From 0022f576e7cbdfd138051f06bb384f18236d36b3 Mon Sep 17 00:00:00 2001 From: Rafael M Mudafort Date: Tue, 29 Jun 2021 14:48:55 -0500 Subject: [PATCH] Revert "Remove OpenFAST subtree; it is out of sync" This reverts commit 0877e99c2b0b7d001d13d91684f47108a2b6fe69. --- OpenFAST/.gitattributes | 6 + OpenFAST/.github/ISSUE_TEMPLATE/bug_report.md | 56 + .../.github/ISSUE_TEMPLATE/feature_request.md | 18 + OpenFAST/.github/PULL_REQUEST_TEMPLATE.md | 18 + .../tests-gluecode-openfast/action.yml | 21 + .../actions/tests-module-aerodyn/action.yml | 9 + .../actions/tests-module-beamdyn/action.yml | 24 + .../actions/tests-module-hydrodyn/action.yml | 9 + .../tests-module-inflowwind/action.yml | 9 + .../tests-module-nwtclibrary/action.yml | 9 + .../.github/workflows/automated-dev-tests.yml | 148 + OpenFAST/.gitignore | 51 + OpenFAST/.gitmodules | 6 + OpenFAST/.readthedocs.yml | 26 + OpenFAST/CMakeLists.txt | 173 + OpenFAST/LICENSE | 201 + OpenFAST/README.rst | 142 + OpenFAST/cmake/FindMKL.cmake | 73 + OpenFAST/cmake/FindMatlab.cmake | 1715 + OpenFAST/cmake/FindSphinx.cmake | 17 + OpenFAST/cmake/FindYAMLCPP.cmake | 27 + .../cmake/GetGitRevisionDescription.cmake | 160 + .../cmake/GetGitRevisionDescription.cmake.in | 44 + OpenFAST/cmake/OpenFASTConfig.cmake.in | 65 + OpenFAST/cmake/OpenfastCmakeUtils.cmake | 66 + OpenFAST/cmake/OpenfastFortranOptions.cmake | 255 + OpenFAST/docs/CMakeLists.txt | 43 + OpenFAST/docs/Doxyfile.in | 2514 + OpenFAST/docs/DoxygenLayout.xml | 194 + .../DCM_Interpolation/DCM_Interpolation.pdf | Bin 0 -> 137738 bytes .../DCM_Interpolation/DCM_Interpolation.tex | 238 + .../OpenFAST_Algorithms.pdf | Bin 0 -> 226733 bytes .../OpenFAST_Algorithms.tex | 594 + .../OtherSupporting/OutListParameters.xlsx | Bin 0 -> 224114 bytes .../docs/_static/GitFlowFeatureBranches.png | Bin 0 -> 124925 bytes OpenFAST/docs/_static/css/math_eq.css | 6 + OpenFAST/docs/_static/docs_options.png | Bin 0 -> 58191 bytes OpenFAST/docs/_static/openfastlogo.jpg | Bin 0 -> 8355 bytes OpenFAST/docs/conf.py | 261 + OpenFAST/docs/index.rst | 59 + OpenFAST/docs/requirements.txt | 9 + OpenFAST/docs/source/acknowledgements.rst | 18 + OpenFAST/docs/source/dev/build_doc.rst | 102 + OpenFAST/docs/source/dev/code_style.rst | 15 + OpenFAST/docs/source/dev/debugging.rst | 103 + OpenFAST/docs/source/dev/github_workflow.rst | 117 + .../source/dev/images/offshore_lapack.png | Bin 0 -> 1257083 bytes OpenFAST/docs/source/dev/index.rst | 112 + OpenFAST/docs/source/dev/other_docs.rst | 18 + OpenFAST/docs/source/dev/performance.rst | 223 + OpenFAST/docs/source/dev/types_files.rst | 124 + OpenFAST/docs/source/dev/versioning.rst | 22 + OpenFAST/docs/source/help.rst | 15 + OpenFAST/docs/source/install/index.rst | 492 + .../docs/source/install/install_cygwin.rst | 81 + .../docs/source/install/install_spack.rst | 111 + .../source/install/install_vs_windows.rst | 79 + OpenFAST/docs/source/license.rst | 8 + OpenFAST/docs/source/testing/index.rst | 90 + .../docs/source/testing/regression_test.rst | 394 + .../testing/regression_test_windows.rst | 121 + OpenFAST/docs/source/testing/unit_test.rst | 136 + OpenFAST/docs/source/this_doc.rst | 40 + .../aerodyn-aeroacoustics/01-introduction.rst | 47 + .../aerodyn-aeroacoustics/02-noise-models.rst | 576 + .../03-model-verification.rst | 230 + .../aerodyn-aeroacoustics/04-conclusions.rst | 22 + .../user/aerodyn-aeroacoustics/App-usage.rst | 301 + .../user/aerodyn-aeroacoustics/acronyms.rst | 49 + .../aerodyn-aeroacoustics/example/AD15.ipt | 18 + .../aerodyn-aeroacoustics/example/AF20_BL.txt | 136 + .../aerodyn-aeroacoustics/example/AFtab.dat | 12 + .../example/AeroAcousticsInput.dat | 31 + .../example/BladeProp.dat | 35 + .../example/Observer.txt | 6 + .../aerodyn-aeroacoustics/example/TIGrid.txt | 11 + .../user/aerodyn-aeroacoustics/index.rst | 43 + .../media/NoiseN002.jpeg | Bin 0 -> 34634 bytes .../aerodyn-aeroacoustics/media/NoiseN003.png | Bin 0 -> 85473 bytes .../aerodyn-aeroacoustics/media/NoiseN004.png | Bin 0 -> 101057 bytes .../aerodyn-aeroacoustics/media/NoiseN005.png | Bin 0 -> 56302 bytes .../aerodyn-aeroacoustics/media/NoiseN006.png | Bin 0 -> 88663 bytes .../aerodyn-aeroacoustics/media/NoiseN007.png | Bin 0 -> 174802 bytes .../aerodyn-aeroacoustics/media/NoiseN008.png | Bin 0 -> 74675 bytes .../aerodyn-aeroacoustics/media/NoiseN009.png | Bin 0 -> 88702 bytes .../aerodyn-aeroacoustics/media/NoiseN010.png | Bin 0 -> 37988 bytes .../aerodyn-aeroacoustics/media/NoiseN011.png | Bin 0 -> 30537 bytes .../aerodyn-aeroacoustics/media/NoiseN012.png | Bin 0 -> 297781 bytes .../user/aerodyn-aeroacoustics/references.bib | 183 + .../user/aerodyn-aeroacoustics/refs.rst | 10 + .../user/aerodyn-aeroacoustics/symbols.rst | 95 + .../examples/UA-driver-timeseries.dat | 11 + .../examples/UA-driver.inp | 25 + .../user/aerodyn-olaf/Acknowledgments.txt | 19 + .../source/user/aerodyn-olaf/Acronyms.rst | 52 + .../source/user/aerodyn-olaf/AppendixA.rst | 14 + .../source/user/aerodyn-olaf/AppendixB.rst | 13 + .../source/user/aerodyn-olaf/AppendixC.rst | 35 + .../ExampleFiles/ExampleFile--OLAF.txt | 42 + .../ExampleFile--PrescribeCirc.txt | 26 + .../source/user/aerodyn-olaf/FutureWork.rst | 31 + .../source/user/aerodyn-olaf/InputFiles.rst | 239 + .../source/user/aerodyn-olaf/Introduction.rst | 156 + .../source/user/aerodyn-olaf/OLAFTheory.rst | 628 + .../source/user/aerodyn-olaf/OutputFiles.rst | 24 + .../source/user/aerodyn-olaf/RunningOLAF.rst | 12 + .../Schematics/FVWwithOpenFAST.pdf | Bin 0 -> 43255 bytes .../Schematics/FVWwithOpenFAST.png | Bin 0 -> 14529 bytes .../Schematics/FilamentRegularization.pdf | Bin 0 -> 20732 bytes .../Schematics/FilamentRegularization.png | Bin 0 -> 31008 bytes .../Schematics/LagrangianMarkers.pdf | Bin 0 -> 63510 bytes .../Schematics/LagrangianMarkers.png | Bin 0 -> 364547 bytes .../user/aerodyn-olaf/Schematics/OpenFAST.pdf | Bin 0 -> 48072 bytes .../user/aerodyn-olaf/Schematics/OpenFAST.png | Bin 0 -> 92541 bytes .../user/aerodyn-olaf/Schematics/Stencil.pdf | Bin 0 -> 11847 bytes .../user/aerodyn-olaf/Schematics/Stencil.png | Bin 0 -> 13929 bytes .../Schematics/VortexCodeWorkFlow.pdf | Bin 0 -> 5268 bytes .../Schematics/VortexCodeWorkFlow.png | Bin 0 -> 98584 bytes .../Schematics/VortexCodeWorkFlow.tex | 80 + .../Schematics/VortexLatticeMethod.pdf | Bin 0 -> 35491 bytes .../Schematics/VortexLatticeMethod.png | Bin 0 -> 34658 bytes .../source/user/aerodyn-olaf/StateSpace.rst | 185 + .../source/user/aerodyn-olaf/bibliography.bib | 438 + .../docs/source/user/aerodyn-olaf/index.rst | 36 + .../docs/source/user/aerodyn-olaf/zrefs.rst | 10 + .../source/user/aerodyn/ADNodalOutputs.rst | 41 + .../docs/source/user/aerodyn/appendix.rst | 69 + .../user/aerodyn/examples/NodalOutputs.txt | 58 + .../aerodyn/examples/ad_airfoil_example.inp | 191 + .../aerodyn/examples/ad_blade_example.inp | 30 + .../aerodyn/examples/ad_driver_example.inp | 23 + .../examples/ad_driver_timeseries_example.inp | 15 + .../aerodyn/examples/ad_primary_example.inp | 104 + .../user/aerodyn/figs/ad_blade_geom.png | Bin 0 -> 109001 bytes .../user/aerodyn/figs/ad_blade_local_cs.png | Bin 0 -> 70601 bytes .../user/aerodyn/figs/ad_driver_geom.png | Bin 0 -> 98962 bytes .../user/aerodyn/figs/ad_output_channel.pdf | Bin 0 -> 70628 bytes .../user/aerodyn/figs/ad_tower_geom.png | Bin 0 -> 64349 bytes OpenFAST/docs/source/user/aerodyn/index.rst | 24 + OpenFAST/docs/source/user/aerodyn/input.rst | 775 + .../docs/source/user/aerodyn/introduction.rst | 198 + .../docs/source/user/aerodyn/modeling.rst | 131 + OpenFAST/docs/source/user/aerodyn/output.rst | 54 + OpenFAST/docs/source/user/aerodyn/theory.rst | 30 + OpenFAST/docs/source/user/api_change.rst | 182 + .../source/user/beamdyn/BDNodalOutputs.rst | 39 + .../docs/source/user/beamdyn/appendix.rst | 58 + .../user/beamdyn/examples/NodalOutputs.txt | 138 + .../examples/bd_driver_dynamic_nrel_5mw.inp | 44 + .../examples/bd_driver_static_nrel_5mw.inp | 44 + .../beamdyn/examples/bd_primary_nrel_5mw.inp | 108 + .../user/beamdyn/examples/nrel_5mw_blade.inp | 744 + .../source/user/beamdyn/figs/bd_frame.pdf | Bin 0 -> 86325 bytes .../user/beamdyn/figs/bd_output_channel.docx | Bin 0 -> 100545 bytes .../user/beamdyn/figs/bd_output_channel.pdf | Bin 0 -> 34948 bytes .../user/beamdyn/figs/blade_geometry.jpg | Bin 0 -> 59406 bytes .../source/user/beamdyn/figs/flow_chart.jpg | Bin 0 -> 66044 bytes .../docs/source/user/beamdyn/figs/frame.jpg | Bin 0 -> 40985 bytes .../user/beamdyn/figs/geometry_member1.png | Bin 0 -> 44278 bytes .../user/beamdyn/figs/geometry_member2.png | Bin 0 -> 50845 bytes .../user/beamdyn/figs/manual_plots.pptx | Bin 0 -> 2924727 bytes OpenFAST/docs/source/user/beamdyn/figs/n4.pdf | Bin 0 -> 8756 bytes OpenFAST/docs/source/user/beamdyn/figs/n8.pdf | Bin 0 -> 17141 bytes .../docs/source/user/beamdyn/future_work.rst | 32 + OpenFAST/docs/source/user/beamdyn/index.rst | 30 + .../docs/source/user/beamdyn/input_files.rst | 592 + .../docs/source/user/beamdyn/introduction.rst | 111 + .../docs/source/user/beamdyn/output_files.rst | 109 + .../docs/source/user/beamdyn/references.bib | 223 + .../docs/source/user/beamdyn/running_bd.rst | 92 + OpenFAST/docs/source/user/beamdyn/theory.rst | 712 + OpenFAST/docs/source/user/beamdyn/zrefs.rst | 9 + .../docs/source/user/cppapi/files/cDriver.i | 53 + OpenFAST/docs/source/user/cppapi/index.rst | 94 + .../source/user/elastodyn/EDNodalOutputs.rst | 41 + .../elastodyn/exampleInput/NodalOutpus.txt | 26 + OpenFAST/docs/source/user/elastodyn/index.rst | 18 + OpenFAST/docs/source/user/elastodyn/input.rst | 366 + .../docs/source/user/fast_to_openfast.rst | 200 + OpenFAST/docs/source/user/index.rst | 24 + .../docs/source/user/inflowwind/appendix.rst | 44 + .../docs/source/user/inflowwind/driver.rst | 115 + .../inflowwind_bladedscaling_example.dat | 10 + .../examples/inflowwind_driver_example.inp | 24 + .../examples/inflowwind_example.dat | 57 + .../examples/inflowwind_uniform_example.dat | 14 + .../docs/source/user/inflowwind/index.rst | 22 + .../docs/source/user/inflowwind/input.rst | 113 + OpenFAST/glue-codes/CMakeLists.txt | 6 + .../labview/src/OPENFAST_RT_DLL.f90 | 125 + .../glue-codes/openfast-cpp/CMakeLists.txt | 86 + .../glue-codes/openfast-cpp/src/FAST_Prog.cpp | 149 + .../glue-codes/openfast-cpp/src/OpenFAST.H | 311 + .../glue-codes/openfast-cpp/src/OpenFAST.cpp | 1147 + OpenFAST/glue-codes/openfast-cpp/src/SC.h | 39 + OpenFAST/glue-codes/openfast/CMakeLists.txt | 32 + OpenFAST/glue-codes/openfast/src/FAST_Prog.c | 185 + .../glue-codes/openfast/src/FAST_Prog.f90 | 209 + OpenFAST/glue-codes/python/OpenFAST.py | 49 + .../glue-codes/python/openfast_library.py | 204 + .../glue-codes/simulink/examples/OpenLoop.mdl | 1261 + .../simulink/examples/Run_OpenLoop.m | 12 + .../simulink/examples/Run_Test01_SIG.m | 39 + .../simulink/examples/Test01_SIG.mdl | 1498 + OpenFAST/glue-codes/simulink/src/FAST_SFunc.c | 473 + .../simulink/src/create_FAST_SFunc.m | 70 + OpenFAST/modules/aerodyn/CMakeLists.txt | 117 + OpenFAST/modules/aerodyn/README.md | 14 + .../modules/aerodyn/src/AeroAcoustics.f90 | 2468 + .../modules/aerodyn/src/AeroAcoustics_IO.f90 | 988 + .../aerodyn/src/AeroAcoustics_Registry.txt | 252 + .../modules/aerodyn/src/AeroAcoustics_TNO.f90 | 198 + .../aerodyn/src/AeroAcoustics_Types.f90 | 10536 ++++ OpenFAST/modules/aerodyn/src/AeroDyn.f90 | 5112 ++ .../aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 | 1291 + .../modules/aerodyn/src/AeroDyn_Driver.f90 | 180 + .../aerodyn/src/AeroDyn_Driver_Registry.txt | 74 + .../aerodyn/src/AeroDyn_Driver_Subs.f90 | 969 + .../aerodyn/src/AeroDyn_Driver_Types.f90 | 2236 + OpenFAST/modules/aerodyn/src/AeroDyn_IO.f90 | 3443 ++ .../modules/aerodyn/src/AeroDyn_Registry.txt | 269 + .../modules/aerodyn/src/AeroDyn_Types.f90 | 10477 ++++ OpenFAST/modules/aerodyn/src/AirfoilInfo.f90 | 1181 + .../aerodyn/src/AirfoilInfo_Registry.txt | 120 + .../modules/aerodyn/src/AirfoilInfo_Types.f90 | 2575 + OpenFAST/modules/aerodyn/src/BEMT.f90 | 2488 + .../modules/aerodyn/src/BEMTUncoupled.f90 | 486 + .../modules/aerodyn/src/BEMT_Registry.txt | 175 + OpenFAST/modules/aerodyn/src/BEMT_Types.f90 | 6580 +++ OpenFAST/modules/aerodyn/src/DBEMT.f90 | 932 + .../modules/aerodyn/src/DBEMT_Registry.txt | 89 + OpenFAST/modules/aerodyn/src/DBEMT_Test.f90 | 729 + OpenFAST/modules/aerodyn/src/DBEMT_Types.f90 | 3199 ++ OpenFAST/modules/aerodyn/src/FVW.f90 | 1181 + .../modules/aerodyn/src/FVW_BiotSavart.f90 | 430 + OpenFAST/modules/aerodyn/src/FVW_IO.f90 | 411 + OpenFAST/modules/aerodyn/src/FVW_Registry.txt | 233 + OpenFAST/modules/aerodyn/src/FVW_Subs.f90 | 1088 + OpenFAST/modules/aerodyn/src/FVW_Tests.f90 | 754 + OpenFAST/modules/aerodyn/src/FVW_Types.f90 | 8329 +++ OpenFAST/modules/aerodyn/src/FVW_VTK.f90 | 565 + .../modules/aerodyn/src/FVW_VortexTools.f90 | 892 + OpenFAST/modules/aerodyn/src/FVW_Wings.f90 | 508 + OpenFAST/modules/aerodyn/src/UA_Dvr_Subs.f90 | 621 + OpenFAST/modules/aerodyn/src/UnsteadyAero.f90 | 2610 + .../aerodyn/src/UnsteadyAero_Driver.f90 | 350 + .../aerodyn/src/UnsteadyAero_Registry.txt | 198 + .../aerodyn/src/UnsteadyAero_Types.f90 | 6050 ++ OpenFAST/modules/aerodyn/src/mod_root1dim.f90 | 235 + .../aerodyn/tests/test_FVW_testsuite.F90 | 48 + OpenFAST/modules/aerodyn14/CMakeLists.txt | 53 + OpenFAST/modules/aerodyn14/README.md | 14 + .../aerodyn14/src/AD14AeroConf_Types.f90 | 2921 + .../aerodyn14/src/AD_RegistryEntries.xlsx | Bin 0 -> 35792 bytes OpenFAST/modules/aerodyn14/src/AeroDyn14.f90 | 1238 + .../modules/aerodyn14/src/AeroDyn14_Types.f90 | 16900 ++++++ OpenFAST/modules/aerodyn14/src/AeroSubs.f90 | 5531 ++ OpenFAST/modules/aerodyn14/src/DWM.f90 | 341 + OpenFAST/modules/aerodyn14/src/DWM_Types.f90 | 9855 ++++ .../aerodyn14/src/DWM_Wake_Sub_ver2.f90 | 2851 + .../aerodyn14/src/DWM_driver_wind_farm.f90 | 51 + .../src/DWM_driver_wind_farm_mod.f90 | 42 + .../src/DWM_driver_wind_farm_sub.f90 | 879 + OpenFAST/modules/aerodyn14/src/GenSubs.f90 | 669 + .../modules/aerodyn14/src/Registry-AD14.txt | 412 + .../aerodyn14/src/Registry-AD14AeroConf.txt | 56 + .../modules/aerodyn14/src/Registry-DWM.txt | 274 + OpenFAST/modules/beamdyn/CMakeLists.txt | 48 + OpenFAST/modules/beamdyn/README.md | 56 + OpenFAST/modules/beamdyn/src/BeamDyn.f90 | 6807 +++ .../beamdyn/src/BeamDyn_BldNdOuts_IO.f90 | 1494 + OpenFAST/modules/beamdyn/src/BeamDyn_IO.f90 | 2708 + OpenFAST/modules/beamdyn/src/BeamDyn_Subs.f90 | 1134 + .../modules/beamdyn/src/BeamDyn_Types.f90 | 13004 +++++ OpenFAST/modules/beamdyn/src/Driver_Beam.f90 | 267 + .../modules/beamdyn/src/Driver_Beam_Subs.f90 | 781 + .../modules/beamdyn/src/Registry_BeamDyn.txt | 376 + .../beamdyn/tests/test_BD_CheckRotMat.F90 | 44 + .../tests/test_BD_ComputeIniNodalCrv.F90 | 83 + .../beamdyn/tests/test_BD_CrvCompose.F90 | 137 + .../beamdyn/tests/test_BD_CrvExtractCrv.F90 | 73 + .../beamdyn/tests/test_BD_CrvMatrixH.F90 | 90 + .../beamdyn/tests/test_BD_CrvMatrixR.F90 | 74 + .../beamdyn/tests/test_BD_DistrLoadCopy.F90 | 46 + .../tests/test_BD_GaussPointWeight.F90 | 123 + .../beamdyn/tests/test_BD_GenerateGLL.F90 | 117 + .../beamdyn/tests/test_BD_GravityForce.F90 | 46 + .../beamdyn/tests/test_BD_InitShpDerJaco.F90 | 173 + .../tests/test_BD_InputGlobalLocal.F90 | 102 + .../beamdyn/tests/test_BD_MemberEta.F90 | 87 + .../beamdyn/tests/test_BD_QPData_mEta_rho.F90 | 50 + .../tests/test_BD_TrapezoidalPointWeight.F90 | 113 + .../modules/beamdyn/tests/test_BD_diffmtc.F90 | 163 + .../tests/test_ExtractRelativeRotation.F90 | 34 + .../tests/test_InitializeNodalLocations.F90 | 134 + OpenFAST/modules/beamdyn/tests/test_tools.F90 | 238 + OpenFAST/modules/elastodyn/CMakeLists.txt | 36 + OpenFAST/modules/elastodyn/README.md | 4 + .../modules/elastodyn/src/ED_UserSubs.f90 | 156 + OpenFAST/modules/elastodyn/src/ElastoDyn.f90 | 11858 ++++ .../src/ElastoDyn_AllBldNdOuts_IO.f90 | 665 + .../modules/elastodyn/src/ElastoDyn_IO.f90 | 5271 ++ .../elastodyn/src/ElastoDyn_Registry.txt | 873 + .../modules/elastodyn/src/ElastoDyn_Types.f90 | 25173 +++++++++ OpenFAST/modules/extptfm/CMakeLists.txt | 33 + OpenFAST/modules/extptfm/README.md | 4 + OpenFAST/modules/extptfm/src/ExtPtfm_MCKF.f90 | 1196 + .../extptfm/src/ExtPtfm_MCKF_Driver.f90 | 105 + .../modules/extptfm/src/ExtPtfm_MCKF_IO.f90 | 911 + .../extptfm/src/ExtPtfm_MCKF_Registry.txt | 129 + .../extptfm/src/ExtPtfm_MCKF_Types.f90 | 5046 ++ OpenFAST/modules/feamooring/CMakeLists.txt | 42 + OpenFAST/modules/feamooring/README.md | 27 + OpenFAST/modules/feamooring/src/FEAM.f90 | 2885 + .../modules/feamooring/src/FEAM_Driver.f90 | 228 + .../modules/feamooring/src/FEAM_Registry.txt | 219 + .../feamooring/src/FEAMooring_Types.f90 | 7286 +++ .../modules/feamooring/test/FE_Mooring.dat | 77 + ...ELOffshrBsline5MW_ITIBarge4_FEAMooring.dat | 172 + ...ffshrBsline5MW_MIT_NREL_TLP_FEAMooring.dat | 172 + ...ELOffshrBsline5MW_OC3Hywind_FEAMooring.dat | 77 + ...rBsline5MW_OC4DeepCwindSemi_FEAMooring.dat | 77 + OpenFAST/modules/hydrodyn/CMakeLists.txt | 75 + OpenFAST/modules/hydrodyn/README.md | 21 + .../modules/hydrodyn/src/Conv_Radiation.f90 | 785 + .../modules/hydrodyn/src/Conv_Radiation.txt | 87 + .../hydrodyn/src/Conv_Radiation_Types.f90 | 2097 + OpenFAST/modules/hydrodyn/src/Current.f90 | 323 + OpenFAST/modules/hydrodyn/src/Current.txt | 88 + .../modules/hydrodyn/src/Current_Types.f90 | 1906 + OpenFAST/modules/hydrodyn/src/HydroDyn.f90 | 3365 ++ OpenFAST/modules/hydrodyn/src/HydroDyn.txt | 209 + .../hydrodyn/src/HydroDyn_DriverCode.f90 | 1243 + .../modules/hydrodyn/src/HydroDyn_Input.f90 | 4324 ++ .../modules/hydrodyn/src/HydroDyn_Output.f90 | 1127 + .../modules/hydrodyn/src/HydroDyn_Types.f90 | 8405 +++ OpenFAST/modules/hydrodyn/src/Morison.f90 | 4715 ++ OpenFAST/modules/hydrodyn/src/Morison.txt | 356 + .../modules/hydrodyn/src/Morison_Output.f90 | 7698 +++ .../modules/hydrodyn/src/Morison_Types.f90 | 11249 ++++ .../modules/hydrodyn/src/SS_Excitation.f90 | 901 + .../modules/hydrodyn/src/SS_Excitation.txt | 71 + .../hydrodyn/src/SS_Excitation_Driver.f90 | 295 + .../hydrodyn/src/SS_Excitation_Types.f90 | 2331 + .../modules/hydrodyn/src/SS_Radiation.f90 | 1002 + .../modules/hydrodyn/src/SS_Radiation.txt | 61 + .../hydrodyn/src/SS_Radiation_DriverCode.f90 | 282 + .../hydrodyn/src/SS_Radiation_Types.f90 | 2134 + OpenFAST/modules/hydrodyn/src/UserWaves.f90 | 984 + OpenFAST/modules/hydrodyn/src/WAMIT.f90 | 1728 + OpenFAST/modules/hydrodyn/src/WAMIT.txt | 149 + OpenFAST/modules/hydrodyn/src/WAMIT2.f90 | 5771 ++ OpenFAST/modules/hydrodyn/src/WAMIT2.txt | 145 + .../modules/hydrodyn/src/WAMIT2_Output.f90 | 561 + .../modules/hydrodyn/src/WAMIT2_Types.f90 | 2874 + .../modules/hydrodyn/src/WAMIT_Interp.f90 | 625 + .../modules/hydrodyn/src/WAMIT_Output.f90 | 589 + OpenFAST/modules/hydrodyn/src/WAMIT_Types.f90 | 5135 ++ OpenFAST/modules/hydrodyn/src/Waves.f90 | 2440 + OpenFAST/modules/hydrodyn/src/Waves.txt | 137 + OpenFAST/modules/hydrodyn/src/Waves2.f90 | 2433 + OpenFAST/modules/hydrodyn/src/Waves2.txt | 154 + .../modules/hydrodyn/src/Waves2_Output.f90 | 576 + .../modules/hydrodyn/src/Waves2_Types.f90 | 3802 ++ OpenFAST/modules/hydrodyn/src/Waves_Types.f90 | 3460 ++ OpenFAST/modules/icedyn/CMakeLists.txt | 32 + OpenFAST/modules/icedyn/README.md | 23 + OpenFAST/modules/icedyn/src/Driver_IceDyn.f90 | 473 + OpenFAST/modules/icedyn/src/IceDyn.f90 | 3244 ++ OpenFAST/modules/icedyn/src/IceDyn_Types.f90 | 4065 ++ .../modules/icedyn/src/Registry_IceDyn.txt | 234 + OpenFAST/modules/icefloe/CMakeLists.txt | 47 + OpenFAST/modules/icefloe/README.md | 31 + .../icefloe/src/icefloe/IceFlexBase.F90 | 90 + .../icefloe/src/icefloe/IceFlexIEC.f90 | 186 + .../icefloe/src/icefloe/IceFlexISO.f90 | 351 + .../icefloe/src/icefloe/IceFloeBase.F90 | 350 + .../icefloe/src/icefloe/IceFloe_Types.f90 | 2459 + .../src/icefloe/IceFloe_Types_notFAST.f90 | 36 + .../icefloe/src/icefloe/coupledCrushing.F90 | 139 + .../icefloe/src/icefloe/crushingIEC.F90 | 116 + .../icefloe/src/icefloe/crushingISO.F90 | 165 + .../modules/icefloe/src/icefloe/iceInput.f90 | 352 + .../modules/icefloe/src/icefloe/iceLog.F90 | 155 + .../src/icefloe/intermittentCrushing.F90 | 94 + .../modules/icefloe/src/icefloe/lockInISO.F90 | 93 + .../icefloe/src/icefloe/randomCrushing.F90 | 177 + .../src/interfaces/ADAMS/IceADAMS_VFOSUB.f90 | 264 + .../src/interfaces/Bladed/IceFloeBladed.f90 | 233 + .../src/interfaces/Console/IceFloe.f90 | 196 + .../interfaces/Console/NWTC_Base_reduced.f90 | 69 + .../src/interfaces/Console/SysIVF_reduced.f90 | 373 + .../icefloe/src/interfaces/FAST/IceFloe.f90 | 643 + .../interfaces/FAST/IceFloe_FASTRegistry.inp | 77 + .../src/interfaces/HAWC2/HAWC2_DLL.f90 | 248 + .../src/interfaces/HAWC2/NWTC_IO_reduced.f90 | 1003 + .../icefloe/src/interfaces/IceFloe_Test.f90 | 168 + .../icefloe/test/GLA_Proto_flex_ISO.inp | 58 + .../icefloe/test/GLA_Proto_intercrush_ISO.inp | 39 + .../icefloe/test/GLA_Proto_lockin_ISO.inp | 41 + .../test/GLA_Proto_randomcrush_ISO.inp | 41 + .../icefloe/test/GLA_proto_flex_IEC.dat | 6001 ++ .../icefloe/test/GLA_proto_flex_IEC.inp | 40 + .../icefloe/test/GLA_proto_flex_IEC.log | 33 + .../icefloe/test/GLA_proto_flex_ISO.dat | 6001 ++ .../icefloe/test/GLA_proto_flex_ISO.log | 56 + .../icefloe/test/GLA_proto_interCrush_ISO.dat | 6001 ++ .../icefloe/test/GLA_proto_interCrush_ISO.log | 29 + .../icefloe/test/GLA_proto_lockin_IEC.dat | 6001 ++ .../icefloe/test/GLA_proto_lockin_IEC.inp | 34 + .../icefloe/test/GLA_proto_lockin_IEC.log | 25 + .../icefloe/test/GLA_proto_lockin_ISO.dat | 6001 ++ .../icefloe/test/GLA_proto_lockin_ISO.log | 29 + .../test/GLA_proto_randomCrush_ISO.dat | 6001 ++ .../test/GLA_proto_randomCrush_ISO.log | 33 + OpenFAST/modules/icefloe/test/runAll.bat | 6 + OpenFAST/modules/inflowwind/CMakeLists.txt | 67 + OpenFAST/modules/inflowwind/README.md | 9 + OpenFAST/modules/inflowwind/src/CTWind.f90 | 1345 + OpenFAST/modules/inflowwind/src/FDWind.f90 | 1300 + OpenFAST/modules/inflowwind/src/IfW_4Dext.f90 | 362 + OpenFAST/modules/inflowwind/src/IfW_4Dext.txt | 39 + .../inflowwind/src/IfW_4Dext_Types.f90 | 830 + .../inflowwind/src/IfW_BladedFFWind.f90 | 1883 + .../inflowwind/src/IfW_BladedFFWind.txt | 39 + .../inflowwind/src/IfW_BladedFFWind_Types.f90 | 783 + .../inflowwind/src/IfW_FFWind_Base.f90 | 1172 + .../inflowwind/src/IfW_FFWind_Base.txt | 53 + .../inflowwind/src/IfW_FFWind_Base_Types.f90 | 711 + .../modules/inflowwind/src/IfW_HAWCWind.f90 | 387 + .../modules/inflowwind/src/IfW_HAWCWind.txt | 52 + .../inflowwind/src/IfW_HAWCWind_Types.f90 | 1609 + .../modules/inflowwind/src/IfW_TSFFWind.f90 | 659 + .../modules/inflowwind/src/IfW_TSFFWind.txt | 33 + .../inflowwind/src/IfW_TSFFWind_Types.f90 | 738 + .../inflowwind/src/IfW_UniformWind.f90 | 1121 + .../inflowwind/src/IfW_UniformWind.txt | 67 + .../inflowwind/src/IfW_UniformWind_Types.f90 | 1484 + .../modules/inflowwind/src/IfW_UserWind.f90 | 286 + .../modules/inflowwind/src/IfW_UserWind.txt | 36 + .../inflowwind/src/IfW_UserWind_Types.f90 | 646 + .../modules/inflowwind/src/InflowWind.f90 | 1746 + .../modules/inflowwind/src/InflowWind.txt | 191 + .../inflowwind/src/InflowWind_Driver.f90 | 969 + .../inflowwind/src/InflowWind_Driver_Subs.f90 | 2461 + .../src/InflowWind_Driver_Types.f90 | 111 + .../inflowwind/src/InflowWind_Subs.f90 | 1771 + .../inflowwind/src/InflowWind_Types.f90 | 5830 ++ OpenFAST/modules/inflowwind/src/Lidar.f90 | 589 + OpenFAST/modules/inflowwind/src/Lidar.txt | 68 + .../modules/inflowwind/src/Lidar_Types.f90 | 1969 + .../inflowwind/tests/ifw_test_tools.F90 | 145 + .../inflowwind/tests/test_bladed_wind.F90 | 35 + .../inflowwind/tests/test_hawc_wind.F90 | 62 + .../modules/inflowwind/tests/test_outputs.F90 | 62 + .../inflowwind/tests/test_steady_wind.F90 | 63 + .../inflowwind/tests/test_turbsim_wind.F90 | 34 + .../inflowwind/tests/test_uniform_wind.F90 | 103 + OpenFAST/modules/map/CMakeLists.txt | 55 + OpenFAST/modules/map/README.md | 25 + .../modules/map/src/MAP_Fortran_Registry.txt | 22 + .../modules/map/src/MAP_Fortran_Types.f90 | 674 + OpenFAST/modules/map/src/MAP_Registry.txt | 157 + OpenFAST/modules/map/src/MAP_Types.f90 | 5368 ++ OpenFAST/modules/map/src/MAP_Types.h | 123 + OpenFAST/modules/map/src/bstring/bstraux.c | 1176 + OpenFAST/modules/map/src/bstring/bstraux.h | 417 + OpenFAST/modules/map/src/bstring/bstrlib.c | 2951 + OpenFAST/modules/map/src/bstring/bstrlib.h | 1765 + OpenFAST/modules/map/src/cminpack/cminpack.h | 370 + OpenFAST/modules/map/src/cminpack/cminpackP.h | 62 + OpenFAST/modules/map/src/cminpack/dpmpar.c | 201 + OpenFAST/modules/map/src/cminpack/enorm.c | 157 + OpenFAST/modules/map/src/cminpack/enorm_u.c | 186 + OpenFAST/modules/map/src/cminpack/lmder.c | 526 + OpenFAST/modules/map/src/cminpack/lmpar.c | 338 + OpenFAST/modules/map/src/cminpack/minpack.h | 301 + OpenFAST/modules/map/src/cminpack/qrfac.c | 285 + OpenFAST/modules/map/src/cminpack/qrsolv.c | 218 + OpenFAST/modules/map/src/freedata.c | 328 + OpenFAST/modules/map/src/freedata.h | 86 + OpenFAST/modules/map/src/jacobian.c | 391 + OpenFAST/modules/map/src/jacobian.h | 43 + OpenFAST/modules/map/src/lapack/lapacke.h | 16445 ++++++ .../modules/map/src/lapack/lapacke_mangling.h | 17 + OpenFAST/modules/map/src/lineroutines.c | 1397 + OpenFAST/modules/map/src/lineroutines.h | 225 + OpenFAST/modules/map/src/lmroutines.cc | 20 + OpenFAST/modules/map/src/lmroutines.hpp | 47 + OpenFAST/modules/map/src/makefile | 89 + OpenFAST/modules/map/src/map.f90 | 1599 + OpenFAST/modules/map/src/map.h | 465 + OpenFAST/modules/map/src/map_glue.f90 | 338 + OpenFAST/modules/map/src/mapapi.c | 1317 + OpenFAST/modules/map/src/mapapi.h | 559 + OpenFAST/modules/map/src/maperror.c | 291 + OpenFAST/modules/map/src/maperror.h | 211 + OpenFAST/modules/map/src/mapinit.c | 2880 + OpenFAST/modules/map/src/mapinit.h | 881 + OpenFAST/modules/map/src/mapsys.h | 162 + OpenFAST/modules/map/src/numeric.c | 270 + OpenFAST/modules/map/src/numeric.h | 163 + OpenFAST/modules/map/src/outputstream.c | 947 + OpenFAST/modules/map/src/outputstream.h | 264 + OpenFAST/modules/map/src/residual.c | 58 + OpenFAST/modules/map/src/residual.h | 36 + OpenFAST/modules/map/src/simclist/simclist.c | 1498 + OpenFAST/modules/map/src/simclist/simclist.h | 984 + OpenFAST/modules/moordyn/CMakeLists.txt | 43 + OpenFAST/modules/moordyn/README.md | 30 + OpenFAST/modules/moordyn/src/MoorDyn.f90 | 2210 + .../modules/moordyn/src/MoorDyn_Driver.f90 | 416 + OpenFAST/modules/moordyn/src/MoorDyn_IO.f90 | 1347 + .../modules/moordyn/src/MoorDyn_Registry.txt | 174 + .../modules/moordyn/src/MoorDyn_Types.f90 | 5598 ++ OpenFAST/modules/nwtc-library/CMakeLists.txt | 136 + OpenFAST/modules/nwtc-library/README.md | 22 + .../src/Generate_NWTC_Library_Types.bat | 34 + OpenFAST/modules/nwtc-library/src/ModMesh.f90 | 3552 ++ .../nwtc-library/src/ModMesh_Mapping.f90 | 7920 +++ .../nwtc-library/src/ModMesh_Types.f90 | 240 + .../modules/nwtc-library/src/NWTC_Base.f90 | 77 + OpenFAST/modules/nwtc-library/src/NWTC_IO.f90 | 8693 +++ .../modules/nwtc-library/src/NWTC_Library.f90 | 115 + .../nwtc-library/src/NWTC_Library_Types.f90 | 1458 + .../modules/nwtc-library/src/NWTC_Num.f90 | 6907 +++ .../nwtc-library/src/NWTC_RandomNumber.f90 | 190 + .../NetLib/Dierckx_FitPack/NWTC_FitPack.f90 | 721 + .../NetLib/Dierckx_FitPack/dierckx_fitpack.f | 1517 + .../src/NetLib/Dierckx_FitPack/readme.txt | 50 + .../src/NetLib/fftpack/NWTC_FFTPACK.f90 | 859 + .../nwtc-library/src/NetLib/fftpack/doc.txt | 866 + .../src/NetLib/fftpack/fftpack4.1.f | 2327 + .../src/NetLib/lapack/NWTC_LAPACK.f90 | 1580 + .../src/NetLib/scalapack/NWTC_ScaLAPACK.f90 | 107 + .../src/NetLib/scalapack/dlasrt2.f | 270 + .../src/NetLib/scalapack/slasrt2.f | 270 + .../src/NetLib/slatec/NWTC_SLATEC.f90 | 67 + .../nwtc-library/src/NetLib/slatec/aaaaaa.f | 71 + .../nwtc-library/src/NetLib/slatec/d1mach.f | 502 + .../nwtc-library/src/NetLib/slatec/dqk61.f | 241 + .../nwtc-library/src/NetLib/slatec/fdump.f | 31 + .../nwtc-library/src/NetLib/slatec/i1mach.f | 888 + .../nwtc-library/src/NetLib/slatec/j4save.f | 65 + .../nwtc-library/src/NetLib/slatec/qk61.f | 202 + .../nwtc-library/src/NetLib/slatec/r1mach.f | 419 + .../nwtc-library/src/NetLib/slatec/xercnt.f | 60 + .../nwtc-library/src/NetLib/slatec/xerhlt.f | 39 + .../nwtc-library/src/NetLib/slatec/xermsg.f | 364 + .../nwtc-library/src/NetLib/slatec/xerprn.f | 228 + .../nwtc-library/src/NetLib/slatec/xersve.f | 155 + .../nwtc-library/src/NetLib/slatec/xgetua.f | 51 + .../src/Registry_NWTC_Library.txt | 71 + .../Registry_NWTC_Library_typedef_mesh.txt | 40 + .../Registry_NWTC_Library_typedef_nomesh.txt | 40 + .../modules/nwtc-library/src/SingPrec.f90 | 78 + .../modules/nwtc-library/src/SysGnuLinux.f90 | 562 + .../modules/nwtc-library/src/SysGnuWin.f90 | 531 + OpenFAST/modules/nwtc-library/src/SysIFL.f90 | 541 + OpenFAST/modules/nwtc-library/src/SysIVF.f90 | 470 + .../nwtc-library/src/SysIVF_Labview.f90 | 543 + .../nwtc-library/src/SysMatlabLinuxGnu.f90 | 559 + .../nwtc-library/src/SysMatlabLinuxIntel.f90 | 551 + .../nwtc-library/src/SysMatlabWindows.f90 | 518 + .../nwtc-library/src/ranlux/RANLUX.f90 | 379 + OpenFAST/modules/nwtc-library/src/readme.txt | 8 + .../Compare_LAPACK_MUMPS.f90 | 249 + .../nwtc-library/test/Test_CheckArgs.f90 | 44 + .../Test_ChkRealFmtStr/Test_ChkRealFmtStr.f90 | 49 + .../test/Test_ChkRealFmtStr/makefile | 117 + .../test/Test_FileSize/Test_FileSize.f90 | 21 + .../nwtc-library/test/Test_FileSize/makefile | 140 + .../test/Test_MeshMapping/Makefile | 173 + .../Test_MeshMapping/Test_MeshMapping.f90 | 728 + .../Test_MeshMapping/Test_MeshMapping_Mod.f90 | 1738 + .../nwtc-library/test/Test_NWTC_Library.f90 | 583 + .../Test_OpenCon_GnuWin.f90 | 44 + .../test/Test_OpenCon_GnuWin/makefile | 117 + .../Test_ReadComFile/Test_ReadComFile.f90 | 85 + .../test/Test_ReadComFile/makefile | 135 + .../nwtc-library/test/Test_ReadFASTbin.f90 | 106 + .../Test_RegCubicSpline.f90 | 138 + .../tests/test_NWTC_IO_CheckArgs.F90 | 381 + .../tests/test_NWTC_IO_FileInfo.F90 | 84 + .../tests/test_NWTC_RandomNumber.F90 | 58 + .../modules/openfast-library/CMakeLists.txt | 81 + OpenFAST/modules/openfast-library/README.md | 6 + .../openfast-library/src/FAST_Library.f90 | 724 + .../openfast-library/src/FAST_Library.h | 53 + .../modules/openfast-library/src/FAST_Lin.f90 | 5633 ++ .../openfast-library/src/FAST_Mods.f90 | 72 + .../openfast-library/src/FAST_Registry.txt | 720 + .../openfast-library/src/FAST_Solver.f90 | 5883 ++ .../openfast-library/src/FAST_Subs.f90 | 7281 +++ .../openfast-library/src/FAST_Types.f90 | 46499 ++++++++++++++++ .../modules/openfast-registry/CMakeLists.txt | 35 + OpenFAST/modules/openfast-registry/README.md | 64 + .../openfast-registry/src/FAST_preamble.h | 45 + .../openfast-registry/src/Template_data.c | 849 + .../openfast-registry/src/Template_registry.c | 81 + OpenFAST/modules/openfast-registry/src/data.c | 229 + OpenFAST/modules/openfast-registry/src/data.h | 132 + .../openfast-registry/src/gen_c_types.c | 428 + .../openfast-registry/src/gen_module_files.c | 2466 + OpenFAST/modules/openfast-registry/src/misc.c | 710 + .../modules/openfast-registry/src/my_strtok.c | 139 + .../modules/openfast-registry/src/protos.h | 189 + .../modules/openfast-registry/src/reg_parse.c | 756 + .../modules/openfast-registry/src/registry.c | 311 + .../modules/openfast-registry/src/registry.h | 63 + OpenFAST/modules/openfast-registry/src/sym.c | 163 + OpenFAST/modules/openfast-registry/src/sym.h | 97 + .../openfast-registry/src/symtab_gen.c | 208 + OpenFAST/modules/openfast-registry/src/type.c | 426 + OpenFAST/modules/openfoam/CMakeLists.txt | 41 + OpenFAST/modules/openfoam/README.md | 5 + OpenFAST/modules/openfoam/src/OpenFOAM.f90 | 1210 + .../openfoam/src/OpenFOAM_Registry.txt | 85 + .../modules/openfoam/src/OpenFOAM_Types.f90 | 5488 ++ .../modules/openfoam/src/OpenFOAM_Types.h | 108 + .../modules/orcaflex-interface/CMakeLists.txt | 43 + OpenFAST/modules/orcaflex-interface/README.md | 28 + .../orcaflex-interface/src/OrcaDriver.f90 | 655 + .../src/OrcaDriver_Subs.f90 | 2088 + .../src/OrcaDriver_Types.f90 | 94 + .../src/OrcaFlexInterface.f90 | 1082 + .../src/OrcaFlexInterface.txt | 75 + .../src/OrcaFlexInterface_Types.f90 | 2655 + OpenFAST/modules/servodyn/CMakeLists.txt | 46 + OpenFAST/modules/servodyn/README.md | 16 + .../modules/servodyn/src/BladedInterface.f90 | 1126 + .../modules/servodyn/src/PitchCntrl_ACH.f90 | 759 + OpenFAST/modules/servodyn/src/ServoDyn.f90 | 4216 ++ .../modules/servodyn/src/ServoDyn_Driver.f90 | 191 + .../servodyn/src/ServoDyn_Registry.txt | 394 + .../modules/servodyn/src/ServoDyn_Types.f90 | 8170 +++ OpenFAST/modules/servodyn/src/TMD.f90 | 1692 + OpenFAST/modules/servodyn/src/TMD_Driver.f90 | 908 + .../modules/servodyn/src/TMD_Registry.txt | 122 + OpenFAST/modules/servodyn/src/TMD_Types.f90 | 2692 + OpenFAST/modules/servodyn/src/UserSubs.f90 | 459 + .../modules/servodyn/src/UserVSCont_KP.f90 | 243 + OpenFAST/modules/subdyn/CMakeLists.txt | 42 + OpenFAST/modules/subdyn/README.md | 25 + OpenFAST/modules/subdyn/src/SD_FEM.f90 | 1018 + OpenFAST/modules/subdyn/src/SubDyn.f90 | 2892 + OpenFAST/modules/subdyn/src/SubDyn_Driver.f90 | 793 + OpenFAST/modules/subdyn/src/SubDyn_Output.f90 | 4932 ++ .../modules/subdyn/src/SubDyn_Registry.txt | 222 + OpenFAST/modules/subdyn/src/SubDyn_Types.f90 | 9490 ++++ .../modules/subdyn/src/qsort_c_module.f90 | 61 + .../modules/supercontroller/CMakeLists.txt | 39 + OpenFAST/modules/supercontroller/README.md | 5 + .../supercontroller/src/SuperController.f90 | 166 + .../src/SuperController_Registry.txt | 30 + .../src/SuperController_Types.f90 | 1493 + .../src/SuperController_Types.h | 55 + OpenFAST/modules/turbsim/CMakeLists.txt | 33 + OpenFAST/modules/turbsim/README.md | 16 + OpenFAST/modules/turbsim/src/BlankModVKM.f90 | 76 + .../modules/turbsim/src/CohStructures.f90 | 901 + OpenFAST/modules/turbsim/src/Profiles.f90 | 1411 + OpenFAST/modules/turbsim/src/RandNum.f90 | 1046 + .../modules/turbsim/src/Root_Searching.f90 | 98 + OpenFAST/modules/turbsim/src/TS_FileIO.f90 | 5475 ++ OpenFAST/modules/turbsim/src/TSsubs.f90 | 2536 + OpenFAST/modules/turbsim/src/TurbSim.f90 | 386 + .../modules/turbsim/src/TurbSim_Types.f90 | 299 + .../modules/turbsim/src/VelocitySpectra.f90 | 2158 + OpenFAST/modules/version/CMakeLists.txt | 36 + OpenFAST/modules/version/README.md | 20 + OpenFAST/modules/version/src/VersionInfo.f90 | 45 + OpenFAST/reg_tests/CMakeLists.txt | 104 + OpenFAST/reg_tests/CTestList.cmake | 175 + OpenFAST/reg_tests/README.md | 88 + .../reg_tests/executeAerodynRegressionCase.py | 138 + .../reg_tests/executeBeamdynRegressionCase.py | 137 + .../executeHydrodynRegressionCase.py | 141 + ...ecuteOpenfastAeroAcousticRegressionCase.py | 169 + .../executeOpenfastLinearRegressionCase.py | 272 + .../executeOpenfastRegressionCase.py | 186 + OpenFAST/reg_tests/lib/errorPlotting.py | 289 + OpenFAST/reg_tests/lib/fast_io.py | 180 + OpenFAST/reg_tests/lib/openfastDrivers.py | 66 + OpenFAST/reg_tests/lib/pass_fail.py | 101 + OpenFAST/reg_tests/lib/rtestlib.py | 57 + OpenFAST/reg_tests/manualRegressionTest.py | 96 + OpenFAST/share/discon/CMakeLists.txt | 100 + OpenFAST/share/discon/DISCON.F90 | 589 + OpenFAST/share/docker/openfast_dev/Dockerfile | 29 + .../share/docker/openfast_ubuntu/Dockerfile | 54 + OpenFAST/share/fast-build-cpp-spack.sh | 41 + OpenFAST/share/fast-build-cpp.sh | 17 + OpenFAST/share/fast-build.sh | 16 + OpenFAST/share/fast-install.sh | 118 + OpenFAST/share/spack/package.py | 99 + OpenFAST/share/template-module/ChangeLog.txt | 38 + OpenFAST/share/template-module/README.md | 3 + .../share/template-module/src/ModuleName.f90 | 851 + .../src/ModuleName_Registry.txt | 78 + .../template-module/src/ModuleName_Types.f90 | 1916 + .../src/drivers/ModName_Driver.f90 | 128 + OpenFAST/share/vscode/launch.json | 43 + OpenFAST/unit_tests/CMakeLists.txt | 80 + OpenFAST/unit_tests/README.md | 14 + OpenFAST/unit_tests/aerodyn/CMakeLists.txt | 61 + OpenFAST/unit_tests/beamdyn/CMakeLists.txt | 79 + OpenFAST/unit_tests/inflowwind/CMakeLists.txt | 67 + .../unit_tests/nwtc-library/CMakeLists.txt | 65 + OpenFAST/unit_tests/pfunit | 1 + OpenFAST/unit_tests/test_SUBROUTINE.F90 | 89 + OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.sln | 61 + .../vs-build/AeroDyn/AeroDyn_Driver.vfproj | 681 + .../vs-build/BeamDyn/BeamDyn-w-registry.sln | 64 + OpenFAST/vs-build/BeamDyn/BeamDyn.vfproj | 295 + OpenFAST/vs-build/CreateGitVersion.bat | 9 + OpenFAST/vs-build/Discon/Discon.sln | 51 + OpenFAST/vs-build/Discon/Discon.vfproj | 52 + .../vs-build/Discon/Discon_ITIBarge.vfproj | 52 + .../vs-build/Discon/Discon_OC3Hywind.vfproj | 52 + OpenFAST/vs-build/FAST/FAST.sln | 160 + OpenFAST/vs-build/FAST/FAST.vfproj | 92 + OpenFAST/vs-build/FASTlib/FASTlib.vfproj | 2235 + OpenFAST/vs-build/HydroDyn/HydroDynDriver.sln | 28 + .../vs-build/HydroDyn/HydroDynDriver.vfproj | 273 + .../vs-build/InflowWind/InflowWind_driver.sln | 61 + .../InflowWind/InflowWind_driver.vfproj | 357 + OpenFAST/vs-build/MAPlib/MAP_dll.vcxproj | 217 + .../OpenFAST-Simulink.vfproj | 62 + OpenFAST/vs-build/ReadMe.md | 20 + OpenFAST/vs-build/Registry/FAST_Registry.sln | 25 + .../vs-build/Registry/FAST_Registry.vcxproj | 179 + OpenFAST/vs-build/RunRegistry.bat | 328 + OpenFAST/vs-build/SubDyn/SubDyn.sln | 41 + OpenFAST/vs-build/SubDyn/SubDyn.vfproj | 183 + OpenFAST/vs-build/TurbSim/TurbSim.vfproj | 80 + .../vs-build/UnsteadyAero/UnsteadyAero.sln | 64 + .../vs-build/UnsteadyAero/UnsteadyAero.vfproj | 324 + 738 files changed, 678110 insertions(+) create mode 100644 OpenFAST/.gitattributes create mode 100644 OpenFAST/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 OpenFAST/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 OpenFAST/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 OpenFAST/.github/actions/tests-gluecode-openfast/action.yml create mode 100644 OpenFAST/.github/actions/tests-module-aerodyn/action.yml create mode 100644 OpenFAST/.github/actions/tests-module-beamdyn/action.yml create mode 100644 OpenFAST/.github/actions/tests-module-hydrodyn/action.yml create mode 100644 OpenFAST/.github/actions/tests-module-inflowwind/action.yml create mode 100644 OpenFAST/.github/actions/tests-module-nwtclibrary/action.yml create mode 100644 OpenFAST/.github/workflows/automated-dev-tests.yml create mode 100644 OpenFAST/.gitignore create mode 100644 OpenFAST/.gitmodules create mode 100644 OpenFAST/.readthedocs.yml create mode 100644 OpenFAST/CMakeLists.txt create mode 100644 OpenFAST/LICENSE create mode 100644 OpenFAST/README.rst create mode 100644 OpenFAST/cmake/FindMKL.cmake create mode 100644 OpenFAST/cmake/FindMatlab.cmake create mode 100644 OpenFAST/cmake/FindSphinx.cmake create mode 100644 OpenFAST/cmake/FindYAMLCPP.cmake create mode 100644 OpenFAST/cmake/GetGitRevisionDescription.cmake create mode 100644 OpenFAST/cmake/GetGitRevisionDescription.cmake.in create mode 100644 OpenFAST/cmake/OpenFASTConfig.cmake.in create mode 100644 OpenFAST/cmake/OpenfastCmakeUtils.cmake create mode 100644 OpenFAST/cmake/OpenfastFortranOptions.cmake create mode 100644 OpenFAST/docs/CMakeLists.txt create mode 100644 OpenFAST/docs/Doxyfile.in create mode 100644 OpenFAST/docs/DoxygenLayout.xml create mode 100644 OpenFAST/docs/OtherSupporting/DCM_Interpolation/DCM_Interpolation.pdf create mode 100644 OpenFAST/docs/OtherSupporting/DCM_Interpolation/DCM_Interpolation.tex create mode 100644 OpenFAST/docs/OtherSupporting/OpenFAST_Algorithms/OpenFAST_Algorithms.pdf create mode 100644 OpenFAST/docs/OtherSupporting/OpenFAST_Algorithms/OpenFAST_Algorithms.tex create mode 100644 OpenFAST/docs/OtherSupporting/OutListParameters.xlsx create mode 100644 OpenFAST/docs/_static/GitFlowFeatureBranches.png create mode 100644 OpenFAST/docs/_static/css/math_eq.css create mode 100644 OpenFAST/docs/_static/docs_options.png create mode 100644 OpenFAST/docs/_static/openfastlogo.jpg create mode 100644 OpenFAST/docs/conf.py create mode 100644 OpenFAST/docs/index.rst create mode 100644 OpenFAST/docs/requirements.txt create mode 100644 OpenFAST/docs/source/acknowledgements.rst create mode 100644 OpenFAST/docs/source/dev/build_doc.rst create mode 100644 OpenFAST/docs/source/dev/code_style.rst create mode 100644 OpenFAST/docs/source/dev/debugging.rst create mode 100644 OpenFAST/docs/source/dev/github_workflow.rst create mode 100644 OpenFAST/docs/source/dev/images/offshore_lapack.png create mode 100644 OpenFAST/docs/source/dev/index.rst create mode 100644 OpenFAST/docs/source/dev/other_docs.rst create mode 100644 OpenFAST/docs/source/dev/performance.rst create mode 100644 OpenFAST/docs/source/dev/types_files.rst create mode 100644 OpenFAST/docs/source/dev/versioning.rst create mode 100644 OpenFAST/docs/source/help.rst create mode 100644 OpenFAST/docs/source/install/index.rst create mode 100644 OpenFAST/docs/source/install/install_cygwin.rst create mode 100644 OpenFAST/docs/source/install/install_spack.rst create mode 100644 OpenFAST/docs/source/install/install_vs_windows.rst create mode 100644 OpenFAST/docs/source/license.rst create mode 100644 OpenFAST/docs/source/testing/index.rst create mode 100644 OpenFAST/docs/source/testing/regression_test.rst create mode 100644 OpenFAST/docs/source/testing/regression_test_windows.rst create mode 100644 OpenFAST/docs/source/testing/unit_test.rst create mode 100644 OpenFAST/docs/source/this_doc.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/01-introduction.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/02-noise-models.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/03-model-verification.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/04-conclusions.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/App-usage.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/acronyms.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AD15.ipt create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AF20_BL.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AFtab.dat create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AeroAcousticsInput.dat create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/BladeProp.dat create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/Observer.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/TIGrid.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/index.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN002.jpeg create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN003.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN004.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN005.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN006.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN007.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN008.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN009.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN010.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN011.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN012.png create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/references.bib create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/refs.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-aeroacoustics/symbols.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat create mode 100644 OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.inp create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Acknowledgments.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Acronyms.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/AppendixA.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/AppendixB.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/AppendixC.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--OLAF.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--PrescribeCirc.txt create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/FutureWork.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/InputFiles.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Introduction.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/OLAFTheory.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/OutputFiles.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/RunningOLAF.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.tex create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.png create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/StateSpace.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/bibliography.bib create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/index.rst create mode 100644 OpenFAST/docs/source/user/aerodyn-olaf/zrefs.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/ADNodalOutputs.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/appendix.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/NodalOutputs.txt create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/ad_airfoil_example.inp create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/ad_blade_example.inp create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/ad_driver_example.inp create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/ad_driver_timeseries_example.inp create mode 100644 OpenFAST/docs/source/user/aerodyn/examples/ad_primary_example.inp create mode 100644 OpenFAST/docs/source/user/aerodyn/figs/ad_blade_geom.png create mode 100644 OpenFAST/docs/source/user/aerodyn/figs/ad_blade_local_cs.png create mode 100644 OpenFAST/docs/source/user/aerodyn/figs/ad_driver_geom.png create mode 100644 OpenFAST/docs/source/user/aerodyn/figs/ad_output_channel.pdf create mode 100644 OpenFAST/docs/source/user/aerodyn/figs/ad_tower_geom.png create mode 100644 OpenFAST/docs/source/user/aerodyn/index.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/input.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/introduction.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/modeling.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/output.rst create mode 100644 OpenFAST/docs/source/user/aerodyn/theory.rst create mode 100644 OpenFAST/docs/source/user/api_change.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/BDNodalOutputs.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/appendix.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/examples/NodalOutputs.txt create mode 100644 OpenFAST/docs/source/user/beamdyn/examples/bd_driver_dynamic_nrel_5mw.inp create mode 100644 OpenFAST/docs/source/user/beamdyn/examples/bd_driver_static_nrel_5mw.inp create mode 100644 OpenFAST/docs/source/user/beamdyn/examples/bd_primary_nrel_5mw.inp create mode 100644 OpenFAST/docs/source/user/beamdyn/examples/nrel_5mw_blade.inp create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/bd_frame.pdf create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.docx create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.pdf create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/blade_geometry.jpg create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/flow_chart.jpg create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/frame.jpg create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/geometry_member1.png create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/geometry_member2.png create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/manual_plots.pptx create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/n4.pdf create mode 100644 OpenFAST/docs/source/user/beamdyn/figs/n8.pdf create mode 100644 OpenFAST/docs/source/user/beamdyn/future_work.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/index.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/input_files.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/introduction.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/output_files.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/references.bib create mode 100644 OpenFAST/docs/source/user/beamdyn/running_bd.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/theory.rst create mode 100644 OpenFAST/docs/source/user/beamdyn/zrefs.rst create mode 100644 OpenFAST/docs/source/user/cppapi/files/cDriver.i create mode 100644 OpenFAST/docs/source/user/cppapi/index.rst create mode 100644 OpenFAST/docs/source/user/elastodyn/EDNodalOutputs.rst create mode 100644 OpenFAST/docs/source/user/elastodyn/exampleInput/NodalOutpus.txt create mode 100644 OpenFAST/docs/source/user/elastodyn/index.rst create mode 100644 OpenFAST/docs/source/user/elastodyn/input.rst create mode 100644 OpenFAST/docs/source/user/fast_to_openfast.rst create mode 100644 OpenFAST/docs/source/user/index.rst create mode 100644 OpenFAST/docs/source/user/inflowwind/appendix.rst create mode 100644 OpenFAST/docs/source/user/inflowwind/driver.rst create mode 100644 OpenFAST/docs/source/user/inflowwind/examples/inflowwind_bladedscaling_example.dat create mode 100644 OpenFAST/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp create mode 100644 OpenFAST/docs/source/user/inflowwind/examples/inflowwind_example.dat create mode 100644 OpenFAST/docs/source/user/inflowwind/examples/inflowwind_uniform_example.dat create mode 100644 OpenFAST/docs/source/user/inflowwind/index.rst create mode 100644 OpenFAST/docs/source/user/inflowwind/input.rst create mode 100644 OpenFAST/glue-codes/CMakeLists.txt create mode 100644 OpenFAST/glue-codes/labview/src/OPENFAST_RT_DLL.f90 create mode 100644 OpenFAST/glue-codes/openfast-cpp/CMakeLists.txt create mode 100644 OpenFAST/glue-codes/openfast-cpp/src/FAST_Prog.cpp create mode 100644 OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.H create mode 100644 OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.cpp create mode 100644 OpenFAST/glue-codes/openfast-cpp/src/SC.h create mode 100644 OpenFAST/glue-codes/openfast/CMakeLists.txt create mode 100644 OpenFAST/glue-codes/openfast/src/FAST_Prog.c create mode 100644 OpenFAST/glue-codes/openfast/src/FAST_Prog.f90 create mode 100644 OpenFAST/glue-codes/python/OpenFAST.py create mode 100644 OpenFAST/glue-codes/python/openfast_library.py create mode 100644 OpenFAST/glue-codes/simulink/examples/OpenLoop.mdl create mode 100644 OpenFAST/glue-codes/simulink/examples/Run_OpenLoop.m create mode 100644 OpenFAST/glue-codes/simulink/examples/Run_Test01_SIG.m create mode 100644 OpenFAST/glue-codes/simulink/examples/Test01_SIG.mdl create mode 100644 OpenFAST/glue-codes/simulink/src/FAST_SFunc.c create mode 100644 OpenFAST/glue-codes/simulink/src/create_FAST_SFunc.m create mode 100644 OpenFAST/modules/aerodyn/CMakeLists.txt create mode 100644 OpenFAST/modules/aerodyn/README.md create mode 100644 OpenFAST/modules/aerodyn/src/AeroAcoustics.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroAcoustics_IO.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroAcoustics_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/AeroAcoustics_TNO.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroAcoustics_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Driver.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_IO.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/AeroDyn_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AirfoilInfo.f90 create mode 100644 OpenFAST/modules/aerodyn/src/AirfoilInfo_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/AirfoilInfo_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/BEMT.f90 create mode 100644 OpenFAST/modules/aerodyn/src/BEMTUncoupled.f90 create mode 100644 OpenFAST/modules/aerodyn/src/BEMT_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/BEMT_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/DBEMT.f90 create mode 100644 OpenFAST/modules/aerodyn/src/DBEMT_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/DBEMT_Test.f90 create mode 100644 OpenFAST/modules/aerodyn/src/DBEMT_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_BiotSavart.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_IO.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/FVW_Subs.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_Tests.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_VTK.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_VortexTools.f90 create mode 100644 OpenFAST/modules/aerodyn/src/FVW_Wings.f90 create mode 100644 OpenFAST/modules/aerodyn/src/UA_Dvr_Subs.f90 create mode 100644 OpenFAST/modules/aerodyn/src/UnsteadyAero.f90 create mode 100644 OpenFAST/modules/aerodyn/src/UnsteadyAero_Driver.f90 create mode 100644 OpenFAST/modules/aerodyn/src/UnsteadyAero_Registry.txt create mode 100644 OpenFAST/modules/aerodyn/src/UnsteadyAero_Types.f90 create mode 100644 OpenFAST/modules/aerodyn/src/mod_root1dim.f90 create mode 100644 OpenFAST/modules/aerodyn/tests/test_FVW_testsuite.F90 create mode 100644 OpenFAST/modules/aerodyn14/CMakeLists.txt create mode 100644 OpenFAST/modules/aerodyn14/README.md create mode 100644 OpenFAST/modules/aerodyn14/src/AD14AeroConf_Types.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/AD_RegistryEntries.xlsx create mode 100644 OpenFAST/modules/aerodyn14/src/AeroDyn14.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/AeroDyn14_Types.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/AeroSubs.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM_Types.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM_Wake_Sub_ver2.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_mod.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_sub.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/GenSubs.f90 create mode 100644 OpenFAST/modules/aerodyn14/src/Registry-AD14.txt create mode 100644 OpenFAST/modules/aerodyn14/src/Registry-AD14AeroConf.txt create mode 100644 OpenFAST/modules/aerodyn14/src/Registry-DWM.txt create mode 100644 OpenFAST/modules/beamdyn/CMakeLists.txt create mode 100644 OpenFAST/modules/beamdyn/README.md create mode 100644 OpenFAST/modules/beamdyn/src/BeamDyn.f90 create mode 100644 OpenFAST/modules/beamdyn/src/BeamDyn_BldNdOuts_IO.f90 create mode 100644 OpenFAST/modules/beamdyn/src/BeamDyn_IO.f90 create mode 100644 OpenFAST/modules/beamdyn/src/BeamDyn_Subs.f90 create mode 100644 OpenFAST/modules/beamdyn/src/BeamDyn_Types.f90 create mode 100644 OpenFAST/modules/beamdyn/src/Driver_Beam.f90 create mode 100644 OpenFAST/modules/beamdyn/src/Driver_Beam_Subs.f90 create mode 100644 OpenFAST/modules/beamdyn/src/Registry_BeamDyn.txt create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_CheckRotMat.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_ComputeIniNodalCrv.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_CrvCompose.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_CrvExtractCrv.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixH.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixR.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_DistrLoadCopy.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_GaussPointWeight.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_GenerateGLL.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_GravityForce.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_InitShpDerJaco.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_InputGlobalLocal.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_MemberEta.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_QPData_mEta_rho.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_TrapezoidalPointWeight.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_BD_diffmtc.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_ExtractRelativeRotation.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_InitializeNodalLocations.F90 create mode 100644 OpenFAST/modules/beamdyn/tests/test_tools.F90 create mode 100644 OpenFAST/modules/elastodyn/CMakeLists.txt create mode 100644 OpenFAST/modules/elastodyn/README.md create mode 100644 OpenFAST/modules/elastodyn/src/ED_UserSubs.f90 create mode 100644 OpenFAST/modules/elastodyn/src/ElastoDyn.f90 create mode 100644 OpenFAST/modules/elastodyn/src/ElastoDyn_AllBldNdOuts_IO.f90 create mode 100644 OpenFAST/modules/elastodyn/src/ElastoDyn_IO.f90 create mode 100644 OpenFAST/modules/elastodyn/src/ElastoDyn_Registry.txt create mode 100644 OpenFAST/modules/elastodyn/src/ElastoDyn_Types.f90 create mode 100644 OpenFAST/modules/extptfm/CMakeLists.txt create mode 100644 OpenFAST/modules/extptfm/README.md create mode 100644 OpenFAST/modules/extptfm/src/ExtPtfm_MCKF.f90 create mode 100644 OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Driver.f90 create mode 100644 OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_IO.f90 create mode 100644 OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt create mode 100644 OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 create mode 100644 OpenFAST/modules/feamooring/CMakeLists.txt create mode 100644 OpenFAST/modules/feamooring/README.md create mode 100644 OpenFAST/modules/feamooring/src/FEAM.f90 create mode 100644 OpenFAST/modules/feamooring/src/FEAM_Driver.f90 create mode 100644 OpenFAST/modules/feamooring/src/FEAM_Registry.txt create mode 100644 OpenFAST/modules/feamooring/src/FEAMooring_Types.f90 create mode 100644 OpenFAST/modules/feamooring/test/FE_Mooring.dat create mode 100644 OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_ITIBarge4_FEAMooring.dat create mode 100644 OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_MIT_NREL_TLP_FEAMooring.dat create mode 100644 OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC3Hywind_FEAMooring.dat create mode 100644 OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC4DeepCwindSemi_FEAMooring.dat create mode 100644 OpenFAST/modules/hydrodyn/CMakeLists.txt create mode 100644 OpenFAST/modules/hydrodyn/README.md create mode 100644 OpenFAST/modules/hydrodyn/src/Conv_Radiation.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Conv_Radiation.txt create mode 100644 OpenFAST/modules/hydrodyn/src/Conv_Radiation_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Current.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Current.txt create mode 100644 OpenFAST/modules/hydrodyn/src/Current_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn.txt create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn_DriverCode.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn_Input.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn_Output.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/HydroDyn_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Morison.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Morison.txt create mode 100644 OpenFAST/modules/hydrodyn/src/Morison_Output.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Morison_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Excitation.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Excitation.txt create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Excitation_Driver.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Excitation_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Radiation.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Radiation.txt create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Radiation_DriverCode.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/SS_Radiation_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/UserWaves.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT.txt create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT2.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT2.txt create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT2_Output.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT2_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT_Interp.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT_Output.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/WAMIT_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Waves.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Waves.txt create mode 100644 OpenFAST/modules/hydrodyn/src/Waves2.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Waves2.txt create mode 100644 OpenFAST/modules/hydrodyn/src/Waves2_Output.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Waves2_Types.f90 create mode 100644 OpenFAST/modules/hydrodyn/src/Waves_Types.f90 create mode 100644 OpenFAST/modules/icedyn/CMakeLists.txt create mode 100644 OpenFAST/modules/icedyn/README.md create mode 100644 OpenFAST/modules/icedyn/src/Driver_IceDyn.f90 create mode 100644 OpenFAST/modules/icedyn/src/IceDyn.f90 create mode 100644 OpenFAST/modules/icedyn/src/IceDyn_Types.f90 create mode 100644 OpenFAST/modules/icedyn/src/Registry_IceDyn.txt create mode 100644 OpenFAST/modules/icefloe/CMakeLists.txt create mode 100644 OpenFAST/modules/icefloe/README.md create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFlexBase.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFlexIEC.f90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFlexISO.f90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFloeBase.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types.f90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types_notFAST.f90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/coupledCrushing.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/crushingIEC.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/crushingISO.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/iceInput.f90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/iceLog.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/intermittentCrushing.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/lockInISO.F90 create mode 100644 OpenFAST/modules/icefloe/src/icefloe/randomCrushing.F90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/ADAMS/IceADAMS_VFOSUB.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/Bladed/IceFloeBladed.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/Console/IceFloe.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/Console/NWTC_Base_reduced.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/Console/SysIVF_reduced.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe_FASTRegistry.inp create mode 100644 OpenFAST/modules/icefloe/src/interfaces/HAWC2/HAWC2_DLL.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/HAWC2/NWTC_IO_reduced.f90 create mode 100644 OpenFAST/modules/icefloe/src/interfaces/IceFloe_Test.f90 create mode 100644 OpenFAST/modules/icefloe/test/GLA_Proto_flex_ISO.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_Proto_intercrush_ISO.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_Proto_lockin_ISO.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_Proto_randomcrush_ISO.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.log create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.log create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.log create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.inp create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.log create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.log create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.dat create mode 100644 OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.log create mode 100644 OpenFAST/modules/icefloe/test/runAll.bat create mode 100644 OpenFAST/modules/inflowwind/CMakeLists.txt create mode 100644 OpenFAST/modules/inflowwind/README.md create mode 100644 OpenFAST/modules/inflowwind/src/CTWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/FDWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_4Dext.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_4Dext.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_4Dext_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_HAWCWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_HAWCWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_HAWCWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_TSFFWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_TSFFWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_TSFFWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UniformWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UniformWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UniformWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UserWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UserWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/IfW_UserWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind.txt create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind_Driver.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind_Driver_Subs.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind_Driver_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind_Subs.f90 create mode 100644 OpenFAST/modules/inflowwind/src/InflowWind_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/src/Lidar.f90 create mode 100644 OpenFAST/modules/inflowwind/src/Lidar.txt create mode 100644 OpenFAST/modules/inflowwind/src/Lidar_Types.f90 create mode 100644 OpenFAST/modules/inflowwind/tests/ifw_test_tools.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_bladed_wind.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_hawc_wind.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_outputs.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_steady_wind.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_turbsim_wind.F90 create mode 100644 OpenFAST/modules/inflowwind/tests/test_uniform_wind.F90 create mode 100644 OpenFAST/modules/map/CMakeLists.txt create mode 100644 OpenFAST/modules/map/README.md create mode 100644 OpenFAST/modules/map/src/MAP_Fortran_Registry.txt create mode 100644 OpenFAST/modules/map/src/MAP_Fortran_Types.f90 create mode 100644 OpenFAST/modules/map/src/MAP_Registry.txt create mode 100644 OpenFAST/modules/map/src/MAP_Types.f90 create mode 100644 OpenFAST/modules/map/src/MAP_Types.h create mode 100644 OpenFAST/modules/map/src/bstring/bstraux.c create mode 100644 OpenFAST/modules/map/src/bstring/bstraux.h create mode 100644 OpenFAST/modules/map/src/bstring/bstrlib.c create mode 100644 OpenFAST/modules/map/src/bstring/bstrlib.h create mode 100644 OpenFAST/modules/map/src/cminpack/cminpack.h create mode 100644 OpenFAST/modules/map/src/cminpack/cminpackP.h create mode 100644 OpenFAST/modules/map/src/cminpack/dpmpar.c create mode 100644 OpenFAST/modules/map/src/cminpack/enorm.c create mode 100644 OpenFAST/modules/map/src/cminpack/enorm_u.c create mode 100644 OpenFAST/modules/map/src/cminpack/lmder.c create mode 100644 OpenFAST/modules/map/src/cminpack/lmpar.c create mode 100644 OpenFAST/modules/map/src/cminpack/minpack.h create mode 100644 OpenFAST/modules/map/src/cminpack/qrfac.c create mode 100644 OpenFAST/modules/map/src/cminpack/qrsolv.c create mode 100644 OpenFAST/modules/map/src/freedata.c create mode 100644 OpenFAST/modules/map/src/freedata.h create mode 100644 OpenFAST/modules/map/src/jacobian.c create mode 100644 OpenFAST/modules/map/src/jacobian.h create mode 100644 OpenFAST/modules/map/src/lapack/lapacke.h create mode 100644 OpenFAST/modules/map/src/lapack/lapacke_mangling.h create mode 100644 OpenFAST/modules/map/src/lineroutines.c create mode 100644 OpenFAST/modules/map/src/lineroutines.h create mode 100644 OpenFAST/modules/map/src/lmroutines.cc create mode 100644 OpenFAST/modules/map/src/lmroutines.hpp create mode 100644 OpenFAST/modules/map/src/makefile create mode 100644 OpenFAST/modules/map/src/map.f90 create mode 100644 OpenFAST/modules/map/src/map.h create mode 100644 OpenFAST/modules/map/src/map_glue.f90 create mode 100644 OpenFAST/modules/map/src/mapapi.c create mode 100644 OpenFAST/modules/map/src/mapapi.h create mode 100644 OpenFAST/modules/map/src/maperror.c create mode 100644 OpenFAST/modules/map/src/maperror.h create mode 100644 OpenFAST/modules/map/src/mapinit.c create mode 100644 OpenFAST/modules/map/src/mapinit.h create mode 100644 OpenFAST/modules/map/src/mapsys.h create mode 100644 OpenFAST/modules/map/src/numeric.c create mode 100644 OpenFAST/modules/map/src/numeric.h create mode 100644 OpenFAST/modules/map/src/outputstream.c create mode 100644 OpenFAST/modules/map/src/outputstream.h create mode 100644 OpenFAST/modules/map/src/residual.c create mode 100644 OpenFAST/modules/map/src/residual.h create mode 100644 OpenFAST/modules/map/src/simclist/simclist.c create mode 100644 OpenFAST/modules/map/src/simclist/simclist.h create mode 100644 OpenFAST/modules/moordyn/CMakeLists.txt create mode 100644 OpenFAST/modules/moordyn/README.md create mode 100644 OpenFAST/modules/moordyn/src/MoorDyn.f90 create mode 100644 OpenFAST/modules/moordyn/src/MoorDyn_Driver.f90 create mode 100644 OpenFAST/modules/moordyn/src/MoorDyn_IO.f90 create mode 100644 OpenFAST/modules/moordyn/src/MoorDyn_Registry.txt create mode 100644 OpenFAST/modules/moordyn/src/MoorDyn_Types.f90 create mode 100644 OpenFAST/modules/nwtc-library/CMakeLists.txt create mode 100644 OpenFAST/modules/nwtc-library/README.md create mode 100644 OpenFAST/modules/nwtc-library/src/Generate_NWTC_Library_Types.bat create mode 100644 OpenFAST/modules/nwtc-library/src/ModMesh.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/ModMesh_Mapping.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/ModMesh_Types.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_Base.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_IO.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_Library.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_Library_Types.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_Num.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NWTC_RandomNumber.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/NWTC_FitPack.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/dierckx_fitpack.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/readme.txt create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/fftpack/NWTC_FFTPACK.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/fftpack/doc.txt create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/fftpack/fftpack4.1.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/scalapack/NWTC_ScaLAPACK.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/scalapack/dlasrt2.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/scalapack/slasrt2.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/NWTC_SLATEC.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/aaaaaa.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/d1mach.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/dqk61.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/fdump.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/i1mach.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/j4save.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/qk61.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/r1mach.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xercnt.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerhlt.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xermsg.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerprn.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xersve.f create mode 100644 OpenFAST/modules/nwtc-library/src/NetLib/slatec/xgetua.f create mode 100644 OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library.txt create mode 100644 OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_mesh.txt create mode 100644 OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_nomesh.txt create mode 100644 OpenFAST/modules/nwtc-library/src/SingPrec.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysGnuLinux.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysGnuWin.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysIFL.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysIVF.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysIVF_Labview.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysMatlabLinuxGnu.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysMatlabLinuxIntel.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/SysMatlabWindows.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/ranlux/RANLUX.f90 create mode 100644 OpenFAST/modules/nwtc-library/src/readme.txt create mode 100644 OpenFAST/modules/nwtc-library/test/Compare_LAPACK_MUMPS/Compare_LAPACK_MUMPS.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_CheckArgs.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/Test_ChkRealFmtStr.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/makefile create mode 100644 OpenFAST/modules/nwtc-library/test/Test_FileSize/Test_FileSize.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_FileSize/makefile create mode 100644 OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Makefile create mode 100644 OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping_Mod.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_NWTC_Library.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/Test_OpenCon_GnuWin.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/makefile create mode 100644 OpenFAST/modules/nwtc-library/test/Test_ReadComFile/Test_ReadComFile.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_ReadComFile/makefile create mode 100644 OpenFAST/modules/nwtc-library/test/Test_ReadFASTbin.f90 create mode 100644 OpenFAST/modules/nwtc-library/test/Test_RegCubicSpline/Test_RegCubicSpline.f90 create mode 100644 OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_CheckArgs.F90 create mode 100644 OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_FileInfo.F90 create mode 100644 OpenFAST/modules/nwtc-library/tests/test_NWTC_RandomNumber.F90 create mode 100644 OpenFAST/modules/openfast-library/CMakeLists.txt create mode 100644 OpenFAST/modules/openfast-library/README.md create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Library.f90 create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Library.h create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Lin.f90 create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Mods.f90 create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Registry.txt create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Solver.f90 create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Subs.f90 create mode 100644 OpenFAST/modules/openfast-library/src/FAST_Types.f90 create mode 100644 OpenFAST/modules/openfast-registry/CMakeLists.txt create mode 100644 OpenFAST/modules/openfast-registry/README.md create mode 100644 OpenFAST/modules/openfast-registry/src/FAST_preamble.h create mode 100644 OpenFAST/modules/openfast-registry/src/Template_data.c create mode 100644 OpenFAST/modules/openfast-registry/src/Template_registry.c create mode 100644 OpenFAST/modules/openfast-registry/src/data.c create mode 100644 OpenFAST/modules/openfast-registry/src/data.h create mode 100644 OpenFAST/modules/openfast-registry/src/gen_c_types.c create mode 100644 OpenFAST/modules/openfast-registry/src/gen_module_files.c create mode 100644 OpenFAST/modules/openfast-registry/src/misc.c create mode 100644 OpenFAST/modules/openfast-registry/src/my_strtok.c create mode 100644 OpenFAST/modules/openfast-registry/src/protos.h create mode 100644 OpenFAST/modules/openfast-registry/src/reg_parse.c create mode 100644 OpenFAST/modules/openfast-registry/src/registry.c create mode 100644 OpenFAST/modules/openfast-registry/src/registry.h create mode 100644 OpenFAST/modules/openfast-registry/src/sym.c create mode 100644 OpenFAST/modules/openfast-registry/src/sym.h create mode 100644 OpenFAST/modules/openfast-registry/src/symtab_gen.c create mode 100644 OpenFAST/modules/openfast-registry/src/type.c create mode 100644 OpenFAST/modules/openfoam/CMakeLists.txt create mode 100644 OpenFAST/modules/openfoam/README.md create mode 100644 OpenFAST/modules/openfoam/src/OpenFOAM.f90 create mode 100644 OpenFAST/modules/openfoam/src/OpenFOAM_Registry.txt create mode 100644 OpenFAST/modules/openfoam/src/OpenFOAM_Types.f90 create mode 100644 OpenFAST/modules/openfoam/src/OpenFOAM_Types.h create mode 100644 OpenFAST/modules/orcaflex-interface/CMakeLists.txt create mode 100644 OpenFAST/modules/orcaflex-interface/README.md create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaDriver.f90 create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Subs.f90 create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Types.f90 create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.f90 create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.txt create mode 100644 OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface_Types.f90 create mode 100644 OpenFAST/modules/servodyn/CMakeLists.txt create mode 100644 OpenFAST/modules/servodyn/README.md create mode 100644 OpenFAST/modules/servodyn/src/BladedInterface.f90 create mode 100644 OpenFAST/modules/servodyn/src/PitchCntrl_ACH.f90 create mode 100644 OpenFAST/modules/servodyn/src/ServoDyn.f90 create mode 100644 OpenFAST/modules/servodyn/src/ServoDyn_Driver.f90 create mode 100644 OpenFAST/modules/servodyn/src/ServoDyn_Registry.txt create mode 100644 OpenFAST/modules/servodyn/src/ServoDyn_Types.f90 create mode 100644 OpenFAST/modules/servodyn/src/TMD.f90 create mode 100644 OpenFAST/modules/servodyn/src/TMD_Driver.f90 create mode 100644 OpenFAST/modules/servodyn/src/TMD_Registry.txt create mode 100644 OpenFAST/modules/servodyn/src/TMD_Types.f90 create mode 100644 OpenFAST/modules/servodyn/src/UserSubs.f90 create mode 100644 OpenFAST/modules/servodyn/src/UserVSCont_KP.f90 create mode 100644 OpenFAST/modules/subdyn/CMakeLists.txt create mode 100644 OpenFAST/modules/subdyn/README.md create mode 100644 OpenFAST/modules/subdyn/src/SD_FEM.f90 create mode 100644 OpenFAST/modules/subdyn/src/SubDyn.f90 create mode 100644 OpenFAST/modules/subdyn/src/SubDyn_Driver.f90 create mode 100644 OpenFAST/modules/subdyn/src/SubDyn_Output.f90 create mode 100644 OpenFAST/modules/subdyn/src/SubDyn_Registry.txt create mode 100644 OpenFAST/modules/subdyn/src/SubDyn_Types.f90 create mode 100644 OpenFAST/modules/subdyn/src/qsort_c_module.f90 create mode 100644 OpenFAST/modules/supercontroller/CMakeLists.txt create mode 100644 OpenFAST/modules/supercontroller/README.md create mode 100644 OpenFAST/modules/supercontroller/src/SuperController.f90 create mode 100644 OpenFAST/modules/supercontroller/src/SuperController_Registry.txt create mode 100644 OpenFAST/modules/supercontroller/src/SuperController_Types.f90 create mode 100644 OpenFAST/modules/supercontroller/src/SuperController_Types.h create mode 100644 OpenFAST/modules/turbsim/CMakeLists.txt create mode 100644 OpenFAST/modules/turbsim/README.md create mode 100644 OpenFAST/modules/turbsim/src/BlankModVKM.f90 create mode 100644 OpenFAST/modules/turbsim/src/CohStructures.f90 create mode 100644 OpenFAST/modules/turbsim/src/Profiles.f90 create mode 100644 OpenFAST/modules/turbsim/src/RandNum.f90 create mode 100644 OpenFAST/modules/turbsim/src/Root_Searching.f90 create mode 100644 OpenFAST/modules/turbsim/src/TS_FileIO.f90 create mode 100644 OpenFAST/modules/turbsim/src/TSsubs.f90 create mode 100644 OpenFAST/modules/turbsim/src/TurbSim.f90 create mode 100644 OpenFAST/modules/turbsim/src/TurbSim_Types.f90 create mode 100644 OpenFAST/modules/turbsim/src/VelocitySpectra.f90 create mode 100644 OpenFAST/modules/version/CMakeLists.txt create mode 100644 OpenFAST/modules/version/README.md create mode 100644 OpenFAST/modules/version/src/VersionInfo.f90 create mode 100644 OpenFAST/reg_tests/CMakeLists.txt create mode 100644 OpenFAST/reg_tests/CTestList.cmake create mode 100644 OpenFAST/reg_tests/README.md create mode 100644 OpenFAST/reg_tests/executeAerodynRegressionCase.py create mode 100644 OpenFAST/reg_tests/executeBeamdynRegressionCase.py create mode 100644 OpenFAST/reg_tests/executeHydrodynRegressionCase.py create mode 100644 OpenFAST/reg_tests/executeOpenfastAeroAcousticRegressionCase.py create mode 100644 OpenFAST/reg_tests/executeOpenfastLinearRegressionCase.py create mode 100644 OpenFAST/reg_tests/executeOpenfastRegressionCase.py create mode 100644 OpenFAST/reg_tests/lib/errorPlotting.py create mode 100644 OpenFAST/reg_tests/lib/fast_io.py create mode 100644 OpenFAST/reg_tests/lib/openfastDrivers.py create mode 100644 OpenFAST/reg_tests/lib/pass_fail.py create mode 100644 OpenFAST/reg_tests/lib/rtestlib.py create mode 100644 OpenFAST/reg_tests/manualRegressionTest.py create mode 100644 OpenFAST/share/discon/CMakeLists.txt create mode 100644 OpenFAST/share/discon/DISCON.F90 create mode 100644 OpenFAST/share/docker/openfast_dev/Dockerfile create mode 100644 OpenFAST/share/docker/openfast_ubuntu/Dockerfile create mode 100755 OpenFAST/share/fast-build-cpp-spack.sh create mode 100755 OpenFAST/share/fast-build-cpp.sh create mode 100755 OpenFAST/share/fast-build.sh create mode 100755 OpenFAST/share/fast-install.sh create mode 100644 OpenFAST/share/spack/package.py create mode 100644 OpenFAST/share/template-module/ChangeLog.txt create mode 100644 OpenFAST/share/template-module/README.md create mode 100644 OpenFAST/share/template-module/src/ModuleName.f90 create mode 100644 OpenFAST/share/template-module/src/ModuleName_Registry.txt create mode 100644 OpenFAST/share/template-module/src/ModuleName_Types.f90 create mode 100644 OpenFAST/share/template-module/src/drivers/ModName_Driver.f90 create mode 100644 OpenFAST/share/vscode/launch.json create mode 100644 OpenFAST/unit_tests/CMakeLists.txt create mode 100644 OpenFAST/unit_tests/README.md create mode 100644 OpenFAST/unit_tests/aerodyn/CMakeLists.txt create mode 100644 OpenFAST/unit_tests/beamdyn/CMakeLists.txt create mode 100644 OpenFAST/unit_tests/inflowwind/CMakeLists.txt create mode 100644 OpenFAST/unit_tests/nwtc-library/CMakeLists.txt create mode 160000 OpenFAST/unit_tests/pfunit create mode 100644 OpenFAST/unit_tests/test_SUBROUTINE.F90 create mode 100644 OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.sln create mode 100644 OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.vfproj create mode 100644 OpenFAST/vs-build/BeamDyn/BeamDyn-w-registry.sln create mode 100644 OpenFAST/vs-build/BeamDyn/BeamDyn.vfproj create mode 100644 OpenFAST/vs-build/CreateGitVersion.bat create mode 100644 OpenFAST/vs-build/Discon/Discon.sln create mode 100644 OpenFAST/vs-build/Discon/Discon.vfproj create mode 100644 OpenFAST/vs-build/Discon/Discon_ITIBarge.vfproj create mode 100644 OpenFAST/vs-build/Discon/Discon_OC3Hywind.vfproj create mode 100644 OpenFAST/vs-build/FAST/FAST.sln create mode 100644 OpenFAST/vs-build/FAST/FAST.vfproj create mode 100644 OpenFAST/vs-build/FASTlib/FASTlib.vfproj create mode 100644 OpenFAST/vs-build/HydroDyn/HydroDynDriver.sln create mode 100644 OpenFAST/vs-build/HydroDyn/HydroDynDriver.vfproj create mode 100644 OpenFAST/vs-build/InflowWind/InflowWind_driver.sln create mode 100644 OpenFAST/vs-build/InflowWind/InflowWind_driver.vfproj create mode 100644 OpenFAST/vs-build/MAPlib/MAP_dll.vcxproj create mode 100644 OpenFAST/vs-build/OpenFAST-Simulink/OpenFAST-Simulink.vfproj create mode 100644 OpenFAST/vs-build/ReadMe.md create mode 100644 OpenFAST/vs-build/Registry/FAST_Registry.sln create mode 100644 OpenFAST/vs-build/Registry/FAST_Registry.vcxproj create mode 100644 OpenFAST/vs-build/RunRegistry.bat create mode 100644 OpenFAST/vs-build/SubDyn/SubDyn.sln create mode 100644 OpenFAST/vs-build/SubDyn/SubDyn.vfproj create mode 100644 OpenFAST/vs-build/TurbSim/TurbSim.vfproj create mode 100644 OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.sln create mode 100644 OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.vfproj diff --git a/OpenFAST/.gitattributes b/OpenFAST/.gitattributes new file mode 100644 index 000000000..096b1c29a --- /dev/null +++ b/OpenFAST/.gitattributes @@ -0,0 +1,6 @@ +# add (semi-useful) version info to git archive +CreateGitVersion.bat ident export-subst + +# Declare files that will always have CRLF line endings on checkout. +*.bat text eol=crlf + diff --git a/OpenFAST/.github/ISSUE_TEMPLATE/bug_report.md b/OpenFAST/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..a9fd553b0 --- /dev/null +++ b/OpenFAST/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,56 @@ +--- +name: Bug report +about: Report a bug to help us improve +title: 'Bug report' +labels: "Type: Bug" +--- + +**Bug description** + + +**To Reproduce** + +Steps to reproduce the behavior: +1. Compile with '...' +2. Run '...' case with '...' settings +3. Open '...' output +4. See the error + +**Expected behavior** + + +**Screenshots, if applicable** + + +**OpenFAST Version** + + +``` +************************************************************************************************** + OpenFAST + + Copyright (C) National Renewable Energy Laboratory + Copyright (C) Envision Energy USA LTD + + This program is licensed under Apache License Version 2.0 and comes with ABSOLUTELY NO WARRANTY. + See the "LICENSE" file distributed with this software for details. + ************************************************************************************************** + + OpenFAST-v2.0.0 + Compile Info: + - Architecture: 64 bit + - Precision: double + - Date: Nov 27 2018 + - Time: 17:19:38 + Execution Info: + - Date: 11/29/2018 + - Time: 10:52:28-0700 +``` + +**System Information (please complete the following information):** + - OS: + - Compiler: + - Compiler settings: + +**Additional context** + \ No newline at end of file diff --git a/OpenFAST/.github/ISSUE_TEMPLATE/feature_request.md b/OpenFAST/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..b1a58ca9f --- /dev/null +++ b/OpenFAST/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: 'Feature request' +labels: 'Type: Enhancement' +--- + +**Is your feature request related to a problem? Please describe.** + + +**Describe the solution you'd like** + + +**Describe alternatives you've considered** + + +**Additional context** + diff --git a/OpenFAST/.github/PULL_REQUEST_TEMPLATE.md b/OpenFAST/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..fd601a3d4 --- /dev/null +++ b/OpenFAST/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ + + + + +**Feature or improvement description** + + +**Related issue, if one exists** + + +**Impacted areas of the software** + + +**Additional supporting information** + + +**Test results, if applicable** + diff --git a/OpenFAST/.github/actions/tests-gluecode-openfast/action.yml b/OpenFAST/.github/actions/tests-gluecode-openfast/action.yml new file mode 100644 index 000000000..e29549283 --- /dev/null +++ b/OpenFAST/.github/actions/tests-gluecode-openfast/action.yml @@ -0,0 +1,21 @@ +name: 'OpenFAST glue code tests' +description: 'Run tests focused on the OpenFAST glue code' +author: 'Rafael Mudafort https://github.com/rafmudaf' +runs: + using: 'composite' + steps: + - run: | + ctest -VV -L linear -E Ideal + ctest -VV -j8 -I 1,1,1,2,3,4,5,6,7,8,10,11,12,13,14,15,17,18,21,22,23,24,25,26,27,28,29 + working-directory: ${{runner.workspace}}/build + shell: bash + +# OpenFAST linearization tests +# Dont run these in parallel, copying the case files can fail in a race condition +# Exclude the Ideal_Beam test cases +# - They fail consistently in the Docker container when run on GitHub, +# but pass everywhere else including running the same Docker image locally + +# Subset of OpenFAST regression tests; do not run +# - 9, 16 because they're very sensitive +# - 19, 20 because they're too long diff --git a/OpenFAST/.github/actions/tests-module-aerodyn/action.yml b/OpenFAST/.github/actions/tests-module-aerodyn/action.yml new file mode 100644 index 000000000..bc83c599e --- /dev/null +++ b/OpenFAST/.github/actions/tests-module-aerodyn/action.yml @@ -0,0 +1,9 @@ +name: 'AeroDyn module tests' +description: 'Run tests specific to the AeroDyn module' +author: 'Rafael Mudafort https://github.com/rafmudaf' +runs: + using: "composite" + steps: + - run: ctest -VV -R fvw_utest + working-directory: ${{runner.workspace}}/build + shell: bash diff --git a/OpenFAST/.github/actions/tests-module-beamdyn/action.yml b/OpenFAST/.github/actions/tests-module-beamdyn/action.yml new file mode 100644 index 000000000..660a2de9f --- /dev/null +++ b/OpenFAST/.github/actions/tests-module-beamdyn/action.yml @@ -0,0 +1,24 @@ +name: 'BeamDyn module tests' +description: 'Run tests specific to the BeamDyn module' +author: 'Rafael Mudafort https://github.com/rafmudaf' + +inputs: + test-target: + description: 'Which tests to run: unit | regression | all' + default: 'all' + +runs: + using: "composite" + steps: + - run: | + + if [[ ${{ inputs.test-target }} == "unit" ]] || [[ ${{ inputs.test-target }} == "all" ]]; then + ctest -VV -R beamdyn_utest + fi + + if [[ ${{ inputs.test-target }} == "regression" ]] || [[ ${{ inputs.test-target }} == "all" ]]; then + ctest -VV -j7 -R bd_ + fi + + working-directory: ${{runner.workspace}}/build + shell: bash diff --git a/OpenFAST/.github/actions/tests-module-hydrodyn/action.yml b/OpenFAST/.github/actions/tests-module-hydrodyn/action.yml new file mode 100644 index 000000000..4890c414f --- /dev/null +++ b/OpenFAST/.github/actions/tests-module-hydrodyn/action.yml @@ -0,0 +1,9 @@ +name: 'HydroDyn module tests' +description: 'Run tests specific to the HydroDyn module' +author: 'Rafael Mudafort https://github.com/rafmudaf' +runs: + using: "composite" + steps: + - run: ctest -VV -j7 -R hd_ + working-directory: ${{runner.workspace}}/build + shell: bash diff --git a/OpenFAST/.github/actions/tests-module-inflowwind/action.yml b/OpenFAST/.github/actions/tests-module-inflowwind/action.yml new file mode 100644 index 000000000..4a204980a --- /dev/null +++ b/OpenFAST/.github/actions/tests-module-inflowwind/action.yml @@ -0,0 +1,9 @@ +name: 'InflowWind module tests' +description: 'Run tests specific to the InflowWind module' +author: 'Rafael Mudafort https://github.com/rafmudaf' +runs: + using: "composite" + steps: + - run: ctest -VV -R inflowwind_utest + working-directory: ${{runner.workspace}}/build + shell: bash diff --git a/OpenFAST/.github/actions/tests-module-nwtclibrary/action.yml b/OpenFAST/.github/actions/tests-module-nwtclibrary/action.yml new file mode 100644 index 000000000..a8d27e417 --- /dev/null +++ b/OpenFAST/.github/actions/tests-module-nwtclibrary/action.yml @@ -0,0 +1,9 @@ +name: 'NWTC Library module tests' +description: 'Run tests specific to the NWTC Library module' +author: 'Rafael Mudafort https://github.com/rafmudaf' +runs: + using: "composite" + steps: + - run: ctest -VV -R nwtc_library_utest + working-directory: ${{runner.workspace}}/build + shell: bash diff --git a/OpenFAST/.github/workflows/automated-dev-tests.yml b/OpenFAST/.github/workflows/automated-dev-tests.yml new file mode 100644 index 000000000..1a7c6f7ba --- /dev/null +++ b/OpenFAST/.github/workflows/automated-dev-tests.yml @@ -0,0 +1,148 @@ + +name: 'Development Pipeline' + +on: + push: + paths-ignore: + - 'docs/**' + - 'share/**' + - 'vs-build/**' + + pull_request: + types: [opened, synchronize] #labeled, assigned] + paths-ignore: + - 'docs/**' + - 'share/**' + - 'vs-build/**' + +env: + FORTRAN_COMPILER: gfortran-10 + NUM_PROCS: 8 + +# runs-on: ${{ matrix.os }} +# strategy: +# matrix: +# os: [macOS-10.14, ubuntu-18.04] + +jobs: + regression-test: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@main + with: + submodules: recursive + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.7' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install numpy Bokeh==1.4 + + - name: Setup Workspace + run: cmake -E make_directory ${{runner.workspace}}/build + - name: Configure Build + working-directory: ${{runner.workspace}}/build + run: | + cmake \ + -DCMAKE_INSTALL_PREFIX:PATH=${{runner.workspace}}/install \ + -DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \ + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ + -DBUILD_TESTING:BOOL=ON \ + -DCTEST_PLOT_ERRORS:BOOL=ON \ + ${GITHUB_WORKSPACE} + - name: Build OpenFAST + # if: contains(github.event.head_commit.message, 'Action - Test All') || contains(github.event.pull_request.labels.*.name, 'Action - Test All') + working-directory: ${{runner.workspace}}/build + run: cmake --build . --target install -- -j ${{env.NUM_PROCS}} + + - name: Run BeamDyn tests + uses: ./.github/actions/tests-module-beamdyn + with: + test-target: regression + - name: Run HydroDyn tests + uses: ./.github/actions/tests-module-hydrodyn + - name: Run OpenFAST tests + # if: contains(github.event.head_commit.message, 'Action - Test All') || contains(github.event.pull_request.labels.*.name, 'Action - Test All') + uses: ./.github/actions/tests-gluecode-openfast + + - name: Failing test artifacts + uses: actions/upload-artifact@v2 + if: failure() + with: + name: test-results + path: | + ${{runner.workspace}}/build/reg_tests/modules + ${{runner.workspace}}/build/reg_tests/glue-codes/openfast + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/5MW_Baseline + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/AOC + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/AWT27 + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/SWRT + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/UAE_VI + !${{runner.workspace}}/build/reg_tests/glue-codes/openfast/WP_Baseline + + unit-test: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@main + with: + submodules: recursive + - name: Setup + run: cmake -E make_directory ${{runner.workspace}}/build + - name: Configure + working-directory: ${{runner.workspace}}/build + run: | + cmake \ + -DCMAKE_INSTALL_PREFIX:PATH=${{runner.workspace}}/install \ + -DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \ + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ + -DBUILD_TESTING:BOOL=ON \ + ${GITHUB_WORKSPACE} + + - name: Build unit tests + working-directory: ${{runner.workspace}}/build + run: cmake --build . --target unit_tests -- -j ${{env.NUM_PROCS}} + + - name: Run NWTC Library tests + uses: ./.github/actions/tests-module-nwtclibrary + - name: Run AeroDyn tests + uses: ./.github/actions/tests-module-aerodyn + - name: Run BeamDyn tests + uses: ./.github/actions/tests-module-beamdyn + with: + test-target: unit + - name: Run InflowWind tests + uses: ./.github/actions/tests-module-inflowwind + + compile-all-single-precision: + # Test if single precision compile completes. + # Compiles all targets excluding tests. + # Do not run the test suite. + + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@main + with: + submodules: recursive + - name: Setup + run: cmake -E make_directory ${{runner.workspace}}/build + - name: Configure + working-directory: ${{runner.workspace}}/build + run: | + cmake \ + -DCMAKE_INSTALL_PREFIX:PATH=${{runner.workspace}}/install \ + -DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \ + -DCMAKE_BUILD_TYPE:STRING=Debug \ + -DDOUBLE_PRECISION:BOOL=OFF \ + ${GITHUB_WORKSPACE} + - name: Build all + working-directory: ${{runner.workspace}}/build + run: cmake --build . --target all -- -j ${{env.NUM_PROCS}} + - name: Test + working-directory: ${{runner.workspace}}/build + run: ./glue-codes/openfast/openfast -v diff --git a/OpenFAST/.gitignore b/OpenFAST/.gitignore new file mode 100644 index 000000000..3827d6e22 --- /dev/null +++ b/OpenFAST/.gitignore @@ -0,0 +1,51 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +__pycache__/* +*.pyc + +# Build specific files +build*/ +_build*/ +install/ +vs-build/ + +# OS and IDE specific files +.DS_Store +.vscode +.atom +.fortls +# backup files +*.asv +~$*.xlsx + +# LaTeX compiling files +*.aux +*.nlo +*.log diff --git a/OpenFAST/.gitmodules b/OpenFAST/.gitmodules new file mode 100644 index 000000000..9650d9f06 --- /dev/null +++ b/OpenFAST/.gitmodules @@ -0,0 +1,6 @@ +[submodule "reg_tests/r-test"] + path = reg_tests/r-test + url = https://github.com/OpenFAST/r-test.git +[submodule "unit_tests/pfunit"] + path = unit_tests/pfunit + url = https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git diff --git a/OpenFAST/.readthedocs.yml b/OpenFAST/.readthedocs.yml new file mode 100644 index 000000000..2a5338b5c --- /dev/null +++ b/OpenFAST/.readthedocs.yml @@ -0,0 +1,26 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +formats: + - htmlzip + - pdf + # - epub + +python: + version: 3.7 + install: + - requirements: docs/requirements.txt + system_packages: true + +# select the docker image to use: stable | latest +build: + image: stable + +sphinx: + builder: html + configuration: docs/conf.py + fail_on_warning: true diff --git a/OpenFAST/CMakeLists.txt b/OpenFAST/CMakeLists.txt new file mode 100644 index 000000000..e98907948 --- /dev/null +++ b/OpenFAST/CMakeLists.txt @@ -0,0 +1,173 @@ +# +# Copyright 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. +# + +cmake_minimum_required(VERSION 2.8.12) +project(OpenFAST CXX C Fortran) + +include(${CMAKE_SOURCE_DIR}/cmake/OpenfastCmakeUtils.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/OpenfastFortranOptions.cmake) + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +# CMake Configuration variables +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING + "Choose the build type: Debug Release" FORCE) +endif (NOT CMAKE_BUILD_TYPE) + +option(GENERATE_TYPES "Use the openfast-regsitry to autogenerate types modules" off) +option(BUILD_SHARED_LIBS "Enable building shared libraries" off) +option(DOUBLE_PRECISION "Treat REAL as double precision" on) +option(USE_DLL_INTERFACE "Enable runtime loading of dynamic libraries" on) +option(FPE_TRAP_ENABLED "Enable FPE trap in compiler options" off) +option(ORCA_DLL_LOAD "Enable OrcaFlex Library Load" on) +option(BUILD_OPENFAST_CPP_API "Enable building OpenFAST - C++ API" off) +option(OPENMP "Enable OpenMP support" off) + +# Precompiler/preprocessor flag configuration +# Do this before configuring modules so that the flags are included +option(BUILD_TESTING "Build the testing tree." OFF) +if(BUILD_TESTING) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DUNIT_TEST") +endif() +option(BUILD_OPENFAST_SIMULINK_API "Enable building OpenFAST for use with Simulink" off) +if(BUILD_OPENFAST_SIMULINK_API) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DCOMPILE_SIMULINK") +endif() + +# Setup Fortran Compiler options based on architecture/compiler +set_fast_fortran() + +if (USE_DLL_INTERFACE) + add_definitions(-DUSE_DLL_INTERFACE) +endif (USE_DLL_INTERFACE) + +if (FPE_TRAP_ENABLED) + add_definitions(-DFPE_TRAP_ENABLED) +endif (FPE_TRAP_ENABLED) + +# Setup dependencies +if (CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") + find_package(MKL) +endif() +if (MKL_FOUND) + include_directories(${MKL_INCLUDE_DIRS}) + set(BLAS_LIBRARIES ${MKL_LIBRARIES}) + set(LAPACK_LIBRARIES ${MKL_LIBRARIES}) + set(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "ifport;ifcore;imf;svml;m;ipgo;intlc;c;irc_s;dl;c") +else() + find_package(BLAS REQUIRED) + find_package(LAPACK REQUIRED) +endif() + +######################################################################## +# Build rules for OpenFAST Registry +# +if(GENERATE_TYPES) + add_subdirectory(modules/openfast-registry) +endif() + +######################################################################## +# OpenFAST modules +# +set(OPENFAST_MODULES + nwtc-library + inflowwind + aerodyn + aerodyn14 + servodyn + elastodyn + beamdyn + subdyn + hydrodyn + orcaflex-interface + extptfm + openfoam + supercontroller + turbsim + openfast-library + version + feamooring + moordyn + icedyn + icefloe + map +) + +set(OPENFAST_REGISTRY_INCLUDES "" CACHE INTERNAL "Registry includes paths") +set_registry_includes("modules" ${OPENFAST_MODULES}) +# Fix non-standard path addition to OPENFAST_REGISTRY_INCLUDES in icefloe module +set(OPENFAST_REGISTRY_INCLUDES + ${OPENFAST_REGISTRY_INCLUDES} -I ${CMAKE_SOURCE_DIR}/modules/icefloe/src/interfaces/FAST/ + CACHE INTERNAL "Registry includes paths") + +foreach(IDIR IN ITEMS ${OPENFAST_MODULES}) + add_subdirectory("${CMAKE_SOURCE_DIR}/modules/${IDIR}") +endforeach(IDIR IN ITEMS ${OPENFAST_MODULES}) + +add_subdirectory(glue-codes) + +# Install fortran .mod files also to installation directory +install(CODE + "EXECUTE_PROCESS (COMMAND \"${CMAKE_COMMAND}\" -E copy_directory \"${CMAKE_Fortran_MODULE_DIRECTORY}\" \"${CMAKE_INSTALL_PREFIX}/include/openfast/\")") + +# Install the library dependency information +install(EXPORT OpenFASTLibraries + DESTINATION lib/cmake/OpenFAST + FILE OpenFASTLibraries.cmake) + +# Create OpenFAST config so that other codes can find OpenFAST +include(CMakePackageConfigHelpers) + +set(INCLUDE_INSTALL_DIR include/) +set(LIB_INSTALL_DIR lib/) +set(FTNMOD_INSTALL_DIR include/openfast/) +if (BUILD_OPENFAST_CPP_API) + set(OpenFAST_HAS_CXX_API TRUE) +else() + set(OpenFAST_HAS_CXX_API FALSE) +endif() + +configure_package_config_file( + cmake/OpenFASTConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/OpenFASTConfig.cmake + INSTALL_DESTINATION lib/cmake/OpenFAST + PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR FTNMOD_INSTALL_DIR) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/OpenFASTConfig.cmake + DESTINATION lib/cmake/OpenFAST) + +######################################################################## +# Configure the default install path to openfast/install +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH + "OpenFAST install directory" FORCE) +endif() + +# Option configuration +if(BUILD_TESTING) + include(CTest) + + # regression tests + add_subdirectory(reg_tests) + + # unit tests + add_subdirectory(unit_tests) +endif() + +option(BUILD_DOCUMENTATION "Build documentation." OFF) +if(BUILD_DOCUMENTATION) + add_subdirectory(docs) +endif() diff --git a/OpenFAST/LICENSE b/OpenFAST/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/OpenFAST/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/OpenFAST/README.rst b/OpenFAST/README.rst new file mode 100644 index 000000000..76e3affe4 --- /dev/null +++ b/OpenFAST/README.rst @@ -0,0 +1,142 @@ +OpenFAST +======== + +|actions| |nbsp| |rtfd| + +.. |actions| image:: https://github.com/openfast/openfast/workflows/OpenFAST%20Build%20and%20Test/badge.svg?branch=dev + :target: https://github.com/OpenFAST/openfast/actions?query=workflow%3A%22OpenFAST+Build+and+Test%22 + :alt: Build Status +.. |rtfd| image:: https://readthedocs.org/projects/openfast/badge/?version=dev + :target: https://openfast.readthedocs.io/en/dev + :alt: Documentation Status +.. |nbsp| unicode:: 0xA0 + :trim: + +OpenFAST is a wind turbine simulation tool which builds on FAST v8. It was +created with the goal of being a community model developed and used by research +laboratories, academia, and industry. It is managed by a dedicated team at the +National Renewable Energy Lab. Our objective is to ensure that OpenFAST is +sustainable software that is well tested and well documented. If you'd like +to contribute, see the `Developer Documentation `_ +and any open GitHub issues with the +`Help Wanted `_ +tag. + +**OpenFAST is under active development**. + +FAST v8 - OpenFAST v0.1.0 +------------------------- +The transition from FAST v8 to OpenFAST v0.1.0 represents the effort to better +support an open-source developer community around FAST-based aero-hydro-servo- +elastic engineering models of wind-turbines and wind-plants. OpenFAST is the +next generation of FAST analysis tools. More information is available in the +`transition notes `_. + +FAST v8 is a computer-aided engineering tool for simulating the coupled dynamic +response of wind turbines. FAST joins aerodynamics models, hydrodynamics models +for offshore structures, control and electrical system (servo) dynamics models, +and structural (elastic) dynamics models to enable coupled nonlinear aero- +hydro-servo-elastic simulation in the time domain. The FAST tool enables the +analysis of a range of wind turbine configurations, including two- or +three-blade horizontal-axis rotor, pitch or stall regulation, rigid or +teetering hub, upwind or downwind rotor, and lattice or tubular tower. The wind +turbine can be modeled on land or offshore on fixed-bottom or floating +substructures. FAST is based on advanced engineering models derived from +fundamental laws, but with appropriate simplifications and assumptions, and +supplemented where applicable with computational solutions and test data. + +The aerodynamic models use wind-inflow data and solve for the rotor-wake +effects and blade-element aerodynamic loads, including dynamic stall. The +hydrodynamics models simulate the regular or irregular incident waves and +currents and solve for the hydrostatic, radiation, diffraction, and viscous +loads on the offshore substructure. The control and electrical system models +simulate the controller logic, sensors, and actuators of the blade-pitch, +generator-torque, nacelle-yaw, and other control devices, as well as the +generator and power-converter components of the electrical drive. The +structural-dynamics models apply the control and electrical system +reactions, apply the aerodynamic and hydrodynamic loads, adds gravitational +loads, and simulate the elasticity of the rotor, drivetrain, and support +structure. Coupling between all models is achieved through a modular +interface and coupler. + +Documentation +------------- +The full documentation is available at http://openfast.readthedocs.io/. + +This documentation is stored and maintained alongside the source code. +It is compiled into HTML with Sphinx and is tied to a particular version +of OpenFAST. `Readthedocs `_ hosts the following +versions of the documentation: + +* ``latest`` - The latest commit on the ``master`` branch +* ``stable`` - Corresponds to the last tagged release +* ``dev`` - The latest commit on the ``dev`` branch + +These can be toggled with the ``v: latest`` button in the lower left corner of +the docs site. + +Obtaining OpenFAST +------------------ +OpenFAST is hosted entirely on GitHub so you are in the `right place `_! +The repository is structured with two branches following the +"git-flow" convention: + +* ``master`` +* ``dev`` + +The ``master`` branch is stable, well tested, and represents the most up to +date released version of OpenFAST. The latest commit on ``master`` contains +a tag with version info and brief release notes. The tag history can be +obtained with the ``git tag`` command and viewed in more detail on +`GitHub Releases `_. For general +use, the ``master`` branch is highly recommended. + +The ``dev`` branch is generally stable and tested, but not static. It contains +new features, bug fixes, and documentation updates that have not been compiled +into a production release. Before proceeding with new development, it is +recommended to explore the ``dev`` branch. This branch is updated regularly +through pull requests, so be sure to ``git fetch`` often and check +`outstanding pull requests `_. + +For those not familiar with git and GitHub, there are many resources: + +* https://guides.github.com +* https://try.github.io +* https://help.github.com/categories/bootcamp/ +* https://desktop.github.com/ +* http://nvie.com/posts/a-successful-git-branching-model/ + +Compilation, Usage, and Development +----------------------------------- +Details for compiling +`compiling `_, +`using `_, and +`developing `_ +OpenFAST on Unix-based and Windows machines are available at `readthedocs `_. + +Help +---- +Please use `GitHub Issues `_ to: + +* ask usage questions +* report bugs +* request code enhancements + +For other questions regarding OpenFAST, please contact +`Mike Sprague `_. + +Users and developers may also be interested in the NREL National Wind +Technology Center (NWTC) `phpBB Forum `_. + +Acknowledgments +--------------- + +OpenFAST is maintained and developed by researchers and software engineers at +the `National Renewable Energy Laboratory `_ (NREL), with +support from the US Department of Energy's Wind Energy Technology Office. NREL +gratefully acknowledges development contributions from the following +organizations: + +* Envision Energy USA, Ltd +* Brigham Young University +* `Intel® Parallel Computing Center (IPCC) `_ diff --git a/OpenFAST/cmake/FindMKL.cmake b/OpenFAST/cmake/FindMKL.cmake new file mode 100644 index 000000000..90a192fe6 --- /dev/null +++ b/OpenFAST/cmake/FindMKL.cmake @@ -0,0 +1,73 @@ +# +# Copyright 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. +# + +# find_path(MKL_INCLUDE_DIRS +# mkl.h +# HINTS $ENV{MKLROOT} +# PATH_SUFFIXES include) + +# infer the architecture build type +# https://cmake.org/cmake/help/v3.0/variable/CMAKE_SIZEOF_VOID_P.html +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(ARCHDIR "ia32") + set(WINDOWS_INTERFACE "_c_") + set(UNIX_INTERFACE "") +elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set(ARCHDIR "intel64") + set(WINDOWS_INTERFACE "_lp64_") + set(UNIX_INTERFACE "_lp64") +endif() + +set(MKLSEARCHPATHS + $ENV{MKLROOT}/lib/${ARCHDIR}_win + $ENV{MKLROOT}/lib/${ARCHDIR} + $ENV{MKLROOT}/lib +) + +# using mkl_intel_c on windows since that is the default for intel compilers +# https://software.intel.com/en-us/mkl-windows-developer-guide-using-the-cdecl-and-stdcall-interfaces +find_library(MKL_IFACE_LIB + NAMES mkl_intel${UNIX_INTERFACE} libmkl_intel${UNIX_INTERFACE} mkl_intel${WINDOWS_INTERFACE}dll + PATHS ${MKLSEARCHPATHS} + NO_DEFAULT_PATH) + +find_library(MKL_SEQ_LIB + NAMES mkl_sequential libmkl_sequential mkl_sequential_dll + PATHS ${MKLSEARCHPATHS} + NO_DEFAULT_PATH) + +find_library(MKL_CORE_LIB + NAMES mkl_core libmkl_core mkl_core_dll + PATHS ${MKLSEARCHPATHS} + NO_DEFAULT_PATH) + +find_library(MKL_DEF_LIB + NAMES mkl_def libmkl_def mkl_def_dll + PATHS ${MKLSEARCHPATHS} + NO_DEFAULT_PATH) + +if (MKL_IFACE_LIB AND MKL_SEQ_LIB AND MKL_CORE_LIB AND MKL_DEF_LIB) + set(MKL_LIBRARIES ${MKL_IFACE_LIB} ${MKL_SEQ_LIB} ${MKL_CORE_LIB} ${MKL_DEF_LIB}) +else() + set(MKL_LIBRARIES "") + set(MKL_INCLUDE_DIRS "") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MKL DEFAULT_MSG + MKL_LIBRARIES MKL_IFACE_LIB MKL_SEQ_LIB MKL_CORE_LIB MKL_DEF_LIB) # MKL_INCLUDE_DIRS) +mark_as_advanced( + MKL_INCLUDE_DIRS MKL_LIBRARIES MKL_IFACE_LIB MKL_SEQ_LIB MKL_CORE_LIB MKL_DEF_LIB) diff --git a/OpenFAST/cmake/FindMatlab.cmake b/OpenFAST/cmake/FindMatlab.cmake new file mode 100644 index 000000000..3180b470f --- /dev/null +++ b/OpenFAST/cmake/FindMatlab.cmake @@ -0,0 +1,1715 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindMatlab +# ---------- +# +# Finds Matlab or Matlab Compiler Runtime (MCR) and provides Matlab tools, +# libraries and compilers to CMake. +# +# This package primary purpose is to find the libraries associated with Matlab +# or the MCR in order to be able to build Matlab extensions (mex files). It +# can also be used: +# +# * to run specific commands in Matlab in case Matlab is available +# * for declaring Matlab unit test +# * to retrieve various information from Matlab (mex extensions, versions and +# release queries, ...) +# +# The module supports the following components: +# +# * ``MX_LIBRARY``, ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``MX``, +# ``ENG`` and ``MAT`` libraries of Matlab +# * ``MAIN_PROGRAM`` the Matlab binary program. Note that this component is not +# available on the MCR version, and will yield an error if the MCR is found +# instead of the regular Matlab installation. +# * ``MEX_COMPILER`` the MEX compiler. +# * ``MCC_COMPILER`` the MCC compiler, included with the Matlab Compiler add-on. +# * ``SIMULINK`` the Simulink environment. +# +# .. note:: +# +# The version given to the :command:`find_package` directive is the Matlab +# **version**, which should not be confused with the Matlab *release* name +# (eg. `R2014`). +# The :command:`matlab_get_version_from_release_name` and +# :command:`matlab_get_release_name_from_version` provide a mapping +# between the release name and the version. +# +# The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give +# the path of the desired Matlab version. Otherwise, the behaviour is platform +# specific: +# +# * Windows: The installed versions of Matlab/MCR are retrieved from the +# Windows registry +# * OS X: The installed versions of Matlab/MCR are given by the MATLAB +# default installation paths in ``/Application``. If no such application is +# found, it falls back to the one that might be accessible from the ``PATH``. +# * Unix: The desired Matlab should be accessible from the ``PATH``. This does +# not work for MCR installation and :variable:`Matlab_ROOT_DIR` should be +# specified on this platform. +# +# Additional information is provided when :variable:`MATLAB_FIND_DEBUG` is set. +# When a Matlab/MCR installation is found automatically and the ``MATLAB_VERSION`` +# is not given, the version is queried from Matlab directly (on Windows this +# may pop up a Matlab window) or from the MCR installation. +# +# The mapping of the release names and the version of Matlab is performed by +# defining pairs (name, version). The variable +# :variable:`MATLAB_ADDITIONAL_VERSIONS` may be provided before the call to +# the :command:`find_package` in order to handle additional versions. +# +# A Matlab scripts can be added to the set of tests using the +# :command:`matlab_add_unit_test`. By default, the Matlab unit test framework +# will be used (>= 2013a) to run this script, but regular ``.m`` files +# returning an exit code can be used as well (0 indicating a success). +# +# Module Input Variables +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# Users or projects may set the following variables to configure the module +# behaviour: +# +# :variable:`Matlab_ROOT_DIR` +# the root of the Matlab installation. +# :variable:`MATLAB_FIND_DEBUG` +# outputs debug information +# :variable:`MATLAB_ADDITIONAL_VERSIONS` +# additional versions of Matlab for the automatic retrieval of the installed +# versions. +# +# Variables defined by the module +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# Result variables +# """""""""""""""" +# +# ``Matlab_FOUND`` +# ``TRUE`` if the Matlab installation is found, ``FALSE`` +# otherwise. All variable below are defined if Matlab is found. +# ``Matlab_ROOT_DIR`` +# the final root of the Matlab installation determined by the FindMatlab +# module. +# ``Matlab_MAIN_PROGRAM`` +# the Matlab binary program. Available only if the component ``MAIN_PROGRAM`` +# is given in the :command:`find_package` directive. +# ``Matlab_INCLUDE_DIRS`` +# the path of the Matlab libraries headers +# ``Matlab_MEX_LIBRARY`` +# library for mex, always available. +# ``Matlab_MX_LIBRARY`` +# mx library of Matlab (arrays). Available only if the component +# ``MX_LIBRARY`` has been requested. +# ``Matlab_ENG_LIBRARY`` +# Matlab engine library. Available only if the component ``ENG_LIBRARY`` +# is requested. +# ``Matlab_MAT_LIBRARY`` +# Matlab matrix library. Available only if the component ``MAT_LIBRARY`` +# is requested. +# ``Matlab_LIBRARIES`` +# the whole set of libraries of Matlab +# ``Matlab_MEX_COMPILER`` +# the mex compiler of Matlab. Currently not used. +# Available only if the component ``MEX_COMPILER`` is requested. +# ``Matlab_MCC_COMPILER`` +# the mcc compiler of Matlab. Included with the Matlab Compiler add-on. +# Available only if the component ``MCC_COMPILER`` is requested. +# +# Cached variables +# """""""""""""""" +# +# ``Matlab_MEX_EXTENSION`` +# the extension of the mex files for the current platform (given by Matlab). +# ``Matlab_ROOT_DIR`` +# the location of the root of the Matlab installation found. If this value +# is changed by the user, the result variables are recomputed. +# +# Provided macros +# ^^^^^^^^^^^^^^^ +# +# :command:`matlab_get_version_from_release_name` +# returns the version from the release name +# :command:`matlab_get_release_name_from_version` +# returns the release name from the Matlab version +# +# Provided functions +# ^^^^^^^^^^^^^^^^^^ +# +# :command:`matlab_add_mex` +# adds a target compiling a MEX file. +# :command:`matlab_add_unit_test` +# adds a Matlab unit test file as a test to the project. +# :command:`matlab_extract_all_installed_versions_from_registry` +# parses the registry for all Matlab versions. Available on Windows only. +# The part of the registry parsed is dependent on the host processor +# :command:`matlab_get_all_valid_matlab_roots_from_registry` +# returns all the possible Matlab or MCR paths, according to a previously +# given list. Only the existing/accessible paths are kept. This is mainly +# useful for the searching all possible Matlab installation. +# :command:`matlab_get_mex_suffix` +# returns the suffix to be used for the mex files +# (platform/architecture dependent) +# :command:`matlab_get_version_from_matlab_run` +# returns the version of Matlab/MCR, given the full directory of the Matlab/MCR +# installation path. +# +# +# Known issues +# ^^^^^^^^^^^^ +# +# **Symbol clash in a MEX target** +# By default, every symbols inside a MEX +# file defined with the command :command:`matlab_add_mex` have hidden +# visibility, except for the entry point. This is the default behaviour of +# the MEX compiler, which lowers the risk of symbol collision between the +# libraries shipped with Matlab, and the libraries to which the MEX file is +# linking to. This is also the default on Windows platforms. +# +# However, this is not sufficient in certain case, where for instance your +# MEX file is linking against libraries that are already loaded by Matlab, +# even if those libraries have different SONAMES. +# A possible solution is to hide the symbols of the libraries to which the +# MEX target is linking to. This can be achieved in GNU GCC compilers with +# the linker option ``-Wl,--exclude-libs,ALL``. +# +# **Tests using GPU resources** +# in case your MEX file is using the GPU and +# in order to be able to run unit tests on this MEX file, the GPU resources +# should be properly released by Matlab. A possible solution is to make +# Matlab aware of the use of the GPU resources in the session, which can be +# performed by a command such as ``D = gpuDevice()`` at the beginning of +# the test script (or via a fixture). +# +# +# Reference +# ^^^^^^^^^ +# +# .. variable:: Matlab_ROOT_DIR +# +# The root folder of the Matlab installation. If set before the call to +# :command:`find_package`, the module will look for the components in that +# path. If not set, then an automatic search of Matlab +# will be performed. If set, it should point to a valid version of Matlab. +# +# .. variable:: MATLAB_FIND_DEBUG +# +# If set, the lookup of Matlab and the intermediate configuration steps are +# outputted to the console. +# +# .. variable:: MATLAB_ADDITIONAL_VERSIONS +# +# If set, specifies additional versions of Matlab that may be looked for. +# The variable should be a list of strings, organised by pairs of release +# name and versions, such as follows:: +# +# set(MATLAB_ADDITIONAL_VERSIONS +# "release_name1=corresponding_version1" +# "release_name2=corresponding_version2" +# ... +# ) +# +# Example:: +# +# set(MATLAB_ADDITIONAL_VERSIONS +# "R2013b=8.2" +# "R2013a=8.1" +# "R2012b=8.0") +# +# The order of entries in this list matters when several versions of +# Matlab are installed. The priority is set according to the ordering in +# this list. + +set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}") + +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) + + +# The currently supported versions. Other version can be added by the user by +# providing MATLAB_ADDITIONAL_VERSIONS +if(NOT MATLAB_ADDITIONAL_VERSIONS) + set(MATLAB_ADDITIONAL_VERSIONS) +endif() + +set(MATLAB_VERSIONS_MAPPING + "R2018a=9.4" + "R2017b=9.3" + "R2017a=9.2" + "R2016b=9.1" + "R2016a=9.0" + "R2015b=8.6" + "R2015a=8.5" + "R2014b=8.4" + "R2014a=8.3" + "R2013b=8.2" + "R2013a=8.1" + "R2012b=8.0" + "R2012a=7.14" + "R2011b=7.13" + "R2011a=7.12" + "R2010b=7.11" + + ${MATLAB_ADDITIONAL_VERSIONS} + ) + + +# temporary folder for all Matlab runs +set(_matlab_temporary_folder ${CMAKE_BINARY_DIR}/Matlab) + +if(NOT EXISTS "${_matlab_temporary_folder}") + file(MAKE_DIRECTORY "${_matlab_temporary_folder}") +endif() + +#.rst: +# .. command:: matlab_get_version_from_release_name +# +# Returns the version of Matlab (17.58) from a release name (R2017k) +macro(matlab_get_version_from_release_name release_name version_name) + + string(REGEX MATCHALL "${release_name}=([0-9]+\\.?[0-9]*)" _matched ${MATLAB_VERSIONS_MAPPING}) + + set(${version_name} "") + if(NOT _matched STREQUAL "") + set(${version_name} ${CMAKE_MATCH_1}) + else() + message(WARNING "[MATLAB] The release name ${release_name} is not registered") + endif() + unset(_matched) + +endmacro() + + + + + +#.rst: +# .. command:: matlab_get_release_name_from_version +# +# Returns the release name (R2017k) from the version of Matlab (17.58) +macro(matlab_get_release_name_from_version version release_name) + + set(${release_name} "") + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=${version}" _matched ${_var}) + if(NOT _matched STREQUAL "") + set(${release_name} ${CMAKE_MATCH_1}) + break() + endif() + endforeach(_var) + + unset(_var) + unset(_matched) + if(${release_name} STREQUAL "") + message(WARNING "[MATLAB] The version ${version} is not registered") + endif() + +endmacro() + + + + + +# extracts all the supported release names (R2017k...) of Matlab +# internal use +macro(matlab_get_supported_releases list_releases) + set(${list_releases}) + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=([0-9]+\\.?[0-9]*)" _matched ${_var}) + if(NOT _matched STREQUAL "") + list(APPEND ${list_releases} ${CMAKE_MATCH_1}) + endif() + unset(_matched) + unset(CMAKE_MATCH_1) + endforeach(_var) + unset(_var) +endmacro() + + + +# extracts all the supported versions of Matlab +# internal use +macro(matlab_get_supported_versions list_versions) + set(${list_versions}) + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=([0-9]+\\.?[0-9]*)" _matched ${_var}) + if(NOT _matched STREQUAL "") + list(APPEND ${list_versions} ${CMAKE_MATCH_2}) + endif() + unset(_matched) + unset(CMAKE_MATCH_1) + endforeach(_var) + unset(_var) +endmacro() + + +#.rst: +# .. command:: matlab_extract_all_installed_versions_from_registry +# +# This function parses the registry and founds the Matlab versions that are +# installed. The found versions are returned in `matlab_versions`. +# Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for +# The returned list contains all versions under +# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` and +# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB Runtime`` or an empty list in case an +# error occurred (or nothing found). +# +# .. note:: +# +# Only the versions are provided. No check is made over the existence of the +# installation referenced in the registry, +# +function(matlab_extract_all_installed_versions_from_registry win64 matlab_versions) + + if(NOT CMAKE_HOST_WIN32) + message(FATAL_ERROR "[MATLAB] This macro can only be called by a windows host (call to reg.exe)") + endif() + + if(${win64} AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64") + set(APPEND_REG "/reg:64") + else() + set(APPEND_REG "/reg:32") + endif() + + set(matlabs_from_registry) + + foreach(_installation_type IN ITEMS "MATLAB" "MATLAB Runtime") + + # /reg:64 should be added on 64 bits capable OSs in order to enable the + # redirection of 64 bits applications + execute_process( + COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\${_installation_type} /f * /k ${APPEND_REG} + RESULT_VARIABLE resultMatlab + OUTPUT_VARIABLE varMatlab + ERROR_VARIABLE errMatlab + INPUT_FILE NUL + ) + + + if(${resultMatlab} EQUAL 0) + + string( + REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)" + matlab_versions_regex ${varMatlab}) + + foreach(match IN LISTS matlab_versions_regex) + string( + REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)" + current_match ${match}) + + set(_matlab_current_version ${CMAKE_MATCH_1}) + set(current_matlab_version_major ${CMAKE_MATCH_2}) + set(current_matlab_version_minor ${CMAKE_MATCH_4}) + if(NOT current_matlab_version_minor) + set(current_matlab_version_minor "0") + endif() + + list(APPEND matlabs_from_registry ${_matlab_current_version}) + unset(_matlab_current_version) + endforeach() + + endif() + endforeach() + + if(matlabs_from_registry) + list(REMOVE_DUPLICATES matlabs_from_registry) + list(SORT matlabs_from_registry) + list(REVERSE matlabs_from_registry) + endif() + + set(${matlab_versions} ${matlabs_from_registry} PARENT_SCOPE) + +endfunction() + + + +# (internal) +macro(extract_matlab_versions_from_registry_brute_force matlab_versions) + # get the supported versions + set(matlab_supported_versions) + matlab_get_supported_versions(matlab_supported_versions) + + + # this is a manual population of the versions we want to look for + # this can be done as is, but preferably with the call to + # matlab_get_supported_versions and variable + + # populating the versions we want to look for + # set(matlab_supported_versions) + + # # Matlab 7 + # set(matlab_major 7) + # foreach(current_matlab_minor RANGE 4 20) + # list(APPEND matlab_supported_versions "${matlab_major}.${current_matlab_minor}") + # endforeach(current_matlab_minor) + + # # Matlab 8 + # set(matlab_major 8) + # foreach(current_matlab_minor RANGE 0 5) + # list(APPEND matlab_supported_versions "${matlab_major}.${current_matlab_minor}") + # endforeach(current_matlab_minor) + + # # taking into account the possible additional versions provided by the user + # if(DEFINED MATLAB_ADDITIONAL_VERSIONS) + # list(APPEND matlab_supported_versions MATLAB_ADDITIONAL_VERSIONS) + # endif() + + # we order from more recent to older + if(matlab_supported_versions) + list(REMOVE_DUPLICATES matlab_supported_versions) + list(SORT matlab_supported_versions) + list(REVERSE matlab_supported_versions) + endif() + + set(${matlab_versions} ${matlab_supported_versions}) +endmacro() + + + + +#.rst: +# .. command:: matlab_get_all_valid_matlab_roots_from_registry +# +# Populates the Matlab root with valid versions of Matlab or +# Matlab Runtime (MCR). +# The returned matlab_roots is organized in triplets +# ``(type,version_number,matlab_root_path)``, where ``type`` +# indicates either ``MATLAB`` or ``MCR``. +# +# :: +# +# matlab_get_all_valid_matlab_roots_from_registry( +# matlab_versions +# matlab_roots) +# +# ``matlab_versions`` +# the versions of each of the Matlab or MCR installations +# ``matlab_roots`` +# the location of each of the Matlab or MCR installations +function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_roots) + + # The matlab_versions comes either from + # extract_matlab_versions_from_registry_brute_force or + # matlab_extract_all_installed_versions_from_registry. + + set(_matlab_roots_list ) + # check for Matlab installations + foreach(_matlab_current_version ${matlab_versions}) + get_filename_component( + current_MATLAB_ROOT + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${_matlab_current_version};MATLABROOT]" + ABSOLUTE) + + if(EXISTS ${current_MATLAB_ROOT}) + list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT}) + endif() + + endforeach() + + # Check for MCR installations + foreach(_matlab_current_version ${matlab_versions}) + get_filename_component( + current_MATLAB_ROOT + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Runtime\\${_matlab_current_version};MATLABROOT]" + ABSOLUTE) + + # remove the dot + string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}") + + if(EXISTS ${current_MATLAB_ROOT}) + list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}") + endif() + + endforeach() + set(${matlab_roots} ${_matlab_roots_list} PARENT_SCOPE) +endfunction() + +#.rst: +# .. command:: matlab_get_mex_suffix +# +# Returns the extension of the mex files (the suffixes). +# This function should not be called before the appropriate Matlab root has +# been found. +# +# :: +# +# matlab_get_mex_suffix( +# matlab_root +# mex_suffix) +# +# ``matlab_root`` +# the root of the Matlab/MCR installation +# ``mex_suffix`` +# the variable name in which the suffix will be returned. +function(matlab_get_mex_suffix matlab_root mex_suffix) + + # todo setup the extension properly. Currently I do not know if this is + # sufficient for all win32 distributions. + # there is also CMAKE_EXECUTABLE_SUFFIX that could be tweaked + set(mexext_suffix "") + if(WIN32) + list(APPEND mexext_suffix ".bat") + endif() + + # we first try without suffix, since cmake does not understand a list with + # one empty string element + find_program( + Matlab_MEXEXTENSIONS_PROG + NAMES mexext + PATHS ${matlab_root}/bin + DOC "Matlab MEX extension provider" + NO_DEFAULT_PATH + ) + + foreach(current_mexext_suffix IN LISTS mexext_suffix) + if(NOT DEFINED Matlab_MEXEXTENSIONS_PROG OR NOT Matlab_MEXEXTENSIONS_PROG) + # this call should populate the cache automatically + find_program( + Matlab_MEXEXTENSIONS_PROG + "mexext${current_mexext_suffix}" + PATHS ${matlab_root}/bin + DOC "Matlab MEX extension provider" + NO_DEFAULT_PATH + ) + endif() + endforeach(current_mexext_suffix) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Determining mex files extensions from '${matlab_root}/bin' with program '${Matlab_MEXEXTENSIONS_PROG}'") + endif() + + # the program has been found? + if((NOT Matlab_MEXEXTENSIONS_PROG) OR (NOT EXISTS ${Matlab_MEXEXTENSIONS_PROG})) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot found mexext program. Matlab root is ${matlab_root}") + endif() + unset(Matlab_MEXEXTENSIONS_PROG CACHE) + return() + endif() + + set(_matlab_mex_extension) + + set(devnull) + if(UNIX) + set(devnull INPUT_FILE /dev/null) + elseif(WIN32) + set(devnull INPUT_FILE NUL) + endif() + + # this is the preferred way. If this does not work properly (eg. MCR on Windows), then we use our own knowledge + execute_process( + COMMAND ${Matlab_MEXEXTENSIONS_PROG} + OUTPUT_VARIABLE _matlab_mex_extension + #RESULT_VARIABLE _matlab_mex_extension_call + ERROR_VARIABLE _matlab_mex_extension_error + ${devnull}) + + if(NOT "${_matlab_mex_extension_error}" STREQUAL "") + if(WIN32) + # this is only for intel architecture + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_matlab_mex_extension "mexw64") + else() + set(_matlab_mex_extension "mexw32") + endif() + endif() + endif() + + string(STRIP "${_matlab_mex_extension}" _matlab_mex_extension) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : returned '${_matlab_mex_extension_call}', determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'") + endif() + + unset(Matlab_MEXEXTENSIONS_PROG CACHE) + set(${mex_suffix} ${_matlab_mex_extension} PARENT_SCOPE) +endfunction() + + + + +#.rst: +# .. command:: matlab_get_version_from_matlab_run +# +# This function runs Matlab program specified on arguments and extracts its +# version. If the path provided for the Matlab installation points to an MCR +# installation, the version is extracted from the installed files. +# +# :: +# +# matlab_get_version_from_matlab_run( +# matlab_binary_path +# matlab_list_versions) +# +# ``matlab_binary_path`` +# the location of the `matlab` binary executable +# ``matlab_list_versions`` +# the version extracted from Matlab +function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_versions) + + set(${matlab_list_versions} "" PARENT_SCOPE) + + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Determining the version of Matlab from ${matlab_binary_program}") + endif() + + if(EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Removing previous ${_matlab_temporary_folder}/matlabVersionLog.cmaketmp file") + endif() + file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + endif() + + + # the log file is needed since on windows the command executes in a new + # window and it is not possible to get back the answer of Matlab + # the -wait command is needed on windows, otherwise the call returns + # immediately after the program launches itself. + if(WIN32) + set(_matlab_additional_commands "-wait") + endif() + + set(devnull) + if(UNIX) + set(devnull INPUT_FILE /dev/null) + elseif(WIN32) + set(devnull INPUT_FILE NUL) + endif() + + # timeout set to 120 seconds, in case it does not start + # note as said before OUTPUT_VARIABLE cannot be used in a platform + # independent manner however, not setting it would flush the output of Matlab + # in the current console (unix variant) + execute_process( + COMMAND "${matlab_binary_program}" -nosplash -nojvm ${_matlab_additional_commands} -logfile "matlabVersionLog.cmaketmp" -nodesktop -nodisplay -r "version, exit" + OUTPUT_VARIABLE _matlab_version_from_cmd_dummy + RESULT_VARIABLE _matlab_result_version_call + ERROR_VARIABLE _matlab_result_version_call_error + TIMEOUT 120 + WORKING_DIRECTORY "${_matlab_temporary_folder}" + ${devnull} + ) + + if("${_matlab_result_version_call}" MATCHES "timeout") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab." + " Matlab call timed out after 120 seconds.") + endif() + return() + endif() + + if(${_matlab_result_version_call}) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call returned with error ${_matlab_result_version_call}.") + endif() + return() + elseif(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") + endif() + return() + endif() + + # if successful, read back the log + file(READ "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp" _matlab_version_from_cmd) + file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + + set(index -1) + string(FIND ${_matlab_version_from_cmd} "ans" index) + if(index EQUAL -1) + + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot find the version of Matlab returned by the run.") + endif() + + else() + set(matlab_list_of_all_versions_tmp) + + string(SUBSTRING ${_matlab_version_from_cmd} ${index} -1 substring_ans) + string( + REGEX MATCHALL "ans[\r\n\t ]*=[\r\n\t ]*'?([0-9]+(\\.[0-9]+)?)" + matlab_versions_regex + ${substring_ans}) + foreach(match IN LISTS matlab_versions_regex) + string( + REGEX MATCH "ans[\r\n\t ]*=[\r\n\t ]*'?(([0-9]+)(\\.([0-9]+))?)" + current_match ${match}) + + list(APPEND matlab_list_of_all_versions_tmp ${CMAKE_MATCH_1}) + endforeach() + if(matlab_list_of_all_versions_tmp) + list(REMOVE_DUPLICATES matlab_list_of_all_versions_tmp) + endif() + set(${matlab_list_versions} ${matlab_list_of_all_versions_tmp} PARENT_SCOPE) + + endif() + +endfunction() + +#.rst: +# .. command:: matlab_add_unit_test +# +# Adds a Matlab unit test to the test set of cmake/ctest. +# This command requires the component ``MAIN_PROGRAM`` and hence is not +# available for an MCR installation. +# +# The unit test uses the Matlab unittest framework (default, available +# starting Matlab 2013b+) except if the option ``NO_UNITTEST_FRAMEWORK`` +# is given. +# +# The function expects one Matlab test script file to be given. +# In the case ``NO_UNITTEST_FRAMEWORK`` is given, the unittest script file +# should contain the script to be run, plus an exit command with the exit +# value. This exit value will be passed to the ctest framework (0 success, +# non 0 failure). Additional arguments accepted by :command:`add_test` can be +# passed through ``TEST_ARGS`` (eg. ``CONFIGURATION ...``). +# +# :: +# +# matlab_add_unit_test( +# NAME +# UNITTEST_FILE matlab_file_containing_unittest.m +# [CUSTOM_TEST_COMMAND matlab_command_to_run_as_test] +# [UNITTEST_PRECOMMAND matlab_command_to_run] +# [TIMEOUT timeout] +# [ADDITIONAL_PATH path1 [path2 ...]] +# [MATLAB_ADDITIONAL_STARTUP_OPTIONS option1 [option2 ...]] +# [TEST_ARGS arg1 [arg2 ...]] +# [NO_UNITTEST_FRAMEWORK] +# ) +# +# The function arguments are: +# +# ``NAME`` +# name of the unittest in ctest. +# ``UNITTEST_FILE`` +# the matlab unittest file. Its path will be automatically +# added to the Matlab path. +# ``CUSTOM_TEST_COMMAND`` +# Matlab script command to run as the test. +# If this is not set, then the following is run: +# ``runtests('matlab_file_name'), exit(max([ans(1,:).Failed]))`` +# where ``matlab_file_name`` is the ``UNITTEST_FILE`` without the extension. +# ``UNITTEST_PRECOMMAND`` +# Matlab script command to be ran before the file +# containing the test (eg. GPU device initialisation based on CMake +# variables). +# ``TIMEOUT`` +# the test timeout in seconds. Defaults to 180 seconds as the +# Matlab unit test may hang. +# ``ADDITIONAL_PATH`` +# a list of paths to add to the Matlab path prior to +# running the unit test. +# ``MATLAB_ADDITIONAL_STARTUP_OPTIONS`` +# a list of additional option in order +# to run Matlab from the command line. +# ``-nosplash -nodesktop -nodisplay`` are always added. +# ``TEST_ARGS`` +# Additional options provided to the add_test command. These +# options are added to the default options (eg. "CONFIGURATIONS Release") +# ``NO_UNITTEST_FRAMEWORK`` +# when set, indicates that the test should not +# use the unittest framework of Matlab (available for versions >= R2013a). +# ``WORKING_DIRECTORY`` +# This will be the working directory for the test. If specified it will +# also be the output directory used for the log file of the test run. +# If not specified the temporary directory ``${CMAKE_BINARY_DIR}/Matlab`` will +# be used as the working directory and the log location. +# +function(matlab_add_unit_test) + + if(NOT Matlab_MAIN_PROGRAM) + message(FATAL_ERROR "[MATLAB] This functionality needs the MAIN_PROGRAM component (not default)") + endif() + + set(options NO_UNITTEST_FRAMEWORK) + set(oneValueArgs NAME UNITTEST_FILE TIMEOUT WORKING_DIRECTORY + UNITTEST_PRECOMMAND CUSTOM_TEST_COMMAND) + set(multiValueArgs ADDITIONAL_PATH MATLAB_ADDITIONAL_STARTUP_OPTIONS TEST_ARGS) + + set(prefix _matlab_unittest_prefix) + cmake_parse_arguments(PARSE_ARGV 0 ${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ) + + if(NOT ${prefix}_NAME) + message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty") + endif() + + add_test(NAME ${${prefix}_NAME} + COMMAND ${CMAKE_COMMAND} + "-Dtest_name=${${prefix}_NAME}" + "-Dadditional_paths=${${prefix}_ADDITIONAL_PATH}" + "-Dtest_timeout=${${prefix}_TIMEOUT}" + "-Doutput_directory=${_matlab_temporary_folder}" + "-Dworking_directory=${${prefix}_WORKING_DIRECTORY}" + "-DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM}" + "-Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK}" + "-DMatlab_ADDITIONAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS}" + "-Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}" + "-Dcustom_Matlab_test_command=${${prefix}_CUSTOM_TEST_COMMAND}" + "-Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}" + -P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake + ${${prefix}_TEST_ARGS} + ${${prefix}_UNPARSED_ARGUMENTS} + ) +endfunction() + + +#.rst: +# .. command:: matlab_add_mex +# +# Adds a Matlab MEX target. +# This commands compiles the given sources with the current tool-chain in +# order to produce a MEX file. The final name of the produced output may be +# specified, as well as additional link libraries, and a documentation entry +# for the MEX file. Remaining arguments of the call are passed to the +# :command:`add_library` or :command:`add_executable` command. +# +# :: +# +# matlab_add_mex( +# NAME +# [EXECUTABLE | MODULE | SHARED] +# SRC src1 [src2 ...] +# [OUTPUT_NAME output_name] +# [DOCUMENTATION file.txt] +# [LINK_TO target1 target2 ...] +# [...] +# ) +# +# ``NAME`` +# name of the target. +# ``SRC`` +# list of source files. +# ``LINK_TO`` +# a list of additional link dependencies. The target links to ``libmex`` +# by default. If ``Matlab_MX_LIBRARY`` is defined, it also +# links to ``libmx``. +# ``OUTPUT_NAME`` +# if given, overrides the default name. The default name is +# the name of the target without any prefix and +# with ``Matlab_MEX_EXTENSION`` suffix. +# ``DOCUMENTATION`` +# if given, the file ``file.txt`` will be considered as +# being the documentation file for the MEX file. This file is copied into +# the same folder without any processing, with the same name as the final +# mex file, and with extension `.m`. In that case, typing ``help `` +# in Matlab prints the documentation contained in this file. +# ``MODULE`` or ``SHARED`` may be given to specify the type of library to be +# created. ``EXECUTABLE`` may be given to create an executable instead of +# a library. If no type is given explicitly, the type is ``SHARED``. +# +# The documentation file is not processed and should be in the following +# format: +# +# :: +# +# % This is the documentation +# function ret = mex_target_output_name(input1) +# +function(matlab_add_mex) + + if(NOT WIN32) + # we do not need all this on Windows + # pthread options + if(CMAKE_CXX_COMPILER_LOADED) + check_cxx_compiler_flag(-pthread HAS_MINUS_PTHREAD) + elseif(CMAKE_C_COMPILER_LOADED) + check_c_compiler_flag(-pthread HAS_MINUS_PTHREAD) + endif() + # we should use try_compile instead, the link flags are discarded from + # this compiler_flag function. + #check_cxx_compiler_flag(-Wl,--exclude-libs,ALL HAS_SYMBOL_HIDING_CAPABILITY) + + endif() + + set(options EXECUTABLE MODULE SHARED) + set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) + set(multiValueArgs LINK_TO SRC) + + set(prefix _matlab_addmex_prefix) + cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if(NOT ${prefix}_NAME) + message(FATAL_ERROR "[MATLAB] The MEX target name cannot be empty") + endif() + + if(NOT ${prefix}_OUTPUT_NAME) + set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) + endif() + + if(${prefix}_EXECUTABLE) + add_executable(${${prefix}_NAME} + ${${prefix}_SRC} + ${${prefix}_DOCUMENTATION} + ${${prefix}_UNPARSED_ARGUMENTS}) + else() + if(${prefix}_MODULE) + set(type MODULE) + else() + set(type SHARED) + endif() + + add_library(${${prefix}_NAME} + ${type} + ${${prefix}_SRC} + ${${prefix}_DOCUMENTATION} + ${${prefix}_UNPARSED_ARGUMENTS}) + endif() + + target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) + + if(DEFINED Matlab_MX_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_MX_LIBRARY}) + endif() + + target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${${prefix}_LINK_TO}) + set_target_properties(${${prefix}_NAME} + PROPERTIES + PREFIX "" + OUTPUT_NAME ${${prefix}_OUTPUT_NAME} + SUFFIX ".${Matlab_MEX_EXTENSION}") + + + # documentation + if(NOT ${${prefix}_DOCUMENTATION} STREQUAL "") + get_target_property(output_name ${${prefix}_NAME} OUTPUT_NAME) + add_custom_command( + TARGET ${${prefix}_NAME} + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${${prefix}_DOCUMENTATION} $/${output_name}.m + COMMENT "[MATLAB] Copy ${${prefix}_NAME} documentation file into the output folder" + ) + endif() # documentation + + # entry point in the mex file + taking care of visibility and symbol clashes. + if(WIN32) + set_target_properties(${${prefix}_NAME} + PROPERTIES + DEFINE_SYMBOL "DLL_EXPORT_SYM=__declspec(dllexport)") + else() + + if(HAS_MINUS_PTHREAD AND NOT APPLE) + # Apparently, compiling with -pthread generated the proper link flags + # and some defines at compilation + target_compile_options(${${prefix}_NAME} PRIVATE "-pthread") + endif() + + + # if we do not do that, the symbols linked from eg. boost remain weak and + # then clash with the ones defined in the matlab process. So by default + # the symbols are hidden. + # This also means that for shared libraries (like MEX), the entry point + # should be explicitly declared with default visibility, otherwise Matlab + # cannot find the entry point. + # Note that this is particularly meaningful if the MEX wrapper itself + # contains symbols that are clashing with Matlab (that are compiled in the + # MEX file). In order to propagate the visibility options to the libraries + # to which the MEX file is linked against, the -Wl,--exclude-libs,ALL + # option should also be specified. + + set_target_properties(${${prefix}_NAME} + PROPERTIES + CXX_VISIBILITY_PRESET "hidden" + C_VISIBILITY_PRESET "hidden" + VISIBILITY_INLINES_HIDDEN ON + ) + + # get_target_property( + # _previous_link_flags + # ${${prefix}_NAME} + # LINK_FLAGS) + # if(NOT _previous_link_flags) + # set(_previous_link_flags) + # endif() + + # if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # set_target_properties(${${prefix}_NAME} + # PROPERTIES + # LINK_FLAGS "${_previous_link_flags} -Wl,--exclude-libs,ALL" + # # -Wl,--version-script=${_FindMatlab_SELF_DIR}/MatlabLinuxVisibility.map" + # ) + # elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # # in this case, all other symbols become hidden. + # set_target_properties(${${prefix}_NAME} + # PROPERTIES + # LINK_FLAGS "${_previous_link_flags} -Wl,-exported_symbol,_mexFunction" + # #-Wl,-exported_symbols_list,${_FindMatlab_SELF_DIR}/MatlabOSXVisilibity.map" + # ) + # endif() + + + + set_target_properties(${${prefix}_NAME} + PROPERTIES + DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))" + ) + + + endif() + +endfunction() + + +# (internal) +# Used to get the version of matlab, using caching. This basically transforms the +# output of the root list, with possible unknown version, to a version +# This can possibly run Matlab for extracting the version. +function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_version matlab_final_version) + + # if the version is not trivial, we query matlab (if not MCR) for that + # we keep track of the location of matlab that induced this version + #if(NOT DEFINED Matlab_PROG_VERSION_STRING_AUTO_DETECT) + # set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version") + #endif() + + if(NOT ${matlab_known_version} STREQUAL "NOTFOUND") + # the version is known, we just return it + set(${matlab_final_version} ${matlab_known_version} PARENT_SCOPE) + set(Matlab_VERSION_STRING_INTERNAL ${matlab_known_version} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) + return() + endif() + + if("${matlab_or_mcr}" STREQUAL "UNKNOWN") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Determining Matlab or MCR") + endif() + + if(EXISTS "${matlab_root}/appdata/version.xml") + # we inspect the application version.xml file that contains the product information + file(STRINGS "${matlab_root}/appdata/version.xml" productinfo_string NEWLINE_CONSUME) + string(REGEX MATCH "" + product_reg_match + ${productinfo_string} + ) + + # default fallback to Matlab + set(matlab_or_mcr "MATLAB") + if(NOT "${CMAKE_MATCH_1}" STREQUAL "") + string(TOLOWER "${CMAKE_MATCH_1}" product_reg_match) + + if("${product_reg_match}" STREQUAL "matlab runtime") + set(matlab_or_mcr "MCR") + endif() + endif() + endif() + + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] '${matlab_root}' contains the '${matlab_or_mcr}'") + endif() + endif() + + # UNKNOWN is the default behaviour in case we + # - have an erroneous matlab_root + # - have an initial 'UNKNOWN' + if("${matlab_or_mcr}" STREQUAL "MATLAB" OR "${matlab_or_mcr}" STREQUAL "UNKNOWN") + # MATLAB versions + set(_matlab_current_program ${Matlab_MAIN_PROGRAM}) + + # do we already have a matlab program? + if(NOT _matlab_current_program) + + set(_find_matlab_options) + if(matlab_root AND EXISTS ${matlab_root}) + set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH) + endif() + + find_program( + _matlab_current_program + matlab + ${_find_matlab_options} + DOC "Matlab main program" + ) + endif() + + if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program}) + # if not found, clear the dependent variables + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}") + endif() + set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + unset(_matlab_current_program) + unset(_matlab_current_program CACHE) + return() + endif() + + # full real path for path comparison + get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH) + unset(_matlab_current_program) + unset(_matlab_current_program CACHE) + + # is it the same as the previous one? + if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT) + set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE) + return() + endif() + + # update the location of the program + set(Matlab_PROG_VERSION_STRING_AUTO_DETECT + ${_matlab_main_real_path_tmp} + CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + + set(matlab_list_of_all_versions) + matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions) + + list(LENGTH matlab_list_of_all_versions list_of_all_versions_length) + if(${list_of_all_versions_length} GREATER 0) + list(GET matlab_list_of_all_versions 0 _matlab_version_tmp) + else() + set(_matlab_version_tmp "unknown") + endif() + + # set the version into the cache + set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) + + # warning, just in case several versions found (should not happen) + if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})") + endif() + + # return the updated value + set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE) + else() + # MCR + # we cannot run anything in order to extract the version. We assume that the file + # VersionInfo.xml exists under the MatlabRoot, we look for it and extract the version from there + set(_matlab_version_tmp "unknown") + file(STRINGS "${matlab_root}/VersionInfo.xml" versioninfo_string NEWLINE_CONSUME) + # parses "9.2.0.538062" + string(REGEX MATCH "(.*)" + version_reg_match + ${versioninfo_string} + ) + + if(NOT "${version_reg_match}" STREQUAL "") + if("${CMAKE_MATCH_1}" MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*") + set(_matlab_version_tmp "${CMAKE_MATCH_1}") + endif() + endif() + set(${matlab_final_version} "${_matlab_version_tmp}" PARENT_SCOPE) + set(Matlab_VERSION_STRING_INTERNAL + "${_matlab_version_tmp}" + CACHE INTERNAL "Matlab (MCR) version (automatically determined)" + FORCE) + + endif() # Matlab or MCR + +endfunction() + + +# Utility function for finding Matlab or MCR on Win32 +function(_Matlab_find_instances_win32 matlab_roots) + # On WIN32, we look for Matlab installation in the registry + # if unsuccessful, we look for all known revision and filter the existing + # ones. + + # testing if we are able to extract the needed information from the registry + set(_matlab_versions_from_registry) + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_matlab_win64 ON) + else() + set(_matlab_win64 OFF) + endif() + + matlab_extract_all_installed_versions_from_registry(_matlab_win64 _matlab_versions_from_registry) + + # the returned list is empty, doing the search on all known versions + if(NOT _matlab_versions_from_registry) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions") + endif() + extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry) + endif() + + # filtering the results with the registry keys + matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots) + unset(_matlab_versions_from_registry) + + set(_matlab_versions_from_registry) + matlab_extract_all_installed_versions_from_registry(CMAKE_CL_64 _matlab_versions_from_registry) + + # the returned list is empty, doing the search on all known versions + if(NOT _matlab_versions_from_registry) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions") + endif() + extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry) + endif() + + # filtering the results with the registry keys + matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots) + set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE) + +endfunction() + +# Utility function for finding Matlab or MCR on OSX +function(_Matlab_find_instances_osx matlab_roots) + + set(_matlab_possible_roots) + # on mac, we look for the /Application paths + # this corresponds to the behaviour on Windows. On Linux, we do not have + # any other guess. + matlab_get_supported_releases(_matlab_releases) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported " + "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation") + endif() + + foreach(_matlab_current_release IN LISTS _matlab_releases) + matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version) + string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}") + set(_matlab_base_path "/Applications/MATLAB_${_matlab_current_release}.app") + + # Check Matlab, has precedence over MCR + if(EXISTS ${_matlab_base_path}) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_base_path}") + endif() + list(APPEND _matlab_possible_roots "MATLAB" ${_matlab_current_version} ${_matlab_base_path}) + endif() + + # Checks MCR + set(_mcr_path "/Applications/MATLAB/MATLAB_Runtime/v${_matlab_current_version_without_dot}") + if(EXISTS "${_mcr_path}") + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Found MCR version ${_matlab_current_release} (${_matlab_current_version}) in ${_mcr_path}") + endif() + list(APPEND _matlab_possible_roots "MCR" ${_matlab_current_version} ${_mcr_path}) + endif() + + endforeach() + set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE) + +endfunction() + +# Utility function for finding Matlab or MCR from the PATH +function(_Matlab_find_instances_from_path matlab_roots) + + set(_matlab_possible_roots) + + # At this point, we have no other choice than trying to find it from PATH. + # If set by the user, this wont change + find_program( + _matlab_main_tmp + NAMES matlab) + + if(_matlab_main_tmp) + # we then populate the list of roots, with empty version + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] matlab found from PATH: ${_matlab_main_tmp}") + endif() + + # resolve symlinks + get_filename_component(_matlab_current_location "${_matlab_main_tmp}" REALPATH) + + # get the directory (the command below has to be run twice) + # this will be the matlab root + get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) + get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) # Matlab should be in bin + + # We found the Matlab program + list(APPEND _matlab_possible_roots "MATLAB" "NOTFOUND" ${_matlab_current_location}) + + # we remove this from the CACHE + unset(_matlab_main_tmp CACHE) + else() + find_program( + _matlab_mex_tmp + NAMES mex) + if(_matlab_mex_tmp) + # we then populate the list of roots, with empty version + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] mex compiler found from PATH: ${_matlab_mex_tmp}") + endif() + + # resolve symlinks + get_filename_component(_mex_current_location "${_matlab_mex_tmp}" REALPATH) + + # get the directory (the command below has to be run twice) + # this will be the matlab root + get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY) + get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY) # Matlab Runtime mex compiler should be in bin + + # We found the Matlab program + list(APPEND _matlab_possible_roots "MCR" "NOTFOUND" ${_mex_current_location}) + + unset(_matlab_mex_tmp CACHE) + else() + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] mex compiler not found") + endif() + endif() + + + endif() + + set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE) +endfunction() + + +# ################################### +# Exploring the possible Matlab_ROOTS + +# this variable will get all Matlab installations found in the current system. +set(_matlab_possible_roots) + +if(Matlab_ROOT_DIR) + # if the user specifies a possible root, we keep this one + + if(NOT EXISTS "${Matlab_ROOT_DIR}") + # if Matlab_ROOT_DIR specified but erroneous + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})") + endif() + else() + # NOTFOUND indicates the code below to search for the version automatically + if("${Matlab_VERSION_STRING_INTERNAL}" STREQUAL "") + list(APPEND _matlab_possible_roots "UNKNOWN" "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version, empty MCR/Matlab indication + else() + list(APPEND _matlab_possible_roots "UNKNOWN" ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version + endif() + endif() +else() + + # if the user does not specify the possible installation root, we look for + # one installation using the appropriate heuristics. + # There is apparently no standard way on Linux. + if(CMAKE_HOST_WIN32) + _Matlab_find_instances_win32(_matlab_possible_roots_win32) + list(APPEND _matlab_possible_roots ${_matlab_possible_roots_win32}) + elseif(APPLE) + _Matlab_find_instances_osx(_matlab_possible_roots_osx) + list(APPEND _matlab_possible_roots ${_matlab_possible_roots_osx}) + endif() +endif() + + +list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots) +if(_numbers_of_matlab_roots EQUAL 0) + # if we have not found anything, we fall back on the PATH + _Matlab_find_instances_from_path(_matlab_possible_roots) +endif() + + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Matlab root folders are ${_matlab_possible_roots}") +endif() + + + + + +# take the first possible Matlab root +list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots) +set(Matlab_VERSION_STRING "NOTFOUND") +set(Matlab_Or_MCR "UNKNOWN") +if(_numbers_of_matlab_roots GREATER 0) + list(GET _matlab_possible_roots 0 Matlab_Or_MCR) + list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING) + list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR) + + # adding a warning in case of ambiguity + if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." + " If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line") + endif() +endif() + + +# check if the root changed wrt. the previous defined one, if so +# clear all the cached variables for being able to reconfigure properly +if(DEFINED Matlab_ROOT_DIR_LAST_CACHED) + + if(NOT Matlab_ROOT_DIR_LAST_CACHED STREQUAL Matlab_ROOT_DIR) + set(_Matlab_cached_vars + Matlab_INCLUDE_DIRS + Matlab_MEX_LIBRARY + Matlab_MEX_COMPILER + Matlab_MCC_COMPILER + Matlab_MAIN_PROGRAM + Matlab_MX_LIBRARY + Matlab_ENG_LIBRARY + Matlab_MAT_LIBRARY + Matlab_MEX_EXTENSION + Matlab_SIMULINK_INCLUDE_DIR + + # internal + Matlab_MEXEXTENSIONS_PROG + Matlab_ROOT_DIR_LAST_CACHED + #Matlab_PROG_VERSION_STRING_AUTO_DETECT + Matlab_VERSION_STRING_INTERNAL + ) + foreach(_var IN LISTS _Matlab_cached_vars) + if(DEFINED ${_var}) + unset(${_var} CACHE) + endif() + endforeach() + endif() +endif() + +set(Matlab_ROOT_DIR_LAST_CACHED ${Matlab_ROOT_DIR} CACHE INTERNAL "last Matlab root dir location") +set(Matlab_ROOT_DIR ${Matlab_ROOT_DIR} CACHE PATH "Matlab installation root path" FORCE) + +# Fix the version, in case this one is NOTFOUND +_Matlab_get_version_from_root( + "${Matlab_ROOT_DIR}" + "${Matlab_Or_MCR}" + ${Matlab_VERSION_STRING} + Matlab_VERSION_STRING +) + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}") +endif() + + + +if(Matlab_ROOT_DIR) + file(TO_CMAKE_PATH ${Matlab_ROOT_DIR} Matlab_ROOT_DIR) +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(_matlab_64Build FALSE) +else() + set(_matlab_64Build TRUE) +endif() + +if(APPLE) + set(_matlab_bin_prefix "mac") # i should be for intel + set(_matlab_bin_suffix_32bits "i") + set(_matlab_bin_suffix_64bits "i64") +elseif(UNIX) + set(_matlab_bin_prefix "gln") + set(_matlab_bin_suffix_32bits "x86") + set(_matlab_bin_suffix_64bits "xa64") +else() + set(_matlab_bin_prefix "win") + set(_matlab_bin_suffix_32bits "32") + set(_matlab_bin_suffix_64bits "64") +endif() + + + +set(MATLAB_INCLUDE_DIR_TO_LOOK ${Matlab_ROOT_DIR}/extern/include) +if(_matlab_64Build) + set(_matlab_current_suffix ${_matlab_bin_suffix_64bits}) +else() + set(_matlab_current_suffix ${_matlab_bin_suffix_32bits}) +endif() + +set(Matlab_BINARIES_DIR + ${Matlab_ROOT_DIR}/bin/${_matlab_bin_prefix}${_matlab_current_suffix}) +set(Matlab_EXTERN_LIBRARY_DIR + ${Matlab_ROOT_DIR}/extern/lib/${_matlab_bin_prefix}${_matlab_current_suffix}) + +if(WIN32) + if(MINGW) + set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/mingw64) + else() + set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/microsoft) + endif() + set(_matlab_lib_prefix_for_search "lib") +else() + set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR}) + set(_matlab_lib_prefix_for_search "lib") +endif() + +unset(_matlab_64Build) + + +if(NOT DEFINED Matlab_MEX_EXTENSION) + set(_matlab_mex_extension "") + matlab_get_mex_suffix("${Matlab_ROOT_DIR}" _matlab_mex_extension) + + # This variable goes to the cache. + set(Matlab_MEX_EXTENSION ${_matlab_mex_extension} CACHE STRING "Extensions for the mex targets (automatically given by Matlab)") + unset(_matlab_mex_extension) +endif() + + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] [DEBUG]_matlab_lib_prefix_for_search = ${_matlab_lib_prefix_for_search} | _matlab_lib_dir_for_search = ${_matlab_lib_dir_for_search}") +endif() + + + +# internal +# This small stub around find_library is to prevent any pollution of CMAKE_FIND_LIBRARY_PREFIXES in the global scope. +# This is the function to be used below instead of the find_library directives. +function(_Matlab_find_library _matlab_library_prefix) + set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} ${_matlab_library_prefix}) + find_library(${ARGN}) +endfunction() + + +set(_matlab_required_variables) + + +# the MEX library/header are required +find_path( + Matlab_INCLUDE_DIRS + mex.h + PATHS ${MATLAB_INCLUDE_DIR_TO_LOOK} + NO_DEFAULT_PATH + ) +list(APPEND _matlab_required_variables Matlab_INCLUDE_DIRS) + +_Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MEX_LIBRARY + mex + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH +) + +list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY) + +# the MEX extension is required +list(APPEND _matlab_required_variables Matlab_MEX_EXTENSION) + +# the matlab root is required +list(APPEND _matlab_required_variables Matlab_ROOT_DIR) + +# component Mex Compiler +list(FIND Matlab_FIND_COMPONENTS MEX_COMPILER _matlab_find_mex_compiler) +if(_matlab_find_mex_compiler GREATER -1) + find_program( + Matlab_MEX_COMPILER + "mex" + PATHS ${Matlab_BINARIES_DIR} + DOC "Matlab MEX compiler" + NO_DEFAULT_PATH + ) + if(Matlab_MEX_COMPILER) + set(Matlab_MEX_COMPILER_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mex_compiler) + +# component Matlab program +list(FIND Matlab_FIND_COMPONENTS MAIN_PROGRAM _matlab_find_matlab_program) +if(_matlab_find_matlab_program GREATER -1) + find_program( + Matlab_MAIN_PROGRAM + matlab + PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin + DOC "Matlab main program" + NO_DEFAULT_PATH + ) + if(Matlab_MAIN_PROGRAM) + set(Matlab_MAIN_PROGRAM_FOUND TRUE) + endif() +endif() +unset(_matlab_find_matlab_program) + +# Component MX library +list(FIND Matlab_FIND_COMPONENTS MX_LIBRARY _matlab_find_mx) +if(_matlab_find_mx GREATER -1) + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MX_LIBRARY + mx + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH + ) + if(Matlab_MX_LIBRARY) + set(Matlab_MX_LIBRARY_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mx) + +# Component ENG library +list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng) +if(_matlab_find_eng GREATER -1) + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_ENG_LIBRARY + eng + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH + ) + if(Matlab_ENG_LIBRARY) + set(Matlab_ENG_LIBRARY_FOUND TRUE) + endif() +endif() +unset(_matlab_find_eng) + +# Component MAT library +list(FIND Matlab_FIND_COMPONENTS MAT_LIBRARY _matlab_find_mat) +if(_matlab_find_mat GREATER -1) + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MAT_LIBRARY + mat + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH + ) + if(Matlab_MAT_LIBRARY) + set(Matlab_MAT_LIBRARY_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mat) + +# Component Simulink +list(FIND Matlab_FIND_COMPONENTS SIMULINK _matlab_find_simulink) +if(_matlab_find_simulink GREATER -1) + find_path( + Matlab_SIMULINK_INCLUDE_DIR + simstruc.h + PATHS "${Matlab_ROOT_DIR}/simulink/include" + NO_DEFAULT_PATH + ) + if(Matlab_SIMULINK_INCLUDE_DIR) + set(Matlab_SIMULINK_FOUND TRUE) + list(APPEND Matlab_INCLUDE_DIRS "${Matlab_SIMULINK_INCLUDE_DIR}") + endif() +endif() +unset(_matlab_find_simulink) + +# component MCC Compiler +list(FIND Matlab_FIND_COMPONENTS MCC_COMPILER _matlab_find_mcc_compiler) +if(_matlab_find_mcc_compiler GREATER -1) + find_program( + Matlab_MCC_COMPILER + "mcc" + PATHS ${Matlab_BINARIES_DIR} + DOC "Matlab MCC compiler" + NO_DEFAULT_PATH + ) + if(Matlab_MCC_COMPILER) + set(Matlab_MCC_COMPILER_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mcc_compiler) + +unset(_matlab_lib_dir_for_search) + +set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY}) + +find_package_handle_standard_args( + Matlab + FOUND_VAR Matlab_FOUND + REQUIRED_VARS ${_matlab_required_variables} + VERSION_VAR Matlab_VERSION_STRING + HANDLE_COMPONENTS) + +unset(_matlab_required_variables) +unset(_matlab_bin_prefix) +unset(_matlab_bin_suffix_32bits) +unset(_matlab_bin_suffix_64bits) +unset(_matlab_current_suffix) +unset(_matlab_lib_dir_for_search) +unset(_matlab_lib_prefix_for_search) + +if(Matlab_INCLUDE_DIRS AND Matlab_LIBRARIES) + mark_as_advanced( + Matlab_MEX_LIBRARY + Matlab_MX_LIBRARY + Matlab_ENG_LIBRARY + Matlab_MAT_LIBRARY + Matlab_INCLUDE_DIRS + Matlab_FOUND + Matlab_MAIN_PROGRAM + Matlab_MEXEXTENSIONS_PROG + Matlab_MEX_EXTENSION + ) +endif() \ No newline at end of file diff --git a/OpenFAST/cmake/FindSphinx.cmake b/OpenFAST/cmake/FindSphinx.cmake new file mode 100644 index 000000000..353c69c83 --- /dev/null +++ b/OpenFAST/cmake/FindSphinx.cmake @@ -0,0 +1,17 @@ +find_program(SPHINX_EXECUTABLE NAMES sphinx-build + DOC "Sphinx Documentation Builder (sphinx-doc.org)" +) + +if(SPHINX_EXECUTABLE) + execute_process(COMMAND ${SPHINX_EXECUTABLE} --version OUTPUT_VARIABLE SPHINX_VERSION_OUTPUT) + if("${SPHINX_VERSION_OUTPUT}" MATCHES "^Sphinx \\(sphinx-build\\) ([^\n]+)\n") + set(SPHINX_VERSION "${CMAKE_MATCH_1}") + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Sphinx REQUIRED_VARS SPHINX_EXECUTABLE + VERSION_VAR SPHINX_VERSION +) + +mark_as_advanced(SPHINX_EXECUTABLE) diff --git a/OpenFAST/cmake/FindYAMLCPP.cmake b/OpenFAST/cmake/FindYAMLCPP.cmake new file mode 100644 index 000000000..a3557319e --- /dev/null +++ b/OpenFAST/cmake/FindYAMLCPP.cmake @@ -0,0 +1,27 @@ +# +# 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. +# + +find_path(YAML_INCLUDES + yaml-cpp/yaml.h + HINTS ${YAML_ROOT} ${CMAKE_INSTALL_PREFIX} + PATH_SUFFIXES include) + +find_library(YAML_LIBRARIES + NAMES yaml-cpp libyaml-cpp.a + HINTS ${YAML_ROOT} ${CMAKE_INSTALL_PREFIX} + PATH_SUFFIXES lib) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(YAMLCPP DEFAULT_MSG YAML_INCLUDES YAML_LIBRARIES) +mark_as_advanced(YAML_INCLUDES YAML_LIBRARIES) diff --git a/OpenFAST/cmake/GetGitRevisionDescription.cmake b/OpenFAST/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 000000000..f6459366f --- /dev/null +++ b/OpenFAST/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,160 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Obtained from https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake +# on August 29 2017 +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe --abbrev=8 --tags --dirty + # ${hash} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + diff-index --quiet HEAD -- + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} "CLEAN" PARENT_SCOPE) + else() + set(${_var} "DIRTY" PARENT_SCOPE) + endif() +endfunction() diff --git a/OpenFAST/cmake/GetGitRevisionDescription.cmake.in b/OpenFAST/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 000000000..a0f9c60c3 --- /dev/null +++ b/OpenFAST/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,44 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Obtained from https://github.com/rpavlik/cmake-modules/blob/master/GetGitRevisionDescription.cmake.in +# on August 29 2017 +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 8) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() \ No newline at end of file diff --git a/OpenFAST/cmake/OpenFASTConfig.cmake.in b/OpenFAST/cmake/OpenFASTConfig.cmake.in new file mode 100644 index 000000000..952563d3e --- /dev/null +++ b/OpenFAST/cmake/OpenFASTConfig.cmake.in @@ -0,0 +1,65 @@ +# +# Copyright 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. +# + +@PACKAGE_INIT@ + +# Compilers use by OpenFAST build +set(OpenFAST_CXX_COMPILER "@CMAKE_CXX_COMPILER@") +set(OpenFAST_C_COMPILER "@CMAKE_C_COMPILER@") +set(OpenFAST_Fortran_COMPILER "@CMAKE_Fortran_COMPILER@") + +# Compiler flags used by OpenFAST build +set(OpenFAST_CXX_COMPILER_FLAGS "@CMAKE_CXX_FLAGS@") +set(OpenFAST_C_COMPILER_FLAGS "@CMAKE_C_FLAGS@") +set(OpenFAST_Fortran_COMPILER_FLAGS "@CMAKE_Fortran_FLAGS@") + +set_and_check(OpenFAST_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") +set_and_check(OpenFAST_LIBRARY_DIRS "@PACKAGE_LIB_INSTALL_DIR@") +set_and_check(OpenFAST_FTNMOD_DIR "@PACKAGE_FTNMOD_INSTALL_DIR@") + +set(OpenFAST_LIBRARIES "openfastlib") +set(OpenFAST_CPP_LIBRARIES "openfastcpplib") + +include("${CMAKE_CURRENT_LIST_DIR}/OpenFASTLibraries.cmake") + +set(OpenFAST_HAS_CXX_API @OpenFAST_HAS_CXX_API@) +set(OpenFAST_FOUND TRUE) + +if (NOT OpenFAST_FIND_COMPONENTS) + if (OpenFAST_HAS_CXX_API) + set(OpenFAST_FIND_COMPONENTS "openfastcpplib;openfastlib") + else() + set(OpenFAST_FIND_COMPONENTS "openfastlib") + endif() +endif () + +foreach (comp IN LISTS OpenFAST_FIND_COMPONENTS) + if (${comp} STREQUAL "openfastcpplib") + if (NOT OpenFAST_HAS_CXX_API) + set(OpenFAST_${comp}_FOUND FALSE) + message(WARNING "OpenFAST ${comp} NOT found") + if(OpenFAST_FIND_REQUIRED_${comp}) + set(OpenFAST_FOUND FALSE) + endif() + else() + set(OpenFAST_${comp}_FOUND TRUE) + endif() + else() + set(OpenFAST_${comp}_FOUND TRUE) + endif() +endforeach () + +check_required_components(OpenFAST) diff --git a/OpenFAST/cmake/OpenfastCmakeUtils.cmake b/OpenFAST/cmake/OpenfastCmakeUtils.cmake new file mode 100644 index 000000000..483758241 --- /dev/null +++ b/OpenFAST/cmake/OpenfastCmakeUtils.cmake @@ -0,0 +1,66 @@ +# +# Copyright 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. +# + +################################################################################ +# OpenFAST CMake Utilities +# +# This module contains various functions used within CMakeLists.txt. +# Consolidated here to provide a central place for edits/enhancements. +# +# Available functions: +# - generate_f90_types +# - set_registry_includes +# +################################################################################ + + +# +# GENERATE_F90TYPES - Generate *_Types.F90 files +# +# Usage: +# generate_f90_types(BeamDyn_Registry.txt BeamDyn_Types.f90) +# +# Inputs: +# - regfile (filename): Path to the .txt definitions file +# +# Outputs: +# - outfile (filename): Path to the F90 or C file to be generated +# +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} + ) + set_source_files_properties(${output} PROPERTIES GENERATED TRUE) +endfunction(generate_f90_types) + +# +# SET_REGISTRY_INCLUDES - Set includes path for generating *_Types.f90 +# +# Utility function to create the includes path used when looking at module +# definitions for creating the Types.f90 files. +# +function(set_registry_includes modules_location) + foreach(IDIR IN ITEMS ${ARGN}) + set(OPENFAST_REGISTRY_INCLUDES + ${OPENFAST_REGISTRY_INCLUDES} -I ${CMAKE_SOURCE_DIR}/${modules_location}/${IDIR}/src + CACHE INTERNAL "Registry includes paths") + endforeach(IDIR IN ITEMS ${ARGN}) +endfunction(set_registry_includes) diff --git a/OpenFAST/cmake/OpenfastFortranOptions.cmake b/OpenFAST/cmake/OpenfastFortranOptions.cmake new file mode 100644 index 000000000..853395ddb --- /dev/null +++ b/OpenFAST/cmake/OpenfastFortranOptions.cmake @@ -0,0 +1,255 @@ +# +# Copyright 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. +# + +################################################################################ +# OpenFAST Fortran Options +# +# Utility functions to set Fortran compiler options depending on system +# architecture and compiler type. The entry point is the function +# `set_fast_fortran` that configures various options once the compiler is +# auto-detected. +# +# The remaining functions provide customization for specific compiler/arch to +# avoid nested if-else conditionals. +# +# Available functions: +# +# - set_fast_gfortran +# - set_fast_intel_fortran +# - set_fast_intel_fortran_posix +# - set_fast_intel_fortran_windows +# +################################################################################ + +# +# SET_FAST_FORTRAN - Set Fortran compiler options based on compiler/arch +# +macro(set_fast_fortran) + get_filename_component(FCNAME "${CMAKE_Fortran_COMPILER}" NAME) + + # Abort if we do not have gfortran or Intel Fortran Compiler. + if (NOT (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU" OR + ${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel")) + message(FATAL_ERROR "OpenFAST requires either GFortran or Intel Fortran Compiler. Compiler detected by CMake: ${FCNAME}.") + endif() + + # Verify proper compiler versions are available + # see https://github.com/OpenFAST/openfast/issues/88 + if(${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + if("${CMAKE_Fortran_COMPILER_VERSION}" STREQUAL "") + message(WARNING "A version of GNU GFortran greater than 4.6.0 is required but CMake could not detect your GFortran version.") + elseif("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_LESS "4.6.0") + message(FATAL_ERROR "A version of GNU GFortran greater than 4.6.0 is required. GFortran version detected by CMake: ${CMAKE_Fortran_COMPILER_VERSION}.") + endif() + elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + if("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_LESS "11") + message(FATAL_ERROR "A version of Intel ifort greater than 11 is required. ifort version detected by CMake: ${CMAKE_Fortran_COMPILER_VERSION}.") + endif() + endif() + + # Force all .mod files to be stored in a single directory + set(CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/ftnmods" + CACHE STRING "Set the Fortran Modules directory" FORCE) + include_directories(${CMAKE_Fortran_MODULE_DIRECTORY}) + + # Get OS/Compiler specific options + if (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + set_fast_gfortran() + elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + set_fast_intel_fortran() + endif() +endmacro(set_fast_fortran) + +# +# CHECK_F2008_FEATURES - Check if Fortran2008 features are available +# +macro(check_f2008_features) + include(CheckFortranSourceCompiles) + check_fortran_source_compiles( + "program test + use iso_fortran_env, only: compiler_version, real32, real64, real128 + integer, parameter :: quki = real128 + integer, parameter :: dbki = real64 + integer, parameter :: reki = real32 + + end program test" + HAS_FORTRAN2008 + SRC_EXT F90) + if (HAS_FORTRAN2008) + message(STATUS "Enabling Fortran 2008 features") + add_definitions(-DHAS_FORTRAN2008_FEATURES) + endif() +endmacro(check_f2008_features) + +# +# SET_FAST_GFORTRAN - Customizations for GNU Fortran compiler +# +macro(set_fast_gfortran) + if(NOT WIN32) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fpic ") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpic") + endif(NOT WIN32) + + # Fix free-form compilation for OpenFAST + #set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-none -cpp -fopenmp") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-none -cpp") + + # Disable stack reuse within routines: issues seen with gfortran 9.x, but others may also exhibit + # see section 3.16 of https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc.pdf + # and https://github.com/OpenFAST/openfast/pull/595 + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fstack-reuse=none") + + # Deal with Double/Single precision + if (DOUBLE_PRECISION) + add_definitions(-DOPENFAST_DOUBLE_PRECISION) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fdefault-real-8") + endif (DOUBLE_PRECISION) + + # debug flags # + # -fcheck=all gives the error: At line 695 of file /Users/gbarter/devel/WEIS/OpenFAST/modules/hydrodyn/src/WAMIT.f90 + # Fortran runtime error: Index '1' of dimension 1 of array 'wamitwvdir' above upper bound of 0 + if(CMAKE_BUILD_TYPE MATCHES Debug) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -pedantic -fbacktrace" ) + endif() + + if(CYGWIN) + # increase the default 2MB stack size to 16 MB + MATH(EXPR stack_size "16 * 1024 * 1024") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--stack,${stack_size}") + endif() + + # OPENMP + if (OPENMP) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fopenmp") + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fopenmp" ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fopenmp" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fopenmp" ) + endif() + + check_f2008_features() +endmacro(set_fast_gfortran) + +# +# SET_FAST_INTEL_FORTRAN - Customizations for Intel Fortran Compiler +# +macro(set_fast_intel_fortran) + if(WIN32) + set_fast_intel_fortran_windows() + else(WIN32) + set_fast_intel_fortran_posix() + endif(WIN32) +endmacro(set_fast_intel_fortran) + +# +# SET_FAST_INTEL_FORTRAN_POSIX - Customizations for Intel Fortran Compiler posix +# arch +# +macro(set_fast_intel_fortran_posix) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fpic -fpp") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpic") + # Deal with Double/Single precision + if (DOUBLE_PRECISION) + add_definitions(-DOPENFAST_DOUBLE_PRECISION) + if("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_GREATER "19") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -double-size 128") + else() + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -double_size 128") + endif() + endif (DOUBLE_PRECISION) + + # debug flags + # -check all gives the error: At line 695 of file /Users/gbarter/devel/WEIS/OpenFAST/modules/hydrodyn/src/WAMIT.f90 + # Fortran runtime error: Index '1' of dimension 1 of array 'wamitwvdir' above upper bound of 0 + if(CMAKE_BUILD_TYPE MATCHES Debug) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -traceback" ) + endif() + + # OPENMP + if (OPENMP) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qopenmp") + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -qopenmp" ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qopenmp") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qopenmp" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qopenmp") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -qopenmp" ) + endif() + + check_f2008_features() + + ### Intel profiling flags + + # https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/optimization-report-options/qopt-report-qopt-report.html + # phases: vec, par, openmp + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -qopt-report-phase=vec,openmp -qopt-report=5") + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -qopt-report-routine=Create_Augmented_Ln2_Src_Mesh") # Create_Augmented_Ln2_Src_Mesh, Morison_CalcOutput, VariousWaves_Init + + # https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/output-debug-and-precompiled-header-pch-options/debug-linux-and-macos.html + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -debug all") + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -debug inline-debug-info") + + # Intel processor feature sets + # https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/code-generation-options/xhost-qxhost.html + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -xHOST") # Use feature set for CPU used to compile + # set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "${CMAKE_Fortran_FLAGS_RELWITHDEBINFO} -xSKYLAKE-AVX512") # Use Eagle processor feature set +endmacro(set_fast_intel_fortran_posix) + +# +# SET_FAST_INTEL_FORTRAN_WINDOWS - Customizations for Intel Fortran Compiler +# windows arch +# +macro(set_fast_intel_fortran_windows) + # Turn off specific warnings + # - 5199: too many continuation lines + # - 5268: 132 column limit + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /Qdiag-disable:5199,5268 /fpp") + + # Deal with Double/Single precision + if (DOUBLE_PRECISION) + add_definitions(-DOPENFAST_DOUBLE_PRECISION) + if("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_GREATER "19") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /real-size:64 /double-size:128") + else() + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /real_size:64 /double_size:128") + endif() + endif (DOUBLE_PRECISION) + + # increase the default 2MB stack size to 16 MB + MATH(EXPR stack_size "16 * 1024 * 1024") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:${stack_size}") + + # debug flags + # /check:all gives the error: At line 695 of file /Users/gbarter/devel/WEIS/OpenFAST/modules/hydrodyn/src/WAMIT.f90 + # Fortran runtime error: Index '1' of dimension 1 of array 'wamitwvdir' above upper bound of 0 + if(CMAKE_BUILD_TYPE MATCHES Debug) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} /traceback" ) + endif() + + # OPENMP + if (OPENMP) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /qopenmp") + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} /qopenmp" ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /qopenmp") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /qopenmp" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /qopenmp") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /qopenmp" ) + endif() + + check_f2008_features() +endmacro(set_fast_intel_fortran_windows) diff --git a/OpenFAST/docs/CMakeLists.txt b/OpenFAST/docs/CMakeLists.txt new file mode 100644 index 000000000..7e67f2f05 --- /dev/null +++ b/OpenFAST/docs/CMakeLists.txt @@ -0,0 +1,43 @@ +find_package(Doxygen) +find_package(Sphinx) + +if(NOT DOXYGEN_FOUND) + message(WARNING "Skipping Doxygen documentation due to missing dependencies.") +else() + configure_file(Doxyfile.in Doxyfile @ONLY) + file(COPY "DoxygenLayout.xml" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_target(doxygen + COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" ) +endif() + +if(NOT SPHINX_FOUND) + message(WARNING "Skipping Sphinx documentation due to missing dependencies.") +else() + set(SPHINX_GENERATOR html) + file(COPY "conf.py" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY "_static" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_target(sphinx + COMMAND ${SPHINX_EXECUTABLE} -b ${SPHINX_GENERATOR} + -c ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/${SPHINX_GENERATOR}" + ) + add_dependencies(sphinx doxygen) + add_custom_target(docs DEPENDS sphinx) + + # Add a sphinx-only HTML target to avoid building doxygen while developing documentation + add_custom_target(sphinx-html + COMMAND ${SPHINX_EXECUTABLE} -M html + "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" + -c ${CMAKE_CURRENT_SOURCE_DIR}) + + # PDF documentation generation using sphinx -> latex -> pdflatex + find_package(LATEX COMPONENTS PDFLATEX BIBTEX) + if (LATEX_FOUND) + add_custom_target(sphinx-pdf + COMMAND ${SPHINX_EXECUTABLE} -M latexpdf + "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" + -c ${CMAKE_CURRENT_BINARY_DIR}) + endif() +endif() diff --git a/OpenFAST/docs/Doxyfile.in b/OpenFAST/docs/Doxyfile.in new file mode 100644 index 000000000..88c8b3b1f --- /dev/null +++ b/OpenFAST/docs/Doxyfile.in @@ -0,0 +1,2514 @@ +# Doxyfile 1.8.16 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "OpenFAST" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Wind turbine multiphysics simulator" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = @CMAKE_BINARY_DIR@/docs/_static/openfastlogo.jpg + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = @CMAKE_BINARY_DIR@/docs/doxygen + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = YES + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @CMAKE_SOURCE_DIR@/glue-codes/ \ + @CMAKE_SOURCE_DIR@/modules/ \ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.f90 \ + *.F90 \ + *.f \ + *.F \ + *.for \ + *.c \ + *.cxx \ + *.cpp \ + *.C \ + *.cc \ + *.hh \ + *.hxx \ + *.hpp \ + *.h \ + *.py + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = @CMAKE_SOURCE_DIR@/.git/* \ + @CMAKE_SOURCE_DIR@/build/* \ + @CMAKE_SOURCE_DIR@/cmake/* \ + @CMAKE_SOURCE_DIR@/docs/* \ + @CMAKE_SOURCE_DIR@/modules/orcaflex-interface/src/OrcaFlexInterface.f90 \ + @CMAKE_SOURCE_DIR@/modules/servodyn/src/BladedInterface.f90 + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = YES + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /m<{g$hZU%Vq}w<;x#q4kvIbs_B2sqg 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 0 \\ + \end{matrix} + \right. +\end{equation} + + +\section{Solving for $\lambda$} + +If the logarithmic map and matrix exponential are truly inverses, we need +\begin{equation} +\exp(\log(\Lambda)) = \Lambda. +\end{equation} +Using the expression for $\lambda$ from Equation \ref{EqLog}, we get +\begin{equation} +\label{EqExpMatrix} + \exp\left( + \begin{bmatrix} + 0 & \lambda_3 & -\lambda_2 \\ + -\lambda_3 & 0 & \lambda_1 \\ + \lambda_2 & -\lambda_1 & 0 + \end{bmatrix} +\right) = \Lambda = + \begin{bmatrix} + \Lambda_{11} & \Lambda_{12} & \Lambda_{13} \\ + \Lambda_{21} & \Lambda_{22} & \Lambda_{23} \\ + \Lambda_{31} & \Lambda_{32} & \Lambda_{33} \\ + \end{bmatrix} +\end{equation} + +Doing a little algebra for $\theta > 0$, Equation \ref{EqExpMatrix} becomes +\begin{equation} +\label{EqMatrixAlgebra} +\Lambda = + \begin{bmatrix} + 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_3^2 + \lambda_2^2\right) +& \frac{\sin\theta}{\theta}\lambda_3+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_2 +& -\frac{\sin\theta}{\theta}\lambda_2+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_3 \\ + -\frac{\sin\theta}{\theta}\lambda_3+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_2 +& 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_3^2 + \lambda_1^2\right) +& \frac{\sin\theta}{\theta}\lambda_1+\frac{1-\cos\theta}{\theta^2}\lambda_2\lambda_3 \\ + \frac{\sin\theta}{\theta}\lambda_2+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_3 +& -\frac{\sin\theta}{\theta}\lambda_1+\frac{1-\cos\theta}{\theta^2}\lambda_2\lambda_3 +& 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_2^2 + \lambda_1^2\right) \\ + \end{bmatrix} +\end{equation} +It follows that the trace is +\begin{eqnarray*} +\mathrm{Tr}(\Lambda) &=& 3 - 2\frac{1-\cos\theta}{\theta^2}(\lambda_1^2 + \lambda_2^2 + \lambda_3^2) \\ + &=& 3 - 2\left(1-\cos\theta\right) \\ + &=& 1 + 2\cos\theta +\end{eqnarray*} or +\begin{equation} +\theta= \begin{matrix} \cos^{-1}\left(\frac{1}{2}\left(\mathrm{Tr}(\Lambda)-1\right)\right) & \theta \in \left[0,\pi\right]\end{matrix} +\end{equation} +It also follows that +\begin{equation} +\Lambda - \Lambda^T=\frac{2\sin\theta}{\theta} + \begin{bmatrix} + 0 & \lambda_3 & -\lambda_2 \\ + -\lambda_3 & 0 & \lambda_1 \\ + \lambda_2 & -\lambda_1 & 0 \\ + \end{bmatrix} +\end{equation} or, when $\sin\theta \neq 0$ +\begin{equation} +\label{EqLambdaSinNot0} +\lambda = \frac{\theta}{2\sin\theta} \left( \Lambda - \Lambda^T\right) +\end{equation} +We need an equation that works when $\sin\theta$ approaches 0, that is, when $\theta$ approaches 0 or $\theta$ approaches $\pi$. When $\theta$ approaches 0, Equation \ref{EqLambdaSinNot0} actually behaves well: +\begin{equation} +\lim_{\theta \to 0}\frac{\theta}{2\sin\theta} = \frac{1}{2} +\end{equation} +and since $\theta$ is the $l_2$ norm of the individual components of $\lambda$, it follows that they approach zero, and we get +\begin{equation} +\label{EqLambdaTheta0} +\lambda = 0 +\end{equation} +However, when $\theta$ approaches $\pi$, $\Lambda - \Lambda^T$ approaches 0, and +\begin{equation} +\lim_{\theta \to \pi}\frac{\theta}{2\sin\theta} = \infty +\end{equation} +We need a different method to find $\lambda$. Going back to Equations \ref{EqExpMatrix} and \ref{EqMatrixAlgebra}, we can compute the following: +\begin{equation} +\Lambda_{11}+\Lambda_{22}-\Lambda_{33} = 1 - \frac{2\lambda_3^2(1-\cos\theta)}{\theta^2} +\end{equation} +%\begin{equation} +%\Lambda_{11}-\Lambda_{22}+\Lambda{33} = 1 - \frac{1-\cos\theta}{\theta^2}\left( 2\lambda_2^2\right) +%\end{equation} +%\begin{equation} +%-\Lambda_{11}+\Lambda_{22}+\Lambda{33} = 1 - \frac{1-\cos\theta}{\theta^2}\left( 2\lambda_1^2\right) +%\end{equation} +or +\begin{equation} +\label{EqLambda3} +\lambda_3 = \pm \theta\sqrt{ \frac{\left(1 + \Lambda_{33} - \Lambda_{11} - \Lambda_{22}\right)}{2\left(1-\cos\theta\right)} } +\end{equation} +Equations for the other two components of $\lambda$ are similar: +\begin{equation} +\label{EqLambda1} +\lambda_1 = \pm \theta\sqrt{ \frac{\left(1 + \Lambda_{11} - \Lambda_{22} - \Lambda_{33}\right)}{2\left(1-\cos\theta\right)} } +\end{equation} +\begin{equation} +\label{EqLambda2} +\lambda_2 = \pm \theta\sqrt{ \frac{\left(1 + \Lambda_{22} - \Lambda_{11} - \Lambda_{33}\right)}{2\left(1-\cos\theta\right)} } +\end{equation} +Equations \ref{EqLambda3}-\ref{EqLambda2} give us the magnitude, not the sign of the vector we are looking for. Here is one possibility for choosing the sign: +If $(\lambda_1) \neq 0$, choose $\mathrm{sign}(\lambda_1)$ positive. +\begin{equation} +\Lambda_{12}+\Lambda_{21} = \frac{2\left(1-\cos\theta\right)}{\theta^2}\lambda_1\lambda_2 +\end{equation} +so +\begin{equation} +\mathrm{sign}(\lambda_2) = \mathrm{sign}(\Lambda_{12}+\Lambda_{21}) +\end{equation} +and similarly, +\begin{equation} +\mathrm{sign}(\lambda_3) = \mathrm{sign}(\Lambda_{13}+\Lambda_{31}) +\end{equation} +If $(\lambda_1) = 0$, similar arguments can be used to choose $\mathrm{sign}(\lambda_2)$ positive, and +\begin{equation} +\mathrm{sign}(\lambda_3) = \mathrm{sign}(\Lambda_{23}+\Lambda_{32}) +\end{equation} +At this point, the relationships between the components of $\lambda$ are set, so we have computed $\pm\lambda$. If $\theta=\pi$, both values are a solution, so this good enough. + +If $\theta$ is close to $\pi$, we will need to determine if we have the negative of the solution. This is required for numerical stability of the solution. +In this case, $\Lambda-\Lambda^T$ is not exactly zero, so we can look at the sign of the solution we would have computed if we had used Equation \ref{EqLambdaSinNot0}: +\begin{equation} +\Lambda_{23}-\Lambda_{32} = \left|\frac{2\sin\theta}{\theta}\right|\lambda_1 +\end{equation} +\begin{equation} +\Lambda_{31}-\Lambda_{13} = \left|\frac{2\sin\theta}{\theta}\right|\lambda_2 +\end{equation} +\begin{equation} +\Lambda_{12}-\Lambda_{21} = \left|\frac{2\sin\theta}{\theta}\right|\lambda_3 +\end{equation} +For numerical reasons, we don't want to use these equations to get the magnitude of the components of $\lambda$, but we can look at the sign of the element with largest magnitude and ensure our $\lambda$ has the same sign. + +\section{Interpolation} +\subsection{Periodicity of solutions} + +Given $\lambda_k = \lambda \left( 1 + \frac{2k\pi}{\left\| \lambda \right\|}\right)$ for any integer $k$, it follows that +\begin{equation} +\theta_k = \left| 1 + \frac{2k\pi}{\left\|\lambda\right\|}\right| \theta +\end{equation} +or +\begin{equation} +\theta_k = \left|\theta + 2k\pi\right| +\end{equation} + +\begin{eqnarray*} +\Lambda_k +&=& \exp(\lambda_k) \\ +&=& I + \frac{\sin\theta_k}{\theta_k}\lambda_k + \frac{1-\cos\theta_k}{\theta_k^2}\lambda_k^2 \\ +&=& I + \frac{\sin\left|\theta + 2k\pi\right|}{\left|\theta + 2k\pi\right|}\left( \frac{\theta+2k\pi}{\theta}\right)\lambda + \frac{1-\cos\left|\theta + 2k\pi\right|}{\left|\theta + 2k\pi\right|^2}\left(\frac{\theta+2k\pi}{\theta}\right)^2\lambda^2 \\ +&=& I + \frac{\sin\left|\theta + 2k\pi\right|}{\theta} + \frac{\theta + 2k\pi}{\left|\theta + 2k\pi\right|}\lambda + \frac{1-\cos\left|\theta + 2k\pi\right|}{\theta^2}\lambda^2\\ +&=& I + \frac{\sin\theta}{\theta} \lambda + \frac{1-\cos\theta}{\theta^2}\lambda^2\\ +&=& \exp(\lambda) \\ +&=& \Lambda \\ +\end{eqnarray*} + +Thus, if $\lambda$ is one solution to $\log(\Lambda)$, then so is +$\lambda_k = \lambda \left( 1 + \frac{2k\pi}{\left\| \lambda \right\|}\right)$ for any integer k. + +\subsection{Finding values of $\lambda$ for interpolation} +Given a set of $\lambda^j$ to be interpolated, find equivalent $\tilde{\lambda}^j$ for integers $j=1,2,...n$: +Set $\tilde{\lambda}^1 = \lambda^1$. +For each $j\in\left[2,n\right]$, +check to see if $\tilde{\lambda}^{j-1}$ is closer (in the $l_2$-norm sense) to +$\lambda^j$ or $\lambda^j \left( 1 + \frac{2\pi}{\left\| \lambda^j \right\|}\right)$. +If the latter, set $\tilde{\lambda}^{j}=\lambda^j \left( 1 + \frac{2\pi}{\left\| \lambda^j \right\|}\right)$ and continue checking if we need to add more $2\pi$ periods. +Otherwise, check to see if $\tilde{\lambda}^{j-1}$ is closer to +$\lambda^j$ or $\lambda^j \left( 1 - \frac{2\pi}{\left\| \lambda^j \right\|}\right)$. +If the latter, set $\tilde{\lambda}^{j}=\lambda^j \left( 1 - \frac{2\pi}{\left\| \lambda^j \right\|}\right)$ and continue checking if we need to subtract more $2\pi$ periods. +Otherwise set $\tilde{\lambda}^{j} = \lambda^j$. + + +Interpolation must occur on the $\tilde{\lambda}^{j}$ and not the $\lambda^j$. + +\end{document} \ No newline at end of file diff --git a/OpenFAST/docs/OtherSupporting/OpenFAST_Algorithms/OpenFAST_Algorithms.pdf b/OpenFAST/docs/OtherSupporting/OpenFAST_Algorithms/OpenFAST_Algorithms.pdf new file mode 100644 index 0000000000000000000000000000000000000000..15976008ba4c0758ce66f60b71ffab19dc4456d6 GIT binary patch literal 226733 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 j8sP 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

=1MgewruwsmBjSnO=a2kz*v8QmtveB-J~54;5TZ z*AOTQ7oww^JARnYS28b5ryaW6J6fNJxSHK1by%Gyeh9VpPloy8^_*tLs`;jz94)ud zFBVw4xjm(c8Y(rOO*v9_+9Z;HBEHMLeVo$$=IBzghmJ(&b(N+b-Hrp@`E&;fb4;3j zl?j=0_|Ql9@%>#4(Yi>aNv=6)X`};h%BO5soEOcm7b1s1IEOG#E8~1=(<_h?&}n8^m#q3EZM3u_pRbm`OO*?iQHPwwhj2i8|8Tt7;NOUEZXS&SqdqNcES@@ zY58!t7f(3v6GQMd5f8{x+Au7=zptV=XY1n2V~Z*9l*js%y014hY~?+W-RglG);%F})msG6Ro$F0&0Z{i zjli)LZl5xwHm^+b)EM~Aq8L+AJ=p4`Nlt*MJLMd&NbFV({;`CUB2(EC@5m9VID$wY zUcpJPt(+ofDh_#Tw1u@jtA3U7Jm<%y-YVX!M&NQsx>cN56MCe z!&GPoeQM$M5UVB2loef2+cIxkb7wVREd~aZh+~HNeK6G`F75X3zkm)I*nsHC{xvjR z6u6uzp2<2#a-{JfcX=6hb6*lAQF66K7~mIpIZ3uQd^ey)RaMIkdwR!u_AEG3`^ZFo zo0h`%U&lkhu^f;BX}(kGQzxI?nqueoH@>TUhaxAUO_Jk)v|P zYfqdM54_T_C6N{g9t2NC!q1U%XvtW2J~?u8PD!I93#trNKBp&5H* zVdYebmQj)dy`jSplr<|Q)&%PyQiUoM6qsGy>p{19NDmDl*|N|9^09h?Mrja*=QyR6 z=?~caI~A|eC4G|q;Bv&QDe`UHMk#Xpqz`G^_VW%EEa$`UsduwGnpoXVhe9ozQEsni zuP3{-RF%adBGx@6iFaz6xk0hV_EbSbXUT1`2+OM&18#8Ug_e&7sCAn7UyG*4NOZwT z$HO~;`}qt{0HDNg6H*975j!6xU0q)A-qXk}yUhm7Fgg0uW_0b?#urC4#XEC!bPM*# z88gPqIq@2Nzw4C7L{^-CR7mY?L-7I2OFG5BUW6gJH46X6-wao=zqF)KR*wgJD*Y{} zWYh!g@g0}*y;SUT@5)4wbc3~@g3oB?1;zqB4m&e zE=}z9rE&K6^%*eKibnG7Uk>I3q#II#LI;f5#ubT$O!oKkaGL#pU3Rll7L3cIoo@D! zzPpOfNyC;Yc$?#oC!i>5sIorn)kWT_JO;#-l@g|oed@zV9FZK)R4fob(IHBk=kT7CCzl5fwP0PUt}+Wg5K=NB(>3xd;q-2sZygPhj7j)WsAzsYwW$Ne#j zhwmJ9a!AKin?XL2yvJ%OR7PZl?{!@K%-YQCFpie())*EH4N~hyW2ju@t^#Fx!y+Ca z#!lTv8coz}|31c@V=?j`AVGGN#5C}M@W(8Yq3uda@r@R9I1*9)4m%|1j7FI#EUv+` zT>Im@%q(G_3QSMks2y|$+6;L!Dybcb9CaOh7>sh5+FVQ_`AG4kQHR3rb~(5GZM-F8 zJ#hOitt3n8Fm^rY7q6KfaZBJdIXj+Q+@>|?p0%OOnHy(kwPuZRt8Ro-O{$FMx<|MT zh%s-RzQ)Z+-M1AlGFz@*Z4=HX?v&gu&gau-Q6-X+v#N?XJqelfVu1y9dk5}PoCm1# zbsw~C!h32|kJ=|CwpDn$$E6Pt!$|ffD+)Um%4dpA+2ig<&#+{3k7Lm}GF`du(kD(n z(|F%NZPzUS1JRsJ2fI8bslhk71jTCiqmD|cq-s*kInoqlAz4rsX6ud*!ise8E7ECw z?@9u{BtmO3UMo%Ywp8B!X;(d2h6Q8+CKd)%lie=$jjeBH{Wcwf7QDUuK{Fk6W){oD zY3oP+C??6H{}-DvGBEsa+>Dd)zXwX02pCxzS^gWN{ZDYl$i~dX@PEh|6up?Gjf<%h z0lk=wp^K@Asjn?>{#LgQXqt%*}4Hoo|2DyVX?${U=vWWQa%crs zhOznvzzp_}O!p5=&A{rJm><953UY|)1-8aeO`sGEK*l!KfpQQihOVx7aRg7$X7D|K zPKg6HLcsb41_wod>D>b&VCN7`j7*>v7@S%FHhfH27#qOK*E0eFX7GNgL0Ef38yk7) zk(08ru!|C6kc)DP+6iEJ`(Tf302M&F0C9B#O9Ohfz$mcR0e%;;h=D)_wt_ani zG8(fIh!O4x>%lSrY;*W@bZle;V*}!@09Y|S0}^@XUUo+we%bQDzfK(hXrgI;VPElY zdw~LNevfTTjEv0xz3@xG23GL&!0JE%Qb|uSb9ZyEfP|WJ{V=f=IXCRodxme6zuxe(c@N;?EoA<;=HnlXf zvTy~3eEdO`u z9$p_)o0%J6ws-QIqwJS*{h6Ox;5!er0PyQpBgzdw2^vJ_!8o%tzPzn|Xjk8?cdG?k z1WdWf=k)2P!qJ%@f9HK^G9s5psSlnQGk=u;`Q6U^PgCky|1y7DuWN8}0E)%Nis3=v zyMGJf0MMt#)v$ne{9302%0#!g&EV4o#Nqh@n7PG5`0LV;g9k_+(a-lrBKMJeusZ^$ z5B-wi0VECiNB+U=BY9{43zS~`OU4F}G_^YfXOQ@v)dnB~<-aH{Q}T=SDlT)}drn+> zvHOImd~N>`QSrm>`;>pr?rSplL4W@*^M3bfKH+}%DPjAl_i6QH~l(Zgflo6K@H6&=6&dvYFIn}H_D*fkvr?el<&no*CX2Ol^&4V%L1uM?pKzMzQu~9F6hfZ9rd(Y z!mOGK&K1$di~7x)I~-WH?!o1{&}d^yzloDd{uDIydX<=7%me~5<3a<+w)XXSf*@`Y zCay{mYmt)^Zqu=x+EDUYBuLUY{6(-44Nf<3^~tk-L2k=8a`L>ZV>@O!5al>8&if;n zGC*gP&u%1++1+wr`^{kB@|c{F<&d#ACexR)x{|tAV-uC>tdj5+LU1L5;g;S6J-fj_ zCY{*I*B6iTZjotCVzney=w1zu3MtR2Y0`!e5(C69^n=nfUvRaiQ({Svsdbncl5^_r zQZw1o)W!JHqZTS^o%dQs8H|DWf1sSALFfOtA>6!IfCZWk_i52-V%vboajsgRG`$u` z5G%#!i|Fwp=Olt!p&@uU%jLvL-v>A`Dv#u4Y*eIch0P^>3_R@wU%n9zIP&OQ`33JR_G+8!S(S8!BUmj(XAO%JrGCmB za}Awk&4oj#lX!=&#yGxw=-EJuPE@)sr#`Q??<9~fZwFmSjMrJE6e2$OA(&g&mJdPa z1li*B{|(YjQ?GYSZAS@6iR38T8in4d^=Q(Xmt!oOP_U#2vb z%ne@%j?lf}rWkim6&)A)S^J(1;pR7ZLPR^FrK*a`HO>C(qW~GmT<@Jn$qj!lnv9LF zpmIy+PwjOF{N;(__EHKTH#DU{thyyB`&NXk-s*!&OGQkXP7k9#I7IDlyBIpmm91a1 zL3BUNth;T^ew1uN5zrh&*nXb*1M*k*$x5sQH+~^O*_npGo0+WQhck{T8;c+%47P(`+Sq9KTS9e)6l7 zpCI1#%C9`)_tF_;Sgr6n8O?Rh91b0`ns#DccF_m(4T!lW?|SCgi!#n@E{EKvddMAN zWOcMeb1riX0hZaS=SRxDL=`qKmLds8KaRGgIj2}e;_`(8PVoSoTuH*5W@htk7u$%n zy=|_FX3QyZ{BF@;xvZ4PIVU0iXt*zOiuqJqRaJleVZ{eU#s|i`u6Go@3#?c&Ma|!| zA^orGlD13TAtCTAh@tk!kUV@mzuE08u^-k&2Rm)f%GP|970vW2C1O`GZLFL@o=iAK zBf}Bvs5;}XqJss+RdokKB}b-^MerHwI-B|0p5;KCGHLbl&kpuFV|w_Mp=rT{6if zLrumQaiAhTez2`6$(PTrp7z3KvfE|JdX|F^WY_*v@&in1rxE+OdkiD%HR7N~_|n)< zi*2s<+-@65A}QsS$o}f%fD538A##jjdfPW+{_Kv(>xcNgeyzOWoVvWYn3rRSZ}M*?4_`F} zZjW>nwWq0>4TC22>gn1?%v=)k?leGOE&vh4RO@Volzx-sJeg|yEdbW3L;T(iDf#p# z!KVc9R?9k5!o})|z!u=5vezrHn-fA3R#_lkX4aIUrJP z@^Qt=V3PJ>;6CNXy)|<{yF^bF`z3=LO|@pzaPAZ-I-J_km~{1o8m~19$0{Ff{}NNh zUHBHB`TYv=$SBIj?9JnLHFp;R{&QI>virqp@h1Y~{Gz+IsP?Fsg`W}D5Z%yKQwh4| zn#0r?HJhE)=1af%bvT+Tx_I{C^4Omwae{kw4INyZn@2d$fW^9v+{uaxD;j;9#lLpZ z`7dvJpG1J0ii8-B7u3aXzJUF9y@!}t5dL?lvpS-&X$~GPT|gv9>)0QRPHJQe%nZr1 z>}Gz$>)Gu?C@hsIMI+c-)Tt$$g4y+uLu}~j=df@N#z<5!MnidI**%l2)4hMdRrJ_> zYW~&JOb7A$eV9;5<~6gTd5hoMBk}L)+-}sgp%^Q zmISuDG=5y#=Z{e@R)&(q&xCsYW)4fjGV6%`d8xmzj@+^h-}}?5kh}%ppXm$^hW<9B zE0KCezDt{bL`MYarLG6P1S%AD;whq(9}`~hEvO0Kof8q*=NL7;r+AfW>r&vcQ`iRG zKavxpc~XpcwT?K(D_V?|x|qIi-s3a<#Q+m_2IR3>qiTf30(llK z6ZS@r9K>Kp4Kxz&eA#%RhhlGS&(h>kyuelZ5dMtsqhh&KJ>m6r$KB$8Vs(O#P~H3T zr<>-}{_%wTR>WMvlX;30)GNe*&M5%+b!6yIQbeG|EE1wJamsV26Z8SfK@Cf@!_ zUwMG%yvkH~xPiX3+#D)bwkPBP&{StD7g>8sWV0Il0zSKkVj6HMD39~Bi^R~WnCB7@Yy%^nP+ zE$g^%+o|ok+%&QiRLQ#NbElDD2vNbPInMN%AinwDtthuDe2TI_vc{8jrNr(A`A4vGlZH&ST^eyv!`4 ztpXT;S@St%^8!1st7fV17%GQk5%LG3Jaub)#))Bu@qctvru=2#vR-T-RaS#LOm7CS zFL?#5gbs6Y;QEHRSe3&s-S=oI9=?;LN~_7tujB+X^K%}d!AUQdmo4$sypw8IP~NrE zf}rXiR6adkS08UATMIwgO0m@qC(Q!KUu}WkP4?#o_)YD6qZ+3f`uP$sOE-KRXzz;> zPVE$h!O@dYYQ&&O$$UBe%49rGLDWY^MEsmw($CMU;j)g+%q*w^|Mr*jhRrDyL$rwJ z9V@0@r4tEPY#G5J?o&NkHZwdVMq5ckF%J-5Vb$dlyF(--B`H+TYC2k8PzGYirwh7F zJ`?(LP47M|4kGIB2Fr6vTK&_)zAI-uLvk*)H;Z!6n~oiy)A4Zswikuu296b+k^_5} ztS?KJ{HyZf+(l>JL%!6Vdk+&MLxCe(1vYwye$v8^~1pF%+Zz|p6Q1+rh+?EHK(?0R8k{L zdgVUV1I@VG8Lq5}L#TV$D~}Lg3--#>9TuU99RpV^=XB!r0BM&OZEL@lQ_vW}gNpZ0 zg%uY$s*It6C5~)^f)p(wIksu06}W01vex2+)ab;rmpcv?c8K#>g?shAX2`$m$fm78 zE-ro|i4Po}YWs|=elA`wcmY{Jh-{ymD%%9ek|w}MdzBQh>P_nK=9~b5N+0(wf&n_4 zv1qwgC}Mghg}Kd|$c$Yz)j^(ny`OET`M&h5s(h6FXFvclH&5|!c)j-0@hyVSjO zHG4XCSO^UWUhx1xLJL0?b#w<|D$RB3*)VU8q)9@v!!=C!5613cOB5|iuxQw}ZQHhO z+qP}nwr$&X+^}ssUnj??MmDN>{@`fObw#PN&k!^DRVi4bkj*;m?CxX zdJmD>1=Qd0PsYGOMm0Q@sU6eKGrBjhvGwcaH$YhOUo20Bn!TWH>#|`dMyA zfQ?t&_tAK?^NpKK6iSwvQ!NN`i76Fe!iXFw_!2Al3^`Ytp)6?rYAGFMN!h^+G1AKq z>|CORkb6HGXYbsDq|AI#bM?z`JUbkI&e5Ww*{a z)f|82F6df^qAheG{$Tfa25re#Gq1~Af8=iQ*w5Lg-;#iox<7xI@t zt07SHF>YHxQEux>9-AYO%B3dM_bw#?NoTukQr}Ey!KWHT*&de>&tXy6Ib zvB6Ab)s7+v;+wI|OEe7Cd17my`-@dIn+aXevicH*;7^mWu3A1!8rvn#dP^p}jcdC)x}VSmUK@@^?I&DdRJkqN!+`j!{YJk?U3=PNqx;D}^tchHq+cE`XS-lG@Vp1RcGL9fPJP(#SN-x~+ZBxtQ;)B~`^i zeE3bMR1vHoJ5vVX#CR9i%!fQ8)?DlS{Cen0&sN1Vu zIAa{;)3XsmVh`c)j>sCVU5(Hohn3}mxr=<2C>OW`Q?0!C;42Z*xI$BIO582i*n>tf zf2vB@$Js9~iN_3>WL}ii?2MBAHo7v`tSNX@3}$#g{41g8&qhnef^HYhYOH6?HV+5_ z32u7TFbd4}pzgC#axu`BG{(g?z=B0{nsCQc+A_u4Q^}2z?TtgBQHCn1n_l^d5FqR6 zpusROs5s5#7KmQN<98)118H*r)qD`bo&Ht+WFDi_Q8+?hA(ae-PU-Bk>fdG_l#5`S z@4oTZO6K@TS6aI5$S^VdViVj;JQw{>UuLRcP-Rzx4>$qdQ09Bz2CE1Hy1tKyjhtMM zvb3G7N^=2i)Fiuq+G8^u8`SGYNRmYCJPPr|=h3vjUF_|6ime)Oyl&m+Kpm$Ll(j|% zg||M-3ldSDN-t!!hP?~Z|JXNXgiaPD7)2WQ+iI?`u|7Z{A5>R%UpAq6SX(6-xOvP; zk09Qg>iG>;K{M3y?DKze!_2{M!MY-gZ?SWyLr0=6Q)WpTqwoA<2J4xza(&Cuh&6YC z(AjT0gNZTZ!xJf7$F&vLK2o%_>`2iC*d?}Q>|k8K1tLpSua zUtH-KNXeBMj(U;Fc^_tLW?=U;^R9#%hO>V4-gaBAHAzB)jC zcBT2@t}(fheR;ml;SOIazIMQ5q(w`(g^zT-hukX!rzZ-i*=mFBRBbBE2e;TGaZHX7 zn2!_dS@gneVK2=x_JOhe-T+tD6f_$MHI)(P1dB4xgj~smi*%d6J3|}j)okVE_a^wL zOHh$(AGiTSa+b*4b2W=Up0kooHJ;62!hGEu6doNh2`;P2Li*(Vi2qWj@t9Y14!D}i zBl}+v<|lh`QrtjO3>^|t(*8R&)!WHu%b?OQ=v~eF&93dm?7^SX4JW#k6EDXOMgyy}Vm;t~|il*RONHiyaL3r_sj_&Wmmv2Qh=D zkD*E*k88$(%rXL+{J^W;+qQr{d;vlv*(9J(xekuSlO7aHvg%n}+Qod=NuaXsk%wuF zV4G8R)$74V?C-~s-Hi@5g({==H>o9`{-cOkZme`amvjwe%@=-m?uJ;gKH@m^_PdmW zlptH496`NT$SBdD5ImseR5Duaj_s$MgyW0d4K14OGfG_Kkc4hpsDITs%SfF*wztC) zGN&Fh|73>QU7CKYw3U9x17zGUT}KA$XoZ$xOo$d@w9bkMB(=qZjkuMfHqk6s*$(s= zL^Mj%mQV{^fl8z6VAQ#{CYmjb=cZ^ojq_pH8QJ7Cj8Dr_f(hWICMQg-{sM_p{$|>~ z`?rs~XL8(LKd%@`cJBc7-@O7xv@_4sKsek37IZV-W0IbFGNuj0cmdGodR)|)WkC&M zE});nH8EG_g4ZouFP6#b_tn*yxFhUgvUWnIIF!r zG}BCYTEMeQEF}*>7bg)a)9Y(<2juBX`YG|^Oy{{csYm33$TBFW)nDoAfuzg<3AW%# z^NA%+?_j0Wm}CqO(j@JfgwKn8t0Y{j@F=I&w%+dSCWzgZI&*I9!p@|f{EL=+`IRj* zquL968p}xWcM)u8m7>*uT{SKDSE&C3i~?-efc z6A!xxp?c}@TMOR+2#);_8geO!^XMWPk`uP3w|Z=Ujsfxa{w}rr!>uKcm zO#i7PY0s<3et!0-iSL{814DdT*k}VyXJ{3wV<=Zot<1KMJg+x8BborWJLw+x+&SZt z@fY=Bp`8Ht-1GV2&KOVh|AsUwD+V0e?{MS7<$yplUEt)|&d>q9H6>TIR3QLpOH!AN z9eY^R4#hG#Zc@^5+VoaS({w2G^VR&MuxAYBGutMzwFSwsWZ_OnV!O`V=PSFj4%aRF-gA)Z(8Z%p&B{^?9N$s-QA<~j z;I#4%cvozQ)d)UjxOqE>lT+mNLqL=JuNpAc<{G`0p?*b9hET*!axOrW@+>h^u0-CW z=y9#ZyhC%d%;D^huFC1#iEnB!LTfvk<=|}J?kMwb9kH#vYE?7R;HMQ~6M9N@NYqa1 ztJF-@x-rPYVZnzxvUjDdEr2u(g1F{Z8lrIGBl>@3c9~A|Ni5 z;vQ-VG`iq>_M0WSSV=C=73`8>;ejZujVpxsU6CMy8#i(PgFsXX{!%h><0UFfxe;XQ z7V$Q@$%o8|LGqRSE;6|VP#f+euY-4IcC*MP4NfZe@Fi)i)Dz3-7LKsp&Ehp5|Xu%X* z9g(-bvN~wuq3`~Jnj$WZ$$xHUNbIxb0+01bP}Y&bEHTwe;TR)0w(KpKOg?@m<6QR+ zw^a={ztcEx`1cFWfM>Ov(N`&ce>6EieNf3gqHv|u(U=P=csr+JFC{uMn&Ejzh}#Fq zf0o$&$JgE%Z9P0~Dz0FPG$YBfQPMw}x$DLLg9*7Ao=ZUP6_Nxsqa8VI7_vDe?_1@- z1oWa>@kS?|(I$Ch*vS@Pzzx|IoAskUlbpdFm-1hP(@Ky>qArTF1+~P|v}OFQ<{tc< zI)OuRjm#g--c;6|0Ysi^#O>Z*Wo2?0>7!tN?&$*+hgLP#G}4%>VN@)V(Z{F0!MBAC>e&bDc*|_te#osTKZ@<_Xn^tPIdW)Coq_4CXyE zksCIz@ob;fpYZAm>d?`Gr+Yk3z3k*{mfo3p%8dl-zvf80?=*t#0<+3dXv6D88`cSr zSjpH37cef(n10yV?XJ5GcqruOTFeMRIDNUN8!_$}@ZrJv+*|D{cUxW@BHm~{Qvfn` zhQ(B+Qb~$RPOnU8ISFT=d!xqYw5~@#2xvZ{>s+fJ*k(4UHBFe-Q#&}JJd^F>?{y&q z$|#dl)*D22Hw=dWt5SrB`d?xQA)-{nN`CNu;G6`S3fcgduQo51!nAv1+&W>vRn6yb zkP50MCz?gRwO_)`-~I9~*gqJeK=aq)rt1&H&&unG*&I=|y+}3} z+xoNA%*}yA7Z9xbbkoqgD*^@^48)jrC(|WIlDmw}O%c2NQ?B+mnK}{Ba9xh!a$@@K z(xBhe1e3KeOixoTO5B(duDIO^GI0`&qp+2^h53Nx{+nRI^>{q`io;2F7n$GPT{0 zFVdAvAkZ47DZSjLThSQjNmw}#M^}k{UsCBfbS&HX&Qs=V{V|R1ycNB)&~-uBC+r4r z@d`>e|8thOOiA=CeuEeyq!@>+1mZXYT}o$K?lYu@w~rEjW!If6{HDRY!&B4RnO3XB z)j`Eo=-z1DU{x%w7MPeSBQ%9x`-^0e5RAQMn7+9R2;X_3yjMOZmg*;W@UK!9 z^m;=rZ4Yyw+7&zg(}${>SBBJPm+Th*Neu;H4}4 z?H1ygROF!XWaE}!6=HZ1m`OE&8& z0QdaUNT#bSsd&qqHe8GAS-6be?|s$i6;3comCJ3P7MtJ!D|-Uy&?Zh z-aYxnA_`0OGvU8G*{?lHG}2M)Dd${?@-wF{?0(qeo$-OoMgq`+ z0-?G*z*AR8c02*CN&T$FOEl1;4_oHFoWu-8%A@a+24bY^rqe|0Uqeu^c7ue2n|-EA zaEGsAm(?A=Lm2{1+P&@19&n9CSvv#Vb&Pc1XgR9M%QS0I!H?#sowZ+UNu~EDd~{(> z6h>XJ@4$Nt`4T(p*HK0e>QV*<8Ro>6U zr@92?A)rqcR-3$Qg1nEWsSVHggXeTP<3PI86&FFz- zdj~m<;DwSrMxhl*Xe&2Kb^69<_N`FfSHP(wPxb#2V%s?wS{Bu~>Xd1y3SqZbcmO)X zay|Z@r-E9n*8ed$mXP32+kYFL=u(U$s6J}%l^nPd4ZY4lch5u9Kplc3D!y{&LEp^%)XN{j{i$F|J77CwZ_>4HCGss6;MTqU zUh1JGP%&Q4PibW*YIt8Fgtj0rRIbq4wvG`rPR5|5@={)*&&>KGA^m8CAh zydkJ-T%hVcB;?Gh8GPw$^lkW}Cn)2Ah*1jdVDgv*JRw0F)}H3-f3dNCC_^BxB&;5< z)5*wPEuAP@9m<~3=1u$~q6>;i1Lw0PCFZ4&jyQZ@_kJQh3Nd6C6xp`$_MzkfXSfLz8$K) zkjV+rYzVx84chnKgWclr>`K$Je9>({y(Bt zJ*M{iX+r+X_9>WaIZG!;LJdv)D4h(;K&_#72PB0@G+(dJHq>&R{@6J~Mr+7etmNW4 zXK|ohAmi^IOZC|+u48+gDM@qhYONue|1z`-BQT{MYxc7@+gZ|HB{_HgbwH)FKoZs~ zpWq4B76t?l^)xQ*o4i7)m;8|N5THt+HnybxmWQ7*WxFz2!hnMob3`dsz7`peElKDZEj znMD668kl9vF>9B*BViRbYYx%G%m!u-;hb{iZWye)FW+>2&ORTs`s_SbR`flr2Ky)i z{X7DiABbG!Uc2hK;JT3~2!FT)urf@CCV;6!jt{Dou1ChwiR#-WwhqIPT>B1A383rA9rfRJbr6C8t8m%eR|F{6hAB4#r)_xgA;J z;~>uu7XMKifRjhmCy{||R&M(~;k~K0;zPGqu>OK^kBW1hvyM!bO)&Rqoyl_lGY?}Y z-^xQQrb8+uS<@F=c}*o0N#nZ8-Q{?BCFdu^E4p(-RJud0)31{7`qBzpzRcC#XndC^ABi6LoawJ{>Zn*!hs z7K}CIox>unbFVx8FVJL7vub}ed+FIgp{1j^%**x<3TRiSL++UK3I$&vV&$Kw<1{37IS&dZ+zsqm*MVLNrO|D`bq4tLP>$X7=-TgtT4=XzA zn7g$+OJ?kh%KfKNlC6dLLPqnW@-}KGaSS!@oV3ju6{nJ=aJz7-jV$k})CuwYgG8Q_ zGxirr5w_HS5tj}l)E*3)I4zLAJz%oToP%7vCleCJ@#-MSU__Jf7Zi|YKs7?~b6G-Z5* z|Dtbv^N9tP0SKdAO^Iu=rzf&leZIEF%mV|nJAP^<0|Z#->N{L1ve4N(#EJu|^*fpt zsQ6RVl|(R5FR2=v<~?&J*mYPrjurlO3U|{e?Mc(lrmbf?4Fg3U&v_RT`^NItZvX&# z!vF#H3|-K&eDb~CL!8_iA;So(eMV_dU~+TJVxMkA#%%$A2WU zatp4_>FC11a*)7`n%m%711Xt>d$+Jj7JHeQdF@teOZZ>B!-=UWX&lK9EAGApTv#w= zJ~9_ws1G_bjRc&%IPItr`gx^R2c9gcgFZkYR*{uB>26PMXcSprnW_=P36w;*a@OIL zCuzv7hKnH+T6sCi`=0JvVn=<0coL~7D0Vd{bKS(&nB|8d84{5G)_dy1^ZODsh#h@8 zE+xnga!)n+eB~8}9~@Ju;i14k zT5yp{BL1^)!Nmdor)H)8G3d4@j!J-Z*M3obXJM2ZhtdU9pQIZ>!XRHsI)H zu3e^oCKdD=V%%v|{(i+3{1TLkt1^DcCy?&vy&U+^>{#AYq~$zNIsWWO*3>?2O}6FsQQ|T7t2v_;ztY87CtfBBTn++7cDRMF`k@sprx28UqX0`xN!ave_o` zp(Y=!=_bjzM8w7P%Ng}OsWxH{g`{*Xtx~Yc7A6Wwd+a>~fh$U%%j_5XJTU)J@8$aO zY)AH+H3srz&Ion9s_2Ku$wbUBH`m-uJ_QR_O$?&-A!mn*9ic@_tBD=r)yk|p{Ua3@ zNO~-+WO}xySA3RN8JW~i^i(UHth9s@iro~m{%EiJMwov^fXD5trwU<2%Xv-_O>yR9NL+Qp3=Den{K6c(7j#op*kA@RqiK%6K&M4_W8 z48k88hb}gW%q`Mar~BM21*y&*iCQeNGOnkh+6vsPw_?6I zH`8o`sOxVZ+DM+>l$pF;xz4{lJ_9K%6r4TML+u;}7iKtLiyn`q1AFOU7p%E!U{0Fi zoB^PCe1(p8tViIlK#NJ*z5c=_=vwDikJ%S&L0bLjmVfzFT1z=}SZqT!qQvvx&ZvL{ zez_c}Unlbde*ziIvwZXP$M-XNuAqRhvT4XL#xS%K)bJWg7D0-c-g&}%=)XGx;|SI-;A(%p^1z8Qex@u`bh@2NuTH|v?R3J zo?JB0z`mp!=xX8gCsEf;=VXpUC2(%woc$aR_WIT{u53=``4hTq07pg}Y|PDtuj4l6 zMM5Cx+b#P1SKVe#kZ5-8m|lnK>q`AP{e5why=ImF)ObQ}+!>^=inw8|?zvuj!1Rws z58^&nHc~p0SdTFc7$tWMeJ-p=0kCk^lQD3gg%-?MpOatZ>nO6I;MB#HKZMbAdZprf z?`~NNyZy;=$+=DG`z$AScsWCk5%0+Lh)%XB=j(ODK7e zI^?f*^)&6KhBv8`qa2<0AD40oYT>Evp0mIGJQ>fbBAQ>TCDz5rzZvXuhI+1RMru#Q zU=Td9dcob|oP`)Y2EGhGt3tMgZ+1JS?`p{41eAfra+6zGOZ4ulrth zhkXne5-6Zeg@S{I->AR=x1?*|_{f~}j{@i74h)K;VVK`fD{xhgRL(B29&fd;KK>+EHIJsZYju zCd2p26kkfydvIqI?Jy7aM$|UD`>DYvyZj z(JxPu_VP%|qPcz=?h1yCp85KoP4|mjVLrk8(IMb?{@Xqmd~1G1DuPe5Zdb5!+eaJo zIs!T*9AB}gqp4EAR2)zLmeEzFQuOhA^D2Rb_dSJwA{N%#_QBG+Wq`}m%vOX>OhPGZ zGRw38nql|ATdR4W@pV_HCR$zHYGPMlSis~i+Hp85UkU6@t{}Xd4n& zt+P@LBj}MAQ76+>#tX7Z-La`Wd8zoo=1}mj9K`teU@R|hZA7Zx1Hyv>ko2kwx ziru5n^*_~V^t;{w>j^}wNAAU@X!3N;_B>4k$+9g9$HqP;8Mn?HQY1$hvSATHdrExcZ}%5?55wi_hnR{$ zuOn^H*rJ%Mh^)jfrPAzBjNb+)--abT)pb?2$ee&J3;(oCMPt4Q6ac83C-kV)C=Dn? zs)}&h5mQBr?zjlhLY!@e3|QC1k~91RqPs}YL60<5+NwG?UmXPb9MfgS{Rx34;cKJq z?rxb#s*@o1mS!eSyFR%C_{^TPbbW7gH5UgLMxlBlg+)g#critOfmc-8+uzqsMnzKF z@Nq2)dpbzAZDBTyMx%8Rk4v6+l= zr>AB1KuhJ-biu-0>eJs<-$1moLzvxoC6vkbhcO6?ir=!BnRh)Txu>t43&~4o980*1UdimrS=SmL( z9W&=&Jwk?!oGk>h9oMa&m5-9wr4Rtb)$A^*W%77OUUM&`m};PUF*kHGQleG0y$b5m z0PK>-?f>PAM%+LEsD)XYlV9LRy-v@yIB+O%BDI^S295bpK=SRGRAZEW9$rs}mo#Y->}`<3>vyf_hl-Vg*SsmJpLyv+5; zPom2p1XhN@$)qGFaChH>J?0`NbLGdN&|H9uL+D?rcd4D(`!Ay@=l19Y$#alGQIj;a zfZp{ZvE_(cR;h!5+!L_@`8n{HAqdXop1VDEysF0wr&Uo|No@?V?u53}euc7yF}}m~ zlVO)vS3>bO-W`+K%g%mMtx^I!xr38h{|9?jN&bb@-RDd=KTo^}=GL(czqeyn-=V?0 z^K{qZ2bUk&@1V+|rwf9%jevmh%FMDBvRAdy9Y3R|(apAz1?U=2f6xqayYrIC3TbSU zg*f698*aDxT9q-{RR@5*Ah_1>%z5lurWp!)t(s9Q*=h=Y_(=NljGAX;L(Xe2_dJKh zRwQRh#x=1`i;CuKVWrgZq4b)1!xy-c<^CN% zP#)H?LMh%;W>Zt+vB`nkn$e0JYZR(@aiid;MBNnU%kznSW{FT-5c`I!H*x5>5)3`` zpuLo?$hjo&{qy>|auKoo5moehF_M$iSMrdt0upXWOi@vhfT!@CFe)3>V7ST!(0WUrK=FswwRCtWr zG<|qy&Ay=!y#v}Je$(lcePctx5^lS79;<3-CJgN>5FSvouvqdq&iXJs_wHm5ba&_% zd$r8=LX)0m?6p8S-N7P}(h}eLbuBXlTOd~p!eFjzB2&Di@N$zfCztb7tl*Lbu!|L?=bk<&8`fp0#~ zg|NhS6TT_XY|l)+LmB*gH`*Qs4MI0pLEmAz2Tn7zHgXJVX9XuO2kZuk3H`poD5lCT z2|Oj-rXeAIrz*xiCqO+@J~B-&f@a2Kd9 zJ1)0VCE2@su|^yuv00(sRvCC$yT#4mDN(;8bsL8Uj+=m(eG&2c12&_v30$@9jKy5Q zwOQ7qI;9crH~Jh(H-p*^G6@JY?IGW3+vuF6Q0Oi=~E*x5MP|G&ZQ|8mnQ*6VCi z?(9PeNzB6T?(7oG0|3CoAUmW>6a-5Yr6m%<5J*5#Ap|?IP)o58_?MpZA9G)S)<1t< zYguQz-um8q-g|GZyw)Yx37`4^rt%acUt{G!4}F6dM2G;i_#6TX7z7k#q!e_ZV89^*29tjP ziFrx@s1futkOj~n7KDfj^gwc^Bvb>)r-zrm&9nY#0CwVd0R<%`9DjE%0Y%^|$fpp3 z04{{Pbqev>xVVH40gOwCU@vg*>X3Gr>h|_2C=kbIXW$_o9)O8?bWS|q0Q?#4)B_Ng zpfAs%T!4PCFblyR0)H}KB>Ny49Ya08@3DzW?Ipj`sk+y3+8T!&(#pU-(Jd z!J>n4?EFE0dn$jqkN(E*^;CcKNq_FbR(uZccMNZL?|+D49s~P;{(yE8S4Y0Y0J_Jq zFbIFJtl__iwR9_xr$-Nain8_-u?Q%LbnGT*2q=I-qQCEkdR7en70G}zTZ=F7roZp9 z{*th8!UC`fdJXz}Y1uRk@BK#XpH43QAATM?_mA!nUc~wSchyl2B3wU9nF$pb0EZWl zkOUo_7ueD$2qYfF666(s_GG{U0w7CYWS|br#t;LT7n1i^TB9O>1f%+O{AnNnC6Dc- ze#RF+wvrIQ0%QHP{;d1wM;D&NBYQlZ7q|Sc_N&5$zY5|(7my{zE-Bi!Dp#7VM8)|7 zp9u*Nj(39Jhnr?5>z~r&Y`8 zb=@8A*!{qfcJQR6`%97%5Xd`mR?0KB)k;;0IJn-`lLxK^3@tzJasS$%YV!OD7gKjL zoqn|&PH4tvWsOo^6>rOQPS@!e!EC<_2Pn?8(y4ahO>QTO*D4_F!0Q2xHD7RDX8*hA zuXU&_iTYOOO-pT{;iArccA^p*YC1*Oo6n=2%pA5=9InUQG6a6yQ&w_#Sty777w7}B zZdu140xGsIgY(h!X>ZT@SZ)ZsOG4^LGQ*5&bKsK3gCSs1{kx)mKuPDc36*ulqVkO+ zp+i*C-*{Va)Y|fFv}e>uXe`kj5?6*dMqS= zm(q>oya+DM_!--oiA&{xyzPwdU;0(Z-1N4Xt0gS^keEftl5YIUoi5Y^N6z)_LH^9* zM|H*rzVI~qfR?8$mr3onVnG^~NM5bI>vc1~rna77sIWpxxfEzgdR5tu1&REu(es!s zoODs0Y+%Q>E6!!K!s^xiY3>bG#sgFs&Egl)5%2Y`t_x4Z!NQEyZ!=izHk?k*ybEMi zrpkH8m%kR9AOl!eWmCFSjl6)1XvfuWi!Hd~&w_|(rybDr^nCA9s}$}#pRCzlNS9;M z1Lr+i_N~|Ex+9L#P86v7(kU^DHi!A|(@!SAqS$o)?V-m+7YQf{a5pl1dAbx6^runG z*oBVw$m5~PMu$mp!2l<6ZZU%_;wCd2lUTCQenkQ{|AM_HzC zboS0_f!m|r@Nf`3m*fF-iZsOD^lH*1>^trRRYvZ~N0n zpt%EpSl-UADx#f#`!hQr3&~GK=H=l}s5-2c>CCnHE-&+R+I-ZL0CC&wmZT{e*z-#& zv%)Jv(HCsEp|LTPa7K^p{zdJ1y{~MJZE%Eqpz!i`clmKfszYdd&!i*==0#hNX>aQn z$LNlPQ8Q~=cQR^d^`l#zt?%PTNPdo`V!cY(^o3})er^d%-2Tpl-sfCDN9Ut3$p-LR2X{HLSqtvYoUI=Jc>(RFtu!O`odVF+x)~(x zt4Kg;s*|Cxs}n-~o2r!<$0mIJsT7ry+8eOQa~ej+rLrt^im$BAFe^NFhegofhSMsg|N zkrb|fN#0h}fJs)M#u++!@NBr5lji@KMM9-OkP%7~pN@;Sff8I-C%2Zre+dO+D5?n>;TxA(!w zL6bII4QZ0?s5-C^APZ1_y|lExer4^ITgxpS#}DCH{mdL71|U?bz%vFq_;F$_U6}M2 z4=BDqDg<6CBtt|O)Nh#3qynE;@DY**ltdol9FmfpquRFnl&15~l+Y8kqGJ`*=b{hd zNO0-?NxU2A(`qGFJwcu{j8>ubvYbVe>n0@$g?XHP=RbZ|T@^#5&eh^&3!+V++! zcce_2KYh*ZnF4-nejr{ZoDEfRgg3<>KLxX2hlj`J&+TQ)j@PHO<<(%30d$EPI3iI2 zv7^j84+6-^B86_qUf!vk!1aikFD)DWn`Q)u8)%*_bi?Rvgm-L{AW~(rgz`XNhs6Fc zim5D|uKqi6U=!|{(Oz;laZvpzzUz3B84c)0v*t3HYeiuGh!bo_dUJ5%sjT>Kbd6_| z`x4yCzK`blUBtC~{!P2c1bEmstf3PXqGhgYJC-52AEbU_U0c<#6>iEU0Izl3o)T<# z&Zp_WsE`f9!quOGInRlriZ{^RoNDvw@;a%wC;1#60!F3%2_24+Tev|P$dww=iK zF@10;Mtd=M!#e>jhx`f=W|X0KT?9)^a(-y_VN__%oQ3qHs`hf)VanGk{@tN}AGYw6 zc~Nbck89(#ypXjvF1<>dd>tQV_m+a`p2_wdk!259$t*d;tAZRp1r;QwIhymv8lC6` z3{cAxrUqB++kU6sysHzFjkC}zj^8s4m^7G`t)Z4>Z@ivCTqF%rps`mNTE7l{w6OmR zq&=LbLZe;HpDR%-O>>z8add!?0p;d7!}rseGwiqUkh;(sVog&Fx2VssxAVNSslyk zUt3SPPKCLMiz)G)H^^qff0cEMxKNTQagS(rX6q?+B^X)v1!`ubdkGq#x~xgCU5V6U zk0L}jZkYr)Rcq+?d7A7!g%h`l2V7P!uO~Sbg4A#^onZ2kCGVBUh3DnD<-{r+(UGAj zPVg9~z#7a%&KPDZ%EM~aI%>fBwM<<@N#WkFmHEDD=FKq=y9H_PyG_M7^7!sjrCZ48 z(~v%Ay2H1BVD`>l2S_|X#e&!Arc02iJ7+?=Z{l0*%)DB2HXS31mcQPdIZ z_GfFAGp5LCucF!>XF(Zbrzs@h2`=<3JCwb03Z2fjLKr_5D}JY&3+KwEiV4=(gqu(D zh6jx?kI(2dw|lY?%nVC6<|ZHLQK4d6UrnD1>StebKPFNS+j4Kxd!nSJl#hol$?ILT zrFuT5xSM=QNx*$i-$h(lDpDl!k-+~DaHl>VK;lTP!*w=pASY|)#^4RJ+>a{cdc?gG zj#npcIfE~gDKR^p#4wkG)2Wi@}jaJHo=><*t6HwSxIb|)QMkGsf;`b@mp zez_Y3nHg@5HZH0?T~EI4usjsAIu5M;I5gI2PLl}c3i314a$>xj4$MzMQ`h0Hc+Sxl zrN(`QbB6(K$|Y0R1Iiy$*T6QMD}S5YD`g&TjoBfHukbI85KIk@Z5@GMgJ)4Tu^R5% zS?qBioAG1EuP|r>^-@L)zEd$UWZ^;W};8>zqO#;*&es zSO}K8PJps5ZE5BWGPsVvrA=Z@MM{Ei-%wq<@2$&-yc+0WcP8->LM1Ovo^|ag_f#o=UDYyD5xWkvM$+y{ zTibSOq`vxAJ1Q%m9XkX6r?Ib$t*cqGH8aPI$Br3~kC|g;W@cuHDQ0Gf8Dor@nc0q+ znVA`59Dnb=D~&W)nvwR8uHN11(pLYdU8`!XRKWYmY2H(YZ>=;*hRBSA=0@I3e4O+w~#iSD{DeF7X}^&9C7>tD*R4c zywx3}3;6-Nrt~v!w(VY`hbY^h`mcd(B@xCC1>pBTIQzcOCzyg$7#2h~F87MLo%336 z{wqV_*NX?dx@6Iyo9)=6u8Btrq+rq0nWFUMYn~gwMWesj_r(g2gAByeI3}S=OdTWK zap8W*4;3$EON;r)Z<*4H$F^4cb>oNoXKPxL2yV>6A#EmZiK&|BOphLoksI9l;zxmT z#7thhD3a?tC)VgneN*=Gzdor9&)RL;ZK(*^@Nsf8Z>_?}4fq7J3l~$fObXxy)|P~5 zYp5|BRm-;@hUrT}Tm0G{w(`&_vHN-#O%E8qb5R4b*E1K=m~7)8-`ORO`}JDc*^7?H zHjG>5)RWNzMznZ5^z)=NV9Vkc0zu?WdvuO#t8x-3>-}a_Q{Qt~W0cmoWEJugz_Q1w zoZz`f#On^HY6mB2hIi%&b?+->R;S)GqvD^#Dj5Bni`4~-Dr~lOPOue|WAS_zod5(Q zm9=ccc(#Dgx+E_kl5X`DC!=K>U2}dPN_7vl&4_;yP4Xf_X4D`u|M<)6^=OvFM*vAZ zzCGSkjlS#jz%3?+lRbYOh&6VK-d6pt75`&&jo!~rhV4f&R zA(kQ`R%pWpV_HE;-MEAMBX!Z%Bxp6Pmg4nJCZX)v0p}<<+`;^ z{Fqf+J{C^8BWWIHTkN~SU<%%r-k!{dVF-s4&)qQ{YZ>W%C5IN-%$98EB>#5Jf>-y} zLD?KC*n9cqudn{5JSo6GZ8wSoPn^pY%toEhl~CsJ*>kO> ztK_GRABdL1k5k=UPu_$;%@<2TQRDSupdo8_CapqGw&?1|5)dO6t9gs+n3_#BwPf&x zPH-W7p{`7Z;s9cF8HcSPzS^c5-2lf1IAcE_b!kioLA2Vsg%CFYL6|Ut0d=7uf%|p6G5M=czSx&A%swuWFRKIJm zDbg>xzmB(af3lQ&o6zo$+z94?CmC@OtKHSz>tzgj`kAEYu#Dj{T#5#?47(Dkv^9J+ z$etY9D3^+GJ~3n)&NPt*^5edw-Ga0R|NQPxQx!H`l|EH|$#Hs=_srtgPb* zf{>CGy*dELNai{s7NjA@tdv~*qE>E&9~y>CMQvGwp_bA#zeO&*6wk#v*x z1aHq&UrKp{$=qwen~zB@w-GQjZ*%;Qv0Kz|QklK5`Z&JvR`@oqTP(As+&Uv=5#hGp z(2Gme`stIIW4}h@F04VOIPAf4=ju^P|5I|zfS+vbJV~i-JF5U2?mVdYOhg_)-p#G8 z9nJWwEd8wMeyx0UJUEC<8iTV4(=>sP)eZDpWv(yyDxIOLJ~j^F!1kORi!|6zwyy{S!)d=j9KPHbU< z?G4MYAaA;IMWh}h1I0(IpwqYLEi|$zFKwUAzS1)ole-z~M)nQf)0Bk(Z-6ZRv{OSV zIFjRBcpY`KNMZ3L0H0_o45Fz7LwGZK;Sf0t&ROyy*~Yq0t)NS!qEY^IppJ0p=Y!CU z`c|!nN9%=b(=sLjOj!N!v0!_V-`5)*OUf~x`53YAoOv59HBnF^#QP<6qo^@o+)ghLo;l;mV)wA7NNg1Uje$H?iWclZXcii|bq$ z0)RbN-fH)X^~p?gXPzcQ#!jpq3Ke+%9=N{I4dM9%y~dDx8NS+vLALQqx(7Dz^+#EC zZz^MB{Cs;3-~2)d7y72h!e(`vy4nQbiKsljM2TGg(M2VvU;4(RRafhXl8|NK3#6Wd zRb8VdghJSdw(i0M|&O?{-{e z44?e^5h)E-x~JqZZ(7_l@TGnTi^vsF5tvcR-2(0mEs>W$Pc1b%FuPc2&ttudbcQ?K zSas{!buG{aswFL2*^J1I4X2jRmOO%KuTS+Rd0}p+I_GRX=uri|@%&D|PBD;sgi}UN zQ!(l$232p!jGgWXM<*?EMH(e7c%q7UeE0E!a(0otfa#_#=yTXxDEA%n>t|#vq)KAn zM2#n}ovj;9$`CK7KtYxKOQ(k{dmOt-yO;-?{j)*RulAlG8X*$c+9~V!m=}p;V(4RZ zZ6+FHMdMzEB|-z`cElg7Fg0CrDIsm|qx!<$8tilRAOvgNd`31hNX1m#aUoHTfudtf8dYwca|Xx5rHjCH~nASnUugJ6M0(a;K=rqJ6hko``D=ug3^VV5&C zt*B92!v2Ho^?tpr)h8y=lzdp`+YKQz^J^^9X>~|9kFD)3PMR7M8q)`QB05M%ke}WN zRV01z z2!AP3hh}6r!QW1{eVrH8*9%YU#AZE^gvDO3r5482lh@2{?_!~8=XWTbh(YJKR<~<|~3HjR2HO zTz+eX^c`Ckkc;r-B4ZBTOJ zEr0dN)+YI*xnv?awxmiR)MOay;$#`vCXLw%m#8xpMeTckRKPkrEUQqLG!z`oaT z9%f&73PEsX<%1AxYqUvM*~ z;Ilw7xZRnYLGsbND5MDe!2L)=OZGy%3ZcSYKt3P^ zO*iRL5t6z31;fAzG@-`V#w(;A#%$^I1j!7Z19RU?bbcg8UME@$nWsZYkojYh)8;~R zGgkxgYvg%3U35bHgv6LLbHHklP+`4fgp^`}rf7omS>t~P?T?US81W2JiMRhf=I@LE z5+XQD%EmHRn#vgX$P5oj(-XBgiX*R!)a5Z5ep`Pjd<%%HyjN^g6Ml zU@Zx?+!B~+kGZybP5ssoIL|cDLc$2QQNqA11QGPr#|sM=e}$kvH!wc6Z&dz@JI}J-c2(8Ku1g7bQBa3)Gf}7=Nx7@?9;$mg~wj8eq zS#VS~yOhm-4KLN}UGgpSGm_H(5?ziB+cg(Q^}}tValq)0puCNx=)0x3a|{CLQQs`~ zZOV$($-K}LpDVuPB3s-{ds*F@B{Ku!%gV`x_a2iJm&Ln}z>BJNWa5VxtCIFS<}&f& zbId1yZ-rcv3h~}jec3m3{SE!}dDn*8I|d>^B$@>oOI zYfncR9y&|S&~%TF5iTqwoW@$S&Y&kohMm3H8tO)DDz>)oU?Z!yFS_SZ^}Tur5)-FJ z_jG$y~}Nn*8_Kbw6+mEGVU3j8cLCjcb}p%Be+r^p)_w zlro5ms1DneCDRdi6pv;(8Xw2I4_S8HFSxuMdy;V0nZKTzXkH2_QFJ|sKkmt{HG8kD zVWr>qhXwQevj$oD2lDH7M0Y%Ti|8(`5%X+ zboIZJIFb(m7<~Gwv5!OLEWNI8D{Q`s)V<8j=@th&#~lUx!*|A2KR$6R3UkyFzDNW& z>lToBlyeML`C97)@sGHOI9DuL#5=sv`Ll@fbsEd%a`i5D!8peq+jF9?INE&in+iR~ zvif3zmJ?Uu!BLnjuPDw%f-YVqrmsCp>fz#8)C&&*a|k3sY)Ck*hhpM~P@M?2dTMD- z(*V8xW1jCNr{llawj8Yn9=ps2h^oN3xZ|c=Gp;v2^(_;me3xhZ4z&4x6F#4ZiWY$) zZbxsbtp<6{5$=5zYrrlq}|$frUNfLeqb1Ox#;^?x{-**-_?3_x}& zAdu>Fovgjd|F%TM$U)Z|m{$I!;v6oE-WMO1@P?7NMPk)fU4Kfb6~SULkfpMUv8 z4^T68a{fFTz{2>cCB()BVrOFjF|z;L*Z=1sK*rM56!7U17Y)GL!O+FR+0+o=`v3Q_ zGk)%*`A1R6)Xv1-$O?h$zkLD~4+m2Klf03YvWqPOlN^A9^Pj-Z$=LU0k~Q4wh^+-)@k8kX^ugO@ z=o3|pj0F8^ftA~{CA|TkN>YXlJ|Vr_8sb5Zol`=iy)aKuX6)E2aH^adQec!QBE`6r z-Mu2Yh@tfU;Vi)Ud?6s#!am^%Of-{D(Dyb4cWWqKOnzEzcTK1Y@9ppC25(>NBhd_N zA4OGi3SvcBnK8ldzCdI{K;+dx;v*pL_6SpfC6hvkAtZ+SDrq6ZLDbxB$daLr!aa!s z)DRS+zLg`zAm+fpVcrDmiLk&&0>#zAS{AOttF@sQAVKG7rUh4e@?hj8khO@P^aXi6 zF+pnJX^O>UURH6zVs+olw`OxI{5!5uhPO!4b$i3Glw^>iG~lt5sHMT{b5Ln15Rq%k z2PgvcHH&)Es&}!30_VW7(EreAu>3tPlKlHzRi&!fnVPMd;AHR9P+F-rDir8UEI+bq z#nq*ksV04;g3npXKl!`u_HsZR91?{POXl7ZVipI8T1d7$De&bGa!c*?PFax{j0|Se zV9~#H4Vs{J4m!!}BtWnPR%Qez^6zn(m8w?|^aTm#{^`j}>66N>ew!1Q&hy(sc15io zzJ>n+US(GFuV>=(gg?kyO!pM6eSEAcPC16{zrNSbH_)1SDw}B(EsRsI>1(epsvW;r zW-xj7i?zU{O%v#Hp9BC@S*~%L9;ehI{TsKtwmO27tzAa2ET@~xD1TRlt9`t1jx}^N zh4|#;b|i(EiS)@-tl_Z8w=LUMHyjO$TM9IXhM2`kM|)8t+uyZ$z43J{e1&K$^T+|R zLe8eYq`7)WbjT7`&X)3qX-MA1x8&ElR{u(U`Y1UwgBFmY4t3ip8XiK!^7brr#pLH{ zgJc8na#3USp{VG7Dlg%Pc0eXI%wA#B&J$_SE8<({To#CrSj3BE5Yd-L^^%(55TP+6 zUMOFml83Xice`5^u3mpXHI%g0B8Wq6`rEv~YR5oNRB9ggbLGepyFrgf1FK1GTHB5# z+v7C%X7b}31EfU(DkoVtcgwgr7Z_uuWngy$vNm<5Bl_`IiSR#;kx9I-T%ln$cDYyU z;Z0Uwym!|B0K(T`dX=O+C91zvTf#+HJulsnTL`fpp^OEz#5ByHSqkOS+4YI*ut>ux z))B;*@I!8x>x$6YY{SdZ?B%0j8c466^3b3W5DeF`S&@Hz5`;=g!DQS*MlcQP-rbAr zjhFAPfj8?7NA?Or(H0>?N*~D8Cy~4n$;!^m!a>dVZD{1SHSVLbjH**C? z`PG7^1u97hEVnKODHJ}y8JCjg?gx^MI9Ly7W+ROhGyok#((g+lDl59@5uO*~_Fr2x z8pWL+Jd`&}=s8b+4a>+NIry2Lig{YgJQ{?SaWN!!SN@eW$z9q!pLiu~#>zm_NzCFB z_#-)P4Xs$&%l7s;|2dV~7U8{Mzlb6~eCQ8NOOxC}QwUS@vfS4(7}en5R%_br{>lJ%>i0xjlOm zl%Vb2s(c%?veiQD!p%y2RI~R)Q(Z&B$f^ieZMe~R@(8?DT7ZfwCf=G^q=_Ye9xT`C zpU#+{EDH)cR_@`eP?S1xecG4}F@HI)?){E6X-SJQg~fNgcF5+DGP|ROBvk|ekQ&*w z^-wNdxEhIanmV(cF3QmH!e-RCA-2&z#3-e%L~DW!4-J6guvu@dgM_Ayd#>9s4wWkS zwGbd7a0y*yZe3H9ve!2J7%)s~=l)$vyGnXkV7EVP>Xls3(6uQhY62tm=L)VR;-na1 zuKrg+ZM_hw$}h3FOMt5?@13S|4SrbhBvaolDA{n{zThVssk8R^0_1}1b3)A|b~|Br zG@{>bz1FL0$_)LsTPo=dI+z9Ml4>{2Jf0i1G~Ydi@9X;uu*z+yk$-T(Qrkksd|`*B zn+BR6#1*hg0)`E^t+rqL8ou%D>9oD-^X-(h7x6pm6a69g=eidkH@^FQXVZtfockVK*vNJgGNCCBG=lr zRGgbk6jlOTSvJ4dRg<62LxyZXm#$bn)y7- zTmf7HZW(ao_q23m9I$tg365sivyb8N+QVv@!DFY_`m-i0pxk#hGo@9(ZYs?K!IfEL9S2$E7?SVzdgW%QZ9g}A)^wH!iP@B3zKCg<}W!MuctHx`xC0xX#_Nf zisG!{eFBS6%Z-@)a~8WQK#OUGaJSY+pU(QU3`*|0q>6X`4K%(rjSs6;<1j8!5Sh$c zmurR~tX)tuhrfnV*JOa_qTr+yJpkL3KGVSNj$L2ypb@FsYRYu&VsIdGdHRTU>n|rI zR&<@tp|<@*K_P8ob~M)`6_3<85xBgPgJ6=BvGVA*j&fMn7$%VFn^0t}hCfRFViY+MFElG7 zs)@q{^ORR}FvRl3p8H&L_DYQQ)l~~_kynEosS&~L$N869W(E4<@**-K!Hh@Nz`=5t z#QN(A+Hu?Br!30FK03^SHy4i6h}EW%e!Wvu@<8V>TJAM*TF&Cknh-haY{oXiETf}l zrmKe~x>l~QQWd;Jd8RvlB`EDg96X)rW|gcw_mH|q5`qIn6LO%EXcx!0*e$GNnX-un zJgdR4W6N+UcGD;PnRJS~QIzBRjw|pO?0SmO-<+MZMe-|h>nAMN>Jy(HlpiRdeX^?c z8RT*5s>=Qbbm_VCcLZ@vx;{SW`8*k3T0C}OUhNopHqs+0pUpI3323Rm7FP$vO&FYC zSt{{sW$(CQD`3ctbQ~`h&7YkS5(j1^Qp0S%QD5(GTX{0`c)NUeRmAFkpD%6oiah?I z)G41}APq}=I1BBAdL4VC*rLx*7dvveA9lE{*td zzL1%*qk%Uxex4$J3-3eUvXSGBbt*?M_w|Wb$Ji|h-=5F5&Y5#+9g8>_sE;ku^sCJ%|na)d^SR08K7x+u)TNg(~vcQq}uV9w{PWd0F$J-s&Z#Zt}eE zgzk~XbA{`*d4xD!^DgoCTbmYX!uqo2WzDS@=v2V<*JmTu3@KlOlY|XrvCjoc<`~Rm zhrjA!O_EyKya`s~Ja6V4>NseH%6-u>uR8h*pYNmlW8YVYy!`3*JXIoT%C)$HdxqPQ zWbpe;p_6fd@~@PSket@y3>rld1vTu@>8$UExkZb|RScFCwcI32jJea(N}_3SL= z|D|)q-_D%6skMtO-)VB45mFI7N+fO~?R?@fX zyEjGJHXO4OA8$pZe667AnkH-DGxKxSeJh6x@L$m`JX=4U%qHn1Zx9bqw{|_W*wQiI zshDs4YNef3#?ZRq6?c*q(O$-IpRR+1;8vR1tUAN@bhURK$x(bBR$D69s#F5YTuTzG z8-+Gils~Q({y3e{*B3ZcEQ`yWWsRVI4P0qfwB?jqmR$XUN(K2e+S>%b(RnynfpHzF zZtu(IjQ4=g*J+3{}WiYl*FiZHB%#+l@&Ls~V<)(ev{bZPsCLi7J??D^f@gcgr=GIlG8zk0yo>i#M}LWc#9T|chP`=H}({&QL!E%1@|5#$BbrdOwK z1XlC$XZ(hx=^?u``=x#;{YtUC(EE~N%(vajL>R8ME!EKb_Rt%;D9Ly2T6ZDEzGJ(l z_qz4|n`#}kV2F9|{$b{2k&>2Q^mIo z8QVv``p1>wK+Tq^)otS}oY+0%d}Xz%w(p_#M^RVynSa%A4QJhIrI( zlGbpU=lYm9l|%%aZ8o40wocmJ#`Z(Legk*CIc8bw(9Q`&^vlI(MX zt$gEVrkWOx+YL%>o2aS$-C$I5k9Vlf3e!jH&+Et0jK_HT_KP@GPiQs$Ct&`5Z_QFU zTbHoKqjYZPm48*R7bI%Mj%#$)Hd8_J)0Yx!dg!`elsC!B@7yo#^!zvSMijo(JtVI$ z6a!t_vrs)n$YbNU&f}j7&136V30NH0!t|-&A2Faei82mTdxU|FSDRjEg6VI!B;uL_ z!T%{A^goj!8cL>S2uzZ8CZ_HHZ6JV|8K{fEq-^PF`p*!7Ngbfg3}68;e@-gd+q(dm zfgGRt6s3Q5nAv|?|0J0Hu|xpcyh5L?J{ z7(d{DU-Eg5jH#WuivMy=qnO}g>Q}@a*nV8=>RB=?@6#CUjIu2^2D%P{ zgv@CLX%qp16nQy{mT^zmWZYU=YWqCJ3h~aY@;;B=_I8zN%T+A5fw*H3gXyHRGrj zejGs(oIY*FF`hmi3j-ipt3c={ob1t=_lO7@s3k4j8Hz#vO1hzOEoDK@N8MRb=aYxRHR zQ$^J|lbc6ua;%8x$;v8y-nwv8eRE*aE(LFnm7WKzP1ae#>Fr3fAu%}@L?p0k1~+*d oT%k;!qt^bQz5Jhd!r8^p$;I92^AdnS?987DF$xM%c`=0l0s&1$8vp;Fx2MG0t(0nDe;SwUp)IpW(tF!XUxGz)-;OE>@KMgoS~LMTddGfkA@P zk+8LKGPZF7tGU`4JL8qdVY%u)|T(|fdKT~Y9!-5Rn$q=57Wz%+X$cFbt`SLuhz;B!!R@KaHgONWy z&wN2I*)bBY*jbH7O>*MNA-Q9Y=7!`*Tp217L#AMZj6)&r#mT#ysI_5)-yej$c(t9y z^VU*+cc-6F{P9+xwXd*4wBovim#<6UFbffaL2Ff!SC=m>e8em6R^;t-@bvV<{Q*x(Fxms3+K9oN8IW9sQ$liR^UU)$W)9Qh&Aw}PszCg|1&O=?epnprF zAwiHJ%BP?@CW-Ys44`lyAK_t?|CjEsQD>t%10)JSbE5#=4|XuNa%5$J{{DYm|9^3- z|10$3Xho$iHq^jFnY*CA%Zd3&OmX?oVlqt>YF<9Fa~L&YS=7YyZLdi%)rkDzrM+9c z?gnP(1;cjwC@xmGibJq*1*mF2mjuS&*gHRGpmm6ovM*ll#`-jIK5_9wTF#a3Q%eLx zQGI@feE%Yq)Y$Rc3QPzKi0B1Q4oTokp&!25J&IZjhF7Jq6XNgpO9IR5c++>jLz29w z;&QjqM85JX?2Z1w>vJ?Toi6q0v!Xb^CQ^TI#&2G3nCkF`(iQyCs{QnBQX9^_2lKn+ zK2=IC>?;n4bT3W%xwm#T*YRMAYd7zUuA;u9e!md1`~~13{GUxyP1n1E3p3*Z zDG-ADVyobg)=Kkuj#XHoA8C8V`ObsQHFC+>G7X5gMP3|lA6dhFQN-au4K2lqYRn&< zQNT!GyK6+FIo^VmaY-w2WA34>L&KE&yP_6b6MfgitOVJoR=wH1PhozhS;B8d9y(v% z4gP5d7au;DgJNKznZd{ab=YgSIx^Vl&!i zXG*6dPZ&Qp)$lLWFh!}971US>H0gAw{N*Jp2a6(yp+ctWAeXv|(;%Me@2l!}0#aGx zitsoR)@VDSU)|>CM_vcC|55lBmY7+Pp+RNGuY&QLStExoMN*;6?t>7zk`7+ayzDZ4;0-0tlSBPo5h`H zFfe4m|Q=4G?XwLuc?OyZGWrB!}bc#b7?h^9hSe8$5%I~QW3 z22%1*J_AC+owDo^kq`IRz3YL;WhgzZ7UblNfj4qr=XifnYDeMXlg52VeHRy+r`aCe zmLNI&B0L0-f>Kdow(maQqkbEs{dkgUgTr?~ff_!e)M1afLBb$#_=u zZ^&on2n^Rkmg z4Pjf`K`twOy&)^;A+Z`KAM=yI$aV|e{O#ZbY-{47Z&=^CWi|EId!-pl2LtH8+rMCE zC*d?vG4OiH*hw}ZX!=1kGYL7yUclB1Zip`$i-Y2=0Pm;8q-8kUdT*G$lqDjMG(}-w zUkn#C5Rxb?XAx>zzrfCL)z@3I2WA3SjW+z5o9K)@ zj#HT;cDyW4f)$H%qgpa#=^%{RYQu-HuGFAf)Ng-JRL7zo)>Z0O=v!}){IU{jf^I7{ z->hTF)rr$xO_vW=YxjZC;pha3L+L!-`4OW09yzwP$PYW%5k$r^U}HU>Pcqkv+cd|-gBkmU^((Jg-T(bqgqXj$@_P*f6U_q)L-5~Y(b3G<*vXOg z=?@q5OixbHv7POU3s`)f@Th;)VsuQaEfwuwOJj=829LTiv_4%C+if<>LGApR$p8BA zy?S=Hru21b#+fU02>9S?}uY zuZfA}J;mUhl_;+F20~&lhtdAvep%E1SZ1WvGv3?|x;k7UoQC_TC?q-+sEov}oNK z)>gp=~Aso%USFdKG`l`xL2s$6fVymH>R_44+*ak_2` zc}N3yrb*sSt;9tMF`MJQ`hYwppdMJ@N%oE}Icy@hW+j)CKjj zy_F~;8~AgudO(wGdv*D9*YU0(0PEt2^Zwd&YT-O+=fnBb{<6y>iDh%M%iX=*TubV^ z!m`35YA4k~>bq%>DlS>Daf@cpDW?YZo7d{t4||N}B21=}Dwob*L~h?C;&t$oJO+zo zQYLRADe|p5Q7%KqzExK-YF)&B5rHfg-8Y%tjxIx5od~5muJBza&aH?vc7s;CHY0B5 z)9{z4NNx^}9xyk1R%q1-p3C5QYuGbH!BdBZYOYObZj2d!MeYbXV!T>CU0IzVGZ+`X zz^Z$biS&4s-o!#@msa$God!d@D?RwRwZ8H%|ATY>Z?&!IReIH%7Nwn_PY(-lLiY<& zZDj<+tr~FJ@#i&H1MkF+K?H5Kl_Sfu3BvL zBkvHEZ+D2vO@FoevfU3qAQ}>0pe3WTy*yrR-Sz9^wR_Vp$8D(XFLpwVB(`~7r8j9v z;z_YN_^0cGNRm*T!CoGGsCf7z%h&QW^m0}C4s?HNcO)XC*T9a|_0G9u{6V&hF<7~Z z7^*fDO6X?Yp&!Hq)YB3p1Ooivp4P;uI>X{29eMj#b$RKI3p?nM%`_NRYrgJUz4#73 zDV{M+j!g$Vc)^~%jdCx-G|%(od9nvI-pP6D3Km9r!fP}2|5=hjNBE@Uq$)}NZSkQo zB2j#2CsBNqc_ZozU**?<+5Dz4*3k3ltA{Diaa>i<6mGN)d&HWuLLGuCojm(s*)5$f zwIgikD7;dgCXWQi3Ot0u*9L`}KhE$(?^5Nx3~d;^_7D|6*DvelSCjBcL;btL7Rde7 z+M*$@)Il;0%#n0j$SRcwSF zs>`JRWQvwhoqH)GUM((Oe49^ColVGvZN?r#9ph(>eTdBqkuQ;n*v$;VmQh7mrkjvY z|2Yvkd(GV>E!16u$1PN?Ds-lTBf}?0nennp=GD0}<@t!*`G~Y41;u$f;wuaGkZ0o( z$$C9;nl|$3uVz%yn}vfZYH~h!h^nYlZ2WW|U$HQY#1Kq>l^f;bW+p!&uV3(t+?USh znf4GR>^WN)psgbp27=Rti4?^Zg=01Wwk1fx?PM_L^n@_ZpR8mu8y8Bdz`UrgCkjL$ za}gC%pn^RgiBrXl)pv&bUo1Je>d1+y{bNadhhj=zTqu;4_A|fWom$Y~V6z#86A&CW=sJFA*l{7^(lWu9|UC8f?@lKUe=u(cbiz{m~TQ*Uy6u zq6?4%WEP9p*h12JZ<)^!<#ZX6g+pl=!^WiTf5!fVwJ;!hjZ0+5;2=R=a#XgesDOfw zi45~x_B&I!G<|oIPWI>09I3BqmL!?cIOn+-Njs#~`B6U!)x=$KOuC(_KFM9Fc~ENh zGiF{jAoNmW-VB8LTPq`R+G);Dh~Ix|^kDH4X#A|Ok}e)XIK4nP-hrB|{1u(Ybz0fE z;ls*T_J-}QT*TS#UzoyGXao9)=uOkg%xi+W&aNKVz0}Bmts!vQUEwz>x23QIDXkQpEAL>%jQMQ)QM`w&PhwR%B5b1DqKST?-j|Hrjdx8cH$I?pU2Il9>sfjQ(mwLb?vSu#`M;dhhHU6?%Y;-*+&wA?axNO-%J*=A;p`j zf<<%<1mxaqbXUG>SB!8Lduc$b#iAP8B zok7Ob?0__aA-{ovZrt{H5nOU0P0xQoL z>r5NLzc${D7pTJjH|XWU^vJf9EB-!#!p{nY>19J-S5*+uz>M{A_*2J@K2)|tPz-2u z3VnKqT(8tIQGR#OzTSb_M((ZF7y+5=0YJ>^pMaD-f%_UZZOQ|zePK}MBvwUGr|4Ou z)yV3}*5GgEz9FFY-k6|5B4Qt1=McLiNzSC~FgR(Yv}IOW`3;9Q1((x|7?!3ZW0yc_ zP_iy7$U$yZnbGFyoX6``Dmz}HN0NJRell4}Egu2*HK30v*XAf!ZkLVV zTj>ORvQ~Dm+XF%K^y}h!VF}pnzm-qDoYth4Y~%TB2(0{3B|m83g62oPpDH#+Sd46 zqvflQ9Z|k9_n!Xuk|n|aSi(pOa! zuvzIj>gM3V^j3B)R<6(~@mUZ(_5u{SC+@x@+POP$>hin2l z4J7fd{hZ*jbeOp5($H@OFzcBq3#6c8{c4w@7ecD@x#2W*k& zRPqbWyIp^r^a@)di!1hehIc8NAWKWrEm3X&b-l4GF!JX<{ycG;1P-^T=&7^B1si1s zqc*tD>m4!p%#2*aDXM_&KT`Hw_Ft*A2GTc0VMJaUyk8CWO5G$lxdBwBa#GrFh-j^T z{SHvHAL%(EkxF<*vjKCtdR`wK zn<5|rp{Q&yPudFxMBc()=rK03E>!+GO3|iqp+hZhxY4V`tbL5Rvjh${`t3nZl>t;=#kTcmxwcw9u z8vOCu7S8c>0&&7NegSpypX0TBYFyw^m3B)`m}Dok^%cIge4S8?C^v+STSa3NtdmFa zbq19LMo~WC@=kN+p6M~Q2RFk8zILg}s41F+8>9D?C3qjs`chwI0j8^}d4_#j-O`tR z{aP)>IKkK16|j6hHG_z{;nwiO;ysf>zi@z-e)}k3Vbi_l1@Hvu3x>V|=&0ZgO6coN ze3aC)3EBwU^a&In_8iZJg}(7U*}I>9rVo}Wrb{_@H5?t^@DR58U$n>Eg#^65%~Pc| zFWd}lvY2=VqpyH}*4*L&!Q^Z|l`7j_RA7=chzU@$UFf~U(;(_GL+G0!_O++?Sy)y| zE}BF4#P^6*>U^vgCmDiWmK0%^-sT}$;qz=jT|KEa>F+D!giRWAJ%R(Py6^1GRwXvAk(D^7c=@(~mb+V(ct0a^ z22_hu@(ZA~1I7dZs!Fv;XKYbzhhTZNZ6aWIhP+h7d~(GCNm4*G-CSHqR6YqNaRZ^+ z!?Ut59;VpHOdlVI?hr3KZx=1p0kV*uc9b(b78I8#bol!asDQciEH^M3v>iqfe#SZq z;$8wG{v6lJpnJm*8;#F$E)JC(QO>Ikx^Ec>5})G*6K{j#TX#zEj31H1aCZ6YLMnNq`StJlSFq-`r{9VRtpU<$fqN}cPt#UlUr?>bP z)aD=XZZ1irT`F2fo25Lts||=CES?iOZ-O6U7i4|$w-`TY2z?YEc()a%b;EGYF?;|v zL(|&jHAS;Z4e#al$^iqBvS_y)2W@?ja?#xdjkHz9L0p0!5OzWJ#U2`Lp{7}_;y@9Uo->-+Y2jPkTYROu zM>)q^;@)9&VtKNaq%m+@d^Uk8?UK<7*Gz}L^&}`gFEWebpCc(madt#QtMZCavQR_!9*)3i7QMavqLQso$nmC@v<_07^C;=Ej_ELg zDCCdIC6CrMJJ?kp7n_+zvrpI{Q0{Z^V|hREq$SUjq)h--U(?-{AU^k-O&qS2O%Y@I zXIj7Qw-9PnOID0kY^FKBs<<*Uq%PFb8=q7$j02z442*+uK!Iqv_D2oJBVD?!NqHuy z3stBdUjL83I3O8c%KcH}@QW_plGYEwhedxq*}_q_c} z`7&=}ko~u3HVImc_>pjLOeRN-j2wfLl3_GO0S%aXU6YbM&ftX=RT)YcqxUe)ErOx) zuy$2L+S*263=j{+URHVgB{Ksj? zkT#(O?g$l5#~)l6TYwu?m^t#QI1|EUyp*GGv@Jp?l68X*$UejxlP4|nu!syk+PZLO z_TQ_1D8f>+4o(l&&s9}w3=<(#_Z7n`)V*YT0ff{)>>!K^hR>hKY8s(=vdz0bguxjP zw=^7ET@ZM{hcod;d^ZnVMQKPnx{gz4pN z)66B&b_ZL=YGvLfoC;tpawtc5GX~Zh2$~Ks=n*`>!S7jj)lEd4ahn_sBtP=& zHRd#)xF8`2a*6U7IBk3>oGxv~ypIgW>XJnh%JlwiRCE2{yv?{3r!C(V_|HfWyFs3eUzdz48oNPG z%$Xb=TP`J730$P)@zV~UW7MB9}1jr@PxdKtQ@ zbrbxjXSkfzr?vdNX6BVZchoiV!rW*rZaLa`8=&Xlm$KNVOcf>B@sS0G3w21 z=trIPRu78dwNbArrmhJ5rC0FJRl4dHSE7vEOD)aI}FHNL>KCdw7*K$$EO_>mr06EoWEO6SLhiS`IA{fbPJF-#H^Z>nK-= z2L}hhH$saK7OMsPvAAdKI&gR(>Sdd2Uw<)OLbyS8L!{ChM_dWGVHiX?z#wvo$~9l_ z%7mUtVz$c~!buGj#;D$qu2T;TWo2s zHsz%LJVoAmpeh{C)PKx{Z0>B9#%#n+NmBziC2K_JO(`X-Y~bS;!8H6G#%m-K0*E#^ z%E(G^aGs72{do8{$e8QB@X%(!jhwJ4u}e)WWiMTs8zV`$L^IT&RrKbmxF=1T9$GV0 z4W~IDty=(q(APK3CL#d{I{zc!@eJ4<9ESAmx+dal^VgmDE;KoOCEh4f&}w+}iy@tW z@UcLiIL>H|j>~{vG0dLN4{QeTX74=%t~_|QuD{aCROw?Qve)&2)G)l)xcu8a_t3in zdSh&y6QBe&Ht9#r)cjGXa+){t5k3C<@BE`hX3A0 z7=cD^oppMTat5?vDY)Psg{It}wwIu+QCOS@(y=PLR^t8v{4|eq{xMn%5N!cPb8hUa z`)P!x+QMey0RfwL2zr@2aQ2^txkmxWY&^rO)JLCvzqTv+*V{4ECEPQp9`wL!^@|%W z@yJ@%eX*C`U-9B^)K5eADP}rfQZ8ttjDwCoK!+~E6Mq@cK8>sqtg26;l%t*923$UO zyypEu5ApP>{G#!z#6wCb)U@0Sn8~hBgZ~h?l=}h2G1I0DCt&7amFaB_0WUwz@PC_I zk9CLbyt5hyv9Um)^|{{=>yFv!g18I%QHio#A~z6TR@e1c3oQdkVg|{|*9D(lP`WqZ zB~?Cd%9ue{9I_S1HM&1VZV&&T!^JDm-gQ9?jK{l-e@a!~^bX7_sHd6o-6{M}U(0e|OIWgN=cNr}3Qs#El*(^?pYJ`{N)OR&{FyY{THKV|K5^HX*Iq(8nyaB3Na(hO;Kg7b4z?|i>HXvc0LY2URlkx0kU|7FPA@) z7wjNzDmj(}L3ZMvU3LT=u$|pLIC8)fLLn3Rt%NYQ-hAPD;|nD85mH1Fp7*>bp5J$| z-As5QhZYT?bcO*CkwW-cXX0=YqK~Khv_j9 zcA=v_#HJBTNGh1DhNyfQxIa}~pT9BXJ<0JiFySmMwktZoBAMcxniFV>I)p=Q@vju> zWG{qUSV9WljUqcRnePMLBaq}HiyjiF!`j+CdtUsN0FfAk5HKvDjMq17WKd414$C_- zyh{Fj-<;&YY`zbFsziP(ecp_O;5n_ulO0#ngN%9Hlb<*=XCqR4JxSut9e~f(p*hJW z727n%jF3-RdVc~}l@HknIs8`LwE1T~e*dQ3;$8Yhcm}E0MLvj^&u?{R?`KL0@i}56 z_8W65k}QTLwD6_+RPOMHiR#be2yk5WHseXdas)w$#Flo?de7F%4rL)$061swaN&b~0Z z@mS&ZB|cEHfG~A_tmHSt|B44FtH$oh=;$FL=>XiCRVdhv&u;rM5^0Yk@b%O@Wg2kY zYZRPyKrSl(aa=%3y`6YymE3XNTpd$hg(UWK`l@}F-i}5mAKRaQ__`0K4^Pa`$Y6&8 zIRXm&gC)Z6@B}EaTOc4xfU3VJVxQK`bmsEwGGf`#(RhH`h4SiX_{50bKa2q7pe=TW zOUt*T>rBH%3RE+I;V)i71$!X9XSg=wvpfHlUVv;zwx7RoxSRc9{&I>%63_58unkvQ zmt0g@|8Eda2DUck?VT2UKVxQp`uUi#YT5)_NukJUH#ige( z3dtLfRY?Fc_ua6c7l$Ae_!seJ0%qQ`}^c^Ij&)&MtXaAQNae;6snh zN2Z@q_(=3i>2}%nort{@Bs2Pd-*!H5N_!8R;+r-L>qZCWbd} zL?7NPDg&FlP*DJs3PHFup4#uXaVvez-{D}w=Lo;8j_7Covp2<8^iiQL+eW`n3KTf31r_gZP=|>cLU9K>w36a-pGt!m zZ}|_PKM4d56fLicA5~pIP)Fe38Tog$+gbH#L8DT2gdMox(9 zf485VXY=jA!4i2>0z>d06V-Rwd<=)8N+UTl*&jOi(vdX*`hl^g%k?}Nx+IpQ_{HeI zVx#@>)Ft@;UVD{*E4@x?7Tuth6vLRcZ4xZN%NGb8Bgo%Z^1l(e8UM?hQ+YPu3A#7} zGYhmp%Mp9+J^(GE1uanJT5zG_KiQvhxi5vcr1gVL5a_p{mqM11&*L zG_*oqGzgt8SR^&F4So;bVV?K+Hd7G|twQ;TcnWYvo@IjP&wv@|#|o1_^R(dbE2|3N z@WSDCig?S{BY>3I;c*D;KJ$9oohShXh>5mg4`9(2eQHQ-k zStDw^l!qQP@)>KHU<&!I|Mh}>3EtbOw@)c8p@dHH-}*0~6LP&P^3x24n$X30GT~&P zU?0~JH-}=H_ZuqsMwCcNNwTU9_*)bxt?@H6mw6f(f^Yw_^TYzrQ%ZNca%LuU2$`|p zC!3cysEKh=X9I^?V0Zv@-T*{iLhG_k%r6THEE4lyLHI=i)A-9mR^(!i4v-VPQ1~fe z5C{VM?TR{#b6#6iBlSv;F{lf+$nb41U zm~1;)JJ(<|?29^p;!1`aPub1s@qP6bMw%<37ofz>w#zsNux0xHv!&|#+>MxJqI3bd zCu0H29W#)O5o{{I;peEUQ=}P8YYyZFA`Z<>B$|mmqPqSiPcamN25_X#K1F857Q&hD zXCAavSjU9xNwrZkOR=|y>G9?*iQjofn6OjX?oB89w+f!Ge*7t8y33Bs8jM==#P}yD z$J%`p?IRPDsV$N4{x;-SD26&q41^fNk1b!vMym+b;7({xmp_DCb*T=Zic4<`x_u*g}3ZlBY4{M!pF@P1?O4Ey$R9lw>lWB@%8l1qSURHIz=fHbn zr@dV^-gmvn%k?dPY}-5=o0&npm&a2Vr|0YYcBiMtk7{0xclLsZ96<(=251MrZwH$zSukkzNqrQd7W9v;+=UBHVjOI56u7Ry*=)y_x5yWZC3lR zJTW4@G0%i~Y%{5i1UoFKl~AeMDU$}Pq;h*ZXX2>LZC;!lZd*hf&L=Wm7=E^{Dk^f( zoX`#WWpaF<=G82y)T-V)_Hg7TpjZ~Yo$WSH`s$(#Y?JqRbvxhm)5+nDEtsqp5;V2* z>89$9;^WzJgtyD%z1`jYnVS0Mx3MF)#uVWch%N8bRNnmi^GYFI(uG3M)QJmUs}tk1tGe!~m}{H*BeHIJ z9Us?A2)#dOx=kO32aPQsd#rPTr#6|ESv5=Gy96mms96QJAwN{ld8UulTr^}2xz+LS1#Qm^WnyJli{bj>7jVC!EDWY z+neS4t_4>DWySD`)%~;hvkl>2n`65ehn~;w9l@R=8H=wmBhxT~7BiL?2<4K)>-H_V zudip59E(s6w%0sdZspHi9yEnS1j5i)K7C&BF7k3VtQ&&_on9Zo?F+9#4n|gwkJ5G~ zW{Xo9U+)ehI;k#e%a%BC2f?1&dJh~m3C!;fUau_9I<}p{uT8D4onEMU3JN}2KH7OX zyxv7zkvOlvzwtOgXDNN@8nI-co@W4a+LPuTM)ea0Ln`tCOcsGU~Grp z)K$f~^&sLp-NpBLx#fP@+sk$@N9OWiw_o?$g+k(kv(o2Z9!i&0+YQO@gh6?yx{lx6 zZyM>2Jm(>k7WT1VOu`!6u$Pxrzg2TV=r`MUIEWTI!$bM~&L^9zUbUN?Nf|gqWffLj zjcFx4YlTc9+0Wt$l`I$N>_v!av_8eo#C(_v2j10NNUbAVAj4REZDV5pN~EFB`P9j6 z75CP~-n5`61O<2N1m&zDrEzzAWou1ptPZ39cGs5W>*ug;Il1fuGKRB?mkw8~7Rd@y z0h5Kw?*e!VmBj)M*7(_V(yFW8ZQyfH9YpJvCP_q;=^UQJP0tpD9H5L)Cb3S_SO(}T zcd9>VlF{AM`NLa!>33nw*^{P?z&czUeCToWMDVo9vvJZ@9;&qJm{Uh-5bYF4-H}4Z zbJgbfEbAy4=bVT{@>w-&S(%(aWQjY!IRzaiN*p;-8z~6|-gnz#&FsT6EZ3j|&%k85 z1Ljv;RiANj9&#IGLbUF4F_rJ9KVZ}*$N1t_-uqJKh<4-#S8l~bmOCtvq4`NE4AW+C z=aV32$k3CQ7qB6vlNw13oOevQ^dR#8Yq^(3%HK!Wqjg}Ksj4&}VXTpU5zWhY`!djgwA*k6ohovI)Bw-q7!rDg-#Y@dK`hHMCj!Nk%6^&1 zQgbK5-{nI#25%Y37vNZHnBJsPcRFhg6W&EoYRJ>C}p-A_LYh%-EQhfF3=0 zK^KEytBcR9kj_O|cH$WriKONaCi>i~9$(I8!sm*|2=X|)YQK)LrI~rYz!Rgaw#zPr zX1#0j5XNp$!C&R2EuhRbmX>5na^~3%qZ~fh&?I!i?lR~Z3ue)<(@ac&lgB~n>XcnX zEqXUKq?0UH!l|y%soKq@8LUb0a`*v_DZ%OH@X-7sts=W&AaPG=Q&c#E~qUgSyPnk%y#g=$WmAA%R{i zYGlEOypLTTIG8vtiXUIU?;B>*llw%iH>2mku@)Bmt?(nYQC7&W?sgjaSA#GDzi@fD zP{*CcnRMWC_G#L-FQm{!)p=-q4J{>+%u0{4#L`C!Fz77P99P!D(BUV3K2tViMpZLV z=n~!L_;zIWZg$h-9DgRZKQ^e8Hn*hT$kHI4odo%y*-c0e5E;PT==d-g5-C@9W24R! zoWx*6zMd4`)IywL7R6&nqtgN-!G#$pUc*=#?mMzY*dr2OJ87T&@zg?nTyhM zB7d>L>IzMNUnXsS>xYAAJHDhs%t>jAb76+c$$*%EWeK+H1cHj#c@~U=_!Iyk-ji28 z10QGroKFEHsIUV7p$4FlvQz!fjgksUp-0oWgEql=Nx6pq*)Q_d7ce5J05A7L1?j&$ z9_8QyX4Jd6(qjk%d<;$2Si;OXO`#qH8YPQCt{L-iYIrzB&E48;PNrD5re3~J0cRP! zhd-AJI?ZRH^}zNyh;V^B%*M$9PpU7KjvH_h%}HfDj@ektO=Vaj3X08+Cp3{VNrxXoiZM)2 zCUnh0Oh@J%6$~y3@HI5~i1?;G)TG+8{|8pJj`&nh=+_!H<)P3a(dP-jLu*<2IsJe@ zXA`k1ULpqnh$7sA;Y|E}L1QX4Vgp+k+UE{aWJE|~be{XZ>-3mWW-6Dukt$@XQj-M#WxYDn9f zUX%4%ieUDW|E+<}0Qi zy+zu8nayJ%Q5;n=fu{P2hawwm&Qu-S=6e=C#6lY#DzuR(HkX+OlnhT+Y5B)&uA?K9 z1eXgiXYjH;vSMg+C0T1X7Bo>PI`(=(zm&%du1BEBg~hFX6E)PCg0-H1na_r;03MP- z66(JmOx#snB}K-TR5*Q6JGqK8q%E=qq499-U(M!@D{Ok<{di2RHPg%@joot$!Au_fh^WJy< z4FVHtuAR2L+G$y)V_QLEMpDH zm}$J@kH3^dld-}G6ixd1IsrZ*YNR;n*n<-tiR?i;W0bE*E>g#p3@iA^0kznhB_JKlWvjaB#Z8w!e!q%NNEVYWA`YX8ys!J z(*-`;f20bZdm)r|gmvTRtl)JSpmt@mCx~OK{hlcD*gZ`Ht)VW;7)i94m}-UPFtr-O zQ7!hJGOYjcl-9lqX01+?JTNFR0nO?YPjOGo{4jetn7hbVt!tF?U+*Xhpi z*=QgETecvU&q3?fdF{G}^+UopKt9TdN0b*5?j0&RgZVr#<~8!jJaG%pgV?y4%(owQ zXP@pq0*ab!*&Z3zV&F;}RGFIz&1W!PXmn#W8aKf2a@pVKV%?2Ro zB1iqUbblrRINpZOSPC7t&&HBT`iT;(7L%i?98R4Dn(wBpLe+sc80!$?#jglf) z=f^HvE!R^Hj|thDh*Mp==TphLj!Aeysr!kfKYaW%Hc7#f7Gk$@oLEg*q9M<~>MLU@ zN{bjK34pjByX>5SsF6|a7IJh$0{Tsvl0;Y@8Nj_Yi8*0c6qIh2oUabldL;&9g@odA zGwUs=`P(dJfAZK#%nKZ{{Wv`^cf<6Er711A(q{NZIRdG!-;L%84*F=?p3O|!eI-Jp zX9sYiN^2LA$f^|pnNf?Gsw_Fi>37WwpknMECM49x#fg&Ogd$Z_(oONW$tpaxxX4@-<@A*{K6c4Qu-$z zljLQ8sDD0efQj**s8Q-b>WP*$nb@Bvbc%_`Fs*b%ng+)X^Kcn|NbHpmIvKy1V@t&D z=wX-9D&f)q-q2SEw3mSiQ?0{63|HeUui_NBhl4hSxz9TA$ zmc6>*facg?@^GC^Pla+i$#mBY`7ke7t(oT_hL(K|DhzhBPbXc)!<%e&MbSIKRERe8 zmO|7>re()1gi0G7(pyAQt(gXh_cj>O%EF{`WKp9E-DR6IA4tp&BTS83%xMq*v~+ki z*W%@Ieam?7%=!(qK_!e@<>3h?p+b^&UHD>LMnbL3InS3U^pKAF09FPT1Ps`ITNJTy+URf0Q+OTu= z7>*HV6%=z~M`l5OS`}*AvR0ufkP8q|t6qRRA@FJy?5r!Nc6Ky#yEtUiNg zj#TR+5WPzF3U?{^+F>ATwSl>F=qUJ>DzeMv8vd6W^9|EwoomB^mzWkLBd+t|Ts^6G zRsA}aE-%vW)0g;o3cIv-X1Hj_vY9f2ZR3FT{By>dmrg9fXxZ5wr%aoy+XBsKD#YFL z&$u3muJIV~geb{sCX&nrLqNyxBX=WAsoE%m)c{c}>y)5ys=61=LZ6bDySLzM>LZkf zSsc;F*HY#|kuS|J)3(I9TdU&X9 z!2hcGwcKXLvh4|ta- z)x}O7iw&QSi;o!bSaX%2C313}(t8V91tEB6xuuNmj3Rh*&Mw#Ni$NPy%4>a4Frv3; zzk;EAcbcA=qvU5*6!`be?}2;q`Z?|pQ+>JBV~e}O$TWo9n%o)}8(g$~({$r(?&h9z zM(~-dpq}-8;nJa9lMC&g9KiRfSf)(arthZzx#{3;giM=to0|9htF}F`(s$EKU#F|m z`dzPL5y1oR&uJQ$(z;g@WU980ZiTfNvA3o64(qg`y-pU;47gNc%T4n_pcP;*S+PNLhq{412>z6_-v<_Z|Tf0)9TO*z> zzGnEYC0lx45v}D;JRheU{*j{($-(#;;ck=nbuX((+x2V^1T5@zbADSle@M2_dVREe zt0dxecMe%>yC-|Rzy91?XWQ!GdAS>L==E^68+5q%aM~4L_jnTYctzHFdz%M&d{}2C z6ZY`LVZOUrzpeAWzB#Y6ZM)tWylwNiTAz#ciXEFvbG0Dv$Opq@PhYk+T-1B9^~-h z%yH{J!shniKFQl7{Ly;l@%}7v`Lp{NE7_v=!`b?n64;xJ*_-oXdP2n0@n&QG)>6LI z`#tCUMG}PU;o_LX*YSPQZR7ZUskQY+&y4`_ESR_nb!yZ0@#eS}pkp!UZ0c|Ya&S@? zv?$~h-)8K6-&W^+bUzhOzG4+;VaWze}C~mB%xnf_Q#3}s9*Ppibv8YI2 zTN(_|;$ou5|2SLUjs6Gn7JX54d(5=Uz5bH(^q+{paF?&&b+P9sF%iF~$1lDwm&c#- zd$*#+{T>e2K7IKk^dIEOw|PVCgum_h%X4+^pFg=`J}=jw*qH~agWmf+?}!6`dr`3C z!e2g{&aQuX5?p`#<;(TxU{rZnNZ0e=#s0?Nf(08uh>55v$Bj;}{}wp7Xf?ywcbq;` zAvs!80cG87ZMCH(LfrS^>Q+#>J7%v(Hgs=$qO|4oJnnTb@0@+)`yD2K8$LN`Ib2+m z^m+XJ+5K~0TPWZ5#H?)Bv#%ZU-Qm{5wNTl0{Z!?^PZZuTmA>54?9b7oM_e)e(5&CS zU$O>+>7T#_1tI7uPd8`BZQ?%nk24z^eP#IHujuT><{!>h4%A+VHN}4Ywr&X;GWn9n zzx*j}yr}3)2M@0Z$m5ZY?8fm6PLNYO zqF)pLIQ{Zt6oS+?*moMz-^Ha`g(B`O7yO~@eGnK4Ml`bUSTm*{w`i^Wb&^h!fefu_ zusWZ#6vtA}bA$}o`f^N!ceZ8g9WrVjLGgW!=x?-Xib7Su1?zcbovDa6r!U4iOt)(u zW#^2V2W>dzJ}&8#y6C$~7{j<1C*);Eq*2pcm-j z>-Xz$9G@?@kS?5X#+Pq=zB}?Ph(4f}vU(1O5-J(tkVy+wrPx{g2>LSmsH ztc6EIoZf2nW#Nt|(-io1{+ZhDRdh++jHrDQllGK86|oV2}PT;^n~wsaRm-gqFSD6^&1dMworP`yQV@G z(2Y%fxkDc5k9hG ztmfE$Kr=i&HbagtNafu{4OYn}8YecKPG&%zYXD*Y!lG;#ZOR4v9>MHn5q3XOgoT;U zY^34A2pqb5%CiyNeVg1wmufS9%YC5fzR~4_(S>h=^%-S$eQAFPMV7lF86}G8%9}ift)8n@8oKH!idGFVx;z&@ zH&F>HBdkq#cVCzY)}Bj@U_%wc3pm;Y$$nTK(V`RuTI!Wv;$RP9Bc5-n+5%z-HM^Rg z`Zie3H^_(mJCk)JMSj>plk!2>R<=x0X))@Jv~HwnfocS44k)jz;JYoRHGG0}`n;ab z`$zGf1VYK@0oY+3aRrJ*H9?-H^%%C~s{A~8+hGae z8>YcGJNxJ;b01{mXNk~15ld5Sso}^h?7ld^L)%q%d)>_%O$zt}{WdX>r}{;$JvDgb zQPU?_s;LuRYMi6+ZuIRGP$f;X($N`Gf3NLNpr)TnG;~qVLsL z*u2l~=4SzB9lf=c18D#oxww&Ibn@aI;us6dscukZk%WxN)1m%GSltfQ&cn1?vC-^q zjD_8ppBT(u;8Etrx2isp?RMU@b%lke$YTFuEIi;qO@2hwB+0j*OGgU-fwBda^FLe| z077VGAWp09^AP;}dt5FGntgjx+>M5V2#{gkt) zt9r;CBf*d-by&b=jy*55EVTzTN|u!Ibhq}$1+1GI<xUne>LBy&vx5%%A2UK_N4ZhtWDx`=?iwSHI@!uO%17Hg-jq1oNN$X;<|Ii(;+5Cf>t}Qi=e6T7=RbW#1%7vFT6PVoRJ3zr6wsjL1 ze3Qg#M%w#OwY7QmHT6s71g2H3pdc&U>5qHw+A-Yj*guyGZNMKjVSZD|P*dja7qLs) zN0%~Lfmy)Udx0@pcCa#0U%nGfb2xrDG-s(SXiThH+MiW3MR!0 zL9tvN)9voxH5H3g?PxKL_Z1S=v=50zE7g|a4UDSAI!HrC(wpAZu>ao6HYlUR{cug6 zclx5QnRf4hWX6)@!8w2XGxy)Efmnvhwj8^g*C;vADkdzhBoi45Bz5NK~AT{sv7JMJbVAmwrJ?dCrOB zfHB}`ScSoR_*uRdeu7wG!(BVTnwJ*w6*akrkwu>&tFL!|k!cPYOACP?Ps6 zxr}hRuR|9Crh|uU-~II|y?iYh^j^Ls%jR_x27m#^aBl_(rpG4$1iIbicnR4wBk7|l7hO~KY9(8~Pzo)h)!;VCYJoYfp=rR;x3MOPWom8FWj zSkURH_|FMtkbKJ~8Yt@o8VIVp17TC^Ir&vH&OfN(PfX~(HtS$f%4hG5o-KT;+xK8_ z{jc`+;n|07&2iuRtq2G5YlS5uCd@h^G8iJ~H0Dq(K`+0nGj*zBOGt_M*6a00b~#2z zSvkhVXZ_D8C8sBg%RhrG@|ui3A(bXtM&@W5J~ksCD5F#*oCu=?LL-FHKVzKnwDqcV z&4UuP_AnPdp?Oa7;ugNt3Aw=zgmoL!nYzK$G~2($_FEyx-^Nr<&8;+j`?Q9pv5Dzc zqN3VTlrnNYpRo*cpECCyW>qroflLH$;gq7V-YNmk6UM)E0nSfOx$%%K{QUhHCv`p8 zb5VcoYcFGRTknnH9_BOh>t>snr=6#ql-JvCau~_^D@Y^it4C1IoVT)@WDNne1I?vrF#b~mCh|;@B_6c(budW zL7=bV(HbqnN?rJ8-*Pb)_8nS-JYiR1v8~tyUHvcC>x?8Ij#kLQq2I^J?KKON%C$u= z-v%z@ZJ=IUQsQSab39p#s35cBk`(_eRxJtemQ^k*>?dtpiHiE-B zERPLQ(Yxf4OWxwl>9xoS`PBo430ZLxk%$5=F&TXxrzc?419q!BJDZ#|gU@r)5jp;9 zjS6*bV3M+-lI|?_-lT7f${ksB<29+Uj~t&S0sn{e8@XVIxm&{ce>3^mB1~pM2W_84 zjc)#Z#`&7i78JVj3z*I+ru+e)o`RI}a4tC*%)=q{ziH&5vnSa_aYOi(#8IZYxGgg4z~l zqxtM%PWaA6e4w>x??Y0dLR$@*BP9R{u2ZnF_KbQllymzczO=F!^{)eG8Gyysuo07$ zt?O{Ojz4<0=|)FGS}z|3&ubQxmdp}H0KBRY6ut4Te0&`|!h&=({X*FvK5Jr^?G>oN z(P!G4V`4=Zoe*q^(3MWJH&hG|7h($WOWUe)w!es6vZ>g{rH z)JD`Wd^{lY@XnzyM)Agzt2kWCNjCOC9#TN23!42;OnGVdja`pg;OmoOr?9m}={q@q z{Amp=1EodZ+m)Q0AVbbAYG)To#GyINWTXodVIA9axUQ*bg^^e&Guee@Z-2BR3mN|S zDC_|lYgmX2uXUd@zQ$L7TEv?@BTAf2xI-XfDINOZp`-Gu*c4gI^_Z}D{Fpo_&$`08 zmy33?Il%u{y8^2~FM^4;m{{{1+z|F4JS>f(qtp2I<71s@-^>sf zJsiIo7IA;1sQFXr1@2nV!k;Rrzn(=qbKX&z-NNFAaPn* zsN9>LtYu~@OXbICLvZJ}hUhx~GpdT8ob+lR`WC_}u_%#1fzgBp#ouYDBMmU$F_szQ zSkUo>Q%f{1kcLUBbM_;!fbu;l_ZS?#hv1mrgPCDUZDXzUxNZ-6>%w5vWfsG8 zGC-vKShc&bdhFfOghNd9yQpBDGk16R(x8NG9teu*n6WByTxI#4H#PO59E#Zy@)K=i zjR2fte@tmE*PaaTTclWqK~h$5Uu01jk+OkS?qu-&i{=)Uw@Gv#j0KKaNCE5ia!HY| z5M7gXVM9Q}{dy@5u6oEO`X|u9JfWJ7t^Kep3RuU*cTM7*b66Pmz}V4UG;Bt#`!)6_ z3KX-}Fo{2;-*Y%EwV#R2Is?O^A5=tSRD)$oaqr^~i+iMbNJYfGpjb9=1>JwtJ51(q z=45*#wExqXB7GCm9#Bzj z0%&*?&WLSKTK9x{t~cEQWXe+xJdKSt<+7^2Fd*{#>F<1;O#H6ChhgW1anMp~D`UFD z7Y`UH1YR=5>@gmW%+S(9!`ZMT{=k9)&1pjWB4`RzP)_4%&512w9Y0iHg>nVJ(~9)X zBV)s31$g#6Nkmh-pYC(+HH7tX93M$}L|oH=vIMP@J2{88WogsjnJuaAOO-|cz@#O$ z6QmaYwpXJ$nW*MaP<%4;S?@I84&=02nlW)B)x{sF(Kr%7vw!P7PAEzf9KERFPI*kQn{P6!+lWqj z2?L+#cz<;((bz49V5v8d!KkHY*(kDtyeIIRAR?9>YDs{!S;wCL!cB%@$(g`OVODKk ztKw-xlDCpj@RNi)8j6l~nExjDbO@7Ckeas;{XhbC`yQsa39T9i>RBRdMf+?=ZSgZPh4~G)N{RTvs4x!Xp(0U>HQVkjN%mD1>d1ehZp(Tf`(iGI;1t6)j-w-^;Xi)jglr$e%q`HyBbPZ*lx~FY>Ru#W_8)qSGBuBvGM5 zo3Am2LUME3VesLjEF$rr-9S@_>zG|rq;mq9=%5}alMB16pYRxiPx{4~%xA}-AmPJU za-?$&^9yAY%(M?>{LQTaQf3`Tu^B>UZp15u2-V2+((Y2Op_>8v!RR@YAKAwFISqk{ zO=ey4%f@KGv*;RC)({Tk>Fb6?>Z0!u=G3jw&6aXZ>45c%NmM5oAc5_yD&$L??eQeN zbecW0bSK6cMB_mYCd{6@BwEo4YMzmlsox^XVdU|dmoKXl$_7Q#?ebmvT?cxB|J zL=iJ`>pTl#+qrpkl+aLPiPDhQt62Zid7x*GE3K5B+m|^d`Gm}4r7JJ=?PyV4Z!-%; z)F;Fde3Q1mSn_0KjY-7AS2nBpp#kLA8V3=5DM%I&Hc6-9(QWxOhmk~di~*|qhDFGO zyd9fZcN_W>FT*v+QOZ^BLS6ec@XLHTX1a2R6sR8f`sA^5JbvYca;@MuP$|PKlK0=3 z8qb^!yY=1FHrFG`+`=Ml;Ahg*#o2y0H<{L}7NX@%W@WQnb6&P_l&6jljGLz)h&znw z=hoGJW&agN314GaNGg7W84QB589;NE4Z^2+F8$QHj!LHjIB7C(Q&(wDai3+sN{V@S zS9{}*P8=37^eXKMdw!_ACG6$Nz8F1Aur>cLy>%<~vwWGiZxu~dd_Nd|N7Eo~1!78H z>vIK9X@HcDBF!^GIs%Q3O)8c%X48Im;XE`l`AtOTDi+j_ARDi?PKh0n?G}Y~y2T!@ zO+i&ks>yM2ZUN%X@0pf9aj=n*Jc;hV1xj1PUH8jxVC8X$|EjiGow7`>XdZAyEmtdvEwN##USuy^}Dj?gA{!{(XCYPQ|AJl*e8~HU1Mhfwi zDcNw&_+ooh#2mqWo638Qhnb=^ObJ*Xz#q1&RoCyZ&yl=P-lN&IP=Z-)^kk_tAa22k zKD297s=|1mQ6VUs`ZYL_1UkuKV~#;r*eoK<{iYBUvKe6#c)q_L3IPv~hBL-YO2)sb zB4lMmWTFJ$L=AFH;6Jvhr^uLzC=I{1fC?#rJV5PZ#HB}J{v5x_=PNW8#)Mxoln zyT^twFsYVqmtEa!)g6Yv{yxxE30S60;t!VxZ&F=oO#fQ~9<$bKf;z{fW%2dA!#4z# zgXtbUhyG%P9ur99748`n8o^G#P^S#PHe{QGNK3aib)E&sqCgZOsYI;`3#`_1BY1rk z%ve)Hp}PT;-zk`2Jd%KT&_{d?<1tnGtzK%&L39m-Vq5qUyUjI2Kot#(IG43+HZD{a z07*t)p7|V!7&TyOxu`B+-n=7BApQ*&PS=-6(v%cObQ-R3RIu;`HcFb%FUpJ*+dx|r zcKvD*NhNVFI0TlpsiDE0o8~wiFFCvcTIQ72yFji_dsH-?cvw?U+u8NCW8%Be@KEMo zz|s#)L?pP|nl0J$EuG?rEY=TQt_p>$A1diQa|~E^vRyo%)7Mc)XgCzLAE6_(9^Hw! zqe0{bl(s1a&YLQg1Qa)$RLZ|uXB%xX#s%yreORDgW^{fj1sj6yfho15sbGqbFd`DV zNW%XxZMLn`jrG5a+M(98=@|%7${fb}?I%GDVi|(cWM;RaDD8QBsG{ZjV@P*NbBrv`RpD1i zToD<&);ucY?|%IF8<~S;j8l&8N;b0}K5qmsE0P!$9lwiusO)h6mvlGr z8Dfr55EAx~tr=fd91}iTWGceAdFZJUF}`b_r9vJ~ev`1O;Ud#hyJ7u# zm90ss8gctGc7nDRSDd&}6B&&Bssqg_bZHJ2E}pD^nyub+*Kb0h_7FTut{VK6ZUl%^ ztXh8tr#AmE+R`FZ1I=*YA_~a>{Mi5*0g^zM$>VI6{TN! z^1TF)e2XX7Clm%+6noPs0of|(KKYN;cUj&+@6}Y+s;z{V6f4-6-fKX@5k(}UMG(3f z(eV&P>}+VjJ~l*HXpkd9h1BEbnqe&q=AMmL3f zE%01d*xhO0L_@gBmz(!zNm&D3j=aO@@31FI;Tsi+BL1KC-C4job-@3u2OM2sN1Brm z;{*91(TQ@NGb{UYD84%(1bxVg+AvF|ddAlF&XFZJ`7sE;` zp2Xrhpq|_L1bj{hgPX5(+6!xc-Z@4X@l)-O+)3wY2^Wi`Vnaq zGlQSNK5oXC>u+Dgf?lAkTZ z0!GWnT(PRjEa}D_;o3fZ7LP(68g4{JuBF+yxgs-fI+_p_wc%nj0~G024lzBji` zTG!O~GjvghClIgx>}Pi(*YaO!+K!XrnN-#X$4|VV0L96?WMUJyMImR@Qi0~WBY!f# zz-|fBXDBT@O0aiWS@JKWRVdB;357U166Y)1vUtAXhR9(A9norQlRJ#D5>_n3e3i#f z;+Yd|@|@;KzMj>|YuzD+&=89h#?`<3x_z7^W^BAg1+9?L+&YHYy(ys8LT23erva#H2TpT04MHsESTnmy2ePr{H}Q+s9S zK~`eIap9aJA3r@6QAy&ySqAc+l zB&pYB3r}r@pspw;3;1@rt@`gm-vrCQ@-%9*yLxkFuA|grzP9E)i8eO!1CD7NfMKny z5Lc8|h7fc{Foit1OWy*DD9Ucb9#>ty!oihpJjgFkTm|ffBq&N;l_6TX@BZsLQQrdV zl^OEg;i2C=VcC+jK>(Sut3PTuvoBR6(D)NxfDT4WplC2|vR1j}OGRNwN!H(b%aPYTPL(KTfqoBgR?LnsSaIF;B!5P?Z2VM=GYiR$; zS>`7-cbK|vQBBlq34=rv{V*Jo-YhB<4S7?(+yy?(R0iuYiOR&Cim8BG!U`GsrBAXz z;XgreYu`-sC&9aXeW5`86+!rQNM5mczxX3dOBnJoxx~0zdNV6$PBqh5e{Z2|WCM{a z077?!v1G+x^P}&|1UnHp2l=UJbA)Q9)0q0O9d#EkGfWN2Z*=672TC^%aU>wdI>fwO zu>u?>IdO<8i#~=EfBz{>S?_ZJgBaf#{FSJW)`92(`wJkDvFpo3WN1i}7{W{UUCppA zoy-{>0S80U8JzS}y;^uN3Ru_NSj3mvknjrR+OTLKB>z?x&_Ju0*9w4?IW2;$UAka? zf(<7wvP*5W0ofZpaK2w$;oD!N)QPZIm!1h%2wZj}c9M zM5$UP5}AxxR}(zv^o_)6v)n0zu}?!hr>{1#>vP~p(@b?fKqFN5Hj()g)BYcFZl|ID zSB<0LV|`s=*aDX1EvgySeh}C?>A~FO-yTfBys|jvY&&s@7K!K*TbNkFhZ~vYPP8#) z1=mYXvmMXdL)t6C(-_m6?;C4inqOz?gE^+oPpCBbHh+e)r2pq7B6+lg;F-R* zK&KmJS2RI>M6c)>Id)sgd<9DxGJ`KTI3a6^s0T_dP~RDjkgQIgJfCm%}`e@DBt9gw2Q| z07xeNo&5iksle9HQzyCjIw=YuZTB+n@=B#HI8sm#^}Mu^4$G$0S6XyMhocu`m8E)* zDrYQ~t2V3kdf48dk)9cslmrnFqc8;~wD=blMKR&30JRx6TjqdV1o)#@>xfH(6#$6x zbB&cThS50A?L_^mpDnQSDK$vFX>yEabnV6SDIy4*^wz4TV@I?9pPDsT626OP3J@Et zs}i?>4oyY+PN=TS>chyIrZH~nE0W^mj$J{pbH{$#`Z~s|0+(SDi6AKLcxr?Iwj5a) zv~0)fgg7H)4Q2N;NT?Pd)@W3)e_gohKryJW$^CT2^$3HIE594p!UiCC%=PftUsl7a zZYBnZ(#r2XL_`O>95oi|1F|Up4&!eG=kJjo%`4{rAu6eKu+)_Cj`Tpcp=OAC1a3aX zAa)K)tz*Ht`yG{ArN(~di3qKD@$zenJP*1l@)7q7R@Q4eKp!5kza<}v|5 zN!9cOGUICae;@&(u#Z8rV=fs`e3yW9G^{)a+91S)*fdx+foVXSu3xNYRVn8CU~c5D zwy0okogOIsKlUX)m>(^FqFiFpCRznBkz|1mg0=;3k5wN*+eKs&(ISPY(chbvxkCZL z2xwaW;<=}Fpx;#WZO~uU+J`Wo?)~eej%SaL`{VJab?MN-LZ9KE)eweS>IBaQ+;!4_ zr@^ zNQy}Fm@hQ!f$oZOvySuMw!rjnD^LPxia`$68&u7Jgb_QZWmQvT znuK6L^%sx2=d*txc3d!1GG}|VzVW8z&hkL8eAMY$u>Yt;FaP+lb#|CTPP)rQL~X$E zoop&^negV(t%P}rm_l;dN+Tqp&gJ*){2?Pt&o!-fRAEw?l^Z*Y7BX{^@&2ZBVjE0^kt#LrPh6UTdHsw8TKXQEcEz-?psjSqNV~?QZ7U0p&4P&8{or4a-~-?$qm;a{`OdfM@ga zR4+4sS%@}C8-Wx|X(EMxZV+_A_iigcT(Y8*G6eaFs>#l+>*0y?r9GRcZtvu?Pga?m zEXvHfY>_tb-Y5he`4v|4um7w)y;?u%T$rJyb+6MbUnDG1`GCQKw84U?koYrB75H+e z^63t(_OI5e3)UhQ5yeC9!Pl~^x|4|cLeqJ2uG;}Uk*3P}Di#riL$C37io?6<`|@So z*2HQ!pWa4$sLJJ0q^XDM^(h_aO)YQ+;*eNi_kBSlf5&ua8=C@#cMMGQ%|~UDLL<4$ z2zGfESrXJsSUwIICh}_y6$#6KUreUcc#Ke^Adcys&kUOl13ly#nvB3)(RLrX)M!%) zRxCu)%MF)K*+cb@2brN~zl5yV$9?r02~cZO!4x>j|CGxpsgRwd7g9KMhq9%`ZgmUa zHkefZc>xtWc7201lkg5*m{VB;S|chnpfkf%fNjSj*V49os`E@@jGrYT*#5&)|0AOkfV|CYpNNtlAq9T--b zPsCqZKV6JIaC;jIt5#NqJ^ zhdU`VyD$e#D_hzlcw1a^a#B1k@h(63II@cjinJW4C%|*OQjo@xFHur+>;^BWTDjZV zxll3ouHzj?0`>C#zUlP6MbKT&LinHMS!{PnE6?_4+LUsF$|VOZFtj{Vj92I6ZYhIu zd4m6ZeyjsN`=FYz_mHEPC{trS5xah(jh23Sg`Xw-lsALS6$>__^$wfECJj2&`mnE- zFUct0cj}5#csG)atpM9v#)1f&h*U)8b>s21fx$Znxy@D?45gDqsic(ETtJhe$1w0h zC|KaAFU~XU2)OI@_030Q6cYe`j9v!M%55x_a0EJ00SLyVdaxKHx}PJ><_kt- zbZ=Juw28TR98jF*G59{O%~Z->X`)Dd(BUBGgB>_$*`=g(`pZ}8Mj;~K1ZHu>lN{lQ zsr)wj<3t>|hTOiByc56kXPQe`5k{LQFWZV6&n5fZ!(_o-jR?%pt4HsBp{$oZoF`D^ z*?k5AB%{#0iuD*JL5_0M{593??3>2mJ?YesJ2GPR*}DYSNPlxqyp zE;K$m#}#djs=Z)$-fZ2dYz2BkKw7_+!hEkAgf0F0ben^IF?{5DTgul7satoYs_k&5 zRM7~@wAc^;j|=+Pt}ALxJ-cw!!V79i{`d2&ZP4ZOO(?X32Tx2vzt~{boRN;h)t$+q z$)p&Rh62(9E3dObqRmqUY#w0O zBcdPi#QQ9kWpbH@qFwT(=K1$!^1OLKu%)fnM8(~UcDcoyV7T+z(Q-r$^e)x<4Lgi?2>BEz) z0~(&mB!%%II&k}`U+U|7!IAgbBdr`9_-ewUBgW~MUbdxB&R@%*$gcBKmvvfg_Aeu< zF&ge`959lj{%q_CYS^N-`srsdVxSWpuhl+(ujUid_Jlq18cm~n!Jc=MsZG8_8gp*Q z+42f}DDc^oP0i0GqU{N8VZHD4(Ut7|khtyK!XQz(rr+RBusn*|k-6%;;J6*GDYX|~ z19|6H+IzDZ2hI4-1?XSa@@q=(yf5dz>w4rq(>DG-U$6aabWe<5neHh-UeKJJyZsa< z=yGr3StB29|L3lDJ%D{TthCZ4yLuLS5~i?wyiZ<*QyLX|78@bu`NlDTXzArtVzN+J z&SGk7dZY2ed&L0x{b+$t__9v|^MX*vvd@{M{W)Kp`}Ft*@S0M1@&o(%xz^Ih^C_`g zc?Gv-ACB;V@m?0wY=%xTdr$*p#D!+} zwf)JN$VSYO_z&6$^~Wv0{Vco2X18YagFTsh!aeS}p6@*PIBAN_KBq^|;o5)krt=s$ zY3h$m^ZghF3__^H6SQEj42<66ZC6;?f%&!a4@{w^%40Exhxv+YY}}cT_9uXan-RY; z;gG%)Qa*XMQ)mC-m=zOemz5nk<~L}%RF{pJMVEODD8H+DQKQNiU3}y?=WIGu- z%7Yo@Rrs*N$L|H0<&76!t03e_*RiA?-vN_!dQo1UT-|(nlB@gVPDV!eZBFD`*Rh!@ z-`lM4+mJ=?K&_hFQ=dCg7u3@)D>UN&nYQ&B>|g>+XYV~r0r=cuMD6zauEW00xp%!; zkPJBcA!q?a?i!7(v^GSKu03JiOX7?B8sb7nuu8qEMcdBnf;ah^&iyNJV~FNW)|Zjo z8`amFz=P{sM1&w&r&Q10L!Q$56j1l44$ol`9IKLZgAfl`~u>L>>*D$GVIjMmpOnmnc5juw? zHRjHyCEb4dL{k?9N&d!kc`bFqX4B&n_nMLXM!HE!sXgIkPB*Y15Z+t&!_hQ~QJZMP zn-jfnNYa6#O*P=ZSsgJ={v_n?#ZAiCbt$hX^g`w8?XeawqX|9^2F9q-p$icm;F&?|IZWQ#LL>{NE}5HbF50({D(*g5M(! zH2-;z2>wkO?;rX;sqUxtF02tB<2fb!_gP(J|5U^O3Ke+!-%{!%Fy}XX6X_ncwPj_| z7h{d#aE-@VO~%Zxty`3ot?iNgo_j^!*VS32y6yqI78XRIoU-MkV{z=XM81?TUJMT* z`{v>muCJGkmi3I2N84yllO$9X-+ikea7{2G9dR)^0>)Hp6X`o?M<9^87a?iKv&@N1 z)wS{~A?WnBQ6d;nROJjU7mG-K4*cRDK;)xOTN;v%T zgH)EC_Dy5o;ZEylHC2{*)_9yAgRXC3LL^Uir}8LI%!|=6K7AxDXo){hmbu4R_YeDQ z8d^Zq(hBe?0KEF<31)1XdPk`kt^D>3O=9N2>Rhi6A5HI&!Zcbgak-zz?Xckmk_uCN za^PYb4HKl(FK$Qh2ya@k)k;Oi)~ig^C0#k6=~+=MCXUnl^0FShcR%!LXLLBL-^S;p|9>T$VgIwvtLsz#BHVz9ByX-&4Mq zR5!hE*CZqb8Q`3g?zmE0#|9QKG^L-}>g&cwa;w#IsKX6DY}weivvv?<2KvzF$dBnh%iGF(DbVOT_~@i(6=yCT!v@M%@Ic$V&+ zTX5xyE)IoXxrhrLah+Hlg(fZ}Xz^AOw*2I-zo|2&4!3^c+z|$Tt%E-EU|t)0@-yS( ziM4y#_q%Jh%+O(Bs9732WBGUnVRfgYrqKhg29eh^tqwY#4E8;VGitGGZ2>_;K5&rg zm32A5*|=Xvn)NGj$f$D>d@_QxaUwM<4ABq^;ZF^3i6u2DO@ROFRlJLsohN7Oi|ziw~~S3 z=gdAAyVgHidWn)yZ200Jz;(<4-}y<5sqI7@zupWAn?+g!ND*7y*3ah;69v7nxH5Rt zt@Jg7j;ye$kycHOt8-f=RpE4$6IH~IY=cRKKX7&W@TBAxxcgB|N@@sMZ8Le4y!?MM^i73Rr^(nO|NU4Q(-#~-6k<==;HwlP8of?iWO(E zxs^hD67{&0XlMyn%^6>wek=b&9Tu&+NVA!^v47OFHIFNX-{$mn@G`q-rifwGw62#B zI4#b`Y?bW&or^xVYL>;~r(Eo6LaO*9??T2$T@NqMNjQb;&SU8?Lk)8D{!&@D`MU@H z`lefO55b=hUO}|3KS|Zf9{y&2S4}fs{6iTqAq!XOE74^;1X;0aKc=|{IhEs|fm85Q z@YX_Zr0H}4=crZY{JI~XE-v4;vt687rB8LXWO_?{%E|d zi$ppMTq>n44}6UK0=)%>C}&)2!W{$&vH?`gqS>mtf$WmK>Wxt6K&J;4yXRn0L2Mwl zSpI8!S-E55m@k;|0?~N=z59&~0)=hka`whPrgrv9flR^{91+egw0^IpL=2+8gvDDn zJz@GyvluCj$&26E`!)g>dYzgz#gd4MQ9UOpJOC1${z`DCZJLq#xaH{&^!!+sLrsBV zZ~Qq6Ch8nSCaN4RM9R>;EiCTz^}r*N2z2TRGhmt}Tk1kyy^6bL=_br^-_}>Hxfz&E zi1>wULm!E2Cb1vpqyl{n2y<7E9}GLpuW#OW{4^I{AA%hajD`K6W>D<^XPN0==Rcjq_c z1-KpSNtj2&b=5{Mg4rO$KXAx<3E8G%epN9wiB25suNEh`Gymb=H*}tH0kN%EJ-1E2 z3J^b-dx^dHk({zb|0^Ht8`%BuOZD<&?#Bzjh{~*dV^p1U$SHxdCAB0j^vZqp65?H_ zr*)=Yb>I03f)VcMLh)Z)`Wlh{z!Jdrn|rqhZ!}l_NWSf?xK0;Y0nP#@xR@A+ z7yi>P)wsr7)y!;H$XL+@b5^ICPX(J|!)C7aLU?copr3QyJ2%EXuVC6H9-yImU4vq% z4j>;&9E+(c5SBq8EPnetGBsj|W;V`$#ei(*)^h*_! zn2NpW9O)#y?n3#}Ot_OpmXB|S+AUeJVv;Gh3Zbqf*M;yo@)lgrPNPqaOK69E7mbKR z!@N4rkTd<}W#R^0r>_a3A;b?N1wn~q6edyTIYk$q7#CX(H$8ZIG_dilv*(_AAsYX7mU3I z(RiDeq7USKgQmVNrKCHvAc{|7#<>sUeL1W->3wL>z-!=jc{(=W@3*Hi@?c&w|3K+$ zyF#x3VCl)kR5kW5>d)Ez+G^-8RfoR?T`ve3*08<{acZ>e@ zI1s=dox9$H-&z9Fa?4p8nC#!Aw9on@ZfEtwyyf%9EnW3f_(ka}%x zQ1u^-+TY6zUe<-G1`l?S-sRxOb-gBy3lGoa5swKE#q~n-y_2UyOse19XI?7OenU8VPFllQmZ3h)SlD)0tP{(8qz+~Qhgo`E~) zl|3!nr#YV4=uy;HSp+n@{!s)Kgk{OZ4tZwE^h}tLd6(@ui4_SXXOZi*^3|zbrK+U( zuMUQvJ3m>Wst66f?{Djk$|hY^y3;4Iyj7uQ?)yJ8FIN5y`}MGST)6*#z7`nzb`o?^ zE3?Oe!M{Cz!^hN8eV4;1e#TD%Rn4II^3U7-`*&%c+K?=*o5=mF%x|mztW;}QQOKOs zc_BxfFXJTJQtustL==-|kdS^L*Xbho8Har?44x6X^FT?Pzh_K>ngOk#Dq_mA`s1vXWR3LiysUc&G&^6vcCIJ z{c~6VY4!I4-o^;6%9D|5CuCIr)*LK9vfoTKY_dxN_lk4`z_ zCUCw{+~kxP7r8lfqHdmEpRu$vl<8h7oe`=UR7*{Ni4sqPcK&CP!r?T!sK_JyQ*|pH z065}qLl>f|C4MHqaVl!_3e0M$9q&cPlIOhaYA3IDZ$QI z#((?%j85bUlJ8lQy%c~X1QP|&$ zDBRRd^9&wL)Ozm&1PZGxP~Z1w{(Z@C^qvs`2rEXrvl!Z;;PZdz`pT#}f~HN}T@&2h zf_rdxcL^ROI0SbH!9BPH33AckF2RGlyIkCz9rC_=cF&&u{tTDtuBxu;p00kXrl*y; zn=CpW_Z;ufo*O&<7lpTu(bs;4ADi)Xz&cFXH>9tv z46|<2BLC=R=Ve=7qQ<#I?QsyhPY}r< zgRV-$!UNWl9Q0Oav9{f`pc0uo552ZQ)ll#l*!@S!J$Jv7SWwpdJxbmb|JH)QLD5Nmz-SanH zyE}1TWY6O{(M|zDtp>Khkt}8XAIbu&gWinNsOE*=nGX)B&riZGjr7OaGxcZ~yPfe9 zhP{(eL&{yNVO53n%U9ji_omv=a{FkRZEy$ckbkY)Amx;sREH8Q)+l=@u>0Bi>%8|C za2(+FQk6v7bhoN*;7Qg;{ETXE!CQ8uo<3G~D_b2x$8RK4i}vZu7lvEeRB7LJ(W8|v z`C(rA6pV^);N3CNqhrOa3U5aTLju~C-h^#K+kTtZGJ}*Mf7I1{)m8nDl!D}P@25_& zlQEV|*ZZFbWX96q#{%X_%mS(r5c!<1qffO_CG|q?qaW&W&B$~mL zp#^H#O`=Hb!)_ByoM~;uHy6hAqt6^R;DD?>6rzgow-6o_fi3XieYUz=4K#3aH_Dum zuN#^x%2zhLqu&2&5qq`Z2aIwZnd;ljc`~!gKzUzYTkqX6@htejdY`3 zzqt5Mq;Lg1KCE4}X&$~YPKWWM##xRM2xaHnm45Y=~Ut_Cls1X;vav(bH zM!>7C?fD0oXu1>4#prdd29Q<`{3;&~3{Dd_v10S>G9gk>+FJw4tyhA9C#iWWI^`b5 zQ+zKG>RVqT@khewcjYn7C#obrd6f>xm7aMI>V*eA^y3tVW)b*=TN9EyI87h1HzE?0 zzrm>Y@WS5b+YJqQ=(7#^Cd@R#^{IE;s6E z=vbrqDRY%)ojJQ}AW?og|L2QekXrRbyq`|zwfI*HV|OKtO8O{a;e`i3k#yC69Ds+> zSxCZ&y$Y0!ZO#?NIFU78*v8Gx0Rf6riAq}UD65q)lT!nouPMF|N*aWt`~dO#Y$=X- z*M$vQY*l4MmV7S<%hZ>5B!({9O>;fKIF=#(7?TtGlT5p+rV1|>M+isAYbA-;otK)W z1Mc?^pJ#XZT3FgZ_=V=qp?0v)3^7m9l-h?dUu+zfocB&Hsh3rI$b&bl_2R+VK_gPc zi3I#ykWrrPWEts>NUrNX%Cg^_c;#tMH$PU{ZIf4Q&}Q=~Yc-RU&CGB-{Wx8$3=UML zvRzdYA1e?ZXxo;ru{-Eu$QUSK8Z@y`Jyi~>G;zOHn_`_{IG&HcR4Gu~XtiXfiFd7P zr~iD@`+=v1eb1sg_)m!XOlI+A@n(|pwnZ~|9wa)}M<$}yzk2|cuNisVO}gsu^|##F zuHjoz-7MAuasuKZBZfT$1mZU@7+pglo}{){FRG-7>S=s(gWyHkdf!8zAgaL<%t9^g z95L=#_cDTrTKcHESj?X?5=bL>d};DEzWK@KYMqCN+Jr8xB#6}fbj;$vI(t(K^&O$G zuu45@n!Om1E=z!tNNQ#h`t>u~*wZ-;ZDUxQzdT(T5}*Rec{rgcqIs`}W812stW+jmogbG8_0Y9ttf`!Pd1%E? zl8M%iS7t4_mhol+zW4(BvekxnJvd8+A9viimaZ%W7%+UkIrB;AMlgP&mhv7)e*{in5mznDU-!vOo4{Ap`34I9t zf>0Vh^kv`Zc^ON>kyc*Ap;9!4{MN7?qH8EfrsfeC*^&u2kxJ_(X;xG?s(z9-AJnd; z*=?9S`2&lAt}u?Dh6qY-qtGqwIyz)UTx6WIBa*_zQBO9WU_=@@O=!pohgS?E()Ol4 zv8|GG`u%j3sk_t2A8%vbIU@>BZiw|nERg{YU?qx_d5{m} zs>e}dw!KuK3W&(OMmr>8mOmX@fF}nR%nh0$C20`7@Xrlt(?m7MZVkK8b7lOWM||KJ z$JDLbb21gB)*wmne3e~M2=JQ8Ami>&hVLCx!c{%@Yn{iecUXzrCCWaXu-u^$bHq=I zVRhMJYpguBLRGx3%hQf{@OEaxUM3{}5fqHy6*xepGA{W#;@uV~w}#7$`qDb)6CUJf z>}9rvrbTesb?CaBr_y%xNL*^aXqDXFbN^F2pL=aXVwzO($EgYI2jlQAF|&nmnT1;c zINNjL3lF_*LY=2tp}(|hBOU{cVk2Pe54$rX+g9?I&qmU-n*v0Z552L`0_$AH$TscR zrP$WkgWxDB8g{dQYeW$K)04T|4th?(8%dAvTj zw68fCem_OZfn#PtP`GV6O{gYk)Y$_&8d{hC^%x5`Zs>oI#Q1@C*y+_n%*!?7Hk--`(=+VH}k@IID~@;*e~EJmO~mwjp6Cjs+M8!^#9K2CQpc;kcb0Dhl$aF9G*Om2RjIBwHz==YjbEd+b4 z(Gwgl8MoDiPwGVy{qZX44UK3A&7yPnA_UpZ!oqiqs$<%0wHfA{4->dyad|W;7n{FE zr1rB)6gB?3i?{`MD0tVpILVHo$EFv+akNlVgL*hDrs;LHiLO~x;4@e7&YT&rM+`dU zxggV2J4sjEBMOw#K&~wDj^7$!1h)_2R+gdl8<0H>cW@t7JKty#Cvkyi+BL98;4y^o zD#4s>SlSSsrZWo4NHlA@Mzmw7SQT-_bGSsj$l(l}I_d^%Ti-o=%Ls6PqdtJR5$+-? zIe>B%!4gLC62N)aZy!2WVHijXD@X<3=f>~P+>{-c$`i#Omzn`q!-VPG2FOc--@^zB zO|_tLr*5iF|3O*>_WGtaHnH5^1*9!Q8J+Y6y_KsQ6f+qfNKkC>etGZ4>q~s4#e|Wl z-#NSsXNhsvY0NTAG@pdN!L4<6qe{zJOgkoG>;PF=0P3&AIm5L^nGR*Bojka-%|9;i{yDN;6DD5&a;#>ES$@#;kbBklefHq^3d?YizeXa#9 z929I$bNlCVBoVgNcy~YnT3F9QzN}Hn8srGa@df6j0jG#I;EIF!Y+PY=MK}QO@#pd7E}1O26~;*10k zi+}cV_3f?5#bvru{@~8yuQeDf4eU(mkoH?5ObwW`P!c8m#~FP@s_n>Y%m$3Iebz%} zQ9A*ETcP`5jvuO>IR$)&b6q8CE-owP2rjuvW32W~Ge`7#)T#AXwBG0f)=T9zoST`B z6LV`8^REnR;m?Ib`kZq8*5|iKISWIiaTCxRo^c~Ag~9n>w}QUxhy#^845!cXRZp5< zXH6LWMWg`7hUkln7P%X;&~7n}yW=SZL+D25d0A~*prrMpPpMZ3Mr~HwFWY}0_Wj+6 zCNr>h40wykppFTv_TXfEb6_Q1+-}<+*-w4>M`VrU93oWEs^Pv}--7&!rE) z9;Dpsqzz1Wr&a~bTQLiDL@ybqDnq;XL8Bg3dR)8L-}b$GHuf_yPqho;jw_e@Q-}zT z>;*uY^uZ#G5%;A*4f8r^!pPy0E>h#hrvka;gQTbS-fPc!kb0tkH*#8@DfiUl{37^p zd`Y|>_Y>>3zU@@lKS~SZQWN$|b@h;w$Gh@U6mz(jXVE*Ke9iXRgBv9ar%1a}q}39$ zKJi38Y`Bt`uj>b-g0`dfUzTE9%#&q4ioAJ>56Vzbg~+xpG-N8L0^8Gq+WGfr_!`vS zF@Ph@tEhb@9zpx_>=&PB8jH*hrE4iW?P8Tcg@G$uH|a(Kd|gJV5#;E=ZnX$|y@l5J zH`QgKk@1s0SFscpJkT`!_nVZLzd`$tj2NGd_C$9~FwiRBUm8mi#%*8hEbg|D_=B>~ zhW`+Q1Vl#WHu%Rs^PWB9BK&>?h!ju-LfPtwue z>_d^IVhja5wlBn1@PU5IqQ@q<*X{FKVLonI@YQgOYhC3&TFtVkoUsB3I8ni@J{h7% zCfD1;W9G2nryo>e5ntIDNi(Rs5t+9@XEsTZH+%yW+qPMm(7K2`iZbtdlX-g7qe z2$WH3%Ywl;Jq$zk0I8rLrdjrdTOmh}L~WkMGOk6m8V);rUZ~x&q+wh+-J4Uh7DyUX z!Ey`7TLVgss&=`9DSG%3K$LFqhI^t7kp09LZhZx{66<+=9+J8RB)GxdJq%)Y90wwu z{J=6p1Yy%;xy8|N{L4VQDY+9gJG#5SuC!5n*12&rSb#%l3O_7B@m}OJwyyQsX35Ja za+%Hu<0nE=iN)ZNs0&qtO5P8!gAvek-VPiiWFscwea&r*<+Xzvqu+EShD)aG;mA`L2~(ZP{C&emqGYDW+{OdX8s2}BzsEP2 zxMq>Szam;jIt4H8nWS_RAbYwIJ8+0}YEO3njt-vv+ZDiqv9%^3RgMlLrz#-T0u7kI zHhy58eRf%Ycz*i*=Fo6i&fX_c+l8hk@?zx%1XPyzQ$j{g7FK-4cDFX(-FGO(cWF9~ zexzVi)QWF}f$@=iCPXkxQl{db33Hz#m*=@#O$Q@QF|E4+o(Wqz3I^zrj0 z&GPsOFtI8>eF06aXjBegC|K5YYv=OCu8jktNF_PYlb_{3cFK0|y)ukV(RMojBMLU%^zKh#hF9O|M3&f=SEp#9wtFn6he z?3o32vY;qjzSsj@$UfcJh3$- zia)Pu5>g>`vL{LoT`Zhv^a9tYkzx=9Dm(kYP&zL>A1nlA%z-E*qKawFtJ67b0MCK& z&n}&WJhc4is4m1B_;x?AIpML;@Xpxhx=`5OYzoh*E%NK{5ntp=chXnSVaXIDI|8A1=-@7Jh!XgjYYSr+fH+BgShaemw1uC+JJn zFFCtp(Njr!^Smyfd$G*7P zoKIwWm@R5+dW{mW+e|a5rJQn$Rq;1cL?%8@@X&A{IRqW<^}T5i=vUoLYGm4}$&Re( z=xsCbqS!zjO62!D(03FvAGW(mVA+ne8Zv-g;X@vOZ=`)D6^SCbhAkNu7Dp=y_g@JL zo^NQvxOf1AaJbl;-anI$z3vVT|9!}b9b84I=Kk}zoLRe4JUMsDqtQ^Yy&U`~ArU=0 z!sQG~BuW`uTVC=XpDYS-yYk6f(3Yy2IR@6x_jPz$G?X4O1z4P`crR z@j3%$yBVI8t1DWWl;RY#D4^Yr62^!5)>_bHL`fk(lZ)7zYBG=kIHR&<0D@TH>^bI; zVDek;07U<0?(eDx&92$6L2k}`_}Majes5EerFnRVe7w72o?-6gmU7`9({|_w^?zuME8dgs#PIsd&qTHnwYiu@6fecZy7x~u z55op|qapw@nUF~3?m;0yDB`A`hpT&!0z1IRmuC366?d3IGyRh^@)ez#tkh zcL8_s$I7}i?JFxen-?@>p{bn2L~ikgH&jM|u-mL5md72uItt5yorW{V=)e)jEq<!;wNbzCJDi8%@Kv(-12XNcqY68tGTx!PX@vTMK@3X23WIOC2&K-vFhU{!z}Lg0`nmkxP~xi^ZJx`f?3De+0N4iy^%bv?S!} zA0Irzxqc3K+3AjCrTi2Y`>^NAUbooYeBG1gbx-!GfPSk;u*$2JdmF86LoRnPyb0b} zdSPvXUrs3n2hyDjr}Q%eu%W9q+EFM2D79xD^We7br7W}(w1`snR#E{VF~B#Gp$e<-HdC}i&z)L> zET#c0B}U$0*Ny(72hzY!_%B@1%<5sv7!tGf9evTp`Y$4BZn6oBfqEetRqX)$)-X*d z;Bi+h&*U2_&eFfu;u;x-FQH%na#@6{9Hv|9NK%d~&8MF+H8@=uTUk$N{!RWlU=wx0 z0KMiqlA8{!IoMJA=*Om$CY@|E+XKR&0QBfWN`?%=d7{Quaimt5z_4<{;H2-;91Yz7 zaCJt9u-X5?ei*rnX3$a46oxCj&#?{iejmOB#f}!X@hpkPUJy_z;xb;ji8wMzeO>jM zjP4oF^UcyB6rT+F6Z${!3PUaj&o*3CJKow2?*_+n7_=+W+ok2HTvKyPZj42@&Io)C z0BkbdGERgjgksdw1(khL^l%BQzY8%ctH-WK%|noo^97|u6ajekH$L%oc9@S$`cGrVWd6` z$A2udNw$8BXpNQLiV0!o20@{RBBRTvI`_P2pTK_QhV>S83S_iA#n8MzPN(fD z7Q`Gp28z#a{}dK5Fy@{K+4V)O!=o{#vpa>4+zZi;DL;EwF?%s#;C63>&Q+24;MY8E zq+&1A^5Lr-lJ`dy6Iv8IbBj}HGICDKR=1ON7H;<^zY?v=JHM0u->BB_df(9~ubP}n z$C_&A*-$e2d|aGI0V~5gg#0xgz6ARfJ>K{+;92)MCRUnO-4=v;^#se%)ci0WwS%0T zjgl~iDml!TvSW&_4fcS6xJ>^0XpS8mti$&Xg8th^*O^b@nJYu$ks1pHg3A>MBz4|;HMu!xe+O5N=2PUeg+Uh@5BqN&gqPz}RptQS+;)f;oLX{`55@Rxg?JEW+)%`Kc}Z_XGHd ze^KJQ532E=gu|D-aMf_X`iw+Kx_7G}NZEpaKPpIee}yfn>}DKjkd-6cCLd?)3~Oe{ zIS}WqgecSWgpC`}&SWBcGBLVO7h?~;#-k#xY5VgP7NHEFNRUM%=_MFv6j5qU$hP6< ztt6s3)Q58KOkjcB3NCi7~3i^lZVYlNSdH7u_xG>I7f8!fr|D3hOYx% zif?r~845(`x$MvmO(J)*x?C)Qo#(HOss?ipI_$o&LDV{kO32CPV4RyF$*zOFf(gN6 zBe1Akn;Oua<0RyIR6fP`BJ;%&=@^=)onX5|EvTdYexd5DUmZQ^kQ|-xI%p($kw{nw zTE=jEjLk=C3E1vDbmOe}5{VThIb-JONr9#=zeHcsL-+AL}F$cHmVzRLHz=30qLrxy8hVEx8%(Bp}j1LEa2m?+%)rpQNAs0Zx+y5cKuZCHV3w)kc0*jlab#4U)QdHu4(b1f&uBzcZCVgTw#g&2_GliE7chS`4?20!hB zt89%`5twqOQpGuVy$Q<+qs8n3!D!}>xrUf6>RFfDC}Ee|=P`<)n2*>LFxy$mrD$St z#JbrcjM<+x5~<$P)eSp6mi zdC|N-lLas1B@6W4hZpb~K~DTD&H4^0{kr`NVbqEL9rPGv{#S%YEJA^mii4-}I;wc~ z&aVuF@9t<#=?sIC%XSkuSlKujK7KqplhKQvDBt(d{)_DSK&vd}sUL9ZKO^95!sX4- zm^weZ&?(+OqR!6d;0e)Q?rs{_%0?Q8`7i-s6ELWc(QZ>N|N-L_TuNKU6!_PCKzIkKI27|d<9 z_y3&CH1@mDxmlw5fze!+Mf%B943TwlY8Z^}8{*_du3Z(Xs->bYh$4uxnK!&#^$1 zkwx}v;P-nVw;}PANUBQcA!!$j?i`$f1NAS1K@WrDd#Z+@6Hw`YLFx5f>j3G6?xOoG zr}U;iW2|?oSSOUvb7JZ==h|<*Bh@6!K_FM7L>|EJE_-qDb;N@nhDoINqYX2yf zII)0FKoY0o(!^a>F4kZK$m6Voa|FARqFX5H`$hK|WXMJ4?)gIl?gows>yO@G3B}7G z$5O^=Xkej_aS=k>?g=e2Fmq$w|Q9;`sCFVM|XIB5wS53Sn77t z=?lg$>fA0F&MmUJ7=rvD&pVn}m=aCkz&@eEolxBH1*@=!Dx@MEtATfG2B~AbYy|<@ zI<%6IN!O4UHrwec;`j^n? za~p@JBbF{F4D|=IH@qe{p1hCC|KYMyzy~aYKS~2>gH8JBML^}(WDi5N+KG{-lZAr8 ze_@}fW+3ddnwYE4qY3G>QqW|*YjA5F^DhxWbY13&SM8widJKs^@cGI{T7MT|^jquu zf7yhldA02H*1ek*_PNAtedu%lhX~UvU1=9zcNILU_<^W<3ZP zF+eYwm@!7+FUXD6vQ+aTw z;!%06^?XF%tQq#i`s5{*b@Ao#h_)g1+8|U1I?z8xU&ueB;&WVN#`Z4pZ*H1Q6Ht$1 z{M8j`mLToMFx>4j6lRf1`{vhg=kRYsudO{IVPAS!bpuRN6boce7AnW}7B`rY))Hr^ zO|ypj^S%f8quSj$5W!qS+q7pF>XNY@kCKO=UW zu7xfaQT;-E)0+)|%9uU6{8>6j97iIUzipmneaukU*}P}{5Ka8QHdREC2tkI zHq+0zlXs!QPSk4GvZWdMy7hjBPw$f|em;!L*9bKy*V!VYDeT|N9qLNhH(Dd#Oxkf9 z#J!h&b{0BW42Je^0#~yX*1-?cKgm@jdoN2WwnK5T?dysrjoP!Ria_JE7Zm z6Y#dL2;gM`3Eo%>|H4@`ujSueSQdBt3!TTrVAy8Ui-wvbVsYGY(byK@gTTzCe6ig3 zm_f=fcy-tB92RlAPXFYtWcop_9-CeXCf`KfGS9+>9%YT|eLY;7V)aInve1*Ilvfh&OKNFkQqAZ8W2XIvK>DSsEL-09rI`WV&rq5UZgTkI$- zQ;C#3Omb^LZw$Rx z=iRS1i!rh+kWwl8`8c=VFoW1pVM!om6b+#ao*b^)1BEmaIN@H^QcQ9M>(5ml9Vao3 z>fH&Unb}b4Cu3C$;@Mf29W;-uCv2gseHY>e+{U8t!8uXg@Vtk~;JsUG&8L$^y7VPl zT3@AysE8)XoW%A&gUdnaeHXmTA93`d!s{iJiL8lNM-A3JhqA3x{$2%l9xP%7QY`Fd z`Y1!X)WXKteR~_TaTHW#&g-uBnZ5DlK8%d#?8972$V4l=!&`Ax^gJ+Vad=C-1KcpK zL&3{!J|D+^@@ZjZtRt{IAiF4(Gc+E9YGNaKNzxF|5nG(V; zlm@KM{}JWZ{(QX26LHI^%7D)ygh=f)?AYaWLWgz9ScRHloG^iE$r7wd_Qe33Vk3oQ ziiByJ&wI-c{l?>zsWbPtE0yzf73NueKbo%-(#9ykyzgb-T56?EY#v~04_{}fwUb;< zE=G(eJ&gfc+TZTuTOd@t2*R!lea$cIIik+v=vGr#-nqq=&$J!vxV1J zom)lpX__^?52Nf}9@MtfdDn21h1hT3BL}HaGi$ma@NHY`dKxZXYL7YWcPGVFMV zUic0&8l4qNv z_Er79Q8emMz;5r~clLpAu!0AB5~}yG@~a-8_r+}Whwt^b@7igSb!}kLG?0-NjsjMu z)pV%G>(2v$f*1%|Rt6hYQTWIgwZb+t`{M*Mk%k&Kdv}p%J_WsW%#n-aQRC1$v?)vN zQiu}@EW^OrDSoCF4#yBQ3e_92io!3vK2<#&!-ek+iSlTksEx~aQ;s%7UTqu(e^AzG zp=Cz1)$&aSS^`AgylmcpQN%HUdCXB83r~i%qUXW_St0{4Al5grDgVqiCS`SK!_pLWQjALSierDE7KG92nmz**n(6vAO;Ff{_8^BwJF$K7VJ;!U9DEPz=+xQa&Sr}a==+ids9cJ+m#wg)oXLMNYmIlr;b zSJV~JrtOq$Q1oX`FN(%a*{*Xd`qfRITq1FsC=nHfn3yabd@1?}w|-0U$oMwQuF`7T z`_D%CfVQhJ0fP??`RE(GQ!6IoA70Su2VYm9g&352u@>Rf>^+-Wb=9xGJ<@KJDh?pC z#lTfZS-m1UCyoyjy02k2r_<>qWcYxRtB6NI7URFqkA8QUKI{T_*HPc@${P6Z@MP|4 zgV)%OBLM?)`T@qp{gzv~yusO~w`RI{Qdb1ucw636vw~S>)YNl;Z{-_q(}2B@fs1g7 z0`k_Hw@%rcl)Gas=q@{9o0wEI>bbT|9W((q4p~Z9BsauFb%EOZuRi?Z66!VKxi8aV zWptV%zG}3srNn9+wC!6ID1y@R&l&cLf-S$j{t_+QkZ>%zm+$}2Pk z#4B)7k%xxCfq;WR0FHzuhp@!l%8Z1AfWRh#_@9n|<@t96tnQM-k`#t7>$pGJorCId z22+1kEKgf9=d5Seqq0lHi*v+Kn5$y=|JRbOk@3DtO5x_B{_b2UQt>u%$g)Bd)T-uz^DxnLjM zlEYMp6cgWeT}felf~6Dci*}2vF>%GtApPz|qYwX4C05F5SFd<_;dKVvXZ^42E#6Ez z??0M%J|^EeeQHZNn+x?{J?H*p(4wAALtQpsPZDS${ZKxY!>>-OL?F-qnmB^7Mt|Tk zgkQzAW3-EfNTBavJJK?)GyiUDgTX4?m80QR_W|6O&eU3FJ7;Vdjqm5^)|Tz1jm%2b zWzH8}lnC}eUdm8JVjR)crC#}aJZ65==VrfmBZaU(mej71H8zX>=i-a($lPZn3WxTW zKd@k*0l@RkMY8Jg*Iz8IKPZvJn6?%vJ zIop1fLXSGm2qPpO;cGX0Bk9wZ9eP&mIO6lN#`b|FHzw_CLSvY<`UG)UNIw4FUz~Vk zuH8@u$*^L2dwSUDb)|C*cc*F4zKAZ4Lg~=lLnFQQN}SNb$Q+KEmSP^;Ur**K1uZMu zJPaT+t01*4dXS}xmC$C)8@U7R_k#3ku^@-K5gQoF^{!9-qj_6iENqZSO3 z6uks}Za&`XHTcMp1SN$~6FrncBc0@p-KE0_a_2}9ab#!Qau`WH%)Yxty{>VVu=n>q z0_{%O_iebJ@+c9W4uVs#U;^z&ApRT&Q&0|ogSDjM*5E7La>m=*(^^TC2{_OsY7l8* z&_l6Pw2=2&Ot)!vxfN{h;DtqvSgGl7Y=(nLHv%=Sa`(tn^{l#-br)cBC?loj3Lz>o zU@$RM@p1D*6X{?+2h%6ju?K-BfX@QlPie^u{f#5Ba@lp^{Hxxp8-!tnKPa3~g3g;E z!ZH;7`(&ET%IL>mLn~o;7k5>DCTav1sV02cY4}VQ$0W_`PbH zb3OvAa(l$?%<6jT(y@iUMed-gdbi@`Dosu0rB>?#x0kqDrYo`{rJ`n?C9Du$Z{Rw! zcSODbiX!`2_D^2>F<&Z2PVn4hOds&>#D5_faptw)7&FaCK#rWGCIR#Eq zK?ZUdklOs8&*CU3zlmkWn`_a;#p2Y?W;q837XPwt7-RnQ3Cr@>))4M=JFnqj>gKnw zc=toAZ^Z;#ew~tdezOhF2+_3#tx(aoBaMfz$6IUT?b7aF z$Hg$!(Ra3>idC{`}s*7{y$G)y2^w^;L&dN}UqF|wIYL_7rb*gp-Sk_t*HMT@oK8N@K7?l=en9-|i{X*vBo7Oow^r&{N7WIwHA=<@Yo_!+vKGV5-~4 z_R%7<6HkqXiRFn$3X9lcS&Eos$P{anHppHWHX9dewY%eDA)U&vVfPg1RG#UIRU>Kn zK6Yj#8r40e)-K8Gx73BqffW8_3zIWg|IgtTKCk1Bd&k5>RRhEQDrLyQQr*kn80iNR zlq&YnM4xj%I|r*X3iM8Iq=uaHh7UU{VG$lEqu|!1*Z=Pk<_vHJ+GWJ+$^N4rs)Fubo!T(F5n|5)amU^0K`h`j6c_$`)<|1b4r^jHZhj z#z=N@d;B(99O`(@`zCCt4Yc+K=yI|n4cl2fD#M@V>%>ZZa=1D>{OFb3XpgG|q?gId z+S{^O+;=u$C`clGC!XTOvKCA|?yv84v=(|uu3k<;7aVTdf;xnskeh9`-Pot{<~1!0 zg}GefTCMriucsuN2i)7JN?&z9wK}Tqd5EC5=i!v-$%B8eqKNVHMDd-(p#R_N88b*=oTO{sPYpGlvz!)m z>KYi!LO+xZtbx16I80;FE$$V4&T)60L?yCLFSDwmbm2(9+#9y9Rc2O@1}VN$7DncX zZs(`+JvAkEBy&IMb9oOOK7p2B4F$Pb*O}HCWAD{(n!jB2nPLNO^ZoSfA;Gq z6a06dBARL}s2t*C>l4X5!f#m*Is^GD1U8i5@4h)c36j1_4m;*kt2_ouPL=*~ zQ5`oWx${<_V9R;cme^!826cGP-&vF9FLNg|o2cbZ#TX4Z8(ldc_Cc_LQf==#@65*2 zVPVb2!(c?e7eH=2W%Om?UnRcMC7%^{cYhy1c>6b`muLscG19b1?&5Af| zC>cKK15~X%m@!by*5!&J1rV?wQvLv+V>M`M=m5S zDc3GKpq7EBz$vvz195X)s@qVZ8(N#TmrAfI6pCfD@qILdB0a7kNGn3tb3HONEd;(^ zkBk=fyK`5D8tZ^)@0pC}Iz!moZF90PD^(6p^+@0gS7k|YXPwEYh=}NRDGTKbm~BogLhKn zM=GxwkHeu{Z$*&ZKr(Z@%g0vs6DMW*cTkHCGG>!&Y9)CUkdbvw`npbQIcw~b;)!K2 z>XFcV)!Vybd<_xqQZWd|TKYt$*vI?nX>xDTAwn6)NeU12 zsh&j|P?+|oa8P<3`Q!7o(e!*XmAsOQzQnIXXRR~uPXXr;I3332Bl>3Y|GPZ`oizg7 z4*p7zNRosTeUM0^5j%Os9P=Egw2XIUvkCXm>t-VdhvT$@R(QZ+5%}R^pUPe|hsK6X z${@AKSOjzKSS7u^&q;V3aUn=pF;*n1kwx)$00n3%kJI=2HsRs6x3DiCLjUu-7LZsp zCHlep>ym6?%9VGw;#qFY`!2evSK&XckD7meoG#$>-Ng$Uy!lr!MfsJ0cH5HOejhq= zS@A?AUD#!vXEGc0s{yjf0%dke$&>i2iSpv z)(w(>;6n=C-zr}MYJLaKxE^eF#wb$u;z8niy9&uoH4HRwB$YG5V*+|Mm4DBPoTt+b z_R5KOK+F8c*6`_UP%m%%@QuaQp}zS_93R~G%Wi3_eto`(a$zS!7I4DL_XI8j-*mU< z!i{eg)KhG)N$o@ufY34(>+5RpO^M(2`vc2|5#3vt2ZdQhgJo@9_hOxA8SV7Ab~(V< zzkn{?Eq~AE>4aCp#34akhOd9y4F*r5>~UU9^0-m+e!m66{CYRP)~G{WW{4disbnMsrL2=6tnQiK$l*0W9A|m^8Wc>IFv( zsaq?4?uM96G2t&F#imeZc+BMZ9uV&5a`u~S)bHKZw!>o)8hE*ZL(up{WrBrf#7@Qf zoASV;{HMJ)zhsCsr`W>#)hL3Xv>ba$XNTVKBtihwn~olYi}WiBHA7N0`J-?!V=^SC z#)8V{?v{_(B;R(GCP@Bjt6epUV-*2Em?BG`&YKK>38Hxk`-yb;694j@*-jGL>#&@0 zaVocZe3ETvg~?F=&5G0HQmwip+bW48{@_DL=t)`fcnoXQFuVc6Y<1ll$sVdX@C(fC z*f(Bpc_ID(MH@2GygF`SARs*O{>RlC-@nzGj$vg1uv)8}ehu(czH^pwNHR}uqgwJU z(a>D6H*V^c9f!??x|J_`xsCY{$7ZG#H*<20$|uaxPeN+h_HdO=^M`TlyN=ys}e5;nS89MCIgYbzp@MuPu4{4 zk4#miMIw)_XA}%fRfWXf4>GXup`*|IpQC6+NVv%-s-^ob;MY6i+6n;sDmFLJF6Ey zao&Lph7tYVy&Z9Y@-WOoOBjNCrGQ_0>)>LlkoGrLPjnhXDa(CuPB=45r8>L1y# z=IO(q$_AUQRahhF1JfFj>rUSHi_s-Q0t#}YIR4KCir7Ku>CBy0|78)|^Edn*;S_@+ z%r=}tnGDy@SX{(673pYZ94qaz_GHL*I(<-PJ>5k{jE-c;Wx6Kix<1|^I2eZ1kY++F zwf(dkb4+ZrOtt6W50$bec53IvF=KYdC%0p%J!*sontB*18ykBQTuWl1{ug849gp?*{-2EOkrA?2l(LJEk(KU@ zY$54RMUg$qNMuJwMoP%uZG=J@B?(cIP%_F0+5E2ax^KOEf4-mZ@A3Vs?sLCh=UnHy zp4WPwgPrRhCrgXW@<#KtF6B^eS#wv5p(cy4~^JZ{}p(xdb7vF zCrzh3S!5r#r+gmItWb8iyZf{G*E`HvMGr38S)H?^4(_yN&bm_(9f{jstR4L$yRqQ9 z+tlYLqT#BSV>#W+JXy$Ex9wm1ct+WQXTm`6JEPplg)Q*Xovephe9<@CFDP5$5AXAJ zEI6b=xBv6o^QNiSx!fx~ITK#C%Q7vKWenTBZFcD#e{|7Z$^GRO&Mwxk8K!o*YG=B+lTL4Y znb|w#^Ov*6X_S6Y%TXVydvr(5FsXy$N20sF7vFlVcGMfe_jkq_l&Oc{If7QgM>HZXBrNub?+_T@GePp`}8O+2i)2BTQrPu8}#thukx=#OtR^)J**c+V!u()IE{*PPEcc@x)6 zAFCrhDQs`u@TYjXr|w^JFK|0FbcH?P^fm3UNyN*>oiKr0t=Af5Gx!hRcD3w`yL;Ed z>dH!&n6laKW4EmiCN+M0oI7J(_e;j$M~8TEKUx0yZ_Q)lC!e=?r(gbDIw7uC)V+1h zXDZ;Mp5VvmlwY!97B8;NktK7B-OpcpXR+Vqom9%wam}GOX>kW~KV4Q%^t!1t@pR~y z@4eAzyubF#R+Ez3@9JN!CCLVOO}Q^_sSq?;%UJPyJlP$}qV)RVJzd{VJ?VX2SHAbY zS+yj4dtA&fKVgzBrcwE1zjvcqa_A;aO_|iGrZPKkrH}v+OFTJo?#jLHXJ_CHp4#2b`9ueLFjCT+euh zmFfQery&n?`GVEng*TqkF{faz%T3HxV&&gFWHx>2`i##6+11IjCX+|soI2KQWODy0 zYcBuw`saRj@=7-cCfuceYE;FMuZWm``Ec*`=Qe3a_)ppEW<_I?>=4GObD_)3{pn2U z+ZT0@tXw6#P1meG-I*v93I8qDe;R)Ame94?QpyLCB}2;|%{JmqK2s+>t}RlJl?1Zi z{vtDK!Qs7GAahGFZxj#Z_BXRBM&SdDJgg1tGs+fY$+jN~ zY6udF;vKxIbM~zenVk^7(90wA>vj3?fSK^zbwy!H^~2=5uPbg*Yhq~UJ9F*R*_N-Z zS56$i{Dt=vmEI}yOa`Wb%wn?98y5^Cf)DZqkzQmB-hHA))`3drQOrHETxs!kMO91n zpjcspuu%B^-abyU6Ni(f^KUQ;DAU@8_4isI<~OGdkZo27x&4(VC99}MH#Y9;6aJ%| zvQ&$@C8cBgc2s;~=@i;>$gtB%_zb_prkZWR=MSdO@ucvt3NSyQHF!5kk&_-%RJ~$7 za3x{b*q7zXJ8!xhe43+=)QmWbH(#f+q!6w3BJGF~t6q`MR!Gc{{ncn1#FE`hapY{m z6#Cj*kSE#3(9(W1HteKD3(Z&FBSz0J&vZ7n_uom-kh2tcsCn3=yXe_VSC5wdh=rSc zCH+-Px;J(@+#5WigL_=gy2W#M^%hdz7rwHaT$?v%c+%$&bc-E+?y$|=0{!RDgQRP!|-K*!>Y$x|HSzCO|lgrdDYkNeeOLthI z#5vqJYR~XoSNnSCH&rq9%~=!9g`8`9ckX5CE^<=}@(Me%iFH9M(K+G*zjUkb$m*Ur za&lKDn%?XkvAt!>P#GD%5(o4lOOcr5OG zVX*Fu`CUpmFKG62*8l0M@|^)S{nEl<-NaWrNz6^CH0?$*{ZH1auQn+to?kf^F8(WU zq|x{n{3dQgVR};&_3g%C%hP(n%jHS4{`H5?Ead6taa9y;4Kzud(*2U*zrqsSwjmB<%o++J;jH8 zT+~ILem!y8|Jc1vSrZm?`*?qrGF$CBDnHA|d`Csv^s&l9m!6lQ&pMRp|K(J0VT_wW z7E(_teEq+r9x1F)x9GigQ-{&-_}O)m=>u1tKC+AVwtK(yo+*3h@G$9g)HHjv6q{ty znTPAQ$0$19S~Kb-kX2o()H5``jJwfm%ZbIJ6_6}D}|NvKjkaBt2%d4R&QMT-Dkslv9W}k4C+r{weQdG#ksq-#_GP3lGT@|DpWLrLo%VYENcp0 zoF}@I-wCzc7f?);nL1}8HJ&?ptcF!9ddKRDb_M_ImZACJt%}w6**9ZI~6(3t&xsA?`lyT|aZ&KWY znY3GZBF@svU!JAeaiQpz_xm=^VoYL&KG|Fd`dSQd6NJ5ml}nR#k4nxX>y{UFDbR@Kg@Q}cJg^IuGqTujQ{WR zhrbKmx%KjP!;O>OA`c9fxjMPV`Lyz5PBU6Xi+neaw#pAu-7*({u#5QV7WQc-2K#RG zuId)4q~=-o5(U}CGp^UVni6do+znI|`Xe89+UGew;wp?|wm6)rxtY6DpI%q7@|1$9 zqs5@u?%q48H;Q)`-{|^BieJ-WD*Hn=7kx9>X_2u$U9aAE z($7@XydU2^T2pd{NzXI)n8WW!5-9>V;q~KPN65PRH7>o9uUV5E zHP*hwXXTm2^(CF}cFf(aT20Q5XY!Y0&tGwY}PcRp5Wt)v-3 zB~q`Ec!EsRn*4#b^#^6rRGgtBiRs~1Q!*J<1D)99U-Lifo5)Q1sms{z=4dA_JTf7r zI=ba~^{s>(6ZS36I2N`RUs*S1*miX?axD>Fz@;oxv(*T|06 zuPlqX$t%4MLwqpUz&dl0GgL2yX>$=iZjmsC|0G#ENnzi@m(fI#MjY!jIX;9-*}LKs z^ilqGH>b8XzglL=66fg_oy;a3yP9|My%fTe{#clJ~I;}(@n7K2|oMbb|l9^L*t=1_XBZhBT0#X|P)=r4^AoHHEY)5oCr7v!YEn-&rzT(({>MJh=oHdq7<1FO`_;57a3fQE%$-nU# z_Kizv(s1O2(3sFLb#7W`k-{gl?=hCrFj!qF+5PRUMcwy|6H~?+-S&zuy!YjMW8U+LoS(N>Aalg9&=mg=1!*S=r>`kjHdzjn=P zy+0-ZzI+_>xHP~)Wp=Ia{^GFx#oudly~opkQ}RgzbX>;!XRI@TQ%sc5Eu=*+T z(o?_rCAYct(WJ+fB$wx>9O7I~qUlT(dY| zySg+mG+tX%7%;Dr`)%&#j`bDu^@}CzMkTd5s}~oKO!n6-E(~;prmF;4?@}4RJ=dn9 zqNs9lb+}D;X+E?C_v(JkR*h^^Ys9kDgbqOR61f zZtP93^;=3By~&$&^PY;|??E5MkhQknUX=sfYm++P1j3GTZ!3 zXmvc4A)xlmdiC0`o3Hd$;&}tQ^xmycPd6Vw9#FZuR$sNg{5!X;w$mxEb*kfMTj~1r z#LQ}~lAqtsnIkE~b8YKW0sad^wS6_K@VhF$zR^}?O~m%3l|>N}4qSO$!D&wQJ& zS)3|aDqdf1UVfZpQ<&Q`9`Gn&&1HW1ed(+8hy5!<9p4!yOZ6uFYu53~vOjl>tCXrJ z_*I{O)#@oV*WIh1e!RNc+h^%3jpi8tS<@seLfyd9qE)t6Qm=OVxJs;o@k z-Ro+-tY2GQb4gsUzq2LDD9dX9*e@~Z+njT0Pga_a?@^ig*-=n1sQ-|}Kfq;X<-_FM zB|o>^1wB@y)zZ++$*R1PAL*wG?EOW3!!v&w%#udj2+cGbJG)@55;uNxwN1KhEN->J zX|7bIq<35QcxLe{--UzS9^2QhPL^aIUbi+~TwarS^xhyTVA^$Mn@ZIBV3+w&V|}gn zml|J=m?dNVHxjF?{nq}&y}1u#)|9N~O4->KPi^aB9u>6=70gJyF>}FnC9L-R&`CpO z&6pQn+lp6M=Nq5wUfso-uO{wpcV&)?Vf)iFFTVJgtHH?52mSlTuFPccESEix^pt(V z5IXtI#9jI3@lpN!lSP;M?=o<88;So|$YgCixL$qqI%k9W{O+k|U%rix3|yIuEcR%R zcwX*ke3zm;b~JUVSn%9bChL`x-FZ56cKjW3NzQU7LXU{EHP(qk&@Zi?qY^$M9jYpmd zy=buD+_6=j`G$0~O#hBILn1f5e@x8u$lrPA7N>iDUyjT0asyRzaB`2+%Z9VUyvu21 z?UjAWFHux;#ldBXh4e%}^I~O(gA=+)nOF zPfKGDrE%D0eoo`s!=^^gt7hH;+jX%I3qK$CGF*s0$u&A2Jz#h9WdjLo5fZ~lI=rLd z;NZCq*h5h7uB3j&8>vTz5^#gE<;FbBTR@3*j(fx1Dja>h9xix$?E?#JN26O$?y`!kDsg!NR=^Fi=%xvvhxdE~v&o0pWfH$TnzP*`EG*+Zb&?(;jEpM!e08kXF|en26?{Vx1P>O zHvh_`H^M=G1Jgvv*3;LKUT#=ggK(!a8Z5y2;q_qb|Ldnu9c{S5BKH&bT4wZ3MztAl ze8deE!NP;nZm!#jijs-GZx6!0_)3&D^z=Hzge`jNAMxxtPqzx`F-JC+yQq?jh`H=V z`mun2k+y8b9(&lLuVZ#8IPrLsgLbJ)`;c}`b<^M%Eyu}QwFtdQJ(LE(Px!~qiCa%6 zVV|U<@1FtzP6>l@5^sZ-{N(CEX3skGL1EKQ$wT2op7iJbB~G*Kn;S44Tl~qPKx*94 z!8F{^zaF^Ot5Alfd~p}^ss!Rk?f83cn~cli668;r% z0xI|Fa$(DdXX6Hcpw$&V!D_lkj^^*b`K;Gq9w0bv>zZ_n6bu|IUj<8?##TJ{vs01; zMwX+`rYQp~z~%tvJ5p(b6wwC`l>*mXxUd>YlP&M_34p!c^r4WA>(La)tpxgg3O^s%7{-USx3hwu7*g5yJaSe z)=LiUGI*{)mHobtj`q}6xIEzE`9XB^PPs!c(lDri)(^dyeD)IgPRZ~Y`C;`RX_&Ex zLKQHzA(3P-k=8WE`sj8_QgzFt<=$Y+ah#0&!F2~)9~)?v0?6(H5N*8WisOP^Jb7sW zQo9kQc5(O8)7l!UTRic;A6p+YT9J^|P!T|7+lYpD)j2>vnhMbW#_7z62(yBbQRESh zXPZ-&8tleD9Qo9Tw>$0NAhmy(zPU;C+QO6ks++i3+>zZ{rz~ml_=MY|PkIA8j)?eI zT1H)4JSZ)#+vf49_}Qokvzj$L^Prg3PgF2#_FQ8heVUWBRA-l+`)mHV>xLiGzBp0o z?Mo3IbC4>C@4x zzHbsI7AE>^k(=hIjxe(!wdV&H3m*c ztUNpLtFgeal}kFp?ZBRtqmoys5-aTmWS{R*?A;ODo{@{+ ze~Bi5JtJC|@wlOGPJR9T@rbK&ROM8m5|0_8b8NRTx6^xmxT-I0Zm6+?t44-i%gAdc z%o}E%?JGV*=_AR1;5psyBVr?JW-+|_Rq7q;-MBD=3s(*sQD1u7WoKNHvME+Il;?ZU zr|zdLE4Bhl&-akh3khb)Z~s~|EXSz!WSr_4OqO8-BHI6?;-GZeQQv7x=91;!`ruWc z5+B#wh{34X<<#y#Y|K4*?n%iR(UjPbFP^eEI$g$ny4^VHTV(H$q2hbHB;_R4J|UBh z&U$DbY!1eeJ-&ZJSBY<^@_8}k!vT1 zT`Sx5MkZJrw62+zvx$nCY3uKLw{>I*9T@8!m6V%Mdy*0sSC*cj%=zKR+km-+7ax9l zCUchYIVDUCbMFuIWSZtk!P{`^9 zOKUUPd!sk8q2xLZ*%0f28veA++wQ}}J$#>WAkoZvWo8CmASZ}B0>Bnha>EVGrfyEY zXP6=@heAHAR8**A^lcs{cRA~i3!Mo;yWHo>GIwzJ3vu{e8~ky-ilkk2%QR~Uen0mC z!;)Q`x*~SsKRmZ+P~Vee;v5i)Ivw{s;%Ir_M4--PHW7i{Y4p5)Ub{HeciWct(H%Y_ z)}wCrN@1thjQSID@khNN`_3-Vg%FXK%zZoc=oBV>oLKPjXLg=}4!R`lmA)pH1_Pi+|SQh1I8BuyEGjZyLI@@D9WxapU)QI}s+pc?=aX5Y)DciB1=Nnn_ zP6#}$8=YePMbLp~kAnj~WFaH;Ra$)1ptgw?G4O!jyT(s69TUFqf^-{PMQZtD8z@ilpdYB8a_goYXQn~erET(_=pkpm$zN6 zBd4~Iz2)Fj4otTzJ5FTH&v5~YS$ltgq_0m1 zkkucuF;$b^Kl^~Rj@~9ake>MjyPmo`9|y+^ACbo}vc|+YtPN%m@40K6~Owctr#bq|qBO6BLgg8mZUl42^$EcNHE=z$*WoN{|5je4_HJFxi{(YXpi$KgHSnO0GRSlf{zVXVg zB?GNp|H!7DRTl`@$i};}f7p1ZGXk=zd>g(bg|NXqA?CN-XEeo9h{{ExY_23_*Zd#y z-@jr;(4%pj*uOTcD;@H;DGU$gFp_SL{P4W6Vt}*mxbCJ2gL!cs^vtRmL%`Ys!ZGRK57JWVyb1s=mh1W>{g5ESStq zurN>g8=dkNNlXJfug^xKxM%6 z7Dt(IL6Pq-Q#L_@2Hwi<8M`n(m^dv`eOOd% z%#OdMX%0raXvR+-&531_G30rpZpX*L?R)7~eAVF;b*$5Gib;#nHg&&gO1@~<$4 zh%$UXRFVQ3i?PjD()chi>8uE4c}Gfa~KGf^Nrs;_&MD;384h`)-zQ)EwKHX&{4WO)D9GY4zx%(iMM<1mz_>19HWQg+wKX|GIGdYbq7K6SuH`M=vfV z$^P}Tpgf(R6U8>yA=50xL+LGTC(=@Hfo%uMej;*|v@wH34CzB9-W2wiJu0^0F)O}` z(3OV8D|w6y(>rwe1?|!x?i%Srt6jICyV5BLK?Lc+A~A}M~Rnf@D9in)n^1`VHo(2$BW z`mcpLgn8<`bi;mKVB1msVqy55NxWv_<0(csO*5UNbscP@6&cjKe&cyEFwG;L3kQe8o`& zbCbuUng5<+g4_aIsy#23{XgcIcZx^8SHaDQo`5#_z-h?9AYD8r-CqMqI0zRcYz@8# ztcE`cGYbg5j8qhV1bD=xDS|8|AlM0^?PkYLLR>i{qM?IOMTU5mw5t+V?0#%y1aNkzfNyb~Ol@C~A@y?sPYa`_TO)e%w5 zHTh>QgDlzPaZl9*LO9*n-oKVJ$iloWA1{Exl>9oA14IEU>Fii0hye(4vWM`;iPzDW1U!GtlUCRP!ppTdo~m=1(;EHL76Q{ zDIGC`D;b9X0y>+!^u)+JX%35jJME9hVp~8l66rPse@~)mLuZ&l(oWxNP0$qq^&FHS z#*ntJ0D(|Eey-i@LKSktyq;FL4Zj>N?YNm&< zT9#Oa)$kSGg+gle?HND6Y%7_EnGC0Py^nv^SIsY*Lqlr zkJ@%S7zpaVpoqoih1f!Xd+f7GRtZwpX4TFRZK(eUT=U>nc4$1;*ob)IJ~HNT%UW8l;NZd#6+uqwrZ1%FP~UEUikU6O zT7s4m!YIK_aV+~z5W}tHiH&*jde7f`NfXNxa)TUm8 zXkF>cw5BW^jL=JgoX-N0oT`{wpF;&aWM?{6g2pKe#Si^-) z)8iD3IvfZA6OJ}8Pauh5bW5KS1dg9rK6E=Oy;KZ65Y7*hSp|>&E z#8{xMK93L}t;;xl7;C`5TMU>mKPOsp?(Jde%UG)l-btFdi8K?Yfz4+hItI+cf9y)w z2-d3N*|4l3rRWJ1j=(v1ZXRN1gq|w||B>7G5rRLm>n2vUKMqY&-bYEA83-X=DZY=S z9r_A4V+l6`WHT8J?7SqJEYVCi4yxG5T*sLu7#I4fy(c&fcRciw0Dhb_wy(%`DU=xj zkFp(qJ&-VrI+ni%{@WW?G6dE9X(Hj*IAY#Rm=kNlh*Mzc7Z&mKyQ=p<)-ISG6C=Sh zx~liuhBh%5Ec6>9E{jD6J>o|Jalt?*MzPdWOz|vxGh7BqG9uePzS7k zyJOdthm>vy5nuxq4xOJotvE~gm;4?Se&Zrc*W=Ld{Sc{CnUj@*ta*eBA_wGCpB(Zp z^u4Vj1b3>;e3T;HjiY(Sy%7aWvL2-zZ6@1T&74xSypkxmE0k#%EU!^jOlA>eLZJbA zWaK^w8rVcwkCg{B1ko}QgtZ(x5xmO*awVACtHIWiaCF^_dLkQc*r2W&UfD6Zc)$O+ zQo!$=wKkXWDWujp?-A6!>xkH?b~ZY`IkPi`Q%XGw{0M^})UZe!^`34EB^T%YWKn!` zRKETxA}8)oj42N+;Phw(mlqE_kNF!#=xuh!o7F#)Vd$?=aa;%jBr*c#r)amYYo{Hs zKwW8r+ULL34>6AzDM5>hd~6%r0CgPPjb$2gcE&l#-Nd()5zL(7P5 zuLp+ilp-hT`7cfyb5KC|hJ_C`kOP4n6XW6&!13(wUrq4kV_!GT1 zBJ)Nx|0^9CNU0FO@K@Z#J3P5MCC3brlMr0R$r5_#t5~kux4f3w{Vb3WPR4wR&HLX< zY7G7)XOy+SfuZ{9AvqxKz+r*Bc<=;8*}sA6KZR+|_XpwzXiXu10N3(Y(ldU|U_)@t z|JVeOhA7(qr_dX^ctOO^3Q>Kw?pp!jdE?Wog!~Tbn-hsbM2y;tv4~1MBnUP;RichD z$_fSo6+59A!ZL=nAv6eJ^e_@B#7~rE8Whn#e6pPpcB4)khC-BJ)`GtX3hQWlz9YoE zVn#qTBdHx)AC7gpp8yj}02CBt8(Tn$EmB5`PXy5#3~rZELOv&xU6O*WXGenNj9y%R zl}|%paxh6bL^~*Z&gXQ}Q({t^0}hUMr6{6Yupv+u>qe+W@#0A6HnUI46*Q3kdK`#= zX)N`L$G8mRA|mp!+0~@wXAS;i1S=a+t_QrwV<|dZ5AUT4!2@OlsSzo;jB32U2atru z(sFhUJ#%$|=7ju(YB1PTtLr|A1{nKBj6lE&bQ7aQ9~J|M8vFA0VEO(wD8m2I{huWB z&&pT@NNUGV(I7-j!5Et)PTY>P?hKBQ&Ps_2rIO;)G1;>HUn(vJsuJt8unmbr$jTp! z_=sAse+CK+dvW!jpB_J8_S$jv(}IALKR;W8>^(jkn^SXlx(d>7*LbfjN1orhmDJ>B zW9zC)oI|nK`s>^EP@djSVx?0Nak{>1TkK`vOgalqPtV4Q3@}hZJIl7_!v*aNf%=sUb_qLW@yAw%V&v^JJHmLPXQ{nFWU+Yuw|W;2KM3INwIyo z53!ZC8u5ho5)#zmqK70R4I|$A(eTb*oV-%!M?S`O%Ae44iZH{x$~RoyEFDqbgo^lB zCR-L`{|)J&-jxoDdUut|E6J50FO1LzMQycjYduSl4i&Civ4+0l9^OwEzbuasHUY&8 zo{UJ|pcj2*cVgtyN6CSSqb0<~mC##)x-0B0xA*a{DClB_s~#DG{+mAL+Eq8%L>y+_ zvY;qa==k7F@8x+o9hT#M`J1l~C^%Cnw+C`ZfmSrbTOebgx@l}CQe5k$u z_l}?w--iE}{BQ*Jb3D{KU0ti_51yL8+Qee|R4)0`(Wkxtvq4xJTIwWR^aSG?moUCT zNa!jnGRx=%#|!e>M$H=7Zgw@nakxqa-r>{Lg@~ilRN)&!6P1pN0212GQ3BF+Kw$k* zGN}E(3E9;bsKYO4YO8jR0ADDSXzpRqIt85wSP#Jh<~i>kdZC+H8gP10VrgXGB~hS| zu*V2}{uxbRi-e7a_BNOq*Wdl6{MCu)86Se!MK!|yit;|SI%@K&%o2$&b1Dug?%OB& ztYt1onZgo31I-cgHYh?(d~h#GIRSc5Z*oArNnoSOH`8S9jTd4DB><5m4Ez)t;Y@Ty z{Ww;#|~0MdI5`r0HHQm0}C7_;`z)k zlN+M80`o&F8Q>Xq5gKoT)QI@_M{3yWUL%V8k6~j$(^|gVn6F|JciyV56!aqSXo#3< z`O#YV)>|4i8b};e7y?Luc=J$6UQx!g#5F@VHWerv!;Lk9!ubR-8zV;0aKP0aGAzm{ z$mlTe+!{~l*NG&`oc(rog1+g7KXNkyplj@bY7rN@x<6&>A{X+f0`F_aGKK(Ou)x!C zv6LV5VOn0`ia$6(OoLM4gXpwn_`%p6e+SJ0g${VtW)_Yt@b?t?wD1k5^u}G87GEe7 z?;kmQL=N%nKc1((7gr)H$YJ)o`^(KzPC+E)Ik7!Ax0T4#30R2rz!SrT}0PgjDrJqzxBBln5^JlyE1!cooOH**@+sFfJ(`1O? zf6sCPc(KFcXl{CC@L_vhCXunoHzQmq0g+~DB$rJ>oCyv`Zm?_HCc{`@;VvdgYbNKN zW-JDxj_CRDmMN@OcMzRUqJSY*r{U+pRg^b{LO+I{v0+{&5&HrDBK|tE{FUVg4oRmD zXopKm(J*WPe*SDRh^;3A6A5k^Fp*e#0=vT)CKyq-%e#Nab!UfyZcO&4Xg zeFB3|gv%}$FYCE~#AByPm{QDO}=b_h|vRoc$x>sba&aVho%5?#1U7stk?kA5w?Ts^5El)@=& z;+JzW_3U9n?u7G2!K?=-2A}y{l%zE5UrT{Y4LS9C%i|FR7#hyz?8YKM`}A1`@XBi{ zDfo|wc!Xmr>_h@ZjZ<;?HMTqlrn+4U!l1jwhDuV#9&1YP|J*8wof*1W&M8Od+h^h} zfi12cIoYp$$b{GDqkW5zkzez+VwBUNe8fWatGb1S; z@ov>Xms+%*C=^rU+KNQW_#XKXdVK6nlS(njQ{&#PoskE8M@YmC(;rva!!f|lyRqm@ zuZbA4!F$DQZ8r`}Fg?;qN@GOoVNd!RN&DSG{pP)ras`YHwDoqM2 zIh#f`S3E{h;9V8@9%1=+=nyI(@ChX;fI@5tItvIzgbWCq8M9`R|8o$6!e8em=AnoQ z*H%J6B!DOSAS!P$R5)#ExPgiyM0;;cL`@&cPFSMBuz{{qphB+stIoq?8%0plR%{l;FK;j7bBK&F(gdIp zVGHF!NJAM)4aCzP$Fb?Rn14WCY(0CPSlnP$5d`(k35W(LSJ;p#$P>lHf> z_7`vvpq@m-*k8)0M zZ3PtjCy4xcLW608wl8sJ44c}`4aW;ax!dqn2jiCW2YE%Ka(S`svI>DrC$*kJ&XK0g;6C5jF# z;gnN@TSjUZ)CU_wh#E%j+dv^6=Gz8Wlpupb;)4q)XgeAe*QRTR5(O$X#JUim z3jx^OIBeb?>=pX{I$kGnsN29)AQg5B3-u?46u78}mIv><2TVm%7@axe97!++6^viX z$2$a4A$Ay}9bH>x1q5rtB6=uU4G}phN&R9hITqt<1SvF_plODB{3JL+x!yWqPU z0{Kj=q2+|IhIG+Dfn8w1dRsIx@dn7fD`r5E)!fv^c8gx>+D1_dy?SweW63s*b^x*w z>#CVZGr2xjdCn_vBBs1D6Ql2=*%>u~z_`K+_d>Xz0u!>=PBo!^F~GXrKw1qRnt1OG zq#V3TiQR-C(#iiHk-1OZM+Zefo}W-Xhe9*qK%#--LTKund!z!0B3mQ3I0l?=d^ol^ z6nt$dcg#bkq2Gpkm}n_GXzz7QqEqcZqKg_lg2o_Xhg*ViSKiqiW$YAXKhU`lvy|e` z=2RY+k@D_B*MM$nL)%>S5+c(7cxY*JU}r>~k`WVyhQyM2cYHxy@p(v=XLk^A2I&YL z5s9RX`CIhO8`Dpg{^-BGaTZ~}rQvfJ(~!bWj9;jr zS6}8mtLU<>~+8ZCQmWPTDTjnwUo z9{m?Z2=BE=9$5NG711>>-(%lmCG!&y?B@6{zE)9+uZ5)dLek$HE{q|Ep=c!of))Y_ zg~lz#z{xDQSO=GQCx#8ni9{~xr;OVGb;XDIojLLs~@?b&DZ6FWvAqTnxyp?CV5 zZ6@Mko-PZ{sFT&b%4U8(Y zvuVI^f{((zWs>rbz1Lu_eFZUB$2R01Gl;~_8;Bx&;S#3M@Cyxw_5ybP4~q(X|6k4w z1t#$rwVas{Tkr{z*LBRW@k*SK99Lj zI7vB*c6gS4VrJPGfQkr?tzlch;S%GoD-kg~RW|>~jPPl`;g^515o}5k)x9XtjHTu? z34VS1N)B~ZKsjS%@}G?Z!87IH{N(BdX(m#;6iCPofg`m`0|V1n%r2tL=Q{FD0j|Z_ zYF;N9`0V|VfOOzX&>`H0%p?;AE)OuG^^V=#Td2J;YZzz!O2cpi+&cPqOI?Gxa;Fw zG7tjvR6UJ0u#l1Km;+a2k^H_mk$ps2HzJ<|txYy4g=hkLWtQc-FD8&~m`Uvj$)8BZ zdp_H1Y*6`!un&Fo4@$631#Garg#XhVrgaq6%19#oPD~Ym$)UvAFoaegb|`{vkTR}4 zqY)i=<#RLsWvg8fTpp4JVSw|DZI6KbvYeV^rwZN#_9PT2YvR~x0K|m<1tsV_9hC{h zeF2l%r-Yq){__e(@J|ebb%}Z{(CdevLg;H1{G)wh8iyzY;MdVYS0*w}&tn0?d4T{v zN0BPhOzbKqcqS3o-?o(Mp^)(^0$o?_U=;>$*bl<|xf=ur74f)SG|!6>!X4PpZC^cA z)6gj?Th@>q;!vy8ff18OZxId$5kyn)`{Dfi!FUyryps=vq4%FBj(q}J3%l|8WAK`> z|I}D#9=%Hzr^wu#=}_NOn^~8vShyBErXs5N_-oJguVE9}`}hVe0?*~N3O&?1mJ-lx zzZwxK`YULPxp^vm?aa(}caiH;Ek#lBp)Ue;9<-SfO7Zqbe@Q= zXtTz6lIgbfNRr6hOJO(L0)z#Zb@FNtoRX@_8e3nR{@%Yfcly%M+_Ko~TkZu~wcEI* zYvsHH#)Xx{@fro`wJ`*qJ=W*pVIM2^(BFk*i-V|mWX=qWg$pV@a54|q@ zy;!C#K&fJNx!tl+`C%XQh>A9$$4VqU0$#%4>vD zESunt#{5}sHfe#bHYP;cjp)aqr7fDmu3!>E5jN_W@0#>ZU5ksTRq2Rs1(RkxzaTyE zmV|cW;IK*hdl#4O9}xp-qC;yj+gLR648ly?2HjpjbC0Nt{@=)8U>}8)wBNaZc3QrgpN4y%N+rs$yi@2ZDWss@ z^cJLa1D?9PBG6VC>2)U9DW>%{U=g12*=jIxxG1{Kt-hk5;c#J;wj(f~AYXhls4U4+ z%lJKkedr>$K(?8y9}ywkjLj*~A1{k#%7>qhq9*~8AR#Wlk`Dp#C&QcIs2&W7D_>|| zWESRG%2*>k_O$i}H(YoS%XGJZXx7D!R|>&w(m@ejewIYb_dP8fX$$ZLg~TBVo&|;F z>c-`VL_r=RNboR(02%=6K4D}}<-z3;{U-Dl=42z6^W#Rr@8Httk$d)FLwW;{uu;=%WP8YD z3QUD>=RLl#=|&!LA3i|Yg8*%!!bX|}%E)XehWyL#AjHHn85h;?5tSB)Lzpl8gKx(i zq=%69zc+BDne4?F!Rlk*!#04SL;?l`@SY=px9{mMvS4tDKyoHo>OX$b)^!Ot5QvrlL#&jC>D_*bW0EZQREd1(9N%)A}pe4K{tyyq2BZYVz?lv z7T_rNFXeZx8Q%^Bgg`*~^Tb1Y6k*EveiQ67rEFyN*kbk>1Q|f_O)NMPP&^Nu0bq!L z7Kx_)V4;hwK=H$S;GHI-EQK(L`NyOo*pYT^HaH5b@sG@cS)Ix72XX&i|EP4LpCz00 zARoSA1H%!<7qI}BjwXqUvQsf)&DhqLp*&8-QBD;;aE4z{$K-gd2NniCwlZ%$$hJB? zM`jzYHk3$+LWt^_%?-sz*w+cD??%A-#*v8CWxr)im=JQnP>&^o`>mredxO-w0UoC` z(&6IlXjohU00KM$yr`{D2?Bvm&QDL1Mq}C zIzb1)uj6vD*txpe-D05+t?V{B)81=@F~5mn=y&0v@+XRD`4=N@gdbqZuRC}PMNhlg z6ht2<;7o?P&Z3~Kg%T&|@a(bkinp;R;37HlLXV9HgbCpnv;%bs=;CMo@wmclx!{GDshl0T|BVUSiia{4F+8PylT2 z1-iNj+mqrux+;sMd>Lxha7oJ}NLCx{hs}W2U&TQV*i^Pdif^JnXmt%0rIspZe!O{G(|2TWaC>7lHB;5cPiy zW1Rj!A|id|nfG~n*cgZYz6dRtS7+aMnU9t-Ks|ws7wG)59^Bl4L>!{w)nNkD`dnsT z(z-lSNku9UxpodRmc!HiyP@I(pZzl#k_n+%Rr6WV7897AFkm6GQ6i!jc(o=I>gS7U zBi0t8f(oE+M1wCt#J?XxeE(bS5uh`7>Z_V#XqbMEBjBvP^C)B{4A@w1MmI_K*9odOhWK(2Jc#X>+Xgnd9s zLtqc~<7)q7Ko_u0MG0Wv{OCmg#v=smmC*tA5Q_;8S?q!y`NY3bHlq;6&X|A0LV{py zP(J#ME*$(fEG*l6~x@G2-pB0wf7h{wNACVv#z?hY$;d@Dk7=_ z^{TR&?ha1}m5I*#{=csDAA*1%1%ol;*%_-)Q`9EqFp3XzX^+j&2f{LXKvn-ZUBKoA8~*de*y){* zxp!kQx8870Kc4CfbU#a-p&6qg9Xtml18d*DZ}@v}pwAohPn)O?Wq^hNrV>H^K+;<_ ziTsEioN%@G;UrxVVgA)m{TDUh#6Q2|5pnZ3w$%tR-w|jMWwLfwnraMNiwOMT+Xew~=2Dx8t{=~rKDs9oMK^yj@#WKoa_-#7Ra!N$Ate-h!*kh~VRkyC-{c{ob z*t_i1LsrbR+>hrtS0wvQjAqccZgqR=@GPRB*0oNuuzc&xdWzxXJ(cqZGm4z*s4JL_ zoEP2jA(WT*b6Gqs%}=&6oHMgw7c88R!)~vA*PvlDc3m9LzYKL9flW zoHj-^Y*o)A5_pV7r@Aqc#^cP5qlFGF5e09)9dWKuy5ClPpfkhbX>GnvN#0oC+-Fy* z<=1;)v zz;ef`uZ-2CnoQ7F=!kJ}2?~j#YB;j^xJ_q){456rhq%8d2iK z&kICKL3LUU;j7tH6#FmPpQSSejo5=m#v1l?hI@TTKSW?U} z31Yf#S4;Qe^#7ym&EslXqyO5I~7sJMk3cmW=E=f)iE|`P&9|GXf~Y8 zg#~&BMUBffV?kO?xnwj$J zhUu~XcVJ5wm~Wg9n`IU+aYK1`r>m6F_Qij#SCEOW(eSx%KdI8h_Rn7*?yj66(_Wn# z@Gc{#WBJMG^x8e!Km4Jwbu1@FKGS%3`EwZg>oNbvHXwP1cxKGeZFh8THnfTyx>RDa zC06#x#P`PALGY}PUs&woKiH$WhsT_A(M-LHEw2)&x3hLlru>teY)<<4)N3LGzdw{o zQTA3XHSw&x-{I}qkn&u8*WLrNZLp|M>MxjGd$!$KOug~Q+o=VybEiF|J(PK`{JQ4amRi~T z#Scw*%-N-S3I^2)8jnma-j=LsAmTEv^h{}6u|=j#6>ey#k$=g=zE+)`hisId!%S2i zZkoj^#XpOK*?)HTOmA9~Fw({u84B%f9ICD!>8&;x9xTro4hr|0UFuWiGSXdFec$Te zjP&8^;hegW0g2&ipO+&8^LOhu7hvn?=SXHZzd>6Y|I_-g~{O5?~*V(>$R6N?4FAJDV1?y@9b26cGb1a0Z;q1;NOJpD-6PXg5&O2muhr} zUQpjJks@V1uJLKaGp1RN{XCxifOA27SK_Z?X>BRjL`J5U@8uY!)hlRhtl8NcJZ)hf zcWuH1mlcWU*Q}8B$#STqZ^(oAaLi;+Y|E^W8v~_rtMGqO#}N!Y}Z`EtRgn9-1^?)E6yp zlb$}Vp-`hZW}yFOYy>;AMeES>iz-pP^+COHmpy`_VjQfl=riBsm=9N2KdrpdwKVbB_h<2Q-sfC<(Q#Co zS-R$lzjN3F6WAvFy?sYQfWjvZ_jl9j6#Ln>gq)twbCv|Vm1WCMXb7G@#Ox;Tt=!Pv zRiWE6?S`e7hWX%8htP0QMJ=I2PkFA{GV(=vM=qHNiOD|FOtrY%t&^C4M6NhSYk#0Z zD_bt!(DHcc(TL_C4R%@Z$u`du$2@{WM2?B=Q^Cg>EpF&eov$#&RQWacP>J5^!Z!J! z_iQ$NZ1~URVgBb05}Mxk^?KW{U1Ps?aeYtVn-v8b>`O0nxlIKH8s8eOl>c4-;(Ntr z&OAF6o-6#lFw@7e=DqW}M(r#+o3aq|T@jV;|7K)Nsd2eb2MawW&r19Zd(SSg@>Fk0 zzOA=$UD)(yb%A&UAesJpttEQdDtk+dX*l}|%vX@)0 zV{N}a6rgju4xW=&k;|Q#^hi^^zHdlAaY)fORnC7la2D%o4;?$OfzPfcXdT?o?c$MPJPz^Tg zShscie5HA^N$p;8-%8;^+0bH(=#cKZ^7Db_ed$4DBW*{ntS~dp%Zl48=WAT5;rh=u zkDzmF#MdT2DPclIEcG@M2>gB4ud{1ww)bv|Mzz8>S^G!tuE+ywP#9JWEI9Ts3?904 z>BeO)fsew@6wYvPbg)?cC@eyF3D;I-W>i&_*x~lWO7na|;-r_D=1`otxWW?Oe04|> zl!toHe0)#B1Ye~lnbeYdt-QYj%ib1fEC2O$>Wgsp@&b*-7@+Un*yi~aMJd0}n*m!Q zGfr0ep<$`Uk=P6S4CaPTKkMWe!y4xz zx6qb8MAbww^dyFX6)T*Fiz_5mm}tLy}j9Em$|Mx)!V4CHFSx# z&{`Xxd9o*5>SY>Al1j2T;Ynd*&YS*mS0pH$E&oosVdBTSzvZ26hULP}w%2vU*-R*E zE8VklSD#<+xS0o%Z)=rK4PGGRaZ%O3i|~if100 z+nUDgyVNtbeC)5`ZpSr)4bdSqXcWu4N9!cQUBcRb$Jp-UY~qxFsCS#@XvD9v{4MvQ z;VJ8N-^1gojMJX4*=7IfVXos!Q!nogj9$^ytiK*PaVqQKC5Lx@F{F-oF0cyNQNHP7*BF6*puv zD!L`x&S~y?n#W9)G9{0gWHH@>E$=YD(7zm9!6_3_HK&T{x#`!-tCWUM8!8g6yYj7k^k>#z6AyGTJ0t@qt9>!+%oc%Nv3dyWnWbhU{BX^D+ap&Vh>72D?+QNJ z_V`hfrixjv6AN?eu0H<;(uT>7@t)AB=xHDxNTeLHFk%5j}tHA}@; zuO?3^pF3C0#@Ni%tNY~`|KAziqDhz8$c{jn2TmMVCkWZ8n~P0PZ4@q+e_Zh6LJsQK zYwbx>wWW|XEOx4U`%RA&TJwjcH<)Lj>Lfh;C5))|7iU^milvayQ zU*|BIRGM+G`HUk*1jMCd4yYJ&3pLO7zL!&N_iH`X51dr6>w=i7o;pcZr`Pn zV7)1)ZNe|*D(9^GECTU4Xv*rxYh+GG z-d&Wx@|!Gwtqw}#Gs7;jQx+XOYqGa6%gY{|Yp(Lba1+VfR$-DkoLuFuX6J-8GHd&s zIrD~&^UXxK$=7w7_BuRp2q4l|*+Ai3ZZ0ezG!97KcWI5xCBJFX%ez1^kmSD}fhA_G zwh8}Scw4F-^}hl99#b3E@FdN#N@G0G(>c~0`08O3exApC$2@e_<}?q1Jb56KM-XMJx1f1qi9#Nxe(zgZd>bn1T{f#swGp0a^2?2-pQ`5EtJ_%@-E z=M;cEr1>|HE0E-XX*h}Q`fFhQTm8Q;2@J3-(w=kfFkWktaWI9vXN>=A2II8z!W7Lz$BhYBP!mwjQ}c9PIfn3TwA?^aCWJCX zXe-_)yf%*zV$7}}7Z%oo=}th?4M9szDZNb3@MZnq45PxfyoE@#qoU|}4i}_P@MzZx z%J>|S^E2LH;_w1-#dMEd6*1$i+1oJKK?@?jS zMWaeki;Fg&(LJU)kynq#Z3r&c1 ze5nkA@JreP6a;Wd`KaUVv+GkP_$m+1Hgi65jHb{f2I#o~zAv+sld1qVblk%nZ^CB? zh4sm<3j1Fr9+YoAE*UD-#j?gN!ytuP7DKUZHf z1mT3jEXRl1=(2F}@A1-I%O{|}5#TRR$Cn%dx2kk0de0t+Owd6#K1(b09er-lv~JKC|5K3nc!+h?{?yj(;Kd%@Yj09 zuv{8c4g0o%g95=v|*xIVkzG*`(i zU0n861p+l>vn4=E*0W_{TT<{ntFBf|V{Ae!Wk zwdeo}HNs6Ax|1nN4stBmK9)sW()M@9aIWE9BpnnM3#CF0l|UxE+zreW>tqA)4}^%D zYitwl{DD|p%O@HMui+lU31u6>0fa<~fbxWaNEtV@IHP|8v8}mg`ZcxnDw+*H_RKA*RX#Ee63_y$4Uq9&hu9SCVjIRz zA#oVjS+9!9es zbd1%q>Hj|^LWr6YM4rR}VRt!EUMGXzq^=YR=&gW|+LmGof(8teQjM9OOb7mz`#d@e z#0ZtkVAvQqq}oOvI)!RONs3vnFeB`6Oe67ep!cC~$M`cD46&qsFMfIuNPG-11#%p~ zUSfZ|kK9osF@oqEI;QI)B#aiqhzEH)qM!I+5(fH2=FrKo7)?_4T}|Wb3pI`#Hzc6J zPX3||4ue31U1gI9nX~!Jr&sGFXI^P-i+=K7nm?2a+^U6Ec3JNeMkyeJ0zZumf}i~S zKVl7rQr@cn(nf#m52No;NbQ)nFvHMNf#hgIA_7s1+<2S{{Er*|=F-j=()--t__39v z$PqF-nZwVwa7UeESS0j#qW)la1o%#P-zUMQzUD$G;iJmn`*Ml;7k0-m^B}CJR0K@! zhGCP2`M?WRYPk}A#>)2h&Xvl(eR(*h+QFZ!&_=**pY-SGS-ej?Pl>f3B>{}%_F_{v z3lsz8uZc6gh~mDGnW@WxgB&UeA?}CB14VoDwwvcU=(C0~M4HbTz34znDH z(~!Y*+~HXb;Zvc0kBGlZd7bYx=@WyZkM~D1(Nm9(dvqpyH%apd)*+7N6K?g&b zTm}n5tE;}m6YKF}?VH91D1F)$9@kx>1dXzc7$_DI{v!id`9xt1 z-bQjAnr<5B1@vXI;?Sf_d>KaJxxy)%s9#NkrSLA>NZnif#LFHmd3I^h-_b={TwCh{ zA|huYDlPM8ET||lZV^lC&3Uxwm2xy@vGDW&r3aG?9pJ)NG{OC|1A`nQ*Y!Coxh=om zJ$%)0nY(J3X2tf%X**C19MxH?5#ciVO}GrAWAK4tPlKLF;yY!EaAWS+_W?qun zhrq!<0d&3uZm6l?)jE_Ccf?a3&4U;LP+ExNN>Xg`{XY6)Nz13|V{F+wdom=LUiK7O zKfDeYYsf$awqZM27hhMiVs=Hu(di^*kIU=$cYyV{&W4oBdrzmKk~+h%X1Npn6i_w{ zs02O=8wEx zV9V$?@x9&61NR_LQ?nV1;WNF&M+Ia7Xj1{cVg0q3!jZQBNF-1hkqd~CQi;WOk04}v z-#c`LIU9vB8z#5V$TZruBWS&anxy{qgrd(4a}ocF`M#luiK+7y-?;0hPCOtIxOT`| zDL?lpXXo{yopiEA{1ctCv4o~d0|q4rI@`P;9bzb*=s1SBKpVhc5?L7qQ&Dn3VsMf$ zjplI_0@kszZ*OJfh%&-HKo-Ys>Zv|MVHtcLYBPMJfbjGC4ETFWEcEkc=l|`|7zPjo zNH>~90pbius{bdGY0T_rsp(EGA&3hd+yKKZqeHxxF-kw{%!Bwtw+Lbbz$|fv!_&&w zB4+9G?5{@zy<>?@)vjzw92iXhNdo^b8GtzLr+2?yv<*{GmJmZa>qm^F1z|SEQr}i$ zobgIwWXM4WLMf65tSuxt3})t|l?D9IEC3UcoOyIwNDGcZ&UTWYoM-cQ3G(c5jL9w# zLqT?7N$)m4Ad918^J}HvCqG)fyVC-wN;IM>J`*4kCD!^koA9*+zySE9%D5|6Sv}lj zE(WWZ6v>qU6fuXJ3%{YD2!qLB&oAUEpDWS=>jR0#;IcxMz*s}!(|`LMXj2ATBVS~1 zRjHr89bAKY7-VwZ?2_4m1O{k;(0$nRUFC}g=L0Sm?3l}qFr=jMnzbbG1#zHa?Ax30 z{}*;7pav2Tyystma8^Llr{zKo6Hze%^Qm21NZoRC;y!6j!Js|(* zYb*ZsZz;SW!_G-xzhuQLWrIfrQf4-rJF`C`K3l9`=V!cK*#CD-eo3l;fCB#ll%JKs zNCk-!Kk&-&#U z4dAlNwl{m*QckIR+FBan%qRBcH%>TFk*?E@)N6nEIqIR5hobZOi3~-*b&wR&fD`@# z0Vf*3kPNf?kLRNnPy0sLc8YM?0K<+W4TIm%7QF1yV3+_L#lIsp&-+6>%KYv=yqk^9)qu#um&H+#(MlTkCx}OM#XaV@-@C=Df3ihY<_%d^H|KtXMz4(~pcf$0iFnJ8uXFp`*kf5)#ad1NaEWbWs0t)P&? zU;bzg^W6yOx*hnZkv_gB8VBO-(lE;!GvS+AF(l~|;Dsc>BX1hzQ_H7JEwYW|`KTr;-01$$ z`OiR=zT3g85Ds=aCzW1^)gK2jVsNhVyXNoh`|vVkTo9pw@f!o+bv+GU>qhs_X>XLj z@4a=*f-gGiLwf+|H3ir#BA{oi{N$AonS){F`e{~hthOE{&r1NyeaaCqia6YRFq{gl zA$?)KH0~`)g8c@oShM|e^jaB`6Xz31h7d+9AW-#_MWp@*VFv^R_dk@0#pQBO zjNFm&)Z-Fj>Bot()p@?t+Am-5hFm0YBBpwQ|9-D{G4TKp#5=F%CfmcH2) z_FDae6UHt3eY|p@Eto8T+%u$;NkxKGZPiX3nctc#9zwejUWIJV-o9?0{C#|pSz}0 z@XWH_orwiwFIWC_7sPdqkkm^D?we*#YH7rDbZ`MHNVvJU=Gm#i?E)N_3+ECF5}e)!TP}W2WSYF7rm$ex051;-3s3 z2?*+*5{Ne5NVWAM-xvk`fPH>45x2URLL@DvX0sh|)9=at?mt}+l;~{17x97ATI9LN zr3w0~{1Ba#Dsf#VG&WOSCmggl%>md{xZOy3Z`o?-nxZM`>zIgMr0tw9sXTL=YR&}E z-BDO>PtqL257BeSrND25t|eRt2l$$R4RsLy*V4ulv3yZODNkub%FDs~_wu)w&uHqx zW)8ro;L{+gW6|Llg`d#NF4cfYy9L3i-juQYRlR5b=N>kTR6K1X2K&a9FQSV-wBh)o zUr~=8|6Mdu!;!5 z&9Y-X#5vL}FlEgbhkEp~D~T)Px38>HZN=wqOropa%VYGihm?IDxit&?u6)tGjX|lS zQcDc}n?_M{Ifj>@K;1yQH_ua~P*f(wXupg*KEwPjU14#BT}Zm{YT&gr#2Yqcjkicf z1!%uOwwj&EqgK!Y5B7v!xd5`m6;O`wbDa#AX}@}2%0gER__MJJEVcYF*WJ}F#HM+C@)k?IzkS821Z0t_1 z>WPBTnEqd2webzWWyljgvsSaVJKTUccqZT%eZ_*xBK-!ep>ZdmZKbG!G>ir~S_pDa zK_vvt%2i$th0iV2OFktEYc?SjWJ4(5@e>uF5-Tc>LG`lPc{u<86aS_nV({247#8w9 z_+j$`?Z(L?8=}HYFg9YIfJ!|L;|AVb+>J0UWNG#-yQ4#fWx)oqrl!S{Iv2hD2G`5+ zho4o2pi~I?ky)T)K+vGxbLX2At=6M6DFo+eWw8~Zh{rewTK{4 z0`}~HH&_m+Hi^xtkodoHNoo9#7SNLoMCYLSuBa;%v;Zamv%F`H0mQ`YJ;hAusq zge8sv2piT$R+61an5t@)dlMe`sni$)HNrHycFB=!i=a&dpY5~?3PL`CI$K0QpxG)? z2zg?;*5)-MUXUrnVz7siu2Ocd8=gV@_&zxdkzJ+qg5t;ee!f{BoJM+Ax|4^Xf?+S@ z{+LPXr0qFABj)(HpHg@T%J&a*^#NG^@>mUlhP`rhyUH~~CD>cjQwbA{0C|ACuS{$z zSI{I>iMaa|H5-bXKtLq6)6fD;T5<^L#otzdRVd#x`VK@L%AgSMmD(^%1w@tjbLff1 zr)F1SMhfYZH|!Q00ph+d@ob!B8`Q zs^ij2B3-+rBuMX7ym>Bn2k~ksnWTU{FmnEyMF?{#=W3F2vGB>xjKe8~7L#6>^eh{< zu;X5Y{i5i~#`6o6%ilFG)cTnE%R9}$=%sQi6qIQc_mR~%V9@_$->U6Pa54Fhh zg=VG^(4=WS8+*GFYMr;aUhC3$77(%i%`}e$pW$sQQ%y7buN$!lh3Vk^P9PaCz z=hSPt>9?zSx=XE_@!QMkX*# zI|5Bz+Tyhpyq|i$dLICJ>x+U6{iJ<1;hGU6J>zyxXmSaWppwmTc^2);%(yYvgf?p;o zO;1`S!_qW3@zf`~C0{bge1Gc=Py2#gWeZKO7)NbWnHz#9xe?$aR75nxSm6rqn8#|F zZ`c&7OW)J5WvM*G4Zmg7=Z6GA80v8{g^-jR`j?)|^Wo<{ z!*vFTE6x}E@TMwu254airw&pv`AaH~ZA}1(Jl2(38B!1(C(gvSchmSX4JK0_ zT2?$J(N6;ZR;H+S^5YN9sEmLG{VzYLb@mu1{;mB=`8IT}T{6DPAO-_#8>Xcjz6a4P zm?p%4##hDsy=7}VMJryU+ivU3))y65vgnGdi~!w*rNki2?G>mMUG^??!c=aglN_dF z)=4|VzTQu4!iDk4iILVy)#4F{wjFsgAS0k~UG+g^`TwMF+amTp);Mv9H8)$${m%}! z5*weRkskJSAImix8vI}t1F&!xSOl)i>6>}lfDmJHi}}ZhGFtzilz0)|#Awep;Bmbm zi2_=hKyr$R2GaWgm0lIUH`AIMspmMx3~-IiL?8EiRga$^J^SPsc z(#&gWgiY$4R(*p!X0=0iUBI8f@Vyz+77|a><#epiSyvJ|)}tl|Zm2@*h&^LONVZ+x zztKS3ELV~dwoJA7XTcdQfw_pvz5JTTqAx?7Kj=E38OuCV3QY`{z0BO$`C zreJl+(&fZbwEiQFw75DQBJ{zF`=;N@82xTg<^(1cI#CJe*aNyeSRpu66l=_u(mh)w#h3ExhMx%a48DJ{Av3J&&A)fs zlapH3^i|yJlsM>ct**STs5+xOW@OIDV57rGZ*xz^U}Fz>AY!I_=4>RG`qr?op=KLJ za(mwgDn;<543d?32=|HilNkUBoYtEis|6VjesUE79R}75vNr1ea zVDZMiee|P?l2UYpg~d|+zk|N=e!9huW0;6WI-@6!g69?US07m|QwCP{S8O)qoQWBd zIymZrj6_jW;zE)wur7dUhJIO!-lH5TmQAJ0A#C4fxh69_Q+qFlo46|eRh*?-IUNH~ zqsv#=8Y+P<$+2QkcT`D=_BiTwpA9dE)>iau>sWh3&CH2Yp(>aB|Jzf`mv`1UOo5b7 zO2MvgH!Q(I)4ujsCAdJW+vDY|FUQstgFU%Vst`t(%Uu)C4K8?E<(mBDg0(&rBKrOE zIR%d=Ohtbf(uZZx@wy%-KWY=V{z{v=BVGT)s0*|SpUyCBD8hIij)mP*%zp!#Qp9N5 z1PTdt-_w~6Vm2D+_Jc$)3w&sPQ?^{C7%YFvU<<$Q(k=QJEE&=1eF+9fKmnVajB4t7 z?7&pPLUeeHsV|@tmgyJ!<2Ds9aP#(7?(o;G+>ty+#ETUcf@ZvsLWd z{E6B`Lx_Xge;B~f%nWK(XaR-P@Q_8>hq_&8yugNxi<*qv)%Uz5u?idqpc8z7j);8L zVt=cq0Z__cyWe8d;B98=Ajic`-a_Vp>W(k^bhF{u1KoiO#`rH{_-=(4z&?}be?;S9 z0+oSnovR&O|48%4AcDLUjW?7!(?P*|JXm}VyxF^^AKCKW8?~NK{zHcw=z_?S`{8Jd zp%NM|!7d?Jux~xz;+-uC;z(;f$`S9!0x_W%(CD%C#y>5%Z}WJXrsV^dCmTJO?q~dd zC06WFveQA!$x0g1;R^W2?v^!##Lt4a3#5pUgFj-z9RSwrNOuNFL2=jxoFoynBCz2M z@jo%1@T|344;B~hDuIinfk0OAOJ%ddpW4G-5{$54{~76#txCOm3;0(f!RM&QdAi{X zf&?O%)!EHd^#eq6fXE?ZGxP;wb0lSvOraC6`!-$xCbW7#LV4GQZV(hOaIytl(SJ)B zjLj-g?j;K*;W2D_^E$YIb?t};(dF(}{ER{9??JRcI7O^u5&Vo2`FT9*0+?#7G&aeQ zXl;!Dqb=T6Q%L*{#CUVq`+}eYSd+an5;7@b!Z03!=ZgPxYc$0Gwb9_LEZX67^$Uix zz|q=~K2?8a%!l<8qMo9NN3i}T;wr)VI%<2PCc8*r=*?FPlyI;#*HDUt7}0w#kwpBL z=svXQcxAqMiWWAfA78W_OgJ)3z*0h>pRq1M@Mx!4#9t-|9&G(`HJgW?_eb1%vOc}} zw^zr@#UQUv_qLUp$6&$BlKnPDdt!i+j{Om|(bR8P<1)jX zV$4-wgYvX}PF@Z-nI3Ke>%mekVInJ9NG!U4d(!Htm5?Tsp^3swo*_|MpOYLAHs%r(Z7el!NjBYjeWI8}a7lXosw$4zh z$-GeSLIGR=G;Yt`#s$?Rh^6lVA4nq2brB}OV0aGpyl=y^uaK1?$-@2u^7djpu!vls zHi>Vxwh)8^b`h;Yu%VI(V_?{*sbfncz9}YRh_7*Wbg%@*VkX)y_WCgBy9pL4x?sMT z7ee_dE?~7_U@Dl)(F;^pQcaA43!~G~HN>71w+TC|$$!EdtUwaQua_Qibb|99n440} ze4F01Bw4v;JGo~b&$h23oVXTJr7X%?GtfW!0Jw}sL2tfbj-36%V3?*k z{Y~dWmj8LHQ)4%qVgMZ!&!X?Zb0-kw~MB z3VePE6(MrI+=3N{xhP~lgO3=0Z#wnHY5O4<^yqE z3wS#c+K{AWB_&&fU%PK3I(M02818gvA7p&fte%TbZHFF+1(@8f~PVpoy{THYFYR?&cP7%{db}1v3qW%dFhSM-VErTq@YoIe&tEG; z!I;(dn5-fOoi^W2&9gaD zAb|{?5pH66&OUhDE9LR^_Z)_pJnn=5rGdtFp@GUI>#UOTk9OGGalk5%F;%PuLrtD$ ziRc5+q4-x5Sx=4z+|`VxdOSRBv|~X&M2xoGKUPP31YAr@VPM93$a5g&hD5k69N1*y zFoVj$iJ=boa{cL-R^ae zZA`uIJ7{?I#OvW3ZJ4iLFdxXe2wDoH zVO%o{(49n2O0o~}L7gp_OD<(FxEXj$6QF1RcxwI-V%kL-D*adl6?o(tMTJG6yMa*D zv#$bFp#b~~yvK3Eabr`o2IxTezamP`Tz-0%QFVjl`4R?4oBKJqF0mbOr z0yy`1yFS>O1~>_OdYI-Ef?#>!C@~k343DM{@1dNGFvEk2kHj9)E8RUMD(y~t@`R~Q zSK9|npLAxqRUceUVz|)?irzh<;2Lnc3o43yrcwTtub~4F9fI#H2VfaV8Ux|Wn`vHz zXGB7L$l94dHzOjgwx-*=XUq}Y zz(M9ZZtU*D^d|1*o-P@3>2-SS<@Mcchvd%Yp_cJ52ZVhobzoEeTvj(Hki0P7e3`Y2 zo59xyuuKl+hp?ORNvc9u9WarRJ1pIqom%GS;@eGkBxyyeALBrV zMco$G6DgYn!66HR{13HRRU7eXc~Cj^p7&>OTekHpq{Xxg;Jj&SUxw;#Q}%`b#LaLX z9O4495$ztFX6nTS5d{}k@W8P)X&E^@y)rXbdp}&-mQa@7biR6Ed!c;m-Zd4F#pv>s z%}kSFc1Fe3;aIV#mtV$S(~68Sh-~K3o{*5-qw~CSNbP5mGg8wk>eAwp$b!ALlKcR@ zQvyo{sc+_qr1@cr^R>l$D;PSEtvU6bNLwSXBJAFMZMQ%n|!vqRZ}v+#E45L8NFDhC!DNOEmQ zs8fN6xk<62D~vf7p&|N*guzr}BpV28mI(+=CDcOtCv^}OC>zG!v7wmHgrPk_c$2PE zYSdy_5(zoM38*>gaRyq-pEFN%H~6DBTe%kc2#;6YO`lm2;ddXb4s7UGEpp9pW{8Ne zf9Z$1dtmxD^ywWNn+BvS@}kmyz06Hu3j3dzD2-@Fy{AGR6os+uOXPjuxVbj_SR&%{ zWC2HiZ$MMdM-(@bjPEv2d013O*ncbFC}Qq>&E|E3`79fo26)ab>|h+LeYpJF)##8m z2^$gdWbWtmoaR43z%n@n+f;2(i!6wIzo*y--3V6X=P(0Jtnj*z7w{N82yme)U$RpJ zJXge?=JF?y2-F_u{$415_cHQuvK*eWV-kE=M`{mt$@s-&6b0eNhet2n!#>1 zoJ5Drm2m%D*_7)JdXra28K!EtWysJFv`jSP;j~)JNq9cE(F+9^%A1114V4CJYu^<- z8H*5*bFFi&ZffSns4%a$3s=*LJ#0mT!Wvd$eV4?KD|ukp#gWf6`K0b9ON`zx6Fzp- zI+xfcYC-y~NmSSVfK@k_vhZ>lFG>Csp7psA#IoUA zL+hOt={p`iU$~mQ^ja9Udo>8HKeGG@xZk|EeD1kosZNaw>sZyIVoC?n^%rj>INKdp zjK_k_ivVHHvpdg*NS|#5XH6sqxQ+P{kqNeWB>JzNr9xujX6C{h0|53QC>?dy|^0n*jtxN?3uY)m>)YBj83jp{N32)vvp$;E zOrLHcFop?B_u6hL>bMKZe*gZFKZDtvx$M~WmZ-4j?a9N{m3Gx~Gcu~0N4k;}YMoPy zwC?H+)=6O{bUmW!wN|$sg);#X9ebdqE4d+dzsd)!pNizdOdCM@l+Qw=JDALGZ-#CK zliXZzN$g}w$q$4_8?f*lbViW;^4dH^y@Skyrzi$KG>1aQn!E2#cTbySpd8qQ)zaZU z&UF-qT~oNe_pk{LE#6cBxw?sd(_%l^7H z7r=pimq-wgD6(xH!N+xYzJ^q3jkQ|l50z@&0KY)6{MlnX=+T*~i;#py zcc6&nOU{9^kGlJ<#mgVM`GS<+IzV2}<{aR_k-#;=#9N~#z>|Lm3NhlhM``wMgqc@3 z&V;y4GIZqb`e?wCPr-4$JytY@1oCAdZChJM!;?nk(1Ja6^5oE89BOw=2qQK*mQ6~pbe?vq>{7c)DQ8oL#DyUi*f}G^p zS#d4YX;j60Z!9SbUJpqy;vF#G#gvbAfuBW|UB0>aZ@_fEHN>qTr91kLCs4G8Akqa) z`v+*Ee8juo+Hq~Zs5ln?W4+WOub?G>#-KIV_j<^H}^zpUZU57KKwbP#`te zUyK;!=$bBNAdgt_i~F?2DwsB&F7nbkz%TM*eU`tz6+FN&5UsidazX%iV(x85Z4x+d zzKm2fq!Y*qiqB+YTS<|m#XKdmwblE_Z&3B1qX2SFP%GF;u)+T*=94n^8!v!t?B+7J$ z*CE7q`AcpBN$UMj_c!42k32&Hl$r&_*4SG$b4V^Vg{G zeUho-HjkS*o+MiPy0`2q0{#71euS}lJD|MBDOp*SF%;@E!ROHtexZ_S>YNa3X_;Rk z+!mkq<>G_I107abAmWfCq?JS@kNs`C$EyWa4z8IHnkTciKVY)${d!9^4ZfuNa2ueH zg&60X3Z)HY!TmX}o?LKZQ?A2+cay39a9Q$&n3H@U=RDiw%bZcQ*Fe{c!RGnb?{y9I z#P-fgx<}(Z=h<0|6J!b#1#r2l2Cjh4A)`}Jh4jP8Ku}@aaisgLDS))WaIV|P%ygu~ z;KN0zY~L%L4|5WU`FZ9p0jOW2xW_%odHibvlT=)LV0x0Vlk&{aAJOk43k>GKwkJ-R-1iz@@%0MTlLZhjaT9w&&FX%(8^lSWnOZ&b;wxJletqB)kt!St z6g7FIzv3#Q-m8!AEh}pR8dKa0C?SW@C?06wo;ZA~xup?FUbe0p3JrK38;g*O`F$E_ zPay4(^|fzo1{}v=BVgoPI*q*)2bCwYGVcCIqbNA)pE_2LyXBK&&6Nvd`5^ z1wmv7zM|ieIn!_lG`k@F1Cv3BE~-F6NGb;~(Snj z588l}fn%@k31jwsF0A592}mLIk_oC2NWkw@AJBvT_r&50F}N`DKoL@4XaT8pc7{j^ z5ISm-8K&x#%!Ek1ZclJyz-UIZ0I*GjET|I`XLE1STWn##F*W$JCk}iw53&}5XF^D% zD{D=O)uH3VmgHxNL+$I`)>T17ah)FeGzqP;eX|_iNpot2Gw znI`t#qYP%d9V4J*dos~zuQaOq0#WO-V-)kcdieDjfqwA;O4srJS8JVpuDTArVsBFP zYs&F=@$jBMc+cvZ$IchuTI%ROO1u*<|_Swh1}fVZNjM$U_?J4JU`8J zQX3tf)APTun*#FpATp;5N6pZ9($F&~D#H_y!(`h96T|4@9tr4y+Py!jm&$=Ne#^K> z^43AAhSLnWYFB9({dua$;iMgU?<`qq{1*`?8W(kJF5r>Y6JS`VUHHPTw(?+Qs9g~6WSa5v`|M=3%!_+nT#Xn#^{4?Orkx85v8rHso{XkT_Ph?=1BDgqs&_I~{R_y^bo2 ze!!E*&>FLt$Dve~Ul*l*#ZOH0pwA)+LLzKP%7#NRBnmNMCE|FvT z5poIqGNc7)v28gB&+EYXb=W8wkcB)hudKi>Egu?0=V4is>V!Z?36Qk6n!7cQx<)Id zL9#M0oY%!)^s3N5aO5whGu*jl= zW={(kOkQmU6LP({gAngMWLC`=83 zq=CKz@MpRq4=SJ(GxD|>|47@Iv_N85?$Ki{;5)QIQSwiQ15r{<(iT3CX}4cBw399) zlc-~~|Jg~JWkzkw1ZY>{d(CIFnxX6@0U`_#qmgrY2NtNVNiq!c;sz}fVTcKIO{FTJ zxVA^C+#u~;l1+ddnQS4N2IFXIA%ci{nLf4>IzWk7f5YN7^gnqjk)AXzqx2R=8I=F> z!8TYJ{E|lhLEG?=6=0yT>IxHK;QffX^R2o>7_67fl>rh>zJzwl zS+)C4D@s4_9gkyTj4r1c0lSy7!is6S9 zNcS|FZv;voeSz?dtPF`B)!Bn26AdB)SDq`h0E$C&MI1HZn&MfHWlTCUX@=%;7&em$ zdrB&+g(d2i#InQqm>&o!GxeOwbzU6|KN7ScP$?FR>h$7w8xvW(1fw+24Yz*kN=7?N zMw&&5($RW3Op}WCf|OVe&y9Gngv(HXXv>FSJpl-)jxu@(EnJ2g(oOXmfb&VzBHd`%#Q=kvK+$;6ln(v-w?K{HTJ%U?vzpdBv# zIB*xPL9ze`1|Iwo@hI5~5gD)vXj7s|MS-&5s8{kL{>&&0gVDBmTah7Cq}YQ6Uf6A{ zD8i$l5&lEnd-R4yNnB_n>C*THT{GrXN=5o%F%h)|M*$HnnHvPc$u7H$E~kPTWPts= zhbRY21`T1yVJx7tOL(JhDUXOFo`h=6KOy!R5f1oMQgbgxdEQ*1|jGYNw6e$%_gTwG z2M07x{(|<3I=r+^?rd-R!to9h8!{ClfL3{BdB1XcE;-xPn*D z4KOg)ql-c?;v*KUd=Z^z^9Q?-e3Z`WVE7SsGP;yN7ubf)YvxP)p4G9)U02=M{4dtA z(mm~o#Yp%)v=1GKWmnwL4dqc|WReOk)9Ofe&7vn235+9uLJT@;Y~Qtk)--DR3wTni zpwSmd9EtLo@jwiv9lbBGkq1*~FTv?tR8feW=(Yzw$)JI#I@o6OJ2?h+HFzbSNh2C2 z2kwJ7I6yEco7WZOi2aAqD3?TO0)6O&wlmP$p7K<_w{INSTf%$*Fu>Fl{cS?Q0nkx{ z$vEf&4Ahxe^ye}|JUkT#xxeRFD0;$>ovNm1;^Ue@u!$qM-aY`M6)+z^V1>c##?5OA zlU%az;(eyryh1}1{5>i$eMoecKc5GC1>yOmEI>JnyHpF$PrHa1!v81ZNtdu-CyLUk zlR|i7(Z-Fga|5EN1P!~(=cnQM=&h@iQYCW&I52euSup;11| z%wr?DKySKZHEAFL@cp-_Fr2t$oz!dmAF+V`G(7GZOS1s`K?tIK!BFWONlVFL2-SbA zS3p4preayc;kvLE(w-H2XK+~O{txtr)TZ6P>17+4<%$D96u~w}$M($}JmIG5v-c}f zs(Fc2>PVV$tcNH5ft{OKE=#{BXQZ``cN5O8mZvXV;+?Nh8QPu*Q zbeNGuF5o?0&^>s?J{X~!8`H}p3hdBu-*$iwb{i?^`~S5&0Rwnl%6ou}bQ)jQGp@vf zC_uIEMX_uPxih&3tS2AfCwR{oVsbIY2CQ{b4cK?6+48$MAqLpQ)#d*L65=&?@n90@ z=<-E8q=wX4mrE&r{szMmzHK(_F2f^Eki^jo0edTl?flsAT#oc$3z*_xQRd2lz4R?l zO04y<9!$4c;@hBg<+BWhdBcW}TB|F7-tg#VY?GfU1vVv?*pDh9a=sBW(&~O!oSq`U z4sk!#u^0vbI(QvWH3|a7Pe2iS3YLiIg}S>np6!9tuZ_;-Ya7TJ%|r&stBUuX!+ zP^o-gMga`30V$;z$xk#8C_qetkdhU5eSt7_j0qS5trq*B^tji=p>ywe?gRll2vR^1 z3`JIQKno(VG2}_9Q~#{IFAAUo9LKRkrV*q9t*I@T64gqamcX|@uq<7|MwBD8VToJ# z?WsT#9BAIM%eb-ydlW{TBRfRMc_i(D{@p{f!;}51c@$mm%^9J1-dIki~X8yXBZPd#kz05SNrTg4;d=#${sMHC#`Q~%3!ku=#+0AJ=y zPoBDmS9eC~Y;sA{KjBeWCqIlX0v*Zb>NShtzz@}kixKhW+nN7Tmy=0D&wdqiu2akG)1;zv zZqZg#jZ_a$R;bAg)=6YA#sBltE3nE@6^A8*F-GC0Qvh@sEB;@Iz|xjvoMVj|+F z&vmt@L;F=0H95?*LX}ZKPFUb~I>-P9OPHNN9ZjVs8bK@u$EGa-b%15lpQ-_JwLtrG zxd}i01j=AxYjMWJ4`z~C?=T3jf@#zW#~R^BKn)Ir{&5Ta^^Z)wY4gbtLD0~c@;VrB zBv{cro_1}L%4`g z@?;M09Nkml3t2)$RZ6M&csphPU})$ zH9Maob09A)Q6h{w$jO?h`DWZIIC?T@V*(fZM7>;JB4#jNCZh08)DMbap=sf&powhwj2Bmauwf zJ=2LfydNTDS!?t7@S1Fy;|TKI`p{q9Q@i9`E~=eg_G0# z)T}TvDjoipqy+2(dvV{bA?JUgGoCtxN_eRSiMKYKpr1iLev#>nNr3!P#AruCh`|5nsrBp#ea0=B^IM+zisM#{uk&WF; zNOjm?hjt+K_#<48z_jW4MFAJog&(BPj0hr{4of`UPuZw>CX zmQx)%w53@pI7~!l&ybh%2mgYNn@NqpN@&t7-)RD0b>NW4GP(m6U*v!1giQDr!ogA0 z=%Td)yDMT3V6P3FQG^+9=NR;G9scPfoNfvf2YMK$#rx}J13CDCyB{V1E{undzmQ37 z@GT{9XC^-6G$ggnc&sSiYsTLm3N;XmlF!P`Kq?Dd1m8-+DRyw&#%7>2sb4QK#Vr@N z5@+ws)(rD^ct{UldrM7CZ1o!nd1md)Y*K8kcLY+j9nPrZ@Bs5o~Hn$Lq^EsnJhpDq_nse}^^C(Vb_uxWrE z(^Kd)7{~- z68Ir3`kQWG+JHOop&shvEog5*n);k=(d^<-BJ~WM!UMu<_s%(pGQ2os2c^L4kM8tp zF`OADanG1|CHk}&`Gy>bZ#AwE&Y{qH>5X&XK6Btel^%SV5x+C{-+MfR$u~bhpRQo7 zj`|(~Q8~dxG1LN0*F(+VsE8cIyZXArHOU`?q6TOGL4Cx;l-c!(E}Z<36}t~du;fOM z0L9~MB-JJ}6hlDZwKvfD<@QEHhm~ufG4>FYpNd zly^94M0Mf7OVU@tXD{GF^XEHnTQ|NY!`bQa@Nh&4kDyBC$TZ}CtfOud{O%3R>4hUo zHd{zB6dV=KxBQ~W&4sr^szg4QhrXihytgAvz>JotvIE|&UrWx@!ucd(ig3a_9QC5l ztdb9lDS1H-!LoE)N)9gL9h(qeW++wJ&%O89GL^8qUv7 z_LL4_N(TfN#hG}n00aKhH=4i=*#6`O1aF1!FLf`amf~Tob<<0da&-6w9#}qgxT(grKf(fL96mLsR2l2lGS|H`0fGSesKsE} z#<;xwYimCD9S**`#8x;|>;{u)uZzH!V}9jrAd~OZ4OozO!BEN)=5jJ-mp)40S;O^e zfeGp``K|rjFAyo~L|+i$_8!YE`@SB^rgk`5f$;nSTNQ)j5NSMKit-Ad6FcT?Vq;s| zi&bkfUMi1!4ugCOEXL_|8y%{g*Leh;f$!}3jI12{ZEmx3-TLAE`&clVISf9?2_GT) zf0TW9JlEa(Khi+ctRzuUW+Y@&N=q6@R)s`HG9xn@c8e4d%1TDrtH?@ag=A%~tc+~G z>zvp7E%*KXe7=wG?~nU&=kXH=e;rmvVPtRSh2icKl4mm8?rGRY#4O8Q+>+!hW9!JM8WofL2 zlT1R%!>ZR#9bFN@H#1q&*}b)$7(Yqv7%kpJ9(xoLB)FS9*p3v6FdK9QaxB*Hnvq5~ zGtyj8CpSp!V&DqCtb1GM{y-%+@JcXJjp6kP$bh_#X+Q$Z`<(o&=b|?l(xA?K-U4T6 zd*fbg9dN=EX|s{<7(MRmvu|+M<Y#RsS^(?>KC3mCLu#R;2RTGFueBD#lilXWdL zcP7n-eW*bjqBI5F(BS9cLlZ2px{M6q0dkp4Jc7JwJymGOAU)lJBH>Iq7BJ{Yx-^4; zri1GcBF1;pCD7{lW50>Q+)%K!Cyf%PAAf{_BYOdNT7w<5I7U9qgCyKXWn8Qb2dh2o z$s{BrtF)$)$$<)-?M!-aznlIA`e#3`W=38<2_d8-yR)1dl~R)o|Dj)SgwTe}A|o#m zM*t`+{*pKW9tChPhO(f3c*%@i#^>OsFgTInoHq7lo!9e&tLsBo`;uflRHDZguaki7 zydV|FI`^5vH<)j|KlL!)-4cd*i~LQr_lW{{l6Mx2xfR8@5Wp*RdITAb zKZ`^(HZG6gmjbtd^nw=fAX5;S*Bg?wc*g;~4H=|YgN^|+<11=~iF#v_2S?hee=p$C z7A?60T`;Rf{Q#9I9K5lF;D*=&AR2<4?;-IafUIt(QbBG7l9ThZmk@j!LMW86iQPH? z1}J&AVkv;!(7$XCXxgD535zV_9NhFs^fDv82_THg;w1o0!#m02z-$(29&aZyKsKg( zboIfg3=x`*2J(T?o0l!(b>^6md?5$#$Ov1iUaqwAHOPF5B6>K3WP=X!=oVh#_OLkO0;^9pHFVaN&3}_Ls~$&q;wQ1aRq@#`IG50kLy%TNtXJf-PaJEo%1r zPAh<06WXv)Df0-v?KT7mk+F|JwH{DzmwayJbRG^A+G> z%~uXi%!dSG}@Pc9) z#3PGnEYLz#5TN$x)6Vu=%flIH|Fxk2Mr9Q06(_+~a^VxZ-pn+dt)#$~#&0j^zq%S+ zm%76RgMY-%A@`NUQZUHB-ZgpckjnLX6=NTuVfY)wI6efAU?-p>KG^}sa|gHZns|;a z)vV40`WVz@ASRpG9(`1{NwlH+w=*}wVj@ZKe!8}UELUdBBUr1BQfX{cf4#5~L^E^= z0DqEm6N(&Ao%;#LS1`MQ=WpjAay71|CHMb$Cb&;Vt$Q)xH>ZL4gZZf_y$&Ow` zc`!Kyx3x#19141XUc_C4bs8V5J0bKBaVN!-0A7s{kD!e&dlP_fY|-N&^%C|Hjf5Gl zWM8@dK--ZDqTMjKf!`xWFT)90)ZrcQtu3wVWmw|&l=H7=*Y(1E+fnJ9ag_{9OLG7O z)uG)2G>6wCVk>q%Qb47nc?cvP%w^;<2t#KD6x`oa7KTQ}wv82A@#g!;`Ubo*4gJN& z4#>&>b;xDRIT=o09qVO@IKs@KEky${4E_7ywA3-!kJKF{7#tx<9%P0l0(!{ZAXJXV zA-Vf-xPJwb)hkoiNp!bgDLXN?hv?1jjl?J@c(jD`H*X=U6M?1f2dC5Gq3kqr<=|OB zelH6n?*q^>C)G&M0oW{CY#u-g8w#&N?G{iZo8+#oAooll!0ggNMDj&gBTS}6v~YkW zqXVR9&*qKDd<3Jjoy&eBgjz|lpijvUaRF~7!lGxIR5khF>VB)jd!C|8t$a%cuw>X{)u2>h^XcOz??`Um+xk~-LPLI%R1U>a)4u`Qe~=C1kwU2_YEiOiZ>}bF zMEF0-=pErv;uSYLC?w;MJOiAC_f9*Ehvz zYMYZA(SsuaotrPmHFVXlizbU2*|!i2i7ZG`Q~|RDeZW=W(ixQ^$P@Cl*B6!C-L zT}QaK|id-;gLloxlR&VY&gSVLyf(#tiJ+R6$bu}nIzxyDE}K$}oBIJJslS~{`AN0c2QbEr06xb6$n1_G}POLna#k3ffc z!J;zka^T7&1xsr%;FiYfI>Xq>r%5ehJm4mE#W+&Fi67zC`2s zTsomiFV|~NL_s1lpk}}_kfgvcPDrHVATgmuI@vCTGXe2QOl~n^*GSA|(fP|-{6Olc zG5}#U{MQGdMd%O|?1BSs@22n+`oiZq{BRN$cZzSx424nQzVOas6J2HNE6LeP|(VAmnf2hUowz;(?GqlS`I=^ao{xf%QPm2o|w2RXN|GsRe;;w=qgHYBCR|B58UAjw*=3x`%wid47^4Oaqc%Pg*rdM-ljpEi#MCo@LT5 zNoh5*98-XugE|LW2B4Uv&B#)(pjh2n<+|*Ithn+1wh=CSf&#+-)uJT8TPS zlD`1iG$`O-^ez)uxhlvQ7XFcZK|`A%$6|OE!!g52bbJh;7~-&`p@R(kT~9URV1m0W z0AQUha-I1_)CmC3j^$w`q@CrQi<=1Ih$^!6GXR5h*D7dXPXZspD`5Z#-cTz~*nuSJ zL5N&1Q^^|;6c2t2p2*@sgvI<=X#MEilB8ORby??;3e;o(lKY^G33)<-=K;1LNdXj+ zxo<%1f<@p9S?CM|kRW710p=bwM^nO0&7m{FRQ9qzGa(g7%-Yd^k_Kz>I>7vFgOfej zz=KE&nJ4gq(}2l>0>>FpHow^N9XW46R$o8C>=pp7VMI|1(oAn~6O4l*UQK{xd-RSR zM`#+y!q$eaOvqo51QGz!LC}2op`3$v1fUyiZU2HHtBRImuO)O2^f!x(G}ZPf=*-RYzRyG{bOj>3^-u`E@+3 zl}c&0xOndB)TaaBH6EC)VK#nbeb>)C!+XHe$Q`;l09bTGclc||;Sql4OeWmT20&`c zg$+4a1Vmo9`BL0{$h?!TA5>&Rpd#~)G6R#)W81&A0?J*7DjxCecUXP^M&7vuvrxK> zKm)ne0F3hX^1Azi z9(N~A+SY&l4pDA{01ZH#B^s_^+b;PbV#>B&m;(aCOZmrprA;{dT4KAq6a`jaN8~nptKfRB$e4T z!htA6-tk&=cuoL)0GGYB~v>5A%;+ zduOs-khlhD&_M=hWCsF5P*)JBR)_=aI)cN__1;XD$os=UQdNNN6#AzY0s;5305S+v z6wvr90`~@F?J~qJ+5yw4|kbzf~wTQ=lKZU+Fl`XqDvfElWHMMLck! z*?B(5Kowm>Nb@r5w%yEQkh^n|s^^kPnZ{*Tg*IqL!-bo+AV=;qm4`dsCt-Q>Fj8s) zdl1U<=I#x(98TX9uU;Z(c?S36kwWRx%Ry*9j|{wU_t<^v>X2aQ&OzSJZs=B1U*tsf zEe>ssK(w6Dr$_+9+II52g>X5DX?S-S!~v*1&JI|fsx3>_oS#)bhtF+6c>|~gDvyt{ zzO@GIAkxru5_OtnSgxDYS4%YP$LI#$a~I| zdo^6w2HJ;9#N+l{kj>T6VmyalNH1_jd&1RmdahCQ?P@UANYPBo>K4R~lXZFr&SwY! z=}v_t|I!N_`12jzR`@*tEoD9&n0nQZHv;h>^rN<*wcoCF}9!E{0rd$ zSbN2I_?nntw9iPrnlNt=9^LgpT&RJwaS&t&Un(TbP!>(c93q_nuT_$>cM4X@7Bm#Z znlgXAE_XTyzZO^4uUo>2B$m3?AoXxv=9Lj1Ltwo6T+sZea}o{<@LF9bi4DwWb}b6v ztTh4G}q2{S{QPkZ+D&_fm){NhYNa;;oVfjtg%C@ zLP5EQ1r`}X=^IMIU#IPc;QE;!mZ9X3!z;m$47{tzOv7Sz?jYRMj$%2}JKH?i?<;-{ z#0RP%tZ>TozT&0NS2%2YM0FP>D}RT}Mqy=Wkyd8&ToXtLi8pGcya6!&qbdaRP4~{q z0sEvmg0xMW&G^L#It0bnOX4{F6*UB*cK_>2 zmI*Tb+EoLM#eyPGkNn>XvD^76$qpf?46h#G)bdkSt`8p(y|djonqI;jpe7lh;hw2hbt z3FN6tChcEwQD*G1|8;7~&m$id$)#EYG;b0lH5kybP<#;b6Qxm=aacw|4tbLJDLvj| zNCP3u4%7zV$pW*ZC@<(hKkr#MU#a#K372stbNX$S_8hvY##;J907LXz3>WJ=i=rNarEPLHJ65s-0TS zkCxy!)C}Rs5O}cvnc_IZ8wwDNel0@JQKbtWARpxUF@7`V3IcixCO! z9Ibze612tAb5*#FYx2RjddrTfN>t9+ z9Lo!QY$!|SFH*1&!#k1*iXt=I>wk|lf^=P^X(9?m;-_vPmmlE_FLDa<()0D`9K1s} zzVCi`A*56nN@wxF33p-wT2{c{NdPex>2)~|hvms1!_dn(6bLM~SoNgq4Hn_z1yXrr zi2@=!J|B&sa}m{LTP`3L$i(g}=1P_{3;>2e_K?>C+>S@GRnz#*n{p>9d5$j=86I~z z+Dm^Q&7LkJ3o}SP`)rT>Nn}UFw(LxOx*P(uoz z_D0o{K31sHesQr-WHC#`VP*|DGDhYGZ1;DimGe_G{+G=QN(6(RLCqThHR^N$I1jwd z#ns2j0#dyVZ1`g+nV4?*`niFc?LfjxUsa>>-Q&&QW8w44Q07_Xkr%F9B z*yyX6J}(ObnjTlgF2S8AYJm*ui=Bqc_YL)79YiEW0a;tuJC0DD&aqvObnQu zPJ)`|Z%S~b3|{q5$@tr(^QZ^TKQV-rMg$T@a%q zCr78ghuV3^!``H%5H6}90JcR=VBkhLPf3o5gA7DL7&y>{+|s|HJ9LBzyb@Ay7{3}J zRge;MjcAf2Fl$Ll9E2VadLsr$TghQH2;)f?J%;Q_ds@LCCn|D+7!wB|Ds2MiV$f6o zjrCuno_yt?k0c5jH8`gzyaaoa{M4 z%GPr4>M#qP`J>)Fn|Ng&!@D|}wxCM*x^N3BYWlz89*%tqU};$uFARnu2r(##Fb^Zw zHtKRVzuEzfic$571tCRn#9jk}HbmzGwl=|rZZ#ZLr?aS%VvHbQAtyV2$YYF!^&oQw z&b9&+Hv(nN+OX}mW;(~f>FL5Ba0(X+nb|)=E)}eN)Fgj|F9Jm>(TIL`OUmPFp1*cE zq*i%}>X|ZS5b+Q=`awoDhMHmx{pIu}>8KF`DwDO`kbaDUT2sPTsvr|OlMwAM~u%Juc z0c?)UN0{b0ROtmVBT$=21Hsl{B9~oYc>%#Ei29?JVlugd>@63-*ugu9lnBL!%Mt?O ze8M6D$>#3j;7B>?zXTSH=yE3crLvr zfFwMTq(m>04aK!nq0}YGnT`Tx_wIe@%llx4`-!ljpgcfpEc|;kqQw!bzi3p1&!UXLhw2A9(NC@tKRkwgd(Q8|( zMWE=8(1odlb>R54L#)Llw84d%ewFXSoL#1vDU#jg6B!jo!C)_s+3F_UIp64?3Z)^B z7Pe$xi#ry9q?1R(?_1xudzr{F(?Fq1Sb;dDHW(FHG%ovFA(PH8dlzbEY#{gKBHp_% z@)S@Lm&~kD+9s4r;ZVPoCTsi~CX%Q(wQGlldCn1tc09p#2TR}E?(gUlQEAmf9=ej00xSX~r=Er}BeAlVuoA;F7EU0GqT z;d4-?xEc-O+;GGW?1kUuvH@dP6#WOw4)}htxIqts zgP;;%EM)eDL@{PB6a)Pa{6jj*VnQ*o>UAuP5*khH>evM#d2D0r5pA?c@mmU77$Gj# zFd$0+Z2t-<}DcyX*-p{zJx^RP3W$49dfuN z7AMRlP}sz_C)s-BDJ+J4%21+Nl)^&`w+xX*wNg$(U=Gf+u9kxZu0u_W;2MUCreH+s zi<}%q?_H{TP&Ind!!QRoAvjuj0!{-%EHf6xs>${_>kQzi*dILYIeZ)bN@p^=oO}VRM`fq_06oXEq z91d}=$|MYm?7-^`ztgJrhZ^d+VSy3NA<+Rcok%($`;+9t*ON#AWkfxfF_QH%h`@ur zhqE3y^0Nk!kGzRUME>X@O%70lCE+Bv^dZoO4&D^B$kiZ?*$>LJom-IYi8IhJoFD$k z+-O@#_BKTE#<%2=u)Q?1!8ot&*Y(>qAjml^6vih*58s(A zo5*NFhVi^=vIr;6iNZ0=K^*1SsZ7-A_T94kL!1Z2cW4?w3>ZHH-D5x-oJD#LDjvbN z@p*`i)F0h8M2!n-ERW6#olb+PfjB2bGXiCW6E*+&6&lbCp_n;;Xk1=!x^z_wlua%b z-&sq=w}D26M<(%M!a9aC3s^9(yi_tiUin}=2V3z#?Nk+8G$1GlAgt)c0TPlJwka`V zFjh&D8hw}DED(iKdOWMW^KGemz^NdA9?5)EsObDav1`B*7agOzhQBLF6lS!h{!nOI z>a69PTD#zdM_ZLt34zbzkYMWDZK+7bj5dHJuS;S?U?~S=Q<3cvG~9owee@9`tZ~zf zau?Ejq|f5Y7M#KEPeka%S2c*pA$WiDDo~DTL*7cHiXsf~s|e*TaC`_#8ez)FdXpjz z_wNM%Yy|rn>$IiwLnOl19uXWMOAjb8hemBnDO8?>x}Xk+04myln2mY(;hDQ~i!Lsz z7ZQWg&A2>sZLe^#335$7RLDt^VD3Y~!h;|O+Ea^%0pa}D8#u>{X1!FpqVX{Sab;tfN6D(C z{p${n4RB?!e3hO#d^**bHOGUioKoq{8o^!qC57=5$&TOO`gSwBzB3YRV37WuUs zq^^3E^Y2>*%V5j~fo0Zl_;~7s!Kk?`Tv_fW{lg314JYqtj7GCQQ&pi^?Ee+b{*M7< zXwm#AdmzstqT^D|ucK1p@1;2aGg`k{@O?KknPy8Tq@K1Jk`viwyLRb2P2)L$f$dl? zV{$2KS?13%@+@cmMFm7Ac&Ru<9o-aeL*wU z$3R*wVVnx`9D;ZtX1jOkhaBP-L}M?5*TPCx*nQ|Fs80;`IiefyA(+jJFn<;w)YM6F zn`tIyfO2Dk+yOAhUbpJ*0BP6&$A-#8?DbYZJI5^-rgUw(@%kFt(l*OS8-HK_^0Q~M zF>cVkJm<=E;ek3qZ*%9#;f6cqq4Og_f^6`ahOg2;3MLIGeCEP?S&j)qh#AIGwsqiQ z`pY{Ho;nHL{-PzZD)NNa-9Wx%73fXy3XU=*P;bP9d7yY(i}qbAgVO4YX>xkyh%oy1 zIr1`VaEK->sZ7MxWCY#R*jKwNh!2=33f3$cty$CNoeveSWFz_?V@6!28KIvHTnMyE zE>S4u6nqMij$E@5_jkS9&kAbjztF$WasnZ603m*q!Dp5~ko!RwsSCX<>9wSt-TQWW z@jZebz2px~YT*wL3f}-U?WdYm%Sjg+kHY!Htd}~XC${mTk?1xVxbx*R|8sxQ0RtTsC07dniRvS#mV5FtZFai~l?pB#=;z>}^ zz$_(j=PiXR*%V~5FNzFLB=bljf_|IIj`!X83P{0C)Bs@qBk;t@|MASH=RNnG?#L_^ zl}I##03Z{qHy4E7ZbruI4wX79fQ@@MwTnn(;N`OX_w4&}v3#{&Z8Ys&2~Vx3s4~05 zE$`P&Ly~HEK*Il`Yl7K6h&b2<%7-brEV7F5Du7%0R#w~Vx%i^sg|vRPmRm>?ci9Fp z*{g1&h|D65Q{tDHV^I%~Y!yW>nL>j$KguRL{AMLw-4x8k1`NX5c`04r)u*xJ#m^{v zM-Wmb4NGX+)n&#?me6Rkj zorNTReBsBth0YFvYP1?_qW*cb0w+gF`mpz;TWS0RDm;?nFm(#Nfwa2W9lMg^=PV$4lxKnuasN5I zrrG*f&hZGbqQsyq@1K1}R@YmoLz=ioGDcdopZ(Z(tG#UQg=DK`nqmXZ4*y}nTQY5- zvI9Ih;VM~6(tlM9Z`#%aa{)<{Fj z?^7<)vNFs;&t=qeu;RcfwYQ+Sz^kjj@jSasExL_R*N*kAH3K#A5A0l$1+BI2;Ye42eb6Cu?~CQmyt!sEfo#do66)gX zz&h=)x$EZ8B>4^5b+F&?co&WHU^0;w^)n_v@()P1E~dU$Ll)UO2jPn5f|L?TxN_{6 zIL!b$nwE0g!2GGjf#bVAlV9}j4*^4sV-td;rofK+_uuQDB-hdaF@}UmluWpqXgZ;m ziDv-nZZ(x6R>so?1*5w{&VN2$bm>;ZROxpfNW3Va`C9#1`q5=2>aPERG$0WpQ z<`lui|6_f?QEJWDxy{tGyhgfm`q!IvcaWYA{fUqph>OY>F!2$Tn% zcy+939P}%&e)h4u$eH`$O(SF7!F5eEp;;|qAssTzFG3qM=6X}B zk1@x9>>WhL^sK>qx&6C;=;xb(9mpcL-e!9KAP7s^BikI!QbJt7)jX;6jCljd zb_FDOiMz%#LL66XgNWt`JkeZM}^4%e5>6?aI+qZ3Kjw0`aMa!4OwlZC0OPSy{(hL60=C)w;IGjH06e1_j!4~UGciR5utDx1i zF^r5=c{iU@@5OI3FtgT8UH7ba?YA<(;Dz@cmFKWU-i6J|jYxt1y?~w1OAuDD7m@hI zww7H`_KhZ(E?~>p2C*=nCQ$(E&>>+^9V;`c!LNl7Fm_tOv)}fP1Uvi3%1&w1D`&6(6<^0KNBt z$z9D+WgRcTl{pnbzXU1`F0f?mcy}R5PY3Batvlr8sr%yY% z1nbn%=zaIr>@&Et*>c71I_W7m_^4}Vxhf}u}owegbsF(v>juSQF&AwyP- zQRVSi-9HXn3?;=a4XE{-8J2G(O<+-L|KkpjfB%#Nla2PPXm3n8wzw4CVg9Q)G8=kx zf30Wy{cV7KX2#z_>A3Cz=b3^#Eiz!s`<0t!95SEn4V!5ljdJ`llVI+wCMz}ni*B|) zw6)yHePn)M)-aH*l0!v*LDTULRbKa1sVQx_^-2p3+V(BBb$ZS=m#6{{yr0*5ysn*p z)U=U9eTQYMoQ{%M+!t!A`}h7RwLPK{AGO?1(P+N+MP|uI2MN7T)Fzn$Ec|o+RP;f1 zhWV$terEjq9nQp-FU`p?q~W=nVL09VMy0}^XJ4Vn)$I5Dc#um3cVI!? zbHA%pZM^UXnvC5H?=;el3f;#%OWf6kI84I%?+6}gxtt&SUF+ErGC1a-#nNc#q>R(*%ow=KD$-o$%c!lo+Exc?bvDuv__Q_Mx zL-=(*o`mh|YE|($Tb4?M(VIh(^IoImutg| z6A%6pJo-2x%8grtNSzw`SiMZyO!m;2?)2Up3CoIQOr_@&t=md6PZoE zVzCTANu41`dx`Yq_i@FkKJ=vdiK9x>;orxA2<~ZIJF9M<+HAjE`$8MFzih%2YJWjR zSvhL-^pp1%X)k+LY(^iuL{-#uqUY*v^aW2ED;u#FtXGJCS6Ki3Hy`|)iGjGE6Yjsh zp7{4vwg<@8X2bGwpL(0kG6o%w zom*@xN6UeRd24~T23b8xUA(7KM}x#aye&_lanWuFFX^DoyuhV=+$5h`np>6r`c5v< zC$J7w`9BO50&lrzu0YhM?hkKlJ4$`^Lfh$!c`Ru|n#0_MJ`^>bo;xSnCSoO7#FkUB zXO8Yo>Q#5=mf2^qrZQ_rRo(1;)QXb~C%+rzQ>&hP|A*qF4_fOhRR-08g~YmVtL$_c zklJc_3op0C4ySsn1iH+OdjsxPGC5q}Vq1&V_dgI2z8HTojqMjB!|6sPmY_tQU*PXv zQkck$^g4cy$tGgicb3j-^h0f8gR=Uk<0U$QutHbs@+vKQy|#87hh<6WZ|PwiYwt<0 zc7vbdE}2=SPgx`kU(TQUVI=wD?mY?lp+TnJ%>|crpP6&#@44vK%(pvc-|Z96#9eQd zpQxZ|_o6z-+T(V$?c*}8;}uWO`iV5Vtn`NIJlvC~c#@}C4sVZ22d~pAti(F*GT(o} z$WN0I^Gg2322-QtqDFjMmvW=F{ozxLMwpwQ94unm=`9Lu^m<>{3T~aW@Sp2@IT>m< zTP~A{f9AiBs}~qaYT!l^r&RnFm7L-xO4#KFK0ytlW^!KRn=)SS%WGuMtWHhZQuVau z_|=`yWlI{AhczyB{p^np=dSX-n6PHZ@uaoWp0toB$?i0h60uv>Ry#bSnSO3%2D{M3 zWnA|evlzi2RP{BUTj{b~@oG?{X42Hlnd60G7JqG~pu-_EvB+%I1jQ& z8+HmcbIh}f&TYcSMv-J9-}Z`2*>F-Of#D+`Q|B2`^qBAG)A`iD+Pr@6W)(hW$#D4c zZY1xP{#E+~rt@BOxoz=1jiXOo1c!-xVUwJGPQx(#Dw>#u*ocmh?(;L7SQC}vcZDis z_SC_JGh8kjJn(o4-xtF+r5iF+*0UqIImt?Mzi$>-mOVZ>RW1L=H$ry4VY}}e=ZWsL zg$eCH?KiT^CI+r;9gy*vx$*8E9o^RF0lXbmVz~)Ft8cW&ZTWP-)?U|MvXP&qZlwax zXc@Oc?5?}X8#tIUhG|8@PR_~rpIj%V5Xs4+sJ`uC4TOsp`fO7F; znISQ1S*GRMqHdw#8N4t(RHmE2X1^TRtF7Z&8q;ci(%rbG8gGYWGS$+0Yv%&TiF!CB@ zw=hpCK~{McS2{npA9vk&j%ND{#D+w*3x(Dx=Z8(-7^o}o70nNWK^SvesLV-SwSIAO zeLnijRb`IPz?w1v4bYhTKKypp`bB^BHS~pDXJrLXYg0UD|5EtUrYm~P=Sj5Fo96lx zEvIt(zDgcdJbNYk+F z(>Y#VpD{cc<1-oKBqH5Q$CX|}W{ zPw4Dd$4!CugI)G zB=X|%d~Xs)r)`(=Fg-eaHTkkP5A6rokXm;7-wx@YtvryS#F9CzGgWQjs#yPYjnxaf z1RHu*RmL~^s z({d9f7MQ0bjUA8N_w~b!U*O;O?0D>>za9E`rXxQt#9fL>n$LK9htXj8jnCEox_PJ6 zN^V2S+t)3L&A=aZ2ZC}zbdCD{UVmX? z`UsCtogPhdp6&iTXQL>+PWn7~dzP2SKX07)ZEe<(ADiMM7Za|sx;H-~u{Op>DJJ~v zYV_WCQ}?4xg_q#HiN>Z4m9hOH@mi!GBsF&m=-ZyiEb%yeY+v|G&j&)0blT_ozpdDK zme;e$U%;xh=6u`B*kmCeyO=PYU|&fGos?BiVrh#-s9tfh)Jmjm5K?{Y%b`8VI%3St zaYl9I$)S?7uv!BDbMKO0lZDb&#KP9+OQV3urc?DiYjIBA*r)yU8oPL z?!2~{@|3F=?}l;5!&7sGD#7&M?s~_nGe!;V(zT9aGf+K$yU1(e!yUbFdZS67^|7(( zh;BOZFD*l3e+&C;jQzR$i?XD&ub88b?yB%u+Rq|x(J;mMou08gLe+P}VfOuJ^P^)q z_xkLKh5dW=UPSDt&mwKaP5!YwBGs!R5s3nnVq?D@-~IsY#1rV~^I1t=B{UrhMF&w_$29iu;&7a5_!5 zq&3U5{)4Zsw8q`8UY}m4{B(&LRA|YoK$2x>NA&ZHlqqLoHdiU8Sgw5V`zn81aO~-Q zA?#^yyx5e4wJ7eLe;nJJnAi=}{kUKCrLn}yE=2X=V*}}u_Svn!#iLS}9Vs%W&UJ+m zcwZDWPY-waNV@lF@%|JxC5g|9*AE}bK9f_m50)fWa%k6M=NmoBTMQD{HB)l6i>=CV zRGkVuqy;Oe8AZ>c`q;U5NPp}(t(KkE+3f(tj5J(rmf z4{;yFJPO~4eO0;P6n^hI)yJ_$R);W?Vlr-KqbD9wMvp`hj|87Vj|iOtiEn9)Z&PAX z<^TKdOdz}ket=t1F>gbHP1Py<#o#j?ZKowIw-{`1j?w9Tnj3MmCdBs9r@RWg%D0?; zUdC3@FkcU}4QnxdjkdDX*tqP@%i==h6~6sNmc5>mt6=%S2+SV;R(g$c>NKp1kcrb0 zQdn8rA3pSV8Bzk$qhn`}jiyJZE;~Ne?}q*=+gO_}kZsKaq?iiqvN-ica)oh;V2i$b zr>+tq9t2{k78JVWmY=k?btz337-Kura-@HT1%@g4UOzqT2hFTkv0@6_1z|0ff$Zyo za}AnaUgu@bYkiBGwYR2Ky_GptQ{Va3VOBjOJ$*%IILNbaUu7h6yy#lOUxmjR$(f$_`&C~UtFUBVo0xR8vS-t~&~r{~A$;pS-?hj^1gRpB^o5$(r?=(J4+IVg^8In1pBNvSksZG=@0ZY$>p0g^oHsY#9Xj9Nt(&)? znP;-_d%QobIB(4Iq|;<~o$i9e!v4?&b_$Axg=G{f$CgnuQmmj@ML|KqL7^mQ$iJ1E zf}&$Rbbp2`b|!+h=GU)UUNJDRvJ}Ms6WS|aXKE6BuE94>l+iKao3mW@9WRdK^gH)| zGI;X*&QaBxvbP6Uka*og-PkFb7MV;AlU)tx* z?ozuWr~Rod?}lo(1=pAuiQE<_ES%XFdQjwxYukEmp@j#LukIi68tV3Dp7eij?VKs& z>s?Oev|;u}inmtXqbhNpT@l=7ly9|*UhB>`K5q~=elph2uGl_pBQJC5)cXM1xpPW` z?^+f3gZ|vomp{N&rONka#KK^H?>f<$jD^e)_tr9}WEw}2`pK+%{qB>7ty@mq`tog| zPD{{F=$uY4LCr+Bg*V`5uaXYWT5+{4t9*7QmGza> ze%JG@D|2gJ{Y0ijwk&B_*p~8Rc**mP%Y>$l@4v`wd*ma2n3?(g>dXnf0ltBCJ=xI; zCf4qBvVLLOG;Z0VA};cNVUFA-4%9g|ZnK9~qKhN1o-Fj&g>zvvJb*|4UXSnX_ z#K=Y8y6N846tgV0vW+V49wMw4&yM`+kt~DPY3#>(d9bX{++D~Wg&)!(m^`dJ} zQ$*o%HKsp5u76sw25w2W3(tHT^unT^_BEHxnO7Ps$Gyr!*Rz~Ekv;D6`;)bb^Or(x zo3WS261mu;mAQ7YpISEUS+MR^Ge7^Z#rK?;*o24`W1-hR#cOU32v69b;oB#eJL6q< zBr(9b=9h%Zvgz{gAq}0j&--lIqABMLx15w}=^aQoud~uPY`*--^M+3Q=Y96*r`kUi zR6TcQ^2#O$2lYB9v)I1YIiy)?_Orfd>2y>YmpKyi**Re#D}KhOVklWQ@<(XomN>uj z3p37+G-}=JV&>~y`-Ysq%ht?GD&&36tCO-C=;-Agofmrj@f~l%X0F$2J5JtU5U@4q zjIi}B?@-qYZuj0qv%i#|@!i=|gGpQHbS$5G`P6uQ|E03FA!52|dG3jA!y-NBeqQB1 zdSmX;ui2+V+_ejo|4FEnY3^QaxQv2Ak?y|>6%i~{)Ea!B?O9I}Dw-}@kMtk2HaLP} z&ykY6K!25Tdqc)+5GlpC{i(TmGf&YMT56Mq7i(8n^{>&W()-EkxdrDozE>HJ$zTZI(je+*D}J~!e5b(A zBS$rSsT-5yzZ|=LDm?i2=ZP)c?<^0}zP+^Zt-uzM6Gyz&MVh>GMp-^e$25)wx?|rwun5)IGXR zzxR_758s8dd{lE^U*{`V1Eqo*_Ms4Ecgi?UHHs9dxY1K?0)9 z5A}`bHCErcA$Y*Jbix{ke<#d2h8^8GmgW zdCU5A!X%uwhvmazCu`FZ`$m;%9`7rON4GQY z%0Cv0zq{>N-kYUUAvLS)r@N;C(u%WK?~ zjiqYso0)90yWP6Fm5diYF{sJk$hVuY;ujkWQCX4lLF?ebqDz~H{N*N?XuS88R`d-H z)HUyMlA`uM!|~pZqgSkcK>U8b6lPWd{+%%If zqouxKdWE9B$xY2xeonJuTA(CvxuX4X{`hW(QWiWoFW1Z3=Js zu9m5q8waFZz9+JEN=;>8_3!uUS;wq@sY_bjOP%DsqG#oauRy#e%Qr^P|%ix%ZELp&R}M8vj42{FT>MoPPqlGjz>=-<|vL z?hMp6?-O5tdr1Aq!uqM_Hy?;>Q&3gv?JYbSS2L9^`oX1Uhp)+*^K1joEf!m-J|_CB znQDKQOkgkfz9)HOcGva(5NHDzw5{CczTzkE_$wJlD*T4L zp$-%5M(;b*+t$vey|c%5Z2jkgZAvRoy0Wgzj%vNR z-a$v=?(_Egl4r$EQnU+-)uo;a9yM?Hlxu11e-{ZpzZ2XWX%-gx=vQHBOF&=oPCfHJ zAN6y^s;7%91p1t2pJ^WBD+%t*>p5!n0+hYFzK?B&l=6x=jI*_dJdMe`#E_VXi7bo zDeJvF5yqH809$3*LbiI&@Y-n~L8u7&;O z^!o(%hzeZvyD247xkt1z*WBUHA;#&11z3Ixv+aZO9EALBq@|0OhZ>U*$ z^h9LSz3#z};r%1mg)I)P<8zFYIU_{lre~GurM&YrzuO@RCTre{5>u5)x4z0<%xDhd zDWX^->G)DnOzuQfTv$a>j=ZWjt~=C}5X0O=u`lF} zo7)+DttiCXxN?n3buUkJ=9P)rRUt7Omsx$ItO;igdsVGkQOP2wdYomfBeAdQD*3i= zW6DNs`e8O(C5$36KiGfhm-xl9^~K)w^*SYSBg56Pnu)IhY2pMQO;_r+u9>16UBmD3 z_@TAqO80%~xjQmb&-b|*k z|7kmK8W8TjyPSeze&c`N&Z1~Lzt+%1+u2FiXyL%4KM%xr?B4dXhf%>HQrjryN15ej zs)Hw19j$t%)}1%>{p**#UA4?9k?EnbetAJj#h0fC_>cJnrtf-qQ+99tdr==d_RfC& zypSO0g_O)qL5DOvW~`rd&DdSeEq*y=I^Qo?U6*agV{4(c>3yQ0Vb`13wG3rE5!%5X zo!ewTI!u;x2_`4H`4!gktW(_bMlp&nWlO_EJm2w&SNcyF1Fv;FJ3(JqCT0J%&2i@u zPw_RpiFu7X?<8L=3qRJAoM>k+(|GWP4TWd%juWxA^2VDrM5dCOx)mp%JjywlQlBIR!NqgxjbZhhf*WB%g{*$ev5Y*Uqn9^b8yrEM4D zYgc?e|Lk=fTO^f!zC^Qoxlzr&%y!p0(S@KqnUAG5>XaMLEABX6J5-kLy-nm|wrjy* z@8688J#4ohv-6bK_b_jp;yHXh`@^-K?+3al%Jj6<;@r z4Zq}@nEmi*l4q+7i35PpoaR+&m*J}L^_8D(O&2_aTq^S!?P_} zugbmQ>9XfO$AaU!Df=UztdwFs@cm`LIpISGuLuy!?}=jp5&VPv6?F!mVJI=%XehaBbdQ}NOA5WC+0re?DLUE5jlH!8{kI}X**UJPJd zcAi5;4t_LVU*mbn_iEw)W9=P-G-;YP(6M*y*|BZgwrzW7X2-T|+qP}n-m&eOGy6Q> z!H@U-BF>2uQQe)Dl~)#`@5<`RzO%!xpn)w%;3(ehf+Vk+Dt5KRsI?Zv#B3js!6qiU zJn(*OJu#7O^M{|8fjtne<5QM^{h?3Th2tPuKl=@2jA7XDn=2`uCg8>#(m1w|s92Oj z5K@6KN+}2#q%CevE}WndzcEZCGlu`6OGNF*yuE&RPMA?c#65c2b{^QnBi$V0y{6KW zu8u_3G@kUuA;C1wb12qaMYdoAmC+-$PT0CvCsLqic=<4<6G>=QDJ}*z9&d*;B#lx| z>p*6m+&T0@1DWEmu!i*3G-VsW85Q0^BbcKBWLJlm@zJTO7q=g@8k%Yib4fK^r7XVB zj5(#*n-hh_{cK|G^K&l!T>wu*3^yw85t7tWo`hq&i{KGOK8U5p>kXs8@N3S6vjT1; zXlHyfTi@oglqaL?@%-ZKR6!+qqv`71tJ$dv8rob1xz9^xI@|AN>dgt!f{t0Al*nkL za?C<0Y-}B;nEYbZmQgFHjOp_HQYCFAPO1T))7y&DBG0<#17jY*Vio}D9 ziVh&ofc596niZ0_Ik8=nWZe?KaA?ZiF8@c=Pdl7bToGW%|4Rp z@j=JU z9}Cm=;PG3t@)a1nz@CS{Vp2SMC%mtXDK4*+Yy@v8H~t);0F6OIa$Sl`me?avf1fev z=mJlV}j#?lRrVZ%L#&y-|F^Rwj5E1uA^6+Ty?x zGxc9TX!_qzS>+;tuoTD_v5-7!jUqM;(RHm0TrcBd*?`MO#5BH2nUv8(V}2nZ44Bxq+%SB7az_YL(tHbI z0iZoo?JOzp*&P1r&=|_HkP&fMfw~H)G9e6ziQFJQb%7xpxj<)P;365u94ZX{?Z~{D zXdvbhO7f35AY;aivvhw2a6n@eq3bVx7)huEV&feh-2M`)AI7U3Fx5`;jP>R7R=&hp z((Ih(fbk&BW1(n7} zyw*w~==}9=?;q(?BZngS+ahak!p#P*Dzi}VEtvrN!X4&aS11%BGaacVQBDqo7$?qt zW3j@@_De&!P8!tKvv?NoOTap-nZf?)j|)6n5O!QvbCn0sF#DYz@+DEUn?G6O7r4p02wB4}3hSm<}gyL0zu^`)aUPFAbdbBC!=1-dDr^==O1EyNKY{+!@@swfY+K}eFLj+9 z0N{HC_MbLT|J^^;(2hR7@1x8n+VVj_xWL?-0mgdD(&$1<48wq``TK4(0 z1~Bio5k&^NhIqG;f2}+WBxrrAs&Q%;2k~;p>^ZGsLRg zrtX7dJ?YKEy!)u}WA}9!w@PRH)bbq^RPz zIxuhfu&Zaut<`2$!}?U z_JxJowPj;%8%&HNTvu%6o6$!%T$&H53!l*v`>%Ht-sIOnu%!b}^1u9flF{Q_w^OZV zN&9!pXtKi}=01-e9}f+Y!KZ|O7HPA(m=BdtW{M> zv`u;xeY)kjK7V;o*5va>eX*48(v)_6POwc|_h=WkGt=B2`}Jg;Xnm(!3$|Nw#^>}T z%4-_^QheU&VMDh(7lj`p{2`a5dowc4w*-je)HSK9rlSIeOY6EUfcT6T(XDCmjO{Y% zZgBq=YP1Hm>tM`nI{AcrT&{K>tHg`*2-S)@4)a7EYkuwr%x_s-(th1tx zOfhUlC-EG_HKJ=*sXZE#o?M$Pc?>aABN8%y79fbuc4$ z9uJ)9rvarBw7+tf?iDAK;8n}Hautk_CH_NL1IBl=JuXz$NIuFmx9WfFBH?OkPK zs?a8oEm{xw{p`z~0Rd`AIAbWqWI9N4FfL=FT&Cv0P(92_595sv%-+5N+SmxJ*nNSP z^MYE>g!wj{$PwtEkQfPO{8=z<^L`!}31toHnokscPMI~bjKTD0;IM77;Fsq<_^3mP zj!G_8v||!6)#5tLwRB_B)`CFGg;oCQChqP zXpk>(0t|nL{@HS`Kvlqe+|SJ-nq!lWGvH=DWDQXk1Fw)n;)~@0jabC~0WFI!-7hl7 z)*eY5sg}r;45BQx1EvMTRPhg+jz5y*FI!O;h>T+nkP;4aDW*uD&^)DEBwnOKBF&ru z5Sf@;3beB2(o9V-Ehw_!Cd}k8bd_j;{GnEig4S?G zmaPd-FNy6&J}ASXRsux+L@I?Mxs3_SAmELRh~j{j>)a379h#JT1#%j(SVJgzBRSi)%w_g()HGB97ssMcp|$Ba&e3L9*a`}46kr?ao36OQS6GGh^E8e!?F zKR)RVCK^5wDBFrY0St%sN@JF|hA>RSydf&R2dqTI;YCa`Qh3Q@_YUdP_izQyaOu+} z5Ch~*q)tkaS-*$tUzXrMti5j*!(Gv{D74Bup-H@`UyUzD2bBJFXF*HqD)Rod;}HJO zD(P>q7NCL_#NOy_eHnR@uPklix{M3JRJMwE68=vbKqow;n=dK zkbTO3>;gvp4x*PW=KD!{;Y&E6&MstF zE2>Vf4MX^$HBZ2IUZd$p{>mz#=O-4;Of(mQ>deY2Of}QsQQnmJ zHPW!4m(u;7>C%9l8&Tc%a2nmzcdxwvaVNJkr@K=U8~^~D007|olN5i~9*$Hj`8oNGwhVzI(^p&fhUJ!YxZ5f3vEfG1H6iog3+7L3Gd$hSANj)RJ?&Q^*=fkGim zhwDJyFA2`F@B!V&ePT9~uOW}<9>-{jONNJ44hif2_Hn`8hB=yC&9&WfOQ3U<3Mk;J z1V1<{1c+t&!<{Dbu;W$iX-&+hu-g!fAuG;}j)<|L;r`W`?xH+Mgb#77*cx`mU!m00 zR)Z(#5^>;^6^p#}&?;8rr-?v)55fc31*xe3xk#m3n2IJ4S$?K{=&~g(LNI zI^?V(T+n##?33;4Wl0n?T|M6B5{DZ3vn5Nv)TtDK>yi`6-zCgj>$;A2evIsuD?UpY zcCKpuz6LY88CQIMj9mLQIEW=TVdlmZxCCq6>~Lu)mR&DR>jAn$S@@HOpPwlrUy^qA zs5A}55|Zan-VcBuMryOjrTQYTYyo68dj*tauyR3)G`sxfwF@-Vyw=Ri0 zK$)J%W2K@Rh(vWc>#?3v_lK?qygX@yLcN5U8|iLAN49@M$9-F}*;}x;wv6GI4vfic z@?<25N^yrNh7u(rhB|S64}phU6_mhkx0#o-8-0V~E-3LWT_(a_a{@9KXb?xb9-kq_ zYgwzEd<0(DnJ9h$WB(l+1E1m=a0P#ua>If{mhr6i+paGRY`c%*5z>_oSs!6J4vGsK zVMxAQwBUaB9BQU{=iVK?EOq%}-72L;EcZAz`Uv%~BV=PobP}C3Rn;VINcbGv6$C$Q z7DtumnZ=n=Xxksxj$?ikj?8|;(+j^vmQb`n+~=4Tc=zVOx^L6tXB`ho7eze{VsTBC z;EyL^QA2q4+)iPLe$p0Eh&JzGLVkbKs7X?R?a16RD@0wr%|V-r)3*e%<48wF#>^s3 zB@TRdJ^~)Wtc%^$KE?razd@=g&K)OGM}6D7q&aO=928$pWH+7=v}*a^#MfjX&X%al zo#>qHNnOdGF4$1R-e{xrBjf$9cZg;q8%%O5v{vb`CR0H1J|}u%O&$lRVn3f`#qPT- zM!Jw8unI)N!Gws>**B+!onnKdG#rK#v8(b2_7?X!5GbOB9b2> zo`{$*WE3GbbxH3f3yh6PwO4t#A77I-XqdA@2%8{sYM6;Lv6~%Cvguei zFs59Ts&6ezj5I4Uv{S+=uaM@d`&46gVQV7speKBu0;8nuuTdX|bzm~9c3-<(5+!Ut zE~H%)W(czF+Yr^bGRIAfj2Ee8C=6NZ2lLNT%i7QHvtXWl#8zn!i4PlBHlbp@-D-C+ zXDZ5c5kI;}bu==kXIBrCIpwcxQ~MzoQtvhs3`ng-g5jcldWAhfz;*zUSflT4!;o&5 z=~90PH_kAzQMp-+{QH!Tq+qRwp($5i=K#M)fl-F#mR6;=BDv6~7*ks+tPlkvs9PGU zCjU%h?kZjmB~#nQ;P3=2CRu?;PUz=AC(?p3aBXz&2Zs`WHcld)I4cVOc290hQJisTm?%A%X|`d~ARBEnhp=d>)ou}9q%obdiUuLh@nPa78EZEM$pNi+q5=BXw9@Pw zWJFW4+Zr%_hB#D&W6=UIjnYIelrjB}bs$(HsS6)7Uw>hjAN-)C`G?JT!>`Sg?Bo3f z%u-~FJdrUuHMpf}@ZWyZQK4=2iLsY0WA(a>*b6$6y|Ia~P2%AIC&wRJOYZJI1`tk) z(zgtHcBcE&ozsjZSSKV$*=sK=Mp@0=Dd%NLpMITUg>v`Mn*5XPPpMfJTCiJnwbQMO zYhlcVHwF)Vn$}?8$aXZPcq9T80_aR>OK2S%yKi!u2pMVXk5K$dy7iIZbD(oc!!%4X zkGVfcCdYp3xH`L^SR-dt9%f#;XphYC&Yw(~pW8be(j5KSTW_C!iOAGksdcKIe@MZM zd$bBWeKfnrH~eY%$&>#~irnE25w+#he+sBLha<@Aw@>ywRx`XA^S;y?57_`e`am2Yo zHds{Jl=U~oDEmOvy*l?h|1&qxOOa|&RI}Pt+OQ!Wg8!UFAV)eS@DBlg-)?{o z$(Y5?*F=v>k4Q<#6FrVmNDcd-k}&HJv`ye1lax8lMA$F#EWPExAr@neG1;A>oh1s2 z$LO8xO~deISmaOm%0ZkS4jMZi9M$shOrPYgCf}XAir>1HW}QWviQ;WP?E#QPmxDOp zQK5+_Do|eti78d~P`x;O8|Gn^eF?;i>QK;&*e{*zV{kT{6Jc4rjjxWjFF+kDJrT@2 zgU`114&TT>l_*SW`-}t1Gu*|WygkoI#d#$Vc4AD!$wdvdDT*?VWl3=g7_(1c@+fV> z@1NL5hmlX$OW*S$7@$0}=w_bCh#Dlw)USR>`9nx*3!G)mnwMINCt6$M#G*xHW1 zNt!*0r%m<0OolJZ)#u)YE56R3imStKNRL^BgS*t|5(yUPCRVP8$S zv02pp6FUw@F#9x}z1TQ!lL4D?=Kwm%_`JyCNA&8=T2H65Q4ocoUO#fJb&gfbtBKyl znoW&rZpFUz{>ATp_hWLh2n$+$@^J_y5Vho(W!?JbH*fN>Kfh%6jdu?B9~@5KhuLOo zLMQ6=YanEd?_GJ3)AcEWYZF$lQ@EBlQWk#d`KI;XWdv8z#N_nE70t@Fxw};8kU`Z} zedpBrmztaN)&Fr;I@Z|2xy}XvND2o7K>nXu$xQ#3v5}(VFLN8ye0%42%IcvNsytq=)9tCIp3Z$EKi;#QAG1Gd4B0=4QrbQrra8N#qMx?T)#R<- z6xX3Wj*c=5kuKhk+P^-!y~6TV1k`z7U5`kjj(B;zaincBQn9(A52N75l;Nk&(Y=F~ zr}JHpSLTn0?DtZiJnsA9s=rT4DPRWT*F?dAW;CNAEUyyLd)<-xi(s$-b`ppGhM2`rp*Eu33k_=#Fqc zN4dBk&M=vyktuPr8rhPV(2z?`JP%!8aW6pWa#P*%H8Mn7LR|7-!K((0-%mOcD_ zS9txY;PR#8@|ETNC15r^n0ehblLej2jV9nu^Zckcv+}slzK#=7c+Ino15^9AkTCcA zPg!4LJqXWSsLwFHd+X%a7`G%H)y+reZ1-Eiq^|ay(0>wq?}Nxe7KxYh42vW77gdeyYl#B! z4ng4uFc^&|agD760w{5u!{i4(2SEX}&TkGP?}y7T44)GKD?tcB*5yxIfS?2tr5e`L z2nF(wzCBTR;%C@zJh7u3W-r=*gBAX-u;l*&tN!0>Q~htS|Gl>5{{pl9-)m$2Z?ONp zw&wo`EAls7e^?>(iO9(WjEL6$nn~X_D{d8fwnJW9ewhame%{kDFV+sTbF09fEuOw& z%OU(?if{ySfA{y-RpFRFN<%N0X7(ySiZCmhcKsv03U+xv6}9c@q8k zEbYxQkDIx+R^MPzH7+{A4yQA0Sk><`;dgDtX)usk!(IeR?@rIq^?^LEpFpDw$ zC3##N9OhG<8r;`Rj^IMZL8C7@QyL-!pHrYROAibeIGsT}gWw~ylWVp;l^mlXtZ7;b z0w=t#(FAg#L;QUcG=??#b0rK=u9ejin~9PjJgdwWh0uOG!C9!RAlJOaK)RG0Om`&3 zD)WrnmHdM9h?zD0RHhL5ed08PCFOA>_E4yiRuLO86Cgaw&G?7@RuN9z1VZge1hh?| zQGHGP-HteZieCP}t9-*M`TGpuyd$8gP#*_^os45Pv?#mH$o93T-J8tp?AQ6DHBXOQ z5Au%gKij+r*Rq!ZPoVEefVirKTr;b=YI{0l_W1uy7(mE01TP$RNaP4aC4`WtVtyQR zxrpQ8jP7L^f@FrE7i|>u$}=iu?YmmKAf?JdUJglICTJ`Zo$3a&b}qx}Og&?JDa=uF zAl4^P-@nly=&+tdAHX4UO?C)0j$JA}7=hzllOFe%qE zxq*C7Vl{$q^IeK{y-92x#^)I;*cvspJ7lKW^>dCer_8xp*|}Sn)8i4C3L<*=v?qr| z{XBbP^@{C?R?tGGiGOzL3_^L~+L2g+9JemfIw4Hkk$G0plX*_J!Dj1|A8xgZ$hT_zLKp0q^QD?wsFq%N$ zAOmWE)CJm(0U=J(TQa(Q_eXoJNK*ol=_mIaf@uU^UW{<7uta)LQzbdR+wH8uL(0mo znU-BGMthxq%Hnpa@Py7Y$ONH>QE6OdazBuytK~lPuz8zH*WGqc(a9WnWu^TrFPy|o zH;QchK6=ytpt%CB6LnLOd_RhH(~xwNlXOqUBY{OtaN($%;E?Kpo7DIt>gl4@Kj|=N zV0Ooc$!JS$&bh=ZI0(pNB3@gD_<3b`80roh@VoE1WEu93D7k@_*WhjB8>-h@_f{fZ zM*6otZ1kBLcRHWLKQ8Z`&9nr%jE+P=DqB50H_5%TjM0K}TTiVMH}o zJXi=S>5a#4@N$`19=*#2tKVrG3vyH4Te1adEr8!4d-*WA^|E1Kq@s{j>3P99$^-Do zO}sp@OweuB*-V(5>qsBxAsOgYh697|FbcIcQ5c63&fY)6l)STN7!CI-~B=w$1IWKkp=Yw@)X;r^RVn! z4jkGio4paJYFWq!_I8+O=qQcaz@4y_w2jrab4Q2;Cl42{b;* zps!PANk{?vFh4}%UOuSWuCZ+o1(pu4rM7+&tj(S(>PRn932%P+`WMoN z+xP{FBJ%A-HP*N1J6=yAy|V_GqNKpFR=%rs&bT`?@hK|D|Ju)_l+@AV6>*>n@Y?cC zSN#*Potf#Jw2N!4okmk&_CZK>DXyy7lGFs7NtZ%HpLQ9L>6K;M67qqVfy1tv)ie-{ zmgFy=DnRA$2y;pD=Kh#jE`9p_acU}1kjBnMxZ)HRz54cI5g65Rvxt1=Aj@VqWn0!e ziYW0F8WT=Z*^7)SE_bi9J?N0y zjl=`D(A*)K+DIA_!$PuZ!lI!B+mEmsg;w?hezBNaX2zSc6X`MpTY9u)%YMu6~EL zt!t~Z$)%;jkCZql9)kwqTHWzWI~~#1(s>92OI#x+?h(DUnnfBV(rp%_V5a+bw)T27 zt|~^0HYGlfWrL7*zMmNCnI#Ol<0r@4s8idZp+ptjg=_`3t_gLF$LfxU2CnDY0Mz4`;L?_L_ z<%}Og^#q*Y7gF6Qs_UU%l#0gVua#1X)~BppT~giVah+A$&v~g{lw@I=;^vJ$?v>;I z;2$ages9%#S9tTbAj!w9yPTV{q{9J~eIh=v5H(+S=AxBLwrj6;4i54^q}1>iE!E36 z7hs#x9ThpjY=Mff(^vuLqgK*=%)xJ^dj{6ah4vc>8dh&>P;x85Ng%Ab>G;jgd?5ui z;iTZ#-1PirmVl80ns8F^8o;eB{xXWb#c1A7J<`96EK~6s9(q9jpU4xm!qCK@ne?4c zMW=__A5vc8$$2O2QQnb~0h_LTq-Va>*e3;#j>#*Y#w(}AeW-9!W%`B(@%rW2P@3`T zTH+LjWK{8bJbd8hFInH;bx&exx0A$Ya#*@={cV$!qMWt0`-|k`WkEnJXO*C9bU9ON zehm^qbZAgZTQh5I^z@p>fK^<)5rQnSac7Tw6QcZ0(-3LlhqRDt=Zh+%`z*?Nt{-!kSHD68) z2K?Oh)cYk$h`Yq>eSxX44a@C1Ld=(eM>H_})vM!O=Ps(W!8&@&rJ*+N&PmG+4z~{|a|C{H=C^_Uzkjlah$QI02Yo zM66I4#nBCCaKxcKs{1 z+l_f^I8U8hWoz%#pWf5=Z{(SHml7z7aScA<0|2I`CCO5Z0ef-}Lnk)-PyuEjV>)14 zD9OYrv09Df^G^t5XvpA$3yp@R`E1gnWtW)e@l6d{Kf zRE44^Te7Srh%e;7NP7^X*Nel}1NM0sZP!=~ zDoVzbQoNJ&4bdi}$jt1u*--EM?#b^Ov2?bi%#<=M3h)T{rs)^@33wIfh(rm}PyIG0 zrJ%HoP8F-M)2M0{Q599yM9yEgFG}rSYUv@MZ*&I|L7WGEd2!~c6k`MUqb zQ;>}RUgeb%AUV@h4;E1IDydTeLP;m3nP>PJ0U6XNl@N27Dg7~l9QBwHbMnT`wO}1M zyQF-=Xo|zb7;excKh|{SW)E20CQ=f7yceiu-|_pA#md3od`@A13tFQc;QL zrDw8H#%1REzbcH%sP9EK-2Oz+o}pB;vzvfXFq4W-GU%9f^zxJ*{!weX0rM|Pi#Jqp zpB$~V+W!Hj#7sI|7s%^5t%1=s+{pIYR<4W^=f7C{&y4TK=Qu7u!*i8m4Wunw?z6Do@u+H(mGsal9bQu-w z>`4b5xsPd_!*v;~E3Qi$fAhU`4Tn>;R7XD=m;cR2HU66qs%CcnpBDU6UaxtONobmG z*nkuG9W013Fnpb|Rvlx+k9(np3+Jt@ z)g)!)bTk@{du32a#UMl`i5+4uKxDvC9qKM;B$M>hiZ1m4+<5Zm9Yf@55|ytJrNq2D z4?4V}8k9Tr$mq}@lDevfDuh2nZ+ZyUceEt<-=HcoZOR0NJ2v1@+S2ItB%o;Asvu3JhF}LSc{xcFctJtWE?Ca%kUw(sEGGtAOtr7F@${2FcJm}q zOu!Ne?1BUGX|JYSIkEQ*JA~2s!)4lvp)G z@s~MDu3IdBW8_wCLRE*vlNJ0=kIo(!ke{l^MoJ$GYalf7WF@Xp@!lg%WkLvGZWoYD zYD6wE@u`>Dnke$kn8uYl)VXYYnC_fIL=}DsWN25~Dw_>q5^xmdM<{98XhZmBTHPZ= zKH#)lpv)%#Eg492`736IsrzH!_l4)1E>$BxF{@m$IYZE&&YSZQ2*dr*j3?DFErT=o zL0#7u7|qtC#FQ(2fvyP&GM^a$y8(`%p^8A>g5MbM2t69UGB(|>=l9_O&+@$Th~UxG zCZ<-LCCG^r!aI1NygdR;iIB|t66fDK2Mz&}Aq1vkGY;459}m!lJkFx8d0R+U2p^h_ z)PO*bzZxku1LI=Zd)E_cfQCze?2D)VQJ3$nL z>u3Ewi-NnE^IU`HF$`&FVg@XIiOUnBOk;ET-bv~Z<5~0h!B2=mmM$1F9pWK}3uL1C z*cTR4dZm+uP;;B#L2)?nRT_^{xY@=vBLts8Q;xn- z{dMG{oGNJ*;J`ZPW^ccCcHw`k6)bHb*sKzu`14RH+(~X&seeq@i7i^4YeH$XF>IJY z+8PHL^l1t!Q=b7UH~AWWw2tj1I{mVMtY!kPFKICTNEvIYu25A`@2IPipx#wJ)K#}F zsJoy%(^N*SuIQJSbV+!QA>2W5a80Zn|+@b&0+tm#1>GtFDXpyWrvx(qU6p(U4RaiU4H&r*_i*(Mu(favIURqij@dsjgHq1Enb?5T)(dbD=I z_#EBP=vDQt8i(Xx)g63m8sCz->b$W@_vUvGccoA%RdsutYrDv;?DmNsf{&=>Mt&5| zC5;j%$)DszaTPwvhmqsg&*%0i*K_Yo7&z=0W2Do0%T0)LTF?mp|2Jz0?PJx4rI%o3(EC>MSCsaldb$1AkB6D!9*5}~yqb7GcWpnBZM45% zUh3uPe2T}t5+rI5yGi$3-YZT|^EOhB2?a|v%dLbC36NNj;*lI7#-t*EW6zJb6)z+t zv4kI!3tV}jpI6}!#S&H1A@c;pi(ywRO_m8d;g$6^`kE;|lScpUKC~zWa!U>f} zFkV-=2>5|$^Mn^!6QoIg79#MeNXBBJV^VPkBh~5zzw%I8rnk7yRLLlnq8H@QcwG|S zRLAVQD=oF;aEwqmCL+IbD@&b{uV>Pe2zr3Rcdri)X`&bP=ec(e6QdeI%HHo?{97 zolp}AgU7_tVRM=h=7`at$Qa=&iDKI}!D26u_GH(>?!nMH@27 zGE{M)fi5|=tDu$l8Ya+#K6FaKWpB^+^?`y4;drpw_-Mmlbw=m$kf^_qGfj=@`it?Ew<~IYUj*AIX=8 zWZRG`6yjY^ztb`zZ`{hiz@zG&Sns@qd{#p5?xHjRg8x3ypKXyVlOA_a7A9&Mq*_)m zIPg^x zAr&D5u^LI_qS-)8kq_ARA^&hmH29tb4jjeKMAI~nmfm(o-t8n>w{nL*1u1Dr-V&!) zpV^MUKWgP$^?!*nQ-|tv>-rUK9c13gN>(HWsY%Q3oxl=!GSu4B(-CJ+E5j0_uu%1_ znyubzW1TolEHvDB9jx8f!iT>$xHbQxesPHwZmigUb=a%Fb+Aj^H{1=b7J6eRSbP5(ZX}|ef^xECs&qm zVksd(W)zmt6r7I|RK2;n1!P;EcT$E6Z^dz`(l&}zB_?#nY%Q=GyE}^Oqc(d1iU0Y8 zjIPhhoS3>FmX^mC@tA-CZqsnl>d@@9S~&tvu5QVPK>B9UzsoHUFyOc@ZO^Yi9T(Ig zW?)O=9Xr4?P&{IDUJs8;f$ZO=CMvd6%gL*5V4e2aF)Z6=7EBhESYok!AllOPM81|C z9D=73f({F@Tw@trPuj^WE?gZ@%QpwR?r_E0mt3*kJAbT*g<#qzD-d0TPldRfQ{`5} zk@HN7SCG-_xTguu&*mjpu~JM{fdscJ-^D4*6gxxEB(wP)g}z5p4R{`|LYxLTWq7vC zbbf^*a>t!_Ux+)jTrAd(6fgpRBUBRKjWXaudjGg85w%Pl2xz%Nn3C#&c-F(|EichV znDd>}kD)TP?}9|3_EXH$WR(JSHoxL7y&V0fpu3^)=bBZYh}k~T*6p+GS?gW`?n?c;^h*4Ikm0-aRFpwL_}PzsWI;v-ltB?j5;_$w_z`d+exJur5J0MuHu z8d4uN0nsb!!x|NVh~z(6)PQ!Lb}EJ?$mnj;0k=ua9w5gLaAdl9cry+M25ZGR7@tPI zaY&YOW;R0ib)?>0$ES&qXh5Gt5+PXuuo$$yh2@gRN+;U{Joi~=y7E>zjr zZ{87PWJpv;$8dG`miAJ&8+rs|)hlkKuswoC_bBPvJVFS=gWYvgDuTFvwhbzIAM%M~ z$uDF6bX|~Dz`VPwL29Kp)usWwVR|{mBx$@`l5$Ztg@A% zP$(1?-4&OTpPE1Jm)7zBU=q$SyV-9y+7wy+acR{UpvZgU*yu6-L^l6b9w+yrK8n_BxaCY0?pL!Q{NaB)Izu(jTWE)X z7VzhOYEyAiv(4P%3g}v)MK>E46D!3%7nvqmhrqa6NmpCzTHuG-ddrRz%7(Kp@CpE- z)FI+`%r(!nZ6%M+p5j4Uj3R3(%_-DQJ&y`tZW;lXNsATDU`F51RBM z0rJyvYY{nFH9*m5iqaVS{q|S-;*-cSkLWA@-1YYW9u!eT-|=_^2oDVj%FM!oLwH;p z3PxgJ38XcO)ppjFrnaUOEswB1EQ7rD3F{o{45e-00TIf%(47p?u=9*ZUG#X~ZGx*j zA^mNnO6fei>&PH>tPPfBW=_k;%iJKwOQ<=Z+B!5|Lf$nZm9iEoZ4M6hlaLiZcbzYH z{oJ1=o^GGd4WUnDD&cDQpK4W};SDSyx6F{jHDqGwc{V@=LYkTyu6#H?1%mrd4+?%jzQNzgjhNrJNANp!Cgt$$e(T#Tw-?f=3(V zF$CF~_Usx;i%qhj>?Iyc;qwKunY5MbWdqrW-;_e+b7g587`Zn*Z`Zp#M*y z(}KXgS0!djCF2Mv&$4)=FiY9R1i3_diu+O-0kSG?9}D%#!SmtdVdKg6ZqfN=mg&Lsb$fFSQT@l%zuVir+q(igVfQ4& z)2*lbEmm;FG#lso3dho+#RB;0-pAcJqD9eiVqOl*HP6 z+lm-$Ps76VV=PJ&(QP$$&etJG%+3ihOdN;2qAe5me#rG%R*|)9Ike_{+lY=__X(FX z#Neod?Q(ogjcN-$v+;ATp)sR&zlh}?y2nBxPN+A5Pj=}y1;qRsT4H*rH$TdDrVQ-V zBED^8$a$s!awUVtr=5$sU>G&$OJXa{oJkmf^0P6b0Ib_}#SL&Oewc#<$fvDEf`JCz z4IzeA@&|*oMxDS(2E8~h837l)gA^ls?;3WQhK3U)sW4mg0wv#^SeqHY;Jrr8ny@cW z!@BcdKjrUZ$UUfQ;?3>UVl=TzPhxgyCF;K&w1$DcBUGWDJ(2!=rj2+w9R#W`2;)m# zhfr#*RMgwyP}o)ALgqC*C87Bz8EI^3Tf26r$Fpf{g|Et{HY3f&m+x{&!z?kD}hkgI@gOXTvbHf=UVo*-I@};?nNKyNDZ)5)}A| z4^a?`*ER_H64G@C_K1(rYdg%dUfyOyHq*NzF*c3Hw*rY@-=MP0HtwJCm@ z92MHF9KC}%5S`PB_Mv`X=tcWT90sl!PMmDgLyyjR6g#J#!#B;NRw_xd7~Cfj+E;}{ zA2ttkOsVW%MCTZL2|NHPEp7H?9y|wrJnJcLbAPoew7N2?W8iNoG3fjwjT6*DhOas)1fro%7C^mGgma%Ij&NIF#N&ba@l$3tPfV z+Q<&P_H1Q+y&OFjzxoJayM2x=HH36|iTHK73cf0mQF%%ES(=KRVk&aQ?a+vK59D@8 zyn!DOf6dr_j)bs(B^4|C?Be13gNA09zwN8WQaM$`-cm#T8nH1g6-`Cs{3lP}j)ijE z2Cf(`2!x+?>AiJlOb#Esl_c)PIt7#Mnd1($<>g^HO~o%K?s>Li5t(FUjdiE7y}q<| zeS7`H%-R+&yzQdXHj$8Rney|9!H0ez)(hK6pWaNBRgCa6a15KZZOq+Z&dNGQ)MYsJ zjfQS!KMZFLV^b;`CY}q&Hp+_D^b?u#xTHAR!UtRkKf#!W1dneshsOpYE?50+)Ifsq zAWtJfK>c>$iTFDczuWfHkErB>@la3XB5E3hECK%aFyeyPcbBi#<8xrYjVMSqGvr^} z>9iA;Ki@1^Ax^0ztu+j5r@R>TG0e{6WtbtRB5Enw2MK-l4}oEeQS5J*>4^LLB5kRdpf zOp6cJ5adm_^HdZ~J?CV2InLt$p`x(T`>v_!652s!W78lgB8?-IH zVHT$qvTHb%^*puhy&sJFOCbDeFj{SN6A+gJ|E{nPO3=>@|9gC?xQR-V z|1vD3{Qg~6{9RPQt4JU&V14&OACmar(N2>4sbm0#CuG~Nk{-P^gb51}W)oeAC~(gL z8Fsm;Mg|{nY>kM#*&Ej&70sR8L-@tf@9SBjXUeWV>!kE{!n&C&T-f@i zS}9eq$}VCS*QQ!oRj@2B!xn=qIE@;ca<3v6gVNd!8vlW2GTska2u^C(uE|*kS1d*G zy8WxEQdu(Hd;|41cg9|m3?V?f2}HPg=A8x$E&4r6-7inmtTdozJSpcGHEr8iva&Ce z;X9f};Gy#>BJyQ|>;FOBTR_FtW!<7lut1RD?(Xiv2@U}gAXsn-E(tEd-63djLJ}N; zI|O%k2=4CwcJY1P{q^7d|L^vAZ`^V37*(tGo@>q}`|LU+)Tz{=`KO_A286{ftN7s= zW88BGK$#OguC=I8L6O!#AbfLF1drW(Igx#>Bg0dH4QIc?KrZ=37VbOsb2eD`a;#Ls zmN=LxE>mkO*H_Q;D6+-<#^&UQ-LwugGeWH^3)j^v;0C@0lJ(7z8~MwWq@!7iceW?^ zBZ`!k`C*fXwHI|dc|Esd2^E!qrAR#b?iY0YcA5e@+_kt%xp^5m0{K;c6fUEfm{}W4 z&T4ulyro%(!wN}#E5(QBgG@bZQt+1FD0REv9g(qVkm}DvZ{qqCi{PDVT;?60pW-89 z&En9S6tx#3YsNDQg8!3?EBrb96PhbUP>GtYIvE9}{Y{XM1YlohPJtr1&1)+SgP}chw>znLVv3z~qe0CzhNFO=laYn%=l<_f_iPE(uXm-VB=1 zxGv&VXX(mY!q1M8S=ScuQ%Sm~PwPTpCc_{yp7FH|`ududi(LMd)gDE3WX6wAkWUPIFzDJuU2rE_j_r~%)RKBR_v%vR;ZpcbY!vt^5a4-!`iMrV&?jqc7M!T zmDXOyublbNzI5bIIh_9ZhToW^wU3Cw%%y5-TZ^xl96vj2e)nd1;o5YTL$pKFFEJLT)UL(AL!vBDB-^)Ak)7^#UkHG2+r*|q2G{H@bYk3O@z zT_Yw`rYz2wwAQU6E(o%(F`8VQsk2%0wpI=#RCD{=D>)K7E*~eP?h53$LV_f6SXcX6 zr>Pu2Xp?s?clfRQVss6NUA)kNDR(uSo3Dz&?+MRrLwr1#nHcugO|$=i3O~(jk?yd?YD00b z4UQOL!m(wtydZBdmACsh8)~%q^>j&+g&VB@gsxLe*g(?(9-?*WAui54pGA2tL8w-9 zmb$KX6I~}Hf9|OZM8u+INI*|pf9mh6dralx0_y#|UN!@th0S=0WL8s_A%Am4ii8I! z^RDyI#My_FllTyzK50vFUGGU^9IG7KLV}nSy81 zYs^_goK#Im)&5@nNm-JsLgyq@o*#pkK=CvGQ5#(waFT>*&^w5S`ENAz#cINMnX;`<#sf zckY;TF8w>hFyI^K<1#*O@pg*Jwz~#?Ps^s?r8LlCPO|Pa8wWonTFS6eB_K{oIPNAS z5Hag0G<3h5^5H|x8a^B1+4oETP-=Jc2GXUy;rrrVAfthE;kmrapj#cF z?L%mCx)7T3Rr;k&okZ)H1Rbc`Xt`z}32guQyRtJX|Bv2H6t^|+Ju;-R14A~jp>wFJR zub6*0Q@7pnVrBX1ZO}kYY{))=6r<`uS*Uj`SZgMl6s4qt#ui7*IEPpLk zdm0>5uB&99S<*Zt&hwq&d8j;?jw7OMuu}$@b_I$xY#8<*_JYHE@ak>g{IE^RWL?40 zC+Gp@wu$BkSryI2N)t)6nZds9kP6yQg)G#I&nvdNvrch7VMu5K8!rkL-2vnrk-a!tddE zaHN1^95?_5h9(XK{EKC2sU7<(&R<9D8=73DB5#Ygq=#LQLFcSCcEBZ zKPV?OIk!JPwN3X_Wul<-%i@f(j^c*+Gv@GA^+q!4 z5d1vH6n@vWt3uB&9>FM7Jm#S#-t^lC8wV?H4_9}s8Oi992ERIl8Zz4&%C~sFWB+_J zrXyr#dcCt%p@L+YCa-;;VkL{@HQ|HzBOY(tc69Izx7sofZ(0zla#uy{OF{+Z4vwmr zwncXZb5M81kBr?iu9bOK% zs))^)1eDjCeM5hiFM{+j*S~^!q5~3vJ$M=tfp-){cr7*)?_{7kHh88^V_Af^^^0rM z^DADB<2hBc1<^$~N^1nY5j|Q!1u>-raxrbUg%=m2e_`t*Sh3IRZjLXu?_oVYp!@dU zm+4a3+TFpR6c$EPzry&&Caa7ketnr&(}17ehPz+;SmR_D3}F^_z)*1q4E=)l!0^#3 zWQYkF7SDYtI_sS(F%FSRoNulR4Ml65$uQSxIq8MNTvIBRmqVHk_lZ1-<%IvL@Gkeo z^;OSB;^||T-RJF^&RZ>xdfO&b;6Ks5p8Q@vv(kR%-Vu_o&E{SlKWh~0)oTxF2S2u#ekV_jf)N()dN43sCgN%7 zd<~dizj@01?(4VbOto@Kq&N17nK>=EYG^?WFSMgL;<^)>Cp74wpmlz}k$`G2{r>dU zZ3vct33EKTsQk^r$A)htt#Fh-eFrB%=!Vae029)kFU4ZPV85wjy16>dWXWG_PsP- zzokWN)lx-hW%(Z0!qRJ%!-6=X1t2#y03AZ0PXG$8334;VMGamVWohM%ijdi5>2;Q0 z$x`M=e65at`E3-rb!A)}&WNvy8yEfaaon_CLU2;&`y2-xswFBrjqim1MpEd!1*6D5 zDTQc@n42WvC$5!ZTUab`W%Y2@W|VRKFDo$o^%@xc^b)N98L}iZ&_GVZGp~`sF+!K* zN+?V2e4En{+oz{C8eiHq70l9YOi15CldO>EPtWmBYT(JiLMQr-%wc#PQmXunlEqF5OC^UL3lTQ0-gF*S9bxc;y_ z_N=si<&BG6c-$u9M4UQ1kho40>3KDl%0uLYoNH~4)w^N#O1E)~L!tW?$7<0zp^>)% zeR`A{F@+OZl#dI0KIcw-`_`3s+S3&7SiNQJE_Ho2W+g5A0f#j#) zx@SMZ-Gsu$+?2D4`^gRsa`SFG4h=$yn9y{e6EDHvuqzr(Kid=IV3);{!sPT}9R=_c?tvCNgt{^vk?cxGR_3YeYXvr%BpnyxvEs2n55p1RY-D z-h1ryzoruNtC^-;QFprwu69 z!+Sq>%>Ph{$Cx!aWL%n0m?Wca-BGH_&$e-$$uvLVM^xS_VEM&cm40Il5j7*3-PcFZ zG=Oya3K3Chun(6^l-uMf+-)YIzo{AOUy)LP)HB;QkzE=Iuk*_TI5r-7^{wlj(Uw&qZ z>PQsuEPq@~BfxUoGO)c-oqyBO^)rY~mW50d;H6&O93 zBD$yaA5}!&M&%*2bZe?SSDoxX3BfVhgqz3E8^JD~w4MoD}M7hWi(nXHmBBv*rfBU=E553+RcDLEf^euL1Sn|)4hT{J{u1J2lNvic)^_sxrala)-hv;TUloXqHD(QCH>n{hT|uDfCnHyy|nl;tm2+ z+S+l&1JS6+vOfx4*vk~vFCE4uv)12w(WkEF^bu3HEerJ6hGbIiAS81(92{^$A1K4-}%{9zvBp)udzFv@`1Z&7V*Qm1vGLkDcBf z7?(|c*5pi|&C}fbTKHP1j`bVSJkF@lg8Dzor9ce6%|NtXie2zIXZv+ebazv&&Sx=llCo4xPs|aUah0BdI0lDg^i9x|M(k8X z4EF~LUbmwAprZelk3ZWR;*)W6qWyPKrq+uO)BjPi??cGGG(8l!og9vft=)CtUTo0* zQjN`xcqg{D2dQd6#vj69s)=5_*6j!lDKxwgoMc_jq{nSQap@~_4G zYj&TvGaLUag=w=hO{-L!PC&8>Q%(Juob%7*eSaheq=(ubSfI9la&P&-mQ)P=4=eSL z;`A-E{&^Aq;rhoqH=xvYH9^5Zc@XTI1N|cSIJWRV|J}* z-2^gi>UDuxgcuk-U}zym9%5`ECJq=5Y^&gIf2KNErKD#?BC%^N=FfAg5Aej_|2t?F zV+~2$2?>ba`Ox(FO_0dgFLDMBYyAs!r2Q7_))LBNx4Y9td=ae+7!8QYgqSUeVe1CQ z1!7u&dCz2lbCCS6asEx{VXaA)-`xLgiGOWmwYGT2z8LAEJVaz0)h|yJm>w};w#9*Y zCIJk+Brvj4z?e&Kqvli>>or;1{ri^wYbkoIpB7gB$JP2$j)d29O0 za??r>CmT>vIwbkB%9oFmhiu&5vg3unGL~pPWbHNO5wyoe>VRX&T4c!?@t7SWrhi{B zhY&sxDc*YM6$RXcXhlR#6IPT4XHR4@?li1P!oB0Gk)E^`FD}Ws@Kyz>5%IM0+_X zmWzXlv@no<;-NvjvsJ{oSWaiz=n&CsituUCC5H3!5?r#MeatF^i`nYQM#tu5_=Wsu#Ev{DouMHZR4l*G#?QK7+FWO(JDRRPcnfKmX|k>g_0O0m(EMgavCP$&UKp?KCf zTRZ?*0bl}vX`twlmU!6`6B;~Ajf?qS5#-2xcN#NRfA^a%c~&cJ{g`3rsRjSj6~0}P z$jP5R!dN57PiSQUKn;LU0IUrmKY1^KBhHv>3g-o#NeEr)=kQz#XvTVu!6tNHh(G@;T#Z$;n3=H|7&g-%yA@2VW zIs9!kN^EkpVjPLmqYYbm>BNV_xDVyC5@7gt-X;>U2OlL`&lyUTjlo)6%6}CJzN@&7 zl@#|gHw{JWk%XV=GQ|H@$#dO>??9Ga+oA;ub>?EBRTa&7K?BfcV9K>Q3 zL8DIv(R5H2aq5)1+{5%>U;wz{J&!bvGy!)NaGm1;w*hcrjX&*Phu3mxwWvRFAjf8J zQiV@^T+!VPTxQ0f3Xa%;Ivc3v`W|WKn8Qvs?03Q^`P4eb=*fGV^Cl^jhTQ4$B56O8 z5f%6N>>HTR0FPSz7LAOpm_mF-TRO0_BKmoh0VU}bxt0}Uh-m)mYk*|}jGvN}%m9c| zV|@d6Xy8$Km4GM%h=h~^%k!y06a@gJ0Du!HjDez+f|Sf&T2#Ct+BcA4)#3?5PLjIW zE0tlrsG{svviH&fFV~`xLry3Ov3TY97|;?wyftLsES7q|q-X9d&&Lp*3;-Sg*aO8j zP%Hw)cnosLC^aG0<*OGKjPNo6FR5aYLq5=e5K16K7Enk6MHEm_=d{|%n7pXna;5#! zwaPQ_6}wdA{S@&HUe&8j5`^Fw9wo(;`XKM6pYj+O>*ks1JWA*=ZMaD^GzxvhV2;MK`uU{GrT-Uu2@8|`Nrn*IX7Q_cZAE=q*p5gNb~0=!?+7#JpU zfTsd@ywMKM{b>>9_1ztUTG=qGFDfkK0CcaD%^>30zK zwhbpo3uVWT(oGo%gkENlpukyY((oQLVF0{WsPOGmL4YR>cvNI)p~onI_Yv^4#3*n~ zZ~$)|6Y!Fs!?*ML0v-Y2HISf%mO%p^KH!B4Q{W8y#N;V)K0C0oV@>t2XnUrSMM7#C z<}H`biJ<&xoCfDwGfQ{SI?Q{hffK?15&#Q6N@h^5<`|(H1xhTjl@iT3^LQ{mjsTbj zfEECF=I~&kKCsAG8d`;UlU8#gv@ZdjF9>vE8Ro5534j>@m;%7p-IcwuFOPK`^DLg* z-uck#@QM)5uY?O30m_O1Lt+k`)at=W%@dr|o`RDaMYvCk%`EZ{E-En51(OW|I6qQ8 zWQ64p1Q@W}JT#$`fL#ID4wXJXkbZ+n8<@lb_6u-6Oecc#ixNOaXmusPXusg0K|WbF zi@n$TP}0lv^;jeo>FZ@%n<-25>q4*Uv&tbGf`hC@o(;)X+usrX%fE?{I-p7L!li{d z2++Mud8nWY7PsI>-yrijQimZaUO2p%d6mmBnEV2h zE-@et1Z-5mrT}a?z|H_{W!C)Y;8y2*w$wKO`3^x)kvg);K(?14K`@YD0tp?Ey!q*$ zNB#H7f6E57{Z)F$vPWdy820btPN*m=Sv)0>XDZv?ESFUh&!!({Nqm>B$JQa$dJ=H< z6>*nC&KUoFf*dcv9RYqR)oKWf7NGu03;-bjAeC-C>2RZV=`Fg7`7WK5+WQJPvVr5Z zbgN+vU=FAQpb7x406>WG?|MOn6w@V#N5!7RA@`N@eL}D0-jCTeC%(qdd6PXK6T((G zlEbcJZd4FEN}7!e4Sf1iI$)ElBapc4N$@S!M7bt=gDi>@@uzgzC1qL**JS{Z2mpQn z1e7)#GZ_IzH&DbORqXSBS-!0Vg!19yZQghgf*FL+1wb26!~g|%S+jAtvCrT)vgjC-Ho0ajffa$0pVq2Mt$zuTIP!$t4%&Ou_&)FOLYS?jsG`D?cxSyz;`JS+V-Nm?wZOgXgs0yC!62Ze1DXh+`2ZUH z?m;5<^ddX=&(`x>*}XJR{`b9`NQGaI_1-89z$QCqfSN@?%|4)J7|Y^BxM^K>xS!3& zcP60b@L7wr4gS+QX8Cha|N_h(Aqj^tpl{?VdB#_+YjPs<2eZA0zeP|S`Z)w z1m*z>YoM3|ib|j`(S%(+S#kz_+e7-c2K6n1HabAx@t{vZ&}T~j|6=3p=dv9|>z*LQ zW6&bpG+2q%@Mn{Y?8HA?O%zN62I|04RA&$h9<^rG*hiPSrOwGo^jM_4Vv1Mu;-<aa6$}m2GAlS-!)7ga)sUM`2gYA?5k4 zr^JUt%24Bdq*UQBNz|(x5i&m+AMtSvICa@r0N?|F5CE{TutC|>NNCOqcofRXK*9b# zQcl;Olbc-}ErCLcibWbsqe&8*C`8!2q`eKF#6WjJQ^7~W%b`)AC(v}d{4?BoXn z#k4eH(fJwIoB{zP06=JIba6*rse^M3XD@}%zvY}=fVdW2!Ito9x?5M_J-tu-OCYHP zlAB>wSbI55@JT>7Bd&zUy8%wiop1Gwt&_-WDHRSZ`+zb#0;0YGQAL0Tr95u&I(;_V z7Q=0cJvsoq0pZG9P43=GN%|ng-AmFgcb1G)4e40)PP0 zmmHvJK?d@`!wZ&8a3ef=vRii#EYf8zShaMpY5~*T2W|%+E*F2F9qs+-mUxxhvw3rB z^Yh~L<2_eAbH;kBMQX%#&yZ!RJAu6al%-%QvP93d#q!>%u8Tmj!iwwHB08R_xzmf< zwtS(^`;#$?ROTaaJFu~|vQ?E-?YWem_~sS1#i8uR-mdT}@<(aHXCFOi5hQh7VEH_V{Nx3%(8i z8e=wb=e#^g&!>&GbaRJ*;iyBt_jqPMPk855*kpah+{ppboWBPh=6?BZEc5Ta`eE}K zdYz{28l&YaA--$M_=>w$(%FC zkIX#EoQ_rvbnZSlf8ah3KK59IpF&xpcxLfopF0U*oVv*APJ4WS>DSEXJ%irk8?v9;iP98T=g_}9s>0rEeDS8PKnDR)Go#G7JA#k9aw$NP4;91 zr!K36da-q6Lx#v=?vFfYL#?ju=7#P3F88i0jS4K5XSMU^SttdQEY*@QH2T!)Un>xS z`x;qeXNFY;nA~OYvJ$Nf{lZ2WHtqMxqnJkb9X3^b-u*o^iYWA*TJLh%dc;845W}|o zT-`nr=)+-S8M{r;Ln-tk7tziokR&(YsomLPt}Js5C4$FAVu)wP(rZ{=qsS4Ir_qe- zw_Po)v76$e+boSZ@m}mR7jjxebr;4*2XE>OxU@rq50b_rSk8S;sN=bp?`|~VXGqpM zlmxrhi(JWV_jHV`E*kHtlTX)gx7}#VYzmM^syP@*bzr_7jt;^Radl%)N!+`!5-u>T zCg;5h%@CwE&`)P-q^D}_IXuyFai(N?E)!Y)8-G;;)fDX}mvf#KHyNm45QI z=X{mqc^r#br_9n9N0E8k0EF5%RWJQ!-c*VCfsv$Nsq6U2afsz=3N!j$pVL$t1NI(S zs`c~jQ8Wbdyxo)${G0IMMv^K&QfC5WVfhhBgmJ{A7Xtkeo1E``D2j7yjuW@ z1*<~Z?~4>>lJVR!p|W1Uo5?VUTyUNe(?Qy=9^$xN7EsoUcryv&vYPG0AY7-nU~gsC ztrA!d%l5|`f49&fm6}g39clF>wadA?9<*Jr9I9sHzTyiZN-vA`?w?zbSnoF6+GcS1 z)US-dXMM}Xr)I39V=@Hw;j{9f^EHI6ef>8!e`8pG+~wSa`pKg&IT#=2Z!JF*LPP(Z zy${%EB5q$^q716bh^*g&*fO1mAF%|4O=w}haMP}zQhxo}vyYfL%)e+GfM(mF|G4eT zz2}ZuxV)(v-0oJic89V|)DzT-=OQxi=OuhC#UquIUZU#3p=QUfafna8gr?2Gg+)CB z?ydz?Jz@aYp`dcns^_!v^}nQ>U#8^oOA|SojJv8f(6fy63?Ip3yK=7=|D1;Fi1+E8 zHh(?cPS1p_q1QWQ1Q*MxO%=Vj4e!XFokS}Sn$IW{A%q;AqN%6H$9lixcW_Zjh%Son zd{Uo{aWY*#lGozzRxggVL79_2k^1EwX8ZCsWvMVTElmB{?#Yj0JRRmJ7#Hd9MHBn2 zI!W{E9>fJn^OFy@>%rDM*t`du0xaG_7}tBFdewj)uK|_Pnh&-tz%P{DezC(c7X}&G^P@2Ds_`yMyq=+d|{a*9^YRBGXlx=WDUkimi$xkr}mj zbF#C)u|kQP;Z`k7OwF*%^k1-tE1Pnnzz>VvrKT<}G8i-DBJAR7*0+|t2oGQGL)StR zYUVr~UrL@ZQgVZ9bJPs6ei!rdknHLB*GdgAj)07RSyy5$)M14zy?h?H@Sd^3nGmZj zgyebSjE37W9z!s;2#H5g`Ni6)8V0ks@QsK0VV`*s%{yqXi$3(Xk3INyV{64U`uMA8 zSD+pJe#R5C9R3b}9=l-4ETp^Eyh}pknOA@F={wxHclyol*%8zl(d<+2Bgg3;lms^$ z?5Eui#It5bKr8~pO}KN<^qX4xdi0+%zJEPqSZgy)?pkGWCXl?2=df2>rYG zv7E2W2gM+(Y_z@+R65e7z^5lGMT9?ithd)egXcLHBN89YX& z+aikQr(w}yhRR|<8Yjx=pkMwpp)^u41FN<~1G-mTDo-(_{w?DZDn<&mZ*3kRNEwzg z!?6DH#VIENuBZELfsPxS26ADkPxH}NW;pk}+@}i2RPp;%^UlkqQ5K1K>vlWl4$EI| zKJG%ZZ%BL+J>yBn4314m#ml|TK{;QK@o9b(oc5@H)!U11_H~eth~Q^U

vo=Rr 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 LQ&e>foC(z5g?-H$ literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/_static/GitFlowFeatureBranches.png b/OpenFAST/docs/_static/GitFlowFeatureBranches.png new file mode 100644 index 0000000000000000000000000000000000000000..5b96426c76e9b59f162331cf2c8eb5bd1446b8f6 GIT binary patch literal 124925 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 E57MRp_5c6? literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/_static/css/math_eq.css b/OpenFAST/docs/_static/css/math_eq.css new file mode 100644 index 000000000..ffc5f20ea --- /dev/null +++ b/OpenFAST/docs/_static/css/math_eq.css @@ -0,0 +1,6 @@ +.math { + text-align: left; +} +.eqno { + float: right; +} diff --git a/OpenFAST/docs/_static/docs_options.png b/OpenFAST/docs/_static/docs_options.png new file mode 100644 index 0000000000000000000000000000000000000000..9105d95e6ebfbe6e524b88811dd589fea9d6770d GIT binary patch literal 58191 zcmeFZWmH^E*ER?QcM0z9Zo%CN7Tn#P0FAo_cP9{B8wl<a+}#OIa0zZ-b3b?TyzBe^ z%$haxXV$Q)>8ASZs$F~U+NZ9n>ky%&AcX{v2M-1Yh9n~`t^x)Ip$U3bz(Rv+Sj>87 zz`zitt;EEXWW>Zsl$;&Rt!&M}z@#IRHDEM94PoWzsK{6bz)HilN2nCY!R1My#?dXp z%8=ys#i5EHGmX$SxuJo(N@z&verEKqz-+CBy?If>N=|mIF%;YV2w!pJd)9uIeU|C< zn#Hp(MCo#t4K7?9N}ary-vYKH18;hPMp{8zYQ><!-4y_C2qtCNzdcfT+|*<VW_I`D z?&0!|WcX1Hn{q*D|F!%8F4$QROq!q%7lKC!Wh)5mC#8331sGU9%B;==Qykp|M>vux zi%58(Y*t}ErEFGSe==QW9{{<}3yfq2z^{b`wmhaZLAPTeLUf{o+A0fa3<t(*8vgE{ zEC*~$I(%SfcTC0D5{7`S<LA%=zC}MQb!;kU;9Px4FacePoQsFc%Y@sL!_bHt;s7ux zh$=y%pWY_ar!|?KUN*uC^;U+>*qC%a>@HjLYi$@#VdVRG8EdcEB<B6D9B`_>DhPec z_kBgEVRFtU`J4|?@=hPHjhjR#$(+EsmA6|}X;9=Q9p?wle+(dR%j1SsUfBH{Qguqc zDaPcHu|;}ijF00ReQnW9O3NR|{e~5pXhJd{nnpVz6Rxsi$n}FvVH6lGk5)ap0c|Xl zM?oe&7CSbW6f$6QZ02#f=~+`q#>y=jR1Pm55s#N6;GIL~M;@LTg6=lW600Og>Dh!8 zz``M~$2U)!L}7LKqon|f^a5`qb$azfw15KUo+Qn+I%?)H0tQD1zz|$F&f1q>QX4h3 zWE^8+aPMQ(r~M%80Lw1$Jb$S7j;8)vB>3Sgj~Nd?nXlzP`~=4xgb@9iKZWR3P-0GT zo&grwO^gZ`;N8b8&Pfj$qV#GdUf$8-FF$9SH%t!0ANm1BJV5tOC+{*LN?Z=QQzZJ1 zc<P>ILH9$F%j;}S9+mbtWyGu6&!LPFMtw@g6s%bX;h8@JnuLgus=FPVwgsEc92@+W zFo-aC;bLJI;Pir5*nh~G8qD=VBno3kp;ndhY>#9(@eLkEg#84MBX-`FUxjS?xot$j zMFeT$CCVt3*j)Qi-TbQFi><e?sH{s%WA>ghZR@<gxFNA&ANEUav4NX(woSjZ0S`I5 z!N9)vlofcJl#g8m;}2xRePH4u)G_Qlq~@Yi1+GnR4Bf>b-NVQF$k1;;$}fik__zG} zwylim_-NfL-A`PfOLFK@v1m79{n_PsrKrZyF@cNcW6Y*blutD#nx|Fv9bhz_<cABh z^hJk{{w&Ndg(E`X{tmdR=Ff%OTJIe1Siz#W{eD##^bD9_f=Th+!E5DdhtV@b3PbUp zN3cQfb>V&J@>~tTK8NWhL6nEAAweq$#08F!HRYHYa;3pw1*s?@s|Q?vg|`J?>0&y^ zSVYO_LUTmVf=U&JX+l2jnVWf+6X1IejYtM7DtZ9>j#ZKYRi_WvNy<A;m;y0Eaw}ey zf^bNbA{-(;%sVKF+$N6BlwKw5DT+W+febrNVTbDy^_PS`8L<*#VIFh|u60<9n2!<{ zUI<nG%oGC$F{7m1B&H>$_Lox;{HeqP%HO=pA%bEsEdEwT@}uZ3-QFz7SYHZ_($f%i z{F99^H5upq>$_g>>E=VOjn16N#=Eqd5Olla0qElcR~Jxs&Ta4;A>3QV7v*<iZN#tg zUoqt2#vz3uQdvUcB+@?8P^zN3p(3M=cNLe0org+OutnU6JKS*;q1Q#YM2tjahI>U& zhiCWMZ-GUKvr+LRLP*z85S99?$}USUi}5P7h#r!*liS2I4xa8fI^$`H>Wfy9oKX>z z8;}Z-qNsePZFnyv%OD|~E~X{3q+pe&Tl8BAy3|wE%NmR`KI5aFd}RTb(uC5PvVoPA zm6p}L^~ZU18^-Cf+2vwa{iD2juMEMli2l5f-)JrAE%~gdEgP+>4?edL3Z&&oGJmc9 zx-g|UMLfA-#r}Q3+NB<98KJ(s9>2cYQfMLXVDS*>YJTwkNcDhVvbkcWSZ=C*X7}Lo zGxmY{5z%~mDc{$DNtc-~b0af4RgF4lf$N`q5<0Sd(>jDZ#r-m0XrJw&`+??;INtr- zQ72LCQAF?Z1KPnCNLIeC{-h3a3-T57>AeUY3Y7?*3zb4@O~aXq88X{r(_p)0cVH2U zV#EJIL`hI@tJ+&a|7{&FnhTx_9WNR8gtNu|cXyf@fq9lm+j7&;T?d@~mMPnkX~U3t zB0H7OHzdi&*u7XL{C2<Jgr8<-hd9<hSN-Ce;hF(wcd3JAFI|$X`(*C3Cx2ylWqaki zH!$kOh=Ub?W&FhzYk<+$0=IUtLRX#gh@*UCdX{Zk#i)6%cFlQmc%5#@I$}=0{Bd5@ zhWJSS$aTJQ{+SDlE75juX?A6`rf~6LG18WMF{jSQ#=;@h_%>TFaqW{AxmT4>jZgct z08EQmoLGlgWiO{x{<m0@m~E;7Wa`<W8JQi`lg~@It~btDd=Ad11Y$Vbe3EQMZlfQu zGZ0n^CkxkiH#PSb4{GH4xuSgp$IW$@o94F1qaTkCe`OrCtX)@ScC3guQra`xGp}W@ z-k;8$F7O`^Z4w~}WC-X-xf3xHbb357Du(V;Oq}uS2ncz2cn!7TwRyJNwav8Kv^hNB z-1Xfv-13~sog-c79eDNKw&$iA1Z?<r3O(yRxjeZ)3S}D#iF`163_b-b2h;DG_pcIG zH}w385}+rNBGUGC`Kwg-e0Sha!fwUIm}A=;qMIw!1yrrUytqaJp>gl=2qgv%vhNJv z1>}VoXe;QBMVizA>Hr^rU$8~rYB)xG@L<W{Ts(KPxvpSi%!<&I*Va=+@i$9lIAt~E z*!=8#vnj^JNf`|4%Iwd~{aljhGw%_Mn`>-L&IXnSb_br>(m(LnJ74b%T-aY+ZB0<J zpqo=2D*zI45}Md9>=VQi$Vxf2s6Diu^)6SECX+a6^*;4~Oc&Z!DU&JtP|p*cl#<mz zZf9t{ID7rctH?uvKHJTt<@tC1FKqL)(ZOt|&qd?%>!a^}1^-U^z4nXPqoz%JT^O4C z8`ZbmiA{%}LKu(;^KhOa;60o@)al^qHf*`(P^Oh*hnP?ibmBh7F-@{hWPEI1ayKhk zi&@z`V$HP8URQ%2zdXVy9})<LerfI1MVh<HW)~JtS9y0nUEe>~(kvnKkmWKtFtPaK z-*ANlZRz~z?dj?{>~XJ4v>>LLrcZcZKjxHCXFHy_b-qQszvXi8qO-3xuET$}>3#E5 zi4X^ci=d6I&CH;+SVv<#RrO=`2hSHjy{#70v4n+<0`D0WWA)mSg2$C`ha<UqIkQ6U z&Z}4Z5f$%JfYl>gtQmf)4--a`9)mk$HO*^NR_D{!t^J0Euh4fg7l}vN>f}rfGz}T` zHBG|ro(p*GoIh+@78JBsnqum!Y}byi*%u5-a13h9-nj-Di)omBHoKC{j4tQ$tw2}P zt41ze*D=wqtJpiC>Mo+s4C3atWnEF}*zHBxBDS}SUR>6+(a@=hZmM)#**+OsnRq_9 zGFd}TB;4f_JV`n}UdHS^`kd{qw`M=HMt?NrDdBULW97x`3;$f&++ApNq`$X*>0_8{ zym2N}{OWDuH~TXGP7nqUd6}q!r|*O6d^pFr)v*IQrz>YMmpf4opsD^x=k6r4iQke( z-=*}ma_=|#SmoGc0(@S5Z||SMzr{C(DiYT!*>%oxGMo>We+?C{Oo(Um_;EcQm%1Fg z3{1de2|0J4^=y6-#Li^$(6hF^vgP|-zF!@-+`f#@>}6nodVXU0D{Io@SavcwQA4ac zr@g=3?U(21^*Fu^xBXg{TisF0&-s~^=0<~6+BSB8`;<UWd+lS(Ej>}1V99gpcIS<o zhby5E&I9m7x#wH!+S92;=aApy;-|~Bm!_?VABio+r;4$^LvP)l1g~#%ET%1jd<y*z zo|UgwH}AWJf?jQpa;G=0L~o1_b}u#htKB+?URzvA?0<G=ws8kJjI85!u3WG0KR2V$ z66YX}zeqo5-Va@T8rd(IxDCAw4K3iuRjkMC`YFuL4i0F>0Q00<<@*dKoLwfkUka(5 z`%w+{iMm1%p{x(VKf4=@f)RoQ?^Kzq*9d_XX+2rzy3f$x6A*<MJ;*MwI;YD4*dlGi z$MZCU1}lZ~SFFv;>;5PvmfO&4>hR8y%)qBZ6&@`I$(Kbvzag{br_DWggr={j61mzQ z2wK27N^7}*fnia;y})HuD9*vaz_YDXH9u>9l;<^ZuwybZbucz#0@yi%t_B0+2k?SE z+L?VeA_3Uh+Pm-q1jzomf*17pt(uvP<ey7E+X#?pepDh6b8t2z;bh`qVj&ZRCm|u> zcQ!TWRS}o`R~+=00GZ|I&yKvz%<k^)Oz!MV4$c<LtUNqC%q(ooY;266D;Qlo>^~a; z80}ri|I^5ycErtGOq{J8KU+E2lf1QSWbEMjS%8e}t)ss`|IyP7VD;ag>|OpH7HELX zZ{IMpGO;lKZ5t%Y|5nSZWCbv@)fBg~GqZOA^&!Z`!ovU0_5a5=|LyUANNW8L$qyX= zQ}Ta&^RFa7^V<Oa$AJE0t$%7k<`RVGXZ~w?LHP3>Z9I@S2&}{vRYC6%Z>|A3P95}% z=0ERmpWSHVm>NJZQ5Z}{TtpQBew+=H_Fip1bOQ067<5EJkZDquND@upS4eP|byuXL zmObF!@9HX#k2VV70bc_H6W%K)Kqgb*Qp&|(q`i8(KQuJjv{1WEe4g3xAZn#wZE-!S z?0?wHa#5uGe6-BD-SzUEkQPUh|N6^f9dV#^_r8h5LgxG$(^Nx~OQPi!h?tNa2L|__ z(#IbVd`btr`DFOxDS8L$Z@oB5KyZWIvgz?kt46klAh9ZrfXd6rcb}tBM?lNdvw7Xm z&K%oiN9=!_0m+F6f<dWMl+-GslYswI0-C6V127jFbFmd6D1`qhsBjQ)CmiBUsiZy9 zK(pL`YlR`4Wc`UMKD1x7+5QzCMElwmNuYBh|5vsck_Nc-yZ@?I#vfAppF$?(&!ZV{ zGLrMRW-AFyK-0-{+hgf(+wtTeEqEG^)BhEcCQ*P>GW_u?dfzPZj}^pYz+8Z211SQ3 zYx-!xJ^#<%An2WKm)QS|SvU(Fq~i?!#0b@YMhuP~P5=&HF<4_Z@wa=>&>-j)9Qc_t z|Mu?;8p!|N8T|jf;s3v;PyiW*CMKO~9JYb4mi2rEt=Vu=yz!4n8BtNuE<4ACwcXw@ zl#vAkKSq>Q_uPVl0!RWAjnx}B{La6wkp9X7`#!y^<>kyTb%d#t|0iC1{-B<F>WRqh znpbrcG52^Cv^R{6K^wq{R;$)jn6H9Bz>}juX=M5XJU55^swPwWF&ld=_RFKe{qyZc zFPALr1`Lt+<Zo`*L)COn7xTpjCQB)^k(4pAVY^%qM1UYwApbY=@=25^AdZ4D6yh#0 zsAcajci&Yl(MPVjx-Sv^o=sF7&U9!q(s<VqRNr~9^<{T{#U8=ZLgVFb8)d1*wY);7 zRejy#(N3$uHhm5AdZReUv#jm+Fui#exl~k~f$u$~tw|`2Ufbu=UuWsXxhWd6M>vc( zy=@*URl3b_y-N*tnHAdgvg(z(v~sBo@m4cMGLn*#gEy-p|Az7=*_(FpQpCyZ(1?Ru zKIf5S?rVAt*nUftse`dXFP8tPHlbh$MNmP%F`7Zi{d|?{yfcV)R#l?I9Nu-f(par~ zpV~P%L#OU{w;9H;fHeX!;>CKkH=gYEa?QN--73)?d*NSCkW@fMiW|09tfwFo@;yM! zKWE5sI`sq-Fju(jk6#X#S7*3+-5kfS7w6hLHwNw+?NR_=oO+Qiw|hd0s&{rwOSLOA zvQ}#gbpcZnDvkOAbv`|J7njwoXX8$~5^G;cAdY;IUZa(&7la(zl#9IY%~IqdpaSZ> z@12{K&x&niWMou2Mc!F0e=ohSbUj&~I~L40>K!2V(-p*F@3$K_`*+5}(g%oQYYtJ$ z4kBJ7lVT4?e$5f^91M5|Q`^q+y?uL}&usQ!s%ULL*N4je*TbYyZ-Lv%^5tsX1T=xe zqZ@Y%Q3XBct4)<BM;mm_^|;rW%+=o5*xfjxpzb+XtT}ynm*+>Z3cZ%k5mo^q=Nld! z8xkdt9DqU8=Buh!c}+Z{o-a&I!dQ&j@5^`^|IGrz0kH2|x&j*^QFzldAk7+2*W5?O zxJPDbKS6Hx&&(#yt?lOlIoeKY1h^p(PDnKM0lz5OJ04G)r37E@Ol)JcLA_>N&S^+~ z?XQKQ2VKKm?fd+|rXWy=I%P9o5x*%GCTneNJ-e=f9QBqQB9r`ixzLZSb8KqFc^Z6U z2W!X(KaOU%DM8IgQ0LH`wOz%iR;m2(zl{8PJiq1xpvhUUD^926y2^Ag-RSUPI~Zku z_p|lnBxV)90;B$Op9UTO<bVxcf;gKGi&%p1jQLoB^;}u4`L(rHIoxHlhhZv%nrsG# z6<IVMCtJidy+#Ep#nOI1YKQGyS@Q8lr$LGh*~`tzN;Ju+VgjEzER)I^O2-u)(D9^F zyD=q!PF>v^-NXJW104gSFh^gEeYZj53_oGg{d6%tQ*L6qpQ?FZ-7qhx(}w1vTEoEZ z;o<CR0>NA_lx_8u*Y!{u1Bu;Oovg}bWN$1l!(u5$E2e4u@S)Y9JP<jbN%O-Bk!HK6 zs}*2cMn&S)C++6JOH?{h@@)!9h>%<qL?(Ev(YqY>qIfeqhx^6t?Fzmx>uUKuEjRXV z92pfQ)96rQa7^qdMaO~jUirgK*jZ<4r?s)$BQoJmH1|dlYlh<0K`+XR{g}H5<UB2% z;rfE$)PPvVx1F&C5v|}bVh?d`%kdPOFl536YPG27Ig_9<_3~n(q{p+)jVOH4-sKvT zfv7mIm*)M^pjCVK&Q`Z0s#w9BG&Gmf8|KbC(ITslz=78*;yNDgI#@LHwg(44_MCD& zIw~X7Qd;e*9z4;i^HmQQU`HCi7SVI(Ya*B3G9-Y+!tb$i)#>r1)@FfeMWTyaoFEuU z)+LEakJpe`wEotzYQ>@R84D;-ocsh^p+aY0Ojj+NOg98t0_;=-ysOKCzTHEAt_(yI zPq1m~pymjpZ_VnKe0T(?3Y3rOe1|nm%E__!mAi{>>VfkE{Ja(Dx{`uej`eu;@wiF1 z*!kHVbjs57&n*{?TB+g_5-n>*4G#*G`nnVKcbge1le6`9KS5Yk)h;%nt97GEa&MpY zGL-nK{p@{*TEK;IbB{*nP$%mk1W}|(e@rrT#&<+7d18IQ`D%fY=oQJ+k%8H``vw$& z7HYutM5aBPD40*wBtbRip;2vUR<)niA~1L_p;Eni?$%`wM;Ux-uG-I!Tsn@}t+kk- z&tpHAnR~<e%aFjkGs;7r<w}$ztOr#4igkuXud@#NSU@mYLlACH87l1ux6MGPqIpby z`pUU4kagGX&g4K(OW5C}0x0O+%53ja@B>1$LUEYkd&!uQ^i#|;%Ap+yY|~T1a6C?% zwfYKa>B>nL=IMri!UeiJURQU@@>~bHYHWrdNsW~uB*%{|f6f?_@`c1|32H<!QiDy4 zIa$f%wY=eI;tCGqD*=Rc(?=Z96;)`LeXY`ItXg_Wo`>vZ`1E^oIj(LZ<xy3f91*Vj zc}7tPcS4Qx+S%=BeJxyW)Vxg|iU9HU<lVDf5cnl3siCs|Rv#W`fkw5yO0)BBTqnW| zxX|0WheQ-I0eUudtJva2C>DbLEDm8TD7nPgtfx2^uR4OT=$}+|ieExWq$Gb;HzAZt z_wZ9Rp^ckkzoBt|<YPGM&?GAHx$#dU_wq<Gn|kZH1jXwtDl~l?v+l%ALBn{Q*X5&X zIgd&eze-Obb1Sya`py#Ar}CHEWt-|D{N;YE?mmyx`Dt+JbtwZ2Bs>ayZd+iO43f{J z!u*mC>gO+<w2x=nU$0}c`JNxq0!1aBta%a8K_)jt2{nAytwu}9L?vDJK~PMN99V00 zH<??sJ8W*zlr!&Q;ltSKt@rv)!cc{>-61NV*;&?93q5tmyyjO0&mJCsRZqz8*<AAk z&*0vMI(bR~9ey)X-PH4xL*)50!2gNwsp#ii%T3GCC@}>}x%-t5=EJ-rO2?#E2r7$p z{F>wQb*<S5R_n^_v8c$R7Q4l;ih&&~ti!5bIQ>p=vp)aR_=6>Gv;!w%OdLz}TRw(Q z6ppycl&eu!8>6KKUMh4<LaKu%!0rWg&fUzXB9rU4JbWU^pLL-W{K4PwQM;Y=oB}Y` z;NI8@fdIw6DG`u7#e(W=hss-L)OoMnho1j#m!v|VFobKfu;-n}@4<NRt>K1d@sNH- zI$;v5aeU5Ud#(*sj4F~kKGMOCPl`BwSi_=Gk2@HxBLK1SITsP(n}sk&=c=}Oxh27~ z5z5Gdt_RWH_{K7@3wV-XLFywx9R4q`<=SHD!Ljwrf>kHbm|;x@`axlra@jzz8t?j0 zU(zjSlY2}}R4-H?mS9eyx%@`pgC`-z+#~G7dim?4!Qd+26Y@i@Q|JX%&acP*3)H=H z$E`82=f~?2HG5pqvHcRDHj7_}ZhnZP6(|*Nk}EwOOC~7M$xxi66)3FG;I@h_aLOM7 z@=5k#Q+Q1hO>Jj@-htA_j2|!O(+388Cwz-q`3?&NT`6m<t#}&DV++PM=ze_P=)+28 zf859=vyyWgtjTqg?pMC{KjMkZR#8h>J|rGWmWwE`knW!kN@)1pN}xl;zYDQX7y5Fj z5!Z)jMv-StJG7WfhpU4uy__}XEFX(v4o8_-pn03Im*E(7aL?XAm|&85bM)alRz$#E z)Hskrm7WnUSyuK!1c?&dL`5$9yxg?F^yMNmK7nb#_vH%3=Xk&=g03I^C~4%l)7FWn zLGN*%weS@vF_3y)@0RkZe_kws*X0`zS7~Z3UriL%tcCP)8)L%F$8{AcmK4hxQ8Z1s z2ghf5V%@=8r;ylIM3SY-6(7JksSs>4|Em)CZ)T)ypEA)An}+t*HB8M@H+PTThif(k zsBWE%mEB0v@NZDsv+sFiUgrr48aF&g1V%f(6R2pnNuvoe6||2==p~<!1Q2HC$^$4Y z&VqcZ1Of3dkZ546sH2yBUw{FTvuyxiZTSvz090Ox(utae{x9OajjCqJs!xjJf=G5Z zlc?z<vm4UbIo^k~pS-a!;JZk;Qw##k+9f{>*x@xuN@GKxp*!a}PAHk!Nrmq`a@nm6 zdkIb?UoURnHV7Y;b$eY;g%QK+ZztimZW6zu0=P+snbZQz1az8tQtUu;r<PjD+mv0# zI`!9@VrHY7%0MN&r?BWR3R({f?0AZ?=sB3jc&U9n5hY^)25nIfLP{0NW0I4f=SGm* z&Wh&N;k=6c55@lY&oa5snH1M!6_p1>i5;G?1#KOwvQaNHayzF3&dbLel-F0B;F%b7 zR0#daiyzqA$qlL1RVfOiUe%_tZIKqCHa~4mCsO9gU-+N6K^fCr_a-Mev8c(e&kxxn z-~0R?f|3-@6X}8DEm9s+J5NSg7Tk8sDDZ93p2mjag?-scqN1&4NZzqoHeG*b!2C<j zU3&O2Z-k=#eCtb5r0`_o9uO@)*oK1)O@=;+fB`^bULFR$2T$z2)H=~>ze1)6v!2Jz zDIT`;8GzcNPelMzcf!8FCZrbtMGE{Rral-Dun(_KF}forP-rM~i%OpRF~gMiK|k?W zY|J|dtZr!d-R#P4sP}3OAa%;UHxy}CY-~VeQw`_Rp(9;jg+Zt)|MVlKPd5V|Bv#}A zS>w@uu3w5W-f3Ov&SOA^G;+f_KhFyE2BV_jlJ2WGW`cVtYJ$BN!@h=LUJf4oa8GEq zOH4XpxS7sp%pUkURWV%gS<wxA$T<I(+C5uRWuN6J+&$E!o4bQ=v7&@TKtfXe9c(g4 z#0wsihtK!&uZC%rw*pw}WT=j;x}*U#<Z+tSZ4|E`iI-Wf=Lvi@H`Mdiv8ySwwO0T( zKmk1gIodNb!CATWISKUP<U!l20m2SymW73tSiQ!c?yBv_G|x!38-jRaB)ae<8gn<o z6`%(C(XSS~HuZs*4`dPb*M#Mm31eK|1U^nR1S`Oa3Ncu!jb$x#S#u(k34$AuuCH05 zq8=Mgyz}IWqp49og4OXk)jQEAYOu*1&jgR#jz#W>>vfWtlzA<lQL`$7nxwzV-Q<Rj zR!S$86;s;X)>55>ABS1SMhB)+Q>FXIdnJLC8wDY~uC^@S<qR6+*pLgQS+8I2L%w=~ z#|n1RbYUDg4==j*0mkI1J7T{(_$AKD*sOg7A33ue8+JSSTyf9R1_gbMN^TXh)qS{D z91DlCC91o*&E$3Ku`q?j!|%gEpk8Av5ikHFa|zH>V7a=9=Bny)Mu;Yhy3QGYs=JPt zw6UDX-VHHP<U8TGuP!sgK_3(IFqVJ!>@NjzFRsrF3#qB-18|=%`wgHmffwS}pt<&E zZG{-QP6{55@43&{GW027M~f$j!TrXAnfRmLJO3nC-9g=+p%dZ=^E%FTp-o`57x^J} zCPe|DLyh}=p}-v$5bR%9ccyB(?QSXX1u)WeBnXa(qVHxry}~Toc3WB^89s|=j-;SI z^}L0^oL1o8n!N$K4|tHrd5d{rNcJk1=2ozg@;RUkal5jR3fL;%Z>Y#DOcGV>jL{L4 znT8Isxe=t0zot7h?El_`hk<QLYV^IhP5-)Cy>qlI3(;mKDEI6cRPb>nj@D2Wk<!37 zasxl9!?d*^O3NryHey5}#rUH_9LF_up-=OvB3g3AfL`9f+}LljLaQ`(*I{0lEFF9B z&8~0Ej9fWPD^@i{$s8I*O$Dz_WA<ztlxIq;`xst%&Olj2JBA;;3oIvS=mHO?Y-pI? z^O05ub$un~>5tsRao;9hEZt?msMp}*(;t>HMp27H-J*pN$-?bm(vV_|m)!D`*K%gK zhu;|m>Xm4n@et;&Jcp10S?Cc^NYd!NSIy1@&v=)&<~VQ5+`-uEiM$U;6Uh@dQUyQ@ zgZ&=)_EzueA0o)_$G7pE>jZy$P?BU_;th-FPef<XhY}EumIZaULMh_#TV>CE3B|@H zc7PaZaa8UHFXZg8x<}K5ZOoT{cM5)}g2Z#g@EWH-Hv|JHM0P%o+fU72nq-vKS}m73 zwBxkBt75hVREA1eJhW*oU2mQSX&fV71CVEBknb3U!+S}-GbuY{W`>^;4S+y+z%d+! zYboiE2`gJXT&If-32+#aSXwPHPZoe_RQRQbHM&hovT^a;6bJ1Xj7m2;T_f#RF+Hac zv0=Uuis#fW??QC)OxYT@xiKTjCaWeS5B+&vk)*t41F4+HPe~*eBY>{B&RtemN>~=n zhgu<u-4lb+S{-}RR;5y_WA7abAZiuIrnrxwm^3tCEXy~6*_Jed+G4(wV{@TBoiadI z;oO_hL$aD(x+-NxE#*gBWJM3U299MPl)BWISgi!h7@QNicZx<ph&OhyQe1V=lG^@3 zl+Y|2y!m>^6jc(;2+?cBd|n_oc<544nuH}%edeB(2jt>f#w}D$s!osvq7Qj6^p7YY z`c|iXk0%f{58qAHD$<>U0dF*aDJW$6{b1@!MV;W|F9C$&T`5D-0r+Nh7KaXO$ea5^ zHp#)IM{_XuRn(pj+{YJwuR0``%BMY{-OASQD7i0fQ2hom#9r`%dCX(=zaDXbjO~r8 zG@(F?biD*zjW5P7Dc*_e{D%Hb_4xbPd%i(;(e+OvW0=TNYLg<1&7spUGy!08pQ_QE zb9LotbVOy>D^1i#J|s~|5v6UPA~#3rmLxQq@v_I*@z6-+YFRF~1ddU}+VuDx-e$Tm z5M(5F$=d46BrspVwYYjwx{h9cHIbY4)aF7tIj|8LsxffSbYm)>9kRK~p3KpSS4-Q1 z$HuuJsCc!~g5Z`se7l<=_M;iByFO8FNF70tf_tQRilKVCw4+#_Wi&b*kH{EqcHcz6 zQwJZTj*Bu)^+)4BulZJPA?I5pq*x0(f3~lzhW}!rYG`ykI3gMWR}F=sndT8DdjuHN zR*bm)P$5;<g;!NA=_zc1nSV|f=~=ZP1G!n-2G7tGFQjrt0mxs+GS_X%Tfb84TP<9t zSv0(+$b(jA=`BzHnI5F~?Z+oO9%Ov3K6#nZG=`Eqf<Dd#eVd-KlQ}W03V@x+MEAA~ z2@!0Q5yNP$SWi7Gl2|%FJ<@`irQi(OjwR1#<x?#vh*<)XXX}d$L&+H|bK+x)XT=0Y zeJO^Co6q>_2#(*?QK0n)anp)eFd6R=Bi50`@+Z>*Ntonb+OvgLt?&-6i^?Zu2BIXd zfo26n?3rt^S&-@pp0|;?OI-pK1G}>k<&;QU3XIeWJZ^g&gEFR=4NX0hWT)Mtg|2NX zKQi7D278(<<op0$PVaBOo$;TWp<3RrQ?)30qbuCYpbfc6=($Y;jabOOF*YB}F(^D< zaVL2ke%6x2U>HJp>n%0TZp2L@?l6SBZu;t$;Wh<mh!LCfn7nz+OW-O9Y%T3L&5ntR z3c&}qgu+2iSVcewHyC=*&iqW#Xp#zny3B10Rhlz47%Mt9M_YFCOk71v$SlYa-ogHu z%k{BJV+wV+ZB?|sZpDQjc&_t7@r?YGa2#AY1RbwLZ5Qt)Kw)|*4uGUoV(Rt#dY<nr zO_wqJtPTd{X5VqGY?nvr4yzM|Vq%;4`vS=+a0AnAoy%=4@>6ia#AGeX+gx};6E0!a zf(m8zSsU4u+RK<mk`b_$xu{cM%M9{JxO8vG3K0{5!WzaQIV;t?8kW?A!ng46nuZ>v z6k~dCj^T+!`Cdgx&jkHx&4&k$A)H4Z6&Q*ezLfFOiL%a1G2Pok3!F5diC25S1-~89 z)D<`YR<~Wz+%urZ6$D2H{MoFXKXmN=Yn1tYqd1O5fgl0%0?d+VHWu-4o6k2rdq}M1 zZWsT+goEvmnBj_+IIy8%+koudd0~t9WKqFOzJQO>j6c8vf@?@2IrRmMVl8uU5Sg3$ z5jpu)!>nI$oc${Ds{L%bRdoDD=z&Vg1Sp?zE<2R25H`7BiB+A#EQKX*+f<z!_azUU z^FnhSv!#bS6xu0K6Q9)}6+W>B@0<m~Gh`jvw(m*(<`iOS`-(5R)Zv9DiiJ5|J>{tR z?m62q5M0)5r@x}BM<|Eytcm<*+?Ho`7nUurW!i&jb|Gw#ummg$`*q+F6t@0>A1+U1 zxM-hFO;maj%HiVULthN{0(=jmDDI}{&iq=%E%fzl#ipy&?V*GD%6z4B^NZxUmoQR= zATQhwE)xDqi>+m>OM4-y(YEW15EBb~JZM8M&JThH+z_MdQ~#lu?-Z9zhjQXdc`8?S zOWpOQU&<)C3pz3s8i?jWN(Z04PYJ04eVM_*JTiZI3D3aJCP1ZZfkZ};QLrf>63vop zX6X@`q`~Rk$i?1GoautDDYK^b75N5kHa$bNTISZHChNm)A@j;SeQl(yt`R>PwkEOV zN0K(*oz>0W-SF{>NA`CkTZ1dy=t-nhp1&$Oj@!UMeV2G#7kLgYA0n~?@RgFEGaWiu z-~D)Z23I*}DnU-vaa4cl3FXsdEJ*_S4iekito;Z>lBN;NDAXaCNck5*&qaY`bit=$ zg<9$2FZo;CWrJQ&SPIr7Fq$fZYjo8f!sq=z^AMc^mOOzV)HS*8nFEZn-o)V(EiB=@ zN$`a4B?US%E1ms<&(?zxWC`zk9?l1CUGLon*xiNsi+%&B$=i>@SFC=Qzz^?-x#r|r zPtQKRXu3TY7qK*2y^AKTNH18q$hWf%g8kt|{#sl}3)<lh4{S*@f)yKIbI9b9`B({V zVFA~}7y4jl811PI2toC=NW*MZ=uH^B=qW%AXK=);g1gn9D7<acr3ObI%mGUnj@Lz& zTky`~$Tmv#cEzuY*}49v81@ph#xdM0rO-p#34x$Cr>rO7GI@xU(V-k;RY@}oWGf0R zoo!zmHC75pUZT5VXBCOG+TwvsU>u06l2HEixu~!nl=zG>#=2YhuVOX0OV^2VXWSLC zoOuOjeZv_FcDv3cqopUX5IJMQ5f~^Ax4I*PjdzNgBG&StF>U$U7^R;in(W%JAjV4L zOhh2D#$(;PH$&P9)xf%4LKo5&YfKoLn38f!ic$3VlZ-6G7BYUSeK<Wb1fmeV2QXI@ z!>@4t3c@BsoSSI13_t7Sr6gW3KQhdV=A5<b@hka&5`>L-CK8MqXo+90kDNtb4T12( zU{j>d!x{Dc#sR%=oNDZ(>IcY_c4$~Q*vdWaN4PC;==cC!=O+7L8oMD#FL}3(B{&9M zm_B%M{FmNV;tS-iRXj-KQ&w5PVolFcD3E1X+LXH-rFyjc2yng<P!ejye=eNwU-?K! z`sBtm{m85O3KlRh_LAbL$Qr)|h4h-w01Mh_`f3P?9!YJEg>mg+$5L0VIWn4VSBk;G zd=NI;_BAk@^6DTfSj-nnJ>rY@VH*2uuCcW`<2uoY)izj$jra&8df7_@?Q~8+b&Pel zq74sRMQ|i#;m%1mTjn?6BfrlO0rQK)mAiekjnCpXtsukmv*^#VAr0CEzU9E1)2phL zhI7F#{JjnY6uWlw6|crHFT!<>wr{BG#8F5&;l~xu$#j9(uf|V0oT^D0K^BnmcHxZG z17X&&PNd&MZb|kec7hL?i%$Rp#&DQre6#prsbo@hMir%p_3&!CT&*=GD&n;-k`3h= z;~jo%s$TE$LsAhp_n)%pRXbM|K>0(aE0f){!P*1-lRt;_(!2L`9}o33*!wxn<ZRRk z9~m9F3~8!(;KH8ZD@+-|GBnF8cq-kwD7dhMzIFUmV`rI7;x%q}KJ;Lo2a1~4e0q=Q ziWnlSEQGMfxap6M*zmzB5(_J2f5L{6Nqwrg`XnF^Sv_*TTXgf&0!u4vsoX~ygHA<+ zte4G=WDIJ*UL3vfrY;EV;H;|90Vz2W62+m6w++>pFbr7^l4e5oE@w6e1D^VQ-~XI( zZ)bv`w=46{*8gsPfG6;&muI2(D2GS%p(aMmNhgopZ=baMV1d?hU3XrVts13+F@nM2 z)PDEN_32*2yltF8^wm}fGd`_8E%X+aNaXtVGGnLu4F9*9|A39vxhI}Y6<A=Cyg?J= zCwVJeI9+VIp&-ReA-+3=;(TqN3^swH5G{;^FX^%ufQ5VyBs6nt>zetfwG8H>y&K}F zL_(<wU+l;(=fn&6jG$zl$@iMglt0|wPNq?XAQP&sF-gRgw4Tz`aZt<ys)u=ss)y4F zE3{JV-fZm&JkQ8RhutrgqDvE5rAVS<%J1nP>lV#Zd#^h-KCSk-`*A0OZ)AEc#;kD_ z!ns)%(S|`qdm=m9$XH}pDr38FQ(RLatM(Tim7B8Rk3PFClK&h>_K0+Se2=2Ov?c&! zttNulJ>4;b&3t5|>ugfx$l@Wx2QfpU8(^lN_-%6lY^GVb@bst(UOZ$vzKd5=rm|c% zAw>$PPwkQwx-<QIcibxDcTBnu&EYS2hVR`+t_csba|_T`;mVKoDK+~g1!Kz;=Q~DJ zM*dc0-VrW%zYwa`va~)Hld8?u^fdh_%?=U2-+G5Hn;$7WyK|Y@AZ5v_cNAM#y}G** z6_WJ<iX)~Q6TSkc&5D5SpA&!KP1N(wFG>dAFgS~d7(Qu!ukeieKK)p;#@kTgDjI}> zJ)k}hEcR>`ucjrJKGjNjSI<~B(#z)dtC^pdLC))AgW@c<969z#QtUZ=BLfUUE<Oz~ zX5w+Uoa_&KfJPMJy`}_gZt-6}!3RMQSAj71Hd#aB4-Y~q7(^e4L={y0_@~Cv8^lB4 z6+EM_j{L(h_zDY>!zA_2$@o+A^NvC|z}0(QLm%@me*q07M<;s6&-tgO>q5pK;^?le zx{dBH5rYgQrxtt;0)T&b9ovauQ1cfa1|Di}vGh-okoJcthuyrI{aZ6Y4PruUUv*rT zy`5S7QzGL)3=y=R{nEc2ffz*)A7uIa&|<55H3bEQseazsN+VWId4rFQgV70h=G1*P zbtc#9-?0lr#FGf4{9j<1yw{BXIxP6NpREiKzhmp+=4$J26`2T#aw4ttKS?MbK}?M* z2O;L1KQ<#le`9KhB>N=%A&T^Ig6|prxIWqc@s}wA;=Ks`AH6}T>u&h!^Z&7{Fa@lV zp+q3vBgG$AhueT$?d0?5aq-t;prHj|!j&B-{_Vc%ji~a!btWu2g2l*obGk$h2M2e5 zwBfER7(2efll|>dz`huT>93}7!XH4=A&FFvf5VFeoKiU8M=tmut-#=d(?K3d3#jG$ z<6Cf0L~J?yaTv&LJ@O!<j0!Ii{#QuJ@Phk~-$BY7y|H}EzaGc@QQIG6v^)HNg9S9+ z02Yj|UGVHmZc={&Rv0w)C#1hzqd4KTH&t<ITL0y5ycr3e;RX6{<Vcf@f*S2XOj?Wo z;|WkKVfnrLYdi{6b5Ns3(8H(y74nDp()q{UAa!8bK@rLF&dmM4LLhT&{I|jXkC_7v zQ*&r&Xu8czPG(Z1xUg`jESY}yVCq|QM{q)+tjtW&$3o2-W9Q>VR;?D(h<i6aX=&jz z36rr5?o=#KpHf=d%jYbfS`bMj9~X8)_K)vS)gZ~}fS@CPvxD<Zm6p#|E>k0^%&AaU zd%JkTAc{nxQzBK-Gl;jblNc*F>};zHf@A|zprhNHCqB31IGJ3Z6f^JDzwv|W_tu<$ zoogo7beXG-7}h#{c){=AzX@chF`1djrJ@tI9*`cLHbw8PeoZqBXayviNd<E!(SDK~ zpS#dnDTO$4foJ#<^tK22R!|op$(Vq$<*2y4wrO3NP?_vr4Ha5-R8j{YIXD*Ub+~7c zH@jm6pOj(<1haOV^3gSMq$g$+5<{u8DR6OdFV`A3h7ae;>!M=u|Hjc)tZ*L`R$R_{ zYvXL`r-8|}4xd)}`>ihoGP#_l;i^@-OW$=m?XyQSc-RkEC1`;xUsW=wL!WAAXJ@}| zZ%h7}S^;<DN;DAV>L<(7t%}4#Yl_tJaqV8W4-4%GYGtbN0T$W26Alk5P)iM!I_+bl zp2`RnUxT*(E8au}5=S6AAV9)MVbq!L($5<@y{eOOJB!@8>5q=?TCTH*l_wBd_e-4A z2nt0il$|T<?^P=^m09{`Y<F9wSL^%(o`--UDx4n(k4ZPkWOsF?C?qpyJ-3sjUbzF} zO0m?T`{~sW+YZRYU4^6vB&+SHRcKBDif)eA8KsQ}7^H*gD~&?8BRH+o<|w~lBlP2q z9xhZf&y{JU${xmxozB1bJdSEM*e;QEzTW7hh&k#<;pWsxfcQ*RzbKF-<`<5bG^(<2 z-&MJ9ha%O2m@o_jD@dH5ZK*k}DKNi-b_BQETCcU|EA{C8o-V@d`W^mSjs=6}eLx6n zuJ<tQbb}rr`_p?yoAa7IRVX>Pur85HfQm{2n&y@7oe0Y#Ds+Hb*`9#frvTHjYs0*a z=4IbX>H(Xst^gH1DC8c%c_@;~8IG)wrcM~@P86;r;96M`e^?BX9kAAs%{gKalQ&RW zEK80V$U+e7s~ePdSY-#|%<S4DYxZmU-Mu{eUt*$4;;<j5=K67MRg}RG8$v7d?6;oP z9`n{)D84SX@sXmZK3~c;kS%y2{-I#`Lpm#dorJ^^A2~-Oe;PX7u&Qm<fHhi_wm+M$ zFK>o`1;+NrV8RwB9F_)RBj(`Xm{Zs*ogs;TDwItwC{pYr*(BIS*F}j2o!go`-kx#m zlgvb%z0<G!@dXPCuyj+}xZn6OQ(P@)wnA$LP&fI6kE!Xl3W6%IKa4!v8^oc+$C$41 zHlKFqGDBH)oM0Vh#gQ_Nk6APf(~&w*VELakv|<^zub_<=G(HuZ$ILAtUpKG9LEz8M zxC&3`sJ9yoh6DlD%GVp5a=o|s0uBD=&rJ#?O9+IZP>n+0AZYWal?J=SQUl-gU2SM2 zqGLsSgKu@0Bz=ach^Pj@N<8h%QX=wj26`2iOqAzdk}AR1-=FHDP&5pU2#sp*UG|5W zo<j}!N;n%(x%f@Gz>ZT0Gs0hg><oc#3h%^|=J|kl7#Uo5g9?VO$FnlpIo`Fn8{I)L zX8qr-s75VOB>jqS4=E{SlUOo;{?P8QP1m}CukfKOD>}Ns;YNfgeZ{qqzQ$1GILh>U z)hqhI0E3LTv%!5*UTwPFA6-N!NTP~n{DXCAxBDLDC&Zt7op25uh*T6v;?DxSS?Y@b z_mE5Dgbgq|`681TMHA3y-q*aJF*YcNSDlk87KWVeN)H4=bgL*{WgEhZh%R>N2DpMq zdx<l<V{_K|P#;^b4~&+{k3)x#d9-K(pd8jproMrAICm^I&LFOuR*M*NssMH0R@&`4 zyFP=4A!#)N5f9)(R}5S|ix@iKF3<C!BAWM%zjGhaXDj3F@clm}MCz*&6c*Fbah_PA z_x<G_eEZPpxysV;$+_s#@BysN_36q2L7kp}L7ixlt>tn>x(u>ZZ|SF^L9E;oC#d<r z`>SWTlOnMVDI}zK+9+5(9@5$acO>4TARTvapsEuy3(jsr_*ue9@o$1@#9^l}HDN!I zK^|}dW*iwH2}Hj*v|oe@^&NNuyPT>#2Y#{^{JllLM}DL9jd2Q<1cgo*o)41@zz0Gb zF{|23LAm4bOQ)^Dhy{9s2w9`Gx4qYf&5v=%$N`WpP*`P^-ws<A9ACOEa_!9Vmwj*+ z&hTV=EBJQ2JQ6R(;23s<m-yM<t4SDp(*zBSQ=P2nmaW1v{C3}zz?N|`2)`IxFt|lv z2v%u*Y;(G48>H2#UI0ppW#yUkEjK*<U0T!NylHnnkGSAS+{TS6RaXzeo6x`6TpO_@ zts8bO`T;f6n<_~G=*CeTms)M013?O6@cEG6w-xU><v|87pqf95NDzxh)+<4jiw(p` zzRxE_KiK3%Fl+w~TRtWiR1!?XP}0@YeD0YKIz5LTP5ExpWh<qNAQqMa`-de<(gq2y zXJ~YHUPVGn2!TK<q{9ndUu-xS5C}7@{RNA$z+`{i9P^C4&kL?H<kE2I`EI<jOH}7~ zm{t(dXK&Y|`D^Mt6Jk*(X)37%0fwY5(P+jaC$W<XL$mktFb`7(7)N%vVd*o)nJOro zsG0}FM&h&G)?YCYy5`M7@N^BV$%OtPy1d=$NS@wkqMJss{G^Xvxp_ShIRrM+zK!gA zKqU6lhnph{H;3u0f?o!Hc9{>4=MJ#7ao7R7L@^iLt+UN?*zAwUk1StM^|>`^0@Oex zQNLZ!oq%Tcr_q3Mm^KeCYNSFurD0NCh!LJ>9x0n^OHP$;Go*+M>A2#*(Gr|091qK& z8>kaQs^(H-%Y?SBc5q$MR0q2$k-=i0MN$lFE|H-HcM%VwDYS~!-+)`>SgBtO6D2wN zhoEbgWW`|X_Oh%i3O-09L!z-!A65*rt646)owZ%33|&PAcd=1V#j@A?msSeK9s$=s zwC4U<GYCUKQ7f53Aef=G98`!@`#g?uQ<bi^64t?<Abe{q8x+x_r5FMo+$GP%8^!?1 z`Ss>Obh1g5U?lzG?Xi!du+_QMZNd1L2$VoaeOTP2Lg7w8A=05+v&`k7#L+@$XK821 z&3V-3vJn)fW(gn`q8PPYzn70ld5(z7Z4}3^8Nq?C>Mxqu$rX-=V^HNKW_2#`xXmRL zlqFl#3USMP?&rHx8WLb-owDUE;H*-&^u>sD%xB*Dm<NrOuup2*U!FP=+6hvO<rCV_ zuk)hk{Ob7bithIx8>)-o&IVs=F_+dfwoIvkN~MH#=qCVWCU7$N>qby&o0$lOj-N$g zPOThMLk-wfj|*!=;;||ES~kwrCl0Oy{f-?@SuyG#;^jXpEMEu-Dxf3npq=Omoekh@ zy$1^6*gC~wN6e@wuhKULx(amE=C2hom?#QBek0oXuGK7dtU81<?R?Q1Q83Iyy3AIp z>JAk;aXRG|$K=;=>nFd#1VtXyJgh~iXD-=;)IHoR&PuZjwfcXPoDr2$0mKm`z#|lq zH5HOII53N=k#5$tCove;bI^dUl2in=xjqd}lxg<Rg4+h&&#7V9ZG&-$$y#6km3A1v z>oK@RbN(lzPFW7gsQveRq(|OT;XXvEw4)_9d~f1&^}JJTexsY`fP;5DT7!O~a4-(i z(;#nkhnyR;xX?GWx&l#s`@Ym49WY2|ZQ${Hl^k*Ut@Cf+*R9<Dh2g0B5E67icu!hX zbW}!KJZ=7Pjr}`*b*K~Ue56gja0Xbx;PW0M9A<ISvijnX(uu78kT@f#%CnGjdhu*} zR2SZq$G_<GQi`Mql+;06%9rl<{C{CR2#+a(@Ys_)2>tyFpM<kO=qmDx7>qgh4*&yA zWe`}JND}x92K#tG(C5P|`1$4E9{&G^{vWoHCu|a}jyfK<y=?=LfTwB-v(BDX_nak} zV-Fm)bo;~gSX_hM8l6sqZA8(g6T?4K2?OLO<1MZqHzXivL__R-m)9KbYO^4_A?RcL z7#MRkwc)g%?Yyg|kzVfoM$ZL3Z6G*aotF9!klv&Q;cnj|Z~-bxN|_Dc=K|BA1n2Xg zBKOvZv;NN)Ky=ywwIX?39?)6}d|M`wYN-1iOeBE?M+|MX5)t5Br1@tL!kE!}O^?EX zn>TIZKwCfbJ)Oazyh{7(vkB#rvH@BudEOkLZL&)m+{UA8ij52E<Xn1acxJn0*seC! z3^EJi4J2vMfZCw!|4$pqp#21ODx)>$84ywa?I8A{pbH(&BK*ANs5%w@^<J@;OB+)C zO$Q-M_=+}k6R)>L{@~j)GW3Z+dykXrh27u!?ee+rH8(LeW1lx(hnmTy@EWGbfcZ}H z9?v4540n@pR^HO3usQ@QC2%;I9)ure<4#r@M{)$bM(04=NO#rn_srBefc%1@qG1qS znra}1@ahbq-hcaOwv-&xb#JyG3IFLi)Y_qu{0wHG8#O~#Q4z%1?C5-a@nWa49sSZJ z`g(mhmq;!ZleP`PJN84?*f^iVVO{s1M?}ilyCbJB@yPlXFATJ`wHtbU{YG(qtrmW< zN(9jl9&_U3<LzGWm$c$oclW(FKR|bKKKU}ng6P`P7l;GbH7IW*rh$i0rUjn1Jlf+r zoi+!)T20)a@_9U64D816oyL9gy7?^x*nc?>;(uLrskNLUvzlwEU-dkyoEEVt-^9TQ z9&)d<7-_#<B?ko#tl<}!VN4BO(&vc}Vt7{f{?mnWkGBp>ZCd(wXMVduD1zq>F4)jW zc&4JhAX}Lxl-Ho_KU^;um{kx3z2b4%(xlqFMrU%wgQ)(GC}D=0oxbgUJ}+$^&bNB* z_X}UJnVI}r_wasI)*WYX+0nhNu^;2w-uTNyuL3t|40<iI8$<}VtDuK^@C24^SHAk7 z;PPvtrtn)FD3z*LW-PtzWjYK8-EKIfeAy!BhA1~FR&Z|EQ?0k063w`)BCNm~&1F_R zc;2YDNyX(A=kSH8w^>Ljf4$)rkpai4a;jGRe74c3xDFaVSb!dgG1dILcBG*GMg0u~ z7!p2LYj)_a1GbU0es9MX5uZtsw@)nSyJz$C!>_BAtEWGnUw&c6tI6G9^_WmgJGzSw zlv;5+8FfJF+}s_8NMw1#u>0A59k>c56t`{XeTdWO4=W0D8?W1kuDU=&kwLlkM}yY{ zH(shmaulH~yOp?XN0_(lD-Iq|@?P_{6vy8ZXbhLNYBqwDQ!zl~qe|qr1=qP)^Jx1B z;x~^7XInulA|nRw2ZRwNP|^9;)`4IYS!1cC%gGB2(fLG`b7Sksl^SZ><2c{tXx&7{ zm>YpTek;Gto_w<|u`@7Hfp>^tMi)wwCMXpgg&$VV2Ia6m%dZ>CO-=Cin4L#XBE<#= zCD>e9%MAiy>jrDrd+G-^O#1*1JLKj4gO_GGC6RW6Ep4vvi$_c<n{ywmR+D3%)k2|- zhR2rBE9?4%AxzKA{o(721!P6*>#@stykB`!5DAL;8`A8I-{7(vzDf(c*3ew>ygg-9 z{B>4RF;6`*6bM(*cImx4r%@PN%`tH7(3vdvTOWpfR`zk4djxC!yRXk<MpnC_UGqOH z%=~O&c?5<oBuc~8lXJ<nZ~Cl@jfZGrIIP@mLlW3SSv)TCGeo?PXJd^U;}^iWa*Yv_ zSbnl<>r>28!mwLI(9OLE90d#C`FDfM!o^SAN)M@dgrAt2_ByRmypjOWf6y_b2C^Wa zvY%Dh&8Me~XjH_3_Bf<L4{scs*HnN2Jf+DTc|rkEe3@GL!|j<0c=l;<@N2$nRtl4r zaqw>o?Vj$)0-wXRjLY5BTK6-3E6@WlpAT1;HU^OVUR%*h7L`DcqTG8veC~9|$Qh&c zj76UlgGbR0f<_v3x-ErqdiZYTftUCiECHO9@9obm1s%C#L02Ef(ut!<hH79z{4e(2 zGAzor?Ha!5h5;m`kyN@tI#rNTI*0BS7}|lM8<cL9kQ%zXyQEu6q`Tog@$$Z(Ki~iF z-QMllw)utQ%s$7tAF;1}t#wTCmA1B1GkR=<Qpl`7Yo{^CAC^U5wsGH~Mo7H6U%51p z-XXbev|Ms~?9b9bwP-**h&JV7^i10U2vk%s{+MW#3PjY336NA_E}k4jS`UwiDwonH zyIz5#No{|e6B!%t^R%ItBC$<US(DfxNAr5zKO8-PP-$HUXSU6L8uX2=Ipoa4Ws9tI z6m@9+_grx*MgfhjYa+4L?VAn=y6Y;(F;j*&!O$JQ@ulO#u^8oa3ZKn7wZIbd^iIbj znM|v`XLG@|#H&k;8}^1<=LTJk@Bci_-=GF(BNLb4P&GUM{sz%%(&I57Jft?9!J5S= znottgH<<MLN13iMmXPV~;Z{Yu`;y0TOqjY2vlCQ=-$vX<_VV2~`Q%9zA+3X^hvwEb zL}|zwho-?(5O=p|%SH3e;C;HVdkQyMKL0_2uEcA{+8{kV%9o~ds{+%nnphq|vuL&5 zx-0j(r}5igL&OX;l=TfMg|UsMZFmR6RI2zmTa-nsG-5naG<+e?n4G(dv>A)SPg;>~ zK5Z?_Iy;wpmp<gu6d6r#w={4xU$(QJ1U#OgjAJF<qO*#0-fx^pARKpGkIF_74`Q;y z5NI{Pz<f>=;6>}<LuW;2o7uir2}VN}(h0_+J{OR7l7%r9XSX2S-K0*E7<#_BzDg)V zpk+Y!-z~DLFz252c#W*!+;f>|=}QFrR0XDDx@Ze>v*Sxdmtsw7_1xG<R9uR?S*h_M z>2e1q@>*M!^bbh<TpOyv*Xy&LR3o}d7%09ftrOe%q`MFtknONA0Mvi89e2z2#@DlC z26tCmnTqTSLp2M=bKZFdBjG-Q0(WSETD?|pX>nOT4dL(}{I)r()^1QQJ&2DMuP(el zcy;P-cXF)<C1TG2J%9%G4_xvwwQhRQrP@VLqlpg=+QcQ;A5WPQ*q{&$=-Jmzt)}CC z7T+`^G+bUG`k9ZxoFaUA-}B3ZOpmU}&K={YN5)N7LVJf-pzVfpQ-`DCvx$T#rHMF( zGk1rWKDT497`+4OjY>D<z>~$g0xN01ko;B;RHLJ8I(YNY4Y+LhdwN;mE8m{x)=9g` zCD|E%S_YcgyWN|fdi%9^ZdZ=GT7D;KorArqU)EL6tlL+LujUOOev41(*Ge_%Bpv?K zpuJ-qNiDvl7UCxvKU3V6dK^a_5qQ}@>`eCFtw+vtIr;Y)&;UCn77AVbfNIW(PiReS zBnfGs4}MxT#pCu_2{F0k=j@!;ox7=Y`-9KDhsQgYP0K$gwE<+~cVMH0G1BD#VnnPA zMhILlKt-xKs;c6{`7(g3?|r|b7ByF?vYDS+&safF(SC4|#g-yx`+<cbO@$$)-G-e_ zN1xb|k5{Uga%js2APK8vAt8-(iZ75E^FfE0MLiF94jz5@s2+O)1bZg{EvdNOr%<&b z_s5Ti7<e?sKb$Z_@zHVYDQ5y6_utrxA$g5SXH?JB__STB8m~MLKhmn<80{_Dctxdk zo6Zw;37F^Wlv0?lW|XeBf{Eq9L@=h|lOjx}!S+C(yR+$I&E*?hC%?SkFR_Jm@~ooB zosa(WJAW#HC1YrxKtA7(H09E@`Y*}=2%R_;Cvyv^pQiF~RKlN~6$qba5|9oQsOSeR z_!ey9KGw|IC<#gdes4OG$4nn-SkKY35q`_IJ2MXywzlt%8z~Kw6Rf(F-|)#`mtjjw zUHb8A<|iwgHuSWgAW7a;ZY{}Hv^ob8mf*j+Ya6uN3PQ)~C#-WsckKXC!KOU`XwiQh zo4*HSzy_)LH`E<uAXL%fifz<%SB=q|px|5_qbw*8tggTiPMsRzu-9+HS$o~xfK}+& zVxn3)Ido&QY6T(!VehA1-hyKa{pgY+<qSt-=?3(Fd1=o|ZEy+!Dc$OE<f>TKFP6Ar zRcfppQh-r<c0q0*Lw<jR=fZk?Y2UKPUy+s=4QQd0y>Mt36b8s43gim~@%Sn?gF3ue zte-k0_BfMvB+E@|ma~yH1R?G3%|zqSk)9<wMR`uBXkxjA2kZha4}9B?UI5?j=U?<= zJWW9Og9v41A^(&I)83jIHrlosO_527De$^ucqp?}f%B`thy(l5=-b#h3dY1K(;Z{4 zIzp55lgOd!au!!?>Sd-lIR)Wim?7Z{TC6}6c}az?9YvOsQ41A1)kf7yViJ+h0nCj# z1rvB4QjoDJx&Rtci(b%#vadMj1ddO8ycG(RjoRoY!W<gtX?5Auny`&M*w*ZrPT6pW z%K&e0Bg}XKDFUOHwIhXiVRz8SOq}5*E;K^hC|duVXhVz<ofzOTU%f&xpV=H(>KCG= zX$OE5vC_hp03>=Ijo^2l_t|F}?Zr77#r#*#QA%5-o+A#LpE73o75ca1Xg;gK6w)w| z-o~I``VthA4ka2uEX<pd_LOeY<ouB=W%R~fgQ=R%8}k64RTw&{YY`;%qdq8(D$~XT z&xWL+74AB;TYc-@(D#$&R1EL<^Pq%bNh>CQ?rj=}UQZT%_l`~#RnRi{!S~Lz*kQ9+ z6s@s5|6*!#E6`OMwz?APXL6_|3E)SPUCmA_;$-7px=;ROnWG3Ogayhck3uY>G-W=V zW@Vm0OFvn!NPfcU9vH_0j}iCJNn$=b4BHg+x!%q*M<tedl6$q*h9GTNe5%g+{Q2`u zegBCwijwSmJQ-w6^&Byx1dbp6x%mVKbG+$F4=Eb0O9k(z#@s52^>@Eza1Cn6+(#61 zQx5=(%=4Wl3DwbTF<LVr36MxBo}MuI4`6+~3P1y$D;G1MI?y8{iYTJtQSr`;kM@Dk zdD>&Le9sK;pE0BEko9|Jxsm<Op1tKe4cEK?PtkO5k{QsQ#58xK1kDEK&ziCcn3UUL z-H^AaKAEdxkOYNw%<N%nHKuF}DasrawhyELU^ZKeh@Ic1oa^oCOO`3V+XhKX(V7h1 z3oZ6P^%pMzFf@Tr1Mse?BF@bvR#yD>s~rm#qZ}R=@keTF_%Ip4oN6$ppU?dFnVI0= z1jX^L4k{`f3hF@vjqG!Wq2%_X%m{Ler2^6-eYjl`U)?(k+3xbz_6S8al$vvKwl1hY zpej8VdQq*iJF#h)9SO|t1nQ+(bm@Kar7yv=85;wM0(_-#97NL31F;Gy0ZFYwhjWzZ z0wIDmo>!biJ_^Jf{2P=jN3cA!XP7zXAA{IbW6n8r_S=XByBg?wE(vPJ{Or47Zn9>~ zNnW4B-r9gtA<InWqi&PsIG<l=RyPdRXo5Eq^X8x5Cq2zG(3xgb&R_)&TEz{a1Aq2~ ziN^_RH;u+l^=ql%B6~lJNUIm0Ox!8w;fy(Z?u*1vkYbj*A$w%|x5Fr89`pwO>w4l4 z5y<cgt<9HboJ;{EgU!*L2`I!eBR$u{ujsFX%aN{gY*N2$5NSO$ZZn=d+XVMK`vHp~ z#OA>`n6TcPnkOm}t@bI-HW(}lK=;zHi49D_Hi~|Q@UBs*59eyr?QL~*`+d+y&#guG ziglbhrxiT3CoWa4ZH<6J{kUV|+@S@(-gUXb1L}$5cR18sWq0`pzbbpXQVY_8*hRW; z>gT`IQv9)oFcvV5P(q7+8Zpe-sdn!^NeAV`Jofhl%n+<l9nkuPX)4EFFVAk0wFl*g zL<V02#rJ}KE;apGM&SWo<r1k#%+X6qNU7}`Gzw&8Vgn>zsgW@i8>G4njx;1ZF-Vi| z)dtCfkg+6qRj2uQQmB0Ze#9<o1C;WdrRHU&4rTNBDFGp!7f*c5@H=AxG%p<X{l0e$ z@%>?-V0(mQ2umt+w3w>QId1Wnz&Q)ZNERQ=`N-ha`dS;(X4p4`6y3Aw!cu+%ZWv{; zqy(M!P3|U-B&;DJk*ltUXp`G_9wMsZ;Dd02@tX}s%PXMyK$(5oscLpv=BbANu2Z4? zsNAu1BRFq9_=b#r9ZLHU^#}j#A$+X(JP>SU6%3*zbwxxDV_G8^U~wwj!ZoNI|4@y; z`3;q97mAy9;TD1H1yF7UOurD8hTvCF#gZU7RRLZVYo2aIQk924C0A^_?s{d1UJT&T zO5UPLhRIx{nP+Fy%eeZi3P}0Zl7O^lpNiO>of>?a@(M|IsHGOtHt6~E-Y<3zZ?m=; zTng&n6FTYVsktlv!_4U9hSm~km3dDHy8X9n`s<OHv3L>u<-e?o5J`X|!3CKRH2vQ< z{r@`zvKLIWw32c0@k1fp+}!H`D?^pHepLF++qa(x803>s3knM2GBT*@xi0<#^HPAA zd7<inlZMbLj8N)Xm$b*l{$ly7hxryizh1W`N)SU&ICMm)BPe-bw#=u&`+nAf%gL&E zzB1MgP^Xs-->sr)pAT?waoOX>{RN7j$pTGjjgblEM9;I|D0;7$oj&Cn#4P(h=o1g7 zG6BUireJpi!FN1|1}&{<btsAxN-WBk*04ZBvYyxfvMsD0QLJ5Ax&>ZC*{R=#epRXE z-tWO?lJ9;2+%`-~A?3gC+j#6P73-Br0n7zP{#vwHHGnuGl>LsOK&`Hv*LFq)J`|Rx z&Z5~5=>Cyqt>%#zpPG<ww}q9Fcdz~hu_e$EWuL);di@!&sN-_c$M(M{_dMNwPQ;>d zT9f?JEX;Pcakj;tgc;5nnsbwjR`_e?Wbko~mOvbPL-PWKSOs|JTi~piaAa*n8G1n2 z6FtH$9f^qbA#4iZ(<O+H094dR28j=Hjs_TE5}-NsK1D*kEMQ9#2RvV{EFNAG)4=;b zJ*UIrEz)`;9YM5mHco(+6k7{8HE1`u6;lX#&-h`tJLXkdn@yEHY-Rc$AGnarRodB@ zi&9OQ#MVZZV;I-~HYiW&s!eQxZTks@X0{Z{Y`IxDO{KO$Vk(~v<K%bs`1Lr3jaDeq zanEr2X5*_U3XEUeHMH$O4X9A{ds0!5Xu8>NS<IzaaO(gtf*8$n|5l>J+o}Z$E6z9R zIJ?WHNU-U3tMLsk|JfC;u*Rr3SoXP44gamo<yy43>0-U>JN=$G{Wve2rszj3a37~% z1>9IGzH_>ig-7<cr$FI=oTCFqa64%B`KFZqGU&$BCut-_Xo7V<n(>A6O8~0w@^MYt zb-RhwdAICyQ)~+`_-xyee1CXsVOR^aiCrH`3+3nZR5@?-_Z_;7oH;zgD%$Pwhwya2 z)xhov)FZylrVDxo2H9Z>-d^;m%1YiVfZ?;9Wg@LxDmml*%}7}j3@E~Aa_ciazyJ8I zJ}{r|=d+i>cieHYY*CP{o@=YUJ@zH|2e#8L;KE@FSW5Jj7HVAGlw*M+d~VKojK}P; z&i2w}A>V^M$@%OlDusqa<8YIDCH~_Nv=%Dy1FMLbO;^50DINO+pyBkxoYrn{mBlum z(1CYRKYf@fSjv_;vsN$GnS?~_Hf!^k_X3Y#$ohe2_z(*x1QU{?XXA0)ckg0+6SgrB zY3VdCaeAgYhA>~mzz{=+T7fuF^b1YI7NiRRw4A9*B1bZQ$IUfU>Og5v_0@<@4xJIH zl}5>}-~uiCJ*01?sbcjVB!^KcY2~8+v)agPNGu(SPpgWH?M=0v986u^ffz=Py+(0y z)YDC9!T$>_DsZMUP{wJOU-Uf2b0>xl%^^XQBgzRyqhfRDn@x><E=$CtVAxrrM^^)d z^^$>sp>Ijl%XEP$Gl~E9FEtOk76^<2t4PRdmw(&))BSk|awmjrF12uHoe?6L(S<q} zMF`05=x{%KDZ`UYDL@hwq3MK*KPDrszxX2+DZs*JPSY^i>;}5PfsSVbvZwYvgzEDx zFV?%0Kt{kxt0Bp;oWLoc`{Ac-_^mP8^hAxH-vlvryx7A+2qmip6P$*dme~khb~uTD zh+__33^1ddJxdLIX^}aI+kL05w}r;cBLS~vYr%;r5`}kTd=ee-b5AY=Bf#9_oOAm} zU4?{WyW`ShOIoJL?&BzHquP|h7G@FjaI+u_20a3VXnTMbaaAkiJ-Wqzb6XiX#{f*L zX?Yk!>$^!!_cagCQ{*zW#?q*f=`i10$fLX^QeT49QLs@=3~xw;2n?bGhzoBmn-r)U zADZzE1aX%rAYOW<*wtUYUn^yjVD1Pus};PH6O2?pGCOJ1gKl7QP?*@Q=d1e1P})`p zaoB0Ge`<YEu=SMBvr@cBXd|4%)FtNW=U$A8cKmEr7~A3kSIF~qC6D6jFfnw_8M!lV z#rOCq6{~728F0#*rXbGzAsc`bL8={1-u-h(=;XY^_3!2_Xn-!$)aq}6k^!<gq^I@U z9)uz(<_N$>Beo|3#4eq%8^!j7KX3+jc=6n%It+40)hrP~%!=H<)df|(bl<a{8`PAX zQVpcQ?mK*K8ccgDXn6>(XtdkWxN66DFKImv<97MzOJf^!_!N7o_>snyAdOK(#%I(2 zk!OV0E+#2@_EQ_S6nai~^9ab8SD=*gMWOM59ueRxL5XhwqfHClf$mLoo&p{DURE!0 zsi9{dM74VPQVR|ELX7_VI1U~khtc^{DIfTkmpl6bTqc9ZzfML3q!1CY@O%e{vCR3@ z(@rPSSV+weW-o5)q^ub*ldai_Z9igipkvWD`xV_~6fUtsS~*Yl2#1vYB~>b|7w1?z zOxA*a0^M+sa{wCdX3)A62CG1#70}Z;-Ye4HoB>mVe3KZ^Z>)c-T@58J9N2}Yy?~7M z|E{799*9D#xUtP3H^<RAC+GFEs}Eub0H`p5AZvF+<|!()>>#~bKAm*G=uN}1zZAh0 z2tDWwu`t~;Q|V}f%5IVyIcY5T_B$4PeeVJudJ*8?puo)=`Z9?Y{{|rG46$ow)n!Y- zD8$Kxr(m~o*37s*ITXm|HLm;PU9e|k2rx96HlaB~+2!y;CyJ;VVhrd;(2B24{f~n; z6<Z%#yw3L7AZ7g6wDRk@+5qJThQBjayo0AY=W{+!q-8f>#RFjBc+Utt^xGa8A-d?Q zpGx3Hau<+KkW0y)-qCD@z(2K%1Y!>oG@n?@ZIi+|7d)WOI`}>sf44oHgCEZ>B)jbQ zB<5L+oS;J%V{u1g1!&Rqe1uWy(~G&OVb4?%tGG8}uOgYq8Ks#WB0XbbzMyolO3)WH z0I>$%GKR2{#%*(*aD6(PhPmo?8|4Nm(Hesf{awdKnIPKI`9vAw>t?jr7%nIYUIy!- zw1%unK**z1b=HS6{3@$k>8>Gj`fbNs{^`N<e}|Yx16`)7wS7?NlNFp_yDNgtopXJ+ zLh-XZI%)`QNIH1x@N4`atHAF3*NT}1&P3f!gr68f+UU=9qKTs<9}cZ0>1iG?q>v2Q zNS(_Y1Lf&x;VKlB(GH9Z=8J9NB>gJyvH|Lpxqx#)%=^Gu&qrxh9WsnTb$ue}S4>4< ziUGittLw@BSimN0MD~&zz_;=Wp6dSPvFu4h5Ts!cJ96K@EDi}){16>z;LlHojI;h( z=&DA<Syhj4I0!S~AOBw%8<RrP@g1@6Q36Pv6+jXpS=CRl-^}zv+pkn^$3;oH$J7eT zI%vvOTrh(cI2;H(=#h!PPvDV@Eu;}5K35w~PW==$8*pIx>xpZj=f(CKhbC02m|5<( z4v?f6s1{doSE@^h8B$N)pOGC`#+0JCSm1lk*X<;kew4rCd`lp4nfM<rM-LV>pFj(w zkWUuXSU9Isfw990E8}#*#q+Q^=X+_1gb#(;5B_q&p-RfgOE>42bbLE1cJ5)#-bNVo z4ph?izIyQ}gw}hrxg5=owo>eDsM;ku5(czROK2nuV97ebQN<4D8OAqaThYSF6q);C zhwgQ7Q}+uU&=b@s(gvFnwEi<NtpnzgFnNxwK?;k=Sa51ypes=0yFKgYtz{iU4T7_^ zmvW*D=q3)>uKek_0jJ?kLFhAlt=_=$)#n4HX<`wvg8Pip(jwWE@+`HbpUQgDa*a6F z&stYz+iWF%eD^28#B;bHVlz1SyoYo!8t@vv8HBdSA7R4VPkrg!2AEpNKEXfJ`HD>3 zXbzH}`hrFUQtkcXAJY~gN>2865?B`M;CP$OC8%c=oF)V}ob!iI6s39^5R2;&vF2mG z+7IY~DFe0f*<rt=N)m}a%%A}~|K^A!Sn~3jkYD1k%G;^gaP%9UXp;Q{h=%hBtVj9J z>J42BdSp8(;I%V+YFk5AMaD-udNOzz6CC{F$IaO;7ka3XT>1_|#SQ1cAw@B|!yZW^ z`3Q#W+@Af0n{5Cyx&~C_9bhFOvqV5JX?NyndqM^y6w%yQ$c)uR#nWP50yr$QsHZys zVO0Kb$s_QSC<kUrPO}yk+cjndfIVyc*q4g^p%QfS5(7oA${Y1REU+jh#6U)POwYRK zr+>zLRyub4FUD69@Ji+E4YU2lR+^x%fJ-14D8Qii5GLw&9SE9%8^78~Dk!CsG=?*J ztq~OpZBG`YhN&}`hO@w>LOIu6B;jofFSYF3MwX9!J81fLEhi-79}2f4Ug_dc89y;n zTj!!Z5}S#ThbeGbwKlthwt@r!4s4f_YAV*olSkBIg-_a8+<D2i7DOwW=1_(ShRap? zyhV0onV_@9H~>?!VL_dAr7a1kgSknUVv6lL9RBW)A!d(1<{3&Kk=1wKuW8M%N%_j8 zh^Qie2!`btqLaQyRyWL|*d-EN;(`((Ydpu9&t@bg4Lrv6jIP=N$^Ys}U2wPvz7Ar- zeny;wyA{a%A7W$ck^IUffmY9s{!iEcve!DF01TU?dVLDk{}OXpK>#r)u%VOde`q-W z`=<XJ#tB%QU5Bcs<$>zx7MqZO;C28Fk0R!5XL?|+3NS&ty()KD7JCqD7|oJIs$1<Q z2bw!>H?2WKEf4I48YQ1LSTuU)_-ugsg(1ra{&}aQMGUOhHdi};zPHGNCw>}3A>`b- zs7F6A{cv}1U)FLwu5f%ZBEBUU1-Ksevehh_&rwd=)UKV+GqABKzI5MyMxqBXiUI_c zaHkGbkDo_9L-y`^SR|}5HA~(+Ka6JWTh_-FzWD^>=Hl${oQ#N)j4p|eC~!2=3?#5& z&5RKJ&3AMXXg-ma1HgCu0N8B$r5iYzx<9%&-d`LK94AzZd!FVmvI0DrL@tw_>*+Gk zcf8#IOUOy2z$33{SOdH1Zogq1Xv|T>v2+N%!lq^q_r2xP+@qWQm42~w5`Aa4;rifn zu>q-%R~FM|^gT~*(U0C=Gz07#xqmLWY&_iGIXs*<vhU7Tyqc@Av%z)g`5YTdyM_HU zj^$`8qXIy`%+t=PMv{46vDdF4)`Zq>c}O3eN#lut;F&D{R_gR1c0?`?_%4#`(n6i{ zQ5T6qcbQ3$q5(<*O1=H!%es>&;RuUCdzY5y@OC;lprU4=R7dX6TMan7I@#>|rTPV) zWaD*lcY%Z~grZS0Rz~}0GD;w$cfwl93N!L8GCceBd<))v`)XdSGcGADnP}(~sFttN z7QNwgmfv{Y@{sIW+Dhg&EQFBV`R<#7LIvQN2^hGJ*BFXRz8)iMWKOiI-ENqz*kgRC zVSxkn8qJ9KL!+NzJ__ua{((-uTkO(4X0pF0{Dpc6E6|_CdAUx)cdJ#b!&h-|Hf<0O z@UYCRYJ6_o2y?n{-Sw(hmrI&;a+Q*eH7oA+CkqoBudjCy?3m$*j*fwUP@1e53?O!? z%LBk}YuG;*pfWJBs(q6us&D{WV&fIB@G5qRw9?gLXjzE{<r7$+3oLsU9(~k~p2<~A zH62a1=wIy!M#6Oh5axcQi)CuKcnUxidJhP=7hQ*MH_0XUiFYM8PRwzI)c0#`TYAfc zr2{#nYG$>|jJwuP`r^NZ#+L@4Khc_1T@(9v<9baPVg*GJ>;SBAUr~Dvj$lYxmog@7 z$%1DCI2wOFtDEjq@E6#9NNXO8LS*5Qu}ns}!3}PeYQYn|%xYXcdh0PFaNT&azWR#l z$Ue8VUkdhDXakt-4PvoE*jL)%ZW){VxA_<wfYnWCXehVQPZ_JFoWSk<q)ivs{TZ&- z6Im#cHnht0$k=KzH*ys(d*SAE0_k%8CgNb6Y%^WVCAT#mL$}Pkj@M>sfpsFljPvkM zXa99p2zqB@YkSA#muT_xwGQmcjq9wT=vFDFq&jqb6zSSS@3R;h=n@%<hAGOFVM*gV zstLV%peOir{Se$1Pc(S%+kxZUA%1V<Mmai8S+nFE-Uv8>nWrPNkaF4oi!Cs-J|?jJ zB$=Y7f$QhhK=1Uayfouuw__G~7(k>FzdH`6sX;@;64L0^ESG!y9ekeaudT8fNcQV4 z3?4)&M_XFJZh1DZb29l&f{u)hgc$`{^=ehb4nJ>ZwK`il{cB^L1;^;DY<&rE`#i3b zEh0z}YcqYX-^gK;o0D#8f>&2c^ZtN(PoaErc@Gae`wfbjmyRgJahpwDtamuB2sca- z)Ccx2#?2hKuLLU0Hv}`vH~QZ+xb5BU*;2AT1kqrj^tJi7>Qq|BdKd7Zlk?hIdOiTv zQr&f_AC4g5aY>9H$~=Hvo$f8_Dp^g2A+mfV(ERtT9u@}hCyJ;6HI9l0xds5$ynmP7 zFib4drYyX}Au75EJ0afbc&Y({@@<E63>NX8-W6<`-c1ysA7HY&<k*U7So1jz%0v*K zU>4m*6mlX@c^3~yk3Z#TIS%s+*@~pv!<*y>+@T$#SIl6G&L>0M`|-+O0ZQ2uEnj23 zf1wR#c|<N+_&>dv&pB9aUoF0Xg&269sXy%dqqC~9J7kCM|MD8&${fJC4tr|jfv?4K zN+e=|Lt%->cI*HQo~v|&^rvD+w6K`Rg7GdDQvtjRGZDL#c<H)tI~+NEP1AyVLB?0A za)TMvdERD`&X5!%0X2*Hn`AVYk4Ywlc>RTpUCOw@=Fx3YJv@<}Xi%l&_`R~&^9R?k z(0W8H4>4wbvVKmi{hiWg%&LY_fPl!Nvje7;LB}J;F5ON(+|KiL@)=MRNOq+8Uai|8 zQ+P3Qf39004>c<|{MSr8EB|qEX#a8N;De|7k2H}Zy{N;e@ux>lU_U2d;V{`3D}ocy zDzzWY5~m04lKLV!rXcA8FKU%Kcu<9U4UcAT%Cy+X-U751^3_0`imLH@2AzgMGL!^{ zwtr7i&>Th(AtH+!gL`WLI;J`BTbOmiNS=0#3jF4@Tc{oL!vyTkN1lB^(TGgp+t{(1 zK%P9;mwpY(mV}`ftAe!&{^~85t%1(NFr~z6>$ITTB1>I37@AhvH`#krCI?loMZ{Wg z7^gqCDQTKoLOhB5>PBDFAP3zTU->J%Rs~e4$78`gI~X{xCQJ0^Z2?p1*tP)FK48B_ z+6U}uSFu<JDbllv=2>>Ia*ZHPZq#f8aI=%mk6zMHqK^T8cNf{$G$km+?Mi^%aa;u| zUIO4su6OvI!e+$Ur+6#FXR72H*jF$O!3bj38KU={gmGzUwl5l5PR{4=y^J4$WsJWS z-V;7(Es!=<rcx<W{pA{R78p~L#yQmqaf?xoD_+;%(_T^eYQ1~^e$V_t07YXAops@( zv(72+^XGl^^*0V76@YXiu!G-b+}q7<(RCVwQET)+Wo{|*PdP9`#85FNidA|L(gDDG zIqCnb0_+H3O5i}i^xq5E3q{#~Tv+-zUEX?}NbPO@r{M$KGG`6^I>~@4I6bR)1^SMF zCC&R&B9@YT=fp7%XNX3L4#S~+b`)_x7flP3u-9=xo@wu_MJi*NM(%1sUM4Q-&E3Uf z;^MayA3mGOIPGQcHM~r@oY8z?_8MG`sDKk*U;%k?xctitztV0qqsM+=zriq5OxyXe z+-Ah*@BR(OkST60M;hFoXGw9k9=ZGb=SN)K3dn$1#=-mlGSGiU0c7EYMP~!f{~npY z0y<zo?Q!$Sg8TCd5eEL3lly>2+kZbP_OY#H)xP^bboYHgT-~+EwuSPy{syR-DZod6 z#i;Q6`!O`o+Q(Y}+-uTE{^ve{{|)H>YlQUZg@m*T2nYs0QwurM?;_hiY;SMJrKFIZ z-_QPgoC1bd82XGz>zhJi0^tkwIQeVpW`!plfUn{HXMMk0+6MQ71W~W^UI3aeH?s_s zs*XG^s{k<4@f@>(tXJlyroGwH!KS5A2Y8e=^78VdZez9hjqLU71kW{!lAd089W)Y7 z8EKU0X`^QPRO36g*v-)!DyEZ7-Ji^ByIoA2djKqs*}&!W`&UMm|5*uX#Q#+<O@GrB zC;+T_s!f92H*OA^;}x&7aLoYjI#ZgXf12nA%lwJ!nnx`(0NQT=Et<I3kbqkz%n2!g z;H~F8YnCg3-qDCz#BDYp4|p!GkG2H>wLmlLm+z`yg0M*iM{T1S0gAWBFx*JHo7@%& z`P7$4SAm!<4q&XJ*|gjJP0|>)M`_s^Id6<ox-c57Kq_)HEN`;q{srLBkMmm{ZYOmX zyS!INq*eV8@Ip{5ol`Q3O4M3FcEeo~Whxn1*B<TOfx~@#-LhZi23a&3bi?3@%ufoU ztJ)U8G3(FF=moxmNJ}w=|MReZ{bdiTQzcM5Jl;Kkft737tke}oq}U5rUF&{VZu-V= zezC!=53tTpU@+CvLfiqk*a9YPSMpYt6;fBn<CWSxLaL(tQ~Y)d%oEM`b0u<r0?9ua zCWN_}=z}9~F4sOTzjMM-)>PvlX`if`tiXiY;jFeRGbw%YA#2Y4TLnwlqd!S$mC|zT z720|oO29B!8};lqj|vnL2M!8`Tu_NVp1SWBfy#z6Tkru@pP3bUwz*T<kax!6zCEX& z!slQ=g|Fjzu~&oAw>V}E7&rCKOWhME_0+ev-*w($n%6c1z083=fULEGGGA{N?#<=l z4BuS%51ys{`1Ox6TuBHB6@go|!wRVDdbw#1f+oDq;yeKs<xsDC3a77ktCK7noaQBa z<E3%SXh5RfRutvZKuF3Na6W*L1mjZMmux_Ywa(4?M7HUL_D(1EzIzJ*I&z)5@s?qf zzvGWCo27zG+|C|=igzAu)c3Qi{6inXgQpvo8D9ZeUmu7YZm3zzEyShOjno2&+Ywi* ze)Ujqz&*Q^tY=hy7sRlX(uxd9$XMbV_2OI`8Vsfe5cLNHisADI1mp4py3}&|4QXWl zQ783c4Mom@l21Wm7nkM=C3<D;gRgnfyu@Nu3=F%>7({c+x!;a+5}Rwbr<UuvWR<5H zg^n^X;;*CuH+FFGthwbMN=w~)km!MjKh4v-!>n1DcYs|}p>V2rsO(V-J0*y*GGF5$ z@aCY+8SaQfir0+@wK(Vlnq8urw_Db}$#=8TD{%sSqQZCyUhByzaEFf8-cs_DB`--) z!`g1^$--1Gl%*S2#8&pZJ-aclvm1w&I(>8P>S>*C*6Ia07xiE76F8y&R9Fcx(+#Sf zkqKu0$d9e#U=D|#tk#s-@6BcHHTAfp|EYFp%8@Z;!F=}PG9dW?qg={k!(#$Do8{~P zjA?+mmllhM)FHhY0kj_m27Ir&L|O}fOTS2JJ2?c53fkOI787)#feY!6xchR?rLq{; zH^yC5^v;amC<P^W%V5;llYk(3{W5>I-h<yW1@T!AU{sD-fF$kDI9X#iJ&dj_Qri?{ zYKQ)hmOaW;L0&pz<f&0cda-VelDSf*{eEb=Y^}5`i42BwivQD227=zE1Vi&B--R>4 zkR06@R$aVW6aMbmRBQPSpde>s`eb)8dr)OFmE=WXi-;`qL3txQ6sZmS*>&DG1+%hY z%SwN;CGa{kDo<rwOCV6bqRbEdT|WY4fYj1>mCiTw76oZn;LgSu5IK9)i$IKlxnUF4 zhJ@^))SKyqk}yw8_3`kZ)}8lrOpI`9j9*Da3FHICt-q(58fZMIQI7-xePK&5QU*2b zhi$poc?TVWQ2<)a5JyLq_x*MrVC|qZfp_e;l3WoKhj3_4<A<~KgeA>CaGOT1I1!^~ zO$$B!>sR`MTq=6VtD+4JaFrFnZcWzapo|Kh9xWz9;h^n|+i5G`Y7^MUxbF~!=EH+t zYVV8oaq!F=<{to~avBVR6V-!aLGhfn<ow1k8beUfGUGmBQevq}8~xzCSD-jHh}iw4 zdBvms=={PcI@q1CsEvS1+&0*;$ARq1SHG$=RFqnzB7a$3L&0KY8DpR4cSYpH`M--G zH0O__g5kscJtx+Ey<EAcL6N^$(E^!VZ%4ayCkvc&z$QrSAJwcULBTk~k)t@a09Mhx zW1``F+4}};^!D({Y$NxFU<yhYXR)Mr8zD+Z9T)#}I244}NWuw&s%#>lI*>F<0QByJ zE1isXvC%TT?0f^CYw(x|M70Og7%eFH7--ZExtdTK$$YA5MIsAA^K=lM3Tkv_fe*G_ zBhZG1qQSvGap#*5u`W#OF|A>x;990fna=kc5q@+&rK@9w3Owp7v&{pVPAS0g3^Pxo z;9b`#wlYEc7$<}@79B6Z0^}!1gKbls5Tq6>ZOP=;`aaal7-vKNQT(Fa)zp2Iq-uj> zWPjSCUo-2ehg9`8$Sm0LRL&v}9Y!WK2LA0iYwP!)L%0YcU{ZUiS&ySIG>LZq0taWK z>rhj~yi{A-65GG)u}+B>e*k8c|2g_ME!B@dlc;?zv-cS19ZFmM(GU~z>%iznvuT|3 zeH`Ks6rcoX;-(&v@FBQ$B4Cu@dy5y2e-Go4-(?%xy{7``8TyxcDm<@UZRwy8oWOP# z#8QkRKql=hU#MX|OJr*vaDa5DlMqX+Rm&95yG_02ghRVVMWzv8l+zJx(vz~`&&`t# zyJQY&^?zMsqy$T${kn=l0rXJ)5>`KPG{+2Gr=IG(C;GPNo%3U8)t^*qpUQV0UOE|{ zs4uBMU&<B_Xzv5Mq?~~M`=3L*ga|(1A%TMT55c&RIJ+J*h|YrxVj!34*Zcqy8LYNn zB%^_Y%rP|rFb&dUuW2gJ&r=;xiP+p)?#?k;8y0VH4%$aNMbTsHf*chyeeWV#=W<Qb zg-n7P=3B7wNTeJ&A<ip4y?qN56nYh+0*wZsbhv}X(6N{3!u_Gdhy%k#qbJ-^*}v%p z+6A%{!cRiP<6?m&&SmhFW*0W=!XPHV_;v~qz%)PUw*FD{9Lf92@3nbmzQH6Il{U(z z%YpQ~4AUD1viW_)?+03H!dUA@5f&NXpAJC5k2EeVnPwS4`0J^nLjSmg)-jO99Ae=~ z7+}+i4Q`eP<zybB)>0LzAY%3CIj#npqf$}*IybVv!93d|(t0h`bCiS;tl6cN`qhAE zUC;w3gMM9lHEAJ50A?B;z$}%4Ct}h2JV3KE=nABvQ|h4)kNqNd1>pX2RR#hT6Bqb6 zh*;8fDom(PE+%Cvc&=Nq4Qd;;n9Y~OfZsKI=XXB5EL-v-Y^^Zzb0E5#eI;)g{|k*A zd|qqhFY9>NsHrp>V;^a_3d<Q0%0RZr<O*yuDmngJJi8bc><2@GUa5nFfg{h$g?SEo zd@_YseJ^h7+lbCd0}0fOr}UWH-O=Z`zW68H3b48iCk#iYV@BC8Q3(5N-@R}?L2|CR z#J#1M?mL9|ZYpEEmOvz!!GRW|vl0)Vj;q}9R~eb$oWvGNG2_ewU=%-2r96Z~>ccwN z2u6u9F}d(!iK!)MDCa%+j&jYwindeBlxLNE1nskzvaAvgk@-`3>rz#eDaO?=KEzsl zOrcw8{Y7T)4M&KyU}`p*6(c43x{zsW!Gsqr!Zi-l^K5tb*L5yv$%ToC#Tm*2anC(M zpKu*M6yUsfd4GHsC5=q>QZEJ3@K2C0AA^(<FYS63AJjTm`IHF}$X#`JQrb#v;XNrZ zS5Qw50dDN)91F|vGz)1xRnfl7JoYTuD7wPf!;456R}msVSt^nPi{1iER_8(xGO356 zbfn&eHn?qfBfj`kF1Lb`i8w%(m?}I!`pkmGrN2A^U!7@M7V*0`AP+8*N^`y+b-jvG zp+EX?>g^>$aQMF0g|(@sWZu;mJ@w$t<2aH%hS)#5&G2bsx03EsL<Av~6k|*+;Tyhz z>4}A{CStgkxXbzOcyrh?B{he7NNk0)GcOkPX9G2FJL^if-ZVa~JJ4qv)|6Rd=pDsT zl#x1E^=(WB-^+fyK=#K-v5i6%%>e(tE^!xR;$_Vw^YEaTxg9(fxJ!aol;avw)g70I z<KJZ0beBeQVBb#Ygfbf2>*T6du~x^vH}!WTpD%bpGLY$M5HQ}-!HJ+<F~3Ugt$AO+ zrHc-Pzpe)LUhF6ngj$)z`1rr}ZZ;s!(Z^)%enTL<BowhF@xxTsusCF`V%MZn5Yi<M z=~-%lI5{Erja1qLmxN#xr9_BsA{gtfTN~lkhdHwLrF-FRfG5iojk?dKX4RmwlPvS= zrV22>9D?JCaz(=QJ#oQV{*W?X=d<5!nMk_g_)9**IxJxNQ@;;a$2l*b&_+Ny1T*O` zCaN{^^|y`)CXNi_KLW8s7eO;Atv`=0!^Kl=j#CUYmStSzW!~7m`k3_$=AXzcP3^7p zO+z2%#s(*~I2#;031vT-O~gcSgFt$}u#2b|%5@pemw#NhBFHF^>y&=SvTZ3Zk5^y~ zVaXR8_-f;6bLTvM8JF?q)V#g7E!*Qck&RWFLhXzA(>x$=R++V0E#p<Y?3V(B`jqzH zqYzIgb+8^Z{ocw&#Bw0A;{lb;wuJ5AGE8VnN;5Eh&T$P!Y_ElIJ&$NTY@9N6Yag_Y z4k$~<bxB{QT<Vy=)I05~C$|&33_#X>@)BkdSsbe4wbdTzC5$?H=$6m++AFG*0eD)k zSK2@`-&=DKqq@VBl|TOs9VIaiM|LKz!e*Enu}VtLZj&jqfp!TVmNyaQFhp8+=*i%7 z!)~~rCa2|R=Ae;2iw#VB=M$HCl@^$6piQc7Lz)p;8XZM!M+$P`jrA6TS!gUfy~V+I zRvaF>WtAb0WV?DpMBbEk%rl(+0{$IhY+IRk$&r%w40O;r#i}+jX|jo4Bs3T#@=C<8 zN&`H(SxoV2pRDJr<B*Go(p=bzU9lhXp^%sDxIewik!5PD`zI;v66r4L9O5<MsKoG* zagf155Oe>55S4;w=N*0yDef&ame%kX_h{wk+0O^GmUz7fue6ibx0$r2Zv`p8#DSs< z7=dAsKy09ct3$g?*zaH9DPw(BspE_k6~n?4^=*!9WFctOokxRqCC$v`+A9aN_BWy6 ztE|VU8%>CzmA+3Z3t7vS@{W9p#bx|YA!7J6z1T#jO9WdgLOlIQyQn&tcEuUGWiSbH z;%ycwZvC0!k~CR{eYb>Jlx;G1Vd(;G9b$`^8}U$FBD}HH7@MaG&i^UQRk_V$@M_K@ zVu)n==e?nfi$1~pc9VLIu=PP8&DXk}?_4!ompX_9F&~ll#i7MmMc&BHkszd9#h!zw zQIg=5Ra)DS+IG58PuycNbud2T&F}8WTgz>xNIC5^kZtODTR+A3MwM!--sv-@aJq0- zD&&1=4PsfFaqy~B7Hg(AMM<ihAi8pAbeWHezPGl7VJL`5DqzQmlg8@q<~8JjjaUzc zYf!8Kc4GCAhSh?IA|jpOEA8kGZ}&B|8uDG17`u7kS1z8Oq$H924zh86{C-0qT4Vd7 zHfy`*u|DwMcX`}}Tex=_C&?o7CJ@}}hE;8lhWEqFmcwp?=16c?IDU%Hvvwb$mb74t zND*coK^lpk2+mc7qq{6J5PoV9Q`qnkg!ZHXreYDE%S3mY=F)luk?@Pe)aCbJR4aa5 zHDg-sF?QdAtD=XDp(GzwjMy3XxTH&ahzGMxE>=Z}UlXr3j4^*k@tH(a>gAPw8<Jf; zJypL&dm565d0;rSr|rH}KVmfOE&AkVWHr9_V(oroU8b@T{{_{>j!3sWbJ{|UpR}bi zSFIQsZCCIblR>HLNhGO>uMjR*&F=<YGYTq}KZ%vc1Q$TG+5d9N2;UUT+xin3u-uH| zA)si8yKKDvGYx@of58A>$M{g^q{oN)xRRbqOF$<_^n~91*-L>xzNF1+{cV~<k^ASL zft<YqsesRTG^5o1Bm%I4DWNmNUnVmLKmYU11Thlg$WOHH20zn%{`VtaXAvS|7AZ0I z8_7Qo(En>;TvGq@&%?vA$K;ED{$2pPmyTAeHaQt2fF72gPxDNkQ055;nFyuKq;$sX zDxP#AH8<(j@2znPqw0IUp``{I{#Hcejv!-ce0&sE<`*w$j!WIQ_WPQHlZAOMl!RSc z&O|PTliy$XUL?CTSDer7R6gZ(T<PyRXgQdxv|39s!<pxE*)gZ&Udo@{h;q-d!UrMz zeKFHQ`3bZbz82_*enb!X`@)ZDebHt$TB0v}F>8_e8LT`Pi2gNPqT0o;xN6$%?&jix zNW1<+!Q<6;Vc&mT@01=q(vWJjYr)V|aX(+xd7F(7_?FvO?~3Q_%Qg~90BfxKLuJt` z)2guSwJA<$3XzuK-Q2X^!;rv8R(JzqqW5WRDvw1}s;F0W>ivw#KHyl;Tcp_+Dj9%U zhs9CfYxkq6A(h`Q<>olCd0p)8bV8mud%fqnTc9O*_5K2j<HLy9jqQ@j>F(@A`cVM& z<ynHxo!@B(wY=lzx2apA>+`*x=DWp%&4spOvw;P`{d?OSXeKp0+}|wb$c8(Y%rBs% z-H_Y?&H9DM>ogY=n-5Vg`j|2=7wu{m-S$&<N=_z9=Nvu^Qh7abO`=Zs$i2zAOMr_T zI6@m%ZcoDJnl&_rr<FdP3<)ebax`7$c-;q*EU<92>?UZ>SMl2bLxE$kQ&bV<^|K&P z59r(8tqN2uuLIT<g{n^|D}pe76t&i0jw>wo#?tZpGKPLmwju=jXW2Kwp=k<sJ{but zRwTDa(e@8WxV;p|sfG{rshmbqn_l0TrgUuBYA(cX1RF7HmVFzfLx^n>4L!b*^I3md z-sLvAuBaI9ZwLo$(i(JoA_s~DJbNe?y&KvF`lZ41b~Uck27W%0!mm#CT!#4el^NBD zISlkh`2&kid&KVw#_Ar}2shWrhoK2eoPPJ=hP7)^;!7lSLx_b*ZaL+UHjev?mc^^B z^u%klDyiXYxRSz1B0N*x*KK>eOZ26W=VlCn*3%~`A?RNXz$mL{zv!ZC36(|0if?aE z@;x`wZwCPJE{dXHzh=uZkvm{D5m-v}Ao6P^V9^6d`KDp7JUms{-G0mr$VM{lE&=BA zZbgJVk;9KSneUaHG82DY98I^}6$4S8mHJLDI`vRy$SOD_6{~{-3AZOT4bKc#051mK z!S6dG2^k!dAL*d#IKQ`r&0io-RZSc0u*36S+79tee;{`#4_#wC5uai!+ppg-&(HK4 z7TV8zxO}zgRmXG)*SB1xheR28ZZo(Ks=oUCLqWy%s^vb?q4t3H1LYeqkphS44in1M ze#8E6(Yha50e52j3y#t?cjxmB@ro*3lo2KKJG(V%m}?6yy}mYSHypatQ>w2hR+nnV zdbNOf&tAZBg??qpO$SGH+lRANJ0hWCJ9_O`CC-1CP~=gRcAw~DN?!*U0&&TjrG#vv zhTq#{5evzFOt=rKp|jQldd3065~&)S>5^s}>i``7!vSJ;y<cvC1I_2NexU%Go-<*0 zH!N0A&799+%hjI4BK|9??Lro)`mjdnesesc&CF=F_8JJl?)U7;#g~fhB)4YHh)K>m zg0$-1{h*nyTOKDjZ^A6H3&wLlXu2@aIEB+k9nll2x3N3`Q@_FIVo8{AKEbu)Wzy{U z$u}}|diZxqQJ<c-Rjr5@M#0qkzIUn1roGXeBO33^7(1E96yJR>i5rAsrLFv&)uT;t zm@h18p0jJ|z-^`{&_dyVoiKUqG+h2h)`I8-ocW1<_XkQ7o($i)NYQnWxc;zT*AnNI zVu@DSvy%p9Ku7MZ%P?Q?97;5|hK%JRxMLxXWw<ClD18r1l9wl<(=u!>z3Q8sEi)&9 zdw^B}FgR%dB!j^nB)3l;G>clT-*{lLXK54(Ar_EmrOv<ZI8p@*Eq+iIIfC8XQQxmX z{QdT-rWY=X=66Rsa9#2M-y7=t$kw`z%~W#Hp#yL`j2vIuVU`IYucB!F01)82PwT`S z4kq(xT8Zdgx7^$v+}&zdnDfmUYI!uBO`YiTNe>Nh_WHM74Wsvx*tU=udY5^P_oocB zS4#(BJ0aQqAQt~UZL2Fsq1d=Z<-WsKbIG2P?zS|0_G_#o-JA=I?bO3ww@&a1QF~XK z+$@v?4pP+~CS|Sv3~mH8BTu`1kw2H!c6S=_ccUZE#q!^M_TZ{R*sGqmw{O6wTgY)= zc3m5imaZXjV)>xSb-mk)g!e(z*3`tZqk)w@ikwK`$d*`8ATP3fuXN!gPGDb;inafU zr9p_=^>nQHb@Xh={1<YOw87f$+T!Nx-@da}hWF)OJH<7(A8w=Bx6<9_`bMscJzi6n z;RldziM4P=xICaOKQw1<8qx~9m75t06dG)N`5~6;I$?QE)O~sHS}QEbBuaGZfaB?U z6shnM;>yLMpI?udrLZxMP&6r+d%t>~dn5l`raT=JUn@esVF(rLki1RM!ow1Ku{2vL zZ3p%myKJXFVQQ%N^`^(k=G7<C3AW4YcQ<!E1t!BalDJKtXU;6Us|2~7>kM`mi|!X+ z-s2-_8aM?$C^AkPNen#PpXQY`RdoR3n0;T5^I3be8-2g!Ilnr6o{@4h$jKGuzTJ|5 zZ}1N&D9npV+074_Ze*Xs??{}RpXe^vE>H@)ePBxWE}sX?X+)<LSvz6DjwNkB;t?cg zv2n4hXJ&tD2hUcYsyUX3-VE~W9}jR`v}D5dxqC$wx2*C5#1xci&Jb<#(=Vr&9UoHw zS1-S3HaZAP;C%7GyXUUWxc0IQIrXLMcj2yuqa{8E5;XgTBj+is<vNwSJ~?ayOK8)P zA{iHd^J>r4`Mg6zEb#>aISCcAmV3jc84ofZmq|;ch@+7x`^%8<eR2m1^WtM6t8seq z-@h=)uM$V1c$KM1I=wZ3dji)EbT4{BRWDwZQ$UZFZC4})A?@kz=5t5)H~TIPT8*mX zAkChXklGph7nN`Ly?$i}FJSagCLYDXTy@6fjHo}~zg?<z!C<wQuhCr*vf|~Gx!`zq z(CfnZV_M4ur^S|pP<0_Iz8moOe+xIZc(~oV&;Dp7xV&@-?x<@Cz*qub*(WXZj#Q+2 z|EkBHH@k^IA>JBuJ=bNDm0_nd-yX=z&>{SC7`LYu(wbus@pHqSbeB}P=4mHk#9fBX zG!gQ9cDf7FX;BysaWEcDNyvfx9FeB}=cjd%F|Ak`m4?7ok^8?)qK+y&;It(UnLZb; z*q3e07A-^kCwKwAazClBa-yn(S7rh}9e7(Q`E(e)n&G>uAx@ot!b0^ysK$g&V48Xt z!FVvktGmKQsRxn8Zp&&|-bykY1K8c1)^LSfYTw{3TC+UBo?sP8JV$42UbZB${;66E zrmzyf1Rtbmn&xi!S~tvD+q2A*DEGGAgGu-@TK)ML;D`SB5B|DO=`^SH8Hpjz?Q~su z;#wk|=^i4<%SHwy8UCEG85g%U`cl;z`^DSpA1KNcSHZqU%CUR9f}LMcIvP4Atl{tX zLgUzT9-kzUm#Uyxga@YH5Gmep`z43py-RLV8DPMTujZh2PlH&8v<#0>798RlVb~+# z5n62I5=h<RCbjGIAP^*(0G{OJCGaFGFp2<&-nz_`q`9$o=3q$3IR#JmmOiFgNl@!g z0iI!B5?Vh{%PiB|OAa_JXCW#6=W}8$@%ujI#_6DAmwn|F!LhCO9TTe3#kZAC>@lA{ zWj*NhGJUqqlR_arOR~ZXy%pnp_brASr6biV&*RE}D>fLPig}sSX|Nn&a|m-<=s0uF zXvtvMrm^{<@(GC4w)!dmpbub>buawzGSz+4h`fq4s;}|xVt&NSBdL4lK$<bD-62f1 zK;*O&aYx+deoLIo^p^OjyDNb0=QZ5?Jz`<qnORHfoa-r-@GC^TVLnf6VsgAjZCbZP zmu<K-o~yF1K_R$LwS1k$%d;E%K|*YBrt1QwIuu1?Zg@h)!Y3g^;yVhlP^P0#aCke9 z+l1JHFSFJ=@EBXL@Qu*UZ{7L0&N0gJ0{tY1N^<+!nPp>rd+{>*VA@QLJf(CB<--qc zM(a=J2JGL_R(yDmh*e6kgzvk+vm5O3o22CzWE?L@U@H$tD0j(Yi;_BxI_l=a?|x!$ zEG7+KGU%Uh{cF>{T(6JU21KIUVm8krR1>tG8^dQtkP`B_GuvEhUC)riPr$U!_S_{< zF2t=K@oQDO?sc`Wrw3N9co8O0luU=Y*Kg`yl@;$vxu<UgVD62GWXL@QwM7Qw=W5Qq z_xNS+G1I8k!}me7jD5h8u4sn;m|T6^@VNVK1rYe#gTpGK(knhd4?C%nTmrfZ3B4q> zYRC}7V}nh01z@!QytX6AqZ90Iq_apCpbc5l0xMRsGuAVf@hFKeE`C^x^iA=DgkF^G zAYk|zR_?d!z)gi8_xBr9LiP~AK2liO?|6;+W?SwSU?c7%cyWA~FK=(&RD8MR-s18h z+~@<*{Q`_X$F4p!e1-3;Lel;W_ygSu%@f_hjH?f?mTX(hB5nib?J6QKWEfD0jn{1w zm|u#F#(p}H$3j5=d4+P4w(qckJ@u*8+TLeYVA?<=1N|A5y`LT4M4LjmM18-MxD*E( z-omo@8nz*Qe_w|aXNk5&N*;TN8*Enm{*2=xi(=|;BA`7c!V6^L<QxuLN6EGNjb{yC zB8fXcQ)MXCW>eXaY#sLdYk_@CF$D0c?Qt{mjc?*TzSJ_C)Q;o9nfNozjiuot;Kfkd z>QMG3(1#QSuoG>4LEC$&y7MyH8Hj!yG1|BHV&%DO>TO;`5tm#)yZ#S*Zygln7rqZG zE-g|LN=OMxg9s?yN=PWMbeEL$(k{}C2na|hDY=Bi(y)jKf+8)sbc0BT?^zW--}mo# z=AHS??>n=9FwFCu=k&R+`?~J?5R^IN6-h^@>a$To{j1z(-o>=QBxcg0wyu)n^O<o6 zLpc$l+qH~w#&;SoFsEFTyY3<J%<l7Z#!-187WF7cO3@L@@A7_Dn#W1?P755LC%H&B z<PsAku5~=Nfd?s=ymPa~oeBOJ#bs00ai_7f$#_9^6N+}iYucIJ{qR$4<WV~wXURo< zLc|Y;h5_G&ACtSKH(I?ZR%uvG%Wn#@4hq!kz+Gq<13yLMiUzJXAb5~NVRys1ZU;6V zHEh(DCTF(QusYedn!@D*reAO=U*d7IGeY2Y-=UFZn&@wtA0QZl>tjXWb|&^G&1}cQ zhiB<yD`h@Le?gI=NA8cIUHRxoi7W3LyCy{QZQL5#8WtS2X5PybLtsbzU6^O%F>pni zJ?#0xv05j5hiCg35`j%Alr;I{u|eN@d4#6XiegKTKq*1naK*@yJ2S&`+O~MtaBOAM zS_q{<^t4T^$%s)|Uc22#IV&DQNW1i&<{Qpe5d+-wVoIkq6>AZmIh0WI0RK`(HSr<7 z<X)ASk}l)2=2p2I)Itd%OP9%2`DRF%$p|^;+tWp(6{xn7)`A061c`ACa?6~+U^u1! zs^0Jc$K<cu>90&jZ%z2$&5ajwaKJLTaH$Cw>AiU!B~LXrv=&TDT##Sc9Nx|?G^H+x zfLx5N)X%~TV`Fx_Do-VBunP$kT8P5#G)tWEE>8<5h3Yrq2ttsP4ii^Jt5L1f>K&V8 zPWE_f^hp_2{wN%Qz<nfx{MP>WouHuC>VAYUuTI72A(B$^Ba}$wxAxGz8>z;}O93cT zVlanD8fbZJwl-odLK`;;^7OF^b9Ph`84u_hpM6A!ltRZoI)!ZQszfm<|M0v%r1U-K zW~>)nt{QjZ3Yx?e^mQ3lXP~dXa(dZ%>sJb?XFgTxcB?M_G-a-EH!~B|DG5pB92vA; ziD)Zujx5;E<X6mI@mA&O7f0VN->!5mzJTE+UCw?*E`;u30qroE5*alvk3rR8^L`9b znKtj0gYKXBoay<V<sVIj{DpD0m{5rj8DpnQ(>C`j)uD+ScPiBzcRn|Wdd~DvzGzn= zCw=%6T!bmRhnJ4r>}ggcEGmUodC+U|B0p>jTUF?TOv_Q3(NPX&vO?p+u5?!9c3X!D zZyr@Wev1`h`|<L&Wr#!LHs|nRulq?@DbWZ$D;ha&!6{hrT96Y)u=P>Ga?61+^0_U& z2~J1~1Cup9;l#m>(MxO}FVKo+x{Aznc7%>gGX(9GP%<HEaO$nIR9@ISzJTFHH9O-M zB@PPFa`^ldVQ5T{9dNzf#s*o9mmzH-_Ab$pdc%rK9q0>8f<E{3;QLDzzaScn2t4sO zWEKLs9HHDo8k8s}6~1&ItcY)(#Ii?YBeIW6_7>vw!eMlrFsau)HxWJe_VhC-1Kjpo zepaUS`dK=W)pv2xugQ4fiP{F~7UOeLt9~eHGA^^?=qAkI&F#ASf{)vyNFQrOf7|*c zk{QZpf3@oUpw-WhX)4A+<$MI;N&L7oL9^sEqFxD<(6VP}eYPsz)b^EjgTUj&MyoPy zqjFd|!|2S~Qr}@Bz9N6uPyhgAYH+#Zu?F>3<}H`dj{VVC9-Gwx_cgprHfY>S@<)uJ zh-Sg)gV|})p1r%-PI&aU`)H3da*Uf{H_1xn3ADK3n&F2U@}efF*HMVLl93*oL3}Ji z6SwLU@dw^7_;>>)PqP2^5$j6sMh<f<0X%^tUW8gWxk5)A-ma#bPS&;yF$iY-(s{CV zJ)%iRi237VZR(flO2)oz4zw+Va@}ftBNbt348d5;yzvZE(#3-i%E;S~jg^lzOD>pG z8(FJ<rjGP%ZU1}|fzF%p5#lh4y?zL`PobNLTe~xZ_T=(nX=b%Wi~JqzTnMy-u`InQ zPb!$-CI*2bhEzz}whO_C$aM{zcPJ;AiB670{MwUz5DJ8CapjU$c&%V8a9We^HVGc` zUk+xh3Z-Vg93w`bvNS(n`h@9{*hfK@oSUCgjUDOT-7Db?ke(O^n3BA6ze_DdOKGKR zDyhQ0SxHp!jn_8sj%8b_5Ov^-cC3g=ImD$e6+L+Cn67C>+T2r>@!Zkz!UEoK_{%&2 z{YmPr+juE<?gi~?K_&P|7MUS=Zg@NS<C;*?nrMzjHRd~F^t_R5TMdNWZLNnNSP{3# z#|hwDL#yxi9(f;ru`JW0`>4NP1}3m@;|qtEU=Pzf;JC-*Im0b){4I@sV(1!S(N}|4 zMGCjKjp=MXKRvh|;Pf3mpYY`;ei4iY>G>e|dObfUvz{+?3uUR^(h@lT!Qz;nw3Aw! zej7N8U{RG{L=EB4KY<x{TEc9o`KZyGHHJZP!LIS&R6;XNGhFe>`kn`^OXkk3>!bBd zy8W&_tS)vV{^;ZgI-aX|LwhYHx`UjV^ZE9vmYGt3dZc<v<RB`b*)(PULu@PK?tVEZ zlo5-gsLP5gBhTsHT?1XLVqIfCXG>QZQHr)Y)%(+dnv47d*hx+|l$M_JnWwNxb0#&T z->2wHP*W+A>6ibOj_e*3l5Oi%tyFHk+{S|fM;bRn`7o7jPR|Rsu(=KV+tkJvBC=cd z=_7<9u7#K^fr?eCKOj@`47bTLKj1hK^PF)|G;U9q`us43pik4dY+r1WZ0n`6kWG@I zyUx528Sb(3I#sImE0(g~RRY(kh4va&rx{01T2+q8L|Aoxmwk<zYZBPvxuX1WC3VH* zeVD;3ANBGyur&_;ZulUxm@eHtrIP`?s5~_A1)&Mo$GLCnjZ=%(9!8iIK!ZEPuH-P> zp!6)`4ODorP*#ZjB_wXJlQhH6;wXuWyYkPDZ^0rImS2{Uwlk@3>KA-6<8^0g!uw<h zY8)3Hp#G8C5of=uy&cG+xEbvNEw*m8&LX$=bVXHXe%c@_A-W%$(evc;1J4tD_>z9K zi&0b2BkzVDG}lnmJyq?1<siU0Z-J8ByiWz8+%nA@5r0|6$O311A?kF6O3?Mkvlk{; z74g(8QhA`UexD{=8y}7;)Z+2a4O}&OHGO#-75fp3IpR)fpNT(;f>Wm))!VyQ+K&~X z{_?GNf*Bi+EAK}U>N~lqOuXDl&F?tt*@FdJ!)=(Gq$qyhbQ~LjP_Fp}jz3?rWSpX7 z7EYElbfz|Ons*RYgq5|{qVCCPYr<j}SE`>Ft6%AJiZ!9H8**?!{R}j=sb}{uhhK5p zU4<Hx<|$|$;tT%dc=Yn24*v3$Yb*G(3p-*1RpufV<WSeF_~;8U?6qqF!*5reR<BO# zxEHpU1bqvFnKoMg2z=vI)Yb@lmhDZ@HAvxIlSXAO6vLHDC3LzL<Q9L>@!E(RKG1jg zu@)t*(XU2~L$WCdkB#S|ggV_Pz){)!7_)yd`IlsN2>uI_VJl9|0fEDM$SDTb;zBfg zmU%*@?JiDw23;8^)Zee-(}q!(bn{OnQHgT+I4T<Ry-8-A9b4peU>c)_U7ri-{O<Fh zzT>A17n{;27G?44+%H=`8KL5@swRn!(_6NTNIg)euYU^lk(v#VVrns1dzcXTe$4fC zQZG24g(q@$CrVh%mQy0OVrY<@!-6G`s|1L?(8+yjv|$#FVpO-`vq$X?l+Q-dIK5gb z=aXuJH&i&2i>OLhZK(AyAlvrhxt=BOea4=tSNQccM=8B_mLpx49U*)r>wCcKc@big z@5-)jWwTMtDw1wh<sFm|$_bqG)A!^r)I+;iY<L$0v!u3;O+$&WKD<zi+|$HtC5)ls z5kGGiTMWSs2URF~n$*PWy|srOgHfM4q5LHeS$Z$aBMFh?wenw!-I_1rnwJp4n(_D; zxVZ$;TZ=e^L#&DIWu7ME!jIxSLy0CL9{ijc23x<dywWnw!l#*w;SiLgo)24?!aXbL zMXZi6;F(~!l-X*n)RQB^nHyC}HbxA)Va6FaB92!ike>I-NQ)k;*wA<@yThBHmYS6d zCB>VeE_&I6)x-#q3!z-$Rb1nAQNiWATBYPy?uez(7BAY>WKVw!CG#_c*0JkLn1hNl zt;trrc0K*~dNi9JH)7Unjs(if%F0DEv%mjr3jdy^{v&vMnO>i~(+J1CG+@|^2%=Yd z=dYR8_}b0#FjuR8dQ8b<mO`_f%4*r_J*LQrsPQy#;29=5D0<m}x+ABU5PO3gkJG_U z)RiIM`I=BGd6AMBie^r?RAW2Bp6&Baf!K4tTdaCRMz{91c2n6L!f{{e2jiJSoJ(GJ zbQKY`+P)fA7!#x3O;+|&u6tunzn7ix*x0FPelV%pgjbqBiSIQlN*A0<J4-so{pKYr zJj6^}94-OPiZh-m5i#@CZzR7Ea0Y)1u|smv$-!c4CuNMy1kH~_A01@;-Wq3g{Sw6H z59#IXqW8^dh-TIMxCD$IvuP)^=_hjcH<9sqO5E>UAEIs0@9)~wq;%3$=Cs!Z=G`8g zwpq1|Xs;PIy^Ss*8=M{w$JG;JJ(6M2z?JW0ERh~k`zgG&C;Y?Ztta9Whf5O?H6B%# z-4Zoao(j(*;#zz>{zvU$Yzdkfs4<<f)VF$+VAb#oIiZ!>!D0%UadpvRTt7x)t@=kw zz=T)L$&KHDD$!G!1XgdmZR>yCaS3Y|3(Ah}bR*@2q<=Sfq)ijd;N2RK-PwThRMcjo zHG|8s+M3pEHj+$|%MX_OzIpPJVJ$00^ySDkGoyOeryg||gI7<+R_V)Hi0W6p-=|dw z4Iii^p;dox{H_-YiNfcc-;-1}S~Y0vdXayakaol)&)m$9Thu4p=>850n=wQ@cl)fu zEm49!ouH#aLGw|9m$53LVMw5{Bv!@&$;W2ga686LbSm@x8{MJNTZ@~<SG~Jt%E2gw zu=FXiMA?#dDnAT}X!k_?Oyen<96NlOKJDsl9U+#bkGn)F+)H1CA1Ki-&HEAzMPHZX zKGt~2n*}`B#AEN6fw;IDE1d`Uv|CK*5yHf(ZGl&M898if6<CE|3qBg=N>|%F6&sru z<02-)vM9k0Blk$?g8eppHWbqRsdmspoGQt|-R$s_-_&ttttW-)am}@@)`hzH+@7S0 zuvAum*eyI)$AT+Cv`zgh&D5oMk+#J?U+l9q?iBnwwI)Xj33qHpY86C8Z9g~r`Bg2F zvC&J<Q-W8O$h2Hzjw?4ZL09Na#df3&Be6Qj>Q@{6*bZ>`i&yj~OPV5zIVea|R=w;C ziUM7~CUkiwE`>WjePNy4^Bqr~;|=f_NM&vRA}<eZGVNRpfB61uK-<&DX9OzzIvWFA z)BIALLU5d>-jB`62Kzw$&{C#BxV|p`*+UmGeCkiysRkYGADgGci_7=B<uAU(*I~tC zV)*wXgUY2}f~3d$#J#3C-0I9f=Ab!M+I31kr)2RYC9w*xEnLjHjL*cjcbU1${QO-e z67tyQa2sn~h^*wlpCaaI2+0S+|Eds*|G>CiK!EGNZ{B18RmTbi-0m6gi-&@+AWW~P zP@b{FBychkQ1^?nYtsJ}Zi+<)<s(vwIOmHc@$nuQCtP^v&iG&9eDIg}obIEn6D~oy zKPumUROfhdk52xq5QYTsA&n6`_R6zwOLBom6wD2(kDNC`185RB629b0pMR;JACy}3 zR8IOfPGO=dPlC$7@^slQ;uj5$tQUMZFYX$CrLwUc^ZslLyBUYg(0OOQXJUXS6wGUw z$es07pJXNrR-x_$#{~`?4x+r|&$s@yqBufw8#@t+t2dPVZZ!O?wO5rv*BU?3<)eXD z+5bQSo^hN9WLHl<I^OQBD9-i#_oc4|c$HA&582)bvyNzolb$pKtD_m09S|T6vT}`M zco@K?rF;KA*-NcA(MEcc@O^v#n9XPqB;}vn8tVC6|LeQzc*hO@RZ33i)O^!Hu3n?h z0XrM1+qlg_8n|!tWW{9x34+XE32p?*-#~D(zy6>vNFgnj<@2Ms?BjKZO)b5H0j(nF zbh_8iPM_4P^*%9tX8NTQ4JU^)4s~A|KujC9V<E-AZpbvmue>JuY)UauS=}@zX#9n3 zNp0>Alm1&n6;{1P`Z7A=2eagRUtbU-hm8CiI(N#sIk&nE8@vwqnO~)p1NOaJ?Dz4u z!^g*}cgb{rY#?6H2wSUJey>}vX=|`C<)n6-c-BT_Ktt~2$ff`KF?7AEgT6#HL)`C9 zU|+ndD5-ngwo97Zpi{^VPje7rm}D@RZ<mby<@K<~?~`$P8vEI5unch|?V0`zjam|f zof~mzhkQ>{cCw367u<v6z$vs~o`alwfMgaR!|rrzMdqBYKBpFNlC6y>BNpFp#t>?I zaL-u;okEOzDlv8JNc*_Q_}s*6As$TnuXTrvlilsfQY4z7+I6X~yBsEs#gY5=Oe&GD zg2hD!ZFeVjXl$o6EJEFyZ`@7Mv!+j#i=ez`3LDgO6q~fD(fNHEB|Ge0<#Sx)bglQ% zO^6l<s2yVrp<f;}^j=erlc-p4N>bkZ7Io0*W~O0@VlsTAlC>@(h)D(DJN|lo^h4nf z+YDcy`aY43`kAEZH3GqA)X*(*lh+Wf%y+8)R`UZkI2v2)P95%&uE=7n4FAP%8GR>v zUuDGUZ`0f#>{zMTVof!tlo0ntdV@Pdj`tMtitMX@aFf@eq!xNJHUO23PW1Vuo~zs$ z=9g+ek3&qqin%>O=%lRUIu~nj#QL|JN{Ip~y;RX320)IiM#vyLOhD$}TGNorG{v%A zFmUg5t(dN@T}#v(Q&7Q6kaQXvcXw%^F^wKxPfT^(#mXDQDs)NWUT=PJ<ufYxi|3A} z$7I7^uxY}v%h0%oN2;K!jG}P@ZK?a&a-+DZ_NMu1?q0Zhz|jquv3!xJ{l%$c3RBnK zD6v)EkUiYgojxUp6zoQ3#GrwPfspG;F<onf@rJ6sfYD^5ufdHYW<=_%i>_S!PaS*S z-19q<{v9=9%QKXvK-_eHJV0n1mUZJcbaA(HXHlNzE1g+3%f;n>6ET{wn&<&1kq9NT zKqmPUEdkdX+||89@5+<z<3tRXlF$hDnzm9WzpmUB)Nt;P7C9V2CAPzNIvMt2zKAH) zj|Pt;4@wMW1(*qKs);3zd24Nbss8Ssa3srD%gszFj<B2TpP2iV;q64UPAz=Y*I?g? zgoOLBuRi@@S7)DFc%=npeK)cuuVHU|NL50}CAaClBccW8)cZJQ2IQnCTz_lx9X+D* z=!RQ2U!zD&LOSf&NoZy%FI8V+vh{<qES+b+y5C)S`w6=Mu6szHA#rGuJwk)9NO;$F zzM}WA1=8uva3$v6y08RIoNJrgkcCzl_Mlme_;OXbE6L@{53Zy48av~Cg>0RZ8~^RJ zk`1KR6$$v9&X0geH=Q=piZyl*=Qh=Pn!x*8(b+D;<3G7fU^yi<$Ic5{C3Y+bG#%Qa zMXA4C)QWCMm*cUJ{LYuIxSxy@>GkSTYP=a!hl%qZpIL!{?_^V0T%{}D?Ieo&q*!Q# z5Mfn*7V($?A??|DX}8L=n40DJ6w!pjJabQehVs7&x121Q%J>4e)Er`D2p>@1pxE54 zT(1ID=ITB4O-5(~brwhLH=mZ!Hl`D))fUr{5Y{5rR2bm|y~8GLot{j3t`OJen_qYb zkvn_#50aaa+9{b`iJ}6Ne(1Roh*tgar>q!v+hl4KK~zgC%>z5AxUFOIpisrsk+Bnf zk%kvySi&H~^>=XO`gl<xi4$#~^AtX3)rm~)&h3Bagbm|Y%SA0cPxyd2oY|?}t3B6B zcr}!n9}T}e?>a<b29tawyu{LkFTGhJvf)Z-Cu;<Jt(w_#4EEA?+1}I*-yiu=X8kUS zK~@7Ts0~s;rkhk}w6t-#0Jg>cJ@WEp!xR`}ZILv4Fkk`pq3y~^O2(wA30z8|I<wU@ ze63V*q_2hyTvYhl2ax{`pV<3Y_Eq%!=5uw4-`_usfM}JW!%zB%<o!4zVY#tSTY7Iz z-7v5L$s3A{$l-2zZpm>X9F$O&wQNFOo6sBeGIk2pKP-~;`|^*tYQ-n7eW*!|T5j7! z>H96^+^fb%^Q7W#9xSAH)syAXViEEsUwzg1HO&7N7pw#Ng!_*tZp~wLtK&!`NDz;{ zL{@!A^K2*sBvVafLP}V+EFRgutubwK3dfOuFDC5vw5QENuQ{~xt3?R3=I}E|1LBsf zaaq&M>ii?2Ywk<!R0~&?{IHJ{l319jUXZ?0)z=ne_G5<)z3ejb+LDuCiah}6C<mtb z=yn|*V4#=%$MD(AoioSrdV??TamN3Xwqd5Vu5p5-{zW^G1kGW^q)k*Lpq&k>ZOAw1 zzx~BGi4Gl}#BKx>AAZ};_?*!$$6;)TQ!ZBoIz`QDCqh0s8#dFLMhcdp@>2z}Jz|>! zdi+=MXr!+3qhqSoGa)Tq|4f%ZhiT)^AV<Z-DwC7kT<Z6`)R}w)vA?jW4P-q=Bcdn$ zR*DfdovNswi;0`@`nt*;25{gix*E!oWpG_Xd{bk-j%&S;gc<j0r#c^g(QmT0u8z!0 ztJfoJm?e$Qti~NhhPr0<w>4O_VeG{8B7<9pG?Cn$_%j_xOFqBxgm2t?`pSq1-d^}r zn!no_<V3uLizFoqle)KmlGuJSfF-}0^T=4|Fp}hJ3`6&zFF4AI^bG=0EkV@x15U$i z&ihP^9I9!Y0M*Ba;Srmb1vG3PZ=V|Ys$h%6kD4SIc(_3xnt^c6O=i3{@z1vrBrZpE z&z}1~ywlM(!@sp&XV7@@q76B;!E4XmTVR&j?A4qb(ReAGFT?2=`Z!D;j8*v>@uVe9 zlhXcH3d@<f+kXenimj!D#IBH{saQylGMrGxIj~7II5F6^ZV$V=^?DOM1Al>I;okOB zuhX9bJ2eR)Pvd~`t@@y=mtVn2W3!n*v0fG#Icx)(rBKeI*W9hb@?q3>QRadiZmfGd zYnozC(Pern$DHBv31mWYb;XVbl~6#*_M%_m(p&c@M$%h6m;SUK9deob%!<#q!ivJy znr&eJP=m#kPJ)g{4oAG=tCyvIDB5Wz7kOo(;A_Gn)u;qA;Zp_$5~uChnUFJD=7Na9 zD_0ksEKzeUwoBqtd#|YY2Ho0-+SnT%W{=Pf0nk<KcO~_wtX2C7cU<2#irOZwj1(s6 zeMhk-&$bl?0e6e_i?T$N+jy|R_1X7K*KXNMzf?n+ZZc?006#+4Wcl#@QT&)2X#35n zmSoa5c3q*}cIa337XLN^H6F+*2jVkl2^Md?6fBQghgwv|M5jvir-90yQe2^hY)xrn zCuPXh4Gk6vEym!yh$I>bd+8ttA<m3ua9NajV1vf3RI%f)GSP2zq3^LNkFryrdC&xs zKzO!IncuJA7}R-P90Mr^pO88xe3|04L8IyoibkpiM9(Z08u)L#qFcmT_e8ZvGF=6E zv?RQJ2{#C{k8E~=MKwdoCzu}yQJ@LlzU(rEw{w`SH*GW)6~43<fVC5JzDRIm6RZe{ z3YLwWN`AY-u{40z6pQ@iWBD;s6T&#2UN3oFJ^9Ovpqgv7Gtmw%N)Jha_M63Y;FAXh ze`|a~dL;!EfP7&=sd<wor+4a2%tzH_?R9I$>GwsQsMjR#O@}MkhQu+CUmy(a1sV(_ zX_kDmXz6tVLmp8dJOR;IFWk2Zh5mngviP|qkPqH=N{Hep6KA=Uv%)nJbTv?_YOUZN zap_fhn)*9AiXvZokW3<iFgO}kp*TQp0<MZ?yRq`I&@aUn@2)JPLG;;FvbKltV-=>L z*>C*PrGOrME}r{0Tnt#n@z1HCDvj)UpY>Tv3dSznuRljL-yoxQckH0M%Ik6)1)?+n zafKA_vY#O?HF2!FTnLtu&qJG|73c39V1QXn@h<1tV_y|9Qqz}v1qtbK1y%o^>%R!# z(|v1MO{stTv}|S-UVk>`v8qR83FoLSQyA+m8~8@Jtz_{zj#TpoQ0{4|$`htDtO<Wb zo_`yDb3^lUFDr%7S&_};`Pbk#opSDIoc$-$5U)S5`DIN(()Wiu=Yr(tk^|U@sDwwd z=f!z3t7(EaH68QfmzmERasgg|&l$#%_WZo-b`&$&v6RpShN^4>N@w4=fJH$CCDXpY zb&e{R(<J4<2Q(Wp9u;Jqb<_pW23PuX7#u1YhW|v_xYJt`o%ntI{MDz4l5!C6>X)h} zg0o$iNeu_f0`mzA>$_|JH7ysva>RXqGr_T8M@xr5hXeie!+@4chW}};Uahl*&hq;- z%16c#T-C00_gyz>M0aN6qXeIb+--f!^S3>>S=9vL1GG*9bsmm;X&b)1Gx`{eiMj2@ zFiot^xE_eGJ@V4sQ}ldy2FAmC#a$%Cx0OBSRsGP>!e~5<cDW{Fc<+Z}Q^VBBhboGr ze+p<y%{4s-WT#5HXl<tbppF&Y9_q1bEda8IJ3<vR*x$T&OZ^gT@^1WIRCt;f5c>4y zpHYD8-c+N+R0lgVnob1y{(J5{2h=did)>*1ujNU;fzMKo!>`3}(K9?=K*b9rI(7IS zV{s$2WmOBW`I0wMtd-Bj#xu#DjVfvU?P;#)FweomUNpA>vPL0KwYP`{#L};)KaA(! zw#no3UX45GL2XXAja#y2E_5f)(EHBD$#?yd`!}#pqa+_<Yq<nzUY^SX*QQ5HOhY7A z?to+{$n747>DHhvcAY%$o#i>!6t<f%1@8JyX`%H&z45iUW^k)j;twEXt#Bw!?$J~- zCZgtTR;k(UQ6~TT=xFtW_Phvr<yvm4!?Hu;fu)C6oMDx`NFUX|$(Vlu<ABfz<yck{ zGV-Yq`(3|1W^{VIP=Bk@<8W!6!|0^ID8?aA%>BogFR4Pk2K#$Wb>kkB<HgXj){~#B z72_83b1yB}Vy{9&qUlz|_orU0atL*w%+AD&2VfJX=(BNl&$UQjHTo6fZ$7%TYIOWg zU8L-|mdfxMCTm+W0q;MfQ|&uMmlL6Qv&d9Y8{9>)m&;2W7YJo~AeIC!&g)U}+>{#n zV5{Bq8JuR%^4|D3Tka4EjeYGf_66ehWX}|6f~1D=$OXK;3Ga<!r0Jc7S-@O+)Q-MC z`bbmvez5ViC={M3{?|3|G+7cDkoQm&h%5K^jrWcujv3q5{2$$GXH0P(nK)XVIW@hw z)e`yxxv*Z>HuO&7y*6GWx7W;7N3|>Ppdp)spL6Mo;_w8*@zAwu4{altC?igILd47Y zzfhx}3~q^E<cwc<Az1x6Ec?F4`l=OUV&h>#X<&PykD*WJO$WA!f!28dTW6{k$xuD} zr+ed9L{_KrmY96dVQfHm3YOTQ3tMuB?IN)0zD~77Z$KV5S&wV{k=F8$&L0zUKSOyJ z^Tv$cu)m+WnWgmd8|)eKXE?{$U2P+}8$GJTRWrvMs{YHPse5Z%9XCJ*oWi0f)7NrH zp#2BJH2R2b?z$QiJ;$}dYQZ-m9wit|JvNtQv|hruVU8e~?b+M-J%yX>{w^Zc{knj4 ztRwL#CT4g$^&6{){Fd(JK-hZiLM!(<T(~Qh32sPsFrgry4nE3xth!Ty=RRqXm!@Ck zV*rw-xW;eP^+sINY6Niw;~A&>9o;3TmM!bvf)M53r8#yrhXsZFU9X2tW*>O0Z}=@B zJvJt+{qi{s;(u4}XHK5Z3;7*5`W@+cpyCt`ZBPS1JKk?C(x`9JL2Yx?PC`|eJp5pk zhl{J_TL<lom66rE83l=B6X%3*f5-RDy0&W{#&2|Q3tRSz5wd%8BDm`p-zkfn%yvlZ zuKoHWM~kCYc|ErEf)%AIAjL-h59#VMsl_%Em}b4i-uRvuQ|FCFMLxUV>oA7V%4*$i z_2_>5>qDvkcrS6*m6^<yT*x4}4ssnMHYaThBK_){<f#DS4ptj<Tvf1-28EiIKE}{2 zxL3ds{-;NieuA~gKgvHl_(aPlQtWs!D>^&5WmjmUi?CPXM&sdqG4uC0(%sYsnR}@Z zimE<5F+SOG^mlO`!tn-~4adIUvD`<!Yl|dLZy5$m^c@xJZw9o&WozJyOd9M7iCqwF zLSuBKTd#NK(3Bj&7r2cmU@S6aVl1WDF2}B8j--Eme}I%WYTS3opwRWE;7vqH%}>RR z7SkWsSRswaIXtx>_9C@(;*r3{RU2jmxaF>6&F)^+rnO4-df|sJdN0y;=Xiv|_wFw* zW{sEno!B;U9%pfo_Ua-S2Pr(afylcQGT~VLMKD=72l42xI1uH}cPERR*jAO-n|Xe0 z{1wDwPWde@1WF`d)So<`AQNaxV~2nrbu^vM1z)~KrsZ@1(SmM0F*^piNHR<jSQNg0 z{guFBT7*?N+RA<*%a*wG0m2+1(nYG)vRJ~rWnl+|PfQD}<QJ*ad48HT94;4b<@z16 zM`VmPG6t_q0bw|B>lKOgqR7%II7b>3M5(tF${LKFWR5oK94!Yuxb%ECk>jQo`-V}o zZi)m&%J2$hk`+O({`_t-)9+VA7a4x1Ieg<Ide6ttF^s}E@#uXP-*$827hNV$`Fqs% zUxUkI6>0@)8b^jKi$}OD4;H6xXeoK+pIR8W)vY26jZQ$M#<tMT>|zs8sC>$b{tQc@ z<kFpOOkp-VrfS@mtJaor)*#bIOTDGx#FG#;WG?22n<=SVM~XkbH<!Nk>-)ry4<Fp3 zOtMoLp3yVc9Y5!)+Wh{I_;rR(j{igWhuN%{vCp&?Z)w~&ZVfJ9*{1KC3r{=Q&Nynh z*r}3wUG6m(4u>5Nu@=MIzrHtkCCMkeB3*Lri&H{PJ6s(%g7d;0?gxwujhK^rY@F;_ z@mG@vo)RmurvNs6MPb)a8ub_<y{sy9W84?xQT6VYKivwWGfhvmvU@f57Wf5wK+w@i z{iJ{^`RUh*!VvYwCOrnBxm-PRX7`Bo7FCIpe*e<lrtD^R0b<HkOWnwk>$XMHh0h}0 z;w`<?q99ry^q?Jo9ZvaIFY+MJHCc*uHD70Vk;FV&c-Mb7MD5Sq{5pBKTRkqsxk=01 z6SB@Os{XL+uTIEg(In(xfE2I3jyL0E)k<O;zFwp-QS5sic_JODDY_h`9<!QMZU!Q^ zvPHTf)JqJfy?u9#Jzle|tPqVXoJ6w!wk-kKe)t&PD#Xw?;?!?A?Q)bBY0%&oX~tRy z|1qv4)5!8Y;n*I?nAWeqf$w;H%|>Q#qZ-PAyi)dKHSNXZNsq^|>rcRa2MNn$GX|72 zt>531Q6f~2Bz2S>BbDbBHcSP&7^V=ai`!;2rj>ZdtQX#Jqv*KY+U~KEcrxCllxIEU zxw~0<6DvY{1S0b6_esTk?#pI^z+Zp;Gin=uBvjXbSKmCoEU!)Dbgw14s{YCMJXK;N z8sB*`C@!@55S!?rd~qTxwUpZID&u${9y^NMAi!0`^sPv&%|s0B@R}9xQjgdIt%5GT zY2_x;-gf*2>fS&&xMN)XRDsg~iy50w-t3V;j8-2D;-%~_gFjXZa06sZ8*i0QhQ+fT zU0&`ChArhJjrpms=gj`p$Fl8$UmD;4;n-W`*Xq<!3sQ_)G*a<PiF5umHOY3&d^22< z=t-+eQ)M&R=zz|C=y(5AsB=E;di(SCu7bPcWN^7re0fV#j4R)_j?sa;gz%w3X(U;L zpw(3qt|(;WO75BGIuuh2^(mgzj^#+sahODPO@0@5gFwmStR*1FNPyXQxiib}?>zkW zEX5+)|6neO#=dDLS_Db{Nc3BWngMlApm9!HjBxA8V7*3}#dfd?Vm1eaD1~afSiSK> z)-8Rcq4`p{o0N!GB)kK8LHeld)wMEXItxB$DjoS_U@lq~=;Sw>@?t$y;FCAyXCgQ2 zXYDir7b~AgpPZc^>|_t3nwP=-$=+W@mFq=?sk1giZJBhexNQ}U<Je8!v_A;C;3dDU z!dp5Ba?3W5FknNr9=BYf6B!gc>3=+3*sJ_#h}yufrKe1LN&gjzX=DJ)1P3*iIjZW% zVdR#HA(sy;Hl<-rOp38m@)Ch4u-a(Xwx74R2gN1S6aI|GCqHh!q@lUF-aa)==*IQL znC~@%U-DkV-o%QyVL58es?5-ps!jjQ<o_Vca2Jcvnq~iTC+C6R+TEd=8$u|tEwNOf zyMkuK1zPD;xld#bz1q?+3FwQzO~GA}bZ=&kfYO6F*mE|7N%aZu%eU#~hGn`HU|DDT zY}H-Z`o$;Be>=O?k3=3&<OCGZdOz!z_CG)xGeluGo2eV{E*AH3CsPQV5p0?avFva; zkBI@+f&kLjk1Tg`SE;Nr)}rt2LYow;lEf;W|H6XggN*T_clhHDAn(XU{SPdX4u+=9 zSHkZPnpO+r2#%mp=%J4NWTM|C4X0iq&s$o%B55cGx^cHm_hdKxIkSx)bL9;^WP1~< zLs5EzXL)_HscG*rx--Sb-ZcjQiKw@gP7-(b#D_|1*j7LqIOr`$Z`0hsx&M`}%Qns$ zSKgn@e^1FQqkH1U?)x+1BA*ie1iwg8vQ@9|i{X;=&~R%I;hl}XLR8tx5;aP9XL<Yw z?orayY!-uBU<v)gw_2i{&lx*|&G~YGc>FNT&K`dT+awDBshNX3cmg{Ii@G4(STmyd z9shYaYj%nxjrYi=qG3AczxnpZYPm%OKyTl(e#3KkC(9rM2*(%F<mZr*N$ooLWX^Pc z!~cMW!OtODI6<ucy_P8e(4%6Tx;N>6wCQC~`1vu1d0Em11I2^0cK=dXe|X<(pl}c# zc@BL^;C&djl}KUj4Ca83@PoqnZ=H`ks9O#rXyWzg(TKBdc#dZd3b#<R{vRZ*B4|sY z0PTk}<N`kO2^9W0^K0OLuf4*w#YXt)KhTM3cPuD8LFz63S%+RE{r}ccau%$kRp3Su zBVRXv1V{i~i^-PEk2|P--hb@!nP@Cq3_NZ)`sK6&5Wt|3zi+kkoMQDpNJr_t(Xarn z2j58K)X^yWtUV*?9eHiWYiE6pSPaC5jfprm8AO>bzCIr_3l=qX_=ir`)S5Vv^+iCt z*&F2u+K&npjQ*VK8V6+Kbb9K&?}VlDge$XMjYk_B7&*BSII`~BJkdNOxyT^wtcX8h zoRdH-bS2}eb~3i$*3TjxhtHRYQ5DOUx>$t{DH;_2MjZYI!p?*sc^pFTSEFZ@=H??M ze!MBOxBqL&p(Oy@A*Y?e4MfBe(TWc5fCy!trr(W6W2@SRojQvGJh9D+E-UX>|J7fO z8Xk^UL?k%eO!w@oRHLlxr3vTnDmrGxf=l1pih*6z7=ZwaR7WoSqF*1970>)S?PU3( z&DRm_ln$@j4NXeFB+sy_raZB`w_@pwUxc(#)Rg^)o1Mw>Bb%@DHb;Sb+Nsb0nz~hw zJ1g~I-Th!Z4qy}}Sk9oEd2mFYky{Vh&!t=Wso~%wjYBkkwf@I^G1KPzdfKyI^NdHc z@v38WRpTHP`NBj+Z??Ud-Rr&VvJETC?q>$}KNw{~4%K6_HD3e9&d+c7N~xZs2+om} zD~sX%U2w<w#=hIklgq&T0vxwNhKkV6T$W$tJD;JdKhP?#O8IQ3Wr`KYq9BFhy}EQo zlvie9DKFhwRrC}#@6AZAcZGJb3a}q>^Ngttr-v&J1=t@u-kEdJ6bp|Aj(-&N;!9=p z$psmwsid}kG6Z~j?A8&8-?+NvWaNusB4<1O$m?C0t0pG^VCJ5XvrPF#{&>A<l996v z;h0OReo5J<%JEY~d%baJa~OzIl+%5kceaa>z+Fi|cT4-wI?cwFw58Zu=GQycmOkj< z?Ld9j*p|I(0eclpbR%77?u*dmFGG4VcXXO=g-MgkLXTVgdTmGP&|7mdE8z<l=zB32 zz{=oy)X-J<9_^kUg;Q{h=@C*LnlbKU;<_b%R{+P3(D*Z%tk(!Agf#X>z_!dq68RXh z!+aX#&Y;7-;E%wObr89@>sh=B6q*;|A=6ta;3l+;=)E<oVTsS1?lR(>RfNo(fN|gw z@*Ar`r2K>RVEJiCXEI?CQbv-{Rt$l_r<RCc!ERd(zt9ouZsZSG=%a|7?(8Dk>KDQ- zz$z@IvM`|w?0+q`_iG&1Eo01Bi4a?ZL3)}@naO}kfsg0;>&YJ3A@QTt_z}yG-&K#) zqd41MGU4&`XAw)RQjRQO>{h@!$Mt^f`SgilibNgOChft%WaF~^=-b@`z}lP3n%6rn zzYyAZ&z8~MFVeZRyEW6md#u{|>)eOPK!jPB&%ZTzd)$Z^0LNpI9i@)Y=!?gBg3FZ5 z!s!mec7XEqDtkHhx+V{VknB{DK3!#|HeJ56ed}g%2);OkT5u19^Ja&U-zh{fg>oy% zi}hJh{n!N#1)M9_XRW4vuRH3D5SGCv@ye-;U?vG)qD7bUBlie<sn9C_%}RPK3JR!k zOU3uLdc_mLAKm_}Gck*XG#)F(4qNE<bTl0I#_EIZ=NP!C^P*3Ovi_m#CG<|Gm3h2G zYvAQzMBQD2`WU&duG>DOi|GO{bKO@4zx1-wN7NKab53}aD6casL^<o()#iYtIb7vG z&UhtBNS_SYD>>xbB4Rvwrj3>Oky1k?$#V7au~W{g`{b(Ku5A`t)}~l7-v_h}lii3+ zt3o4mf1pe6k9?8{_|AvCu%&^`Aq$~%SuIO`UA|J<Fz9PO9vlQ^Jfb%jl^%IHo)knY zvvPjcJxP+(#Ma8cZ^(tj3e#!DJ8VRkcO8Ecg=isE$;Vwy{EiROv3n;+7<yi-?lCg& zJlG%!=$Y9`=GHPMt@Lkw$Y$a0(%JMoE$r>*?ruItc*3Pf%QJ?Vjx--1j;$In5F=Qs zMlIzrvolnOQEAY5wBn0rzIndc#naHwcO9XYm1+;1^mmTTMNHps3X&!b_|8O~l!Q}2 z?E;$#-d`)JT`tfxtvrsdIF4`rj3rm`?_A03!RwC%*dz`1voqR3<}xwm7Ie0ksTfN> zpf6VSbFVdeGS~MAY2fkWOKHm|apWj)tNw_i$1)R`D(kqhk(bJhxFSAFk^y~1r;K=A z8bo=d847~^r5~Pkk0cWRiLCJ!zg6E&-d3JRkn35@*A^!d?_X?dlhr2|^a2hYklteN zJ5O)QTrQOVo3!1Y*zV?*K~d`3+&3-?XsD1Z?JkH0J~DrIs+8_e2KBsPQ}*v@?!O2x zC*(wa`()OhFNR#8PZ9jm6vJ!T!2zg`Yw=-mOl}u%Uq)=cvli8NCI3k;)5nhbSl)PY zcrdiUyL_crTl8>q5NI$;`@^akrEY~um(9ZvXaQo_Csy6lVxjpj5yaC--6=mK8m@yk zIY|sAw^`u>cyW#Y242#D>{eZ~sq55fVjqL+iB#M$yF3AzYP)q~6c;5yT;TLH5}XM% zo=BjVhA+2R>Y=|LREb@i@+6+JJUKd2O>D9@EVoI-warWO*xgQ6nBNOgMlfzZIIc}- z(2jkh-;%<N7<Mmh*xOCNmrLr;1MG1<kU4}|lijU#TfSkkOjIY^yqN_digOMSkgRI% zaBMLop2vinc6E9~cg<~?3*(N-qok^3afTOLP_|Af{1B?-v9OS3%hER^9!)3wtz5MR zpFTdKFPSIctaq+UU5GlI;}4{o5JoBhPE|i!;A~r24gqd`${Lu?Pc4~X*z^kqMjQf} z=Oiw7dkqJ>2{S!goVnW`w<~3kJ~e^dSV5D{qy^tu8xMA3$2HA{Nx8x{7*?2CL+9Rc z#Q8j~UqIZ3w|f)F^gXUpy-v@Lr0HB}xAhHRi*`^%Ue2hR@*+#d0dZ?3zVWqypnCn& z7~A>q>OVKyFOvM%&5BG?fbNo}Wt0!+lkL90i%hH94I3(apCnhojb-~Knr>WU#ZR_7 zXb+pxrCWM1N8DDgAu%~r4<z|*sVyTIsUAExLmv<WlBDPtgT}*iv70R5aDa?yt8et& zU}B0*0#=}*tnNAcBMAv-1|}vg&wnfr1C}Q+wddrrDbDS-|0{|De3wK0!94nD=7+z1 zSWYHvw>n(3efKd$HuD(R=AV0^3K$C>UI5JN0s?osClFCgf*Wwrri(quzVj<j@GtCu zCNzV5F9yfe&!(lDUP1;7iUbrO>~fiw*jnHoR|Aj~rlFZ2BO&13%pbgvg2zxI{`=U4 zr+oj7gnuJXBSb4jSKXpm2<t8f!t2-KG&Uug{WfCLt`jpNnRm%0pI{SW5jwR`)_ZOr zGvOCWKFDBF^ZfHPAVReC?C<`jA}nGkX|<Y*TMEStznTG-lzw{#ULm*_b-$_BW#JG@ z(O9!O&Gpxy3Z_~a;=cMozgF&5#!{lY_popjY~I3?ba)}zd&?Nh#AUvFEA;O=1+CB5 zfe%zWPDVDj#s}rM##1OWam0Sj1IWjgnM72(pQe{$a?6k}syPLOrzkMN2S$4?4^$`O z0XlMds5FBL8d^vaaucqplo$OOU?epztcUO*1c5;yUXiw;XFHV&&}edH&xAjBxyyrC zWWCJ90V{6JyRL>YY;`%{4CVWg?FkSqTQTM*8@kMD-?0jTNtNu-O0r0g(%dh)o5>!7 z*<D|yN^+J2G!u-!=t|;A!Yv#l$~=jXya;)!Wo%zHVri&<^U}CX8VdpoALBx;6vUD; zR^Rw4Mh&5)FG@1<8(~(bGO-o8^JEhEyuX7B3bpt(Uj%A$rHQixI3{@)pP@1Umm}M{ z`2}do7p-q)a#Io*ZjtrRm?~o6YUT8kRV^ui&NKxo*ny8qEe1TWT&Ag+=Y;`wJY4U+ zz{8dI!8$E2>C~LQ3e>}j>SpirF++AP^?e!v7Onk<5XC=?C^it!vQsB$U4@5ZWVFK0 zbbtEgKM;5e7XVUcwShm@UnUm#BKrlM5E8g0S-u{;J!l~-M%+1qif0#JX$UA8hd_FE zOVfh1FBo5|A#57EdOpP#Y0?&)&|nN4XC5FixyuV&V)wNBZtO=}t{1@UZv{=G=uxx{ zm(0QM&uR9W0j_tD>t`D1M&sp0hX4!{^4Wh@{Y{?cZc0Wjk7MIOE+(l31}%*>9<A%` zzKfv|>TwwZ`IhvDN({REMCmZo`Wfhjpo+c}CN&!@H#USJFy8lu&0;*GVZ|7(=+m>~ z^|}qO7)nC<Xxb&O-Blf%!JGHeAzBZ4pRzHjQDJ)a-8Idy`#06Jv22(6a@IkL43GMV zi1muolOv(0RbbL1M=Gr9=sd>0ZCy_nNP%cw*Hf{eg#W}KaboQ?O^BjYW(h<qr(NOp z^~_=4C&=h!CeEs$%0|2=(O?MXpeqlU)HvZt5ZgNSYM29w-4S{1F(=_<!v5*ehKOMz z666#*l>C|N-rBy_Ml9ia!)Ft|GF+B58JzT(&A#*H%@X?`Rmmq?gGWJxR9-xzI5c)& zt=*7!@Vh%`6s`?B+JV3&sYOUrDaf~SuZv`ZdFWSOhF{7E@p$3d=m(b|JWkW`TXzhl zK6kqxa2koV?H1u0MN3_#E3@*N_Q=fY9ef0)+J}sb1^!&*`5f>d>spZY>V)WZ=4v*q zbASZz6%ZMZVaUp+WbvYoU62$it?7M;rw>!CWzU->Oxh!!&#mQm2cd0I)O@XO8xvyP zKQlZgeXFS$LTH^sF=@NJcSo!mLS=5z`t46Q*4KVU0Pu3aZ&x!N>}OQgJZh0-Fvc7s zik|R0TI=3&PGGE%PQ*ub$q<Xpf>Z}--5P;R<3;`Pb0Yy`7<p<fCdWhaT0Z&Cq&o=c zj~?Z$Oka&%AG-#K9QDZQ3!ycPGQl+<HARrl;Z?Yn5@_ClU;}$P7M9yhL}&vbfJNwp zd?2lsK-%hvf{8m{Lz|#cVTQ7Rp>D%%av@i!tlvjROl(&Ie#2b!q5fCE&(VkE5%LiK zm@1PJ<|9_6Sn22h`m@Vr@}rkDI2qpDngO77b(2;d=d%iXAV&5)2kRiYM(YCP+j|}O zSP}e8mcztZOv$Xx8HZ}YAoUZ^<9U5IEAfum;a4UnJ3}5oVC)`R3Ha9DX;N8b(}!@m z0z4FP$2dsw)G$P{C3`^f6!sl(Q8Du9%GX{@?s+Py^Ihe0iF#h#uPA!5CygODFPk%c zO#!Ry!~CH3xNVxG0Y0bk9o<*~9M>}JtS$slQyYr1IDQ5qR0Q*W+8ivylzF@jBvM<H z>(5uu;*TH^lY*LCj-oCRi%wxg<#OYKKkVXlu0kjSo`QSMFsY|Lahe6F$Ao4%j3aBm zWhr=1Q)o#FXix=S1tD19FX3MKb@2Z6$C_a#UQ$a;k}4p)KIsi$Jq<Bq?h_V7b5cv= z$1se$mNiRHJp<R4u9VaXDo!?w%ChXV#DnWEMS{jDG<%z0^4r&MeN6V{g)c^Qjaa{J z43*>nqWppI>w20hbZ{g&wDLmw)p}K!$mSxX?aqtMmX$zKn)ZAdJD`}~-I6&~`sLUf zh(FQgGHep!sZPPAYvDXtq_Ykr55EE~Ns)2lamrq%FC4x#xeov&v{N$}cEW&go@?=1 zexK(vWT7#JI>P%7dlg!SW@=bS_x2*zf>MfCw1Xg4pgb&vsr~@`GKtm~A11u_<gJ{m z)x%!so2ZD7r(27dqgLxC1N;L!`4>{SE~8o!7DsRd6%H|lDWM}tdft>9J}~)KH*qZP z$dXG9x;|uln!+D_*Yl_OhW$Gw9w-SEBgoi$7j)o*-fGo*5yC#fYRHz}12#7Q6So_x za(i<?CQjjq{QOJLv0)BuZQ?gL+`dZT7MH)d2KE8B>=M}V=CMTu;>!3tS4K)bRpgDO zVAP5Nl4v(B#=pwhIvub74%q3v91I4y)*#D<#z8o(dU76A<9exf<zc-+K}jo1c^SLo zDk@PvGOyOa&RaM(MQVsgZ~9{MYanUR!?LRottv=f%ZeO{NGngq966NHJ?xtg43)x< zyuZ|A`?TLe5boB+RSn}|oFi)4>zpAGh#Afjd6oIgbmgJY6gWth+nt7m+?YyAz`Yrs z4PhoUzTuK$m}6;SP;<QRQRV<1=XLgMCx)Gti?|>tMt2Mqw#7J@r^eh9;Y#9a!q`o6 zt9~Iig6`crYB+`L6=q6Or-PzbSP>55NZ=uXf`ojj#Nk#~nVrl=A}_e13`5B|s?tp| zE?<FxR9(l7B%Rb9*@YC-9OUppOsvM;>c(Zm6^L#^Gl4<C+oQ{G1u*H4&@t*BLDUDi z>mZ}qq+7c;QP={(#UT@akn2L8qg(=cn^<(SxnAy84lotmRp>-gaU&e$kW?~zMpe>x z_(_3Su3*^9@&{W0k(9DFPs?_vEA>d#H&Id`6C{J~j3Ep3M)CU-np?AEjonI)wHbv| zYZ%cXHR>}_(|71^4n4^V_T`n1iSsJEt6)q@5*_+hspvg-^|Ln`1e{1Ee00YHE~)U) z;VEgv{TDc<;*8=1s$_;m*=3U=Afm$im-MP`*^cu19Ut(rszN#!lEC8sy*Z5IaiT5= zxygUDZ#<Zf9(y=z+FFD6P3#k%M7@f+XGcU(kT53-dpywTlpS?_+&WU6MdB)D-*r3S zhCQYB%RQOdXE{MBX+`2jtc6|5qD4`E+X+&*P5my)*I5*aQoM~2#&NP?v2Lf4WhV&u z%qKhW>h@!wQNqR!5a5e<M?Bt;Q#f`sz?bZG&rjp_{&)tjnhy9{B{RK(s97bWK`K9~ z^%rn9>$<EIu77xx=>Vb3>@14*z;+}tg?tM%X4ro-G|3zDd}VkWg~Y>$T-<sBvmkkZ zcNh7UgtRP=HL}mlK$bRulLaEjP)5XOxE0!*8!&cT$il3jt~6EZNo>!>xOR_Sg>`NS zb_e^1X6a9X`r7?<AVr?IamGO?w=gdqA?N4Ixb+WP%pSbdSe6=Ml=_WmW>)YGpwLxa zj@BkFlMfFD$|Q62kHx3idV)Pll)I&>q(Ha_Dy<h$*l5E93<|={(3cAt{uAE!77JQQ zbYLPR+G9l(*XX%VNtE;}d1bN2)#?*(qICFv*Dj=QcS!0R<FU)qFprUNK+LEB2F5+| znoqW>e}-RMN1_!8W4U)5jmz<&*)#(dNUee=vizulR1ojM^5;Td5O23;EH}YbZ-=LT znRK|qO4Vrob+VE5Z-QbrW&zSJJodnAIK&!)Y9&)P+l0SVA-W*dYLV9HW`R39UVmD1 z_<I+#`HweH59>LH1h6i^Uo6~A-VvL?>7|k;P}LgCp(_18W>YV}nsK7#oJ~v598H7N zinuM&J%t@3UHsJxO)68wr|}p#z&4G*^!{z}_BLt$T`V^)#8aZG&wnh?91QQGm@=A# z_bL&XMK+#K9sfWKKJYw+O!1{K$#0<V!sT;`{=gN`F5>}tk^HMnu~Fc0LG~0jjI!@G z2uVu_kk=s9<HFSc$FG7KU{#M|%;pAc%~LN{@R8o)LL?w}`tO1#kPe2L+;gB{jfv;% zjo{H0usaWU{V=>+>I**nVN#y`Eyn6M2mel>h_DQoRKcLMFiSPYKh=PNhuZIar({yQ z4gN}CD*lVT!oUX;sPo;~ux?_SCH;Cd0aMD8m!PUQZC0R6YP9eaN@)EMNQWsybt=8X zeh}UGO!<%KLXwL_5{f-@@^(6AFYISW#7bG)$7rI$B@A9{#lQ@3%P7zG&nboy5=|*+ zP%puD-}IllEJFgC!^NPXoG1#OTK~BOZJ%p55d{-Z*d;kw0o34tAut$jqlMrdyH6F` z{qX<*q`LRuP;<r-OqdroC6f|XVL}FNfu9Nqpxh}?nwzHBPsw!Pff%D-mj=#IlJBud zA1RjzP?88UKrk$r;7qVdC+~B}QU(yjQ7B`bLpC5$^XYg&fyB4!O<#-4k3f7#yH?=H zMT$Xrd8!$a%>)yL3<a%LT<|A4f2#iy67UIqXV>(boUm07t<hD$^HqgL-^7Z-2u`2s zEBpRM!M8B8qYMSi=T{i>c?tSd_0K$c3<mLO!M!K1wd6DBAzB<WrOW3bcm0fDsPEf7 z(R}!i#gNTJg2xNGj1>OG+FT^fmjMIlHk@DZ@}CbaRMHKMqGnQ4H20ZiR4oL&wTw{L z{Htojfc9mOj=6x_pYAVXk3k$)z*_?*Sp|xiYW?{QfXSn2aC#qkUNRl#tu}eh1We2S z{0cB;DDv3N^^7-z-^a|Hkf;KXlIY)iPcVKKw}X|%^OD^_vgE=mG@6=ZXUt(fH)!he z&!KOBy$zu7WsnY8i%zhhfaSay2B4_}bER4Te5qh9{BH;SZwH-8RR8~-L9Yyqch<h= zA@BD8H)UlRq>Ojp+zY#xbHWbS)J-2vJzqHlm{h<y&&$HkqW-{IxOr2}omlIkQeoQp zQVEqL00%@)X55qiWZ<qCKZv&X`^xj>bADQ!FP1(zz~CFK<@BBJ9of&p@*%kXQ0||T z^&;s5DzL;{KO`w~oGqwWEU=(%TeDE8pY1OU24JV?8!%)q{vS2}-wOS25B*zY|L4x3 zf-ysk+vvDhzqXId04d;TbKiAwYDni_1p9VLDFwsVk01V@07?M0|LL%nN3n9bF<!B} z#aP;OSo=TwSoVoq`T2?#?@v1r0THlYYJ0oBt=7)}M*VM9P(&cb1pXh5cn!23s3r&i O0000<MNUMnLSTYoL^L1( literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/_static/openfastlogo.jpg b/OpenFAST/docs/_static/openfastlogo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e5f5209117e1985732c0ae0794f4a20286d6435e GIT binary patch literal 8355 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/conf.py b/OpenFAST/docs/conf.py new file mode 100644 index 000000000..709302a58 --- /dev/null +++ b/OpenFAST/docs/conf.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- +# +# OpenFAST documentation build configuration file, created by +# sphinx-quickstart on Wed Jan 25 13:52:07 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys +import subprocess +import re + +#sys.path.append(os.path.abspath('_extensions/')) + +readTheDocs = os.environ.get('READTHEDOCS', None) == 'True' +builddir = sys.argv[-1] +sourcedir = sys.argv[-2] + +# Use this to turn Doxygen on or off +useDoxygen = True + +# This function was adapted from https://gitlab.kitware.com/cmb/smtk +# Only run when on readthedocs +def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): + dx = open(os.path.join(sourcedir, doxyfileIn), 'r') + cfg = dx.read() + srcdir = os.path.abspath(os.path.join(os.getcwd(), '..')) + bindir = srcdir + c2 = re.sub('@CMAKE_SOURCE_DIR@', srcdir, re.sub('@CMAKE_BINARY_DIR@', bindir, cfg)) + doxname = os.path.join(sourcedir, doxyfileOut) + dox = open(doxname, 'w') + print(c2, file=dox) + dox.close() + print("Running Doxygen on {}".format(doxyfileOut)) + doxproc = subprocess.call(('doxygen', doxname)) + +if readTheDocs and useDoxygen: + runDoxygen(sourcedir, 'Doxyfile.in', 'Doxyfile') + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.5.2' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.mathjax', + 'sphinx.ext.intersphinx', + 'sphinxcontrib.doxylink', + 'sphinxcontrib.bibtex', +] + +autodoc_default_flags = [ + 'members', + 'show-inheritance', + 'undoc-members' +] + +autoclass_content = 'both' + +mathjax_path = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' + +# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs +if useDoxygen: + if readTheDocs: + doxylink = { + 'openfast': ( + os.path.join(builddir, '..', '..', 'openfast.tag'), + os.path.join('html') + ) + } + else: + doxylink = { + 'openfast': ( + os.path.join(builddir, '..', 'openfast.tag'), + os.path.join('html') + ) + } + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ['.rst'] + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'OpenFAST' +copyright = u'2021, National Renewable Energy Laboratory' +author = u'OpenFAST Team' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'2.5' +# The full version, including alpha/beta/rc tags. +release = u'v2.5.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +#If true, figures, tables and code-blocks are automatically numbered if they +#have a caption. At same time, the numref role is enabled. For now, it works +#only with the HTML builder and LaTeX builder. Default is False. +numfig = True + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs +if useDoxygen: + if readTheDocs: + html_extra_path = [os.path.join(builddir, '..', '..', 'doxygen')] + else: + html_extra_path = [os.path.join(builddir, '..', 'doxygen')] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' +html_logo = '_static/openfastlogo.jpg' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + "analytics_id": "UA-68999653-10" +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Openfastdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ( + master_doc, + 'Openfast.tex', + u'OpenFAST Documentation', + u'National Renewable Energy Laboratory', + 'manual' + ), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ( + master_doc, + 'openfast', + u'OpenFAST Documentation', + [author], + 1 + ) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + master_doc, + 'OpenFAST', + u'OpenFAST Documentation', + author, + 'OpenFAST', + 'One line description of project.', + 'Miscellaneous' + ), +] + +def setup(app): + app.add_css_file('css/math_eq.css') + app.add_object_type( + "confval", + "confval", + objname="input file parameter", + indextemplate="pair: %s; input file parameter" + ) + app.add_object_type( + "cmakeval", + "cmakeval", + objname="CMake configuration value", + indextemplate="pair: %s; CMake configuration" + ) + diff --git a/OpenFAST/docs/index.rst b/OpenFAST/docs/index.rst new file mode 100644 index 000000000..0b5f130b8 --- /dev/null +++ b/OpenFAST/docs/index.rst @@ -0,0 +1,59 @@ +.. OpenFAST documentation master file, created by + sphinx-quickstart on Wed Jan 25 13:52:07 2017. + +OpenFAST Documentation +====================== + +.. only:: html + + :Version: |release| + :Date: |today| + +OpenFAST is a multi-physics, multi-fidelity tool for simulating the coupled +dynamic response of wind turbines. Practically speaking, OpenFAST is the +framework (or "glue code") that couples computational modules for +aerodynamics, hydrodynamics for offshore structures, control and electrical +system (servo) dynamics, and structural dynamics to enable coupled nonlinear +aero-hydro-servo-elastic simulation in the time domain. OpenFAST enables the +analysis of a range of wind turbine configurations, including two- or +three-blade horizontal-axis rotor, pitch or stall regulation, rigid or +teetering hub, upwind or downwind rotor, and lattice or tubular tower. +The wind turbine can be modeled on land or offshore on fixed-bottom or floating +substructures. + +Established in 2017, OpenFAST is an open-source software package +that builds on FAST v8 (see :ref:`fast_to_openfast`). The glue code +and underlying modules are mostly written in Fortran +(adhering to the 2003 standard), and modules can also be written in C or +C++. It was created with the goal of being a community model developed +and used by research laboratories, academia, and industry. It is +managed by a dedicated team at the National Renewable Energy Lab. +Our objective is to ensure that OpenFAST is well tested, well +documented, and self-sustaining software. To that end, we are continually +improving the documentation and test coverage for existing code, and we +expect that new capabilities will include adequate testing and +documentation. If you'd like to contribute, see the +:ref:`dev_guide` and any open GitHub issues with the +`Help Wanted <https://github.com/OpenFAST/openfast/issues?q=is%3Aopen+is%3Aissue+label%3A"Help+wanted">`_ +tag. + +The following links provide more insight into OpenFAST as a software +package: + +- `OpenFAST Github Organization <https://github.com/OpenFAST>`_ +- `Github Repository <https://github.com/OpenFAST/OpenFAST>`_ + +**Documentation Directory** + +.. toctree:: + :numbered: + :maxdepth: 2 + + source/this_doc.rst + source/install/index.rst + source/testing/index.rst + source/user/index.rst + source/dev/index.rst + source/license.rst + source/help.rst + source/acknowledgements.rst diff --git a/OpenFAST/docs/requirements.txt b/OpenFAST/docs/requirements.txt new file mode 100644 index 000000000..0d73b5867 --- /dev/null +++ b/OpenFAST/docs/requirements.txt @@ -0,0 +1,9 @@ +breathe>=4.4 +docutils>=0.13 +Pygments>=2.2 +pyparsing>=2.1 +Sphinx>=1.8.5 +sphinxcontrib-bibtex>=0.3.3,<2.0.0 +sphinxcontrib-doxylink>=1.3 +sphinx_rtd_theme>=0.3 +requests[security] diff --git a/OpenFAST/docs/source/acknowledgements.rst b/OpenFAST/docs/source/acknowledgements.rst new file mode 100644 index 000000000..dedd7a58b --- /dev/null +++ b/OpenFAST/docs/source/acknowledgements.rst @@ -0,0 +1,18 @@ +.. _acknowledgements: + +Acknowledgements +================ + +This software is developed and maintained by researchers at the +`National Renewable Energy Laboratory <https://www.nrel.gov>`_ with funding +from U.S. Department of Energy Wind Energy Technology Office through the +`Atmosphere to electrons (A2e) <https://a2e.energy.gov>`_ research initiative. + +NREL gratefully acknowledges development contributions from the following +organizations: + +- Envision Energy USA, Ltd +- Brigham Young University + +NREL gratefully acknowledges additional development support through designation +as an `Intel® Parallel Computing Center (IPCC) <https://software.intel.com/en-us/ipcc>`_. diff --git a/OpenFAST/docs/source/dev/build_doc.rst b/OpenFAST/docs/source/dev/build_doc.rst new file mode 100644 index 000000000..91fcc2d98 --- /dev/null +++ b/OpenFAST/docs/source/dev/build_doc.rst @@ -0,0 +1,102 @@ +.. _build_doc: + +Developing Documentation +======================== +OpenFAST documentation is hosted on +`readthedocs <http://openfast.readthedocs.io/>`_. It is automatically generated +through the ``readthedocs`` build system from both the ``master`` and ``dev`` +branches whenever new commits are added. This documentation uses the +`restructured text <http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ +markup language. + +Building this documentation locally +----------------------------------- +The documentation is compiled with `Sphinx <http://sphinx-doc.org>`__, which is +a Python based tool. Install it and the other required Python packages listed +in ``openfast/docs/requirements.txt`` with ``pip`` or another Python package +manager. + +These additional packages are optional and are not included in the requirements +file: + +- `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`__ +- `Doxylink <https://pythonhosted.org/sphinxcontrib-doxylink/>`__ +- `Graphviz <http://www.graphviz.org>`__ +- `LaTeX <https://www.latex-project.org>`__ + +Doxygen and Graphviz can be installed directly from their website or with a +package manager like ``brew``, ``yum``, or ``apt``. + +The result of building the documentation locally will be a set of +HTML files and their accompanying required files. The main HTML file +will exist ``openfast/build/docs/html/index.html``. This file can +be opened with any browser to view and navigate the locally-generated +documentation as if it were any other web site. + +Pure python build +~~~~~~~~~~~~~~~~~ +If CMake and Make are not available on your system, the documentation can +be generated directly with `sphinx`. + +.. note:: + + This method does not generate the API documentation through Doxygen. + +First, align your directory structure to the standard OpenFAST build by +creating a directory at ``openfast/build``. Then, move into +``openfast/build`` and run this command: + +.. code-block:: bash + + # sphinx-build -b <builder-name> <source-directory> <output-directory> + sphinx-build -b html ../docs ./docs/html + +If this completes successfully, an html file will be created at +``build/docs/html/index.html`` which can be opened with any web browser. + +Building with CMake and Make +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the OpenFAST directory, create a ``build`` directory and move into it. +Then, run CMake with this flag: ``-DBUILD_DOCUMENTATION=ON``. CMake will +configure the build system with the necessary files for building +the documentation. + +Next, run the command to compile the docs: + +.. code-block:: bash + + make docs + +This will first build the Doxygen API documentation and then the Sphinx +documentation. If this completes successfully, a html file will be +created at ``build/docs/html/index.html`` which can be opened with any web +browser. + +The full procedure for configuring and building the documentation is: + +.. code-block:: bash + + mkdir build + cd build + cmake .. -DBUILD_DOCUMENTATION=ON + make docs + +If any modifications are made to the source files in ``openfast/docs/source``, +you can simply update the html files by executing the ``make`` command again. + +The table below lists make-targets related to the documentation. + +======================= ================== ======================================== + Target Command Output location +======================= ================== ======================================== + Full docs make docs openfast/build/docs/html/index.html + Full docs make sphinx openfast/build/docs/html/index.html + Doxygen API Reference make doxygen + HTML only make sphinx-html openfast/build/docs/html/index.html + PDF only make sphinx-pdf openfast/build/docs/latex/Openfast.pdf +======================= ================== ======================================== + +Adding documentation +-------------------- + +Coming soon. Feel like contributing? Start here! diff --git a/OpenFAST/docs/source/dev/code_style.rst b/OpenFAST/docs/source/dev/code_style.rst new file mode 100644 index 000000000..eac515713 --- /dev/null +++ b/OpenFAST/docs/source/dev/code_style.rst @@ -0,0 +1,15 @@ +.. _code_style: + +Code Style +~~~~~~~~~~ +OpenFAST and its underlying modules are mostly written in Fortran adhering to +the 2003 standard, but modules can be written in C or C++. The +`NWTC Programmer's Handbook <https://nwtc.nrel.gov/system/files/ProgrammingHandbook_Mod20130717.pdf>`__ +is the definitive reference for all questions related to working with the +FAST Framework and adding code to OpenFAST. + +Generally, code should be written such that it is straightforward to read. +Syntactic sugar or brevity should not detract from readability. The exception +to this is in situations where performance requires poorly readable code. +Here, comment blocks should be used to describe what is not readily apparent +in the code. Indentation is typically three spaces and no tabs. diff --git a/OpenFAST/docs/source/dev/debugging.rst b/OpenFAST/docs/source/dev/debugging.rst new file mode 100644 index 000000000..807c72674 --- /dev/null +++ b/OpenFAST/docs/source/dev/debugging.rst @@ -0,0 +1,103 @@ +.. _debugging: + +Debugging OpenFAST +================== + +Being a Fortran project, OpenFAST can be challenging to debug and the process +is unique for each system and environment. Keep in mind that some OpenFAST +cases can be quite large in their memory footprint and may take a long time +to reach the point of interest in the code. Choosing a test case carefully +could save a significant amount time. + +It may by helpful to write a small fortran program to verify that all +debugging tools are set up properly before diving in to OpenFAST. Be sure to +simulate a bug by doing something like accessing an array element that is not +allocated and verify that you can catch the bug with a given set of tools. + +.. note:: + + A requirement for all systems is to compile OpenFAST in **debug** mode. + +.. _debugging_windows: + +Debugging on Windows +-------------------- +Windows developers using Intel tools can use Visual Studio solution included in +the OpenFAST repository for debugging. This is a straightforward process with +lots of support from Intel. + +Otherwise, Windows developers compiling in Unix-style environments should +proceed to :ref:`debugging_linux`. + +.. _debugging_linux: + +Debugging on Linux and macOS +---------------------------- +First, compile OpenFAST in debug mode by setting ``CMAKE_BUILD_TYPE`` to +"Debug". This can be done on the command line with: + +.. code-block:: bash + + cmake .. -D CMAKE_BUILD_TYPE=Debug + +or by using ``ccmake`` to open the command line cmake gui to change it. + +The GNU debugger, ``gdb``, works well for debugging compiled code. It has a +comprehensive command line interface which enables developers to add +breakpoints and inspect variables. + +Driving the debugger through an IDE can make inspecting the code much more +efficient. One IDE known to work well is `Visual Studio Code <https://code.visualstudio.com>`__ +with the `Native Debug <https://marketplace.visualstudio.com/items?itemName=webfreak.debug>`__ +extension. You can set up a `launch configuration <https://code.visualstudio.com/docs/editor/debugging#_launch-configurations>`__ +so that you can debug a particular OpenFAST case through the IDE. To do this, +open the launch configuration and add a block similar to this: + +.. code-block:: json + + { + "name": "AOC_WSt", + "type": "gdb", + "request": "launch", + "printCalls": false, + "showDevDebugOutput": false, + "valuesFormatting": "prettyPrinters", + "gdbpath": "gdb", + "target": "${workspaceRoot}/build/glue-codes/openfast/openfast", + "cwd": "${workspaceRoot}/build/reg_tests/glue-codes/openfast/AOC_WSt/", + "arguments": "${workspaceRoot}/build/reg_tests/glue-codes/openfast/AOC_WSt/AOC_WSt.fst", + } + +macOS-specific configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GDB on macOS needs some configuration before the system allows it to take +over a process. It is recommended that ``gdb`` be installed with homebrew + +.. code-block:: bash + + brew info gdb + brew install gdb + +After that completes, be sure to follow the caveats to finish the installation. +For ``gdb 8.2.1``, it looks like this: + +.. code-block:: bash + + ==> Caveats + gdb requires special privileges to access Mach ports. + You will need to codesign the binary. For instructions, see: + + https://sourceware.org/gdb/wiki/BuildingOnDarwin + + On 10.12 (Sierra) or later with SIP, you need to run this: + + echo "set startup-with-shell off" >> ~/.gdbinit + +For Native Debug on macOS, you have to sort of hack the extension to allow +breakpoints in fortran files by adding this line to ``.vscode/settings.json``: + +.. code-block:: json + + { + "debug.allowBreakpointsEverywhere": true + } diff --git a/OpenFAST/docs/source/dev/github_workflow.rst b/OpenFAST/docs/source/dev/github_workflow.rst new file mode 100644 index 000000000..8d690e087 --- /dev/null +++ b/OpenFAST/docs/source/dev/github_workflow.rst @@ -0,0 +1,117 @@ +.. _github_workflow: + +Working with OpenFAST on GitHub +=============================== +The majority of the collaboration and development for OpenFAST takes place +on the `GitHub repository <http://github.com/openfast/openfast>`__. There, +`issues <http://github.com/openfast/openfast/issues>`__ and +`pull requests <http://github.com/openfast/openfast/pulls>`__ +are discussed and new versions are released. It is the best mechanism for +engaging with the NREL OpenFAST team and other developers throughout +the OpenFAST community. + +Issues and work assignment +-------------------------- +Issues should be opened with proper documentation and data to fully describe +the problem or feature gap. It is here that communication and coordination +should happen regarding ongoing work for new development, and developers should +make clear any intention to complete a task. + +.. _pull_requests: + +Pull Requests +------------- +When a code modification is ready for review, a pull request should be +submitted along with all appropriate documentation and tests. An NREL OpenFAST +team member will assign a reviewer and work with the developer to have the +code merged into the main repository. + +New pull requests should contain the following: + +- A description of the need for modifications + + - If the pull request fixes a bug, + the accompanying GitHub issue should be referenced + +- A summary of the work implemented +- Regression test results + + - If all tests pass, the summary print out should be provided + - If any tests fail, an explanation of the failing + cases and supporting data like plots should be included + +- Updated unit tests, if applicable +- Updated documentation in applicable sections ready for compilation and + deployment to `readthedocs <http://openfast.readthedocs.io>`__. + +Git workflow and interacting with the main repository +----------------------------------------------------- +OpenFAST development should follow "Git Flow" when interacting with the github +repository. Git Flow is a well-defined and widely adopted workflow for using +git that outlines safe methods of pushing and pulling commits to a shared +repository. Maintaining Git Flow is critical to prevent remote changes from +blocking your local development. This workflow is detailed nicely +`here <http://nvie.com/posts/a-successful-git-branching-model>`__ +and the chart below provides a high level perspective. + +.. image:: ../../_static/GitFlowFeatureBranches.png + :width: 70% + :align: center + +Reference: http://nvie.com/posts/a-successful-git-branching-model + +OpenFAST Specific Git Flow +-------------------------- +It is important to consider how your current work will be affected by other +developer's commits and how your commits will affect other developers. +On public branches, avoid using +`git rebase <https://git-scm.com/book/en/v2/Git-Branching-Rebasing>`__ +and never `force push <https://git-scm.com/docs/git-push#git-push---force>`__. + +In OpenFAST development, the typical workflow follows this procedure: + +1. Fork the OpenFAST repository on GitHub + +2. Clone your new fork + +.. code-block:: bash + + git clone https://github.com/<youruser>/OpenFAST + +3. Add OpenFAST/OpenFAST as a remote named ``upstream`` + +.. code-block:: bash + + # This adds the remote + git remote add upstream https://github.com/OpenFAST/OpenFAST + + # This downloads all the info in the remote, but it doesnt change + # the local source code + git fetch --all + +4. Create a feature branch for active development starting from the OpenFAST + ``dev`` branch and check it out + +.. code-block:: bash + + git branch feature/a_great_feature upstream/dev + git checkout feature/a_great_feature + +5. Add new development on ``feature/a_great_feature`` + +.. code-block:: bash + + git add a_file.f90 + git commit -m "A message" + git push origin feature/a_great_feature + +6. Update your feature branch with ``upstream`` + +.. code-block:: bash + + git pull upstream dev + git push origin feature/a_great_feature + +7. Open a new `pull request <https://github.com/OpenFAST/openfast/compare>`__ + to merge ``<youruser>/OpenFAST/feature/a_great_feature`` into + ``OpenFAST/OpenFAST/dev`` diff --git a/OpenFAST/docs/source/dev/images/offshore_lapack.png b/OpenFAST/docs/source/dev/images/offshore_lapack.png new file mode 100644 index 0000000000000000000000000000000000000000..9aa9d2438f0096b74327d676333fab0029ba5168 GIT binary patch literal 1257083 zcmeFYXIv9q*FFj&VnIPsK|umGP!vQIqy_{<L7GT!(gdZ6^g19aRf1BzDG?D+Y0^bX zEc6zT5}HP8ga9$2Bq7PnnV|Rcy#L?%dcK@<UYBHMGJDVL*|YXq*Sgk9tf9X4?wyBs za&U0$zJ5*XCI<(v7zYQB^!9D=H&1$Md*Cm0?rLfpUf0wVGkoB6=dQam2gkM8R5KoP z<Bo$lRyVJ^MsB~hqcQg8Yuz2WSNM}ok8Hm#mfM`fueB)Mb^3$<UQXeUr(gZD<gk!h zuoV2fY$+P|Mw008`AKKyesdh_M+jaSuRsMAeR=_%xgW}05&F9gPWN2#<7`jf-#&Hh zvU&2&0rS_=5nBY*xj%l2X-n4~_4e-P=<H*WDC^tQQ>aDKI;B7_WY#aReKwRM=~9f` z)(7FD%{-i+bZIv&I61TsZ)$Ta#7w46@e8-#e#ozzdP(=GZptOir&1>Jv1E~$050_c za$v<7j;hSu9FunJLzS^wG5^%<&HFff+xdAYS5!EgpYfwQyE1c|`}SON3T;VVQ|L{w z*B6y>6Do2u+M#&sO!^$<4hy|R!#__i5{k3u;n6!DpI|o3%kY<Sxtg+XKx{eHsk!-b zF&{akT-}*ZR_DN}qsfEoZ%*0uMyhh%h_T^r=#z}m6W^0Q)2ijRdg#T}ed*@=k6&Jy z+T!`DHK5#3H0|YN@w1*7)R8YQ&hN3B9{-g5cIxz!fz*TNBZon&qv8QEkY2f@?3HY} zt7rF1w5b>GmNm{v=FhMB>>hU|D??oP#ZlWAnBC3cm#=HZ{Da6$JGBdi8|k9VXs$WL zUvcnE*k*PhX5X=kD)n>~6Ywg(!mbmGuf;`kLvOAcp50>an(@)U*hcdDx50Qnon4ow zE;g0DuJb+|l6AWKso_G2n0%_>N!L*Fr!61EhM0i~RbtXc*%CR=dV~>$y*x5o`Xjh5 zbMBJ-+0G%SF3(@PCcpN@ZsEoKPh97dxF3DGl6Q!5&8X+v&x@S<qmW|zw$R_(#oRO9 zzB3nGd2br#$NA#j=;c)HJ%PO5qA^?Qe%D@}J#i>8jaO9TDGkw2KZmovl;Q&omgk<d z%roL8SNJ|T6KmgW=x|&%>sL(X&&Ur*(cNXA?|+z9`#>_R0Y(Kx1(de)?ZEBGel$MN z67Pf`{0gg=L;`>5Tg7SOKi<mi3$f8ZIg=0%rf*Da{qWP#{<ys8R>zRbXSI{-DmJ|8 zAk(jAHn<TZ>r;}>TTf(6{Vpl2Nv<KBi?1lO3%Hi;)_UJg@v9uZl@K~~m$N}T%q{k8 z>z>;#<;f#Ki`$2{nvZxFAF6+J#AIsHWc6Bg+>=)=MU;+6l_{Wk`mV!i<x>GA0ZZPj z*Ev%B2T$Qq5ptSJx+i=09e6+TyGO>!`vkK;&wRPmvx!3zb8G=O=vJ`6h&U(1%<n>S zMtB{%b%&KdZNYV)Cd-jf3(ObWeQtB)=FlFe@3hFZjFytwO7r^`X^<j&j%WB2=kWBN zh6v>LZT7cSVz^_)4%~>cIrw?)442$zk@x&54<EeWQp{~~TVQ0T|3lT=NY^depRWIw z`mlZMv)_H5(j3p<BCC<Lw>dQU_g&T&ijj4Q968z>qdXP0^{D-|3;R&7kIr8^cvNG5 zyU2|4YY~gbx5TZIlxAFJ&OO+ti1HPyea3T*kFt{<;~=^FqI!>^vM=vKR7Jn!g}vEv zcXH{jvX&2}HKqD3eHF%Ha<pV#;rjJg6~|DVH+DHXq-E@yi}HSNer9)9v(t!5F>leQ zd*$1Txk0R1xqh)ABSOG?TkjW}pF0zqlkcnLps-)lr%Y)24SSJK?OG5&!)StAvTy6$ zKS|sB;nDR+XTIFHd@A?h`|SHM_qVC(eScJ|b@bWwDv98)g|ev`dRcnbIuq&>x+)rr zV*Yy>*N;D!?Rc?YJ?;eg8u#m)--5q+e)Ilz;HJX7sztoJhQCB~@<97O%FzehL4tH4 z`cC?epomwx<@q!thf`ZR&vZWMl-Jocdp<w&y!ueym@(Iz*g^M&%lA%HM+QF$PT#Q9 z)$P*hGIM*CX6_bgnm?>o;$z8IrPjB4SO3BukDYoNR#(S0lr`%0Li7p;mVSL+y%5Y9 zcBnBiJT4p!+GggeT4olV?aL{%Df#{;><Z)Yo-1vp(Is+vh318q2@$={*|s)urP<Qj z>4nM$wU*TP%X;6#RiET!+7{d9{J7a@6HHjkSx8=8TK&4py>Vj0YRzCiK=#~|i&0;H z$~8H<J7(GY3iIz?-2GwO=(gEyA-rR}8@y|~+YX-;K6uDfSoGqelfw<=lj$$Ita~T0 z4WF5pzPN7<d33+|`QF{fN)rNIE_{<5x#oK7P8IIg$9`?cH17=WM6%BG$?1@jA7Ya` zw31((6xQp_SWUbjG>?3atZ<(JpJ6gz73dd`3o7+$|FJ#4q#&mde=hl-5(Q=FVYl83 zeDYX%JIC<uhPH?HdtJqA%pJWarVe!_wcMGlIBijA5tdev_AG5@*V#0WG%nM1)9a@3 z#p{;eD+??c<}Q|H<(}2cmF4eW+?H!A_%Rn?6<2~PY4^`wvKSBWU-v)dj~ux;s#>j3 zK^PMp$BpCtUMg=@oKYTBvi3Qyv~g+flIMN*fXmq`*;@KT`svw5E;26VE87T(Mvsh| z@{Z@-)Bf(8Tld~(r_F+mXu_SuMA1f9-+^C(j_$3mpIRu+EoR7+=9Jczj$4yH%-25+ zu$md3TJQYckxjB)3h#+p-n%S|&l{bdH7AsRDHm@0L2(My|IPedIkZxlUYp)s^tq^Q zyjA&oeJi5?6={%#y@~c|+KT7L)0?zIk+dNC0ooFkF@SGDwgKtTfcN_Jqv@Kb#GUVV z{^WMw@r&1qyMV`Y&mwOH?-cjYHdWr5JqNdX@r8f!cXFu=sI+_Z;Ys`DJ&zlvY2I@W z^dC9o?#*@1^|0Ttziw}0PyJf*rSc2$E90oju{+vXF~_y8UMWpz=(spdsq>p?BLA2s zBqEPoiPwpF7Z)tFwEt|p=Zgq^A*B7<qk7pI+2<Jr=KNhxZH|P<^r}fCm(ydLW4#56 zB-9cE;?V+teB`rps`h4I#+#FxXJZ4Ni#*?dy`)2_!}vMzIX?eUL9xz!)`dIYCawz_ z>)mX5+jIAI)lAjWT~_kflV#Zxsx3Y`^C`l{ON9sZRFOSSmdjOn1AYZ71&C`BuM1z3 zbfD(=*&)h?+=oLK4~2#90gga*V&?C!_8sHpFWsls!P{<~O1~f_=H_RLlDu|HeBppk zv&mHY=(Ewx3jA#I++zEoZoQ80ncBU&SmiVQ=`+{#vFFf67xFY0&YVs4pJU9H^^lUU zbkub1rQZtjiR7GkZ+G*OWRsbSB=4DG=}@Fx&|Kuv#-rE!^DXo%)4GFiir6v-+(YF7 zf1*g2;x2+pMpsU~v*>vlM_Xbjk$z&OUQp}INL|v$b1su!@z#PRmaB91DI`msZk>ZE zzF`P*SlC<tx5cY-d?3=@GC}5`jHlI9xfAQTjPt{aU9+XL2WHV}lyqBK|595gf+yWs z+RbXYI&^yH)Xt7LVW}w7W$XOfcY!9jg&jr0xc9>;B|(+`8)GX69Hrz-@=A@1iNy(} z?zUc);Vl~mCa>NRhs1|M+-|s~4K|F6jof#3{N4IQ?@nf?LfFKaAE9o#&1tQc^<!}* z%_Wbm5MH`J{MRMW=!Ke0cNshw6z!x<=%r;B5*vsM{x6m-ZBfHg3nBgnqu-k(d<}e} zbibxGb~ny4KB=`dxgZOnP)A@89OhEvIlN~~v{<qE(yif`3%&Oi-S%DdlP{DH5D^7F zRJUMe`(*NfQSWBTwKb!!d0i+YRH}%uifw2E^k`L!)KQ#lQ!-#h%KFE5VQfCOaJ*M5 zTaoHUD=X}+z=|RT?=QCpVOFALXx6SDfBBV@pA+&mF+rgJo1UT)as_pE&L6*?mgs$? zt#qr6V$j9ag)-a+oU|>f?uYlW`PPz5V^9Ad`zC^em8t7p_+0?vL*-BDNzYN$?;!`M zdL$g!MYao3Zd5|4Z4bLYZ~x`1vJJD8fSN(6`K7BAAWH)s$gh{*G6s&RPO2_pPa=uo z(qU?SRvXbj5Eo@cY(<!IG^}n|^2SHIPTM_AmK$TVwL}F+eARl}8Xm}``v0^U4Vk7Y zBWa<R7_zg|$&oM6*U+bt%Hf{$eQUGJw}1S6nIbX$wq}cvi0hq`9A*9->IRQPqWwAE zBo7f(QpFZ3-|mcr9u2u@qy}=nKPD9MnwvxGt7_-fOYY(YpX(nK<p}W_@}VYk_XZV2 z*Z&j0%|PW5H7csCheNEI<F|$UrAzPa@Bdzr&sg-}(4Q&7rt64*sr-D$<Af5v#+Q?J z72F+M1gPA3wKoS2E_U3%X5quZaqtBDkMsJ?<G(pLIMH`+nfsdS-B5D$@{qQ7@^WyN z4)nMWx8~qb2~>i2J)C{*#R5ItJ$;k{RgZ4AP=fc_U&|a7+ic?Nrh3#|&rnR$>w&Y_ zMd=ID=Z>oF6cZCudEj(M>894zzun;@)uXPyzW0@6WC8*Lqyyxny&ky8$SNu-%A7kd zbN>8UxW!qYAWvWWz_Xq{$NpU8-|J{O`#3(hd*Ao2m!}x}y7mrUe!i+lkFsy{pMQVG z=^S|XzjyNV`TJP#1In<^$jC~clljlJ;jSv|Z<P%120FW&Yu)v5_Vj`8p(ZDL?t;o@ zhyUBD|K9R{bhY?zSJ_K)m;Pth|8eSXR}~rdBm9p?`ZHgf-@+57wo^ssKa;PvbBDRQ z5d1zw?rIs_g11}PFNcGJD;@rj{IiAkckx%C_57zfIMg|=YiZmH<Xmj@==OKB#04y= zhH%Mo@g8l;J-1)T>Yl@uw|Dzrzy4?c*&CU+i>^D0jK7|*4S%ioPsWA2KOK?sPY+l* z9=m%k*D-$V<Q2D)ize4fYPh)%Z4HgwD<pL14)#Yq!7H0evL!UG`(f0mmFRSq@|{vf zC=yi-5(8Ds{FVs5ahJum{_p?)oq_+If&U-Pz|Y3GPg2vZboH`c2RCB?|1I3(tujh_ zVcCA3_L0X2$I5c+_(1$+h5MF>+^$#L5-aZ~Tjd+tl2kXzx0BSoYeLLBuhBtUna-6v zV=$WG`WpDPBcm9x<~k()yAzD~Vp81vG~C;`)wH1kDVD-Al0SKP6upR5UW)ZU&ZuXI ztU6a0j@jt8w&)$PBDeq=l8hqv8y6}tqxi)#`N5mY|3IT*d)6J+BpjSOK78n}g>MCM zU8W<P9bY|zGz<pCbvJLN0~HL$3|O8&>bY7r(%%b47_Mu>qj3WIl1)&ip{7T+lr3UY z{yAn_mAi;-);MH2dx8;iAak@6bOI_c+9B_b^gxShf+6K&1IO+p#9OTgIFwJNLK>Ij zprNO+S3w0R6H?vS$7=7I0*2N)`L{<3^MB&k6926t{_@7nCRMc*FPoI%-44H^7ttk$ zX3Ep}nlB-!m3VoEQ9AaG?F%nV=oE0k$D32(no5fzv#c}u!*M`BaQ2F-<`dJfYCA<; z=o`{m!$RZg@!9LDU7+=lgm(u#w!YnKSCr#L`^!Q{%6grFN=)a&isvlu*y{_){s)Uq z!z%1p51N8orHP@878RB*l)~+Ng2lx?9lXu7NNp4i>RC7IDs#n2*{)0Zz%!4kcv<WO zs5?C0c%98zWCFhm_%2DiX5qW+FQGUf!v-rcqjvB}I>3j`$Jeea@7lZ!s|P$P*ctDC z@Ra3jOZY|whK^=>fo4`OOWGm0-O}4|cr+pR0C=L}ttDkPEMB{&3Nq%qpgCX#L$~vY ztT_tp+Lv5axMA_$a_KFLj;H28Yok(9sp7x8`9Dcs5&u21UF1m4^{;-d*l?~cg*NVz zinl9HS+eck!{7Lf0+uaX0RxKs%RRssV9Rr+9_u>f&v@wMs#}2^#WS&0sdRj-CRv+o zMkbW*+UTr414@HewY%jCsuqDI8Tg>pGX+QigzOwnte%*)W6OZoJH+g!7)$hVhqYLy z!425*!bRV$9ID1JE13cqBhUi88~QZ$T$&_w29~UFW7gk2B_ptop%Zq}nH~TOH69IQ zN*K7|@UV992d3}+i9WRQa?kKK^wz_mfYYinN~tPQG2nZfx9%KmRQ>~Px+y_}jJ^~z z@BSF`pkm72ruaFA_0p)Z@)mVau3W&3F@T9pIPced*TX8nlakJStG$qYf)$=3+__pt zbF3B~#lJl=cFXUIs>S$lcKy_w9~SRIQl#q2Sd+;9y~gGH3adT7*G-}!W7MFs?gmRz zA*C~w_ze@gCotxF+<-`<(%i(V49ggma)f<Wv&gzmnw9x0B6_6cQcr)8W3L{pl55vS z%U|PB=d1qT-?i{9Kq=vkgkO&GvG<3456*8r=b3P%&7;ict!A+e&M*MkcFOGQe0X<M z76K|Vk3$8Pn0tJ(xh)9Rcb^36)lSKz%p)Xk+(ZwuP05Qzul0bn6ARHB57*yF3BF5# z5bDJlMs~9MzAl#St7P0O-wQW0vDk-R^-4eD+#)(Qk1sWb7a-}~v9Tm3>YyX;0NjL$ zHL*IaMn~KDryK}zB>?`}ozM(mdZho!3{WLhUmEi?a26;XyGibV7Ax|KM>Lh8O5!b0 z0;*hykv|UQwT$>(ac`D_e1_8E3_zDZcY-fhNI}xkCfZfvbi~=#QYnXHwsdq+&8<)h zvVKugYQ3))T2xAfI-p{uSGzkPS6P3Xy~5;9$htaz%Eu0>JZ5ut>*b%SPdTnOzuYS3 zK2Z31sL!x;&F_etpF_6=G2!lOYoG6Gt8&o>Og!Da^sC1wKkk*^JkM-wlQFT{8`R#d zS~pSz$3o%7iOzF(0t%1x8^rT87GdGOk;jhblqxSfDzmy^(-RP;5zzOPxcY=_LKs$Z zglBj$&^Fp}-NhjVwmElzfRM<gc5n_TT@h|?TkydtInwP6N7m+*MA&x4H=mXVi(_s2 zNbeMC3Pog|q?EUcxMi15@%?EPk34ymj)!ekK&{|NBD|$4VIo6|)dEW7(je}~Ht5o? zvaoHxVit#Fi+@P$(iu<^{Lt%l6yergK71&|Xo|1&;!b!)$MRoNl8y>JqEZ_d`3kMp zroHy<&7u9@2r3J0;Ttc9IL@Q_oU;AMK%wJyXol~I22yP8*Bcky8rFoNw04%2*&d_4 zF2TrzMwfUuB0OgR3bI`TblHd}G8g?=J|>`9=xS|B(h@vI!9)GM@OjM0Hm8R->-rM= zYOq0hZbU1_e3W%zW9}pO%9HeQS#Cb>{Qbt>uRYK!SIuaM`<w#TCQ=l1+U3n*b-fW8 z{ou;m;@D#zj4XwZ&oNxmx3|P*Qm*b8-PSeZm452CVX0*5#lM{?0iU>Uh<O|TkQ5)k z{ero4o?Eo@Kz_x^#HuBqAHQ_KJs%==9QW)LKH(&MCK+Q>@JX}o)ve*?XEkBH!Zsav zPQi1L&3Zw3kKCi2DYaeu10~H;I{&%!jXi29y7JF0CzC#$@=8hacz*-*f3bycHtwc{ zfcDtBqL=RpfXDjN)_n@IPxn>qPV2x+8~@C;HahJ#b!}XY@U(P>6tOEqeX5|r=yJ{H z^Yn4&ohm6(I?j3`cgG10{i)0&|4%)15Q08_kSYNyeTxRi37q*ojtj3QTJG_>x?Olv zHlvm@jAE1zv#g2MZNCZ)9yEoK1z!~9U%F|@2gUZER_;vx6>CCK@Ds3Zj{g`qnhr*G zDqmN8Rh0wkWtol|<!Bief5WVj-pI7aP%1i;Dk{@D_vWunhj(VMiUUd=*NrZd(Lxad zDJ=9Q5$Lpb%5ZAs0p;0_wO&220?-c9xSEn~@+2j@`c|T334&_ey6DpAbEFcrFAiAe zJEX4vauI5tq?xI{sw&MX8F_0^8sNE+&O&zXI{&Jn`26d|;`|3%cUd3M=kFki*~E;n z6hmeu)Xwo>i!&s#rwy~PH{Wl~y+uFlL8H$AW)U*7P1-x_oGR|@ayIpt4zZ1uBFnHK zS+_0bJ(@zZw6`S*NHUP#mp~JgWJ!^Wl>b69F*_4<hESA;36e5Jyr-1i-ijDmB9{vj zMzO&Jr8|fd`=LeT`G_p_Q7HB+xhz=gu8pcyxiQ+B1bZL`kRs@$6=dOjZPY?{Hs;%g zH`2K~d{`ML%aF{axj@f2XSQ~N1|o^T5ImZN(YWl5nP5TzFbd^0h#l+fI<48+YssE8 z6yucRdgYJ0#8K@Xjc=HQA*urWKI=5pzvlH@j9VY~Xyd)$I^HI-J2i}`(waMcc&x7z zwK3+;oM>8?l>l)_iQkc5pm(sbH<mUH(}gOKMJi(ARn^r+Hnk|lQ9RLm3qq1n-}Nle zu#}R<s*8)Jy>XjI#55SEv+W#_Ihc|W(8;UB?F^jUGnR3HkL-PhQR#T%<SL9Y;RdQr zR!hx;8H+OO4%LSSbBBK1v>Q*X_iPzboBPwi24kuUTa8ucp+gIO@4V*mCMwO^6Q<Tn zj{30SNM?;Lb-k1L#q+4CSV{9pCwN1o`A&;wsECz!H9S1@qQSaLtxQqQjipZTwv1_} z#u3Y<-D}lLABg|s3Ttjd0;^n??M$<C_mpg;fj003nmztIgzrto!4JdLe|5c+8{9<7 z?xrfuZRH2d7#Yc|4zS_Px{D3~Xo_vkQQ9K3Bl~gw9&LgHQn2#yfiWeIHc1<8o5Go# zwzaD7_-}Q~j!4E4TpQxn$s^u*3e3Xpm>#2WS1G$RSgi}JV|SGt3!ld~UvrmC6<(OP z+lcOUHBQ{nv|?5GmOgMoQhcq^@H%>Z%yYE>m`6Owbr)HSuGw&&pIGJFJx0zAZ<b+j zolZ`Cpy>rqPL#Ezur@2V<a@cV=Q_{-x6YFsN6_(0QgBcz%EkG#sa3Zn-<MZy-O8m& z|DoEEtt&z+j+x)sK?Zh=7S)+pX<qW7_mGc1O#*-+2dogTA(E9yGcK9m5vC1qTmS`g zX_obRz(Vh734vUjLLp@dgLykL>U<LHZx^Dg-;O*RDrGyL7Q{gPg27O#iNRa~vrLWc zX?4Ra)|y8&F^+HbXW<q_4Te}4t*EPqyecuDbvl{?aSN|<yEnVF#L6Oj4`6*(U~^)y z9w6Bxwx$Vpz1Q0gM(F+Zfi3qWRvS|m;?^JSvm_W}LC^P2fCR7bp7zeu5`voP=UYY; zgLJ?+AeD1QQ(23Z)xZwa=;*sPLwtVh*iF##c2vU*&^vDIQRa`k`C`jglTtWrv~z-u z#p0!imUj|9PHpY}&f6b-I<mJf$nCy)L4Pg^rPC%fW8LOn*~`kPRXRT=)#%@UzbT~e z2()8QMhtmzl<`*ar2izE`PQIad!u&z^l$T147q+o+bZ$ZJAj1z?N?8;RYQ;$+nS{r znJg1@5(>tFX5$em#VODW*Ecd!`gC;c?u_53pnn2sW)^#e$6@eMw!YP(1CE5McaQDq zVv@8jhgo=cLi+BX9vOfEQ<HYiSKQqRaGW$I;B*4UB17`7%4b$E0z1~6TTVgB<(vX) zaBve1q#h_Q&xU%Sdj?6V?BHws<<k3ZNdNd?`hh|wsd?KC+6*8e3YwTUxBA0zSdprR zDTN(-Mb&&g4=F!0v@^}3U<8EEO(sLxe+P%ngw}$k;N^U9tD$*nnkO+usD6m^+#cCG zNROwlSj(TY{1WQ;!<Kuj337L`zbU$5)@V`9uMarh-~08q0cbjEK6~Z+Wz!VF))HeS zm!;YqFcLmH4MW~swmBMlYGPM)b`))6_ep}GoPQijhK8;d2irH&92a%~X2Mp?^6|bY zR8d84vzW|+DHxD0_`3trKh*&(D^+wpUSncY1YqoU^5Cx<Fn-IW<BLAZ<~yy=0s%Jt zgomg#rU9sZ#A5bKFerHZ<SZbuhmQYV@bDV^@bzO)-kxYd+<xWt`HqlJ1j<i`P|O-$ zL5j)VO_hZQ&mLXsQxn_4vrbon>?f4+eTKt{^N4FVEM@f}|3hqA!1TNM+LiI=tkE^@ z&<c#P4veVnJeuDL4x^8Q8T*FuE>Avf{LUG@(oCah!<oP{=RT+iE`*Bd?kAU!?Xzx5 zw0yum4{uk^m_9sL$K&(T@9Y|lWd4xH>6HI%#vHBhi7D@AOOdx_Zmug*x;pKI4{FMD zjKvwZy5$29Jhk!{bs%Z?Z7_qu*7`$jGeA6YIO8p?h*n9fXXY{8T6<>EjM12KA9?_R zFB{V>(&;17bun#$`F5qS7hQn3f*h8cppYnDm;eipJ9L--h{X03ARTbrH9S(j65WeX z0)8<gMZWn6c3n*W#mrwx@3o70RghDxR>j`Usa+AAy(QeVV_CyLb-bPiOkG{x>+t<F zv|1N^X(SN}2RZaNOc(m=6Cy4%q$|U)l>?II6p=T1yu`_rCoTJa7P}d`>Iw;NF{V=J zA6uQ$!*^$dl?I8@eSo$Q#UDs&`{c47l{BJ9#fn^0nGt|u<13C!ciORym)*Lya8dTB zd*%UW7$J?Y;@?0fL*Lh~vMl`IWkKc?_U?eK&#ElJx3wJB1j0wA0;Ifjm#zA{s|T?T z$aomgC+$+>cZOMkblG9W%t>>2&y0*?CQi~=x@5wf{suVvrSPze(d97{#tKGRx&_gK zXcb!Mcqf;50NB4N_ghVv7qJgiNK#-H`B9*d%K>1?`=EIY+&@v5>_RS-y+bA_<45-k zyK9qi11L;^^B9&l!O!yxS}|!o?CiW*=@Jf<TYrTC+!wz#YLT{V*>1GDEUs=?H1+P+ zeTBW}f33wCdg9LE<@4i6huh4%tT)8zBjIVx$+JL8wo-F-e``dLUEW6<<*@E)HQJ@N zAi^@fv31qMPG=Y<5QL%uN;;^QnFRai1-VtJYfr$F@IpHaj;wJWF*1n5oILoG^I%d< zvywAeLUKR+?o)u<Qk@vK$fx(wv5!@MySu%rXtVl5hSaOEIgnIfxyd+863WU*0Z4@1 zw>ka5bKa7WG%U-^T()W`0WZ|bNf;{0y<1AXfCRWqjL?k<2HD7^^-rO~!u?cy7*wLt zaE2hWp{}!ho#8dkXw(PG4>)KXsqg?jFpj0q6j+pyT6!7olb@Es4o*?`Ro}gak*eDt zW$Lu&iutwPlHdO<T)>HtSo+l6s-l;ka$0`+^u@J+C?tlX@hOHn?-%0nqjq-SBSa%< z44ek0JP(1!3PY9RW5S~~w-P@Sr8m-<Cji>k*^>-~uw?(X^Dv0gP^hZRB-@Ow7iq)9 zkpWms6NWhL5pNJHWmA8|V0zo)*77LtLTC8xN>tcqDZbmhUL34Ye<VQJf@uR9ffpUO zPjS70X(F}^G(@Vrg16&7JYDQ%^+`UkSACIVv}Q2T7wn^J!mAYN3%(!k__O9F$yh{R zQFJT9jW-J8fN&7RUdi!ihS-7DW~(XuKPR;fcsSqB<_TEW6<^lN4%&w5j#hd7s`P<n zt=@caXKKztAkg)AA`|Cku^UOP`4(I<<ukzQLaCa&DT8KcfJRD`rH^NaY}8t!-^#5! z0R?3ppg!iIih2<=gzrPcvHxj4wzj)<R}ZrnO8aM~!*;y5xWrAEMdPV?1zVb3R-brI zgA*$krqAC0>_1k}v@ubg1Fyq5*cQcM?zl%TrMyqxS5pNe1GZTb*ld0V95fK}IwrU} zTF@JPiD=H|-u{(kR@9`J;1@F;+BZtsrpUN+BHl2In7T;&rpMNOE{qJHetE$VQ@S8- zyZ4dM52mHgCrI&XW%QGbHWBJe&+(7c?(lDpD*^aUZLNst{i@PiB==oU*NL2Z`KU(Q z@7RWs7{e^z;i2Q8_*fFdh)S=Eo<_CU<-6F?R{9P50_?!4Ph-=pva6}&yvaD=kC|~9 zyXx+=F1X(xp>qWDARFp}7SF>z5*!?POLN>f7<%Rwvs$9@rxDZQKN9QpC=L@Kk{}$1 z=|Xm5*0c79og-Cgxv>}3`xmol<2`-59i&*>J$$uZp$%Z0BUr%++l@<a6k6=qQg3$_ zJPlr0u4%q^5D)~W<>E2%m}gw>nsjY?y7vW&A*iVSLG1pdF=zum^;Dn5EAJV5N+GS# z6|TkZU2|miWP~LQm^Qf^pC{x}s6x!TC%>NYn<IW7^PuN^-_{awE6Zf$ZIShD{cO#n z8{WSLao+nAg2E>Tz-rY3o8G)-p?s~d?~n)(<rUaTD5q88KVq2kfJdkrAcTUz8$sLD zjJ++!9cjY^1lVD>QA;#hciG5V^n#fuE2a_C@1okd-qT=q`RrjY(dqsv?3CBqRtrN@ z$$Sc`XgwcRhGaSP6zN|n0?TP3s8cBNdbwT#Y)xf3;-|2&SI7$A&b?($zY9AHNp8yN zO@@`tvNjw>z!pexRu->P6Z^gk*@b+@`G#4~v=Wv*;m|tT2-Fa-(y2MXF+uEC23AGD z182j8f}0Am%zg-PX1A)QUt~o@=x9;*8jr2#y7GH$70NXmxu|pci_q9Ljas`CxhZ8Q zcFk0uZE_u#0O%hR<<Ud@AHa4r(NDEQ%55ULE}>*ADHY>0(&k6zgJxu4uIh&J%bu1* zOKl{Kp;wUYTOK6AHdYcGo4)4Qm3uh-7OWdKpzIK*Rc>Mmu;icj*DP$B29<G+3TDVr zacQ;*h&aQx2fA!i=?7L3p3M!n?nz<q57Gw)V|vj_z`#|1@B?G_)Lk`p``bCHXYb&l z0Py??jXJiA7IfM)z_v9jg5lfWX4m&ZlYH%kl3~Ee^NVwqgSn2N2mWyMd7h?#SWGY3 z1^bJ0y9i>Kt0oXDV`RVIwbSI<=RglRyH~)8abiwsAzxu$g`o?m6i`y%`%PBodbnGr z+WvnY?DoI)V0fjD51^8R+bB<SP6DKK28Iuqa~MGnvD%Q#WDFd<SB`tQPu0)DC<V^g zc&#hIsJKNigE#}Ma~+n|(C)5G^jqnrl-Zz~T|d?AT}pKo{OeX-cU4uxNd%N#lBB?f zK&PWBq%3<1p3ifMX4(mLu4P*Fuu)-)uGPyj_F_2={zFh*cm$?UV4HFV)H)dlFPV4@ z)#rhG;iK?kEjB7*i>B4>ViS=3qZgSJ6>tnvUrwraIRR*cb9)y!J&4`;`a#9@%jW0p z9C~zWaH=*kSRW>Nw4aNgqx%=QJ!bs$`}MoWU5#rI(t{}0PWh0xv_TKl!oifAmsjg0 z{9;rWqa+w2^n}t9R5)-~3(drRqLwl(zJ_aqHD&csCe23=`yA77>hoU9-MlOZ)`evx zs0uiX(Z>g6SefVCfy&K%g{PpXGT66%6DBybT$b*^y0bzfdr{1og}iJoK+F()OYMMe z3&%kPDw{9_LN3#b%6Xj0ZJsW7&cgn^13CyS`isMRWQP9hDQP_PW0mCs)~+C&U((!a zD=STzCYw?{{`ik$`+o8uu)Og*iOTo1Q8FImuWZG<xHqtWT4s6bN)K{KZyGVy7q$f5 z6EyFlUR$VFaj%5@@EB2grI#<?*3cxXIVC5jQ%1nZ_WpDphvn&RM_1#WkA*nbyKZh| zXwQE%YGmGg@zH1a;_t8GKbq0rsk)-8CCs-25`YfL<(5M5c3^m-*-lLxtg16D)d)V! zoa92$?7~1e*vbcB`l9Ry!5*Z_L+P83wjVeE90W?~X5@hXNbPoC@M73Q#blRgS`V=o z*@f{`0}gb-)&~|A1NE=DnexiR_HHT%c}HvaEMfr3#xrSvfsL5$Cu#MR&^{ES2{3^j z_#cr?AaL93#$$3kn6WBN!ekljVOwe{R6Y|2<(G7u<0O0##Kv<dS+#FrbUFN5niN1S zY2b`Juqs?|@dCf$&og`F$(kSbULM;i?m^7^$X%GS_04*j-PZSMVJ|Nx`Pprh)GIL5 zt4z*O3wqRSg^@WC*Tfc)6sn*K*!Qq;ro)m*p@Mgn{e>ZgR_k@@#&GrTLe>WDel~Ry zz%fw&dZ~@bMbdIT9ERXws=Ew+W)cMjJ5j8v{NZ_;b0P}0HS;1Q12qMMj^P?RY;!RG zfgP@hPD}viCa7Be$Ih}pN5Z~t&+S5P+cskjC&SRQc($o|XqK`5o*h5*@hl##xE-!H zO1C1QvN3zE2o2JG2-s{S3Cvx=sg^Zi=~7MW;$*@=AT&a>WnmQ0gNP{`mzcWN?QK*v zuCCh=xo$xkXu1fUZ@ol8=;mee^N(cCHQ?Izo4&tE<Jaj3AKQ7(4`&o@UB8p{k&jjE zl5@iE*T|i0H&opFvqHcxv)EtCZTPT5z;>WC(vRp@A-Gya3n8Vk?XlN_$i|s`z@QDh z8*m0*QE(cwN@)~P;zc%qJ=Dqt3LmS~84d(8VYKp49R@Vf+y8+1#d1!y=NYkq9V7GN z1WYNMCLELPg<QkBV3Q78Bdn(|y#056y?ml6sPD*Ef>ZW&Ic_&`(Q)W?-)xtywwo}Z zj+p+Dy$oHE)s-XNuxr!~dT-4-?dK6gNru7*49x8<jl$&U&|yLqg`lXTRzCzPrz=v2 z;6;^+VNF1tc(9Y3Gt%ngJL&C`T2rq-+wb&4RvoxMEIG1TchJ5HA7-+Rd+icFXk89# z_n>q9W>cEuLMx*kP5*u3lC#Vhfu^kAk<;hLoTu7~CS!1P6*2*%&mCJ&YcyMivY3tO zIRF*SEQCg3PFI?16r$=glVNN#3;B<mF_9}@DCkoHG9h3l3k$kHmC!7*o;L+bf%e04 zTOb}P5aB;YYdqlR{#xxT$uH(a4?3f=mk=UBP&L5AO(?I|UFKK1K)oB^pjfW+6$?Ha z7-E9|S%!kFhWtwt+X{$|TssaS*SJ(qff?pPx(5MYFwu5Dys8~`u}$|gF4w0L_!1^p z4)!^;A_;A{>ZrB)p;Dpug;bC0_&NgeV{Kg#_T`=<gi1ljRZZJ^zp+p;bUky)=Pdn( zue$pEJ>N<6IYsfC{Ma2*m*2eKBKkoIC4YQ4Z8^X*oB4v+Mo*#m$WYTISi^^+vfSqR zcFh<d5dx4&`7dCM$rG=<;v$V(YV2D-jPe^x@;Qs5lClIRL3Ha12_#7alW5Qx@Xvg= z)JG_;$&kHP@AiU~t@Ii?kjKP^XB<D-ne4pj?!J4x3udR}W8=-cbB+`-v0BGry=!>_ zn`f63BTwL!Dud~6zIjxjH9M^Z&6bcG`8h&9ZzWcBS2fbu7#tQm_K70A<R(^b+Hi;` zr#Qn{P@CSCqnlw?9NxT<=6faxKGb>*!{vWP*DluU3>56WB9n8(Dd(KkN|`rmwsIXp zBhuGA=?KaR()hj?h2d4e>OkA!7{$;m%tBnq3si~Y@F<r<X^7_$){B>qzAEoEd@p45 zVZUhG{%d19$NerpQP(WZElsLVQ|q8tl}(p%K7+h-Li(|hdu9$Vh*Cu8^?W{J<0(mS zK^esbL7g~h%dAU;Bf+N9XZZ4^hPFAVn1lq?<}KElg&zC|$k#xLqw{c%q8vsD+IpG! z8+Xc<R=tis2lYh0Vde{SE`VL2>)ktV8_RM2>n=y1vtC?cd%>B$QG8J8Lqt$JT@!Q} z6Mz=H5|=jTSI)Z~4*ma{LOzE#f6QS(lau-cuXK{EfFB0NkQ`65JCOzMF)@KDfSy(- z1}5d7|M7%u+qo%T)6Eyd&p;mz%k`gz{`q)Wr0zNWNmxy4QQ-lg9>ZMj!uu^(mfFqY ziI`=2Wv}8OilOubli%AWlC$v)`ZebC^jpwiUS!1WZLOjWV(L4ee>tvSwf9akl6$9p z!LrcGeAEQW8)xNWZ43Gw?=4)Nwk>x2(FuHCkp~^;{huy=<+-`nLJC>dQNx^MY|x6C zjVC*OnA+6*=cTydM5NC=a0C49gj|0L^<V+@{UBG=j8`r9ukPeu0G#3J0OvM&T6RD& zvwdWXTHilFUjYWjOuMWm3uyv989~&rl|N7Ve|-M&8x+zDV?XeH+ZC~In`jiX<YLg= zosHD9q9;+2O2A(#NeLL6F8&j)9WrJkTTZQ<T4p>ksCLTE;fh+4pAOyUtN{g-3ps*C z_W1ouFAS@KgD)bEik>HIe2`zioj|vhb90qj4kqRi8}+s@eq6N|Jjd;PK=iS0F~8`- zb^*tt2t^lPyM5D1Zu@TzkJajZaIJ*&m<K=~W@FBD`0q)_EgeYUi(elPvSXd?gNf_m z-;En`PC{!Rr)4OWywE8^2Yz4xf&pnd3qKt>w8aIkl^JPc(?WM!@S6!>1t_E&iq-s+ z=Z(YsiRKA_I-wl9i51vjG9E*q=4J!SFh!R7e+U_obP5Wcpkg~QU4I4tohe-3#i%hD z2lpv_=6bd4Q_~;?xNk+?HfPB&t`pT(>50{fDq+J%tVnn_r<~?X%|dHyEU)!og8{`) zKZ+tG#Zp4|Um(Bd<Gh?CWX72>ed)yO+hewEhm3_rqm@GHBz#P&jJ~(4LHSz=6$c*x z>yhRp6t636^$!orHBszvZ(cigUM<BuMXtQ`lNl=o_JNB*X5bGrZpCv27^WhiwseTm zZbyrT9LMo9q~&!aTp{!gb0|PHo+h=qyIRKFMPw`!{tMoFHgzf+z><_cP3GcZn>|b) zx4{6X{}aUj8_Y|CbJ?%|Xi{_|U=9bWEZZJTthn8NdRvof$qL_tdrJg8lHIi1A&eWC zZ&xsrS0+02bg^CvDD7_?`LvdjKqhCCjKaM3-EJ_u+ZgazGxAE1*rTT#O6lRQ2gF)g zm(bM>&0feYyH9<ptR^*{E+$Sy5ta5ag2EEYaC;1Joj{{Rsf~k(QX9e%TRrg@>Lke0 zz7B*09%SM|VxT}F9;HsaBa%(04nQt0zyKVuz>l3{!ep-<wuKo*yCef_RrwpdjME8| zzkMz!Ls{T6((WX_DQ>kY+=%@WLepT0fl4)CQb(LyPB4>^4j=2oAv5N`5>05(X#rXQ zTH6$U3ZkGXn2T6;Fnb}ua`xf&SFpWav6#Wnc=uH%A!++0G*B&Q)(EkDTBg*y(RAV0 z?`NVLphEeV4dy63GKn8PzI#TfTekmDc&KiZtG-<%&vznx<BjnB(-+oJxlbnyG#s<| zwC-X;6z$ZADsyEzSC6z<QFEI__m?AHQ_d}i>b8yQf<I&&d-EC+p<pOrRz@Z;P-gu* z6-0c&Gd5|Dfwb4az)2UN;Cq|=Jqg4(SpO$@>j6v2F0fyV2O?Gl=;*c{O!I++&G{jP zgU?{NGXwnQrQ5Nb*esFvJ{PCXhXhhK((%+u=>S#8tjyf(FGn&;<qLy81z_2gR?R#~ z-VbHj)N5gdAyd^km+4r0U=|^lxOK1l39azQy)-gQ8jqBMPX9;FLtnhqX}qi!M>KG_ zRwWIZ3|{jaBrQN6_RNXS;u$p;WVi)z<_H^M(;osJR7X|cY{(BFl!bJs%Fyj1g39{q zLQD<$x3-$uZ$oTke7)qD#27I^Z}BU=)t(V>d`^=(iM9SE%``bo?@l!%MK;y{mgtN2 zoWg#{FtTk!2PNUw%$cL4ped3ZMXff|794>pen25CdH^(FD@lm|<z>Q1hVIsSQjh`V zn4ff&QOpdIu3bB{vI?EvGW8rL4D4$wA>%!R`@#;vz9REY1oxvQbD~3a8f=YZ&c8xy zc$!wA*?C(wsS<T0Y4yZNG@KlAUaNDnDIPu#V~8tPS1T7%^I6>*p6txljQY1UF~lf7 zw)373?xT4L8-BzmxVj8U=`vnKO*p}7+#dP*tcF?zMj&-)uGFvGvI};&>|&C4W@+nk zJarv#LCrI+>sAj#;auD4q8=OeaA4Jkhm&nmc4o<C&x2%kr614pnyvIenNhp7sm5Ta zjlj3ZV46OSe%baOx%ky*<%N;jAe0>fj$Dli6Q8^Pz3*As663dEeBHDzXvS|x84qn+ z^2Tr9y=5xeZp%^YG%5M+XF>tHPcXzTEWeF7&*zX3RQ43**lR<zSL<AANX2YXc_IVt z5WwY3%OG`zDM4YOKe0_XGBAD4>w<zqBd+oXGKxBj{ih8M^XMYqlS3NjLG(6&JZU)v z(^L2=N5Z1P29>rB(-DsUY?cjGVw(Hu=zvxT&Ip-_A;R0;mNTLE>p|@R1!BncKm@42 zYY_nX6hFyR$V|6e2p01cqyBGab_f6`*lPdsnrvc$xX$*76Kl;>y>?tr+1oM_n%~YB z{5U<pkZ1%3VE-wTjqwG)(Yv|;@Ur!)N;8s{)fNmLtn<Sdeg7p+MtdK1tBzjW6;!gy zum@qYSh?qc9WMJTkj(>(*OFbbSlP8_Ltj9}8emr_`iJnBhd<R*CXllmeP)pldNUr- zUn%<?c<4<SkjW{{^FX+HPGfB2eNKsw56&8NR2v7M%?noC<Ap<}U~pwqB@DYZv|FU; z1L&|A$qcL+#j)V&a@GhZ^N@=uf}lY145@)-q$c_bn#c31S0L+Ay|6tT;&IYoJcs8m zCmu*eF|o-6L<>f4xC>nLH)D0ex>JcEsQ^Yu7<VC95;c@xnnIeU-9fmIJ~m#$Uav#h z^{H%a^5@8mcp6c~$EJ6{V=zOZ+RD#{xNhBb!>I?BqL+p+>@eV8VJ9R~0nd53g!0j( z1_=r}c(1{NsrY$6YKp`PEn-fCbe@b;ntVObXjHYrq=CvOk+t+X?L$qwpmO&-za<am zk#q%Nl@v@!V9By`CegvGy>3ETYaCwEE<GO+OX>e?CFD1Cc>Aagn#7oK=Qh=R=5k*Q zNC+nqFR_ZIAMs%vyn7YFov(d{!$z@g`S`k3D?41j46uPyB4Wu@oIFu&kgjg<1zk;8 zMiZxkUyjqtaI>nFy&FpUVY53B;XN~1(GwUq(nEmx6-giWQ`;<UTS0F0F-fAe`=NwS z?uKN1!obkpnTJXU*CmCyd_3H@5mvCTS$|kAx7yqmL_LiEKgAz}8L|VwUI~%uYh!(5 zUftI*Ykpb5a4y1yOc>1kgIvEy?*~ZXm9$LBSG4*~38C)I1`N)0VhRBB6<r_wtHov0 z|AzIO*$3J~IGwl1Y%x!Gj#3M_B||KN@)6xbn4yD}Kjcq%{1T^QgU=dt;zKN{xxGA= zjBH(`AHiGo2iAj1674NiS#}KJ^>DnsdQ(7wd43=mP`kg3<I%&P7LttFa`mlYKc8aF z>A^9K-eJJHmXglrV+x)=ihK3&ygm{-%)#?wk*B{+M9mF@yZDjK1s$v?3sHT9q;k;9 zgj8lgL==)rQXA*Csj5T%I?1%59;ZV5%rKCQe@Y6QwWIHXRE0A3A=kv|XxG<}aa*6@ zqR7T`R*(wBcI7Y4u;;;8Hcz6tLnh|KN1Dq+Bc?Gkig!PB06GXWN-0n(lm>5+!*qav z$c9nP=9CCV^X2{8%x1x)>z2q~yb?fUmaMe(+9?A|%<2^!d#7=UX=10b=QCk~f$5IS z8Kw)XAmWj@dDZV`U~IN%F!Ve08!dBf#A8JfKiaqhpeH(;(L$s@U1HP;=3~8Y+39a- zPfrcZAZpqWCn~A>K?7g?5rj&<s^zx$Z;PCY%Sw-RL{mzg)fh*+%TRne+#T^B86yO6 zStIu4k94G)7@bj38#exv<|6>mEh}1yKHqIfkP^7qlY{#X#SsU7lERu1zEnaH^D*>w zm9Oq$jutdn0++jX0GqWI9gtp#M`$uME>OV4vZhH)Xs~b!{Q|N{huDhtuSBYo3DP{- zaMX&Us>0NE)&n-B-9eRU!SgY|w<}ODqzuh73u%rh-M2xWjtL*fu45Bln8E1)wwS<; z;kW@~ig}16he|?n<?T@Kh;M506zUL~eUGL^vH~@F8L7v@wZ1aoTSI1vt29G<m60<{ zPV1KvL7+p3AUI~7!&OD0j^3Bi{)UPtdNUt;?)tJTOu$7thhd4hv{a4a>4|!r(WWh~ zq+pP%SZYK*Gpeak7Yl6=v&)_2_8b@c4M(E5_Rxiz@4Dgzh*zs08-R^@pWPmF<?Hfb z_be!e>+>(G|4seJoD13B=sAsTfOG2;QXn-MiKc48i8HS$G?Pzg*#Y<lE#mv{^!0*^ z<+}o3O7PG2L*o*6dUYXB)FyOX<U8ny8m+|85n-`(b<hR(j7iEdE+ri9?7pW96K=%` z11g1=YyTFOj=#h7r;WgMw?eZps{sG30lRhZ1>B))Kd|`mCQ}yM8;4n!YyLxKs@9zU zF_=Ck4Nl0y3AnI(>@>4?s(c>2(uH4q3P=GKYi`1{iZm$yMEztOk}Oo;v&g_T0T<H( zzcINi98eea!}c+{Y!{?MN*TdDd5lE{s<aX2?jP`t?6`)QQnhJAd#mxSVSd|Cn|1*t zw=>^MjmPJzgO_^qp#0+zA&0IzPiZ_r?Tq0Y=DCMl2^!(o`Kt13B6#?cHn&eHqaC5v z{fy6}?boy>;tT5L<%BNi;~J&f>4;k|xsW8nW_t1E(`y51WhX+irw#Dlja2O6pa}x# zHH~oyJrcgEsX%tQ!KI!Z;*BJYKj6)7grOUe6b!M+JyQ1iv^<MP&hHE>L?YZFs^?2< zM86`OSYTuJA8%pM9vfSex=%?EQY@sopb(Xq0fLwu`v(bs>i?Coz@OAWJf=fom{te7 zZ>~e<YEMH)li7v)Y7h(8AD#y1!QJGP;o^tff2$xSX`tSJ+_)@!X0sSV2?#bNcr~9O zJz;tm%&Fc4zESN)<FPhayPqAQ%jsAfI%9ep{m2s4kBJvj5o?{~E^qTzUGkxYco7-V zi<P!W4_xBHY}n^yKmKV7vNk+(wSvi+m7W^<J7qf$-vG~226Z`V{qq2jRd!o4C9T_; zm(#&+n4D{%);+8FO7|}G#<MvTXX|T2(as&wZ8;~|1P6Sxl@zMdq2vZzomi!ic02>w z2DGI5Ee9Y#xHce)GZ5d5mL(CTnJ+N=;8%hn{>j(aM0>(9vRAd*fbAW)M)7DAuQNb` zf1$yqKH*Xt#B-=o4LT3>V+{{Nq>sm>|1zOv^;xi`V7u#OwJJ8dka<m|mk<d4pr;$n zor%W;jEkRd!T&3AX`fsi1XM9~OAONASK>krfSD{D2)+OZRH7>2aA=outjIOkJ;5TQ z4aWAg@le!C2&=#9R}C2?(HYC-F56JgPK-7DKw}atoCh7T!V+O&SOl8S68~)2EZ#4L z^70Xe5i7vj=U6qX2YENqWkMP+R6YD%F_H2R%Qa&kgi5K}d%ErF+D`fxWgi;?S7C|a z`xyBz$KO6$Bw43ER$MP(j$*@gXe+uRF#b2W-3a!FrD3L*gJwvyV5nEM4FM-BtdGr9 z_Y61Onfu`j!GY^!4a0?W3|NoONkQTs2mm>ptHm@Qz>rC(+{QP{W1X|U!Uq`YgK)Vo zpB1|zV-C0z8g17O>EpK_?6a8yX4`0t0ysbFIQ0+AP5;TH$6;2{flpvkpU;8oEzPa- zE391o`BT`t+Rc-JV4^!a6Y^j22dSQ6P(owmUnT?2-Ty0htRJZ^GQAu=<9m^4(uzUO zvvo!g6GRh35>^am_`lDH_8W}#9ma@|5Y|E%DFEw6dI$Alq(JLkh+j=~Trl)Qkdajn zY?w`fbiO^s%u%jaD8_AoadoZbq(*o-$pI6bRe2e+^9Z#g%BP#>jhr2Ki!5T*=%x8r zk@Z6T4xU#}IY#;H<|=p)ZTs)dX%J{~ttvWHd(ow1P=EDaN6MuDC_#KCU=q7_9!0Mu zW0t|uuOam$Ru`TT9UT}5SqrmpWa`ILFkCG?3&N?P-B*Ns1sPwn7$fM+RpchFVuQ>c z<{f~Cx3&eYje>Qot$V(YyIrJ5Y1W4FZxshjyPmm2mjU5qSSP1aKYd!%3dZZitL&PN znp|2)#JM+2$Au_!!!%$CPtBF04NOykKN`vY3{0S4;nYeS+hQy;?XhQ-fDw<sH5|Vw zS(y9bTU1ME(T$Uzc|=p11p_)T)fWS*G2PLL1O)ulgi@G&T@Dbi6~OV8D@^nIxi;Fe zBpm}90czE1xa6$2Ffb=;2Tl+_hF`FA-?u8rke=hB*oJ<n!tva(;-uufn6@M+r?2aj zI*W*#MhvU|B&iJsUC()b(JkbH3<K8CXBb>L#bw!sCf7#v0d(5kg11A{tUMw9kTNRJ zaEE+**^y#Ln!HZ)X<Td(4HfHJvrU94q1d5hH8vsgZL>0ys!T`ETTw6}XDpcBR9bq* zR`lf{E7+6&@#*YO`w3_Eq5T=Qi+`*d@t!Xm@-S2()4l$amkS`*de=H{9#RwdI+1L- z(`y8pz(1X`0e5d{<{9C#8?<(8ZGwmlY!j5N^sw}{+|$Cl#w6y_tQs&NN@+mP&>82E zj0p+wBOfrc_oFU|bot>4k-j3D!bkAcKmBoVjY#w1^#>@U?=fnvVhh~?(jM*KsuSXS z<R`DNrk`To;D82CQT~UYHC5Ei5r^~FOfFeZM>!{M@%EHyJFrJ5YrGS!Dvne3PekH+ zRp!)fQK6D27S@s5fWQutJowuYp39IPBFhK88YRat{MH1!%N2V(aT(zC@R2kFZ5ab| zGFVzPrs94wh^%3D$<cMel*cn(RGU$#kO-vK!9|7I7VWT;io@WuncCT1aLAPU_-|G` zOraNFrN|D6Dv~y76gY}P7ecIbd3Ku0<RDzC$qqW%2TKg>{H~l~hW5q;JA2@qyO{?s zq7lW(g5g`grM>6zQ{$f{vmEEtOY7oUlhNG#4;GYkH%idcz&Hb^4Nj?_Le8nz;1pM3 zKfoYt;HruLq+-_K@;yRvNOnEs11p7XB_q(lx-iUE&ZC`$dmc`$K(Fu8ooJ5NSGy#- z)h{Oc!|;6N|3%fCfJ4>(;o~iDY1d9!CMlA#q{upzqD53H$}*Ku*^-cD9BovVp{$8X zLcNyBzMCYbY?G9cZD@?aV9aK=Gw1xz)cgJYe*f#aE*+O~P3An$XSqN3eV>_!+{32h zFZuV+VK8Z)@#u}WhXcWMx$L!b<$HmRktV45*E7R8wTWPw<q$Kw9zm>!yv`Ho<cN;P zNM&`9+mMwZEJJ~3ttODT*>xKHMUpWH*uC4D7GKjX#(<M`PtlUkFhoX!iG@RI8o&k| z0^uSU1OhX$RFR@_BQR)$lsPZiR&2P#PlnkZevK4C|659!1%Z(9%tC#G%CnsMnm=<9 zW&{;Z0&KO<A-nG>uoun}pFytv?=r?-L)3ak$ec4;Mq+zum`Kbdp3a!t!NB>gQoh6r z>9FMLPQM^8-g3c~?NZt4@8A?f5di7I3X&?0(y7XN@fT`?B7(Ylv8IsmY;C)=8Gj(5 z?+M!RWNi2R@U);m9IDiEfS9huShbVB)5kPW8V?F?3-!Wpn4O<mu}Dx?9MBQn9y*_M zy`u*C?0io37J-{qwf>@gS<Ey=Y~%iV0Z^ssjCQ_rhBSp&B8N{N^U?w+XOG0%V?+Za z{t;$h?J$O;hp`xVkn2Mf_&b23&5)~+WH1QsKwdj(5lm<C&$$M}7Iyc(AOs(R?C7)V zL|`*OA&%*anj3QgBMFtnlg&<XY`Z^`EZL{dC4OF#Wr}=$8E2p&gtVqBxoY5f=J(YQ zDwlwOy~uiRFN5^@y8kw!G5~mJ&6N!$ajogHKL(k`7f@k0>uqz{jjf721%%urTLS3o zg#pL^7zw#5yAT40MwB6WTTqm@Q=_*??hfn=z@$^+sZ6>H4_6~-!q?2A|8=;dF46j$ zj%=mSd1R-Ay=o_Zqy&EH#?AsZ)ZSqSXhf|hh55QG@Q%52!9nD2pKYpDNU46RkbKWE zl1z#&8D5DE-#8KIjlEH9B)n?D9K;8%SQ0oskT)Ajs!zEv_e)~J5nqHl+#4S0Jug3E z4e`GAcx59PN}JhJ{}a%(U8a2bFx-aM7hK0DGcKpX{(BKb038f>1<13wjUY}~r%U<d z>dZvKFusC~zjuEL3g3PigR~Ly37Z#bYKderl3$2Gl~>Sbxh(UW?G!wjuPej$FbPX6 zT2QRdZ;<@7q%ubs5cwe?D7pA={r~5yUHD<P;BFFvlji*s$00DuR2kK*4c(5$d9I^V z>D0c*GAiLDc(e5fGy|U4A?sdCknR;_3QYg+Vg?Lpjk3D~dE4;cit@?7Ef_>+bGFon zff`@n$_$*xhai<W@~xk9`$<loA6*{B5*dOjo`eBm2K<$>9x6t1bSBMQ4^K9RI<VQx zMqICR#G4k(K9+m9?U!}frtjT@U*smtQ2)|a<oTfL9~>cqLotmRLPA)r6%<=y6h7g^ zh#&7Ir-A9}fZ$3NID~)RFxYc|XIbnb>d^%l)VuKPVJ$%7`<vBJ9A+OqhIV2hJzIle zNO!OUq}@ALj}!?TOkCAxqB)+K6z?st3)CdZW3bAW0SW!?PsJ_>@H(J>3eNM92?}{n z`x2*F<+)cDP6mA51!E8#KtIqDb+SN66N4KvZcXp>kRh;y#wF%$Nc~lkdyY+tZTgWY zi?rdIZ{>4ck!<HbBmxk$TC?&K&f-xi5^e_i7NO69F35`0u-T2!Ck`zwPZZm}%@KyR zEp_}W8=f{?h>!qF_dvt!?w}N4x^ao=<^S_5P(%&Q@7hu~uPou|d7S<->cUCOchsGb zGo^ao0*dwuls`4L!Gz-p%)6dqq+9AmC;_eM@>W08<{u4ah!fF1;|8Q^@AFk5oO}f6 zvM;@Ott*k}Hr=UscLN{@QuT5^m02-MQw&g(G@!(eD~rN9vJ}P$Msp9GXM@r$b`%fE zog4~dH;Fzv9>uy?t6Y7Hx}Rr@8f%<AF_|@IN(s_oW}eb2=>mdqHJmCukoAxmshEnB z)M`qZ*l$s<jGQC~`aQB*<M<SIDlS*jKVN&JjARUT<tB~UWtjWXbn#4K9T_VM^Fbga z>~Hdm>fOM#fLW30W~gU;8@g`^9~18T0uFRVK$`v&*AM@Cos^(C1H1KMLaxIapGMJv zYxgI`jrp}LMaDET(MZ*5*+6A%u&?FsNTmQ;*Pxg8c7I+e;DZ}&ulb>(4K0d0(SmWH zYa{2W6aEXE$=H+%045F>TNc+8_kIR5a5N3!J36wBZrJRG8h2y<*QWg6e;sJ*G;i81 zw_6g5;krETJJXBc>a8!H5eaRS_N{<A7pDe)&YRkp8#eqFu>U?^!{CwmMx$hlF7DQg zP%LVo%LxIlStjGu%|KbIq_&HBd7w9a<*&RX$ErqH4H*AMu84f<MGsJb+<wsm&w0+Q zw0toC$$75j@tq-NGgob2c)ccSyPMgKFMPARs*1TMv$w?-$8Fpp$+Q!Rg&*?4^!EDX z5qJC%a(HiDJi9`N+}$vwxs!$r@0PpL?O-1;y{ropQp}H@^Tdb<<SQ+(26SblArr~K z(ynZ07C=Ww=}aPBc}YZr=e(!9D0a%qHAaeSLN)#&(@<)7exxHA4;PkZA&8m;|0n$- z@>=Q;V+;u1!>d91K>0sa$jVE*V7%v!k-2Z&)c;24$Y9xg9NF_FdgHPg;l<5=d+$G? zia56fsimoz=#I2sW-H()zJ+&ZrGKd7lQJ6P%u>ULb}Zs)<qqSLoZhB<q*15c97lm` zPZ(Ryzs^?!=I%X_dUm?7sLVzk=wt7o2hi7y{d^26Bx*qcLv8p2Oe}giFrSE~v<}a` zZTy}{45*hsIbIztm{c8(mX@d6P4b;;#~*9eBr3#(JDMFtY0yh%ElpAiB0nr$FDDp9 z>YB%&qdUYG6pIV$G;<~Q;&Qyy`@3>1vzAo`3QG|}sKvwyAz5Xf$Vo!`%%e%vnrn3D zlNN)i^ia4XRT1;lFo2G9%0P%omx+b;W(wOgo_7Y~JcTcGv@CIMhU-C1;1>0>r(dU` zNni$~?THB8^7mYa32jG^lv{vuow*Kq3J$garkj6!RR6=Rtza&iU!Qq!oH})qP5QjT z?BX6-dzY|$?6uI168D>+wpQU$c;VaAvTU97`2Td+0_Z`4|NK^mtGYA!u1MG^QZBr6 z4y>_$HBz?T=fiF!;hx|8cjo<<!yfW=BXH$aL+b_MO38cKnbDRjc(qM^Jx#k?2YGSC z4Jf<w?Cc(-*=_72?AcBzBz7TmenJ`0e|p|b6XscR%!biS99W|vaANY<>{=^+D+`~d zeb$p8;RFu_3dmXUMFKncBr>MB8HVEN<0}JODK%c$Rp#*L&iY+r72-41v;6zU#UFa| ze9_$ZD9Ji+)jg;sIIKu-smhWTbBFsM?4V`MfuJ;ZgV)A9bwG$5Gilkp2~_9?Dg(l= zz<FvDzA=~y;XskX&M~YCG>rBl)B&^XdvLjQ@GfkJ;IvBc)5Ai$21||N9+;H!m&%Jc zUfh>W#)ymQfQNEOERjnzVxYcsVSoFLGi0=qzgQA7;Z!X_YHx(ie6Um~@ui~8c%YJ# z{hy#N%LRY(fwjzP;?F|T!fv>>UE)W_8$|C2I^_8!e=a*IfdzM42p|`c!=Hs<848v3 zJONO0K)wR)7h6%qMmNHTlxjO6?E%U!^!)8Ld^f1cyovS&Uo-FJMUi+a*LFdnLyT!% zuRf**ObY#ieMdl;BCMHO37V5XW6rH_ux=a3B2w;l!5<g_b`RzUF%#8?ij(C&EzavA z$z6G`hs!?w0sF*k)#Jw&<26y=rB;FJj6$!phmo!%`~heDif!^p8T7;9aDKyz1OdIF zFYhieHIJL3Hx$wk)T1*j`?@N2zQ+Uo6iP-*k&!1HTQ+V2%_R}JyF}lJ!|)AXsWvd) z1Q!bpf*asuG@mAI#|OGnjG;o)V7Rzu1{&gCVl$vD`d=gpnZ_d!iEJAG3_X8P9(%9q zH}StlNv8TYH<0mrV$kCvRd!<N=%sXQQeUU0F`)g22Q1?P_s@7EXrFA!l_ZvI)^}u6 zVv|23xmqTVqWxQ>e9J$*EF0B$H%9s~{+o4dlbp(53d3+<-k<hC@~@qiY@eryq78qg zEeQ!v{0;lp$cMtofrCsJzI^yLiZTt|>h}y*WaLPdej>SP&k4yB^oGgki%=_r(t@83 zaREzagKeRS0HD}2({4zD`e{mIsZMKl2gjpjBe;s<Z0N|h&>k{(Nm!<tBFgN_0B)`6 zxTPa%yP&oCA$WfQtzcWJf?I-aEs{CfD0k>&<>LGL^XE$n4Z5<{E<$Ygtf65!c>MzI z>?bNSktncpvd{)1q({+MYiJNH#podrRSt9g$|=eaQg>0qI1rK$kT6IdLYw{Skzlui z4KQhhB@M9)u7QPQPi4r6i3+`)frO>Hy-Nu^zev3ajX%)pYi(q7$2!f%{Gs@lFz^$L z*_&&gie%yiN)1R9dZAMfj>CT$Y%SEkS|Nj!&#LPkj`V895DCAL`UoM^%9?&GS3s75 zDB%j@qKzew{Ex{RuF^Be&t&V^o?Ji0pY0}C*-Mx;NB_E~^t2O8YWja`RuCg}L+~u> z>?ah;-yZ5zrO@$(4Lb0ZRVKl(E2SIykSh54iZ4Y=kiStfxDk#YoiRc9E)=$Au?Y!} z9bK*870UY>rYd^}ZJ^iK4$P!w6#}!z<v4>beRmEoYO4?*THt`RyDKW0y&;9P(IY?7 zb(gMK;v-RUD-M50K=l@Jtpe1A+DGqx^HAZs=;FHrMQ-=i;XqWYbNg1o3*<J0xsaSG zZ=THh$HTSp2f|-5REsepQ$HKx=UWW`#g&8s$!t%Qc!-9?sbT?nFaRVpV~|_9(=5Ag z5IHoLB#H>Q_6&}n6i+*dHfXl}fn+qRfM2M>6Z1xJnIs8BtQN-sPcvfwiRoki?RC<N zaeRSGcb<&<R<P=}Z%Nw;<aQMleSxNH7izQ?OyNRSn*_{)em}MK1B=|nRc@=Y5*&8| zriO@!BUM@hNeI)dh^}{-HrNIz{hdv%=zwP}G+<MDuF$RRD4SBOBqNi_*5{S2Yg#wm zi$huwJ9<;8Fs#*HTXibloh?vxi`*a^4Lx0@2;^w9g21QBZFn(OSU0<iG}|QI#!NDr zMC%TeExl6&rSkhXwepESX3!i@n>sfwfbi5ffwhj@J0xn}0DVJt^haSLnu}DVkkJs4 z(w?<epf<~t8dO%&Poc*SoI`Uk1F`7fu}*ZbLQwTK!iKq!GYRq!)?Zr_s0#KoE~`dK zExa*Ng2Vb0(Xz!{MJLQrLF)c#dbIIuU_3euDG{{c?)r_d5Xg4SBpyuH^gA{GHUb5K z-=hy8!(0mj_X`5=?C@*bq}@Nfa_8M4X`Nhvv!x4&Y%W@H&ZBz2Q{rB!?{8ohVm0Hv z5(w_H32(-}NS(JpUFY}WDT7k<@h=y`5~U5l;9^J@8Fn9-{a`j_FU#(oU*HaKI~<0E zQjz-fmgbz+T8n=&@0agP5v!aUmvL>kEk4606&p-lkWoOSdtj=~=S_eNb<57&1Eq=o zPSwl<o9dgt*Ec`E^q)YFb;f~L@b_9q-R`j}W*<T1o%s=^U;s|74Xv@c^<2uhN=nD& znG+0ZCZMg|pR5^2#O*sKvEYyb2M<62!>7f-1^}Ey(zIgv)Jp7N%ud?0uE(sqRvt1y z@IrUF>&}lY9!f?BT%tw%XyG8a=$i@Ei|=|73YdRIc8&FSSqnO@{F;H>2|m)-d2|I> z5BCKGU!^^$H#})!v20-l-b+Ck*kM9T;A*KY8Hlz)x$(4ZWH=P499(2JiDAYQa>KjW z4tkl$j&u>B7=0dV-X1EIJF0{n^w<y=B&3En#MjMXSX9v*-vkk|*gzeRCteV8CEZcp z1hXRY774a)+z^^xu8(O<L8!iruRS5WQ(YCYaJWX>=7aa+5LhXHEOI&Odiy?6M(JYJ z=Y8K?napapB%}(9p7{zn$6Y8ThJpDF-?AKK?1sM8V~5Wf-XQP;2ld;KiHIh0J7pRl zNAhZfFi125_Pgq3eb|Gf4cTf{J>I{x-wUe}99xQ%uK#zrg`NOC{wDkI{6$5GW4h*E znS@EUN)T?%{rSrnl1h$D=k#}(;ele~^!XngMc|h!#gPJCE|t5RAq_O=(!I2ZJ~=Vy z`0ny9v#FH$?#6gDeCy*@pe{<pZ2Z!BGX7VUD-qnAUdG8^QzFL?0Dsx3PP>7YDtD$G z^BXwss^uIE;U^S`5ma6`4-{}hd$ENEf|{LvBO&#N2&ZpT<Ua9tukG02J=NtF|Mr9M z_GCV;rZ`vrIn@W;bY4_OHg0l9BYM=bab<vj*Z;~-N}yD5JYx;vHw!6Ep%!!Q7U&zV zk$Epa^diLTi9&}<k9EIueNM59rdVZG6zA;i)<g?}bOOf6u0JxH8-`lpN(suz*#ekK zpja+9Ukc2#v#N2)W1h%k0ql-`0)Ef!;E>mRrOwRDz4}gcx%g3Cy7=*A`^N|J`|hA% zgS>n|p_&dSL}iv6&G+R!`c8am3Hc$_w9HvYrimFehe;1*XX}bl4BFF-j-hqB)d>T( zp99VPW$bDzg}(sx-><V`srI^~|CMH*B0)z!=meQ#o7dsGP#W7a(KgC5eY9*uh;hy1 zYK9N?%)w)q6IjG^L@oF`Nsr7l7GolIeN?54vclVF5;8N(3$%t!tTMeSe~b^Lprwp1 zR2qq)29iqS99iby)eNtl$S|QSK#dc204FJW5gVX*eO#cI6LjrxhRIRs7d&Ep5<MSa zIouHtaJc<(;g!%#3meqi*DLfEeUuT3!y`Ka&G~^v(xk2`Uxbkn#(j=98=+gM))#_^ zkrg9!j5VkZh}Fam!M#U@SB6tiTl8#EUhfTB2X(jN<>Sc`5@V%~MNakS7UpKn-p~dl zN9qNQ$&)L{VV7A{e+ogM4a|EE8$+?(tkC|#hpFHeF0`dCo+!j=DIv@s7A8U)vO@$1 zi{*>Wp$!k`sP1Z_0iRAcCLj*}i4<?8=r4z4;cu_3hKr?hiMR{|$K41NiU|KN)~%bx zVUyuL1Bt1R4+B?6MnwOPe>mMJvtv*`NCaVhB5*8UcJQ9)KSK-B3WNcqH%NVlC{6AD zr^FQ9W1+9vKO^F?V4RCO^!Ob*PKXm+SIaUo6CPr6krR;L*ov7Rm5_^ba9*A|JAI1r z{!jQa<Cl_#VKny_BY?(DXN#tVU|UPHbXXCke=UoJYUau&+~yoN)iLZBDu0emQ*P~* z2rSA^$m*<gvN9!ZY7@la4%d71BU9axm&#Rt*xrto1Cm@;jhf$dP0j0=m6w_}I1@H~ zd%t*(+ahmxqV`C9S(Ndz7`P)EtK%rhwNqsdn;lmzcbg?E6T;5xey!jfiNt}3SfSa1 zSy3$)FoxX7SMdF_@OPFlo+bQZjTU!P`H2Mhi=Xsg0`xB~{A+6XSHDmxpMn-n6%ew9 z@6qCV-r+6a5MNqRPXXbM_FzY!?=(0iaW!rb^$t7~3G4SUSz&?YI>jScH^?bRpERr- ziy7)|Y#Xe)M0$)PDmcK%tIZn@%s;f0<+}d>Oqo#nugq6QhbutDjdg$V^Qr$4W@f<# z7D@~)!F&_gVc}i@Za|^HQb7z=u<#P7K_LHRbtwEsU>6EUmC=ULQ_=#YeU#P>qo<|q z!)Pp<N|a7}T5yrboQn~EMGQFb;%=0r4$T3uumAuF&@Z&a6S#Z539pQbNc(8|<6Rxg zO5(boelos?bjpD#q40{h6saOtg&8Oh)8$CJD1qe;clHL1ATtq0hrs*}bGE6mmp~)G zO0HKGIw9rx&CHn4;U`|d)xWvov5g?BdEI%EmYVpzM33U%>PU7?Do^)B1xOP=zVkhb zUo;)sdnQ^j-*&lvs`RGhD!@1^NHygIua>Badh!>v1C0&)1)|^VYb=LwvH)}d<}xBA zM$$$qZ<GM}_=V5L^<?<PBdE=6XUT(YSWooSK=Rx%QW|Hzw|b)P9maLaG3adYXG8UG zy=cSVF*!4^<a11k{?mfSK2Pl`V;NARE3MO0>`8D|jA?n|+!xp2NpQKGj9_I(NSfOD z&!vv$iw)jRTj&>MDNDAhKdf}}KTGVmpram}OEQj4hHd)V;5MKgA@b}(dMIUEe^XYE zQGc&r{GEcoz!?Ia^*t`Cey7_#|G304^pz#AC{ETU{ckDTW(xz@aY*H;EPJ27jc?<h z_rbiG`OSLz^ve^H#}yKOxziu@icG;`EsADWHa1nNUQcqW5K1!Hf_vGb3Q8q>TU0<p zM|1(zV1C4uXM`|1V!{u^p(K5zMnBNH5bi$2wWl?k{s{lVJJcg6c+Vy55JLQSzO;ID zL$<}qafCA+NF@Ztq4z6VDwT8z2<fbsF?+br;a6CMXD_a|m@2#^>WLzTwZ$~jAZI+2 z99Om(sT>EAru~fnC1=%FdjdPTD;6Yq{XT3NS@g|Yr5(@DE@{PaDHSAh>^pCg;@jKZ zR>EDs+%_F$#Lu2ucuj@U;41Oo>ob0MMMBu6;m=5YSz@&?56Y!-_EI?+M6M~3OO=jO z`JI3;052W92|k$MwVfGc<JNl{?aTF-ux#Svx9lRnjqwRSSQ)d0))DT`%=7f}QR>|6 z;ufy71*m$OGnf{OropjIn$U)r)h}0*p0-ELjpr_W)_o$iI<9d}Zo}FWkfD##8Jqo) zJER$o3)+4ZpN@NngAG#t5DtPe^c%!KVnFhomIzZg_WC#OY4dNRr5Y`m*ZUg05!QCp zjo15HF!uWv<O;oB#IBBFdx9wMzt~W|j?K!$s%ZY-I2*=YZ>eTjbjToxC=<V%$I&%V zE!5BHb-D=m2>uvq+mP1X;$dY9?}ZhAe+cPq1U}pNI@+w(f|f=%!m|=sHbdu-J5TwZ z-RQBdmX{&x_<Am_dB4q9@wq-seEjRrDCrqTH|d%cCF5EWBGO#rf5=D-vHTlhrJLX+ zUsw34$BRG=5~HDhjKrQQ9imD#Bj)6QIap;G+$IbU3J({Ap4X)+2!?#b_mq)1P;a`| z2X|{fDBsxQN`=RxS4{&u<{!%Cg1GQOMjsGQl&Fa6NQr1Gxkl(+WFRM-2hF7Bd$lHc z+Bpw$tz0+IAG;G5?K>p?xForzw+2NDc^514N1y!CkS5>lp>uQ+yl}9$*6b4Qbv1&7 ztB7##m1-#d77v+$dN^ZViRLFdl0jfjlOK4WIJX!cWeHoUkhKLjo!kZRuh^so>pisA z@G~-i>djy6uwFahkrVg8Z+~0Jl>>fZlCW;lluwJ{eV+81%BCmgiUYgvuBx4=bKC-K z+p_kt%<01&(8JL%iezZfKl|H2c|99+t+e6ejz8F8?)_cR4@2*~-=Bgu19o*aqUTFq zaBy3^d?sSi|1}J#M?=UJCKGl!x+*G_j#->w-Z~r~D5pV3t@sjunk^_cmA!I6ZTRu= z+gZ^zGH$NVn@9&O84*Il*qd@hQ)Y6|M$}ofw3*4#HKQLLUG$<6)<%BbduY1$EYvX2 zh4{`O&NFYO3J~H&bGtt@H>FL;vJl>ve+3EH>W^>{yc}30OkE2#A$+xE_k-VH;jQW; zk{|U(MTgGZ+O|tn$ifU*7*QLx1jO;XE7-T!_y`FS{Zx5u%8we~aTBVb#hOAl6IDlh z-LQ}DHSrNVlpDJ&s`HJvXeK)MagQz_9VmLx%<q=F7i+LIWM;lc^W*%l`Rwk-r^PhZ z;@qR(woN?`6b*f*GJ|F=m&((eStew08y=+=-XsL4SfVVJNYFSl&^Ut@4>Bz3q-8r( zZ}?<<NU|I$(vPy5t8}6F8mtSLF7?U?TsVFw(rh2S=)icx5p0CPF}G=h4sg$SGG;n= za^R(#nT*Af9h2G?HSc3m7Mu(8d|z;Cp0O{o3*iPWUDWsV4}zO|*aIP^{9#F@MERER zZog2t%Kxz1>BsGLZm9@$Rb45pwBqa6wK2Ie>7Q3tx=hcU3SeIS4*Jhq1Yw{55Gggj zX2CjlqGcum|H-$;gC)&-f}l!KR7}UsPfc6w5j`&&u@_LS41!iH%0vf45u*l-5H|)n zBmI@8?>mxkbiU;#s5l`_6?j0>KeYh7k~qPWQei1oY7I}Iq#G>vKwpJ(wuZm=9UI># zuJ@KeM)Z>%(R;8s$)JQW>mLpeL<oKz4cxzLOWAcl*}S20FBX<)K*3m8dQU|g5QV6a z3&*zO6*%~^56%RiC9(ef5es_dP7lfP`dgG+(@qWO&s$imou}gm?n$p@fm%br`6>W= zXt<p93C{-|M|8l<;Cc%}H1p97U~YgY9UxBDH8Sg<9$iVPuB5f<3)Bi5FY9|!FxYs5 z<k%hHfBe(;?qS7)sqs~$`tIS{)<vrz`ds5^WiR|pL*g6IieI^zt+0Q=a^TQ$NGHk7 z^sS|vm8o>Vrpx1!PVC8f&nK-Oh_V8KhFL!zuUx6G9(&U?2CWmX6@~gW-SWu&;X9#U zuvQDkY3*fX%zYr~4M-4%y?D@RmjtX*G-Ny_DlUD)MTX^S@)^hfr!I4OyS^-~gm-rn z9n)x2@vEK9*#3DI1QuV9+K5<)cnY(YE!TpE&-5kb3d26WF5U?EUExW+*n+(E|2xbE z>}sJCR1y-s(2@$v_C%N9-^zPe!J6YGZNyG3!vNzy-cLqbzl)lqK6&hM9pgr0ge@3h zHhP`}^#L3#Re(jC?T{#tJa>!3NiR)UVcg*g6ml+xgCq(xo(dIKbx9qQP`h$?%@*~P zxSu6mX)L@!Yp4i;hn>gut(F53gCk*6mrJ@UI<sfYPNL^{;xTls4%Oas)iszVVN_Nv zNA&rjFUSvwW)8P69$NUz>n+}J$4Ggm9XddC&^JS0+-u(3K)1sOGR_^Td|#)qldILR z`QEwcG1h^iu!D`9w|;b%@<~c9dXdx}0C5PB8)6}w5ke99y%{tNdSqYa2XEDBpZqX4 ziO=J9y-)w>xa!bb5Hb03?}ml9{Nge~0(qScLtb4qdJ~*2Wi%9IiFl%(KCH9<W|6%2 zA1;&;%w3b31*_b*W|JOM`mVkIt0|T78#v^>cEm3`^KiT1EVZ6l{r|B>G2@A2k6o%i zq;t=gA&yA@_sp%qybnZlbBJ^v3!B=yve$6K*#Ez&yt3SK1<&PN#K!}nm@iMy-|wx~ zyf)$QOZ;y<4E0Ay7w3mWUJQa=5F~E9hZ124jiKTgxCa3iE#^ybSaL!+UIkB%!^xQ# zU^9j<(`*)0#T$_Hhim3BXC0};#%1ExiJuko_F||?Vh~KXQ@S&#FRGJ6FMTchFnbA< zuC0X3i2k+M1hX3h!SS%6=n};Kokc(JF@w3*oAA{_jG&>2@BrdBvCrIl-NjZDtxab= z4DPDcrSU9zlDQjrCu`z^FD6sV%EOdJJ!HN<&ctln6mzSXPIf*HVGd3aAtX)95t+=! zSubLy?#47>o1S=p@X-1p&~ycx?YGrpOZ@UXZ$d9=hW8ux&%ZIzy=v1}nen1(n^){w z-%fVSC8X+Q6D;QB(K~>QPtLcFi>*iWJG(rJ^i;m>*HYk5lOx?CAFbKDK<!w@!P6f~ zi3-r{Im991%V`L>VTHgqrb*dCw*bY|&80~5B5Pk>yek!E9DI2w?AxmMx>I!2=R{dD zq~l}me{_t6{d9eC&EI9IYx+8aI`L&(zmh1kML^tIr~pq&{_qS7pZs{VZ$GyAV-7bu z9hvgKxGUcj`OdYsomh3_UluHe%2+@?Hf`9gOo2}Aag;^p#Sw3~ayjiWie&=%FgRO) z9^SwLzzG~QgcgKFkXfRxt4k4<=skRYaB+x(IF8+YP-r1UirWB+fKc^8a;<Zh4u#Xm zXCvCtKtD=JDoAH2pA_7Nke9giydq<*xouE!E?yi6Vi^d4P>B$NpPS>i_^Xo_Ybh?G zFQ#QL+AU2O>9L^vRc8$2<s*%G?e>R9?kkJ9<g2^h<%EiI7LFH5XJ;&v(cB%3j|1}D zNzX=5YYU@x%x-xIxm*<9DG$%d!;=^(9m6I!@(nFtEbH{RaxFtCEKKirm1V%)uDLtu znoblww@><vJ15+_jx`mAd^s+dc<X;y*1gCdOMm3?7Whx_<^&$TtEc|R++#PiDCVc< zgEMT+$)=>_n2(Y-+e&vqS?>|4`&y(hJbx{RL%yjWWQO21f69)(U+3a`EK`6j>avP4 z1qg;-o2R+H`RhtH1;+UWm;!^>-gaR;-yKvwCbO;ZBPLEr@m*92)buUn)!w_%umt0! z^Gl$Mg})1QaUyAZ0S$9VI7WsBVS#Qq%}){>H7b270|tca%UKvq|JYf!)Jt9*JBGz& zM65CEd#HbsN<;((I1^OF$O6=ph9Mkw%nm<xxu0i>j~EZb&Q@?zabX{N#qV54?Ig+o zE5lz@Ml#r`GZvzD*wj^CK5Plj<mgvL`3|`WOBI)aJ`>MO#=%^9`>Rf*!ggQ?7|N)a zmhYDLKh0Eb&GbY|5SG|7@wPTTbh9jl6Vu9IMt~#$1XSbXec|Qz6PJ0z-EsOOE42u# ziv5Tt9?nqeE-P%ia@7epXjy9IKiA4dWc%16PwGXb4l8QkT?uP_Y{>Z50e~Jg+>X73 zg6B}zK0NK67bJnJ&At;mE3cFv?<_@I8s$B|E~AJe9DoN!omReQDR~>5eA1p?-6a!I zCq6`MNaUOIuc}uT7J^<cZSTZ$?3`PU-KbfThE$n|v?~ShE1_?`c5QDot6FcptOJm( z9T^#MeWhI-@=QU3sK{DoVu*!*3ILgk?uUTt^sfB<5yT;h$cL<1L~rT@nfB<fDyN1U z+!!+&oA`z+=%SheED-UKn<9yz`&DnKAecb}D=?A@cuLOzuZYK}qGIDw)Qr5bhFinL zd2|0Mp5?1>j`|~6d$?0jV!nD{thqlBGyaN3Rt`D0&y!B(H{nqS4oz!+rCJDraRJ~Z zrb$~e;`<}*qoqGL;uq>1Nmy`Xbgg3RJ-tO=4xEb)Ulw1}nhIr>#S;R+pE2BfyP$)S z2P_7Y(b$gr?<6DXw2F3&t2P{nSrReC<j0u1w7Vjc((iKmjFlvY5&VM;@-QK^GJKAo z`kEEged|VclR6x9A{<9Xn^vv4Zs0q9%_6u(er2R6xr#I+9n-WWfOGPhwrGxeeh*q4 zonI9(nQGWd2xlwcZHcoKye&%9nO_A+jIwMo{L!!BZi0KDNYkd_<gAx!$j4i~80imO z=CHVi7!k_HLo+>2c+q5!HeS+VJii2G(jY#D2?=GkN3>5SW4NXyvH_GH;;yv$yl&)Z zl$=X2T*daxs3O@nJgKN`xCjDcslYVP0e}d2s5c*)pVS2C`F3bngc%%<nBeQ0V}DAB z9G(+#43EZg3F6Fr0svEdo~}$S`whPZbyX!J#w<Z284Ve=Q+*J)KKi7$Nh-MTs5pNz zlM|^Dos}X*9z#H!mN!X7bcr&%0}(Y{ya~7>AA@YZ7@~}3(rQe8Y&;FF&NxU0OkpNS z-ZeTX3S;1#g9mRz)W4pDGIK4NlMPb&_KDnN7wb0!LC??=GL@IwKMk;+vKzy%NBQob z9}}wZXuNAkvi($#10Y0na@ocJ5H4K!Y4$v!aSkyN8U8hH?mbM*d$jf-m7aH3zKt(s zYNh1_e5-8*mN%Izau>@BoCOV&(g1<yOd^p5Am<rx(T}*hBU3~SqsGHY=nE}O@;qU& z5mU*y9KUTJDP+Mhmyx|H!KjmwjAmuhO^M~hvqRz;%U#=AvD=uTt={bp7O^F*m2?xl ze}8NZnsN+<wn#wJ*1E0O2KMqhMv?IKMKj{JCd|q3!$v@yUKi4W0%KvnYd<P5%^RcG zp{5z@B6{wwGqy5+-RewNksLb21Pe;+{NOm4%iDwjn|dTv_`d&R+IniR|4qO6_D}>( zB!F$m9hJPd!@G)9h_t)n38H@}VyF1CPw*h?5#0CSx=QHd6`G=r;I{i>UHJ3l3=wX~ zcYwaaL1K=4Ly&kxuGLT96`0|*Ng{7{gar)FDB%$fK|VT6T!TmTf&G3K4blU^4RGyf z^FU@-5sA7w!9YM(4fuWuQo8Ki-ZwK-HEyBs%?AXg9U^}7s2~q-ET!Y61^EK3NMeWK zA#J6r5(N=5fy2r|Y=kq_(?UAg!$6DDd#b=GK*Wm%Xeblxj9jBfor5EKIXttyvORQ! zi#RKx?<14&#rJuBWk2OPGA=CQ3;VL$fKB#cTO$~D2CP=E3w6TrW<J8_VRYhuW-X{k z>sl}a=|4iDi{R5M&d5_wHs$|^j>_O^8A2L!@5-ZdkJf}me!zAM;#nBdJu2+8Z4=V7 zB>~FAz%KaHlN7)Op~cR+{=f4GS(bAx244V<v}P3al4|}tlW1gt*VwI$!pvIJvB1lS zPaggCpF7fyW(GH2A}P0??wK@gM0dG1!aiTaDQyp*H{h5q22qtvgk4EG7<QOa6f9r- z*!Wu_TFTQWN%Cj<&o)dmvTBBdGpj#%9$TQcd}HoWmn+q_s8t_V?8<dpaD#Zrv}>zH z{RGRbb%$smFNwHlFVO2GP~AmA$RBPT0ZG1C$ugBPT@mIo-4srs94K#chZc-(K(if& zL9+q*{vgG6tIx-}PAcVuX+=A^mHvVXJXgh8Or-|E-{Cu<bfRRqhX8+6$aIx_ON}>G z@vbsY3*S~5$}H+(0HX?a@LUhxxIyYCZR(lCh*C-@8|Lt-!A*Bgp>zm|hd8_*0J<x# z12{aTMsTJ_A$;N?O>D)8qX_0F1Bi3&`FPP-nt+co&1~d2ku<njzh+egc8oqh-;gM@ zo5Dd~bX4ECpQ(=`BtR$;cqqmW{Ms{sVT&hEEsY=)3PUm#dYZtQ`_z2oTX0$_A08<{ z2Z<*LDipy#AOm+GYdcgm2!L{j?Chat*h+c|dX8{eB=CsPlgr3hIlO3Ld`;ZCN})PJ ztY}b!+L1BHA5M{c4S(Fk^9c4=+M4-(ZZzm8LhJV?Y=t%>M0blBp~M>Cu`;19m>X=% zQi3n!`bn|W(9jtyVJ9$&JlYg*ge160xrh-m4oDYv_E@(Pw}PvwbL6=FSIfNfVTm7H z)PoV9f|--r0L>w*QHp^pXVB*Z%wQ=A9z$h9<5Y08M-wdy7yzorl_J`WUNuf;KrJ)q zD_k~Oz(%avX7O1OES9t(ADJ;w<X<3`hJTiMhXdOvyV-*jtk;HqQou*IUQ8`L2UYAu zkRp3OSxHvD4h!qMd_B!V20gMpE?cXdF8y&>y8zW>=6S91cpy>~F}!F){RC((8W1cH zl1L1D+F~{T`n8>s?|KN-+rtxCE~e(Hx(tN(cC5_sk%W+60;7?l@HCQZM>6T1uUoxl z<E)xIqYckrEB)Sv#MJN+7H%8DU80lC`dt-#o=By7$V01w$5<x4jb7!hpX*wAORZKs z`KZ5XZkza@fyyi2=hf!Ey=p%wO^}cCpJ!(uO!XIP-{x6%<a9-wFx5nzy^z~eqzb0% z;*-%{2yr1eQ}BV~>0OTn#4qi_e{TTjab%*tVNIWhwvco}$mcGJYn%yNZek_9Hh#nT zuAYz0Jw6~5PFez^a<&*wLF4q@P*{k4sN~(f@x_{Q_qRE?)d1Zf-%i?t1j0|m`J()) z#u;k(T40et+OI*FSz*l>Sp3xi_#I}4nJ)vzdAS&9XTC$@#L5(=sdMUS!-tM=Iyp0f z{Q_?y1s!66<)dEENK27R13Vzau{5h99}rrucKv*?56*$|ky_La=Ie%2qo@kcs8`tY z2ZRlaBD@b+;2S=&aN!dOCO79Ntg4xc>y;4W;H6)JZpw#2$ef0aveO2m6?XvgCB#W; z=R8^xTn5W5B)DjG?>2aqel-Bfd}O^xna5@ipM~_pXBRvM%aB0$P~l~9J8a~m1uN+# z!3_>l79R40d6NnekbOQz;01I}nnE8@X<7eBPTXiTesR`Sn0y*jxmm^Lo*^Wlp<v-8 z?8!16Dc=(hGpemj|J|RvtZ(IOeYV2kj}IIp7l<@l7ipkRTb$Vca+k)rBXUZ=bz63A z-e~iW+nePnJ2W=$IdT5X<nD%LPwu{Th5=$3xt=x59O^#pKR+8%)!8-OHQUuSTPB(A zNX1+fyIJ8<E?1ZQi1jeGgb1$O?2a_H^_bZy+m9ZcS;k$5s+9a^5D_a`BjW$Cu9&l~ zyrG7b@Lw2F!!12JU#c9Ru@;pD+@YINMU~%UDX4-RnAHKeA3`27Rppy$Ci-D-0#%y* zyGiHQjLVFeN%Rt}j9KCSB_aEzpv%SN6!61*;KHR#?_-sXPX>)@I9I|87t5W@k5@U+ z)laPp82?g!6E`|?_~uFYAT0*-{FJV=wtjxfixZ887S7SX*Ix>#5se@2Z*+#lLT-o( zux(>^YCY5dVWkh<Vz*A|o+q47KM}Po?)ajK;_KkgE1(cmm}ZNBlkl8~ux2037gq@Y zURWxi0~<%wg25tUsuZ((Z#cBjPzbg&Fc$Ee+1ITMOtd?c9uqisvB)WNwW@AYnVh`9 zmn0$ha4jDEyt0vU@8W8~g@J$4Mw13B;S67k{f~08so%X8MC^%=XzfAu<WuK9PZ~@* zS;RKZNUiR)d@c76jq0%jZB8}s??Cyq>JPRp@qEnNOqv7UU$ughqmqwpFnH$s(k5!( ztJt#J53_xe4~2W*E#Kmi+`2z}PuJF{ZX?IY8?HAtWZm}O7!@6&H)yk=Zn-6~JJKLo z#~}XRQ{ry%Bl26j&=gdy*Ql{?OWP(w(&Xx8*~>OcY-}*M=MHQ+61ZvkVewKGwGaG2 z)aI=HbT7j3W~y!K0}bofpZDxrrI340Bgi1({Cdm5{X2J-(r9s|d@m~U^p?6=1!<&C zQ%=lPo2*r|Z7yy@-0xRrum~k!jrDa+Z?}{^xC`#Mkg~#*l(x#%PVUS^>WfnKuw4;( zl(#GF4`5p-D&8&V{rxFNYhB_JK^Y1@HaiR^?7#6{ak}}KQe@9VxpdKX{IzD@3Dr}# z6RtB!8Dr6L#VMy=x}M1f!*U4!Y>3d>b92Yj`CMp|A*e@tX*f>ok#kz#dhsIM1sL+a zY1T_0_l`*APcO=BrIUwA)NP@^0=^ie633!(=%?}PUOvR3Eug87zr}Ly*S{O>(zMZE zsUG+2+%5H{Q5p_Mw18%PAOdzLSPhMeQ`>AQL}&Q>fnw=5v~`^7PSZ-iRFBS#_HDjT zERJ%~s%sr9JSsN+*qaa`6{~({154$%)$g<46xDq&@=V?4l#2!Fz;u6wy%lb&`c7df z_He_ZEf(Gfb)Mzk+1kI-C0$G^AP{wcdsFhYP=AqE@Z`_@R5M9O8HaO9H}|UGEcCoL zGuY<c2S{<(#nUkQEJPO4R)x@iI+Wk|CG7t>m#F^McE%*Rn26Xb65rj%t=eK}Q`VQ; ze(5{G54gLMS6F&y3)=UU_pjOu0|P%DFb@aT+5Y1^aXS`e?y+Cov&Lr&_^#8x`tWFy zy={u_tB5F&8wa#)Ach^`Q!f@>Zd+{xo*6jmKEpznKv<B?_5?_%Phk@I?|OQl7{vaV z>KjK&F1JX?dc0El?YT7^3LV#uN<~ks%r+H@1NMCoinZOZZ&&)b0Rx=gx^(F}3fdVi z?Hv(2By1=K4)3mpCdE}`bT~xkl3$y8Oe00TD0p*k(?F$9n4wkr&U<s46ow3ZqSt;K z*r+YA2{=9;aVsXKdF`uyu1Z~c)a^lUZ{Gp<^uXZT=IE&X-f*xxZ*TEF@!P|e_51a8 zT3hx{YDA284&MG3U!C4NVURVs#lwG9PKlJEAHSBnMS3|Kt$t_I7eybpjp~ycIf~Xs zsI6sjqp_MjvG-$*!dq>A>nq0O<Lj6=dlXeaeOIjSme1ZasZ?C;e>rXRwaX^#v@PKf z+Mr0~-j(Vt4@)>bU8I0%4!s?trM>smX1Uj(Wp|16U{au#?e~Z0CVy(4xcA{Ux2a$L zSZiGJMeF_R-#^Wezfrv`e`%%hi-e?HWeRG<cG^7bI={8^oCPoc-0<&r*f)0Jm#!!n zO&hS5=OxI62krBsoc#I{TUPFS$-b21&t15h``PSbveA-H@`?I>%fE9zZLj|_s7}XJ z+qd1Svbuffj0$$=wY!ngw#QNrUYvH_Np-qc_T$#iL!7VZM-B(WuiV^g=b;(0eV^&0 zGs~bE*M<wT<|12T6XK@reX&pUPMlwkjnmMXqaB*Ur^)Amwy45jC``hI7#zleR!k~# zT!ccW3Mjt~$3$=3Fum*F73YSI8^2Sng%)a5LrgIYkpau9J0km^pwp7Lc8uW$+3&oK z8cJ#=QIjBjj}FCOm2P3e?UK{;$AadS^q%_2J$qJk>fGCDrg*@dSa1EIS1S&8V^7s8 zRh#p>Q-1g-fQ;442p!=UDAQI~n}b#A7T#yZTqq=-4jEgQj`nLznKY$B@ycPK|IaBD zQAj7d)BjDr3>`Ka-my2{Tg|VLpHgogw)xb9Yi|*jGAd$MT`=onxKF&Vc1?}rdX2Ih zXXaiFI@gR(706!_E$-isrSDx_pao}-0q(q0>=MOcEB060Mu%%lVt6wH4z;g_cK)0> zx5moA63!E2MzfA=G4X!VJ9No2FcHE^-e+8>y+vOUvU2A2F|InYHK5Y#?p)^mCT~#a zRx>ki>Zo_~XKAuCA{uy}`66?7kpJ0|dU1b2=_Vt2poV*CBA_!|+CsrRZ;aGvU79C- zU}$z5F^&IeMe;bIyu3eY@j|#usyo)x&f>FXs1o@8Bwh#J1zvTA@}nA%j~I=DFOWHW zPYf{6XXq&`vtJXhPz(eN@<h?Hb2rMB#{+$}8+U9!x(K+5K)3;`!;|uS1}a?=!?jfR zq%j+B&5o{l*CVN^amY|loMGjiZq|#*!H*8!_R2|VdTf&?xa(vx+wAeG`=LF%8^wYR zw|-V&p*78#pWvc=e-}QppsmU}IGJCf7tmv<oFdOvTJ!0f<M2&jymbYXzQJ}`Ye#m5 z%{GIZu~$nvZ@Z<@hZL<dlG~r@J3o5b<D}etTr<kR=;{r}vsUfXim5f54&JY5b+2CL zcDuZ&``c-8ui}JJXmYo8`S0x0mSEsqxl_rt7VVwYA(2s%X;IhlAz{<qWx&_Gh(|rB zXGvC8?)sA9uv}5;&gTP)RV(!x)Uq|3tY0N>eN$ejzgVa{Tz<jg7RB{sW7v#Ecj~?! z|0d?OoUqw~(b)Nq*PdGY%Spt&qPP{$LA3`VHk`a)ogJEG*OuMT3{n67snhg&!z&$k z%^_utuCQ!EoBEbxX8k`m1b@o!Zl6sux-))CYPI?RWFIa6re5RNit0Uft9G0epDi0O z^h-22Wt%uU<GW@gsqg1EqgOUr*H4ty68J<Th*bpIqTg#Uh*iX+YqGTtnayN?2r7se zKzT~vy+JA#8iz_k^VY3MKFPy<^LmFC3Rz;i?Uq+XLK=<L*a17kx24T|T?*O-wr#cD zb&f55K}OGGA^lrFZv2W@T6=k9>7$ILL#vVlSxlT{A2i5q$9&~%IvDxwL&+-D^@aiY zo0Zlt5gy`G^I>6ZM>yX-6W}a;WD+<vT>&w4({yoW;D>Y2Zw2D6RM*g($znm?-VA!L zKkWj_biJIsZ#~=U0zKUk)9YD?w#8ex48J^Z>Z(<|vR2^A4?iTvPH+bC%6&7lkWvms zj4B>TQHr>2nKp4-=XzU2<iF41Hj_=Pm&daw-@K27)0t!|_z(jV_H2cFUqbd}IMe^k zYYZ{sXD_iEQ+xgCU@#TC%df^cynE-J*${>pBr}Mx{|t;7f?qX0TbqndxVKwiaZ1Dh zgCVB2jS9bBTCzA4w%6ySPhfNaXQ&z+{Q?ux;d?L=-lSv+9!X_H3z#P&XTOB!E)G_X zE`5~yv1Wt3;7ou)`3y12{`8g5P``tw+Xa_4#A`p>pQ7QNXDiu4;u*U4Z2Iz<eEXDL z)eO2S-uLG29P-__U&GgSO$<POT=jn!VcTQ6UsLDGz>7K$V|qv-M&ivL2baO=Tim{R zTIs1B9WNd6=s+1{`d?qsoM!ha1MQKLTXHZm*HE01F?q>&|3&|cXIH7O5znlRWIx`& z#p7m&-Q{pa)gGg*Q88@qZ{@4)Vq<)_wqDx0`gp`~T-?js7b9}+hkeSGa@^Z7d$qNj zRvLI$E==-`h_=LlH;+`$y@}F2u)i6+uVr2QexpZ`>)u~(Rwvsli$)J$naW+WeM4Wu zA)p7H5)k#ybon=%q^~dO1#idl)sJ4TC{D3>@gjCyA%5#|oJ4uVj#C%#_&T}qY`=1k z;-Nj;HjG3E{a$so2`_dJn$vr_m2a@X;w`4;`ims&)i+5L<I67`j^S?}&@_oTXS4j- z+_k_hzMjIaPfEFy{(BFv%&)%fQ%T=DrY*GhUcKu`<8QMiN8T+uqpka5HL5W2gr;56 zd__F+KOmsTDoW)p!#hr0RJ|d}Y~)f0@B(xyI%%=;<!z@&&xHJYCz(?}#iq~+vhuGM zsqGYaH}5{Ok>WXt^(TBj+5-t?qb*TPOfgUc(Z#8<i&{uZ$O2-w9ynRa>bt*qS?BEq zSJ$@A>cPJ%yizxA-gF|uH_La9A*N-y)bTGaR-L~wT=;&!ci-_lrDfWMFk8>^(#_?D zIq2<Pl%nKN{?u1KT6n+feW|~}p@v%iZWp+}(WjuW>GY!WDlchzM`^8b%_a)TK8jB8 z+pwtN$hp!fl$-xU%g+9aBaK^@+owZKxW-sz^OHfW!Mzo?=<Rdsa(H<U+JtZwQF<Bz z8E9=Ofj6t}QWsQo2!H7rpGdU{TV<qPUo>YHdFG6fN#yGfj^~$Rhxa$}tHk`3AAHle z??s+BFQt1^D_uf<zCOJ8;|NoHLR95VeYS~yhwiz0PI+Z&Y0!+xsDprc;2pup@ke3H z&hfT(@||<=?!7w6IE%}gN*2RA;^r1^=9uWB(Mi@lQDVX^X}Zv$oy@0N=UeO!81LE? zLI2mDw1(3)z}lyNhudkyOoiei#>KRhy-pi3($FQJ?y!Td48J<-=(ua9zbf^tdF`(M zc>!D&jYeS#;C*uw%@tnmJ*~J3DSO05$M@H2gL~sTNr0f(yfptdZj4Sp;i7y-P5Qj_ z+@-QxaT_<yBu2%>Cup3G|2Eelf>j4^nR@r>bvmS$nJ^drlS8g{sh-&`XN20g@rS)M z*l1$fit1Q;_x+sSiUBLasnAm-Ta^RoxA+(*y)UqjQ>9v=&8?rs+M+MP?lZWn)7Jf{ zGmO2L%M+riXZre&Xuw8(LvNDLMK-3aR!vFS*#3;J?M~7(eS4wc;`gy9XOJ$U+wkK* z6ru|pBpu-UQHc89R|>x>!-|ze8Za(oGSQ0DY&**sGd`O_!pO?xJJKG$oh)wO{c}M? z{NO^;0e>lRrrW3Ps!91j^77ku80;7d@R7WYS=VLWAKr2M>kCOyr(V3IJUz-k{DwEN zs;1K~tYk}9`MA;6&pxyFU?cVvZ?)moJ;ZV!xT@PK;rC9}))!ITIPRBw;w_&04Thea zY}tbSly<eY&u=t($Z)B0(2*_w#4azqUHdhBU$<h@?SgF&k0oqvFMDi|+0<ibb=l1S z`|0rgv6{*~zs4h4TSlXBldI%?wsJS<`YU2j`SFVOSW!RSWN1t(lJa+pQ&RR{6W`@7 zeN@?=Lb#W^QFr3Q_Jw}OHf;7kuCs%F^cdme;U|YZ(FT?;>%j*<ZuRfbTJ1KcxZrH7 zuej4Oe!{^h;@y%_KoEs<cN1`P-#X~V9Q~0$xxtwG2rD?5r#xBqymZ^~TZN%V;``=J z-w*7s$yDnfAzV2Tl>T_5e45<W%lA48BG!L`HI*vcNPOaM_afrOz1T(CatBy1&!2s< zryE^6yFA33jLKank~?G`d1zUuLWIyRc&8Qj*p9p3@?MB6i~N?t#qWMuFD<Vwzbp<t z|L~@^TB$Cdyy_we@F=Y1m`e57{t!@`7$%_=(5C1FSs2m*3RGcP14ZG>^B(Nx+5PD% zLmn|<6W|%({O2C~;ej*JZ;cc9niMpm9UWV}XmGkCZo-JR^dBZ*pJ$UO;xewi2r`gW zrtWP&-uKNlZf@7;^UW%R50F|XPU+U!TviRa{!SMhzSDk1>ywA1jfW3ivZPOlK9@@N zmbx!&d<7#z4p;74#IY=p+2%m(x3e{`$f=Ct-8xo-AV0D7;x-$dpI>(=AA0wq{~p=< zybFXj<0sY6i>b-bg~f7<1n+GU_E`a+9@Sl!iurvVnUCWpnjeeeC!IuFTKVKjoViAs zC%HE~9zk?&sk74Qm=CwJhu0pGvYe>myjOQPU$tt-g-CZk2FYnOW$bi#$k5EZ`+)N@ zdX;aTG-yd3r%gMdYBfhd!Suw<RYGlXFasZ)^(uH+bWS}wTIryjX5N+Ro6w25kgmay zWzn%Gc=Epc&FD$?V_q1^%OCIK;>2<vpc1+03-{*U6qcX2HDm8ECRodhT681wc66CD zlxxPGpGpF1r=KdPLtOo~z_5Rv9onWYAetf=G+nc7PG#d}X%p-gZ*04CjpFO*9a$mc zTSAbKbzNbNLZ3KbulFoVkWBb8nUBv(I`9L|!PzDn2aKOA%R9|q8bh^UKiZRqMn$iG zc8(Vku(Z9C)8i;rSmZJBExWC`tZQn!)PM1VpD-&z@Cc-#{Ei#`e@wl1IF<4LKTh^m zWOJ14Jwh3Wl#x}+7Re@CA>$}3+1Wc;Nw#bbPWCufDBH0P$(D1RbMD{m{r<i`*Y6+K zxtz;&j_cg#`FhOfE#uXn=kJOK(7&8EdRcA0se!#WWWLHq@PYmOOr?zDAH|a8<99U0 z6g@9Au*a+;8n6JFlW1pr2mSA-00Cd35&fil_5>G%=!^I1cW)BT7L|ZoEopJSaT?<i z78f@m{3G)mQ@!}}5CfSiogeb76i9trXmu)s+J#C3l|Zu6;Fpcv{q+Y?INOWCKft>A z%XY9T2jfK<;t0u=BeMnVKnt$?3;5&ou)p7Cr*>Q>^{Pw!j349WkOINwECiu#dp8vc zLp0kOO>P0IfMGQhgQZvxuPkw8J;XQ}AMaaz(`}+t;QdBg@p`4u`9?E)YfE%?-x+Lb zv(r=LrFU-k<R-yWN%8sG5VP_z$$f9Bg%uZ5%>tJf*ob<+I6m<rH~Cfee!)H+=v20Q z044H>?OTZ*+oC39?5V{jV(q=4fnhVkLmO8wWAdxGzb9MT(PD$0gv!&akE^sWC(-!k zqF8ifj*_FqVr{J)EuYGy3^uMP2F(-|pWe4^KiQ;+5}ukG{m|49QH#r(-)4&PP>m>$ z>nw5Lp#~{M=gVIs*SOSHcr}YsZj9cP&8CzkcP*Eilcn`4OxpP9|L@tP&#*wZQywGR zy(jWl1=RgaT(A6My#78~FSzcB399wvBV>^oXFR?|Bg(NUHvWPzU1l|qrEu@}wDk@1 zR|mHx)}HfVsy*~G1K#r^7!@X_9=?3l^(;X$qjDjzA@wy|Wz5&lo@}**%J)WG_Cy3v zYZ;^TX-mQH7-KOduEIc?!#*QKii^{x?(v6=$8E3wrk*KT4CM94P2Vz}U`VznrpZiw z!ruF5uY>Tf5BA_;yBO1fL%I!W(69_*R`~PNh!4o<X@+howaCXj-KVl{WV}ukM}PD# zL@XWl`^(&MJCIB>B*@);4a0di??0HBP%BC5y@p~4T*W5t!df#?sOnuv6|DUJNG{Mu zU_T+B1&^z4;Y=i)-h*(*k(L3xjXDXX!Ya|bc=!{ZteeN1qiJ_v(G<(epL=#WdjA}k z*@WMAoB7z?gd_EOWe(C0uh`H%cpb)**ejk*`rfJ{uqsX>*?yqVJDmMZ4^Z02@%T(c zvPOLsAl-(>b23`zW9kx;i?mQgS3K0Tv#(5iDUTz3O{-Ynf&wj*TisD_6(f?$Vb%RN zV%r1^o-PRH2fV}W|D3HcyS|;GCI%}-kw=&-hN-D}{McHJ(ZkZPiYE;+=+Cr2I~}d4 zL3f0=+JV385KMstGX~Vzccqbl_vXFEYdBMFDaiD<Rkys+ZPvh(@;$nLmtiYEsLCq% zu=o15=kI162Kkpu4dyN~1zE?2OU(xz`!=HSobpexg<Zv;>;J8kNZPYiHQ+E?P=W*; zu}Z$y!IiTT$hOjW*fb<CUSSH)r{%m$+r*jV%<FkFTWG~380GWbW6{E7jp*HXI1%S| zLGYx`BoXEfceDgZG7yxr%U<CPFMrD1;FU3+-w$5!3$x_OzMb)4UmV9Aa;09e<IS_1 zi*5cCgP&l>n~8-QQ8yc{#&)<MYC;+P5SSIH>PKe!WO;3ozDU~257D#^M)Qk9y(fR1 z!fcT=CH-VuG#F?oE+BGuqNvO&OoP%J99>9QGAjXV`h&Atbri;9(fsH_W99OMaaeoC zl*HNI(8bypFr}#nN1A$t_y2mP5hZh8?ZxX5S9@ft1(zZ8?<LMTuN}G3ya<~z%p@^6 z#|AkIE)lw-$EDi=GR*E#nJZ@h$druyO<cSn*R$y|lq+M+rS3GGzOr9n#8JF!BR}#r z*9$K?FcAO(`{-Rr+9>>&kr9Whv(zQlPnM&;Ja7H*mK%0#Mz5&Xu>Z<V_j6xzsX5Qm z$0pa&GI**9AvCHcHVG~qf8mYzW!pKbk9`a2;E0;n3@LTuir-sx<WP-T#>p46OGKG! zLb|i_4;^VUCS<cuIISGnDN|a2g`*b%S!H_GX1S{+1s*--n0QqbecO#y<WQ1{m6u&j zr0iHvrl1||qFlOsR4on^LZtJrJ9;$?KJCfWZ|b$Q=sRQ#n<y-hiYv2Kgj57XNssa9 z_6JNVw42m!mg(CCj2OP5l}$lAHBXea$>*O9r;F#ATN!<jR8)7~y(y>Wj4H@kekB$D z(dm9>QU#{HHF4l53U}XPrsw-~bEi3zRO(eZ#|ou0Uf#!C>}mI^?rU>0bYdGE|M3WO z_~(TFEEmCM6P`c^IAsjw?$mdRx@TVp$&^I=bC%{oNEBr8;YRh>XM}Vu$C%qXh$h{0 z$$ryXlh9OAey0W29#LE=+OoV{I|Ehm{OhA|uRDLoH%+ChGJ$8psv?}GzFVfsVPU~0 z114k)@6DG+vesh*QR0*j9z=e;ur0@7Q<LCdw^OKcx4E71rb4fW>i0MNv12e#*b-nx zc(kMu;QQ!z;-Lb+kEo&*;rBVb2}H>d2rL*xRQ>;b@algu$L7szZ?0rtalA(HozMu! z{@b1?vcG8Lo@{^M+k!4t7sfvECh2JpJnj*r*mdNtvF&tg@-V6fOJ7vBeR1q{fxdI& zq4M&I|Ikxf83Xd3zur|>XS^Ue=c_v_N-XA)N7)2{>rV0Fl9F0Gb{cn2;ol)u>23Rj ztTDJxo$p3ZtVC*xq3Q!Pl6Y|oIAZNZ(D{dZbn0X)xQ}IJbMUBT-tjGM4Gh<C4{d>r zpswY0KmAU4-Ot@Ltkqm8C#k?0eM3`cG#jIxx(O8I2boxRIr>Bl5CsRq?fMhGFs~TQ z*l5s;5DaqUpDC225Z+G{lTO<;5SpKN2OS+C7;f0M(6;a7Ox7ZV3$kGnR?U>r%skWB zEmI&(-sqbp+(f`2GgHKJ@Avmp6Jj1sAqk0eg{6Qe)<N+($F)}3dGVH<QNqjdg!MrN zDzq=YUO#8X=a9dn*d?W}&K98=xS3VvecZ+24&zpO-P0W{de(-=gW6B(by1V&`nOGo z3knJ(VVJ3c_3HNPM5jl2`@xn8Drcl6$fJ5fIZ*km&H8W8W*`cN$I=zsELUrXaLJoR zaPnEh@UMQwFto7&fdi3yf3z2xYwZWGrC!jj-XM3(Z|9I&8DdVHBW$j{rn3aZg`9ai zf^2SzTk`PF`v>0yaQ(YSf7^V&tJb-#4~U0*CX>@~xL(YMlTaeONUrE_jpdct0G;L7 z0#%ji+b99O6=Kq4l^|+|{sitipAG7)sDNx;iB@fcy=fgZEAup&r|Td~u%a{W+}nac z6Li)^N2x*_!xG#0eG_qen*k_0srU6g9gklek@8>S3M3$rx>VS-vuO43V)J^(htV7G zU5SSHV!RVd)UN&TQ^<Vd$Gi+daUv~jBZ2#P`Bd`ks0${=qx?b_`*Ndt%Ab&fJ3a&T zCeS*u!GHah@OKbtePXzGd+?mW<!h-3ezqTI0DTfrU;nQ(!MYxXgas3}j%^Bn3oJ!c z_}72S0z0pwHZEW<@wKfOEs2?hTE|7Y5zB;rdS0(G$$vIeQZ1PBT%TDfx<zo3D3;c$ z{5oMucR`mHjz-%`^F*=J$0q)R_4{RxJ*R8J$fC0#I@9BZxW<Cqw|csEiXugxnA@32 zH=oJVG&MB1jL>%?PTa^8^|nPn#j_hIh{i<T(m*GmDnDmJ?HJuFm`i1$xjUr=QQlFy zBnJq;nPy5SIrcFP3fu?-!kJdmT{UXBM;1@6HBY;kt`)`3O%sc@a|$Ur(dqYMqF6Ku z#d<ru<?49(tIqU%Qs_QO$h|wce5B2P+qY;W1=LH=O=7w!pFdino7Jh<48SCXi+T5c zETnolG!wz1%|LsYDP8va+?I>}!8dClnHi7cQ8U&r5Xux=k8)wZLgFK)@fRwQA+J^R zCE#i)W>7ioQy{&L2;RZ^+|XlkP7~H1Y~J#sj5!3O@UTt<8~4=qeX$F@mw7eqm%8HF zHdAf&Ha@S&*9kqsjKmC^L{|>d)6)hL90Cew(Y3B<-@23`rI-{L)&2>#sbd=YiQy~G zU>UQ&m&mR9^Y9W%tGiL!{aCtmPG)>Rs{Zh}pVDySb;VAf&Hqial$&VVxsB>wAgBQF z`9hVQlL#H6g1~;=x`f*_KE!$5r%3!HTnl8;?(-!Nj#+%BK5=%#Ypggrd7*~0kihem zuNCBvdQCNw>tA!r_Zqfy+Ad5lX@+_&GKd@irvDcBhSMc8`r<i<SGqNbuFov%0q}oI z7xw5$ehZt~mGrkvhKi4E;|NOi%jx|*2n&vx83Pr}Q_Q9U#ZA>rr$6MRkL(F8Hwuz3 zi~z~bgOAFw8srg#J_U(1+0Fn>5qI;z@;LaZ{7dF#vF}H2JMQEQv^>>t845Aj!{|t- z-wiG@K{GE)pgz;u<>B+jB(#Mtb@tson4<v%1D`DmJuhwQ6T=NU%4{@q$kNAyar-Xb z;7?0o<Bx~oe>Ikv89RM!NTNAHPY{rYv3!<7*8HTiMNc4UExt8{JP~mGp6BpkKeyJO zl|!Q&)nE|MeSYX4++W;mWFeC4NPem9aU!Sc?@v<gWJP53Md0v_i_m%a0{JmMM}Ek? zX|dE{`v(av$%H{oUmJ0>;os(CgLlKMonBGFs5;$O_@6rkF0+Mni@ltTVIm5GrXGYt zUYF@}%3{i0q_VvXD$6Mq5NgD&V0TME<wqD>;bqr@guUeyf1dEtyLiEm&vXBQ>-ZLN zcFQ1fHmC>=(?Q#<Ii{-<2TpLigMu(gSpObfF>EtqEVViW58Mc$6Bb+GL!6M4CfB$6 zC5PIeGb~_R#1X$<lk||T=e;Z@PT-Ht7%09F6vm5sG5v69rn;H=Y2KrEHTMwZLFRnN z1G)l^uX}HbI~ZOy*rQ*Rz(&C_9n)X%Nyi-z<oP=edyYe#@8-Vw+IU02x+$N6@d`t| zoBi<j*=M5d`ZuSm-k}7?x3K<Jp`(6Rws#@m{@hFF=p}B^6ayKChp@w*5sLdkot*7F z7^jo{_EKCu2fYWwOxVRa=ca@_P>VODrPCnqqi@|VoG83?j>q#Qo{Q?H-nKW|#KwA0 z5QPx7P}P^dJNA4RC8?EwD1@zVY#tKbGo^hveE7#8O33dnXQbkX3R|-;?-~17<ATQ6 z$2#U3f%(bF(i>a_BM0}*$Gv=+68fIU%ezM<8_>F)pzvGiGcSug(V0=Un}S^N-4pIE zRCZB+n{j?jtcWbhR#X5Yb_L-U=MtUqu*-w21erN-j}s9m-1k07L@LIEM!`{rTQqS* zc7cU8L$oS46Rqcoey{YJi6MR?#iM6jihHpkFo3s|!IOIINKMJW&CgCLMfK1=n~h>P z-i>CxxkNXk!_3Gi*EQL1B~N?%pr(>HAT~Ld{rPLQhh$W&5Ux!U%1G!1|Cg?(>NaFd z_4kW@_3Sb;hwaNd9}&EJS5?9epm3`1dN0z(8B!SR$pN8vGA3~AK3?SxhGXIgcJ5HR zN#m(4eMT(Ldvo2P8tDJrqRU|;d6jz!NWCfn<7M*uM!ENHbWN=vngO@M9UUf$ebECB zE;U97EIjuWJ_AKd5S9qR5i{Lu1Al$WFbfy40i^F-#Zrb|Wvqr@I`mtF?d2k^_;hzA zFQP(o-vv1-?TqQU#!}^@_ag;JPR2Sf*`D~h)X-w_rt(~Yk!N#Zqt(Z=<xhBvG~?|V zf4^7(RNy_t5e^`$yU)k&LjxX4aYe!XSW|EBWLh4Xh&5}2F3sHvc!+)pYB_?+e@JVN z4Jp~2$R;iG0B{NZZsV!em3imQh)}sP4JRRnwr|_C1m^jx-57q)CMwt`h2Y<b&znAP zyJAxV^hzSITR?6M9ohyF<u~fUmV2teUPdCVnSuKB!!Ph+?-z&MiyxH2Uo1ZjzQDt} zKSwqb+t#H6Im_)24Y~z<Mr96uox`^~9vrP`FbL-pn_3I!-CaE+Q$uTpgl_P3(wF6m znBM5%7}ebdXjoRlNOs~j09SCOop~Peou${@8haq7HzTc&PT@HTO!uXMlZucduIq3t z*MCDHkzjGW094qdfe>k!a#;b?^WZC`;qcB+ity7)&p{o*ya=vvA_B&N@O@V`6}J$~ zuIdx9B!3kNn>pUaJ8Osmtfxsm3UW4uFE{Ff{#8BN*Pd>@P2aLYbWaQzI-JO?MfDBL zRL-9|#;+ox%XVNxPr1}GW6xqqmDR>Ee<aG!oHmvt=dbt0a|=c~C&qhSbdTF=q=nkr z7ScLg-0!^W-$xt~8j@zY{tMN<_u@=!bS*;3o8;at7^|eU*uO>pf^^_W)Qf0Uj!R9g zy%Ku-e7Lz5b=@<OMj|OcKs)IqdM$}Q@HLJ~aNzc=)e~VL@RJ>h>b0kjs)>Tx3tfHz z0xPd+H@`D^ST(PG5KUF}?%k983o{7~6QXy6Wozp89fVW>&A1N<==TF?CE%Cs=d<d) zv1J(Po%=J+(dwpl{*SF){O!M7DyqK??uk;x^PvrN5VoA%O!3gdU(NrOsAi#ll#emb zv1N(ym6%Ie!pozl@Ck)p^D|IWmvv!mn7+KI%cv;{5q*Vl9VIGvQg{{2E{}wx>4-Y_ z=oAts%Jpa<c3jm8=vi_&;8SXg;tCq6UF=Fr3wXV<YW?zWia^;566f1-iT~VukqQhD zDLP2s)tSjD`KCw>)DyPfjlja>HTjgz3C+|sr@QlR9<Pm0vid+-$pw=+zs<?h(|59B z43Df0mNQ{NXh0X^%Jh{rS;r7gVs_Dq_c(m5oM}eIiZONqKhSZQKE<B?noWUFU9I^^ z>0BwtI38Q)Z9y^7^u9^+Oyi{0ngE2|2`X4xEXvMqP)<6elt1LRG>@Bo17^C%SI*jK zWc~Vv9P`sRJL6_O#se}DH!1G_u-2u#Zm(nDM$aiG?zSqX5z4d1^pRRGK;U6qUlv7U zJR@!0LPb2J?>ft1_F|AdGSjl61bOR?NY;;c5&A<{k3Rl8`#xD}UTeR4*JIRhla8{u zAWI=?!i*=2KRrXBg}AW&i`gYL>@5SnT3~-$4fG3nj=ZlUhmx>_*nCJF>Pwr$WX4^i zmpkuzcEj?z^82RttSJx2@pea@$BzrwL(N1I^Zg{B$7E=m!-i^^Lr!l-2~2xTPoEWn z3Kr0jwv47&QUW^gfxtX)*uTMWzb%36x<fFVt<bTwR}1dnA+jI1kMPDvQw#8i6Oy=N zE@@%`J`e0&?_Nq(wt6vJb5$_!2yf6^*~jOA9-oR)qbG1b8)foST>(XNG>Ap<oxj7i zw;X#vab}VKvn=wfSv6}^lm{kYSC8w7j4c-MpkY(;co})-&mey!Y14Txp^J5of}ykI z9icvf6M6Xa^$xUhzTu<n*twB*PA%c|n*10zv~=1q&6fSPgR(a0<BD@xr_MNB>hSi2 z-DQre3%<Vxn=IDp8C|<wGjKk&ity?pw&~NtmJtq$+X*|%ul5dq?^dN0%{P##JU3{) zuJdC<0VAvOUATj*Ngyu0m8_XqUIVz)-1S18>uxshe60W(5CiYiX&6gK(<7cY&+8`P zK3zoUxx$ot-=5KgE^>GJz|<3Ye7Yl9$wME=nN*vLgBwTu`P!pS{!Zz(zS^VqXYsg_ zDFP~X#(z(C=M7y~_><U+;4V`vftZa9B5R4ovA+@_os*WUqL#1(u<m10>Tb82UTMVS zHp!<+n~}@)O;_-E84L%Q=LenLNfOPdws}(?d>AL`iisy+L6NBESv!AW6sVXzxU}ty ze?!a-uo~m9Kh&JfA2uY&5H;QVaWaUy*oUdHz-r7Cz%9*$C%q4_%4)KnOTk@ER0x`# zpLX&h<4z037yBs;s%D>u+nN>=UgxLrJ?M>;vEP1FvP?#C2m8*m@jjsFp%&mK&ybTk zOxm&f)~q4zlYR(qih#<e4LGiDc>QDw{>eLnA3d5QkBW*v^r8as6LCa7r6htlC2<_m zV;d!3nUF3Sil&W3t^>M~oe_i@^H~TuM>e)LZtT6u`V#$Qh=c*D0_}ydq{B3Ak|%RA zlRRx;2F4yyxIu7PbH*=1T>k|h3|wtPvP2LWf~DmI1p-@pi7)O9Gz7$*68f)3Aqi+$ zCt(FukO-TOxzmjD#sodOfL;a^z`Mqy`&0qS-!VuyuVV;-N`Mq~3@HGb347RoTMvLu z@us~*7Z`o<vXQdVp_klql9eAn7aH7`8zcF&>1<ut3^a0T8iDM?sOX0stA#n<!Pgw% z@09wS&@QsM2aa)_7<Q!8-+lR}i5F(UX79YB5*u5@7q%UKgL5S&9ux1#<!`nyvf$*P zJ<MZLJki)wchDEmI?7OHLhW8^+g!q5j}}N!9KlI*hZV1UyD1*07&FYlgO?j&h@U8& z-%iPoWE$H}DaBNF-_(xZh&`cGa9>*ue|Gi(n$n5U3HK;nC5~upejV&6ZT-dTYCOVo zfSmcMqIiUkm@NzI{57e3i3&`8TglIv(VMUK_*oxq#|q8KMO2QNl~Wbb1jgV84a^rm zCI4wz)g*nYZ&P0sNcZUVZHocV^mR!#e)pYkN#E`YNgVgIAKEN_xO>=@=kh-Hy)%E~ z-4%)D7E6=A$`&6CHchLpWQOjN#FF3F_d2bhfCdB_kCBnZKBY{yOpi}5Ii1mQw@R^I zCAyc390`6v7zuW<KKz(&Gvx~Jh+J5DttbPgTq}L!8-LT^VQ`=pznOY#uvJEx`H>;( zM^^0uk^Rv0WpoPWoWh2rDG#uJ-vm7q-iK{-NKr@t!dNRpd04q0&Ksk<^q=FbxbhMi zU&a-{M1sK8{~Td)AGVoP0n?CV8lFzV+t9+`Pv2;bZu;WgVOur}U0_;U-X)5Y(SyfN z*4VdK`8oyT=2%X2^~~&a^$*iNK==uyS786n$BY6=RDb-GdC>%XD+B(~K{Q<lr5W!% z-~D{WJ^^Ey5Keczo?QOqr#t_z`SbpH_Uzkkr5gp(D3?HoO}!F@C<Wf>s>->44*0|q zr;gjYr7DEx$^F@CC^%5kQ`6H2*$!Ux3l?aj`kKGn9z0jO>3=Z}@Z`wrFZGrBO+q4b zIC_XlAKjE?j@ed^A58IXCL%Va`$0#^efNu!1P~Ovr0W4n(r>{aQlXtz2|R&<QDCi< zND8cCElqxRQz))910a<)lKyM*#2;xX7+Xd0Ub?+^H<UxK=sQ+?IIVt?T>X|LC7uvb zU5e99mq4%rhw5xy8}?4aE(>1O8^%}a9OhY6xVlDod`D`J7WYG&uHa91XLiJ?#B{2y zJ4%8S*0ZvHcnTE^FfQEhIz38grdxZsK%M-H010^hu^s59FoICfhTaXn|ACOIRXVhQ z@lCGg0uz1nVX}(^?H@zH4<>ku!qRzJ6^yRaLCWKg;yr4be*;onYR|1({krKWK|yqV z9Y7_5p2cs5T4DI(=RFfZ_Zq(s5R$SYoG~ofcF*9V$3^Vny}P>dsDrLbRKJT^V!nzu zQDL;^QP==qq8>4QBYn0XreX~k4IhVOHzl366RR^EzdzYo)M_nq7h?Kq2AELuzSv;M z^2G;v9z|dOgJSqya@1`>XYq2H@XHlN07+aiQv}Q3J>-SWbriA_EMZx?doB@-G~)hi zT;E_DAf1JET{(J->tYHG#_?-31ZFmJYhIfL=I((>veo~3KZX6xge;C1|FyEg+(N}9 z{P>_d^=$9=D~jlJ)UWX9pfB!71!L;J^(OAu8(peSSWzIB;=qdM?E$3)2MbR6IiVb_ zbPRaSVK4JcjClTP`q<F}wx|h#P*pJD=k=kprBY8%L&4iDbE0?|%=FrtIW|u?S$}Ky zJHGR$PbOrJil0;)nVD}speRXhM=K9yw~rt4y83<fMSDptb)!^|6dg*Io!gZ6^G~y0 zvrcEukZ^@u;|amfL)(@b^?pBCQTBJScDNHJR?h2-iqgF9Am}|Za?zope(;Ee@%5de zt5;%YzdM&}_+5FR&Ar6`uf?h4m#E~!%2NGn64#OxDN{1%+-)1;WrY=7$lkOm1dHvq zy~_9)`^Hq)hVPDLg?jdg3dLds@1u=xm^``p!_;Z_-@NOC9_&Q=WPHw7c&=nt-?D4S z%==M+(f8muw?~*@zI-Z3ZNOQmJtYfy{^%rEkNw7GUGB((?B#Djho0mc3yx%%v-um! z?rYNFxF(#mvP`z*D4#6*&ALqJrzKiK2w!!E)x;mbShqmgZjz)D#y>*K^Zfspj#3}k z-#_0yVx2@>is;V(HRyQ*LANsLV~Gd|j3h5j6CeEW<pV{NW<t#C8pvfV3Sxl|8rgna z7sBbO<}9Ls4|wE?_okM=k3<lY@<^~nBgm#*dj|4Kp|6IDWGJGkT-SQv^>{shqMdBB zcr3aQ7DhrD&$(;*#~mM!MfQ-<tQSTLioPUPEuO4Vw`;Dj0l1`A9;%FVVPS9jXtOXo z!(U<XYjl*~&)r!w--o`!nm)EIjAOff&1OcjN1UQ^gJO1(cOMSd{tMeC7Kb5ef*vLw zx7<<Q_SyMTj4K87VSl8vMyuDt2?NP|B?gPFRMnF*9^LQ$*&p#Sxa7lQI2jF8PnjQZ z{sSTh5bG4(tShUt1f?~iE7G7eEg&?uG-qGc#A(01yz5P5dj<ZPVXDG^ZUnhtn5+1B zrV{^X7Haw3rTk>D^lM)M3d{{ibgr*G?be`re>!yvoS!TY<t)T`(v$|R0yV1|CF=Mn zvHVG=76BRLHgKt9KSQF^U11hpU5oF+d3$@oiFcKPkDT^CrIFS#Qm37G75}e<2UNxS z>1gFf>KAcI@!?mSmS2nBt6?rU7};hzYf^r6AmAw{l+ule(gtCRH@jCME%!T4#^+-@ z3+C8U1aU+$ZmJBLKqBTTTt(%-_K4DrUl>^9j|H8OTP3jG4bv5JQZBVHTkd+i=Ta*b z#Vap_RL@xdD#_Bju4b}h)<FaVwD?8MCxf?gFQ=uLuXq_B!n%x2AM&lg68BWgWZdac zpfB^=ozb6qI!izufrj3T0MC7h3<i>6LzBM#3!O4tc=nAT>INHw9Srot8q#+9p^YWu zW#d&hF<W>^aZpA2#NPdAry2JO!)bBP0+cAC?ew?VjnVKb;L~z(o5AO9(sIyoW)JW0 zU!Jxa0)-0bOE6x}x&gX>mr1?7<HUw*8@o_jysV%kXgX}p`SRY(SX-r|H1ozy6TIeS zpG7Hh{65ToId7QfSQE2AH0%Y+-+s#NYE9iwlz(YpfAlN1+F4|si0kWt@;7O6MyVTN zXj}H}YF%9)roPUCopQL{oTIeNmP0lUtkLM5cro4LbB<dzxzk6v*()OKcnf70H90CJ zGjU`Host<5Svr_<43^;GkmuzgstJf<r`wE=s!`rnvyzkMj_N%Thi08n*`*nB73*lU zYZl0_I=>ez^$eD=pib?&nohy^8x&=OBvV&+Tsf%GUJq5S&MK;w3Jx$v=MdFee;S^e zOG>2Ia|R;@GvAVNmi-SaUb}}8J<zodb#4@My3f;wcA_5v!<s8q*drP9j+Z6O^y~r~ zTC4om^^8wq<Zn6MJ-?>Qv|83zmG)6#tKa9OR*N?wnerCb-VgSkchFPa;s6mY)lbo@ z+VB^Ln!<krqElx)o`{F6P2KYAI?y$|ourzC{OAy5GVpI1sFhRdyzcx{d->g`E<MJh zhobV?k~bTbr9b`xFFv1x{i1)S!_^6Jjo&|MG4<<NCr{$W*Dq{<AHy$6mwG6WWk(;J z%M1nHGO(W(Y|@%<;g)SMDDXrA6S$Nt2_($z60i_lZMTV5E-yrEpugY)HX{)}BQs}k zDT$Np-3SzZX#K~X&_4qP5fVW%-wY-=1&a%JmnlkMi9K{z=9~7CSishfzQS@U2aG5G z?gN&QJcx$^8<b^N#}+Tm1M3l|^5vIA(hHN4Wum4e_gg3^7}It6f**%&i#HX|EPnye zj)5<;O9@kSIb%W3CUbs%aVrG#(kjO%Q!>YCrb(ZyG!xmuROV0mh!mUNv}W-9D>E#R zsCQbOxx&aL6YvFhirLzz{N?F_!TiLNH<K0Coz6DnW&oa`mlld)MA=|O6C8{YMbcOr z7Kzls6o}({t5D3wTyAJ<I&=o+*rB3ZO2RsNy*YBFfj*Df@O%h={~16RP19PqC`bpb zjVsfe2j6t-3%<LfsalXUjPIrpZmt$}3ko$vV0@*pPSUEMWqp27E`CE|p*vrSZnld# zNGbX6r_(7qs{s#KpNVbd`Fl`%sK_G?GY3d0&2JzV+e&{IfI1J+Jsq8^9^u=!NW4j| z9M*(Z;{HLsp!A8sjNn{?R5h~$lpY5w#2iO3MGx68%S4bLRF!(R=ZK?aCA779T|l}0 z?3Wu&OQ99^cKXeX6i>++IKQ4ENht9b|Hu}{31u#AStTce3xQ>y8%}3?W5IJ|5-wJ5 zR{`4$I^GnQ$yea*Iyg{A(!6oKu!R5RYoWovbzjZ(SoG$+Umao%vuO&=)9V^#mFsxC zuN<a^?E^AH9X1l@A&VE2zzaf3W}1!cTS(bH?%x^foA7^78z5#GTFOtdQCtn2pOfgI zccJP|mpS=rFnWY9SPB4Qv3D9AM_@h9oT1MEy+oPIOKKIX^#(9)b-KK`%66BlU~L4v z`6$$NdLW(2K#`#A?4o;kKy>BjoxjM<C71a`{hZZCpq<iV9;R>BcQwj2zoZ_&T#C)o zH*2Ny=kib#%MYFJAM-2LVVY{fuSR8@panwyK54>T6^!o&r^CXwEZrixMo!<5AqP1^ zYAx=tCuc}uG5V)jH@#>wX^XLml{3pioN<&fulsO;^pqFdRA%~!Tr(R4G58W;=K>ZE zEs8wT?9eZi{W#r=di|mhJ&dVe@0S)zvlStwL|GSE3>4R-u?=)%UcB1pSyhdY;Dhdw zYwhiii^>ne$=)-6r<Ifz&Fp0F3X6efGpO=vRhdb&#HU!28+j64TM6qpvKf8+QQTnd zz^2`$;+slqCA0N0H$RJ0nG80YQm(wK_{e=aOm-h1<MTA$pCA5MeL$I}OL@{Dca#3c zIlqXqE7+W{3s~LcKC(3z6u$dcOI!06<+rF#>$Kc=x?QUb+x7OiuWcKZ?U6<WHre;| zuUdEO<ZjzR5zcGM{GlB@oRtoo)?y*G+qc*!v0B;t9TTR(xQWk6@=4JnE@prD<K8_u zh1GyT0xF7J!1>`4;nIKe#^j{OfCZ#zyGy_W8fy6NQ$xxDDZmKr#dr+L-&1z+y9JjY z?jE*jciAQD+<a%bC<P3ETgqjqhm)7g6a+MfaW)^<wgiiLsC{{fgZb?g$@ni>y>v~a z=Y77IuxkTv-O5l5tGSYMNMrwF;Oe8Isa;RpXZ-V*Vr3qSYXh4{MUW+-+jS`pv$Wo3 zSp@va6mkHp<7%c1PLfc5chjO^yoTi}M<}|RWUJn(%<0|FAx-jGc<uGJ{b)zD^|1Zf z{Oh9*H+X?-LfQn93n<f%rRR;~;D5C<t&aV0a=Lr|Z?P<^<$Nu6W5E}x&%EpRwqUdS zLx$5=MJ`3&g)lWax4<Vv3Ogij)k_^UgY8O_CRQ+gZZ$Pb%iE5irYdS+p&mIHE7?IQ zx8d`%>+NKrhE{~2W_@O9bs@X;q-hN;e&2oJTq-`ApSQL3^`1xw_Jm4X_8fkkk|#sm z^fEO)?ctPw{<<KvrS}WUG3u3%sSi<i=Th~_O>f2X^lqbwv&r%&6zpM~j54#ZKq6wd z9W)6g6~6olkNQPkb=Foq%ho?dC}<!Uj?9Q#Zp_U0>AL7-$*F$!{;K~MWKIY#=eMQD z=6NNO9%?mbP<O0cR%E#7I`C}ayg-xn_cZ>W+XZ~>XxM9DordbzIc+$7G{>9hZIg5a z2_@@EGZA{Yr1{Hzat3u+n9D?aB<`ROf__U$_vIa60w{-h%|4qTj`+Kn7V3Brdr`2q zk!T`Db)Ob_a80vYW@mZ3f5Wt${S<PINvoGoR`WqI{CQLc`uYeu+~J$?26?7YEg%ZT zpukyE?T+{zBhTrsp#Jp16<zfM6do$xFFV)$xAdhCrigBEBe9YEvJCfJF5yHVp+oM! z4p_D8*SlY`n|}!HV56xiuQOqb+Pf1kF;136{sh;5QcS%ONaz=<LM0&uD}cZ-4R>2p zQNK9rf4*u760OL7`2$4x4l&+Q=xR&i@3X-AHM9bPmHcFCGs?9mhxxYhiRInj!S9iA zt9FWqW_SB6Eut(fdMukaVnb=7pTuM6(nHri-B691l3Ivcjlrke6nTQ&MrV1F+hkrQ z)GX$HWc`&C7kd_(Q7JpFW4pi?ncWkmwwZaiVzRWGy2s`3MkUHmS#a3NdrOaO%T`V} zp=_1i5&C9D3{KPqk(T-FT1+U}-{fxRRQ-PGrbP~i4OuoEy1HiI?KRKC8LY)bx^3Bw z@3QA*{?O4CY`pb$@LP{C2g%6C+*go?OA$)NKd;8$cb%cV%BUT~_vrS)oQVP2uxqsW z|MeynxBHELuW6SwC}8i>CUNOj*~iF^mx;Q~ij=pklufoe=nvLOdPrvn(mp?UYRgO< z>WoNbWf}Z>8<e?)?Ml9xh(<{HvqilxqsG4Z6xO8ilvgvt_FBVd=kGYLL#gtgU*E2$ zz(!1Ro4y`puE&7)GpDGb>4q;>Gz|gVvL?URQ6^+YH>zB>>vtGR2@H+@&;8F++}Vyv zndu&af-5S)NRz1w=ysyOy77PP(p@aYEnBH7m@wq><DK7vSn-y>!4J<u>A^e8%)qr0 zdBo?NJTo>&LCGWq`lM7@?06H|PaKgg<FPPzUwi6dHC!Km`ZP-^nu2jss<k2VwE99| zQBpTuY{n0Y88j@`Nh$S;K2?~69lVWR@A${+61?0QQlh&hu_KS=l>e4N0ePd{=)RaR zx<Mu*_lwa0i&R$8u<p|gsRH78Zd<s{Zf?}s5=mo&a$u{IM(oi!+>IWKU;R?nkG@yK zo{ixqvnc2Pohi6;cs$9BuU<pMaojOt;I*GzZhe&#$E~C}OOYe*DWI^ZNEt1WIsaVV zeW93hkS6v+DuRUE>IS#ctI1bAuXblNb4D(<SKp1CB2TgW!Al}H-Vha9{_|ZC$pFpt zK_rae+gx8P?eXe-f&nIU+s#fmJ1yxOY$Q`!gMdkdJ#+y{*zU3oVQT~+4nEx|h`{2X z4^j-B?N-CpEt)oei<R>V+2N17DIlpJvM!MJ!83&NRwjBBoy=Ay4*e7j?pOxD-VB`% z@0nRyb-;8GNcX~w-d_Otk$#HU@9`i5qtt{^)Ax@cR@t(%%}^bGTOr!M2hUK42n`B& z;GbC;e~&Qq%=ernUN!6kGhd#&%oJB@z*|LslbEcwvFSw=pr;`HqwJn&tZ#G2+rkgV z47>|amyegOTGbEYh$*(LOtFQq8XXUAsI@t$%jf&3BY9Y22x>eXWurAV%b}BCwfmvX z+pDd%2=W_{Cii)X(+NlvZ8tGh15D+I_w4-@;aQwN_&&364EOKxRN}nxZo%8C510EP zKIPc6f?vP@jAO%7^J4aWal9h%eK#6n1EbRqhl74Gt9|%ocl#1*m%9QQ-vF|f@}jRp z3=o)fYBS-j`j2I3N$LkbB&Ed{;X?3Ybvo%kt!C!@KZ(E!c*jK<yMgw;=TsK$fmew< z_mv{7uiJxh3<!*VsGS+fqr7e38k^C`{?lN^maXMp&P93PKv+-<8X2LL)W=lC%-}sf z?tTHMgLoemz8jFLU!C^LI-#5KGS7Erk}rK=6;TAXJc|wIMxv!?WjPIQM<I`f)q2K} zN78hQp!EfACXGgeA42B1shV5Eh$Ast-jOjgG^$^(c)n*;UUSM&V}5PKlQzy)ETM5C z20b-O-Sk1ay+LQnd0an}t*Lin%#TlqOqWAWGdgq)42VZ3F*=^Jc?MU|_y@JypIhn( zW3Ndu4#;HPEK9l4$4k$oldrDLP9&;)#g{<Hmct`bjK<d~<qnGz(O;X@nPlXz-qiSz z!}dD3{jq#-2|RV>L2PzNF*4WLIyFv$>ej|vEVa=cPV1yn2=vxz&RTlZ%Q~K@n)Lp! zb^SlmjoTUL8*M9IIv>G}CQp?0tL1J3Kc^VhyPzQxEIyp$QSF4lDVn1SL!LBpeU9*u zW_7anuh#OjByWD8tIt@kC8f}53~kq`s#JRPM*eQoJxo@_9k7p!mWEpJ^cFB<84s61 zll9U>^TlYq%^P@ke{5%9_2@srN>B>oq|62-XLaS$+mkz+5cSXR{7ES&jAz4W_&i+4 z)-FS~m!Mdk*zKs>o{WO$;X*?Ls9NiAkh-o!4%-YMi_L{R$ITi#xZa&YJYj`EJQxAs z1~pH~>Rmd@LF^RsLRi=6uiI{#ptN!T1N$s8l6S(SSfZKl!RS$-EDDtXo7$ySu<ssI z7M*^Z8S4Wq;x&&u=*(;+c4sRyV$OYn*k=_Vw>Z6+x+pKpr-qe((^vq%>ItJW^9=-~ z%0H{sO5$&_Gk`1-?6_u0Rs`vRC}e$@unmE|`FkgDwU;$bwIw<H)pT-^=BE*y39Ykn zJz*%<+42Y2tQrAFZMxl$fyYLVx=NOaY{9MuQS;u6r2|c8D>8L&{(FC6?AXWX>U)*= z1C7AL-i!lrw)Pb8c6p;`+;{!PkE#)Ll-RVO@tvP-O@8}JD&6^E;dP-@upZLqV?FMq zjad-YZ!iK@0iN!^1n#h${iLpe_Eu+D&>VjXPDi2G8g$55+x``s^d);~zqzD!HLaf; zTW`~9?fRV;Z@UCXEWER%{)z(rG&v31P4PUzI<0EH4aHw1-*G0{wZHP42s6{>4_Wv# zE^Zu3Dhx!gI1(*o7E&-)adp|R=s3IhL6f-Dgt|&`R~5sapH}a&QZU8=f#-~4n5{fP z{T%s}#h}-_Z)4L$O@vfKvtl{1fxcuIn=cfMQ6hMWXGt~-VV}rJ%k;NwnLs%&)&Jdc zEuqc+@P$eM;?FaXwEA$+^Rk5;^?Rs&%4vd}w69z#K~8?N0g`9D1CLr)Mr4uTzKJ_z zfkGNEvogG`5<R45WUG*i)h0N(b@rHric5`mOx2n5S=%eaLA}Zpkr{ZFqL=jC87K9R z%r004eCWdgNq#cmeG$70Jph-T%{aE>$uPqSrS0P;%$q}(q2Xqn{<_Pg<hzn<CV3ZM zVYU3`K;2;h<>eDGr`4Z+Hsc)N2mcEX>m)X+-^Jo2N5KUZpP;u!ZwlG#z$VnVABcQ| zkp`|E+n};8IYBFdsyqyK7RmL8M0GWS2^lSB{sBC41HN>{ff_bZf<B|DEpU6WaVuNu zgeiItFre8#>2&)$@2EKCz)_^54DN-QKYN)|fMz%33TE?cVDmUxeaeKAn$yFQBS>p= z0$kWM?HV@*x545&J4>0}oUL?v7UG@qJ=c-Cd$L2+=H{z1#||}mPTnSOPg2Z(q?mhC z8X>&072{Xsuu&P!Y#C^$HylyN(pFK?p?{QTgS);asjA-A2;dlYvznkSTRzggyQ!c! z%vmks40oRR%z9o@P90S-7x1{tz=GtLwycV|nJrh1z4vkGmEn^>Sg1jE`^h_IxgP?6 z#i}mh!>l~Ul=n(veB8*!UzIu%NrbBEma=f`_GgmM$d5;OO(}CDl0eaVBR(n5(ftzi znP7=^(UrlkS*(g0E0hAo`k{2Je~wfh)P)?=|9VsnXNH`DB~oB%JLM4_?s4*T@D9xb zzIPcq5UB9fYvd!s1}9)vDst{b!7yh;%|v)+Qjr*3qyuAKnc7(9#6SJTQ1f4a_4}Fg zz{NZOa=g{@zw3L@Cxk$t+M3V`a=jw1gF{2I@<ixG8E_dd1HFIw53L}9H|@nVU4En{ zO$6JIh?!I?;2ejBydmjHaBn6qj9if0E}h1rF5@!_o~rT#TZ8Ad=dMBgyNOTA^wRFk zt>-1uEr5O9>Ka0m*Xq42WlSOUt|u8-sslCVC!>GCRV!&_1)&xU++f1+7a{ZP2)>N7 z8LUVvumFPJfJ<UViUU#}+Xax^b6;5i4ijzC;HU&8Be$=42D`UN4mPkM&tSLlzF<~z zE|t)j4m*FJY{a@jTlyInxV6``QQOa>n+Dy`-h>uILD43SpvI-PJy*-5y;9Tn`&4Gt z<K=XJtNp%eN3rGX-ze4ZgdVy-O#7`*W^ID(_*y+SwJgqHOGgL1JMSpCdp6O`8!JTk zKOA>_Ho`<p5W<S2@5XDsJ;7j)L4#Wise1A42ngnK-2PQxR{F&ix6%D!l}}5XivC(n zm1Z1UVYG@7g{T_bzgl%pdHMEFLLA{TgZ=UIHMEz77JI-(T6ybaToFM~rHhkM6%13K zI;_7hD4i(?BzmjByY9F(1pYUoG|LEgPWD~+kL37_7a5_bT_3EA%_D1He2707PMYFW zs9XOw=A;93;-Bonu&62f8B66bUYS(`uJiXZ@bop!_d)wP#oo$c;ETM#v;{JGsCC_7 z&ZhA?4@=B0CfEd?UJpD&I~5my`}U9k@qHPDVZoAIaLI_dc^^me7^r`!{^Xt;pTjj- z`r@ME8%{bT11NxE_D>n;Z{d;i@FoB}CLdxrhk>ts@UKhI()ETWs6+8T=sws`I12%y z|67Zi6KVyHVY+Cn%_I9@Fpcz|nBBidLPqw<IZm*bx+)WktH%CI1WD#vOgRaqk`%$m zQ!Xcmy+O$JJI9z5j|49*ov8)8Q%)I}&33P-@jH$=v}pCKH$bg+x)(uE^&Lx%PF&B0 zvE;~_Owd=46AVE(1@cL>Vi^05T)Zfa>{d@0$0j+)GCKv{Ki_UTN$Y0E5znV*k!U{B zzc+s$dF6**-9s5o=>(68Tj6EyQZvp2q#m11ABqd4Xp3?bzrD!p^KzPW;;{R&+K7|M zJ&;SMh~@K8vS&2?G||*9-BEIbr^ryrpkJ}aoZWfq>4SnmzL1{7%BMNK5V25i!>jZF zZ^RbykUM$z1EJd-l&l8VTxISSa&TDP|A6+j4$?mY&Qlw{Jkj;pnbq(}ex`Aqu@si2 z+rA*wosl}Tw;=wYd8cLjTfGL3cyh}+L{#gjRb)M>muPc=4wlkxoH&>q@6B7N+9_qs z7o)u;vNwrK)17F{t9zZI?Y#@K`oX}T;L6<-%w%NLms5&hu~{;B(*Bk_TqtE0&@9%; zXAXmzO9OF<*^0%I6u|2+*pYX#)#92@OHKEG|MJP{o6Ph5lZtBC7HqP)1OND5R~SS@ z_Dr9^^9^@+wzVfI*XCSvcvgn@vN?h5gBZP#t6UE_I$Z7t?4MRV1uk2XpqHk&aDHB~ z*L7+$3p@jg)gFZm+1t71+5?Z6I_b~Axs$-@U-5FO-Q1$dg@4utrt**lTw_%R1@+>N z63#xYM0T><lSA&W@5oO9noFS<+`)G`8^J{cni#SwQhMS)qfJX6XKPhk97j3CE*x~8 zEznB6I3EB<&~Qd|DwJ@TSoeA{`kLy<we8vJWwqA)#Rsi^=$m(1eqG;&0=VNN+%c@% z$SFOJM@7?h6?KE+D?s?;1Wy8KmQMU1v6jtjxAkUJ!ty@h(#1{#D<U*D0bg%`5_L4i zO*7g?raj%Ap9OdJ$I{AbtlR7^5~f>iQ$WRs#woW-L2V&Me@{>Ld6yb`x;DJAK|e>~ z1q!=IDbYWBexd8MkgN8`cJaEix*H-2tgP-eNk7G+V)1#08-&bIVUM<uzlO*`B~Q5M zJhU6je=|!Ulq2MSy8se~=W&ySz^wvNam&UC=t042<Kya}{SMP~iD#eDo}HNf$#3RU z9Y-(@dh2%l*!-s){^ho_pvfwCr3NLB0mGr6a8IME4=2%doB~1A{&uneyU#C&j7XgH zybcEP#<@<+qTvyToO6T*iADoXY$mn5x!Z0@c@R0QG0(*>JKo1~#be%N;bvHEr=|(r zot-ay-N@=SlY|)|k2g3;36YNl1i$9gwJ1xT^_4;fH^5Nkl%gY^m-AIfKlez`3Lna} z+Cmt5fsq_gXP07BF!THK{v~-k?R+PRf>s>6U`g`^YAsfxPoI3N^ne3@U345mIG`|( z&7m6#cp^i0WKwNSa_8bt{RCue2El1Ui04!o-237$rdzahvDS5;wFK;~b4|=ruFF~j zjXvxlGeHBsKTjbt#<h5EXTTTxl3nWYg)gCg<IP3ILxO9N&bo~lj1rOvvcGQO4A^h0 zr$Yz*8}LLJm)im4L<<7DNAcK&O7Of;=0E=MNBOsekCRV~V;p0>@e27M9D=Mz?%J$t z+|>M@6QOEvTLnAE&Cf!{1rPSItj6NAP+<Wm!!Gnr%bj-OLZydo97sX2+dO|KN^3)A zxTM5#J)(Re-@By~RvQ^|yya+78t~OR{POFhw}*b<nv|ZaQHtVpwsESt!q^|fis7+n z%X~IZ^y<@v1wfxeGxktVH@LwLd*G^g$gUFZaF?UV;Uu1CPmfLCO9-Zo^I}KjnN!+b zV|R|LRn9E%meX^il@0C-?qj#g9ov@fh@9F)G@Sc|?qtU+@^lLaOcqOXG*Ia>DQH*7 z^%;|MqMWR=(&^sEr@M%cc;zf_liVV+bNC+B7u1nx-rzN1qkH~>IA!7Jez<Acs1NBp z%k`Kz-4Aa>uC|O$KG;#S$lwreziMK)XE6vI7u*UOYxB9U&fT7bpsBI4=M+qsKIkJ0 z4sreW_gS5HzkzUX#`h0ztcCcszCV3Ip$ipSv==<)WcC)xwjiM#TdKG4fd(7-G`0)J zbFQzDad$3}+NMTkC}x*3i-|}i=e1EgOwC*qb~)!?cr$ME(Cz#0vZFF*6ZK__d)ZE; zddDz_RgSFAL!H2o`J9haU(%<4(A=li4dsrFlGM~qf~&N>)*0MfoNOUvtWOHyi`}i= zHh}I)=mKup5|bC&TKUlwgjel^6jh`L8Tn3+@ifR9%h?{AJDU3R9`#><i&pmdxb8gz zp|$ZdNpab;QlP}XY8XtI^Qr~o9#Ht;`ECP~wGSLfZaw%QiN+*eQb%V_@BcOSlz(8i z@_STPggfgBQp5xAn2kN)9L@#6V$D!rqQV-@nS<i^BUa8Tny18@*^96uLR-kZJce{P z=9HScSYqhHd}x`w;7=Fv`@N6hqZm3)xh^BInGfF$x{iR41n5R`xs0bO1MkY~ghP~( zyUTE?xS6X&x+Wc`E9MtHz<pXEa~2)X8HxXFy?CWOyzJ{KtN`Hm<@s>EQhyc*A&{uE z49Zc5eO&_A1DwG+IU1A!g#=g@3T9<WAdu<L?k>+m6%Urb0&jqSr%f8)0sfL>7nqJ; z_w-%CD}3fVy9Lk5F>lppFbtZwoG~C6r^V?Y+gq>;KNo>l4f4~RP}#f_<BJX^xJ7Rm zwR>Uqk8QZO#?74(&W1YQX&`{=?qR`&i{V{#@$uv9!-sRkq<<4j3%!b@p>FXP@IbRq zY>9idj_utXdhN5>9;Nla%W`b>z^rig^7f5~sBI?;)rEiD`#_XJ8njgw&E&6FAf>sy zMhl;4!ZD`z9ob==TIeVcV)-?jg8JE+ngUBi-bwIV0g7~ooOGgG?koZlT*uE>8|=(l zU7S<AU#fv$qv$94xlzP%g7v5qFoi6;B+@04eV)}vPi0@KfCW3_a(bTU;vK7>3le)} z=^&GdQ<j*u6QYTR^d+yE`vE~#`h?kQ?L<_u`J}{m35dZAKiaM57UXnKk(^yx{N|qY zypGN{&2RH62MXS068R7&$Z5kdoCP)YNf%GyfOsYy8LCb=FHlK1=x0CFX?tz-PP9?? zu%rT^4jrWRrD8f_4h@F}&B_ceVH4K>1{fA^^OZjyu{3)$W3{l5G;8&NCLv>zyiC`8 zPoCmwXpxTVW&%2Try;o8L>xK_@V8|QTPiIjN471eFwj6hy7QkKu?;<jmZ>ESc}fWW zR8{YMx+Qmq98(boXg(P<H6nCOK<BXjSoCjs>tc=V7yk4&fDdQ;Cwai7;p9EyiwS?7 zBn`^F{$ALEL6%wQ0C9@!SAM}z2y8O=5Zt3DcyiT%kD(Vg^*jAif16?X$g+84+Rq0* zzt{8Ma_i&0>HcMnDwtl@I}*y{&4;77V0I-i5;r$v1=1Wknf_Uu|AU)T`_K^l&sm#0 z5<J@kk}2_KtnJ_XJ-0$<;o!^t7m<csLepjF`2{Nsh>-V6x`668Jv!B$ZTo`!8u1FR zduJ6}_B|Qai#0VcpyN_g#01OrZ3MhVt>(MCeLfTjqWw@#9iGA$@t418^qjURW{T0Y z{c1q~yJt`%U3&9~S@@^rvqVd-DcSrem+eLs)X9{)B2`Wnk2;6v1rl`<CyQ%v5mP-E z=}XC<Xi%2sMmRgI-An45P%ZA03DQm$7#I+8V>IE_<X2i``tsad8MW>BVBFE6pN@Db z^#+Q~Gfp5lS3V^)E+tN0BOAoPs#x*m6U(BoCx=s|H|S%_+)uI~tvbv9A8T(N7G=A( zk4gwAE#0L8(%lTwN|zuhp>&4`0|V0C(hLaFFm#u6N~a**AVY`4upi!ct?&1J`}ghR zSZf{oAC7TQ2Jh#->b$P&Jgs`K8A~aGC&%he$bA-qp})z$IM7N7dyId*%;I{%i8H<c zh6miy6U3ADI0=L?%@>lDi!doarhgssJ@|WIk5s-A>lZZipDX#SXz$X<Q8Oh|<YwZ6 z2A{r>T603Oakbo9bG<B46o@Tc_PmGCR{sk->(B$(rIJ_#${{u}SZM+K%T`2jRk-eh z+jJ`m-SK&|=tICOv|jB}O|87YCRfII%o<luxuB37oht-3>clp%XLSW01<`&-3A}DW zLBS;G1-KLL3Hx3iY6vhxA<o%2Frj{ID6m>4c^958I|fVm6g&$0jt7O@+=pO5i1yh_ zf*8^8g@)CA{5E6<#>>{h?PbY3BzUyF6`;s<Ux<xNY(uW?b4_LW+y;rFHcCk_ICssY z$`KPcMY*u;5Z^rn2n%YwCkB`^L#oO;y3nxr>puRx(BQ+#7;|c(P?di={4SRAXT6Hv zuUM({Kd{|8ey9A2`L@&H+tstlxnK4Z44l|8&V)a3)>EG+v>ifV?CpW|p80&DH5{CH z3Qj>)V`?(wY%#0v8j}1?Q_m<MW5J>L$zgmd_17cMjY_CXh;7j$tGPQ3o~8eMF__Zn zRDz{sTTydpO1<<Y+Vhioht=C>^opy)(NrNoRWii2ls5_<PodfVX_cZPycOWvIXTjI z@;beDhaei?`Ghh?)N=uj5x8b{Mkw`uUiKlOzEr-fo>UxtNIf-b1nLVW%69}ie)wjY z?S3fiWZ`<+#zsA!K}-^X7}EZMlWNbyd%xgd*s2Ksg_!1AXj~J9G5?L0A0Lysyi|BS z3u0lqpU<5<ceI+i-;+xo1^FNk?~fl<WMyAX6rf-fD#YNo!%q<lN*b|vJ2AW55z3v+ z7%>$@XL7f6cYegGMf>I9>6VhQaaJT1=-2&5aB}-|ZL8*gZnn^4X&=6}_<SEgcUSx_ zR&JQLS;`@Q5axH=bZx+A-L)Z)?!UyKB>u4g-+rH^6Yk5_e6_xh4{bgV5eIJnZXRvn zEs1B{I!_lX3+|;wdV1aAY`zN7(dY-IDyOLKm|D&N^M*!TI@6tK>v>v7U{?hfIv+f= z!T|}MwCj>F1X8n0;dYDwt0iXDpPlUZ!J|9rpajWD-l(2FH}a4Dk?#*;86pYZ<|qa{ z<c6TfyHLtt$$0WcJMi`51Xq5w#`$86I|E3FD4CzxCxF(6xubh`40_(kL!IQIyS%%7 zXIQok92xM`Yd&FYW*lgW<RlemL~c80Rvk7O`<1Q6BfZY32(0NYRM8<hcI6uCM4Scf zHS##(w;WFcK{Vak7rcN5jGr8)FDc61+orc)u29IZ#C!k-MbLDl4BatO;aW=Ln{@9c zeh>Sz=ksx-b!UYjnvK6<?|@(T>=7pA5Eo+iTd~N;l6UX4u)G3Yy6?H5&#&8Ipm(wG zb0~N6>--GS<&*1z(e@(ApyV&60H5YZE213e)lJv0nfB!@2?Jo0g6Ue|bh9&y>>h6_ zC|_?x9s<%wx5+QE{+cd0#fRJ#994mlJrtOF-#>ak;sYZIuU3yh^W4CD05hi=@AvIx zpyQ?$uK9h#z!~}HPfSJh=Be7fiEA+%OWtV<239_eETMkOA`(!3yqpi&T6xepzzlVh zeBAJ4lvBJ;LsFwW61yk>6K51Kq=iKj6?3Xf+%KkX38{5=84i@#1?gv#IBI=5q^h2L zUmPbay(VI!R`cx7IAA<Ju9gd_XXcA;L|M=C)$~8?)QRiQF;to}hM=1Ub_*g5dUu6- z<2kX1KL0d7{y-Ig5?>6=wKxv*n{!W+<NmUfBJVvO=rVVfr+Z1VQ|<Dp`N3)=UdChd z7T%WBvsXV)eh7Dt#|qwdD+%G6mVtvqtfM4X6-TX}^dbUtn@O{Bw@1?NW+x`bo|E*` z6H>U)pt?<jJkVK;7yjTU&HDZUWgxMP9h$|9H(iM}ok8}_-9xur{I6d@K7;U_Zv16_ zK#GTRDn0+=sb!8!dIfd5ros@qU$IuPZ&7oPlWp{SZ!-Rm3{(bl{8yYCA#NC|;T;}Y z>HTO=wSm)<wR>*VD};<fI6Oe|FQU}IO+c*t3c)0DmHvdVSbcA9_ms=z?!!L(x_%TO zyvfvrcD6}-7v!(;_A5gn2@0{PO<~HJl6Q<$rDf<B4M<$y1|$V#z&-BRyY`aA@d7Wi zp!t3mZ6EN=f9=&4ay`wJsgg~g00cTZ7=RD^1M(n*++9NNkbGQ1_?QH$zrz*`!!3nM zNP@lV8zE_bVAiLm<d-Htw|s=%ul=3v@M;=iO;|DCkI%WgtW$nzJNww<w14}yytexs zcP(<4=!<V>DvvnNt(ois(lsD=<Sb83Z!4ir0(d9^&Up$yPX^rNp$+%MOP<wbEuos? zHTaETVbm@gQi=%qfXE8z1fcQX&;Z9_R>ra2U9U+cF;jjXx%!l|=`hTh7udlaaO*N9 zk@|U}D7+?UzN&2QgcGq#Wu#<z%!3Cool}-H&a1O$uJVYUO-}Vren28VLD)F)?4t<> zYWUghcK1ltZDd2=OTVyt$xz9?5ZMtBN{|+aV%{<El~I|gtJANy17@<M#R3d-&Avx* zguDWo##Bh=I$SUw@;N<~;F#MwM;4T7{fbq%XY|y}zq-nGVT@zTiOGIn$o}e*{Qe58 zK9Nzsy<c|?=~C>(#;abi6t2@Fw?DnPqH2hTclVh%b^JXJ4a^quY6LNDzU1Ze@0tan z3LX5lAZvJ+=Z7WHX@T(!0~i%bOdWiL7<(!C><bLUY_8NvbWidpAK~;j%^w4iyQ2H8 z!MxM}7O*yb{}b+GJNz2+%o+-beN@E5G%T>9lbV|5^pq&3`{aJNx@OvmKj-)s6N&7) zcROc*mjUrS-+9`#4IK=I93%LIVua}P@aPY^-_cZ&5Vuy$W#O4)Ze`gl@P8lzYH8=? z#o&kv{w?MffV1ZJ&~wf%VDLg{Nm;?%yNQEi6_?q0?)$?g+?jU-d7t<fNL7EXP*{5R za%5eVd{w(jk+hy5k755YVbF#)#c(6A5rVZ;Fs8>)s$Nq@-}@jS>{iyI0*6^<w}2<V zZ<pMG<fX8rMd5euA5P@A<oI6&Oafz|<X?m-EIoJXJ%cAlg`3t}2zuXH13HJKeNJ66 z_k(YdlKAXX-(Al>Kg33AYIg^SX(#$WNKm~MC1HkM&2smCcO>Fs)bPZhkGAeCFxbJZ z+*5N3td|QM*RH@a4;RU>$@njNPfm!v@+!-B(|^pb1LIsL4^SDbQeq#KL!?F1O7rsa zgq-@$9pPQubUD>K4iYukhyqI^YuyQ_PCe|bMx?1vIKt(hh3H>Qi;<Z3jh?c{08cL9 zha11_hD+W(Ug`u6KZO0>^@<HQ-ricK$o;tqfVJo8W=?P>B{%T~)smV(PR@lQGfmaP zVC@eFcK6lVkQ@K?h17Vr==ttZyAMF-41Hqcd^fx7;)K>&RFL6<LOJdt9^~m6@PMqM z;p2jXSjFwaalWstt@x$&WNgFX(v06m$SRoK9*2w+e{y%HUSeAwYAU}BC&G+cEyclK z=O`P0s+u<J2CyQUrlv+$d?D*iht_?cd|o;pbBk3@;9yPetB4y$r%JS5j~Z`m2yi&| zCcNBYMr$0;Qmzd)8y5Ot;Az;{J>pdIKsYH2U@vmRQb?2U+cA*j$na1Ou{OWyHU~OY zU0^;MQ)`@FIJr+R1<l0!md%7!4;rlFaqeht@Clrn@8j=9P;w#xaf0M+kD7(2UN(;N z)51_5k*9g8ST$D|c0KvfbiF}(a_JXsg=3GNtuisz$=mvCBr-f~0BBJDW)<(-<ie1> zx6*IE{$wPJ<f($?5Oj%fYG+^%LG7Ma49JshqVCP29tL_^!Zywr0c(FZ9f9y`+t@d0 zLz21U3O*KSL+<Ru+K_wy^UJ{z<o326*8b-YCgg7I2#UB(FCz*pd)Jf_NDsN&I$8$a zXos9$IwFxH%OGTP8)RhUN1T?JM*{)cg{FA(u~S&cYg{o-A-Qx@@^w2uOW`FPChApt zv?pCw<Uf3779l@8DP8%>4wYh@f#FLv;oeDZ&U~Ut=FAkyb+a3Q*NJ>Rv~Q;?^+ozP zbIW($tYBwlC7JY?&7~8$pDR{WwAcz`IRamDWFiFK4Y3nrQ;~IBO-5r6O_3_puU2xG z6q3_X$Wd2Tx{+G)<3u0x%P-@JjXBl;|1cnCm&#!QCnoAU70x>Dj}wQhdA)-Q|M7Zp zJ<2unly7B^E_r|z&Ocf_4pLa%B1PyAe1#j$^sX3D&<-CyV<HTI1Z@S6#nSsfI$q6V zBysNfdKIeoGS$$UJ8bn~lpjx+>&;+epydyUEkMlGa;M?f05sQZ%~fo;!+P_^B!RI@ z4Zv?c#<}MN<UMD2#;Xi-x=)0mci9G42&MM{qaYnu_;tYrCKU2h*cz>Hv>l8jS@;aQ z+x7e20|d*@Xok>}a}yItHu&tE%mnhv>octV>LvjOO1;U@q)>)koEKQg1GUV8;9qHN z;p-3yqBi6^mkD$$Mh@`ZqcnLN?&Et`$;uB#MtujIrR3ekIi?9j@u@!ybaf*WbRM#p zLA^VcBcnFlqPsR97UJDJZz^5z>L*S;?rjYRt*XG{u;ZV03Nk7d%OaI)oci1Knnq@^ zx+uZblxW}1*ypPa$v=1a7Eiu&Pi*7j0eE6B9N0w?S`1G1P+o=`(DJR~(Ah_rOY%mo zGW?ctU?&QpcK$r}SWOfhY0b{EZWU==H{Ql8Y|d#qOg?$=6zjHB);w|iE6pS`o)Vg6 zxa8!M5T3;o2SHO{bT_xQ##ww7muxp3_{b=ViOqY;TBlswT|K;f22M(V9^w*$Tvzk< zScj`=+7z-&JrP{9N^v2I^IF2!EJ}!AqRa`6C&~3g`+h@Np26I1^Weo>MGdj<whk+6 z&mN^Q6u?^C{$X*<&xmw}n}7;K!65K{cs`r$uL);7oN`D4S`ityQviqLogZ@JzCQg& zaruyXrGmgMKU<F3LH7P3wOgmZV|uj!IKHbJrDBz_oC4O*8`;3~_^SjeqLF!@Kib}b zZH{So|05>1myyWXWyqgDkmWlmqw(!!VA*w_tC*~~_h4V`r2<eUnLy6Y6;x^5W0iYf z-M{YBP9JlBXyi5(2k=eeFWuMz%*$>f%}V&(9wb?6@VPAO;?kG)xZcI9(<HRNVIQKL z?u3AC*WQpnRo0Vw`oFc9!8qm(6!O%;Lx{)%9*{ky{i87ZKcnV`bs-r*Jo}v@*<}Y2 zaXzVR-ME9c3ZYb27f;-N+!A4s>d(-YS42fuB!BWGSc>31!B5gwU5%fFC_(a6as~$D z4)*7;Iu?$v#&KJMpC9i{%Lm8C#s)G-k;hB*ixW!si)+7lba(rw_*a4vbHNLN3`)&U zv!~$NS>yFzM<0v#GKy>4%4*kh5#jzcjY%LQS7OVHa1Mj(VpY0N0R#~?EEB<#Bev!X zv33t)N2K9%FXvEF4*1njblJfTVcl`Y*P3@{@=DQ>WDn7~KuZsn^jruHT;(mg{l`{w zsl%DPx8}H|Pt?>v>b_@Hy5P;ee3_PD33vzHU6bwXkJ7e;yXuWMPg37##L_^YbXi0U z15_9;ESBrDdWfzNHmsk91-^3fqE~DS&O_$!Uk%z<<G<g@g#?wH0vkgFy~{8V<SywB zd^`%hBKi)3tRFqTL$cmQJt9Wl?qAaR-fdn&eeY->lsBg#Ajo^DK=pDA2{adR&4(IC zqW%Q}fv0LNvmp^QAd{OTe8k4tvdN1!m9@Tz$0y4sh)d?X+W`pVWEtuSU1@K>K5|6< zVRFPpTq^uxOuA!TfI!Zc>25C-?rx7emWdH}kk_`?2H5Rvo}&a5ceg<%>GR8$x0eNI zz$g4kze8@dgFb*bZZG@7O^A?x%&(6|4qV?LT6f!lHm@4;Pr@B?h5!ONn9K3;9Q8*2 zUb`Z)eA}|7HOHsv404})yYN`VaWO^9HA*!wGR+QA;je&EgruU)+(Jxf+0ExW6EiK- zQcZ&u1pnCk<DM@TgLKP;z2>_L_H~i`q+W+A*PA9tr6zG&Q5Wg>f+~IxPo;(=IQ%ub z1It8bt*2ma)a!!9g~F}Ks_otf;eLdLl$9j#s_(jzgE108NI&RS2v;H~+?7jtMnzna z>&0dV2n6!5_O+Wt?9^avDtu|jYvrCqbesNogw;ix%Cil5t#m0nV}Ty&N63vTpS{Tl zFE84zSseLfDc^xbj>7crAK&@c|KQJr<qt^0wDLK8lxwNeu}i<P;@m4@*efZT-_n#2 z;El7Xj$6fKSZBoWB@p-8s?r$|WOCo@C&8z9YOtv*z7gv(Ae5xBUDhy|1f}zKD>AfY z&OfR4xPU@I;Z*{8*Uy;R*Pc}G$W8<^N|{a$GSJT@I%xVjP@)g61;G&Leh3soGfwVQ zY<79K!I$icRR~19xq{thGW3F8tjAK-_n`k9qFV|xM*+{YfDGlLX=AkTmTWNYrt4$$ zY_@{su#eM6YikRYfByINIRU0ntH#S2F+S9PzW4WG{fkGk(l1RfNWX)Q9-gh!ta2+* zJLBakQ9DySn_ovsQ#;?!5H;m+%Kve%M9${HyJ(YQty>Xff2B^V5bs&>!x+1*7-LcS zvLuc3ZTN{6-aM->|G*lb^hVzoLW9jQFD=N$_awEAS>L4gSfe(R%<b2j+YhFNpBSWn zP)3=^M}K}gl~qyIC+}Q=_Ei4C%t)l2{O}~1KVkwgw-fY|J=C*FLqFogJOFe(#>(vK z7HK%gBFOX<w5yjs6Qg{+$>j|u!KRw|jC-9_t+f%-M?`>JBO+jY^8D|6VKt5g48h1P z8$15^Pwxu4fBmwrSdGKdjgfP+(t0hQ@zkr5NB&;cinYI{-e^IhqQVbW8Rl2e@J;b! zaK&q9)4E)XNU3Qx?c}H3*aUfJ@|%A5e-O{LTL}x|y6CT*)lcNB{r&~J^NmO%odKe@ zPWt*i(MS~{a*oMT8`)2qjJ2pPYll*V%ZvG7ixH*A(CeBvgny0Adnsd>-gn$Mv`iR2 z$SgI9@c>*ScsysWgtIx3(#zORiN%<{sf)7}9#@_!Y(uYT4^QCox;A5yhUrBft_vXI zcB}6+n?hzY2L5ppQbTgU3=7BQFR%a9lBh+nwE5``pL}fLH*Q{+;}CM6FP?o9CCqd_ znP#56&}}V0!S^zTCQn0Pqrc)kUJi2`n3$>&oM>{sU8J(7WH00juJk8w9Ani@GpYP4 zS`XP&@qs@BwSAo;qXm_Ph~!m*-*m&C+OROzt=T4^;)}FMnc?9-qTV{0OrhxJ3Xd`r zmG>{vv-Y)UvhJ@`$aiO<b7hHQ`01kZ$#-5USf$xBE+Cx~%Af33gd?_fB{j#b>$_>1 zNLOdHCU7-Q;d<B9oH(hV{7<9#|HF{7fx&~LNHJqt7|roldHwUrVu6A-{T5ZJ(65FZ z4F@^~QMh>`Er_t5hp%8>&hmSsNivdi;cBk0@->bt{P}0~I3?7NqNz>FLU=|-si_pj zD|K|Exmr%T%=@S{jiWXv7$MWB5!8a%$qvN+TMMy*FKApzelrC;?ZTw>vp~aV<#auM zFf!ujwivu+?RyAKx#G^x19y*%a)|*4>d~!y+Qp=Wbc<RG%W0JtWGW*vN;7d5mAj7h zMC~;3L6sJHhqU?Ip>mL+2+`Lpdhcga{3lKpg~`c+fq;sDGfK>ul8cf+n@?q=ey>XB zE=pC_NXUgybgxFoGK!kYrYi0gtkF#)X^52u@Pz$(F<6k3u>QCkdR;ug2`rF#ae}oZ zRb4Ark`%7Pdh{D*7wXMkm0z8h8f!B;@r0?^nCtVWe<mZ?F#quZz5GEOi0NW(;0xjF zZB*HdlVm#QfzfY>e(i2p?YHY%PK$7&`AGggjAee%#YVESmpmt+`&VgBGr^M#ayi(H zP;C_0Ll11fLJtg${)e6D^WVGI@%q{H|J1!=-MiNoHiwToEp<H+3s!q2Iss*rzgY(N zisH0%ReS_Q_evPT?*wKGy^awnb8M309#i%u{tqD2wk5&o<U0(T$+)5xgF}kq76e|K z32LJG7gs!FtobhVeaSwyiK?gkv`zewj4ke9m=IwLd1AYwnawdO!${W$xrK%fB0tne zViq=(9me#m(I<SfS@4iq+!(u;n(QZRg28D8JQLzOIsD8m##51o*1iam0K(1?y}>@} z32L!J(D^RuW&m9#&nzxh_IuvH!izs?6tM23e|C7j^>0O){}YUaKNA#MN$C;R4?n`1 zdL<KC-1WxXZ?Bl*J*JvZolR{VpF*^<M|U>Tuq}Kv13O;zeBr8Vd%N$A^JW0Y`LB&H zoFgzwm(4Eu^HumpoT@kzS=(HGAV=cOJDE~`h)tgt{dL|x+w9aT8#X&eB{>IamI^i& zhqmixLd;C;=WtwCJ59zAKj~;#IX|dvFnQ~h`Rj7ROk<0<k&6J;{RCy91n>?+PY0>- z^|*Cw{E&h(v59vV=IiaEC`uktg>;6P;gr)mAStoHLz?|FEBVF<OlE)avTWu05Au<F z^NQw2H$&_E<~+)__6-Bw=35acMEfZ7$B@9L`%>}b2kjh5@oq!+r71Jl94!f<(?pAa zm=gwbiSU7b>P9n#i|o063vB$=ge`@9J<7PvZOd{!%J&7Inmjy1;~E$TNYqZeqO3pP zpfg6BS+DAIJFh+z_CS3kBBU*3(uOMUyvg-R$Ad@vo8fSnKiwx{h3mNbh~y@1MuXja zo3axv-vc+M8u_TI9t=%i0il%w3G)(!4SNTz2veP5>_*zhu&S4mC=6Y_CjZFMf|!8Q zAoUGsmH1CjgZ%z9o;g>ut<|y_PpObKX`7Va*xM8pUB5B%e7iBNM=-DaBa}u~IaIix zI7Fj%A#P;zOO(YR6X>iv-tc^TFkyi;7)+i-BzD}-FftyNs32<7KZ$_%=c%1;Zx2D) z6f)&GnpA&;B|P3E-0ZX9q@W5)seUUs@`2)ExL@ek$clg|DSB`D@C%A0I)kgk&;rEV zpfM8Fgr|Z_b`a*ymwz3WyfxcKLBdxXS2hz6<>_`p2Hj$I4DpN##l?aw8tGHMO}I~3 zfot#oCF0&<ez%_g_)jgyg<!570<oIR$7QB3jhwyk)EFw$cihX@5u=%pENDwJgG}r5 z*+fGTl>x*u&g42=KNM-|(lE*2lg&q32G%?WH)z|I6H3^=#8jh>oB1p`5+gnm!{v2A z-$QSlW+HfHK9sVho5k`&(fO%mxq!_rNq#L|O~ryYEnJc8%Za`PGBipteNr^VwP;TA z;iC!^3J9m0dYV?HR;&eEX0OW;nn|rHc;H)YKV9lfF8OfnO#cU4({5eC@Dh=W*b8=J zk1LlKpHIxyXg4i?OtTsX(56cMxl8(;<KOq+68n1-@^)<H`%f<oJNnuqtmHl#u87%a zPYoHBGJY~yT!FkM=Z)fK`Q(M7Uz7%WC8<MPG{?Fs4Qs5VF2`{ro(G#ToIs>~tzh<| zeN9O|gCFFpAK}@{PkV7?YahwD!8)K;H+*cVorORYLCQXTCJE5XFneUTg{mwPyE#<* zwnGv7Zk}HVRl48`^<m=`e|yIpS~te|Z$@0#*OkvW$@cwM7|c4^o{RHtg^y&t6>=$i zRyA)}$0|Q(rT~nP$qF*{ygJR5$`YXO{yTT&Ek*SFouTP--$$PBLbC>cMIL@FbdN($ zT(&o5kEnhv5(7d`6u*28=!VjEKgYn|_kdJ`%8f)rjQcKd0x&P|Geupjvj3Ut{Z%^s z9|!#Rwfw)LdKwezF{DKl#q^^go%__3hnD5YL#_$Xe%xudhkR(9mmPRg-)`hs2LC%7 z9+TkJetg-MegrsHrWmB4y3}w|g3N5#(ZgqQjdS58gMs_C4LFTOQinJ}5MN1`7a(72 z-;MA`CS01?H|Pw(q^K$S>@9-+kxF$F1NfhsNH@Zt8JsN=EKPy`@RNxm=vxc>VJZFe z;8;Fg@m_?UM&j-#|DCM?TADz7uhs{NbQB_EY#?5&R2M?EWQ)kb0N6?OFV161M1Q0R z<ORnP(f_CQjS%|l*c#(=aTp%t2W)w|+EhGGBUGgpV8l59q{3$edH%B5|Lbu6cgywf zmCx>Ygk?jT?Vw+~)ZY+WB$>WobC#wcSkm)Bmh;X{6<6?lS-maGb0-Y5XvW}t8%S0M z)i~|6;@OQbui;v!=&oi`bKi4yY0Yd@b|&?#k%fbyo?oZbJ|%+6+WVqQek49Gvn3E@ zdJxLIGO0p9C8j7uO^4!7ZL%azvasK4mDwGrYqy(96w`RZrxtOydc29zxvr(-tI9Yg z%9MW1Bds6d!ZVAE`{v04@*Nz-RX)uPfKMZTD$t6V2CF`8vn9s)bX7Tzf52+4^pB#6 z8}<K{`=wE#^3%06tW0m!vBL`Rurm0)^3n<R{L+p7_fz@b4-Yr219|&LCSB0JJXGXM zkFB>H=U!z|?i+~)&uPQc8V}Fuk0l;r;V!;AI#z0#!rd&!l><SMB4l}@4qH=>37AyV zE^O^)dCu=k5Z#(T`aiVnjf{Vn862f<1TtMS>0-9gQCP!VKR(5El7e{dN%fX!0_v=Y zl-twbwF=fazcFem(jQyo?s9^s3eg}BN)oZmp%}tWwd-dx<%kI$1sGy3&p8RI!KDg5 zR@%14^K`I7isrHmCG_h0wi3WMrSTYMsX-gz5r(#5cD)}XnV9JjJ<RkE!v2{j@&eXc zi2PlyU;6?WzAg01m9bJ2UJc}STIrC{d%L8Kb?~#EYdDpU8IaLss}D48^$G%3hn@+6 z3{!zUrJ(yc;Q09XMba-^CbV8>JA_^r2dN3EJg8Cr9py{kOm9jHsuJ+e7)p6gL=~I~ z$6D8)2A)38BouW&P+vrk{_t<XAm`HAYv_R_JXk&4#IvU`<4`Z_EmjTPGEqlQPAs}< zAHHO2$tbiKJnyLDN%?#;@B#hEkR|3`b7fMiU6_pWW(Q`L(g*?E+QD;%<Mpgc3x7Mf zQWrU8-0-fzy+dZ#ux&HV%U9>KSMb1M?MuNQj0_fo-=9Avn`0%vzVKsKuLuc^BZV_D zJ$JFo;Rm&xU<=Ee5tzu`?KWA!QX<3AMt89ouX${^^f3jmoL|oM8()(|G;F9G#tlTL z>>T%DwrRCsfJDuI(|t_-BLCm9A@u`{KqK#qAUcUUQM;d+ZMr2izDuHYkAyNn^lmm# z<Q~i@((LWBb03ZA@mkOMV<EHdQ22nFZ<R66!J-q^n1#!JS^b;WV}Rrb{Lm31rvA>m zVLaWjEmc5U9GEsY1>}590Rg1dy%N|D`*lmupSOBVZq_@$TD^tOr?k2P9}#tqE6`<5 zrt_fU26cSxQR<r5ETMYQvMz{%Dx-uENF<MA|9M!|`rmq3It=RLeiiI{AN!Qtry`4M z-z@PzH0~eMuvF0iolg&AlR$C`vXy%7;zka%H@;C*hCPCTH(p0LC(?=34TpUbkP~FO zW&wG`6G8>n6O66d&2j@aFk$XrnH={5@H&kp`zIuFl3|`@{+}`x2lh4$SMzXfD?`Id zRCH1{1@kj@RySj4PKn7ac1YB6{oZkYR=^`!3q#9UXT;}q2%Z_FZgg<5aJ>!#@Gw|P z8XL&v5T6e4%Y0uI^2u`C`jhA=1jG9Z-QB_vu?qR4zS(YSZ~q5))#D(QQg3E^HI|9J zk2?qPvCt+LYVdAdpAzy5ujOh-oQ%Ot+Vz7Bnmz2VCV{bZbrjFC&-`D3I3z**+Wd4g zh|HK=)cq^nX+OOxdc$GePrQYLk8P)!QcRtz(itmoKsZNaI9-U#yR&7+NC)ln8UNc1 zK>lGhUWxM&jp)^@t<E0vW5N^>OXImZABAHyF|!1Qu`=6a?oXW!&xek>{|OKLOTJE> z;vOza_ey5_>h`I{N-EpRL||@8qd>fN3J40bdfEDRyV_*Ykk@H^E=9&vRM(6l3JTP5 z7Q2PwgIoq1)+$XW^vN8bSk6qdp13G_!1dGZ1YTs>3~7O;Q<d^PDNi?t_ht2!Gc(vS zPK2^?3wSF1-PTuX2egB!A@h787TBX{jVF%u&e{!h^NS-4v_kyL3OtkNW=wzjKS=I+ zC8o!LyJOYTOguC)3HLu&m~zC*TU6<?mkDKBsvcvDG>Z0?JQbuzjN@VvKKe)gT4RMC zzT^j=Iw@OaYJW@qgLZ)ld~WnC$B4?eb|!N0;t+osv3~;Zp5R#hfgkhOGLavO5eUeF zH4FTd&6-vbT5_A?rw6Z7En|s!9AIUNeZ<o$P#wvNgb0(YY`-*Fw^p)}T9FNCK57#a zJEn)MhuBEP`oz#mbcTQstAO{E3KIvc$NTa(E<gkD2+)ebHmG;N75n&mxQ$t)(yTw0 z!E~;|G{@e+2i@lL!x^T{J8|A>O;=?J>G|4JdMUI?F|Le7<u~i^|1Gfi0ao|jW-*E> z)ug9}8m>ltS;SXPPfFtMAyV&oxjM}#QJ1r;epP|_!Cc{~T&;QzF))KXNfLlD-~mE4 zA#VMf&@Gu@I*-8^$@7TG$k>t@LrInjxq^m%*=}N15Ytl{UwC|Oi2$o!8O<qm4Ta#~ z^RNgUGymbY++eSSHU4^rjh**gv{XHe9?hPFz#MCl!+0SAHB-1M%C48Gi&oQEr=LYo zkieW$sqt~yE76Mx{M-|^tdlqej~#fDM6Tj>-0EbT*#TwW_sI{E*B#|X{C6q;yumew z=#<4Mt4*$dLTpEA)NNOMMa|u>1|kK304Csa{_*N&wmpkPj7{_CS8Lb%WFyjhnOltr zYWz!#K)DFgpyuCAY>7!El8q(#xLAve7l%JXVtfwF-%cuPEgl^HthbCJ=GPvJGYJLU zC@E*d%4crpwQlLXt~b5AOp^s__<WW>aJ(-L1}<Jse&^|<CK7a5Oc7wB-=I~=5*Gm! z@;-$ug^@sfu8zAdke;hLOzH=hggTa0z5fP;JI0SS3<ZGz)))!XWy!(9eKq@qnn!e3 z9hjYSmFD|&rBZ=&eok+RVbS-+RDwzzC{N#p<h_+l|LUZO`*iV;e7U~u#uXbWfKyE? z`q5If!8ddbJ;6yPm9axyRgH6lF{;;^bZZ3ZH<$b%!O}2|>*J6RVztVeH(RkTtdJ&? zG8(E-5sy-tKcRL@ul)CEbHHfb<MOBG-_rY+rI62w6;=i$qspkF@x-F$tbS0|2o0pJ zE1`gd2<YQh@xR-uW+e8>-vHf}?5R3Kmk#5$Zf)P5F)tDWXX0c%c({MoE&TI3dSDKK zMz}((tv?;BWu*Vt^HoF-Hxe!+B3SfON4kh)s7m!aN{wOrp6!hP<@H*<&f^Q^qC#BJ zP;J|9FMhK5bbPbQ#4iR?v%%k5?zmVAH1674&GuBdN1IdSM$Jx#wX?y#w>Ph*tkxGB zUAur?o{+J6$K|mit%A>=X3LGJ^wxFTZ>B%rbZPYa<b?%dL_Q*V9>`<fYeDXI_}aux zBnL2ABTs;4xhq4&6}73Pyy-<^Vq$;Zd<;<GT+|n;VzXcT2^Hn&RQ)%+tv`nB%4!H5 zo?%ZO@QYxSn-SrI?UtI(z0DRkj~6rup*L33ZhV@yxEf+*O|~R(CWYtTBRa{z>mDgC zlj$Tr>B!>cH{$ZUK-WW}-pooxBQb7kBjm)D-kd`pdcs<_H5XQ)z)2;bUV%4IV?2^X zC(?33I!_JVi=7Qq)HBh<;V^b3#e#h*R_J?(WyiUML)H66ssP#lfM8<e)#(P>v)Hg4 zMAN6aVpmyP4e(|%=z0T&(B~6X6nbF<svBn5e1?~o5lPSp^Z|}{;4gdAcK!UVq{!DW z0&%b*f7c=Yq|s89*qGCP@ZDFpow!;UGnB1#Dh4DD(Av8BOuxU96t=zck>DM#w(G6* z>Vg3ipY!QjXZt5Vizx~8a2_6tJ7?ib(ukeBDcT%cUGS@L-Tnawo**|MO7rX^Uo;4L z1xH@CgAlWjTiq36l)@$qbT>N03MSv5_d{Pc*QmV@DpzmzVUB0a2m5GZ%Uq>p1h)s4 zprMP4d#c&kn~H?v#K2|bMZJG-92=~qYS5>EYW>$QV3%#a2y5{u*o#p*t(v@riXhzI z>@-3HFy#@)5aYOiU?cx~sqjB8fr2RNWWEYEzU0+A4bujI3#u!TRV$n_;T;JsmaeRa zT#H9fM4EMI+Fnh+iNH(|t+D&ePEloVh^Sp5yD@y{<a~HjO{ESib+36+Z(`^TvRk3| zTP?Q@2b`4<n&yHy{*FicS?#pTmTRIw5<aMg(_^*~Z*RdDubh%?=@aSx{4;4ljg`EA zhjink3F{noeX3}?d`seYb3-xY{ilxTg53#O8lNn<jI=i$I9nX(TfoFI;)WZR-EUg# za#@%zr0|xouD7<;HoMh*djKT{TGvf&q#NYQbdtfi3*Z{wpz}EVMf2aw)xRJ3Sb@PG z`0vWTU=RDV{i`wZFNZ(rkivH(@S8e`RS9$NAf$qGgQiGrlyiCLu~%P1)T<XB`5l+Q zvSW$P9w3|?G%+zzn(evR;9PrR|9E|mlAwk*tI2m<jx308RGhDSec`EOX<t_@ivQR1 zPp4a(6~OIGsQ!TZJHoi01%KL4suB?8{8ODkJn<YotNSkNa*SZvQ#%18(ByVc*L3`= zoPh6RsXrHoXa%19eMI7(hqr)i^XQDiDT*x#hhYP^6G-^nkBCl~WbL4O6b}gdKa?*H z<`V=M*!3#t!FyUzQFc{nC$!JM9fl|)ZY96I&sksk*CX`U6M~i1*eNSG_k<Y%KI*qG zg#fou50);gyc}9*bFS0-7M9QX!D$QDq0*dbSlVX^gGKYbZ=QnoN*S&<`(p8#9+<-P z5Bonfrj*E2QQ4&yTu%z`On5q{&A*VRH1VA){B3x?H77H?S}SNV94FI1DO^PNXQW<7 z9IVBNaZ#H4BX7eUkANoZdlF}0P^FZ;w&3upz+>5YJ_Y;%Jfp|F;z8FtNkr*q^1DHa zH{XtHIOW0aS~XcLgBue>m{gmAvuRA}1Mj=UYkM#a<gtup!9CLX;JN$@eX=%q#%C#= zQF^E!fd=>Atrw{Xh3vVYfQXqRtfR);Zy4XBh)9Ir=J4$P5Ie#FGGv!BtrL{hUMfeN zOi}mZT1PFBsXUaIwz=dtRYRQET_O0%I~6qeeHekjnq}~j&yn}r^#>i7zn8?o7uC=a zl8V_n6n}D{w7~}5jK@^PiO_kpU-fVW=SGW$Tj#2)P!e28L6&_kH!qA6f;8stxb9B4 z-ZDT`4yd|<x1OpxXE*vmNo*wN+I+kl{`_w4ihriWOA|$u;ZX_PD=9PrX00830)7U- zr+~2Dzkk1)pYC9DM#N?lkw8UY6EU}HY63WgkiPQP*Z&6cCv_@EFWC~$tXdvATNkdQ zDO0v!O>&znoey-?4#?wNc?yE5G;wyra#M;~`&5rtto7AZ8svKtxSScH!oMM`#Rn>q zGd-u13yvoRihISU*|Ox#;_wYPJvq-}56GX9#k6`JK7{HMy$pZ3P~l*RER4#JP;pf% zkNW0UEooQzk}G>MW064d)2bHTrb3ox6UIjO#_LmaCb8YGEVC9;s+$VYQ8R;v`+y#d zlKBh4+>?U+qzt|8clP~Fy|(aNzO7&FVx$<U{}r+=&?&z<#Xb)#Yd$kBqi&5sd@$Yl zm7{W1&lViy;9QD(>x>MBhj{XKx^G|L&t{2b3znbPZ4#qpNo7q;s(~`y1!Cwxl1?OF zvn0GR%0aigYNmiTo=8G8jacwy``ztG6;F;JF4n?W3Xgf`w`60=Xpt@Qu(Vr6p&K-O zae}6gM_Cebcj~xU#66BnO#+6_JtS{6d|l^OZZDVVwuVy^3<lk2jmQ8&y2SL^8WjIo z^LAg%G_PM?`(>qLM*h!L(ug^Mo2WtsE`5cD8j=0htScB-KtHC<1az7@8pt3MJk?*o z6A8qL_J`3{h_eDvW~OFNhIrTt5GrtizdMxWk)0raul*j9%4hkZAg1NA^(g7neSPiW z)dRTvPO)Fd(HSiwyg<qj{qY;p)+Y3l@Z2Pc>0kF6K%d1B-K^|8iSuR2+I=TqMJ7nz zCO=Lq0GDUWWKQY@Mgj*fxM(zg{6XVh%j&UKY5xbX=vumC0?blX`9OO;nmvk(=7b+4 zp17qU*{hvJvE?(qkYpmT#jC}B)`>w8=$QHH<sLP?Xcdb+w^8=v-{UV|WQ8!p&KAU7 z{kGlE1Yfbot?~8Y#nXAffnF?;g5Z^_jo(Z>6jWT*(9*Eb7lF{HtGgmJ@QoWmfo}C- z8l1%Ae^!t;-0V|0W=bdAe}6X!1G9wX0GVa3IRJw2`dr+8^VX~TC(;Wv^|LD<V=642 zSO}XtT{>+m$WK!a7kqKV<>%&?LzB+wnW<5vG|76MrKW4*<NodQI@m{RWPif1LmzMe zR4m%<E1$8`Zi(isB^&n3n>&HYX5JKLwJd5?U~SXsr+qyQ`k(va8lK#ac*b@kF9IM{ zPSZNN0uj#xA-A&-T<RmtaVe)RTp^2=wy7GFmlrxw{Nsz@(-EDb2u|3@<r|d*A=%-y zt@1$!pt|rs5~578vMYKt?sh!l=*x#gD=uv4eOQ}hXjKT*=$2I}V344$3!1cRE8n?+ zu6b)r;qr?^`+oyI5q2Q}8ZzSZPS!0Rx(8{LHhZNy5x8m+LUI_9Q<^fx`|_}xJ&Cvi zhjemAx2v$it}g(Beb&AHS)u&KVPq09_suyGD($e@has&Xz6B3wYh26TW~3868Nh&S z#@Kxbq4P3Yz&x&n_J0VBVi|!BeuGUHs>}?sj_N(2e<RMJoSi*660dqOT)Ue%D^H^3 z2lP@+6KNtHVz~dw1<*E^7g%OdRAx7}p8Sh?&AM!k6?6iQ=ei(hw1739*gE#hO|UY% zl*wHaYt?mc?-9dZR-&x>_X4s4KMhFpB@pV$CKB#DV+?MG3j%J3GZJS}a+VTa)H<y) zOjdMINe+0T)%YhZ7U{g?+|99@b6ChWG*j1FhB->&87cA{_Ed=($lJKtW7P6Va5*WS zsFDllPd=xbEq_a63^w)UyzB4}=-eSv8ypz{OwDP7eoQYYz(GnFo@QeWc$ByG4ojVY z;CBXz&VJG1gg^*S`?ZuUrKp?L1@Wg5feCFM+ZlG1>PiuQhL+=As#QR^-PghB9w6wN zw}fV<cM+GM`0JTmb&_=gxE$usl_`P|R9wR9HmMdsLwyyvXz#B822Kiqp+zItDZ{P9 zhepW3&?EfyUXADRno}Rm$G{i}Vtw^$Jw{DuB>W?qbafMroPjcMSy&c6)Aav4RbwZi zA|-*x8@nV?+i7##%YK&Pf?&!_yTaTL(HZ$@8*Ae{Ay3tO;)ZnP?yjV&%*%!QyNS4> zRLbg4A}ndD!t5Ll;o)+|)6uq3krQkn$%S?^UK@$QuuSgwXu{XCxmV#j4jLh_$Hthm z0fuwv=}(_Wkc=|c7P%3{+vcLm+QxIZ2o6&ZUa}?ATA6h~8GRkBC?m*A2_cHE^Lfs3 z-%hldL1kRnr0s>y4;m}R(o%=;z0CsfC9SDF%Yg}i54O)STxL+0p8*ZFOrA^pW+f%2 zpPt&k{NVNa&+<B87CRN(;H&<zrrLK!I-y_5L6W!QEf|5=={jhg`};G2-;};=Tr9xu z{M30ZtQ?GqwxZ_z-~fZFHn071n@oz^?@u{K1~kJOuV{?l*3h$?)bTU3J4%r!qzjQ$ ze;6r-Yfkua1EUU+BF7u~`l?BvplM>v2T@TXU-_6bme{kz%g#OdQ8`fjdtXrJp_n2% z99GLAg+4?xi|-9OL5sEh%=G+l>}ckyqs5|88h5o`qHET0I$jIKr2u}vZN&9y*V4yj zqoe-&>ZI$wil-?kM==KUsSk)TuT5M>1ak87WGC&|KcJx&NIJciHCJ~ZLH%~@a}B@{ zoygmkbC`$(z))-YtL4+`$q?75YD7oE<tQ2k4%XoUiSON;(;fF}fH)YltHye=bGGfG zwzTL<T?62Uq;zOKpHYAFhE($IdK5FwM|0sm)!F=F&<TX4s^{6-vl*U3^!x?Q8ZEW_ zGk-$Y%I4z!8QA}o;8ZK~4)BGh=X=w&<!=jLVAr-yan#r=6}cX>&d9Ye%Nr4Lg=f3F zptw)0v9`U-ik?!>Er_O+4pBzuqH~+F(W;3w1Y1;#cwx2L{5bBxdu`5OnbjMoygzBk z<ifd02HndQ)pf;-;kbUE+i3Pqiv{n(Fcw^EJWvbOHu-&jAN4V3GqBUm`1A=LJCr_n zhiAPCpL>jRP@w?rWqb}>I16GlIC#qZCJownV$R$t&((lHY%qYl4&Y2=(~=wGA7k9Y zM+*_woCoiz=BWkeScI4YGuLv}oE1;m@I@*Wg!r@k;D7Q(P;xwQv7E~&a48L+$VW+P zOv=-xd!uy@k_>frKIGbVVr8YEjD~H#LJy)Oz|u21ZlfY_0ZQ%Ei=AcZ`7AVCEHYy^ zU~hk{-aS)#0f>11;`ca5!`)$hSB<V<NLll>0K~8Dq~KeQR<q!0Fe{pLeKcaQjH1VB zbu}ox^Q<R5%?M3eCCk`%QbmZSX8em6sx(qwP4ar9l#roaPjtDwa_b(K%6ign))OvT zKrQa+bTM@U;9IjI@;)@%!>L5S+wYKuDL_X+<m_OcPbh@-16rr|uhT4U)6T%x$5b|& zfGGvzQgt5IFVnJgbCEjZ!`hKIV<oyUv!GJv44^6&YPs1fS%uzRL-BXJvK*Ta>q^Hj zndq(+SGuF6&&nKq*dnP#cnv>oCIwB6NN-^TrY#58UvH9yeMn6sxDco<d)2ZqNBqY} z*52jk%)jH?$gzgg1lSO}YLFK;FKF|Gttaxn_C6)Q14ZNF9Yq~fc^*cS3H&UEs$w_A z=B(3A!f!AIYG>z)ep5Cc#A;n7?e&-|R5E+55n@g#im!!Q<hJy$R`x{;!>?E|TplYX z@l`d}niiaYt6XgiE${&v+gn#JH?}(K)P2iToHzOw#&~qa%Y?#h)X>>59!Z&1vWCia z@>TUG#!S9`S3%()742?qAD%1XrFcv}iAd%3{f__ow7{b%3-RJ28J|hyeStunn(fO1 zM7-@&vZv`&c%O<f=}xNgHpf}SMsi<~R-03Y^b!&H&QhyN?SS5?15KGV)&j@+!7Pk+ zpS}wz9z>guT}cLua4NU6%g#(|vuu=T+xbjy1!UR(C^a`mB>$C~MgKBbMvxwkD#|38 zdRLhHg6ys`cx%B=y~+FIT%ElEUOrx?Xt0A38%RZ{z)rds7fS`JO^c2Pi@4bd-c$Rt zE2&+046dV0-|n>90Y47A4W~GXtpsL`Nk}>LwFewtiECKyPJA;R%YJE!xH>kSD%8jU z>eeJXevx=8f{v9=Y%Ux!Be%E}tCP5bojX8}8q3{UI{SKs2zn(ezFH)c@H>Ec`xM=0 zy#4lPJIxfK$uLG>1Xr7|cU9Yoz=mESivK0seeU07;Mhv?Ts4Ed$!)cw>Sny^{ZOYZ ztd$h``v}RI;Xd>B9QzICk;&c7>|2@dmXfEbHm%pW9rt0h0>Js4mfUAIRh?Ki&hD>i z4glA$=F;6-F}PR9HlpNwsQ1^B{KDbG@h5j|%#;c5I@RVhU&VBKki=B|)hmRNoAyXN z@p$pv5mR^rf5_iMWB&ro17JSH4^gK1h@a`n#r}=wX#utTa!&)0sxuiAUu?~$X<fWV z;dQa8>|rW+P9-g$DWLMOc=^Ldr^3Uoc%J-Y_%r$9WRo;4-h+Ow&g7eq65mCQ(!mzc za=FR@u10ycjkxxUP~(&S5BssvJWycF={Sg3=6dj3EuuKP)=jM6(9gP(JP%tIx?t5+ zWlpsCKz@EV|FP5>LjtYA{0;_pIMAKcr!r5Y^R}~k@GjBF_n@#i5qf2lHnu<kzycnn zsSO0YO}Z6wc&wnhDs$O#^0=~%1Oa;G^y`fykHfFm1;>SUj&D;goHmIFR7Knkca{o{ zUPjCjrW0gkh>1zk_^PQ22}@4j1?o#qgSHntQ-kfK9yFC#dP3InT=Be4tX%D-gbf|) zsR;0r#Wvk(fBbdviZ%_p6nv|>aU`CTcB<|WE!2&}He_;ZJ}&=Uopm+FR}%XD7%JXu zLhi!e9zRrM6zTdKo>eO<@v`ll;t0TtDu6WVGlP|A1CX6ne_j5Jq2c)y2xs*~1a2{V z6M<ufY4~$p2lLfkK%tm@7zhJzvSA8z5Lct*u&PO|Og+Bn<O%M%S!s1xYC4cb32$kK z2XRrmdCB6<VOZFBp`xlh0ReHdYqtPO`|GmpQm6T=qt6gCy*Bok>DLYSMz?{r3ZFk0 zc0EQ-Za^WZyA&vO`aPUvsOrN*$_b@l9Q(89foAP7!paUw$^Uxew1Y6P!xR{5B{{w* zjV8MTzZu~NW?EFWhQEFF@*H3})6Ep%oet=dsgfxt@7IpN9hJk$R99!g@aj=K9bzu7 z7ViE^YgkuIVF`RY(d3W$4`cFLNqH<PaB2coymA4v;+GpUHnB}z<+YbP@0pD93lGUS zO6z=!TFolx{oakEqEmR;zc8xVuzLVUdDyAzyE9jVNX;dyh@6v-94yhehKFo$(G65u zE)m$qK`$7^uGwHGRz6pQ!Q_T>{m@3cSVBxqUyB{NljO{;Ik?`>`>{h;6YE|7HD3|I z4ZU;>^qI<)O|t3&BO8^zi#<RI6~vcbZqWSvV4+p3SY4Bs-P>!c7njP6aCT4%O{U!! zO?qI=RD_EBEM2fYNrDD4`-7&ku*!93q0C^17MlNQ(YY1>MMW~7+7kOu?+37#0m0N~ z{Kj^><@$7Lj&n`#U0dobm_^S*nK7Mch}2Ye##W^&i_ErTs03RG0Xaf@gZki1F%Jth z#^2P?V5Qt%ps`~x06s5HGF5wPJy&Jz>bV|uE@CvACDB#cN0U4fBiW=Y-nufThP^oz zww>kkoQw%d@d;7L{S<#RO_2T|rr<5y?I$kP45lh`ws4hu`b>^b^Tk_24S?#OEwiEm z*!rn(SV~)bvQTGDg@H>OpB^#a{LxXb(IqvX$2f%h-AeWW(qRtnrTVMPAO?uQBD5l= z78l(|{<9_~RCRX060hBM7X%E{0QtgoA(N8VmCbIyNsnGarzF;Gn}v+i_h(^4;N;%U z=CiyQQzrS|S?A%!Vs~=hyc1h8%(9Q(VEq#yBvj8D%sMQ|)L&6bmVbo4hzLyP2vbY7 z?}_ohLZffP_;X1|?sFL;P`Pq^K0EvV(&B7~NM`hkQh>t$OYq-7uhWRgZI|UJmAY+% zLuQ-k;>A^(({_kL5Z~*xEp4dV_=}CLxoY3r7tpqjqbHovdiRa+y)Ww`tPIf5$;$Qb z?MI$o*Gam@Z#PGa5yCxLklTF|e6f$To=57lR|iJ`O8*fd;sZbW*3`>hXJVg5kfwEt zBK%i(%;$1RMA0+cS8~Q{$&BA^XUyq*T6g<E%ScrZ*A=MhgA!Clizp-3iq5(p%ou2D zKJh(GUk-eTO=`g$1#i_bS$MMSeUAXmd#B<1?8rpb!4U4QpC2;61s~d)M5vS+olZA4 zBK@2T6J%N5v;zrqRl*D5%CC)@m1<IYmEu_zl~+lgt!Yb>giJB`xqTVL<jE~{!tDAD z^xiR$iw#$7=}yb=AZ+8uY-?fU;14T4oJS#Qpwm)raQE>;pQoiUFtd%A>k-U}$v|$m zIrvyUE}cET`U05VT8p0n$dLjs*2e#x6v>bv8!sV*`2@0LroKN@*5!wS_IPG)Mo7{& z^3KH9F|wM`m>9J-JURSN(bASQh6evYhQ5vb*3KLYZ>Hn}*a*=3X@JK;<;|Q|OV)hB zr-!L*Z71dm5<<THS0RmS1CrsqscWnlOvqR;FjjhPn>iddiuI}-(I5JXJ(Q4&v+Plu zI+CSag0QqL@8RwT>*Id+O4AKHV-Gv&yr@B4mxJ@qPq<Na%zb^qVF40kUYnR!Cq%k| z#uq@xx#{g(N3O21r^R3lwQ(L|x5<4Fn7HJkoBzh!%3YC+|0#CTkDDLp?Uy$S{Z+fE zuW)|t_W}Y-^)8><2riXS8>>#kyFD>8!XKS_>aD!YRQy&><RlSp*%K2>tDDKjI8^bB zw;84nUC+k*0(qD-sYO5jj)y&tQG@W`k2EoZ90!9i1&Gx3kZXwT>Mj2a)6N?ESx%=l z8DAoQ<=2;q!O13`3~Uq0?2x>;mF@(!N5p$lYQq_XQ2Hj0<<f~3^>wLd0pYIzR|Q~E zU2RtpL1gT*8e{Vbqb1tH`Ux25X_8scJG(i9eCYJ%@k#qdOuJKWhNsILaJx{}m*cry zeBGNMj~~}$fvPlOIxe}MzDU<o7v7~)0oyl0$;K(rgvmsygG9jgsk6L)r<PtxCUt#0 z`o)w%?Cfhc6PXdd6`-X`15NLmdhfWuo(5H$F=Tz$ljq*;wI_E}ny26VK?NMuPCYn? z$KRQUu?QvXgA!oibB3ASda~4e?tE{z7<oMG)%_uTvKLC2<+D}v8a7>7kU@HLR%Qq` z{Cx<MUxCZtBl$K`4ZjzWs|&7}Q<NFdA9^&tyt&r`^x(_p<uVtpAXSmVi7SG~k72Cj zj*p8S(NK?MSbS+gzThO>2$f1$vCB-}qnt(ox(c$amAm_1UVYgRXEVDp&^;Fld6kZ{ z_tUR~6{Syy-~P?(i3bTaD67}oP<){Ahsz}Y|FHJn;c&KF-*A*5(W7@Ff)FBl8!bq* zi6FX(5+ZtyGNVNA5jDCXqW8||z4sQqccYHc-pjrBe%|l-=l=G6eBWOV3<uY&bDeAb z%37f~43|@#1kd1wR&M*}R#kJcOPV-kGaY#m*8qF>$m60H;t%#XikiO34XzLs$U3@7 zSkIJJRy<mXCReezKz2&dhfBawEv^@Q?OOT3TcUPwHBM(Z(YJNK3elVgqFx}3^>aU{ z5fv3*<bYhROF28F#8Y`3??6nH8?o6lygEiLK<5$nCC<k>tKM>T3v~KJKnr9)ub%oU z12rp+cihH&<1Y~1%7%A`7+DceMUFJY3!?uoM)2=H@t$EOVlX&A9}Y1xRFO<;ivjF? zWGXM;9T(KvY<Fk10)nT*sL;p+%V7OsKzJ!Gg7{__U|>gvK}F$<=RWSxOPG9Q7?O;W zl3>#w6LFLg7aEBSPOq@QH}{w}w;Fz~D<cxj+PE7NqJ{jt5bE^Hk=Tjg-BK6&{b2In z?M7cig%clbZap1x@Tp#ETmA~z{Yt#!6+3C&*EffWb$5a+e`$KGA5JZ1^T50TRaRRR z-HzD+i@r%2jJ?q^27I<Uj9QAJ@PvMPJA@lrV;>kN;gGw7Ee5FF4!(3sXLV%G0L}DB z$e<bc(<HTfJIO;8nlEkw{QwRlV);s|)}%zKOtpQp&e(8tS39DU1TUA{t23zOfOjw< zo-8f9nPA+jc&i|6>4(-(|L9>Jvq&AA@4=*}BnxkF(fU9N*;(6DUm4<Tfh6Ij-CYx3 zpa9*Rzy7V2KhK=6Q}MX!NlJnOqIMJD32fjsOyso^$>LTJkXTLhW9Elj?6HdGQ-_g= zpnPUt;%uHFQYLDCw?3(C#(E+e&_sd$^C;U6Dw5J{Bm*F<*_n90lp_rGg_Y10K0`NC zF(O(67O^_nIGIa!b!uBY<2&1$l?WAI8&k-=0>aEtpu;^1Xp-LX^;JE&Yx_5`d{GS| z1f5uz)JK1@4}i{O_lwOn5nH%mHs+o1BSvMoo4buw%}E(YgP$R@{kko!c@KjDDM=~n z%sGn1suG2osDj6cBa%%TR@mR9-d=5RtSL{%Hy)^KcIPztb`0FDx4+Ma&-@Of<+o}^ zOUslHu)So#wx54;?9xfL8CB$QnkShKD$-ElGgnyd#^Jjf%6DidOLEhS7n=T{D>fdq zp0cf?;IinAy?nX*Z#4Uv90s~_^)15Zz%*=h*P$<n)laoV+Y4(wOVI!q-1*e<;RQB6 z*8>hsPHq5x>%8=&sAin6JEphk8Zw;D(HtCb7x94W#B8xGHzHEudRsvxr-=Tq^vk$4 z!ush%!<ZmTWZ*7oO>P3=O#68;)ZllaVb<GSR97%SvVts1ivD}%9XMxg=v(g#9MN0$ z0|P#Hdi(2`lO43mkOsXI?SJiE6fBpOU746Ioqamf=JjpKr!i0%uGdw<f|W^&42ouO zzxZh!P6ywjU*;<_e#PzCKT5eei7M6zcWgjLVbIkdy_6<3!r?6dG|fC@5yBVSvI_4~ z8FeUmrjjIw)~D_XuuFc=5>&Jp_9qJ=rnBdgG<pKRy8mI@Cp2klIfB3zVHVb<e(|$H zPL(`PwWRpXB(UAS5PCbtn(J_(EuWCe&!l+$BTC+4c&5Y~?9g(I<EkQAT_l|9)wG2* z*#7mVToSrjykywcMY4P(11MxZjpsTQb~RYd3Y2`yQ-da09lSX5Rb8sl`gAO3e}pEh z;-lzqs*E+eyoHu$gdp$}dmOw!m>|Ti;&drp!OCcxiHlE=<aJN=1LRQ%G+ew=)5U$^ zrr2~Z0qCh~^&HT5L^rN*W$G$V!lFsQZP_pM$0{tU?x0qn26uPaDG+Q;(8#k#lx&S= zLnz(1&3}Ym0YwOYuaWBa-;mpzVNWfAJz$6Mrv-R}x<>c~E8~!tEsDy_{|7Gvuql*K z%qdlk*6n;NvAvr+ltJ(16Huh15?5#0pcqw1C;@3LVQBWd(9rX5=q?ZOGz+!JQ@1@A zqeJX>S<P;C3?MWHF8kAZ`NrYm0-+Mu`G06{JLz57Cbe2XgNgQ1V^t3USzZ@}0z6L# zTJ{|(aIY$c&7Kt-U3_;DX^Pe3ioe40y`tow)79qenbjYjIvo2m?fqDMSlcX_PN#Dc z+kMgLq20UIKU18lHwAh(xwNzpn$C`|FR68q221nVoeaajWm?18tR!DIY7SK$41vhw zD)Cv9UWm|6)<x)vQG1j7{JUDVzb#xs9b@}C7Z6?*3Xy*Lc)37ui<sIzY)RPrw*b*m zB3jXBM<aiagy^9RY&nS4Uy-|kj}~?^?1!K5I#>FP59YxHcl1jj%KZ##k}rC2!K;!i z!e94JTjuC|?hC{PwUzC_{>dwiSn32|D?p;C2-h1pZUMyOVx=vJB=7mR!K$JIu?CyD zx-W#Omwz^vFNaaLwAH{ao-*`nK=$NI=!tCYU-k`eyxy}h1ZLka-3eD?vQxxRn;B?z zU+P!rw0*!#&^RuAYHL7&_2OesbYI~&Wrs+z3^c>_(9V|Ii?zM!*qfW4Te5kltvU{? zg90S{;PUpSNShb!;ls005+VWkg=zK0FPhTxIOdgZt;q!!H8I1V4q24vR|^Zi0rXcE zPwUppZYdWasXq{>h=S-vqNs61TdiQ!Aa;&xC(<KDZOJ7y6|6iAZK4K}!(&fK3eA59 z)cgz7mh2~9yzMTr{!T&^+Zn>Dq{do+?(sRFiL5(YgzR%}p-$zMkIotCS3`MXR^KFC zhTWQ>pa{!ft?~kGO#!Nip*L8B=3FVN@SY;E;C`JL$gP&yzztO-F-9YwgvgptKrwNU zCcRuc)34R3Y_Ve<67L;FPU%FJSOLjh$L55xEmBg%k!+FE5~2C4Y&|bF-ENa!J=b>( z_Nvbd`5#Kk;keG&rd3l98!`jG@8v|n6wr2q)V~?~Jb&3v4l-|*Qr{?+j8JiB9vA|2 z$?zga!lIgv3~5$IT9S|x(Jx%w!G`Ii#>af>DQ{CBffte;2QF%|_16U%Kg>QSw@r3D zVn;m4owN7Tq%m4S1EWZt_D5Kf$iRf3Cif+!K-uJC*JDXjzQx+6)9m*#un2nk^F+}M z--x*`RcJ!Gr|ny$wnL1zEJ9Y)%n7GLDea(?)VTg>%8Bz2Nq>fjIPXUDO9Bm<)K9z! zVQ^nxKl@^;eY0#0>|Ix*ZF8?M?2Toy5C}A0E};G!&9G%UYWV?%MGNk6YOmkVA<q%v zjgIWBO5AaN#zVgOtx@`J@#Gri#EGROhiqTxH@uhv5n?A2HB<FiTy7g#)3kHO5uoVf z?5Ugj>J4WyFdW8_B7!)Ha<GT{C@26|AFJsxpdSL55ZZMy9*zxp#PzDfV2CmYokJ;r z+?Wb{ekK(uz&Q5BMuBf{xY4h4_42SKglixHEz>MX)ZH}8G*FsVYIQ->KxQLJkmVfp znudt9&ZhAO;Oyl62<QlRbwwiN(pZ?@?zTwrGmcSYtWW$)+U7n2ONY$?>~T$MyWdGg zB%=KMJMy@eJ@Aesa$Ph@+@5HP+TyO;Ed_|J!|lEVr8x3Z3*rku<agd*$~fcv3?FoV zdo`BO5KR<87(5Pr7)Uv#O~csN4(f(bYVL^oqUx<*iPRM}ug=5HU7*~DB6-~G>uFLx z=&Yf9aU|$2{linQhLK@{^IFAJv1<5$5Q5~XQvA2%*l!W-fYPFLQc7D}+qr1uyyK#> z-_T$I3-jjn(RgAb(L~4jeEq^@HaDzdv67t2g&lezy3pfzfsez-J=7+daeRBeGFv(* zdm-h#J4FmX@f&QHTc=yveX{|uncE3{nIQOuFadv2;e+&Vz@nig#Ic%j3N+2>uB%;k z<NJpNF<>A#gm2b}86<g0>hn7-<rev8cO*o9SC`u^q0;z*PskI;P<g0F#OyY1%dF;r zZqN0ahctla)KJAkP8Ad(enEySx;8X3+VDC6Z)84NuwTBg67f!DPwgTwX5EayT%GfR zUA{(x4*q%A$@cl?V=pbrkoQo8B`p=jODnG$=*d^c*egCcRXKCK?&9>Cd!9y8Q$dTv z#1ttNIB$1jAcFE2qgqJwxzdQAwCoaaB7vL;dxh9_BJNO94Bgiyi^HmW5}SZy-?Iu3 z&G0`Z`z-m}+#@AH;z^1ZV~>sG;)B~LV>@?`;c*Vc7OFRnJ4W|?no7DGXpO>l#}{oH zSoZYd%UQk_qrrUrP$A6KSaL1ytyn4x`CIWDEzXXJY%)pGx5<JZKX+_UAT|#8d4nOJ z9H%NA0)833f*LgjchZ!idHVvZ<OC1Z)rZrXOQt+eg2n|HyDDq#=4M=any)ajX+O9R zx5uqM1f0qwL<SM8Oo1x&?mC;ZMGyh~^20Tkcg-(zTBr~wUO?FVb)4Q8=n<3GUl|Q> zTj_N@V2+9~pYi%OqtVXr*#=1m6vzkjrH7lXp1oO%<zJ5nQWIKPvjh8fS?LL9E3Ny3 zo+djOY>s4E2n^atZjR?^3RyufMy(wPOhYAcW&hP<ZjKhfT+XMAW$LE%G}NAjWG`RY z-6SrZTDd38J-{*U3=d<)rqeX%02t7~MnQSMi{p*XDBt<tnWMhT8&GPX-`wA@%LN7_ zmJNvPq%Dl+D9ar2n@euaR9IAR{tRjPVV0tOXl5l-SR_!Q;h2J2rC81uae3GRaar=S zJ?dsPJCHd#O`v$TXtN8TmG;2RYE~p(keAEjx!^Ye={i3d1rr{)Go;GXM40x)6W<)g zHMX7GG6#<Y%Aj4`;mvp2@WO_(87)hL8}~+pvpVe8T5nvyU7>Dxr)BQpDB_&*eXD^v zFX~X*3P@F2vO%XgKNmGL3XQsVX1$7mq3(yLMIP+B0~M(aJfWi3q0i#ZvOH@+^~5wz zM>Iq?h%!yHR7IiwJvB{;W|l-)eVvgEd1|`j=l3vZo|1Z)(P^&Bqn1Q$6@|Q>=)o_o z{t=<9!nWTaD{3VR@_aW0N&f_1dMl2uTWR?Km|n&)gQ4KMh^)3-kp_$oxnMnctGxFG z^ECRJZHhoyM=9Cw=<024^2k8sWbCU&8&=AUwIwBgge4cbJr{BP(TjI+1=XdBuuNuw zGiv6<JPB5bS4;_(q_{OM1>lRwQ9UmScwdS4s*J~Y<VxInS46g}$TRYn-DEWS1wo9b zELO38O)@h{E^=Gtw%#0ci@$LgsGO%5Nd{@Zb+`Kg&fw>-ICmN6h_+0M620+7*34A& z0%<o7nX1+!`y-bX0*U~&gNb-(i_}FVv5b2dAc9GXM`m4+1@we9BQSjz_yb6YmUVJj zQci%K!tq0Zpg_SHNPIE@1cc1t66xRZqs&q~UXl+muvrSbAJyDX#Y})~_Om~n3eL5b zbP)wL-!}gtH1M!p)(xz*S%@u@kvRSN#eZTrg@jrtM~V-z>rgsM%U9GL58;ILkq~t? z@(O_ZQiPc&C7Tt)qMm#r(1Kf<TL%H<x-ZG{wMhIt!EBXXY5PQe5a79WnIQ+)+>3%L z+}#PD;$pYEyuwlCJWm=}#qdv)j=8$XLf%h$eOsuuUG6rPxxK+~5N@*!Vm0bZ=2aY3 zU}aqOrBbVESaSP~g{iXUQaVD7@&`a8O<`EOrK)A6b|l|yXqYn$6)mAH+=yoQXUojr zcx8+EDYNYp#(!OJP`7uDwyn`Vp3bxnNB>95&Byr1bt4&o*&tlimMMBFOWfeTqF|S= zP!NLDIk+W}2FPJe2M0kUtXL2C5|<y$R<!4G;p6c4s{;2MJ8(H$&60bZWH8+C*!~TC zosV-K5MhNG3@I@W-qCvbJQcO#<8qV0Cht4B*8K$BMCRe9li7tE0mlf|m|@?yQK|Tf zaa{cggf0unJ3;smqm$5E7!A=Kj&&HtaLYKm-FSUTD4hylQ?Bwm^Vo@iGo*wZM2=$l z-r<A1saKy&ZyF^|B5e(?@>SJxBW#o%NJ~Z4Nu<>T8H(2d28Yep=i}c)H~*{p^#1kg z!(HhNY`Nsze#8YwF5i{OKReWm0q4fY)woUzdB4yE^Uv^{9DnYRJFB<DYk}pQiudA` z+w~>horKawuAehRtV|ByCNR*udUz}cMMInxzZ?4~x!HHgxib|`WY8Xk<XS!lJf!px z%SEQE_+ADoU%HpOM-FVB>f_1fUbXUU=a{5c34YQ#<pN#?ne`gp9N$V-ModR*jMCIR zf{$ZT>kmWqfYDaYN6ZAydPins_^N=)cjBio4^w-qfn8*VCc#=K1r;kxrieX9`0Cb7 zhDe;QYuzg<R>nVfRCQWck(F+xla~;k7i+aMAl?E+9#<oy=fkn1$@DxhTDr44SXa)4 zt6!USoXEHC>(|-esBzV^m0L`L1i?Q77*MIjo{)<@fO~U_M-c=&_t@y_?1m4zs&VyA zQ~(^wA@aoBJf8ZPwD0)I;1Awk?dYD=B|YXn_YZKAGT+jC-UL!}>1u^$t3?Q;|9PJK zIeq%Zu)L;-A0rUGkTwUvC4k`bUQ6c$bql1Pw5Y6^W3=437_|WvBkd<5Z<m53&*rgW z<IA(%pxYxFy_b9fpwJ0Ebs$)SaFbLRMb^d;+7909)W-)_HxF=5=V)B-5Gd2rTmZv5 zuE=~lZjMjMsayM`9@W#5w0B6%T$bJb7-+_YJbPrlM@g0B7GF#LFUXWbuyY)9@L!;* zv2vNY<P@2we4%bt;Y`-C<7uwQcU@@=bg)_D>UYHiE3_}^iE4MOxcc=ol?TsO)zqeE zkfQeI)+)b6C6$N0B+uGIC;}i?%M{)#$GJae1Q>@brK6Ob!uU1Tp8413=X2&8G}O+B zkMj|>Ph(&c^zna~7%M8-6MC>zShpV>mOcBI=M&J>N&|anIg+Qm!c%4WUiAYm-_c<$ z)pzekrg{q;;3z;-;IWr->#iAln_YFA`kBULA3#mL2ZhZs(A%#dmkO?GQ|T&iyB17f z&|~9q(}6d5P?g`o0KlHqkh*qRne!U}LK8kS3;=`V|2s23@Uq_zy``PlG^Qui=f71v z1tfz9D<bbZL$Y;p2Xxw5NYUabZel5xJIxCVX%f}5-7LmoaTG)=ss=QL@d+z=wN^(X zpPJaH+}eXJJ4i6ZZ;|gkb`N7{8OF=x1$3D!dy48qzgsK-d4Fk`UEYM3!31d(5uQ}4 zJn60C`ZzIiow|Z+%Yy$=CS_)OX2~}@bK{(FS&pg`^a$ZLy+jN~4SQyi*OC2}BUj66 zw&r+5ZveUL`-{M^@Wdz5a-n1LJlYY~Y-dNttKYdruE=DVZ&shui&2QQd$VF)#(_;_ zCSCXe5;SFfzHXU)kF)Ss^n%wNx+p!U#rOkUW+qObnpDTn3Oc{S#RW~rw^ZIW#N`+r zI69YShCTNwK8itdKTEQO_#sB=Z*&I=l@lwMerJROU7E36gfP1!(9HF@LEQkEnfpL_ zF8?~-!xv#d5q&m$*-FC8P*ncjR)Ge01Pk-U+R0bJ@1t}sOwM88raf|S&|Ot#`C=<M z`K4rr_a@yzy}G3U9NBVgxR)?4Oa(qzD0Ni>IwD?HrCeWkz-&djrIyc4&5vq(@yRym zSB>51uc{U`2eXZJa}4Q{Gw0s`utLI!BBUf$5!+h*lkjf6qP?i?X=J;wYHbl9#CCsi zx~!N0D>1TW25LWXVm9Zc4~iC&zk#92w$_rH07Ox}TiV+KZ1dZ}mC3jiY{PEc78w4< z@G!48WFPR(;@n;@-0E+U=8R<n`tYP}L^>giEv1nE8NMN$n27E9bNqi>_WF|VHRs^) z30eKA<`HEH`B)xt@cd30444q=r*>!4iQm7kCq1>2Ts-b5GB!p#X<)c|LhG<wqQSL4 z!2sh<@p@4N;HW_H*dpP%1!%&vi!Stpj`M>wP#YZED~SwwzmD%1fcJ%Z9$ltM1IcwJ zmzKGIQUAZ$L6!ex_!1vE`timf;rSm2a7+bNg+BJ}!gUiih^Ql+PFHu5dRmhY7^2c4 zc9AGz7x-9xTp^DKkbCD1hja$$SO5k9$G(s9c;jZwt^NsCTg>i65fYim!!_CNwaNq% znF}(S<fB#&1~DGKN%|*d191M9?8+&rP1%c!A2O?PbQxzDMKwsaT$-(?<NbAiLMUhW z9+CI_Vj=mKV2qKo2(cI70+a!d41ARY>3>M7;>oR<spH8xqKlT+=yfqUx<z)!>Wvu7 z&{`JD7G6<juvLLB%)wJ^67^8ZpuDNbe!~FnOs&IJvjIDFmVZkEn!%Y7wOAQfMzBX@ z1!zma&N+Z&C)BwNIZnkT9Sh9;tUguaAP*?*d4Bk1M1Y<qd93^Xsn5m2#QOzye-a%V zE5R<*Xvaj6Ms0d?Jm^0;S<tT?DzTEU73yT$JdB#0^y}9Z*x1D)pe1GN@}|x}^A<}q z@}5!y_j^Bo4O|BuVK!LQvagcPURYoKNLLh_dz@7+1YEdxN;n%|vsBk-8!v5#7N@+5 zS;%u^jHUEcqF(3JV)@2!X!`nbH^%cG-1RTd3prBB8*AA(^^bH^k^~q@Eo=bDQD|)E zWmR>T`ne96C%h4gk*yRT+7$Wq-&o+;5dBi#!LtWey4j7N^W>clZmL=ZZ)?TGN*oo- z0J$NGj6ug;2q4w~_i>=Iqv-O%z<~Exx0JSlAo&1hx;KD(H5D+lepJRunu-MT1F`G) zJb|!Ske}{9e&Zlkljpq&1VZ;i58fmY`{PkP0@Quv;QD3b-X(b;*tN=SrI7noHr)aq zqj7L*6-x163Pf<|sD%IIikZ&|CT4L1ibT`z8u6un0dmpUQpW`YmR$0kTLYMe%S*jF zPVil$@h<G=uYT-@QY%M8hOILH;jUNzNptZ5bK74s-x~@!(WAN>w-%?|dN0$>VtW{v z-l(It*^Xlv5WdXh!d76|8Lo(+T%(x|U6ucHB^I1T3|Siy8B#qc5DGQtNw7D{K;{_i zFcqGd1M`54da*@Mdce@`$BCoOGUm_%RrngY6Ee4bthwSlt{o}ITy!X=uOoVD*xMg1 zxL6;uC@6zDJXgC+I&r$W#$zmc8ja+kIEhzRwHG5Csh0ecwR~pk)<(f?89v3vsiFBY z7e5?I(JswQ!c~}|)Qa}Y?@B<6|LXHWLFGI-Kw%3k#G@r|JW{Yu#4sAZi6<fS_<Hrd zy~uykz@6W$lLX=VwI1*+`nrN8sOF&#K1!|AQ3LqEzTMvb_IkLr@>ES(y=}M=!^5p~ z7De)aNdxiX4ry@BLX{09p65E!WkynaU8Z^Uf<h_mzRsT;9~z?E88cJ8_Bg?bM*7rD zl#<G9!=>sS!e;NlbHV!P^+3D;<LbfA9dh+Oz4hI(BoouruUB?rvPX|q<l}FqT5B4r zEGWSGY@$PAGD=3->iU2jSy>E$JlRdm`jf38bXsn=R6P%~XR2(Ii^xt*q7g-%h_bgu ziJ;p2e;|G+mz>1{SJ`|t?#igg7V)D7I(m=I=3<HYTl>#s1HzsPn`0$Wc%_j)OQ?u5 z8r(lpl#+;j3iSTt^{si4Tb>QQor^Z<KjRd_*8lG~1wJRQ)*Q5@^Z@!`e4nhPJE<XG z5#4}eCO@NX(Ovg&Cv80(QRLRBbppElzvfv0-3UDxvTRihP+NHDK)3@sAjN6~Dz6L+ zeV)VvnUTs?J;Z|G?QNVts!)m(U}QutZ%9yl0!RWQ6XcPm4g2Px`wlm33AKCNYrdjF zIH?cu_$&>B;y%rlu67;$RczE=`jwU8kjg8n;~}v!&Tdr+P3Ij^H8jupPclBGcLFof zZPnHJu$x9bTUQn+5qFtkpqA}dX1ERjN!b2Si@=XiIx7wNnGe@>Ap5wTI^ET7jLVd< zsR7ztieaFmD5+Mzy_*9AsIwwF<O*p^joSnu*;gZxA%D7X*EH#u*&2=32Q%Kx1$}5| zwEk(W;-R$uJxjogN#Y(cTPXVjsO8fAr_36&ZR$x~rgoGuQK~$MI9LLMr)6M{*ippK z&?j-JN4){6BGA#0slMS}`jo_?nzJUHZb<!VkCfB#T~jj{IpigozLfuCv~|Aps09|R zqat<@4UE6=Jna6o;*Y;Hy^+#Q=34c6Ttq2}PuOwKEiEVw@atZsx~{+R!xdkCgO{D` z=JshJy&jqPIDsF*p26KHBw@zuI2HK9XcaLH1x$a26Dy-pM(6JhciFT3L9ok@s0R1m zmXS$=5OA>m_u~y;Oce#9f?)6|<eS)dDr<L&z)h&ur%8Ttp1mT~bQNV9qMoze2fSvW zSPPsXYD%E}YX@{-=9Yy-_;ey-p+Yy9%4K#-EpaV9YrP!Z0Lbzdel>z?2nfMqcKL)Y zmRE-|<Ou;g2=I5~r9_;&U+)xcK&v-8Pxt9k;j_$^3vlsz1Zt+3dpY(UpuEj*5I@_L zF$A}%@x2syH+0pqqu#Dj1PAOYx^9c}z?>@8rSj3ihkMUb2<mMXZeB?22N>}Z7ac@( zq~zuR`tjHC!jJB1qQye-%N9>DU@Q#Bnw8YtZ;JpxAr8<;Dto6KwbphCK9l`|3(z5i z#iX8tG8;R)IYF;QiAB7Cm5vKw381m^1Xg<6#lQThkg=A>HJre2(UK$#aEgNxsn-Mr zxoGJCxZ&M_p;EgEFvLzw1-$68QfY8}9M0wN)N8)JAL6`@yHh;S3yUgWGz=^ao!J!R z^m@R;t%?f^T*CJbin?lIXu0;R7952wg+LwvVyI}uR$NV)nP2MdF6)oY42D~Ep^ZOB z2YV>wFGSu-o&{)e75A*Q8_(R~3w05D0?{3XGZ*3d4?L7Wi$I4y)>>&k>Q6%SzSBat zp6x_Encrzd@3BjYbOFjnZo4!xXM&na%x<+v)&7F#SNmmOj6`XSy@m2-x4eOiTzjjW zn8@pzrBO;9+>5o=Kye->7aU!#z(1u-0e}~wS*~Q2Mz%(1igBYQR`n*bfX3X=>6q(W z;on2$@SnI|>^5n7p=k;HPJHs?-eatnZ2b=y(cjolzm%p1=Jh44fIR|ffzbzYS1cix z9V-~@z_g$j&j{=-yI9^?caK~h26rcrV#8(XvBUu@94w0rJQ{H<m;Or#%{xrBS_REr zfwahRXI|Vg0z5ib0@HOq&SDUNnw*Wj?WfAKkd(Z=ayT}Ux)hlT1)v5RHc}fJu!xJr zN{0e?H@n(jnn667J|Ko8)(;S&aeXO7DqvuSVbZK@Jv8SL^V>2@;^!fsV~8nRs7CZ3 z_Nh5IIPj2`Mo_v+Q-1$)<aM&8HHw7^1$Lck<fKd60nNh0EA|tLl6|IDe>2&etdgy- zEsyQjNBt-oq98;uZ5n$;YHjkeYB{ax0G`wCexoF|^kFb17mSwP?Nk4=94%eT-Tm`E ziJ=<wq2<TVWakSaUKnj#*nsy2r_R}4=dEys)$G#~p<J_1bO#5&`V$@S1wPGI*ibxG z21%3`30>d&0hYXXe>5`K3m2Q_Y+w)=kO4Tdys_9+$c1+D%a$LAyD5$pUqp;;>Mlo( z0DFtRygineS!_O7wOi?+8{3^Es`*S3MHmezBL`LFD244!1^~SvB<z5{HekM_<lDK_ zQ|2Kp98!S8Y^B+0jcar<K5LjO&^<qFEJA&v6i2n?mt0h|hqR{NA}<fOIYL@WI?sCM z6*mMKhtduKT$Tw~B+Q<YJI-{~$_k<rT9eHFH9Un1nYHPKn!~SAg16!p&i67<$O+7q zJ;e3-_epXJv8A;7iw`FIj?|z=jd9<5T)TB8T?fq6xaJ%GWRlw$p0^g^(ak4-B6*gZ zDVKmd@_J6lk9kbZ!dHH<>po9s>`x6Bu3e2Uh3jbDq+mPJMB(U;m~digR?&VIwf?Fj z-gokaPDB_~XSv)IcR$cWUN<J^CdYOfRdBVIeVQrU+pvSw_%JpszR~fOl;i#b1N+dW z8WSI-L_>$9PmGL|8V&hj@~Q-5(ZHB>fl@xgv(gp6%&D$uH4W!JCg2jeI@~<;ZsXOo zv|sL|m6%@U5G}x^s_YrOkp*Vv+P}1yLOKRdHUWy~gK%FGqA5OBqWaQLhFT?1D&AKb z?;39~TH;B-1L80Pf1s>p3-jCM2HomqeRaC{#oW%n0+!(Apa-wzTc}z}YSkFIR&cD! zg$tWo0#1q#EMHXKERx<=fp)Q`<U#-}{{;-yEnMPqQ=qVQ7t|Q+#o4b*pZ%2bnQ1D` zq+0)T%!NZ|jAo&*nh2CbB`>y{%+WT@KT%TAa2{;|%Au))`3erP%Uxc>*$JP?PIgS0 z<sf`sdiN(3B36=Y6Z1mj%j3wIzU+yTDTmLp80fVHx`F`|%TXy`cBfKobj;_OK+n%J zU0SgFN!V-9m}Fb8BK?7gjwl!1zox!}5EHPxjrbUgkK!P1Jbyf9BUW<s#D1qIeZrif zNPL%$n{AK;i$z|;ZUO&*=S5ysG>rySAE@Kk8$b50D*-E(>xQa4Z;OTDHVd^*7Ed!& zPuD$f<ec5KxAhnn_*9ruumajcAO&ObVfuAQS1&AE71(R@)9oo=B5*=)_I$&oKm57} z9Nas}-}VQHM0AbLe?r%d(RojK0W$>w*Mq3Rn6BDvfrz;aTccJrXHT)zK$pZ4BC9Y# zHSTlSuyGzoDOCjBE4=nra{6bt8y><%dVS?`Cb=Y?v2HddZ6DP=`ZL&~c%{2yMEi3R zjvb#*^~PTJ%3TCyL08}3beXzRGOhO9|DTbJKl_OY4H7>%pyU1!ARJ`*P)<L+dU@}g zbqX-YBE*|ekZ35V=&B1Cy(nhKxE3e=au1uvk}M!nYc;N6VgQGof+re-3dKkM@-;B{ z@~OuRg#%miO6N`S0d0}gU8ibeZou;;T9A!@`~l9)*g7&3DT`|m>?f#ulu|$a%yDOe zKUB=n@r+M(I(r33fF`}8B5|DBNn}-u9bKch?&n(+{sc7SLepu_md%m4E7Vmsvk6rl zMB#hm979S?Y7)4_vI<39Iz)+#0$2}MW$^)Y&+@3>)yOnU4?x)jk{pX|mwK1NTts{g zcDr2d&b9;@lZbdA<(pZ>)_Xc_RLNpz(OT+!lB0icxcEM0{zWrHalWI10s|0wU;u|u zX+t<`6x9|k<Q!JyLoe>;KcHXR#`??#A3&Q@aFrb%wqO4=+OyjFKDo?J$I((aMZ^Sf zlafFf-5|%NG?%wXI5_w%(=tl30O}iYYA3z_psGvOT9W7yeZ(tFJt3DT^G*lTcY5U^ zB+i{FHpT|%68}<w-PvvOb*r8V>{b%6$oTu;sY<zOc7tsP=NcanN}NbcZ(&X9-(L6# z^j=N@Yd_8jMs`F-uT(bV2JWFf#^`(e0E_1yqh#cVUzAURe?)hPo>{tH2k6fq#qK?G zcdqI=o0us)RT+2t(kWU-{pLwLFN<m)n)i1~K4u=AS6B|O_I=NeMbF*g@M{>v=k*h* zZCLj#Yr|5~M#`m=Aj<XNVj6rSaNT;~5$C-BN0rXT+FBty*~7H<43#+Q8{|U*Xvkhv zp7E$pk5`D=eU|})Bh|&!kG%IRqKKY?Q@$gAT=hmHg_nC@i5lHU_m*TN!omD6KOA1* zu%RvKm={d8KfoDMT{2@H>p%T9_)6!v)!d<`;B!obvc#1|2hnUxoqxRzk7r%qK_xz7 zt21I{s8h&e)3}}%($5)wP`zmwQgnpcl;6c|M9NGe=y2&!yEM9xlQ=(*!C4PBge-J> z|D1NL;`VEl4;lBjpv6HFZtkzZaBi$5I~1Fh1*7l-FTdqpV}oMFj%p%DynL%qan~~Q zow4|<nfC@CxbMc(NJ9ss1f2B(6)oo?8el^QPD0_e_DUz(abUM%AhH6=cOHXQLREF* zSv};o6HfE8-*X=9vrCY?zg&;|cI+B;H9#jiTD+8Oz8a|dpyhmMBsB%Ptoay5SP#1e za_(z7Iy#wzlZUfbk2jAyJm%LWjF5+Iz>Z4|#zdLJjpx^Wc7QlDNBPMyjCf*lb~F)n zcJeEBePV20O3$VdhOpgqVx-xdDq$ws2*Aa~xvB3y%_AzF(-wJ?R+A+hM%ir4qcu@5 zzJ+Onm!$H-=0?@6cbCT}W=urgVudt>eok;-J#k*4P7oScqyK>9+8s5D!=jA0Lkl%} zHTNWgnFvWD#~A42*&-+rOMmzFHpK-tr7KCYffG|NUjsfO^j^qyqGz&!$5z$W&k%0K z$vKyhI+|Dp&l5v8&F&_EuU3r8Rx*#zpBZ|ajBP9$4W5vBgx**vAaap5Vcol~yyZhU z4~EDdp*aMlGJigJU5@dOB8dpOP2|PEVZC;m(2S)&>(m_M@BH8kH5b2=0+&M$)9pLK z#)L<rnAQTdM2^bk*<oqM;;6&^HIFOC^~gz-;G0+^@>~eMJLzBtg$l>!j*Gz7z3Ud- zDsxV4MtDr@*1y7e?4T&3m6cP~$D1{Sh#-e1qfYEyN&nS9*@FL>1%NDO;J)XH^;Kj! z$bI;Pif?;ge(?HZqd~DvwN&eX+kQqEXz}gi2`L7tI3fBCtYOnX&QrG9g!-Lt`6o-t z2s?W0Eag+J8i>bY_N){o&L%QW{1~7v`?*i!dy>3t&*Na|=*^8PBcpRs;K#_fnaLF* z<4r$za~zvx<AQNkb=M==8VPW|c^#faH7YeUw3{)WBWBG~k~_j^Ajuw{o}M}lZn7vP z)^}P1A{MIDyw*vHs#w5VIf?1bNZ_Gtt**rT*U>E!Mh|$5W_a2|ag?J~W;&?ius&cD z*i~7eJ1TK~a1-=M(|x4B>V{&g{v(CJm}rvd57CwfIG2x;mH{14AWT(!RRrPC#uUIu z3;gzfk`8R&;shSMCevDu0qKB9s<+<yI}VXUWq;?dlQp~Qi76Q@E}X1TQX`4b=|b87 zkC_VR3M<DzV_m3rpXe8;0$1DdPitL;!k4V|yG6U$qB9fngC4X#uEXHjtj->*&X}3z z5DeP-Z14NjAE3(%JoTSY4O&tAR5F`YptQ?h)ePb!NHlaF#?5!~lV7>3=rHJ@iwkhd zW4&G!(xeYzwIlrb(_84w8osywG`YKPHIiS==f)no9jZ&1dXgT14-$3ihc5rn__Djd z{f^&+4HI;+nQ^il!m;D;s(Z7{vN3Tg52z`<H6gC-4VMG6;}5<#JO85MHOmH6hrxa0 z$@B9qiSH$ThlAr^@FaV5XpcLq0}pU<$48O~yAgE$%#`}Cqc=(AEfeW=$Z)&RsE`-! z`@;P!=|tk1`}SQn8FF#}{m0FX_?FFW<86G3=l)jPVA1XNEvm|V?DsIlY>MErrgM-u z;QD#+gMakqG^J9aD@azqS2V~Dsal8uKlkFWN+(#LQQ@b6es=6XFwM^|GNlhNvr0Yr z5f#ow0pF$3pW)i#K5nDSpk27KMscpYijpG`K|^Lol2*_OX@=V9@B?9&!if^@8G4zj z{DX>WLj7gNG1yu-#szS+j4Wulr=qeL8b7|B)8wM+{ADRW*Hk8i3DGOxi>tNLDA*P< zEdbBXP_Wny9X~yx1mTtDjtiv}8K?P(8|il1K@~cPc4n$ph6*dn2r8%ST>B^1#v{uZ zJl)!lxEhuuOg>@yD@Y2tHnVR9=ExIRQ8EXJqw6ccFZx6BMgY?|=u6=fmLzCTj`>va zQfeN}Lm-lEkxWEw&8-J1ZJ~b!HuC9XTee3;H#c93GH*9-Z#2yZQ#_KrUU2I}yVuP3 z>oXjWbQFMoOL0)_^p!OB#SLL0I1YB6Yx6idU_4=YBd~Sbxy|GsosmT_t@q8%&Dftm z(1s6FX%<ynU8uthV&q(5Vp%fwvuhPjFJmkH?Qc0t5M$#){w!FU;vCdkBhQYqY$~O4 zV~IzBm7Hi4zSS9UF<%~88h$;|!M*dAd$1j(_mZKrIRZ8#FARe1e=(O>6M$Vl7ZTD! zpdb1)%6*{WB;SsIIv>|u)o_XkYP6p{yB8QSBY@gh;}1E-6InsNnmm3!`{KQ|d*R82 z(fpZ(L^<)!+m~_^51nRz>nPiQsLzMcXEav!|EZpF>Q_Z?p^Nmo_e!Rhm0<_dcbtQ_ z%ZhH#ysb;sd_L*Iye0FE3{892B$hWl%VNIvvA>Gw)OR=cohUmUUEPsTZHJMo3;ARG z9gDKU_)kE+fp>Q~`5*${|Eu<BqVQ=-e=YgJG|vgWW#Q_y5iE}H0s5GvM$A=r)#Er# zra77Xt;wY;U6#=!T&Uc|zv`c4DIiA@kfSAgNusy70XL1*zVC_^NPs2DA_|o3_+fzG z_#=$J4DLF6X1p(86$0b&Cv@nw@}YNffahcwt5g{enUy?0&I)(Ap)YHI33~_=I9F!# zaW{y`cQz4}fSfvQ8=ZQMr(E$*7`{bg(0%g>CMMy#hvg6Q^&<|j^I58`%?-MT)s2dV zANmnOt27jRzH*~_5L6CO4Qw=xO5;8|eG!l`&fZb{%4lc&if)7e59K+&z0%A_(W-HM z<#$bB?FEnFcEKR*ldv)VmF|uA3ndm5-4aahGHH#T;CC(RL__CTBa_hlq9ShC*>tw~ zWMQ(xt4-xSE32Fg2Q6wr>!f*sUS_gKKr(`uVSW`tI>Fs}&i{IZa1ah{E+*#tK6ZT$ zhzqFUqQhd#m_=4_tFapxlp8K&^jYLOv}~l@+>UxSu7Vdh0^GP;fh7NR!T8tx)C6Zr z!}PVtyr|>?2FbmSqV#$jz`BRKUtTkP*i}QxTQpN|i6Y+74S2LruS8F`%QoB^E0VR6 z*cwJ>)EFM1KV7vlYD3pyo>(7jb3C}k(aAlC;m*~@Lp$h@73Pw{RRHexi-t|p!!ElN zu#eiq3EL(F3^=3ASBvU#whivFpw?tvRHJcF6)-QARM`0T5Z7R<)g=PU9vachIXj(d zT+LY&1;S*&F|Kr&MV;A5%mdK-V6C;gHPW7QXE6d{SZgYA)7P`6uRoXT|39_zg5KS; z>~E+lDgEnN60l+td_-?qDle2ct!W!1_S_a_oM8Azk1Bu!{n{<V#lhj&DPi=fzKWz5 z1A#oXx30l@oTzu2{Pns<+-XTV{v<U|b}|UF5!n>W6PIf$T1A&yN}DS3#|rxP@tJ-( z)|F9jyPg=~%qB^vadhCuN~PlLGPW*qBR>^+R`7W|^}2e{BDWp$mR{!Et4)QltJ=tf z!60;2>09mWnq5crJ@5N*6viKV1m8S!ExGp^9St>=t~h7+x!IKV8<Ef2Mf9Gy_3frx z*~|B5gZNLLQrtYBa^V{5g%2TwSd82iFd=<Gr!jkUiI4P`nUiZDqcO=4L;jsK;afPE zc87@`0miVuDh*nCoL9gjvtuAQ<phFDChQXu_kSMne^rYtHW9P2Fj_{(>DMmmF&}0o zvn>i_buMYE2@WRkWLg@32f_P>1z77X!E-BP#4~3$^8#5byy1l_qrbvET^2WESMq*b z(k`5xDJP16*dt51XV&aas{4ei8hT5)Dg!Tz?V#(SsTkzoGcP)IJj4p_w;WzoN!v!& z?fakDa941gza5y*4uG_NpQ`seVFc2-h0D;uP_$7zlUr3&9V@^^hToSx9M+bS*d*j( zWu~hTA&liVwk7|YIfZZ~bR6|tpTT+4aWmm^wJgtOp~Af?m+3$McatE+U7_c2V3p7L z*FkE1;Qd-sC~3bVJyG$B)^4*H5B#6k{+9`nmJ>Y&IErg#QCzQwY)h9cm~At2Mgyu< zB=juK6XUD~1Z%(D5?4=;E$L<0&?p?2A}qKBvu1(yJ)E1y@}AQXFn9VhZ(_t=MCIP^ zj0o<lcWwj*0V|_}vJzjxmd`(mc6=fsNw@N>$vA1ZV848Zf1o?we6CzqLJq3#A>rx5 z>JxEE+xPI%nlPg+p=V*Fq}?Vu-TI>Bqa2hL@*<o*&iHK=<*Sn%cTlBNgvfRHf!j2L zNJ>VokK^!)z20`<wa8YJ)s9X?DQ%QUHY467{|dtFJ=ekZ_Iv&(e?21LIUv^`1Gm1- zenVKyU+t}}5EIb@oPg0eA;-I3g@7)0iTyvX{Vz|ajJKqk+UV&~nJO^;P{QSpZ4SF~ zW)a>;dVVK|hNXAR>sqZ#a=Wc7YftVu_Vt_6>ifRBk1~(D{&8;QQRSZ}aJF_aQVBo( zM6$p$%tMhZVnjFVMt>$Rp}AKZFHt*@tv|uBGaCRjv6DsXH@GSUew4J}>PnNJPcH<6 z13>SvD#ZjRgI4<Ah6m9tSC3iAXwx)``4`?#)!WQagOBwY!*e#L!8Hc^W%$R^*zA{% zb1R$0<VI7hB9+f0!rtEIv!-ZQK)-0l{omO7FXQF!&LS-w$I-Do`=jC@T!r^frbQeV z$<dMxGgtq#zu6urZa;(X%Pg$}s+#D8$}B&B$HPezHrtVP@n^G^5H=}JaopTM;K;ct z0)pALY^}Tmrbm}RW`}HGK<$&mJRu)IS%KJcpp6&~n5z7=x1lLI4K9<~R+_=h-hUt+ zYi5rXCwT21T8)KC$8}OuQ$NShaP$W+t+tFlYj3v`MCapzQ>nLCE9Q?+@s%Nywvm>w zajo(?c26vva67bwpzS!bKYk;~TKiCuTseSiz58ltttDV~b9gexVtoZ%RGpDG%j*A| z^?!ouzYLVWd#tTQ-UH#`jyEG^)<a_xTQdc?27D%;Tqf3yTC>)_3M!iu2-J?jnv3=) z{OH9TXF{7BItG?KB9;Q|6u4N~h!!eCTW?MKj3hP}abe4G7YCtCXW&^NrAUNFSZfdN zltHeTrqVZX8~X-@a&*WXIoFVD9uWtc-I;{%@$Px-4wCS)g${4X*7XZrb3R-onk=wL zH4qY+8akknpS{s2cnGqDi0%t~q;gzdq|j|+xhA(1`(imPKV&DtQkmkjl9MOGddYQp zs7E_^X1x+;QC+wNG#I>(h<snY{s$1!-=93%2^_qgU8RlZ!cmyMr?t-NPjLsSK>}HR zB3Jg+WAwaciQhfC&I=O{ZRmFUcepOOcXZ`*$0?^6E7>p82-BayNwD>*3Ka+E1fr*! zaLwq~kYjUav|^eOu1Sv=!VhX!W>S!wkC8_%`$9w9&K_xJAM1|VETm3W^^MFV>xsxa zt2fm5<tc6hch>B7tLyC;5oPJLMS8iSxV4+Y20*1<DOE#Trf1f-`~-bB^uCj?^RxsE z+1w#=qPp=IzLE90vK<@v+}gL03M^Lk`C`A2OGD-#H4K0MD21TJo134&y|F2<WYg+5 z6o3&Dg@zt5<K!}N_^X$N_VaP8M!zw=S)VjRoa@?2+|K4pl?M_usq5Bt1473obhUcr z{il@?FE?~swTto<=WgnsqQ2QfuS7sA<yP`_6A_nUUvf<BB(gTvMXVwyX0Q*(RS28P zKQFhtO5@%0N2_`qB}*YSiP}sb6k?I&k&}4k?v=R!L#FL{Xp|LPtG?W)=@VK;hF<<$ zu<JoIJY9D8m_k0CY1{yin{+eLE1}qxx`;>3<S<On31;g$u8D30RiM+bv1K^m7QOBj zLtDB&pEsue&lR}v0`n>O#}U4+DktmT2hQIms=Mzk+RCJ5G(3MU`XwDKIhA$M93enK zbHk_ix$WAvWNyO)Ilk_$HX=88W&en(Z~TmM<s`8v%(Ly|bi@h|!!GC8a5lsB%Y#`& zzvma|WwGZufVHa^9If;shDtypp~NJq2G}cSYaWAOnQ@+zKM^-*imqR=cVGE)Hj(fw zDvhMQl$&$g*VM%N+8$qi08+@@4G^fr8uT*UL2fdJGED&OZ)YbVMdccDiZb!2-%c+g zUGr?mL!q-u+^x+PiYkzYe#dKShDC>MZx39zst-&&z^U^5!OHjw9sMxiuYdlqUxx7! z5#05h?>*`Nhinx_{ON1@tR%|tVm})XSvrcwioI+j(W*I)y{@{~6T|I5;KM9vt?`IR z2+c60aIf|r9v45wl||Gld#_Um+VnlqX|EAjwBBaSY0fAl94(IKwz4Ey(UC5-)=FGO zuX-sQ@ICHGE+l>xG18rB%g&6zEg_tZJN=!Q8cy#3^h9};W5W)dGiPA)1)!mFQN=dV zd-;sJau}29T$&BmYUd5|icf-^X~4}l(aYPtQ0p~&c2}s5=#|k8WVoNTFbFin42KN` zgty<oj_a{H_9$Q|ZC;Naf%0LQO;$ATNBV7cR%UdT)gq4lu17WFRR=TeTg?9nxPMqq z{ZG^dV4&ZBP@Wbr{zw`-Fzsy%(P)>tn$w4*k{hYL(gjOxo{BKzVJ;{>QqB{SnPbjq zs>%)B&1)<bM|_645TrN^(+6%L8e%@u)|>7SBI$O^EPbq}2V912+&eBW&j}lkX7(C) z>vmH`&c8@v+0t*)#1DGyHzfrN6O0rNq|O@=_?&K?QwN+0fAH~OW-lU>zyQ&h6Q0Cu zsP}m?PHbFo&Mub#)rHK#ki#^^<&lR|sNCg;L%opd3yX``T;t#IK28BCylx*E430ls z{#g#mY$9opJLYo4g2zs(8eG1$>k$#2k?NREBs603IiHv>>A{kLvajH%D2sVw%tjPs z+-@Bz(~3+C!FOMX&YF2DxfX+~&fz!B0_}f7;AliwRD515Lp#*PC?gA?0A*l%_y9-L zk;fG|q4($B%wgH{lhF+|{Gs$gTI(Gh!j$TZ?ag;p_#)-7N9dLGRRmV3psku{tDzNp zDD?43%qdlNQQ!S9P>1O`IYPU{5d;-Sr+fs+u}?!j4sH+aAhsm#*y}ZR{ovV1wECeP z6i;*yEw=mEAkZm3zf-+G<YXD`k+@HvkTGYiC3qI}JEOIFCC->Kv$VlG_Kj2PkY@M+ zPf`2X*@p0=1&hpbo47L{dLuf8wzIWS!eZHa0i&2b^9&jEmfg-&ZC71Q&HqQu{&xky z-+T|kkFIRwX^Q?^%SgHZo1Ux$2hY%}Yo%*<O3stt83B(VOmU~Jr2YBBKiS-HSuZRq zpYQTCnehki0=b(krkq<0^>DIkIgj!8*|}hEX9}8Uj33?_A%iPSDL{wohrHDBG4zP7 z_Fb1nRz_|rjf}_i7bpUPEHKJ2HH0)5itN^ms5Wc+m7hJRvut-eVUX72!Wp|Dzo)fS z`SN{!Vu?|BAGZEug3V>F%joZNYd=CRRfn11hif9$DjuIKtKC0lJ7^6aME^qiO}dfF z=jwK7r*J<?EZe&}-+0l0+`yvo{XsHT?m1IY&X7sWnz-uOkIC;&Ax>*K<jG`s9}`nK z)>S1amYFW{w%2O#HYtQi%Mi3BRH5=@K4J?BoWkt;#GqjKV-pr@WhKUQH{5GE2UAS< zb=_%(7$>|+_Ca^a2v@U)pIuI#IfdTsdBa8W(HDs)Hua_A4zdw%G@&Clcoqo5e9ks% zt-Q}DJ*i-=wzi#lo&owMAy4EB!a;V;b5#3z^AJBje|G(3-p>6rw1s>paJb*B(VXkW zXILROHhX`?q2H~W=gE|rT=O|q5^TXFfRNUNqSP?FBX!^^v{yB1v!kOTP=H8KLf73@ zZs@i&v!UR*{$aA;B*(m*e%&*>WWIY}5_@qD@qGno0!Cg8ff<}nRI>?7xKTB`gsGcv zM*^n6!v0SAgOpcRvmZ9%+oS`*3`UT#tul$hVGnT?PhtNJ-;}*xgcV`x9|V>BB!x(2 zc0}!pXi6=ClC5*`@`DmvFlp)-3=K2NEPcYbZ`rR#`3=Jd7ZOTJ3`^T#{@-Uo&lhcn zHNzp5WpMRUgPP26$jNX<xDedfCDdbCd*}<)vF0_OEp!)}qf_zx+&k`+F13<`XdU4E z&R$F2gMa&*2>yT1oNyh?T;I2<tvU&^n10CTr5u^X(yuK2?me5vSkZj<4K7PV=E_In zb;?ijJ}Y1#B_C^=)M~4nwYL9g0pj@U>6Ynt>ddkHU)5wIuCjjfgE2~P`$u=cu%ic& zWGyx!P+}U$M<e?J8B^6m6ZVk2v;qF!fX^L2sg1!Cvl+5R0oJM$Zd@~Ahy0Q8eiS8Z z77WE4o9=!P+2^5U5$MKpM{c;UaN8T81xBn4?x@h@eeNl{5_k`_w#|>|q)8UKiI-y@ zTTx-wHJHiLRn@ZzuyzLbUZJ1byD>%#>(}jHkKW<_5jQ*G`+iP}V9KNrcgdkJ>XPBN z4u?!<BQ2k_!_jnWCgbYg_s~)${=x$7<xz4E4p&QCo2h!3HU&ACP&~Y>g<*L7A!+AC z?&iyCepJ4ox8;7xwfI~a9&OSjQQ}f~%z1RI>@L|5*zV?P8q|I32m8oidrQ5z5r1*B z318iK3p!GIw!<}%cgcj^E<z?>63jm~SXb^V7VxY@pJZ7AdQW+;tjA0>#UVUHn8=tL zi5HF`x4m?%<aMqIx;&ztCcMJtgtEVxPmR~G!p+C64{^^MHmWz#EF|X&dQse{s}m?_ zD?uB3x?vXOUX#szkhA=whvav))vDqpCFkmI%KoyE`iGv;f3m#=3WHtE66-D3eVmp; z62H|QzXZm+(@C^%l!|?_{9yAzv*aUrj4W|fwuY&zRlC?Hvrbo)7(ZB!th~ItPUXoi z4XI-kP+SBDy_~-C-Lzn`E$g2Z7)~KRvBFTFin(-|DwYuoZ`g_6%rI;G=o!k4Y>x=K z0Sb2nlx`Mg3#W^q3?2PtO{3v3dt6Rvgp`i!y>iz$reyhwUmHz+5)=XHpk1(|nSO0` zi`f~VfcG$qVx{|0>k4OZH}87`OaY=3n3(^@d#t9k7abpma#m6W7)PD)1_MC5ROj)z z+LJ5@m`@2HgPWP+@$59lW3NI$DxILSyy1%>y#P-F#+xPf5urexN$8z!{r}bnz!fkb zzBHGzv@*APQ(!c=@e1?x+@ruM80?#bhBV&zZU3fvSMikD_h)VmWOFz0hi}SXfBqx| zq4+<fy=PRDeY-Cx7!gFIsfY-n2_ga_NGDXK3Mwkn1q4KTuL(t@NN*w~M5KvG?_H20 zQUZitLN6iogaiT!=YD3+e&?ONX6-rqoR5CcW&2<Eb^YpFgUH#VUt`%6^F-T63NP74 zUwU#^t$BZpX_R)1G&y2^2AKE--m>8vbR9odM=MpV>N<;@BtOcIj4Hh#WY#*A2Jfx# ziyi3-vaqn|&Sk7Db4`r+YuuN8ar0$h``3n07aRB`UK2~2TAMBI>GvbE5!6keFL@j5 zXPbV!rF#Rza{jqXx8dPq2hK0go)wpxUG83@xFKVb18uf6@3X)5L7&%tvBCBsdv5sW zVRdz-=>5`J!(p~5u{T2T?xKpZ;?kO<nyq#*^nK>38xJCy;{=XD!pB`#I%H^|oi7{g z;t7{4_Jx85Hdw(264H$!FNk#FUh_1TA_y+A%%w{~etLd8okHW8>o2uDLsqiMi-uS# zzEhs7XrkYfffBz#u6y%7YcD6S)o%TI@0i`EaFHv;DwaRyD$-U(tLyGA+d#$S$>tl1 z<AW$*oy6D=1~k+ofF$;=<|<puGT*@KZ!J3N8x5~XE1lmu`)eF)!Cqyx`@SXBuj=|h zePpKFNXuxDUr@EC{_<FWc{@bE8GpMcv6l<ls{9xUB5E&bRrFly|KV0YKOHR_*}B$n zIYeJbHzf7kHmhhC&>XXx>W66y)W=bhUvhREJ+#hH(to>-L~a!~Dy<;v8gD5yz2%%m zE}5^jpgKIn%O~1-tuI~KQYn#8(oanaupUvWT7#`1w*!?fSy1}VAvzE&oexS6Qi&d2 zg@OA<hKGfIA8sQ}tJXTv{aP1NK6O=|LUT`JBodqsZcSR0q&{4V(7$^Ao8k{&G@=FC zax9TVXboH&|K;~51J22bInB3oqwb(FOZYm#DM-UHumTkei%9+`{us`(FVl>5Hfx+Q z+7RQ~_~sNq8g5s5?!0{7?ed8`Vp(Fat6rymu2Uld;A64k;X~em(|D9XtCymM*UOU| zK90zl+xvYttRh60j#HM?Duk*DIAJ};R|?{%<uYQ^(GTil*ttE+a~UhHK+W&dKVszU zc@rbm+F)w<kltzLejKCYorXxpKXLk;`=*=`kQ3D&a*a59F4AhAprZ?b7`UtrVdSve z9d<QFiw$mPgWb`GhJZ!%I?ynx@qY$pSa4D&nCAGaTz0vZc$H<dAeQ4n!&TM$9W&iL zu)%Bzv1BU@_L>n4)$L`3)O{G4UuB2XQf#@<&Ov?GI^A=AJW1-OiI|RN)ivtOaE&<j z)VMG1>V!Jy?TpZ@OBHPSyb6oqDY^?|Y-<cgz6UEp_V^8Pdmy(60~Ck6ObXj5pE6Y0 zDDjefgOnrY4Gvn`ZziH7+Y73pCw2$>u-b@MeLvg3m6V7)k#}z#7kcjaQS-^^<L6=F z{EXcqbiCX0CQ@m8B7YVV-rFIwGs#3%bvC*im$_GKKLxhh;69Jepv)G&DSvxp2e(JX z>GEmB>H=)3zT(`?h^tvSCxNFw9C{EtyOG0usA?h9h}{fCXSe0VIWC|5UG;09;&JE- z9%KB$IV;8p#Whf~55wpKN`*dRLLJ#<zCr}LM+wNtJaw}e`==;WQi}-ql#;@}b~y;E zrZ_W~wqUjgGJjw#OJ@;U$ptHil{J%99OEv3JnoD$JTy&edn%+=D;7EZW`OK4>`!=C zM%d(fkTY%ar<JNtw|o%Uon7s>{CJ?K9zifqAfBM`7>T@@4B~})U*3eC8DkSv1Q?p& z?KqRYoi0R70L2+q*%oGJTZvU5B*%X2>9T-NL`<YMxri$#-=^Nrk?rg6XMJ10_)Q); ze-Rv*Q0p@Dxp(aYp(Sgn?j;Op@Z-6xk#G4sJgVO;VL2dmv|VCAg8s_SiYF(|%QSmq zLf6kFuA4IbivJ=fQd8%%Lf(~S0}<N4Y|l1GK=C2jJokmS^J@tN&%7NfBx^PhgO&|R zF~2r*iSUx!ba=MhGP@r-c<Ps7qBC8fc+yH>!`<68TGE}!z99VhK0kzDA%rs@VhbWX z`Enl;%Pw!;nmH2isml7KmiM}zjz?D<E4W^aFKj<@k*`vN<;A3(!VGlU<Bf5k?d6Ky zx2eet)jr16h11i<28I)*_#SDru1U?fK7{<jV={4f@k@m@>dSC0N_RVVKf|t!kfiis zDs$E^sdaDS)s&9BkF!2dZKsWZeJax*8An3;aP0ZA@f=E`vFs93PsS9v06voN$O4Uc zquFtpqItSlRr4j6g{j)`*9zPRJ%C-McUW0Ep~1bGJKmpQ!_QQULKr7X0)(Ljhk>X2 zf*Hud&?=!=PI-Y?PHFSidP$$1+0(2QB;B#A6-YdsG;6aJoe)Q;t=^jbm=#=ZJ|Sx6 zXu-Ncb#ZY~<FB>AP9{LNbM-Bq|2|Y`zGiN%F(cP?v2x)hxVE}P4J<yKzjAQnw$n*% zT;mU1jo4b`LVPsEU17<c$A+WF$B4`0w9;km!`Jwsf;c$VJl9Kst?1SlnT-%5wpY5L zQB!Gx8chn8`qx#VMiGrp!xyj4j6B|&=b*8el{_D*Hx;owjo6Or5;_kkDF9iLcw40y z^5cj{9jBAd)J16j041_V#%U=4@?-7wk?2XaSbP&dSM8DW#6#kKq2cU!zDwBuDNX^5 zCjq0nje#vEZI+GeQRKu3u%k@Qt_ALc?%R(twE^p;_^0PvcFp~4-n(G`<hi3?BRQ&g zifZd>3IleVOjah_n=2YT)(SpGU;kt}1K(-H4u-oC3voZIklMI4F8FxqiM4Tq)hgwS z?VLTTAm0N?))T;%u!(z*{e9^L>5fMv3|e@HlyCNejK}F(#F9TdR4)pu)qT*sa-4an zbh>x`q46VJQlBVmj<2r(6ESK_n9HNqp6wYW<l?SQlh1Z(Rnyi;A8L|rdE_^vVv1I? z*QJwTaSfu?@KTrk_H^CICpPo%Rky@c_m0`jUo(AwbSM01t|q|He<d+u(-U*lUNd1+ zz!SCyL>(856~AH};gGd@+j#nE_mak+-4<S99kYAte+UWbKo+6J<&i?SH6y!E<x0}5 z@mhmG=I99uPz7S~kh0}a8@7UH){hH!bWg?pEY!TU&1Rt8pOsJ2gHQks(Wrs`WsE;& zWH&D=S-_@Js`EXl!(YH8TA4C4e`@>|>-Ax4ipwzQ>?YLdx_xtD#!x8BzEj@}cDLcA zRCmL+|ABS4?p)O)UYjb5jFISKL*Z^?#@!lz`wuOFKw4U~C#3aD9WA<f6>O1!2E#T& z!jD9a8ecfTe}>V{$tMX^A2-Ap2{hH!3c1;;8JEb8U2+qv-{ZZ_tgLOw+Z%p34L(E~ zmzX)7TvVzTMS5(TXOGc~@#-ahtx!5ju@;fBQIXrJXMN!2z4|xxBu1R*a~c+f!K3ta zmId{$b}Kf1QU{F>+CBE0rz6DhM9ES5-?_L9&^>M=4@4hxrLMm$WyMY|$LR=WdsY&( zg7j{2%YsOv#1AN%=@o}67Dm8yoQP<sggU_k8s4;1A1gpktkC4tWGBt)MbFCw!2ld% z+ZojV(5GyCTR+e|H$YwWiq>O(zJ1w0Xp%Y-1*A=8dhdkxC{-uiuUg5<x35m(ZEV*^ zT$9D*SFZos>r2w6?uh+VXU+!xv-guKJ;_9wQ}p3&Rr@OqUb@|OYvUSeZlrqCI<Y`& zyKJfDNU!Zo7S4DBmU-N>8o4z&(ovll(O|l^S&B3)GE=|pn-XKt!Q&H1e8xNOqXc70 z>mFQQt+|$Qay%A7L^*1Do$u_tO#OEhgJUQ)JLlBR{J{YG+oMKodXzJwGK>3-qL-Zt zc)owQw)32)b`KzBv;&Lwd5_!0z&iIU9t{c29MPa$5F0tmE7YXKO2%ozs`yBQt-^l) zj~O2yH<ISREhJm?)Z0&5?6pq_l8q&TUK^3^StTXl1)K}|bgd_z=B)^B1~?N-8b-z$ z_qE#2ZPXR13ff6K)RS22Jv|VxoN+PkkI-19)1_P%wTz;swueqm@D#KIJk>uVqF404 zO?E9{!_V;>u)?)~3|5RbBg8f6w~eXK_MuhSzBIO=+JQKT|3xN_Vc>4v>Gp%OezJ)< zj3Z@~yaA489%nR^2u}|-k;;&Eff+X+Wu1EO0(nDe5m&zJJ^1}hgA<M>Eob0Q>5;p2 z@qF<L51{MKHl$=yw(bLG^-cu0>iz}ZrDRE}5JlFgLm&JmVo~RrM9yp95Gr*m+F!&w z!=ZJbCjR=ZBM?A@Sc+C{v+OMv-(t<#<|s<sYMsr2`4mm<FQ6|uOD27Ra&boo0Xwkw z^KHX=tPkh_)yG;cC4R!J9~?M!ne0zHqQwS@OgB}ckLb;`Klwh@Iv2YV&f)ymgXRMR zb|U|p@T<`xGs>LsNcrM#iA2t%2b~Tqmfky)iCj>8q8#}nJ==9U+9h@6AFXGt0jMjO zoibDYgOfkQ)-|7ZbiYQFn+b$2mvM(+MRq&d)Lcg9%XdnuNnLCam%T`sc|DIBgqH3i z=%RCl%yfF*Tn>sFM#hfGHsp@CKTkX^yd^H;C3GB7*U2XMU~g7gb)psXP6q)!b@Sgc zj33J=0Q%kXJqC@wfx^(IpO0Sh_9QD;Ds@2QHaBunT7n{f=pOs+Ci><;4;RP_CWwW7 zI4;Fe+|AuwILvi<o%OP@`h)fK`DXhMe|8R|loiz29K<SKxuXA2n1o<Kt0b(8rc;Mq z31N$#A<5P~OGmU9dB^Ql$#hWQ7gSLpJR{DKnpy##Dr~Ol(o$m^RG49l%r1EwFERQ0 znB8i-rdOwHUHqg#lh$FPHGq6LF;ZOC+>G285TXkQ2|=tiw^Sy7Cr~W>j`Q&(hqB!& zv8%EwR{K_j*KVYbkimnh`SFp@K%<QHVg)ba+x-*+$i*zlUli_iJD`paGa*)58n70A zpi<fY?NK!91^j5F#P0K3T8P+De+kq%;=t_=NnUOmRhe&x<*=Oo9?i%lGop8AsL<;3 zrQ^F3WEG_K8i*Q;iePYZd}qL0(|SW~L!(E0!IAZM>(+0Wf<UUH$#|9MKJ$3!S>+Y- zjz=5RKn_y7(-RK3i|sDA18APp-y2hdx4laPTB{jfySkSzMM)%1cP(aq<P{hVSX#{t z;dDyg8`db#XXMy4B`klGFIdiv7Q=rJ$ekL*b+IkeTE`*e@m=Da;4@PIgqDlb&-5?h zgkgw*KlKB#2Ge!x>RRA^#T_Z@a#p)dP}r&)b!Y-D-GA^Bkc%M#P!rCHN=5i&gOJx| z6Sg#4u}By^JC+oL(eckzrmTJdOQ&!T<$(#AcY8rk^yC)UJjvhE34iX#V@#@G)Gl{n zmkdGEfzgJ>A+QD^7KWoPW3Q=^weJwP{1>P+wukY-Z<7q-hD>$A=-7k1WZ23vCV5=w zU<J$$v9lDv_1|TpTwinln$MCDdJ(qh%^dEhCY`tQ*!_2`^rv?PAW%!Ue_G@^5d5hR zzX_rMp8>JtA|5!2VUJ0Ax7pf{U?G*EbasdNJ5p=TtO<p5ZYojmR6gvAzMh{OCo525 zgzLcr1zX#7jDW@HxUZ7a<z*11VI3Q&d)1G`n^@?xEkLD`=SD7p-r@bZFc36>EL5hQ z2RM6tG(sr@ay_T{754-(OIF_cBAr6=erowp@eSgfNsxYc{EfuY38C}N>U)%vT|?>) z!5UFw@skICM)KDS9=f!o1F=q1awf?Qe)O^m)Jb<`s1_+SQFm_41CA4RHo_#y%OREN zdC-pzdw+@3;htN?Z{wD>&yG8(nDc#{=CiqAD~pY?u0eJK!*sOY#1qcB?JD|!UsHEH zVk>->>qV^!`*3zH1Wkp5qIN`BG*W`Up3wN6)J&LHX`A^~6Xxs-v(2~2ft9KjdP&?l z)B)($`N(?MRz**Nfu5qs%(Y&6SDEToTg~OlZAX2VPm+|RrHQ{kjjB+x+BX+rl2LgK z?9I<&jGG>B=f-6q^bDz=K}3`t1gREV12~ogva=I`oUB#;TberwD4x)D5NIIxNtA>F zE>pV1&`KF<)vgYwamD1PZQ_)pq=1#Yb)WK166rn<<UI1nOh0-zfrE5b`4{P3@9llM zRR43-^a=<}!0ZcdfIzpooA)|!+9O5=+1-!{*_=1+LWLW+xMU_7mHb}={G=t^jZ@F} zF%YrI2;#hth2F;WI`{Jx$vB|Vrnl`#_1lI0W8ARDZhj9q$SP>|g_l<8qU`M{Z4*9^ zICI!xDn2~>V#9p#Y#x$|pjnm_Xj~($xzk9@4*1c_9Pm(-;fmq6kyJx7xEtSoG>9G| z7;C0=NMC$#3<WeC0R8zv)DA)wB0E0{?T^=bfp4(bSe46n@?9uVoAaiY_vo~ja8{fi zZP@!T$#&R(&j2G%8tOt^08jp6w(Ad#J6?-hJj%9i*uG&Szl3s88s(fP9hEb{5-Wpd z00t`U8sl2DpzD1|xs987Fcm&8y&SvonJt9VdeTZz?v3bnytvrwv3q!)6dF4Do<hcb z8G>mHUrcU%%KF+-3@gH07UE^`!`4LmL=7wtXh})85HM`9@e|Qs<77a|-H?l&%=Q2R zl<)rQr1%BlRz7I2F7QF^J8_JRb2g2L8J<G@7p2=!Vs<7ePluAj>!gH)a)cOAVxuXh zoPS}vLq03ssZOK|C1!03H9tn5ioP7<VEN=SMA4?Ep8s>)!$daE1q+Z^FY>smzD39# zU-)XGl;~Lu@v^eJIfqWECE^P$`N9i(lLhmwZS|k<9md}*i#N?cV`Pjq_V=BX{x>#~ z;9$D4lI99i7na>?LWEYDs0%+o)@>7`ndyZb>ww`g3-y^}@iRE|nwU$V>uqV_{eg8s zmhh(dY(7EvrOlhC1-quOFkKgu6+CGo*Un&1w_SR8nMdPg9}99va-a5x2ykcl!1Qju z79KeTCXk`@g~$nh?k)6O>ijumW<O866mQ2B-b$b90!!ZV(%1XVdWNqp)`=?@=tuT@ z5DC3UT_zg_0){~(Ob;fl?dTDl0u<mKC=fOnPZ<?__XN57QFOHHqPMA3CKYkIW(q7~ zqRjTUl1{l2BY7VB2)X4wa|d<Tq5Y$2JFEmFzbjL#@`WC)2pNogOhxf?U#$ZBsgVXb zXGYW*6<<h4cw85IMct9rTsD36tTbRpTfR2)qG=)IZO=zJD$CIg@oOwH>TB)9ct6+O z13D0YoTqnQA;SNG(^RF6CPL$u_#>C>w)?yEe^wLFnOeN>TzaDf#Y&A+D@wfX8%Hr2 zn)<!;Qd$kWF62f{U6|x~m&)?{B!Fm*7hPNbG&7vmJ130yraZi;8D}?O7_~4Eb=AMb z<~<u7Wrt_atk%&e<0~tZ%!ND+r0mJH%RC!(@6jdNS;0SB{Fb}J1rzr!oB2=Wr>mpC z)nfr&xCc_nf_`AVR_hb*a0n|?Hs_L&2n$on<!?v<y+v+W`=F0N&6CWc$uX?;s~=Y+ zqgCiWkf@O;7r|)I5k-iMJU%~}^Q^l}k-W$lq}dj5_>zX8(;dg22}sP{=QtD%Nbx88 z#XVd)yKQG^*l~rsot<4HVcOy0L`rRQi&n3s*p9~%QlxG+V?8nXb9JHl30WyG&BCv% zlvr$<w;n{or%(Hs`RykBN=(-yL2x#j7!U|TTZ>tm;Zblw2FpQdK|x`VKQDC0^X_)f zT8NIpFPH^Rm+26fFM<gsT!IioS;(ogr@~`hQBq%ihEar!O-0G_%-}wt{a#+Zfk#Df zLCUSOzTi>by@5{H!|%dGS%{5a%s!cg`qrg({cUvxKe75-#Xqrb*Y%a0I=L+`D(l@; zj_4zemY9^HdS2GP^k53EW{{y2EuXIl>Txjudv!M`fM0qj<u4obWFH+>ixNyDv6Ek; z<De4ZBC4F=IDL+mXN~{!6v3Y7{<r5C{`igW*`TK}$^}(kkd4<r+n&RuDxHeQI%4&$ zQ_kJ5Y%w}qlQd;py>D~lX_)}uo&DgqVcv&z$-%$!ce_(aN?_C%zT(!1AkeUnQ>$CD z>(eKYr}>84J7`L^!9?V<ZF_V|+-RXil8-mBkh3LVMBe0NBzz8z0h{@2Z(?pB%(*;l zrpM%LHy(BU+kx~Si_d>8x%y@K@m$#JB$_P#p_v)@yx!cqq~_iXP?)WFyQXq|lL|Gp z_d0a_RMKXX`FQ()B<v~R=JSa^@MODg3<#{w2ZaIK<e*v82&Wv+;v1XAj;h0g9qW<l zI(1D*FbJecUWfZ+YvM$%0TaT@AXEXme_LC5atz++DM!_L+;W>+xllNAOS_Xv=maQ> zHuFCmn;$!di`^Sk!2Q(S3=g}Ko|%^*k|}L3f*i+ygSOl-modacVm<&g-iHz}g<f(e zC~==1g%(+85n7<_6&<bqL^^O`q+O$<Z7gG2Y4Y)4c}&J!zA;bwZ6aZ5Wb*j+r#I+e z?m<cuVH$hkS+eWBqe>_3*HcBTOk9B*?Txbc#_icXY?Fh())iqv;Y~XYxL_8h&qB|F zf%lpJK|N&pqzC9rzAO0QvH>+Ub{2?fo6DM2NuqX`x~=Q`8;VGxmPrjpoh!F!@n22o zrJ69seHiVJVws!PpAAs79?&jdpd>f{uCfli74J@Pyv@CloftO4tNMrjqGov=5{SYr ztny;fXp`Z~qPP;7j*^1!Kck~<iU5p?TmUA2hbl+KiV8VolZJg8%Js~q%gr)KVg5~! zuen<4gqcr^UgU-*w%U$kyG)B;&J<P@N%<LpqSqXnJOhPYD7>dBcq{1n`!O9=#?gq0 zf6P~&<5PC)KsNR<?k5}GnCraW+#Nk7ZX?XF23QLrDKqtU<$I$2L0&Has-tygd?fXL zH5_~rM*VsA)ca675UMxlwGL13%#_!*I66fr*gt>&Yzf)4+iZ}oua)zBwe!>dvfzft znJAR9TWWaY+xlk{*cZeF#Y+D{(g>6|TMRWvf^FwC?(js}t+f!*V_5?Tu&aXetPDKM z%?JVwe|W9e;^<@cX_t-=m1XibDg{sBP=n26QF>PCv<&h1ra=Y`HqK4-x$133uq)79 zs<iA}oZ-beaU0fGyCGYua{}O%e9i_v5wa^A9^zo_Q>GpdH_j9Hz=y@5@Q-qh1mNOQ zVVvLK&X#tX!2Jpd<oVNn3Gz4D#;Ua_yPi!8^Tj;aiCu!uV(hZ0+&Iyyg?VWI3v{@r zei=o$(U^UaOt1zY6(W}!0%plJ@<^my3ZCIw4`g^z)%3yIlW_2INF3QfkeQ0Tz+rqD z`Lh|`U-xgqfg3kNWT7s3$7Gj+GqRn2VMMl{(32Z_l`6N7mD`45p0ae%-sX(?&JSJz zfokLr=?w~7aXy+r#;vCEyJdb5Ol#Q34z{?GS)I|PZ$om{V+n=%+!H-qLotpHmpIh1 zFc3B(PFUl)(lSzO(8bFaoA7<oTAduVgaV6Ga-scn4BtqQS8v^jN$#K)$75K)|MvWt zIIpd|@tnHD>`;)qygoNxP7Zp~FJVw;?rO-C&htE49Xf-&DZmZ%YiX)e0P+D>aH^^p z*)cFslD^gCw*0u|!fB0Mzd$5yKzI85^@@6Z{ug8h`Q$&uNN#z^{^MgW>?2L*gy8!? zT647~2#bcG6-wJuv6~YnC+<c5O@I261@v@9{0)fVhggoJjA&4pPD=35VFMkl?ySp4 zWS(Qo01QY!#vIeoU64IqJjFfIUE4l}9=BFUUp*yZ%ktCANlu(Jc9*P^M1C!7`^-NH zP%m(~?%f>1b#SD|oE+g_e43wTnk2r#D)?2u>|w+&c~ch~grrU7p9L(cN-Zn+*UXBa zhrA$n^{4x@sjN&pMVTC&ddly{xlGdZm3>Qd&`BPj3osJ4E7F+Xd}~hI@^ugOlw~yN zXsg!mP^l0<8OZN6HUR`;oxYODlc6YvE&8>;q)#UUE$HNK`?K<0p8L7yKZH(x-t>4T z%O0j4HWNfZ^;eba<tCw&_SAS)^ms$6o;^_>qN7zym}e6+`X=3^Z@3hycQrVrOp~cn zUj3h#P!s=^MG}fTQYpY&2)OPN*v#LZhM%GI<V6ND<)xjH%ZTd6K|rJ1M;<KKy)1~^ z@)PM*al#PXXKwg@yY*Bh{Ya-4>m&8uUZT^22&IcsyyK<Vc9IlaZfUj*N^M6v>}Qc6 z)c9(Q#+rfZCswIVqG4k2SM`hAIAGBCUz5@RLtmgd0uHi6G=66b5&CXG3u106z7l+1 zeZ}vSYWM5H$gSrO#^iYq+D;Gp{1`7kmdO{l?pZNl`o#KzMiakLv1@!dg-X<)+tBs7 zD^zR}P;_t7;^cz^&eZq%ZZj^f+Dlk$8GMgFN*69?1}6ic`ymD>e`Npp)ZXmd+aCap zwLT7<KUu6pzM}6}Q!W(dT`0^-Li>^rtF2Z)O)v7y)KT^#<Z`U_^?n?`pn#t}e^jz} z&m21T(tcz`%WorDAEHA<`{-{Dlisg3I+XRP+du@#vXt8ZU;0(nY2*=gsM163Ek1=8 zd&Tx@$Oj1<!vr;r-W!dh?1kzPjWhVD3!lBVKd@B5mxt{*yP49C9=(&N0hW8tctBBp z@zgI4Zvr?cj@-fd(1z;lb>OG&1Nwgv<MZUzqc}@AS=7z-4oHdc(mVx<TJOr~;XN1i zNVU=K!~MAXJ6$FdkU5L-+&HBk;upX^v7GC`#EEE-Ic~QmXhpT?^a#}{>T6?vWUQ}1 z${6K0J0GWoQTG^nJ-vl5C$75vWo|40+>8KdLhTy%uhl_~&y}!)D2(NpD9og+n%QSP zKYHww;FxfLxhT8;)%_AMpl)8CD5Cw1r>7O<Il2l;VwCf&+3)))8uv4KQ<*wc6{jOM zKZ_Hh&6lI2Z6VpTM1O+$0WhcP&EcOx)kU|?x|PtLyY|{hikpK!F?pwY2epG|o0sQ% z0{41hthoO<hwU2Q|G%E<KkYaX*Qj59tD#8sXO0t(L18WY+?P3|?wRq0-gEiBvpldx zn(+z<(D)4sJI2Lp)29Y2S9Wl<h;xNZqVMv0My%l*|CGjR;x)MZ-ZlaerV_Gg(l%@^ z9Xm*|<qvx;mTK0j5-tpFK%26AGZ!<FXO~TEn^ns!NHBuyBKvh-DG1<QK2|6^NFzT1 zCcykwmHt4qdW@5a(pcsISfr`ni$$=s`C#*|A7_*IT=G0+ZGt_*_yfKA{p`TbtBIZg zxcM`$H=#?_D|Ljrs9()aGqtDVIAi(gvm@}?Bbbg-6gZ*kQ5$knWpkdp6u1QxOzgVp zXe|Kq7?2D$@~vzAZKb$`{n$;Q-{G^q*LQels{prYL0z6cP&MP_(LqHt3h3+f(p-Hs zatZp#otnsb<>SY7sYuWA|HuNM?vV5Ke80OhU89Ec`}JGxbDF8U{Y^z%$3)Gq{A@dx z4$=BR=@(T<^2I>~tRpk2>4zX^0thuco{jc*c;dg`HO64Q<3LSa&lz;;)}eA@!m$cu zoL%K17llJyT32n|bd24pJ2`plb|<eO{mTQ5=x9G6CYGu%AznX&zM87y@I_-0W6&qc zugl-4kO*~ca3waG;V|;Iv_ouF&QahH;g4^^jdJ(ff<~i=Z*O9z?D*#rWDaL>NCp}` z5f&Zi`o-=*e^Bp*z$@v>NSF|?)FMw@8uVJfr=s-b72*Dy_La;<7R02Ly!lgtbj^FY zUe&_(JM5PQ#DIU9Z()(fKvlCUi9&2ete?y7-^LVXzxRE95s7J-Kh~pU!4_ICjuavo zvg#i=O^@OUGrOaW$ZarXPXibL#wJoOy84QTo^W)coZs4WXf_e!_b8)=i10t4+a}j| zH5!__z1-Zo_1W8lIuvqpF?&&NOby*mC$%o7sH0K40tz#`8|`xQ{OtR8uOp9Foqrb= z#Jjk={_Oo3oVM*o8m<^6G(9mQ<^AaH8I+4L=xOsRl7}>VYywt2PQ=J|r9LUzW#pr% zQ`x+i*D7S|wcv8h)Mr?aSiF3kmy-qn%NpyCooCIub;<I;=Kfzu3$3>2>ll~X?RQOO zfqbK8*N9c`w(d|dB1HEGzI0VoJSwkf@v7+Q_Q;W3`0=U>)<@uHtbY>4)aNE-FAsqY zTepr1ImHJ}yc`JS^e2QU&3Ju>7}C)yMT0;*%>USI|F6fpbs@xN#zhC{l1f9(D;#7> z7682UUqP;`g4{7fTD1H;F{6(#D8_JMsvH9&8h$QU;MKk&hc1CYu-<)XXsZg}F@j}u zAycl+F==+b#G*2QlsS@>TUfB4D?gIGGbcwXJzC_1KLmT`2fc24c(?(MMx)0w<CMG~ zH@XjtV|t6uoCxgy;k^7$)8fAvFIR#<t&xBym^|0lmI<^LQ2p5+0ODOm<_J}!f7UP= zolXbz%G`{gUIE2??ps@c+G+UDGY#f^!=K-SW~2%)n0oGa$%zC@clW(=^X-yaIjoJV zt#<oObDL4Y(C55>5Y=MSJlVMxyCb4^^A6hAoM-4|<T_KVv~x!f&I>}2rm|$}=1q}) zNGz29ELMi2KPGl(I=^~;0mtIkQgpk<K?E7e)NGF{kR$IxcLTJaZrn?f#@C&|O4>fI z&{=9Mbr9e)C@4`90$)I$4I>K8%z*rdP>4EpBxc)~Sn!0y%fGYAYrpk72(;!ucQ}FN zx~@gdbmnu%Zz+T(><oB=^{)f04^sHT@@dJ6SqD##!vDTz`n;&|E9njkqwYE4H|YBd zh2qL`Fe1F}(PYpxFfF3lM6^+M1KM*<^j5M)oU`$kaz@sNn>nmZk1vC>TZ0A|4-_qx zu(q4*OlN8p4Qw3J&hKt`5VoK|O;O^SSHF0V?X3qc>NwJVe9-J319`rQ6rla>Msl+4 zPQAymVMg#%V)H8kZ6KQn4}#E6nNlCo{b1*10YDxA{o(mnsBjH=0sRA^KgcBg*hni~ zM~#{}>e<%Em&G>)xo=pr6#0JkS1&m0)u)s$LYvky91M~Pevo}te|`~e**F4y@0%u{ z-RC2HWG{k_mvOf#)R`cxmkik*7gAZp&<K9c@?Fxxc)|nQAwlL*Ob!#JB{;8Hx1Lp` z#oFJhp&tff=%FZKVZ)LiC{86y)y5^@T;f`+vPaq8W>H8FXXGed$$4bI*3XVnA{Vw5 zRpl&4D3PAQ){YYVaIq7Iw?+j~3FkWK=oJrQ@5fJAoP8)SooHDIrAPVRR$E2Fpy4<L zjyA{B3$R7?4Eolp1W=erV=XqcuLS<3F6xu%h^X^Bapy{<#=Rf*xxZKCz>jIYyDp-F zEv7fD7=vagci4XmddC&LAFmU`FZj#1>YU_Nmyn-MmmNmgD2Z}fsC@t-XluuXW|lMi zS~(5P#u{WG*4eqs-+YvpqBs-Wy1pw^xX&efV#KxSql>Nui>u6YH%KZ2>*7`s$Ndv2 z&6__$SC2OMveU56);fWmZk!QPuv@I~oXza$<;GY@MLpBRoWS)c2HL|)_<DG}o*C+& zTnl&Do6G;AYN$hUnCtgYZF)g|JuWCd;dxCUbjS6nw(^Z45J(W50$k!$InSt7>DdoS z13G5~xfZYRv8G<+CN)Z&`RSG4!)_!VRi%d;EwrQ%b8FH^+s#>ff0GV%I79st;Fk6@ z<vV+a%B<bl(h@tR@R65h1m_enWH{9RZ*?!G02ikf4?b49-17a#zx|H>*W}(ZKbdZ* z$FX4!p8_WVHCtAoHfdZ-&^A;;e0s(hg(LvGvW^REcX&RJCsaE6%S>sTQF8F!c*euy z*yWn9Pf#=4X=c99VAcvQ%)6-hhRjD>5uNi>Q`vMgu}K#n@EEyFuRX!dHHYbkX9XtE zZJe6H+sX{BT;%fTXs@;L9x(!bK>)bT)_3`CHsLj4hKTBA`pP4oOuIj%##o>aIewdP z_Y2w+Cn6j2wJCaqL8hQXS*q)FW~3A@j{;<K(tieHl}?5c0C>_-YS>H9M5T4QF*HMw z#)_<3*iut_@LIm<=+sKry-XJ{Q(J;*zqqM?YjOe<MlaTU|4D{qzNRFzRKS4{W0p5} zsP+DBR?a9hM4+;mAom7{dJzc;T&@9t!kf)1TmzMXSd)2eL3p#WOWg!)=emmN%4I!N zaD8hX2oz`vJsc}i3&=I`mQ8=m@3=HyWI)@vQkK}C-Qq$=OV1{%i#wD$g=`a-{8Hwd zb~I<|+H<(>v0)lAyjLVK4}}Q_)ns7>D$76XFAW5y3Q`StJ%hsiUlAWtEp{gBjo4i$ z#)b*7Fnuz3gzrs2FcA2AW#OD~H39Av@ikdT)GP%Tf98QkePGtZ0J+3Z0CAsIlON@- z%f5yn@JFdi0)>^x39Ygzo%xm6%K?|i2%cS{%0lnQWV4Nd|I&UB79R&8ZFsJ++tKB& z;e}&e(9I2c5vZ$iN{b-)Rn-yt7dhkj!5NoA!R+ruK;fqecl3B7ZlS2=awmOZBR5Wq z@A2h6#2jF)Yb(a-_mn7|N+?=yHLd+qn<7W1fMFJeKH+)@8AAOsZk_!D|F+}nHc`bH z?kLCMZ(a7?{prW-*lX=kC|wzbrM`r}bhOfU$7#&ug~jQvpgzS9PbZ0!EbZNfz2}@9 z`!S+3zkjcNfRD6R<isH=T_%K>>q_(y%g;34c`&0+eKtFBSqfm%o_$cQNZEi_k&T(- zkcXDicI6}^w(M~C%aK>hc<Yt}VpB%`YDd^s-`8QOH=SR%`=pa#V&NCmnx$z|1h5je zIbe=3*yifd4&QaJo)-@%hHpb!nWy70o#&?`mz!e6Iw6W_2e+Dy05NKp6y78PVkOhc z$~c<(@%ZcV(IoHWWz<76;LKtMWT{&J0y*zXQnSJEyCW9pV{LzYmr{W^Klcji$|vAU zbC*4YKWw(p;%XqZs-E(YQm5w~=62vd-;d`z27#aw<4VeVPcrz!?vb1aq_?sHzgk@J zANvY<znLNl$TK9}w_e`{Z`^4qEh%bq2$)7y$+x*J?9Ky$Yk@ui6rNU{Gp2n?9NKfG zUkH=o5eHx&O2snqy#HNe=7OunLbSH>m;081ji*h9D{bN*sOT;zk*D-=_7`k)0dllo z0{OSof`wWpHkg(5fxXGwBcNO*a?j*UYNv>w`(6`w@>4%{X9UH&L@CX%mzXK#JZjR0 z5R3ThMcd0};a;@my`D^?smv`9Bu_NioxzWvcqe8^GcGPG>nWdG*ZmBbC*i;4M#O^l zad@EcW^`b;slyS-TOtKCqrVOIGLN*8Ye~s`kK?)Ez|ry}g;iSJYHc;dYH@AlLL?I2 z5eEvp2s~)`SEZ{$z7soh>0gl?BbKb?J6GWK<yz{i>j-GAv$Mr09W6*srIU=(Q*7b> z6TMvSgdNBKI)CUAG!Kjq8#dDf0lkcrMwuvOej7by?%g-R<F7}fA)DvFnWSow__>46 z?$4Et2^;1C6!OEbc{c-2fkFYUQEBULeDzz5k9#P+x;G2mv@ubHYH_Oyi2Yh0WToTy z@tsh$vs}vA7{TD`Is_~;GA4yF{qmdNpHr(k_#Y)k07}=ucZOr`y|U|hez^7Zx7YQQ zkAAQ+y+;@(dC+9PWJ#^Ii|~C#lm!L{D<BcM7R5Iw7ZR$@0PGjU&}@dC3odQ*CcJbv zkZj#qD~ZY9^Ui?6&Ac56#;;-xD@l_6_{r0To@nK0l*|I|PEjZbwB3YE3I4UNUXpbJ z_xMM7n<|r!)CS1i78@P^rQRNgu@L}!O}#E=o;1}Q4>{2E2kOhPo`VX@{gM_@m;A~$ zj~65s$Uxv+oBvjYoSEKoJ%z;KX&lSaTK)LB#E~vvLk#GSUcEhk;J9m?dKDfKurn1d zC=Ot6cLuWM>%K%}Rrjs~;^sm@g#VAh)uO`ej5t|B{ieiYYU=9s$4GbhzKVB(f;T!z zLYB(1s&uZAcJO?(a<4mFKl3!|cW{_=ZKmN9I`B-EW8haEy4+|vYl5ZH`0!K0qbMd; z#Oe_~7qDt^k|I^^S^Xk<2gVl($3NqZnPKz-f$^3fz;#7w7dS=7<F70o9q~dS_3wU5 zXxxgBvyRgzf9;IB(oF|ZU>2hZ8pYT#1BPK@$Gek`2(g!do@9z~`Dkfvc)eb<uVO>( zVtcswlJUf^MnvslpWI~1NrTGlXk`$#SbkpF<y_C5`4^td@z03OEd`ZVfL|MPG|BjX zCuE=p_XYpO^D1)#Bcu;~CXGSN9}+R^ZDyI>)c}X-O05cER_VP6_%roxb6z%p3j=eX z?ZEr622+=F8cqW>6m50G&eXPfV4J)VFzSi6-z#9b$4_ph#mVf?6j^V9Yz}mq43&g^ zge>a<GGUIdSX7CF)tDCj5v68ADa>z3i;iUDP#Aaj)YZ^J?l_Fy9-}3JDg&bHHZpJi zcL9%EwzPo&NpKH0jV<kSxg2rhk`P6Z;ZMDu@*N;HXHuIw6fGr6eb;5#qR!a~w(Kk7 z$j_bC=4dqCQY`N!<Oak|eNQ+AXvK8_MnGr~S)K6F?>uCJ`#G-lX!15V>)X?VXY%^f zv9#O8uS#_R?NWgrxfz#sdz^+Uqwc%fSQD^R)c`Wh%gl4glB{z)9eA!gpE~dADgObM zE$@Ph0C!P;7@-7whUS*`RTiAa`N>kp1H2U26df)9i@>v!dF1O#!8#bhsIiS|9|kP) zqEFrb0)hwEkqbn-AkDv>Wdbo9Pw;R!Cx$H^k^wn=ci$+ey;rc%&>ZSDRKou7{foxU zAH^P4x^*np+y)0y#1`g>?Kgz2DNL5f=NEd^LOVT;b!ctjl+*huZ>rv6p5GpJC21J= zFJ8E<{qxuwF1K>jfLpg)l38J95#~Bs6}y=<!uIJhtY2Ki?!hUiPhbrl?busH#`?7- zonnX}_Ya?~RiilsD2!EKuA$z=3_yGzd>Yz<2Y-Egb^BwEUge!6g|&5Zchw9UeKg88 zYyOS@`>-|e?kQLO5P6sKj7-4<`a+Sw0=wXV7s5dM*)!^ndo6D~^&$BmKw*N2z;CZa zI0LrC?H4<`((mDc=bp!?bgMZ?{B^Zv=h>78@V^mHj~d5M6(aI9f++9cZLe;x%=)54 zNVBu>WdEc7dr6+tDL;qP^u3BCp7$^Y;d8V4+oP@_AvjOtCTBDF^io$e>Zg&%4?*$Z z_JG}%+~gaZ6EzDd1|x1gTo$v!z!4dUlkFv@iy6x}Sx=2rxjfBcXq2I%qItEyXfir5 zZ~NSo_BMDe#%;KJP!(KNh?K(fOin2|;p?~P&1-u&f9Eeh{bt9Z?Rk%&g>V|OgiOl% zh1PnReRlee(#O1>l*x9wgITYvN4m`sNIzY`wKKbww>;Zog=uI|$@ozFrntK+eqkJM zIkd$>8_M5IXMuvb2$AcU8+h?oG#ziIq@Apu^8$$$`>RJW%Sev6BS12e-{_8TQoJ~A zTHP?~eamb0;j^U)ayBb@(yw&;M{W<m{RmBHd>6+W>X#g`8(ICQAy9jY#UppgYX12A zLwiSnu+~$&VWg$Gu=3#w`5@=a<6HZmxX+Tc$!;yF!4}${n0cUS@?sV&cm=GEH)}Lf z`YDZJi})O8X@68NZr=>cx#8AnN@f|T^N;&78vhVVg3aY3(!5A2XFJFdja_FgK-_2E z)_Jw?_SW-*c0KYka<rFk<US{Z&v;#dFx6sEzuS_|e;t7FAK=Qr(Atn+i}AnM(u2$2 z?SJ!3(UaNOjrcW_1v~HwG9*gvxl^mUQLDC5vP;^0u)9-CZ4;$X;Sw$YV_{(e_<)>D zX?LvC!trV#$>a!4+xt@0<HJgb*aNDNwsE!bZKjGF4*=QW8BfdUh>jP>%Fn975tGq) zAjM3563Dj?Xgs5wY~lgYL73-3r~wUg0S`zy(D@n-ocHez@bVc)r$*ecC654sR_3u~ zLh!Gw(qqa)`_Au)FHqz9N>7M$K}`R!o0dy?QM|syx2k7c+l=UUZDP+ASozN-fO0_~ zOFw{gj(Y8!?XtLf&?kx#qK?1pPA9nBo#`@Icmtmh%nf_wrW7tvIzvS#Ju&a9CQu%& z2j4ay65@(wdFfcy222}kW$>aCC0>!x7fwgp981}-P7VIr;yKCBJ*rTqpdSH*Zggr> ztNOU;UAl9pMtzzH3d>r_S>YitX@RmX4WWXCO`a%k@T%ByQ?*Bl%_5Na%L)`<vKA=X zOSKF5m>*n!<I>XNXYf0jI!>Na?@2JC$B|(RApkzRe$OZg;IE9}d=wez%3=ig;Ck`r zKp4<5Eb?fHrEqY=Z;5L!W(%{c<AZk7cv)x4o)WzGlZ9!#RG4v{WCbnzQUnSMWcfgV z6oxk!15<(n;Ep|Z>zCsvFe3bkA)M8#VnC+DiF>=xb#z`Zhv)X65c<2<lNW$E9lEk< zQy28O-rRCbx{s6m(YydDAcpbYX5i2Iyd9XMy@xEIwX_zM-lu=?T3iW;5uQmub3W_Z z2<9TKh0UOGc?h|*iKw`SwV%<jc;Lt5Psdl!kM9dHd(N#N^&bZVIdhXCm-j7|XsG^) zkX6mRQ0^;s6FLKYoKK3Z4O<%~c?neI1WWmDPK3C{<X0E)xLp=(y48L%ZTmYaVlumN zSz-sa+1g7`>y^pu^H1R-HviPXMEf<AzRxx+)CK}kB!G1_>0jLGn|GkkPRB~X;*T>X z9qVwQHnM`B${s484LwjT1jq0nD<7_XCU_qB%|BTd)Yn%;w4_Ou1@gx_VaD7X|Ki7e ztXLRRR<gqxcQt?a#OVF*)_)}nsbK(T1MEe7_Sc|h%#hFfRwtdrdCAn<aD1PN62M+G zc~W-_R(thL<GY1}H02NDrB7KZOr~)BVBMQa_nvUgeTHDbp9hD8Xyf(cL18(&?_>U- zr}@8xAGrGR>^&0T?$45y5NTSV7N1Rd!ToLXpBl}(!((>>fwLSy;<ZxMXM_*ltLTco zb30Lek2YcXF!9nvt|6zU1R$cCaf6@n{V3$<k9<~r1#!6hUwcxMf*`kKJ`oKSR3sEz zjA2Af>+cU_C>F|4@w8pI)tHUeEY15Ex<@(GQI^5=SB>mz|9r<{e`e6~k&HgsWECTv zfIzfpMc}X4^_3Rwk-}p7xt{ASW^JtQH9K8%K66HP1h$}ki-NN~Fr~5d?2~Y*?(gu} zKZVwN#@>-LC+^hLaiz_he<f}4GGp96b$6&1;;O9$71p~S1Q00jU?7o9Oi}@mOYZQ) z0es}-W3n)J4V#J0nV$0GE+{O6m8tsB^OC9#MBH|U;AG!LkBsik9sHE=#hqkdSXhLL zyIND|yEgIDDA^p=07=KBT%bR&qx1aQBEYR{NUbW?`+)a47H1!zr|dh)Q+)g6s36mM z5CK<YI@2OO2S;5ef76-w(jZHOR<JT<9O^0(w|F%FVN!d*KB{`Hn?GiSv(uoy)x{37 zLx0OH;h1KRK>($H(y0FZuULs#(03V~Ug+901NU?Vq>Q=<iHXQo(ou%pm_~cYG$2OE zaY&gZ7&c>K@U<+2(lUGpepwkV-czoG{k$IA=FY*1AJ8G*a>T-V65e}V$&QD<3DE3p zXZ$DuWG)1R;$>-|t*`GbeDOq5Gdq?b>s4~VD#);)6L+OXe1oTBTB{q-^t^0s*8;>d z0zRrl<)^~gYye$&bdaH7u{2o*q;wk1LxhHV0P$2GppH?f+9b@8zFzq^Xe)>LbuA`H zC&+Ie3utpv9<Q=8YAOun{|rq85VzrimGkL!F<A+eskSB^7pfbXkduXN&$F{*eS?`E zj*)6DKGZ0?Mjo9(L4KlvZ9(l|qPFBal+xzL%6alr3x4)JC*uwm4gfTNUZ~%uTu4EW z&Q}RL&Eq5RYh@OCb7rL5I!YBj4(}phDlS;ZCx!hS$q@8(Dr5(oJt#x@gFlKnW5@pM z;s5K4cyx)`cYV7K1&HKR(8joeID3ku(;O*1E}Sd7JBBm4fK%4Y<+1!jPA`1LG3|Dl zYX-C2e{r2J+*e+R)>RHxhW3@ztp!EAe??Y0+n$H5($NCi0_`+Ye|r_lHJ1h6n`(I< zn=|GirRq^qiLNt;<0k_g(go{>G$dnL0E=C-CC9d9+#1SBW~hA_*mpDwFmg%xI*-20 zCm&9f9$WiUKC-<pOb~6{_$KK*3rcitDt0-tW3X5Ug#kj{f<Cb(Q{p!z=xG!S(@smF z^V|s#p1t_dekn{#mhRVEdp(ul1qQvLo6(h`VXk63*IX>u@gD$O?+zL0u)dWyIW?6| z$qYKMC=5C=3`(WLuC@cZOleMWuMG5HDO-HBRxi2-xj9yRGikoB)-K!4R*qsa|5xjV zyw8qq-|lO3uF~Q&A%5<J`=I%&m9lhK$;~eeV$xr=#3sMZY=QfB;9!{5w0ua*o2o}h z0=@s|@s0E!sjT|I*`l&JUBdcOy?foG{p9v4tEuLtcc`{1MrcyklpP$t#`#bQnTX<> zo-qMXP;csvjS4?AfaB4AK!vqB6E}n?nV6X1b)!Ggt7vk3W(y~5s$W1;7$wq<n@LTE zH3biAbhPcV+#bs<g0^oT2e`Tja=%~&@H=UD>JGjDedUc(0q%{}BB$-p4ShbK6A8Hw z7#S?Y%B43#K@4`cvL!Pg1XX@l|1R-3sKS!|d7Iy4OpbM2&5v|E5-xR&aC5A1o4ZZ$ zGyLueB+*7$PhNyMKrJ0A^wZ)#GN{e~LbICT_!P3ZEyvm?3*0=r+E88W@`E+Vmcz3A z=Wv3>mhYL!#e0_(Z2WjiO_JR@#an(=a(a=V)<cDi9Oo_DcIw(HuXvp|;4<_fXheYn zU2~$dp*P-oz4ZDSFUlsD{o#ifY>Sn%GatGfFK1|!29u)c2rOS#?YT|n^BnL$#aye~ zANYSu4i`=t&Q$4WT?#bJr=Mp9e_i>Is4d4$6;f<a2*z(-4gF|1mj&BfKWl;YZj6a> zm)NhioIzrzN&Xqq4(~T_Nhv(6^C~EKWhN)2VsW+nAXkm@WP1L`n8tJJ<$<m`JOx7L z>#_sq#hafw`Jco)xUWf0lQ?;|7ue*;EOiU@QAJg4f-SiHovh%!ZB6AHr10+liOT&# zNK&7kUo|21^b_X;q*+5uycE_~dJRTWgbYxCIQL*ig_1}0sp}$;-p->IjLc}-IWqDG zsE=YuPb^1a9nTYF5P!hgoDU9cz<x^_7T8ESnE*_dpI4OLzGC?HFG}(M<I}n)`0=0h z_gn(-m2}Gxx3-04o&}LI+hp&tFagrm1Krc@>xp&xL1#OtdGyJn0c^y(dzH?a=)n2m z;m=Z>9iXtggG>dhnd%{{b@Q+4CV;%PEYUXn!Dw-t$h*6kR73M#!;+<k6Q|s5z;}v{ z_B_az`Q(Sz6^k~23mmFH95+#)-O&Vk1Kb)<vYQ;z-~<40{uV8&n~bmfB6>R=?~3?n z*Y;;7pfmLj?G~@}C(!VQI!Leho&B{CQ{oQ;(C(qbL_uott1B6OdA-RaBGPjyuu~r; zEie>6{I$YBPxc|F&+I-hOZB7p6MA_*l^Gu%)6q)U_G_|5yCR#p|0<D3Q6B;)q^>AX z<tQo=CdEdYNYcy3M)j`G<kr6A;@UXob3l>XGg$pMuWPqLCEZ5U;lFqSA5E^iSZ47r zB|{D*MjMFy*?pRqhx){lS?B-@ep+_GPQ!FjUe<ljDVr`WFo20Dk}HR+rhfzgObp@R zCqVUgXbHkouHTb+bds;RfqB_M9Z;Z!xV*)hq&Y3ioV$!;VT${U5Zba~VS<rRh;isz z#UGti&_nmpFSn3LF=7^y?zLjp4K<eYFip*`ZH6+t<56^qigW&hQ<>ZTn4t~)q!^bD zIPge?(_3dyR&W6B^P)Bgs7D)#0K;AvdJHDrw(m{@?rS?#74iyzWGqQKj61p|E&Rd8 zV*Lp+<kctuY0t!kmhFMUuD}W9fFWA?{c{el?eVU#90Q)cKV}gIu>h?tT9?+>ILc$7 zw$af|`eDn7ePC<i`O~mgXhJa#9KHM-Q!5I=2)2^tu6TF`c9-Wm&2t$T?(_&g=PGpK zI9>d`ulTraVi)4Lw_aI`AW+d=VSM$TZQ(*1`Q|;b48Zg7@F|}CR`*{kGt$svrC2<> zj3-lB><s~Ynpa>l!_UKtF1rRNGm?Vz)`m~ubk@6t!(0b&XQ5so@`4EniZw=v6LYN1 zNRd5bIS$_Z+_WG6^<7->V3G+UE9svVvoLYNj<<oNVL`BD{-U<RjZ*(iSo?<4j^^1? z*{+s#kG`(M8Eo|oiS|18_@%;b2%b6&&67j4&CyIltE*EL@mgtgAwG?~xOYeD>C-I+ zj!;e3d>?i7XV3gK{9S;9_zW75zC5=o+7PxAqycVn0g3>8%z@O=W7|Bdl7dPH)cYwJ zXkLm~wtl4zQa~k#nI`xgKQ-*vew8Dv>lhcq=n#0{Z8&rlBnDdMgE%~m%$jX_6z4c| zFT&gLvvoxLgPR4%sp}dqsi(spebh-$^5egI6qD86Gtd^XwEAm`wxQHfCEYC0RZfEb zC+Rm4t#YT~81n#!5`J*k*viU^UpfI>v&R!SQ1h_NS8ecQXY+PcAzirlvk9)2{AbGr z{{FoqUG(dH8sO&TVT+!bMs50g@A4mko8=#W7B$*ve{h6h(~Z=RR}HXwn4t1M2>Yt2 zwxX@w1P#Th;7)OOC%6=cBE^flyGwD`;toZMyBD{jh2XBmouD`8{C?%!u^x6__ZZo0 z&iUCyf9kM_=(wB6Ecv`mm^pT`>W#=~be{B@q}T37@B&#UVu0BLFk60_c3g5zoplL2 z;cS{#Kw1<}&mga(qz<E?);yt$<!aNB0z{|d1(n?G5+jEwjgunLLc&@sl%70HCt*V2 z@>R)vawDXvcou(PS&-xm;a_f6)I__`<nimWbz@!TIKF1Lzx2O#N}ku;oBX%uHZLK$ z74p-0`IDb)bWzM*+n{5MJji$bh0itEHA<r?6|}E}ti#3~FMlx%MQ<Zsg)BVmt^6w* zY}bDkuBP~HJ$3p&jpVDA*t9bE4!ilJPXTz`yY8Qi(>ac4B4T4x2{W6(A;ER34O)(I z>-`cQD@(1$nKr9+l6w;`vQ75u)F0)N6Ol>0)W4n!*O_n`{>yXzsswM>=RpAZn$1r~ zr$VhLbK;qk0gHSkJoeipCh;D+Kq=i>z9>WQ@8r_T7eg$=q}05<f_cYE*$0_EmpA;W z)c&MsbjF7r+Gq|y8jke6z&bXXz4x9iiMixJYwnC#yR^5Nkx<MI8gi=ip4R%l5$GaR zu>YHeXZ6p7k%c?}E+)p(BD#xBksx|@_U6`BheZnkAuWeZcsvRa0`iz56?w6a&gHJ$ zr)6iCYjZgaV*B{Z*;7Lsq44<TNJyy3IaaT2CDwW)<IxiDWad88g$o{w_obwz<m0E5 z#NbEFVV?C^^8{qXH(;{!VgQloN5ksShkRt8v;;w+<=G@b1sXj_Ruh(7%TtY*!=iFX zXe-);=JQJ?Y{B~%ZTT++5-66CrWl{sXOqR~8x5KiS`}3*NEy8Gg+u^JVhkG}Is_g_ zHs#RmekKqzecu7S+Rg2Lb&OO@iHnKh!sfVNLHHH#f3fvZSm;Th^UB$8B?(sg+Kw0N zX;Q}9YT9WP0B~p<-7kCW@K~37DNVLZZKtjsq`EzT?+tJP0YiNYp+z^9NN>PDzBJO? zC{(!u;Q)~`y;o_`*3!ZF9VGGwzv!^BQi0K143Tivo`*B0^4AD|nGpaHaU#(E756nc zJ9jm22|G}l1iXiXP&YFGj?eSkx&52-fIB<5wPv5mi|6F`*w_>llpm?3-Oj^(u5KVD zN@v3SE(d^i@=KGHvLqUVX+Q}7lpaw|=4`1YDrTXXAac9gX*{3vzL(M`W(L5o_rQDx zq(;OcN1}$Pk{GUa3a|6sUZ<RjX_2dr%1Y<U?LW4fr#96cl{96HqaRg}FqbUb_05I@ zhKHO}Ih067Daz#MleCn!T1QRsF>@G5>q2QiLA6Rx)MKNLbYBG_-1JFh&AR5q%O1H$ z_lvQf^X3`qS|x}@oa%@w)8!_gF_3@2o9eS9DrWh7iLD$FfNGc2(Pm1$l-rcpd@A(Y z`^>$}q4c#gHf}e=oKM!2fi+-vhmtN%?Ze|fuhyU!iA@FFQ2uiT(d{oUCWzw^UwJfI zPLk44zZ1^m4F9bXi4>TY+kA7<z~gl@#Oad;{C^z`bj~$S^-#qnLjVZ22cGS(D3xC) z<wYP420)B<!kWj5zBAWDvg!G%V*F{#wRJmP>AV)3kz?IYeROYx9(pw>;{XDJ@}2nk zDzao`kOIi?X`d_ahu`zL(Tm1r?F`-G2X|nIG%6)F{Y*p1gD7oMKAo4D@P%@hw)O;L z&M6ZuQi>PPH`e0dhs0IRUL=M~=IH^*jz!)wLsIC->W#zr%@UxDKv2|&iLqpWmy_?- zNd6#zLk*5uw9xzEnw2zc>GPewyFNFd7x}F7XCLdKZ8i$n;z(uB_i|03Pz{I`D*U)5 z2~S2O=m8df-4Ty7a%t-n5DddTr+s9}ee$0M##9c);+ry?Zd3m*BJAM{oaq5Rn?kx@ z32qY#*Kb&x(A1^KeAfN0il3qeFbFJf59Vm%sWpWrQ&{(rPg`dJSXHgJ4;4rOHMpov z#%o@BO}49Bj+hR?f&G#aG`qvtl+Pqk(hm?hz9@w?s7+D1d|@6Hx9!7qr_v=Z?ZGce zEI>8GVbjFw3}Ox+VfV|Z157r$t}wk(n#&UvIPq|OiCcdLKAjtS6bVP1_f_o@lk~Ld zF^t=MsGtOF*1llkt=$sarMR8gUs$;FDIF9a{^rr=691u9_9l8Fvy=b>2zu}qF(d<m zcGWHxf+}?2FD@=F=Z7_S&*uCyy6FVm{!(Cvho+KTyl8hg1V%p|Q%3Zg4TwMI#(y0! zp0zeR`iWHeFVBlHLCXRl<i`(MkH#}2wDNV|G(d<1Cc3^AK&;CLT4Wri1902W_l(SE zi;hXcLkX06LLl!sPm}t+3<7Jlz)FeW2>iaswJK?x&>e#DyKI~J=T68=HhP&k$**6c zI3IB6H?i~CuS#=OVGET@?}*)7qR|s_g`bgmH=Rxb%Q|%VoMjoL9D9}w#UeF5P9Ck0 z$&#7%zGQIQ((7ivK4jXvjGl5T1H=eDAS~)X!l{Y@Sc!?AKT)`U{jye=Lb+V|sj^!8 z7UCLYL=`}hf9|G;HQv$cY_dO*eaglv9(;oYm><vNQF^(*Qi^NSZFTPJ^R>o{q51B2 zFtCOQCgU{>MrMJS>G^P;xlA+htTTRlgPW=(@`#qu824RlG#u`%cDun-Sh}`05Qz2n zPZd+KA<^VxR_Mv~p2%Ultkc1HzH_gtQw$+bD9^)|CIWz*6d-<LZ)aa1o24ip^c)!^ zi^mi&Nl%FmU~KS>nl$Hvy^E{IT($O<R|oDnGXM|>APXW!!vfw#0*j~ghXArZ@K}G> zz#CH9@VsPzK*&uL%V6;g3o6W~&2idUzrknwKt?NdCN6lJ$JnBjga)Q#WBav|=EH*R z12!*OtdoRi{Xp&ibdg#4<p!D1L)k;3#ii}%TayBG8{ZPebSEePBm@;UmPo6ta}cH= zvspW4)5y{Ff4&KCQz3!i{sNpUv%~e8oilxDV10k~9soWF5xw}<Gey?%h51iEpSR`G zm!x~;tM}q0d)fOtDulMX=H<xCHB8G0+YWH}-%EYDkG@;IDta!_lq<X@S3EP2swLh| zzI-<?7hDoiV>0$9dh4k@$bY+^Jmj2GY&_?ujxn}~i%BD*_?u5{-qO2C4Zm{iU2Wmj z$I&U^W8#o#l1q;lkPq9|9FIt_TriuJro67q@N?>A8Ie$_;I6q&>Q&ZdgMZ1F(8`gc z)+B?+uf&)sL)?{=mI6W$cBWE6l4B8sunEyI^`;y(j4_!dkt40a7rt8uBFFkY7Gl_z zvef_ni9A{7U6hcs@3f<{?>6g+0mLNac7n68MO7*MLz0=Wm>S#A;#DEs2?iy;RMvZO zX>F@WawC7yP5MUpoSb%>aWr``g+q-zLVh4g<4lZ}9VFuD=Ox>`T9;96!WYZzwk1}` zSTfp3jBM&<nr;`2)H#o+qbMpS|5%8`foyyjF=#@fAlZozZf_bLH1JCthWD5I75^3h z`y*s0lgZvIn8P&drF}aObx>2qmDv}Xl)#KDAX!Z&9BTv7^|do=5yi{JC?zU*c!4Xw z_KwV>*<IBvT0i@wy6Nc^mzX!EvRWO`8#RfZa&t6K5I=j4O<CQfL#MXgiL>X^2*lE; z(y~MAg2};6T}TKu;id_zz76Hfur9EecDNlcw<~G9Hp-dF=h7qKClnOckMzK{%>yg5 zCXr0lEBt<Ly1(?*R3Kv>rx6P@jhT4_t47Ae^x1D+nE^G%n5jYF$MZD(@h<pQ&F4Tg zUVVR8O?H?eKjY#0YmsKc13KZS>NQ{3H5-RW#@l$YKK53E^=~6KH9Jb76_?FQzi}c> z4Su8Nm6TCGyef%DRJr~$0m=Y%#LPTXrs<y}7Q$)+@f=T4&_Uz>zweZW=WHp#wr534 zWRXA!frDO+*|Ajr%@%OQA$aM2o>&;e0E19a5>{BTN^7g3nDdU*aaUg&t&Cp<;iR0y zdjP&R%YHckgkeFqr|;U{QN3$i=u5!>FbEMq4i|dT&G@Q4|I;AtubD9d!e!rA%`WI) zYrenlP5GFaHU6$BV*(H)VgfW>2<F?P(>7akAvlBWn*il3epgj$r5E88pAXju)2J#m zAVcsq2v2Laz6~gyw~BE*$^4~;>~p(d>y=E!JZmNL!6w=~b#QPH6_A};@tT;eP<oQ& zyFh6I;!$#@33&mZN7CK182lM*@f8AKGr$LB@^tMTEg%s4M=OTab+5H8MnXpm<`^YC zve3`B0UMl8W(KehtxCjYSmr&^B+TiQysc&JI)fgLqx{qBGxWK6-Si^y;{<(S8gsMz zr)ee%?Vj@`Qb6F~4&O$x-w?(UNBa+r-x;dKPNtr?*y72T+pTgzq7Q-aRYD(O3pUWP z0s<~l>9#K?l;ZC5zpw9a3-geDNGY~lZnFIb$?#d%-2;JIop-qdlBwX}L2p=l5~z&B zCuso)NFgCx+N*AU00g+=f_l^Ku^!iIFn))*2Px~;{bGH%32^(BHGud@68uB6Ij6OG zVyk4I>-8=6K-xq28cu|}{9~p)+nqE8P=ao<`UpRii?6C4h`YJC^(^z1Ak;hI?vsaB zODhl5M@iHKer;&2-}?73`}ZKvefdl;Paw$LNNn7?(d7_FyP5e$APx|3^|=B+0A*hc zFtuLsnz-Bjv?bIyMhFC+ol~P9IT+g!V!&a^G{lu;H<C=C77RXsHSoM`sO-o9S5%i3 zCyjfZray?eZR-|EBLuxBx@6@)BTbHc^0tc&?no}I8>w(=^uMf-H$k`5xwOu%&%Vv> zJv}veEO_SIujbz4_q(hh8Z9O|6CM`#yW~64%AqUByZV@t9}IEEi1!q7r;l>=V*Acd zQy7_Fz!g`S&=)1S?TxdnQj&OEZAx!2)T2JspNzaKa7CZnF>d`zAI$Cv%(iu~l3^iG zvz@H{+ghK4P8)TTEcw;oi<JJp7HypAlE`Fhy(JK&9Q3gQ`0pq1nsdsc&k+CeSt|Yd zs5_B~F)9Q;K$%QByn&XKN%E`MM`6ZX&f~{AiQQo)R1qK536cfI&5wU&vX_yE4?{e( zZ*DkLDKuHp@C$eUjCd?I?Z=0t*^`^vTTm`TDwBtgTdDZHqmP&F(?s!c>GcqKzbR{X zUn4JeSw*Z&J+qBOUim|w$;r=iGFYl8gqM0v*V}fT9M<sY-Z_2=n%oixkqRH(WhE<w zP0B4>M~!CTOcwDp2K@B}Vnx1Zh>fG&!k?Um1uB@_o$3jT{5Wmf_Y2{wbdQC;8TGxr zK;GNd3hQ@FWiSv`V$uG~Df36Mx*r63HHbdDA-I=&?LO$SG_eJOx=usJ)INl(+zpT{ z&LM#F+@DKH{QF^1ku0u9T**0|XYAyLzK0Rr#nDd}3}Dovj`N+%m2=J7+FweZxTe>O zdAQeX_FYB=Qp#eG)6Nb2Zplc_geVj^2lp)+XSPR-9evXln;<UG45QYM_#xV7AeKi= zlksLoGKaa{Ti`&JF7Oor4$K?-`=_tB9(gkA2l}8^?-wCgMEO39O+ijpqo*`>+tIt3 zVrwPKrH*1993J9QrEDq@L$yuLQ%_ibn;?GL)tsALp**cOZoWNWB(Bi^4$d>U#?fNL zs^?#xjn^<FW==r9;>nk~<NaOM<C4YiQ5MR2?HWv;M<>m@oby##E@hNtypOjN%~q>O zQp3|V9s;Ofsc?hBJun5?6zjTWgQ8Gaj|Z2Ix?4nK3DEI-r9r!f##39bHy&)^wLs<E z`vB2(ZO_+WOhFgfJ^J%5gR-xt5n*9B5+2`5jhe=a&i=xa{prk)W&Cn%*|T1|%|tEN z-@?)@Uz`aBg31U=-n|Ppf6d^s7Pn`fyc!wd<P~wRhB<SC*u<g}+(9!eL%w_5-_=`x zXK*DYe*82V8bhc+g~|lEPSxSxB6-90D0%%f5l%3Mg}x>LC&rD}sadWC4E-x&twyKY z694CihF*z$<{mT5CqPhVdZob^zx79s0S=MuPlb-=XbM9dEh%%&NCIV;=~MH1IbPg# z(?m8PK7!RSwYnSnMUhBT;K<nqri}j9mnq1aY)*v@P$f$<#2{EhMmFUF<kUC>XgApg z<33966O`=Sqcut;N18|wVtE{_zp=mT0?_~S1?g1Z^#GQFH?$FD43{;Ulvb7Uu(6(Q z`apOm%kIfV9HneLQY<JJsNf$4lZaqmzpWOV)wa*6Oo7hIq#FTmv@-WO<Z0F-7J|P@ zU`%XtUPgG>XYs#3V<TEiLLvi7n~{?<1Kx__ipb}_0gsAe>gUA2?qv!XiqHm`d%!X< zE!9f(nm`~SuNxd(T1wP{%2)F4=Ubg}He9AJ>R%cxEZ0myHb&sL9A-U!mXERO9cf%} zy?lUP4YX+7NEU;SG{a!qN>4{wpApt-xB1Fag+_uqO6%zBIkV+O{gZ}9AydoFt`3i? zo8;mhJtgg(*_U((I{Cg<L+5-_Zrva1tQ#Vcqx8gNi0dA`IpI9VZoYHAV9LNBoez;K zCkum`uR9~GhlU(0Qx(A7gM7ISaG3<teuykT5RzVz<JnXwDhzET_S9A^=8X_kL@b|a z$f7f?Ws10&a6CkW@RxXD4_DwCJetcD=#o%f)?>y7+g@+9-d20gTjtm%4-fH|RGJe{ zx=!#T-&S`F6Oh1R$&G8DU-1^uFlnP}{pY!dfD3PeO;`b-^`9#rRmioA3@5N!OBI<> z1}4v@`#Es*%BvdM9{CoVeX}clUa<q-itWmHke97_hMP>PX{E{&F+FO?r&WSCa|fi? zrbA5Vyl3^Cd^2<Qwmt7k=GeDWUT`A14e+Jd(Gswhgt+Cz45QuoFOrE?+tsMMpK6lB z8ORduHx#0o86m4rc|h{Y%!l%RA}zYbpo!7^B$Ug!r;|h)1B^pm77Rd$`Lhx|JXaS0 z^dh)6`{Oj&eLeMaclGr_zIK$x4D^<S#Pqgb4gN#GMp+yKbQ}(Arkfug`8rMS^~D-b zI@S-@h^D@Do%StJARe!|*zx<-9l7sUu*=coEPJ}nWkk$bVY%^)>_lKC_4KAV@NtYq zn1OJ<UC>YPe5z1&JL72Og#8WJuul?oAH`ouHicd@0Vc{Zy?omL8U$F$z8}#Y@0z^R zzd;6{bEGg7@L~aa-?J$Tghv$w3VFMY<pJYHT_KRft~=p_>7k5n&9Mp=5te~%Ihn#i zg<_fMuSg97_7jX(eun)io7Ekg*lhCaTx)qBF@N3m|I7QX$7(~Q6qxqw=37+2REv?g z$Bh9d%Y(pb+h{IJH*8V7<eHCl^u@wi6?jh$jtmx7gRv1{QC~U{j<wwMa9f`90T6i9 zG!#pmR5Y6tE6Qt5P=MSQz>AZ!Z2Z-!XYAE4UBEq7jhK3UXOJ*IP1OmGWJ2Wex?cUp z)#yMM0jVA3B4RK}q_cN6JO^@V6&2v{c#^%FSv};9XEnRf1sA<5Lde5Bw=#(vpxoh6 z`KMeDd2k&CfJ{|-{Ru0mf}v0xZz_`(C*Oz_No12FvY(0AjvL$j?qoR(gtcBwK!bjL zwKry6g&A{+4gjvL!>S~V3#4CH{C<#{@E+qUeKHG;|8wJ#o|{^G6YGvaq9s5q_~EAb z>wp}!lO!D4iupu_DTQ8(fXoOhf!rO5Q1ma}&MAMPmr(?=cT5`cf9HOl#rD?@2v$_V zx|pm9(f}-GVgU7~eomI;PI!%>c9RQT)wY*84{%=`TQm?{iWQ)SCrgFzgd)i6dP#N4 zrD@_?%F53e6&cH}f_cCjuA=V2@>8ozcfL|@+r)K$ESZTCqNn-xEYC!u761UA)sdDM z2m{0>^*d`set|$=3tCvdbSwyI{66<QTG;#$G4kFx((Po4Nv%X)7P0H=?mwp7Xd{~; zQA&$0K8tpR0%EQ!I{UZoIlB#wX07vVrucJWGo;aEI}tO+tx0K~OBVGxz7_%{OWpGc z5bcQ<?UKuQt|IRB9n)8NSB$05=%v{0Ibkg&zeHF9%1|$VYSKceZA#XO){wI;Z0aq2 z%5Wk&hR}UFf>Ug~3Lv~UEJ7oh2>j8ju3ZUX-)qdW)v9u3G#8SEYVCLMj?c2@-q=hg zBd18|?{R(JJ>)Bw@4W51RcAkv<tN$GmJ%-cQsrq|=(IrdID;x9oXWRc8(l<qWi!bw zD6^D15oo&Rt7-;{l_8Qe|84MqIIZ)447_cnJ7s4)V-f%?dR(*=X2?#wg@mXK;K6Tw znySoy$goVkJ!SlP$8x02woF1YWTZsgyjXWRta$4tX1Cc>&E#T;<<rYK2M%`DT)+nq zxTQ*gB|^kc!mJaKvj4<iMqYwdcz9y8>Yl9iWrAFFD<c%g|8L9F?P{hf?{&z|$OnoM zlv0!Jt|Zl#5#L0fsze)oPW_1&=uZ;`VWzQ{HKxqloJ281<07?et#lo)@2|3^dDN5u zgh(Nm^E|<ab6*mnDTgGaEK6*aXJqVx^Wn|Dy}slh7rLO$G+b1}z?n_)umJjX8tGUf zww$l9FYXO)Rtu{uc?7Cd`$YoGHKCXfS?ch-`s7x$FP=sa(8G5u+47knVu)<VG{0B! zJdh~k^c}mkkN;Lb%3`;DHPJvLpD(|PQ-8mVqOO7d_BfW1nf+?rK!^Y%(EbB<I7XsM z+mdViG}J8F0G)L4R8<1J5cU{+7T4Q?3-4>jVYT4{2WIu^H}6li0p(_JP;2)1^4$y# zSP7$|<;zmejC+-IW$Ybib&CMR;0j)j7rM}~{p)1Ao?sm1x0^B9YqFQ?4WL$$ur&pK z2k#d8+a~^awx6&`wppsvOsiTteBb-jdw7+RV-g9M?yUO}gOU;!gu}jd)4XyCo5Oon zBXY+Fjs*%QOYg8)cmRQSSE3%}d_MPi7nS{Ys)2BbvmIf~9{}VWXK(C%FSE9nW3hI1 zh3K_v;!)gBq9#*K72(gK@#(sM2@tGvb-i>gwz<~7WB71%VYkEOS@{aTcXyT`jVxmt z!s#}1HHpFPUmfFdqTt<`6<O=~pA*D?OcMY78TeZB&#uxa7|G1m;aBfByPu9XFKgas zp**i~RW<-P3QP&<Rscve9YB^9f_))-tnxrf;Ew#OMd;n&P(lLsf|5)sJ_n3$to~e4 zqF$}vC(-OmP{Lqbq4Bfk?47aT4{xvB?gtnG*5)b>3n;3yy!wz$GB4mPM~G+X|FCF& z%KlrI6(B|d0I^QFdH!&R!vYAC0f68H2Z^$UPU|!nl&IP6UMke)p2W)Q5gmstvr|90 zx|`AZ@{oa~YfSM6C%{l}{}GN%;!|~w(C*J^<MEforhR>~JH!;2YNr|&W!MZLBl<&; zG&ndY=PT@7^ASaiDsUj2dUK3dShGrZK`Ba1J@)Nj(=WPZI#!xv;-x0*Fw<uaKs^Gb zTrZEN2|`H0K$Prrn-7HQ)BFb6@wR>FRkq|r+4rXu1n>rz?LtlM&SWm>^d}t0{xMnI zxVIkm4))WT6ae+e@aROWg(rkUrb5S%Z{Nt;;P%>R8?i-}r6nXb9#&0m5%Eqaco~++ zzw};P&Kg1L*4t6bkPYRgDF)=<p~eP+1Gc3v+LN#TBMTsI^pB;Q+J(~-jPQKRPinsN zesuql5$&wLUOUnB39?>f)fYt4(w)>ZHjLDOo6dIyQ?Db)z3cH~`9<P=dwPQ+Y}hyU z1`N0_lnq{LHpW|aAlmi-cX&Ld8<&S(4-*uea7L8P&vt!*-jJIU%R=eG1O@+05NS6P z?V%9lF`B>9$DPQ~r_o`KnrAP09JP*4IgdKtDtSBR)a!e?M$<Yie;0V9>AtKZj-Y#- zceM7eq~wD(`rB?FuMcEL_|xr(VbOqRfZnA<oGF7&21UE&TAz76UAK0OM9M8rk_0m} zNz6xYy%hC7X1C9C6cdpg=ayZvD&Z65>Z=noMEYFTp^q%4?kATybzUXQ`t3_n$BoXs zcq%e<e68PSc?{ajW&EFAAOHwbQe2|Cf}Eux|LwKl7ep2Ik;GBVO%OMy*r`gRA-`Ut zgKix%J0X!$4=HA)iVwa0c$*>R1nI$ca+p+v`p6iJWc$bzh}Vr`ODNF#s~NO**|IEl z+jc&&K9SJ9%b>!}7sW{sQpLzdPg<DAlqt(#+S!;uuk(HhQ)Q>=-P#o2J3dsa^MsH` zlrMgIqtPbXRQa9U-=9Y{mWY>8T8U~jFlj`U)j!&$N(T)Pvj5Lc5Fe3j>PNf%*(nL> zMzdR+-j^o3v~o>?1QuOZB@3T!%k5D08^+-<%r5KdijO?2E7%qeTeLzE&%d*UK7C-x zu*X`;X}pI=LzRBNY5Oop&7_L&nviA~F$=C|Se-Af`12E@tRyreqWR36)SYXHW^?%M zmn;;Jyg_9D1JdII;y;2LF`x(Ziuk{Nd^_lGx)*-{D$96p@#q76Bjf91!ec$npAxwH ziA9h>z}<$2G?jDB4W~26WMGJWM92TnV%DO_h=G6AWeZJ%uZ>OCAL}U@0#2*M@=4q< zbj0Cp1Je|N$2A5RVVhcOEH$#k_1Ypxn3sxL`|Zv9)FbQp1a6+yW21$AyW?S91%3y# z$3$}uW0Rl3Xq<3xXHodGCEvf{2dO7t?u-Om>q*(2tZ=1Z?~jxE$J4DVaaNXYScalH zb@)?KP6A`}32&N)obSgjP1#XT=Bo`V^jc=wO~*E$r*x~tJv8mT{Esc5@OKU->P2Xz zY^w9sIt&K>7wK#pLfKn%VNstXu}PZTvb~&)XZO}9RI?2ZofWwZNfFloA+644qgm-9 z1j--!S`#U10l1n4Aq`f}Ny*j9BjTf^6@E!~L$Pe8jaKVq&F*KrDrdgEN5790y>|TJ z$(oCJq9(7V0a#CO$be<u)dDdP$J}V)H=YK*57XXz*|=}w_-(3_7tOa}Zjg6t`yB@B zj}}C0pR1H^U`WLj+v6t|mvww!;avQuB5lK6=L2;0Yh*BQxWk|lCV^o||6_$@1vhm! z`kITrC!MkXBO2ay1N7P9Z&<euhkpih#p?sd92`est1c=F*V9i_R8)5!@5i4!JER^h zG;9R#Mi>Rd+C9E*%aQ#ZNGi#?n`}`MVTXo2h?uRp?)4w#j(0Gq_ghoyOC0Pgfbew{ z9#(w2D}y1~Wl7!Q>T!)oEz-g-ZXcL5bWdBZ?C4_Gx5h*fJhS*wFvYZ5w>-xEWwQ6p zbSu?J1bH^;ygG@DZy_}MGiUk|yzqvH6J0rAU4Pq#r`6{5kg$>gC!PZ8Km7vJvQN)j z&%4AC10%*)|Ha1s-+#R_p*#GH4!yX(C&kz|l9i2MckD&TO*(#Kd{MtMG~**kwCF4F zvaIfN-Jmbn)ZznM?ba<BWyWqk(ZN6vFx94@vu&G|>Oc+G+tdR?P4Lgy@J{~fE7BJi zy;Fv8ZWZHRg@-#tfH0F}lc<ZoR;!mKa#|=GaNDhb0(#@h{@Ne?8PGx+>_gF+Ii#v@ z25%ct!r*49{!P~8-LCnak@Zrm$siITFMRPWgyZ!Y0Z)x+CcMy<>#8nz#o7-{TJhz2 zB)o!Fb8U?mD}G4cdz_Jq0c@B35nX3#BtqVXHmp=3$G^42^$!5WKhEv++K0PePZRj` z6Udf+ZNr9dwdCK~IV^yDyxRq<uX<eAk2jnyilLjrcdxQ|)UR9+TE>A{!Mku+-5Yts zbK%)q?@pRkucrY$FT_+m`IN?_Gw+eF)PF@~4&V>OzGtt5l*R^NF}bhK4F%xco-Ci8 z_N7Mz8uzYsp2fo?2kIDRH~|~UX&O1xTwkMx(x2ZDgc#Jqz;-YhfE;RrbJ}OPSa-7p z#9CVSL9MDDL&~}vs58Zn3jhOTqV|}gw@LZ21)O$%5DB@htOWbGWdlOU#%bPo4;Xof z90&wMg3e;LEqI>84)@aUx?($gVGBH{Tk$>N?|AN%=@>qxa<CI(vtab_mGbDl0f@oI zpx;;dXFtx)yUyRA{PMPWnWzQ;;PiXy;D=<1tYGT3h!*`fMEql(vRV_rZO+7@zjcsr zI)2HF4s{$MZo?7O=z3~TbnsN)4yix7!wSy~d&!C*b@x&WL)_@sP6D1*?u^M8)X!$o zJEj5(jag6hN^0{7*Se3ILTy%)BVRk`RfJ`i+a}oWtKW<ma$ve)zzkE)0S$&*8`oP% zlxIYOp4!#O&@zuN#fOOE^R%kFS6Mz(<^n$<wKcI$-|G}7T^X~QV==YWCND0wW^5TB zA%5{(H^~YVq`PzpaZcLRo+ojF<5zjQ`@Ek?BGFZt_p5!Dy4PfO%yWF?DIMNrbJ>ri zp^+N@4=Ax4iJ+R0Y*KNZzLqbE3fIpPzc|34U0RXq(}+~_r$Qal_`|nDBRbU`WPD=v za_=x+HmJ8seRo1y@9{>M4LTn}i0*y6cA`Ov#sD()R;XR;=AMAb@;Zab><+eSp;(s0 zF9taO8~0NYYSH)0atZY4ChMW=JHv@_RLlkq(C-OF9*b>{@gaH;g*Tt=XuBt}Xi<d; zV#Co!z?``$&j7M_qokD05C&>zx$X^rRs0_#v;d>+P}j?+dT~K753dCWIt{`3!syU1 z_FXTLPw2t-;2#nZs+Y>ILopDi-Tke;u(LQW020$x+NE)g^_@US&Puk6QZ5Mzs&!Yi zy5*18-<r8&S=wFG>x!P&wDQ4H1axL0%-n!L(wKE0XzO?`kHD(Yv~t~@-kl6~-cd>p z$#sZLFwe#Ha9KCv!BJA&+TA_)4w54^%$c|YmoNhZJiZ26m*&W&RSB7{t)x?11-DNz z^jQ$PuR3>!8U3i!jp3iFHHhV`mzpQC_5vUfxGUkk7C+thHE^C`N{O`=P73uNm2<*i z;*y^^k8<nJ=Nycqmr05{j}hCukFs63U$Sil+)v1VXEZx~7}23LNJ;5_3A*!0UU7aE z-&-N{*|AZsP}Dn|YiIe8b+5fAt2ve>Bz^KYjso6je{M(V60)e_5;bggJKW3H`MWh8 zcA8SC^+cn*8PmMxXux71gyC^az8x66wr}78bv0lV9s{u&tD_Sz#1TE`C}Cwzh915% z+gsdtl%^z`;&@=Nk9NCr$`=LL{Q{aW|FiP^gG_YscSQ?Sh`T8IcR2-{C&7w{z%^YG z=5_AAzR!RJK=lPYsI)dyJSO)#l<V?3-@(0w2sn9BW-C(-+DF2`Hyh3FzJo`?NP(4P z@AKTrb}__h>z6_Fqu=fIrbkVee?PI{O$vQElW%REKT8-Ya(b^c`KXu^m9SsWcOLQL zH<Y50i%zgcE9AYN@?q>_^|n2tKZo7fyjljQHNL~Ex7!&GoMTW;0x#MfWuZG?#57Be zM+0dG2^VK~*aUxOGeOP2Jooli0p1z7I04F}NaJ%An!&Z#G=sw$jT&w0bc=1anM1;K zM{-6&^=7}nu!btdOW^&PP4b@KV8nszTXewNuv=<S@zZaTA845kLPYJ|RC|k8M@^7E zNXSEUIdw10NF;TAU_D(RY3FB7je3V{Nxc6sq&L@L%J3E#m}-|FUyqKh@9X(_GKr?T z!D3N$OX=hAW}!4dn0F5e*zyfJ+!7tJ3Bpo5r>IH8LZ{ru7nuN4*)G-Q6t*mA!NT@p zD!(+!WhGDzi_%DC3%Dx+F<YV!EG;SrJ6C90GXS7w_d}c8&%#d!+s<#mRjLD#mk_Ho zN)mI)JOIMlENA_B*Wkbg-)n}o6+xf9l*q<QH-CF?;Rg4;S#o4}I4iHS_8YQcq<t(Z z>06?iGBxuC1tkA?A9QmcX$;bf4Laq#08ZO^w9pONJ?26npQ)!b&2TEymxt>vwY`Z< zn(l3{$AUMzW1pOd9}x0#g2OPpYWlbIQK;a8q$x#c_y8^z%O%+tHcEQu!q0BK_YCZC zVhIJ3#rmsWtajfZejN-=b|1AYjLOpy34no<)V59?>!>SN*1^NH9nv03-;9*FIRFSv zKfU|V!(9y2F^Ktt?miTP0N@bs_=Knw5dVfg^_?m&kyJh?bXG+Q-w+g7rdEQtZ#;S? z&+xgD>T`vr`-noXZx~xH5}1x(r)WHf@6)Y82?(_6eGLvl6tw<sj+G@}rTxfr+b1L{ zG~rp4)|~}Fkdkbz75!O-xBY?W+`}}S`%g!>Rg{8`9f_5J?V1Gd(0eYQozH$`$tylz zl>C}B3q+%ujEJEPIj+aKyGtUTjs7J|p(o$Xh18mg$$4UkXvH5z=g(O`)@D6<9q^|A z)zTV*vYX}}2RpfD4VNVLUDO#gIbUx688(um$i4l2-4PBiY~VyMw|m&5PInw^S}rJL zE;PnRm))?Jl13*xnQl(lRQ$D!bzf3FeW|%*M`f4XI^2~iwF0dZz({H7Z9C?Cl3RAG zq<_hK#AinGWiNT8iJzww?KeYp6U2FxLUNN94$!OlA;9q3=(YAgzn=4oKq>3o_%qFu z-mpH$h@K&YdD-!yi`pI5L*4_mk<|A1Cv=upZ}&5aVNSAhl}S=vlHKw@@!wZGO^-6x zO=0OyMNSt)IFWG$Pv~B<P%mPW$xwsc;oiF<i5DWR78GC$xwab-@5f&$OP><TV@%fD z-aFYGhT&xLEJdH$I2BYbHsNApdCAq%qnqxooB_ce+66(0yPU#Wx7qTE6fhJ^fP!qC z?y6v&&$Or)7Z6DDBMRQ~jLM6uMAMp}W%h^sVQAZp(YRl=HqjJ&iG2tEipK}{)C<at zoVwtefQH-LZqwHn-wCVM);`;rCSPRt#p84ilNEE)_Q`ZQy^_jz%&O|QXUpaV^d8<v z{ysg1bej1E?FwW71THZ*9=Q>RU*S>aYwt7*iUePF44aJ#+&inCOGOLjXDMBDb!CNa z(qEuMXCzV&CIk=1QDq(Y0z!cTh|o-N7Z+~4hpy16xJ5K?DIjPWsNvyt4iIE`s-KhO zBw>!>8|cGI3r*-S&+4be6-@2`g4T?0gduJ)5Z~21W1hW4vk)U|yZaAx98dcQZx)`6 zcb!3(*2;g(R<%jjb0qlg<5_m`C)|-<sPpG6w%DH<&jik0#*f_Fi<vaDCGv?dfd3QB zxnI0(+uRPd|Dj2GmQ{KF@EnKc|AMbJ@#76KcFecIt_17^r~7jwc;@f0zI_moimL77 zmSsrid#e{E7w#84kRKXj*Z*~zOSQm+&Kc8Qw|mXwgNV<4{9&n8BLNcQE{VL{o>hAN zU5jrv1ArVYiXXv*wV39iZkJwWvsV&}{A*?<be}~x_iUBKjNkQ;`nOJ#W7OmA5et^S zOC6umSUrz;gD^+`E??KSt)9Gy9l50m$f>>hjChZ@f4w5Vk9pjlqJ4b4zSiYJ%o7uv zOXfYp=TvD@QVSTzAr=f+34$NiJ?P@N^l|cd0V7$?LE*_*FMG}y{1u$%{VTuFG59%3 z4v?MyWD%TTs6F|?BlTTPitDQcB^-L>&;b4<r}c#}dAySN*4nF~f9qb`5xPj>dm>>M zkpED2LY#;PB>93zmy+JJPayIPDe>xV4HvNKv-Z9O{;3dv5JUmB+p=d{uQwe{PI_7} z*<802d10NC$p4y&`W$`0J0l0ZTU3h^`5GW&c>ygq{u8y#?|${!b#e6F@!nC!1K~TN znodEV?-8u7cfQXXyA_J`8u|iKN}ED_2;D0G19txJnydf#{qjiAG6e`}b3Kx4wEA32 z(xR;K>^PC|2EE1->r=1}jUG&t=vV3Mdb|KM45NB06tK;PjAn9JgIMykkXt(RpnNQH z9~UsypsmJN^BSKekqjh&&V(<tDjjAO?tO-kFJxj!BOt(Gr84UUb(RW^epNkXn`ZS# zL7UgCJl74I$mGf8w4d$`AjQE028MQOLAFJqE0Z0t0tJ%>B?@|84Qm?s#&kYB+X+cX zNZem1lF$P3nE*sE%^>#!U(9op$-#(gw&SYWrTK)id&7Xk35%M)pga{w*B{Q%tY^8y zS(nHVd)RiiNg-0j>q9!XE&plC$!RS|UsE<#S&-D;yU9oYGE9INCjivxy&CxA@6ir2 z=`=HK#Yjv{G2Ah_@T<=XOb>gWQx^6-@dQQv?wwAS?clNU>bBLK_C5d$AD{eVt@P+K z7JS1m=RtEO=~%o72GK`sU6zAXl?va$Z~vgDf2gd&CbEH$$NC4wjn3XXxQNGQPVgie zAn?R;a`w$5ddIRN#TO2sX7VHyD-R2Q<OlL*3-U<z`)4)+WWeX}oL>jXsMskcgaMzs zXbrl2!u_UnagtbHW=C*xzmr|iDE3B}HkeE%=$Xk6`T8uvz*YqpyuZoQ%J%~2loZpm zj#(mGSE|H@k-KC5vI9<hKoCMKSCxSp5JaPjH1w&wX@y@u^<r>y?hilLwUHd5^}KaX z=>2F^WmspkTGwSg)7YZaQ36+yDGaEa@N2|ea;sNrn(Mes3@dUP?h7t@<}gjawCc<e z@NDe7<S@<UNB(W?PanLk(t50Pl<-@y?0ozaFJy+#p)-$PhPb1|rg&71L^1Y;pPI@2 z(kjQ7?<gH2oX$T~@W#xa(VaeFe}b)y=v}5$$&MzzSJm@XR=*qLEFW7n4^iEzpSB`} z$Po&+;j7&El|yW>>ypS=x_LV-jB1%QxRn${lltE<KyV>f+(`20cGL9)<3u4May%fr zOfTuCQEg+<+$xI<*7R?>orimeXFO}|`FH)jS<R%W6z1--Tj^vGElp9$Wy_*&)du8Y z`?0C2h;@VjG4?LEW>T5>DJ$Y)nMOh&_+B!W#ZM`6HzGCZqI5&$Yw1&~Wv+VHiN9*G zpEcBV!X*6>1`Q{C)W%5!fO%7>Qsnj$bgGzWoyWS0#Cfa#Sc1~9MRny{8=W;R=L=lR z%{W`Uiq=>63e_1h8!bM<()oF!K#bdAJ21e_7;P>kEHpp~!%s>H7UQa)u&z<%kjrDU zBH?xYcUyRWXmi=Vlf1ji0iUq00Oqd|V|kW41Y*7DKbLk~&RmV!sS=1a+byr*LG71X z^iz9kTz+-%kqF}71RQb7Tw^6iytN0wxk~8q9cEZpr=|W}PUpiqsQn6^JpcNVGQ>sh zu`|(i$Co+ME#N+!NAtR`!hL_ZUz?{qQ)ojitlCX<7ttQQ1|KRcKt#IxK=X50NklQN zdeHap9-aD+8bO|?&v&gb^5Z=@;IB)dyODk{h|$5OXKNBS*FTG%zPE>bQf@@mbfvCJ zgSdsp0iRuw@@Qd!w@kU#si#nj)jyU<#Bb#sHl<WaOJETs&wk>=#cZYhB!27zy(&%Y zeA@rW?lzto8n^L&jZpX4apvDeml?Nx($Ov&>4HL6N>IOo5fQ!ve0b$cvj^w7vrB$} zN|6pwdBZus2!N2|99XY2xwc1KaFapO4>x^Ojh2?}AuI#CO+UXmV<@h$oZ#PUP(>t* z51S?@@w-Ne+gDhwf_gW0@Lj&ICnF{%W@71lpzfHJ`2M$3tHb~DBJB4~=Le~kyI<dz zabsSsvYuFdBenBLFCHu+Mh*{&S2PJz9gUL6XjQ*lqKhNFItmlUWO63i33-*$1>PNG zvf4n*gQj&exJCBKpJAnHhA3Kd7sexX?k9=2#sd(l%Zm9w@@^qYSVSW8e(TnThb?f& ze!u+>^sKpXV6gt}I#0Cvrh-m092UI&4b{u)Kjj3BPwj<DEVy{(etm<~6p_gAido%v zYlDAr|LWxf5N>~m%Lj*IBy}wGUs3N1*e#$^q6N%m?tjg>vX4wN@ZtU~X?ym9^0%c> z$)F=i$RD!<%6tPYCGBRp+8a-tHWumkW@cYKRm$Qe@4Fxzlu<&kfIfI@e}nZ5mW$2q zaUJ}ZwoG+pa{>SI^!RJRuf%Qmfnq%Rj9jvllWE`5$e;6V!y>Rov@iPz7=<^Jef|x` zyVNU|d%qZX(=w7&T2y|=-0}wy;<LbD1$m*Cg@x`_uW)jQ2C|_|CncefZM>kN?dQeS zumZ3)`bRb2eOqb0B8#*T!ZXX|OaQUNf%CdrU-3w==~d2MUhdZYe=)ouVKzztvK(kS zwkET<bmpt{wpBFC)n)PIAdb?}c}7B_Z>wqzd;uZLcAcL=E%%;KC+Ll)Qq8xael<nd z<=-F?5*f5`_9;)453SBpV&Z7r^~OYEF|SYx(N5W&3Q`}BBMFbR&dL39Ip&CDxV7c* zJQj`+L%_ox`bXO^lg)n3NBe~Gi}?P8o}mLV0{rj#mOTVAM%nkUcoFSRuNzKpeo}uQ zyXxgdgXSu|T7&nL2GNgj0EDz)_MdSvLa!i@WaK+GZ=Fq}P1cUEeV+qL-tTKKeI~u8 zNMutrUE;`qP@Id7%P(8}GgZNmgfu3Q^&O`MEH;5k82~4$2GMo?SwT9?bBDTy;({^K z1(KtXp@i$f@dt#^f2RMGAM_3T&@`%2r+IC7>Zr)Fcr@i>lSd_xte*xeAfAf61#&RX zY#pfwe<n`yix(4kAE1KEZNEZ0=BG%E66(~7yHui}vml8;sN9DFz-*DmixK+FKWD7| zZ44EBK<=V7u^+E7C@Na@oSJ(fcn_z3e)q$4?1L1tTB)MiT<h!@4DvV=OG0XFH)LIQ z?B6y-0OHUTdoGz6mkh3D&`o-_&ukd*WHz8lhN`ZKg{HYS%$eyVawrMgeiFwUrBbQd z8!3FQ&w8SouegXFB`3wSEv!rDe=H^1Rr7?^747P6lg`_*<hn+YQlb;JM_^{A=21g5 zOjUoxt}rpd&LBZk3SU4(FaAEyiBI`5G3zZEDO7t>J>|C(!IHI59kmiZ%#)N{Y^$!K z$oIqTswS(SJ6YVXY0imBEu8=(c-t^N_S;iOV1q6Tdn8(JZ06-cY}iDcCzJI2wUQss zZerX`a+wiF)^mK=enWCJj6ZechJ)iY`Y(Ks3>}^GVc(y9vsth1>;PrtE$|#{p|R+C zT=~w@sk@=0j6+ysez;>%g!}>MXL2DL)!qH^U3UxO*BY5X`2qf)AE^znwYyE~j<baZ z^YZH<r*x)-E7a`}=A__yY1xsdMKmW7sLh8(M-VC3oPewf0PD8uRnqO56Q(W|31@Xh zhD}-Jw>dJYOYUgN<>*VpZva?keyqA;6M&l-5qP=xaS1+)6h&qcc<DN8y8}EiWr*r2 zmH;^69+)b767T9m0J1*K^xJD`(r8y)HneqAO8vC&cuIY$1Q@dcS`nm+#%qsSO1qoL z4_<gbJ%dq)TRdlx((g|or`&wbdr}gi-Yff-KrFm1$6>X&_L#`UaFUqUyMD4O(F(B^ zJa!YZdp8>hMVV?NL9~<JVD)J)C%a;BKj#8mxf2}LJ@7^A6<M%A)xqYO#8WVZjR$?- z0=!=oC?5K&rlp}hd@v{wfVGA%q?-EL@n<!5BglxQ>#MMQV>}79#gmK>!>aSTIL^0k z#EC2bvF<R^Br7i6ob$%tFa_eSwug+!j@E|b-&d>oz=;c|B3LcEI$S3VI3GRVAKzj! zE!l<U+?;iCe1REVhbvu5FJ5DQ%j>_&PWC{PFxTHonUZ@-i>ToH`2E9fC76TNFw=IT z@Wu3WGNrpskWanZ@u%Q@4bA=F?{Ku3aXu1N=$rSuwZLG7oL5~1XE#j#m}r>7+*bZ< zbsS1!zrLwqL$R`DrqbzP^cpj5tcHJbxikgNCfSG4^vsyR11wtXp38{?mC)=2T#F6w z{9&jK7M><CYTjBuqMTRydaJVlg=5xoH0_rLyaG0~JC9d=d8~lDmX1jlv-LxvT%xgJ zI5Mnz-s8j4Xich@pKLqnxT=BLB)<2;&cEq3%c!HTccMI$)*#Jk5l<?_-IADFJR`DC zoqVK#AmO*kp2BC+G%#NdKAfq~bfke_DomtnS5ES4oiXL&?pHB2!A2Yav^ktWdFbX_ z9E8bx?mifuJm>#HZr}AR+IB_O_Ycik1-9r<X9&qmrDp}_vd{S`o&+q+V9oC=i4$s5 z{4a}5z+8{NI6QOV5h^nHhgxZ@dSC*RP^$m+^w6LMFO$MQhM=_$Pov6ZBtWEuu}vk( za4U&*^sdD{YVcl74Hf{a35rD4lP}+ibi;uL&Lcrv2*$=T9F~jQ7jUylTK9il6_@0k zZ-=FFnau2r)EPfw#I?Z|wK3~d5zWWEjZvu{6L_3M1-CRBOOK=oq#dueD|J1d3dFTO z@T0s7n5y)2etXCTeC(4AS2jW$0SW@Hdw7TYc9B%<sg2vV>cQu-%5U)Yj~A)%Uw_}L z_t9!p{^%bVOn>|au{xUnS%(+~i`Ac#vtR&E!UWu+btVz^0I|4Jp{eUiAMR6UKDX=d zVR%6*r{EBT3}-*+TpG#atVwhXI$8i04i1IrFHu%2%+%w>x?kza+(y@ku`DdnPnHWx ztf)5<EH_p*{;fce3p1ojPiN)GM;|{uV46|2N313(pG^S$y4fCC%VLuPbM@li>d9O= zgmv<Lplms+F+r402sXJ`zPJ?l9v>V4+k9R6w?g#!LAA{3qq7o|&TW0AZY%qHCE*T# zE6T68jsXY<J@oG`dkvEc?#R_Kog_szxIm~Vi1C}8J-SJ%u!P|e?<Uiz)I@l1m4*=^ zw`1BKWEwPDa(@0dO=5Hjg3QJUA$Bd@Z-FG_0U=jA0`ZDe;toXoK3cIods{vE!AK4& zuoVY%0l@)i`m>~d-+x(pO_?H+0T^eBjEG|b9Nxee`f?jkG~|}}a!2e7Y7H@rcHp3Y z9+vh?t<UkHN}Zk003*SStx_Z;jOLwc+`AW9Fi@|~j>KH#OVx7?6HGSCi;=RuiV1BX zel#YGm0eC;_wJ%6{Tw=6ZLA4}6&0ALijl@rL=fV1GRtamP3q=C9{zSJ&_R_7BhfSa z-PLI6F0GS+3&EVTD%F0AI^UPUrtu22Qr)J{Gj9ACv2nhvbKE<hP3ac`>avlKWHZ>S zpRGwV>azNipEBx1U}_4w5$#Dfx&`nu>#pb`)h<MERdJ94u9ue(7)W3HUnZUn19<dT zKlQGc8v{O29Ezk<$nd5|0v%zH$pV9Mu}^E=VBh5vX{pRRznDU7@_gMc)-q)>F{f|l zDTOHJMe6nXPI{SZP9~EY+R*8@ILQtYmt4n8yM(LEuT|RAkA6O%Blq1r<xJlNGa=)A z)XY9rEjL5eZuf~DCwwm23Dt!oJV$5tR-^(3u*#J4*iep{E2UbVb<uuvMvzU}n#KX< zP?iQ4nU!U+SNHNMUA~y7`6-wILG<Z)fzl-2Go|~EyB8@l9#=P-`pNzqqB<jl0brK? zYpKe9i?@wOf0Ej62np<0o<Q<(GjL=uZ?;a3&#@6E_6yqe%hR@d94#pS9P9uQy7O*O zINJFN#JW9RLuA>G^Ken9o<vafc#BR$>U$uJ2PARRbnW;V1>^lE$OM#Oz^H)_y~ywH zr>TANhwP@`LVI>cHGAOnlclq(VRMz(CWYiTk__MJ9oe@gGyTq}in`GRkDL2@!BAL< zsBYCSXD?0QLhnC}Ay?-2ybRIqpzMAd&?5=)K0UVkFc$efE~V5cJp04Ra<e9k$jCJ+ zbNuZ(NCp|n%?Z3Z>wcy$)OTOyh%V>>(d_~-K*?EazexR^!du;EttzCtb#)8!X>k*( zn)ph&M1HCP#CQdNcX0nD-e%K3>QM87`d#OHqxTd_jHsUXzhq?&py0G@Pqf$aO%3Y} zjl(#Z9Z!!+8lkD`?myt2RB!~i`ED?l`<Sy!kws24&uL`ehnszdnVVY?rUnoZL&LqW zaAOk%kPt(8Tfh63-uXE3rojdDbko3=4w!+(bf?V!1h(K5t6B!<@#5fWXHR=&MO#Cj zVh-ddGbp6C4)2D)!IS9@yMOD7;+<*`yo61wqB-7X@#%5Z=2PmrLH=&fkJS+&8&8jY z?K)kgUN>et@XW4yp4W>*q{AzG9HxK1-%;`N>tw+1AW;LWt|@M3DhgR?m=~cm`buya z`ks9^idU1C*8c&6{lA_ss014X-`OIS*xH2GK_HlJF;y;wUX)AQ<n~y*4o0(Z&bf>L zL7ta#V;Vnq-$nZ$e$ECU@Us*qw6H}F<dDV;hy$?}9H#-G_&A|#S_uOYuj_C|SmIks z?CG&DGTLQ#*wAAziR+Eg&bX`p()x6vM`FYZSWVc12$JZXx>8Twv-zhiiB<Pyt*|o( z=207yu+KB%DHLgmo(PuTL6)l4YA_6}Ynv4ef0`<HwKhJG4?q!Wpy?kPgDD0m&8`m? z;k~|LlMntczRo%*uD09q-FR>k5*!*2f#9x<y95mh8XyFBw?+aa!6iWO0Kwhe-Q9vq z<F1X(dA~dNelt^d?q7$ZtEi&t^s}G6_FBIUr1%)p&kx)O-#(9JPT&x{zds*k|4b~K zE$)wm|BKfOZR6Y<(2|U>Ye$VD$j^28zi2wi@gQc7>aIt<+NAPekGNE#uK}AMFHHOK zVuH*z@5h5bzW{R94<q8IJ7fsp$DZD?IQlD4;oF>R?4_rd!fmxch<2j8xnJ7a&kaP@ zPPYi^sR@j*k4#Q}F?Q~navph+UO0`m38R<cJ(DoZWUu;D+|_m5f;zS>RglkXF`;?3 zIZS(cS|UgD_ZrUCbqP0uArZ$zSpGh7#i5TH@ADSZCmEauR`ksbC;Kc@q2NcciBbY1 z7--wvJYMj(&%1&DXm6S_7XfeViQ{4L?*z&ieMVw*Cip-0d+!2(&;}4Mo-SqvgjbG3 zJW64RMy@i~Vd~RKz1>nn_%5U341^1hE1eL6oo-Ai6VilM2G%WKC*o()-zVG{nJv=N zP-tJ%m+%fC57@}j0PzNar|=10ZlRe6nG7XxAq4>U%N7x<BZ8(}`^dVh-ilw>$kjuI z-{+IPQVAr#FrICwiq*pll9)lTHVh0Q2lC$b1U9^7mL{!4bA?7n%D+*@1zRP_17<_2 z8#Do!Rbfm(bHc_PKdQN(C^+b_cVy@>$7WNXq|Um<WI-X0sxtAI^roCDX2#;<p`ph- z+j#-{Or_r+;rFWQ5B84>tt0W5Dgwg)lo>O#UnvTGRruUf;C&;eK>_HD6@`Y1CeD6; zue=&~NXX2CS!WS8Ts4kW@ZDu5HpC~t!lh(E>`sFQ4-6U@bjVYp;PcS^<LEpjC{yz; zNf14)P^m_%enG~pJOxk!{pb!20Xy{BT(B&EM4bSZA7#Qa73ON?zst+X(+6Z6Z84ga z`-YDy5NorV6Z~7tEslQedr}X-10jrVR|&x?8&=)tk@70<pK6QaBo*L2qnv*6;-@$K zaS~cvJ&guYMK@XA{fwgnr^Bss<$rv#0R!p24r>&uNqUU;ICTsv6^H!liW{e{<=+L> z5}TQKkGj0F+hHCGXEJDH(egK-IUiy9y=xLW9@1(aP*7`bSj-3MPI^J&ae@fCzVgaU z^-5C}UA6wL@fn_&p{IQ;m_1zo8Z*2-H7>LpDFF3LsA?cDBZuZ%=<EvT7YFnD?OX8h z4*1U4y2<U>;QaI-Dok0Zy_~Mn9uCyrbLPsZ>sdIq$%aDPPBZzd=>j<m;=gyCua&TX z7^uM?Z(mr1$F)i2*xJ&{Z5m)^)yz|qSNO>q`)6lG`w>Z%Y*EBLg#dr2IaOv#ftz@n z{GOosfYqR?O@H|HEAB)sOhQ<h?V(stq8brWm52uGD+lTlLg5gdqW98oGz+ZNo>VBe zo52`wKUT+o6mq-#%mv4;7j%xwb-PF~AbEyIaJvPRpwWJV-x9geE;2ZE=(sy<+^^{Y zp_s*lBH!R4*ikm!X<SYzGtzHrF7+LE8kz5r0fUt%+KBu~=qVwH|L*$OP4SO8t|vbu zB>4EN-pTikNJ3cK*PL=H?`?wHE*&z)lkIsTgP%0g-$_J(4&{o6?U=Kf;o|XWbJe`5 z5P*8W4{Jru>S;PIf&ZoxSG{-?H+n8kse)Lqj5M1WA~`|CP(VX!eOfwG??;+mG^tg8 z!12g?+8Eh89}r3puR?KHi#4!3+hT)xl@xG)nd*Wc_jaRzvw1{k^oLp|y+r4qazGI8 zi$|df`*vYhbC^HM8#D!O#GepfnTk1-V}Vv6hyChd{!s!MpLO%@9T)?9>#pbHF(Q>U zOA5!!Gb*1ET4=n%;OoKW+I^&tLXE9>Sxa?iGj<}g>mW;2+2>c@8?Aeb8RTu<29auC z`&{Cu4kPpnNh6QD5{e^Jy1qVqi;DS@Gg|0gv6|<<cdq^Ww@)u|>{Zu+BgAt0C+17$ z#D{&HWL_G_izaR@mwYe=x3}$lMGi-cPUK$6gLDFk9;9coev}IdDcnwSZC>~}D5!F- zHtkfylJ=T4)i(AS2x71LS6(@pJGw0NHSyVRLTxW@Ivq(*gTX=^*jT0{`U~;Ip06mM z02yaQU`g{92F75I8pW|Y4<n2YeaPfO`9*9I<{70>#FTOBt;Sx0114u*SZ*+@1moOn ztF%^e!uY50%L96D#o2icD@+~UjNV?TuWY%3@Y!2<tY!xQz_l>SY}2FX9HnOPp=^}* zk1yCEO$Q{OOpt%T)Dn75%aG;R({`RgjjE7I=QrMUi#3Ie5O<sUXNrJPxNBNDK^Sid z<ktzY4|dnYNC@yT82sZsF~_KF%GBBbvzbkPKy$SQ3Isnf?o7|DKOh-3<E2dGDpxWP z0h%o^?T;CwWn0s|-772=F3Cx&vRa{Bjlh7JfF9+)jjVYG58n}AL$b<HI!BD}Z%)zN zGY@&*2EX3HA>#?a8D|1%;3m6~9xBq{>wc9Q!^)C0#ejiU`%Y<P!D)#FOLZCxEzXAv z!w*NMRoE?q#5rr$KTS#SU}0=~%UL1yt|+edcr?r<6!0CvF(kxRGdv)^4THpKI}LuM z-)OpBl$0-J00srA5XS-aVsCvhQ74rNxR?}Yo1u{A>GKWtNiJG$X|-e%ivEe)T?($5 zfAhoU{b*b^=Y?KxkLK1JDvzn<kGKEub4rEDLq=5ZW@`jR%j$Xu1>P~>r6TtZ@zTY2 z-&W#nnGDp72ym!QaPaTz@sQjnq^7XtW8;30UC+>>W-)0#%X^*_^L|8_QPu1`#b!Pt z`<}&|WK_T+ezfU~bJ{UJ^L_xnnW+SX^7e;&%cE4|2jkG?dpDLM3uk!n&UU&@>nlaJ z3cSsqSSHE7dI0!|mMT9AF%JxAXey82F8toO_TT5f5f9K{Tt0ceZ@DumrCaB7nvXz9 zdW1W80Bfsq96E!~+Cz>9g|ZBy>za%wYF$;n4S8x~VD^3p5O;r(=?meI`ylcd-L=Wa z+B%d5+31akLaY7zc39{truFA&Y=5aJ!`BK_MRqd(h;`NGg(U<TsADh3$#napssbwr z|3>!FLP~Bf90No7n386e$Cmk{Z!*)JFDbo;<f#J;@4HX0%HXrr=T@{x9RUNh{~65- zO!uW+1}h-qIgctMO|OQiME30d!)mn4x)Jj5-SB6Bimq7yb~qUa-(z?(uLm;z&D!-X zBh^4tedS*)fk(Q{VD!+MLm{~bv~ZF4K;to#C@S4@YnhTPX83r|>D~2pyzt`}g&try z%uBpj3mf<OZ~-8B%ywhGQnILk0{G+t4OR`^=f(KVI&Rp^7UG=J_`VZG#%6XJI1l0h zXDu24{o$IGZB}Uf>Tc$)Z)ZKDw@}qMkDR@Z1KpXZ&gHi8J)(5{F5qxqC+u!WWgabz zxPj(}qGlB8qEo(T=wbvEDlAm!jSoG|^QN`$a`slai#cZduDc`Om+PNd{&q`rTYj4A zgbCpzn|sFI-p59&i!d%Yv<H0MM0{`=x?{pzW=zQj1rZ1JXM?>xyRPTq>Aqj)rc9ou zdEpn^eV)J|R6=e7$O$Ie#sd0I#P!2y@Ub!o|2IfV4Y6G~y0&HVro`$M$?3wE{%56v zbgb@|$MElc6HU@qyUt#2HqX@*)H)@vuX&oJzrTt%Pj_2#1M{dDuS;CLb7!QEXVG7v zsPDd;-&uHwh<laxjPDgvCg7KrD}DMg?*<u#ccVe>FE*TSE&t}q;1r*<?1o;ee2^NO zSpSL@1d<APAF)x}4JcBanZD%&_L*P|qO*UdA%<;l;oc>5Af(>zP-(W-o1&23*8wyQ z*G=c&(WvYXP*z(21kvtPPV%>_E>6EHw^2&#IGdOQ0Y?b85U=kfBz%49Mn=kUcU}lb z<)hjE2xl|mIWZh>`-%pcDtHEx_<B~-ygm8tteeO%yS~&@05}3c&`>edz|Uc$fc7u5 zo3^~T3--mDnf5i<Ua+$_I0mRB#8Dt@4<<1h8a)~ZrC;1k@ev=m?O3^dFaADl6WccA zi~Oddqfu{TGT9+V!`p3VCuK-w1McS6YsSVE$SRJn-k$u$`*Z(;0KB%HZ1*#foTKNB z<K5LEr_~IL>sA7AoxV9AJ62_{eZS))^7=LLI2*Azjnd=IA>S<)E&-RK^qNumczC!n z3JR$uo52AYYz%OQZ8$suC5F@Nj4<-(!<xZxEL-U}UJi$jE+v4vGnJ3LaiiX|Bf`|( zDb_sBeA4FfG<hc)CO!NhZ*n(?2Zb2*373K(V`!_~{&eoz9@R)-EHf0CTD_yz3tcIH zdCP69qaPp;2C#1%xS26i_s=<HgGI6;*&Q4Ccx)Dw9O3;ozXeYoHjo1BRlI}s+rAq~ z8Lx@d*$lqYt#JNUi-C+^zxDH@!wOx$G5QUJMVLk!_d*hc)COK7@CSN{YT4G_NF*5h zr34bbCygiSa&_IY917)$M<1pdt{bmKf)wPXKRpU{nJ6JB5wOeLdQ)i@YEwicy&<-b z#)^~R`n)_C=j-ro!*U@Hm+z@&ZMA!gaOz7s@>)CR^TP^{G#+}Fr8-vMmMV*~F3y?Q zgzSp<Ba&P1{?xMA4DwdZe{Md5SedGq3^2C76Hq@ZY$rV5bQ+Pqt<p2w(Q7-R6uQ$S z85q4fh=dFBnl3#!J(iGlXsH^A%xN#~C;D9C)r7r3O=o)-{6+#@A!%s8{hQNC%IlZe zTYaPx-*yEwe&$!aPDdY1!Td~OCUDoA-&lOr=}M0Lm!#1Sb0#{m!eGlvVBfi^Xyd(R zgn`kYO>>bgF0BdPH|aL>t!GSZ8Z-IcZ)Kx*4R3W-*9CfWKtXIQAb-pMTT0@)A6NbJ z-~#<=EySRqO%dC4`=jrGWHJo=0o@x$^lXXkkXc5)W~}H&G6jqJ#<)jJN-SjkhA1>3 z#igMi@T|T?zdHEY?qeI1?D^LUgi)vg!tkI8#1@lv5El3`g$l})nT$B&17S?c;6xo5 zM-3Y~1T_u@p#G3)MwkCe_M!jk<)qmxo}HW$yJ*k}(Y^nRe#hs2oKs9MX|W2!&cyPu zr%VAH8Q^*%;T)S>teRAdUk!X$+REZrgjj;heK}BsNlHltvFJ994R7E;$1r77AsB0= zV%lq+=C!Zxlos9Uv=*vcyY&-Zf!Y^|#Y7}UYsZvKfi&NmSCH{$X52D4L&TE;0D{Us zShuN5CIBIQCGSK(1!Rh?$Q8fN->WiiU!>g7Bb4Y_XvP%lWeQHvAkK%&ini7Z9pmeI zyp(HF$NP)>dSFL9;fuVfx@|$Or$Vj&IJ1{!W|llJaNSWJX&^;G*C+qP5jUNK#XY!) zf9A@v;gWqn`C~QgBMu5!rm`jq^{*UQY4uAlLfFuUN%_U%?9aB}b;%cVTF^DA0_8x% z{W{Ju0q|g%kEERK^<985Dt!^+0FCm+<m1sDLS7j}1_(%vjOj8AS)icty6p>cRnLcE zH#&5p5)HX<D~~-C{o;0{v%$^~l9GR!fR*Jfp4&SD0O3SbzhGXUjpA}jP%boR$4AM& zt8W~nk`2-vfzO{zAK%wkZUI(nE-jmdngrZh*Q@UBN+q0O-TZfk-kb=grbHj~Gj9VW zP)GU=S)iZQ*oNYC!E}z{Q}2*OIh7XisJvYhB8FVRajxu3RT|*aQSc8y&9PtmtzPYk z;{kY}K}!4#(`)p*?IBd>_`R)mhzm!5@;yFlmS)dJD7y*+{P+RpFPWn>fA$9<(ZYPu zB6rO9q<{=jBe)kDf#Ks)#>s>ylV;sP+l5s`4EKcFnIDdt6$^|qAJXoq8jO~#s)A%G zDIfqZxY5Y581g@6F2RNV%sR+KlrS}{ccFtMqkG((sko{OUii_=RQlgQD4x3TUxzKt zUZ%H>v%Y~&_i!wz8uB6rF`5&b(e_Zfx<Fq3hw1{r;5#t?7Q2I1=_2^WoRgr(8v~Wj zWDy*<z*S9VPMYVz=b1?nu(mr0KPs%P*<ObBgaH*oH}OIwtSHbJnv#gm_JTp><TDRk zWc4;>d6mg)a9df_Y#AFWT|<1Z0mBo$G5ZToPYwl(qW(SsA{<jUfVu*c+~M(kY^tv? z>BaSvl&=;3Sn~xqKO;)4P_p)<ML`(vLSbXOGb#+6V4U%Atv?!^HsTrPq@t>bqekGo zx1{Bi{}w}!<Noy;N95iqa*cePJWep<+5^e7gdG$>WE5)B><tRa2{kQWOW9L*oHg(& z?&|3wy+aA$f5rOYb>nLHN^(i_ktdUW0rzht_JTlW(ys>Yd+A=2C10>Ix0lLhd+#be z!}ru{oCTc3*afB7L3qY><}Xu>)6Dxg2=Hkn)>019=lzUYuhoXmH36vVIjb=}#l`sY zr#($o2==}(Eo7Af7Lt5?b3p^BTFWo4llRk1px=PN7a192MD#g>eTIEBjXEiT;Fl*t z6f*i3VDKHE)92Aovy=d^W^2v5e+Mrk*c8UE8G*hb&Ht=Zs0IjI{!QHYu||w5%I_WJ zZZDxgPKdXlJUO-k2#HW2OA@oKg=<r;|3c7wLs`<N#=L&Pc3<H8U(PDO;>pK(gT?4{ zAB(4vIFB<Xv8^(tQ337v&bTxA&G8yRw6n9-`*_uTHPag{(NX!$++l%R-CUn?Jr5q~ zciW*ztb`6Qa&irdMBJY~Uql$CQOhIp&p31ZMeXq8{fpL2DDY~Gy+m}jGWx341mcH0 zpO0$28k|eN8WqNyu^OoH^si1GSQWU_xfP^5{NY$_U{;`a_Jw3I7P#EwY0L=RO^O1A zMnje**J`xmp9m%=Wv1o->%Tf&p^7U1aXql})r+3e&tfyIpL%QHCn^oUxFe%Y^i0l4 zIne>8q)Zi0#q$8M4q6~<S+Ml2!n0Ri9{c-G8iyREr6U|ag_0&zItDjic~KXs^=s?s zJp7=EO{$9<F#<n=piLIKOo21GiD&Kxq79OmTM<#-^OE#Bniw}D3KH&MdF*}$T@}i> zu?-=5Y`<qGlB+AR=B9(0Tod^+l)8EkZ=YfZpvs>?7~IQVo9$l0o|z%DjA^8w1{hR- zL1GyquJcMimS#>BuRy=IZ}{?$-O=UpIivxqXPL?_KK9H^@kd&}r%QBU;!;A-_Nzbd zOqOGJcC7#KzXc)DVzGC?p5w%=c)}$`F6DNM@8rJcS{L_$M{A_I(Ir#@rMBEiH!PFf zei@(y8UAF8tzGf#Tw*B}i0Z%doP_-fo>BnPpaA#aLaG&PEI4~#`N8*Ny@YG$WI5l` zKXy|zs#`i>wou5+ClBD0-T64+Dzu-?+^=pEz!|R@bSiP3SrceQsA#Qt{%+R+un?UJ zvq9TGZKxCNs`c2eyVDJ_rJ}nk#VbB;Bql4sx!L!Fc4TSLniwb*rMNduM_ou;XXyz8 zO#+o+-e;%HCudf64J+c9(A9v!IXqFWAHpr07W3{>O1I!>4LMS#ZOi1!5&B|HFh-7I zLOdh7SnR99e6p(x=zLh&$m8-FEr|OD9Txc8-5|Z)NfAMac6)A=Xov)h5?2*7AK*kp z2I$O<2w|#vR_uUtsD2mN8;=P+AG#GLYeDGOUQv-eHYrBxZ8qT@w?pOA@eBzhkfI&_ z!8YACy$1yWb5<rcVWBxtI3^J*jVcbwXK47Nb4TmTU|eqrTv|;|BI{?`)?+&|*DIJK zt_9~<IMBMN<L>}k461*A+-LK#7Q_Er3923ZWu4<Wl@Gi2PnHi56y+`1E+)S&x4y`m z;@9sgoPWK;x%tS0a&0CooO^m5Ia>d3MA!crtpE4V{!cAvbqq3r?w;d#A>$6}>c5pz zRu?mxtZHo?f8NhAMyT@BuSAH!<CJ)`3O~PP(ue>BnfBqt_-U8^G}ONTJ)J)>2!?)n zR(h7ZY8@7QAs-6$3f4Yj56^mV^S*y((nUq`GKm3{=^KdF(|F57EW;J^)~qhfuRc=6 zqosd`Oc2{&T;Mt{>o;wg--Xi~$*ud_^LGF5jP|sKE%y?tSG}q!UHs3WauTg4q-hg| zugU48k;kC9UjHN(4VaqC?tcFhSEQh8D-<q$sr>MTn}U+^(^Zu>7~he$z<IysFpSZ2 zB;o$qj!B2x3m+G15l?4TFvRo{3;IPBBymMP)uPLm&g1m+;BS3ruJ9{>Zv15-JAZQ| zdDgv3RWQ}Mq*5_&f5F|5#(;>D`aKa2R%f+8tHp^QHf{i?B6~NqYl*T>l>H4O$atKF zxTN$NUlt_M8&OMYcO)-gmqwn58!<|XTQWUy;&GOJ%!LEZLj_6b={+;4N=?Ktj|I(- zEjGD!i>FSCBS0vAh#c$@9+czQvJ<uWa+~C&+TLu3jy|;F#j2mCdSrs#e;Yh1Rbk(S zkUHprxLdxumP&icG|2kIAj7tzO*@!ZK-Z!41&YL2CtE8^!Z2|upT660wK@y$j1;#K zU3jaJScU8G2Rq&u-+pT!F1U-16VV{kCAYX6HXMn+s0Tra1%>YrgKXs2M*{C`PRP$5 z1;1T-FN6d^o_}vaw|}OFR{fbi5v@iV1i9zmke#m`J@=8Y@J{dQj*pXS>a1;f+y0*{ z0DGatyQkGmWX_Ecsu7o;F&jLGf9sjkm}VQf0N$w^C|YR~v#HQs%<r3khXx4@uRzjo z3iUWs?Lzuw6nFuebaMnj82=0?h42xbT(K!qFTS*(Ym^(DAhi(LTC4p)qg%A^+Q>NM zWkdajJnlq+Gx&bgX@+AOS=WRtEmYI2EP~DS4~tWCiawm*WwtymSlm)b#o*BJu;!iV zz=hscMarT4UyP1!KA&Cw{@jgBr5eUv_p0J6RUt=18{M9(BJ%-BcuxLRsSm9CghMOo zL+(Q*>!cJlTv3pHU~Myn=$lK*YmJ#xB&NupnSH}q_beMyOg|LH9kn1Ydjc!uhGI2q zep(3)sCx`_I&G&4^It~gJVYn>oTO}wKPEArrZ~Enn0zMLstmu%aT(#9u@LKPkY7}1 z@Q~Z21^HKytkB!e+~;gqqo920i1{yf2$Ynx?s4|cbO*0-b3Z=h1fAcv%3)PV#xg!E zrbH`C4-0a$pXBGxwI@z2+IQl^R>=zx@4Qq<?4cN>8Sf=dRf*l_()@;yvmk3XAvOU@ z9<RP(;KWGW($L!})pbdsD3;iJXRN}LscNyEdLsQ}pY_MUxUmLEZ2bM?4+I@#L_az} z2jG!E??^Wj=%;(LISShfn{X!P)p4vI<aICa6i9A=4TfrZr1bQtWU0-psMWUooxc_} zbIG0j<INT(k+I2bU`9L`h^y(2(J{R>m~N=6JRt4=>}2O@122tw7a?+%2!KPw*W`i0 z19MEL5pjp0NVZjoVuE|%%ilpzbXI&c2_oP#EOvIl!b8VfB2{2KK6dy`_OAc&0X}v` zA?O;zduZ!=j);N#h}j$45QT}QYL=<3X*NLEjSdo{OUz$?trrkpcMCB0j^P7Q12f@Z z;k!?mx#kkIXR2bpD_JLp*P=ZV(7GGa^XcEnk<awkW6wD%uF#<w=#gH>0d6mw=oF3D z*7Ms({|GQMCguYn5eA9iN^xM?phrl3`fzZptJKx;Qk<ZnZ}O>}F?^hPkqP8~>o1uW zACoh{zMrsD?KLdsmyF<Bd2Dm<uV2_caC3~nM1@Gn$n;y$_O=D8CT7iWCBvjkWhv`= zS$qY+XezAmX5NFZ1RdAiop^t3VALYVb%VqKLbu4nPc3IUB$quHog=8@Yo%cqUR3Ub z&N68BEeU;aaytNnO-DN}-gLJnAd(<_0UOlt1rxt*JvrNNnNyD!Sj>U%ifV1dA?1c) zExCD)GKSc5fG`*%s1l4vvE!P(u0T+Ho5#=nKa?}7`aG1IY3T(P9m;PWTig=wZvQok zXj}*Q%=|9CJX_BKeEu;MOWXmlY4%o;mY&ja$2XcqEKgpaGT2^e{DJ-zI&RRh1sD!& z>BawZwy})##?AtI&CN;(%G|!>A^29EG8jd8H_m9(CSox`*Q(G6cxap6x7y7Y#1D?~ zgFz_7E9u<^v=pe_oe+MyF0(J>BrlC;d>*8sU*^g($z|z~ND0U~9s1UM<34QVbCmrl z0PQ8Ci+E2$g-D?xJXVkXosBO4q(8VkJoAW{v<k9;2^Wb8DhPZ>jRH|?xoYRVkfQ`M zx(N_aAh^lN(Qu&|vK|SUcaJ_^z^r|qa$`-t#(F+X){pc{db=na#R0jHCyI}fO1EOx zt?g1nr@LVPkQ)|ujgLR+0vHx0;>9~hU)Pjhx>Ba{^R50*g|t^F*w8OCN@trRKl+fq zv1Xu&JWA?RssE9`eJXdO1ZislfuOmOiFOs;U#Kt1kbcX(JNQmd`qJxD>G+o^DHFSQ zCQ3?S^c?Tn4a)hT7H{UHrFLIgJJ*c0+@{`bANkm=bW|J!Y$p3R<_;$b!2L#>kDI;B zN2C}r^P>rTohghCBG=pu*kP2v$BC<CNvo|Ed8IPj9L&C^9iuh$ICK&7S|@s6Ud~!H z5#kCY-d0DUS?UTXP~bDDmh8do=Zr(pO)S$EUyLJJQy&Pm@$(n1!ZJqafX&J{HdndX z*;4kw-%hL`Su)`z>zg1ud+5#_$MBbAw@di~y<{GHXy13Xv#A*=T8qTVt|5}iSv>S0 z+eHN+3ZUqbR6@kl!`Dl9V8R};M!_B-7(P`G@5Eaf-Ghx$pa)$YBD2B6hj)9LMOdFX z^wnz0rafGVLHG&cH&Ak1`QvBpH&FsN+8n2EZ#H(5t!Y5kctRIt_D{y{IF}7u2FClz zTj3f=*8%wQ;uQFGX|4SgqFw;n?t1_21?jlkUr(D80qABzf}wByK%Ikihb{xZ9V$Hc zmo$|Bik}9u)2vWRl%hfDed7P7f^Ws!Y2E{#2FB_c^>JT_%O~a8EPm4@;(0ZNvn7a{ zOL62cb>62p2snt}N&5>1AIz8X5#ayXFMp30=420nRAas2B*xIzDwjlZVPU8&=QY?X zQZ}btEYuh^#zi|BW2_YObbyq34)<)Zdz{QAmL1AO?9N*EWnqa{CghgxR@Jwgc=k#5 zi%#i^O_-87=4Xio`3^*df93Q*=q~q|3G==(%cn@1Sh$Sv<iJQ~;o;>sWkk0Q<QZG5 z{x;9QicYw1<tR^$Os<;}MQ5iT+;7ZsLbsLZd!rn=wU)bNYQf8}r}T4|&tOx-{A@>x zMB&PRlpI5eQFwDrwpE&c%o?%)QNIvB`9wXjHocZbwb`?~iNTK)0i#_79@DgClZ&~7 zFWG!(BU|`%aENGISjn~q<wbren1t)K1!6r=kfq>ZUiK~)c_^CQ#C3CeseC2e%eAu? z94o`97p_wim5AeE9*CX^cg)e+(6h+g4Gurgc_)r+Q9uBY{2P5>=r;E!Gnf}qTfLae zgX9RqZ8lwMDxZ%GcB=ZX#aKSP5vsO(V}3C&*W>ymdl~y7{O7a_)F@$J$hK9>7qQ#R z{Z@V>pG!rQS~!R!*hKXv{(_2q?7M^Kpz`bhBb6UvLM$#ue`<iSku2u#7p9~nm9bq( zxoL!h5J@^T8cry)6LfWL%5FrIM|c%;2$36dBxAoo0{_6FQd)PgUiPt6%Txxp46!$X zaD*B)CsLR0me^V!@7SI^)orl#yqfsI+M-l*(BPt%Fr4_bIXM!i?|J>r<3>DU#Ps6Z z9yuSU1DSIlTM+VqGc<$MNqFk?1WvkS?6W;YLWo>#Wk{o==OfuyI!c`Vr&1**Tl{E` zR96QMYm+KzL^$4la=aMhUA$FNx$=K{WR{Z1JPM_ajP|(_g3LD!U|_)0JQUuCEbbu} ztlVF%SGDwaSd})t##{C?%u`s7jKRfNx}+W?F@Iv1fBW|7kk4>1r}c+x$%=I)FR<1T zW>Y0PJm1q)F-4BQ+J2LE`Hq4f=NA1Svj@?eyAruut4T$k<~KspzGn1<jJ_LKUA#HU zw}S8by#De^NT<Qc$HlYw@fY(GM5E=Nh7g^?I}v*#^-xFpoaYygRbm2}@ZV<5EMdA- z)tSwOJeAtR0@XWt#&iZL)DJI3+@D&vs&x!7tqVV-GskKfHq3rSM!LTHXxE@3`f#yv z@*EWMySTx&vSK%+CM5V?$H4dWHmdaK{Cm&t<e!1~1jFYy_NHB#9P&F)m(PUZg!9cS zAc3`PjhJET^!ujPn`=Mp{iVdcJ%cq|jNqLGRYPyzMB%eBWXCpt^uf#!sw5XslV+me z7M8_K(^u=};Tm0!P?fV>vXW<P!4B$q7E;AU9ZeGi_9*0F*|z`gVbm-E;cU_lH0BX5 z{sDkfr!%U5kXC)t{9%o4#PM4{FS*_{%ViB#_5`-PCvz1vB%Sz5TFra#yLe-G`ucz$ zo$%#LOOyaR`a)!h!kLO*7`Pq8Ps~#2@V2L;9V|ZlDCgmeMNffZ{fINo&%atMv&Apy z{V=V=Y21NgRl>XEdv}<loa{<XYNzY*^%J=?v<!C}2HFlMeYs2gvtN;|`OC1yu0yYu z3>2d=qR<~CGkH*D*x>Fjd}oaa_Hy2SxET*bAB<TANZt++w%pgv!cTvlEGn3|Z5A|f z1uoROwUimA>x>ao2e=r4xTJL9JQcT`6wE#S*4&qKCXrgv<}Z0%pmV@l>7e0&f$4s_ z2(?T&iWj;PSEt9g#OvVJAu-MrwyCAftQ`U^3iAfn!#9mPN0-*?eFA9bO@GN<Sc&P= zl@UY1B)Q0lYn`l%=gqI^h}X?sp!^p^mQ(sABhUBdG943gW>h4*!&5J?&Mp_Gluy!p zu9EO|1zwdT#l*O5z|>F;T_DdQUJ$qJn>tNJ<Uk!#1e|^~U2cEurw+LveTxL7(w0o` z4&6e-7A_mUljCX!-AQ^R$&ifs-CBAZ6yZuzd8;)eODwt`2E34uHt@6dPIwywvfAEh z@BPC49W#Gy-(9{gA}d~w3>WS1k3r32u2D_>z;GVR9xysNVTs?6V*<*?<Ll>`<Gd1~ zq%RY)2);N@N2TlEt&j^yd<Oo6(t<@Vh1tGMW50Sz(ghU(^z-m9rqb3&PliI7Hx@L3 zQ^t8!gaGt|F&n9QrRYnU5@2nQe&dsu=L`)c#|p+B&%+gj)46EE6Ga<1Vy59cJeTzb zswTbKE;4(ivr{r;c11UH)y1<e&c=+=Gm4^HF!uLfRcEs_@l?oT*Mdt|(aBDO^EG4V zGSXZ(I83||pEPjAOocb|Lt-j+%xjhy22G=W`MMX0dB@4e3ZJOgxDNN24Nlrt#8l+- z=`sYymD7x>Bh<8+YutskWigX{3uSRl^TU@GlwG^Dezg9nd!=9L$^j!L4&=Q>3r$@e zdZzXV&y;b{^!+cU9~EFpu``%ehK9Khi=E93A5(HUEiz>&rzxkk_f&MP=YR}9-kiMD z&;E>5(V5Sl$_y36LO%SEeJkPY6Nf0anXE%A+8*3Btd!V)Rib|tB+baSD-+fDLW8uo zk<DU!_xLtT+&Zi~vl8E(Xc=MnpH=;=U+r~9UbmD)%`&{5Vz(cpGaMx6r`S2JU(F~p zp7fs2w~2PPE-^-`&XmidT20IlMMnfmy6wzxdw<D2^LFkPtGv`m69(?6s76U=zTAxx z%SkoRmgH8c&ZOd~ZqEa~2`LJE-nd$~NArIbBWqlY``2u5=rYvlPw@j%4gHj)=*zTy zVTMi{Zzn3u3e{Y8rCX!zS|56Tnf0c+{;V8nhOowZSZ&(hUN=8s<B=7CN6&<gZ%bcJ z8(m&hQC%KPjYd4kE0DITkK%O+J>DLdae=qu1t4Rhj$QkXE6r}v;TEI*cYUIFRK(kz zk_qPNo)T1>*~fGa2wiyph=^ymk9NE~DIMuC0V$_l`U7s&r<sc*q2nlytQ94zyA7>b z#k&|>ho!`Kq^WD^Ze3=a4`>HWcSn9v)@AL%?R{6x&yM>Zo?7^XPdIw4;a~OFzr{pl zUmXesQ4D<C?QF)m?A?+fvte<2*eGov>&Z(jE+mDeIXy}vAP}*VWFD(vJ(t^@Q#>8g z7_{Aaa(wqF*Y#4Bcw0mpwINl^Dn7@B{}YPI<omMEBf@vy^A>PQhiSxjabbU#DBTyd z`@nyy^ysZ_Pi~|@y!UjqE+z-CPzs0af0N>`AaeIRk?Ch%HFi{H$;Gg&gRXxj+bJ4u zoIE^~)($k1y2iS=O;`IBJg4tA6%oGh=U2y!VE((2k&TRm_tMX2AZeoT+BWm;ZOC2Q zq2FVy()~rOTB^rGsj8F8NMVEb1UOT-^0VXP*8~ONNGL2Dow>VL=F_7PC36?Be;BUq zPDf4}a>eDJ{b*euA2xHReXM`iSE?$)73)$xP(&N%9*#IzR*jg<!xRo0m64jcg|9pn z2rVmN4kKSL>qL-xdz0?}(j&77c>Yz#z*9U}^d?<xvd-Z}{i<66=Jm|p4(-zLmTNe7 zm!#cxhfk~WqU&^dX;n*$bLk$!RLz9~yypLuH#uR&7IKR#dL=b)vbxNi+Q=iCIUW-% zLMFo9Gma4wp|md8y7r6N3~`a4$&_sJf=y0E^mOOMsJh`Y`Mzn?8Jbt<^;HOBn$}$X zvE{m?b$_rpI$&~AJmj9HX-YqpVAcCBvUTYX+bwrMFIDMu)N!~@ZsWP&f8GcG_qFi< zd=$Ykrb3V<;KS2ke~RkM2Tmbf08LcV@-aE_Wj=7v$T)t3jwAS*_z&CI4)zbC1T;y< z-w>lt(&fxT0(;|k{zH%3i$y|-z*+s_YKCG}QE@O^DLgbGpTlOZ-oQ-C!c<CSnH*m( zJRrJU)C%sS?%<GVYg-MKi6FNap8nH#)R4?=x2*SSH<4MB4R9pxKp8hbN!j6ISod8F zFpqN`C}k$$Vx$!5AqtQKa6eE2o7sn0Grfn(dkd5$4A^;l`F$tM)6JH0QeO9Y9X7kQ z1-}Mc*PVZUC3z8O4;{NEJm4Q~Ecf=|yDpN^OyqJ?(SG=+_PMS2m~MpgMq~2CMWmp% zeb1Nf86Y04q!l_A;pfvs=Z7Y?Us*3<9E7iR7KUZ^jtE(4E);9oO1tw?g$sx^3He?x zxfPz6tS;F!9tPg?t&k@HNcBvFUP9<Ae#J74CK3(W<Q>eS*xwyUE>L&gVQsJ(J^g+U zIP*=5o|sYozFO&BFzFd}DMW`)a|#3461(_{{U|*dxx;nQhEd1@1vv$&u4KS@5?F<3 zCYbwWDbG-PGcmgc`PlEofQJCzHRd@_HoO7yt8c>W<=Khkd})?=AX>hps)N1#YKl`S ztb?=*EMD6A71*Qbq?_UeK;Sd4%fyXS%UU{pWM&<KfgDs7+PD9**h)|bC!~%ljOwXI z=EJvTX*B74G2+MTW1yQ8&wCdo7_pfb*zM&xTC#^<UA|y;P!4ayzeLSV!ykv<>db=u z_l3A(&@1r9^6>dJp!Ivg9G04{xj;9#XqZ*bt#v@d$kG_Bp;0i4f?h0gcjOrNCMmO* zM#LRFWP8xCXCh>4do}*7xaw_gYX7bRCX?B|q=-+E(syM+3-zC`HaIWIclhf6XcSId z(Ds`CUNKGf9_agxL!w<e57jom{L_0encfl?-g`C^3_;Mlyr*)9>?bP$wNG2MekLf2 zhn|cdnHq0?lSS2X2Fz>EV2Rk3oew+VA;S=uYL`vx+??xTisgGa`NcBagM}ozz`rW} zGk!chuDClf(wA4(oft0&8<Fh0rxeovn+hw&(<%#>^C3>T<#fz;Ln^&GYm&vajMzGt z06*9h1x31}|3B}V@1G$pMhHlk$O}LSiFo5C@2aA%hEMb&0>In(*HC}TbnjXz$|QC+ z{ufdz=zHE7=_6Hq)4o29+|ftLF9$FWYc>6LPfghPDR**t@$mZKd!=Fz6vb4_(HcnU zJKlMc-ceRM;}G<-ZdFCoFd5;*N*L9|I8mV48~b<Nn7i|t-%_gYWX@C~5l&DH<bpLS z-?-HC<R7LVAE@o(hQG9!^o~^A{`?p`=6ay5eABuaNVV@Z>Lc0FNjeZIBAoqwO$=@L zU@j8<sVZN?biGS;V$+m#x^w{S&+*s!VH#1ktwAP{awch+DT*;jZtg;WwjQC&DIX|h zRl<ypvbp5FQGK?{7(Y&@Bx}NBX_9a}B!FLWyg+6fzl{hKkUvTFL6lyuQMIlV#2ivS zWj^9R{vhpT*s7@PacwZ+-gT=qA4ES^#lYK8!W0`RZQbSdiIOQRIUv9fOK{Q3z$1KR z^?F(f$gkAt=sB6Z3~aq52pp;}9zOd;tXnz+_7_Mr0eQ?IkK@$YChyyh@yCae2`Lz; z<x+ZOxb5wlD~{^BeiaEnYB;y!biMeP8PP{_z&WXQoV$2jmX-Dte0Ehg?g*!-4Y@iw zk#%cbF%CIupp}|b3y~b2duP|rr7Bi}7x*)uR*DPgr2K+f*b{;BL|AWLnRdNkF6Q!U zkD8u>o5j*1KUn!eIP7wejR8H0pUnt+L^7MMn9WHgqQ0R?0Af#ZhX0JQQWEdUER>~E zH@OC>B-Vu}te1+Spz+%f)+e;1oZ$Oja>G<Pd6_7X-3Z|5)dRrrSzmajU5ms!Csjom zM)w42F1zYCDl;_Tte%uYU(t6eKaUWGwXQKwpJSeSIM$~PD)lDt)bkdQv0CkKla+o; zeczU0*DBK4U_OhV;{0kToo!_Y`HD}rh1&ZwF#*qdS*J&hwon1vQelHAiH*J>r0EpF z?D*t!jfP)``}Wt!fLi++>hiOVm1na;O@Bk|o%aibCY>lkF7I#6&!#pagLhP>{7KlX zSR2n8PJUDGjybk_n4{#98H|yi{h;lrr&SGgdVTAWz6*nT>HlT^3kK88Qk*^~KsO-g zsGlV-zHa&1FrzKql;M5b4d2{lq?}#~;Ei^gc8H~DPx=2fbN_UBkABo`Tzy9Ph9Ly_ zf^PE?e3cr>N<OpEg=ht0J5E3c>Os$3X0-@5?!@7Xlf)H$zf#YNd5q&>*x4AeWeI9h zT6uZGkg_y#KD7gEDQbyv*yzzBxke+ihM-##em%pN24^|&sLwnSkJ3agb<I<gOMYH( z?-?{UjX?6SB-SfBmdjal^jNzkDym;_w&U5cn`7tWS2hAs2?*^B-VrAKUEqhXHv#h8 zdC$#lJ35sdS>^7|Y-zf6efO*O&l#Dd<ibz)=elm%$3U{@;;1<}!XZCGK=zMvdW;L> zeITx&9G~<%^q?HexC|=-^q@%5d#LFBiKIr-&zULk8Vva=L7C6y1#jmM`-$@mc!HC% zKnmlC2wZl*tP3RO%HP{}b3V#2aKrMB32}9pdyKxAm)URxDt&NoRnJHSHm@kkgb}Cl zYGYEo4Dnq+|B!?%VWF%0K9XN??!(%`Cc;=r8j*&8Z^EK*R<@+XF=nG!8GLN|=W<n( z|D5}B4T;^t;oGpXPFx{5yzpi9Khdv4eaodvjY}-Z@k1jzF2~j2lBNOAj>7@{5c)KH zxe%Jwy5nI|>zCGT{(S#StTMng!=KW%%HLZL*4+j67oEdL<B1GHe_Jr#)lP(;`FeB_ zwAc5f5Y4^Ud=Tqc_?E&@w_?9TI^lH(U_#P(eknRQl#}~ZwVcyBA|a;Nwn$v?Z-AwR zF>fS&u~HW!_$~6*{JySt3gYZ*9Gfsl!tC|hP<&}vnli^<e%`&irE@sM5%nx1wA{pK z`*S}w7Gk=5zte0NbFCIm9FygwAQM?;#n7)q<?&noV7zwLC|*P#5BohRBGz051S_HP z^)Jf|J}_0YyRXts-`SM)9;~8FwnnI_k{FzkNA-uQ*qe#n<Vms$lgspbp8Z*Ieutjq zi-?iU?dPFf=yOWM-OmN|N3;rRcWc(3NTq!fM`Z?^nUDshhYwm_72qiYiK*EBc@$1n zB}XKCMn-Y59;4My)~bH7vdPNtEB&p9veAB?#(to9I0yoO?>>2wcv8*P<D-b!4=dTC z#klv`+N#Sp(Lcx+ik6%qk%9}#Vh{YpWKxuz9y1Aou@=IVV6f(YeZBliA!9C6rCSR+ zEeVXGDa`0LD^duz*Ks+Bjd*klew@w1gtHsnt+S~Rtg0fziA!0VO{ENDymK;zbd~Oj zO8sc=ccno&2;@jA$+bY;ryx8l-#kmI2OmPja{_;=o*$PlTB<(P$L->EO8<JyOG9^h z#TK9B^t11;^j>?B3ET}&tW`cb9J!-}BDny$1C6s~c8Mo(sX(_v8v5R)G&E4ZKa$_F z3<$9a6=Ml089L0<x4VlKQ@>k97Y@#?$*SX7LL~Tg$($a9o*a7}O@z>P7JKAa5c$-( zK1wI-NPh1~w9~@HU?0&zUU<5{v-Pl(nAU&(Njx7Lt(fTX2(O&L=d+i~R<`)>)2SR} zq~OA*=3`2dr=vxNmIdcnW#0G~em(^!>;PldVKqLXQp}kP9R<-Wu#QuIZ0Pots&Rgk zZl7J^X(>l1i0Vo^odj%LEBe6g*fV?9y*V15qwqm}f||d{R8Xa@PV|$SS%6jfC*`mr zoh?|K%DUuHt13=@NbYcG$ZO&E+;7H0&}6Bc0xotJR|+O3hA<ds+-F;lX3<%qk1tIk zvE$((A~wp@^v^NzL}MD*@gEP5eW_%{VB<j7Hs`dOA-R=FeckIgbR$|ahK<&fo9bc9 zZlp33YiPKgB5-7F<^-KH?oAD-MC)0UnYSk?>osuPT-~@xnN!u>P*JsOIx3i(x9SY% z#l)5Oel>;q&!CAkY0Iv`YW$wt!FyR^JH;q`(Yi6!UW`^jiJ`c^I+}@Dcf0cRxM5#F z#XTv`!{)sgo6C^E>1?i+LrmG#uRoWWjSREqKwZ&$yu(73jhW6|y2FWjp(05C7t3}= zjwF^rIjphr%00vK`q@bPTC4DfmOI;;rbo*v$(Q>NRa~QrKk8yhz!?7Cd^ZnUI_UHL zqjx|D@8VEuj~;ZxT{1c3M5?vH<iY^)zAI_Gjvq<o!%OE#wr<dMw`g0%2oW_wa3|&W z_C?#Fz~c{VRsaIW0}Bq*%9qrLm3X25sYxP30h07G1;n$!QdDYH;YatGc5KmYVjk{k z^CZN2T~U)JrPoFI8*dS>i#Qei1{7p(pKc0l&H3(!wU7`QnQao0nHpq?G*Z;s8MlF^ z+Gpq+)T3glL@v!<$E4)=EsvIe!YDoh9awnKhgyXMg2Bm0DLZqGBupOlNSq*oG#Yj| ziM?p>mh@Nkzj@KZms7Fr8B6Y*8VK^Dh!;P2_K>29qA0@PFC0C3^d>Pdda*^d2d3o% zC{~nlM>8D08`VCTr+K`Q`rJp3?zG|oKbk1AaB_K*Sde_~^Rxf?z*2)ttj#5qx3OJy z(mZC~wL@&DEigOU*2tWID-_CZS3+t~Xd=m5kdKTcv%vq{-T?9#?7c@`YqMfND_J}1 zQZPbmX^KmBv)0sp-y2Srl^meu<5zL)d-pXQMsxp-v{>bZCneEd<EgQ(YoXnAMGm=l zU#4YgxrEG@xF5j&w~*7h^!1)@36!AAVKDW#QflmAu<b)-Z<?1v$vUt*E$*@d?5|9i zywgtlEE<Jh9Dv|XGAL(%tfjcngIjX@pK_Y*5ej{EXizNG&o+UNFrlMV?~hw;brTsx z9Z!LoV;d~GzS`6*^YTM9HCOAhc{k?HcStuM7=n+^;ln^-E#Q4F)iq~bsZ1LZIOW6q zVJ-f~WU?};g{%!6?1m=xc#+j~@kvWJtWYC&q+x#9bxkmp+u?VUVfeXfX<Bo3cA#xy zE-uDeTBe{q>$;Ok4lYJ7C8OfceV#uuGW;w}cOyawUu$&+x{1teDc3oN5PXYuWEY8n zSLI;u2;sfgE~4)Xu1jBkK!v~7ThyYP@sS1s_&RTV{3#QSj8CZa(c*bmKD^v}tF>P= zXFy?qO~}7v$K(hxU`PfB_D`!$LgV@w??~9N8GbbNXGJ7z&qVU>@e?OZYXFo;%1LDk zkHV0Z?N0vJl2x&cTkIYTR3sObys;)s8`UlHOH=fhjEhwkml(z_;=Fm;EM!f}{Q1lR zU#!rv_n0JM7B5hRE1feUI&XN$U=^PG2`ICO1!5&upZ>|-SEy#8k1}EXG<a(0sufF{ z6TvK@gp_2BYsO7KN!iY9j;4~lZ<Jd5p?)t!7Fu{e9Yk?nJ~})8moD$WM=-ZOY}oHo z>dQvuXULFyZChZtd|EVv_wm8>?SR#5uI)mC`^0)gw{QLCJ|nv^#0A;bLNAWC*TwG7 z`17eTEg@hljA+=UYJ_N1+b*<GQS^RcP3V&U#-d$4sd$&qX~2aDGdwQiVai|V;7HA% zv33Aj>uZkJ6Vs<z(<bX2)C~+Yb2T&sa#gL8#_rPg7^_L&7H+`C<fwY8v`v(;dEE|L zoa}{Hjg@&j=JujPD2E!D#e}|4dEJ+0D=*eKj*zsfaAAwwR&kjnEc<+l=BExDrx=pO z_IrC^K*2}HNnCNX>;}8gp?&XqrK+w>jvwZia%4KFvQTO6_i;=1MI#cq;~c?+A{DIs z9I>Z90U1Zk<RAz1lRu3tBBIWylO7KFEb1mkj*fj?kJ->Ez2_9db=&WO5m?l?T{yOo zWU}=HppR{hGWfo+Yq|n<FJcIpsU<-uDeXnC|5~NLX}td|2sx;I66ch2D|?C*<Y_v; znmfsulA<<8Uovw);b1J9xHa+VXxpx3o#5f9Fo;JE7=}~$yqC)kEOjP&E+I+kAS$%i z8BZH2s=})slDHRIeKYkU^4aWmlZR912=5641-^URY0aL;Lwv#o^{43&#&FX7*!QK& z)D>VM6-K6A*vYKlU$U9g*hn$G?!F|iAwcEa6<JMK6W3Ii`TPhMg%6#6W(Kqml_jsf zeDf6A(&n?@O*i*t_PAl`USij0&DTp}hiNv4^Xk8K%dAA5ci4QH(8-<Ucxyh)4ySU- z1`FG#<7d(@9x-4ntGSWEmm9N2iUmK!T4f0)^?Q;F{)2M3ePdD^O{Xd^k1l|idr{y* zsCZVQ(!%O8yNS53=ZC<?e}Bc2oQimdnD0?}FC+ZkcD6(cjmj;+d1p?yWh#$RYRZ`L z?M{&s8%E<_GBK4Ok)q^2t<*|<={~^gV&pip`LAKsdV^}KPDp$&m6u#ks|f4CW_Rd& zji!^7tm|x3DW;Nr$&2M$o7#aq<9%N=QKbKVIQ6fIm49_ODEP2_=OsD{Pm4iAQ7|rs z*&giVy%su(D;Q3)^_-_bzvNgeK)i`G?~}Kv{>toUb#tD%!+9qnrs?5q_Px(Um%;T2 zgOA}eSkw640||x&95-`AwiW#h$$c=9D{P^k=qC1;t{BI|^ErCqZsx-&)OO96+VQ?T z`TU!!lFlKA<VgZ1pJy;I3S;~=q<bTxGg(LdxM*JzZ{L3R*o3LEls2Chkdo)xS;kFu zHWv9KUt>mZD=J<twG5b{KW4AJg>$$<$K0kA6WGR;mw)5f##HoCx$YQ$uNQTjNgXB2 zqedE`k$M=Jg?}TSSDEOWJU06Vieh5?NJ92iJP<ef_qvSn5i!MiiRj`j|4tinAhLw? z*Iz7q+duf3%Ql{9BZbMuh*bCHibrjMQ`O}CM-Ksyvz?8|opV=S8bgr<&wU%y!jg|6 z@beTZa<#TnXsLh4Z*LxQKMw1i7^X|2R(?H)iKSWHLQBnXFmLeo(CwOR@aKwsZ^zA> z7pmBYv@&6NdoZ;kKz#gx4>tbR(mM1CEZ&<v+fino9$mke5}h3r^SoMdhit8AgNnzq zN>C+RNT6*+F?>T&&^79ebE(;2g;uH&Ve;@!zDO}bSj4bhKqiY-_;holx+7ufzyZ37 z(APylA%})$b135=Ry-^BF25^xiQXM$sqh^%7+Tmz&|?z_*}vDFzoeA@FsFKK)lk!B zK9yH=qxm~ZWLAM90&%rp$~gslTym=rgupm@?iC4FU|A71f9J}zMg&L~s;zQepZjQB zv!&`-b~f3w&0NOk`oQmRvYM_CR`ckZfeXdX=fj6Q706_%0jIQhV!!u!J!drokF?%P zY=WD`PDZ%C&t<sEHMC%1PKCW+i4-fCwdNJPn%mHbmJ2N#gMQv?_RxHLJgh%eUwk(r za<QDTPrX&wUj0L4av>uKxkG8XH$3DA#$onfGzj)C$7=aIdXJdHlbvuj@{@@bRs{p{ zPgJ%QYg|b^CN>L%H%fjnvkR+Rup$bNzKT=bdH11{0r%I*D$ZuxyQ(7RwJpDJ0E`=y z(!gD*=Ch<B87-4Az6bM1QSPbjNPo@bmKk&sG>{86p;~c7g>uZ4v-&7XSR}7d|F7^n z;#TDuSV#!3(3g-ewXq8Ne<)+k9g8Ro_QGNS)luIu?1Javf;JL6nb9mZT`7FjIZEOp z2d9E}KwDNM0<)?-{KK7&Y#2!gPTT+D>@B0(4!3pRQYfLtYdAq#TmuAmFYZvhxVuAe zXp6hMySqah+})wLy9K-H+Iy|N?l@=fd(QomjPXzMDerjaoX>pbZ<-Bbb%q?~;RL<% z&z)a|l;~m%<O=X#+BDvQyE0$@30bU><Hv57f6fI;aKg6qPP{N91^3ySC>+m!_+RA@ zM~}ZNgND02-*>TL?|2dYM~k|eWXx={VsnI<UvekxvRBc6tBceJb5_V}tXk`&jlJV6 zh6`g?76E2fwmRA~UTqgnINjFdXjZO!>&BIt(GG*ddt5VhQKt3;yj%L&L*fSuR^$6O zZNB6<$CY$MU84Gc#Gf~?&pxLCK5~%Q?oevyZ}kb1+6z%lR)l+Tv&B2yTT`9PMj;CE z__z<~C0>=`_b_TT3Vdx?VLId+7jfySK-brT!5u)a{LAyqhn7k;9Kzzq6oIZ*_z>k8 zG2?o^L)jr=kh7rmc(w|zL(TT^fwDNb%}GNo3$wEQZrkEcHNtpU6UhYA*+*BKhMs;J zV1X)3B~2#9YPKL^w^m}orLWg}liTDlJ!d^mX0}k9#A>x7?Sg2U6XfbCTJ{Crih^Xd z$O(Hs|GA&OSsk5OX5x~_Uw2h8Q?Zx<pcRM1yla90)w(5BSE(5g#hfefM77F+dlFSp z7yn-P+a=mJmt7<`D5-#AO@DYp0bB_5z9kK~+ai^Px6{sCAQlypFo!e;8EAS~@Mu9r zdos12ut*HpYO!J}iaG_25RbU^na_)3N#M!xfM`O<C94SY&q6Pr(MW2Bkl}kihuhRS z*9{rAQriufyasKOh}F77ko;U|UDHYl`+}>1Q}kTpN^cW9-n=R0IuxN=Jux1|NNkv? zTu!l6Y|?BiTKDM0X{LR<?)u|eIit4z_`?+^Ac2Up(eq&((53M)xG8WyRk3h1EV=k% z$JlD|wF0K?7u)~Jr2cnC2QmZK&~OK*NqQ#%`JQXaj6(SOnzgPsxE@UwpN#8N+#k;9 zFi^}17pkOoDuwItObs%*3}B9IPi5wMp<UK;%Ni-@R?Jjec%Q|JElYi?cBZJ|>2sJ6 z79ke$VNuZHmbu7C_>#GREWcNRqIx1@jd3BOA3nis5YtF6mTORZ#&Eue3h1vt%Sm9D zFpM7eKum0Fn+}U<HsOwRKcM}DPF463t|i84z>bT#zP0nRHvh^N4e_snO?>8X%{_S- zPUPf>5QXtX-pp3C!M><Q1@D$W2*!&kb$-lL&{x<Eu6Y67Y4!5bniZ@^U#)&4tz19Z z_tMLGnHTq4jTPCBeSZ3LLv`viBIXzhig~~&R9_?lV@I1v6&ltP`7{_XMb)xs-6AO& z99?<O-5SCBWLk!{*|2P^3GWY49A*<cJE+kyn^JZojw%8nrlt$qf~GsI=oIz=_;v}j zPqdehc8F~CRAbs_%zi*FM+wzd$lV}$uH8mHejK<3v70oQn8wIlFJoz(ccQ?Vm`gkx zRGFVaaBZmyKth}EsmnhZ>Rt0W-NJE{%c=D6vi(VoIZnYu!hX+hU<e^BMR54#dj5mb zZ!+X;ij{Xe(ZD~IQSFaU<?7QuZYBl}y2?(inNkf`;hI3@4d4B*a50hh<4SqI>SSwu z;&e|gS8bjjr>kD`q8nYBItldojTUcD!(l*pV;vdhR#Yd2h}}~~N+pg62H@5n1cXI` zR5v~)@$|EkcFjPX;B3MDUF9HQiGiw@6qRelh2EE3x}SQ2F)Jn-@;|`$%%PvW<QQGT zSs}Wq_bgA*nGOQa+{-;bAqxG9{k-p4BVD0FWZt-H-=UE;!V$p>GgTe$CCtIbx`b_W zS&Wg0S5yU=Pr_>H#=@Fa6TT-ZW~Rid#)^*{b<(ixKkN@^5k18szC`}Sa@7f6k}D>| z+#KAPMg!_1UK)T3C$$n8v&aJXsU~r%xfHE?YrBNGsSWKxS9tt9m%-B3)r_F3XE5g} zeunV|GYKO#073w8n>2CCr5IG)kh;zrzO(=z3lsa{4CM2h7yVw{M6wv?J@zAviA#-T zmN$v<9~JmEfqPk_2M-hMnW3|WU%kM5lQvelV)+@>{URR$Gm5+Hy)O|HV|z9!4(hn3 z78|9FqZ7a|fz2pPg<dTg@AmESQ4Y)0+Afn|W8swrYJ(4}V&o)fS12f*3Lbx;Zp$hO zgR#`Q%Gl?#9jouqgy*v0ecV;z6K9i9kE0shx#{VFI!QUc^<8y_tcK%u8wsmluE76D z6@BAK<j<i$&SCG_Ds`$pabN^69zTrVAGaCo4C2(#3jIQS<o&>xOYi|4yWtLoFK*gG z9(9J;p7jJ=3tcJRilu$vdv4dF@KR&A_(&h-43W3vU_`2d1v9?d%-RJIP`7u(J_|hC zVx9Q}<L1IVSUJdIEwa3KD9%%sH3tDLkF=LJ{NbIjpPd7QSTnPnca5`*NW~5U>K(>a zPodY<QV;^?N0XbAzjn4OlQllY{~^Ks*M*fCj@7xA80J3bM%;7pS&Eib=srdx500=< zfXU)rRDS3}d7@^M9mze$uS-WkIgAdAD*hSI6Ib%Fvr9llm#sjdKsJqa-(l2L+#<Bu zzlv_7U#aJ~4`KbtrI?GvvXo%=@}xtY>HBXx{oijwyWGTyIT?nMIkm&W#0&O{&3x0^ zyNvP&T<?z>EEeduSpWebr*Ni?Kc~mMS7hxIV<}bJX72;Y?iAUxk}mIZ)y0g1B(UKI zg1lG;1|<`8XFrpXJq(mSBbE}=8<?M-z_U9Wcj3D%z41T4&0lEedq&ZXD8>At*vHBo zK}mjId%S`7(|#lgYZ$qmwB5uR(<cKq?CG$X-e$n9PocyrSDuF*&j_S1h2AqGQu-iw ztvwysbVNt>h%1jzd(3L*<>m@AaTympQBFyIi?SALXns$K#rj6*dwN#Tcqw<b_~zDj ziOesM8(D~h3=_WEQl%GK6uqO@J124u`a<k$hf&N)nf?j#_e|w&*Z5RctUqty{LJYh zvgMTu^)yBdRpCoTHj&<_ptMt^!B2BG0T)U30<Mt6fmw8u=qa5vUgv`vkGWP%lke~? zeS--aXoq$>dt-t*_G?%<7L+OL&b18WIp;jn8o9EVa=cfDWv9Ot{HqLB6Y0-IEtUzb zSG{gxKD+D6H{d0Ky?&NQ6k`aV9@RB)krYmfi#CZ_tB-t@nQtn5l>VNWHK*p%ChmT% zMu3z37T$w~YI5aMOQKlB_9A3?cR&Qs0$h4c!hFVZOyrz+_TLloV102!21|Qxgw59M zb37!72YqLBj_@gJZB@Q!M2}MV;?yHLBW(o_VU`WTl^1l3nx$Q`_yee;=%^MhPKMPC z*YhU2W~BtB`nM6}f{r$n*$5c~P42^V36#|$zXV6e{Ucsu+o>;ldalU}{|c!x=q(*# z>K2P>DXEcZ;u2UJ^SSu4&1+kSG~<USp2G{f=K9hyG6lDC@l8y*)6nOQq@wmYoOVen zBf9n*c*}gj^IJt3q#uY^wDHUj`76oa8EPu>x8}biw(NrI^D>z5ORYaeXM=_46gQ(T zN+>tKcVW#)dW!Psq-^=}(^hoB%B4EIc#%UXLVYR1ZI%S0UPQo*sg1FEq|zj!=1DTV zLeBR!F^UP3?t=<`(M4%G?GjFpeX3nlFCB)W0o_XEu6xWnFJpvGldLzBA&RhWlMxJx zcYOP}DRo^o_7dxCWV(go;&AsuClMA}{6Zcabdk!#y7^R^W+%|eeVu(V8ubdbIB3fr z5Kvm_miG^r7e6=BLc6nHXmY#6mn$iUb}`;H{|1RRpVd@V(jGo_tW<<cZiuV8@I7-& zZDbmFDC*}LY39{}FR+;d*veZXE#}!SKajAW;C=Ki_2X^{$So470=`c@K>A))ScT&< zf|K}E7^Bx8-biyx#lE}=JZy4%$Jt?HaaTFoK_>V#i>)q)4VQwiE`L2@qAwC*&8+l4 z98St@<`a}-ycy+v&aOo4TbMjf{-1h@|NP811Mo6xoEiD~P`V5Q<%7}rVa=!^(bBp& zA$*;jL$}8!h|SbX%%y51m&j#Fk_ZdFigFxnii*uLwE!*@FLa!rhu~{J_0}>FaXH2w z^SX-!t(nW4%c9o5dsb%q2vKt(9L)`5{o~jH84q8=&0c`N<ke*D!=t)kcfjkUWpib| z+ckfG?4{788pBpG3U%%MrMwVFMd3|Fr}yf9<U#F*m@UbaNLA!+Os>6SErkN@X^&x^ zrz`ib!!Ir2HvT}Wro6mEz0u><!Q#G6Ei!gFtKK)~s8a$BLVw$R3{)x$&pwEbvtCZd zR6UU{l7<wS;1`_c25__iTwR@(=TL*nxvHTrbPUmu*F-PFm>q3q+tctl4>(^V_l_?l za~d?`6GjXllHKncH-|a0-}X`IxTvW42YK=ab1?8+&yja^a?G10Xge$15!J?h$KgD` zR5~2%;OJM(d6?Pv9CJD-6aIwg+}j(OM0DPS3@^bIR$L$JXzah!5S+ZMxFByvoFQ~G zH%+e?0p*Cd6@`CfDY;zK$nn!d3nzu-I|z`6LF~o^{ijYne{hxTvh}EE*JRl%VtjTd zj(q-uI@-?@)}EeQk5B5^z~@z)p<`i=1(Ib>&sGoyz3$D#AmR=>pljCo?vqK$BRCi0 z!`*0q++>{LwY~Rs-D7H8JlNx}Y+~RmM%0(9O5OXC@Qtl`ayd2@G`z?>5@R(Tu6QU= z#@nVHU~5$8&NP>Q7{S9pnV-RVyiwh7Ba?ZTwDx$mA#4~kbXHotRIEa~*Wkh5Kl%N} z#zG|CoLM!PhJYLc*C<44YhHi;q+lqd@VCf&60+ajfv9Y{@R5-BriQT-6QUY9&{Ff# znf7T_?L5r}YkV_3g+@#q9QGN9Cb)?Tm-M1$F79iG;n%{8Wv2$diRP=IE<t3I&rtLC z*+GRhZx61EC`-6<yIcaezS?3MF0;vRd`kV;*daG|58FfwCX7i*dW(?na<c4b1xA}a z1o0;H8PXflZ48w=eI1#t16O+6!21&u2EN3|$T%@X$><_U&V-ni8PMH~SP+G#x~YOV zzD&L%vXQHV#^q^b@)@61tXTm%=&>Jkl#c@;2;M6gxikgG3lekoNuMV|HWMK*ljtzg z{vP#GpcjX9eHanvCh0=i3iR6}qOjG|T&MZuEbJ2?erS<|z7DKNo{}0Ti2w~fMgJs) zPC_9|^w>|pM3GXxC$&GjFE3|)l^Yqi7XqQ84(7Vd8HFczGd6CDC~nRq!F*U|)hkfT zjX=sGAcP=BUsyYe*h+_p&z(v~LbgtP4Q_`g0eY$51v+H9hY_<%2z&1Ze<aOppOWXC z)qd<%7i4+N<T~*SF{%Mubti;*Uj6#|?i>Zh!Y}>C>92yFX^didK5z!I-X_y1%t#8{ zca1Cve+g63I(BtP_hgsz_R0HoifG$86SlQRA7c2!{Z*+R;Puw<ETYTp_~hVbm?UZ( z|ANNL0;E(d(`|pA2cLlHbJ7GDXGzAkXQo5pT&+P8#DCU@XMHe?k3HH~JGt-G<JbP) zmS@eTG(z7i90V5ub??#T=YhUuge=JD=3nCsGJ!QN@wXMb`?B+m2>yU&P<ivQ94x7? zAnV_3xc?dt`F9`SKOUYwqxznXsIR_b{}ri*E<BhJ+mG5j=?><)tn9fIbtq?@y6Fv> zMp(boA63;~gxnM58WfCl%_ZE-wuXhH9XS|Hn7rG{iQtnym~7AWKdhY`>3YGt@R-JD z9-8kgk2@hZomRb?!o*jG8Hj%6=AE&857=-+({vjQBQ+1?k}s9-nL6pnC~M{`o~WSs z066UE_+mk#JDmLa#9Q7hM<u5H)bVgi;ma4US38KI=?SzLa9M!vTtrZ?9sf0>e9v|< zGAzHQcZ4_Z$FYD8@rj<Uit(XzcK8bsrb2mx?eUxy5VqOg$|22Y`TdWyU-~E*<O}?A z5n^FKbK#3y&!=Z~_vWC52q5Ru`6AK5_z7|JI07~rjG#*n;F?eO-KbJZu*RgxmwJhh zh&KzGKc^88a;!#x2h5a4%6#8$ZSSnF8_eF=*_!GqW>^2<8<P(zsu}tgwprOcr4m-t zpbS9T{?*il3lw%GR5vbUz7KFI;YxSh?fiO#tsigy^@YQXxwUor--;h(HesR?BqS24 z)6C6>&8a>rX+BjLby%Q4LgUwiEH+*0ZHpMv*T;7Vs+jE_WNf3l*eT#9!P3ZbInk~I z(AN95=8OyF%cSAMD4!1-4P2<l&)zj5Af8)t_xkh3f8sP(e!Djmwd2(Lu&@?V^A==F zf}dcd-C#NY<$B3MuQT0EHiMZS_nNX-y4@&56{HuzyWupD{F9K<u^z#LP{7`3CiL*2 zL^LG6%Qmf#VeR6K5*T>Er8HVRKtGM3&*+4!7Zyr1=vIon5l-Yt?*MKLwtKSQJfjO| z-CeBma50;$|D-j^5x=JXi@I;z0<O*Kj!bLXgay>8*8Yyylt^IElxPzBwvON9n(-Zb ziFQ@hBm!^${V$G^9CY?M0q5ym{JZ_3_s8$t%k(aRoF04l+6s3~RgQOW@#24zqR$6E z{yD8IZ=%e^q%7chB<!E;dkwcCqlHrru@TsXH_RJb%sVe0Iig8@h%xGl(oYf_>8lT_ z=`S2?Rz?cwqH$;@4$xVTO^RwWR>HAS7T0|HjlptY{FP1;JAuvq@XAsuvP6`D`>x!I z;pdC5MEhY0Q@3X1HsaNxbTxP2$0>bPF+9%A7%rLcJtp4V$g2Wr-I9j)aPK?-#<G<% zBK<h<)k8>K8_S<X0~y~45sfJJXia1SQ2m2hpX?1T3Nn(HDNFVW48KzHv7c))0<G`X zQcxiQiQDW}PP5t)RLK4a{y0EE@YolS;jG9V8e!LknANi_z5>%oiIYL5w#VNahgY0D zwdLf0fpRh(T4AwAF1rkx`w2g$v;KC9PC9PNFISvguJY+L(#oBn9%q3&`w1oURjn4~ z9U9=}QW-7ct8J8~n`7@^TRJU=GzF;;XDyw{P;Qb^YQL4$zdlD_74ph;sowrZJXE8q zr#|c0Rr#M+t_J3Tt*2RBW9MdNBGr<EJe&sb#zbkxM178M`_p&oNx5VFcQ}LMEI1`S zzE5k@a(~twGcyL_gD_1WbB5P@cpmaVpI04EH~cXn>FB4P-+_<0567R&#`@meTaJrB z78~L`Cr<d9IXPb*(7!zPsa#2KeopdjK@@sSADD!ArSh%)bY2pChj~5PajLkyZoCLn zIh^=UjrE_2-M>oDf1eHV&7gj{?p5{FRryiew=a>49rwq!DN(I7dab{p8xvpH5OmF` zMme;T`A|EHTa$6trI!PnPV*yPaWX<P-a^d*TZ^9(#!1#y9*eyliFz?|-eES;il%{9 zxaG8dixI$!OLj#q_{=op^R9w{Zm0sYo;HWKU}RbeazF0pogxK}piA6Z1N8`I3s*s6 z<2YE(OJ?I<NuTApgm01IzF_k4CT4ynjU+TQ{UllgeM)brViw?TjWFvdYTPmJ8}uz& zp_8Qu#^&6t@jqDreS|ih%Hjxoxcvq%2%UktanigvxVK^$gk0WihGKjddWvg9$Lk-O z@yHC&c2su4vD?Fbynop1mAwtb$IeoZ04<9W3-2{uY@1&OD4G>xU=OFTCqR=wZo*sX zB-~sXYuHBvKz$U5vn)a3I%tO<m*s#HiF||_H!Fn-W1K5==7mKJ*cI1=gP&SQQ%PSt zj|ttP@U8i<9k|LS)8>uROzOA6WX<x88G0grdQsMsT~BcfhHm=B<PxqGQ<EE8nO#L; zT8B+t#5T*sU<`#E9+5Ep;k<32Haj+Qz3QRoW+68B#nAM{z*XnfyX|-7;%O1-a^+uc z=c9-r*`)Fqja3XzRvVkx`owsCDd{A1SClhJjX1c_Gq%`jrlLcfvJ+dPzypD;gXA~o zPNi$UXWTAtc&*k6{R*@RzN5}Ii>c`!W%u58eqI80;}@}VnWSPp9>RuHa-0uF>lDAL zehfWn!oVZoZ5+w2%i}=SPK}XJ#WMAd<>$cI^E_w$^7`hbAslRy)8Lz*guAhXeQbcc zbHItR<9{G`=imszI$%n*Nt^uE7XEQ41z3K>B%snoX!~GRDvPMa9-3g`he9+iUlYnM zvCWqYI1sYa%nj#6#i3U$$P_D1Ije@eub8T96zZ)KI7zy=a!+S*vF6aVbX<n}I>Ls= zl%00+D|aBo+BwcPhE8hbai*c`d_6oWm=+lpaS-RHM0PAc&BhVOG<$DjSyVQ%o~5Za zqrhvknbIcs<~^ab^5j?Qk@`3HTeLK@2<I~tANID_5S>pXkpeW_WB0pIPSY!6{L<J( zcmY?rf4$gR)y6S0E8)As4bd6xwSxUT_A%8lkEJV@lQ@r4!nygtdz%<3b9>VQw5W!5 z@W)$e%!^9U-KVY|1Tl(~_nd_Jt57}ge!jRyH-~gb*bms(sMp0RJIa)Xa{`ti)~JGX zNhXBz)98ZmYNDydta*8xYH5t4%Z*J1@p;2!!bzjnsT79GWa)j9194t}p?w+9=)3cN zG-aau2Ic5$R^C&}USEcNiFN-zVT#4`sT9Zp$wcnMH~I!Ir(cPrTlhNW+Snric5UxE z_w99`PxdoSIDO&!qMGmA4~EyzD_Ty_N?k2<9Q%#xoP`oA*oR!EH*9B0@y@4*lGcq| zG#2Y8@@2T^^$U*i>y7<uNgs2$9l|98$=%QHOjrqJSs{tn+<K8g?cE*Z*=9-|v2c;q z>i3#TYftz%VbTFbiZ%YiZDa=ALJP7UGX2}|2g&h%x_e;?A8xF*n$_vqxeRkN&`<8) z_7O<TR<H?=g<s)sdF0rqB9&5#f{mUL5QPgf4WEY|N|RWGM1nPb_RQ)IzZH`56;7!? z$`!BBW=&PnH^#Z!D*zfvcMCVfxXaqiJ6WKM)(Yr&-MvbJJ6VEAztZ7oySts1vLS@9 zDvt-8odgic706{2>tda=9;O8G9<(-D<~`QzRkx@AW16HAjBR=~@%p@+i)3h=2=JAC zB<>D=*Ve1;1W*Ca0Buj|oZcrh)skIr$|!3yAgB9YtxOfZXm@&1t?X8Im-?j{eV+O| z>~#E7mo1)DJry0yA{mH*?c<mq$~Kj>2_!jgg@4u{=&sOjQ5F@)y?M;H+q@p$tknib z{_r}<3XUPKTp?pROrpHXnqP8#(6m{Wsb94#XgtId&usrI0l-9Y0ReB8@la@{R`EJ` zVCs8|-VrdB{r|&Y!1=N(Qn?p5G~g<Y1zJ9bC2A9m#}kxGO>V$Ov*l%Ph!#R>w*QLt zBw8uxaBymj75rBGXM3*oce|={F*m~=AfA>uceS|Nifo1ahBov)T0)O2)AlsqS4@45 zL1eGpPF$z1hd{rhx9?&4NF`z|xZlK)`#HzC&rgYYqOlX#F=0$g(=Y9rS5*8RH^&Be zm_HdmDBFqT4@Dutggf7cZZLQE?tbJ<{+3}RK1B{AU{cdRbH$@I2oK9nDi|=7rlt(h zLn^hGAvU8(TGFc}wC!9=ZW2lK*JiCZ-SOVGIFB@XoP@@K{6;1v(8Jyk6e%GZ`yrqZ z0WT11OjB_$YA^~BDNo<v=Fg}wrJHapFs2G0;jD`RbBk$x(j3tCl*CptF`%Jred1iz zNd}$Fpic!1p<$o$Q7AXX#kR(A{e}HUI(+eE#*klac+FURafuXdDYI(BP<IFoWF8;M z`*x60RRit$`Wx3D!fe6{+7^*BWH8`smd&=HoC@MJci_N@@^ln27#L@b29|}9=(hN> z`{3$?k~iy+wUUMAT)Zz!8Q{zr{C<(1uQY4Oz~z7D;mBtuM+rr*ALlrH5cf=#YjakI z{5Y81M&;t#_aWtKoQd}AKUiWid2mkuYXtt>Y_l$+oK;`c6-AXwd1_Ri8n_GjP{vr! zzWr|a^CFu}txsz=8ByB63xh}h92MLG=a5mBqf`?jk{iC;Snkq$+m6XIJH`+vyOB7+ z{dA!DAa1rd(t~;kdTwK*I{C-<v=o;isgjP)*g*qoAH4Uo9Xh$hoSV3G>Ev^sy0gD^ zk%l<u7o!ANK(ko_&H^1m&_2V0&qQbQmN9$2hRF&nz>wNbo4T3|T9*nouCiQh+j5Uz zFAbK`H#gMi?8VqtlC*|jV_wKZMu;AJ9!0MlMol7X#Shd&ETX=v)|jknhpWa-UUm8; zyf)CnL;xV>Vx(AM>{kNWxveQouQ!v?DZ{xCdtvIyu^Ihx{0nev)1*zaG%~dlwrkw= z=GPBO_Dg+&U=e<Y%1ZZz!^)-!u@z_lPfARGJzwsr1FlBeRTT&pbHRc)V^cSoJ28En zx*v%&NiouiM+jeqIJCR+@x|3;o#fao4Er@{6O&~sasU`GKjk1Vr+eOirmj=s4_V;! z9oHuLlQ#?<_~SEXgZg_x8q>i~g0pnx)>1YUz?qBX=9+}#cDr8pv}qMZab@9D8qDJ< zZ@>!|*Py$A({wF0#~Cxqyueq*MdS$KsA^iyb_<nz9+PDa1$d1G%*sl*Ec-Heur=>) zfCTs>nmz{aLqc_LXIl^8BTo$9y|Ojj<7#<WqT=$OvzLL4%MHu+N|7xf1jOq(DY*aV z+XDi8I191+=($ncy5&wRiN{UxgMw>Ln%%Wc?%=kjvRTjKO;Q1I3{Hjz*i%ATf9wq* zb2$Ir`+4`2OCm{1Z$8QLj_nA$1g{%z`R0RG>y|C(>AD%Z_uZm4=>zUo1nZ}Tj+4iN zp)~H^<jD!}{tNq+yN;Onvabcx9$o*)vz>eeCb4k_W_3p+U5x2tG0NU-R$=}ymjB2X z(BpbJ*=REhweO1$tag2kiFApmc5r^B|Ene=VX*H<bB%wz!xc%LKk$9kJHIz?jF8N| z$X)|s%7KhWMX`)153+CgcZG{}-?C1ln4ItUgQKmrx%y($*-4=PIm(n7k8*08N<`Sm zf8o(nWR0B&cKSIqBj0w2D<slFA(K2)_A+7nzi<=(i=Ob8LGh1=rNJntI(`YzPsWk> z16h3THlcfo$$rJmrkCy-M>28zMn8kH>hN(4QVH-x#J5daZNjNQT2PMU1d>A^%vTVj zZar|HcxXIxcNp~7z14KqWA|LQ?iQxKT49!5)A351z+e=%*A(OLlAto&2C`t6O+lNn z<R{9{G(!y45x*N%Fk?;m4Vmgy2KBUzaZzQdIkOl{CDlsviZ_f_iiCHH-)2{tx`d{v z*)k>L_le*cU?T6ir~ABcTjvS9Q0EkLjWRPd$RzBS=hVxB{>Ig<3GvK2MoKTirs!5z zw#LmE_`WS8H$uK)!Z*YgoyGYG3`0z}J?{L;@ERoSetU<b5WxHxxroKN7MBckC%dD* zHuU>a%Otk1Lb*d5E&2++!x`NnGtPKRa)fa{xLw~X1x?1E4;n0cG<vSvMMAD$CC#+i zETnVJBj3|hY4>?+(%9h3j~p63tB1=_<3cm_h`3p!{PZ!-t6s<I%bu_5AKIxc{TNgb zjK}M+@D3bavqbLli0#O7c5CHa3CdXwH;$P3GyZV1Uvh4j{9)foVJJ0CjLoYDv_;Sa z2?j1}s(R^CDfT@2bw7}h_r12@#OH354_^5MO*L!*y!f2c=gvP3`;CedxC=;{WgP*C z;#a+BveUgRto8w-Pb(zmuizvon<@vsTF0j!J78tI<EZlxYOJ%15FnU+i?q$f8SdkO zep)~P>S;?>2x1mf&q}c%)R6a-BN@FD>u@e~_qK}co*3ajS7(tRm21AH)@5%Yp6j?_ zE_Q1sMtw)#8J_GvEj#er*m-g*x%X-DaLlX$PaeQ{WV|bvQYVgM^$W3@uvWpwYATBT zamE-np9bHrr6k_c-%vGoE8U(46(3lNzRJ&l<&NY^TfMmewdMBx5%}0D4=>&cbQL?U zvb^eE=UIH|W8y@92|`DSkxTNWq(twys&gMul}m?6NAmzcB#IcF*~Hb5&8UP!6P|nk z@of|)X>j#b&dS1=@QR@+m^gT^p(@J0Q?A2MBSaA1(1G=()VzdQX@P?b@!aI2h(!ck zUA4so`WyxH^h)f7`a+WhfZtD9*_UCn(;zf=*ImT(3Dh1kgp%9E8Z{fvt5AoRYTDc+ z4|m%HLQ@C?LJ&y1Wv&A1ce=>Xash7WV=$0&PJNOP>(<r+?q2*(Ax~sg-JfqijNTA{ zDYUUJwd16w%K+znbQh~86MJ-51em@NgL`4T?vF^}ihwoBg%MBgw$JIGi_rmcOx{Gx zfn>_iF}IF3^@WC$$hu|Pf7H?HnkesO3CYm;fD}Ci4AD(SgIjwMAN$E<?&P<6npI-7 z?wn4HCwTbJzwbb_3RjSUo-N8x+{WpUrU<^dI|Qi=`5Eb3dx7NQosf<vxyKh{(#U6d zL|%5qZV;R~-wVMA=djJ7HqHL*@cTiRw1}a|HPQc*HuC?wmgj!i%DsKWOnnkuMhGqY z(8?Z^4Wk0y3K?am?vJKyOLJBoDgzhB@!I0VD$JO9=b<_F)1a`l9$K0K;fza&J{i}D zGQP4pQDE`=l4&&ZOh(W~ECU7O+c=6(HT+><3aLr1PjAjRWcaL#JoTi)ezf*iv(}p2 z)qs++Y!Ww%w@4|eX=%i7Gr^SXYCj!=U7gj%8IU(<*a(9pS>uK-aH~YsSup5LG#HB| zpUn)uSVjYz6!<rO$V$KE%Eg~|?Y{LRIRKU^-Bw4`DK?d(Y`yVEzhIjWQdn>eW8VeU zNH<%EvQACOR}Zqz=gx1Dhde8IyJkD-y9T8DQWq-MqxcWpbt@35Oyi+9Q`{!E`v68z z+}rT$iv%g5L}4M<h8@y;&?Kv6MvZ2X0ja@&u*fW?f!Iph{FhHz)R%y?Q-0<s5!Ezv z)&X(5tmA<QGs~ZjdTW-R`l&uZYNdRX$=I(4aq(ha(}g-+Yb$l1K2$Ali~OWFx8;-Q zXLFmu@m1iHan#b&8l1v5=xV)lm)Vxw$Pb$wY3hGX-P4Oe;?t$<r)V7Qm(FP?U*S~5 z2^~<xi!r-0GlFRfOGM$QD3>#CBh?e`ZTPUS35zXex5t4dL@M%x6cn=1b|+&{P*|?i zO99s_b6*J7<zLKCNurBv)Pb$hrUc`ogI80rsmNC`U=yR?ArujiU3RZiT>hf|OkyDn zr`#F2nyij6fX3<AD#mS5aA*Y2ReyC@&*7jI+RW^}3;<M$p0>#;U12<%D&3VVRZK|u z&LlDtJ-HP<HMajH2J}8Qi6r)QzON83QU=~b3QtM!tYJ*DwUkWoSt8wmjb~CbE@ib@ z0j7)ac^~ta0l(Qkn9+GkjsI}q6WHaz1|%ti!F6#ZpkpiGYV~W5)M($UxqP>bJ$SI= zxV`2lY(EvN*nv-=^Dk<r<!Vn&RMqK&Qh_J+tj<+%fVdjsyhX;NQOl9DJSMz!yxr>s z!7Cu)TlyHg5jUKHYwqLsWFI}*J)8^Mk7fvrM&$VMLbPnhPx8zr2hzAHL%qe*A?H<% zY2N{V-P2SJD|-Hs>F{CPKX#U_XB6kbwB@hE-!Ij6BtA4PIWEW9DZk`7c(U(ZHgCnJ zuQNnKQkwAENw4k+U+&?7hT-Lnyx1tC&h2<yKFK?niBmv>V}3Z@O#2?0F>is6efkr5 zgC9ZOPdsiWOSpJtQDmW~$!*6_ekr*1L`WqcQK%e}^*aXp4`NZA7&8gs!Uwfgl8{Sb zIKJRH?KBY4e5vsVq37=UM3s`s-S$C+@~Fh!=0=1Nfj4f?=LBuM1m2CmxkYEQ0Ex*H zYd_GzpN=|>vLQ5;@}!ttXmgl2EPwQ4*rrd}&s^yo;3=t;grNORxF*SDdj*Q_(E287 zGbh0>>Z>9f%*(L$U*goOAG=QgTrrgE5ukIdU`#g@08%RELPK9n3+AHwn~;<NHEyj> zMq!KMXz(uce@_<r_iN~1I-_2jh>uGjwnk6_w8*7bLHIUh1n10fqlO{wLG@i;l)jmJ zTHM4vD+*W{6-R_X4zQtYFeDL!T#hGGLYKVM99i|n=yg!sUJdi-Ig8jb+3o#47QA?4 z8Yp&_f&zK}U@tal4I7O~dT$?o)_(GrYuOW}`RFNyegliT=n9zD^_AsA9H@x7iT30j zM;P0&u$57VV^ghYY-+@`k(9+mM|3Z;lADluF=bIpajT(4z2}yvS=k}*OA*E%Pf1V0 zTdZuN*o3%1)_t1`w(tSgrkN7W9$SMB^(mBhv(jIHHe0FEI|Iz%r_bhwHKyx+tc&sl zDV#t<^ZNF<1E!dq>Q>7=kVd5*M9=7*@pkf2syN8%aGdieA$p$){;f$o?Um7XaX1@M zgEVBIze@Q!f`hhK=YrXAQX#?V)vLSezom>~(&QD@Bsn-|!gEXL`}v%mlF9WFZpAlm znIuTk18&E+VbPYTtH4=U<X2udS&Acy(ScKS{==py8|O6&)Rj*idz3QQ)89({+X?$V zvFQxwFF!~F?4=oCGUaDEz;CUm<D>g)qL?Bp;qnS8{1lB~ud)c4Ib<nbdpy@@(_rZW z8K(J&)--7ffP%?6oy<%Mj|KTw<x{`2MNUT=9k<<#Sevh<Qz(L4tPFz_7(5)*dM0mk zzK4ickvC%<GPWNTH6`~~EE5Z3n|%6<X``$7j@DJCZ&kqNBvdH1gShQF4P=ZnQ!4m1 zN#uF><8P6&0m4fKJY6Sf{%MY<*9@dWHGYumIbq-sZ-0JjN!*#~cpwK46`Yqv?Hk(3 z<;A>;Li|pmciG<y9H3{{HW8)X8&hEDsIHdoVUgo4$H30`#dEppI5{lDIf<Y@%jdPF zMwvl;ao**+WrQ;riZ{8@oP!KxgriQ_V{wKufZOt_BfRQ3a<a0vK7FBFOmOT=A1z}C zmh0`LMS}KL?BpoMmNWo~#$ihEPbGPHeETCnA_`K()_fOav8m*A>@()HRmc9@;fI@b zt191P?!@bLMYs>NG#o|tKMDd`B>Yl!8qS!E_@E44>eV6o1k!gO`*8S``<5n*x=`;# z!XRTDE`f9^axeHSQP1%Qa)I%KEGMIw{3Ju%oT2<zN1cRNioe$a^c1En)2}~ww)3d- zZpjyT+v=Dq#FA^X(?m{sfMe?E-x$dT3!W?WBkZ?!&LUC%-zF3AM(;6}db?#4ojQkZ zJi`w#RT+0bLs2=F-t1K$HffcIr}k?XctT57DRLw`=(i!bY~?cy?G1DE-{#ToxDw@% z!nz|NP}%W}3~OlSBBRxd=|>)snZC>9+fiJ`ed3?O+1%+*e{{#3X&M=W`-Loft4f0U zQkvqX6>OYvWm0(Aj#O>J0jj}!AFU{Q921*xtO#ReOpI4xG*Z&}fR$VZL#Favtr!z( zt5bOjOpTN+8I$Veg+dnIK4zU5eefAnj+ZCict)xG1F5YHwZlvBdaf4YAcYKp)9J!y zkpa)tc>Jf0JPcxt7$d9LVO!lA-{ALd#%;k2G3bm|gz|4uU8OOPB%9!Av^0NplSQ{p zbt(GeRF^;9c|QERYk{ULL=?T3n*0+&ytV?k)#XH3j)c`Tlt`}D%}?eUt*+SftY4S= z0FDgw^l|W`$Q<vVFi*eF5$Q-*3FUu!B1__Q2>P(~7Y`u=US?&eC_?Nm)nM5?mty?6 z6}7kEM6lP;D==?fQkK`q+)g&F1h2-8@OiU@dq>QO;LTEOx9dI1Kh2LAxSu*WUhXiy z9>=zRzR37fpVoX6$ui2x&!B1i)av$^MDR<;Tkm?O<B5gU#6duS&pleXTo%J5)jk`4 zLo8u9ocoB*B+WxG`t#<Gxky5#QJuD}DVC9<?wt?+abi`F;_0GO%_;`Z`$q?&MK26t zsh`h}9`d3S7UjQu-86sy(uq&L!jJGVc6iW?YL#A#G-Mzl*c4@oUHL{Y72|ujz;11% zxyEy_KmYo5p?9NP^lXPhvWBWS;5hfR$lYv`POZ6iBq2z2*bs96XsD9{spe^LE$iMG z_#Zo0{|Ynz7JHs<use^<&$5fbTF>_^y8I@);V1_?ZuguK?)}lR8-i}joWxA4-PvT+ z48}PIbY}a(9~r-v*5`!Oys1FlK|FN*NT;4Tg7=~8xTX?|MY{kdK=J_r0T8g~PB(_w zVs=>VFR4PqmSVGSD)rWBThzpB%>?0V();S_tzlmuko{lx+Cy$=$a_A`rTiYK2)Bqi z&nD-tjXfK|cgU1*Z4xBr9lqj~F~7B!G=*9Ik|6;IGzbR6<_XtIJ|tCsb&_=i`6L$l zTCOo65Ky_fqA?9aDSHJ5Hra_44GlJJ^kTXreEHpC!rF6r2!L1d1wf>X{!B|)zi{k& z79&?Q%&ew8eqnB`N3bmq%y3X3qkkA1!=QWmx&N{!p#s2FX>M~5OW6pDjThrywQx(D z7)Zs!RoCVOk{rN!9fNgh+G5}__>@}zo=KX?@7l{O(q}le(37v6d*g6b;wH@lx&?;_ ztqJe!(?T*nhLOUNb~503W$@}Z+WGoL=jvq)?!ZEX{%dJKK*!T#I*lwUd^WFo={dvu z_j0rXZaVO~mgl-}tnp}WLoWKs<M2a5OcE_)i%7m)2EN+z(@jgB-3CSUo{!J$ij{YZ z6ge<ASTGsRJ4`zO{(0hHuC<)zf}iR@cLdoK)uMtNF69S7BHI6$;8(vv*%jZ-J~8?o zJDa<XnIX|r&53{ZdCL$!CDOF-6`4c&+TNCFj9e|JOT<hW<7(e0^4;wesi2#X1g8^~ zk6#bM$Sc^qk1!&D7{y&vdWt&doGzG~l|AzFD|$nPkTSz3<3}Si1q-Y7694}rOUb_^ zpnoVq^6V&;DK})xY^hUbkHVcq*fSjt*A4_{icUOK^t5q5&wp|e;irhf{Y~)?FQqjP zf-8G88f^vZ4E`QVv39+#hfKs?e-$epZGM)=XL7bJpHr!{vsrhniI)b{WCQ|p@&=)S zWvl^5jo428n4sHTskSrCbTBzg&qCJxyx$-LogY*>yinG$S3taCIDZM36f?MPOT%LM zb}2=1oWK;5as*ta!G-K;r!1<jg~8GoSG5kG?&@#{a{HeyS@3G7f6CY92cQwyg5A*Y zs}UAov*y4yKZORruYOJNeF`Dn*T^$}b>MVfeOHRtXfp|-STbqZr#XLHL@CD~6UH+s z_eP_`Fv%U32#N8}L2zJtggdIZ?K2Hm95vGP{fu1uOUR)->N>qZ6n&(+2c@)kLSVbP zAD((}hx;L?E%5K~VksxR*Lsu5=6G=MFQ;Ha_W(lI(=0nT86qsKUkMlYPfiKaxX-do zOksg0hVTI%0k|A#2$v(R?W86U5Xfgdo|X2b^`vdW2pOK6cVub5OdzbUv^+87tl;A{ zq~(ocI!{rd%<tA~T1R5?yYgE%-`=PdI{b=PfwMfY1arSj5B%b-X=}EJZ;{{1*L+sh zu9^LxM(6)i0Q~RX1b9g+CCG_m%{CDWu7C(GBI?hh>kH{!ASbS`r3#4q3uiuV@AV2- z3)S&=k<+h4yWGs9xa8=&R9k4K<1P@unMOuN(J3jE!^!L=#eEk0?|uCqc;;(#PjXat zrQrd|r?LSmwt!(-7B=*ed+(E8$V&(cL^E`=ss#*jrL(D)AXS8E%wKBGyH@Uq1<gAw z-mWz~<!7{?el}9qy)C1kkAQue_go{5c;uAD5AA`Ofg|IhEH>o!eSTDRCQQkBm7xe) ze4*$;wlPAMSQ+U5F$NWR;mgX2hlrd>UolStc)`3Byc;Y{K564bu?iJ1Hz3;*fPiey z*Xvr1{jE0_UgwT%#sr&+f20O%>=>pz8MdhQ!stg^r6G#m)%;w;GNE$}{M-N}3Z-}C zS8R5C0)U_=@B2Y|L&U4SMP1p4=^|BWsSL;;1vgkx??$shIJYG7VUwCxIVu3@9oXZ# z;k@hqo#CHeVE<-+hDjJKG9!aALB~0+)<XAf^JgL~`zeCc<9nL4&(g<mS3jI;2Xx!Y z!wFT9<vWs|&vVIWOdVQsJ&J=nl72PrCm-0v%dlH0{YKCap>G*DVQAxluVkV)E@Opt zK~pTh!HI4|cZU}YrS;1M|JOn5zkZNujjf)|onB*cdv27N#`(xd3SZ9oEM-yy*?!AO zjCGdTO8lNR5-Ni)B`7G!+gJX+DK}dv=Pg~Kv(j#}Js*{JtGX304l02JyTy#Oz5TFs zlRaH}i6+up3=|e+5V8H7oPj^OzG1{Lo1v3uWKvthd_s(3a2lK2LCm2XzXf}WlVg_! zXxLb@<Yf}wehkbkSK8ZfKCz77De@}f%ed}=u=iy$<ZBr}wPC9QwRwYEr2U*$q)D{| zi;<a1VGZB>Wlzn5p}+P~I37`?0pK0w=;n*@eLNl!-givdMA<+!dZPmX<CRbJCs#By zMa1EK$>GclNG)Y=AjFj<#){InI?dBC(u5EyH{h%D4_r%WYHGpsWCUMizdxoBzgu`N z1S&)H&_}w}iICNEK;Fx%UaX_W&;B*(U3W4UkZBe^UKSt1$itrQ?1X&5wB)q2YIwNY z@NFf8p-HQLsn|lRTnZ4NUTCaZs?IQ(FB{j;8y-Ka<3&yHIsXK}i0;AQr>Xp#iS=Pu z40_$Hd?+FQi$NxjK@q-OTur5RfWW9(w>CHX(rzBqB>t<*QLfz(wW{+F+-QkMNXO80 z%0v4F9xVs{LW~(ap#QgZ^S>oDGrTWDrp_`;OZm_uW*?V4k>XGq$%Q_DOb@|QuXjv} zHUH&*?rz63RtUIzHBs0Y#j4!W1N)R+kJXmPRZP3%pPSxS^m0<G047GV<zt(>pOhCI zxZ7p-qFWW8+x)PY^c<^xa!S7dU87|_SjhyWo*7?2tiwITK+t3ygB}ql1OMmu3RVmQ zf~J6*NnY$+QD&f0%u=upG^6%IFtFN9oxrJ90aL-op&<28oWO{H)+nZ6p7k4HC@nQ@ zSQf=AC7pLGaD!-96ybLSW4&=}r_Hi-z9~(Dt6E{GxaRq0WbgM3XIPB=3;fnidbZQj zQkksf%Q0Z2S+FI~X4%N)T)%JcWeTC|7+j)_tRo-X)G)V?5>1OMt2m3I==~uLdw(## zJ&kP;6q}%Cdc7k)pNh5Ledm+(ZOI$fPbm@T-YAI97BDK)@FerK-txo1bwMlqhH;oN zQ_L?KKl1L-#AmnuCaR$X2w>Oo(BSiYZc|@j?tT99wa%I-q5q#4FsKu+`w>||8aAhV zDg1E2QzC|09Va(BkDM@Y{DC#h;S?G|%f_--Bew-TDF0akp6mmtSs)=5=3}4?CNL(j z$QJ!-gBvUDH-^1m>j!`9O7=aOPSC|_EzGJvT99fuaz=4`{)evfANcbBzMu5pgp(_O zfm(yxZn*E0A75*K6dN8-ZaLHA>bUdQT;=n_0av@O%1ez^??29T_&&jn)=tE6;EW`R z8F(a7$Nr2=Lqnt3`)0^KZ3g+}Kcxp%ZI-LVir{(qm~WI;L6`7wokldLOnKB(hDOeV z<<!^xefqF!ctop2sO3!2#(mg$akB>%&&D3@k{L27&V8i{=A6pvJsdJ)*O{zPIaA*Q zj7Rji?g65*Q~be`1@i)ukQjY0s+iycII*yqgyO}#4~r7=8`Ej@nSFG1M8YJno$Hu^ zK#D9pTJiM9KB)%H_HA1q<@T)$@E4sWdRnlo7<zyzv^VUOA|Tty3ibXVkd^1=y3~H~ z?B%3!NN&~kV%uNzMz#C7veKP}GzTfq<(jvDDmeg13D+1Kpdgvff6|0R_okXcQoYwd z!vx2urt}{my+;jw!N6AF#pQlmN~-;WhF#K7G8aiG-edlf*A7wDkR>*Xj=O#$51iMU zxYL&t5!ZG-&mTKGg@9lZdQj0M)Smd@M%VG|<7+>3M)_M7h5zBSZOOBT?R?p##vuJ2 z#OdeZii-f%-ydwl>31}vyqZ6_o5Q)b8|Pjl6hs6EFERG4y3)@$Wr-=xeaWHW;QSvj zJ^#(A_~$VaSSGI&q90?*ExW~AjGlfhCI2Cl%sRe2N3dUhlE?L&v18nR#dagzbo@Q? zN8dBV&5DC~b8G9>#>0}<^+-AY*L(utyEY?9QTq*;qnFc`XXo}T>bAiRL-#{6*do5X zPwMKYzyQKJl?q5I;<tOEAP==+(R_@7iIr1-tUEjhA+;PL-On`SMy2f!Av`bvm1Wd@ zzS7hLeIE5qW3L{9F1r>Ae>|$M>=#zGadX`>DVpxFIj4h9p;zyjv`T_BYBdSq5h(0S z$=z%~sc{3VGqRBYCE$A%kADvOpOF|sp4Qq$1pdyQJ$*{)8U%?LIXph9`OyU{x?0lU zSTOCPdSXKuTmVlyv$Kbb&>ef@mZsuhLl=2Np;OWX=Rpf_c(fiYN{V<H8iF<e=DWn% zjheDKx+EQK%_M^ZT(~?h$Ij!HED?9Op8U_ar<$*jow(ley<q6L?1rbo-F`xQh2bbo zO`PVD{2Ct_%h9@or~EB!T1Ast&62_4@RBK!-zHtl^-1H*`WYRcH4<(urC6?C6+FMV zU~BF)!AD;c)o5mIt{8vnEh$fMK9cI@fb;DTNZ}4}YIt+MicZrwA@MI!IL{$rIPgp+ zg-bM^uFfN&@1v&W=fD1?!^}!9IMG?+uIDpOA140;7IYLyMj9LIsEkHqIPvR;S#z`F zybwdv;XvXn%Ri6B|Bt&y-UX#nf4BP;>VfQ<JK5`;bqbjjC|DlNqse;vYki~iz!aXo zDAS;(9EDPEkE3`17xJYE)!+T>`;JQW6A}nc%!k=xVMsa8FbYddoDp5z^7Vbkzxiy6 z=7wjb5N`uM*b>*0-tL?IR}Yl;AK&*8dwHO%hD}~lO(Wi$hH6#SfHf`AzHtscEm>C9 z(JZZ*^*klV1mEC!ZohcJXlS&NliqXK5anx);aUXeo5Bwn(6v8>@RG&(uq8?`3EZc6 zJ_T3sHpi@CR(wN<!~?Y{+HJ;&Mg#h-yKJds<-3gbp=&J5{q7dJWwC-4)SrDpZeS+F zS430uxn<JaSJH1XNd^fRsSS<JFS8gsU*Z<^vnS;*D!QWa3?pZwXRjE}z0Sm_ews<B z-lJrDJnc3B#TXsL#7cVPTW-z^G3#uj>sF%yt8^CNgUG`CE&wDVleY0oGo`Hz?+)$u z$Lo~1{Z4_W*@Dz4C!8nv!4WtU2evbMw;aW@_T29yv)<0VGm7x_=pBY*`hA$ln0anj zy-Oxvjp$9kiz1Wd-AH8(j-0j=5ICQr)*aw~wrlZZZvkZsfy3adMB`8y+e?2=ii343 z9R7tO`roN2|CNybTPE_)hrY@1%ftm$w^G0bRn1`G*#;h1)Zd`a_cXZEFw!PeS5LTZ z%<XeNyJ#+9uX~>?RZB8sfZ@f;6<1SgDj~J?5{C$&P)(GkRcoi(c6}hNaDU+L#RHtl zS&+hO0HW*q@gpohZHD2cXkZ{n?<Rd44v5>BlXOrVieE$yXk)$Jno~?k<D`Dbol`aN zl;d~pOQDl0VsGl7GR#KQQCtWs9l6vbDC!44Ue>kl`2#?lr|^w0Onm#HvkPUZn{`i6 zxu3GogrO9^7+>NAQi7JaoQ1CsZ0mKqU-Lp_UM4v!TD}FlO6^&$;bF#PEkg~jBy|RJ zXy;{D9HS|Ezh!1exFZe^^fM<B8lj#`th3{(f*)f^VG1S=-PFFKmaym|RR9D&Hw|y0 zpFRLROc0Ds?5@s!SbD~+;Y-*u9?ROAqUQZxCh~iAvxe`-jYO4Kn+JUL<>l+H<z*qC zKLLg{Zy!f&z|Sf3EjJV`H{~asqZcbx<Sfs#s~#h0k8k_=j<7&TB$ou7u;2GIi|f@I zJ|uq-V7kw)R6H#EMUA0}`;tw2r8URM`U%=MD9bH7kTuKiFOV#~p5_bIJ0ke;b-a(_ zQZdU085)G<>`Sb=_btlNJ%aFQULXW+ct5hCb?k(n9&_6S7ME^(D{tC<vuJs9&tzLt zM!(O_+v-;~ajMX`>sQ0#^;JJGuKS1oXkV;@k^1ZP6HHz#9an4VvJ`JdkJCBB8v1VV z;xR5z$iCkr?Y~g?{~w|1f4!652fe`Pi=kMrnQuoa*qz|>5~570Yb_7(#`8sqDM=)0 z@rnkJ)jmD)Efen0CX<}L$ZbxlFd9v7ECln#EjoqT4Ts~?-0DFu@$~&(0j1M^dQ{vc zTp#K~^1?crdk&#9I*af{4{wpJt5=S}Pj>a#GCi_gYRMrj+54w8P@As^FLJSt&fCP0 z`LK<?bDi&sQo3z!1=DjXI;sHQPqz+C#xEogEkya|0{FoFeSAfh=7fJ@_~r}J+lw=5 zl~jLP&*$j48!9=MQlJ0Oy`s)oSfl@*TT8N@B!r)eEX1aV;*(@)$8;)m`V+`^i-%U! zna}6J_HuuWv{G`M9M3mqziJx|^9l>J>kHJFE|KM`BSe18l=TYCK$N&zXj1)fSA8E= z3Z-1Ej?-o&+MO~-DIz+bqx^qJd+WF;+pTSw21UZ4gds#h8bL-FQb$E3hLDmL2BeX$ zAp}8bq`N^HhVGK?X6O_cKzbPZyS(?_-*fNZ_wDz6p7;Hi_~$y$bFE_?>p0e0HS;R; z;;$Dk_R^;vOWj}bBwKL5bcmHeyw@-q_AvNevz|LVfA32`z(KVD4k8W$H`@?ZU*I1U zJJf`ztHg$aji;19NM7w3VlfHDEAjy5J`*xy#_^_D=?E5@&FPGy`lYAe!uHMGLO^OR z?Em<9hwvzyKUG?Mi0hx{x$dGK%4I|2-5tU_Zsl-|KaEsXd)HAoomBh{GXJ^HnfV3j zG@Zlt+goBKIQK*5I<iBkr`qy}<x3ynH2OtYjQey)m@v_f>9-II8ow*16&%%_EYg7% zkBoHqjUBH)Pc@JE&Tlh%T!Dvo`!QComqzQE@I^jqRaBwwqBK{X`7?US=N_}vP036# zc(=?mhmBP3Yn$HJcS7A8vqD`_N=-5>r}6nZkg!*<_r;B})aPAofea5X$Fnpok@!rm zS+d8OV^Fh<0#{Vft>eqvl*duMzf79ZUy0<{N1un&q@ahPOte9X7**+;Eci`ldG+>T zZ;RoA4@HiBt_*zM3GkE35z_0k&wccd{GOu&8F`0z_(hLH%wmfD%LdcS9_)?Bi>cok zkQU3mMJABzt4h4qJxn9s=cUEJtv&jmXLhNC*IrZ<8mFlZO8(>^sOj!Jn1%DV6B(51 zSDy}CVQ$ny?G*Ed@$1mR$=Q+VDD>4Wv5)a~jesHZNplXAcvg)*CVT4V033c7zlEwS z!|$d<^J~=4Z)tgXobg*@H7XmUIo2NoN(ZdmcWNw+aqzg9-3_(kEU{{KQen1~%Ukkq zLG+DdSdCud86+LuGzq67JqNwVWLLUB@}g5_{B`_<))PZLF(fP?`RJh%JwjFnBlBv? zdyGvJMZ@RVO-ejX$I3y!6SlYX>+$)0uAN-Qo)NzD4bE6)%A0B*KBG$@fkov$<@v#p z-aVy^5=1QP7w^=;)!(0B9z#XeWM-CHqMIi);F5^@-u^fQ`y=f3S#Yin$YvTD2pJk= zZ+0s(3m-8ODAz+uflHFfq4&Nr`!V!7&8m{j*{n~t&4t$Xe?5!lUs>}%rrD2fByw>A zk065rhR$xRiRpm(s+7dy20C_>dpj83RCDag{K9V6dm3{?>_>UCPXOCZaO;f}yC5pu z_|I%wl+7<miDK^x8SS-X3XskV$h~SfKPvTN)Amb>C-siQC8>)?5Hc^)2U}OT_w2W2 zbEh-5UTb^ImiG?6ua7kKhg~gqeUGtn-XCZC=<RA0`5qiSoR&~@kgL1j-MIZWW?O}t z0y9pGVvo9INy%}UmNI3elB8x`k{85#nim*)4`na6%5wCE#*vgQ=$`DzbAOx{qJAMt z(sj-R=@5Bw7ouVxJW$v3W&cn}k5?Fl&A6;THvD<AyqIazkBkLMgg2}?0{I*rYTu>c zU|zv3HXS#XbFdM0HRjPXsLE3jN`{INa{#g()049=Zuxn}O$5RFfCuV-e$W4wSIPwl z*ihU{QBmV%j#bDanz^}=`K&bAnCwph$;K_9D5|x}iotF#amuufwu+C0g4u&5sXhm6 zq++RUI@}wnCZUXJhV0tP^eLP@z0ev<yL7)>5?z%tC4}Dc3jKjnG^98v+p^=65?y!r z%)^<z2sJ4j0Igy*p;&mClENW2X~nZ}oMPy?XeJKMMG-2K0<^mHNL3VWBuw{%CKN6R z&SIiFCiK{bu8zY{K-|cJV#1**JtHh0tEM>xjhbM?lzl_ebe$C?rborLyyr^QjgpUf zqlePG^D{Oc76*Hex)Aj!C^f)YP4zh=l-Wy$248~?@M0nMS(w7u@F>vg2L8Y$<nc$J zH>NQj<D=PEBiW#gq#yS@ra2-49<p9eH8)~^%DzoF%Ae0mN9>Q1e^bXLIdQ>xA;f>R z^)F%T|2U5W{~)C$<wbYeYZ1LiCul=suJ^NVwNG(g>?tb|3;(&hoA#$x{M*26<Q0bE z$0qGQBBH;Z8ST1aIEADyvTy9AEjW;6n++}Ex0Sn(aBI`My^8Xim9*4R2cmpyv-|`r z&XV~|`9q?sIjmfc$Lv_?(qM2#lRJ`!-o+u}Wr$e9MNxQ0kRI4U7|jZ6aIaFW%nOo0 zsV8i6{g48~DNx&xqd+F{^8A7;C1R#Cmdy+WgjbCG)pm4$dARiJGY;t9id~5A^iwr- zd;VD7P1bu)?+rhP<ai4{cA%y=i^&kT+-%+?B|i($S6ayQ5pY@UF1x|dYwU=}EF0~3 z><`)QmT&=2M?J^~af@s!US}~O&<XGi-JWvUoTJu!$TSN|-Sds9>`pfk@;fmr+HJbB zt818VUe8o^<o~Aj|8w!ntq5#h^Kx;KM$F{GGzOEwqAn-VPef1ek>ceR6x<^4DSvh# z<=e5a(of|)RAVQzF`jR-F{W8m5G*=jI-1?CpO>rhsXs{^2s6)BRkKh$y|hNNh%>Od zzDhQIa@;qmXIcouK>3Nexd1&>$A};UGxjwU`yoH5Sm>drWlwoGvDOY&->x*89KGMk zmZi{$T2`lrUz82Y+$`SiwVuiQkks=%OZQAT?H;o?IeJOObLg8`=GB{M*KI*RZR8jW zOq7Ejx%?;!fhx)ClIE1CP|CJ`b^C3=BZph!w?Y(#WynIjTcHU!cYXk>4DV1eUvezY ztK)JOA1iQog#TmK4A<^7*|VR}IQJgI_8&2kV3ZFHedK27Ht@>~f8?25l6_b7^iT#w z8C7cG_b^bwnHftWCFSHaLli`N*=nPQ+Y<J_89MgA3G}H{tcvh~-w|w4s666AXG%iH z29+Fzv~t+)P%f*L9Zw)&S~m73p?X4_20t#?cU$o$Aq#!7{wyE#E^;tFu4$=obz&-v z{Hlg$tRR@HMlO~Tq-$O|#w%pBP$D|K9RRW4pgpren5L(aqK=<R;_1{y`g$i64c;U% zv|KT2hQ;IHoxalopBY9hrvzV%aCl7RdV)R1DILu2N<O=XM%~lL33acOc@(OHN3vRH ziIPh=YVi^CwRYl!f#4P`?4B;iao}JwMidK0mcW=y$WzO^<h7dVG>l)xUTR_@)ti21 zG`{qH;bBxxso6brgDe{2Kt5;cKd$LbUQCqj(M<99dz7y78?TJOq}YRONTz>da|AjZ zfrU%EU`=CqdyT(BHoqhG(^DXu(60iKJ<T~dcqm_gv5Tq6o5az<FX>+fh?D3}G}7^Z z7&~msXR`yeF#nfn08C&km%_-VkVu;?XPV-nKUe2O0j$roIIZg!>*V6h!@r$9BVi6( z^(JZG-Kk#o21)kcb{-1HNg2`gR>g@A;N;4~&qIGGX7Qn@4pB(tAI7UOPReL_D+^Um z__UC_#>_8>V*uM4)|lb6XluH^?&`>JHG=)R!o}n7iC#0|VH8<m<?`r#4T9i2OhGH# z;Mk5l0%amYud7y<GUVb9nz_Wwp`2VW&06KTv9c`4WAntfrk%VJtLRYl8<u0(@rHL~ z-mY29Z?hsi4|p}saN+~JuOT<?(Gq@jw87v!X2rk3u&J2W_?8Ba>%-vEO!#v1dyr~7 zC==YBUArj?S@eDk9brit3s)D1-&Qx-d1)_0ywmkV-ZAU0&Jl<X{06zq@+CA_45oeg zI>ckYvB$A?Had9W|6TU-KNJK0MJ0Hv1xjU!JcPwR%^k-y#fCVQYj(RG{|3E%`;^c6 z$#lG0Wsf^XqcpvNFc`r5m!W0oW}mmDVjq(a>qYR~tFu2@=9B&bJLQ0A1ZY_DTgK0N zK{w_zq?`RzdS9fPPx2ZpvTf~HHJtT;70BJQzqPhWzZc~{-i)>u*&(1@lrF>}=vI9F z8m_$hMny-hFEZDpt?{U*Q5AmnKz!ueWjQ%0QpObOzx^Kk9sQ0^6d5XpjBL-SpH}qM zHiHW6Nqv`BK?6`fl9Vm-o-A4z#6n?e(-YB?rVBDjMTRoKMV7R{cU*t?go-5`eO!#} z?v<z?fus6xahWVF_R?kH+c~v`u}e?|Ltkl_=!TRohKK%eOoqmmA#ATp!Xa#1CE8<u zsL103Y-j2n$$O_>K4UKC*<CJX+B^S{kNuyd-M>=69fI_Xf<jk*OU~c$ozPm8#j3ca z+QEdvwxrrCX67{UaN-AJaO**msI|(QQi6nx_8UVjYT}Q{9_iGMWtEY&w)HT>k2U(U zfZGl{o7-%17d&!F0$cGtQ*K&e5h}e<FSlmugo1o3N)oBC-HOjRdodG8se`&~h2!NM zc>ydukXX|8)Jf&fZU~DoduG-Y%Y7w(T{P;YskjR&h6l}zl8zPwFJ<Y7A!Rhd4^33# zyl&Y;_daqjOXnD6s)Ij9+;Tu+3iE7~iEmCS@^mjg_1XqSkmLNer|cRg_6{r)KNyit zAhJNcK?~+K-;vBkhmDf6hLRcmP@%*<HiIf0WPX?5(R5g4R~2{J&!7=6&(#4BNrQHP zW1~j^7TFPYO?0M;SR)?ZkN;l6-MQ!ed#={6{hWv4SAx^;p?s6jW~Sah=cM?IAl4gc zq3nX)&(Uk0`n2E|(1Tgye)lXgvG?DafvKgGkNNnjP(!`+vWUQm-URdFzp!W#Pi@Na z4#O^OA69`M?-cWb@oShHOg&niVBnCB&S_%SJy>;SypisB8<j89L?xdDc_fFme32A- zO++Ta&&;k6OPMW~oakL{*cp-rTWIti%Uxp$EAZM2KDJ7?+<we(<$xPCSf$$Tnsrda z_Ju|Qyc(5Gyc`V$J#4_*LL=AMc}4a|iXgxzO}dzM&{yh=K0~PZm4t#&*&+4l(&GJ8 z7$PG{j3ePFw`oI4!Ez+yDOuth%eIth*i1pLhcD8P*@1KX6)1ryar&)jp(E&4Bun#{ z6fR8Re5~}_0&+M6{V3)$m*(+v*YHQ7LF6}kC=VW-WkwPI@L{)%(VZS53~$Y7Y|H3J zK7rkA3G@g~f^15^#yko|v`U@_Gh8ksqIS4lM>=-?Kh>{%kNCvDW&!;FWr%Wff-@eZ zzJ}>(R>D!}sv}u7MWZ~cm)%eullz?x#Gy_CV-Cf@zn{|S?N|Z0ZR|TRN6Fc9w@h9z zy^E=6Y;fW@CCST=uzW2bRvpvHQ@*Vstb3-uh}-a(X9rYkZ&|BKQKG4;YRbhF8D99O zNW&%4bYO9#x>F>iZI}3-4NnHARd|bqi+Pbf*!n3);|OKQ5mvpoSoBX}y42A_RD4my zL$7|jSyH=pDO};`xtWSCMn$)xrI#odgxFBNen%a8(b5jp1eZo7NhiB@@M-qGR!-pv z^QU3lth9(!Ws+I)?#eH4w|KlN%}n)xi_V?|2fgt)H7^87B*U37CWx~?oSg)$5)Z-( zY2Z>&SWW}eA14*EcxOV6WJ0HxvJ@htA3=4drH$ZBA_p5o!W^=m@c}UK8x|u|pRw1P z4r6zJNNG{bQ2(jV&hzq&Us-A<{WsN7<pu;K5*jXF;M02~h>syshs=8e=S*&tFAk-4 z)&4%Y;v)@-9A^S8=gfYOmblyTO<-w*InDWdpF{!p+aGxa1#7g0n9A77Nhx1i=jH(7 z{_3+=GBPq7sQjn)Xy1IZ(c8E*R8$Un!&xmp6g@r5F3};?X_lF_;tTvFeYd2h+RB5= zf^i5=mCP$}PYqTm$d#xm;0M#Ig1n5UC2ctnWd-u-ur@xevrPZmv1Du^1kDm9>BJd$ z>uO=dhi6|CJW6~tOw`?|Yy^inWR7ILbI)APkjL;OgtJhzkgg&1=9HWHI_N(SvFdE5 zW+p($$R)ggrheLhWjy^zqqrQUFitO9o+IFHk^U5xv>g$nV1%;S=xoFzCE({su+KVH z18t4-ZOXZrLWv%PdVGbHgdtuOloU7PRkY*)uOlTSBWIk)>>pVIC-lGd@rN+CH|7h? zr|jD*5Nke_P5B7lelMJm2N}r-k$2^WIVHwkbMk-RojCOCcC1*ODn(E0(PnjEg(P|` z*KT7j$7y3qsmOkZ0w06OB7E>p?OnW&>$x!bv@G)rSrW0uAT+AXWMiViEh1UF9$I#Q zGg)1$3?(L7z3H(5Oz7TFegA%vS42;cWvCxB3gnKux;Q2ituK~XX*+K@l>^}uJA9VG z*B$|ud*3^+<KNM!6H;oZ9vx-}Sy!Rk*|nA<beu;k$0X{JHz=;=k)ie5T``G~u5TRM z+3EMb!YseDM1d+=WK({?E_cUyMRRoz#(G0~)KrDjGFeC{E9{UC$`eEsK4SyX4Dj*r z)(H7Lnpiv-eDgJXrbpNV(li<g=dOqcu)4E!@G+glK^|<4<bD`JnM4Bhx_CR{0cpx- zP$n=oa3f)QF@{mu`PJ$TVx3kz%HNhfIKB<ZiZNqUuzz0TX*|3WtA3uI{}psf&0;N? z9l>wCb9r8IWaWCz06?YYb-fT$CXa(x`8!Qcv;Q8F)|e@i?0EL{ZB<o!H{abo$#e^4 z#Pv7K(Ik0C{NSCh>8K5r#rc>T{%uY!t{1OdUX>A3M@8CKF8b)EshG?vB!mD32Q}Mt z9-x9*cGG!gwy}u+S&~iu!}5hDaJV@`IWVS#YA7$D=MkGkQf_?Ua<r&Hoe==^-OS6G zRiEIy3E<w>>2jjp#8{Z!Vz_d23Q$=Kx3Rl)w?M^dbe&i83m0*F%6p%`KQN7RM19e_ z3`3xeI+1Y_VbT;36-I^WcT8vDgKWpo5s_ruvP=#=`MVn|6vIWX$FB~;)54e>3V=!? z6C`_x&Qz`l4|pmJj6+jWz^>9|D&uBCR=Y`QH?z6jauN9h+sxw;FF0BA^FQSQWws#< zczdPAVjR8_mK)EB9>{Nvn;g?5k4aphBTCXjY${$!2f1Ed<#i`Q<)MsTLr;b4sQ%K% z$KS`Lkosu$b1wNm)7f8GN`_s{eMfY;zi<D^Ji*@0Kany9eWb-gerA)K|3;1sg;4%L zqJDo0dPI^YekUIkiTMqJJS$bPH*byCT)FW&Ryh>4qBV*|o=>ac-JUX`T3hR9bjE1} zY7n4p^9<oNxZ161uuO2#zNJ70a#sWrNj_iXI9ke@RO0cIPRE?+(B?iWN=$ijNJa3Q zI~RHT!yT~u%5OoIn`BYoo@FIniTSaJPChM#tIUJBY%;o@k*HsVkO`HT>6}|E`8+%s zvJwkO80a#L@gP@z^SP7beBOiNi{2<@3hTGu+dV2hP(S?+PzSk1kTt^BNwFqvFa0xR zQ<bRozba33guEmg(Wm7%X_R6nBr*DUSBXy(-Cfo~oaKNl2JdfreU>B?b-2jk;gKai zMiw__BAOe|<V9_#e@Ztk0&Bze!~JPQ9s|GRaILoE2Ev!v;@?5;E0#rEl2<M3t^b+n zdrF5lLq6MO{Ar~a?~l3R<1GRkN;iw2u^oy#kiX{-8-i(EywM!kvz)1K20fA435u0j zEz^ZsRYPU!#nBUm)H6&WaW@mX8<6QEXOF8|sAuNVMJL_^FQ<R0;e&E7iP(k_t^`om z;cI|}J{3fp6hioOB%a#u;kJn0WtaN_kKQ7mWXhTFmU5a=Pq3~h2RLp^AdG3_)VQGA z*gfVck1fU`^5&7@dri?Wu#4rvA+;p(U|ivFL*60BHZKNY7>vpFe*<UowBCFa#W>9Y zU44|_*vu{(1ce`Pv;cF@M&tt+!6<d6)eK(Ij_)l>E+e01@HsTRZ<sA^4CzOjFyH!& z8|DvCrI8g%#r?=q-P$*g0vU+$9gz9=7*Xj8;K&c^kX#?56j$(@vxm}j=}EQr#43Cq z2isC8Z^<3v${(y>C>~JAQ~@DU!jjT7FJ&|MEEr%u5UQ#Xrq*{3s3_wJjGrz4x!+Pi zioqq3C$FKm|Bp@NRAz$88QYc5tJ+;a)Ix_ednUVQ|Lz<3_Xn~_()ThoJ$;tJu6Krq z5!9zzRPJQ@cylCc?t|iXbDU1oi1B2K@$(y&N$+Ku@dS5b%9dNoqf2464plfQ$^Ca1 z1#>OZ3#XM-i=ky{J`~vsNq5*Tz-bd`0Y>b*;<=Frv337!>@iNnl~$JG;Yo}H%(tDq zZ=AwflqvaNS6@``mqkm~zy+@syIQ#DvU0C1JnV-<B#hvCm6<+~5DR7~T}|YOM+UJ3 zi3p*_k7TgrMmXqTEFv9d_}!{IEUzg#I1|$SBk0oJedLKs!PO1Fz^r?6N2bm83N991 zo4Uj}K2S9usc1-#uW=T!-<eFp!3Nvl>xSmH=Na`v(&u|f{7q7Ua_H)C=YUU1G5)JR zy`-0U63wg<!QZY@{qH>pCGU8}=;53dQ%{~e)~IT-9j2aA6UcqFIy$%@T62TdSRBV& z=N~;FsTpW9KIQbh#PRL_#EnSJy!`VgzdVkWD!2*6aMIvA6uZHHk9RyE??05ED)2em zc?uB9F+dM3x4-N67(WSrn_E`@(*;Jgk&n6FB;(%1RMgJQF(ZDcsxM{+LVY9i4Nw`u z0#~WM_Lo{H!u9JjMJO?oO<|Hg7n9L$#6Xhli<CwLdQ@oL5|_lj)X=53e`2AxR$!tM znJJrSZ*j2ML9FF5`m%ZPx}Qv4ViNlSI@Tgv$8fneW2s7~XXU&%6TJ(DgMlV25Mod! zmB0`P1)zL`fn1JZXHfy6PiIcFF}X0yY)BzTh^(W`aJwIwa~kj?8a*>Tf%3@&{`cHz zP*(yx2%+zhO7_ZT>QYPrnj=41%=XrIF?tBIG8izne`jzx%CcP!2RScFOZqbQe9zFe zoMPbvMfV>;G2_pa!Ps!wUbP^{H!LXDVtvBxd_6Su{cEPNIk1`(How@5a)0k%Q_CMv z?&0`8Xtq=O&)%ze%0EfxMakT|x>tWrW~b=H`|ql9MQegsx`x(Dj9kN8w=YFHbrmKg z_bs=DwbfPCd;<b{UY89k->Zt0^3BW3i{oOvw-z&#T5@M`6bNlY!=EYR<4Hanw0mp* zMmlUg2Tp^MKuHbU^4Zpm$kkg0$RitLH=gMN0z4@vt$xG9;0Xgl-%pjFSl2S!)Zb?& z1v7ykdRi#&=aK1|CzZbqU&>VC$Acf4L#ah>+m84%U}RL;J(M>~EFK;yN^^?b4^#K- zYV)ZF0|w)t(#dD#1s+{Z+K8|MG#npf*2d-nMpansKg4f0j~^EyQebCsh_8nz^yuUI zmn93}`yyNJJsyMZbua0iy`w0$kLamXMp1^^%jmkJDmU0`O{HIR(WOd9qCcxY6fsiq z=wPPX9G`kr?5Mo?oY?#w%UyiRzi6trb(=y|r#DIDzm(5>`fFaP>22T`vfF10|I@1g z3iii%j9!Y5ZFzyE;2_{ceu%35Td<OHd*v0^+{+eC$nbN9%K<$ra`bz2CNX`@YEn1+ zW5B1u5~|yrD_~348Hr!<T)<8yB1RjdQX~m3N&oYxC{+Vx)K9>O0AMU_Yj(L<+U%(w zX4JdsnZ3;sF|5%^d+#yyzql)9Lrd14n|h{SpB`7S4Ss=fT#XS>E&9tNcs)MjREuQM z$Q^X0OABP?vGeI!qtxjbyVLM55Ab7nomD(g?DFtJ+TJ`UV^ZdFg~iybo83eLBY}ub zFKJBos2(;f1K0o{O6g)*njXf)!TVB8;C=~27FbK={I(p5%*D;NU9AwLV|bZ##38?x z1+&bw_zs&H_p5h|c1)c9LDQ9&L9vm+-7uDG9UbhlugG`VCAF-Y=Lqu6la@9EvI|<~ zRReb!_N&q$MRB}#Q<i0BYS<V)<;~~)@V^N1kEbNgI4^n^r01dk`AtXx58*=ChTuNa zpSR&2H23-M0jiMB8;KN1h-%y!d?Q(h7~3Q7C@cGA$$=MPiClgwdKDYj$fKe{_<+(` zQAyXJ<t6rR6$9s{@`rrJNIwOTO3ZNf)&el~lzTBNeV&MZWtxBZGX)#0NL<G0<hS^X z&}4D+oHWfxIuiQ|L-)n(tzFZG(;hH6*u8TfuqXDaYdMVNhmfWMMWJeOGyZt@x)#I; z+PKtJsubP7U2hcp2#UnFHX{WcagB2!-kSRO3%I<o?CCY0E&`*Ch{czq$WMO;rnovs z8c(Y5epS@qhEqu4D;(eCCW{B77snTKGb90H;&<m<AAk8;pu`S2j}8{g+-U1&YK^vU zlclGR{D2#}J(P@AO#nJdwVEJYk4<HIOs)^H&MJHX84maoBgi(x5#8ZPE2_WRcAr_6 z{z;N3-urXQ@454C{~J*KyHiOj;t%qYC#s+~>-=+6qVuN`_J2PrW1nWD1ccjnKuVL6 zTwB-wI+YCU@YG~uzQK)HP143pmjKAaW<V!{`j*PflR6i-iINF=E=pW~j4d9;t<LDz z;%*qAgkNEtK6+}{aa3JPI$3w7Y)HUl)Bk9ZE#d9k+MiS!$gPH1SIXELJUm>We_@zQ zc9Ff`8?E;&*S)cOH2RJM#QPDx<kdJQ0Q<R$aqxOJqCj(t?J!PB8|)BSx8GUh^zBf4 zX1)fcDG%Vrr^{oq*ui}TG1t{bBNFf}`I(_`9kqq9QQAeWubBnROE2HxJW=%KwxRWc zyk%s>HAeLf+<t?)SY~<kOyLSI;hsm~1LnCY+2dT#F|JSsf)snjXv6^}+&QdW*DM9x z&8fOj()PMR`B>I=;@-IeUBd&c@^=KbcFK=TO={z0EH>tMe#u%?e1JQlZ}yAnoxeET zq4GbUcXWAY;y#V{e$&<cM(lFg-VAo%J7(qdmmV{BN%Loe`O{ydp!eMeDM#n(^qoJy z-EDP0>}PTXmcUl0);LNtQ{btpMlAvR<!-KYUf(yliZz*cSvh^$l%(?L(I%H1BcbjN zaMFY<dzU8*UzjY;fk}8!U~R;5gV#B#{%}A&OoHa0@`VzLykE3?rzR=BDIOQY$z|-* zDJqE83r9;Go3t-@g76Bb<@v*DF1{}=+qz`~wOi|7GI;8(*Ff4_W<YRND=(|hFQf*Z z>tn0QeQ|F$D-*l737+1B@B5$CEWh3v`7anh6n#7PiQ((VTxE3C`RLuSnP{8MiNb{b zu8`h%71<a1el_fB@vMlfQ%Z%Z>$n+Cp?A!9A;(l}5y0M->hwzPzo>`tI`s_;Q#;D% zJOBWH{J1Oc$!Cfl_9%Zq&h%c<9&O~Uh&Us{OHX{yhbM?n=~!{w-5d~|Y%B8Ye5Me( z8maw}#m?<;Q>?_ILps5ApDUF7wm_nG<_L`O+5%fz46cyX1pxUop0*4hCCs=}Mfd|B zgfcc)CB-NOY>|0pbl2nTX6W`CisSOKtP8au_{cj(k<HXX=2pd0UvdZG7zqejZrilC zZ61u6g;DtpzMph0E=>O$45Rv5?V?K=Mu$Mc@*uq(^*zfu0QeXQmO!z8c^DI&3ox8n z#C)I*X5i7k6m?B~%BPigmu)V%`1<QG->qV^R(~xDsjugqp8p7@c7Lu=zs}i=^-7ye zClj1cbruN~Hr<OeK&`3$=pOt0c0Ex<*j?Ppg0_0R(x6HlV_KO!CwWoCf6(0tZSuHm zL#^wLtzKf64`FTiZM!#8JkCl98TY#0MUcFhS~?N^atxmO@v7;o#ChM3y&<2IFE=nB zD0nKTmX{Jqd2j4C9;#KJ1q2$-t*PrVonex=eqFNrPU^Wm(w02xA!#3?x3VKf5(z)9 zCZBg2Oj_!HrrTTN&h`9>mQ{o0?0r@#zenPs;s>e1-&sRNSPCl7;^UMmBF%NPp$=V7 zPmW8;b^5v=6wqkfEZMZQtFNx^_xM4*7Rx5}5JF;@6zRU_n9;-lbq#~8z4Ii;8@=3h z+5?Wo_5=a1q}CA<;skb%JJUi(oIGTK+{ho|>Xr->+U7~_+q%0X<s<~y(d`t9Yo0%n z$&JTha~yaL6Iz}b*di|<BWT1x{`N^lG{)WL1XSg#1Pi@Yw^IX~GTYiQYZ*%1)jCZ+ zIUJuvyVDmuX2V$;f>MyNN{4XMMrm0$2wBu_W)t>Sy=++t5#_yDxW3ezvS}l0OLCe= z-Km?}Kpd>3gMZ3{ycDel_&OPsE*Z7!o{bBEwyl5G{7M$(E?InmQ7Cbra-9Lah~e$i z0td#QPrpf>7I&JX237=&%jJYXFuo;c_s!uw$$z1ne=2lSD_9iag4Qt31fv1Nifc~` zOGA$GCJ@AtB&*>qRA%DPB<)PQXrGe#O?G;EYvR^g+l+H%ysTZCHwll(9u9Zh!z}5+ zUkQ)1denR$Cp14iI?m}Jk<fRbC~BzrF{WnF?ZGtAzV5(7?_H$x7LZ#^F0{Fd41n<{ znJ)@!mdx@UXVc-)e2(`YN->Ve-}g8*i0IsXf3f$NugOaJ>phVuxE_3eaWI(t)Gpt1 z4|rbTU--sZG_m8+JxVFxJMbx7E(U9wM=82B!QXo}RIgR&`G;w+%I9M=FCTM8XF`+I z<H*0Oi-1ThZxK+w8Eqk<^-`NhDpBApR|B)B6vDUj70$+qm5;wgl3kkWo-L`)BZtAR z75KRk9tV^=8xP<a*V`5-*i0eBP|u~~(Pi%CJH~{w?_Kvr8NF~^|J7Q1^{28GV!0T+ zzU*aa-W`0m9Avv^AZ^^k!(#`S?fpNkG~U#*EYmq8VxDzVcRpwe{nAdo%QPU;G_BN_ zTXNsPk;z@Z8u4c7c0s(xSy{PL%3fK2rJ8A3(KqUyNxno|G>XU8G31ZCRNHa?G!7>~ z7sC=7MLz&>dUH#v`T&V;4&f?pNYf!?c0cQu2HdGup>=ydTTBRSWWGsG7T0A@i?~k7 zSGnQ5xT%19O0nR{H*4QEBt`l8ht{Okr;b)VkJBu_6~-1~_C)vhv?V{kf3OUT#PQ9b zkmN^0&Z_U46EK$p4-7J-WyL_<czTv!;wQ578|$AmnjPEJL{}VI0Z|DJup1D5<bFIp zRWkH~)Sr|um;4~tzq)MVuD9FodLFUMu?V_c39z8kLZh93K+nP6Ax!d%=_uAnQQmF4 z!upojJCuraY8vH`iyjlA>3U^gDOB`2OX7jU@)`w_bU=jl;A)ev&Ob_Bvm$ynG5NOH z4d+*NP_M0ZvPm6~M3p}LHZC#gbOV_*Eb$>#{cN{!@3djcWt(w=HOB;z%%ON)dFDF4 zajwMGMw>;=sj0V9@OIp-gmVPf!l6gw84>CekG9McToQi<+c&gNKD=yUt>3AfX*Eu; zR4Z|pz4s7jDO{TI8!m~{0>Vjl`$NV_cWB@=<uhrVRwaMcCgRE8^1tt^y%AmBSb<*S z${Nw$-<sB#TrZO4gYfMkNI5sP@6<YO-N%UTDN;yvZL<viS3_3H{DoIHx`!=#E%8UL zP;kanqhsj}nYWfN?&M5-!C6qh@$zGDzT=n>r9nWUv!br9Zd*+1qn&<oj1JPtba$xc zrB$i?f@nyT?YU<qrCHFTPq(V-C#o6k%gy1koKt*$rz#b5Y33VJ*q#n$1A0%tWgoI7 zqtHR2Ovpvf+HSBN<<&yw*pi97u0XDst(ml+K;>eT!nDaHov19$aV~<ZL!f>`Ipq-y zAR@DBv*TkNj||i?rZHk1e?+Wk$6%jGdBf)^_Tk1`$UF`9IBm>Q?z7yoW9q&;QlVfX zh2$38bo8d!L!5ls@txK170#PYtBYBTiprm*^}}vH9S54=Od`{x9=Ob6VfN<iiW39U z#4cwn9?IbD5#IBz(%i%lmE$fJd>JNpN=$cI7H0FA!(N7eWH62|F0kTqWbbBRxh3Zx zrs<|>)n8sXsnG|2-s8T+app?v$$}>hi1+%W$r=iDcdE@cg43QDpB9<clqgI1N4J(! z@gDCjFn$#@US9M($TguV`oZ{Jm~_tmvSMj1M)#|7pGIwjNHb6A*oXnJmT~aoGHgWp z>eR-5ImdQ0D~60c(bhFEFrc&hDmVN(xO3J8%1c@>&5t-cs{Vklur!%)c+bA&Rm{xy z&j?^+-vzKtIAJNTH{a*IFwOatZ2(8Z;Y7kxbb?=do@`O|grsoh;+SBl9ZGMv4sax` zgrxc;IiiHPt1fODgugn6tC64XcQUoEgkH@U-)5vceY@i`1&mx^!oP<$<>hlTCzYyR zoE2OSI!>^X;NLD=cwW&l&M?{eKIw7li;yk=!{ay~-*Y)yxW4Imt>v({!r7!Hv|Zn8 z^&}N$hRx9L6U=CBvLLcn>uPbqJS6S<FrmUOoyu~1$VCzmc>DQ~i>F7M;TcrF_B`8{ z1|0P%-^geAK{k5^2Ef+)!gf8m_DBwu)->YZAXNs}pHB>u943pitP}=GDhTS+by)TQ zPs;l+^cuC8rue5j`OgYVe?ihbuW`L42UwzaJzQ5KmiDhNL=POwQ5PY?u8KYonO|;t z<}v`5e=Q06UA>cC^4pc(7fLP(u}dtEJSlV^C_hCD;(u(5`+!F&afMyk%O_kgx;r_C zz@XUGtn2qXmiF2x293Y1!DDnLK0h>Xj94?WcooIyMfsVDrh;PX*DWax%VQyn^za>X z`+#<d-X1nTV9%w5&D_=Ry6bk#7aHA%MTw{yyW@q>U<b>BUb{&EOj`)GK|eHsnW|N% z98MZmp7A1P@}4mB{nv~3VjXI|y_oR)H1mLZzPDpnw|GRi@&PBWSz#y}>KO}L@zz9x zRz3&{O_i8a(<|aGz7_RLe_l;}zl-K;b5+PqQZZ)B+%bS@ejnle)IqP8P2ra6uRT2y zp|^Y9gh6uU*R8g<Cs~VR6)f@p((0l<HdX?y$T#fVjU!m46?L+3|GlJaa!JcKI|mdw z3Xr`zwPaW4if%sohJ$WDX*eo}{5t}j1&l+wc%E`mSNct1GwfCYn(q>ZXkYSwN?xHP zO@B;zd|!0!T?n`b%>~~qvmi@n0!mX=pEO=Vx?)mm2}b*pEYNLzyg<isKnNr-mLKdo z&9Xln{hQ&y{Z$6YMHwvR6H~A3or4r=cSJpB1f02JOb2-ppdAKhBR$u}mT2cUEEO5D zXOVCDYJaF`B9~d^&%Y@cxlUJZ0HAeN9WKi*L<NXPRakZ${{dUy1H_{N^*od3(er9- zs~r>&p0{eQlii?6b~C=<FP)SiCb$wd{}wrzmh}izk#>GGLOR$UH$5z?*fQLiqG9fM zG4@NRYT?f7gwdzvbL5^RbyF6#Jl|}P>lAYfg|)82jzir%x#s=TF|`-na|Iv^){Yz8 z!k3ZH_v0t4cD46uwPzWQ4u(kwgKt#LyCV{XoWDJaxoMJ!crG#FI$2eL<Lin)^nzgZ z>ozV)a1%7vAzoEFTH`}5KQ_qjbD}?z#}gQEzVw}CohbT-uE!TD9+IU#3u-=5yjLuW zDTf~0F?zl%>nT*%^`=24G(bsYre5i0zyKPA>}2lkR4x28M|%)6+?iOgS*fpfx8$PJ zfvnck`ZkZuscReN<4noDCwqQ6Klxr6=ksR{Smk+-t)u7dihn(m@$1S&>broJnkJbq zTFa_t3aH~m{d@VE#F)$z@=tJlFY3z0nP~dyyu$dZb=(5ZXM@{{$cq~fYzwB{n(zg= zuumr{N_iKIC9bzeo5cws=k<ZD+l?GA*{=T$PZB<8CSWLVZO-K1iHl7wR^J^ND)pJ2 zd{1#-?nm>9qnhhIl-_lkR@HCnpdoR=rReEtmG`QeR6w_J+0)zd)9lTc&67UkFfH3f z+@kabw-fS5I&b4G)#b`?lD<*9hZQyJqzpWLy@z`qw1}Y_{S;m(lf=E3Jl=+C`tuq9 zq7#rW7F78M8z)-6OzQHFkMxlWIRdJpB(Qs4%}^T`lerGo0S8!u`OIN%Xw}3@b(l}9 zeyrCjFBB5)JSvfifrmPxRn;VO+d?k-OlgX@wN$f<?^D=XEWaXukX39^-kl6*&AJ$2 zq3c;);)qooq0CImAUDaezc+N?pmvO><~90^jDc~R<Ri*g+GRhJ<AAe`Yh-F%0qDeR zM+8WpjkC>{i}xpd%w8BXOeuX1bY5QPoJlh_{%J_V63FkosG<IcM~gH_O7PS*f|z-X zUV!E=(Ojx3GmzNI97hYmfoF%m-qrOXd%v{gq}=t>af3VWjK{2S|6EVh6URU2{v93O zyFN4`;5zBtpx<#bG3!&ju1(9ARv<qKt*4`!QU^=u7zb$GKj_0rjWG>JJ!w2>!s7s0 zzFWHu=L&^!()1MV6KOTPp0-sX;pN-9^X@ASOYQ3^!GigEHv3ec2t!1Uu>&*Kl~I(* z0TwaZ9`do)SA@SFD(5%?Ea+Xi;DL8c(yOm`<><l9x3Y5*oh=wxygw0i^@mtB0TZ3K zW0gKdec!UGZP2;a6cA0UFXSgcyUpv_x1g5pYLR)X+TA~MKEm;B#iYrqvhMY5<g_ML z%`uQV=%o3qGbj6};*%p)#liDWe+6E4pEOP=<54y;o~R0M9Yw5^EriJy_tZ00Wd1Wl z1kRZhKA*>@yzj^d#1juOaU2#&FxlK^yFMj<5bgK?2M#V9Lmr8dA9&vWP^ttprZL%3 z>z;7BJsR5fWj%@N{8RXx3U$e@!@uzUU#vtq8$pj{w!N{e_3l`i^x#mT^oiPyw#aT3 z3#z3B<CzoQM>-z>3kJkvu+m3<sH;jH?>5`BrOZxw{sJ|_^!&nsX@G0*bE^KeA-sEj zsz&!i*7H6qR$l@4HUJ*Tl4N76W^xPvXhFR-p-q*+^!$y(SmlTpZ`WYS`SJqgOXg%t zhU7}b;dx2=1Z$>HU0Wo(NJSQAJUV+7wRiYB#(lOO3ab66?wjG>s%kAC*U0Q2wA!A5 zR5oIcf~Q<%Khy!-Es!_J@hsP?w=&}GW+kH>xJizbCN2<Z`k$y2M@HT0iWZ7J=U`KR zO)wtEW#p2NvPeZfUwInfjgA_p=_tI?1XqqqI$F`pl<<j02k&h7*;7H;37A|>)q$=h z1)zciv=iTGK#}8;+htcyW_mkaVKM3;nCs>1Kdp35H)k_WGjm*$eBNoUf;m8{@M}}^ zj_$>W7qpk%#ZPqX_D4#Fza!e5?y~ux>s?B){|p?Q<FTl>U+_w%qDIqs@TA=DxKgIO zI{g*8l*MPqNBHnnd)Hh4oWIWJ>0hK}@IzVCgH8~i);Y+g<kF?;m2<!G9eVIlPZxh( zTwUzame0uoDdHSMMsHCr^P}X^tp&FeOS`T!etywyZM%LDwXXAU$-Z%d);q_A`nnKF ziWG$LyXG6KF?t>$up8nQzxuN*9Iq=THJ|0!Syw_yZ!Zl7xk9Fy!#-@nqx;QwMeTli z?u@H{I0vS^P`~BrVQf{pPO4f6XrYn3#u_GqQmbA?@Kq1J_=BMOPl+Fd9O`-Oy9A9b zblJm4r%Lqzt#PMu9FL3UbpF#m%jY;-1yzlN?%XN;5}gNMuO+B|16I#2btdApPDaGT zi=E<=S2d%95J~Quv5^XkQl@#g^_{(Obv?i04iD3O&LbpqByQTZ*Q3?|uEOt!hEi#r zQktlr{AZgvADBAC4&Pyy&UXQVC-6(f<Q($^kF{W!K%E$Q9$(YZhXVTQ@d=Tbn{bZd zPz$QiL5Wjg_tUj?YNIE58Xd+Z+LjeUE7C!o*N4^#E&8s(hNc%-y*4|;<ZrIe=Ep+3 zN6?1MY7ZrM>yNXSo=k+S)tL1$2HxGaUhyR5DyaTIt1svTt6bFh>^zTHFP!T1p%4`q z{$L#fuH(jdAe+PWJTD(bY7CKdP6Tij-<i;`OS&)Ezf6ER9F+9mZ9JbadMzzJvx_B8 zNXzu!@j<I{|G2oSyM`NI&bZF(*b=4hu>?!@iZFHF2aj4#__m*)gq}OBsj3Mj&6xo! zJp=kHXLe~V8?WcxmQ+NGKUHpjVDhKdv>z_{^?s}JO!HEBU{HK(tUA8sjNalNIi&oT zM?T>|UjU!P_0vSp0lL!2!B4f6+ks?Ke{7G2{1lff?z*<Q@K)R2V#;V_<Rw`2gWoAk z;`FiZVD;5;g&||k4F<@sB&Wup4L-^1d%Dh7H5wjft9O?s^*p|nO%_*nyf3w?S&IpE z<mlTxBcVV5RqM&l?BxSp_I1ENS%O`@+_~SVJ-?Dav_+0Vzc_YyIgnEpR+?2?eTBFf z_FpO+l(=zyj+t@(&1+a)P<s}?A4;IpCJYmGTph1*xIH<UU-X0Ab`~*+Xp7de7M;Oe zR6JV5KY5+J0;5f=Vb7T?cu}-oTz~WeyX4QbU9AI2=99cUGOV}qINR@ZOu81jrD5A$ zvK){<7E6~9mEnAK`V#}|Q~<TPAM#Lw9ErJ0jS8PUt@NN<6$zoMldLp9E_S2<Od~-j z&3{03K@A2Hcc^@kX;&M=BcU&~7@F_$D~`RO?#eIsW3X6diu-b@M%D6LuFiG8`?m^H z6&DV#fB{=yPd*xhY7eIA?Ic*oPb8YfqwPGV%X63hP;%*&nA$DWq0)8ix<vail6R1V zWA%&JLe_dzGT}U;?u;(Q+{W4sv##k@STWgO(Au5?wr)6f#bVniRs?UJ+)iE-;S1C( z(w%fSUQd~GSl-M@zO@$7Be;&_cXnO%w45jon9`fSZ9}<wv4;98IdMMYBC6l~-5^U< zjUz7wIhn|@zMRVrG9Qd@nszX~vKfY}Pi|f{mqIpT+wcZixC$@o_%||D%*irX<|i}D zd2vY?VAhTM@3G5)gRR$%r)=CK#VI-&>bC%cwfn$2hQcz%!?^R;1t~XWsI2kD3SI2F zS+Z&foxL*9Gx4vb96kSCBN*g-u)nts__b%OuFvJP3>&PeY?B7o<r0b|1W9@+-|YL% ziMH(J^ECyn^9+9J<*EAclVh!afQB`pFh8xAhXrS;oks7Lb>peA^Y!J)iXcHgd%?%u zFZ32A-iT`r;q|Z-S2Ty4$>n2iqXp_KY^UV3=r48e+LLYZzzcz1?z<i*bqimD!P8xz zKip@ljtjZ?ICu<{igL~~MN3TXd(YjkwG4xWT2ro$a!P(QjE+CTS&D#3+~8|CQg%L> zb81^p@w6I52X^iQhVgiVtSGfSq4_^_sE4fPhi{KsC$y|}@{`t!nyxQ*OFfRq)hV_L z$`p7Q`CX2Nr428w>UO9XI)TM7G`b`}An@FlTu|=_qPwe$09dFhLK^L%dAI1Bd%)t# zf|Ho{JzE+rBBD7_PZ(V{(!TDWZ51<}FfIJN+7I=7+4t#9^+6AM*G%9>^q|Cf!5rU0 zfNhZHoWmqp=A0#X1f}!@SvH!GU-+olEA@&T@@o&f^Lag7Wl;E;+T<EAIdQ?bq`Pi< zQ1Y7gwYbm&jA6cIWtp35ig0%ecxES+*JR`mdFO7m>+J4!zB9RRFx*aEc4+2>(0k9} z!Pmz>(8tfZzH)uqq%m!?BENj1nmqnGLA+?cx41<4FH%>f!O7@ku=j8MkXoR^Y|fN{ z3mNxW&#`hAoFqXU1For@(22EuRN46=nb_i#-46~~AxV%gzcJVP>NC?@LFmzJ7-<w$ z)Tew$y#g-R0rkgtfIw;Id~5qUpZlGY&Kl=VLy~psmp_fQk`bnb7pIIdfv!;)v*U$A zyWsqWNry5!gFlX~Q5)<?<;|Hs(uZd@D<(X87Vf#Iy&1MBib{CKf{+7N?~r}pXl8Lm z>IF@GSkH1sa<G8=1~c3z#ueqySHVZ;+$~Fi`LxPgN(PEF^#PpAj3SmBX*w7o#tvKx zI8d|cMi%;CeNY$v7J5(o0oF*gP~ELT8KT3TB_)#rVN)!5o<vkAurnt3*gK=%S%xL5 zo7IQ=&s>co*&GY5FVc&e;5(L-$0KPVDbPcgZsll%GU|`IS+4iHjKfHBAw2@3__Mcq zNw#<IxZF~S6xiB~PkHN`tFlZE`BI)vG`U+r)Hy7u<@$o#erNVcVqKfp9vaYr<)>Ls zAWOFHANq62OP|~Ur3+~$pW3@mofJ{DT2m!X3gyzG;^XW8YMe^7{ekP_!pjAAgGp7d z{5SH8>Yf~J3=8rWyUZ&2$CoL%X!j&O>bJWcGDji7F9r!<@?6ecLIw_ohHRngg`Jo@ zR!fBvPk#CsUI2q%_2*+a87e}>92GUzobqKJW}|RP2q+S5Tc0fDq<HictSUm8IcD8X zc9wE)Uz6GOi#t_c<ZW%QyzQ*coTG}-rcLU<J8>Tcx-PMs+Jt%LD#Z+X`^B`+ST(jV zICPFJ!u}*;TjAfn5q6M}9Cy<zU?cFi0aM|hdbaI~5o@Iu1HO03$t@Mx&r5#Bs<<8= zPqyw<&3}A;=k6$4&f}3?q$GAIL!jlp+2bSH<|ijXDzM1-_nSp^yHwXw?P=FNy}SWC z>bh<|gmrzYJ~Zq|^P+lglO`HXqhT9>c>59o6NbFg^uif<C#?EhSS!VIVDpLRRakFd zTBBZ{$@Q$mIgi27kMLhoRdT{ReTM@5UFn8EXR5N<?-)N{*xk_Z^UxQCuPcik29p}8 z&9bG5TR>BDos6AKLh$ZKyUkbYgjZn$ueR&7e$z50{5o1ct6K25Yb7wV!d=2nvy|#E zb-Q!I_MUuc&3<%UYlG9m?WA{Q4nr|b+m(|RNw{V3_wP?rC?shaPuJT@wP>{MT{Nab z;%dJ~v;6+ZlwFq8MB3gsghMc3ts`s4L(^07J5ptEVAF!=df^Hpc5$+Qy~+SNcRA## zy!odobU_(>xb+BXoJ5Lx;dypwWpEC<rp-UpVKQBfzw`{f5EMHI^>2MD3PXMi1p;Cn z0y~=G6gpW@-Y~SKkZ0(4dIou5vc+j^G1A^}Dj|AeYv2Pth}N=9h%-3+HM5&LiFgT) z7ky;2H^oZvZBD~t|7!n!pwA}+M}skyt$5S)XXg1zeG)Z&>|9>{jQHAj>_r5|XJx<3 zkm$=e&yXK8i3m=X*y?rlVM^QXH8$t|cyJ+;AyfUeRrOM>x$QjZc%1eiKajg`-#WUm zGh9x=Q`d7+nGc<vT`6L6Red`C-o(9d*Tu7?#w2!SDu+dH?>)<jw<qd2jE5=7W5Q)= z*V8Q(-~~sNHV$=Mb#*)sla`8RtjYNru=Qic%6Lu+B0JoqB^OV$9lHsKhebz)1>3|o z`s{cMj&H^E#}pTsd+?DiH(<`R4oc%zE<XXNwW-W)h-tY28pKWknVzTcxaC=57t#D} z3BxEQWenb*bw2vUzE-bpd{{Xqpn#2;KBp}Q2qWKqVk_14q64w!%fP`>)Gm!{N7o6v zhR(v|SR6{6sTt}uUHD9oX<_hTM&$Z;)({Da0^=5Ej?4ae8KyF)QB`#<)=FTAEu{Xy z)`3#c9a`KZL<E;1>Ri4XA}&T`uH({ACN%%){t5!XY4(llm+r^+nY?>|&3Ts0&4M(a z23fy?X{cBeWc8qvLMAw^1m}X-F%=kDs5nMrz+j*K2*_cS__vUB3KFNQUS(&~=EWc) z3PuLZf~O}bZIQSj+&Y0_37ua|o?umLS{dLPlj8Qf#-{H{=g-tk3xlgY$(10%R<7du zJB%)?;U!Cc^nP`_jdeuyyU0mBPek>vc=K(o&sQDs?X8Ey&xt|z6d;?K_a}q#$%UDN z?hA2pBfB0vk<yQT>F~RSm??->aoVD+ztys8F1r7Y9~nJ$QT1{Ft@GYNFJI@0cY<}J zh_?HFyTQ1sI+@e#C+R7>L2*OMH<f#{jtg`U`;Qs`-a;mzRf}YC@LC=cI3;?VZ5sH4 z97)c%%R&hqJn!sKzB|CKgm#MUnm?PfSGo13%Yo;S^YYdCZfFY#mBjrTtfj8gTL_?* zSXT0Y2=@a0ffIIe3087T$H|V4Gq7EogZgCkLMCmQ^2Bk~Y+UY#EMhf|o)ZMgRl|uS ze?isNYdSgsIp<GPE$1B&wr>WN6XwOW+zNQmHEJy@5N6ixdg$IRsPyjD-)8Dr65)P! z&9}G{fl-*_rmZ%CX%D|=-!Fo+H`?8MOTc2kH8D58wVJH{BYT2N-N2hf6_c2>HCJ^U zlDBqLpPBhk;X|8|LcdJA?jca#<EYQxXhMltwCLA-?Y<dXKAOA3B1Jj%i@vxlCwN<S z=4(I;ES}=XVv~t>^_0K!Mka-Q=3a#De#Z?G5$7)17-e+UGx@B$^n2e&c$Jg3^Ml{j z!kIMJ;1rB+To(;|hFB!fKl2@<RCK!oQ|=`k@%8s6+w1!~zCozh)K+@waqvl%M}H;q zR@k{m_996=prrXOg-@CeLK)GMFIG9?cz~3N$Gl4Y5bElkZ9C1r`K0nk=sk~3MNJF` zv`Z=H$<k%Vb8a_Nv+-~}%(x%<rnkSxH=`6s61t+ie|SCLo^MRN8>3c}VlG*{!dD|n z;8ocve}*<pU|EaUUrN}IXuDsDZedc7d&WIfC+oaEBV(}k#SNh0h2i<_Z5&!W)CPcq zpMC!NQT-FE4;r?OzYWf#e%<Kh(?E>6VagU-d7m}iWrK|x(8v|ppt7e2tvUgr@HEpO zeNw~VU>U0ElbnWKp+kC^Ux=@$RUHQ~c+WoZ%MND(N@#K$WlPd(;EySm8+4_&un=tJ zGjPI^e`3=$wp*i6NlfzBwpAsQo?A~rut8$<?}7?QyfU6C@CiFCd3C2W3P03!TG<i0 z8XF*&lIm=_KDN1KycoJC+b`nDXtzDUc4hw)<tusaguPTSSl4k3=BAml_?0qKuq0ez zQQ!UR$=9@>+eq7%vcVuEYU7&blw4%{$Ne&#b-PrTE;V{=D51KP@YCh;H%5~G4`pu| z7Iplsd(+*BfOM<0NW%<>f`Wk3of6Ur3`ip>NGc!=BHi8H2n^EQ&A`wD49uLL|GoFw z=Xv?ORWGkWuUYH6?)ACvRr90GZcJ#Tl_>8|-$10~9i!(Io7nkfhyl``%%aAzKVG9o z`8+;)n(r22+MVvt9fnx-;c30xIeed~@9)ZLiHrX}XQ0z7E#-1O9QA0r6>)5sl46i- z>=dfkkW}W|MRH#Qymydg;=g)01_)vv*)Q<5st7c>r_(d?urMl1mb)l!s-yY|<jnfD ztW&<bk&n4v7y?Eib9p99*!B9)57waiK2k%JoImnN9Jr?4PBD;%`iROxBa@jt(NQHq zf#8rH*W`q9AakC~9F0vL?NNht%b0JfXujK^^ZHw4Ip8(&j97R8VUy)gmFWX<?+tMy zEij0A|Ng*zu&VPZ367HxgDH#KQcp^}<M7mz_kf~TK7ynETFL$mA=&5otJU=MM~5Pr z7L|g}G1hk&!op}Bcie18>t^cdzvxz*RWn13{GE7vWN0!D2@IreYHJ)7r*TDk))#!6 zB)=Vahj2Wp;rX;8M2ujl=y+72PXIHM$CWm8!JO?y-<e+4MW=ivG%y&~QC_?LG9!eP z$~-e>S#Q}HRuP$fXl)BHt(V;|#4KS5G*Y1TYT-|cnb=s0X6fq3IHjCfCfH2q!C^#t zS<TO?oI_J!Fugm>ny%@l8m~RDD+zyv<aZLW_h*92>R6eFz15iuGO)+M@|zVQ_?$_N zs{P|+Zbd9HQYS?$)AShV)zpEV=lCVRE{>N6%9{=sm4%~}3ha*K8Fw$fS~Bp!td2fg zU5d`e@P_)@h-89JuX7*P3Jt|flC6)ph4<d)whvPlR$Wk!hl|MYGFL84ok7Y>7W!YH z0w99)R!|Kv`c4xzwl)d<3Kc&{!=gA_{v);wkO)9b7Y9;4obkOS7wbMN*ENPxao&-X z%R$O+zG@k_Y1VlrlAV{;#Tg8QYddNuh}wOt8AoEwE&)-fqNu-l7&<X^H#-%XFTd>0 z=$d}60vf%0;m_Tci`EVLZ9kv#4P)~g8lBqRvvODKTOdSNGKN9P1?z==y>AVFeXUzT zKw+v8jY$I}vyU}1I2PbmepbL^%WvG8b)io%f{-lGkUjmLG1IX(U&_FB(*Y(vmw9wQ z<XEqOAEe&i>9V2X_NuPwhDJ{fe88ZWQUNEuZx71=y7@PM?+=a0F~d#dW*}G6H)P~A zBf){Wb`y*LH3$^I>_6pt+NjYniGg#Sb?00cEHRc|YCRzG&f9sN5x7EVF1cFt=+>{~ z=YKcywXX9nF4}a4rzKA<J7sxqs=VoW<xfbU!>;4?i$`>*RtB`|=r4;8HXlDO8M)!I zeq#ZHV2ztG58Y9!jI1In)SR7mxTO}IrHE273?~2U^}kQR53Ny;F@oliH$7>ddOG-K zG?*)0fbw-oH`nP&l<6bbw3Q(7C!jbNbQ6F^u9}Z$%b#X;`*i9UI@0Lf1R|ovSG+i+ z`p<X8?$O6B@K1QG6h@s-Nhx@V9Xjr>uG-svk2a!Sd2M{<c{YarhPnHBMKtGmr&(_V zWxYYFAB*x{2(?;-*ZaOX{du`+i$#xFV@sFbEcD%O1nwn~oSyf`G{zxRAU+}kvhbwT zf_KhEojdN!G=<lIc_N;J&0!*{`S&HEoW%AI&5cOXQYy@#8}2lR1bs|-Ue)pXQL)9| zHG+2Ye|x9(ihz6jB|#Xm3v9Im>_GoiQ7rd&W=axsU}q$D0Xg#nrB{`ACP-$A^O_bh zv6%*X9fR9$9lR7FbKjk&@Ldv}<$a?G$$ty(D(BLr&&T?~o4=oEo%q(B!FB2oUz;`? zrgo2*2kaEyL4>Rx0pFpiG6;I(5!4loSUT_RybpSqy)p+hdbj^iqsIywx>^qN4BoH* z<mJP?(ssT2aCdL!^(6m0-&R?Lv7ew^`DW-jZxF$#tb$)KNxmFcE02f*2p+6P8jJzI z$GLgV;~Mk!=ZWFUkkH{oLq8#i;4f{kXS>nVJoi3qvO&F^yTTru!2M`}i)878taSvv z4a48SYa=&#xNRD{M&tWU@iGhyjR?q%3CH)9aSzSx7#Z)sZ<s&dn5)D*Fg}q#d8%$` zX9}^cKvC$G>E4IvJ_8I5_QT&4d?$F2Q<kRpzcZ>e+-r*XWC1HYrwQQc@qNmJ@-8T< z@+O8p7+;%WE5=m782J#z6i)j^_wJ+%+W8tYOzgmQOSi?!l9>rWR!xQo(zRkmZGb5M zIC=8B!D17SiJ?gve4_hzS!-4*hjk)lQfF2O2K{LDdMn-*015i)x1J5kVL%!?FqrYO zk|1dQjnU&K_JVZf_kSkdZ!9Tw5X{QldywwGLPAK<67Jh{Z{-xOhzRa?4j!4%x9aR! zlss-d>2o$mEUu7KKlNxU((zb_CliD_x4!0sc_Q%F;~Ppc7$f7$W?&uvCGC^_>-R_L zF2^Yaih;3J^k7Z=Vt2ezY;ur{RGtl-P!i`ol%-R`OR#C`ndsbu2Xfn|JY+Fr^A>TN z>rbx=7KI10jC#5rWX_s=mLy>?X!{^r)1Kc9d`Z`){3lM8`ss61MAN`W)r12Ve+1fD zQSUuZt#p+N$^lMFGTmz_KHkF_x%o*1i7k@%6ln?nbq<Xw;kX-P<cO7B|MAuhgrC~Q z!_2_+VaC8`IWYLG*ptp++8KLC#j&X-u{2$)bcR?dSf}2|wh(*!?Qe-+>E36qr<TfS z6!tGSy+>w&0_lEwOhG9uGsXcuaui{ObCwvgrOYQQE$|SJ*+o{yPuG7nm?nLJ@joH( zR2_Uzmyv{@;bl-3NX>Y|;(dbp)($l9pR4Iut|1no5q=2pZ$*|l(~;o;zLuMqfpx?Z zr6TC&<z2QoEMMA=5g*=qZ%x8(hM`N^CM@;c8qYGtH=ta^hksX8ZCGNS$%;3EV(I$? z5MIq3X5#kQ{iOv7t&#65?oJ*Lsh8ZdlJaKp=^8fT!FF~vTsu%nHy3vaW&j}*Zp@zp zJ&f{W!z7SWasjOw1P9wHr*o7Zf0^XM1dV9%cgLsByXNpWtjy?K6q;<y9evxqt5I)| z3loIR)lN^9w-xo1bfsc4@>oggyiR()dP!L@by!~3UhiDF-f!;gHvHPAeb?Z;)6a9j z4O<q;<n@|_go9kP*Q3Bd^LX`Eg5AdcF~ng+>YE7ZEGeTdS^c47Bq^`6(4=h4@UI!h zz|MO_0x?uHyp82~`rczjxjz~^MvB9(X;RVFUly1n|0fH8&c=GeUI!q<3VVW3KjnF5 zf1cWvGNE@3D)VjAjvx^w9ffZr&o4uFwX+QWfoz?auQ`=ihof`Q6^LbOY*rVL)SoXb z-iDQC$}$X9FCNHS?h|pHJjO7GAgV?1vM87WnxLdo`?XpgBj?|Gl^@<caqH{~$7M7& z<k)ZJaj`4_-#5)r(6Nja;Lrke-+=JoVYWg{=_%~nyD9{x`-##l0NkjG{Rg;VB90i! zmz3prfb>ny)HOnrgJ63G_jKNuRuFz~en|9gbj=t8)xW*NTU}R-wu7@MzMmJ4KFs?x zS)L-%mxFt$rVbcb+=T8@T``up9)%1NR;z&7TiE40B4JaFt~6gK@e_P1Qc-;Alg)~@ z%7I8>n7?Tcq<t4V>CtXmNM~GG{k(vQ{iG*nxi}8#3CUZtuEZ<fQe-d|g#=!}&31uM z1uh$fL?4m^`g;DiHkq2lO>O0da><8O24F<~pU#@@No(p7GunxIPm&~k0MLg^leW7| zU#GQLb)pQNZVoU`EI#B`bKia}#|QyNOz|b4QMvxuLaemhN|l+T@6Ms?gB-CWBQxr8 z;w7AGrGgq5SXS+rBn)DFQiUZM4+i{o$mygZ4nJ)&KX>o_&E;?&)=ZW`@aa5crEp~< z?rhr4^s&RmTq_LN%L%vEQ5rPC48p+1dXf#$xRT|t?DJ?TtULW9`4Vm;_rI@#vN88` zeXh*%@H6+JQir9LtNzG7?|ZXDLpRneKv}mK@9!Z8GwO=IlZL-6DXTZAbv-O=2pbh& zl@SA;Ggyd3X?UwhY5Q%docBRR%W?C!NpJ}#1<t$2L7Sic@YD8ntpW3OMV>M*D_{Mb z#TDvad(JjDx;u_dVdH?@!ha{lh8@o+YHziEam-sSWcRS5BZij;Sj{B^{MF1?c>+>4 zUZ&9B{E`@$O8(a9T`BxLsPavDbo9MrnE!7$c9RZH3p`W0CxVA1Ty*#8t0ip01FqNK zI#bRCTKW7Bzko^Q)|xUr3(D$O1n#<YOjV$N`u*YAg8$DleEgQuOxu7v-WJ~b+dJ=} z@3_HN?bSaHR89S?E5^;9aO>5?=J1`&s&?UiUD}M&x5oPKoftq}YN4#-L+#NnF*G8= za%_+qt84$$MK7J~Ue!7wyV5o673UPar?kRsY~QU;qlbzd*~jZt-q1Df-;R)-=Q+~U zuZxU^IoC0Ml609r$<5D%fFLC%K?KF&<S&@P_8NYSx|!8mKyU)!x=6R;_^Je2olt6n z6|VlK0G!Jj`*J#)nr*iN`Un3U#jkHmRDcT<`0Wo^roU^D50P0-|FQm12#*actS}M- zW9ukAH<L;si)_8tie<j-G~24JkkWX~T2e7cq&FY8@>u9x>C;9|z#OZ#sTs{rA~8A7 z=D%c5xCD{aIX}E39{A_YS@wXQgpmAK9;exl|H|WpJ2~Dv;)bjPahz=Ll{NzEY1NE4 z_-f>0g?1)S*U80opuf}j+lMCnEGe)q|Eax#6us|6J-qey?~;3<-y0uJ|88HF4xd#w z<c$NJ9FVU^;1`3jXgLfgza;+`GNlI~Q*0qV@OD`l(T$G3Z|L!NFSsc1i>YJ5Po*A< zU|$y5q#N4f53)ss`I60a%$2tAkV;97y-1dNraKpf{2R_fm%$fXO+T0NMk3ASndIHt zy@f};reQe-4qdp3-)Hxc4|wo%!Qy-TQ(&vjXoEBG7b~3ju}A)x$vW$^Ir5lhXf!>I zO@IWz#cF3v2I1`j>$Vkfskm*!^}rM%SE?^p^XRolWQO$H`YD1Ap<(Bad3d()doq$V z$9AiSO7~F>tDh{rX8Qa1Zgx$)KI+Z6{CR~~u^NaRh4qK?Ff!7@!K~FZZX|<hK%Xhv zd@eF=Ej_0qu6719EfmJ07*~lKGFM_Y{L}O`k>e*J(?~fJL}l-z8r6L7Q!-ss*Egj= zic^kgOt7RR?GDn-SVScEL4iwpkK13~da8kcWN{i~(Jkv5Uo3QLUnr~RiEpraHESBY zBX$!?^8s63g*&}8M&d)qo<n2(Xgd_dmlWC8-i}ECJg(Q!^Tjwu<c$Jb?AD&l7V=tg z>1>T^Y<~^}?vH#yhpkbczJ~pW==T2mxr!etW%L>Y3!*N)eeDHX<CNH%;61`Nc*DQA z6g&pn{Bd&G=qh}@lklfvsI+&IVm8A7?>mtsyI}2j_xcON_1y9)3QNnG-S_Iz5o6ZL zrha~;;Z&Ew$X&t#MoOEu-{qqCtm9}xu}S!M^u0Qx_^zDTslyA_?y!3HKY$dX#qo}K z<sw!4E$|5hTCa!qveTFGM@wVeZmo2Ulh1SEgab^JSt(*Hwl$T<ZgPsDj6si7I?{vj zotjkVEaCUhAd@4XZL%H`$XIGKd{KTyB$u5IH@VuPjtxbIuhL{u3v}$<8g#h;>vD(2 zoBqRJA}89j%X6$`&;wJ=d@1;$o!g;fJ-IZ>)ka#kMEA=NBcQWgJb#Jtq6+G{|M}HB z!dbL~_mIv?(|%Y^m6Y^}Vryx>;yAzi(PcxgCt2OJ=(K1D8y3Zw%r2H;kz-MM{$%z( ztaCRVi@#E1mce?u{kAzR>e$?}tzsKMWDl<lyZ7F6IO0b7ucx027J0PU$Sv`xHS7}T zge=ak<cQ5XL`kUOvc6lp*|>`m_~RoxF*0BJ!=*~r^rTe4?i-@aqI~i{W{$&FPOo^3 z&F7C_TXK$GqO`v`6t`5Jk5UH8$#nvd9X->AKJI#|eff~&+w_BmIg6-ke_@xkP6^8n zI$+GS{xfg`rlq7iN$$Ag5@U0lGq0=YXxf^P!Xg_3wcO65uNIxj{|UPb=|kX)aRp3< zcaH+))-djEmZBC8=u0`{@OqUop+GkK$zLUwKC>_Ha~1o(KCxZ3jFs(<5^Se)oW!Rb zyJB!|bv4QfT*JVks~-5;ra&gii3bIA3w!#-j~Lx=crtzv#>F{lTw%&%wDJHg?z4GC z+m&+KVPb_k23BOlqEm|y5bE`4_Q7pe)%neCR=6x;NhCc0bt8%Fl+ZuId?fkl1D%kW z9HT-`wPf^EZnY#f#WiYh>%kNHZ?3PZv-le`wHux~C~DZISS3f5Z0}2D!WZV|R;~B` zz_2K;onFLA?mi64!%^L0Z_mo~K07_tcM&x-KeSDIjHirE@%X&FOIk^6UoyLDMY{Uv z^ZftjnHbPwNtABFhDGdrxIvf~wO^kbob#b;+zg!d{Qf8x;&8Y-<(0gA5IgV<z$B#! z;GJq73fV2Ht$~yNZkkqHvuzt#9*=mhvwbz1+7^>`LnEg34bDBD!aG~pf;&erLYB)m z7#4>eHu0hbMW3*gHtoe}41@`af@b!kjQ|2`utZFwKBk^6ig|cXt5|HJb|sP?xe@QD zvGtcn<G&+^o8yXAtE&Y~U<tHjwIYfdVhe2R!OqPv`_kG1@5d?~u-p<eW%<W?UkQtQ z4)~fU$R^6gH1LS%D11p?jNKHKJGgKKGd}yFnOV!k>_F%ct$kI+^95g>{Qr02FmI~R zgi8g_^Sill9YoDpw`|Xz{B#ZGkv%W<ozKoNP7~hQ!J23f)j6bsCh%l^{xIZ5r6r`J z4W%G)(Qe1nZgdtkr%cq=;z5?EnI9_XUmi2Xt0<OC`d=pj0N;i!9FyQK<sa?f7&i3g zG`3_)UyZIHhEZahzxJftF0zR6%VQ(|%gV+JPtvdyT*;?!z(3-sGk*Y{ycv8oCHeBA z9wn6igz9^;sW)gzqSPC5>@YA33_0*ttD1gOSJxll-MgqBizo!Na0}YL84H?1HS!VT zvv_}S|L{9L7H@#*)qStftdU!&?9~Few7x%8GQ;HAu(kD><oIKXU%ia>=*n{e;0{;A z*dfmMG7(cr5B3!RfZ6=EedBd#02LPUZykNtST1SC62FR>Ha{05dk|L$0XBflKQEb| z?$AXL!FZCfzb!m(k=_REHf$G1(z*^*?NNLSf@?0Ru_j*rZ_}S7Ui}kJb=J<qjF<s< zEZ)F)t#RY$X0Wvr{vo~j^|EJgCs~MK(}scD(ob-1!8k@p+9>_WD>tGoy>?i!d5vrg zROYhxBpSD;wDt_n4x&@fAe%hroUBTrFWZP0lzWoak(cP|0>0?<+wicho1U!&Bh>kt zqxvjNS204e0@ynb3+LdHk}7uE56kpUGjRFSA;Z~^)7rY_#3&>VRI@<*0!rVo>kH$6 z0(3o4gq5nvI?XHCM&U%KbF}7htG~O**RP_~6xMkB^3`Ymtq3FFuMMMH1W-u|8-L&t zx4VJ_?xjSKwMksPD3isI58i6p$|YYVFV(sLo(sLxZyLk$dtuw*3(As3*sk8APq{II zrU}(#&zGi*xGPesZNx>I8Q<0f2W=5d>D}tn1fxk^pDWuC>F(;|Zo5m*y4u<F#bY}v zy2N8qSbGX?lJjTM=*hFq*5C(0Bs?5zPxH;u!3S{8qW0&W#pjte6Bj1wS5e?p?gfp} zkw9EwY~;EUi>{?dg#{dY&oKfc#3BnmaemONsYVX$x1Sl8$nV>IykSIcpM<YXD>xU| zy-*?z{Y=!nL(32djIAo6B4h2Wv59sASMmdl4^P!s_0NcEJH!4s_T~Q5*->4d%h3(A z%RT+xrhgD9_iEfSx6xsfGA<uh&$(d-%S?Kj3BT0#hWsGH`RX5NZ*<%G*8!9u;Ib$; z4_}3A1?LH`G(<M3?YiZU>Q=1f(&!pUrn{W&i}oiy)LTCWtRT26+7--@?~>FP1bu_~ z%?#43jDQ~-*!W4@U)afH`JN3u;$`>{ix?4slJta=$IAbPw;@b+r190RB<{|4g=22~ zs&)93FJZNlYU^bUD@69?P1ar~UHFsvQrr4Xfixr!^*_WnMgo8r_Jcl~U{bNl^W%a? zm;|N0KqgN}k4((@%^uKDNR?QO+alLj(I`aYC(PE;hh55)ckj{t49+15DPvDhC}b*u z-q5#(gT*(ohW~*ulQqKP-!^a7#PD7=;ucWmfk7&&MEYHpYAH(Yr1!lN6Ad0|vH$AO zPLWCz2$R6<4p{bu=Oq~whaCWe5;xw<cS9(sNfnzF_q!172c03Cd35ty&TKcpeyGqs zK%eWVQ-Q34(l+tG+s8T3J`};S&z3v}_+4$A+RO4S+jqwnyC>CU>9L)i8n?^6NZ(*n z00Ytroy<T@fSBl&k5auX0Nno%Mk9A97YM(#vijcr0C}~rQq*gmCQ$c=LF%P$$4o^3 zHzAZRQcO}61f1~0%LKQ0z?spzYCEpB&1AJ0D(MO%I?$G1noc-UkUctR)fm?&($Ue` z2X)(GU%!5tC9a#*>%vb=q<Kj9-shRXWsOhlaUC~EBdx#@|DS1tkEa*|$2a#z^8wf% z71FIQdH)@l6w)vpDUMFg;^kTsLjNaYJwD}G4Kw}18@By-^ghMkO-|p(3e<fcE_aW_ zM;-*jRCMk|k_Hu0{4LT{EwiD6aua>8lmK5pi~f9r!^rmu0pr03Z|R;S{SGD*etbkH zl^+zL#9BN#_1)$~>hX9GBd7m$VJ->l4Tf%;dxWX9qTg@kj04)c3x;2UCxl)aVz2Lq z>NS@Q_=#g7+?Pc%-g)4<tTSqY_=SNam`bJ;7R7BW5ct!kt=h<^XHPCS=eqs5#~3N# zJRVwk#Z?ie9#ERe#;x<=eyIgbWZpuvTSOT+o~u%Dav68Yv0DW2HA@$;27Qg2sJ_9S z*#rLn68K24j)2l4GV^7}6tc)Ggbfk%yT8<3Z})*mPA@t%C~T>G-lFKu8WLae_S}J9 z{s?ciCR_0z0QV+RRWCj{4_|0>wd`rQ!aovU{YGr+d!=vv#$(~|QDC6v=}>SCA$W1b zeBMvT1xxUou8Et1wV2}t_!b@z7S3{OZ+#VOB4&7h##{Qp#@GbXw5`z5_Yf-C?o0Ok z9~w^w8Kp^~FLpiFTd=n2(f66RN+ws)H(0eg_eVOm;=a?8MmW}uLjIYia}IH-S(JZb zGAjoYS-gtL`o{#^0oa)s@nva>3&RH8W588dI;kEhk_&aZk_bDQo)hemv>}Vh{rC+i z&bG4f?mJA1C*SxSrH@Oh)&o`-gi)7`duD$|E`Nm)$;DASJknxim@i`FN&(X6>9T<d z#p8A?X_~K2g}?1TkW6)&;Vb$AqbtlHWgI>lmH+ez9OKD7@tT)AMDBlouK2)@B&1uc zHQri5Yo^s79yR>bJ4}B_6&NR#J9d2ii+VKxZQL3VXEOt_b`F2E(M(OVeG|{|$q$<% zl8GT^MTy1r9c&t=BN!xKGx6P-7Z`lFxY9R3$O~%2>Al30;<CB!d;D&~l)yCHhenT+ zCjTR(*_YQrfPrvH&8`%y+m3af?5+x1BtW2&CKA*DT(reyeV&A>C6~~34Y-*(7AdXm zl?|5z;rd!5Ofd-n=A^0{6B>Pw&qt{%pP*W<j|2IIeonk%mKQmr>>&&PY~uIN2vJOd zQ+u|{Q1eX?$U|`5>s!Hpr{RF{LP2JAdb^d~Y%hUr8i9t{&@tifw{eroH4f@*->iqj z`*e6^59X-ta5HEa0)<+%UrYsw03qU;3T{LrGyy6qb&+KEk06sre~Vh#kaO?g_Dw5U zdN;=r3Rkgk3jo%$05qkWGf0M~mX621Q-Cjd%YMvYG9D{Q8)_z<H@0i=@*u=AHbVZo z)HZj`n%;g7!N0F<uzKhYvRUxGY^J4TZ0k*!4oa)e$Zt(PS;ETjL%kAXxDR~ye<ur} z4})<ofPgeZ^mI^k2A|oBH660>vFhW<Phnw#z%N)7Nyd=*lR3-SZK~0!47V{!SF6C! zyBXrGcV~a9P#aN#WM}~6d?qtbucIZg7Km+eS-<GSpvyJqeOT5*Dt-s{*~PTccD+BP z48^5<_n<P6AhNCB$wHy@Yn!K~pfCi-NB&h6wINJVZWDY}`1n`Em;RM;TfPU;{pCOM z_R+pJH?lS?@S}D=XIjW==K0N1Mv6$m$ldWG^0*D2p2AT5s-%t_bPWtalbnI^97<t5 z<Q2_4s^5u<pNxI<1wiy1PxwlesO@-mCGxms;Fi|Zm(t&Uh?MhLd|cIOKZ8=ciy18; z<SFaWm)|5*0vG-`K66|*ft)z;R1|S6;!Z|m2$4bMtd}GSOp$rboUB{Y6)>Wl^Xf@8 zX)B1^plCjToUT9$knG2xE+dt{qgEXPtv4xwoh^;89EC$2*k3zT#V{%Cj;Zu}+QU{7 zRRN`J{?p~X6CP5Oi}mqobjHgcT5+=6by+nTfya$yPxZ~m69WjN7Cl&1<qG%x6$uH> zH<}bSFDL$YOnD@ZRa!p!bWsiFUHN)!IV_DxtX1#>&w9TcVDTfPf$Y(j3xE4)5@UW< zI-e9F#Lvw!qS6t)tQ*QdQ}epz)ec(dNES!B;0&xuB&v1R<sLP<<{9ccHId0MzdTcP zM`>$ys%_}pG~_QfNeGFHpXesz!l8hU=FmBBR7=_xcx;T(R%6R<lvK%sf4{`MW~>e; zJs8v|&JvS~<VpTk^$cXi!W51B`M&4<ti-nIr;R^hcWKJju<IYBL%Ffwg-2=HBB&H_ zJL|0|OZ59&yWKOE#KT+so;)fsoDjT7)dQ)Y62UgVFgV+_IX+t0X?9cV&FuyzW08;> z76sT_yKm#m_RG0+fF4}P|G4<metq$=^<uwwkF)q?rvJhZ_WeN+=tNL*NCVhmZ7}fO zCd=H%eMk%xnxdvC4t%l&uSyf7#)Hj?L_)y!Z?B6IVila4y`d)S*`&#(Nr9CM8jd}C zn*P)@c8l_Ci*`?%=j&Vlg_p$0`EiUdQByp4tNXZI24-X~kKBK1NQA{N#u|Y^qSNT_ z-FrfJkzVdT5<|d=Q5ngjWs8MXO%A?}Jz2X)^s(>=HgqQ7@@+CV_vw6QJn!DCd<6#u zt&KT&BQhGWx_GJi%mmX2)b?veAweuigL(3mUq+bE0n+6%$8(kWwc_htMKCzk`D}4? zqd4s@!r(EJPcNHrk@@na7{S23q-XXA0YjMk>0B=PfB@A~z|i1mNOSVt1vP)q0hb_d zHk$n+X#WdvkFR3UuSC6ha1WR|B9m_EJ6{VE5^$<fnCTj__ah!wdRKF)$&tnfzMHh0 zyZ+!2YLn^ztX0Tci^M&ghuyV63A){bkM;*wR|g{^moe8Hb5V5nGxcAj)L5#~-@{?( z(CG^2)@|q0P;)l<@Vz7jtZq?VBfBnvitu{J#jq~%rQuql`~mch3+pxHw2zkD(5X&! zikAl2%*`qzc~|8EjcXxd7Wo2Wms>*v3Nn=Q=k$X@-S4LsR1_1!vpdP~h+HyR)^f4T zaz$g7*^Ja3ZCln)_0bx;VkpfP?kr6YRn+;{g3!8v8mIcGw@9wV?X7%<;)JkaQA{=w z{Su0w|Ngl{X)^-^s>SEVAxDzscC(op75b!1g_Gk~m?1PREa+X1b%56#;shyX!=TUp zxRYug4fMm??;+(lL|m*>SH@RCehBhfAB?>Xl?oCSfjak6FnXzGUCi)nYx$7W`=<E& zqC>RbqYw4_JBDFkW{6h$`=V8Bx+kKTIiO=W(M`uwF3fe3MZ#U;MM@r)OX>60%3oZ^ zFY-*z>xxk(NSO1`ko1ll{mpH_s9Jr|`yxsY5bz(n4o568DQV4ab?ch=Kf$|P<oJ1{ z*WhWblo;k^^5^pIhriPyR#7{4VqoVO=j^Jlk_q*KaZ&zq#liV!73?QhQW=6j#aK*d zS#S7%Pl;$eX%4+E5=^;?4|LgzR|=!#Pz<5bH4-lWWIAcoAH$S3FT4iq{K?WBH0lat zvEcgKD4?*H485#NM6Ci1pfL(VTBwp*0R#|!-=9fS0t<%&S0(-g;yKl9?t|5ifJVfM zPYD;RP&+0z-pjgK6Q5Bk5C3IM{>6uINgb2V+t=+JJ_A9^kVSsLSIrQ#6)~v}mMykR z41fgfEj78#xehR4OTVg|#2zA`=20U7Xu!`TQvm?8zv-6h`xG-M1GV=@sm({1OK9W| zPKfWWXy3C{ubP{GKtJng?t^8AG!I886!;zZAyJA#yFEuU=?zeI_uJOFl8qDJB;`Aw zOb7E7-A=z-B+DGkmwuZu124TcdH!Ez7a^P(h>`GrcM@{vih)RXh;Npt=Bd{xExG^X z4&vycj+pj_Nz(KZ149+7PMR3aRhp!^?`Ry~c!pb#^K>iNeyn$lozn>Fys?1TM1VuG z9IJ*k3Ud<3_4d|yRAL5|i0f@BrRJo6;+DEU4ZwN&)F2d;=KL0`n^W39Rm2j@`vzmt z@Rp=&Q*V$A>wcdj=FtnW7BvPC3+IKcX81rf=IzP)--3E=k*h6Jzq5+pSU11l9?nsa zBNGP5eCtF(UXKd2OZM$Z20sY}^kWvqN{Io%K_N1xcY~7!P2I_*%9b=rbcKQzfg~{+ z*pp_bIsUi{lgVm~Ojs9*UB9Y^@Ei~JG<PW^bVk#0<dOvLACb%44S_w#Znb}vQ1i*o zk6&A{_yFZR*LdOLPd<#Dm-#;K&R*unMILGk+ju{i@~$4jcYaYw8?L=j>~<cRdP_#Y z`5;aYqs-%PM|Us$%u>7;A~y%J#|OT5e2gYCWlyiSPg+*V5gn)6UE|5W3@fQ=|C8>S z{Te6L4GSyi^d6Z>r<=QJ-p_t<o@+}!Ub8DBVS`_kOhwVF>?OYJ;&?q9Wtr=YwWZUL zeQnhYAyru@?pNVo7DdhZ?#Uy2Q9ui)aQ9z$GtlRXIP!$(&FlQ-{COC%851FhH3o7H z#PzR;^Blw3Z@a%@SXUq>K_igx(25S!Ws9@6N~FZ;lz&Ph(<j{V4-7lFy%H)f0H2Fz zPXOq;lZp{E3agbn>!P<YrqC7rGxKL!Cy-Ha1kc#Rm^Gq}LRmLkc1N8DPbUgFtdl8w zKUIt|ra%ssx^t@Gw|maDYF}2TCb9mb7~_iu2>X-HTdWu5%XA+E`6tb|ac9R(Uz;&~ zYFPEwq?0|MH=J&|eTpVpSaOJ3S&vhQed#X1{__sN>+6}wL9v*qHXWlre;JceEb-(> zu%cky)HAUd^p>$~;~Y+irn-!PFTmL)tyO=NxGUV;d89i`C$=@#nBe`WRQs{mc3fcg zP4HKp0M*kW-QCcQtQb^oo7NrIMg3MVHW}!7WKyJ`F*QZM!Hen9Bt6_C05OBe7DimA zqAGuF?HD@IWYXVgT`w{<DE=+MTcwk7A7s({0W|@-43S>{PF}JpwUozk0@T+i<62#b z<sovuDBRdF`xa1#6h5Q&40LC+4>Wd@oCm^<dft9#df=O)QZ9Usa$T*w{*w9oXSDcy z?MzN}&)+9JjI`}&RLgkP=EnM2NeKuUYEpA%3}ujdSCDg5fd0d&QeHK);97vC6TZC? zN%JAmJ=GaMB(?pIyTusHM!J6vK|h;n3=D(Sm-lUe1{De%;r{+I?SuXZ`u+(3TTn|+ z7`rRqGh?)BP*WUiqRQjYB^p!|je=#hy}x{W@2LpK-sQ~R`4?nRc=ZphxT+Eod}KES zb-+eWa=0!^TZfBtoY8J)Uquc4A9*!FQTU;b^~*VHRR=3chy9_+M$DIw4nFhGo>L>r z@6d9-JbaFuk3()9YRb4E4KZ)FV!>Ch_m=Wh=p^=1TZ;h+^Zi>F@ZU_UnOd7vqu+<} zelpJH9X}4;z11d-`Oi*~^EFH@Q5V%rA7_k^;!XMDw9Y_S1~KgCyU1fBMTR(GFcpQG z<o1t7WT(azBchvFa7v<uC(HL4qu<5f_d7Y^%tZF3Rf?s&m_e*QUykg5@s>BT8+k5! zoM!a+z}skPgIFoeyF&;+PkUb;SnakQ+=E-_eVtb4eU9pM&2~dl|Dj$4u`*|`>u^GV zcedbnq0Xmwe*{__OsGqrHUi6m0sjR07>SLDZ!lHy<p%<77Za7kPfJ1qQ0G~$0IL1W z`wB)+Ek)6~_baL!5SbqRkP`;B1THiBHhsn<a~|w@{po>~KuZY+$Wl%wr_vgG+$@$o zK=2W??bD_LT`haAUZ?Qth)eOUt2c46KEG(8&n|z0DIb;d8!B|8rta<cPww6H^GgN# z-QNHr2FJ6O^aIlSrTEDrk^hZp&i>2RY4Kq)U(McqGnEC~&QY4D`dUjfzcHZ&mtWl4 zp!1=G{c^Latz`@Q^V!b*{f8Zc!&iCb&8t75Zsk=~1_40S@7eLYpDG18UUj$#+Jgq5 z+*=#Gm{SL%;=Ym(i88Oe`ckBME|*=$uhTre!*FC@vmMF;P8z9JkT>kLC{ZmH#fkM_ zxOjqRc;9Pw9?HgW@^v6Tq+rfrs3f)?_nVc)Kzw4rbwYSSy?b=xJ`c)}km?c7r$@0D zfB$-YFhr#&2pD_qO{xzCm4A4$&0@&D#X3|JD`v_2RY>FMN3%KePbA8$lLI)9_cwp5 zD9Tt`ec&V~XPCo!a9R}#>U4b<?oRc=(0AWl<%&}w&HJh4s9pUQxxVkXwal41)30cz zg-0SXuv`w)1C`GgL$TT-oW>69*lbE4nCchj{#y1HRw?-6<0$-+yInqG>h2jRrO)$h zKRpt<1+VT-``%n!cAsS|Xf0yqOn)H`f#RbC=KL%h*Q(Tera5?arcFN&g(@`k8H5j~ zfR(^`dpjN*O#cyZrl_$-B{74tI|4vw??@us0V9%|le56j`P92DFblPAt>yIHcfM;A zEnB&F=t(sa9G!ejdBHXb?j<02=kJu04~)qZD{i@#j~f&7-oE0|gMT4rmHXC)Az%X+ z;1}+A@3t3si49!&F4Z%P>4178D{Px_MXAJ+Oqeu6BNzNu^#WK`g(|T$gIjHR^%VAp zn?(2jA_4+ftflE?9`un(UPM&RKQx@qr$WLTPQkZ>!BzgFrl?1H(Sc@Tx#ZFkBk7_d zFteawA3Y3n5Ie?KV|=f#)klyHav!*-*#rJ<5mr+ovnAWj)i5B1&IG2{{x8~RSY8{v zW%~JuwElL(B0gZhk5=!~U}NQka!JS}RHh+SZQ(W8rjL_#Elqe!MQ*MdF|!V6nkvTD z2cFCRZeCX@1)Ig>1B-S$C1oZwz6q3-%Bo#HecY^%D~k)b=F_c)#6;u$vrU|un1Lj{ zViy6<J&H7-1H@URAD$<ZOG8B0-H4y$gnJjw&5B~KPpX5+Xw!Z0%1g?Wnd$59)|>mi za%#qyD7*zaUYL;TfU`^_Wsjdu)&Vy(n}8R)9_F<L@kxl9RGukG(iq)Haa^|B`e&P0 z$64ytOqer8%8})<hiXYBcB;6{Gr;3`s;Q5Og-lw=fAzTa&$0RL@>Qu=d2P-iace&C zt-a~QG+%1;eBpinX7^`_|DkCG6!yiXXVkMdd-6qv{!RIAGnv?wat`UotiWa9qk_1N z%Fok0Ha#B)HO^}pV!cpZwW_|{qDGS-NbU`}8^u>xn4K|`l6sY&y%v7+wtAUv*a8I? zlqd+eo`MMMJABo`=FcH|dg+6~kjKqBHE?gthSn8b?hzt?tQy$neWIG<7fz<l<Z*2{ zD4K<w0>aH6TO@;=*MN~7=a8~im-<Q3@3`OTsj!g>kd8RaXW~@2$?~)>nE+Nk{VR~B zX3i=s1gt}-Ld`pg+`IMt_k{12lsO&*_gB?uGVz+thSp+Z1zlj{nZ#=*Zl(KQ88y#Y zF!9IxR2sKm95gk1`GK4hy))FX-xI%)8$UK-aH@SHaWDtg&C=s9({Q&JHm+Dc=fDj5 zfRTU&q)o_BVJ_%VsDL!aW$yvwOcIwSKh>+mz{;%zl`vt;{w>YeJHSdSDRaFRoa2Ky zUQe;fEP5}dyNij>Na5#D`&Th25S9A6<w0Dn%dD~ItM?FEz>iame5bR%Y7xbMmg;pr zD&AAxa{LGhXzx3f(>fjPS#)53-#Gv};&6g_bskgjWO`XFv26g|=bID|RY(%f;_o%C zH(zIVeX=g>DsLHg{;$ZRQAqsJH=B9DE2W`lOd8Ip5Bnv5_9{m!(kTaYHk4?H^(8Yy zFTRFtWi-$dXuGkXJGn+Q`ZyX*EPi(xW7kq_orMiCXoas7qZffl5LpxF37im12inF< zNAX6ZsW>Q8)14&r|It%uv0Bwrr9LbF6iqv+-BIO-eGZ7fIwCUZEEE1E>T?CHPe3BL zDz-osyE=c1*|lmvF8{6)#I2dHvF>}7e9hms^cBHGljJ@@XPbJ2A?q<bl@LDhZV11| zW`2w$$@kr)8a<~<{PXQ8Uy4H8>1P-77Svzd`WL(Ke<n|JQoN($C8cyDrOX<omEmeN zh3SoxZE+H-`z0vhf$(qV6!9_~{BB>fQmhu!FIMyT-9{X#-S^~13vQi+^GBzEt`p)} zwsN%aGcO)bg4P2;A+jG>4=5aOG>tbCzV%blMBZ=|^zA8!%iC6;JeP1Nz@9O~m8wqt z*&o!3Q6SLrBMxKWA<Gvnu{t*CZ@4K_F?Sr$9MHkwq@bbBD22>?Lcov(b|x(6C4;g@ zoc%|o18Vw<xB>8eQNZ+*Q+&2R37N8rGSb$A7r^EFT~g6YCJL!Kdzuw#o1UL?E(3Gu zu<z*8tn^ODN+aY+Z`MqtU&S}{69<v&=x<AhHl-}ho(@bV%xKFw$VnQ#zk&YXvj-;o z4JLXsTd12c@%2vW{=Q=kcTJ>;=YJBk+bM0!2?=DDDw{cZ2`bwA4T7>^3$MEf_+bVC z^EAN<O2oE7M1%w{1az^wmw~8C#Tc(=e622vE=QN*yCg9;JBJlLA9-|fiKeaaaeUiv z`t8?Kc?Cs~#Nj1;YhSbb0@|L7!7PK$7xggwlyM*wFJGN3kp&dqx=I`ss7-WA+N4X( zM(#FY*>bC<Qs|B<IU{7RhHf_5F+ul^c{3G`G5gB7ds8npxz)-1)Fnafon{3Q!~*Rj zI*MC5Pr<I`&;w69BUKrnKL|G{i~%_LM={`ndX>B_L$0SrjfwJ_doTPE%l}Ch=0y%r zK9AccL11;TzCBg6!zPcaoEeRcj$2r*ilPH&zyvxG_!DEt0e080nm6YBhJF_z-;vx& z0cGugTGM#B!@wTQTBVjDWg|7Yc5TEvwM+bZ!lpXUPe7m<HeA_DmGMk$lBg@U)P0zY zsr0#u1*z8SakfuD?eCPST@W@rHF<tAOlL$4W}%$>JQR4|9RRvx^+z?f*V@m5B9s3! z16Xvfy$|nS+f0QBvlYTIiM={ecJ`(8{x!$9>x<6qWCfX89)6=_GjDfM+qCFtG%xI` z5{|+TFKbu^O&Y(&!kVq5M!COiO>#1q7G}H{;COab&8wUgoOPV^4$yWSOh2~#l>2aT zXzA4KH1*?74r6$ThmoOT|Jt#bkU*;A4o>r^)Bi87jiC!P+_m6$lweEb{($z4N>iq| zd$yXwLcsQRa`$C$iHpQ+!eF!EGkpOK3`jc@1<@P1wR6=MPv1n@WV!{Fb<2Q`f4#7v zAbg>kac~;|jcw*(w3oKmUlSW*!KsnY^CvgUox;I!_~9L(JJ{CQsw_8ta0<H>y}mX4 zw4xi}gfO(3_oMxBpOFs*LvjAWQY+I1P4zC(K@-NF?74*ZY@P9PN{^8@Pgb8#04l;j zOPIIGB>GLW4}m3v*_&_{!!vWo7B5-w?fl7*5=$tTl*cfvUE?*@7piK{6_41?_*g)} zDVaKSZ%5wy-l1!<rw91F5^W+?@QgDM^D)1Nssv?Ng3agoEptL25&^HKo@%yhpz^aV zPp<*65TW#OqvcA`QPlwRI-tYU_#_^D#Z#7(I|a5iqyXLNuf_nYtp_w1pd4Sb;lXR9 z<&3||T`xL!$Y#z02oNsBY48=SaJ<D6evR#w8hFx%+f=EE4ecrIg$m%_0Lr>NU<57B zv~fF1s=U8i4FBgP5f0i+)HNaO2_q#A#wRE1K>JNgrwl;?s>Y-adySbpqnW6@tZ!yJ zP*y`Pw4=xeJvHCT{gm>s(*wp}i!Zb-@*jA#ZJlH);<vg#uewjF_J}PySR!uw4u_qp ztbq6Z9(_p;Q2*V4`oAxlwk4F%d-k`FHj{c)w9@c^2C|Cv8S4e8HXZ)I0pl+Mk#;(! zo<yf@l)TmAR;j{%iff3L{I|plK6p9^r*h0`nN95l=ZZU&a$CA>P7-n7>Puq%iw`Cv zX=oahjdEU?GH7j?NIE4hJt5Y>kX>m}l2~u+yQ}{Vn-CACc|h8{m-Jk7L=-N|gN?$k z$=r(RdLNYu+BZtMa?O0*xdin;u<jSsk83(KI1J(C-EnaEZP{w(KO3CT>ChH&oZe3^ zn-cS#Pastu)#Q?z;|Vj`q>QCX2so|6E}EK~7F^WUcy*V!$*$#AOu&lQpKWCtxQAn- z9w;Ui*BMWmIA3o|Om|U;Ex<aQ<o=Cj;1_5=zn)%NEH21ap_(o2q%ca|@MUkB8hibR zV1M^1o{s9T{QWUx_?*T=@7M?AGw!RJWn~ZgauUylEGvt6Sm~_S`~7r@e99Ij-)4fO z9T3UlJ&kC!po|<be!~!CjGnB+M2*6h6%T8A{bh9yx_;SmwOqW7NzqRNAwcAV%6Du0 z*pc{agb?9Jhq{`etul#pdcOAGdC{ymsrFb{Em)P(7+Q<ure9E|g3-YJ2i-bD`A3!S zl_~Z->KVF9>UlA{{w5ns>XjEK2DEI>$c<C}z-yb-F`EV=FwEZI;&&A*%8bXio-8-4 z_OGR}c`h?s&-XBu?D6X95fNeW5F||NyUA`*l3eXtlE+G8z}j~~50`3Hw4gL{-?`No zfoz0_KkGA%w0Y}pMR+%}CJ-Zbexjnx-fL(q{3-jsM83TvEkk`_1hHtpstY?IJ%zMh z<@ZqAk#lIMA)h4n0=g3%22jj8#wk=wV-4E=;I!w$c$gFyMKnn&Hzb2W2{@n1<g&Oy zzol7yPgkMXV0LKz`CW_Z{Psp6og7En58oMlQ@_tU+iIx*hIb{b#7NaA-eAm0R=><y z{S}8Et0Ehy@iE|?N;;XYYXXcv`T7rgCD-n1dO}XK`pchpK2ijp#oMCwNCh1X#aj+Y zGy4I${q7mwx9?jTlaVXRtY%zLx3LZh>P7>gxNm;<7ZbY><x<9eO!(>M{EeT8-d1Y3 zj^J-W>A@;3*kNj5Cmj%qSpfubDlOExe{}(bQX7=`K6SL8xqIVH{-MSBg~%8oZ&|Bd z>EWYZWiD)iCidOosp{D7PWf3amGO62FWS*LMzcz=CCGVn&{`L+qxMeCQH>IYg;<rc zaMy36o{2S+t%J?x??-};v!WD|)BGMzxk|FsP92x|w$Du0_EzCdi$Y${H|vYIS%0^< zT<kUZO5A^Q+l&!T`D&%zzo>lfyVF>ohk2f70%dq6ANb_??|Vvh5OdgypUq3V|Jj_S zP53lEpC@S|hDwWYXXJTV9~K;StO!XQuS~T-#nx-SQuAk@w0V&yz(G9Ij<CyS)at4< z>{#gTv>4rUfhwAUW4aV41)51KIND0Tw9<4$5ag|_(tHw(^AE7*d2iQxS%uwg=-lpv zR!Ua<uC(11>|>18mIH%ZbFq#i!ZRSGrCV95oU~-^w~=1(xdjMi)5Wm;uD8kH%*WEB zBF%!3N%b4IR(!6)J3zf7NdqLn)*e4}o2xMWPkZ|c6W+dzz6)#%1=))27O<D=$oYDO zIEstgE7PZ|bKG&h7!kL>cEhqsANZm0qN%nX2Z!q+`g#*_1-nW9r-v2IHyvDFwrU@E zNUh%cgFpy%n=5H95F&pz-~CJaq1%`YKle%5e=AfLo==*K?!(HVu{b!H;SGQue=@|A zrMH24<{Ikn|8p!K=n4|$C*<hTnlYkqW^Y?XPE|S9!Au-Xs*>tA@>eJJi+-$zx{eU$ ze;eP;-N29tK=yfSoRWY+05R|a91rY*s&aujr)M!ZDcZVa-u{Dhl|+OjYu&>!KrkKQ zH`%n;b8BX_7&;fg&k)-KBuFwoG`*We%R}Co@q}usNpj(>e-9J}*3=G~e^H%5*qhRX zkdK3a^p79|a^gRliHA<Al_*n;@EB4D0BJqu+ljg{?63!}fMWs5)ed}^-VA}Wqrkuy zXw<#s#2eMDjDK71F_zB>&&8Hp6pFd_6|rBTo;2Wug!zkOj{s{~m*wr2Lt>TViv6bh zyeh$vG?+gFyQD*!qi2MNx?F_N^?x7M!2}Lc3<h<6qo3R?$G=mXSsL=+sa}OF&ciuM zKQ6j|j4azQ`B>7FOdTI0_YCU|;b^><H8*8WKE_4<7Zpo`JhY9^SY*(>PLeWdqOaUz zSS<LCZWXc1zyWuj7yY?<kdaD@MMG2eB5PE9W!74@i|mWn*ObhU_$+vSRp^ANOY?#( z9ITDP#6VW2g}p-6ugq3<e^OJ#e97+ql;1J%iaeZ;SG_BcaTw44P0ny;KmB^+t04F+ z7SvqJmD_wP6k>9qAO-L}sw&sjT%e<0gdBMZcw=&f3aRM_KZpuvJ5vhpa+M6_uXUnB zn7jtx@5V8yri*#pDCyLfrryZ0DzV^K&uK8AiyZB(x5g(K<Ns!0h>a%)l=Mr<%)f{w z=X`cXPM#33P%TJ*E2?%^#FFLB0QDF7vp`1B^B<9jtafRmtVhLfmYAQ`h}Bp2v-KWg zP09Qspq*UP`i^n#X05iYB{bT{oq)Q%?3*;*2OieA>=Og@r9$#mS$Ay;I2^o;l=m8e zNd5#xX+E;p=)Odj(s_Vy@}D{QZ`%vc2eoUs|MmROX^DSCDKI+(S1>;?0TT2Yqs4hW zYj8h1_L5idFa>D&%9;3{a`D-28u(Dyz1N`F>mf&R$atas{$8T+nW+e@d$=#|Jy-jV zh6vx$997M>PeXVL`7tqNabr&8-kQOi4;?9DkZ#k(h-#G~<+Xw=?-wL?oCFDGSLMdZ zqY;%vY?xWl7)Hv^rFSiNM7;gp?HH*dx0w$Dj5vkYB64GhODdYIt^IL2Wzb6^>(2F& zVDQU)LQ?tyQ7t;C6>Sy^sLt$dp<A+m`Rp>HUifmj6r%2e1ojTBcSq%hmM(;!+8P$P z8C_0tv_xL6b%pL`QaV=k^pOS3ap5^V=?YwCbV44I(woj>R$WpO7y*xO>c;ydhMv9M z%xE{Z!GJ$yw|Z+{P`MKlLRtqyr~)#!K9W_UfRNyEMgRmY<bTI=8W5yCH(RBhZm6xL zm)$=iv@x`PMc>MU3aC6YgT(o<$)^S5nb55;Ae@XoB6>A%Luqu2ff*W6kmbv$`vx_x z!$Onsc`Wplu{e4JcvEKIlSxRF8?1I?$vrf#wc{G}4N@9h6}c!s0XYBnq@`+p<80wJ zRCIczU!X@(SDRu#+Snogmdc4LSXgdvf?<R*OVeMdb@e^!DleWH^AnVZa#h_iqGJi1 zd?vBj*uLyQr99<~^q)W5xqE_(1UhM>$yLp=R->9=-NnTEcuy>$Y_ciH#M!IpW~I@y zd-b@Ht2}?miI>($X7JVvR?S5Nd(>_7?NDxa%((mSKnBHk!9ANXC|G>BT(hBnE$>o% z?lI$e0rl=kb@BMIgmH@pu@cky?s)wXdkzq4^6U-8O?m9M6njqI@N)~e9MadqRIlUa z_E4B03;I-E9h<M}SJcrpdvWYxjKlU*nurm^GNqF45mmg3z;+PJn-_Uw(eUsZK9{() z2UO1?H6h}V(!CE?lBT&z(IimNxqIsj;N;eIB~TT`4C*Qvdf*FcKm%D3*oKrplFQjq zf+jb!QSXzW&!u^Q4fE1?-D1V+WS-G~+NLDXHp%%g&DLJ+Diw+?Y<aG)ftfRJ&>X_S z@M<NNb}$|u`;WGBZMIdbzt`ztoTsKhZq6w>$?b2uAJQe1Yw(GlWTK<p<qH)2=KW?# z1&Y?h+x0DL5Z(b0CC8;<tVJ5E(T*RoSe3*%B%1I$9@w*R)Yc+BsBD|KU(_vg{O>5W z28#J@K_!w@7wAqEt7~ADcr81ieAyGWMBm>kB((xPZ7O|&i3yt<+C@M*{>ZXl0Kvr} z9fmImrSs$iDmg97+f-9tm+!2EAx$GBD}X?jQ)v^Zzpp7JBf57pw%7P;BU%#uOJx%g zy|eNTYJYP~e!Y}%A=8!Mwt3&x6&~s_yV}`KZP4FTX$O{;@xAWqu$03@JTJW<pH2!q zxwWt8?cEZcHIQ~OHDQ>ZJ=ZCk-S<TxZ>~pFt`Fv&kgIT8G>dlEnapCeubo$GvfLG2 z3&Jp<C%Q=S=__5aN6qOhgajiW0Z05l3*om(!<FMY{W5=5pZ@Uc)+J!Yy*|ua@eMJ$ z+~P^DE_<m}hor~7P{Kvl{8eP=%fJOL>`?08{U6%iIxNa{eH*3}5NQP^2We@fV;DfB z8A3|Bl$P%9?vh4Iq`O198!2g!kj|msXIyLTwf5fc?|a|xIKJ;M4wyM$c<$@I^1RN| z7z|88+9Hr{Sc-skzLl2iuZxKi`OLXKi(?e9R-IOltk7m|FF>~^w9WKJ3hb4b=5?4$ zeQjPnrDFXQ*i9q_mMLZcVw}|roQp!B?-s_@TK#~$?jteS&1qD#j8^{w*+F=e|C4sJ zi<tVEQVhs?Eu4Gq^P^A{6-!_@!?pw9>PZdhY>0U!LG)1y9Zk1>BSE8k1U-ZF=RgVC z4<WWCpnuru_tc>WB?D;jy*O!70j5p}-@O$q(a|sgsFSgo6eRN=(-qsbxH;0_$x`U1 zcMVXu8tCB~Id-EJI*e@XIpAMBD(BDMzZO8GXkY)MPWa7H48riv@JKc<^tdiTZ4<HK zKA_)w!-tWZH)SYZrG9=_s2P0nR*#{X`;01De+2u0Yqr48&oA$dKuT5RJ)2<m;K7kE z^+DJ#Un1s9(2N{SwNC!LquOMNUh5s13c0Nfu`DtoUS-XkTlTF*)!H5i(VL|_V^1Cr z;b{Cy@ynynSDY#WvTrk?d|TN)-y)H3GGCK|Ees26A;-aw?YAk!NgEG&U(;ta+zb#3 zNB~?F5zyKAFt_mp?Cs|au~7<V9cuAmKVLYTONl$s^KOY^kycNAC>obQrW=x)k{m~= zfXeV8-sHq0Jn05m)yHIFlask4{rDQq@m|VYI41uIwxGF!O)r^%R{1#iGzUt*Fqu)F z%_MbHAWhadlLfs!_7-$H9T0LM3B&x1)t7F!(wApAM>OIHLHP8-IP@tYMlDI1;#OVR zG4HO_(Fuzl1qPSj-PO(J$^iKXze-0n<|cu=p0d4V?n38FU|=KTxiMO=RoF{=x$Ju{ ziy{3^Q6yjNtGUWMn|7?}=I4t^9QBKKh0l)zehZ<U1wm|OATWSVsojM3mi{iYdX}Jh zEhNcbB>AB$LsVlNNFJ#U&21A^^^5NVM5gx)3Neq{A`j#<ifb`YBykSAMfbiI7UQZO z=9fmHpdf|F30=bKq`-W%={7EK(w#5EVpRNPHq}AOZ2XK3#y@saA@UCn4G-!vL6|<# zBaK#>lO3JtYfN;9O-WUVv9D27_$t+W4mT3-!-c>dv~+1&=uZx@OL1OEq$@|pKcOJC z>Qv=>e}yI^(CM>_UN%Cbg4cZ1Q20vnAxbkdKyYgv3Qfa!P`2A}ozAu_%_RlYaBs@d z(QeSBt>Tfk%X>CoZ-zjcJwBup4ht53e2l`Id+=PZdaBUpb(As)&pwC=i}wK7=ohOJ zZkM{)aOs5P13?GvvHpe{k_5=(wdI7%%HZWD^*o%20yz)u9mO)xIKMXZS<IV#Nt>T) zW&X3$2lJ=n$)4z!fMlddG=b)ma}6Yhz7W_=bX(gcL3FCsOmt5-pzQbvo$qx`DjrS} z_Pz9tQ03>6AYFlB;v`(Ompikz{#H4~?J_!C@jmXr)E%~2*>)DH97)mL{CZQ4%|zrL zyU9yv0*~g&7s3a7*xp#4wVjVt9Q@I+-u-aMyUe&HKdkpl+N>wkj6v515L742x1QL* zUSVr;xeWeSfVc+N&@ooST=k)r0a}pec+6wPBIhH=UOjR3QNyW6nKp09r%7k~m0#lU zs_K9jf!s--zt^0wQTh|{Lzu_<oG?NjU2{#edCh>OYuD4l?fYLAj;a_|v2sdul6Lhg zEUNSU8~6Q>6Av=G_#CPT=SbVvGdx1ReY+w#`J~&ENhX*$(yK(j;j$Qojuci*v3KIh zZ`I~plYHoD^|ZAICbYV^L)@6LdL1}bEcun>XcAxHJ^i(ZQ1Q|%n_eD}|2>oUp+4Jl zfQinSWgvgya(?;qK7E9uPjz<bL9QD%n#4YZ5bWaGw3}Vlt9XwL(O(h3Yt<7bsRCY{ zT6QOMh||aH!MEhmMc@eW_ZMAG!kf_1cB{lzgIXM6;Ptuo6CY#Wa4xJsG6%ciYok7n z_!!+=;*v(1{fGH%Ct4z-YZr6a3vGXK0W7(HoDR<Dj3^8yx7kwA!^9Yd7G$MQn>Gl+ zZYm{@TvuK(P;?L4hnpquOFJ=NPN3&^Q)z_P!Ye-6?^XP1<^@HOo5hNy6PNoJCr8iu zrvo)C8^9jirp#`OABNJE_fE=gvG@Z7FIKoqbPAp<=oE99TX+DVtU_Q7ke-HYtK|~} z1~iGglyAE<^!%T;FMspxkYXr)i-|@JimHN)`Xg<Xf3rl`eGJhRstTc2UjRg;66~tY zIf?B}tXSHB{*hczg8KVUYPY+UBl?nfuZcB+kAcb2Ck8}BZ(!}6xupMoh+BDDGCk4t zbW2b2X3an!iJgkJi~&*d;bqXWt6e5Cwg4-9`)}&CcqCbxBo7Gp3gBNYyT7I`>>D)( zI=x}HKtUSTD7D2O<T_`W(0L2&k{G3Tz({_0-rq(?MtpgqHT%U(9f&oWuZWKq9>cyT zczF%3-MjI$=!{ol9_%|E^kQYKGBuyFuWSjW$y+EqfkF@j;abhVBTO4E4pRJi<ILN} zrRf8?Rqp8+(miJtlm5<YRG)&)o4A>{e8tfj!ZJq}i`~>}%LN)nR$7%}P!~Jy>THIi zX8gp<y;Rj^RO3OVwdQZ_=Z$&>6jmwhxh?|w<pyTG>&OJdV~vAuYYc(ER9otKTOCkh zNO7DLdInrpb1%zVUY4y-Cw(*!Ymw6b5?r76I)M-M>SZ}HlP;=&goFJ`maO1ZEaP#7 znAZ6+?md&>)v`4!*^!ATtS8c~Bbym~oQ%Dei8%&MixE9HBq!b~fI7To*WS)+S;@Vd z0RQ?*tXBk<@RhPKIZU?NVIZx#I@8O<M9iak<n(ARu!q9A@J(iCqV}T_JI;r*Vu^fw zSMs9)ql9dE38renGIK1ALAn^9U%xRRB#Tj|SKl?;KQtugy-dWssjck5$9e3hUofx# zH0ywCp~GdM2BVpe#T@Zds~<O$x-QIh$&Vo;{TcJ(tOw+NVSFW{rtzD%V_3?-5MF|@ z)i(1$;35MP0bkXa_@G=uTAKLc6<_MfR*&AQWBn^G>9I63(C{B31!OqJ5x|sB@Jb%m z+KL^zm1cc@S@YHPjJ(UtN4aqEg(&M*c~8dMaV)f%OIY^3pKIV9Q%+&qi7!wsNe2j? zFS3+e37q?n5vaL}%De!znJs6U$urR*BJw^+IqbO0EG#Lk5n;NeFMlz6*h7v9tS7nB z^M6mQgq$+DT%e~|lq*-aB*RBOsW@#nMjG|%LNrpJAQ!S8wd&Oi4<}U<W0>Z|fk6|E zKn~(~#W$()>$#mvpiA~ujaM3p252X?9FEVh5e%LwzX@0lvRr8BIT6M&;F=N#Spm_7 zXn;-w^Cmt~C#(<=zip^~-zb>0$a3ELh`Rj<*cTHUA-6Kwdhe9e$=f=h5=hG{{(7~Y z?^g-1{i&=9uv%wW)A|EZri}aN<>sm!35r#)8byV8<VMH0Kr&p_nbu$DDX$8n-qSv0 zYeC&>qI;GKDiXoNSr5I>=-CzDKSj0hsZo<{xloyZ*LGTiHx%cOLi$1zxJrY;Pk*Yb zC&uThy9=dA9L@s5H0^mQ7sEwTpO~^8*k%Y*yu3y}GNPSW&KG<AqHlBvf(@EC%o40% z^Y0PelXpU;9gv>8Op_+~omy8HLnLEnU5GX4UGlYTXe4nB`8!V+J${`%I~=qx8AU<4 zIZ<@qT5wc@Z1GPaQK+x9OouS|BV+MR#!w_k1QPu^vtIZ#VBAhegTpHeX?t64JHe{< z;3PWm4%bnEA}idC!+TA0z;VeeBPr=3(X1q>5%FfDTO;?op|nbn$9mRvN8`cU;+GkM zxFrL?aT>v463#+BU4OI?ojIy*;f!5BUagnZNxyDb;A`A4Z`n}M%hz%U_1@aW%ewYs zC}{ydv?7f4I_xxv>|UTtn)mWnMe)h$_kMKSO8cpFzG9$D%f{tmwx;{KUmvJ^Hh`^w z_nT+KgUy&iFM%q$cgijj#NYM1iO9-=j|0<-$P`pr|KQJnJMvKDY?is?u=Kv#jUNQ; z_3i7eEm;x>weH5{y4ni5mJw@^Uk@|Tu4)G?kV?FlJP_j)-#@7*{NX$;XyY+LIgK-7 z#wjSY5(^n<UE-%|I`1Et+8^82a1ZCSXmVAV=X~q|3`wM<Xv_DG3(Y*pI#syhubPzm z?fG;*3xhrQ&hs;f$na%buXYCN2K=uiL}pDA1=}CioFHc0YXUQOX4kX6lnlTk)_~G0 zq7f0!xAm#(;W9pJ>)CgW9xX(eH8>^CtL)oDVn09!h8j>g;MAKb)0^6#=XcyEu}B4o z*w64F9ge8MkKwB#yWsl?881AcvWx8r+I=4@U_~Pk-edd#RP~^-P(MVK?fYQ|Io#+U zO^YtSy1>+2UsxIqYahgLX9B}2uz9VP@_5O*lY=?{JzKkF=0_GdY(w7ps=~E_f<hy* z+QYk<iVwhxpSpg(;Y1I+Kn4g*Kk)3=t?jm$ZkyVwWW%F{G(1`iHd8DO>9zu?=epB0 zM4$SAY&;$+S)#eg{mZ}ke9^PywFD3+c>fV6V6#Z^`8S4zCiAWav>0}k*T#6C)$I!D zm2&rf_8o`}#lM@?e`hiGcIHw>6h8%<NI4j7g8hJ=cw$fzYh|{TEiI+b0dw84?<zAu z2AuT%fOmY!#5TOvKIOZ$>ZPXpuo)Q|6*?NeMYkI+4y~*?N3Ql9o<wPqRiR33R<Va+ z(A3YihgTszKT)3|xfu~ZpN$K<Dq_fn3dSpwSCB+ql?O6mT}{@Q#*HOb8yXML8Vr?W zV`p4SPQ&X7qRD8nH#NmX_MC6RQNi}r%7HphwyB=x3W%c<BOwsPBECIB$&tFu8A74z zS+|cVPDXrloLuB39snji6+Qix(>`!c=~|KPVYm`JUSqeMYw%k2ZY(<j^XH3}-Td73 zbzeM@M6iT=g;H0slwamYJ^qHsXPgdOr`sp{-B(^KMCk!aWJdFkG$>}+QD>?l9P5#V z0eh+%0-8cQl~&&=$wSjBcN>hw)LN8M4*mC%54X8%l;ie-<muu+Yka{@wEaE*=R!#~ zKoYS?8Z7nj5ox*GVbEBq5Zjuwn5{?BMO&w`^6_F(=_|p|vRSET199^|E1)4p`Q>I- zcykL|!?sqw>LSn(D0!k8D<|vT1kwHQTj`-&N3T(kk%(`0XB~sFtyu9Er;zIAqV>L- zoUO2>HBr;XWWGzcpk9TMrIVPY5nP!@J6EICsUoSB*S*{zvOC1^9EnkFC?2AW>pg{{ zB{F?~7SZHQvZTTKK=_J^(XiBzQKKsXWyt-km1V8Jc#p};y&yLsxUfF&9F5~<)~7a6 zJI~B_S+;EPLo7{qqT0f)C*!o-vu&p)vel4Ylm}LVAo>t3Vc1eJ!;snTr4T4MXoLi@ zH;vCRxUh(T-4a}QLykjN>sK5nooV5&oo`Ci;ke{M+)}mhKB26wklGwIz~-~!=9?(S zCCXhn3Ktug0ozvUdY!GgV~7ofivMMXyTj#hB)U<kL)EY2)uXxINGX4LQSA|oBcWEq zuVvTmHP-253EOi_mcgkJ{^YdiPVc%~KB%eZt2NxWxVC3U3K&ZkF$4fx&Y5bjhNM1f zdt$F6*A^@;<(>pzyiJ(AOk2p`yh_cl_<B*jFbdPALWBdm!pv2iGdQe2KQJ1>8gMwk zRYgd2t4~P1M|aS<*&x&bL{6nUH~py1H_k;`H;Ip(i)jYyv9AY*m5DKu_6;x4sOZ1P z*P(g<%N(n=LqujOOB-3tHB#=2$$&`0F7HtXWAM=rN*f)u#Oqmr!LCO^XD>hkLigTW zGZJ7v#&7&^`EuU@g6Ae1M+5o+a6T!-QI!MW(vkgUPqb#2vx*N9^^U5Aeebod)SNwk z)LD=904SzJ?#mpS6rGtfU*1X^&*>5^GrY4FBAjJU>+u{(I6Brl2j8IqbkvCRQmhu| zI_A?fI@<C4sF8sacQ)^F+Hsd>YtYD|)}Cj`0#530KAk`F&)z_YEw<uFcdl%TzlE5C zNKZ0XbdpR(fs(R_q}Y$AStbYX6?W^_7X(`ohs>$a-#jg5AewsB&q6TW>x$`sQGjha zx{fUUGWngfB5r6q4$Jan6K+zhS6N0D>lhXuPEcq7T0<aOJGJg7C##?uLt~}stR(9` zx&Tt%BRX`s&p?x5Abr>HI<_hJ4S!rOq=1<#_&$NuO>+3_CpO(ku*9A6X9mwzh5iJo zJ_V@=@MW#(n?OE4#<&4bWhkzvwKlmQ>8unj_52|R?>Y)z?9ap#4ryNxL~8ZfCrhtC z3spz2;pEyo9YeLa#x_9iIQLSFIBfuBQT%Z@=_OI3d0xe77P5k>AA&$xl;;c7qY)ks zxvQuNy(u+SAqx+qoh$eTL3#B|(`OqA$c#bSuwL|cjDT8j3W;{g;jc&h^Z{w+j=r_S zbD+13lP^x)m$R(~Ff#HN{sax};vAy*Rq*H9$_DAiR*vv69kV>Qvw!>|UAp(VEFL0K z{1VWzew;dEcfxe?aIdoBM=Vr;KqpSq^>#?srUYyZ)CtC5w6b{|Nl=s9%}~Ry%`~21 zWhylj@y|^@iz{f8lt?HRX*TWUZ1Ou%9TAUHW-VFeA|M9hAXOw01M<p9IMnQza#Rfu z=Qxtp5n6)c_akQ59_6PH(nhiu>wWYY?mwme<hfDak0e`!R>_pq5F0Kq#wBtz3dYve z%S-!baSmM`MZ~|hBcQhZ8iDXFkPY{n1Hrl*H}`5K+Yr(WLw<R`P*%)I`iy!G8<W2H zI3kAfJ7&*jc~Kg2nOdrtzM5VY*-pzGQlR0k?$Kh_p38e)UDHJeZ-2R4?Bnkxy+_Tk z(a)cV;nN}LR8-o`l;et6EedW85GR&u)vPNTSCMR8U&kQ3J(d>SlfI=4WpR7a;s5S# zERkGF!l7WGbbTH9IRH1t`y5ApMlq1IoPTt&lbA8dY!5rmt|<?p4Vy$o{4DpbMs|)b zN-u_Qc08MjjGBFxs-^9Tlj#5#7e%-)o)%hTFNJ6tp8FLi!I{ZmuL7aa6r~B|j-FzD zow)HB8q91X<q##izRbpTM!^CYY{-|`{h0{>FLjQB@=a0A`Q(lvaAA7;$zm0XpGB!V z<zUi~$z{CxMUK^wHbcPe^Z_0XG=tQ`wr^nNSKnEzAgqwElo!6kKUxPjm2P`5kv@lK zv!0cc^)7}Uzygd#n?7Djp;<R{>4$)h2CSewX(o5Qkz_;TcBLyibw2Xn>{O=QsX%^H zL;CSI831c3&a<<@i4{Q542#KPU`4vLj%#zDe<ad_3qBgRmY~h}E>r~I*G^2G_VYhc z9{#9=1_JcbymzCHm&%?dZ-riSoG7hLlp-QRAzu(l4s1}8K}hLdqbLBIcYPnlGCG>< ze%z(kKXB`haRK;@R1#Ob(`#BBV{?WILRXddgGpo_S8NwP<y~`(s?7;Z8vfrcUWyc| z`0qVawd5(I6xo<8(5s=Q9>g#;Dm<<=TUva<^|XSQrRn>wK?9SF;H<-=0v1!ChIJ^_ zO$?a(qSbhQ-uTGOfuGY6Ahn%$8IYBLzy`6vTUQ@wGgSkXDe2FXA=<0?=vVnU#XJ^H zH^>I!SL31&!EAHAbSfHs$W`0Z4<J`2DL|J@do9Y->DXXu@Yxpw)RY35WC76q)`!^c zsD4(0n*lPHuV%Y5Sy*E%E!{6}>Es8=F^isQZRa3M|02qfI#USY;H{=dd?O4)lFUWW zUp*YnXVx`LskzC$1AI!{s*;FlcBm&^H8S=+EY`E|{Y{}9x*inOVbq&WsinK<=tb<6 zxV8Zv*WujEn0;rZL4a%q+kwy8fF7z}v5Ge157(I;@7KQ5w0BP)3SFx^*|$fsNn7oe zg!=h%zk3Nn#&o)wu-cfwH(0p;eRbuB(VUP(oYNQbfpx#$Ve*T8es7TMm!(ge0RSHd z_4ixoB?w~k4UVB>tOCTj=Jz~5N}>__N01U?>j0U-;R@<OVBr3Jt2}Qr`$H*hmo83k z3-z==IM)Wz%3=mS-OAO(7w7qj5o$5sc=Twsn--Sh5@^?1BypICIKj0ulmHk+KEi!m z%LlHX+pw8_1n<QAGkwkQUx1QLC8_`2bEoarUzV=^q>i)2kKb=98Dqgevn|g6xaX&z z7cGb*zjDtuO$Yd4`;ExrE#JRLExagoqy1ie2q-wWbo$Pyf0L@ll)B`mQDb_A*w}PZ zS~azowi5seeW2kN62b+rLz#t!)9#izk3GgP-?Z(h&dU0-_afBqd$Brp!x7H3u!HXx z79d{veyU_F57Ht+vmJtB@&?>!H|LkXVEusVcWdFcwwI)jO30&M6&xGzwmqBW){EXl zll@ddHLP~0(}=;u3y=TU7t4ND>Q{G!Tc4s-I(Ua~oU7)^$&lJ1cBJA74)okm9IV(< zV05~YEsb7KWO~a-c9U-#Lnh#sbC;{}Hn{u>^pHveDZB=u1J!~wRl*J=8_-vtjSxG9 zh_f|Hi}$Q*B|GB^>U<oDDPeO3`6m5M4*7mtdcFdYoIk2NCIa!Ei2FAARqpyTLUtT5 zhtN)M7HaOEIsfZ$`)X30{UcJG7b^Bwl|6iE9m~zG{vrN$FAEDR8QOs@hX4j~nIyA7 zznz%HKL*nRaHn(36FFPC<$9da4hSiv>3ytRz|zaO#p<tWRs>=X(qOeJ<|Fc(>)WPS zV8kZQvtC9i3bdHl<Bza@x3P%uk*J6?Ik#dCfjyWF((ez6ElJM#m!n2oL<5`H;Xw)& z3D6i7bpj+$!V1y_RncyT`B-S~jgqvjQHa>!t|bT>fjxvvhXi;WIwTHNYm}WJz$zwj zSqXn*Z~xMFPsd4OceeR4)|fuX>HLa{wCaP{IXj4e%(NHbnBD73CjHyDz<Ag#r3{Ey zoCG;41R|9mMzAIr^3~-%jGBi6AKcBHWr~IVVDmfs`6VJ?M$(J)!A>X<`(egOyOU>4 z1&yiEbY)$~Ygv)S=^`9s14*G~?)fNE9GY3-8cgd6Ln2%NF1?BQZPN=%4=jk|dKM>{ z@9>>QGCA9A`;PNDD9sn7!;T}F&zD8xjz|2}9q5e$J?3!iw@n#)`>;>s`L8n`J;!2= zv5?xe>TT`Ld}e>i7R`foIi0jjD8~La?wEwy+!&PnSZi`6AMvi2{khZWwpVG#*Ju`v z3Q-}KQ~{@|G1X63F-1;suy|QSj0|KjDwQh{rA3g3(>8hli!(5#xD*DH2HwcOKvf7d z)Br+XskK7h`TV=a`5*;@K)DQUPaUqunKUl}1|*KwuKAkBaJbxz;U$*dC#>RCEHrX= zK_<7;sj9<e4V^&jmeiLDEWaH+ohym}VwM2(sI2keafZjSwOfz|yjX>IqAE3Uvjj%= ze^lyoB0BIpnd~MV0+?G&p}SMj9}lvm6LUps_ZK>7S{I7Ont49C5)A(qS<U1_s(e56 zxU~7o#%ZluwS#-fjZ`)5V6wn=t72VIFJ4(Svhl^+>B9udQC74tvNM@yCpWe={b~cF zh131kJy|N}qLHzbqi=DZ-NCZ0RX-{3&D9@&E#!>XyXFBtG6)+97*6W}=>8Re2M&Fq z!5#y?FP1*bJCAEj0(U=aJlNnze>Y-*JPY8R5R^$1;2gZ;<^NuCsT(CY(Ovh#_52xz zNoDMVKGf>sFzq0w#LK7N{siw>X<oeLs8GK4B-IoB?om#P`*Ka8pEG-?9b<lYz6f!_ zDM<H@9Oik+8&1e<;fDFi?QmeEwR0WWW27+n9b=vDmTqV;XU*%#<nCQ}%t(lsSmEf0 zlkkgI(6v2XR22Q3Grbq*@5*O>kXW@*dT3hz=u~G&|M8WLjF`-&S4!N-bg7}RFI&7d z24h{P#n2az3_O|@t}V4)SME#VmyXBSnGb}V^*}y1sa+Gf3MNu1bL*ha*oZk8bd#2N zywLU&UvcFziT@LsU6c05a`vyE+LdA>#EPoMLI}w$97H69o)OWye>F(qLv{0xj}W*2 z6>%56fx=E;w-xxsATkzpMTh*!Ss%6yPHwkX*g6Mow=bzw5Fb|(q5XPvyw=XuVa{E6 z+L5T1fp+K4LWaxx!G%{uR<0Bzd2i(a*lbhN{%>9bTk$r0oaAfTw#|Q_W&dI{^7=jL zlYQU~Y~YN(Jv_7KLjnQW#~tsVrOWRxx{Dyl;ba^zs0kezB#sPU8W6##u6pouE?z8? znPCc=#$JEqyXYrg*M@|F5`&{AnF>1i`Q}v~G_o;o(#SEK0HX$NZ@wBEV{RWcJox=g z1gg-i9MYL2X0n?u1{M3FNZE%?WCw_q4T>VlyK3|2HH$W}$YI=z5vKz_Jf>J(cKE)< z7(eU^PeuxP?AGhjyp}1XTY-gXrB?lV`rvt$T`r5WZ`sWEJF%WBp*`T+!>vU3aIv*m z_xPCX!3e=bPgudoWS)JOa~}(J4bP!BP}vB%_2u5>ih8D@=L5VHhT<SyB}gyW;$gZR zk@I#4RKsm&i%oKeWX6k*7XbrI1(3W*pHWc?^@1YZ(fF%!0bD06i<wwuC`|N@lS>L~ zeN1}(dzc3u#btJh;e#79O(M~`ZnDX4EC)#4v?C<Q=`To`Hy%71;I-K*|9va|`KaM; z_$LM6uUWCbIj9a10N&cTCV!Fk_fh_FSSL8%QWzxZe9jf6VHvuM&r}Ve0jl{s>lri} z`jSRzcA9k@C^O$`?SF9%v5%&talK^7_ur21q}j~>Zt)JFX;8nYw;ro1Q0jQgzY|Nu ze(7Z`cQ+Q(V}6l5XS`BlA)3PF*TBb%G=*zya39&sy#RO4bKiszjutzmLM7<Df;s}8 zM9R{upW&KeVk=6fIhj#Yj&`?T*^S|6(YkJ}WGD*sDfI^^Q|h6T<(_Uqbk?#W9$)cA z1!7A^@ZD4uThp~@8bp=Aj=eF@R$}=AZ{Ahg#rTdh-SY9!41*{zlN%n&^%)`tF1ydk z;PgLK%4`daQfh164UQ}_SL&~ox{L}lm(;PDZFxppvn?*p|6Er*ZcapnO3+TpnVR32 zdCP2nJW*C^_S?e(-I-8yG-#xYH68c*Nr)S&pR<3}^>5FpyZ8by^Am!P7eD`okpKIo zh=7#CU08W<eLAH)4{#*%JSxoF|9Ce<3l|0~4R$<{7SOH!nEw)mK+{+lBgB&MT@6)S zk;w#0&C4t7C18VaL~e~H<vcZcZi}$$=^X<juD2n|JSa<jjD_H{I<Nh^FI5ZN9(Vp_ z(ql+j&Bg7|m^TL5eVAn!GNQEPGUaKqZFO8<zZjDem`ua)z^25t7bC=fkqI=FIun0H zC8xWcP|Q2}K6$CAASu8p`M}MjeS{i{hrl+worr61S58R^U<w$%Yurt}dE+wE*0S1W zgfaV8`;J~o%dES`Y0Ds1u|g%h2C!d<xWf?(ac{4XeRn8{%OQo~5wgNG?(?pj=oNjt z+-!8SvcvL$Hl@$xF;H37sqB*2zIBjOMLzq+K>8IOZ%)Q}A+~!OV;axdH^Sakwuif8 z30h77g@Az;`yoIZBT?~ksuVj5HY0J{0gv#j{Xg8{>A6hCxBKxX3MeFro2QZR_tp5x z3BLuUxQ?FxaV&q_g5N)U5(uO)PXbfSc#-Ud0WY`XlQ8hl#1=TV_=!A!dZoN4C8Lk2 zG-^xGEC@|h30|e~+P;S!1(NscGjFg5hlGTT&Z%VR7*mKmNg*6c0#nLVnqi?o53MqD zyEmYcxPje9CKQR1*xo9@Pb7_xTBedJaxQ2@6Ofc=Tvb`AtTu7-v=z;4$Md-|FYmkK zIzV?g%zELFT4x&6pkLkP%R(kR5t5&$<3>#ul%Mo*HVPZIBbwOY_I^6o?8WmKaziDZ z8TqE#-TrhbSnuffIsin{n>bRX<9@h~${!Pt+0`jc24;U*d07?u;&Fo1EdHpUQX`Ud zY#ugQMY4cEH*#c492ExkbF5iKa*GH18l3&|`p~6JSd4|?_L`R>V^lQxl~UtQtk7i- z7rjmIK*H4_HuiIK1pv(XMugxq6l^Gdmn%Ly2XvDHTmW|ImEVGdUX=29aJ$EIE7|>r z-T&hNfa<7CKoofLKc7$Te|b&`+^Heh`t{^L3RhtqP@6;lI=wf7J#a<dsma^T*M$11 z6u*mqK&6x~SDm?DV8oValZx_fxp=+`t4QL2;~qDO(^dsgl0Eq44#G@xgNXD@BE|HY zQ^u8T>4$O+bSAn86&RUY4Fhx&ps?CCTK=FE8s?N|=A<E)d9pfEhjHIx`|)*(xu|n$ zcBDX=;aZnjepJu`9;@{-%)Y?xxU1+e^GudTh1t7IRPxWzJ0n_$!4(D%O}_1<ioHDd znO;jX^DPss-lt;hDseWSsl1ZDKnQqbAjr89VF;C`KiAQ6%$@t>^;1Be-m<|>4!BVk zH@W8=VA$7eR0>++s*Mc3*Tm25juNl(p$#uNxo)i5R12&nM;caVO!BX<L5VRpls#Is z;2FfM`Q9-W%ruoY2QC^7mUVv6Bu1EJCwy@2{RVE_91TjV$iM4|KNIwS{{o@~&L;|= z-~%7hSqMCxXGpai{A=uOg_6vRM3w};K=sP;b=aF9Sr~iGD|8DpNMbX1gHP&yLc|q1 zRtpTg_d`ZMKcEPgJ0bG!@0XJ9P1ZcHB<8!+y*lk@z07a#ZU$JT1ZHy=N31TNrviP) z+M!)rewdZDf@0naw#iOl!xa;kpV=qB6WOUZ3q$Al>jbSxpqj1JY`&Zu*YS*e##JuM z{b981{PD-#Fi)pmpn*hsqqK^V-c5CXy5j4B*5dYJL@nAI;8AzG;#G7u>*g~08kufB zs`_N*%iH#Vhp7W(z5yJ%X^;m~`LR)tsdLaVUORcwmQm5(n^NYNXJTY<ov#CNr?9(W zE+!C4DmdGnexoEZE<JxZ7VSApG3LeF+p0`C7D-B1Jdo(ro)g~3#H~L$Los2|2>RCm zC^HrJko^0=<?hvwe|B&GGd%zGn)hWWL<>LCqw(9j6UVmwg})#BzurL;)`paTJC!9G zcx(O$e^1^4<LG;*#4phIcR6ai9Fksqegb|?t7QfFj!e#mZxflMg75^ZH*_rea7My0 zyKK$edZl&l#>AMbDYVw75_i5qB~OF{_>MNIOjxnD)j4D4W~N|D<Y;UJ>x%b>fM<x8 zs>u3QID}A8m?q~3ra?lB+crdb3@NmnGDbx}{}DLaktcE273&`Et!VIhz0KoYqPwAT zt?6mFRvN^q0@(j2*N7tt%ZO#VH)$<@b*KD6y8@_^&yEV*YiF?g@Npm`eSiFynY*~~ zrmIjFSonX=WBz&!h~l~}@RrsIri<f$`;j3WZ(wBLBkP$=+6l$?#l$s)4sueF9ZiH> zsJQV`3#=9uNYhS<LvKUWdk8Bk3X&`g#A29W1)h8+*^x})>Q{%LZB>9*Neb2dreCOe zJl~H>W9sY9v;ZA12jOlXfl&>Ufmpho&82wWaL%{y>TJ@8`~U-)Jq>Em>MJKSFh0&0 zc2>R?Voo5V8$=SF)LWQ-v@`!LM9Aedf33asroToG$s*0oT>b+|O#XTs%k6O_S>W8Z zK$kc+sl<7d?;$je@@%ATg(8wv3UHq;VQ%}m6cgqeWdCMYD1J8JMlkpP)x)~`othAO zUi>5J`!fa(VR-YRqg~Gw(as7ZA-!HjcwNL{JsHB8kA=&R8OdWIaT|giNK4$QRft8d zP8u@MU7}wRt)OwYB7BUk!=>MoDm0_y#tkl~Cmt7myJmD_Qp9r{^)n0XbowoD*=)Z` zN$|=Tpqe%s`8pM3%~~?4!s#tSWTPEq4t{QKm4l3{ixlc{^d&SB%kAu2K6wm@`*vTJ z9FEZKmXZwuQN^V4BZ2B-hVudJD=!(LoFjQcsE3_R6mSEDAL_(p`AtSL%_`A1&iDY_ z7S!UOBJfkTs;aYp{ZTc8JHGx+$8-sQ1RJiF?(hHS;Qx11z3t`=JOo`lx4QqYw~wac zNH{=}j8E>yu)5@x@Mw!6E`@J=@_mzbIKY|~DAC@_dZB&@T?P!pKh(-~Dh@YP+2$)E z8L4LN9&br#-)#k!*6g-*M6M2QCl<k%E>uoIr#w`lWUqriVqL9|e2rFgo{hq?*y(*D z`>X(4A1Uf#susIEWPn@k=s^)ePaaLgV-J)nw-?zBhU0kd)zME)_IL6-u~6^msVT2_ zV$J6=zRPmHvV_4tSmIcaR+SeVDTp(lMHbym<YV`}P|-QxR$##@P6aRg|Mhs_lcdri z=NM9@J$Z-#b&lfEdZ&75V!|PBP<22MTi~*=iBKO}0i#0>ZOXWk&W?_|iDa5D&qs6m zZXl^E6Ki!al$WW4eSc~cB?irf^$w&<U4g1MGLG`7G)@b#$*2~-s*v9IOOQ@|4Sq$3 zn1&Ul>-<ohyz}er_HuNt4(c(&(l}NcYvCJ^Q3jWd{MUSsaDVWw{CIv%cY6~jxUk!! zyQj~>2=#8G=W99nJdO<x7sYy+bnA}F&~6OqekM2KW1qfnO?Tk^BYwsE9q~ZE6Ca@M zYw<_hH*3Uj{rX?~JehwDi@+5BH&-!p3|<U}|9lIB{O!#CjKG=CL8G6=LPr6_{H?{; zj5)R;tkrDv0GeT-q0p&lOLwQqHq#wqJ$;JnDeHFjm_JGh385ltF2;8x3ua-yoPw+l zw6QdIbohD|6G?AgIjlC83#Wi3sO@1}+ih64$EBC7*oMXvrFDS0_SbYc9WkVS&G~w# zFYcG>mhW~pU0^txtN18x*F+cT0r??^N%eN%NDjgyMXidssJY28VM1NRFvW8tr55EE zl!rw`!C<r&^DUG%-y9aLxnn5(eeVm(6cY`;0@<rd3j-+mlRoy3>*HKD7JFN!=x7&C z|4ahE!|NdRjKvt*i=!U$KtS-E5l-HqH&<n{lBiRsZ1X=SD1SYyeYCPi1}R(?B0UkL z9dIRhfDcIh17%YwoWipMz=u40KWt7E+E;Bp%YM2u#qb;4zQ`%tK(aYKijEdbBl`$| z-WmZpA$j}h_Qb8AgDg4g!Ee;SKQkh48h?b5v8PX;0wEU*Xp1ptnN62eM|ggFK=^oX zu38DH{fQDtE}6%&%VyxAFr+gPU%HsbR%)F-xR?e;CTRF&AVCUNk&;jmjBQB2O&Cmj zzmpwjaVf59e<}JfhSZP;WG;b~Za7uy@RGs3PiZywDA)cn7V~Bl+ho^N)jAZ$uqO6p zIQO%pt`e<S?C7%cXU0RS4#TbKq)w=ja*yg9R0~W$QI7WZ<{P20X}&=WDSqfVU34NQ za9_Cm$OMLhb5OvY$B7Bu5y!`+VDnxq_AqH6NfO<P@*3Uy?Fp&~pZx77dEpuNhMPlZ z25~Uz$JSeiB)<5xnSUET|8LWmFP<m>+5AdbH<8(s)F6n}9UuibV~B@cflG<IvXvb< zoZ=^6a$@!c1qBaIzUnKluKo$Ly7uq1{$CHBP8#K1ttF|7rgaw)KCZ;OGCzNJOs`;v z!?xFhoaN)4atyH<JZ7tT@dyy~vC<hcyD0pzfMtcAlGV;JRg#)hx^jOKzoH$0Qf?#A z!wxhn93jdFm}f?E;JP97Ze>kpEhnQ!%6x#_Z8jQuSzba%>wKiddq$!0q|aEP-!_he zR~Cg!7tM=T-<rKwq*scJcm31j+_r#>W@1DEb2M|QT?z5!9ET!)N@Q{oRQ}#<h8Cxa zf<4w}r~=_noxzaRU+Y8+{YH_*T0_v54TcmJ;+aWHv;y)S*heFA?0H1JpaU;m37+5c z!)3HMcu^|<J-_x#U-NN4gY_9}oO*B(K&O%glrmWs^EKXqPyQA6|MiUi^9VwOy+~E^ zWj^5noQj3O?iH-=<fX$5sc!Sx_rj@lEysnY-QmQ9Mu6b>HEg&-CHD=eEtTB!=BTZ4 zT3J<#lf-URm{(jGIG-RCKgT6^ZjS(j@g;-J8y?<?|4KrEIg#7QSm$w3&73Lk2Oe5P zVSbRzD+>L*r=e*y2sj4CGuBs6BQbS?(N-x@>4m)%g<pT2NJuyD=m=P?-&j(MroBHM zAhW+5tD~prN-h*S6Ww*{pPtE;cH_B%31i3He*IqRe(X!)U?lA(1&g{e4rR$u$Sm<h zd98I;vGJ+w;b-($y>^O|)U;rSXUMS%qb*KxIDEZkMPCOV=I*}Z6dj-7c}5PV%k?d5 zds~6%G4AUD_`oY8N+!-XQtQeuI=nrlf{uja1~dGSz;DMz6Gd%iZvctM)IBfOPDcnU z)nCTmPXwQA{F>0%?91&#h0{a=QeEO{7Ii+qTb%!u7%cx?(fWhnJF$MiWJWNAAjZ$? zeD*`n0ydpGYc4&mBpRW%lb$XiO26jYl9R#%6hDs3HsE1jQT>x*=FjNR|J3`Gmrn;z zqyoA9LqLZie^4<^LUPQEiGDNviZzb3Y*@8^S#k1MR%8y+nSu?DV>q*eF@r~{qI(?u zQu6crm}pO_U0rAnxH}={Mk(YFxd7U5%%XmyNQia%N?Z!-ieg37yy3>I<TT&Gc%bFR zpwJi)1DOk=H*F(gtQkifF9l1{0Ae6EG9uqD3yRIHa(&78s+2xekw14sHy={IJE9c{ zKtbtar!mj9Fng1}I~s_2DK5^%i8@!|EjTMi8!raD-2ax@LPK>@??&E?-zALXc09^t z!mY78NW$AQ0JHv;!0jY{mPYMHdp)7HV&?Z7LjHqY554iuqpT6G`9Sw`e&ajrUh&_L zw@u(RJTaq~3I8$GL+(kU?XsQA)4z0gUJLil;clH^f&W7oHr_#lOOvetkny02833Iw zI+8AUB3A%xMU{VCZu53FBC-{?SSu}VWg7`E-yrsMrvb?%bI>;d*hSn&o{<YPLbzb? zfBg|-G?ekpEzW7pSAe=^b#e-jRJ#%@p`&%a!Ph8GvRN%N30)TL%wUK}@#s>QPT;!j zrPn6W+NlU<ET5xdY7-aFRW=|dKBSmZYCPQDly9nEUsvU#_Vo-GzRL||bjP8#=nj^} zI;wK@EoZNJQpn6JWw$}DzJudnD18!2YJck+t0>9!3<t8+$;#?<D*XmzI(k^}%GsT+ z%$tnLd3|~8p`V*qC<}3nII25VU(T9OPaQ?KPpVh`x)%r8Y*fbA#g|%!cI+$pS2OXq zlb$c3FJAAElOMCVJ5hlc;gxM;J~Ts5IbQ_#nZrfeN&zi7_JD&9bE>1>Z40askW^|1 z&}e`-<Pz&{-HD|?RspE~FUFdhSxZ#lBB8Mn0#V)DMg%y({%!LFu0&utoDS%Hal%3r za#yzI{+})s@EQPfsq$F^sGvw37M(Yn`Y(}woV?_yh?wiv(eR{98P@FR<G#C+fjk4$ zfW8zJonFk?W*t2K?}L&<+v07o|Mfi!p!v3ybsrNWTo_5h-vtK9*5guWp!5`99<!i2 zbF4X&v^v|>(&}qOuC2g0FUSwhz+F9GzKXb={BW$J*+XiBsW9lQxVV8Z**%VZxY8Xp zZHsxYkjspc1{YN%__m6Z3xE;4@^lkEH3Ji6pH2;L2)&#>!w!%J=7p<7bX*0$bXOmz z2iqui)|yhu%2-G_Az@sT9F7vU9hSvk)xLkD>M?5Y80F%Zs4)3!$=2OaXhyemhFqB3 zXQ}n=d|CRKh}|{h`<PfpYWE73mh#V@eG}M{D(GmUf{0m<l0@zoJ(mPmW<R83!52;4 zuQQasyc4!T9u{J7yBYIrCuqL*^TpzA0;P%g14Baj9L-_C)%WAVeO^!Hy9-{E3*QJ* z{s5+$na}$VH9P(*4*W;{3d|v#05{hG#28}Jxd#+FUashtn+2xutK^xERfG27vRg+7 z9c}IwaCU^&Hkw`k^&9)K5Cz3Q9QXi3eH1)ketR^L8jQarJ7`DLgBj`TWQlb9G}dB@ zPFjZ3kIWvcODkJErOw<5WhWb3r+nU&n885wZi@C^>SYx4Qj|L-(7n$f&;w3t+p9+& zBj`kgTtO1@q1H4nl8>(fN-UC|WV<{5AFQ@=_#YIB7{QaJ5Z9~m;8z6y-_zR4Wmqcb zcYDDbaRHUf2Jp6=4cw*m9~FIfm&+E9#JX`>Yb2i}<)8k~Apf5ad>nUlCtR!10TZs! zCFcv=2ir&7BJY3uE?l{Sxv1mt))qV*ZTGV&V8u;`YsPgq!}E?8E(0x-#7ZHPF2HMd zuqb%CJNv5al{h$A(A5Fn#~Zfv@pxBl`t)5Dh=f9DD3$lsU@|8IXk;h1ddx0VPqzqz zxlXrACq-b*Al06FHiOIJ-CHB`u(3ZIIseE}b_l(#*Sh_Id=Io+F~DrkUbMNztknQ` z2`%pIfmagO=X)2N-6;Go_dpIB+$Vo<S>`xd{EN$SnUeU>xi|AqE=w-#*CC|hDtAw7 zEsA=TG#U<#B4Hn?C3KO&HbmH5V}TrG+x<eey}20J?pO4@qw$QnHv@s?pGk7pC&g3B z<6l3ckLO_BW#xU?1>)qT33=?E3hE2`P{boSN75@g(?*aP1SP+k`I(6YAHx5?C$vOD z`gcOh=qTWfWAIlx;AdO`Z)x}M#}RM>%&C8PJ@d*TF1=_m0{Z>{hCh?RzZ($$-Vq0! zA0rZqo6zNYEZdChW}4%$2@P<+<W}DF7Fpa>pK-U-D-$cW98Ci(X1&prqDDqW&8<D} zH^Yf7>nMHz+}muIptL8#u<PAQ=oY}Vtp;pvjhCo-o{oukkh$)%5egXrEM3fHFSfl= z$(}hZxnDr|a{<&o%VQEAR>s;NHY>LmOVCD}?~ZdO`LNasKy}9-sE2;WNq&MgAGBO6 zstBLCUo3C~Df?5s?cBtOV-&IIsJ~kN|HzBZLJ>yLsX$Et=@Z-<jAQ(POgC*z)&cVD z<6waUfMG{Mq%I%FVVlM|nw669O6>k1O^|*?1tkGEDyW}<vXd;Nw$~C-kh&~2I45Xb zdyQo}9rCYYdI)Vo62(=)oZN=M^gM2-Etbq^j+SIJ@EJ0D)K8HVJ^&o188fCPlfx4; zv07DF^~{e3L)^E+fln7xC6lr+*o34PImFH=5f5*9X4NmJq5yMNkFht$VV&IhQi0U@ z%4p#0b01m_Aa&a9h!u=87A?TCkpe|Q4Zl!EdhS{2PDudT0x;jG;<D_XpbtHdKY@Km znv}B8ny!cE;VhUmt}o3SE)$+tM+#j*oj(3()C1xUX6u68N!v^GgO(E&*rD%52Mj8N z9?JB6Ok2|qGsR+--)^hS_{{;F8O@-l31^-%gN&@DGEqp-wFKw8y5nuHhI71fJD?Mj z6s@}9esZ>gdXELDGbzA;+ukn4P)ektZ8TM8ez9Rw!fL($$-Sd97{48$Lc%$pJpg?= z`YjOQ{oWhyi$W(fe^DI(a!IhX`d=lDSC8IQf8O{9pz9xJ_;;9=UqU-fSp?ScaF(EW zhiRe559&5!EW(<8M`VLkCB8hjwbD`)KOj+ST3j+{1q49!02%nor4ZWg0=wNAwuiHo z^4NvJ6_iMwat~3CJ~r;vlot#6Q-LHBY;xmO9*qcIq~6jjQgoc7_&t6C0FVCN1tyas z0ffV<JjcD1YfZp1{3NSxo0kupL`F8e&<R^iMe(~0|AvgIk&LS&Yb9t6A1qMH6;&bK ztuPF~V}H~wu6nEz4lrKjWXvhrAOK1R#Bs;ao7&UpY}rr!AO`+ZQPV;>jT*)ILtaJV zDo$wp>0075n{aUfDTy_F0M{iIu60|XMXlVa!^<qfnID3n5428%5kKRn3L?&JL6F3` z-kKIwh-tKCij!I)D%9i{6gl}!(k@JL8T344$FY#$GQ=mdKQalGARCqJOfVmfjJN{Q zzVfb_u@$czhUZf2JYQ<7v*#zWwMpKY%oFlGjc9{Id7y%qPLEH84%)q+chQo$Qr+C9 zQ)F!(Gx){I?U6skY+{vpc5jlW6YsD$7ibW{Pf^sgV;X&SaM9y0&C&u{u#Im#sE5LC zBU&x_MfE%2JQhtnH7`vlH1wWUy0%NYixxhzk@290LSRoZ;6PW%3EX`pFY%6WuIY6I zh;cE{@ctiN7ON0W9l*?)t)ZelA_fmmeOzy}|46Kd=}DFT@K%6OB*DVewCir|q6>q0 z!*-rtLl+7oU@0p;7|dvl;}f6#+tEbeTFE?ju(b|As2CsU5#a{_Ywuh$y1s)|6DWS% zi%yhLZBgTcpI&vS>bO63#2aNsnYXCbf=iCQ(#HhI4FLV)PTuz<!v*k47s!b+F!^`O zMC$+wyUIr7!Y?&IkLWQG2i>_hpzg=Sm6-bK-wh4;E|UiZU=P2p)0hL+{aVAkfl4s& zY`XMaCVxj!*5^&*{a<3XKn7HnuG{m3Kj_nYP6z#*r#)%ib__MC9(ZU@bc#qmcE;J+ zT+}Xc1x#k|=MH%fSsIT&77eNyigO)h9G3~F!~pG?Qf10u+LoJMp{uR&gs`2R4jh*P z>}?RTBsbH_Kmx2PlqM`riiig}3(LgjtJ2F%ZR8K1f%$>OgB1-<Jcnfp@ib8f4(qu| zpg5SVF#U<_P2x_{t1oSFlV4N(DOwb2`#RtVG6T`MTj>il&+0)1ItI(a$54%PYSGs2 zV4<_MSSr*n;iP|3?)U|XfAchzhN!*&RKf=H^x1PMJNn3tAvp8d+WSGfbOLKz!~;V^ z`~7ihO}B03qpo4X`&$8l^R14td*aeoA{yu&J!3t93-i}z5L;~c^%3X$yKC-pu)B*9 z&;9P*N+`=6v5sFEvS=jPK%jc%`v-W>;j|!CBXVf8sXw^izO5P_9Kgr9%V@qpsI1^w zy5BU*!k8g`WEL(s^AtnG+*1_br7RblRQp^`9DY?9_1Zu(teN%=E@wA^^kX`SC*_%H z3XECv4C5SE86%7r*5_8k`?E%b2^$_IW)APu`D`;P`&$l92A^aewxK=q_Qyda1Tp%N zy96^eB4nY^y?>5Ksf!Zkh0BWc26+8HzF~#p%CGui;Is&BS)_X)*giKGehGmmP``zY z%u1UH04nmdw`yfSYzE?Adl>?&=q@=Lcr~-{Q&^o2mwmLgy;x1gbIMM~r3nqYeDR?I zY?}5{%E5v_`zF&#R?ADi32VsnI5xvioZOv5eiYDcg_JK4|L3QO#L4Wv05rWyaV>xj zD%3M$QujOi*wUCYB9hn?DZj%cCfXBF)GJx->JWt9#5@q<i$EeD+LqJkzK5>cQQ~rP zT(+>mF(Vn@b!5^Fb7^cckClnnycy-I3<LraN99H`GIr6@;%uK70(M^%%13#BL?hi3 zyMo1q-@JUtKHJ6+L9UKT%apl7_LXTil}rBS+d46Xe+k8*NO(EMJhJ(QVj^ITHTt^@ zOIZ$-h0Niq?HN8YvD3>JUM$ZYD)JL8$XF_3!OgI++(?}pP^>1~Au4wLs)4wH1&)El zogoGkoV!Mh1Ia~vtBQ!k%=>&5E~8jjTCNg~hW+Cr(rRSEk!BH{_MXqYYz5n_7d6%O zz0>Ait;mSB&?8h*8#T=5v5f}}f&#EM_w9y$B@cHMHF^U6b&j6^c#)i?1>|-+G@W&@ z@9N*;y03);96N$PDsb40erR<FdK5RK(&n=d(5NA71OIjY|F8^i7fP$U%gw;bVZOpe zhi7!w?GMnHA#`UCOb3Z^EP<#t+Uj}#BtQe92CxN13XG<dk1f0;_LB-GV4L;cGJv`z z*V_FNPCBsoSO)N^QS)1hZcXGviMThBP_S^;->Q58nt}fF6nV0Pv1?v`aRH<xSSlMY zwYVEkeN~QuuU6{q&XjKl1g(mM-QON~>P>!8SjmnAOFbY5aFo(q)wj<8ajFJqBpo<~ z=hkSJsKrjgzgxKXgGb&Jq5*!uXDD7zW&tSot$-9UG4AQBGe<jZuc!qtR{9;!=fs!e zR5uK$n!HQV@vxn~tT%5WnGKR{zHQJ}C@ylcOL+8c1SBy)1!|$~Fj0Y@MHoKfceT5n zz9TN3AF${@XqK<A5s<s@1=_y~jCz%q-<NT-hRol$F7B?)6W#MhC^BQ<^A``l%5D(T z%Zmq*d6=8!$70eYEXcNKtknwc#(;!L4mR{?Wq=t~75)C5?~OhKu{(W|=uD_utR<OO zpd53ej$vou*4WtGm_ld=M_%A)SL-<z^sZdNZ5H1%ct+(p`|h^)t5y5Zynfs-IS7E< zuqT1TuL(yifO+ahfoG%BV1nrZDw&({OxA@Qr=2MS1h$op-SIp>J<5`w=QwGt{ilYx zR)<Qg=b|SR*0XegCf!}g!qRXW(vFNr2tuQ{fSXVl+=TRQCO3baGy$H0(@ez)NZpb0 z`Q3pD1$>OKZTib7QOjXijPpfcB1IG3iWr*eo6x#<Df2M|T6SZ0X;m=H?Ru%}vuPb{ zfFk?-+;qdQ5@M&z3Q&wy*30x&h1mbSXZmfKUr@XgwO#0`$?vzJo{z-IoDHdIIPKzi z*h&GH1?1m{01HcCUo36@Il$_g`@xl=xJpspENp$#h8qRVuVH=Mti-+kOz8B0cBgus zEJc;}f{>W=Jz{&L=gpd3?6>zR76d>P)+RBH;2n{HXO4FG?Jo<96r-l|5dg>DLifYP z3Lw@acmzteMQjI@BVs&IXIN{+;B8}*gC0^x&AR=DU+q(>I;07}AjWEtt;Y|5RZ%_f zlY`f@@YJCrMw<CKbNzaZ6)<h_V`-&2C`g9OHrNrrF8Hto^r;<xCk4Q)hwjX4MDTou z@^=AJ04rHC{CBraV21+y*}_AhdldKM;l13?gI@sIY<-Tvhn<5h_6KPApP9KqQM9s_ z9D?=ZIKijustl$4(|sFTQH8Ris?O8aNtU=EA<dStXy}b_j7br!zQk~A9MpFd$Wjco z-KHbg<Qse%tJY<(yHe>n+pYJa_!GK;-B|Pik4()wN<lsxgCR~ipMV=23C!|%OfU+9 z0Kua#t8CLW+fVVq#8G7I?!DG(Wzj8M49jD}c>yFMCD>23tw}Cp$@|9qY5O-Tyc0`t zHM)8t*uYiLpT`*&<4TWR&@>FA3<tY>p<F~24(0Zw0_L4<pI&|F$|_Jqc}WkcgF#ih z1Ceq|({Ik`TOW~k2D-Xm?LR*Ucua`&%ord}Hn1|QwKLVg@5LH{fSPc<yqbK6a4Mkg z+Ox907Ad)Vlkk8L^n`Mw9<VYDd?aRwS`v8g*wtbO>37Q290tN-VGIeL_&h9dGT0_f zu1&?kbtK~R0!4rHb>l&cs}rCS)ehJ8y92yYs8;D6AV`kh#P}KJg@l3ozo`4lfGE)I zZx}j<ZWv02MwAwYK}0$P5d;JYmqtni9J(6`L1{q|ky1(NPAMe>1%?*X8OkAq_nEzS z@7=w7@BjPz(Op+}nCCgqIlnps$K_S6fg7`L90MDTziPz$Zr<#Ze7BwUW^E3)u6h=* z_~z5?2%63}qliljU`4@yd4K;|f2mj?s)qxHz*dUjcw}xDhuImDiebKCUS!Q_gzjz@ zM=oaEGbmnnIPmViI0T;HNFXe4>?MS+?hRpw&TZ(nNjC01akcUIHBvzkrtYjTQebij z1>IrBhc8BYTPDE3&uAE#=l2p3`2*x3Q(4}<74+guxK(KT#cv%EWTgv-AOwr#3rRB| zZzv2L@UdKNp!%BFGQ=Dt@~AYWI@|*@a};ol)|2jmTj0I4+YTe)XX3{!WX3VVf!oJQ zS{byq0RQ%o-By<VYo|fQ0AbqLxsP=3Ug(+czQMZrV}pT&{8)32qUKs?p|VTbcfM8I zbSSNK7OhXO%OHDJviHn5V@kfVhr`T6oIuD9kyHx&SHD5<#(0>wrCa~mBbc4G6fKo& zJM4lM_M?5dKYDy9D{ymM7y208XWJ1i9VvNTG`O~eP?h2fTO{moQ2yKk=B?r$F++|} zk!sZhQnIi_tN^W<$z<rW=kydsZHQ$bg4f9~9K}_2LJ0K?)2nh}vvF1T1{^CBs5xV$ zPx<_B7vbjjHBrngTG9CyT+h8)p~)}5G2BHqe3s`WFkHny>~LBepDu|zj8ulIt2qCr z{s)`U#2z~RWp$9qwgu_)%6p5yHU-nZbKZTFGa}7{{eam!@7xwl7M16BdX_d%LhjS< z5RE^j^pH#zUQY<q$67`qJuN9aCBJR9Cf`j4h0PeoLOm)ui2lt`&u_KU(I6%C*;Q}E znb6`n2QO)el;C%eQqY+>k`(1)!o=&j+=1UpPbs!@PqJ>tZu3S|Zr}b`bN8#4F9&Cx zhjr5#4HWn=PhF1oHhucn$+}3$cZu%x$^7-Z``3|e4^L_bY-qND+O*`+{ub-v#~4tC zr6}pNF2l<nPyT3BsbxS5O}G5~a_Lpm*O!?uMvF`&)okML4LqB+I`-bW>p?<3?^~39 zA_WrLFhe${uRBt2ScJCIaB{V)+rG#9jA`GF7s*n26GGa(+M)F(8wX4H<O8k;+chM5 zRgG&;Jp1`#nASia>D#dRJO|Qd*zCgq=4F#2vnuP&>JEVCNPPC^odp>bJhWgZr*A4< zltHuR`Ty(==m}}-ON{CnIAolR7H^My(hAXBCn4v`X5VenYF~xT3qHkYN(Foj7|mV@ z_AX<eWDDWuY)Twxd+tbE78)w8_<8taS9-o(hk9j0qR&kp*sY!`F{ryeeb!zZe1~^l zHGrz-TLNcSxl*N&Ry6cvasBXTnwY`&ENN8FxbkZb0|jSl$dw?c9>nAFqAsC*+o9w} z|Gf>SbR5KF(OGf<7x|Vp(2eipX$-A>;PyjTi8SYt4QUqD`eG*}c9U<9iL))<FhwFz z)GyU=Z?Q&hU@Qw3=&O-9*Ij2Jj%@fyLLUC?b!#Ogl9u}sc}VNmqu1{_EWjF(0!d1# z#K6{93&!D}kM?Lpy*&vpi$o4zgj~ICt5#SEA*O^Xd=3KK(I(|r;|9-6$!X^w)m^lA z5{7kVYh`$(pde&6ou_2IbX$u2*zG0$_e+8im$+j>S1QkXWxMU{w9GR~)&IFc9!E4a zI|C^-TdH+)VL!~U*~;8^{G`CiC&msOOAJGXSbY&_&LmF0nzd1a9jw;33%0jFLDQBp zFVkB8jd<$3+e~%!+7s8Q8S3frUAttH4_2W@L>z|yYlyi`%tA+u0QJW==QnJafFMP> zxRr>A*V8g8I)%g2m*tg|Kq&FV-WhOOy7Kav#1u<<|Eu|oqq09i+IuxfabMex?_Fis zyJMAQ6*y8WRe!p6BNPJ+@?d$@tWbv*VMj{vUNNcq6IR}nHTgCQRLB*kI?Ow1Fymkr zBcRdj7k?8Rw>jO(+T%|9y{ZN`?uXhz=+C&#16DIlY@t7rc!F`ZamHtRlZG+*Di5AZ zx7l+m`D)oC7!f)4$%;Z&-UH|2vd(~{0NVM<wJI;ac=uIMf<#?^56@p`r7#jmm^xJD zt@T!kf4$tq?-SBd-lhA`3BptZ+Y<FdX3`uhSYqNb9_TL-#wiK@n!IS1FQ@EXffaZ# zTSQdA<?fqNUV$cD>(6{6ag0i~@*1C3VuIzPyKQZ060s3LyKRM?hn?0)300`MUZ+M6 z!IYC~{Z7tDrzTX@_9H}OR$^GD=qzVfsD}D1N&*KqG(P37?S;M&MD@BEw-7KuAM`@5 zwmufK=23l31xv;4rLN5|zy^P{3m~ves<c#C+2=8s(rB0)?@?}*tZU203U++@NhD2k zUCljq<-M{w$M@*_{ntexyX6E+Yn+u7T?K3$XT^;U8!gL{%o6uMR^I9&<vcyV*+fvp z-~S4<NJuJ;LQrDy@|$y}K9G!9!A;PQsSE?mU+?jSXT91#l+U+<E)4>2mrCqbT@yhr zrhuLx(ic6R|KR)MR!Xai6Od9_lAfm%B(K%H0DyfWDIQ)AeFgA!=$6UFPS22#2WTjj zO5$U{?o4Y)Yk)}Q^yZ98D!ReTj$!|^eQk$?6OesKy?#qikSYbdqS?3nD!b#JOCoV# z0RS@(P%d;T`G5Zm=n~(w2c-silqe5v|DT`lcL5YSE1q7Eck_v*e&cE_;yNg#h_7k7 zRgDL$Qw#HybPZ9r0q(AQ-dkZ5Am8J+wRRzqO}Vcc(D6(6+m3Gup9V|ylaQZ$@$5H} z_A(y@r=0t}!g3;>!Jnq{*$Sim$_~INrRrF8;<+rV3(OMKJjxA5yvAMU4FZ3D=gtT1 zlP7?7KQ`PcG9UH%D|}F0&0E-34F1AddEUJQw#0;Q<um=|LYg_s&RQzU4lCCZQl+z! zdk3-6quI@F=ME>u?sKxs4X=v9H2u(BL(3Oqs!fO1amMfK(Ovf3J6#GXBC0q^9?csQ zJ*1BVal<}o64-=aVnWg~l69j&rZOyS%p%iIyTey>3#D0aXJ0T|j_4+x_-zJ*uAv|f z3~eWU3=~{T7oQiAtt$6q=>;BLE-Hwq(7QsIGrCH|*)wgiBTHwqbu~Hf$(}i@5}ov0 z)!vOYtZWuE@WfMGEz6&%lXoGM?%@lvkt#@}CeM*$gU?t6(5<{*O3AV@NntiC2Pf@I z>MR~xVTnXGLWp^ec>HE;qqgn>>W9;b^KP^BwC_1$g>&(&vQ`DhAlX#Vx&RT>2?Mb| zz8W4>;bl)NFcXU-@(a|tn2-r=xT(XWRR+f~DY3zcjeU|V1kQl%G?><zuCwu-ws5WR zrTn0@^@{Oo630g;c^4T!!cLpBqiIZn%?ZD|<4XTS+u|g-m+r2cJ*%Lv%<)iL4E&L6 z6`ESSRP(=2Vt6z`Y0mVc_Moq2rO|*Bse0-T>Z5|1B`ACI=c-EJhlgLwt0d>$+IKzj zH~qGzDqbA|-3Pap%=*p34Kh`nS`&@guFg@@lucH18r!Z(>HJZSC1EF+TC&r=bbQ69 zq|aN884Xg=HJob%yfld!Qym@wwf$&nMssU<$$$QB;p8cmj@R!H177N&opPW09(~NA z5fXfiV|<3vGs*qe-X8D(Fs&1jQFu}LiJ;{oGH+Oj#90IXWHlIlo?$_DY!+<^D3L7_ zNxeOFIc~4D{lRk7Nt(G|$3Lt1)}|r=Hz)YT@@`9JFK+D@WB2X>@KikW!b0OY%o#`5 zrQU77wyRnHS6lNtEOxs{9r=3`kRaJ4OtL#4dS1G2v*w}vi1YS}mikJ7IwmtgUkY&{ z_QZA7;o=Q}QI0f3-QdUfeS;&9e$3Odqbyn_lQx+PPVOE)%Yv;8^Yy;|XfYNMLwh`y z>tz5!Y_(c9vFawM3N^*A@r<S}+v=|23%nCoIUJPdv^X7KjyMfNW{Ej(CraA;4}V-N z@3BP>v9`F?EDsSFdVMS|Hpeijt9Y$4@|55(&Z#E@$%>I&)~AGBSqOUsvPVtThOB0B zyqHWndd1Qn7oS4?bo5t!%C0FXlvCPsZTM!tJ~RLMHcC2co?mvj<#Vhhf<07{M<(We zjjOtqIFLL~{_{(aS=#;=ul4GQ!CMoc+?`vxFp0+!iNm}}$W?!B8k#^9&U1l^6&5qF z8k;4hybYc&C*#8|*eM8MlTaYXA5%Psf}g{Q3F_6Z2MTmcg&YpGZ(ar8#l6J`Z-*}o z4HNQ9$pH5D@cMSg5CtWdu-{@7tX?Q1Fl-Y1ore{q_vgJdMc+TRFJh12=eE8AvI{55 zZkGc6*yf6iLDYk_$BvYx6?tG$`+y6Wy>pi%OTk`qY2||%`%NX+%D2%o^6r54qcJr# zjWhd7W)`%2IleZ0_O0_|+UZ)(T^?H16U<nv${Ao9g24htvQ|b;w`#RQ&!^c6*dz$O zQ+Y)l<-2X;S(@u$kEs0rXoN%Q%`x;dU^fdD*@uj|5&R~{Q0rSIps<S~7ZqopWm$7* zAz8V-y6K}zT(CO(Gv17%6l45TH>Z~bC!R@V6-wp(flJ8OLn47XQO=XI12nDqU+&C< zT>{K%gKC!q7uQEkK#kQ-7kcK{&a60;aeA_@N=A9lKlv6aRR8%6wzL<9ox$K8G6@e+ zGa6O1XX4Fh+RwW4f*{OsIflzyD=Bl8guIC`j57m33_m#nYxT7%CqkrLCf^MI6$E_i zOT703-AoW>w~?*;CS?A&VWxpFjLSJ~i_g0Xocs53G(3mPgUdpr7KbZd=KW-Sv>-}s z^cU;aGL_<KwJEA64I1d*-5#yzr?|S+3k{_66RoC$J?02zijhVIo;VxsNN@&L$kQ^$ z!8u3b3Vs+Oe#`mT2Esp#X@yST+Om{NOK132NfG39-N<QY;qmdf+~3A#0l$!h9myuO zxxKnIt`Kj6@;xNDNhR0M*9!=gh}bHrc!&51o-0+dg#s$y;`SF~c<d6P2R&>-zN=X^ zt;zu>{gU0buVnAXE?1rfpOjfT_C)HKtdb8WKq9|AIG`ni1^OpxU{g0<T{NIILC1CG zc+_bq9L+Gg^vgCLM!R-m;L*`?6?2iQ)?WI`VNdlL8VS_M8^M{lZF{BgIw2%(5Y!t( z&kv?3-r)wGtP(7~{n*b$RA;pu0|SgbD=%hZ=|{-fgHKFxUjY~Cp~1OwwrNFT77s2+ z3m%Y+0TlX+3<d0sn|CtXzY(KYeO$I7kv|tgRP$ncb^9dh=PwvBsa;bGassJxwg7XJ zbiM$XLC>85ID8hcM3WTe^WvQq0?%T_7NnXno!9k@#MkeL!W(E{h-UMQwIPXmD>g9V z&<q3Qui;zWoG}-ooZD}PZyvN4VK||`zUqI*fuo>=dGprO?*o#%FTQQkieuC_4aMLU z&Y(QLsHV;rNQ=BBf`|XYIQ0X5BfAIW7u>YQWkHR^L9^56vc3Qzau-l*W_qMEOZ`y% z=3ScSCz`ucFr;AQgzX8qbE@K1IGiD3((1^Rq~%{#5?b>6TLPK8v{4w*3FZLyhNPcB z*e3i5n`?4@U5MyQRIbl^#VE^E&SHY4yCKJxfop^7y_=_p5|lobf+d_3W6SIpM$<TT zM#>0m_cq3DLF24tx%4Q_AH1e>kaF}7uL@EY4#Gcw;xLx@(9`7iRCF^g>+kcRv7Z}e zo?igVOY+9FhKt~2mI0F|MY^Z;J7W*i6KFcrSsNLCWzKQmjI#3Z?Vr2xUCxJtIHd-y z`y7|ck`l6lNfm3Idb&T*20#eb^?WhJiSlpXFUC)_GG$pG3y?M$mEkbsA1#<{<odVt z6>=;)V@}A4QIzC|j_*l#^oyk|v5yl**)GWqWJg1_+6h@uT7HSxtT}B>uQ4^)8C`Jp z5N)eNx1Bi5%iKH$?drZKvsW{;?)3ycrXJsy4Htgmddor`(FeP7z$VW-zr;z$z{7mz zGzf_tl59Mm$n)#+1_L8ih}Q=%tV0}ak^8&4DE{zkqpF;h4clpNr(k{yf_s-R>$aP- zr9vSrFjB<XeE)gOR2wM+$^DI5dj(ADX;e_-pI8MZaJ(0^d6ax)C87SBiEP)ryrs>U z({uG8hbD$9%vx^IU>9PJ=db<gQfYYsaq#9YML-c+W=E}nClbLPg1J)HI~cPQy|Qg) z9dJ&TA#WPI5+CXS;muJ>#hi!^W$XUrH|O33D4~J`N_&IJrO2Sz^a_718n36yr9<kP z-1n}7;CHEsk6pP=k%?l_iUaXvi@9%Y;{9)SP`#p&pFa-{LUG{^emui2_myT{6D;55 zk8$uccoefxVOjt73qX&nrpVTq?t5AwD1N<i1u!pd?(Naq5iB&u_p>y`SHO5!2GTzz z2`x?=Er0n^C;!F*c%^RdEu5Xoi{k;6DDB3rwA$XLzyl5Xt_H8=i6pZ541!1V!R<q_ z;F8NTD`S3Xq;N94*kF<MBZLGuK0`KCR(Dcv9(U`iSoda%Jsk_&IOOqsIf)0`I<@t! ze$jd<F)avejHyHQ+r+kGIC&a+b6nqvh%c@v7^I@F5?R-6yn8~u3=Pi0C2#Z+ThH6I zfkl?jvzg*BE$H8(0W^0Zh_yz-EVTV+NyyphW?*1Eyy04re$Ll$gC5_zf5nskG)`B0 z0^pe1?6p0^Pq59n-@-IgVf;D?xw6?Rd)-D!x`EDUxolO*Iy?J=7=MHNofOZYSH)J# zt-@P<x6*Wf;Ai*I2wAC*yYtzPCbMjUAA97l9@+y|hicS_S$=w?FZXD4cdtn+Sh8U; zoa5z44MA9hDL|33rUraIfq8h!+z0D`haPT9pz@!E^L=0gfA{Wmky3N%m;#CLQ3p+Z z;8};Q@_h1~k&6KdIS3CjT{<BDvV@l(ovZJ;#QfzJHgWDh@$xIg{e)%E&)}`DeYy2x z1H5rod9>V0o<yCIGtYajw#qk7@KaJ2Dm&&1a;{BeCR(}rrv~<Jl(U5?o_?(EF^J4N zvDHNNsB0eW?GVB`p~``?J+`l>12Ivw2QC|3F(rL$!H8)kE#7o!;B0&q+qLVd+J=bO z&%z~(NlSVO_RAK$$~|<q_uN=KwZ4F>USxNkgc3!ra_(fP0JkwH-(pv8M!ngewf)SD zE8!lRQ&EnI@_cWK@Xx49Ex(?lZ8f=_@|GcM@4!R8-^ypIwMod;qg7Nqd$%XW_(#Db zgvSAYsD7vZxp17qQ9k4P<5#CgP-|N}eIB0D(TguXrIe_-qIs&$!FVFXx;<s(`pt8& zYBZ7J;X=Xo5+o9$%met~YC3)+fCOu+;zLR<hqF=!+8R;F2!8XqpnS!<*+666ftQlJ z@c2iYDu(wEh!CJAr8ih-y(j44q-x5_svu*u6A;D|%{Wbv4M;Rie-~t;_B>^ZFvoQ| zitr=qm5_pWwm`!wm+L(!5@(pE8utY(mJfWguBs)jitT1Jd3ZU0F`4!(+wt>BjVI{w zScbEq+)6SnR>caTSsb@b^=@CGCmGo8>82t-zZ_X%X91#CO~Q{rePEqA!^1A^=H0rn z0GyWB*XA%wd$$6No1sWGVz^pG%fY9pEU$p(qhzq$-Q<Li;Xveq$a6d%-=Z9G20-zW z?gyJP8iWw3Er0r#;g6JAq{?yB8$-;mv<g_OPV%uq=-r_>OBfENn3)JESOD-(qe4=g z;WfhUIG-b)i)WvI1hax=t;*3$0A><x=G9Ha+4raNmEDd~)ZhlqsTV`0D6+7f6w$-m zy&N?+&+@3`_NndvzK2Nu_N2UhzWk8QSvSQ?=L}>_2|L?P_p91z+UZ841N?5B<kruB z>R!JoMX^OUnh<dCa(#G0WO^&$fme9z9=ME#B;?QHsa?|bf!f<D_;7WACg$6A>+yHz zvu+792csOlt!sFi0Dl8hw7l16kHH(sjPt-_2cLA3PC?kML6dU9IspgmZ3fw^gb>%w ziD$Y>!!bXJnfN?$1|sN|5zv~X(VE%adiDjL@mj3M6<o+yDP6t_Z(UMU4uqTE^iTf+ z-L??-7Zr?nj^n5Q=rpPe`H+$f^_!-bBS>j<Lh3(0FUP|P#Ha6*LQGD?KP4r&Uv*p2 zQQr#)mb2e!_?T{}e~mC;2BW)aLX0$!^QO0V!wPT)V%gJkl5$C%laseGVIiwwL#$1W zt?0@1IxmaZFbSH1y@{l*l>{DR>XUvc>?$jFkK=IQco!`qQqqgJ*ClQ|73Mt;U@WID z3vtxRYfNscdVCqpnqT6+?Q2Ey{FAcL!ySO(>K`;(UD)2Y-Hb@5Zbh=B$S$Tdo^(!r zLZ451Mr3nZ6IN1g?HxqX)2GP;L(m{vUZ`{Va^q2~-vEj=08lJ&MbG=JC3?<DgiuJe z?OoO}KX+KsKoE8>Ip9~V=X#-KSBXEz&h!H6?C{=3^_7``X;=*G+gqQdDdKNKB;=Pn zTkwp40HlY6JU2ENOz%R%-|;l%*Ry$a8Y{1-#U+Z9+?n^P{sD!f-^lQdztZOdV#mG4 z$Dxeb3L3G4R+Iw53}gFag5y8Gek|{u@IRmOZJveqx~XXt-XoJ&J*utFq~e)C5cebZ zEA$({@0S3-sAvD{ML9v3Yp)Fo+f!ojkSuO99d1awsHYsu$$yH8Q7x$n#$4Xcwolfk z_?3IzFc${?;bt9)wJ)YKLGa!bDPs2>NMbu5c&&?ynqhkVk^kfN_0b9rfNt4n-v^2~ ztEKCLl%oFHd@k`o6Y8@}s(r?k?74bR1bvm%n(`X*DW|-5%O^@Y|AzxV6XzI&6E|mS z>^&^lc3TRoW9BaHu(mO|cuw{L0{2EkMbT}U2S{l`c@fO5kd2}khWZ8q!flbS+GnTn z3%6SBGh44qB(LKMz`u_D|5n2Y$AmJ#pS&ap>$330P{(ZGIfvCp#*b1|g0FDB=%Q)L zG{QHxQ|Gd*-8D#iF667FSJMQ6CO&G;{Bb$?5`cAWHYn+4R7b%DSroe23MC??)*9W| z-%jr&$d~n5q#Jco^p9EJ2mTw{wK$Gq0zysY=~bUl;l#y4b_C3B$Li5&CXu6WHeG!j z#x20(MI$pWrqUkp>e`k^-|mLwd^uN!j9p)7=41!PfTnXfU9V77o%5)pI@v#esO$oA zqYMKN6Fk!fLalt<MYW%|73(qqppJ6cepyh@yKkU8nl1ezO<bS3a+*h`VUiV!8Dwwd z-aRy;#--T~nM)`1y-pG(G3N5!HOJk)h0CxxG=ajn*An>#WNr*wNwO>VbfoyMsw-kA zVt~-k4zWv0PrLpoUcQiKJ(%Q?ToN@;(<f!+DI(}igNdjZTK!hAt*HB#f}YYIPGA7W z{|Hr_kVv{}URbQq@6(nhl8;`_S^henB{dKWg>s{$Z=5LTMM_5MNv~*P?`SRv$x+gg zHWBdg*Mu@aBZUm}*`5bu@0bV9-dWB}8Y(f-Vj279Ka2lf!-Uie!Nt0A*FYymYeUHE zfrp3`(i~`!x+2X5dn*WX{XPOu>Pr5Z2R?zj<z%TynuIjhFP(AP{tV69MxINV0;7cN z@e{Q4iXz)tU6*^V87MEVMKM7;iqMdxCQ7>Mr5@txVlUbI24q~GNF`bA9+u81Rw^b* zy<7$9SHQF;g3V#&Q@r-!A*%%FkUhC&T%#JEJhn@*o6t=F8-?DOU;m-lbMEMi8_<t# zuDl4m<Qz&!any8Jg!{S)(1WoH0cx@+9LARuQcr1Az4Q70QK@Gwi-y2_yBfWQK`k@y zO5kcQ6KXMMPV?yJ4_GCjYfA?2JI><n@*<$Y1;V1j8YjVZAZow2Eqw<<>~U-HSi6QK zN*>jw!)%<f<DUP2T!9x*h)%B4OGqTxwIrr|cCzcN&2`|_%kKEWF+e+OJ=FqEonIhP z)6KwqSXSO%DA^d!#L6CPXd@1O{}zMP^gth%a%bET)f^3Z=WQ^tZZ?*BNUXhCxvAV8 zcdTp^wdfPdINI#v@(Mzn-?qbr$B85w;D`C>M|fpDH$t!@`O^1nj~5kt58&_6t>FAu zx8fJG<HZopWnACY=}CV?3ZE3FM&B1c;Q@>1DtqRz^M8dh#Er=D2HDN?Q^pBGj<Itc z@w*W^n_quS0&&Fh(~&Fy>FHa`#fiHN9{!dr4)<q*AR7^fAD>LBKXH8pfvn+7xdOF7 zx(AUabRpHwNk4#Vv!Co>Cns?ky1l60&twyvc3aNoaQXGX^!07|tfgZA%39k}mBMM> zv^S*ej#nYENt6y@U8HY~dN;_c6~s{rkTP={aPWl&Y;I2$S6LFT<oGwLRzO>OXVf+Z z$b5Pnsiif^EYYjjhXXfSrmk{vp!O}Ywx0@D<S7PgY^;{xHfrOO*ycm42kpBwX>$=R zM>4Sr@_#UzP7lfP=j@I|X<@zloLn=oO`iLyM@Tr0`grw3{jo`4A!vCO&5U9Gi(%AM z-4t878$@1%V?Z-wle$VY_1yKI;=S0*q}S}3dGY=UW{Up1UrZv$03p#nM4t9pyO+h( zIJBLLveHRX$Xe9%B5}9r=)4nw3P_$`GHW|B<%kIIx^|VJ8-|zUi?Z3if07X^6>uxa zo`sh#q5G#)+sTD}lnqC^|I)?ZhO@7~>ZB^HvG05C`ug4_lA8A0;1-BQ;)NKO3ulQu z)C-NGMpHO>g-Ju@J~<U%cS?g}%m6`5C0zL-7_i-)0BC<`9gMxCV@pe-OxFe#<%I}P zGV%uB4cz~l*_(M{1iH9t|FW(T4!Q-eUs#Jc*w%ll9si7S9Pt)98Ukbk$#8MhM#C}h z-i@VHF6`H@0gsMBIfu*U7hDT968UI)+bGM*D?Wj`yHx7YHO~${A-YjFMK$XW&vdhV zA8Y{?Zp#=8Z)gt=yFBS*N?S*NqZ8!C`fWCf6^sBww}4;KU2x<TR|tynHU^bl7Q<h7 zf)61@>%vbT;!&o^!dnf`cie4_U0+hfzK{E<+gvRD#~1vM7b}c}8&KBs?)9H_JeC35 zN`t4swQowBglJ|7BWL8l8YH{BxUJkYg9oDue5~`FjPow>^u#TeVF;qV-!AFe*gNpM z;RK@cx!fHR2S%?J;L@}ukH1Df`LWx-+lbcOy^Qk5WhC-&q9+-t@~290{jo`0;iFcq z=3+|2e1~Bvsuq>7QfGq{y@Qznve%^aVQY^tMI>1}eNXu$%wfEo4{sUw`x58NiPMb} zDTkd?IUMIwsUWe$4P#4jd*~ip4p+$_Tw+c7-4hXnir_mGEsV1#tDr|9MMXH6OXzYk zOc*Bi2*l60f7p`qpNR#{Q*LJBN!LFwH&RyvU)WhMHHR*$DZv#p`Bzr03AE2Z^Faa6 z^EH052703@bvr+7mzM|EqOZRPDQ-06)MSfd3n;C9bd;nd37o)pP<dVq(W7<zv<(QT zy1+*8oGGmf4IZ}mKF5-C=79*B7;NbJq7>%={KlQxtQ7Nm)l(L(Q9yK7lHrVAC7~WE zA}9h*kErtDMzp0of5vAd354NmM?OF8x$gDf0O-5~WL^5N4sV5~R=EP*;^s5DdVXY2 z{lyR9lt~jQ0Yc>$msA_39vv@6>e~>-Cxu*O5@tRE3L7Pi_e*1A!tlMr(`(y=*qwy* z2EG5)tbjvNSOZkMR~pwxGle#?ELlf4{7*&Ebd20+K5KUsvM|i6WX4Ut{G8R8l@Grq zysF#>sN5Nvp9s6@`meb_I}aVvMSDpcfa5|HuC^_Ne0|9g4*oYrle(Ly7lnvD(L&(? z`t$xn>-%8w5Q#_9+KS1SDsjDTH6#4=*3^>qV;!8umh<il5B}1Fn3K~f06^YEQmfT; zCv&Is(CUWEtKXZDZP-4%8;lfJT4fa{TvjX+G7|DwDb7ca#f(kEG!qBjJwhmP46&+Q zNy%G_uWIz|U+<0CX{<%;-KoOOJk2^zl{iXU^~3l~1drM3ohoW@yi)h`%GUBZarqTM zoncND7=Xgj@N<nw48*WhDN;GS3TUNwa3iMM*c~Bf3!PG+O@|Q(dcitr3;26j4Nq%H z11sY4qt8&{XB#eDF(Puo`-Gk8A-#0osPRd2RahN*eFvb()7e1-Av~(}@ZZF!`D^1w zNXRKD&;EHaA0;Eb2s<}R3wXd3ocz|^;KsT|l^uHT9z%!jcr3kuF~4skBoaVh3MXx6 zKhM_Aua<CIpE9vB4;Qhqi{4o5I0J&|YevrCbTagUwINm*OXWg3WM(fD*@n^@XgOTw zIHedHWFh=&LBI>3Z(j*sK}66I!1dmVV|9KN(xLlQPrVpqV<5!whWLKqZ9dR*v3hg~ z*B<2d4cPuV+SgqmvJT!96gZd$o9r(`PASD+(FuD4+X0R7GRGRwt49H4W?QJ5$>-4a zAq`5SjkqG&wPRr({56Rh%?jG2blw99^5T`(fOskM{Kf-+xqAFtGf+)DpB#9u_t?0Y zfKN3b;c33U{O7m+H}9+m5O&gQa?wjRZ9IKz7_52tdGWr3?SolU7ICUSAx?iP#Q=gx z<;Q>zQuF1K>QW@5OYJrE6%)_^Q$KW^oA;%<w=u@|S#L<>XXY5*X~6>;?{LvkaX=RJ zbv9S3-6A2qH?V4>K`Qus(wpBa-!V${XgtMu=nlvR@CuyDVukU-CF}WpX0)a0%dNaF z*LeJ{2>ns8%sQ9x<mU{k*m&Fb0wNsWp_R<*{TU_x9WrhYk8F1=2zum=xW4lKQw-j; zG3WLszP_lfc!-HNF(vtV-_=tY#Th#7gB2@v^h4E=?B^%mfom%_FFw-uNXc6nya{J% z+9}KZ)~_RIgW1KAKekVis<?T8;hi-beHk)H`T#A8FrJ-MpQy+;9jb)}J~;?iJ$x#4 zz<e_fo@0z1FOzq!*_RW)(4NA<={USba1F%*?QkUGU!n7BVn+IHbdqJ{R@1ZXLG)39 z=l1Mllx<kC%x10oeCMZQQlP!B)Q|RL(EMhoZKo&e$4szGZoG%;P=18H1y8}fE_Imd zo(v`3OP&XIEAEqy!?Egr2y(+7C4l1%DLunecFtY%T7{9{b?6rN;PC_saV=Khx#iUY zok7|Qpk3ggRoW=@e6P69l;Aq7Jp)Lwvs{Cgr9IBi$T0xsH9G_Vme#dfEWa5bz_wrv zG~C7$=i2}YcD6Dj?8K`kE4?HS`kKL?OL5Rlz06c`aa8#YzVaS`!W)*uGb7dQXg%%t zglRctIr);L6>v>C9|1gywfZwqk97gHZnibKH>3@d#jVoA%jAMYrR-*9%(tI+|MWJ} zHd!E8Sh#4B=vXIK^`v10@|1wESq$Jojb*n1YC#UXRu4K#fQ$s-*Rny=*VaUTP8wX2 zc<b`)$*c=&v(d^5Jot=OaV6DrM0Q$`u#J;R7|F!E|7}h_DIvu3nSzESUY;(W>iHy# zl5Pqt148mK?1ANQ(E!~fH6UDmvpPld$ItaIM8rRiSZ4x3y@&UCt!Ldn)dDHXuW#Ht zXRtDQ;2q&j@x9UDmOX8402pj3U6hI7U!ErHd}>fm0tQ%az0O_f7xsP0Vd0edB4#@G zDu50YjnPYSTv6r}*Vw)Tm_PkE@tz&<=`Ou`Jt!)hf6*I9qd~PAt8TuxU7JgL0)%<^ zj+{LNd?lOgTPF>fg>@~Kzx@rMaw3NS2c<4w%GZ^2Ls~H1zL=p2fqe#`+vb!UtpYRl zr!hDM2MN1zHJeaPN-|#WX9LAIDi!Tx=bimmoYm9BRJrm|7_zs$m~m4RYq?;oc7%-C ziHnD9fiwz4m-2-4W7PEm4^#CWn5Tx0Zo;q*tTD1X^Sdf$XAf=Mi(87T?zyTC--!vq zO~iFUYRJ%Qt(2WQWY4(FT*OpRV>?mg=UFKDSW{|nGwoT_2yd;x{vBwHwDw7VO=;;W zj93msoWBN?{_zniyaF+Ad3w<zw1FIAttY~dd^h+8u;)U)`q*G(vMTmAcJHCnaa{ZJ zcQDoTM2_!snPdJ1VM(xtp&^lYn4Jss)XrUk%0GWBw4p}~^OYMtCxU=D#GpqslYE4V z+S)TUH)!Bo)(4Js2nEBiVrD$!tVSj<vB(6W<KRM!X_cnUp5TWbgJ1Q|ESt!FQAoUw z?MzTuU-7D7+SWNsyn<5<;68Zv9nkEUm<g(Qt9YS3$O}a#UexZ0ye(K)ON&?3ALVM< zt;cVCasti?TcD?-%{^)Z2{t9&_fLiSone-zo=2-vA?%Vsc$wzWpp-jG*K~TcMYUkR zmUJ^TRMn$p@yOLfaFO`@(I;{);n!if(_i23w~4)&z7g79L4xY53BnWaa)-Pj;}6;i z$%rXs3fXH?A5D(7Cvl1dAI~kU{T3yCwAj=S^6v4zGFz}HSB#0*h(LWQEEYokxm&G> zoJ9R!Kf}NEHDOV#g!vyIJ@}qc+{q^?m@=)g`;-8${WKU|-&qMVI9&kcSLX`>vZG@; zMU|)FSExGj3K!{41ndMk8GqzWade?lSF&a8Q<h~27-cZ*nE7-|`^J{e|KJ0_>*EC0 zR)W?~r0pu%l^acP+Q8LEt#a<4B7yvwdH6S0-fb8=qunvT+^W%JI=te_k%AtvVUj9p z_r!DL+7+_!7%56fMoNY9ZoiKAW~Z6es@sriQ>yQ->}`Rd9(5r9Jq*+2^6oyDRf*QT zW?KP<yor(oo7nsr8Hae*m^kksaK3qLj`qKMO|W&7@=7!`IF5&swlT#?-6m0J`lO)L zO+OYNm)tus@L*e3)2yUL*B}MPf!%y2aF(VmpS8a1WMM9kLcfuZZRGGlxdbJS4=op$ z<NEi`EjjnR{GA-Qs@yUA$LB6QCxA!xMX<Tvr=W?8y7TC!5H+XVD>P&7Dfphq4BTP{ znR!zMTY+?Tgiu5SDtK`B?fBI)rTer|i5>0)xz(cs*XJjAUzQMrO)h2j+q@(ov}xA+ z`l+^j{{8p@uw+N2=Uz=@duWiPStdeBrx4(Z*C&Cq2?f~h6MG3e{F1WYN5v;{phaOx zThMAxXgL1<u1dVp>euITvnpQ()jB`{-YLSJQyn-15lggqzlW$SSVXU?cfcf#1YXE{ zI#08V0i$lD<pW4(_)k2Y-eem(2hpK7Tf^pkEOWu{kQRNPD(U+1<L<VA)NhNTzQL>s zRD=#gLx%CRFPvg<twy;5cFBp8Gq_e(o4)r{Cf27r+{L&ER{vBFq;T?32uyC)AszGm z-4A047?56>I@-ofp}+hUU-;8FS$K!PP+i7l?(;wOA2L7*?Z0;GC0n>9k%E7uT_h0i z<C~TuMXpaByF<A%R586DvIfs>3>n_?-jtngoj>9P0!NUOY)E$Cx$6q12cM{ptqXrf z^L}qKKTw5DTR)Is=EZ~f`>zG=F9T{^D?oR}I~JVR6Y=-(UO5Rl@8W@H&tpD_6*On) z$@TZwM)%_b>h{u15(}j-Y~LyMf1NI#B6ai2#pe&#lcZJ~bjf&HQyF2#1`Rk26ZDds zgB173M|&dYO57`X_~B)M@@dt5d=q$@kskQuqmkpaPyVgQwAGtj7h(khcYBHxtZ0Hl zZItDLZhK{iW`wM5s5R!TSWsO!855Yaa<yHsu;CI?+*<B(XXeB*!)epG7E+Trdf|~g z!4F-zVq`s>k*sZpO3XGe$*pt2TQfVjwB-WnK)Rm}l^6UsOzKB-pZ#zE%WVG%SB0^} z;QJ8HVJeD-F9{_-nqp11@Q(YmXX6!j2|K|tWYx;O3;bhj%Ko0b*d`_~4g?9qb?grG zhcbJfU{G3Z%BAlOo+sG8tP6%)6GP8{rb#dY1~A@p-)y~KGf(^a5D|UsJL%#EV00v& z9K!2xHhlvrW$>mRrg9t^e0-My>LLk<j;J3UKnCA`{#+XjNPKM1e*J_3*^tF2#t>>1 zpcnn!@oU9N%N>kc3cJiqUoYY*syguF+g!b2l<47r-QAY`8#6%j<1!x|)^>7f3^2;M z$$r4%%Sw4$n1k23fYpX+TpZ}0!a6BDo-am6P%sLWe8ao!!q8E<q_kYwluV1a{FkCO zg{V#>@WeWP05}RlUbQ8he(qyJ*sW_AtlAi*-hJOl%6SRvov}Zhs8M@Tqb<%n9SWBs zZX6&0*x5VEdZ!FABr*lUed}{Q5CoQXGW?&C5JtlMdha*xis&(p{IeUE1M7M^IG(+* z3V$H-*|^!ehwPc}5VnCnYu&HuR(-CuNbs$#DqZVAM;~<N?==~Zkm5VP&0fndjM;x5 z1E?-SxW4G{e2nJwFc%n&Z%*?!y3-ar5@Mgj!x^V9sGjavVddss<~*osM(gMBtl7h1 z#WB6)f|%Uib%IdIlE%Ho$!tbO*q)5<k{ANafwP4}=E1R}p9X&PlKD6QQWsNW(gpSI znGT*IQyPA_oK^E;2D){w(ld<*K>Qmbe($rItyL28EeFHWR3-EZ>4@^>DipnOZaRxj z;<o~|e0pbYQ&kgOl{(ugoB29U@9&jO&Q5HD*duI@aFDWGi#M#oZ9EkyIJA;$G+gOv z#g<CN`_9S-9&)uD)ZB|BA&;;E8q<GT5s(R2frO|N&@WlmY*^lckc_ky6tEdR>cLyi z$V+p*b(FByI{Okxyw`CCNFIp>*1%V-+wk>e`O3?yApn&v$sy1>TE7zHp+<*qLYawu zfo9V)?VZD(eQ%<+RJ5<YA81C>`pynVLmufJz*GW#XF#(?#P$o1bpu6?1>Y6WVc@q~ zh6&y^Xj;D_!SKNpQ`oK^O-&(q@J8qb9!vM3yi$laR=v-=RO)rAuD!ioQL{OGag-X* zY|_-{3iaMk*n01S?m+{^1zqZTcM>@skqN5>zzK;*^Ww@W@aDmT(vBPN5DaS-uKz}O z4b<^P*5*;Lu5$0Out8(~FC(UFFRP<|EcJ5U%|+PH?tX3pF)I*w;QsdPn@~m#3h*|$ zA4!@lwsYWGmV8z(4N<r=sjPJW44ab{zD(c~FW*k2!W@J-egM3ytaz;xGH(CZepQJ6 z5vZH)qP@aw5B@T1{^b|dV|?wq_WA0}lK_<C_J3|6B72AMav3@T@Sq4!F_BXJDUEsZ z!Hb`~<%_27q%;G?gBu`O{~^RSCn4X?v9xj=&VEQ6QTFnsOQn(jt-p6SLK?_=7#?N; z0gmNY#l5eiJF-NPI8n-hbfFZ>#`y{Oc<hO{cUh*RK?*`;;F92iJ+OWp8bfV@cdZd| zVUjA|5B=k%*jrFyh&m229;MWiLiGp?pNjuPrq!;M*}+69Txe^kFCGr-R-<+P_QcGG z6Jzq8^R`k<oLrb;knpESmMR|mFgUkdgq16U>h#BK^Tym7yNPvI`WM|1Qe!fs(}Jqk zBo2!;Z4feMs5Lr2%v*Ro1CBw=`irLDgc)i8!>77YE%^{F5K~=5V4KO;mCvIfAmsA+ zkBj`)fmjCs_BLtzP?fzg4Bm_R&F3lOz*6q>_XB5i@al8|1kkRP^p$-RyzE1z7DPpd zi75aM$vE34{jf%ZlTy1Zlh@yYg+vg3tyQ5+rGA}-XzCr1j1p7Q`Zr#wA<&-D>6J1I zMG{obtd#^-POQP!zzP@2t{5m3w|YQgfOgD>@5%!r-_`bWt^pJqUJjzr$}n~(IPB&f zDh-Nl#(9y&MU4d@8pzr^RC|g8Bx=qY)5VpzLt~dg2(g_qz_80+tbhi<z+6;PMH>rd ze0`nJ^}TBEZtY(vvYFD@(dZm0ypc1bdvv|)RIB>zuJW$}PT9ie!pJd>nMq)RqsN<{ zIW&m-%`BXs`R)<`iyUQ!0OoAuZg6_M$k<ZPI-bifG3Zg!Kvp&H=+O9hJY4ko48%fR z0DVYr{UPjWay7V?N7=g2JDs9{s7IV1;Ns_>;v$;>7=!@-i+c;<c!?keoq0LVyZ({z zqX&P(EB<i$gYlhUG+rJcJ-$13twR6{y?C+$R~@)no1F8Kpy)c5upYI;MT<^l^abvi zjDtdTH-%TxjwrFJX73p=Q4_^+`=|p~%<7vz%!OcFD72&lIUp%KQTNG5m>H}7ZYUp{ zAx|w=^B}*DIwn-6l}l>mvXW5Xt7ETu=%ZgL(>SRllA-Ln^W2o6(1BrPu%(w&h2Dpp z$Nogrkn6!J@Ivv}Y^ZIxB#Nh0DfHKbt&piaabqg5mac_v4iuof;H^_}xs8D+F&@<6 zHNBp=rzP+ptdGjTm^<Bob3~#er?bx|a<_Imf;S&0ejAG#%R~fjykQRvqiMs*LHu!a zGkds)N$mr_u6U`DAtGsl$NFxduq!@T;pK!*rA6n8jdfH|!^6D2`01pIgVLFJ)8Q;A zior&~NgpSKc<f?|C5@az5naCW$7mtJffq=-J((O=yq8bxL{G6Gh)53|9x&pMhiakV z^hZ;ccijOo0pCxL92p_yx8BAp$HF)nuCzS(Y0yI^h*;n2AOnjefi6?8;QcpSY{*xy z3fEUPS9!0&c;p2zkSq0y;Gr(WT#lk^HsaUL8MKY3E5w^NPJkm?2R;t(-G%`cqy3Yi z>aV@aSdyjoNIRm~l_Svc2+$R9k_am-W}vS5fFo)lOt5s0C+TwP%a<?rf}VOlV?bYA ze6x6r^r9?1G;^_xJ8K+Yx*uM9jkkkJC;pzWLm3pS$zOUOYkaY-GcSi$NH06p<9^|b z@Htp~+gWCJhkOtDiHA=Du?A6(yvucTpVHrI-@lQLLbfnG-lM|GQV?++cn6<6B`B&y zN1*pn+uXx{WC3`El8ufk`EHz_CL!x-#rs;T{&e)(zchX}{XyMy|3`lQMR_y5X34)D zeWX2qVGb0djbJ<!=#hCxpa%TVS2W(g^{y#TPii%M3Qu{G>$<XHoPJ;5gfASop*ABn z${7TX-xDArp;1N&7g%Bi#IQ`T#uMoqTopMymu;|{y9(RtewbRn*{4;qd@(C+fj3%6 z4>QiVU_H}Ks}Z%u@K(FQyDfo)*QAOW2HlWU<Iy(-?cL*R_PSGE?b%kdpZk`e38mnw zV7Bbtd3da0BY3GIVxK<3T5f|<kC}7v(%pW({X}LP=?`7N?QdqN4CXyPH{QSlLp4Gh z(OFyFbZhB0_l$c9K-sy*NypFd&q3O0ocseA(0jE}c&(+0fOB*9qg#HnzORpgRJXuj z2?m<s#kW7B=R<iHn53<MxJzW#Li->$&BoM}nHCIYo?~ic+V_%A0qLQm!3fAYZ?)be z8t^T7HEcXhn9!$D`UXJ0PN2K!DpZT;1XlB#4TKQKW>56hNU&T_HP7Fa{QQG4AQO!5 z5;=sbo_OBA3y{J9o%RJF%j>+R$(_kC6)+CLx5c)3_og1+eA7T!RLutc<JI`nIQ4HS zhEol>=UfNg2dz*Yy`H_VQdnFAY<zFm0NGFxc0YJmjiy66J41KOY~x=tdLXVm9!;QA zD2eIj{9@+$pay!&xpIN-Z`CR6h#&c73QUxlv~kbqjsd-_Ejh>x;~n-u@{YR#3hhR^ zuD;=SnZ_@B7$<N_>?^po6~t$Fi(eow1absS&!A%(cltKZ6^|YQm5~&8PiY_Y^h#Py zT`nk5SGcq;%!;=9#toS(@H(dK$*iPe_~dV4Yt2>~VQV{8IGoG*RbH7HZJ7_@wdSZ* zsw<N0Dx9WvDuHg72M!yn>^$!<eoUv?wSs3AtBZ$Kw1^_GS2m17d2dZcR-t%G<KU|O z7_cIyzx1Hp3W0&Q&8#$me~m2ITHO`ak$VM0e;<C?7oF1Ve&p)``xk}i)JP8Kr_>+0 z>63?j;?vGP7YR+@;<e$G6EExyhC;xwKB;|{>$^}VAse1aPjQ5gOJ02IpN4IuDUxdf zvwD|EX>Qu}>Pad}N)CYcryW>=VRdnOt-S2ciB|`ORr7Uv?CWQS1qkQC1QqMoA7X?( zLJxp>@+kY}^#7cnfB(Xbkc+@BK?!n10-Drr$d9u`GE;K^-B6BBV`J9(@Ysnsf;Sil zZybzn?YLB|9lrrWae&)02^r*OBP>0FW&g^P;;Rh{DKS1;3G|;8V}PN3J(qVYwEFIK zP=XuBS8j-v<|@0b@#E+Y*9VucRw}!0UeHX=-|4BjBfhYaR-!QuLAibCvwgBmgedX) z&I%&=S~s4RHtdLSqg`p@r7V3Ps_hNmgd?2Mn+MVTqB!HqroD|CQ<N{eI_{y=)W_TW z{qt$4YTnQ>vaZfWzN}>Aho^x1-aRs2B)X(^w9#QtOTJ3LYJ(_Ap*fJ*T-gfmYvP*< z&krpvRkKJz2^-YD{lvl@l#TIua54x;r|D8U{uD#%o-7q*O1dT*9y#>X@7V|ge^8@C z8ifcFatYQbIsoJh|4{L{_X$rsEp>rj!K5zLu051+>3NO^rLJV7gFk4Hw_4m-c|UMo z;QX(5?;ordp@0#D&?8j^Xq9xdzJd%WLI{21ou437k6f&>!4BUVY*}Anbiv=j{(s#; zQ^Ii1Lb~50_T<TYs_A2J|7FaRAS8^Zz~^Es-TTUfpRFyZpgX_(zRw4oDZpTJW;GAt z72yOsjm|4K)mQFJX0O}tydP+r`bLIB(v|^-Ypc^v477J+Liarv=gylYT{tb3^eT+A zf+Ps7o>*(plLdAlf-ACQ=yRBgIOu=u>h5J8J9-*N!Z#iK_Uf#wwP^5#${$d!QHdpW z&gsk80rRA!H~w;iG5mmsp6Hb+je%EV3?pJ%2%=-El!J3w+?dHOO(DJ8TABKJ16Ou{ z2dskiF@h~9_UpLj`&?^5&O<mU_8I(Epu>(-u){OlgeI-F83{QN$UUM-4EcxU06C=5 zPD1{%z}-g@xdEaTELK1%eQdBHdMcL;P~UAJx!WA9ElyT?>6xxxW9{w(zM<&kJO9UH z+D<-9MGRh0TkBWvCfM-CWt%^Y%fMagRO$cU#*o9X_H9l&VPrPjT-KXuWU##AWB`x6 zGRNV(;E@>o5^cJq;zv5aMCZYGy~&CJvly)peLSt+^|C3i!lA%di8Z}mm>nPEE)6}K z=!1HX)FS*hmSAbB{uV?{GOKU;Y}I<%I1e3Ziwxf@20wJJ!aOTSyym#7;3RGrCT_s# zXksBQEok;s<uz*gRTOcMX|<F4PDifvL83FrO`w87c!yXTr-)Mg<43cjtyJocLhry~ z7HucXhOP-+D_M%(hZ#1$0Adwsol;K`Pbp=a8RSV^tWR-Y1;a>d&{bu=jz6KEi;&2# zhV_j=TG3Q+x>t%15wgYhutH<F{mex#FTSk=s7mB|{sYNdjtIaG`5t$GAfYY>UGZx_ zs$NmieWiI!^M5~54#ZZWn61bS5>~6R{{Huz_a*Twx-P~4O<+|hN6d25;o%t2y%cEV zVQWTWljhyMi}}23WZ}~s#;tNb4uc(!a=Er|)(nuLc4{`4MC2`x(xl<4mW|6BqOCi1 zpdXRRl0Y2_oLQ1E;6hXKry>lu`6@K);zxOOW;?rh6jf*}Hz&ke?XKLID9*}v7`{1Y zMQ^b7=<WHFYDJbF{#r%3c-jjH-pyFno6hOO&Kv5ucGkk!6zT`4NjCLFzC#upKU|vX z=6T25t!`%;oA?+>>FhT=cx_T2)Te@-2Sg5u4|wxj=mEsb087CJa^qTP=#RP@Q+z>^ z!<%RS4Q${~I_xeu>3DZWCs<3slOJ?2`+A`VBs)o+0MHqV&uzMy_lX#<{+%|)$B~5T zIQ?&G>>mbAYkvHO*Qf{I8{sMi^WcfniI&V-v^H*Jzp!Nya%<<ehG!hQqV>TGASXcR zzvKky$0PlSIvd!WEZkPKO^}7TUlqg!2hs&g!ijgPcTe1QUh?^;X%{HF;bfTE3X5~y z17{htAdpoLaIS?yHf}>7&gIQ@*&B%OWk{t|*ty)@5T>;kt`CD>I<gYts*Z_`qb+GU z@0gg^Ymw#q_R))p^TuP*H_a?-$lY0zSz>;mIxJoxHO)9DmBz@JW(TEI1lzGaWNBM# zh?SVy!t~>7s6A#)`@M%lW?U@f`6!WAUo6z{^t>JIs@z5y5RZ)8CL*x+y3~MLhIE_} zdb$3dn`uN0;@;fwP1L&nAEm-V66D*wICTT|h>sY&rF{SdfPC0Scv`n!3k66#^!HeN z6aYfQEa^acG|LpQX(5-|0i$SG96b(vVXO@rwg4QW#JfAQ87=?*zW(J}aKyHM01FfG z&Dy70SJtD0Z<Z6fjl@6G21inFP9JTh$#+S7G&gSC2Z>~)dij5UbDl7Tfnc&<cBx)9 z`YA~#E@@i>#X>euxV%7cCI)H~Fg0=Q0-|mrr3=KmX&p35F_Ybf+w7=S;RF>2cvRN* z8flw$ic5q?iiHQVhs?fnA|!rxSRG$a$!%CkbyY!+t6LP{aA6-@zoiY`uf0JOEb2+5 zr~8DQmqp0Ph>7<oG(o<di&JZ{KPIrkv^ATGZJUiql6Nr6jbAJXnKmHzbL0~?jJBIA z4SE>aXO3Fqk0;yXL+c_^?FAmA2jQ*em*ix$>L!XbQ+gYM+{&rh5BA#GFFN)X{po!M z7eeCan~Kr*__RmRxUhlwg$GPvU+rCP{cV2vV|4!qDQqRs-XR98eU~?Y1b+q~7rIAc z|LxF&_abzF@o#?^GM)eYJAx%g>3-ZyYkX3!vw=Na(;{F#z@XlH=%EP`$x};7=g`H) zIkH((JQ~#FY)e~k6?JHO(l7c-BX}hprwD}&Z$4a7_X5#({%Emew0(+%&!&?&dvf)V zeLpF;R$TzprnTGg%k9pA`81aIm)X=m<@WCByqNBseSx;`v(m-^m{b)rX0MkHbI(<@ z@6j}CMOR~@kWhA-TPSCPlll9(EPK_HJma=1bckv*lz%**%?vgwQVQ@7*vCU{zNxNx z-RZg6Oo~W%drR3bp`P#VBDMT+|6~T<-UelOEL?Ry(Cr)WAW;ZtCR6K5)LzF2GO37H zxcrU9{-eS99RtjMKpaiW&4B=U#MM14mXRNCSXPvD0mA)UW)9yQylCofwB^g167Q}1 zgqLZu|1;GHTsj#MNP_rlt&N$QVh>~?L0GQy&P!8bWUCAb1)bstI%Vv$6g{~a-56zW z@7IsJ9FryOIRs%F!j6`K7z|Z`(BL5$`)U@|;!`B-?VcuBDa8+1NjtFKj0&elsc$$* zP4tzzt(Zxt4v<=Vo%FjXI1|$RG;$wUdmDy^3M~+PIuxq5r-5WSJlI}^K9=K(iF^B7 zVA#2!Ky39SS#LJmOuGp^A!?vHU8Tis*B^iyn>~)=K__Uk$1Cw+s{Z}VuuB}S5p3!^ za7%yC;Vy&{i2if5G#94xB<#G5l{R}j00saly&Sobdfw}ik23#q{r~e9PU6JA$7=8V zzFh{+uc0Oha8{=ZA5(n&y+GIHDLyjs_yyicBGHTg`Cp!g=ttuVbP3za&`f`p(2|Yf z;^1NOt8TNZT-QL~@nR8Ht6+Yy)mvh!mVeLXD^<RaMq-=-zR3G%DK5v;01ZI*bTFp0 zme283v)AEdAU2HK+hL~|A(h*2FIIVE#q#+>isuAdNzY2_;`rMo<r}R|1N(Pw(-H~= z&Jd=i9e`*)Sd6wNYIb#T@P=!ujT^gtu@s39`2%{_i4h{q*ud&e0<{gDiju`8B^R&k z-aWb|-1L{F0adwpsRw8&`Z>{m__T%}dpZ5V=#6>PgTS4kUv69PE`AOVy#)e6Izh;n zjScJ6|8|=H!2seRKV@)E2cFl>L5+mL54I|F_gW+Vj25KmRtfw5USj!i_&Aim)DXaU zGZDXrL{g0N{eK({R|NTMG~D0Ht9$=@5arT%-fw%x;S)gCj7&{G(#hBTM-JH^&*UFJ zq7QMQ9tflt5cE*v!}==Z@FHLwu$&SF9UoY^v@MR|gLvPoo}E;KZl<*L!=UBY|3}<g zhef@v|GzNQfW*+v3`j^wcMhNef}$YZt#nAq&?&97B8Vc0w1kv&gMiWq(jXlYL!W2X z-s`*1_w4=K*ZJdI*ZF68t%Y8=hR^eP?)!be@7MbhkcifY#Rvbbu^keH_VXhr6rN?n z81bOJ@5h{QdfPbROqTp$cVaYIgr9l2>^&EYobPmZ*>wS<%OwI+7R}QaZ_bB!vt_<? zL;!XKYwE#5SsDI0YbceOTy-=T%U4uE8q3#%MD7448b><i-%1}A^wb%4ljh<S(Jx9- z+WRD$uaz|s<xeP1|L~A3LGIS=a|b+9+Y?nu;Oy<%rOGZxS*l;p$wu?=!I}?5PkK*Y zyg?hLp;qd;%Yx|^;UNSx(X%}980cBgkT!r!4ji`(f8xi8oc=hF-G4T4z(oM+>D2Qz zaYq+l@>VVNo78n)TMQVn=|Cw#LF>O6RY98{9D%^pZg>=XfWFWs=saD6NtI!jNTGti z^#MXe*k9vqo=q^7yrw}8@dJa?NSr~_aZs9I6snZ4(hu8%fJmX>EE4zsc(%c7Bcz!v zhK~Xe($E#ZQA&=(R@W6?HLN$-X}BxYj>JBRZHgx`>0B}!7Kwa>Y);2zTUno1(=4B3 z)ids_<x5B?v3#f8_+`PWRPrG4Tv*q5jT>M3M^Y@yJ3XeJA)9-<f6o1SsJV{&=o%Lu zvj9YFrYJu4JNZh>?EcXqi=@*sn=WJ7XHTQmP{G{5JLG~=G9-|zh6Q|AjuetR>aL>c zskA+yi^=}^Q1mVO0QM|8&J1WqG;-83-CWOh^<P{6?jw_{W9xLXG`dNHm|lnAw*2im zFysNX+~b1m&FL)+8w)Itox7(4tID+0=c<3}GX5o>fj7omVh8|TUBjR)^qs0kdmoQj zYhsoG!Pev&P1viKcvhWT1Q?Vi22Q2UU-RES-UuYvj^{?EQ~gXU=O%b9>rf@Bkvr`` zMAn_nxt5((yI(o~!XXYm*+<HZUIJifV<&1dL6wqBr^!{1rRbQ(u^iwp0R5eVc`O{Y zBJH~uv|weXVW?cv2K2MQi6=!>i;+TM#;D@kM`}5&3YBFM6TO^f`toCJqw04AeyoV* z6VP$YUt>Q6s}*f+S>-`5Tvnpfx)L_q^J%kLelQs=DA&S$+PSg-_m8y^yofJHc0);S zW&f$NEv9`VD}QR3R2DogUd@jwme2YP&Pl}-PPgk_+O96LtH;mBR;m9{;x>nb23>>E zWDeQ~6eTO+nm%)*m;@LD9IoX5nQ{Gl_4?O)ghVljQTJ!H6Jw2U3j6t8pl9gImNE%j zs{-8jCPX_5IgkBC_F#La-f=JZXoBK+6@u$uxBVZU<OEE6e%hhBXnDpXzW=G`JEtat z78#jA7IE&m+Zw{Eh{+{R&0P0;5D^s>0b}QWO2T!Sy$|XF{?@Uh`%;a`f4&(;ktLX( z!89+IRD|3EM0qFLx>8xR%;e4j<k|<1*=2m%yBGVa73BsPLiH0-grX~uSi1hvM`94O z*A^brH=1onu^^1rY{4x|@<+bsnfYjRP;R~eRRhze>>k`eK8+02(v_(wlJ@bs7Y>65 zKdelCBin~A>E1^&ClAJ4RL1OMULA_xz(0<Ey{5R+B*_D|qF!0ViH+ZVy_aB*%i@o2 z+5PtA>KZVqDgK@+?k)Srhl<1lkl7qaVv*&)U0?sJV*Be~M4^ChEeaK9{P*UBAq=!K z{1|{Hp)*G3IGE^uy&~%6{(*JBffe1`kw*)szjayV{+Ygzd(h}~f=5pV&MRTm=pkdh z`{blfG*1t;|8+UdG$2tVlCDqJL6M9_dQ;h>Qz}P!xR|VasDtd@UKRfGN8bC73d+ff z2?Ih^8J{HXIbL_lED(P$bgiHA{JV|FZel@;UQAnin!vMzM60eeY!;8bWtH;WYi8w9 zyxG9?+mf%i&nvS6bN4wRAT~RVJ;9<TxIi(thk&_SJKal{IN)Irj*>r~l^@Wf|0fTX z)kXZEhYKEQcSn}G@s0oK?kk64=Er&9GX>^?*-HRQp3x5)D*p8U{YQ%Rh0JSx<jK`z zS$=V#ldHU1dKNY9uxy!BaW7QmvSz=gr$SfWmx*S-rCeE0eBI-!;}oqFuiywu+oezz z7NIhWc$51lb$g*KVQ+}|+Ewx*;2jpk*(`xmNvOUE(~Y>cTMIpRJQh~Zk`g9u4|kxl zUy?(gD>$WhJkcQLnAy12yizvGSr*=v`5Lw_5Ha>#!wMym*Fvj*@=P>-feLOSj~ojj zaR-o2^e$pyBZe(w;Vr>;2a?~antqmY=$uHp#ZZ5tJ8%=gW)#rGQ0d(09KJCx)NC}t z1J}n4%r?A9_s;W=^E61`X9bpYDjA3E$}s@}gXLPnUne|;4P1YBUwr;=+jD<ErVq?O zNAkd|z3AUj3+Xbr(%#!B<bfc6bwLK#{>LZ1Yn&L+h{$64xyy3Sdli0hTr!iTy9avC z-qzIawclA?jB0=OKY_`1Mhj#tco@oFzGzb}K^w-5f&9e}DrT8}CFtEh>9vD5?w)BG zKif*6!&C@uDtZn85sfI7n0It0gzsO6?Q$cQvZWZiCE^+#JM8%7tu`mvtr+AH*aZ5! ztdl~WX3kv99f}|)SQ%}>FN1zb9#f72I6&s;(yH&nLtXsYT~DHw$+%gpsCfZN?FYlY z)aBdiayOh-=5Jg0xHQK{MlKN&ov{}B2wK)h%781-s@IBxX-APAm~(CUvFP#ti*r3f z3C{HhrC_1J11M-XZUS~6M>}pQhAc1ez~R^uyfQyNZ^rmbcLBZmdJ$N5z?fZ2xQncg zz`BnJCi?~Bupqq`^Y`0TR1N}AF#3QJjw6B4h;jnrk6#k+&3A9HdObROvTgZIdVp1q zpujG+F`7Jm(Tv1s^VUQU+^bzr_9@`J!*^NFo8PCIFmd`76PW!rFO85#sXmLHU-c+f zK3O&lb?ne1MycM>=oIaUYpdnLOZU^96^M_kP*shwEeap5Flc7=1)qCZbPLsuUDku- zU4g)b_q?+Q(Z!}hx!27;r<uC(jXif+n)uC$a~|bx_B+}-(y64>l3)wZZ_DIpUrj&( z{g|5ZQVY8^(L$3fQz+?O){4qb<As;c#i5=9U;k|=EBJgn^;-XG{*kvapEg_ie`o^! zemwu>eG$b925YY9d9uLtcUQn2Ovo@^orxh)V%iKf+Sh<FDH_Wl#*+!k>KvEZ#;S|~ z?MaZbNL>Q<J%>Pw8iwOGI6QHWeiI0Kr0nt+vsW)dzKcEuKBkD{Uw#79z|?S$@-0ni zcEITq$<<7cRv@t^je+;`t46b`bgEnIQnP_q7Z_g8JTTNjiw&!Yz+A}!tUMC}7MzV@ z>B!s*6&6A;)_&>(e$Fp3m^V#v@ZBA_5ApxpD8hK7^g+eWu=!q!E&!9e3jEOb)qR1N zPTSJgLw~%%5T}U|r6~b?ovz?Z1BGROZVrH*0?K&Fg{U&HgB1bjbv3^>&_8D{X)xw! zSMVLifnxH?p+xQKCfH8=*#=xeCOZ@2e}8^M>Cj!5-TQB(FZfQGXn)2|bf-l8{)2Mp zTyiVq%6|0@vR^u%_9Gt}l<By{);Y1DB7U$SqFeH1!Qmg6f(5JVX1`ZXqcyXCc0PF( z6DcRZ_JJ|7hgL3^ZUTcT!1@0JQ&8ahqaGxZm<Dd8FvK`SvxOCCHxYx~nTP1}KZC86 z1!f)5Ge<dA`S&dfKBPwbuQKe3oq&DMwl26o9hl`X))jreiw3}lRuvFeD}S++w0lCE zeLLVaNVQ-FFm<n(#WCT+?^ip4vthvT^kD*I0>qGU(vUbAej$1zEkLacf;TS6P1_Ln zqp!jAkCS_nS~033+tnA<$8an6^=7cK^vKcBN?wE}3w1D008Dc7WM-&KU;PH14UDi( zSMLF$J#5tF*)5tj>;2D2K`@ja5!ih&K?|Oy%RaIEE6?I-#kWNq8hgi2PsaKU0FLO_ zwQT=WgY?tUH1dRaH>W;!W22OoTh;$4&ElSea*%=Y-r3*n`@c@kzt@58xC~&2aQI^r z*uNbrHEVJOn1&VB6}mt$a<Bj+2i2W|K|tRu0~u2h*;nVQ+=}PGcjw@R2mQ;ThNJ_D zKTLiGF!~1g6_5m^JjE)V`c4w!G(mQOmL$+^wSP4OSL#nR_WCY*!|Y0$LlOf~wg7vI z*D(514VeFLlo45I^#@B{91LskDRM6Z-WNXyl6Ljs?u^1(Zc;0l3f|2KFRq^AnGE)| zg7u7`1Wx>OByANrz+e$LDpIcibLbo3(SZ>k8zx0&6A1Hb9+`SRzkqEp91;dP<bs~o zfzk_VmncXWaA(U>BOVlK!(Ykzx?`M$ZNR#jPDHqF6~lj9h6?hKY9v{I+}q@z;zn>d z<zGtg!gg1exSaU^#t`KFZw$e51PIP3N$;?lypsaqCav@3L*1A)3Ru>ZLp@CwiC`br z7xJjJ-lZZ?_>n@k+^!CnmtK!K>1VtpnQ6rHD@Z)^j9Pz66c~x^|Lp3M$y!UP(XvR3 zp1h2$r8r&`TpL<UU=NJa-;d)LW=OUQj$c3wUfj*|iB514{_@{31mdfZu$oT6?WUaw zJu}}7i(rOQ=zRU|7}&bloR9#1&h__vVQOk<9i76+s({_lgRX<)m$0YG%K02Jk>4bK z^29QoJi5Cy=t-CKc-DXMp4Ngt{~2Ev&F*H!^|tW}+vUwxpBJ~U0*?l820ksIt|<Ll zqTfBGAukWU@m330_hCD~S2_EH-*|iWsYDAyz1qkGHQ2`&qhUkbR^$i?35j~R1`q&< z5T(mMZ<cHOv%Y$}OxBmh?3|rszL63E_ODf`)oHoaU#l4gZM>B-H8(d#)l*))z_RFi z<8`DIxifQ6pxrm>kRK2lQSyzy{?u(l_(7b9nZMZ2IJm^vO@mBR)aQ;=qf-N6uRm6H zEwR*{(Ns*{UyG~V>$k@S`~|&=UduVy_F827`{muD^k}@C3d}*msr4r2VxF6LIj!EN zFv_1Y?1Ty85(lr}YQ}|*J}>DI$0f#AZpQq#|ME+~43tVe2=jif2hP*)PRoG_%#yC= zQ)-K0q5)_ToU6H((3!k|ceMm8K8XI`q}ci*@A?9D@?sMV4h%*y8JUIdH*T*PE#QPW z)yzi(gtU=FQ%H~sk6qCO0?uvi&N*&W5la~lE);BWc@%{tCcMQHmbFX=myhT!HpcUZ zjJH#|-MyEXY9O`n@qN5IW@iD_ZQ&UUR#V1UeQLn6qzS+uDPNRXv`sU6PtT|NIOC0r zSIp41fqi1#;|Z$-JbqOt8rBgi>{jp+up0+qDwV6%bgR7Du_+u#eVwi}+3inI7(Y1k z#{e8CV|)xIlWGwIPqO{cfG|XS%+4k$^7kiYuEPo=gyo@y`i~hKp7>0{f~%hY`6lmK z{xAZD6?4HlZJ$jw+_+BxE7LSSRF3Y+PIh~-z$ILII+XsgOLbW}EAA+IqoU=piqxGq zr+S$W${UQ&-KrjH{IH&`iKpxFkBjq?#y=+##^e3yHlm8<_7-9==ZeK}!xx2{KA3ku z9(nh)FEV)|@f=T_`x18E!z+H#u_r3uo088Qk!@L4df8*Oxu|S(8g-U`-zml3@u2Na ztyY}+7D|Us=8QM*jhP#^RzgAGxq0$1!OPuF<vR^B=HJ<L;RTc8Hoa-iA+)T5i;YEe zY++Zi0fYWqJ!t(m(u}qEBn&kq{&hoxV}rsGMZ`hn6s_BSUYK|lT&U-HG>$__t**Y> z+lTKvEtbP((c0o3D+gr^5G&h`ps#hFnpJj(!4}E{^=1K=9mVy(>Ppm-Y%M&4u1>T? zTz<()_)k?LH1yj9EGBG9o#)kK1YuVy5L{hebKMwe#uK-*QK<N?fB)+<6MYhkJ@<#o z8{$rF>%{izr(lVrR+Cc$db^=U!v06Q)8{=-=e?I50k<Pvw0#hnzej8UQT!RNtwR(Z zlo2hU)p)@B$lRf%DzB?J-t4GM8y(^>HNw69es8h$#PT+tt~#)69?rC$T$?_iAD&LQ z7Dz0x2NkKFstbs+2>k1qe7ujV5%l2AZ$rnwABg{Ug678Kkmb10orXX0GT?r|Nl#F? z^hy69P5Bu-yw!f7xH3-TH(?U-cwNkdYq^IlN248t<;%Em2{;2wmm6I8$;Cw25Lp7; z>l47fDllH-W<`?!;{aH9-1SU6bzn9~V$J(^(ZCm812zlz+mY#?G4qu3M+$ojz}(0r zi4VfftkP}dwxcqB0Uc}qK^Qs@EFQagD*6(_9{00HSLuYAL&8!jAWBZOh~{8W#p~6i z)kYFkm0noqg3`_mjq0|!ovd_L?iCTlY7V7?L?Fd+Q?J3|j{^GNer<NyEfTvfVeHV| z>H0yaW>L78UG^=p!ju+&;IbYpwQs6fEWdamDKa}wLFiHbvnsu-<VD7v!a%dk^=#qu zM=Ez2Pr0b`GcVf%^JAq?5eekV{uH6*3(8V?lF8bGG-qcsWtt3M^50lK&`bROP$!O# z!L`nZm|-}`6LR}g0-2J0ZaS$xLJQvqq8_krc7}e!SNS2+f1w~yE9Jzo+rbR1(SScp zsd<rPX-~VOeV_5LR1!)eiGR3L(ejatlxB4_tv8IYXx}z8BJP>x-ok;%ZltQ%Z%qyR z@iIf_FK-;mx4fpl@xGDsOJ)3%{n>_yQOtSCYx)VT06SKm@FK@n5+S@^;DU&FVxZXD zEl$qBj1xHG9E!iDI?P&VegRos1=6|M_bx~LrPq=YU7F5VocnI}>58P!tD)hi^w$K# z2&3SZR!>^U+al|1)YIy8Wj5ztNw~cDl!_G`5)sExJLcrI*BbG7y7AjvMV!!@;8A*M z&ne!~qx@`|S_>CaFA!Vp!RS)={AaOAq&ozMiT)>=Oy0HcoR)}$LEOE*az<>_6cToL zK};G$bMaez`fa?!R?|~J(fy{i5Y2J<j6wS8gWpZLz8>TDXUy83xQ2BHX=U!MdMsB} z4bAT=y8;v|6W7~?|N7xS!hy6AG#QdSyqWutN8z7O#DDqaQeyV2-!h(ZKIxiWmg#!n z#@6@uk!MFgU1kWmGUw9e<llVDR+tr%xd2b+f^*#(=XizP;9RGClSc&)u#!COwDtuF z0z`)Zr2h3P&R8^@`d7bbf=%@MXPgb8=%h+(xvq{oX6s}jG9vTCS(0=%u$`up6-GTR zEehQb)z16d9u1Wzzcl%4z)o>3#tBgad+n2W9Al%lhwT=_jg(wTx0(jImb}DY^Z}?M z0RxlOh^~3FYRG;<^0erW(o~Leq##WgZk((Ht9&3eer-dL4kL^P!>QVi<}LX+*XcP_ zpv^TXp-&Yi0(~r~%Z7vn4Plcj@1NSpVyIyH^NS(Z_+6VWwp@7I2fiR^5JT0{x1k;@ z{e)Imz%Xh8F22y95C^W;ZYF^MF{{}99jq)=Zr2jQ+@GhE;6!a0OB8)>Jps+sz24e2 zk5%yDd4n}zR~06=TX*?hu8F)$EO#XVO?wBcZh>BD7GMkfdC$X(SaLVrmy?&z1})<@ zV!d>O>(cr*qx_(IxuZVi^`Au0y2!odS1TS&_2AVp4M+*UVWk+ra}M7nj^>(&0wH%{ ziEBKgxZ`iB`$nDo1+rV1y8d`XTT|*XA)Oxb&(}dABzPGTwuqV?K99h{4s{_>F=RA$ z$f%hpR}GSlP>5(Ub?yG6#Sw@~*5lKPP4=47yP8TP6EJH>@Lw{(FYQY&pTw9kDLd`y znM}v;Pdt@fkD(Q~#Sp8!wN&cAV1MogM+?!MFI;j9bVDEMXcLo|o)ITD94+GH#N%M& z{y>}K5+iwcDp*O)Q{@a&s;=j0Toh{TiQ#L-Jx`89yP59o>HM-&o^Ah7wE4}q16|Pd zk&A|#aj{G9qU*3xaufiO(iXZdy0)Y^znc6RGbzM{GX1V0>q3uW=OvMJMt1)?+gu$p z(2M-=s#lw(CX&p5xb$gRvtr)P*w>M!bS$?Ym#g7eZPTcxA6NqTGwR1~MR$Wb0P5JV z%Kc~M;|#}58sFBdp_b5A_0xEeOaDszCZRk9r{LxG2RX3omgY}LL6CmXbL)zuN4Duy z$wc6@KDiON`)>Rm^WPciQ=0agt|@mu9eKi%<~buTcciWpceaa@F#G8EwOGKSUF&Ze zT}@S;I~fV*_LSORcSH6(*QYy5*UO%KOu-6fcHQ_<<p(3bb#Dgk2A6JUV?3c|koMeO zH+x)z+xK%&J-`dBak#|<8g7O&J2jNOf8tB<Qv_2FzU_vlW94)Q8A|@Yx#pT-s;m$A zup!vwRLF&5v!+I?vE!$mn;;9qzse}^;_zb0RaraNPjwP(ND+$EDv!mJSZ-XM1zrut z0RRh>_T&2tka9;8weV^_YxW0N&7MVOfkixZ69DsH5VY{R1k1<r$wCpozWSvVM)G0s zZ;?VIjN*K`fnWz3Lseb{5Cp_H=m6))6pw>&NL85uw)xi@a6lOxhh90Ej`d!Vg1^Xk zJ%|;#bGv}*C7;Nca%Z??jAG>sxQdnFP^p!HHygiv7UPh*_r>@GlkTICA1#Ssh$}YO zi+f-S??(Cwgs@3@*fy_&Fk^3u$RUFE-(Z8hgBffHt_wpEFr{3PFn;6g6#8*|Udi^> z^jrlu+i$O^ODs$jXia@`7=^8)WWXG5Mr_<T$r0cWye{_=0&(|9#?^Ihaw8F@<+q`k z+O`95G5bezagY0<HtDxnUUcGT`MnU`wu+Z9CBzZ-0W%?GMnb2@Y4?H>HTmK~)2Ayi zGEGgwqj+feAc5-UX}=_BI;RN&UiLlhJh7j2$D93-SdQRaF#ZbSbDditZrA!s%y0#w z4A72?6`MJcEO#YhiEK_X(~J|yTCmx#f^i5^>j!@~JkQ=t-lzjSCF;(XWMiTw8bQq$ z-|X<OXkoFyVJzoNps>c>>3asU3tFX?D|8}mtN<axtMu#9t3{9d_-2nWXotO**)5u~ zd$%69*>wTuWdUa@!{4tBUTW-1J>Tz4kg$RPqa_LSuxpu+>Jb}mp@y-?QHKDR4g4jq zZ`Jdk!}kvpBPa6(P}E7!daa{x`%WtyZZ4|x#Tjh%b@wcHEzE=zkZi5#U1%2^<))+h zj(XQUnQ|SaX%@I?o(QK35ZTx#l?0;p#Yx0>BA(;7fA0)VTAh<5<gweOTV@K1eHQEG za1!TV)t2Utd`<!nR^%CabpI~jl;ud*;=4eUV8@u6xfv~)P`3!_Nz&)<0*C9_UXD`< z3EIn*?@97}&=v=pSvR+{-LxYV+*Bvc8`6mBFSjXU-Vvyp=~@-1^CEWfaCx!KWwxd} z#d_XS<p+!v(K{Cfl6OgatuKh1H1;a;A#cq1%~rBOric$O&VQdN-x_kS{~U>iH{87_ zCU5&lT1bGnKVdD^qd=v*uL23XbBXt%$}ENT&9_~%F%-Hb{lRF(xFR=s^PB{Jga9AN zR+{sgtXhbPvn-Epc`MP|*l#~-?>FAiQJup>gRrI`ZIH4~G+HuyV0h|vGxdx1v?Q~{ zKn!bxuw3n3<xMN!zYctKIPyu_XL`eE>cIt2^8LpP9(i~ji<LAKmzGh1-vV~8|F8O3 zpB{>|Z%d9~KC=R~Vig1S3vX82KA@RgBT!R-{{-8;ZT(})5lxh@oJ_rAGGEylVh49F zb|q-OxFl!W1SlVBOQlPHP#8mk;USHDNm$t5v2U4lUnE9=fHUT(Jb>IFsW4H#6*w16 z08vZTmzZ`{PM@s9kT{w@p>qL3Im#-}!x1b8dt*x9?u|hpm}~+@5UHM_;j8^VP9&1A znHb%l`xWRk_&*LowltHHb9o2NHh5c+P~v||0ENg8urp!c3{sbZ8@}x!2k>RqkANJB zj9T%DVMTVc%bUw~P$7P!la=Hn6V0fxAt325&5R}Lr|0^J8`u_&$;Nf_AZTR!a(yZ& zh`2WMGiGOl7#kZmf)3w}pvKf|(k6#*I2*WN2ZV5Bt?hgW)fVXk0Gg9{5N)guG8ahr z4KISx6gBKW-4zgyK|`eFUq7YZ4?^}^K8L{!T=|L~w|e$RQ)J@U?yY8p`GEEG`g#oZ z`k-LZ7g!A2zP8zu7p=F*wb)S}^NzE*ZG+#Dy!%lYTdA>}4rdjr2z^KR>nkWTSyVTR zLf%qKqx%u!++p6m<mU+3T-F>z8=ak+np!ulFpcirIa8I9R^R#Qihb<yl`uj|2#a~Q z<2k5K_T>a>nc&%Cm{hu&z#2VCJJ=QLap+=$@1NF_g-dfWa)U<wVg4ilGYuV8{GH&J zy73A09yz?b(m+{L&U*ITw5BuQxPCT#Q2kdEIg{&sgYXrw{Yg3wIRl7)0j?zmA<Hls zjDUTW6nL>=##(YA^tV`{D-HpW)*E*DXZOsgt}`{y-EDh6M%%X})Tp0FoF$(3Y_E-5 zo7iW(S3AB`eDCvfbq#Tiv-PH;%A!o!<>(w~t%c{a_p;lyiL3T*7wicKbgBf}uU0Jk zZ0`wC!r#ZmzwwVV>S}A8npdwyp~P*Na4tH_wNh$rf8Y&N6`x17(2(5<5>kzQmhwVR z%ISt4^YVz*{(F9TsU_AuZB0L|YV@t42;ty-e>1AyQL-)UjAt5)tfj(-q1pTEW^N;C zC{>|RO7*?u&hi_>jZ?h|qAXlOYuQ!P44`PYZ?@DFFJ1dbJD#1QaGCSuXX;O>Y9*le z+t!1&TtGDLHr|>gD+}^gP?huWnApBqw>bp@H{5&BbiRZ45&I=Eqx8g0<FcXB#IoX_ z14;Wf?`QqGzU>h`rYA$cc6m5107QDH`6ecVz^|X-<Bv)oLBjOu-b#NEv3-UeqStOE z=f^x});>mDp?`jMsHbdT;}jZtCE_#GbU}otaI$!)6e(__6bZ(jR!vy}-2I+QEWjrj z=ynwV$hukUr?kI8wDrdky->VAflvVhOgr?`yUCQNdgLz!%3cwpKtT%e#Qy$i{%-~9 z6E!v^;t_8H%{2J!`$%Lf&IeynF+K2N`j`V{$AgAPkv)AJ1#3({(wVp!ffbA_B5o$a zh8eO#y6|i30iPh=poR6wdwqmk=gs{fEbc>qI`W9R338Z-y+N2F-aDx{L>DI5#^OVG zUce7|UEQGW>mj_7nD_>!6ZjAACGD(H1Opk1@sUv-z9Oo-8CYUWqIV55u!6lX2#oYC z<{x#$?wCj%+5kV>SWKS8rw}AgIX3QW)A_PM2>^i>NZYR1cKW(q17*WU4HPn8%peG> zHp77sBAe^k&L*Urm_z>B_2vbbs(J7A63j*FWBUORe(#GsWsBgzr#I1)_H7z_&sJ2z zT8a0e_H-W7R<~j8R7^O99FInY31Lx2#N;9ElKm`$o&{DM^1S$&&(;ep^3L<Kp7BJv z+{gyvuq0XH1bO(=t*Mj+^Tcj)3QTZ>#WJ}rq6PeUqUX08Fl6y*y;$0E@(^+ZjbE#o z7@X55qGRS;hfgaOXr)szbP~DK-|vG36Vh2t6@xaG!QJm!R2Q<$gS@fS0Lvas(deS> zVjn!bX;nqDeNz{%TEd_W9XmzE>-Ef6Fj+A0YPfza-^Xsno&+yJxcr6zb#TfPYp4vY z$Mx%1Al-43GaQ0e$n9KnzOEhs^`}8w_|{hOaj+zj)pFQV%lF9@Hh(`I!S+h#wOGN_ zu)LEvo00Y$&Ty`qY+ncQ-)k^tu73z<(_?Zt5<&^0KB~YF^3^^ojW<U6(%cUjyWVSX z&iW9$U9BfP>#Ztv)4HSJ+O8vDcDPfhWi`4t*T-qLV3`}65+{AQTG3(|*zw?XP2kDu z8;V@IyrlQoT-x{~kCXF7Qm*M^$Cr{a!B5GD)+yo3%ar+*<MNHd%=PPP&)e=?<?cU3 zjrK^CB>ZW7Vn3Zctk4xvUK;0bX^&dki#Y=ghjxBUZv3DGz3k>2Y=ztE=#$S3cG`{S zt^S)G1m!xnQOHbzb75~vE)<p0c7@BJpcRryVL-s>NI_!vFtGOOMAWnc2?_HYGx@nS zY;{$mR*M2+gTSWQsex$Y`FWG`cTEcO;>UI0I~mWYK_7qm+yI*$IRP|glZuxwsY%`$ zOJhTNcfX{S)|ENbA31LnZ>Zelv7MzqtUenEBo7w$Pl$gL8j1_W2xLD??K;vfYZ9W# zMbb6{n}aW7_)PLLE{gu4AuEv!Vk_lz8_4|U?!bJM6%i8OZN)%{sSG~-Pi3I$^Y*FD z!4rRsh;+yXy9Ps)+jF9o{N9MI`Zeue<dx`yyw1zR(rrw93&LOdGJflCsSC~QJ@i(Q zTL@cz4HpVJ1Tz@V)9vX=a)~D~a%OLV%p7ceH@ly6plIU5hYuD?Qnue|u<74<0Cf#g zo{~{T4o4c=L_8(_EPsgp3Whe$R#&ejIDecd5-?MR;U}|}!M-<uSt};R^L<UG;!uR6 zABYRXTM$d>ha?E%wDR#@Z)Z0Wi^wH4U@nZt3SJCqFv}RV#)hz455TP-mw;ffsgJEW z(;&fa8whX2;{vxVzr~s|LvROZ$G0)s1_lv`d^8?}m=aN!W#7?{diPALL;{LtBH)#I zG|EGXfPoj%`2FWjL~Ajt_}d8@$1Gh$zAO;QV@6JFGLcCS1+Fb{_N4Z^ueVJ!hi(WY zVdW(1Lo@X!!$j3m$MyC7-+{e*#RtL2=hV_=z0lL}*l@p6kk2{q!NINcLw|P-ShHd7 zOMe|)YZ>|CyB;0XdNly+r`x9f!Tfo1A=o3d=z#JNbx3m~%@4!DyjG-$qQzb?>a!&_ zu0Jaj69N_Tcmr4nb8paPUkgOH!CU3RKdP*19iBH?Oassg8ALqg5C4EYA)QhNnBi*b z{NL(*5+D=cUhdsL{+SRE%1Dy-ib|VD-nUM=DyL*qeU-WuuUAlO^!l9#S<+L5Z%(yk zMmsJF`S15sD8A)LmE7LXiPaw&R=C5WUAvF|alfE<Pfzy4hy@T6VkN{o-kEwPTi6>_ zr>&ad^;8&0dE;}uUBp&OwR0V@=%0d<v6!t_&6DjqoZaK<x5G({9+VHzpT2*{aLu!w z^~3!$hHG8Ldnb+`?NFJ<Sw(AR7ih<iT;dV%I~v3a3tFWOgZK)k53kxeG&4}oTN*o6 zt~O3@ZkruevJSdgXq3+S3=O@|<TriiAe=n@QK9?+5~uJJI!JOjPt$Yp>pP|m-8#*6 z4rwa(%eO~?R&x$Hl_}YZIlg~rSj}{>m8MAqaA#3}s$Q?A49=czt#a_{eu%nFR>}P+ zC}_d=ccNm>&o>tucyWwk&m$kODp;Z)NX#Y_ntm-dt|zUJd`1WppDv5vnEG0&^g5g7 zVkv_7())(X@3c6plV;;012y0YN_UPkHcU_WORzg(1!C{{uCU90KDTc<5#Z~uTxlGM zLCKE=fsHPRZce~47w;&v9fE5c8xdwk&8Xn!o^A}zDlRVhD--D~<~Kt2co5Z+L=!7@ zE@V){pyP(b%u{W|dgo=Y`fd;+i2k<_xh<v-^af+u$j_MA;*5rjZ}qvk?EP6}zK0n0 z)L~*P>jIm85Sky9=;oZ4G&g$#BJ~)xERpXLx;kPn%s&HbgN&_;rd?4p);vAt3?7{i zG`h|!eST8R38vSI3qT|wZMT5-uEkm@i-!CTo18G<#^%k#3O>80b%4QFS}NBx0ac;R zo-wESDma&nwO$w-62e$=TM#bgp8JX>)0Pr}@S3~i9;rD>m&zKYf_-z9uby`Ai=A(N z?icA1Tw{*OH`-9=3zL-1E~`_M1~0*K{h6>qy09BjQ3nR}WMO+kyz*mU5`~CBWUB=| z_^r<_Ige6~*OZ_+y*&bXD6a=<@YQhnGL0@3<_5NH`ml$YJAhy5I)DjpEy2ds($CTF zf`nn?;D??0{m4~QG~NZ{;S{4M%8PT2^OtHRhAk5yOETM)gcYI$P2H~0cU!0gt&#Kg zbnX1r1L^O#Hy!@b!eLY#Y1mv~39T%A$0~5`%k6+rI0-#N*5Ru@?V1tCL~XT>mZQn$ z`aI%GF_G0mqrX`ISIw+j3tZS(puSpGkzzbMP$Sk7M{(<2p}~<PX<VX?yrh>oceX6k zWX?;LU9KFy!?Zry6d$?R9O=K_QFuIQ-Xj^C77(tTp*Lx^(7mfY>sGt|=PvzIotyY~ z_e2GQmEg&1Z>u!rmYJxK7QKCGRKxPVQ$sZ7*s+iHsI~ohJ5=UQ90k_}d#RPVf`m1; zMpOL{H9uYMb*Km}`d2--(#np#Cu?$Jf4OEa=6LVtkV{+x)_lP$9we+~HbKOu0|tjV zZcpz_fBZ5_<o45hqRq*m)bvw=^~%}K>PZStMC5|kmbdp|s(^Oh9(5f==`(x_cqIC! zi4}gf<!W-~HU8$A$&U=oP!iDsD4xC&jfS#*v17AemG)Jkbw!E$mZH0ddNaaT3lsf= zy5#`niw7r!t&dE0Z;clFO?kPXy_(QoGQKvRNu1w!(E7oD9lb&bC~Av{Mv6864`<IF zqqy0l4IIGNZ?Hf(kvCXUX?kEExuH?rL_$rU3gNCAR`Qv1dett!U%3pk<tuNF<lNI$ zP`&7n|Mg`jdK4S+7~F$$i6&>qJ3C&#d{^Dweh|WLZ8`%!m!TyOcH^I<rF%dn-l`nF zzx|vm3o3LwK0G!WiS=GnwFdS@{qEfmRmeWiSvs_?XL7585C$Xuof(GgyHX8mj@`s` z(>F#n76BtETIP7#!|M1^z(A%{@FR6a9Xx3JM~$!tNqA6Z886}m!U3{X?j&Y_X$*eA zlKsV!5QgYA10Lx4Q$s)wodH8Txb3-SeE7zz4H$N;Zl~&LnG()BMqLnA>Zt!&dgr1S z7YY<J3q;&1v#5P@G@{5_(0=6OgI>O`H;t;F)}slpXFSZJUs}}RM!bMy0A0<$^6sq+ zLZdceUA42%v+oBzc+9sQXj=(Vt+qmkxTG_S3}&vFaK>L24V8nCrR&>3LoXF{Xj<SI zP4@tBe?QX^&AdfzIc_D;;Btm-0T`4kCUwL2v>leC8uZp}HKqy|TI5~^N(Y(K7Fb-_ zLMPyhFdr={oPsUP5C@rRkXSEM6w)e}Fj{IhTjlg~tjb}000;uyPO|4P3XEhKpJERy z{+Dph%NUGN0`0g7VGoGgk|Mfp@_&hFSCB$4yB2haaCKx;Ig2g%P0cHtmM3eK)VO_0 zKL{4!J`_$V2poOEQ+=9WyuVHc*KpglXp3T1=v^v&w$;^WFA%78YK?L;z2L^bc#!a9 zb4q~s=3HqA?NFr>B{Qy&r`A&#LxUE>HQ5ta!4U@yo&^7t{L-4NhEw*qF18123GTsp z7d{%%i!(~HTIbZtXY1Miv0lk*=`apg^1>#`!;TiSi^6!i=uoo7mj!|ALQ@FjV_BaG z8JvJm3y!3?eAO4n6`FF`S4r*`F&y%U-xN))&2J@4$?WpnhVw3CGWrEvpxBpZlS_iB z&NIhej6R-Xx<Em3@@<(Y+FrS|_!<zEb}r(yP9+gA9hu`ZJ~LHYydeQSQPM-c-7{*7 zl-4!+Sn-f~+@^GU*_I00l6I9Lvg#mlI^*4Hx*=X)b0_X~7)l%)a{u})154^1$BB>S z4i)M@hxli**M{?+HPv2nJZ{Tuic+WT>iw&)=*9!*aw+8H$^Sv-61xVzK2r3@;=K@V zz&CJ4=f_b;TN8SExVOCQB3x7lb;NL?j7|;Z4l|s8cHX<eYoV}PjZQyupZlFGrzv~b zp4e9JbjC5(V-yUx?nK(217M<jFSC@W3~|e%AN8mLvvo<;Uvy0cBG<*2{9d40WiS~` zj)~3c>gsKdTgi$gwxbb)3RklImCS>`vhD>1!NQKzz*U<l`2O?c8hu5)k(FlWfVV;t zG$)S;ray^=4Z;6T@21A7+%NR(;4y8CH0VKt$lQP=j!#h!-8Zhs5SFGaaw!$rnX@qx zdA`C$PsjL^A6(fN8jvu{C^At}*QLhg#%DlBYxDmg{mUDXd;L=|GV)^x{cjJkZMSXD zdG&fA?~4`P1xM}0rU7-R4)4BD)jfbS_T$4~$`OaFAeA$HUrL}AF}(M1kcSLqDhFoZ z1=QM-`NoCN4t;Jc*1LSj2Mwt5R4m0s%R_A4YzrMC`C~ejAM7;d9LXXBlGhEkFg#<) z?NSU!*EM>nc~y9UL$^+G6ZX2@d{3z3FjeAj4dD|b_NAt;;;-_?>?Z+dJua>#^LN|c z*ot8jXNd_gP+%omj>P!gV?4Lsv`T)#RpPTyIUW-;^@8G>0<qb0LCl$+!pJbbHq-gU z$eoL%Pnyh;=Tw>(+V`&*xDGdYIjT?J8@r9<pYG|jXkPLpTs(?&QOtXbCuaIfl^`D{ zhfWZ;+5L;FAlee$3s*RoqSFe#Cv_`e^vrRcjbb9V{UKv8WmnD{)QzqQJ3jQV?lMo3 zLLs?pjv#5TD9!nz`x|33rt_DJdByRX{)MI1wU#jLLe`Igz1_oC(gD1Cya?Hc!@9_H zIfp#PKbL{$ySn;99R$(R0n-G|uk<3WY~yBqMz>9!tx8GnGnlc((jD2Ne^~RDQv515 znRE|D>)Z|!+-@Ud!bMT_Fw5+u9Q7sFnwHDkkNmVyWtQ>udhM)xBnXtu*4VY-=}34i ziIDe%o85R(F8k7=LSO1l5?*;hzs|ai;?+7&fkT0MWATAyHZTpbsyj2^On2q*-u@A1 z<GirT+T=P9kpM+%Q){d6mo2a2>FS@=MRQhoe<{dRl;9{)QQnKO!Pp4?T~jV%0^W); zch_oD;^3(;tfi0ZqPEZO*>NIOBcoI3Asve5Iy2)G2;@Sfq@j*-P}z~R11N&i$Qvs< z`oRC7-;pC`c#KTOKy#-t8D+K^wl*Oe>^}fR)eXUxF5!|@znp3`4dPDp*M`RQt>WA( zOhkUlwm(rFAb_J>qjXA5zak%Tz(jnNFE0Sykv!n+7hnapZEh#XpFXY)hz5;Oo|7PE z!otKB_O$a8O%!VxxZa{t?uR|l#)HPDP4?09>BDqC>SypGhPalj!#MhP11D|L!Z#v? zY(9e-^tW<~J2uv~<kcsE7a$?gmMF!;7nG6Ur`Z#X=*2i|VQhlh7nt=o<I{t+#lK8R zpx&zmv#)vp_v`x#7UC>8!mML`vIm7!=Rr3d-uVm=szY3JLHP4F7$_&y_q`fFQ6qv8 zF~{gaCx8!f8t`^9%CA6CSp&?3J<HdTQK2?60{h>dqDDL}FE4fiBR9a&)FfNT&I=HJ zG{DhG#LuLR@~4gV<U`KMFaA<Qw%^5t^1@D;0C_XV?82fdeZDP{z=9!rHNz3alx+`d zDtKasdu$TA9?kk6urp8KtTN!D4Ry)8QrWNgOZUUL%s%pCyd#y6R<>EP^T%%GR@hif z4mCf|ufI1%IrehgdLR{$jtj{}TlH3ydPU!(7n-0|n6?Y;QOR`acyE01cse(|X62I} z@e~CY|M<jc>gAIJfi1xffuBYX^8<Ec_8v-cFQ=bcm@Ti1NG_eJAeVmfuMJ{5Af(Ol z>ETqqCk2_3vB9D91#wg{UAGy}b@Cc46M0Go^E9?ZNjp{Gx%QzI&B+r%0Sj@@G`M}& zsjuG`yQ6iUvVf6y=oZ^lrJQl`j33#n7>S>7^o<{Temf_EYK~M=!+^qWbo}e%3+KuG z<*%QVQF941H;)9ol_P;eBhX-d%+T*<DcXfnmtMc^8bwe>nw%~|f1$~BfwfM3d^=u% z%vy&W(Vr>QmUJ*nmZNWCUa$L8CY3Sy=6)-|`a{Li+Obz9U5#h?EK7xK$T^$EtuK-F z@D+b}Nj%L>!#bz)ml+gv{l|sZQIgJ%24CU*0|AGjoqc)==8oVxQi2Cihrt`K<mc)Z z2Z~K_nx3_}1XSGd*?S{%EF<CjgUf>Rg;>LapFjeydP~M%ll=#8Fx9B^_o|8ia8Cb{ zZ!n$WdduiL21pfsu+HsA;@C<~jrNY4V$8uho@VMnyFe+V#$&^U>gV&Dctoeg0G*bC z3dtAl3Jf9M$3P8?q#tGd!g=o!On^?o13DSUEHgIa+D1|WM2j9yi|on$6Q@_JrGS=@ zheC`f70m$CItcwcmLZrI<s4#@{SD^5i1a^3r=W~l1TJz*Z-DpCvrOd9!%}3Q13Qu( z9O0zv2L<_AL|uIWLZC=hkA~TQ#tQa01gAs>`W;x<Y1&H7GyQDMBYjZds;ehu?&Y*u z@(vX2H1%Dk9{>38J(1He^-#P6=^l2jjjrN^ePQvB+Em`f)1`(gmst?A*Nn5gUU~h6 z(#yG$Q`B%SR?fsiD7gNli3wi>Mg3;D?&IM?!Xhgf<*m;V<mZPOimtx<ym4ftkg@#k zb_`Qt;s`L06a!IHgXnpO59~<r`%)sS^7NF0ayX9*5C-ni$*i7YCaX~|1!rFO{L%ic zkLXv<T=jT9YJU)*A0Rpa?Ee>L`W&2pb(VPURyJKK4J>lcaN)WoPkvS}+?51Y=VA<^ zv(G<(CK{BnMrUe|2msDDWDzWWdPI%R%?{~-v<hucl=v06Y>Qk2{daujqIO|KAKH$A z7x@~56SC(!`*}IK=eB`U@Sw7;in$HLzYLK!*I~s$f^EmZ4CY!mua&e<##AD~ZR6-# zFt4vIpv|}rqy8A5O!7<2sZX_o7rof7%Us~IoSS}{mT=0&!G9<`DpWl&qEG-pH~H1; zW{n5xri*X0tk`Ydv%Jrua~&R4uvuF`FFdL}<<f1T34P!Sn|**Yrbx-lf;jwieHn?3 z)0PkllTwIJ!PRqmtipI?m0iOEKc$$E);-h=6h`^1rwUlH={D?mD`zY`P$53lWb7Cb zDl4UH*EW9RYL;Awgdye_&pOV~6bXA)8z;rq-BI4z`jt_mD)y=0vgG>W&RmNeel>(U zJdCSY9L)IR`P*(!)270(sCI?HIh14r9k~>)n2yC0MF~v#8y$qaECbx77=gkNFIcuv zaF?R&$k3sl<MPA4%GJw+;(0S`FrYQ5Z3IUd!C6R#nj7r}TjmKfLlS1uyTZIoHJ@Ny zl?N4%lT9pJ#JI2_S=VU5+18Ksy0-GC*3^rM5luUreXhPM(8PC@x$j@;@TI;mtu2j& zHR>PpvA0B+!%H-0p#7g)O>=5i1O&G|b>bFQ@KY;Wa2b!rV2RM_jiv{2Gy4`N*0Ax| z85X=vOt0*r83*?Zo5L1y@Fvu{{_3-e>duRs&Q9bABxm>|LoKZZKptU?sxGo@))-mi zdxM27jB#&l0T9?CB8l@RXDpZ9=M~==YAPT8&~uVWG{(CG1X|X9@Yv4)@pTED?v>`` zQP__cqri;?J4wZ6CoE4^^ok%p1AStJ(Nk=QkQKSoJ+Pw-CY;+~*PIa7TlXyJQI;q! zq`#e1?Gnsw@4ZN@<tHLX{FQKle*|0?;q(W?hZ#&bXBg_UzF4r`#pT7>86mqj&#JiF zLOb%8ZS@sqQllvPa3Ck>jegJr$35(}@5Fo45*X8CIC&$$^C~ihNLpa9>OXoxE!q|b zmU5<dKoM;kE)ET^SzQ^-hU*5;W!#t{f{OC7(@=V{xHe-4E411T0%DiG1#z7%qQ+ye z4-8vA3Rv^W0@T%Mi)OAbh$g6^yf3L}@<FQ|hIX9=buyTx3|ZtY4p;U0F8z7(O{`CQ z5P_~>>jR6hePC46VVE7Pc79?k4MIDZ3Re;G^OxiGe=yLPFmn<HQE1^56sa3OccrE! z`tF%-B%oqg;RRE)hJy@N-kQCu+rCx*x`Dxfo{tvsHUv!8okgeZ8#N+iNXTCMXEa(z zG~Z>u^VMf;U&rV?O6{)Eesr9`)dBg<2lp92$iH6Cc8|S$>BgNO8>jz?OQ$KC8-6-Y zH_|k<pw4`!SAH?qMLgxnA--91G)GC@x$2X`%RP<+a+PvAy_P#%I$|B>NUR*nw&ok} zP30jEL-R6a2})x^=qlTm65uwQI7*z&Iwf@b`6OGDOOy#Q!kuxz^o1+S&6u}$BjS|1 z@TNmd!hOzVH;~s7Fdev=0At(EmIvQlI|3_b@~y@DQvuV4b~}f6LdK*O&zyQ*c5E*u zbk^^j$MjfUX|XN#?S2z4-S9dPsNN_wbBnnAL<CE{d6xZJc-ce36S$t|Lxfv`Pwym_ zEz=wt_lW;Q({oloa8oVhK_a?8+o;c2H#ts$;CH6No83O-N|OyUM>46eCzTFsivZ%$ z#<X0)Z2?!pZ>*oFFVz{uSDMn#^g7i|+PZ)F=fLweX5dLwiuXUwimn4Lh}v2MsfwGk zvw30gCmANLAZCc9BBpqZz?s1A?*e%Q3)emr3)^xm@ak+<uuw28$?4p?&Jp&#pE!6F zI~X%8xvU42H8_z1K4wABJMm4l#U!*N{0JP=dz1*Iw6*OTSXpTmd-8)FwJi!507GqG zysDtVulD1KCR56hq)tE{N`duzT~Ra08ck2JA%m6-3=J7LeM5&XfUO~76hB_!5?wiz z3&c^jpj*TbzW|jf=WBen!367`$eC;tbrUE_`A>Y^!5vc%+>#OWyHYz#nB}iWSHPLz zf>;{P%Gf5q$6lNcXul%w6_%V%L(l6>()9;x!D0@7e<z7z+LfY4yxye7evjKqg#bB3 zWN4#SEc>Vyy`M?w<_qi?ZXg<O;DeeJd_d0nP|9Nk*Zm0WuBE>!W>L{)ssU9!Wb(Y1 zx0IOO8t=xVpyn#DuV0DCR8uk4JGbr)d(OoBjz;%Bl4%G?v%s-Qfc<8asYX6yhFRm2 zy|E1RDX7?*Cz{W|Y=ihJpEcCs1J*j4$wn7t`yoN^&s^;WSRx?d<unG)jpYHt)uhpT zu;^XK+r6GyK;u>A>*RbVH~j)E$n|Z3E0v01@s)KrrTkS=2uBtp=BGm72AvQVH^{NV ztjM*|NzMkI4rdz=X30?t8;=)l?iH*yngc@xk(5CD;8Rqc=AK%#6)aZJSy!eR2K`<8 z@<OR>fE|hW1x&DS47b=D^9}G;F<~&-e^9Ba>^VAg>4GVXF@s`z=xofUM&!neiPKpj zi`FpLHznnr4Dq8f?$iwA!~K8ndfecI1l<0(h-xSZ0L%B9h9Ow!X~$=X;Iwa@0hy8B zq*t%Jgm$KO@b60taocIjS|;YlKRVo`BnuE<-rt*il#L!zZ~|@X8vJ^x8^yK2lLBKQ z)is>!Sx3~$mzDWh{&C;zwB4ivPFp{Y?>&ySFTHqr5!rci$?6IW+|sTj$>~c~Zga$0 zICz37XO4o*=|^hZl=|&<?_-Z3>B5#B7iTk%j1HA$I<acaXz@JhxDTUC-Pc7;*PmKG zrAS%Olsn56u6l?%jnXqn6yWv*UtAb!TF^@9(F4M{m|oBW@wt?fV_=Z>6>5ewF|<TD z`(Fip6^^C#)@9LOI=fs>%buy*C}PAVb0}?FD+xIB?HP2w41u3-DsQ0S9qTn>4d|SS z>UQ3`)iWJ(G&ZSYjM(tQ@~$U)Kru2u#2n_ro!YAF|8PoHvo?P|1P*}518ufF&jQ}+ zo5aGq(ZP}M9)llWIT=Ot_HY~<Vyim)$av0cI>>hUJWaJpl#rm+gs`rGy0@U9t<vp( z?6macuop2q53DF(;6VmHeRf;y#M3$ibNU^<*B6b`f^^;h@WVXlZshXSvsT)xq;CBa z^5ZA4M1rNI@@M56&WmlZvwQEGEN`GKzb*bl;svtYgx*bXj7cl77IEl{fH5JZmVgbu zw1SGuFaa!hrg3nvkSL4PZ%-?dR~Wx=qLrPCh&aXO>4@Y6VAHHvH1@Fd`%=rvO0V@E zr^P)W#uo6^%;i<bAE42@CG?@^h}Q~Eu?2F>;Hqh`t(Vzx<`<C)=d6jbhf)P@LVh<z zjO>KZS#PsduNYc%+US-<72EWsTCAAja-iaEDnP9;gNai@na+TIJ*7_BxdCj4@*Jw^ z5n?|ZD>B#~-`%eGJo}LMtUpKtqo)xpaIJp$bd^vs6S%fL|J0_(f!)aX#f@yRD{DO* za@2*AWUbs7`QUJWOUCnYQWE_Bc_6cp<*nUF(cWWqBgcmU6f$@~IeQy_l=&t68ZG`_ zGbu3K2Y#7BBu-_RFfCrn13$Qu{AF83`xPjx!`X1TF#by8Ekvzwy?iP=dtdnkB#d6f zHf+ZxT@<nyC<b|;D>o+sOs@gK6EZHp8tf?%LjoeN|NQjc4<z&K5F~$njT#|{AI6aB zS2ibA1$y-PK(MdrPnAWoXMyi)TTjcK@mUEMnpkW=g0sjFw;0~q4i6JZ?6d*>v>R}9 z*u&x<bY6)MaJ`f1#F-7U>$fZp3p2-K^8{W{v9Nb}PzA)s^|y1<7SqOs#u7}FS8eD( zzb<C)FoTs*DN8)@_zZ*XTC-a3mdK1tsRY;`0}{MNk#gWNV@<fB*h)gQA9tJamkaC! z!7w+qauO7`IDZjoN1^-37tmn(-YjAmF^5-77Np1Q7k`{XsfB5>EPS{a<WW9R!C2v= zLd~R#MB^%$IeUu&XhCvTIfnPd9LD%iUiSg|WbQk-5O$3_q6v)6rU{DJ+tvlmTZt%9 z&X(ckCcsXUE}LIYK{!rm$=uEp^{r-r{Jt9#1%dW}_w*?or<#L<16xnttQNm)$xfz~ z|CZv~C07{!QP<z^F?~YlF4J5SEiy=O#^qF)GC(48Ege^#o)Kjqb-7@D=D0hWHduLm zkn@+=*2L;H{a(cSaF%=T$Kl4oJg_4&S`au@$b7l3>HA?_`?5Vp<BTEuJSu^k#s4ue z`m@{lzV;h|yUaLFHt05~F1T4-hI`!Y0s)@>1w|?vi`%^T-E&Xpm}2o`($=MJjJ{Y$ zs9HFB1mB1l%(HwT@SwYbkSUwQX@bCdUGRuHM)*|wYH9ML-d&?N=2hCnM{8z#&uQUs zH=WY-=$O*p$6zHZE;6~UM&VG=sEXivZ$?1D{G7#(>`78!t<YaD8qA)Nt{p}plg>7g z5&x^Sx2J`iBT?OejV=3F)d4hdeUnX`lENFzVY0aR{be+a5ZnO$TS3j6mS79SXC7}H z>;mjAGAj^a1{3F!XyCT11Ni8nz3URypx`BVcTHiU3!nQrd?a0msHNkRu&U&FP(PW+ zD?&$|xQ^5R@oNz&VzuI?vQO?WQt0ZmT0ym%;ob6yHxX^-ph$MdI00@k-3nxDRjivo z(X>W*;sp!nDM^IEvj{R$bdJEhHxCyId-0k47lMQZ%x`j}*wY;$VK*;`s-cYgVzxVB zh+43SkqdrPi7r7Q59f(x5cDWF>Ha=1;TMe;#rttD4oZ7{xt~(wZjV})1T+iTT&McO z6wpqtl6-wdIN+Be4<(sh4DWpK5BA2<uVg*(-pMbnt3;F_c$Ip?h9b+N44h76o8#qA ze<PtIb{sY+Q>WCfPa`)CD_sE`lW0e=vJ1hoPv0tK!#V8;9A@6ixZ0SUx)0mlzkKbY z%k&GZ-cew;f}D&tzsdFUZS7I-5nM;9E!)%npeSfL#XdK#o-Oz4m4*)A&kH@1V^1dv zM0@TyNE#49ttJxw(SYEd*GBr51fiJ}RLY-GE@_2vtq}(+9dFOH`L0$#g<TzAvA!0@ zWkyA?7f(QN7ye9k@@*u#v92rchbMl!!j`8*`2As0^B1!1(_|U$oe%(jNw)xCa93={ zr#TI55n-RDXQh$_{BK?+(uut${7}hnA}->}e4b!<Z0DgqdYu!LG;&&J);_5#(#wI+ z_GhtIPhjs^bsef=9z48u>H2^1_10lgf9oD73@8H<LkUQSbR&&0gp_onC@^%Ww4lV$ z-5@C;B@F@!igbq{Az{!d2tzsaUE^=N_de&Id;f!nXJ+`WdDmKRd}0nI*|Sf-h)sju zZzXHL!`q>AyMy!x4Qz5ZgJ<da0Dypt`(Bh)fC;+nahIOP2^bdyz!ZpRcI+c!0syG< zO3;S^HRd{2YZ`!iUvgLEso2%v;j!j5i>|0>Gx26ml7F=}Ll}tXPzAxArE+`7EiId) zlCB!@93HkFLV2aCX*IJZlb^hMHz#zR9MZ~bUI8YOZ8@peO%B7HVoqb8Lz%~b{sBW3 z&&9|fI-u?8A&3}f7<XxQiaW-iGSu5ulIQmBxm?HdkaF9<U97e;IC70k&f!~a%TB5P zQuIBB%z+jO{w0JHW0h!6=gq?{eGcNcn+q2EZN=0noxSWu8sD6c%j5jeGhJ-mX)W~v z0Rvr2M)%Dr7L%)1#PQi~X`S6-Xy`Rw(se!@5h`@LOS4_dVN+1)t2QZDYmK(t)2Ba; zsZ>`^D9gO6Oh+6ik8iyxfu*-8!MvxNA)tQTmn)2bUDGkp;+@5zqxI3?kgqkY^6Ju) zIj+%`Jwkn0L6pk*ZUp=F6kv#*<l%m?8N!R>%6_H%`~_M7s4_6|A{}jkW`;9~wSG$> zydk!Ue;>P@)e=+HgNLrU#|rv%lP3qW?f>-k%3**Cd1lWzqMZ5*D8;gU)v(+EazMiV zw?Yc%S_1+wR;6x=3wRE;T}!=g{)J_cR~-_pEZBwp%`C49zo1P+DUt(}WgKJpSR|JT z!%N0CZRzb>c!{=#8Tc?G%Dpeu{~`(2!d^#0aQj$?4&s@4ZH%4_Gn6hdU|gcE2)WC2 z9a?sVg_^P%3SdJ3WCK}?^2IK_Ds0>8e-6Qp&UmO2dxKKd7;W?pYhf+-_+|Mk*KC+A zETx$B1?t<tJ`WmBrx=4T@90@mhDZ{)DkH+^vz%zDtQ)b?U87;WXojGAPXH<G#+(c$ zb)>0HtxQH^)wWk!fVh4~L%&8#!uq)B+s1@h!6Hk$o9BTBcs_(=H08DON1Fg6B`M6; z1^=blXF)A8(}P$yLBgLa5!BXp^ro5nZ!mxl5-bo_Qie8TsGI|pQdgh{y&sImysHsm z7ICz%ETn?J^`466_Ezk<jBAP)xtBNCbbG7tEzgVi*}@Uc^Fi0l#)~y^e$|c^CHUJX zZ(o#GoxT^t6!~KM(!ZKY^-IDs-W@;Y9(N?jn4Ri!lU?&BP8>y!5Zcn%z4d8{7vWLF zVi6~Is?oz%Aie!$O37EE<m?Gz2;7xgznwMdocOJRmWSPC$+LF@VpGRpV>Ti!1xg`E zW@`Cmv)7b2qU~U~@vt?Tr$Q~&{2shA`-0c2@Lej(D4#tPJ{&}&&lY|lVwwm0VR^eb zUC%9wpI1xO7+w0>fh2L~<8R^-O>X0X51a}FxOXES_@u35mxzE1I){{_Ry{o9FDbBw z8#eFfaZCW!_q~)mA<DT0fw-3WiQP#G&n3FdP7z>2_=`0=#t2XL14q{tXEKU;)=y%k zv*QBh6;U6y>q@1%J5|h)yLqs8X>xuG94*Z~G1YNIjE9O0(O-3ny$W4ly5!wfHuDvv zzjg|4@7TMtH}2Y-^f7wgQ@!6{36nAzxFvz;#ra}!MXE(gFcv2Ou6w`xW;d=xtwdz) z6FNm#>T9yDbcgY+C%Oy)o0Nlg`pOxI(tu;KT;c8l(o>UfSLN`b6CAS3sFHxqnKUkK z^#JOYimZFW_UnBd*9Furtsrs#IZ`%}ND%trb@sh~=&@~^fpA_p8aR-?0WQKzy2kAA z*F?SU074u(lZO_Hbx+yA6Ai&1I_r-YI^!&0Y?M?61LiQ1M^?A~8D+jEf<~lZZ*Ynw z(l2E^Upm<wP((U{m`QI+F;!vyt>AIjPQO^g6~G0Jy|paZ5w;|$fN%!F(WIMF4@y6j zE(y|5w~n68>r4jJeS45f2(k^iB<>!V63kgJoj!338?q)fX9#Q5j{bOpz0{{{pge&S z$uP!JCn++%1#k?sN?joHpG<r4f~+jt=Fc_i7F+JKR#EqffaeAi<k?11nqEhg$M?<s zD`%!xH0uljVhL10ee}<H$#ILtp_d8ALePP4rzV~RFa<n^3ws+}Xc&-2HoOr(+4`D# z=XGdaiW<mDJ^^3ukJ2FH?(j5K-LlSd{%!90eTqdy#413@c_^G*Azkai`&Ei6{cthK z;|%>fxJ-<4KqM#5kY_xS#UX#DiPS~N{r%styOzAM8`H;4i7J#nwqRw(8JU<dY8v3E zI{r85=$NI(4C&JRM7;Y+^jS|@U&7A?-OjWy)=z2gSkCl6$(H&m^^{be`H8J4KHOe1 zA;TNhs-*}vIPbhPdVV&|5$m^WNVh4p%`?)1=&t3mi?*t%UNTU>ecr)5<!zuG<>1TB zL0oKLW&9D5=0mw_Oiwj>>k&D2R~s%t97Ksj!Ut<>{3^LbRK9_gA@9)@!tFkwdCdJ{ z7X8X4$e`q{t8<SQp|9YPP`8f8Kwo*bAI&26OC<!?)x&z-mnViA2qCZ88cRnWM!mD? zz9;MNdVpHK$UH}Ny4e3;ei#ZkY~LLsA47LG2!)C2DCE<phSVK<sRUX2^u<7nKrl<U z+^EuxOdf`Tn+5tp0z*wR#Q+c9t<&NQH{mP#yM>A;k_V%ToqL})rN2`TUO`F6#M2lt zUn;sdfD$bt@xUr~=_b3#!>F_0fEkCUM^^W{R;fNBdSkYPCs?Unod}l7&B_c$aLzGl zrm@l<>+|U}X{NZ$Tkz4%ukW6ijAi<_A@^al>8{yBGAh!xDM1tIY6q})E4^NytN=Oo zJ1~7-!Wcg{N-ft_BJ+OY*zMw|{Cob8$IhI0xpX!XrFp4u{1z*a<{aoAfk=SR=#4O< zrWa-E5-$PK4)k?M+13Lpp&c^%hU{>rFBtwYh95Z9;AH$8NRNi^iatQ**}X#3#M;ph zEZG@;ngi-J5L9T!X7UJpi1_s4bO-OuyK2xT%p@n#`|%_2ul3AGVJF%-Rh6S9C6QTc zxxPv?P)cvDV(lJ02VsY25B&k87b5TbVf*d1WuG(e9&JR*$i6kZu&Wzk#?k(REBR7J zU_>_)F@S~}*uC)5%NZ21eN`0m^Vf^}kMV6#xz4UPWpr-5tNbKWH}?*xY&HLu0Sv;x zg9oMo6&E_7{ciFZnTiE8Dw^kW;;{msN9>1xMD@^Cxvza<HV1I5XYbU0jBos)$;e0_ zadAQ1y)h+4&4iwRX}VLVCbu2T_gn0eyiIdwsm!=c=nZ4Q^)gxgd#O(+JcQiopX`Y! z=5C)oS(-&q68+-h9sf<SaiVSfV*8>%)AQRD7|K5tb5x<pU6G+h1tk1TG_*uK2fguc zz$0_rACQoC1K_z<wec%Nn6WQfltmEH6;bm>pxlP?y#lbvHd_FWiqu8}fRFLgKUQ#7 zi1r^uzyu5zP23h>-bZ*%|NQOf6PMzQ*q4mf-Ak*{HY?qHB@EcuGLHDLi7>xe``i?8 z74WuZ&6Z@xUQinQoxE~8Csz^LFt4S|^+V{Y5MsJZsikJ;uLEYsU-%t!R!c!X^Z!zO zwA(%*rp0B<n_6dHLt0o?94G?YODERy(Iedybs;u5ACL1(-1QTqcIE7hm&saOZ=2z$ zzCaoB=4w8Gp>=!11ZwNGFI}Bmv-S#J#*s4i1d|3I0X>7me3Sa6ph7bMMh38{?lh9a z8yx4QIkMgCCUa|9Xi8WP7!=Ep{k=KLMFGgqq*A+@KKswb*+3Aea0SX+N5pk)saL;6 zN9~3POqhHDxcRIw6<Ip=?tL3_#+}*5z{~5_%Wf}obU`qz_$WOtYk%9M;H|5PcY3x| zF$RMsTu2$E5RJPJpS<5Fwv@D;RcH&Yz_@UJ04go;1%(0E2mZ$^zZfsk;RWV2N+Pyv z%V;G91A4h6!6o`aJX|bbC75&y$}~s@BVz<(1U5h+j1gG#b*mO<KA^zH=}OjECY=Rz z8JUDBbbcr$InXisg-(=y2@Ex!KL$}iY&h@v-E-;+A=8)cusmc2VtjZW&o$m_=v%Mb zH{m`WjQrP!)l8=#YWbB^d>A^h1%S`vW;{2NGYm2;Xa3!&e60pu4+zkNF~J{(;f|R6 zYFc9mr)JJ#Hc81#w7Ye&hByYYEf|fM?5_ak0HMh}0(&@tty0)FM|?zPe`uEuBVcy* z>?#QZT@GvMS_auGG>|r<QF>8vL&*OOjTApjIAkW<b58q&vB2Bql>w&H2BOP;xO5nw z#WIbIV$H0uNv<1W&eXX1+#}+{caTVvLm;K*M$Vz7K~JJ&^NFk65mQZ1@{PDx6eoOQ z8vY3^n%DY0)^0wKOHEw?ndlDBWbFyI)nMprnde7ayK!x|Ik6#&DHz6Hf}v9~mi!Kf zSzYr_gCqY}?!6+iz4!I>l2}$&S>YCwsV9d&!(A|Je~f`f-;_1BLh;jF^h-?tCT`?< z$hVW$4!gGU>XsX_bEMDZUn?^4D<Vhiu9rKo#a>?Xt@<pkfL8%j(-v}yi4;)N2ur-3 z#tNmx=#3kk%k-jgxjWv;xil3Fd!TjR#jJl^MgTFM^m_yenc%8OrTN8dq}C4la_=Ud z-uSju;oIqFde5=WeQF@tDHw<c1v=hAJ|!>`ny29$e|nN}wN096L<q{}^H}&l_t8y= zZ|mx1n!^=b|Grf`5AR7b?6x%J1Z3n>&5VH+?U%Eo4`p}z7Od;EB~Q^wcAXSBjC+N9 ztlDM+GuEz>K8MvUoShSLkNU?sS|$cn{N7Z{PJE&&!lmf~X6Chhx#^Atjhn%ML%=)J zD!~2i7P5mirD1vA1FIicl4AWp$&bbfLCyM(>WyVKJ=$bxHLTbvP4+kpX|_E&`o{4d zaVAF~-6lV4ZL3X+{TiXd1F|8>X>zWSiZ3@O@laq^1&)H)TFYgjZvFcM6#BAnA&}R9 z5u9h-FhT5&>cv}M<^LoYIy^9wR0u9~^GtA%@D#RiT#KZ!sRg=U144Dh{=OxIZn!+u zzMzL`DW+)a7UBZg@ZX#$Z46;_!#IV8HQV-uOti(k8CoSd4q_AnM#z-DU~<TGqUe~f zZ9DJ?^nIC-g2kT;RKjOuNiCWIcZygjRKuDK_bR3mVIpT%f*&C56%@kc!24O+ax|3l zhFXljdonj4l!v89ZQW@`Xn94%frUHoNgRC=^ax1INvpcR9#H?**S<|Tz+8l}IbLX- zd-jv>_uS=$c#7Q7v{fLI%Ik~~muW~4UzbFIDu@(%>#Rl=h<(rZ5WdW2RJ~=wPDYF% zQBCNAXhYST7_6Yq|LEjkl%`Tc;F_TCG2#lv9v^;~%fkzHE3w2pmbi5v>?shKZnDeq zVfWC@x&poZ>;PJ4Qb#bs@O*25>31BRq;Le5#GK4?d9yX25+HH1;6o6|fw)J=%>D{O z1JTTB_hz@b`YVoJS}I~zhLstso9U8uG3JpCKJ0Nbs)s4YB3q_l8yHQ>^A7H#DopEw zRNsOQ?Jpq20qtD!d1<vg6F<}9Blcxqppl7*@4!b`jXe(4Cz|_{8`?~p?KZ&G6gE64 zK&zW!XN4;Oee9EKY2;j$&ynNJ(rnD+wje3zFtg~mf&=>BlMN#T?#<-PZSpA(UIS#+ z{0T1~AJGH(#XI$JleXB99dBp{%teq~s{95Jck8RY0ohUb)79;&6OJ`{_Z+x@1@C74 zwidJ$#iiMK(45QsC68#wquCDS69$WVDq?%}@#j~enIXR)d=y_}g})w<E|U_lZtfq6 zasMRQ8;GCo`mK3q|3|#d{b7}*z7#+ZE&JK><tY={HQO8JRVx574l|SX+{n~V)}o(X zUbfT9Af5lfm=ld|Wu%>AC$|GbGVw^2zoY^GN6=kAxe*qPRd--@yX=Xs$Zq>RrNL78 z`>+|3UiY`a(^10p{$kz&fr#J(87yB1=%q`AkoV-GrG8vuM}Bb}h54Ryy)kzHn9p+Y zn>~*4Lv>ARwM>-9G%xC2y}ZBux*#SN^*Y-x=3+y|Pha`r3i_uvwcIK7;j-Ecg*GZu zUV4%%POqo@t?OJ$_j#{p3%4AriI7Hcl$FD-)O=&L_h{Kvcbn|hbSa%Sa)(@DvEx%` zEcF#fs^IdsH-Z<(UdTN1(5;F8{IDne%a=IthCeB(s1TNgX#1@W#TNCIyT0_&Hc|1p zC&q*)bA3-@@kpNAwP|16HTic|Y2m4i8T0JVG+6yJ=J8^Nkx!lc-pOStDUl}VBZA@x zR$9Yb5-4Hzy(B*?{E;wuG25YZcnh+t%Q^3Cor!#gr~?<*Q}v#39F8!__G6%G=_Y3Y zXS2F`Gp-tpP#wv}KpU{<05Hp&fD5QZALWo4M=&pLsq^YkhI}FXBlznPv&wG4K7ju) zlrc}kp9QI6)jrx=?sqhDc<-^Hhrv5tZAa3P%3++W0tI_ewX^azU`CnNgh8X9O;^sK zmq}_N!t~ZeP%cy%&cSf}(ixIC<H};n7Vsu>OL)m7&GK;G+Xku-(N9<nl?>69!tOXb z-VYuDnFYNPAt0`~sn_Ir|A)sVdIg*GhWBcOrqY|TPmOfFLoe*Edm6FM9}{*c8}b@s zLqzm8eKvtA1aX(|N#!tjz!7);jxhkqsQu~vn1_!~Gm`rQ@V_x?QZR@T`YHz@G$KQ4 zXx*o=_EQy<sZ$7w#P5jU^NCZU9&o1|F&55gV*30hs2$)7D;Jx`2aMqJO(c5~QvzKN zlwb)tLVc(Rd()=CnOX1ENk`L({WBunoTbF+6t{}ewSKmYM&5fD0d<u@ZRe&B${E+u zYF`_i(!6%RnKz4|_}jS2saYtDh%m}rgQOixSToR3G6v4ruSRw`sZh{g_1C4;RRQhE zGvL_>?>&X=@HRWG*ENa(Q$&?N%08YJ!9-%v62Lc_7(NVQ-m@^2uc9O*h3ynWhe!i- z;!&;PUYJt-4^^&MtocbT0=t|GNww2+l6xlr!<&x?q>esiqblE&cFbQIKFGjUo==RA zVEO9$&prmAy0;?w&o`U2o9vqA(2q;G6+X|pPl)OLFJKSQ8N(X61cdl;8L|o_mUgB< zl3I6lm?{a?eRIKH*%k>X&TG5i^5L**?<rYYBT^(|)ij!u9VIx)RefP)KDjU$R+{78 zHHNMiU_`aAbhexnR$J#BrMRCt0<F4RwqAWp(ea2==O}&coN2VhaznN6YtH3(ICo*? zEKCtgrw5L0XtVW`No|q?h-#d@9#=b>F`zyEX>mnHcESPRxE^w(zOj~zDv>AyPVlD9 z)nX~#R)v)(CG<Xsb%`0{Gl|sP6Q*wayY$6UM~2Fh3RgDKUX>dF*m0E?1MC?71J%de zDU(zf8coaEm$*MkV&H5TXtwl;9eI0AA)qj(A$bbb8*Kc2W<&3vbrOk(Y?87nHv*uH z_?gQ!OUR<q7}JL0UQjxTy!wl3EO{m2*;Y_4$;0wZ)Vbt9v%HhP@R@B|7aQE72;0_d z!VxEb?9%cMb_BhNtOzAWAru2Zat$~hG}kM?9l|tt2`3It!Kr1N;ot{pEX*0M7kKu{ z5VklC6;Jm|HdW4eL=k+ecN4!5)*|t%5Q7%{1z?dxY|KXa7FXvBv9K4(mT&jb4{i2q zv}ZkfYbu<w{jWNR8X|fXJMp1Y5LTdF5ylDTjAZ4wh#L@omk*a?R$-dVqo~VFJKngL z8TF<%4h6C4#;?7u!O)fo8C|BSJYx7VoK_7u!zTi{Ak2hia8grJ3T-7<XCe&qfzS=D zQ6Pe{vhX%2CKobdQ%PZL6kh=ab(d~npEHP{>+MF2RL=3PAEwWPc`yQ>95xqFwU&+3 zi9lT*H?6#g`7zmag8kB#mD@d+MX(eQ&>UkhT0BA2-Its%x$oM(=}z5+JG}Ap+}bBD zcpmsuaYrolfbtp)gBLSmid=$c=ZZbL2U}*k=y?oWRCnW;TW5LU@IKUM6-LQO5)Tb% za@z|l#VuCmz)egh&t#!c5pU19^pVE(9FTgbev~ekQ&f=l2}%npyz$_9+$TO&&kY(& zapL24J!LQ^gDFfJYgP^4|93L_H--Q&Zj~9+2+C%hxz)-HhsED3CyEFsVx+S&m)%O9 zV*k|WJ59B7&!%v<v9y5x5JWAwg!<>G!Y|Y)#UJ0LMbAYkn(yt;OiV|r&=+5%jv1Yo z#u(J548$AwPm~7aYBn&(FGLspY^^9pwt74yWQ{{~;}uP(Y|QVHtJ2*HxiBe`|A<Vg zMwET~5OPr;&zQygNx%4_pNIX?4Aa4QYseKydWvT4qMJG0fGB@=j9+O1k#Y{2+QuUP zB7;Bt;wG;Sz5lGQ*z(fS^k|ys9$*JJ@GxP;|Em$!wi$zINUqg6_5PUxz_%5E=onlT z$(GZfPD-hOV?>Az3Atgrr+q`D_UPwS^|!6ip)PMQGB!|u5tJtkhPUs4i)Yj7a8^mj zDi0hPLlRjAItud01cH=4ol8s~WbXo_NbPtNZXtSA)j=(|rnlm0A(Ud#mECWATM>)y z_Op6SW`pBHNEiU-$SFLv?eQ4~R^=K<EZ2}m*!?zsu?X&a4cLjDpbDZYW3H%G$1PNZ znyZZwYITLo2Vo}2LshibVCn4?pSv1empaO>nMI4SS|A56{>2@bu)uXp!dd`*R$>u5 z#i}s4Ib|{ya~k!~e4L=@L*_EEY9!JEY1o*A$#n68yo*!I!w6{>P4aoFj7<Tjp_6y1 zKYdGNU%cF?CJM5=1eBrJU*2!G$-sqPqvF@VH#GfT<}_91aGDoKS>Y|Fq*{A4dp4mD zy4s;K+GHZ+8R_qR`Np}SXS?@bmNN=|a#q03Ij2!^-WXVXwl}k=?wxmQrbX(=XKqZI zP-N4cgu<~Fi}^m`4}Ft{;NM;83FaX0ZLUMbW!;J#1dN2n8id80oc&=(4_7}22M4s= zE*Q{-rm81Bnr;Q^Gv5K)$>i5<>6hj$HlfW0*QI`F<kFNYAQOHuXc@og68VY=cQ(Y^ zCx4M+|6y3bx8;$Bch1>7drwHU_rJ2Vw#SDV)0ZqW|L!beA5p%rYhAd@a3RWdN_`>R zVvR88TG`V#PtmRR@9*_=y+oI3`_4Zv2a|F}Jq_3Xa`WR-65r(#DZLnj^Vh`YJxY>t zM&oizIv-CWmy${VM1PKo@-Z$~n2`6&dTWiNhJ{Y~P3v;{Q*PF74hL?kbcpt8l%|Hp z5>pYMve_A~7}s{`l!-x!(9c4U4>l}iSs!Xg>6WxamS3njL^E<ca8*SW#MG8*ou9sf z1vd)s0eo%~71Mz@c92Ewzi0&(o_`=YKQkJZgfT7jyd!3yEdYF2MWz7UE1UQgH6#Q8 z%|1nTQ9T`~_yB{ZAEPh==Y}fuo+%hq$sbChDtT?dTi+H)2y48I@X)Wpp`>@;z3%ty zX8I(}XaG@e)I0}v#~rE%6d_m}Hx$2wrwjU@c~1clw+Fvu8sH`JMlhL3A}R4;tnkM{ zxP7jD;6UvQ7t+j@5Q5TStj-d`=}=(cel^Vm*``hi)ti0$=%;cVT`9~|A0KA2lK1fA zv&WzXn@^;0wTmuOQ`Cvc{omTWMx>BuUJIAD&MZ`l{N|=T?gKziYeQ_#*IgXIM7TY9 zuoYfPc?Q7+X$Tdp>uiTR2vnia<X7F`OzmTn@&ml<??SzFON(}S)Ks^p0G0bTE2<*6 zhB+Dat<D>@D5&3r+mhkC&o=_DK1!jSXrU^qsw@xXmpQtoD?x_UH6ZcQ$@b0Ra7d2S zsPH~6%rKIF{cDnh+Dc5pRkoM()b`Jmpz)FCiezs^;}M`@hdsUdBa)y2JZnS0orbe- zmD_FBF?qoPC!wQKkQRpQkiF^c^#K2vv{4`2`o&`#5+f;#D}g4+8lch`KDlAi5I2JI z5VQM4C+@SiTtf!oAv8)`*^9fk?hPhs6$Aikg0}fkt%=m(eDmegUqr~i7mP44Gq4Th zxB!MN;IwwCN$1?6@nyBHeY%8U0sG7$@z)HMc9yXB6uR^ypjb-MJ@W0EeBq7s+br#z zko{5e@O-h_74WYn;sKf?frD7cim`FgRc3Kq*5O8Q&uiIra}=lkLn{tqA0Pqb#OugN zM{ryaNI7QoXfd$che)q<Q`JUFVmle~N)^2<sagb4wW;S2u%O8DJEZ!(6Rppo3IOm& z4tFn2=)#3hO5}hZY3W5OM|VU?tVDgg>XKWm=~6exFUEjawP~HVEptE@NNTUY`)*_S zKVlmHcPi9YM!^KXM`|k2qY1%P!b_MDjD#}X6J)iPEq)6Wm7W5BF8(Ql<yefI9t>TY zBFBTz#MWnhuM|7Lh^>tc-lxRg4up4YFTw@&d4oMXL5(gM!q%UWfFT1v6Qo^D;nLUZ zECm98!EHgDD?mJsTct(68Fc-Df~QLr`>UKYW?mvX3BiijwV)G-hsfIG{WoUBkp&{E zhGYtok?;dJ1xuS(&gskv^Oxdm2-QL0%}b&QLeJLS$YEgWDk1eeCQry5&JwR4Gi-1f z+k`CJjpS^L%~+Ga@ww0b#!pyBYK(hCP9~Z{AL#;i@CN|C<eBm7IR{X=xx<Zd4l6%q z$_&9oB+`kR*@Zn=CPpG9MNFo^(s8cLkVhOeFbIbC{c_mg@AvhXT^O$P8^XM&{zUXc z5YY_bI-f-Eo8gnByl^s$mB!#%%AaNf=!Yfyh1vV}K)CB0=$Wi!iapv)FJg=a=lB!4 z=e(^WYjzcVd)-v#jllGoEn>Q^;RnzI2_DUyq_{X+le2Tzz8?UZqwj&xdk_uLcfj#V z{SvP5@s#P!1t4GP`_KHK*{5WxA!AznWftp>ocFacdH-~xEC!@BVfZlN++iU`Eokb? z_a4Jr6q6pCqwKSF6@M%8KcmNgQR?8bP+oKF1@E~qMl-6DZE^qL0wV1j`sy^EyRU5~ zY6Tcqx={dt-RzurrWRS?Zx0y8i_HSWD|<In<vf=gh*}(N|7rnrpLUV0-9Ojwk?^2f zUXrC$@p}!ff$f=+%7N6y;Mx)8%YO7`vTTa>+uw%AH0@EAgsQc;H%=ijveQ#Nk%dIX z!3)T#qbxWKR-dn>+%!ut-FVrkaZZktoXgKSfT*!rl=DQjAatrOM6VxFW?e)^${iNY zF84O>wy!Jpsyy5_DDmrNy7}p<ztgfY+#4K2Sls`r(SZ^!rWE*OHx)OG+5UmEp>Qy7 ztZF&ggl|TK;)Ygby8yWD2S8kBwL_@+UT5R%GeqjdP{N{a!l^}UHDHvxp_JBeRsPf& zARA7qYBZ!yNOQFohrPWG3?){XhPu3f;^`G#Jilxp2Pa?HuF*>SxY5#uyh$kMJS{^a zqp}XryB<&1Sh_Z<@3Sn-djLN>+{I733!M)Dwikyq$u#)%X#2hcVfnu%y8ys-6SD~f zEjw`E0d1u#5=<X+fozj$z7Jp>;B3&U*ml?+`B#)dLO`%_+_Xhz6RUj`9v8XBb7d%7 zvQBtP{ikr^c5>`kqEWdb6083Pwo`8$eK1l)GHzM690orUD7NV+lrjc{0-q!+t)~ym zg6_CchNOb_^U^Ro1?K_KhsNaP`RB`D<1&7mdoP6U9=ETJ&N}Vu+pmP}Mm`Np){^S~ z4wAC=CTbu<YE1(m8{Xjyegavw&pJCouYIq4_v6M7zc<Gv<<$<Lx{t7@vm`|bDqT;d z+3_<p^{K*4cQHx$pNMrOXR_|;ar{r_{co{sPB9433}>G^6zc5oXstEi_jR(h3TKUN z-|yk1qRKK@nXufg?(S!=Cdv_I515TAr(f$HHri?gH+Eh3l3vcAp{$u+cYcmvO!KTG zFIqQ@q&MGhuXdrc*pTscXPSibrnwbN<-xgknp<zaknY2T4LE^gb8{kb_5=EuJ;H?G zd91#ryE(!~4Z2msc8X1i#4^6^Mruy|R&|uFc}gis(Ls4SW|HG3rh%G>^NV>lut=`a zbk^?<nIySDNvuZ;>zxVir6YK>n@&oIS!0(vo$Y1pr(a_O0o(i^|DIu(JOW}#9gfc( zx7+@#!)s3{1vlW4`jQS_=QWu}E8KLb;BMP`+YMu~zuq@s`)$nxql1jM5j7)fb4&n( zk$eLMPnCX&)?=W6M4-=H#ISdVSFBGg>!$pkDR!V~RL1Zgz@~7C<2(v&=N0e<2(Lfl z%Agv~6djxd{IUrHAbV)iR)$Z8%Vrh4@&r_BZahq?Df4NhMCI&YtS{AXE05JK+D14C zddZDW;B%PhU5S~c6`rLCJ?9p|Qfv#hpDa`(H#Bwpn_o_FV$yGHizA@LB#!8Uf=uWd zUOOGa!Nv=ejZ(M){i%NxQ>C9iMw@HT4Ly#_s}ok_#WwW@3?Y&cywqbOqqIopT<7Gt z`g=ep$*3D>kEeaL&3e>9i0XH>4*<>a$ADTIcq{vtq`H4-VTNF!hbH}qEk<JW=a<U+ zv%3@Yz_D<_hfJZaZzZ)7snfU5_Oe7;zyU8+CErNi#1v%Z_09@`GGXTbeVRifeuL)L zXy+frV>ScZ=Cmy!h!ID*yO>HG#S9;Pz6eGhYqFplFc3!i<Ng8hDX9BPx=d2V)b&lt zuRtpdgx!`^fA4mZe89N&48MMP3e2{@0eB#7$m(%LdIF(Q%+m>l-mDFgPF!ezT|HtB zP-kmu{u%Q91)}|PR8PiY&8ZxxK0JP99W`fy4N?{6DJz%i?(VR<VP%>#S5)JIX|(pQ zIxbm>?Oj9KBG<D*x!Ttp438#TPxJ`&2G)bcw#ND2dVlL`Cn<P|d!4&Pi`I35#AiS) zvcyWyxq*4o+fOWgU_$xyfRQm5!TaPzfI_cf1GUED29hRw?|^yiBR>{#+*>K=tX_}o zct96bSdZGvy)IA|G_^(b7Bp8ApDzvKTl3cEGq7sQXfY^XzSl7TOxsRX(W{^eutLam zF?aWo2QRV2%e6$^eMqJKtyMtlQ1PKv80F`KSaFpj^S!!Xl4bwZz#+k$+Wu=3aee=s z+EMU)NJu&_W(3tZHa6x414NtNZJ-4D_~PvN4k?oi5F4oi<3aiLHgznZ#LG9uC=IYL zX|$lm3_iF3-r9wm;M#;Q1`mY?Y6Bp$UTsRGYcO)W#qU(d&>0&d&%7E-EB*;H4hZCZ z`|JHrM{3G345167Y!_!0hQ%?+21nv{@#euk!|pScsm=l#$W{&j5xD(<dN<O0O}F!z zzUi`Ip^xnA+sefFDnSP;N}#YsVeUq)^ip@g)Lyt3G~biv@prfz2G>-~E5?U`IZo;` zV#U#?zz50pjFCX{9jK%O(ZrU=AgZ+6%P+sGSt<-LhZEvjL>z)E;gL7{;K5MPZel8} zcbvrORvkSL52a&9-%-E!hHCjFGkiYdYLH0RdD_Eg{fFzHStU~h?@QOct(&EI^{`UP zu)Ve|Xh1OV)~7n2kzpJ>;)+q6kq{{P4{)Hv1uxg+E;IJ}+2EW9K1ppGpYE1*LPYLe zv9zi5ZxgJ;zd|6BQh@;++_RSptsfu28L}Q}`1C=ZT^g)YFv%3V0+*3&`{L69lk@~G zt@myrpDOmk&H;Ix1hM7epRy1xm#Yc1+THFyYA|G<QXh1Bg|z@$*Tg}48n5_&JyN|q z8=2p~0AF*(0d<|B(II`qC<*{(fs)*+h%F>!Xxb$9|Hx)01ChDSmGSY?-A}H)Lhrtw znYT;sXutmCS?x&YWmq`hCs8x!7-8Sia09-_Z#TPF*o(9dx60#$fzGDqX70>lr1ou_ z2_9LSWl`B~V{W-Iw%=yw`V7BmdJha28Ycv}YNyw6%y}PNrhw+2`J>k(U)Sr)lnJ{@ zp<NU(AQXlZPjVxm!BFy)n?qZgI7x<9NKj9#?G>HA^j=r=*M1d1;+I1SE!I?frIg3{ z_wfMqcTfI>sF<GEnFH0%>Gx3*uHuV6R;kgJo+6>H)2_}hziC0g<`EAQuFO{aKhN9d z_@`mBl<XA#Ps4^!k%@gw@oF$Usa#(8crjYw8%C$j_RWOzX#|Ou)JCCT7N1f$q5=ue z1|zUAQ@)Jb<Vkli9A3pq-t&Yn84W;urm9qGxC+>nO?|i~&@5=EwTh7)`LGa1%N=n& zy@4u;QshukFK|>qG0z3e5#9sj;|JC_36_cSDk;E5IBHKf1oC{q3f5DeFi%#Ec?Y9y z7wFM(@#x+6)lV|}8gJUG0KX8f8gdq&&dUDVJ!UAxr~L{QF7L!uy?IQQAoz+`O?85B zz@I%HCURXsBVCX=ff-EMPvMUPmxFA`m~^Pjqv@`Rux9<6{US;fn8^;u$_3EmFOi)7 z0N5Uqn!UKj=9}ZQO7j%MFZ0=7y|RFzNOutap0EUWX7k0#&tE{`^BT(gBB*ds9jli4 zI!0&YI}r5`hLQ>IVWuY^mQ$-^oEh=dRqj<1V?+G*=z<%A-P;^t5wh0i0q36HIf~gC z6vKPXy&^P)>p*)*UUN^2r_*|Cx>nw0piZ>I5SNE6O0ZnAu3scrsyvHXAwq5C-uHY! zr;#@sD0}!uA(vzPB~^EY`pLW2b3U`^{?j~eAs(kwCkl|yn>jd?-f#A<{R-5@I~{GC zo$R{_cNd?@0cBgdaw3b0FJ5ifcp)+Y;P$b&Nh<r~2WVIe693roj*l=7&S(5_g;d&g z+uU=~(30}Q1blC3LJ1qflP!qd1}caZZ;lm{!%Kn~n4Ou&=Q|5OR^5$rha>XPj6sK6 zGvg2Z4ksn^bpbs6?}e11ods$MD=X3ec@zElje-{2==JZ`v^q$~t=98(ar6(DA{!`y zp!ak-db)7WklxH`K(J_e;r`v2Hd$1|=NDeWvs?_@>$wItV5m-*OQcLUpgI{xFzY0< zjLQEgcE;7atdg_mZN7w@tD-J+EO$FxDA)7c(<eOPk1E|q;EvBrxDX`>A2PS8N}99< zHjl{SMcf3QeJNJx$lYph?q1_swaIsShs=!Kde4t<o+7fligU!ESNh0RuJ?8r7kjA% zMACck)=$-ze?%m46Z=&yi7#Hk?f}dQLUezCrNh5q&=$~&Pk<9`=_&ic%lXfvPVnO* z#-6r7a8(ImGlEdniW^v^M8X6JK+6nY*98qyKlqj;XphrF!a+Y`1nejNp+b_tSQ@`t zw#Xb|+b=fCnuH41zk+&`@kj(8mj02-wH=LG!chyRF}VNMc>~k&5p-I6V>3u+lW<IX z%N~Y6m4Kbqg~7<+SmJgNetGZd1biwwgmVI|J2YMZk7mW!7ztE5+?Z*TcI1BG=dcVf z)21MrXUwlKlI!_Z0Q4dM4cQ1m5SZkG8FgR{BoeP<6jQv!`2hVljBo<>^G#S-&2YBl zIPfUDFE7|Wln(IrRF6$;Ah?^%*A92)<jmx<cRY9=%-j8Eakz1n)+a8lV-*)=Rlo6k zg>fmoUJ0ltRFL4gCB$H)w|FVivp)nR8**842U<a0fI!jhO|@Q#hJ;2C27bH~eLe6% z+Go$YSKUZPMgExzmJ1LhafDteN=@8eLSpW%n{Z@;-;hwR1TKvX>mx7<4Wy1)N3QWy z(SO1jxs!>XQ@i&K$C6fFaAYO)o|pz^SnBc-u8w&klSk3+kigTdCoTB6Zn*Dd6nlHr z4J+IN1%3zS4)aBrlQK}9$YlI#?((~y8UD>|EA=Kf?O?So5{scZ7%Yvee99-;9eY3r z#qY5B@p-zD5ms;J+D$3H9+F#uc@)=HCb-=SDd7VCZ~7evfU|XH^gGan{nqI{?WcXx ztgFQ-?;~pj62BNmX4xIzW~#lJy~`PC5<#wLXQC-e*4IuZF?q-tQLCN^$)8c!L$A`u zGmXrQg-S&2?sOxa8h;|pC@Bx3UORm<O_Jmx^Z0)M$->l^Ti-=)-xle(HRqEPP`24s zwsZNxuJ|;YTPuC(au0B(iZ91MFC1#45+jnC(5=^B!Q?N+?>;pDI&rC6p7EsVHz5^M zN~=CUoHIW5=KpqArw&|IMvg=*{jM=MiI12<dnfV`eO^7DIp|+9`pSO9#XWz`5M6Y@ z1!3Z#ZBlKTM<)_hq7PDkR-$hduu3m3nfuJ|g+8vTM%OnzqARZTo?c2edS9F6`&l6> zF!qehTy_+YFNdgZZ_O*Nli|Ip<`F78X6~Jw9#Fpa#d={WEpjb{PEUhR@LfT5R{tWC z_g;zE+F-7Az1f?Ql_bmRtRh+t8s9)(2KP2btK-m;rtZg^ckx=ztZ>wfE0>=^yL(j_ z7-gw^?|rVQt=pYv?tGjhm^hX6Z|nJOj4SNy$9E4iFmBv=4a}n{5Zt5^3=Yf%h_;3@ z`dg5Pn=CMp533?}0H;A6!Q%4~&}(<K70y7*Dl=&oTtZXHJZk*;=}27an^><%VrfL! zZ<^LD@k{R|^B#f`)J@YS(4%DQs=-+XE!!L|Y1OMJJbXU3)Y@M(c7??k#*U>BToxTd zS5Rz~6v~seMmd1}cK4_C+7g1Lo$#B4WKaio&z2)lgC7Jm+WA{JUh6i)FzO_W9yJ0$ zTk+R<g(sXuO?BT{==}oFpx0<5p%!HNp4Am2$EnK9pcdh?M-}O{6*CJ=7VF)s4kq>5 z6d;7sPv7KV7}al1xgNax`>hw_LiDY$gIp}qPyi9aar5hSDup2cmt9D=ic@RNjlT46 zZ^1l$w}UQ)Qo`uNsOgPMQ1YpFrxY#6E{LW$3z(nWUj=EI28U_;6YyBRKX<GzjEZXv zagW%xes6yj9}=JQMU))918n$d(A*fG3pjhwI~N4I!^{@%4!IuMQWOzlMeqQ9|Aw@e zX^Bq$Y%9mz?`e9jC0;-3?;+d#7A|?T&gKm$lg^_f^~cb;L6A*^BWA9i<e}|$ySnM@ zQmK3SW6<TC>gb5JN<y>H_5^s@4T=2S1Vv(eiq}5_JkS)@yDb&^j`Q-GT=2FQuFC?% z-1PB_=OZrI5c?PGU^Db|n_-M^|A$XK{4Ue(UF;72&*F^GH~K_PODB41Ep83n(G`&R z!i^0JB?bNmlnfCi*-wsj2!Z)wZ?}n1^y!;e?kjq99{VO}i-%3-$NJHP^gRd6{S(GR zX8bfV-R<!nE5T>`*?76Nv(uXAzJ%4ELxPL-P>}lhZ`EyMuM*o8jjx6F`pz>Cs=ePG zT}Tq>r{-~$^GYV>yHMQ=kGMIv&axEb#yhG@x7=jj58y7S;SK2eV48JTcsOy(I*<Pr zy8@L$G4);n`c1)0$%hn7gdW%mN*&h!Je_DPFvxT~IeO-biGV-{V(g?D%<Q_poDF|l zeaK0TNp+LOG*Ib~|H1nZpS73oZgv)Zx1R$QKz;BI5LQ0D9y^)fp5)Y)b(n0XDlA8> zL;aZoIJ560X?t<qln?zbd}m%W=!VcV*E<SV0ZcAZKhEinDA7;GY&XnD-cy7JtnGdf z;-G|I=eSstYBkIyCzWW39KVYG5c>T{l2qRPta4TUGiyM#OXBW_K9=ahR@1#!A^-9w zjeZF>`#N%&J2hZjq5h#uyZ?B(mW$oy@i#`Tp0QHHCM~NI&GYAPgldb~A5b#YPh<~J zh9u~alxhZZp_hOxBNPbX`Eq*~TV#xD`~RGh-U*;M-)-qEeVonNA!8r#^LHDUH_w>b z&1}N<Q^6f+zVk~r{Y#aiwu^V!Pj3FURsUEesfN2)-@Tf*3gqd!2>w14_J0MBMjRGx zb>tgJ2x;Q)2hDw1>;hRN$(~$mSwe5J=XIf2D<{jwP8!!7Dq0Aj)Jw*$_RJgO+$40j zeHEkfC0ASvSsAAXp9sgv)dZ6;>-!$71(~By$V|nKv!l*eg?%aFMa8%3uO5`KNR|&s zh>*c~4VbRcUC)agQ&B;7KVDdc79#vMMi;Z#0s=LoW$`Z#R<gXC<c3LFPNwD8`|+&0 zOGt#2@$Ms*QHlLVm8;5h{Afo}ftfqHnbKBgQKN%usLxg(R1pa?qo~B*+#3>)zZKF` zElvL`e3bLpNnNlNG=CTg3_$<ij;fAyfnRixI!o``21OwH^bmb+UDHrJ#}X+E8D`c| z;MJ^G?L@^?zZl-5Fa9SQ{<ClvnM!#|*d1D=5hP28e$9P#tJXLXbdGyP{i$Jn^i=Ko z3)nITHK782hl!Cj%v0G$7aPgBv9hvk$!14UB#hsEE6|A#B1lMX_uJPp%T~G#h;nqR zC=)Kje7n2w-0$GYvdQfxy04tLruWo0-S*lGtl(zR(Z^@Zbm0onxG@&uiIZxOE1)1% zpKzTQwt$_}mXx#T6qB<W#OK?C*7v=KLWm!VzL51jneG?Apvb+R^guQ&K6Y`CB=l;9 zJjzO()a?xJV_w@u&R(bVQ7brH)@MHiKRND9^TmbbzYdnXtC+PT`e7jO_cr?P^Tv?@ z<D-4XcLa%rm&?P!vfUr<x~&T$Yk)<tfr<$z@i%OJ<NIrAtiuP%&awGxb2~Z<L!ZuF z<`kQ~!pb+Mh>4=Q0)-uaSyuhYGIg)eY^zxnDH|di(y~{xk^Gd;&toD@;9kUa=~zm0 ztBr(_SdtZYC;#=qhp5^+0>7E>AKV<=o?k0G%u~!gbC0@}9=?STPwYWYp6yd}3Q-;G zp?Aw!=tNVO6_cmZ@yDhl%%Q^9A<+6`1aQ+TXZ+Alf|b-rVi~TTxERfGnTb=msx%mS z*(`9mUdH%=OU&OBXQ5xt4=UMW-;^#VejnxTV@<VKKJtE9E<X1wc``YS=~D_gvw}M0 z{yC8IzF^j^a?Y}P<o}8}Qp~z7J~+&bf&Wzcvu<nLGEQLK+<>QhLcv1IKPQg{53t#` zyw^1Tu;kCp{}yJShh=GPw%zERD5ps*rj&GBaw@@lS(|6>{_#rvZeLxoK-M<~>HgF@ zEnbfmeaWwhsj4mWYba9T9tQKwx~&EIH@UYm5A?;R$&FEo13A}|eieRZYx*KTSky4D z-C`f@cgJY4zu3Un<A!FYa{*B_;ch{6=(wFLl2bN0e7+8g)D0^Al7LCtV*y89YZ^*; zFOXfflI)~bF=r$i9mO;E9zVu&A0?mbqni67y0MRvQJOz?-!m$nUM%4(ACELw)|esJ zr&EzpuHKA-$-{rSw&XE`xWDgK=HGj4f*-;UfBpUW&s3WKY&38N|M>;}Uzw2oBk1d0 z_#>yR)-@;Gn6_oiO1Wta3H{llfwL-YSD+06@gEg1#~hrGMMoRE<CE*hf~7my5Tyky zrK(##69b|pB#F{Q@iLE8-B!XolS%ffCd1>a_*ZO}j3sB*?JLl`Ox@uEjB2}sBxhW$ zS?TB$l9{}+W8q5~V>&<8p9zEv!f2Rp<xAJc;W4$V111-Ucf>*@tEs1D1v>rkcAn3C zCBY<BzAO+83udbL7W8ym8lkM4>a)JREX7<l|K;g%H|!hl4<-p@VhcF?De<1em5Ci> z54!c~zSDV7nEQ`1zwoeU?nm7Wa9p7>-@Wys^1y!IXOTS13$-cey`GH2p^;Agf&K4E z-VlwsD1ZNWX7e{y`n#%N`E)*j70UP8sWi65y+;e-meKh-ySj6H1DjP)5-fQ-9l86z zLiY$0y4!PB)uWhY*NKKs=p#pYs-7A&x5TEoy>{qNHe&JHVh<{b&fb)fGqa-j95}xa z9fY-F#WN!FCdusmE~T;L*S&atw(q{g)2imEgw81w|9MgspVhvia&)3$I*%93%WSNh z_|;7@D&g+v?@CQAzI|areja7)*|+d&u~f<VA7^mprDj#2Ax6k0{c9@W5|DdBpLNZp ze4;=0tVh**^*f+C@A%%^=xene8(#5|%e=lyl#8w)LR3Tx$%@LItgoOx8~R#5Q?-pf z4`pDG@|{QHlOv}7eJ6PRdB`94tB3xt{Yiz{pT9mH4#dEn6#wkcuV=T-!8)^J;wsq+ z5%<pqosh*u>-qC7O0bRqo<kb=i~#nm=P)jAiUg&nAj4N^biBN58lCoTx2dlotWPL> zUcM<C5n@Iq_a<3;M(ss!8t;=0_r$eWftAL)cnmEGKb5YoghVsmQNw$%H4zoxa#nih zszU{ONSxzX0VHFpZ<Cc{&$u{ZZ<QB(D#Z1Wl}}p9pc9UGaJt`L5DkW(SaOQZ9-Rnr zY_7|g&%tie{i0OX==?jywW}TPMO&ve-Bx>tUkW|!GR_7+`zo%>qeDhJ1>6p;-npm; zEiR?W))qyR^kg!k?4pbr%-x*V>-g<ocze>xSWokjvu|c-_+I||ICsZH)av6>s=urH zcb{VJh;b}TR9$`iCe0rA9{!(rQ!n0j0PCbff>|^?y6At!n=R(682)ij;Llf~GY(Aw zzH?wA)B%uAEqBe(c&Hmx0(%8&VeBLKnx>ca+_^5zB&QQo_o@;T12p{)yS(#DAXpyE zu|;^fcaOiKnZ&3-2r_<@X>lGc5|Hb%`?dUZDOgBYmCp}7z0pD9);;yi1Wzg^k*8YL zi=6V*vZaesE4iNiyel4hyZh5|l6aZTm}U_j=ka(KE`iXz!{-~U;UllG2=vU~*C+HG z)V5=k+l?+(^lK+yvF;+oNrj;;zUx=pf~^Ja_e5!zqt{=t<{q1fHEAz*x1dV!?!2#{ z{pcI>@PoG};GzdS{r}8u|JRA9Q-E1u<tG(sHn_m+2eV}f(&o8n!4igmogRgS`m;kV zaEtN5wIQha%~oLS&z5z^ETKJyK?^Wm21r3M{!AH%y~fl*KDxd%_SS4O$CZrnSK4<U zi}wGX&Q~;VndnHHYfjZh<lT)nW6N2*tIRVO6<>K06;8}1x9%d3PGFGPP_J^W;(5L? zPL_PU;@6!_vd9#E>uD^9YdM;0%`jcd_SKzveepZdqsx;B-rd4ZM1qsn;@bO7a-Ott zV~tr~en_hK?v>1*<LqUQvYP?*>x1DvQ6tnH#5rG-bRi_Qiz|<;IRJ-@kZ~`Vc%O_* z)(uKa0F#oH@j$ns$l2RO{@w?#O~J$J)V=$1P2|s6|34Nj@P;zjprXF+A8)aa4#0F4 z0%wiH{IsV)5>JL%Ok7UeKkrk_1j!A!@IhnT{D8vd2SEV2yyd|Dq~+Ka(?RaMO6v?q zAd-D2Gg0*>$X$#q7!Va>;jL+d<Uf!eThXW_3IrrXk?$V>Os%m&^ZULisLV59oQB9< zxyyaIv+tuKVbqk>C=|<DrkR6ViKHeL%SdLk10~j|LSO3hSfXbvJusOQv|*0K(Lm=5 zdcKy?;88<HQwDR_1S_0=l4oXbbbar2Pe>JV1VoYKqBA+%dK^)e-n%O*LX;d)NjV4I zBZq8?@3@o3%VGkA#un>g)4;*PU-xdbJe7j+$$I_>!v2cb+2S~KenHV<d{IRV!ttBD z`wBf8CWe-0ypQTm29nS1GV=~q>-$)d)mgNrYSrF9rXBsFDowh5kK0PL6#JG&IWA&Q zn{?Xn#u*MKB{q$JE*7vy!CDqSsiv~~Uj-;;=Zi*RuAzgTXQs+|lq`82I1QC9_&IOD zU+!RD28EHtB1zM^NxcCyL;(mObSPZoqtKGxu7Bh13&gxSK><dEVFR&uX{t(lZBbu; z;PJU;SnMnAxw+w&#+Z4)rGx&S3kdKA?oOS+%kl-;aYirDS!9&*+%)Ln4q3|$kd*=a z-M}V&)tWJNo={+X$DhDv64wGOT513;t{4)6!K?5BlfD%L+GUX)jBH^2lR4S>ySV(I z|8ET1*5Vxzq^x7luA8~E*8o%FP`R@O5<Q-Jj93cLkK&K{`Ev-Uu;$xo?=cRJ1Ed+b zENH>IfY3=Z=4N%+G{dNPhhQw?n*o+_0prvG25?p;)`@pIjP5_81S*h5!rWpdx&F`8 zGSWe>^Qi>DN{eQ1&Vs?VB*trZBS)kOe1ga~k8w?#HA%PSK0%8%<eNQ&d_2SL4!yg4 zhT(h_;9-6pob7&lx-oXsQd3@|sLQ<>_;p>4;`jx+u4M!qn5L}DAm6(}1l^Y}pv!hJ zI}1h)1J{q6L0iRgzAf-js}4*~ECF;iSHtcMjlwr~Sv$lu>aP+!^#0_{XiorE|IPv! z$!JwCAcnFQr{01XsAs_4<bsdlLzfmE`!bC9y&hu0;~Lz06Zci{W%wysBH|eeA=vlM zNeg7HX8Oftd<BjCy|>tt;@nzRNLm){f7B<q4c|;7aYiNYi$0wpV|?yW8@wDawr-rU zm=|sibP2A@ve8(fC`Gt#9fc$9D<0I!Ui+d{Z^51+5Y=+f)l1@TA;k7&T;aI6M&4ZJ za3$Et-|8Lw&A3cDqmaE#@S8S+T5Q+7Ym$X8WZjPY?hhwk_iI>pA<eyx@Q3mJEY3rQ zt9wnmsa2=T-A(a~;$Zr=MGj*j`&TCQ+5vOIjK7<T{y$HcJMc*1%kyg4>$&whH>+Z3 zdw;9{c_Dm|6%*`yjGsxt&1R2zlhHBg*H#etns+P~yCN-t;w}lJ@2)&Id*fzVIlFuR zr8<CCJ?5rJ*Py0hTev)|4&ckMFjqHk1_u#49T@g=>6*(lU|P9&^d36XU{2r7U9T8M zsHXNa8&PwzSssp&iEjpt?+vyf5M(WR#@{4SUF4nMX9h5%CC9j8AY2Q2{<uq6=3=Na zns0YnFa76tBnWP)e^#b_^arXn#g!zn`MRJ3M53{}pYTJB?ds*lImc48{Ng3XSlu?= zGRy$V<X`kie{~P^3yYpBBocJdxorZO?naEqjE2Z?O5OO!ufVi<b2kc)?F$KmOk?_O z!<YcDO>4l+DqP5_rw~D&b0vzObDc{C9Jm_O0CqGG$+2V({x3@)9>TX907hO1@4?{u zIYD!?B8%*Z%}u3+E=)(#z}y$rt(?0YxXo3PP1XXYYW*F$)Nog|($l+vS9fR*b%DTK z2hcvgrxL2K0$6v*1Ajvm7#?`r2h*SzqzL$g(RV200epz|i>cj9gV8*;<*3+7dr%%| zGUZLlh6cad!VM8h?4@O3WJ$iOdH2_?rXTgYjeSMzy;7Goreb}Z+zBx+qMMzZQJp5o zOZ7>gSI;DPyVBwo#~1MeSo+iNYei}Eun@ClI8&Ox?<x|YOQ=)6$G@Dg%Pjr?)nK&T z#MrY}jYgMcy1~l4$cRKOHLsf=<0jr!9#p`_QHa08DJl2ckg&?RrZdd7DtYiT^NY4G z_b79{Sv=6!G~W;5n;%OMlWY4YEGVLC6SXS?YklXn{cHO@Kj&iwicJmn>ZUlS%iVHs zmXg~;>x;+J_HMBLS8dQ{MKWjnA$ot{zlwtY^baREAwV74=pLpG+>#*v_p-(Gn{VKP z>F1F3QS0St>twpN?f$pu>YESWHB7zKFpB#8XmaIl?KQQoEq-TE*;~viBMV(Vs<>v# zgT|_tcq@oe{UCu4MNa@rk*nPoV8;U4?7c+5<$J8})=W@+Lm~C$)a5~mTv11$%?nfZ zm#`WDj3^N*;gtbLmnDcD5@R#hJF_znE~bzD(jIuJ;g3w2xof6_9TG(L#@uHmwa|Ri z8b|A9BT$-w>^uh-g4atHtmCTsB9j8ZI=f;%EhIod%c;O*nZxEl_E{~xczwbA^29ik z;|$;&@?nnaqxl<ML68EaHH`K%+fg#14=^uD8-)foB#(j<-Q4&AQfJ$&Ew`Z+OtKt$ zpKI|<V{Bc4P<~p}t;TR57HakW30wJE7x4v#v}^(-csl^VJw2M>+-rL_v|;Mu2f>_7 zDT-Fk_M8rCEg%>rA%ygtQn4rrBFcG?bMrICR`D@tr+bWHRjX*p<fY?%1k)eM+tKqw zKMQ4_0Z^YlD$(P{edI1MBfk=bi{=fr%ar}Oc0i&<2LI%QVR);#8`8~U1b#Pgakbb? z!Mw*^H-7}5=l`MXtK*_xzpY6r=>e3Ep`{e1hi(J}1SBOC5mZV99AXIRE@S8t1qm?_ zq&uWkKvC%s)FD(rgm-^E=iJ}D?>&FK@1NrN9AS8#{j9zAT5Io=^C@ehtV}&SR&$qf z#!m=`q(~3ED}d~?D%TmaR&P?ST&s@)e|EKvqyWc*bEiRinERaO#3c12^Oosur@zVu zP9$g(_%?<zyA$mK-;QQV1og3XXEkAq3?H4+rXkdv;b@53Ch*O&{EDJarg2Og6MKX; zh~B;%G272-@5&(IvZ(JVxqkb^sTA0%WFJ&FA%=Oe#pgL6A9(gOnY&mo1+(*+7cxeN zxqVhBwNA5Rf?2DgNq8pIM|J7BUDQM<o^NmP1$$O6r5R(S0tPsoC6}oJY$WwIQ|UYJ zpmSW~ldcNwO>sAG<aG~y7me(hW7b^1K%Yz!`G?aQgAF$>|No8O-#nKQQpTlAzJ<*p zu$zYj$=s4h0$dElD^bhY;%XBBSK60Hip;~;L4a@GElBkZt?28+DSWsBB)Zq<7Y@OT z9{4WsCCFezM--*(c<+RQ&YlJY_TI~&LEzOtr&ahH8PhPm-Q;>LYBQa2XbmufRC!re zI5E?K!tW%FI4Fn>NsTq6OnA{o-q;tg@v|3CLYkJf9t@tZV(WUxv^)CjW%9VTScBN_ zX7`DW(bt!RDIpY$OLQeK^4eRG2S3QjCbK>I2NxiznR3tZ!_zD8y&$llgjt5w*0Uy@ zgQ?v_ekM{@NHmA}gcdyi#?$BI;R2HOZdE3VWX$Xc^W}!)7kQ}_0~TRgIO3N^tpBqR zkeGaL%Pz!m7%6=>)VT?9bj5|qESA=MdviPoJ=)iIk!352XK_oZzZ4;QW%xD;SsY!! z58Z?#j6qw=sky(E!>FSW;gJPCf5^T#f>t<`ur@ywH(z4opo(%Fke^GKfsck7B{JV} zqU-UgZ;hL!Hw(-qd~*zTQ89k2ZzWjd7{;LeY^jS<gMz~VBOryK&Wo;%U0w0Y?kr>} zLxbA6C$$_-vCTD_d{o#OpI8VS_rC2jx=xj6xKB{$Ia)cNu&x_&3cJ#Al}|{qqg%&U zJ#U*Kc#zp~+0X>LlP`EEQZ;cwb9X|(tpWyjtx~JPtdVxBBb*niyvw(HpVz2*O<A-> zvp$NQO>dH9eKmhhBrKMvA+}CB(S3&M*q(1|y8}^syA`)89nI6Y2rggVdPjQl<1wuD zd-2Ieo7$xuMfdKr2G1wBYuBcRIx{#1jh1K&9n9)l#z_Uwr}&)>lO6`jA#B~`FPi7R zJ=v*GmvY|O<AKQemr|au!#JEhx?rp(vN$es*dYthhdC9AfNoO7rKQ*9t}k+L!B+s5 ze}KKYQV$oI8TvF_aPXx>t!YpRo{k-OJb21h9)tkqW})zjQqw%0aE_n<4FK@bV}W`N zZY-g71}d6i>;Z~MRts%yZmq^78@p4&lrnibgfQLezVx#(Ka6Y*R)0vWK|x(Hs{rYi zXr&80#HY1cW=+5zQZ1m`u!)4$I04?zzW?9{hzd-UzMH@ny_I=N7BW+;8l%Q~BPw$K zYFhgw<36alPM4wdEFY2Q0fdMB7ekNM(3VS)30&Lp<$}}<pYPE`3F9}aAyYL<lTHDB zTDZ9kT_p8v%BNhfB=lh4397i1Q9Zl{q9gmzDVR`wB3F;%GR7Z))$^mJ)v)Jo3N`CT zm+OWRx4v9nV&<e>qx!Z(Tb=wTo`fv-+<j2ttr$dzh1?g3;3s4H>N{IUX>5|eeE|Z( zUTK#fzy&CFCR%KvqE;>|p|p)76`7iGrFB?J6jdYgW#Kq;I3;g5Kj3`(D*hLMGZPfG z$#%j81d45+*=w;A=ZnjeKV4waO8NsC#9Mn*J{et&noU^9uDVJ68q!!Z9Hf@dBy^~( zPSyMN4x`#lP20+u@Wal3-dpv23u2OHdStEinJ{TZhflx55AA%IHv-N)yt`A1pXqmI zI#+{!HvTfD(ym=!Lsyc_wJCz$>uzq0vMYP{)z;`)!_sXru@<_*!CwmW2czBeLF^tO zgyD8obSOcV!mmDKh`WLOXt3veo=haBnUWB1<Pjxh|0MM+*GztW4ApT33B0y@ZAS`T zTR%$*U!RgcM9R-oV@tr<<qt10$=BTT^h-}wPgtPgUPt9&*nFN$@qRcz33Hv<qN44c zU4nQ$wohtz)`?!UX;Jeb1)06%8lha~)OoUI`$kr5z%s$MtNXJ4KXWUb4btI1!QOZY z=D7cL0q&ngp!>rcZ&#0#RMHd2(LdM2%K(@$wMAObr(esgT*xjH<3fJ#mK0C-OEw%6 zB=OZiD#u%c<6ohiS)an?k$Ezui5`Y!IVag8mmu9ouVGgT`u-U(*IYJLwc-st06noS zuXj$)l6F<o?q!3JPq4%T!Iz!JWry~VjS}gcjtrI~Bl<LJDItBLWhmto5n~ymG8R~% zaF@JE5q%<Eb{}RRn4HM`15H7xtNK}`)pH;rqsEs$hR%TXVeyBh$$AGZ=aWC5)YCAq z-=!hv#<!*9QKqu-N;kvxQ%ZmVzKSML5RXgo{&$y(X{hzyJrU@vI9|vQ#Vqv^yE&+M zXu1J#bZKF_VmS37{6$16K%Tb!gprtPuOf<>-SXUp%y2ep(SVPJj6>S{o>`-!-9<6v z$_@Ts*!98((>FyE&eNf2_K<BG)8EZ$*YD14G2|$&L)vk{2stH+%ao|SR}kfq!M~`# zfw4BbR0rLJ;K}_@=K%khF}CHaM;P46n)iM{8f6YGdB_APoee${cFQL2KUa$&$@Qpu zc?t_~|N7eVXW&b-aJtImlNSBeWnVFSsuBv)lX&F!62dkB&#KDY1KlnUY-7&{Avt#b zYc?($rF;t>Cv-|VJ$rjwbB{>vgqiHiNhmLb8#*5En!hxc&T8N3b}V?o=S0?(HP-q0 z(1&UyJfmY+*W|=SflqNm>;{u<?c53yY)?l^&SJ5#!x6>8M_t|yqucb&^_ko0<NL2M z9cNXGPvAgvt@A(37YGhGhH?z!$23(_$V={~Tn)#@ODSP{^ZbsC4PBqDPLk@>%s!HE zCwX=(`p8^#&EjGDg9(u=R|WbzvmIA)uJI;*yjvn_EkBQ~e^v(OUhWrJWK87WGqua? z2;IE(<@@Zv*K^a^Xr{w;13uW^4}WOpyBx$!vAk@&vU0UQ+{j9m5u$bDXUhoy>(f?b zdfb?~gcGB5pHXZn9rljIB-+#<3evR(NJ!K0u%AQ!J;*Px23i-#y>lpe1IvFv6d1kS zl$Ry~YRAgS*U$$r8!tusGu_pvcDPg!^%?EhKLj!ea~yF)e)@e0XNnO2S-0-%{z=gp zTc1h{vk^a%mEY&Ey-W`UZCv_Me^|j3c~0Raekhhc6o`=a=7Zng;%N8~h?`M&x@`yA zugnJV_Xn^KYE<RQSCYtEiyCJrg*B@MFb#d0fy5-Sn`;3>2UCb2(HanbI$iHPI#UWF zU~q2H9RX>Rq5&--kdaUIu=1(R=wN6y%|3W^9fxh*OEO2@$=9Y2;Aav(oAWvK{hRS- zP?)umv)M5`x2nJ?jD~`Mr5!BdX}O(%6-o)7-p-^|@#}Nl!U_$0QqV+*l4*+|ir(NE zgT5|k79r{>*Z9!Pw?hus6xMBus&Qk70%$d-e5r$4LP7X%EPSfEAyk21A+H{Hv`QWG z^O6B9xn)#VKG@q7Z2!GIm+Wrb*rdNPzWN>dXrrIkz;<jDrPcV%w2?Xe=2-A2*g!sZ zB30=^FusuZ1N7g$*Ceg-e%2t|5lexoE3vmC6*(oE!Mukw1f@&ZS6ip~ne?-`(Q6sH z@YB9?lf~Em^A3E=Y{rL4^YgE3Huj{KhN&sMsj<~d6IQh)r<!+K+L@d`t4TnoV*)1# z^%m#Dl6;=JUof$wrp##IY9PO}R}i71b@j$o`ed1!Ve=;Cr*Y*^3X0^n3Z@R_u3hrI z<JH2=FQl0Aw(T~?|Feg~=!jjR!S&+&H|I=hotbQoah|68v=e#q94_e*YiVFUy-01Q zqm5qJTs%kG>LO-7x;{Vs*BR^<II6Z%`>obkDRZ%+O@8b2Ci~LPhZjyQmxrmzj1(ke z)>BWgmYWzVQ+~KJ`zDZ(;v{EsyXOS*L;e{r{P#K5|Gq9zH0m`XeD>aHw}}IJbKXDz zq*J276r7(Z>p0<_TvG7-G6`Ky7oXbk>)$@UG!H)j`x>6<AqQxE&Sl$g>u-F6O)ZcH zNNZNmI$WShDomdeIdJte`i_;x+W8Q$a+JAV^^~s(Bb&o#+4=NZOyn0|?QPoI=x?Fh zMV5hrMD@CXm`+zYCAw|3j>uoJi~&dH9Y=rrhVL+toEc0V^eS7!)xb$+UGG)CgR~B$ z!qTuSTU-=(m+Qw8AlO=eO7L_&tOj*_3EJI1X~{Lt;6A{d2RVigVJ*KG&$)cqd-)y^ zd>tMLM8yw={u_Dn-m|U^V?`atKb36}1V<bW1fbI4qsP&nAT1QFw>xMkYB{0qP20OR zr1H~lW=G^m_Oj`70xW%#VbNQIC#BpvlAkUnu!eMhQ0@~Ro4WVvv8dS@B5fLUom^Cg z2$CC77P;f>*mw~V<f|=~)z9=noyaxr>G>{CJd5{zrLU-vhl%1k-{sq;PXpS?P_yz< zB3w9M&ZU-LL{;6+vlcWjb%2yg_tIX1Krw?(ZbOMD7K&HGHKOn$&Wf-flA4^R=e93o zLZ`FKKO7c(R%9acTH@IhlZZ1fT_-)N-gJt%2_+fpS4%<8*jTo{79$cf0esUa0cqU1 z6#Y_qkcZ=Bl9~!RWkW{^NC9C`?s(cqCGhpUVY-0vBUuSDM`&Qr9LGEz&6ZS5S@U%S z)sJn{e1zrtNUBOug1ax5-%&&EhNzm|o(1urw2sJMty;v>?)UPIV>^nXP>$F=waX`O z^e)^?vt&_ac}_i+CPWewE91Vy#`~hRljeK^E!t~d^Gc0W7s(-|-7uP%4Z(Xo2EM6A zPwTHOCei!xcBNo@gq3$^Pq40ArCsH3nkQ8_l_vTKI~!l`(oWuMsaUt{J+g$YNTR3b z!gyi**R1C6{BzP@BZv5Yz3pf6|Hjb#Gj?l{4GT+S!Gf0A>+wr10qIQS@R#o$3JlW8 zr$X=#)%4_RIQ$ni!?-?7=KO}y1*Mh!^|N9cErFWkl*`q&D*7D&%SGE2Uq7^}s_y2# zX@PAcQcB;vL9gG8?6Wq|TOt#Qqt%lYn#qoIVtP{rE$%SbP88Smnl5H<N<5w5_k;vK zoYoTJbrbyjcue8oeT}UO)v_+9x7NG$9IXxYh(jgeRB=pM*3PjRAoFN2&M$0*SkxS* zH%`7xZ7`5=C|+MREmMxsbe7j<Dq(t3QuG7K5P_@b*cKi6*??+I@71+e%y1pzsTo@K zAhpl9_ZxcSaYS<r*S2U+*hFxy>vd|gu7sn^;C*@I$0y*9pZ6YtCxJ%?8qXw^9~0HE zCpR|7CateEtk|DvU0k2DEI-Pba<N79a7l~;LD^f3^rz)(J90|sn+~J6Q=~(Iy3IbO zIP-+)mhue*rEh~BsvVT}xyCB_)iLROEm1@AA}?AUjg>>8-C1#s-F}1O4fB0=^@EuV zo$wv6AT8s@L-q71VKsc61|L<2J|#*`4Ie%X4rRaDR@iRAf<!Gj4D|&35IKxXS+|Ln z*LQ_XaD(5oJm7PnfkZq#kENGk%yfRW#ATkxn)f!Y8_CN=1fHqZs7a17SIRnf@s4b9 zz^$L`2vQz9MDiWQyOlthkT5<Gkb2^`OJh%}CHIZovC1i*c@#s6ZY2rXq;!{#iw%@^ zM{nyR?MwVkdtxE3EQ|cA8~S_rX!@?Y9zwzMntOW6>nytKHQiY?pust;JFy_+8bODC z-xww3ID6vJU9VA#(T+Qm!FuuLd6rb)@5<Ah#jYI@r&9H2o}u6l+Nz(|rExQITp!7- znvhUtSmvA4U~^<=R{hBpO|G(5r{i~<K9YWog(ug!hs|F(g&-I~A&PO?$)@ueOb<w7 z_B9i|M2TOmGgT&@Va*F;NR|HU<g1-VPWRoWmkxONdH;GF{?iWtoeB43gk$x>QJiHA z%%f~(PH$!;szo8!KqJ2bT4%L*{+3tMYa79c7vT>R_^<#d%WtaRUz?k+6E{qxcNq3d zF8A;nACU*%fqm)&kG(N{3Re`-nsr_twVLyH2&&9Xi-!Dg?){DI=JS@kY5lR^;arq; z{8%ZyC;7$4*oic@158Oq<Wzum{dxKBFmviz3JdkV1qY%B;#+Kox_M_0l~-#@Y4Q3@ zxat~$iYx2&N~F;;zoGY_L`irVka^68nxxfkqW8jErMQ@Sfd1hUVdYbAP9qE28Q#15 zkf=b^_Z%QKvsUsbJ_cbLFP`rQa*d$nmSH&x8myBn30^$DW^F2saL!Iv)b@$#W5EF< zWNZ9!x+#sQ%ACdLm%(mep+XsF1#Hg|9F+IQ-5iG?NVU;j@M(jw3AC%mr=}w#%zF3k zrho?Uu|L5)O<DP^4^We3V|*fhPHv&b%wYi^MeFhdB4&&54?wiK4;-l8&qR#ySx&!U z^(YMzhdjljxTTn%oYZIX=aQ5pSya}IJfFO=j4k6qod;yYc&N(6YiWx{+KN#v7&?qP z!i!1htY}u}(WJ(*`69R6Qo_l;x@gwHV@Y9rd?v7{rSA{-gZtAdsCG6>`H_&2Q$q7= zRmo4ZQ6j1rw$*<)cY9P<h-0lplUw1MQNqj#oooynnrC^qER#EUuWgBG0lOPlWerlF z?ktSVh_)nGr)$NL+V~0$^;;j$kBrz9C!0+6R5|me(>Bh6dPT*Z<ju|7uD!E$VY3|R zQbb>{j1w{xxPC{*iGH5r67v4c?yu@d40r2hoys_L@{UZj+}j%OLw`zh6256Oxwy`+ zG#G7(-5u?g3Q5sV3LPZp_UY_SimzAS;@e4=P~OQ%GEpO9`McdUVul0jbocq7L-D_z z@*^Y$VFW75lm0F*IR%EP5g~<mqdUx6?=wJ4VL_Sk1|E(}GGux!g6aVXSk?a-SbGCL zTlA}Mz$uE3<T2C8t2<?#n~3*gN<C~8E~&qdX7-&`)70`NZs^rqGlLmvyvaok?^YPq zWHG%3!sDa#=D-P)Qcb=#*cRCaQ8SLWnPdCVzUhrdHRR+}2VnefM^ZzcLXC|iPSSgY zf&YH&(Pw;?DU}L<;+Y<SWTOWIqTL0Un`sXwPv()`h$-F!?QVvw6Pth9mux^)UO<jy zz83BFgx=utl14$dV7498M<~J>MD$JQdvaOZJUNkAYI(hirO5~pEUb$S9=&>y;D-0^ zvIx`QBNcW}kvC@45sbVh*t%)77$sdF+?2krNw0!pJ?EN=zM2F)qy@}jpZHxSjgo-G zR0r-C!xZLBzxax1KJEOI1z_B@3^@(zrLO>^jm47SP1T6I;X%1)%*+>f0D*Ic!qHyr zy2fu<c}>xpPE5jd%bO^S<C#2j4Q@zJu`u##qY}2*I}CFxwsO6&aXDc#Q)vQlMJQvx zBe3`#8DVS)qIQFS{h&qDUwb-vaixxetnqE&2cHMjTI+{~DA|T+R;9EdkJLT@{vTsE zZ#n!d*%|;`oBtG18noQB#eSQHnbrEPqyqpPLKUai0#?^@_Mu=j`%#G(TlLje@jNk& z9swzPX&iJimbuT@isS8+cQ+_Z0>5@dOnb}ZO*wLwZg-sV4A{yvOlo=?p*l#b5d02H zyOB)4hEC^s5;&v9&GB0~L^8gxi}BUn2-)%}Hf2c(`Q%I!8y}U!34ATDHLj0Mx6h?v zltC-kz-cGA=Rvm-U+KAJDt)V(O{Q#5O2p5ney^}9I*yfVkc-Q{=H6}{!;9_lcOa=e z6(@Cbc8Im=FRZf{Nmb+V{|fZ~OX~)P2zUwJ`gbck3Ya2Vw)>po9?&Qc?@^`@HN%Mf z7EB%^K}sD^J8z$MQ<R!l)Pd?1NK*|PBGWsDda2NRX<8<=H)LS5pokqL1n5VPQLq=n zrYeOmo*x0-WOzCn<hi>0pN;Ng5k<YPA;solf=7F))>w!1X@~iuIn&Z6?%ZR_ZY4WF z8=4!zF^4C_{inab$pLtV&W=ca-Z13!_ZObYxjFJ!I56RQtU`^U3e^NE-c)+z$mLgX z#utzCEk><3ni7b0&;jOJZLc=pjKZ8VjcH}Fb03VeQqN}`eu9<B^e|DWL69!)rqM|I z)Av_xho#1mz=EKQB3^+Iz1>${!YnG1G17}dKhhjL6Q<@wO|^>}R0eIrg*@>U#-B*f zSVlW6RSFni8Afs(QT*iozn3N{40HHX-v1%g82}%-toSihi<~8-zn>45eh!L)QBiXA zj&B^<Pnu?kF4gPQX;i&GEbvTX+$|Ty?EQd>+%%AwlAJtV^2H_nv37b@<-w@u$RtiZ zT0@XJv?Y;05f2I9^({A<t{CG3WYD=SYS=}mKaHzeK8_^v3?uo2J3Z+_a(A=r++(zY z79vl)x_-nkDT$hxP|)b%C$Ej$^V-od!K_p0mo|Z}D6OEMTt7(_>mI^xsJk;g>Qr&N zL+q;yect!pQ%D6qyj&EYgzdgs`-anf1h?!_5yE7#smXiRMVtdmNfcm&GVOG!&>j^N z!m{$JxW4GEv8_&RVilhrQ7@%Yh_sVqaq#BcN$2Sui4yMXuEk{!G1@|v#$f7<yEgKk zjhY{}p|o{PaZTuqFexCZeY$QFKo}OLFupA<<A3@eFmm}nGQz*7Nq@;$|NJ5UzbO#w zP9a)>cVBOVlvNB-7-qU$I1TLPT^?d%VUf%LJ4ZA%%fwN9$1()67Jf`80ZQy~H8AXg zHxS|m2AG<`kIWf6a&CM)ir{KR{e?~)c>cW=17{LWywX$ZVC#?XMmPBSv|VlZV(Iqm zJK!C@lxhdNOVuz)kAC(sNPG(BSh(=`Ta@;myiBO2J8rqJp;!-@kDh4w%G|(NBY?CE zM=ZffriRm!QGuF119@Gvcw^kbY|iKS@A2J(=fZ|3>Qe$jVD3b2ta=+VM8;liCradt zIMBN=jn}tSOnn=LfX(AxOcV`YHtoEtc2x7i$#V;KFI|==CdSL#yCCyjZIXq>Utn^N zB&Cz*jcu*JVr#Y`R0fOFR0yG+5Dbx>D@=XG0ph%SS^B+1bQD21)33+T?EuElc4&w1 zQu8ib8N3YoPTd|&Z?cM5-pywy%EG;BNy+sWzKUzpO_>|3&xmOY=p^V3(R7NV@=Yz; z$|)P^=fByD&EFrg5<OT1h&lX%@qQTy)9ohj2b>AZSH7I~m2bf*ot{o6i_T^DMaBt9 zuCBfY*5oYZtF9A#*{VCZ?C$gs*Rt)pjeGB%HTR$GF&GBb*xpv!Pf?GnVzupLPPS}% zZIEmk)Pqv>r#ZF7=T~61F0B7xTc5DVyVqmYB(ig>tg}Ek#afo?cVOlrA7VlK9hB;W z;sExdZo$4^1XNxV*12C>Lv{VEHE)=E{k-^+uK%ou!^WLe{`NzK$)S|o)*=|efetGt zoa^#R+=tgg<E@U%T(eY^&$h|PrV$?ej~E&O&NfXA4)^{IQivf1^o`Q$^`p4A(Fkz< zq_UZis8&LmVR*OVwL{R*OL_Mji&s6W#4TT5d3IL#%f5YuA9P2;mgA4?<F&bwF=+&4 z^$8WF&)G$>%)+JitqLF1sGg(KrD}WlX8`X~HM&(7DfF(FEJKMEU0WV<r-E_xHPI&| z*ARJt{iOb`pi?6%^>s6VM4>Z++O%tNA+X`Tv@n)N@_GI%$qkfa_0w5vWP|;??+D7I z^c_5DRqp<JW+93dp_*qRqYwd&C-8^**&hy|5dBc}XJ3|$g$%!wgJ-c%2J)_Z`H=2& z7$Rr(cD>gwk^Vb$r>_B#(w8cr=)W81xuvx+7~4FDL2N(f1fJa+NR#56t;vyGGC$*( z>4N~4uzB1cJsBbnOUCSqs65^&r>f80MTs8+58MhFx$%+nKljZ#UhP1OM+b4P!9f=< z6_n<NNrRND`eV?lpd;SQ)G=)zdS9*p|CTUj`IZ-`%I5uD9Qr1;kGy+?Ik8BtsBVv5 zTQ^Uq6ez-U3-a&dX|Zv^)pHKnV$%ip!)K`-=<#bU9t6O0hT5m6l&F3B7+2?2!hZ6w z)DpP2VAPc@AxXscRdDF-A4oRk({GW`<}P+(P}Uq7l?u`Pg!PG0s{8B7?p%sj)D5-^ zt8a}l`hy0p2H~1b=MW|7^h=qhY;V7j`vHmZY&#?KXO|>`(|+}qln!a<nbQuJnCzdF zaM2?t+v;7pSizdRg`xpSTawqmvArxNq&R<59P=YilcrZHxHB`?IbQ(mE_^nfsfX<s z$yA4$v+cZnnzv@elez#}&lD?AGF%^v3qJlfiZ1^3U>29l`lS(3p>^`omNDz5bt-r6 zx(SVKZF;WVx(R`CJM<WSq(~~{s_sbG?3l(f7&Tb(SZ%i~)_C)lTV1ZE6-cSpEypbn zaaKvz5Y2#Vj*|6n8=>h#q!YCKRxy6ze+`jf_K<*}i=D4QS9J2P|3Memo0V+^hL0e1 z`bb>`;yAdL*a9MrJO1pBAdqW^lXX^Dnd&=w^A(r}MV)SIeRSrp$zx{zEH2V>MUO#f zB|H77vFh)wH2rb3iz6J^a_Q-}w%01nO;dgqs$LwpJq)YrGL%oJsrnAaa?OCKWX?iw zq;#;#{WO~8v652n6q@an7Fs_2wNdM#&Le28coDUH23+Bxx0Xf|wE{>EnCc`I?I;pu zM5;}O7s6e2p|Zt#F_AVb$VIWAU~>k-95%9cC(Wc8N>U*lp|xjCC;Q>5$PFYOP4Fih zhbf^3;t~!q^_T#HX?e7bo-tR}9U;~KQeqq{52+;W7qabHk-1UJ<1q&JXTfO)fnVcd ztr0{}hB7^-)*5-goSYINYJx5jtUi?=it84o>X-td%vdZlpwia7dJPnvcb}eShrVzl zE28M~`^G++ZC6J7Cu|ImE=$9(kE5vGJMi(1t#Y;^kzrqXej{OL#~u$H_gfu?w{DC| z2y5B?xbqiN#|i(1Osmp1<~W|Xc<$#?%EG8<FaASO^r$Vb%T$=<Y<_AdSa~w(g#;@g zVGrd5d}ZCJLHW=xQ=l0Q@7x6es~Ro8=>sC%g)V*}YKE?k)rJ63ihIf)fK&DA$5Gq_ zT?+k!x`Z8<2u_cHy6x1LYr{B`q*IE0Z!Fh|T;_XtCzo92<KmkZ3$_U;VSgIT@*G88 zJzf25z3QHeqtV@n#rsD(vQ+~<dwkt4pyy+A^i2&myT2GMWSLm$xe>b%eA=wiwT@rH z*u_T8f(f)Q<(5RT(JH~j0-q9Cq>_0iqd3qQiDH?j9nn6jgcuX$&g2go*zfLqd!S`M z#c<`-IR2!gAKWz$<F-Q|VZJ0C&{J(IWHf)$_5T}6pEuwo08d8Y?|{VbFOQZO7L~$d zq0@Tdg23<t252uIzOc`&V7$G^aKDNOH%1E-MqVBBHgrWC`yk?aqi+`Sxx8$YZU!yQ zCj2V>xgo!F$D{4NV07VmTpPK+hFkPHR_^DNTYY56juS<&pEYTjnBTXL_Jtb##su`S zgD=-YX&^1mdG@g;rgsX2t9H{Jkp?UGi;@f)o<BBJ&W<r>e*`r$0~HJm#x2N%JXe^Z zX2M9}dpmIPj=2xE%s7YIN3kLz=a;C(ADs?NZEbWNdh<uYe!KbeGrT`XUxBQo*G|q~ z64un%ijmB`PDniUPGsjH#1k8}<QB5#QpC|}p>CxdHm+4^LWHy#)=8ZB=bz9m@Legb z#*2{5G&RA?u<|+?qBG43Yb9b2U|Y{=vCHQr(69QJAQeFqbj@abq<}6C&wF@WCT;^R z=g4zb>+`t$1M)s&S!$6i1pqGQsZ>-ufwQVV^Tt2Jy|o%yp^r0nByL0WM9O{&=hUfo z6Iyebh2+;G+lU+t`Hj;-q{BR#!mN`qK(DEdYCKfkzdo-OjzFcH^R2)1_pzV|Zb0O` z^oT4?k*nm|r>3Ye9r-J`@i`Dp=Y1_PW+<4(jq_`xJB2x=*^EQ;&&Q-oBTEE^D{bW_ zW<ct093o;=D36;J`<qEDp=JnCAa=@*X^9C)Ok@juGk+;vn6^ABIzjm|ILk)QI4XQ3 ztfXgGqC;)=MCeX!Er@>uWMY_Yx!be6+Sk2p_UhSey9>7s#c$=(J&{|p!y2`236<NI zM{q}c8Jj1XotZR$JO2{7%sEq`5JT0Qt>$v9C8pJyO^%5}FW#y3M28_SC8cLd>~z0n z%i_9k?(7_CS}wOpfWicPcD2}JJOma;U#DZAI=Y2-d)%+<CkGagGHR|CNh$TpX3^X1 z)g@X*2avRV3ML^j{hLb9&tkkiN=}K@>xkBV!}PRMiQHoKp~9DmbK1J%fGxB4DVh~p zpGf_S#DG##ji7m+Z1!21OE;^3uHa-L6aUTyMEO!?>@RHZ(<?Yemj&y2-EM=%arHVh z?vBMdnz7n#AyfL2lWDKBghyVl7IQn9FaCfStx~NcOrIvMWagN|rj(-yB@x7L%v3|O zYU5Fvc?jX$Yp)E8n46BKVqN)ffN=gk6Yft`-fU`5&rL2R!SuBkZPeng_46x7gF7z* zb~_>_4llPf`JWrQq72R43@j2gIB^fkKPgrJnxt{tCMbP!whg6T`WY0zGC7jJJdN~) z8~3ih5EVREroN}1rbN|;z~|Tn6z?&Zi8^(}F!l;lweOvdq*L0>7GSzPxsV$f%(QCA z7<$dDxO!NFCJNXUS;1@<-C2cBDvyd99nr^W%Km;!8RY)omQZAjt4<W(kz~T($-O}_ zx*E#81hkGO`t(xlk6H>tW3Dh{<4*N!Gedm~Z*d;loUoRkkI)y*8O%OM677_`N>(I~ z@#F(Ed+23G9>rP`6CQzJx!9J3;&s@pSR&(bNN%yqc>jDCr$VL+{Qjh#&)t~`r86$% zmBFXeY=?$_OWnDNS6Dw*bBgJgIG=Nh=@5R~7N?O3N>qiMpfE@OH%lKG<;qG~c@eg9 zrI=)&{soK=e8w;QLIkKtGF3W$KG<vS8y>{ee5TUGRiG>aNj=?#;Q8=fY6iVst20yw zW!~>_F@*xg^wT@HV!A(B?Im}w-X5|Mku03%6<#!0r##RM7w@E+KsJ8N460az^0_^X zm~=FF@XF>Bb9CEHGIBQM#|)u!-W#NW%=~fa=g)@QXr%Def&mx>g#~EK^vP*gD;^sM z*{{Al#52Y5aU59^RPTd864@|>2;F}gTlUL~q;2^RTzjk970>A&qkN4LlkHR9se33j zv=Z;R`=aOZt>R?*h09C93m4lp<(`=vbtcai7b%R2VRk-k7>cX*9M#;q@UT9=Ouj<X zWmln~om^+*bUcq_=Qw9Z(IfdYC1FLob!XFA&7MSDx*s*C8Gj}(s+y8jjmLhMaAY;S zO5C5>vFXx<_?)ZNvk$a&Yo<kS+06C{E9<S#_^NLRD|IpW1nkh>k_z6PQtMP#&7-K9 z9x0?4iJrF&-i}K?TsZjqS^QiQxRMpT+9G3n{?k>n;zaGkS}2Y|Fv7GZ{xW31Yh;GD z@ihfVUZ1+~L@xJ(iJygNH&;+J?s95f&cF0H85+=Hmzc_2v(cP}WfZgk(2bR9)AY=E z)^`RFA;Ix;R7z<o6RmafBU%^=T6PpNwM=vE=zkB>$m4<oDaxbPmp@PG9TB*bFwe%+ zW!(?#(ry0>7uZa$q@B6!fR)tUIIOP-+g>i_MAn(@mIOd<NmN{*PQD^gu>wvB^P^_6 z{l^{`b7gFP2r^tb$u>kzIT%&^8~A}?CQ4b0Ff}88YT@!b%(NnO4C^oLLE3J{q}bb` z@Wv`EjQiUg;7Ij%uco^C#2gIiaes1-ml%~?+6|SUiVu-yiz6B?%Mbhc!>8lZIW(X7 zdFq1x8~4`ke>}op69id;)HzBwj05JM;vHJ9enU$wewwWH^?}}P?9=-lefs(@5H)31 zdrCPZ^vRX}kg7xh7CPA{L<KUw1(&kZ>ErZcr#i95aXs-@>c6cihXPMq(nh+nX$Qk} z6_$KcJ5wVRA7Sl&fVz)Y(UGWhMKK9jldMgz{22ZEaX&^23d`<VZXTO@PbnZpgrdl| zPCMw74=gY%q`Xx~MctsichDh9j`||IxKj?x?Vh9DOr=kFO}9XVXrwF))Ahht3W@5S zqIZjI76*Ij5rv2tnlTg-^$ouX<HJ+fPUsu|0$s^1$g4f+r5F*jl$b8_+yvEzVy@EP zUm{<{w<H{_BNObla<(1?iKy!`$wkQ+MLF+JFd1dnMbvbm@g1KGU(Sx|cEmF?^rYr) z#XFmQed1HoJGscub8pXk!Fw}0eWTaqSqgm;*NfUS_kKye?Pl}YbLx-c=}e=y0sQ5Z zU~jzBxL%}6sCEh7pjT}sfRG|}WH#B*H_hnj2HRPt)@;eju8yH`;a{#6gY<a0Odsj> zGV&7&-(w4!Z+#~sqI_x-$vSYG>HS{ouySg7^0i$%0=XB4=X;TSr*1Y!k6pDo-AFf& z96f&%H>wv!p%P>1tEL-d!@Su_FQLW5QxOl#p8KSNRg?qwdL%mvsuYIUf6=IJEmz+Y z+TZ9ts_`E|omLnL83yfS6}2ctP0GHTAI49FnGh554;oJ5!BTdsek!>H+#(&8$db0^ zA%4%tRg{NLmaU$spgyIJ=U-k(k*F{xn+-JkR^Phej`R>^-9<9JcaxwlGT)$9Qa=T! zJN&3pv&PzM{kB6&mbEw0v5x2h!qG9rwDQ)@cTjOSh0-VuL#48oYsg2c^eSYdR~Xm! z$4#}8F5B@aJ+Y*8Aki9~&xnLl(jy%|wTamPqOS0F6zq*c7n{`qXL$?J(0f+59zrC< zVvW%mqY~Y|#2N~&19BvZx?z!_Im@H4eYQ?Xy5YKS9~ITZ#_{!r+z+MTIh)ufN~{C4 zD?t4C1r!i-2@)(@-whmk!}s$Wm_>h>uiwZ`FnRYXM@eow=RV0ksGapfZ>IUZgy@eL z`=<+`nEhNA+P$kH+0%A!Tct>vZY<oOB0oCt3{?}as#MX<m2S?Dt&iL@d-|lsg>Ao! z>3}(b{iN9MYiCw&45D~98*-LX-BJ$>`*NC0SFqbnIq53fc^5~t*(!Gx%4Hp%1P!FO zxu@++PBz~q`Fh!f?fv=z*UzM1t-S%X3nzPW$LOl(LiHTl6DMO*tnndgIO^4F%ijl9 z^TyZ$s`w<!JWLxc`VcjiVU=T?_b@^XNq^x*nxHq`KkwSRoZxpzPm&E+5KX>ocbTd3 zQl<xY1Mb1Gjb{B>vsWkUCm59dQpHCc>p!HP?OD)S3Js}GIk6Z%J!XaN&3JbDg7AK7 zyXK>9!m>xmwsVDLP+e#JQXIW%@||A^g>{mhC7s#M`81hv^o~J+*h$`NvNhGEOqh9H z-f45S9#t2iTq*Y8$+#hF$gQZ++qK&cyHrm^gF!3pZufsFE|Oo)2c}Ck;R1!@@!8?* z<OzuZ&GnOVHj-O4{oUTT0b9oD<`t4Ao|GEo<C&u`Y`o3PaP>PCB^CYO#$~XGssZq; ze}~tm#PW8sWoPaeIUJU8oZ2Xn(7K@7;3F%C9BsxYs{eAdw<{S$tS*@*9oP=`dnc$F z@)4i`iUMG*TCMpR*+Zr_o8|w|^F9%-BglUx5)m$VK}hmz{fTKZ;y5O~HEY-<+YamN zY}}5*I!(idj5O;F7>E@+lZmD<_#guM9O;=4a97;NZF@N`-&2(HfBXe>zhct70C3f_ z3u6&`V~Scuy5i<ewa4lo2@d(6#U;lbB&+JakwhA#*5)$a2kMxA<~mhnbsM!4Y+5Nd zM{Vsa<we82kWAoGIwhF5;`eFy<*C!3Ng_*U+>q>vgqGKlVgA2AA+2|>gZbE0X;!_3 zd6@K*fe)LvpE6FP6S!4^iVtp9J)ezp=Qv#Tk<uvQ4?PrF_B{5GFmFN}nBMt6-LrE~ z^^X&z=P<*Zs`L{S7-#1O7v9cWF`e@Xq4pEb!fnR;AoQyY7%j_8o;V%J6Hr&H8TN8f zlZR{VdI3F88h7yaj`b#Qvpwe01@R_ltuyLEDm%RXk5j_sqEDPoit-32pftlqYOP!N z0`p{OBI6)GkHEK;L68caEfW7!7guR1Q!L<Eo9*CzY%%uQ{Di598jot>6x$2_NtV@z z6Y3tV4j$Prv7>$TGL!q{q2)v~GX?DwNe2t}OM3oeGu9^)Q472Ow2V?+_r$5|HSjwN zDoTzSaCt$*r`sO<FK0uV<T~S@!{IpoPC#IIm*M=414yE*p6>v0S^hG(H;LVat(bm* zyW&;v9zuBh8HMfvJ^9qsRjpMMOn1x&QlUGB@(UT}LXR(u+xi!kggJr8ks4g7<F1Me zM^4}2z$om5F*C?N!KLf?Do%%ylJpA0+*4;8bjSGkHc$kozwLSSa3DL-$`HB%R)zOR zaW5!M?Y;wwjJ$L4u4vAsG&Yp}CPcm-!@sD7A?;avd2}f46A;Hy^7TW9Ax%<AK}_u? z>hKH1i(^#QB_Ts~xo_$QjO@dPk3R=ORG{UcAJ`xhF^nU$O17AM0l+QNXZer<0x4`d z>?(6wx*dpIH}lq|%{|ZEdGCjUd3Os*HmYW_N6RR~@SgMh3*mFRr|M?MgylFC*otKo zYXva-nG}+a%Zs~lCimWVIq@BOYPVgSd38<5u`b1VS~nzCs(D!i6TBGD?N8wIizOWy z&ph&GFJ<ns=Y=A2k6OZde}}IIooFfR?e`<&gRb5T$~)%wHWy5e+el6>`Sezg4~{0L zA8t}(O;(sruGwoFn}U3t5>m(g8eH*1OCOcU**Sq^`aBv;<)yb1=K}s#9(wftlWqVL z8&k-koTssFI)6pXyJ8NMo8xFX5cwZb4Z-f#X7+_hCh@?4gk>!IKEAL;ra-~F0`~g? zHo3Rb@8$}^PrK1M>pn2xp0c9H@^)jlNn++ulitZLRctnw3hHQB95+~b)Pukm&FY_3 z^t?z$SL!X*SHzw1&q(PX9T;L~&k&at>6V&lJBCm*i2JP#l1eSzUZG9A#WX<Ag{1he zaW=t?XZ2^RniHWzX8C?hM0?0&6A!~_{RJR@X%QOzb9!Afl3EqAo{Y3{c0kOnkdYYk z^WvT}UGAGAK&ae7HCUfAj$xN!gRvNf_viu)hop?6Y4zma%phHfhs(#)e4t4tS9#Bl zb7VyNC71*5rC@BOu3x6Q+cOgJ7J^6pf(+UBHX;i7F#=1!Q!(GPy~q32G!_s$^U_xK z)FZo3<dh33GJwSZ2`e%pUi`67q4@A8phc^DrCm2&0f#Vr`rY+-J_01T730Yr#$hJr z9N$^v0#~xs0r4eI2)+se2T*7Hl=sF1zTJ5v&DjyQ<YM;)a{)HTD2iFpC0h(ivwmj6 zTgGx=w#l=|0EeRZpv;QN_$JZ3QO1f<OjyxOE3dj;Z+AQ(E`n#JFWP6egr0}%Nhh}J zEF;}LgHD>^aNlMU!+4!T^!5_m+?%-QW5O$Kn$d<$XqSqP-xH@5>$U}YdHA!iMezwV zeKl&j-YH8Vg67Jd-Ew6D`BIK)j6B?m+l5uzHTNj(DepM<B+vFI`7gq#39<VyQvHq2 zUdxhz9Ga$t2&WNwIaccz?Wu`;o6T_h5_rK(yUrAFGCRg?o84A@YUL2P5Pn<gB5eFI zJF>(@O(kTEw?2=={CU>)3eCK+a+Dy%DItJc%(&+UwKuVbi~%yM`Hy4@K5=9^<jZgR zXgHs<S;6IfHsfs@hUXw{Z3oks^)+IWGNu8jFYbM8_I_vNL9f|ooEIq&cX+#E1%|u& zLEFNw;JwR<JJNUb@eDaR-7x%fjL1CF=K*<$`O+<c#Ysd~h)hg?q^g>}M<=Z4Rof0` z%<<tW$L8>aK{>ti4oF7~<B}YLIOW4-;OMD`J)Ozo7>+3Ud&)!UWXc}jy!^1z5=4S2 zKWmY3B0>xo=q7WM6IU&T{$6#QS<2f);lkywq&*&YxEZCecze$3BB=_TO`?=e<RXD0 zj3|_X4z~H)h5r8T-u}e$c_iz-T9|bmwo$sOP6pi`^GBF8dV$*I7RYR$o<}#F0x|Jr zZ5UOPF|{<svjvXLUl6alXQ}XMD|LY^S%XOL)N;CGrHn*z&8`^l`2@$#5!HvIWoNnN zgSKy>G=2N#^mH-R*`HiFL(fz2Xq0Ymq?0uhGF2t-VU0UOe2-${y6<xM+mHsGO~s$R zfImvb%PN*aPDeAWwNfO|;{43Zm&~lD$?wwo>9ppSQf<dF${x9OpU}HJ*zYwF!|C)8 zJHq3fK=-txe@-C1(q=GG-j49*vO{frq3n&WZI*)U^w}agm&TY@DoQS%z`b(ZT$lH5 z%s-i4kgH^B7pAuH8$sYmxzdrkJ0BcJe|L`Oy#X}?>?p0-S`cf%JaHcrf_z6w_n%K! z%0L6*bqXFe3nOXp8<fr+0=rdzT`4Hr#Df`?!QLkwK$z}$54xdIy6f9O-FPr1O9j6L zUkw2S4bk9?E#WGWe-+Xz2$>(CsC*}rOuw9ubyMz=R3jq)r#t!YC$tVlvOrDSw{Clx z`-cZvDVih`!iM_~9z1+>w=@u@4iv!{i_0H5uGF2`t%w<lxJAp6Wr4WYGA2GjoGk&O z02?yS&8mO}%c=6oTZ3TCxO02lt^4J^?W%cmmGF(1PvhF6@gT&x=QVDBBMP2;#hkRT zgrT<E9A!Gyxh2^SigM)-0Af8j|2UQLegqN648bN!M9c>2<!aAnE3MoV1Cl&G3?Y`o zpbJFvuXsYn!iwxC_)MiL0E(3lpKpt#($5}xE^4$5N#Z<oip%-=&1^o+CA)uf1b?aA z|L1t>{*^y<P4v-Tdq6Oc)JBEEBoTk~U97uL37=25HbI1!p&(iUyYevED3Z2*v2Md8 zZ_jgUo$t<ktrd2AdC{dac})YXRQfvcwCnDf=8qIaF~^;Gqo>7%Ft^1O34A-aWW4xz za=UEl;Fp?ode^gzxVr}1!;ywNE~6<z6&yX`7qU^uxo~CVG+J9kCg=4{LS%JJd|O#D zE_<SY<v`QJZpecPUYq9#jWeO?mE>vf)>&VO)*yYGkCZrtko?9f>shMwbA=9Nt(tj_ zfo+kFH`I*Z{wHa!i$O$E?R+4TPQAO4HaEeci9jx3%*okZ%q*XQHnZv2IWTy%{oz{j ze}Qs6waIgkYeVoeC}B9ZH%eh`E^drTM2De<1J$6fjzSSSjf}CP(C65eNx5tv&n{Z= zCE<BHkop#@4l(BRtR3)?tIhnK<@8tm`&+0{M?_-4x%Vw}$NHC*Sogu%b`=3rB}xmk zu$0g)tuw@(<O?zB^nd&;+rK~sEOc^fGAz6}7@H}Oc93mzxg0G-^&A%XELhO&mA<0Y zo$E?8)bD|Lm$qW7IXOAvinT_jhA=5;hxeCZ5m-o~Yd~9?<VD~<AQaSXLvuwyWYj@V zPm-iFOmAf(<ScE_&#yTS;|taGFd1(XuWC%gu#J~XBB3NmO60rVUC0GD<oGfF1Do{9 z?JYyYyydP!6Agn8>cd~zg*Y2TUGgL(`X%O1vA=@kqG<r2KeJv)M9lx`F2p{jdPtZ- zpa)uwXOv=iS)BeJCU6{*8iRKVqb}8qS+AeWqT89;HpM(!jBWziuI-i&Pp!6N?G#;z zu?@ZAR<Ek?nWVrTNf6;AI1Z{N<CuKarIP8J#oEr8>tkdC6YuZ_CvHaZy6}am-ILO3 zA*$Q0xwl8e8~cmFe;Xy*6tGdHFnrm#&Tf0?*GBRq_)F(GD>;VTy|L(&x%jO39pA?+ zs@b~!d`-I*hWne_^(r!%sq(&S4MfCS|HRX5B5ld}5m0zgB7W`8)g_w2g)G}g&cAP= zHl@x33HGjKWLUxbMJsH#ykm{<yA#)%fBSeBgu+^yXb4f3NmTIJj}b@`>0uXB`;(0E zY5&JFKhEDknp;%&E9vqC`~8`SBHV1#K;{5BrA8ZKKKQ?ZS{>QnHOraqhdWuREK;+) zNQi`q)jTa*^$#svg1TiQ?BEXz)f+*Iqn}7Ct@n9hp6t{^5#2SNCIDsVb%-F~0UAH~ zuV++97naqVEss|@Dh^JAo7AX`!;3_OoDF-i%gv3!<2hs$v_nt`+r$9r?4~N_=1s^@ zAT5h~1hU_9Y4xbX`sFwtI9Wuz@rlp}n{N5Rlnp(2i<)eE?M`?&yp{q;@JO#t8UKLF z&nb0nsz7UMR(*pVsQ9Dh(uT)sv?L|pLx$D4OUM5DadGTgaHviOn7>3LhYDe#NkKU; zKsGn4y)UaU!Jz+R-cEBC5(^=oYoRWo_n(x)-lJ|t5L3vkpqz?r9hwtxOOR}mb(?ID za8-4eT`BXd7Jf7<kf|bp{-9r^?^79(W$4kGhaF-46<5)be!6^nS@y2%qz(t`(P>>a znzEr;qBB?_`c^k${&@y}^vsDYt``JiL190#LzQaGAWi>0!8f#|jrHT*d3*YN#l2+u z-2u(rI=c?-N81zL?)WNm>{>N$o?azpd#iq9dw_#`ce`K#vMDzOl2xv6K7W29;lJKX z2?5hbM7Wci<mf0$+7To`3TP${+2Xe%h>?O*bCB)$+G|-5di47H^+o)ip%0~mLuZ4S zRY<fc3U5&}$j?jzU0|}I(th|g=4}Z)7`I^EfZR+Sj8fjT_K{Owui5DNmuR}XY&f5& zLkru393MVH!;VuEB&XbQlSR^05T{(faR^YNhDs?n)+S_vKSuHkAF7t=1dBf-ObK#p zpMo0ls-ibh)c)^Z(J<I-sCYznI_KVAiuDxiO;;Pi8EenHJP+lG>ilcae|rJrMDDNs z4QB2JcDZ2bXoJmXJn*zL!U>7C2xxJqUVC6{cEUpfLu;`fXUoQm5}2)FyrfKm|JYA; z%oIKg6vKK`$I`|-ujq7}t;wI%;uQ>k40W29_KZH;7*)a#>b8>lFBiuXo?&u^Z99?u zq36D?2}wvgXcQ?!{pkD|@o_vx>#MBtMjc;oCJ&tnrl-M@2lL`ZMs}j(f@@Jx&1`!F zil+&SZk19cL?3qSD9)sx)UtGH8c-c#(d8LcL`Os)#*jIBxZ&UPxm462&uX5i)U3b- zE;M}>u{dr@F!1YNnT`<8iy?AJWAIsDj!&k=_D%~#7e^m!R@l;?)lE{7V9PHsbgXO{ zlaEWY^RA|FoljZRbX4vf8C2I@U!dS}){kaQ<8<68vkX}$H*uLXNIsP(jHz*FtD^g7 zr13wbuCJ}aq`hZ52+(pzgLbL(7!i8W96Jo?vsUp9B^06QerIZQTs*Zw=Q~hgw6)+! zHJfg71<|tbqJB9GHz2W5gbNH`V9C!B3<&p%7fB+W>y!bu{^Jh%M}mmU(#p3hP*(^s zeAU^M*pi`<p9Z#vJ-4OM7_FV%w9hx*xtDo?5~C#jFoXx?xVFa<;qld=3%M1|9VD`D z@OyfbKZo55BC>A5vWzDgHe3$oOP1Z|II&PWXW*34%*`#@AaA!AS}i(f)Cy*rEf+bU z7xY4sQASHSU;sf^q?2f%&4vv*lmm178CZT}NKS>1Go=FRjVYtTh3vB~vQon!&#6e8 zm^n`_Tfq1?2>h%_qqN|=xMT+X!?#g)A;;kFXW2J@wm>hMXZ*F3t?K6;w~O>mU8&%i zj?RAahs^jNAAmVEj)|P|<*c1f=j!_a(dfHb%I<=r-B<YoUi6f|+H60m!^lO+-6TS3 zig~&*ARyjbLgVP2`B>s$Sz~l?DJ*e|g<b)hxIn?}o#B>b_actxTvWX?g;Ten{Ti>0 zvoD`{<HYHV)&6MDBV)Q{m)rDx8EC>}XJ)fvNo?wS<D|}$%VVB+`Nat2voLdgFG+tk z;gRr2&m$Yps%qC!mYK9?DD=TD_h*s2(?>$=&^z9)7f0sIH;a-TxOwb5bxWgN-%dC# z{~@dLr1}24&=dy)NNac}LUZC6w!>>t>lcK|7-Z#6T7<QHHO7`B5i-$$o1T9paH@m? zogR%CRI1b8gF5u~mbj=|04Vs{6_)VK6RBUJ33$X@2C8)TFWA^sl1Rnjfd9KoM9z{# z!e3TP*4(5I95~T%q!J}7Z|Kd;ziN%3VB0MbLUO61k;UvthvvRX<%i@hZB0%fqwRNQ z{sg_fZ||OXFnxlU5+^u2Qe`&Na@Vht>wfo>{}7g_ERrG*BB*wVbh=x2b}yxhg}4m& z3cg32>qRE~S&K6!F%}az&IIJqw}>Xn(?kO0k0Oa^1povuaCsjmzyRPV2nTb$rg0Rk zTN9=+r+p`s-84pSOkqzoEf>a@G6%Ckz+3of&7AT|qJn}Qo2&mK29t>m8l|FC5nwHv z`>xrT!C*pDeiow;_;z+d0xRiL$>%e`7hozWTytz3Q1-mJf7-&jV889I-F)Djp~BZu zT(s1@fv36g^X)Ske#4!{mD|hxc{Z*okba2uO_Q2WYmIPKa(~^E=QFDJSn;!wf!Y!? z`dn@=U&O={)jZ`FJwS>QKms9m%%3@BW9W#A$g^}iU-er&Hm>X*k`=a_@gLA`Ayam> zzhkQ8Ywpc&-x`h}P!&Ww&VTN{Ix3KagnBBk!0y6D-Mu@rncdl(9J>`XcLg1|DCm#+ z_eaJC2{C_C{fAfrgCUfZ>S<UbUOaXvj%|pI6;a{HG@R>#ucr`(=&m5DndeXsJ|_mk zD-ew=+Zj+?tyt+d7nMWKn?Ep4R~2tH**Ew*L6tCWm<L~=vlH}rMh!FTC13P~bLL6N zaG&4)%kvh(OxDN3o-ubIl<vbIK;RHC)h8xth?A=6U~<2Rcoio=OxFJ@%@v#W71Bb+ zyb$H-OIRdJo)$bA<}z?w=E4<GMev_<rD3-TGb<gq+P-GWyNb_l?FoDvD>HcxzS^-^ zO1z)q@2&KvIG6TBL<QMf1^!#bNAi45Af<MKWpKE{gj+qryt0ug3p)8uWC(HArlSOf z>})}PdBy@FgG2KEEKE&5*Zolt1ecneY41rDK<vEjCaS0V7?H&qNWM?4#6rXEB`C&P z|5A*Nep8x8B4X}uOm4gC2xYZ*DXpOQv8Cjx`qy??YpsWzYZIpf#|b^nLd`+Wjl<@| zL@!dhMk9tw_O4(V?$Ox8sN8|u@znBYHqY#d8ygMltw)Xm-Hu)Jo1v(m^-!rG<?8BL zH*~aEi{4?flGjgWRpsA8DJ>a(yq~2HL&yAi6J}<Sj<7Oqj|5IkJd^xq!)(^k+n7@m zB*(%=`kJv~Pi_3j93Y|pP-`~*2cm$KwF~{$>+UQ(_I~pxc>0BY#x_pK?QiAlWnVAK zP9E`q2M(l`-z3#y^ltxksPao0?}N082od6Kl|;2nlZ69~rPhA&8t~#1mx>Ze8s1jE z`21i7Zu$eceZ*ARB<ld3-e;5<jKW*8$FPh>t;8=%{Bu5!SLM+#eAfQ-C)W9&7wvD3 z;1bneXXjZ5=h_%01UHHO#mrs;tMoQB{~UB+ysp#NE)VqG73MG<{t8<$h(DQv(5?Nb z8$NXxO*sUCi{*}c5wv34c*<GSAUuE1tS{7hn=hTZ)6Rb@j(?Wz)ePdwgBMKl(%y<m zC^a&Cl>hpCt_|R^!}J(X2UptQS!7`sn@E9IC^FJkz*L0<MTz%+=f3jtGPvDnkiGZ% zZYZ|=Zg)Za)mmswvR?P!!AEWkoEVDa)4YW~XiQ!YvHq{8@Sm&sPlI~<1w;Ne7T}RN zaodEv(nc|CIgxxOWYi?PvoLQaK7?ltw()tW-_%XVwYyQm+O)S=iDe?Sx0&Z(M>!t1 z*|EfWzOhmU7_1&m(-yrot#9R%=xaY|n3r{XK<b-#E|!5pp}5{dIo7t*M4_t9?>Msr zN!|-ln@FK5Ru`Nw7i)x_FO%x{**xode3SF&qA%n9jtHq?*;h+w)iV-1McR%SSxame zgFm58D2^#0hDGX{fYOS1lk0X0kKgTVz4cVh3DdCQ^*`^JlwvN^e~~>n8x2IKmvrr7 zb{!(%9*}N7T)rJ9b<H*oX~Wj4+yCsNzIfNYl+eX-Ez&qgF%#bh^OG!p-(3(plQyV- zfb354m+%@QAPBK07lRZFsK;dG+Vj~rK(tqdgmgms1}Ez0|Aq%T`JI1_a6Zj4`w;yR zQ56&6+$+Hqi8H4H%no9%!)qi~MxK7Hx7daOgpJY7Y;6wRzY0aMO_ZX?#|Ad_k;ZN# zZleHD;rX6<`MY$W64SjF)C4lENXUzM0OYhUIKv_lg+lORr<<d~6@;RNbcn;>E9J(a zwMx46OD8{w4D7#m{cKtxe2@A6(DvTpaA<4a@EC(3!DvCW5lKi0A|ZNbkVG#LJqUt? zDAC6tNc12g!Kl%Djb5Vn-XeO57CpLe%{gbE=RD7|-|PG5egDed*TvqktXcPc|Jseq zGfbTR^{o|5clmbLw!ja|^3lL~+_4hxw+SNu<Y?&xeb9ripLNakWS>=0vM3pPO_5qt zwu|C!z6mKE?{eHo^-|n?p7jVnX1nfo@@7`XN>&E^b|A<5>uQo}e6-PL$D=WCRz%(` zJx8=;Eej1!4G#}b{T8~n+|{KwmHqWGpQ{fs&OY6V3kSPg*`c}A?gEi!HrC&O3qnJ^ z*=GLZk9xjf$TWLXW07YQg5BTLOK?WNDS8QY*O^LkMz`sUHUx4@x~5{Zq(NDlUJAur zH}`JPP}By**U&n{%Q`e-4)VP+(n+sLjM-;|9J6a-KL@NYsGOywqeCLyI+V6^&-*&V zjx{BcZcnru9uFxyjcF?`lqiMJ@((QBrx*e;xL0DE+l_;aIo;O_EcjBP44wxsVJlm# z1&Z4#AO?4zD(jxW3dO_>k^6)aPrOGF10F5OykvUeGwiC<YhU3B^RO>vpRvc<M&oWE z2iI9f^<t%M5ItpALN0>b+hsyPDY^gk6BC3;%Hbm*0CGl$O2Nh44}vFqcodBXB;Me1 zK7CiP9YDcs4k}?t_P{pk5@+QirR}}mrhPC`g%}{NTR|E@fT!LwW#GEc#7SsAQySZW zqMEIH)BN(`7k=xH0CH^sQ2wV(cObR31(Vr3b34;kI4!E4!VboW_dotf{E9%_iqM+U zXirzM75xpTCV|qBN*WX4JM&56WMcDwk~N<w#!b5%ie&%*w#DZPNVW>ODQA*&`%31_ zAMC-#<Rox)=74-8D+e5KU<>MNSY>gq_#{pt`baGMvq~)AjgQ10Pi#wv`JBwM?v+u7 zet_=&8qU_a960mfj@M+z6+7ef006Oc9x`##ED62*Q9)PIptQdDjtChQ5I!mbrIGO_ z@FoPZs*pcprsVT)4mB&5!Q$bm?R#%~BS8YngI!lgFn}~q|9&uOb8iw<+kxk?r!x({ z8^D580HSjz0F#ZqN5^Se%`uM$9}jdH|KEp!F=xTZ;lU^HObqGno?6-$4niPa`d8k> zxosErb0VbN))55o@MmEhD!LmB3{2u2K`hKgYG!Ob<)=wH5?3GGx|a8Cb<wx%P;vii z)x?0rMqwJ$wF@9#a9Sl2IqitqOI@KDR{Ln^Dev1+3lHol>nyWqyc&433puD55fi_6 zXma_He5&U!1&Rsd{KDHjEU7yTMf7SSA->!FM41!DT)Z?kk`lk9#FC>#_je+`US+#= zpj0@Uh*tO8W=-wFdPBKym!{kaSTEY=^snS^B7>iK5czrg1^x4rCMm_H8ViAWdpk}8 z4a<#CMc}`?EUDKVxlB%f?g-ZO@i!l$wn1H^&~Zue01eSNVB;PMu)(g|fL~-GZdPlR z&>x?|Ncf<S7HP}a?wy-Gr^&=cwGq-Acd@kMQbN{^q=-lv1cK39TkQOEcyJ0rwEh3S zboCTZq~Qyf?zg2INjKS*ht~gokNZ%J5qQ7l0y(Yj*8RzH`fX4jaX$39hv|(ik<ALW zkL|e3th@O!_Z1-05@jJ*`QHzNSlZe`LBb$CL<vq+5&dMrXSfB7G-sBRIlA}0h<jH4 zXep^Q<(#!qn*|I)If(D-5`MF3)8tRu8O&eGB;i%<1W=FjbN=UDbk^fV<~h&B5uYYY ztu4TRqcpd`=UnNbUQCxeL|Rd_dI7FUg8{o0$AR~S{EL`-S>XvU=JCW)%yjB_>;jmg z12=JeMpxb)4nvn&f)kK3F_%ZY{!DrcTIcl8rI(89?W><BU>42D>UbmuNqXc`J@9vz zkP>$Z*S)uF1)m4tzvS0{p<Xd)SEJZ(zlD!rw6-sh5g7Cb`COW)4!qx=%MO#c&IL19 z6*N3Ko*&16x38J}{CbwDO=bpKo%jryrJ=Xaqj!9RhcUw<G?j6Pt&!;3r(@8wsGO;O zMDK^?-+o8}@>Ko&uNDvn<vV&0Wrs$+TOE~L{{(}Ct9Y9GW(zcMl_kYZr0$RP#ng}J z52Nqyl4U<*@R|z0GheUsl&m=;k|jj<Y*1dDpQvL8BXN}W_(c#Y9y~SE;3=6_A?ZBo zN#)nGwO4i1uYQU;v)KRpI*`y}I$%hyCk6F~RFu-S+890cHqGl0jKsqynYl)FUa=-y z%N$aWQ>ojmf|wcn^M%LeAfRIe;2RY_@q4GYnnWXT>7^|lYH)GD+S%$=*qK~ztoN^l zzpf|K1zBv#XMkDR0C$k$|8NJ@|8)n|=k4mi9ejtogLLztMCXECy7q;{9qZ4De<d^v z9EK48>Q4!%0T4ngO>+ugwdCm(Ap14|-0=Q(U_<!H`2K6a(X?bOAoh>W01ia1UHs`I zt+%(DQ;T+Tu_}_zdxk_CWx<Ujn#vTvUdB5D@iWD^>=W*iZ7@7ffG*M$5$&)+9bxq; zdK==$C0V@!*TlyFvT`5+Y(GEz=KG~3grU_K<`c75#eZpq5hQAEKd^RcmKI*Wp2MVb z82@FuN%4qDAM3zXDT9pm2^|tQI(8>OcAeV4u4Vo9^MBtoJX9hhY^>&<T?`rgIf<k< z18Moy1pXgZE@M$QRwxda=j=6j5=w1`uZVbj82DK2VR}jDOCrHuiQ3ho*z<n2y_gMJ zF=4XpZu4}nMGb+y{JR<G(&mrCeo=h$-`N8kgJT5(J>F$=i>Oazp>5jPN+Nh#w9Jzt zSKoW^B5$TqHP!d2@i1UAq*B;>7o5~)e4PW=3uRFBh#frc8jrRFfs*C$$HLr>!3-u` zW5h1%WU})S<og=>dOxl(#6Q}zazE`rPoQ6@AY~^cJi-4Og@QDG&L{QyU6`Ew4El_t z>fb#E!8=KFDB|Ny2o14hp9?cMxeC51Fm>HScWtrbRP*K_+^Z-aY>VW(6HP|PTaOc# z(-rVqkK`N%1fRE=R2}0c*3BGVho!DZdgpuNKs7P<LKF6^z=zqB?bNE1rMnhinvlC! z@Lk;dwZF0e{%4DWYk0WuU^@g?7Y2DStQ8MYGjC9deBcp20MSR~R4Sr(KkOY%p&DO_ z0aI!vE<|0soZI?o^p*8j-xjX`L(`hl`m_31syX+2o+uQjUBiQyWcG{=u~*%~Nfz&N z_!uybbtiF|5UF}S@GW^1PSDsx1|Gwjc*g-nbN)MO%Xsh`Gh04vs<tqI)IJB>37&cI z6eB}Z!7ywe@Bu7-xVgM}9sG>%FsOBp#+QJ4EYmB0SvIV#r@On<J($I}%j~UsQ`GR+ ze>86YYUAqp-a)4E{(wi=w{hmCpQ*Coj3Ot}o26NBMwiWFdm%Ay>8KEX&cC7l(}_b~ zSy;T^p^ZhnO#_wX)^X^I4KWm8{ql>7;W#~{#YgOnZGm6e!-PlV*P?HfIN~&ui=`-C zY(I*>EWG>B{JdG>GtH>A_|=q&?6_?7sn%0FeS?O8n|YYI$ZE2iJu|T!-ij<mYWMF( zEB52!R1;HbAo2nEB^Rn)C0Y_CrkBG{oYYhU!qs^$1~k&Q)lt};lyk+xbmogx%F+n* z#6aD;*+ZrH(}ygYh3IjOur_Tx_!)Sx>FCf-|Ey&k`mm3~5Wg&>IH*qyLa)tEo1$_z zbVKrPnt>go_WYvSVPG}8#*c%ieq^V+><B%hd@!xX-YK+BHu^LBzfTW$hzl~3(+_oB z#iBiqhgx<+>sgrav`H+Y?G<Xdj2m9Uqa#4E6X%w1Xrwl%bS$LN(J$od?kvge8GB+m zKYejtUTWFjm{&1JGPo=i%jB=*rE#(lsWR6?j)PW|pE>A?i$apP9IJaMGK7J4_YBBj zTYe8#=M#U-3hWCtAb+A6undC+jgevuyf``QbRg2KKwGNYHT5?y2j;UR@|0T^(wJ)3 z^>l&U>p|SFsMe5BU!GvZS#vwtxMemA)(Vv%Q*Aw=<{uM6mMp%}A5@k5TGjkC6Fr=X zCZNes*+)&<FrAx+v8-y19QK(6pk>edtS*ne4(w$viWS}|i9mP25A1rjAI2}eH!M@~ z&3fVE`<arkZRWoH&9sJrfK|DYbnbXTQ%qt${7T4UagNAzF;_ASRZ(mtr0vDSnik*C z^C1aWveoDTZT2S{3o`RD=u;~jR)#b6uZH4_w0gfXP(yVsGD-#$*yF_9315n1|5-~h z%dPO%<p7o>gTESOjI?|`x{YU{c+J7#?;05nO_(g#0mM&QtVx^)Wqc%6kB|6>by#F` zg53`CCPHdnxm*6`e}AL#I5<MD9}j}fqy?7(@HYj1Si-o=I_z>Owo7kmu#=Uo&KmQ; z13VG~!XCd@{$Vo?)^(rS*tZsHUCh}MX$@uOl&vh1pO-_gZ(*24LWr;>sQb*NS{Gfc zI(m*J=?PK3Wkol%E>_txl9@8sHBqsJS`Y2i4f^Z1nilA&eTNo4aR?0A`<SsAs5UFA zFV!<Q5Y<BD+*U2aUXks<U1e+2bZ}XfHXM;Ew$g=uJo^E6JXN2Iu3|-{=_R80pF19= zha9ULWThyd`Ps-1UBQka$0)qLUwzE7x|o>xb9_Vw$0PpN$bs>Z2Zus(ym!3t*Qx%u zDTIU?k6e<Yk7{l3HSD7dOcY`wBx)sYhD!8-gL#nv^ZMTZm|1Xx%tuz(lajC6xlh-< zdBqtWn($OUL!kCqG6FIm0<gK>Fqg4g5)6j?KFUr-0RbTiGI)ezfyIxr4)z`bhrlH3 zm&`~B8_Tfz4duy{lt)Hm?|4-7_A|ekq<FQlSur@iKz$w|CYoT|dq<l5P4%XV$Ra=Y zxFuIZ>WgIM?2*a}8s9#%eoMPUWulx05=R^UyCL}Ql4^QKH{@V~wSugfwyQE;be9A& zS@y$fj@6jmR~I?W?)fO!4%OLghbf<1%F-)N8mB{``|n6y*MAv_F#6e0uOifsWeRd> zLl5$6j$YO!6X@^$H8X}v&R(0rgTHlu>G}MB49@?2f8XM+8ujM4{a7JrCj*q(yP!J$ zE=xX}sy#T)q`4>G(*E1D{m*aeB!LD&5oBcZ^emySv))Fe-<X;CJ*))h?9${8QMlSK z+mfEUE+cSUPpEb>6yt+$$!@eGm32Og&K7fyQq*9uSqyNKHDA2dsk6!;hFbM4TFQ)a zJANyZx2=GBZ|N~GPo$Prm~B`al$*7c6`I|5-+~J7dp(TAA1cc(=njpt@`W=Vsb&>+ z(3<1Pi0t5!@6rUMXjH;ihXnS!$F?z~()1DJN3tkGw+>1lB1g*Y8!SVE@=mKd;@iz* zR!x|UTpNYLdE_)Nqb(6B^8ngQO|7l+--Z7_PvvipjhY)AlxoHDh{Y0|>lL_bjXTaQ z9@U|e%@kV@zxSq#AOGf?xE{j&ro&GBw;#b<<Lv5VpYuBl4$Rr7$Gx=g%wz`}l}n+B zA%8ww&6{aVR;!%U_ssVg_ju}7B{KL-BUp}7FEj(lJ5q;cWzPI<sDGvENUUNHO47I( z7PSJ{Cel1JNCg5XzTR>>`jGHCnt*+nhBOWnj=C?js3?~)S|6KnoX%t(u_Yrw;?-vY zURbaD_8kku5@kCyMX{HlBCCQ0%`qK&*kiKhV5W`xC>uI*AM%N8wBxEwtz|30J42@x z#J-B|xw%YDiy}HJUB!nnoTjNzehhEcej1N;ZkFdSkRlj&pSIffGll-HjiKhkom@fs z2s=2rH@K5~{iegCK2-88?&L^h7XAP3<TP+6SBekCgWG+b)#8LhYVYF_2fB=|q{fIj zy^wJquV)L0d`vH9Zqx37+`)thP8P`o80|5B&{Q!z%jR(mJWjvkdi?#P+jxdb$EwVR z&uyx3%qti}x7@*@Cc}{y%TOk1<@&jA)@m}I=9G;6!<*^EX4p@T&?o7UiA<)5itr69 z9`uk^BP)ZP=}np^MeNa`&cY@OzkCH&sAatkok}#^)k`0rTw1kMxh>{8K2Iw#lxgTW zL(a6nigjiTCS?t4!%l#dpYcO7c;ejLKkN8bfFyX`&JpS3?0?f2d9$e+<6bdLyec-7 zt$>jYe2hD{+jo;hpo>WG&x??S;lDep6gbxe-s~iAweGAp59zECqn&-N@9ov-_YRNW z-*IM~^XXJkmHSzGIKFc!h9QY7!DT{R+n@Fq$31RXyvydEZ{oay>vR-_ear9z;hllO zx+PzUkPx?>xsXn5OAz^lno9gB$76i<f!g8xffDYD%($7<o3g%&o=Nk4euK3GQrU*I z_~tO)!W1URyOOX_nFCe^+f<z@YW>n-x`mjs1*?=GA3kY!V$*>h{FMU5wZ#}=57yK% z%k{Ap`1mJwxq{}prBLN_tCaKMgmWDd)TESez#i5}le*~t@ta18d(&?E-z~(4idt3l zr`n}a1nzBRH?Jw%4!GIOyl^n){OQ!zVgQ>7=zJis^G-t6sU!PhNZV=bH8QJ}rS`sf zv^kr2g$+lx%5g`}AhX!6&SZE<@?8yN*d2i#rlP{!7KQhu(uU@XrgB<_Fm<hoEK+e8 zM3|5yV?b@>y5caq+fAg%s^bSRrpq6E&hc*b7iJn_1ODCQ&P~+$0&0IOIWpC}R4OJk zq6}QCh3zC)^^X_#qvMZ}a+VL7l7%}4lGs%-m4vgFe{hwQmgWvz_ut@Mq8;uN)+kmk z{&z)@5z{D#E46=q9CtBd7D+M0R5$5baTeif(y7)paAE&{E*<!Ql9R}Mp(BGLzNh#* zh6M(YvM?rbF?1|A1>WOkupcXo45em%;8fxpa|gZS%e|p;AjNbR{=PT9ERFQ^)lm}9 z_*<Ljmk(3O)Gm~)vd>f5qIuGa*rJ)7Rwc~t*|xEbUHf*-lb6}Z89(YbgQ^`+Y=0p9 zm`nuoJ(YDYUG3`7C64iq^u31b2kCsyj34fYDW65gs7$<;TuDb0T!9;_lN~ATOEK+V zjq&(eHq=kZ8is~3J;}JJWL3E!;ZkLC7M2!R8g#vXxl+J{$gkCt2sZN<;J{&qD}~{` zdA;3#I}5Ag4pv&M_#a)ItT)7u9|%v67^}l3z?bjf%CBqEHpzc>BG;e*M=B;4KTL#O z1>%Lu4WMMW;b;gzR?H3Gdf>pZ9Y|HwPFH3E>$2j9vu-@y{_so1kX<Fg21IkJ-u-%N z=zhB08q;@{@Rm2BHtFKs>?c~X!~U(T!6?xMFG;pusq+{+<A==W{I|?y@n8$HjvCtU zm7P~Ff%hoJ<7vzR*thqcu(td-z2=xzZXu@n7+j)ydFL!PIfdb{)dKTJD;noDtHUa* zF`{n!DX&$v4D8gYpn<|x<Knm0>ird0&9a%ye<>8UU-?DwwO&KFcKe+rV`_=qRuGfG zf})j5O-r(H2))S8K>7y!s_I25+<BFuZWS9<Hg;=FO1w~}bxbp$<}~~nC##VJBa<|w z(UjR6`9$=uAxRT<H9teoHL0g>dGYUO9%^PN$d`1A8@f1eRhbWx!w>^a-NCc8<^Svx zGhon(eluNC$qEqSxB(3CWx$r+3Lv((U0plBVp{>_M!Nx!AyYTQj{AF$V&OwDFCZbP z3SkzT2o;=zR{`3-W4)KNQ+@^@=fya^_W_{ZCTNX3Ogvatetau-S{vyG^oT^ZUW}9Q z!%kqOvH<gLF&K--fqKbkA`$x88hg_Cla7Dbt?bqF(F22W=$#*_MerX-t54iFn_lIb zX3IN|_KV$~tTx_=5#WA6emWrkD9-BS<-o+j%C`yiCa0N#-|Mk|>PlbQUY!(j&(Zqj zrBZ?Z6cR7odN5v58ed=<pj2-3k-_6|UqxX33)bdG$u|MhO`ef5Iea~bXu`7H<J=tA zlpk34ht}d3hpiIpfb`_<pTcbz2$MK>A)XrG22^&F8;As`ssS^f4bD3<A+vQ3F5~<9 zs9PHAAj72)Pz(Hny&xIOR%D|ja{t$0t2oGf5CORo8$c7?F|>SA8-6!K_IX=4t8<@} z4R65{?I$J#^CvAu$V;@`CA`c~L@jA+j$NQ{cUU|4ti7)og)!G-{r6Oq=+)^NtsPSj z)!a*)2*ns}ZN3kGC3T9*Oea%2DS1?L+-x`xNRc6xw&xz<t>oew3>9;k5~qXWdiM!K z)I9s@PLnhYO<T!b{oH=>UnvbE)N<{w&l=FS9l)fylBxrQ^Ty}6j#O_BN^#elnVJwq zl=}`;zV=pjUCBjaPaN`>B1N>-!wZE~BBrxJ>@oTHql=EnYlnjvmI-8PrlIMGOQGUP ztDz~Sz>4-|)R)np9)Grz391A1|GH}b`E>rb@#J4$KthX~QhqqB-TU_(==BQraUbFb z(nlJZ-BwuFCQ7qO83lRqb;QMB#|}M0>=T}VIb`+@m&$n-`?>zN3i?>%@;|hp;3axi zuw3HP=L`fc<3I)AF!E+~sQo3tdGy{)4K(1bJYjVK1Yt2Q)7|1^Cu&sm!Nku)o2PI| z%NL_eC5Em`hDHRiO^-!u_k*T(R-i<g^6c{0+EV@W_~T9P{LoL&9$Y@;gSwjK^KT^H zndGKXWj_}jRjx)?(41BF30(eNxR$-eEOK58ux3`fx$jV7$xmVzI#p+j`Rm<kgRc_; z<oB&7Z;8Aq*%&prVR1H~dK-d?9wi4Z=&?m$rg#n#t2zf(#9y(%kb5g?jBSnp{Re%H zVQTd=S2@UzgcJmh_X)%!7J$3RO^93vpGX0ZL%X%f@_Yjz%Zk0V^v|p24++FE2xW8+ zUdG{)*AVA1fTSS20?j8UYd^H>N}?kZoY+dGNL$J9McqjXEwYJfz2e31wzE|vx5M5X zcAP}&dZe@qYC_SCXfdY+r&M!~ce}ag{ddW_eLW`9Pcz8(W!`6qEk;@79a~ZxayVF? zFDz<!s%wi^d1hqA&E(wl!vpytDO~j{zC~op*KHAx3By<YWI%q%getpKei>9?Ljr&n z9>}6Wg16iRA~()8Vm>b7*Bp;N;plvDHc#cgs_4`fYH#A(7qEmf+|W!f@(7<xmlB-t zV?rcsF(JG=n*UjG62mDD2SX>RclJD9{!P;d<`zk*Yl+eByBpr&xjYI84|VWW1&@$h z0N;5KD&x0k{!CRI4oXl41q_)m>US9!!5xbiM<%t~3|uet7TCyuzU8rf=`4sweFApz z-SZrVVZ`Ux$v<ThpMooQOiNZp>pc%7<SE5K$~g%%HkYyi(|CPa3`kR2l*)lVyr>4e zvLmUAk(BXn5NTq;kK>I4*Czl>xIi~H&}iNfeB`W;-0r>O<MzC)1d8x7IFu0CND8y< zdQ)s#r$s6$xYn;?drIzLTh5%_Qi!tXJPLwhKeZfN-!IG^eQCw{AkV_+QGz*s0NSE> z>Fg@J?0Gr!h}b6Mw)-O;Jop!zqIWpAMO`c6^}#PZxR8mxIR?q=dF(g|R3CFTK#!qX z1$=8c;B9VER)gU&x-LZ6muCQ-NGms3_Ry8H>lxNYr+If5K>y=_AFt*jL>A!VfT~MG z9@g5X0c;`lyYhWOL62{XIl)h@?Tgyiye&f763T{HtrE@!7es8?#hiXsM6qjKY}GBs zXaZU}I9x|Bgh0e`jF&t*=+%K#p+dndgze~NGkL)ADBX889SP8{B%Sl$+|!~I%2J<~ z3)xD-Sn_E`ps<vuh30%K8G{%@RGWN_M?3j`$^0`(RP2G$V67P^)2*|PbZ@y{Oagv{ zL`Vdmv{>aHEG0(FRXOpvL7XYzn6;S<%pB!AE5mgya-WZ1(RJ7wF`OD+BqtM;IQ$op zas{*F)y6aS?&SMlkJ*2Jz%Yw+;O%-6s**rHMZv*~>x1f*GgMkB6cA5-LJ=R5V%kPv zm|DLki6==nw{{_Zt48->V?RJ)?e7N)!B>F!Ga^n0R%P@$$c5p9MzGc!0OjzFRRD^@ z7&~oDtSB~ObRj#JZLDUBc&p#^cscrc3Rr#Rf2lg@m9X2Xeo4}0tK0tIP=qSiHKkI( z^T6l!Z|`uT+C}ZN{s$7{M`uBAJjSigw4Fy@#^-9^Q6udh<Dct7I5vEHF<OL~LVNU1 zo98imZ&lTA#-BG(90JK}$PCmB*kgs>pgRcqS$H9{iQY|zb_MuQMys}cILp_$XHDZv zl0;~I(U&eGbCCfy3#KV4Ol2=p?(ef?JscYhbvy0X22<q`QVzvZlJuxbbHIL{NW{;X zq#!&&nCVbWVxd2BPQ~HFt5Vis7a4)~jxSR9&eC@y!{oYeWBcr#ZV*tRKlA!(B#6sa zjuO-_SY|8sU12hJmR8`o91<zKxcxW*zouTPHN_(%^vtxA*o><riJ3J_LYZ0mqEb~e z-K#)GfuGREEM4d>^J)0Ch3$swHq)@&(+{J~kq0b8v0iP~T_Mu7Q`xVoPsV(V_7YMi z{`HL1Q*emleurB<nZ0d)+skhKV@Qx_6_-I7yZ!@_jJdZs?+CjchC?Koi=}O5!5G@2 zi*t={fMlPL>@#r?Kr2M#1om%DfHgdGn?xX{CM0{SqYoe9_q`~dn>6{XC`59z{|>2s zg3Fs^v8@(C5xbzWgYoaN0?+1x(<r@p`SzN72-Zpr+bhehpPk7drM2EjwuSuM$*$Rc z%d-)!l0Np{NvFUo{pB;xVOp`*+i?lt(W+W5EmX5#?ib71%~C!8m<O<gf#ykf2biQW zh;|$S33qV9UU6Vd%}4N}Qz0<t7LqC{MoMphS<T&Xey`?(>Sk4bz-Y7mHAp&vTyMLt z&^IU~vFW25#aZ(PS=Qwk1_qbOxtAJCl6?_67g-t?Iak8atNm*E=loYfRL-M2LhpZZ z&pYo=_xvg@qZJo(d}H`@1z+#F&c#aM@ROms2~{Jj23;otmK`?4)-B`$mXAt-J)~wr zNk!Lfr^NKbg3uNQE?6%emcitDnzmt<;#JVVd;$03$YydI?x%G<f{%9z0-#yG10%LE z@S3B=OMzk^W!ONnmv3)%*@_<B_I}ow$dBEV$S*LU?qARqH7^cdsb?QeU;4YoS+xKM zDKsQJ#eQNd_`!;U6sB(N;sKe2ys_&g$(dbC5WX~$EO%)V<X_+0?Yi05`<cHJ*gc~y zPk<b03~Wqz31X_tA3vBH8ZmU=cvR&P3j&YFKp@~Nu)d%KSPPzlolZG`{E46=YZr;B z2FqCGjex8CGf4F?6fkLo$>6A-=2JkP(X>L^tF^MVzv-Jf*7?a%(_aAg>gps;ABnTY zHTxEtbpkHr@$wFkY~M>@1F{VR-^8B6x%Zq`&whg#I3b;|T;kJ?Nj#JD(<A%+2_XCK z1Cm^kFZV1$`E4hLz>a3>)>5DzeXhd!kyV?NS#<2l85%cQX=<9?(JLz<V-l8Ce|mDT z;ZVk@BJ^fc-yQ6Tns@czGpcg7#a{->L1bQ8=UB%Fpp>KI+zq|T-%*cUdv9$9WU9fV zdb+j_!}i@9)w?}~tKhH0Y44eSFk=U@;^c>c?b!-vfc;tt$hMqnamRI)gXTBIw(C*j z+WF3R)+W9dZv3c;E`6aso#*<pq-J~k{@QqLroo#&H~ML-=Z`EqNp?~i@0$MP8M#w3 zUEq07uiV!3<aAQ^VEYi8EB9nEez?nlm@~HS!4m3(?~wkYN#D9oNoK89K2o9U<p5+= zMUkG#gG|Mv=hpG?&x;psbWL0*&sQ0(>t5rpT{+$??dgb(9@ORcTp5)ZXQz5T*5z8~ z|82OqTco@IR9pI=EY0U=y+a9ix3*M;M^7CV{gY~4+e0HiEXfU?30RwQUgs=fe@@e( z?Pqzh(>gub>kve%G4(9>iv8jro8_6yg=azS#m|P1DVnwtUJUd4`c9lyTINN)AzPNq z-m2qWuX15_%NhTEY%_5)uj>LUNr)nY@A?(;d+6IsAP&}sGtG@lAJ-S|zA%rh7b<75 z&wZT0bb6(EEyum;>$Y2iN|`1sW?dlqR@jkOS^Pn7Sg!38xr?3@x3O<$@(ZMrF7A8e z0#?V>D+z1QyX`_2Kj6u*PsS0{=}ytS82`zTZ%FcHqKkCDb^1Y<*XQE;O)+N~_x-`l zgE2I_rVvDGR6b@{`@Q&pePL5mz-%RYIf!MW3cEb%V?_J3*x$(}<O-=x`WEx6LB=e7 zMa=1i>7o8g;d2c=_x<Rcm6*2&tAV$+9g@A`Y1U6A-n8F`Z>F42@t{jG?*-Y&SI9H? z)nl|8PlDDQBbB>zoo`Gtc)nz!JhQ3WynW-i!|^KLy{6@^+VacqvYN_mEdp#x<)7AQ z?wAuG?RZ>(OBg4Za$bl)EitKp;6IzCuGkT<CEP_KW)=tm>9AC(%gje$CS~~ZFyRI+ z;l|~+IGECMmE%8PBkn!#3OwI(0v-1lh_dA<kKJ3#uM6#^=BOy24OsSD-TPwC%=aVa zo62t2_Xf`|C#<c&?r05UIgh%*VrZ)apc<8B>XrSLknML%9yoOaO0B5G!;1V)w!qG= zhckv64jrpmvJuObKqo06&T<aC5+gaf#V*qpaiBp{B%WM{IxPR#S+8$6f}{h*es8^W z9sbu1KRK<ud?1_|22P9G6|!p*y+WeJdmw^b-1KE(^A+c=yRBxGpqH4QJ9If;(0}cT z5i?!*R;89wB=N_UW$TBcyR-G&w=c^eS*q$I{8N|XC-$a$yrXw|ErMx;z^ZBBP3yIW znO+mE<HO=00Jr^B8mDR?8JPv^$%66XgZBXnQv`b7?}dCzOWh6<<h&Bji6nmL`ERzm z5q49c5BzS|MM~uHs$zf=N`i113p^Z4Ez)9oVBr|3z9V|hL5JZxcj^<U$s7b64eBCw zpgloTTp9<qM`SV4l#IHxnaa2`jisQ>P|TiBM+Cp~jM5EhyX|Ahhx^%G$@UqFhH0Ht zJyn8;TEEj@PnL=ttyhfYnvwjO-UW-W;Uyq(gNaa_FRHlNEPm1S<kVs*ir^^)3D!oz zRMSI){vxcdrwZyuV@gBZlL<l@A*U}kU*x-~A0_ox&L%#-EJ=6YMd9LTR(|DQ(DMwO znh#ef+AKzw|GrRUz*oXh=OqtsV8u(ftN+0P@xKE-z|i&2o1GL-$`A;vn#z=`2kjXv z&pLC<bHlTD&db|Sj2-DJ#Ct%Gh+zV@tplK)i@EwR_i5=mxH-YFmtq=e^5ILH)w{}7 zV7VqKrFK~#Ve$yh3qrhRbp}u{24bi1-X4jIQw3?iis(Bb3=hBstjdL{-7W>T=2z=r zMM&89e9in*V)i)Wy=an!TRzN)KzlF<TKWHonUI<|UNgFQ`W~rEbr?<KEy?>G=)7Nm zBwP*QILadpWuY4hUo?flP$06`C*zRtaD4GadZouLzh)52HGw2s`hXMs0gxkpmr;tD zpb2Mm($TQ)OT-vB4Qs{jMhtQUP!3$DV?FeT$2|P{DE1j}eYoZ%V|~ed9JIM$_Pp#+ zdZ4!8&b;@l;FVV>9$~nDaoS6`te|}>uw)|FmoG_rfA?AoGM#&|IKFWUTdjf8+nSWF zde!&9KJ8B(Q=!zYVsfa^u|J-XY@@yNjqi&=e+<|uV+SkKrNbfOtSF;eBOQ_a3pm3A z(oh4%@i&np&eETn(D<&Ws|bbdwO2RlP$u13yQ9n%Fa0^ZdQ7qY-tXw|O3oH)2;BO` zd&^*N!Q$=;-iM3sfIRGwrnugf{)Bul^vNF`0bUp(5+=epS><`t5<2xGd3yaIrmkpI z;)_yYlnp|AtZvoY$+W=xHf!{6uO^YgHj<rP=&kd)bn&2C)pOUB;f<(xkrrcr4X7du zz02lDdoILK@momneA%m4C$O&Kw?cM3%x(^G_T6R=JEK?SFYCP0{&3mo3ir79Z9Q%h z+0#g7x|fkMstrsiTVp0Y{-S#<NB3Vr8Y`?E)}x3d1i->cV^-r9_v_JkES?r<@?{bs z&r#*F6aVbA;n-^JLka$wDvSD~*@pRS-0!_<4B>)*P;GIeI=`3ncSxbel7iN4F+s$i zFgWa7Q*atq$XF*sv^HFt7C((PyL`FPzdq<BbdA0n{YlFV?df6G^C#hSf4z^Z7Da56 z6^IBfnYL}l5O{d4)A$JPw9mdFD{YtPF5aljv!Pu#@Iso1OK1(p(0Jow9Ij$a5&aSX zk*GG<+nkyN>ML5TluIbcQSt&R?U0ibAmF}2-1Eb_h=5YiYzLPusi9>Ef%Z!OKz+kf zB9DN=qP1RvQ8V3$6f$=JLJgjS2mWK0tWw_s&KaywphJ*)m>}kUwILbUIl^$GdsauP zXg09WIuv$^>G<siOSSRlgV3K=-~>o_>HV5_b1CW|V#$?zq1sB{Dt-sXimM4N4zgv{ zK&I{tymyP9SFS;3LA1uZ>nA0)PI>u2uh=|;cM9~}NJ6yF;`(^=r9~F7Z4pFf#58Xr z7j{qE@9A;R9_<5k@ZB<36*C%_)UnQ170TCp2ZU6iF9&vOVRPrlH$jv^hjuGpuPzLQ z1VXr1m!*IG3(HY!eOUYZ65q_3GY}lN{(0-D<f^@NmcaSRf}Turg`q`4oN>1aPv<J@ z<5!IfN3T<;#retowhH=}i`e1b<a>J$DO@M!P__zb>^ynp$2#;3rA<WV&G<1qHX82x zDxb?po1c6PJvh7`ZQCYqlp1)P7;-vL=V6?3-hR(;-7<i=;iDH~M>sk8HqUGQXfWXs zTNkWsch+kpF{@!e8&8B*E8mQi>1)RhX!4-5*cMe!N&wY2+CK13gUJoU#bjE~Vtyo- zUij9gtCO(ibdWG2SABTxS`;&j)y0ZXU!)Se{l%Y&FTW2spQ;{rMhE|eZ`;90@cuD) z`w1O0{vQT!X&K2>K>!<;+*{kVhkcX)W1Gp5h=uqwRAMrm`WZwTbgiV65}bKOMVt!{ z0+n#fVXvQKx`DdT0!X(!Z+(Ju8;?T$qK{aiAY<<CvFW0#cD9_rge4n}J9wD0lm+qA z($>8}S#^c$3F6(%SkdwC0+Xg|g^Wc=3}TPm{x*#d5wHS4Or5;o{yEy6Jp|L}iyA3? zwhE|8489K|5R^m3h4OJ>#BmbyNq2}$eV)j9h47E4?ppHjnQ3iz(t6jE6e2E<Z+l0- z5n@M>w-;BzIHgq*M1?|cxXWGOfFyCS_gnC}ok=NL8}fAuM6odSULpm~P3;q0#8j+` zF1<DjE*@oG=oveycG25)l`Y~bYf&(AMttwhqX7G^?r()lZd$xG)n1VM^bllM&V^oi zN<n`CucC$zW^gRa!DPBB3|Yq(sq%>7apRuA*Fi?{#pW8b7XanE^V~NtnZDg?;T$Qu zQ&kcyaz*mFg%eua<ANVXUZS6w@c5GK{5liDi`a>li1Hl88i<!viyGTEUTkp+VIm<! zpUdcr)tNr=yjYX;Hca1F`pD$HHMjM9;~=I*c1Jk|@u>bKEL$MgVqS)~!J6%B3(X|4 zbcH3>sqygXcP|$;NMqLHHPirw2!6p+VG*8!N>R>6G>vvSYOEbYv!okwrXr?YI)Ygs zvp-Jjd%(HF#!fJB@G~fIH++pXkPS_aM`aygZ*fV4yFf_<kJMtL_TvWSaYpC@+XT;L zv$HRRUi8{n9x^UL0mSJa3tAu9rHh>}@h%rz6~YpJhXw*qhAaKz;a<e1C--6M)f7II zNR(5U6nrX}W<BCQWVT4$VB;78lSV-Oa-tbVi^Y>zw6_8R^S~%w0KtYpGpkX8)9Wu9 zI{y6j6cXDj=iP*E&k!?=uXeAtitoL)t>~d<Y!JGMOg1^2Xz8KndFvoocLy#lXy$1h zpVNjVr#;G5J`U5VEn60kv-!1p1UlS4S}7#V4e2Rh%S3!!h%l`9s7!`O3gg%#@jJY< zi<omYGT26A8LBSnvp7=|-?e$j1(_W}DDVo$N&J+l^0&q^DXtD1vKn$;kX2Zth@9`w zoUwsZzRTKYZg&`GoDTP!QV{$z<}ek1(8q4yN|BdI+89c|9@p4IvYxQ@bnGssm*RS} z;O!0<#r$&4Kfj-Ui7vcEj6uQFoNTAYUP>gp(;LP-8Xka4j)6yfu1C1b+g(Ux%?@o= z>X~4TNVxP8m=!-Qr{zFkn^@c$!jf6tr3e)BJ1O`Jt|Bk3<7T4X>+6S*_IR4vZ{!Z> zWg%Zli3GW^{&xlp@b_y|RpphTcmaqbS9ue5UmHwYuQCGuXB?z<6!;NW-7Ykx=;a5A z|Ha$Y-kNWeZwR;F-ultPO$B#g-NGbNY0m_3kqa@+x-J6eQHW~|LhzbF<ju!(N9LpW zP#Jh~UopFgDCUyL8^t{j)o4h}eF&yr2`b{!vhYV9s_wG6c$Kw+;<D?{)X-&OpR2CQ zZop7EM@CyRFM5x*=N(L}S6)A5e|0!W<VFriMc@8W@MR3BTM=($X1>KC{fZJ^E$jku za!?fqSm;iESCB}oA(}I{ME&w65<-=!1nS#w*uyP7&iNm}WRU}sj_he+Kdsk=8~Hr| z<MiEuQRL}f5dd9z!?tSXW_Z67<4Dbl`K>I99nmYufruEg0mnPkQW-IZ7@~pg3dwkn z4D!9Kl!WTzuAXdL-uA%b27!%BEWwwsJDg~xep8uP(PZJpVT-5v!j7v%5=GJE%!%qu zz|$iGh+e)*rAuU4oa0n|ei|TKEAlHDQ`u(@VW9o1)HDksV<0<HXIh+N?+qtT{x(bg zK|<PSC*+P3W8iwbX^K~d%2}53836W+MW6>eX~M^-0MgpF?2GUapF7g=$Kfpd`Oc}L zcvRkf)A;|*zk`#;?ETtr|9fc+2d*PeWFJXigmVS_LmJ~U;L#Q;NkGBz9RmC6)k1Ia zoyJvz4q0E^D4LycEj+mLjnSiL*XtqD51=N@uc^%55c|DyL>wXl&BD8`lSn3B{zg(X z2O8+?)lbqrK8z2%P7f7UuYw&;{(%G-OPt*%o4q&)di{aI3(8g2EvvK{kk!zNytFz9 zfpz4Zx`9mw;oWV(Ka_%|9<SoCV@fqU%9@GcfnaE?bV=!wCxQI<Rrs1ZW{*%g9IhL3 z06^aN!w7O#<h5^0__HCBl-h6nMHN|SD0)tS9h>H{&@#@=*dIJY80Z*&P^4pkTV^}I z+J7I}yV{vq;I;*l0vQ!!!$-&3Ap;h23&406yiA+C1Q=Jf=Tv#*3a;ZA!kLEE$zUmm z?-XYC+T>V)VvY~ptkUJSYOnW?BB(4T(p1pT?=3eFaFX#>aE~b>kESV|B_xrzSqfYk zw3;1XY<U{iQP6*IaE3rR<5}!SReig9J2qO0UVG+BMtzjDtKB@}S&!%ODxq1+GggVK z&E$vQN`}C8y77t6Cu-N8254PX4~Bj_FA$Lk#zSz7SWjM`7|Le5sy4=t4F5@9Gw&-X z;lqHOWecDEQ@3%ZP|$NT7UjFeXSpyWD4^|xUJdTfkrGo2H&gp|pSC|C9-2p5B~VQR z6?#Fivm9IH6xu*Np1|T_8Yi~BDQi7a5IRK%Kh5dEcC^lWm0e0W<Vx6;DKl&$oBnE$ zql}NxzJy_%z7U;0AWc1%k*Tq3;l1IfA?_5TTxQYxf%C*6_jEBrB_nhcZ`9XpWehua z`zTHqs#vDWzIG;V>NVEzEY*|2`C8l0$Jc1Ncl6?;?iwJpH;p)9H9x#u{?G|x>UN-r zf^U2<@@g6%IGnNK)=c*&R|%;Ji*!6^`--(s%r|&bnfSyIyJ0ndQYtRNs^B@4P_ghE zKt}U>!}t7LY7e^>XCIHH=%F|LS)#F9AR}LH*$JdJ72LI#MhU9uP8U_;=kt(!Zm+r= ztFEtqYH+RLH&)nExvgK9PVfkB*hXfkv{AHMY1rrR68@r%T}MJ>;^$>NN?Yl^4hfYX z9N2NnL7ou6{MGdcugMm9W^3QTkFQ8C=BsHtg9%(af+EDhgLGKkP)vS(4VY-!J_`UQ zeMQd9vm<&VCQ)oN`iC!T%dSUb%`F<A<4~~5K;Z@ZN`$29rhOZrwJ5Q2Z8AUE$E5i{ zWX7RB<cP^fyjPP2eQN(MQ6&Kj_kxfwWi6+zb}61MKV+SfQC@Z>dhJ$*pi@GyU3c|S zW?f?oKL%SgZDEgdfD+%n-2Z+(gdySa7!$_gF;obi6E&m>fi6RA8UmL^4P^H4S+UDX zJ><Qyag&<xB4aX9_w66wcOzwcc|@lvG(Vr|6Ifv#njM&{%=_NR5ik;0N&$D9<~0s# z19N<Yi?S*6dMzHA=<+Yo*{~yu)Q0_bClo~P{a_KDcYQ_E?^YNxn4BoWSoE~M)898& zChk?oP?}HP;cR}Y7|YQMmG>Drq8ob!Z;b%;*_J>pqQ1Trl0hEw&dpC#U_r=|r;e53 zt@A2Yc%Mh2SvyE*Iciv5T(S7<t5Zokx3x{lAY(!Hhc?~ltLz~#1XdKPJHv}d8U@Vg zTxR#!Q7RSV2Su#S53mc+FVyZE*O1eDF~@_4eVi&HFp;Cgobz_JsKTT>XK7~|>19g% z0>`tG`I__URjM?t%HIyj-ag+Zc%uLGhlI0JlN8Ikci+K&`SfpzSIkvm75^8Mo8Xc4 z)8||yp$K#dpRnkOqkjYU4i7j5P?~+I4iq22UsP}48G5uYq!clBt$A?7cijf8F`;$` zY5)RLFbm&&t#}nK$>4(*j)zYutA0g_9D$`naSMTtGq`sV%w~f)<F4fgLZl5y38Vku z;p`rG+;#VhXbd4zlR)CQ9kk1Wy8RcRc$S0Yr~B>-g_p<4lCR0~1==XQ*QjM8d!hv* zM-mF<L#{S^hm94)(JJ@?-`GR_Sz1Qo;I=C*^`FM=XQMQf-wn@{fzU4b*U0bHfTIzs z(&Z|C$}hr2O+(XcO)_UJ=Qndj+r@uNe%kz<wttTy@fYiN*2{B2JfUV1M|8Z7MQ3Lc zMy+$hM0wU<9Bsa4QCd|pNGe?;E97y0gj837XV(^g7W@83pHDP=x|dW6uHX!5%r#lY zcV@L@ff8*BSEBr33CFSg7dj%Vn@REojr15ujoy=HCPjQi&$#IwQ}c712=v|`#wwF{ z5Q1^a8A;xT&zui<;j<qY8ec-zh3l0eXUgN(KXhxM+{W*vJTw08Y?5|zX(z`KI}sDp zdvij@(jxkl6|>NtN0{@quKDR5rEjs6Z6`4M0xEogoNDaD<GOqO=SNF|dP3{Zx5sWV zv`U77c1Iw6^GE-|56f+m$(=|-q@-*eH_Uy368iM!#eE(^I(?8wfyj$Y`Az?V3LR%r z^{V1?e64l5{^N~e#d{mU0YUh5$PY3cs3QCJ@rn-}vAbTxQjjJa=Zdn5%@GBtz->xz z$ttSGP%7hIGR8mt)@u>vEtB_tqph8^GiaQTR$j(yzxC2qub=Z_m%j=-DQ?Q6U+-eo zrNo0<sVW?h5v|4;sGje(Q(MzP-MN33AI7PrgSrC?)-U-Zoc0s{PqlzRPwXEax`hw! zM4qN9<gwKFw9J=&r@U`-H$jCwOkk#Y{980Dz=^ENb%Dxx!#F)k`|)b)nlN_i!vIe% zXi2SdM6q{r-jm<Gs_47?8UV_#=IQ+;D|5>xZd3mJRt~%?Bl$LUzZ~%Y<ol8db4+@2 zQRye1a9n?LEKA2AA{!z7!@`1{*mU+N5UJv<eh7?_^DjxjMy7DZ%kag7_ETy)C3B~x zDEkDqCWmVc_&+8cHtZy+oIRkI{AM1Cwf;InB#XG1QSF)fZh_S$F?5_4yLw2xFM9#F zC$RQ4feK|*y~Cvj^7TNw1_D~+r%EoH{l(;X$n~qdRs*SHALF?J{82X!P-4R@CXyQT z*wh*Tg}J4Ud&i9<ioW6l2PQB>QM{>r7L$GdP;!1oteFe}<FsQYK8WIK!h_4os*ts= z+tn98x4?(xIaRR9<=r>0n5R4(BoUPiV6yFZKz3-bCz0wqs2{QO{1g(`Om`~<eBO5a z$6>Up1?cnQR~4*eE>id2Dw{T5VRG7&VwTDmFSN)ROGGW8L|tsu-EBD7tlTHsQ8_ss zL5w<Sxf3%o_&tkZQfyZXl#P{EdCH#Hux;Hp!2~kR5Oa-ZqN731on=r0AMl)HI<hkC z-tJ@;bDd~^0RH_}va=PvnC(#ADZ;XzaR}WepTsPo@L9)bfS4-5c+|so%l+*A`zzn& z&;JY7y^U)kGb~2_UO1=PhU5QOu?E;LYy}?w;QvOCcKU^((Nc*BphX5m{l^JcWb*=8 z%oJ92NmBSK{|in1jp%q{q!BBKeNAKX;Jx&2=_BaJ?rx?^-Z^}SVE54l3lMF9?kjfK z#ldwPL{e@5_Uqk(h<2ykkocEJF;j+|hg8Uhth$_%FNDY+9=qNC7y8M=uB>O7M(gU= zOtiL|P_+=4cD4B*LhV~Ua(h12goP~XEFvnF0Yq(HIbTl!E<n#IMOE!>z|FE}q&6ED zglzrh8_fQ}NLL)JzqPO0YP^&}oGlnrT8xJW$$>uNZ3ju|T1~p*HH;=PM9^p8lUV?g z$-dJ>3-!jmBIZ28;STnTW<J8#ul1F`Q14|H5<(2@1`|CykwT-Vy-4sNz%D<k@f<}d zaL!HqeGzbCw?@;{DF%!25oF)yn-u26i$*^?_kFZ|SQ<IEgfW_^!&h|MD0q4{9rgp6 zMdMu{J$BcmUPw>&L+yI>`yqq69+Li>qttTAFDH{RVlItyV2UOcv{0LoJ-EG|!#KS> z!df;n`c_+e%fCe};{J_^X|F><jQ3eA>B-VEU6g%O!&<Y}fy0rSH(W$S6n$_-$XC!Z zCeI)J7%n(22#ZSvG~@RRy9%-w>>{cebzpq27ONT~Tgy$(qP$gQQoz|#Y0EH~8$k2> z`aN^`2qsGBSjm^2g-TwlGX-c5I-N-icG8W+@VVE2?xqosS)IIJB3^e9SvR&jCELjD z{c5XpKU)C;B^AGL*8Z_QTVBv1QDq$*C&>0;=Jm$?M6v{ODTz0JiP&!82VibCs-A@G zS86}7nI0MoNiBMP>e*zoJ|tw%9zpeH9r5K}+1V=w$~T9Wh3W<(uIZs==J02VZ|K`c z!=MP4-XAPbhXEvMsY!tE+u3@fyfuHOM?D^U8VtKr>lK4CbsC&kyz4{RJ;Yfr;COKB zXbSH{$TjHOW1YUb79*-m_|T6SByYMplaHX6>}QL&ZcqjX;_Q{(@i0ks9dQu|=7iJ_ zy;%eHu=K3wM0Q#@9h=j*L)pJc>>3p2xP#@8zZu()aG+LouNBw2upBRegNZVw7&(Pm zdk@hMhC!we1(Ch$7G?iz_=s0$&U<%hcR_xSjxoylq+4LJYfQ@9f?VPF2-YZq34_yd zNR|qZ(&8~sRnnjd3)i5dw7sU81-p0+tZjfHHo@%%&c5fGmuWxW()@aDBzL|C;^uXo zF2<tYV^pd#Tg$aKHkM50D|p>12wgY3Y7+*;+o=>z0TVJw$Y5g(0*&kVhC82u`FgDM z#qc$#<ugIJq~wfVQ^W|~=+kT5&R4HXGB+?c7?S5N%o=nuGb}C!QM0DScdQzjkJm4^ z1RVaj%5v}`|J*9bU{%JpP{&|`%=7kVa)E_eKqfW_4sn~MWCR<9NNnJ<wfGoJNF3iL z4$b1+NovUMg0yGHDf<cEgu+vQnZYhga<UZllS5WD{G1P?GSI&kj7*WkpA>|)uuF?9 zdW$jw2O&oBl8!qn%t_2fsf@wc$lUY6<HVl5e9_$x7bO=ZVxA*uQiubkJ%}It?Y}h* z!nikW#bRuE`ENB1f$+eL?^wmmg~4=zgnu~ZkPH}*Q7W2u*!_NrN!YP1kGpss4{qK# zA01l%Iz*Bclz#0OprQM@y92U%CY6PMr9R=gb_BRkW*twtSVEeG*U+P^H@|-tzK`C~ zEoGrF$pbN82cX`e3~FOQ764b?*kqCUL$LhiS!13LB~EBSta3D=j1`}v<7p&=AUX#i zenl<$(MGxku{8cSu7#`Rk$9B=L{u`~FA=KEcMg;k*XSeM2Z4&&JSQ#)e0-yR10jJz z!RRjUGEMTc-UKn*!N(6uokmR3UUINTN8&aL9%O6h%vAv*tkoNFDl^de5yT|6;G%^{ z2xugghe;Z9_AaUAi+%%`{ss_21bvs}z5Ni$A+7lX$T>EEM4|K3Yq6go`!OPixLx_R zK9UPf1@F{*TaS4d8QrUe{kkk6J|Iq#U6zgqzaWKecH&1cxNiA{<k$wy(X0(RcNksO zzK4F0^CAJ9pz_aM|2J&y0Zi1|#GId&Bkc#5#$qtve<c1Si7*R`ha#@#KbbuL-PP?N z;JLR!Y;W$?wtv*t`={nSL~Q?OD)0FRJh;b{kD!Fp^N5WaMQaf&ip(#eglO^ZyyH<z z+~6x_Kk=33n&UE~aWZwk*Zy<Pr@Qh_&?L|2Uk`k0M#?rS7k`dR&cD*EbM9fH<WrXR zk7q`vVGCr4Cf^K>+<+nuCS3LvR8@e02$VMG?}Xc;S=^6H=VeDnLN*QxE<tu0fcW99 z$uQbas6a+ioSqrV{k8jcQ8&Kg`TMg<`Fpbig<3M%?;tP&8^nFP!KAfllIl!L2-Me| zPyfN6fHhR3GTy|IlyKTQ_3HurrVvRA=LyT73inH&1>FFaMhoX!7mjt0BqMTdlHW1R z)&e*Qx89$v+O-0u6m=1XK4owxH(q)h+@3xYmGJt?JNoKtPia`~QTy|*JLil%Yhs^{ zkr(GWgB!{05<#mwKH4rUJ6`%Vx}NTbsn0$*m({KFVZ&e>i&XGM#0clLhinkmFNxSt z>yD^f+v0CGf#6-hSwtF4C(vH_2eTXQe#;a-u+<@qm+n*9k$k1PiK&d7vQ@PPl682! zm{D>(7P(hEh;fdZ0FkaCT1TwzR5`>H*myL~_&%oj#O|W?d9>CQA|)*g<*PciQNO<j zn*-Bwzn{H>#LbMzdg=k2oN-s{n*I0qAp?m%9-doVji&=lp)YPjSf`aWt5sG~6eDkL zi!Lzeao6~`Sv?H5)NSNu*8lQLna+G%Lnjgs9`~S!pf?Kau_>k(i7&iID`K-9d`Gth zA92&qzULCrsnrz8q47xf6XC<b1)=Xe>}g#x{H~>nlY`3pb}hFCY0GvL#f0B^B&nRF zC-9XW4tyGBW=cM2PMgyyO%glHLcbVJppLM$&#W-qMK1Q~Z?PMtj@SC!ULCrrb1|m* z^!}LAgRU3eEKHB$L?iKKf6<HjBoHfPpe%`qu|*RmLCmV^4f4j}B=>(Q%B`d`?f<G+ zVPTN1b)w{0TbTD1oevkgMRcYPUeea2*TO2ltWXTH=LIq=SW(o3#Jqffn3sakq5R<a ze)-Se4_=+0hCBV25|b7)EdrSZH1vD&-Eh2|tiQ4VJcu1`g+Q|ZY_a1@!<;H_Ken<S z{r9l@pHkpcH3TA7$&a&J1Z%jTAPhyD!474<3{&Y+e3p3cdLh~6cNs#@I{p8#b=FZ) zM}4=4VUPg@h6brYy1Q%Wk`NJ4x};GWB!})sR8j$vkW@mtOF<B%8w8}g;U1p4&wKCt z7t5ut8Q?ePd}Hs=j`D50w}`<&GAYXw$}m*tx;n1gfj*(jWYyURSSh*FOoz@b=vd2N z(j~lI3@a{xi=pOe)pLbPIe;#sN9VT=mdCD3CHb0on+sS~X>P9l{5J-?FQl8D8pTG3 zhVHXDUg4~u)1z{!cn=koD)e;7-&W;4CIV?}(Ro(Mz_=j|_Kwvv9#azldt!47*>ljP zL8m3W0wZh3yb?ZNfKcr6z(KA7#?PVNZ*qC2_UFqziO!faKu$XMeDHT$zSUP_!|tM% zgqvYe0@I4$&+IvcR9#ju5jrH&-&okuP&bip_)ic7CjuPXRnud&de5;CrWhz%7phjA zi8h}wQ;4$r1Fq*&%WMa}EjSHO;-4?7;o~iR-zQm7=b&pI0J65P5uD^{j1NAUC70?L z>867-di47Gq**B$Xx&oIzPBAfvMEcN9`ZzoY@C6EJTByyn_jr&3*RyQ-e!))I$s;B z3s8Uo(}ti2P|td2&j<QGFn@JFaCh{iYO4d;Q(DsCcKtfBqbUzyL&l^roGBrm{pGKG zZypQ(fPXE!)Pp6RU1CiMLzyxXpiDX*T!oDh$HN2><vfPTb6DEKGNdQ8bNo<=lxxkS zB>426F>L!&3{|ayf%vO>K{Y6Xs@~6MDxgY8bOzijC)73XKi9dmXLyJWf}-{&bYpp2 zVN7K}Q8Z=U{ehv~12l9F>;~-e$wo7pVnI&oL+!U{A$1E^t}Tu`l&u0i6ajx7>W}ol zj>L?!&VLE;cd%#^3|N@8Hz+I34_0{%I=5gtueI5+<_fT7Pq|Ntf?tGec$LNK#<vpi zX`!_-Wxksl#Y&m}EF+X>+UJvKbob++af0sC<U8&$nPh7<fMc<~O}}|9(;_cbcUm~; z(DP<};hh5<LwtWC|CPsQvy*qe`)SRWj8(ahq$t<Z6w%ta>Ng27c1En<MY+XunV<!2 zp3N5Qy!Z!;1IT-d*b<{kOj7-iz9;$7vJJI<fQVC+?+57TOV0Ky46n`(p11|Uz44aL zRM=MliFo#w4u!!16SMSW^^nWqL{E`$eQ%w5u2aNcFrwLX2}JKp11j^yNc@R?sy5eq zZ_2*e?X6-A=H13*3($QcEa^|ez?a~;^D!veqiC4lqU!mNnAJkxVF2YnrMxr9eG4%Y zQ1e8Zl5u2NRVs)-+TGNjJy7>BkfgNQ=w~ZfV(*Xp_U;~1c~HUo>f;gE^~cp4=lnXL zZf4&rspfzUepzUAHzn`SdkGH=BvuL`am`<N)LyLEL;td1sP&hk4!6IE*xCGhP4C0; zzi@8K=0!`3Ts}j`BUVXZ2hQPWrFB33ps9VPm7dcVleWh%b*@#Pz}f1mcXP_t6iHSy zG+j}EH{=U+r`JRMOqTp@RBOUVsf8srOleC|)v44{BEu*c&z(puZffs!+hAY?E(9_r zqgO6Ha*G97$9YuikvX_xr~(%)g~s#ul8DFgHWJJEkEO?1%dS_H{CdNPA4xVXYuf(3 zo7rc_E<Ws*ahey9l{D2LblP~Wpuk8Q6EypO1<EW?{~a(-J1S9aj}o)`ET*HCqi4<s zMF;>0P&HzI3IooDo|P{4|C@`oTK);;;WlOQwF8D?IJuacjbY=vCxk#K$yjCgK)%}n zCEwTAb&FtUeSluwuyYG(RE}Zcj-Z<ow(_U_g)>q2H{XJB2|P*Koe%r6XF&o<mHHc= zR$%DE4fbu3pff+*7%O`?$8S9l)7*dS(MfFa2I>i`OI-naNOTZ6+vLC&*y!g7Kn~g$ zy})`pChuVQE2+u|82uK@Y(BfMZG#R=m^%GlVnnHmbV5M~t;Ha`i5D19AwQ|xG>p9} zAy510`d&Co(B)BCz}MRVpFbpl2}xb%3UO&bZZv`5=hKKdnl?bp?up{RF9lVq=(AMa zib)P}CNM^keX?g^31;54nnoZf!g&{Zk4F=B2%3!OlV!j>n2^Duwv-FI*GmzY^OT6? zHa3IYQrUC{*fw-XJQWZ*$h@wH3YdKJgMM+VFbFw_m0f*UEYJdlFv~;%8Sk@uc|GJS zJwT$%?wo2_lm-6&``>QShx}}%3O$uDal;b85#-IjY70;`q*p$+>x+qZc8TTJ=xq() zHl7I>!`1!D@5z2e#UMUxpGEEXBIcd0IaWwoSilSTKw`JXM8`A1Lb8K8WBDYI2m7mS z0D=|Di<l~_kNSESx){|nYnFd~?yjr9D30KHt@3MiBGD5!w*A{t`F6F_RG04IhU|uG ze}b}D^Try@Z`)Bt5(<wxp$C%|<8&p*0Y-D~j=uUT*VEmK@*o=5=-IfHUz8`Na^{T0 zuG+;3^W(*+b7-=Tyx3PeOG-}%U7&{n^3BLqI=zd(P(*`}d6ALyeDvCJ!sp-R-^{QA z_w)9m-1+4F7qp20`>g`aTq5MiaDVi~)j?yZtlAEy@l()mfW|)5cij{d^H0wp(6Gbm z1rA}wduh|SmWMS}n<L>;)stVZv)%8GX>p-?q(Ng|k&Nl8a6DW4)p?fvL3emdRE3!m zQ4qGqcOv3;A151_A~~;Fn4g&0^R*ZLU4jfZ_IQS4c4cTkoc8cwR(?|D?7eT}{RzwH zXOktx1!8v+f16!98VHq-VuW4Eq7Bl&h%E!p$a&L+8tm`s<G36=+{<wv=}J($cWu1g z)02noE;YT=JT-o^QE$d|@eYPW%o9L-gwX57^3L3_pxX;jFap|b-J5UfbG<XC@GD2) zN151FB|Um8WOKHIU;U{I$Vl(XX$EI%%B$;9@;Hh8p3{;R$>bKW9496(njt;S`W}Y? zgx;^F(W7$u01@}2{Mf!;YEBekTpuf(r>_cwoQRmmZsb$#Df$nX)O=kM$#LDa*S5?! zrzx;_MxXg|gE6{+FW2%jx=(OWj?0#Au;U^TKY7XUS4JLd#)?~)t35!yP9@07e9J!Q z2@Tej|K_n}x9ReTps*Lz@-;tqz!m>w;Y8|SaZ=%RCmOVi#J^08g@LHO^|k7vR&rZ1 zX`+;6Zq6_C0<o3w;utz1n3yjCJcqL0>yHe{hE=rjl{tIB8bhUeH?nbal=f)t$#0RN zp?I%9BmKHpSWljpe37&1rZbqN%RBrblX-r3f~Bz0_Y<zw{<zLl;G=DW!f{2!t#Sfi zzbGHRtB)S1sSYs71V8^0QLb1efBd3HVG#MJ^p*DI%b(JP4$CI)mFgS6d~M!Q2){bF zc7j<^r|cE(C3bUd(Hb0SW^xfWQIzlk`poq~bd>Dx|9g-E(oiTG^rsaT^y-sgt&N`l zbI?V5e{Tr=Uw|F~(0|gUZU}hxM8zOy@KYeRT-?zpxieksyi{9B8=|fIB&6gNqzB5& zBBMz;?@euvc0Nrd_<&Ifr1})>_yDf<`x<C=<QEa_8V}&=*gBs|kkC4?-i;+mrMt6C z1Pe`Is>IY@?dNWG02y*&GE_)?g2Wj@UEnTIZu?$yu|^k8MHoz6J?HP^1L*4(JPOq} z`+eX&)5sd{z;viUOA10ZB5)Dp2X!s0r1crdz%Z7M#;iezRQT&J#Lv(mUX6QQl!?<> z_~KI1PccbR%20Hg{Wr>H&q9Swd>}1|X*v*qk-c{o#e#;uI02-_l<sH7<ANy6NW=oa z@iM^f#d+)YH3DVof#8qAvO+Xyh90K$<O)EXZFb_}LeIB=c&O`2mw{_i8B7!r2Kfn_ zF96|?+!wWdtDFnr8`WbpDmRsxmPBg?NakoRk+h7*iJIO4vUZ&I-JyUE%S?#t+)`&d z^2v8mOk6Ue!4tfrsoOA7SDXau*1Kj3>uzax{^}pSx$wI>k5(C3J*G5k@4j-FnG&o> z$72<*T^}ibb+Oi4r3yv(^7)5lUX2%23{v7h9Tc)j3rKZQzD$S$%X{7THwWsS^*k9( z_RLd$?VYUzL$;#aY8F_~u$Sj@+2fyHSU>lOGR;5f&!TuzNHW&{R<#63L1#$Ew{pxH zCm#h|^qWkyn9X%wnw<PKZ>;~U-8S>f?C1>a9f&aCSrUG~2;EmmqWquQ)X(i|2-MqT ze|4O4S1tRlY2^-qBMP%GP4_g&@UzMjzdAlj$}pKF4^>mYgGd>(_PFxvKH?xL-#uQV z-Hf_npGB>VWQtGHztAkFa1E&7DlW6Ep`MkzL)im{fjXr&QFD^*15lF0C@8}6g5vnc z;IZlWO7KB+o(v1XZN_I6PuSMG^*P<|e`QkR)bzoK67t+-i)GKICBG6Kc2_oGaC@wo zNF@MDmHFjycg9s!RR>LLT*@H6l+x?!HJb8Xru1>JGI;diA`0yD@~IX9PmYDF5G_Q2 zg>X?E{j-E#W#tu6xoEK|mx)>WK}75D!G$Y%XEha#p*Y7M7DUctii~^~ghTGx9Y?*? zs3tC$e<IuzP-Q`Y!b(`dmJKvXWH;6E<6K7zAxws0dI(u`%l(KC#T;+6U1$s4YdG+A z268;>Afu|O$A3VU`T)gX2##vWz)>o&ANCWX<4t_X(a)kBXGAuOKA)<1jJZl>#>|ry z>xI_@raVh82scOce`$l(dH$|mWM(bQX{buas;l817UB^1;0<wH-2$90i}(?nl&FOL z`Y^F1mZ3c~PBaKlWdmDL*>Nw|W53X&NbN$;=v~rk;A$+l^R!hkp2^5B=?5CMhifCW zTQ<4Jm5-jXI>J*&rI*wdnm*|P(~M)ZTB>hqvZ@ff*+7oKo?BqT3I&xrOfzGBz9Qck z>ln?1nM%xzjuMp;&^JzJD?Vz^F|rVzB9<yh`sedrs6&ahZ^kr`rUx7mRaVf<!8~A6 z1e?2Rjr(+zTWd;JOKB2f6N|x>T}n40&kC-JvxJu4lC>o}P5sM!{f#Mi*5u#9NmP)W z=~HYZy!<j}pxv)YTEXf>NktNEA>QSqU)Fzj$p31ab@0%y*1NMU|2;3fR)+1;phkM^ zTA}0#&&#Or79f=@P~~ff-`QvLhk#_-F}kC_M=mQ}&ydH?^6L%+qZobvdZ{LZN&TG; z&LS|7G86JwUX(@<>GnE+F8Pu(w&`&jy?7i5eVazWe<@Y-q_yLTe}7i(K!KgGZr3wW zZIufAkN-rfi9j~x+b#&rF#UAtM*XO%vz1B~HF!u`6+jKj_m`0^lspiLq=0_)z0GSK z2c0NM<SsP$C0;F7xhuMS1%OUZg1o)VGH-^)IWX9(kYa3RMML3y9!~Gat~Yf6C1qDp z=Q>VJNz7g6%od_;t22*jI{lz|%&s2;km)KrKD762r@VuP=rHKux>#6Bnmy+8Ny5CA zxI5GRPT$s<bh@}82@_u2w;7I)(yky2@je2pv4P?qd~BMCeFA+LDzUnbVI~%Am0Z<4 z1rf*)WTNkIfhKLRfL@|0@tLWh6@-B9G*ys{08{h^ssu+q&iV)Z;5hgN{iE~5WZ~*m z%GKFc(|yf@t%!Q5dko6#1cAH1GB7<_wsw^Ko-WS~GX40%Ps24E$p-MkzBmr!W{poa z!FFSrdY?U8qhhd~ZNEe{pyiL_hnZn;R9|Yskzh`^wf9S?Vk7%z*!aewi27H(-*XOc zEaS*1U-^qVh2{xfvs6#rG85a*Nsj<TJ3nbJmdTAJnG`P{VK$AJ?Na&q^&*03B0)AT zz-IUK)440+YZXQd(EYusnHQeg_;})ARvS1l>Bl*h@3U>6ys?oT+&xj^-8`vC{mx4F zdN5o~tS0Ku#G}Ox)~bGifX%H)p}p?9>K|g9{1)Rt1@jOIixnm7o|EQ?BdL!*dD=aD zeu-7TZ_<g5?N?)CujE+syqx1T*f2+m<A2Iv&zEfF%t&i8sE%ba(lzKsoao7e_3ivl za`}`@^vlLIzvL}@*_M!vyO$^TTJIEa;Rvw+k=91x;AgoH^-G>MFZ_f!{Y{=<Gy^|n z?8y$>!a@FAVY;Q>DrYvSN6fq=J`GsLzaPcPcASt!>-4^g4i@Gfw|AT>HP}Xbx9K7H zl#3lrM*ON=oI3kz{X{U<3=kunmBjnhfVbZo=AoDb*XljdTn6&5O2BV6c*6S`?`ihM z7RdJ`ZqD78tW!^)9_u_@|FwjNHoc_po@Lsq^T~Pvt;to+Y4y502z}G7!&5)RnzJj4 zdTwcg0EIStyJ2)EIT(HWnAJKGNE4bO?xN*Dx(!!Pfx0<%&>dvSI$rvrI`6?HX)C6> zfM6o!<Sfqman>V(ATpRavdGo%2|&V9^SL=n0QpZfFdKFISD6f>8JDk8txfMfltp8& z7yLswP(`Xee-atBEpdB@#zfDB5Gx!09-zJrIr_5njp?O)B{)l|sJcYBs1Dj%!&xkC zfGgO%J^v5<#*k_=C#u2z@97?e|54COQ!IRHlko>^{dkgCR-3yreJIXXNAX6J&6B2T z#{O&B7417+SXO`G`O8DUG_d?X>D|1;KWGW#J33|L?mcezTGtcljU$!@C%R{mo?pK9 z9U~(ZRFX9A!<?U3V(QPV{tof8qH-G?0I#C=S6DULUDLdM?(Dw?tU?fO%UrGSoHYDQ zG`EP!Vos|g&7$jyPDQC-m6Lf=g@ebj(nc(mR<q;zR-5D9Md~o5SKI$oCbm?P2BMAM z0=f;Fldp$5!N7b?FK}?~|2GMvreV8SG>ho4x;^L5^a$uJ`@XgaVHE*S;C1cg?WVH8 zm)H#ywExYKbe~whC42L72;U4^DaVy06;NWo3c1$b0kgeQuKmAYYhnqH$HJp}<2u^f zfGdZ&tgd|5z@b9nd8f>ToUvJ|r7rb|-E2{Cib^1)9*I2Xh-N7iI@88S_Jqf5P^0?j z&}=UO12-;Pc+(~+x&d0D5W)!Ku9He;8?&GIeS329+|RD5i<n4=L)0DkrZy6OhQJWl zz+H6k)<-Q0!H#pga&gAA2%1Awsf}duWlunp^UxhDf2mfd{F))%#dU^5#Kc#TKl?~~ z97}AzONLVWoS*E_s^1=)MW>ObSZ6yQqPe1$f-*kkpy{5z05RLgDT{StTVH;CkYZ$Z zajbk70D5nF0^YG3l@f*@jd(%S%c8K?FnLADD|l9+-czeR)qOEd@c*Julq6l1mK3;Y z{Q=HfH4lazE7g+aI#>lcnD={UFO0Qa*U(Jx5)EJF=~7!5HM}KKRBpSUX-&p%`957l zXlPTd2BXy(h^~_WqMP{5n(|kt8XGm0uE+XnKloVlmN&3`&4Lv*V!vf=rBAwJeNHQE z-acFWb}MqM34by-RR&pkUV(ghV~^;LhcVbNh@+u5pU$%n%qYFEp?;R?ph?-~{avzs zGi{D^(roHWm0XQ6##heIXdx2^0kJ63l0JVU{gtaIBwx7BoOD8=L1~J(4Lx3Y61Nq> z7KvqGKj&{dv$UNt!6iR4k$~=L@sc+J%^ryMoqCOrTtBA&)q$7XdM4MK9q#|iCkSjI zck*_QX}sJ!`CX*aSX+-_(ervt@nP)P{quBuqq*NExgzB?9EO#CBl2h8m88BB5Lu5W zHvaw+Oo|D~^T*B;;ohX#cOFO2vuzjSMdYbqu-HBylK|pDazRexL1CH(|7jxzM+4pK z1vu3{aDI-5El7I!?bAG_oGpM}Arkg}A&A}TKskF&gjO#5`Nmo^v!YPYxWX%AT&=eB zq;92=JSJ(Nt^qBi;_+&S)Ly$aRyG|NF`tB7gm<6x_boIIOG9___yDwk{7q1)ZTmMy zk65qEnaJaL%B2ry|C*}`{yA!M4_E~2BWIpw>+8z5f<^eFFV|I{g6){J1aJ{81&*&{ z1^HIPW4ceoENw9n@C>X-YC_>bA^49vPvs)H-^|Kc7X&9=l^&Eo!L@B)XT5?W&#;>u zC<j5%6&}pI&5_1N)d87K`LnNfoz}v-`>RsL)>spXy4D(n*_#q4CIkmn7?Ros5EdBT zG(fa0a>b0~LvMTsJtZ#o{H{R97Bg4|f*<=NEOb`Si<HsYzQ5&P+M$Fl5iak6tiV*9 zr1@v&)*pfU`!%d|c_R2=(3N$tph4567my&VHKniIGKg9k>$0+4z80^eK}%&y`AZo| z3lR|y3~H;rXD!BXJZ9z-IIz%Ru5J2fyc9GwwbS>dd~HuxUKV!pGk0dCPzo*kOq$6V zH>G??n-fUYJa2iO@+#8puZer!{^x7k;)e6~JBhRoB5>axyiA8DWiEEb$Cb?anq6ss zMzei?;vYqHmAX_^<CM7=hknd|XG3^8qB6uF;FT{x>Q!mRH)8*AxS+c4m)<i?W51-2 z76hLT!;NzaGvZYIgPtBLMS=Fc<eHWKi(G-|US5kr$@Q?nr`*PKJ!+|CEXpp%M>iw% zUlyhw{*zTl+m!NOB*~Z-AiYGJ-2~Y(h92@P3=91f(h^lh)lEOa>{;qs<p=4&L^0_T zpiYzicDDbc$iu<lyQ;tM#2?K#-=XCa;tn!h-JK1f!FK2eOp%s9gVxormIqxO$uf5& z9%hOO`eQFCd0vmKHUMdU|Lta__FSvUqx63v#{&9`803MRH=67y@8Ro!d(bSe#mL%c zf>l;lZC`)0sTbwOkzk&2VwhRkeP;0jc%jZz^0O+xo`l6w$=pZ#kcosjU3gCl5LB_1 z9FK#!fU<{``>Nq`f2A*hfXps51gacch+IRQqCvuRiSx4Nf~$c#5fsY6ciD-s)lmZE z39&VA10_>li175w;2)Xd!q?U5_G5$`h23}yH3oi83JP8eo<{zj*C3YEB5S@7NF5bE z@G-pGoXZ~NGI<t(4*Q;(x_V}4sfWRXlJD4AOo%%*bON{sj)FW7-A+&x0H=^Xi1S%2 zYEAfSi@z6Tgbh13C((l~UgEdBxFIB%dcuSZ%p|tNXpIg;0sRH<ERp^e4WBOCvq$9S z#L&*$4G{U=Hpy+^+Thh)RXTN;1I%voCMFE{OMQ|{P<0{sZmCyG<P&=s67ph8&zNBe z)OQd)bekb9exz@~+U$}R;zEBDUM?q}#${wq%?&54!(xNUp&%nD5_yr3K)GwZM5GAO z+n7uon2Tu|CiaQlc5%ZXIlByy<AyxR5@l8fy=3gD>(>oJ8T6RU(M$^d8^1=7CiS-Z z3#+~1NL4-N&Fag>J?VSn<@9&jj(TfbiB*F2SkhJvI$k=|n0S(iS9|){19eT5bLt5e z1YN%sYpoIk-gM#JMD0GNbs?C5qBF~Ga8=qEDlHr>Gw2^b%Q4Ycr{VJ~W;${Nq@H{T z9QIOV4`pWd<XqG_^z4_%mW=@xp<gD6okDhQP<%j>=zyX|hV9YcktoX-9x}++x@ZtT zqocARq0<A~-%KTn(!hPMEn@oEh&A3OKn@1=7ECxyJh+)=%;G-kRXs_Q<Yyxl-k6@& zn5cWqaFKgzrki->c^DsdgI2Repj#*HIK+0M2DW*;RL-kf>^PPu)tvX`+g_!OQYt)< z6qmS1d*V87W&RK`enY6&(0nqU1^i&A{q30P?^1wZJ<In+(#*}da7BOrx!aG;q`;s| zytum6ToHWONy+qJDG5m;_*YHX@)t|nl%z&7UjmLxeyG*{APM9V+#Gp1E-e)!qiCdS z(mOEu*)<aJzK$;8Pm|0XdA%>9CKT}j?D4yOK?p{}>Pf@G3^}>{{Lm<tTmR+<*>dRE z@=RH5Y&N|J!`gCPm2iA3q#}4%b{<3A7-2d}hi&?f1QO7agb3|IZ&y3sdWXG+uvwht z*<KCTh;uxdD~YA9zgoO-(&5Tas|3FUuiy*~Evi9tX!hPrl8<Nu3MkU~w!^v)?hhis zk7wbg%9F-an`C0DOq1^cf+Z@D2gU|TdYDrj;q1w4dgpsj-@Ep2fA90$-7bx)eY1qa zu{IY&Kx|1OFE4{cfAj$-A}P1r<jT$~{oO~OkIXRsEzv>Of+CGft)p3SKX5)3;Mgdu z?f@d87v6)ySRVxMeJ$tUqa6U`c*)&HI;i<2^|H5$a8Tg<`u@(#5Z{Lqcc%dvX2F}( zS9=Q*B6VV6rp%{w`4HjLnVGzq$M%+f2UGuN;Dz)cM}|cN(l=|}33RBt_u$M5`x^1q zIlaluSl$ED;aTCe0S6qi(j6ygS(@^lbxnLK$QFE+D#HRTC0dNOgLg?e-p2HQ<Oi)Y z^ac`HX6bNZlq-LV<7XMof|q~E87OzMJwxQ5mu>PC#OcMLPS_q7Xy6WxeSZtZxn}nA zSQ3qKRm;GST#PXqG>fSsW=6OjwWn{y3trE+zwSok((oV(jHqIAdWMab0>6rCRKyY` zaD>sgZ<;5Iokz95reUmhk=}H*dQ!lB%q@MGi_wecLN%Nipn5hU!NBaZkDpy(mvQ(@ zH`4Jem|J|GRl142N5%M3U&F75G}7{ma$kCifT%iD$P^Z+Zf?fcBio}&Bf9+dUVcm1 z;IG(oKf#d-x^mVEdTJEW)ZPp>#VK5DT!zMIuQOR)o2^cZ97`e=^XyGo^2US=m-qCV zo&P?kNw4oj3)6LIa94=qrK|9dJ#oanFVt`eLdCE^I#U=q<Y_F@RvignYY16UC~De_ zG9guKO4$v42>=bO;e&T=n|zZ*5Ns^yC^90DEp)GVQ<<6T?86U_!96m`qXT*z6Pz=` zf&N$iB^r2!GOuaT#?KA7hw?QexulD@pM7C@9xhfa%nLB6loXJEz2bj=N#TIJ4%Djj zdiQlxA&|BfTYo+vjCLHmOI?9utsGeVL%DS4H$Z6KC!+bm_$w$p3kVDfb=r$U!5qY8 zm)CQ9x&!|&YiRNt2Ei|2XA25!4e!}9_$U237bjDrB-Jb?)JIT7-$kW>iL7Fl6r(15 z4eic@KT7kEooSfP_l|hC$EmLa6L3hDC?KJ7fu^>QK{`k-_Cqx#(61n2F4n2zB508} z)(|t8hK2(4*?}l2)@VUewD-iDK;$k(>jXSI;PQ@43%Lpmj<P7xDoJ&~aQ#J_G<xb_ z)ZpbjpOc-Oyrhqt>bV8SMxT}=o~L<p9Zv|a&EDP4n7fO(tSCk+?)p1TkkjLHwcHu1 z%tL1r+u}}u(qwp@==R_NOltP*BLfjUD$1k?3hh#F1M*ko<#Y6`%k5UXwo7A~4|ilj zpa@xp%Ue(&ls8ESt@J_Af->p6|DY(N{yp>WlkO-FnbuP=y`CgfNY~{J57&TT#}4Dw z`O(y(MAbfTtL^@eGpmOgCVTpgZ=s3H^F2Xbp(awywL*xlmT_|WX7OJCBDAI;2cpZF zZmjC~w^=@p7THh!zQ<H^CEIcsEmwrmT%T@aYu}j-INusHTRE{xheQrpDYyhByeB%D z<1G0-VE5-@q<H&0bBb;E$oe?GczWyRBtJLgr=wQA>h2(LD~U5qzp`^3o5dQ7u6_<_ z6Olfl411Vp@42<-Q%7&`Tjh(|2W_n!Nz^2n#5>9ab+mILvg-aS94Yio4C#!en*bLj zIawHL%9U)DX}`sBDCb*!flq(Jyo`@MBVs-}@G#)ih<yAJ<N=~_J1%vGDqz<Ab9pZE z#??Ta@hw6R&efB`u#y(YvvfhSU0EQF-^-i%Zp?WsyLODURC@nLtuZ_M{%QEB<-1v1 zk341FOF=^T?q2oW5oB6HT(69{H2v#_aEQI!c(yN6a%|&M7ojUABLZ>yvwp6YtosMP z*m?8HdHRm0)TvebO`CPE$}E?Q7WK}>hujlo2FK;Jz`)CK3Mu`W0HN{=Y<X>^qoS3o zQWpERQk>m)o6k5mo3tw=7J>}2_tlW50-o}%r(aZ-m#WfzsO1+$*q7p|L|uxR5cBCi zQCTue%i)W6HVzEk+Hr-KCt|}}T(^zBr7dRXxIxChV$e0b@oJ*;Hs-x&nt2&RGDqoM zYSG%Mqcbg<U&%@nEs(^ZoCNK-%0A<B+8&bFkOTat0N9#d5W2)}?cuN*k;)xIN{O9> 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%0AnUQL<q80;6*3y@cT=1CWQP|5? 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%0DK%nK@=ha7^^OLAy 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%0A^i>0(!Jzorntm-b|xA|=s`u&o^%&l7i|Z*h*d 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 B<!=B0 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/dev/index.rst b/OpenFAST/docs/source/dev/index.rst new file mode 100644 index 000000000..81fa6aa01 --- /dev/null +++ b/OpenFAST/docs/source/dev/index.rst @@ -0,0 +1,112 @@ +.. _dev_guide: + +Developer Documentation +======================= + +**Our goal as developers of OpenFAST is to ensure that it is well tested, well +documented, and self-sustaining software.** To that end, we +continually work to improve the documentation and test coverage along with +feature additions and improvements. This section of the documentation outlines +the processes and procedures we have established for external developers +to work with the NREL OpenFAST team on code development. + +If you'd like to help with general OpenFAST development or work on a particular +feature, then first install OpenFAST following the +:doc:`installation instructions <../install/index>` for your machine. Next, +verify that your installation is valid by running the test suite following the +:doc:`testing instructions <../testing/index>`. While OpenFAST is compiling, we +encourage reading through the :ref:`development_philosophy` section to +understand the general workflow for individual and coordinated development. +Finally, be sure to review the :doc:`GitHub workflow <github_workflow>` to +avoid any merge or code conflicts. + +With development happening in parallel between NREL, industry partners, and +universities, NREL relies on GitHub to coordinate efforts: + +- `GitHub Issues <https://github.com/openfast/openfast/issues>`_ is the place + to ask usage or development questions, report bugs, and + suggest code enhancements +- `GitHub Pull Requests <https://github.com/openfast/openfast/pulls>`_ + is the place for engaging with the OpenFAST team to have your new code + merged into the main repository. + +For other questions regarding OpenFAST, please contact +`Mike Sprague <mailto:michael.a.sprague@nrel.gov>`_. + +.. tip:: + + The following sections provide valuable guidance on workflow and + development tips which make the process more efficient and + effective: + + - :ref:`github_workflow` + - :ref:`code_style` + - :ref:`debugging` + +API Reference +~~~~~~~~~~~~~ +Some subroutines and derived types throughout the source code have in-source +documentation which is compiled with Doxygen. Though this portion of the +documentation is always under development, the existing API reference can +be found in the following pages: + +- `Main Page <../../html/index.html>`_ +- `Index of Types <../../html/classes.html>`_ +- `Source Files <../../html/files.html>`_ + +.. _development_philosophy: + +Development Philosophy +~~~~~~~~~~~~~~~~~~~~~~ + +OpenFAST is intended to be a self sustaining community developed software. +A couple of tenets of this goal are that the code should be reasonably +straightforward to comprehend and manageable to improve. With that in mind, we +expect that new capabilities will include adequate testing and documentation. + +We have the following guidance for developers: + +- When fixing a bug, first introduce a unit test that exposes the bug, fix the + bug, and submit a Pull Request. See :ref:`testing` and + :ref:`github_workflow` for more information. + +- When adding a new feature, create appropriate automated unit and regression + tests as described in :ref:`testing`. The objective is to create a GitHub + pull request that provides adequate verification and validation so that the + NREL OpenFAST developer team can merge the pull request with confidence that + the new feature is "correct" and supports our goal of self-sustaining + software. See :ref:`pull_requests` for more information on submitting + a pull request. + +- If a code modification affects regression test results in an expected manner, + work with the NREL OpenFAST developer team to upgrade the regression test + suite via a GitHub issue or pull request at the `openfast/r-test <https://github.com/openfast/r-test>`_ + repository. + +Development Guidelines +~~~~~~~~~~~~~~~~~~~~~~ +The following sections provide extended guidance on how to develop source code, +interacting with the NREL OpenFAST team and other community contributors, and +generally debugging and building out features. + +.. toctree:: + :maxdepth: 1 + + github_workflow.rst + code_style.rst + build_doc.rst + types_files.rst + debugging.rst + performance.rst + versioning.rst + +Other Documentation +~~~~~~~~~~~~~~~~~~~ +Additional documentation exists that may be useful for developers seeking deeper +understanding of the solver and mathematics. This documentation is not generally +necessary for most development efforts. + +.. toctree:: + :maxdepth: 1 + + other_docs.rst diff --git a/OpenFAST/docs/source/dev/other_docs.rst b/OpenFAST/docs/source/dev/other_docs.rst new file mode 100644 index 000000000..e6592f8df --- /dev/null +++ b/OpenFAST/docs/source/dev/other_docs.rst @@ -0,0 +1,18 @@ +.. _other_docs: + +Other documentation +~~~~~~~~~~~~~~~~~~~ +Additional documentation exists that may be useful for developers seeking deeper +understanding of the solver and mathematics. This documentation is not generally +necessary for most development efforts. + +- :download:`DCM_Interpolation.pdf <../../OtherSupporting/DCM_Interpolation/DCM_Interpolation.pdf>` + This is a summary of the mathematics used in the interpolation of + DCM (direction cosine matrices) using logarithmic mapping and matrix exponentials. +- :download:`OpenFAST_Algorithms.pdf <../../OtherSupporting/OpenFAST_Algorithms/OpenFAST_Algorithms.pdf>` + This is a summary of the solve method used in the glue code. +- :download:`OutListParameters.xlsx <../../OtherSupporting/OutListParameters.xlsx>` + This Excel file contains the full list of outputs for each module. It is used to generate the + Fortran code for the output channel list handling for each module (this code is generally in + the _IO.f90 files). The MATLAB script available in the + `matlab-toolbox <https://github.com/OpenFAST/matlab-toolbox>`__ repository at *Utilities/GetOutListParameters.m*. diff --git a/OpenFAST/docs/source/dev/performance.rst b/OpenFAST/docs/source/dev/performance.rst new file mode 100644 index 000000000..049bbe38c --- /dev/null +++ b/OpenFAST/docs/source/dev/performance.rst @@ -0,0 +1,223 @@ +Performance-Profiling and Optimization +====================================== +The OpenFAST team has been engaged in performance-profiling and optimization +work in an effort to improve the time-to-solution performance for the most +computationally expensive use cases. This work is supported by Intel® through +its designation of NREL as an +`Intel® Parallel Computing Center (IPCC) <https://software.intel.com/en-us/ipcc>`_. + +After initial profiling and hotspot analysis, specific subroutines in the +physics modules of OpenFAST were targeted for optimization. Among other +takeaways, it was learned that the memory alignment of the derived data +types could yield a significant increase in performance. Ultimately, tuning +the Intel® tools to perform best on NREL's hardware and adding high level +multithreading yielded a maximum 3.8x time-to-solution improvement for one +of the benchmark cases. + +Approach +-------- +The general mechanisms identified for performance improvements in OpenFAST are: + +- Intel® compiler suite and Intel® Math Kernel Library (Intel® MKL) +- Algorithmic improvements +- Memory-access optimization enabling more efficient cache usage +- Data type alignment allowing for SIMD vectorization +- Multithreading with OpenMP + +To establish a path forward with any of these options, OpenFAST was first +profiled with Intel® VTune™ Amplifier which provides a clear breakdown of +time spent in the simulation. Then, the optimization report generated from the +Intel® Fortran compiler was analyzed to determine area which were not +autovectorized. Finally, Intel® Advisor was used to highlight areas of the code +which the compiler identified as potentially improved with multithreading. + +Test cases +---------- +Two OpenFAST test cases have been chosen to provide meaningful and +realistic timing benchmarks. In addition to real-world turbine and +atmospheric models, these cases are computationally expensive and expose +the areas where performance improvements would make a difference. + +5MW_Land_BD_DLL_WTurb +~~~~~~~~~~~~~~~~~~~~~ +Download files `here <https://github.com/OpenFAST/r-test/tree/dev/glue-codes/openfast/5MW_Land_BD_DLL_WTurb>`__. + +The physics modules used in this case are: + +- BeamDyn +- InflowWind +- AeroDyn 15 +- ServoDyn + +This is a land based NREL 5-MW turbine simulation using BeamDyn as the +structural module. It simulates 20 seconds with a time step size of 0.001 +seconds and executes in `3m 55s <https://my.cdash.org/testDetails.php?test=40171217&build=1649048>`__ +on NREL's `Peregrine <https://www.nrel.gov/hpc/peregrine-system.html>`__ +supercomputer. + +5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Download files `here <https://github.com/OpenFAST/r-test/tree/dev/glue-codes/openfast/5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth>`__. + +This is an offshore, fixed-bottom NREL 5-MW turbine simulation with the +majority of the computational expense occurring in the HydroDyn wave-dynamics +calculation. + +The physics modules used in this case are: + +- ElastoDyn +- InflowWind +- AeroDyn 15 +- ServoDyn +- HydroDyn +- SubDyn + +It simulates 60 seconds with a time step size of 0.01 seconds and executes in +`20m 27s <https://my.cdash.org/testDetails.php?test=40171219&build=1649048>`__ +on NREL's `Peregrine <https://www.nrel.gov/hpc/peregrine-system.html>`__ +supercomputer. + +Profiling +--------- +The OpenFAST test cases were profiled with Intel® VTune™ Amplifier to +identify performance hotspots. Being that the two test cases exercise +difference portions of the OpenFAST software, different hotspots were +identified. In all cases and environment settings, the majority of the +CPU time was spent in `fast_solution` loop which is a high-level subroutine +that coordinates the solution calculation from each physics module. + +LAPACK +~~~~~~ +In the offshore case, the LAPACK usage was identified as a performance load. +Within the `fast_solution` loop, the calls to the LAPACK function `dgetrs` +consume 3.3% of the total CPU time. + +.. figure:: images/offshore_lapack.png + :width: 100% + :align: center + +BeamDyn +~~~~~~~ +While BeamDyn provides a high-fidelity blade-response calculation, it is a +computationally expensive module. Initial profiling highlighted the +`bd_elementmatrixga2` subroutine, in particular, as a hotspot. However, initial +attempts to improve performance in BeamDyn highlighted needs for algorithmic +improvements and refinements to the module's data structures. + +Results +------- +Though work is ongoing, OpenFAST time-to-solution performance has improved +and the performance potential is better understood. + +Some keys outcomes from the first year of the IPCC project are as follows: + +- Use of Intel® compiler and MKL library provides dramatic speedup over GCC + and LAPACK + + - Additional significant gains are possible through MKL threading for + offshore simulations + +- Offshore-wind-turbine simulations are poorly load balanced + across modules + + - Land-based-turbine configuration better balanced + - OpenMP Tasks are employed to achieve better load-balancing + +- OpenMP module-level parallelism provides significant, but limited speed + up due to imbalance across different module tasks +- Core algorithms need significant modification to enable OpenMP and SIMD + benefits + + +Speedup - Intel® Compiler and MKL +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +By employing the standard Intel® developer tools tech stack, a performance +improvement over GNU tools was demonstrated: + +========= ================= ===================== ====================================== +Compiler Math Library 5MW_Land_BD_DLL_WTurb 5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth +========= ================= ===================== ====================================== +GNU LAPACK 2265 s (1.0x) 673 s (1.0x) +Intel® 17 LAPACK 1650 s (1.4x) 251 s (2.7x) +Intel® 17 MKL 1235 s (1.8x) --- +Intel® 17 MKL Multithreaded 722 s (3.1x) --- +========= ================= ===================== ====================================== + + +Speedup - OpenMP at FAST_Solver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A performance improvement was domenstrated by adding OpenMP directives to the +`FAST_Solver` module. Although the solution scheme is not well balanced, +parallelizing mesh mapping and calculation routines resulted in the following +speedup: + +========= =============== ===================== ====================================== +Compiler Math Library 5MW_Land_BD_DLL_WTurb 5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth +========= =============== ===================== ====================================== +Intel® 17 MKL - 1 thread 1073 s (2.1x) 100 s (6.7x) +Intel® 17 MKL - 8 threads 597 s (3.8x) --- +========= =============== ===================== ====================================== + + +Ongoing Work +------------ +The next phase of the OpenFAST performance improvements are focused in two key +areas: + +1. Implementing the outcomes from previous work throughout OpenFAST modules and + glue codes +2. Preparing OpenFAST for efficient execution on Intel®'s next generation + platforms + +.. Year 2 stuff: + +.. Further, `Envision Energy USA, Ltd <http://www.envision-group.com/en/energy.html>`_ +.. has continuously contributed code and expertise in this area. + + +.. Furthermore, NREL is optimizing OpenFAST for the future through profiling on +.. Intel next generation platform (NGP) simulators. + +.. bd_5MW_dynamic +.. ~~~~~~~~~~~~~~ +.. Download files `here <https://github.com/OpenFAST/r-test/tree/dev/modules/beamdyn/bd_5MW_dynamic>`__. + +.. This is a standalone BeamDyn case of the NREL 5MW wind turbine. It simulates 30 +.. seconds with a time step size of 0.002 seconds and executes in 24s on NREL's +.. Peregrine supercomputer. + +.. BeamDyn dynamic solve + +.. Performance Improvements +.. ------------------------ +.. BeamDyn chosen as the module to improve from year 1 + +.. How to improve vectorization + +.. BeamDyn Memory Alignment +.. ~~~~~~~~~~~~~~~~~~~~~~~~ +.. Work accomplished to align beamdyn types in the dervive types module +.. - Ultimately, this needs to be done in the registry + +.. Multithreading +.. ~~~~~~~~~~~~~~ +.. OpenMP at the highest level +.. OpenMP added to BeamDyn dynamic solve + +.. Speedup +.. ------- + +.. These are the areas where we have demonstrated performance improvements + +.. BeamDyn Dynamic +.. --------------- +.. This improved beamdyn's time to solution by XX% + +.. - VTune / Advisor +.. - Vectorization report +.. - SIMD report + +.. Optimization Reports +.. The optimization reports provided by the Intel fortran compiler give a static +.. analysis of code optimization. Specifically, the vectorization and openmp +.. reports were analyzed to determine diff --git a/OpenFAST/docs/source/dev/types_files.rst b/OpenFAST/docs/source/dev/types_files.rst new file mode 100644 index 000000000..61c3154e0 --- /dev/null +++ b/OpenFAST/docs/source/dev/types_files.rst @@ -0,0 +1,124 @@ +.. _types_files: + +Types Files and the OpenFAST Registry +===================================== +Being a modern software project, OpenFAST has a complex system of custom data +types. In Fortran, these are known as "derived data types." Each module +contains a unique collection of derived types which may add on to but must +comply with the OpenFAST Framework. The module types are generally +auto-generated by an included program called *OpenFAST Registry*. The OpenFAST +Registry is written in C and adapted from a similar utility used in +`WRF <http://www.mmm.ucar.edu/wrf/WG2/software_2.0/registry_schaffer.pdf>`__. +Visit the `OpenFAST Registry README <https://github.com/OpenFAST/openfast/tree/master/modules/openfast-registry>`__ +for more information. + +The OpenFAST Registry requires an input file to describe the necessary types +for a given module. Generally, all module use a similar naming convention, +**<Module>_Registry.txt**, and resulting Fortran code will be in a file +called **<Module>_Types.f90**. For example, the AeroDyn OpenFAST Registry input +file is located at ``openfast/modules/aerodyn/src/AeroDyn_Registry.txt`` and +the resulting auto-generated Fortran source code is at +``openfast/modules/aerodyn/src/AeroDyn_Types.f90``. + +Since the types-modules are autogenerated, any changes to the data types +directly should be expressed in the OpenFAST Registry input files so that the +changes are not subsequently overwritten. + +Compiling the OpenFAST Registry +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The OpenFAST Registry is included +in the OpenFAST build system through CMake. However, the default is to +**not** compile the OpenFAST Registry executable and instead use the types +modules that are included in *git* while compiling OpenFAST. To include the +OpenFAST Registry in the build process and compile the Registry program, +configure CMake with the ``GENERATE_TYPES`` flag: + +.. code-block:: bash + + cmake .. -DGENERATE_TYPES=ON + +With ``GENERATE_TYPES`` enabled, CMake will configure the `openfast-registry` +target to compile as a dependency of all other targets. The OpenFAST Registry +executable will be found in +``openfast/build/modules/openfast-registry/openfast-registry``. + +.. _regenerating_types: + +Regenerating a types module +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +With the ``GENERATE_TYPES`` flag enabled, an additional step will be added to +modules that are configured can make use of the OpenFAST Registry. The +additional step will execute the OpenFAST Registry and regenerate the types +module overwriting the existing modules. Any changes to the types module will +be evident in *git*. For modules where the registry input file has not +changed, the resulting types module will not change. However, for registry +input files that have been modified, the output types module will be +recompiled. + +Adding a new types module +~~~~~~~~~~~~~~~~~~~~~~~~~ +The process for adding a new types module follows :ref:`regenerating_types` +closely. Here, an additional step is required to configure CMake to execute +the Registry on the new input file and include the resulting types module +in the compile step. + +First, a new OpenFAST Registry input file must be created. Then, it must be +configured to pass through the Registry in the corresponding module's +``CMakeLists.txt``: + +.. code-block:: cmake + + # This is the control statement for allowing the Registry to execute + if (GENERATE_TYPES) + + # Here is the CMake wrapper-function to execute the Registry + # syntax: generate_f90_types(<Registry input file> <output file location>) + generate_f90_types(src/AeroDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/AeroDyn_Types.f90) + generate_f90_types(src/New_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/New_Types.f90) + endif() + +Finally, the resulting types module must be added to the source files for the +corresponding module: + +.. code-block:: cmake + + # AeroDyn lib + set(AD_LIBS_SOURCES + src/AeroDyn.f90 + src/AeroDyn_IO.f90 + src/AirfoilInfo.f90 + src/BEMT.f90 + src/DBEMT.f90 + src/BEMTUncoupled.f90 + src/UnsteadyAero.f90 + src/fmin_fcn.f90 + src/mod_root1dim.f90 + src/AeroDyn_Types.f90 + src/AirfoilInfo_Types.f90 + src/BEMT_Types.f90 + src/DBEMT_Types.f90 + src/UnsteadyAero_Types.f90 + + # Add the new types module here + src/New_Types.f90 + ) + +With CMake properly configured, a message will display during the build process +indicating that the OpenFAST Registry is executing: + +.. code-block:: bash + + [ 64%] Generating ../../../modules/aerodyn/src/New_Types.f90 + + ----- FAST Registry -------------- + ---------------------------------------------------------- + input file: /Users/rmudafor/Development/openfast/modules/aerodyn/src/New_Registry.txt + # more build process output will follow + +And finally there should be an indication that the resulting types module is +compiled: + +.. code-block:: bash + + Scanning dependencies of target aerodynlib + [ 70%] Building Fortran object modules/aerodyn/CMakeFiles/aerodynlib.dir/src/New_Types.f90.o diff --git a/OpenFAST/docs/source/dev/versioning.rst b/OpenFAST/docs/source/dev/versioning.rst new file mode 100644 index 000000000..8f742f196 --- /dev/null +++ b/OpenFAST/docs/source/dev/versioning.rst @@ -0,0 +1,22 @@ +.. _versioning: + +Versioning +~~~~~~~~~~ +OpenFAST follows `semantic versioning <https://semver.org>`_. In summary, this +means that with a version number as MAJOR.MINOR.PATCH, the components will be +incremented as follows: + +- MAJOR version when introducing incompatible API changes, +- MINOR version when adding functionality in a backwards-compatible manner, and +- PATCH version when making backwards-compatible bug fixes. + +For example, ``OpenFAST-v1.0.0-123-gabcd1234-dirty`` describes OpenFAST as: + +=================== ============= + Version Component Explanation +=================== ============= + v1.0.0 MAJOR.MINOR.PATCH numbering system; corresponds to a tagged commit made by NREL on GitHub + 123-g Number of additional commits after the most recent tag for a build (the ``-g`` is for ``git``) + abcd1234 First 8 characters of the current commit hash + dirty Denotes that local changes have been made but not committed; omitted if there are no local changes +=================== ============= diff --git a/OpenFAST/docs/source/help.rst b/OpenFAST/docs/source/help.rst new file mode 100644 index 000000000..d0c2fe969 --- /dev/null +++ b/OpenFAST/docs/source/help.rst @@ -0,0 +1,15 @@ +.. _help: + +Getting Help +============ + +For possible bugs, enhancement requests, or code questions, please submit an issue at +the `OpenFAST Github repository <https://github.com/OpenFAST/OpenFAST>`_. + +For OpenFAST usage questions, users should consider the `FAST Forum <https:// wind.nrel.gov/forum/wind/>`_, which provides a large 10+ year legacy of FAST-related Q&A; the forum's search functionality should be used before posting questions to either github issues or the forum. + +Users may find the established FAST v8 through the NWTC Information Portal: +https://nwtc.nrel.gov/ + +Please contact `Michael.A.Sprague@NREL.gov <mailto:Michael.A.Sprague@NREL. gov>`_. with questions regarding the OpenFAST development plan or how to contribute. + diff --git a/OpenFAST/docs/source/install/index.rst b/OpenFAST/docs/source/install/index.rst new file mode 100644 index 000000000..cba321cc1 --- /dev/null +++ b/OpenFAST/docs/source/install/index.rst @@ -0,0 +1,492 @@ +.. _installation: + +Installing OpenFAST +=================== +Guidelines and procedures for obtaining precompiled binaries or compiling +OpenFAST from source code are described here. While there +are multiple ways to achieve the same outcome, the OpenFAST team has developed +a comprehensive and well thought out system for compiling the source code. +Thus, the methods described here are the only officially supported and +maintained paths for obtaining an OpenFAST executable. + +For Windows users only, precompiled binaries are available as described in the +:ref:`download_binaries` section. For all platforms, OpenFAST is configured +to build with with CMake and a system-appropriate build tool. Background +on CMake is given in :ref:`understanding_cmake`, and procedures for configuring +and compiling are given in :ref:`cmake_unix` and :ref:`cmake_windows`. Finally, +an alternative and more appropriate option for compiling on Windows while +doing active software development is given in :ref:`vs_windows`. + +.. _download_binaries: + +Download binaries +~~~~~~~~~~~~~~~~~ +OpenFAST releases are distributed through the `Anaconda <https://anaconda.org/>`_ +package manager via the `conda forge <https://conda-forge.org/>`_ channel for +macOS and Linux. The OpenFAST glue-code executable as well as the available +module drivers are included in the installation. The following commands +describe how to create a new environment and install OpenFAST. + +.. code-block:: bash + + # Create a new conda environment + conda create -n openfast_env + + # Install OpenFAST through the Conda Forge channel + conda install -c conda-forge openfast + + # Test OpenFAST + openfast -v + +For Windows users, each tagged release is accompanied by precompiled binaries. +DLL's for MAP and the DISCON controllers are also included. +The following architecture and precision combinations are currently +available: + +- 32 bit single precision +- 64 bit single precision +- 64 bit double precision + +All precompiled binaries can be found in the ``Assets`` dropdown in the +`GitHub Releases <https://github.com/openfast/openfast/releases>`__. +To download the latest binaries, click +`here <https://github.com/OpenFAST/openfast/releases/latest/download/windows_openfast_binaries.zip>`__. + + +.. important:: + + The precompiled binaries require either the Intel fortran + compiler or the Intel MKL redistributable libraries, which are not by + default included with the binaries. To configure the libraries, download the + installers from `here <https://software.intel.com/sites/default/files/managed/bb/e0/ww_ifort_redist_msi_2017.8.275.zip>`__ + and run the MSI file(s) to install the libraries. If you have a + Command Prompt open, you will need to close it after installing the libraries + in order for the changes to take effect. + +Compile from source +~~~~~~~~~~~~~~~~~~~ +For compiling from source code, the NREL OpenFAST team has developed an +approach that uses CMake to generate build files for all platforms. Currently, +CMake support for Visual Studio while doing active development +is not well supported, so OpenFAST maintains a Visual Studio solution +giving Windows developers a better option for developing code, compiling +and debugging in a streamlined manner. See :ref:`vs_windows` +for more information. + +Dependencies +------------ +Compiling OpenFAST from source requires additional libraries and tools that +are not distributed with the OpenFAST repository. In many cases, these tools +can be installed with a system's package manager (e.g. ``homebrew`` for macOS, +``yum`` for CentOS/Red Hat, or ``apt`` for Debian-based systems like Ubuntu). +If binaries are downloaded or compiled manually, be sure they are +installed in a standard location for your system so that the other components +of the OpenFAST build system can find the dependencies. + +Build tools ++++++++++++ + +An environment-specific build system is required and will consist of a +combination of the packages listed in the table below. + +============================================== ==================== ================= ======= + Package Applicable systems Minimum version Link +============================================== ==================== ================= ======= + CMake All 3.0 https://cmake.org + GNU Make macOS, Linux 1.8 https://www.gnu.org/software/make/ + Visual Studio Windows 2015 https://visualstudio.microsoft.com> + GNU Compiler Collection (gfortran, gcc, g++) macOS, Linux 4.6.0 https://gcc.gnu.org + Intel Parallel Studio (ifort, icc) All 2013 https://software.intel.com/en-us/parallel-studio-xe/ +============================================== ==================== ================= ======= + +Math libraries +++++++++++++++ + +Math libraries with the BLAS and LAPACK interfaces are also required. These can +be obtained as free, open source libraries or paid, closed source versions. +Some packages contain separate libraries for each interface while others have +the interfaces bundles into a single binary. The most common options are listed +in the table below. + +============ ============ =========== ============== ====== +Library Maintainer Paid/Free Open Source? Link +============ ============ =========== ============== ====== +BLAS NetLib Free Yes http://www.netlib.org/blas/ +LAPACK NetLib Free Yes http://www.netlib.org/lapack/ +BLAS/LAPACK OpenBLAS Free Yes https://www.openblas.net +MKL Intel Paid No https://software.intel.com/en-us/mkl +============ ============ =========== ============== ====== + +Dependencies for the test suite ++++++++++++++++++++++++++++++++ + +The following packages are required to run the test suite: + +- `Python 3 <https://www.python.org/downloads/>`__ +- `MatPlotLib <https://matplotlib.org>`__ - used for generating error plots + +Dependencies for the C++ API +++++++++++++++++++++++++++++ + +When using the C++ API, the following packages are required: + +- `HDF5 <https://support.hdfgroup.org/HDF5/>`_ (provided by ``HDF5_ROOT``) +- `yaml-cpp <https://github.com/jbeder/yaml-cpp>`_ (provided by ``YAML_ROOT``) + +Get the code +------------ +OpenFAST can be cloned (i.e., downloaded) from its `Github repository <https:// github.com/OpenFAST/OpenFAST>`_ +via the command line: + +.. code-block:: bash + + git clone https://github.com/OpenFAST/OpenFAST.git + +An archive of the source code can also be downloaded directly from these links: + +- `"master" branch <https://github.com/OpenFAST/openfast/archive/master.zip>`__ - Stable release +- `"dev" branch <https://github.com/OpenFAST/openfast/archive/dev.zip>`__ - Latest updates + +.. _vs_windows: + +Visual Studio Solution for Windows +---------------------------------- +A complete Visual Studio solution is maintained for working with the OpenFAST +on Windows systems. The procedure for configuring the system and proceding +with the build process are documentated in the following section: + +.. toctree:: + :maxdepth: 1 + + install_vs_windows.rst + +.. _understanding_cmake: + +Understanding CMake +------------------- +To more fully understand CMake and its methodology, visit this guide on +`running CMake <https://cmake.org/runningcmake/>`__. + +CMake is a build configuration system that creates files as input to a build +tool like GNU Make, Visual Studio, or Ninja. CMake does not compile code +or run compilers directly, but +rather creates the environment needed for another tool to run compilers and +create binaries. A CMake project is described by a series of files called +``CMakeLists.txt`` located in directories throughout the project. The main +CMake file for OpenFAST is located at ``openfast/CMakeLists.txt`` and each +module and glue-code has its own ``CMakeLists.txt``; for example, AeroDyn +and BeamDyn have one at ``openfast/modules/aerodyn/CMakeLists.txt`` and +``openfast/modules/beamdyn/CMakeLists.txt``, respectively. + +Running CMake ++++++++++++++ +Running CMake and a build tool will create many files (text files and binaries) +used in the various stages of the build. For this reason, a ``build`` folder +should be created to contain all of the generated files associated with the +build process. Here, an important file called ``CMakeCache.txt`` contains the +user-defined settings for the CMake configuration. This file functions like +memory storage for the build. It is initially created the first time the CMake +command is run and populated with the initial settings. Then, any subsequent +changes to the settings will be updated and stored there. + +CMake can be executed in a few ways: + +- Command line interace: ``cmake`` +- Command line curses interface: ``ccmake`` +- Official CMake GUI + +The CMake GUI is only distributed for Windows, but it can be built from source +for other platforms. OpenFAST's build process focuses on the command line +execution of CMake for both the Linux/macOS and Windows terminals. The command +line syntax to run CMake for OpenFAST is generally: + +.. code-block:: bash + + cmake <path-to-primary-CMakeLists.txt> [options] + + Options + -D <var>[:<type>]=<value> = Create or update a cmake cache entry. + +For example, a common CMake command issued from the ``openfast/build`` +directory is: + +.. code-block:: bash + + # cmake <path-to-primary-CMakeLists.txt> [options] + # where + # <path-to-primary-CMakeLists.txt> is ".." + # [options] can be + # -DBUILD_SHARED_LIBS:BOOL=ON or + # -DBUILD_SHARED_LIBS=ON + + cmake .. -DBUILD_SHARED_LIBS=ON + +The command line curses interface can be invoked similarly: + +.. code-block:: bash + + ccmake .. + +The interface will be rendered in the terminal window and all navigation +happens through keyboard inputs. + +OpenFAST CMake options +++++++++++++++++++++++ +CMake has a large number of general configuration variables available. A good +resource for useful CMake variables is at this link: `GitLab CMake variables <https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables>`_. +The `CMake API documentation <https://cmake.org/cmake/help/latest/>`_ +is also helpful for searching through variables and determining the resulting +action. Note that the CMake process should be well understood before +customizing the general options. + +The CMake options specific to OpenFAST and their default settings are: + +:: + + BUILD_DOCUMENTATION - Build documentation (Default: OFF) + BUILD_OPENFAST_CPP_API - Enable building OpenFAST - C++ API (Default: OFF) + BUILD_OPENFAST_SIMULINK_API - Enable building OpenFAST for use with Simulink + BUILD_SHARED_LIBS - Enable building shared libraries (Default: OFF) + BUILD_TESTING - Build the testing tree (Default: OFF) + CMAKE_BUILD_TYPE - Choose the build type: Debug Release (Default: Release) + CMAKE_Fortran_MODULE_DIRECTORY - Set the Fortran Modules directory + CMAKE_INSTALL_PREFIX - Install path prefix, prepended onto install directories. + DOUBLE_PRECISION - Treat REAL as double precision (Default: ON) + FPE_TRAP_ENABLED - Enable Floating Point Exception (FPE) trap in compiler options (Default: OFF) + GENERATE_TYPES - Use the openfast-regsitry to autogenerate types modules + ORCA_DLL_LOAD - Enable OrcaFlex library load (Default: OFF) + USE_DLL_INTERFACE - Enable runtime loading of dynamic libraries (Default: ON) + OPENMP - Enable OpenMP parallelization in FVW (Default: OFF) + +Additional system-specific options may exist for a given system, but those +should not impact the OpenFAST configuration. As mentioned above, the +configuration variables are set initially but can be changed at any time. +For example, the defaults may be accepted to initially configure the project, +but then the settings may be configured individually: + +.. code-block:: bash + + # Initial configuration with the default settings + cmake .. + + # Change the build to Debug mode rather than Release + cmake .. -DCMAKE_BUILD_TYPE=Debug + + # Use dynamic linking rather than static linking + cmake .. -DBUILD_SHARED_LIBS=ON + +The commands above are equivalent to having run this command the first time: + +.. code-block:: bash + + # Initial configuration in Debug mode with dynamic linking + cmake .. -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON + +CMAKE_BUILD_TYPE +**************** +This option allows to set the compiler optimization level and debug +information. The value and its effect are listed in the table below. + +================== ================================================================================================================ + CMAKE_BUILD_TYPE Effect +================== ================================================================================================================ + Release ``-O3`` optimization level + RelWithDebInfo ``-O2`` optimization level with ``-g`` flag for debug info + MinSizeRel ``-O1`` optimization level + Debug No optimization and `-g` flag for debug info; additional debugging flags: ``-fcheck=all -pedantic -fbacktrace`` +================== ================================================================================================================ + +Use ``Debug`` during active development to add debug symbols for use with a +debugger. This build type also adds flags for generating runtime checks that +would otherwise result in undefined behavior. ``MinSizeRel`` adds basic +optimizations and targets a minimal size for the generated executable. The next +level, ``RelWithDebInfo``, enables vectorization and other more agressive +optimizations. It also adds debugging symbols and results in a larger +executable size. Finally, use ``Release`` for best performance at the cost +of increased compile time. + +This flag can be set with the following command: + +.. code-block:: bash + + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo + +CMAKE_INSTALL_PREFIX +******************** +This flag sets the location of the compiled binaries when the build +tool runs the ``install`` command. It should be a full path in a carefully +chosen location. The binaries will be copied into ``include``, ``lib``, +and ``bin`` subfolders under the value of this flag. The default is to +install binaries within the repository in a folder called ``install``. + +This flag can be set with the following command: + +.. code-block:: bash + + cmake .. -DCMAKE_INSTALL_PREFIX="/usr/local/" + +Setting the build tool +++++++++++++++++++++++ +CMake can target a variety of build tools or *generators*. To obtain a list +of available generators on the current system, run with the empty generator +flag, select the target from the list, and rerun with the generator flag +populated: + +.. code-block:: bash + + # Run with the empty -G flag to get a list of available generators + cmake .. -G + + # CMake Error: No generator specified for -G + # + # Generators + # * Unix Makefiles = Generates standard UNIX makefiles. + # Ninja = Generates build.ninja files. + # Xcode = Generate Xcode project files. + # CodeBlocks - Ninja = Generates CodeBlocks project files. + # CodeBlocks - Unix Makefiles = Generates CodeBlocks project files. + # CodeLite - Ninja = Generates CodeLite project files. + # CodeLite - Unix Makefiles = Generates CodeLite project files. + # Sublime Text 2 - Ninja = Generates Sublime Text 2 project files. + # Sublime Text 2 - Unix Makefiles + # = Generates Sublime Text 2 project files. + # Kate - Ninja = Generates Kate project files. + # Kate - Unix Makefiles = Generates Kate project files. + # Eclipse CDT4 - Ninja = Generates Eclipse CDT 4.0 project files. + # Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files. + + # Choose one from the list above and pass it as an argument after -G + # NOTE: wrap this is in quotes! + cmake .. -G"Sublime Text 2 - Ninja" + +.. note:: + + If the chosen generator name contains spaces, be sure to wrap it in quotes. + +Math libraries +++++++++++++++ +The CMake project is configured to search for the required math libraries +in default locations. However, if math libraries are not found, they can +be specified directly to CMake. The two required libraries are ``BLAS`` +and ``LAPACK``, and their location can be passed to CMake with this command +syntax: + +.. code-block:: bash + + cmake .. -DBLAS_LIBRARIES="/path/to/blas" -DLAPACK_LIBRARIES="/path/to/lapack" + +The paths given should be to the directory which contains the libraries, +not to the libraries themselves. + +.. _cmake_unix: + +CMake with Make for Linux/macOS +------------------------------- +After reading :ref:`understanding_cmake`, proceed with +configuring OpenFAST. The CMake project is well developed for Linux and +macOS systems, so the default settings should work as given. These settings +should only be changed when a custom build is required. + +The procedure for configuring CMake and compiling with GNU Make on Linux +and macOS systems is given below. + +.. code-block:: bash + + # Clone the repository from GitHub using git + git clone https://github.com/OpenFAST/OpenFAST.git + + # Move into the OpenFAST directory + cd OpenFAST + + # Create the build directory and move into it + mkdir build + cd build + + # Execute CMake with the default options; + # this step creates the Makefiles + cmake .. + + # Execute the Make-help command to list all available targets + make help + + # Choose a particular target or give no target to compile everything + make + +.. tip:: + + Compile in parallel by adding "-jN" where N is the number of parallel + processes to use + +This will build the OpenFAST project in the ``build`` directory. Binaries are +located in ``openfast/build/glue-codes/`` and ``openfast/build/modules/``. Since +all build-related files are located in the ``build`` directory, a new fresh build +process can be accomplished by simply deleting the build directory and starting +again. + +.. _cmake_windows: + +CMake with Visual Studio for Windows +------------------------------------ +After reading :ref:`understanding_cmake`, proceed with +configuring OpenFAST. The result of this configuration process will be +a Visual Studio solution which will be fully functional for compiling +any of the targets within OpenFAST. However, this method lacks support +for continued active development. Specifically, any settings that are +configured in the Visual Studio solution directly will be lost any time +CMake is executed. Therefore, this method should only be used to compile +binaries, and the procure described in :ref:`vs_windows` should be used +for active OpenFAST development on Windows. + +The procedure for configuring CMake and compiling with Visual Studio +on Windows systems is given below. + +.. code-block:: bash + + # Clone the repository from GitHub using git + git clone https://github.com/OpenFAST/OpenFAST.git + + # Move into the OpenFAST directory + cd OpenFAST + + # Create the build directory and move into it + mkdir build + cd build + + # Execute CMake with the default options and a specific Visual Studio version + # and build architecture. For a list of available CMake generators, run + # ``cmake .. -G``. + # This step creates the Visual Studio solution. + cmake .. -G "Visual Studio 14 2015 Win64" + + # Open the generated Visual Studio solution + start OpenFAST.sln + +Visual Studio will open a solution containing all of the OpenFAST projects, +and any module library, module driver, or glue-code can be compiled from there. +The compiled binaries are located within a directory determined by the Visual +Studio build type (Release, Debug, or RelWithDebInfo) in +``openfast/build/glue-codes/`` and ``openfast/build/modules/``. For example, the +OpenFAST executable will be located at ``openfast/build/glue-codes/Release/openfast.exe`` +when compiling in *Release* mode. + +**The CMake-generated Visual Studio build is not currently fully functional.** +Any configurations made to the Solution in the Visual Studio UI will be +lost when CMake is executed, and this can happen whenever a change is made to +the structure of the file system or if the CMake configuration is changed. It +is recommended that this method **not** be used for debugging or active +development on Windows. Instead, see :ref:`vs_windows`. + +.. _installation_appendix: + +Appendix +~~~~~~~~ +The following are additional methods for installation which may not be fully +test or may be deprecated in the future. + +.. toctree:: + :maxdepth: 1 + + install_spack.rst + install_cygwin.rst + +.. TODO: Check the windows paths: math library command, installation location diff --git a/OpenFAST/docs/source/install/install_cygwin.rst b/OpenFAST/docs/source/install/install_cygwin.rst new file mode 100644 index 000000000..a08d4f105 --- /dev/null +++ b/OpenFAST/docs/source/install/install_cygwin.rst @@ -0,0 +1,81 @@ +.. _install_cygwin: + +Building OpenFAST on Windows with CMake and Cygwin 64-bit +========================================================= +WARNING: This build process takes a significantly long amount of time. +If GNU tools are not required, it is recommended that Windows users see one +of the following sections: + +- :ref:`download_binaries` +- :ref:`cmake_windows` +- :ref:`install_vs_windows`. + +Installing prerequisites +------------------------ + +1. Download and install `Cygwin 64-bit <https://cygwin.com/setup-x86_64.exe>`__. + You will need to ``Run as Administrator`` to complete the installation + process. + + - Choose ``Install from internet`` + - Choose the default install location + - Choose the default package download location + - Choose ``Direct connection`` + - Choose a download site + - See next step for ``select packages``. Alternately, you can skip this + step and run ``setup-x86_64.exe`` anytime later to select and install + required software. + +2. Select packages necessary for compiling ``OpenFAST``. Choose ``binary`` + packages and not the source option. + + - Choose ``Category`` view, we will be installing packages from + ``Devel`` and ``Math`` + - From ``Devel`` mark the following packages for installation + + - ``cmake`` + - ``cmake-doc`` + - ``cmake-gui`` + - ``cygwin-devel`` + - ``gcc-core`` + - ``gcc-fortran`` + - ``gcc-g++`` + - ``git`` + - ``make`` + - ``makedepend`` + + - From ``Math`` mark the following packages for installation + + - ``liblapack-devel`` + - ``libopenblas`` + + - To run the test suite, install these optional packages from ``Python``: + + - ``python3`` + - ``Python3-numpy`` + + - Click ``Next`` and accept all additional packages that the setup + process requests to install to satisfy dependencies + +3. It is *recommended* that you reboot the machine after installing + ``Cygwin`` and all the necessary packages. + +Compiling OpenFAST +------------------ +From here, pick up from the Linux with CMake instructions at +:ref:`cmake_unix`. + +Other tips +---------- +- If you would like to run ``openfast.exe`` from the ``cmd`` terminal, then you + must add the ``C:\cygwin64\lib\lapack`` and + ``C:\cygwin64\home\<USERNAME>\software\bin`` to your ``%PATH%`` variable in + environment setting. Replace ``<USERNAME>`` with your account name on Windows + system. + +- It is suggested to compile with optimization level 2 for Cygwin. Do this by + changing the build mode in the cmake command + + .. code-block:: bash + + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo diff --git a/OpenFAST/docs/source/install/install_spack.rst b/OpenFAST/docs/source/install/install_spack.rst new file mode 100644 index 000000000..bc5d3091f --- /dev/null +++ b/OpenFAST/docs/source/install/install_spack.rst @@ -0,0 +1,111 @@ +.. _install_spack: + +Building OpenFAST with Spack +============================ + +The process to build and install OpenFAST with +`Spack <https://spack.readthedocs.io/en/latest>`__ on Linux or macOS is +described here. + +Dependencies +------------ +OpenFAST has the following dependencies: + +- LAPACK libraries. Users should set ``BLAS_LIBRARIES`` and + ``LAPACK_LIBRARIES`` appropriately for CMake if the library isn't found + in standard paths. Use `BLASLIB` as an example when using Intel MKL. +- For the optional C++ API, `HDF5 <https://support.hdfgroup.org/HDF5/>`__ + (provided by ``HDF5_ROOT``) and + `yaml-cpp <https://github.com/jbeder/yaml-cpp>`__ (provided by ``YAML_ROOT``) +- For the optional testing framework, Python 3+ and Numpy + +Building OpenFAST Semi-Automatically Using Spack on macOS or Linux +------------------------------------------------------------------ + +The following describes how to build OpenFAST and its dependencies +mostly automatically on macOS using +`Spack <https://spack.readthedocs.io/en/latest>`_. This can also be used as a +template to build OpenFAST on any Linux system with Spack. + +These instructions were developed on macOS 10.11 with the following tools +installed via Homebrew: + +- GCC 6.3.0 +- CMake 3.6.1 +- pkg-config 0.29.2 + +Step 1 +~~~~~~ +Checkout the official Spack repo from github (we will checkout into +``${HOME}``): + +.. code-block:: bash + + cd ${HOME} && git clone https://github.com/LLNL/spack.git + +Step 2 +~~~~~~ +Add Spack shell support to your ``.profile`` by adding the lines: + +.. code-block:: bash + + export SPACK_ROOT=${HOME}/spack + . $SPACK_ROOT/share/spack/setup-env.sh + +Step 3 +~~~~~~ +Copy the https://raw.githubusercontent.com/OpenFAST/openfast/dev/share/spack/package.py file +to your installation of Spack: + +.. code-block:: bash + + mkdir ${SPACK_ROOT}/var/spack/repos/builtin/packages/openfast + cd ${SPACK_ROOT}/var/spack/repos/builtin/packages/openfast + wget --no-check-certificate https://raw.githubusercontent.com/OpenFAST/openfast/dev/share/spack/package.py + +Step 4 +~~~~~~ +Try ``spack info openfast`` to see if Spack works. If it does, check the +compilers you have available by: + +.. code-block:: bash + + machine:~ user$ spack compilers + ==> Available compilers + -- gcc ---------------------------------------------------------- + gcc@6.3.0 gcc@4.2.1 + + -- clang -------------------------------------------------------- + clang@8.0.0-apple clang@7.3.0-apple + +Step 5 +~~~~~~ +Install OpenFAST with your chosen version of GCC: + +.. code-block:: bash + + spack install openfast %gcc@6.3.0 + +To install OpenFAST with the C++ API, do: + +.. code-block:: bash + + spack install openfast+cxx %gcc@6.3.0 + +That should be it! Spack will automatically use the most up-to-date +dependencies unless otherwise specified. For example to constrain OpenFAST +to use some specific versions of dependencies you could issue the Spack +install command: + +.. code-block:: bash + + spack install openfast %gcc@6.3.0 ^hdf5@1.8.16 + +The executables and libraries will be located at + +.. code-block:: bash + + spack location -i openfast + +Add the appropriate paths to your ``PATH`` and ``LD_LIBRARY_PATH`` to run +OpenFAST. diff --git a/OpenFAST/docs/source/install/install_vs_windows.rst b/OpenFAST/docs/source/install/install_vs_windows.rst new file mode 100644 index 000000000..a682d4d5e --- /dev/null +++ b/OpenFAST/docs/source/install/install_vs_windows.rst @@ -0,0 +1,79 @@ +.. _install_vs_windows: + +Building OpenFAST on Windows with Visual Studio +=============================================== + +These instructions are specifically for the standalone Visual Studio project at `openfast/vs-build`. +Separate CMake documentation is provided for Windows users at :numref:`cmake_windows`. + +Prerequisites +------------------------ + +1. A version of Visual Studio (VS). + + - Currently VS 2013 Professional and VS 2015 Community Edition have been tested with OpenFAST. + + - A list of Intel Fortran compatible VS versions and specific installation notes are found `here <https://software.intel.com/en-us/intel-parallel-studio-xe-compilers-required-microsoft-visual-studio>`_. + + - The included C/C++ project files for MAP++ and the Registry are compatible with VS 2013, but will upgrade seemlessly to a newer version of VS. + + - If you download and install `Visual Studio 2015 Community Edition <https://go.microsoft.com/fwlink/?LinkId=691978&clcid=0x409>`__, you will need to be sure and select the ``C/C++ component`` using the ``Customize`` option. + +2. Intel Fortran Compiler + + - Currently only version 2017.1 has been tested with OpenFAST, but any newer version should be compatible. + + - You can download an Intel Fortran compiler `here <https://software.intel.com/en-us/fortran-compilers>`__. + + - Only install Intel Fortran after you have completed your Visual Studio installation. + +3. Git for Windows + + - Download and install `git <https://git-scm.com/download/win>`__ for Windows. + +4. Python 3.x for Windows (for regression/unit testing) + + - The testing framework of OpenFAST requires the use of Python. + + - Please see :numref:`testing` on testing OpenFAST for further information on this topic. + + - We have been working with Continuum's `Anaconda <https://www.anaconda.com/download/#windows>`__ installation of Python 3.6 for Windows. + + +Compiling OpenFAST +------------------ + +1. Open ``A command prompt``, or ``git bash`` shell from the ``Start`` menu + +2. Create a directory where you will clone OpenFAST repository (change + ``code`` to your preferred name) + + :: + + mkdir code + cd code + +3. Clone the OpenFAST repository + + :: + + git clone https://github.com/openfast/openfast.git + +This will create a directory called ``openfast`` within the ``code`` +directory. + +4. Using Windows Explorer, navigate to the directory ``openfast\vs-build\FAST`` + and double-click on the ``FAST.sln`` Visual Studio solution file. This will + open Visual Studio with the FAST solution and its associated projects. + +NOTE: If you are using Visual Studio 2015 or newer, you will be asked to upgrade +both the ``Fast_Registry.vcxproj`` and the ``MAP_dll.vcxproj`` files to a newer +format. Go ahead and accept the upgrade on those files. + +5. Select the desired Solution Configuration, such as ``Release``, and the + desired Solution Platform, such as ``x64`` by using the drop down boxes + located below the menubar. + +6. Build the solution using the ``Build->Build Solution`` menu option. + +7. If the solution built without errors, the executable will be located under the ``openfast\build\bin`` folder. diff --git a/OpenFAST/docs/source/license.rst b/OpenFAST/docs/source/license.rst new file mode 100644 index 000000000..674b649c0 --- /dev/null +++ b/OpenFAST/docs/source/license.rst @@ -0,0 +1,8 @@ +.. _license: + +Licensing +========= + +The OpenFAST software, including its underlying modules, are licensed under `Apache +License Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_ open-source +license. diff --git a/OpenFAST/docs/source/testing/index.rst b/OpenFAST/docs/source/testing/index.rst new file mode 100644 index 000000000..ab1cfb87a --- /dev/null +++ b/OpenFAST/docs/source/testing/index.rst @@ -0,0 +1,90 @@ +.. _testing: + +Testing OpenFAST +================ + +The OpenFAST test suite consists of glue code and module level regression tests +and unit tests. The regression tests compare locally generated solutions to +a set of baseline solutions. The unit tests ensure that individual subroutines +are functioning as intended. + +All of the necessary files corresponding to the regression tests are contained +in the ``reg_tests`` directory. The unit test framework is housed in +``unit_tests`` while the actual tests are contained in the directory +corresponding to the tested module. + +Configuring the test suite +-------------------------- +Portions of the test suite are linked to the OpenFAST repository through a +`git submodule`. Specifically, + +- `r-test <https://github.com/openfast/r-test>`__ +- `pFUnit <https://github.com/Goddard-Fortran-Ecosystem/pFUnit>`__ + +.. tip:: + + Be sure to clone the repo with the ``--recursive`` flag or execute + ``git submodule update --init --recursive`` after cloning. + +The test suite can be configured with CMake similar to OpenFAST. The default +CMake configuration is suitable for most systems, but may need customization +for particular build environments. See the :ref:`understanding_cmake` section +for more details on configuring the CMake targets. While the unit tests must +be built with CMake due to its external dependencies, the regression test +may be executed without CMake. + +Test specific documentation +--------------------------- +.. toctree:: + :maxdepth: 1 + + unit_test.rst + regression_test.rst + +Continuous integration +---------------------- +A TravisCI configuration file is included with the OpenFAST source code at ``openfast/.travis.yml``. +The continuous integration infrastructure is still under development, but the +status for all branches and pull requests can be found on the +`TravisCI OpenFAST page <https://travis-ci.org/OpenFAST>`_. + +For development and testing purposes, a version of the TravisCI test can be run +locally with Docker. The code snippet below outlines starting a TravisCI image +on Docker. + +.. code-block:: bash + + # Running a travis ci image on docker locally + + # Run this on your local machine's command line + BUILDID="build-1" + INSTANCE="travisci/ci-garnet:packer-1512502276-986baf0" + docker run --name $BUILDID -dit $INSTANCE /sbin/init + docker exec -it $BUILDID bash -l + + # Now you're inside your docker image + sudo apt-get update + sudo apt-get install python3-pip + sudo -E apt-get -yq --no-install-suggests --no-install-recommends install gfortran libblas-dev liblapack-dev + git clone --depth=50 https://github.com/OpenFAST/openfast.git OpenFAST/openfast + cd OpenFAST/openfast + + # Modify this line for the commit or pull request to build + git fetch origin +refs/pull/203/merge: + + git checkout -qf FETCH_HEAD + git submodule update --init --recursive + + export FC=/usr/bin/gfortran-7 + export DOUBLE_PRECISION=ON + export TRAVIS_BUILD_INTEL=YES + export TRAVIS_COMPILER=gcc + export CC=gcc + gcc --version + pyenv shell 3.6.3 + + source ~/.bashrc + pip3 install numpy + mkdir build && cd build + cmake .. -DBUILD_TESTING=ON -DDOUBLE_PRECISION=$DOUBLE_PRECISION -DBUILD_SHARED_LIBS=ON + make -j 8 install diff --git a/OpenFAST/docs/source/testing/regression_test.rst b/OpenFAST/docs/source/testing/regression_test.rst new file mode 100644 index 000000000..8c29e5aa1 --- /dev/null +++ b/OpenFAST/docs/source/testing/regression_test.rst @@ -0,0 +1,394 @@ +.. _regression_test: + +Regression test +=============== +The regression test executes a series of test cases which intend to fully +describe OpenFAST and its module's capabilities. Jump to one of the following +sections for instructions on running the regression +tests: + +- :ref:`python_driver` +- :ref:`ctest_driver` +- :ref:`regression_test_example` +- :ref:`regression_test_windows` + +Each locally computed result is compared to a static set of baseline +results. To account for system, hardware, and compiler +differences, the regression test attempts to match the current machine and +compiler type to the appropriate solution set from these combinations: + +================== ========== ============================ + Operating System Compiler Hardware +================== ========== ============================ + **macOS** **GNU** **2017 MacbookPro** + CentOS 7 Intel NREL Eagle - Intel Skylake + CentOS 7 GNU NREL Eagle - Intel Skylake + Windows 10 Intel Dell Precision 3530 +================== ========== ============================ + +The compiler versions, specific math libraries, and more info on hardware used +to generate the baseline solutions are documented in the +`r-test repository documentation <https://github.com/openFAST/r-test>`__. Currently, +the regression test supports only double precision builds. + +The regression test system can be executed with CMake (through its included +test driver, CTest) or manually with +a custom Python driver. Both systems provide similar functionality with +respect to testing, but CTest integration provides access to multithreading, +automation, and test reporting via CDash. Both modes of execution require some +configuration as described in the following sections. + +In both modes of execution a directory is created in the build directory +called ``reg_tests`` where all of the input files for the test cases are copied +and all of the locally generated outputs are stored. Ultimately, both CTest and +the manual execution program call a series of Python scripts and libraries in +``reg_tests`` and ``reg_tests/lib``. One such script is ``lib/pass_fail.py`` +which reads the output files and computes a norm on each channel reported. If +the maximum norm is greater than the given tolerance, that particular test is +reported as failed. The failure criteria is outlined below. + +.. code-block:: python + + difference = abs(testData - baselineData) + for i in nChannels: + if channelRange < 1: + norm[i] = MaxNorm( difference[:,i] ) + else: + norm[i] = MaxNorm( difference[:,i] ) / channelRange + + if max(norm) < tolerance: + pass = True + else: + pass = False + +Dependencies +------------ +The following packages are required for regression testing: + +- Python 3.7+ +- Numpy +- CMake and CTest (Optional) +- Bokeh 1.4 (Optional) + +.. _python_driver: + +Executing with Python driver +---------------------------- +The regression test can be executed manually with the included driver at +``openfast/reg_tests/manualRegressionTest.py``. This program reads a case list +file at ``openfast/reg_tests/r-test/glue-codes/openfast/CaseList.md``. Cases +can be removed or ignored by starting that line with a ``#``. The driver +program includes multiple optional flags which can be obtained by +executing with the help option: + +:: + + >>>$ python manualRegressionTest.py -h + usage: manualRegressionTest.py [-h] [-p [Plotting-Flag]] [-n [No-Execution]] + [-v [Verbose-Flag]] [-case [Case-Name]] + OpenFAST System-Name Compiler-Id Test-Tolerance + + Executes OpenFAST and a regression test for a single test case. + + positional arguments: + OpenFAST path to the OpenFAST executable + System-Name current system's name: [Darwin,Linux,Windows] + Compiler-Id compiler's id: [Intel,GNU] + Test-Tolerance tolerance defining pass or failure in the regression + test + + optional arguments: + -h, --help show this help message and exit + -p [Plotting-Flag], -plot [Plotting-Flag] + bool to include plots in failed cases + -n [No-Execution], -no-exec [No-Execution] + bool to prevent execution of the test cases + -v [Verbose-Flag], -verbose [Verbose-Flag] + bool to include verbose system output + -case [Case-Name] single case name to execute + +.. note:: + + For the NREL 5MW turbine test cases, an external ServoDyn controller must + be compiled and included in the appropriate directory or all NREL 5MW + cases will fail without starting. More information is available in the + documentation for the `r-test repository <https://github.com/openfast/r-test#note---servodyn-external-controllers-for-5mw_baseline-cases>`__, + but be aware that these three DISCON controllers must exist + + .. code-block:: bash + + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON.dll + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON_ITIBarge.dll + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON_OC3Hywind.dll + +.. _ctest_driver: + +Executing with CTest +-------------------- +CTest is included with CMake and is primarily a set of preconfigured targets +and commands. To use the CTest driver for the regression test, execute CMake as +described in :ref:`installation`, but with this additional flag: +``-DBUILD_TESTING=ON``. + +The regression test specific CMake variables are + +:: + + BUILD_TESTING + CTEST_OPENFAST_EXECUTABLE + CTEST_[MODULE]_EXECUTABLE where [MODULE] is the module name + CTEST_PLOT_ERRORS + CTEST_REGRESSION_TOL + +Some additional resources that are required for the full regression test suite +are included in the CMake project. Specifically, external ServoDyn controllers +must be compiled for a given system and placed in a particular location. Thus, +be sure to execute the build command with the ``install`` target: + +.. code-block:: bash + + # Configure CMake with testing enabled and accept the default + # values for all other test-specific CMake variables + cmake .. -DBUILD_TESTING=ON + + # Build and install + make install + +.. note:: + + REMINDER: For the NREL 5MW turbine test cases, an external ServoDyn controller must + be compiled and included in the appropriate directory or all NREL 5MW + cases will fail without starting. More information is available in the + documentation for the `r-test repository <https://github.com/openfast/r-test#note---servodyn-external-controllers-for-5mw_baseline-cases>`__, + but be aware that these three DISCON controllers must exist + + .. code-block:: bash + + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON.dll + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON_ITIBarge.dll + openfast/build/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData/DISCON_OC3Hywind.dll + +After CMake configuration and compiling, the automated regression test can be +executed by running either of the commands ``make test`` or ``ctest`` from the +``build`` directory. If the entire OpenFAST package is to be built, CMake will +configure CTest to find the new binary at +``openfast/build/glue-codes/openfast/openfast``. However, if the intention is +to build only the test suite, the OpenFAST binary should be specified in the +CMake configuration under the ``CTEST_OPENFAST_EXECUTABLE`` flag. There is +also a corresponding ``CTEST_[MODULE]_NAME`` flag for each module included in +the regression test. + +When driven by CTest, the regression test can be executed by running various +forms of the command ``ctest`` from the build directory. The basic commands +are: + +.. code-block:: bash + + # Run the entire regression test + ctest + + # Disable actual execution of tests; + # this is helpful in formulating a particular ctest command + ctest -N + + # Run the entire regression test with verbose output + ctest -V + + # Run tests by name where TestName is a regular expression (regex) + ctest -R [TestName] + + # Run all tests with N tests executing in parallel + ctest -j [N] + +Each regression test case contains a series of labels associating all of the +modules used. The labeling can be seen in the test instantiation in +``reg_tests/CTestList.cmake`` or with the command: + +.. code-block:: bash + + # Print all available test labels + ctest --print-labels + +The test cases corresponding to a particular label can be executed with this +command: + +.. code-block:: bash + + # Filter the test cases corresponding to a particular label + ctest -L [Label] + +Flags can be compounded making useful variations such as + +.. code-block:: bash + + # Run all cases that use AeroDyn14 with verbose output + ctest -V -L aerodyn14 + + # Run all cases that use AeroDyn14 in 16 concurrent processes + ctest -j 16 -L aerodyn14 + + # Run the case with name "5MW_DLL_Potential_WTurb" with verbose output + ctest -V -R 5MW_DLL_Potential_WTurb + + # List all tests with the "beamdyn" label + ctest -N -L beamdyn + + # List the labels included in all tests matching the regex "bd" + ctest -N -R bd --print-labels + + +The automated regression test writes new files only into the build directory. +Specifically, all locally generated solutions are located in the corresponding +glue-code or module within ``openfast/build/reg_tests``. The baseline solutions +contained in ``openfast/reg_tests/r-test`` are strictly read and are not +modified by the automated process. + +.. _regression_test_example: + +Regression test examples +------------------------ +The following examples illustrate methods of running the regression tests +on Unix-based systems. However, similar procedures can be used +on Windows with CMake and CTest. An alternate method of running the +regression tests on Windows is given in :ref:`reg_test_windows`. + +Compile OpenFAST and execute with CTest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following example assumes the user is starting completely from scratch. +The commands below download the source code, configure the OpenFAST project +with CMake, compile all executables, and execute the full regression test +suite. + +.. code-block:: bash + + # Download the source code from GitHub + # Note: The default branch is 'master' + git clone --recursive https://github.com/openfast/openfast.git + cd openfast + + # If necessary, switch to another target branch and update r-test + git checkout dev + git submodule update + + # Create the build and install directories and move into build + mkdir build install && cd build + + # Configure CMake for testing + # - BUILD_TESTING - turn ON + # - CTEST_OPENFAST_EXECUTABLE - accept the default + # - CTEST_[MODULE]_EXECUTABLE - accept the default + cmake .. -DBUILD_TESTING=ON + + # Compile and install + make install + + # Execute the full test suite with 4 concurrent processes + ctest -j4 + +Configure with CMake and a given executable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example assumes the user has a fully functional OpenFAST executable +available along with any necessary libraries, but does not have the source +code repository downloaded. This might be the case when executables are +distributed within an organization or downloaded from an +`OpenFAST Release <https://github.com/openfast/openfast/releases>`__. +Here, nothing will be compiled, but the test suite will be configured +with CMake for use with the CTest command. + +.. code-block:: bash + + # Download the source code from GitHub + # Note: The default branch is 'master' + git clone --recursive https://github.com/openfast/openfast.git + cd openfast + + # If necessary, switch to another target branch and update r-test + git checkout dev + git submodule update + + # Create the build directory and move into it + mkdir build && cd build + + # Configure CMake with openfast/reg_tests/CMakeLists.txt for testing + # - BUILD_TESTING - turn ON + # - CTEST_OPENFAST_EXECUTABLE - provide a path + # - CTEST_[MODULE]_EXECUTABLE - provide a path + cmake ../reg_tests \ + -DBUILD_TESTING=ON \ + -DCTEST_OPENFAST_EXECUTABLE=/home/user/Desktop/openfast_executable \ + -DCTEST_BEAMDYN_EXECUTABLE=/home/user/Desktop/beamdyn_driver + + # Install required files + make install + + # Execute the full test suite with 4 concurrent processes + ctest -j4 + +.. _example_python_driver: + +Python driver with a given executable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example assumes the user has a fully functional OpenFAST executable +available along with any necessary libraries, but does not have the source +code repository downloaded. This might be the case when executables are +distributed within an organization or downloaded from an +`OpenFAST Release <https://github.com/openfast/openfast/releases>`__. +Nothing will be compiled, but the test suite will be executed with the +included Python driver. + +.. code-block:: bash + + # Download the source code from GitHub + # Note: The default branch is 'master' + git clone --recursive https://github.com/openfast/openfast.git + cd openfast + + # If necessary, switch to another target branch and update r-test + git checkout dev + git submodule update + + # Execute the Python driver + cd reg_tests + python manualRegressionTest.py -h + # usage: manualRegressionTest.py [-h] [-p [Plotting-Flag]] [-n [No-Execution]] + # [-v [Verbose-Flag]] [-case [Case-Name]] + # OpenFAST System-Name Compiler-Id Test-Tolerance + # + # Executes OpenFAST and a regression test for a single test case. + # + # positional arguments: + # OpenFAST path to the OpenFAST executable + # System-Name current system's name: [Darwin,Linux,Windows] + # Compiler-Id compiler's id: [Intel,GNU] + # Test-Tolerance tolerance defining pass or failure in the regression + # test + # + # optional arguments: + # -h, --help show this help message and exit + # -p [Plotting-Flag], -plot [Plotting-Flag] + # bool to include plots in failed cases + # -n [No-Execution], -no-exec [No-Execution] + # bool to prevent execution of the test cases + # -v [Verbose-Flag], -verbose [Verbose-Flag] + # bool to include verbose system output + # -case [Case-Name] single case name to execute + + python manualRegressionTest.py \ + ..\build\bin\openfast_x64_Double.exe \ + Windows \ + Intel \ + 1e-5 + +.. _reg_test_windows: + +Detailed example of running on Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The :ref:`example_python_driver` example can be used for running the +regression tests on a Windows computer. However, a more detailed, step-by-step +description is given in :ref:`regression_test_windows`. + +.. toctree:: + :maxdepth: 1 + :hidden: + + regression_test_windows.rst diff --git a/OpenFAST/docs/source/testing/regression_test_windows.rst b/OpenFAST/docs/source/testing/regression_test_windows.rst new file mode 100644 index 000000000..4894e7b51 --- /dev/null +++ b/OpenFAST/docs/source/testing/regression_test_windows.rst @@ -0,0 +1,121 @@ +.. _regression_test_windows: + +Windows with Visual Studio regression test +========================================== + +1) Clone the openfast repo and initialize the testing database + + a) Open a git command shell window (like git bash) + + b) Change your working directory to the location above where you want your local repo to be located (the repo will be placed into a folder called openfast at this location) + + c. Type: ``git clone https://github.com/openfast/openfast.git`` (this creates a local version of the openfast repo on your computer). + You should see something like this: + + :: + + Cloning into 'openfast'... + remote: Counting objects: 23801, done. + remote: Compressing objects: 100% (80/80), done. + remote: Total 23801 (delta 73), reused 102 (delta 50), pack-reused 23670 + Receiving objects: 100% (23801/23801), 92.10 MiB 18.99 MiB/s, done. + Resolving deltas: 100% (13328/13328), done. + Checking connectivity... done. + + + d) Type: ``cd openfast`` (change your working directory to the openfast folder) + + e) Type: ``git checkout dev`` (this places your local repo on the correct branch of the openfast repo) + + f) Type: ``git submodule update --init --recursive`` (this downloads the testing database to your computer) + You should see something like this: + + :: + + Submodule 'reg_tests/r-test' (https://github.com/openfast/r-test.git) registered for path 'reg_tests/r-test' + Cloning into 'reg_tests/r-test'... + remote: Counting objects: 3608, done. + remote: Compressing objects: 100% (121/121), done. + remote: Total 3608 (delta 22), reused 161 (delta 21), pack-reused 3442 + Receiving objects: 100% (3608/3608), 154.52 MiB 26.29 MiB/s, done. + Resolving deltas: 100% (2578/2578), done. + Checking connectivity... done. + Submodule path 'reg_tests/r-test': checked out 'b808f1f3c1331fe5d03c5aaa4167532c2492d378' + + +2) Build The Regression Testing DISCON DLLs + + a) Open the Visual Studio Solution (``Discon.sln``) located in ``openfast\vs-build\Discon`` folder + + b) Choose Release and x64 for the Solutions Configuration and Solutions Platform, respectively + + c) From the menu bar select ``Build->Build Solution`` + + d) You should now see the files ``Discon.dll``, ``Discon_ITIBarge.dll``, and ``Discon_OC3Hywind.dll`` in your ``openfast\reg_tests\r-test\glue-codes\fast\5MW_Baseline\ServoData`` folder. + +3) Build OpenFAST using Visual Studio + + a) Open the Visual Studio Solution (``FAST.sln``) located in ``openfast\vs-build\FAST`` folder + + b) Choose Release_Double and x64 for the Solutions Configuration and Solutions Platform, respectively + + c) From the menu bar select ``Build->Build Solution`` + + i) If this is the first time you have tried to build openfast, you will get build errors!!! [continue to steps (ii) and (iii), otherwise if FAST builds successfully, continue to step (3d) ] + + ii) Cancel build using the menubar ``Build->Cancel`` + [ VS is confused about the build-order/dependency of the project files in FASTlib., but canceling and restarting VS, it somehow as enough info from the partial build to get this right, now] + + iii) Close your Visual Studio and then Repeat Steps (a) through (c) + + d) You should now see the file ``openfast_x64_Double.exe`` in your ``openfast\build\bin`` folder. + + +4) Prepare regression tests + + a) Create a subdirectory called ``reg_tests`` in your ``openfast\build`` folder. + + b) Copy the contents of ``openfast\reg_tests\r-test`` to ``openfast\build\reg_tests``. + + +5) Execute the OpenFAST regression Tests + + a) Open a command prompt which is configured for Python [ like Anaconda3 ] + + b) Change your working directory to ``openfast\reg_tests`` + + c) Type: ``python manualRegressionTest.py ..\build\bin\openfast_x64_Double.exe Windows Intel 1e-5`` + You should see this: ``executing AWT_YFix_WSt`` + + d) The tests will continue to execute one-by-one until you finally see something like this: + + :: + + executing AWT_YFix_WSt PASS + executing AWT_WSt_StartUp_HighSpShutDown PASS + executing AWT_YFree_WSt PASS + executing AWT_YFree_WTurb PASS + executing AWT_WSt_StartUpShutDown PASS + executing AOC_WSt PASS + executing AOC_YFree_WTurb PASS + executing AOC_YFix_WSt PASS + executing UAE_Dnwind_YRamp_WSt PASS + executing UAE_Upwind_Rigid_WRamp_PwrCurve PASS + executing WP_VSP_WTurb_PitchFail PASS + executing WP_VSP_ECD PASS + executing WP_VSP_WTurb PASS + executing WP_Stationary_Linear PASS + executing SWRT_YFree_VS_EDG01 PASS + executing SWRT_YFree_VS_EDC01 PASS + executing SWRT_YFree_VS_WTurb PASS + executing 5MW_Land_DLL_WTurb PASS + executing 5MW_OC3Mnpl_DLL_WTurb_WavesIrr PASS + executing 5MW_OC3Trpd_DLL_WSt_WavesReg PASS + executing 5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth PASS + executing 5MW_ITIBarge_DLL_WTurb_WavesIrr PASS + executing 5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti PASS + executing 5MW_OC3Spar_DLL_WTurb_WavesIrr PASS + executing 5MW_OC4Semi_WSt_WavesWN PASS + executing 5MW_Land_BD_DLL_WTurb PASS + + e) If an individual test succeeds you will see ``PASS`` otherwise you will see ``FAIL`` after that test's name diff --git a/OpenFAST/docs/source/testing/unit_test.rst b/OpenFAST/docs/source/testing/unit_test.rst new file mode 100644 index 000000000..e8bfd3f9e --- /dev/null +++ b/OpenFAST/docs/source/testing/unit_test.rst @@ -0,0 +1,136 @@ +.. _unit_test: + +Unit test +========= +In a software package as dynamic and collaborative as OpenFAST, confidence in +multiple layers of code is best accomplished with a strong system of unit +tests. Through robust testing practices, the entire OpenFAST community can +understand the intention behind code blocks and debug or expand functionality +quicker and with more confidence and stability. + +Unit testing in OpenFAST modules is accomplished through `pFUnit <https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git>`__. +This framework provides a Fortran abstraction to the popular +`xUnit <https://en.wikipedia.org/wiki/XUnit>`__ structure. pFUnit is compiled +along with OpenFAST through CMake when the CMake variable ``BUILD_TESTING`` is +turned on. + +The BeamDyn and NWTC Library modules contain some sample unit tests and should +serve as a reference for future development and testing. + +Dependencies +------------ +The following packages are required for unit testing: + +- Python 3.7+ +- CMake +- pFUnit - Included in OpenFAST repo through a git-submodule + +Compiling +--------- +Compiling the unit tests is handled with CMake similar to compiling OpenFAST +in general. After configuring CMake with ``BUILD_TESTING`` turned on, new +build targets are created for each module included in the unit test +framework named ``[module]_utest``. Then, ``make`` the target to test: + +.. code-block:: bash + + cmake .. -DBUILD_TESTING=ON + make beamdyn_utest + +This creates a unit test executable at +``openfast/build/unit_tests/beamdyn/beamdyn_utest``. + +Executing +--------- +To execute a module's unit test, simply run the unit test binary. For example: + +.. code-block:: bash + + >>>$ ./openfast/build/unit_tests/beamdyn/beamdyn_utest + ............. + Time: 0.018 seconds + + OK + (14 tests) + +pFUnit will display a ``.`` for each unit test successfully completed +and a ``F`` for each failing test. If any tests do fail, the failure +criteria will be displayed listing which particular value caused +the failure. Failure cases display the following output: + +.. code-block:: bash + + >>>$ ./unit_tests/beamdyn/beamdyn_utest + .....F....... + Time: 0.008 seconds + + Failure + in: + test_BD_CrvMatrixH_suite.test_BD_CrvMatrixH + Location: + [test_BD_CrvMatrixH.F90:48] + simple rotation with known parameters: Pi on xaxis expected +0.5000000 but found: +0.4554637; difference: |+0.4453627E-01| > tolerance:+0.1000000E-13; first difference at element [1, 1]. + + FAILURES!!! + Tests run: 13, Failures: 1, Errors: 0 + Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG IEEE_DIVIDE_BY_ZERO + ERROR STOP *** Encountered 1 or more failures/errors during testing. *** + + Error termination. Backtrace: + #0 0x1073b958c + #1 0x1073ba295 + #2 0x1073bb1b6 + #3 0x106ecdd4f + #4 0x1063fabee + #5 0x10706691e + +Adding unit tests +----------------- +Unit tests should be included for each new, *testable* code block (subroutine +or function). What is testable is the discretion of the developer, but an +element of the pull request review process will be evaluating test coverage. + +New unit tests can be added to a ``tests`` directory alongside the ``src`` +directory included in each module. For example, a module directory may be +structured as + +:: + + openfast/ + └── modules/ + └── sampledyn/ + ├── src/ + │ ├── SampleDyn.f90 + │ └── SampleDyn_Subs.f90 + └── tests/ + ├── test_SampleDyn_Subroutine1.F90 + ├── test_SampleDyn_Subroutine2.F90 + └── test_SampleDyn_Subroutine3.F90 + +Each unit test must be contained in a unique file called +``test_[SUBROUTINE].F90`` where ``[SUBROUTINE]`` is the code block being +tested. The new files should contain a Fortran `module` which itself +contains a Fortran `subroutine` for each specific test case. Generally, +multiple tests will be required to fully test one subroutine. + +Finally, update the CMake configuration for building a module's unit +test executable by copying an existing unit test CMake configuration +into a new module directory: + +.. code-block:: bash + + cp -r openfast/unit_tests/beamdyn openfast/unit_tests/[module] + +Then, modify the new ``CMakeLists.txt`` with the appropriate list of test +subroutines and module name variables. + +For reference, a template unit test file is included at +``openfast/unit_tests/test_SUBROUTINE.F90``. Each unit test should fully test +the target code block. If full test coverage is not easily achievable, it may +be an indication that refactoring would be beneficial. + +Some useful topics to consider when developing and testing for OpenFAST are: + +- `Test driven development <https://en.wikipedia.org/wiki/Test-driven_development#Test-driven_development_cycle>`__ +- `Separation of concerns <https://en.wikipedia.org/wiki/Separation_of_concerns>`__ +- `pFUnit usage <http://pfunit.sourceforge.net/page_Usage.html>`__ diff --git a/OpenFAST/docs/source/this_doc.rst b/OpenFAST/docs/source/this_doc.rst new file mode 100644 index 000000000..24ff4bf36 --- /dev/null +++ b/OpenFAST/docs/source/this_doc.rst @@ -0,0 +1,40 @@ +.. _this_doc: + +This documentation +================== + +OpenFAST documentation is hosted on +`readthedocs <http://readthedocs.org/>`_, and is automatically +generated from both the +`master <http://github.com/openfast/openfast/tree/master/>`_ and +`dev <http://github.com/openfast/openfast/tree/dev/>`_ branches whenever +new commits are added. Clicking on the bar on the lower left corner of the +page reveals a panel (see image below) containing options to select the branch +of the repository, download the documentation other formats (PFD, HTML, EPub), +and link to other relevant websites. + +.. image:: ../_static/docs_options.png + :width: 30% + :align: center + +While OpenFAST developer documentation is being enhanced here, developers are +encouraged to consult the legacy FAST v8 +`Programmer's Handbook <https://nwtc.nrel.gov/system/files/ProgrammingHandbook_Mod20130717.pdf>`_. +Instructions on obtaining and installing OpenFAST are available in +:ref:`installation`, and documentation for verifying an installation with the +automated tests is at :ref:`testing`. + +The majority of this documentation is divided into two parts: + +:ref:`user_guide` + + Directed towards end-users, this part provides detailed documentation + regarding usage of the OpenFAST and its underlying modules, + as well as theory and verification documentation. + +:ref:`dev_guide` + + The developer guide is targeted towards users wishing to extend the + functionality provided within OpenFAST. Here you will find details + regarding the code structure, API supported by various classes, and links to + source code documentation extracted using Doxygen. diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/01-introduction.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/01-introduction.rst new file mode 100644 index 000000000..3b33cd5ac --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/01-introduction.rst @@ -0,0 +1,47 @@ +.. _AA-introduction: + +Introduction +------------ + +The increasing penetration of wind energy into the electricity mix has +been possible thanks to a constantly growing installed capacity, which +has so far been mostly located on land. Land-based installations are, +however, increasingly constrained by local ordinances and an +often-limiting factor that comprises maximum allowable levels of noise. +To further increase the number of land-based installations, it is +important to develop accurate modeling tools to estimate the noise +generated by wind turbines. This allows for a more accurate assessment +of the noise emissions and the possibility to design quieter wind +turbines. + +Wind turbines emit two main sources of noise: + +- Aeroacoustics noise from the interaction between rotor blades and the + turbulent atmospheric boundary layer + +- Mechanical noise from the nacelle component, mostly the gearbox, + generator, and yaw mechanism. + +This work targets the first class of noise generation and aims at +providing a set of open-source models to estimate the aeroacoustics +noise generated by an arbitrary wind turbine rotor. The models are +implemented in Fortran and are fully coupled to the aeroservoelastic +wind turbine simulator OpenFAST. The code is available in the GitHub +repository of OpenFAST. [1]_ The code builds on the implementation of +NAFNoise and the documentation presented in :cite:`aa-MoriartyMigliore:2003` +and :cite:`aa-Moriarty:2005`. OpenFAST is implemented as a modularization +framework and the aeroacoustics model is implemented as a submodule of +AeroDyn (:cite:`aa-MoriartyHansen:2005`). + +The set of models is described in :numref:`AA-noise-models` and exercised on the +noise estimate of the International Energy Agency (IEA) land-based reference +wind turbine in :numref:`AA-model-verification`. In +:numref:`AA-model-verification`, we also show a comparison to results obtained +running the noise models implemented at the Technical University of Munich. This +documentation closes with conclusions, an outlook on future work, and +appendices, where the input files to OpenFAST are presented. + + +.. [1] + https://github.com/OpenFAST/openfast + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/02-noise-models.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/02-noise-models.rst new file mode 100644 index 000000000..b1b13c469 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/02-noise-models.rst @@ -0,0 +1,576 @@ +.. _AA-noise-models: + +Aeroacoustics Noise Models +-------------------------- + +The aeroacoustics noise of wind turbine rotors emanates from pressure +oscillations that are generated along the blades and propagate in the +atmosphere. This source of noise has been historically simulated with models +characterized by different fidelity levels. At lower fidelity, models correlated +aeroacoustics noise with rotor thrust and torque +(:cite:`aa-Lowson:1970,aa-Viterna:1981`). At higher fidelity, three-dimensional +incompressible computational fluid dynamics models are coupled with the Ffowcs +Williams-Hawkings model to propagate pressure oscillations generated along the +surface of the rotor blades to the far field (:cite:`aa-Klein:2018`). The latter +models are often only suitable to estimate noise at low frequency because +capturing noise in the audible range, which is commonly defined between 20 +(hertz) Hz and 20 kilohertz (kHz), requires a very fine space-time +discretization with enormous computational costs. + +For the audible range, a variety of models is available in the public +domain, and :cite:`aa-Sucameli:2018` offers the most recent literature +review. These models have inputs that match the inputs and outputs of +modern aeroservoelastic solvers, such as OpenFAST, and have therefore +often been coupled together. Further, the computational costs of these +acoustic models are similar to the costs of modern aeroservoelastic +solvers, which has facilitated the coupling. + +Models have targeted different noise generation mechanisms following the +distinction defined by :cite:`aa-Brooks:1989`, and the +mechanism of turbulent inflow noise. The latter represents a broadband +noise source that is generated when a body of arbitrary shape +experiences an unsteady lift because of the presence of an incident +turbulent flow. For an airfoil, this phenomenon can be interpreted as +leading-edge noise. Turbulent inflow noise was the topic of multiple +investigations over the past decades and, as a result, multiple models +have been published (:cite:`aa-Sucameli:2018`). The BPM model includes five +mechanisms of noise generation for an airfoil immersed in a flow: + +1. Turbulent boundary layer – trailing edge (TBL-TE) + +2. Separation stall + +3. Laminar boundary layer – vortex shedding + +4. Tip vortex + +5. Trailing-edge bluntness – vortex shedding. + +For the five mechanisms, semiempirical models were initially defined for +the NACA 0012 airfoil. The BPM model is still a popular model for wind +turbine noise prediction, and subsequent studies have improved the model +by removing some of the assumptions originally adopted. Recent studies +have especially focused on the TBL-TE mechanism, which is commonly the +dominant noise source of modern wind turbines. As a result, each noise +source defined in the BPM model now has a variety of permutations. + +The following subsections describe the details of each mechanism and the +models implemented in this model of OpenFAST. + +.. _aa-turbinflow: + +Turbulent Inflow +~~~~~~~~~~~~~~~~ + +A body of any arbitrary shape, when immersed in a turbulent flow, +generates surface pressure fluctuations. Over the years, several +formulations of the turbulent inflow noise model have been developed +(:cite:`aa-Sucameli:2018`). In this model of OpenFAST, the formulation +defined in :cite:`aa-MoriartyGuidatiMigliore:2004` is adopted. The formulation is based +on the model of Amiet (:cite:`aa-Amiet:1975,aa-Paterson:1976`) and is +presented in :numref:`aa-amiet`. Additionally, the user can activate the +correction defined by :cite:`aa-MoriartyHansen:2005`, which builds upon the +Amiet model and accounts for the thickness of the airfoils adopted along +the blade span. This second model is named Simplified Guidati and is +presented in :numref:`aa-guidati`. + +.. _aa-amiet: + +Amiet model +^^^^^^^^^^^ + +The formulation is based on work from :cite:`aa-Amiet:1975` and +:cite:`aa-Paterson:1976`, and it represents the blade as a +flat plate and neglects the shape of the airfoil. + +The model starts by first computing the wave number, :math:`k_{1}`, for +a given frequency :math:`f`: + +.. math:: + k_{1} = \frac{2\text{πf}}{U_{1}} + :label: aa-eq:1 + +where :math:`U_{1}` is the incident inflow velocity on the profile. From +:math:`k_{1}`, the wave numbers :math:`{\overline{k}}_{1}` and +:math:`{\widehat{k}}_{1}` are computed: + +.. math:: + {\overline{k}}_{1} = \frac{k_{1}c_{i}}{2} + :label: aa-eq:2 + +.. math:: + {\widehat{k}}_{1} = \frac{k_{1}}{k_{e}} + :label: aa-eq:3 + +where :math:`c_{i}` is the local chord, and :math:`k_{e}` is the wave +number range of energy containing eddies, defined as: + +.. math:: + k_{e} = \frac{3}{4L_{t}}. + :label: aa-eq:4 + +L\ :sub:`t` is the turbulent length scale, and many different +formulations have been proposed over the years. As default +implementation, :math:`L_{t}` is defined following the formulation +proposed in :cite:`aa-Zhu:2005`: + +.. math:: + L_{t} = 25z^{0.35}z_{0}^{- 0.063} + :label: aa-eq:5 + +where :math:`z` is the height above the ground of the leading edge of +section :math:`i` at a given instant, :math:`t`, while :math:`z_{0}` is +the surface roughness. Note that setting :math:`L_{t}` appropriately is +a challenge, and advanced users of this model may want to validate this +formulation against experimental data. + +The value of sound pressure level (:math:`\text{SPL}`) is expressed in +one-third octave bands at the given frequency, :math:`f`, originated at +the given blade station, :math:`i`, which can be computed as: + +.. math:: + \text{SPL}_{\text{TI}} = 10\log_{10}{\left( \rho^{2}c^{4}\frac{L_{t}d}{{2r}_{e}^{2}}M^{5}I_{1}^{2} + \frac{{\widehat{k}}_{1}^{3}}{\left( 1 + {\widehat{k}}_{1}^{2} \right)^{\frac{7}{3}}} + \overline{D} \right) +}78.4 + :label: aa-eq:6 + +where :math:`\rho` is the air density, :math:`c` the speed of sound, +:math:`d` the blade element span, :math:`r_{e}` the effective distance +between leading edge and observer, :math:`M` the Mach number, +:math:`I_{1}` the turbulence intensity of the airfoil inflow, and +:math:`\overline{D}` the directivity term. :math:`\overline{D}` is +different below (:math:`{\overline{D}}_{l}`) and above +(:math:`{\overline{D}}_{h}`) a certain frequency, which is named +“cut-off” and defined as: + +.. math:: + f_{\text{co}} = \frac{10U_{1}}{\pi c_{i}}. + :label: aa-eq:7 + +The formulations of :math:`{\overline{D}}_{h}\ `\ and +:math:`{\overline{D}}_{l}` are presented in :numref:`aa-directivity`. + +The current implementation offers two approaches to estimate +:math:`I_{1}`. The first one is through a user-defined grid of +:math:`I_{1}`; see :numref:`aa-sec-TIgrid`. The second option is to have the code +reconstructing :math:`I_{1}` from the turbulent wind grid, where the +code computes the airfoil relative position of each blade section, +:math:`i`, at every time instant and, given the rotor speed, +reconstructs the inflow component, :math:`I_{1}`, of the turbulence +intensity. + +Two corrections to this model are also implemented. The first one +comprises a correction for the angle of attack, :math:`\alpha`, in which +the effect is neglected in the original formulation from :cite:`aa-Amiet:1975` +and Amiet and Peterson (1976). This correction is formulated as: + +.. math:: + \text{SPL}_{\text{TI}} = \text{SPL}_{\text{TI}} + 10\log_{10}{\left( 1 + 9a^{2} \right).} + :label: aa-eq:8 + +The second correction is called low-frequency correction +(:math:`\text{LFC}`), and is formulated as: + +.. math:: + S^{2} = \left( \frac{2\pi{\overline{k}}_{1}}{\beta^{2}} + + \left( 1 + 2.4\frac{{\overline{k}}_{1}}{\beta^{2}} \right)^{- 1} \right)^{- 1} + :label: aa-eq:9 +.. math:: + LFC = 10S^{2}M{\overline{k}}_{1}^{2}\beta^{- 2} + :label: aa-eq:10 +.. math:: + \text{SPL}_{\text{TI}} = \text{SPL}_{\text{TI}} + 10\log_{10}\left( \frac{\text{LFC}}{1 + LFC} \right). + :label: aa-eq:11 + +In :eq:`aa-eq:9` and :eq:`aa-eq:10`, :math:`S^{2}` represents the squared Sears +function, and :math:`\beta^{2}` is the Prandtl-Glauert correction +factor, which is defined as: + +.. math:: + \beta^{2} = 1 - M^{2}. + :label: aa-eq:12 + +It is worth stressing that numerous alternative formulations of the +turbulent inflow noise model exist (:cite:`aa-Sucameli:2018`), where the +main differences comprise different definitions of :math:`L_{t}` and +:math:`k_{1}`. + +.. _aa-guidati: + +Simplified Guidati +^^^^^^^^^^^^^^^^^^ + +Sound spectra are often overpredicted by the Amiet model implemented here. +Guidatai (:cite:`aa-Guidati:1997`) derived a correction to the sound pressure +levels by adding a term considering shape and camber of the airfoil profiles, +but the method proved computationally too expensive for wind turbine +simulations. Moriarty et al. (:cite:`aa-MoriartyGuidatiMigliore:2005`) proposed +a simplified model based on geometric characteristics of six wind turbine +airfoils. The validity of the correction is limited to Mach numbers on the order +of 0.1 ≈ 0.2 and Strouhal number :math:`\text{St}` below 75. :math:`\text{St}` +is defined based on airfoil chord and mean inflow velocity: + +.. math:: + St = \frac{fc_{i}}{U_{1}}. + :label: aa-eq:13 + +The formula for the correction to the noise spectra is provided in Eq. 4 +in :cite:`aa-MoriartyGuidatiMigliore:2005`: + +.. math:: + t = t_{1\%} + t_{10\%} + :label: aa-eq:14 +.. math:: + {\mathrm{\Delta}SPL}_{\text{TI}} = -\left( 1.123t + 5.317t^{2} \right)\left( 2\pi St + 5 \right) + :label: aa-eq:15 + +where :math:`t_{x\%}` is the relative thickness of the profile at +:math:`x` position along the chord (i.e., 0% being the leading edge and +100% the trailing edge). + +It should be highlighted here that a validation campaign was conducted in a wind +tunnel on two-dimensional airfoils (:cite:`aa-MoriartyGuidatiMigliore:2004`), +returning a fairly poor match between the Simplified Guidati model and the +experimental results. Therefore, a correction of +10 decibels (dB) on the SPL +levels across the whole frequency spectrum was proposed. This correction is +still implemented, but a validation at turbine level should assess the accuracy +of the models for turbulent inflow. It should also be noted that the code +currently does not check whether Mach and Strouhal numbers are within the range +of validity of this model. + +.. _aa-turb-TE: + +Turbulent Boundary Layer – Trailing Edge +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Airfoils immersed in a flow develop a boundary layer, which at high +Reynolds numbers is turbulent. When the turbulence passes over the +trailing edge, noise is generated. This noise source was named TBL-TE in +:cite:`aa-Brooks:1989` and it is a relevant source of aeroacoustics noise +for modern wind turbine rotors. Two formulations of TBL-TE noise are +implemented in the code: (1) the original formulation from the BPM +model, described in :numref:`aa-amiet`, and (2) a more recent model developed +at the Dutch research institute, TNO, described in :numref:`aa-guidati`. Both +models take as input the characteristics of the airfoil boundary layer. +These must be provided by the user and are discussed in :numref:`aa-sec-BLinputs`. + +.. _aa-turb-TE-bpm: + +BPM +^^^ + +The :math:`\text{SPL}` of the TBL-TE noise in the BPM model is made from +three contributions: + +.. math:: + \text{SPL}_{TBL - TE} = 10\log_{10}\left( 10^{\frac{\text{SPL}_{p}}{10}} + + 10^{\frac{\text{SPL}_{s}}{10}} + 10^{\frac{\text{SPL}_{\alpha}}{10}} \right) + :label: aa-eq:16 + +where the subscripts :sub:`p`, :sub:`s`, and :sub:`α` refer to the +contributions of pressure side, suction side, and angle of attack, +respectively. The equations describing the three contributions are +described in great detail in Section 5.1.2, in :cite:`aa-Brooks:1989`, and +are summarized here. + +For the suction and pressure contributions, the equations are: + +.. math:: + \text{SPL}_{p} = 10\log_{10}\left( \frac{\delta_{p}^{*}M^{5}d{\overline{D}}_{h}}{r_{e}^{2}} \right) + + A\left( \frac{\text{St}_{p}}{\text{St}_{1}}\right) + \left( K_{1} - 3 \right) + {\mathrm{\Delta}K}_{1} + :label: aa-eq:17 +.. math:: + \text{SPL}_{s} = 10\log_{10}\left( \frac{\delta_{s}^{*}M^{5}d{\overline{D}}_{h}}{r_{e}^{2}} \right) + + A\left( \frac{\text{St}_{s}}{\text{St}_{1}} \right) + \left( K_{1} - 3 \right). + :label: aa-eq:18 + +The terms in the equations, which are also described in the nomenclature +at the beginning of this document, list :math:`\delta^{*}` as the +boundary layer displacement thickness on either side of the airfoil, +:math:`St,` as the Strouhal number based on :math:`\delta^{*}`, and +:math:`A`, :math:`A'`, :math:`B`, :math:`{\Delta K}_{1}`, :math:`K_{1}`, +and :math:`K_{2}` as empirical functions based on :math:`\text{St}`. + +For the angle-of-attack contribution, a distinction is made above and +below the stall angle, which in the original BPM model is set equal to +12.5 degrees, whereas it is here assumed to be the actual stall angle of +attack of the airfoil at blade station i. Below stall, +:math:`\text{SPL}_{\alpha}` is equal to: + +.. math:: + \text{SPL}_{\alpha} = 10\log_{10}\left( \frac{\delta_{s}^{*}M^{5}d{\overline{D}}_{h}}{r_{e}^{2}} \right) + + B\left( \frac{\text{St}_{s}}{\text{St}_{2}} \right) + K_{2}. + :label: aa-eq:19 + +At angles of attack above the stall point, the flow along the profile is +fully separated and noise radiates from the whole +chord.\ :math:`\ \text{SPL}_{p}` and :math:`\text{SPL}_{s}` are then set +equal to -∞, whereas :math:`\text{SPL}_{\alpha}` becomes: + +.. math:: + \text{SPL}_{\alpha} = 10\log_{10}\left( \frac{\delta_{s}^{*}M^{5}d{\overline{D}}_{l}}{r_{e}^{2}} \right) + + A'\left( \frac{\text{St}_{s}}{\text{St}_{2}} \right) + K_{2.} + :label: aa-eq:20 + +Notably, above stall the low-frequency directivity :math:`{\overline{D}}_{l}` is adopted in Eqs. 18 and 19 (see +:numref:`aa-directivity`). + +.. _aa-turb-TE-tno: + +TNO model +^^^^^^^^^ + +The TNO model is a more recent model to simulate the noise emitted by +the vortices shed at the trailing edge of the blades and was formulated +by Parchen (:cite:`aa-Parchen:1998`). The implementation adopted here is the one described +in Moriarty et al. (2005). The TNO model uses the spectrum of the wave +number, :math:`\overline{k}`, of unsteady surface pressures to estimate +the far-field noise. The spectrum, :math:`P`, is assumed to be: + +.. math:: + P\left( k_{1},k_{3},\omega \right) = 4\rho_{0}^{2}\frac{k_{1}^{2}}{k_{1}^{2} + + k_{3}^{2}}\int_{0}^{10\frac{\omega}{Mc}}{L_{2}\overline{u_{2}^{2}} + \left( \frac{\partial U_{1}}{\partial x_{2}} \right)^{2} + \phi_{22}\left( k_{1},k_{3},\omega \right)} \\ + \phi_{m}\left( \omega - U_{c}\left( x_{2} \right)k_{1} \right) + e^{\left( - 2\left| \overline{k} \right|x_{2} \right)}dx_{2}. + :label: aa-eq:21 + +In the equation, the indices 1, 2, and 3 refer to the directions +parallel to the airfoil chord, normal to the airfoil chord, and along +span, respectively; :math:`\phi_{22}` is the vertical velocity +fluctuation spectrum; :math:`\phi_{m}` is the moving axis spectrum; and +:math:`U_{c}` is the convection velocity of the eddies along the +trailing edge. Lastly, :math:`L_{2}` is the vertical correlation length, +perpendicular to the chord length, which indicates the vertical +extension of the vortices that convect over the trailing edge. In this +work, :math:`L_{2}` is assumed equal to the mixing length, :math:`L_{m}` +(Moriarty et al. 2005). This decision is partially arbitrary, and +dedicated research should better assess the correct integral length to +be adopted within the TNO model. + +From :math:`P`, the far-field spectrum, :math:`S\left( \omega \right)`, +is computed as: + +.. math:: + S\left( \omega \right) = \frac{d{\overline{D}}_{h}}{4\pi r_{e}^{2}}\int_{0}^{\delta} + {\frac{\omega}{ck_{1}}P\left( k_{1},0,\omega \right)}\text{dk}_{1}. + :label: aa-eq:22 + +The implementation of the TNO model is identical to the one described in +:cite:`aa-MoriartyGuidatiMigliore:2005`. The inputs to the model are generated from the +boundary layer characteristics provided by the user (see :numref:`aa-sec-BLinputs`). + +.. _aa-laminar-vortex: + +Laminar Boundary Layer – Vortex Shedding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Another source of airfoil self-noise noise included in the BPM model is +the noise generated by a feedback loop between vortices being shed at +the trailing edge and instability waves in the laminar boundary layer. +This noise is typically distributed on a narrow band of frequencies and +occurs when the boundary layer of the airfoil remains laminar. This may +occur in the inboard region of smaller wind turbines, where the Reynolds +number can be smaller than 1 million, but hardly occurs in modern rotors +that operate at a Reynolds number one order of magnitude larger. The +formula to estimate the noise spectrum in a one-third-octave +presentation is: + +.. math:: + \text{SPL}_{LBL - VS} = 10\log_{10}{ + \left( \frac{\delta_{p}M^{5}d{\overline{D}}_{h}}{r_{e}^{2}} \right) + + G_{1}\left( \frac{St'}{{St'}_{\text{peak}}} \right) \\ + + G_{2}\left\lbrack \frac{\text{Re}_{c}}{\left( \text{Re}_{c} \right)_{0}} \right\rbrack + + G_{3}\left( \alpha_{*} \right)} + :label: aa-eq:23 + +where :math:`G` represents empirical functions, +:math:`{St'}_{\text{peak}}` is the peak Strouhal number function of +:math:`\text{Re}_{c}`, which is the Reynolds number at chord, +:math:`c_{i}`. The subscript :sub:`0` refers to a reference Reynolds +number that is a function of the angle of attack (Brooks et al. 1989). + +.. _aa-tip-vortex: + +Tip Vortex +~~~~~~~~~~ + +The vortices generated at blade tips are another source of noise of the +BPM model. Although rarely relevant in modern wind turbines, the +possibility to include this noise source is offered. The sound pressure +level is estimated as: + +.. math:: + \text{SPL}_{\text{Tip}} = 10\log_{10}{\left( + \frac{M^{2}M_{\max}^{2}l^{2}{\overline{D}}_{h}}{r_{e}^{2}} \right) + - 30.5\left( \log_{10}{St^{''}} + 0.3 \right)^{2} + 126} + :label: aa-eq:24 + +where :math:`M_{\max}\ = \ M_{\max}\left( \alpha_{\text{tip}} \right)` +is the maximum Mach number, measured near the blade tip within the +separated flow region that is assumed to depend on +:math:`\alpha_{\text{tip}}`, which is the angle of attack at the tip; +:math:`l` is the spanwise extent of the separation zone; and +:math:`St'''` is the Strouhal number based on :math:`l`. For a round +shape of the tip, :math:`l` is estimated as: + +.. math:: + l = c_{i}0.008\alpha_{\text{tip}} + :label: aa-eq:25 + +where :math:`\alpha_{\text{tip}}` is the angle of attack of the tip +region to the incoming flow. For a square tip, the BPM model estimates +:math:`l` based on the quantity, :math:`{\alpha'}_{\text{tip}}`, which +is defined as: + +.. math:: + \left. \ {\alpha^{'}}_{\text{tip}} = \left\lbrack \left( + \frac{\frac{\partial L'}{\partial y}}{\left( + \frac{\partial L'}{\partial y} \right)_{\text{ref}}} + \right)_{y\rightarrow tip} + \right\rbrack \right.\ \alpha_{\text{tip}} + :label: aa-eq:26 + +where :math:`L'` is the lift per unit span along the blade at position +:math:`y`. For :math:`{\alpha'}_{\text{tip}}` between 0 and 2 degrees, +:math:`l` becomes: + +.. math:: + l = c_{i}\left( 0.0230 + 0.0169{\alpha^{'}}_{\text{tip}} \right), + :label: aa-eq:27 + +while for :math:`{\alpha'}_{\text{tip}}` larger than 2 degrees, +:math:`l` is: + +.. math:: + l = c_{i}\left( 0.0378 + 0.0095{\alpha^{'}}_{\text{tip}} \right). + :label: aa-eq:28 + +However, it must be noted that, unfortunately, +:math:`\alpha_{\text{tip}}` is not a reliable output of standard +aeroelastic models and the impossibility to accurately determine +:math:`\alpha_{\text{tip}}` weakens the formulation of the tip vortex +noise. + +.. _aa-TE-vortex: + +Trailing-Edge Bluntness – Vortex Shedding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Lastly, wind turbine blades are often characterized by a finite height of the +trailing edge, which generates noise as a result of vortex shedding. The +frequency and amplitude of this noise source depends on the geometry of the +trailing edge and is typically characterized by a tonal nature. Adopting +flatback and truncated airfoils far outboard along the blade may strengthen this +noise source. When this noise source is activated, the user is asked to provide +the distribution along the blade span of the blunt thickness of the trailing +edge, :math:`h`, and the solid angle between the suction and pressure sides of +the airfoil, :math:`\Psi` (see :numref:`aa-sec-TEgeom`). :math:`h` and +:math:`\Psi` are inputs to the equation: + +.. math:: + \text{SPL}_{TEB - VS} = 10\log_{10}{ + \left( \frac{\delta_{p}^{*}M^{5}d{\overline{D}}_{h}}{r_{e}^{2}} \right) + + G_{4}\left( \frac{h}{\delta_{\text{avg}}^{*}},\Psi \right) \\ + + G_{5}\left( \frac{h}{\delta_{\text{avg}}^{*}},\Psi, + \frac{St''}{{St''}_{\text{peak}}} \right)}. + :label: aa-eq:29 + +In the equation, :math:`\delta_{\text{avg}}^{*}` is the average +displacement thickness for both sides of the airfoil. Note that this +noise source is very sensitive to :math:`h` and :math:`\Psi`, which, +therefore, should be estimated accurately. + +.. _aa-directivity: + +Directivity +~~~~~~~~~~~ + +The position of one or more observers is specified by the user, as described in +:numref:`aa-sec-ObsPos`. The directivity from the BPM model is adopted in this +implementation (:cite:`aa-Brooks:1989`). The directivity term, +:math:`\overline{D}`, corrects the :math:`\text{SPL}` depending on the relative +position of the observer to the emitter. The position is described by the +spanwise directivity angle, :math:`\Phi_{e}`, and by the chordwise directivity +angle, :math:`\Theta_{e}`, which are schematically represented in +:numref:`aa-fig:directivity` and defined as: + +.. math:: + \Phi_{e} = \text{atan}\left( \frac{z_{e}}{y_{e}} \right) + :label: aa-eq:30 +.. math:: + \Theta_{e} = \text{atan}\left( \frac{y_{e} \bullet \cos\left( \Phi_{e} \right) + + z_{e} \bullet \sin\left( \Phi_{e} \right)}{x_{e}} \right) + :label: aa-eq:31 + + +.. figure:: media/NoiseN002.jpeg + :alt: Angles used in the directivity function + :name: aa-fig:directivity + :width: 100.0% + + Angles used in the directivity function (:cite:`aa-Brooks:1989,aa-MoriartyMigliore:2003`) + +The reference axis is located at each blade node and :math:`x_{e}` is aligned +with the chord, :math:`y_{e}` is aligned with the span pointing to the blade +tip, and :math:`z_{e}` is aligned toward the airfoil suction side. Note that in +OpenFAST the local airfoil-oriented reference system is used, and a rotation is +applied. + +Given the angles :math:`\Theta_{e}` and :math:`\Phi_{e}`, at high frequency, +:math:`\overline{D}` takes the expression: + +.. math:: + {\overline{D}}_{h}\left( \Theta_{e},\Phi_{e} \right) = \frac{ + 2\sin^{2}\left( \frac{\Theta_{e}}{2} \right)\sin^{2}\Phi_{e}} + {\left( 1 + M\cos\Theta_{e} \right) + \left( 1 + \left( M - M_{c} \right) + \cos\Theta_{e} \right)^{2}} + :label: aa-eq:32 + +where :math:`M_{c}` represents the Mach number past the trailing edge +and that is here for simplicity assumed equal to 80% of free-stream M. At low +frequency, the equation becomes: + +.. math:: + {\overline{D}}_{l}\left( \Theta_{e},\Phi_{e} \right) = + \frac{\sin^{2}\left. \ \Theta_{e} \right.\ \sin^{2}\Phi_{e}} + {\left( 1 + M\cos\Theta_{e} \right)^{4}}. + :label: aa-eq:33 + +Each model distinguishes a different value between low and high +frequency. For the TI noise model, the shift between low and high +frequency is defined based on :math:`{\overline{k}}_{1}`. For the TBL-TE +noise, the model differences instead shift between below and above +stall, where\ :math:`\ {\overline{D}}_{h}`\ and +:math:`{\overline{D}}_{l}` are used, respectively. + +.. _aa-A-weighting: + +A-Weighting +~~~~~~~~~~~ + +The code offers the possibility to weigh the aeroacoustics outputs by +A-weighting, which is an experimental coefficient that aims to take into +account the sensitivity of human hearing to different frequencies. +The A-weight, :math:`A_{w}`, is computed as: + +.. math:: + A_{w} = \frac{10\log\left( 1.562339\frac{f^{4}} + {\left( f^{2} + {107.65265}^{2} \right) + \left( f^{2} + {737.86223}^{2} \right)} + \right)}{\log 10}\qquad\qquad\\ + + \frac{10\log\left( 2.422881e16\frac{f^{4}} + {\left( f^{2} + {20.598997}^{2} \right)^{2} + \left( f^{2} + {12194.22}^{2} \right)^{2}} \right)} + {\log 10} + :label: aa-eq:34 + +The A-weighting is a function of frequency and is added to the values of +sound pressure levels: + +.. math:: + SPL_{A_{w}} = SPL + A_{w} + :label: aa-eq:35 + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/03-model-verification.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/03-model-verification.rst new file mode 100644 index 000000000..6a3c13712 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/03-model-verification.rst @@ -0,0 +1,230 @@ +.. _AA-model-verification: + + +Model Verification +------------------ + +Reference Wind Turbine +~~~~~~~~~~~~~~~~~~~~~~ + +The noise model of OpenFAST is exercised by simulating the aeroacoustics noise +emissions of the IEA Wind Task 37 land-based reference wind turbine +(:cite:`aa-Bortolotti:2019`). The main characteristics of the reference wind +turbine are presented in :numref:`tab:ref-turb`. + +.. table:: Main Characteristics of the IEA Wind Task 37 Land-Based Reference Wind Turbine + :name: tab:ref-turb + + +------------------+---------------------+------------------+-------------------+ + | **Data** | **Value** | **Data** | **Value** | + +==================+=====================+==================+===================+ + | Wind class | | International | | Rated | 3.37 megawatts | + | | | Electrotechnical | electrical | | + | | | Commision 3A | | power | | + +------------------+---------------------+------------------+-------------------+ + | | Rated | 3.6 megawatts | | Drivetrain & | 93.60% | + | aerodynamic | | | generator | | + | | power | | efficiency | | + +------------------+---------------------+------------------+-------------------+ + | Rotor diameter | 130 meters | Hub height | 110 meters | + +------------------+---------------------+------------------+-------------------+ + | Cut-in wind | 4 | Cut-out wind | 25 | + | speed | meters/second | speed | meters/second | + +------------------+---------------------+------------------+-------------------+ + | Rotor cone | 3 degrees | Nacelle tilt | 5 degrees | + | angle | | angle | | + +------------------+---------------------+------------------+-------------------+ + | Max blade tip | 80 | | Rated | 8.16 | + | speed | meters/second | tip-speed | | + | | | | ratio | | + +------------------+---------------------+------------------+-------------------+ + | | Maximum | 0.481 | Rated rotor | | 11.75 | + | | aerodynamic Cp | | speed | revolutions per | + | | | | | minute | + +------------------+---------------------+------------------+-------------------+ + +The OpenFAST model of the wind turbine is available at +https://github.com/OpenFAST/r-test and is optionally coupled to the +Reference OpenSource Controller. [2]_ + +Code-to-Code Comparison +~~~~~~~~~~~~~~~~~~~~~~~ + +A detailed code-to-code comparison was conducted to verify the implementation of +the noise models linked to OpenFAST with the implementation available at the +Wind Energy Institute of the Technical University of Munich, Germany. The latter +is described in Sucameli (:cite:`aa-Sucameli:2018`) and is implemented in the wind +turbine design framework Cp-Max, which adopts the multibody-based +aeroservoelastic solver Cp-Lambda. + +The comparison is conducted for the main noise sources—turbulent inflow and the +TBL-TE noise—for both the single airfoil profile and full turbine. This helped +resolve a few implementation mistakes and small inconsistencies. The comparison +is performed with a steady wind of 8 meters per second (m/s), no shear, a rated +pitch angle of 1.17 degrees (deg), and a fixed rotor speed of 10.04 revolutions +per minute (rpm). A fixed value of 0.1 is assumed for the incident turbulent +intensity, :math:`I_{1}`. + +:numref:`aa-fig:TI-compare` shows the predictions in terms of SPL for the Amiet +model with the angle-of-attack correction from OpenFAST, the Simplified Guidati +model generated by OpenFAST, and the Amiet model from Cp-Max. + +.. figure:: media/NoiseN003.png + :alt: Code-to-code comparison for the TI models + :name: aa-fig:TI-compare + :width: 100.0% + + Code-to-code comparison for the TI models + + +The two implementations of the turbulent inflow Amiet model return a perfect +match between OpenFAST and Cp-Max. The chosen scenario sees the blade operating +at optimal angles of attack and, therefore, the effect of the angle of attack +correction is negligible. The plots also show the great difference between the +Amiet model and the Simplified Guidati model. It may be useful to keep in mind +that the Simplified Guidati model has, in the past, been corrected with a factor +of +10 dB, which is applied here. + +For the same inflow and rotor conditions, the BPM and TNO TBL-TE noise models +are compared in :numref:`aa-fig:BPM-TNO-compare`. The match is again satisfactory, +although slightly larger differences emerge that are attributed to differences +in the angles of attack between the two aeroelastic solvers and in different +integration schemes in the TNO formulations. + +.. figure:: media/NoiseN004.png + :alt: Code-to-code comparison for the BPM and TNO TBL-TE models + :name: aa-fig:BPM-TNO-compare + :width: 100.0% + + Code-to-code comparison for the BPM and TNO TBL-TE models. The + boundary layer properties are estimated from either the BPM model (BPM + BL) or defined by the user (Ext BL) + + +The last comparison looked at the directivity models and the overall sound +pressure levels at various observer locations. Simulations are run distributing +200 observers in a horizontal square of 500 meters (m) by 500 m (see +:numref:`aa-fig:obs-loc`). The noise is computed from the Amiet and the BPM turbulent boundary layer-trailing edge models. +The code-to-code comparison returns similar predictions +between OpenFAST and Cp-Max. The comparison is shown in :numref:`aa-fig:SPL-obs`. + +The main conclusion of this code-to-code comparison is that, to the best of +authors’ knowledge, the models are now implemented correctly and generate +similar SPL and overall SPL levels for any arbitrary observer. Nonetheless, it +is clear that all of the presented models are imperfect, and improvements could +be made both at the theoretical implementation levels. + +.. figure:: media/NoiseN005.png + :alt: Location and numbering of the observers + :name: aa-fig:obs-loc + :width: 100.0% + + Location and numbering of the observers + +.. figure:: media/NoiseN006.png + :alt: Comparison of overall sound pressure levels for the observers + :name: aa-fig:SPL-obs + :width: 100.0% + + Comparison of overall sound pressure levels for the observers + distributed, as shown in the previous figure + + +.. _aa-sec-ModelUsage: + +Model Usage +~~~~~~~~~~~ + +The aeroacoustics model of OpenFAST has four options for the outputs: + +1. Overall sound pressure level (dB/A-weighted decibels [dBA])—one value + per time step per observer is generated + +2. Total sound pressure level spectra (dB/dBA)—one spectrum per time + step per observer is generated between 10 Hz and 20 kHz + +3. Mechanism-dependent sound pressure level spectra (dB/dBA)—one + spectrum per active noise mechanism per time step per observer is + generated between 10 Hz and 20 kHz. + +4. Overall sound pressure level (dB/A-weighted decibels [dBA])—one value per blade per node per time step per observer is generated + +The overall SPL from the first option can be used to plot directivity maps of the noise. An example, +which was generated using a Python script, [3]_ is shown in +:numref:`aa-fig:SPL-map`. The noise map, which shows the overall SPL averaged over +1 rotor revolution, is generated for a steady wind speed of 8 m/s, a fixed rotor +speed of 10.04 rpm, and a 1.17-deg pitch angle. In a horizontal circle of 500 m +in diameter, 1681 observers are placed at a 2-m height. Only the Simplified +Guidati and the BPM TBL-TE noise models are activated. + +.. figure:: media/NoiseN007.png + :alt: Map of the overall SPL of the reference wind turbine + :name: aa-fig:SPL-map + :width: 100.0% + + Map of the overall SPL of the reference wind turbine at a 2-m height from + Simplified Guidati and BPM TBL-TE noise models. The wind turbine is located + at x=0, y=0. A steady wind of 8 m/s blows from left (-x) to right (+x). + +The second output can be used to generate SPL spectra. These spectra can be +computed for various observers and optionally A-weighted to account for human +hearing. :numref:`aa-fig:A-SPL` shows the total SPL spectra computed for the same +rotor conditions of the previous example. The A-weight greatly reduces the curve +at frequency below 1,000 Hz while slightly increasing those between 1 kHz and 8 +kHz. + +.. figure:: media/NoiseN008.png + :alt: Comparison between absolute and A-weighted SPL + :name: aa-fig:A-SPL + :width: 100.0% + + Comparison between absolute and A-weighted SPL + +The third output distinguishes the SPL spectrum per mechanism. +:numref:`aa-fig:SPL-spectra` shows the various SPL spectra estimated by each noise +model for the same rotor conditions reported earlier. The total spectrum is +visibly dominated by the turbulent inflow, TBL-TE, and trailing-edge bluntness +noise mechanisms. Notably, the latter is extremely sensitive to its inputs, +:math:`\Psi` and :math:`h`. The reference wind turbine is a purely numerical +model, and these quantities have been arbitrarily set. Users should pay +attention to these inputs when calling the trailing-edge bluntness model. +Consistent with literature, the laminar boundary layer-vortex shedding and tip +vortex noise mechanisms have negative dB values and are, therefore, not visible. +Notably, these spectra are not A-weighted, but users can activate the flag and +obtain A-weighted spectra. + +.. figure:: media/NoiseN009.png + :alt: Nonweighted SPL spectra of the various noise mechanisms + :name: aa-fig:SPL-spectra + :width: 100.0% + + Nonweighted SPL spectra of the various noise mechanisms + +Finally, the fourth output can be used to visualize the noise emission across the rotor. +:numref:`aa-fig:rotor-map` shows the noise generation of the rotor as seen from an observer located 175 meters +downwind at a height of 2 meters. The map is generated by plotting the overall SPL generated +by one blade during one rotor revolution. The plot shows that higher noise is observed +when the blade is descending (the rotor from behind is seen rotating counterclockwise). +This effect, which matches the results shown in :cite:`aa-MoriartyMigliore:2003`, +is explained by the asymmetry of :eq:`aa-eq:31`. Noise is indeed higher when the observer +faces the leading edge of an airfoil (high :math:`\Theta_e`), than when it faces the +trailing edge (low :math:`\Theta_e`). + +.. figure:: media/NoiseN012.png + :alt: Map of the overall SPL of the rotor of the reference wind turbine from Simplified Guidati and BPM TBL-TE noise models. The observer is located 175 meters downwind at a height of 2 meters. + :name: aa-fig:rotor-map + :width: 100.0% + + Map of the overall SPL of the rotor of the reference wind turbine + from Simplified Guidati and BPM TBL-TE noise models. The observer + is located 175 meters downwind at a height of 2 meters. + + + +.. [2] + https://github.com/NREL/ROSCO + +.. [3] + https://github.com/OpenFAST/python-toolbox + + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/04-conclusions.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/04-conclusions.rst new file mode 100644 index 000000000..ba061e8e3 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/04-conclusions.rst @@ -0,0 +1,22 @@ +.. _AA-conclusions: + +Conclusions +----------- + +This document describes a set of frequency-based aeroacoustics models coupled to +the open-source aeroservoelastic solver OpenFAST. The goal of these models is to +predict the aeroacoustics emissions of wind turbine rotors. The document shows a +code-to-code comparison between the models coupled to OpenFAST and the models +implemented at the Technical University of Munich and coupled to the +aeroservoelastic solver Cp-Lambda. The comparison is performed simulating the +aeroacoustics emissions of the IEA Wind Task 37 land-based reference wind +turbine. The results show a good agreement between the two implementations. The +same turbine model is later used to exercise the aeroacoustics model showcasing +its capabilities. Finally, the appendices describe the entries of the input +files of OpenFAST to run the aeroacoustics analysis. + +Future work will focus on the validation of the aeroacoustics models. +In parallel, propagation models will be investigated and implemented. +Finally, attention will be dedicated to infrasound noise and to the +time-domain models that can simulate it. + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/App-usage.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/App-usage.rst new file mode 100644 index 000000000..fb36ee7c2 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/App-usage.rst @@ -0,0 +1,301 @@ +.. _AA-usage: + +Using the Aeroacoustics Model in AeroDyn +======================================== + +A live version of this documentation is available at +https://openfast.readthedocs.io/. To run the aeroacoustics model, the +flag **CompAA** needs to be set to **True** at line 13 of the AeroDyn15 main +input file in the inputs block **General Options**. When the flag is set to +**True**, the following line must include the name of the file containing +the inputs to the aeroacoustics model, which is discussed in +:numref:`aa-sec-BLinputs`. + + +.. container:: + :name: aa-tab:AD15 + + .. literalinclude:: example/AD15.ipt + :linenos: + :language: none + + +.. _aa-sec-MainInput: + +Main Input File +--------------- + +The aeroacoustics main input file comprises a series of inputs and flags +that should be set appropriately depending on the analysis that should +be run. These are split into the subfields General Options, +Aeroacoustics Models, Observer Input, and Outputs. + +Starting from the General Options, these are: + +- **Echo** – True/False: option to rewrite the input file with the correct + template + +- **DT_AA** – Float: time step of the aeroacoustics computations. Only + multiples of the time step **DTAero** of AeroDyn can be used. If set to + default, the time step DTAero is adopted. + +- **AAStart** – Float: time after which the AeroAcoustics module is run. + +- **BldPrcnt** – Float: percentage value of blade span measured from blade + tip that contributes to the noise emissions; 100% corresponds to the + entire blade from tip to root. + +The field Aeroacoustics Models lists all the flags for the actual noise +models: + +- **TIMod** – Integer 0/1/2: flag to set the turbulent inflow noise model; + 0 turns it off, 1 corresponds to the Amiet model discussed in + :numref:`aa-amiet`, and 2 corresponds to the Simplified Guidati model presented in + :numref:`aa-guidati`. + +- **TICalcMeth** – Integer 1/2: flag to set the calculation method for the + incident turbulence intensity. When set to 1, incident turbulence intensity is + defined in a user-defined grid; see :numref:`aa-sec-TIgrid`. When set to + 2, incident turbulence intensity is estimated from the time history of the + incident flow. + +- **TICalcTabFile** – String: name of the text file with the user-defined + turbulence intensity grid; see :numref:`aa-sec-TIgrid`. + +- **SurfRoughness** – Float: value of :math:`z_{0}` used to estimate + :math:`L_{t}` in the Amiet model. + +- **TBLTEMod** – Integer 0/1/2: flag to set the TBL-TE noise model; 0 turns + off the model, 1 uses the Brooks-Pope-Marcolini (BPM) airfoil noise + model (see :numref:`aa-turb-TE-bpm`), and 2 uses the TNO model described in + :numref:`aa-turb-TE-tno`. + +- **BLMod** – Integer 1/2: flag to set the calculation method for the + boundary layer characteristics; 1 uses the simplified equations from + the BPM model, 2 loads the files as described in :numref:`aa-sec-BLinputs`. Only + used if **TBLTEMod** is different than zero. + +- **TripMod** – Integer 0/1/2: if BLMod is set to 1, different + semiempirical parameters are used for a nontripped boundary layer + (**TRipMod=0**), heavily tripped boundary layer (**TRipMod=1**), or lightly + tripped boundary layer (**TRipMod=2**); 2 is typically used for + operational wind turbines, whereas 1 is often used for wind tunnel + airfoil models. + +- **LamMod** – Integer 0/1: flag to activate the laminar boundary layer – + vortex shedding model, presented in :numref:`aa-laminar-vortex`. + +- **TipMod** – Integer 0/1: flag to activate the tip vortex model, + presented in :numref:`aa-tip-vortex`. + +- **RoundedTip** – True/False: if **TipMod=1**, this flag switches between a + round tip (True) and a square tip (False), see :numref:`aa-tip-vortex`. + +- **Alprat** – Float: value of the slope of the lift coefficient curve at + blade tip; see :numref:`aa-tip-vortex`. + +- **BluntMod** – Integer 0/1: flag to activate (**BluntMod=1**) the + trailing-edge bluntness – vortex shedding model, see :numref:`aa-TE-vortex`. If + the flag is set to 1, the trailing-edge geometry must be specified in + the file(s) listed in the field Blade Properties. + +Next, the field Blade Properties lists three file names, often but not +necessarily identical, which contain the distributed properties +describing the detailed geometry of the trailing edge. These are +described in :numref:`aa-sec-TEgeom`. + +The field Observer Locations contains the path to the file where the +number of observers (NrObsLoc) and the respective locations are +specified; see :numref:`aa-sec-ObsPos`. + +Finally, the set Outputs contains a few options for the output data: + +- **AWeighting** – True/False: flag to set whether the sound pressure + levels are reported with (True) or without (False) the A-weighting + correction; see :numref:`aa-sec-ModelUsage`. + +- **NAAOutFile** – Integer 1/2/3: flag to set the desired output file. When + set to 1, a value of overall sound pressure level at every **DT_AA** time + step per observer is printed to file. When set to 2, the first output + is accompanied by a second file where the total sound pressure level + spectrum is printed per time step per observer. When set to + 3, the two first outputs are accompanied by a third file where the + sound pressure level spectrum per noise mechanism is printed per time + step per observer. When set to 4, a fourth file is generated with the + values of overall sound pressure levels per node, per blade, + per observer, and per time step. + +- The following line contains the file name used to store the outputs. + The file name is attached with a 1, 2, 3, and 4 flag based on the + **NAAOutFile** options. + +The file must be closed by an END command. + +.. container:: + :name: aa-tab:AeroAcousticsInput + + .. literalinclude:: example/AeroAcousticsInput.dat + :linenos: + :language: none + + +.. _aa-sec-BLinputs: + +Boundary Layer Inputs +--------------------- + +When the flag **BLMod** is set equal to 2, pretabulated properties of the +boundary layer must be provided and are used by the turbulent boundary +layer – trailing-edge noise models. The file name is to be specified in +the field BL_file among the inputs of the file with the airfoil polar +coefficients. One airfoil file must be specified per aerodynamic +station. + +.. container:: + :name: aa-tab:AFtab + + .. literalinclude:: example/AFtab.dat + :linenos: + :language: none + + +The file, in this example named **AF20_BL.txt**, contains 8 inputs, which +are tabulated for a given number of Reynolds numbers, ReListBL, and a +given number of angles of attack, aoaListBL. The inputs, which are +defined nondimensionally and must be provided for the suction and +pressure side of the airfoil above and below the trailing edge, are: + +- **Ue_Vinf** – flow velocity at the top of the boundary layer + +- **Dstar** – :math:`\delta^{*}`, boundary layer displacement thickness + +- **Delta** – :math:`\delta`, nominal boundary layer thickness + +- **Cf** – friction coefficient. + +In the following example, the file was generated thanks to a Python +script [4]_ that runs the boundary layer solver, XFoil. Notably, XFoil, +by default, does not return :math:`\delta`, but the boundary layer +momentum thickness, :math:`\theta`. :math:`\delta` can be reconstructed +using the expression from :cite:`aa-Drela:1987`: + +.. math:: + \delta = \theta \bullet \left( 3.15 + \frac{1.72}{H - 1} \right) + \delta^{*} + :label: eq:35 + +where :math:`H` is the kinematic shape factor, which is also among the standard +outputs of XFoil. Because it is usually impossible to obtain these values for +the whole ranges of Reynolds numbers and angles of attack, the code is set to +adopt the last available values and print to screen a warning. + + +.. container:: + :name: aa-tab:AF20_BL + + .. literalinclude:: example/AF20_BL.txt + :linenos: + :language: none + + +.. _aa-sec-ObsPos: + +Observer Positions +------------------ + +The number and position of observers is set in the file ObserverLocations, +which is explained in :numref:`aa-sec-MainInput`. The positions must be specified in the OpenFAST global +inertial frame coordinate system, which is located at the tower base and +has the x-axis pointing downwind, the y-axis pointing laterally, and the +z-axis pointing vertically upward. A scheme of the coordinate system for +the observers is shown in :numref:`aa-fig:ObsRefSys`. + +.. figure:: media/NoiseN010.png + :alt: Reference system for the observers + :name: aa-fig:ObsRefSys + :align: center + :width: 40.0% + + Reference system for the observers + +The International Energy Agency Wind Task 37 land-based reference wind +turbine, which is shown in :numref:`tab:ref-turb`, has a hub height of 110 meters and a +rotor radius of 65 meters, and has the International Electrotechnical +Commission 61400-11 standards compliant observer located at: + +x = 175 [m] + +y = 0 [m] + +z = 0 [m]. + +An example of a file listing four observers located at a 2-meter height +is shown here: + +.. container:: + :name: aa-tab:observer + + .. literalinclude:: example/Observer.txt + :linenos: + :language: none + + +.. _aa-sec-TIgrid: + +Turbulence Grid +--------------- + +When the flag **TICalcMeth** is set equal to 1, the grid of incident +turbulent intensity :math:`I_{1}` must be defined by the user. This is +done by creating a file called **TIGrid_In.txt**, which mimics a TurbSim +output file and contains a grid of turbulence intensity, which is +defined as a fraction value. The file defines a grid centered at hub +height and oriented with the OpenFAST global inertial frame coordinate +system; see :numref:`aa-fig:ObsRefSys`. A user-defined number of lateral and vertical +points equally spaced by a user-defined number of meters must be +specified. An example file for a 160 (lateral) by 180 (vertical) meters +grid looks like the following: + + +.. container:: + :name: aa-tab:TIgrid + + .. literalinclude:: example/TIGrid.txt + :linenos: + :language: none + + +.. _aa-sec-TEgeom: + +Trailing-Edge Geometry +---------------------- + +When the flag **BluntMod** is set to 1, the detailed geometry of the +trailing edge must be defined along the span. Two inputs must be +provided, namely the angle, :math:`\Psi,` between the suction and +pressure sides of the profile, right before the trailing-edge point, and +the height, :math:`h`, of the trailing edge. :math:`\Psi` must be +defined in degrees, while :math:`h` is in meters. Note that the BPM +trailing-edge bluntness model is very sensitive to these two parameters, +which, however, are often not easy to determine for real blades. +:numref:`aa-fig:GeomParamTE` shows the two inputs. + +.. figure:: media/NoiseN011.png + :alt: Geometric parameters of the trailing-edge bluntness + :name: aa-fig:GeomParamTE + :width: 100.0% + + Geometric parameters :math:`\mathbf{\Psi}` and + :math:`\mathbf{h}` of the trailing-edge bluntness + +The two distributions must be defined with the same spanwise resolution +of the AeroDyn15 blade file, such as: + +.. container:: + :name: aa-tab:BladeProp + + .. literalinclude:: example/BladeProp.dat + :linenos: + :language: none + +.. [4] + https://github.com/OpenFAST/python-toolbox diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/acronyms.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/acronyms.rst new file mode 100644 index 000000000..d444c4053 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/acronyms.rst @@ -0,0 +1,49 @@ +.. _AA-acronyms: + +List of Acronyms +---------------- + ++-----------+--------------------------------------------------------------+ ++ BPM + Brooks-Pope-Marcolini airfoil noise model + ++-----------+--------------------------------------------------------------+ ++ dB + decibels + ++-----------+--------------------------------------------------------------+ ++ dBA + A-weighted decibels + ++-----------+--------------------------------------------------------------+ ++ deg + degrees + ++-----------+--------------------------------------------------------------+ ++ Hz + hertz + ++-----------+--------------------------------------------------------------+ ++ IEA + International Energy Agency + ++-----------+--------------------------------------------------------------+ ++ kg + kilograms + ++-----------+--------------------------------------------------------------+ ++ kHz + kilohertz + ++-----------+--------------------------------------------------------------+ ++ LFC + low-frequency correction + ++-----------+--------------------------------------------------------------+ ++ m + meters + ++-----------+--------------------------------------------------------------+ ++ N + newtons + ++-----------+--------------------------------------------------------------+ ++ NREL + National Renewable Energy Laboratory + ++-----------+--------------------------------------------------------------+ ++ rad + radians + ++-----------+--------------------------------------------------------------+ ++ s + seconds + ++-----------+--------------------------------------------------------------+ ++ SPL + sound pressure level + ++-----------+--------------------------------------------------------------+ ++ TBL + turbulent boundary layer + ++-----------+--------------------------------------------------------------+ ++ TBL-TE + turbulent boundary layer – trailing edge + ++-----------+--------------------------------------------------------------+ ++ TNO + a Netherlands organization for applied scientific research + ++-----------+--------------------------------------------------------------+ ++ TE + trailing edge + ++-----------+--------------------------------------------------------------+ ++ TI + turbulent inflow + ++-----------+--------------------------------------------------------------+ ++ TUM + Technical University of Munich + ++-----------+--------------------------------------------------------------+ + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AD15.ipt b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AD15.ipt new file mode 100644 index 000000000..26408a087 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AD15.ipt @@ -0,0 +1,18 @@ +------- AERODYN v15.03.\* INPUT FILE ------------------------------------------------ +IEA Wind Task 37 land-based reference wind turbine +====== General Options =================================================== +False Echo - Echo the input to "<rootname>.AD.ech"? (flag) +"default" DT_AA - Time interval for aerodynamic calculations {or "default"} (s) +1 WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT} +2 AFAeroMod - Type of blade airfoil aerodynamics model (switch +0 TwrPotent - Type tower influence on wind around the tower (switch) +False TwrShadow - Calculate tower influence on wind (flag) +False TwrAero - Calculate tower aerodynamic loads? (flag) +False FrozenWake - Assume frozen wake during linearization? (flag +False CavitCheck - Perform cavitation check? (flag) +True CompAA - Flag to compute AeroAcoustics calculation +"AeroAcousticsInput.dat" AA_InputFile +====== Environmental Conditions ========================================== +1.225. AirDens - Air density (kg/m^3) + +File continues... diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AF20_BL.txt b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AF20_BL.txt new file mode 100644 index 000000000..9db17a335 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AF20_BL.txt @@ -0,0 +1,136 @@ +! Boundary layer characteristics at the trailing edge for the airfoil coordinates of /Users/pbortolo/work/2_openfast/noise/verifyAA/OpenFAST_IEA_LB_RWT/Airfoils/AF20_Coords.txt +! Legend: aoa - angle of attack (deg), Re - Reynolds number (-, millions), PS - pressure side, SS - suction side, Ue_Vinf - edge velocity (-), Dstar - displacement thickness (-), Delta - nominal boundary layer thickness (-) Cf - friction coefficient (-) +4 ReListBL - Number of Reynolds numbers (it corresponds to the number of tables) +30 aoaListBL - Number of angles of attack (it corresponds to the number of rows in each table) +0.50 - Re +aoa Ue_Vinf_SS Ue_Vinf_PS Dstar_SS Dstar_PS Delta_SS Delta_PS Cf_SS Cf_PS +(deg) (-) (-) (-) (-) (-) (-) (-) (-) +-5.00000 8.39390e-01 -8.37360e-01 7.43700e-03 1.07730e-02 2.75094e-02 5.15849e-02 1.13200e-03 1.58200e-03 +-3.96552 8.42050e-01 -8.40230e-01 8.26600e-03 9.29500e-03 2.98650e-02 4.87153e-02 1.04400e-03 1.85700e-03 +-2.93103 8.45320e-01 -8.43690e-01 9.08800e-03 8.10000e-03 3.19790e-02 4.70045e-02 9.58000e-04 2.16500e-03 +-1.89655 8.48230e-01 -8.46710e-01 9.97400e-03 7.33700e-03 3.44024e-02 4.50456e-02 8.90000e-04 2.35800e-03 +-0.86207 8.51550e-01 -8.50140e-01 1.09130e-02 6.54100e-03 3.68822e-02 4.30884e-02 8.26000e-04 2.59900e-03 + 0.17241 8.55000e-01 -8.53670e-01 1.18900e-02 5.92900e-03 3.96199e-02 4.27416e-02 7.79000e-04 2.87100e-03 + 1.20690 8.63820e-01 -1.04207e+00 1.22130e-02 9.89500e-03 4.18890e-02 1.68156e-02 8.18000e-04 -1.77000e-04 + 2.24138 8.61500e-01 -8.60210e-01 1.40420e-02 4.88700e-03 4.51813e-02 3.93105e-02 6.78000e-04 3.28700e-03 + 3.27586 8.64430e-01 -8.63080e-01 1.52900e-02 4.57300e-03 4.85938e-02 3.82233e-02 6.39000e-04 3.44000e-03 + 4.31034 8.67960e-01 -8.66600e-01 1.65660e-02 4.09100e-03 5.17768e-02 3.63749e-02 5.96000e-04 3.69000e-03 + 5.34483 8.72300e-01 -8.70850e-01 1.81000e-02 3.81700e-03 5.43379e-02 3.52278e-02 5.09000e-04 3.86300e-03 + 6.37931 8.77930e-01 -8.76410e-01 1.98500e-02 3.39700e-03 5.69109e-02 3.31481e-02 4.18000e-04 4.13900e-03 + 7.41379 8.86840e-01 -8.85140e-01 2.22250e-02 3.15000e-03 5.81316e-02 3.19040e-02 2.64000e-04 4.36900e-03 + 8.44828 9.00620e-01 -8.98660e-01 2.54290e-02 2.75900e-03 5.91946e-02 2.95298e-02 1.01000e-04 4.76300e-03 + 9.48276 9.20300e-01 -9.17700e-01 2.99830e-02 2.48300e-03 6.07767e-02 2.75551e-02 5.00000e-06 5.16000e-03 +10.51724 9.48080e-01 -9.44440e-01 3.80160e-02 2.13200e-03 6.65531e-02 2.48447e-02 -1.60000e-05 5.76800e-03 +11.55172 9.89560e-01 -9.84930e-01 5.83630e-02 1.85700e-03 8.76076e-02 2.18890e-02 -1.50000e-05 6.49000e-03 +12.58621 1.02883e+00 -1.02353e+00 8.80990e-02 1.66700e-03 1.21588e-01 2.00072e-02 -1.30000e-05 7.20200e-03 +13.62069 1.05789e+00 -1.05226e+00 1.18914e-01 1.51000e-03 1.57264e-01 1.78004e-02 -1.10000e-05 7.74800e-03 +14.65517 1.07975e+00 -1.07394e+00 1.48726e-01 1.41900e-03 1.91423e-01 1.65710e-02 -1.00000e-05 8.15600e-03 +15.68966 1.09657e+00 -1.09067e+00 1.76430e-01 1.34400e-03 2.22657e-01 1.56180e-02 -9.00000e-06 8.50600e-03 +16.72414 1.11040e+00 -1.10441e+00 2.02883e-01 1.26100e-03 2.52158e-01 1.43276e-02 -9.00000e-06 8.80900e-03 +17.75862 1.12290e+00 -1.11682e+00 2.29606e-01 1.20600e-03 2.81695e-01 1.35432e-02 -8.00000e-06 9.07600e-03 +18.79310 1.13461e+00 -1.12844e+00 2.55478e-01 1.15500e-03 3.10143e-01 1.28744e-02 -8.00000e-06 9.34700e-03 +19.82759 1.14605e+00 -1.13974e+00 2.80923e-01 1.08200e-03 3.37970e-01 1.16844e-02 -8.00000e-06 9.61200e-03 +20.86207 1.15722e+00 -1.15073e+00 3.05117e-01 1.03800e-03 3.64240e-01 1.10866e-02 -7.00000e-06 9.87000e-03 +21.89655 1.16808e+00 -1.16138e+00 3.27770e-01 9.81000e-04 3.88826e-01 1.02373e-02 -7.00000e-06 1.01370e-02 +22.93103 1.17845e+00 -1.17148e+00 3.48909e-01 9.33000e-04 4.11299e-01 9.52780e-03 -7.00000e-06 1.03870e-02 +23.96552 1.18930e+00 -1.18205e+00 3.70277e-01 8.93000e-04 4.34300e-01 9.01762e-03 -7.00000e-06 1.06550e-02 +25.00000 1.19987e+00 -1.19227e+00 3.90503e-01 8.36000e-04 4.55921e-01 8.12755e-03 -7.00000e-06 1.09080e-02 +1.00 - Re +aoa Ue_Vinf_SS Ue_Vinf_PS Dstar_SS Dstar_PS Delta_SS Delta_PS Cf_SS Cf_PS +(deg) (-) (-) (-) (-) (-) (-) (-) (-) +-5.00000 8.34300e-01 -8.32480e-01 6.49600e-03 7.74600e-03 2.28566e-02 3.97467e-02 8.39000e-04 1.54900e-03 +-3.96552 8.37330e-01 -8.35790e-01 7.10100e-03 6.55800e-03 2.45059e-02 3.67266e-02 7.84000e-04 1.80000e-03 +-2.93103 8.40670e-01 -8.39370e-01 7.75600e-03 5.65600e-03 2.62162e-02 3.42658e-02 7.27000e-04 2.03700e-03 +-1.89655 8.44170e-01 -8.43070e-01 8.45300e-03 4.96000e-03 2.79616e-02 3.22259e-02 6.72000e-04 2.25700e-03 +-0.86207 8.47840e-01 -8.46890e-01 9.21600e-03 4.45100e-03 2.98142e-02 3.07238e-02 6.18000e-04 2.45400e-03 + 0.17241 8.51730e-01 -8.50900e-01 1.00790e-02 3.95100e-03 3.18738e-02 2.89503e-02 5.65000e-04 2.66300e-03 + 1.20690 8.55470e-01 -8.54730e-01 1.09340e-02 3.54400e-03 3.37289e-02 2.74209e-02 5.12000e-04 2.86100e-03 + 2.24138 8.59040e-01 -8.58320e-01 1.18130e-02 3.25200e-03 3.55603e-02 2.64490e-02 4.62000e-04 3.03800e-03 + 3.27586 8.63480e-01 -8.62770e-01 1.29500e-02 2.91700e-03 3.78947e-02 2.47691e-02 4.08000e-04 3.23200e-03 + 4.31034 8.67590e-01 -8.66830e-01 1.40320e-02 2.69800e-03 3.97441e-02 2.39342e-02 3.50000e-04 3.40400e-03 + 5.34483 8.72380e-01 -8.71540e-01 1.53110e-02 2.43000e-03 4.18407e-02 2.22446e-02 2.92000e-04 3.59200e-03 + 6.37931 8.78360e-01 -8.77360e-01 1.68420e-02 2.23600e-03 4.38267e-02 2.12352e-02 2.20000e-04 3.78300e-03 + 7.41379 8.86030e-01 -8.84810e-01 1.87390e-02 2.00100e-03 4.60113e-02 1.94428e-02 1.44000e-04 4.00100e-03 + 8.44828 8.96310e-01 -8.94850e-01 2.13480e-02 1.83100e-03 4.88127e-02 1.83696e-02 5.90000e-05 4.24200e-03 + 9.48276 9.25990e-01 -9.23230e-01 2.81520e-02 1.56900e-03 5.51012e-02 1.62260e-02 -1.00000e-06 4.73700e-03 +10.51724 9.66170e-01 -9.62320e-01 4.28900e-02 1.36700e-03 7.03103e-02 1.45187e-02 -9.00000e-06 5.34800e-03 +11.55172 1.00255e+00 -9.97860e-01 6.33540e-02 1.21700e-03 9.26255e-02 1.29836e-02 -7.00000e-06 5.90200e-03 +12.58621 1.03100e+00 -1.02578e+00 8.62500e-02 1.10600e-03 1.18923e-01 1.16999e-02 -6.00000e-06 6.34900e-03 +13.62069 1.05406e+00 -1.04857e+00 1.10634e-01 1.04100e-03 1.47132e-01 1.09721e-02 -6.00000e-06 6.70700e-03 +14.65517 1.07334e+00 -1.06769e+00 1.35720e-01 9.66000e-04 1.76016e-01 9.96935e-03 -5.00000e-06 7.01900e-03 +15.68966 1.08881e+00 -1.08308e+00 1.60129e-01 9.17000e-04 2.03832e-01 9.33244e-03 -5.00000e-06 7.27400e-03 +16.72414 1.10158e+00 -1.09579e+00 1.83765e-01 8.82000e-04 2.30423e-01 8.89329e-03 -5.00000e-06 7.49000e-03 +17.75862 1.11342e+00 -1.10758e+00 2.08205e-01 8.32000e-04 2.57695e-01 8.20477e-03 -4.00000e-06 7.69800e-03 +18.79310 1.12407e+00 -1.11817e+00 2.32504e-01 8.01000e-04 2.84583e-01 7.81234e-03 -4.00000e-06 7.88600e-03 +19.82759 1.13501e+00 -1.12904e+00 2.57953e-01 7.76000e-04 3.12682e-01 7.52201e-03 -4.00000e-06 8.07500e-03 +20.86207 1.14614e+00 -1.14008e+00 2.83630e-01 7.33000e-04 3.41005e-01 6.90325e-03 -4.00000e-06 8.27100e-03 +21.89655 1.15868e+00 -1.15248e+00 3.10888e-01 7.07000e-04 3.71055e-01 6.60979e-03 -4.00000e-06 8.48600e-03 +22.93103 1.17050e+00 -1.16410e+00 3.35623e-01 6.81000e-04 3.98279e-01 6.28286e-03 -3.00000e-06 8.69100e-03 +23.96552 1.18348e+00 -1.17683e+00 3.61314e-01 6.45000e-04 4.26528e-01 5.81057e-03 -3.00000e-06 8.91700e-03 +25.00000 1.19753e+00 -1.19058e+00 3.87323e-01 6.21000e-04 4.54991e-01 5.52432e-03 -3.00000e-06 9.15800e-03 +5.00 - Re +aoa Ue_Vinf_SS Ue_Vinf_PS Dstar_SS Dstar_PS Delta_SS Delta_PS Cf_SS Cf_PS +(deg) (-) (-) (-) (-) (-) (-) (-) (-) +-5.00000 8.23420e-01 -8.21880e-01 4.67200e-03 4.76700e-03 1.77334e-02 2.96859e-02 6.92000e-04 1.41000e-03 +-3.96552 8.25550e-01 -8.24400e-01 5.04400e-03 4.14000e-03 1.88321e-02 2.75480e-02 6.57000e-04 1.55000e-03 +-2.93103 8.27930e-01 -8.27220e-01 5.46200e-03 3.53900e-03 2.00407e-02 2.52464e-02 6.21000e-04 1.70500e-03 +-1.89655 8.30490e-01 -8.30120e-01 5.91700e-03 3.10400e-03 2.13254e-02 2.34284e-02 5.86000e-04 1.84000e-03 +-0.86207 8.33100e-01 -8.33000e-01 6.40000e-03 2.77600e-03 2.26264e-02 2.19701e-02 5.50000e-04 1.95800e-03 + 0.17241 8.35520e-01 -8.35690e-01 6.86100e-03 2.45300e-03 2.37731e-02 2.03359e-02 5.15000e-04 2.08300e-03 + 1.20690 8.38270e-01 -8.38660e-01 7.40600e-03 2.17500e-03 2.51176e-02 1.87906e-02 4.79000e-04 2.20700e-03 + 2.24138 8.41350e-01 -8.41880e-01 8.04900e-03 1.95800e-03 2.66635e-02 1.75032e-02 4.40000e-04 2.31900e-03 + 3.27586 8.43950e-01 -8.44520e-01 8.65200e-03 1.80300e-03 2.79650e-02 1.65339e-02 4.03000e-04 2.40900e-03 + 4.31034 8.48180e-01 -8.48810e-01 9.58300e-03 1.61000e-03 3.00737e-02 1.51804e-02 3.59000e-04 2.53200e-03 + 5.34483 8.53570e-01 -8.54090e-01 1.08300e-02 1.48600e-03 3.27612e-02 1.43249e-02 3.08000e-04 2.63700e-03 + 6.37931 8.72880e-01 -8.73060e-01 1.51570e-02 1.28200e-03 4.16833e-02 1.28096e-02 1.92000e-04 2.88700e-03 + 7.41379 8.92130e-01 -8.91760e-01 1.98220e-02 1.14700e-03 4.87740e-02 1.17767e-02 8.30000e-05 3.11600e-03 + 8.44828 9.17360e-01 -9.16020e-01 2.50640e-02 9.92000e-04 5.31945e-02 1.04181e-02 2.00000e-06 3.41900e-03 + 9.48276 9.42910e-01 -9.40410e-01 3.17040e-02 8.85000e-04 5.85499e-02 9.42477e-03 -1.00000e-06 3.70700e-03 +10.51724 9.64800e-01 -9.61630e-01 4.02300e-02 7.96000e-04 6.64893e-02 8.47323e-03 -2.00000e-06 3.96100e-03 +11.55172 9.86420e-01 -9.82570e-01 5.11880e-02 7.23000e-04 7.76623e-02 7.65452e-03 -2.00000e-06 4.20700e-03 +12.58621 1.00657e+00 -1.00210e+00 6.43270e-02 6.71000e-04 9.20001e-02 7.06023e-03 -2.00000e-06 4.43100e-03 +13.62069 1.02475e+00 -1.01984e+00 7.93340e-02 6.16000e-04 1.09051e-01 6.35528e-03 -1.00000e-06 4.64000e-03 +14.65517 1.04370e+00 -1.03850e+00 9.84840e-02 5.79000e-04 1.31195e-01 5.91001e-03 -1.00000e-06 4.84500e-03 +15.68966 1.06004e+00 -1.05467e+00 1.18503e-01 5.43000e-04 1.54410e-01 5.44594e-03 -1.00000e-06 5.02500e-03 +16.72414 1.07448e+00 -1.06905e+00 1.39604e-01 5.14000e-04 1.78759e-01 5.05912e-03 -1.00000e-06 5.18500e-03 +17.75862 1.08720e+00 -1.08175e+00 1.61656e-01 4.93000e-04 2.03997e-01 4.79726e-03 -1.00000e-06 5.32500e-03 +18.79310 1.09867e+00 -1.09324e+00 1.84226e-01 4.68000e-04 2.29525e-01 4.45243e-03 -1.00000e-06 5.45500e-03 +19.82759 1.10970e+00 -1.10430e+00 2.08500e-01 4.51000e-04 2.56774e-01 4.24858e-03 -1.00000e-06 5.57800e-03 +20.86207 1.11936e+00 -1.11397e+00 2.32097e-01 4.34000e-04 2.83065e-01 4.03443e-03 -1.00000e-06 5.69000e-03 +21.89655 1.12815e+00 -1.12274e+00 2.54679e-01 4.14000e-04 3.07965e-01 3.77358e-03 -1.00000e-06 5.79400e-03 +22.93103 1.13774e+00 -1.13227e+00 2.78750e-01 4.00000e-04 3.34530e-01 3.60784e-03 -1.00000e-06 5.90600e-03 +23.96552 1.14721e+00 -1.14164e+00 3.02299e-01 3.84000e-04 3.60352e-01 3.41109e-03 -1.00000e-06 6.01800e-03 +25.00000 1.15816e+00 -1.15244e+00 3.27151e-01 3.68000e-04 3.87710e-01 3.21949e-03 -1.00000e-06 6.14600e-03 +10.00 - Re +aoa Ue_Vinf_SS Ue_Vinf_PS Dstar_SS Dstar_PS Delta_SS Delta_PS Cf_SS Cf_PS +(deg) (-) (-) (-) (-) (-) (-) (-) (-) +-5.00000 8.19760e-01 -8.18060e-01 4.17800e-03 4.54900e-03 1.65706e-02 2.88150e-02 6.56000e-04 1.23100e-03 +-3.96552 8.21540e-01 -8.20450e-01 4.52500e-03 3.74000e-03 1.76308e-02 2.59028e-02 6.23000e-04 1.39100e-03 +-2.93103 8.23580e-01 -8.22970e-01 4.89400e-03 3.21700e-03 1.87333e-02 2.38284e-02 5.91000e-04 1.51700e-03 +-1.89655 8.25560e-01 -8.25320e-01 5.25400e-03 2.85300e-03 1.97567e-02 2.22669e-02 5.60000e-04 1.62100e-03 +-0.86207 8.27870e-01 -8.28060e-01 5.67900e-03 2.46600e-03 2.09522e-02 2.03860e-02 5.28000e-04 1.74400e-03 + 0.17241 8.30330e-01 -8.30840e-01 6.14400e-03 2.18100e-03 2.22219e-02 1.88758e-02 4.96000e-04 1.84900e-03 + 1.20690 8.32880e-01 -8.33650e-01 6.64800e-03 1.94100e-03 2.35312e-02 1.74735e-02 4.63000e-04 1.94900e-03 + 2.24138 8.35130e-01 -8.36090e-01 7.13000e-03 1.75100e-03 2.46910e-02 1.62700e-02 4.31000e-04 2.03800e-03 + 3.27586 8.39970e-01 -8.41060e-01 8.09900e-03 1.56800e-03 2.72181e-02 1.50508e-02 3.88000e-04 2.14300e-03 + 4.31034 8.50470e-01 -8.51560e-01 1.01990e-02 1.37300e-03 3.25448e-02 1.36378e-02 3.18000e-04 2.29400e-03 + 5.34483 8.64450e-01 -8.65280e-01 1.32660e-02 1.23700e-03 3.92329e-02 1.26866e-02 2.31000e-04 2.45100e-03 + 6.37931 8.78610e-01 -8.79110e-01 1.65810e-02 1.08900e-03 4.49765e-02 1.14397e-02 1.47000e-04 2.62200e-03 + 7.41379 8.91030e-01 -8.91080e-01 1.96290e-02 9.93000e-04 4.89936e-02 1.06282e-02 7.60000e-05 2.76500e-03 + 8.44828 9.08900e-01 -9.08620e-01 2.35230e-02 8.71000e-04 5.22284e-02 9.45732e-03 2.00000e-06 2.96800e-03 + 9.48276 9.32700e-01 -9.30700e-01 2.84210e-02 7.79000e-04 5.52443e-02 8.61055e-03 -0.00000e+00 3.20000e-03 +10.51724 9.51380e-01 -9.48770e-01 3.46600e-02 6.96000e-04 6.05165e-02 7.64709e-03 -1.00000e-06 3.39700e-03 +11.55172 9.71740e-01 -9.68450e-01 4.35850e-02 6.37000e-04 6.90670e-02 6.98615e-03 -1.00000e-06 3.59500e-03 +12.58621 9.91260e-01 -9.87290e-01 5.44080e-02 5.84000e-04 8.03205e-02 6.33577e-03 -1.00000e-06 3.78700e-03 +13.62069 1.00996e+00 -1.00542e+00 6.74960e-02 5.36000e-04 9.47613e-02 5.73102e-03 -1.00000e-06 3.97000e-03 +14.65517 1.02771e+00 -1.02275e+00 8.31660e-02 5.06000e-04 1.12645e-01 5.35979e-03 -1.00000e-06 4.13700e-03 +15.68966 1.04427e+00 -1.03905e+00 1.00836e-01 4.71000e-04 1.33082e-01 4.88548e-03 -1.00000e-06 4.29600e-03 +16.72414 1.06019e+00 -1.05485e+00 1.21136e-01 4.45000e-04 1.56673e-01 4.55077e-03 -1.00000e-06 4.44600e-03 +17.75862 1.07407e+00 -1.06868e+00 1.42220e-01 4.22000e-04 1.81035e-01 4.24533e-03 -1.00000e-06 4.57900e-03 +18.79310 1.08623e+00 -1.08087e+00 1.64037e-01 4.01000e-04 2.06006e-01 3.94306e-03 -0.00000e+00 4.69600e-03 +19.82759 1.09748e+00 -1.09215e+00 1.87080e-01 3.86000e-04 2.32142e-01 3.76503e-03 -0.00000e+00 4.80500e-03 +20.86207 1.10794e+00 -1.10267e+00 2.10804e-01 3.67000e-04 2.58816e-01 3.50553e-03 -0.00000e+00 4.90800e-03 +21.89655 1.11776e+00 -1.11253e+00 2.35256e-01 3.54000e-04 2.86067e-01 3.34709e-03 -0.00000e+00 5.00500e-03 +22.93103 1.12664e+00 -1.12138e+00 2.58366e-01 3.43000e-04 3.11568e-01 3.20986e-03 -0.00000e+00 5.09600e-03 +23.96552 1.13635e+00 -1.13106e+00 2.83067e-01 3.28000e-04 3.38816e-01 3.02058e-03 -0.00000e+00 5.19400e-03 +25.00000 1.14573e+00 -1.14034e+00 3.06604e-01 3.16000e-04 3.64612e-01 2.86692e-03 -0.00000e+00 5.29100e-03 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AFtab.dat b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AFtab.dat new file mode 100644 index 000000000..92aa5948e --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AFtab.dat @@ -0,0 +1,12 @@ +! ------------ AirfoilInfo v1.01.x Input File ---------------------------------- +! AeroElasticSE FAST driver +! +! +! ------------------------------------------------------------------------------ +DEFAULT InterpOrd ! Interpolation order to use for quasi-steady table lookup {1=linear; 3=cubic spline; "default"} [default=3] +1 NonDimArea ! The non-dimensional area of the airfoil (area/chord^2) (set to 1.0 if unsure or unneeded) +@"AF20_Coords.txt" NumCoords ! The number of coordinates in the airfoil shape file. Set to zero if coordinates not included. +AF20_BL.txt BL_file ! The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called. +1 NumTabs ! Number of airfoil tables in this file. Each table must have lines for Re and Ctrl. +! ------------------------------------------------------------------------------ +! data for table 1 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AeroAcousticsInput.dat b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AeroAcousticsInput.dat new file mode 100644 index 000000000..f79c9aae0 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/AeroAcousticsInput.dat @@ -0,0 +1,31 @@ +------- AeroAcoustics Module v1.00.* INPUT FILE ------------------------------------------------ +IEA task 37 RWT turbine -- https://github.com/IEAWindTask37/IEA-3.4-130-RWT +====== General Options ============================================================================ +False Echo - Echo the input to "<rootname>.AD.ech"? (flag) +0.1 DT_AA - Time interval for aeroacoustics calculations (s), must be a multiple of DT_Aero from AeroDyn15 (or "default") +0 AAStart - Time after which the AeroAcoustics module is run (s) +70 BldPrcnt - Percentage of the blade span, starting from the tip, that will contribute to the overall noise levels. (float) +====== Aeroacoustic Models ============================================================================ +2 TIMod - Turbulent Inflow noise model {0: none, 1: Amiet 2: Amiet + Simplified Guidati} (switch) +1 TICalcMeth - Method to estimate turbulence intensity incident to the profile {1: given table, 2: computed on the fly} (switch) [Only used if TIMod!=0] +"TIGrid_InVerify.txt" TICalcTabFile - Name of the file containing the table for incident turbulence intensity (-) [Only used if TiCalcMeth == 1] +0.5 SurfRoughness- Surface roughness value used to estimate the turbulent length scale in Amiet model (m) +1 TBLTEMod - Turbulent Boundary Layer-Trailing Edge noise calculation {0: none, 1:BPM, 2: TNO} (switch) +1 BLMod - Calculation method for boundary layer properties, {1: BPM, 2: Pretabulated} (switch) +1 TripMod - Boundary layer trip model {0:no trip, 1: heavy trip, 2: light trip} (switch) [Only used if BLMod=1] +0 LamMod - Laminar boundary layer noise model {0:none, 1: BPM} (switch) +0 TipMod - Tip vortex noise model {0:none, 1: BPM} (switch) +True RoundedTip - Logical indicating rounded tip (flag) [Only used if TipMod=1] +1.0 Alprat - Tip lift curve slope (Default = 1.0) [Only used if TipMod=1] +0 BluntMod - Trailing-edge-bluntness – Vortex-shedding model {0:none, 1: BPM} (switch) +"AABlade1.dat" AABlFile(1) - Name of file containing distributed aerodynamic properties for Blade #1 (-) +"AABlade1.dat" AABlFile(2) - Name of file containing distributed aerodynamic properties for Blade #2 (-) +"AABlade1.dat" AABlFile(3) - Name of file containing distributed aerodynamic properties for Blade #3 (-) +====== Observer Input =================================================================== +"AA_ObserverLocations.dat" ObserverLocations - Name of file containing all observer locations X Y Z (-) +====== Outputs ==================================================================================== +False AWeighting - A-weighting Flag (flag) +3 NrOutFile - Number of Output files. 1 for Time Dependent Overall SPL, 2 for both 1 and Frequency and Time Dependent SPL as well, or 3 for both 1 and 2 and Acoustics mechanism dependent, 4 for 1-3 and the overall sound pressure levels per blade per node per observer +"IEA_LB_RWT-AeroAcoustics_" AAOutFile - No Extension needed the resulting file will have .out Name of file containing +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/BladeProp.dat b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/BladeProp.dat new file mode 100644 index 000000000..12aa4c92b --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/BladeProp.dat @@ -0,0 +1,35 @@ +Example aerodynamic blade input properties +====== Blade Properties ========================================== +30 NumBlNds - Number of blade nodes used in the analysis (-) +TEAngle TEThick +(deg) (m) +10.000000E+00 0.03000E+00 +10.000000E+00 0.02900E+00 +10.000000E+00 0.02800E+00 +10.000000E+00 0.02700E+00 +10.000000E+00 0.02600E+00 +10.000000E+00 0.02500E+00 +10.000000E+00 0.02400E+00 +10.000000E+00 0.02300E+00 +10.000000E+00 0.02200E+00 +10.000000E+00 0.02100E+00 +10.000000E+00 0.02000E+00 +10.000000E+00 0.01900E+00 +10.000000E+00 0.01800E+00 +10.000000E+00 0.01700E+00 +10.000000E+00 0.01600E+00 +10.000000E+00 0.01500E+00 +10.000000E+00 0.01400E+00 +10.000000E+00 0.01300E+00 +10.000000E+00 0.01200E+00 +10.000000E+00 0.01100E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 +10.000000E+00 0.01000E+00 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/Observer.txt b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/Observer.txt new file mode 100644 index 000000000..d8a8b78ce --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/Observer.txt @@ -0,0 +1,6 @@ +4 NrObsLoc - Total Number of observer locations +X Observer location in tower-base coordinate X horizontal (m), Y Observer location in tower-base coordinate Y Lateral (m), Z Observer location in tower-base coordinate Z Vertical (m) +-200 -200 2 +-200 +200 2 ++200 -200 2 ++200 +200 2 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/TIGrid.txt b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/TIGrid.txt new file mode 100644 index 000000000..240382606 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/example/TIGrid.txt @@ -0,0 +1,11 @@ +Total Grid points In Y (lateral), Starts from - radius goes to + radius+ +4 +Total Grid points In Z (vertical), Starts from bottom tip (hub-radius) +3 +Grid spacing In Y (lateral) +40 +Grid spacing In Z (vertical) +60 +0.1200 0.1200 0.1200 0.1200 +0.1100 0.1100 0.1100 0.1100 +0.1000 0.1000 0.1000 0.1000 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/index.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/index.rst new file mode 100644 index 000000000..c6fd838d9 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/index.rst @@ -0,0 +1,43 @@ +.. _AeroAcoustics: + +Aeroacoustics Noise Model of OpenFAST +===================================== + +.. only:: html + + This report describes theory and application of a newly released model + of OpenFAST to simulate the aeroacoustics noise generated by the rotor + of an arbitrary wind turbine. OpenFAST is a fully open-source, publicly + available wind turbine analysis tool actively developed at the National + Renewable Energy Laboratory. The aeroacoustics model, which is also + fully open source and publicly available, is based on work performed + over the past three decades. Frequency-based models for turbulent + inflow; turbulent boundary layer – trailing edge; laminar boundary layer + –vortex shedding; tip vortex; and trailing edge bluntness – vortex + shedding noise mechanisms are included. A simple directivity model is + also included. + + The noise models are exercised simulating the aeroacoustics noise + emissions of the International Energy Agency Wind Task 37 land-based + reference wind turbine. A code-to-code comparison between the + implementation presented here and the implementation available at the + Wind Energy Institute of the Technical University of Munich, Germany, is + also presented. + + The documentation here was derived from NREL Technical Report TP-5000-75731 + by P. Bortolotti et al. (`https://www.nrel.gov/docs/fy20osti/75731.pdf + <https://www.nrel.gov/docs/fy20osti/75731.pdf>`_) + + + +.. toctree:: + :maxdepth: 2 + + acronyms.rst + symbols.rst + 01-introduction.rst + 02-noise-models.rst + 03-model-verification.rst + 04-conclusions.rst + App-usage.rst + refs.rst diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN002.jpeg b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN002.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6f4ae6fb6349543c7d9994d7241807f605a32655 GIT binary patch literal 34634 zcmdSB2S8KH(>ELh1VzLaP%KD?&_tTjA|m}lXbByZ-VqRy8ao;Uq&EfWB@`*4LqrU{ zNLQ)?2^}TWKnUNF+l%+!|MNc2`@G+QoMg}LIhmcEo%zk|Y<55FegYj)S5{L7QSGCm zK2Lof1lnCZsI6`9cFWDv-tFdjG2siKOIOu2sTV=tjw9b%fT%z~+aKS*)zL5lpFtoR z;B{`VeCqdQ>Xp6nfxR<uqS|{R&B47g6=<)-dt|S45UBj|*thqsYkLJ%kch1<P~!}o z_wQYy`sqqae8MkRE&?@FAY<VCa~p}hD?-0s*?Z<DPzHf+0zLi9gL>v$^<P%){-4zC zafbfevq9hb3iNZ|l^<U}a)9O>aP>zn{>UHJy|O!S{;@xMMXDtbXpi^wAZw5t$O_~I zy0G^r22}sdyS<h_oqlue+kM~e|EFV*(xZE=sD2u&6MLm^BTThdd+1x4uJBtKcmccw zDFGj~K_KJj!1YMbNf6cU?_>+43jBd~mq3RVtlcbaK-PDGd#HAYK@UNP=;`SX&>uQ* z;LuTqgA7N(Oot9JflnSk4nBVT<k3TW$4_rR7XEmqVq{=oJj{6H@ZlpT4j(>z;@j!) zi63t{`fnbv`v!EB9_YYLYAO!UzN1vsN2zv40dc0=eMbcasHCOZI{<>e9n`>7p`qPR zM}OcT127SOUr7bpNBwi<5fBv(74<%veYAA@>1nACi2;>IscG1ciP9?Q+&IqRe(&P` z6X7XES2?-By7iV~;vV<A73sJm^uB&xw(^u<PAz`Gb1hQeTIp@tElHLh_=F9y<Y7av z*W`*aZ&doD(&%@6Q>z&mTt9vdVSD>=OlDc*0AXE9#lX%xC^oCSX>fYuC}`h4fLfY8 zn&|e^O6-xqE_#dxpunBuIPJxI;U~UPP_NtlRgBB>v&a1iMLn>Ur}#4W{%-`(@kqSw z0f<Oru~vdh-m;nag@o@@!22r+yF;Ku)O+7~6a)pW=|`w>^K(V0sjG2C=tih<MP)Du zx;P6<Z;E@smdZ)$S~s0E!WfTTSL<zN*YCZ-QgbwYph5mUQm(_(m|%t(+Xanm9pE=9 zK6Usev-nHnZrW6{r7hQSOf~BwcI)Y}^5RCx#v=q-I*Eq+hhODDd^UDa!Ns{&1x3#S zur_%bOP<DZ(UMYIb&W;It37(|+zPci+x#L8m4#JhhK}p5w#$_ZrEYBP)vLFi$*ZRR zD*^YhC8MTK$G(o%StxwjQsdu!zt@KgYdK>CH`nzmp4O_PtKLj_F4ycIYEuuLRe{cd zwNiSr+o|d?#h>i@z2HNO${ljH)uXEjPhTsuJ|SFl9!MoeOR;E1qNZ{za{y|)J~cS| zVK^7Lg7Gy1e<V+5MlE3${1<NC?lGPbqw(lL+rT}EU-N913aS=-$};aNy&AMK9zILT z&mYe~Kr#~)Tm)Tibc)=(&PdxSleAL4GWI1i&3mO3X}SyQlj9aR6%QUP=jiqfVq*N5 zPPODZ?N{y>egLHQ{;>M3Q&O_`I5N-r&~~0aHyY*?G=r7wT7AkNY_c93Y)+l+EFJUw z@Z@S@coi&cW*4;h&g06lThtM+<`V`{O?3@4udh9hEbo&E4nT2~pDf-`b3XfEMxw#H zvWl*Hb{F(;r|YW&zunkbBfm4JRb8jeRYNkWA4Lc7V7JvJtU4agD~z0#z`WN`J)AvU z0jnC?1-0*j%8#CstoEVJb696o;Bvd+S61yb?}tp>1<8TAC6;D4Pcf~DH0BOAj&@m@ zT5Z_WYrQZv_1MtS^g4a0rYI%jT_B}<2@mFq+6C=)uh!I{i^h73k{&#ip1yQ<P%9}- z@oZT+GGiniroAwvvi<`3<;jx$O`)5#=?Zk(3h=nLqQk92^F?9r?KuOGEjyfvb;+aT zE$jp~PF-gw>%)6_7!;R%ySs1cM*f#3A=&#)>wQO*@`nf%r*KNQ-A+>pC5RHGvB-=Z z@q^AFXRk%w!+1S^e^~i)C?%L6y9+YZDSBzpm+98j-w3@5NHcQhBckq?8{s9z7g-zS zqCRwlia8weG-NOzhcB!pOcxbwS*%a5IPg0O&M}G{ZqCTdcCDO9qyb4SI*$-OR$^gp zD-N@+E*P=*bum`VVVeDeGKq^4@)5%e=x#5Ex%K_wK~}+DR!_4Rg^%olU|#r+aZ+pY z54N^o{odebyP%Jl0fDsBt2XUc%B{xjL3kD{DX>`Gtq~z0MP-I5jo6yIVTIYayhe%W z(%Ht=14FwD>WXyw829nU;l_(h4=9mrCJF0EsT~8zfUWhoM9JYVKO7Sh3cMV*UKKWb zZhRBAwmNB2a_aeD_ahtlhfl&*$%y9ex)Mp#4bipo6~nGxq#3ug1LR9fZNYg<<4*^u z>iZQa237Cz7QESBtT@}ycrX0G{u<vXF(-PNf{oEHAGe?KzgOFz_rPXA-?1q1l3x&} z;i*+UUkm?k&+pWXp8A|?Q_du70Pj9VtAuHo-r4*u6ZzzifHa4#x)~T*-3*pCIpq{@ zF=K3oc__{p<(n^)8<4j?=sGONHjVtWP?clxR8uPu4o6tWjvF~$@p&To#k(8pB%inw zgOqaHGLDG*M6ellGO}eypIR$g9iC%2%bo9qnQ|E|TJWotTP)rM!7bpvULPtA^I99T zdxn+s0&LN&3PW>CIrW7$(bYo)v>HF45!H2pQ}S-_ntp6+4p-J(`tRN{7y?ApC}ras z4r@}4qeWlFtA|S*NjJEnc2t7aVI}1YegOw=k0vX7%lIP)r8o<tb=6?~Y9haR+x_?> zu3+CYV{qUMSa%SJ38b(GB`iTUpz|PYkUan^ZUHaPy-(jv`|*EhaULWI5(YpB@W3Cx z;YYkew}%LU@A!??2ip8(_4m`z(9qKCr={J0U_bC;px?irp5f5JgA4}`9y;=)iT~;C zkM{n@G8G*i9pfR!lShu6{6DbzR7(Kpr2@?4uU6k0u==S0nRLH3`XCxw>V5mEKtEai zefy|?Tl;&f4*=<JR)0SoHE`PJNwtsqC=G}fF#8HR`;XrM%>Ids;VE?BAFb|ZF=orJ zTpstAxfR9rB2tU3Jl{%O<Bd!!kz~=gzSYn(LC^Exz`>KJ9!4oCr<Wpn;e4#b$(3)G z-^S}v^pDp6JI4Q#s-gXzCvn*o%^zkq`7f&(Iruz{&#7$rI7@;^s~bD|q7rheT8HMg zenbh>w6p+np`oXycKHRUDA4Kv6z_Mx7k)9N=<A94?$4Z8!Mc_n%VJ#Oiuai#^te;4 zir><C_DD=zd%&U}31Fg=r+6flSb42)!KH|4B@KN1y^|{sqtZ)%PqOlF5X)}?%kOCZ z8<PJ3EVLjC@DJ!B1Iq%O8LAq5`~Ocx08{)2<X0Rt82^8*f4klPNe})fheyqSlCX2S z)tIpngKl{{#7YxlZylq&ee_y-s21fUI#6psBE+t(EFq~d^X$3x85U_jX!gvbu&n0p zJ0-l#)>-wa*NZYMVn*-DUA(bKQK1{Xfz@Jx_XdS31FlYpRiIRmOSbBdHYv=zAl~(U zU&MbVX8<PY`G18|*EcL;y``H7M^<>_zHnlDZoSjNcbs8AS}#B~*CnBLOrr&P8%c=9 z88t#;NWpChB5|w1A)H1SjcSJINiHqvI~S93=eGqb(1B*}ol6-HcPSS+nD;b_o)D4^ z5qzXj_-?Us9+gQIU3J9X-eE!%vHb7nCSU>og9-6JB~A#K_yt9-73ro!>gGmg?&jt~ z+SO)2I78%fe^S6S!;bmVz&jPZh6D3iHhoto?&17vot)R{QuEi@$o&YrpOnzl&|s{8 zFUdRCjFi~2+=eE35LK!M$*<eZ^*s@O!Mq+O;ZRq$l@Nn8l3P2gcU-BAoRg-obD>^e zP`~oiSzUVT>-6mR*p|=0FaB%Aw%hmr0{aZZ2)q#@HIptkGS2EOh>KYC4J@Y6XnGw( zrEBnU_G($Uecr@=n8-_d+t>vwzTeo&eZOZ&0!6Q_qjN+@-~TbB@E1LP7o_bhinxr& zLP?(OteIKqA2qm)Gb6<my{)`XD@dGpul{5gbo}iusCX02`7hbD+y6Z#9lxSBBWkdZ z>4*PY2BkiW{I;%+j0<WtHz|EgIZZW3O4bhlXoW$1WPg^;UT|P1Y%>gpLwNqekUcwR z=$4EW68|C==Ov?-sJa5bE0i%`)@PJ<T~dvIXMuM;%^5C7EcQu|+utqQ!Cg8ulw(rq z{6J7pf!#>)eP2F<OH=GeoSx~w=%t%^;+=`Y-GT3M?EjY0)vs>9ZCtzl$j>fqoKZ|K zi6f?*0M)<Nv|e!xGd%uz+c4K`3dZFiuk~I}<8@wf$*ICZ>oKRqr;OGyiW5x>VIM7m zz}AL;MhOYyf!0n*IxD8@@^{KnB7$?rlivqgmLZN@&0lx<0)f$;plmGcf{L~e)^hM$ zCUC{@8gYaxHgP;}ZGHRdzU295@PEb|yMzDB+&e&SCcmj5&Kb?Jg0uT&$MdAJ(q~8Y zk>VRC&Zi&!f+)o8f@pCF8>h8owBlO9zUlj06VhMT_?O)a$UXrH6S;AJW}IcV3rwRI zV<sOUqf;Kb)QCUiIowLkDd0tO22P8&5SW!W=sw?lD>~d+C^!z`aL$(M1LpE&-Y5BB zq>a0NzuC#xh(r3z*BR}7-%sRE{5^Cl{Lf(0|A19sBnIKzjYZ-xVPcL3K?W=P^Z6M9 zxGbSp`)`Miann{jVsj2FN0kVEcShATw2%F;0*mpl_nUU(kTF;Dy;ijgik|kIHK!d- zFSD{xCnVdgn*gE~jw*ri_!KvE_|mX;M2QWn@Y_$7SB0d;T(*+6Rz~crF?6589)`U9 zd!GF*EHgbk?fhLz|691HAKNMK+Fg@@-+t+4@H`{Gg6gP}bqwMoM+nkkWT7JWIB`X1 zB{U1)yv8Omq;Lc2!>Q?J1-kiuSniOT)J3E}-EbCJBL>pq{`bfMA(|CvNpjri*r4cM zRC6dW?2Z{*JOnj*hT4k3Ve1qqu&r^s37nCf(v^bg%)bF_*#8<hyZb6@{$CoMfAUa{ z4Pb@yB(O3LW7hoz>D8E?8`QAw<Q+oj!ezJoBTP-aY!5vwf>33UwtwJ>fn}l4F6hP6 zptgarD;0xoE?u)P<tACdWEz|&?Qq4>Vs-2h_~@v7n>)^e!-9luAIi*jThl}kCYDM~ zf)aE%B=}p5jKf!VUcgs3$dgh8*CK+8jP`r4%A}=jHA8%P&GVS>MLhSN=B7n)*J`On z0c0eqwkBbpZ*Li787ed<@3B&l=!2f6_?t<!w+K#*x6U$_r#V{QJ~}+A$gy+dL-r<q z3hVTF`x2VB4=cKs&)IIS@g5^5sZ={KVU?GDMB`?7JI5<S?ywDOu6~EQ@hrN=5qJFt z9r7@-KLq!|$wfIp1{R->VYD6VQ4_o#PJiqG&)HNfH6w68)CsI-0X2h>A_MRen99&b zISE$|EORl~sO5QSQqj)GhmE-$uCnH??nIn%DY?E^yimZ$D?MSmJt4Hvl@;gWqB1Dl ze?&Y|{Cw`UT>9yjegm))QwL0diQmE})grIKCZl7`MQcFyl<Q(9AzRlF_U_=;lkqu! z4O9W~3&A`rZ(bx_A~Yq#?6jw!y_bNeYq@0W6$eYM<VQXt+>yP=;Dw278MltbV-7AE zE+YC5uGPL2%EORc-V{gUky;$|o)?=0$fC{55J||B{#}sRYAw_Z`+lNVLP&WR^n)Rx z&V-NV>6v5KY>t(bq`Id@eQxXbrYxQYYnpT>@ISbcz#Q?}zqwhw{@7!|!UHdwKZQ4n zKl2F3+JRw!*cAS+q3fKHk>R1?HcwBE2Dg3Ukv~j9IQY<F$6tdi^B9@~y;h`NkQ@Ba zh7F8ZJeg{-l!RB_>R6q5TYj`J^a#^a74A*!r;6OwGyg(q1@D47wdcceQzjwc)!^!S zj~ve}tqaEn`kElQTM=v+&Z1ARvk9#q(D+%bFjCYi;zVMbahiB*aU&KU7jed)`;G`} z!p1Jh233~~Oe05f&Y*vC#<<hD8)0)p1-V5{;1C6Smq|2}?!z#IvdiE)*kHZVvd}(C z)zbawK6BoCt}k*h4#VI(NoigwjzcCUr1@s=LHRq6j8ED1mXe^z3%TiK<zLAHr^$l( zTy3+KIi-?;4&7GdqU81?W{xZa`zHnsD#}%=?<CEAz#Uibe$1`EtY*6nEk_lNiw^lT z7!b$f#7D38wzJ4zj~e4*)r@j*NEcLAxlq-5j~Q=#p`f)_L$Jr6@f@VX+4YM_*KLEK zAF!dlM#O~+iUPyU%%`7N$JnB#9Zj%w+H$brO;P=@t0gOR(btLQ)!wOQ;|eY*WnsA{ z#!B<%#;RRsa(L6}?UY61raqmD{fyI>2w>=79gmX5qlKT!Wi-WMgyc=mp6yraE-Q%` z6BBG{&aKHg-P~fX9*34#IhUB<GQGp1+q)QGm|t3}dt64ZM-4BzxKDm<b4U_rZj&=x z=ho+6Zn<F$jrW3HnB9nBsVW|6eg3g=pf^2|LBRUf<0&1Z8~P!2OksV~s9L+W1h0ia z=M~L0T#1rXwnVUT^Cy3&v)L*q@&oB|6DIP+h=odh1|3xx%xAS*h1@k;%6BKy!@bW} z-R4^C<YQ%U0cL{l0AL9I*Bqsyaaoe^a3`y@{YGrLWDKLY$C#31y?oIz);KP4p;>Go zx4S;EvvZ)e=d_G!41>un!&i@J!AF(ASH4n%5&vLp47*<Lf<$FYrsmltbD%OUb*F_c zGL4y;Uj87c!`QhCDh)gX$Fk3xyA9lGDI~X~Wj^U?*GjgTJH^Y~cSiF~#xdi;&la0t zoW5)W$<KknCgtEemhU6fn3&Ehqe*{PDCCm|Vh*-3$wB6OcBya(XJq@$rsnRK^Hz-1 zbrF`k`f-hmrWVz4>IKz6(St4u3s}_|d*N1nzSB@(k-I~NO8S_Ros;0kfm6x-Wud-3 zSFtQ#E-jnF<@+T@kE@liRORnr9>t$$2#(j~YjM3R^SpWj-D}X3thvJ%`&=^dP1{;G z$4NQSN~CVhB>+8{!c{a^cw;dd2fP@i^f0wW4`TDZ+{8WJy-?wqno-YZnHUEfSrL*2 z$HxP%w!up)>sANcolY#*)J1071RlgyfY~c8vrBSj(L(K--t;joH09y(EKz)KqJ3xs zX|LxgN<tpI_aDS3U*PIWnTx4P7=B)oXryaSvvk>=CwdW;U%J8;gUPY!b(T;SE;u(n za3?==Km1<HGqtbhR4?lbASEGa{1@R_d5c~HtzHiM#fH*?9+@_-2vtX-8rP#F6|435 zMDP!QOIP@PpY*@tVO^PJB}C^b$yT|%9cglM7fN5ioUyxCq5Ak$KnzajPf#Spq1^mW z7XhjYaOR!_Cg^-sSdx%`;?zTwUn0L%V*5}jdT!X*<N>0bU44L{&Bqc8tP0WA8>IaM zsktm0>(T))2FrV!oE%&;2o=%yIr!#`LL0zF8FLAN`B^58#x8Ho49yx#OiYy>3!Xtv zTIPUbpZmW|_X*NnaqEwo+j!XKnLSeZ{O!F!_M^|EA4?xh`W7JJB|?)W#xMIMY^`XN zg+kel*~>B5__KDkRfjHX(Avw<r14Bn?1G-;b}fJFmG)446|2j~(wwRz%`P*L04?4} zRJ$Mn@EscFF~u;VpF(Y~X5~tQnXv?>_2v%WP@Czi3Kh-`T;(Z*J~F6h7i5JhPSmhy zI~~^E1q~A`cq#k}tCu@>^>}0Zho)xS+&aFkZ<3-yx`bxycFxauUlYrf5b~%j#pQ6i zKlTRU<T(wQ5V@r*4<;>>Ubf$!XUS~qgelZDoq;o=$9Alm%bw2;xh7^fl*v0AdUc;E z?nwQ?Va}J_C$hz$wfxj7wdqV7u1J4d^>`bBNy@x-DO?bZA4IJ)((-KOxOcqrnX>Hm zol8p1<zJH%!F*lD=}!^IqVZvE7Tl!4tFKjE{cB<pLbJH|>S}S(eN+;Mo$2^Z9wrsO zLyjU3L+-B7X6E>jVEI0cm)>d;@)3hNwMIS4@a~D1ocDMPcR@Zg`Ne`Ixx1jMsaP<K z{E}-Zh~Sm+q5qafj?k_6w94SNB8^$`V`^-v!ZspYiVt!mmv`#qvlb@uf`~BHp1fU< zNa-+I#_)4xtr2%k9N#fD_V_t#Uk}GyU;q)y?P)mVe`mnq6{Z8h$f<<wccnKJ6v9_N zPsTrGNbX0~a8lf*Iz$3k;>B~O@B&&1snmTKAk?x8+Mff+Gpg?4KWN(@R~yp&TsI^= zhnvKPWxH#f+`)3HZTwWd&p9IoBl;|J*uwoo(tM;8%|tXAIjc_<x@Dv!5pIuWL<b?D zUn|fYfBO|^UNL&E3y{)!wWp@fGjhJ(zakFCncr|AnGu*I##C|x?Jc+$+@Ufs0mBmE zM3#FArGBxyAdAntAQP~!7Y2jLuerV6&BeUTr<xLSl_PrwtOPoVW?T6ZF|iW*q)MnU z#q);ciV8Q;7_8^Mj}0~Y;r=y`z`-+cx!12tdKX?56+d!W6biR2zb~qEO+iUp?$^j1 ze{icjJjl?+QRrN&oY|a-wjt;72;XFF5l9lD0___cMb6Ltfv2z3PvGN&r!?iv%jzS2 z+ETo_j-X6PVXnO~Prkk2nwk6%rCU|N&GVSXNzNNeH<cmi!?Bt5*TrXC*n?sEtGEPZ zG`(Vfz=cch>zR-et?pX^7rXOT=TG|yD05+IYt&9ymk;HhXQ+cbkz6M*q2rzpFR$*L z;|w~e7k2Ii0K!Z;o?PRgPd#5lbN#TagSuV@KPqK)hgZGV>dxvspI};eWpm6jmqHw+ zmxckcfzvtKbjJRe1buL~K8WtU=#OZ#@V_&BQ&Udy&@*GTz{_Xsd(P8ujl$8|t2dMJ zS!ALL&YWQvbZIbOAuZ7M!_~>|VEAJb#?F!WfNL~o=gh%yoQ17rwi#l8q4wg^(1e4~ zs{~#(SB~cmT#l`Z(yjEO#UUh0CxrN=jY&k)kMNY-mE|~8lcbALF74sy6XC63A-Wci zF2^O96n-q<1qC7l$Q5YFAXfaA9IsAov5CNrs)KrAp6Tp5rAE@Rt!tyB1$I8U#`>A+ zTr$fUc(kE~(Hyhn#(<s>?q#2oM9qw2;hDP^U&|lL0vmi^iVu<7$#2fVdta6Irbtm7 z`acZMNE;v4<Z5!$d9!^1XRa#=Y4*n)u08y~iY-o<qiP_AeQkEJxA$qfOcKK<`7V-$ z(`TIC_v0$nV0CgEA%LMxT6U<h@^*~ztrN$z)}Y5(A$O?++kN?PhTxc5QuK7~)q#1% zCnQ+Q*S0fF+BG5O6pF<45zD*%H|{HxOKrvnc0$&^xfdO4So!&?u9u7ClqrLI<61G7 z$=&GoOhcg*#@gJTdrREZVQ<H)cR>$6p?gHX*%D*WeN89x2Mu7i@2<>!H+*%EF01Xk zcl}LBY(KeyocDT#kdt=S5sy`HP&P{MwWKwkaJcknnomNtUmtaTdU*$fGn9(J@{utF zHZGEzaqpWRuSK3EBNxocBM4aTxGGqf#m(fi7W;>-VDbn643`XZEeMPU8_c^4Rs*ic z7>;FS+$^eA#vPyu)wn94xeP?%$6MV5e0<k?<~0*_EV4r-*NNk!YWoV0)dVnmvK=|x z)&%w`D}3c7Efps_Ogrq8ywhRc=9k`(@-U)vS(p=kRD)AVq#v)WcP0tV;VXN30%zVZ z_433_l1}$(B+IJ-MEJG$r)X+U@=YbZ(r0?N*oK<O8T)S3#;`G#<d^z^)TX=Q*CIhE z%7!$Zh!tu#etUu%T#@zWnG$Tr3svm@U7xYy`KuCEs!HBhC((zycR}Lh$^xItn#z>) zt*lp}gH@Pf&!YR+W{-CmvmifyZgEE#c{w<EA9y@>a*3TwG!%Xqqt^msrg2sRv=$JZ zSDZt*`DKlK%y?H8=6?KLx%Lt6CsonYr>?(|9zd5tqI}p|q<JH6oxBym&qTYq<eHw6 zFk!px(b}*ma|RCm{sh{CVP+`op96Yc-Wl>QzT3Nh4&&8Bxu8Uo4~%7%efx*QHtPK0 z{}5BO%yEk&<I+f;N>u}1!H+P#i$`jT%Rl8p9X^mD*wPPZR&rr~&6h$G3sP{qXntsX zuCxYzhx5tWD-6RGVl9;jw1M~dI`X4C&ZzFYqiUw@D9~E~c?Tp+k^Cv1lFa4C9iyR7 z87}vgwkggAzgLeo;--;KU4}9(df<!>KTWaUVoqd^Py2|ox&cZ@e9eZR+xD^=4a1?* z0M_N5UJ>i^PT)ceF~wfrVV@Rqi!#=X2v>b1FOY*?XAfG0*A0@HA+4pS1B{22iXRwM znT+c4>A1O0!ZfX;m_qI!zWV~s_WQ+`zf3at?_S=$o*bdi78~>GmPv=|!S&1(c}V9T zbp6XO2YfJe5ki8{b$({dp-(*crMX%rriVw0KhuLvKgswoqpUTXUN1*Z9i-(7Nc-0J zg{{l~V?m(pT;TQOR*G)#{#ch|?A0qan~VqZP^>ZG2e*0(=9m2;yC4^XMa!JQaM^oV zB;~P%CLgaHN8hOX0eZT%(diLB`bSQO+&K^4gsXg{IK!iU@(Qec>7L(`JKb)KjZ3>Y z>csl)MP^Oa4Ne?$U-`rLzBhB&>?jVV@Q8o#A%4_~$bSrE-H<}QgvLmgdm}uZo~{M+ zn=_=Vx^k^fJ$pWf<FwgSUB>Ap!emM6#Ixs|<g`vd@tVF<`qUDg_k~qF^i?*ydaj($ z@;0;sl~s`&G?-Uc<t$&sHu%ue)2SoCLbd!T??K|{W_SF$k7e%WpVmh7Pdl+%&L2oS z{fIR^X7P4R^~wd#Cqr6M6KA8{_4hpH-`)aD!~WQ2Q2_&|9j)jS!>bQhaYo-)dS)m< zZAIAcpGvxGSt#*dcA6j}?Xxr7R?L9pu;(%Hn_pLQ&oS!_%Q_&FcXOvu2RZ45GmrkB z08_6d69yvF%meRt3yrr2y2O4CQZAN7u@Nes`(H?<42lGUttp7ec8?i^2PuM2XstZ7 zylg$sm?lv9-hrHLSs#DRWy_p`A15;cIvplGdk*&ArXO>xhxJL`!sM7!aL~{tOY?;$ z3LW@rph?5DUP=pcngKQE8`W_u;if)=)$!g(uWdkBFxb@sgDS51M}4Mnh3j7B$lj8X z#Xkmd?j+;OGN$K^Y9`%Y*&~cYB1o}%JacoaLq*}~XCiwIZ8!DZH_@oV*TiTboUjJv zFq!kX;&oQB-8d%Ai}4l5&?(`CEH~wY@3-9Fd$Aq&!0B2@kiv{zWZLDg_xQIF7*+Ip zxvFADR}*iXd*E8uey5)O<vvsTetu7mHUSTO1K4`KDqx&kphGy|CD3F`Y_+I;7?_-{ zlC3>_uOU7t`Af8q=UU=+C-g9+-kCf<?bih{_IX=R?t&(`W@<#bt=a9+yjPQ8EKUoY zx%PS?au?(`7dQslI&P6*?_Zr`dexY}r_<qR6j^=#==lc|hat<Sg-&-^DUqxDr&f|m z-N+xgn5$a0-iV%bbvgIxiKW2XQ+mBe^IB_2QaS5I`nDN<1U7z^X_)YA!rD|(eq+$# zL}X5<t8FoBO~|385;fgB%Xl`C*B^4dJ@La|1bw=cx&>t$a$%XI;vq`w`sv~FiiA_2 z$}TqfI4>^axRu!MeO?x6KxG*7Cdjtr%~JG<*Ak+ZNvU1%1SWB_CU&Ec%x6>8)l6X_ zUj%FzDGO_CV0E`O7pHcqF*j^XQ+vdmv~7yFP0HA;Cl|9MN4u`D4(1&{XY3BXP4h%> zeUbiPyF01cTzY>B+Q^Z$_JREX(a~2Vc8zb*t{fW`F(|~UaiAik*Zz)Ly^(w;WR<Bk zM5{}iXjW9#SBOz?5?n9t%FW91k5CezrhNlo;D%BgtW%gEd|KYlP_{mYl)Ka^=WSZi z%ad>t!{FD|?HiaVl&2V_P1%w2;c#pbuY2|)@iR`RPN!#3pNu1h)_VJR3$2YuP4o%F z3eT&&{Nbp-Dif3DySy()fH}F{DO+Sv`bUM9$4T@+AbBoE>M&>IG^V`~S{-&lm3$wj zd_%b1_-&-9PvG{o$|OH0zs+YCyBsMmTGLU>j;sa?W#e{W`1@OD1r&OOZiVoSx;P6R zQ8~mXO*N7{WINX$*lU?h{)=g)k8V$LB7TW+hN?OZE<3D0dg#QJwJ63)3kTam=bpjE zY0V(?);EgI(qGC|!@F_$7_^oV8(z(Je>^bKA{&f|Q0Bp&2{ju2z`W_Mzw$GT)eq7m zs>EVoVzYHN*n0&MLL5?Iu*2^fPG8Q6x)#W07}%b?;tEOrBU8Q$cK<OhrY4(@7lO7q z<qAa=H%pjZozzbrxISWAdA=%RADKF=!6KNP2RASx_CL<gvEO>s)><+XE97m@c^&-n z^BvXaM|?z1F=;`WA@8`zk=@p>Yr7MT`(xXr9^0`V@;-33#_i@J=dzcA3~x4mfS>yg zHr@iPnTHg1Sy+3?VxVbG(dgi4ST)U5ev*%WEgNMT2D@#rS*bERk>f*-B@V;RT(p?e z_3=H08#!m-6t=+{f!+#Mefw07J95(SP+geF2b>Y+on%5xvRtJ*H>S_y>X+k8#c$Gd z9(kXh$dUFrenk`7Rz_uW!N+VORy{B1xjno6@jhtzcDdsO+6%@`vd|8=9iV(%+;^wu zh~rbPhssu^hb(PoXNx_BI*?Ammf1{@KocJ~wSLZ(LsElPz=~3TUA`4Edo;02`D6AS zlSn0a01(P?*##woHJxQ6@xx3KbLNhivd{UB-72&T<d9PwAR(5899e_#oq|ibngq7i zaUKgZi#hKSGectwCOuP3d3D4<>&*Ghq&W#l2%N3PH%o%D0@fddipZv*YctDfI~v0! zGE#>da%Ndv>`cICVkGZ`(cPna7ro6^g32=2>8`0ww`U$mGXFGWLM^VBo>ZP^Bb#6w z7jv=ZA<=<BN)XOnO->~$jim*6OO#HW)odS%Nr=^JvT_#-$gwF?F?>0c%skGrXqh{} z79(%ayCkj=49#y4z8j%<{q3BUA-AjTDaWS%M<xrv8rnf1+#K^q@ylZ(S|)!MctbDi z6{7FV-?L>3Px@n<UqzHK9v66Puwbp(|K8NoeLgXZ*Q%1T4PF?##Lo*DScw6Vu}F&J z5Ad0oa7}QYsHSK|f;c?FV_*EKE3~bJZ!fc<9sth#UjR7`|7O{@w`A(^z0OtLuvJdK z_BZF!7Qb%RbvRHEkOu#Jl7hqGS4oyD(UU$|9r`q8reUilp5&OaUC?M_8VN<*DGUPp z^85^~vo$Rcy`=#cr}g`?Oq>`l4VgS0PfbNd?!=*~$W?tcql6s~q>R~!W|ohx>ez7G z&?)WAI~vq$!*?BhplqW|cp%SlF?aPpa54T}*zRfI4N`*+G2K``HD(!>)|IVjldq0{ z_*~H=Ks=uRYd1H9Eq28+$F`c3EE$>SlZVOkw3i3qYen@-!>t~RE&~l4iBD-gpWD_e z)#GwCQv&Vhmz~BeN(V4!8T1~sN1R6H&K@IHyndPLU}YpAh&6n&yqctS)IE~?0xm+# zid)M+4g^UOq+&kZ5AZhYUz3qxshVE1=L{vzIb=n#A0B(*u+Fkr28kP^*!!ScmVNFw zb$m6RV@-;;Ih>MiW++e(o*2<wvwj+(9N8Q0dJye?d-HS*B(BMmRBi`h5>?1_tddW2 zxaAhn!y7zzjEj+jD=9sHEsl$`+g7`<4QwUNIGEr{9wphhUtedv9pa5A@$8&B<dNr| zigUFKIimJ%r-Fi}kl=xVnUKWf_Ag?{2VYWF^TS>)VjA!tQm$E1YY`uu8H*1LOzuBD z=oYqa0%+{G?ih0A3Pio1SFPso8|~w3-Z`0&NRk;9Iixo_M-l&yQ9+?L`7z`vIXa7+ z>&D-EV@q-@`Rhrv_+N?Qb!=p6l1U%VNz)VY#bR?O5^QJqThO}aar~T{p(>j{g%lxK zYO1>k^KNzKdu(`b=v|I+;POzV9iI5~;z<Y+SbzSr`;uqZWf5m?K{R{FB3+m-xDk4z zcfrNdA*&+p;Ff##a15|s)rKnS5-<*Q0vt-_I_nk2W@2ZMt5Loz+D(l&-VnThOPAk_ zMBlqmPP8mk`)x<`)7mNeKqhZyL1Mm1Vj_2fOqfa}pU80!b5qqRY<tMpGDso^2S+NO zzV^QC6ClRBAj^NsLi$w!d_e!Jm>^`uBG#GQg0I!MTEkY+=Q6h6wZ<su%_KQ{Jh+gg zfhuC8BPRBeG5xYR1jZ}lbG{peJQ#H2E7{04CAAa40+$!ZHI`VSWv)4bT(<%T@|HDo z&K~P*P@xf-@nZ+$=IPt*?R=<K!N?lXHztXc@k8)Ta^66GO-ULcgGCAisK}gwZ_LX( z%VH*%Y7%Vk@I1TVrkRr5Ym30Q_y|L?r10_>g6i6Kq4eBMwcNS&a6`k8i&BPyH||^H zDR*z-lGFlUGb3y#*Y8YZ&$IDUY{t!o%j0Wsj?Q`4lTMWNvd6IHw}>lqC#)n!%g4D| z(hmmZEL)-lvBDCI7m*yAS#y$|WAKsyDQ%XcmsyxsxCA&AarZ(kM*PpTiQtwk^Zb<F zmxhT32F?Xq^>RC`<}(jT)V{hwHE`F@s<G4{;`EJ1<(-&GRIR7>YfPV@u(NP)AEx^0 zrz9vLR0-0sbP3)0iCjs3i+MlXT9)MeNES1jXlNJFmXvWejo;#$#vHu{tt_(@3pd3S zo@_78lbm8-CN25mvCLU{n)0%%j#rgalwh~TH$x$zzm=Vz<@$PZB!+c=LDst0qNzTz z-8l{|^H<GoL*4<4uGkBL<mB|m`J;7%5_DU2Pt%+9ggP3IfIx2bKGd9+x!71=Xrg!r zXcvT96U%Wjh*a~sNh>FS)bBHCxWbghw&VGAA}{%881*v=ijKaSFEc)LAahKc>}>YM z05Kza6y4KH=u<=}L8AOcp<AMQuW;|xvV%erErY%H7v~h8=;W}&DM+AGZRbu}TRU(X z*oX0byvuDIl{=V{f-{)-RgT}?h1{mj!I>lc>+>l$NR2Wgg5zp8rn*E%xDpDAT#d}P z=EQWITqkYsIcyWQfvh5`7K7aH+r__HLi}#*v&i7kUw~4B&hZ3bFW^fgA9>TiBTd!K zA5AclGg%b=9G_zHPMe#4xRenRxO_H{t-R&*W5^m)TUaNQn?xKDj`v)1fg40OhI?MC zfE`Oq&!Lzi7b+(5KEn+b?m`?L%BKG&LYv1zd{{o?a#NHpEKcGkzh=<DxHJ6aU-wiM zPc(lZmH2tZx?4N}S6ft4?(Nat_-rJY%kHy^#AM4iT_^hU`2Ca|3cr+oU$;k*qvc)P zNZNj?s3k_IgBD=XyGVMeq^u6ftxl}BS3uU#HMGks@kh=NTi?aMWKK$P3;GQFe_L)W zQB6gijNl8mLR|oJYJ=fdUI8lWWbW_OuwGT!{kb70lSk7uGu`Tmp{kR?j5P{4ZQuR( z(tVIBW!<ZOHl@A!#~&UM(xlT>ld!e)wsnSI_-m2=-IITl;%f2dIOK0?{{(7^u<bBz zLsD-mYf$Xc+nmbKvXa+@X*Uybe89#y${^`XEZCp9N-9CT@S>^1`m!kxCcTC4xe1*^ zir@7gimBO}8ZVq8g?#{)J_3I*541I%iHRhI>GZ6PvJ#kdyAY-EW5Cu_NQ-I&KeW|V zgQI*HND>kI<0Sfpz`WDMXro(SMEMs9LdMCQ9$Ju2_dkr3fn~O)2>_cyBq#Oy3XTml zb{{HdImQaf1~#D<A?Qe+XrJ<qt<kO*OBsop#24YG1E`f`p*@`Wnp4{z2utW~Y#RkO z44?T^RHzN(<ko?dp4&*!B@*qTT=4eXbs_z00{wbduXE(kz{tBGryaKvR0)!gq<EDW zgGx{iW>B)v>yc4i1hxmRPIFctGa5>q$Qk$<-~Bj`eF_O8FTH|0;Ij9o9;^9x`97SJ z!ePBLjh|C%u(K@<Fm9)_v5|Qo9ps`Eo(HcCXJ$PmCO%%{*y?YK=YAg2CME&XD<>8< zpfc}#*TDb6z+Y9zx4HhG=1ksjBDvVG5ehe#n6EjMPM1{OPd*Oo*!KeyYzdx*TtAts zk?Z4aKn50S{oC-D&V6Z<(y|2-lTwU}MYp|U7=~a&F(dvLDNQ(3E%nvGTQB|8%KA$a zqpEwCdS4uGbfjNm^0JY+nEccPtn$}W_cr7$6yhi(+n%l$7PqFb(ayB|m!W9h6<E|Q zHu2eIhpo}ds$$fHObQ(j-0opS%G>Y`sm<`ZGjPe!OA{ehAy<{}LOAZ8;5z}LdVdK1 z8$KD^>g%>&%|(@*y-QsQWI7cFx{d%o6A4KiYW4{>g*^_qTG}f(zpbaK&E-Y|Y{Tui zgzmmolwFW$UzMo5_2jYWov-^i#N5xNTp9j~H<!TaT>8`S=wr2r>rXSsEyh0>DY^LM zH1qWFhFtMU*Lf$F4B*l4@!)$?``aSJe_{6x!Q6&Oz)t0BO?Hf_-W_#V!R8ZS5bk{= zF3Y1vVH@zCkWrS;6~MCeBBY}xhtR>$VJs-!_|!vKkdO^6Uar{IX$`s+&NQTl%ABJ9 z>p<lL3WDuHM=-h0rY~r$85s)c{G)<3h;pj48ze7JOAuotMQmPouNp<TiIGrD8&l4w z1oMZ}#Pl}COSYkQ5mkl1TdmX&YCq>oOpg7sAiiUu6AJvwfL`?Z;?hz4?eO~#>Zvbg zz=qu(fVD*O^4%5+1PdmQ4UH;)?K+yzdieyJKMVB&&X_VIE&nL9A=805{G;KU6wCYE zuTCuamE0-u*F>fL5%eNBNl!^Zc6bJQW*P53%%VCBJu@UO)8;Np($CY_c0=U^8j%!D zx&;d*prYd~0R%G-rOJM~><%|-KKAqX<lm;Nk6h;4+y#Ad|7D-ix2gCq$9fLf%JE;? zA=FjVHMOXx*l)WM8-4@cf6`-M_2{+oeonI%kjvRQz~jx_1>FvK>W<LFvt6=Ja_Tv* z+mpd%@Tep2!L#)h;jTl=$*9Xm78Oxhf2Cyry<B3q@+2R&8AHLUzjOcNb{B-^Ax}lF zi=jHL8D|}p;E(9Dak}GzJ|<U*b>Zj2Q-*>yP6l6i#%yU6ViX@2a~s;;1lIhGVh{J} zY3L~5;xs0i=sZyG!-s<l3pmy)uE4$=a_H^P`hfqs3wl?ipVb15mNz1nc4gn=K@(1+ zFk{t$0Zut5*Cw>OMM(U+AVyS)?4L19E`-)wj;;-?(2?dKHg|g~Z{TK2jxlGG%bn&- z!yZ^!?&=h^Wp?|YZ~PadX7P{VuivPg-x}W}pQh%7j-+aeB#}3ZE^dYe(aR+(gi&Q# z=N?Cy@=@lHo3ik5AA!y-Sfco>un@C`$*{@=M_;q%&t4AFJK1>H=7XJhmTyTrf3~Le zSb=($Krg!N74Fa5pYKlOP5-uyArrwad8stEjEIeic9UJq4}-xl1p~_%MYDFLJ1XD< z<`xb`2#u-HgBw?g9gm{}vO99ehE+5Yw;u}=Rojh1OeQ86+|?;SI@IM~ut^YUV}*$< z#+{j%HEUoz9*2?e%$yx)zABY<rAzSLO_X>c4%h<3&?0X_#<@7uv`ovnMz$PRp^GWq z$rI|I36zAMAm+=Dlc8teNfW=fVtZ33BgtlkCk$W9JZ&@}OpAGxN(}FuN<uxUH5wuF zr7c?K9dDL~#`*UWz+~LY#jfiqT*0kd2Q0A$rBT`)H`5k1Z(>=Pw*{KWp$BVae#?#D z4$41F(%<Z|LR5-8!I{mekQ=_>5b>YRTI;MngF950p0$03EM^-78+x6U^{Ra0KZ-1X zl+F!lgQcERP1wNZQTfuH&lwrlYW?N(DHXX51V$RKzI>I=JG&r49^3)Ql~gg)eQ(fs z2MZK$0NYWRYcPK7ii#$2z-E+sOEfI8CR=(QK}`w0u?tElf@gJ_YoGP%kVSU)L01rv z*QCi7#R6<**p|!#iW3fzEKfS=wZa?+ogp%j3c-4A?XdIw>@{r}_oWBc$M;&a7q%6t zlakfJvy?=)U68~C`t*tn@v{;v;a2!ANCgO8t(ZefD2Ob4){dsJ!48iC(8v<aL>R~4 znJ3f=H0{g>Q5<myDZ(xY?>JEB)Ps}W1!XAhxWl0&;73lP+14Z-l2@N6155$@hUBPb zM*okQC?pO@m@9$@t+WvzBI=xb%RW#xE%VvBELxTaI}(uO5K24z2AM=oI*mjvKtByr z9B_uP7l0dwgxK}Pc9`q0JWjqb&0x4A|AX~bUCO?M9mFC$kQ=&`gROZ~*9qjTl<a~o zvyp6a?cbX_`o8d$eDyX~+N(+O&WP7Ub7?r!LOJ<Z0VJNS>r2Zgh<}F*Y>j7e7bLq3 z&j;?KBFSP`d)@@<bRzZdpj9Xy3`Bnr@}16eUtNaCtyG-ZE=ZA@q}J#3Dm0pTP^FMe z#F;{&0MKR9wCM`k;wG#PyNyf~uq7u)S1<PwWY&vncR{(A(3+$jk|op8fLrfY8E*K( zMrSPxpvlRx;Pa*yQjf&v7iT|jzku733wJ?n4eKU4F6gpEzg>`i5rTgT+KJ>cG$-Y! zvn-SkjSSvAndfSq=b?CTU%mF0ORMB2Tku3)9wmTuF8Pb(>p)|(=^Z_sDK^<$!}97! zC$6w<_$UBiBf+LnIseSS&iDehZ7(w<7$94gT->T|zqNhua|SS6KfqH+ldqy_?9W+A zEQlwfHa9KNLDR0G#t+((tVxuoNpWbEm2wTd0v;)rjO-TE`%(aj9->?)X$`isj9Hcw zMdA&N`Zz;RSC4n=#@_jSLJ90EJl-r14f?jBQIb3xwC*2I$OII+yR(2r;xl*yund+J zA=_Wc86f#m-or9KtdsvKyMG8Fa_QC@TY)LOgjDUXdAvE$&IL_beg`%EkP8R+)2V3a z<2xqv(yi5aJ<(0<=3|ZQ^H0QdGgSDidcg+0$jjt<-!KnsY{Ir-8!nG0l#ir#ip^0e zd~$VT`#cM<AYw<(ckxdMYwNlYvHu;;m5Kav9cK)PYazkY92#p(N?9sv1Gaa#!?8q+ z|7Q$TXswsh+80<UifAIlzBGP;6vE`PopPa@j|97u->=lO(c#NpYYHezqyoQ`(+(de zmdKI=yYK~QO6y!ZvT-vP+KNrMT~$ysW-=&Voh;<@EGyqB%i`jNipR;02ejj+Y{nBr z-c_J~RjJl1^)$9dQ--O=`<AX|=e!zOth|&Plae{R6@oUNW9~K^7Dd?eDuo}=Yf(ec z_;cx7W<UEc8L@9F5cyNUOkhPSrZoAYeL1T<`m~zeO}??jQV#*f{_eiV28vZL;48Q= zd||X~GNJJ6Gy!66HtU=B&d0OE!mJuaC!}sP%H;u3ys#6reax~@$AZ*k(Rx!s+NI4e zaeMr;BxHPtp%8z#zuQ`Tx%S(H_<#-~Pi9R49%2TqpPTm`Brv#uH+|^~=@Kopp*hf- zMTKHJf!+npm;<410gJCAJV|1v$)rS71+r5vP!ri#<a#@kXv#Lo1Hn@C>87T4)Yq%O ztY-kaaT(DxMK|?f7nF(UqNpP~?&L0$7)WyE<hdB0mykT9iDiD_l*-iBD)D6yIhc3t z1>BdS5~#zUOM<~@Zpp{4PoM{h8pLoX82@ak9P(xs*c=-PjfU{a=49U61znik5rr#| z6iCK&Y+o~DVbo4XcdUTf1-Q)uK`@Ae$r7@g9U#LUK1s|XHnZ-69^HCLcK!s-cZbiD zEJ)6&!FU%gCenQ%(=S03xMWAVRXT|e;M2<x1T+xg89<I%phb2n$w`B{VGaSPVP!}~ zpoPz&Tg0*0Ny_pt;E|lneMOXtxRSMr)XWO%`?U9@h8A;8^Mu1M<Pp!2K!eXyyCA;M z1fC@R-W_H(QWn_RN2T>{pM4o<bI15wS>HmC<l@kzUUFhq<4zFS36(4SC?)^W>_D4V z)MHUt1K3<VgzK166euaHM{^f+2<|=8A?3EJdV6*oGyD~2z`$^{qWp<L;Tvo(*j#84 z$A8SF_w&izFX|#w78REHUtxH*+mKPZ$3LYY93WZ0nWOk=gR<f>^J%4rOuT-ROp(L% zvSv1w1XV~h>}UG~yFc`i&$c4I?wzQ}qRb08C%L3YmY}&2PagLY^vx{QZ%7e{bh+XD zFfQ#t@8HDvxBRF*3tqbP<k?caj)JYNIEb-@Ya*95FfD5i5kBUyA!=@{VWBlaXT<5s zm6OH~u~!mBh>75l(FOjqyoqaEvAX>r1)H;zTV?AnP8=M5r*cA2MY>#AWSRF2Job0+ zfSLS;T-Q^B&s1S-s7=bTrqo5E6~1;kT^cnzO>&eM-zi+H6NH~9st|ZG-12$DYu1nT zb`)he7wWrX`X<hD->W)sdlN``F8~{)?>+dZw2_Iz(@-Pw)S$|-uN1?Xjf0wsoQ@kh ztc%@`@&NYJjN_5F(I3HAv*9N|+Dte8+8z4~hr=C=*W5Cw75$SV@=N?L*MtBSnyIty zF1Y35*e@c!oiQmWEKktuH`AJ%UlxX}FdjD@L_*d~+ys5f<}_7Wyj|IefXMMm_}M~j zdq~wx8-3%`tc5oa2<=t{T?qZik>5c4@B6fWmj`Faf{zD4!-KAgT8VXW(#PS6yp5m1 zn|`%Ek?;r&>_(VFh?<Q!cqE3%s~Lnp*1fc%PU#obZ`y0vSSmiUeiGf1+yae*#<9S7 zlM1vR;2(y^hzL0JJobx1ypoC)SP#!JKe`KQk%iCt@&u*Z8=JBs!X3`WBs*WKccGui zJ&;3+;mK>7u>Fgz8E00;pRd9$&opWEMW-e3tT{{2*PRYF8uW_couijCST8~dOm)dS zNekz&L?ADGygo2LJ2Uio(*>hCcpV<v=6MxJeJLBq2V|H7TJ1S4><9SO2JP2<LNRl1 z2?EsyTwGtJn;+&(*te>FKw0KKZ#X3SBqhW$#0htVR!2|oirg}M^WVFde;S2fgN6Fc zm{bR2Lab+oV_A!L)@VwopARiOijpdgW&#2>KJbE^e2TV(LdJZgMoysd$fckk2Ga9l zSxrP!6>cM4$JebAl9|ZDkahYDlzoKZOKX%8)0roV0s;r`(|@@CQ>yk~0Q<ii{$H^< zHM#tZf5-G%HgxHx1f2z{b-V!5wI|H_OTy>N?rQ`;Wj@KSOKhEj<YwpC@?Hnw%ysa? zAx<k|orp09wX9xp5S|n_qn%@)tXpNAHqxR<S>c&yrHqr$LDp)3EmDuxc4Ct4Bo<d^ zUF=*Rt1WR~fAXX{##V+3Rb$f0_M#4Os9n@oh`s9JtC~XRoW{jXUmdMdT$cW*$Svo= zoDq+;+X=QTG$oeDi32Fr#~U`VO2XkXR`~@zvL|(wPJ+?yHm>SzZ9u>ntoi3@_>D8^ zfu2C*dYbW|%W31g8g9I}6KDm&i(y5Au<c{)GssC(_<bK}XVqYo1RBX6cwNgn$##`o zPEgK9ZHca1#)o~VGK-zqMt<#qph-{B^AxASbTWom8e-4N9ob=wKgpnBWPk1G*-BGW zz%t$41=-abyz=pEtAfUgo0zevl$)5zcU)3Dwu1-K?MwW%#!Els+Wcz;^E>5O^rM>j z-KOpA07Y0)pR?U->^))Ug7DOe@~HhP$|oRiCJNaft%bED;_rVZ^kD^DttS~9JYoXC zBMV{uN$rvA*ij_W-Qe|*+0d9V&f5V3bCEv4o*;QB^cm!op|irt+@I3h{-oOejkH~d z#-2gqlH>F<keVtMTM7@rc6-`0+eJm|b-(y_h&+X+s;D|7wc@@)%h@y9Ip;QW=LG~b z7%n;IrD*t>+&WrMa~;?#o0?7i>SS&)apJPJgcP;ADg2pfppB2Rh|~~CSs=4!P*}sW zyfh@s<YumM`Qd0o<-SeqN6WkiI>62}nNxWZ40o0m3QnZ2_wwBth1u#A0pXL2L&L)) zDMVS>(;N5Y<nbJjB@UuenL&_yS40guu`5rL;}1A_ONFl;xO<;iE-h+R+|FF`2092| zgCpaufwa!GU-At8z=u4~c3)Ve|Eyg$$wc>#NCN2b(#NxbMb1kHPzo><zvNWNE{Js^ zkGFNqaey40Uq6MFYj+h~V#>mINnK(W*14_W*ED;!l^SQ%)dT>7)>^xtRq}U7;M1E` ziN(JaC5zujHuVegT?!U6FjY@^%U%MpC632{sMy%Z98rcWZzq~r5pAdEeI46!D2Aq* zty^y*R%SAl#|)X?^%#9wZX6%o1xZ5IMrCx0`tq)0U%wR2E6`SRb3YEq+X$EweC@Af z_225DI&*msa{bxReAmEjdQpTA&?_G)0!y4%*kzylur?U)$d<VFn9D#<y3ueEXgGy! zdHF*2q{Zeqs!*$Y6|KpsUedGBz@TwbcZ`aYCGcoAe5ymY@c~$ABG0WW&}e|%l&P5I zkgzaxNQ6)N*+6!_Y#CYAJ}n$u$<+&J0FxGq5)m6E{v~@xlHWPMW+fTrlUUuxzd0JV z<B7`pkZVM6Z)-CyUdxYuld=nXrisGJlxmDB!s;-6&Ro{mqFYI0UfT{_DiH~8#z#?g z6mt1WZP-iyms#`c8H$}RMA$7h;O)pmMLUc@#33A4gwXt}aeIpumz~a=kz_V@ixt#L zA%yrMFg=#nuZb2H^7F>e;&j2X*-Zetft!F0$Ytc3BBE{R^48-OQ|t}*0>_?XJtHG! z3%JCI)xMb3L5d_El{I#qNC_jHJvXm1AQbThR(&<{?N0rS!dzZ0JP2@$+WfHuAroS? z>4O%EYlUAJpV{lMwsSUdgFSM2OT*>o!kfpJnU<pcj-0=%kS%lnuNCaS8)IPI<PRa( z{1`rb$V4==YPxR0Gb)5Gp8}mFJ<eRpFU`p!a_HICcx+0dF1e!Wd0U=Opmd95Tt~H; z5sIws9m59vl;vY3^ODqgUqofbuw#{GpLasQ&;g+(4%z5$#uZo%ao2bK{fg0dLWX~q zT0<s02|8KWe#Mtjt0!6O|7-5M!<x#rx3P^fj-q0)AwdC46c~`=AVopCh=3vVC<qb| z5UIgHL`4)tI*}Tco&W&^LeGFkApt1~AYGA!CLjsLKoWk(&l$(jxijP3xzF?cnUKTT zXYaMwUh7@&dJlFZq@@T3q=C}PC)*V&WF={NL#0<aJ>zqa&SY8k3AC%J6lFoksJRi3 zBV#>rVs-$m&g>|iXsB_lO4(jA;ZFt4?N6Q$i{`bX`~lLLI7b5BRzOfB$aAg-dco<@ zrmwZ_i-NZ%Z0<d-bS48kp#1FRFYFY}@v;x{2h~Me0(8a&#kbHfV3Y4zSsj_4u$b|I z6RjlKl4)_>3~`h5gx)8CzI7)t-|+>d9b>fkCXVmX=hfGc?eGp6&Pgi$h7Jgi?2O5Y z{*nWQ>GJtML_S?Z*j#0wXFtgPNpby-IX59qx?<pW{r8o!1@5e-f_tx8IC>|&-o}ZC zVVCf9vZXAhx(;YZ)hX@tz8dV4J+S}izBAf>57!v&u(a@W^eBFbbNIbQn@$=wC5a^F zAQpXiv*ukrk4vn4sv~q0+mP}PfST9GUtjAg*&qRLm+_9U>y}lRD3NPfef`0WK0ou_ zAI-BQ;-UpNhn|ljGF|V;awEKlcCT-`La#{%KSuZuHu4vf`HK8W7y*Cifa9L{5a_K} zH~PMb(DKWX`l|_ljXQg;2sQ_;wHMNqgT=VmS$2{Rmxco?r`b<HCHp?}_>p5JTk76{ zAFz-$3MC%~myjIh0~PHe8Q3GvwN7nrrTHQZ_mZVdhG;l_^J57D)aRId3iJ=TM}KXf z!AL=W{<$Fgu+GYm@W4gyqc{@NgDH<RZSOLso#RO{`yFcu4-p4+_eV{RH*%wNJ9>GM zi@1!Pj#I%LT}HQzYFC~S4oQF~Pr!<D5d|_+FW1cGp94Ed@+Z|P%L2-83n0y^5&1~0 zWm^(}x2VXD?z-dT<!ax4$5CV{z)ewLmT`;~Iqzw%_1RiugZu*whbQzUheXsI41(N_ zi(rbT&1irW7nfQ{FBPIr%XK4CYDu2iHqYI2=M(Q<d<FLdT3#DTva{eOH*40CQ7x+_ zMZCR47~vE>Ho4CCPQHWQv`Mx^YVMpv99Jy6hw;un2fGKE%1!1dGtr9Vm5q){MQ9(! zlAn}>e}TKmE-w>OMmxard?N;lU}ZD&U$GNH)0>&i%FV5=kMs&83WMDSp1qck#~(CD zo3BmRU1}MSt$&a2p84%;jYs0)#<ED?WdSQ!{ppZ6of8O`5M~rz0GHm!)t!e8ku6}1 zu4td+2um(+BzPQ&oBgqf*2vhH=<@v4^*ywXH@pcRp_C7o`qXzIh)1Y65weZ5#uJJL zENlpZlUZj*DX0@b5G|6KA7nhfx!Z+pl*_lWJ$mnnX;h+&LV|<#EwA~EQoinz{<6UO zu$q8@q4oDA%8AiV*B!TLLpD(w>TwjEr<=pRk&p6Qu=2+(#=~j$EZ>UZ-7XU^(vA~d zQ<WGsaKOsd(o=%^o0Demz1Ahyp{oJ7g=`nfkX0I0ztlQ8m%nA$ru($I@vg{H(eMsQ zt;Yw+W}jhYAM>uCyZ$nc`ItYYaezeQNeett*)R6Fo9l*7tR$OKw|Og~4VrlW+IJA@ zWWH(zuFnz~GqB5*8mXBSgu~tA-yGaF#h9q$-Gd|`&=@gOT6GJWd3$ohv#K1u3s)yF zh&1uzVkx2%qtA)m#sE2}@pn6Zgp`&m%-LXiCNCd{a0vHSti8Q?x(qUV7<zYrZ;jl? zx_T#zwl&c6#z5WHm?x{>9&1^BI;sg3c=AKn#v@esFi*BA$gGM*PaiLXZ9eR|9i;on zVb9P7tINFJM`;Rg05cb34aTT4L@FF}IN=t>F&pG|yS<%F)^fsZ0i?zXsH!1hgqLCJ za;*17=7GQNDjb}EyrIM5$ExS&^*?vWwiclEQJnE+C)zV&PE*Qp@}11}cxU(gK79|B z!-WksJ4COTgMajdp85@_%z;~U4|X>@Uj5#t$7atxf2lJKqxB&cV&(XTEw(V0gUM{x z5f^YgCWb%dK(Q>bl+<vneB6CRj5I}>Bh^6PDiM9VeA{fTD6ze#uj@J81tLX|x%n<2 zQvA^M_m!`@)-|`QSy{J=^tdqAth`KXuZ1S1n6k~+f{Ido-xbF1MIFVrC}?mRjVbwh zx2H-46~bfZAChio?ko|n4$82<3DETkTJ5TJ4_$v;T+~T-%h5V+*lQ3IY#0B^NbYP9 zaFpxWS?zN0-ha3EfMiRfzd)5RrP`Ma1;xk7M**625p`?-nCSGMD2o&>Z8-8rq;b<0 z&KnkM#St4Zy9+E_R5U!(#fiwfKh@<$Tp+zGhJ=T+Cn)#Ato6IvHCOoGi}f{#?a&uA zh`a>#;}Sd$(O0A+Z^pK6*gFl>Qa&Kv6O8e*&SDodq{Su{?enoM(jp~dR_r6FlJLkk zVO4zCEle+^)>+~yLKtlWC2?#MPNLLJ*oNR08C3ZD1jsbU_DAsJ;TA>gl8?p=3P8Lo z?hwEdocwFkiwZ(NQ*Azc<Gv2Z5o*53?;iz#dwk@`hN(VOFf$#_@w|<0dJ83RtQU*M zI9HiKPrpuKWS0`8mD}H?m&2`M%a)!ag4xGF9(?oXiR*BDTjXtSI~}M{Nfg1r&2YuD zD>z;R?4tIE-(2R>*umLgYM|Eu!C8ap4(ScL$mxnOWA$1(ymBgrcgX<%x0&4y0w+|G z8v44000g-d0BU8~t9e+ek!kIMuLR%89#3L8@a?gWIfxwW_k$KfwZ$L4Iv?aHhD{(o zz%uEVjuTp+gD$fdn89NlH!rJcThpgPU14RYIS$^IB+bkWNVTGZ{N4|;ooSJb##JO~ zyVju0qj;?s=wxOIx9Y^J(?za8BddJ@`e@LVE02QU$6@5sWY1**`5AK(c`$W#5^^Pd zMc>4a(+k>RB?B(pNgj5u#oTnBE{%V3s6fn#`%V$S!}gzse?R_;pW_J&<1A3q+`x%5 z$jBE1uwvH@o{xxSWf(K(5=MELqFy`mwQydF`u1VHH_;?S5v;h^1-QJdtj*dADXUE^ z3jvAWQagp)oAUq)y(aL$`%M^ucZ~C1KRdoedpADU0Dbl--T^p8#L+K^4|1n%HNA*! zB9J%uAT;(dV_G)%trZ^_MiDFsC>5q$mqeF)Nasu$F}iss_WAh>+~Lg=nH+@bAs_z_ zWwek%?(iP)^xF73ATL>X&Q~DYTm&u)+5ftfRUA=ECyva?KmZV%9YrQaQgEaRm(~1- zVTIF8MVvNI4+c*eYAjPh>U^8f?3OSy=DA+6e#gn=fK~141aSC02q6B)X>cenXW^Ct z0)m$XB8totdihtjMusg=#!)Ag2Z2<EpAOXaR-?xdj7*NT9k}y7j+Tvnp$T5JK_XBG z5kURnK8}_Ne3L}8V~wZLiz_t>PC-d+V0P450ZurTKQg`z1XR(=@jwR`Uow_yw9bD; zb`#pB95>hs#%5ecbv+91+n{8`=XgSw1zu0Lco}d=dR9JJ3C~EVm-v;XEaMSlrbf0O zv&LY9%oE*e*({5`mnQBRcWw)}xLjCTiLJ8S4KzHl<@2~mYc|n^^Tt?UV|e-lo|h=} zA;b7Z{Q(r`LRO7V#E#yvWYA?6dgKIn8xvH>aV|vf@C2#^b)=MJ7<<d+6EzCffh{x{ zNE?7abCv}t_qM%so{!_&3<1@JV3JZ5|AJazNw~(4CrmjCsOZ{UN6R~z7;H*{M)Cad zTC4@O<~48=m2{tWSoa<IECGF3by*<rqIBvAQ+jxwxUS83J)(1st*A-d_0&4DnGj`~ zdTe@+Rde?K`|gUidvKle%9|do6HQ9ELyrMfJ)i#xWdV?LEl$o4rs^OA0UZUIyfwY8 zLaqT#61i_EvB8u$#wqBz67H0Ss~Kx_Fz0d2F?72Q<c$NT8~%O*i4qdZ>F1O3?D0An zPLDB};B27LNGmwKEMW8kQjX9_8JR?eYs2Tf8(StS$u<h`7n(t`N5;Nag&D?SpN-n* zN33Vx%BsE8K4zPnLE^>R=c7Y`LenwM6C+N9DDaL2a|n^E%&F5_7C4q4a@9-+JP!>k zQ+>>-4C+dK`~0@;4vmOL@>!2rY?GU;G4>3dyDWh4aCDAPY<@Df3HL}mci-dp_JmkP z_+jKkOPXVChqs%^h{-+HYld~h;fM_RmHvnG1ZUHcTfJfzNUk6!J`6B@DECF$*{WJn z8EYnIKP{0_zN@q3`kiF~sTo-7AZ8F#ITD{bOs^iy<=j-Ti|Mu7I=hK3=A4~UUG{)C z4{4r(wRHKmpU4}>#>(L{%ZPcIJR(Rv$vHN%!0v$ijfJ8{k0*R-vRy9ILm7@pdWL17 zWyadzu718OTgfBMbJiBp;*gMGAAM_I$9qTHm6iqU@j$E)IkJjrXgFL^q7p>NuvNR2 z@6cpW^x~SLL)41#lcSW;J}4>C(_H`S!xjDSs(@;`Eb1iYA&5Jja@}?_LVC7ONoSsE z0HRW^(Ayz`VkoRj<B+5w_(ww-{P1^<;YM8tE>zIYwwdo5|Gv>(Mb~E@^R_Xp#z63O z`K_N`MLXVt3T@5#fJfgl{h$i_;h_FhC#jxpSvwob#6~HENQT2moiYOZg54&0>+o89 zF7~sIoe#ljevIBwL`L*=ookP)Hi6E5AEQ6|9VCup-CVgg$-9d_dx((#GNavkM}6@P z$^GG;!)v7ga@>0R+-INP@DBo$Ps0JoR7ak*8SSJB2WDK}VH{Z33$hbfdE=bQ4<84d zckCqVULlH;!>O`O=+0gwjrQ;CY5mC}e|46bWZo-b)eM4+#!7U2ScXO-DPhEtZJx|L z|FDi};WjB&KdqaD#?}0gmf^RFV!Y8a&AE*vrUx)vLB^y*+)QPRf@=x(RB^jhZROQ? z+S~Oi<jpG_^qsDpVy}S@=pD^|n+0j|{4EvvWz2-%$_QWm?YDUT(`^6Q!+(VQi=EG> z?Z0)w@_e*`{;q3)l5dE`?%NU|<fR_F3Jy#aQz<GuA$B~z2~!CXmU<Sqaa!^IF{+D7 z4Y4P3Qa7yTkY1-kjl=01rtMSd)rA#j-q~o@MF%f{Zv&E<+di|~G-vFTHJi``o82IU zDWMwe+c%-_{<6Q>IB2i<OML5RIoDe#6MH|&IHj7w+>T20*xCb&J!R-gnAn?A&|0dV z>3%{AX|_Nv=V}b2{qe2d`G<_!6($0ePnF$kukTpxJ3q7WKp0R;c=WrN{u?IblX3i3 z68Q#lZ^3Lf?X$=J8c6!>zZSvnyQ-UYRY&3snHu6&(l27YnE-ZRWDJU%b4^|`Z(ot! z8@^Og3l2>H7|VEO|Egvy1D8sv){0Vl(-WG-+Ix99nL6*&qcsrLpwn_6%)x4PjLShS zVl5;a>9-~|W5Mr-EdxDD2^ZBsn+@d_fkF+MvtteUd0atti*L1uYIly!#Kv_GEgXYH z8d(++_wM7{KC`%}F}`oBBG3aVW>FkJLZ2-+b!A4Z*V?8uv=^aUzi)bsM|gh;s{V<W z_TSC%FU$3hXt#fTXDo-%U{#Y)$oF80Mt1|xfkSw_vmDPUeZOy&^OQ2LzoiFgfkqw0 zA&0T*2)j#<Qy<*3-fc?e?S|=Aipu0Wf*<eo1I~P(2GXhmNaO#TY&#@p5bZr+c7v)U z^yDntr%y$(0$x&d+SN;@Kb>fKDC}|SA)}J^S*npz^HD2Ht=%=1{<>Rknk@VP1${CR z5$;n=i^jt(w8p5DJ(;sq4=L^x=<w^y$iB<R8cgG$@DHVJvj#CB4Z=LgO0-wAz9WRs z8Q-W8=yQ3{-E!lI*StAt<xn2x>-6gn4EdKy{%fxQNO*h!%>MN?f9rmEvVim==1@Mo zmlLU3ts<M^J$uLzr&AqsHb02q2VSb|uSBZ^W{|B}`<bhg=nFfy-Iv~`%}z+=FCY%T zPB_U+PBzyVwANq?70rV|PX0haHW^XEhK)$^AEA+%$bEyeK8b|-p7>WnSDp|LoD&q} zo1>s(M}IBc78xt^9XYO)%4c^nTukL^x@1HK*1dVNl<Dxi^L~-tX0JU+bn}M4Bfjw0 zbE%>7#rFRiN&G5j{#%pym7}+Kp2`i$LT0VoC$Ekz7#pFt%~b^!NIQ-nK)de)*vOiL ztHZ-G_-EMs^o;~?tST$I8(DtP)i5X6TJ5ydvVfmeQTC35yvd69ZM7{=fC>SceZlT5 zE0tdi>nOi-(p-ecth|5w)$NT8h9mi`hO}y~Y=SEGVs^g<9(T%)4Z~Jrh|=RPI_7;} zk%l2ddFdam5hn~wHVrkXN<Kw2tkF4Yn>U$(Hj<1xcmUw|7w;%5fUu?4vJ867T79mP z)NjwpDkGz}4-S9_r0*YlvLVy=ggatpe~$+XKv_8wY-;neKmz|<6)QC5X;MLaW|P~6 zb3fVi-c%4022VdcNbUd+z2@}>y?`uUrP?{Ssy1hk@y@WKK?|dK$J?`N9dxeVoB8PH zhoR{Er94?`4`{vuM;#qoL`kbPT{|0cqV4$7sX<5Bd@{&ih-r*PE#!@f8L&kXceljP z0wkmfrB0<HY3`#T<_l(~*wBI4_8WAQ#z5r+s5#m0A<!S(ln@D+HjBU|XDP)N?DF!- zJWbr-=Nh=OD^^z_T(tJljJpXXrS?03u%2j+{^S7u+Km3x!G1=R{deMl&kQgl&4c9| z!ff6%+ibUGhOSog^y1BV7NI*qa4lIh4DD=BkgAAmQqjetiqiQGgFIJCl38`-ch%Hq z$C{5{E2HL=`fIBSwzNCEGupq6K?PmS5f6)~8}<A+&?0~W${EyQx!;f><R*BUfHE_* z;<|)MFK<arHHT#-sm(4d8l}#WGs=Yf>SG!m)zmC3>B75aB(K<of^_T&02n<Yts%Q3 zhSs8j(n@+)+|hhUn=rLcV{hR8Wq~vc{3amm4*=YVG`Zth1p_T-J<7ILwPzbu>1POQ zK?L_A_N*|~b6UN4<<`hM;&){DY2<Vxi$iVLiAnItHoTf@K-XE=ywX9Rj>kh{8=gs> zc-Mvb0s0D^q&#q;6=*=e2rRn77<CQ*M#0!PF=0We#lvq+(xR*6`Qb3<L`<ZH-GN6y zrN(zCZwcDw;~Lo{$$iO2=|4hVq=*Pd$o#B_QNDtK2`M~V`7Zxt+`R(~%+TwwV%tM( zt+OgGA|05<(#;Qgk&!W@m<Uf$%TJmC_zm?sD~Rz!qH#epNR%j`w0!(eZR0C9@p<g= zJJ<A|@UZ{VI6n^HxND_IGy$Qka+=_RN%HA=mo{($dY*pu)>@zQGl%R6Kb3aOktp47 zXejcLaScopRRqIai|-rbMr;{a#JaCp+H6C6y(B+GFeR2>A6hr^0rv(HjH0LpO8vw5 zTLA7&0H&dOp2k{$b&%xTRlAvEkIKv1Gvqjih9QX$gAdlwA71YSR;&9mK*k{3g#eq+ zP__AiB{G!Sb1O99kXz32cX|jrRWj&j{skA6Wr4VIe2c7tKkCK^Sklhwikr$}r|dzO z(`!~KAYRlv?P{wz8Kc1&3#+jP9UmA~**!Z@I+g0`qj+>NR!cPEsV{ydA}nJdh;=E* zfhB@xTs^Y;es!6gwTb`Jdl@RwGnZ20t_;b+Qjof=@kuW2p-l@zaMrs`wE1d|i%QAD zIPEaXK}2qSsOb(OVqe73>?dPG1oy92`naIF+Amw_^Rrno>#w6BKw|eB-nC^T_syQ= z1E;|K1E(NFMmozhRtplUYrYji>G)wIgf%wXe3ex^Zpah)X%0>8-d;0sW4pY~80wBw zLQ8c*hekC()AZrx%)kKS$5V;wHe!yUXF_HrR#fuDcP(g2ft>aeccKjED^P&Iy*^1s zb-{DQR(-+T2x6<Dv+X;zom0N)1IN>myuB+TkaU?zD#-Dd8L?P9l3D@WvLGtHoJR0o zqF&sJYur72d^az#=->0mAB`UUZ|7;B`Q=}iyPgE#2vQy!O35SfJEvzslN4JdhGK4- z=X!Z-2eSmWVQ0&dk)T*gKHm<KhSZ>_Y)kY$>QN%3&WSOUGTHV3Q}lHH?KL4Ci<9E@ zGqgJqfP^j3SO66h6-rTULK%;(fRkusD~-6q_=jwd#20kJnC{x=#XkVFbzNr_4!)_G z-I2uyv;qLg>k(}pKszx_$>^Se5%hDA7M!n(bTBD(HPSWjB1nTHk0Ix*vm?sI3>(*b zDx9bCE<tUAj7BB+7(f6c=sv(u23W+v&5e*=F5{JKp9%cHG#uDr>E6baX<6sR%-U=> zKb)cGC4KD*y8Fm&mMKZ}ik`{5Mv0s`{NFoE|KVH7&U(*`eaj&10-4j|F7uVuX_r|) z6j>lsb9@d72JKQaRUD+1uX=0DU#x)NL3;pVpCn1-k{;W!WN38^)x6L{*Su{?cYU&D z6`n9DrCSH#3WXJ4`VCw8)iC}AxBWlL!+v+_0K?2X(gMb0TULg`TiurhG&%J@qaTh( zhvhXWFP8RvAJ93a^SV}&cNgjrMUsQtmY27dP6$6lJ~0*;7?W3)ic!Bl)X^YTT1CV0 zA^`>V|Aw9RpCa*p*d+MvOJG4v1E?DWCF@=TR%7-=fY)M=I?+|Tq7+lKnpfV->lQ|B zvCq{7bkBZNv?z6Cg<|)F8nMrS3M+26x0u~_8}F4{lAm1ab(qP1%RP#3{dTYYAH#!R z9)|Qk%U`~_^M}yW{RR_wUsu1~MrWa1x67e7=YgD0VT%yZJ2`tktgwG=GygoxH{X?E z+_XN}5A^mrSeBD-b`!RL{#^AcXZK1^k0Ry8m-sy_B2ztrz`-`DTi)HSh?Z>`qpsSy zSQu53sst8Nn(anAlDhst2I=nyPk*%3@IS7o|Ba*h@7(wDRssJnc2ZK17qZ?Btd~|l z(Wo4Bu?=`JGkx@o^*)|xHeU4-)>(f{7W^_6ghHlsdaYZzT|!CT75$0_WOg2RiqDci zsNn46`#uvEx!?v5pRXN&EMZwA>{Z(At^~Ka8oBbvsBLAJPQ(mcRzJ`u^j^}V_q6n% zsmcBWKlDG1K)=}A_FbezJ7{4=SAMBrMlqIJnBT!V9kRYo{Jqo-9{28GrKm<fsS4<! z)Mpw~WU1Ju-AcPnm-GVF=NF|?-Cvs^0%~#e0Llt;Puot%AV7F!R<@DQgr<<>H+VG? zH*+F&F?X#JVi;~yj>NS@iP4g1UQVApI+vUb3f!0xzxp~LR;Q3NuTTK_Gi}RnoWy^* zBJjnOeeuzs!1TkY(wL;5$hfh9Eo#K*dK>MzhOjb%oKNDUxV`rI2;msLzSs#1oF^w8 z5S$)pp(H3p<~YxAlFXH9y*<^HcQ<LTi+>%qsd#I-lcSEi(3ot_dw>W>A;=-Gk2D1g zL>zO$4A>HHtxuIW+v#?pta5lbul0zkXF#3aaO9H&$m}2K_<eJr`qA;cl7s#8aP1Sc z^bHGUDx}O&qBa#;ZL7c<(@VN*i?Uo2?&8&|GY#bI&bLLk#>FU`!)%~hjeMOO)UItk zA%Hx6-b501MIg=&#H4~wdOnN3d2f3R>HId(g@4Jbd|cyiz`DOmNxmfp`pV^h!}R^h kwZG>!fBC}`{~wI-3&;J%$Nv%R`gcy1FZTF9`ncTvf5WCKcK`qY literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN003.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN003.png new file mode 100644 index 0000000000000000000000000000000000000000..056545a2ef8f7913e49d5e19f9900130325e69ab GIT binary patch literal 85473 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%0DZORSF-i9;JH@GXo>#Ao<PS8so;+v_s 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN004.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN004.png new file mode 100644 index 0000000000000000000000000000000000000000..2aa065769b4ba9be2a81e98a0a684c7b7f09eec4 GIT binary patch literal 101057 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%0DKLh0 zX)%-4t#p5X98iycbSMd?)h)bFA)wX=>f}F5W4YAPoDr)Y_~`SZF?wYZl*IB}QiW7? zy!d_ne5^_?Aom3)viUpF#*0P&nsReS?=bEF?e^`QN+&D-=Zvp2k&`cDgRR`^RRmB6 zHOzH-V7<uXG-uo%n%2Wv+m+_1;eYrB4>N(7?88is0T9F5>Ohv0kl2rW^5om6Jh#x7 z3y50<adNlrtv{1SfQO}V{I_9vry$n&Y=aY153jD2XCSB2>z@-3ZiD(M5z7D<J8md; z#3Sif0#)Yv$?DiPAFSjvW(cfCC${C0&*f*zDPFFd>Sd#pZKV&{4!+6CVksJ!uCRQ! zFSk&^f<ZdUscFtAV`yU))3^`(S)-^I`y9ATsa}a5$>z&z_Svv?&kY30{>RM^x3|Pq z@3X~<+`v(nkXN7=O->s9BmlmfIB?rX^MEEn|5H_D)5W%52f{5YDBtEV#Zt98=4$HF z7C|&@D2&fzJnKlbDSo|`?{q8&$=d0-dRLYkU~OyT3ZM}0K8$axF3o7)=3-fGiHTnM zn(1kVnweuA4LU&|PV($lczSgyL=Zgw3s`{w5?p^-uaXw51&0Qqs;Iv&Te)P<M8lX% z?|ymDk`d|+`z3}CQw|`%@D*Nzn0c2@-UpWt4T=xPXJRNs4dC1u_ryg?kPi>O6V^@E zlx%_Y;HaQtJ^YY{wNfxgDT$cfTcJbQ*$1EmkC_om0f4ToC&*JIWQ+P^h@@spgVgj& z?XYVT5@6phj%@9eEG?8q<PT*V(VYQ3ljoxxyBf4Cs$A~jGY0m-F3*O;JcL`~;U(4k zf<JIX2N1vQ>MYTh&xY$`o!*N(H_&TDrE_8V&D9AI3X!+Gd?%0-qK~O1``tdL_#Dbs zL(YT>++1AqqoOG<eS&%_>rOM|;CbXNPNatBktcuifodO+poQlSxuAA0oXXW9Np8Y% zJgP^OR|q&bzhG(<?Z!7s%iZJ6GD^NU7ey?wug$zrtRzP&{G-a0z0Di&O0i_0RipGD z;|PS}=H4ad<dm^Kk!-K7+OpDR7pUvHmx!BdXz9sg`{C*r=5NB&6BZVJZkU^7d#78O z+P!qgu%qV?s4EA=408E8BnR)W?_v&F79rU&P~L!NZ6O@=!5NU|7{jM^*K;30HrFvZ zg0OB^9O@Z3@Wml&VNWJ-!2YXmdQ?Sb?6D3#`0VeC(DHdtfQFDpApZJ&wV4CD)U6Ao zw5Pug4W;le`p}r|TT8;fv>9LwnZH?P|C75)$UL|N5B(gI7shM;6Oo%*F4!W73L=y* za{HGuJPyw8NchXo8DW7+)O8JyAGU`eum7BL#)gK$(VlIN5rbU)w$8VNduxE$r1s0~ zSPMHS?W3<y&M~;)|0oR$!mr4~jHE*#%i<j7CN{WDPfw2;E}NVB3FQNqCnKa$<`vN| zp{yPle3{Eh2n1gOsV)B89OzRdmm{0|M;Rfp9oYysVG_E?h(ZkI+1&-2KVigwn!ZAS ztPPDCt^R-1YT)q__zA{De1YWN(SiI=%J;`!gZnE1Cvh_-vi!*l|4UeEe+jTrAQAS@ zY5xIEq4*%<525aJ`|p{5Y$=@E<nsSM{Qv81X}?3xiuNTJl^_W~0Dlx^Rb)z~%tHSc Df?qO* literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN005.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN005.png new file mode 100644 index 0000000000000000000000000000000000000000..7125e90374a87e51b9509b3e3434b81f701020da GIT binary patch literal 56302 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 IX5jsQ0P`HaaR2}S literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN006.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN006.png new file mode 100644 index 0000000000000000000000000000000000000000..313d57fcce0bc9fde938db0f5ae8fc8141b209a7 GIT binary patch literal 88663 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 P;E#fg%8P0#(~$oM_BJk^ literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN007.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN007.png new file mode 100644 index 0000000000000000000000000000000000000000..e5a627bfe9a9ae16608e4b5542bf43e6366a0b42 GIT binary patch literal 174802 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 a&sA1l!VW$6oX?xUOG8ChIph4byZ-|;%zxeh literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN008.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN008.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea66edd5983a3fe5b55c0325454b795a587f448 GIT binary patch literal 74675 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN009.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN009.png new file mode 100644 index 0000000000000000000000000000000000000000..95ec7140aa78d0d02415aa3bcaad4c2364c25f16 GIT binary patch literal 88702 zcmeFZRa6}9)-H<ExVr}k?iMr<f&_PWLU4C?NN{)8;2zxF-GaNj`zgM){`0T3@6Pqv zV{`_gM$ujU_FHp4Hv5;Hj2IF;K0Fv07}7WKuL@vbkOW|05NaS8;0V0YQ#<ej++IQK z3t0IW;Q{aqoQ=4;Js21c`ujg{<IE}GPXxifeHBu20Y6TM^}w9H?MI=Y5ES2Uz0=7< z0Ey!u_~k%g(`QldJXGF29zXZq&IJFYHaPQxP=LmShJr@RyIYNkib8$8YIaFnTwGjP zq-b8e<n>5cX|&%>I7=T{wjXW`lp*+liB1asUylJ}h`=ju0Z}ms3c>$+gn)%3t%ClK zgF<A2hUC<0cr<WPVE_35PKErxr~cm+_`fUge^=oD*DD~%hqjI48&1GARH|O{y+48o z9S4W%=5RLl_2o&j(Qc>Zqs`;Bsd}ZJFTHy8S5{WmJo#KvR=p0eZxRxhZb-8KRaOP_ zP_wF{`%{Jn2cvDb`UXoX+Gv@HM-)ocSX?&(alX&|mfzL8d78);wp%nx9DIJbS{YL= zQV<b%y*E6VDT>wngd*+(^}i3&DUc1mGO_t_vT;VVs*bD3P$CmkER`&Fm`$m6vkI~I zv+dx}P>iN^tMcwh@>cXvysAzSB2t)Fsan++PU}^AS-y*a<HZ^=#-{xb9A7qV(IEf# z$$=Ll^#k?r8;C>ga2;3k81#U+UCy&wo=%%tzYn0&XgAfe@-;b~(27M8$LC8X4izaD z&QJ%9Jp)g;Gbu(A4}*kH?VqbrXQoiBMAOMpR8++3e5%D!cG!i$G?RFq`X6t^2kJuv zm>B1!nh`8Ap&Uz^{TMefOS=1MBdyetN#MbBVM%8FvRx>}$B&14H~db=YBw*yE6|Yl zo>2TBE8+*5SQs!g;;>kd>-9NMRCze6XjhV(E|6Z4(HHszMUJOZq|@3oQ>-i*o=~b; zKjxOw|6ltXl?BSgV!NuC*lnNeo4B}KXip-8W&!puV`Jmty-aULwQ>3EFVJ|Oy;|t7 z=&9#}zO6JlYH#e4@Msax?b<&}|5wY6{^GOx`%+EO^XXRk)cmaN$?9Mt+dl;x+7R-H zJqVeI_U&QZJI`#kxLj#!Y6@zPj8ZbeAu!cjZv}RHAewwvZ)t6%**Wp$>CQcEsm?r6 z<IOi3-K96@KQ|SW4A=>a)UQldqY#Zu0vE(8Pw4P)zB%t7KMGo2ZkH~v#y^+zZj@=( zCjc8`h^hVg1Do+!oJyI-V7l|_fdup(=|X6(T=ti8o2$qVA|bzpd(t&KLGWStJ^IqH zrbp~iB>NiBd)cr;gevuIp#GmS8(o3%`hhN`2ZFHX3aAn64vT2z(0kWSShyzV>qc04 zzO|&(v7B=wZo8~x$UR2!_xCQHu$y_y3r{^V4vnqxaP#|i?sTz@%h~j??M+|#-J8!G zl3U`Jv_4wzAlEXs&c-$}o(u)pk$x5l#a6y6uV>{hlI#H=tYF=le=$|H+Ez@YiE}(C zliF<`UY;`&il=FRW4z)2btwqp+Q(BQX?<7ta5klxJmQ_`S~UF3s7Rg3u{vbwHRsYC zJh~GRa0m0sXv?(k%=byNSF6Cr?fv-Gk$Ud1<x46g<jmVI464%KF2_CqT!M}ADC&U3 zDv;84KdBpnwz9LUR#<EEY}Rs|RkoYgb}oXs_Pkpu><YzUDsQ_m=pYHVdQO?1K%t{b zeHyJlp3dG%{$!i;e5CspgYx-VuF2sb$KU@FDU?L9+YHZKdMJT`AdVfE1`g_r9#B$> zC&R;8X(;3-pq$QD8E`GFmK&<}odt#VejW5Pg4gl`pIJU9QMr1}k7GYj)^?LLG*eDo z2b|5Q==zA3s>MR35FWnKP+T<EnulU-HaN7DZVJ0;%#`Qr!=837Y|>QT&F#t3UdZq> zq`RdctxBm0@~-uNLC2re5bT_na@t4p6{@PacS^F*tYX1B^Z_IS9%>^&&|PHabEPaL zC2P1%Pr$C4wJyP-LotH+&&?Pmh>HPKxZt5lgcg>sR#XeeC|A$S#+;Otz4=pxvLrW8 zOV;g<fd?cup`oVVq*K_@EN;cf{u99Zic<oJ6oq5HK$?Jq((Gz?l-2Stdt}l&HVy=n z@~&&sysmev2H{Url^=J1)UpcZo%Fif#nGe?{A~lYCuk^8k)fC?{y3fd-H5{4^@Ymw zc(^>oD@sQ~g@ePS0H-hL<879Rr-e>NDj*VuY7pc@i4VWQv9aX+F@jqs_*^qCfZ>wc zCEgc?$M*eVv)2qCYtAAmUnZUBaz8hcwmV0$P{wXrnu|tOg~a>0>b;CI?6*Darj8~C z+*tE9?CWrqmQe4q_KRwdD7&iREF4c#m$D6w^g@Bx%HNMg{3=FH{W1j<DCIC>ehtgz zyX{z6_%I|7QkTZ-<3+^`w?i7!`SNrz+PhWvip%Be9t_z5;F?Ot46hA==3vGqcyc(q z)y0hHW6aPHAe>Q0*UCKdu?ABZYJGC__>wIsWGp9$4BX|dbAV&+ymOR35DGp9Y%XXM z@0Sz2R;z+I>B4(?gWRAiZ}@WFse#}U^TnUwh~fE$FpQ8}K{O1PjMw>8$@{+HBf9(d zNRrPo^YsrlBrGA%<Y0S9%w7kNoNr021<M#6eI*W_sqS7atln^0{x&Cn>wsU|)$meL zfGy<F0e6i#M-SCx1>Rbr1tO+4J&Xm|h2SYj53<IvKZ0hD$iyM=%LJMK>UUhC<8R2& zwgnrZV6QMXp9}KyX~-86t=Kb!gPD19D_3W%Dr!vV?S&G5^@$42gH2QYvsplJzB4mQ zvkma^(b))r*LvScJ!NvIl<u|Vp!7`Ey?Q)dulFbYhD3b}o1M>eij;~JI?{WfGcG_Q zVBz7QQuZIo|1=*`W(YO5D#L!{+1$`N3`&VO&>}t?`(dROWNQ)bXhD>q5QdMY*Y$b7 z!MK2^6LYcsW)EEF9Q1uNyE`Joe$%hMYg3D_hGo@K|7sytP?e3eZVs_AF?nt`hh&!5 z-4nhTNTpj_13{W~=UHH&^)pg_er-H_CjxXF!Gtdv6wC766CD~$!okRs3m`kB2?o(9 za5lGpZc1N2Djyvw(A=!8L-zWSKR2nb-$$T=n8rin>cp+1uMddYJoJ4%c5yZI7lwxm zK=8$8&<K!JNs449^D&i*@=N0Md$`cTCH}|-QIj2J8Ft>=wBJ4`SFsTya!R=Pvsc47 z`P+Mo?*r)_f&y~!SyV3Q8R0&WW@VxvD;32c0H32Bcz9w1Mu*4uk>EZ*HsD1d!ClmR z-4*}&AH8_*06YQvh8)2N<f-s-<niQQD=IDUS6@VULZ*FHgQZhBY3d{7wWP2a{6H2f zO&lLz`o-k1dX-cre+wHUhKDB=-&QixpNjF<F~8p<BGBOY1oHCX^icmpM14L(*zb+S z_lDv;DQ>x<llpp4bU<%DfMVsN|3y{>fvc;Xzu4-BjT`L?Cm04g8VyjRqTw(;il_59 zZofXAp->~2Jzowp4G+cB<x3^AUOr!qAFW4u+?}py7AqBfSgN-kS9D7fKtwTqZ#Pfu z+cc~?QV{YoK7FEbs?4GPL!*B{*xWqaE?KAgKfj(%<_5EJI-M@l04+7)y{HZ?bkr^Z zz-XM~#A$ybd#cINy!{|Jwafjim5OWG#-HzTKlgG%7$s2iHi-lsL<cNWS20f#-oMK) zh|w1)N{hG0C<L5R*o<1#6|J`^S{@g@R>=buqiX_>`{YI@df%bUU-TLRrWQKf7?0DW zfwBoA0+uY>kf@Gkqcc4FyFf?opAhnLy#^8lgU^9KA$t*F13Ol8O)q!Tl&kelIJwgj z$dn}#quNHzhmiO+BrbB`gubywiC>hKtCXemQ{FfG#xZEl-L~{YH-aX}Y0p}&BD8Ee zp;<j29p3S2PZ5iM;Am2pQqEVnr5P3xdZ4TyJq?sE&;6{-BH@)JCvL^@SEibZtcvAd z5fpP{5S4jt6y&ozq_wb5NlT*#c7!tTRgmS!<f^0(6Inu#9EE%Z@S|Np(7rpVx8i41 z0&#CIl@fDj0`yOj=~2p>cf&Pn&$Nkrca0sWzmyj%_5JBJYQ<BytQobN9HNJr+O?30 zcqnu|E&>^1D%u_;4%!|MOD+M#C$Tq{p08GA;O8t8`%!v3n8ZtNUf*oavVNr?46+om zQ?$l;#WAsCr&1Y!r<7{-`czkY<End6q5z^-(f}}*sw?La3W<OgvB$X(RzOQO-y@r0 zA7YJ}+G|j>FY8AN%$5y;1fQfL4=SKrtwpnb`PV(GMq$%~+uLw)lWa#Z>NTEy(~L4` z8T+IE1HSSP{$kscy7^+mm+&GbC%?(S&#(8wKSon1wVR!kb4lvgyqdKfCPgj*kXdY< z7JPAjGp{>5tE$V8D;lnli#E=Gm&SLyU`Raq3he4?s}-KebD$M!S299p6vLnpmxlc^ zFK-l00KjUO{=JEivFK<D$E^O&Q2Y*nrfoeX5*f>8?*Vvvjsh-|yIB@x41tG-SL_Vm z`VF|h#_c`Ae4s8R^v+gW&G4b!sAwqGBL!u~Ox5p=S6eX1!kN4lNrM&GJU-T2Y+1RU zJYh}cX{?@(qW3wJ{&A#xkfKYIF)*8&DN>wWqnry8WHyt_6-7#BGmg*@R%mr|T%ym- ze(NK!9sp3S_8v?1`Fmq~*vn)BE;6?L^-=O>PFR1r!FDP~1mPVrY4n_0(_$hfuo(7% z5QCu+u*F;5ZnO?M8afT`(a1%`GX*?n;`Hflf=^>8CBFk(39Vj`@Tpag7QaBjwyCJ3 z_<{T<(CDDhtV+Kk85#mNd+|KbKuTxaToN(*U<v?|06KGnPh3tP5uluJd$b&=zPe8Q zyvJSkadv3P`A$1}&*cjixG2^7V6kqyS8;ZP14}w=F08D;L!KT|KO_pDUTQi3G8*yl z<@`3l4YxXcAt6+olCbmg^}B=2D4;|UMFsU-?$L267uHV!c4o`QZi7@Vq9JYw5HVJp zbwOQukr8fO0%mp-i?34gA`YV5;j}p=k;(t+Z=}BGR9S@*+Q2TgN}g3LDv(OvbPRSZ zovnn&cI#H_{9qMkp$1L<F$$mtnzF8h<EdP-f%<MUKoR5@a6Fn*-t&Gs;fgfJ10=xp zOn_NEv*p12Q&t5rF$8n#ta=q(88<S>O=A+0cepaD2Yd6BF21(AwP6+~N?$ngl#UVc zxyUhN!6P(3-Ja0lBF#hOf|292KVOEXbOjVCt8_Z52&H$HB&=}n9}>HVsoi6QH3;%J z?5`_gnTt~c?a&v%foPxDbcFsPM5rQA=%GD>Ey2OtjbCe2t>qDVJVoMANvPP)TD557 ztDRR4kN%4Da{*9~+x0T<u|qSCs}sVG*RVU)%PX+krW4lPM~}##i=|@cyrA0#xY=ZZ z63Um%9Pn=v3Gs2FS%jf6OPMJ7Vd-PV{Ho)(;3QUdurIRNU2XWQb2pw(C-s+uRG9;G z6)l^NwOw>Gd>KB*G%mlp97;vQ@u4vZur(C{^6LRy_eLtpI1i~$V1vz_Smp|{o;)Q5 zltcpkL5e6^3{)}*?pb(!hrn&nFq1y|4!bOxP*IqjhDGO;6ES>a?@6bW(2`WORE?}e zrA$GmP)|+|s#B)CVH5u0ek*dvA4NbeBlFn756cNCsI-P#qg-ooK)d=RA<88F*>*F4 z{KZDGi=9n3_tQp#?k-g|oC^t4*s&eU9T|mBMlp}$VL%HPZGgyk1vF7G{&?jQmGDX} zw&qDeu<5*vhC@E}=X++?)5BA{vwWhRcmlU!Sy>$d`yiM@#j`RNfVEcy!CV8xGlVIz zjR!R8z11J7+Fa0nzZq)AW$$9fI$W;Z9M@0pqCGR!U~71D)qK{5krqke+Zjx>^wJ0w zk;lqXu^|n#MwfXM`+v1YR9~p#gl`FSyc`Mgo@3FHf9GOjT(wY%eL)m#Y>KPiZ=Ugv zmQpTsVsEc6vtw(LiHvnC4&zIX4`>nmY|MuWMGBOSTM@i@2E8Fej*PeG9Xv=bZGM_M zSJa}z2@JDs1h{oV{V<|%=aW05ksd6_=s&R`(nPTsIMjW1#ARg@`Q2~DA1-&eo8*0N zI`YQR7n&SPQbc<v!)v7OOV&Xh<mjAr!m@UsWVP{_^?dXqLmqFA+yevUy8+zS<TP<x zY?8L{$1+t9^0Sorb^Sba!G^%w^Oe~UmMDCs6GSfTf<*-YS^o?Ifc@_gFKn}K?w!ur zbs4#!$3Ud=`Y(6_NCQu}+r5P<!(atpUM;DMuJRq+PA&vQ%ww%KyB!H`r{kpU?QLqW zAL%yF;f^2GDkI&aa|t%ogeMaVzw}A>&q`0KR+#P0c)uL!R+~(IIGD<pl#>KG`<zSb zl&COpU=q#r;Bo`VtkUhqtS*RpqBjFMr$8bA{r>5!eYSkiMdsk)Hk%f{U?<Bq*r9uI z0fdE8pjZhtaV$(lHfPyE8mcS=+X1|5<%^5*^FJ9N_=S5GCCg%yQWTlokUkBg<p0)u z5Z{ZVzl0w4e;>w&n^^ey|K)4~W%fC<pTkPECi1>V9db-fh_)=rT2N>{M?(z_4WJ>G z8vIeH+IbRP1i9SCXL`+hG?4SS$%a@M_YeXAYh1JY&9T6736zVK$dJ%M1Q5)e)D)<U zP<r=M_ehC<^#t^;yJndKp}vUtO#l8Ol5+6hJTwdqs6U2S#9^DnpS`r^O4Z31to^@0 zYzTt2O#@{H6IorKSX}Vr%y*@*>VN>CNhx5riybdNTXlg~fq#dwLfk{s9etmGE@>9L zOwB|aibDov^Z8N)pDZ4Wd@(N@jU0=JtheW7fIpo)uR4b`m7Oyu3tb)R-<a-SwhTz@ z9qLu7BvJj>;hzu?*P`*k5<S=1u*5DM)`)fH^9j-9Vs85<OZBok?k61T)!%=m1Oc3n zJb(U=r6!8@|G~5KfcF<2jNhHsUzq9j*Ba3u2I-QS6OaffTix#xfVLo+%xXlz&8-g5 z0t)Nan*^z}Px7LX#3x)jwEw+QpZ;O&e}6?rChB^>%$g(O=z3HgueNHIH}2wd5z%V} zf<p*zUG$SA0%%tCK~J~ErD{C|kT1UhtzowRq>GtfTtXrSC{5x3WA0`T9#JVp`>kG6 zU;|mFR&sOBz;wGHE+vJS>W+@!uc)X92@!Nh#A((0)631RX{qjBQ~04$K8;BzMZEdz zFZ9MA(FqCIQL0SaNC(^uY`2+$>d(K3V72@`3)Ac-Oi3eMybZ3zcn8PER916sWaj<T ziMuA+21Z7d3O(Z~(@w>#jr3hG(U@PsXoN`hq{4YDmp>MUkM_zK8yPj`GaC(II-UX) zz!{<6m!(W1y?HxEl5Y$e{d_Z&sn{iKGDeUwm+`$(ex>w9BH&EZX?8j>&CMo^-$BTe z<8?ZgJA-Y>P4jZQ-p`J?KW#p1(eb}qsnqY5c>~bQpG6k@&BMO{pj*svMppwWTgAar zJS8Qih=}|7x{%oXifuoUOtr1s>2jmaR*778*8!PuP#ULJ*HWL+$oKPxIc9blE|ZD% zcU8&x5hy8E^Q~87yo@i!$|V_`h(z^QyO4%`0h05k>Lc_0Q`X%-7003YaKe&l1wzL- z<7N50WbM9pyYN5@GZVqvy`#+xkUf5;_iG~$p@2sNx7rIQ@eC^<bvytVQuz!`41o`o z<zIp_DGC(x7vD+8l4qbz`PBvBs#gG<VCi6YG_{!skU&)!8`dFIac?!d_MdA_r?&y{ zt<<hrYqG(Usr&iy?(D3p5aZVM5y0MgUN4UZqf|p?Sk2YuL`OF~%S+BcP1^xfUx)O* zeWXuPnF87XP^VLGu*t5qTKVg^`V9Hd!MkcwGzf4hBjDW2%(rK;w);(lx`dkVgE2oG zIq+-k_hgbe%oDDU=EqM6kx}~rK`rYVl`0UbE67LJJ^&sZgPEAK&~ZFa8$}in)0D^k zSGXzWYE2a#Ujays{K?W&h`Q{&I~XOCvmiEIz-HY?CS#34E(<D*Lte*S6@lGQs-**j zxjhiXQn$mtiqPhkhkzJHvmxO5_}h6LU=Swoj&DU`oQVECF9Egz^5osPa<;fgrjb_< zEY%xmMQA>gV7c;+k7K-NwY+6r*8?!3sF%Xm1EK&9;LCx89gz{t2rHT--gA7?JDMxA z+MDRM!nHkY0-kxnQ6|#D;cWGV{nC3UUbSf~*&BDddbSQ|ZAxpaqMQ?<kx!EgkpmvC zBQLuHqWi^Z<OD*@Pw%u)h)EWpI?%)gBYusEeW-uni{*2J9^#I;x+WF<iJ~UEw<Q6J z^u0Nm*iDsGd_1Xd2OD}f&;Yqgz<SxrYR}f^YQmosnU`pUs8>tT6WLy^%rw~%HB#Az z-+@%kCh}9M!Ca^7zIrbp&hp3%eV?mJ5Gg#UkeZmbcS?^NOpS<TO?GSn6kDlPhqSoC z%!tN}miWQat+I>}qsxM=3aJLF8_!>ldfI+n>c8@uzLq<B=E|I8kWXBwe!P0odkr@q z^>fFJA>nZs$YeYqn3o)CT**@_aiW#6Z;_d1)ioTW^WqJMY?9fWbaQIrVX)>=t2jUN ze$)Ihl0;UbT5&5rPFVQBwOIo{b(x=g1wmA1{2G1_F<Z4OM3TBSsXxa)%98>q$~i)q zWjK}#oM;JXsv6y<xNruzjt01dwA|^~qN#|&U&0CT(mmdNigcnIOR32OTIFK#3Z2#& zP%wvAS?N}H)kD2NMf<4Hl>VHx_DA!EhlR|DX$MqeuWi+S!(D%8sLSk3jtQ1_u5-qm z?F>L<TCTZr%g^}Y*p0;HvflyfK#EBHyM#&OQsCF2cR>Zv9>vg!)&t;j<XxLsGnsVT zT1<pt_v-Ww=2%2^dy<@s{q*h^TGv^=TaE-fa=fwxghr|}Q-q6{sm%oITa{$#yN+@1 z{no>k5tWTp7P0LT#`S}~bH6*ineY{3YQPP$SZz^{Am%^J_7AoJNTBk4ljD(A=>ABE z+J1z-El3C5X)5m<Mx7jb=y^w<46{W959jVGJgz3R)U^$N0fU~&GOZp$AF2(9+iods zafF;|RQubjrtKfv>~i_ND1f_m&t<Xg!k0Wj-5i%KC!vFr!`}@9Afs&XcW~|GaA8;U zyyem#*Zq!UAI^?&*Cn%|AZ55|Ho)u1_tUrW&sGj|9X1$QQR(ahWuI7WxR?r_-|d!3 z^-<?&O#CA157!aNw|=Pr6a!k&9p<GW7CSvE3e?@lAtNky_`|uf62DI9yC!8h;y46@ z>n?ZtE|E_SJ}BFFYu?T;Cq+KqujUJt*&3*!IFt^@c}Bwt#kLW~h*Q<@_@@)Txa0}M z-t(aT9L+rF&KHDW92FYX@-)3F0Vr=+r*U@ntgyyc30Oxxug(&|t#&}kgDZ&Z_<5s} z=z?u9Nr%m}b+#mP&4z;n+xl~^G<YvM!^z)cVF%jc8p43Sug;xw^NgY`>Z0XwpJ;IK z6B!=t-8bp(g$~aGXj@Xo0l;0bAdnwG$RKYB&Nif?#&GE9BW$1JXg7~i-Cm@<*X;Bx zg|_IJq^HKn(A0>^P=?*(Q00p)+q<cITv~F~wxTlnqJ8MrRUa{}k;p@6dbGCN^tJ5- zKaM)~ln+988!ktE3wQpYX~y=*Ichg+IG}09k7xD~B&@xu6TE)*Epys2$f3Ob)h(Id z{ZGr=>l3TTy-j}T8?z&Vw_)FYgc~+F;v)|-q50%aXH~47d-G@8@%_D0ZJwXHZ=-+_ zLv>de+b#)Q#0wdJI@3#Ok3Igl`H_3~X=B8td>Q~sHo{^J8Q6bch(+RDV5w?t*rt0; ztV6F$pGO7k2d8lH2W;u*l9>JAZ<rGiI2X$$NO^4G{9zMz^|(_!zO_Uc)EBO;a~&#{ z2z`;FtM(K4iNa+rV56fOy4El!BUT7WWK%bcfM2CCLCvC@+kGR9((eMkz=7^S4#DH( zD%9ZBu(_0qd`&tKoF3uDA_V(TJ<T!?zF?NnAd28(BBY%%{JVSfBJ0AqU$)&NDo9%g zHBn|wQ~U60LL|lMBI)77+2a}byh+tu{sVrQAtTkPthsjA0?S@MBhyd1sHU$1$D5PK zsF~AEGY6aa47+yS>l`HJL|1D#hf@)mW0A2<*G}FkS9`ULj>MyDb5GN0-etyRlGaE9 z`&+L1s<595uZ~Y%**{aEMeYWe*Cl0&ts55_wpBzGJmB}(J1j=p+08o*3N+~A;e&WD z=JC1D7oQXsm>FX<|HN<J;5TU-dl3t+(XL*a&)Mf}l}XL9l7616P8|++IGGYQo-mB$ zFQ_(>y1Dq-ou>QzryzU$=y@SO+wq#q!C_@fv%hG|C!=mzqhITzmbt*(MQV3e?(`I} zAx3z95)i(-4_MHD!Fl+hlCF&U)d}A2pXTNd*lkbp6LpFa&j5dS=qDPv1Lv#;9-&_P z{zx*L@~6xEEgKsA&m#|x3Rc=G_JsGAjG@{*KRovzr!Nw8?Ri!mAQ)nkX)g15@kY-G zu4?+8>DdxP+tdHOQ_2Qospz!%Oirw1R(u5gQReC&`sRM^N5eE9)kVDa8L;wp>JTw= zP8j|cV>!Ndh|F2xCi<aG{k!|7{*_!TSN5*y(EgEN=Q<u`KfC31C=7-}psnZG=e!_T z9@%@7soh2JVOmIdC=*$f`TT;iZQ=09LAG7s&(p1Hq6^s5FcW^*t3%ohCGqJaxOJjx zz`-Pk^&Xm)YNA*Kp>3<&Mb2fSE_>6<!KWfg+@?8^^tqN?v<=y`nSA2OOKco`(Cg54 z9;5z#3NQ8Xl>bFUB$KT|qTBa=O+J^od%D>Ark;V!Q}BMzasmQzy8eB%wfh;*)fh)Y z<SnL~$auTIJVrC1&*zKov>C!{o@Bj8oHm4oT)jOK%6WYQOWK8<Fh+Njb9V02y{%hJ zjA7JHM{}cC(5srb@?E?;fR+&lm}x6zEbt=sxoGV#`DiA|asthtMt6jW9{zs933uWD zazwlQ`SXbFQ4rfHomBE11oFN^&l)#kMe}LX@D05m@=zH!sepYNZt{e?vp#r(Kq0{s zHA$FvEz_#Ul{CjxNVLHS;r(&V`1Z2>I9AwsaySxE@EA$kXgX#S;qKMknv-pkqn~`@ z?)_*x2ZDXlP5m@$wxRHvp-aZ0n~=vnV7lJBtEyjh7&-$qXxVl90MuI2_k|IwKb&jT zgaGH&<bt`+0YQqtqn4;-pN3<XV5PX*@Ly7@#|J%!S3=E3`pgekMAEla<PR|_RT?)Q zRG8Z}%*)r0!W4l;0wyi`#e}QYNd*SP%1Cxj5Fx~hs;$2`#aq+sgEYC<aV^1diBkMs zug5(2InP93DR@XOR{Ptu_XB!r^-Dc3J|;;(8ybdGi9+@P%juCbCHx7%lhHu?_9%_F zZhukX*E-J<MDge9)bivDP$^a0(6?9@@^>As{4*(x2Ir?ETWWYd|AYo-q)(jd4>p&T z<X)7Mt3(eC7k~nO{YpTLvBDZ~!@rPs3*15IQac=coQ*e!%`{J+I+Q+Wna2b9kH1cC z*~;VdEURVix5pRx=o8$f^BRqI`AZy0eXegWcf;=)k@lC{RC=|_4oeDYI`5a8`Nu+y zD_;&bn_zc<Cp-~KA1_qpYCPQne56>O0+-0GryDCflVoC#Z3=}VV~h(}`%9$!pE|gw zmP*1@j*}udgK6CMJvL0#iMn2m$SP~+vdI3B-P6&m7KOo1EAU;A=+uG`PUevC%)C-O zBXF2qaW$!}cNDNGFa8KWB>(b^_dXak-NmCLjeo)bvCEWrd4xO>BhFnx+lCbhzrCD! z$5T<TS6*bWEg!(7VI6bX4l~rdXa)0gUMqc%jMc~VF|A-`2be`+0b6%XoGTM@y7H&L z6VuMe1xn`p&1XmD%`$jS)-4x7tUtn}p<ZPAXD>Piva+*H&v`N5{Ywm^>o~m(id}de z`%w-7!(O?<4HQj*mutm$jm_wMy;Fij$Belh10oVV`U5UcKPrzXr=E+Pcvcpi9z3j0 zfp1#}0?(RMyB-LWHA8df327j)hlRvz{<>bv7K=t(r5ZW&g2I{h#HB5NOM-O7OHYQM zFS(O${c>m6-pHauuyfZz#kTsi-%VPGXiNL&Bnd8N60wo7#ri|sQUn@3l=r$X?2H55 zvc0cVwx56iI}iNf>CaXNQ;TiIbi*>3T~lPjPZMW3D)ca3XRUYNJAA;046$yfI;i_{ zL_*_In*egXD3EkXQ}RHJw7YMhuUV#HykfWO{vj+13WC%Jhc8U`<Oi3JWRV1f>jxhg zt?;GO1S0EJ3gz-9ouRaO$v^FP1%#Tfu}Z{liW!>`aiKRUKbP^JY@*hCzI|!9>Toa> zx8lC1B_TAt25hjCe&5MxVt%)Kg}YC%&VQH@{iC@edvH;&-j{ls!KW2$ebZ_ri6z1y zpb+lbiSKHJ?Q&Z7b5XB;Qn2gQDA!Wch$ALV{J-QP_%y+T+w^>;W|{IL+W6q`DAq(> zx?aRHhe<}Y;L7iV=*lC2#whA;+nRu)SO|DszsFKrom^W<ai~5@r{vvsbk;JIieyI# zHlPCnhb#xAs<$sZc8FmBAl|&Ytf<;hrS_X;{n0uaQcpxc45tJ)NdjT-<GX*O&$Z$Z ztBO-|w`?DIk|EfDIvrkF&Y}h}E(>@lm-zgIEn!5wb4RX6a2B^ecEE5t)Yc=4B-AuF zhV{cZ+5{suX#Zw5?+b1M3IJ3nPz3a%javR44noa`s+6(q3V^f9_ZNabld4~FN(CJA zsgtw^Fn4tqjD{eTf+}AJKtOS{9+U)_0|YB4v(ZQdBp-X%?+c>^mr*F$D8aaQQOXEw zX!G9+jGz^$BhU<xLB?;;lkfw>k4qu;sFTLFhBYxo1(>VXC7&&kO`RD;v8@_5U^0mb ztME#-+sZCnmoU1EgH6YsF1R<q>O0o;>dA^YhzPrh7&(!z>l+K&uz5qb@VyDv%{;wg z1uFsJ4#cV7C;RVc5}II^-OiAg{jV2107xIHj>}{NPKHybE3$pHKmQ#2Hs_iX9wKEh zI;8|iKn7YA1_`OK_BYP|YGT4=04$f+k-%n(0o4M6WlZ&OizqkvwbPa`nXe70&w*8& zXjT_l<cP2XTGo@_ez9yq(0^sUx`Kektt<)|7!_AhNdS}ywG$8G#(cf8++Q7&xnj_# zzyFov_)PM|+{ugfk2v>kF)u_Veu2m)1spfbxLm&Q+FJI-TGQCPf&x+3Z|W`LWR;Fb zD!!5u|Jc*)hpcRDrWOIhM$9N7V5efZgqY|cXz=ny5cCeUq~X-%*>)qzXRPbVeB&SA ze%#V@*YugvSd2hQ)1y=MqHoTg9gQ7O-Z{3i4oQsv&&TzT>HG=Er*zZM95#aTjEsg> zYst$EZ@O{GyL~JYCgo!uWsL_fMleo!_&)qcs^urmyJW36oBlbF|71zJi7r~v>$#{I z^TGc=)`gVzU11$EL$b<tA{IEM_9cQ%Kj01tllb=*{3p$gCI+aTAIgW|1-hRi^LdAQ z%E@n6eFU_xaz_@gQ#I%t_e`1y`7#)j)w#`D#UA1e6so?*gm~+1$xIdMn2VXp|AHEU z3c+Tey}0mbNlrd@?nLh>umhF`2cm(bY7GX^Q-yr2x8&p^s@bb$xKqV$mNsS;PCk?8 zn=ZQ933boeNjFC*a25rWF0{%QytQ>?gqYHZciYXHSS%<S{3d}w!e>9v?VP4S<$+k9 zVR9%<j`4<IX03$e`A4bk6a6hNCeJe{f{_;Ax6l49zWeg3Q+IohvVDL&bS+N7b|?R< z{HoI!m_q3PuFQv2Fip>BZExt9Co`j1`$VhkX*&wzOhQ{u1j$>%Z^PO=EwsCE$1BaM zo12??T8(xr<9=Z98Si>7EIDCXlfwB8+7Wk0f!9J9j$+ZL752HapozH5SaIQQ?qY>+ zjJp=!xBPgBwx?1&^X;M!6{x9fnw`ectk7|lxnw{HkpH-QWKz-JqJ5kp7K8}Hc~41C z)8(^_D`{4MCT0W}8@@Ucp8mitJ0%^{BvXQdum%sJHI|~<gqxw&l*u^c*NWfDt5Q6m zYG+6sf4vvkJ-b)0Mlil-SmPq_jtiyAA6&;K+9{qpq3o<(=juOi=RJ<yQzA_6+a<<@ z=FYI4a!C%wl%+SIXJxXIn&&aZe7W14R4Cq07TNQ{$cOkxujKXx%$(t#Ul@?IMnD|L zXrWTS+I0HkJBE1C;We2cHJ!@)rQ7-*)C8on^@8BZ%+20VNg%$M4+J<B0879A>eD@7 zIs<1g(#isTDWl&N1}d^62#H|38|AZuB$#7DQW7<X*-R9W{?Y}are{t%BzzCsu~wp7 z<&rWo34r@3S#PyMLDt#IW)FBWtoFN7j;>`Ib=!v}6?5{g9^OC{t@_6(K2}5nAd~T- z5W!#~0#ZM8H-C;|Yqh%Sf!522B*irIhd;+Wq)W~xF+=gR60OBpNEHgkRwW^n5{*M} z!ulpl$cOe9+Zfd*<E-=C)}QsF=>OI$VUMcQZvE($yfK)~cRxw6Qw+A6s<kspZro6P zl4KK^OC{7d`jN?g4Q$kI18N|RREqWqux9w~*Zsk<2*SN^3B2E4>T}IE@;ZN2U2H{u zehfni>I;Cw_}=pq4Sa`dVF)+>i+>Z~*!#iQ(hmZ1ipLyY0m7>5Uiu~AX1hoc^my)B z22=n()@A$Ki!5W?y#dY`puH}}V`JBCX${6uYVX~kgv~5_T#c4Tmx~d*2J{65VZf{b z20<432L^<Ai8ySJT6PB4ubdw-ajtoQEQSiK`%Agj(0=~kt()4DU(<m#Mw+`nlADk- znez4zFwqRbf&1#c@d8OE6AC5(B5vgXahMV`e?V4L3#U%Pl8EP-cFiLQ3CHJ%;aYX+ zF5SE(;GdQG+V6ajpE&e#w|3UFz25163B+j!w+Ca5fZQp>7If?E2E_om+m7LTJ|aI1 zQrjym>0Oh)1Z46d@7F65jv;W!4jJZ@_?VavNd^s;OPr2OqseSyjLpZa4?Bsv@0yEM zVzwptDz1Fzi(b5S+k+?`zQ(v)MnAM9;2(BgMh?yl7h*aqox;#K?g*Nt5c1T`Gt-AX z$bTH9{*K?o9Jut-GeZmizPAHX1p9XDDGa+qV-_}zqPLy0Wme7Il8UG5%vB?=fXJh~ zK5ld+Z)B{SFE4(`ssrDLTePe#fAAT=IN=&?^L&!{!{R33c&L=jX{oV*M_`p4-U%7T zqke>__#4PYFuaHDirK9DU=Xo9+v}{?bnx(!ZfjjG3|s*<b~y|;t93sobQ{Rw#nLDi zEZ`G>`VH<n{b7dzv76Yx4sBIr7vkc)JoD!Ok&c#2gW8_PF2|Mdl0%&IT?;)yUmK-! zJptorOsZrwp>a?Mw`J*0Ru48fVokqYq@l&E(|tVW-nKsX>on>&U2Y9Kg|`F@$w$et zKI5<h^1?2r8vTsi2qNBMLW9FZ3|HVodxwjcfc3XjjDpAdRT`Ep^ZBHHZH5B~z!Vem zyD7Z__`BrhgG)s=i={S(pN?x-k079{7nX~p-0LZcBe<=j1x==+2;2(-mQ5c1LXsPY z+qDU|$9<)W<5Q4;sH2{RGG_rIIf>=p+Grdd7a^I9YmdxMJeW&Fa<p*)DKWFjoIovr zhWK%?{OHValls=}>T*<~kRJkw`5J(iP6^!Rh3Xvh?Ys{AS>=uz#&SWEt}Bl7MMo+X zI%RF6Z~92%fHIUlRO9vHc17bW9EHdBLma50%8M&9m!$L{oA2cG#bniNzQKY(ii;2j zg4f@$TVSAb2654Izv27$^cVxU3xzr<IGT7RrF3)c#*9ZsYedDhrKc}9LLJXYM@B={ z(3ib)>W3}uZ!prHLX759->d+EgqDI}x&m>KdCpeJ%_*r}a`wS;Yb`pirz4zDELxF< z8tR<25D5LD4)9c}O?fry*vVLMQCc_PzdUh&<Gs$MsPop`47qxpvAJfa^|W}=`Exw- z*j6B&sv)~bT%pyd@a}3n%(uT9xxWI`{Kn=E-XDBkudEX=OX!1<iO_Mmld#_rQ{!%m z`8H6h%N@zz?L`R`bRRJ)sk2D~E4}dye$77?iyu(<&VBfvj%(~r8~2JQNpZoLEh-0y z_#bSh%b=%2Dmh{L;6x*t9TCYv6U~5qz76cf1RxpQ$aANlsHohcCh1@F!^Flgo3r4f zG~l=3(TU?!dp<e6r%Q*<xcAa>%l)60fU$<+XeeBEnZovi=f9q?8pb@xCqeV6iS)R# z@17z4N(Vaw12YT@1Sg;ps@IvtBkwxnzJplNcr-e7Q_Z@z^;pdVop#?eV;7o-O;h8( zJ}1Mn{!qH`@sPWGEf2~Am7095wFn(ryW!0FXu(=EL4O=_RM+^CGDS+m7bx-+!lmEU zC=Btr_J1W5LgCPLZ>1tz%W`5n8oqX$6m5KE({-%1^%1>kalLBkTWNK7o{yuekSM?~ zIX@Dmof52g1KiJI{DgCfz>GURged|Zhu>xs*bHt3(?`H9l8C_AAQ-N;?6MVZW*vgS z)FQ`mI4RdZ0EylB6ayr#GyzIaHk!(%YQ}89<9tf5_KdhC6dAKl5r&S7@A-Hwe}r+Z zfyZ7jd4(dY_nyEq_Z)uL39wJrY`T$X*LFP!x$V9>;f-n5>RoUk=Ju0#YvBp<5Uv5K zQx%wa?vXX?IN^Cb2U|o)1anSik;As9(<_|7C0D6fKX!|S2?i|^AN7~Vo1GQsHRaIp zP7>DMq%VQ;_)>K_RoSM2^IYNK=f#mfN2CFY@II#Dx(hlgqU&plge-I#E=)atVEmxY zHa+&9u2jC!0nFdoMd+CjO9*Z}I|rxG3FZNr_*$$C1T9EuzVhz~G>cbzf=t6TZ90bF zkzdc{cBCs&L`fCRfmDxVXFn~Fuu_;#`cfrCHI)S9#!ZAFT|1RNN+CQR6lQK$w7(81 zkAFr4S(=c_v{12}!13Pzl*<{9An60N@CO>2Z+KXLCptLxZ~A{Di0V~-6k;mqZ^kj$ z+r^qs-C{n<@tRQUH$jFHRm}1WYRzCZYQr|_{bHq?OR+!#4TC9a=XAV4_MSJ?i{{!c zNVQ@W+q)%z!4VCqOd^EA6Aga7-$KFTvPvtVx57CGN(4Y@Ld||2ORa<d(xK*ccG!@s z#uqUkj<_a@QT#+lSl!JR-~+a+4LdafCzOx`1@{#ioWEMWOoOBGW=^v;VUUkwpd{u1 z3cu`K0ilCRS2GdM0S~D|PI`qxQR~E{cL{b^F3FliG=yw@Yr~(IJG!=Q_j<XOov&v^ z*qrgZG=Rq`_@e(^ux4)W<}Z>9y8nh8VE3BNl_v9q*L_Hu3X{jRPWRGq252+Hd?jGy zjZC{Y|EanQc_0?l1Vi!;lheb5SX&84W8|IO;mYj3W-68J{9teWZrTnBqwwd6vgujq zDM9+tD8-$>C*nPhg1CpNAZo-`>5M`shi5XqV^CC>5@uoFVn)976ZL1<vJR`&Y^bG& z0CWLOtm8aadtVC0I-}Z3>J4r176W=}C|K2c!(*T#GwpBs965oS8e*idD;5z6Hoc*= zpYprlSLY2;fL{g-4&C%=I$pY!US+kCt8Yyc;VcZ3aT(w+;m@Jkr>U)hcN!S;i-<!n zJO>}hF>~rA=}E&CU~2=-((DCxxzFG$%yb(wv^0V!A~UNW^r;O?s60~Xh9KdDh=(so zG~(nCF_(k+yPWX?)KvL1ZZ;TXWq%5$RC*I&#XmEimjmNDAp`{X`iDdX@trkT0>Jx^ zLXmAbXCSo4ZiRx!p`}-ZdDX;X?sw@tW5rG;`IM3E<|jc(DN$EVqd;*w;xQJ}ce)|6 zxw+FPqdfzQGpcpfjQDWLBId)>=GJ~)vLw^zctVFnm*I*_GAxy-QW35)Z=5+4J#wsQ zH-w8E)PpBH{p-RO{Z01KJHoa56Jt`4?-1%6IXL?Hw=6j=c^bBf<a+W<G(4(lucyTC zR+nvWUlp1MW7J+~y(fD{T+Po~>(<ZHpmJdplP0cExQaT_EgiO<pJldsYd?Un3%ha8 zDbGJa`^rPici@%@LJ}hUt&)YF`^onnJIX|FJ>mqo{|l(E56EF;^YQAh3;-F&Z6HG^ zuisYC_b?RsKq$(_tPmJ@j+@+N5};fupPP<mFk8dhM-4L<l%<uVtbYr(d*)Rg8mZs; z9#6dwOa6iiTHo+A-C`r=w8QXp?luor<c_ORU0pj5Z)txeputj=X;S_y7F2&mA1t#F z8S$NfQ*8HJVU=Pe04-BM6iP(<D+|<Vq;T<%Vv4r@I@o+i8}V?{q3fG7nI@5<yJ(P} zNL|1P(<Qs3ct2K{wUo4fR^ggePlsv>ZgvMO1d8&xlOs?-2Y^h&PH{=O-Bky)KLiYt zn$TTUKQTrFVjD23bY<yVr$e`yH|7yPe7X!IDwT=4);snQTbxa8%@#~Oy@G=}lFQd7 z@_LoTNi9IzhrZuOygtR)3$`uuXu^0si!a0l;=QM$NgytEn#4Vlk<k;UW^QQGmcPQs zo6y6}2IJM#jWw(xXA%ZG%P`l0thC6IzHG@lM7{wWhffJG(o3)@+|vd`z*fmj_6@Qf zz2FeRaPbjv7?rHd><O4Q8-R#+Je}6{^OM=RVgJe7Q~R5uVoK%y=g&|uBY-%ltn}As zDAL7|P)!wbz7KcDFOjw83M|6HL}KGc+K{~Eko<!^<T%m!cm4WG#t#VJ2OX~Bu+cNO z8cim0`ns6`DKGc|8dFr=P$ef#F#C%wFuc<icYITF6uWGgOyT(UEk>gq{~~`roZAJh z%TLdm#M+(m6SR*DODpX3uPE#}vh^+5TGfJi9e3$QgV{%BHRf6B&(Kej`q`XwG26j< zDHttE*~irNi<V^(-oV>6dqea@oNshWz0kiBI4<$+-CRf~^7G_Eh4IbK!?`e|#R@AB zyd74ER(lmrHxw2K%hThB&gfJ_K}YO_aNc&`?D=IixmQd+$pAwP<quXU5AAOj)(d9{ z848`N+(yKr6N3>lNJXbQu&ui{7~*M8SyTCfNy`i4#t^*19RwZhbGm{ka~u{A1wrm3 znr^iK?PPRsdelcaC%Z2)=G553gK*Vn?!>dp+>n;e=UPoSU{Ts(k9ONJVcHyL;q|Uv zHv0Ddg|@JRMNwS9fFe$-jM8ZKu4`mpCp|_L@OpNsBj9p7XJIG;C@t#_3CcHcF%vB? zS;>Vg6okyG27)6JRIV2L&fgtYd*^cj=@VpXQpl<edI8c8%sYt0<;=Yx0yG1+IGuIm zyXqvnfZiFks7T~54RHPV$lEVKTU4>-c|my!-8VIF=+iP*vxwjq?3$I#pJr8H@_wH~ zB#8(^T?r%mpYH;o>;h5rVMWL1>NxH2FtABR<YnR^%hDu}0(ywn9x%8<$<^RUaMStg z&RhE<Fq$})zjf4ar1)_tiP1CP8{<x=@x@eZWzLh3*H)oA44UMZ2)rbm;v-g!goJ5# zD)v82(C-^qsN3Y$Ny!zcb$elEEOViev#uEi$*lSQ`X_f-AUGsU1O5mPGCgD8N2>+6 zC3-dH@KvwlULQ~1A7g1WHj^RH6S-oMDhMHEK_qVL(Xi|tCs0qK>n+4&6Fj(qzf~(T zfW2RgJ{OQw=+;Rd%e4g~3chKv^rtLB#*^F{7_^LipDn`EO^OIGRbFt1Bu7aSfXe-b z(88l%3+J}*9gW~YzZGiED67Q=r38Au3)Jz7yHJXndajQ@n<eBw^D{)}D*L9@GncKu ze9Y!d>9?E^12PGpOJx~?&J3Ptan{k-_YlDp>zU%_5f5(C06`nghHzGtZETk+3FQz- z&jbwx`}#DikTS^+7CY$o28=8dJi-sR4b(f|T0;fv&2VrdO8J;P!+dNz%|d~xLV31E z=UdE&Gp4o2@U2N=)!~K+$mc`(4SL_3qxllz`W6|4PXy%NB0S*N*tsk}`y_uCdVJ7! z!S53H`J7k~J(m1{;tgSPYxMp5?@3PnL$ue%u{S~k3Yar^P?(`ExpB6I;*R$>1Od?q z3rr89uO7(fu%WPtt{{$0gq=dL3(+&htQZ>8YQ1p<_47pqnva7Dj749w<mJ}Lz?UPd zp3xnD{xSo?zpGmBQ$D~Uc8~6S&YaIATBO7;jw9&U%)WWkMk4fE!BpD~7P3nx)W&#J zFP7-L)cCaj9+P>Wy&8B|fw}EI;+jKouDn!_5MG8|mrN<f$Ru7c^F3cIIFWjD5?m!B zkH1f9{d>B`3uB$V`1#||y@8*g-52>}-e($Rl@ae1XL@bqLL+gqE!|{vk$evcTby7h z!@EoS@IcSKxkiyd2KMLn_F9vKk(IiycJNPYFV<%)dl?m4zb;|_=eYq=4-P0lLcgI# z0>47e9A0#3Dopgc!PX#fTQ?!1pg`CLZsj?~yBV`7-W<z%w>QmIFx_9fZZ**Jy8PH8 z*PS0(Y!pwCUihHOarSYm={9=1r^elja8Nw9yC8j}Ms{bQh;VC_PD^}qYYbT{fi~r9 zq)Hp<72*H9zM$Ou{Yh17YHE53c$<T;Bpz8F-@AQ$LL04CnrIT;e>l7Fe7pbS^?cF) zo=6)~gwp~u;2Hs(8IhSThLac+0(AK_4C?qeYP$*FwkrFFh_I8(XQs13gy90o?zkp9 z!)6`UmKE2_xy!Si3+U+=QPw}*l$UDbHK*t=I;b1)9OiS^2kI1Eq5a2VxZn<aofz>< z)?8>R6hFAS;Lg3m&f&u<kEa&~g5j5dXz`_KYiAO%Kaxcy97+qH#oyX*Ckt?pU1k<~ z-5G#Gs1g3-eNaaMm=AjZT)?=BBS3#CLh}5u(+lOjIPjU08De(0;HL$`amsX{%wW^j z(au=o(M|@*D^+~#5Hz+>n29}k5pK~wi00!e?DaDSka2}v{JP}FMq`kb)BXD=;2^5u zou_*ZQYL~B!-42@u{@%MXx_WhXf{pg8FmH<i#)(kznr5Zu%HHnq`v^Evpgq(-hB`! zOVeR-iPERHP#Flgi?QXs4BfI;i@(la{}@@sOb3p;74RriOFHH8UYo=_-Zt&$4J!P< z+ctpQw<fl!o5dL|s<3|5O;V*?iv~Bnqk!p$Fyx{&pl9mUOV>zc@Ts3H|B6PkG+F0! z`s#VRXdHhS%G74kMp5c**spM`<941E%Ppj@9alM`<!nebqwLH_;~n9pXl3D&AIGHB zeQtuaka_wCvZ`*t1Bea+!!=EnrLsS0Z$WyBpQY+{bO@?c?>5v7q^|m2l9H40A{GrZ zfEn!fdG#V-yhwp%84v*@3{zMPgQkesO``fafPrtUQqK-0+AyCux_(nu;;0;o^`g~o zXp)+B%5}>}t$c;S%PynDVFbIz(v?QljC5Y%wnbLm>aD3!`Gr@3xQrhJV}k!183uiP zPef;>rlio)sg%m);sNtd@(8W(%#DKx-khDW^;*GnwWU!E-uw9?7~XubI=`QLB)7+8 z03dF(6Wxy}633|LKTOo%*o!pe3$*N8wKzDm+m=|?-2QI4EWXB18Bbx@J-OmYw8NBX z!Ho6^Hyh1g2s3(Kx0qS0>~ilqN~p#Z)Aa2I{KxmrfPfL{a4<b}Wgtal%|ZVjR)0_O zZv$SpoucdgM(_?WFP8`?NS#;_`jY%BzX99neaalj*8LWy=ewg?^SBC6`vhdy0R75K zQNKTuBoWAGHm3*Uz@Ko#?^T`l(0)SU2NitF?q8t=rZZ9Lk>~fA>CLUOzK|d|q6M)> zC8Y27?&!s4oGwbD$THH<^ck25%gu#_Ax4^@qoYIVQ~|mui)ANm(xyu30$zO;pmf)z zPx*X8#pxN6?hkGum9<gzI8J&Aa?h8DS3r6M=J|>@%sk6pVK7>M;_XzG2v<TIf)+k7 zmQYafJYz6AXe69yQVI)bQ}!ZIeXGDPGm;9{xjapIV7-ZSoipK&I6Grk>vL{hHrDQv z`_f1zbBOL}$rW~%$0#4^Hk6~S-DNVRsAA*2N&E+c%CYE7mdf$q<kdkTarX)14(pVu zB<YQ@btQ9faM0|6Y6ykXDd$Y~Ieq=Cmv;9(Sd?Q3Wh&G%n;&Z&4ouEJ@4o-IzAa_> zj4^TtyE*S?w`EPR`4!eNFVmX`*<<TW^D{zr?wQDybxp(y8}0=u(*VX)Wiv_IK2(X+ z>k!chYxc4maEH0s<!se53d>tjJvhFHiW;bDU8dn?U(}-<f4M8YSsv_#SV59%1(QWO zSz?Svt-Zp1vM9Qbq{imB4*%J^kwo&k?vFB*#9}yua1ZES@j#G$2oTPp7%c%2NhJ^z zE(+55&?H|1A@yb|+)<9Er=a*by6<#l6$kF@Z=IxTFRQL<n}=(We0S2FHE3)p-#<DT z9*dSb9r)IQzxWh4;jJGges&3?RC~X9-N?hfJqJe<#bF>}yX;lN6Pq-#zyiyn4$W6v z1ukp}46vzS)ve|OmL{zSAg28Zr^mJZyRZOE?OO`hM^rszl;bo%e*h2TBO_+lX*qb; zEO($$sCkL<vc+0$NKTd;6%SJ1gp)gQA^!Xo=QxUE*tLjmd`P)YV}CFk{%}L1v0ust zSrc)?HPt5xcM}Lxr=4sgTW>Zip&in9`NwjpbduVCLMssn$6rm*X#Oc3w&`iLG@ei{ z(@<_q=<5~lA48qK17eAnq33{fSllk6btYX1II42WFq!GdVNjNzau_eTfSluL-NsMW zZoB~Hby|WQzjd!l_r_UP9!>|U4q(bp%iDdo0iV<2_f%Kt3}gF5?{8Xs^VLK2z1j`X z>%Dsw{E&YwY0~8{_ZiwG7<jH8)R}zkVBtEmS*;-Q*Vj=|-w42@b_-!SoY729;V>^a zM29K;e`q=f;JV(gZ8vG0#<p$SMq}Hytv0rk##Uq7R%0}_oyN(x^ZS4AOs6wVPR}`e z?+5Ey>%OnWf%j%3#_JYBe_{U?^+lk)BOsbxGWSQU>Xpv?G}4;(vmWbaNvT93q)>}4 z3A*RZP>8OdV`Vq<wpZnkZbN5$2R^WU=t9}8pqAf3%r7)3?|Lp;8)Jpz=atzC<n^_N z81lKU#|^S=^pmC>OGUbRxfSC-z5W#!oQ`U@PMVHc>z=&w&^52W9T(ESC6DT)%8l<` zUd~#kUo}@~o|;3fT0h&XhXy9Ezo@h9HTwgqmRFXW@;rjH$FHsL&!_vqNz(aP&uzu@ zBrnnxOJ3luVSJfUfKYcVh2WW}%9XBU9UfS5zW>#8{0$43BO-DGqahkJU5vpEIqe_n z<`JNda%&A9a%UJ!-<$%G3cR@;@kCQW5Xh|grz|qx2$oilEvEjka)?grQB{S0?fYZ# zBU?2Nl8&+XOb^@31<dO|`5|JS(DrvoFGPoixtWRFAL3c9a)=N@uUb8792TyaT{8Ha z2K;x=?Q%-CE54-P<pyxzgpHF#WQHuK6^VVPUbB?yk}3iNyqalH^su!I6qb)QPL()% z?p+@jeXel|{M}Ad?m8jyFsByVL<<%smgyN<)L6uSZMft@_I4VU7|TJrT6RrO>3FgO zdVsJcI8R^v&4W_|m!rb~&EZ#f=>C2=7v9Ie_2UdxGxu?+ZS($r!w_6e-u_CoJavid z?(jE7w9;Syu3aR%b8YQi)lPTui!088=O$_(#CP6sX?emI_c>_0FD}qLxqW2U5A~M8 zA$zQxt2s%lUg~b7?>fH$93SU}vLh9`yxe#LKb$^?fgP*8PQjp5`oyO~Q-@n%V+;(h zC3bjq=&xP-cNYnizQ!X?hqFTZtd!9UT};XJzC8MP$aMpEExXBu*Ym<Ptxa`ZE4-42 z5-wfe%GR!|6zJ<CpS-!R`8jNW#4KjHkt$cjQ9NKMghj4Nt1T3rVq0^J+Ce{Z2-ORG z1~z;M1e>;{^;%erA!i*{>tXNLZu3xOECYbNd7C@eeyAe$<8#_7zM2lyeOBXZ4~f@= zd=j-6&?|IfpgP(yyrd!c(;GSbcO3GN$RaHbhr(QV{iE5sr_DMueZv&49v@H<j-ALu z$^!aA3)~Zkd=9=f4l@zSQ!><RyynIBQcY*i(ig@jpFwO-&ujO(gCi|2)dA<{sKsW# zOZjOhw%nTv`fCLaf#pie9nNN8#TD)LxjL`T27a8ima}m(tK&!E|MEWe^Ds&PuOkT% zBen`;&42CzSwgl4JB6Pc#!>n_9PRoD<FM`9x#;lU+bLWO7eovVl8@&u)>FdiF0iG& z&=`6Y@pLV~u|Xph>wK8yp6vrfO4Msot&>lmXIYcoq3GEPb%s>;p^g-2yWJAGENURA zbBX@qZStJ+Mb{1xMqU)k%DGJJH_1#(wPx)tg~v3%_8H7hOSZqv{JMOlROU?jt3y92 zeh7Px%L4n#E`amaSux>w+e`tnDbFeI8<GZP&;rLn`tESPsJ~_SrMWq+_$P)g9iWbe zi`i%g67dyOBACz3FyBz1is40ra%JDY1xQj#kRCYt90~=+rkp8r1<Cv97~aopKYKg0 z9|TSJ?o#YEf(wkv&=kw4b-Za|`@(fS;NMmoFESi$zDG3&O%cq+(t&!&r{OSz>w59l zyUJH_F)%{?fevv`YRv=3YgeSYZS3;<089laEj~GbV|je}s%YA|mkiPF!Pr4&e7Qdm z2y=MnLA`Wm3c7*fHJg4ba0;-i?S<;qF@yT|=g%xqW;C^-)ooMxJp>Vz@ZYIXe*h0U z|4{Q8dnN3rlc)%OCl=OXUGjH&as<73?E^b)a+=soM{<J&CW7hZCP8|i!<wkmHGQu| zODf0U=_)j??BnCy9-qqhtV|Cx$1Z;O1CB+g?cfvpLfSM>gSA=-gZqui1ixA5%b+=< zSC$RP@_35iLZfgcrN38KY6?MRKFb8a6zJr)UZic@oCB(DhJ2H|ltcmEGp+*I(^4?d zU>ToRh1_*BMzfz6ik|>Dn?(Vb(+N6`m*W;3#Oc=wXX)DPU7!w*em3I>AWvHFJ@OtP z5dwk8diio5yLkZS>I<LY5mJR|)S3fOQBV`5PmrUslkKl_pEn6VZ=l_1l}7h(kWPq9 zip!&G8x3pnE!0txDq}Nj5nFn9xYWIrF?wBbrTnM$gaY#eZ^-^rqeUS+Bn%1<74>>U zrs-}Fsz141=`|YpX8*4O;{s-x7bVL!4SlU=*#{NRauEqPYTlZH)Zrpe;zE(V1Lxia z9e0-xH1*OUH=yjN!&JZn4A}>C4;NUmM6C$<#|pFf|2)HBsLXb2oKL_5r}@MzcrC|Z zG6}z3)9bV-&|yoM02YF7?aa@zz>Vn7L0iE4nOu_XB|SMj?6VBi>_yoUwpJp9L3_y+ zI)85~Ezfx-Oq;}-7meYJcdO<=6qUcs?@IxwiX)OQmyt_4&e5v~V>;YX7xGNFi4FFf z8)#9-LtZl<fMrZ)`w^u7t8x?LSdbj2EJG8_qDd~w)aI(tsVgt}e_71WLl?%8Z?7H( zW_ZBgzy2RDn^r`*Zrb5lgZ5o3osh76T%YU%gOO)|>!lb1<7LQn|J9mc!}mdVKY=Ay zb9bL~D^;)-%se&#TkK@K%2<N5y_AXW&)%ff8<Ko#>HoANf&<6_>eaxR2U>>{0gqe7 zuH#z#eyZPsZ^N9=>n?78Jhgp|*dGYzPw+VGH+b1#dw5+ns=o$`pl~930M*HP3kdYx zzAHhA4ZvqrwRXS5Cj%s5!(>6Hw6Nnfo8tDdy{SKGWUV{>Q=6FC0}W+B?Y#XTUX2+9 z{X)(4#@+E8cs93zMGx?Ck(@R*MT5HrNTn+I4XpI~y0gr6CLc`3iJfQlUAK|w;i)iW zk+9zqYVlqqo6BuYZ~FFcrp7#-YW}E=N;zCiQfoY!caX*rfYr&Fj`P)*>~WRzm0jSJ zdPO=M$G9@Tw@Yov@xWB4D5=?9vi^y;^P}z^<oOnDUEQe$2s!Z7=daX)XF@;Aco%J_ z^iKdcWPvMcZ#t7p8K}mTI|A{f?$QwfP#KK>EG80^UjoNmsKw}>A87vo%NKQh-cIqv zSK#T_kOO)5oN`Ed9EoUbGzA-nz;HI4M?io|2&K`fnZ+6f=TT3MY~OOiD!%pmrl)9q zZ$oA(@yWVr-1-({v~PW!v|_-n;@7#O+|<e&pA8zOBq+EjA<tn_N8`>*T+w@KZPnMD z4#``XMwo%+9w-PfWxq;LlHFhoJ%u5VMN3Xc-Du7&^kuoN8Kf*XMiq1hJz3*^c;tRb zLQts8l`d9L<}uoYFVJ8)g2FzTpUNU@i=+A7C<wvn1GfD+CiU^(8JDxYe%%CF0^iwj z*N)X=VSuvIw$zsw=bnCI_8)9Kd^4@Vj)CjP+j)p2NP$p`fd+6S=;{4*48<DT&VW*+ z!h-Ra@c+gEK%1HHg00XoKEl-#p{$k2l|D8Z4)%Ln!U~cPwTj+rQ{&s89Xgc0CJuKR zJ5qgjT9=R6X)RQg2<K>Bzjss2#Yypu4Bf63%9YGyQmyGH^Q1rXt~eacLwSEFv{cJ0 zzAIg4mOoaNrq3!lb#`Xzpb_@*#2c`?L9DERe|-&wd!}#QLvEb&`h<e`f4q<3poz0@ zom&Brrz$wCH_^d4c&HxZv~}`Yc={q3=sf_G8m(ivD+XLKVcd~JU~Br~^pKCM&&BII zU2Fb|=ZSMa2E#Aaj`t0Izw)0>-SE{|+u^0eU%vjU&0gATm91y5axk%Js8kZrpB;A& z`5Gn2q0mU9-9EkzgO~4m?(*C4Q$2d45nQH($K&S0^9HykX^i{n;vhducb|4<;_|jW zmU>N1O{d2z!_kSmwFzoo=LsD&us~so#I=O)<708n>QgDO8@?lSyaMolD!c#%_-j~% zBapd!70Ctiqhr?di<R07dYEdA06n(OYJnQfW@At7vNMpc@ORL$;<A1Lzz)C<fpBs4 zSv>W~^ad@3oJT8eSCl0DR9OEEa!M)zjJV_(?6yv}YpDB!rq@nVTW#F^h4X>`lt>#R zBx4SDZgs@1y|J)G97?2sCp{tnnzjg5t+>pw3t&s`!#qyr%gT2@Q}1@lm3R19kO=s9 zE#mekkOlo#QD?w0%hTqrB@D!qJYY)b|En|Q3ShuZi-kZHrE^tgNLQSfSXJAyAeBx3 zU22=$c9AHJJgRp)Sst(F119~4i7@e*M=(#1Kb|+e2?G0B!4)PlL*%2<t7Ij}(-U7~ zl|*UPz9D%$)bWs#@Qeewka<I}77L?%RA%fm(+Dp8(>)|j5Xc@_w6#^hNm*c}PuXG} z%25WK8&qmW>7qhEebscSURJ1mGa2xg(THcGf%gO&#=+|&Ko)@x7~(lF{Ylig#t5Gx zB|(!<-o?uO@LHl^AW8rdNSStR)brz*!ZEU#sY;IX-hp1F$rOS1Ue=TUNJsaQv{#Y7 zukHbNs-0}-&M!C&_;)B4(ED+<#z~}a(Vtm}Aue%9V$B)?RQBb5yRGF0bOJg+n5UL8 zYZTwCSp&<-{$-#`=|Fej9)1T%K_z?&9c<qpR;{aB=?90J84W;PX)YrI1ORPVUl1^! zYf2%^g20R-1p#_rp?u`(NxhRb4wwHg7UP2R)7>cWeck<&l*4hZ<Wp*kWfH^Ql+E=o zcB{=RN4C+aS<qN^+gD!-4`bW2wm_ic0(kG|m7Rw1+)Lvj^f?)cuYoPIV)D5rkFHpC zp;}-6d+n@p@x+pGgYjyE<&FQxgMXc2KSbj-U9qg{Zw<vV!0Rp-Z0rIC0ocYPG6BeA z(6PpHZ3nOe1w}hdf~K}$ss>i*e%@4%&zrh&-@g_wIFC}Qo0qi9j4$9RY}*wAw_J1k zv_R)2+3i)iUx$$Gf;!yQzM1-y^961IS4@x$Im`$Y$R4=qaC>C*U2FwP2E(9%5%Bbu zhOI+1C)22-`~3d&KlX+Ks&d44Fk)|Bj#mJu1wUi03h)Zp)H%puCWH@YKx|0UaGsn$ z+*&_E-3#9`nhy`0^h7|3$PfW0r7%onICvJI`i!}Oz+*vq3<WZR9yELDf&eCv6(E^R zUo(OtUr7*ND|{W5TRm+meVsqX^-sO#g+`?Wq0JovJ{!Ohh>O=64fYYyOo&7Qa8Lj$ zFlm$kh~L9Pc_tywP0nL})V<}tZD1zLB*!6(MM|n!@vSs>|Jvr_(3K-UPx-y$z30OF z;10diX4>_Cz=k1+%RpX~k&zJv99~011HhGki%UQfMhB`P!gPMqu9DaNVOuY&dDZ^f zW!t^&tY4@Z?c`*;Waeae>W}^dD23ar+ayUjtB;pg4w7AK;EmF^$;%~a??P#%Y`Y~| zv*YIFEAb--w5$6tw)K|LJVB)>?nit<KkOF)@H>OU^;l^%VI7o&pdI6&ePX6O0J-54 zXc!)X;E9dn_7n3UNpMrG5uCstnLu3wqM@RizuRuj7!$9;WXOKSsqZg%%9UAlR6_6M zRASy_yHtgLhh`CW<kY4%+jPFAzlTiw`#%ayX;6Ns9&HqCcZ=nj<tvbg5@B({%~$~2 z5W-uGl3$B7w=mt8D7c4gq1~LYRd1tge0<wWECJ4y8BcBh&aLc=ol-$A@~xo2y3)*P z`m7mGSD?;TfJ!IKj}5msANl{62{3`B@QNKEIfPk&s*dm3aU68RpT$WWWUajM=7TWa z0_!#K$CJ1RX_$BW)|;vQ=#@AhkmCw+qEKdUbxf09D~M3}mCJHsgnGgvgR~rl7)Yc1 zSEjqG4+s&zx&%M8Ki)bFruwY72=;*O?Cun4U60khIQ-hQMwz9N$-668BEI-Jki5ze zEQ24{PZ9gr83Pk9|HXQ&ri+%1O|^yy4|qSqCg?5AFTMPR02mG!LpohdNZ!K2K?V=% zKFX4W^I!=mk)tQIfNN%N<tBQ&Y)p=x4L!Mk@B#ypL$Yb6UiVRjiOaVpB$Jt+N(ypc z<5<-#)$?aj)<oQ%sF%*|7ZeZ>Dk>_cyCcO<mEdXs>dV()s{%fc{2&u^bLT)0ur->Q zY%!05Ad6w}89hDgCx!P<ZGN+T4tKEmSF#r1E`p`n%MQRJsJNcYhlkhI#cfOFI&2Hy zoJ4mPN!0(kx#(l7b2|hvCUPgT)T|F$TP_H`v-KS6U&u;rP{;pW{MMp2%Tlju=)|1) z;KY&1sRY4xOe&(C$&h8m3NMd2kxUl|*cD3UkT7vx9xl}hw8bER@Mho}NR(54eG;+` zkShurPpt)NTR+3T9IWeY)aE^V$kaI<Bj0S9W|^LW+nS#A3GAJFc8_=6eX~Eo-#%VR zzu7qPJW+0UA;VhCZ`U#PXedunlFQb-tL3%zc^!S6`mq;ir~ah8`$ULX3J~+0rhWHD zkVXL#g||K!5tg_Vu(Aw+G3JM-V**%L)H8%3Hk{sST5OzNbKHBX!jh8lY(DQ#K4nlD zG%7Ns1*mqjovJss3ZUX*ry+}^7)$fBH4&XoVRl?J^0Zn&*5=a>%s{w|r$F~1l&61G zXj`zOr-B}ur`^pFm{G=jJ-+sFfHD{pEiL(OzzR;V7OTM{OcWSI3Q%wXMWN!Qbw@K` ztFQsUBWN~#Oo$(V^Ku~)braD3LxQGd_`g0nc56~;k?K7+I`M;FHNr}aKQ(FtMZO$# zOw3!3>XhpDXHCfK46rpQ14Hg8xK6kJPxvn30GNTzmY=8u(SOzf5}dr;3D(bDCq-~@ z50xrGYf|x@+^0rN{9lJ?_BoqymsYoEF_v;UI~EDx$oL;5g%HFWctB^Zj7h*y7Kc)i zrlMLOb4@h$zx=1Y<C{P)@6#lz_fD@E;%-mwT;-|u&fOulq0gt!|7x6<$?Ix1)4CZ} z`rlLpW+Rg@5I`9f=4;9V?|uoEjkWkaA=1-*U5A=VF=8MK5R|g=DU(lW(BobD%XfVo z=dL+lEHD@MlWm|dX03SbMYW45Bl-iQ=f62Q|2dx;RmX#XniMCQLbH+O(@u=gY@3@{ ztW1r>aBM7GVv)QKP4k@{8Ce9n<FSc}>9|RM!Gb43Cxf&9<^jyZ{cd8Tfb^l%?t;b0 zsIq34if7FKw>A)G1BwYTA2f6ykeU}Wz@-04tOL)%ItT#!28u?brh?N94qD)6+P~G} z9EZyjPlegq!;fbwgPNERZH}KvHFWN~+2d^L(!F>y6(nGCv$nZ!Z~~nS#tx&?zMCs4 zWlmMK()``-?LgJjWrG!KrYUF5L5?83?F2Ht_8p@eX>IkLxV7QB)$hI(ksoZU2w{4J zSZoTrd^?fnfOHY6=bq+5;w)Z_C{W>ZV}cn|%!Y`H28uVLo>YL_hWLvyNppe{t>V=+ zIcLfGfnS43RtM7|$BN&d?n9dP$A86miWkoM8n5Z|l&V7S+%^4jlXPcw^Zj<iyioq2 z%L<4D{~2{KaeT}}MZOQn;d4e)yPf<ZBLhN72~dX&Z`)?Gx~=#;W=9WsDdz9hH_5WY zFqQkjX@QLC!iM1?{46o%8=U_2&Hoj3f0BU2*!(oE6xGPC$>{|$@$(_7%h8F#py1yP z0FkAYayKA&2IHf-b__N(c!8+1lh^k&jR8bFA_eR>79aRGfRE~CF+%gEdw+8@@XlCh zngWHA6BJlbQh|CN^o4{R2VIMo!I(LeL3b(uS(5_l!d!j58N{SuoOMXZ6Ej&*_&UoC z5jbjM?tBtT#|{D^UWub8MdQ*sZqVI1vFNr5>fQQ8(7};o>xXbDYz6wMsn46lMG@p; z$VLZjUqFFK{RC@tefMjC_(CpHk8hZ{i5fbd3K$$Si5m&vI)a1z4|YxH4z@a9wRhCl zFhT2iFrEX~+<H0Y&#zA{F;};zWvsPO6wSlcmi>ReAw(%){S{TRWvT{dhoMZaV`JTH zi78#q6OE5s1-#VcNWzl&2YD90kNSnDe_&xY=kcwU@6Elw*~m1{`)uedkc;@7rofrD zhYiP2mu~{N--4t_9+n;qPY?60%*OlVu{IC3n%eknzY~30T(X?9U?1Az5?8ox-eaxF z3hp3~AX&=T307!)OZW-jP8#DO+Y#c6(X6}*2Lpo09OhC{OplucbkjMLou$9C(ABks zp)%`GTR(Nfic9BsRo)YI{|74l|Mn=;JYaQ!2@<>>AijAH>#DQ7MAGcE&B2usprRT? zDfEoK35xzo<gT-(Cw|W_QH%vKRM=W!G9Ax~W+z(!FWL3t-Rkr40E4ymJ92I5UfT8i zdV=M}?=hm(YxG8kU<X!#Ka(fUO~nnL<Dc#|$+4#SH#q?--v7AXNT1|0QFVO}6MjJO z>Z!R6A+)VXFcB;X;5^p7;zTA3<p!04VmSgc*5W(0#;z_V_aaSk_PXoU#|Ys6W}!tS zr}$D#oi#dY$&E|+(<V$W(#MaDnwq@Kylo`71b4F;Wa=z7M4qO7hV4MCuA`IbWllj# zI-u68xe5x50Fv0F?Lg>k@eb(s(%s!oW4Z6&lNTz~X{HeYR*}kuapxdf)%G$P2L0WC zs4VFemzHFA5OYo<ez~fnc}a+zzY6sJ`$@Db9fS5U;y8BBr;C)tvD5zgi*NPN22D)g zhr{!>Ih;NLQKEbxvirL{JSP=gzhOqecRYW`m}h&6*ZgQ|o(3v?Hp(La!~WA`0xSrm zSv>A3z-A^56wgfocS0S&-2H0}<Sa-Lv%s!y>{W|mP)8|GADoXIVsw^svuLrdgI*tY z{uYKX(E+Kn|3y*T(mmd(-Yo~5vbPHzp3ZEp{lEBr{{4iMQ=yQ{#$mHrjR48WDle>J z`5bzE-}~fG!inGWF-3Tir4(S-j|ar;(ty{f&}OC1ZO{}G`e)J?aabm?T!6<<^qqqt zoUQcC#>L^LW7Bm1z?b=b$Bntr)4lb#l)0z(ppEBNs5=?W@C&82-p!EpR}zP3mzV<B z#f!gYExi0o@$|`(gxydE>_Y&E>C<7>be{4m9eN!X0OWZ@5=VA9#2Ep0@-}4(aJCr( zGNh&7qJTZWrC9Eh;AmyC`>D=P)$@`9(q;G(*MJF6lJEw)M|+{4;EnQ_;tl5;P4iiD zh5ozv>S9@8R7}R-`&3OF^$~;&H8K7$O3L1{JG>a_>$4sCy<1nAz2Ze*Q_0ASgai#8 z-BhoepP9_!-EUIiKl72*Ij3^4|C8_t1|o+^8t($F1OTF_`8v!2hLEi3(LB{7j`jC+ zW--R-lY<O<H!N(*ud~DR)R;KHAu_)<ULS4T<1<H;Bu!0?QhiC*Ecc5{vxFDt*C5JH zkzsNjsEEjTb;iGuxNv=$(C6fR4=M9@kZHhqsIy$ti5h*lqcF)N(EU(|pQ0);izm^# zy+z;Z4M6CZUyq$sZ|#`#zw2ZDJ9e(S{$tne=)-nrc&t^CuFv-$kxWqN^BWrj2ULKM z+2eB<GPu@-?tQ2pB=CCmBjOXoiLcmXIVTQhYos*`R6ytFNfF3Csc52PAW?Qco=b$D z7Zs*;N7Hx-wl317=;4X{bXKET818XeXwqX5lintM9Ni<ryB#Sx9A_zabs<PfvY{Ry z+3zo)>DEyJQ9SMeI{tF@RBEI%?ab3)q6SY@aLj-YZ_guzrGFaNQ%fxb$i8{sQ;CcG zi3<5#lZZ0~MX_<VM{r4yfK2konJ&=iXYj9|lY8r3cHB=yLJ;B0&WPCxRxwmGG$An% zp?B&W@G~?p8Z}X*+T2`F>RE65JV>C+&xW^CtIzF4t#{{7(o`L0d%ujVEdJ@U^9!Ea z6nVkLqQ1U9MwcUnPy8$BuEFvqAV`H$JlGqh@&l^fgpL&lvIs#a5&<NC91xEX@qgMM zMj=7`R#O)&K6T3+bc=-QeUOjtk53~FJYIHZs-4{`L^UzKZnCd^?YT@_I+WvGv*kSc z%2A@Rd)u!S++~-&SjXCOM<91O@Jd&qpk=4~O%BZ5vVf(f%4vAIHGV|VGV2Yk%;uJy zVG+15AVA}WTzZn8^k}PJSwOa&h?P}k8Ed7{8smttGZL7T`S$vipazD9L`Q_g`?SiR zNIN2Ky2-Z5R{%UqLP0THimmicOgyf3eSPh9tf!}!u)-tFK*hv<C2w|3NuUTEWC;Hi zsYAEt`X!*zBSVvnjf@Bi1-=hU0~IUqx$gN8DjIE4ZgI7iurNguBrXwRG5xw#G10N3 z*4EY#O~EdH(S4V`%F>bLR;+XpwD0*FEsp(r^yrh}rD^tI8OxOS!Oto~Y7B`9vXR_> z(kyIPmyVB*jTDb%58|M4h_Ml($K%%4)(}w(YgtWTw8yG>QUQGiB^}$l<n_ZtXi3Sz z?w?hi1ggUU(K&)@;I9jPM@J^Wg#*_<&L3fF0mzgP?d|Awb#xGMacTE}h8)6rdfAG6 zZO&5X3f>`mr>C&?_Vz@p^E$Jf121(!p5yI)Z*7KXeQa-Lqb@Al;*aUX%sYZ6cJyVu z3nHT3V#?hT>#c<^LOu{s!FKNj*MC~VCML<&cYh)%hA9O%Q@HhxK05fc9wPtyOW8`| zo{;xi4C;*S%>U5mZ(U<^2_b8>f}<~P?WP+HLHo+%y6N3#ub(ONygr+WgS_tU@`03| zA+v4{x9-jA9wOTPwJ+`<>B3N%l;3({vgo2dBwP6|gPC-_mG$9w-r<kOv*OkX<6XbY zNAlmDH4^1=@D#krn4w7c&(nHif?YUbO~k^QU-Uh((82Tuiq{x@QrD4Z27f&zQ`aLB z$}W6g=(CT__AK7Oy2~iqq>pbkhvOR_e28gno%dZ-S@P~*)wy{HdEZlC@)q$KRy;q* zW`n!#6!Hk0#_oTB=&a^k=LUtJw)qpO{t)U+qwwduOT~_|Nz=bg|Bpey)=1`$O$y59 z|L*e&;Q5039)J{DVJy@&Ng6)(9WtZXoshW6$&Ud>fn)!)m#w0XyFS)?P-I&h<+id| zFt4Yu35d?5@7p2-;z{zak9i0Z{jn19Qn?7u%5S*{D)B41vC_((7Jh?XrPakZe;^}9 zY=CzuK!65*gHcXJ9yvt2Az!>oBr66Hu*#Y$fs5k%m^LOd0le-HZ^oDiL5`93&x*2G zlIMWgEEy5A*k>66OX7MV0*PY&gHrf-N7e<5@=*TL<7_sL)Fg6doCAKJBRwPmg~>@W zUxkyYBC3OgE0lD&zCqMPG9w9J4i56?p8S`-S)GUph;@eI6QVUyv;H-mS$nZFgvlbR z;$NSy_99Pzenauwxr{zYsDUxgS7t!44{vWe6EO>RwLaJldLdz5gRPLa`_U4Vt(joY zQb4pL)s1HDEX800T$g$D_HE!v{$Um{5H1)*@;B+$hgEXQxN=|TF}$jNwF|hW!#Pi5 zTLI4v_*fJ6suD8e-l_%8cq|Inm8BK59Cn`2jR<F@OhZ93doZy*oe^a}LC*`Wma+Mk zzYlE=xC}RgKbE`;1kY_WCXRkFqK&QrA7mfD!uZfm`YLAj;~?yUPPy>qciD;ej|*LA zXDa?n;CA@iTXZ4FZkvyL|2Sv^_=|m)!CmT)-Xh-3D1LXigtLQ7^KVsjgCdKF4n_#} zS{9C!&w%xnEGrtQZov}#Q^o25>;~YqWL_&7&!t_-ZDrX&II{!zVT1O|JZ}%67yiJ} zbZHzL$}k9u{9-nR@q4>h_W?jG9!Ghh-xBYujtd6ohj)ScR}3I`0|7XZh_4<;==qRr z(aB-YmM7@BE@S3Y2%XDiA1WKTc8fO(o?{}S9%<N-cKFgIJ|TrX<j$TpSc!J{$^?A# zRgFxF_+GszE6o4*Q~p%Yz1i*%_EdS_TLSi+4)W+t9fOThI}OGrj9FOc+M6wMA&K0Y z2@m%<9nT1PU$e?9A4LE513%}shmuy_wp){P{HDYDq18)fZZ`NiKR=vnZoR)e>{bz~ z(Fnwak1b$1bqmCl!b8$as18ccy(<;L0fw5-{HTLI@T#+yXMuSu>A1)&m`h`<?eSjV zaP;i5nqfTo&rr1o&lNAPtf|8(p0kt2w%Mg32RF+%uMH`~DNM%)OzxM*F{3)!V{19A zcJCX6s0}Lm2RDG1e4sBFw$^+a{~IQwAdet^9W+Sj=1PraQe#}WpTTDVw#NpS+ePvO zq*8jeoVHRJserI*OBzc<P^TAN9n5v^TmQjL7|qH&!gc>r4Xv(n8(UpUsGh-{QJ&+> zj}_FJADc=7rQi4-k84C#x?9-?oSOD(*~!btwfrlrWf$1&w1-USV(E<Q$mCt4kJSzn z)T)lVP~D+%`gEFXku6Z_YmLSo&rH4WZ^iF>Dnu^Kxp8){XYvGUPL9-?<_vM>ggj<_ z2@~jUO=Pm$ocyPrZc%>ob&B9-e?J_Z&>za^@)wCOGG$#`?S^SyoQ9f~c!nx^nYqF` z#9bzEDV3R3L~e!vsN)S~d}E~UvnQd;HyQQ7SD8S$udJFV3PAC<NBoA2G$+@t!z!_u z9jy{JP4-fm{?rsNxDOHurSV=@uaQKdB_e1->e5Vk48C5jN|Sd4B(-JL9G`AXiMoKZ zDf!%~7O8D}B6Isiil6Q&$)$Y1aDXVrD3_T?K96@pkZdSO4eLK+b>*v`VSmFj?d~lP zS#rIuH~!a`t<#i<D^?aLPA0f0vgXZ51YragapUHs@y30fz?obq<l$WNLaH~C+JFf_ zBcTYp#lnj%M{5Ji#r3kB5Pi4}bwniC&gmkM(1k-06TpX9)AidnR!^l44q5&gpvVR* z0rRuc#B%pcCWRKsM8#G8B+6NpUtDDtecyBtThfMxn;RSG${+#6HiH)1vQZFJQVA1Q zDk@2O*xg%D4q%+12Z)6AEixA;v8idsg35bivPa@<|Avn_E4Rbvt}WA^R@55cV0(Oj zXs1z|F<-chvAMv9v!*Y`5$mE&J^I}c-%UQ@lGWlA<<VqpKsLwNOD!cs|M8aW7sbR8 zXRMNFZ#T&tGUfyYLL0$#!5*S?xMz<XZda>DB2JT$IPLOCRB_8-K^4ly%00l839z#n zewG4?kYjSg=ey%iTGkaHrwQVXjU<*&I_`YfK)Km)-}Dv#d+wEd1q(z=0VD<iJyE@Q zGpv8KujY`lausiqS>{@Q{AC;b_<j<ZLgW{e6N8o!YbfE;q4Mlw1cCmMHuC$6q$2v) zX5Tkj2nm-yA2asUDY)e93m&Am2=-h~w??o)=MhQ|mls+230dg|wjSCL$DRLf);%~# zs0sTC%%cf-IZ(JF47OX%BZNgDg=_`XlyO1q;quW00{DRVV)m3-v!)GTFI@q62iSMc z5o=D(Ck^0PDa8Cn<pY>HUZ#)Wz?bhqssRt=;b#4cw_hlust01ubu4VD-ZLr>`E<?M z@5ZKP!xiB#H@K=)shFL$B=;jmu6Gh#9}gvM3Up@BWvF3U@H~yVu^`dD*AcbEmk>?_ z=?_A7=Te`PTBG`Dpv0!cOryP`hmx_zPi&2(d1(IwHl$VT%fzT@bGyLESvQteB?`~a zZ?Ofnj1^eUhjhNSQqC&zuS4qk*MxioxkQB$K{8peMMAGG;8%7yT9hcBL#NdUSkmX9 zg9JRTRzk;C0Q3Tr&#OVD0m$oUbo+IhXeml>eFm}tBnr@AdnT?^eW0Gh#X^rx|0s0~ z+OcVxar=vvXOc^GGwxlaY4KNDKxN$D1F&>Mc9L~Z8^Y0rEvKuDqZHP?z)e|7LNe%a z2b$7Q(7md@Q-6PjyPDG(@8s#JzpQphu%0lp0!Djb5|0QHKhjBLb#0%ON+}FuAB~t1 z`#<!Mx`$Zr1vh!>O**}x|E_Tj8PxSu%3nt0izHSOuiab~sORRVS&j^;5U6kM0JcCR z7t(=~zfHE0z#zjg9*ROLusfEOh1E>r_I+kGGByro)O;Z%fZZFBzx!%X?u6X=yd6qV z<8rJN*GO%oB}tU&#`mo<IgNUH_kTm)mGDo<v9%AgGpBeCeE*%m!(WyCVsCvjGiMH? zzYB><e#{`&GzCOx<$*m(1o}&-sjcK)=~t}eO{by6X8+tz_l+O-*YsYU_rb>IwP58B z#;}LR*E0GmKFCLsx<aIyedwH_12)q%@_a1&sxe&*AW);O6@)@2>R@m?{E*&$HFfSk zdkXz;o-lyn{#qe)uBbPg>;u|b6@+3?McZ$5VC^kr45W>K71L)4`0IsH_~V5<qqaTS zK+j!3ge%QB(uk&%iJq!7D|OK)5lNT;{XD8+b+>)DprD{!PUao%q3rI_k5;0587aOs zm3icl+cF(x!xQSG>{aY8Ilts8;ds9{mDOpDiArB+SL62Ur^1tT&!d~#%;C8@S%OuA z_zNAF>1_w&f=5h&eqS=;QoHyIuIGgI++uEEZx|QnIlfPlxl;2DN1pA+m-M>*OB<H0 zt0Qcoo<4H#=mz!5<j*!G;sC4A0q7?*k<EuQ&HwTnses5W05guu`5?_zoZ?{D{J%T! z2NChg(b-U3$CMrKtG-?&Tl;i=vOmgi><?5qzH6p~J8W14bBxeHtEa%t+V?X%5^<7| zen>?SL-y!?sSD~eixEB&+cE!&bQApFe!&zWjEdCpO*QM7a{ry%dXNwuG|YbBl2+=p z&e9G6#r|28Eav2Efa4kzYO8F?JLLvuL0?x_C%D+k=?HcL3d+UBH8MF_39IXv#@|AX zhPhGJ`u*+u7<CV<0JD4>15>f_k|tQ&)6RV!g3+{WG#j5bHPIWC2(h_wD_Jl*UWjRh z(|M6ge?v^OVLu<kR-bakAC?LB`d#|?`rNB?n?_6I#3FOj^Px?ccrKk_d5mxOvMCYz zqaA_cSWQ&BGQl3e%ty@K#9EJS<L}{Q#0~r<+G99a3QxdqQ;)*MOveM%U3*38!sP}B z2c^>RIUT<AhrlIPdFI|g{rP%&vQS|GxFq&!TW=b#kZ}V~L<0PFNp~!y?8~3EDg@X% z`E3zLOze!zx<-ZA{@sdd*@29uCDY{Z*#Lb`Hh&;A;}2&d=`wXx3~42d_Cdtks!btJ z9K_hq;TRWq5%sL&K(`(rJzk?gaDCS|<NHXA4{{MVq@RUxmc?KUOJ=#PD=6?XaB2s^ zTq)<#L6fE$zRe=OR(MzXr)nm|DqAcX312N~N(+9}AA?&O-<8W|KXGsp|Kcj7F{Ibv zI@<e$OhEMaU|fP}dPo=3`TpiHB=k%AS&6%wfdL^eZ;M!ch&$x6{{Z~BP27Ww?k_H9 zasa9J6Tkxf$h-@uk!&Dt09sv1l?2U7BJlvVLrQ!Ulmcxy1ZQAN#SMgr6s(DbeD`o; z)_XD)c;`j$zhh*5w%f3i=5_Iwn7~`WJ8l(we7r<?bo}5-DrY^W;sOt1=}rEqQI9CG zy-HRuy(Um*EZIG#(>D;Da|1kmowmXD2W<lrXZW%$0V2>C!9UbqY>Sc$2>N}q>^agq z<Lj|6q^)_3!LQt!avTEsN?0r|Jxa|Z25f9v2h!jUPJezTHF}Ur$DufB>*EvhlXc1D z|L!dXVZz>63c=rtBJ7$-tEqctB&AcxrV;Lygm34gyFUHf^WBBwqz5(ST2a_H6WQMX zYQCBAPZ7_6Gf?kB<LQqAt^XA~YHCXTA@$af=<lN^Y1A<{4!w4B!ff0XRRiwD^Eqa` zvesaB7MwPPQmoxto{QfOM?=~$614tM#iF&e$ur-bn{)MzA}vreQR6&CkJK~^3|sBh z^WO7h?RWdXMW-!o56FzrPW<R@SC4L*q&fU=BUTma@f&AWJuV8bYpV+xPzYlX9+TEy zAP)ZdGfe3Cw>4T}LxW1h;s3TF!JCQlAl@X5G<32$w7lhH`<=BlNTl|@hH5<R)3QpR zy^{X^1*{ADDX(euS^=W2Y!BBH!82b|ZnJL}Uoe7oWb2MQt~XK{+lMJx|J^iGbsLg9 zM}^d3`?!y+^=<9t*FKvpS9zST9l;-T$kTX{4K2-UUMyh8wdQ_BDX=R1qcKfP9!+cY z|6>SOERaxBcF6+;QV}eTb!%mQ8ri{c*J~Ew@%*Vl8sTaqC@GE|9EBW$=0QmoDhT3B zou4oOJ-67);-^NP<a5R~UC|WgEn4D$xxVkAac3#sU3g(^w8zN^U22xX>EL@c6cu>F zdiT9@<z4W`?dt%wp_j+XTGsbI2!GA1>aVd{Q|5dckieY(EmCyCI3YV>w%w|(pqOBm zR_I>&Eu++3cMfAOS?6L-aoLg>Sm8#%=qdiUo2Mc<XfTzxeX|ld&CsC_t*D?mng}OR zz(CA>QFNclWA+{6uaQa2I;Jrp*a+>(Gq$0}f7#X^S-X$*^BXeA^s@*;JQQ%CBu4Kj z&C!#ulHA-Kgl^tG6jQgwj-Qaa?a0-&ta}$7rUi}#6+w>-${4VwK016hR?{i6Xyw9t z1R3GXH{a~yO&s9yteHaXh}R=s<WDYoPK*CylV4Ze{4NMmEhnhUfF5kp=Zi*G#rmu1 z)YOQbT^&dw_&~HCJ2my1ZMoGPv>u|*kOs%>TtP!$L}Szlu<$!sh1mtVt#**yGVmZR zN5;otNymnOD^o`#<f|G}cptRT@qFXT3#)omc`Y|>d0z;1Fp6>+DfG@WBbQZ`?TENJ z!Y6er8k;t**iOmnH?7x2(c-E;kuWzMGMnxglMYj=T*ryFeEXZnZ0a)1Oj;Kyg)4x2 z%L$XN?qH32R(5%=t(z3q@zp(#_vL3(Da%~*_2u|H%N-VWx;kp21<d?GJu(ao3@Dx| znWB9GgY(59xpILdorsWTZSE=a?_lwgf^yrdn|lHfEzG^kvuA;6SIeLGK`VqG@NF== zZC?`QLRwkZeRwB;IFD5atnT4b*fYEKJ`YG_2g2tMT=G{l3y$@OkF3_ib@|%=m{{?< zc~`w?iAIa_lc*Q8A1J~xw$vDmJbl=i^OxJ9GTT16=&Ib-`OZ_2*PQz`e~g=)5gTn# zN{J)uM`&;T(u0H3zmy#-9zpc7FdfVSrV$c6|3fz9Dh_>a&?y@zg)9Hh(*Pc@*|@Tw z5T?L2$?Vlc*o<JHGt01Ma)P>k0nsu5y3sVRCc=<YCwo6*MkFGqfd&k%CM*c6jwtx> zp)aL$hp@!T3iUPTSglqH`?}U1!6rVhtX1M@K6$){>SEsAAP`ol?OR2Ez-Q2uhC~%X zcN4oWDI76l)6*UF)Nk4^3|aiK<K`n71+h|<yy(AEw2R1ryYC=Uz2{IzPOaGjIfW`+ zagMzhK0C8HP4|S45o9A&U~pqE2Z7WRLqjAqBLS*b4o8O<7ka_JJQQOD7mx@ch`FA> zWu_~4_kjG6Rny4CjE%zcCow+Uq#T!INtcL9YHjH&P}Lsc<GqIu-e|<wyTBLr>RTcp zdijH2+cH{D%>YT&{XvPVm*q`pG2rp|?_|1*q%n4{P`^t;?@sFRp}SMbi-a7f!FVr> z9?8Ram9XP=PVeAVem7LaW+PFvS<6e^KQl_EKlWux=6Fx^YNfFq5qIQ{Q)h6E&7Yq8 z10rIoyWBR+cck526J#k&qQP+iacq1XB|F~4tCQO4M$V}i=WqdHzjX%lEPiZ$H+@sc zZEa+HV6+g^1=>~-u5({?-W@D#CD)yu>%PD{0YxIW80k;fid9>YRh0lQFD}4l`R!Dh zoP1v8^rHh5ST%CRkw$pDLCX>J!J!4vIP||Rkz<Q#&6bU<wr4S6X)8KNZBmsM!K;>z z&lp|f#I>&sNsikyuhA1lBXPSzB=~9lKyGs0S#QKh{6H`<Quz?lEnlD-;c-QEfi+J| z{XZ4}=gSjIu@Nn3Xe>$}6^_3s*Qv9nS(^wG&d>e3z;mX2XE3*{_Lx(w*0@^Tf)NA# zwMBZ|4Lkal3VZDdtc_?-e1VYr7Y50xugbII+rfWnzeB$A>eM>Um?S=9qr;w%swH6* zY%SX)k-w4-a&x`()=zVDLTcLSQ!B`T%>D(&f}mmqz8^hjLQ!k#yHUPM=1OUi)b^wk z5DTCKYo^(5SxGi19x${&14SZ19&FJBHY)U~wdSuE@s&SyqcTZkxiU1*nTXSI`PaRA z$r_-QK3;=WRRYD0$qP7{;9DtTVcO74)3M@0SB7j@bK29GzU^+~&qPomwf9tS8ldWR zew${O1q)Gp6mkBEm)y|J5japTN<BU%Iy-Isv!9Dl(twq+lJgyVM?il{)GO)gcs7!W zPF3Fo>F@7R=eTB`;yc4Gq6r0KfB6p2OWQP-d>l19t`L2AJ=8RKikfve*d$$rkk~ZH z+lR~Ueqnmsgf>p_@(B_Lc>F%Mn6<P7f9ARAmJCf-Zer5}&!!;tZn!w_rlg${s{mT1 z<RO0s7yC4Mc4PLnpI0g464(CC>&oiwlP`mx>yZH%Zpw;9kMmII6!1?>LIsa=m?;KE zbYH3GYn&gMt1`_8bVv@vl5t#GGyU#8=Okc}%GtI&Fj)2QXUJ(_=G|jY{)kwx<)Xzd z@tAOJ<c_pPW=A7D?l8yN9D%Ddra!-lwa+%a%83QzVM!RW|Aha0RV@{Ov60T7=1F=P z;?99LG*pmUnX>A&gKf<I+f2l9!km(~|94cG4570%=u#6y?&GVq0tT66Fq%+vfBgf3 zO*XDbrs&0Av6C0PDf4Rx)``QFc}~*3;)3wzbG5p{h|j<pxR!ZBP+%koIe0Dr&pp5w zv8I@W=%4WRF64)h2v#B!%*AB%{$EQD;ndf(h0<T7)oxir5*`=Ik}nVPq?P*7FtE}C zFw<?uSY>UFmSev)=(3lG$<0WrTjukj4PB)mU}C1lHD~peIKq1=dEe7qzJsKWXgXZp z@!x`7a8?Tk%Tri>i@!k?eFodIk_$nUP%9fzhyK5<9C2&0^kmkC(?UN<7HMgE8o}jY z0I3uXY^{$Z4Jzsh!O>KKkr<s$tfbmc=&@h^mkFy?!KP6LjJ^I(x$GEv0UIP2o&k^b z`n5UO=n}p{9M#Ldrsp-n!6UqxYw}_JY<DECkNa6;R#{V*(<^e`H0BmQOgN`p@#&Eh z2OsHT4^w<CaZeMCIM$9y*`x>*i5_fF=5*N>f>t36Ysu@o6X71m6lWLl4j{;;1<WKA z2a7+xLVW818jsp{g6bjP^+ZHP?MXU-oke`%8Xo8BNImBC3GGXZH2X^qe*KT2iYY@c z71?A0mi0JhYrwF;F23$D*qlHj5t2ZnpjJ6*_EZFn%KxRMov=iqLeSny2aVQgh$3T# zju>+~>NFU{7SoKQjMkNh#khhEmSzYiJ2}tzTY=TtFHAUYAZI0;RNg=+UTT-7kHp`q zdEM3GJVHYilo}}>ThIp3CFdD{MRE(+h}lY9eOcj0ZGfI-TLaK|4ArWFT&%1OFh!n< zz~b1m0i}|ZN@Bg~7H6rU3vTWFMkyC2V(CRal9x?_NL3fPhrO6YRc@_*HQGz)$vO?h zev>&q@GuOw?OaB9F)k^inKfZd2n@eBjg^~Y^<{cHX+8um)$%~+X4*}SDPO&o71SWo zy_Iop7A9$fHpF+Tg%8`t==-LlHMwZUB+|8lZJ8(-YqQR~<W3HtJgYxXF3&#$e)GeH z#1^?B5}Ny|SL=bVBpd=GgBsKXo&7qLA-?4wY!U{B)IwQ0y$JW5b(o)1+ZN_@+>C>H z7h`5-7Wko$-Net|+8;bW>qz}n^tL!3%=TDhwuW3Jh|#;E{t@_wUZp#O-*%E(ktt1W z`*J?q^^XYni$|4n975Wi29%`LwNTv{;E(D5nnh@CUNT38*Olwj9cSO+AM(f?g)!55 zO38Ai1RX62k1Qj%BBiIHk?{~uNz&M;t!;E%T|q1(en1s(I-}PMid2$PxC+1m8<~da zte=~ueZgc_&XjNlqmB*`xv)|3O6m}dCRWhWg7Hd!etev_;OV#t2^72-C6P4CR}{6I z)aq$A_a8EO4Kz6boBkt>;`#RPoDVV2eSKPXO*}8@sZe46U`yIAFjr*W>{T~NBZ1`n zi-%~VSi7mdbRwNr74`V2_}LgoocC*7oVbRLk0Jitt_LPj;)Q7&<h}X1#mwVI+FCnX zQ&zZ`ju(CAK68U5Zb1BmVJ-to<1bGMbKLe{Q4jB&QN9=`WWWFENPfY~d9aGq+c<FV zo?8p)&Gr`FdrZoXCn6$J(yu^{W4Uc6R!u5oG9y7gojOC#e>dg9*`MHu%1r;9+Kj<p zm~dPK)I#Co%bq=PC3+A)GnvH1#8=D4&uU@=fk-9qr`5mCO=rmnv%WcfDK*-GOr_WD z%M%F|6kt_a&fw3YGI5)!LJW7k`aG%__=7RKf6%Z>%RPunzrF)4C~x3dRLj@55oeb} zlRkQgpt6{ComM5Tr4LwR;WPQ^Om4%hC^Ap`1<VQb8+^8Hdru$XnodP_ObiH;QKyWJ zRFUMndt@J<mqPPkj0q_M>VqZ)a@r+A4AwiYIX#X;dR%a0q!Nbwi0Q(ZaAu420?M8Z z-px2(H*_cYNAMDb5?jG~N9n$yiD8Rd=h|Z>O}zM6w!*9oJ}vvdfkLobS993;^#Y5s z1DF-;=cNOP!YII=Fb`FKcjpq=n)?%gW$ywl8h><mzmGq>KHXw+*x?!(8O5cihf`#G z^p)b{fByGnjKEh|bMP6;el;28J2c;{G*H)`I7O&*4+fneob0Y-l)t0U>6~zS=RCV7 zFEWb1e$fi1xIbe~P5NUZ-F_f!=;HPt=WOe2p19_e4n3M~gPrmF>l$!R4UrjYTuIe0 zWQ|$IC{sD<NKS~pI1Ht6Q^r%Ou6#G^uiT=AU^@-4RcG7XaC(9=XUBEX^K9k<y+;BW z)>&j?K>-MY!+;22dt$F?>9?lwfQ3RWAlusknq(qc0sP{xpFB;L#%qhug+~u6iIhyk zcC5nL-9_V`<QHF4jSw?-+n1S`@4)EoRUbwOqo#mOP38YFa4BHkj&DQpun*4ZI1ROC z(8Yrd3TK5A^Zg?u>aY!0q|m&a(PVY7<>N~EsP5eNIL+~niinPB-0{vsb~0zJBoei9 zj6ZlrQH$JpeBW3J8{xC)fE&0fp1Z+_(@;?hU`s)!b8`v7z`)W5n*i&+((0!!i1EMI z{gVht>KSKdNt3I#bk3540sqA`E~6-uVkug9wmHbXLhMOwf8DMA$K@YrF=q9>W8&+n zR;D?*lT?GWZl4SIKfCJ0x9V`YWQ+mBjt_{k6Mf{D9a%fDcJgW5Hpn<#1=@Y*fq<$6 z56^#6QGXPXyHk>*U@e#M95p&VwHShYqMu(9a5|yfF<Zm{Dum$vHJ>c5g2pYUe`lJ` zD;^!uP;u|D>4<L5EN`_I#%#RWUqu8bX>SW{bYko4OJFLlt?<T`+Z0BU=!2H**Ey}X zx3&zxAh@f-q8hJ{iy@;sP;57zzL}7#7v`tQ7|=Hb%P_xrzo%<*c3ZGBH(B2s4s_ff z>v&l4C&?A{#W73s*4~V1)c1S)t=n~UZGWk|vCcley17Blj&C^C(=DtZt)g!O`b$x` zK!+!lZ}#E6N@-jL@PqD||JYbrD~;r*e=R>iEajMh&=f@uPwEB0)Ow^8)_duL9^3>1 zez>G|WXStu!H#mxF~D*G=uOZwU)H_oI!r`_1a;LS=DXRq&UPON4eu#}?kNjuS=PbU zR5s`sXulkjs)S%8*9*0@aM%ZyatI(#y#MM8&%{U9YYkvETd3$#vh0IMBC}2}b7%N2 zm_7CiDw!@Ft@>9ke=~B^cqK<7PQB1KRE0x4J3G6NrA{jy?!keRs*yXqp`EE*6`|~O z4Xg?b908M15Rehn`}+FADLs-&<eDKmNP;^mE5y-5P{}8#8|DM_6a-)li2+TDk<ih} z&%6MA8Tic1jMrd6e*QAY_s;FsyP+Wl;E)Lo;v|{+zG-%F?HwHtt(_i80~#75G;^=f z8?HMLgpp1F242<q0mGt;0|E4<J)KoJG0{i0!-v9U#y<Z0&b%VfH|M{lkZ2i$uc??4 z8Z;MKXh=HhWneAMajeBbXdd&GPd6())d|j7Q9&sLft_HGgJ*gxd|Q{v*a5PI>fW7j zq`<SR9Jgu;#-r6zY|-VkGMbU=L76G`Sd`j`J)eAMl1~77Ndkp|q>>O)2!D;V^$XO; z@Mlzs4SFB4LKtEM(508_Oe4X}u$)2NfR>2It11S74X-%gQ-|zx^9Ce9pvuGQ($pY2 zd=pv;2|v@^^^kq|8?<ilQStSH!WW~m{7H^W?8#20cK&1~NwZ>eA@xqkgQdHX5$~Hl zGm@WN9cxk1iY`CKPUz62RY{l>s{I}q%7@SR{>L``R$yeEFTPHypu3m@v#B)SfadHz z9%i~TDq<%iW!!|`g2jc6|C{n|*7r~cK9LHjjS4YJy{-xYt&m5f`>FcJyG;~XcadF- zSj-3xe}OQD=A6DnlD6Hh!1JrW+cLs<maSTI<C8ypYVI!HCu$8?GV(|h&qz099*kWh zGN^spr6(ZHZCoO>0vM~mkRF)k2ED~oE_~GuSzeRRt~Df7n3^!tZ*c(e^YiP2m*~f2 zBQUikR<KWl1C5{9{&%@a5FV}t^qcSbL=0t1CKq+^PV$1@Z4sBKx*W^{X*lj0STS`5 zXhIW$RT@SZsR`_ayhbW!LmW;YTwx0N(E9E!Cdl}iTxpm7WTBJ`2{L07Y+^LsZZoH4 zG+CeX)tjX_?`O_m{M-l)87c&l$*#C$Oj;rYc9mHD`zxUC%)7Gg|7?PHn9)@Bttio) zwh@P4IsXo(@z?NmJzggD80=xBLQ4&3biCf`^+wt0)z(_5+GxR>`P5<2n0@R0nXPE# ziat$RCG$|&a%;!rOor@w&u(G<!$L&`!N>E=o@gQ+?*Gwrj!~JuZx^22WZSlFYtm%f zHYVGy$+kIJlg-JtU6bp*=l5Ul$3C=H&(n?b+UMTK27&yT{sPjDc;Z_Gp$V)gyoeNQ z_rm}@NhnZi8kh!ceSh7LXnc1#8JMnP?di$$@1;%vqN>MGQ|%$jHTN;c^`~h4Cbv6m z8BuTEm@RAHDPZ*Y`UJ5Ls+PFWup2$c2o@Aw_Opsguipl^6w(wDXC($%(x`B$qcI0{ z*=3xY!XshWVdVKn+pA|gl7Lg8^_ls7sBnQoPK^w|gy@72$#>YHzXRRsC42RTy5P*z z%#&z^#3cz$mv@5a65U_T#3qd6STAhCi>7)4VN^jRT8wlS<yJi}*doW+csY&m1pgD; zLA*#6Yuz}YJAwKD<E0wi<u>QiZRt0F2n~d`ki=+2L_}r)6vH~O(X#-6&0Y0}7r^#~ z9CRh@kt8WX8XM)rLTcc?9Mq05Vx}CiulRcz+9cRQls_tJiq-2!s?_rZ6dMjN1fY*W zcN(KLAY6cO%hPqb$Xh7ZDL(Y9K>L|61TG^a6)H(jlu}I#5W8*_o=M6E*WU7K`R3GU z@YOS#ZO&p7+VO{8xk-xpD1RzctP=^f6AafD`@ebp!5HP!@*f>y4vFzz41p<gk~b7; z%(+%+C+TUz60cA?kLE8d<<iskIk@;IC%|I{{1~<gSLXJ(HkkPx@lVj#1kdt$hakj0 z1j-DUopUFT=tKQJd99jBJKaD)=6oz!_P&0FpLWX@f;#CVt9h3(5TmLO)Vwa-plrBb zIFAsQUFsL5*@FggorOos(I#<KT}h7EhtS+w_z9B+&35ZJT&WC2l6qqQ=C<Duf%o!# zR1@L_*{z$TkP0SuO40NjRf}Po=j)QcFBZ-UdXGLA(SU86OEN32TMp(X9&l0R#R+wx z6wVRi^!(eQTj2!EHKCbYJ|iAt!JB^yxxBqmPFei97h6^oJn3QcG~m$czGrw9TFB^} zSZx72!kiKVVU0PHQgN`_nMC&~S=&2@dW^MK(SG#d)3K?bC1zbJ@n%n#R<H*e%vzW; zPHe-Q9>(geme7&U4*$3IGk^s}XloSyU<DRibkVh<VF;?tT%tb+($muePu3mx@YIWX ze}1iv;3FU)=)-I6=vWea=$zsS7xEMqNK7j|{UhiHLQRlKs_ILyKS5U66>;BUv5=a? z3@V`OmA}zY>v$2Qo}TI$1Fa-|3$Nqti_k~l0rz|Fl7&HK*hnT_Fs1>w=UW$vgy<m( znXWqfOi6wBEU5E?Pu(-t6uFtfZ0n}QhQ`@lACsWwJF%Y_yJ3?*UqqA^wn;*yg+^3O zJojiCRT@q?#0r<&9?Xy6Uo7VsJ$8A}Bk7lTni7=}uk`^UV_~*{GhrRr?l!w`dX_o> zOuNxBq-sh*0D~){i%Kcql#_nMB;t>!Iy?SnaIkqns1U{@xSuG`Z1J1Y#}l?WK`ur3 zUYZe`j!0ixNV$-qEP64ytonBJ#;|0LV^>$##b!+*n^fd;^-ns{Jxj!IQ>fCz6gy{e z4hIiM5Ry^ij?AsSSn=cEFkwhETup5NxgISii_%r{_dsa!BtddbB`H(GH}Jb(hHF~u zf~7{xZx0V?JuiX-#hIHYL=r)O02$lX9^q{pu9D+LfPSj<)aIG5?}5vVlgUV!(8t${ zoEL)CPH34Q4=4o$&?=uv(*#|Iw*N*+H%b2iTa=zpye62MZvz^^4RLC!@*FZKd&pB0 z6>3Z+WWEb59<G-NS5sOE2pdj(IvvpQES|?3h<%Nsm^#{jEA}mzkB)t_w6CE%HM~KT zX(-2deLy#Lf2qY<H6Dp$Zu++~>CHn>LacZAYFu<^eB{_^a2r$QJe?9IGdH${?qBXk z5BU<bCT7u-B``cg9wr&j&(fwX_Rt^3Ud9>_BCd~2V9K6dcBT2R7oY?`dm5@NNv%)I zUbe4}Okg$JdeA>wjbllapiQU2nZ?2!aGU2}pAFr!{V=lc93uLX-s@v|-4!bS%nsa2 zfLjFipQHqm2JogL$5YwILVzqzP-<%GsM^RPyXMqtk6(|$T{|!V^&vzRR&xN6LQ)C} z$jNl_I{z<g1BkMqeWcd-0VWhUDdT9N?=SEYGvPNPez()v5`Cu%iVn}6dY>jWcF=}X zPl3Y<rX+Nb9a?rm`vt{6o-aHdU+yi1#r%Dhv*<{-7iw5hD_>yh3A-b*3UP{e8=~1v zE??AX(pvvIo6TCaY-f_b<#Q`_c7au7S)l3b5woAIo?23MS`RgBLpOKS-}oh6e-KL6 zy}r2yoH)3DH}EKh=3}kF%z*r1d^TDMnC}dA<fl+xii}Fade%^5auM`;>tZMCNqGoN ze#sP(l_>h&Td^!&_4pGW#)457si$O_z>IY9GF9pfhg7Jnl-jZ2Zru2N`p^z!D|Eyz zpQEuo!q-?icY5;+`M-5%@wmbS1OyNzD9ZzDZ;9TW^ccX-Y6SGGsP<8llNZYzxWZy$ zU>H4J@AM6G4ifUZ!2v#(`AL#sX-SjY{n5Y(y^R5&qUE1W5t5l2kaquy<ppw^%C58$ zRCMAQrevx$qb^l}rZ+E;re`seOb~DV2_viB`f>8sw}YhU@tQZd%ZYq<_(^;eKGcwK zNd#le5P(3!Qhc^Zr^LC!V5pTv&3BVr_d@}GY(4XL^~D|gs$1AKk@wwzMLxXMmLj5s zNvc%9bDnO@fggTCXG&^v%HH%Iv)QW~H8rYp_Xm`qApdWhoH4Ta&Cn4W3t14sV5v{V zCIp+nsFSZEswOF?H+sf2%JkFY|DA~|fX9b9hlOf(Y`X}MG5-vEdh!s~<KtXvdSiG1 za;D{=h0H*)Md#mD>%h1D)nC>(bKe*Z0Z>9-$_lU-|C3^P<NL=LoaNC@^7o*{kjXww zG$j15v<Ojg!RIfq%+E;pw}5tH_&6PEt#R>;F>``|s74AJi07UwJi_gZWDs3S?ezD~ zyd>93@}`^2ja?-@BOCKH(<>EyqMvU~q!AUH1;?n7B^|Zo-g2@trDXuoYufPOr!f)Z z{^Ie>0a-lf?V+&1VuP04(!v^%J}ya&)q?1_4dBq2vI!sgpJJf^j;AENp7TYuq#9r` z82}kUjV23Z5z$FrhF8ERSr7ECh>43E0v?Cs)nAoFfnw2Pfe^6qDJdbGn`Hv5u_@SK z(`(mAQg3!C2C6j9OM;L=ODs49)oX<hxP<wG&b5vb{a=b-T(AMLy2<B=)l6n_Wxq}* zLrm!Mch<;Cgo-9*{GGo2{zYzZAM2_voar(dm8isWIc78a-UQtnpNF>OxzB+>Q@ugD zOiT0fAH0omZG`!$P$}S<kXEh@-^i80j7xH1{DQkO`0ET)>>T#L0SF!zWXeWm-a9op zc^fbzNsRxbzX5D?T2-#V6)W-rw3wQi{I&#I(nVGQy<-3aQ?8alt164q37jV2ON4yH z&%z0G=eTH*%oc$F^R?K+hU=#v!TuA2a*EfS>_u;^6MxRuu>scjf{N3x!GsZ|*}=#7 z4re4~4}qA5efo*gp-DvN5X^PnE^S*|Rd;banG(KBdt6bqf{GmT&h=6-+@Z-OPfz4O zo;V4dEbh3+HT7d^Qxn^EQQY4*`VSr)|H%O$mC#&8SOEL-UAO~mLGG}5)Yj4*DEVpi zxG5mQ5jR7iN2U%&g~u^Dzu@5G(^)<UkBJ!!fyJEZ_VN0rdczhgl!8PxKGig06D*q( zJM=hNrG(pAXG}~K{(a+|C7qdJd^E7VOc6)S(@?-jy*r}nop<*9M*RGvT(1!6w18}% z&<DJt312C*9VA5GolCV)0e+*sk`|93@42@{ZEM(%P*VA4i)~Vcq13L4(-jBR^nymN zl4-8Nk}ZTjE~&QL@M9^vhMie~it;LA-6DO?zg30<cm?`Dr718l5J;TNSV0ufq$Hp` zd0lmdNfP?}Ap^_TZpqN3B_5X(qt|MhkxT4DQ<#8cW{mB%iT_m%Fc%%6gy-NE--X26 zA|vGABXI?NjTc`zV?-_w?TXN}A0?rL#p-FIpkkSZGER+WM!r%>%VA&v#iGvX(=j#! zKKBS&L4gU*4xD4K>;+sVZ8SeF!Ju=w5kZ2&)W5mY{4tfaslcR>nV(!Nm062;6P@2) zc*Jb<wBj}NID+=>_-4$ptfVhLRARKBDQGBjwHO#usVKPSCMLT;{b(q&%b6bIWR_4t zcW(DPosc>*swssT*K4mJ-#~)Er93WH0b#>~pe7eOURm&m`BLy!>PrL`p{gpfgOpie zMNrMut?5MWmk0%Rt3S~Hswx&LU}0c{%#OlGZqlep%z4F{sk#vf_^<$`u*8Cii3zkL zFxsOgPrI@{y}o|qAy1aaXo8Dyk*6X=X684_b-ha%<x^0Y98Z{d&mfumMqKLm2lAJx z6pPte4^W*g!WP5H%sk5k3uI5o7;j9t>G(IEM1$+l&`+g>1sNHq%Lp<^jZ`9PblN~s zd|1g=HBqvEi%Ux4Qot?^z|CEvr<DGXMdlwlF;0yJ*Xi-ypn~<Zvt6i2K~mUbHbss} zYX#_&FrLtu%8y{_I0#?ABHyNEers@`*i>%PR>N>cHqBhjCt)8g(?{F+L!~0qQSXJz zvTCva8;GgXcV-<EP?#;pA45=NWRQ0i;&R$ynSpqw$AyO@?ItB95pR~ZV*`@MKS4tb zuwoGl3hHxeLPJ48!J6To1Ww4N{``q^Kzu$jOBS)8#apU*!#*Kq6qj7u+Nz-i&NM;F z@&-7~q@<*nWHH8+`Ni(FW##19#|n8<RiGA3rA$H-hs4EtN()Gg$&LF$u8Dd4KKLwd z`r@JW`_gmdQW-1<EaC2E_-4J4n}h3#sUhK@CON;$8zPUDOo3xNsJamPM{X^N_-F=E zdM3u{-tZ*4zr{q(DsS(X_Y^2R;&1qgxlGS=8B4i*Mp85a<?NCEb2b{v!qbzq5}m)V zl6)2JJ4n`L`QwfsrFy=RI6F)CSUVzzAI|=1OvypK&mt<=YNi$?s$Ovp#RIeBw|tvG zg*kmQZlUxQ@Ic0m(-{h$GHmV8=Hg3>&?ULOm7VTce-qJZ_lB5qqNLh?nVY_UD>^D0 zle@z!cH)kBMJnV8t=HZv{1yQ-F2m$@fpVe+hnM-6LrY8yCiT9fc&nCJ_0cP6Ao#@7 zB=X6t@Un|jHo_Hvb?G?3No_&hXB$M~0il^`>;6XxrNooR;&SFYE@N=6M#E_7Vk4=9 zOgc%xQEG3N4z&R@7)SDBHdEWPIL?_wnXtdzbs>d`Klr#XY{=M7*0s16zKswt^H4pX z;FifVS&O#sUk3Q^?0t7R<N_Vu2>H`Hq=;`uyG)7j+jIB5og1G*mJ#Nr<&Y`c%|Djs z`APVBJ4q3LBkY#Gr=Xxn<Jk4)q%iu77xAdxU39bUs5&l~UsQ(grT3RX?I4c~->bH4 zEo=lKKObDJ?Q$G@M?pSC>@I~Ti-gglzm!;Lh|!>6DLEm2@r38L!f>teHy4!4ixoIy zo?xT*fT*XZt$C@@Sr*HUzW3|pUJU3*XUs~pDS17uY?>pKc|zYG5KrPk68>pU-Ho$( z_8=Vyn-N{fzZ8T!I4+)Ivbmih0pIBG)6L!uP~UV6AFhTFG0%D5C@kop<w{nNBB?C+ zS2~H}>%=$!FOGsD@DQri(`Ez;g#w=Mj*J0P7#35WnW>BAU^eeVqpO(}M{dT3GI|9I z7d2WuH*Lre4Hjuyvn#1x)q7$@@9{ZG9b!kXp)oRt4+fgv3+){H+IU7S@T--c(ck8k zkzZ%mMtBFY;DMQh6<W@m(Z8{l(Ai2ia2-`L?Xm&Y+iP`*2u=4HTD%nV<c|g3J-#bC z3um=Qykl%Ts<NU^Xi{no2{ScB_Nqj_xCYW%{!BP?O5@g{0u+M*pk!i+=J)iUA5@6x z)!)S8$4tyGV4odrMa0Sl6$Mm`JH@|;nWZL?e1js8$Yj(@n4^c7%YB`dY8q4W%{g3# zb}02t$rbeSRaWhGckKb+S}E(p>jJofp#4JfuiejwxLp}y%n`tV|22n48au1`$nslO z^Rd)KSo4WEGT25RnVtw)q{?y04U=Rq3TQp;mJr5W=FWT}q1MM%CRM8o!cFDR{OeQG zE~88Of*F@ZP!BOnamITVz)bIt4xStkgY;|Pr|7*)`kJYhVKLmtl(j4N?N}K)mp%9S zcl_QdFXLDCU%G$E*Gbt5f(|PfraP*Rh}TsF+Vl~_4B5&)38I<9;ci2%HM_T6bxhc( z<faC4OCIdQzVd7DM19Kd00tr%g5gPK92JIKW+vyJmCy^u4blsW@hl&ryKw*ZZ5&fW zwa%)uXlU$b!T;IL`k@`n3SquPwIl2k_TwdlITrx9cd3S6GGi}*=oK&TPuwVsD@PV3 zM>ZA-i}^+<*$V^O6e%myA=XBTxQEk-m27EHpmKQ`F*I+^g1GJ87vXd4unVn%9*~E; zw*z=flu67x@MO{A!aHa5z5L2^iW{Rpn}s;WLN1&}wsBSm%2pbp!A1m`La4*caf(kQ zsQM|6^%kR;(#NxTE1)iMXL3AA1S7B9a@ie9E%_$Wl5Gae_wzOL+|-qJ*3gSd8WYCT z;f?=zzyU`%Mcn^BO&OzJr-mW|rz*trIFUH75)LJKPY(YtrwM@BjhPnH^YH=;%%StN z@@9_GbP;IS;vwc;aBqP?*g**JJhAjZ$qK7ax|rM5FsL(y@QX^2ZvRDw_S$w7?i|d6 z@f}4jLjh%o5t*?%VJTvD>^iFyG=mG0cq^r2)ve%ssMQyS`aaC)3waS8u9ES@dmA_L z<&Rb&d}RE02Lv{ZE+<Pj>w;n<ZP#bK?Ss&zOYCs4R1|Vugm3S1rtNs`6QS!ZtnsbF zR0S(5GvP{F6+xx{4ROFZ%AXZiRVeMvCymsx#dsv1n24EH_XiN`x(1$zd%&GP0Hn?t zG<}Hi5sVDNM|KE-Obb1<$@yE@GcRj10cnbBBJpX;!S!k00}Ea84PYP2KqA^h5-z03 zqasGI%w#9*Jgk@!bcgu}VuPh0R2LB5IWgB*%sdTZA?Ne*hBr+bJ&as>^-wRitv&1{ z@ySNuURyzuPC=avT(xG-$>siM!13=w-gZL!E0Og}k{6#$Puz^?_2DecJl6*U0BmCb zsgoe!Q3VUL(P%zh6Owa7fsYL0)Gi6LLlLnukC^+6X3i!X*iUK=8bHBHAUT6|7agd6 zL~woKm1&^Wa6NGsJ*zR&o^QyOmF2U;zFiABX)%-4)Hpl3g{uD^l%gG5P*)_ICKH0V zw$dt%UOYrGJIL05myz^|EpcQ0zw6x=I_+7cy!i#!M%;um=Zz=a%mzNd18Dn%SiAiP z+1$?!s#2Mihr0L?-{m1m-0-TP*2c9$7?4;bW@5KBMyF`$-GcQu@1*b!iS1Ut|M-XB zM!9n755b{!9-)RnjE@;q+2|{KpEGk#UfIRUsmTsP!@WDj@2#RZp%c~AoiFxie1_i= z9>|1zqmJuRE=^_j&K@)W3g>G}8b-iey*q+ey5|gb&TcqfeL373{>4la8RN5l{F4=q zarp&83AW*8y|)8C>B*H}%)iRu*4>RiYng|y2y)aWi{DGlDNUSktibu#X;vwa7tyS? zTddLyTyk_;mXIHmk_^g{0bH^gqW*ASi)=sOBetrIj4pBXp-RT~nH^JrgKSz~;P47! zK<7NAEDO#bu=GY4Uwn5a2~vgA_^j#?uZP#k{3==L?AidKrEmi}ta;S&4<oZ6xp-dG z#zbc4K9iJ4D*jq%#+t2hI<4#>P9H6jFPuc~6+)=)<o#>IV(=4ec5N`05ZqL?GhCtG z*3;8cW8(u232`j6nlA)Ha%#P#|GS1_pxLC%jK`9x6I;fC#c>eYFY73&sg+su-_lFL ze8}@taGu78Dvi*|MP$T(`&-gHXOkr0NBQ}Xy^mCiKAvG!+PD>&C4J!&M()|(o5k#} z;gN$@@fx!{SJa+f8o5Wrmc=N`#*?L<im_l2$pc?<0_N1u@Vls15N{(TcP^?Pu)k;e z)J8O0GDmpRC9F6rcc;ky;`Wn8Y=U_(UM!E@R!Tf{uTmLdDsU#lP&fx;<Rlj`E^+Ev z_r)1B&B&g7y4QJgnnG_(XLS(t#74OP{=0ITvdWu+gRm#k+HxiOYeK%Ov0wDnEDDV# zGR5Z;4}&QgjPBFV2<75^^S!eOh5n6n!Ew3CZ$9CLgETB+q9|y9dir1}<qhWw*xyHO z{@idowq7P&jsi%HSpY#XW%FnId=@sa>Yc3WS+;>ke3H7;2T9=7Ql$<N(B?MMe^L9H zt-A3!#S#Vr?g94Y!gg&}fZ1_PaxfurF_9n{wP^9aYl4>Jnc>Me300lMnRz(<!MYL6 zLSLBR4j|;9NHy+p%)Z-}ZfEv)D8HkQPK=GARG}uWIBTcFXS6YIXhB19f6}U}GnxCd zjMhRHe_l;(dN?>hRRILtv%lGxw>l%Rg=7JVyNKH<<Gg8<PR0pU?i~1iYme|lTZo;J zUcSD#VJHkRrp<cXp*Pm4M(-Qb#J#%KYL8|qZz_mLRE&(6n=62*1PF9ccPG%I+c3Ma zOy4@=;0Xc}|Cs3bK3fj>b?d~<UY~JdU8vOr`1PzIJFGDU%o5e1ZFWOr@da|L?wx&w z|2V8?{eoWM4IE0*LMRDMa}Hei7E?`GBt$#r)pmYhHcT^r^FfyvL5xD(TjB5iqMq&- zJC{k}991*CJC+&cXuDE5(bOohK0MW5jyjoeCs-^}Gi(u#5Bv9~7kA#SKQ^_*Q0EbY zE4TE)5T#72|B!Teu<FNAgA;qsvmF!z`Jv%n7o(w#3M2LVam+YY_aVf9S*esGAj1AT z)7qf}a>F`}Qzzgdk%x{CJ9NG?V+ymREW$w76A0IMVj;m~9<~(dR^kIT_*SSOt3Kn; zwTLo%JuS=d>E>vl61BpwaXpw52Z@D(2@QYkB=56MqyW_{z2j3H@B@vkH^M(-PK9ee zt$>40;y!QhNrvuKKF1XZT~Hrb>=h#?B$Bv*T5;$D4<f7@81h9~y>Q9)n0O^)mLw*Z z2cz?tC<(Xk-Gibu17N_z9`HJVgL<#bgH!QE{(JW#DJQu9CG-AqkM2e-Gp~g7O)p)6 zaQ-aTK3CX+#|y-Lsx%CyrwkT4J}0`JYsE@E3++;bAS4VkW9kP^faoxh?}8JW4iDu( zlJi*bLhcu*>Vn%C!tOxxHTihvuDTiOM{V1}e6!<aHt04-{(PBvjTfu46n|39>WMzb zCz(WpP>mrM?oC2&)R?Zfo6{Osk&pX6ooL;T0UJ$b;<M*mKo$-^dHc_&Z3CPsX6ue} z<GN#sglPMu1$|&|TXoR<QalY9em~d?gaU%bY5w{+uAKRl@zhMH%)kFo**EC2Z;eEc z(PEyl2fEOv#~NLB9g-6H58Amz#%ucFpH9UNpRm|zHf>VRv!!X@gO&S=^*`5ka4OI- zQSPoAAwfdyF(Xzi_H2F4gPa;A5iP<*r?A8eLf$EflbP`pKAyk+DJT>t4*A>zt_3d8 zme4Qe9Cq-WdNNQT+}b{5NnI|7D%{{s@^})46XIpJP7o47GMK~qqU)4br>gt&m4X@k zAJIig`Kcp}0HX1=o+YwX0{uE%hB$AGKP)j#K@sH>Y<_-*#y_)iV8wqW&%22hh0CVu zTAL_o>QL(NaL7$zBGZdQy@q4&M6bvzamWHOk=0C;Y;~nhq6e=toZ3f=HK_&1vDu3k z9>b0I@NLj7m1}_){8*sqbvBEz?gyuVK%SN)FsS?zfQa1!VL1ZYEWCyZrRbxHcFqvL zXCc{loBqAE7jUm9QZp4mRbUn)qM;dMiquy}0a>+GF1|35-^F1L0=tNoQD^#uGac1d z^gb}QMBkuFihu^pc4inYjS*;aDnL45XSM>Kfl)UY<`A|o{?A0P&28-#X>f#68>hWt znhs@cP+*`?SXa0khnUr24y3x~*T{uKxfO;NUrK>3H<)Sp<CvXnlHh{(Ozi144N5^? z4$vm1k*$?j{;=3ZFCasr=dlApr{Ded^P0lz2#}zE#Rx&5B0DB(etd10Y}$>MuvJh2 zv+3z%B7g`p7fSII!s_~V7q+wc%x|_4eL<6akjM5{8*SJd#?`P2nMZz1h>Q9?Z>q;8 zSps=%2vu$fXoUp}k^_X-oGKq)p)mVe5a_m7koa<4c`b009QyQb*t=Xsy)W3#mrJW> zkn#r>Y0$O|?=uJcbQ5njwC$3Rd(U5eW~me_n`(2D^#3;_ju9I?e=BuzU14{(w4{cC z{dIfpW}C%X6843=YHVTx+|!tH*f+~Yv^S!fA%vd~N`321FiEdBNJ2pju%WK1VNVx_ z2?3~6qD4u!eQs5RfVp6JDy|#wyR}48bh?Ol98=jHjmx!|3o{#Z0i)u9Opsg9%hlbl zRQ;s|e6M6OD1OWnBsv{pQ*79^xamG7xh^N?M~J{`?<{UeyE(b{-&z<Z%)Lbb8fc?2 zKWlI6myuU+c6JWgfcFZo;bJzm2Yj^=n&%ktRs%L{u(v~V9gy48#>`I-*W$wNL3R9Y z>=4R7-(!6*Kwa_=cK{_dBRxT0ULIp}>3;K{#n$ql-MP%tz~jA{RA@p%NhxuACXN-i zc}HTGSo*9-e2#I;l8sFcO&K!8K@gk5p`JW44gNM3I6-L7%<U7`m-nGME26x{jEbBF zTIY$zW$ioI@#z_`WPw3RNk{r`=IyCPxNySM=pbQ5n>l}k&E2aE)OZA8OJaeVIvA6E zzTrn2)k-ZK5eP!_bf$^+&U6q4t9w<asg0H7DxzV6^?bPZmabJlN?V;{fO>j*_OT`k zoS*-;QN%p(m6d)wochzZmYl}qiIUiGw;~^g+6UG-%R%R_iRadbkDp=qw{FVg?lEZD zSB-YA?a>Gn$!g8u%2XaiAOH4?79?A9^_OYYN@%1;;VYXT0#0UyYNZ9g*{0HCAXyi@ z^IRbU5|hbvv_EKI7$k6ArGIz&RW_vGu}Z8!xs#go@k@AmfCG^Nq%y^HQ#QCYXQh`Q zu}U3MbJ0V+ceVU|yUTE$>%>1*ee<vvKmEvcUs=t6HoYd?&*Px6l!%eBpvr|&8gqo7 zT-(fpa4!1LbM?`UPn5BniJs^3Ps8LgP_?ZXh+kT|Twq7nKy$2wEXIJ<y+kl`xg0=l zzFiQ->Q`p5_Rvq9J@u$7un6M!-<<n*Y+qfPHsBMC0`EpP+5epED-Gm!J@0>MrnQcy zR?+Kd)Q4!dp*4hwjF);Qa(h|$lbWYK$WE05;-w#nE%w35>@}i*n20kn4XwuQ{;7Dc z^dVfjx^~&!ly=oJw+S1cSFLG>T@A+Ff=hw@^hX})(G&4+n<j=kc?zddTyEy8{l*}w z#|cNW&*s<@Y3_Rbcmjtw3(a}ms)ZL<dZiRrYeQh4%HdW#DDYsng4M&A5!|Do*FWB4 zAM`V(QA1WrrF^{p^cdsK!wfU$L=YR%9XAy25N-y;>eN{9z*GCB|L)&|9xz1ov)}^J z;s0_BvHn7yh5@}MCYPHfOB?>Y62xz_p79;+(l`0;{9ky0c<XtHPzVj-pn8u1%$B2C zri=A^kCr)`3$Jv+cbEMf0R|@g=UK{P6US7=a05telqGKp@KFUxz$skh{lHB0Xg7ZT zmABCquH>u_!HCPHT16A*4#>P*|7`;+TzogC&P-m6W`=d-w(N72mnPO*|G*dEzooR> zH<k9JgJ{6~w4qM_?@)>m`|r<2h~>TV1rs64jrgXk{TD_?`BzTL!DWuc%ah0xVrwA? z@$WFLB_yJ8rG3J}r!mQigd7R)X(htZx#abp(qg(_KMyy`agRs%9l_N%btbxNzfJxv z4u5VSc9cjpz)eA!SX6OGwJ4RjoDZNr%SGammU(Sv!Bxp?vuEl=frK@!e&@YCr>o*= zfVjGNMIW$1S{bv@sLU+=XJ3hp`_f{2^yI8@MoJ{EBPb{+Ox&`_s~pB7RAMV#^0vEM zdXEJ^-JCsh8C1(%_&vz^U~doX_H!;?S~n|tZXl*i5nKC0Ikl*e>Bm>6X0iO^by~>i z&?L>}<d|XRVHeleUx30v$>Y-nLh$|YT?|b>Zg6Gz@^@P)A+noj<Zev{J}Y^$scBw# z3h_~9i^#rEOisdIH}8tGX|chyn6da=C}$Dqbh+Us#1F9^i7toTn>eP*VJa$<_21T} zb<OU2*mqlEkEEQ(M)v!-c3uxg=EeYP;vcxd0RXrHzIP%bqA%~SkHhP2&a;4-IFz@; z4Tqb*j)au-;*ZvbO$izMS7!SzBJc2DS{1XSt<7)j`?-SE7ffCtoH;Lf+tCvzC8c_{ zB#5e%pa2=La_SVXhT%5gyT>87|Ngx$Zhzwurvn1cfJ;cCqPHhRWUbHdi6tB+Vi*PC zosK}yFF;R`auHmn2~GRdV1h`SwTCk>znRzDo6JTcD3Q2-{Tc*}e%EKb(3jP#r=G7R z*@=DQnA?79Okxv$zm2j>P)_<|5xkPtTWGDFe$CKb*r<f+q`*X9;zUeR(y<z;93`Zg z$a-IKMjzt^98t&)R9%uX`;F6_$FxNInF9BY8X+j~p15~+d&nQPZuoD@I?}cUAna;5 z)mXedFW0&Mp>Lk<=M`>_3*%0U?_gtvTuI}73@{^Wbdf9M0Bg0$#dDm`xMd1yN{k57 z@2ayus)An@VxVek-H`I|qXLZ^(;1^Dm7r)M?TPHCr4C68VaJ@)Aevx&Zb&H2^;?_L zz?ObG6B$oEg#$}E%9JH|F6PGaSRwR@Cd%h+B<Y=lem8Qb;BToEaw}F{sFA4m56Uu$ zs0p{PJUb45Vf_)Ev5wcgzM%esLB@io$#OOk982$Oll|>NybPtStIwv$v_(l$?li@u zk8>(>A=|}li^M=?wrge8tP!)xJ+K5ex&ooJzExUdxR$OVd$EKO^|INY245}COpW@V z$rm00B+QHhAncnDSR79oaHAS~p4Si0)Ei3zZ5EQ85n+{p0#hS}0PN8MagvW=xN$l@ z4q!l}8+=KXUbb)t^Bn#XvZ4Lcao4jw?+;8c!FP9e^AxF&Ffhzg|DKAF9<*V`ceu0B zL?+3)l!_#7V4`O01Y!l<psh`MM4up^MP+frC=<sHUdze~JxzE@X}o{!yYvZuKEjF& zwiguNEH@6<Xa&EV)Xw9&;b}m;kicMNmg~T17c)}6=jC{#Ps$HVnwNml#Er=gyq3(F zqc`KoN=bp>Iren{;ANS$?Wp?#_?jtXe@igj8vb~u0*^OiXI8*Svi#H|{m<!OV-Wj! z8^sQAN}jxS>UVS<K70Ric|1dI8XP()3>L#Y{H&zC?%#CQ@H@xqeFt5Q{>9Ilm>aXa ztg+)GcV+uO3xi=gypzzwzs>Jpn6C=JgZT}7rPYTA*mm$Bw}<kKN{LDKQew2F=@ZG- z<W??6{Lr~Kt;KYF)sRR;jxuxPR#GZIo5$e_4gCXIfV%<nH~B6y7xg+k%GtE(7h|Sl zq;fz}0={fFcv#E{xunsPxoEb-C9}9*?|pIBSxK{@1sv0cjqy6Dv|MEKvqw$jJEEMF zjKFOPVK-9_3tv;c?-N<|q3KEoSygC_!dOqO9oxUWAYml2wR;P7i9>WMTjn`w;QaV_ zvHb|*e)HlY5_8Bk2B}miX$C3E5Wa7G^YA$iI>uQQiQEgw5cThlI?lGW$1ljhMXqhD zA>FQ<7-DX=LP13}4zA72#Epz(b6Xf3@cVpMpE<CwAnf0LdTs;k!e$(AmMwv5ymATa z<J$3`94SKpsbe9=zpp0@UX|y!`x7<=P^5wZSp`xE2Q5;_oD?jYk{NVf_?poE%!xLr z!=|m0k`$6OKg={7fS-<Db$NZd3=c@@X_^Mc2ggk<m|zh%Qn>Dzd<4F8Hreb6c?Lgl zi-A??EnP_qvhOrK=bnv`jghHw$FE+gl1AYU96}p`$mCr<=FwBn&xgC#_sk=v;`c9| zY)^U)J-BMbd)Qo{2qFG%o_+c4@JNmM-}bk!0HOp@LeBBA1^=MK?yf@iTx8qv&ppG~ z-fEI<f)yA$S-gHU>Y%_`--8w%$$m60z8VRnc+X}dUv#=!LTXSb2Z?@|7Z`g&aF$Qb zi_KTOm{RS<$4Y~a_WgRko7ZW_ot0sS+mHIz+m}13=RI?@!9gbc2pAwSAOb8+3Uu)K zQD`^HnoZhjYc?egk_TwlzOLSQY&Rn;H{J`#o{wG*%giy(dd=Q7dTKPhd+noP=836> z8mX2qh)%kE2WA7neT@k+ZeP;AW*?8z%HZ>Q(efYIZ=pt)w@RZPR5TPWp`ob6YG1k- znqV7R1tcH~H4M397k=ingc?ZIgsxYAM3$xDu*OyLgR5u`C-~hPmb}?&x`<<Q)c@r< z@uxq^=CNv6ngWSY%*lmym9E!oZ!bgQwowm82uKs@x|Em1zPoUIG0Xs?1pERF=S9b= zieQ*cjl@cx%{~|#d^*{}u^>H5*BVB5X4Ck%?8E7QG>E&3I^hWM*2CFLn^}{4JL9#t zh@bbm$^Wq#R$e?o|7rUj|JVxO74y(_zak(=czCoDB<glp5!NN=W$H7M0>C8|P!Ly5 zY&#}vW$MgD+!Q4a7;*777*pAgj)JD(^e%p|D+d0U+Z$-$9YC!3{d?>#tbO5eU#1#1 zyp{6G)6}U|yYQbq7hsk6%Mx59?L&2Ul~M6$IzzZ5hv&89?<Tv;^t};dNf75vO~bO% zUN;W7y|D(iDO6Us4_iz#(aU-1jLOIcn`F!Z;mhxLCHcINtc?3#-KA_ZVOx1<>)aMM zmc91C^)}iNq@QuTS!@khCKg8b0L3$)J>=gU)x=Mq7#3EaLMUp^-u^u3^rpiP9p7Iu zGou*aE$dUVi@OA&upPpj+SKpj7Ha?49e646G||=<CJv<LuZ>vNvu0=dOs<gVh5oo7 z4BvK+_t{B!{@gj`J%Pib<)VFi6*^p8-c;V1x%l<t27f=B7h<~XudIk1i2h+v;nNR1 zXRKv4tW@(3`8+UX^EzDwEdwrkCIaq>(-d+aM4I#SBSwt@67h!&vh+Djmd8Uy%psV` zcu7YuCfxk)90$jrg+&ujdVlck9n)dlJ8ww|I;%<D_?{TLdG8PfxayE0OkX-A+D$!L zt)Sy`;eVLp`ckS^tLbI@vqb}^?Fqz)(q&u_BMuzSnk_<R?6nq>k0``EGmgLF1q)Ln zA&mVo*{;;L>E!LHd^)he5$C(U^bA;QJ4}dq`W&-!FJ<CH7d2nIABgz25VOqH`SGF6 z1EldVY^|GCHWW$>8a8}C!$_L6ww6I2>A5clJH&JN`?0OrfmMs4+D?YI+l+AJfiUS6 zn)eT`QR~ALSphXMvqH9Kdte)tcCPFyfl_!ga9yMEkxI;Jvo2FE6T|qy8}jfvZ9Elj z$MtmV)ahpcrj}c0b1~gYL0}9Ej3s{_-J9vTuKE6o=9%T#{5|WLK{+wzd)f~AQJokE zuloYLOX`69<pvcoFua-5Y1H*n<w!b!LxVK1p#v3QCYLKEP|!YjY@Xp+c`MUq-Fi?@ z;$4zLx>=D8_Zy0kh~~abogp_BQ78$1HW(`9YY#)UHg1A^JYDwtjG~OFJ$1C8PKXMP zJi6`p#K?3!7Nw*P#~R=Wgixjiq#JZn8@ISJ=_fj$Anwo@wf88tt?^!BLVLtuR598y z-mc7i?NwDbucn)21X9!VeePZbF+WbmWl!aCXApYuyUDmAC+KMgGkXXJPIb-e9L|Z} z&U`>4+D;@)J;8x{bz1}a53Ct!?h2EBqgjmj{^QjaA`hJ9{qbzp3KMv7B4Ana43CS$ z#8Z2Ic~NU{*%;MxILVs9e*9?*KHUqEI<<G&P)ubilT9+p-!=0#YQ92Kbh2Q~Oena- z015=>P_kacB_tN@B<<=ScCEMauJ1(*j|vn|5aaAB(*zU+U=*e##WiD9Xt@vXj$gjc z4`R^{-T;KOyg+)76jN(BsgZZE0D1oW&6b!+eQeaO(+M|$+qA)oN+omYRML|pcBz*K zuP3HiS*@At%hjk0DKtR7iUUWMQ?=vB5PZl|8Tu)75+kVSeF585RlMXEOtVMC=T#lh z*K>G3X2L?*In^1jU_SNPEICX}Oo~`kI4i)1M4Fba18fR%2<E}`uegE~J_HbqIKmSf zV6G?Jc@<HH+%9b#v=nk?xmRMp&=2YTFJ9pt*6+6LF+~I55z=C4qH{5;A;FJ-tLo^$ z^=}kem95&TqA_{BVCMMfSkx{gno>o#`Qr+D4+>m2@tTlj;@{jyNmRzVosrp(n1KTm zlUS)QkV{6(Neh}AfS=Q#m0?ZryJi4P8eCzq#<C;B@yww?${V8oRf_-C&<$yKJ&8Z( z+nGZDp9OG{kd+>Ru}1;CYkDlg0;xXxG>dHC@ikxFSj=`0H^EpJa-2<a9Y)fz^_J>N z5)-+(QOFbINor$tg(;fpzyBWfq-uL<8>J&tOX-NZNOtj#@=VM%W>Ihz2XKa8cw~{8 z3CZkS?LV8J9L|`%JI?5&sv^spva)TTWYRmHS-qJ~nc-rI;!d)vh=mH$?xX39qZ$8) z?%Of9iL<-r0Cc(_f12EMRTIR`s*O)+{BXcCGuFUTWF7BKtNaB%-KnQ;FJEq(I9BL^ zSV%4K)(tVNoodsm*hzr`v=NR$)+JJTLqh2CG!(EnBqSHD;H!oP2fW>d@2`}AIm0Z2 z>>vt;++S$Ne>_SglWid-eV@XE!`RQ6)oVObJrA3>#VVAT5H@IqfC^|@wU3>Rr!gr> zj4~D|cQg~VnilC@>PKgkzl;lmbnol%!!z1dO{L#oREV6E9}IS_H82^!^l%+{w?IcK z$qo2V)B6<(NWfO;zMCFEz$P&x8pyrjxC*DvDl&1OVnpc$m}_?%nSrClm8pS`HO6Y1 zvuQ*Tbae-Oqr%LrP`kEnV{szGV%Z@8-{MC1q)dOjkP{?++&7HsB0*jIIWj5@+2+TX zY_3%^%xzLsY;~TqNY)DrWMBrXh;<#-PJ`;sxg~nM{(;4sD=BZJT6R3_wso(a@8+g^ z|I0IL3HKWQ=k47EptZFu7E=>0)TN;jLYFt9YET4RE^y{-RRsgADo~*9IXUzTM>a#N z$;B*ulgvm&QHGnk>Eg6*`^<v;>RX;)D{Nx6zHT6MwY4_zbwMB={H%(m##InXKsOV` z=8<SQ<w2$BLg1c%t_xYQxWtcK)|tFakkO4*m25G1U)gxt@~1vVL5avp6sg=hC0Ip? z;lo!ynmPUA2^lLyPXf%Zkk2k<SHAdGH{BLUa!_#CgEq&xW-JRYKT8IFL#;Ez0Lfug z#^-cW#X{&2K9Y1-BK;DfEZb&$rx^<8zs#9asHcdadN!O3l|JSr(}p(U^?{xYaj#Fd zMW3%wedd#4zzU55N}gaZYDBC7+eyhIlRd?zBwV-fwIgN_ASa+2mhYV4dliVovj4o) zfki1N8Dn7R-L>87Q{9O+`c60`LT+99hG<-1C9k<DGS3I_ajyQsEebcMqru?gvuF|* z2qm47#3FyLgt=vkWlSilEuKb=MtYc36U|g<vTA7ERHw*mS~jumP!3rz;gi6cAbvt) zWE@Gign#)j`H;e_mB&CYJXIg06eTZ1P9wv<m@y#LkoWi>4P0e#@zY-J>ML=62*wXg z+`s}O@%n4J>Dz%ojqf(cl+!PCWy=sgG;X<F#+WJq;d0a30t7|sYGuQIO84+`V{+p> z)P_TQY6tUjJ-to&gO!)n+-!>5+P+PxY=R#>o1qi*(Bv`OQ(1&yWGJ-SrTlH+!g7>b zd?Y{Q^5ld0z1{d`=&&~Gdq~cU)7M+)x$Bve`MMf2a)Q?b(PTod$?LFL2QYFNy^(F| z$rbvOxbI(J)$8GrnVJn(vs{vigw$s(SYnVRs`~<PXvgYL@_9qvqlYtOHyhrHLK9WC zSVAa4fnFdfdAHRP=m(s5BKwCi-tP}b<OO967v?_>nh$fzk0yPIfm|jIn?yzkx|821 zk=uUbG#8-+vB{?EZ4B1^TZa^ZZ)-sSjpa48I*Z6}@tc-h<AViEgDXtJcFUPUDVLNn z+}Tk{s`)`lL@_s+PJMA5eT~4;X}=(SUobtv2L>IQeU4}myO45f&?aQj_XG}@bgTda zqV3NS%;>o$VFKV(34(pE-R4A&gNuu<jRf?T;W2bS?bfYD*n@c#FpNf~e5*f*c-^7U zp@!6(lUlerhaDUsh|;z1fm7x~?EAjNy_(<WX2@E28W#mDw{YbyO*DG*J>7X?q<su! zF4qQf`AJYgf(jt6^heS?h^1l}zF%P@(oTSPB@y@9e)^#NT5F*(G^zJ~jZ)yLRnrwf zmj(-?`Ec~H7q!XNMt6ViyQxEe&ucY?TBpQHm`8Un`;ZL%)ax+gW5{Mj<b71<pgw%s z;WuQ)y}8N7wSZQ)m<`p<>zS9hA9zK*`dysMU!+rRb<6C<1R5<gg9NQ@R;Y(Zsqc01 zE7Bh?AJ}CxuDh+-+VxK6@M}jHWBwTbb^q~twf7r}Z~$mIjre$fwGLYLL4r>H`O|2= zL=HeniAqQe2^Y=$&E>L*S$^nIuhYhwP%<Y^u)UoT9mqby1?dnyZoDc$BlG!FZ}gq= zl7+I4BB|Lvy?N9SNF$7)2Xy<0x;xrcYJ^2@QS|AxeTVp+%=aZivJ=tRn{z>dr|&{5 zjgC_=B!MUY#SQSt9xv7EM{%~16%sopUr7gr7JlwA8eVnADL(bI)qUOb6EmT5c#kfZ zLT%>b(RX66!qyy15eZ9!iedH{SV>P>sY|6#l@7g6I(MdPJ<HXov%*!gVHA<`A>}Ed zFmTzLI$j&)-qP`WQ{=mzC3$Ny>(EM_{#XsJ{b?sG5{H)D7ZHPlb%3zyq1$YO&BDqm ztS%2+Ld_CHHt8`vpC8)X_3>Z$Z%0Vy%K6j*dmlhZMaYQ`jTXbGRp7l~I~WLpm?Wo3 zc&<Xl=xv#3SJ#Ph(t<A4!WnRdY~Neoxp&T7zla+(#J@;bK@}-gdkDExlwK;q(PhEG zaNHojiN_S*+E@NHV_81K5b@hYqPeamLEy#X+<On={M9!{YdbMS5W3&LhvshpT1q=@ zYTk9V{fuEWtBmmp3cFnyuMr(Z7FScpZK?X=M>gxtkn7&f-73DvcK=qLm1I3iwJ;V0 z9X)zR*<0&QN4^JTFX--%>jpy787rWoY2^tpH?7kMI_`?KJf^dnzcg8NdES|I0&VJP ze4Y(!E%ct69d7i8)46d#OrMrly=h$GaS)MvA4xWYP1<7Q_=LR;NM`P~9p&`b_Iy-m z+!g6+(7^hPqhW#n{k*4#Ih;WG3p)_(>~G}6TR7a*fwaY{|KlbJ85#$a-I`Eh^3+Sr zx296b@!gE5`RYOrYby^uk`=}poUYt*q~kA#Nwxz|bJr7i1!tA&sWGNjrCZmte#qB| zleDPzcLs??y*6nLirPr3!=LiJhZ_Rl+tk?a=C@pH^*pVQJ3=TbO}(18bBr0qmXhi0 zXP0x44ZsmV1L^>h9i%7<{qYG*99g^3!>lCXsQQ7l$V3>yk20qXb0CLpwG33iuG5$q z{{#B&Cn+S~NAJecTe_E3R}U`f`@!?r0$)~apGz4wfx`^)VXNbwqKZl|0A(N}C*J|$ zHACMRyMifmy_MQN4xZtAyZ~&9Vw@b}I*6AjSi7z(D&0x?^4~tx<(_TpmN=GJUI<-= z9s-k<)CgpYZ{X+byx)7yln?YenQM|XmQ@Q+Ye&nro&#vLoeQ`o(`a|=5(F@*&UrMz zQEp%Julk+Q4g=+RaK>d)ica0G(0+~%PIWEsws2yFyqL6Wo%d$o#!BX<Z;2;I<LGko z-OYGsu~bp&y*ol&YCN@UIrugms!wQtQq~B#@Ri_uQY0FA<Xq$O#g0I;1qm&);QnhR zt7La6Q$~{i@sFZkR^ilB_zVz^cZ-tbMLa#ZArT3p0|P<HU*?Lx9hgHs6tPY7oY6&N zvqA#3FltRPGw<s_fiest|2<Mo=dDaM0l!uPbpkdLtJoG&q2rd%BlXZ%Y4i=op0@&> ziwqvuiaso4=Yf4f(1X5HyXQH<lo1o37Nh4aC<^tX$C4*87j#*v_SWHv0q7=n&|jJQ zLJv;FqGq+?50Pu=ARD2&xxFQAlnQR_iNW5X)NT6Om|^pAB;XeHaup8qv0ON3SKVJ1 zaI;JC<e}lpwg}^vZA$BYkvsOV*a4qjc7Rw+y_N!2GZqR{`};0K^NNk`nGL+hTT9&a z&@G|E(d<#amlelp@I)>nPWl>dxno3kfg=|wQVMi1eWS2?JlVnizEtV$+q=8__zYl& zRK|jbA#+W`)OA6=?D_O1XP|%57F8~hwY=p{2?L*zmU7+f^n7}|n|ADn=PbL~^nJCR zL9eMd9^Reey;6Ax+Ji$r-;M-Z0bp!ODIfE9(z?R0ple40v~JP3ioX_J=TzS&&FyYb zUJ%3{am|TJL?t=>d=0@tWBj}H%49#RVQ^sBeP;B+R@oohOieEx@K6wa@FlD>G6j2> zKm$a2ljFm4=C9QMcw1v5w9AmE$F$m+ks&y2Rl%x!<R{9vlcOG(UjCK7A9GXM%75zc z;D({i##oE07-MqXysN{Kvp`ZC^_lI2y&6o=_1x>ll*c2;{`XaU*S%;Dx+?F;+NW%C z*^QvI(nmMum<wuRVGFP1beW`?NzTo!Wy0mid=(<E_0V-1C6{aH+zy0A`|Z{qD((sg zCF<z{5#96yVogYKp~Q8WR-QSda349WaOncEtb#N%YTPg(=*#=x!0N71wJ!JrK?2yY zR)GaP%?>${zUxx)XW2>dy*g+SB3fG5^73-w7ICqRvKN7Sx}Un<?G@FL@*HI8bRG3( ztEMCTpGqcpUJXpwn4WIb4ClNAaeh196!8yB0+{b+y%5GzVZ=U|dQWGtf7p1i(fqLB zZFzRKOES^e%)M%|`|{6qhOWhkY$P#Q63L{!iX-2Sc@lrd^4&^ZRAz2-y)Ul@&X!eH z_5&vIN;;2YaM5o?(os@Z8EDy^@p)W6wJG0beF?4Xa9X7bG5Le!N{Y~GH4`JH=H^IL z#ec+%fFOr`i9!6$!D3m<a6M{)G{dYrWhg<q3)C{A7kGvaNhO}aawIq^m1CsdF2Y1; zD_hSfHef<bPYs;nQsmpz*M(ymvfW$@)TMdvZ5lXlr#xF<|L(+D=h~KeGwwZx7VT5T zUk%UySjMm>RA)Fh0@r~Kz8IAlj>Q)~wT<Y0z2uFb;e4Kr_)`8WMNF`QG?q)Gn?@nA zJYI}fJ|GVO&Hu}u5qZKTLV4Z{V%7tAZE*@?Ac1Iw;gZ+@2r&m;)=M=NJ&VF0m1@;W zHCiXkWUH+}qnf*Mj){h8@tu4PUt7Y*ebHA17D%+q_{Dg(1S%c*=*`_3aG5714>`FQ zrv~Dl1nE((WT?SAvX`7)q=XEkX=S3@rJ;O>@~P$Zde+1+{LsYQCdk=i*qa!3$gWF2 z6i3gl<RseLyHfd8E|=Y6$?j9Jtr6k%TprJ;LR(7Pu3x5eLpO`^tH95D3fbO+v&~5@ zJeGS;%9Qqw-U|_Fu92h*T2O`ba(%}+`pNONf2D1`?Y`xIT^{z>x5XpI1KSYndN8!* zeO?nR*ZTu?a-Z5wdAkrs9b3!u9Z%m_&d0QE*?}3>*gr;O;gP$HmI3WjwQrhOo&~S2 zWC5Bx7JQIvd+1YEQsndZNSg!8u2<WmxowxvFVvKAZ9KozecD(zJmBwRkxz{_;d9zy zZasN;uKVgGlOq-iHp*o1-7^M7MNc`-yjvq=y-DS5>v+_|WM#bUQPfPd1UI@q^!8TG z-j>(%EH@ZFMLDXGuE!g)!q4h1Phdy7A$w#?JG;rTb73_1$Ez}>EuO8mQnxHr+`orC zsbs8*JVM!NQym5I4Y6pb0no-|XAzCXEW)f)`0%G<@?y3yjN>?O12FaC5O{2ZJa}cO z<oNv66#o!;KtrIRl}o$dyKxhbtRY8MRcUp(rX}F{gvaAjWX38+E%HdH=TFax7KQt1 z;zFgvLcx-iqucHx9EO08#%Sby4;iu9<weWFWNK=9&8M4a36H}jm2Mzykc-8lPyiBW zVig|lm>BrF>Jf~J-A_Uy@vn}(SMN8I?-Pz9-8#>HS#5vl#V*gcwzGC!J3EFVZ^UxC z5{Poj?|xF>oHq+8({cF=_RO^g<{pD%2#|xMZDnD;LK`a-d<ZWiCA`f}Wy{rW&QN0- z$^uw;xAV0Y1xM@8LXLuFlGRp6W7I+DeFa<kbSobEd0e)WRpbX$D|7n?ib0sBy8Mp@ z00|_s8e<Xva}1}fN~=U)LRLyjQU3BcJ37nKwAKWV1uorPr~_}5135J3Pq{LssdK;^ zfIKQ>dd_h?HVN`2y!X0OD+K|A^p_Ww3c|BRI7W^k7W*?@&X*&$rOY#wMz?I-@mu3e zMPLUzZZqa9f4#AN_VJnAD~9dQ|D)+F!>a6pH7rPpfNV;-yFognHznPj(%sVC-Q6G| z-7THcxhd%e>4x+2opb&H`+_%EYt76v_sqz5gqm#$d#EU%W4wYGr|l@M8z;AqC4njR zLWYL<wW+aqtl9QvzY4|PMX@BNP$^*dlh86Usy^hH;*SJekmkRXQ@s|m<AS^1cd$fZ zSONvubO-WyW>jwdN>AcoEy*ITxdkmPMJ=TabepTk8}bMKk*J*bc(hfP2=9gINjhtN zbIxL8cebxXKLQ5mq(&3WGV{)ZL%r$hakeA@FkOue6fZCr_E1VCN#<K0wsTULF(8L4 z{y_`(J>M`|LLih}SMWd?qB3QXLDk~1)Z&BRq;!Kym<2&%&_j;sJ<7ITgF83Jnmxm$ zT>a~!lCRTVuy*U5{~|J-0UCD774G68a9t8xYn=TbTa&UM-0VCB+S`mjC!f&1&oV6R zOSjj4)gI%zRVVM${5RxrdA>`eC9iX)t$a#b+B1`b$j7VEcd9ZYR!cR0v8t6NY`&Iz z@9SN4^;p<>P%0mCh*oh4XU<tf7n6Mn_ebsjHp-h(Ud6htfA_qbQOvtyd?YMgUvdYG zw@_i?&MPB?KOjC)WP_R#mHZgr;<&e&Zdut4RI(N>Uc|P^ISA*4P2f%S2^BWQ{(IU* zBe@ldAeJMYYjw(s^k#F&quDY``-GU%)&=YjO##i7{Uoswv!Pb`R>+ZcV)U<%bL(~Z z7>r#MoL=Rh#dk&Q&HR+Ew-!pC?yPH^cfBw4F%GT%Y-*}_P1%Hp_pL627Dm5Ii;S+s zwHollNqJm@tLPIM8OnBMwD2kX?_x$OKZjsB#+PWj+t*tQE=tkwxL%R-kt=9f98o_v z987NKFC^FcC=$AV&#O0nS%WABD`}4?F%d9yD!bf!<l2&hL`cK1QX#g5U5(kZ0{qMI zsRY(Pu118-8wwdp@!bz3j;%29^sUTV|0RAe{@IWq|C0uyxLb}qGoOJ~4{^njdwk4q zob8oM9?WUHnipu;xol$ij?*AF@lwjr6}h*R>^@eF|K6;9((=8Obn=qc>y_!RxJ3o` zHSZM2#dNUmP1Cn^koj^nB>sYuGIWKtvr$h;>o6`-+WAt|_Fl))S~6J5NK`aKe}#s? zXilPA%tqy_3_)B(Ad8ax<$W8q-bKhaS-bO5UuQZHuN3`&9MAjc?>_nqZB?`zORfUZ zTv=LBkeY#o_6@mLD;cekuOhI;-fqUPrz1J#{^Kqq65&ei#gTa7U&NgT>AI|bhxmNX zJ^xLEz(Q$<ya1V4UD1-hrH0;IgGk;?%-0tke@d)rdMUMjZ+jWs`028JV?NU6GOCfG z!6@zV^V9ApXgC%P_Ep*Qy;0Oq$2k=>8W;L@%pjLlv#AP#*>#UI{!GVl?n5f$*|VOH zOv>x;cXD-#(Pg=yBCr^saj@HWlC=^G%|oP;L$HYs=69u&|40VR;n}uBp<xSPlWGwZ zLPc1);yceOz$XN*ug8*zKpMtI9Zy;xp6x%9awMl19?g7WZ&AzSimfbNigR6cN<~ko zk-<Ly^0P31re7)W>yH|`ehg=X$x~7W4v7~U?AdBt5Umd{9!g$R8MhQ+8|p6Go}{GX zITw8`YA!k&1Sg3K^F)VNjQw)DRElNnAcW*T6*jz0y98<d9%7|z>mbm=rv8igL^Y~t z{6(hBSqX)JLiW-yj*kn-<u-0Q@I4Km-5pm&mF(Zq;qPkZ$bgqaQjqXMUhy0mS<w|e z2W%%0>bXTM$qXIZ0DmM~>_bL-Kua+qp1h{K{2rG3$FB%QCBWXRHyjjhGolz3kA!1b z<o|pLaAENZi3G(7a$hyPJ{1PIV3>@h=8@lb!!wfU*1wBagS)C6pM;;*({)BPZs}pK zxcDBCfxw)uG&A+M9+N-e6%)}#6=boD-_NCTYyM?&r}ijy3SnUYrOqK?qcc25?q=8w zd#jbT0Ayl~SK811vvqcrBe?>V%6R<9Z8#vL;Earkx~!)HS7igmfK7!JH&F82RgW61 z%!$BD7_}oKH{VOpRGBvHc2jGAcidQKaOM4>yCS{blGk;(37g}Qhp%NHon&vr`{EQU zO%L0TTI6?3Z}+5FATVoF__p4B=HHx}9*zG(pY|ldk&+z03T9>kd+rQeZH*96-I@em z^GUXczE2dl%XS?<_)4quNLrzMaauK&vi)v<jg^39hG5%_DrC`b>3-LzW^e1YMJSF` z8RF7*>Z0EF0S=vPQWs&?COzQr`;6!fJW6PkDmnfInjw#zRTZgyXQZzj%(r2-rb$}O zD=jVdW6Yx<d&xZ-V(Yb{7;eH+ar`Lc+m*->73q$jRE*%+Q%H2*_T<{|t*+m$NU+lp z@vh<fOhx=ZgGqUq*X+$lA)L&&XSQ}{HJ`WYzlJ<e=rihv%=J;7qltTiv7in9SPc~u zZ>T<8ia9|9;V%8fK4Q_!*OG348Gz9?x>LE=KrE%dDS9jR0q24&cng4*RAG}E*1-uG zlr;=>r_Q|7oT&`^PgOMg%xeTqW<5bikQao>lbQ4+*L;_NqrzEzNuf>9S$8~l>+{DU z3VoP#q2Kz^@aA%LD!&vA*^?Pm(va_QbcFtN-P&VxULqo{V~%i<i!hLdnp&ms{n0Y! zQHsQ&F1;@L)t@(H`HNaBXc{5~8(LB1VSgSHV`w%=sNULEYWP8}9?Acnu4PL{&eq!$ zh7^!0I>B>m41x<;gx+@s*N_DIPpcv18nHmjN3HYLt7+-)u@~fd&O8cvM=IpNDO`WM z;(k;yQl5AoYmoOu4)ujchG$WU6uz_$bMWdaQTgea?^l{j3tj<exg~>Z(<d7T`2(6j z2dQ9s9YjjE*Pu##E+=6H8`((vGdU4|4i0h^1KKK7VOIEnM1{VM2btltc2RB8evWQz zT-UFJ2|GgneT-(8N7Y|#&$w3Z|6b+W3IwUZcOE+I`<~<&QUA_e5t5&id|!~M{zk4D z>9aN`tG+Pfc7wxgg5-USe?;k%5p~>)^$mkP*on+Pr+xKmy`WODM=Kzi8=khmI%!&u z{xXgl&=4#U@Zp1xTq?5=NR>(px3DNMu!ZIiP#;FS@S811wBB(>#1%2`OfSy+ip#0R zkhbxUHxfnHm}|M?ZrIO)(L&20LDB<d149@HJRrcNp~48jNA(Mo!ZH^j2~Won^<wWS zJD0&#2Y?U^V7`@#1j<_H&B>u=S-BNVuYWGHun#go*{~_IX}O9CqQ-=S`Vu1m+p;I? zPr=`-<zTSqGdvaW??JA-x@)>A_HM*qG52@m7JPPCS>d&MvzOT7T*}8WgnC%$F{^rL zm0H_>K&&57DIHhoKFuX;AvVm>V-P|B$1_FjLG11{ElFi?zS%!Aj9~sNUnw4#l%@@G zTd)|Ne&m>al2~P0(#_T3mGkq|``$38T;O?-BUL{wCQx8F$I6CrrXui#f`aTUT`SHV zTTezo$RI=xMuLEi<*{!OKKyu&SN{A6N7!qhmR-_uUY(ra1qBJ~r!_viFF~X)9Mm+Q z#0}CuZI!B5DW%k8*6yr<MRwzKv5TIuzG0V8=<rGYQ+Dh6mF=w6QXrsd<Dc_C{?^sn z;_+%+mIoAw#n-K-A*_M-brXC<#m#PM-xj}0vY(bOWQLEL_=I)fw#n2A4}Ll<&V2H0 zT5+zuTpmG7jU=#p`1e6w^BJ!(sco0-UdQ9>0WP(99C;ACCi|Zg4a#xeT9Cd;0p^J` z&lZ(j_OB;`Z>;3hvQ+pRvc{;PRuS7fJNJLAtb7j46B!>qxY(m@bLlhn>Z*NwNJwO} z!@jV&6HxzBTliT32dWE|*vOJC4laDjj9#mh88<pT%i?98@l~`Zl-sZ_C5T5welaiN z9nMQanXO3BQZ72TB#HsifT{}d>~eTe9els@Ni>vP2d!rii>5&sU#Ev{AptuUxcoA) zWqSd3@qWNZL9JQjK7Qa|&#kV=)ItvNUZ!*`g=`V>CIrQr_9XQ&b8;v-`l*fRa)_c{ zPg4Hrr^ic}ZL)3mg+J-+EGH=y1C;pf86qOtgQF73>FZxk`lUlQHtG41&-9hP+?^ql zV06tfxTV@W?hGLDQU`)~F)2z7j)4p7jj`u?No0L){=7<kvym0z>Bz_1LZ5uh)-WX5 zYke&H9P^CrCrBpW^=PU5><k-O(;~rl#a`o~Rid5cz?NLD(SOr|dH()XVST9^ArKE5 zY>69rzN%m4ayqmu6%^ZyQYUoHiqC9Jdqj<c>@LT9fo*@`i4opc3f|zY3a8VckYZB| zYkTges=2+qjrHipq<%c&oV7ytpWdvpnBgH0O^CD0zr+4Gj-6KZbdcm>Jb~}&aHMg! zc_!nwpCCp}?GXLh8JST-wBu|s1{4Yh<3{lrxdPwNnH-LEkLYuPq{V7H4erlCp|2)v zP8$Xj9KwR2CtYtk+I|%paUGD=_fh$qX9)w5EoJ)$N*rXe&5*BuBEfhKP*ix@FyGS4 zm81NZxYYB}V^FAa!u;yig~wY`5WuVENg31S%N-xJ2;0Q9s~%)!vbQf9$67xv>v@B( zBQOR_dp$Nod~!lOUhFZZ(F~s}lSMM|`JXO5O3X_xAMpTnH1H$zLwScC4S&iPdZ5SE zTxa3DDnj#qa#u#|RBnMQC74(pVUd<2*YgE?*4h)oFP-;83Y*mK0mle%8eBokTMoBe zPXh>nG|(n!Xaa(bCV_q5@%4a?ghTwc@jXt)S!~_>t>Ef*%}lG~*L&XM=VN}h<Mlm4 zCg?T#O>(p8MIm*!Ggxe<)K5MK-8t+1B#y<K&nh3Ep98m8pbh-qeZe!B`WB}&l<xmW z-Eq`dEOt_>qHMn63ajrWQt&s(ZV^x6rgvjR66_e35r1Luhr6ML8XveHOz2Z8yisUX z7ikNgR$Xox?j6+l9o-oU=iRt(lJ=^RL>mHiLh8rA7DGk_exPmXJ`2#VwUESbY_y7j zpy}&CVo|HAD(qo8_-M&LO&yi5=BO6G-r{f_nl~+q6$gqsaqZ9_-#>XR2Dy~EM{&@q z(YvrfzmN$&PuU7-zrWTx`$(ErPE*t5bddlu13}MzE|rT9u9qiu9MNy!LLtd8u3Dw5 z6y%1@p7T}Z+D|0=erKTWv8>Wsx)?;+dsu-NhbC0!z)vUj6W=>dL>=|>bK%;2iRi22 zo;&{QApw`^U$d3358BFzquVc&xyO7tQzb--KJ^H_QQsm3nNjsk$gru!-3SZE?SVPw zx|U1o8h-w!gy4fSfwq1Uy1y*kSwX%VQ@L5yW9YKLeiw+fKOVL@zY7AH(Lmqd-+TKA zqgOR-z3KJdb?fRp*^5?O@T|~ls6!(o(9c1*I9m?-p~G0LQnJWW<V^-AZo+~Q=I9na z9SYCcI*V>O^48vW*iJ2gxc}w-;J(}Fm&F$&_bVZbjVa<2<xXmrZr{k$wwhYwEZpnW zB!R62_6T`XOZn$?$HcV_R*Yi?LTe-rPE(J^=w}?i05RVx1p<19rz|}L<x1V?InHkm zMr>m==KI%Y;)%mWy)>q@k#H1XbeY}ea~ZaryCjgfA&jP<Z^KO5*RDq6FLfK}<k6@u z2&oOpebOl~?N6AauZlB~XLAcOZrX6MxK}C*x`C@i9TbTyT&_3Y)td#jjD9tH9@}B# zo8<VYBvD#vO?~*`TrkN_BVN(k6&d^h#f$BSD&i~0A^c0Ir-sY8+5%{wBq1ZCg7m0B zfG-^5y75?5@NZRZ6{b5OgwVge^z|nz_J+D1qvJkVH83x9N0aCv?lvS*>0<yk3c<ri z0>=jsREO@STpE|`HnAXBZgg}sX(md(t<?~14BVStg;|Xk1lK62G~V(GjbqDB^^@3i zQ>=suQc%(-!|jA|!*mCiWSObjIQ(^Rd?9<Vlc*Ezf{@eym|hG~CdZBoQM&Bkk{(`$ za+vaAHfue6r)DEgQp5O6#IqQS9mcg-6=Rlyl}^NTYdGb4!$3gfC!mf%E3L|W%>-~Z zaG^{%Ah;XU5?#jqXc#Z|c*g-DB)Zrhq-hZhG3)R=bFrfC5XlAi8=SqMm5%QkU~e!A zK)A&!2>1YnQ~mB$k#Kp2Cr;pP-(L0)JkXe!nAG(2${fbRQA>6+5_5>xO>2Ven!onl z`<2<bij5fESMRGYvbj&$j&okwUD`Rc7Wb%Co-AB3^q(W~V!!UXIdyJZs86%b+V;*F zaNwLDf8Vm3+J{0^s_AHku2D@eME&=x_aZJ0BZikQ<~RB!)>c%GYJmdtd$@Dkvm0_Q zq~6JnM?$MoSDgwA29!Q4d7r}bxU{JG{NeS-0N}WJ$?daG7t?=ztb#gHGkP8AiZx>~ zDvzD0{=kha$=2eOb7M<>bxPH7H;fR71dZYmz`V(+!4N}2`SJWc5%f3JxrumwS?9U{ zP$)S}J#Oi-iq>B<>X7bu{6yOLcIAN@Dw3UQg++>Av7f!3OZ6YJYLOp(9#FnV_=ube zFp11dno=)VatgRN$!BzmESk3>n2X~RB(lP>CiGr93i-GvW@CqVOyERG$KXW53+M(i zr69f!_1}L`Q4qrY+p1D@%l*g#O%eq>2+1m6o>p@!e^7V@l6XgTT8%-J;$(0S!Q$0q zmQ7IcYH6jC4fKJYsUeIo$S=LYpPSLOR7;lc3R%5&Aka{u1vp85gNW%i;T&r%n&Sie z0#;xDe2@$;TZ!C~>u=<)lkc#vP?XbhPHJ|z#t83vRb+wDx)}BB&#BZ5BCFew+uCuK z=)O#l>(k3{-Fo@tgDLm(U#Gyj13s8o8Ke(&E^nQN%Cyk<`qeM$c5Ty`5#?C41ykc# zeMiTYw{@K>00)^<|BfON6>xRJAkO1-1j?1Er)n@>d6-geb{hGgpm=nMTaYCir+<%H z57m3|qr2Y-t%sP>MZ%YgrYP5af6p<INusCFc_nA{;{s}@%AvxtKrjjwDjLMkvssWa z(Q~Pm8Jg+z8LP9*#lL!@rqC{-$_#%T0R|IT@&1Ue+s3MG)|PciEd3P3&t{$O)ASPf zi<JnmECM?Zvru_<M%rq9pWJhGM*GsfK%e;es*+)5S=CeFM1t+DEui7}9*bj_Cv!xA z7*V+S$#SP^|40r}*KD1AJKXF3w<coXA!~xD=j-5N%Z&ZC>4c%{_ptSKdr@#M!<)Cr zFctN;{&74Ld78dR{DT)<?khS|9ikS$-69h;LSbQ{?{OEKcmtkEcd^2C8uJskeOBKq zLErB5E;CpVZ~*0{rKK;;@01^9m{*HuNi19%Yj3`D7z@$Ul<t$lj2bz#NmLcf+0&vg zYrD-b^-K@aV^=3nYtdop_Z=UdFESD3mvv%2mW|GJ#Y3cs*TOXmbgm2jJ<l;}j3)06 zp5yrKqUxtb?M`kmS0TiLI_nh%!?%w6Wi|^5IdJEH9aFv>cO$@j^s`xQWzR^e@MN%< ze-e)}I=Nv|uZ>Z9bJ1YXpbXjenUse!dA>2ER~Tl=>*&&PL>Q`c-8cYJP2a$r_6{QE zhX{{&A+uJ}Hkmlt;d2&YyETEMOY>y5M7C2k;!=x}elLN}sMnY4BCZ`fi$@C-y7J-3 zj;4-PZ44A67!*X{|A>Of@e+zkeSadZLo5~KGx%j<0oh0noZA7i<2o*RdXzGFEz+e4 zC*k;f9-!lZccSxkJO_lp0X<OYi6Fwd$w>m#-&$2CRrqpy8COT-W#mj5DjYlQ!^Zo^ zTh|eZ4fhaDo<OufGbF4k9LUFuuv-aCJ#v;V``v$c7ZBjl5?p$dJ2BZCaVf@#z`YEh zx146A;ON9IwDvn$Mo$p2H8GsQDDgooS)9XOfdm#60UVGB;uv{-EZWfWVEjQ%CND4V z3nZWqv1(kll&Vi&MUbVjZ;&FBF|M-+A_a3n)HF2RK>K9{HMP(Ch416DyY>BPzQ?Ak z8u22Al?QSCB@XaaIZ~yuh3j_fyFER^fyJbI88|FWsCHcw7j~>va<)m3FgRto^sgC` zmHej}QK%k)2EO5r#N=kS#S1Hh@L?mjk6j|-!owg#odyX7@LaHtU|1lAv_H`BXglJK z=!-rSTC!|MO~mnUtPGXYFHrwNrKY2MkE3`=uC+rs`>R#_y3vK3Xg)Jx&eeq(+S*Uh z+L|GBqk758I?hvYdKNLv@_QO|yc-=FNyEYYEnjpYNl5P5*j`X$8TY=^IYuGj4<tn} zer2&$RYkW;9)<mL)<S`5i9rn82qtdn*BoySS-h!_nmEz3f!He?8_e`s+#h0e_YEb6 zzJ}yA!*3#f5^HDRpZ@#zArJ@JGm3T$mwq<fGCb<Ng-)CEh(`%#{Ae!%0*u*U-62!! zSBlDT1lB$$!KYYpOwQLq1W{gS&FiM9@1w$q(S0ugaXz<37HRbhPQ!OZOPglDsFix? z)R+d-@fgKUVN(iv@4^5DFizO1Rw#MMx(C`#CqO1s69MW+xh0P4c$}9#goOWm{Vc`k zhErNzW#OHY5ua5*zn|4leDOm4?rQ`l7}7m8Y~5x@a~voz@esnSb#}mjS64|3C6X5! znC|SZ)VG?f3}nZ<gnDC&FYH2wABr@1<MY5?7?yw{=|VDEV{}@l?mE~|vZ_GbLAGm- zhNSEn*&j6(n-o!}Y4<!#_V2RewNK0l?zb`95OI#2p<yb32nqV8MKua0%^1UA`^5_X zR#ovmOkzB`nU^)~g&ai2(vp1+2ARDnVbA^cIl~$-9t2i9mXJCwhLMcf?VIKu!mH+M zUCt9_@}nAe$j;*PMuza|>M$Rs*E3CH*Ao)$!Y?xg!VN6$FEoU&+_p%a8TO39d(QvL z?>O@Kwsx!ZL?vZr=t{gPe#c=$F(EM5ZNOsRm;m=OB$Ru2M&nzdSsL4&?su0LBQCqs zOc^Qo4wYD?skqSFLaNb)<Mbz1AuNibCaYkk!=!l#xwr_wOXmypylfY)3f=+@6`_ZK z$0v`kUTWa5ebb3!Hf{G`qtW42Bb|2(3;*eluX}uKklrn)QMD|t_UE_5_j#H4SXvOS z+`+*C^)uBrC-9C?1&Mii@qoV7Qj!);?STXNuok78A!Gh5l+s?N@MM$o2(f;WxMU2% z8H&^i87p9HR=mIpZW^3b+f2V~SH5@Bn!$*!*8>ge9!E*l3*6ruM_zOTH*E#P0kJgK zWx<7Amz+n_Au0S&Pg5&sxic$5foUz0h=X^>^>}l(H>XRYFXm|09Y#A|tU@kADO3@d zas&*pjhcoyHi&?L%81Z6Wu#-%r6Dvq^E~vxA^Kq)1x$>MKu$^N|00|vVN>9}j3>on zO;Y%Bqi-ioz>P?*-uYZ)TJ7_qHcrlFVNY;<P3?9H>KE8rOaS!qtAJrj`p#jAiy6U! zNn9&dgf>bu`NM`vH~8^~^=E8=8Sy!V{H?3(_~LNBmn8QPIS2wQvI$3i)t{DuNI_9D z{VF=e?Jq!z)F9J}Jun@&s1r__7A^QI=9Kf^2n%$D(C@^<RvRNatx7YyF9=cM8&bQ0 z<W3#OJpYLx235Uy?1{;4AHxw|6@GZx>&}0_GaRNQx@P%pU?r$?VZug!s<`#gYgQ5m z7?XYC-wP#9f(BK|B!V|csuh|+)6>(*UPCoFe(%WS_3mItIx*YoV5{<Mw!UmW%zm;! zIS(-H!A>dY1l%+PENC$?u@P(yrLFpX{9m40=`q~>{Z?GKqXt!wm1%Ne#!ea%g}ANI zvy*u7DXi(tO#c-}rYU!^LXYC=Zk9qzj<hGs3sVg5fFx#+MH6XdJrmkZWMC;HJ88{d zDOjR6XCmfD-;P9Z*^rqEHQujquE`c*8w4(^h7wJ8GFqPu1aU7VuZw{|!fKa}-zRv0 zjqnc=G%_k+1qZh}TLw^k7=STI*mxII5Zg@Oc4Pi$NLYK}RFi3LRb4l@p-C?w%eDi- zBjEBO78hG6db=6B-Dd_T)q7xLe~v|EasM5f;TSe2^(Ue=Ps+~Jub`Y&cMg=3ot0P? zc5;$DGp@}W<iKt$NG%vN`wgUp*$Kw1kr~A_g2{gmrTIH)f`~!cx$;WW0Fqa6x8p=k zbltMRh5s9Y8Cv)^k2CgRdFFyOZqQ0_!{w5}r-<J9&}jjzvTNpnJ_I5A6c$Z{3hB0W z4}zjDCS_wzH1}(jEpR;9yy3tc6;kiE5xl`t?e}oBD8Nl9Rlz4!-tH7QLGrBg{7Cp@ z2I4rO2`VZMK=uBTPifhLJCPwmhPK6k_$W>T?O6*dLY|m2fgy#3YE`l+hiumI+@uqH z-LiuL6GK3D3Cq+vXdpZ6ZzkKBmrV9itb{s&NQ1d4Uj-p0HU2eH0o<!aHDxZ#Sid?> zXx|7$`w;~qkh4IlR3>vXZ)eA)_KMG%nKAhQ%|hjq<j;1^-rx6^P=jH(FsVzS>BYO@ ztk7{0zCe8ZmCp1J_o^v=^zZ)+h4f~WumqnXwa1evlGoNpCsa8!{4@K@RqUtf5bV3- zj3J&KdNuYS%#&53_AvGyZ2h^1e=Jt}WrF(JCJCU=F*qgaq(r>Gogb#O55*cD&w<oj zdPI+bLO9^fD?t8fTZ4(?QU49%HnY2WlB=X0^&r%LfQBR>i?8bD^_!b!Y|jve;YOZH z6S{Nu59A$TD#iJ{Duo^_N;0UPL_?E|+5_>_ji+*s1Nnd^ORKFZX38!;3K#SJ%ukln zx!2zHHV%%@Nxk_<P`7%zi7MIUc-Sy#XlRoK;xW~eWJIaBj<k8fzC~M-zEf?CKSZpe zn;GrRN-#4<(J2rLi;8HB3g;}4?{O2lrA0C=r(_)PrUWJ52ful)bW}vKhu-}(gV`}_ zJ?VH%B0H@rh)8r*o$q|Iyy$PnAE~VjSkk^p`6LF*d8v>OSY2TDGdxXX9oZk#HEkVE zWcO!}45`u`tJ-^?zr76Iyp4B0AmZ|7wzL6+JYGt0E<Y-BDmq5Ds_hRgM=H0EhCblj zKOo}Xp8&A^XCp5`tQ?wCkxlV_W@sQ)U97m^Q<lSav&*HWt4%LYUX8^l`fWj_{E+tt zzl(Uiy~hM&i2)LB&cm2`h5b+8f8Kxo<l<VqU4i+L*>L>YZL=vxVF9}(z4NJ?8L|~P zIQ03XqVL)i1{*2|*wiW(_##$}^h<-KXDq8sYOBZkfFaujF&CkT^q&5ZDjb+D`Xe6w zTfUZW?e#nb)4BQ0JoU8ZT{OK8+Ri~#|5xEqTyvc0LMja*C<+!!-@4Ncu#-%YbbGzM z{#s_@yQ&xjNxZJs%G$F3?!|DL{Yt5;aY0avrYNthvP*{iw^XTE|J#~i&N-Lx9r5om z@Lj#iP;z4Ay)~r%15jHvG-PLfgRlhc*iDM!7wi=g*kG5!e3TvO^O52rB+qtzNZA0# z9vOQBla`*ouTrONvPw^&Z*VZg)B2C5^rnJC)JUCz1iwv+<N~qzq@C5ngwuq6(0vJw z9WMV0=WBVjA;-{ZME2owagx)6x(pVd=UP}vDa*!akqk1w31$CAVczQb6cL`him6!7 zn#fdawRDZ>DKobmTVwJm)bqUvd(^MF5u(f<8k8@18?&0)s$gHxq*$)Y>bJS|OndUf ztzeQX+re@%6L>OIMTAtvkg}bc1*?FLP8a|PJp3#ZZQN}Yo4yjScU2`5$Fq7>Fet`H z&Vq%Wo#RRRvZ5RcTi%#gU5IGkL;Y9YAY&^rk3SC8vb+AA?EG#o;(VT|+@RzTM%o#^ z+s;bJD_@>fAN8lmH-(6|J-B?OZ4V}9eG5rRDm^_*RVf=MDt_x;ClN%xBbyY4`F5_O zUtQd*(4}`D58(U+1C7i{L!p4wUr6a1vE=_O;5}2Qcmu&zwq5g`jVsVcKu^o0OfvHu z9Lna-72qHF7Cz`RP81+%1WyBo>e8vftoeRljWAHa;r!mJX8fh_mf=y11Dc+g@b^u_ z$3K|Y*9@F6qFAv9>Iq>06s#F7c+x698}p4uME}Gs|IGvN1#xk~>^G6q;O=l3ukO^D zM0{4MG<;cmemQzmQ<Xg;$k4;$O{=2K-44nU&QFoinVT)KzD0eIpe95V5!u%xiHxU2 zbZ1XnGK1ajBlo;rb!`S(qE7vkBZ^g}oE{QA+y;`8eDr#!ts<2ve}G=@F-FncaD}CT zoud;Ig8-I|VyKyl4F&$q3Eem%Q?h>Uhs#nq!BCd*_Qve~A*2G@e4*L21jW%WFNj5% zLRXc<d9ATA$>p6=Lw9(a$r0r*OeFCQkE(8iI`$7S;21y!IbX6i-71wF%yV={i*$Kq zoJmxj1CwckbWC40zvh#0-HpWkUT?M^Z%YS|No;=i`h2O=v#!?x-m~_APXbS<M4tbk zWO+~ODbw1o=e3&u^?bxs2?a3c+Wg?t@~Y0Bx1=)wPW$#q@)Mww{YG#T&vkh&Ae|h} z#6$P!o<8_?7RMb3yzeKlpydh^M2_Q|Fk`{1QdRC<#zd?aL_l9kLKL#UrBLVf@zBLe zWJ-;Qt{E+%=BOe?{$Y@5sO`n2&w2O~?@S^};wbeCcz4T~WMRr^cf#%f=}LENA!U4! z#w&!3hH~749OVNY%$;#T(jVui^TB}BK%jA>LAO8b-CKRA^O5SeEFMf`WaLyfbF{MZ z@>K^KM#h0e8YO*<d1;`Jsio(|FqPX*l3F#uGhP9MmtG&&UolMjPYO`IC8eYkM`Vyb zqm!Z1!wl8h>vU&WxY*w}A;7J27f#U_0QC4AGZ3zwgbAvuCbNR4X<V9PHR#B7TcD!B zKFMJlifzd$GwIo3E0>fsk#JsFd~RH|a{PEYRqddTvou&s6L|Ki!zjy|-D0}xy@c0p zkUuBpPzg~5yMv?S9BWfU0L+*S_?1Kc^Qm_5hGS(f-l#XKW{5_0d&M#(_Q99BDa1rx z=fgnTu4gP@24H><*HGcU)a);fy2O4I7Lt#j854y@E_YJ&z+z%S4z(;UzohpW`S}UH znDR6n@}2jg+pGs(d_>l^x3|xw`tKnvI6~J$drMWPuorOVEBDGZM$5y>-~lDqMbtO) zehOO>@7sp3lOnb1JbXCaHX?gjQEw4SH?8T#U(o*RHr)`{DF(arTX50Nig$F@u8R$g z0ZA1O-LLn1Ak%q9q14dQ56e8Z*M97`ip=6Ah-j=rHeune;t&Mn>jtQjL~<EgU`BIa zGJ}@9>aI<n$r|6!n!>tqo^r|4zUEj$msTk;Dq`|i(4jH9_#ip9ZG&do2Ez3~c<jZ} zQMf|W&i4k6nhx8*?)`KwOH0cn%TTL1-Jno{lhAiG@A49C4r4ZY>?UdQxW6;w-o6$S zo1))v(Bp{LlZEGHHPC#8`mwMUT;DsG`?n>{jN0Bpw@kYZy4<!MBkP47R)Z?bFZ_E% z%~k_<b>a8iTco{R!)i<LPgpiE8an>BU^0rYaQ&yFB+q5b{U1W7e&p9U-I`=x0TZ`Z zeK2^aOncn^UTMCH{5&h_9n6!KQgu||q8|d{xGAvjOrJ2=F_aHEqC&ex@tlaYujoYN z9QAc7CMTNnGm|b-xa%0p;81R?*E9_>-u1_&-LN75IU7%`YVIm3++S&-2VaLPvX2(3 z)Kc{(*0Z(9-<;z>K?MZ`b)4&j>eT7rvN3S|sI|m5Pktp7ZsAOa_HZDt3r!*5QzhE8 zFlYGqQ7+eMYJ#{pkWFh!?|Sz-^epa-ZrC?u2988$x%kf*;CsUIdD(vG^qg-<y%}gy zudDlk*$hV_p_`)ZJK&ZA`u$1ub(3L<@`dV_uzL)Qt_)cSNQ>g=c^#(8fstVrC;UMU zhm2detEi^-bI3JTTsFG1(&9&q1Hc|1x~}2p_`I}KA8O2yyB$myg%hzrQ&3RYY}B_= zRxBzuXG3%VK(5D_MEh*b_ziNTBke6KD@#9y6crXydndy06o~_E_`^93wrJLcp`7^X zxVbgLM4XEVaOCopk^*7&;(We;FRG2$#|f#NpPXU=WpNysKj*ViGmy%yV91>lB?XO$ zzIXZYqvguQBmN1IKxHQE)5fM`eVgPWs)E-QB-SMp!H85!M6RN?k)f1cnNsfJCxhf^ zFt$!l-zB+h@m@JYX{VwMz_b-M7Q1C{mopGVCH*d5s+?%m_M3J%M6dJ~x{f`OeolC( zCcK{k5W9z&<h6&N0@kG`IWP4^O)m#>S|cx#8KhSp=j7H}?ngPZdels$wr`)W4d6b= zNNK>?c1fS8Z<RAV<5;#g6bTps7#Z+o3B%4=#!BtP<CpoNMgW#OpHF^?WQR1)Mzf<x z+csFT9lvThdss^Q4B+}erWe#jVB@;pz5)K4o)Pj+!Ltr<F?Z`UjsqTbxG2H%BS-xz zyK!_N`;$+u0(lzyrq1KyPeXx;v!|UOnbV!hS<*pq|7G4y>;2Hn!CCthI|s5O6W@DR zuYd5JdMBNoVGXJFy~DlwpB)!31%8Pxy@;}@@|-v>Ry<h3Yrs!XH8ic=?N6waEl)eH zO=@Mh?T((Uf$Xli&g{7ggAks8K10o0(Y%R4Cm)&G|K2ocyG<8Ter~V<^+g!NTwy_F z+f&J5mE9nI<nNesolb243Yf05@X3EIHdw0l$MjrZ0PE)?kCPo@J0?ab0UQA@F;KFk znu^>~Lbe<JQZE{bHJ5-zpS_do#s(UZ44`Bl8BIX=G;9@%G?vX@xr&05vaM4n`0sSJ z&H3|KU!SCj(c{g@VIk8@u4xP*|E$Xt9aDc^0+mz<rK_!d@FyZ!g(R_5UHl$V);zY@ zvy~R5u&U>n!*AH=ph{&|xqOcJ=OBpU4U;vWg{6gKeueN4KSB{<=s7lf`BdE>2g}_7 z@N_3)?^|^74`+b6UqvN|=)g==j{b`07&r%OE#NlP@P0LaVP#bwh<o6W3D%UN@pyj_ zHD2cyz>UL8uqD4YHAvHWoU%Pn$8`S*n_18R-~9Z5VLTK>MqTD#p^L8>DKQWSiHCG2 znAtPoh?iZyJj=M=@VFc!#J?xYf63)++1c4C&3HGP4B;8!lSJm+5$n?ExKQNdQ7M8A zX=*HF9_B)Od0UnL(Zh5(*<D^23#XZiT8GwLPNypx-#PYg<+|wP4(G~K{8<2YI13I1 zzoedm;p_G0B&jU#JgRrLXqV-K7y6W;n5|V2TfKE@Q%PPFIrsczF=*pk;d9oEo7ff> zNT(?&gCl&<?-l4C^Rr&b(VE+8k@>q(z(a&?M;LehIwOc7`I@6<ze&zVbT;`)+_*w6 zpiVq|U1>*?<ai}lTMenNeQHG=o#hhjF8=o-!?#5asz_$=td#+;&v_CVasInkh{0WI z0cKNEBhqX;$=>^sU;MjKmN7&90`R7WDU0M57)?beIBf4a9H-?~bP>}z;pFf`Z&OZt z_R5i%PxxVw&x1;&mykk+1$a&R4J%i)*POPZ2Gnp(!>EZmkoj6)7#B<+>j`U5<>Y;@ z_d$Rw?A^WXQ%E75tlty(VTAPW^@5%nmMkIk^Z)k(_yVcgiS}P36&gs05W-P=IN}dW zi$hQ2$lMmz{jq~7whY6N+dwWyKNN%Y*F7>&`?n%KkI7sH!j3WR8S%_JN-Fw?Xo-10 zEaU7Qy8*jrx%I>TJh5NoC&J1PQ%Wc(+r{01n?K@L_$ho0i?1NQSiSK8s%yZ?l-}3T zA7_pl?QTzQf)Rt|4B?1dSA2*^&}zv|^1hn&7PqE(jOK`LWH7IRXltR(yYCcT8S~1w z9rfq+XObIIUu_PtQ4==AY1a>*?bDo7a56yZ9i&k*xH|4mybu+si}x^`4pzD(wWjk` zB5HIssG-7Gb`BV#zfe&l#p>c)e+8DCH)U7S{Uk3-r~?U8??LHvG^LmiMDel1Y1C=I z>8F}*IMs3<yETo^aw2e{J=>h8hUWx`V%t!j9VvHoY{md?$9mCmZ(u_c&+vtO_S&XA zp(t?h^(mW;?mkV=neJyn6j_-8sJa$;NM;O!VJ(a%&m}3<Y!J6aLHN9Z+~?z;hN7oc z;3%8KCY_nxC95G5u#j#c`CIJ@<q}~pL2bw!Dxh^w8=G7vIEMEpioKRE(1;jP+p!l_ zt2EKm*`$lX#j}H2znHKbzl_7J13M2tl+$SSr(Ni7<d5G?I_Gv-;6oMuCz<pgM)K>P z+8T;MKRY#|nNsldOAma*GlL96rb`dC4U2BaFdU_0#)=nu>$^-LftEJE@|+sH<ZNZ~ zQaB$E$bOFne`SQ<kp@2vox+{KbOHmexE_z|G73e|kz`V5hs{&uZ2gmYTO5Ad#)l3V zJ>8wBbEYVrRw_QYC*(zzrgR}C$Z?|%xla7dJT9?WyU6eUqm}wChSGo=BrPyOg^UG( z>iv?rc8yh?eSU>?nr-iyltL-3XK!Y>kg?M6V=AyrC)2FAFr#{oQMRz_=0MKpd@gyG z(`$}K-dYm9Ok33AD9_oW@%u?JcZrSNX=@L)-H|iHrcvg?RQ>vtY`ZaZiO)lsQZ8gV z=LM&v@k)it2NIu3taorXBk*kgW{LCwd-V3{!Nl1#0EHjtK)zD1UbPjXivuxo#loIf zgP*|j7kTT0C4o^zI6>TNG7@`3pi35DzhrVDtoXZ8^<ke$9skO|k%>zTE7`-(aAagn z2@b+yP%l?<KHe$W)-+${Y?y;D+J(9z_I^4ITv&@WzXs@?TNmM=+<jdwalOkP)a04p zf3~5>e!7bCopQy9-uMI!R53v>t>hkom^$xB8Jqt?uTGdv$3knks|D|q{b-j{ga0pR z3-j$=3x!<Al-tG1H?s`<;Qw}Q3=c#^Fc?ruBdF~BSZHc_W;MNxl@{&=Uh5ORhvq4H zQj2@~7U94DR%*E24tx+sPdd74H>XdT=o~3__*E(I(f|)IgfQ=}fk_g77mZ?6qDS_| z(h9IIEE$(XP`E`uya2#tx@duiU!i13v)K>VX30X-%UlBb)`juGNRoMGkZR_`$!kD| zNk*M2+!u+}3eJ4q!(U+|cs$2MRxtaBI8kvM&Ab+}1jRiRa$L%vT<)R-`)dW}n$P(! z4XOu9&bCXI8{Quk>qYh4>e)Jq_&Pm^KP%XHwqlY8>OF0<_hBkOA6bxSH-s|be!;7- zGBiXAog&VYn-&y<Uhb68t;$D7op`)7{ulEE1d(hxYL=cmy&I8&g~WngVd>W~WpgC& zy^Gxz2u$CY#CK$<@&JvQo`7tyII;21%k*n5Y-ntsLtta+uLMfsy%p)n+YRph*E?wm zLLM}8ae|NbK2oJcBGmhf*Sit2BEB9U$qIM<%7Z1fFRw%5x3X|4p2J4%{R7^O0wAU- zu$2L%M%*bV90p3@VZVTqCf)@3B&j3}or*R+bjWTUIGAJLi9F?7VqSp>Wt*pMXR4=` z<EbnKl012bBr1&4m03(_5%Lx9Q|RhJW{cNh@<c7Cf+RuL%THSA49w=MdAu7hE8;dB zBq+u((7wLPMBi#r>dWzEMT4LFEYzRERt*i72XtFN#f49HWx^7PbJWIYZ2)h@AZ=yy z`KoiY#ZS@x0%!4|&qrQwd$zs=8@hc%(J9OGJ!>?#!ZW2j3Z$Ln&ku6EO=&D<`5$nk zS?UoVoY!m%N;Qlr+AumwvX9NwV0tWPE!9fWO=MX=D<*9K<7D9<W(o!gJ&<OKTi|fw zm+ycAaH090oFBV5e77r(BQe>O<Y-c}GloSeHYIm)|Hw*10i?#rgiINiqGv>*Zv4CX z0_5OZ&7yr7%#EtdgY~rN$XGCE;G#e(LM$--`Xsi@Dj?0(@{%=m%K&36$oK|NIt7Sl zH0Aj_<qid4o^w(oteN<t0YRrc5Mo(Yb3F_%-+0IAl;wav7A8B_N0>u6TdvIeEq$;j zY^nKq-{)^s&}fZ;YnV-kWbxJt*<+riMX?Q+M<daHK&?mXnM9;N6KOBtQP9o}{aahM z?TQkMz@l-XmN0!5`>az)58>as<RwF`Kwvw*mo@9v$X69;l)L<iYat3m>5+nhsLVf+ z#Gd^U`VTQ@3}gk6iUZqy3;%?1frv*pS8bcoX~?2~1JFhvN&L*B$uQHULW>K<MP=7} z0O1#B*H!{&`;P|ago+D1qBA{LBV9*T(s|u;AGqE57qH}q%tV8g-(&hGnF1JVlrYbH zRqJ6{fUKVjP`>lzuydA+zVQji4?$eeqs(CVtB^tm&W6hFA%LL-`1Y#8YyClK;EUEY zV7q=4iDN#->2u;1zcv-uN0lJ*!bf{VR+MF@RpsH-z`emV=+)sQ_2_9C>iCN|iy-2= ztm}!k8z_2}ejdtPzn?=dqA#`BS*qUmCw6&)3%@B7cs)lL9|EZQG-J`u812?Oi?&zz zfec<RItU=ofn=souEDyk8U2d}gB;MLLWPqTkfL&}LDee1#CM23cT>Xju9nn5tN6Tp zME2+s>6xT5VD4{$y_7yetu}EHJo7Lyn4mh-Php1JH?vYkE4&4YCqN4g@MWA_bKCKr z;?uq)6{E~ZT^t#aL$U@-k#^=hCLBFQMa`L!f*7Ro<#BV&rjh;>j>;JMzg0|N{9}B3 zbz^FYqU8g7I(BsRh-d5PPlcvS<l4myUIRpZW$Adbe{@c&J0rX?oDIB)iHR1CHqg(K z5SCkwzMX4~1qj;I_xR2!L7bGFNI?%0RDM(2lOQ{cZE5H;<3EYn0J1}jTD^dguRCPH zcKjkGQ%Ug?ca}&}Ff$B<01G4W9`jmqIu?t=xEcXgnIos4z0c$^vKNFx=y!M8F?Ck+ zO4{ivuqs-{S@9kRcIEM)t%Po+6mM`Q;eq5@yq0I84*}*q)Yl~hxDik`e5oTov%X;9 zLVWpWB$y#7H=qkbV9~!pQ5VMEZ^r$LkaL)>h}fKoGVW)%2(m_QXblaG+%7v(%~;La z!MwbGmnIQ1_Nfpor~>A9sq8j<h#VF0#}7!k?4v%#F&uC|#%-24wq{pBe-n^h`R<|s zy$$jKN^1@)@s&%J8Mn}5t=~-E-mq0?MYd?u3de6>>^I~9i71J)XL^H+$exP}6~P$M zq~L69$@jCtzge;vzlQgghKMlpnc%;`3L*QK3f2iXCJJ;KQd3hC*I8}p@e|6mdE^!D z{bNv_L_aT6?LOB9GzAHHl=iqe7P7am>6+puB%3ToP*zo?H6q6mM5d~B;!|0?y!3|Z z$^3y4Ie%qWrl_8x(h_XyTIw;UYEp$ts3))mH~aZ)&i$zMgcLcwZn&BV5TlTQJktNZ zLl(TCprDe{(y)K&4%ZMwzq0-mDB<2HwOW<D!z#KCI1e}=8y<$x)kO6M&W&K>*o*~F zrPInX4!8$JBU!P+e)6mBdX@hYak7F8WHx|+G08I7=(>JX{$Y>F<|Uh{&uTJLM^$wf zr|&FMFoXE7*J!>>?UpEj7x;qA!hN|Nk#Hk+IguytQojV6;8OxWMWBT~4=~BEiI`av znX5Gy3~=P+D_&6Ub9y$FA4NM!`!2@?k4*81A@=@FIzoO7ueokX6OLXFE}N6R?rRKp zuyX&4;>2}AwC^;P#9WK&R_~e-TOt7PXj4eq2w>t?P%eR@-dHgE!ou_U{y?lHQ1=82 zUA*0yE0F&{aP|S&UXRwMfE^Z2x^{E-)jz-&h^`jsip$daoyNp+JaXjMZlC{QHg^2u zI(BXtd0d-V6DiUcbYJo0q$UK)d9o4yv6tP5=3D{*0Te8h<>|rZQoE+S^v@5GSb*nJ zPX=8K6a}0{6^$x$@<NFGB8}vPyTtVbwVMbn3?vvBb;==K|KR6h0Jz5EEqUURJN|<e zI?@+F%Ja(C6J0_xa&Gz)IiQR0Dm9s0z5qvWEQtAME4|9HRF+z~zc$QxB@T>4G_dfv zhxp<+Y%`6kN(Yh$PldXV#rsRev#xfj$WWEv769!^TpA9J96)Lrky*qowF{Lebz_{d zS0y9n7yk!%F|$DD`2s9g0SoI2a!xwiSa63s-Z3)0K0e~Jv=&_L@Raq4%)b37zhMBS z5Hjt{?w4OJ*HW`q>*4XR>+fD$K0Kba5~46cDrP^u5m)b^l9v$Pg-&IQdV2D?U)d3? zf_VwGUz34U{c^~_vrie(z|AA)rn^o-XYX-3n@;wc4lu^_l5mLR?HPel(Jwt&-_BP9 zGr@@X@To{z2a4Er(I~eTV#fC~fvZt>*}z!snl^<Fg9^n#h_zPr&F*mM@B#fd9BzFk zI+bmncsP_O38ZGlynuH(R)Mlwc9PhBB|u(hOR0yoaz-`+Ks=h)7U+6@lKYlD;Q$#I zWVK8X0tL*<4#yp>3Ux!2sfJ;#<K(TMX`I(Xi$!clCki`k#_a8%&G5Oh(iHt(e$G;F zAl(N220!|N*$`*QjJz{AZQ%~$0me}?+!x3YHDm;SUwMzQ>`_)tHeZ{7bYJ0#g@K{J zH=cEo1e~aCr1FZ2`H^wXAUo5w%tHulQ%$T}+YOx$D`)DTeZB(=aulZzx0YR&^sAqE z&Z+fUv7J2-8-$KcV4#D6i$Vpkx}%p>Rl&;?Um3q$Qt)KJR5`#KP8!$H<D0oTn#^WG z4XufH#_t}&lfZX4UyE3#DUV44dDGa&z+@l8LS!6W_%1zD<J-$=W%)gk#)fGOl!zG3 z+(>|h=+^K#B^eY-4I}Zp-e#uGBFoT2kE&9pM!yLW;XfW((4!V8JSIjOnG00^(8A@8 zP>3Xe^h}st@VW3#WBN-VlwkRS9SV>pdZSz`gkrkB0~S)1M84@<LuD}$M$X7xceU*5 z&gkuA(1M8!>v*TM;`i;iI*Ertt;xDF)14T#WUYP8l2z>TYfme0mH2ZfX_Y+}kYZ8? zmNS?7_8srruVO++2P0Cem7o-&&0ONv)C~;YRX`^Rn7}}=p#tRR^<{DLcc-b@6j_4c zp&NLc+7NlR<*{d2b<TQJ8f-A<SDd(MRcrrt;W0l=TfnGaTbGk;13MY~S0A-xl}{_v zB9Tjgor<&(u)+yQKD_{lAO!Y3wq`rkE8MoA16;hJe?(3$+<V$cmLbv1<dg;xLW_fF zjiJA!y;ZDi6JJ>MB%2gUdUbpj*qmDJSS7{-0MiKb7Lq{sQ_BS)sREr(h#6%GE5x~p zwY`9hE^fJen@~v`zhKSgL*f)J7cb1xQV(fM*xZhk=lxRW|8YN9(vMi=f-M<JAwrOR z8{;TtC}DQ4VPkwp=;NMPz46mkVmyt~J>7g`Z9XS*;P47ue1{gUD|$D+u$yb~Y_YAw zx%!7o-%e_{MHKgqQk&MSCpZ)t1KZeCvf4F>++=>oCY5iyhvhoF<(9UQLj8%m0AG*Q zXJu^Css}<agUiGwn}mh|dN3!kuqpyAzA5a12;U&6wFcJAZuSQJ+l-C&nT4HQg+Xff z{Ad1Iz(h~_oWeDo&K3In3M&q~Fgqh~cE0fqX2|YO3~vV|Hq^APQrpId>$XKgwI1w* zyf;`zA4V7tN=Z=w!H8>I7;<Dlr$+#R-JQM<67-z#yz)5ik|1;`!R@kHK>5|-jCk|< z)Nwe70?sXZO9m+Rae1S|3}tthsg%oWYC^~(`LUtoU=BID5CDMTXVavG2>1zF=1uI6 zEP>_Gk&OXyVZ(%nhbOYs7E`j$_TheGVW#*bpI2QI+Z-;&#Wl3{@y}A5%ZY`ec3pM< z)X{iIoa0}2OtES}_aFV`QS)5%bHmI^v<Q`)DfP?8HUamx;ah-9-6#3YisxQZtrvls z>lYEJD(2r^hNY58)`SfeQh~*eXHvS}@6rW5u!wT#k&8b|RG~VLLqyHToi$G~NsVPT zOGSVpeuRdYS9L&}RAH5-m=7i)Ck%)XDRI(H+(pgxmUyno%M;>E_p8*%;{5QT<I!Mr z>$Y1}rL=GP@&2&{(u|cn>okc;M}i$PX1`^C1-%EjZH@^4hQW^ecG&+#*M6-PjvFPb zC*NkU0~Vj~-lu=18UR*$w~%jOAH|Zogtjn9VImO}5@D&rMA|8C+n}prsfGyNGTm!i zG+ViUxLl;Oa!P#Zl#l8~0slq^T(*Crf$M<L&y_*73vF9vKO$0^i9YZy<(jkmKvo9z zAEXc~E=WhdrrxN{-N1s4M51TIs1MX`5048Gk#KcB6w}E!75x1@Sc%@cY5P^_DN<Nr zY?8Cnx4Un2B$))Cpyu9~j0citIgC)x3+=3>7gS*Kvko6jw|QY}am#8C^|pooz6B`` zUW@7<Ja)hfylte2PzCI8AJS)#J4SHERM`;kWhlXdZy4E?yn(=*FG39f_U|ng_{)lM zW=`~&2b>k(;9+LyjUZnk>`gYx-SQyH7Ubd~G2*je-Z+o$omNb?fdP`&?7={K@xN9S z2PS>l25+f*gJq{YrGJ5eFhHBx_l45gVW3HoT<_(K>IExDxDQEbHC{IJ5m?M!Kst!V zefxbfF%{643EHo|p6z>NBwG>e?ra_{Z6lfqhcdJ9iV&Qf`M6CO18FO%IP{jgF#x6x zz@G|U7hk(~9}gn<rXipHPkV0}R%N%f4Z~t7Eg_AhbcdwGqPx36LK;bFSb%_pl$4|* zok~iFfP{c_gGzUIymQ_A-Osc4kN4;I@AFuP$9*4bd0q3G*PLUX;~eK016nQ{jHUC- zitO>@v8@_G_z%!nFL0tPK)+mHxjs5fX0~F>&qz>HQ!_p@bDl`S{X+~a`rmq$1kaoW z6K4=)B6=O;brnp4iV&hq<Ffz}GhZY3;_X~`fDA(9$#iMmN)`d~9;Lw@-$FrtAmaTN zE#2|&Oc-U^kt_ev{yWLv7x5Tj=$C1iD-!H|Uh%HahrEMDXbnj^t~<+<^AUxbc@z6+ z?c+W)u#^$Xj6&Wy^_;%hSeQN)|LDmTGA@Ejv4J)ipB{_mIBu@@Hs%uaOfZ|ScQLD~ zUb~Tef*jGc=2c>`d!?3!e>B@XK9I`U3wqSgiBJs%;~k*FJ3A$<W6CNj&KP~CzjNnf z=?-iaafX-sHeC(98<7d#X$A09ow`=(Qg5=MV&T_)vEHx0YfasP*^x1ps^3TI+az6R zDkb(4F_wHDWW2mH;(o|<dqKJY><Qk&?r`l(=qv&JYIncWw009lDf|8OTe-^d-|q<Z ztT!5oB~REV)Tw0ox_Ug3ojF!UwbP!HY!PqhmDo|U+ZN4$jO;y-i9S5-_RA+0&m%#| z7aI=0ZN<QhXqR721Db%o)MD3-L;0=f9FLM}2C#l1F~LCG$vof$CB2L9<KQpky%G~4 z@9V<R8qluxd^$NVLYmx(ORePr*iBiFdhw}jJX>Dq*6TndzwSnqO>*3+*S;C6-RKD1 zcuj4tO7Y3Y(ekvOh3MA?7y8FT)BAH=;mp8yhPORm@yl|!3A@Gpi?6;sy+UMkUCm}X zfD~LI2;CF?rZXBoDu?yAT=d^Oj!OTvf2(BM-vcqdxLKa&$4JA74qIs;(aD|j9J3J2 z4fsi8C5@3Ci1vI<3^ihbvUXb9z5A&Wju~2wRX{+?r#JAEV!uVFaaL1nYkK*#+PXR- zMBSA_RmTlw9L6(D9O#oe;c+J)yt=5<s^m&tOp1X*G8Q6WH)zq3cl*LyY$9+m78#!r zSW9aXe&axe!`8kqKIN~+<QMf|-0%ps9WLC@wdvJ8Y1riWcqh`)=N%c#99nhVK`?_b ze5`Y?Z?8@p?(eQ$*V12pQcC5BDn}nJZZ+=+vC*o-+`Fr2+LHtURc`xnrYEoGUHi`; zGbp!bi~4=I<sXM6B_@uv1qFRBC<r(F)gU4vo%_Xuw7-?=?bfOQX87L+d@q#>c`a1; zDqB&z5^{3lK<o+iDeF)u-od}c4fD8mRx#Vq(1~v2X?^FXD;a4qSHCi|GBV~0tW|cN z<KBiXdmEc_^5q=01@+F(RY*GhepJ?Kfq$3n&4#fQpo9HV&WaYian?CR9keuV%ZFlj z7nTHsgqKd!dnrcF9WCdJ(J?VtgCF=X-Peb@L8ZL|P<oDK_?2dYJc^#N@so`{f&ero zy#jub*rUrli^};CD3aDuJ42w;u0*sjKhMl0ll#>jEv)CpHs)CrD?@_3p&xl{z7p-1 zC_Ej;Mo)>`1gxVvK7;D7zs^6tOz^!R;VYe`cp&-e24mcLspKO0rV-|I6qFDRvwG(* z;aHjQRPIkVvDx=TdL>Zp9!?`=-08L$g(!T55Klxs7&Z&KB@|fne#-G}1>gU4LQinF zW~}N(H-^aRxYnW=j!;mB%Cu%tF|ug-CmeXc*|78}hDFivuUw-`P^0am+aY12h106S z6#n+s)+~#UYAPZN(rPNWM_%~XJ87Q$M>?h5ZsaTkG~2n@v|Dl5*jJWbxtOZq_rCMK zoNhyxsUK=gEZqwV%z1T9JzI}@LsnR%@m7I0JNc)AUM@$|4i6TE@c6z-h@PpBOu7f6 zBA);$_N-HGsgCsb_ApGmBpECM(sRowF(_FS(M6d@9+j&<!)OSaM~mw~3OhUCwRj*- z5lC6SV<Za7ujmpDx*VT<l`V;Pc`-}!`K|$!`^rsDo)nlNW7o+ho!VV|a5Z<{rI#&n zLy3$4Gml~~ZqJukzh#4DcNI4(?iWx{ar2Aa7=z<NW37T9C}IkvlJtI=!?Xr&s)wWz zPZ1=YH*K!yOqHH<NZuD75!TLpXDw*VA76(Et>Lo|s0K9queJ<KyM(Cy5gK%gS?Ar^ zTEz;W_?h@=ay2%D0*HexH2vpUzpEoB=h6QWyMhx^4H|<kisb$W-uWEXPYYOkH7FJX zZ=-Qwi(YtFW(r7JXs!I@S1_>uF%GG;72AzGVY!~*uHZ42=+?-`&_612`>h-Ap6|f` zJCkHPkRpWYH|kgm0=4z8Mk$k1QVK3K8WtD4Fbch;pL?Nsh6}%rEzYEiWbHcJor@?b zVOb@=q_S(G{w?1xr8YoBQJzS|Nvny{9CROeS$svu*ZH|NI<mq(IW@J^Vl*K>J{N6n z?D=oma}7~udin<^a?-uM9&xitMJj*({v~u#o3}D%!AyR;*F;1_r07!5IPrE%*2%=! zc!x-qGwkg+RPyv!Q;00Y|8sY^JdV-PRNX4r%MvB2qRgTuSj%sR-UL_Heg1n2@@0G( zJ~k&A+Gs*xdJ<=Q3)@j+f>88_yjbrFyfx_}m`UI8`QTD$;LQ#V4e7SBGc#+fWWFc< z88ln>+5e;>JASQtWyNZhwWaQ}?~g!*^Q3y0rHa0e)xo|#jS6vm=dc_~&)r#_!?Vd0 zIxB@u++Qvl`{zYYN?SN?Sn6WJ2UHVs_8!NRDWBCt4ro3JYb=PoJ)r;Xy|uJhp@0Z2 z<LNq&rl8{Id8ODlY<{4tO=i@f{K~%hTB*%U?NgxKZQKtdBl}*mEkEC{W+%_7v5HlS zakdklAk-0FWglIm0=2R~J1MzXV#ngR?SMhdehKeEySy&&%3l&osACU^<-4n)kM;3& z53gfyiRF9tZosGapDVWbJmsk4R8EdgZcLc($)0uIa#24NImq!^JeWukaj{LnoCon^ zLB)kR{jro|*}ne#J;LV)y7iXix{DqUGz;b-?x^dTY7(<w3fR}N`<34DWgmwxlE@#X z-$(%va{mfLpY0o30eWx78AGv*oQuRC1Kh;>gSzGXhG%`7DzL<v+*d6!5EU`-9|{I8 z7OI#}qZo-rYM4HXvnw#biPn5qsdw4Hmv7=spOBGQ3v27P2-d(p_GSE-3yCAb2j8IU z#Pxj=9)Rm}QYo78AiXcF7yPPPbMPx#YB0)*zbFd?=l^J}$uw-Szq3WocT!TbiR)L2 ze%9wW@<-l<Th30tM*~!jdc<B-JiJw#-#z-6`*hS$u-i++dWWgwl@M`hjd}{Ewu_Sj zrlOP47I$h`juk%|u_%KQ=qrZr;`!+f&S~@-h`^GMo1Ki(%+po>E@$7Y|Ky}3TJWJN zdGMi%qi<VKryBSk2oDs$+a<s((cWw(r~c7c%3I2=zf<^|WX0di{-Rjz(q4&-oUU5J zGIsp}X8rLic;liUb*>gP#S2cFC*Jl;u1;>}ypKznIpCjEr)-@~3}gk*-&$Oc_R;Of zm+;QjhRRr_3%fbZcX`^n3h!}FPuH#(x!*}I&L&>fSJu(p&{s=1Ne3v!)qp!RCpd4s zBM?l-9+j^h<|&!+$@_N4-0SD!)OY;w{h`Eu{qk@#O)ssz<(0`p&&8^@D#f>`S9)$N zBSB0D*KsfO`oFopSgI$cuikq&)Pl8<DJP>H$k^ILwxtG76F?IuLyfGt@I8A?54m3# z0JWdm`4-5Iuif8myln@CLBhrFE>Og84p4gDQEZczvF)sWR}_Er0ZG*E&-b^W>jloi z(Ez9A=x2rO4(I(E+h0Z^tw5F8a6I&!JLt~8`(4D@Q?erZJSpWcQ{voLQF1Hnk5r1Z z13$n7To%i?u-$kPFF|F+2+A(WC9Nm4ol=z?vw{Swhaw6_pb+9saT5Q##ZM7Or#g&L zQjbLv#66FQdUHUXL~jR1r>y4g!$Q@c-NiS~Tu=Cnl7+k8BaOCj+Tg5;+ALdgy`;!% z2%Sjrc#uG32Ox^p(Q2Kxx%$0B1v_(MT~_m{n$r`PHX*0`6L7^l=D*(Laz%siillm9 zD&;KO^E6cy-}Ak44lApyqMh<flkk51v8r2@agLU#5)`d|YPu)4rF-*#O0zcn%v@^% zhK-(sL2dh?j-|A&4ZI?8K&wt>)nifS<^I&VHU8nQcq*mN-Zk2yLqJ}9O*-u{zD8RB zt5?tkgCfx#>}O@XM9h*&Wg7}}1m!9}Wv!l(*zL(!!)8Io!SS&8-=e&CiQOxOIRI~k z=fEDYknLLiqK)+W7^xAT*}xz0EtLH=wALcq*~N85l^?VcwOYAkZ_#StJR*!B!NPZR zd1t%qQt{-39sA~F>d7ytO3=>)aYT{H(Q}<e7>Jplo)xOL{sE;YhXqgHm^F}K!;Oy8 zDlJqUTE%f&?`o37T~D@FibFokCE~g$W;@M1leN9&xMi*scfGm%dHJ|^=}w^#=Ljl^ zW7#5B7E2uEIhqnTA08v6?$<u1+xn0pZ(5nxP&BW2|8Bf5M-Xn$7&NC@9!xCP5X0BH z=IC?^`6XWKWT&7YwHM|-!8W+y$E@3ZPQ_1Vl;aO$BC!pYDoeniY(h2RXd$BLQPci= zHKuy^{ZNOoUwtm+J;PYX(~+D0z2&i0&K7EzxZvypqFiF0a~U>yX812qKRJ(lC_4tm zM5A84hFmL{@~-fr+qQ@bRNDa%7=o;osP0Xhj!DyI&1yu7clt*WiUU8%dndEsMD;l0 z@7p2e?%2p(PSMz1_nZmQ0Cdwn!NN%dV06F}iQJcqqb&EA(JL2uOM;D``1yG$sKAij zL363v+vAa}sP>SS4s-Ag1_{KY#DewKNCmV|zc1c9^N62+mt7|3m-6=bohejaHmpa! z@g07#6&Hq(v}=GOzQgB4`LM;L3Kfl@@uUgc{ZR&Nk`OT*G0d+b9CrJK`!5FaUUw~y zXd_3(bPbQlf)qe6+Z-TGQ}6RU+nG@btELJ#(V*W6!Q?pb$uFXas>q<n)~BoPfM_=! zNY}jl`Qg6kw0b3zMU^kSbboh~iHYf;<ZZF&K(~(^BSf=8MJ+*sj^>4`YcYE*I*n_= zh;;A@rR~sJ0a|X062%lfP5@PQ>;>hJ5w&)9q8YJym&w?O{x5BEYroXg<MY_yea!3D zvB)iw&*jUY%)1_UuFNAm^v3}}1|4;M(1p{B=qb^#DgIUXE-vT>WxwT|@}2mdcelM@ zpJ?;tS_XB8^C$stz?BD|7$8U0rE>$P*8gaC)#gTS`^hm8B@KK>Fo%*rz+L$z#>oka zeik{{lb8a(xz6ddas8xmcfPMk!8%pe-Z)n&Q5iHWtsL=WeS*bR(ei+1n=}FGjX^%( z%B({ZW*b0N=n@4MFk1;*a?kG!Z9*acD4YbZ@8_Q5aIr@1?B=|c&!kZxh^IqCBT*mx z<N%{fdu5XB+1+3>rNh<4Vl#D6W^w8+^M<d&Ko9SMjK@S<Bz0Q+6Y0dT1cloPBYl<E zOMB!tzH5tf=jH39&aZVm-<T0D1T=1C^7<TEkqUb>y<Qayxcb36EMl3VTZ8!<8QqEm z{`K;aNi3G(#1AfI$4BTZSny6w>z<Q(_1fR8r#xuU(ep5iv;zS?$OCM0h4aJuAAchD zQgRBLD>&~wXI`Y=Pr2vMP1N^?pzA5T;mK<nn~vV_5#g&j&CckQWlwkwPz=7$6@T4v zmQF`%*Jp*Km2h(Bcr~$0>E|4wl7hOT<|d(VC{H?Ur$p9f!`_OAw=Nd?Ni{e3bLAFo zwpqW3k50O_%Z)6?2Pa-}iqqEWAWtbI)86Ozmz9PQmX|B{g{;N%RjRENL2&)H%~xd^ zLb08)3(Gj=+8E@u(wjA_W=WsS)BE)cOZrZm!=a-RxsI(`dX{OU6C`QxY^qf8so_|( z@p>cb7$5d%b;#E@b#*FoWGtSB_Aq8-jP8Bs)|@YiWor%!*$c;e_Uh~AHmCKFPteFA zMQ`TQ{QfWwDI2_H#*;y^xH3oV9ks4#o?Z2qs|We>8%L{^EGDrAXP)UrrSQv09AqrI zcyy@w7?nGI!EhcWhGKn?_p3$5PmBAGTU2W_Yk6aF()=}TcK1m4DvB<a+fn&fE<gS5 ze}-4A7?Xedn&2))85r>!kD`$Q>zhP-d1*p=DcQ^meqjL{EWa6$|JPy05!N|+*Z=f{ zZb7Hak;{q_*`H*v=cSj$n9b->{8Q_nelC}i>}<@*x)D@=GkSiU;OAB)nBJ9TLBB@9 z21{haFD8DlL^`seOQ!{o(dtZu&*1GbH|Z`xkD|%tQ!#tr>X@)Q6t+-k1q`<>uySP# z#QQ)SVp)!R=(Y`^5jud;No6;xvoe{RSsq7gxV3-sRCSxTI9a>?n_jtL@)!P<?Yea~ z(Z}fRv^0AOuY$==)z!adEXb6;Xwh~uwaq!E=0(#kP4yg<(;pk`sk&@(5|&u3bGdYG z6^L3Vl??8b4abt^7eMLki6UhETvo=G(bQ4LNUh#_Ls;xKJ>)X|-2K*GeOjI?O}Ro3 zLN4Gue*VK4m;WeQiM~yPID_+)-;sdS9mxV^cn6!D-%2?n(Mf)FEw=y5Qk|E8?VN-m z4h6j;siIk{=fsg!v_-2gL%WmqDOTo00;~?7DP#SlG~pYV@&43Z26z!JlltUlNj=;6 zLb36EKEZ1e(&UOSRCWyN)B2l{ivk*xszGvwRNTf#<U7>tj|7$b^(r;nA_~5FmWf3o z>G6mB;K~N^83x>@5{Wi4{wI|2Nazh{1Su!=!=;l!7F5T<&`xS~?OEelEO8A?GNwv} z%2tABok&Iz*6PzmQVnb$pr2svnl=wi8p(DeSWRMgIUj3mJiUfN=x`~K3lqKbEw`<` z`Ksu^>UN}sSv<{<jdr4kKf^5=X(XE~@3;D77W>THBAE^bL55~hJuNfSQ#`FKg}Cv2 zfXY)7qp45-c%xDASFF>=@ObU#rgZr`p~5`xmJ;rzkEIFprDQ;x4!P(2XF)H+u)#dL z`hRGXGV0R`Vi;Kpr%51f14omu7(bw4c*(x&N@pVxet#<d-E&D|zN*n{*YKS1OSms1 zc=`m2Ml#@qRlL?Mi-(4w!A9E6I3A>RSLlEHdHJDEe&Q_Bcq>r$oUrp@&J3xjbb`YZ zJ$_n&&pWv2VN&LEB|SgAEM#`&n7{<^pX@>r(-<Ed0h8!MdLGV7&W}ME4^u^~@}w?G z=fdBEE+8caVswP{i$?v+jrFSDU)Cn6na`zPY=6-j)H$Xvc!A#wqn8=gt1dmQcV74~ zWHautpxT0cHCv>2g3cP6gDq06S81BX#mO5FBY`qGhDmVu4lr?Y5{oDw4&Y)#zBH1} z)RrK>)FBAW<0j4<!4wqh7X1p`UyKEX5}XJ5D7*d#-!x3Vbcn4>_@cw6+x@>sNIt|b z!hsO*Z-w$~Q^VPw;#QaZdj8yl?<*E>h7u%!UVWsYdWA4~`nFVa=$1r280waU^d@%x z$?LNZP=9povTO$O`_~^F)2mGynC!(hF_f+@*Iv@0gQ<YxF})Hx&mepsdk9`M9wW>_ z8;{D|D-N1SW3J<zz+Qb%YeXzYnbcyjf5`0`LyZhpi!>BtLbs$pr*IqSSk$DWH|cOq zz~DYTuiGI-r<2LmWQMz3Efs6F9A>25_{iiZ>Wv68WaEMB)5S-^B<zBoV<vxhA`qd5 zXFdh{M@V4h_iK_zrGV;X1iKEa?Ny3?A(Uk*fTOLszO6DB9#tN7`qg4<QL}b4LfA=e z`c1vvn5<!~J)zeZwm7K0G}0pm*Elv7mXcqmGroAb{K`d|RJ>&+JnsEV&+vnDum|M? z#jUB~SJdsvu~)fI4uz>5Yh0GZ{<Or{oR=M)(oUe4Md~=?m%6#@A_rG>z#!?8xe7@P zA#KK(mnwdd1VwS`hChlX3u-Wpu=@G1NT<xu$o*|z&R0n{N*K>Xo*aC2r^C&GNhmB` zkb2l>6Fl3@mKL+2K}^*y^ymoVbGwD{r$nOSx~|`N=qtF$8013FradQgE_l<xvMw{L zY)#~~B81;i%*qEQWxLK9PumCeu{sh6s1?u$g07mgb~**M(Yt*rkXPB^epUtsdrnVT z*cSE_GJVO@x$l4PKR9*;O=i-6QP<HPffXkm7`fdV+Thw@r^6vsR^nH3swd?dq2bEP zs$1Yv&2BC>+GkZ4Yv?g&WMELdpYSRr-Qi=dRa2Ejw01i8Ra!)YoUXREm2BvA)Q`ux zRd|;)HmC~JV(?FAU4Lzu_PA)Bg&!*f0~-(t`#45B!Rg*zQi0Xq?+qR|5<fS@TN*WG zffjCsuI+NQm|R=6+G;;H&Tl>GpI@4=R29ma#rV%cV1tL)1V}Hazqfl%Z>8;$ToQY{ zLHEqSdr%I7M+2-8ElQtrJWK^mU$^%C&m40z!}&v~9gpp&fFTrounLQ?;msirHAl+o z>!jbfu>^ilw8-O!`LLr~(I7kL^><2GCMi&}K~|M=w8Z$=?sbi`pY6!F{I>XFEd*{q zhqfZHXOqWtZJ+u6XOjV2Y5%*w$msE~8uVAzPiOxcake<jH+=B`v<w+vKS#98DTFbU z_0VX7$##-8)F{(`O!)O48%TfcGi%SJQ;&dt5OCo*kkd9cHjb#ZviW61td<g$>>^C| zlG)-fLv80__Or!pS7zIqq^GeFrxLljxiIl+cUQ4VRI^DuC2(r7J?{A|k7Vk4$YuS5 z12Je%??-y2WG#8sB@)98GknB(i-u@q7X$ghaikgI;!6F*;=6OZ{d~MDsjpELk^-_5 zK24%ttyx$t;I>DQh*fWgvn!o4g1vQTOakl!L#`g*nve&d7a98lmDg`Qa%P0U%krgD z|HiC7!c|_yGC43wMa5TmLywFf$pqFX9>w(44pHW1z}@BgSDT+7uF6t8CqiJCi9t%I z1uj9X$c<!w?KKS7OoaW;9Mi>@Ha=OIUQd6Tr$w;30dezRt(As6L@JBYR|xABr<Xb> zQ5grjuzuqQFA<AW6SEr<ICrqcLLuM`K||`Y#gAk`X0mByQ{VMSG@OXsmk}vpo8|-~ zY<#Ldf0q{ahFD`-{zoLKJoOwpICakOtgaQPfq+(*FUBSI=0~~x=g80*up+l2VH#kW zD}__#gfN)=U9+GCuk;Ko;e=buAHZynLQhJ<mGn?b$wU)dvq}G1!v+xj+8?Ye*n_6? zVy#^G-ZYPa_52zItY;Y+2Y(9GUM|--{bSkUO_$4?BAwX9U!xO66cnZ^;1FeiH{Z}Q z+Y7K&{rCfArGgXlz`>>{MI4MJzh77?<gP(qc<>3|nmSo*m>xrX=n?joj(Ws9PVVz% zk;)aPOT;^`y`KIRCyQhFnGg=R@h7F=K!hDVovbcU$>;}>iVsPTO1H4x&<K+`vp?(d z5#8u&)_C&yp6w_U2GR_Y65&09gZ|J;c6P<jY)7awA=O3iord@@J)$u)aN?r~l}=qx z!)IuBBVKB#eHzmiJniCbs*0}+{zW=5xQG7IkgT`&E1S>#?YZ^ZVEPg0XRcUj+G6!R z5)TqLKSS{9ul;nD1wWtA`mDW<UL(7@r?5e}y+<@#gt2=r(F{CBzV|@0m-u-Cz?6#9 z-YRkSt5=*)c^YS?u+f5ng<NW|c8_Lu{A_nJSz*EoG`3~R8T>ydLIB@8;65zMc)izD z$tsql2GZ0%H#ZwsI>HXje~2JnY~cK4l?eS4*}=;2RKc*<BI@pkN?%hS43DWH1!A+X zu$=f04i7IZ3_Qr6t5?w}&q=<6_x&PTmSWsXzzvR$igJ4oX)?)yx}8_(<-8BrA_IxL zM9;z>QLx;f2i-FQ1}SgeV@&0%+o~cdzhfGkNuyKo%=&0dG{R3ubaIER2V$kmwFl|s zIjr$L`%Z*tZhUpG9Vzpb3BQON4myZ!`_Y*mxCtTfSd*Daopwq6C|()%XG)v{IPUPy z>Okt0WqBD(Dp;`cT^ntHed4k1C+KKBA~y5a0J%R*pvyx-X+@(VN6U$(LA`U<yxRb~ zoh@l;3@!YqTTSUS<;`4U3RtQdPo&P?0whP>rXiQAcUXcwuSodD)tXA48V_vLw`da* zS1Wx<p2h2#?y7_QahMzputHIg`VdlygGHxKj+jj6+GwV|6I5o~=IVc2Pc_H`MVGFy z{!_Cwsk=lZ0O!Gqe}=UuM-}kdL3ATG^o9NYcyW^Hsy=9|I+!Ca&X9#i7mtA$nyb!J zLi0f-2%UN%6hjGhdR0$DVcw<#1wWDp4Cqv(abjZPs0(K<vjouE6ZL1#3v~wQovrQw z!Z0J3HcA@gx>eX`e$wS@9Ip{Hm4g6tT+5)ojLXkbOlRtl%?7p~9I0Gm;+V;4vDv^p z9s2R}=kN7rpf1(6_l7ea22h|^!7fM0V?u-oezn-ZEV%pibAt()(O`?g9+n37+mq#x zZNf!$V`H|evKM6<PSu5bLk}Eak#ZD81LT=Rq3Vy=>bz05U?ynhFE50Sg|5SRZt8M{ zeyTBy?NeK;j_v1)eKaXpk_d1+YpS?<Z`PuL!4g!*y(-|N*U#G6OQ96Q+cU?RCidWT zZl*9duuwQf;_u26rMAnrfw`h-*N0c{2lYSPi(8yBmtAg7xx{2_YBdK&h^BxG-nEr& z>KBx%S=_fhb057~Qe36X7}S6GQ*HfzAXiN2-fYr_EooB=Z&A3;v8h*|N3JBQDe7v; zzG`EsYW<~pTh=je(bABg%E%M1v*+a5<QoEM%fuh+_L2GqhaJ70gWr%Ux#aLWP6u0c z$Ss4Ik{Q);&I)1)X6rBsxmHWIV`JeUw*~jTGe5doRUn9nK;4?Iu}iuEjA_WOK_D_G z!-X23%c4k2K&eKaEceW-zY!A{E88O<rIfEgvawZPB0Z$K<(2U&@d)Md=vwMK!TF29 zpPWo_$30Z<QE#xiaz!@k1#;sWXuNhBehxT&It%~Bi1vmFb?46;tLre-H6XWV)Tdx| z9ycU>+qO%SpvK+Y&Y@ogBj-eNXj|SDsOYda0U3llI}(;}o2x=Xnm4r6DGt}jS(sT_ z#{>c{3Oa619*W?q-+@X2j+hjSB17&jIhl5Af<<Z!6m1qmYRxs~Y+f_g#7p<Yfwx|D z-DpNbg8N_UmoD0xU;UQcTxhD#;!6+g&B%!+=A4A6&(%5Y@`OIRxe7aLKgWIYmwt{> z|Fo;c5p+a6Des>t1iE><9F)c8p)cS4L%U)7`hwT7U+gE#(rfG|`gIuh_{8sTsuAg! zzG7FG0tegm)$vwWyE{q8hU;Id)rP$P_4kudi6jP<6MgTo=5^QWamVYMqqYG@R_tSU zP_rfk=M}qQ&4KR6VXa+(?6=;gLhFJUQBy8j+&%c5S!rfzn1LPp-{3E~)<`Q3?{bb) z;LQ#9zZZ!(m+zC8{CTI^h3Ukkh4%*-utS)8@Q1ghhbfI8zh=|%<vHfnXwy(Dv3x7` z=bkWTS1@$xcp?4WU+wF#YwrHj>-%l?jCC>SI3}HxD84$5I~(4H_^EYA{ThhpZk>Rv zkE?=0e4jr0RQ;|9oH)O?`1T$Fyf%YqgRgr?U+NcTx<$EMff5HLl|i7HmH${Z{n1YK zaGk2~=4W50J&@4s7)$Y-zeac>)FAGS?@Wb8y8GJTuc^`q?a`^A<DUXoWT(N(-q^Em zE-S;z8hrl#6fnM+d6~26_I}2C$<1rlj?n=yac3$6DL)LVZ8pV92#0(fjv}Z6i?+2T z9c(@S+_{7HN>dHZD31i&8-ItBYc>Y{h^Lw4n=(!s=Zm25O3P<M?)mAkmf?$sHCR7o z>Ss{D;FaOh_?4sR8w>Ax>*fr;koST4_F9HZ#njr__SA6We(SYl>2Z1e;@9zLo7e%Z zho)@wf`uL}M_Jajjx#*P4yN9}A1I;gq8~pZd&cyt_4gk{Q@pLw{Ad@UhQehrf1o(H zDtM^``s0b&6~~3njLv5|GkWs-L#rBNLbT^=?6gd}fn?3Ul;;psP&rijmlK9?N&op+ zp#T$VM?zoiAH7Srm@948l8=7awAWZFkiL#U&HwX>7lpd{nlP$l^(MA_pqT_&9Ry<` zIARyDLS~7l4CM@X_AbTwXI>1=AVT<!sLuPr1IL68B8oQLWGC$n%TK$afwz?^Pqvh7 zt~I`TnqOn~Xl}~V`MqV$nN2OJ#F_oG-hVTPz9pH}=h&ja@6vo3Za+ckYf?D+<<KFK z@QstU4cqvg{gT+E4BZ|w$p9D1o_GV!#51NWY}RC_fFjhXqLz6Do#L}m#zBWQqvkK_ z!sIEVKM%@zS>}qy#qQttb`r~DBq&l18a8=3Vd#AyF7e=J%g-Yb*UHq+uePw*wq-${ z+fQtH=#xBi9oF5O;nJYL$*ZpzG+duq<d`Q(<<Mw7O^o$)I|fFnI7Io2iH!XXEzSG3 zT*ni@<<3RfsPE}qM_2=@{nJ@dl<Pt2W=r61?bJ$|<vYCmYMR0<FT(<X)ZGDO2v;Oh zcW<2dogk|30Edk*9Q`rFkBh^<GMkP++Tkd?E#Dl?zN5pwkSU%kzLcW$SxJaIPgxj% zLgr<Y!!?3~VgY0_HGc@q+Icc-MT4Ys%c-sgM!6xN3KJmvf3W`djUk-hpU{S{2|d63 zE`CSI7@UpRT#R6)*+1d6iD8OnsKfUm%SiQ@;1Vq?tCa^efCE(iGMM1<Cc@;Qi=f4c z(=2YM2nzb=3?yZ#Qm1FLV&a3zJP0bHy|)Ks_>`;sIp3WV$WpOb5JK=^A5h7frp@J^ z@Mr#B>KK-N{UPJW76S18&nH(Fc#7j_<eap?PyLUNymYWIfEC<X|M6S!kN)33&*jp1 zSdauugXYTLfnEOt0GyBIuA(3kr)g+NW<$sp4NYV~3MdARRSf{heA?d|h6Pfv?=E`9 z-BcM=;z_&ca{bwUC~>yXf&L@-tJPA5_0H^IpEo>l{f=j$+w~Q3b92QTFbm0|=kr=X zu<?~Fxg#2I9G?7c?(<`l4y%qTxdcnV>qr;%t7BSs8U>|>YHA}0*ZJX~DU;n;L2Uc{ zvo(6t6LWT3Fow+3Z=!soqkgO7I;uje1i<P9SOJSqp#SA+Kj@ydFek841SG)O**#{Z zN5&1tBlnN#;PnH><;qlnhc2ECY|_5O7p>}OOlno5pwqI?-naFY?~m0!SK(pk5NT>b zK+o8u&_}{QT8(|OQxI%=&i&2HZ?|W2yWYSL3BWC?s7Sf-Ki{*tFeejm&g4&c6#WJ; zWse|0fs)VUvhYcy$YJc}f~yM#>BC><FR@Zsl^65ozQ5Y8v<BA>sch|=Uhet14&-yG z;E3AXWjqL3%#*`0dx86mM4nm)k`|}$V>{pAIyjJKW-uKRlFU1u6mbB~anv?P4ha;} zMvqO}7T?pv?r7p`1QQgD)Oz&C)WF!d?DiYoCkPE>u?rBg^iFei6Q<u=Bp>u2MDw1T zkN3hLrjQ2CK;SSyg7nY;D9#a38WdW?zj0hPFw@qi3w?+^`Y7Cz=Z*-zJFIWeB?=Ti zYS{ff-uP$?xeP2Q==z}TV?zF!g(2u<RyFSUD`+d)MUrP&{JuFq4F8(UefI&evAK?p z&I8kXaGGp6j3+vpQ!=b@AfLXf9#4I?{krWsD<7)u7g!u&Y0L!LqD_KEs}9AeMFA?N zrrDmI=#2UflVxxH*zxr$jP01s1STn7&nEyfZsigDXNG{$>jlqLPf*In2-Huh;VOJp z`TYLo__3rnP$jX`@5~<KO?mFk&-kuqy@phpwD{KMi!JJF6{^+($Zi`;#>c|N`PeNf zc=UD6Be4r}C8z6}bzKPw2}u$~^C~bq*JQ_oVkaX~0s9G{M`$g`(SOOz_`T7w_Dw$- z_Y3Jx-!wQh6M9e^4~Ommi&#7&iRuh{8-`t5Y0@_Sdvymyr|JRFec1w{PLsg<D{-;X zGYjyfHozc<+ot8B8M}59o^|2kXgw97!{?U;vA#+zv(R!-H{|;VLDx^&y=lXts5o`w z#4WH^d&2L+TSa+gK!s`mm~O1W-mv+n!Nftwn&HI4*5i^njQIQo%IPl%iHNr11poHN z)xTQmn%8Bey>jV^A#LSK)@(4zx!NjwW4;s<GiU$-g%>8=p;VR!Wj!~_bdJlRN}%S0 z=OT#mjf5<JeBW9Q+8%B;fV5k>@b%g$QwPv*7oK96HD*V^{{okr79B8ziNWtN4Hg5= zO_bQXwkk^4HLiM+<fpj=8bF)bA8%{{x=fkf`$SbG!AeZPZ~Vji4^41tO<xkkqJIPl ziF92-T0)!A$Ud$r@Q3HtxWaIscjv=a$X|GLWski>jtOlTT0T<67<KT)0}=V&7*b2- zZE@XZ;hPF;;}Zm7JA^pi+0an+SJSvGLbBBk!?4SCfS$)_z026^AzDXTsebJNW<N`E zex0#_qQ$)C+>08dvO4@LYir|o`0Bb8<qt54HWvQ|rp8pcf-Y2>{{3k1Xfm<Row_+^ z;oW3C(=TJKH%CgPz}`#>EcsjZYD`yY98f<1Pp%o9%xaK?$DhJsQsSZv7GizX;1)JG zhd!wGqReutPaouUHc&(Q(8#@m|G-O?d3y+sCyiV-pINUm0$|rO{l)Usi(SMRa3FYa ztFYKOu`Bsup?nkqttV^7pk1_Q<LGLn!fRQkTbitWpa%4kJx+r<Li#YsL7^)5<;<=K zl6mpu-$YIG1DtL1_7f$^Z<6_sBa#XH-*<e|Li@t`2O0eW_f<xVI&Ul-aKE{&2b+%e z4pF*^C#HF4iCaaW*40SHcX#}v#}IpKsnqTDB&1`!{^o;2h_(CUaZwFK<t~jzxld;! z(N~Qx6EBn?wY27IdA`ii%yOIlk)v{>hxR%`3=5>ld1z?hZSj8SrHjW$PAj_w4dQC? zh|{W0A07{eUs^vNuhZOBlX9xWKQ0vGvcKmP)GMWAU=32B=0G;gi;9kTD*-i!;C%Eu z-)l8cZoWGDt(YSo)LImf_u`NE?TOZ|yHtQHUTx}law;RjR5wTdwkSDcyB<=ozJM8h z=xpwO5~jrht#vUNPa)DULX~E|n+-whw*y4S*9l%K^zXRsB2vMgylv)xk}EQ@L_pXV z&Ph9ugJ-_EpQyxvmw!&92nXroDERWp!9F&Y&Jxq755ISj&4P$ijX9=7CmP96^957r zv$RgYIa?tJMFY*jb=oS>4l#go<#sNuLB}u4WXi<-C*RdWufMSZ_DOyKMK+7+&6OBm zdP_ozaf6GEp#Gkrxy!`Mv7{0PSHIf0qOaRgaBPQvb4|sd7F|9Er;{h;ofL$R-hA!z zZ1^7|XyzGB+GV6=^N-?Pomt|9QPEMe_+&m-9|SgkV{42!NpQJ_9p|6kLZF6%&t$lK zLXT)T0ici!=4Bu>9CUcB?n`z>!ryos@-{-$_hm4z_(OcOj9?z0(&+EH#ks)~*w7?m z9OZnhy^IA%lS36NI&?Y-bD)0|PECKksHEK77je>dyX)dMY48$V_jy$b^8VQYJeTdx zhjU#B{j)UnFJAID4@B#;2s`pb!F?40N-6oCX7<>2yeQ$0Pk@V)=&98~{!b-P&R3$n zIR@zbP>Ebdl})X*Cqp2|yl|+!RQn(=?|!p&y7#`9sAFCy6$*No0^+)!hu<g|TvJx* z0OhGlCZhTwcqZ{hbBZr#SfMerTBki@$Q>UoDR`zXqOzlZG|uJM2%#jGPXI4>B2*GA z(-{zY2vB-9SEeksq#Q#Bk4K~PwXy6bZgd%$vjr}ieC<~f{At<X&WA50W6{z$J5^U@ zUrN~cMY$cU$E<OqkE0`RJOayXr+c9D4W{MRs~+<1`84GiYB(->`!Z4|fQRcwC2!aL zPrAE)#G{*MOK{%+fCHj9Yh|4x)yY~~+(tK<n<5PGS=`(z4RT*0|8lp)0+qLS0FI1J z<~K9FH$$PY9(?XQ=A#O+c&u*f?3vKBQdI4~x@)>^-(KSsuYvM1kTMD8gr0UuVl_KC zsI~f}wod2J7hhf;>AXesY+9=7bY@U=UB=($x!r-FBd|%G3?H7ZcG!1s{K`9x-3HL& z_30Jh42YQ$B)+)<3b5i?c09}kPY@j8p1(jQyxL%D)APLssY2$LNuD~Q1N6wm$Y^-| zr1}2951Z|O&wCgvuow?oJ1PPXURvmb2g6|+bStJk{bhFXK<i%P_DS`eb`7B1G=|hq z`y=`+M}d{F!2J=L*T#kMf^<d&Nq{QNL^}AJ;dEpK3{e)a$r5zH{<>K5f)<bu41T+{ zsdWRQZY%P;pD|QJDg6&5oKy)?3W4HOFe$5zF8&!DROT}UH{y7H54yYM2bja!`3lJ6 zM2>!tSP-$=fgaO%%^SC;l|d7_{_kHJ`v7kZYIG%by~BGoTvdETO$ezXcwokXhD*In z{ncfu^(zpOZwoRl3$L@$ngP!b?z0cz<Tuby5IQvezV{WWcwn<5f~1=C+8FtG<qI}s zF|Ie5ja6U{$5XX+bkMy>soQ^5pmTBKR4+2L&kNktw&x6h$_X477a=|uKztH?q+J=% zI3IAn!0;RxIT47MX*X$dC{$Ja)<enQUDS19STqTb{nD3wXPcB+OpK2@_sq`^Cjne0 zNJ<5q92@c}SIv4-y56GMX(y3ZCjNVN`imapQd2bcQ?A&)VKjXClwf?e7i-Dxsw_0q z^+kY&9kd_){C3-r-d`Wk5=TFW<?-digRdg-&wXOozg;a8YrW_BWC6VQNljnUvrKJS z3^sZ!BSqV{h^wK6g4p!<SjfjS=yIApII?}kMKU$H<6%x{?a;i-s3+Qw&Ztohj^Opi z{t`W@BK`qA#MXfO!-nT8rS>=uyQiSCiUIP|Rd%NL!Z&6&ziM%+&dI3d$VNF~Hr*Qr zIh8jD5cjKj2V~a>Me+BcKf#1$wZ4utps^x1+P@n8w@c*=(Z*FfN2?0_FDK^z1~K%# zqW{Z_8C3x`r%^8WH0j?CH^S|P{XZ{Fz&|PqDa-k<YtSO>);}Sx|8Sb9;U0)E!ycab z?SBmqR|D)bTH&f4qW|mQ|I5t>PTZSVk2s`l#{aqoh@Ms9{eoN9|F4&Z2(v8!NA0s8 zRA2nRt|9#%TqE)kTa(Ox&;l^XCWCs~-oyWyjz|nRfcU^j8~Ha?cRhM8pUPq4KQ>D7 zmOpP-;v;}`qo6=#u2m0WLSWQz5v4cn+6@0p3en>WU=mgVk)cqGDo5e@z6J=n^BvOC zp;&OhxWL424y4?-u6Cy?b3je7xpx5XW;KKUduKwAyylz)W-Q}Gja}DPs)xmrDqFAm zGq;uiqo@Gl6s#2tjDXn5#v<jRI~ZNh_EQC7tBZDzf87=rxxx{eU?BpAGx^vX!0;7N zo>H}#3SjX3sswy)n+j&Q^*~Br&fN*))T*Abt4wayA?P1B;8ee`)-P^5lB*tut@lyn zpXe(tSTksN4AK8~aT(#jDU<g--OA4cwY@f!`-?0clY{|TzRPbxZwVyw|BAxM=N2G* z<M&T0pZ@Fpz@botpGf-L%Q3`wQ*Cdix=;k5d@m``9#g`is{oMS)c-c!%_-oOZKK^B z=iI*sb<0rep6fhVj3pQ72mLnb%8lw%KsfC(1w>w%fuE89kf0LiQmVOlrfF)*fglrG zi4=R%ar^uGJu*NUPHW(nz7NMHpDZz0jufl2pJ1_;v8s9C50nQbm7L7X#X3gb-2bc# zm^ak+ieDs!?Jc-JCK^H+4(N}^7gL~7vmWPO>$UUdTz%!Ofd9p-tUKV2%00v)$$bz5 zH17j|Jz8me#QFRF?!0YvL<(oZC)Z=K+(^J~vH9Ch^YKtf%VnuvrI*QHQFzGnEeBvb z%rh`eH$Z{bAUFpG<b6VxlY3yg>{Z*{DW{(B*|}dAFx!7XCA8f7Kg58IrUnT%Be${{ z!k$~7%UOSWgGSkjz-5sJahw~DWK>G;cAen_Im+T=gxm9VSnS$X)}+Y`bTfvdQZlKB zza!SIFlL@Ic8}F9>PZ8sBdQ^;!CyT<vgS(IW7T*e_q7dLO1~X$y#<ma>NzHX`B$N= z`yg-T58u<gQLdcKW13%I(g#Q<(D}o`)VKi-2Jah<bp+UCopiyev*5s*mC@DF>07$L zd;M)CQE5kTAKCOuRpd|_5g2Pxxbg=bzukbZ>tL}A(p=sHH=dJW3G5pyVD!0dw7;~h z0z01SxA#r1^>U3owfzsFX_e-(<MS|x3oIzpC;pwzLl;C<nOZ(tCO$tDC@UK3MQAVz zrjq{dtA}NGg4^)oi42!kgNoKG`<MI@2B4-a95(ekFHS7+?)JKA)D=Oj_Jd=T8Tb7S zqz9{i9E53V0xx^^eb%!W^=Tww&#BcVHeNj(zXbys06=tS1E_SD#D-2#%5sHB8SOcH zvO#PTL`XjXqtVDPcm${*o+u>Ku=SrA>vIfcVleqgV&I#w0FuVXoXBxiXf4h1h4S7D zLZs5iTmezL+GyU$z0n7N8DSCiJ*gT9ix1{JmbfE}KO9x!Ouo4pCo06mz}OMi6iNeN z+?*c5O3skW#v~?SI|2g>KK~8$^Uq8nE!lTZm~m4;8m{tLn%RZN0S4KS^2RmDU|Ipt z;g#$Fpp#kJ?r-;ZuQJ~*Bf~q$xhj?~0lPk@Fs-^y$WOf@_yD_%?qkIj7NQj9Jit}0 zIt+%phb@r_2)i3^1I+EH2vQjkPUQxo-~6SzM=Qgf^T9_a&)|0&ow8(|q`EsmEq_`C zP8T}>JKqHzbfB7qJT&dk@jp_y&L=cmpovK%mTPV|13?5(oVap&w{wzxpQRi4R2)+# zud^1zPiGw}`wU)YS!1%Fy+MDZNvNvqI!(Jq@Qhlp<?d?RcLK?W+T6UhyQ<?7yg?RV z;3}ADZRYS>ONfbxFzVQW#6|h}`!1HwPcqRv4vT@;PVBEp>qdSGf(YIVXcQuVmm%15 z_H3mi3ay8RlXIA38+0}HKqsGm_|ijKnV~FAu*<cVg7LKco*NNTG*f|`z_|o&Ai9}V zvwyL0JxCG9NA3`MdojSrz?MrV1kdh43-cB3nJu0^3^nYI{ASvsZ)C5es%$E~^L2ou z;-){-R=IU^tgz`QHx_90>W`UQ@b#_$0m^>by{OvT0bt>Ne<+W0^P#L>Ho$;g$%ViO zS9oMH9T!xHFv*qQO<x8AIc=K9=_lvH43t`o-~EMk;^}m^rMle4n?>s&Z_RZz{h6Jn zayF<E);W|H22b<IzkX5ZhcnKS#ES7Z+V|&D*6T&PLe}5C_JFU;3K!}Bm6esf10OAR zP5!8>4&l^!bY<+L(xiE*<I4<R%?JZp*?!HCf>I7^8de+C^qUKvD@yPv1QopLz5lF+ zXW%R;Y7+iu5<W{V13u+wfi}!ZV<hj@!wZ&R=Mdftr?`+QJIB+GsPN-$v5L@jn{_?k z?^z%ZD}?jPlj6NOfz|_E>*hve!0%?UQq@IE6w>~XB)<B4vK<^9D~|C}Vu+B?#i&XX zMdmseL>zY%JGUNss42JWvXrsVz}jpkN^}?$a?2jIBsk)5HXnq*`WC*mV6Az7%=nX~ zHM6K!2fzh2FF2-t47ysBB6etG@Kt|lx!@%s&TXhPvXPGYYA>hY`E`bepj?;PC-aIo z?SHTX*Ssxgi8zlW6h{|%UR8)mUCQ*v^6t9X9AT&pJ#&v~JUF7Hb1c$<I`vPj^j79v z8m}vTt!J--J=iwwdx+)~bU9!qT~52HL`@<Y3_oSvCt~qFQ|%oPtjjj>Sxs&=38Ckz z?B-sIX_I+TO75YW8MQo37S682x1dQ}DOQjGz(Oz;AVCAQNkIG-*8ozL2+a!p@UVGh zN+!4hIV1;$dooH+Ks7G59^KSuxy84>Xx4V-eGJXIE?-V-4h)g`L~QP2q`50jFnP#> zlk|<D-I%is-ocWFZY$TQyeKJ%`5~uxBd!?;1bk%%?V?D8$&wh=Qa+GjaQOqL0leK} z;3y?vu&)8d$`2pNp=sn{?IQVm)8I-wBNwsb5cKunMWg|h#VY3o;ndMO0gCm-R9Ep1 zNUO-72l{Sq4^OC!-u*H7z;l^JRM+gp?W1{lT4xQwtZTjfWiod6Rfcn;!gC~P;W|<Y zi>2cDpznBc@*rpQmSZ?d(6KKRCl;hMPB`y_bd&<Z?@6Qr*R=oW3SnpfID{c3$ozxz z(3Y)9-dzV?{6-~5dlzdOOtC4Xt~fo~8sJBP34g%gmUYK=Ah|Q4a^QS@NKmZSVw7f{ zLVQL2%Fz~5Cfki^N=2<tVbB)X5-5Sw_{fJEjf7QG;!-m<;;~dAAGae;<N2bW2`k|c zPr}}9R9rIqMiV04Qkd2B$M4WC(jmdWSnGDW6kRbqx?Gv1ipysp$g5P~oiogm3-r73 zuyXXzHlJH2C%zydpmQWY@_sZ+-KKd?%WKTXgWtuD2YF|$c8WCejMbahULQixtzV_t zzxm7GEa>|NM-RCz>ttt!m%-40CJ`L=ntoHV>9$hM!4v4sWx^-~O<7Ts4A^4w%Z^pA z_ZMeR%HHB^6SLwjPUIotC79&0-^eq6mqJwU-+Qtym3(B{!&3hvfIPRNuEzhcOw&TA zr??k|;%N-8ht{I+Hv1HnE({@Rl+UdIbV^<YdbK~mTbZ;-IRxJDUQAI)YlV~=5@+|p zPdJjyOD0BgWGfKq8#`R1V&VqS@~`iMj_;xe?I<DQFWV>SDk(#G0}hruLYxeS*d-5s zbD6gzJtwb|N%xvg$VRcY(R;6;Hy8JCHtws1D8^h{l_;j^uP+}oQa`%>?Fp%ip%k6n z6PSJHq;Vl7tjiK3S@T+_r^X4?vIiB2{AR>}v)t{_-EW+_*|vdGHzkAuWv)E1ALR~| zc*LPXiI7?VPYLl9bx<Esgmo4~Gv6Kor$1?4A)Ip`z}$%-?~ds6kT`ao122mG{Bv;J zOgwr(q0{^1&()lB6FbAAbbB#n<`O+d|I2VMB0&B<*VFYTiufz)y;$KO(WQ-b++I}x z?dT+5PG3MHTYR?v?X_pu=PnGwe+*$f0Ez$sQ7WZKg9Fn7YEGmhG~-^|zfV7r+~FP~ zdN;(g97Lnhu5<|yPL0q6a2J(bggT?EcwxEIK(w<8GOSVnxSve_92WruH6S94yQ;13 z0_W~jXbZeOsiSH3V0_Bdek^#lB_((X7;Vp)5la#tt4Ks6?$H*%*YIAqm$m>z9&1x| ztwa4C+Qm_Ho!?6dPeqGDi8o4jKz_5YL)vRr{5nP<p-#tg0hplMnnYvHVy|6c7DL1n zw@A~~;C0VRm&f`}oh9M!4|<J=>nbGBpBS|%lRUFk&o!`2VjMI}Gdw#ZK4xb!PwvlH zVvbKqN$L5Fn*8R%YR#>AJ6#rGMEY=lXek{Olbfm)Sgj#E24wsZz|K<`r7!0`;!N|l zQ<mA70g9kAgO4J?O*e|m-Q(Y66n$`Uv{PiIsv1MSQg2+ed@tlNo~{UM{1_S23KOD) z$O%JE%qGhW^4OIn+E1!CR;M@w>$@-#(MQS;g~^`T_1#Ifb$=7ZockH0!-1why_ftJ zxzq_)OeGi>RSJorT@UN#J=Z@jSP69W*h;=Oc~A{8SOaAwR&;OD^AFA{bxJB3{De0X z{IGAcrRFAMJYNj|)C+5j9of56=)SnowfvKeUTUmfBY>RJq$+l4<xV!cKbX$@AP7xA zxnJADa<xC1$Mw(mk*l8}h;7vlY^jC(LFzw#F7+sM(fcp<tt7UCihe+QR3y6k4vthV z@9N>dzBeZahCdS>alpbLLJ~-g6oCbSAQHg(w<i|!O$Wf8F3+(}h&IM64+`?H{lURG zA*LTPo3Jxkle<j{o+Q2r*vOT=>FR$X+VNV@W|pYw#fPi@X=6@+gk@suoGl<ywA5sR zHcIzI2VkUfvm*8h9Ubh!VOS&xpnxIsBq2Sy5km2|S&r+-LAnWr>7gJCGgf7HmuuaX z0mUO2ngt$krim0%q!9n}zn^8=b~SU3C;#|||KWV2MFU`5CI9uwf6)lkfZ@U*|Nnpe hpYh@UkLLt_j}yFZDvC?Y9)|?}D9ETvS4f(N{2%F9pH=_> literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN010.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN010.png new file mode 100644 index 0000000000000000000000000000000000000000..8580ad42ee9b03841d544db2f2b8ad021df3d432 GIT binary patch literal 37988 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 MCf0}sBhSSD0X5?Q{Qv*} literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN011.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN011.png new file mode 100644 index 0000000000000000000000000000000000000000..168a9e632df7bc519000ea3f924f0364d1217bba GIT binary patch literal 30537 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 HHw^lJg=q4O literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN012.png b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/media/NoiseN012.png new file mode 100644 index 0000000000000000000000000000000000000000..5da7c52d87004e36829141513fdc7f90514e2c28 GIT binary patch literal 297781 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/references.bib b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/references.bib new file mode 100644 index 000000000..d710ca837 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/references.bib @@ -0,0 +1,183 @@ +@article{Amiet:1975, + author= {Roy K. Amiet}, + title= {Acoustic Radiation from an Airfoil in a Turbulent Stream}, + journal= {Journal of Sound and Vibration}, + volume= {41}, + number= {4}, + pages= {407–420}, + year= {1975}, + doi= {10.1016/S0022-460X(75)80105-2} +} + +@techreport{Bortolotti:2019, + author= {Pietro Bortolotti and Helena Canet Tarres and Katherine Dykes and Karl Merz and Latha Sethuraman and David Verelst and Frederik Zahle}, + year= {2019}, + title= {Systems Engineering in Wind Energy - WP2.1 Reference Wind Turbines}, + institution= {IEA Technical Report}, + URL= {https://www.nrel.gov/docs/fy19osti/73492.pdf} +} + +@techreport{Brooks:1989, + author= {Thomas F. Brooks and D. Stuart Pope and Michael A. Marcolini}, + year= {1989}, + title= {Airfoil Self-Noise and Prediction}, + institution={NASA}, + type= {Reference Publication}, + number= { 1218} +} + +@article{Drela:1987, + author = {Drela, Mark and Giles, Michael B.}, + title = {Viscous-inviscid analysis of transonic and low Reynolds number airfoils}, + journal = {AIAA Journal}, + volume = {25}, + number = {10}, + pages = {1347-1355}, + year = {1987}, + doi = {10.2514/3.9789}, +} + +@inproceedings{Guidati:1997, + author = {Gianfranco Guidati and Rainer Bareiss and Siegfried Wagner and Rene Parchen and Gianfranco Guidati and Rainer Bareiss and Siegfried Wagner and Rene Parchen}, + title = {Simulation and measurement of inflow-turbulence noise on airfoils}, + booktitle = {3rd AIAA/CEAS Aeroacoustics Conference}, + year= {1997}, + doi = {10.2514/6.1997-1698} +} + + +@article{Lowson:1970, + author= {Martin V. Lowson}, + year= {1970}, + title= {Theoretical Analysis of Compressor Noise Evaluation}, + journal= {The Journal of the Acoustical Society of America}, + volume= {47}, + pages= {371–385}, + doi= {10.1121/1.1911508} +} + +@article{Klein:2018, + author= {Levin Klein and Jonas Gude and Florian Wenz and Thorsten Lutz and Ewald Krämer}, + year= {2018}, + title= {Advanced Computational Fluid Dynamics (CFD)–Multi-Body Simulation (MBS) Coupling to Assess Low-Frequency Emissions from Wind Turbines}, + journal= {Wind Energy Science Journal}, + volume= {3}, + pages= {713–728}, + doi= {10.5194/wes-3-713-2018} +} + +@techreport{MoriartyMigliore:2003, + author= {Patrick J. Moriarty and Paul G. Migliore}, + year= {2003}, + title= {Semi-Empirical Aeroacoustic Noise Prediction Code for Wind Turbines}, + address= {Golden, CO}, + institution= {National Renewable Energy Laboratory}, + number= {NREL/TP-500-34478}, + URL= {https://www.nrel.gov/docs/fy04osti/34478.pdf} +} + +@inproceedings{MoriartyGuidatiMigliore:2004, + author = {Patrick Moriarty and Gianfranco Guidati and Paul Migliore}, + title = {Recent Improvement of a Semi-Empirical Aeroacoustic Prediction Code for Wind Turbines}, + booktitle = {10th AIAA/CEAS Aeroacoustics Conference}, + year= {2004}, + doi = {10.2514/6.2004-3041} +} + +@inproceedings{MoriartyGuidatiMigliore:2005, + author = {Patrick Moriarty and Gianfranco Guidati and Paul Migliore}, + title = {Prediction of Turbulent Inflow and Trailing-Edge Noise for Wind Turbines}, + booktitle = {11th AIAA/CEAS Aeroacoustics Conference}, + year = {2005}, + doi = {10.2514/6.2005-2881} +} + +@techreport{MoriartyHansen:2005, + author= {Patrick J. Moriarty and A. C. Hansen}, + year= {2005}, + title= {AeroDyn Theory Manual}, + address= {Golden, CO}, + institution= {National Renewable Energy Laboratory}, + number= {NREL/TP-500-36881}, + URL= {https://www.nrel.gov/docs/fy05osti/36881.pdf} +} + +@techreport{Moriarty:2005, + author= { Patrick J. Moriarty}, + year= {2005}, + title= {NAFNoise User's Guide}, + address= {Golden, CO}, + institution= {National Renewable Energy Laboratory}, + URL= {https://github.com/NREL/NAFNoise/blob/master/NAFNoise.pdf} +} + +@misc{xfoil:699, + author= {Mark Drela}, + title= {{XF}oil, release 6.99}, + url= {https://web.mit.edu/drela/Public/web/xfoil/} +} + +@misc{openfast:2019, + title= {Open{FAST}, dev branch}, + year= {2019}, + publisher= {GitHub}, + journal= {GitHub repository}, + url= {https://github.com/OpenFAST/openfast} +} + +@techreport{Parchen:1998, + author= {René R. Parchen}, + year= {1998}, + title= {Progress Report {DRAW}: A Prediction Scheme for Trailing Edge Noise Based on Detailed Boundary Layer Characteristics}, + institution= {TNO Institute of Applied Physics} +} + + +@inproceedings{Paterson:1976, + author = {R. Paterson and R. Amiet}, + title = {Acoustic radiation and surface pressure characteristics of an airfoil due to incident turbulence}, + booktitle = {3rd Aeroacoustics Conference}, + year= {1976}, + chapter = {}, + pages = {}, + publisher= {AIAA}, + doi = {10.2514/6.1976-571} +} + +@article{Sucameli:2018, + doi = {10.1088/1742-6596/1037/2/022038}, + year = 2018, + month = {jun}, + publisher = {{IOP} Publishing}, + volume = {1037}, + pages = {022038}, + author = {CR Sucameli and P Bortolotti and A Croce and CL Bottasso}, + title = {Comparison of some wind turbine noise emission models coupled to {BEM} aerodynamics}, + journal = {Journal of Physics: Conference Series}, + abstract = {Noise is an important design driver for onshore wind turbines. Therefore, there is a need to include validated noise prediction models within wind turbine and wind plant design procedures. However, the literature presents a multitude of different models and formulations, combined with a severe lack of publicly available experimental data. The present work presents a comparison between semi-empirical frequency-domain methods coupled to blade element momentum (BEM) aerodynamics, which is the typical approach used for the transient aeroelastic analysis of wind turbines. Among the various noise sources, only turbulent boundary layer – trailing edge and turbulent inflow noise models have been considered in the present analysis. The noise models are benchmarked in terms of emission spectra, highlighting differences and discrepancies. A time-domain Ffowcs Williams-Hawkings formulation is also coupled to the same BEM model, investigating its ability in predicting low frequency emissions. Thanks to this study, a few inconsistencies among published noise models are identified and reported.} +} + + +@techreport{Viterna:1981, + author= {Larry A. Viterna}, + year= {1981}, + title= {Method for Predicting Impulsive Noise Generated by Wind Turbine Rotors}, + number= {DOE/NASA/20320-36}, + institution= {}, + URL= {https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19820013840.pdf} +} + + + +@article{Zhu:2005, + author= {Wei J. Zhu and Nicolai Heilskov and Wen Zhong Shen}, + year= {2005}, + title= {Modeling of Aerodynamically Generated Noise From Wind Turbines}, + journal= {Journal of Solar Energy Engineering}, + volume= {127}, + number= {4}, + pages= {517-528}, + doi= {10.1115/1.2035700} +} + + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/refs.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/refs.rst new file mode 100644 index 000000000..06850d67d --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/refs.rst @@ -0,0 +1,10 @@ +.. only:: html + + References + ---------- + +.. bibliography:: references.bib + :labelprefix: aa- + :keyprefix: aa- + + diff --git a/OpenFAST/docs/source/user/aerodyn-aeroacoustics/symbols.rst b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/symbols.rst new file mode 100644 index 000000000..794b2ab97 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-aeroacoustics/symbols.rst @@ -0,0 +1,95 @@ +.. _AA-symbols: + +List of Symbols +--------------- + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{l}` + low frequency + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{h}` + high frequency + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{p}` + airfoil pressure side + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{s}` + airfoil suction side + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{t}` + turbulence + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{0}` + reference + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{1}` + parallel to airfoil chord + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{2}` + normal to airfoil chord + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{}_{3}` + blade spanwise direction + + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\alpha` + angle of attack + [rad] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\beta^{2}` + Prandtl-Glauert correction factor + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\delta` + airfoil boundary layer thickness + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\delta^{*}` + airfoil boundary layer displacement thickness + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\theta` + airfoil boundary layer momentum thickness + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\Theta_{e},\ \Phi_{e}` + angles between emitter and observer + [rad] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\rho` + air density + [kg/m\ :sup:`3`] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\omega` + radial frequency + [rad/s] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`A_{w}` + A-weight + [dB] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`c` + speed of sound + [m/s] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`c_{i}` + chord at blade spanwise position i + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`d` + blade span at station i + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\overline{D}` + directivity function + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`f` + frequency + [Hz] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`G` + empirical function + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`h` + height of the trailing edge thickness + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`H` + airfoil kinematic shape factor + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`I` + turbulence intensity + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`k` + wave number + [m\ :sup:`-1`] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\overline{k},\ \widehat{k}` + nondimensional wave number + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`{\mathrm{\Delta}K_{1},\ K}_{1}`,\ :math:`\ K_{2}` + empirical parameters of the BPM model + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`l` + spanwise extent of the separation zone from blade tip + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`L` + lift force + [N] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`L_{t}` + length scale + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`M` + Mach number + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`M_{c}` + Mach number past the trailing edge + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`r_{e}` + effective observer distance + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\text{Re}` + Reynolds number + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`S^{2}` + Sears function + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`\text{St}` + Strouhal number + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`t_{x}` + relative thickness of the airfoil at chordwise position x + [-] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`U` + local inflow velocity + [m/s] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`y` + blade spanwise position + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`z` + height above the ground + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ ++ :math:`z_{0}` + ground surface roughness + [m] + ++-----------------------------------------------------------+------------------------------------------------------------+-------------------+ + diff --git a/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat b/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat new file mode 100644 index 000000000..e2d414dda --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat @@ -0,0 +1,11 @@ +Example Time-Series Input File for UnsteadyAero Driver + + +This file has 8 header lines followed by three columns of data: + + +Time Angle of Attack VRel omega +(s) (deg) (m/s) (rad/s^2) +0.0 0 10 0 +0.01 0 10 0 +0.02 0 10 0 diff --git a/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.inp b/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.inp new file mode 100644 index 000000000..1bef7307a --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.inp @@ -0,0 +1,25 @@ +UnsteadyAero Driver file for Unit NACA. k = 0.077 +------------------------------------------------------------------------------- +FALSE Echo - Echo the input file data (flag) +---------------------- ENVIRONMENTAL CONDITIONS ------------------------------- + 340.29 SpdSound - Speed of sound (m/s) +---------------------- UNSTEADYAERO ------------------------------------------- +"05014051_NACA" OutRootName - The name which prefixes all UnsteadyAero generated files (quoted string) + 40.36 InflowVel - Inflow velocity (m/s) + 1.48 Re - Reynolds number in millions (-) + 3 UAMod - Unsteady Aero Model Switch: 2 - Gonzalez’s variant (changes in Cn,Cc,Cm); 3 - Minnema/Pierce variant (changes in Cc and Cm) +TRUE Flookup – Flag to indicate whether a lookup for f’ will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files +------------------- AIRFOIL PROPERTIES ---------------------------------------- +"05000051_AD15.dat" AirFoil - Airfoil table + 0.55 Chord - Chord length (m) +TRUE UseCm - Use Cm data in airfoil table +------------------- SIMULATION CONTROL ---------------------------------------- + 1 SimMod - Simulation model [ 1 - use reduced frequency model, 2 - use time series data stored in the TimeInputs file and ignore the remaining parameters ] + 3 NCycles - Number of angle-of-attack oscillations (cosine function) over the length of the simulation (-) + 720 StepsPerCycle - Number of timesteps per cycle (-) + 1.8 Frequency - Frequency for the airfoil oscillations (Hz) + 9.685 Amplitude - Amplitude of the oscillations (deg) + 15.195 Mean - Cycle mean (deg) + -180 Phase - Initial phase (num steps) +"UA-driver-timeseries.dat" InputsFile - Time series data in an ASCII input file (whitespace-separated data). 8 header lines, followed by column data. First column is time (sec), second column is angle-of-attack (deg), third column is InflowVel (m/s) +"END" of driver input file diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Acknowledgments.txt b/OpenFAST/docs/source/user/aerodyn-olaf/Acknowledgments.txt new file mode 100644 index 000000000..365650610 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/Acknowledgments.txt @@ -0,0 +1,19 @@ +.. _Acknowledgments: + +Acknowledgments +=============== + +This work was authored by the National Renewable Energy Laboratory, +operated by Alliance for Sustainable Energy, LLC, for the U.S. +Department of Energy (DOE) under Contract No. DE-AC36-08GO28308. Funding +provided by the U.S. Department of Energy Office of Energy Efficiency +and Renewable Energy Wind Energy Technologies Office. The views +expressed in the article do not necessarily represent the views of the +DOE or the U.S. Government. The U.S. Government retains and the +publisher, by accepting the article for publication, acknowledges that +the U.S. Government retains a nonexclusive, paid-up, irrevocable, +worldwide license to publish or reproduce the published form of this +work, or allow others to do so, for U.S. Government purposes. + +The authors are also grateful to the Big Adaptive Rotor program for +supporting the development of this software. diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Acronyms.rst b/OpenFAST/docs/source/user/aerodyn-olaf/Acronyms.rst new file mode 100644 index 000000000..fb0d492fa --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/Acronyms.rst @@ -0,0 +1,52 @@ +.. _Acronyms: + +List of Symbols +=============== + ++-----------------------------+---------------------------------------+ +| BEM | blade-element momentum | ++-----------------------------+---------------------------------------+ +| CFD | computational fluid dynamics | ++-----------------------------+---------------------------------------+ +| DOE | U.S. Department of Energy | ++-----------------------------+---------------------------------------+ +| :math:`F_v` | core radius factor | ++-----------------------------+---------------------------------------+ +| :math:`t` | time | ++-----------------------------+---------------------------------------+ +| FVW | free vortex wake | ++-----------------------------+---------------------------------------+ +| :math:`N` | number of rotor revolutions before | +| | wake cutoff condition | ++-----------------------------+---------------------------------------+ +| :math:`\vec{r}` | vector between point of interest and | +| | vortex segment | ++-----------------------------+---------------------------------------+ +| :math:`\vec{r}(\psi,\zeta)` | position vector of Lagrangian markers | ++-----------------------------+---------------------------------------+ +| :math:`r_c` | core radius | ++-----------------------------+---------------------------------------+ +| :math:`r_{c0}` | initial core radius | ++-----------------------------+---------------------------------------+ +| OLAF | cOnvecting LAgrangian Filaments | ++-----------------------------+---------------------------------------+ +| :math:`\alpha` | numerical constant :math:`=1.25643` | ++-----------------------------+---------------------------------------+ +| :math:`\Gamma` | circulation strength | ++-----------------------------+---------------------------------------+ +| :math:`\delta` | measure of viscous diffusion | ++-----------------------------+---------------------------------------+ +| :math:`\epsilon` | measure of strain | ++-----------------------------+---------------------------------------+ +| :math:`\Delta \psi` | step size for blade rotation | ++-----------------------------+---------------------------------------+ +| :math:`\Omega` | rotational speed of wind turbine | ++-----------------------------+---------------------------------------+ +| :math:`\zeta` | vortex wake age | ++-----------------------------+---------------------------------------+ +| :math:`\zeta_0` | vortex wake age offset | ++-----------------------------+---------------------------------------+ +| :math:`\nu` | kinematic viscosity | ++-----------------------------+---------------------------------------+ +| :math:`\psi` | azimuth blade position | ++-----------------------------+---------------------------------------+ diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/AppendixA.rst b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixA.rst new file mode 100644 index 000000000..a350de151 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixA.rst @@ -0,0 +1,14 @@ +.. _OLAF-Primary-Input-File: + +Appendix A: OLAF Primary Input File +=================================== + + +**Check the regression test cases for updates to this input file.** + +.. container:: + :name: Tab:OLAFinputfile + + .. literalinclude:: ExampleFiles/ExampleFile--OLAF.txt + :linenos: + :language: none diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/AppendixB.rst b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixB.rst new file mode 100644 index 000000000..952d75c57 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixB.rst @@ -0,0 +1,13 @@ +.. _Prescribed-Circulation-Input-File: + +Appendix B: Prescribed Circulation Input File +============================================= + +**Check the regression tests for updated versions of this file.** + +.. container:: + :name: TabPrescribeCirc + + .. literalinclude:: ExampleFiles/ExampleFile--PrescribeCirc.txt + :linenos: + :language: none diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/AppendixC.rst b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixC.rst new file mode 100644 index 000000000..66613d90b --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/AppendixC.rst @@ -0,0 +1,35 @@ +.. _OLAF-List-of-Output-Channels: + +Appendix C: OLAF List of Output Channels +======================================== + +This is a list of all possible output parameters from the OLAF module. +The names are grouped by meaning, but can be ordered in the OUTPUTS +section of the *AeroDyn15* primary input file, as the user sees fit. +:math:`N\beta` refers to output node, :math:`\beta`, where :math:`\beta` +is a number in the range [1,9], corresponding to entry, :math:`\beta`, +in the **OutNd** list. :math:`B\alpha` is prefixed to each output name, +where :math:`\alpha` is a number in the range [1,3], corresponding to +the blade number. + + +.. list-table:: Available OLAF Output Channels + :widths: 25 15 50 + :header-rows: 1 + :align: center + :name: Tab:OLAFoutputs + + * - Channel Name(s) + - Units + - Description + * - :math:`B \alpha N \beta Gam` + - :math:`m^2/s` + - Circulation along the blade + + +.. + ============================ ============= =========================== + Channel Name(s) Units Description + ============================ ============= =========================== + :math:`B \alpha N \beta Gam` :math:`m^2/s` Circulation along the blade + ============================ ============= =========================== diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--OLAF.txt b/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--OLAF.txt new file mode 100644 index 000000000..e0d341697 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--OLAF.txt @@ -0,0 +1,42 @@ +--------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE ----------------- +Free wake input file for the Helix test case +--------------------------- GENERAL OPTIONS --------------------------------------------------- +5 IntMethod Integration method {5: Forward Euler 1st order, default: 5} (switch) +0.2 DTfvw Time interval for wake propagation. {default: dtaero} (s) +5 FreeWakeStart Time when wake is free. (-) value = always free. {default: 0.0} (s) +2.0 FullCircStart Time at which full circulation is reached. {default: 0.0} (s) +--------------------------- CIRCULATION SPECIFICATIONS ---------------------------------------- +1 CircSolvingMethod Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch) +0.01 CircSolvConvCrit Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-) +0.1 CircSolvRelaxation Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-) +30 CircSolvMaxIter Maximum number of iterations for circulation solving {default: 30} (-) + "NA" PrescribedCircFile File containing prescribed circulation [only if CircSolvingMethod=3] (quoted string) +=============================================================================================== +--------------------------- WAKE OPTIONS ------------------------------------------------------ +------------------- WAKE EXTENT AND DISCRETIZATION -------------------------------------------- +50 nNWPanel Number of near-wake panels [integer] (-) +400 WakeLength Total wake distance [integer] (number of time steps) +default FreeWakeLength Wake length that is free [integer] (number of time steps) {default: WakeLength} +False FWShedVorticity Include shed vorticity in the far wake {default: false} +------------------- WAKE REGULARIZATIONS AND DIFFUSION ----------------------------------------- +0 DiffusionMethod Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0} +0 RegDeterMethod Method to determine the regularization parameters {0: Manual, 1: Optimized, default: 0 } +2 RegFunction Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch) +0 WakeRegMethod Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 1} (switch) +2.0 WakeRegFactor Wake regularization factor (m) +2.0 WingRegFactor Wing regularization factor (m) +100 CoreSpreadEddyVisc Eddy viscosity in core spreading methods, typical values 1-1000 +------------------- WAKE TREATMENT OPTIONS --------------------------------------------------- +False TwrShadowOnWake Include tower flow disturbance effects on wake convection {default:false} [only if TwrPotent or TwrShadow] +0 ShearModel Shear Model {0: No treatment, 1: Mirrored vorticity, default: 0} +------------------- SPEEDUP OPTIONS ----------------------------------------------------------- +2 VelocityMethod Method to determine the velocity {1:Biot-Savart Segment, 2:Particle tree, default: 1} +1.5 TreeBranchFactor Branch radius fraction above which a multipole calculation is used {default: 2.0} [only if VelocityMethod=2] +1 PartPerSegment Number of particles per segment [only if VelocityMethod=2] +=============================================================================================== +--------------------------- OUTPUT OPTIONS --------------------------------------------------- +1 WrVTk Outputs Visualization Toolkit (VTK) (independent of .fst option) {0: NoVTK, 1: Write VTK at each time step} (flag) +1 nVTKBlades Number of blades for which VTK files are exported {0: No VTK per blade, n: VTK for blade 1 to n} (-) +2 VTKCoord Coordinate system used for VTK export. {1: Global, 2: Hub, "default": 1} +1 VTK_fps Frame rate for VTK output (frames per second) {"all" for all glue code timesteps, "default" for all OLAF timesteps} [used only if WrVTK=1] +------------------------------------------------------------------------------------------------ diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--PrescribeCirc.txt b/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--PrescribeCirc.txt new file mode 100644 index 000000000..b174db2ca --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/ExampleFiles/ExampleFile--PrescribeCirc.txt @@ -0,0 +1,26 @@ +r/R [-], Gamma [m^2/s] +0.048488, 0.000000 +0.087326, 0.442312 +0.126163, 6.909277 +0.165000, 23.678557 +0.203837, 55.650700 +0.242674, 74.091529 +0.281512, 84.205843 +0.320349, 88.740429 +0.359186, 89.730814 +0.398023, 88.568114 +0.436860, 87.114743 +0.475698, 86.110557 +0.514535, 85.705529 +0.553372, 85.215829 +0.592209, 84.547371 +0.631047, 83.774329 +0.669884, 82.889157 +0.708721, 81.635600 +0.747558, 79.788700 +0.786395, 77.195200 +0.825233, 73.765100 +0.864070, 69.275900 +0.902907, 62.965400 +0.941744, 53.603300 +0.980581, 39.854000 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/FutureWork.rst b/OpenFAST/docs/source/user/aerodyn-olaf/FutureWork.rst new file mode 100644 index 000000000..f75531757 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/FutureWork.rst @@ -0,0 +1,31 @@ +.. _Future-Work: + +Future Work +=========== + +This first implementation phase focused on single-turbine capabilities, +fulfilling the basic requirements for the design of large and novel +rotor concepts. Future development work will turn toward the +implementation of features enabling multiple-turbine simulations on +medium-to-large-scale computational clusters. The reduction of the +computational time will also be of focus. This may be achieved using +tree techniques such as the fast multipole method. Further algorithmic +options, such as vortex amalgamation in the far wake, will be considered +to speed up the simulation. The framework presented in this manual is +compatible with grid-free or grid-based vortex particle formulations. +Such particle-based implementations will also be envisaged in the +future. Further validation of the code against measurements and +higher-order tools will be pursued. Applications to cases known to be +challenging for the BEM algorithm will also be investigated, such as +highly flexible rotors, offshore floating turbines, small-scale wind +farms, multiple-rotor turbines, or kites. + +The following list contains future work on OLAF software: + +- Lagrangian particles + +- Multiple turbines, integration into FAST.Farm + +- Code speed-up + +- Dedicated dynamic stall model diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/InputFiles.rst b/OpenFAST/docs/source/user/aerodyn-olaf/InputFiles.rst new file mode 100644 index 000000000..16de76bff --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/InputFiles.rst @@ -0,0 +1,239 @@ +.. _OLAF-Input-Files: + +Input Files +=========== + +No lines should be added or removed from the input files, except in tables where +the number of rows is specified. + +Units +----- + +OLAF uses the International System of Units (e.g., kg, m, s, N). Angles are +assumed to be in degrees unless otherwise specified. + +OLAF Primary Input File +----------------------- + +The primary OLAF input file defines general free wake options, circulation model +selection and specification, near- and far-wake length, and wake visualization +options. Each section within the file corresponds to an aspect of the OLAF model. For most parameters, the user may +specify the value "default" (with or without quotes), in which case a default +value, defined below, is used by the program. + +See :numref:`OLAF-Primary-Input-File` for a sample OLAF primary input file. + +General Options +~~~~~~~~~~~~~~~ + +**IntMethod** [switch] specifies which integration method will be used to +convect the Lagrangian markers. There are four options: 1) fourth-order +Runge-Kutta *[1]*, 2) fourth-order Adams-Bashforth *[2]*, 3) fourth-order +Adams-Bashforth-Moulton *[3]*, and 4) first-order forward Euler *[5]*. The +default option is *[5]*. These methods are specified in :numref:`sec:vortconv`. + +**DTfvw** [sec] specifies the time interval at which the module will update the +wake. The time interval must be a multiple of the time step used by +*AeroDyn15*. The blade circulation is updated at each intermediate time +step based on the intermediate blades positions and wind velocities. The default +value is :math:`dt_{aero}`, where :math:`dt_{aero}` is the time step used by +AeroDyn. + +**FreeWakeStart** [sec] specifies at what time the wake evolution is classified +as “free." Before this point is reached, the Lagrangian markers are simply +convected with the freestream velocity. After this point, induced velocities are +computed and affect the marker convection. If a time less than or equal to zero +is given, the wake is “free" from the beginning of the simulation. The default +value is :math:`0`. + +**FullCircStart** [sec] specifies at what time the blade circulation reaches its +full strength. If this value is specified to be :math:`>0`, the circulation is +multiplied by a factor of :math:`0` at :math:`t=0` and linearly increasing to a +factor of :math:`1` for :math:`t>\textit{FullCircStart}`. The default +value is :math:`0`. + +Circulation Specifications +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**CircSolvMethod** [switch] specifies which circulation method is used. There +are three options: 1) :math:`C_l`-based iterative procedure *[1]*, 2) no-flow +through *[2]*, and 3) prescribed *[3]*. The default option is *[1]*. These +methods are described in :numref:`sec:circ`. + +**CircSolvConvCrit** [-] specifies the dimensionless convergence criteria used +for solving the circulation. This variable is only used if +*CircSolvMethod* = *[1]*. The default value is +:math:`0.001`, corresponding to :math:`0.1\%` error in the circulation between +two iterations. + +**CircSolvRelaxation** [-] specifies the relaxation factor used to solve the +circulation. This variable is only used if *CircSolvMethod* = +*[1]*. The default value is :math:`0.1`. + +**CircSolvMaxIter** [-] specifies the maximum number of iterations used to solve +the circulation. This variable is only used if *CircSolvMethod* = *[1]*. The +default value is :math:`30`. + +**PrescribedCircFile** [quoted string] specifies the file containing the +prescribed blade circulation. This option is only used if *CircSolvMethod* = +*[3]*. The circulation file format is a delimited file with one header line and +two columns. The first column is the dimensionless radial position [r/R]; the +second column is the bound circulation value in [m\ :math:`^2`/s]. The radial +positions do not need to match the AeroDyn node locations. A sample prescribed +circulation file is given in :numref:`Prescribed-Circulation-Input-File`. + + +Wake Extent and Discretization Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**nNWPanel** [-] specifies the number of FVW time steps (**DTfvw**) for which +the near-wake lattice is computed. In the future, this value will be defined as +an azimuthal span in degrees or a downstream distance in rotor diameter. + +**WakeLength** [D] specifies the length, in rotor diameters, of the far wake. +The default value is :math:`8`. [1]_ + +**FreeWakeLength** [D] specifies the length, in rotor diameters, for which the +turbine wake is convected as “free." If *FreeWakeLength* is greater than +*WakeLength*, then the entire wake is free. Otherwise, the Lagrangian markers +located within the buffer zone delimited by *FreeWakeLength* and *WakeLength* +are convected with the average velocity. The default value is :math:`6`. [2]_ + +**FWShedVorticity** [flag] specifies whether shed vorticity is included in the +far wake. The default value is *[False]*, specifying that the far wake consists +only of the trailed vorticity from the root and tip vortices. + +Wake Regularization and Diffusion Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**DiffusionMethod** [switch] specifies which diffusion method is used to account +for viscous diffusion. There are two options: 1) no diffusion *[0]* and 2) the +core-spreading method *[1]*. The default option is *[0]*. + +**RegDetMethod** [switch] specifies which method is used to determine the +regularization parameters. There are two options: 1) manual *[0]* and 2) +optimized *[1]*. The manual option requires the user to specify the parameters +listed in this subsection. The optimized option determines the parameters for +the user. The default option is *[0]*. + +**RegFunction** [switch] specifies the regularization function used to remove +the singularity of the vortex elements, as specified in +:numref:`sec:vortconv`. There are five options: 1) no correction *[0]*, +2) the Rankine method *[1]*, 3) the Lamb-Oseen method *[2]*, 4) the Vatistas +method *[3]*, and 5) the denominator offset method *[4]*. The functions are +given in . The default option is *[3]*. + +**WakeRegMethod** [switch] specifies the method of determining viscous core +radius (i.e., the regularization parameter). There are three options: 1) +constant *[1]*, 2) stretching *[2]*, and 3) age *[3]*. The methods are +described in :numref:`sec:corerad`. The default option is *[1]*. + +**WakeRegParam** [m] specifies the wake regularization parameter, which is the +regularization value used at the initialization of a vortex element. If the +regularization method is “constant”, this value is used throughout the wake. + +**BladeRegParam** [m] specifies the bound vorticity regularization parameter, +which is the regularization value used for the vorticity elements bound to the +blades. + +**CoreSpreadEddyVisc** [-] specifies the eddy viscosity parameter +:math:`\delta`. The parameter is used for the core-spreading method +(*DiffusionMethod* = *[1]*) and the regularization method with age +(*WakeRegMethod* = *[3]*). The variable :math:`\delta` is described in +:numref:`sec:corerad`. The default value is :math:`100`. + +Wake Treatment Options +~~~~~~~~~~~~~~~~~~~~~~ + +**TwrShadowOnWake** [flag] specifies whether the tower potential flow and tower +shadow have an influence on the wake convection. The tower shadow model, when +activated in AeroDyn, always has an influence on the lifting line, hence the +induction and loads on the blade. This option only concerns the wake. The +default option is *[False]*. + +**ShearVorticityModel** [switch] specifies whether shear vorticity is modeled in +addition to the sheared inflow prescribed by *InflowWind*. There are two +options: 1) no treatment *[0]* and 2) mirrored vorticity *[1]*. The mirrored +vorticity accounts for the ground effect. Dedicated options to account for the +shear vorticity will be implemented at a later time. The shear velocity profile +is handled by *InflowWind* irrespective of this input. The default option is +*[0]*. + + +Speedup Options +~~~~~~~~~~~~~~~ + +**VelocityMethod** [switch] specifies the method used to determine the velocity. +There are two options: 1) Biot-Savart law applied to the vortex segments *[1]* +and 2) tree formulation using a particle representation *[2]*. The default +option is *[1]*. + +**TreeBranchFactor** [-] specifies the dimensionless distance, in branch radius, +above which a multipole calculation is used instead of a direct evaluation. This +option is only used in conjunction with the tree code +(*VelocityMethod* = *[2]*). + +**PartPerSegment** [-] specifies the number of particles that are used when a +vortex segment is represented by vortex particles. The default value is +:math:`1`. + +Output Options +~~~~~~~~~~~~~~ + +**WrVTK** [flag] specifies if Visualization Toolkit (VTK) visualization files +are to be written out. *WrVTK* = *[0]* does not write out any VTK files. *WrVTK* += *[1]* outputs a VTK file at every time step. The outputs are written in the +folder, ``vtk_fvw.`` The parameters *WrVTK*, *VTKCoord*, and *VTK_fps* are +independent of the glue code VTK output options. + + +**VTKBlades** [-] specifies how many blade VTK files are to be written out. +*VTKBlades* :math:`= n` outputs VTK files for :math:`n` blades, with :math:`0` +being an acceptable value. The default value is :math:`1`. + +**VTKCoord** [switch] specifies in which coordinate system the VTK files are +written. There are two options: 1) global coordinate system *[1]* and 2) hub +coordinate system *[2]*. The default option is *[1]*. + +**VTK_fps** [:math:`1`/sec] specifies the output frequency of the VTK files. The +provided value is rounded to the nearest allowable multiple of the time step. +The default value is :math:`1/dt_\text{fvw}`. Specifying *VTK_fps* = *[all]*, +is equivalent to using the value :math:`1/dt_\text{aero}`. + +AeroDyn15 Input File +-------------------- +Input file modifications +~~~~~~~~~~~~~~~~~~~~~~~~ + +As OLAF is incorporated into the *AeroDyn15* module, a wake computation option +has been added to the *AeroDyn15* input file and a line has been added. These +additions are as follows. + +**WakeMod** specifies the type of wake model that is used. *WakeMod* = *[3]* has +been added to allow the user to switch from the traditional BEM method to the +OLAF method. + +**FVWFile** [string] specifies the OLAF module file, the path is relative to the +AeroDyn file, unless an absolute path is provided. + + +Relevant sections +~~~~~~~~~~~~~~~~~ +The BEM options (e.g. tip-loss, skew, and dynamic models) are read and discarded +when *WakeMod* = *[3]*. The following sections and parameters remain relevant and +are used by the vortex code: + + - general options (e.g., airfoil and tower modeling); + - environmental conditions; + - dynamic stall model options; + - airfoil and blade information; + - tower aerodynamics; and + - outputs. + +.. [1] + At present, this variable is called nFWPanel and specified as the number of far + wake panels. This will be changed soon. + +.. [2] + At present, this variable is called nFWPanelFree and specified as the number of + free far wake panels. This will be changed soon. diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Introduction.rst b/OpenFAST/docs/source/user/aerodyn-olaf/Introduction.rst new file mode 100644 index 000000000..00fc2b101 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/Introduction.rst @@ -0,0 +1,156 @@ +.. _Introduction: + +Introduction +============ +Over the past few decades, substantial reductions in the cost of wind energy +have come from large increases in rotor size. One important consideration for +such large turbines is increased blade flexibility. In particular, large blade +deflections may lead to a swept area that deviates significantly from the rotor +plane. Such deviations violate assumptions used by common aerodynamic models, +such as the blade element momentum (BEM) method. Such methods rely on +actuator-disk assumptions that are only valid for axisymmetric rotor loads +contained in a plane. Large blade deflections may also cause near wake of the +turbine to diverge from a uniform helical shape. Further, interactions between +turbine blades and the local near wake may increase, thus violating assumptions +of models that do not account for the position and dynamics of the near wake. +Additionally, highly flexible blades will likely cause increased unsteadiness +and three-dimensionality of aerodynamic effects, increasing the importance of +accurate and robust dynamic stall models. There are many other complex wind +turbine situations that violate simple engineering assumptions. Such situations +include obtaining accurate aerodynamic loads for nonstraight blade geometries +(e.g., built-in curvature or sweep); skewed flow caused by yawed inflow or +turbine tilt; and large rotor motion as a result of placing the turbine atop a +compliant offshore floating platform. + +Higher-fidelity aerodynamic models are necessary to account for the increased +complexity of flexible and floating rotors. Although computational fluid +dynamics (CFD) methods are able to capture such features, their computational +cost limits the number of simulations that can be feasibly performed, which is +an important consideration in load analysis for turbine design. FVW methods are +less computationally expensive than CFD methods while modeling similarly complex +physics. As opposed to the BEM methods, FVW methods do not rely on ad-hoc +engineering models to account for dynamic inflow, skewed wake, tip losses, or +ground effects. These effects are inherently part of the model. Numerous +vorticity-based tools have been implemented, ranging from the early treatments +by Rosenhead (:cite:`olaf-Rosenhead31_1`), the formulation of vortex particle methods +by Winckelmans and Leonard (:cite:`olaf-Winckelmans93_1`), to the recent mixed +Eulerian-Lagrangian compressible formulations of +Papadakis (:cite:`olaf-Papadakis14_1`). Examples of long-standing codes that have been +applied in the field of wind energy are GENUVP (:cite:`olaf-Voutsinas06_1`), using +vortex particles methods, and AWSM (:cite:`olaf-Garrel03_1`), using vortex filament +methods. Both tools have successfully been coupled to structural solvers. The +method was extended by Branlard et al. (:cite:`olaf-Branlard15_1`) to consistently use +vortex methods to perform aero-elastic simulations of wind turbines in sheared +and turbulent inflow. Most formulations rely on a lifting-line representation of +the blades, but recently, a viscous-inviscid representation was used in +combination with a structural solver (:cite:`olaf-Miras17_1`). + +cOnvecting LAgrangian Filaments (OLAF) is a free vortex wake (FVW) module used +to compute the aerodynamic forces on moving two- or three-bladed horizontal-axis +wind turbines. This module has been incorporated into the National Renewable +Energy Laboratory physics-based engineering tool, OpenFAST, which solves the +aero-hydro-servo-elastic dynamics of individual wind turbines. OLAF is +incorporated into the OpenFAST module, *AeroDyn15*, as an alternative to the +traditional blade-element momentum (BEM) option, as shown in +Figures :numref:`figOpenFAST_a` and :numref:`figOpenFAST_b`. + +.. _figOpenFAST_a: + +.. figure:: Schematics/OpenFAST.png + :alt: OpenFAST schematic + :width: 100% + :align: center + + OpenFAST schematic + +.. _figOpenFAST_b: + +.. figure:: Schematics/FVWwithOpenFAST.png + :alt: OpenFAST overview schematic and OLAF integration + :width: 100% + :align: center + + OLAF and BEM integration with *AeroDyn15* + +Incorporating the OLAF module within OpenFAST allows for the modeling of +highly flexible turbines along with the aero-hydro-servo-elastic +response capabilities of OpenFAST. The OLAF module follows the +requirements of the OpenFAST modularization framework  +(:cite:`olaf-Sprague15_1,olaf-Jonkman13_1`). + +The OLAF module uses a lifting-line representation of the blades, which +is characterized by a distribution of bound circulation. The spatial and +time variation of the bound circulation results in free vorticity being +emitted in the wake. OLAF solves for the turbine wake in a time-accurate +manner, which allows the vortices to convect, stretch, and diffuse. The +OLAF model is based on a Lagrangian approach, in which the turbine wake +is discretized into Lagrangian markers. There are many methods of +representing the wake with Lagrangian +markers (:cite:`olaf-Branlard17_1`). In this work, a hybrid +lattice/filament method is used, as depicted in +Figure :numref:`Lagrangian`. + +.. figure:: Schematics/LagrangianMarkers.png + :alt: Evolution of near-wake lattice, blade-tip vortex, and Lagrangian markers + :name: Lagrangian + :width: 100% + :align: center + + Evolution of near-wake lattice, blade-tip vortex, and Lagrangian + markers + +Here, the position of the Lagrangian markers is defined in terms of wake +age, :math:`\zeta`, and azimuthal position, :math:`\psi`. A lattice +method is used in the near wake of the blade. The near wake spans over a +user-specified angle or distance for nonrotating cases. Though past +research has indicated that a near-wake region of :math:`30^\circ` is +sufficient (:cite:`olaf-Leishman_book,olaf-Ananthan02_1`), it has been shown that a larger +near wake is required for high thrust and other challenging conditions. After +the near wake region, the wake is assumed to instantaneously roll up into a tip +vortex and a root vortex, which are assumed to be the most dominant features for +the remainder of the wake (:cite:`olaf-Leishman02_1`). Each Lagrangian marker is +connected to adjacent markers by straight-line vortex filaments, approximated to +second-order accuracy (:cite:`olaf-Gupta05_1`). The wake is discretized based on the +spanwise location of the blade sections and a specified time step (:math:`dt`), +which may be different from the time step of AeroDyn. After an optional +initialization period, the wake is allowed to move and distort, thus changing +the wake structure as the markers are convected downstream. To limit +computational expense, the root and tip vortices are truncated after a specified +distance (**WakeLength**) downstream from the turbine. The wake truncation +violates Helmholtz's first law and hence introduces an erroneous boundary +condition. To alleviate this, the wake is "frozen" in a buffer zone between a +specified buffer distance, **FreeWakeLength**, and **WakeLength**. In this +buffer zone, the markers convect at the average ambient velocity. In this way, +truncation error is minimized~(:cite:`olaf-Leishman02_1`). The buffer zone is +typically chosen as the convected distance over one rotor revolution. + +As part of OpenFAST, induced velocities at the lifting line/blade are +transferred to *AeroDyn15* and used to compute the effective blade angle of +attack at each blade section, which is then used to compute the aerodynamic +forces on the blades. The OLAF method returns the same information as the BEM +method, but allows for more accurate calculations in areas where BEM assumptions +are violated, such as those discussed above. As the OLAF method is more +computationally expensive than BEM, both methods remain available in OpenFAST, +and the user may specify in the *AeroDyn15* input file which method is +used. + +The OLAF input file defines the wake convection and circulation solution +methods; wake size and length options; Lagrangian marker regularization (viscous +core) method; and other simulation and output parameters. The extents of the +near and far wakes are specified by a nondimensional length in terms of rotor +diameter. Different regularization functions for the vortex elements are +available. Additionally, different methods to compute the regularization +parameters of the bound and wake vorticity may be selected. In particular, +viscous diffusion may be accounted for by dynamically changing the +regularization parameter. Wake visualization output options are also available. + +This document is organized as follows. :numref:`Running-OLAF` covers +downloading, compiling, and running OLAF. :numref:`OLAF-Input-Files` describes the +OLAF input file and modifications to the *AeroDyn15* input file. +:numref:`Output-Files` details the OLAF output file. :numref:`OLAF-Theory` +provides an overview of the OLAF theory, including the free vortex wake method +as well as integration into the *AeroDyn15* module. Example input files and a +list of output channels are detailed in Appendices A, B, and C. + + + diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/OLAFTheory.rst b/OpenFAST/docs/source/user/aerodyn-olaf/OLAFTheory.rst new file mode 100644 index 000000000..0c901f2b3 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/OLAFTheory.rst @@ -0,0 +1,628 @@ +.. _OLAF-Theory: + +OLAF Theory +=========== + +This section details the OLAF method and provides an overview of the +computational method, followed by a brief explanation of its integration +with OpenFAST. + + +.. _sec:vorticityformulation: + +Introduction - Vorticity Formulation +------------------------------------ + +The vorticity equation for incompressible homogeneous flows in the +absence of non-conservative force is given by +Eq. :eq:`eq:vorticityconservationincompr` + +.. math:: + \begin{aligned} + \frac{d\vec{\omega}}{dt} = \frac{\partial\vec{\omega}}{\partial{t}} + \underbrace{(\vec{u} \cdot \nabla)}_{\text{convection}}\vec{\omega} = \underbrace{(\vec{\omega}\cdot\nabla)\vec{u}}_{\text{strain}} +\underbrace{\nu\Delta\vec{\omega}}_{\text{diffusion}} + \end{aligned} + :label: eq:vorticityconservationincompr + + +Here, :math:`\vec{\omega}` is the vorticity, :math:`\vec{u}` is the +velocity, and :math:`\nu` is the viscosity. In free vortex wake methods, +the vorticity equation is used to describe the evolution of the wake +vorticity. Different approximations are introduced to ease its +resolution, such as projecting the vorticity onto a discrete number of +vortex elements (here vortex filaments), and separately treating the +convection and diffusion steps, known as viscous-splitting. Several +complications arise from the method; in particular, the discretization +requires a regularization of the vorticity field (or velocity field) to +ensure a smooth approximation. + +The forces exerted by the blades onto the flow are expressed in +vorticity formulation as well. This vorticity is bound to the blade and +has a circulation associated with the lift force. A lifting-line +formulation is used here to model the bound vorticity. + +The different models of the implemented free vortex code are described +in the following sections. + +.. _sec:discretization: + +Discretization - Projection +--------------------------- + +The numerical method uses a finite number of states to model the +continuous vorticity distribution. To achieve this, the vorticity +distribution is projected onto basis function which is referred to +as vortex elements. Vortex filaments are here used as elements that +represents the vorticity field. A vortex filament is delimited by two +points and hence assumes a direction formed by these two points. A +vorticity tube is oriented along the unit vector :math:`\vec{e}_x` of +cross section :math:`dS` and length :math:`l`. It can then be +approximated by a vortex filament of length :math:`l` oriented along the +same direction. The total vorticity of the tube and the vortex filaments +are the same and related by: + +.. math:: + \begin{aligned} + \vec{\omega} \, dS = \vec{\Gamma} + \end{aligned} + :label: OmegaGamma + +where :math:`\vec{\Gamma}` is the circulation intensity of the vortex +filament. If the vorticity tubes are complex and occupy a large volume, +the projection onto vortex filaments is difficult and the projection +onto vortex particle is more appropriate. Assuming the wake is confined +to a thin vorticity layer which defines a velocity jump of know +direction, it is possible to approximate the wake vorticity sheet as a +mesh of vortex filaments. This is the basis of vortex filament wake +methods. Vortex filaments are a singular representation of the vorticity +field, as they occupy a line instead of a volume. To better represent +the vorticity field, the filaments are “inflated”, a process referred to +as regularization (see :numref:`sec:Regularization`). The +regularization of the vorticity field also regularizes the velocity +field and avoids the singularities that would otherwise occur. + + +.. _sec:circ: + +Lifting-Line Representation +--------------------------- + +The code relies on a lifting-line formulation. Lifting-line methods effectively +lump the loads at each cross-section of the blade onto the mean line of the +blade and do not account directly for the geometry of each cross-section. In the +vorticity-based version of the lifting-line method, the blade is represented by +a line of varying circulation. The line follows the motion of the blade and is +referred to as “bound” circulation. The bound circulation does not follow the +same dynamic equation as the free vorticity of the wake. Instead, the intensity +is linked to airfoil lift via the Kutta-Joukowski theorem. Spanwise variation of +the bound circulation results in vorticity being emitted into the the wake. This +is referred to as “trailed vorticity”. Time changes of the bound circulation are +also emitted in the wake, referred to as “shed” vorticity. The subsequent +paragraphs describe the representation of the bound vorticity. + +Lifting-Line Panels and Emitted Wake Panels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The lifting-line and wake representation is illustrated in +:numref:`fig:VortexLatticeMethod`. The blade lifting-line is discretized into a +finite number of panels, each of them forming a four sided vortex rings. The +spanwise discretization follows the discretization of the AeroDyn blade input +file. The number of spanwise panels, :math:`n_\text{LL}`, is one less than the +total number of AeroDyn nodes, **NumBlNds**. The sides of the panels coincide +with the lifting-line and the trailing edge of the blade. The lifting-line is +currently defined as the 1/4 chord location from the leading edge (LE). More +details on the panelling is provided in :numref:`sec:Panelling`. At a given time +step, the circulation of each lifting-line panel is determined according to one +of the three methods developed in :numref:`sec:CirculationMethods`. At the end +of the time step, the circulation of each lifting-line panel is emitted into the +wake, forming free vorticity panels. To satisfy the Kutta condition, the +circulation of the first near wake panel and the bound circulation are +equivalent (see :numref:`fig:VortexLatticeMethod` b). The wake panels model the +thin shear layer resulting from the continuation of the blade boundary layer. +This shear layer can be modelled using a continuous distribution of vortex +doublets. A constant doublet strength is assumed on each panel, which in turn is +equivalent to a vortex ring of constant circulation. + +.. figure:: Schematics/VortexLatticeMethod.png + :alt: Wake and lifting-line vorticity discretized into vortex ring panels. + :name: fig:VortexLatticeMethod + :width: 100.0% + + Wake and lifting-line vorticity discretized into vortex ring panels. + (a) Overview. (b) Cross-sectional view, defining the leading-edge, + trailing edge, and lifting-line. (c) Circulation of panels and + corresponding circulation for vorticity segments between panels. (d) + Geometrical quantities for a lifting-line panel. + +The current implementation stores the positions and circulations of the panel +corner points. In the vortex ring formulation, the boundary between two panels +corresponds to a vortex segment of intensity equal to the difference of +circulation between the two panels. The convention used to define the segment +intensity based on the panels intensity is shown in +:numref:`fig:VortexLatticeMethod` c. Since the circulation of the bound panels +and the first row of near wake panels are equal, the vortex segments located on +the trailing edge have no circulation. + +.. _sec:Panelling: + +Panelling +~~~~~~~~~ + +The definitions used for the panelling of the blade are given in +:numref:`fig:VortexLatticeMethod` d, following the notations of van +Garrel (:cite:`olaf-Garrel03_1`). The leading edge and +trailing edge (TE) locations are directly obtained from the AeroDyn +mesh. At two spanwise locations, the LE and TE define the corner points: +:math:`\vec{x}_1`, :math:`\vec{x}_2`, :math:`\vec{x}_3`, and +:math:`\vec{x}_4`. The current implementation assumes that the +aerodynamic center, the lifting-line, and the 1/4 chord location all +coincide. For a given panel, the lifting-line is then delimited by the +points :math:`\vec{x}_9= 3/4\,\vec{x}_1 + 1/4\, \vec{x}_2` and +:math:`\vec{x}_{10}=3/4\,\vec{x}_4 + 1/4\, \vec{x}_3`. The mid points of +the four panel sides are noted :math:`\vec{x}_5`, :math:`\vec{x}_6`, +:math:`\vec{x}_7`, and :math:`\vec{x}_8`. The lifting-line vector +(:math:`\vec{dl}`) as well as the vectors tangential (:math:`\vec{T}`) +and normal (:math:`\vec{N}`) to the panel are defined as: + +.. math:: + \begin{aligned} + \vec{dl} = \vec{x}_{10}-\vec{x}_9 + ,\qquad + \vec{T} = \frac{\vec{x}_6-\vec{x}_8}{|\vec{x}_6-\vec{x}_8|} + ,\qquad + \vec{N} = \frac{\vec{T}\times\vec{dl}}{|\vec{T}\times\vec{dl}|} + \end{aligned} + :label: eq:GeometricDefinitions + +The area of the panel is obtained as :math:`dA = +|(\vec{x}_6-\vec{x}_8)\times(\vec{x}_{7}-\vec{x}_5)|`. For +**CircSolvMethod=[1]**, the control points are located on the lifting-line at +the location :math:`\vec{x}_9+\eta_j \vec{dl}`. The factor :math:`\eta_j` is +determined based on the full-cosine approximation of van Garrel. This is based +on the spanwise widths of the current panel, :math:`w_j`, and the neighboring +panels :math:`w_{j-1}` and :math:`w_{j+1}`: + +.. math:: + \begin{aligned} + \eta_1 &= \frac{w_1}{w_1+w_2},\\ + \eta_j &= \frac{1}{4}\left[\frac{w_{j-1}}{w_{j-1}+w_j} + \frac{w_j}{w_j+w_{j+1}} +1 \right] + ,\ j=2..n-1,\\ + \eta_{n} &= \frac{w_{n-1}}{w_{n-1}+w_{n}} + \end{aligned} + +For an equidistant spacing, this discretization places the control points at the +middle of the lifting-line (:math:`\eta=0.5`). Theoretical circulation results +for an elliptic wing with a cosine spacing are retrieved with such +discretization since it places the control points closer to stronger trailing +segments at the wing extremities (see e.g. :cite:`olaf-Kerwin:lecturenotes`). + +.. _sec:CirculationMethods: + +Circulation Solving Methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Three methods are implemented to determine the bound circulation strength. They +are selected using the input **CircSolvMethod**, and are presented in the +following sections. + +Cl-Based Iterative Method +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Cl-based iterative method determines the circulation within a +nonlinear iterative solver that makes use of the polar data at each +control point located on the lifting line. The algorithm ensures that +the lift obtained using the angle of attack and the polar data matches +the lift obtained with the Kutta-Joukowski theorem. At present, it is +the preferred method to compute the circulation along the blade span. It is +selected with **CircSolvMethod=[1]**. The method is described in the work from +van Garrel (:cite:`olaf-Garrel03_1`). The algorithm is implemented in at iterative +approach using the following steps: + +#. The circulation distribution from the previous time step is used as a + guessed circulation, :math:`\Gamma_\text{prev}`. + +#. The velocity at each control points :math:`j` is computed as the sum + of the wind velocity, the structural velocity, and the velocity + induced by all the vorticity in the domain, evaluated at the control + point location. + + .. math:: + \begin{aligned} + \vec{v}_j = \vec{V}_0 - \vec{V}_\text{elast} + \vec{v}_{\omega,\text{free}} + \vec{v}_{\Gamma_{ll}} + \end{aligned} + + :math:`\vec{v}_{\omega,\text{free}}` is the velocity induced by all free + vortex filaments, as introduced in Eq. :eq:`eq:eq510` . The contribution + of :math:`\vec{v}_{\Gamma_{ll}}` comes from the lifting-line panels and + the first row of near wake panels, for which the circulation is set to + :math:`\Gamma_\text{prev}` + +#. The circulation for all lifting-line panels :math:`j` is obtained as + follows. + + .. math:: + \begin{aligned} + \Gamma_{ll,j} =\frac{1}{2} C_{l,j}(\alpha_j) \frac{\left[ (\vec{v}_j \cdot \vec{N})^2 + (\vec{v}_j \cdot \vec{T})^2\right]^2\,dA}{ + \sqrt{\left[(\vec{v}_j\times \vec{dl})\cdot\vec{N}\right]^2 + \left[(\vec{v}_j\times \vec{dl})\cdot\vec{T}\right]^2} + } %\label{eq:} + ,\quad\text{with} + \quad + \alpha_j = \operatorname{atan}\left(\frac{\vec{v}_j\cdot\vec{N}}{\vec{v}_j \cdot \vec{T}} \right) + \end{aligned} + + The function :math:`C_{l,j}` is the lift coefficient obtained from + the polar data of blade section :math:`j` and :math:`\alpha_j` is the + angle of attack at the control point. + +#. The new circulation is set using the relaxation factor + :math:`k_\text{relax}` (**CircSolvRelaxation**): + + .. math:: + \begin{aligned} + \Gamma_\text{new}= \Gamma_\text{prev} + k_\text{relax} \Delta \Gamma + ,\qquad + \Delta \Gamma = \Gamma_{ll} - \Gamma_\text{prev} %\label{eq:} + \end{aligned} + +#. Convergence is checked using the criterion :math:`k_\text{crit}` + (**CircSolvConvCrit**): + + .. math:: + \begin{aligned} + \frac{ \operatorname{max}(|\Delta \Gamma|}{\operatorname{mean}(|\Gamma_\text{new}|)} < k_\text{crit} + \end{aligned} + + If convergence is not reached, steps 2-5 are repeated using + :math:`\Gamma_\text{new}` as the guessed circulation + :math:`\Gamma_\text{prev}`. + +No-flow-through Method +^^^^^^^^^^^^^^^^^^^^^^ + +A Weissinger-L-based representation (:cite:`olaf-Weissinger47_1`) +of the lifting surface is also +available (:cite:`olaf-Bagai94_1,olaf-Gupta06_1,olaf-Ribera07_1`). In this +method, the circulation is solved by satisfying a no-flow through +condition at the 1/4-chord points. It is selected with **CircSolvMethod=[2]**. + +Prescribed Circulation +^^^^^^^^^^^^^^^^^^^^^^ + +The final available method prescribes a constant circulation. A user +specified spanwise distribution of circulation is prescribed onto the +blades. It is selected with **CircSolvMethod=[3]**. + + +.. _sec:vortconv: + +Free Vorticity Convection +------------------------- + +The governing equation of motion for a vortex filament is given by the +convection equation of a Lagrangian marker: + +.. math:: + \frac{d\vec{r}}{dt}=\vec{V}(\vec{r},t) + :label: VortFilCart + +where :math:`\vec{r}` is the position of a Lagrangian marker. The Lagrangian +markers are the end points of the vortex filaments. The Lagrangian convection of +the filaments stretches the filaments and thus automatically accounts for strain +in the vorticity equation. + +At present, a first-order forward Euler method is used to numerically solve the +left-hand side of Eq. :eq:`VortFilCart` for the vortex filament location +(**IntMethod=[5]**). This is an explicit method solved using +Eq. :eq:`eq:Euler`. + +.. math:: + \vec{r} = \vec{r} + \vec{V} \Delta t + :label: eq:Euler + + +.. _sec:vortconvPolar: + +Free Vorticity Convection in Polar Coordinates +---------------------------------------------- + +The governing equation of motion for a vortex filament is given by: + +.. math:: + \frac{d\vec{r}(\psi,\zeta)}{dt}=\vec{V}[\vec{r}(\psi,\zeta),t] + :label: VortFil + +Using the chain rule, Eq. :eq:`VortFil` is rewritten as: + +.. math:: + \frac{\partial\vec{r}(\psi,\zeta)}{\partial\psi}+\frac{\partial\vec{r}(\psi,\zeta)}{\partial\zeta}=\frac{\vec{V}[\vec{r}(\psi,\zeta),t]}{\Omega} + :label: VortFil_expanded + +where :math:`d\psi/dt=\Omega` and +:math:`d\psi=d\zeta` (:cite:`olaf-Leishman02_1`). Here, +:math:`\vec{r}(\psi,\zeta)` is the position vector of a Lagrangian +marker, and :math:`\vec{V}[\vec{r}(\psi,\zeta)]` is the velocity. + +.. + At present, first-order forward Euler method is used to numerically solve the + left-hand side of Eq. :eq:`VortFil_expanded` for the vortex-filament location + [**IntMethod=5**]. This is an explicit method solved using Eq. :eq:`Euler`. + + .. math:: + \vec{r}(\psi+\Delta\psi_i,\zeta+\Delta\zeta) = \vec{r}(\psi,\zeta) + \vec{V}(\psi,\zeta) \Delta t + :label: Euler + +Induced Velocity and Velocity Field +----------------------------------- + +The velocity term on the right-hand side of +Eq. :eq:`VortFilCart` is a nonlinear function of the +vortex position, representing a combination of the freestream and +induced velocities (:cite:`olaf-Hansen08_1`). The induced +velocities at point :math:`\vec{x}`, caused by each straight-line +filament, are computed using the Biot-Savart law, which considers the +locations of the Lagrangian markers and the intensity of the vortex +elements (:cite:`olaf-Leishman02_1`): + +.. math:: + d\vec{v}(\vec{x})=\frac{\Gamma}{4\pi}\frac{d\vec{l}\times\vec{r}}{r^3} + :label: BiotSavart + +Here, :math:`\Gamma` is the circulation strength of the filament, +:math:`\vec{dl}` is an elementary length along the filament, :math:`\vec{r}` is +the vector between a point on the filament and the control point +:math:`\vec{x}`, and :math:`r=|\vec{r}|` is the norm of the vector. The +integration of the Biot-Savart law along the filament length, delimited by the +points :math:`\vec{x}_1` and :math:`\vec{x}_2` leads to: + +.. math:: + \begin{aligned} + \vec{v}(\vec{x}) + = F_\nu \frac{\Gamma}{4\pi} \frac{(r_1+r_2)}{r_1r_2(r_1r_2+\vec{r}_1\cdot\vec{r}_2) }\vec{r}_1\times\vec{r}_2 + \end{aligned} + :label: eq:BiotSavartSegment + +with :math:`\vec{r}_1= \vec{x}-\vec{x}_1` and :math:`\vec{r}_2= +\vec{x}-\vec{x}_2`. The factor :math:`F_\nu` is a regularization parameter, +discussed in :numref:`sec:RegularizationFunction`. :math:`r_0` is the filament +length, where :math:`\vec{r}_0= \vec{x}_2-\vec{x}_1`. The distance orthogonal to +the filament is: + +.. math:: + \begin{aligned} + \rho = \frac{|\vec{r}_1\times\vec{r}_2|}{r_0} + \end{aligned} + +The velocity at any point of the domain is obtained by superposition of +the velocity induced by all vortex filaments, and by superposition of +the primary flow, :math:`\vec{V}_0`, (here assumed divergence free): + +.. math:: + \begin{aligned} + \vec{V}(\vec{x}) = \vec{V}_0(\vec{x}) + \vec{v}_\omega(\vec{x}), \quad\text{with}\quad \vec{v}_\omega(\vec{x}) = \sum_{k} \vec{v}_k(\vec{x}) + \end{aligned} + :label: eq:eq510 + +where the sum is over all the vortex filaments, each of intensity +:math:`\Gamma_k`. The intensity of each filament is determined by spanwise and +time changes of the bound circulation, as discussed in :numref:`sec:circ`. In +tree-based methods, the sum over all vortex elements is reduced by lumping +together the elements that are far away from the control points. + + +.. _sec:Regularization: + +Regularization +-------------- + +Regularization and viscous diffusion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The singularity that occurs in Eq. :eq:`BiotSavart` greatly affects the +numerical accuracy of vortex methods. By regularizing the “1-over-r” kernel of +the Biot-Savart law, it is possible to obtain a numerical method that converges +to the Navier-Stokes equations. The regularization is used to improve the +regularity of the discrete vorticity field, as compared to the “true” continuous +vorticity field. This regularization is usually obtained by convolution with a +smooth function. In this case, the regularization of the vorticity field and the +velocity field are the same. Some engineering models also perform regularization +by directly introducing additional terms in the denominator of the Biot-Savart +velocity kernel. The factor, :math:`F_\nu`, was introduced in +Eq. :eq:`eq:BiotSavartSegment` to account for this regularization. + +In the convergence proofs of vortex methods, regularization and viscous +diffusion are two distinct aspects. It is common practice in vortex filament +methods to blur the notion of regularization with the notion of viscous +diffusion. Indeed, for a physical vortex filament, viscous effects prevent the +singularity from occurring and diffuse the vortex strength with time. The +circular zone where the velocity drops to zero around the vortex is referred to +as the vortex core. A length increase of the vortex segment will result in a +vortex core radius decrease, and vice versa. Diffusion, on the other hand, +continually spreads the vortex radially. + +Because of the previously mentioned analogy, practitioners of vortex filament +methods often refer to regularization as "viscous-core" models and +regularization parameters as "core-radii." Additionally, viscous diffusion is +often introduced by modifying the regularization parameter in space and time +instead of solving the diffusion from the vorticity equation. The distinction is +made explicit in this document when clarification is required, but a loose +terminology is used when the context is clear. + +Determination of the regularization parameter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The regularization parameter is both a function of the physics being modeled +(blade boundary layer and wake) and the choice of discretization. Contributing +factors are the chord length, the boundary layer height, and the volume that +each vortex filament is approximating. Currently the choice is left to the user +(**RegDetMethod=[0]**). Empirical results for a rotating blade are found in the +work of Gupta (:cite:`olaf-Gupta06_1`). As a guideline, the regularization parameter +may be chosen as twice the average spanwise discretization of the blade. This +guideline is implemented when the user chooses **RegDetMethod=[1]**. Further +refinement of this option will be considered in the future. + +.. _sec:RegularizationFunction: + +Implemented regularization functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Several regularization functions have been +developed (:cite:`olaf-Rankine58_1,olaf-Scully75_1,olaf-Vatistas91_1`). At present, five +options are available: 1) No correction, 2) the Rankine method, 3) the +Lamb-Oseen method, 4) the Vatistas method, or 5) the denominator offset method. +If no correction method is used, (**RegFunction=[0]**), :math:`F_\nu=1`. The +remaining methods are detailed in the following sections. Here, :math:`r_c` is +the regularization parameter (**WakeRegParam**) and :math:`\rho` is the distance +to the filament. Both variables are expressed in meters. + +Rankine +^^^^^^^ + +The Rankine method (:cite:`olaf-Rankine58_1`) is the simplest +regularization model. With this method, the Rankine vortex has a finite +core with a solid body rotation near the vortex center and a potential +vortex away from the center. If this method is used +(**RegFunction=[1]**), the viscous core correction is given by +Eq. :eq:`rankine`. + +.. math:: + F_\nu= \begin{cases} \rho^2/r_c^2 & 0 < \rho < 1 \\ + 1 & \rho > 1 \end{cases} + :label: rankine + +Here, :math:`r_c` is the viscous core radius of a vortex filament, +detailed in :numref:`sec:corerad`. + +Lamb-Oseen +^^^^^^^^^^ + +If the Lamb-Oseen method is used [**RegFunction=[2]**], the viscous core +correction is given by Eq. :eq:`lamboseen`. + +.. math:: + F_\nu= \bigg[1-\text{exp}(-\frac{\rho^2}{r_c^2})\bigg] + :label: lamboseen + +Vatistas +^^^^^^^^ + +If the Vatistas method is used [**RegFunction=[3]**], the viscous core +correction is given by Eq. :eq:`vatistas`. + +.. math:: + F_\nu + = \frac{\rho^2}{(\rho^{2n}+r_c^{2n})^{1/n}} + = \frac{(\rho/r_c)^2}{(1 + (\rho/r_c)^{2n})^{1/n}} + :label: vatistas + +Here, :math:`\rho` is the distance from a vortex segment to an arbitrary +point (:cite:`olaf-Abedi16_1`). Research from rotorcraft applications suggests a +value of :math:`n=2`, which is used in this work (:cite:`olaf-Bagai93_1`). + +Denominator Offset/Cut-Off +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the denominator offfset method is used [**RegFunction=[4]**], the viscous +core correction is given by Eq. :eq:`denom` + +.. math:: + \begin{aligned} + \vec{v}(\vec{x}) + = \frac{\Gamma}{4\pi} \frac{(r_1+r_2)}{r_1r_2(r_1r_2+\vec{r}_1\cdot\vec{r}_2) + r_c^2 r_0^2} \vec{r}_1\times\vec{r}_2 + \end{aligned} + :label: denom + +Here, the singularity is removed by introducing an additive factor in the +denominator of Eq. :eq:`eq:BiotSavartSegment`, proportional to the filament +length :math:`r_0`. In this case, :math:`F_\nu=1`. This method is found in the +work of van Garrel (:cite:`olaf-Garrel03_1`). + +.. _sec:corerad: + +Time Evolution of the Regularization Parameter–Core Spreading Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are four available methods by which the regularization parameter may +evolve with time: 1) constant value, 2) stretching, 3) wake age, or 4) +stretching and wake age. The three latter methods blend the notions of viscous +diffusion and regularization. The notation :math:`r_{c0}` used in this section +corresponds to input file parameter value **WakeRegParam**. + +Constant +^^^^^^^^ + +If a constant value is selected, (**WakeRegMethod=[1]**), the value of +:math:`r_c` remains unchanged for all Lagrangian markers throughout the +simulation and is taken as the value given with the parameter **WakeRegParam** +in meters. + +.. math:: + r_c(\zeta) = r_{c0} + :label: cst + +Here, :math:`\zeta` is the vortex wake age, measured from its emission time. + +Stretching +^^^^^^^^^^ + +If the stretching method is selected, (**WakeRegMethod=[2]**), the viscous core +radius is modeled by Eq. :eq:`stretch`. + +.. math:: + r_c(\zeta,\epsilon) = r_{c0} (1+\epsilon)^{-1} + :label: stretch + +.. math:: + \epsilon = \frac{\Delta l}{l} + +Here, :math:`\epsilon` is the vortex-filament strain, :math:`l` is the filament +length, and :math:`\Delta l` is the change of length between two time steps. The +integral in Eq. :eq:`stretch` represents strain effects. + +Wake Age / Core-Spreading +^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the wake age method is selected, (**WakeRegMethod=[3]**), the viscous core +radius is modeled by Eq. :eq:`age`. + +.. math:: + r_c(\zeta) = \sqrt{r_{c0}^2+4\alpha\delta\nu \zeta} + :label: age + +where :math:`\alpha=1.25643`, :math:`\nu` is kinematic viscosity, and +:math:`\delta` is a viscous diffusion parameter (typically between :math:`1` and +:math:`1,000`). The parameter :math:`\delta` is provided in the input file as +**CoreSpreadEddyVisc**. Here, the term :math:`4\alpha\delta\nu \zeta`, accounts +for viscous effects as the wake propagates downstream. The higher the background +turbulence, the more diffusion of the vorticity with time, and the higher the +value of :math:`\delta` should be. This method partially accounts for viscous +diffusion of the vorticity while neglecting the interaction between the wake +vorticity itself or between the wake vorticity and the background flow. It is +often referred to as the core-spreading method. Setting **DiffusionMethod=[1]** +is the same as using the wake age method (**WakeRegMethod=[3]**). + +Stretching and Wake Age +^^^^^^^^^^^^^^^^^^^^^^^ + +If the stretching and wake-age method is selected (**WakeRegMethod=[4]**), +the viscous core radius is modeled by +Eq. :eq:`stretchandage`. + +.. math:: + r_c(\zeta,\epsilon) = \sqrt{r_{c0}^2 + 4\alpha\delta\nu \zeta \big(1+\epsilon\big)^{-1} } + :label: stretchandage + +.. _sec:diffusion: + +Diffusion +--------- + +The viscous-splitting assumption is used to solve for the convection and +diffusion of the vorticity separately. The diffusion term :math:`\nu \Delta +\vec{\omega}` represents molecular diffusion. This term allows for viscous +connection of vorticity lines. Also, turbulent flows will diffuse the vorticity +in a similar manner based on a turbulent eddy viscosity. + +The parameter **DiffusionMethod** is used to switch between viscous diffusion +methods. Currently, only the core-spreading method is implemented. The method +is described in :numref:`sec:corerad` since it is equivalent to the increase of +the regularization parameter with the wake age. + diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/OutputFiles.rst b/OpenFAST/docs/source/user/aerodyn-olaf/OutputFiles.rst new file mode 100644 index 000000000..8068e64b2 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/OutputFiles.rst @@ -0,0 +1,24 @@ +.. _Output-Files: + +Output Files +============ + +The OLAF module itself does not produce its own output file. However, additional +output channels are made available in *AeroDyn15*. As such, the *AeroDyn15* +output file is briefly described as well as the outputs made available with +OLAF. Visualization files are generated by using the parameter, **WrVTK**. This +parameter is available in the OLAF input file, in which case the VTK files are +written to the folder ``vtk_fvw``, or the primary ``.fst`` file, in which case +the VTK files are written to the folder ``vtk``. + + +Results File +------------ + +OpenFAST generates a master results file that includes the *AeroDyn15* +results. The results are in table format, where each column is a data +channel, and each row corresponds to a simulation-output time step. The +data channels are specified in the *OUTPUTS* section in the *AeroDyn15* +primary input file. The column format of the AeroDyn-generated files is +specified using the **OutFmt** parameter of the OpenFAST driver input +file. diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/RunningOLAF.rst b/OpenFAST/docs/source/user/aerodyn-olaf/RunningOLAF.rst new file mode 100644 index 000000000..4b91c6150 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/RunningOLAF.rst @@ -0,0 +1,12 @@ +.. _Running-OLAF: + +Running OLAF +============ + +As OLAF is a module of OpenFAST, the process of downloading, compiling, +and running OLAF is the same as that for OpenFAST. Such instructions are +available in the :ref:`installation` documentation. + +.. note:: + To improve the speed of FVW module, the user may wish to compile with + `OpenMP`. To do so, add the `-DOPENMP=ON` option with CMake. diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.pdf new file mode 100644 index 0000000000000000000000000000000000000000..554dfa9386fddd5cc48b0a831add5debe7702305 GIT binary patch literal 43255 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%0DgWS=vA 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 SM&)D&0=ZDBsKgZ{Q2!5Rm&cs| literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FVWwithOpenFAST.png new file mode 100644 index 0000000000000000000000000000000000000000..e474d79c1e348e34235dc3668a7eb19a14ac28b1 GIT binary patch literal 14529 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 Q0Y;LRP!O*YGYa~D0LACtsQ>@~ literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.pdf new file mode 100644 index 0000000000000000000000000000000000000000..09d2d503210b6185428ebc3e98370a3a7aa6722f GIT binary patch literal 20732 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 V6@yzAAt*R-QHp~@MopIV{{Wy3>mC3A literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/FilamentRegularization.png new file mode 100644 index 0000000000000000000000000000000000000000..77a97adfceeb49046adac0c7421d4c9f04617cd7 GIT binary patch literal 31008 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4d911dadafcf6edfd61563ec71c7896a3c14c209 GIT binary patch literal 63510 zcmZs>WmH|U);0=k+})jx7cI_4io08jySr1gxVyU)cZ$2ayB2qM=hE|@_q*S?<NjI6 zni*3vSCW-Hc_<Y`#28o@zrs`Y?OpGk6y4-Z^$ozYkusCo8d$)CK%`7E#x|x-W~A(& zA|+BLF>@;?V~5YuO5e#?#Msc*$e5I$AKuZ)!C2oK-VJ;{Q?pKcP;v0@Ly^W1q|v5T z)eF=HGe{6iHKjN#7>GivpDZgGz~$%Z<^AE~T2=or-E8$8?l*>N!FR{AqpS|O$$Q&$ z+qAzN3_d~D)<O2>-meW$5Br^IRUPlzi*0Y(vrm&38ygolnJ_MIGY#V;Y4uOZvrK9F zXOCemx-6Rl21!*u8-EV$HCOddNWQ$iTIw}fPBMIGE_fdWg?c|*ESfJ5n0r0eJtN<E zoIksppSQfX-OsXRY;@Q@R}uxgTRc~sHRxLxo4=T^FIh;-3b2))w?thyf2VS3i4y*6 zJ3b{VEnqvox_>avS!82LeRhRY^ZUNsX1yA07WE^a&Dx8TrBAaYllfxhEayR(x5DzQ zPW$Gi#Zdt1z&OS4_r>IwItyxYl&Pw94y19&;?=b_3@dVNy$YyZ>(MIx9|OPtCYMg0 zR4SY!N){HTH{LWLzgg4EzO^wLPMiKHvcVr%QSlm(npdTFKk@pT*;=ESrAZqt)ET+j zHtX$YakI9d^uS+c+lXj7#m^z!nKkI0nWb}5=JR$x*!cJT;o{?9@gj}H2P`uac7Vhl z0`fQHd*^e}gZ2$dC%4zE=bi1}j+eU&pU1zpo$uqVe_tPaUu=Coc2I2DuK_McgIjG3 zqbs*>V4+-$3U<VkXP`)=0s;BAhKvox#q8kNon;h^U^h(Tml}bGSrD_!mQh9NOUDx< z_X)~ye6qN;Mv(n%DCXqt=$d?&uG!cm(8uKstOG%W0j%pgI#4m=B^LwLTKV^d*DJBX zQ|7$<Pq?PAH-W_Y7h~>50JY80<S0l!vrFgM8d{Uc)E?ldhY!aZ{WiCD2O!tup1geL zn2k(IR5YE|+XJ~EiFc+a-^{e}-Axr{z7%RMq&mVAwK!*yjrTZVzzALIZ`w)le+dz% z*kXC=de2TknKBPBr9>BHUl0kh60LuZ7-+ZsTk}z)8}og(S@cjl<_!F4DhtP6N1%4d z0K9w;)vQvu^r3oqZDs?7U|TO!o^aM46s<Q<YlhF6J#>fIW42-@G-1yM4T))W;Lpo= z_9ooIghb4*^}Ky4r^!1ZvA1*tnTxvi&~Z(pzKD{`U$EO|N4R|{hPEKcet4-yi_A0> zUwim%Z)ic&9JbhdpG~GH*H*tfN`IXza}e9YQD#EHTV;K!dq@vD)oH;!PY&_Nw%c}_ z)zI_WOl{8KxzBu3?Fr137V7;y0~wbX$K1EySc*MCg?Ri&FBl-l4ODc&mAd>u3M9W+ zzO$LKC?d%+MKJmqqwJ1+OTDZW6b;ec^77E9>f~@4E0cKpnVwZ5__sGnBm4vVOF8PH zW9^d4`5NoV8{A)i7B#qVSnSRfuOD1QtDG~XQpb0A{^XDrtLaJ>9j~~LAlP|dcR(Bc zq(AX@oR?!pe?k9dV&90YVVZ?L*qd@{nKg0R4-cVYm2X8Lf@fjh)L3PnR^2zHlk{cw zPn6Z!hI(e_Y1lVMq>1>K<0PAt!kk4NWDh<)5;E}0(|j$D?ijOa`k6*>^LdT2oHpT& zE}s64qNtr3(yy)9QAB?(nEkV|(OdLi{KOP^nQj90p*SgI2Te|@x117)Gp{%33>e=9 zzEvK1>YMAej>C>trq?X-oABdeppAJhA*$avj}CdB1!cXYJaOHv2eAx8GaYCaVV^<6 z<BY|voU=m_=fVB_bBeqA4)K!$KMsq7b}#*4M&BPj2J)R(ZY4s<hT!xq+?pRD*^2h7 z8?W4Izm{e6H$>+zuc9;56<Bh5%QQcaZc7$MrX~)&wV)dU(hjlxgX6M!j%1B4!9GTr zx;eh3-D!3@*9tTkZ!q(7C(h|DEuEv{F`Y)uQa8(Ri7uhhbei)TA_mBAJkYQs4tjS7 z;v;@vlmoP&G&LYkFIm$AA>!1?q5p2p7}A9w&XV>5q!EaPjr%K6CDDE%gyE9FhA!I- zEQeJfV{?*1yJp-ti=zIzmNc2eGHPXdkmMrZs;B3NCB{fIu{>kB%S@PsHo}FIuu*h` z=3SCnMZ6XKHI)=1Hal|P7G%}k9n<zCl99`~fMs$%VJ43(xrr!@tPI;8Y>OKcS)t$m zdou)lnTx{0Hv$0mqLcacbi?=5rSl=n%~LQ)LXO-7jiMM1`Kh~71S#gsvJOf6Z<3a{ z#1+g}ETG~2=b~b_Ory853Gs(Q3WEM6LLIatJN!oQbL{&xe4BKe^Ag~c;5R&u3)ke_ za{BcyP7n>5FF2YeHWxD9hG|LRN!9T)xYl40SBM5iaf2&QJe^#UM6G=(CO(Gg__u`Y zLhcK)_LCyVNdw&a)`hXD?jt%U1)I@sbhm;YE4h&TSy$me%;Pe((GKl!$MEl=WDtJL zU!vax2rGxKxUK<Nk`;kxjoT+hSPHri&o)+w!fEw9RyX%b{sPU|*ElRQ^FQhqw(Wv- zN~*NVo?Wb62Lujo$IAnU?RGk1WW)UCejs?lOeQ<W>o%+1ohjU(_<9XI4R&b{94x>O z!D%yuEn_9cct7IRSCmy9hh2@C?ALs+xnjvDq{2uh|3hp?Jep1hUELs)Nl!Lt(gW5! zbEodyAM;BiBP-ExdOSJeeNKvR1?rs96G@{cWKIhwx<9+-?U)V$mptzeCM2-*p77qG zAy`;-KIL2G^B7Gs4b;gB&!Blb^Dp9+IgU}rn%WU^Fvg`;&w32TFOjVNT#K``VYcZ= zOxAt=6%Eslb6t;0dU4)agecfiTw>k$vyxxaq^a)K)RoiunP9LZY^xw-T7gQ4!hW*Z zTjo>}ex>aVVZ?P?j$~&F3qOMtvBtEhe<9BZjD<@BUa{DcSo<E2VB^t>1dAn@&)0Wm z9Zp1cdm{OSh;fEElo4AIg~XrEY7|tM9g*mp{`f41pqmw&B|yScjfQ$5>*^8E%Xs}M zmhOsZLN&MF%#%zJONVN=?{|>98*`9L1TdI7$N`aQc!@@v^L)FFu=^k6nXzMox8uY! zOYtEBx+!wOD`{$X@WZ%H8NvvMMqocSMh|61I>rauA9N(b+&c1x?lAM5m3CF=FEGF5 z`r(CyAIQV9b--5kP`w8v19@c|b=va~q4gIJ6C=-sxPu3Z!~}6_8Yt~#ToJKc(UZp) z4#U&2!|_ufOX!$3+cP;{8p1d_G|;SFsFo4r9Y!}sU%_`<a%gRq-7T4b^3CcAOih$@ zA~AZB(^Lo2HsAK;%rMZX!fLDaAbjw}%UHyH6TL%^-8rD-mVsyigvIvn8KUUV<_;uo zG#R~V^Ix#PmKJA~!8wc+f?1FxGjGU6EWuClk5Ka_Ay9BiRA$OUR5)+Cp6Y04V`ZNr zi1uT6=5e7N*4ko<hLb>bUaEg#iy-cR2qc96^QT{pBZU8iWh7gP<B=<ihvi2vzNf?y z9$T8|LdO&>0Yr|MN{{PTA_sBAp9#pVxYK0w?CYkaRj_0JiFS&$Z3*P0Q(un8_mI6X z_oL!&A#(A}V=RvOhWVNK_u?d(+}=}4p;<AqJSR%x*oHc^*eLbbt2f(HNg)AkY+aqe zFjQnPD{c{Zpa^&M_yPWsg57sh?w&DpIv%e=3HDGU;keL+$G%~n5y>?|3Df*h$I?Ei z*_!`jhP<B0*GCbPOb5K-swYPx>8AK(HY~sKG1<K;tA`_HATjxRzfcbAS!IWxjlZ9A zK4G`Q&j~xqQf;IG_&}M@;wN2tTD>8cNC*)Ttz?XInjQQ31Ezt~NvBgpZp98bTZps= zNs^%!Z`p3~$k0VZnjtD%k>F>0-QU6ouFz{DwjX{!vMoK8wt)C%$Nop}4YsroRnJpW z<-1YGp-I%wbDH~H*~edsb`)^rvw`9Ecgk1RbpfIM^}2t)Ys3;#_!SPMOuuO%dd$%j zqER}CVI8HGvE;9!mlA3)Z^%Tf!B2Gne*`?B<zCUz$G|D=k!v)fXt5pT&_Rh(vT;m^ zn8jJedEzxS4EbG^I6+Xp6_<pUSdg-pK4dTsH<s+xN}9eH=y|gqRBYt(q58kli1LeD zT27k-mtpQno%S8@Wcz-_lk;4Pj2;%DyHPo1V1`oJj|<kyDg=ZGjg@45mkZnNDzF|i zr_09l=m3F1X&`;!vMrLB01IFWCI5LELbE~f#Do$+cdqIz@v@8~Tfne;k5x$6#4~G5 zf!5z<bsEAfRIc_wpt`TN@TFuk|Mix+k4K9Do!2Vin}#RxAb9EYcKk~VA%3<IRCAHK zgw(#EN!;8`d3jFl^SQK`A%wax!U7j0Zz(_7nA%V5-p(8@O_Bx{&Zib;j7u#R=<}C# zYdB6N9VPCR*5m|P^l%)&&TNv{(oKPXU~m2ES$ZVgWC=RQ)8~MJVt(m*ZPSihaLKCu z$}cX7uV}ap#jKPRP7uNbgWn4~yH_tw=ypjP)oqKFCsBqant-E^JSJbKm>7@aK$<yD zn>8yVl3}FFm?i^3UKW(AH=EIT+^~jx(*~4WF|76*V|iVmx$w4Z{sR0yJ*bv7BSsnE zB!I1>#IZt0O)}4>XgP+@r!9BAFKFscSch*t*1}}&f%$LHw5QV5^Fi}VB~DIDZ)1Pw zQfB*+>g3lc$PgOeO-;IbcUzrs)!9wGoNy?W2AP|Jk*4yLLPwokk~b?D$4m)a{6DiH zlf0Qo&^v)VJ9pQCgB?$Bfie|IrA6esZd8+K`wW>D#H5xGlxVFazV5KTpS7{h&;PET z=In`lMJ1lwSAq-&g^-0#l3p8(%@&qSvdOrHX!bh;U^3@^bwiGn(D?f7{B;40-B2u| zrNdN?<~Hu2G;y@XcEY7fzdy%ggBf(g@*_*G>`=_ZMNsMcZK}z;E?IFuvdN-jP?=6+ znFC!W9q1svf>NzwH-@(hiy$#m_9HZtMFRQfn@}R<XMySP_1rNNg_09esY?_6anmVX zl-#Zwwnb9N?qPJ<xs20ZqGhjzS+^*|#Kz!xYPal+@8s;7&7F(7)A61~7x_%!P2sT` z2G1k04;^_2{0{eNQqQ_~GJ$M(?bS=c0t%wA?3)qXT)f;PzJ?T+?lZ_5KHUVR3lc5l z*20qx3I?b8Cqov-=6sz?8hGy{Mcr@{Ex#yUqFelKqx5H`@koKZnXyK`T?Sve?(aN< z(%m|1$tFi;V=qL>;hljICww@DP+#G2AZZdyj$Ju3^o;|L6qWwQ6>c5De!C_Os9D3n z<+vVq6X@c+2pgi9(ej`WR0BHqLI3cFj%x=9eXMTZvI`p042gtyfm4*Y{F1#iG)A+u zTi|QSdin0Gs5V-F$uUf3Xs#dLGgBI@ji@RFb<sIwWB8+1#1FDHX^=psq$yTuCy>&Y zT>k*bh87c91Xqw9Ybau*-b%TsgCPZsj|dinq~BGb^HPs<C6+v$lZ8s|SgHEU6=OAg z*6*?qPjK8(lr+Ud`}20!9Z8M@gY}`|>b;AKYMBRLhG_Cq5c}<0P!!a}vpdCBAY3B$ z$rl?cBb0({A)p9~`b%2$X^dQ37uZDH0RY+z+^?8`lh_*9ut0vGl_8Vd;r;EkgrFJ8 z^Y7~$0oyOU@sC5}MS=~dc6Z@-v77zY{kv?h<+i8EeUiU@;RA=m%i5Fva?|Ul33;Zb z?srpPJOVjn3obX{l5PKHXJzh(!xSmTTo~Zr2blb{koWPHq419@O6K7vlo;y$e%%~D z3N<5s{kI<#w{Wy{(43H2hqq7h;4VaCoNCGn{*W%PQPm&=X<-MFISBzpNBM{bZHv@e z>82Z_LY{D4Y@(?&r23AW*lg=tBDZ#^KO~Dm=x`f_jW+d7p$>UPe-+3`hFHy;;buHT zFRsw*$LcZ)y2_w5oIN#&JLXrRcaA*X?Y2QX49iC^tXxoFxVX*`F8>B1V}>!28u@_^ zAas+EpNMNi)}8;@S1~vSysXCbK_z3Y2WUT0zg|M2E8`66f>i*@$4v0-6&&L;Ot4^< z7WcX`UOLrPmbpg#L=-&_nN<m{zRbtbFFpCAsdbL6V%A6`LgA%}yTsMAQ859wM&3bH zG(Ce?9y46!-FI&ZOzrkFbP$mJVInLy8>*hyYcxVfCK>9E-Xf7l3RMK5f5^jOy}9&( zO&u0se*Fi%-%5yFx~c>kAl^i(b8MhV#_W0RB+R%_1fSrx>z0)WQBIeIB*GL@2bW&D zv-z|}#-DIoB`ikna=X)x`0Z~w!g5)w2=UT@24?wUj9C?r;G$>ohIus)S*n1dIFV!w zB9w!qvh(Z<9k4zIq9#)RmA0Mw5Bg5&K;02s@dV_rSQs$&gd%Eu_{uw=`Ya1VbWEfx zrZ2OvlwVOy@*JJn?+3_jV~q(I6t3>tMwY7xi7ax9z@1njrAbZc7VtA*yZfMvumnGa zg0~AS=EOy_GCC)|IVqWL-j9V1AyhRJj({n&g?wB+RXSFq{%RQ3-+GQd2<cX+GGPNP z0n@h&jy%YilO`YvfIH%KRI;VSvy3wJ@)9qiVY>^3s6P5SAH~(+tTK9b$lO@`&OS2j zP1^=n`+GQmGV{-Lc@h3vZtU(w1WiD18#BqIB=>I_DaIC{pOa0a!*kO|RB7Vek+L}Y zoFIS4Nen$j?ZEW9-yqL%@Fn4<hmL^+4ZO3|P!5T_zi<0qWWb4&gWE&}GyX6B{gWIp zQ0^w)WT6um8S&)bL}76v1Ho$4JWaPhT^uPW<EK1PQ>+yTH)Nu*Sho}-kuviNnM~3c zzfQoqqA*bp^n;K&VjaHF3%IA;0p&Mov%^(+8_EtmVU3TCPOm(BQpi0^dneFWS$n|z z`1(>`^!?qD#xRLeig$9MR_8tGfp+U{Hm4Z}t(Vj?c+QNaQQELx<=uf0*V4=s-yAKq zev$dB7Fjt~=fQkylVoMTg%l`t!^@|}SPBJUDr7?b{_7Pg2vD(KA30HDg)Q-qIuD-N z{vDU4E5TsTAS!_Ci}58Q4?77L;XZ~!$~q7?lY}kIEJcGHIs@GnFT)dlVJ-TAM5gGA zGI|0#QFtuwIgisVd`EpBzJpA&$f0Pwi=lI*2(up9?C1}mi7>(_rqX&#j6kJ#0TzJ9 zndT1`Prvz^SQcs-^7=6y@)_h|50!Y?agM!K=4F=vGAF$HerpPtVZU(h@IW}@4OC51 z`Ob3oR8$UCwX(AZD5vGyei13SYr%%2o6L3!3T+>T9pf=-$_Q?>_NAQ!3<?E@x7yZE zBE{XLYH<ca>eU6K*!f&(F-&dZU)DYEU_#$0{%DO-8g)n1#wQrJ%7<dQ7%AV*Cl|4b z?g2>Irmc%LiE(}#4mBT~OJgH>``u4|m0WH;riL>2C*k)!1x2Z6AqwQ`N0M(_=V+WS z_;So>h(Hd0yHO0La?VVsS79=Ak7XRWC&)v5!;)8sba96wtkJ-h*399u>5aB$Ryj}N z<8~)b@vMo2dv@blmH;F}vo2t(geLjMx)qOTh~N!Wo)nmDfmui56xAScqcm$`mbL01 zkV+vEukg0m^VgI4MX(UeN=gpn<RVL=<qUPi5#;j_um9xd!lRzLsi^*ak^_BFn*Y}- zcAL}54`P9oZQI);-5^4#F-_e=GQ&LT%%Iy1Nt$X|+6srCbqv^-cdZyzd+erO@>HyO z#i1SS!1{%&r?&;1q~R-~2<MX_Gh^qQptw;!aZ6CJcy$Vo_E0g4#4tGzw3~@WKfYJo zC|u`>ai^A?-8rON+oirRqvJCg??9&ygGgcSE&zR8BEgg&LBexFU#tm%{H+wihBAMA z=H5qgJMoWr#>&VQUz?{2m9XlvWRnS*_N+m{R**g#EzMgoAP~%LEj@m0wWxU*<z-a3 znZyL6cH1KD;H?^gU@JvzVU>~%#p>AUEbsmLPI!|mPGQJhr6a@6S-Jysdc4gG0?4_K znG3vKj|O*r3)sG;pt#`LmMjgi(;w`YFYT+0$%_diL5w@`3eJ3fp2y)Tcdgz!Q5SfD z$XF-KqVZmSEp@+{e9(4W!)IXQbcGeH5-zpGZ9u8$ZT-8bF#C0ZuBT{WUhJ0Xt{Gk6 z+5r`w;&nr+IEh-#<4qk#XVcOF1-gey%P!4*ioBSuh9+vdS`RP((SC4>Y=~CFX{tBd zHIfoSzPz{>QqfJ~G@v^|(KHEX5Ou)WNNXlG*KIeh%Sq^`)aR}hrQ|&KuensY+?y|q zaxMI~&*|Cy^CxD}>+lpoH5sdz60$fRwG{o=gvNU~B=4joaQvW%7EyKLFW>_A(8)KW zM85u!;kOBWiGK6fuoE}KSBnbXg9ARd<?$JKJ;M;DO!-pI+2w^HQoJP!aYB5~t|j&m zn5*n`w<QC(#|tU!9><Fy%xu9hEyTGI_OcOhSw_4_I4z_-<*#0S+TUy@1y2~ncZ+p9 znz-K*ik&8emmZIiFkRI7Ge>YZz00mnrGF7Iimu*4AJZ{VD!CQEEa}>T?bIfEiG~$n z;Dn8Ab<gj)G73V&OHRV?hy#9AaACka*bCMSU%8#b=JS71P?8A}M9cqRuLX#{KHG-P zUR2_}y<!o$QD5?$tR63Vxz|q7hE83eZ_#}*D+JK!_3-_a8Is&3W=5i&l&XxR{HsJa z9~T|U+h(}cEu94KsRZvFjHx75`36}o`Gnr`_AQ3y4_UUq+n+PNw?hQtrlqt+URDrW zjD+4|&T5U$nR@Q*U3pp=>5~Wu{<h5F4L3Zmjyi$DcFP+72tAafa|wvWEJnEBQna+C z=I!b`L{q!3FXAn@78;o<A^Jx>aE8ewjd%g;n$s~=GiDHv?s;xkfF8o$<v!oh!^_?Y zqV)KFX?l9k&bNn2na|CMf9a~sxTL*7hF(=wAyJAxL&Yn7@Nn0cg9&d-3$mUVC%rGj z7YzZ?ud+_2PfAGVVo6^NvJNCP15^$E+nw4~X+RT{F65H|wl1RIPkUSKfXbF>bHV&q z5q7INwl3OP{#K|F*~y3%&F4duCUJYPSi*D1X)aok)+f>Rz8KXT53+1I86L=s3ZCRQ z0XOj1pw<sb?^)WM+!zwd`H*p2&;#FhNx>uNxVpPp*^Vu8C{_i1Hb4G$N2eMq*P6)3 z69i>^Bz{PcnCTHF9q48`hJsZNsdR&2(<NQ0TU=Ttr8ib7N7X;x*t567zDLq6(jKKe z7X{Jn9Kgik?uAN7-RISCEW(y2BT&Az4r0ok>~JZyS9Rsa;goAR$2z8*6IQ*X56T-E zOBaM_d_DWiwyT}}uJw-DlV2raFMURSm`vdm!hXpo|I(zrUH<@Kg7s2|Z=X)dqap@t zFN*@t@+0)4>p}d=jM#Zyya{d=xyFCRjvSst;NtEnzcczJUAU)m2<o2htK3Hj+67mW zICv}K$0d8)uhiRbjp~;(zc0Bqx%E78wO)zd+D0=CnKeO<KG-V^x$E5`o3Q2gwis3# zsk%#Oe*}=|qPQY@dfkE7krJM7uE{(U-g7rsB=1dIFqvT_*QDHO3*^DD*F#IC{{CsH z%_<s7;*W6mHbmPLy@K9BzA3|1Zp)j3ibnU3-2QFeHlh@*VA<a}j8vwST{7^kSr>}X zzg0igDyl<4V%Qa0(6C4bX5mT<^P#zQG`ooU)uDj&BFh8U!?wo^(+m#Ag;vGebE`yM z68dj6V_cUa8!6LIP4<7Ar^q*;wA%Z`<Ij+f&C_(Ye<15FoW3gwWJ6`2<Hf8zk3;Xa zW90ud_BOYmw#>vOKR#sqwGkzE(sgR^Y@hqvQbUCFN1!eXNJi1yIMfbR|9fziLFG?9 ziPN>Rp1>X8AqN}+``10IC3LxO0#~DD$Ybm9X>9<3UptEiC{wVa`ULW8Si@T__KehL zeX^L*yDn4|a{jA5(Wp=4Tldy^k#G6Z4#rF-!lO}0#g4nr3(J^(-P4qh(Bax+LGix7 zt7TaEEwUdj-@xGd8eY$Fql_<Ky}9f_cWGLj5hN_DzY=*yv%12XeUSj6Wm=e2o$MOk zBUg^xI7Mf~T}zN|lkoiLCoL(_ZomcXfIFg|@syn<1G%Hj#XI|6(fu`pG~cdOPWlHe zI^4M}b`qmK@3d?VO1f^vW-pHAIJ;=Z_ex*k^_yAACGVE;@S_$9tN!?yaS7X-XsCLv zkeCV$ds0uJ!x=inN+%|zKC!GuP%_{K0|nwQFzp&o4#|iLIb+`lK9TL<6O;Q7Hd0`k zQeg&FS(+^G{yX+%{=6@#g}gg)s%CxfL8q9j8_9N=0$or{JLFE-`=H8v&KBOSJ`D07 zws@5e!K;M@r!WA!B!{G>TOyH3js-v6BCk(zVz7-q!m5BtO$QudAOA!Ig#qe@bTjx; zuA^3y7K{dJgvG)D94_|D&&|S`e|Z|V7pv{Ke($%rC9Kn{Rs!CZtb)<{Uwf>4-mVn$ z*5)Jrf>CR0#d-pd>yeNI@^JFx_mPuW9FtK6ZiEc4%}$buR;+kYepg3}U%xS%-W^I& z4G+t3{00?Cc}(lDg%(0m^;$!%iua9Kz``&Y&60#F$L+jJWL$4m&83Ln=3l`!et|)G zoE`YhxQyw@*4Pw5BXq~r*?_+%{ZdqJ)K#jQ{frjXP6$!}Y++oPO_bJNTl$eEjfur4 z6<wHQ|B|m0Q`paXkLzjQkH_x;ed37+zT0_|o1BUX+pzDzy{&{-a_q__`xJYgjau8= zR7x&NpQK@&1dCc+6;wXx0aKcI3*ajQN?s6aviZSx+9T1{GchJyS@1RfOW!+_7D7$B z7L9X>xU=0y!aeoZQh+O@0_Es11G*a7ZlWvY^6yJn%1iMWx<68E`W{n$ox+!UMLyMq zBkZb(GLnbf!c-2~N~3`?U%DLhyf!9i>obeE_Bg^$+slRD`>v%0UXWOc9Lj2MP?+07 zIG{wESPG-Pxz;FYgi<(Z;$-au9{jFocfR}`=@Md5MK+?cR~$3<CbxC}1jNv*@ipu= zCMcTg*H^so@I{Zp^@2`Rjvi?a0M4eoE2!iF5+v@bjDDu9=>Fu(Mv}c=hL<7ed!Ql@ z6K=G0fO$RM8Mms?Abm4yQg|U`IW%@gqcX4&a2ah8|8^^2?tIq%F5o7TYr9VW?0Q(6 zu|-~62SM<@XG4gn!;UtRFsJ0UhFL<DX>l#-Po9a+!uQW^VX5Druo0FbsWuCq|Fz1g zT+jeL#1uyE&08LzQC|54rr~Wig8$Dm3W+aYPp%@wWVM(AFuf0UM2$WAun6Y%C_AUj zft&+oh7R!)+xmv4@g+H&iUlfu?jMpEJ?8@UZmcNMfacy-D3PE{bQnde5a9g#rrcAP zw=ZE<HzEuanIioyc9VS{Gy2iWaM-;Re@LdV_CQ4vRLg_|LkdnGhMCcL6T$!~{Fp~$ zAn&imt_U0{ForaELd;jSr~5%ELs*AiSfktfby%z{+^|?6mED6iihe6c61hA?cC7R; z5)|(>414eiBdW|{l{YF=Hugai{~ob{_u<bPo<Hl7M~W2|*^Yqk7(R<SOCN*Wk?5ZB zk(6CbhiBV2{P}A^<MYzNq*~rDt0vWMOY&NBNo>t8vg^g~a0fmRnQW4uS%8S8_}>Lf z>M%zR`WNk)j2DOLT{D6sK5*e4H8g)B`D|3rvNsQTChEuivY$)S%{uxCS7xNR$&<Gi zqOnt09@eyZl2}kXEkfDb$6jWh&j*FIv~Ws*qc3T@<#gfp50rJ&;(i6wn@<7qbsP9f zA!NU<C|N3XRADnYAnLRl2(xMBoNF_G%F8EqlRS{n%H>ZFc2p90@os<5|HO;u_62`f zpU~zDjO2~f7_m|P2TskTYo^3@msB~jj)~<Uze?H*L%76K8TO#(PDT?ODIhKMUo>yn z#MniCnR;}RAWNrPO9g}qNR$_hme)e?y~Hi!I$j9h+_>n_9^yX675Dgjz^?V#;;1!S z@$gy1$m0np3?W%13C&21?AhWJl11o9Oq(kI;5MYqy|sjFMRmx24DCr#CiG=-`%)AJ zQ3!qhIX9@e`_v+tkl(p*czm{*qluO6e@Kogr|^upFJWyXVacGg&?p7WQC`Xntzd?R zMTpQlKaop}XB^|1=o8=JhqyB`PG>0oBCpqCr__@iA(~jFjT6q=j^)$3e1gR4coGof z^C5&cwlVrId*`$EkM#48>GQATX8Fqfuk~M@_5UISskqx2lQJpjoBrqNU~J<=`t^Uv zK}yDsw$2WQ#*U;M|058#wQ>4vcO?BsDEed%$r>A(>kHYsk!mu33chl4k$z?4)Q0~g z5dGKBKfQnc{t=H99Bd7hjh#p}KdT~Qq)aNtZce03lGdM&h5lO#|F@JR)h1;UwzaZ# zP`1-IG$#G0F6_uc%K6Xjr}<C5(q|<95v!=Mk+S?ZUKJHqQWlo~2~9<XgOugJBqtRW zE>f2N=zemWNSQR`4J?ce|Ea@&x@RHf`j5tE%l{kqKhgij{a?Zq_kZpFCtLq(f=Sug z!0A7d|MY{DN!{G&lU&8Z#X`y?VQg+{_L)mI&d*+b=FP#*_8-X#-pRrFGt>W9@BSw; zCS_TDN6Syu|M4Sa?&PRo>>zAwZD(uq@0)P_|B|)-<@*1Swa(TxCr%q`g0{wJ0hi9u zn`NZ1)ri2TGeTDvIgXfB88YQdU|n{72a!<Oe8ocZZ?!8Sfpl5L{?cSs;O~Wx_-qwA zqy%Uwz;C}9LGv6o1$>(S@2i#^z~^;`<l{j3`OMbmXY+)5aJKoTyw5WR&-?3vz^H_o zyNj5Y4;d0<#6{=FyRFZQ=GxGO&&P{x$J4$LU2!F{h3_m_=<Q<X`yG?dll1kT7__rX z1=Gi6umB`_K-Z3s0A*n3^L$n1?~vm&08$8TB&s4bX()T=%lZXzhGPHXjIS^G74be9 z!}gFJ?V^&%-Mt^Q2!>6--^Z7~ALmODvQIHE@U2=`0w15mvW^$VfG%MwzaWCA>rp1A zqNw9bJ|vAEuwE7`t`P)2EVFa-lQ3g7#<t*qNEuO~@ExpqMXz)7F1epKWU%J$sXFU) zO?l8VqHZXmv#@02zaNjo@Jsl8D#1tb>X3;6Kv+0nt|-`Zn~hgX9yAv`f{vRV5f>b= zu;hAVG*T-zR404A6d;z2+7*yQUQkp)kL~$#)(DICJq-npfqx<GAx!Z0*@_M#2r^9s zj|31Q(;S=CQ>g(Kf&Co<?t*Mb<H5ZOR-|gurq2#Xk_^~IV?SD`-VV=L<Tn5S;*%}o z)?jyJ@RauQAsH>$yV60V=)PYkw|_0&{DD7&jVDy_h&s_HO!0kA<5WwUXnr*ddZmr6 z*cXxv9_<(2(*~ZZ9RpI6PcXb2WMWgSJn`N~`$+wqV*8nS&RIJ}fvnn&AR)MND>+}L zb|q;nr8fmX(2pv9>6v?D&-c)oOQ3X{Wkm&&`Z_guF0HYsdK7C{-vs1TL=MNMV4wZq zfM0^_Q|Sk?3W}*jK{NA|k%UT{#ByntZ|Dz*OQ-RV89<a{EJ`@G69=f#lNGdPpy~ER z<cCTXc^ESlfd}lGwt0$bUXqIt6D!GzG7k0~5Zz;xu5DqdUHV2QdG<*%nDVPHVF_H3 zrMj)5#tC)Jp<Gplh!#y=VR3W7ko(63WO<|&=U331e8u_}GDj(*b7)^K=qUPy#|v8o z-Ha=eK<F2e9Nm-?rc3`9Ch+Li&vEj^<b4%RfBgITRToKP#sMc9wp;#f?6|YE<?ydn zXrHzd0LhB=yK3%!8BXAia-+}NiLR-R$Bvk%h=fVC=ujfu)3~iS06=izmwO^61pA;A zpp}ZsX(!7;j23s;o2~U-6z78X0}L#{H}^zv_bCQ*!4OP62$F0+&lS#3+!H~ivOF*R zA=5_?7P^3d#K7b_+UFHO-J`&_<oR8$_R9Nn9Jz@=lJzK@rE4dlDh7r7f=k5M?TD=) zCJ8i`hn4PJp>uDb<|!y?#Lv?^_Bh+2NgTeQ?p-lNsjE%*zc41~0RV1IS7fxV<<#g^ zh;U#){sMVey=@)B&d2R=dP{TtzveS(R|V2NYa8tZ#`t8ccS^B%F}NNorn6nsVR~W+ z;#_<22=3d$PSp_OK*K#+`;J8)tOCAN$s&?c){A5sj7{gFbj;(-9rxg_iIs-){H{kM z0;%hd_lHi`B>nZ#qiJO!L8Xu1W*TSvxZo53I!#GTUe5*Ej<@HNDuNr<w}Me6(Nyt; zTS!qCBJ<FDe)E(3MX&TCDkp_b;&GK(<G&*rPIT`>wWFg)kZ|jfzuFZ2q>?$kGq9Z$ z<Q)@^sQn?xqK*m0PZy;OuEi9!e+ME3R$*C%muU_htG9`epil-$f{J)FVeRrbZmJ>q zBxKdy)lp33=3*uD!iaDWU7GLsQn{3J7mV)ytseyge+yaPj0&8v`h#f-em5TNuSdN; z?nIm9PIn;@oEfTFlQyrQl+y&G(@;m{(Tc!zdSnuT@mcrg(&ic?Vm#-frk=>CrCVBK zM9>r<{XRj&_Vd46%_l{Qu%QZ|QM{?7@F)@*{Xm4_IimZPYs98~1|3kNr-g_y)8Tc2 z<6(MJ?cA`{?LIK5<ET6&t9fH*(JeVUEIXhc6y4M4nJ@%T*{EnkMezL7o&z0!jXft! zUuZKHUctS{7kx6vb*TvtbIELHJF^9p&y*Lj^qhd&Sd9^As<rJ~qz6DJ`v^iJsUaIC zRJeW<Mdzwb3Y~dARx%JYmimBx5o!TL1mn8rEmOEYdk^9|#ky(Y1wq5+4(|t}tj6kh zJ1H}1=yHPpHKiEaJm8^!){m^W74Uo%)V>w_>D6A3t}g+#vF`*w*1ibNv68UEaIiH# zRrj@d5fzGq_&IeyN&e5aC5i`H$6pG{rJ*KfK@<ARGkG>;Su^4&RyI82tY4@dQGX(j z`H8OxN|#A~{={H9-Bj205>-s#4nhsXvccA|Z=DtGx)pT|S%IPOrr4cRcBDX>&LYL9 z0wOPWf%Y8+I&^`AdH~|5h9%r#u~M>v?;qzm()wk9ILR|x?Nm@?B>0o^877&7Wu&Zi z_DtFx4BJ|HSEPJ<pV%EYB!r_^xd5sA(k7=|BmAm_t#UehmBi^lmv5G^1bOW6*<4w< zW~XcgV3?wYqHg1RRRw+5?;oRC$99iVaC4INI2-R#gMee@tod%Sr^r2KpPO+`Lr++V zCd+`K(~llJo$wg6O<DpQRMhKnVlG{q!(|2|UY^3}DmSMHKaDUr6J49*(C=M&1`z>} zqveLjs-^F~&;f|glaM=T1Qj3?C7+z``VROONW)vIu6&uSU&`(kW$L`L0PEzV*lSI0 zW*JMbTc9AXS9k=1<k;C#<vWcqa6YFs5I9eT^m=M4Fbdj@g=^Ux>&7k&CtxrwmxTK| zliS~(BA!UZIS&@DM@mtH(7WDd;n|_AraNKw)qCgM*%sa(RgLN8B~v!G$y_TT_aipI zXsNVwJJLZ`)RzG9+*<@H#=`P;ASB&;%#BbI7SJDDUYju-<OA6>D%{9ywM0+fSwoBR zHc&?rcR5`@v<?CpC=7Zl??^vJUa?SW#1%Dk4p_SNr+t?;sdq~bv&kK4gV~X~F=FnY zC(U<F_eyYWZi>S4Ujfxrc_tw#1#JosXdvNgIApj2GIO;@kD_DD_Vg(>c19Msh5mkL zI0=bZFv%BB9n;XTi@UTwxThu7@0~w!Sp_25{=g$Ujk|@7P$L#9ry7`q7i&SjOxYN7 zQAjU6+>Q*6X}T5b$w#CJ`ppthoPSlc0f*JxGJ@0C&(b<c#>_(?8Qo>JcU*kBGdnKh zB5!eU|CO$w+h8ZfN`!7fpVmbl@@Tb26CEbcsH?C?3jZ|AE#B6Oba!ZkcG;{egE=OI zRDN9o*530^%`)8@=`?>(B&o`?KsYq&FC;kNc!KL!B(TJnc1QSGY1c{B^Dp9&x04ld z6qdeQ25VNXYxTD9hPqT8ENlZ1llhLl8*PyZ6lLe+we^C%9VQgf<rxlKl5Td%yR8=; zqavJRYkZ1(3A!Sw7b~)c85ODMWaEXd49G#K+nQOxBOBRy&$8u~^?T^0Cd0TVI<Tx3 zH0QYUU%AXIqM0nKRJJ+o;ZEJy;%hz1Ld1U4OEG?HqPH%YHux7ys5tv*J%(VtHA`GL zUrloN0ZP9@9uQH6vI*S3!Vcd6oLj908)07Q8buK;>L4VcfzjS=wnXsJT;PL}p{w6E z!Pynak<7s0%1z8THDS<6V!?=Oy6A-2DK{0DYgCC-hiO;vVhTEVa-a=d#V+ty2Fv*{ zY<7DiWExi<+h$cOha3dKphZSJ3Ql;^`eXHmm<sahlh)PG%>+}PkInEm2{r5nKy}Mr zGKEn2D=@tHV7=FNXjkZl<)BtMa_KjO3w=$(vsFlB`P|8dmlO<H!^h&Z1mf{$`8^ie zJs#FSgSZ|#L}!EF_!5ig2*m-|Xyq<-dZ{p7m*2ZD+CQ4d?8jP?fHtkYz2W#lk-XQM z@$!=XZ_gvjO-Z}+6Ug{OK?4pK;Gqh!GS}J?3A=K#>v`+l<z-srRfs=~l|1VFT#_4K zq3iDZ)N0m|BQ?Zv=SHulLYBJGME9e?_mz)5P@ZH2P9x5y>Rb98kih)$E^LxEG+Z7j zbaOL<f-k{S9^=nL;gxk(4MwdSg%PYqbOc^6{bd%TlyAE8TZ_Q40^j-_6v~eVkq5NB zLpjE_V%>LCn3V+FNGn2jE2Rhn4I9T#R~Pw`3yXJ5+bUs*<8s$K&*B_(hn<kt#~<2* zb;>SlrY9$rl-;-NJ?UD|f5<L@>2vvOi@;Jx#i0+YH}5db%6nbp+MDWAfc_}+v)>C? zC(R`0Uc)R3>QH0h;{Hih+Hm8n*E_$ru4|GRanG`W!DxOi0*1}s=9iUW?BPuuny3w) z%U>wF;Y7D~izW-tMFO@m*;FUVvSCA6@@kK?IowddBtlxusWIjVV9+lcy#HQD0`KfC zkr02P@aLXbq%k99rR%8(lv>kyM9W+r{%GE7jtYqImiOvExWuifm4SarEZc3v5Bc7z zX5+q)+_Gx0Zu8?Bc>Cv>|5wGmT<Z^>pYOE9ZGG$fJS?wlpt%IhjSAgB(>dQOn>kJl z*RP0~Rm6An2SRz7>{=g+ysF+BNQgV#x4(ucwixs;ee-&DV#6kMkbT8BC}JT5qMyxv zKtxnNz|z%o-%A)C&~d&lH}bxwlSnjIL0?WSPtC)|#s<lACx=yjsaSQ98P3tB`=P@P zg8qdtzn8mUgRsyOjm@jBc8B*eaog+GciyY*ugnSJbLQ%;m~R}M_LY@$V{^5S?;c1= z48bOyCX`_Pw@rzj9gj20f?it=7OAr$LD8*wx7%6%e#Q~EH+K2`?(B*^Cf!nd)CEqG z8|3{wn~nU?|DANWc|ywjG2!|C5uZ8OXapQ|JwN+ViHvylJ2%mj!8RJDt2zMWFL((X zZQ{gY)<hKjyMBZfKjDi-&}6ACN+r11=>*;CrERK=>>w`BO=L##cam(mAIOy%=qLp8 zS0O*$OX&qFy8+BXAts`g9!G=9?L^Hzvzxz=%-u}OofX&<(*fULO;#Ecxig^+rZ{#r zWz6yRIb0J5oMeq<f3pwfu<rMjI?5nLboWvmQe15^Zb$v_ys9CV<1aiKl<1GbyB^nG zGxDUTC7ey;p);h7%;^^ohyXQ~63GG#_lbM@+%SZ<4V|9YzBva-t!MG3O%IMzH1*|h z%H@0AR<LdKaZFXuIg>J8In6q^b*VbaBZ2OSmr^iEPZPFt-wGZuv`93U>Xe-;RN1Dy zITt-e1u$OdNPI*q#on-W|0oD}<5jiq%#F#poi4#pP<Hp)w=L1R?u6fa-SU@RF{q4F zn329@M0Xu-cX#YS?I(~<Z-);-q{K?^T&b6&X<Bvx!2yPC!4~lWlIdM`2CtKI*i_n; zbhf$RC~5rt{<+Jp$Gd)jX$Qg(Y~cGrZ!n7HZQjb7#HWsU1h4aHZ!cs$fv#IzNrd&> ziG@o6bc9(JI9T}y4Lhi?qd{eKWei%PKRFhgTZJ6}x)~6+qCp`BH;=pQvQzt+#D0TH z8INBw!ZZhF$kz`b8|X-z0V;ld1CwlvkFbpV>y_zLQQ8&=y^Uwk0S*(#te?lK3N2#Z z(2s+oq*UdaQaYeMZ^~5Y6BevkH4zc|yQBo;tP&_e*)g~JTgUjkWYM@j#k<Sd=&_7r z-+q<=ybp&OI&L9qOt${nO$I3h=d%xmNMA3fPDGN*?X;!Sc!IeLk1I*Bq$6*M%R!Un zpXBH(QQn^Mb=PI>Z(9e)6auzf(WyUkB*yXDF?9cYOj~-cKuhx8NTl1}@fe3fi+MyZ zB_tkbOT#+atb%oip7faLSUNA*;OjN9bnneh`CKPOgQu=rObcCZR*eaJzJ8uHVB|`w zqH_FVHz?f3bnNXg?MYXrB??Kfbfdt!d=bkB#N?@ot-Wjea;_BZNlC91E$;xq;3sXb z^o>gcJKcrSm(?ofvnXv_kYqEXi3$*)8Nm&@0S$R&f{W-heC2aGSo14NlEDlOXPrE7 z*FjcFTz{Cl(l!yfpV#>27%G*$gFiaIC>|9az++QfndN(jf(%k!YQ5lx`fz6FD6JQo zSIvEE3fx}wVdByd+JmDmanl@}xWzq3tQNa1+(V(QoD2;?#4_A>el-MF+vPtzhv6Hy zM<bJvuVZTpw`-;no)*up$n<*QOqH(oNI`2MTgazwAat~j=i{<;u|jVV(Qq^KSt}z8 z3RNE%r0O{d&|Cy95e~dbGi3BR<osZuoO!N<^RqUR6HM)^9Xdoc+m2sNy0j@1vPrRB z|Jq@4bBP*>ZY4NE@YP1Io9V17F%Wz1hbNiuYuwvXa@mzOl-`Mk>5}cPrkfpU*(RF! zZb}lLhg3wMWu9yOG{Q?i&(4*eY`_;3#%Ieyw86y3IClx|7@Rn}hZ$`GK4;R)p@1zL zWn~0Mb0iKCgy<5UwU&1vD227s1gpf245{HU4k_kGXL;UgJ^pZm2Iy7!qC0Kohau<$ zr){sLkfcw;*q|=Sp)_-UDZ4fof<wcR0Ysy#90N<X77|TGW}L8N<|~TMB)07rv*)_^ z<DoZ*LtC5wQPtD@+1+};-?OTp;sgAv8>xt=J#fZyUP(O~x;BH&YOo2}`7yOA4GRl4 zhzse=G)*cCYqhG-#FA7`rbl?sS={x~><S9_Oa0B;r$JU76ic>^K{!~@gv_p<u(dDn z#nH^S<ZKp;9n@MvFbkp#I1wCbaa*&>UU~BkW@}Y;-u{8F2c^Ro^+roT*F|B@06v3E zEf(ZUEnJF)BYqO*QL=FQ%`0GMw#5NR9LjW3$!DFN$LNOY4}vW@8XQ&3@DsOcJYVa2 z=27t#p*ksXhVyJLoum;Qup($MB$Ut^KW?B1O`?!YYP`F@OUA&uV1Yvs)_j}4@`V%v zhU{x_>gq(n2v^s$4cHbSgAg4TwA9_&Qf*^^R=|LYpP?4krO;nc`KMWsP^=z}&*v=p zDzc4LaH8kE=9KYDh13CrkBA_|GX{_k5RUlT?CBHYn@?=G=Cve!&tMpU!KoB}v+aCy zaaMc^JKYw;Rqx(9Rxg1bw9Fwm7e}upBJP_|;YRKY4B_lxQgw7j8XM@H($U66S|OQr zNcSdf*dY27m?hr84M0K8eo}MSXlE+;DJTL@93}Z?p;{XajX25iLmV2%jmtQ^#JoiY zF*$^pb%wvRxa^jldGaUovP<LGpK>p6ibJ0J{>nHnHdKs0Y`kju=$dsGw-BaKT3{@= z-I@0(pm$t#4P7=TJ1lr}yDxn~?G+Xg6?(3(1B;-lP|Tu>uPSBJ*DZ&<)|iN|R$SFu z6v=J07<U@vK6Z7Rvel+-H{Gp89v2WF#zep3Wu)xhx(HnCHaexW4jaVL^^8SeSCf?x zb15yY_zf<6JpeyW2uR%oFRkxuT8(O!EhJ$C)*Y!FRD!9RT^JA(+jFJUF`wjX(PUV8 zG+VS)frA@x5No0wr0bf-*A<d@A=vydP!v4FOJ}8s-!xFLjSP;;=d5jBTd2#Fz4M$I zILclr+V0jsPii=KHqd1hpCGDia*m#u?+9ez*x#!0e>j}T*sAHpnl$dH_<d*7<?e<% z1bw%#y*%ff`&vx)9`;95_s@zge$I`%8`rd*&6!m)nl8E;`LRo5XyZwbyC%m&$O_WT z)iA9j?`zn&067phNV}$xgg4%VS&4Tq+EjR4W8`X(#Aoft=Bo!I{TFq%H;soycg<0s z<NM{6n6Y9)d5I8%5+V+Atvm+X;ZO_``HCA1IDwz~qg!0AFd&-QK!^egAr6m_D-pF- zS(Wa<+#(MYZ>o4dFPnH{cgr`3Pau_d%-!W{cPta;1q&cr2KxSr7%4hHC}4>2dzmc- zfvTY)G4ab7U!Dc1iICf!LGs;N#%?!C<lyV&Q1q>J%lRyC8CJk<;!45Z?S1oke^o7N zwAU{Lg4Erdo=(WHR{s&3<PKJ{TbZ-Cu>#DCn)FC5Slk||D9FmQS)!)EK5Cx*&2A;C zVqVx(>82$59(3R}``gmDo4PAzB)vjD-E&|^49AB94)v!LJbKv?#m$aav#obau?j<X zTX>V~410w*^!9$Q+rN}r7Njz<W|(bVV-g6Py1A_}8(o+h$=bCEX|mHTMgZs1_#H$F zv>*SyccE6+qskUz>Q%!6K#?O>k1CU3t&QzVKJ|`CJt<T7iBMUOut2zCc3U<Za8AxZ zFWREnay&R}5V@YsOs^Qis|4VtlAm{a`UaGlx`)TSJ%KV4O%XCaq=^G(p9&H-Yd_lW z&aabpUv9WHSBrRACXdDkdWY71F88-s79&rJ$7{}tM}4gG4<x-Q5*-($%MCxj#CbU4 z(uSj@4X-9)_1^33(z07M+R5o(CWzKQLm{Yel`o@qf%M)VZx5#gNb=64HPg~Evkme) zd=`#Y6l!(GJOn6KrvmJebXsYE8gICHf}?}&aVnlK-8-rjoZbLpv<{mNt8cZrjm%AL zMix?7NsYipuQ1e@#cLM?&^2IndBa~DtRYa(a7CoB3?^E=zlp^mt1;@EDWbz%=w^JB z{RLAW#pvpq5A8(_RKTARz~>6nJcIo!(j0>rh(b*2>aREUUDdP=x;WX(bf??7&Eh;a z+Km*%Y~_2{lZ8SRxp-M($#_M4O5Q&8bINlY0TgoeLsBlXn_{aZIrP9Ch5DMf3h5b0 zEq3XaOY*Z|qb`~0mKgd=mrij&Q`HxpO~qD{la*gm<{D{#OeBp>yM?{AV+$J!5sZe$ z^F7$iO7DYCOs_j3Q4WxG4Nh!pzCm+F>zt1?oFBcPi8tO{hMc%@6T9<-JZy>;yg5G( zsCxoHAff<xg3diYHJC&LBp*0xW#zU(OLay?36EIu^r_mGB*s-zU@b?+NYHb)zq!tP z9x<mD>`gC<Kuj1xb2+>E1=kMa;LhHt<OMFc*s8X!wsf*JvkkYmUMavnsUVPOL;Gn? z(137aI3I`U!9@NypJ<@WF+ZOBHHy`DGU^}rBwIST?we#CF{Lg7YTc87je&P`(3pAs z<@Kfz0nL2ursBiCTDS0!&M$H3FG5kiFo7XVE{ntd@v66uS7Isb4_cpxYzt1_s2oZ8 z4$-V@;<A)pnjOA<YY#~3aHt~bvZ1<aG-c9tvZZgk-<L9zv*jWc_d$zWUtDL{Ygb$8 zvn?XN0u$YbzHP57`$cPYt7Nk}W{3|>U!v;vcy84Ywt;f^FIet2o!CH!z<BGyz2{~( zghIQ46(Nv}9>3?K9ieO-OiL4AlmvBRUq#rSTZpW|n<Tq}0g9O~jLBNy20*Vq<`W=w z@2uU{IOpTKS?S|v0s!I=;1RBdItJ~r8vvOVRfQH^m=jC7=vu$T888Yh-ZAf*k^djk z-T}z6rt9-9b=kJjW!qI<wr$(CyKLLGZFkwWZCBmu=Y8M!X6BoFXCiK#h;vS6?%X@~ zJ}cv7#`>?{G8^p@VW~YknkuGyQY2`NI&ih+XUQ+pZac-(0WL}yzv)q(;Eu96!$7R7 z7^$Oc0jPN7HvakbTx@ty2M-s~is1Y{nG~qNT!S55;cjlup>$VVV#80tB-+}|vIidh z$3|vm3(-Cf^tuKTm-#8B;IUp&8w&0sqi~$$$Q6dJ-0kFco3JaQ+jM~|9JGQ>8G<Hg zSdEHDY*MKsL|9UmOskn9TL4(C75z<;i*{k`0692|Y~P+sQfpdiP5<uR=eph%dMNR* z71rcOwE8mc`ZVLfT?y}1EhH{xDgj@ny&()pG)ejDAvZ+}_R92~;oY5QzBfBA{!Y;0 zsH_Q&GO#5Db*mOs#I(}pUX5}VbqXF;y^VG2*dK{rVB`A15~S!-KUHUT+~uEFc9KZ6 zu@qkyef0x(@4}N~c`etf`o9gb((#t7{J|7Yt!#!HZY@i1v2Q6{Q??eNkc_c*Q^*d{ zz8~Vqkou0DB;{1nSVEi;nzU5C!>((fi^`<3Q0DRyA5}Yc^m#_Y)3L?#Jjow(t9E#} zczJ5uUk^kd3jNb)JevkPRpeankZZNhL$8=TPNTPYtvLd>X+<&4=2i*Ute7L|`AHtp z9bVEIZD!p(S?a))?r@gKxW&P_wD0Ph{a?Df{-+|ZUNG5h#7Lm|JPN;8L|jb=UJvG1 zf9}{Y`G!Oj=+Wb*rY-Ijv7U0ji8QOJ4CHTWxjExn@9QAIr7URtwwd>MjP{o(!mBsI zVV`MADJ^w$4oY~}f<eEvZ1cQ~bx~QIZzx}59a#g_F}ehV)Ba872ArvgmIjK5slP&U zL-M5AFsEMiXN5Uti?6n{ArR)sJx7%2q2**H_IL~~x<XUA7ns;-xT$=z{s;>fN-JdU zZa~y3JQF9h>OE_dezQ_@u`l0WLZ#DW%H*;Z6&KHhj+vR86A9;~H3}6Cl>@%_2iD?9 z<{_nrHH_!WK{B}7Gi9(X3YYn%oi#pBGEaB6HUeCUr+3h+qdttGwz_M^a-c?7*BI^3 z_TIwHw(i2#M{7>Fw5nrn^UK<1h~|#0ZT-qvoJ#dp%hD5trVq1x{S!D#4O_9pgs`8v zS7to{2jFUh9)>oNoNX?d6r6>i?^h#@{u0+ET5}5a*L<d~bjK9wr*!4pw|o;O)J-*7 z2yn55s7)q9J6Y??bf@DU>vK|xA0Sv~yK=1eTcH#?_^`i<vO%2%UK0~d#cyMJI7^Sm zylO{BE9mG><8cXMZKSB<J~ck-yC*BP=2-hjb#>@FQ|-$*RpxrW0BK4>$^N^d;;$6o zuR4H@j)CbvN{4^^_Wz4yfd2oNX5haR0+6)7jGWC3j7049-2Nvm0sg<V1pk*>f&U5Y za-rqoiZZy$dsGk?NE!$$00Mzp7Umy29YLt6_$<5gCd(HVR4$5yfL!2?K&cCez~8Z4 z0{NTJAKYIQB9HG_$sK~=BICulY4Y;>m6b{DhI<%o=rZ>9Y5cgc;x_&V0;H<Yg2>hi zq$;wf5ut?zC_*IXE?`0)Bi=D<9qxyZ)S2pr8;>M=!y0r?>B@yd3Zhen>ckTu02=DX z5gSnvbXin8q~4V$X(+i;acH8)C-g6`(@J$|Mt$*a#itMWhr~h>C@0OuD|jbYH>e_m z9j4l8oGrrncK0E+iBOUc-H#P`W;W(lDv7eFxiStKxV)}gDX(GnT0_}GGo}ZW3s3x! zxU#v1-H^<n5~8D!LC(LuS}wux&1LC|DJ06I=e~d1P`>#csR=>pdVR6(-Z25DWipSX zp9rONZwvxjnstX=EjOklKs~efs!7q)X6jSeJF-{qIln63+RhJUb+9#iPj2+Yx(|$* zLVd6Qw2_<$&guSO4fS=hLQ;bb?r$iY=<Ev}>GdWN`!&|(7A2U;S(w+q*B|HE_uByb z^m-mkEzT)Lx#S8LmRWVSjo51*>mymjYnPW98y7!me{OU1NLNSA6-%NHc23+Y)d#0{ z@yjj+N#fQhi>oJmBo_gK>V!jrvi6Rb>+}v!#UTkv;<R?->9z#Q+k7&vs=i@&jjx|V zJhn5MZ9J6ZAw?s}?u^V772~_@du-kV)!99RCnO^=nOs>qynf~5*0!#`=yB0__OWQ^ zyOovb--A<>yi(vg9hr$UEIjvAb;X&A7IStDM30+VC(5D8&}rYVcuTW}xg!KxY>F^o z!<>vOYi<(d%e)gE<=1i$^YeYxOpY@^5zCB@SpNCJShD{!+UVOq$sdr{EHUXqY8ID+ z25`M#MKY8WPj_2Dx46CZCLR&X;Jr<N;54~Ma>$AF)S{~iuzmhpd~&i5x|CJxXB4xl zf<3D2i39OGC$8Z?m+TZ4=&bIpuRxc#c?<}A9T0sYjg5k_tX#mXN|4RYR*u@SMUN?C zJK1iL2R%3xI{9huC*!6w&r)sEEnHvNs#`Q6#$pv((*v4weZ+Zgz>q)fWI+$mc|k*K z;YpnfYvRJPXI9VUy{z}FT3_8PMhaij0PvV86ALV}Mr!ga=TK6*(fiLOpCIl5Z@g?k zeLS|N{?dD>#%Q<FW{E+AQQ^_=F=zm{Y&K(0o7SYcd(@?ZK_g9CyChvNe|bc0?ZFoN zghH`SH;JA@P&veDrtnOfd{C&<S{;3`a>*U`_X)Z*>O<<y(caD&i%VS`ThuvI_OCL$ zGs82363mNfL*#mr0^TbVEQ+{${HszhG<1z7|GgG`1l-4)ES7GyFoIGh&FKPKIQ@&8 zC=8-yGK9-=!Iajb0M<W;B0$KICfyyOI8NF*QJ<ZYrl;ZU9-Vy59YuA!fHke5SiNBT z*OJBy2K<eVaQ8dH<aLeIQ2v;hH-bMj=!T6(E7Ks87|S{dJGVUARjs9#@b&1T+^r<q zlwTV$M=&==i|@-<sKhX%@;5g(QCnLcc^#smKU(j@0@CD85ZF$+H!N!?wpc~_GI%Q^ zDnHYiqRztdlm-*ttmkb!!v}9?w@(9SNiD5VhbfJ_-dh{<^Os&!YWL_WZjgp2_?IGw zx)^dy&6wgv&waa%{^+(saiWZM`+Lps@0*-`SE7&hK-7NONjSodtC!zaLwd`5H+Wwe zR=VN82)(P}j5jQEjh!A0iEe=ezFiGd&y+GqG5GWkxoN3Z2}k-Sc)@7s0NWb=4nlDb z5OR&~|1!=Q!sH(u8;d~O5X<<Tktx~9*KSf@Vb|A$gfpK&-|=oVX6TkC1n0)G0m)gk z#y=Y6-}Xj;w4f0nO-pnlHTWAvvQSNLm^ZxJAArhs%`53S3&?55<S;mw*t!`PQ;+B4 z*!z#-IanPEm_K;6xoKXJN=Bh6yxLVzKkbge5Ad1~+<Y-&)iaGCHjyUQMI>&KJBbOo zj>zq6!PhjinyL~Nh`QLh+5KL&AKXS&`iH>DZ)eo>0jv;!W<Z9vOyfj<{P<4T!>XZw zcT_NjGOd&59eibbFEf5ukBK}#!2r3Zvk?`P4ZWNrvCM<L*~fEHtFQ;(fh*|zAs)O3 zpM<?<t6+YC@%#Yhyv}qkT?vE>Me|7hBHVbI`;0l27j=!@IwcYS!b&SY9hy-7!w{tN zqI+j{JYxw#=Tb`~(YkKwgiTBPs{Hm-vD5K@#h}pslye!TxqN797>uKCm6rbI!GvO~ z0qLXm_kyIRCn1(bD?=2Mq&N(ZZ#clu=c@_*dWP|uYA;s|B&;0KwZpFhX$zE+e#%RP zpUxa%C>2(w@o;;GtUfu&=M#OCzoY3#SBkP!(G6;(tH$nHu7PZA?Qukj4WhZG*()m* zoZ5us%V~{#uPIy%y6>aT_WgJar}R&d-_2z#ReE?j?_$t9AQK-SacSZr+_80@l-9@n zp0-^%56FgpN30o<SF&!)7M>wpMBZaI%ay$ZnUj;Ghj?{lZqboBWiWK4LQ_0&nt2w6 zcU`K*&F71DMPE3y(tWLinF*Lx7B`8i7KST(dqB*!$QJLO`;Y|cpFU|gR>)@2|C$c5 zh<`iNvgYh9w0l`FQOTGA67E@QHLK6Z2u+aNbv^yc-mUd6JQ2}iSCof)2o>f*I?+YF zoW$>=xmA8ygl25;iXZ|SWOT@TTt|4OA2rXZ>)$pFI<p-1vPShld}0GEq_E)aMb(dm zSvy@wDuG9|rrkKHexggsWx5=XfpWe|w03tj|1rl^IB-O4SQegnaTPy5RQmbal#pK4 zN3n_e2OMNo3;uGk{S1B<x{@Nl?}$)*;mZrdkMF&>Pvpa1K?lO=))YnchNYe5T$`2t zS7~!~AV<O{yY)RH0hHc!sYFl&`=`1Gh{fXyv0!3#ODrrj0@F~YHzyoR)yz*GPa>bW zkZuW5I-YG!$Hx7w9m-r`TH~?G4`oX&`qxb?1)Zck3TN9~vRZx93qHKE-J69oMUmiH z?Oko*o^X+z4<2oO)G-R;)1qp59kbLltq|a(Yi77rA1H3O^<eScT8ZE6R}<N|^6TnV z`_1JyyP#S%BFm@>Lf7+Mr>rFmStoI=PdU0)&`}2@#))uSzW|%hsd-;(Vip3MA8_}K zG%vG#s(2E4qRF!1<tFwbI)%Ovue_eVBt|j4jB~)NDA9t@vPd`IE_|*zPr_ZjOTeqv z-I0$GR(#t}1{iqXWmJhUQfQ)+06GUc!%Xrat`khzT;;NOui?F9sw9)13mkL?-+APN zyJ^ZkM}5Awx87NeOdV#<)VQWxEJ$(nDzPCP0Uvjr1W?CDlsjv%T3xa<3q#W&xjfy9 zxM~X7OWBV&$q0FcSx0X`cV1F1e5k@O$FO!s`O+9VKLUwyV+U1<#gQ7!DL#j?b#9?| z_}D-`!2VdmHzP^~`5^73ON#WJK*D7R+rHdm!PY{BO^xB~GkujDyA1E9Hf<{pL;Cbr z>)$kYF%bXe_Ecvg@3q^YaBpwvV~zDZmqDX^J^2C`TLaP!(Qmh;B*shDzD80-7$^Q) zm8>t~bE^!_(J>Hxdf`YF##mgrjB@#f4vu*q>mP`0w7I$6%N&9$uWJ^yzt^WLl*Ma( zUDCV9jgk^KGgN%7f6iF?^YPl)ub`!8j~MKyZ(uO~%kqU(K{HV3DQSb`EFb_|bs7aG z(cau3nvzsUx0HIM(6kO_E=WQLqJI?C44kowvdcvkkoA4%tva7}h5&f2jQy=$v4!bR z45bY}TL|(m-ZJGA)1~7=xiZZu8;eU+g#ND|Hs#j^p5IEeL}eonuk<E7V6EpaNa=H; zW9E%H^~8&Zi%Ky1>7CY7_SQ*2)eKH$f)i~)SdcWzU6$@4MKoBAlW5uOB%LE}S!{kv zq4O_s=C);;k<SKJD4X4n2jJ&TwHoQWJ1(aufoZqB4-&j+y;W3zZo4W%&!6Ly+xz`G z1e722R#5&`0l>mbwOZ4w#Krj>TXS!EVRT_zjbln)`?eh%GYT>0hkGdP;m)SbY6(aB zsLHzS*z?5e-98%jNCYbzbJ79$2|;a60&7@OQcnz<{SDLruv{ev8BMVMG?xct3UeZH zHc*lGwO@1oG~B3(p2x+<wNrG1Ke8Uybf7pKc^McC-$Z!?ph%*jFsJIj7X4w@ef7DZ zUY~~(Vj2(?G;>a=Tf^wC$ur3Hniz-6^gK&w$G`kRRmEHD%0)>L&V8v&JZzF3xVp+B zyj2vXRmftl=QVy<AU{1slGnL6MWAb=lsr&Z!HMO|6;9c5(v{j&9cV@K%-U19Cy%`F zG?a1dVtugSRB|04XB8@IwMZ9G2PqNCybb!SIc7(oYf<A@(Ie{oGJ?X$ED`ohQD)HC zr62@pQmkyd9#|#%I8=n9Ou(sF(|#n(>jfzvt+%tX9!9uB`p7$1MOz6U@%t3YZ?g^D z1I@RYrVuvq6Ao1}UzEtT0=$;6DiyVx0X>04V|dS{;Hh3+Xs+!7DtA=agS*EUekLk% zPe2y?&DUFBktW85f>wJM>se7*HFAFn$}58G_j!klLmV(o)VdvgJy!~81w|8nxdgc3 zUta}#J@|BB71Z>jC)b)IXPidh_J;f+RDr`V#n9*HU^BrEz_u$bcU^w$XPkmY_4435 zKA!LJ&cSDfyLhw*YFH2Xb-(n^b5Ke;crMRV2JZ1Zp4`iby!*lBLGlM6LGSEAvSVs@ z@Hrk9<!Ms8vaDRG76023y4L2?Wk`;LS50iesj+3kj1iCA)-Fd}Sc3g@NXz!(MJdt` z<^&PQ9@YyOEf#{yX5k|b+Ic6JyqSJ^^vl3m39Xqt_voSXDwU1e_h27A-_~)N2P@~s z>AcdBw~hVgyO|C2+v*1+mS8A2m)qakZ6OZP;zEH@RKOz7@uoMOt2sb83hj*?xP73h z?V3{amTo*53fmErVQVzVuaD8AJJCR|%%C&}(@WFp7;f_x4~5y{YyKe+y8JO|lW;=9 zoig`2N>acg48djJ2F!xNzJ*B`AlS4t91+QXCMC2Q48~suM)B#<QZm`>%~hKg)%g~x zDvKNaQH>S(Gs^Fw|J8ybzvz67G!LIeXw@ei;Q{q}Fw*m?R)()~3CLDa1m~z-{*d)2 zo=61oNXdA_*rwu1BR~cdY>5bmksg}xdOk6uU?HIZ<(^h>!DUF*y}r|Xq#o2`P(3m% zJMp?n#8L2kHz9uA${ekmX;vRW2w(O%9WLhmnaC0J!DdV6$Lv6L48341O#=hz8qy@I zirA*`o-wq9LX3t$Dorzekq($S(4dan3khv>A44L!3RXzYvCuiBspE2D*@(ka5n*vT zh3t`0D&O&spx4=a(!>m^st#>H^bO4m-M$*!h<S<>Yx&X9-Lh^oz9Sa~J@hA{jC&UJ z5=hbuE3_q9j#N3gTh4Sj98i-C1E~pfc9pE)N0pxnekZJL?3yQ9-o5Oy#tB&4b|YNR zgmW%bMp#V5p4P&vt+&GF8Za3F5P<yR0KH3kPtI{4kz;9->&$C~2{5i`GmT{u@O9gg zA8-T$5@p-xgIZ(gAXQ)=l8G1Mbl~{W=mtAf>VEE|hSkzjX{RJN_1nN|2dNUZ{oc%m z0HCR$(}8V$%IsNE?r`PnFC|d@e>$zrY-b!d>o*d=!Xui??&bYU4N1L#ovPT2>TJZx z+8|~0-z<dAt5eEJYCCsC?7~$DAb^7yS%rFzzg+KFsg}Vpi(u2K<@2ya?v(pcdgr+A zA&@Ny_L0YNOr*DBG4o@Sr4mWye5KKWV5D?Xr5U4iVIvk)2LW;bamE5`d)BxZ6yy11 zSm<OW1XYNzXk^+Ynya)Wr&DeLQpAx=We>ed_Bt*pltWjLm9{|;uUsfa2Vc=@xwi|N zQv_Zg#C~brMh#Jb_Pi;kIU^klEYGl+4>@Cc129`Sy{4EKYGPpGN#8g1bFMboIqZz7 zW**A@Fd>BveC=bJ`=Qq`0=-J&RVoa9)tytv1IDPEvLa3)#sB~>CATsNG7U9XBD$~w z;8fLKT2@!7sK*Y-bYK&f;Fq@h4Z$U7VndmyDBUxc#p{w$nV)G7bt^zemRg{6qU)|( zOaSXiOFv;_;Q?@gPNy|E`K?x>q+~G$tm`Gn0jYG@FDS{Ss<5;!8gsIhHti>k4FUr( zq)oyhfNHU@AqmhKG|P%$>9vT&yCkLQSqu5>yeh@^;O(#HehKA7WSTfvkQqj#3!SBv z3IXuPnK$o*rSb#8xBHR_pzNpnJw;9;i4dm;tIJ0zh6y^XaOZH|jkN8nw+DEh=|-^b z7%*6A_e3Hu(6-wLTjfuH8K#q(Xu4SuN$gODofbd6Yuv~&d{#Z%1tlcsADnhn@oDyl zdNr4%r>hYZaTWU8fuTeQdtUtvwi&Ojx)+vOJf&=4{P2nKYV%C-!@dGbF6_J>!T57u zjya$>$I8&8Nx9XN1*B-TMMGX={*kbsLx;1gk~z~z7-BVH-|@{eNTMGo=MEkgk3SKQ z!`;(`!M#FXnCuVulP~6p--t#o`1y*HnV$*K5ABhk+5DBD_n+$M949^jwq#SW@7=Aq zvkg&zgS@DJ<@7kDIdAD_)@Gs-m!pI8S`C6QGO%_B1d$nlQE#ybzr>&HuA7*_%sa!` zK0QSv@%k0XSYeu9#>azItTWJUEHEpK9jOn{nFNxcm>X_RDLON?W<OSqQ4{;)TA9JN z8(blX3x;yn=%0mcA@WB{p;Au2M{6Xk1sCC#b0jtZT9=^hRbV`4k2*Ynt(R4hMl}dc zJ3YeG-Xkt!-<n&f`NB?S+h<DQE2rsHZ!Qf#=@CZC!0yE}4@j-KbH|ax`I0m7utPVr zC$riRhJhu@OllRNHxI4K3e1PYt$VJbW4Dd3i4}1H9DCY3QY|l;1LCX)GA-eO;U3>N zM;e2XECtbyh<F~u+i|`D3ix6Lc9uk~@l{-(x%=W{19++|K_WDtJ<4L6Q8?))iu95> zZd?i0h4E)=0=FG*&J(H+0z5AmNiC=!g&^t==EPX$ITEWI43)8b)`Q0V>Nl|H2<6T_ zPlP?jN!XMTr->*>xQM>4z!AS9Ghj;CANn?oYcfsK&g=xsW##l=zfl6}I-?igMp0o% z8k@oORN(Ik_N)>T1~SW70^ps0@Z&LV3ZEcja<uiXz!MPQEOFk4MOD-{>gy#ykZ1mJ zOsb|nz3ID(E%W;lyb^5~<SiQtm6*4Ed7FC@7MjcyE))f{hJV6%B7!>R%xDPXnmv+Y zeVVz`)n-h!90N{nV=x(v(p9S?huh~KiUM;GM-i2ClhucGZ##XdU9498Za{u&+K#Uu zn)SY*FjT+=0OneS5|}GI)flM<b6tFBA;xU+%sgv8^Y!ixlZnd0i%(;X0a};k4JM<@ zy#kMQoM_eW8+qFq`PGT*5JC}4Y}i1Ooq_9Sa+{7rLJ;g${fzGD&<87Ch2;(E#i|EJ z0_GmUd{xY7pCiZ|Z;1k|>o1g@0qZ4Fr_q1GJg{$)t%)_EXDWcUX~*o_zY1*T62vyy z@U~w;Z=lp3aQK@h7pcDFakSQ7FLF}QHk*omqS81rCcUvezEa;dI|EF^+LZGXg#H{d z>Vr@vAkK8h{y_lvcO4*OcmCSCNhntSSnbq_-{(ws)WEZzd(P6!Qf$g~9PTm9rxP)0 z)FN=_=mQSQJfe<y1@1BL``L$NY6+Noh)-v>(bhEZhY8W?@PYH-+2#yz=UVsX)I5fJ z&ePk{o0?k@?s5O;gST>aIoN9o*qRr)PSjcVG_aSyI~EBErSrn+>2v6|T_?tQ3tdry zbW~PwzYj$`J*D%$^}>yIj|0YP-CkdcJQ8<02b&9?f%5stMwLkxC>rPA>RB!KB<+|d zy1&&%*dPczL4}GD@&()UTkc_FMh!MgRazPZjb^~KtJkHCGcrGFuo_E#206w@fBcqv zn9rH{0;ZCO=l$<qhkv{Ye?1H=bj)=BaXT>l4ZQqc+zt%?4uO>Zj^m`||I2r`{*F7u z|F;uCUgSI4^8bW=&rEVrR9Ha`nd)TioJJ(XC%MOThrplZ6h#4%3l;N~1qu!%b^i53 z7#V?F*-)_uP$Y!VKnNKsz+Zm};uc<Zs8{Zn(7{H81;kY)^WA3J$FSPg%2D&uipiDN zQX7EmyFW;uqbi^;Q?4rV<yo&LBGUN46A(H)Agn52&yKM%h{*FVp!xSs?$p#0(V_as zOB!Fp_BE<*SyG3^FP~UKRzYG=07#()7A|j6v;&|7h5A7ZhA)t@`$TevV0s4BT!_31 z!o7iN%g5qF%J$KeWYYayOtndj4yLS#cG=A|lAZhrkX+3al5LZGPcWlSMX@x1gQuT! zbI%!)0CdQyI)9Exb1g#|gpe^VLvMiqz!L`8JM3Y@U)W8v09=bq_QOCz#q^61mQu_P zjz^4NZ|W6Z^yw)R`lWV$yGl;oH$X?xq4`$ZBnbhMs9B|&#$HrnUtFjy9-6*%uWaFZ zD|~Q|xW6ggke*Lv@keB-ZCRdI&~~B%JQAy?<J5O0DgiWDf$|;fRLET61Kj=qXxPlS z!wt67jvLs8CW8t;Keu!M%(kGRJZ62%_O}`94rYH!9lv~2<}5<v^&=8PVKfptC@L<J z`1R)xG;H#e;l~sF*Ip01*~Dl+RYrCX+D*{0lH73uL|~|Cdk~kOY7C7bWT4N&jt@Eu z85o9lrUkO8lMaAa5W8%P7}$snH-I1!FtIhSJCN6z20T6FNLPnxWo)%WG=ux+(JLO5 zW|;MkBtN0T;Ujdkp*=|+6-NG6pk*%*VhosL4kVKw4IL1bE)2FWqb=|z{&)DBC_Hcy zFpVgX86QX;KhH7%BtQK!pmTt^Ex^2=`!tBOKZ`A>CWuN8j4c$juLvJxaIXX%;HIA$ zxc@agN*;e%3~B*fs=y*VmO8kbAipddGVq{aXbgND-^(;<2|7hUS+1Zg_dSs#W*fLx zz-tcJG(HpP2cTCVLJH8F9?UX8lkZ9mCpNf9-}v?~SCkAew4Svc@fK7b*ycX89jt2r zsvw=dcyPWEaNrqXRdB4EUji|z#DE9{7O{i{K&3)yF|Y+#t&yU!cKg7fA-Q@f=%_;& zdm(BOJNn9ci~8bp3n>OE%93b@EXMGRelPxo`U|y1s$><s&JZjJ>5<d}%DU0I8a2ta zz{`5)oY=6#Js7*#w%#r1nhe&=RUpl9OA+n9XZ<icq&Kb|6r0Fb{&2kx*ZQ6WU64N5 zKDb-acthP}F%aq?7XEMqN%-ITJVkg+@FVb#K!iRfIlmGaN5Wuuw*gIk^4h57Zv-1Q zsdPNDSTHe~JTZA{gP)?9IiVIQH)$t9{3wT^h&{R*pSDaDaW=jV30xenY{E}cWEpX6 zA%PWXcJWp|H$FGPLV1`H>v`3(l(tNDna*Ec;$E~O@r=oL$$O)f@#V1=iD$_kBr*w0 z$u7w{G}&Z21U}-QMei*@a=m=L3V!)D%DKWj4Sn1}VnS(oiTc0w)AU3219q7Q<w!c> z{NkDsWlH%@YGz3a2{6C^$=qgJ8l)OHR*hEaa70)O-sa*@2Ji8XJMSTkNQ^WNejZ>S zU>?+u$%FRM={_^cV-!ZjN3=&o-!UDwPVG&tu~eIBe|3;2zED_GcqS4i8YcoKMwdw{ z*(@M0WR_W#$;{K4lbY+9ub96r(3D3`6;HWjO=apZeeJ)8oYu63y0^TVKlGn+pT=XR zVRm6+U@BoIGYv6gq*<qprX8dmF%37EszWt`s2`{wHEPo(re6M0G$yGJXV0yyx+tce z;VIZC=dLs;saG}0m#&{g(u$+eVC8StY*ug)kddHOrPZmHyUOK}%dX5W=oabL@EPlw z#$VM9=TGk~$qmcx*2~h%-!UL6i!Gm_$XCzj9AYzQvJ1Q6+0!7c3C$FX6N?;`Qdpkf zRMc&oYM6qyI5Z_?DrasV&Z}8hQ>zeO%wg~68u83`OMjt+;tp30&qUoo)uFneQlLJg z!c!wx`=M&pa9Z=)zdDd+p=IDT9BjU4P(N9;aoAW{O1<UWec{EKrd6|n+AiHb^$7b& z_(u9h55^th8qx{-wCw2ovpvvj0paX;r)BacVh@bWgRFK=tavL^ZIXNvW-=cN8tocw zo*LbL#%`wt+dh`YkS0RM)i!rtX)SS2{p|IR)KcV;^MKXB#xnQHN6Q-}oCI8~NceC< zar_bH6qNSw<Z6{zmFniWC;cn)t70Awo=~1h9;7bku5vHhXT1-g59im7yQS-+*QGZZ z5H^qsh-1hC5MdByFdird2*e*wApO07z3u*Zw6i+In)9eY0`G#(L0k~b&{`<34(K#g zOckW(ZY@f#-mWen)cQid1P9thqeo^(M8YFcB~V?2M@0sO7DS|kJcN>kB$8FB)av(z zBh(}Ci?~touuwdRo$X7XW;Y~4_Re=9_bzD|HIwSkSM3`QO2?<FVsv`d>?m-t@Nl-^ zze17vN)IHf?sZyS4nUUT+e6;sj)o|YB5$;wjoxEHk^}1kXMQCQXoVVxRf(a9?E%T~ zH*P!C>D>D5mnOs{<dZX&&Xi7=1vWf4%n6X_h1F1MF>;f2()Kgu(+ReXnJru@A?5MS z#7h2jP%~~%iTad$5RD*CCkar4syDCOG!Ze%9+UfnaCpC;wr@R-GkQ1r=FM!(?BZn7 z<@_1^-phPx0b3cgSf#nvD(#}x+qU!2brx-fZzZ~NJuW;RX@s?99kw|ymm^oxrE6M$ zbvPu@Dj>JhNj<3nYdL6%VtKJ)TwiIvmQ1KU^PoSz8@4M$vL1J~rRJsbvhn9J@S?Nu zvGC1h+Zo(tedDC<PBm3uO?zd!YFn%F;LmN|ZF9TId6%-DhMg{)S+rqv14Bt&r+Brw z$U^aH!Koi+blPF(sYmlg=IZd;QumgX&m3SR@E{luE;4q9&&ZRkMJ2!0px*jUMgP=U z-f3I6iI0xYuM5$e*eQ`9k;37=Xr~3v`6bp8)&!Qm$he`}J-cC>kL?FR52W%FS;qX< zXAm|5_M6?|XS}N{Xs#8vFt4%`vXAV?rfKys_1wkv#n7e#7Bde?kF68mxlEi%9BSV5 zFVFjk$JDg?F%yZY*h!R(boOi)?^}VPpqubev=9yzN1nEZ{n^Z_nySrlzvOD|n^ybM zwa&M9rQ~vxDt0YSuS~Dbi{OvQMcnqRB%O0_vy;XvtIiYK`j4c&%BZd%UPrH5Z?v0_ zZC(daUzu3I;h?XVG+iEF+UwjWUYj2?V5M-{yno!;K1@Fh&iC@jAY~}B%6Kb37M_=k zOFQq+bCz_c>VKO=2e$~)ekHzC%k=-4DxIPfZV)~dsT7%tc!}6>ue~3<9*;<#+Y9O@ z|7?0noGH)tc6sYG(H|YSwwO6f<rUv7>0*Cfe6%_;Jl>ykF}o@%4%;m6;(he{$bB=o zAC5gamwA>+%#P%B@q~E4btSbjKHPc=ynFla>(zgjp?{aA3@r2v|5>m8WnKKO`-Xss z2?`46IT#t@|Fedb$JhGLF@I?u|5?)h7o5c5{|z_tm!;wK4aoRLZb+CJI(+j*{?bjp z&-Xv@JQ)5v@I+A0QP0xG<X_|yhyNf?l#T2i%xtXjY3XU0{)hhmP(}XdG5tdz`7i#5 z;y2afUxWR7Q~zpIR}v7C6{1u$vodm!Hgb`-vC^}aRghBr7rx||k%NJ~nXRLZJtV__ z046p{)@J|YU}E?;VMW-?-oa7ORL>rt@p~~ZsrT;!)A!B(gBtmJyUcWS_)JVp-$yV) z{{7C%#E8$r!1A|@&%pf6W%>U6pB~2lCLI*R|7AWXt=I|kemeNTEB7$&q7dCd>vWKa z+yW5KV>qWbfUpKwe|6M4&+9dpf&%h;x)2+c`iSAdTrca)NX3p2IT!5G=1GvOA$HRu zr0hzh^tgzH8*#THumd4Lhi1vxki`e0g+_b|9^F)ZRnrH<A*8Ls6%9J<3eLIHv*`md zR*$a<;C4}YCK!xMyGx-L6=ph=l{RabM;023mQQU@nk<OW?PX2ElbP%N#KWBRR3U03 z1-$4;U6aqsN3{OZ?k*};sZ8Pn=cV6mRDSTXBo)3f-^vPCxWJkXGEV@3I(ZB{znBU~ zp2i;n*T(CB1Ub^1-0(ns;Theb-$@}ZDj~T;d{OPcT66Aq7H=-lUS^7c)p!xLL-YPO z#{VDc4g=eN?bZIfVgI$0|FVOB*@d*8)%RxY|HF1H^-TT}c>ZDF2z=9bAT_9&S=jKY z8R=NR=MvL5_lAy<{TrYo_HE#12K?40mPX$bf|lRG;2(|*`?u}<z2@HnH3L1%_x#bb z{THkTl7;mfR-@o(WTpJKhw8r(HcTvkyE~iw3vR<i_k98>J=cGg80fw&?w_H2?<tKK z@W1Wu@8tV0l+HgD|Cu`fX6Z2e8+r4uBK<e0hnf9*9RH_X>4k@ftHxmC)t{`&W+SW7 zBtwlR5;u)o!McNI40gh}JutD1ka#xTLi9De3^WMmEUvWqA|@%@95Hg3X?es|(4T(B z8l?Py>Y6kSAx%uVK?(BW0$AdB1yW|)4J5UfHcc6P?vtHQ?OPvb-gv9p^~Q@8scQAc z6KTVnn;mxJ0Q9j4eWFTVuU!OrpFl@`V{gsYj|FqH9)Y4ds_YHsUK|%cvgy0bH>fG+ zPPQHQuhhAxn+Y>X(R|NT0%D}+)VFsR&RDlHq`|x)HQTIfd?<L2`B!VZt`18dN7F?; ztj{%g0U~q^zq3e~?)510To4Z2CWa100-Xp=&R_XHxpB+PNr2$eLyCw7b_h8B!bc2^ zrA5qp$$vJ<<4-#}16Nb9r=Kwh^~{-CC@1NDY4<;J+uujizWOk|8{{lJdkBwV(yT&1 zaNHbKzEAaRc**8XuIkRnPZH6!WQdb~RM~-$=UYFgJ*P6Xt*?i$^5Y!c#4<U!G>y;9 zB<MVkHstjP$pHHO3rI+S3KCs_>&J8f>GIlMW#vLGv2Bk0VCZb!sR0*JY_iS=_hZvF z8##eByfg_m4f9duK!ut@?CZ(Nh^w2>Ln$edNBBDmeogZ-xqKQ8v$ndLSJfyqkWn@f zs(5HRwr)28Bp*Kg<B)4@xBHjFdGW{>y+>$;Y<On^okqFbPV}<EK=37wkw}q!RD_9o zx!4@3Ga3`4-!;fK(>69AalknO1N1U58#H|Ak6bKxAgX<2=ifN~8DMgo{&XPdAm@O; zr_T*?wt55~e`-jC$v#Ru!_@*`8SBX1H2dAfe3Bjq^}rEK+<cbaFZsEBE)^X=5nb@T zc9DD19@7*&eYdC-&uXloHm)C%d-__5BexY63G90SC;<d7bN}7|Uf2jg<`-SLu*{_B zMYm-(*UTP5Z@hr0u85j>v@@}O04#CjRP4q{TZ5gjA|rHd(%M}~IxN*)>#2v~`unC{ zs-Hf+NeYe5{}Yf40JPJ_f0JE{pAC==P<I~+{0Rv58o3?9ohm@lrKT}do;AX1!Ie!J z$1Aupu*|^nz}1@nAuCz|l!$d8aWD7}x#dm=FvV3*3qgPa*w7v1EV?EulTn@bt(q@i z9Rez_IUqGa>;qYt;AQa&P@T4ne(I&3UJ6WjKW1%N&}x>!LIE)2oRnpS|F8S~l6Eoy zEN5)f)!w9het%gYXuwCHU-wO5j&SX`)4-kgIlxN+((s4{#61uLGQbuwb-q(TJWwU5 zveY?<fn3GF(@^L@*P0gx84^ZpU+h`HKl!am&Bus=PDep-=zBB^{)nc=G6b9j+5#eq zgLC`B0w|ajBlJHLbR?)SCvHJikZ^rr^U03ibfEh}py~I<g))>S%m5oX+F(Qq<w-5n z5`wU#TMcKqg&c9SUOjWwnrv=&?6_4Bq^6<EfRvRfY3}bmixRR{xAo3439><ty2D?B zWdPBAN23A#0t^6<V~d!k<^nuL%HiQh1#$<#OmGD{pays2ncDl#kQa%`8I)ox#3P7@ zE5o!%Wtj%Yy9m4tr(5!7m*As$AUzCQ?)YQJEU^oo;D{GsTb{?e6<QD~+JSw!u5>z5 z6?qyM9msUV&YAlCva!QE(7FeHn~u+L{91Fo3MH%OTYtm`HS}lh+<Moxr+KZyy;Ka5 zfv&{(wFGmsIM}5`PZ1{EAk|?4Z<5)^r|Ko#VS?m0cwqs=k4rg0n?Li0-gToLHKUq~ zhQe0TyClZFRl(}Gv%KXyK+MoXb)APk?h`&wX<vuTKK&M(+srx#2M4$G)PDq;Fw<N` zpGtQ$neT@st?%GA4lOngL7Q7gCGiSk{Qk)I3otw0#B_ZX6b=eNPfb6GL7nD@il%as z!=ub763*^R&yN1uH_r(V9SPw3693h;>z(u&UsnF(gHFzKXv47h=mZ;~9PHx_`4cNs z5SG9T))nQtpIE@FXG{8*_1^oIz)Lm3hm?H5(E%<Yj`_=nW0d&UkYXzsV()?J!&&Gy zwdsQeu_*gfXXrMDY<C>^CZMAWVGFFOOyBSi&Gg?1?dcVcDCDSYHoP|wnsIIl)RV#! zXE9wIS}n{7`-SSRz+$TzF~xw1w&dA`3@5Vb4rGRn@jrek2aS`}Q8a`<D`tpMmt7mn z7wCHlbip*5X5VMpeVOcIY}(xdHWK4HeqE~FUttpaNE{Kvw(77CEhO6F!I73;mAskU zGG3yE$KR&~dJv|}6YaI?%IAoz8_3oHY5U<i;lWnf^AeP|f*I}WmpqA3tm`Bvw_ZIF zWZG__dM1VQFXj&~;dA0<oMfS~?_1xIkk=U?FrhNGVI4$X(v8f;J5D|mJT>eRqZL9r zVRM|)h=hA%<Z+!;X|y%$nB_(tA1A5GHmfyjx<p#XS_fANtK{AtLpr{+S$0a%o-jUO zxaVtEFP#c?=8(Of8=g8+^)wr;sD~0!bJ3IJVJ2^1{4BzU3*~zNGLDWLTn&08sV~w0 zPJNkKpAgLFA)l;XAqm$&`5HCl7%BH!$R_{2`4kf~QHd*JGYgTZWp=?KN(gpdKiG9$ zi)!DsTdk73kAFPCJ?JMn4z-(M5F(lyBZ#V;$tbZZVqRao-2&;PsBI>>zM(zZ`>D_V zqdvjwLZS`PDVkfEj<QOz{6-P-#`)lsB<rj#3IZ#zcQMJJ4_@S^%HUpEPw-4%y12P% zfVMuCP!HUaxDUYui%cjZ5_!fh(JD(F>%6g~(Wn9((8N7!a!0Zz|46Awi2^CY3%I&G zfT#u{s6e%{T=nO^C0&H0QId>u5`T$M<)1kI`LSE}xs<7pM}P2LEdv-Hx`-Fd`Ex-$ zlX3G$dQ7s69rT--mQ`4#H8B;rv_n67$s2I@Yt7t=ucd*Wim!0YW7n;8%2y4r{YC9o zCxGel^UXF65e&7<n}|x+coSFT!z-=L?zFuwzym3_93eG=X4j$DdHb)Vjj8&#{UrL? zt<@FgMLaB1vHQVS^@FaY=jZ<Zi3^nmr{RO9w2-g#reHUtiH^#U1^cf>WzH$@l;(xW zHS;4YZfp-#t8%X!s@2UI<|4BC-3fHQsNo;+2y=N$2a!|uqJoSI><s<sckD}ZguSmu zkOPU(Zb|x}*Cz@yiZcWCbYgDGq$5eC6&X_#*KJuv(b7g@_!<Xl#C-PZOAVTzYYk>| z#yv$78ciVZ)|-6}2)+9cG-fKRsMKfjgyIECp$|<1<ajJ}&V#2O`?xwXW>frjvbgs! zNwB!cXk$=bP!edk$ocm3Xw;Fo$b$AGXcRCw$QyNQM>I}&$jv3)t_~`a?lksXgwVpl zL>`21L?J|J)EaCnkD4<#gt^70HKr}5GBclf{X*(lc3Mj_s)jx@I^oNxs)QR6I+V$X z^1yr1WUMwjI4dA0VIDAo!3e<d(71w$1jfg7rl2cyYyBzdL8=MVhTM_?R*C{ks=&w= zb1aMJ%s6!9MG$ik@xn9GrZT277E@--xK@cQMHkbL<{=G4tDURB>iyam+L_Z9m<*9A zDTcQxWs>v?A!2)ra{ilEK(;tmE4yK099H3LhL(1Wxr0{I%`L63yMEMuhgC&{v(X>) zgW6sGhJc2AFuD+Yf}dc0Iso2a&zyY3%|!2z+Zw)h(t0QrdCVqKP)q#S%(z7C7498n zRqpPHEjC7&v}#F1l~A*6vx=Dk@4p&`mJNHAGvkU8KGCm1w`F{N0GTS%l*$wHY0IY5 zM~VQ1n!)AM-D=2dQbFN!*PU5xAVGS1=J4@<2+COnB};vQZ!`p1uKv>1;?tEMO?Rbl z@T*hcHM~{_`gKQ=@o|K}ijPOefJRW-3}^!2lai6%mecAt5^teUtcIGDPgdj$kGCT7 z7_V<1B~3IH4?!ghX8^ave@UPczqd~}O58l1&6my4Bpu!N)mod;h(NXw^EO&N;$%qV z7LqX})}GlRWK~j}2)$E)A^m}%$GMWo0ZKz;M!H2JGw0+80YSi{0WN^XQ%A<kpHaZ{ zV1MdV(8a%*J6KB3fK|JNL^+Ajzdz3AUQNO)eS?*(Uzfop&^*JdKesI59NxHVdJ4)A zfK5<6<2-N}ufbG}6{Wj&XLL(_T7XolQ0g-JR4azgCzVasj&J8L37%M?=HTo4J6lr- zHHK&3JLx^lc*cw>i9&2bd;{*3Xy1zf|2^geU&Qwh0rx)5EqsGrTt+YM@UOFD)?)&$ z>gjG%?GVcgL#Woo2)^48xko$u2<iMe5Hgl7Aa_;aBtjcF_TP`gqY$godyf8}zBu!W zQo;%=<Q}IRieU-yG@>op?*LXA#Y)@!P!+$eP@x7V(oVyhb3-UcfcHTzJ*4BBbDrQv zcum=}nuDew`b#YoqKh{DsN5~XisFR~F))ZVMy2-C(HD+Jq4sU=iFyGh_jbe6G?<U% zT?CuG8KCNDL7oujJF)T;@Wr^uW+W&da?s{ZfZ9^3@;r`t(h9osx)B@v(ImdIQ~JF7 zHj&Sm(-eu!?XTx}EB4jvFo~|&P2a5VpX6={-9lGOvz2p1$mBi+^@6AUk2L!1cBq>I zE)Zx<yV%^^Z>Qq%3We=-7J%B%{8{h<P(Q_SVsay@3e%6T@L#ld#F9pdN$WWl2RPI+ zF7%&jzI1t!Si?dFSeYD{ywU{Qx<;|cbi^8qy8yIwIYC>+MPugUK$oY)Rp(%0Y`~|4 z>mt{Mg-4ThX<g!hmq*A(9rj6XF<)TZ;E4E2&={)u&(8FmIFFOB*JbdEd2?uIlaJT# z1wX-sT*ZUj2`HGLtokVQz_L67k^01T;Ha`6`op8P-Qbr*y8FtA!pNnVvsThJ(nK0~ zXA)11&yvo3+;`3gZ^LiGZKUExJ4UA@FVo+9_uES?<eT}t@k;R%V;so}I`CLr;in90 z2J-hq_KWwE%POuE{LFQ4*cF4BLFmop+?kuC9gaQQz^CN7mS&AyUytqEFsJBna<hw@ z=V+(fk5v|qc<wLoKVZ4Tj>un`vX+j?Up-#QUb_H@P|+(^$P&N_2qLmrpj4osf(Bic zAp%^310(yCBc_S^T5KiRM(a}GKAWPgbf4<4>W)^*&$ILJK?h^d5vmbXLYu>f2UP}^ z2BVp*rOJ&P5BVqV)RUW(+ZEfDJ+dEb9^qD@I4Y}v+pn$KRGi2=;c(AHj-L=BPKLW< z9@#buMp120rS-J;YX~N!+mJEmATup--VonfjY+tNx$a>&#ujU^<hS&#`goV|JB3}N zQ0be${hhonamd`n9n=|Un<y6z3eQB;DBY6Th@fiqzH9K$^E$tsZ=5IaYW%)P%#fSr zAa;b-oj0;xan0trL}koyk+lhMZyI8Rr1g}qkS~RDvmq=3Hwq*w7Ce6~@?CAstV4TE zAv@35KbAe?yM>JQZP{6_gH_)!WKyC+EkWtIgX2CCQWKk;fHM5*7T3SWc*RN^Q2vs8 z1kWTh)NMfSmBg}5b4_(SDgPt7t0{bncHSV!Mn+{cWiC_0k#Qs)lO3-?p08AsDbX!v zPh{M~Edb%EPT4U^Ysx%I@YJ`Jo$Z<AVL5S@woy|bq8dX*s#Kuy3}H5~?g}P@c9~Q@ zI#<)HRUqCHZ7C5sjdJ~Vx5N9xADA3M4ymIMsSd`V(-vIlI*8l!74Q0sH+adW*oS~s z4$gQHgdD|fGE<+DOM&+N%9@K(lvN%sroB;wsT&`vG#-A2@ddx)UCN$&F=H$DgKM41 z2P5l(fF8V*`}z--?5^MF3UTmJ_&%8;{u;rZ<exiOI~K01u6gx)TbRWXH&rAZLJRq) zIOB+o-T8~sjRLX<*;5YejpPE{ps$TI@fi0y1thep8IS?>=jG&MDAj0hDVKhmDN>sr zycbj07o@B!fzQ-5laZ2ViRbSCpUHWPmQ?CNtBa3oMu(lw#rSSMoB9=y(o{|Sh{Dxn zc;ylWL%Gw~gmlc&(|HcpO_NdnOwcZqKxA{+K4+J3${>mn4Pk61kW;6$kMrbno89?# zz=qe8D+L(OGCvvS>rzmjg`Q%}=Pwap*o@eWWt#(Cw7ouzCTPwm`wYqFPoBU|De6aD z7`E1+TAx%uuSuol!9RUn#W3G8wPh3PfqIZB`Hb3KHaDG+4|!H+VQ#kmsva6k6lraX z>vdnPP5eh8jfJ@_sbx4XSk5|x3@4swoLOnEe6|U1h@(%hWsHsRk2$~$gzlh?)xG6| zh&{tt;^C1eJJeS{cWX}svPe8VuqT6Cr1L><aqr-}qp49^+eg=ccTA7^<`MGqDrp0s z$G7E1P8OTh7CqDJp@%bT)pp~DvP9tV_GD)oP5AK14hn{RdalmguBxUYcXg$bIzsfH zw3O60Z(#?7)x%n<F;`>b6LuVR^_I$`ab}Zr7%=Xc%0vtu+u%)OR-L$mTjjsK-5$>& zvy$HUj^99XRc?Ieok^m1cMe`-oPL-<XHb4cGA12HXdM>BkqHo@@XM5+%V}H3a*MTD z%AxJLG>+Is+bc&-sqA?yv|!j(qy6BjWG~m?g1mTWps><ViEesqQUp0k8C|Agg+r(G zH~eENFdvw*n-DTo;y|iI<X_)tCyDRQ*jBPXN?j>l6_HmG{G$G*{1Yd<O<hA%+oprC zWctwCtySO|#hA~CV8Wa+tV!+LTjjd=^B8930s~4qVly>i<aU#92+~bx%Sj9JOc19s zjM>*&1No@Z#GXew&t5a>^4+j1JaX56ygyY$#Kk=UIJ}KVZt>uNd0?+Z5W&-`GvCVe zSvo?2vs*$X5a)&_=#np><?^A_OZ<t(3+>`e>r4*%mdfqncvTx(a<fDLb!%5@|6nkx zP&&RtdCJrz`CKWFhJAA>jyFk47;TFo3+rxQJ5>PzJHEoKG0I52h!EpYMi?~b)-elH zVa2V&>&B>4o+h6Q46P-scnesp&G6og0}iw(e&+M!8~9}xCO-xlF^oAlz0OI&>`#*$ zt~m2dyu$bj*!w(gveh0p%PKVUS^x(=wXbZyGL4)uT^u0|0g`ZQZ;jt(9P!gI<2ze5 zg}+9;KOvkLF23eLJnV53?IybaZKpO*M|(Vd9X5oKp_~fG1;Mx$1R~VVn8xt|J5sX! zxrE!~NMXkKpoh`&O?-<l{y^37NAed{98tNGQ@#MsSNgf1qxTzPE6&qS*5b@2dAikA z2Vvsm5oFM23@b|hiN9<M;VW{bO%(K;Mnt$1{B`k7<7lOYyNN*=zc5L8Yj`V&Vvm7; zc&SpaceRFdDNok%*tSzBPo?=6WgG`Lv}&QOOgiDiq;!Z~{t_p1=ci0iT&Y7xLKqJX z%YsQEJ>5dNBVHngN<lR|twBPgOCKl1MdrA$NTkYsWA9aDRMTiy)6C{fm!Y{~>v`<{ zj6p@XQzUF-pFv>=Z>qa{vxHeYV^mc|Q6vh#EBP!vN1J{GosLN|qC=z{^Xzm7XB8Fn zfRT|K-{Y7Tu<Vj5(df1FBMT8}jG6(%Mx!Z}unV=?q7!sAJ$E}tJ0cKDnup2Ya9He; z(;q=m$wJ7CvCxdcek8U-0~!*L&ao>FR3gJ)6DUglX_vzuQi(~%K#_6Y9Wg3qabv89 zDp+AV*15doMGpGO=J5P;#b!iim$T&7-1fv-cTC#NyF<a_8K02^Gb<>JECZMZjQWgr zI$)8u@<0j2y_^AYH>oXb4w1Ri_W=9EI2h>&4mb)H;_+EUMBDof2#Rcjr0|oEp<&a8 zZF>@aMea3@YD>?O{;v!0*!9oRZxZ12M$Ba&{nqm@0AD~BSHnO}h-{(c>y!q{;|{}t zKdzs86bJJi4i-_iw|!CaVCCJoDR(m@4i|exR6lj-bHm0Z*RM(wqs19#v(&8wqzIsV z^2f@0P(~M$<E=&xC910#xXX2?%B<WI8)=NRxO(c9l6XD|?U9AoN2oE9AWs*t-RWzq zm4#p5rr~%_-i+W6{kKolqn12MVyY?gO$X+-LiF>#>?Ot`{V2-<Z{{XxXeoBpWraDo zI_+d=NujjngI+G=n0m4jy~HIi_mB#JFZQZ|yC6$!93jTy*f5>QIb16ey?_~>Aae$l zI?IRx7LO<l#gYXy^Yd>@1PJn~Vg8hCR-1k}u=Q=p@?BzWufaDQonXn1H}PxouxQg{ zmn%IE^%6d}Y_{&wp(Wkr_$UfnZFB;f_HmeFJp_vAt!$(u<aK|gX-n!x@0;C~2yPq+ zK)Pr4E7&O}7&ASy5sj7mcpG`?R%jf(rR2^2Kb*Y<aNXLLwQF|Fj+q%_X0~HyW@ct) zW@hG?nHgecW_HZX%+ERZrcd|n+kbbxDyjCaRg$)(IW<+g#<#`<2R1e8P@^DHUn_9X z_?CY|{>TrCc`52=&rbgYAbTD?yOByEy^{`nH=yH2t+kT(#fH7qeJ{|lldZkjJd9ou z8p+Yh&OMkA_hwoXTN770W#S~E{JuZimbV5u0NyfXA1XRl>U+WWp~x<A0X_{MXeU(i z*>-6H4BuUUWaWo1yn|;v((YG|WndR50{M5x$(7J`^l#>a)Q^mjQ<A5el2uN1R*9XU z=s<#OlAS@nMk%mWi%!2dL_*x6Z@m=rl5!^FVbGC#e25A~u;Z}tiB@WrxxzjH>DEV} z9m3qY#UaLUM`%P)#!LwBYe&S8ZO?#$%$92C3rHM$v2{ktU|%k=i`nt{%H)`-t(o7c zd44hJ6rpxm>I+N>@(6(1huEl^7;fodZa*3&IMXOhX`g%!QGC=Jz*g#Z$?g_A?{%m2 z$ToLjtSjahZy;RGT(rk;oz#jDAQG`*c5}iwcQkD>&oJ`kA;l1kpF5|yf^tMKtu}A) z<62cE`?7kDz4QW5@qSqcM}4_JzRt~dnBH_f>Ts*5CN0mB)YQ(>a?u|jER6evkz9%( zr<o_lq?}mVEJ3+Axj-ADAE=_*+{KKBFZaAhI~%ps*7>I0zs-kUdq|vHdyFL&JWl;p zQ`57fqOvhxuDIP=XA(Gm@Z+ZL<-py3waHW|p{c6f{km|G#G6yp`nKUcb>ni|eB`jV zRDwkc=f^|rM^~tM$2WOVjSvoP8(RN5mInc92ALm-g5euNQ7d}rBsJ4|&a1+wV_Ero zk10bl`d=wq*x<fPL})#{hOZmvwlg%+Hmqc9nJU(&TiI}dDjF|Yppz8WkQh`z%zsZ- zjX~*o-Xq9VqP||7UszP&I9*=BRJNo&bRfy5a#z!Le=ApXCxHVEzjrW5g;@?7NHeue zcT<YA)uhfP{KRcB>1Rqt&b~4df>Im@Gd0hmhV<yPAe?n2+0t-*mzJT@8kxtzC)7Kj zubd8F_ekM4{%VI0T+NU)cMw@YxYpV1qSfXcn$z+a`>P$bqDAM|#kS>@1Kof+X0Kb6 zAbqd(Sjk;DGSMbBH1V=^cKJ{oNIS{LnXH_w$-Ew{KwfT)!&P4>1k*3}TznNri=v8o zk%yEAgY%m6+lz88Q}!c|yxm9)|ALv%21j8G%ot56UfLC-*5&n-WvCQ+X~jqlQV+u7 zy$y<y_7YG9feVd2Z11iGXALz2=5|$Aj*M2*FzG=Bx+m58OHYdHUZy|qVl#|i15+`= z4QkZ<tcEQe!ABzuCuH(u%{0tZls2cyqD<$bkoeEl3ulko3Dx--6^^RL>B92k9&)Q| zbMQ1&m(dzmdhpFz1^9AJ5*`GeC0Q;~Fs`}R_a}#k9oeyn8yXyi<b{MJqrMWRo>cXV zHcl9??tD=#X`t@4a56x$m^>rP55(Wh;iQDR#z`G%=^Pock?emlG$dxio_f4zS1X!6 z^k`w%w9TYxtDH#QA|o#;9UiJI87?lnJ3yn)U?T3+n7xhR862WFb98)qjStW1rZq1i z&fagMBgqxx#tVE@nT4#IQc`kpsZ`;m_y!3D6@f0g;$|?#i=Ft0LT$emFK+LOj4r21 zsXWY;=}xV@8(<q=!Tf-pn>F{VtVuDnbtH~xJ~|#l?Iz+9*b4@K4ELea1DqS$ADGQs zsTJ)I)`HbNOB!@3c@8_In3bTrrPvqg2v)~0pkjh{D{U=R6@4kS<qh-~789Sn#nxGF z#zQ{Cy2gpI!u)E_dajiW5fizkI~-l6R+xd1laW~L8BI<zk}L0rAFK$R8CFt9O&bRQ zOQWwv*Tg#-UBLu#gswdOU33w&Zc)(`ir_2UPM6cK6#PvLra=uk#$fr_U#v-cV-aS0 z%<>A!{yABL7`cf>KBHn(?Tz-rRJz%N2+Sn%Riu=<*xYx(Jr8|F(P^=|O5}9mRHqL% z)qX~Mds@;dE~&E+>KLkuNcO3{2uM1hpRimtk!nx#(HC(2dm9uC@ul7<##&zJ{Og!7 z!{y#PH}~fHZyXw6)yLSnz#qF)dtZ|K%K_Y*(}2~St``8?A5)lKt#K1Ho^=G?)OO{7 z9_iE5zDBp{p$}krSE!JSs773>;xbg$Ay`gjPJU})LDN=NG2Nx6`Bkn29O007tQuCY z!ht14`g8Yc)KRMqg~rxV6*hSGyrOJ>E)D_PWzNBq-;<v|bd#p-aErdm!j7?FlKOh~ z*|dK)$%<!|je~PpHZ~pkWm{S8+cy$z3a6)JNe}1qA7x8iogT(g4GQ&cj^0@vT?hJX zf|$6e5*zf9$f(A~?3wE{?U(50QlT;$<-^p?<c_+Uz($$_2ACXhJjzs*Zvok(%xFM+ z5o;QJ;*b_Ar&yv0Nk;Z8#)^4LILLFwU3v3n^%&E1=RlKS6JQ&?h%g;%p2L7rPnmrD zK1c@Yf$C*fLGxh7gqtI))dt3k@N(*TX<VFAw=C;40(qv=z-lgPi3D3nuUy+=Z~nW5 z6S3`cEp&N|*gVjq`2HZXW6&NA5<{gG4&}u^HS72((4a9e-y29L;fE$}FvBeSUEjML z!a!#o8!Q`i8*C-dN7}s>kAICnt4B2LZX`4<JKA5u?qIh(#J)g3?4Ln#@=MKi<|V>_ zdE&uS(y(k3&hw=urfa4M`psX`3Yq7QS3T_R?<po?)^)=}gM`66TbRHKj@&^1kd01n zZ`W8`INGC3kL1WlP|=}8oJk7Uwec-jI2s!bv<_{#M>`_lVauB`$D)6qABtGb3knRv z0cNmR?3M3_1R|xvF}pf__>#rN#ft$c<j+UjRCv#^5gfb~jFNG&!TKTb5X68w>70FW zzF}j_d-8qsLe$~CpTW1DW*a!S701&M&%Q0eiK}akY7hR1GLhunyg2^$lJZC~vn|nw z9SSH2C_=M=DP0$)pP)I)1WGK<O<GUW7jz#t#O~#wSE&HwXStfUQc~-4QAKt-&%D+K z7%Mi@e6?%XI7$|@+mM#*7S~;^Vi67Gl%2L|6uz^a^V^mn!#<OOYj43oPg!_6Np`J^ zJ+U#&SZ97tzGH3Lds+FM5pAj`H{D=5dWX$UlqOa8HAb+Zk;hNk^U4H<eCW<-vfhzS zSQP6b(s@sTp+Z#qzPD|!oA<Gc5K-BtP0{fQs(sTt?EKLgU1RF$)KtS3Ee#7c;;ib! zLduo|`XYbT00~K<wjeJheh$VC3|{%fT+5oNag-H(^ggK)G1|C8K~_U1AF0bhCLE`J z=v{tMvszRH`8brpQl>Q0$UqXhSv_(iJ!X9Z28bVlMh5KT?Z`F!{7j1b&=qs~xk=x? zp;1kKVYvF5Mm81!ie9l6U8(4lVw%WighS6@uQl}9qS}GpSg4=`cGU@gam$0O!-R_U zr|$a`162MwoG#-*+oXugBaR1Q5*0|Y!LA;VlU~WnJ0EP~M5k~*T%k+`4U>UB0H%>+ z=CDL&2zqsC^*0a#7CQ!lBs6Jcj-Dig<MF(xYL&F{yeiyr*l>R4&u++bC@A))oX^2| zP6AYB4r6u&@j>8GZCUiG^ruev{PA-g54)|<6*{8F?+Gg4FlEfi8|4bRvlH!(bLxGT z5>}ThC8&*xn_ZO*nl74$nH~)^aeD~j4G|iz7@F0E>*T2>=euqF<($fuSsX`gm!(*@ z<$m;ptOr>AO}+)U45gX%IE){?RBKl6tw&Z2t41q2oxOcV>HE!rPpwZ2^H%#0f)2{6 zs-ZQkv)Pjx@5Ia%%!5aL<%1tk+cJrni3QzTAzlpo6oIp3<m84~GtfzUwR@(oD+sF# zoM#JhDmZ83m?N0O`mUml>`AiK)d8?c(8;Idy2KgP0!~T?`;;|P$8xoOGVnEhdNnH@ zC>XT@H4MhsNm`>?Q14I!`X#m1_9!C|gKWIDl=ZaXf>A2a`2O&pspcp6R+xy+cZq6j z4)0{WRBfyOixSq*ly!F88Fzg~_2@K#D&UDX)Y|s3GAQpDep6XI)<%S@<EsK63!V*j zxA3<D^sM~z(^$ttgOZfFm%+uo#N+w98g`5>o01|wjNrTh^=(qehQ1U0dkfy89bhH> zJ0oOuVqWT=n$i8SYax&AcH+5jr`fNl+#ENvK&|&@5QL7m8pMy(Swnd}{ew{%nr$>E z+YlI?Zf<qKC~y0~trpiR$B(-uN8@#vB;EoPsM8!*ThjNtRg+j5uj;+KlXN3b@%H`B zODv+GnFGR4Xt8ot1N#PQ=9;`9ZT1&qoANezx55?sjbp2nO{+^5SI2QGA*n?1Op7D+ zsn32b7L`jR<F*Zn^|{W=_dc_++9Q;DH4MEv5;G53b4P1}S^`l>Cn9(pJ}MTuh)oOZ zZG^Ku(DyU11i{mmIYrQ{uFRO#Hp?AyU%6xjZo>DsC|U`G1N)`U?scO5)v#oP;q5c* zUgx_*`0W(fQhL9Z_FZ1euAz0)3fXLIPm7arh11!ktjl`6hi1V9vt7>n=$?E*aK7?b zY6S*VCdgaLoXZ^8AStF;V51LZ@Y#KAwJ37SfKm|7V`B0(lVH^L^z4<$EnG1j%#|t| zHDE8Zs4(z2kqf9Jk8*}B8sDm4_#$2LCXv<K)=oI5GXqWl>pmW&xqk9;t|7luEj$8K z7&O(h$35Io>fABNmE^WpS&-`0`rKDzy~aUfUK`Av(D7KN{jqgJQNm+?q$x})?ZuJp ziNo?0X;VqhYOAO}oxj%NsC*%6;rl__9dJ4d^jf`(jpt@0w)nm?!Zi;d4VOXgzk&Du zP^xUKbj*LK)W4d{{o&aDL3;il5KvKR88sm_3VvNnJv&ofN!`!paDTyae?xze^#APm zrtmlX`A^@t{{jAF_+<b71O8-WVZvi#X8x~$=O2T*-+lA`iQF;#o+$R&vhROm>@;J> zrTXyT2QN7Lu@-xS8VCA-@#)N&kGi8(JOLp2iEF+W-cB{4R#zIqVLf`&@&si+4{o%9 zye9hL(E2)Vz*FlIN78QZa+-6{N)^2+F>#d*xlqHc#@U>Az~F%Z|FUkWC0hA)snZj} zBIu6qzxxUj96c+Os2h0&Wqb>PK|+jH|I|W?oIM}WWq!Ame%e-#ZGS>@)hQStk$`yy z7Y7TLT+A4EjYvPuD3>uAm&>BOpoLcPuFxm2D5iUEebKd4Sn;&pGU51>P2t$PQi3eK zIp!phjDOK_{sT$s;Hq{SO>e98029T;L+`&w{;#|AJIM45tbYRkSA70^;Qx-`KO*`M zZ1dm7``-YYbid<9MbF60h)2)L%!0>2N5}F%BAaZV5bu9NHa}tJ|AK6Oro(?nHa`#l zH?qn6*$MGKA)9QUQwjeQvdQp|`GS8Vn|}@bx#B<h^AD){pXv13ijnQ}EdIA-a+K8; zk=I4y*?c=cXBMkMY%)B)Y;EH?S_@iTf2~`$84wXiWGGhLwY03T`8L{v$M=mglq{s! zBSwh(Rt64~3xs$<9PVz$eJY&N?>h*;Sck*;+F=Q<$3w;@+vWoY&qU^!ri3qGp)U|o z-3SO0?}Sb<4~H9@=5`an(36DN^f3nWRRFyT89g3vgdPb8o8q=G-8mMvbkfW05R9r} zX+E5GEK3ymGSX)Y^B~--kGCO&doIKlg=O61n}=j}d*}$Aq5#q!aQ^|(mK<WFq#R@% zAaG~}UpOOx2q+Sk1<@-4Ws#;T=xo-0VK3gy+{bIlEm;Ne&Nci|^X_cVq<KvWk;vj| zn7R4M5^R8lJ~bQj?%HQ-gCnr{Gk?Knbc9n$w852o$~B1RVgc$L6!IgO9!nP(N=l$= zhE`o0fACiyOkz11qfes;KPh*4;=CqtdWibZ)}%0TVk_UvjoJhx{6sk<QtBAPm5i}B zsaT%-)pkS-8cDMfPF(4>O&!wi<{yUkQG^r6ovzpQY#GHX)wFYZy>yC&Eb27tTrq*J zxTM%HtdTjXow-<&Cd)=o*M!nEKW?xzzlsz?JWC~maj@$HYA%J$3ym>lY!K%u(%8B( z4LZ<#?E&)4eOL0<aK6R<8IzH2-QiG<&urto!f^d)nI&uQI2I%ITIeOWSmgjCq~3Gn za(uM4fm2X7eDSsIVDN#*<^Fgt5?k5!n^iQ-QB;=|Krr((r3gJ?>Zby)Q|oRDrCVC+ zk*N+k+^^isf4f6@0V}|F!2<RJR-aO7>+raU6wWEsLt=a|&i8m5mp~?R1%q`g=V3~R zAj{-PwzkOrAi>L!{sxtFHm&U6Jmr68128kP{CUd%>J|DY=l{>;U0hX7Mp5Wr34ba+ zYYPKO1;~G?^uH1QziRN`mHxAo|FbIpTg?AA^Z$=Z|2bjeH{$=FG5){y{d2~Dp3?s- z#vemx-HQhw=<L-Wc?9p<;lL}RSSo@Or{wqoOq)TKk2Zx4_x=ESOd=PA>2l$D$?A2y z!Eu3bDGgaT2$FY`WCKBg9so#spgQa4NOD$GnyM;1z_4a5-qUiU4?vC%@G&wJXX4+R z4g=hYbmmVPcY}!KCFQC3%rt;GaftY(5J?5=#t{{}%1!7OGM5wc3$^8-1Q)`ly1-B* z{q(CMefKs(1MiF%A4#ChwTBXPhi9#m4%&mkDw(QK$YSIEN2XsA%?3qkB3V<3d$FK6 z;K5aADVm;Z^#qNLqz(GNiTHou_<uXL{uPZs_wVnB|NFZB{|xkJA^b;)|3}1sGx>O* zOg__ZCjay8@fRXb_vx$qKNfh_{~t^~%jY}cZzlhfsQ*s|{$H4UhJR)9{~Gvn>3>q^ zUzmJ0=Fd4O|7(TsaC7%im~Z%4anE)oiXWChxc1?kAR>j(CBe6i`~D?nj3_l^z!yLk zF(3{g)Q7W&|C<T^l-+y|Q-xNU3FxNQ5f!O187y9!x?2Mr@?4|Z9e9o2N%&xu@+lSH z{=>SlT+I9V!N%ml!=N?nNzH?rdqu;dS4M}l%Fp`+D?1rnh*FjI+Op)aY$Z^7tE-^9 zEEm@?_}Gs6qKEy&E4v9)fraOEWsB3$<OU~#bFG#21|qFOsGRtu9|T%PGg@0Si6_?K z$qjNcFJbfH!h32IBMXU|O_9$<a5DGh$7;*ii!^GGYSV3v?g|sXXe>=P;V94})neRy zhgZvM$F?K4p%1L58Qp@*`-Ua=9DuQSdc1j25(<7q9&$82XsaBiIZbdcST%ZV=N%gj zzrMR)P(MGPhih8ZRs~x15cirGkK#gnh4%7%a1DOJq?QC05uy!UNpR?lw-Z&Ixr&gT zfe$Xt7c6fnB`qZqjEj4V!!S*KFWwGGa8Xd6s>qka^@)dS#;JzKlNck*$;W6?1p9$! zzGI-6K^Yz2IMNj^^E2t2KEIe55yL2rBVnlMJGbZ=L~VxNSQ#`3Vggb=-*Lgz8Y`1p zK_U_%Wkvqf{MCwxJlRGmzLq9SsfKz97*y^)AP7K*Plrz(0L2gKT)Qp+JTRHDxVcrJ zX1HohTIlK#cxd+mij<0GeA{$SXF_>2DxVxFK_e}e8u1!J3a2#CrGh09Sp*ohTpXXT zUm*ew@(H%nP2}<n{5Fx$cI;k*k-KpVuk!ig(b1O+10sTgWR2t`GeTWPUrGH!A*ay+ zltpwE5Ui2OQxADw=tm?XV#4WEDX0b3^nXceL^RL5`sS#=Mydg3IM9jk14xziv#kLA zlG!v*&?LqV?TGC&_=)*!JOq3Q{AC4ZY|IWIV~z(=bTnrF!=hPk%!xE2tdtee*7!-? zU%wAL<Uo0wYDNUv8)O{V6B!9nx}CsFRElAuh=983C)|5hz;nDFp`_2FX-(*B&SdC# zf@SGjw@B2>lfUft9XMit-8QVeVWtYdqKqcK72Rv;L5vGzELb0EEJ$#~1ypb5IS(Z_ za?=!=NoIgj;W0a<k}TWzdm;=`n`dx8QGzflp;#1TI{FpEZ6B9WAN<D`)M;V#7;I#9 za_n2znsE{3VA#-~Y44qJO1~~3#?V9wCJa7gXn8pSOQ_%dB0l<W?+x>t2c*08Y~d6E zSmU0*Hb-~0^qblg(Mc51G5%h@_M1wmAr#@Ufo9s-X1MjgFaj)rYVm?IV+`eBwMGi* zhJN@wMl}Pc+Tik?qnWV?Bg7dRIHQ%A7Or61`7Yw3Tue~{2-j{TQrO+$UwPJ10LPYF zEdOc};zN*gcK4vvF^$La@BJZd!N5>6Kj!m}5Eh}a-Db3-LPXyG6Etr#Xxr@93&0?N zF#zP;%2Y73+86lCH4IUwC(YnK&blimA-e)Mm9g)O#wp8by7{OnblO}aWYmNllOG5R zVc{dyt51mr{bmVeb#S35W7(>Dg*5_#r*$w(iEOFpB_(&tSO^T`8e@zKR9cq#kxZ#Z zg!tT57=)qZ^l>Ee)5c5jk}cK_qL9`G5{23@t%4QHt719`@pK;Xbd2#eQs2hAFNN1i zQr^S^Hcw--*}Koc4go;*PlH==^-qg*>jsEPa@*p`z~IqVMIBIlER{3_?|fbWXn=zN zQR*5Iv4lNAIURuD09YxL@=n2E0oVaOeb#;OyHtH5qr&JP$^D%`ZE(MXX8@3)mC5zV zLaLTtP6@W#D6I70!p_xF)dyN`srR86h8u>vi-&Q^Xeu1TQ6`)G5Fq{@&w=QM_>3SR z$cLB9#M_L>3BiehNpI1Ri07+dZn@{aHQ95}OW=6z<JdJ24HmBgnF){q_=SCBjjTo1 z4*VQR_(W<hvjkDNm$b*YXZ!He9(NK8Rd`e?A(I@@*T$*B`<kyY%~JP)PS9|#JZoHU zgs(=;;_Cy1AoAW19DCj)hg<e%tRFpJZR*(rR<~>~0SB#u&(Z9#>{T32V(wBLm)sW2 zOdFg&tFz|<;E7e4VngEUu_a)c9rM!Arm&nd@CksFXBRNZ0hkdZh{qV^s2Vi5O_eGv zKvP-<m<B$Z519G|Zxx&ifKR`164Nh8RWOsK^$&ndtzUou2i{+Hkra@?AY0m|<cCUP zGN}v(A%me>v{)5}g8dp^H4iVq769o-oTugNFl+*M0Wf}e4$irQyV-3$0K%oLS^e@Z zKM~NZB8U0&YwuCHl1`uuPlVOY@GhvoK)%bc*>LGJsLJ`GdxNlcISUOWZwF2~WArZ( z@<MJC(MZ`zAfR(h{G>hX0W|!*eGFxZkDF>3%vEqCNy$q!9ha0Dg)~UfFRE|+t||9G ztm8l%hIV^hcO<05OQqC_jyAo8`KT^U!^2K9kV<&fkYwOP_mG>R2f8-Yoe&M_K(JEi z=&ULQg-h~zuQ@f8ijmizLZO&M2&6$o-Hg;R-lQCs+u3O@$)UKkSCJ%6pjc@))@e7J zOb2yo3@JlZ1$>O`=G)Se?VK?hhp+ilPhz<@!+ZybffM|vgx`GRymT~tZ+3tVKEBy> z%KY-^>~i(?wfFM1ck;by1u`uS;N0D9L8!A%WhIR{vemj|<+)|`-m!h3+3{H0IlW{x z=aMn@&izKlZMKb@+WZ{&tw?QetildwcL=6!*haPoe_~m37b!HTNh&f7B>vKaP$K|( z7i|kqr15JOF#W`rDo{~|o`<q-kaInM*6L!;RG1ZFN&0qme5bz9^-C`(;_$7^A41C^ zTl3#LnceJoCos8O@wCyo6!8v-Tw~wB?`%?ZKUNQ2q4$@K6$r*_dF1IffiakR?xwu( z&oj^R*p&jzfJp^P?h$*#e=XSuHG%A^_NsrmmdM~Vbx};fVR0kz<21TmgS*zxJ0Kd8 z$}<Rbc%V&8al-kb7hlQHvkYHF*E1ti^_3c2)iR)r*NW~~3tZJ`E;B*W+Q=WeF8wZM zF`|C-@QSb9rk)V0xDRQv$ZYm{UPz@dUljv_UDc$XP_kS$>qP|^ld%E>+8T837}}a{ z=+<Sw5S@!V!7KtHKTVQZ42OT8B$7P^Z}31+DTFp3fBf>?H_q%<0$`ZIjSp|RmRL^; z^Da%y(MX0oNZG6frb^f|l&yFWnk_bLdE)I@aOtg;dc=x$?#8z`6a83Q{QG^Gb^vNg zc5oi+U1_#1)5UUCme27Odo^J2v+qOxvzN5*vpEeT(DHFrJK{WHKjys2Fg_E)ggp4y zl#M!(^;LbfM^m~q^kaKs*@-DP=Sjz7ey!~1JU!?cue)HGPWfk_+_R0y<HqfZ<BF7! zlV0btllB%f>*1!kJ>nVJ!qzbkVa>3pwFu^QE|xOQjhFceGlp$zS8e43u>~1*w=o<| zd1FYU+cDYnuYe$Taz0-Q^|YR+9rW(-QwcMaFbJ#47NxyncO=K20nC9BErTu7EyFD= z8^PM`2Uf!@o*Fq<(cDYdEu|Ytml4mL+U6^lS~5@j1_ktc0khj@B5TrEI4G!rB5aTW zo$Nz>eL@*H1`Wlf5vke@t^B!{7ZDoz_YavmQPwxy<X`agH!pOko~QK8RClL;rj-e* zZlAig3YzP<nL#zwGa2xz9ykl4H#7*VN;EEIRTMEd;^Ga6HEpI-ncm#HbFh=?^Lr|J znrV(C>=%9jIi@9MO6HPm?rAR=qG%-1D0^2MTD84<d{)I|3CgBC!ED+^hM#W$+TF>) zX|R{-L`Nn(T}ju-xoovrRF=m+D+=<F$B$GpdDTQRJ2xd#rMX`3EOSeErRiWNKKV10 z%w&nxCPt}ZHxlaQSLtGU;O2~p82zyFM>U^w`?r01eTb?JRe7~$a~ErS6h`CB{QLWD z7J=ucxesZAdUR?wktRDSsYAm*n5f^C$)o6<RJANe;B?@UF~F+}62BjWA-#K3JFvX+ zuo}c3VJbBQw>HQWp&Wxb9CI*Jj?cWHxN`cJF^l*LqxNTpqtGPQm#J^&II<j-)ssyA za;RJ930W<0X<c9xIm>Ol@4o-;98bqZ%a!lQ<S1ZdRiSDhSk*@JRJ#1E{kZZia$ZE6 zVchBCmw6=8WJ2eHh_-otRjO}lVO0_vOnE_r=adu-b|jj;DB)Uc$ox!d=H_(F)_Da( z^2FS0`S>z8vfgBD?_w^gDNHLOp0c89H6@v#%8Xn>gxO*-nfcA!>#6@~i)<|BJh>Wh z#Uvz^dCyPB#|mw43NN&H$CGVfLc`h(RQf#`6*yQl9uvQ0pRm#EJ0i=7caP3y>WUkt zM!2Bf+;T(7W!53#-R0HAnkWx$leEq++|%Ya)!Di@_t*;&Bb$Ldu-Q=I_%{jO(4?=r zHwioei0^b=v{Fy5dd24|>o%EakhoBA{11;cJH3PbGRrl!Tl93Uj6g@F{`hmFlNFtg zO(SNw44+<sn8b7C4;B27KEks;2p}hb^x|?Ps>^fW_JvcZ7ocX_5zBV#Zb$~ebqnQj zmIh_&1+L`pKfSKh(1g!Dxkn#F8#IjhqFey9>B#Q!e-ZtPk2TjvrEH2}uH|H=oT)ZM z9nihS)cooR7u+Fz$m^DhGG%S!1YHw47e&LZ%7~Kwf@H=E$uQi5a0MZfhho-G8ft!| zzn|aXfb98+m{3fx)E&xZz!-1W;^gB_SvfhL%CCr7*BRD>S7hr0dN{R4jfZ6BEYD%M z19FEH&P1D#iVr}YuqO@GFWIW72s_X4K6CY(;BXl%!%$Q(1}pVz<viVzqz_t!?M*S& zhcVCc-?CyC#-CC%=d0*tDoBQ#P}S8iDiJjHXXRmxwn6ZOzY#b=<B}=!KHzzFdy3hg zGJ+l=2KFayS7!?)x+qN})@O6;sFtfS%F##V+{A`+m{gJRMlc*&ePZ@)nP<quHAPeD z!}TeRI%?|!K`xzpnxo50Bw~UerSPUaT!J4$!iV-M=0=u!dm^6Do4}V+cd}oyI)y(3 zcm(&oq7G2U`mdLns$Z>7Szlzz5xo8OjE|5!1wV$xmgpN(7jG<4KKd(avSsPq(0n4z z4~5itd35_JyR7(Dg`b+9j5Jao!r>AS_9V(loItW|ZJ3HIZ#kduz&avne&Q0Q(Y|nP zQW7M2hpk7sjGB_WU2(ak!A`Lm=|WJ3M(W}y4U^;<H`U?a<4^8kSfhsbX^nE#MAo>I z<JubnI_B-!JyTm2p&pXG#c~(PTVSar<r#9B8$N88zCw8^tdZ@9gD3i2=hO;6wb*sX z={-FSr4#lJwbsk?>T*IA2Q%X@%5n-Ha*?PokNOuJovNv*4Y@60Tll;&xW{qz-q$HF z)7_JE^u7<&J#xJQdWC#&@Qg%<YHT4(>Lt5K4l8fScQ!g|j$ymH?n;b(z3Km^4_qUx ze=#VPnis<_s30AgqS+*a>&El_LxM+W;$iyamSe09ao;{}LJzvrNNKFFCZyQM)Pj>j z@WRUA>~ys}dwnuXuc{huS=7lFQF<HHrQHMJXVT=s>Lco_p9oUgm$22o=sxxB_S)&~ z!Med~hEdfMQT5oj2B>HaPHsNJQ6U^GS0bgz7L)!l@!qtuA7EoG=5!<CCNNnI^}d~v zSeASPxcy_x;$YZ6v}eqR-elcyy@^?QNyiW5Bl?mZVujEKUDQ&rr8(~*BP0lo#7R#E zmIks{mzkYd+`mi`p3>d3UcZpIhj)xiRYxze-G;iL!(Eq6=P7w1YWo=DYmYTuV|(Cc zu{>Tpy}U-hw%ddw<%V4m5Lux(hkE6Pdu}&vJB!sIC>W77kyU-O{&B!Sxu}AohNAAI zg44ul`qZ+wm=vFsa_4n|xKMnDsQ$w;t^!$jw$1WGkHg@l3#Bf4&;ye286xi`f#{(w zJ;9E<OOG?m>u29$_~s?}QkJzzOabm!%I*U8Z?HGGn{+<W-8@^XAqgb%=Il;2i-&@4 z<JXOGR!;$1dpn1W_r2f(sNN8ZXOzsM5{iu!Rl1AIA*|WEq|K2RfddC<k%10enBv~D zRyhnqAF|>+b}M7ibzHB=8ri5*ZMR4~0?ljkEa?%4NmG-DoNqqZ@HmaQH&#&Cc{C=E zcI{$M{a{+w<J*|!4QRQ*7EY&%-1zrwN^ijy933<h`sbTnMzwZsLEJsXA5n^Qis-Vn zN0O%=uD4%|&a%n<m>$gw;3*EVu;CRMrO^jGsD3_{#gdG=U1{DU!|AayjAyzhtwq*= z^8|E=o#zeLqncy4g|z(ODOywojNP+5aj%a*&+{k94C|Y1j~?u!L56#S&jzdVU%b%q z9_ik!%gRfvhhDzxduO~xqNFUsDAf&L;xzL!0Nd+VBDglLMg`To(T7uKr{s3?*BqQV zGCb8%9oqI!3W$}TS_^i3<Q~`IAfvAh2)fi7))O3yUUnF%?WWgp-Kd?sj@xrQQFOpm zIwM5u=b1@%F?U(g+ude(rr37_R+1)PkcO8X>*BBgy?_rciH*$DI`t)9YQl{1cSRd^ ztgekb?{;&;xQJmnq_nSlx<%*+PmB+B>_mG%tDfas)Sp|NW>~`hIZ9Bh>c>OnQZq48 zXQ0%(*qgm(jN8Y}5s<>2!=rl;l4_e+TT%{@*Oc=9ZIPZ+;)l{21X*Kt;V;Q$BCWjW zE8lTRm?iBjzBZ|`NQ2j5y|6vPff5G;qw*jc#9&phjiBKaMN5}D=}+A~5bCX2<j4X= zF<Jx0+`T%vK`m=wbupNQpIutns$L_yd9yeD6h;lx+?c~savR%L=?I2VV-uygDxKTX z>?|Q|cwRB_z3kfvX;R{IJEGVCDk`!W=o1bT4GXFJ+EV#g#4Vj^3AvSWEyHkZicXU% z)gu%_-b~EG+R=14hhu?CI$fSbQUkSugJ<3k`G=g+Co$}G!c|9Jhd?8MG_H>v^bm6} zYE$|qV+=_Oin{>D=y$jH{m@$1y4CK@)qF>nTX_;(<|n{-XTQlwVPI)8bJKWX<IJp> zjdopA@8Y_W@&p)m1k8qk^S)X+3<(DxN1s`Sh7H~%)j^3M;~+C|w&l#jAKX&rkVpDV zjDhH~NXKeFnkKB^m<$gNoD&j{%WZ2KMMyvY=cRs|GijZ!h-@8q*ikLaW2x_DP+_0* zmY$OgXZI8puP4^LS#_KS#l+|82mdMQwqF>pnjB6WrT>z-nP3#|g%!^w*Yfj2D!S9% z>4jy*=s+9_8@t-KvAwvZ?k9TXMYl-9P+8VQlXLxv1&7A=v8=)Uw~e2V9mU1=EyB`M z81)5jqa1XMJI{`3b#$9(EYvo5%o00%S?`TbRN7UO3+%0Fc3^`t9~qIcHGq>#6vT!F z{^toUdf@Szc@l9q=@Kk)ILWCQCDbiRY{~Sa1`#VvZU78sHQ=%J=7;i;0_#k3KbygT zeYC;(DLf&B3{tbEmX<Fn6YmZQW~l_N#%H~wXo2hHwKY^{nbh>D?6L{T6K-~A6lPTy zH(l2cW;?Xl1T7-b<oi^NlgdWLSOlJ^D;CcHyBp%vVpl7pR_yY5c(h?JqfC5Ia&sQW zt)i2;>d7#1K}K!gwln4EZ=FS-@8o74oQDhcGck;=xu5z2XB^$H3cRVEh15(;D<<gQ zF>ReSHt3bjQ@N_v5sxphG8?EYl@qq@Qe}2wYGtLQ%`H%uu^i)emU|NP<R-G6ML`4a zi8RT3c*@vHk_9ZC#>DD^T+<w#4<cC4MaCv^H5oqS^Gr_5EezvE$A#K*7oUZIBZDiX zJAQZwx`@90D1cFiwKh#(+{|_fEJsgQ_4cmYH$A^Ny$Bn4Mlr={TJQ!iPP=;Rz_;MP z`WiU^dp@*~esT0&IjL4{OkE1bAEV9uUdLyh$yw_K&;$EsZGOSZW&o1|lN}5S-<;<c zK4eOR#=?kL$#yKLMkVbuj1|jW9UMr=vqXuWQp#TcBel^&f1=EwiEYB*$y(utPR$XS zPt)smF+wuPyA>~QCYRPC>LNAzd?WvMQk;MD;g)#TXCIaLHX(iW7n2|3s(7e~Mxd%i z)mXMP8xaAlyB0)ZJ<CiGj306^@0(B?+1EQduu_O@C_PULLNG6^9C{6cfm|^{D0?9} z0_k=E(<*KAb^+n2sxb(cGe3Q6J<h8NH8YrJ-}dS+`%M+#Har0jOT%6hUK0rLlJcfN zqtRO7tEUzpFHrgEG5P{H=DwzN4S*wH_eYUO(TSeB1-~Z9$f$rmABZ%n?Zxkvl@gsX z%$e1tq@z|jwMb&1@sQ+=oaw`{gL$mcEu_lrjr6;F`=y;s*h^Q}-bRc`d~@L&53ikl zfuz@#wI|Lq4Lk;+_0^!7zJT17EOQ36BUx;-YW(s_8VRw`z9z5;B*r;}vhCDy83?#a zw^}W^^y5^gix*KN)r@5F)(rG|M@YPZC^oG0TfC9G1O{4snk<t-mm3rsa<lD@%OuB* zTWT37)WQ%A$SgJW<Mk+LkyMK`f#G$k)5t+DPd3#um*om$<F8W4>zZb2v#UFw0_ik` zqe1nJQe>oPngvJ;rF14PE_(?hAt56-ue*HFd2+>_@bE$9I&G?EQk7Y>3>B`~q{A_6 z7X0;I3(-9$!p0+RcRkxcm-{9j6|_?8_D0bfBcwU!^=GMZB<Fh-SrwDi+E8^h2D<^( zFj_)1tE?+k{eID4HTL}mt<6(&^~PHF^|5p7N!5;8bH$Uj+Ms!gq=41K4}hAHk@kP1 zk^P}wn3-7rmPP*z{zggu7Rf$|14lgvSDR0xs()vECZnh%CM@yaWYK>ZQvEw&^uHl6 z4F7KghUpVv_zz)}iHZ3y547LjXAG=te|@KCVZ~$l1SNiprhj>(eU3AKau$EQ(tdyb z_D1{b^K;wJZ6JT|^Lzb0_Ge}ObbkB2{yENn5n%rfX2bY@#cbk6t^8@>1s^;Dlg|ix zx;YUb@D)o4Y7Y4e-T<nDzm(7o#ejNma>O$xwz7unPeOMtUFCXJzEu}Laz!-e3f}oU z`|e*MP?khV`A0W~+WBi*k(l4FNy$d+8)c%hFLvT8stSqq<C>%<SC<BpvN+uinOk?u zqP>c8d0=Cxno`f+N*Z5>&&Vp03v&&0)X$o`lOT(q6gn;8COP_7{tTORBnU*z)pzHL z!^R$$Hz%)u7mzJ+RK$r^6xeuM6}vVUUfdLmw^XE8D{2fIA@T*PxS=ZZ1v2SQ<MUk* z>`CJVbP8n(20F}Y@Bu2;U*`p^*I(xcWYo9J1&D_+2M1+MEDmH}PSo=Qx-HaL<M&+% z4Z;X8u3oJp!15o~uz-*9Jy-b}#cMkeW&@q@5yZ<XbP^G*3m?^8c}tKH>l5gKx)lK; zVTja&4v`Z2d!!|TkChM*>Xl+`_9E~y@oKh}2h<$`u<H9pHYa@NWB2S^sMJm$Z~*Sr zc2~}S&;Gvx_gfNWU}gHl1Tg$g%Re&d-^u^)72^LT=l`h@Lw*{y{e=bmQzT|&`=@am z-EWsZI$C;$e-VkPKDYm$oZBG(#(?nt2j@1XPYw5Pm6-OE+4&FWHadpSYyKMpg8cLp z{IAY!e+~S({C}#%jQ@fG(Xlc7Hi!G)K%h(y2p5I<<x94QjpZhem!wp8<LqG~hG9xk zBZRng7z94N7#|3Dl;y7m%CfP|K)n5Cw#wD#e)L2>z*ci|>KfduD}t-s^Iio?>hc!h z3rh4iKM$n7zrJ6*ydOLr?5{m!-EFvUym1{E-3(BT#z4a0V<=Lowz+U2ct;Te6w<Vq zF=&sJu@DluyF5K3n~S?5etMxb=#4Mz6|~ELFD}*FtL+yTcXhzg85biX+p~qt@!ne* zUre};V)i*%ELW$Oy)eMb)@*xB3w_Dk<jeYLceP?zaIa|&P`F^N!7Lm7@>Pya+K5HY zM79K!?c$-Gn$*=JH$)>L_h%lM18y7vWDQx=K3-ph>|2O0XGt=Cz5Xl@u3EAABcD}r zI2Z20byZBbww8O-e!Ib|)1LkHH<OBHR@&QmSIDz3<k8v5uWiClShcaX)K7^_WwN+$ zu!;QCebX0RSIloHoZ!MgnZ7yN7OP7Bj3~u}h`Hw<;f+I*o}r0sY$6Td>@txEAlwq! zZdTd)LK2h~c`I&$o6jG!5eR|^ZVZbc_)`Fz55JFhXNM4_Xo-SnW`^EYR$jRkjjBq* zW2rp<=8%#oY+`m$wt3E+5lh@-qud|Jh5uPF0Dqd66zlEV8%9`Iq!#8?GHKN8;31}P zZARs?STsQr4liduj>rkVCx|GdG)owFfCGx$R|J3PTL!|9mT>pPjo_*-xSryNJojA{ z8T-}LGXyh^hRi~gP7wK^aMBvbzD~|qnk+2MeHGYAt^k%;KjlO9>O@YND<Vgee0K6( zz&-(5$Qyy$ylxo?Hy~n_fpD8XWiw0Zb8qy0a_}R<<0)CS9Img;)0@I|-J+q%N9jYp zwRR2(h(I^-=bY^auLV=Ts`7kQW<XT^QWUFZSbDHv!i}lO!%0=-SnRd<B!AteLeTii zw<4<f5XQ%g0r(NH66=1czYmWTLJ*xX&gV46lQbtKhNkKEiI=H$k)j1BA-43rZ3n^p zQiw3~-Bk|eVG<R}k4Gj|!FXr557_qrh!m&@ID$w9xFNJPfD3bY!O&E_3lbOy0{j?g zZ1gsA_d6gPf{N5&Z16$l78$Z~VnEaLDj8|#Jv<Efc1~<+nI;(rQ67pIoGAGPuSpdv zS}^8^k_^snJ46)?dwBcIeXNKah!#Ehs_+_T#C;L!`m{k0Ogt}{(@Tvh145{dV6Cd^ zD@6yk;jjKqAT-cN<HI<~>nZzsQ#&9d*B2AcbRX9x*h8ec?*-eB-9-Fm97Tm+0z#2| zNlpDTa-4`ex=RImFeMhc-+m$_@HV#)9NrQIX$Pw7x^b|{z-v(s%-emMcZ-T$<iW~* zx?IbRaX-VqVZ2d~m-{QZo22FKI3RNQYl(<EjH{YK%e2E!yx@6$2^F$sW#LsL-G>E) z(Padlpe6Vc!kUrZS4P6uFY-G-i5pcPwO8P!x^KU5@kMsW`U4LjVl|*C>H^B65rP)R zV5wH%DMP!pOqKtr%<~`%WORvhsYITX>W-Z`6*aXIHB~BP1SXf%7MqQoQOIZ9N+?V% zm<bWa7!jR#Y<GG0bvge!iR|aU=rLigwa2u%$E5B$Zl+b2vPikhWZ7P*>W^uQJ(DB4 z-6F=>HiRCHJMDN9v(3aA)fyYb4IOV0l*|+jBCnA}9|@8UFeJQ2V>|977Pe*w-GCqh zjz@<WBZS32LRU(14d5N=;R4%*D&)7Pfy1K>1U{59ZuANb8MpB$x;p^qBb@`R_wHV- z77#7jB`oA&p7YQP!bow+KO}4g#3B;L(qcx0=6}pYIFH$4#MKFOE_&X9@YHW~_MI}{ zbyk37Gvr0~-0+mw%0&V;kFdL9jrA5T!sbJ2f6pc0C7DMW8*PglVxMmJ{fi@9l#OvI zK520?k3#m=dz~BVL!C}m&tP*l$mZ4t#4ftYBSF1S5DiE_FKlZr{0fg+hff>LBbl?b z>8b9|r9-2XF<`&gHV7@#@C)cBoFLWX)gdY}7^XwSY@PeT?XHeXPTKc~d=*wM5in*u z`BG(@cz^Kbg=6Ptp-mv_QQjvy>K&fm`R6|2kf*-$Ju4SBm$;A%0Mt_MuJKAw^q;;4 zE@*NJA;XQM%tK1UNu#X>e&te1gk=e?hB&FBRxx#U6&h5^BYSow8L{$qL@ayZxDc{G zVkPBh(P`uSI(tICR;h+*^g>L8^w>d43bGNd3p(C4?waLkx~keLRZ_1c%HNKi@I+i? z0yk4Q+d&++W=wi6pN#77jkU0aR)HQsYZjMP^@By)&rNU&dA_-75OG;Ke$F;|%bBRQ zIl-0!0=MeW*8xziG^=Go$GA%!w)_}3ja6wbrg|QqydN)cF|^-1KRZ5~<T}6@A|4W) zW|~S&pBbIJ;E}S-t2DRfkkXXy`u<_dnYyyT9iFf=Yzd5-4#=wsH||pm7-O^=o6ZP) zyg|*Zju!=XS`*0#1^+#b%b&FdJvbYG+-FRrtrxuczOff8BL}7q2OEABOJ^Z@1*DG| zS9?aN=SOruGp@MGm6K9U=q6mRLa%AgNA)5c4D3sX-rbmWsb|5l<>#Vzm$<1wDn37% zSeosB{6X*fvAJwW^-)!MR_3N|qb&WQ%Vvgd5@?D))l+GWboAZZVJ7AVggTGsd+FhK zsU!2@5)Z24l3^4>OdAiG(h1RA39!%@$&NuM{~Hj0oe@!cCM0u`(r@V$>7vLn3?(ys zHC8`HocKGyt**xekfHkBnjxla%TW)n!|pYn2mm@80S(Nx=fS)Ybr7E{mun4Y3&(9X zYC+vV+}rHpjV8``u%H_cPQzEgew;NbTBd&_tA5vPu{)d-U>`O(V*_NjTtPy95zJE; zL#1VId9C_6UO;abP8P;j6p9NL@@pADCuP>-$~o_xUKS8HlEkvx<l5!R{&}D`h{%-3 zhb8vF|D9IN6xt4S@rxBKp>XW3Q~=Q|Ja|dOhL6P;WN)}5#5hR#@B?DJcqoeS4^b9B zizSX&fG!%JEM8|l<dq;RzB4l4tnb!8D5l&P5wU?zp6y>L7(s0izANW_L6~B#{nc+m zUm3WTIi%)+Xts~cQ@{;Yas$x%mD8W<Fxdpc4R~xG+!o<U7TXO|@>}J1q2ZTeu=SvO z6mNe62}rKc4Vw2xmG9Vx?uVXhKJG{OqJ*u`n&FkgP5KnngN~1GNCC#pU>$x^a^>4( za{fjcQO`0wYQ9lER=F`CcRBozs16isCAen;rXIB}@N+f*Zc0ClH24L>Nn<b*{q?GZ zB@dNuH63`Kk)yUm9hmH~RJSrw@^)0hsg}aEDYzq8SzD()TxM3MI}X`yQQV;Ho1?>K z!-*zQxOvs;VY6&7S0cT9--8k#={;Z)i?V4Lk(E(}!;5m9sn&{Mh%T6>j=5dhil*rt z5Ik}BcRf#gxE{G*m5u6%=)Cl|iUOm<lD0QvV6z;V)j}%;R;Q`ECi4y*Z_ORRJOj}w z2i;!T6$RhY7U-kJ$^{kH09AInFU*3LTfxr0b8NA~a(RWgVhxD4qkqKB$g!KjI08HR zJV$JRHumAB@F1&)Pa=5(*uRszC~>p;nV{%6V(M7J{W`~U1H=||z16=pzGY(vXK2B= z7zn<SeU%;&;F5mxW214^zIMHe-FCgSdZX<{E{2RE8vBJb2Qg_!>;_Nkh|%Hi75*Oi z9+}DNZ{5XlN!y8d(f_awca=P6sYCQ0)tT&-G%?L%L>sT8B<>{69XF9cMZKo(QoRIf zZ5&V||D7e0Hh9zrg#}QO6Z(eLPfMVxyY3Cq6Xr(mvxn@C8z+>uf7Kw%HkS*}yU%fs zlKe^W9b=(peKhPe2YM7+*K5L4!>-!!IbSucOhhP#9K@Uq+~hjkAYVP!xg8Z&n=TG) zZZe=c4^ZhFQt=biEz?>g5NBC6y1UJnrd~SC>WygBU;Qq`8$q~(;Fncb+T=;KvRY<v zcbdnx$HsHnpXLEvxBRzcZ#bGdVF-ytfWpZJ02>cJyB9OdGn%z1%X_s&d)Cp((H}0a z&Y+In8efpzpqh}hzTKl%ebdtPD1UUgdfLw27VRn4q4Z9E?DTQR$(TX2kwQ%iLg~8E z_GJc;gw1Q4a{lFlv7w8E&0FNN?G@$~<Q2>vu%mwqp>t2O&Ee@g(aW)14W|s;F}MBn zsWD(x4K9WaN<MnM0(gBnxHNwx@<RL>>>ao{h}(Td{7(8FMlU1uO=@1wat_H1j451= zk1B7$zs{BC4*m}5j=<6H8DHlqd9JFMM-H?Vns!>sdCLD5C?&Sy7dw~GPmzy|chEQP zH}_|X6ihIiU0n|epJ956l=ReSBHfgtg1GrOPn&jXMNwt{1IBNj;?JQH-=Id>4Y+EH z3<zrpY)0@MSZt1nd2*VKZ35E3rA2peWrQ!e9<j|pwh`4heX0t+Dh?|EL^|h1muNZw zu*@v#kX~M47svn5g>9H4oI}d7x=shx$N*tKjc*@Jxti6HT?b>fgmXjPl|rpw4wcIJ ze&v}jyh*O*8>L5KGgrF}+y%wo43!OnqsD8Q^FEeQq?$9eIg1Oh?g8DN-SZ%}$#+vi zCbLRZ52xA{4F#CgsFxL%+j0o#Myj*oe_EWON(hJ^^#L0-Za>#CM|~`E#hBup?Yovf zDgjt`K^XJ0rz7wI+5s?mPjZLT0EKIq|47FPoRtgB2Lt7k^fpImg5CkjFb97Jx9@oi zn3%gigZy|Q!6cc7(=|J80`LJkI?d}rbBBDN)8X=E<30M3W)64S=oU^Rf8dB~PV80x zmCz#hM{{5$AL#MJqn!%|&vRKH<bV;?Wh~O+vHmfe8yhRcg{W4M_o&0{AiTeJf5V(> zTG5IPi>5LbKj4vaec@%e9)($6SbrP({G)10Cd{G#HhF8D>X^ja^Wox!oRSAihtiDp ztGjOcu2Jb%s$`FE=>d&$6?pg?pqdU}5_jqnfcG=~<0!`x5?fAAs!CFa1U;jEeqa2> z)rIZl63-oj6+8u5&EZGuEEhBNkmv0meZziS*yNMJ79<7Opbb~ME<y#!RfjMM1k4`P zUFEmKn-lbtu53z)5#-SuwEhUN*-ku*^2;I5_w#W;tyh>07>z|<!xXPMsMcGO-2!jH zk4ROT`muAwGz?OvIb#OLh9d=fSxw|<MJ0hz!YvuvU!ShuoCi*cY}iie^LosmR#8et z^Tmo{ff^)<w2UsI$Y-6y;g1?NvQZGv?Cjq}H=58OQMBc%$p-nScdeU-ukttbil3Fl z0oABKXs80^#JBXs$F5<Db8G#qAFf)QS3Ep$CNr1e7M<&#z#i99T-K?yHi@;&f358J z!g{n>8e(SmhCkk~?UpIQHqn@sm3IXzjworL&>I?pvX?7#7eH3pDQ!OYF0F+0LyfFt zaY1vpf@#qmTsHVd?)z8LLSvg~w=*s>)cx!jKe~ceP};RQLD<}56M*h7UIJ+dYZ?|+ zx2L~iel5jnhgliNtz>2MaL*D<rU@%eeoms!+RV;F?L|9d^F%sdO{&v!AGnu90RuO8 z94u&%aziU;&0@sC+2}sFpFI7UUp31wgofrrmqUY`(r)5HzxM3Zh1A%;wKcR8uT0)C zN3YF6u3DcqN$x?_nb=!~3doJs%f@J4X56<0ABD=p7v<#DT(x;H%*5si9KJdNn?7|} zUXkbI+vMF=Si4PIMl-&zTVb`$SJ85-hd$;|BGrzN9$!|eiduviPkQa>=bFBge0fRq z#_bZzZl|Uc9F#oQUEXUAz+bf{_r13?<A>ukZ94HDZ6YfvL^Ze9BNT|qL!{^ZSzJFN z@eIHVC_!QXEA@;rEaMSK#omu;4Og~YC{+qPgsd9bu_6kJ$`N_*y9#4h09w!DBHUIO zgB{uf9Jub|^L8KVU<oS|BX9D_ywOZTkr00#UMd16QkuCG<M^~(C??c4n(P0sv9Ann zV_CN~Gc#LeCRs8wGcz+YV`7Gw84@!y#xchfJ7#8PPRtzVIp^GS-`#uPs`sY!L%nKs z_xF7>)1{HLRzp6LL1IHvxGRx$K9rfW4Bn+JleE0B&5z368g_NFy5K$BZA)Sougu@q z7*ymc(2o(%DH`m@*8FNtp)5w#PEEnH55_v2>{@~W{yHJS4ic`A8J52W@+KDQggg%O zdZ|hu3*_JU&=Tzbo@X$A`E-NT%e_u(M3oVzBw%yg;C{O~^8WO4uHQqO{5xS~mGh5_ z`YV0U6wwe=bmhCtlt_G3wh8=5*89t9=La5wkhbmHbAZ1b!8pG1nb!gBrVvD3BbIfr z6T_U_Ql$5U0P|K(m-};qczNjN@}jVqX{D#?XpgDz+%5SbCf0!3hty=TnJ_xSx$xjA zY5KOM4POHh8<}d$0Vs~IFd-ynx)qqIrp?sKX(Kuf>)ZK0RFHGOlLgc(F<E1KM6x<H zxHRlYb8T26iPGmjLBv5x!T27`Bt(5!=zfik#;XWo$5sgkg^r3eQ4W)U#$E~@$j3@| zs<wXFWeEpOM21s5p=rRg!>Hr~!y^ea1W+Fl(nNo$SV8fKUr|MU5ha#ERry(JSpLZi zcPPI$Ayu>k=_%ffY$l);7cZJD_(uvQ<Q3UonEo)pSqkpL?`ErnzE`WDr=vNBiCgL- zmt+gMK3^659p<hAC!|X0Nd6rIPyB9K1^9-@O2jSCL!?DpNW4Lf*Vr?QuQ02~^W^Gm z@}>!OHkNU>+&1k|Nxtm!pjB`#4r?ekTMB?cH6lA+<$<Y!S(ybtR;DjNlBy*35s9k9 zfbkJ&LGNNt_1pbB<n0JH;z8olrbD9kAz~G5gQml64a5Cu{~Ji2Z6I9E;c?0#EaK9Q zfIHTPck6@yuzCKtxJ|;=eN#=PmRGk&xLwl~<NW-O)g^!3opw@H`&?kBX?`)E!oKU5 z{KV&<>2%@(juYyG__y+oNEU+!0_S7}UONI#gox)7^<!=WsiKE6ordhGi0bWXmLUvH zbtoAu$ZV@tF@2$EQbp@|@zO&RaXEw%io4d?M1w-+lN#Cuy{JAIv)wAOcfP$_Y1xYD z7KNo;43+^#@7Z&J4=IRMI@G=nS$Rnh{Iw3GUFSVJxe3=D!UVC#x;*zY>XII-#+Tjq z=?2>7O^>5A+Bkf54mwk0?E$M<8DD?*e>Hf&TR`WX_j}^!1$N$$Vkr+Z`Y-sg2M7uD zoz~s*<*He3t$rp1?$suS=!NPowg-<3+=KGhZ}}+ppAqam`KYU=Z16@5fia^ejbU1Y zyD|N>iOr#fc=85nO%r=SPDm1$XG6&1*)~I`l+pe8At()nqWNs-)Njn*n&IoLT2IU& z^>nwjXX1o3$m?+-nxYg-*aqaOFr@QGhwa!PDW`Tr6=Dz830&`Kan`euUB#hF9G62z z8Ur#R^j?V;3dV^OxWvSvq$(Z|Q8QPY$V6;}BPEVTnhIbE$SRsgv5k#T?U6?)%$f7c zP5eIVVJm{u0_BbxLpg;4+nK<8$jioDb(rfe6}7=UQ;=5&s-a;L;~AC}vZ2tUO}vlG zfuF`a_=p{VKTEk_W30%Bd-G@$B3(76u1`fKrABl!?<aR#ke}e^^7}hjn;Z5g!l_j) zzZ<Txf4JWZ_PB@i(h<rhPu}F&Ifdn!{7O#j4HnbE-yl!>-YJaiIX#_*1#*N@C`h>) zZ^?+G6B^I>APN<q7LK)<aYo25b$w3`Bre2*NE8+9D}AY^EtbkI-ZtJ3h%OZgyp{#* znLk+_>In_so|Qb09lbjAYuShQk;us>%qzCG&6n~c6Ww_B#1+~Eu(ZDG-Y_FInF=XH zDyOX)Lkch)c_reyi6}`>d>NslbW;ipCBXz=VcG3jFkq=byBraiNC{bBH;5$ywfbZc z$(KyVMMN5cNr`8z5u}<oO^U-3XR-tp4@jL{=h%)E<L&}3Q!oPu70m4U%!^>R5PGmS z-~~7PLMMqUZ@+i;*aJgoO=>N~2Gksrg<Lku&t20$@@(pQpM$#86eagUXGtTz8-G#? z>>u}kB2u?hCt?4^7|P^@nxkuk%RCeuB)rqP`@(kc?1-1Msk__Vo-Cu|czHiYlE{7Q z)8cYkgUdZw0h<lG0^2^H?YZLF?s>*F?se|9?s=xNuX1KOPPG#0=|GTXua*{=#v~xm zRF`2~wob50^R?!sWh8PA-HzPio;FW(vI^Z6{TQuLc`!GQe5kI{c%geRelY&q<hQl- zB?Zldc5TkOMmE;8?CR2r6SQ-UyYx&A?TToQ#(Ly|^n4UH@biS9fK|31;*bc0b-oIl ze5smDuN3M?Xn>|Bt|qKv!jqTZV~!Dqn>6pFG}#C=4+)1A0>Ni~br>WiXL{UwkZ*)Q z^AHDv-xOeACgO`IXd!0i@<`|g^9aM{krE^k0*+JKBAN@bN6Q#61Mwli^u*`HU@<}n zwI`C3%n}D-1fdC;4<Q603r@i$WfETkR)V;7;)W4zvy{R^_GHTJqUx!KO4g2O#xZ#G z)hZ^D$3>>>7X2+Ff3*72;lKBn)jc~@o~LQm)veI_$;gIWdjouSHu6<xi@&Q2^tbOH ziKCG2itPV=R=whR(V*$**(GeKC+NO4!L6xQmsYqwA3hk-vjAUrp4HiP@jP@;^YCgX zudxU%PlIqXZo4IcZp4U?FP<jXwMOkNC#cqBWWpex^Den<BX^rK7tJgC-N#qI-JB=E z18D{HkH#GK8LslaC#JtBevSHN-<y(Wd2D>7bQws)YeFl_B#pC_q^BO4_1my1wPNy+ z%joOnH$>x2Z`<?g8n;|*s3tbWHoHYQ)m=E;RwP5uV>6;5(AnE2_399#C=-yuTr>~N zB_cC*zW5Xb0falFg5=2nsG5jM9`yjq#l%fmm%2U(2wq>D_FU1R!jHY|^A>IrL72Np zc(c>MZBQgEztSnOUS69raKyuW!}_K8RCYt<2ZxF#5&R7iUK)OzP7WJwiO4F}<%{5M z1Rb9PrI`f;>W*kMy+t6v!cr~i3&(dOjE=Bn3br&;gASvOm2GV`t$E9FsglabnaPGD zGex_AuZ=639e0(kQHnL$yR{AoF!kJKx~{L<bCWFtJXM@yFi^1*4NnbqztQlJD;eL3 zz0cc#oel@Riqtdsw9&;m_kKxzdyMD*$?#R!i`|#GvNB`{r`k?^7CW7;vLgGcLZIYs zW!A2S`_oKvJBk5F*IEZ(?^sq-hebq-WodSZg&am0aVFD@z@kA1x;J09rXg%6+N7sX z<0DgYtx4_%@}27UpSP5{1fnwIB%rMEULFTd0#D-X9bZ0L8xk}v%UVSE@oFobUr0`p zC@@`P7cVz4y@%sa&CssCYEw^83>H@7npRJ&W-B<6Qhu`s+T~p)>>CJB8?dSP@+Bf| zxj5CmDkI>zj~j=4r-cU5L{0MsMG7zZ)YtMLjGU?ObkhEP64-epic9iSTuI!|a=z;l zyaG{66FMX0E$KJlUi<s9!@^MF!fAK&vxf|Gd@vV3UROR*p-7el->2Ru6d9C2xK|7V zle-(VLcTpz{^qj^bqU>`C&VZ;F(vF60o{vLBk|*%NmV2@0z4J5Z^|cI@HaR#T7(UQ zQS^}KCb*W;e46^m%`j>(C{218TzK{@%$sry({|Xyaj&oF%*|@G3z_2M8+RR|u)1U1 z#=PcwhbN0amYV}+6q<fViVa-_I^x<#qBT!-3?5F*((8cBw|!gE?2D34a%-U-=k>LJ z_Qz=7Bfj|ug2z~6&ul(kF0s8A_9vQVL>2M354!8qp?dqGveFSLMIA+R%Z47$Ng|Gi z$rc41;aukB?-h=wqWqBHR`f1i9Brg`i6$NcKYfE}U@;;>T-nzq1||bKS?b0XQ%3>< zl(c~_gj3pw5DxYVB;%Aecvr#<p}~J*@e$%x>!O`A7^6n4O!4%b0u@8jV754`K)2k~ zgGfo-mSo=oK4B|eOf$tJ!lS?=CzUYyN5(-hU5Rj#T=AWZhte?D21LuHM+-#e4>Dr@ z(Cop&>Cy%c6q~X7GI)746X@P-`1Av_An;NH?2;R{11g3l#0M(&V1OB0XnCH98kM9+ zXafB+Vt=+*?aQO4_YeLc!H&gR#B|BlDArm~`%Ffj!^h9Qw)cU^@46gEUrEuoE-rmp z;&3<WSHEj#YgpCT`aFlCvwm&&C%h0&M4W}Ma&etHuR~54SzFrse44G%(<vvzSWrq) zLQR*(lBQG<CV|x$?J-i}QLe?HT_L3Lszl=moMdMMO)3F5J+7_P!N*G8*1yh{;%~Yh zC}u+s%BDCzX_I-9%Epy`4n%<Gc$Frqa-7m&=#iCFN(mG3OWwNfm(*Rc06xF;=DWsW zF=<{xomD<WVxSCF?yL)`1J!Xotn345R}eB`6PT3T2lIz*P-uU3GN-V;`VHg^V;mPW zE;qjkUwLdSRC7zELnC7uDIrtA7k<&w>XoK67RJ@V_)dW!*iz%F{Nl-hdrB(%;#e9A zGXY4kVmKR-Qy3zbK5;(S4B>t18$2a!z>#R<Cr`7ou3j537d^IehJ@@ePLx#eFYZr- zzkx)sA510#<sm@PckLuPBoaX~j6J_hfEb03X3TzM?;(q!J2$5Qn^H^U4`lC%MN)!D zqMQbZzX^O2@!rC6eQ|bh!byv^;V-tWzvz-FrW?4y&1INn0>L>aeAy-I)!#-7JUr1g zoaO3#y6|MOD}`s%9-iZC8p`%k8edc4S;Y#akKCK6%V2e5LM2+Iyq-C&Vg$z2{<cy2 z6+iBOSv}vxl<f1a2g@t-v!AX>Kni<T{n30a;e%(PH_X;A)ShRwsQ36`M5I+nOFH^N zqV=9(z?%_k#`5|?0hO|HZ}0DX`#B%b_5~g-&(3-T$L=%f;;6<NAc!evg%~omd`52+ z-ReZ=skOi3V$mftjR_EWA-P!=4IaA<<}}Y%Ts@)!Wo1fsn)o=aOUL3dm~${%TI?W8 zRtj8{Q?!DD?`#_u$YMiiGpC@|e^b^jm~fxn6WJ3%quaCVnc0L;_ASt)q7){ZX$P4E zORHi)7HMN~i-rNAa8IO?$sy@?6z1**kzX8g5(n{@jA&6ID<#;*m;~uMOr3^mxIYfP z^St-IUUHi}*=NZR?0B8?hOg^jHSBsx@UidXtgm^Ob;|bW>F>IJ?SA54#*&5OdPMaZ zy*Z;y2*Ow2r<^_OmEyvW$;h8%`hv%u>7xxWa&UQ?w!*}*rNsin+y=idDVgw~{<&u+ zT%Er@pu;5CBDC02{e0@Yo>tKGq+AeXb|WGXDt0#%6&33Ap32tkC-r+8vwOZ@NI3*_ zfC4BlffW%Mf!BETD8J4E3~BWmme|Qj7Y+Mz*c)MdplFCw$!kWe9bHlKbZd)Cl(~JQ ziP$O*lAV`kE@P}t71;L!-V$RGgu`>d+cs@0snMGXF57LrmmE>L27CNwQT;_C4<Ul? zqL85*GyxgQt|zH?I6U9Vno*(gms#{0;RrIheB_bp>3Oz8F1cDi(iim3?cHikI9?^H zcbIhM-@{8p>Kzm@n6(CXXaUb8D~!~>g9mE3p6sx9BvDldOx9!U2-(@(7;eH8Gb1|c z&OWu<oxVJx?i&ENP%?G1`Unhp=8JM}`jA&P(pNq_WmhD4D|{rscBhCGGk2D2F3lmm ziAWdI-tLzc{<MDfCGxR#(Tu~+5-Ga+;DhD<`+{7D1}=01=-{p&a>i+!6NCGDS-?*l zD!;9x%y5<QX*pH5W_YUa75n8V+`UiDBMxKXnG?PU3Da2npx)iYwJ@SqEzcY3FV`5N zdy$?cpLp`sx>i;+xH3wZmjdI+^w~L?CufI~kYHZC5_-OE$~-YyoWJ`xk<aa^;wnW} zU1@t$9_Yh1tLo?%uGFJ-&RD-h(5|N<F{itkE#uyDW_d<ONgye5kX}X==Hl7w@*!?3 zPr_x-=U#tShCOacCod#P@~m2U*_FKvLGGId6eWHhG4xG>W&WVwG??y{;IglylSn=# zzWx-p+?-gquLS~e6-upPjBY2<1h=>>?ZFmXiLjSFUjwEW(L>)-Vj}&aGpSFl73&wD z*(`ik`Kj&h6RNO54%Z{U@q6a9wWnj!#jopm(R|KP<DHKq#J_Ky77Isy1jnP^GutS# z*&^c$aQYJ;2z)-QsRiG9ERJM9urO(rKOkv2UmY=pR(L#D=d9n#&rXYeas41nl&f#v zeci|}>~@`SGxodRb3Ma4Lzu6droOF~W~H^2AGBNuC(jHu^8k>EAQBMQu|G-~j}{;+ z(3aI^sCB7Bbkub4G{)~_rT!_Y4O6iJYQUJ0k|9vvpZ<Vk0h(_fI*6Fn1g|e?%L=$= z>5cRHrpylaTg7A})dH<5t79K433V;QXG+}`B7Ci@lfkIOqO0+hmXJCH*9qm&N`+QT z^nS$$U2;7?%h!|MKHz3!it6ey!=8$S?K5B^ML0Y;(9||B^3|kiS=Rtv^`np35L`qE zeGU${Oe9DBDfQrL*O$;_ndNZUq9F8f08p?7GoAQ2Khd;0&T*DD3IPylt7-B<`&!~$ znwJ}V09XK_Xt3jn0t%K6)>nQj5IDP&29rIgp<rOfEXb-4Vo{Cq{bKr>0EZS*81?nG zo)|4qH=Bt5<#=f|R8wsEvsRZ}(d3-#Mooq<wCg5q%=#WuGwPC8I)AvoYZ==JA(Yi{ z&f)BmOL0kyrKqV(wt@YWh5~o#7wsWv+{LYq_Cnf^B>`0TABVesvM(C^M36tmnC|`c zO}RXC04nJM;SQPNG;O(gztUj^0~h7E9KtmT65R4!|BcA@ehf9TigMkq*(ke=9FN3K zSEoi@+T+uzxm$;zQd)<=nQPO6DKg+DN~s}N>+mua(=UlNA&^aKfnY6!Q?YYx+96Ob zEJy$f7S?2z#U+5j8l<PD`9siY#F5Qge|>+Xiq3_%AO<qcqFd9cuwp#~PRT+gM(Rx+ zw*V0x{|+U0j{6-R<|Q^9-jiEwSCD}SBS$OZqCTvPGnn!TsMSN(CQv!518XRojvlle z&XzPT#lgzAt)iHDgpZj$=$vkSN|p5Fa868HBxOBe5$JfmN<_u*tSE5U+$_($d?gbY zSS+Bw1lr(}9L-)DF*+S#I6e_EK@;+|%qmfU<p~*Y?8$l$HKDLmB$l>fKT-@E$C`#W zcHG=kn#NeNQrcK$U7&xf+}NmRukP3A8K33~cP1)LBUq5jO9F+=I~E)YK?Do0sGyTm zF6Y&s9Sy3!sRYO@&)vXER8$jAKgGUJr@oqD2(xinYnZlZ49>iYydmH$aFHRGa#AW< z)Uut6t(41Qmbh+JV2}Jpp~yvih@SoO3UKfgL*anKdP<b7L*K?&(;@BKit3%E-gYf4 zm7%Uwm8UW-@vo!W)0CvD9!&B=@9#d|9dfXK@tw`us`4PQxkbZ)OA!8GOeEVWO)VU~ zg2|&s%Lw(bBR&=nr5XJ}G)qzXtRhOYxi8o&Y6*_Q#p-33O%x?oJnV<LORuUrcY|y; z5o=U1)^n(?_6!m}O~1rmiv-tZ{QAhA1GLY<UT0h;>VPDj7Ify}UM@xj=J+{4Vumfu z-2&TGupBe+QYA5cy61&P9=-Lw-S*gE#tDj@akz4L0%OMlZN{ZLb3oj*&5XYKZTIJo zRU<Xqy@pI=gR>*lka=K8C_v-Gw5^v*Pg*Yk8_BD!)N}1&)J2E<?DNm|G4+I>UF{bL zO_mMoHoIv;V!E6`&-l=mZ7vd-NaP?w6K*s*o|(Y%x-;f`Hm0IIO-)A8`64roTCeLh z7u_^u88`tJ{BgoD+R)x=b;32%rr=+t+eG__FIXtY_;VgTK`0N!+jMXvi9@#`Gd1iw zs80Ly`K7WC;&byozC%fn7l`k^isHaym~kMOreqSM>d2Ky<q^sWs>ngXzy*7zpHTcz zJ1O}r#!zmb%x^bJ05b}U91938KWpGT6e8}#@M;5~L2Tl?@X<?c7iBW{BQWB&B_w}h z{~p{g1SC>@&S=-h&m=P*Sl#J!_bS4Z&>8HiFB2kFxY9X9jHq#SNjX5v^q>v2K=an; z%e;D8oSk%>S>@4%VBcnXN7;r|U2Rlp*!m5PsHheTo&KN#-;R}YypDJbZGp`uQ_#M| zHO<oVo7Sz?=x5wT&{?6k_L<Yt{1d{j#JhrQX}!Ebcu>N;kiIv)JH3DTYk0)r3YoL8 zo;S09HI<9x_{hq<;|()tipw6atIEoH_1F1L<Jf1ge&gb2!}&`eDWbt(1sl15yLO@I zp;i5$xIIfTV;?O|wt&f`wCxG2IADybcBNjOb8Y&t-!?Hs%KC(4Wl(Tc>N2zTrcGs? zbJ(~<7pZ}DMnzK-@`67f-^ppyhzvP>{NPiq(gOb(#ma^gl16X~{@k62#8fH1q)@C% zl0X_?3u_FzrE5CD<$+&sMlJp)%L>oi)^7N<-y*x$w{#b>OJx$|$A0e?j+Ode7Ge<s zY%yIZ3Br}k7K}#HwWD-<iIhtgJaf;B`OX6|?YlnD5*<Ges<jSi0L;wJ*4i3G@tB7j zdQs~)e53bWOiSVh!alM_p$3&?UeH(#5F+gNl4F)%NC)^nbZA^A%3N%jL~q;>)sqqd zDC+n)aZONt1q~x~3LrAE0Iv4mZ_|Ttk)kWMbJ)QWeDI9n00>2tDa0mmEu<f!1h!`3 zGANMm%!4s1+^0t`44Y+oj0*w>ktrF%jJuB;Wswg{o1*bfQ-^-$@=|Fzx6afhGN#=r z^qFr8aUaD<AGqSwsGW}N_AidveElhs6@CjtWF)(cA8_BQh<5<GMe@@&o$1a!J@uhb z6)Xy>s<XGZ8|K2VU9FvGv>g0^=KgRekydxY-|CyQV)N#}KYjkb^Czd>g<Ha`DKhSK z`br;LMNXhp__s3JPtem$Prh59h&szGLN%3^O#1q<r7{JaM3qJet*u6^7_8c?uk<fH z(>m6a!*dbx@|9pTuP<LN>@#z#GEZ|yV`zWcc@J-;O)%tT8DYb8KeqG|<DRdNBzMKs z*FhDH1lCupqH;Jb(?mGq%uBR=kW+^}tNvib?#IORN?eq&<t_x1RNh5(JexK!9v#wH zg@M>vsKF58kPT6|D}fM^qGLddhb+aOKB={ZWCo}Gf^NkQLo@j)7`F2FC|0-3@a9sl zNGCDkE!Iqz%$Gv&%U6Pai(9Cr2xiLP++KA@P@(c3(@I#{+!pv1N_c%`PJzeL*VyB= z_T$xJHOkzsp<T;5`F$PBJM8J<r9a4{+@t*yE`=gjNK>JBE$hLH$xb?YnTx}AaoJbA zgZi8WBPR2B0p8ke!%kHJ_YKRVxy4*g^?CxabLd)Z(R>L|<2ELjhrR{6N(?p?$?y6e zLL9%k53rm0&eP^t6W4Frb*{H8K17|%hE@+|epcr2T476><hUWUl>4mrQ+wDZdf>!b zV~<~@7eIV+qBtC(H|uZlY{DP34oOV!gd=9ALX4;q8MXilp+~}6vkmjn@xq#VM=dJs zl1{0(6GE}9qYCus5QgPWiz0A?vWKFERj7#$$-!ZNZ)T$7!5}~F2QAoM=W@_uI4K;H z^JUF#tHPJ`{>5GOko0%4-w&3Tr>%nZ`>l&!d|Gr?hOy`2KHLY_`mzr{`ZS(~*pY=& zd%DCH9RebsFmJC<GQi2PZODoXN?hKllj*FpPSZ}FBq-z=UrBh4-mMfk-rnW&>Me<X zyh4f^Bzo@&b*HIAvcQNukXAL;?PX0S%wp5O!D!5Vwd;dHMOVGOM&X0#A7&~XuRO~8 zi8ivI@P<iqO8&4X-eT$4gh?sLoejD&p@c%m%Z*wMiUJeCN{9u!^#+9y&xH8aZ~5J_ zY?g#qNG*H}wco(;^*-s;@i&PT(e%*o;4|ak*x59`)1Y#P8B@<hHs_{D3N^MBNDC@? zkl#673lBe+QQ^u_84a>2wC;Teh*2KTij}<|)~R(44X3CHwLWHtvep8-fCPpBIl4Q9 zMwUxer2a6Z%LK-|K8f}tGoU=-{ZjW`PfrhOIQ;MIquP^Z9rg7OViLSdXXIbpI+;8z zcPr<zahtOFs}?)86@NbY*gTRFztjJ&GlCRutA$(^soB+jev@sKGRuM-M_gvb{Ugv_ zcJiz)m$Jo(S7C;_#|!3{yiKWylpkPxpy?R)1MG-y(&15P`=Ns}AI=xPJH8JX7p7z; z^xW`yJT3mOB=H&rP6}B*NZk`R17Mw$p=X#nL@kDTW|X{4K>V&CZEoax&q#fwbrnuX zp|mKIk_uEngH(cqQa|INEQQthg_xb%2Ykkv&aKG3aF}><w$wJYsG+FMp|69#!-Pli zeHmb2yvX9N7Q$>;azBbFgOGA_Y`z7WH)W)c=j&*E&iKIOIv*?H85CHkY97>GjwBlp zSKXL#$B+a-^Vx)9Gn>Zs*{T)yx1tpkt*e<iF{RHkC|Ts4>53U$-&cDL-tC;&<9JiT zo+6=<bhWeK*w~hPxJy+S)Z((fZ!PgIx`nel&(0JbXEeEsF*mXOjcD~1sf(2dn?S#- z{(@SYgYV-=^=JgOX`1pqgkoq3qI@Qi;^-NVQ;6dQa&KtJKBFk1KeXmB^=s5vE<78% z<-2|>&9)amTyX4057a=mKl@<W=jFT$^2@yI8?SfhV|%i>+xMeQy<PF9&%|87W{$KL zM9oBjjk$NLvc#4h-A^!1{qmRt<K2KU5i#mRIQXGp&WWh$9}%1wmrfzq0NtJlUFyMb z^Z-JRbj#1FVre_YkFm1IQ=D1-1l1bBw~+H&Wa{s;aT2S~oX$KnH$mr*`h0jkC}|5l z#X%ms$+plA%Qjc>o}J<yV&tB|p!bI@_N$cws9^66n(BbDs`%}eXXngyf;+C408hV5 zM=U;=Za}~+;&oeC8)kQWDp}<3)C+!7XdSt&GGPi{`M{bIYyQaTjLf@^Mw{I9g-h1l z6*LLSwj`}c!f1sE14}15uhh0Ru4qyr4X8)UFPtcW=qu<AyhTWJJn*J?G2fiF`@E3l zJx{j$T`CdC539GQDYBe&{Gsk7zW1nT5;Kb_(t6HZVI#v9pkKK0!1{Qved#3OuqbH4 zs2dd9!Na30FlmQpuZC%|Hj!QrXE7LHqj+xVVGGuctO;^~(CrtZG!quH$mS_bj)2p_ zVm&9Kj1k$1XF=e|=!+>-_w5A-w*nDJMnJzXfAzzU>ZA#po!*Y+X=YTE@8)$Y`|hv1 zXAvXkamOVvGtUwSl;Ym4+J%0e&i2Ik;B6d;o@HOiq6~S?we=jPzo+Y;4lJ%J)3^s$ zw>W@}?RjlpDW1OQa_}!`f7KK9&U&6Q;6&{(8%w1l8CHSE;lXx5nnYkjd2jkUb0sNd zRq1TQ&Y0S(Vn}P>AeVdqXU@L&2}hom4k|)b7usPc4E-VwwLWtZLf%_xml^?|i$Hh3 z-V9T54cfZ@T576Hs@F=Hkm60%WKDoibWd<kNF#MY4Fet+3MYt%edvO7jb>$HosJW8 zPbLLt$=6fTh`otA$|^sFxC=AmEYmT3(kjArs_blUCWbJWcV2_WVst|i5>Mg5xF8FT zlyt`C3c{>|<U!y|^r1S!nl=RRU$gcyKcHfN?2Q_rbb<tA0#fNQRRBHaFf}_un7vjl z6+o-Rg#pg;NDbIwRKy>U!aFHSfLs`C)-6&OC5bie^mGlW^kliwVeE6_iWR-5Ib@1B zIr3xA$)g&@2u6^@qWk+!0a^`%!PB&Zs|o|{JQeJyNc^xftI3o8kJ&6Y5tpG~o>2Up z;ym>O>-!FCK0aw~&*mY|8=`OD@RjNPG_qJWAdZ8#^TIc3`)1wT^0F;W9#!=VS46g7 zL{{|X^VAFFplOtGI4qdj(J$zvEP;dECsRf@kT76M<M5kXI93%{FH4cOzmuFghj5g~ z=o{fq1T8cwW_Tdmi5S;T0roZ=GE`x#JKU_bqa^XSRhZSpbJo=kuIO>hg9zU_LTaFj zqZ~J^H4HwSF*2|>!<O9CYyetTV?a$pzL%%45o#0X1`B1QAN|t%@>w+VO0%<Pwm$l+ z11R+&r*%#QgOn6{_8f)j$0Mb06n)y;@3X{B(002PZ~wk@!5{*`4QwUg){CO4ycSmD z;A2M-U8xp=YI?{fj^;)`uR46m6d;;6nbBsgkLM=`cM;YrHd&u@v{$*>-A6>0=8@mU zx*gZA9@{V-VxJFN1gtn;E##@`lgo;!lp%aX-2Ux*7Q$w{--m^&iU*`-iu}DZWfQ_? z_UnQiy_D~8%kXaKvgz({BrnUOJo+4BpnicSS21_??u!6cxU!+ps5GZnWGEwB0vA#o zs@T$Q2?-i2b7r4uK?6xxnb0~=;1RW$Zq=8^U8_Q(@rF1{g&9wSWB*QS@<QlmhtY_? zo_LO}aBvv_a_3k4N0XQXp<YYjS^7Ee5+Ydb_6Ap^I!us1C=wJqIGt3lJZwH|nt6T< zpc5twdkiC_)jKiQ*~a8vh~__)V~PRDeghmx-kB*YOB~8QTVb@WsxG04vy1HQzz9Q> zDd<2+shS&_P$P^6;|I8o$1^V_8kukfy{430CfjvT%>2|RYHll(HO$&Xi6|bQ<*`nm zF5t+Rj|fnVu@Chmb06(TrnT%NBMva!^R}5Ee7HZ0!#bTqtNOT+Cih6*T5<x^BD{wA z>;<czzM}7A1!o<n2sQwB6*7cTg@094Ze@m4hIO_KJv@CaaI7tO8K~5OscQQIX?0q! znt87Ru5GcLMe67$Yfx?!mLx4u;)xHtj^;k%&g4FK<^$zSKpryEjrVXHxJEObcxmw8 zpgiU>5wW_D2+m_wpy()-r0ZwhxU3V?QeWrAN38KhEq}tXtGW#tNt`+66)Zuo`l5qq zzh=4aT;f+PzVIpSphi<gN}s>UGpBBTr*wtzGqU~hioiKGXpFondZCI|PkAlJ5%!?H z%J2Q{vR!+bUwQUURaIrUU3+%D)&Z0~rV-Qv5%meC$0wV+-gnuTli5TQnCfdtAt}Wu zSX4}fRu)QW0VVVsQKlV)%SS3^jfgQ}nM^XYEYVUu-MB>2I^kN)QS%r-uJ}N>sBbnA zT2;j>Pbz6&3tbhr&o|e+y+6co!z&WCsj?=?dVbD{G4ot$$8$%80XL3z>$7_b2%H~~ z<<3_%4^qF77buwy>W4oXlR`v-sp+X*+a!*2{CufA&#4?|Ai`8dzYqbE@^HH6#08rU z6>@+qD_`u+8x?0W3<d4iSH5ZA-Dr6^8FgCCC;t$#xqA=6{Uw&_f02Iv#}1kU1mga0 z<umAyS@R$DBfX-jIY3z*pz|irWaR*|asgC5P2D{F04fqv;?7PUmOdT~|51#-sg3`u zlLQ}-or9O1hn<%l2m-V7>anxay}kaM`A2N|A8n<Io3n+dxuqN6Uvs{h^ozS$ntIqe zJ4u*&SiVV*|E0@hQ*^fYpY8u^*Y4wHX@$fN0D+O-e1HGz0C0i9oM3<z;NKV*kdymO z$^GX5IQ<vK&I<&;*&_c119I^I-xSP$!QL8gLh8R^yui27|Bi9K$+G{70lBz&-opQL z{EvCTfAahb#=*_a^^fuX#rP`^$i@36;{Gf4@77<jw`~6z^B>CJ`f~CDf&V}Ag5I>_ zf3Lw?%shYZ3k0#hIWhk=mNyLaCM5pX?Ek6#TV1&RUW2#X*#CiXga6r=o8up`0J*_` zwki1Q9NgTzf3N*pUD)5Qyua``d4T_jnUkA`_wTX1@!0>K8z&El>+k3Mt)}dMuL~zH zH}D_h@q+%5?;G!b!Faj<p2yqy0RKG?5I2bP@A17w_ht_8*L>f29RJ{PbG_|n@K+ue z5cno-{s+eMPafz0ycay&Ol=)3-H`qmCaBx`z1_cWdoQRtJ9_~BT#<ja;E;8)at8dl z|Np#~0O$h*z`P)HP7sIbpS6OM(+ms(a+vd2Sz4KbI5<qLEG&eO{@;{;d&9eXye&=t TS`gmsyTL#t8X8GuDWv}cOaa=z literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/LagrangianMarkers.png new file mode 100644 index 0000000000000000000000000000000000000000..ea4628c990f0385f2a5ef3ce6a34a890006d9bbb GIT binary patch literal 364547 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%0A+pK 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 bJ*FovEg}2<-0lkaYuL%-#>Zai*oOWeT|czs literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7a922ec760435d8ff91cc8d246c011261f3c629b GIT binary patch literal 48072 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/OpenFAST.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d9084e3f5d9f2d35f77f2c1931fef9268b924d GIT binary patch literal 92541 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 Yg+ztLI!tg!z+*hEhk9!7RIDTZ3n&ZTfdBvi literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.pdf new file mode 100644 index 0000000000000000000000000000000000000000..064309fe64a9c2689d5068044f02ddb7569225cd GIT binary patch literal 11847 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/Stencil.png new file mode 100644 index 0000000000000000000000000000000000000000..7097d3b0b24209b60966eda3a8166201f8f158e9 GIT binary patch literal 13929 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b0c1fb9c1094845adbb74958b8bfa9b368ca0457 GIT binary patch literal 5268 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.png new file mode 100644 index 0000000000000000000000000000000000000000..a4973027c196cf228040bbdf219947723f306e2f GIT binary patch literal 98584 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 ZD>cL4%bmr{=|}|sVPutMaxWPB{2!I7u^<2d literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.tex b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.tex new file mode 100644 index 000000000..4f2289dd5 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexCodeWorkFlow.tex @@ -0,0 +1,80 @@ +%% Creator: Inkscape inkscape 0.92.3, www.inkscape.org +%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010 +%% Accompanies image file 'VortexCodeWorkFlow.pdf' (pdf, eps, ps) +%% +%% To include the image in your LaTeX document, write +%% \input{<filename>.pdf_tex} +%% instead of +%% \includegraphics{<filename>.pdf} +%% To scale the image, write +%% \def\svgwidth{<desired width>} +%% \input{<filename>.pdf_tex} +%% instead of +%% \includegraphics[width=<desired width>]{<filename>.pdf} +%% +%% Images with a different path to the parent latex file can +%% be accessed with the `import' package (which may need to be +%% installed) using +%% \usepackage{import} +%% in the preamble, and then including the image with +%% \import{<path to file>}{<filename>.pdf_tex} +%% Alternatively, one can specify +%% \graphicspath{{<path to file>/}} +%% +%% For more information, please see info/svg-inkscape on CTAN: +%% http://tug.ctan.org/tex-archive/info/svg-inkscape +%% +\begingroup% + \makeatletter% + \providecommand\color[2][]{% + \errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}% + \renewcommand\color[2][]{}% + }% + \providecommand\transparent[1]{% + \errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}% + \renewcommand\transparent[1]{}% + }% + \providecommand\rotatebox[2]{#2}% + \newcommand*\fsize{\dimexpr\f@size pt\relax}% + \newcommand*\lineheight[1]{\fontsize{\fsize}{#1\fsize}\selectfont}% + \ifx\svgwidth\undefined% + \setlength{\unitlength}{1584.33259703bp}% + \ifx\svgscale\undefined% + \relax% + \else% + \setlength{\unitlength}{\unitlength * \real{\svgscale}}% + \fi% + \else% + \setlength{\unitlength}{\svgwidth}% + \fi% + \global\let\svgwidth\undefined% + \global\let\svgscale\undefined% + \makeatother% + \begin{picture}(1,0.37987951)% + \lineheight{1}% + \setlength\tabcolsep{0pt}% + \put(0,0){\includegraphics[width=\unitlength,page=1]{VortexCodeWorkFlow.pdf}}% + \put(0.65944109,0.11446444){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.25535428\unitlength}\centering $\vec{v}_{i,ll}, (\vec{r}_{r})$\end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=2]{VortexCodeWorkFlow.pdf}}% + \put(0.63558708,0.20735708){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.20717198\unitlength}\centering \textbf{Vortex code}\end{minipage}}}% + \put(0.60215168,0.18502836){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.27356877\unitlength}\centering $\vec{r}, \vec{\Gamma}_v$\end{minipage}}}% + \put(0.32921211,0.30084711){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.30485953\unitlength}\raggedright 1. Tower shadow model\\ \ \ \ \ (update of $\vec{V}_{\infty}$)\end{minipage}}}% + \put(0.32826903,0.23341478){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.3956149\unitlength}\raggedright 2. Induction computation\end{minipage}}}% + \put(0.32826903,0.13392726){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.5344643\unitlength}\raggedright 3. Quasi steady forces on the lifting lines\end{minipage}}}% + \put(0.32826903,0.08442459){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.51629305\unitlength}\raggedright 4. Dynamic stall model\end{minipage}}}% + \put(0.49325791,0.33819968){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.20355574\unitlength}\centering \textbf{AeroDyn15}\end{minipage}}}% + \put(0.79169925,0.10320964){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.25535428\unitlength}\centering $\vec{f}_{ll}$\end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=3]{VortexCodeWorkFlow.pdf}}% + \put(0.79577993,0.29769798){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.25535428\unitlength}\centering $\vec{r}_{ll}, \vec{r}_{r}$\end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=4]{VortexCodeWorkFlow.pdf}}% + \put(-0.00885268,0.27822337){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.20355574\unitlength}\centering \textbf{InflowWind}\end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=5]{VortexCodeWorkFlow.pdf}}% + \put(0.69583824,0.27908716){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.08495527\unitlength}\centering \textbf{BEM}\end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=6]{VortexCodeWorkFlow.pdf}}% + \put(0.01537801,0.32400133){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.44217675\unitlength}\centering $\vec{V}_\infty=$\\ $[\vec{V}_{\infty,ll}, \vec{V}_{\infty,r}] $\end{minipage}}}% + \put(0.02471082,0.17907865){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.41731078\unitlength}\centering $\vec{x}_{\text{elast},ll} =$\\ $ [\vec{r}_{ll}, \vec{\Lambda}_{ll}, \vec{\dot{r}}_{ll}, \vec{\omega}_{ll}]$\\ \end{minipage}}}% + \put(0,0){\includegraphics[width=\unitlength,page=7]{VortexCodeWorkFlow.pdf}}% + \put(-0.01097736,0.13673){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.20355574\unitlength}\centering \textbf{ElastoDyn}\end{minipage}}}% + \put(0.57551823,0.27600282){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\begin{minipage}{0.41731078\unitlength}\raggedright $\vec{r}_{\text{elast},ll}$\\ $\vec{V}_\infty$\end{minipage}}}% + \end{picture}% +\endgroup% diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.pdf b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d4486621d83faf3eb86c92c0fb0eec0d57b69496 GIT binary patch literal 35491 zcmcG$WpEtLvNkwkw3wN}VjeLwGfNgr7Be$5nZ#%@Gc)6enZYAQi)F3+o^$TK-?zIz zHg-2+qPr_AYbrA<GrOXyo~BljkYZwE=0v1!Jga&}<RoJyb2R;oC?G(_qF~`*<z`LB z^-fYlBqJkZk+QLKvv7I8+nKmoNLZLTnp+?W2_d?=xmcLkBYI^X_>b2y4Lfgibep0= z@SdxBF8OXF^w&|EucFtX??9A5ENo-vE#o%Ofp@w+s~YP_d@o#?MSbbm0htEvZAQ9@ z6%!Q|drfO^!o+vg8e{q!u6(O!Pj#<*9_yEH!hc@RSOVL({`|>l%94E>4s1R9X2-&| z`DdY~yD9LG$@3qa&8b&A>O|o`ix_V;gKL59uX|_P#n1Y-zoTdo7%0A7HZ}Y3-@V}I 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.png b/OpenFAST/docs/source/user/aerodyn-olaf/Schematics/VortexLatticeMethod.png new file mode 100644 index 0000000000000000000000000000000000000000..2db30e3972645616f04adac036539d4475872dac GIT binary patch literal 34658 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%0A<BNcu9Qp{^*y**5p4u{q0J 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 CP*iLH literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/StateSpace.rst b/OpenFAST/docs/source/user/aerodyn-olaf/StateSpace.rst new file mode 100644 index 000000000..501e93957 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/StateSpace.rst @@ -0,0 +1,185 @@ +.. role:: raw-latex(raw) + :format: latex +.. + +State-Space Representation and Integration with OpenFAST +======================================================== + +State, Constraint, Input, and Output Variables +---------------------------------------------- + +The OLAF module has been integrated into the latest version of OpenFAST via +*AeroDyn15*, following the OpenFAST modularization +framework (:cite:`olaf-Jonkman13_1,olaf-Sprague15_1`). To follow the OpenFAST framework, +the vortex code is written as a module, and its formulation comprises state, +constraint, and output equations. The data manipulated by the module include the +following vectors: constant parameters, :math:`\vec{p}`; inputs, +:math:`\vec{u}`; constrained state, :math:`\vec{z}`; states, :math:`\vec{x}`; +and outputs, :math:`\vec{y}`. The vectors are defined as follows: + +- Parameters, :math:`\vec{p}~-` a set of internal system values that are + independent of the states and inputs. The parameters can be fully defined at + initialization and characterize the system state and output equations. + +- Inputs, :math:`\vec{u}~-` a set of values supplied to the module that, along + with the states, are needed to calculate future states and the system output. + +- Constraint states, :math:`\vec{z}~-` algebraic variables that are calculated + using a nonlinear solver, based on values from the current time step. + +- States, :math:`\vec{x}~-` a set of internal values of the module. They are + influenced by the inputs and used to calculate future state values and + output. Continuous states are employed, meaning that the states are + differentiable in time and characterized by continuous time-differential + equations. + +- Outputs, :math:`\vec{y}~-` a set of values calculated and returned by the + module that depend on the states, inputs, and/or parameters through output + equations. + +The parameters of the vortex code include: + +- Fluid characteristics: kinematic viscosity, :math:`\nu`. + +- Airfoil characteristics: chord :math:`c` and polar data -- + :math:`C_l(\alpha)`, :math:`C_d(\alpha)`, :math:`C_m(\alpha)`). + +- Algorithmic methods and parameters, e.g., regularization, viscous + diffusion, discretization, wake geometry, and acceleration. + +The inputs of the vortex code are: + +- Position, orientation, translational velocity, and rotational + velocity of the different nodes of the lifting lines + (:math:`\vec{r}_{ll}`, :math:`\Lambda_{ll}`, + :math:`\vec{\dot{r}}_{ll}`, and :math:`\vec{\omega}_{ll}`, + respectively), gathered into the vector, + :math:`\vec{x}_{\text{elast},ll}`, for conciseness. These quantities + are handled using the mesh-mapping functionality and data structure + of OpenFAST. + +- Disturbed velocity field at requested locations, written + :math:`\vec{V}_0=[\vec{V}_{0,ll}, \vec{V}_{0,m}]`. Locations are requested + for lifting-line points, :math:`\vec{r}_{ll}`, and Lagrangian markers, + :math:`\vec{r}_m`. Based on the parameters, this disturbed velocity field may + contain the following influences: freestream, shear, veer, turbulence, tower, + and nacelle disturbance. The locations where the velocity field is requested + are typically the location of the Lagrangian markers. + +The constraint states are: + +- The circulation intensity along the lifting lines, + :math:`\Gamma_{ll}`. + +The continuous states are: + +- The position of the Lagrangian markers, :math:`\vec{r}_m` + +- The vorticity associated with each vortex element, :math:`\vec{\omega}_e`. + For a projection of the vorticity onto vortex segments, this corresponds to + the circulation, :math:`\vec{\Gamma}_e`. For each segment, + :math:`\vec{\Gamma}_e= \Gamma_e \vec{dl}_e =\vec{\omega}_e dV_e`, with + :math:`\vec{dl}_e` and :math:`dV_e`, the vortex segment length and its + equivalent vortex volume. + +The outputs are [1]_: + +- The induced velocity at the lifting-line nodes, + :math:`\vec{v}_{i,ll}` + +- The locations where the undisturbed wind is computed, :math:`\vec{r}_{r}` + (typically :math:`\vec{r_{r}}=\vec{r}_m`). + +State, Constraint, and Output Equations +--------------------------------------- + +An overview of the states, constraints, and output equations is given here. More +details are provided in :numref:`OLAF-Theory`. The constraint equation is used +to determine the circulation distribution along the span of each lifting line. +For the van Garrel method, this circulation is a function of the angle of attack +along the blade and the airfoil coefficients. The angle of attack at a given +lifting-line node is a function of the undisturbed velocity, +:math:`\vec{v}_{0,ll}`, and the velocity induced by the vorticity, +:math:`\vec{v}_{i,ll}`, at that point. Part of the induced velocity is caused by +the vorticity being shed and trailed at the current time step, which in turn is +a function of the circulation distribution along the lifting line. This +constraint equation may be written as: + +.. math:: + \vec{Z} = \vec{0} = \vec{\Gamma}_{ll} - \vec{\Gamma}_p\bigg(\vec{\alpha}(\vec{x},\vec{u}),\vec{p}\bigg) + +where :math:`\vec{\Gamma}_p` is the function that returns the circulation along +the blade span, according to one of the methods presented in :numref:`sec:circ`. + +The state equation specifies the time evolution of the vorticity and the +convection of the Lagrangian markers: + +.. math:: + \begin{aligned} + \frac{d \vec{\omega}_e}{dt} &= \bigg[(\vec{\omega}\cdot\nabla)\vec{v} + \nu\nabla^2 \vec{\omega} \bigg]_e + \end{aligned} + +.. math:: + \begin{aligned} + \frac{d \vec{r}_m}{dt} &= \vec{V}(\vec{r}_m) + =\vec{V}_0(\vec{r}_m) + \vec{v}_\omega(\vec{r}_m) + =\vec{V}_0(\vec{r}_m) + \vec{V}_\omega(\vec{r}_m, \vec{r}_m, \vec{\omega}) + \end{aligned} + :label: eq:Convection + +Here, + +- :math:`\vec{v}_\omega` is the velocity induced by the vorticity in the + domain; +- :math:`\vec{V}_\omega(\vec{r},\vec{r}_m,\vec{\omega})` is the function that + computes this induced velocity at a given point, :math:`\vec{r}`, based on + the location of the Lagrangian markers and the intensity of the vortex elements; +- the subscript :math:`e` indicates that a quantity is applied to an element; + and +- the vorticity, :math:`\vec{\omega}`, is recovered from the vorticity of the + vortex elements by means of discrete convolutions. + +For vortex-segment simulations, the viscous-splitting algorithm is used, and the +convection step (Eq. :eq:`eq:Convection`) is the main state equation being +solved for. The vorticity stretching is automatically accounted for, and the +diffusion is performed *a posteriori*. The velocity function, +:math:`\vec{V}_\omega`, uses the Biot-Savart law. The output equation is: + +.. math:: + \begin{aligned} + \vec{y}_1&=\vec{v}_{i,ll} = \vec{V}_\omega ( \vec{r}_{ll}, \vec{r}_m, \vec{\omega}) \\ + \vec{y}_2&=\vec{r}_{r} + \end{aligned} + +Integration with AeroDyn15 +-------------------------- + +The vortex code has been integrated as a submodule of the aerodynamic module of +OpenFAST, *AeroDyn15*. The data workflow between the different modules and +submodules of OpenFAST is illustrated in :numref:`AD15-OLAF`. +AeroDyn inputs such as BEM options (e.g., tip-loss factor), skew model, and +dynamic inflow are discarded when the vortex code is used. The environmental +conditions, tower shadow, and dynamic stall model options are used. This +integration required a restructuring of the *AeroDyn15* module to isolate the +parts of the code related to tower shadow modeling, induction computation, +lifting-line-forces computations, and dynamic stall. The dynamic stall model is +adapted when used in conjunction with the vortex code to ensure the effect of +shed vorticity is not accounted for twice. The interface between *AeroDyn15* and +the inflow module, *InflowWind*, was accommodated to include the additionally +requested points by the vortex code. + + +.. _AD15-OLAF: + +.. figure:: Schematics/VortexCodeWorkFlow.png + :alt: OpenFAST-FVW code integration workflow + :width: 100% + :align: center + + OpenFAST-OLAF code integration workflow + + + +.. [1] + The loads on the lifting line are not an output of the vortex code; + their calculation is handled by a separate submodule of *AeroDyn*. diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/bibliography.bib b/OpenFAST/docs/source/user/aerodyn-olaf/bibliography.bib new file mode 100644 index 000000000..90f791db4 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/bibliography.bib @@ -0,0 +1,438 @@ +@article{Larsen08_1, + title= {Wake Meander: A Pragmatic Approach}, + author= {G. C. Larsen and H. A. Madsen and K. Thomsen and et al.}, + journal= {Wind Energy}, + volume= {11}, + pages= {337-95}, + year= {2008}, + publisher={John Wiley \& Sons, Ltd.}, + doi = {http://onlinelibrary.wiley.com/doi/10.1002/we.267/epdf} +} + +@inproceedings{Bagai94_1, + author= {A. Bagai and J. G. Leishman}, + title= {Rotor Free-Wake Modeling using a Pseudo-Implicit Technique Including Comparisons with Experimental Data}, + booktitle= {50th Annual Forum of the American Helicopter Society}, + year= {1994}, + address= {Washington, D.C.} +} + +@article{Quon18_1, + title= {Comparison of Wake Characterization Methods for Large-Eddy Simulations of a Rotor in Stratified Flow}, + author= {E. Quon and M. Churchfield and J. Jonkman}, + journal= {Computers & Fluids}, + year= {2018} +} + +@article{Martinez17_1, + title= {Optimal Smoothing Length Scale for Actuator Line Models of Wind Turbine Blades Based on Gaussian Body Force Distribution}, + author= {L. A. Martinez-Tossas and M. J. Churchfield and C. Meneveau}, + journal= {Wind Energy}, + volume= {20}, + pages= {1083-1096}, + year= {2017}, + publisher={John Wiley \& Sons, Ltd.}, + doi = {http://onlinelibrary.wiley.com/doi/10.1002/we.2081/epdf} +} + +@article{Vatistas91_1, + Author = {G. H. Vatistas and V. Koezel and W. C. Mih}, + Title = {A Simpler Model for Concentrated Vortices}, + Journal = {Experiments in Fluids}, + Volume = {11}, + Number = {1}, + Pages = {73-76}, + Year = {1991}} + +@article{Quon19_1, + title= {Comparison of Wake Characterization Methods for Large-Eddy Simulations of a Rotor in Stratified Flow}, + author= {E. Quon and M. Churchfield and J. Jonkman}, + journal= {Computers \& Fluids}, + year= {2019 (Forthcoming)} +} + +@inproceedings{Jonkman18_1, + title= {Validation of FAST.Farm Against Large-Eddy Simulations}, + author= {J. Jonkman and P. Doubrawa and N. Hamilton and et al.}, + series= {TORQUE 2018}, + date = {20-22}, + month = {June}, + year= {2018}, + publisher={EAWE}, + address= {Milano, Italy} +} + +@Book{Hansen08_1, + author = {M. O. L. Hansen}, + title = {Aerodynamics of Wind Turbines}, + publisher = {Earthscan}, + year = {2008}, + address = {London; Sterling, VA} +} + +@techreport{Weissinger47_1, + Author = {J. Weissinger}, + Title = {The Lift Distribution of Swept-Back Wings}, + Institution = {NACA}, + Type = {Technical report}, + Number = {TM 1120}, + Year = {1947} +} + +@techreport{Jonkman13_1, + Author = {J. Jonkman}, + Title = {The New Modularization Framework for the FAST Wind Turbine CAE Tool}, + Institution = {National Renewable Energy Laboratory}, + Type = {Technical report}, + Number = {NREL/CP-5000-57228}, + Year = {2013} +} + +@techreport{Jonkman15_1, + Author = {J. Jonkman and M. A. Sprague and B. J. Jonkman}, + Title = {FAST Modular Framework for Wind Turbine Simulation: New Algorithms and Numerical Examples}, + Institution = {National Renewable Energy Laboratory}, + Type = {Technical report}, + Number = {NREL/CP-2C00-63203}, + Year = {2015} +} + +@phdthesis{Gupta06_1, + Author = {S. Gupta}, + Title = {Development of a Time-Accurate Viscous Lagrangian Vortex Wake Model for Wind Turbine Applications}, + School = {Univeristy of Maryland}, + Address = {College Park, MD}, + Type = {PhD thesis}, + Year = {2006} +} + +@phdthesis{Scully75_1, + Author = {M. P. Scully}, + Title = {Computation of Helicopter Rotor Wake Geometry and Its Influence on Rotor Harmonic Airloads}, + School = {Massachusetts Institute of Technology}, + Address = {Cambridga, MA}, + Type = {PhD thesis}, + Year = {1975} +} + + +@phdthesis{Ribera07_1, + Author = {M. Ribera}, + Title = {Helicopter Flight Dynamics Simulation with a Time-Accurate Free-Vortex Wake Model}, + School = {University of Maryland}, + Address = {College Park, MD}, + Type = {PhD thesis}, + Year = {2007}} + +@inproceedings{Doubrawa18_1, + author= {P. Doubrawa and J. Annoni and J. Jonkman and et al.}, + title= {Optimization-Based Calibration of FAST.Farm Parameters Against SOWFA}, + booktitle={AIAA SciTech Forum}, + series= {36th Wind Energy Symposium}, + date = {8-13}, + month = {January}, + year= {2018}, + publisher={AIAA}, + address= {Kissimmee, FL}, + doi = {https://arc.aiaa.org/doi/pdf/10.2514/6.2018-0512} +} + +@inproceedings{Shaler19_1, + title= {FAST.Farm Response of Varying Wind Inflow Techniques}, + author= {K. Shaler and J. Jonkman and P. Doubrawa and N. Hamilton}, + booktitle={AIAA SciTech Forum}, + series= {37th Wind Energy Symposium}, + date = {7-11}, + month = {January}, + year= {2019}, + publisher={AIAA}, + address= {San Diego, CA}, + doi = {https://arc.aiaa.org/doi/pdf/10.2514/6.2019-2086} +} + +@inproceedings{Jonkman17_1, + title= {Development of FAST.Farm: A New MultiPhysics Engineering Tool for Wind-Farm Design and Analysis}, + author= {J. Jonkman and J. Annoni and G. Hayman and B. Jonkman and A. purkayastha}, + booktitle={AIAA SciTech Forum}, + series= {35th Wind Energy Symposium}, + date = {9-13}, + month = {January}, + year= {2017}, + publisher={AIAA}, + address= {Grapevine, TX}, + doi = {http://arc.aiaa.org/doi/pdf/10.2514/6.2017-0454} +} + +@inproceedings{Churchfield15_1, + title= {A Comparison of the Dynamic Wake Meandering Model, Large-Eddy Simulations, and Field Data at the Egmond aan Zee Offshore Wind Plant}, + author= {M. J. Churchfield and P. J. Moriarty and Y. Hao and et al.}, + booktitle={AIAA SciTech Forum}, + series= {33rd Wind Energy Symposium}, + date = {5-9}, + month = {January}, + year= {2015}, + publisher={AIAA}, + address= {Kissimmee, FL}, + doi = {http://dx.doi.org/10.2514/6.2015-0724} +} + +@inproceedings{Churchfield12_1, + title= {A Large-Eddy Simulation of Wind-Plant Aerodynamics}, + author= {M. J. Churchfield and P. J. Moriarty and L. A. Martinez and et al.}, + series= {50th AIAA Aerospace Sciences Meeting}, + date = {9-12}, + month = {January}, + year= {2012}, + publisher={AIAA}, + address= {Nashville, TN}, + doi = {http://dx.doi.org/10.2514/6.2012-537} +} + +@techreport{Jonkman09_1, + title= {Definition of a 5-MW Reference Wind Turbine for Offshore System Development}, + author= {Jonkman, J. and Butterfield, S. and Musial, W. and Scott, G.}, + number= {NREL/TP-500-38060}, + institution={National Renewable Energy Laboratory}, + address= {Golden, CO}, + month= {February}, + year= {2009} +} + +@techreport{TurbSim_1, + title= {TurbSim User's Guide v2.00.00}, + author= {Jonkman, B.}, + number= {NREL/TP-xxxx-xxxxx}, + institution={National Renewable Energy Laboratory}, + address= {Golden, CO}, + month= {October}, + year= {2014} +} + +@techreport{IEC_1, + title= {Wind Turbines - Part 1: Design Requirements}, + author= {IEC 61400-1}, + number= {3rd edition}, + institution={International Electrotechnical Commission}, + address= {Geneva, Switzerland}, + month= {March}, + year= {2006} +} + +@techreport{Simms01_1, + title= {NREL Unsteady Aerodynamics Experiment in the NASA-Ames Wind Tunnel: A Comparison of Predictions to Measurements}, + author= {Simms, D. and Schreck, S. and Hand, M. and Fingersh, L.J.}, + number= {NREL/TP-500-29494}, + institution={National Renewable Energy Laboratory}, + address= {Golden, CO}, + month= {June}, + year= {2001} +} + +@techreport{Jonkman18_2, + title= {FAST.Farm User's Guide and Theory Manual}, + author= {J. M. Jonkman}, + number= {NREL/TP-xxxx-xxxxx}, + institution={National Renewable Energy Laboratory}, + address= {Golden, CO}, + month= {Unpublished}, + year= {2018} +} + +@misc{FAST, +title = {OpenFAST Documentation}, +month = {November}, +year = {2017}, +url = {http://openfast.readthedocs.io/en/master/} +} + +@misc{SAMWICH, + author = {E. Quon}, + title = {SAMWICH Wake-Tracking Toolbox}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/ewquon/waketracking}}, + year= {2017} +} + +@phdthesis{Krista12_1, + Author = {K. Kecskemety}, + Title = {Assessing the Influence of Wake Dynamics on the Performance and Aeroelastic Behavior of Wind Turbines}, + School = {Ohio State University}, + Address = {Columbus, OH}, + Type = {PhD thesis}, + Year = {2012}} + +@book{Leishman_book, + Author = {J. Leishman}, + Title = {Principles of Helicopter Aerodynamics}, + Publisher = {Cambridge Univ. Press}, + Address = {Cambridge, MA}, + Year = {2006}} + +@book{Rankine58_1, + Author = {W. J. M. Rankine}, + Title = {Manual of Applied Mechanics}, + Publisher = {Griffen Co.}, + Address = {London}, + Year = {1858}} + +@article{Leishman02_1, + Author = {J. G. Leishman and M. J. Bhagwat and A. Bagai}, + Title = {Free-Vortex Filament Methods for the Analysis of Helicopter Rotor Wakes}, + Journal = {Journal of Aircraft}, + Volume = {39}, + Number = {5}, + Pages = {759-775}, + Year = {2002}} + +@inproceedings{Ananthan02_1, + Author = {S. Ananthan and J. G. Leishman and M. Ramasamy}, + Title = {The Role of Filament Stretching in the Free-Vortex Modeling of Rotor Wakes}, + booktitle = {58th Annual Forum and Technology Display of the American Helicopter Society International}, + year = {2002}, + address = {Montreal, Canada}} + +@article{Gupta05_1, + Author = {S. Gupta and J. G. Leishman}, + Title = {Free-Vortex Filament Methods for the Analysis of Helicopter Rotor Wakes}, + Journal = {Journal of Aircraft}, + Volume = {39}, + Number = {5}, + Pages = {759-775}, + Year = {2002}} + +@techreport{Wiser17_1, + title= {2016 Wind Technologies Market Report}, + author= {R. Wiser and M. Bolinger}, + number= {DOE/GO-102917-5033}, + institution={Lawrence Berkeley National Laboratory}, + address= {Berkeley, CA}, + month= {August}, + year= {2017}, + doi = {10.2172/1393638}} + +@phdthesis{Shaler19_2, + Author = {K. Shaler}, + Title = {Wake Interaction Modeling Using A Parallelized Free Vortex Wake Model}, + School = {Ohio State University}, + Address = {Columbus, OH}, + Type = {PhD thesis}, + Year = {2020}} + +@phdthesis{Abedi16_1, + Author = {H. Abedi}, + Title = {Development of Vortex Filament Method for Wind Power Aerodynamics}, + School = {Chalmers University of Technology}, + Address = {Gothenburg, Sweden}, + Type = {PhD thesis}, + Year = {2016}} + + +@techreport{Johnson19_1, + Author={N. Johnson and P. Bortolotti and K. Dykes and et al.}, + Title={Investigation of Innovative Rotor Concepts for the Big Adaptive Rotor Project}, + institution={National Renewable Energy Laboratory}, + number={NREL/TP-5000-73605}, + Year=2019 + } + +@techreport{Sprague15_1, + title={FAST Modular Framework for Wind Turbine Simulation: New Algorithms and Numerical Examples}, + author={Michael A. Sprague and Jason M. Jonkman and Bonnie J. Jonkman}, + institution={National Renewable Energy Laboratory}, + number={NREL/CP-2C00-63203}, + year={2015} +} + +@article{Miras17_1, + author = {M. Sessarego and N. Ramos Garc{\'i}a and J. N. S{\o}rensen and W. Z. Shen}, + title = {Development of an aeroelastic code based on three-dimensional viscous-inviscid method for wind turbine computations}, + year = {2017}, + doi = {10.1002/we.2085}, + volume = {20}, + pages = {1145-1170}, + journal = {Wind Energy}, + number = {7}, +} + +@article{Bagai93_1, + author = {A. Bagai and J. G. Leishman}, + title = {Flow Visualization of Compressible Vortex Structures Using Density Gradient Techniques}, + year = {1993}, + volume = {15}, + pages = {431-442}, + journal = {Experiments in Fluids}, + number = {6} +} + +@phdthesis{Papadakis14_1, + author = {G. Papadakis}, + title = {Development of a hybrid compressible vortex particle method and application to external problems including helicopter flows}, + school = {National Technical University of Athens}, + year = {2014}, +} +@article{Voutsinas06_1, + author = {S. G. Voutsinas}, + title = {Vortex methods in aeronautics: how to make things work}, + journal = {International Journal of Computational Fluid Dynamics}, + year = {2006}, +} + +@article{Rosenhead31_1, + author = {L. Rosenhead}, + title = {The Formation of Vortices from a Surface of Discontinuity}, + journal = {Proceedings of the Royal Society of London. Series A, Containing Papers of a Mathematical and Physical Character}, + volume = {134}, + number = {823}, + pages = {170-192}, + url = {http://www.jstor.org/stable/95835}, + ISSN = {09501207}, + year = {1931}, + publisher = {The Royal Society}, +} + +@article{Winckelmans93_1, + author = {G. S. Winckelmans and A. Leonard}, + title = {Contributions to vortex particle methods for the computation of 3-dimensional incompressible unsteady flows}, + publisher = {Academic Press Inc. JNL-Comp Subscriptions}, + journal = {Journal Of Computational Physics}, + volume = {109}, + number = {2}, + pages = {247-273}, + year = {1993}, + issn = {00219991, 10902716} +} + +@article{Branlard15_1, +author = {E. Branlard and G. Papadakis and M. Gaunaa and G. Winckelmans and T. J. Larsen}, +title = {Aeroelastic large eddy simulations using vortex methods: unfrozen turbulent and sheared inflow}, +journal = {Journal of Physics: Conference Series (Online)}, +year = {2015}, +doi = {10.1088/1742-6596/625/1/012019}, +volume = {625}, +issn = {1742-6596}, +} + +@book{Branlard17_1, + author = {E. Branlard}, + title = {Wind Turbine Aerodynamics and Vorticity-Based Methods: Fundamentals and Recent Applications}, + year = {2017}, + publisher= {Springer International Publishing}, + doi={10.1007/978-3-319-55164-7}, + isbn={ 978-3-319-55163-0} +} + +@TECHREPORT{Garrel03_1, + author = {A. van Garrel}, + title = {Development of a Wind Turbine Aerodynamics Simulation Module}, + institution = {ECN}, + year = {2003}, + number = {ECN-C--03-079} +} + +@TECHREPORT{Kerwin:lecturenotes, + author = {J. Kerwin}, + title = {Lecture Notes Hydrofoil and propellers}, + institution = {M.I.T.}, + year = {2000} +} diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/index.rst b/OpenFAST/docs/source/user/aerodyn-olaf/index.rst new file mode 100644 index 000000000..e706234e7 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/index.rst @@ -0,0 +1,36 @@ +.. _OLAF: + +OLAF User's Guide and Theory Manual (Free Vortex Wake in AeroDyn15) +=================================================================== + +.. only:: html + + This document offers a quick reference guide for the free vortex wake module + named OLAF that is included in the AeroDyn module of OpenFAST. It is + intended to be used by the general user in combination with other features + of AeroDyn and other OpenFAST modules. The manual will be updated as new + releases are issued and as needed to provide further information on + advancements or modifications to the software. + + The documentaiton here was derived from the OLAF users manual by K. Shaler, + E. Branlard, and A. Platt. (`https://www.nrel.gov/docs/fy20osti/75959.pdf + <https://www.nrel.gov/docs/fy20osti/75959.pdf>`_) + + +.. toctree:: + :maxdepth: 2 + + Introduction.rst + Acronyms.rst + RunningOLAF.rst + InputFiles.rst + OutputFiles.rst + OLAFTheory.rst + StateSpace.rst + FutureWork.rst + zrefs.rst + AppendixA.rst + AppendixB.rst + AppendixC.rst + +.. Acknowledgments.rst diff --git a/OpenFAST/docs/source/user/aerodyn-olaf/zrefs.rst b/OpenFAST/docs/source/user/aerodyn-olaf/zrefs.rst new file mode 100644 index 000000000..dd7761ff6 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn-olaf/zrefs.rst @@ -0,0 +1,10 @@ +.. only:: html + + References + ---------- + +.. bibliography:: bibliography.bib + :labelprefix: olaf- + :keyprefix: olaf- + + diff --git a/OpenFAST/docs/source/user/aerodyn/ADNodalOutputs.rst b/OpenFAST/docs/source/user/aerodyn/ADNodalOutputs.rst new file mode 100644 index 000000000..075561c13 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/ADNodalOutputs.rst @@ -0,0 +1,41 @@ + +Nodal Outputs +~~~~~~~~~~~~~ + +In addition to the named outputs in :numref:`AD-Outputs` above, AeroDyn allows +for outputting the full set blade node motions and loads (tower nodes +unavailable at present). Please refer to the AeroDyn_Nodes tab in the +Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` +for a complete list of possible output parameters. + +This section follows the `END` statement from normal Outputs section described +above, and includes a separator description line followed by the following +optinos. + +**BldNd_BladesOut** specifies the number of blades to output. Possible values +are 0 through the number of blades AeroDyn is modeling. If the value is set to +1, only blade 1 will be output, and if the value is 2, blades 1 and 2 will be +output. + +**BldNd_BlOutNd** specifies which nodes to output. This is currently unused. + +The **OutList** section controls the nodal output quantities generated by +AeroDyn. In this section, the user specifies the name of the channel family to +output. The output name for each channel is then created internally by AeroDyn +by combining the blade number, node number, and channel family name. For +example, if the user specifies **AxInd** as the channel family name, the output +channels will be named with the convention of **B**\ :math:`\mathbf{\beta}`\ +**N###AxInd** where :math:`\mathbf{\beta}` is the blade number, and **###** is +the three digit node number. + + +Sample Nodal Outputs section +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This sample includes the ``END`` statement from the regular outputs section. + +.. container:: + :name: File:ADNodalOutputs + + .. literalinclude:: examples/NodalOutputs.txt + :linenos: diff --git a/OpenFAST/docs/source/user/aerodyn/appendix.rst b/OpenFAST/docs/source/user/aerodyn/appendix.rst new file mode 100644 index 000000000..add85ba4c --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/appendix.rst @@ -0,0 +1,69 @@ +.. _ad_appendix: + +Appendix +======== + +.. _ad_input_files: + +AeroDyn Input Files +------------------- + +In this appendix we describe the AeroDyn input-file structure and provide examples. + +1) AeroDyn Driver Input File +:download:`(driver input file example) <examples/ad_driver_example.inp>`: + +The driver input file is only needed for the standalone version of AeroDyn and contains inputs normally generated by OpenFAST, and necessary to control the aerodynamic simulation for uncoupled models. + +2) AeroDyn Driver Timeseries Input File +:download:`(driver timeseries input file example) <examples/ad_driver_timeseries_example.inp>`: +The timeseries input file for a case in the AeroDyn driver allows the parameters +to vary with time. This feature can be useful for debugging the aerodynamic response +outside of OpenFAST. + +3) AeroDyn Primary Input File +:download:`(primary input file example) <examples/ad_primary_example.inp>`: + +The primary AeroDyn input file defines modeling options, environmental conditions (except freestream flow), airfoils, tower nodal discretization and properties, as well as output file specifications. + +The file is organized into several functional sections. Each section corresponds to an aspect of the aerodynamics model. + +The input file begins with two lines of header information which is for your use, but is not used by the software. + +4) Airfoil Data Input File +:download:`(airfoil data input file example) <examples/ad_airfoil_example.inp>`: + +The airfoil data input files themselves (one for each airfoil) include tables containing coefficients of lift force, drag force, and pitching moment versus AoA, as well as UA model parameters. In these files, any line whose first non-blank character is an exclamation point (!) is ignored (for inserting comment lines). The non-comment lines should appear within the file in order, but comment lines may be intermixed as desired for reading clarity. + +5) Blade Data Input File +:download:`(blade data input file example) <examples/ad_blade_example.inp>`: + +The blade data input file contains the nodal discretization, geometry, twist, chord, and airfoil identifier for a blade. Separate files are used for each blade, which permits modeling of aerodynamic imbalances. + +.. _ad_output_channels: + +AeroDyn List of Output Channels +------------------------------- + +This is a list of all possible output parameters for the AeroDyn module. The names are grouped by meaning, but can be ordered in the OUTPUTS section of the AeroDyn input file as you see fit. ``BαNβ``, refers to output node β of blade α, where α is a number in the range [1,3] and β is a number in the range [1,9], corresponding to entry β in the ``BlOutNd`` list. ``TwNβ`` refers to output node β of the tower and is in the range [1,9], corresponding to entry β in the ``TwOutNd`` list. + +The local tower coordinate system is shown in :numref:`ad_tower_geom` and the local blade coordinate system is shown in :numref:`ad_blade_local_cs` below. Figure :numref:`ad_blade_local_cs` also shows the direction of the local angles and force components. + +.. _ad_blade_local_cs: + +.. figure:: figs/ad_blade_local_cs.png + :width: 80% + :align: center + + AeroDyn Local Blade Coordinate System (Looking Toward the Tip, + from the Root) – l: Lift, d: Drag, m: Pitching, x: Normal (to Plane), + y: Tangential (to Plane), n: Normal (to Chord), + and t: Tangential (to Chord) + +.. _ad-output-channel: + +.. figure:: figs/ad_output_channel.pdf + :width: 500px + :align: center + + AeroDyn Output Channel List diff --git a/OpenFAST/docs/source/user/aerodyn/examples/NodalOutputs.txt b/OpenFAST/docs/source/user/aerodyn/examples/NodalOutputs.txt new file mode 100644 index 000000000..2e1f3ec9b --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/NodalOutputs.txt @@ -0,0 +1,58 @@ +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +---------------------- NODE OUTPUTS -------------------------------------------- + 3 BldNd_BladesOut - Blades to output + 99 BldNd_BlOutNd - Blade nodes on each blade (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx, AeroDyn_Nodes tab for a listing of available output channels, (-) +"VUndx" - x-component of undisturbed wind velocity at each node +"VUndy" - y-component of undisturbed wind velocity at each node +"VUndz" - z-component of undisturbed wind velocity at each node +"VDisx" - x-component of disturbed wind velocity at each node +"VDisy" - y-component of disturbed wind velocity at each node +"VDisz" - z-component of disturbed wind velocity at each node +"STVx" - x-component of structural translational velocity at each node +"STVy" - y-component of structural translational velocity at each node +"STVz" - z-component of structural translational velocity at each node +"VRel" - Relvative wind speed at each node +"DynP" - Dynamic pressure at each node +"Re" - Reynolds number (in millions) at each node +"M" - Mach number at each node +"Vindx" - Axial induced wind velocity at each node +"Vindy" - Tangential induced wind velocity at each node +"AxInd" - Axial induction factor at each node +"TnInd" - Tangential induction factor at each node +"Alpha" - Angle of attack at each node +"Theta" - Pitch+Twist angle at each node +"Phi" - Inflow angle at each node +"Curve" - Curvature angle at each node +"Cl" - Lift force coefficient at each node +"Cd" - Drag force coefficient at each node +"Cm" - Pitching moment coefficient at each node +"Cx" - Normal force (to plane) coefficient at each node +"Cy" - Tangential force (to plane) coefficient at each node +"Cn" - Normal force (to chord) coefficient at each node +"Ct" - Tangential force (to chord) coefficient at each node +"Fl" - Lift force per unit length at each node +"Fd" - Drag force per unit length at each node +"Mm" - Pitching moment per unit length at each node +"Fx" - Normal force (to plane) per unit length at each node +"Fy" - Tangential force (to plane) per unit length at each node +"Fn" - Normal force (to chord) per unit length at each node +"Ft" - Tangential force (to chord) per unit length at each node +"Clrnc" - Tower clearance at each node (based on the absolute distance to the nearest point in the tower from blade node B#N# minus the local tower radius, in the deflected configuration); please note that this clearance is only approximate because the calculation assumes that the blade is a line with no volume (however, the calculation does use the local tower radius); when blade node B#N# is above the tower top (or below the tower base), the absolute distance to the tower top (or base) minus the local tower radius, in the deflected configuration, is output +"Vx" - Local axial velocity +"Vy" - Local tangential velocity +"GeomPhi" - Geometric phi? If phi was solved using normal BEMT equations, GeomPhi = 1; otherwise, if it was solved geometrically, GeomPhi = 0. +"Chi" - Skew angle (used in skewed wake correction) -- not available for OLAF +"UA_Flag" - Flag indicating if UA is turned on for this node. -- not available for OLAF +"CpMin" - Pressure coefficient +"SgCav" - Cavitation number +"SigCr" - Critical cavitation number +"Gam" - Gamma -- circulation on blade +"Cl_Static" - Static portion of lift force coefficient at each node, without unsteady effects -- not available for BEMT/DBEMT +"Cd_Static" - Static portion of drag force coefficient at each node, without unsteady effects -- not available for BEMT/DBEMT +"Cm_Static" - Static portion of pitching moment coefficient at each node, without unsteady effects -- not available for BEMT/DBEMT +"Uin" - Axial induced velocity in rotating hub coordinates. Axial aligned with hub axis. rotor plane polar hub rotating coordinates +"Uit" - Tangential induced velocity in rotating hub coordinates. Tangential to the rotation plane. Perpendicular to blade aziumth. rotor plane polar hub rotating coordinates +"Uir" - Radial induced velocity in rotating hub coordinates. Radial outwards in rotation plane. Aligned with blade azimuth. rotor plane polar hub rotating coordinates +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/docs/source/user/aerodyn/examples/ad_airfoil_example.inp b/OpenFAST/docs/source/user/aerodyn/examples/ad_airfoil_example.inp new file mode 100644 index 000000000..5959ae5f4 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/ad_airfoil_example.inp @@ -0,0 +1,191 @@ +! "S809 Airfoil, OSU data at Re=.75 Million, Clean roughness" +! "NREL/TP-442-7817 Appendix B, Viterna used aspect ratio=11" +! note that this file uses Marshall Buhl's new input file processing; start all comment lines with ! +! ------------------------------------------------------------------------------ +"DEFAULT" InterpOrd ! Interpolation order to use for quasi-steady table lookup {1=linear; 3=cubic spline; "default"} [default=1] +! ------------------------------------------------------------------------------ + 1 NonDimArea ! The non-dimensional area of the airfoil (area/chord^2) (set to 1.0 if unsure or unneeded) + 67 NumCoords ! The number of coordinates in the airfoil shape file (including an extra coordinate for airfoil reference). +! ......... x-y coordinates are next if NumCoords > 0 ............. +! x-y coordinate of airfoil reference +! x/c y/c +0.25 0 +! NREL's S809 Airfoil +! x/c y/c +1.000000 0.000000 +0.996203 0.000487 +0.985190 0.002373 +0.967844 0.005960 +0.945073 0.011024 +0.917488 0.017033 +0.885293 0.023458 +0.848455 0.030280 +0.807470 0.037766 +0.763042 0.045974 +0.715952 0.054872 +0.667064 0.064353 +0.617331 0.074214 +0.567830 0.084095 +0.519832 0.093268 +0.474243 0.099392 +0.428461 0.101760 +0.382612 0.101840 +0.337260 0.100070 +0.292970 0.096703 +0.250247 0.091908 +0.209576 0.085851 +0.171409 0.078687 +0.136174 0.070580 +0.104263 0.061697 +0.076035 0.052224 +0.051823 0.042352 +0.031910 0.032299 +0.016590 0.022290 +0.006026 0.012615 +0.000658 0.003723 +0.000204 0.001942 +0.000000 -0.000020 +0.000213 -0.001794 +0.001045 -0.003477 +0.001208 -0.003724 +0.002398 -0.005266 +0.009313 -0.011499 +0.023230 -0.020399 +0.042320 -0.030269 +0.065877 -0.040821 +0.093426 -0.051923 +0.124111 -0.063082 +0.157653 -0.073730 +0.193738 -0.083567 +0.231914 -0.092442 +0.271438 -0.099905 +0.311968 -0.105281 +0.353370 -0.108181 +0.395329 -0.108011 +0.438273 -0.104552 +0.481920 -0.097347 +0.527928 -0.086571 +0.576211 -0.073979 +0.626092 -0.060644 +0.676744 -0.047441 +0.727211 -0.035100 +0.776432 -0.024204 +0.823285 -0.015163 +0.866630 -0.008204 +0.905365 -0.003363 +0.938474 -0.000487 +0.965086 0.000743 +0.984478 0.000775 +0.996141 0.000290 +1.000000 0.000000 +! ------------------------------------------------------------------------------ +"unused" BL_file ! The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called. + 1 NumTabs ! Number of airfoil tables in this file. +! ------------------------------------------------------------------------------ +! data for table 1 +! ------------------------------------------------------------------------------ + 0.75 Re ! Reynolds number in millions + 0 UserProp ! User property (control) setting +true InclUAdata ! Is unsteady aerodynamics data included in this table? If TRUE, then include 30 UA coefficients below this line +!........................................ + -0.38 alpha0 ! 0-lift angle of attack, depends on airfoil. + 15.3 alpha1 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg) + -15.3 alpha2 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA<alpha0. (deg) + 1 eta_e ! Recovery factor in the range [0.85 - 0.95] used only for UAMOD=1, it is set to 1 in the code when flookup=True. (-) + 7.12499 C_nalpha ! Slope of the 2D normal force coefficient curve. (1/rad) + 2 T_f0 ! Initial value of the time constant associated with Df in the expression of Df and f''. [default = 3] + 7 T_V0 ! Initial value of the time constant associated with the vortex lift decay process; it is used in the expression of Cvn. It depends on… + 1.6 T_p ! Boundary-layer,leading edge pressure gradient time constant in the expression of Dp. It should be tuned based on airfoil experimental… + 9 T_VL ! Initial value of the time constant associated with the vortex advection process; it represents the non-dimensional time in semi-… +"Default" b1 ! Constant in the expression of phi_alpha^c and phi_q^c. This value is relatively insensitive for thin airfoils, but may be different… +"Default" b2 ! Constant in the expression of phi_alpha^c and phi_q^c. This value is relatively insensitive for thin airfoils, but may be different… + 0.5 b5 ! Constant in the expression of K'''_q,Cm_q^nc, and k_m,q. [from experimental results, defaults to 5] +"Default" A1 ! Constant in the expression of phi_alpha^c and phi_q^c. This value is relatively insensitive for thin airfoils, but may be different… +"Default" A2 ! Constant in the expression of phi_alpha^c and phi_q^c. This value is relatively insensitive for thin airfoils, but may be different… +"Default" A5 ! Constant in the expression of K'''_q,Cm_q^nc, and k_m,q. [from experimental results, defaults to 1] + 18.269 S1 ! Constant in the f curve best-fit for alpha0<=AOA<=alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1] + -11.324 S2 ! Constant in the f curve best-fit for AOA> alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1] + 18.269 S3 ! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [ignored if UAMod<>1] + -11.324 S4 ! Constant in the f curve best-fit for AOA< alpha2; by definition it depends on the airfoil. [ignored if UAMod<>1] + 1.9408 Cn1 ! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. It… + -0.8 Cn2 ! As Cn1 for negative AOAs. +"Default" St_sh ! Strouhal's shedding frequency constant. [default = 0.19] + 0.0016 Cd0 ! 2D drag coefficient value at 0-lift. + -0.0328 Cm0 ! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. [If the aerodynamics coefficients table does… + 0 k0 ! Constant in the \hat(x)_cp curve best-fit; = (\hat(x)_AC-0.25). [ignored if UAMod<>1] + 0 k1 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] + 0 k2 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] + 0 k3 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] + 0 k1_hat ! Constant in the expression of Cc due to leading edge vortex effects. [ignored if UAMod<>1] +"Default" x_cp_bar ! Constant in the expression of \hat(x)_cp^v. [ignored if UAMod<>1, default = 0.2] +"DEFAULT" UACutout ! Angle of attack above which unsteady aerodynamics are disabled (deg). [Specifying the string "Default" sets UACutout to 45 degrees] +"DEFAULT" filtCutOff ! Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5] +!........................................ +! Table of aerodynamics coefficients + 63 NumAlf ! Number of data lines in the following table +! Alpha Cl Cd Cm +! (deg) (-) (-) (-) +-180 0 0.1748 0 +-170 0.23 0.2116 0.4 +-160 0.46 0.3172 0.1018 +-150 0.494 0.4784 0.1333 +-140 0.51 0.6743 0.1727 +-130 0.486 0.8799 0.2132 +-120 0.415 1.0684 0.2498 +-110 0.302 1.2148 0.2779 +-100 0.159 1.2989 0.2933 +-90 0 1.308 0.2936 +-80 -0.159 1.2989 0.2933 +-70 -0.302 1.2148 0.2779 +-60 -0.415 1.0684 0.2498 +-50 -0.486 0.8799 0.2132 +-40 -0.51 0.6743 0.1727 +-30 -0.494 0.4784 0.1333 +-21.1 -0.56 0.3027 0.0612 +-19.1 -0.67 0.3069 0.0904 +-17.1 -0.79 0.1928 0.0293 +-15.2 -0.84 0.0898 -0.009 +-13.2 -0.7 0.0553 -0.0045 +-11.1 -0.63 0.039 -0.0044 +-9.2 -0.56 0.0233 -0.0051 +-7.1 -0.64 0.0131 0.0018 +-5.1 -0.42 0.0134 -0.0216 +-3.1 -0.21 0.0119 -0.0282 +-0.9 0.05 0.0122 -0.0346 +1 0.3 0.0116 -0.0405 +3.1 0.54 0.0144 -0.0455 +5.2 0.777 0.0146 -0.0507 +6.15 0.854 0.0154 -0.04555 +7.1 0.906 0.0162 -0.0404 +8.15 0.888 0.0266 -0.03625 +9.2 0.91 0.037 -0.0321 +10.3 0.927 0.045 -0.0281 +11.18 0.948 0.052 -0.0284 +12.2 0.957 0.067 -0.0322 +13.2 0.987 0.074 -0.0361 +14.3 1.009 0.089 -0.0363 +15.3 0.948 0.112 -0.0393 +16.1 0.918 0.123 -0.0398 +17.1 0.815 0.175 -0.0983 +18.1 0.7 0.257 -0.1242 +19.1 0.627 0.305 -0.1155 +25 0.528 0.454 -0.186083486 +30 0.631 0.4784 -0.2459 +35 0.592 0.524 -0.2636 +40 0.554 0.554 -0.2813 +45 0.506 0.61 -0.29735 +50 0.442 0.807 -0.3134 +60 0.296 0.987 -0.3388 +70 0.193 1.172 -0.3557 +80 0.082 1.236 -0.363 +90 0 1.249 -0.3604 +100 -0.159 1.2989 -0.36 +110 -0.302 1.2148 -0.3446 +120 -0.415 1.0684 -0.3166 +130 -0.486 0.8799 -0.28 +140 -0.51 0.6743 -0.2394 +150 -0.494 0.4784 -0.2001 +160 -0.46 0.3172 -0.1685 +170 -0.23 0.2116 -0.5 +180 0 0.1748 0 + diff --git a/OpenFAST/docs/source/user/aerodyn/examples/ad_blade_example.inp b/OpenFAST/docs/source/user/aerodyn/examples/ad_blade_example.inp new file mode 100644 index 000000000..69b1ca77c --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/ad_blade_example.inp @@ -0,0 +1,30 @@ +------- AERODYN v15.04.* BLADE DEFINITION INPUT FILE ------------------------------------- +Description line for this file -- file corresponds to inputs in Test01_UAE_AeroDyn.dat +====== Blade Properties ================================================================= + 23 NumBlNds - Number of blade nodes used in the analysis (-) + BlSpn BlCrvAC BlSwpAC BlCrvAng BlTwist BlChord BlAFID + (m) (m) (m) (deg) (deg) (m) (-) + 0.0 0.0 0.0 0.0 0.000 0.219 1 + 0.1360 0.0 0.0 0.0 0.000 0.219 1 + 0.4481 0.0 0.0 0.0 -0.098 0.181 1 + 0.8001 0.0 0.0 0.0 19.423 0.714 3 + 1.0767 0.0 0.0 0.0 14.318 0.711 4 + 1.2779 0.0 0.0 0.0 10.971 0.691 5 + 1.4958 0.0 0.0 0.0 8.244 0.668 6 + 1.7137 0.0 0.0 0.0 6.164 0.647 7 + 1.9149 0.0 0.0 0.0 4.689 0.627 7 + 2.1160 0.0 0.0 0.0 3.499 0.606 8 + 2.3340 0.0 0.0 0.0 2.478 0.584 8 + 2.5520 0.0 0.0 0.0 1.686 0.561 8 + 2.7530 0.0 0.0 0.0 1.115 0.542 8 + 2.9542 0.0 0.0 0.0 0.666 0.522 8 + 3.1721 0.0 0.0 0.0 0.267 0.499 8 + 3.3900 0.0 0.0 0.0 -0.079 0.478 8 + 3.5912 0.0 0.0 0.0 -0.381 0.457 9 + 3.7924 0.0 0.0 0.0 -0.679 0.437 9 + 3.9684 0.0 0.0 0.0 -0.933 0.419 9 + 4.1444 0.0 0.0 0.0 -1.184 0.401 10 + 4.3456 0.0 0.0 0.0 -1.466 0.381 10 + 4.5216 0.0 0.0 0.0 -1.711 0.363 10 + 4.5970 0.0 0.0 0.0 -1.711 0.363 10 + diff --git a/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_example.inp b/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_example.inp new file mode 100644 index 000000000..cb10dc9c3 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_example.inp @@ -0,0 +1,23 @@ +----- AeroDyn Driver v1.00.x Input File -------------------------------------- +UAE Phase 3 turbine (BEM) +----- Input Configuration ---------------------------------------------------- +True Echo - Echo input parameters to "<rootname>.ech"? +"ad_primary_example.inp" AD_InputFile - Name of the primary AeroDyn input file +----- Turbine Data ----------------------------------------------------------- + 2 NumBlades - Number of blades (-) + 0.432 HubRad - Hub radius (m) + 12.192 HubHt - Hub height (m) + 0 Overhang - Overhang (m) + 0 ShftTilt - Shaft tilt (deg) + 0 Precone - Blade precone (deg) +----- I/O Settings ----------------------------------------------------------- +"Test01" OutFileRoot - Root name for any output files (use "" for .dvr rootname) (-) +True TabDel - When generating formatted output (OutForm=True), make output tab-delimited (fixed-width otherwise) (flag) +"ES10.3E2" OutFmt - Format used for text tabular output, excluding the time channel. Resulting field should be 10 characters. (quoted string) +True Beep - Beep on exit (flag) +----- Combined-Case Analysis ------------------------------------------------- + 2 NumCases - Number of cases to run +WndSpeed ShearExp RotSpd Pitch Yaw dT Tmax +(m/s) (-) (rpm) (deg) (deg) (s) (s) +5.0000000E+00 0.0000000E+00 7.1900000E+01 3.0000000E+00 0.0000000E+00 3.9700000E-02 8.3450000E-01 +@ADTimeSeriesInput.dat diff --git a/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_timeseries_example.inp b/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_timeseries_example.inp new file mode 100644 index 000000000..6c091d0d2 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/ad_driver_timeseries_example.inp @@ -0,0 +1,15 @@ +Time WndSpeed ShearExp RotSpd Pitch Yaw +(s) (m/s) (-) (rpm) (deg) (deg) +0.0 4.00000000 0.00000000 2.0 0.00000000 100.00000000 +0.05 4.00000000 0.00000000 2.0 0.00000000 90.00000000 +0.10 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.15 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.20 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.25 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.30 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.35 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.40 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.45 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.50 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.55 4.00000000 0.00000000 2.0 0.00000000 80.00000000 +0.60 4.00000000 0.00000000 2.0 0.00000000 80.00000000 \ No newline at end of file diff --git a/OpenFAST/docs/source/user/aerodyn/examples/ad_primary_example.inp b/OpenFAST/docs/source/user/aerodyn/examples/ad_primary_example.inp new file mode 100644 index 000000000..62a691d7f --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/examples/ad_primary_example.inp @@ -0,0 +1,104 @@ +------- AERODYN v15 for OpenFAST INPUT FILE ----------------------------------------------- +Description line that will be printed in the output file and written to the screen. +====== General Options ============================================================================ +True Echo - Echo the input to "<rootname>.AD.ech"? (flag) +"default" DTAero - Time interval for aerodynamic calculations {or "default"} (s) + 1 WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT, 2=DBEMT, 3=OLAF} [WakeMod cannot be 2 or 3 when linearizing] + 1 AFAeroMod - Type of blade airfoil aerodynamics model (switch) {1=steady model, 2=Beddoes-Leishman unsteady model} [AFAeroMod must be 1 when linearizing] + 0 TwrPotent - Type tower influence on wind based on potential flow around the tower (switch) {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} + 0 TwrShadow - Calculate tower influence on wind based on downstream tower shadow (switch) {0=none, 1=Powles model, 2=Eames model} +False TwrAero - Calculate tower aerodynamic loads? (flag) +False FrozenWake - Assume frozen wake during linearization? (flag) [used only when WakeMod=1 and when linearizing] +False CavitCheck - Perform cavitation check? (flag) [AFAeroMod must be 1 when CavitCheck=true] +False CompAA - Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2] +"unused" AA_InputFile - Aeroacoustics input file +====== Environmental Conditions =================================================================== + 1.246 AirDens - Air density (kg/m^3) + 1.4639E-05 KinVisc - Kinematic air viscosity (m^2/s) + 333.3 SpdSound - Speed of sound (m/s) + 101325 Patm - Atmospheric pressure (Pa) [used only when CavitCheck=True] + 2000 Pvap - Vapour pressure of fluid (Pa) [used only when CavitCheck=True] + 0.6 FluidDepth - Water depth above mid-hub height (m) [used only when CavitCheck=True] +====== Blade-Element/Momentum Theory Options ====================================================== [unused when WakeMod=0 or 3] + 1 SkewMod - Type of skewed-wake correction model (switch) {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0 or 3] +"default" SkewModFactor - Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0 or 3] +f TipLoss - Use the Prandtl tip-loss model? (flag) [unused when WakeMod=0 or 3] +f HubLoss - Use the Prandtl hub-loss model? (flag) [unused when WakeMod=0 or 3] +True TanInd - Include tangential induction in BEMT calculations? (flag) [unused when WakeMod=0 or 3] +True AIDrag - Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod=0 or 3] +True TIDrag - Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod=0,3 or TanInd=FALSE] + 1E-05 IndToler - Convergence tolerance for BEMT nonlinear solve residual equation {or "default"} (-) [unused when WakeMod=0 or 3] + 100 MaxIter - Maximum number of iteration steps (-) [unused when WakeMod=0] +====== Dynamic Blade-Element/Momentum Theory Options ============================================== [used only when WakeMod=2] + 2 DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2] + 4 tau1_const - Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1] +====== OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3] +"unused" OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] +====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2] + 1 UAMod - Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2] +FALSE FLookup - Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2] +====== Airfoil Information ========================================================================= + 1 AFTabMod - Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-) + 1 InCol_Alfa - The column in the airfoil tables that contains the angle of attack (-) + 2 InCol_Cl - The column in the airfoil tables that contains the lift coefficient (-) + 3 InCol_Cd - The column in the airfoil tables that contains the drag coefficient (-) + 4 InCol_Cm - The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-) + 0 InCol_Cpmin - The column in the airfoil tables that contains the Cpmin coefficient; use zero if there is no Cpmin column (-) + 10 NumAFfiles - Number of airfoil files used (-) +"Airfoils/UAE_VI/cylinder.dat" AFNames - Airfoil file names (NumAFfiles lines) (quoted strings) +"Airfoils/UAE_VI/Mod_S809_129.dat" +"Airfoils/UAE_VI/Mod_S809_185.dat" +"Airfoils/UAE_VI/Mod_S809_242.dat" +"Airfoils/UAE_VI/Mod_S809_298.dat" +"Airfoils/UAE_VI/Mod_S809_354.dat" +"Airfoils/UAE_VI/Mod_S809_410.dat" +"Airfoils/UAE_VI/Mod_S809_600.dat" +"Airfoils/UAE_VI/Mod_S809_800.dat" +"Airfoils/UAE_VI/Mod_S809_Outboard.dat" +====== Rotor/Blade Properties ===================================================================== +True UseBlCm - Include aerodynamic pitching moment in calculations? (flag) +"Test01_UAE_AeroDyn_blade.dat" ADBlFile(1) - Name of file containing distributed aerodynamic properties for Blade #1 (-) +"Test01_UAE_AeroDyn_blade.dat" ADBlFile(2) - Name of file containing distributed aerodynamic properties for Blade #2 (-) [unused if NumBl < 2] +"Test01_UAE_AeroDyn_blade.dat" ADBlFile(3) - Name of file containing distributed aerodynamic properties for Blade #3 (-) [unused if NumBl < 3] +====== Tower Influence and Aerodynamics ============================================================= [used only when TwrPotent/=0, TwrShadow/=0, or TwrAero=True] + 5 NumTwrNds - Number of tower nodes used in the analysis (-) [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] +TwrElev TwrDiam TwrCd TwrTI (used only with TwrShadow=2) +(m) (m) (-) (-) +0.0000000E+00 6.0000000E+00 0.0000000E+00 1.0000000E-01 +2.0000000E+01 5.5000000E+00 0.0000000E+00 1.0000000E-01 +4.0000000E+01 5.0000000E+00 0.0000000E+00 1.0000000E-01 +6.0000000E+01 4.5000000E+00 0.0000000E+00 1.0000000E-01 +8.0000000E+01 4.0000000E+00 0.0000000E+00 1.0000000E-01 +====== Outputs ==================================================================================== +True SumPrint - Generate a summary file listing input options and interpolated properties to "<rootname>.AD.sum"? (flag) + 4 NBlOuts - Number of blade node outputs [0 - 9] (-) + 1, 3, 4, 6 BlOutNd - Blade nodes whose values will be output (-) + 0 NTwOuts - Number of tower node outputs [0 - 9] (-) + 1 TwOutNd - Tower nodes whose values will be output (-) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"B1N1VDisx, B1N1VDisy, B1N1VDisz" ! disturbed wind velocity at Blade 1, Node 1 +"B1N2VDisx, B1N2VDisy, B1N2VDisz" ! disturbed wind velocity at Blade 1, Node 2 +"B1N3VDisx, B1N3VDisy, B1N3VDisz" ! disturbed wind velocity at Blade 1, Node 3 +"B1N1STVx, B1N1STVy, B1N1STVz" ! structural translational velocity at Blade 1, Node 1 +"B1N2STVx, B1N2STVy, B1N2STVz" ! structural translational velocity at Blade 1, Node 2 +"B1N3STVx, B1N3STVy, B1N3STVz" ! structural translational velocity at Blade 1, Node 2 +"RtSpeed, RtSkew, B1Azimuth" +"B1N1AxInd, B1N2AxInd, B1N3AxInd" +"B1N1Alpha, B1N2Alpha, B1N3Alpha" +"B1N1Theta, B1N2Theta, B1N3Theta" +END of OutList section (the word "END" must appear in the first 3 columns of the last OutList line) +====== Outputs for all blade stations (same ending as above for B1N1.... =========================== [optional section] + 1 BldNd_BladesOut - Number of blades to output all node information at. Up to number of blades on turbine. (-) + "All" BldNd_BlOutNd - Future feature will allow selecting a portion of the nodes to output. Not implemented yet. (-) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"Fx, Fy" +"Vx, Vy" +Vrel +TnInd +AxInd +Theta +Phi +Vindx +Vindy +Alpha +END (the word "END" must appear in the first 3 columns of this last OutList line in the optional nodal output section) diff --git a/OpenFAST/docs/source/user/aerodyn/figs/ad_blade_geom.png b/OpenFAST/docs/source/user/aerodyn/figs/ad_blade_geom.png new file mode 100644 index 0000000000000000000000000000000000000000..5b881833d6ecd0134517cddd8e14a87e0353b4e7 GIT binary patch literal 109001 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn/figs/ad_blade_local_cs.png b/OpenFAST/docs/source/user/aerodyn/figs/ad_blade_local_cs.png new file mode 100644 index 0000000000000000000000000000000000000000..1d7451360052dfa7a3cb6cddd3f61fd35f5a432a GIT binary patch literal 70601 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 S3W0(CNIz8&|0JsK^Zx+LgaY^g literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn/figs/ad_driver_geom.png b/OpenFAST/docs/source/user/aerodyn/figs/ad_driver_geom.png new file mode 100644 index 0000000000000000000000000000000000000000..10bc8125ca450b56753683d4972560358e2f1298 GIT binary patch literal 98962 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn/figs/ad_output_channel.pdf b/OpenFAST/docs/source/user/aerodyn/figs/ad_output_channel.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ac44d8cbb72598f0060e3b52b49ecf143fdde80b GIT binary patch literal 70628 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 Dv6fS4 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn/figs/ad_tower_geom.png b/OpenFAST/docs/source/user/aerodyn/figs/ad_tower_geom.png new file mode 100644 index 0000000000000000000000000000000000000000..2f3a1e15d08f8617745eb0efc7b9fc74fbc1c2d7 GIT binary patch literal 64349 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 G!u}r`tyKH~ literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/aerodyn/index.rst b/OpenFAST/docs/source/user/aerodyn/index.rst new file mode 100644 index 000000000..48ce1edfb --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/index.rst @@ -0,0 +1,24 @@ +AeroDyn Users Guide and Theory Manual +====================================== + +.. only:: html + + This document offers a quick reference guide for the AeroDyn software + program. It is intended to be used by the general user in combination + with other OpenFAST manuals. The manual will be updated as new releases are + issued and as needed to provide further information on advancements or + modifications to the software. + + The documentation here was derived from AeroDyn Manual for AeroDyn version 15.04 by J.\ Jonkman et al. + + +.. toctree:: + :maxdepth: 2 + + introduction.rst + input.rst + output.rst + modeling.rst + theory.rst + appendix.rst + diff --git a/OpenFAST/docs/source/user/aerodyn/input.rst b/OpenFAST/docs/source/user/aerodyn/input.rst new file mode 100644 index 000000000..2103b2076 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/input.rst @@ -0,0 +1,775 @@ +.. _ad_input: + +Input Files +=========== + +The user configures the aerodynamic model parameters via a primary +AeroDyn input file, as well as separate input files for airfoil and +blade data. When used in standalone mode, an additional driver input +file is required. This driver file specifies initialization inputs +normally provided to AeroDyn by OpenFAST, as well as the per-time-step +inputs to AeroDyn. + +As an example, the ``driver.dvr`` file is the main driver, the ``input.dat`` is +the primary input file, the ``blade.dat`` file contains the blade geometry data, +and the ``airfoil.dat`` file contains the airfoil angle of attack, lift, drag, +moment coefficients, and pressure coefficients. Example input files are +included in :numref:`ad_appendix`. + +No lines should be added or removed from the input files, except in +tables where the number of rows is specified and comment lines in the +AeroDyn airfoil data files. + +Units +----- + +AeroDyn uses the SI system (kg, m, s, N). Angles are assumed to be in +radians unless otherwise specified. + +AeroDyn Driver Input File +------------------------- + +The driver input file is only needed for the standalone version of +AeroDyn and contains inputs normally generated by OpenFAST, and necessary to +control the aerodynamic simulation for uncoupled models. A sample +AeroDyn driver input file is given in +:numref:`ad_appendix`. + +Set the ``Echo`` flag in this file to TRUE if you wish to have the +``AeroDyn_Driver`` executable echo the contents of the driver input file (useful +for debugging errors in the driver file). The echo file has the naming +convention of *OutFileRoot.ech*, where ``OutFileRoot`` is +specified in the I/O SETTINGS section of the driver input file below. +``AD_InputFile`` is the filename of the primary AeroDyn input file. +This name should be in quotations and can contain an absolute path or a +relative path. + +The TURBINE DATA section defines the AeroDyn-required turbine geometry +for a rigid turbine, see Figure 1. ``NumBlades`` specifies the number +of blades; only one-, two-, or three-bladed rotors are permitted. +``HubRad`` specifies the radius to the blade root from the +center-of-rotation along the (possibly preconed) blade-pitch axis; +``HubRad`` must be greater than zero. ``HubHt`` specifies the +elevation of the hub center above the ground (or above the mean sea +level (MSL) for offshore wind turbines or above the seabed for MHK +turbines). ``Overhang`` specifies the distance along the (possibly +tilted) rotor shaft between the tower centerline and hub center; +``Overhang`` is positive downwind, so use a negative number for upwind +rotors. ``ShftTilt`` is the angle (in degrees) between the rotor shaft +and the horizontal plane. Positive ``ShftTilt`` means that the +downwind end of the shaft is the highest; upwind turbines have negative +``ShftTilt`` for improved tower clearance. ``Precone`` is the angle +(in degrees) between a flat rotor disk and the cone swept by the blades, +positive downwind; upwind turbines have negative ``Precone`` for +improved tower clearance. + +The I/O SETTINGS section controls the creation of the results file. If +``OutFileRoot`` is specified, the results file will have the filename +*OutFileRoot.out*. If an empty string is provided for +``OutFileRoot``, then the driver file’s root name will be used +instead. If ``TabDel`` is ``TRUE``, a TAB character is used between +columns in the output file; if FALSE, fixed-width is used otherwise. +``OutFmt`` is any valid Fortran numeric format string, which is used +for text output, excluding the time channel. The resulting field should +be 10 characters, but AeroDyn does not check ``OutFmt`` for validity. +If you want a sound generated on program exit, set ``Beep`` to true. + +.. figure:: figs/ad_driver_geom.png + :width: 60% + :align: center + + AeroDyn Driver Turbine Geometry + +The COMBINED-CASE ANALYSIS section allows you to execute ``NumCases`` +number of simulations for the given TURBINE DATA with a single driver +input file. There will be one row in the subsequent table for each of +the ``NumCases`` specified (plus two table header lines). The +information within each row of the table fully specifies each +simulation. Each row contains the following columns: ``WndSpeed``, +``ShearExp``, ``RotSpd``, ``Pitch``, ``Yaw``, ``dT``, and +``Tmax``. The local undisturbed wind speed for any given blade or +tower node is determined using, + +.. math:: + :label: windspeed + + U(Z) = \mathrm{WndSpeed} \times \left( \frac{Z}{\mathrm{HubHt}} \right)^\mathrm{ShearExp} + +where :math:`\mathrm{WndSpeed}` is the steady wind speed (fluid flow speed in the +case of an MHK turbine) located at elevation :math:`\mathrm{HubHt}`, :math:`Z` is the +instantaneous elevation of the blade or tower node above the ground (or +above the MSL for offshore wind turbines or above the seabed for MHK +turbines), and :math:`\mathrm{ShearExp}` is the power-law shear exponent. The fixed +rotor speed (in rpm) is given by ``RotSpd`` (positive clockwise +looking downwind), the fixed blade-pitch angle (in degrees) is given by +``Pitch`` (positive to feather, leading edge upwind), and the fixed +nacelle-yaw angle (in degrees) is given by ``Yaw`` (positive rotation +of the nacelle about the vertical tower axis, counterclockwise when +looking downward). While the flow speed and direction in the AeroDyn +driver is uniform and fixed (depending only on elevation above ground), +``Yaw`` and ``ShftTilt`` (from the TURBINE DATA section above) can +introduce skewed flow. ``dT`` is the simulation time step, which must +match the time step for the aerodynamic calculations (``DTAero``) as +specified in the primary AeroDyn input file, and ``Tmax`` is the total +simulation time. + +Note that ``dT`` should be the same for each of the cases listed in the +COMBINED-CASE ANALYSIS section. All of the cases will be output to the same +file, with a ``Case`` column listed next to the ``Time`` output column +for help with data processing. + +For further debugging capability, the AeroDyn driver now also has the +ability to read the combined case input data as a time-history file. +In place of a row in the COMBINED-CASE ANALYSIS table, a separate input file +can be listed instead. The name of the file should be preceded with the ``@`` +character, to indicate the data is a time-history file in a separate text +input file. An example is provided in +:numref:`ad_appendix` + +AeroDyn Primary Input File +-------------------------- + +The primary AeroDyn input file defines modeling options, environmental +conditions (except freestream flow), airfoils, tower nodal +discretization and properties, as well as output file specifications. + +The file is organized into several functional sections. Each section +corresponds to an aspect of the aerodynamics model. A sample AeroDyn +primary input file is given in +:numref:`ad_appendix`. + +The input file begins with two lines of header information which is for +your use, but is not used by the software. + +General Options +~~~~~~~~~~~~~~~ + +Set the ``Echo`` flag to TRUE if you wish to have AeroDyn echo the +contents of the AeroDyn primary, airfoil, and blade input files (useful +for debugging errors in the input files). The echo file has the naming +convention of *OutRootFile.AD.ech*. ``OutRootFile`` is either +specified in the I/O SETTINGS section of the driver input file when +running AeroDyn standalone, or by the OpenFAST program when running a +coupled simulation. + +``DTAero`` sets the time step for the aerodynamic calculations. For +accuracy and numerical stability, we recommend that ``DTAero`` be set +such that there are at least 200 azimuth steps per rotor revolution. +However, when AeroDyn is coupled to OpenFAST, OpenFAST may require time steps +much smaller than this rule of thumb. If UA is enabled while using very +small time steps, you may need to recompile AeroDyn in double precision +to avoid numerical problems in the UA routines. The keyword ``DEFAULT`` +for ``DTAero`` may be used to indicate that AeroDyn should employ the +time step prescribed by the driver code (OpenFAST or the standalone driver +program). + +Set ``WakeMod`` to 0 if you want to disable rotor wake/induction effects or 1 to +include these effects using the (quasi-steady) BEM theory model. When +``WakeMod`` is set to 2, a dynamic BEM theory model (DBEMT) is used (also +referred to as dynamic inflow or dynamic wake model). When ``WakeMod`` is set +to 3, the free vortex wake model is used, also referred to as OLAF (see +:numref:`OLAF`). ``WakeMod`` cannot be set to 2 or 3 during linearization +analyses. + +Set ``AFAeroMod`` to 1 to include steady blade airfoil aerodynamics or 2 +to enable UA; ``AFAeroMod`` must be 1 during linearization analyses +with AeroDyn coupled to OpenFAST. + +Set ``TwrPotent`` to 0 to disable the +potential-flow influence of the tower on the fluid flow local to the +blade, 1 to enable the standard potential-flow model, or 2 to include +the Bak correction in the potential-flow model. + +Set the ``TwrShadow`` to 0 to disable to the tower shadow model, +1 to enable the Powles tower shadow model, or 2 to use the Eames tower +shadow model. These models calculate the influence of the tower on the +flow local to the blade based on the downstream tower shadow model. If +the tower influence from potential flow and tower shadow are both +enabled, the two influences will be superimposed. + +Set the ``TwrAero`` flag to TRUE to calculate fluid drag loads on the +tower or FALSE to disable these effects. + +During linearization analyses +with AeroDyn coupled OpenFAST and BEM enabled (``WakeMod = 1``), set the +``FrozenWake`` flag to TRUE to employ frozen-wake assumptions during +linearization (i.e. to fix the axial and tangential induces velocities, +and, at their operating-point values during linearization) or FALSE to +recalculate the induction during linearization using BEM theory. + +Set the ``CavitCheck`` flag to TRUE to perform a cavitation check for MHK +turbines or FALSE to disable this calculation. If ``CavitCheck`` is +TRUE, ``AFAeroMod`` must be set to 1 because the cavitation check does +not function with unsteady airfoil aerodynamics. + +Set the ``CompAA`` flag to TRUE to run aero-acoustic calculations. This +option is only available for ``WakeMod = 1`` or ``2``. See section +:numref:`AeroAcoustics` for information on how to use this feature. + +The ``AA_InputFile`` is used to specify the input file for the aeroacoustics +sub-module. See :numref:`AeroAcoustics` for information on how to use this +feature. + + +Environmental Conditions +~~~~~~~~~~~~~~~~~~~~~~~~ + +``AirDens`` specifies the fluid density and must be a value greater +than zero; a typical value is around 1.225 kg/m\ :sup:`3` for air (wind +turbines) and 1025 kg/m\ :sup:`3` for seawater (MHK turbines). +``KinVisc`` specifies the kinematic viscosity of the air (used in the +Reynolds number calculation); a typical value is around 1.460E-5 +m\ :sup:`2`/s for air (wind turbines) and 1.004E-6 m\ :sup:`2`/s for +seawater (MHK turbines). ``SpdSound`` is the speed of sound in air +(used to calculate the Mach number within the unsteady airfoil +aerodynamics calculations); a typical value is around 340.3 m/s. The +last three parameters in this section are only used when +``CavitCheck = TRUE`` for MHK turbines. ``Patm`` is the atmospheric +pressure above the free surface; typically around 101,325 Pa. ``Pvap`` +is the vapor pressure of the fluid; for seawater this is typically +around 2,000 Pa. ``FluidDepth`` is the distance from the hub center to +the free surface. + +Blade-Element/Momentum Theory Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The input parameters in this section are not used when ``WakeMod = 0``. + +``SkewMod`` determines the skewed-wake correction model. Set +``SkewMod`` to 1 to use the uncoupled BEM solution technique without +an additional skewed-wake correction. Set ``SkewMod`` to 2 to include +the Pitt/Peters correction model. **The coupled model ``SkewMod= +3`` is not available in this version of AeroDyn.** + +``SkewModFactor`` is used only when ``SkewMod = 1``. Enter a scaling factor to use +in the Pitt/Peters correction model, or enter ``"default"`` to use the default +value of :math:`\frac{15 \pi}{32}`. + +Set ``TipLoss`` to TRUE to include the Prandtl tip-loss model or FALSE +to disable it. Likewise, set ``HubLoss`` to TRUE to include the +Prandtl hub-loss model or FALSE to disable it. + +Set ``TanInd`` to TRUE to include tangential induction (from the +angular momentum balance) in the BEM solution or FALSE to neglect it. +Set ``AIDrag`` to TRUE to include drag in the axial-induction +calculation or FALSE to neglect it. If ``TanInd = TRUE``, set +``TIDrag`` to TRUE to include drag in the tangential-induction +calculation or FALSE to neglect it. Even when drag is not used in the +BEM iteration, drag is still used to calculate the nodal loads once the +induction has been found, + +``IndToler`` sets the convergence threshold for the iterative +nonlinear solve of the BEM solution. The nonlinear solve is in terms of +the inflow angle, but ``IndToler`` represents the tolerance of the +nondimensional residual equation, with no physical association possible. +When the keyword ``DEFAULT`` is used in place of a numerical value, +``IndToler`` will be set to 5E-5 when AeroDyn is compiled in single +precision and to 5E-10 when AeroDyn is compiled in double precision; we +recommend using these defaults. ``MaxIter`` determines the maximum +number of iterations steps in the BEM solve. If the residual value of +the BEM solve is not less than or equal to ``IndToler`` in +``MaxIter``, AeroDyn will exit the BEM solver and return an error +message. + +Dynamic Blade-Element/Momentum Theory Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The input parameters in this section are used only when ``WakeMod = 2``. + +Set ``DBEMT_Mod`` to 1 for the constant-tau1 model, or set ``DBEMT_Mod`` to 2 +to use a model where tau1 varies with time. + +If ``DBEMT_Mod=1`` (constant-tau1 model), set ``tau1_const`` to the time +constant to use for DBEMT. + +OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The input parameters in this section are used only when ``WakeMod = 3``. + +The settings for the free vortex wake model are set in the OLAF input file +described in :numref:`OLAF-Input-Files`. ``OLAFInputFileName`` is the filename +for this input file. + + +Unsteady Airfoil Aerodynamics Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The input parameters in this section are only used when ``AFAeroMod += 2``. + +``UAMod`` determines the UA model. Setting ``UAMod`` to 1 enables +original theoretical developments of B-L, 2 enables the extensions to +B-L developed by González, and 3 enables the extensions to B-L developed +by Minnema/Pierce. **While all of the UA models are documented in this +manual, the original B-L model is not yet functional. Testing has shown +that the González and Minnema/Pierce models produce reasonable +hysteresis of the normal force, tangential force, and pitching-moment +coefficients if the UA model parameters are set appropriately for a +given airfoil, Reynolds number, and/or Mach number. However, the +results will differ a bit from earlier versions of AeroDyn, (which was +based on the Minnema/Pierce extensions to B-L) even if the default UA +model parameters are used, due to differences in the UA model logic +between the versions. We recommend that users run test cases with +uniform inflow and fixed yaw error (e.g., through the standalone AeroDyn +driver) to examine the accuracy of the normal force, tangential force, +and pitching-moment coefficient hysteresis and to adjust the UA model +parameters appropriately.** + +``FLookup`` determines how the nondimensional separation distance +value, *f’*, will be calculated. When ``FLookup`` is set to TRUE, *f’* +is determined via a lookup into the static lift-force coefficient and +drag-force coefficient data. **Using best-fit exponential equations +(``FLookup = FALSE``) is not yet available, so ``FLookup`` must be +``TRUE`` in this version of AeroDyn.** + + +.. _airfoil_information: + +Airfoil Information +~~~~~~~~~~~~~~~~~~~ + +This section defines the airfoil data input file information. The +airfoil data input files themselves (one for each airfoil) include +tables containing coefficients of lift force, drag force, and optionally +pitching moment, and minimum pressure versus AoA, as well as UA model +parameters, and are described in :numref:`airfoil_data_input_file`. + +The first 5 lines in the AIRFOIL INFORMATION section relate to the +format of the tables of static airfoil coefficients within each of the +airfoil input files. ``InCol_Alfa``, ``InCol_Cl``, +``InCol_Cd``, ``InCol_Cm,`` and ``InCol_Cpmin`` are column +numbers in the tables containing the AoA, lift-force coefficient, +drag-force coefficient, pitching-moment coefficient, and minimum +pressure coefficient, respectively (normally these are 1, 2, 3, 4, and +5, respectively). If pitching-moment terms are neglected with +``UseBlCm = FALSE``, ``InCol_Cm`` may be set to zero, and if the +cavitation check is disabled with ``CavitCheck = FALSE``, +``InCol_Cpmin`` may be set to zero. + +Specify the number of airfoil data input files to be used using +``NumAFfiles``, followed by ``NumAFfiles`` lines of filenames. The +file names should be in quotations and can contain an absolute path or a +relative path e.g., “C:\\airfoils\\S809_CLN_298.dat” or +“airfoils\\S809_CLN_298.dat”. If you use relative paths, it is +relative to the location of the file in which it is specified. The blade +data input files will reference these airfoil data using their line +identifier, where the first airfoil file is numbered 1 and the last +airfoil file is numbered ``NumAFfiles``. + +Rotor/Blade Properties +~~~~~~~~~~~~~~~~~~~~~~ + +Set ``UseBlCm`` to TRUE to include pitching-moment terms in the blade +airfoil aerodynamics or FALSE to neglect them; if ``UseBlCm = TRUE``, +pitching-moment coefficient data must be included in the airfoil data +tables with ``InCol_Cm`` not equal to zero. + +The blade nodal discretization, geometry, twist, chord, and airfoil +identifier are set in separate input files for each blade, described in +:numref:`blade_data_input_file`. ``ADBlFile(1)`` is the filename for blade 1, +``ADBlFile(2)`` is the filename for blade 2, and ``ADBlFile(3)`` is +the filename for blade 3, respectively; the latter is not used for +two-bladed rotors and the latter two are not used for one-bladed rotors. +The file names should be in quotations and can contain an absolute path +or a relative path. The data in each file need not be identical, which +permits modeling of aerodynamic imbalances. + +Tower Influence and Aerodynamics +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The input parameters in this section pertain to the tower influence +and/or tower drag calculations and are only used when ``TwrPotent`` > +0, ``TwrShadow`` > 0, or ``TwrAero = TRUE``. + +``NumTwrNds`` is the user-specified number of tower analysis nodes and +determines the number of rows in the subsequent table (after two table +header lines). ``NumTwrNds`` must be greater than or equal to two; the +higher the number, the finer the resolution and longer the computational +time; we recommend that ``NumTwrNds`` be between 10 and 20 to balance +accuracy with computational expense. For each node, ``TwrElev`` +specifies the local elevation of the tower node above ground (or above +MSL for offshore wind turbines or above the seabed for MHK turbines), +``TwrDiam`` specifies the local tower diameter, ``TwrCd`` specifies the +local tower drag-force coefficient, and ``TwrTI`` specifiest the +turbulence intensity used in the Eames tower shadow model +(``TwrShadow`` = 2). ``TwrElev`` must be entered in monotonically +increasing order—from the lowest (tower-base) to the highest +(tower-top) elevation. Values of ``TwrTI`` between 0.05 and 0.4 are +recommended. Values larger than 0.4 up to 1 will trigger a warning +that the results will need to be interpretted carefully, but the code +will allow such values for scientific investigation purposes. +See :numref:`fig:TwrGeom`. + + +.. _AD-Outputs: + +Outputs +~~~~~~~ + +Specifying ``SumPrint`` to TRUE causes AeroDyn to generate a summary +file with name ``OutFileRoot**.AD.sum*. ``OutFileRoot`` is either +specified in the I/O SETTINGS section of the driver input file when +running AeroDyn standalone, or by the OpenFAST program when running a +coupled simulation. See :numref:`sec:ad_SumFile` for summary file details. + +AeroDyn can output aerodynamic and kinematic quantities at up to nine +nodes specified along the tower and up to nine nodes along each blade. +For outputs at every blade node, see :numref:`AD-Nodal-Outputs`. + +``NBlOuts`` specifies the number of blade nodes that output is +requested for (0 to 9) and ``BlOutNd`` on the next line is a list +``NBlOuts`` long of node numbers between 1 and ``NumBlNds`` +(corresponding to a row number in the blade analysis node table in the +blade data input files), separated by any combination of commas, +semicolons, spaces, and/or tabs. All blades have the same output node +numbers. ``NTwOuts`` specifies the number of tower nodes that output +is requested for (0 to 9) and ``TwOutNd`` on the next line is a list +``NTwOuts`` long of node numbers between 1 and ``NumTwrNds`` +(corresponding to a row number in the tower analysis node table above), +separated by any combination of commas, semicolons, spaces, and/or tabs. +The outputs specified in the ``OutList`` section determine which +quantities are actually output at these nodes. + +.. _ad_tower_geom: + +.. figure:: figs/ad_tower_geom.png + :width: 60% + :name: fig:TwrGeom + :align: center + + AeroDyn Tower Geometry + + +The ``OutList`` section controls output quantities generated by +AeroDyn. Enter one or more lines containing quoted strings that in turn +contain one or more output parameter names. Separate output parameter +names by any combination of commas, semicolons, spaces, and/or tabs. If +you prefix a parameter name with a minus sign, “-”, underscore, “_”, or +the characters “m” or “M”, AeroDyn will multiply the value for that +channel by –1 before writing the data. The parameters are written in the +order they are listed in the input file. AeroDyn allows you to use +multiple lines so that you can break your list into meaningful groups +and so the lines can be shorter. You may enter comments after the +closing quote on any of the lines. Entering a line with the string “END” +at the beginning of the line or at the beginning of a quoted string +found at the beginning of the line will cause AeroDyn to quit scanning +for more lines of channel names. Blade and tower node-related quantities +are generated for the requested nodes identified through the +``BlOutNd`` and ``TwOutNd`` lists above. If AeroDyn encounters an +unknown/invalid channel name, it warns the users but will remove the +suspect channel from the output file. Please refer to Appendix E for a +complete list of possible output parameters. + +.. _AD-Nodal-Outputs: + +.. include:: ADNodalOutputs.rst + + +.. _airfoil_data_input_file: + +Airfoil Data Input File +----------------------- + +The airfoil data input files themselves (one for each airfoil) include +tables containing coefficients of lift force, drag force, and pitching +moment versus AoA, as well as UA model parameters. In these files, any +line whose first non-blank character is an exclamation point (!) is +ignored (for inserting comment lines). The non-comment lines should +appear within the file in order, but comment lines may be intermixed as +desired for reading clarity. A sample airfoil data input file is given +:numref:`ad_appendix`. + +``InterpOrd`` is the order the static airfoil data is interpolated +when AeroDyn uses table look-up to find the lift-, drag-, and optional +pitching-moment, and minimum pressure coefficients as a function of AoA. +When ``InterpOrd`` is 1, linear interpolation is used; when +``InterpOrd`` is 3, the data will be interpolated with cubic splines; +if the keyword ``DEFAULT`` is entered in place of a numerical value, +``InterpOrd`` is set to 1. + +``NonDimArea`` is the nondimensional airfoil area (normalized by the +local ``BlChord`` squared), but is currently unused by AeroDyn. +``NumCoords`` is the number of points to define the exterior shape of +the airfoil, plus one point to define the aerodynamic center, and +determines the number of rows in the subsequent table; ``NumCoords`` +must be exactly zero or greater than or equal to three. For each point, +the nondimensional *X* and *Y* coordinates are specified in the table, +``X_Coord`` and ``Y_Coord`` (normalized by the local +``BlChord``). The first point must always locate the aerodynamic +center (reference point for the airfoil lift and drag forces, likely not +on the surface of the airfoil); the remaining points should define the +exterior shape of the airfoil. The airfoil shape is currently unused by +AeroDyn, but when AeroDyn is coupled to OpenFAST, the airfoil shape will be +used by OpenFAST for blade surface visualization when enabled. + +``BL_file`` is the name of the file containing boundary-layer characteristics +of the profile. It is ignored if the aeroacoustic module is not used. + +Specify the number of Reynolds number- or aerodynamic-control +setting-dependent tables of data for the given airfoil via the +``NumTabs`` setting. The remaining parameters in the +airfoil data input files are entered separately for each table. + +``Re`` and ``UserProp`` are the Reynolds number (in millions) and +aerodynamic-control (or user property) setting for the included table. +These values are used only when the ``AFTabMod`` parameter in the +primary AeroDyn input file is set to use 2D interpolation based on +``Re`` or ``UserProp``. If 1D interpolation (based only on angle of attack) +is used, only the first table in the file will be used. + +Set ``InclUAdata`` to TRUE if you are including the 32 UA model +parameters (required when ``AFAeroMod = 2`` in the AeroDyn primary +input file): + +- ``alpha0`` specifies the zero-lift AoA (in degrees); + +- ``alpha1`` specifies the AoA (in degrees) larger than ``alpha0`` + for which *f* equals 0.7; approximately the positive stall angle; + +- ``alpha2`` specifies the AoA (in degrees) less than ``alpha0`` + for which *f* equals 0.7; approximately the negative stall angle; + +- ``eta_e`` is the recovery factor and typically has a value in the + range [0.85 to 0.95] for ``UAMod = 1``; if the keyword ``DEFAULT`` is + entered in place of a numerical value, ``eta_e`` is set to 0.9 for + ``UAMod = 1``, but ``eta_e`` is set to 1.0 for other ``UAMod`` + values and whenever ``FLookup = TRUE``; + +- ``C_nalpha`` is the slope of the 2D normal force coefficient curve + in the linear region; + +- ``T_f0`` is the initial value of the time constant associated with + *Df* in the expressions of *Df* and *f’*; if the keyword ``DEFAULT`` is + entered in place of a numerical value, ``T_f0`` is set to 3.0; + +- ``T_V0`` is the initial value of the time constant associated with + the vortex lift decay process, used in the expression of ``Cvn``; it + depends on Reynolds number, Mach number, and airfoil; if the keyword + ``DEFAULT`` is entered in place of a numerical value, ``T_V0`` is + set to 6.0; + +- ``T_p`` is the boundary-layer leading edge pressure gradient time + constant in the expression for *Dp* and should be tuned based on + airfoil experimental data; if the keyword ``DEFAULT`` is entered in + place of a numerical value, ``T_p`` is set to 1.7; + +- ``T_VL`` is the time constant associated with the vortex advection + process, representing the nondimensional time in semi-chords needed + for a vortex to travel from the leading to trailing edges, and used + in the expression of *Cvn*; it depends on Reynolds number, Mach + number (weakly), and airfoil; valued values are in the range [6 to + 13]; if the keyword ``DEFAULT`` is entered in place of a numerical + value, ``T_VL`` is set to 11.0; + +- ``b1`` is a constant in the expression of :math:`\phi_\alpha^c` and + :math:`\phi_q^c`; this value is + relatively insensitive for thin airfoils, but may be different for + turbine airfoils; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``b1`` is set to 0.14, based on experimental + results; + +- ``b2`` is a constant in the expression of :math:`\phi_\alpha^c` and + :math:`\phi_q^c`; this value is + relatively insensitive for thin airfoils, but may be different for + turbine airfoils; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``b2`` is set to 0.53, based on experimental + results; + +- ``b5`` is a constant in the expression of :math:`K^{'''}_q`, :math:`Cm_q^{nc}`, and :math:`K_{m_q}`; if the keyword + ``DEFAULT`` is entered in place of a numerical value, ``b5`` is set + to 5, based on experimental results; + +- ``A1`` is a constant in the expression :math:`\phi_\alpha^c` and :math:`\phi_q^c`; this value is relatively insensitive for thin airfoils, but may be different for + turbine airfoils; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``A1`` is set to 0.3, based on experimental + results; + +- ``A2`` is a constant in the expression :math:`\phi_\alpha^c` and + :math:`\phi_q^c`; this value is + relatively insensitive for thin airfoils, but may be different for + turbine airfoils; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``A2`` is set to 0.7, based on experimental + results; + +- ``A5`` is a constant in the expression :math:`K^{'''}_q`, + :math:`Cm_q^{nc}`, and :math:`K_{m_q}`; if the keyword + ``DEFAULT`` is entered in place of a numerical value, ``A5`` is set + to 1, based on experimental results; + +- ``S1`` is the constant in the best fit curve of *f* for + ``alpha0`` :math:`\le` AoA :math:`\le` ``alpha1`` for ``UAMod = 1`` (and is unused + otherwise); by definition, it depends on the airfoil; + +- ``S2`` is the constant in the best fit curve of *f* for AoA > + ``alpha1`` for ``UAMod = 1`` (and is unused otherwise); by + definition, it depends on the airfoil; + +- ``S3`` is the constant in the best fit curve of *f* for + ``alpha2`` :math:`\le` AoA :math:`\le` ``alpha0`` for ``UAMod = 1`` (and is unused + otherwise); by definition, it depends on the airfoil; + +- ``S4`` is the constant in the best fit curve of *f* for AoA < + ``alpha2`` for ``UAMod = 1`` (and is unused otherwise); by + definition, it depends on the airfoil; + +- ``Cn1`` is the critical value of :math:`C^{\prime}_n` at leading-edge separation for + positive AoA and should be extracted from airfoil data at a given + Reynolds number and Mach number; ``Cn1`` can be calculated from + the static value of *Cn* at either the break in the pitching moment + or the loss of chord force at the onset of stall; ``Cn1`` is close + to the condition of maximum lift of the airfoil at low Mach numbers; + +- ``Cn2`` is the critical value of :math:`C^{\prime}_n` at leading-edge separation for + negative AoA and should be extracted from airfoil data at a given + Reynolds number and Mach number; ``Cn2`` can be calculated from + the static value of *Cn* at either the break in the pitching moment + or the loss of chord force at the onset of stall; ``Cn2`` is close + to the condition of maximum lift of the airfoil at low Mach numbers; + +- ``St_sh`` is the Strouhal’s shedding frequency; if the keyword + ``DEFAULT`` is entered in place of a numerical value, ``St_sh`` is + set to 0.19; + +- ``Cd0`` is the drag-force coefficient at zero-lift AoA; + +- ``Cm0`` is the pitching-moment coefficient about the quarter-chord + location at zero-lift AoA, positive for nose up; + +- ``k0`` is a constant in the best fit curve of :math:`\hat{x}_{cp}` and equals for :math:`\hat{x}_{AC}-0.25` + ``UAMod = 1`` (and is unused otherwise); + +- ``k1`` is a constant in the best fit curve of :math:`\hat{x}_{cp}` for ``UAMod = 1`` + (and is unused otherwise); + +- ``k2`` is a constant in the best fit curve of :math:`\hat{x}_{cp}` for ``UAMod = 1`` + (and is unused otherwise); + +- ``k3`` is a constant in the best fit curve of :math:`\hat{x}_{cp}` for ``UAMod = 1`` + (and is unused otherwise); + +- ``k1_hat`` is a constant in the expression of *Cc* due to + leading-edge vortex effects for ``UAMod = 1`` (and is unused + otherwise); + +- ``x_cp_bar`` is a constant in the expression of :math:`\hat{x}_{cp}^{\nu}` for ``UAMod = + 1`` (and is unused otherwise); if the keyword ``DEFAULT`` is entered in + place of a numerical value, ``x_cp_bar`` is set to 0.2; and + +- ``UACutOut`` is the AoA (in degrees) in absolute value above which + UA are disabled; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``UACutOut`` is set to 45. + +- ``filtCutOff`` is the cut-off reduced frequency + of the low-pass filter applied to the AoA input to UA, as + well as to the pitch rate and pitch acceleration derived from AoA + within UA; if the keyword ``DEFAULT`` is entered in place of a + numerical value, ``filtCutOff`` is set to 0.5. + +``NumAlf`` is the number of distinct AoA entries and determines the +number of rows in the subsequent table of static airfoil coefficients; +``NumAlf`` must be greater than or equal to one (``NumAlf = 1`` +implies constant coefficients, regardless of the AoA). + +AeroDyn will +interpolate on AoA using the data provided via linear interpolation or via cubic +splines, depending on the setting of input ``InterpOrd`` above. +If ``AFTabMod`` is set to ``1``, only the first airfoil table in each file +will be used. If ``AFTabMod`` is set to ``2``, AeroDyn will find the +airfoil tables that bound the computed Reynolds number, +and linearly interpolate between the tables, using the logarithm of the Reynolds numbers. +If ``AFTabMod`` is set to ``3``, it will find the bounding airfoil +tables based on the ``UserProp`` field and linearly interpolate the tables +based on it. Note that OpenFAST currently sets the ``UserProp`` input value to ``0`` +unless the DLL controller is used and sets the value, +so using this feature may require a code change. + +For each AoA, you must set the AoA (in degrees), ``alpha``, the lift-force +coefficient, ``Coefs``\ (:,1), the drag-force coefficient, +``Coefs(:,2)``, and optionally the pitching-moment coefficient, +``Coefs(:,3)``, and minimum pressure coefficient, +``Coefs(:,4)``, but the column order depends on the settings of +``InCol_Alfa``, ``InCol_Cl``, ``InCol_Cd``, ``InCol_Cm``, +and ``InCol_Cpmin`` in the AIRFOIL INFORMATION section of the AeroDyn +primary input file. AoA must be entered in monotonically increasing +order—from lowest to highest AoA—and the first row should be for AoA = +–180 and the last should be for AoA = +180 (unless ``NumAlf = 1``, in +which case AoA is unused). If pitching-moment terms are neglected with +``UseBlCm = FALSE`` in the ROTOR/BLADE PROPERTIES section of the +AeroDyn primary input file, the column containing pitching-moment +coefficients may be absent from the file. Likewise, if the cavitation +check is neglected with ``CavitCheck = FALSE`` in the GENERAL OPTIONS +section of the AeroDyn primary input file, the column containing the +minimum pressure coefficients may be absent from the file. + +.. _blade_data_input_file: + +Blade Data Input File +--------------------- + +The blade data input file contains the nodal discretization, geometry, +twist, chord, and airfoil identifier for a blade. Separate files are +used for each blade, which permits modeling of aerodynamic imbalances. A +sample blade data input file is given in :numref:`ad_appendix`. + +The input file begins with two lines of header information which is for +your use, but is not used by the software. + +``NumBlNds`` is the user-specified number of blade analysis nodes and +determines the number of rows in the subsequent table (after two table +header lines). ``NumBlNds`` must be greater than or equal to two; the +higher the number, the finer the resolution and longer the computational +time; we recommend that ``NumBlNds`` be between 10 and 20 to balance +accuracy with computational expense. Even though ``NumBlNds`` is +defined in each blade file, all blades must have the same number of +nodes. For each node: + +- ``BlSpn`` specifies the local span of the blade node along the + (possibly preconed) blade-pitch axis from the root; ``BlSpn`` must + be entered in monotonically increasing order—from the most inboard to + the most outboard—and the first node must be zero, and when AeroDyn + is coupled to OpenFAST, the last node should be located at the blade tip; + +- ``BlCrvAC`` specifies the local out-of-plane offset (when the + blade-pitch angle is zero) of the aerodynamic center (reference point + for the airfoil lift and drag forces), normal to the blade-pitch + axis, as a result of blade curvature; ``BlCrvAC`` is positive + downwind; upwind turbines have negative ``BlCrvAC`` for improved + tower clearance; + +- ``BlSwpAC`` specifies the local in-plane offset (when the + blade-pitch angle is zero) of the aerodynamic center (reference point + for the airfoil lift and drag forces), normal to the blade-pitch + axis, as a result of blade sweep; positive ``BlSwpAC`` is opposite + the direction of rotation; + +- ``BlCrvAng`` specifies the local angle (in degrees) from the + blade-pitch axis of a vector normal to the plane of the airfoil, as a + result of blade out-of-plane curvature (when the blade-pitch angle is + zero); ``BlCrvAng`` is positive downwind; upwind turbines have + negative ``BlCrvAng`` for improved tower clearance; + +- ``BlTwist`` specifies the local aerodynamic twist angle (in + degrees) of the airfoil; it is the orientation of the local chord + about the vector normal to the plane of the airfoil, positive to + feather, leading edge upwind; the blade-pitch angle will be added to + the local twist; + +- ``BlChord`` specifies the local chord length; and + +- ``BlAFID`` specifies which airfoil data the local blade node is + associated with; valid values are numbers between 1 and + ``NumAFfiles`` (corresponding to a row number in the airfoil file + table in the AeroDyn primary input file); multiple blade nodes can + use the same airfoil data. + +See :numref:`ad_blade_geom`. Twist is shown in :numref:`ad_blade_local_cs` of :numref:`ad_appendix`. + +.. _ad_blade_geom: + +.. figure:: figs/ad_blade_geom.png + :width: 90% + :align: center + + AeroDyn Blade Geometry – Left: Side View; Right: Front View (Looking Downwind) + diff --git a/OpenFAST/docs/source/user/aerodyn/introduction.rst b/OpenFAST/docs/source/user/aerodyn/introduction.rst new file mode 100644 index 000000000..62674e3fa --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/introduction.rst @@ -0,0 +1,198 @@ +.. _ad_intro: + +Introduction +============ + +AeroDyn is a time-domain wind turbine aerodynamics module that is coupled in the +OpenFAST multi-physics engineering tool to enable aero-elastic simulation of +horizontal-axis turbines. AeroDyn can also be driven as a standalone code to +compute wind turbine aerodynamic response uncoupled from OpenFAST. When coupled +to OpenFAST, AeroDyn can also be linearized as part of the linearization of the +full coupled solution (linearization is not available in standalone mode). +AeroDyn was originally developed for modeling wind turbine aerodynamics. +However, the module equally applies to the hydrodynamics of marine hydrokinetic +(MHK) turbines (the terms “wind turbine”, “tower”, “aerodynamics” etc. in this +document imply “MHK turbine”, “MHK support structure”, “hydrodynamics” etc. for +MHK turbines). Additional physics important for MHK turbines, not applicable to +wind turbines, computed by AeroDyn include a cavitation check. This +documentation pertains version of AeroDyn in the OpenFAST github repository. +The AeroDyn version released of OpenFAST 1.0.0 is most closely related to +AeroDyn version 15 in the legacy version numbering. AeroDyn version 15 was a +complete overhaul from earlier version of AeroDyn. AeroDyn version 15 and newer +follows the requirements of the FAST modularization framework. + +AeroDyn calculates aerodynamic loads on both the blades and tower. +Aerodynamic calculations within AeroDyn are based on the principles of +actuator lines, where the three-dimensional (3D) flow around a body is +approximated by local two-dimensional (2D) flow at cross sections, and +the distributed pressure and shear stresses are approximated by lift +forces, drag forces, and pitching moments lumped at a node in a 2D cross +section. Analysis nodes are distributed along the length of each blade +and tower, the 2D forces and moment at each node are computed as +distributed loads per unit length, and the total 3D aerodynamic loads +are found by integrating the 2D distributed loads along the length. When +AeroDyn is coupled to OpenFAST, the blade and tower analysis node +discretization may be independent from the discretization of the nodes +in the structural modules. The actuator line approximations restrict the +validity of the model to slender structures and 3D behavior is either +neglected, captured through corrections inherent in the model (e.g., +tip-loss, hub-loss, or skewed-wake corrections), or captured in the +input data (e.g., rotational augmentation corrections applied to airfoil +data). + +AeroDyn assumes the turbine geometry consists of a one-, two-, or +three-bladed rotor atop a single tower. While the undeflected tower is +assumed to be straight and vertical, an undeflected blade may consider +out-of-plane curvature and in-plane sweep. For blades, the 2D cross +sections where the aerodynamic analysis take place may follow the +out-of-plane curvature, but in-plane sweep is assumed to be accomplished +by shearing, rather than rotation of the 2D cross section. Aerodynamic +imbalances are possible through the use of geometrical differences +between each blade. + +When AeroDyn is coupled to OpenFAST, AeroDyn receives the instantaneous +(possibly displaced/deflected) structural position, orientation, and +velocities of analysis nodes in the tower, hub, and blades. As with +curvature and sweep, the 2D cross sections where the blade aerodynamic +analysis takes place will follow the out-of-plane deflection, but +in-plane deflection is assumed to be accomplished by shearing, rather +than rotation of the 2D cross section. AeroDyn also receives the local +freestream (undisturbed) fluid velocities at the tower and blade nodes. +(Fluid and structural calculations take place outside of the AeroDyn +module and are passed as inputs to AeroDyn by the driver code.) The +fluid and structural motions are provided at each coupling time step and +then AeroDyn computes the aerodynamic loads on the blade and tower nodes +and returns them back to OpenFAST as part of the aero-elastic calculation. +In standalone mode, the inputs to AeroDyn are prescribed by a simple +driver code, without aero-elastic coupling. + +AeroDyn consists of four submodels: (1) rotor wake/induction, (2) blade +airfoil aerodynamics, (3) tower influence on the fluid local to the +blade nodes, and (4) tower drag. Nacelle, hub, and tail-vane fluid +influence and loading, aeroacoustics, and wake and array effects between +multiple turbines in a wind plant, are not yet available in AeroDyn v15 +and newer. + +For operating wind and MHK turbine rotors, AeroDyn calculates the +influence of the wake via induction factors based on the quasi-steady +Blade-Element/Momentum (BEM) theory, which requires an iterative +nonlinear solve (implemented via Brent’s method). By quasi-steady, it is +meant that the induction reacts instantaneously to loading changes. The +induction calculation, and resulting inflow velocities and angles, are +based on flow local to each analysis node of each blade, based on the +relative velocity between the fluid and structure (including the effects +of local inflow skew, shear, turbulence, tower flow disturbances, and +structural motion, depending on features enabled). The Glauert’s +empirical correction (with Buhl’s modification) replaces the linear +momentum balance at high axial induction factors. In the BEM solution, +Prandtl tip-loss, Prandtl hub-loss, and Pitt and Peters skewed-wake are +all 3D corrections that can optionally be applied. When the skewed-wake +correction is enabled, it is applied after the BEM iteration. +Additionally, the calculation of tangential induction (from the angular +momentum balance), the use of drag in the axial-induction calculation, +and the use of drag in the tangential-induction calculation are all +terms that can optionally be included in the BEM iteration (even when +drag is not used in the BEM iteration, drag is still used to calculate +the nodal loads once the induction has been found). The wake/induction +calculation can be bypassed altogether for the purposes of modeling +rotors that are parked or idling, in which case the inflow velocity and +angle are determined purely geometrically. During linearization analyses +with AeroDyn coupled to OpenFAST and BEM enabled, the wake can be assumed to +be frozen (i.e., the axial and tangential induces velocities, :math:`-V_x a` and :math:`V_y a'`, are +fixed at their operating-point values during linearization) or the +induction can be recalculated during linearization using BEM theory. +Dynamic wake that accounts for induction dynamics as a result of +transient conditions are not yet available in AeroDyn v15 and newer. + +The blade airfoil aerodynamics can be steady or unsteady, except in the +case that a cavitation check is requested for MHK, in which case only +steady aerodynamics are supported. In the steady model, the supplied +static airfoil data — including the lift force, drag force, and optional +pitching moment and minimum pressure coefficients versus angle of attack +(AoA) — are used directly to calculate nodal loads. The +`AirfoilPrep <https://nwtc.nrel.gov/AirFoilPrep>`__ preprocessor can be +used to generate the needed static airfoil data based on uncorrected 2D +data (based, e.g., on airfoil tests in a wind tunnel or +`XFoil <http://web.mit.edu/drela/Public/web/xfoil/>`__), including +features to blend data between different airfoils, apply 3D rotational +augmentation, and extrapolate to high AoA. The unsteady airfoil +aerodynamic (UA) models account for flow hysteresis, including unsteady +attached flow, trailing-edge flow separation, dynamic stall, and flow +reattachment. The UA models can be considered as 2D dynamic corrections +to the static airfoil response as a result of time-varying inflow +velocities and angles. Three semi-empirical UA models are available: the +original theoretical developments of Beddoes-Leishman (B-L), extensions +to the B-L developed by González, and extensions to the B-L model +developed by Minnema/Pierce. **While all of the UA models are documented +in this manual, the original B-L model is not yet functional. Testing +has shown that the González and Minnema/Pierce models produce reasonable +hysteresis of the normal force, tangential force, and pitching-moment +coefficients if the UA model parameters are set appropriately for a +given airfoil, Reynolds number, and/or Mach number. However, the +results will differ a bit from earlier versions of AeroDyn, (which was +based on the Minnema/Pierce extensions to B-L) even if the default UA +model parameters are used, due to differences in the UA model logic +between the versions. We recommend that users run test cases with +uniform wind inflow and fixed yaw error (e.g., through the standalone +AeroDyn driver) to examine the accuracy of the normal force, tangential +force, and pitching-moment coefficient hysteresis and to adjust the UA +model parameters appropriately.** The airfoil-, Reynolds-, and +Mach-dependent parameters of the UA models may be derived from the +static airfoil data. These UA models are valid for small to moderate AoA +under normal rotor operation; the steady model is more appropriate under +parked or idling conditions. The static airfoil data is always used in +the BEM iteration; when UA is enabled, it is applied after the BEM +iteration and after the skewed-wake correction. The UA models are not +set up to support linearization, so, UA must be disabled during +linearization analyses with AeroDyn coupled to OpenFAST. The interpolation +of airfoil data based on Reynolds number or aerodynamic-control setting +(e.g., flaps) is not yet available in AeroDyn v15 and newer. + +The influence of the tower on the fluid flow local to the blade is based +on a potential-flow and/or a tower-shadow model. The potential-flow +model uses the analytical potential-flow solution for flow around a +cylinder to model the tower dam effect on upwind rotors. In this model, +the freestream (undisturbed) flow at each blade node is disturbed based +on the location of the blade node relative to the tower and the tower +diameter, including lower velocities upstream and downstream of the +tower, higher velocities to the left and right of the tower, and +cross-stream flow. The Bak correction can optionally be included in the +potential-flow model, which augments the tower upstream disturbance and +improves the tower wake for downwind rotors based on the tower drag +coefficient. The tower shadow model can also be enabled to account for +the tower wake deficit on downwind rotors. This model includes an axial +flow deficit on the freestream fluid at each blade node dependent on the +location of the blade node relative to the tower and the tower diameter +and drag coefficient, based on the work of Powles. Both tower-influence +models are quasi-steady models, in that the disturbance is applied +directly to the freestream fluid at the blade nodes without dynamics, +and are applied within the BEM iteration. + +The aerodynamic load on the tower is based directly on the tower +diameter and drag coefficient and the local relative fluid velocity +between the freestream (undisturbed) flow and structure at each tower +analysis node (including the effects of local shear, turbulence, and +structural motion, depending on features enabled). The tower drag load +calculation is quasi-steady and independent from the tower influence on +flow models. + +The primary AeroDyn input file defines modeling options, environmental +conditions (except freestream flow), airfoils, tower nodal +discretization and properties, as well as output file specifications. +Airfoil data properties are read from dedicated inputs files (one for +each airfoil) and include coefficients of lift force, drag force, and +optional pitching moment and minimum pressure versus AoA, as well as UA +model parameters. (Minimum pressure coefficients versus AoA are also +included in the airfoil input files in case that a cavitation check is +requested.) Blade nodal discretization, geometry, twist, chord, and +airfoil identifier are likewise read from separate input files (one for +each blade). + +:numref:`ad_input` describes the AeroDyn input files. +:numref:`ad_output` discusses the +output files generated by AeroDyn; these include an echo file, summary +file, and the results file. +:numref:`ad_modeling` provides modeling guidance when +using AeroDyn. +Example input files are included in :numref:`ad_input_files`. A summary of +available output channels are found :numref:`ad_output_channels`. diff --git a/OpenFAST/docs/source/user/aerodyn/modeling.rst b/OpenFAST/docs/source/user/aerodyn/modeling.rst new file mode 100644 index 000000000..a63f54107 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/modeling.rst @@ -0,0 +1,131 @@ +.. _ad_modeling: + +Modeling Considerations +======================= + + +AeroDyn was designed as an extremely flexible tool for modeling a +wide-range of aerodynamic conditions and turbine configurations. This +section provides some general guidance to help you construct models that +are compatible with AeroDyn. + +Please refer to the theory of Section 7 for detailed information about +the implementation approach we have followed in AeroDyn. + +Standalone AeroDyn Driver +------------------------- + +The standalone AeroDyn driver code is very useful for computing turbine +aerodynamics independent of aero-elastic coupling. The standalone +AeroDyn driver code essentially replaces the functionality previously +available in the separate wind turbine rotor-performance tool WT\_Perf. +For example, the standalone AeroDyn driver code can be used to compute +the surfaces of power coefficient (C\ :sub:`P`), thrust coefficient +(C\ :sub:`T`), and/or torque coefficient (C\ :sub:`Q`) as a function of +tip-speed ratio (TSR) and blade-pitch angle for a given rotor. Moreover, +the standalone AeroDyn driver code is more powerful than WT\_Perf in +that the standalone AeroDyn driver can capture time-varying dynamics as +a result of nacelle-yaw error, shaft tilt, and/or wind shear. + +Environmental Conditions +------------------------ + +For air, typical values for ``AirDens``, ``KinVisc``, +``SpdSound``, and ``Patm`` are around 1.225 kg/m\ :sup:`3`, 1.460E-5 +m\ :sup:`2`/s, 340.3 m/s, and 101,325 Pa, respectively. For seawater, +typical values for ``AirDens``, ``KinVisc``, and ``Pvap`` are +around 1025 kg/m\ :sup:`3`, 1.004E-6 m\ :sup:`2`/s, and 2000 Pa, +respectively. + +Temporal and Spatial Discretization +----------------------------------- + +For accuracy and numerical stability, we recommend that ``DTAero`` be +set such that there are at least 200 azimuth steps per rotor revolution. +However, when AeroDyn is coupled to FAST, FAST may require time steps +much smaller than this rule of thumb. If UA is enabled while using very +small time steps, you may need to recompile AeroDyn in double precision +to avoid numerical problems in the UA routines. + +For the blade and tower spatial discretization, using higher number of +analysis nodes will result in a more accurate solution at the expense of +longer computational time. When AeroDyn is coupled to FAST, the blade +and tower analysis node discretization may be independent from the +discretization of the nodes in the structural modules. + +We recommend that ``NumBlNds`` be between 10 and 20 to balance +accuracy with computational expense for the rotor aerodynamic load +calculation. It may be beneficial to use a finer resolution of nodes +where large gradients are expected in the aerodynamic loads e.g. near +the blade tip. Aerodynamic imbalances are possible through the use of +geometrical differences between each blade. + +When the tower potential-flow (``TwrPotent > 0``), tower shadow +(``TwrShadow > 0``), and/or the tower aerodynamic load +(``TwrAero = TRUE``) models are enabled, we also recommend that +``NumTwrNds`` be between 10 and 20 to balance accuracy with +computational expense. Normally the local elevation of the tower node +above ground (or above MSL for offshore wind turbines or above the +seabed for MHK turbines) (``TwrElev``), must be entered in +monotonically increasing order from the lowest (tower-base) to the +highest (tower-top) elevation. However, when AeroDyn is coupled to FAST, +the tower-base node in AeroDyn cannot be set lower than the lowest point +where wind is specified in the InflowWind module. To avoid truncating +the lower section of the tower in AeroDyn, we recommend that the wind be +specified in InflowWind as low to the ground (or MSL for offshore wind +turbines or above the seabed for MHK turbines) as possible (this is a +particular issue for full-field wind file formats). + +Model Options Under Operational and Parked/Idling Conditions +------------------------------------------------------------ + +To model an operational rotor, we recommend to include the dynamic BEM model +(``WakeMod = 2``) and UA (``AFAeroMod = 2``). Normally, the Pitt and +Peters skewed-wake (``SkewMod = 2``), Prandtl tip-loss (``TipLoss += TRUE``), Prandtl hub-loss (``HubLoss = TRUE``), and tangential +induction (``TanInd = TRUE``) models should all be enabled, but +``SkewMod = 2`` is invalid for very large yaw errors (much greater +than 45 degrees). The nonlinear solve in the BEM solution is in terms of the +inflow angle, but ``IndToler`` represents the tolerance of the +nondimensional residual equation, with no physical association possible; +we recommend setting ``IndToler`` to ``DEFAULT``. + +*While all of the UA models are documented in this manual, the original +B-L model is not yet functional. Testing has shown that the González and +Minnema/Pierce models produce reasonable hysteresis of the normal force, +tangential force, and pitching-moment coefficients if the UA model +parameters are set appropriately for a given airfoil, Reynolds number, +and/or Mach number. However, the results will differ a bit from earlier +versions of AeroDyn, (which was based on the Minnema/Pierce extensions +to B-L) even if the default UA model parameters are used, due to +differences in the UA model logic between the versions. We recommend +that users run test cases with uniform inflow and fixed yaw error (e.g., +through the standalone AeroDyn driver) to examine the accuracy of the +normal force, tangential force, and pitching-moment coefficient +hysteresis and to adjust the UA model parameters appropriately.* + +To model a parked or idling rotor, we recommend to disable induction +(``WakeMod = 0``) and UA (``AFAeroMod = 1``), in which case the +inflow velocity and angle are determined purely geometrically and the +airfoil data is determined statically. + +The direct aerodynamic load on the tower often dominates the aerodynamic +load on the rotor for parked or idling conditions above the cut-out wind +speed, in which case we recommend that ``TwrAero = TRUE``. Otherwise, +``TwrAero = FALSE`` may be satisfactory. + +We recommend to include the influence of the tower on the fluid local to +the blade for both operational and parked/idling rotors. We recommend +that ``TwrPotent > 0`` for upwind rotors and that ``TwrPotent = 2`` +or ``TwrShadow > 0`` for downwind rotors. + +Linearization +------------- + + +When coupled to FAST, AeroDyn can be linearized as part of the +linearization of the full coupled solution. When induction is enabled +(``WakeMod = 1``), we recommend to base the linearized solution on the +frozen-wake assumption, by setting ``FrozenWake = TRUE``. The UA +models are not set up to support linearization, so, UA must be disabled +during linearization by setting ``AFAeroMod = 1``. diff --git a/OpenFAST/docs/source/user/aerodyn/output.rst b/OpenFAST/docs/source/user/aerodyn/output.rst new file mode 100644 index 000000000..2a7d81dcc --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/output.rst @@ -0,0 +1,54 @@ +.. _ad_output: + +Output Files +============ + +AeroDyn produces three types of output files: an echo file, a summary +file, and a time-series results file. The following sections detail the +purpose and contents of these files. + +Echo Files +---------- + +If you set the ``Echo`` flag to ``TRUE`` in the AeroDyn driver file or the +AeroDyn primary input file, the contents of those files will be echoed +to a file with the naming conventions, *OutFileRoot.ech* for the +driver input file and *OutFileRoot.AD.ech* for the AeroDyn primary +input file. ``OutFileRoot`` is either specified in the I/O SETTINGS +section of the driver input file when running AeroDyn standalone, or by +the FAST program when running a coupled simulation. The echo files are +helpful for debugging your input files. The contents of an echo file +will be truncated if AeroDyn encounters an error while parsing an input +file. The error usually corresponds to the line after the last +successfully echoed line. + +.. _sec:ad_SumFile: + +Summary File +------------ + +AeroDyn generates a summary file with the naming convention, +*OutFileRoot.AD.sum* if the ``SumPrint`` parameter is set to ``TRUE``. +``OutFileRoot`` is either specified in the I/O SETTINGS section of the +driver input file when running AeroDyn standalone, or by the FAST +program when running a coupled simulation. This file summarizes key +information about your aerodynamics model, including which features have +been enabled and what outputs have been selected. + +Results Files +------------- + +In standalone mode, the AeroDyn time-series results (a separate file for +each case) are written to text-based files with the naming convention +*OutFileRoot.#.out*, where ``OutFileRoot`` is specified in the I/O +SETTINGS section of the driver input file and the ‘\ *#*\ ’ character is +an integer number corresponding to a test case line found in the +COMBINED-CASE ANALYSIS section. If AeroDyn is coupled to FAST, then FAST +will generate a master results file that includes the AeroDyn results +and AeroDyn will not write out its own results. The results are in table +format, where each column is a data channel (the first column always +being the simulation time), and each row corresponds to a simulation +output time step. The data channels are specified in the OUTPUTS section +of the AeroDyn primary input file. The column format of the +AeroDyn-generated files is specified using the ``OutFmt`` parameter of +the driver input file. diff --git a/OpenFAST/docs/source/user/aerodyn/theory.rst b/OpenFAST/docs/source/user/aerodyn/theory.rst new file mode 100644 index 000000000..39b383dc3 --- /dev/null +++ b/OpenFAST/docs/source/user/aerodyn/theory.rst @@ -0,0 +1,30 @@ + +.. _AD_theory: + +AeroDynTheory +============= + +This theory manual is work in progress, please refer to the AeroDyn manual for more details. + + +.. _AD_twr_shadow: + +Tower shadow models +~~~~~~~~~~~~~~~~~~~ + +Powles tower shadow model (**TwrShadow=1**) is given by: + +.. math:: + u_{TwrShadow} = - \frac{C_d}{ \sqrt{\overline{r}} } + \cos\left( \frac{\pi/2 \overline{y}}{\sqrt{\overline{r}}}\right)^2 + +where :math:`\overline{r} = \sqrt{ \overline{x}^2 + \overline{y}^2 }`. + + +Eames tower shadow model (**TwrShadow=2**) is given by: + +.. math:: + u_{TwrShadow} = -\frac{C_d}{ TI \: \overline{x} \, \sqrt{2 \pi } } + \exp{\left( -\frac{1}{2} \left(\frac{ \overline{y}}{ TI \: \overline{x} } \right)^2 \right) } + +where :math:`TI` is the turbulence intensity at the tower node. diff --git a/OpenFAST/docs/source/user/api_change.rst b/OpenFAST/docs/source/user/api_change.rst new file mode 100644 index 000000000..22d7566e5 --- /dev/null +++ b/OpenFAST/docs/source/user/api_change.rst @@ -0,0 +1,182 @@ +.. _api_change: + +API changes between versions +============================ + +This page lists the main changes in the OpenFAST API (input files) between different versions. + +The changes are tabulated according to the module input file, line number, and flag name. +The line number corresponds to the resulting line number after all changes are implemented. +Thus, be sure to implement each in order so that subsequent line numbers are correct. + +OpenFAST v2.5.0 to OpenFAST dev +------------------------------- + +============== ==== ================== ============================================================================================================================================================================= +Added in OpenFAST dev +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Module Line Flag Name Example Value +============== ==== ================== ============================================================================================================================================================================= +AD15 TwrTi 0.0000000E+00 6.0000000E+00 1.0000000E+00 1.0000000E-01 [additional column in *Tower Influence and Aerodynamics* table] +============== ==== ================== ============================================================================================================================================================================= + + + +============== ==== ================== ============================================================================================================================================================================= +Changed in OpenFAST dev +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Module Line Flag Name Example Value +============== ==== ================== ============================================================================================================================================================================= +AD15 9 TwrShadow 0 TwrShadow - Calculate tower influence on wind based on downstream tower shadow (switch) {0=none, 1=Powles model, 2=Eames model} +============== ==== ================== ============================================================================================================================================================================= + + +OpenFAST v2.4.0 to OpenFAST v2.5.0 +---------------------------------- + +============== ==== ================== ============================================================================================================================================================================= +Added in OpenFAST v2.5.0 +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Module Line Flag Name Example Value +============== ==== ================== ============================================================================================================================================================================= +IfW driver 6 [separator line] ===================== File Conversion Options ================================= +IfW driver 7 WrHAWC false WrHAWC - Convert all data to HAWC2 format? (flag) +IfW driver 8 WrBladed false WrBladed - Convert all data to Bladed format? (flag) +IfW driver 9 WrVTK false WrVTK - Convert all data to VTK format? (flag) +InflowWind 7 VFlowAng 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) +============== ==== ================== ============================================================================================================================================================================= + + +OpenFAST v2.3.0 to OpenFAST v2.4.0 +---------------------------------- + +============== ==== ================== ============================================================================================================================================================================= +Added in OpenFAST v2.4.0 +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Module Line Flag Name Example Value +============== ==== ================== ============================================================================================================================================================================= +HydroDyn 53 ExctnMod 0 ExctnMod - Wave Excitation model {0: None, 1: DFT, 2: state-space} (-) +OpenFAST 44 CalcSteady true CalcSteady - Calculate a steady-state periodic operating point before linearization? [unused if Linearize=False] (flag) +OpenFAST 45 TrimCase 3 TrimCase - Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] (-) +OpenFAST 46 TrimTol 0.0001 TrimTol - Tolerance for the rotational speed convergence [used only if CalcSteady=True] (-) +OpenFAST 47 TrimGain 0.001 TrimGain - Proportional gain for the rotational speed error (>0) [used only if CalcSteady=True] (rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque) +OpenFAST 48 Twr_Kdmp 0 Twr_Kdmp - Damping factor for the tower [used only if CalcSteady=True] (N/(m/s)) +OpenFAST 49 Bld_Kdmp 0 Bld_Kdmp - Damping factor for the blades [used only if CalcSteady=True] (N/(m/s)) +InflowWind 48 InitPosition(x) 0.0 InitPosition(x) - Initial offset in +x direction (shift of wind box) [Only used with WindType = 5] (m) +AeroDyn 13 CompAA False CompAA - Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2] +AeroDyn 14 AA_InputFile "unused" AA_InputFile - Aeroacoustics input file +AeroDyn 35 [separator line] ====== OLAF cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3] +AeroDyn 36 OLAFInputFileName "Elliptic_OLAF.dat" OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] +AirFoilTables 4\* BL_file "unused" BL_file - The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called. +============== ==== ================== ============================================================================================================================================================================= + +Modified in OpenFAST v2.4.0 +--------------------------- + +============== ==== ================== ============================================================================================================================================================================= + Module Line Flag Name Example Value +============== ==== ================== ============================================================================================================================================================================= +AirFoilTables 40\* filtCutOff "DEFAULT" filtCutOff - Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5] +============== ==== ================== ============================================================================================================================================================================= + +\*non-comment line count, excluding lines contained if NumCoords is not 0. + +Additional nodal output channels added for :ref:`AeroDyn15<AD-Nodal-Outputs>`, +:ref:`BeamDyn<BD-Nodal-Outputs>`, and :ref:`ElastoDyn<ED-Nodal-Outputs>`. + +OpenFAST v2.2.0 to OpenFAST v2.3.0 +---------------------------------- + +============================================= ==== =============== ======================================================================================================================================================================================================== +Removed in OpenFAST v2.3.0 +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +============================================= ==== =============== ======================================================================================================================================================================================================== +AeroDyn Airfoil Input File - Airfoil Tables 2 Ctrl 0 Ctrl ! Control setting (must be 0 for current AirfoilInfo) +============================================= ==== =============== ======================================================================================================================================================================================================== + + +============================================= ==== =============== ======================================================================================================================================================================================================== +Added in OpenFAST v2.3.0 +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +============================================= ==== =============== ======================================================================================================================================================================================================== +AeroDyn Airfoil Input File - Airfoil Tables 2 UserProp 0 UserProp ! User property (control) setting +AeroDyn 37 AFTabMod 1 AFTabMod - Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-) +============================================= ==== =============== ======================================================================================================================================================================================================== + + +OpenFAST v2.1.0 to OpenFAST v2.2.0 +---------------------------------- + +No changes required. + + +OpenFAST v2.0.0 to OpenFAST v2.1.0 +---------------------------------- + +============== ==== ================== ===================================================================================================================================================================== + Added in OpenFAST v2.1.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Module Line Flag Name Example Value +============== ==== ================== ===================================================================================================================================================================== +BeamDyn driver 21 GlbRotBladeT0 True GlbRotBladeT0 - Reference orientation for BeamDyn calculations is aligned with initial blade root? +============== ==== ================== ===================================================================================================================================================================== + +OpenFAST v1.0.0 to OpenFAST v2.0.0 +---------------------------------- + +========= ==== ================== ===================================================================================================================================================================== +Removed in OpenFAST v2.0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +========= ==== ================== ===================================================================================================================================================================== +BeamDyn 5 analysis_type analysis_type - 1: Static analysis; 2: Dynamic analysis +========= ==== ================== ===================================================================================================================================================================== + + +========= ==== ================== ===================================================================================================================================================================== +Added in OpenFAST v2.0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +========= ==== ================== ===================================================================================================================================================================== +AeroDyn 22 SkewModFactor "default" SkewModFactor - Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0] +AeroDyn 30 Section header ====== Dynamic Blade-Element/Momentum Theory Options ============================================== [used only when WakeMod=2] +AeroDyn 31 DBEMT_Mod 2 DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2] +AeroDyn 32 tau1_const 4 tau1_const - Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1] +BeamDyn 5 QuasiStaticInit True QuasiStaticInit - Use quasi-static pre-conditioning with centripetal accelerations in initialization (flag) [dynamic solve only] +BeamDyn 11 load_retries DEFAULT load_retries - Number of factored load retries before quitting the simulation +BeamDyn 14 tngt_stf_fd DEFAULT tngt_stf_fd - Flag to use finite differenced tangent stiffness matrix (-) +BeamDyn 15 tngt_stf_comp DEFAULT tngt_stf_comp - Flag to compare analytical finite differenced tangent stiffness matrix (-) +BeamDyn 16 tngt_stf_pert DEFAULT tngt_stf_pert - perturbation size for finite differencing (-) +BeamDyn 17 tngt_stf_difftol DEFAULT tngt_stf_difftol - Maximum allowable relative difference between analytical and fd tangent stiffness (-) +BeamDyn 18 RotStates True RotStates - Orient states in the rotating frame during linearization? (flag) [used only when linearizing] +========= ==== ================== ===================================================================================================================================================================== + + + +FAST v8.16 to OpenFAST v1.0.0 +----------------------------- + +The transition from FAST v8 to OpenFAST is described in detail at :ref:`fast_to_openfast`. + +========== ==== =============== ==================================================================================================== +Removed in OpenFAST v1.0.0 +------------------------------------------------------------------------------------------------------------------------------------ +Module Line Flag Name Example Value +========== ==== =============== ==================================================================================================== +OpenFAST 18 CompSub 0 CompSub - Compute sub-structural dynamics (switch) {0=None; 1=SubDyn} +========== ==== =============== ==================================================================================================== + + +========== ==== =============== ==================================================================================================== +Added in OpenFAST v1.0.0 +------------------------------------------------------------------------------------------------------------------------------------ +Module Line Flag Name Example Value +========== ==== =============== ==================================================================================================== +OpenFAST 18 CompSub 0 CompSub - Compute sub-structural dynamics (switch) {0=None; 1=SubDyn; 2=External Platform MCKF} +AeroDyn 12 CavityCheck False CavitCheck - Perform cavitation check? (flag) +AeroDyn 17 Patm 9999.9 Patm - Atmospheric pressure (Pa) [used only when CavitCheck=True] +AeroDyn 18 Pvap 9999.9 Pvap - Vapor pressure of fluid (Pa) [used only when CavitCheck=True] +AeroDyn 19 FluidDepth 9999.9 FluidDepth - Water depth above mid-hub height (m) [used only when CavitCheck=True] +========== ==== =============== ==================================================================================================== diff --git a/OpenFAST/docs/source/user/beamdyn/BDNodalOutputs.rst b/OpenFAST/docs/source/user/beamdyn/BDNodalOutputs.rst new file mode 100644 index 000000000..6a13a4654 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/BDNodalOutputs.rst @@ -0,0 +1,39 @@ + +Nodal Outputs +~~~~~~~~~~~~~ + +In addition to the named outputs in :numref:`BD-Outputs` above, BeamDyn allows +for outputting the full set blade node motions and loads (tower nodes +unavailable at present). Please refer to the BeamDyn_Nodes tab in the +Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` +for a complete list of possible output parameters. + +This section follows the `END` statement from normal Outputs section described +above, and includes a separator description line followed by the following +optinos. + +**BldNd_BlOutNd** specifies which nodes to output. This is currently unused. + +The **OutList** section controls the nodal output quantities generated by +BeamDyn. In this section, the user specifies the name of the channel family to +output. The output name for each channel is then created internally by BeamDyn +by combining the blade number, node number, and channel family name. For +example, if the user specifies **TDxr** as the channel family name, the output +channels will be named with the convention of **B**\ :math:`\mathbf{\beta}`\ +**N###TDxr** where :math:`\mathbf{\beta}` is the blade number, and **###** is the +three digit node number. + + + +Sample Nodal Outputs section +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This sample includes the ``END`` statement from the regular outputs section. + +.. container:: + :name: File:BDNodalOutputs + + .. literalinclude:: examples/NodalOutputs.txt + :linenos: + + diff --git a/OpenFAST/docs/source/user/beamdyn/appendix.rst b/OpenFAST/docs/source/user/beamdyn/appendix.rst new file mode 100644 index 000000000..41f3023cb --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/appendix.rst @@ -0,0 +1,58 @@ +.. _bd_appendix: + +Appendix +======== + +.. _bd_input_files: + +BeamDyn Input Files +------------------- + +In this appendix we describe the BeamDyn input-file structure and provide examples for the NREL 5MW Reference Wind Turbine. + +OpenFAST+BeamDyn and stand-alone BeamDyn (static and dynamic) simulations all require two files: + +1) BeamDyn primary input file +:download:`(NREL 5MW static example) <examples/bd_primary_nrel_5mw.inp>`: This file includes information on the numerical-solution parameters (e.g., numerical damping, quadrature rules), and the geometric definition of the beam reference line via "members" and "key points". This file also specifies the "blade input file." + +2) BeamDyn blade input file :download:`(NREL 5MW example) <examples/nrel_5mw_blade.inp>`: + +Stand-alone BeamDyn simulation also require a driver input file; we list here examples for static and dynamic simulations: + +3a) BeamDyn driver for dynamic simulations :download:`(NREL 5MW example) <examples/bd_driver_dynamic_nrel_5mw.inp>`: This file specifies the inputs for a single blade (e.g., forces, orientations, root velocity) and specifies the BeamDyn primary input file. + +3b) BeamDyn driver for static simulations :download:`(NREL 5MW example) <examples/bd_driver_static_nrel_5mw.inp>`: Same as above but for static analysis. + + +.. _app-output-channel: + +BeamDyn List of Output Channels +------------------------------- + +This is a list of all possible output parameters for the BeamDyn module. +The names are grouped by meaning, but can be ordered in the OUTPUTS +section of the BeamDyn primary input file as the user sees fit. +N\ :math:`\beta`, refers to output node :math:`\beta`, where +:math:`\beta` is a number in the range [1,9], corresponding to entry +:math:`\beta` in the ``OutNd`` list. When coupled to FAST, +“:math:`B\alpha`” is prefixed to each output name, where :math:`\alpha` +is a number in the range [1,3], corresponding to the blade number. The +outputs are expressed in one of the following three coordinate systems: + +- **r**: a floating reference coordinate system fixed to the root of the + moving beam; when coupled to FAST for blades, this is equivalent to + the IEC blade (b) coordinate system. + +- **l**: a floating coordinate system local to the deflected beam. + +- **g**: the global inertial frame coordinate system; when coupled to FAST, + this is equivalent to FAST’s global inertial frame (i) coordinate + system. + +.. _bd-output-channel: + +.. figure:: figs/bd_output_channel.pdf + :width: 500px + :align: center + + BeamDyn Output Channel List diff --git a/OpenFAST/docs/source/user/beamdyn/examples/NodalOutputs.txt b/OpenFAST/docs/source/user/beamdyn/examples/NodalOutputs.txt new file mode 100644 index 000000000..7a260bc69 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/examples/NodalOutputs.txt @@ -0,0 +1,138 @@ +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +---------------------- NODE OUTPUTS -------------------------------------------- + 99 BldNd_BlOutNd - Blade nodes on each blade (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx, BeamDyn_Nodes tab for a listing of available output channels, (-) +"FxL" - Sectional force resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"FyL" - Sectional force resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"FzL" - Sectional force resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"MxL" - Sectional moment resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"MyL" - Sectional moment resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"MzL" - Sectional moment resultants at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"Fxr" - Sectional force resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"Fyr" - Sectional force resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"Fzr" - Sectional force resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"Mxr" - Sectional moment resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"Myr" - Sectional moment resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"Mzr" - Sectional moment resultants at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"TDxr" - Sectional translational deflection (relative to the undeflected position) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"TDyr" - Sectional translational deflection (relative to the undeflected position) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"TDzr" - Sectional translational deflection (relative to the undeflected position) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"RDxr" - Sectional angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (-) +"RDyr" - Sectional angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (-) +"RDzr" - Sectional angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (-) +"AbsXg" - Node position in X (global coordinate) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m) +"AbsYg" - Node position in Y (global coordinate) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m) +"AbsZg" - Node position in Z (global coordinate) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m) +"AbsXr" - Node position in X (relative to root) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"AbsYr" - Node position in Y (relative to root) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"AbsZr" - Node position in Z (relative to root) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m) +"TVxg" - Sectional translational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m/s) +"TVyg" - Sectional translational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m/s) +"TVzg" - Sectional translational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (m/s) +"TVxl" - Sectional translational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s) +"TVyl" - Sectional translational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s) +"TVzl" - Sectional translational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s) +"TVxr" - Sectional translational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s) +"TVyr" - Sectional translational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s) +"TVzr" - Sectional translational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s) +"RVxg" - Sectional angular/rotational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (deg/s) +"RVyg" - Sectional angular/rotational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (deg/s) +"RVzg" - Sectional angular/rotational velocities (absolute) g: the global inertial frame coordinate system; when coupled to FAST, this is equivalent to FAST’s global inertial frame (i) coordinate system (deg/s) +"RVxl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s) +"RVyl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s) +"RVzl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s) +"RVxr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s) +"RVyr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s) +"RVzr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s) +"TAxl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s^2) +"TAyl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s^2) +"TAzl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (m/s^2) +"TAxr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s^2) +"TAyr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s^2) +"TAzr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (m/s^2) +"RAxl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s^2) +"RAyl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s^2) +"RAzl" - Sectional angular/rotational velocities (absolute) l: a floating coordinate system local to the deflected beam (deg/s^2) +"RAxr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s^2) +"RAyr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s^2) +"RAzr" - Sectional angular/rotational velocities (absolute) r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (deg/s^2) +"PFxL" - Applied point forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"PFyL" - Applied point forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"PFzL" - Applied point forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N) +"PMxL" - Applied point moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"PMyL" - Applied point moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"PMzL" - Applied point moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m) +"DFxL" - Applied distributed forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N/m) +"DFyL" - Applied distributed forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N/m) +"DFzL" - Applied distributed forces at each node expressed in l l: a floating coordinate system local to the deflected beam (N/m) +"DMxL" - Applied distributed moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m/m) +"DMyL" - Applied distributed moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m/m) +"DMzL" - Applied distributed moments at each node expressed in l l: a floating coordinate system local to the deflected beam (N-m/m) +"DFxR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N/m) +"DFyR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N/m) +"DFzR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N/m) +"DMxR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m/m) +"DMyR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m/m) +"DMzR" - Applied distributed forces at each node expressed in r r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m/m) +"FFbxl" - Gyroscopic force x l: a floating coordinate system local to the deflected beam (N) +"FFbyl" - Gyroscopic force y l: a floating coordinate system local to the deflected beam (N) +"FFbzl" - Gyroscopic force z l: a floating coordinate system local to the deflected beam (N) +"FFbxr" - Gyroscopic force x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFbyr" - Gyroscopic force y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFbzr" - Gyroscopic force z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"MFbxl" - Gyroscopic moment about x l: a floating coordinate system local to the deflected beam (N-m) +"MFbyl" - Gyroscopic moment about y l: a floating coordinate system local to the deflected beam (N-m) +"MFbzl" - Gyroscopic moment about z l: a floating coordinate system local to the deflected beam (N-m) +"MFbxr" - Gyroscopic moment about x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFbyr" - Gyroscopic moment about y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFbzr" - Gyroscopic moment about z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"FFcxl" - Elastic restoring force Fc x l: a floating coordinate system local to the deflected beam (N) +"FFcyl" - Elastic restoring force Fc y l: a floating coordinate system local to the deflected beam (N) +"FFczl" - Elastic restoring force Fc z l: a floating coordinate system local to the deflected beam (N) +"FFcxr" - Elastic restoring force Fc x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFcyr" - Elastic restoring force Fc y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFczr" - Elastic restoring force Fc z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"MFcxl" - Elastic restoring moment Fc about x l: a floating coordinate system local to the deflected beam (N-m) +"MFcyl" - Elastic restoring moment Fc about y l: a floating coordinate system local to the deflected beam (N-m) +"MFczl" - Elastic restoring moment Fc about z l: a floating coordinate system local to the deflected beam (N-m) +"MFcxr" - Elastic restoring moment Fc about x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFcyr" - Elastic restoring moment Fc about y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFczr" - Elastic restoring moment Fc about z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"FFdxl" - Elastic restoring force Fd x l: a floating coordinate system local to the deflected beam (N) +"FFdyl" - Elastic restoring force Fd y l: a floating coordinate system local to the deflected beam (N) +"FFdzl" - Elastic restoring force Fd z l: a floating coordinate system local to the deflected beam (N) +"FFdxr" - Elastic restoring force Fd x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFdyr" - Elastic restoring force Fd y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFdzr" - Elastic restoring force Fd z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"MFdxl" - Elastic restoring moment Fd about x l: a floating coordinate system local to the deflected beam (N-m) +"MFdyl" - Elastic restoring moment Fd about y l: a floating coordinate system local to the deflected beam (N-m) +"MFdzl" - Elastic restoring moment Fd about z l: a floating coordinate system local to the deflected beam (N-m) +"MFdxr" - Elastic restoring moment Fd about x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFdyr" - Elastic restoring moment Fd about y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFdzr" - Elastic restoring moment Fd about z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"FFgxl" - Gravity force x l: a floating coordinate system local to the deflected beam (N) +"FFgyl" - Gravity force y l: a floating coordinate system local to the deflected beam (N) +"FFgzl" - Gravity force z l: a floating coordinate system local to the deflected beam (N) +"FFgxr" - Gravity force x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFgyr" - Gravity force y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFgzr" - Gravity force z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"MFgxl" - Gravity moment about x l: a floating coordinate system local to the deflected beam (N-m) +"MFgyl" - Gravity moment about y l: a floating coordinate system local to the deflected beam (N-m) +"MFgzl" - Gravity moment about z l: a floating coordinate system local to the deflected beam (N-m) +"MFgxr" - Gravity moment about x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFgyr" - Gravity moment about y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFgzr" - Gravity moment about z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"FFixl" - Inertial force x l: a floating coordinate system local to the deflected beam (N) +"FFiyl" - Inertial force y l: a floating coordinate system local to the deflected beam (N) +"FFizl" - Inertial force z l: a floating coordinate system local to the deflected beam (N) +"FFixr" - Inertial force x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFiyr" - Inertial force y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"FFizr" - Inertial force z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N) +"MFixl" - Inertial moment about x l: a floating coordinate system local to the deflected beam (N-m) +"MFiyl" - Inertial moment about y l: a floating coordinate system local to the deflected beam (N-m) +"MFizl" - Inertial moment about z l: a floating coordinate system local to the deflected beam (N-m) +"MFixr" - Inertial moment about x r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFiyr" - Inertial moment about y r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +"MFizr" - Inertial moment about z r: a floating reference coordinate system fixed to the root of the moving beam; when coupled to FAST for blades, this is equivalent to the IEC blade (b) coordinate system (N-m) +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_dynamic_nrel_5mw.inp b/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_dynamic_nrel_5mw.inp new file mode 100644 index 000000000..4ce490dc6 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_dynamic_nrel_5mw.inp @@ -0,0 +1,44 @@ +------- BEAMDYN Driver with OpenFAST INPUT FILE -------------------------------- +Dynamic analysis of rotating NREL 5MW blade under gravity force +---------------------- SIMULATION CONTROL -------------------------------------- +True DynamicSolve - Dynamic solve (false for static solve) (-) + 0 t_initial - Starting time of simulation (s) [used only when DynamicSolve=TRUE] + 30 t_final - Ending time of simulation (s) [used only when DynamicSolve=TRUE] + 0.002 dt - Time increment size (s) [used only when DynamicSolve=TRUE] +---------------------- GRAVITY PARAMETER -------------------------------------- + 0 Gx - Component of gravity vector along X direction (m/s^2) + -9.8 Gy - Component of gravity vector along Y direction (m/s^2) + 0 Gz - Component of gravity vector along Z direction (m/s^2) +---------------------- FRAME PARAMETER -------------------------------------- + 0 GlbPos(1) - Component of position vector of the reference blade frame along X direction (m) + 0 GlbPos(2) - Component of position vector of the reference blade frame along Y direction (m) + 1 GlbPos(3) - Component of position vector of the reference blade frame along Z direction (m) +---The following 3 by 3 matrix is the direction cosine matirx ,GlbDCM(3,3), +---relates global frame to the initial blade root frame +1.0000000E+00 0.0000000E+00 0.0000000E+00 +0.0000000E+00 1.0000000E+00 0.0000000E+00 +0.0000000E+00 0.0000000E+00 1.0000000E+00 +True GlbRotBladeT0 - Reference orientation for BeamDyn calculations is aligned with initial blade root? +---------------------- ROOT VELOCITY PARAMETER ---------------------------------- + 1.0006 RootVel(4) - Component of angular velocity vector of the beam root about X axis (rad/s) + 0 RootVel(5) - Component of angular velocity vector of the beam root about Y axis (rad/s) + 0 RootVel(6) - Component of angular velocity vector of the beam root about Z axis (rad/s) +---------------------- APPLIED FORCE ---------------------------------- + 0 DistrLoad(1) - Component of distributed force vector along X direction (N/m) + 0 DistrLoad(2) - Component of distributed force vector along Y direction (N/m) + 0 DistrLoad(3) - Component of distributed force vector along Z direction (N/m) + 0 DistrLoad(4) - Component of distributed moment vector along X direction (N-m/m) + 0 DistrLoad(5) - Component of distributed moment vector along Y direction (N-m/m) + 0 DistrLoad(6) - Component of distributed moment vector along Z direction (N-m/m) + 0 TipLoad(1) - Component of concentrated force vector at blade tip along X direction (N) + 0 TipLoad(2) - Component of concentrated force vector at blade tip along Y direction (N) + 0 TipLoad(3) - Component of concentrated force vector at blade tip along Z direction (N) + 0 TipLoad(4) - Component of concentrated moment vector at blade tip along X direction (N-m) + 0 TipLoad(5) - Component of concentrated moment vector at blade tip along Y direction (N-m) + 0 TipLoad(6) - Component of concentrated moment vector at blade tip along Z direction (N-m) + 0 NumPointLoads - Number of point loads along blade +Non-dim blade-span eta Fx Fy Fz Mx My Mz +(-) (N) (N) (N) (N-m) (N-m) (N-m) +---------------------- PRIMARY INPUT FILE -------------------------------------- +"bd_primary_nrel_5mw.inp" InputFile - Name of the primary BeamDyn input file + diff --git a/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_static_nrel_5mw.inp b/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_static_nrel_5mw.inp new file mode 100644 index 000000000..3986048ac --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/examples/bd_driver_static_nrel_5mw.inp @@ -0,0 +1,44 @@ +------- BEAMDYN Driver with OpenFAST INPUT FILE -------------------------------- +Static analysis of NREL 5MW blade under distributed force +---------------------- SIMULATION CONTROL -------------------------------------- +False DynamicSolve - Dynamic solve (false for static solve) (-) + 0 t_initial - Starting time of simulation (s) [used only when DynamicSolve=TRUE] + 30 t_final - Ending time of simulation (s) [used only when DynamicSolve=TRUE] + 0.002 dt - Time increment size (s) [used only when DynamicSolve=TRUE] +---------------------- GRAVITY PARAMETER -------------------------------------- + 0 Gx - Component of gravity vector along X direction (m/s^2) + 0 Gy - Component of gravity vector along Y direction (m/s^2) + 0 Gz - Component of gravity vector along Z direction (m/s^2) +---------------------- FRAME PARAMETER -------------------------------------- + 0 GlbPos(1) - Component of position vector of the reference blade frame along X direction (m) + 0 GlbPos(2) - Component of position vector of the reference blade frame along Y direction (m) + 1 GlbPos(3) - Component of position vector of the reference blade frame along Z direction (m) +---The following 3 by 3 matrix is the direction cosine matirx ,GlbDCM(3,3), +---relates global frame to the initial blade root frame +1.0000000E+00 0.0000000E+00 0.0000000E+00 +0.0000000E+00 1.0000000E+00 0.0000000E+00 +0.0000000E+00 0.0000000E+00 1.0000000E+00 +True GlbRotBladeT0 - Reference orientation for BeamDyn calculations is aligned with initial blade root? +---------------------- ROOT VELOCITY PARAMETER ---------------------------------- + 0 RootVel(4) - Component of angular velocity vector of the beam root about X axis (rad/s) + 0 RootVel(5) - Component of angular velocity vector of the beam root about Y axis (rad/s) + 0 RootVel(6) - Component of angular velocity vector of the beam root about Z axis (rad/s) +---------------------- APPLIED FORCE ---------------------------------- + 10000 DistrLoad(1) - Component of distributed force vector along X direction (N/m) + 0 DistrLoad(2) - Component of distributed force vector along Y direction (N/m) + 0 DistrLoad(3) - Component of distributed force vector along Z direction (N/m) + 0 DistrLoad(4) - Component of distributed moment vector along X direction (N-m/m) + 0 DistrLoad(5) - Component of distributed moment vector along Y direction (N-m/m) + 0 DistrLoad(6) - Component of distributed moment vector along Z direction (N-m/m) + 0 TipLoad(1) - Component of concentrated force vector at blade tip along X direction (N) + 0 TipLoad(2) - Component of concentrated force vector at blade tip along Y direction (N) + 0 TipLoad(3) - Component of concentrated force vector at blade tip along Z direction (N) + 0 TipLoad(4) - Component of concentrated moment vector at blade tip along X direction (N-m) + 0 TipLoad(5) - Component of concentrated moment vector at blade tip along Y direction (N-m) + 0 TipLoad(6) - Component of concentrated moment vector at blade tip along Z direction (N-m) + 0 NumPointLoads - Number of point loads along blade +Non-dim blade-span eta Fx Fy Fz Mx My Mz +(-) (N) (N) (N) (N-m) (N-m) (N-m) +---------------------- PRIMARY INPUT FILE -------------------------------------- +"bd_primary_nrel_5mw.inp" InputFile - Name of the primary BeamDyn input file + diff --git a/OpenFAST/docs/source/user/beamdyn/examples/bd_primary_nrel_5mw.inp b/OpenFAST/docs/source/user/beamdyn/examples/bd_primary_nrel_5mw.inp new file mode 100644 index 000000000..1fcd7475e --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/examples/bd_primary_nrel_5mw.inp @@ -0,0 +1,108 @@ +--------- BEAMDYN with OpenFAST INPUT FILE ------------------------------------------- +NREL 5MW blade primary input file +---------------------- SIMULATION CONTROL -------------------------------------- +TRUE Echo - Echo input data to "<RootName>.ech"? (flag) +False QuasiStaticInit - Use quasi-static pre-conditioning with centripetal accelerations in initialization? (flag) [dynamic solve only] + 0 rhoinf - Numerical damping parameter for generalized-alpha integrator + 2 quadrature - Quadrature method: 1=Gaussian; 2=Trapezoidal (switch) +"DEFAULT" refine - Refinement factor for trapezoidal quadrature (-) [DEFAULT = 1; used only when quadrature=2] +"DEFAULT" n_fact - Factorization frequency for the Jacobian in N-R iteration(-) [DEFAULT = 5] +"DEFAULT" DTBeam - Time step size (s) +"DEFAULT" load_retries - Number of factored load retries before quitting the simulation [DEFAULT = 20] +"DEFAULT" NRMax - Max number of iterations in Newton-Raphson algorithm (-) [DEFAULT = 10] +"DEFAULT" stop_tol - Tolerance for stopping criterion (-) [DEFAULT = 1E-5] +FALSE tngt_stf_fd - Use finite differenced tangent stiffness matrix? (flag) +FALSE tngt_stf_comp - Compare analytical finite differenced tangent stiffness matrix? (flag) +"DEFAULT" tngt_stf_pert - Perturbation size for finite differencing (-) [DEFAULT = 1E-6] +"DEFAULT" tngt_stf_difftol - Maximum allowable relative difference between analytical and fd tangent stiffness (-); [DEFAULT = 0.1] +True RotStates - Orient states in the rotating frame during linearization? (flag) [used only when linearizing] +---------------------- GEOMETRY PARAMETER -------------------------------------- + 1 member_total - Total number of members (-) + 49 kp_total - Total number of key points (-) [must be at least 3] + 1 49 - Member number; Number of key points in this member + kp_xr kp_yr kp_zr initial_twist + (m) (m) (m) (deg) +0.0000000E+00 0.0000000E+00 0.0000000E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 1.9987500E-01 1.3308000E+01 +0.0000000E+00 0.0000000E+00 1.1998650E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 2.1998550E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 3.1998450E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 4.1998350E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 5.1998250E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 6.1998150E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 7.1998050E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 8.2010250E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 9.1997850E+00 1.3308000E+01 +0.0000000E+00 0.0000000E+00 1.0199775E+01 1.3308000E+01 +0.0000000E+00 0.0000000E+00 1.1199765E+01 1.3181000E+01 +0.0000000E+00 0.0000000E+00 1.2199755E+01 1.2848000E+01 +0.0000000E+00 0.0000000E+00 1.3200975E+01 1.2192000E+01 +0.0000000E+00 0.0000000E+00 1.4199735E+01 1.1561000E+01 +0.0000000E+00 0.0000000E+00 1.5199725E+01 1.1072000E+01 +0.0000000E+00 0.0000000E+00 1.6199715E+01 1.0792000E+01 +0.0000000E+00 0.0000000E+00 1.8200925E+01 1.0232000E+01 +0.0000000E+00 0.0000000E+00 2.0200290E+01 9.6720000E+00 +0.0000000E+00 0.0000000E+00 2.2200270E+01 9.1100000E+00 +0.0000000E+00 0.0000000E+00 2.4200250E+01 8.5340000E+00 +0.0000000E+00 0.0000000E+00 2.6200230E+01 7.9320000E+00 +0.0000000E+00 0.0000000E+00 2.8200825E+01 7.3210000E+00 +0.0000000E+00 0.0000000E+00 3.0200190E+01 6.7110000E+00 +0.0000000E+00 0.0000000E+00 3.2200170E+01 6.1220000E+00 +0.0000000E+00 0.0000000E+00 3.4200150E+01 5.5460000E+00 +0.0000000E+00 0.0000000E+00 3.6200130E+01 4.9710000E+00 +0.0000000E+00 0.0000000E+00 3.8200725E+01 4.4010000E+00 +0.0000000E+00 0.0000000E+00 4.0200090E+01 3.8340000E+00 +0.0000000E+00 0.0000000E+00 4.2200070E+01 3.3320000E+00 +0.0000000E+00 0.0000000E+00 4.4200050E+01 2.8900000E+00 +0.0000000E+00 0.0000000E+00 4.6200030E+01 2.5030000E+00 +0.0000000E+00 0.0000000E+00 4.8201240E+01 2.1160000E+00 +0.0000000E+00 0.0000000E+00 5.0199990E+01 1.7300000E+00 +0.0000000E+00 0.0000000E+00 5.2199970E+01 1.3420000E+00 +0.0000000E+00 0.0000000E+00 5.4199950E+01 9.5400000E-01 +0.0000000E+00 0.0000000E+00 5.5199940E+01 7.6000000E-01 +0.0000000E+00 0.0000000E+00 5.6199930E+01 5.7400000E-01 +0.0000000E+00 0.0000000E+00 5.7199920E+01 4.0400000E-01 +0.0000000E+00 0.0000000E+00 5.7699915E+01 3.1900000E-01 +0.0000000E+00 0.0000000E+00 5.8201140E+01 2.5300000E-01 +0.0000000E+00 0.0000000E+00 5.8699905E+01 2.1600000E-01 +0.0000000E+00 0.0000000E+00 5.9199900E+01 1.7800000E-01 +0.0000000E+00 0.0000000E+00 5.9699895E+01 1.4000000E-01 +0.0000000E+00 0.0000000E+00 6.0199890E+01 1.0100000E-01 +0.0000000E+00 0.0000000E+00 6.0699885E+01 6.2000000E-02 +0.0000000E+00 0.0000000E+00 6.1199880E+01 2.3000000E-02 +0.0000000E+00 0.0000000E+00 6.1500000E+01 0.0000000E+00 +---------------------- MESH PARAMETER ------------------------------------------ + 5 order_elem - Order of interpolation (basis) function (-) +---------------------- MATERIAL PARAMETER -------------------------------------- +"nrel_5mw_blade.inp" BldFile - Name of file containing properties for blade (quoted string) +---------------------- PITCH ACTUATOR PARAMETERS ------------------------------- +False UsePitchAct - Whether a pitch actuator should be used (flag) + 200 PitchJ - Pitch actuator inertia (kg-m^2) [used only when UsePitchAct is true] + 2E+07 PitchK - Pitch actuator stiffness (kg-m^2/s^2) [used only when UsePitchAct is true] + 500000 PitchC - Pitch actuator damping (kg-m^2/s) [used only when UsePitchAct is true] +---------------------- OUTPUTS ------------------------------------------------- +True SumPrint - Print summary data to "<RootName>.sum" (flag) +"ES10.3E2" OutFmt - Format used for text tabular output, excluding the time channel. + 2 NNodeOuts - Number of nodes to output to file [0 - 9] (-) + 1, 3 OutNd - Nodes whose values will be output (-) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"RootFxr, RootFyr, RootFzr" +"RootMxr, RootMyr, RootMzr" +"N1Fxl,N1Fyl,N1Fzl" +"N1Mxl,N1Myl,N1Mzl" +"TipTDxr, TipTDyr, TipTDzr" +"TipRDxr, TipRDyr, TipRDzr" +END of input file (the word "END" must appear in the first 3 columns of the last OutList line) +====== Outputs for all blade stations (same ending as above for B1N1.... =========================== (optional section) + "All" BldNd_BlOutNd - Future feature will allow selecting a portion of the nodes to output. Not implemented yet. (-) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"TDxr, TDyr, TDzr" +"TVxr, TVyr, TVzr" +"TAxr, TAyr, TAzr" +"RDxr, RDyr, RDzr" +"RVxr, RVyr, RVzr" +"RAxr, RAyr, RAzr" +"Fxr, Fyr, Fzr" +"TipTDxr, TipTDyr, TipTDzr" +"TipRDxr, TipRDyr, TipRDzr" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) diff --git a/OpenFAST/docs/source/user/beamdyn/examples/nrel_5mw_blade.inp b/OpenFAST/docs/source/user/beamdyn/examples/nrel_5mw_blade.inp new file mode 100644 index 000000000..24e2192f2 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/examples/nrel_5mw_blade.inp @@ -0,0 +1,744 @@ + ------- BEAMDYN V1.00.* INDIVIDUAL BLADE INPUT FILE -------------------------- + NREL 5MW Blade + ---------------------- BLADE PARAMETERS -------------------------------------- +49 station_total - Number of blade input stations (-) + 1 damp_flag - Damping flag: 0: no damping; 1: damped + ---------------------- DAMPING COEFFICIENT------------------------------------ + mu1 mu2 mu3 mu4 mu5 mu6 + (-) (-) (-) (-) (-) (-) +1.0E-03 1.0E-03 1.0E-03 0.0014 0.0022 0.0022 + ---------------------- DISTRIBUTED PROPERTIES--------------------------------- + 0.000000 + 9.729480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.729480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.729480E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.811360E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.811000E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.564400E+09 + + 6.789350E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.789350E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.789350E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.730400E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.728600E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.945900E+03 + + 0.003250 + 9.729480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.729480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.729480E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.811360E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.811000E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.564400E+09 + + 6.789350E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.789350E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.789350E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.730400E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.728600E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.945900E+03 + + 0.019510 + 1.078950E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.078950E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.078950E+10 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.955860E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.942490E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.431590E+09 + + 7.733630E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.733630E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.733630E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.066380E+03 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.091520E+03 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.157900E+03 + + 0.035770 + 1.006723E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.006723E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.006723E+10 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.949780E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.745590E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.993980E+09 + + 7.405500E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.405500E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.405500E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.047360E+03 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.660900E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.013450E+03 + + 0.052030 + 9.867780E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.867780E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.867780E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.978880E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.528740E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.666590E+09 + + 7.400420E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.400420E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.400420E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.099750E+03 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.738100E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.973560E+03 + + 0.068290 + 7.607860E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.607860E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.607860E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.485850E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.078240E+10 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.474710E+09 + + 5.924960E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.924960E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.924960E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 8.730200E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.485500E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.521570E+03 + + 0.084550 + 5.491260E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.491260E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.491260E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.022060E+10 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.229720E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.323540E+09 + + 4.502750E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.502750E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.502750E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.414900E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.567600E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.098250E+03 + + 0.100810 + 4.971300E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.971300E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.971300E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 9.144700E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.309540E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.907870E+09 + + 4.240540E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.240540E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.240540E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.937300E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.005300E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.942600E+02 + + 0.117070 + 4.493950E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.493950E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.493950E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 8.063160E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.528360E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.570360E+09 + + 4.006380E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.006380E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.006380E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.471800E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.516100E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.987900E+02 + + 0.133350 + 4.034800E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.034800E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.034800E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 6.884440E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.980060E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.158260E+09 + + 3.820620E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.820620E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.820620E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.908400E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.161200E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.069600E+02 + + 0.149590 + 4.037290E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.037290E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.037290E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.009180E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.936840E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.002120E+09 + + 3.996550E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.996550E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.996550E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.038600E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.036000E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.074600E+02 + + 0.165850 + 4.169720E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.169720E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.169720E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.167680E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.691660E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.559000E+08 + + 4.263210E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.263210E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.263210E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.447000E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.892400E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.339400E+02 + + 0.182110 + 4.082350E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.082350E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.082350E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.271660E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.949460E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.722700E+08 + + 4.168200E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.168200E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.168200E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.699000E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.465700E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.164700E+02 + + 0.198370 + 4.085970E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.085970E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.085970E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.081700E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.386520E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.474900E+08 + + 4.061860E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.061860E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.061860E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.012800E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.159100E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.171900E+02 + + 0.214650 + 3.668340E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.668340E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.668340E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 6.244530E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.933740E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.488400E+08 + + 3.814200E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.814200E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.814200E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.465600E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.871100E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.336700E+02 + + 0.230890 + 3.147760E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.147760E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.147760E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 5.048960E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.568960E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.359200E+08 + + 3.528220E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.528220E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.528220E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.687100E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.608400E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.295500E+02 + + 0.247150 + 3.011580E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.011580E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.011580E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 4.948490E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.388650E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.113500E+08 + + 3.494770E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.494770E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.494770E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.537600E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.485600E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.023200E+02 + + 0.263410 + 2.882620E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.882620E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.882620E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 4.808020E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.271990E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.919400E+08 + + 3.465380E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.465380E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.465380E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.362200E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.403000E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.765200E+02 + + 0.295950 + 2.613970E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.613970E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.613970E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 4.501400E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.050050E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.610000E+08 + + 3.393330E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.393330E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.393330E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.981800E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.246100E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.227900E+02 + + 0.328460 + 2.357480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.357480E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.357480E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 4.244070E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.828250E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.288200E+08 + + 3.300040E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.300040E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.300040E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.620800E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.094200E+02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.715000E+02 + + 0.360980 + 2.146860E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.146860E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.146860E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.995280E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.588710E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.007500E+08 + + 3.219900E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.219900E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.219900E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.350100E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.436000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.293700E+02 + + 0.393500 + 1.944090E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.944090E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.944090E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.750760E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.361930E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.743800E+08 + + 3.138200E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.138200E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.138200E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.085700E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.024000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.888100E+02 + + 0.426020 + 1.632700E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.632700E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.632700E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.447140E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.102380E+09 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.444700E+08 + + 2.947340E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.947340E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.947340E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 2.638700E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.267000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.265400E+02 + + 0.458550 + 1.432400E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.432400E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.432400E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.139070E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.758000E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.199800E+08 + + 2.871200E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.871200E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.871200E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 2.370600E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.942000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.864800E+02 + + 0.491060 + 1.168760E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.168760E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.168760E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 2.734240E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.813000E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.119000E+07 + + 2.633430E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.633430E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.633430E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.964100E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.734000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.337500E+02 + + 0.523580 + 1.047430E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.047430E+08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.047430E+09 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 2.554870E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.347200E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.909000E+07 + + 2.532070E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.532070E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.532070E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.803400E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.914000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.094800E+02 + + 0.556100 + 9.229500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.229500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.229500E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 2.334030E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.089000E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.745000E+07 + + 2.416660E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.416660E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.416660E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.624300E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.216000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.845900E+02 + + 0.588620 + 7.608200E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.608200E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.608200E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.828730E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.145400E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.592000E+07 + + 2.206380E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.206380E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.206380E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.348300E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.733000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.521600E+02 + + 0.621150 + 6.480300E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.480300E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.480300E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.584100E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.386300E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.598000E+07 + + 2.002930E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.002930E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.002930E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.163000E+02 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.330000E+01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.296000E+02 + + 0.653660 + 5.397000E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.397000E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.397000E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.323360E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.758800E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.744000E+07 + + 1.794040E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.794040E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.794040E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.798000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.960000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.079400E+02 + + 0.686180 + 5.311500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.311500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.311500E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.183680E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.260100E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.090000E+07 + + 1.650940E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.650940E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.650940E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.893000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.300000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.062300E+02 + + 0.718700 + 4.600100E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.600100E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.600100E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.020160E+09 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.072600E+08 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.854000E+07 + + 1.544110E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.544110E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.544110E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 8.578000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.220000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.200000E+01 + + 0.751220 + 3.757500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.757500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.757500E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.978100E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.088000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.628000E+07 + + 1.389350E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.389350E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.389350E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.996000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.190000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.515000E+01 + + 0.783760 + 3.288900E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.288900E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.288900E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 7.096100E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.631000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.453000E+07 + + 1.295550E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.295550E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.295550E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.141000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.360000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.577000E+01 + + 0.816260 + 2.440400E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.440400E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.440400E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 5.181900E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.105000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.070000E+06 + + 1.072640E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.072640E+02 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.072640E+02 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.544000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.360000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.880000E+01 + + 0.848780 + 2.116000E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.116000E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.116000E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 4.548700E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.948000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.060000E+06 + + 9.877600E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.877600E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.877600E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.957000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.750000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.232000E+01 + + 0.881300 + 1.815200E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.815200E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.815200E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.951200E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.936000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.080000E+06 + + 9.024800E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.024800E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.024800E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.409000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.210000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.630000E+01 + + 0.897560 + 1.602500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.602500E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.602500E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.537200E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.467000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 6.090000E+06 + + 8.300100E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 8.300100E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 8.300100E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 3.012000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.930000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.205000E+01 + + 0.913820 + 1.092300E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.092300E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.092300E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 3.047300E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.041000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.750000E+06 + + 7.290600E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 7.290600E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 7.290600E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 2.015000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.690000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.184000E+01 + + 0.930080 + 1.000800E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.000800E+07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.000800E+08 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 2.814200E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.652000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.330000E+06 + + 6.877200E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.877200E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.877200E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.853000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.490000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.002000E+01 + + 0.938210 + 9.224000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 9.224000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 9.224000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 2.617100E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.384000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.940000E+06 + + 6.626400E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.626400E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.626400E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.711000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.340000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.845000E+01 + + 0.946360 + 6.323000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 6.323000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 6.323000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.588100E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.963000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.240000E+06 + + 5.934000E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.934000E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.934000E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 1.155000E+01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.100000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.265000E+01 + + 0.954470 + 5.332000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.332000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.332000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.378800E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.600000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.660000E+06 + + 5.591400E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.591400E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.591400E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.770000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.900000E-01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.066000E+01 + + 0.962600 + 4.453000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.453000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.453000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.187900E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.283000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 3.130000E+06 + + 5.248400E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 5.248400E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 5.248400E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 8.190000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.100000E-01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 8.900000E+00 + + 0.970730 + 3.690000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.690000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.690000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 1.016300E+08 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.008000E+07 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.640000E+06 + + 4.911400E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.911400E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.911400E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.820000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.600000E-01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.380000E+00 + + 0.978860 + 2.992000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.992000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.992000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 8.507000E+07 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.550000E+06 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.170000E+06 + + 4.581800E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.581800E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.581800E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 5.570000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.200000E-01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 5.990000E+00 + + 0.986990 + 2.131000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 2.131000E+06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 2.131000E+07 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 6.426000E+07 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.600000E+06 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.580000E+06 + + 4.166900E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.166900E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.166900E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 4.010000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.500000E-01 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.260000E+00 + + 0.995120 + 4.850000E+05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 4.850000E+05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 4.850000E+06 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 6.610000E+06 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.500000E+05 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.500000E+05 + + 1.145300E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.145300E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.145300E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 9.400000E-01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 4.000000E-02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 9.800000E-01 + + 1.000000 + 3.530000E+05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 3.530000E+05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 3.530000E+06 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 5.010000E+06 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.700000E+05 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.900000E+05 + + 1.031900E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 1.031900E+01 0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 1.031900E+01 0.000000E+00 0.000000E+00 0.000000E+00 + 0.000000E+00 -0.000000E+00 0.000000E+00 6.800000E-01 0.000000E+00 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 2.000000E-02 0.000000E+00 + 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 7.000000E-01 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/bd_frame.pdf b/OpenFAST/docs/source/user/beamdyn/figs/bd_frame.pdf new file mode 100644 index 0000000000000000000000000000000000000000..17bbb3b24558803a0d37cbcfc4fadda112642f11 GIT binary patch literal 86325 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 B{g(g$ literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.docx b/OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.docx new file mode 100644 index 0000000000000000000000000000000000000000..00d7296a71c1dcaeea58dff61722bd56506fa700 GIT binary patch literal 100545 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 axiv*O44~ZskFp0|;Xret@&_6O=zjpYkM`LB literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.pdf b/OpenFAST/docs/source/user/beamdyn/figs/bd_output_channel.pdf new file mode 100644 index 0000000000000000000000000000000000000000..05e9611e97c0d4e302e2901e2ca77c0b4195650c GIT binary patch literal 34948 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%0A_Hwq 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 J2}ucq{~zi4-!K3G literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/blade_geometry.jpg b/OpenFAST/docs/source/user/beamdyn/figs/blade_geometry.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61eb72e3d82fe2aa9a8b9604f21168a7405b4206 GIT binary patch literal 59406 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 O#!LI}?0~?(7XB9tLvmIC literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/flow_chart.jpg b/OpenFAST/docs/source/user/beamdyn/figs/flow_chart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa4c5eadad3fb5cc7364ae34265a67f9290181fd GIT binary patch literal 66044 zcmeEu2SAfcv*<@xQ4j=C6oR6HqGF+`Kt!a8fS`0CDjlRq@1G5k8UX<XB}x$lF-lch zPy|GpbOGrd1QKdO+S{nda?bhh{oj4}{r8m{O<eceot>GTotd4T{pg?Q{m}YTsv4>g z6B84p4*o#&L5^1%%F3uSdOE5ar&YiM2;#`N=;CsjSp<R{o!njZ)J}*P8Jmc3bVAI~ zW{49Kgg7r+xVb2uIdd8UA4XfozrTN$+93c5f?D?d{qx^j|LK36mR4>S5X7_!)H_?c zSvZ2SHw3X=ws3KEhamQ0P%r1@?gGjjTS1x66(9)82N-3WZ{?GW@}+NOqpxkw=_!LY z3|zS^Y%f}ZvOg&Az4S}H%`fF|IDi%aj+&K|m8+eF2!j`AT%E1$E?a$l@a^Z{dHhSu zf2-(t*#pr0^&<>^*Sa~J)dc^FGibMURoDAoeq?b`<t!-g0QK)(+)ps-cY*R34+niE zP~HPU%)HjFs`}sBGt2who-+jHjiBDr&Ryf&_j+HaOWHc14Ei!BJ2-1H;4s>}w{TMi zyo9!ca<8qG24ju^J}i)>)kzgl-V4gYwjS!=;j^4_^E}I_{|d*~R#_XA0UQ=r`-`W} zfU+Pc-*$D@V~hoGW=XcXti~7%z-Os)aX<4N2bOWC%i4^w0KKeSR&HNu1Ta~~-EGeS zIc4-^m2r1H_q{KxiM5@o#`pIAE|<T`BEXF`)zw3ffg6C&`thQxiW(>bIIMG4PWlYK zfil}B%Zn!&yxkAVijV=*MaT+rhAx3$3&;tgLL!hJqz0V;|GGe~;E6S42VDj=R^X`> zsIg;O2RVSczi)TuYnyL<ezvgr+IyVQ8;tVzZN7~#@x6^Rs{rc(*2Ca?jP*3D0;?SB z5lDm;$$Fesk@X~~J;HkI2L@+;!BYgXfhGW^-{4$<Jiy2dJPe={cLY7efAkT#?uxRr zXhh=yHb1F!{`nlh`9U$j+4)xvKyH8oe^9sYS3Xtymu&j+M5K-N)%ljS)&7vqzsFy; zVYYF$Ht^fY_W5Ujwr;l1;7=!{1ZLp!SBxA1R(4-!!tF=9eZSH02DEgCE`r|y(9Rj) z`Uj@J&8W509l@VZ7@V*Q)?U(vuJ8R>d!XaM^ntbmj}N3CnEGvupAdiJ5=#tAK1(Uf zYnCFGI!J`2oaGG*j-`qP%ToLU=HJi#Hz+^m{wuwVItI0jS@>hTUwLf>UFJH$wS`NR z>m(O~YbV#~AFV{V1h@`zsdI^eCtH5Z+vT6nf1||?G6uZ*gR6f(7Gnk2LHYm_JID*P zbp>2yaM%g*0Z@NkC*Lt;6=pris_`eOm1D^AA6T%fu%BdCf<)N&upePR$bO1Z{$u5_ zi-BiHz^}>=?7yv?A1!{P!0MM)fGa=X?E5Np3|VFL_5^re26$V!TX_T90YS>nE<Uby zHn#2}hYlQ&6;T4F%t}PV$zuOrk&Blvi+p|LCgN)4X65Q>Ww{?>*g-}=2%6XXYTuYP zHvX)0*McC08KAR1{;V_cfS_k?5F{Y=vrZi7M1Bkey^^u;aP|BK4;bEh2y(MNeCX@{ znbw{Fx~Z2=p9lJiBN~FJQFJ;vnNFvs0QjFFsQfa00CHFHwzGyHEiH!DhgLzXOo9*_ zC^3PrBGZ;1WmP6|puidR%n%f82eE!{!_d`?4@18)`h5GB`4RIUEto$&V);=98W{Ks z-H<ZG%=j>U{bgomVPR)w0Ur)FHdgjk9II9_zN^=)<6OOZ?V44qIJr63uHyoq)tu{j zxVd;3Wd;yNchHNSm6e@q^{Um37XNb}dO5_iig^d~Cl;pd5Hk-G3l9_h9fSasumSIe z;oyA#Ffp^RvaxdjoH#*){Phqs6AKG7D+|CEFoG!nJcn3$*m$=cRAS$tdy!-N6~05) zq8_gjJ@N7lzg`o5$Kgw^*H^FED6na>;LcrQ;=A`qNz2H}9XYCeQbkowUE|c*bNU8` zV0tYqt*mWq?d;v$Jv_a<eSB}+47wG3J0vtZ=5B0U{Jr}L$tkI6Ptr4<X6EGP<rfsb zdR_Fk;$3A`_4}F+%`L5M?H!*wy9Ne_hDS!n#wR8TbMp&}OUp#k3WF{th~*nuKPdYX zT|9s;W>!`fRt^STOw3;3%fiFTw(TH0uaYju#VZ@OAG)@R??lw&mv2^!9@fM2Uvh0) zvvG&iz)k{#w6B!?bA(<04^j4mu%C2wL2FrnQ1Y<wKuCzHLF^dBZZP%tYmwR~@vf*h zC|xC4y0$XC?xjzTRJYf`E{*c@Ob^y#Oy&_pb$=^5q{33wM?6S}zBoK34tK-$Svq6^ z4jNi|l;&I-*jceTQ1FSNs$Sa0F5kT3-1+lk{3dc;AzEpHvpKSKXkZ&5p2~;V0{2(b zp_eH%Uc_d&Nr`}^t%b>g<@2TE^8r)6wAwdxsPP^h>X)FPWv624&_n8%K00(WxC&l4 zBkxFuZXjq?F~4+HqeB~v6rD?jol6m&-bm6sg2D#hDSM5g1tLom=@9-7v6dFf9f8AJ z(4kLFbZ9kqI2{^)MC_(R>_}?F1)s7}v}`Z>O9_HPLerRW@8R=U%IvK5GG&M2Av%<N zV+cjrM2D87aNj_2d<WIekvOXc{w|qw)BFKROsHYW=Z16$gPygfLq9q@f9njtRUVRD z5m%I^LvL==p+N_hhUJv{<rK0c2OUxbs9nX*Avz@J&@po7Qt+FHUS|mcUwQ^2bc{<9 zbz2iYr!JpmD!UZ<Ve<>92C^JVSX@JJ?p&s6X;vU+H0V%@dFc}zQ{APMu*~S3QTYB! z((1zCCw*2VHa^|+HtM=6e9-^;*FTu-I%V=am=3Xy5rRe|GWzTcpG;O7j5c_No@1Ze zI&k;;AvwjW*H=EJ-KseEtc`TmbHPw9cdz}MfjxtQxE<%Sdq0eI+%=r5p+lTvgOXJ4 zUIsfx0P_UYD0?xtaSKTA4m!jUkD!<ZdeI@CJ@FJG3{zO<(8O>)<oISF7n&6Gq*Ex( z7&%}`QK3VR$yGR_{42oGaXJ(fLlB?^&kBNOb3=3}EQPjRUy_8U(IFxefOb8Y%7Ub< zhNGxjO{iM2KaYsO=LBx2Lm#PN!iCSn1b6t|sWdP-2q1qDa`3<zI`qhf4qcO+Lq08% zAX)z1cpG)zp;izj4nR(8(X{<&V#qn%SOpm%#6eMAgIHJ#1ac=$ZBbSQ-i!ImcyDWn zVRT4&IReJ}T%kjiKwAG`0Yryxzfq=L!_Zi9?`coQu_H0GzYJ!K<blTn!II+Mk0cf$ z2Y2cLapax_!i6Ag5{Ew?rbFfNBt&ZuKP3nLo5B7%DJL^g^8-|XGz(3XjeCV1Ci2oD z(UrtxT$~Q^Ps9DqgxrqRr1>LpGzflo;V~UL-bja-QN!?A_kT_X5Cq<*aAWW?K%4tt zAOKE8)S%8gB+)oYsBZ|jSsl~mNsd~~y1vOL?9CPu{~5yeyQ%Rnd`SSE{g|-4ojVa( z3UCRS4opVoQjS#7WnS4{OV+kf>H+Fa@#IiwZZ^DYCVil<v#?SyDZ)qQ;nRID)b}T| z`0wmFmov<BXZ4$E{yCVTDH<tv5e%sXE8!*f3DOoxlIG@vJLKrlg1uo4P;G%}<@b*A zzlar5->vBMRPi=3Q0(2gTif>>a?nQCf75b}w9r3P(>E=L14<68rteB_!KZ9-`KN}A zn*XlmeyFNzLqJubX}i8ES32}VHNTmMyZ)@H1Q?pCv3fbz@0%t*PAL4U#!=tx1P8Da z2N-q&XgMjLvIW?xpAL=H!FYa}^2!KIBGQ(e85$A!T_d9DkcH+~)yzQpr)Eyo9VItW z<8J^lJ_xvONaFZoV3;v5!19lgk>AbBA6$IK4Rrc%YF+U)iqzNJc$v5x7`^ipzt)9) zhQR0*r)ws2-bJ6eZ#9={TrhJskLS)OQ8_u`yN1$u>1A4*m(3A66zT#@#$qyV>(Cmh z3G0~f?a?{i+PA43!I`JL#a|yQ#?{>zYH_4K{ZdLfid^u)?weQfHJoMzCeoCJ4(Z_m zqN63~hGlG<w+8%H1))aD9mwsV^%-_7sKzH8ZjWye&c8p#Z6ZG~g;M$8BVUC{P_Ug3 z&bIccXh+NWHhtLot>)E~agxhoO2c5}nNg{d0ks4P*@n$iY7b}C#N7nVZ5vHca=z_0 z55D%@`nWD2pR6!X79$$bp_U`a1&5A&!?Ezb0<rSh&X}eB_(udf6cX4oNDi|JIQ(X1 zPgu4&G4J_?_1ER|F0JA{rOUO7HA$iswn26!bqw~E`=JFW+Ar}sZ?X*n^z@q-wqQ4# z^qfx=%D9*SzaBZI;bI{wYAd$o1u}6Sx%>e)7(d$Bfk(`=(xJCF(Wx$pt3YAC#OKmN zQCE@p$N6+<=q~*B6VVv>6_Vu$;+ZZwMEEdpw1F1dj~uw{zZclv_<nARxFbv)LEsA% zH^NPtcn%t$436S@_1MZk2M?MZf6hYNSpBwfWp^M@qHk}3B@w9$43Ncu4V4cE!2`-b zTUU#-;F4c)6HO7E$ni8Hn6x!pP_!dzlzr$R%z_>Tn2(@!SUR-z5!ZjC_rJ!y_f7sv zkGx|}`OzV+sRUKrrRaM}L)s;ggVHWcdyH2zUA2;%x~|}0eszs_@-N?K**4}MDaTS_ zTkjjj&3O{s2h^4xs!s14{OlI=d3fyu;lo{5r5y(8Q1=u~_vPU13iSmYYJTr90VWl> z1}xt+3KC3zC}a8!-=hk}(3I6+Lf^=j=sy`Zm&V8CXViFE>a|xGUH38Kd=;{dr$!En zsq_J>pAvQu(H}qD$Q?q5hIK;e5Y`QVHYOUY9MOOHHaYj;I8-CmMRP>nc^fK`jW4|B zZ#aZ1gx?-cEqJoG&cP+HX{(Zn-bs7ToEhsq$91ExlxGDU(LVpu(E9F#cIw>=i2-rx zJ5`K|^NL=yIX#oiPR}hXh<*I3FzHbA$;neWhmw?;SBcE6%Fq?oh?Z+gjk>)i^N>-} z)isI7?zCuE*k%dDdHDurdt8Jau2=*(9#(d9ys|k`-BM3K>TZA5*RGih(iiN~t@(6K z3XTeAKMe@U-fL~Ue>Sd)^Zr4hV(m}wtPS4ou3&bpfQI|sPJ}rtRqfZVIsYN~!3RB6 z)v6IWxg%7&ypS~#DC3X$NbbHaQ~QF!E{7~mzi~cwY|)n6akhzjv=2q5b3{E@zs~aP z-ScMm^}>_8qI1_sm`Ux^(_!lIzQ6BHljH2*%LMqKYi{k<=<U-DL$RUC4=z|>x95mo zad5e7wZ+VdPgiC8iBR!J%!U3y;qR2J=v&$Vw7=@Uiw1qS9$FA19v#a`-k-)~ZE=<3 zUP(ebnjktE0VcW<or%oM;wCWzCDO5tlG)>vjjluo-B2sw7&N@f#1npFa0^Ojd9s7D z4-*70=+O{hL!!c1_!2AOv}Oh7(0Sk_{#8(}1vX*wRnp(;T>a>c8;FR%u6W4)g?-fi z^haI95AE&4M$>LmF9PV$p))6#Hf=r@vbj6&sxM}GH67aZa1gUHhM+~9BKFk_=Qk;n zFZpv(pU|O8v;5er@)}Frn@qb>CIh+KTTLdHc3K@L-HaLC9?cZJeew{K2;n^Hfy81T zR~y~~u3QnFr|t86SJAR)9sgjrf75p(Ae_I#y?d^t3IjGF4-^~@H*k~+yQJJb5`hGE zPs%r;4j2&Ti;G`tWMTjgiDTU7b;s5mQNGtaA0(N;=pvj4EDSIv3NihMXQ`RaTtKq< zCV;sb48@X>igc(ejzWi8i{J(CWE|HJOxn`AfF4FS6Txoqg<2cU5|O9rNX>AkLu7$q zTBP)lu(N^#SYmb?ImtS9_mT6GbZFYbTxc|W5!*^s`os3QEdvG19{``U^SRLu%yh2* zz?2$5XkxE7r79lK1In`X0J)U*Fph(1zzG;#Q$Mfj+e}J9_<pSk*Yhb^eAXxB+XO%- zzp48MD3U>=iG0(P%8h%3z7Ql{Yj!oopSUi~Uke}mfv7pCP$#*wa`=o-d&kW4@-4Ty zS^JqvU3wZQOlE3d0NJd4c<$R}taX9M{5Ru;!-m3yPMPZN56bM*aL(x7{-icLTl`>g zbbmToWWdW2)q?6A!gM0u!i$x_QM2gC&)jZfpE>r?a9-PnMlz)6Q98*oOnvKgC=zo> zS>!+moYP0$5Fkp2Se%i>MFf5d*Xc|PDT@M|ib4#<7pGzSe8V#e5aD1mS}nYwwScCq zD*<-06|Q(rhpccbyH?a_?7c8ylDaebDpCgb&wzZyU5_Pt^nEF$Lnr&xffv=?NK;Uw z9GzV<1s2vh74CN&qeH^jW)pFic?X)17kM9;f7xavUIwfQG*I?j#nd>UKochr#4SEx z$z(0Wg+l+0=6{5ndI;jqu`h*a($AUP^=LtgiL{N(MAXzG8qy&)RcfIkuea{b7J2T+ zX5KyvJv;YX`uW-I%zK#XZfJ1}j(77ocFtWF-M&I8q25J~$RqJ*Bv(lI4qB8BD#QJ^ zjlSWC8iij}<psee7-z-JK6PN<Xi&DlOY`M?PD5)>DZOVek4C2o>wmIb@6+EgSsI7} z7Ev7@cBh8nzVu5;QrC^MTtxQAV{*DrJ`3D3u@!_)su#bC3kNj~c@cdL0bC`^dcQ$| zYb65d<Gnj_lDZ@uUOj(qc1QEdR_BTjwI5z?ja(!j5uo^1)5fu&zcZGkS{;U)TB@K! zn%l5qik`K9nAe^he?zJth8ErU4iSXmr6}Wrhi;*VfU~BQ`q{zP_O6m}+GXpjA=|wZ z_iWbbal5{0E7?+5cxBE}&9tO-KkJFXQLhADK~}T6%1AyJb{(bi%sj*Suxweav(7zQ z#XiNTIkh>>cjw$=#Uwpsn&&->DFUDQXOL?YMZBHMX-ov$jyyB5cP(c2U8nK3D>o12 zc^!PSWBM@r3Fe|(=bd-(_IX_0UUD?FL~;8$``y(6F#jd|y{7|{nRj|n0bW{x>7NRO z74iH@g&ChUhHBTHJq-d^>Bgl5dBc?*qq9|>g-lwnH(h;XO{%If*|s*^(p*DS5WZc; z+fue^wNxX|#GI+x0F`$iM}<t+`IkN8U8Q*iIzIkZwl|GqYD$ka8`!Zmv+L&FBx#4v z_*9yj)DothfM?&~*5X6;OwiQ~r0N$_$SA|->CFjfwEIpvbUnyBtGX~yyro3v@#iw^ zl_!(DcJo?1^Ur329_Xz7cx$J*`k7lN9z~|9PByhD?j+hfcZSZiFD)x!D!t;0lD)5Y z7@MZ-O26W=<$aM7e{uDWmp2e`mT}1a>bY-=H<Ii_Z;$3D4>z07JI@wk;zw=P&hiMz zL@z(Un2k6r&b72HD|WR}{P1y-e8hwM{LLH(H?~OTx4mr7-?Dnf{Oys2;jq(5?lM=P zm*+DQ-v{k9x_zm*rox7Z9Q=HA&%{RGvC1qVRR!dr@WZF}bIKOp7u%(l)J0!^dh$u& z6Hm#TJt-R34Sk#frIQP2-Pp#uXcTN&OcFv&35#JKsz_=()p*UJ@D0^1Lsh-2b*}At ztKg?0sEdzni>SV-9V^+D-qt&45K69_^G_*s*IRu$Sw+20>B?2N!2SNp_`dK3$t@<G zC}Xo{=5m^tHK|8Yo$pK>lwEgq-tM@R8)j{F`LJxA(y<8t5tWPb4bL9eSUH$tPj<k^ zmR{GNJ&HZ*^e{F-^J_)7<)ZouS(6yj-=5ck%awOX^;R<}%)@{7>WX`u^7%Yxv8k4v zvX^DC$Q^?CmZ<BM2Uzx>cy8NEtR6TUSl@f3WueDjJre8SvFrXoSOy45g*eu<Z#3Gt zL(^h?WkPsE2OG^3ZL8Z@vtWSfTD;t`r%k#8+qg32hMHcXWXn~b>p<n>P*d5R%QEQ% z)SJF8!>lx7_nVHcb7hAdl`FcedeH$68$;6agD5=R_b=s3ZpD)bd##ZNE$;5Uc2B^b zgs9FPUq){B*Ss=7HK0RgO=-BOX%Ei6#g0ANUN6OiLXMC^w>hPqi%yA3&Z)B2Kgcr@ zZQ6&O?7W4P%?b<N+icRONy{Dw&YjQLUGNL>rzdw+1`O@n{=uqmUF8>D_1BZn`gur# zb=iGu;Tlc+GW8}17&L{MeDr*ZIOlxJGn-=+cX&y-kGA?6d0)K+U;0479oY;dfy}T+ zneboi8!E*BF~<h>n9r3-`bD%9WS-97SV40RvI_i0mclg9cWpi98j{_gBinm)SueD; z_W5LCQ}@Ku47O~_{=@0;n<A@eO>&OKrc1XH-lHQXv(dW85x4r*ftXEVFCTF=Uci8u zI5-tcaDL}ttEcJr`T~!s(Xpd9mb^Kj{;1NNp4MIJSPu~4p22j9qC2-#KE%0VRt`$^ z>i|cMdZQwUR&7W@B_rjB1ZXYXI&BH&HXx$?_^X36#?p&B`EpL4;TUO*qD>m+)v|@1 z{F*L+5I~<VaCVH#Y!}n!)s{0}xCtuSKB}Ds6|_ZR+eIm(BN38^K^){`yE7x8aBUX& zMa$^U&ceV}lVGs33H1hceIz-HR$sSe3Df$5;r)>S<KKo-#3GTy&S#sE(a19cFiD`g zjb;UR*%i=Qd=05rkxMVJtN;za^yw4buw8^GtsF@<>S#0v-ru4V7n&maaRE+LWVxMo zxeA*}iAotIcW4X<tt-(d2%P>H^r17Y_GQ9AyjLvmwrI6#|LrfU{S5_1(Wv&KMi%dc zzPEjR3)%K_tDT;0KcwQtchcF`Dk3??$-5`NX7dc2->XXfi=z|%2A+!rn2?cy2ST=f zI=3ci54FjvEhQX7+`Kgd0o+;y_Nb@zTXCI7gW4a(aE9=3?x|lNewm9eJWD7QU20UA zw1zDEMo6r(_L<$jovkf<<FW(RU&z?r#p4zSKbSGkJUC?{$X|WEWZhspK_4A%LD<)p z>RJ$${^m&|Uxb9{cB%U9naR(ms~rx?4ZgtWHAzc$Hfp!*Xut5HJ@29R<iO=8*9~N^ z)ZMxEGWOK<wKm&A3Fdouni-&TT$j8eNOu#v4Es#|6*VZ0+NWZkP?OOLN%cER91G%! zC4HYgXmUgkKbyfG*P)XIEstCFT~01G<;N+zimb1)ym!*5th_QrZc#LJ*d4>-9c<Ek zd1hKbI|A!PhipvG_f@W4F4kB#qFTr4x=J{8{UH_i4&g)i1x%h=$YN!yMza$Isqk!r z53m1R0cJRJx;yH=;`yjZ>XED^VVM`N@$olCa|vQW^3s{(aT1P)CVRIExZR30bWd1) zlULY_B`;_Cg8EcK)u!+dal$+!#d#iA;^M=ax~7ZMyvACTjho+`%ieANVfJK)M`meU z<4Kn;uN%_!YHy;6*R&s6rK-ulP^es-JTCvK&8T`lDt_B7fv0a4q^n6O?L|GN?>qqw ztWrG(u_aV1e-%GJk4?9+H9K6`0uz0#0y$2*Z#85Yoo_Gwyag-0TffE7%E1;h1V@cr zQg~o;=F4+iQrUt}(jtZ-N-_1z&l}Dr-lGarAL53a{DC<<58NA71wRk(;4f2+UxEiV z(4o^{BM7Pj;De*^Y%H!)vK~{|kL<An@t!~>6+Xk&?F@bOPk)7Pg>ow&M*xQ@n35h$ zTf;_&P>LWX*}Qvdkqak@wBjb|a8vj=X=VQ4=p*%P$E472!1+lq@Bp{bp{SOn{d6ez z>POsyEVgwG1qY1z9Xj-Wf-C@cmfNCMwtVE67)BAM5ai^t!_+d|$QEJH0o%<@-FvI7 zE{vvNL5JK8j||SP8ZVQ<TUFf{<dg_dK7H?L^y)!lp3pn0N~|u&kwI5R<qSjKwkAJ( zo!my%k6hcqO1QV@llzx3fh|i#FDY5NsAd7mp^mr66@GUV1quVkCxy1zVE{p0QzS`) zROryVj!^_*odevsxQv`fZU*NRO5lL&Q7kxhz|A8QyChal(4ku<L^V2e;yLJll?NtB z!4>=bMZxKfAplUm3P(&p4hpt|DDTt^44|z#h*;po;RR?m^L{F@ItpKlS_Kr9eiMvm zmZa@M6Rof};e|cpI3kk(IQ~<kD4X=nQv(_)6|`;aqO|LVG-f(fM{~BtPH_GS*(N%) zHXo0s1(|`K5IF7`v;`PDn9^YEYdUlfekbw{{&)%?g(6|<r}?Sd{)*{9Tp15ICdx_% z%AXZQ(fUa}H}U2s^vY@!k&_M`CY2`RQYHU_>YsVJE!&wyD;uL-q(kd(0JusL;3yFu zg=O;$7lQr{*}t&zopd%GLUw!xBqImcUqX)Wg!?5ajiXDUv^%)JAo~|y-pa>~t&lOK zV9JTLYE)J%1<34uN^jG@Kk<N<>)Q)Kd;kUP#)1Fri8n3VM2Di|2WH8u-+%+ojksjg zpO|TInGRW_ZY~|oE*)0nZ({xU${l$j>^hecIsXj4H_sANXySvM-;cRzbh}=2N<wD_ zH?J^RK|5Z6TYL}iDLfr29oi#`DoSC-pq^n~gOk$Z!lJ+-s7dxNro9rQg`c9#0gJtG zcnL^t%n5=I9eM%+J1M+4Ibe6G=n5-;Arv9-Hl;5@=;b*&RI!rVwa~+<e51c3c(EJ3 z#(^eY+UmT2F#d~SHgEZhdj<HH$lhMxp&6P{R+`;1j@7bl@3WgG;k^>35}wgRcS9ao z8`bg(%v$U{KJm%m`F*TiA(ELQouWio=fCBtk$G>87pI!9{K(zPk%u2u%ZDsH<gIhu zvmM?RfGxVC)VfQH`JCqnsfLDjj$1=*a*RUdL)AAmUU2!mz`vmD9aPs9+uAqpST~I; zb})6mKdkwwOy9!^H8X29-%F;1Q#IcdHDFRIGSv3RW|?Ss7DVj24-0*av}S$g_~OBa z8#g}o_qRX9Ud7@DENy!ctsZ8~tDnzSW`C&2d^>Ajes#QDmb;bdV<9vaI^ogBOEe4I zGPxoYd^?XVZpb|ERj#9ea$Kk5bW6jQ`<?v5QOZx>?1-#;_dvhhUw@#jU0&>2uf4DA z?Gjx(teOY>bbN`odv*4?ltAK9Rbkii2SF39F(<FQnyC6*P}=c!Hpgx%*{~?k@BGeN zZ!7x}3-x>J?XdS7dc6hC>D*q4yOC~YXE<RUttH)M&*LM5&$`<ql~_=v%6{&_@U=)4 zdvCbh4Os=R8c(1@@iORVjpW4oqtiP>2bi`MsK4IKdf~?Vg{*y9-r7iB{}W9*p^lc# zC0d)3It)V_hH49<oJvMQ&xs>g*Ybvz^B(OVTnZipTU2kiDkSGZ<8)f9dk=^1tCH4y zqiic4r+bgO1#?2yWQ1EzZ{F)7mys1(eN;>3*c>jWg}9}3MbX(SJ}~X<;~@PFjwVyn zyUHX?TjEW>SeV!a@)Ddvva!Km^3mK=T^={%Yn<Ku3th}A*Y|9{E~=`=8He!R%2VkU zMN~77uPovU6Dra1duCGUb}{5ub?9;ROFhsg$Igkov9!yd?1lO922ohEiQb($d{c#8 zm%9RzO^mhHZmd1fz2o^@=D`a=*RPi9h=oo_2?aKDce>7+7tI@*H7PbF+s?%fv@fvB zInSzI9}ah)XLFEO-5%-`?X)lTbxdj3eEaA2zT)xQ5qtCn&)RA1>dAHx8%diEC@IQ~ zYbg`*#++?l$f~`PrpEOoo0_;3aY{Uaa5G|a<bgU)#dCNCLvn@ujwDOjL&|&dTvPbn zFJ4b|QKC5Dbogv*1Mq=5h3kt%bfyoFAZJ$LqR)1Zk~SgY6|QuI4#+FR&H+Qyu1n22 zGVMcW5{yu+PO4F%4}{e?N_{sSy?6gybY@<AmvmkNsmJ(%(Y=r18=fpSuk<Cu51VE% zxrd#o=^iLD1W#X7F{H*PdQD4bf%Fg-I^?iMf)IEV7~o1Bb(%U=A_yKf<2EGS32fU} zxD?yOFcJc^cIkOIaTawlupLxJHzB_OotYouUk|)<s>2QbIeTIByv<mNrX*1>YZAA^ zKDlwnq1vr_C08Iz54{sCEn@lWL!R&7xJfkH$8@GzFwSCuxfIvmUTXE2B1srtd9?0v z&*V|F$jtP|1rN+sfID#Y)@OxQgXIb>uBn0QN}%rbSjgtEfGN@W^d-d=pQh5*No3Kb zxsM2qdiP7YSc^R$hub%fbPP7hwrHB60;CT;jw2g2$IC>QQu6HrmRcH>M`sUQcY6a4 zcCng{5*5BSH$9v;dq-F6w%2!r?3bF7;B;uR&l(Ae)-YQ-h@9flKQ2_$$Xu{ro^!xa zLa(Dl#e<ri;eD#HqQIo`;ni10GnTU9A$*6_`L6QcFFas=BAm<N>1e9~As{}n$iQUQ zGp@kgchlaoluqoNNii<EEZ!!j-oelDiLv=-lh4X_o}0Sr2zO%G9JBKl<m9)yOP@P- zIOu%thO5vN>cm6Q3dOy_{c%wa&Y7L#0tG9NW#-Rk)$<rzx+WigbbzZw=uuR7ct^CI z$-eMDR%goTQRit16i;WT+B_xce3bTd)aOy@F~z(Wq*NP$`Ylq^&c+{rmDOnVc)=SU zFHr=xiF5j5q;a>7f{r3<tXulz#+FW$>3fT$)pxS0Dz2}RzoGBn=eu(3T@u%eHpRXE zdIaq>=ZzV0y?Y!u9ac+s2OJdoBp*2|^^Tc2gGnITRDrKUQsBD(CLF&<woLm<pQ)%u zVR6&K4QzMyn9epGna=0&2Xm`9`}cG9UsxGXR!li+m!BQuS$M8wA;0~3ZGgLVzH8>o z*qG*N$?Do#E3c8KLyC^Vc8gE*iOAd%o2Nzv_XCop4(Dv)tdXsErd7za)d;`hj{=*l zLalif4G;O(emS;OCF(=u@JD$dJ?68(Yzdc^l^~Z~fhkkO!&JXQTDbl48XBq|+2;U< zq7sqrwREV*4*tK#?M=-9Y8MU8wtM(GXGHSz?PhFl_41ROPYs;2iPT7O*_E7wE6hW# zterp+H)4j=mX?Bnd-V{^JaY@hp8BA8L!<C$Hh(O&^f7SfY#2^o9vu=y{@N!u{=yjA z%^>sxt@k7FKo6(E{U&e(qPq)0Wp~F?ICTgqowYCAs$XZRSi#P=@WSS19DX0N3Ozl| zO}lZ_kj9oyZ2B_t>B!LMwtov9+a=d8TM0AvO~$BSVUzuofh*kreCca;G%3F$o?PC` z(zegAze4{L`U($<IpqBk@(c`rqu2H~0)!jPZX_wxn@C9fKEiJ#*zAAvA7#*<sRU6u z{dTE>OD<6H2@T5lck*;q_}RYtSqQQ!T=U4gf>zqXINb}h1=%SpW@J@5RFg!krj>Sl ztp&Mxi)7?22Wn^`5qC1su4?8}COkkj&UIYZGu;?v<#@$Q=I}_xX3z53t9#fzH8yV% z|KOsuNo2+FiN8ESG1jqP!S8LM@D3b)e|m<w(iI1+N!GNYkq23R^pKFn&I&8H>xWd? zoJ{<Yt?2|EbUtFMdO~kjik3Zki^B`!G)nxo`#WXNu9xw#!;$M>`?{g545iN5H%RM8 z=NA{}J;z!(6f3w-Ibfu9m?ux{Pb~H$IZgLj1>{e>9PD*2vjxs$S4?@?D#V7_O9@Mp zW^0hEYO~LqOmqQ%wf(HBHW@xDUo|$eV=I@ChVUySKFqfFAl~U=rnlJXvgTRTyDJm2 zzW&QN`?<=ulAXhSFSR*S%ZGgfG$XH^&^jiSSKR!8j6&^?H}`$4xj(ZgYbxE)d8&0D zoc^U>KbH8Kl4T_JI%abxpH-xSi$rU_7H9cU_Lyw%*k_9Yu!=K}R;q1#)Fkt|30B+Y z^BN+mVplx69&x1~Dd%q<@46hwMUX{5ryS0(_iXpVth<%<<W!4eQGv!t-i7c9^nHzs zuPj74N^Q;_3Env%;FZ5%Sfu6Qi!wX*>6KN^XkKc`G}aIKusCV8*!{KBTQdmi>1&^- z@+`7HlX>djC1@An<KjO2pds#w@<_-gHp#*#gM4cj%dxt_X2k^fOXuJ|wW_n9r{Wb6 zZO_<(sPBTFCmpFvc5pjbduV_Ka?3;e2A{|8ig?^ZIng>2Hv@ASb#`kEbh6%)-RGA- zopa?Dr@+1X$h2en)rW(Rr5ngZd$#Dqp6$Ny(TTp7l5G3+kGhta;2fp<7+bAiw-5eZ z@-0*5BbnZZ%Qc2@eBOt3@(9ch8;`C{xGQ+K<GlrMwf+9niUtj5o~zDv)=Y$w=Ia}M zC*N3H3^5FKIJx*`$$HZRsf=S9=|wF?J%}@bAL@&j;@TN!sk{j4Gx1D1l;h?^O<ly2 znHUa7;FfC4+>xgfh#JIGJcbf>aS|LLb9ap_1vU!`l-+_C?67f^S>F}6r8kbaJg2Mh z<SItpU0{Q#Zr9@}+Zn+%<k3MN)58q!!c)dvyz~VT#(Fz#nl`C5Na}J35i)uo!Ex`* zZVm_`oqNZ3?WH2%-h`QpwNg<10rtyeML!Iu8uO=Z5e26|=DdhTCGMSm$+BMcL}cu6 zk~4@Df>hijRPck>X?(r7&|Gq}`rNkg>`il31}1@AQ-s!qY01HzBXJQ=?Mxy=9(kkH zN?N%dFA1GG;;H1Kx;84$RrIMS6!C67yV~ZggZ^hb-~p+2Y11h!#JRk-z0p<k8m|g3 zS~|Aa#PTK|%2~CvtNGa~(IZEW%rP>yWRvnG_g2Vs-vU{Oiet%b4#{8istq)D?!#e| zW@l}(bqJ>Bj_})~L9uZ`sj{~oHpH{VJ~oOqTjsl9G$W+6W9C@Mj+lgCLt?DgQ}69M zTqfRr6@u*HD|bzTqn>oDr=AYmKIZnmPKnoj$F+RV=`lsaF~6o!LVNTFe9e=`g(R>? zqV!!Ud0VXI=1eo7M3d2`aH#LYzT5J;9$DjE?1kwL%WpwAzbNveQ_S^l%iF18J1(=l zcps?rrruI%Na!eXJ*ua%A6{kFb^h7Ky+TfL60SF(s@elFV#LBDJ$(i8vmo!cemQ+> z!OgR}1~}{X_Akp#4zJQ8GrNj$nK~<dj*+?V%y+iR>kgSIo3{yy2KekEv1;V=LHzn^ zR%;+3Zy~Kqq~66u5C{VdD|*@-zCDHCGEYr@@^wv3sqsn;S#F*zM3e((L%HyH74`~t z9TnsV4mZey=!`iC7NiK4e!#`e>nwNmF|xFJ=jhO~32Fd!2k7T=k07uSW+>@@>dWys z`NqeO93x|2fDzq20HRda;Eu*yxP?$(sxr2=u~V6LwgQB-m_cj`vkso%TU-hL9r9n# z9H$nUaUgG?KNUH5G_bO7$wg3rc58uY#pnAWA~56qk7VOza4%AE)=5U2Ch<Z|FAX+v ze>VKg16MzTXF`dlv^5~Ow`&i`+uq2q`o7g0#I`CJi&>{gQg<c^@X6$a>kxO65Vw%s z34K&{X%vMMCZv$vz>)Z)DzH?pIn$(LRbUy|eh400z~RMcHgh_KPbrPF(r}?PZe^`K zj<^w=%&RSp76R}QhQO)lqd4pdMdn|@&99({VDtk^i^%)bQS5I`Y-yiCoNN3b&<Xuu zum~$%wWa5>G*}Y=fJcRU)8~;TZGUQm_yxyjnc}pzDv*3R0r%@rD!N-~Hp>aPUmE;{ z2t?PbJ`z=u0zwz}{CqKWw0Xnd=#+w;9N>jbZ7?33`&Z>;q>v4_fDJ|(U;=WU+xaXB z(`!$Mer<!E22SS<K`f08M{L*U`^lq=)06OFay{yo=S|etK;S-F=mYNxa7yq)GJ5*F zGldpUV+HXlg;JeS*eB~xZIHim*!Y|-H7f#y2Acr{5T*Lhm;?u%lkFZp{x+#9`?H>E zZ0LRW9PK)MVE>_2joV-Qwts|&eVgDZ8iKmcp{2&{v_+k`m<eiYV9QKN{fos+KO=IZ zM=LE;%E#P!&BWY$uVdYhEhb$gPUW~uk~X+Et}N+LSq<`G<y^8fSVHRD>!>M=#aChl z7GLexNR~v&tS|KpH5Cb#qz$MA0tez-VhsJBRl(-Z@63oQRYdlDiz+2u1ItRFYdqm( zfngFa9vdQRS28}_+8<vZ@`9bEay#z>?x>K>jVxkEYY1xR<12+lTcsTo5a#(ECmo*J z72Y}2Ef>Ztlq{nfUd7(Fr~F#=5$O>{=Q43dY-{t#f|%HD)#(+I!ZG`p=C0I6bfnBP zy;CNVL`T2zu8tH1L8MTvP4;AmiFVMVaeUwS+=Q!%>5eL?P^DWg=BjRD<kRo`&QdlL zHk`-rEvg;QvJhK}z;q4^=*IILIHD25dg<JeJ=(`>`a2Rq9<WdEf~MqSak*2n+8t$u z1#cq{J+n+rvo0Vdp&xnA45{KH8iQx09J${m@D-kzzMQW<(!F-TlXSaDJv=o7iufe5 zHc~>nW$<}E2U@z+b5{FfzVoz}1bKge;$*K%US#X0rAonf<7dP}pbGZ}S8azH|33ew zF~8QveHGezF_BofVy4rvlYgy;ZR*_u8qUBMaa-OiW2zUC-=tTq_AyVwr*7iOgh7?K ziJlDUxlwNMG)c)?ZtGe%Gud$eD;v}B+yjj__vNozTrD+aEY_N;ZtVHq@{Tg+MwTm~ zhkUjM;;(vRH_iuut1J`p1wj*e+3#mcO&n0TSwu%>mlw=i_+f$;oUTa_Gmam0${s8z zXkmYxVV7g1wJCy<7OCl+%bVh<e0kV1s<=SzId{Wyr8TLH2yDgkP&pI#GB!tE(!R1G z!FwT%gI;a8#Lp`oOR6CGEHAPsKnh9CWH=fx=bfo39z%5Kj1mwk6@DT&0)9V<O@(&^ zmcB*K?G4VNbaG5blaaO<?r7g}pc_>aNQeg3MeH-A<Hl~XvbPJ!_u>O8ss$xXO2(o3 zK`{UAPHvE~Jg>bcHrJ$2vIb-tFOH(+VBcK-rm2;tQM4|pqumvQY_R*9u56QSO#+!) z9gNJgdP$JI3{tY{=haA3J}IqwBV2Ae4V$Jk#+ZHEof(N<;-E&eUbqCbnl%8Yl(31i z_@3hm0TZu+kF1=<BbKfcIYA1&U&T?e+kvwF+dt-K$t7*6U8hzhBeT45Zg1pfVcENf zUMMI*p-bFEyS~m`TI7a)m?mK2#mH(3SL6+R3l37o&@`6uqyq$j3he4hliti7uS<(C z+G^2uf~tG#bo6wjCs6nqxHF6vVsjlh9tN?L$M^fDVx1|?lujz=)xx%?-6X@|08Toz z?ig7HZhGs_4fryp{Vh97n^uomaKW&Eo<%J<;-dc|2+597@8QPdyn!WSvs0rS!z^6_ z`BujLI0}E7%R`%wI6TM&u%T`hD+d{-`}1ZQNm){}UpncK+G;!!1QfH6f$gnf<L`Lg zg)2Y^%35+|XA;2Wjma5~{|5A5%Oh=_E}JFiILk<67e{}1^f5Ml)Ygf2FBKqRFB8%b zO{kH45N_IwN72?aXWAq1I?kP#Q%(C9CE%bk&JA5}TU6nkmRq`a;Dg5zkE9I85ENdF zZdog?KRgMFqs<I1S+y>z%-h^4j#?tE#MB2yo?%kq`}tKGxBZ$w=0g^TKX}9ak5G&A z16b<zB;1*)x%s6tbm%S~$jNcs)K~>-MMWX-@yFl#qvC<g>LEx%$V;<ixphFMlzpkk zv9%x@b~iUA67$lF`hYzMoYa*<fk`T0MZKg$MG^zfL~$L;y(|ziH9=6>re^NphT4(K zD*nKQU;~au3_ncfR0h6O=|zz7<(W+bbrXB>-YGPdO&Gl99Fil}`12l#!@^hB#%N(r z5RD0v?~tnk<!ot4e4e0IRpFD6lRT3KRko|5#X@o(-=%iQZM)W3pfoUx-PP(*Tz{hf z<o^9OK50CUR6f@k4X8nu3tQLFEUpCSY9W1RHQk#V=ulwXIK1;!%aX=ZzYZ^h<}Tx2 zsz-B|X<e3?b5IHAAWo24OyhaDGykBqh3So@+k<PGqeah{#k(EUV-AmrWOLR3pUex( zd()D3^r^mQWDx~}9d^8$rkds<*gO(h7#LF4h>aTT@QgPQ%x()>%v<tmZ_bn5IA5iw z{!qg}_3Zl#O02?4{A)yO4yg%BMIU6+SJm9`kqLG2lQ+5Cz_&N$iWqvYwANu7??db5 zcLdaUOd@V`*Jn1F;Y-Zd634dew7q%gV3f~}a68&|qNX<S!j2Yswe%WCMDT)o9%5~` zoolsMiv3b^r@{y!Hkrp-XV=24hH<KZ`exPU4F$#le2Gh0_~}48BxxSkx?mN1vDvx% zc_|izMH5GQ$-D9uO-pi%TNXjSH`z37%amQhmPCi!b*{?Wqo0MRvl*>d;<%$?h)rEY z3XO}=)~p+B6zcWHXcH7~xOcr<@qD}sBh|#C@UXe_9lmkZj;xwB>))T@Y0c;{@eQuT za5?ls#V!6?evVnyvez#wwm21Ch&0W<w9mXP%`?`5wQ-3rR(|v{-v_4}=9I~EDCDf8 z^>jf&Hx?yve{V4ti4OV4K8Wr<SKx&+k9$48Gd5@`{b{vTx^d5>Ks5Vqw!D2i!ud62 z_?5&U-T-J<-00iU7M+%vbfcTHFY*dTtkrg&L~s85C_30xb}f@A$0iX>-bG^mfRO0m zXnckk+P(CIEJ1&`%OEA)wqs-M!1OK$<787izVdJZ|2wiVtD?@nzmytBdTmSFZYxm4 zfA=hrteHm);<#zql1vC{z_=4CT@rfUeLmWq_rWUnU{I{Z`?Dhj^>yrx`zumA3Jg06 z<1wbi?(-%OC3n9~?I<+tAo-e-yNin*9Hkx3`NyjS#0XU4g4@d!n=M`xx9lrX@EZzA zB`67UwUxFcRaLD{?H=KMQ7`4C=fipZQ0k*?R|xr6F5wp@Oym5!X-R?bwb7v$cQZ_* zlasK{@rk|QULv?w@u~qz4i*3L%~sf`K0t_z*_*RNcjuSWGt)t5w(@EyuvzO*@9#Z^ z+b~g(EAIWII6_G01m{&1Umvi@^TbU_L!=ac>C!yOo<N%g$5dJ?CU+n9X5RP=Y>T~S zFt@LW-Pqsn$x{xN>ucNOG5OVBvJk!0G(~32GN>+`ODI98f!(4ntuEKwvuc3GPu!fO zuAk@`vB6dCRrV*aJ;I=J1>K2Scp@Dt9hkD9G~?2YL7t3O%u+QqCb?m@ORfJt9dfIZ z(W0bg>IHUzD2u#L4_TEWf}HV=W2b4Iw}f9Hztr8d7~rl@rY#3uZk&&Np8jPwS*m(D zkc%R*0xY=DMGSSr@vQ<?eW3r+MMChG2`tg{ZQs^1AqU#_*0^I1>lCZ?jjdkArXJ6D z<gufp!uo<=M>lda&JuIYoRgYZqB5w%?SGgUkY>Ncv!gxUAaHZ;b))m@udLj|`7ije zZVe@#R%gBzgDUVgNqhtLe!LWPtsE&WB#nk>Z2>t{k`InaTl=I?5<n&wDq{}A26EZK ztuLu>{!t?FO!C%I%mW2G`H@Acgls)x7&u%e=N~uNk>1{^W2DJ1BOVIde)YAaK!SWl zu7OPgvL*#&&y$qzk;Rr|fJ2vux~+Z$q;80S+^*!%8%vUoeR;^+XsVJLErQQ*9*Y2( zB{N^0#FjS=Bz+`i^gYt?RySFR=s+v4X84H2#=2$fOQaKfH~F}?4Tf~1kQO0L&;fb+ zOZ(Y1$y~uHlulCoMkG-`dybLs1wtxU+H*?=fPXl~jcP9|cu#7uwk16PiE13cKm2yB z&2np1{C$wq=2dUwQ^B~jhMiKm19I4GN+s_zlGqlhwtzt!l{{@pNeey?Jf6+U`O?6R zg^tDK_ebuNb$}yQbKhHxR?1Dg)i#qqfXp>SzJ#xHQ;%S%>#};XNQb59P(U_qci?4O z7%*u+jyIS-{iBQ?{;)wE(s~cf%6tsi*GuOcmF)m$fgHvld;xCIZ8(ldLf|#9q!Y_m z!SzOoOnAb7apf#3q3^GizehR#E8-+Uxc<k;xl33&bP=3P2w;nV1N!y6gddNi@QG|7 zbH0G0J#1Y#$XKIGixpst4)){=ao+N}bZGmx_{a_Sb7d##(0mn&+}|{;Lx<$SF1BnP ze9%u2^PzFr$v{O#^Jlg2kEUPjVF|APe;%52aZ}JHl2o_?cuLteJ|OzjxEY?kVN%3* zn0u@3yGjw}6<&?ARD$^vjZ^7Mk%%66D=g(09JcgwQEgG_G5kL93EYtbk8jV<5<39| zP8Ot&V=Y18M8&~yAq<&!2Hf7iipO@HrJb&>>RTK|E=XgmFo%0_R<Iq4bchatkWI%u z(7qkF5p2p(ue=RuBc>G8W0Kl!Nor<15k9L~x12h!Fm<e67?&;VvPgAUlmPdNz?w|D z3s%~*zHb|~y*I$+AcYC}x@E><V{F~N)`0zNqc2E2&7h2bTak7?Nef9fr8Zypc?|&M zMy0yOLimzr5BUV~4%k9&g2$V{(Ry&7*EHLplN-=`SH5mYDI<e`S9?}~^4CzC{=6B8 zS^|u$#{_tf4XE9uiP#&&`_eFuUJ6CAA;UrEGvwa0MjpOKGUNccQ1#%B!?lel;#$lA z>SPm2bgPzama3zqLBNiTvoXb?&L2tLw9SdY{bk;Z!*52uMH8)^K`3%n4hS6qX0BP; z6^easNb_3G3Cva_34BIB#0}gp69jDA4zvSP3`HDds#y~qz)kfqNea6T9-C~N^8F<g zivM*zcB_4<$G5JBUw%PTi^YhBO?<kGALvj6Z3$tJLJ6BumAUrV$lLj?r-@Ab8q-f* zRid|coXHG53UNRN^?ZiM9E)?^p8<s@^81a-Uv5`c62vICk2X?$YJkt4(De+(3%|ed z42aYN%*yIV+>PAC9UYX%e&z5Ie;ab4%$K?wTkrgrx<|~6n|ptJZ+vV5n-iA5--LAh zeZcr<Zw8dV27wn>uKnGH1)|FTk?^>0NRn+l=?MO5)8dqo^WNIvxsh<W_v0>pp_4zf z-%jaW4?iYo8Doxuq^(2#hXKvf;LRWDM4<Q9*5DgySKE=qH9*ExbWH>73+HjA_oyc5 zImy?Ef4_rTdlr0*{3+o7%=VE8yk6gp-VH<$HDdkry2Jm74HqT@vBB;R>BY&H1?>-* z4?Plgn9V|TrVr$GDdaV#7zub+AQsL|sx_CH0e3AI{;>Nw@{40LZsC#Pgf`ebZl8{) zUO|nhwL6%Dx29OEluC}EuJptBI?P%SL|SJ7a#x<x_~768Y}j;8cQLaM2(V<9E=^@w zbPPqb)&U1!>|l3Ueh#cu<iLGJpc+030_TJ2EJb2GQ+%b(c?|aB{x9ng#|@a0Dto1t z8j@aC#j(!z9x^R}Qw3p?4d}kOXpekfHmvN-Y-+5+>c7LDKk)jK<k0fZjQ2oPbu375 z^LlG9tF~>^4BL`X=XP>(vzg8rrT$O?3;D3W^bX7yzwi1+Jln40DVuE#R@LU{nWUUh zn}$AoUEex*oCg@*t2GQxf(}4pRpMzZ3|$~)fcg5q8q4n@ckK5D43Yj_ZK{2H%gi4l z`hQq^VXJ=UAmI%}_^DaXxL`nj>hh|MhLQXy%59)KN2+wjRD2!zZ;tIQuIWjrIvAQ` z0CKd?eZ5lhj~u#xRR8~wqxW==+_&(H#_vAo_cJ`ieFWaXnWQ3JO^qlrq}^RZ-3`uC zhRuLgd@e!Bng?fP^>j%5$tw^&E<6Qt)vuw_j-n`G1*pYJI2JPhb*uQVDF1GKvNL}- zP7npev#x8w9|TH(OK{QbEVxBDhHXxufUVWvR6~pf_~Wavj!*d3Rpj61;Rl)ren8A6 zA&BAvRDXsKpq`FxJ^HgRfFm(ShiGd+TuU_l3($r(OpoDlXH>@DChb4sZh8NGR&*=B z$IbSf`VHJ4Xi?t(Tbh-zx%kJ^m%+UF&mPtOXSKUTjG>(rvZ0j>0|l++XdoGa99C+F zry9Vy*GG=AU<$7T?M!JulDuXTvw~6xyxTEa_?NohqmaN+_}51<_neB9Brc+<O?p4W zslS9)IYz<N*+iPI7VujwoMP!v8Z+*cJB}o988;P5hxU9GxPNF5j|*h{DtP~bvV_1p z%$&#+a&b(IcHP0g%%1uP9P%(z_z1EUm{s0g-RBF@gF=f9=qFPy<q_!<%O^xGX+Gt= zfq2lse<1tAOUKOAj~w;zUpKO-Fc7i@Zvqf4?-iuR(3k=n8XcZb_9_xUhFPXI#wps= zZsQB{^RaP++8cr&-ZwpIyZi#0UYkm5`hQ@OO~BH;Pis=-AYjV5!w^vRv`0OnI%y3- z_?q7#`!hRSCJS<Fw*(|N-H0YsHScgT+Q0eM;RfU>MdrY!Kz8D6CPl5eWVOR{ophqW zc|oD}!Yj=CBGX-7j-Iuh9DbkSy(6gMT=*^atBPU&3e}n%IzJnNSid(=n8-S**DaHt z^%)nHIuRnGTKwRt$VTK9i0wY!GedsERnNyK((I$swaj%+hEM4Si65!&6wPmy7D8$? zTenJUk`-jC_<Q!%x7PAqK^s_$FfC%GFhl6K_jZZPTV3?zAaqvjtFsv=r0k}w^AE^E zO_uHH=rAS(ff(Cp#uoR3FDlb8<O3%(R&i*3E`~P<dOe&)rS_L725<KceNIhj8C@nv z5k5sqU}R?=WsiZIIxAx|0o+^ciXhnNvc;n)_GqFx@Dp+4w$7A|W-uX>v<19SuVMLl zA2FDSAdw_1D3Q*KS^Sij;A#uzJc#ry6G4DOSsCunnF4tihINSi(!w{WF4-k1g4$JQ zf9;p{dT++YmxDEndTe|U^=r#X#+#hDjy}EE`_g~bS6Tdm(h-hq1c4imoS#Dllenq& zmGIucF`7*cj6V(1W>*n8@bf4_<GX2%%ZfXuHsoiTCQ5{81>MyXijvrC8Ax~&Tkv4L zMdKca#o|BFQl_k`-eM1Bjk6)a`?BJLi4qQaU<j7MXZj1_Fk)WuHMov8i_fCn0!dMC z%sN0GMarK+s50K5SULgjV<EwTVq;ApVp#Iupda{!oP7g^)OG8CfY)Ma(kM}II1m29 zKl>x53?xVv;8xe~<6HgX@n27YyI2%%3MGDk2F#?%OH?fa;C_Fxks=8Pp%$cMX`K6U z#I|ijKn(|N4}+Yq;IL63;Z1(l7deRNhsTC-+;ajeZJ{(HY9pmljG8EK2T~x`!EeAO z-qCsURIa^=O;CxJ;?*wpG?`e}?YQ+Or=v-hYBBluSQfEOh(C!2aYb%=@O8B9kV-6V zo~b5F*sD~W7;wEHe<u-+(i?oHwGc{y>;72@O9!`}z#BY3iVUMW@_!qT5cpCWKm74y zA8~IHIAzwKlLfE&dN{+lt_EKN`7qHG<a^ZLkN#Ccu#JfB#;P&|VKxkDwb>sblZLH+ z<Zs`!=xCMgo)xonOzwVoOqs<dmG?DR{rS?#lBPE<@2w*&#a&+ut=sJl_!G+@P#5rL z@hg9pBqPC!3(A8D=VW^j^J~9iCHDKo`iG5OaB<lU77YAjrEH+(U&6&9K?vyZ6y{G; zgB<Xq>;W;e$2h#P2S`848g@R`i$0c=_lp=J{{vz?ivFPng8qJZ{vMz-{=x9QKYQQ! zvCKP=zfZ_H_|GckeXmz3kgcCOg5!q_KZpNBXvVKA`uh?n0ZU-Ux9L~;0+F=#XNGgt z;98`=572yvi5mUj1y)5mL1iKou{OQ2!TlJwjTj&9PctH9$MEPIx2(fihToq|QQ)g> zo#tN-X1w-g&9NnKD!ODheoBoXVz)P28D$1r_HY!xh7;@(m(7f8<Z8;xw=$jg%Ta%I zM*@9Cd&7kbTi5&#_TD?J$!=Tp#Rdu@q9RQ}rAb$MM=Vt7od{6@X@*`x4T1vFi;C1B z9f2TSYNR*mB~nB0B_R+3B>C=(-`eM_Z|%L$S@-OH&c63~&L1(4d3fhL`xtY~F@6J# zrTb<~<^+}^-R}W7St1*Mx9fNTn{aM0u;(W&pZBwVVM~XdX%VcjT;IKuPt^2#bK+Ea zJU~=v0;!+OR7QrEC72E@FbDSdwMX1ZAhl4Pp`Fcre&$4XV~KKs(oXqDytiU<o|W|Z z0~5jsgQ!314+c!v-zpz^X|NPXB!(VWUk*AGJnVG|+1%Xti{OGi-2q@nF6Gdc+a(uQ zq$?NX)~8GiJwNs1HSOw;5aS<H+0K_95Pkw3y|Gl4>^I==>r*mvBv2@u7wH$}+EWdC zGyrJehi;Squ379a0J6U`m;JN910ajB25#iB)<*cYS^t9&d5K=P-NIT<-1h?r_Vx*! zV5V`$={s7TIEEEyB|@;+SF$l--2J58pvINJyUN~?*{Bvqrv~Bfm7gx=rYaY%)glK& z(+GnrM&M+5I{=ylE^}p1$FT%>uz5AYSbA`w2l)W?2|)kZdyjaZAO&}HPd+F7z>~*( z=gWwL8_57AFd3jg4dak3a_c?6@1W#u7cW_A_W=^Lf59}s8NdesoI!vkr7aU9Q7$(} zT0i;x%QHKEC+~MNcM92y64o1(dsMKFs>WBD8P@B4FMnqh_cOleImOScpdb514x>?b z-FhI5Gn>dOYs!XP-N-_FOK)@(n}@C0T9pi{RZ~$JLp<08P5+D&sQ&g<#)|m!VL5Gv z)&45K=SEX0JmN?))V){JQEbcnMWXfySBxVen;nYq3A*W$UO4eBUE(cQkED%_V0zEd zq(8f*$=p{p3%;YtWmk(o`{Y+cL=(mykA0F4{roUN&Z|KDtpi`+C1$Fm$d#btAbD-| zQPiH(`877yVaMWqMf!e^0uz5kFK5|%9op?c=_^*Qp&9Z8{+`LsMgjPV`y>m`gxcZW z8;NNuDIm6+gGH6{tmdPY{B@mTTYOA2wwrTTG;hb@g-+c%M-|_S?Vu8;3wMW#-Lz;D zbX=*aY#5$z2<;D35pdvkMr6b?S<0~~Q8n0>8l>4MA02t~AhVt(D%-;=)=0twy(h!7 z<7aHn{bmj%$kT$JIKr1$`hH#8fR?G`WmjPeRaeghU=$5FXW4VCrU;6yI)r}Rf#M?W zkrIJL!`ShHI3}rXDaC2)meal-Z8qBMp(*zG%7a=nSy{>4KPd8Cb3zJP?O>W-sNMU- zo%R@+3c&jgt`UCMecF0IrfNz_%;Lc=(lxyAt5TQ8VZ=q}`zEDk7X7*Mo7bzaOk}T} zQO{S!-MCV)e_NYvbdY)^8<CAHR%8p&%ahuEPh1D;P8PQ@z>txdO=oKn3Hc^ZL^q?B z!}0}5Q+OxKUP=7{kLl|}{81ovpj+aN-?Kowx2>g~i>@jW3zQp}&4#s(?JM^#=;xO} z8zcvU`?7kA`T?)A6VJ2iCDCQElRC?y84{Oco&oosBflw`f4?|XZn^#EtqjD*oDh=x z&9RoPeY8<OI7Cwd>$Y2-DTk3hFptjw)^grNeMcYrOtCiYQ<Zi!MH&1vG>8p0E5zU3 ze-B%jXdIb14hyO!YE4yDe2K_Lc^txX4D^Jj*wxL*UW(8DckMy+$kFN{<b9&Saex$I z&xUM?gRSy{^JvM%jUNv^7I-GH3msWfz}4^``iR<imF*@BIr0Yu-Fi&?0@Z5)#kM06 zc#<06XkIQir~$;6ZKmd}_${9h=TZn`HYwy$fK7WH*f@H#diRQulIb-kq}Y>fLlVHg z?kAmG1IL&N0K3oM6#|UYKUISGYWhV~;$sYB^m6ouc7%>Ezja0Ux>U{;ctywe^NVMt zX%Yq&n75L5V?<{@NZ&Pa<daEt=1*aG_s+*JeqxQ(E9<vqY0vat4=(0~!Wzj3H<Ry_ zh2vVuLa5#%ROv4o4Gn${+7D&*3*9!6cV2iZvkP3_RrVGS@SUb<1=P(wCU=MLe*9l; zlY<{ojC#DYv9+e<`yQ+O_FSCmT!8s(JeBq(+!NuHoo5~*Vd{Am5q5>3GBvZY$-?8l zuva2Fi}o8OUd229N5bFn{VZTo)?9HI_9i~~D|FD~BG*`&%eCFgjL4P#_&bKtTXn8p zmeL5XHWWTlfeCX5WDc5AqYUEsZnAjsC9LA9=eL`e&P&OMl>mXKCp6x|mZj3{FD1>B z6Fml_@vD{GRnomZnnM;oUjC+=igZo^9odBN4fT<VUd1-@GnX~=1f$wT&8ye1KJR?| zn#g?y8>D)6F9&-a-@Vgj#Q5Ihg%?8mWl3?@3&j*iN3VN_Ojl}tU6s|E+AHD1d2b}k zp?x?$<wQUu)`0*mesEP{wZGCrN=5<bsFB<t{0qNjsZoVx46UbgVGJV*zkon8Iv`M# zS?WuZ8=9i`?w_{exp?U`&R87GXg3j^gcX5E0JrA@Q)X*;Pa4i3X~&oEK1tm6N$ai) z+q^^zl}!2#0AxtWbF{PQ*Ho;}!HsgQ+Ts{X1R%i01%{D*WS=D5I=Bj^mAmN=aXFj( zF7&;lkX7Xs+GRzdDc6RF-!9gydLtSkPR;3835l~LQSFhUeLA`)g<XZ_Q=o5g93rKv z45fXmS%#b*=VE*gJAA!;@o7ozn=Wv5psj|kW`>-T38-YUABu?BT9@%ooh?dqYDTAh z?1!LA5Mn#$&DXl@W+VI+4)j87QZ&aVc1@FL<{uQxy`!YD`l#PWS1pQVG|<#u2z_62 zyFv5e^iHahj5?=s<PD)Qs&md1ObZMvY);1pz#?g66pZ36sP?iU>>fZ!A4j?y#YZBd ziYkc06Vttl5;2lPWyBeu6GnZ5kbcbP5u6)9oj3ha_ju@>8w+Xq%p17ACLqH3Zv$$8 zHBU;v+0WmTQv1WR|IsST6N^L`2J>Iah-7*81@JgIS-3_004qq$XBfZ;{e4LQTR1tu zso^!$@W9U*bGe_`F-O*ZmIo|;C#dv+9~5)B4>s>lx9fv*dq-{p5k-he<B2^dm(IY> zJOW%>7$Mcop8WYmhA3M9@7?P7h#uVNi8CEpintqzhk^lLC6B6(i~&<+E3*W7fGp44 zLDX6zYk<E%osn}7^9V2lKNySbi`!)3!6cos9<OUoci%BLS472MzB;lnT<qi3rbtPE zHL+~RK!7voRh}@*x(eK@*06TbxR7p_$}-iP&~>Qzf(4-Z1DI~4KCO}A7jfAq7VDE} zh+j<qZ42rTnG2p<Hk0HVL%5g%;>JJ#gNl>)@neGW#5xlKvWV2ds=xUdLZ<^2UrP7- zj!0-`<59RqNXjI{Yz6_#gz=73`C%hCDG)jx9Npk-@3Lp3PosC4kZNX8H2_sFeFs$s zahI&Q4ZG7?*L%H~*JN!ql98*vXIm|aXNjtU(-z@(e}p_0ef*V0f}-H!C6V*({H!Jz z{F@Ad_Ji*UW+MnWrLSxFgR!yF@q!=*uO{4$Dqo4y1;_OZa+W;{{_NVA?ZOvx!n6vZ zLOG6*5@EzXhnLIZ6&mHYclaoOT=a}rVP=RZf#x0CJ6%#7KUab``bZlsH$CI^>8IBo zt6N>3REHVPb{0!rImdV&43QB|R%?u?JW3mN5lfR*!)Y`&kd5uUNOVuIdGEMEJ52U2 z_ImcUh?IHD7yef!I6?6b{0f3{Pj9<>@KK6JdK6wJiqXyQT$|`ns3|msLP0G)wOVj| zL=wV^$#&s^GlQwsxvp8Br*S3|Hf?WSVDnnZd?^n?bxOxxiK^vjc<gdUi1gAhPU5b) zQ)P5=x+JfN39|~ORfiRMO!DqGh=Ss{8|ckR=^jbUN!Dr-->6ocmGsU#wSRkeqfe~H z=#y@B3o0?m-C`>T@~P0Amdp6;x|^31G7a9h(XZ?y0H-mUY%`A4R1D*((!3&QG|?<5 zC6p&3mu?!_+`C(Lx$PS$@ca$zVm0`AMC)$Lwc0nsM*ek6@ARCLR(QV$&e}x%>h~F` z!qUBcjuoAzqa#GiT0K7IP@1Pm)K$%nUk2YQn2x=7+42TkO()j)y){;)^`>#_RZyE9 z*XGQNcTC@O11Z&xJ1DH{Qq%V*-{eIa3K~`wH%6Gta1-~5d(x$b_qG}HtahqOw2k8S z&L%SkXA%zb?0hJ{AXbm+lMO^BSDscU|GHj!<@)noHd8g8C8<|ZtF+EOif`-1CEwQb z6gZ^c8WqSvA#y5%Xf(JIyRBk*KDVVQH`TaOnykEO(*?ix@geNAq~B$`nR0C3+y)T_ z9cvsID+xCCMHVhCi$-4UITJnF%g(gY5<oKyki+Jcyu`>hX@5|#vso2z->+V3|7nxD zTz|wQ;AhF;S)qpXJmN*0yCa3s>z;;fFIXMB);BAw5Q<SXjXRIZM~MvCrmG49F<Ph+ zkDFdC`giPIDr2K(%!ki2J)DfV68+<5w`dnbLxCSh&9@<sUrf+6aR`r=?_@+lg{P*3 zli-=IYi`?J&qYHxE*dP{xVj=r!1Xl{-rpOpV!zh;>=a=BXM?XfxRB8B?JY7}4Zcv} z4z}vuym7;*Fj2lhW#0FDseG$U<D_z;Eu|Ajx4?yV^~2BoOJ=?|2Bi=-4(nTtLkbQW zIB)V<-)FQbRY>tMi`vP=qZ;mnSw)6*1<rxj2zQ9FYSk!0kJWc$l9%J{_PJ`xTa<^V zUZ3e?m{6e#c|n2)+=5?RpFm_Qpz=ESEXD-{TgxEs6Pwgk+Ef?s_nYmq(?PRzFe_0N zX|AKKxU~ZsF_))m${mIr1Ci144*3n(_Q3Qrs0#K=1S4}6K_e*7C-417E}W37pUxxi zL<PH0_;0(KU?_k6R1nEgEna{&2z-jKYnaBXk8QXKi2KRin&}%dn{KeQcHnpNomvO~ zkP#+wRnO2ySd3U<D~pTbMOej;uO+C^f7}{9*zP<P==z=0ebug3@eNVh+io_jQW5ay zu7!tl@Y~Qf1jgM;*t+ttn1hl1HeVL?g{AU9N>@Yx&)O~_=(rV6W|AOF)>lGbjVM-l zfjGLD!_|i9gzr4esjbn`a+&zHRquuO2ha7Q@s5C-`V-R&;0ntvU&omR1Ug{{LKaHG z7ct!EGuZNkgF^#MEhZ5bjvx>8m-50ldgI~%fE424a5!<WhLhNLqF((5y=pd6VeWdM zTR$lLqH^?#uhKO=W|}}uT3dKXWX$K&N>pcZEE1cpGb&yb_xDvxXtO+)7?b_<eWW7p zT+X~$SmYh&6(DomnbbfZ<E!kE5>Vr|Bd1@6(KWv3`ai$=gF<&nE~c6_;Pv6>KIQvp z@m~%whS%aIa)x3SH|ncLh)OT34%{>flU`KcUVu$?EJYO@BWpG2<ANw|t?8v(GArM& zd)5Q?a`HTwJf4I=s;nMDB~m=iAPDk)G4cRbm|V?vO%puNI=+5%SQUh7zJ8Qto)aDw zRyC;5`#$OyZRGyzi|KC965or-^R+ay(1p3vs^~NhRr2x#=IqzDiHWq7JKr|_5X7l> z&)-drr}a7c7P67t)iL46S9`s`(tqkf?BV!i|5P8^&!)jGF`fI^xOt1Q1!le52lsb# z!^0&NY*I^U>s;F95H-^MuibJP>7pXnaI#!hs5+;2XlxbwV`mA7_HN(ghE4H-5mCrf z2KKIqlOX43=&MlU9OEK(*6x#?nCH{*9L**n>QKRsZ#<k>qaq^z+@vo%?UQ+PFN5KI zO&^BzK|z5}CdDtkS)^uOnyXD2q<s}(M29zH;87JN)FA&d^plZXEJcv5-~OnlnN}J9 zU0lX)m-Cle0KsVGGf{>mhfjb*S;3gP4VlJw=R>t?V)S<Jd=huXW@8UuKjXDLFuibt z-7I{t1E=;x7OdeqGv-;jSLQjoe(dCvC&wcIs@x)NxNnVaEY@v$(queS!sKdGgVpcU zXotPe)8>TTGuky1X&Lci=!7*3(xqW9n2{lkz<q_$V@trtC@1>{u7eg{Y}13issn$V zE}aprX#~DT>%HSeY;+uwc-^7dA>CgkJJw!^Wqn*TBxij+Y3};4lbrgO5`@+0#TkQi zpQnD6zcQ57tGivj*(De$c?W;;_RJBI8;T(dUWJWc$=2$KD-QmNAiU>fUq?1~=<GW} zIR@XMjKp3__=;W|6PZvK>+yamd~4p+aFN4hz2&UGL+=(*G1H8ojBaJ)ANA0%^`KeX z+I&6?xuSOCvGLE3)iPi6Z7A+8rtY0ia>BA}hk`KNWn}iGedMJGXu9EuXN%Wa)+$85 zzz4Tj8b^+$<9ckG^@2H@6D4RhfCsbRSMFfrD>#<Mm79Y%y^Zrsy7SV~c~!k&mFdPT z&Qzy)p#ZQ6j>}v2)>k=^r+xMsDur@6XcVR)SkUGUVQXyqQcffL+EGB>0(~(d$ku)9 z62HdVnu-b>%Qk-`Q}>q_A$&beQfE`s`9A`@B%3ehwkQ_!{a$jy*R=wF+k?wtOHYKb zWm0FOnz9^~nr4S9g~O_4ijh&*H?-b>!64P)uGp`p9j|*z8C1DKMh(|xY?6PV{4`0G zUkERIHj%H$ox`-B{-BWbN;_V&Mn}>jH||IK*vQS-ef!|D?()%iVnf4^dI#A7+b!)4 zD|okLpS%Zn*<T$7{FbVT(p!wWlQVv22ySz5I(r{d!*YY00L0$VvZ^)-!J#Y)33wPQ zafR*-55zUm;u>bDFJ<1gUbe(O@u({J%rkSY(fBsn5w$xV9IZ{iqH^Ax3Q^r#dzK7c zUY}IOh#5(AIr+||00C=r*)!appP!0+XQGI-<WU$chAm7p+0EQhxQS^^=FUO1zZ?<b z9%&qiYaP14CUv#P{7sTES5oH<I<uv`x9z%~@Aea5HbrC<$aM?iwJVv<L#u0HG{}X@ z_VLDf4P#}RX2H~X5ybm*T||wqv<_xfl}Xg5!f}p{w=RZlg1I6iv))8yyQNdoV}RQv zBJT(6t)#wuk2hBCz3_XH2~3I7e^8`%4=#+=(8Ah=9TWtI_I+(HrMXzXu!CG5_evYX za=v^zYsn>PS>=*o5eM8%RkL4T#xh|V@`uxZJgil#Q!x7}q%g)aU0yOFLg;uDIVj_u z%|S)yJuU$k+VB|mB^Ec<#umIu&CbajHzWBFiwQ|+%==Ym;#2IUKu0-KghZMf9*TNA zH0Bjs(!-zned0?K#q;fb27fZUU9wFW(T%d9!~z63QEqMzO^$DWTH@xge=8tSGnI9A z_KK@Bf6M^U&CX`F*z(cX-XuwnW=lyp*;ihBGrl6cNTPF+-Ot8F>c_2JT2qt)C+v0C zf+x8{Lz|##S#DnFZem7)+dM^>Nc1gQ%4<sN{%k1WbNbW;o<^CNBPQJJoCeepGzrPw zM{6Z^riyT3@CcGB)K8f1?F*Dgnw#mj;eEk}z7XaY-_)#k=lPRz*`8C-u2UEA$d;zM z?nJo0CS?+Jz8su#4x~pPsF|2KMecnh_*!Q`Lt9D^9eL(mZn-@-539$Q&*3;?&q1*9 z;m*|GR%rW~W`wcQSa2&uzg5t-iW2|C&9Ths!aJHkXA!AAM5F}k)%`x7#4<hOp^5Li z6BC=2NPU*kRTB8q^*R@Sr%bPgz3DZ_5U*r^TU>)$5n3ijcBTQL{}V9F4X@h)JPp&v z-$x?A7H#L<F+%njhO%g)*@<UG;e_-yV)A#G?3A%7hOCLMkPHkZsoWuJS~$9~<Eeqf z42g?<Q&r$CcVsJ4Ea02)QRR`|(C>dyIO${C|9B#^e>)jk)Nh*@2bNnCS>Y9<tW6Bb z0nUlVy}y5^!9Hmw4>kTiK3V}kXP$Tnaj?MWNV?cm$F1N{0#ezP>{J67(7)c(q@HO; zogeyfgPESy&bt2=TgT0fF|sf;bS}Mm{^k{M$b>+$e322zshlbvamcDXm0A`V;&{03 zl1vIO_I_B;n=g^$Z`3_a@?lSXnEa7fJBhnE&p2QvH0f|=?*fgK;nYtpiW>>0>0ZbU ziyVyM^Y5fwKauz%z3yCZ!7C4_E1N;xm`lEgU+(XO7g;+M&aD`smNZG-i*p6X_Jeu8 zZeoo%QA3P&l$auI6xaj<#M`aCML6<QS{Y0qc-d^PaIlspF9O$5LgMmf{@QvDDRqZJ z+fyW@UsUa@8K(D&4Y)vO-!~Sx0;q!~aKGZPkV0#$icyX#Sv9jV)|psiWE26LNu@K5 z+jt7HE?M0UnSW$S@q8f~Az@;D&aAhK1UIOHG_a!g%Vg~4vOr10z-F_2><MCfq4?JC zkrV05@_0M)<<N^!N5z0pNW~2J6Um#WSBr{6UJ7B{cObrJ^o>Z^fgk21D*=!Te-}3X zvOy<>t15+1VQoxrf9MuRC1`x$XKiuh&o|GWQ9+7IxQQaCk?ypWJwd%W3Wj>J6^JTh zU7wB72HB&X!S_82G`sR88(9t*4gLN*!~4ucaj&8$4*YAM%2jCFejJz9zX|6(xDDC` ze4=G%YI}vXhF3@_L~v0Lgmv90xercTznIn;&(-B|v*s@Hqt94jE>uQ4yipj#RT8{c zcNgL(DZa-N-+#YW<MZab&gU9i^otC<)v;=Q4nE^Wb_O4wfhzG;@9$Ra`w-0)7Wkly zdi3#j7HEm7;^E`GV7oDtSxK0Hd)+mhlatVunHiBLFWGN~%sgk}rNv!wkH-Yud+Ig{ zdG-2Gx)24smeUc=83}Aki?dfd7&aAH$W55)$N<_kI3|2;qIafNP@J_`%iEgq0%zju zxG?qahV+N_s(fBIf(@*KTdwQcD{!GI3jH54k-6n_u&(32597t&H?i+rIy_yol&Udd zcF%LIa;Df0k>Vj9ZO*1q<A5p~RG9InW37yyKhUo#tBhK%{r>S~i1_+;D+N^z&$a5< zskNhq(RYj5PToL%8ad6;n<j<42WROmdL-XeATO9JBq2=OV7>*=nVX^--X=I}nnDec z*<H@74{P?O!-EaWFgtJM_~#)|sHGYzC!zfyS-zfei#MomhJxKbY+4IHL-A7Uv`bep zN9u5Dd~RyOB*dT9UmRUZCz$&3a5@>?v*e^*zdLQCG2%{ZYj>1Q<K%^h=KbO{KIDqB zdK9a=WUeLqs;qv;4g3&_)*7l*41-;D%oz@<3=I<NDOTX+6c{TmYx2Ry(~qlh)F705 zTJB9lZRP}OU%kn*_esyA%o1NTF0a>lCLpR7`Z1XId{}lWeeCy~kUkCpIUey>TmHoX zS^*^vz#Z=A4eLH}YbJSyEr77$ir@Agi+kaZAmnKcR{Ux`dbi&VnpEz)CR#_4#q*|X z-Tp(ns?bu9&UMwPtjN7vv#7yjqr^;Dvj@heHQ7Djy5_@$cEuNUFuKF}F(uZ?TI*L7 zp=_3?jf2iFCS%fM?g|G;|1vdK=C1mV(&No?j4qZs8*nQbMU!-Fr#aEhNA}WEBbza! znq<`Z4j_}=W10c406zn@<>Tao$vlj@nV$jw>`f+~x57GWpX*Y^n;f!UKWReaa!tYZ zZ`-G9n#4_@4lOK+(e5`rDx?JW4(l%{h9UMqrdFyp>1Sk^2DSy_O5d9Vx>9bkbW2YO zOchil<`Tae4dMgRU&RP~9Mad`*>TvK_DN@4@f|CUPRw676DrLgZ|15P+8Xjj31zfL z-D%G|yGZQIIwS99@g>K0g07YBJk(9spYbWCa<fsad|<`@UT5r-l5<h(JFnNODLz3W zH*Cf#l}oaw{lo~UJiErr!*Wu!{;Bs`#Iq9^?+bl7{Wit-o6YRa7Q5pq`bfT-I_>y- zeqGr+5Mj=`4c|2<`18EPLN|3Yu?aMY``E4;95>tOVUJ$(iB8J0JvfLvU+kgb`MvDL zovJ-k77<k{j%8&g@eM|c>jRAVG;CD_+ebRQVPc37Vr#1jQmR^O`;lF`AALJis;jWp zC^!!aT)xeE#uZAjxDi~*^X@`D%L0;&<*&Pgen|Yhk`a5MLn=pK=B?$0obAb^gYvgI zdGJ~(>oV65pfS8f{UF#gFX#|RS_;TpH?zdKqGZKT#Ey`hz|mVXqFVkW)JS$wtzzgx zZ1se$3twCXgY@mg#aG|R9KW8N^|2_<F@<W7=?iP}G-Y)Mo_3eNyX#jFZzK?(S+>Y< zc4vKx9`#7XkcUZ13J3OpAQi~z(Z39vzANkLX^oAeVH-ySvvNB=+LBXaPH8(Q><6>G zL#<1e8o!;diqI$grYX91_(?iC;QqCys9(${SmSrVBA^ERt~79yw9X5lPW%AH01#*C zPBlenS@ix%z+%lwW}*`}rVSvf5im%f!R7%s*T7Y4+O~seFIxtX{%0)lr0Cyr_N44^ zu;k3i%L2R_Ji)Zt)5j{%^EQfD*@#1NZxm2LlpCh;0lK0jFvJyBWeKPl7GCTG?GiF` zz|-ySCGxliQ3I#4G4TgQAvj0y&Yxefd+^$SihcCI;81%Wy*{}H2K;EQgPpcy7n<OQ zk!r+G$d{}nkUu}RaN*1rsXz`Y8be6wBEAcVnS&D}?O|`owuE#U&!$I2aF!HOa%$)# z_0g#7F5fMopUxD_oG9J-5-Mm(6H8QDUihBI^p*MbQ{uJHPT}(MZ^gw8L}z_xIJWw# zA34HW?kj|toE#w5C_4(N*;e~U!o`k8@F<joPb82;?5f#x)19u1gVM%PBa0$&owsI# z_!)Z@z9U+Gu-%Ahhcnm9&Y705wF_!tpZmVm++w<w8mQW@Zn#42o+C}<l^|VT$js5p zw!Ar6CPV8q9}^|_=*zU-1ftN1lkth>LQ@{7NpNiJqTD#g6YqOJ*gvN~khj;=n6Hl7 zhp_9GHjWlAhU!$Ch%;)+%t$*Ks+T2Yo3wPcyqx>|=?1Q=Cp5U8f1aIsqndmc%U0^0 zzlzuN_sVvVu?O`CmeDVFU5x8qUpjTsU`y6j+2vVIVo<$xK0yRb4{T7TwSycgafpSg zmnoO$rhLBc35Za+S(x9ot|D--8JCAgrBu6DmsM6*$D#G08$``%cdyz*A0+bUU`mGq z*LU&&&f^x~c{cQ72mu>hVBLDLOZ-l-xWA-=yLi8Yb8)%77)#YUfeHbuG}L{IZZ}q` z0m)0ujBh82(C0$q%=AQD>eIb9dS99lB-<w7ZxP}fbaeKKJ_6TwpK18t;B1cTNZSPE zF)0w)9~p`7(3+bxapB>)(05`fzWlsSJR^c1FKWA8-&f@2=y7HGBKPr(l=#4xH~4T~ z<&9zGqDF12MrAE1LV5Bd98qYD1AWXu?aRW>gIDiOZ4Q+<-uYe=+@s&98XVR)FM06- zd*B1<6)A>%vNTp8T^xzMy6!zD{CcKud0`Vv#MCQ15}K}4wmfvDkjJGvu=F>l-yIR& zs{`Gn(y#kI0x?_fmdfDlr7q`JSNwI3RRB6WG6b{=1Kky->7DB}ms7gq6x}*0`FSm9 z^2he)v)gNdTF_#ieMz1G&^Q`Wp+z?1Br#e_)vK$csy?9u;OXgk8d*dgEFyUBm{w9_ zOpnHwnR(N^Xg1!#ytihI*PJG^bn)vqDjtr6RMvh52d|@Z%Sj&o%fF`WAqD;HAA<dR zc=fp-bk2oMTteHoj=86STaGr9UsYPV<f88sGQDErGO;#cdrLnM&F_N(u5hAD>Sei0 zZ00mQSDtF<x;t7{zIsH@S{*#~+$M6?6`GHSvcMWDj3ugvjb}*e_|FC8of*$H1pLl& z-og%pgG^qilZWO@jk>f;=QD<;GnE!OA77glx)DTaTBb#*)&?3Ta}w&Fejl@{8kvo? zPYl`Jl`T9k#NiN`u)?PrnSW>*qH~^j&dmq?*3WdVSXR3pMU*dGyN*I)H@HTD6fm<l z>-Sz?_Dpy7F-)`kF(WY`Czjk^ITz)mG0gOplsP{dr&G<xdi)ko8#!_;*QgT-VU@o= z<}=f?Lio6KKU~XVf9!ZI51cp)QNi-JYhWoC+GvYX(j4b|UvKBtREJyF1S*#vx@PgJ zoicc~eKuaidpS1+Sgb2piHO3U62-~AxI1e<s|NWV#9x$qaT;<z?&B}zf%;R?{3<~2 zH8=RSrgIE#?>C%jm6*BQ5aO*^k@+@r?$*b_V1`?~?q^(><WKc_N311h`&cCU;3awO z3S@KM<|u%IA{l~?W@G8b%HN8te>9hB7i{Ay8^;NOYh)2^-Oyk9`mXVsXs^YcgUS-O zhVKOU0)GnWl3Rh<B;bD!Ce>+#pfsyPSWSVeFb>t`Hy`w?nRs}ZIny7~n&Br~o!1BY z%XPvRpQ#89xZHv?eN&dfMZT;R$HY$%S+G@wg^&EL=Wo)Pmk&pk$7YJ&s=*nen5QoC zqoaMs6mn)um~F}QF&3k8;zhq!cgh*{K_Zzu%$n%wDH$8)Ei;`@)Pl{_{2+JZT5T-= z#x?)MI{ae}e`AArt;6KY7DAnQyyBHYbWr0h=c8}C`lQ=$o1gpmA?r^yKJ#&(FPbE5 zwBnNiDm<&X1;}^$%J62bRcU)*%cV7@FAJA0e8kmBUsURxFBLOapjCN{<@!0WA*uk+ z^UvfieP<!npTgpp`stiy%L0GG_Y$UFy9qx9>@+#>s5tTM{$#N<<OynmqXL-3=Yr3m z1GSl@mJyjv?bzh-wc^@rB)_ocg}0?5<q=Lpq@BZ!jRH3_?9Thjg}jKZhj(w6e(1HK zgxfHD(CJj=exho~=>6lcG@VL3?<>&|+gO>op6o#`p)p-oWz>zPRhXfxj9t6sO?^w4 zdl8(vR2w-P>m5bYq;MZAo@y*Z6)Fxfn^0pDPo6m4Rdf3Kx!Timts5xkGsV_jnGUgS zMfDSgM4D{X()E|B>M6=LzY1^36$so9p2^YqA$>Q$9XoE9<%B_DajeA=<sX;qd^YkH z@@Bozm@1+-={+f3ywyZA*hJ%2X`rTjO=R1WhEVVBUFBO&mKC#+m(Q;(U=zbKzGD^# z?8`yD8SVON@eBqI)*@orrzt@zo{ADsskJsc!lSv+h<eNX3JEih5&ASXh}MPlD@M=( zwQoX-jaZR08zy6HXR)~j2zwt$XvjV&Wm-n*=AHxHQK<Apqz|Q()U(CeS(ZM<@oyh8 zYOb0!)J{7bRN|`j)#P4hF)P^kSFhQSpZ-D;-p`vWA2lx<4?>nJY8iFK)8E^@X3-@& za=d>Wn$WW73Iz_5m!bX7umTb~_HN@`Iq5hDJIfce+4PJYzUSwjnD<s#mnOXFXGoa? zU$R%=CFEoi%!X)Us%9(%uJCmvzIQur=O=fESneTk?TVMg4G0bSP`9QTYV6D6;PYuh zxr};KXE=(y*g0)Ej4!0RQeK#j4%hpkQ^MrhE}~9i_=Jv$<%%d&*RQjy^YHQ|Q+@W% z`wf#6l%3m&5%*0~zbV?BJiVFhKRhuV2KjvGcKdc_zZcVS7SBY!9UDE?0_oy*DQb=c z()%<s2id;D>dDP~-V-q1OiM*|_1&*nVVK-6QYcBYYb?|_koJEEk?%lE$Up6uoJj<5 zX3<We7K&BFl@UEL=b<625Z=%BSL9RPP!2G^U&zqAz;WyJh1uX|{uN%5wUO69Ics}( zhy_VKe@9avsdf5mv>Hz&b*)E%fo8K>&Uk{1$E~3cW;JfT{W*Xyj@i*c5b?!aSTQG- zD%1nQEt`1%$HC>xh=s3bhMmbfVEYU*J8EHUKTUkEa0EGYC*EA^412GA+&5#Jn}M8X z_A?n)yX6Ms9Y(m+v&~b@0^Y&?)VB~DtzhbU>$!efsEtAG5Mnvlv^pxmiql)9i@!a# zy0B`X<z}i8W#Oz7t8Kt_^5iJ-ezDzzYOFF!bfPS?l#_NQFfLG=s>*={x+(ZL)t<-8 z`s*lOtl(V<<zdDi$}xoJ#E|B{K0$D66`uEnFt|r7e4PRb{=6O}x~z8f$qLn(@Arvl z^>raKGXa5`bxd3se&He%=efHxNl$83<(TAWOL^A$07&{WYS1<}JD(#~Q-$)KLHmFH z5?U<IoeB7N9j4l(>;PU|W1mXr*cqTOrOJ{01}gnw0U>51UdP*fG$K2O9AD!zVlQ2w zh<nzbvI81U<x@$%w9(mZuj3hCE=HU>(mQP2Pdst!Iv(AP1H4QdmlJwdfIQU|!2CH$ zN=*bny1|%qz^b<s7y`I_Ukw9jP{tn*^H2<{e^5{XGyt{P`|!hv4q}wI_abag1_@v| zMF+aA$&)H4y7(p#mH79%xDb28|6W}@0?A^<du&9&y2TKZYe?q;2Gf-o4rz|{2#zZ) z=*p1d0BqU#27S&?+DM@#UDo`A!$<4~g?oy${LRdTk?^+biN(Xj1O?&f0(DcL_+t@c zqVAmYbgz@wHH<n|lQlGIWVY~3tV*Lp10fh|+|GX0!(3#iEpfnH?S<ouDigsm&S$gb z&tX?Di};67+%W!dSkVXx*pTDm9f?wVBCU+~H$12=I23RZ=eVGx-Zin2Rn-np^>-Kv zps^ogG2Su+#JnN0Vz`1JE@rpwm}@fs-r4)r%hNG#7LqHvD|&4&KKfkEo~}s%`+UO? zLY0f`h0BJIV={?~4lgi0>eyFxMTD&8+Vo<tjA^@Mt;EdrICOpdRNe>cxJ*G7<*=Vq zRcb#@H(W=zRb?ttKwFy4V9gtKX{;?qRjyMG>74OH>+QB*?)S2SSo2%MTI*=zBuFdL zoTxVPiTf>oSF4qJMa_zA*Uq5XSY?8l-^|gpt&f<Smzry{gofim!;U9>iLmZ#94=0< zA$=q>+Ez^zi8M5f<%uu7HKzD%nj6z&^T73j`J~!S(dhlPyjCB|LTnJ2+I-_kPJtcE z(?XJcnob5)91EsxO6YW*={#)ykbWx)URU#`%`a}5ESBy8(dWv$JDH5WinQT%1Cyui zO!}C!7x)35UpN0Jw0I5vCOncTobRVXNSdp&lauwxOQS?R!qho1?$}v-ocl1it(-2+ z!MpO>PD$u%Z(s)%6$4RY-lUNO>ZVd%M$opZ^$OiCGS&do7mayIly{P?i>kF<XQgM_ z9wezpzjfwca*{~wE#hd|o1f0{aIE&(-9@`sg4X=^mCO3_xW1MnH3WrwA#n3rZ?*y~ zUw?~?ajQvjJ--~~VA1VQyAx;~(CTZ1sha@(l<<|z)E95$RlC|9#w*yF)&>HGU=%{& z)~b7JKH!kzmvtX2&s`o@eLQdAR`>d~lFpCWUD1igC%AlEVQ!-?%Ls>-n`2ku{wNUD zhWgnY{c6q7gX0=vxH_w54<1-=nQe!r-rSMXEO_FB2bOL{gWmd>-P^<~&85%0aj$vY zVrrQd5-Qj-D;&+}s6l?<F%LKs!KPIroojfxa%gsV9}3{vxIe8+>v=^nRXh|odTC9q zG;5W7=yc*(-ew~gf2k-p$C?{aJf2%TX-JY4nM+aA*L7(qvDxq_@$av4pH@*%#3v0Y z+-X`sQm-{$hPSBMF%;GQbeVeGlY2<nTa2rb=$5n&jKn;;@<72O=SeOhWfs<QE1eh9 z9zDZ4Dy&##IkJB($Rsn~Hb>1ejEFmZ=Atswq9p?koI)7#9*q=X(-7A;w5kAcag})4 z$@`8^e#tJ6c9>zEZt$sQ+%*m#uATu@MY?MQ7Z3JGFX8;P<TOB7Ulk~M9>n?~77gO8 zF4|%0@B3_h7^3o1deIOaroeHp2P+K1kn)-*(->O|??@C-y|+#$?=thKT_w?PC&gRe zzCg)vA&8QSVV5dJV|kE`J&(Cv9RwO2S1AW~r&n8m&XyObi#)4CW0$w#IB%cyHXzE` zu(TXQ)dqDEE*5-MhxryV$epB{m#|e;TzX1T6k;TGWA^Gq!y^r>C!BqY^;oWNhNDcA zUt>^=P-5k<e|h|Vysk*6Ta{=<)Q^S8SB;t{vmozkLUTnPk8t=O6p`LfZC@qiFlAR& z&k0$s%L-oEX@!@DM7_u*#5@>mCQOjE%h!Frnm%#PoEdR4j(y90&n?L7Mf8Aoaj_G4 zz|UquG0KcBVP2lzu@WT6>%Ot|5GyFS&-}XnL)zQ2*o+!uk16Gy_C`=*Yi&09bQ$Jn zBK3rL&SrJ2(o#OZKmm)aW4qR4+k0A+@*6<xUYnZ=M?%7fyy8hSh<Cf$0l|0yF*ajb zp{E<^UZ!m^=rUY=;*={(igL&&`1H)Pw``q-*0nH75g_@i!}j!G;qlvbAJAXhcW<0y zO;cV7R5D`cKMh5PR=pG0ccLO>YE!JI(?MQwj~XqsN#M(W)$;0lLGH$0cwox(;_;WT z_L;Xt)bIVmtV{616N8zFNl@<eXmUB~=ofs;p<A%UN#T=v-x^+Cwnb9LDD7CC5TN1z zSmB++ye$j=Mmz`Qxf(q#zggjK$r}qdP#N$m;~*#)9||&e9Ad82AQ*K%@%&QqQYN@O z4C8iZQ(D$lA{|<iDmMX^sKqi{*>_26ID(0v)WK2FW>Sax5o%sUeQ?2E5U688_zn7E zafR@8f{juw=CC%xFj#-=PN}b*#aa%i^2$Atpvd6++s`e}+~fzhH_8l(BdPpcY6mJ! zGD6L;uTt>?-kH2k8INnx!iljzbDE_)XUkTAiP!;{)quFjU$Jh>uC-blS~z{Lov*`X z+xwE_vG}MDUPeCni159^jcK?Ah|r@A$7c~dyuIgrdEM(^p#u}<ni3hgOjeLPPvUuA zP8voQ2j!)$oPAXvF-O^uvkI=DjDi(`RdUTfJ3iMqJjHJ#P&L$ct>fnDx&odm(TRG% zn;#hSXCh`UIWk^Dy1K_Tm4IvU`*a6sgUGES>)t~<0{auy0Rki52P+g>>_BE4+t&m? zE3FyctVlEC$5Kxo77O->J?&0u$)r&A?CSi1_=5rjp{9EeX7zj7D2DN9Pny>}y|?PD z^tFSlw<}pShx#Se{jx1SLwu>@wHsFyBycbmZJE+^wSFNledERyqO1`7^bTq%Th!68 z`%C5|80&<d_pkLM!`WYrZZ@9UFk)$ZFJp&%H7vY|thmD%+b7PO%^V27S73TAgrcOu zU4f4t3Tj2Nd89eD0oBdGp7pxU0*R{1uV&QmLzUJh-R>jQzl(Y!L_u{*?X1mWgQ9-T zu=u2)dbbk8Qckn>nUA!UgTcH_v%6H3a3G?_2N||c3(|?zg!#I0wf%haa3}6p`Hf4I zYI2wOxZ*WOf%w<D63qYwUw;yeW?ip0vjFKeGmL=K2?FNj0C~D^72XxBCDDyEgixNy zdUoqCDsxN_&X5JeD98A9`TNCYl%cXCq0BQsZl8Ve{uVoTEXV;_iVDrB7<0cXyeH^$ z1Ui;&cqk<#S2HxC!s${<d-vz-OFvXQ)G;wKK&(hs{IRsMdR|KpL`EeE)UPJ*FMqxu z8Q0d<;)}K@N!$-th$m#YZ)yC9ho*p2PLh<-JBq6gsbIG27&c|<DJ9V!oVs;kH$*bl z>msT<?`cA*0KG=^_q_07y1_VF;OYk6+cj%Y2uL=)0j&pD7xX&>G&(^7z|pyY3S{Sp zBLTrnCxcigt>tKG+^0~H?y_Hm1cdEL2!f*25h{<!=n7<JvI*?aCl!V6i7zyI_%k01 z0;*lBVr58NKwP=$Dz@S0R<xwZhbIbvBg#F1R$4E_T}&-)bjKBDU6Nu1e!pR5uw;BM ziwQ{5Koqyx=>AhdJ@Y1<|InSZ_b(8K|Lkx69|7{jJC%eln9=!2Z<z*!RYjVyKvc{K z+X50r*>Ds-Nf%b|u*iPc^Mm=YNU<_QL9LsywmT4Wp4HrV3*!}LJ?ueJaFC7*qpSG5 z*x>=V%Jq-c#7Oy|wpSt)SP91M60T1Q*FNDGnFK7U6m@6n*$(iJ30`iVLtNP|!M{#t z1W?Q)Eqdw=!gD|IMY!&;A$h820-T~SM_Q1%^+HeBGP0AH0z{h$rvgb|!DJ>JU>+i3 zz{hLI_8KHpKrcHLkqT4Zsvw3n?5&EMYoOBx{Al#*lO|u^YkfCei~AvWNp056B8K?n zDU$5h4+uQbQ1WfOBso9@h!f<%3HPx9tiQ1u_^+7x{x^S6*s@P1biir-ymLB$z_-iK zdSI9(uI>-voac&6-?Vf-zaS;wnUX4UmlOa{yyOV5KPVJ{NN;~h!VnNLTaXB}KZ(o^ zWS68XMdEf9V-DFrkbxMtezwY^QUH?U4ZNT1k0KvAVYB|$mg5rA9(qBWd?yzSlx0JJ z0qG$X+JSO9$%=~s20+~s`u=B6tNi!Y0dp(NKMIK4jU&Q3iFyBa&&3cd`$GZX-Zt`J z7)UgPWf1v;;t;3Ua+2Eezje(n{LijI8Y#}jC;;%rejpYXtw|PxwXpdq0&f69X@L#R z_WxzOvw?n-C%|F|2fqg~h7g_vBOb!%e&?n<1{~QGIS2ro?oc0~!f68&sVboV4+_dX zBr_1jZ3=rW9O~0HJ&g|ayRGoHRy@1<(xBP<Eo*PN%Ko13`8*@x$K`+NS2bus;D$0R z^e~FxAGxOYF9VVT^h-b?0OtDLk`u@^FoJ`B9UveCn_gcSXs0Mq@h1?c`j-Lyj|~YM zbiZWu9|i%_0jK+eVr3e(16<s(D9-Z%F%7t7pyr{(N1IMWV$1?rWl7}((Fx4ULiWG@ zIl&k|LJ-d(@?(WJ+nnZn>l*IMX<{Q(2P>5z&TIGx)1=^5g4~yFUPXp`*M}m3*ee_h z=9qab8^*pXrvi*~qccz=Rlo+iLm|f3KJBU;fP+OT{-rDbeu^UJ*)4$xdf;hAUgF#a zP%Vdj%fI}!3i19*3oxtxC!?$ljItc|UpMF<r(CN+570S3PbyAF2>pdV1k!~QW4eKz zW(Zgz|A8s`&&-6Ze`j&(AO0qcqSib9p|St;>RK49Le6H%pn{RFv}vG^n!uN`Dr*T@ z#r<qqQhY;Eidx}1lC>*jQ1{tKatx+EH**_DNa>9XeoUlHMJsJ8KNC!mZih{g*%@!E zSFhrm*A&#Y;PCorCYv*^TQ6FG=<0uSWzPx!+ubJa+H<lwLp;mmvt3X93i?4lJO82H z;0H)u1XuzNEt}T+g(uzqQ<#Qe+{$(zd(q4>IIrJZ^c$sSUQf()N;OWtaDRA~r<orN zKsYWggzIpR2?fUQx_-BL9S}U=c_1yms&JLyGzX?K?YJJ73u@MRelPN(Kb8HC18#<A zK|ssJ78IYnhVCuj5@BQh@@d9vIc0+k;J1uB*q{D;kgfl$-x+W_TcQ|=9{hV!qHrUl z{n1!mmaQ=gU(FJOH|%ac&~4)DS(N4*j|z{BuAvBS^FOBv+t=I^J4IkPmLPYNuMxf+ zza|f0l-%+OMu3A^OnZt3aF{^b#tU3E6KupT^78$7+{1D@14eyhyz|xZGN4R0L^}ZN zLSX+%I3_h9Hw)NF#o+u3ihuMz)A3=sD^E-DZ_}fQ^`sAqOLB@B9pR%x0A3lV4bFG} zOA*FPfY7`aN><VSRY&eS^AJEP%^-F7cmEC0)C2asxIfd|#Ap2tcWCh8FNOWBZl?$@ z091f5DYZhF+K-P=eyr4=Z-3Mg;Rl|lrEX<C98=w!w9Sr^i+FzRT2!R{<^}2JbT?M^ zvhYAsyb9q!M)VbgpJ2ZI!V_%n_u9!-oK~?-Uf<wW>}313*K|#<6ApAPo;%&>^gn`D z{h!4j@s^Ma8bi|lHs*)k$LD~v1c^L@#v8<t$4W-bh_xgjlxmR-IR85x^Qiz?K8@D} z|B`t7_e}jS$=?0n(-<;v{p%_L$;Sh%U`?jTrE4g5yu=##NQZwf5171ho;~F6CA%ja zPJT&ZX7U2LeVYFd3iWdVAJ$;ILgO$L1KHq|&%e+(|4)1;|3R^yvT8R1@L>$lzq6o! z0~6usEx^&q8W3Px_M|5zJte<{$=W-3z`j(L4Z~LkWd0Qrbpqh}zcjGFL)QH-ki-7( za`?|*4)gW8*sD$HG$X|VL=D8F-05fSLyzbZIEy;7Pq*HwqSQJi)i2dY>jqGJ8iDLN z0Ed|%1SsVT9^)E9Z6o0yc-8Voxd(goSwr8ZTI=#G4{m%g20Y!H@dSN<N(I<sXKObA zEES;W(oD{21DU6Q-F2gcENKR_T0pM+L}D1pk72fRu$9e#J)b3pMc6;Q#~t>siXtUM z11d6begJaWQ{kf-$pIZZDhOQ*VEg;)J5-3mPVY{L(qtM0k}%CaF12%r6F$iUANybX z%9L#TBS++1ilB{3Jz%kXS{J6_B<I~yaI{O8FBjZY%r^@-&T86w<R;ewLB+Anzc)F4 ze)F+CG%Z2Y083f!3~?`(8QpeVKHsM&ruWk`pELE$kF&`x5eaIJylPyY_Jd$vSj%g2 zFLF;O1L!GUBq3RGt_t=FeRNj`7?f*hqNYkkC{DP6P5Y?n6KvqIB8H1>Gg@KX4aQ6= zmOGKI-GyPOoygoV1PFY*njC&jk#J5DuowUN6xDzHp+9$1FyFsa^UL3==@0<C-!2L{ zKlf;u><64o=56t@Wa|T<873nAN9RMyXOTY-^ZrqTsU#F1-zNGIK$sPL6RAW_ZGrBJ zO7`l^eJpl_DDV8zP66d~jE2+1BcaYe02XlnKeS8DAoy5g=g}wsPi^D#w*ePcVVpv7 zW}_Z(b{r?Az*fHi+^;}=7#28-{@JbnQs00f_MeS=!u!Dj0KGO0HmgDGFSITBfc%Hv zX8(t7wWC`G`_TQTJOwAx9qagACB$HXNH~Sd*hn7)5{iIqeHt>HqGz65=6~}}e<VgL zoBHT9VuELCr{(49%NPC1_8PTzB|iWq4`7GJ4gA+Add3V`x_QO70oRGL32heQBhiUj zoNE_8KOVZWm3r|mo`)xzH+!<|PO*u8aO!mYba_o?BOq}@=1HlFtDXq}KhNqnRQWs7 zhVJMlaL)e$(9z5BBgi!WjT6AyOTehLdWW5G1+c+v`0y{r5FCZaTgahyiWq=`o<(Mj zz&it!t_f}82_*e*&$ayj@39piUi9D9mJA7_fZBYC^hM!15dv(#0X?(uP!=r8PkH9f z@b<g%CyOzByuq@Lu2g5L9JXl{@iU~<%t1j87)$5PmpUrHtTtkDgdrM-s2SwXyjEuG zlKnqt`M1@Qc*VKDbp2oZH*c!|CUcBBOdyw9!}jRuh!<c<`wa}cDnv=f%{f3kRKN)U z>sc2#v9uja!3MT?$P@qx+SeZ3*SJr9@&BEt3}VTX$nw+!7bW&6YdcQoujk%o$7@kh zSdp(SNU3FKrvx|<+rNkM!*G9VWZJb6k9dYSCXsvHaZ~zVW1j!Eq83eqjfdUYFV1Yp zv@II3SZ6DP-Y@pis|?5cQ!J*R^Dg<TymB9CddbhdHtcGlhU{!c@I~?1^$Hus{gVO~ z^asU%ld#I*2`TX5F?$1B%@c3-zrN)k1-tuy7tBheEZ|HHFFpQeg}Mq}OP1`{1B3{| z7TNzxU+H4ONO(Wn&th-v8Nh<NJ%ZTEGUX2Kisv?X`QZ6YV-Ak9kqeOvcfuD6m2-Gq zM<TS#2h+sXo3p($w(Da)lO@$#@C6m;qNzeDsq%Juy;o9p%=<fxCXWrqj|tAORh)&* zvhjB6UE~~h%t?ZnPhR|%UysOP!zVcsp&O>@P7Q2!9cD*t`rXT7_1i%D8o;v|@DYj; zJNiv?O6i!%27ot!U-?Nk?bW3d($I-x`0u|F`R#9l_K};B0Z>E$GREb^14ZEn2|k^I z*T*!@YjMQV9Utv)?$4vkSBS|mz#we^2@S+ICL9ijMS;vwg(sO|NKU87TiQhaT|kBS zu9b0uVJ*2$z^jsC0&dR&D%us<7}9kIRAHxr0<0^Y2#B|DTpi>H@!{Y<D4==kNKrU5 z@xqZ}C)qMTGn}lY81bhX@@FOl%6EpGfv4o{Msy!YI-eB%x6hdk*e@th__>=HQ!4fv zKvNtP1P^qs@*ggfLXk@xCw5PSq~Z}*;SuxAa{<Rq?7Li9!08pX_LLlj$s<2515$nv zGXaSdPWK3G6!7W)s8}KZ$?UFZ6Yr%4^H3Rua*$8&A3O$QH`tFe8?OT!=Ud?P9gZZu z10?@|#kY1?9bj@f`>!&~d@#106{aAR&wI7qRBTE=KLj$v-dyh-!)HS0E^;Wxb$K%z zJ}~5om#5;SUfK~9awnOsH}5i5*H<NdN#{B4TvsoHJ1a2|o7XgzG>h31*8rpUrI^J; z<;>i#QjJDi0f|PnNDq&LkNKGm+H?Ia+63*2Ue{esiwzAR^t-%@29n+7&sk<J7Y66F zx}4GO`hX`c&^~`K%`{)h{9|a#NQv&l<T_YxgSJ3sgQXrpqj18uiW?A=TBG7>ekz4) zSF^qDKe1yP9vi5bpI0%sySzG^mbG*v?H8lpRg7#0n;@ZtF;u7`>d}+x2on~^JZ}MY z&7#j!b2_z2>O6f-7n(13P%9OGqPo1Ck+J;;g}K(}rOyQh2BQ*_)$=8dll~o1y5?4m z=diEYFEO^2ttP5vhzP*#rfN*4f7<bLdlfyM&FnO|?eyUav^a`!PO%kC4^^KuAN1qT zUuQ9F6&7QpFFPe*#~ZG8?fThl$9r3m%J)q2Z>27T6!Tb9`GRc#03y@uM)$L?v~?%{ z(H8AnEqPQ)(8W^Y+I-UAJI$rEk5n84$$qf2d`u^^Q~kvAdAwL5PB~vK&ig@2GP;bw zvA|5cnhT9ymNnU{o0iq7rw2{7aBbe{<q|4!?28%WNUIAMGKrQ*iKd|!%pmW`2E2;x zDb=4yIfnZx)~p`0Np&;52vjsP+X-#nVXunI1`CG>Pta=lnh2gQW2TvgbyV$5*WSOo zEaCj6gHN>xeibU*#&+pbo18}0vo&rkb1`wKh$#!=&ZRc7Iwf*LB%O)6&%~!RYRb$a zM86po>77FvziT7><eCwW)ZZKKjH-ae%P|)52L%|o_E~i>6)y(V=Fa_0z%PcVc*KG# zh=+A{(2)T!+M4Pl9ns_{>nMBRy~3s83yY*A#XWkn(S*Mw?Kv`pPpAUI>jAW5>+~kF zEGFDDUi8Lu;8td&<U>8$=co`5yfHxst3q;%`G4Ab52z;BbzKxi1qH;0NEf9@5mdUA zOhAl?7%YI)s3=8BL^_1TMiB%A1STLvn$!>x0!quIcaSbMG=WePY9Ph);aqDk=iY0b zJI22E?sN7SdkhuxlfS?3_x9%jd|DaEfa#eE6n=aKB=)lb_K?WlI+t(1`=au?0Cy~y zj%i&zvkJokv@59<dVL%~bpnGfg<z@{nmB6@mceTV0D+C!YwPm`{9FbIO<*P_I|DHK zDzqu?Z2P&P0`x<gB|j8)*g<lPFs7cC5gE)`)D;vtC>TL=Ig>-!o#?e_3`WxK11F<% zUJoT+PgqgL>~O_K)F2pvTDaAd)a@bkBR>%uFO(Uf^xfKForgpyl38G6EpRgoY5-Sh z0_6vbYIGmr#<=(omi@>4MW#D~JFE)U{n3{kwmw8C(f}P9)K_D29<JBy1AyQX{IgbJ zcw3)_z6jOsp9{KHDp>AAT2}#haMF_0lc4jN)3gwc?l~C+P|@|NP2S-#>s~b!O=OAs zEsv-ezQ*_DoS~f2^f{CWy6RFTKT?H?;C{9ae?cfpE<~qUS(+RAr&8tALuCT>-|>d% zKF;{M&c=GG3{CYltriB*z34~d>ts$iJqCWAzK;wKTn7264$cuPhmVFDk&R}JQ_S`G zZ|HHjHw?1EUJOcUj$0)c2z_(JEzESsw~uH2&6CRH8>wte;TSTSP$e>$=Z|CsRXB0r zp>Z2f)rn)7i$;(oZSbO_9G8hy)5@begdHV}RVZDC2&gc>o*H6q<)6-?ax;bF$c}`n zh{3o1$UPW(G?cEXFh)SXz~B#UQ};u*Br0iOzSeIXvb_hi!4nnH)#YRiV>fV5rCF%F zOyPL4DWRHs5DE4s&?7A&wGn`}vzl9wew4!dQjrKOUeV>GEXU&rJA_-dx75AjS5pGI zSC~G7Pv1qqc$UDp0FLf6E)R~*G@kmwB8cP|Pm~`}Xy`W?bUNQA9QwHN4|jDg_j~e- z<1X{7Y83Pzm^6CCjQZs+50OLElB-{f98C$m>oSd4S?4!TyA5StUfT2Kg4xrl$%KAN z<_isd^5#Tf!5ER(p)H*nVeq@2-y?vjbR?yp^JVVty!1n`J*H|1jg7dEmV<3)@vU;g zeD|N=1X$lRLr*@xz@BUVAvb#-b+W7%kG=eZ#kAKY{eqSC=&)k<wV7P?0@;S)1m^7u zh+W|{p_w?d3IQ_`14?#n=$HzXip8E3i)6m9^5w>qqq^kw`0osYF(IU#RkT{>%DC?N zg)}wEk9+!rJV$p?-X-s*;5&k`ibKx2riRMXLxz4a`ls*-_N@}OA(!0a9%=l3`NZ&T zOxg1rMjofz8AJ24Cp-*$BZ@r3*4O5o9N`D(+IEysV{-D#uigm)7OEcX9(V3o3>iMW zs3*oN{$08tEswIRJR-i@e=;OZvKkj0c}Ki<^hoancTSSTnWWuqN)yee9K9zb{TlO) zujWK?$hk&hU>_OpXPl)4{Jm<9uUbNa>O=i~QW??L9qxy$E}CEkb$Z8MH^c=;$Oh>U zJl-nZGo*alfCYmN@Wb8mO8e;$tTnu#S4mW(zsXIy5GwZS*xhq_Llw85c<r^kUm?}q zGMa<1PQtJG$!j|KDWt_fd~W-$756(DCM}e&7c;0ERO88Yie@EnQrH);Zko}fb<$Qk zef8`^526H~GL4MUk*{0>MX&GQji<xOUUijx)Od&SGG}$8p6Sw9jw^zHoI2~-XHs&@ zB1YD;=ssze>~DW`2tFeqD2_GCD6YgRlS<CMhNpI2a!&bYA5u7-vx=fe&8_)jr_6)< zxow<MG@c&_nmPN$*B+%ziWBCg7I?eQ7A3YB7<4a|%V$>9#vL&m7LV+fjDPrTA6MeA zovQla5tU<&SzrH99m2p@4Dp``moTWLIaMcY{b(l<ifWP=q~7%M)L$AhN1%lXRQM!A zp{CR&*MB^e=Et##H!wSqBEONodiIskP|QQix3(<GeJoRlWE;qF6UPQ=q>tVnOA=O! zj|>%6-e{H#Xe^)Xm<c-Xb00nuI}&hLyZ+$CMy>M$Ag2fO@Bx!&-FLc|Zq-B%llo1| zQj#@KvEO@u9$6_24u_K2PR}$b)6FRP-L=982w$Bv<XtldI>zs%=*e!972flg`(hGI zIP7ia0#Am7u!w%TQq?hVSC*(g|B#55EA{2`<HW_n1~ug$j<yXgkUZ?Z_k4$sEk`I4 zc^rHZuaIh3d$?11>{r`?hY4zFI@8Lb-qLlK#{~1gtH+&A_^t%mOU3AsFUL=4n(8Ms zT<O^@p#LzEwJ|@hvmipf*Yb3Xt<ec7X+z&(v`~mQKymMf1+<{;y$h6<C20l>>miFo zw4_&DJF2q`#Wq|&`b1TPpW1MV5+0dmtrD~@!+m_np_t#}`{u@{CObuC&sPp2afqqF zuz^!x4&`HW@v(i?ZNA>(`$$bh3pi7N+}&?za}+9fdx~UO;`Ly;1Xf6OsKgn1$W?Mv zb0*=RK9TE^8iH?H@fr|foy0f<OE$7KJpU*gpAsugWvw)P88G&&nR~bQN2>5<tqnAh zCfAC=W0WBmStJhedVBeVBs&~lmMQV!c=ygU6H1BJtL$`ABpjit81=Z%?@DX4E#{vs zieBXRcvIB+`fjxQ&8%Ugy$?>_+n&)!L3Aqj^p8hWnRqf~`fl1}J&IkeegjiXNS)L2 zYuIp8P#t^|ps>Im8o(w|<o@{JauSxd-08f{sP9UNX)0Od@7yG&4z2f>ew&s@?em_z zP8Lo=`(=z+IL0Nk)jfB3;$zct=WJ!CVw3^F>9P{nv{>S`d;0$PDX$Hci?(==%u!hf z4}?_s4Z++~OKfbM>ABoG``HR`=yK}7d#&;~Ur2z4@%XZOZGQq|p)Xk~ET7*oixYOt zX(Pbo;FU8ZQFpt`Hf5*l=vG)W?}!Q8l6=zO*~}nWME;<?;*eFP)hEojfHCjzqMl_m z{`S4gs*U%KRPb5RH;QR;naVaW))Pc-nX;k$KH_Z<q5J{uB7EGWr@K|5*Xuzh<q{sP zd-^?YCUFB8)wki^^32b}z?q80%|3AFq1o+0H^xRVDgf}2!Y29vddfhaLTDD%o&`)V zO6ztcyMN9AhimB=&}H5Np2gnXfC3T2g(e+a-wygKu@MUN<5XQiPq{Nf2@7M2@(ix| z^?$+^x3+8BhnMc#z?{YXZ>TU!=*J|P*Ng$u;#qFy^YuUl#$X9m@&`+LVbw&$*0KBO zD)~mbT$fUkP0i@3;yy(#i<@899iJFhEMeTqu;aJ02WNHVv`>z$iJAD7>C31Wsu#2< z2u8u&z#K$wwXh(C*q|v;&6J_k$B}1r%8n$4`5C>|P#!wvWu)zHS$M|C;7p5`DqCRX za{()tmA=s>8LDW~WXQCVsI5^g8_UWr!PO2WdLyar<}EabGos&sL~uqoGOxu*hrG6B z9v?Kv_ToOwdtmWfJdV9gLHZRu85%&pl|J%~`oSLm%30h3$L;;vLB(XzrR&^o-91Aw z<?WZ*Mg;rcntmm)YV3MX9lA=<C@qdlpDT&o4v(|5JD!oBbm5R(MvUOAU3}5(Wu{!w zn3z(NEu`bs(%VTHxT)pNwUvvXvP_eurC$``iPqr^5rZ|c=*j%VZ12D&nl+g#Y_J3C zXr3yLZ#CF3^Emu~RY#&EhP7@(cePY&SuL3T4<$#;pa8Ut8j(qjHX(C;AE}R?@KGA! z7x4GLdnG+~uzmE-H1LzP?CW03W*{rlKZ-tMadSlqbSoivnjF)qsa6*??P~eM6UWLl z4PeoWye*IZkot0Z_i*LZYh<3+(r{Lq$L$iT`lDi10_DMtx#Ei^@mR-Fcjbfi-PZ|G zoi^T6VzPzOL<<FI0IN^Uc@x&IjW4mA7Q}_6nEvscm7WdFVwe0StRExMN(NVB{5^YL z1qEg0HD;9=VBKQgy*%0J>>e7ARXTILd1-X;k~h5()ixa+oZ7g$v8;zgbJ;q8B0yWj zOGPUg+ObAi4bg0GbQ{f9qoWw+DxVbg&S{lWDCs%8#P>&MkJbtMen>Iwl@`A@y0%L< zjkH<%)-m@{@yioY?NZ;-=WUvt*bgk-=rBrK>YYbCN1(|GtM$jN&y?^x#l~%xs#^_g zarhwY%6uY2BRTVJB5htHhFgkahSSGe!ru*<<CoTE`{$jnyI8ho=<BP09);N17yV#S z#?L>w2iC(L*~Nu&gRwT<8{OD_L1*82^3USmSUMy)dGbZJa+gY(ocqpVqWe^E#Q;6- z34OAW@F9CV+XZRJF+aCy^hig*>~!zq(v60w`?g$yC3|c3pELG!-m`o>AI0*>sAW9+ zI$kpnlZAE=*usYiTSz(Gx?X586pxHDC_QoK?YLR|)fmg??sQ&q+IT&|X525GlAnq8 z$fnK_b@AcOhr9Yn55jqGzm?4uyHpgw7t_w7?p7l-DOlGLQ-s0Dd&nn~ww$Njb<_$m zG7b<e>p8f(mD1qGiqs&|vwK0~hVz6vjLk|uc*(`xL5cLB?}ddG^h490XLmyz_p!=Y zTr!LQ&JlQkMOFAlKJ|}zIA@XkK_SS(jA8FO=yxmfp_LQyp@?Xg&M=JKd~_0HpV|U< z_03Uk$5@KcTP=y`ntox?lFq$(0p|6*Z<OuY_mrKAGWz}Gd%njF&I%K})!uZj^m&!z zl`@|wf~6|K=mMqS@lR2^_AClUT{a?Y*U50EgzxLS#`Q;_MlZAMqH_l#&I-kl+ul@j zmAR0uUy9+vQ++F45{LjL)oilIv<nOuBgQ_EB?Iym7jK^Bz1ocwanAFOHo5qqYh<|1 z=R(6VN4|GyNv*%JT*`?okZt`<6%?ab<=kg&o+Efjg>(JP(-D`*jCaSQKK7)?3aAI$ z$~`_6mRkNgspiQ$u1v9fg%+8*MRdYE!=m3N;e%mFsHgs7p%r>;#0UStTZw1c99HEI zv8G4{r*<Nplr)cOpV!WwJ7nL5;5~Ack_tVlO5{6SwiWPp;nvDhwTLi9I8-H&d2+r| z=u2rq<>#*T{dpN*J|(t2w+*?hL-|Z=ygH@wSUXSVo^)5p+t`RUNaJ_hGu-6^ZsuAg zu$8s*Ag4C1wtJ_rmrsh*e>h>NwQ?!;%Gj6i%UAkktL_Ny8m83U#2RuL(;d^&II}BX z9tO9|Lz*gKeobMjGVO_62xpE>c>MNy2Cx}MsAGdv&*lN<9#r2!icU^z@~+_Qlb)b$ zA{XFFuVG#i*R%<a5c<hepj)JrRsz7s10IlL-z}#PDJYd5xw^ik_Xu6R3xs2=LujHB zL%L(}7z&N9=|UYvckW|=IT7+xkW`48{lOBHPM7$>lFCIh1N}z3ctLd7Kg&%&DZCR3 zYW@rb|MCCd07c&+^jIo{3nhkBPW)rrt_nA3dWq2If?X7?>?`LHs)#AmXk=|U`Q?7_ zMG&}IMI=SOxhyjWiLmA%j{uU73CCQk3+#5`s?DY0(B&hQS5|{huw|gi#=FqBb9d4U z7>XO*EGToX4W>xDF`dx53i}z8r#!((0vHZ3`?(XSzXKzP1b(%ha2tjdc3sl@8K$d` z{!FxX&w-3Y7C_*q-2}n=4(LX*!$w-0Qv5XF=5E-*<q+;9bCsZaHVGSY7>00>F?xUm zKE?sgCwUR@*>t=d0kST>$&vKPZ9C2%ET5sh%m*SxHqMMJ#ct3V44O+j>&tI9JAOku zKnG~oNkL5T(inM;)$~<(&STKQ^U_x<V%4tNbr1G;<8{X2jOnf|Kyu+`Fk{+fmJCtL zm|le@nkD-SdkE&KwaF_3>I&qX#++;oxFP@93*fFR-}+348_g(|gRzT3jU@*p_~kps zZbq^iBMNy2O?tbN9v+gZCD@_26wx45?+0(LGs1cZ-o}TaeMe9XR_zu~aBrG}^uU`N zdOX!00XrxlK5PvgTMEQr^v0gg;QO`}sB+9?47P1~A%1emKvkl&H12ZJ{Xj9<rMiPG ztWmHG_q&6}V?>XwchsVh{TTyH=qk6KuMbs$qH%=#g~uE8e3&F%3ipb*CNU4$oF*jx zVClU!&wM709s?!1(_7p$?(;y7K<Z{po*r>NwL+bFtiN`7`=|$o29gZ_*fV1N)<y8e zs~GAYLL=nks>n7Qh6x<2##MfqZo;@B@;WH%sQ?irfYd?)6=3k{xD@_iLD_@pBL&>{ zo@`LeHK4!vpVRHUhJX1mH!$D)m^anN2-}lxK<CW~DUn}I$2J$-$U_a*LJWe2NY1=9 zU$2wmY}fdM&rwGU_6Iy|T8wV!=b=?!JithNNxt)1&iHDKx2nFIeK%|Z%qW23t?Hwm z3$JwY1mWtPx$Y5<0YM_@HQYYEcI&^GQn{K)Ho|P3HwA@{BFHvJ|H%12yAY{08}sC) zk_q&;rlK}h!!Nz^;h7v;=j5gbS$Ct}g|r;re?8zzoz>?idF6?Ph@-C@nm-r^zcwCv zU1S|J#=|p5Ag43WpueW%qKRohW+5RWYiAx2H)s1-m$x&M&|g8H0O)#wt~6{Md<Yo1 zS3v{<-x4;qP_{nVr?|}VDB*0(yalQB^;bimBdOESr(a&Zuz9j5M|6KZ^KQ%(=*9uq zL=fWue+gq72zN9Ulp}Nku|T-PRLS{XydD96YC_gje7aTdejE+d4<h-fZ4{mly&s~@ z3uEVR5K0NLbB4m5na?LkI>QDC(NO=wD=fqJq@s4sDVTX-jv^iW$F9)TTysEj&JK&M z$ZZi$LI@3iwTL;Vd$ze=BKAx(6fe|_ixXyRO!S0|>(fC~Ns2D0hY&7DP;a7-L1vA5 z3Co>WBDX8YXaKAfdhH|MRP^;ELu9(!CgD)IDVhQ|qLladxq2sTtG_HOEABo!W>(qB zQKNoh^0maKzSuC$>quQ;SwbKXH83vXsUb7%pyGSMhhS$hBHTCa2vZTZi&QKqdNcJD z?b#Bz6}Vrb6!FWc)0oFFb==#>ln}JFN08of<|4!T17Rf2in$6|Xq{f9NhgeM8(1uF z4p>?&hhdH=i5$5z*MG4uSsshX$GxaZ8MsskfB{10^gBg49@}ac!xU8?Us2oBD*zAG zQu$aO<tI>aq$wQdkgF5R6e+lbFT)Q^wd`j1to}`p^Yj5R)`KUGnxg;plM&XgH6(sB zre%<}_{)#`jton~yR5KV4zo6xSCxtoZdl;K>__h1_8U64J`DL|os(}V429z4I}XL! z+MMtwoIg=@a(docl>!aE*Pqs>1i^nO%>97P<}R#F_882|`h?6;9y2^S_!*v<$tq;} zix_tPDnLp{#><&kJGgIwnr+;APrI3|o4DQ8G*VG96Ek50T>T?-n-8P=@Ab&$+b|nK zulQLk$_*|JT3ku8R!tAQGpI7yoX7X}<4M8koH@)P<iosSJ>``A;WiEP)`Z#%=?(&Q zp7Tfecw)3IWe)}12>9)VJr6klUxZfV7j@AcZ$J5nXqt`CXKitd6E?k?Q6Xj;H?bM^ zp<juE^pM<=NWJ8>K_rJdRQD~s(&!W`p5T`Heo+6&r#QZo%BncE(l1e~x4x9c-_^H^ zN%wfZC*<6nD4kT6ta5S=3+q!B954$3k`!HL0G9=m!T(pmjk(U>k%RPp6w!A<BH#F( zF_m;1m2+(+N2d2*zs5X5uLiJRcEFqvR?ai4S_!klXeuajo^H;<f!O<Bo-AS=wqwA6 zg#woD1&s|Ptp9HIq_NIyOemI@NdV=GuYF~px8oO$Ix8?nsHGy|8P}NHz0FV`f#Pra zst5N^RB)yRtOnc6UcY0Oo^hNgvlM3kz$_&DIC*u%KaL4q%lu1SM@IK1K#wzi#(DM) za4dK6<ig7ex7T+N34|qSx)hq2_eTIg2^#)7U%}Y`G{Po&@#qg0iLeRc_5^18yv*um zhZ2oD=m7O1VS;gZi+G~!{ynBhZ-TY6u(R#fXi=pH>Xj`r2zV|4QK8Qc15KKT${chv z09;3#dCTgf(d|2<Z1O7f9iX#9jpYnsAF$zXuFbMJ{9@?28O`MlH)kULU>YdoY=J9j z(KBTv5Yda8*)(q?NXU%qp$<1dR#dY|B26OMj|ue9$vH5~#y#j-%<MMT|G|>Q#_UrX z+h@Ls9*o>zc5Q2eP26D9Dj^A;`}j#EOt+KiL_K&qjxJ@q4v$hq4#HLFfYX;dowQAS zJ?(6_$g16)XG`ei<U9_O7H{vBOjCHPy)=QP##O5*qXp$OWZvs3e~42MOHkWm>n(mm z%<%J=e?6ZIOI7=M>*0d8X;z&sZ8BRH{ggG0x}YqQbg1p(jN98)pR~4#QkmsF^ToOb zk?^ZMSPzcQhkN@lS$eMQpH&&%7mnh;uqCHOMw-f13VEk?*PXMEl6X6qoBqkt;zP!M z$78{}J05%8=NZ&}*f>cH(W(gO-VDWA4>3ld>*l}-VlL7AXHJ7h-|u*D%&}2R+*`Wg zj-NpVhh=XHKAd)~LVw~7U!<6^hZvjD2zz6rDz<S=WUn`-?&3_KyMU0}Zxo?a%i?4g zrM+b(73bJI!-8VN1TLf<dUDzOR6%z9*YI3p$71XQoU;c3>L=;);Z2osR6o>DY!l%R z!NTNLecrd2r&SNm&sm?qhxAIs)v||WY(3d$=5^(MmFBUao9vqEeT#85h@(WaA<H!T zkLH#m29D0I9yz)PU>CG%_>bTF@=DMqYbL|_mO$Y1@*MHi^&c#fn+j*{<+cr;M|>wS z9hX&!U>@=Zi&{?q$6?Z7-AKTKytCg92q$ba%|qM__W5K8cE;3PKR0dPpr;*4a$yn3 zZzw1Ujs0NRK0iN{TMMzfj(#A|j_zms=?W9!tv;E5cZI3{!4=liIBYpsu8`Vv^!0_0 zV?Fp82(QwJK@Fr37Pj7YYCLb<z)*O?z#zcr+D-N$M;7fpFJ3farEYmhye};~Y?As? z5MyY#I!5G-((haVCf~A7gdFH?!+g4d-dr#R8$c6OCJl=2)B*ZV*v~wMu5n;?64#7y zkmYK001~mi83pFyn$TkqGOU#_A^Q;01o?uFXRx5F`Nku*SqDHFtpG|FO+Eou5={() z#zWsZ=wFT^LLNjHc`=U3bkN9{ap*6H)McKkzeSIx#cg4}vi)+9W4|69-T`Jhlrf7! zKUnk*tTO3;wr>4-)#ZP?YMhTeogT+z1)UL)|GCKj4o}h;6Ii6FMRAc`8@eMQBxJ;D zfv2|7B$?e{CJ=QJHN-qlCIDzDw_JOb8<vTomjhVd<jI*z@||!JKHuG~L<2w^5v<`U zVKwy?Y~IbZT&F<>chNWyKJLWv<WtWbB>Kuoh}8q!x_WFW`Gv#(#U%CGJ~j^MM|aDg zs|QDrKR0Gi{9uW=1JIm!R^k?;DW~fQoahHqc#xH!i%6S?-V79d5}c=Vs5V@?{_#a$ ze}}6#UR$OwL^*GZdp@zDys5sIY3-+{yg20#bbvh~2r_#Zn0^${<zT8C^V#vAy1e;s zs{D7Q_=^%E<9^XQSo<%kyc=D8dc0$M4{!>0RQZ&aAW&t!pQ_CGPieB`FUJ6y{Evgf zJBa@|MgE^l{GX@z|A8z{ku!tRVyqN%mF_-ae{H%7?BCz4-=8YOgVtvhLhQ?M$4IeV zNS*SP>9TO;x^lbce+a)1XUsdP@IP3e*Lf?kED^P7y{wZmQG82EEJYK!W4=D+q~E*E z^8W6w>pAAmE!OtOy{?~Ism>?fR4{d%<L-VAa<1Hm8L5P+uXHP5hmV44j5x}33%`Au zrUx4Q-ct$83b6Kpjm}%6>ok$T=D#_)CH!UgLEb26-8K$j-TYvA*Y7o!#0%}w5~LEW zde#grYLAkl2lNnjHtzTCODOESucM~A(qDp=52hcop{6;fdfTeMk?6YL<Km1LcnR&Q zfmUAn{ASVko0?d_Shxb*m64`r8Y5*tS>{>Xv{~8al85Z*nJc}Kg(qAu!*46RSar}C z9IYUGme^oP%28U;Viyw>V^t`Rj1u*Y70S2jisgods)A2<N18~IB?!k$#^+T9uJ%M* zl+xsqJRYJ2zv`cPXreQRGTGaIa`HKs<NB~tTqS;W(T@pR@_)_5!r>ky1}b+MssLQa zo%?%?;-!ARgYV`#?EF5ix#!`<asl_gde<jjs9DNuVYd~=l5~Gi`H5J<Q9M?%ZX>Gg zc+z{zxl|dMIu7@Oq4+c@>A<}wY^M3<sU|mD$>pEk+GafTlSpI|TDw$bp%-q3nszPP z`z(W}+3)Kv!sQJ{@^i7&>t_x02wfkZ!byW+bFibjiqFMk)pSG!EVCZo>ntpLF7tbI zb;6pKC`CD5Ge_6sy{=ek^44#6VuXyw)|?8@So$x#Htw$PjOj*VU6SV!s}^wgOXS|u zws@Fr@jSTI3jmu2`1xh0$sKiR*UbjG&KXF&D-FP>^xWrFQJxl+ic&3cxqIy0n1>0g z82>8aVsVOfm?KS1(xtT>D_ykMaXjB&gm%7odC(0+cppKKaSWt{olBVA{9pczFpimy zTY7*PFyv=S7;^wZH4Mt7H$ooO57DmLk8bns1R?N5_+?aISjk3Yry4*{7une+lGuhS zsd8i<&hmw{VUj5_AcDMDnY#kTQElo<B?Fk8js*f-3h;i9#98c;tbCX2F%wsA1<%=m z3+6Z90Y5et8LsEKjjknfG)=&QD$kVT3%l@VFN`ijd-7x#AH=F+`6aJNXiGgFN6zf! zYf?Y|`Y>E^tH@{A19!PnU#BQTO2x-|do$uJws_RE^O5V#Hkn)cdNMK=*V~z8$y?}& z&saISx;^te8I_${H^JezwFoLp0-&i0nk0Iha-_;Eu(J&JF~{64gsueuMJvTa8J7(- z1!}*JT3F15vJxVvE%Q1X8~3dQ-Q{E%2_)6a)BxsYgK3JfU_wZ!sV`2vZ?jX}FQdB$ zrjRw2L{RDK>m6+%kSZm}4FN$lBm1~~&psi-C@+0SvDrg|tsixsRwtf57<zi##@6Pe z+fxPoeT8F0cIvzpB`|3sopKp3JrX9-)d5RBGvOEDzAEk$bMUYwJ!k*f@Zb1wyH@?C zBQB;)y&YLr!S)ny<}WR0CKVM2pdT5UcbYp_#+r1)+h@A8c2T%8a0{#0dDH3}In;|j z0>8x}nja9tQU@@%-B+J(*jNfJ2d`zLPSBOQC(F+IWmsG5qeWtgUyi^8MBC2|9DubX zzw1v3GpE|iXK)O~bPJDJDrLRdGCXrLrFl(u*J;hihPPLJax&iPC}rHJ`0nvN&4l({ z%C`V^K05P+_@_czH$BQacp2%R`)wW~fV9XZxiK=Ym-jA77QYpRpXa|U{p~J$quLa! zWgO^@WI79b2|0GAXy42{aW=|eNj0a>Eirmz4wZ&#N3YlmbAt{9ub)BBI9wK~K#d%O z1VG3jH*%2LF#!oxgzcl=Z|^N%)V=-Xu!Pqa_V+6*f<jsE3x!!E$}mqcBIVpPD3ZUN zvRN|(J61IwjQ1&`IVK^lI-W+IVn=oFE)XAcrkbj%neN%0Zo0b9fl0HV-=q)FKERpt z2B0Hdvoz#P{?R<pSIQ#u@7vGk*QZ28AX6PEQGnreWD<lL38bnYEakV>;qe`>nR^%_ zQ|R+OH}uewB6Z_>JYKMFyb%0O5UeXt-a}KzY0ISVjpC=Kr*{^O_q=0)vA$RAavtE4 z7>T?Z()anRN11{1WygxsxA38`WL5bDM>|-dK44SUk6bC-^JG_*IxOSC*NMK#x0YVo zdX_zkG=|I_46J8isfb3sa@1nD)+Ta4%UJdl0AF%f>@GZNsD3UrB=&^um-3L&Q7OC6 zG1Yp<9+@S*`ooA#EV^Eb<B7DiK7bThx+58KMKY{eUogZt@>$g$z>STE{#)yZhy}BT zxDwg17gS{gFpML;49@W9gk;1&$-OU^gKW(ybI8Uf^KHj0@xOcbiC}64_qa(ed0CG- zllBPCgH*}!F8QN#Ke|Y<LTju>v9@;N0=v7a>6u!D<+GkO4W-pV1MH}NX4P5ji}pol z&M1Waq^xJQ%M>T)CT?2AQ2G(F#iX}%t-q5<wp+1Cj}g~;=s8$iVp3dY-oEYF8DpPX znasefYjR&AbBC`R`kD7?sNFBEe8o8!j<MltEvR3$M3|Ue*GT1^8UHNeQEKwL#zma5 zb{PVfifA0#6>ukEE-~)xGWb-wIJ^}YLOZW@)V?(6wMVuGffa@jS`J+=gC8CxnYt8f z?GNF?9q-C5Y}qwXb4|I4fA4SU$Mg1U33@~IsE-rAZwAQ2^$NZ!8s2ZI<MoOP)kLk# zS;*r_!}m2V7mnnAYmC&Y|K2gmF(jM($*>r^I*S`B*+QhuwggcQ8y4r`h^Yh@qRi~b zn%2$K%7p%Mf%lf^s>^ie@g%#dLaJkpNk4yYtFLBa#fMq!qD#K0cYKW#bR{zGz%2(r z%yZyNmbc`1K6Z@b%Nk?fOm$q?SR(fkJnd1JrJnuD+(xPU$2=Fc7Y{n*Tg_^otuAgo zf_wtKVfud9{0bG)R=jL%?o3f!=~QX%%5wK=!Acv?rg9v)p=z7Ee(@CX2G!B+K|`HN zsYF=Dyy=DZN-;c5tX`n*R>b+*P<C$KrFX*;b$hinYAg42t>f73&0lKm?o;COt*LUe zG^ZXEC@Vp0deCz9E3YMn7336_KhkBpUmIY;Q`qz<o$=iR#W?$YW`013JIFD8S=_^4 ziG+~XEb%}3Wo0kV#x?kX$`eE0w5#N`1g%We_HwucdHb5ja{=fr8ygu39#`3~FgG#3 z#P3=b`)*#5q2OKblW)}w#pjp#SkODvh2m}lu*1w;b03SAHjodswEGJZ#ec5Bo-k$D z4VfSK*ZuY7&`Dy$GApwkvd@X`PdU(Cr$Du}G8fXCp3&_}So^kL7gKaSNBat|Enoe0 zGnPFck3B^!@_~dFdJ<$>u9JSSq#Y+*KoZfd{Y227qa{Y=m?)tiEvrQ-P+ce5j@DbB zD8s`+-TvB_Bk!GOud2>PafUUHT}Wo%M^Fd$7hXuU#XZOF6x8D>HO0~xD*DzSQ^Y&y zdI9y`q_Z&M1iG3x=MnGmBW9yMUXo90?N)g`N)@;(D;^(o{2Vc18kk0LH}T@Hp6hBE zms0d29)pvtePL?v3<a7vL)yfy^4N&K{UW$HX4+C|ckDUBmnM5zR|ju)I~ui7q4LQJ z*KIpU(4C&0?sd>P7h>+aiKr-DibC0a<(fEq039rRq?>Lv0paw1QN1BSqGJVg{VWXh zAG~(9(+lK{G{|$Rx=qf^zmoq<12OI>Knyf$!`Yh}rcv=Yyp+5DaRUSUyAZn?>8+~| zXkpPMuJz}B+e0S+@(#G-?T(Xa>eknrlpa37PnY3~5b>i!B)@RJiaVoCjxLO|4+(Kr z_=34&=IO5Pao$?P^Gl7DJ?nma3-?#PZDk8s#yL&03g3TxMN-3VUzs2G3930l_>Mr* z6LkS8EkX2sLoe~X);Cs4X?pk=qk>%##(R8C+pS&vx<E?3!YMiCx??ep)GIzzWZK%E z{P3n=u>ouqL5N>am>cCI<En9o?ahThk4p9_5hVl?KRZp8l;BH3w55z!cbAowet7bJ zFWZ;=ng(mpqUa5;uO9aFZ*=G+`$;Ps?<)JXm9IhDS0_{?`%c4^xA0GvjVlS^ZSn}0 z{I0HD2&clUcXSVly|i32y7TU!n$o)!@6tCI1!sf!lCn-S`=}8R3JqmtO&jXmz(<>y zkn*?Z3!}D@ml2cjgOZEl<IX<ovJS_Sg-VLPU>e^n#JEp#NQ{()i-9b!`ix+I;1(V; z?RrIGGrv`C_c5V~(PoIaAIfP4_d3aVSq{tC0M79oY{0Mt)m7S28~~u~Vnc8=ao|!L zSOAwA_{Tdgv=8`J!cP|(w;yD+KM8}m4F*mCu_*L@HG&$6VemVCN2?H(*4Y+=htT#F zAl=z>2owgo;gUY(o49^&sU5yb=vLusI2dNnHtj`S>D+PnK*iy85nw1^*T{U)Y7a*9 z0Ayp{vZ8P2G-GE51qwJ{+9t7fK9y@eMPO_r4Uh(D5RrXeU?3&2!xyxX{5*;xpn0q} z*C6g}pb!ToH-xDzl+baNmrNONh5CdaETLFz9-)&in)^uLWRcO#lW$rYpAGIF$uBRy z)9B4JM=bPOsG;Oe5EeE(8VUCDLw4hPmoR9Fc)#&Q(|WhTttXd)4TjzvGjQ<=Fx&m~ z>POZPhASiKR5;>WM^%%wY_PM1XrT7iU`0*`tgw5+y|5&F<iz*qoVy*jEEK^IAok}F zAWi-Ui$^At2cW_c$kh-b!t5GAiNVlS`$2}8oeo-r(z+S>X!4|`>AVtX`@lp){vW?~ zY}b|oz*;&@8Dd7jHbBf%6Xt4(jzHfB;H#CqRA@dm)EFG|k^EuOphw#9u!AoyLNd9F zV&rn(fN#9B;5oOEA*#jn4H5}Phcu}{KUnS>?93vjvE!^c+E8{{X9r*IxOs}n!adkE zgpj>&-BQfM{K0R;8aJ&(Plde`&{KuFlC*=nZY>zPLyl;ee(;`|3<{>3rFq}dCu_xL zTW<Aj3&%$k4us{DnI1@s;t-U6UGN8M$ix}kcbK!h-NLptKz+07n1mxB4@my8%b$qO zoAbq0)(vF-jp~|>*ZLkZxf~V_NCljQjP+ariJ~t%cy{glC6@=Hr{qtk$`r6DgixBL z#^?Q{3$mRP(2vRZkptwMm@RX(+n0@*5WM_;$3g%6SFRH{4hJulP3yx&J$K9cCVHKV zI$b<ue7r1cCl_7CBu35nET&fJpK9!LeCwmh+cGIyAq0+PB=FAJ9|NWhL{X#SOeue1 z`s;a~8ncXsZ^h#p?WSj6oZMF_pIV`2J7+rm0SB^|WgC^H>JCFGiw0UZ%VNZa=2u;4 z=G(JfpBA0D%arCLUT$MTG|>4<xEFL&G$eSb+vu56?wMnxiTZEm`1F!nGA!aMa1HgT zR(o94E;@94@62;24e2gw;x)2urk}?o_DH>U{vmUr3%4t1j_>8lZhe2LNT`ZAnaiUz zrfA}!0F}<kJk<qqt1a8U@y6}%=Icue^>axX_$?&E!$b@B2?Vlk*oJ#q+L=hzZu$+L z{1V4>hn3+v#68)M`c6*fGi}lLv~I^)2;0`;j<CtM`x*HARbTXaiBPnXgMh)yQVKM1 zxm@2-EcT{_jOM#ectzTksVkAqEf~>wn+s~!MB9*RdX@@yLbrK9N!5ZWSn4zXqVz-b zN_R#XlDO7^&CAmgz;KUT;~ih@2zub}O^upfz43x}lkaUCBU!dH{pf|sg@r(#hh7eQ zUS_F&FL!k%GiSza2_GEz(a-aiiYg>)+(=%&Zn(jveDRMFwBHn#C2op)j{aWjETX4g zg8Z)cP^0duU=GJN=z@4LpB->*;40?Shd8=Y8G48~(F1~=Rc^tZkY^qDTzFT1r3ABc zTmA)IWisLfUA-4~#3a;;T$$cyx<NZsuwQy5<>{cm_9?<8$oNZ?x(yTdr=o?r!X;4u zBw9d@fkl+Php@QJkivA1@~BVY=!lh9|4~n&^m7pnh;2>C;0y@&&eov{Z@}-M-Xhg$ z;>;!mW;^jPQ-a!HN&$Q_s8iI;dW;RTw-<RME3_qEtNByjgQg+{!K>P`umkUH1Q~UD ze`TCBZ6x4{3r*Yr)2yMY^fwCh6;dR}+phM8V}eO`ie(<Jk>%y^tmg0fH&vE6Ki_Rm z7gpPz3t^%EF7h#`!H7kq7_<18t)$i>gp3#z*s!8v$e6KrC|L@8QItZPaETZC7DVH% ztCWvr)(v$2;da#Zi|>nX{mXli;y?v}iHPPw(>QcN(!9cLl81~ZRLL{MlX;JpJv@OS z8>~RsV$6o6WfX*;az-2Cbf{(&`C14&O4XhTAs6u*0<y?gmjIb}y*+!B<f~69ZyEin zqR%>twa1qM`nN|}o6guJIXOF@jKlBshFkB9Ls=fI2_9fRa1AOng!nESxOcUKQb6o1 zT3oezLqFTE-^-+H&}@|9(KTq%nrp%2BNKv=4=1RK+#Dp8gwaC9C;B`YIZIx5I@6!9 zeaaR2`owW}Md3I!jDDWHS|fa>fBABW&qPc70#-5CUxI1|b3Slg?)#Uc73GcWQG<h; zWnLGWBv0C@1Y}<KxS6#mOz8Le+Ru75=4!Lj!xmv&lVfJ$fKRei^z#co^Bv|FJSQbt z@%~8&3dguybf$MX^*WquNFrr|W8}I4*CT=2z@_@7_Tjorj6@$yWuZ_Y>m$>AN#>LS z>lYsx*eh$1&y?`!OkA+y;_>Q+@pWuqP<BfOBr?NM#HLt(Nyz3^y2Ji(`|`2y=BpRp zor)Zht$giN@d?qw6hd2@C%<0F({QT%m^fsB@`96@<`^YXA8$fK@PcCQ31%nS&s7Lt z^ssu_>u$&w!2Jl=hM<0SZkdiMzWx(Frk;fw3LnNiOAAc+1ckLp@Q1U6qsaYslPPGM zNkb0pKJ2>TK4&+0^l!;m=(=3^Lh-p8{-MI%D~tC(rR&^h{la<PY`Y<({3Png?5Jj} z>d`xW<@!6rU!N-CT9o5$P$etYyIwC#DFqN%#qYflP8aZT7QWnT?136OtG<qw>sRv8 z5*aAY{m?r!*mu1pe{ra#(2o$lDHskDQX^fSCYHI5%qKg}BdB*qIVh5$?k$Usb!nFf z-R1fdQtm^vvzl1W;}?boK_`{&w4SqQ$WiHGmLtmEn=1PWk4d*CmTQs}CQ<PoALdH+ z!C0STO2>p5y1?4Fv^x$~5_)T-l4V(-RZ{Mm?iG}CP{@szEKUDU_%71mCh<dUgH(;C zwWvACy)tLBL<O3rC13Qhw4$UkcI3X49b)5EOKY$W;&vmawoM#7=85mSyGNw@yN!@n z$br}~cDeF<uFl!iF#2gNjGv${B6d}^51W7L<%P?K4m*7cxci&&t_$aKEs3>Be$ajZ zQ|qi^6y1<uQZ~-pXKipR-M*`KP%gPU`wBAteb|%8wE(aBj4Pa8f~&pNH;rzFUD{ae zpXtuuap8)0zjnyh$?<c@wB9DUlx=+@C&(;)L+X!V(G71ZpG`32R*k#LdGpUU1mhN6 z<WX%wrbV&PsCJbn&tB~nm4J+kNQYEpQfsOW#%Ty1=p>Aj)aRKj)%l(xfl~>ZjznG( z?S2D?9^rU0b**{8%tZY6ur3~nvg0=lf3URlBH|o3Nt-@I-Ac8+l0R7Fd&@}pd}hBP z2BtoXgn5i>dbZTWn&aE@&fgg!>E15!EDctStzTSJ2^jf|xu|0G-sO*xu=0L2_>BSN zZ`6lCa+om(vk#SlaXkU&dlGM*AJ`qNlvP==kcp|Ed~j!Z_}EnbVuQ1Xc}Fd7?<n%p z2x0=hZ^%j_F&FyY`-6ZwDZTq)61J7&LPdh2YYz0{B~g8i*w6Rbcey6E%&LCK!Nxg{ zG6+}@VdTlCCgjIPb{mc|j4RQ~5x*b(qf#<@;$YnP!|tAW->|TX#dHz-h$FhLP9-;# z7l$t2_i#GG-p<YzGUZ4LGo4@yv}2T&t4;C&>e+1jVqb}PN55PPQkS-1bXB^pvx1nG z`A4|g36?{y?JQU`4F~cDI<V8B#QMxfIM=Yfxll|5;HcFXUe)apjcuIce<sf!5E_gN zH-S2!dP166L?!O<b7NvtJDbj$WIOlcV(6vOvL#${DD&(m&H7f@n^!wLDs$!-vL$xS z#<+ZY^UNR(9e3>gVRIsfw;bnvJ@iQ10Ykp#C^h{<lWKfbReMbPw>xUNgKiSvcWHQJ zLMM92z3U*0J2d3jLMUkU5HL$|5Lechvc+3`HjX;_J>D}cx3Qk$RV%;OJFsEmiAv~N z9ll4_nZMazxp}&M)2KAap!h|zH>zz)DJA}dlU;DF?!^brreD4no#v%Y5nBrVX#<}9 zOI;ss1ilnm?)J4Xc1~RO8xbFXqllu$6<U099yAW`53!?WE;o+f89Mm#qrkHT=nZ2T z3(!gwIj;xOs8sZtQr;6|WOWdAax1N_M&0DaD(K3O$V62W1#Q1##e+6F7}(TT6E}k~ zhvisqgg-SVQtyd`6W4sv_ztF^V+h0O>#zBNKYQ=50jK(}-Z|*KD2f0918y9;u*vwM zvbdM#M2A-p2ocvlkvC!{)t1Ve#7#wK#Lk5bJ4tu(oIHLb+;KA@d(>gW_vO{NSjzCJ zcUi7)xLD9?gu;>qbxPdWW;Oaa(v*S;QvyOgWcdxuhIvEudsJ$?GwOQ@NFO)nCea(- zPUqe{kr@GCB>i)kMZRN?nf2Beu0-1C6<O{*!8&6Opt7MAsNV7Cl?O|x1l<*;x@X-j zQ2d{>2W5rP^`z;WAkx}KNRfxZxc@Q;q<q_VKvGaYBdZy|1dT4gKCc8#Lt$sYsBOOm zVy;TC6CmLHGtdGg-1F+K>3@Qx%wq;XBYqeEvRXX|8t{5NYzv-41p78L^N$yxVh4cB z=OYMH9;RK8D2UBCFPPhZvyM(Y$@oOHTRc1ta>+*E%F+yxfwnVPe><8(F>#Q$CW!gI z0qmSWop0O3eNz>Ji=}`u2W6B)-OXZ0i|<>f4caFFCut$La`0!n{npHvFxXB98=wdJ zdAVyKM$DMmp$_UpfDkchStl647I;<cbMgJT0dN!T^t!2s0D{rhoqP8utpuH?3D8u~ zO^IN-umXg<x{o$5l5qot%xfK0@by{rnljD<_notwu~9<J*ecu>*a_n@Kp3}^l485N zgZc0u<EQ@lw-iF)JxWA1)~!b6AZcHQ{l>}#<r6YeY;64rL)<rX@*Zp$DhOT@Bwdy9 zjHhF7z>A>F{iLzBhJ8p730?vHkiaQiBO}1T2lWuTngF^Sf**px4}fbnMWnx?uLE|k zOfY@ozf6y)o0HiHVhWMQh-RRn`6O`gMaavrecM1#pRv);{AJHzbgfi7BtgUvm;;J$ z2qOiQQGLBt`p|TC$T*a)-d$B$2;6p{RR<swd?1blpj}%kAk{5GIp7vC9W)BUf4X%l z!5%$6n#{G1`N6WAdj~h_muron2Hqj;pu>ShzcGle^KNo0Ws|T1;myJgicq~WU-;XB zM(Y<lja3yI0`m~&9uWWlCK@Zxd@c$+NAwE#_rKY_Y4Q9MOdX^eIbuVZ+)=$8?h6ZZ z-%LU{=?1SVYma7JzpTmS-!MqfYy9-(;kN_c4*L4_+qpv~#M=>lpHGX{KIHSO>33*} zuTWPcG=e~7y`um?2R;1{f2jt{14lvbQ5p=u90z)+?Mo{zM@*uttyCr@t5(Miji)T& zMPidSi|TQzGu_cQOfW?ms@B6zxC*81WLu9H$@06*U#h${H(iCUO6sA$g0=3KSMsYw zp}@;L)B+S)8{~DG2wO+VXlj63!>aBwdI}{E#24~ck^5DsbY<a;Js=nWS<fk5rs#E7 z`d1opOC+?%bdme768Be``t^L^tiiY5p%t|@nb3)KDY2|QQEb}DF*G2ke-XW3#jEy0 z9cbIV1X)2aFF_`b&4{#dR{(24t@z*GsR)I$;3q~}BKR)%|LdC^4{qPjcS2Rue%RBw zY3SXghUp^Pf9|GvXy6(C-+i;a{|@A40sfa;#RH#h4~^_xjB|W!{T-QYTxId%jdn+d z$9JaC{m0ZC<A>JAUq{od_|eS{2G!-G3OAnwMwEe-Y7L?TUWN*=#kdFHmFhVf8*m^B zX8ZcSbi|yv#@Hu4f=Wf}?hHx^^V0OuO$pR)W(5#dU2}R6Fk9=yjcBm4T%eRNe7OPg zDWxA6m?5N`X%)y2@XkgwQyD`%26RYv#*FQbfk6@h|MV!~#&<2Y-+NXoNWfgQ{WKRl z_+Wo_P7?uy*q>u-<zOK6?>6bWDBz$T*hyl7-$%D?0&?kw0b)VgG9$HI2R+9QS+h^g zW!8n2Z3I&IK!*ZYn>zudmpd?sTSC2S5mOO^pVgUqx0yS(vUmuwxOW^!V-*4E)k*Gi zrlXi*$aCba3HjH_f<5kr63#kZno22=lMe+fP>;1w7vRFdAfPGoH!uL=vdW~vD7bE_ zih4`dgEfa<+=(VQR4jRcDksrgfOorCn0eJu{ZVvr<0L3L0DvE>AUaq@f+1^XN6|!w zA1rlXO+P@G;AU`mVKxWR6l0LAoEHX0Tl*YXyyLc#*)}9>0B40b=(jJ7SOwT=^B;lX zv7)dt1IjvRi;(&VsxeqHAhQ;rk*Ko!2TMpA!=@QMEAbNp@*K0a6+KhC13C*8nWh1Y zJzd64H6|WH|MGn%54u)l`}i_sxd>p7W&zaE70mYjpQxkgZ}AayY8-QSJESeGmFF9} zI-mLiOy7*mFg7rgP`dPTu*jdc0w^o;d|-?{HNaBAr$v6*4{(1}u7f>s|JajmEWfj> z*fZdUjZCA7Fs5|GdV~}(yT9+iiPkY*{SI1xU!lij8IKqsu{_m^1naLguxG$+FsI<2 z@?TF$VK$8(>RPw(EFwJbIC|-d`2PE@kqy2Z=1iN`OuqYb&2pqBrW0eHl~+(nu{Xis zCn{X{PgJ<SLAU)K!tKB6Cu=p@0k);UEda{i;Qj!zFdwp+kxK<$=p+8+g~UlN`Ku+4 zWm^jr&flI|2D0&Kc;Xswk;^97RkZ}lJ7^@P5{)---~$K8ODzAo&A#uw8Qrb)j_}7P z@-9mxrWrPgcdGPEBC7x~WdA)NR%QPXtK0wX@uMP`1>YfSM}Hzzl0o0Wmw&uw!0K7U z<nj84NPwvkQ~HjyKl&-{|4P1uzzpYqe9<E0TqbapzLxj^{*TNbEIiQdhPUAJwH^4~ zd;j*L<>}$-Z5gXFe+oAn5N-kxZfXuV^)HI{PfvZ^b@c8IVAel&-O-DmyV8N#`cp^$ zDquA<-tz$G@d!{cGoWw_SAb6q1E0Q~K+ksSxnl|%o&z`z;_J#&Jsxcm&RSiDO83I1 z9;zpz9<xY(OeO4@d~GOr+4W`ypOjukj+e#hje|#1Ov26BZ-<8VL(@husnG+2!*5*9 zPW&F8*u(#VCJD?sMgT$EIFnj=Y5O;3Q#X31eu&8kfqZf&Zc&OsFZq3dDfs{M_T6)r zBkPYS-PZoP>#5Wln0DQnc>O>4m(yMUwA88GlsWcBC4*m|(Npe)Bo!vonXvpV?Z0%p Y<n#8vZ_#_pjiUSSKLZH%Y(ED67wNx<^8f$< literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/frame.jpg b/OpenFAST/docs/source/user/beamdyn/figs/frame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4917f4d39481eca1bfbfc51471926afd0d2d32a0 GIT binary patch literal 40985 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 CIp81w literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/geometry_member1.png b/OpenFAST/docs/source/user/beamdyn/figs/geometry_member1.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7bad12a7b17f3019260ed464812379d44190d4 GIT binary patch literal 44278 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/geometry_member2.png b/OpenFAST/docs/source/user/beamdyn/figs/geometry_member2.png new file mode 100644 index 0000000000000000000000000000000000000000..5f86415fdc3ca7873839838fc8e51792e8556f24 GIT binary patch literal 50845 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 Kpj657)&BxgZY5Iy literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/manual_plots.pptx b/OpenFAST/docs/source/user/beamdyn/figs/manual_plots.pptx new file mode 100644 index 0000000000000000000000000000000000000000..5ebe73c80ffc68064571bf771415ef7e18bf42a5 GIT binary patch literal 2924727 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%0AF;*)Y+}oB2@QOd<$=M>u3{`;BkLtm?fmZ0 zp){;gT@Oje+bjxoe#h@O<7E;p$1-z5|5JldCvT0dUs~mq8#4YlZE*VjoAG+7!JJ~K zxPIEsPIExM^{$&=d#I7wxmPJKgEs6RRoEUqjJ?3y^}wah#(>smh9w8mb{>kQb?@UE zJ(030&;ob8>kI#Ayd<yR?u9zHhZ@S;8ZMe{1=mACS}6}<TP`C)q;}hOt}3=LDrtq4 zv}w;zV5<Pbcn7~ZW$)!BB<m-&1jZ&M*In8L>tU#4Mq$KF;Jjm-Mk)R}a7?j-5Rty( z?8L*g5BMy3yyfV3*p~}@<4*Dn@RgyS6?`^zA^LNqU-{Bmq@(eSC)QIf)B|RITbc46 zK;?6rs(W>vlWX-$yVZ@!<GW7736jdRV0M{!_+9GWaHF@h;iOaQ?|vF*nNRWhVPma8 z{xhDuf;S9ZkQ%$cVmG*izJsNdy!q<crm;Z68-TYOisD%0($LsI<34{I(MIC(?xLKA zfA}T2=Ec&74|vf+aO#@%*Y?Lpd%~ib#evNXLEOnl@=$?^z+?LHg@ZbdvbDFqz5h`m z0Vsr33n>?c3gmxvp!wMS_Zz0)Z+XxC9Lj_$3;ou+#LnAhg}091{5|&{n}8)t<(-C1 zijC0S-;M4Q<^tb9<Q5lF(L(iFS9p~uCQMGnSf)bUh>vh`Fr}i{Nf|^6iCJJ8#g?O> z_8GYIYzlg|A)T4TRSkqDxqI=X?1`^NXb?G8BfNui2;rj)9%KlAM0p_B!7uCbd^o?1 zB@jl^#7?aV;Ul+pM#V1D7r>wTrRjVCg7Z9}{#&<DLfga@14;KidVJ*MD+4S8#Jtpt z9+Hgkze|7oA~anDKo7r!zaaQCR&Dv=(i(7XW*husX%o+c{8wo)^j!w6Lqv%b=B5Q} z%jBCllxLVoKb8;tJL&*Y;%>2NaP@bPY0Sop8w()cZK>ygBi5pC+_nwfmWgLe(CJsf zGNKoA`PkmglaG%=hYxH&PJ|kdyAzfOc|o%@<Lj^aPaFv2_sU!fU&(}2i^$T8nY6Pi zL)W;n&zGE9d`JU|{m=3J8PsAl#Vep`DzJi@Swd1lFAb+z{^xPox7*jb>AzYq_u!Il z1C&vz^3}^#b0i*ygJ?b6EUmMbXcl_Yi(#1>*ee1q$k}N6-NS&7oDxN}yZXVcen76{ zixr@8dc6~w_Y|+9-bxO9ogC5B00T#`jv~nG?yAl@rc7sT6$R5B4~u)z9V8K3q$FNC zCr(|AKWS*Zc=^oA!sf88s6n{(l{kv$T145~s;n&r3P#G0@{DqMGrmvpQ+HRyy%U(~ z<DUsq7<h1!+javSuNd~{G?>F6pEV}Hnu8B8&-XK52AT^?(;l<heiz|l!y0#5o3Os+ z$=lL4!{>$rhp7!>mo9%&z;wQD48Zi134Q~992|bFkkN_{1bEaFbyt!K2N~t3eo+#R zLdOAM@Nv}fa`)4CtU;~da`E=0u7oAAdxP>Ls)OAMM#n2lel!dmjH58dZ<yq0&Xe4L z=Ph?WRabM<-ynMb+g8-|UB<|(KMSh{V?T&h9BLC$HkH29TDq!e|L8aK+>L=*9bgkn zi68ziV|PAs-Y9-&X|;n82zBm)-;$)(BR7kPw-q`Kzhk&7EJ3C<sEQ}$;s&BM`%9`L zBsjiYn6bZD!Pu)84YI|1N$~Ez#c8e4JHQ9G>_{Md4onc|xWAJKg}8S%`*Zn|<J<p_ zsP~R$`+wiZjUZ?xw$`So+O#!etG3i??M<!Pg4o2UDn+aI>@Zqt?-{D4c54K&R}f<F z(eG1V@6YddP7X&-<d5h5c--^4udC`giU4Sag#2Uz1-_*{%!CFpop%IL$aQFB5r)Jn z`~-QtgliH6GA)XWD#nVHJEU1tgPFsd7<UGxbX!!+fDQA7Q!X*lEqU;2{c`|zo0?d^ z6C@tEK{F+RHs`I!h7JS!^MkhX6|hk1_bJm_I%Tn&`X5*y>$cDhW&YYw5+ZC>fl<%U zE|Q#_?oUr@E1W&LXB^Vt<@0mzpb4I|RJ!lKG2*XZ(p58g@AbN`-YDPwi<A5_+1up5 z|Mfp`8f6elWu9NLt}k<NR}I$ZX25LnKN>_n-=3M$|81g~M*0C?Hv5W^EI_BJW+!~R zrZ(3*y(vWGrdqNlLZkrummMH)Dv8;UpN9#k0_;-+CZ)}JOzvwYc1yn&0k|k%y|!3C zoyRXNPZlQIv@Sp%(2>}cue$Ja-_u*jOqC5=kW??1ty_Q4dVtB7E|>Hc&Z3LZF&`0` zeh?g*Mad;WHIWtE*$QdyF_i<aNS>$!k;?s~eu=bYu?I<|ATnWq47u=7-7nf5!opl2 zAJg)v%T~79lH!+RZ&h5NnY2BU^juv2wVAE#t?g{n#5kJy2>$_>o0uVnp7~?)x6-20 z<eN9p_~orSJ0W@BR<27wU3`zlp!1}p)zxKe*)c`1N-fyGm-Qq``0Q5zv}9N$wB$%6 z#l=ttK%-Mk{{IwhnFO#hY7F(oB*5cc!hdyo&rgF6_l0Y2{wo_RE)jQ_KW({UJE>r* z7^%~X#E*tely^1(0{8poZmrXJjLC@4JV0*Ar)B0&-^(PWG?8GqwMB~w-gPlD&Pg<T zRVd!2#c6~9BX6vbhw+!vgk8LI00Ul{eI?q`{0Bf$m^O@p4oVPODU>@P-P6v(15xrQ zX##i_ZKRdFXx$E}=#vh~Zjx<KAHqK?FwD3hoseMzt_9BJCJ~lUA*yzy4!huqUExT> z7%xeUKMiW<v$B}ebt9Dc#ZniZE_sxhIbSf{#0xB2mZQ%}4UwL$1N5SSCyfBx(fm=p z>am%}72RFTVTFdx;EzLM?^j4Qw>zCj05ssqvANsH-VPC8_1Wo<nC)2lx3F)0gOqsw z^ly}FPH#WVY<>^>{C3Bj)q;Ly@qw&1Gmk&Dd}(rWnYvE8Fsc2EGmSAHg~tJS;)7*e zXdC`XEpL~j(>g9new#)ao&LXm-jxbLG_{TE(6CL#Fq0wut5HsU<9&qd>GiX>u#f*o zExB6AD9N{T|96CMV^M?dnPH_etgM>FLiI@XjRTQ2k3X!)J8-APyswZ&<TKrjX)@?| z{rtS%n6nZ4Yw0P#%$ULdGt3=;KaDd^^kS^GRygsX2U)N1Nlg+*N9Jdo*!EU;Z7-^a zC!BT9UY>RCmZX&iehf^=a>aE8#_d&e`0=1_L8ojiBqXdz{WGqZ(N(gD*|54)NdK^= zKF&GQ6()6L%Z9z=kj*QlUC4Fiy1#%@EQ%Zl1iVM9iF`ALG?@On*8osIKZj3iUkjia z8_6O1^2GVTfO@K5XynI!V-XwOw7)EP>VE(0w*9pD#|Zus0MdN_9o;6cP_1fBej#i! zSmIan(Is_BZwMP*F73lTGZF7;u1KT)ivLrZ^(6|>;)-02*6BG<;hkB*9q}PaT<t3+ zzo$ckx0%ac)=i@S*O0bJN^)uB`Ll@4Mw!IoCur!;PEAdYo*y@kv(a;T85ON_0>L*2 zP@C8Zq6sqT^%6-H@ZhS|7R<Fv0qSkt0syiXrV)zDnEh^^1%i)E4am=lCJYnBr$-19 z2~kxL$l0+ify=u#<~cmxsSOYh?mgoi!*coe5kZHoshLE%H;9Rv6v@)y9rdBg?-*hZ zPl)II832B}O^Igm!;qXM`tl|xIP-QvutFJP4@?GZs&?j(!aG`>;|Uix>?DT@`Z=H( zL&;mJ@Jzax4S$=atpObWClw;WM4BYNIllMdO@A{P?)asT=Y&5w&f`5S{CwZqi6~IQ z3Fi80b$ZfnWySI$v7K`Jk!_pNq{6r4OdahPkN_5R3qVsoG?|ohrr5}nFwV^X=cwv3 zK$j~Lnwj}*D{O4(rsY*TUzQo*8T8$s0=7;&17@pmaxL`IML?e1mPPjwvcW3nKKnl{ zv=Uj<i{6bqL*7a#CJh&y$iTS#UL>T_InCV)_v_DF^vfqk?~SJws+4s^ND#Tc_)cHi zXDjsgRe|-1Htcs?cp$$pw#P5JlNW#j+L5MNz2=|u752R0*EiJ<@XGeb5t5UQU!PNT z<@3rstB(cr<;qjPEB-V!Bk)-8);})gO)J}<P~`W(hGMhR+A@_UfxQ(zIV$^%*f_$_ z0hT$+Ie>2-ydru<whRv=w3^zm2Rll1a}3!lSm#^lRn79$byZKz0(Hn%e9O3-Eng*{ z+Q-0!mssT{#zkNv`<QgagS!EC>)xmL<Xf#5x7=g{kW-YGA%2t4h2FJ*cn1lzd<OR3 ztU|tUsiA4`pES#ZbG>ZK=8al2ndurl`d2N?&HOCZzC{Yi)qq|jvq}LX5bz7WOEuA| zYc*{Jz}ucJSNlV!E9fi!<$b8;e$)xotSIC^5GLo?byyJ~zl28@2U^oH{#rx(vTS#F zxa6$LH2+v6_zW`7C4IjTVE$|n>>mao!}x0fiOjvVh?m<-K071izbYEoH>&;PjII8V z<5TNhL<s-#sF;x!7~LW+Nc%{vIX<jONamj<R$jKNF+hm*{~o8j9ZudKtEgxt>&7Z$ zH6uEEZx$r$>;NE@m-WwXBxWedpyDoggsgJH7`FKtUm@c-ZOY3qB2E#(ZwjT!R<iu# z+=(D*T~d@&1LkH#a6SOhgI`I!K^UJI!9w;^x)UtA1Ud@q4wgzp_Y%cqTAIDW1B`6B zQ#t9Glpg?PC?F4IZ*oIZJ^s+bTVEJOV98sIecI$}HLSdfPk9e85<%`L2XL=V#~m<1 zdQ=hG9lKnCe;joM$Z<OqXXa&ln-BO}Z!wpUk)pSIp=enJ;4nKU$nya^CwTN^Rn+*` z!C>*}6R;=iSptAXus8xMyIAgfzB1wg0%It4Aa~L~u<*b6tqtY_*)L@m77f~B!!}EU zvrbsyr{c!UdpShaH;11`S>-0lw11?V-rF&8<JUvCjWV@0x*6N{!*^sD8!hdTH>}?I zmjbW>tXBEosNhtnlvRS4q-a+}78#YS7{(#8%~oNF#RG}nlqNXbW>fR>7y8?jA($g{ zVp_J9_t71TV|g2XW63rrY_5GSx?NXvFoSl*bo(GwS|%swQm7Xp^^5QtBqJ${6dotr z?`b8ns7d@?%fnr|eR|l_CLnz(hwfvba4-T0cDYMhX17X!bI}590Ux+L6;EBxr6=FC zxHcHDKZqHHeSXg_>UTrld(mggD;o9=QyjB>Fuz8FggIA_7I@5V_R%rOgbr0*ps`7Z z<B$mbO-W`1n-=<+qe-zP04)Yw#N@CZ{l6(-Jl+<V8cyBbe|az&k=d!WtO1M*FXq)= z$%AJk5NTEaSC7oE?j)|_#_Tkz2MfX)^-PrNmAQ=co;DihAePpD#jf>(4$FUU#=ORh z@4!klXGgqM>h5N9`O7iZ7IxE)0y=rcRw7l=y}%X})!8+V?l>`0O-}`G6zhuA8M0Va zlYsjgl;~`{AL`NiE{whDW(-ocA;R_wm67gqF!d2yv}q&km6<}@SSG3t%nVaNS6ZW@ zBI&7py5)v`m{#H`>(KV$?LoeGz4MEqgK1q(J7A9))fKiman6MBi6`9_R<9B{^F|*I zZ9y9YVzS0_q^)6}iECA!eg1;w3hMPiJQSEl(#}2wxccqH**<9w9C0;iTP2wNjmNw+ zR(q(;pEN7`=8%!mR2~pLBKuJYxoq?KAYW3mSI${!sJ8#&?8$VZ9s#5YuV5E^>T8m_ z6|gm-zw>u8Uh(%!){6bF|LKKZJ#ygjmu7oJg?&8Wn&`a8)%oJ&JL-mh#8A6h2_QGv z+MoG<k6f$dz7yX#Z@`QR52=Ic242|I+Q}5t988wHgsUDr)Z;N<@pKwfH*Tllgq65* zwzYiZT5QP@cI=ZVietY^(@Lwy_Z<6ZdD!>o0D)oJ!W|EG#)fN(9sE{d){`ixN;N-i z&qYRpXoo0NqJtn&%<xv!8BfoT&FY6tWfU``?~ejP6;emY7f<%LcI3J^(nPzSfbH92 z{K;A`UA%7vU)BlEimOjVivfFvmIMe7fTc1hw?&iq(={<w;ZpUQfY|Ku9KMRKQd!Od z;vlro*^+PWQcgqUky@$?J01B6-3_c$>Vejs@Ic{yveL0sZL`5U>_&bSuv`rt+L7U& zXi|$FKs#bo)lb1*x-HL9a`fWk`HzTYOQz4}Kmo`|K|VfutHWKAXy56E^KeM%e4KFY zQO>Bs+dEp|iXYwM$J+70!Cno~0Td04F81hHzeNrmAje;yI{^p$YO)y0V$Xi|KS^nu z2=IG}ru=TVZP<!EBYyyl!0bzQm*C$y(ULFi7w#1!c5kYSDA%p+{E`hg??juUEA)-s z+JfXyWEt!CKu1nhT^nQ%Hr}^Ts0tIGZHa#uK~fp65hR&e6FvkA@vtO-^j>~}`;14l z!%3J(8_rIh*3}PVAqqrNf>4|xePUMeH&#&cR+h_m8ys^9u+m+3$0=2-QEcV8<Goe@ zxqZ56yZm?NLl_u;*S(xzg?KN;AJoSmAq_ewYyM>++9lQLHWw0~HjR4ZwsK3<?NE&B znnWMRNi?Cg>sdfM>@PE>ImCvqzU%r<%biB7NFYrrK`xzgpm1Yhl#vDf0ibuqKoqJI z6gC&NCl}lzTrH_kWb`OZoB5-^5%{q6+xrff;6+sU^GBGksi}e!kjhrJaz5B$s+AK_ z(?knZ*H`8zl}hTp+2_O60rTAV*C&CYuHsk3lYjZN<a?dL-#-}C2DJesh=ceiASr3- z0~)9s)i9Ubr!a7Zio5W^B(M*9pBBk>7ULRn0o|x?G`R>d=e4n%_59Ef%+(AOe^t@R zJK>Xl{Y!^=l~f0=M%qM!QR^f!-eLTQqQqv);6b8cvla1i#0fdMM^m;9>4rYuo~phj zr^rnk{<0SZcBlultjus#Op9pWYlk_5hb+peUPtcbrEKIF6ljNO_wBK~v>FMrCq=P{ zL$)b_({6JZA#H61uBSaFkWzZC6*l2+5=X3}dX3Q4u&(u-L|Mk~gngkIBg`;;QciVg z8;v60N!NHd=(6zh(VbrWUxhEX#tPqa`8`N4u{5`|WVb_@RLj0NNWMoiGF%#Syu4lV zZny1On8@GI6HDHrm8Qbp+O5hc%fTBGw+~CaN6)Zh&86d|B6L12!2V4mF->MVfcgFB zK2&E{8={N`o9@<>9jL~vT(wKD2C@~n{JGZ+`v1*cIBS_O7fQogXXM9@5tDr;?w^t$ z8kiL<(|%2o#{`ZWX^T{<t09b-*%<ui=D*^8#SWb8p4{41lR@d*XU&BqQ<pPt*Z~Vk zvT>95J^sX1k@a23^(f8p?}?Iyg^8H}>l^%VzHQM@S;X?s!_n<C?(EeG!~jE2Eb5c} zSQg1jnk^xdO`2|=N-R_T2F-8NliiGI`$RB+H8sB(Ed1Eg?j_Sk)8XqD+WO90RaOoY z?zyD)8xnHYz3YF-fjU=ST~I+W-#3W$UNV6g%wd6q&5MzLsbV{=80*v3tm31%+FMe# z@#|tf(=ku{;?2$v0g4fhqZf?;uT@8gi4*tQ-`tiqNag3AvoqA7boSEH6n0(f%QN8` z)BG8|rs;J>)_O)xwvVaHN=$E{KOI#$h!Tt#s{B+n<9>o{_(a7ru+(BUU4T%eeHS+a zEOuuDbSB7UFJ?onWR>D*-B(%ksczJ*&a~xQyk1l7bg59Xb6KgEm)ASFGxeM#fAOsr z{iCt7-Yr_)VA<J$-mNUTlf!=Z04=;)roF*&sWTCR&kB8wp}g=q;aT~z{%jHDLh;E- z;$=pvB@t7#<-LpX;Y#^Wc*um&nR{hdLhLTr^Z?ge=*9~!awG>hyu1*v&`qh{VPIC) zeeeo+V<=&Yo%(d}35nA9x2$9+_!B1)!dlQxCV%F1A+J*jdMM`=YXSu+jX%7<OFH}j zHuu<f+_lWH@6*<8$opl#R<GQtM?1ziN+zd%;=s+w>zqxo+M=E5u>F-XRRf9zxImh4 z<OIwn0Cf#;Soccb5+aHu*9JN)pUw_zpdx}yVFXiiI5~pPK_)UzSd_}TycQAKPh*-i zYel6M06@CQq{^!A_6cYoq^9!pH}At`H$n4G)MP$|JtLV`At-$|(t|ealN@3nEm&C& z$-wXVqcHBEJUrQoRFAHe@{>P1hjX1Nd}6)(VRkl+dBPY*f|PG4SdH?ba11|aD~7(g zOYP?RrrvnYM9BQQE_hx-;M$;b2f}bG&)WmB8JV4nW*L5JYOz`4JUX_2@UuCt(3B5H zTPaDhu4S~f#h4t?Y@wED{!P+Fp_jBo;q<cBv~(E&CTv6{WH@-S&_xDohsmunfRuno z2nAWg6VIr^%Ow-fNH11lo(QAylPMui=mRwnzQa#YY>=Kjf@5PiDX>A45%{<-Rbc<G zFHOA(Rf`lqzq5`d?Xr6Ln2~!J%I}%<e+eGB_`WP&niM!1Kag$?$;$O_iz1MzB05q= zwK%d)F*Xd`vx>o)6+lA<iNrXQP;weeimA9I6m`4@(=qWL8zb_2kc%*Zh^GQO0m4gf zn#^qJV*}8nkM|@?vtuv@4S2orr$G7<XnH0_D5|Q0S7;~KsdVaw7pO#MB^7MRM?4R5 zWC+*w52!@Kay}N$fG(M74y4ZO5JH#OZ%s<D{8lY+^>L`c^(?z^JB|efLGzbE*1<iY zszicsji~)iWNP>n2PrUc8k;;^<mPqtqwz~Uit(oc27`~=L(R*#EI{2a!Ve$M<rqi% zyD0o}hHO>7Bo5q5s#8iAx#xiROTw*?`}|=Wl_qT3?_nFnz<-|G&J`kf=feeF1|N5} zpeb0$5O~@AXe<1({;7px?+=M*|7`Hj627d?Eq^P}Z3Kega1L-26LmeM?c2+{p*tuD z4;Apv)vH|OhJKp-y6aN*%IASs%P|}7wMzNyw|b{FIo;$t)2H+2dnY0$D?Qup>X1)8 z6&<i{c8;3V=z|m2cgUf`Vpl2~#L509`@h{HWcQL}CuDqRMC8W3=%2}jG9G}l8qE<= zq67;cckMJv1RAtT%?%!9V`A4zR_1d2_ux7T3)JypAqH)q;*m0Cg`>qD!@Eesz6tWQ z`MQ%|AQrn6?q1P$x~C|*Bu!#Y&JSoUEx%TmMQUnO>|q?pkvfS;i0huKMmiCzfZ5<f zP38G1d?dcLyu|@M*lc)RoC4`T-3}9p!ut>gTF|1J<Ru=0A<5fQqaw~y)nqv;O>NoS zZu_&l?eFfia$|Qh9X|u-+he~cBpWh*RO`FJ6#abT9Br5xBi41}zmu&rE`&bmIGi$l zizEH_&QIxRI*_%(jtCE^qv#dNoQcvWv$3a+hpI!K^WCuHzt2Qg6m@<xg@3yd@6lSD zLx!7Be6-<f)&NQUbGEF}RpL7CN8dgwS&5*md?5QEpQV`%Z4D_6Huj-f_w}OTDA2ej z=n=tewbIA3hl*_c*h+qmSf_$R(-zpctX`^U5+l5#8{a51h0v{vsxgDVRZH5YJ1eR> zlJx)Bij(OE6-C&;z1CNEEX__>L7$@V-F2)&{uTj4+H)Fk+H)emXyCqNHpPUY{Zrv6 z$O#*SI5fIWifr9seb$!r_`dd+Pbh0DPogxN3@6jl#K)pJrXT#DFV6Qw(APVReSy`4 z`(RgR?pV?(J|T8}r&pe%OFmk-836N23OKRXX$2<|ec;0lHXp{doV0qhto7kRTNP-_ zV9utksT}mF<%>FjQ{zHSk#7gZIcSVmS@ZW-%qLp!XXT87OPCx&x85|gIf=-3Y<p^6 z9qRjw%@+S1?otQ9k(b@_x>q9{PQ4}4yYm3>I!Q0Bm6#$j*~W51JX1UW&tTXMM)k@S z%1~w=vq2?S_4EC4wk78Dqt#$%?!7+sjj||I(=IS%Mo@*{`ynI{HK65}odH_S$Pw|t z5*|pS!+OmY<^<0J9bu5E{_HFwDo;iP0e`N?+sBG9wO9txcF@~YOM|`mvaE@{*0yFr zC%3b@t<@RLEqkgzgclhBs@Wt5_Yr#pMG9X-@><FI#QXP9cWE{C$T58BU&*Ib0#)QH z0544~mZ;a6Z<jsQq-rq7mP)nxMaXh~1J8m{5x8Fl!iO~Ql|bd4z+<tgOzT>kH<E|_ z?f=qb=3x8Wg2)aF!ps9Vw=^2Ex2G73AYK9P6dSTCr!|4?`RFu-hMr5EClH1VK9w<d z@dlDb{Z{@pJOmjG?_2-%C6)us{b%MS{Qm!*7Ie(FMd4Zl<jODnjfZ%ZJ%AqG;__hp zxma@Y{^-`V|MMA(#<3j!pFkVj$2pk@$?_>@{!q@<nQ@G{@ZUEfgvzN-ZY84ksyciW zs0NU2P^h66UhDW9Kg&$;yAM0vt}(-UiWl-j%Mt-7pVBKwa&HA?woH?X3`LuLBxYG| z>LcEpQf3^=n!iZ^bZkO8i&u!}LI(E8i&FhFpd$k7YHT23k4G>9mgnIL1Vp3O<bLR> zE-olzho?^lR*EDN6p4C&as%5Qlz>?!LXX5gM_o+y+$}<kI>?dV(FKBX*qmX&gq&DA za;rGhikDYsR!3W`;u^v;{l*+1R!87UWb&+IXNm&to;XAzp0Y}$aclo}<R;82{j;~1 zc34*ANTycF5KJiQTz~569lndtY3?O?W>LN}VoyE<)UY!u!_DCa+T<nQgH2Wd!9?Ng zDQ1YCqf{e03Xh~8;0wNxXP3IapEnP-)OKg8c;ZyUJTnhI!)P^H&zLUOSDL>{YPqri zWB1aH%quV5een6}*VQW%aVi3~-Nxl&6{NQ-|G!fXU)p{9lQ7b@1lJ{ksdOw|?Jm7Z zwQv94%T@80zT?x05{vwn5Ltq!-M`dDqPJYioDtW&H%pPU+jlLmJ=`?tCyPs`H^JtY zH$v@2OrpI2RjQvXaFoExyN0`D{N_0%@=L_<n?}#W%ZL!kT8nD^+IwPHRFKPnC)H|s zr_!D1!}Zz6$Jv3pd)ZTalfI=E{;nr>3^DU4hXB24(v`GyQ3x_)x$#umL*j3ESD0+t zJk;a$Cl*pF&u)q-Zj)#6hvej9L!UGljqG0w59K?M;9<BW{FsKb@=@pI3jzAAx5--g z0ptw%)HEfjbdl-CzL1*q$RnTXl@fg9q7wH^Bj@v@i;1d9#|(6U<GM6TWxAq;ZA-I% zNTk_KrWvh{zYJk4E1!*9n3H#D%HHOmtpWcb=7wCVuR$<TQa$9RN~X%?>*IIOg#SC@ z9O#SisY1Zp#8b-Fod@EI4xOb}z@NB*w6S?-*Vd=)^x?uk(@Z3AfICX9TBw#WYY(L! zI?}x{9!OYU`;vgZ(KaQMQ}%OBKgGQ=@p15<qEM+@l7{gs&P3KK+xP|MH^%tB$9c2@ zC6^;IZ$*q9cA5J!nNiCf?b(#;gg!U@RE07yVJcJKw1^6&d&uW*)p>%tS80gqhU{rZ zKFf5{r8#GPA`VK@uD@osByJe?2=^`5^vhp5T1`UoxAZFNk%|u=f(3_Fh|O^a)Ar#E zP<q_*tf)f+pjiel_NVN#oYURY=U50;CjgC+x1MB9?BDz1^AqwdOuoEydGgScuSHmH zc=~WsrXZqrcv7YWoqbHH8(3lfdmx>@T$bO@fC3%6St*{)@@m7RLP%YQ0^`$QE@mEF ztQ29`*r*a<wKr<f=6KjXB~Ye7x<owYE{x#kTaINAm@OLP#z*YjIolqPt}|Cdl^)i* zNKDvOj;ut`HQcAJwO6=tojPC(!u9s#zeB%~gd>n{njI|B@8&<^2a@#NoyXTqelksv zSX*)x@^u(RDh%&1LLRYPWs@@mLXg`eKt@k5t<`zMWtW=6eEGOaCZHtXO=!e}vUv)G zj(otIgME^@MH<)guCwyXL`j>)0p=ieUv%zknKhG(@DDlXjr*_I-@7k2XPc01RD0jr zBHX(r2QuTer|RPgSXmG}hr11L5k)toV!{{@9yDRYX2MTjMzB1;nP#8CFN;Qq4r-A3 z<3!!O1V}=fy}gex7O6Wuy*H2HB@aypi`|QR^W2Ky>vlSSNfh+j2trbcvpzsO>Y8V% zgeJoZ)MAy#Ex_pPrE<I8q|pTiKb{@638l5AQVpdR+V1FD%X~!_9_*$b*m8ukM7A;Y zs#Zb_mu^Wp9CZqB`Sk){)pRnl!g!))7b@__S(0TcTU4IqPpFI?dB&%w1{f7g$@!e{ zhQLt|w~<4H`mmK|*Rf|QXspA{OWl~CZ9!8A@I6Ow)$9LVg^eZLpX}FWB9t9JCDt!s zO3>w>OhpfE%0*6UA{Ch~wgte89+XL5J-k=8>d4_u?ZV22>nN8$R+ye)eqOxE*GhbB zpZpZ#RWeF$2#NcG$3>sqG5md!=6Rzo`{3r!LJ!nox*-k~o0~bXQC*8+?2XVnHcMzP z+QenGSLw}B4cVr%q*cyL3E7D2@JT%+JvT4)Vl`S3-$SWUd4j>|pUBLXZ^qJ<S(<@p zQr5yxOB+*dQ6m0HWkjhBeb#dj|Lh1<rOYGnir*#eUbv7p#X2o4Up_A}I@&5^VAxx6 z`egxebC1y2nmiZiAm)_wh<H{{VMWx#h;;>2WP9G`NIW|yN{jNePbaXK?gT-NkxhHI zEGy#=zxc$pwO9Hmi)1YZ?t{bZXwHa~Ie+2bLiNDS*@-P`oZm&vCTPX2CLXV-Xm95N zAwN58s>bdQw3+XEd*DV*okm%!w*J7jRvx7FQ;-D?<2jLQ7ILtep}aNT>oBx?IzDGn zyqeoKCRX>TN-k64CwcLkX^dsgrfa@xV`r;XnZimEuIwTZ#{J(lL4WC(!9mUzH4X9V z;10ho@&;0%A~TY>ir*bmqKFKIL@99iTy`8KP!5CPB-UrY4*S0?^|yRAb(QNid<8Ej z@nKbm<{N5C8lg|(@kwC`25g3x9(|hz>qi8-H7S4IEZ?*wuw-l|dz{+gyE!Vb-(x!4 zYLTGC(-YQ7@y+(>!>K^QOyP2%049uOS-6vi)7-wZ-PJ#R&bck#1|*%|I4-UDM}$GY z4g2*=kqtJDf<UiNK)omnGyF2IakgSwIu=`NanbRD4@BmdMCq**svca*tMpg7<pbC8 z?sR*^O1Ge;3=7L(dKAY0LCwk>8-4*=w77m-J&b{MlCI;FOPE}&+>ybUs7f`J$EpFk zQKgw`$H7@Z(&>8<$ySlAbvx?x^VkH8zoozG&u@9+faj65`r@W#1)l<`CD9_48N-1G zm8$rfU}|i^cFWoj+gN~FP4L^$-*DT^h*}}+pM;jnW!WCdqv-nIkWVjd&w6Z))ymw1 z#s#ql*>L^36t6<(fhR7shk6R*ZLe;b0`Y@s*^zV53V7H9Zp)1-K$=>ZFyh6oJZ=fQ z%4LnXz2Is<(U5AQGpKRpzph*uz1QONE%A5)*tpWgP_iuMvmS}S{;BR^bOAJIB;Y!2 z307ry6A{O*eLJ^IN6QtrqiowC@(g|dQVUgT{8b3jbFi*_)b~KjMed~|g;eFAb__-1 zsJPgWt#L48nr)0T>RPNBsSh8e8G)APyXde*Gtiv4E7xnXk*HWdx9L{6z}!H|ZRr)# zBH#IHH(_dO0tpt~t}v=3Z=`@3mL>|-?4g4Y(mfC9@L^~V>Y$@U*-@EBAF%N+NoHDR zoB_fTal?sy_D5fvu*W{<YFmm@WacS;RP~+rQjl=7dD0>VYFANze$hH2MCrKK4{u}~ z8!S&fl`T0jxPq>v%itBzsk*&T{0;FgHgNFqDBM)UvWQKG{4y|yqs4Ky53i0_BSb62 zZU$aMI3mIi?|fTVBesN=wVZ!F@p14y%Dh{vee=w~ie&c*_BIx*5R_GfZhF+b&{}uU zg|SNR3c*p2Z$<7!8V#fap@j2QxAJ&z^)1kq_o8YA1Qi-A7$Yy9aEKIbnl4$yaexKb z*g)1S7AxkBG*>mB^{kmDiI)-&xFcgCE)ze`kjy(fSNy}uQ9eLrktJa9s61c|>Dhnw z^TO(LvmxW>Gb*gE?PgH2$r`oE0Qqmj9?85l6n+J#2i~Hb2(}JXocGuo9PF)JdvJ~$ zPOhq>ecW{mMPzO>cgJuQDLu#&fVwe|#xoaY@@$KM%pbs=a27ZcQ$7oK;)9BWWZ#t$ zV(pZ;Q;6VO9&nUtfH)&derrW7o!!y+3~esX9Zm>qRDtEke@_kd9!3M8gVudUNZ(Qb zLp(grk;+GsPa4Ex*p)_tFZ?Ehf;}(rcqRhEo2M8PG4#=BC@QCx`gkYYW|^XG3Q15V z$o0eUjWxh(wD6w%x`W@OVEoyu!PY?*KgH^top6acDa!kOv5X@mIIZoRaru;cSr`eg z!3%a8ZL3^#EjnL^H3;jAPOWO4F@Ha}S$r~-vXA9^Q&T;y;%ymQ7OH8ob}nYTSYM}4 z6}gKtG7^zJ(EU6`a@8UF?-iLn=$0tOw=odtxEn=#WeG;Ey2GfQ`Uqq4t4LMuw9%=3 z^txLe8rgqqvU<lmm}*7s=3-R_{3HOh8Sq2ExW%URV!7nJ@qlUP#w~|IvK05~08*8) z5>?bE=?*fL$ir3w^T3l6D*R+@VP<LMW-==KXOQI_zK1piCmrok5;iFv%J^<sE#(ow zY0FvEMDeBaB$7mYZp$mmf6l(N96V+9ZV^QzCV^6ePXv*6u73?69GRX{VjiIjMX{o; z9|*JRq}F%X&AAR_<P!7>R$XIR2;sdAnkN@+S1LdzCPI(J9MZ|$cpNDFBFSQqgAEU^ zoh%mE=8*b42p(ubLHu4C&#~`?@)7Vlp+hj$FWQ8}_0M0>5>xXNLVt6C7-A*3?pc#8 z+{mEQEPKUR5lr{NwbS&L0od|kE1%1t=P<uDzn@6wRH*~~iOjse{qXe-0rqsC2Z#<I zK2n5;Fvz#*eb4V{#)9blPl12EEQfM*5Rpe+>I%8MPAW`ollA)K*lEgJYeN;z&Vz)w zGLviYJCD&juZOi{n^G7b9^Ln<Gyb2k0Fy=5RI(n?pPxkrW_lz`ZBX%T8s*GT0>#W1 zB*(S++z`ZCS<s0@OvJykhWVid1y|K%HHXWs-}0qrx9d(TeP*E7CYZz=`KJs5I)e_n z4~C1En)DQmodT~{-_(dMDf<|ZrD-3PqXIhlx-4A+c`^9ds1&y&fTJB*AtMH@X_Zq& zO-Yxp(U)!=EGyZz=5BEm9(``!(~&}U<wu-}$6A$U^qLV4>^SsEA4@V`7F~|wQ1BHx zcY-p{j7M`av4X^Jeb@#!w$uhZsO#-Dy!dV;Je7)<Mf&Q>A1O#?qqC+AF%B-w=?Y7> zrQtHAZu7)LB3~h+^g5EobtA>w`Jsy_!#ziagWHfHQnsg|$>ejO&?ip_ldAjgCc{s; z$cGgZ)T+RO+h}l@u*P9sENOr@d01JJN!MWxeF0x2ofe)y%1Qww+Q#__T3=`p5`*=~ z)st>)VubGMb>}2gZM1U01W7g<vwY*XZ^rr97#bwHWyIqf_}+K9r9$F-<WbHoGTINB z&hvO&KG$VDJ$;<p%=$j05(&}z>90e#@rTUCIhZ4*oA}PZD>fE1EmHQIJiNT2``|U; z4DmK~(kWXE$c8Hexo~o^(fs`MX|no%O@Ix>UDps)c?Lje8`tyrqNt|5#brFC>i0#% z+nk$TPjo3-KeViPISO2h2BdXh%F^G(Smy6VCCXV^U-VJ5VGc0EUnQQy7;}BOb4xt0 zZ-H2}tnevyJ^R%{xp2HNi;41?0=6$_;%^NM8DNFpXT=a}Z(D$;eV*K&&GNN_E3dpV z;1576nm#E9SNBWHR0a79AIF~rF=+j^B^udd!79yNx0j}1c^*$<^?3S|7D4U~u^aK8 zhFfA-Lmyc+64M9qBkQvhhLZpdUX|9zoJ^1~<|S_r{O*tQjz_S{1UcTGN-T=UhRf<_ z?U;JjJjK%NUGz1plzzj0L|EJRS@FT}lN;)z2ql=?rF>VI?fPKa-W8SR9YX(vNG2ou z7&wYZLy*{fPvJL7%39^M0*wT=MCdTF4Gj&&hd@nE9qq8R5sHCXu6$^<!?SST$H+i? zT()V~VKc8FBK)Yw7>1)QVhleyjU{TkJtirFx!wA>&1!lJGKwbg!a$~5pEB0Vk{z#W z8O%T{(MK&x9S7~<2kju!Z6>EImOs}OelBH(TuUPJ{FlW4mmq>WLaaaGqYrMqH+@{* zYY_&GZ0X$EWxNIMSp8nZ5r_1GECGcRkg~8+%TwY$)C^z%F3G*#%b7g>qQgL=z}R)x z>#K#6GFgnhdp^sB-*jXJk3J<Yin@e4rF<v<1!o4T+p#d3`y^`tiUC?4Ig+IV+yecB zU^1Czh*v4vq9qfjPlfl1KFITaRYr-H%?X2*^ZfCZseUS~PzS8c4;N`0$ka22yCH)8 zU#ao72lYj+_q`2~4ApFtjBfnEW^2#Drr*}ZRa91dBc5PuPk-hk^kE^2(>{%WiWW+o zs-eD9%{wxnQMlVorvt$mMyyC7eK8c5p{PJJ(gXd2FQ+8it~t6}?Pcy43#-T=DlO4o z%Dnh55q$*eQXO}P3ckrGYS~jb?2G&+PSJ@((Y<CET86S(wR^7-@Rgui9HKTGE;c7; z<KBZbZ59`@Fg5h`T?TVGDO!h4YePA|Ma;A{+Rk3IvTO4xYWK=&G|+cqYelg4kU`^V zV|M)On5Lirl@(dDlZ?I0GgX;tHFb6Y+#2@Hz9g2Z5_4mj1leEWAh;U<_)eG?s~|%6 zU*Jo`Jphct-td?PWPR?bG7uPPp76>%vO?-|iTw=z%a(>r3A*HXResryk|u4<X>3e; z42#~pX~@?-mO0|)(?Ph|IC=Q#y<m0VP!SHB4?pQSS-Ed+nfQea-}XHVpPe`(t%I9v zWeX77-J`s*F~xSjXFhTtIW2zlcpbESd0Lt!d{Hvrj30BC`F7Sz%u&g9NQiVDw(;*3 z9(0YZ-&7e~gYEw*UU+ZXwXIwf9KkF|fIX(bhIJiFu#oJP`dbFG9&1d^0Xj-PrD5qR zRo9yP^%;;yePk<lhjeqlxJLx&z<yHeB#4)}k<k}Pd@Wj|htvB_XYmpQjJ02Y6|7?( z&s|7WX%cW!bEes@=u41gEiw2I9pBU*A{L){PUZK}Bi@i)!S3dW_K1YR@n6&CC!E`4 zju@#r7dhGccOEs&GVEyfGEykZW`9KT>${*OD$oT`%wKH`BWKF%%e;c3tkHXE7893F z6T89+d>$gF#+-4GZgS+vVbuuS53Tqjun6w0&8)R9<enhHawfnT@bYiCx)E((laF_U z`HUo~!?TX#dQa7F77I+mii7G*gP8-{pW^@iikF@3z8~Z=`y}r4qd~_^=cY(Uh-^ZN z^L6V@G!O}|ZspmVX`7YQhfm3Iig*Zk5$bX#Sqb#EAFJ*PZ!~^?&k@(2Uw8RKA$I01 zP`h3I$F=9&?gTXe6=8S*M_`jXZR4&gPOFe6tIQ!Z#-O2JzHdJ0IAqxSA;e%xq1bOJ z_~bg*3#md$44QoO6K8L<Ywkot|E5`1@O(Mk3^6c{Of6%U{8P!&K!2Bvn04xto{>4i z#(mKu?p29L3$(xPrt(G!G*ZGEO@1@{=#H>fTGkNpiqVpcM||jjG$6e67m|z04GG!( zdtAJTVnJq*alx~hQ7lhu<q#%(+a2GVmT&d(RxLNUWlu^pg}AX!NesraZj}iKju~)e zrw;p>TC<6VI+haGy&VoG9%PmJ(nh|1G!n5+6SOwS>US$QLoHb4qAZOdXFl}%U5_l= zb?DGXSE`A9DqZQyF2M|*IT<l(Xq76Z5pMy>t@E?}FkvzBA#UDUPatiL_142p<zSBG zY)RI~Pu^>->&s=?Hf?#A^@fbZvEQ?93Y_MO0`l;z$yiw}VT3vD&n{n?yKTY+n>aA? z*Ngbg7@=Pr?X|fHYzwRSt+V2M$=ericq_iVI2^dXbm74*C#b%9P}?TQOBbmdb2z^G zE`HyY@?R_k3JZ30mn=zx*6c~Q&wC)6&MfCX1V{d+MmCAE(K>ntQeWL|Ys<s~f88zD z&J$1gP_ZWDQ_W9I-2~IOBFUoJ5t1oj@#1$;4du<h2`{BCAaGwqDY`we{%#$7U?p3B z44wctd9&>Q-Kllh<M~k(w*N#2k+_R?Pgb_!(<$_}I@+Ur+~xL|u!(dsrySVHHAJ|H zd|qoMkgpaS8Ec1C3*8)LnJ)H@$oL*O>Z=819mn;svF54uzFy=0X#BB^G`gR!YI`v4 zcO9|%h)@uyI{nts?%#|?(`=&BZ5ar$#+Y=-$8L0Ump`1`FINBnMn>RR$Wp#VoYVFd zE#CK%7F9wu)ym)WOQjSfMxz8H{1al=yYgCp>Ne(umQsD$if9<l5}zfN$A+KW$&+#~ zKo0gR7z`3tt(SSx8|68d5+qfx=|~k~710zUfr4V{^B!&21b^pKb{^JgBmnYhz+f9s zo;W`HzC_qVvaLc3pH83auq?omF1g9FQJnu?3$H^yo6UhqHcdTKGQhAWRc4!?CRa7m zenzv-i7*6DXH{V=OY#}-|3N7GyDpzz|4<*((sGyVo@Teas+F68fBBbi)`h?tEo5_y zWDyI79dc6t^<OU3l}-FM9H=?E58hn;9T#v>p50aFoomqo+PxsPHr$q_A+p}Leggf; z`H|c0<9`>On2EQX{tzNi^H+5K<UyO<O*g&JzMBJ!@rR^a>`&P99Q*b&i1rS{Fomte zje!;1Cf2Z2i>lUE(dj3WQLFmWx3OqkDmrpQU#8I@p*hQPaFG0WCK2Mu1}P$kSf+Hz zx*G)#1V^fXHb=dm!^g%xv<SyR<d8v}8|WHC<}3+6bgAT{Xi!>t_|`+U>XqXINZYaH z*J1cJ)-SctL4fc)GWjl_L0<N|bh_0cUG0e0Ek$)0Xx;n(${0r5XXIG}zdh(owS<?% zVGur+3A@<?5}AMN8Z!BZ(4$Y+?RDJu-ky?fH=PR{@OzkC80V1SvDUoEMHV}X5m3@s z=)MDi{RG8ulVGNDcdP0{PAhj^@U*GoW6cERJj+*|*?WODQTX%=p)3si08`^9&3D$9 zd5BAzG$GBmZKC~bsI?iz(IRZ*F4N%fhK#}Z`w481rLW3FrqwhArqF!A^2l~_rHn0K z_&me|C2u}E+_ud(!d)D<29YeVtx`&Gcn`0heMbga|1Bghc{4Sw<;}4aWyk4&`oDzd zs%Tj{1xVi3uG;^ysiC(yp+BX+(MF0%g`BaUE&htQ3bMeZe&*Zrgz@A>Y&q+5jNhBe z<ag;F5r_Lzv=7|(lRsLBS+*3^za;M2`U!(QXx^nijX4}+Pibv4gJ`Niyk{Y>dH-PJ zA?!Ar-(pd0YHV?)FV&v$T6qpSYwkNCPS(0X1I<|5<Q2VqQ^_?%C!mPTpvVIJo7=Ri zoUXZPlZ%VO5`o(&4Vn*BeO77-o}TtLl6|>k;J2Ce3wy%7ax?FQJ)Ou6D?qTqxI%Iu zy4_?}<(ZBp^+=Cok?N1mA|sMn2MrP9KhX#)3`Ve!UQpiqGDBPn08h7n81GTi>VZ3K zt=>J2e71YQUyufxRBPzpYaXxzdam)LrSLb8L=~*#sa79`YPV3XcdaWOXv{r1AQe&e z?nTa?Eo>V5DfJgQC{F*hW&qH9))e&-<c)Uh$fgohP>fwlm~d~tZ6Ksi9M-7#f^{l2 zCT0ytU$KYlBw-^mby$PWT;utGG3ceChQui=I+JSiZsew$WjAxjLCK&$tg3hVuyJK6 z$M4K2IHdn=%OU>;%PZzUry;|caQoBIkjyutKTA8?j5BYJQWwoCVYQRjHh+-0<Giy( zVkFmYfBW(KA>eCQeO~^HxZxb=Q~;cEIA{jiy0Z3bXW+IzTjI?ZWk_{9Vf-6g#OHZ+ zAP&I`^)2Yhrvt80Z!l#T+0Sezyulx(*uCyCy=iU{W*s_^nJgSOngIkEgt849vMoGi z>q73Ln$#giA}&%zM<VQITGO|qX@}Hny7l8Xb=QJe$7-Fg8<nL|{R%76ZAH<RJC_Bk zXdkorEsxb+D4(qg)!iF22w;AXV;oo$YRZ35<+8^QT6haDGUU7<3W$au#=m-UE%F>E zNE92Cey#pBXOwN(-``P|FoG=W7<MA{KJi=v4c^*=mWjhA6vcN&W756spm@IaDOY*% zEkd$iCuuz~Q-96BSu*ZC>b*4IFUxwbER}<l8LXPR7GTi!c>vk^F{Gp*Z_iIEJ9u06 z0jxB>_()f703g;im2Q_4{c$TvvGld?<0qV|mi94rdFp7H8b%SKpektNa1|Av-}8F| zjE7KMz)|}bFdeN?-tCiVZDN$65l}2!(9JCc;m0?#hg(E~5I}FHpM3lbi;mj*LSICd zAJ*#SMW#7fSJrS5A>ZYT6}6mAC9Cr=!SF@Dx&7VAE!DN>RkI8;51pmRS}iLh+E?yc z=iXJT!H6u~FO&kXVn^d!oH&p-PY)WHG3ICP%V|QF<TRkZ{*sK5o@pF+)NWmUD34M^ zx|TwgwxOK*P$2VwtG6E8xpwpMhdMFg-(cnV12CrQ&j-1!CS_K&alCBSS=;xXd$-#f zJ%Y=j(+aJ!^9=&(Z}C>vjlF}61<qyXN%>**cu{sg8h^g-qe9Ge!eAYlTGMuKX>-Q< z!hDrx;WKxuUQ4M;oZcMU_(2e1V6o;f`6{vHP^rmSg?V87wzbfuR$|->WP_Fq1Cn2P z5=BS&ThKD6VXa#FE@i^5ZLp-r!|C2L6uD2bGm1w`oE#-iU9K8UKox{V#jbnK+1alW z9sRCY_TEV_CJ-06wk6tLjV^pw*%CX;6W}P?JLZ1D4ALZ~bmT>9y=`r9Dd>}I&$=ri zM>W0Y<U3pw`dO-2JcsbWhlZ{CWcHdS&6h_UpJPdFY{c_4Y*LVE@0nKL4U?q&TGf-P z;;YSyLc#b*Z3G+<%Dw{kBx91Zx}?Os^knLq4!5H=2Tqzjg3DH-4<&_<2Kx$DEIxMk zZhB$VgREsO0xm7EyXYAiX^#(Cc!bTM^9k-HZQz9@tGI8;{gitoOTS3vwT!hNXYv$l z7`*Bl2uiH3V{`wu?3pb$N4wMrA2QD1aJj$GdFNjST#ha+TMjUTu78#-xK&w4&g>tQ z$X1hdvIksaZ`DY?xGveCpLPJm3>eG8Vi-Zzi`|F68oZrjMgAW3rqUY}J6I%<C1{O6 ztz4eT30V8r+ax$%r%r@$AAqJJa8;F&{6Z~bxau>|dca(OZi52EHw^NHa{a=OfoQ+y zQA=ycv^C5HJUaZ6V1|4-7#UPy9xQVQ^Ql$N^)q`w@3fyj!W;6qFaX<!XPF_+3?Zo2 zunw})V5;Bjx1%5o0k5>^9b14gviDnFGz&%!!E9{if*I;TK?DA!^|(IickFhdPlH3_ z%Yuwq7rz@zb)ZM6b?OKVk&N9g5E0N&wlYU<Tdsmre0YW-q?jx$D>prLJG)oFVJj#K z{yDEK)GjC0pObd*wuR0^rRgs=2jWGs>q0rv@l*+yyqB!R>vsn8p2bQZ+=hy^3n@mw z&()Qljvn(jA6~TM$V(i-ddDEM*vvU92R1bf^2#2)+H_Z56V!e&j2riAbi$3e*@&?D za0c2JX4?i@oNd0}G}=r}XGGUNk^F#fF4X|4MA|>tXSw)+o4vFcE+v&!JZK{O(%|lm z(TKD>7j!c0>?!6jqtW{bhMLo?D@{6{&g~l{abJcf$J#b-whaq6^$|+ZXeP1F+zNdq z8WQ-HPZzkj;T#*OI0fr-+|nf+p#-gc_fVN*Lubj415D&)s>_s`sHo-kuU3W{<!-xv z62Tu7d}cO5E?!!(aQ@Xw{CSP`C6?P_@kDFM`AY)r^CQ_RNC8Y$kIw(V^PZ9M_Du6f zRzXd~7pe9JHVz%c+C7rB{`~`rGmPkbKrh@)WcQaduI8rJW^&%Nv_9FruA^G)F`i{K zTXe?Kf_&bGe^Q8LGCKkY36sI|jfYut5hl-xaZ_w#k=uB*bPd_E?}sO|-*QJmop0&& z)W>#UdHO5t1H1WWkf8o4S<28}xel)K?%);iwBEjAk~t@vQX*GnDk8&%0ir~&#80Rr zzgM5~w2F$?N#<_C?WuOl(sR?X$Pv2mZGess-QufR-`Q*^>?&Mwjpb>V5ve>k_Vy6x z)2cj^bz=(xpBzJJ3OSV?>($HUSvj9!#N}JP!95|~F!wKA$I>3}XxAC$IFd9cR~e{I zqjZ8MC?--@|B%=O?B8aY3H;%eM3By35ZGyOE62p)=<ytIq@QAJ#q%7ZW(Jdq4om2Y z7=u51kBg)-21|$}5c|8fEJz+%aBd%kx(+|-xhN9OLIleSMQx9)I9%r}r|l?INkHCE zD5UvW#_MvFjYWI)nO`tfh}BIeiS13hg1Cf?@-Nh032d-)`J3_oyX}DS&9o^q6^F-_ zp@+m?v-;!L&ka#^Jl8skzGra6eMi?v%kumWmvk1t>1*Krrr|QgbDVulcs}i0&Dh~L z)i0B^!`sjH0hmh({Trj!g1vy^`78@p%Ut$*J<0y>o`w3`N6q?kUzBj_xXZLd;BM{| zyB7yjzL#FpeC1_XQ$9i#{z7d)vyQC4ZtW{7bF1^<?WVNWY7RY-?<jxNX6fe)sN=oJ zt+x~!9|BivvT4P!1?r4_`V2+{R1&TOM9?ZxbuUg89(dH#Q|2m<DCresuYHakhuxn7 zx_5-B^*^s4FVOD2BHVRfLicZ?$Y++s1r(Zx-pFzXJcJx&_hf%M)AmohF+?e2=sH)} z++Vz%tUxWFDs&mITR2K7_#tgst&w2rYXCrvQtcWfkr_ZGILt%XxWBPgnR%Z)c`rDD z9ZD=l&YuXFFs@{NDQ9BYsefmN9Am4Uho_u6W1YeU*O*vH*8uP&A7s!BG{a%0n%(e- zOLcObENDJBIM*{AF>Rz!{N_gde8=%`Q1V(>t3*5<yfFBV?6h^4m=MJ5zuWiU&qMA9 z77xeuM(U659o_L#(1ZFCC1`*nb^q1AS`RtF9RqwxVpr48@uyui2Nf2`5P4O<7TuDX zpn#}-(tOOmy8D~NVz%OJ@7aUzQU^XCSF1TU*m%t#%|Y3UwdrLdRtOt>o^E^|0Q#|8 z^Fao{?j$R=+|hkHB;QRaf7@>1VE0TJr`&CU$QgWWdC(kGk=Jc0NwNWYCL-fEfa_sw zhS1hJ3s@lrHa-ZM;-%})PV%^b3p+BlhpF+{Fa0w*b1LMuFK8)`7}i+X7S!D3mO<T8 zPbah=Rq~nxsi%_&d&ZD(2xj#h2&@|%Pz`<TC)XMDP~b!Lc|OS|xJ1cya&pYu>RH9` z(4tSfD^Gc#CXk8uYI+>ck=Kmw{@8!l7)>|Q!eUJ%)s71S2X*?Vg#C?yuSke0h`N8p zBHfF+qyg|}X$Bm1ZCI07`oo=t_n95m!Rf-~j-i3x#s$#k+<b2@N#F>YaGqECxByt< zKu(vzhrMgc4|B#qn|MjFAG<wYT7<m^nW=CSP^G{Zg~WqS!HKp_aQh?Hk!%UMXH>h5 zZ?$R=_ek~xC`XeBF%V_}vWg6-oY4>d5ZN6|L1O_EHUzot2BgC;l7{GiT@AoyrNbw` z8J4+^8VE!cCOi6WEnFp5q?`-t)^aloaQS4>t83el^Sp_*G3wy=%wk>aedWB?Z0eqy z;j_9<Z*<p{=U7S`A_Y=yMV<PSf(~}CYe+J4Cg&agZCpGp5BWp)N)k;;2F6ly`ag7A zEOXYS*znb|VtXGyhWwUL@K;SGG+03)G}t^=|LL41`4kREau3-g(1wv0AX%SGA>O-@ zT%PrEXv!7M%Tc|29d-Wh71S}12!UN?BYJ!Cd1Zsmm=Hm~rQAKe{In6JF6col)#Wcw zHnZ?lK9k#D@GN$n3?8&xFVoRf1@&M~LVczWY08=OLvpt%gbq#-H~+XN+>oJ1UJ-o5 z%Qitz*v&m481-!nG^Pd3@z=t`h8RbZ*13w*e8Sy{|32ecm(2@7ky{Xy?jQpwMy~q^ z)DdQ=Xkz@@z_*sx)vVHaQuwo`nyenTH?92v1_4Kk=6fK#*w6t8A2l3k0QW#BBedt- zvb^QUYz{2?A6Z~#M;`aVfl0`I%HuSAm!TvG_XP0E1i9!){M|pEo0*drYLcL(6N>O% zr8O!?cZ^1r*VM$T#c;N?Dg`aKtqOPxDARjivv#%lsk|D1^Wgwv0)@G>If0hrn{J;- zz;bTP|BtAzfNJu6|0W%wq=-nPf=CQRx<N%mN>qA)s5Ff320@XMhEXD+#0X*3V1R_Q zv@l9wqc(D*;eGV``=9rman3kAoU^n0dG7nVK6N49j9rt8d!Ca@+kOrDOpWK`2eb(j z@UQ|V5TF99to_~zvee}mdc>Hw^(fRYY2t?cB0{~<d1z>WwVM8}cb|hzt4Iwa{3VEb z8bm!|9xz>)*W7}p9xCW^OM|>Fgf$@0tVQzqjWJQoIZ=+~m9w&W#f9Pi=2MXI;tz#@ zFgR7s%UrI3H8|AMbg~Yn`umm6Av{!P&BwyKjQ&Ice{!OZV#x0kwrIRSS!42z4_yw` z<H*zM`xT%WeZnN%8R@b-#U1*V4J8G~iH)Eu7R`1=1LDK9>ym`~C6m$hmoPdx_mi%M zZBdM2155{|9O+4EDLATEXhKT?c|+cSXQL&i{weJk(o9NmAq)LYiNf=x`GW64mO>wA z9)9V*&B7o0i_YBBasgFEl*^6`H0Icl;}ZWN_v(T?ku?mL9>K+6x_In#nt9de(J%6Q zNk(nQY31%se3#r_F^P$T9*6vR^2=JtkzU3!8|`xUgm6<TTdgv8JmMsu#lCxAzEXbC z_ZK|o;<i_7+4|zNOiiEp(>;^MPz3g*eIKKgai3%1tYsN;e>nE&H;r{-A41ylzUk0T zVQYYce_pDi-g#5D72#LlJP)H(H8*wpod^H_@m=;anW7+0pNRmi5>g&wvw?28u?5$Z ziTuUz7nlTZQ_(-Z{@*Sx6+8O}TK7_8e}XQd7*}@qRvklkty;snc6j=Do+rN!m}%Oq zU@y|~uEsAI2}+T6a>VYsw1gxQsC$49JHSeA@<y(W!RDY*-QU>)O2w|W*Su-qrzdy! zTd@oJG!M_=;&}8T#_ULKx8!Q7gDEftj1b+Zrz9LXisw%hjob(|)WM?g5xXUom|=)) zGwUZpk6bP2O-nw@xWk4S_cT?Mm&qPO3QAVM(1JX5?H47cq3wzowqMr$lFWk#E^!ZR zB-Sfr5Bp(DDaJiAnq<Q1g?u6@S$vobIg>icqoD!MJ+Tsc-=sHr>dt$E4ol;eV9I6k zV^4f-rMrxG*cSFMnv3HQA1Xkw&a*I-9=k%NH0-@IO(DE3q@#oSvMyG2IjLWa`unPw zD&bA&SP?rDGbt~xB2T3bj+dG=;aeO_dhrjH*UzTwG`{4~nX3A~%AWDBJMV;z9HHx1 z1`}I6+=`hpZBSnX^uWj7D`xW^&xe}R-&|2`Y(3|RB7FCVgGX%X$mm)tJqK2u9A23` zH>vrKqgd_@vie@9tMgCd%j-2#pT?im&TyaJ?g`gI1Owddtj*HyF(6v`S2Xu{Zk|7g zSOMNU*eJ*5R^3NbW*6uF`xEdSPl83m17BDmD`?jzM45ax<GjqZQ7wvUUfp6gL@SF& zMx}YkZ-y-NNHw!eGNM&G@$FGJOP%!S-dXRYkmJEBb6wMs14~`gv8<K<Z4bC#Bygs} zA&njZ^!9OEXLS3j18uXNnrZC^y;X`R?_2O<=F}BUhocAKej~!=^Yk`{gTe~sIy?8p z+L+f%^PKg)cc`~NWa@j9VP(6nR-*1RuCggT)9nb|TCMP7+og1WUy9<GtfvbIw?^ym zGUy@??@z~$bt%>*ZW%9n=;+m{QoMc7ZWa!1KecV4z)0}}LCOg;0~#oeQ|?1vv7fh+ zP*)9}l8rtU3%yWNTg+>D5KpygobR92BiAVKK;@-OZBhag>HEy@VP1y0YV~oNTE(8& zDSQNmt%S{OV-+GYR1&c=2n<~9H$QqdQ)9;MuIAa4y>?Cfc_Pb5_uT#Q-4WiFwN3o7 z5qvZ7MNo^xX<Jt*m9sB`L%XIbF1RHm7*^%%_hVoBnAGZ7kv!zv$%<;BLINiNt*P`| z<Z^JL{$J4P-)qWra#Yc-F){Jv$=}7QRM+hQ6i7io*aPlZ{ky^nG;;NubKtp&a|rG; zF;=RotVJwCd(Z~$_Xfa!3w{JMh`=x6M|1{OwAoId%*d0<TxM;?#(JD&&&Avxz-75o zYlZp_vsz#`@o7Te*M58SALQ{XTm<pvOSam;+h>oJOD3ebhrwR}0NGb8529n4n-b=M zFz4;pRaEuoRf5x^Rhh~1eQPkAbJaSV&JA@rOHMFb#cEgK-W2AqjRpQHk5}@tP2YQ@ z<*bp$2tzp!NnN%{x8=6BNz)53(Y}92?@^86&|UfqbeIgvd)FLv76G`Q#GJo;*uTZY zVu-itD8_WpCDf0koG#oq=AeHqRIyR?`=$9#BtwGyqR-CE(j|^`eegG06o(*~>;hKj zM>Tef84U`ErE{`;r^z3Z%2MAXBOB`bz>*Tr$Xoe(iTe}7wH;t;@t;hCCg%DB7|LAx zlfF!*{~%6MgU}yiVOyOU((Gp6O*8A>q`Xf%TJtS%{1=~h(FfdknfZ`5H(~eSVBAp! zo$uzwJ@zD=0zZEKOt)2jfzC*2dvNM8nRksg-R-;RyqXworjRT=oviK@j?9}ehqirC z6+-gA#U<W!GjEj6NM_jQ9omUFd&I{JAd`sPBARv?bRQ?0@9+9vhl&fgPw3nJEN(@7 z4emA0twf&bZbiF&H2h#2dF;qiknEG5Fvslz;EztV^^rFxtP9=NU#u6iAFYw%rok`^ zU*FQJ@91?}8_Y|Eb;ZOgbZqA=;_{^EnmowY)sA{*2EEOOkcUU@`$Z_E6GFQzL9t}Q zFgyaM+7K85ehU6FaYvf-_YDduDV@WL7kYl*S=+q_H03$ToU)wJP@1h@F9h1mq$eBb zI6gZKlEetRF&?sAkj9e-=SKP7=(pj((m=t$)Ltd5f=%e?+Z>X|W9%GJr$O$&6v%(; zwo(n$Ko^EXi^sP@eIxCHNc(r3<er1CDf|fU_rdMc!QH;yLDIA}_kHr^8nfbGB?a%? z<qq@x+1$&w&D6?69+VgK4NpS2$x^})Ha{^hMXv*0$U5fEgp#!k#@m5AM9}?LOYDlq zzBsK6$Mm`Jo=VS-{6uO!?=Pm^f0FONxIA~WDh|&^&5$(h^`tyRu_i27z-UOT&41@l zI7>n)w{OKo3W?%(Ma4QSLT7<%@))vmD<}0t)j4w8_%}AN+Z#)gd;if0+8uHbEa5`Y zYrmv6C*5`VT7_Zzss6+kchfF#JaSe;T*$kQQ+oHxugDjb;l@kHdk<zkQymb>mW)^* zfNb#7`R|6PSfWt1#oJV;QQw=R@h3lG>cVUv94c!v0PWJ(Br&e;3@f$vzk7gFPxwRC zsld%kAQV!j;(@8zML^7q>?U(GT}AhuGneE~h!W=qaqD_;P-@dWDbhH;jW8}G*Hm1n z&}8w+Lgp)|c0aJqSI1mtOCEu+l|yZ`98-{Eq$&4P@{sfSvtS#ePD5GM#(5nnZkE&y zP%V+FPZ`@<k+BbG0X7N?nnt9Qbb26Eqw#(^n-6~%WG?w<WsLk(ti-XAWmg9!#%jM^ zdP!B0w#pcisUM|@f=Of3DdM0B?`1#H*9aZ2a#$So!&VlApYCurqR3)A+CF@b0o{sJ z_kMcm$IHW6pB1&)4$ZfrxloWs2u#}P1WSGbBT^g<Ce2fq(*kC{%l$DJ^NNm8W6wn2 zVG)8HbKZGl?+Xg_0#7T51IsX)7k96qDAZW;rz(5)uognYkdwj_eKm}jJ_Rts<|dYn zbwRS!;tVtM$zwFL0Cr_RS`&w#sLFn}3VGTDqV-+-k@H(A^*7=Btj78vE+quH4rB-+ ztGVS=18yfo0hpWbsOC*>gv;}|UE_}5NRw9ks&k^&Blp*EoPRiMVd+Iz1MbZJqcUCj zfK@p{dxb?RO`r2%IrG`nhrk!G;s0ZqrYbfd4WifT!i~P1wbQ9V#DJ%N2zE~0E)!k( z?C%{BG208dYP4CrS8bcMl<eYu@tZo#3mGQ^%Go=t-1z9{zmZSaFE(VZD=r-JNf~-c zGgG>|5lYzW>}shDq|%vkc0B&Jg5!P|xIwpr2k!@M6jI-aJA9#-i8GL?HFO=R;|gjN zb(-X2)8@s~%u}SV^aab;3$)77&g%)#DbS(&y=}>v%|2h@xK-$+WlmLP@QNnX>&c=R zT##bV$ug0SI`XnIV#k5BSaxcP{=5B5(637s)hNDnSw0g~$M<v!=i#?xhsmWsEaw*Q zr?q`QWC-D|w45V%UV-nimGmgN$vgMS>l4A|H0?1m4~bf&`LQ-{XDXm$%C_8S&zQrE z3McxDp?FU`a#(Ml7F$x`aCWQusNU!894loWLmp818__HZ<u_b<#pm`7OdSC^cMkr! zV^KN$8nQ*(OZZAX<+;Spn1WX1km0(u0ysOmasyJt#o<m{BQEh!kDrLwr$aCMi={^p z_b<ionR@C}rwtj_{b9x*r7OObPS_lQF#fbwZHQwc5(tQYRn!Sq?x|59Vf7^=el1<V zt+u+<u8)AJcnzj)D^#Wls}#_=pajn5-X_?;&bKTpHA01fI7=D8k6`qA;Qx?4Iga@j zHtYGczDrT<yJh7MJb`+FFJnww!nOkny*}QU%n_oV&A#cQbNd!MzXvz}WB7D8HG1!z zC6Z}Z3VSl@+=O-ynS9<p`JEA4k{D;&`hun<{9U-eVh(Sp?1nZ7a(tuTp^l@qaun_t z_67i*(`ICA1*8O=Zg&(`PBlA4ZVY}kPovv@=o@oY-gZU4PTtTD`+y4|y_wD{Jt)9I zX{*(j&6eIZ;LR;s^iMNogVGK{b6vq2A)0dgA)3=3C4KMrOibmm1i$&-pPGW4GqEh8 zrK5pogGaSZMw8j-y^%H~^zlUkZGWg=?uiV=`iqvYIb=aU;*V}`(*||eSh|@|0M%V$ zY@aG055m>S_v{Y&y>VX3#-dV_hr##E^9&UlB^wB6opR+S(Gv~E3sFY4;p(u9e!04+ zI<(zdG9JRvqoqMW$GF%pO;z_T-P6gK1q){5X3w#(h1yBFayMiT&1v?ieBC+WbbGfG zljXnSUhsH?A+-rKqpj+vkf(dNF>2H@z4Xf?Hq1-$U4d82yQQ|b7KZn;3DPmMck~#( z?h$k2f$G`)_Xh!8x5$5evD@q|DmSDsm8mpWu^UU>!^zQIzBC>xH7BF15w7(ySs97{ zkdCm*&do?ue$y4p$+<<>DJKhx8!zYdBXPg3b-$@)6}%+tzLD5l48q4RrtjE`y7=#D z7|+WlV%67w-Oc{x&<@?A@!9rLRWF(Am%g#!QDOKPY)^&GQadR^Deb|AXO9P|IcWs^ zv}eBt>M5ya=m^Rfl6sOhZ*9(2?U4&Xz1tn+%VFD`_oGhIM)jvf=^cNQ3z^ZCSI$uv z)8-Sdj24i;4YiXb|K8JYY?))-PZGaVEJG21nrSAFK&!H*+k{?~u@=qRc-TBvUdQ1i z)`t-dqO*YYz%#DWHG3>L9A8^tiF2o{&**sSM_BtNpT0eflkd->1fUhAK1nW$Yq;H- zFB}xpx4yTX@@~0OK27tkr&@<KCKam$X3dPNF1YOI`Y?_Ob55fMo(_}64OfA!zuSLa z9>dJkf-ebwwNuN}D&r3k9F-6+S^6Fw%JrVbMc|7{eE)|*1EKr6T2{d{{IzOlWmh-l zNdufs!8J1tXTqiBTgOJ@Ib*5Pnm52yGSa~UmAQAjOPd$BbAJbTh~)MP=1iBLSxFyf zsd<>owZ{{A1R!samQhMM+%H>SFXQ$&UpQOY90;in*8JbT%&;uyv&HOU0(*!OqPo`t zXgfYeP@w^BdHl?S1<}9V)XB$jiblRKQ>JB;i2;a%sEK!-;!~ewUWBdhOuNHQ&-M+! zr9s4FcX}C#n%y9*#N%}QxM}UCTULA(n53l0-G4Mu*`DgSrpsex45F1=0-LDgTJh^; zMMsfGtPS|Q_yd{OH&0utzNA*@Ft}}%(c<n!pI)^_ITs-CAiftDHu4+UgMe}blVD4@ zjf(+%1i`AfNURPB711Dhnmo9Z%yf3y=o#V{DS>427Yd6Jmaq(J<B)K_we|YKX!c&W z;d!B~6C^!S5OPm8ofc-0OQxITUL5N}$6v=N`^No!GqFGPq(Pk%&`Ekm`I0_$e(M;p z$1Cl&*Y$h_hmTlfD-qo2KUefLQKUZhntjIImX_PH7U*u93Kro$j5#70KQAg;9aN2y zf4*o5j3j-~Nqp06?dR3#u=Kn3tmzQv`lE5^V6z}M{qibf5{ZZb)im=xro35(M#Pgg zU-9{gj{VJ36wu&5ZzsHJbX(}IYXv*%_MO!-^vJgb*p6!U$tE8yLmFKhaxY)2i+ba< zVf}ESoc>H2)4@yM^M_Yt_G)j`T#MY`l?#0(Ud21eShr=imlM#)Di0wp+aFm0FBy^* zUH8+eHnt4^*8u<B-Y47qbD=X@d4<{$N=(#k=_ggqdVHG{548Ep*nqHve^+jL)J>E6 z={2_F1?KbSsth5vwoX0);Ucl7^-uhoUQFfC&wg%cVNM09cYRG+Z}?P+%+MKSY!!5b zA176m=NfK&En;qNRoHeOruTB26yl-}5U&J>&^tNuWvQ)Fhk6#gIpu&E1n3p9PE1fo zaWIaIFt#Y4-{e+*d$h~lu%_+qaqZlRkl(`Yld$!bOYG-u2q>=9+Wy9BNy3b(_O>u@ zi3+m!EHC%h-uelOWh1Z^^;t6{Iem-N;OPh%6Xu4+rQuu8)dD9)b%r^Ov4r7sIqd$! z#(k8Tm|*dO;m|qeg`{LRT;AdoE0?Y=n=iK>@#GH0syRUOfX@{HwQ`#u&6oYM4nIfh z-x3dHV@wZ1-#eXLohOT4OEjRGp%plQT^%MCR2i==K&XGYTTavbjxiJSYN=N9NSazH ze@7nh%Cz=PTGJ$nnT1C?@tSAx0cu7GF{4i4d+^|PMAVZhr8Vl6GeU=(@{I}b#u?Z? z+5Pz+#>rfx71cH!x1OKB4?(JJ2{(1WKP3DU&Hb-QW{`@CZGp3BJ=XZxM3n?$)TD|~ z6r-aF6TA1%ul{0g>2t*2OA~1IRgF>{DcGu-OBIxsXgX&$oVzX6d#mP-Yu}-z>{4As zqz%JJcY1Gp`Zc~jW5y*l0dev-j3?gRkSF!I|5_1&Zb4Z>YWlLFCs%})1IrWPTE*j2 z$~Es0ezugbpa2?G4>9Nk-7w}e@D;1zXwe|qk&S2RTw~6evI1UdLAG<H<KR0RTM<R7 z0}YA*$=vCe@3unUykF~S>yox|r7YZEk7l{!mH+(`l#byFtwX!Lxlc$Imw75+x00R= z-D~b+TfjE=QHmkbLG_nlmZ2SaExqPXL+o93vdI9~!N%1siq%jo8|3?!c^9~Q_!}|z zPB0?1YXA1{WZ+b52{JFo$<`-*%D8Own(fNB;=w(w=obG`b<9`54wTDzxOapWUcW>w zjj>dv6ef3?UKbOy^3QZ1@z&X-&P-Q>&Itu+r?tZa*;W%7$rYKCH#+N1Bg5qj7Zi3V z)&~=_pC#ad@Po{~<11N%VdnlnMZLrJE75Uo{=q@d>a<=mHx?I4_$NBw)`PoXVg2U0 z@$56QBh|=t+-x(TMi?=5+H`s*+q024F>kv+Wqo8z-~8vwoiub0H<EjiVE7lQ^ipgx zNZfGzyPQ)w8#y?&3Pi-&M;T+<CMy_VakSla0ao8t=K!e0@XIoz|9o1&|6Q>zmj8^+ zGHaZOUfb%A5;%Kp9dyrqm{!S;{CLzJcP;k!MK$l>dTDL$maS6%Z$o;cR<@`f%vSeg ze5<<xH~){F$UmM~Li5!idL8NO*XN6d=TauAf9|=R<-r3o)q1vQM{mM8f|L@?@w6MX zy#5V2yA&I}T|aN-EGUw&__TW&f(2}Ii<pWubb2a|BR5G~RFqMyUAe*tdiJp6Oq6*x z4?kIIzog_94D&PhOZ7h}i$b?{)9SAr26FvLvsA*k%c086r29}WDi}$mZND0*AQ&EJ zQM-ecqrfehV77%KES<s+Kn4<5YOJRr<CsG#p{+x)-mTC#`IQ3)PuDOeAyZS!>(+Xp z0xxMjVsil;N<TShEk)D0ca%z&0@8|A2PE=yC<t1qK4j5{C;cf-aV#sWxOD%$K%3KK zH9d2x-Zf@t`Wv+77h1hu<1G@1>OO6_c#a|1_RE`Nw&6OmHIJTj)2*2T1A@g98}AZ` zFciG~I(9!W>Ht%p=s!cxWQN^uUAP+W`_$FdzMPLE-jEH1SiimnnX;pq&DybZd3K() z)?CZV)&FM2L1Q;vALxKo^|*4qbIr^infzOD3#?FBW$ut+r;1}RFZe!{Je&9<MhYt+ zxeHisx)DL-&VQiU@7E_|h%y|tePp(JOQ#|CQM#IY6f>U-zh5|UrajbupOwPnrc!CA zRq|<6%H+x<zSKet8q=$aTpQz{yL#aD#MgNkftJlZ866KmzVfGt#hv<GVft>W`n8(O zbE(L*u61VjhN;fDJ=O2hwMtBLPHH<*<w%-RsQaL~EZ$vb5|!-vJhyh_c$j7=erly~ z*y3UBip~O_VuLZM_DJ+Ir^^}N{P2e#r8srK0m8_Q9nStlCX#gy%e+NFmr)aex}QYh zerxD8ywoucerm9nc;s`9Ygt`~)Udvb58D6wDR~CYn3s{0=gW&ZbZ+Uij^Y<Q=FT?5 z0rcu&L}#el>iCJ@?It1&J$|;%q#Jgw2QC@S<CE-&4{1el2CyF*&9?C_0HRn46eFED z?e{ewE_`IT|KikKA+5*SFVbskU)5Ef#B)_XaD2t{vN$@l*&}EO*qa!!W9OJi@+QBJ zV{)IdUO^L3H*dAmewyyRX&3wI>6Yc`7eIUA96ZqHk;l|4Ureaq?Did?o}<3-UpY(~ zkHBkMH(^?`;ugm6uyq2B^|Flh7LSduMl-3#dz?ZP^^KcN#AzQ6rkx>{f9v=kE@G5u zsqJkZG4K{n<!NpA1Te+kxp)FlQSObm{=>E%g)^x9x?UAfuJJj}L%d=VW~*4jyt*Gz z&6ujg#tiM_kvxvxhwVhw2RY2&xe64+c-LO&tdk=Q^a~CoPl9jzz|)${b)sVZK<d+q zrRCgou8jxTbLQu=DJm91=6+Q4ey(}HpHyUnYKxl+@{n#3H;EnR^2}`gyDJy>d<H$< zE;2g*LWDPFiy}xR%=9!un#Rf3Aq$*jeyDpQd<)k+B|xf*9X2q)s^?C=I`s(=ZA;4N zG=3@WUWY$qUv2t<$`=~Y0o$Gg9hn5jGS7Bg!;jl}1<p34{l#WH<eu!sGSnER8qDnl z&742X3tFdk7(gFQi3wGib;g8j2!A!U43iT1#!8-A9)jGUo{c%~?4q9YS9#Pgd6Gra z_xhH~Tc&3`b!y&aC`Hl8&4%pU1XAR)lH3`kEaSwcnc&^bZFBcub=J4VhET8TEZ)AH z!gHN|k-9xEFh~6daHZ<CkSrdnLUfu48)p?kfRLD1;VRit0P0+iyXjc-9ZcO3!EDyt zKDF`(ku*f<#jdS-{_=<6pfSKBiu7>O{X3(V{S1J`tRPTW*$|h`jy@0LgF{zzwXiJz z1%aKyyc>9|7$Tf_Q^ZXZVqRNi*=kXFu^frc&R2VKV7tD$e5a0A-A^a<PYwr_OV;_f ze1Q7b)<3TpXnRa>ksQ%9Oi+-HTzVLAOnEw88Z7mr3fb5`P98avXn5Whx8-N)moj>+ zve@Wb&YKrleka#A<v4~UQ9$8f12@?%n?Fgp5!$ejB6KHvs&<P(*AkdrzgD(5#WlSf zh2d<1=$*ft^Uy0Ym8nDgy8Fe=%UcKU?DzR&jHttnsr?TgG}Ioig8hX@DV?FS{p9c+ zQJWBpZ6#Ko3*G+Q70QK+Qm%!o!;4o;RH9OG<cb?SK%$+kxy;9no5yx6>gO=ui2z!k zcT#XN&W-d6W3H)Dpl8jSeC)P0G%Kq3Q`ICd_eJs8Lp_(>n}oXoYc3pzt(YhqeS>w2 zVp@(rI<FR}B<@}^@o;Q5=kULUVlscllkecClEu}hGBg;k87;^$Yn`VJ=xi?{Je`N^ z>G0!lmZB_+BvOMq#onWrB)L<WFWL{9>vBwIfV3tk-KHn@AOgteGU<|ZkwHyT?p#Z{ zDpK0sa^yQdwJ_h9V`k++NWCLuCRH^#cyy!typczV)2>NBdq5y+x#opqT8PqIq2Uz= z&qmg7=XI<VtTj%-l8=Cm9Eue6_W9dlH3R`aIxG>YlQjNUj@k=&9J!bQwVrZzDu8^! zmfzB8{v{oyvj1WyQXg@RR~k$sF*BX@(px4Dc>1<DJ7wiFV)~hsg?hkQW>l$6W&D%- zJUK#6xhA}xrOD%Tkk&Pixu?=X+5LN&Dgm_tW+zS0<zoq1uF*H*R#TP&AjD!-vJ-p% z*`C(B-V22@)kiYe;~pXjBB+!%VG?q7>H$M3-t8+)Vg4fD7N{cl#gJ2|lCJrv(}nl7 zOTO%?wso4km6tQ;kh(69h0LLRK9X61Rc#|@ZG=psJ3@}?#}~|H=zCfY3W7D^R&hvh z2W-(mEO%Q}5K22azyy6Kv`%OFQ}|jKlyKKv4CEUjje<#dXX=Jb9vUHOg+F~FMYv0V zLJy4dDA$|T#qlERrDS5P18nY>s0Jj}^hB;Tu*m$l3<`}_UcR}|?3=WKVj<k$Lp7~) z639w4d{ZP)x?_M_mA7@k28ghG8|+RaaHMv~Ijxir%!g07Y|EUXrk689dEc(V{M}aa z+}-S>n8Qm_xj#g`b8e5vkg(;Ar#YzY4^z($u)YEE*=B{TJk1aB#~x!)`^lBl-iBG- zNpHu4VsqK@JQMBIB`y3`lKp42#l|2`o789B?}DKrgtPW}RAU|w`{GBdl`3ho197Va zcVy=+QxAnXysp@ctFcqjQ<?d8ADS$0(R$`Yc^uGTdujhC=;Z0~{Kn%tC$mo%`|6H% z4P5g!V8(a6>^1|WsR3i7T_61Uhs3eRQRPd=J$8<YePCb&+hXkg=}I|WE{SC>6Kt)G z19cpG*2TGvaiT#MH!(N6W`6c}Fm_4K|8AE2A&dN$Taf~9fV`ynmbLP=`!+`<XYBDt z*Qx5@P6`y6qeJ(EJn<VXI-Hd3(2pa`<jBo5H@de9*%OrsRdgz2onHISd!L?4=1J>b zllzC@cDZ^i@dc%T$5t{ICf_sIyZxw=KZ3p<F3y=c@`rC0P2)oodh)3;_l=&em@WlO z+(woRb0t;gUN_wNeBi>E5)hcoU+gNd+AQAZPNxSV6g1ZFZ>!U#?Vu(QA6OK6G~b5I z*ol*Kyn4Ts$F)Qn7cSeirr#xNeG;F!bF3ZM-2YQmaS-=3EJ#1<7^0W-r1bLG{DLa} zQqEHA@^z?m@tD3|lx)8~&-b|ficNDMl=7ar=hdh2qUM(G0cmHUjUVtWG3RO67mtpF z&dMTeuC{CnGNb`od;Vl^T+-KI1b>+q-G;AV2^=<28d&1yF?6H-pr5&g-VLgoU#B2? z5Z^C4d4;su!6i*c3i{Elorv)o5EoiwPdd(C-1CfE3_=>+Zq?uFR;cM46ddIxa7ec3 zy6m2n+f1=X?*UIg&hwpu_Wzo><zpQNsn4x0@%xf&hd3RpCU`Ayhy<T1Vt|N+k{%J` ze`g5=L+FvtgNXGF>vYR0*6NtNKv+PS=StIrt8Fpu4Cj)ZYZ<?zOR7sP;n-rTg!Wgd zl7*(0XZgAH0r(9zD<F0UPCN6JdSdU<`B8$yLD|&`c#wj_hbM#(qO<R>Uk*1cD(Uu? zaK(!E`$vvv7R!9?t_79gizwHnatw4so)}|_QS#^xoQfeQ#+nB!@E|YlTVFHPI-6tx z1mxM&7$YCby=x#EnqeJxdm;aG5Qf}6qwgVHIxRFI{q|j(V^MP^%M2-MG41$1l`bYH z%WLUC+A)(f&&8W_+jH@Bn*q%|#`H;_G>ed9{w?UW`X8TVX)!Es(<%9;ds*wjBa(e8 zj*<9aJsNb=KG51rpgytGTT|l2si{-cgI-Z?ipvUihVu#7f*-8tM4y+wYWYe#$UO9W z*4r)qt9*q`p+vyj6Dxy-96%-1xCw7KkPLq!W<eO}1<$df1OfxU;;(b3jlO8urwLT% zY>Z!akQ1%ox8+W;{Lwu%gR4|p9c@3lHs+6jCH<|v+9B%rGyoyP&I7+RaUXq}^&5Kc zE^7lcVpA&TIY1~7=ii)3D+q>D^vQpbCR5>#?<{@gZMPEKUYqhz&EM$~oU{i+UXxc; z?ei0ddacY3%3D*9<#|12-oi3<@FMaq>7#EZpi&l^J#cmc0Z<$J_9b=8*?3s=%;8PB zCW>Z>b{$`lz0zRL5vN8B83PmatI@m}nF$7GA}4xL2?RlMj0su!x9<7Z1XZ9rkBtYa z6dh#{8d7-U)`F&8&dFNO*N8B$@hVx+MCfb^T3chzLoquKL&E)y&qCm%PAs#fxA7&3 z?&b`T(u(;YNwA)oO=bt?4n1j<><`1xsPPU3s#^iNic~1RV#gtpRfa?|=7=vSGHOz2 zhv-H0P&x<`-B9)FV!V(xfbGh=zSHvUnSeo-8j^JpmeQ^8#z<!LrFDxPAvu%;#}^>- zjsYO8)n87{@sp{|R5+P@quh_yW{tK>B;}luFc8Ylsf+*Y_wp6YXlOSgIi$CNlRc{c zyz|QgpE%r0D((_xyU10~HeWrOF`>`~aDZ+J#j2RuLeBL3TR+inUyrn%<kKL}*bT0) zcSB@R^j?<SnEsqHv1=0+WIwx=QtMeMr4G_l=sCg>AF_|_e$Vc5-f&%J29~pV!`FBE z_TNQ!Gv}i^$u?4}#CB~27$!@wCbs@%C5?MTl&ut;SE!Qy*K@yAb$-218;8i6n0kf` zn-xBt%$idA#ZNeS5~65g?=(amI2I)Pq<4{OXS8%5(FhHywDzAeylC5~Es59&|AV8L z*Ix8XiHB4n!`>y#xkMF>Hf@z~N&R8e_qIi>ywKN|NV=v5ePi)JTr&|)!%m2EJkCJc z(>ME=s5ZH&xrdC=^kp;5QLkoiD+p7fGpX+u@0vY~nA=T~%FaWJeh+LLpx0VMw3<tB z59kY3ic<76$UUMFu6jzc9??+2-v%qRQ38p&M^Nis2nJ{PhqU$|9FZKNVKz5x_tdY2 z>elza$kS2*2{d*+&D8L@(r+x$cSTG$J$IX_B-f4pfJ}Lr^A*n>;&p-|AZDtu_ul*B z+tz&f!Gi~RTq_h#3(lSiQt4?lTi%|gJ9pn1|6$@Bj*=}bQuQ3GX(m0*UoX+%In@Gj z^@SUc)!fB!<gJZdy017mBNgj-at$|9upu%z(O^Dv#3nADU<^7y%hlVw{-R==jg}Cy zgh${zT~?>tD&Xv4d(9q>ld)_4om0dizO#}5-XAo>+U5&**!<0=KofkFvB-Qv@C)Wj z>~LCKlluz1xX;bdzi{i$)>e0Tk%p)Jki*F-bVO3=?Q{j`Ii7jAV^{ZOgJHeFAhp*q zxf0Uaf)a`ow%KSO)M#0~-J=-oT5(f-?QejN|7w6a!*V0EY4GcEvk?PvqoroDB7V=) z2@G$eHf?L=|GyC6(=htKwg2)fZGZqZf4~$LH~?||0ADYV78Z5LM-JeUVtur0O&SZR zeD>3i;LC?|!iG{|2e>D38+PhEbLfg$M39W09-hjO0WaUZr@G>{7NH)ot4->w#FNvg zuRJe^oV}xAKl=U&5H^q+&w|OyHC;R~4II6JYMx{0DPHkN$zg7sv2zdYJpvRxXS-L! z_VW0B=-J~o(hr_=`^+cK%2qWoc?^GRQMhyad?4Tym%SjD4~1@3IX0p=wj}7Af66L> zAWP(;YUhzh;HR{Q(HjAmFcL~{X;!zt9&sGrO<MnH;%~=Z6GGJ@lXY=Fn9ccE#%Be^ z3AI$SFxX3INgUWgg~;<ZE^g{BNps8Tun_z{%%n$<7ZW}PagB+rOF~Eq+MdeF6fHlc zWiGFC;a^>n>Ax(YQpzxrhC{xl#P#hPU26RCm)>r)Wb*r=q6XyOF65Aivr$KWL^5Ov zOsJx@ZHO;DZW|4iP+(GcTHF*4B3Cp!LKP$5-E2yMm7d^&a1%ql#GUNLKn<em+RKwv z=B^DBzql`s-EDLD7k=SDF;%W?+doI8v8^ijas3NR*^X+vj%@dJVqQSHL7svP8!~Vu zKmTt&B^vZ!`<}3IM|Da^>V%RSxg`AM_32e$8!-|E;JN?g-?~t6_kVKzN`aoq)m5a0 zZLH79Q>92H=T_5P9_s=MLZV^LKo@wY9`VNXrd);eQq%M~?igneMwh*uvsz)tY|nYT z8!}|5mS6Nx;)yGz{#|-{+_yNNeC3@?yENx$sUM}JhPTiILt-cCQma^=BGyZKc6UUu zH_epS=eEEkB+#SP-G5+F`ODQ7A%W)yl)E}mE=h{je7Chrk^)`=PXU`|qtLu-Rvg#^ zsBiG989Ctep|ZSb>I&A?Z%Zgx2KGj}`_rr;QX|au64038nCC((hJ{bh;3?pU;8?Bh zkp%QdbmY`dCMfE+8JF;X-a1pxVOUI5%I=F;e&CkSTyYEv%aXMp75VdwYS4YdC|Hm4 zHIq!weFM~$YipqmZG7en)fv`w!|RHEmZBM{zI5pYw5Zz>x~%n|bKbJ`Q&v=6UY8jr zZNJybhkwsf4gOUC`cb%m)MBlFY#+JVxtjxU>XG>O<%aeaw|cbR`<c*8Z?qZ@*eRN7 zqnxqDby(R@w>ju@c*HJ14bL16zE>2YB<QhLH?0huo(6gi`<<sJ`1BE|tOM+CkGEZ; zEzKfKD@kD#^bU|Am7ek3D+*p)Vvfpa9Q`v5#jSy5d$s>Co4=3pWFp@W5eAze)v4^B zL*V47Y`4n=TpD(R;$W-4S4Aj3^yh|1^@+5^3e@C2n6H={yP+?a<MIr7wjX|FihfUg z5AY{y%v}jqeCBtQ;IVF)6b_pQ(GG0TVLK)cC>Mleo9TCB;PNQ?xjAa*f=BX4eKEw6 zp&>0*zuCo^3Kyl?(OjQ)_bV7{(>UGDeT^$^fi*B~)h1>bcE!VTsUR@Q=l--=_t96w zJ}p&$g9YcoVUO3~T@l!Hczc6+ZQsfm$LyKMnVmV!$_Cj%KTS2Dx4+~b3CKkktTz_U z|K>Bfx1WMAAe6YyZlL7{DJ_+*2&bgTN3AqCS`aTUg@yd~=OC_rA&dc#)~+n^lIMci zur>6|fPQwUQVnV!w)Oq$2k-Z)^94iS*u<g+aDeEd(0P#xDy=I)y3XZnMOGif#vhtc zhYRnFp%ynECHJIP<l`yQpb}<cCKEK@n93O;bK6+vN=gWO|FgW*SHGn`S?_>$8YEi} z${9N0$@d%8ob}cl>NOKu^fx&!#!9v|3TfOna*6XFKYrNYc0#5CnbAqxJ^OaHPPgsr zBxk&0B=!M?%$f7CVe~_hPnO>j^asYWgqq^YS`4@!3p8Okq-RogSRw{2o3aPpeTjVk z5V%T#DLgptrzZ^9_RprxuV3*Eed9pA98&<$=w2GC*Q1s=tW4Vfb#CoSZ%ZSX<U4;> zA+`S05@q0U4<Xq+xWJ0X11!<Yx_takHvEqdSNXH^e)m(($^1ZQP@@OT!VWo3for1* z^Fg);VIuyNI$<LY${#8DnorFMsCdsrLO4Jo@QBSuNBa52z=Q&SlHLlJ5jES2&m(|J z^OsO)vwI78H+Hl7$*Pi5vHC*vH~H$Oqd|F#nWIDjD18a+*WNQ|wy`Sl9%G3$rZMx< z9-HDG8}wtr(@;Nk<d+t@Q{!tt+X8;r2$O3V^IUpG1KM{tTV_h9KME1#Sx|l3W{JNy zPwF1w^3@Q9wu3CI)7TI{svW|@fEijxI^!*vsDO69$QnPYelcJ=ceEXUsC0vUYN(dS z81;g9ksbK~G>l<vX5E+|#^Li!xh#k59D#0sqla*(H9#SW2ho`?9{QSo4~d4^<!O8_ z3e8!|Y|mFLdbqd%k!d_|JOe~buQ+EVnDo47SgF3Jd^{+FnkOZP?X{5s?ail?cCUHv zS#Ljh#LBowl@d@4RCJ>V-%i(cHjRHH_NL31iY%ID4WF);|E>D~u~2wdg4N8?t<thq zeeAWfm7Z<|=S{jW&quCE97EsN&3Adoz?VR#h4Svz|N61NsE#Ol(8q?)iG|3q#(!Y% ztNPbvt;>TbirkUu+-!WP15^ZnbB}(xsO@dHp^HgVY?7M;h#-xuz;(AueUo=}act1A zvj~p0{c-xT@d{o<KX(7==+A)1iqH2<ta`3Iv5tK9Mo9=ctS{q1e+>nU7dKV%Ik8+I z>KJjQ#Ek+4Zz(uPhbL!p1U>;a5f#bqtZ}<>xA=Ul4>6_m9hW{{M=u2OmYixs+9n!w zewQo!;Nh$>TEvtGDy(S)g5z?S{ms+o_$u2Ej7_V9@|&~-zRWkw`u@Zgs{1%{{uCfd zf2m;`F85||m~`)MjR)p%{ATM>{P;egWy|7UNHVUE-1-#W&?V_iqPzf2Y!v)+y%f7j z#;bV$6oUinWU<Kr8$q@P$pDPy58U&jOg=&WYc2D;)(*-V5>VW_#<&6MmMradibh9A ztM8Wg<#|lWG5?3AaaTW-c-$W8aK6(_adZ-MCD{E_e2BB4Es)Fym_>QSHP@CQtN^D5 z0$i8|;B!~wm{%>#A3<Kew;hLWgb^D@8<~p)ax7b>K$mD|_n!4YEWm&su{KvSd#-k% zRn#-M3=P_28B(n#jW^w6>3%smo#ieHsFiyc8rJwZC8R5q9JHLqKt`$s!BnO*)4M!+ zQ`FcsdDg_Vf6qOD)=c0PVp2Amv$g)JSJ@7TPthx#99A+HDgZzqM}_`RR1p#T(3#26 zD`3S7)z#%5*iOW~y%~Yyx;u@MiM?@Q6}O%FgrUV4(U#dxbUjgp$f2;-2iz7@_+9UI zVl7P@pXq0P$m{Fh-+6{`uXUzeaY-~b30^Lu?>Dd6ZaHQX(L2}`o>Z-s>A1R0Balw& z=E<s|qSzLLzO2w~JVzP$a(2KbZ?J^hl`?(l#$-shZ!|p+QQEAmk)($tfhKqKlQ1$e zZfD?pd7b$3wDXEWrIKKkI0LFa=6i>Ks?4%z6ErX^?(C-*=S%xJSzPBDPZYJ{i$lY| zb(^a^DvKjaqWFF%Vm4p9TlPC^7%>@OP3-+t9Php2sck>tq80?~EP_yY1TON6d{wKj zpvsU#9A4+R94TlqyhS?(2r(xZGMfl@Nt@ZdkFl(ykqZi>Cu9%arZs_i$FhG5fe6h* zJF|tYBeK!0XZC@9x3N_oDT%g1+{yLzYbJ_>)SU1&kv<#i(}k|12so_ouLJ&nuS(Y6 z&iU|b^B3l-cZYZ*Ip3k-ED?dRf5j|5NkbWF|B05wC>mDu8F7`nudU_6wysTVQ2oA< z=`6PY?)_Ytn?~WneIxI{jW}%MgfjbDhIG`IooguuzH_Vd5b6PT^<(qW#Q7$#GX#(` zs<W;=GQt)BZCbe!MYIj+Xl!jZkoy`%?y@dly!RHJwP${8bu%zn5$ibT2*Py^%2p%T z>9(z8In#Y<1dfX&n%#jAH_O3fzS)p=U_yY{mbWuPQS}Pc&9L!mV^kq|^A-ghu+C(~ z_gOrA6ExVS2x3YyQ6)0<Sys4p^podq%i4rUAAa=hxd8292N0@f;`n?@bho(~>2yGa z4r%2N&RRf0cvjUrxwY4LI;wsU8-QwABPOG>h?MgUEU!(AJp*Hc3`BtZKK}8IVR5V7 ztc_OdvHJ~vmpVVv7*WJA?MR7fJ^)cgQ-z9NrNa@u*;e&s+FL>U(W|6i-vb{F2zR$` z3VvNX-`^Ni{BjjSjSd9)2^@LFt%qjk`qmEGpVYX&ob<{xX-v84Z%zfsZ=2@+$hQ=G znNcg~`X~pQ<KaGqc$d~M=-?XOoA2@N5f*kI@d9Nl5;BC8lgTco%d&IyCz+i@<x4%% zl{shK?|)6dDbDHpyWnoz4}qd8VbAq1Nj`+J9s88u@beBBD7y@Nb<}tqu|LBry=8mL z&PtkjHaVyN`hbWs{s&3h?T_}u%e^Avy)=WpT#X%q7HRtS`I8IA6SiZg=Q<{0-X%+$ zzB#EgoYUW>b>$ld+H<Y^4a+uP&o@mbN^L4uei-WWEW#N1vBT{j#hC9oX@jGlHV4Cf z-SdM*1!WBL^=qlfC%QPIjvj>iAm+$U@G+c%D8;=(yGbr&ORuoztzy2aL>=)YP4*qi zRS32<Mesag2aJpP0v_NxCC5G5vZQ8DCPQHIGoLw$XS<mJv!#;tZy4zyG(uA^w`6k6 z8wGnCM^Ya(({Kp}m@3l+tY~Dq9}b52M#YoV_YU-{1l9OXa6|@l1*CvNd@HgXP-JXd zdNP^Cs8Qg=6#)ma4lH4=+*NI5wv-P&9coY`gYoc@5@2$@_o3_-AU#%}SPfNk;Ss|N zYVOi-)E;cvcmd+PB381*VFS$0$o$EtJWlrP6(E4|2S)BR?%$!<Hy3;F?ri9tOotzA zKr#TqaOpWIgZP#L|Caz)>ZT|#1}-Y+nSEWD&}yrTJ&eP7`wB*QlX+rE;5(H2qCv*m zt2xt0q=bNPXQfPYqeggmhE$yg*z-Q;L>AdzQ2yzv+9d%L_kBnOcJ$Yh&r3=NkNO+S z_1`(;iD8}rG1fPmk;}~U4$7=-fndfj*v*!WoBunh6KdYds$Yw61#tD7@lk(%gL_<c z7$Q9RfGB%~q7S;2e`QW;^D7}#B^m-Vf7~l^=gWDOt<e)a83);I-W!MGcMn{UylZid zfzRcl4!Q%MgO1VcX`f%1@O}}b0M|LB?f!0C@zPmx&Q3L)YlKSLE~gpudIrlq^sRa1 z+a5}AOq3DWH#yFJmd-xWyX9A4Vd2zgKxMvx+k}m~+e<s8%yNGe@fNhz{R+cK-bvFf zW$Y+%gCg4Z0R|duHl3ZI<lXLQ-Pzkq{X3@lE{KSB#@^~DWw<UNRHqiWvP;`{)Zh)u zXKH4Z-V@>lm>I+Kg@?X0i=KTD-FIF=F<)T0gNe<_fn`P5!(I!koC6#2Tz626rSnQz z1IcMb*0^^mMk4g++mRs0D#u}d3tP{xuG$p;9ZT4m*xvDLh(k=XI9LF*CpFo_12pim zXEdwv`|;!9dHmzqrwlSZF9;kZ>gzXHLrm@5$<q0)KeV@<z2Uj34+b=Dfua6S(?m;* z1)zvNA>jRG{+l92v4Qz0IfPANlE1hz5%3iGD()4J2mE$+MkYV8%}E_x^VB%`&c&*$ zlIsr+eLlE7?w1_5(<nuJbEW&>-Z?+FSa0F5fX~p{#j@+V?CIpB#qXbi<@9BjWTW6% znY6M7j)ApoS3`jrJ{Q6)am_*21<24%II;PAK)}3d!^B_@28)Pm^+@-vt)86+K+Prs zO9m!l0r$hd8)lhw=26m5+0;t<-%jns*w43@#=mtlD*hp|KQy0eA-Y^Gdzl+R@VU;K z<`LUHAJFrnX~TPsYG#9Ff-N<;o-^Aub#<n#95W&ukdeT)a7Th7Z@R8anG$fi=FPgW zjxj6rIH8Q`N|R9Wk8MfCL+weU(w7}n94QIiGL9CIJNB*1)Ns-`R~R$kXSb*6XW7fw zRL#~yl$bUXo7>3519lvPMwTtP#FSUAh+RnJSX~l5vt3hmJmWZwzK}d18Rd8u6(YsS zAJWsJ#$c-2=>B?0GdgBB^G9ma;lSfN6q^rcSP8OD!TzV7&$1vpe^gCqrm{O4z<`Mw zbfBh!hb*lAe*Aicmh+*7W-sBHe7VC+XJJzC+cd*L?0{YKexOxoUli${#61XS<;Bs8 zv$M2M?u}CwVK%E1{jO?)Ov+?mO@sA{Jw+hb$&8kQrEn@JIy_GQ_qT4T_gOrf@Drg1 zbnd@~*(%K(;RtDQQv?Dy=Tusr-=PY#Mku|xa8T&+{&Ezd-_!tf&NF7OHQWE4?l%)% z5+w>N4W|8rk#|P8s_IH<eFzoK#XaY5*^}*+{=6_*K`Y6HKUtMWY)JkP0V6DAD+UfD zF1xW*^p4(WG&|^=&rOm_l^*^1WQ(x=!6#wVJLZ`7dJ7c->c)*<z^|7g{if~qDrWJD z@@J3&NG!qb_q`&ivl5RoI{PCz4Z^p8P~*xybKe*OOrpu%a#E)F;PYwzU5;6BO57%C zBtz3-u%28SD32`5S<lghiA+sTN;&BonK8>%GN&3NnNRMqv~Nj$(zIZtN_Q(H23+@S z`VCMPD?BdYnXkicFNkq&IKv%~vIi7DeF&a=$1~nzu0r73Q%9&HO4=_T3n-1_cXCwg z;wgK~^=qnu{b&VJdMGoi0M8d~hlZ<lrFQ(QdNRuz$#EO}ytm2xemtmC<lpoYXZVzU z^)c0^`bV{IvxN_7o~EfC0aVdY6xD3j==;DQ3X9Z>w2MB!5d1ju)&7`p<{TT9s73>S z1K|FmUIK|szESEFqR=Kq-gN$6z&z%C1DAfk>+!`SmzG{5;~|$RzwqvXSU<}-wyFT_ zcPY}>4OA*exlVO2%St(2+X*4g4MZoX1KDE#nft8Ze3SA(OElroUOSSw?R3{_KB;K- zp|CeQfRdU19Um2Mn*Qe5zx8%xaH4K&c{K()%xJz|SukT$z&1&W6ok(8y2U5yHVL~_ z@~)UW<x)*vPwUNYIFAeNGqt`guvfN7P<(nPSNad5Z^Jm{dYekV>>RN%G1p?=F?zez zsV~KEWgOxg<;3cDL|H3jXC4#JoM1?}>~vIpPbboHHsxl?O0HjD6;7Y(yL*<i<=z!4 zWI!3pEV2;bNrR$a>V$AD(9UL~6on)4IwZ>Gg{E>J)6{%f#v*nQ<CMg8QTf1cFj0yz z1WVkX^_MkIse~EsQDWRv)5!+i(>3+rdw~R*Z3lARbZ?(fuJoo1Yigg++l?VboxD7G z1H3)C_qa3sL)~H4H2t~*IE>fA4Z+EfdFwFtt8rLTD6K|WM5Apt!ieuP!>1?|j^kxi zh+UBk#VJ6(l46RB4i&BVWvSLhJd>|MSv3GFLLlLzA6b2t|JaoUo{NvVp>$5;q@K~& zYE)ixqGuj_ze9l*ED?OglxLXSu^(OD;jdp2t>;<7fi`%SMCK%)&1lT)&wGe}RzDC` zS7*0|hER<e4CT+}<{I&O*iLTgdA|aZdYgxivVpd<Eufh9qxZ>^dn)OG7_jtgSoVhm z^bFPKvf^4Tn!M$^fpw6v@YEqLjRc@7e|1-4$VFLm%Yzo?+4X9&1A<tkT581`Lc9N) z81|nKDxx;wBNY1>uSM0AVwu&lT4m^Z5G-)(DsThUc0>Yu0}kD<`Y-3`-OWMsuu8cM zSQGxqG`qrJ`Q%PuP1j6<6&=>kpbsk_3*YM1ga2$(WN&LTr#DmPPCu8S!{2!R+@kX} z!LOu5AKpcj1f4fRA(ODN(jy~MU&ZXoAvTC~QFtbKfMq0h&ci7%4f0a%iz#FENTGYv z{8pT4TSJzGY>mU)I}sa%eKMhv$%y2*&B7Xgo#z#-e`x1)0g}#3M<rK^Vn0RQhZm(( z=KO{&eJN9p0w!iNfJIS@x<TVC&Uj89YY*(C1ovpBzO~BPc*~fMeb-2~Oq?iVK?{{D z8Gu#K-C8W?E(Ja*aPIVWn<PJ3d=v|I$*M5}5lW8Lb1nfhwqQ{zXAcR2%9M2C9k)u1 z>BOlys=yz0fyr@^s9ATY0PjuGSFc{_X~bB(0><zep573E>OOwK+pcX-hnszto+H=R z@YC_+^>Z?>O+RPue)hr56lk-kg16eiR8~<P>>hXUrY#NHKo_d?bc!ye5;>i_z9E@C zEyQ}!>~dK!;;{4dE2;HIi(LKgO@4>72T)0VN4)h<{Yd<dT%Y)Cnv2qIOFcV$#fyDc z&_Q)7;J*=-z@Bb~rIJszWHld%2{C6N3Vh}SDDlc-r!X<PT|pq=J|Z?>@&UAFp24bB zY%XKN$7MH$C&*^lVRLVTrFlci>N}UazrZqjYDb_`mUVJ;yzu71AQukp8>Ho&2ESMF zToDT9Zp}RDe#;GaR~Z6$Z6I(<85Su$F73-brl?TBMJA~|*o1O`El^eVG{H#6?{f5w zs}huk!juXi2FjrEXW*|EBu*6>vI{(%kT1|)`a2Pm<E12GKd*A$1s(W0r$6MmX<*=m z96QN=?o<>)ol4EqY7e=G2wzL5_a*J09Oy73AKc5`WndWLqu?*gLq422zc!l4^7+6~ z)EQ=G`_Y{!Nh3M#W0h~}rz`N<@*68HnShxgV@i0Ff7=iDN78Jb0v_`jNZFvqqkIHJ zoNoQu_1u}$08)9cAm>Rf_Q5~K^T)|693Cy36E0U|bBROjZd*S0W&a#`>$NZybTd^W z-tF(y=3Xq{<eYq@EE-?uRj+y!>!&b($E$a$c{GxReO8y!3V!oI<i97*OKB-U@OedW zL^)r=9Dk3`txfk=Yk+^g?7-s*L)W5{j)VXpSTlDQzeT@5r2li7e>2uqYiq=<&qrRz zOwQpccs74hbil9fhN3Lz(zQB>ddn{=*Izd~4gVie?;Xwd|Ne2?vsSfLwM(l?rK<L( zs#=>;n`({Pdjv6ynyuPm)~LN#5L9iVMq?#L#NGrk?{`1n-+kZbIQd7;iR1ms^}5#c z`7l=5T?CAHjV)mcBij{oiwU>`9ou<O6?;OQ?;w8~S>XC_rBGk+t7})R%XX6J0J3_$ zFiZqk)=w_sJDUv9*i~pQd;_-yr8rrvJPI2c#$I{6tE8LpH{tiTMvi08MkLyHZtSxD z6)_?`1$swUb?#=!aCg|JX?$?woVPy`d)$(oospf0A6d5kDrmYOi5&I>2jC_4WI2S% zSLT;ad}+k{xuq%R`uPfjLo;=~2}ZGcw;|)tywjN$I*><(mqadEhxGtN?D*$yWkn|b z-MRWGlGi<m*n3U)%sQu>ePK0cM_cGk#|b_IxOk1_)m~&MzM9W-8E__UQ!LihP$Tdd zJpFqTJvE{UcodzJOYo&mN!FcwS$}q=L6Kz`4D7(qM&l`q8^qx2Q&~wuuFpIhrG>*S zWXhDs;FdCd%(A#l6foK~hd(w)siNC5zx!;@n(T~k&l-?ZV>3>(14qb@Lmhqy`Q`Tw zG*w8alOKyj;A-B2&@0>(!X<wcn+E0VTFuRUfHj5x8&`z2sR??bb-tMfLSE4yKRXaG zr4JMNuPSn~ZrBwb|CcaV&C)B>R5b+Vd+W)?et@vfXykucxhTy&CQG_+ZX;I`wrL+d zUv;FSij+`X<u{ROxHl*af-6Xfv2E9Wrf<EOzS(|2ce9B+KoRSQ&j{JGmJKD@P;L&< zDK>{FD5SWu=*8<>o!fRCSQ2@)Vx7R|sb&+6nUzG337gBazeqQG5%jF&r-yj*M$(O{ zX;YL!pUUk0rPkBRkaa+Aeh+amrCOpU1jFUgla;S{pFFsvEXH`)5xTE@PA78z`~a}R z=&~#fmcr}K5&QQ@R1mB-TZ|j?5DM1x-2|dzt$YNZ=iP(K47ukZVlnqP+SHWcwiWH1 zUTF|<W3iMtDNi>~4*LSzi0?N3t%f^P(TAN-^XagHMLHj_uarFDnlt!JjMzXuh0!7~ zcjTKwpiSTqD;e$<qL`O+twd^glaWNT*gWk6QI^h0!joU+tjfgXX%C5J>dN*|0i^fI za%?z$d#nSd3(&ZALqafsh<{Hyubc`07`|x8cRDh7D%B~8KDf0-P2s8Hjp#(((%3V! zg7mkgXq*9%5vpvlu+3pyO;1*8dfCIUO4gOlkmJHy|FOF?=_A{5Sz@BMuzjE7Jo8yq z(y<$wyt8#y{YGo$PxYCwsEgis*nX~4%WIiBY4QJm?-+1aZ}kzRkcy9OF=u}Bh}5!o zU+y)aETAP1d1@B_mE0RR5<sf%q^HWV_4jVQC|A6~`$h+9(o6eo>dhyXFBfx$ALEc2 zcULVpKWF8iitn?avwoL%^c_O~5+AZ<YFJm2gnSN@y{kpLjYYN+GT$%+v5sP>6dc~U z3+$S+PZSzwO^6f;7JK9P+4U#bW_e#*RtcKs)f>P&7>}7~cU!i2(+6BzZWh9}iD2sb zg_w%cOkqD+i{{&{rTSkh`YF`N9`hIg3Y>sWuvT6C7l#){1-kVOSgHZH+log(Aw2s) z0;rqi1sgUW8PxRkXrzE5Zf#=gk4y8|l4XhxE-J$M8KRz;n@M;fzP4svT8Rh&!m${M zURZ6a@I?%*3-xL<f%E{EQ^C!#bJ}fB-T<cTE9{k7Ig2^LsM3|3!|r7ye>c!~J;&1@ zDF<lFkZlNinzRvJoLsn?5nJ0b5D9xw1glEwFUTsq;t~fPN8EQZ-3*qsd(&hwTk4pi zIeq$Mc7CeiTn~r=Uv<Rq;5E*Et}gG)JlR_*(%Na%PpB}OAYI2XnVgYqK6IXwbJ5tk z3QRxW*1%50rL#Wrrz@9-BYirp6Gmm69U5=$)7!aO)XX$hCtK;3n|!MKW1itq=Fylw z$xh<9e3{qgA9vS5`*Mj3R7Ps-_nDWXOFzM}pZ|4e#T$2K&3|#iGU8^uEkVsbQp&B3 zi$aQqVTZcw%35ywx|6-!@jmJu{r{;0fqg}~O@@CGQqdmIAw*A;^<1Ba_dts1V->(Q z<%q2D&C{_+aRI@M+n`lxj<{x1*!OxS_%El9`irxXn*mS6tt&>l<Z=PD0cObUhIlv6 z*GnjY)93@@LcIuDmv7$UFS#-`f`T6C$j>tI$ckjU1a~pZkXf(0bo2LmqU%F8iytn~ zZSQ*ez32$@)HDA8tf5&azmk{fw%V{JU>9QQypW{^v;udp84mSAc76caG?48$^44m! zA|Ltl;yNm_rw@)k$*w1HqAov{9&w*o3{nn;8dW4EOi#+$l`(<ORoWHJ+1^gEKR=5S zTs7$Ox(m3NIu7}%M|fk*9vKFh53U2~QN}#`N*Xe3qxKEP^h#w5*%67Umna2Rg9Wyf z^Ue|a*JUT2d-~Ha!}!1JjI@zjIx{#Wa;ZPWME$F8w-ydVx20YW;)AOgr=l-iiYUaC zZTb2F1-JCND-7t51^&sptlD=m|JKfcx8LF_tnxlL*oTR<3Cv*5<D)T6_=cW$#+A9! z!^ckOFO&w6=1&#*4nFS*-_sgsv4ZXJN3f4-K4!3m1YTu&{o0=^m=%DGrf8Us-aW22 zpNY)iH<x+P7+4>m|K(PI%1LD4svpgZ*yBEjSSYN%)bWGvz*c^DWVZ%+z4#{(t#b25 z+<|_d-3VhbL2B)|yBEyf>+BxjQoO^uZ7hD`)+k-IzH!h<pZ1v~T)5Q~RGI`5Q~nYR zB+qSc5Sns8Los^W)Zg8>;=ZCxB7IQv0L}Bg=2*mSw=Riq#<fZt?Go+J5UkF_T|AC6 z9XyF@I^G|8OXCI4;~4{yY-o39$-AQnk6*soZ+lI7-_cP7_fD!B<!Gr)8lE1&88e>_ z)`nd-5@)X-))q%h`i>wv-`2I<PUYevobgDl`}t8`&Efa54B*5dWSZ0aOekC)PX41C z>*0U__T7sf*6wS5Ss(i&lkaAMP`6gL`|ZYi3-LPQq|CzyG*B>T*U0)$-xuPUm?uFu zP+{|}My9xc+Ec}c*GE$ZevxNlh@rk=$airvK8a<bCZpc8JE9XeU>RS!-E;6hx|X<+ z13R^ySca*NK7Ze3{Zy?A>h$gmpT1PjG=kE9UnEQa_rOPsUi9K0E$!c3ov_JhDR%@2 z!HzM3@MP|!)<@3-vhHion_tlO0<9BUpl<$OKczgf3do~npG*&i)3nT(_4~>=m!*V` z$!FA~csvzPEFxXNCNsnX!(^<)`Ohv{t?@d6If)#Z;hLvvrUZwQtIdo<e6k`2K?Y54 z131<go*G`J?`9yH7{v#D-3f<In)^yS-mat)TTf=p(ef11C(IYcO>P`LD{3Mn2@C7E zQCmWzHf~8Z6p?8|I6<j%^Ql29$%0{EBpL3>iZ9W`H_0DnVasDoMYzV*SCI2)c<F9- zDETCxC%+3nZxeIs$1lt|%8T;5B+JdWo1_-~UaHZ(%QIlCTh-^xzJ=ur-xA_$oVoM* zC&|`3!T=+xiQNjy5$Na~Q!<k=7W)L-GVWJ>CAPI|<pnL;I?BiT12(K;th3R2!fqI9 zH0q!Vq1v7>A$Fd@uVOXN$Nalrwp5)d<jj%?uZ^IIh^L&6Jg;PbmmMn`!N#5v>zhFD ztROS>`Bdw8P;Z1@G}wnYuLb$wX~v&jqx-CY8{EJDc$kc50FTXS2xrIMxmz$r6tK5z zeU<IcrSL!0`)QH<nEk(ZcCy_r7%^6D_{H7M5;h8}Mx4<uZZ->X#C<id3jSkOKJ<sG zJg;{SbkuP~-dmf_zQwt_(r~UbT>j{JaXB)^c;b<{><_ai&N4DNtWY<+h05{9fPQ6D z>-yTxTx;#vzO?gEW6qE{c=m_>((G~OOg*$GgLc4;M1*%g5RghU*1_EL_a{Wi52~t7 zbtH$ZAgGHLcQ96aCv#Tho}MjRA3yJL)y_nPhhbcoj7(WUsHa=}z`<Lfc^?WZ)it=y zV4LBa;ry;ZPQ^`Rb1h=kBAA^6(Zz}!B63OH+@Q*7F8}-4Hy;&B=q>G0p1qNKe%W*= zW7$MCfoLYL(|0bR-oqY>p`5L)@naXk^N7k}#WFWfs|uIyEW(z$HEoJHr7z@EY3jn& z*ciUBm2fMttum5NX0|<i!PGbycJ3Mf@FrkD6~NC$%I^mv846#JX~at^`0~9H3uQ&^ zZ^Wus(q|dl_+(_1YU%_Q<-EK3op$T{rfCtq$9dNY*3H)midvr?anAU$#fa}{a92E@ zFh=aA<g>H92VJ|yS+YQ6>j0?RrlvPmFGJ%R9EH;3aC~u9mCdkP#U}ark#8(O*9M+8 zD%`|?A_I)7aX(Kv@>iI`^omU*99em&x_X{*1DkzHKL-8_%>YhlnOJb6ac5|f@)cGA z&gsyLt`vJPxgD^7{~L>&ReifXsEu;F&<1}nre2xKUAw0~vKA41PC0R_m|MW*-syMa zG}2^zDt`xw#9$6u542B_>b{cccen3UP?G>@n@I3xNSM@C#L~2jZt@_jPGf`cPe+O+ zdezFEb_gus#=7R3?RRg@DB@^SV2t>%IqkW(!oiAjU`3ZiV89-AdC_W4zLxH-t~F8m zKeeC-O-wi36glf}Iye@5X0XF6h8NP;!I&t3vGB_q9_6cEi)Uu7@4ga2bvW6dXU;)i z$yKV>>mvSK(zidA=4YD&TKqax$Wl!0AgB>9MHsNd)<6CX*)hSkT*~xn@4!25$qp04 zxtEDnalK!{x`BJV%2G->6`cvT-`ZS!s5*fPP5uA{7qQbfLZ9kX=*OY&u&Fn6H3xu~ z*zQwwX((l(fZOh0A(F63r7%Ug6)uI2k|uXBVf%tP3w#lV>q5U|oeLMD4F%c;*+RVJ zTK~S9Q`R%F(X-nh<g%E4NbRv2?dBeTA*1-I!sp$v;?+<7qdw3m){D8w-!I1RTw?(* zIi_AN>}?;ecfjQe%7h)ZH%+ol{;CNeFGv%~91c(cN-=Xw>9V<k&A9#cM1M1T4o9}> zbGTNL@LaI$!QYX)Yu#qX&RXZUmiGL7iTICxOE!~dX^H2!wRqROZfyNnxluc&iF!ik zfCktVRkHK`PR_9~+)TkC_-mlkmrXectn8~MK|v*0>$O$ABLLp6jBbwh=nqD01DL5H zLYHJ;x2N;Mni<F-NJXI!)r2eB2B>TpusrJ^Uo38R=z4Gf@4F50#Y@ecG9TgAt^LBa zngQTev1)yeS;X4@f>Yw~&8y>JcYK$?hPG#Lt-DL87K)1XVJ@{=?GR7aFBwX}5XxxL z4<Xsm3(WKU{w~T?(*pbT;ZJ1?=pPozSKdl4>iI2)+sICe+c%t6fhMq3qI6*G?rPp$ zr**e}!0^g2sa!u>Dn36Qs;&BMl{C}JdrwCEX5V78cLLON(Sf+*{{GG*vKW~x?$(;| zLcHB>lI)+^izOunm9`4*m}8zZ7S}RO(KUabI*^V7()UB_Z<|^cyu8*9kX8Omc>evI z$Hw|>8&?#aaNHk7Lx9|fqU#fDGBCTzdPxBohz&6m{*TU9mEXV2>a08ERJ4v8LtE}o ze+g{KIyM@fhJ9-$%eYs09MrV#`GX@#W3aPimYlee?sf3qBaxFg#(+zlzR5<|G(N%Y z7T*h{84<_se0<0YVY8jz#O7MN&a1u3x|D-$xVKL~1Uw2u-!q>w({vtngGjy*R(>!+ z*LpxEO8dJ`F#J%t9fyrF-B}^Wo+&h&YB?EFPS!Iv@jGJJZ-$Ivqi=+}$m|`QG)52H zTtAo$>e80vCUg%KBpek*Mgjd`HKJO88zSDLptx`{3|`TFYJ-o_?NF^qd$4ey5pX$> zj{ecnYIr~RVq99}gm~9Ij(H)(H$xcENehun539!MoJRica8xr2_SPObWW{K3*3s^~ znX?!;9^_jf9{Eaes2_ypw)wZDCsWZ0I6T5OB(!)Z2mKi*@>;rdJDd-Z;>5Q1@6Tp) zJ4;r<qj=Z;njO{g@_^3l^Z;MdZQX8}Mxx`1*Av82Q2JugN$N*GFKJX`8P||(e{0?5 zM_P~Huz)DSw5YJ|m6?tiW@R&8kU{%FsJ!e`{kxT0)Qk^nL77cVY9{bpeaLn!hoRw1 zy;50+yQ|{PC(emNd%<67=>DpW`7C}I9h9s<hsKK#_kyq_r%6FlMklTfvgoD@<Vn!e z2Xo2f8avSh<!oN<x8hx#xaiiF6T7?2U?Yq+^8a1XB+cv$FCQFL#FHu%CvHu<GWjYi zBw*?Q)7S9G?6Cc&E}H)_O@ZKUs?_k=c$nYu&kR>%h1f=T=p@OLVgEe!$GcT-&l~M) zYpN=m19gLTlT}LVAPuj5jfl^tU*o6;ab(m-rY(+|L6zhJbkN$<1Rs4I_1V%Qbyvpa z+@#p232y%IZtR(Lv#2?8={C)@Aa2aF%RSmHWW`ScS|!&wOJ09*@G?M=NU;Q@7S;e5 z>PzV<9_I`pluPI<qzD5oRt62|h@Pfwc`@p10gPX0l?*Oyr@cxR#|qQ6$Pygv__(r8 zWYDC6R7ZUE&%~a!OAPV)kAQ3z11f4MtmAwE(pdAyS1<$Fd3=!h{5a}zQ>uB@ekwbF z_h_{_MJY$=vPP0{BU7=BY~%aw5ePKDgeG%Yypc$FXq1fhnKn4;W7LFXO)rVOLtA;G zn<O7ZiIbZvkG?@_F@S4D<F$(C>OYCMown0tuFEY@vVp4y5k4=l*>(NYQ*%(l_eqT% zUy!Eb1XRluIi@~I3A?J!OZkZr0Vo%|JB5szkIXr|tIRq322+ULv`(h5s^!Z#Awlw; zs`CXDR{ZTmkM}KvinKMY(XLm<Rhts~^$oZ0^FvnFNeG|#{FkoQv#Rj|{wh`50tQ1P zieY%5Fna5C9=-N2USxu(L#pO`Ilj^iHnn=cTHa7g*q6Wi^*Rp1_rDD7|KdtjBjPk8 zq+>t))7717(-xGXx3`j2TL_uyz;j%j!0yY*+BCB+mt3%H4od7<oV_Z10|B&W&>LPx zn$6x)(6=*VxO|U3KPTTxwMyB6IzsCxqfQ$<P<bTIK^92%Bzl{OC!V`++})#ocq#}$ zL>w)2Zo}VX@{%T(*Mf75!j)RmYJD}QB)h}pBN}dJ-|4zYzMbA!p6~Z!;5q%Xejb;Z zOw41KP)wM7^f_g4v;aLpuec)ZL*d3l(*@xXcTj4)1cIoz(sg8xAo<URm&Ir0`xYTl zV;QY$-a>q%^&0z>ltSShZNSRT_Qm&Gk*ba|H~9h1?UqJU);mkEkwm?*m^&~}e@)oT zShI?D1{7NDTBv}w&NlgkN%qdSn^;^5Ilv8D)tevUEi$KPO~xXzSGzb?MofE2g2>Cf z_r69ugY{P{nUifE>57N@90C;{p)zc4((In+xGJ~i1JC#rsi?xl@9dKICsn=hZQ8ya z|A*}U7t~=X7CiRB+aJYH-jT`{Pbk1%*LO%PIkE)-ZL9#J>x-^`p?^!>Yy3&Hno|`8 zJBBI+fYDt4uwOgD(>77rq05+&UuF2l|7?EhwZy!$x4j54y2_6OtM?vTH-pPo1a{9% z11^lpS($?m4!3Dk<s8HdL1P~Jm6=1i^c}Qj8s(4&u}$G-gG}!`azwWWn872vgh`=( zh{VE;9)AZ|vz;kysY0qkYSo?TgkV?*RN-hV-hgDAGnH-eh@&HuYzG;Wd#;|ce}^Z9 zf-O!6QnGdz(1IxuA`xD^6wZZ=k4#ImjprpodLKT4cBcfB&eR2^Hb_zl{1J5?`Z|{= zQvequzYfxpk)w8r0`rA++LfdBrDq3IZss-b%>|Qli5I~uSGY3H?h99HQ&d9}!L%Y0 z9y_=rhZt9$MvMh5YoRjPS>_q>B$;RW9Yj}3;7JE08!j9@w((|&P{LftoxnehHS+Yy z`^QE2yC0z=bo9i8U)U3@9I{2R7fTP4h<mQ?bOrKLXo_n|W)#WWlI}@JAcJBu90EtG zQIv>UH`x13#HWy>KE|%l)jqSHAFql4MhDAy(0t8)MI}e`@l*4u?Ts$)lkJF&HHN=E zdsPDF;<hnjG+Zzxk$BSW_jJ!yr$HgrPFtIucpt3EWm9t&Ii>yWkyRF#p?gnahduAJ zn8oF|qVrVV*`F{(j%WP8_dW33H~7z?-JHRvPB%LS#*t9;tS)62t;#=gQD6VJ|K8Wd z-nMXWwNSN6wcz&R#m)zj;CH&>D3%&8a6}_yLABJqL36Ky#p*NT^Osgdy50iwj{sv^ zi@A;H>_cPPvz|8XgVK%W2Dg)*7+q`-YuV3s%#zfYjs2Q|U+lS!u<WAbalE#Xd(k$w zd8VVyJ9#Z?;pat^;VERVsfFAp8X-Zt!YvDchbj|(rtkq?7ge^&Yr%GDnY<kr>~dJ< z1<v?qG%Jst_bC%x6N(;XB8V4+VQq|S^F!K_@`I91=1b3no+`g$86p}yl1G_bJo|Mk zf*|$7y@|sOcG}>U3JsULKDtmH^9WFYzlG@TP*+jr0|L*87U)Tka&j7JVcPq#S#!S+ zKuc>|h~Aj|BuflRkaiiX>cjD>JRj^N)6B^4py}Y3=Guk3)$v2WSYtgQ3rVsOyb25% z?B5>#`&&v34*AV}=KE#V+&>q6-Gvw*JFbfF?n06h%#c0s3C82U;k(K$*>uy8ksI_R zs~yvCPpV2xrtf0LidReRCFEE?M%T-V8mTwI->$0ke=f>!d?WL}0{P#oCATWpcQmfW z40%A*0<@1Sc)rp*P(z~R`gL!TSw06Eh%qV=QPscY{uhm<qWt5tNTpV1{S!YmGSFf( zP!*W(Ap7p0^#j{mv1JfcuzwX#3+j=ktRL%lb}hKIj6td9YjGFfQUoy?%kur&eK4Q! zJRM%2t)VCRjn0f+v;lG6;JrUlFMU`uH=-J_cRb=Pv-L)-SfXk*i`#!3Fw<)+RngNR z7m2tk^U&*+gi1j?9HGckH#-ot%EO^@gTW6k)p`5_>ZP$EXxi8&$EGFT%Y=>mf_sZS zWuLice_pw}EUOSf|H`2y5dX!`*v3UfnaZ~1h5W1uC~$q0Y({M~9b*8xT2b<J0h~=# zvuvF11or2x6S39i$Pz7BvdA&@mdM%Uv?KCa$<3A+Xo*~MSMFv_Kk=X5F*@FE-C;!t zJ+$i#wm*}_k?cuUrk%@Qnu`x(I_z)+DnZUV7wlG_fBm;C1gO0e96-P*;kARGJiwFF zINb@`<Ey?LE{mL&z)JO=-$%WWc}LYNtcCclv6WV?soyifl(!md-YES9x>x%-2=%0r z6)g;En`pmx%V&F3tx;A3$+mn*7-BC6UwOy;UE?S}Hh1TD!H)(|ynBRWU40@0c&->v zZq>T9*2{(dfpHZPb=nO@eMmakettxo)EO;rPJcXti~sMNdd?(K$rLup5S$+aF;?Kr zuLk%v1Q6BsHNe;86c9@NS7l#zH-*%r?nlPE5=C^@NB{NRbeM|mfZi{&1=P)MB5Z$9 zMPd<@D6xTDwvCZZ1wN&6Y7|(MiPytf5>ZJ{ZbkZop9&>ba`CoZ<5B7PlIZK^Qm=kT z>7y@ME5paH^qae4%b)(GTsPQM!H@da1{WMa*Lq$5a_B)$!in1oFe(rF=8Mgi8r#4^ z_t{(SJbkknp0UtxIN`j{BeZviX%Z^`Lu3EV0_Xe^k4qMRx4Z#rz)~w^f@6<$Pd#fn z&>}7r7|cJfoul<nWLnn|&+hHu5f(*<YeAwmhlm-T7|GktO4N+4D<?+<lT!7bI;YtH zK9M50TaF7t6*UCrYRk^)y9$BcS4!+*%a#87=9|1LS|^9`6hZtO5Dfy>#j3|<FH+xk zZGxh3=r4}(ajI(aTn->J`AEv(iYMl;bzWb%JD(3xWsU1tWF>)EZDC$PAWnqinODG} z@_Hu9!@~PKjd5tzqAbXC+I3P7bZhzeL0k(4=G1BnNZ`F!<tqnWX8?Q`+Gpxk&*ts8 z-D!H>1IzQ&T~3Y|U!DO2Rxy*ad}lZVw~toC+yKw!T~ATWpG@|{*%z3s`3EqQJ0;%! z_+`TID)&C*MJ(I@(r|?eeiF;dElqnEB(cxFKBS8Hc-}$j*ydl}{pCNO!9E}@*82DS zNi2C29QP&4-TTm`b$?xrKkzSoi~ECS(at*F3#@v7HvJfME9QJDY`0bR)3tMXs#$%T zSwW`XLedX*{vAuDDimOY!Pas9W`P<vt2D5htU?nNF!RU`JhW}3G{Bssc+v6;JmC^a z_j=XmwTcJaEZ0DGwag6S%K3;59gRC2;{vQaynT@RQ_@pE+uTa%Uh^K)Q<N#ejNu<E zQbx9e4dSaj!YaoOQ|wbJA2$rDaiwaMxkwhip>7%wG3t0g#d~r%mqWTD68Hg45}0ph za1z`S>n%?9cuC*$hR<!EpMTi}HNu1NAJMD#T#}Sb$QLTy5Uv_aP5}-k?*7^i?Hhrc zGXvhY;?+}FasoAFidu5o^8-7$JLVU5pOWTWi4+DUB&rdl|9mf-SkTcn1rpv2$$IDN zn^*X0yjt}U$>48pGv06n;1@bk>byX?5bf1BXrP^GAzgH{0k;0?lJeX$sP$G2>;SK^ zm3zCPv5mqyC+}IDghXn01+r$GIXp;K<hP$Af{$H_c6owr(!GS~Rn2EBaDAXYc(Fj@ zuV^?rR2GXeffTeSl;NAcIrkAqlKjOl8HpYUSy{!+`%MPevxay|b~lQxWV-Zn(|Uw( z3a*A!-C5>u2PE@$z>WUn(2zltYBs_))N9AHB8E7_HSnP~eZ!JCfN*~L@IUi9Dud?# zoWSWDD4NBYyk5#}N!f^|v_;vnU4r50$I~%>l`Dt$9Nn%;>uqG0XZVe*AbsbB<j!ny z2^D5sf!l8zIF7p%rkZA0MJ@|DWdKLfLoV0&);TiD^-Dd^^2}gf)ygEL+eCl|43ys- zrhQ%P(Q$QMdvc<XY~l^!IF_(s89p~LjaAXr)y?1k`>A!NOn<Zd_NP#JiW?Y(M|bH+ ze$j__(0@^+|DrrjL7Y#Yo@;j}I*<8|y6{sq;pe{<-%<SHe6FnUC^B4&J|twHlOm>r zf~p=ZUy8F9Hgwd-OxiwUHZ>Q`h#kl0BP0S^oaY<Uq-qZj&h?&<U3#5m&ik%6?&8f1 z&?WM+Y@9L9r2BNFOBFAT6`GYg{Y@DEsst~{P>q3*QkE?hlz+M5Xs8_7j2S1#bjyS& zuj{<4b^-@H)4T!Oz6JfQn=|+@qvLU@39(@HH}lUIk5hn%!v*<DyJzlBOpFKn1A@({ zB!8OINMD@H!o5-g6RafPa?ybl{^1&^q;x}Diw&pVPFJ=slSSqk-rGFB!cEAIePBkn zRNpP^@rZ5Cd9*g<l!SOgaK)CGH?@d3Q@2r=ZbM(Tmvzt4ljTiLV1H>Q@ulbG55HTo zIL)|=#uf13BP-r7Clihye1X-A>c+K)NnUA2!G25Eci<!1%P^IA??+}7ML`Yc%=|Bq z`d`eb7KB+KR^f+lJN@{=5Ur!A%aEW9dW)b(h{v=W73$VzfW47r6Xghob*X$o26P@# z-E{=fXPB`EP1tmNXU9M+34xLM!&3tXv4Gj?eG1Yeb*uNDOG*KA{NwXGmyV)GE!JL_ zMl=3dW#3LbqHX@pj`VtD(=?n}K1iFvd#@U*pfCQ3OpL+p!2ZO}I1s34Wv$oTVg9+T zX??q56ysY6%>4r|ONg`z>-WuZcz2=>G(=jKTB=jvO=iM>q7(3L?%RH))!`WU3rNPc zcZtWbLRzn#&^oPb=?y6em?h-5R%F{GrnekX_RybQ4CRL>qwFRBT`IhYC#M|T#M{r7 z8xD8Q#Xj|1J*<It*I(c$C;7V${A52%)Mx*2DRz2X$+%L4CPy7fH2kvQY8h0KmhaGT zl-On*GGLpt0=)x~9x@aJ86yF1J5y_KtRgP%b^|8-;Hx_9R+oww7!b%0+}5Sawkekf z4^z#7ZD%?J>^FFx4*t1F;pa)ICB2-YG8w6SR(rz$FGO}QXo8X4V{xj*EgC6t>9vp0 zv?R#&vy>4sc$a=$I8SX=65r3cU}->&Qp%cGTU>K{JX+<&gB?1)nsfMST;B4LynX-* zIs=VnlD7X~UlwrTrE?>DXKlzvzG7(6K2{R#gDbNFTeHo8d3+HSnvN!nR1*Hy#%@Bv z9ZCE+qQfo;j@=vC+L8q}=s#_SsXJ!hA8z~^aFuk4p(9<_R+o2fC1`Il02g|h_@K31 zvSyxhn@c((GVn(wR<EwlHoP$B6FHY%ZZz$JG;pVQ%p<3smaFyZ%8#G7rPAmI%$>W= zVcW|X>-KNi&(ZlOjH)^RUrpk2nC%@Ns@&B{KmYOo{ekl)GjJFfuX*)>S=?zO-T%_q zb2hf75cCaNSVtgC<4%MrXQfJGWz-t&J9tXiu64}aZnLSo+f(?Akxi0-L@Jb0?xKF! z&d#YTbS_^AqpRu7kEO<7XOK;B6Z)QCG1Ds<ugEgR4rC|yBQf<dXtfE!qXZx4BI$7_ z_^&)Ef$Xz~NqN<GlI>*J*+iV5{JPd)LuwMek$yvGE39;5=ub_^uHl^^32T7hm1;?Q z1l^F@AYQO)SGgfj)j{O)MOQ#uvWey9riVGj1+1)=_JinUgQI=;pilLDrem*g2i_kl zxV$>a=s<K*)$iGtji@{nUp_f_5y)@=$*$b90}>Q2UWe;6!no?M=0wR3S0*$c%q+5e zdXFbozz_N$*5MmJy}iWR!zJx}0Zdofsq`k}j|d_k-lyJit5KCjCBMLT9O%NaJ=Ei| z9QKNfEmE4x;cG45vVLI^lwra!^G6n9^~bY3KJkxr$<Ejsq1>08W0aMB`C*9lKG!j| z%g{!<yK>~_yfxc66x)54XIbj$yO%!Kjppl)hd%hx0P((KyjWC&Uhe-2M!lWuqHt*y ziqI_B$B<yoEy(dWMP=jZZ{xsfc_0Dl-frhq>$>MyFJSp!Mk*V}7WAxdust-IOq9$a zL$42t4zr<X8@$Zv-=FgV?e>pHH)!vO?6%63AJ}c$R`foG_?R@ciR5L~q<gerFz@C; z6=lv~-wMWyhR1`@^n5>=`6#9teJBcb%nWbaD9a+*%ouYdH9J~-LD;wz=T5ts&pK_| zY%E%n=KWp_XqD-vJ*{RI?*_2AGZi4<h%8+6{Pke5(v586hPgY%Q$lC!Z~OQDB{Vz7 zbbVZ1khMw?hOy#(UIqqmJr(>>Z2!T5fJL+|EK<Y*dS{TI=gl<R*&u&a_kEQV%g?k1 z3Z84DL}vF!oyte2FC?#D2ePaQ3;guvOrS{_!7SoNw5X~*pR_FojQa$8k@<JmOA}v~ zT)l#lCjCs@_^1W>DkVWHJp|1paKd<L5b=sv#1X5McbK0035%MAbAu7oC`R5P1S1Sc zRsiNeK~<ZJ9HNX~rj%m(C*|a3+;%~2K)t`=9y8aiZdmQhw?$qMlSeV2vy@}TV8zY= zN%=l@?b~?~&-UKS3GcB#ly;tPi)%ryNR=+zX9`VYg&jcscY8GsxE|g+;Of?^=pAo6 zncdOMcqoQvch~7WcM4e3n1b{Pck0h%Gy7gYpoqXp=>2=F%d+pp9Zs%+gyhoZ^9x1L zmSvuj8}v^nXoxD}YdjB0*Xgf3PPM=9KkTFe3hxYuPdDWi#Qhy`%HLW?Q0F(?)plu$ z@d{lhO~);kVkEoPuN^(-0!O!evSu6;DN)p}2Y<tMav5DEKjy+1JsNvrtod&I)s5Z# zoBakbiE0cjU9}zZTQ|&Y-sCON)q8GzHSQ>r7|}KKG!B)n1i6&{%Cz#5cqzz{X?Cl2 z$6NgqymIV7DCX1t=-NjkI%T?4Sn{Iga^<>Bu&#9cXaDfqqQTkjQJxl1poNx1^V}tg z#UbP@b=M8FM=V%FWU{F7UQ13}v-tc`*aBb9;c8^i9U-B;8|esQ$LDNRi(YDrN9;=N zuT#{ucmeul`|rvFmX4$gQk-EQe3;IV*fT17pQJe36)F`xJ7FgaK(-Z<gJvauX>0LH zbUt(W{@@ND>5k!oPZojc=7Q6!bwbmdo<wd2aYIhKi`^qX9kX|SySzUUZe}c0;*%E> zAq4Z;R!X+m1auv);3Vls4A?N68rwbbj|{PX-`+mt_#U_O@l5OXl0mNsGD~fE9UPQ+ z9{Gpc@>%bmE9rQD&>zslS#91EzswEHxf%TA%_l3gf{Tk>-^r+PdA8niRm3-+_!Bbj zd9DAIl!b0^xaqR5g7^)@c!<mBbpKT;U6hH@LtBavm%fCQ+O7{D>Rw3x=fy^zxlN@R z-fz1*y2;8oSHJ$GA++u2h0wOwG*xCtFT-et>45hf{hzKh@P*Xz!-yl-*$hh7UX<G_ zo5=1q`la5ayA1(>9#2x<M&RNQ2Fshu<SI$4Pp&dVSvj1L^@sJBFM>b8U9OFeTXAP! zK8@h8cn_?a>p~g3WJP1h;Ra`3Pd4H*yJDH|U|l(Yc5mu<ArlQ{1TS{%%)Bv~b_zLC z<n>xzMpI?Zhya`B*2c?fju6w?dGX+e$0y^RH6zqTuCaw55y%=>yXi~J?ZETld3e4? z#nW?@i{}t$X4yd+4Pu7UGUSX6F69o;hlB--EU1sT)ATh(V3fdvA7qTdygse+vjp=i zG)_TRNr7(y2+mSvi?Tka!EYh1u4W;rrM;;Jbh%B@4|Yh}`?TB11%BqU7I=(m2Eh5l z*4w1_6;Bi$px+40_lQn5=Er~r;-oJ8LSUh=;iyBZ9Z9;Ao7nP`5<S?@H%xRq_7nOg z6n1Vf56|4wQLki$sQm`Zl}{QhLpOd-MAK$Ym*TL;gO4}KDM#{!j9;Awqi(#iVL>iP zr&R@LWOyw5?mw{wX;tnz40_W|x3_To<&0DL-~9``lHaZ7^5}E^K%?}KfTC-0ZFQQx zNw5!;PBDuOqzrz_4pbWdJ0E8pF-7~Y9xLMa*J2~b^hx(5ed@Ju-*D1AZ8w;~dd(W} z**@0?K64>p%s)P3eqvx;F&8%dQZ_Txo6iGDQ+|JLo>JWtga4e=OHiHUS2&w_hXri2 z)+e>j@;dkIxsYzL4Km(T>M>+p-r#+K{dOa}rfGEfamZ=E8xq>FKYznfZgR~5cQ$%} zzvtHWZiQ~e*_ThQ;l_zuh9v1+^ojt1^D{aVi#Xb<4(Y)TR}El6u2iFjsI~LsOh<&t zdq$rq?`E>2zSMB(YMCv;5x|bF_HJa;67S<%Sf}ZJq9@it_9m;6%ShYt;MU)gy$Uj& zWTu>anJ76tnisJO3dVb0-QDe2fv1e14+`Y;TWO`KH_Yl<sNX#RTpiWwTRUWEmolaq z{1Y{}Ob}p?;4DuEZ%`%d1&{pu2NN@tn9es%&>)#m>FU8;cbJs<+K`ij-%k#@f#Y`$ zh^^y3%8A2=tDeY^I;K1o5e3*!iZRAn_dIz)=%4GnR*x8DQeg7mo@%#N?~y~y<(T3+ zNoDT_Z~oca72c~4#*$aiC*}~f2WC>iKV#>99VW&$U9CH2L1wn%+LZJ%TwH5+r2xHs zSg5LT7<ow5W?ulnsOTEGpTA{U?wy8)XTNI1oBsR#AY71(zDI>*r|ZQs;8LakfEG9+ zU4*%{DhFJOd*xsI+sals>$8(jl-Vbp^8)_R8Ed(2p?~_Rw{`e|u^zP3<wA!^lbMKF z?vd3Cms#R5noGA|{;5W+o2!FonX5m$xl3QY9X!H(#&}?x`~vfg0!!jHv55^8(w;@f zO<r0fd(uBmoo3-qU_JNG-Xm)jrUhsP*^;f@%-L<f+s0A;4oDc^t&x6|L=D2n<~Vtt zU9v@r(x+F@9*mwUNQ66%yVD*hs~`D9+<G<rfw-yXacKgi!x!*gSTWT%I7Pv-FW^V# z{Cmg=njO=ZPY&H@au&qjbkLolZEs;)(&srz-JiibychczrMn~+dOIfB*p#6QuwT-w z%@wN?&(?HHdflHMB9~a;@KrkZJMXmP^Cs@|o<6P`x^EMdSXO(Z?rrH9uV^_Yz#2NM z%l~7(is(4(J9~nbc&iPMep8lT(cx0l(3gy894|n$e8K`Z@pPjjU1J^&IVy37t=NC> z@`6E}KJE-i=B|1ww7oGur+isJFXQ3h9gx#*!h}x2<o+~KJ!5NAH{Z_4Jz=pnhA(Mn z^-2tCqL&&D)-{lYJs)P(oX6Z$xbqrj<qD)O?JsuxwNR8CzW5wKImp=uzG+#>dGg@j zV@1P@=oRW=jWY<OBc2pk2f033U%Cs~JB<b0`REu(|Jx{V@mb%gCI3A_n+28&JdJL^ zzu)JiTvn;izSM*F2hH^agmjnP3EiGttz%mnJh)|7U-rWBo4>{q&+bxU41EhwGdMf6 zlT)IUG<V1BBtCg4a(J|7UCve%Y?2Hb?v;E>9rtZU^&8^CFnun)erE?MzJ&OyCdox> z`;6@(GeOf*4w(=B&vWj>vnw1m18CI?%<ACi8^E-pHUH|v<p(X;;AquQ(ck#Fr>iN8 zNf&P~MVEK?9~N<%zfTg}3$Rvo0BZ)_{#%wHRZVnpgJy$#L)D2m+%FQaVqDf_2=<GM zAvs9#i83erdi(4;%xZ{`4{%?;LFqjOR|dyK@dc)F5}7TDSaV)W)B<X8DUN5<WhLk0 z)Y6@rfH4PTSgeVPiR0aMEo6zm<MM*plfxxWZn(Uo>?~1$!13xufim+I582w+nJ7X# zq2%Ro;((BSMQ>gU#N$EiahIJ;t>S@zhsO!gVco-b@tmOUl{7i?DRZ59+S)IN;B`Us zvg;UANH*%43zi9#3GaEl;Xb4Jk6l3FTZN)Oc@8g!p2wtUC$uwTWb?#&N?pgrcM6p% zxf8`j<J>v!#=Fi73qV!bcvJ$K=5_+6>UPu%edXX#O`bop*9%WHjDRx`fsy$FWczbW z0Hes@t9g6EegOXqsrNL1X#kvuLTXs<8$Cs$$quRIO^w<i)qg6o5G^J4B@#<X8M}Ml ztL1DXA4SI!JrDM+K(a|5WXX^VWPu+54vddi`5_wB(IpX(@nl)5J`M#HLhK$pBS-Y- z=P7%nh!4L0Wu1a@H&f17z2Hj)DOa|*wF5jr-Ar7NkI1t5@6P0hyeF0;+mjyw<;G&9 znG;>+RC%P-9O%>ByhK}e8C#`&+}2lTLu}wkzYJLnirshhq_2oWTf8|!WAC9$U_1p| z3$^OuJyX#jS|P^;9+smZUDmfn`ls8CHS?vhx2>;<kf)u`%G_dE2<8^ZawJSM<h3V` z9@`&rUR$?+g)kq$4&41w$%p*0+r|cQ+5W6$2PRjdNKQX|U;YMf&io(EpC6mB*Cp`I z+S;c818v7J)iSx6#<rAJxa0oe5K($u<?Q`S#RWEFOYrMT`m$1Ho!RW0M1(Nh>+I@~ zqtUN2CK|*MxbKSc=9#^e)2?0K^{@D1vJW+IJyg3tSyM#HDkWQOnprj@C|96WZJXyF zo?!gL(p%j&^{!lVAiHAlxYjO??k1{T%qEdCrG6M`;&@q1SHJ(AWGpezf>|F8ZSBqe z8<8_DbmGp~@p%%cg8RrNfg1b-{Dh(BUnIE91D+<@Dr7w?W;O(v^0588AxxD?c7SsM zY^rnMDIU=^cX{~fH2hA!gP!EIVy}P8b<q@e7eloOrLX#VJvUU8)Ur^C8Fc=Ho#5^z zXe;=u<w>IH_$f4O2P0k^fgdP4f~l^_3d~nC<>-g+gpTYU@6yn>AS=01oM?<hljcs0 zoPd+|gGs=mim~pK=GFtb*7m%PTyydOCFEJa^SsQKJ92D3zmTNu#;&&Uj&DR5<DM3} zxLk*FyzpM(5d5X8QAHx)5-efynU>AsE9pv57_+2&grOv0fA_aE`iuc5xp!N3kjUjb zCX-~RVZ09d%ePxOj(A40h6DRulDf{${m$C{*V|T1v&KV0<Q`k|@uvy57l<{giSVQ= zO+?dp&7ENgjdY4!`t`ko>u(%;_gzBdmIy5pY27;>G6;9j%na$M2}Fjv`U>AAX0)Jj zR7L}J3GC9>^sUc<jW6E|5Xp9n>vSwEEostuW_$5e>nL<csw~4|nzA0{I?^v)iyyc+ zU1OV_RK&LSI3oZO-Pw}@t*izAkFt9qXD%ihp;ubByEEpVACaq6iV7-=<oZkI$W1bP zUb1<<9V+zDoMx%=ZZipe#mg#Jq<-B^B0RYoi#k>P<V$upkV9hlyf$Nh4whkd3HH3d zroX<G=x=>642b!G2|}|uoNsI5^2%wx7gzxCPS{0;n8cqL#G?kllP}U^I9V?&wdo%& za{CSa$NCLZQdCi_%8xv?*?kt95;%VIbDfvOJf_arlyB7sWRlK`$al<ye9w_$hh-g& zHr11LPxf1qQ*IasxPG}ux>pb+iNo8KAV&9F?~xmzi-qLMjqn?@P)v(mpR))Ad)6g{ z%HfjZ*dlkSpOTYvKCw4MER6QIKT?_Vxtc<j?rW_5{^st0JoZV6@0O}$5^^6|*Z!?- z#uT?%^09HVgAmPTC|=W>^f9)2XK!Z3d=@)Z#4_t2zTN`aQ7&`8w`;V%Euv!`G|1x- z#Q$TcBEh78<!GG0st>5{a~+|>#vcALo8`ZJ=UMtzhokYK9o#BrOYbo(^cYNYk`Q<4 zWxeBTnLbLt4k^4{;EfGJPbE`w9Dn;@D8Yrn5TUzAD!I|nQ#y}SOTx9$lJB4fnIXyp zrm{rv%Pk-ept5XcY_*Xuw01=6fOr6p_=oSji1r?VlBGliWlA(QG;(&9mPyvOE#U71 zgcJtZQclI0;j$(Tj0zWFk#5uVOaL=VaA=Wa?``mL48p)Oz|;qt@Uwsrd4ur>BdM$H zYnxlb0hm3PqP^{_qvM>5;dngZhwtu}8p7LjA{eSW-()WA#<xPn=N+uEqW{~12LgeB z8yw<JPq>FJ<mVFKyL6U=@W(E{spQ;xMBWxrp!2({DTPHLf#si*mt|$bcC~@sIqvtL zK!%lF563~%!I54Kx;E#bmq#c2S;}O?t<LHR&N5gpV|Oz4H+$%13UkK(xZ7WKZb0$k z8(bjLmjJ&mf0q*|^Sl0%Zc6SMINz*5#=DPP+m(OU(3-X0)HqS!cg3qZ$QpC&a4gHq zeQJZbO|osDZ<flz1qC0j(Fy&G)#Zzg{S0scU0XCm8h$j=tME3_upMP&9%Ur=vKW6} z{*<OE<G;-A?!kPeBs<DMuzSExCO-JszT@rRb)rL$RLU6*IwkVcdxs{(6+&-VCdxO` z&+a@b|I%PfrQj1Nq<H`f1|V^oHQk<6xxP0pLQ2bsqmLqkr0_RX6oza2Zn~uFp~y0M z7KQqDu_<*5ruyFdti|4w(X8QXm1{+Zm|E6mbGfhP8R0PB)JdAABwj-T&rGW!9g2Cb z%%(-w89;;=FDTO|*0+^9b*OkkvSw)Gxms00ya;oDiQqi7nT4L^d3qsQ$HDIasPj(P z+6bX+3FRM8P7gZLgIw<Os_hE4j{*OzKfHArMv=YMW(!A-_ZpDBMdj@$Yq8TirkM@r zxsQYWzhNS<ko1$6>vzV-jfZ}lT`!>JEG=wyUtljYrHNUSZGfBLzp`#;6Nvg<HlucN zbp2VN%9zhxi<>E3mWv$!1Z@le?VEW}pz41-;V{z&QWiDAe`yP!5JjVYZMn48K6%|J z37Zpq`P*{tYIf$mEDEmzwJ{;Y=R}e3NN*GN77&vh;11I}?Am^287a&iB^=Vtu#5dL z|53`a$zQKaV5C6uYunT2bV#Z;qX)Nb(JYP*i#sndos~O|+tD_c$Rq~e`d;+b-M?{U zE4UWcpm_#-=TQaj4jq1tklEyS#zkHsA8Ces$WM}GAk|xOVqVwG<|Fr4P5GyGYV54^ zDB|L)J081yC%t2Ex*afm_{lnaT2506;>v8cNJd9ki+^k?e>hEeS@i4Xa<9*qM$T*P zt5;V7dv`OWKORbKwOD?Rxi=a0sBqVr>jt7v9-@D3VoG+I=cfQAnA8US<e0h$pj{iy zC9X@gB1^T(Vz&6)aC^&Msx#L`GG6snaHQxHty-QVPR+Fh0tOi!7Q|Ae`+%6ff95;F zmTE;W4CxAU!6EEi>*g#@qe&V=iY**Nz6brNq*~exabgqiV4*7Vv9dA}unBzsQr}ni z?d_TrqT`S>&iVAQW+~cZ=X<~AUgS@w?*&eX<Qu$c99{-(MQodA6THpl)StLK-idwK z?=1P=ImHZ|vLn(kP#ono3+<EKNSBO$`pE5|^Nl!#rsBaIA8^|PDWEeoIO)}e*2#nZ z;DCXtS&WW=y5>|$+lC9}0Jr^(2dvV|amshWcmH>6=#S6XX3_p?sFJ-vUN(lVSL(X2 zKy)L+LPFddiq54d8}2a7pLZJTf*>ec3Br$c16#4`ru8#3-v!)t+I*;D_6X%a(WJ4i zy>MgRBa3|)(9laM8x(Zo4ke3h#`gs7Nrob!*v(aEZBPA5sc7W*_Kb(5S;AJ>^3Lz6 zg{E*!lzWy2QLvwGro*R!t6^#(!Dh$o66~faUBEL$E2p7x(P_wWkYCiLAMbN7Mf?~Z ze##;yImUb3)Zm#A?-)Js>733<?q|yD&CgyUk)mX6YUc&U8dyzG{uN>T&)(qdJ$5>R z;@Rfgk*7okL88K}q)t^`LJMV*zaAEU#D)2h`y>fxhF!QzC!3Q5j>!1Nc)u`+YOxN- zFfc5itkSu$jMUF5qp6Y2o%bl0k!c0wb4e#uT+Mz%g;r~Xazl{La|^RR^FcTP9MXLe z1ajKzw;6Wdm?As!c?TsJDH#_amirK8CEtBR_&Xy@CL?$WIz`=ktbX(6La$fA>rb1q zo9^#Hne)2mZ>WABvyXJ5^jIgLqcQ`+^YOoq(bPT6j4=i~-eeoIZ&Z#;h`~CWAcnU^ zr;?uJKB$EFPw>)}BH5KqLfYN_pz}zDZLd*WrPNB>ucmBVrVFI>#31xQV%_Gq-8?Z) zDr1u&?u;4MZ+R|Xr^_+w4MUSGawhaQ-czt`<z=MpIS2fsmfH>K!#a_w%_j_DZTm4= zft3u?<(ym3uN%VTQ<tk%fiyxHZKK@vFR!HNVz)MmJK6cDYOL6@Esl;UimTJ~o4a^E zF`bKiZ@qPS)PYe_IdmOmJc>Au4Al9e$BQse9BucoKnCFLC6%NtU~h`7khB0K?=~0A zKBAm~7WXIU$f#3~)Kp5d$$Wj!jAACcaTdbRt*mrKJ+G1fIxcTvOF3|0+wv-J#@7m# zZJbRuvN2*O<MA0Ovih%4xIfFiIZ;s_3LccKWg1NL{1hJ`=>#uf^j{(!2oLg0QWp(Y zuW)Dc`AS_z0NN+y=jYJ`R{J0jQrV*RKFnb8tZ$sU7PHO7vpwm(&>YhlN&QB*xY`5= zKjL6Fq@^sdkb~Gm<I1VP@tC@-_xxk%#{7h4hYQjE_ZtVy><9?qM(u{Dr&#f|6ry-D z!TiA@RWYw4Vyf=uK^AmF=*{a7DfO|*v?EisM7W{V<{0}M4nDl@R^hv8yGndjmhpoZ zFH+0yd&D0Mt*97V2I!}WC+bMnMQE(Ks_(JmF|UDUQum+dF+!J$UX3!PvGSK)N1a4I zA^v}m-nH!>(c<x9g>)G{w)d{&n60)%iD&Fue^<*%L!3i4GcC^;`9+3-r`+~Fj-?m% z7~wRpw2iFY@=nvJ(L6*cPVH*egmB(~!vRZ*gwpH9hhOQpM%`QLUH~WIhZAYD?5<3U z?vBDN^xY%IZzPL_T>obtMY5QKTGTk%f5rkRSm>t6O<&1X5O3Fo@9hU=mr;lBG7p1Z z6>|9_i8q=da=NpXM~ooUk6y;sjL*_dS6a?Ro}E^vK4$I3LL!~sA`n%j_H<V4n<7_T zh884rX3)<KH?_5lu3z`aafKZ#TAJELMB#c^c|5#(k<dk8Ny7*Pk>+G$is=69G5E6H z=5V%0!dgn@bSPPFV^Gs`PROj7y{By`em?|re`H3g8HO$NCK`dXiR7?3&%kTj4a5eW zVf7QbyN~AQn4aB#x1wtkC%~M%C^rBppAWlm4D1(hiD7XdvUm8VEm>;*5%pKDP9Y#d zm?r`Lt8$tkAbE2mBjH*v;4^8CiXzpDjQev)l1>7ovL!-UOW4Df@I<Irs^jq?Fq)uU zO(l*i{kXyjN!?xDC8ooIiV^aGG5K{0ZMho7C&6NP=Iqcl=Z$PEJoAB{-X+H&f9;+G zPTW9j!7Iy>LA*zGMgGY%D@=a5_#9=g?#(_i)wSshCc!P$-<@qX+-2Km>QcG#v$&t8 zq9T^C(tWjnwC`h<G7aZ8G_*Sv5J__Hl)$x#tjWx=@$^J+lMMBl{aAuVtvrfyN_`#& z-x+dxj3gCy5fG)pynp`T+7c7sJanFD*Glg!*^cyP7xrj{8U6@BLLCN?#`v{~3G`=` z0$#5F(**(u`}1a962}nEOCM)fag_)AZ&Ussp1v}y$;N$Ky32u6I#g5;6qFvRqDYFA zzyJ|Yx@)6BQ2Id$X%Xq}7^AzSMvrbb7z`Ns-agOo{~iY(2Os>#eP8!^o!1$@_t|e> z0-;c5Mu6f`wexYj<o&<b#YCxxbv|IyMSszk&1sR6cQPx2yk=g3BY!RR7>}fx&Zgh? z+w?zhW8E^>ub=X_>iE6=-Cm~nL4*T}y-RJOlv8IU$3d<}^&#T)Nb@5X^{J8-5C$J@ z1EY0z^;mV=tg%+dImOu5n!uWUlfd<Q91Gj@M`gke<5LjV7>2%EQuQ_}IiBkqP^oGg zwyStI@)C*if_S(0(S>}CWmc|zgL!jQ9fq>d>4Y*yda&XKUA?VhlS)5rX)iehpchl# z@ep(@$Fv0;188K*Xi@qWw{Y9D-KYR@dBig}98ohZ5CVQY=0RXz(Zfj}RJhL+L^>#b zK1LRn460>w#M5u6FQmo<`WiuU=0o_7H$29bGA_T?cZ&x+W&0i#iMC~OsCpKDGcn7K z<2bxF8*0i)luO{H@IoE4?RJ4}A-AhPJcp?iWk3K>r7mGos9`77@$D<;2^IMH*<;`W zJ>|Pfx~oY&lv*lLMAZ`M;XG8RiL^-2ZYcEee%$elPf0SMovKfJYj87rVP4I#hjnX| zYR1YYYCj69=8xT~5q;mUW^LY{ar8uVfmMQlZ=-c}=UVrcEMg#iRRlfa-De&Nvj#cU zQ=B&yM#AO)|DPW);huGv`PKyg_~IEzbH?t)b%))Rx6GU=c+*2bAtpfIz8`o-2JIUk z#Qf1oEJUcfGw_4%1tUb_#UkDI!<dGtJmNn4J}R`(;0+TuU-2oZBwk;NnI~=a5LIYe znkJ+yAZ8f3w53DsYq2HK;$Oh-$27`ryS2ka^HeG`0dFU%GAmS0^)sLNoQ14!8Dv@% ztj$8DdK2hzgJn|8{=g_nRdP$NH$_WkCMX^cCvjYvtlRDeH^fz?7dr@Bu($FbjY->V ze=U_LTeT+JZo{=Jz<)R@n)9<q1(`@(a~5FM<xmNzh#O{8F*}HG@Nil+QsZ*Z-xXpM z6F#6o)~%MEZ;7O=+=(I%7ktFf|3{0X;r#lrB>*m?DpIakYr}ZR*OK&Hny-h$Y5NPz z*(svdjzL;d>3+`?!{2nv^~pR`$%KcBi5@vn=)dU#Qb^1DdG~}+b@YOcsk9Pt=xYl^ z3-?xR2&w0!xT{yb;GBTaZckGEs=)oKj5K2(ma?z5bM;4Cq?^wT9YHJ+sbRzTeZhEG zb;k!;pY37$GxN<~Tn1*|mi+hLc8#ZDeHOocSJdR9o-_7~47}7^d5YVuKYdN<)RBoW zWP^D(xmkR_j6Z>Io8n&I;<rYQEwC?&pPptGOZ;i5{D%k?=Y2+p4h`Og`$RyCLx0Kb zK*Bl8zeVtPam817Hse1rergL&H{1VFEiV%>IygJEm1lHZ<86z*3(uG^jJSd#hQ9Hq zA)*z0(~N5gSY=>)3BK?_^LJm=I!Y-2z8C`sw>^a({+du8^LTLap_l3Vc9BsHse;sZ z?udo!HaOAFzt|&9K{kfwEUEq)>>bw{!+YdQkFu2C@zyq7LpGf%CG)aU+SXvatD*Ud zvfkEjIg|P_`YfVA_~`mI^x^%gIY+2*pNCT;#wALay}v;5^o9-v{*ijeQLeE4V4X}v zkbqy#jr4XE_zd)fa~v=j4=I00P*ZApr*P?Jcg5=)3ziR!Iv9*?a{W*ul+b$IEmhPd zMrX%S#wQ>X{e}B#k|uol>*!g;g-s#IYh}4mKyfYX8}np_GPThPd7e+xp`YGM-Ez4x zv_XL1bB^VHk^VgzsSL}FM<nN;x0GYLyBfo~t{=Gids!mbYSU_SXx~wD%tnGEz@U3y zaRbA=WNt|4TWmAe`PrY<^HhtabPlh9!+0%|w<QNl)W1G#$u5W=)=~?KbP+R7Nw8uU zpp-cA%|B%GyqQ)BG>^T?QYH^_jvN$UsO%E~#q44bey1V$X_B#taP+oDlAD%zlkS|; z-J8kgs+hso!)aA>!Ux-_*Esx|N>e{P4c+TruXlYXE*5#$>e#+$&}|?OLgoD_t`t5@ zQ4K{WSMG-_wjHsp)Us&2>W1X*GF(q%xL&@q6591@q^Qg0M{9E1p4rD~eC_zqr!Vl& zAbOsMUN(<gwEs$`fxZppRas3;D4ChuYz5Hm+v9egA-9_S1|L{zey#>wF=c@(=3TqT zA}%Jt$7IrQClsu{bnotyKQ<rli)Weah%3PPH}otidbRzu5+ZM*Uk%w<U+<p?bKS~T z`}|Ad<N4!5n&oZ!)6e-8gbddd#wK65%J?4ybF<auxmqADU&9r-hd_Y?mKyE2qH~u{ zc1W>^1=SE!Lqnqa;=*X+oC98T(tz^HvR3@heuqAlf!CQ1ABId`dc&X_X$BNF{9(cz zXwki<iC5Xo7La85d)TAsdt|LnyHd+IE<&vZbeMBOW7E?ZV?w#GPmeDCz?xVld7q<> zPndb|9;p%F^e(2%Hm)-|yLT}!YNBBYupquG_M%8ypgBs%hvg(DAt~UTSAgKQ@Kkpk zxQ$wd`K!&ePHe;~_=;VrT;APdm(#S#xN#!y!|_&Q?m5Fo?ArYmbg%G=2Ft1rQ*O;T zUrL6n?T{^<)yMY>Oc<?oe{(?>T3l$|k1O^uB_jnA@S_ycxlx7#h^EH@r=0(a+~vyp zRuapIv>YLQOF&@nj$48^b8UjO=S_*WTZ8`ZOh0>NSlE<D7+RahPoDE1a%0K1K`KNI zhS=ckY3ea!>BmpaU~6Q{<Ez~?lab)^(Ct*0+Oj^@w&fPzG6(GH2@Cb)>lQEFTQ*xW z+r%gLx-}%A3A<%NG2&Gwl^;2=6c?>8g>Q!T$LxEKY&(eTeHER8CG1ki19zxpyV>ZS zP9HA=v^2kG`islpWVWtd>RfM%${RBct|%lbxL@Qk^xrMFE_y!iK+U~6P39q0Yk;D6 zrQ>ke@3H*jEosWf6)Z=r;5($PwQUuE3hHsZ{(tI4Kqn&=M=dHP{Vf{t$V>^n;!WwK zXkF1!Ypds|{Z%3S?F*`ePDztFGx$H=-PSh7zWp&5c>jY9p3U)^hC{<D*IT9YV<QDv zF0!)_NyovB?2QS@JiyPBHBB0@<%@x5XTd)3)4uIny-ONQkFj5pFY|kv9>hLt7+~HY zEyU~Uhzj6`-*b%)Q|Rb$PGbTE{U|$AKJr|*<MLAQi&bAD%Lys<j#GOVW70vjfzrRG zUf#Y$jl6&#RZAgScl^37FH<c}$WXOx8;(JADq6nG?e8ec(wDV-sR$JWhA#@AvIX!@ zyx|2$PGH03v$}l{xnh8abq?`t3-4q0I%N~Bnij4`@4n~*yoKzzG%jHvxvw;D!pkMw z(b13c?aXiF%YNRBPX-CT%lx#=PJJ8Gr&|h8&jzrhD)3#;<A{EfVMVqbJ6B>gDmwof zf=}D}thr!ps{!{imdY-bp;^*Y|Mf`Ly>m^R`4>M)@NTDcpSF`X>Mh5du@qZXS&pEF z&(1v@(x70d_O2&Z!Txj8V^NYBs&8Ct6jUqQgj>g~V)u$%yQ@A<67C{y&`SA@Xwp}7 z95~>o9X_`^HCU<L9gMEqJidKK#dL|KTTxnT@ty}7u7IZjV?(BJZxiE)ji6V+ChV&L z!YKLLTf5c{)%nlzUrb5^=^}})rfMB+|I(|$J}tg3gXu@h+iOv)hie!2OnCO5iX(i2 zTjMZd%S*w6sdg(Bj3>GrNad;uPg+6*=ReT<_oA)45_^xJCSIpxyK3t_)`1t^-a#Xq z^o;Gtjf}HzqqZl4cgu#NK__}-dsLsYuFa3JV?Z;UKi{3+b<7tgZI#*saK&;kHW?aY zzf&HUX~h!ju|~Fga`+^>&1sEnqf<H#9JuoSEW$@R!%kMjB<_~Hy<yFRq0QifVu;T3 zCd50F$Ma5&Tg>*vR#@AlBfgr(gmnEE7i4ML3_xd<9fsJlHkUdS542Ei(H=WetO&<B zQtXL2>~rqX$qpGTh|a1r;Jkd}O|C%)(0x|^!NE^8HAdGSWPCY@_7_V!O&Ks@ljvm! zn6fBI)5roN(rMcfk~Q0&^`c|n)~ACc#@>YiUNTp&IF)e2Sik(C!aeDWSIWpT;@Gd_ zsbV4w{wh5ZN{jtXrd>6YM-=N*CX|B}t*e|$#C2tgN9~s`NM1&%bE|Ji#^L;jY}m&1 z6Zgb;yjmaiuxK)LX?yCe@2c5v-SpLG|BT#fI$0&<clEG(#1eWWG07>_k$}8wwnOOs zGeLzexF~)QgME7nU3|$E#mKQx%wujUvaqWRxp3-yBibTiEN5Tfu(w5jwCdJpyLrBA zXVMnQl~wI>N2A(lm(zWIH{L<oY3d7Z$D<xsr#Y!0#mo1fga#8ww%82OtIk$AzWs-X zz2?KO8(U$T`o*xb*a@K&B_N-n%z>ZO?E3tYi1>dFeeNA|a_Lunh<%I<V>0Ca{hmO* zB5&}t39J=$4}T<?*Jcjucb6+}gZ1^LpP6WF^K?~RcpY{hNCHhvPOgJ1z@6cjd!8|9 zR(ky)iJK!3U+hy~JH|0)-1MGHj{hZ!#p)<mw@Jd$)njl=Cjh>4rd)MC?rPW~BF3c^ z<GYqRT@Zx@itiHIsK#ahf#q)M+;XpTf&L)6P_hXX9SyeyBwE=fp5%q2Su~AZbQAv3 zwf(Gn^a%zgJfAH5)R3jb47o5uzsQz^T)V$@S-Z@hWfAA>KNkhQt)sIv);d04gd9It zm?J8m_+0!na-ifmE4WG^kJ`AOdnPf!o||5vdO`e-VGdVIFikqq;2;>T@%QCgjdh(n zlSNe&%90pWDxP`W&?l9eXo0v&36riFd&?&TlL8G#9Sc+lQ#rdkQ^vF3zO+*>iV90; z<VlrEw|LzUw5m>VDxD|Y20Wt7lvCjsDmiBnZx%3j<vu)JKfW0!O@zqHRxXt-e%55t z%}G6ZOJV{~Gka@TtpA#s=cM>R7*nze#2)+OaoES;3;FVaf~j2Rt%uWGw_(k3zoneG zErdn$Ir&!FBL1bj{-Vy74}O#MUrjY9HC&H3f~_`{TP2>oSB7yj&H!0Bt$X~GaWT^j zn}7f3qN48uLkU3-sn*+nrl%{~D=~K{sM>2}p=u?Ud~945krJ+_y^rU^3*M-*M(WhZ zyPa~jb1(Y6>qBLHq4~tUL*HlYQS3o@O1H{+JC`99o$8Nd9?Y5egAn>AjB8LZ<~FI^ zple7E@B19B{no2zwt#90wd<TbLL|#vFTH*|$)(3KC>?tAE#FbPiqQYypHrY1gt}Di zIpC1noJ1zEuq(SyQK_cxNt9nd>sHaNGREkC@wQBebQ2T~+0!9%wjPb#oI0pCV%vU{ z_O8VZFZ|&{AAD<6S)C0*3ntVx(G!#lO}QPMV*8pKjB;oQI>i;_js0#D0b(4MJjihD z9_Jp7><6YX2A!WxBwP7EIy5D+`D3mEM`g@lHl$k?m=y`2PX6F^V_%7#kyXH1-FNe5 zttcmE&k&Q5pmUa}KV(s(W~qv^>4B$W>Fe}B{f8v}<{s+LEYabk!+R+w+Iv?KChnk{ zDp&9t*;(|s;pQO}h`DK6iYj~tA4MhX5AHs{a=eb~E-sO(koNLGm7sL}({xAr;Ifr0 zzis?{cL;^0GQcsWOm0xJoo&WGr4&*uQRi^#zWOHYLEw?|&afEzWJIS6Af0mR?>=KV zE)c$zJY@E5Gs45ib#>QnSxTlSw4}D$BYM|YBK$>r0Mq_-y}a)~2N6HnO>+8l5A>q@ zeEnQzW|X{Q89Ew*8pVNcOHlS-l$*HmigHEvRG#-8r<rig;GY*SUU+|hbca6wh26+; z==(9i7&OaF(|Xfri5m4^c^WrmvnwfkQnx(o;{fdg-H#ds{3qjFgy<dn2VJ>YDrP6{ z({?s5VPi@|CUf)oR6+y(IfElpM$!F#_a;lE|AYqmD)C4}v!3cTtmWD_mZo&#Gqt_% z<wjo+PE%(xUEg~2X$|B7j}{8*4`u0YSRR=^73}uFH(t>14^GXkW?{xKOI$+A6Pa^k zDO1u-zbic)OQaFt!IO@o+BF376B!1w{j8~%wV?TVaVfRYfS$hbVvWWJKVwK`Yx=1N zPTUiA3$se6evPAe&8EX^?D=WRj9pUC`hl_+5suK<p{4o4XXiNa11=oooj~kUGynGP z4NbQfL+EuSp+M;HP~H$p^j_Qfr<1X(^X_!<gT7pY34P+VF)L59#H<_)an-ZvI~i)a zgem3i{xtqyt^viVj%fx~M?$aWvl1mVRaLtShY?}N5$W<V(=t{QK68^7y?FHvPN_0! zqJ|kxGIdPx>|KfC^|SDOg462~CaGF!1(<cn@^rdfA;~(s9M=lJtFs44ASDA*Of?<X zByKt|xI^WpjJ1{}Hvw;%r%ttYGq~^_y|Qhv!9mc2-|g+&_ossM(6l*u)(D-DMVP{Z zb4&;~jKJUd+@EhquXXW7S_zqggy1u06d!xW*@wp{5UJO1P%l5L88!y<Cj174-(sor z3!q`=>_mVvZn%moAGq%U2<C_ewwo<)2-QCE{!*>!F$I)Sisd8@jl6D1A7mb6qW*q{ zMJlffvjHxus1fc=-)S)ZjibW`c$(q*#4+pATgoBhi%pffIHG-bMK6?krCJT<8rRvO z2ol1_9Fg4X^#(hfX25@7-2}W4R6jF(IH`#o?)hUUNcWP!TW_3fJystD1XZ~>dbFPJ zHD))@owxwmWlr<CysjQ4?_MjP<SwbAD+tbk3vcwXOW+yj8-(Pt*5!Vb4gTD2o6OD@ z(e8fnJ5_}7nCeU1SO4jg-OtRpZ?qNtTr!-geJ0S)S?sI2rm<d@{?!-KZ6Yoi>OeC< zNKm~LJ^P(yk<xy4(Plxr<Tyo~R3EKfhO+Hk8x23cyVIkE6ZKn-MnAJH#W<~kptj@m zoZZrZl(s_fn(>4|4r3ZHdv41ONosoJMV;Q=qsOi%_=`&xHC^l9r%(8LhzpNFw(!1| ze-;`)P*uII79bw(x;auoxEG8`{$*5#PhTS2caL_g3-dz(Wyn%3IRLRdp>f|-`0DdE zpI>}`j+O1z15#Y}9>f)@;d5a%&jd;FG{tS5ktf)%9HUx3Fc%i4n_hoaHD}>tUX-_k zwz(Ou*4C|i)f__)Z;Q9vp64?g`;fjksQ;r!HsB6jmw1Ow$!s{C^Dv5U%LZAdheNZC zH2szJ^f2W>6eiEQFQT|9#kalm7=znfk&jcgl<tyKQ4ld50eufgtJ;irZ5}5Xnf?oS z8LJgK=iSRD2N<x1XRedC<=Fe5++~h%-ist}|6`l=ENJ$(G@Y`z^mPX3W}rNNd;DUW zBqbc?)9N{z5N$0r4gqmxUmnu5)b^zwwT^4n&#y3JNo%x}W>pmI4!l$!&P|pS{037f zo(+G2;MM1|7a;uw(#qDbw=>lJ6{d#IHc8XG6)HggC^xxREWoo(n_i0J>37EyEt}F( zGtiT8tNAHNe{}V#(DGViO;)c{EM$-rzZ*>G*w2fGS&oi=YuzZ9F?jwcHRG|sZSiu$ zaSgqNp|Wm)zTr$IijR*A-ieuTjS8Q56nVyG30~_HG$1-vHsTyfC&xQ1hs<5He$t*w z3mM$l(v1(3N9GI_#Ko8la4i^U`hE8UO4!ogrmxX72g$UHI5K!RvyTzKwx-$`#`*9w zCmz4tAnF8izy&llUg4N=?KIQcCM8M6?%GNtDov4SD7aKF1e3H&F@CBNbdd>UC5Ehz zf1&+UYQ;2E=nUn*89jDU4O!q=p7XrX6#Wv;l^<>O+w8*wxs#0m;>}avII3}_00`}k z=4hDlt#jGVvEHhx?PSgdqqbv}z(aQ$QC^|Zj2fl=*^&(oM(-ZjbA?3P2;eN|AM5a? zRR}Fi*=i5b04$`EdBLV=h<5i$P4a&H$Jc(0FJif|(xm=Ze}_kS<G1T~mxih?$B;A9 z51sxF5POjqoUq_dcOHgz*gh4{yd|_>*7Hto=(mQd0VkUg_qp3jD8qXiZ*8ddyWyJw z#phaW-Vk|zEPGER*fL?==4*ZNY8G>f-T`nOm>nAt*Y%$>nZKuRf-Y$)v{A>FnM|-O zde_P3OB{E}VlHOdT(jhdcaOpW$V&FCiJT@6-d96g!+wT;Za`yoFv*$oiHU^c{q{Xh zm>Hb5y_W<1ldQdJnGXiP|3Qd!vcR^SXyaT&p!v@HZ;HA#^cv}&<0YWbz4F&PA$H`) zI$f6-$UY}`Okx-(yXMAKag89*PxOPHra4Y#$ZLUIFHB)zk587tTKB>TLVi00RPX%^ zk|Q+z@p-eu3DNN+t}-AT-u}uo%D^(<PLxy78;L8?`Bm1Kk--w;oI1mYB-@oQ6(D^H zbrezOD##Lh`EyJx^0)^lvPE?%t8vX`iwJ*9{$Qw<#xo%cp4{pso5KDET+6SUoA!?4 z_**dcnuB3xZFS($81)=XBG%WMpF^U@dyAuAG@l-$v+mAsG-TcCt34xEplTXs-Foz9 zL;bk~mSfRH8&u3D=adogybifNW3bT8`Oic!AQA*m`F~Ns1363lx6059WtBgoKWw4W z78QTms=Uc6k}^2zY&=!nZX0ob-7pUSb+(5Y-I4eCTle$dPb)N|W?&t@Xv&9$bSj@l zm!e)hXDP)J$^n(|G43HHXfOK471FN;A@uKqLaI=^$^KTsPbS;y8)6Tqrt!_hIK1s> zge}Ec!FYIX>V1QX&1NNuoHu0U{*xjvj63;G`q8T+ns-&s<9*uT3>3$tVHMtD-qoa0 zDb!utkc({dnY$cFP`PUP9WWrv@wSaIP;CjcUdZnFvbnHn3C%j6Fg)6N+qmv)t&Q;8 zE`TNb!<T-=n>wlS=su9yauht7cICIb{rH^CE1<Dha$8!#HG%ZwL5)7y+DRha0%=JF z5x?$bi1=lLON>BTp9%4V{u*1el(9hNMC9PE`%fibhfCE<DS$wrUbp3dTLw0LI8B)@ zxaih&bL>hGXp_IhpWhK`iN(YUZ<i=t8tW#K;X%Ir4b2+k%UiOV(R&YNN#Omdv(I@_ z<ftn*hVPy~4_cBj-kweKG=uTzW4#vZU93yg@4dWm=jRsAUIk*>g&afk8D%SW?=pYu zx;z1XWo~Sk4Q@TWck(>&YYfz9X5#g@BoZ^pY0q$s@@?#fUy!Hg<618`S)N9Ox>1}s z74uvup3rh@{D!NQZ$5xE!KH<F1~v|!L?9dd2KsFg_SwIr_ec9J_4@o=<Vx+2+mLY0 z>!fC9Ljk;hYiAPgI{N{5vQ!*R(Jh=#X~;7bgmUu=1RYU}I9VWZKY>3zGMT3Jm-v00 z%D-~L;8X-US4y0#^Q_2eIJEJ+fhAc%q`?!l{ZS^fJ`2R2-PL`SQJX_D;z5kl-F>MI zn=Yi8vf7b-EY0_k>zn$0b}YDBx~2A0ZjDy!kt0%bGR>Q)Za>hSqupm@J->QRdd9MW znk=F|9?XARsC_93;$Q^3At<vBYG_&>74g}O9_<o16CU;5jjubOx9|)c+WTahDmfS+ z)lpwh@@<hxh{R)G8%jRt97yjN^>QHSwCuF09^`3==tDI7z$0$}bSE<9>gLOhKP1Kb zoI^A0&zkS(PLaN!{?*Lu(%#&7F=P4JAftoUrTJ6TA98iT@WCTDl-)=J4}Xg1I9UnN zz&wqX_Z9Mc?03!gI9iUdu8c7b7~Q(+0yRsYYh#Gq_^*oUX=+;^3KCVEPjrq^4Mf@v zCAk@5b=aptA_AU6jhc{bM_Xa`X*Evjaiw*<<@(WA5G>7`AD<uN6Qcwp&Rjs#Ojl&c zjJt{?M-``Vp|Ry(OCg(V=J{R9m*PylN3?sH1E^3EsO#}Lmg@tkYWXxYn}PfnQfIN$ zg&o%Q`|Oh5M4Jyi{~M;3rh7?#k@mX0ZGFz+Slwxu!9DJoZ?GX_@Z(QC4md#fKg+!0 z3zTj<JpmtCHuV28+2uC=^uCn`iJ^ieAO-(t5&2Mv4dajhcTB`_g9b_OrIu5~&aJ>M zg2vQqw4;1;Tq^{e(Co3%PAL<i+3DlAaj86;A$@F57rktr$@~c3Qrj#>9fcPiKB@R; zz-_A)e_1Qh(qymCC0-~z2+~OzOD!z5NJuq*$KP$GAI0WQtXOA!Ms-cdPb&tx7E-IV zD&y95JQ?4BxeeGuMt^|n4bfC7b9AMj<Q_enzdv{J(7G5@DE{5E{d@HSI|6p}{q*y9 z478>Xbs*#&f`;IFka@zz8J8e8Egy$l_$P87I3)(O0Ewth*OBSZXU|Btex8y=2c0I? zNRl*n^j>1F)a;B6P!}LEMgC)73Xk<fC}l6#8tp-bUm>zkh-e7MtQ>Il&EiIYv}7l5 zuJjJhnB9s=qW5~Ze5e@5*Dp}}p9(y0J&2EkzqR(vQO(jQz{ZmhHdoefs$Om;Mge8K zJNtP>HTk37FXF8-Fy+d3j<n-IDWUWjOkt*`EdK14FsVn>?xNRw;dZP?7z5cs>~S1G z;dtnozv5OcnMmJcGb`^sQM@yl)hYWrO$=Lf_aZ~5y5p;!w`?)rXz;o=Ns2A*lazc? z84gjkZCc-PFc$$MuZVQU-00!#Pp5ns926{5@^|pJUMgXf$;^;*F0V^C4h4B*r@Y=! z1sDxkGy*C3lMnyi=DoAxd$M2uMFuNG7mScftg%>Et;-CR6sX-k#r?-PdlUaAiFfpo z8srxzxuj(!Li5SAyVrpKQ3e}saY-(3PqrLnV%+4d;BDr0dXPFk?PN3s1^3$IzZtRT z{vaMq?8WaNSy(#TQ6=bMeE<d+-&Py81m3yIH=OG!^W~d$_%Fuvt9T(Fes+c-ut6rg z&e$;1X_K}j$bz2{;}zh&&zwH#s>&TE92IVR83C>adwCFY*YsdK@G`%lt|mt@R1<X8 zH#R{=`3Px$CGpV$@9m<vEcE%?8-EV3fNCDYe`OtsA8tYW{C=SW&gp!EKc5T9u8FL0 z9ms+Mlnu=2YFl+C?C96IuM`2fDY0+MOg|CwjhtpW1wQ_iwT2i1G(j_gcYlQ{mR}iQ zmMb#eRen^sWSL(!PcFGp+Vga9#;Jy)@f)(^xvBPCoFDC$0w*uAuR`nHz1znXw93#w z44YgnITKNhXFbvJi=R)Gx2QD5Pb!Rv#7?x&DHB(b<~`Muw|c24AY3hJZq^zvcTW3- za;n{uO??*k=^@zWw6T;KwdXOIV2nMCSVrT1N(l`rt9c5-T$ppT(>dWHsnANby|3tw z;#6$$zAjOxw7Jn_0IF`-er=rt-}srjexJpxEI%^Ii#0;d5(pF!?8?}l&iHg?AveUz zG2ex-zsuKUB5w9f!_}`=%+$w2UiJ{slevcLp+EVUrjAX$J{}*vj7e2z6(-z={!ehq z=>Fr`@BQ6wmtyXnfg>NsdC`}0h+8Ncg_z5lnVp*BHoxn&8u@BBYrJS$Zx@!e(EV#V z0YXg=dAtQYkPoShLk7MqH;KBO9S12jre$2z)>`tZRHZuWg{)xU&r3G!_hs-G?+wvx zpkLbUc|W2Rx+HnL3tB!IqK;_#45SLhr7KXQB{Y|*j!i<d8b$KxT`sA?P(^1YojpwT z_UAV@S`WKxC{R%;eDGR!n1WxOY&qUvEr;=^4H8PR&DStbwLMp!sq@NVt{6MH{61Z2 z{RyXm0z3)&_Dg{at;PmXGLQ{W=o0j_TU_7DCj{M;h$zAsn;rRemf*k%i#pyil(xh8 zJJg7k*ZdxlpU>6PmJ(u=5}wMt$n3#|qeZK#s?n<$JQ@XWc<jsW(wCXs05Z+d9lqej zmQ(-PiuJ(L#9V!5Bakgz6+u@?bNNq*YlzUx3YcrMMVKWq(=ULYz{Pcpb~QM-zi(Xh zdUMPQ&~HRF3X)^tV=k2rJ=W}oo&%e%dLlHQkF0$5E&CQ9R@3A+LpEO{sM*T*DnAAx z6yecV?+)K2)v$oE{;~<YXl3XQIB4*$o=9j~<_kk(MqEIz`iIN%q*~-|iF{7##9MAm zCfS<{rnmFR+!95$Ej^+uzi(7EK)>c7fM-mr>$-Hdo&UnXiEB||3{JfX98&-T!q9cn zMMswyeqA838FaLI`C?Mz7w(&oYV4J&BDbn@12<(HME;j^_`d?x)+UQdA61(Lk~7DZ zJN@&`W6;7K7NSPbjcT^+{?YsEx*LR?7TX1{{u@hqc{BrE1>p5yD0rU1xgGtBSxkIg zv}*Ik_hmJ-fCNX_^S<SYQ&QaXR}(hGuo~Y1n&pB)?BExKh0UPkM9r?VF%W7UOTJIZ zv7n^TSb%)O_}j+R-2WOBwpcIVuo4}8j{|LvowaXtl>N=vXeH*`aa73bsbL3k-QlNN zhIIFxNG`fj7n;BHrxTb}fB7nb5R~w<;Xp4z>+06}SW$CHSS?%PvXT%HQ+PkIvScr> z<2Q3b;@9q9pM{gXV+Ju;`WvhPDG?$=G9f`Q;{FjTez)A`)9v!A;Wu$Pi9Emew4(!- z1<O@=o|%;IJF63(3q1IRvI%Lcm$ZTQVu=S=u?KDoer+0r$EBSBwMti9Mqjwrf!629 zB01bx*?!Bf$h`YgS%rsL*l0ytfL7x*#X0vNLgwJ%gKU$qG|v`qH^icM)-{CdM`5zn z%tssod(qZ|+nv~i@!*3_>F-wGCF-e2>O}&YchkpDy*EEVsZnjaU;GX%PCI+8y)Rk` zYx}dLal9&-=k8dhH*%~=P5WcEXFr(ItjfoJ?>@`9z|uVv-<|*TV?DAf<!31<YTp_A zp9mSi5~Ww0;G?gOj^Zy@^4{g*rT)n6hI)&LC~`Vhn^W>pw(`{4-3Wfwjk|r4<ofSO z2~KWPZ|vT{ME_i$YVnTDdIzh7sM7GK%%`Yd<VB6>-m6DAODkiwDg&J(+BzwDuDCOi zFi4%2tk>J>uBse8{$>puC&yNM@cOS7ZC=+1jngP`=rv5rhFhD{+_Y16GjI?CJZlMx zVQGXTM(SBLZbyb0wXGVxlwKd-6xw>0Utlfj2d{}5iYe##gu8)EtfHbUH&t7dvKTID zAoexCt2K6<^l&veu%Bi%llg^1%)7G7yCER21kRX$)_SOWU{g-`HkK1U^}SvZ!EyjO zJij49ZFEF`h;blT@)55kRg^t)y~j_wk#Qau!SNegvcD_J9L6Sa+r%o4GO96O)Qx$p z;q-nLwdfV$A^H^Jmw3RGuFa$Z`6(MjZt0bN^QBi5WnyO5JB14g?}<7HJ_?g($Cc;t z67>xvv{0wGfjQH%-0t#JsI%cIz8FuPCb2q{zvcknoNK47L2^36wZucN$uc*AY)hnT z5(ZDkNRM?g>kq6-{K7=&_;jmgFWiiN#Sxq`@6VkkzU8z!9empJ^u4B(+sNlK+j5Qa zDg7>oEB;_N3*uJySNt+q-MU**X3Hyjz9WRS@n}cSo|WW(t3A3ea%TPJU7rOC?s&9s zdR|3PIN6;i`~dw*?~%B-L!O?%NVzPRM%7B1Vw8F&fVlJJuNx6Cu%GhC=FdIGKD6@3 zlia{=ix;KUtmi@<Sc)E-T-nm9I>@w~>Rd*aP1~`rSP885TNBSrbbD&Ls6?|ao4+`0 zc+)+H%&`}=ntLpZTP<1V*VhGZtoF?L4R4JBe{#c@T``bEv$AG5tL?<Zv!`92{Eg7# znS!&>IvPOm!1Q}LitF}A2Lg_{^;m7Yl5+-GT*&4Q>!Y4G2eL&jW}RZ^IL}<?oSCxn z9qV5w2suXDd|Y7l`|Q<SvZo9*QxBOeqMFfbK1~!x3%ohp$X3?-d*s*(;@OPXz*VgZ z|451E#Q9Q&>l(kaKKb{(*Xn^%`Auy;@`{S!kD!CTjNREB%;FPZPS7L{ajo8a)FxQL zEc~7(z^k9#kwk*J@TUQByuNN%z_I=+(}FpkPS(z5Pj7DseR}Z@-o+)LUfv1HnAa+p zC3;qvFYT}MK8ncBvaXF2c%)-M*D=>dntSHFvcXYTNgk6L_c;c_A7;mSqb}W|4wArW zXWqSYmzva*6|xjZ`4zA$v~MO%@@d9{Zw$wybgk|W`ijTu9sKTv?BUDq(-p6`k<QgC zT$5EDS%3~ZJU=o09EF^!j^cvo>O~FKJjj^OZ#%11y!<5H?SM@)Yjoaizj$A7qczOS z4Ty{X;!FT}QhZGEfBfg*)J!4xSE!rJqtJ4$ZbQMvM~~@9m^UA{%KmFyKhH|SUn!lL z|L^&L-Q3rkgwVVE+7870A$COU9;j6`y)&1ki4tf8QvRB?-~yWlX4Tf>JL8TiF70|n zM4QP!G!aGl1ez`ywed1p>zf)<x)QP*wT13YwKu>@o22L!K`!crOvV@#**WV+Sl3Rj zGbjI^$Ba@7>;sxef(YsI-sAdQqT(>7x{Emq6EcjLl_M7sb`_pr6V50RlD?j99nCqs zM2-p&1DcWuwwLz4RO(Gn8zx~lap^e3IfrS`ohGHl!!)M)&CvNBU&$*Gxo-65^V>`e zL};^snOt?|VMF!?#r1u~N@MEEB1V}jGHe;Ox3P~hf=n6n7X9{NB7uLu#P=#hu75mX z>{XNhlAg>@PI5Q7bx$BZD#;u$Nm^2-o~Eio043Ll+wztGC26dVxQ5vC)F^U<?7!J$ zCh=P0Kxt$9u}1<?L!MtXHD`n!OQ>fGwzGa5G~9A(EZY_pcJ$b7oGr0E8@C8t?yG;Q zI}D{BYTLbk5w-i{O?TRp$_S^F?ly+7-%dMo)1m9GD~a~-<iYCL%RZ9Pq2JC$?ELm> zs<5SIb<yHc_z97^tl<ABCqPDnSZ_cK+V{;ofBE3$71(~>lON>$i;IflJCevK_7UYW zASE{wsn?D9A4_FRSMmCIVVOEE<iYO4&a#?S@9ETcU#&I#=03v{iFWU?3fPZ3ODG4} z0(3+db=85rov`R_3@Z-$Faf~*QENqw;<m8o`dqeL_kMZc6YkF?K;4k}rcL1Xhpt8? zG^=)m2itC?^Hd9<d}2acwAD%~S_xp{fNF01B+WvqJmhE)%jDQr>;N-^0g<Ay9uv|2 zX%_`P-a^n$>ad1G|EFS8r1gZm#@wqu^?m0pvk%cddhv^+vzdcLdSAR)$L<$b&>OAU z+mor|M7aE=dZ?m^P-6yz0rf#91!wXDBdfj(Hxnet8V4ST9-Xsp3>T}m>RXLY#2y8% zeN!w=oxXnCy^ex#N649KjDv9JhCe5IprQKCEKRzMgKsR7ZmsSdbAD^`T+JI7FMg?? zht37fQVTl1@u6&Np|T7B`pQWXfs~_ce>Bw=?6&S?+6akvKpbpwGHsgbT8F?@8n~EW z?5g7wW%m{FqZz@R!q38U%B=vaLzV@eYK}mu2O=RQpm=e~Mx}eI9y5L3kE(q_`_u+E zJJ(1~Q;~7p5L8Zb=Qms0E<WvBdIfw&C1Un=I-c{w{V44wPTC=z)<Ze}2vIH5LpS$w ziJfmG@F&&Ze9BK$X`F2TQ{XU?E?PP>lDfrGJ|Hu*z3#=}lp8}OEJV-C4G!MLi33qY zw`<k|A5kSA;);X+8yJhj<tXU1EvgJT>Va&)*X|q@7(o=+-)Z+cOf1N7b{1*>E;$_b z+?=JI66TDN6Ib|Uk^y}PoYF}??cSFt@Px&oORtuLF+#<2ymRmYxmS9r6FuVRPHIuR zZbUFU1bCw1V2lhu_fBf?OB0*Knhmv?Ir9qACc(I<qv~QwKBhRJ*tnB=O8WBT%}bLV zbiM?l>#|nFxCU7kD;zvdWo#PBR;bX_Np92JU|U+J_`dvX>_8y5#93Hau+8Iyj>9zI zx#fM*wE%P2s&KRRmJ^0-`oW^?f?HFIj$(^v6?9AZr<(~(G_ucLF^r0Irr6HH@%AXk zQ-&>fmIAQZnnnlL#pNY10uWo*YqCzB=#3j^aGFMHkmMvSN<32TwACEyq(O#%S+j5T z8lpy}?#)rnX}`hlKq>n`!owOo0HnPQrB2fc-a-5rtp~W33Kg${!5z;`*f;@FBw2MV zUCTC;Uf#Q(w>!E@5tpy0VH{@9TCDcl{aYS~A1cP?-NtP>YuZ6p6xb$?$NXrb6TVD# zWr(nhSbii|Ebm=Fe7V=yHux=~`*`4ej_;|LTp#~RP#VBL3_{ka0vnZp1;NyK`NLbr z-x}Vap@$FOO`dutatu4aLM8@3Q{-lM7J5Y)yw3>O6q)=mowFtvyH5Xy3K*Sa<n$|d zY$|QrMTaB;-4XmVc_2XtIS;k_9|E|&uZsm<nfzvE7N?rfm_&Bn=NQ~p$L%*?8W?}2 zi03O;U;pj=YhT1(`xUy#q)YM_YMIM`-&NZ{=s>HOVbqQIF!G&@(OF}Zi)oJYC0o_0 zm@o3mDO*NszzYfs-R_p|YB+qF+fCDEF6=0L8d*#^E576G<MS4jn9!%w0)KJeamc@z zr50`a{U&bve7leYMc|er7hH32Ci9Fn*=OCmmXJgy<Q%*GH@RjYe&k|Wk!{j6&aE5y zO>StWIh7z7-dyuVf@Zb@RZFuma)(H^Z^$$9ji$Gpa?;-t+XZ5-gU2CRr?ig33}vL& z0ngWXkS$M>!+#nnOa4|T0iT4$nZ6_R5wbGoHL+O=7bI!sw=Ngkwy)9$1#{0lRR>6p z^Ba;#ZY1*mc8q5@18xs};Tmobw5T?3gKYJgqyl`g5X(Lrz6%k+%f?Cb_->JH0ahfk z2B(2KND<X&oT;SidtfvUcL9Mn4<`i9%=pBst!`JjrY<8vlMU5Byh1(TzO5(Epf8IB zkntHL{2urG$`nVjx91OA?ofFfCqhRjC3mPt3nJ$(99G=dTr`Yt%5G9rypny^0s4iS zTXe=g?M&5-VIPqIJ{dzje=ilY9sqH<v+i_QsyfL?RBUuiwzzjB%6Fm8ctrkJ|I6zq zi(QRYVgC<J1l#?y`$P37y3JxT$q@EPH<QuZ=*9OoS|d3qqMa}8uJX8p%);gv?a32H z6zMGfTq*!AW9gOB+}H%M)-Mro`?F)prIWfKu-$h4eLG9#w3B9}V7(y6rqNWch`q$- z>^amFN_|ek1Ha@;4yyi+`y7b>$@#uPwmi_i(Gfz8GXdA4h7wLs1pyI+>36jWf3Aw2 zR|`OB10UcLnrWmVAiMN%T-Q*w(Rw^4W+80NEa`xcGW_a{Uak*dqhS4eH)C+OYu?mX zZNEGF+Q|;444!#@CY0LWhIA-bVH=C<&0UxGEA-7u3o#VpB9P0ag^*p|!Ji2BS9F8L zOyecj0wixFQb<)2e}Qdy&hrt86>@U`G6?-m80zvN?u|qy&~V;P(<a)SYp{I{8h@M2 zvQZnZv!D*NAv7EXo(=ava9uh;!RDl_Lyho_neoB_leHlz^@^G!C%?Q#(CP?V6XRgA zyhQrRWgI>-l|1nl_eZWnMJcw$;UeYA`0nE&-m7H8n+IK9TJvw`W9EZVQ?EFtC?rdj zNk%qBAOS1xvbR;2bJjeTlsch=R}KWt|7$~Ny*(5X$SA8pO%YvOY2&3)PRCoP&aVH< z1lS%65<m)x*YGjZ3zGkv1VD`P@ek>J*MFE+8}@%%u(f(tr6yc0Q;%%7ZWg6jP3}J) z5Ux})^LWDRH*n|i({<b)eEi~P0O9NB_WRah<~sLeUk=+ph{9rOCu^jQ`y9q@f+2g2 z7gpnRXUWYyNX~RkN6Z#d=$UZp{OiT~->$!lY0!M>X~paga6-W#5a*GYdaWL487gf7 z#{8WLTwgQsHk=lSOK+q(w_&&7Otkn+|ENz!v{~y$5{b~BP>F*56|nl70NxLa8~UYw z+G~kqPYpd^tQ#jIE#h~DDVU4gW5vS1(PI)eMu>O?B#_O?=hQeF-LU!P+v!=3yeOdH zri_~1JXL7#8iOOdXCN0&wEHUV{EX1o%<C8G(o9v=E>hYqdE-9&EExD#Kz!V<LHpAG z#(k>n1%Q{9h5}V3TOGlHoDbhnFM4m(&f{7S6~ox$yfb~BQtb4sTWCg7uQh!%F&Nn7 z5C|@zx;p5WYP0(8TAptTaSRhzm?@?nFqR@83p7rvG2eLq==7~05pRJ+C`#_-^Xkj3 zR?K`il~fzY0>|8ES=-N1K?ch=rS7{?oGQ?|{7zqT8`Y5Ci0~1Pv0G%V^0>)_gb#-< zCdH!mFZLBQN$G%B{0WW;P}$a%{M`#)INiKc)ia5vx?92dBW~^Xt}f$>FVN7N91a9# zf9Xbd8^U#$0L=p(A&id_w+Cd}_!ZTCD)LtLy?>9Gb7tm3*3UK>KT>&T{)G_!=B{Z> zh8)|?^cLa+Gb`4^dW6nvub4KUJ_m;z5nXiapRRuur`kv+U0-xk!|O_+Z3K3T8p0Ty z1F_(4il`kQr!W$tCi-5cOB9ER$A{=Z*VoD({2xoGXV3cV;4*H*cdwVKFY5<1n1O18 z*O(UGbGk5jhDuy9o|rg(eJzio9-PsY!rr~H@%0JPD9!5g&5dCm@`(%I>F}c(cL%#h zMrj$bgKZk3V-??2H%%aVpi4gWZSvMb&2VeA3*y@E%YsBTE`eFi20$tbyTz-AL>x;m zD2_Sj8YvD7NqiLnjBm_^Vh$^;fT3u53ltCgrJJo-fcEGM1Y;wrMlW>?bS7R<ge8a> z!=oN=d0GT2F;gy;ZGNbpyV;vAV{i5{AWbdj)m{{Y>n)H1?&@|gjO$S+OQ6qysRC{R zZ?JkECz}(=oVGqbWUx#<QFF>JxzV<!+oz{ACu>>9QA4<>IX>JTtnu(wF(k>A_PB@7 zT?E^#K*E4fDx$xDE#^$YjDMqdF50mhd+|I>rcM(&i8#8C8tCzxdc*iDeOLC10Wfp) z*o6X;d&ww=uGBaG?S+g-PlAHy+$fxs8!2#&#sMd~BM(QTS@|T2n|)(M;WE6JYOVWD zBPHtvO^|%Zon-m<d2EAmbdKuSp>zyrT70ztoi|U*ya(j&joaxEdB1h}!N4(@9K4qu z1k*XOCniDw-qxq7KLgT)m7^&qGwg;EZv6Cfi@3S5%9VG+@e9j5aV2DwT5pqhy{?^Z zfi?L<v)e?EzvMRU6`yZUsC@J?@WLD59|97`LBy7mrru^b(4if79;kR?C-3w9j+-2? zz>^YQHO1yM(~90)kX2_Qs+b7!jx2tt45lNL)OHFwh5*K%bTBc@&EO(JSm7{UjL<3g zXXp?;2n_Zdf(%%EffMtAXzX#+8Y<wH6iWciI(1Tf!<l8{pLa}N(WK5mbxmO#?ENwJ zT|jNwASPA=U^4LUMO5CCt#{H)6$Bpk)0`<$0FmyIa>dN0U_xif(9WsmORjO!-7;_! zAhq;EW+0jX)YsGize5tdE!7Q<Sk9dn%q@vl%esm3nxQEh2Y2?G_#wp&rR)n<r>!Mx zUeCqazT=8t<&W#KP1m*-{(D(+O*<wvJH<W&-d+37D)qE3(mGixif~uz&nzNoG@+YG zdYy!}ZuED6?D<==&5JuAd^vBpPVpb2H{<&0&?|{g6Vfm)l__#f<!*S2J0H-<RwJ;w z$*L`$%j|55S6rWcG?yE%e($3LK2=#<s;c2)TOF&l@Jn5(p8RbbcN50eft+$Vi)iT3 zX}2+ZQV%s~;wE1rU9DV&G}t})gI@~nQ};Bc{L|3C!q$9efz|O#M0hjdoRo_Q-Rsw1 z&<rL>K^7hq90rze|By#ds9aW@qu{h~9=S9V;wKf2HZ^SI(ks!+EF4m`R`V?~1roKu ziAPL6dyA!s-dgA4C4z1Xt%Y9sw7{O@b*nbDf}O%m+)9#YHZLmAoSFFemP)24N~+jn zlLd3^)zM>|dO&>4nHTAzvd_bl&DfapZE!ak3f#xdU<-R`Rsk_{q<HWQ1L)I2Gbi<Y zDAk0qv}5aG>mNCq(+@hi^da(y2d+a8h~0te9jRI%acW|#0<$+?bU4KetuGNypmo;d zI&86=1>@$Jy3}}U(^g325i;J%QHG=LLfZtiRjpUl%GqL&%9Gm(_KN=!b^k8ur9L0Z zlS<_to&A<mJK}u(p`;bVd)>#ZglVoH&^QGnM(9Y*h@%>FXHKd9??Ws@^~5oev()3% zEima(+WrljdE1KlcTde4lS(b>4y0QM8Os!_qf|x8l3$dSMoOqV@xuolO1}kz74aWm zp5m9e7y#6Ccr1+q-}$5kUb7LX6q=}^Xup#$S<(e<R)5|MEfyxjX=(l_pU;)F9bJ!2 z4`eX|EAEljD!hi!7Y;8ySm7F75^)UBy=2<EdYf(ustr0LJdMGzL5b%V$(qP#ha{td z>eFW=>8)ccW~sMy@y`c|(sd5D>=!;soztGYzvNBu7fN;wkUn8T;_mSHr3<0%vCo<> z7_u)j1G=)%H_i4T3zfD{c-j6~Y#&}S@;_=`_f&^mBMcoJABgk7P|vn{$<tH%{jxCg z{?Ym?LJP+BxibnJ113xE)S)NztD$LW-^2J_?+5P+7tHXWOF?8QE)Ae+;6!4-W8%@c zkB?c?0i02(!=ejtZd(ua4fSDY<rOf<0pY3cCp{gWdQh>ltZ|K>WnT_LTjp(QT}AJy z<@#}bDP-TSVyZ`mqYR;5u0{mAB6OW`*BE#GsDISd(6(L>ZLlmov2FaNOFh9nXVZRP z!b$f3`*afrU8=a*E&s9erHDNSwLY23S8A+OQkaCDGhGQ#1wOjmt>adepC1@n)p-4X z=o+Ff6Y``Qw{>JWkfqVt@6p%+XSfbOevx7ob8wRDI!pKo$lVYD8ue{MhSYVTau3-A zLL!4CP-N>JO#@6%fB_?9Vo(Gx3Lq3oH8WiAtv^46LvCV?G-9Gh_M2FvNAeI4Jfj1{ z$fGvtESxtRTr0k6d%oxB0`_Ps0(k|H@5AUawRZMNvtY}|?YczAXbQ22x(h9^B<XWe zAEb(&#mQu1h~2;y@Eacw)U)Xlzf!=<IwR(4!VyZD)zVFZXh4-L?RsF7k*0&z^dJ)6 z)3)%pBA9cAs6-G=laQjy=CZc=AAJ<j-2EwgK*zP;y<YG#=fM*XKfbFz>O2omchKGZ z!F3?0c6I2xq-qHXON-Z}hg!BwHtGD^chuik-R)#Xs}2^ILxde_o6^!x_bp&tGHZH6 zpsDi@ku%Cw371ZP)ciNWhYomFi_Z}xm>`WDv)L!oj`OF4zOqWmrCn|o(GX8nfvce2 zKk4e#%LLNITP{~=v!}oo^zR$$PkHhi)P^X^WFl%h+@AY|XtUC2Pw><z_aIyRQ+&wt zaJjIw>nw+xUF2V{J=oJ<`hTty07vtwZsh{0LDwDjtCrn|W^m<`Me4M<G`s`)8fCw$ ztz?!yp?0yjDOPTolD_e*rd=(Q-a&%Q?SfY=%S`K3N80tm_!c~i-pcxgux%>0jJD1q z5>&a(oxa#kTr)RzRMJ(jnbIM}e=d~LKHBKWZjzPk;O`yC67SEVE<yos*Lv5S-h*AW zSdg91CUMob0G;^j=my-0m!z_Nzj4h)m-|9Sc%4h>QZ|RcyC>!0LOte%7ttX3A(Y&V zkST1kw(0iw{vj$uRY^^8d`>O5q-Og0mQ*uHrkTC8nZ2U90NzZ!;$WUg;XBy%tGTaH z13bpDCFw>!rUPBR6;`~7IzU-T;-2F_T<!~Qy-Hi@C5ONB`C-$XAn}5>f224pR&={@ z-Xcf{2=0y^`Ez08-YOscM8hrx08nHjG8M(Ad1_syii-tYQX^JRt&SY)5;J0SNH4V( z&N-=9mrWIw%7EI1dVY6=p}X^O<z2Y&sBr2G5DZ%Z6aN^AIUl?wYn!Z9ArHaoCg{i* zb*CL$uNQEMf3)R@gYN~W+7>>Bzxl`XXG`sR(i%Zo>+&C>Cbyl=zO#$14Q2|E;SWZl z#{bcxl%Xt67#4cIKSGtKb31xCs8Y<nu|(~z{@u5ft=%)M3W+P6_ydB2#GU_X_a?8z z-Eo4Bam#YOpXO8%O#}XL+w41)FTUB}jx1QyH7RmN1zl~&tD~Y^o-}(Qyp6`?d>rfd zZ?1E!syamXX^4Fjd*4V!nym!0TT;0Ep_Vh%gK%|>wv~-685)-KF-pn<y)h3N*>1EC znb=MtE_O-XZYC32P4IU~;SV`ScCisO{B<ykI;LrE$;(~>-O=Z0ZhOK3K>$t)PZ~A4 zcB8K7ezm!_R4|+H-d%llANC5FpmQ=2JmZGd*yF(fUsV$=s|@_i2LD=>g)E-s!o&wh zusEsre&^#v#<_GRL$}4uFG1G-Slh`4GhK@>T=q#&tN*5c!gjbpe2Z%6S{}F-+<K(e zWJQMQa2}!_F6*;j3IJ8I3FK-Z9s$(GM5M>dp+JioKW56s<lqC+KQ1#$K&aQ7VJNsZ zx%cQNvl~(4S;imyMcIRsBAR;So0&`3VfFmhEm}Gm?HP=xwWG;ka!L;cRS$ARoY#JL z`XBqnjZa2St^bdyvyN)I{r^9m3P?($D4?VuGGe5Ph?FRuf}(T{7#oZf5hO&(v4KiS zOZNyF0s_)C7~PB>&F}4f-=FXKo#Vfp<2mnL*Y%3$^YM(Nco3j#9MfpXU(n8WFfuWs zrlw5cT5QQ<Bn^%Ex6Iw-xJlEZV`qVNf=;n8h{7^)Q8xSTe<rpMZqQK2ULc!*NbPpS zDRY=sQQEYz?{;I`zeST8=$%~Mi9jsG)<enjB3*psF3)`H=}U6tOzY0tomrMx5nr5X zgY0!z9gh)>*_oJFYK1mAm8ggl#>dlxJDiszoAPK6=gg4imG%;R2ETt<!ZPdhvS!7K zHHRa9(Fc1whL87X!4odqggaSKOO$3Phn*_%_K+hYx{zeAUJp>Qo4z0gwMt`ylA(*i zlocI3?jPMenFo=n*T_-!oR_`dJ-bw%{0pIe?H$#!RI5@J$w`<(Ctwr3LO!xH;2m_2 zSK%ImxWH|msj(ZR8QLMFMP<5-CNDqmZQZt>)9sKuQcww*KEvrP?#qatZj$eI2^JS* zH1<T*Q*`IU1_LnMNc{bHy;qpJYDEAGK6+jYaVMAt!)7T7d63TDM?oF@NeZ?w6xG7d z5zR6taK)N=V89~pNO}gC{6{@9nVD`z0}yCFD^|eNoz_NjKaV&>=}0p4a92XB0?QT$ zUExQo0pFN%iH>BxRk$l->`&<?zm^uU0d&%{lLlrnU+mQnRkOLu%c1)s!8NWT7e+-K z<HI8&wJh1no$>IT;^K*$DW2!Eq#NDq?}h&_)URbzkj%xF*&kM3u?(Ji{{SR9DP|An zpo-s2*ftzhMkfFT^4}fE^_|!q`9^{NjxW&oK5lYvIQ}k-I?i9&RvKGVugkqQod6D3 zuyyvZaGJGP3)XA&?>LueEWGk3ccfJy^HgBQ{;rL-VR;(w9CZ?`@4WV!#6vc#WrIQs z0|9u|+HUXIK^FDm_Zv6oc0a}7v`{7v+wXMnT;L*&z!XRk3BME?P2CgMNA>j88*<)p zqt~0~EBK2pME2sT%kj<_a=N?74Jz!;GH7$8R&lz7oXDeTWg&#2;zJrWe%8|z8h_nC z9hF8O&%`IG)cm-lGLw8fPPckxYBmSs0r_Z%5%U80c`$mldx7ez9HZqi8@i*YMX*06 z8{(>`RX|>6E|ETtcznxmWO%O5iFYC$j~g;v4WE4u>?U|cl@Pq-P@@84qd25uFl<%u zIghbIewy+O{NZwUk!a7>IJ)<lqfq4uG2~Cnv(=%Bmjl%enwEG=w*C>V5F>l4n8wx< zF^&E#N!$kQBsH<?9G-T|BB8QV1bdWr^L3x0ws89E3;Rxj;{&Ga|2(?Dy(<;K(C?La zdcE0u<uMJ{--^kKd*mCKkMC(pXPM?v6flcy=N|@;x<*II#Q*Qb)iXDTy!eo_rQj-h z^!wqw+|(CgR}lfm-Jw(g>x6k>ZUGUu%OaMyYF(7|^4*%64f^bUS`pI`S7(j{Q;`Qa zA5qp`NuwSnQ>{9dk4Z6mwd`^(!hFl5+rJ9%wH+Rv514JzB`iCNy~LZSEM}RFgSahb z$?<MWy<W7{2{|UzJwG}XwuJHv$b3DiX-ndX9YIb?t<O8Gd#snZwz$wQc?X@s6BMvR zUaQ)w?GL9YUu@1n=}1dSH<tz`Ny`h`E;uaaA7mIh8w-PaJZw<VMS-T+%hJF-E{)gF z#|A&R#HhaK67Zx#tpchOKsp$zq(gNodP+V;Ikg}-MLuO838b1L&=9)d6AS&h9@7RO zjwy_c*miyv7p7i~B1vJZHopdIj4Yj9X;a9~F+#f5&%u`Qt_67TZit25TJdTLpF$(Y zg51@P=_<%YU~AxW2jcg?Wp70-nx!AxOhGo#Cu(v0(p<K3F#Aub<;j6bwjCGDa{thN z_KqxfYU5YAZzE}$D{0s4mTf-XX-`}9vuF9R^c9IS%<lSqy0Wxk5e$=CA@4GxytJcc z_TS_IP%wSHrt+va9DGHYEW+(e=wPk8{=|OZ>aUXk^|&WY6MP7fYfM5bt|3ySO|Wjb zanr5;JF0nogto>Z?=N|DJ&&oq$_h_qY4H)@a0Zr=wa2yoVI?S1bst>vR0cd+P@i!i ziW(Fi`+X@lvB&3&729`4&zRWTCu^8(u(xZkGo9-T)o0qJo2>jJoohVhA0RY(zvygh zAp(dnr+Qk8MLOdk`Xj7`N$|xp9Cj)Ad7|GHld@t3S((r9#KH`d6D~JTK0jHYcBKKu zEJg;4*XIT7Vf&xONT0hI6m|0%D^xjPn8lg<s#bLN-{?oJDqB&UD<IS=R0E<UcV+RE z`vPcEU9XP`z-e`i>AyBjiy0a1mJ1#P0+LvJHrDnEN^oa7K<1Pn`M!Dyk}SS30>xIV zc&%n)v&Vsq`k=1{>}|maxQi$KuEAvavS-^i`y<JN8=N#<<ykR`!bDH`{J{)vYHyuK zsNt}ceXF=(<Pmj6bouagp(_Vm$1i7Bf;?>U`T4v<gZSxeFYcy1dxUnjTbE`@L?}ip zc5bGlLFgwf{5l}uiTro|PeBTL_O$TXcUXRI@1sjT(LfSwtMs--HRt-nx&&Hb>Hv6x zD8b66_-gWL9VY)NFF<+##!k{b4TXHhqW>F50LXMXqDEyn!?d|=e#_bGC#1)@p7NRp z!(j`)A!EZ~dR?3FR^%SU4*8|Mx}wtLKrQ4nusP6v&c(57oPPXkhJ}I7va6#y(O=<Z zN_x<kiSUj(eyWU&=mf+@%_r5g&~3#Ziy5n(nV)_lkXz3=ASru1LLT7Nbls^;=0WtB zn~;wWY*KPSbdx=_G30IondC>J_04P@GFHE)$?uKLTiU!$O3q<@fq3$`H&Ku(F~xxj z$U5TQNvdu;!5|?f7gX9xWZmY}2g&Tb0zzLX0T#BC4PPfB#bIm07ja=((bz&@S3Wv9 zZe|-qDs+-#uA_~J<GVc6uikjc&D@Vx$0$)xk~=e-R}t80`@TG2e6$?*lx9Rm6~JEi zCKhWZ=2T|A!aNZGNm}$LyccMoo|>y?!WeqIh;<@6jQ+~D1Q9;da|$`?&ujpG#_*!Y zIR_HYdJ-0%M;v?;dadW&^udXN5Mv*d;NLW-_~B%qShfSVRaw5goRDxZW6&e1Rfy1& zxYWB&5&tWUen7-}A8_sdh@84NS7F(9>umA5%4I~!@*|pmJ~@bj2;Jck0G`n=d){Mi zx}7ak_Mh<P$Lqsb#TobLHc#uDG}QK^fVzyUJI(PRLHM8WgTKvGiJkL8mc3Kj(p|g8 z<vZr^_tBc4eCyD9kJSRpvku#*pbDwEd`QF7Y6ilY-u$1Ka_S^>?u_5%@5=G26L65` zLC3{Fz?$qC!`3Ez-|scQv9P<I)-}C%D`dti9=v`DA5Q7qgH0vG5)hvy`Q@p)z2w}; zG*bkNK4}~8%)sZ}7Fe-C39HcxRIdXu7IyY6Ka%X#6n$Hk^hpX&cqRcEsqkRW7MU*u zZKh9X;a7roeLeaERKF?;JCcZ<vX_G=^~H^~WZ1#h`bRTN0dyu6WXIAm4<_#|n=Ku* z(TxDvw}kPga3Cb<g<e4)_=h@C;+CWV=wpsrU=+B^(^)->N2pk#N>i<de#ZX=<=V3Y zdfsUbTX;a77gsDsu|q@TldtXu$L)kyNWuCO{oDqg>HYlgWzhbm<tah|UyKLE%HYY1 z0niw4oTt)T!QY@cS7{sMyLyhZ`H^H>?2rmlHUN)Wj0n~Wp9HHgd{gvCr9l~ODk1fp zS5*FYUJs4~8UPh=TJ|}jPl)Np^};ER4PB<}W;GO(z}e!f9f!j&04&V+DsvdEzOdsC z31E8Eis$EJrhqcBgtfL*lda&Ev9GvwDfc~}?A#XROGdxGt(WyO@5`Mz{VcXNhb6}v ze^<*$y}Je|VMu!{)!>PN<Qv}v_Un>Qd=swHZC9}rIhhmVAw~COb54QlXy_dah~olH zlKb^RSBG)opmYWE3?DtoDPb4AMYTm@{faz!Ng)kGT~JDgT-4PiDeLy)F|iHT#uP(w z3WeO#`W%CL&`TXV{CT|wplUZVVy>wxmcDK%=SavQsAIT;x4tu4+<`m!W#YZulv%gH z_rz)j=Qt_qf&n0Ir1g9wu9RU_i_eDBFV-!$nB?N}h4$1JziX4^X7{d-pKq9``5#4* zq!2U#m9Mj8*lPTTVwQK<=IQQp#N!!1b5L0l>NsU1;%8gv3)lqR+y|UwYvfsluf1F| zxS@2TS%>0Xh9{C?$M{q_<e+C`=3F-$SGi`G=IThf!`n0^U&kRXL)*iB{<F&1t}E-z zY)Rj`+(5>Audh<&6aV^;#woX;lwiRpgVi^Ay;vbDzEqpVn$b}SU_{Mv>WXLtpBIno zRGr+A6Q{Qj53y^!Bir-5;R3E$-#D&#TAxwn@!+q`AdO(swyguYM39(276;0z!kkiE z97$)}!kND{w4~g0o8s(69NwDAhdw2))bhSL5KVMRz2$ty7cDnE;HLH8B#OdT@5OPV z@4-*YN%ugoLEwJJ&fSeaT!Of5p{sWZa$?s09V``j@?Z6sv1&(BEW?Pw<UrQyj}b>B zR>?)T!dJ(OMur7(KV^z|m)x<8p5>Cf_4L>+32-fDsip^lr!)5BJ`_>u#fon6=SM)9 zrFfP`SS2$!L@0^1K&HB1cvUq?!J^wDN06}J+a>PfhszAET>fz^&N+en16S96ShylI zsE(dXcyh)}7NYg7DbGRzP0pB=_vK<vqZWU^9K2KR&kM?PwPgqWMBB3^FId~4JX?aj zt`p3FtFo$({Hgz55MLD#FjB?QvaK$FK7Of~71Sol@nTX%?codskp1_)^@^mQ<nV>o ziQJx1#Epvv;*Vm5a_r|lb!y)chRFkc%%<||&mMz;0avH{nt3}J?QH|X*DO!{gV!7K z8d*|R%HI%JQO_UN-vIT3(6iog(~I$CHlunBjNH^z0Zcr5q<2!>U-bB>fEW}ej8r-p zyJAz8-&d4<TZRiO4?VPZL<fBAdT{kNO-r&!JP%MM6R!Z5YQn(8Qp@kc^I5eUiH;{o zzv+r+HIieBHxxe=J*kg7kN{Y1_y5Mw<j$@BIF9+JlLdY2Sd&&`@=1GBznI=G98*ZQ zuoklF$Gw#PL~05?S>3YlhY4(_&&MKWV=DEz=X6<L%g*;kRsz(g{F*<(kE&UVfb3pj zXa4fW+pi^)0FR)01`?{~MYmUAQ}<i8i2O}s3tL9M#5@PElyMk5!$?-Q$zYUtuiH!w zcN?&qk|dhi^Hn#Kd10v5%7b+jyn{Fav-tH_h3*zC=E4WS+<xCfH&4+S{vzWi>?l+< zior#H7uiO#+YO|Kl&aAcl##|EK3UuH4xX)A4F~Bg)-Ws{ohnt4`_A_+Hc_!6B8>$Q z!3(D@`mqZLJun^80D+RF(>#V|%<*>8GmE~~dqkHBJ2w|?)LTCuRLJDm)_Jr6)^<$# zz=7c)^QuBP4%}%(sR!3i^wM@~&m21$30TvO6=o>;9*K+_j|&43@%2pSMy7J2-qqL4 zC7KnqG&5@l*U_d~vBS!r7PVY1{0ZJ6d*5uMr8KbPi{1lwPEPS2_J<Ll!wLgvB)VkA z{;Y&~aHhvD#zX5?6#QA*?6}Y+-f^8UMK7ngraDPf+MX^JxOhXcF)?nXa1=*ap4GH3 zeN8MtkWcN6m{Y>iw%FRMOx_ZHszdF`GteQKK;JU6An5^c`hdWhYI+uru3bkNnEEUr z>t%*YDHSl*@8Csf)B`NyIF9R@%Ml+3X+N36vf&Whqph9F_G+%nC!bK4AE}`9Q_++y z>yGD@#y$G_U$Na-qpLS2?+iyaz*+RuNiv+s4yuLhW9z@dAY;4)9;`+teE&3DKz=)9 zO~TS9TnFf7!*z^;7)R$LUv^&zEOmI`HO$I`I2F2?6l~=*OLd~IE;F6{VhtuaPH;<h zOXdiQs&6NA|9EofU#LtU3@O{H+9b24YbtxMdJ1I7h6|#H3He{+&@<d{O279_oe3F@ z9RWx(lo6us7XB{Li|a1~Np&Rq`VAj-)z~nKj=?6|^znrE8Q^^~AG;)&(L1YmA0Z_O z5qrWoTv79&+^vSSngda|3p>}cBq?^i$y)9p8$qnqpBl<BZ`TW>;T=tn1OJd^0tA{Z zf7_nC4F?13%8P{Y#5+YYvDyIIw}5Nu+>DxGClL-)-}j_=^CBl~Wsa_uMd&O%c4NUU zKSq15{U$Dy0XmVdS99?{&7CcwEMdBgd7fw=))0&O!IlIUW^d=_7kuLz0iTQ){U+sd z9s`&``GJp@P}<HV%1rg&gFTwyUFF{G3aZBjoEVQy&Xzgj^5D!4?dqR6FN43ZwN<RF z$aC))ez*ec9nwf!jt$y0C`Ki4{$LOm!uu)DBBovye4Vx2c&@O)4u%6T_}{Eq*kRbM z%lB5uxQ`S@f*}%RWX|JDzl(P?lu2~m<$Os?U9Ry1fi3{-zd$t*H>_jOUsZ#F;9Xz+ z$uK&)#YkHGz3!0!0(2okAi<g}YR4gxt?^u2f}h<d7geZwc0-C=zc_;@UcG1c2nF(D zxDQTyx9BW8&^^|r0b9!c7~exOG*y6EQvqLuUPHh<Aq|^k;I{2xN*S}m-AL-3TZW`$ zPd4<r_rrF=qs3<lkBXna6*r$%0zO?s4r!~^C45w*KI=}*A8lIWo#<)`uLc!@%F|SH zt=5Uy&l@v=c`D|AJb!e0WdCSl`BJwZ?|UlOSp0Sg()C6sE)9w$I$C!)Zb<Qvr}lH+ zy}g<m6o?!-&h~JA&CV>0sj9le5X<bHL*6AjMxCXmzO1(LWH+b(H^oBwJ#$Fs^sRZ} zgnvOGz{7g$e!I^u=t+nkw21AkhdxCgm{YH6j6wPhI>g=PNLxu17$Y{gu!hkd;tbL7 zwT}O5cWfi%my6F1y1I%BY1(~%h+pz~8cWp<MOM!9%$JGN{Dv&hn!AbehpuI^_UkPM z6^MrHxi>@s8E>1N{1fjKZ0jmls&`)c$Zv|4RyN(x2iS=Rb75`a82<#mlFq7X26&2S z0SW((M_?f3d2;dgjV%^s61+m%)Ix3E<?4}1%c3&6f*+k+Hp%(bsw!<bB<X%ot#*3& z>DcK9_?=v|e{`9ERrZhda|QHn|1U6kBf2TYI#h64X$Jzi;&%@b?4Wig6WCdZ*@ee= zW$+otdb0Z^2@jguL{jzu(XQC38O58VwMHeVkKesizckvUPe$!3IQY2CttYZb%1Tm< z11d<xZ%}|d4QfiO)qsh>do_d)YGq($cCe!)8~Gnk54sh9aBRmk^nrI}S@;N)t574; zVc8sCV+RQoE&~-o+n11OXIYJuJ?Qd|Lff>TVJ4h9k~kHNQi2yaeI||I&Fa{*^jaUG ziN?xg@z{M>{1p2fc!SZ?Oql?zb)NXSurzng`1f8L(E^T{EfGBs_UjR&j@E}ga<x&r zjXPtz9&wRcf9<<}S2{io{$|$CegC(UqfpCWO;ikacM|4P=jzSJ2L2eb`~0=mSV`^t zIu*U)EG?zzD|JBS_GR)Om<_Pt@(gRM!9Z%6zna0UEop!gW(!wXyf{MpL55j6LpxTd zqu5;S_(74!rNeh@5XNOY$6!jlG^2-bNgJCo**%j*AH3S8k#JD-{^^KngyxVS=8iOq zq(`Rr4&FAfdqOp_sY@X@Vn}ju>HX<~i$3u?tokyjOAi{}-y9Gx{|bQadpkGE-3r59 zk!rn8kGVuIM#ktxMn3sf_eD@_&D&r-zLWXkQ(LK~Un(6<bWJDp=*cewY}MpHTQQ2A zxtgl!WXj}Xwk8=&KALJu>0Qu}1Bw0=>j((YE`>POMOR)-mp!!;eoZi?t=R6_yc7GB zZUF#`xb%`O`PfzEV5oiQLQ7Y2tagflxj$=n9XzM`g2Scmxreu8`lwx6j8jsIH3Q{V z!}v3#$VI>vnJiH|)lW(4N7u8nhq048;+F&RzAc?Jn#1hXsl6R_w;(amkjZa$uWNrY zGMTHm?Za0j9@kcSq6&4zM)MAJdg24T2_>HoZZPZHN><FY3L1P46b8s)+^v)~#momX zd13gBNxQ}C@vL_rZv0vM)98whyen?2S@S?$isI<y$6tqC05$vL=1m~3t8nV+#`^z+ zupuQnZ8gr)2VF~852p%Q!0upDYYz4QP<gegHUo|XYWBVNlZu?1KD@YA@AM3~Nu$-8 zViU_H<MeTj85qweb4I56Dl%KR2hvF4k>t(%Hldq6^bXtVH;#o|ib#`Qdr?+nE-fYf zvR*tAj15uvSrrKo$Mq=S*zEanQ`|3D$^epz8Df@BH8rPw8us+vfdavc%@2%-WtZx5 zQNFH==aGm&;6Bp!tW)5#Z0bx9y5h{Cfm)gtB>QZ`e$=4fDl>HMNO?B$uI^na_f+T$ zo1Sx*E5<@mH+md!=a2kegs;9urQ6s(QcEwt0we~~-V(1vlBI@?wl{*5H@vJEk(0Xx zz0D1*^;IEfGW<#9*I&DNy8HG_We&i=feP>Z9lP>3JZ8?v39)Ro92<g07hfzda)O`6 z6%3(WdGe84wdZ91pQOgpB~!OpfQP72_nyst9^g}s;HFrydyCt?eo6_qtVb$EZ=fs5 z4H_)@ieQN=S0+64m=2^@?l(bi@WeP+s*Q4w7|gf}5)A-@o7O=|qC=Wq-*>?w*z&ub z>3z#2pITn$?Z(HyA3=1|Q6K9*s`bWrUNj|P#jg|)4o3y9F}1J90N?le3u&W&&|WPl zguo|i2B6k@W7F>U3OPSyUmva%w&K7Ni2A^(=cl|{A8M~{>V8_XTkbfL_4HHSK1W?R zUXI(0JF6^kbvHlsQ6ia-;gzB_ObVE8*ue^qdS0oRS$D0|jUwI!n(1}R!}=?eG;#fa zTNPUrt7S^vm~s)9B!Ebmb{BP592q5<((ob&VW~*u)~#J`;t9K?Nx@#-nZdIA^!ujx zn-YsE!KY8oH%_nNZ$d(PHO_q+dv0$TLKv$iJRf2-mDHZhVE9R0*nwdOU|Dh(C3^6? zrw$-PPNV8uh^n}RrWPT01(n~I@wXZaHiHD+c#g8qnc<IlS5lIaGO;R)lq3}`tr<^W z4RQ)xxBXL@{AI&Y<+%W<^hwpr@b$>EHH!K1cJl;NHP|&0xA>1_mUZAAvH;;va+!1f zu8(&0MT(t(r%63%0+7Tcsqf!q?WV@cFZr?TWl4iaiVV>)MKt5IiBV_e1c&FO5RbRj zi<47T4Kt0U5<$h&)~R>e%K~!_3M4l+V)BNzJD%*R-QbGrJwK}yitf#}=*cx|g7}PQ zI_B>)e@H*?3G8{yJ<&a-$;0*U3p}s<nCXCJ0RCfu9Mu(m_8{a*kXVuS#WS-Vi4tRM z6#Ip}bu8BN!WZ=GFo!ve_oV><<Uv4L{yxVzv=U_gf5tbUi6VdPZ|l|$Kj2xSTnF(} ztS*U$PbGY|`$Pg}=y&Uh;9GkGx0ty|_IQ?A=5K-;J&Dz1Q-fL14K{p|^Y$5eEqdq! zCB|&rSIu@-s9|f*|Gw1VHF*zu?f!IzCgaZYBCpG!PPQTv84LUz+hNj>;3=2MoL7N* zU~A%h9l7B1Pfi~Idnshtgz}Qt0Zk|=1V}Jo!OX!^SxD;5v@%bP_uX=Y)_ab5Isnq* zL#m^ZLs?^i<H>m9kXPJvstS^y{9K{Sf^0wfSS%;_xpKZP`Sg;QL+}Hj(;7DdG^huh zk&p(-8~tEORy`n^>(&j)7nbv)+v+>OK-%)25e?z7!+^0$TW*<}d?`XZxH6AsZ9r9u zFgwSC({MPHdY{?X*r5TnFrr%qzW4^uWCDhEN}OY(yx>j}|K$v2<10J0j8XBD*1J~| zhQ~*~#VBMBDA^G`ghof4*ACUN4;sPF0o~K%6@uK-?1W7{F}GgYz*=<gkF;mN!TWcL z9M-U7aks}SPw8Tv-~XvOtbCfUC-6qo-TJ196q;H}+l!qMKg$pRs064{e{IU~8G5bi z{FOtQ-{-pm{2IanyyogOjK#fz&dl~$QJ{#Q4t2WQx)|^#Slh30_#K?<p?o!m{e-tO zA=YiMdira?S~&u0K{H+<skz)%^t^_L4&Svfi`Fh??d)YcGNAW4sXt3Q@^n!BviK_q z7*b^L^%i^ZR(DW|#vwW^0{I4;T6%|w!M$b8zN+He+*1^dSh2Doq2F#KS8f%P(2Gd} znRo+Vwp82z8(>PNyA_&raedph=H*=9Uvp3>?0)y9jL0{JG?9wU(~#k@62wSwzVk;? zV^cwLWnib&jJzwk=&Nxqi<*VvFIs$o0jEh0HN0Dhw$HYeZj`?GEXL)IYpSZc*_8rK zBhb{oIv^dc1xRqKS@Yo~;6j=q9UT$3`aZ=9vfYB~Hod29?^cgiL-xen!z6nW_p(?v z-GD8t@N3ENofHmYssO)&34`Wp!Qxh714+{n^u~8y^eD<Q@bw+?lNVr|?MS>9EI@kp z=nXPbwKcuxH|8|;mL>i7p8bJ_sm<Z%-pLutW&7^>Maw%#iT}2D6Lw}~idW3|l)gO- zZ|y0k{GD(f;(PtMz=jT!PdZ>rrx^eO5?kyqFXpd?t|Ni5L|8yr_arc`s+RxsMG~4` zo-`^hZ>8kX_*Nx7l@@I|cW1)#DkCmAh7VfLw;O4$XTt9vUCkx=%x$V^A$)lp3;J>! z&~dH*+$KycbSO+E=@Mo<Y8UZ*6T5ZZvt|~|TOkXq%cWWzCI<YabQTNDyBOnYj7wLt z^+KT_G1LsNYsMO~=l7^>GU5aK&-~WpTGbk+O$n*|#US~`U11vD-Zj)lwkO=u-GyxF zz&+p<?~uwYot$b@ZgK9Vy^%qOLCWMK6)fZVc|ZT+X;@Bm&}^Af_XGVZuY3i19z$(s z67li!&}w3VJ`Z=(pkh@T(4s=RpsVRatvm8Lz8k!_eBJf-$7o9nGE(^Fjm=Db+@3hM zbcYOK8D&JVmo1dr3qS4LHxBX3uEecku1&=sO+KR}%t%`$Pa|%6?i&-lAi?kfub;V$ zH)lK&Xd2dzxIe{8QJL2%GqP`{nKj|ej>k+qxbFYRa+;W5!2LSmFN;8FxFxDSR2Bh3 zOLu!^dGL9yA?~}=OC1mkrZAjpSdM4Ft>Gvp{n5I)_(_gmmYLBbAthc&Aj<S#*WjXX z;`jePH!S!KJrb~+cL_+ErLMtXF-vtf!x+PFz4~(cP;ekEtUG&z%lxXfTWI|6Bu+Eo zvz7Z5!h5f5*K>3H?P8;;H@`YT|9pnmZ78@q`<}?p_*a7&D!KK0v>Kh|o(I>78>7bK zziM({{&o)w9w!kq)!Sc!rubf)o_CdHta+7QOpdnu@Eq?myleo<CI-oLm(Uda(4~T> z8g>VpEkr2MD0NX)k?L(xVS^2kuV@FQvA=?hP2KtS?qeRXzaiySD8FW%MW6A?<%oar zE<NUrt~BGShwB1p%M>El6^9Tfc+d{&4SuQR4RWZyd=A|?v8#d~#IkW}E0JQp__IFy z&JN{S{?Yc)CDLW0Ckl{dx^XlQDi$dcy{Z~=M{bG+={3yNv9zV({e<uOsvn8ziISb` zC!d2d<EAN4oAY@|scFij@a1(B)n5*Hop}uWwySz@+UZla7DgX;U%Q~ZeL{f&-pZ<X zwdJrmV3gt{RuRYx#CBJnG~2Zv+8I}%SMC%KywV<F8@L*4-#HTYW*WP`&-iH$-XW*R zI&kJUE&Shy3Mm=6B7FV}rN{WR+%@}|%4eUd{0*aa`WdN;lZIm}{jkFm^k35d-@J06 zI?2GPdg%Q7wi(q}T2J!-v{36jDG*kEw^?TxeaP<O#_!(7?Xan>v7iR?%SV6gko<Mi zBDMj3R^V9)E9xZ~<$xr{r4p-b^XgisG~JnwBJ!Mrmdpm$axAO#R$u8^xaw5`&)nBe z===K9LApX9Scg>3WJbX~g-wE--&48iM@T0$%9_-A*7F>SDamYnHL!ZOJx8Dv?dflY zv2?k{=*6h1mOjI(c})(UB>E}Dk*Hoi{bq6y*`6K>TOCov?p^YW&ld~1x2j!Fee4>b z)j%S1aRxd*BL~9ei>1Eu-S_w)&qt1WzB@@JR*GTnD`nW!#c%fOJSxb*$@dDg0pTR{ z)9C{M7JhfF^^BSDh!D0;AE-j^y>Z;H2rgAWbc8pufPU5a<$SJw$wp0d4oZNDr1d)2 zF{F<fBJnuCOsL3fy*#?fHQn)Ap?AQQJ7!|1UHLob<=mV+Z#jCgWWTgD6}7TvJa9(4 z;_v@EPj4>tm(LEbOIc$7ooq3lw?v7$6^t;UG|a#*wxmgF=l5f#`D2Oo%sZwav2UIu zH+XW_K96zCCDEkiX#7}OGcC%2EhrlmdBYOUPQ$Jd^(N*dwE=ryd{TIe{m7Z|klpJ4 zJl!otWkl=2lr(QEs2YeNK_M;H)7@=Dm7!{`e(IBCLwMygJvR%@gXR|E2JOfkmHe{Q z3_QOQT+y;y>D%L@?mgGVO*im${09RC;pg;dqn5~d?@>9{r_P*3)a4{w8%y_bx0`Mf zaP6`g)i4ye-)bT|(nLPx2ohX<u+Jmanyy6W7%XpwVN9|6%Xjkn$GQ`fKU>wFct|FW zr%EF6OOUIfvasb0ViSG28J`gh42nzQ&8m*XI?>YPuN8NE3g+MwiHIQuY*k7QefQWc z60d_Q%Dc2qTfcm}eRt7nfp=9>(ZRnFvcPS7f++BdwOiHDkIe^iY@haI0z$}Y(r&+C z*po}nALE(mMhzw1^=?sYhHJnUt0H0uT4=jEuaMsLFp{~Xbo~ZXJfUA@G1hBBh6X;F zjscgs3@_xceu`kBMbbAo2@A=6KI=UHI7G3Tl>uh`krZ%qmqp^o<LTdy44Yqz9a;~3 z@0%Y6IlldtgJqp!Y;^1UFw&LIEHq@jtf{#EM0qONs-J!bQl<i4Ut-)?DO%Fl+zmTJ zSOY5?AVnH+10Wa2VXM;8oIG4rL}YJGB0aF{18}{HhQ-LcKnZkk@9&9qlCpm8_R8U( zjq8rUy=yxO2O%YCb3yg*SbR{0bg&nQ`Y9uBehy&)bmCUPC!2sc5^#}xL2Meqf07D3 zG!njPAl_nt-nzR(w%1n*_I?!`l*mzp{h;nwWqon%%Qb!P+p3Fb$J94!iv<OG47R{s zbPLk61oW*Jug+7JLAi#=XWAHP?2$6l7{AzHMRHw}jQ6s>LdIP9+0Q1Y0y}{wtJ8%~ zzRV+5?u9Ows|E8J=6*KaaQF0`z)cShYtd;g?r{S8Q9DPg26`EULgVR)@P(9dRq1!- z53{$7pd{6XxL+HXI|{2JeGg^G%e7q0@;;b9y;AG&4NB$>OgL9B#y37MJUv7`9~Pc6 zRoZRw4ms;4!R~*%{zfu<b6)F#{`4;7({qa5!7zdqzQ^$a9wiG}PYTGIHpT79S0u#{ zeg{;plBldJ*WIq>_bs?9xS8-fdBjcT&uDTC&qO<zP)#KMzL}n#p`6y@)$YTS=DK(` zRQ~eFwxJ{7>wh;SP0ObA@1>H^MFG*KtDe<y1XI}8CjRz7;f<nsE81XpmP1L9I4~Ui zrvwr!>xd5f->^4yJ&WV%pX8bvPURmb3kjOfGk7;1LDyOcg&>^MTl&8I6HUR1NWQsh zKYZZX5iR9$yw0z~g{R4UbU56!4}P-9#qmn`q~%1`ch$z*$;Am~!CpzG=5OB>;iT#J zOpMDgGD>O1K=e=D?mhQU+^eSe=Mp8P$VI-VcrK@()2CFl?hgXupW_2{|B&r-?_ZBq zJr|V7m&s^s`+2ISU)Ehl0ZqFH)@O8AbO;40bxAv^MzOmHWc}os2b%%58h1vA-~=T8 z#(dR|^Etb_!#NT_16o)vh}sPQj)k%gns)<S@}>oIo>0Wq!i#)fa{E=p>+o5Jg0eF) zz)X}rF;XZ9f69`p7_rB9D=jQ$MVAIO3gQ+OkQ=@R-Vbs2t!K&2xwqfvf#c<$@Yg0^ zg7{iI#}mTl5zU08V+-T-DNA{E%>$hYYI7ilZ7nUbmp`C|_yxkgv_ctBbNdnhd`XcD zBKL7t!ZpE~ygjV<GUSa{x53Lk>IM-#tU^)#7x52~U;Fuq{uAk2tI{R)6Q>#XR$G^I z^S#`Xiau`ZpvasL9&rKZ@t=R|Dz!VXdx|Zt^Z|lbKGL6*;OKtu9V}NXy*YW;CauS0 z&%+Ux-4zOG`u#72^HM+mwb;^3sJg~c&XlN#5IUp0j<gzHJ#(79qc|RZ@6PboM{{ON z(I^*1^w7t4!EBLaQoVr`a1q$OY0)#<^PL=dy{US{VXYVZ8mL$Ss~EB0y~%&F?~1P0 zE8#O#;B%66k6qvHp>4Dlum)j_wF(6NlEP@Jb=4VnMD3kPv~P3+kUsV%{b}(j(_Dgv z>$}4%TLL9Uk!h6+5Qa%wFrBTZ`ZCCB@aNpBl`a`?1%?(MuC&OUIaig3D|{B)OO{y) zaHnIIT(zmh`kP6Fhj3!S=N|$ekyd%{OCAl0iS6{Jpu=x2noa`ANy+4|k_~@Ovx`4& z4w&Tyypj9w?p7g0Tefuo5+rh;s+b;+3zV5sR4UV58>e5P*M!e?aVV4n#1PyDdN^zo zGE*1j^}>#8q_TH(_r8_Lw4}4}C~9=0)N*sIX=6Mv)Zcngz)#Lb*z(iLr#ba|Ei(;| zdlgcvPI}gk2a<_D9c>FvmUR}7ce+4J2D{{4GV9f~8MfIz0qBD$4{!y*e!O_4aI#mk zkO6=9ZvKq{NY(!O>0hVDeBe@F-$c&Q)T&ol@(gXrnp(?2aTK+AA9B6_vvvDRTZ?(! zXQPUzx__q$09uPB12y8dQvC0l9ExXVxDr{PJ2{)st^)}&Q2BiO^}ObUQsC2TP^aiW zFfOndy%no*`0AWBc$LiK_DVFYu>Zr#Px2nQ+b9E_YAZyd@0V#K4P~UeCH2w!&|L*m zn8>5p)8h`9nI^05W~LpCqEl<_Yv+0GM_0s|g2UDg0-145J47F7MvQ}YkxOJ-Ub6X( z41nc^EJsaz=W+}=ao{Vtm<eI-fv7#&?k!DnX}s&7>s0J1nHtvw2qZG)k--eS;}|mD z#b60>(a~6!y!U76p(k7;HKaGZm&xw%z6yHBDNA24(4``A{vwE2-AT1&={iR-ueW`V zpTv6J{1i}7xp|VA*u>NbAiTPz$i3I0xUf(ZTXpYPlj|4N*k`{-tJxX0gnV1}U&!w= zY>Lx4_yCz9fU7+o%n-KHqXj7M^a^Yg3pd<Cb_bI*at`!K^h(xy_>Xo!jl}Dd6bB&W z*dly{pP?>OEDKc!YRcOBH|S+mY?KLZs^DHHL|3b%^Lj-OR6OhSOew`m7<Ty@25RE0 zg;}CMQ#pDb|5@Pr)Fa}rxX0SZ3FR+4+udy6?fQ-G%UO^I(42p7UeI2&s2D5O+4kd- z>x@l5IOyeg?1pUOtzZ3oVPHKy|GY_lnh;ntAc^U)mY$Z9{AUvo7V!2oW2{F-|5rW~ zxXUv)Un@TXHGUrHn&bJibM&r&$=5TufyLeJriy`1va*6ztpSFweLy~!V?|D}2CL>T zu^BI}31DeK&9%2Fw{-D*;S+!A)mNm78se&J(Otf?b|1|mw)vW<ik3#I87yqWyD$;R zC8aHDxOo#@_n#Rj){vcpcRtU{3)%1FGPvB`8p5PBxF5TYownaYKda=H^e$3}NebCo z4di@dMN?y_T!}EOcQ+46!^%^yLX>j?sT>UgB8`JlW_V%MDB)yE1+iSHewkPa$^G&- z<Sy4=WEj(odkK5HC4i`X5sm83>EDlLB{};l)ekE<-ow<Oo5+#YeK0?Z;guhC`KM2G zuA+}Nid53x3p8F1Y|_WOo(8rLn;Xfyjqm}ETo$^K0enGwWz(0yeD!_KrY24)_Lmh0 z@`seAUWsn2b90R*MFfryS68kJA#5#m5K6&Nw>Ceem1M;{DY*XWy^ZOfd&P>O{Y|DV zAKwJL8+B~JbuWeE4oL)Ka;aJ3d7luJEw109X$gEt!7E2y)5J`{sS;jz=TV2UXeQ_G zv7j|C<D5*sdr8V*u3%yuZ3y0#9!Q93{9d%2|990I78#Fq2eRC+@3iFESDkAA=KGZO zL`L(^)rAqm4mYJ&ms77m-(y(|k~Vkzzkr6*N2qz1ka!L3@pl#&G*I{*Bkzb^orOY; zbtM^O!_a5KuIbrB4DU!@mLbQtH=^!S-?SM`3`C9afhlVkO^X?YE&c_!oh$RA&`v1+ zYOlxTN6@G!O!{QI3x=|&gaJ8odnD*`Ef0B*=f|sqRfm_t@h9TCq+Q6DoE@+8Z{nX9 zEl85bZr|kl#=4H4<0>WxW(z@KzHbbkBs-C6173Jgr-3XZJl%KKH)!Zf^3juXaVrwG z{N5e*T<!0zrtho<RC?uJ$?w?hyDboUzo77UdR#E3J&Q}hz26@s2AL{2zJ2<Rz%$-t z6TU(F#tKxLvln!ixVG`FQC$@k_fa2sT_`u+?)t!V4z0Xi6w?jQHJ%|=EsTXoKug3M z$pTD3mctvJY9Q+b4C`IDU-iH*yE;qCR`RWqL4;KqPdpTC8rBjTGAtdb5L<=CgrjqN zt}3_v+LS@m)xCS|)y^2m<AIB7wp{$R5%M_37jYVAx(Gjhi(W+-ub$5g*KJ~!B36yX zhnJ$cdXM+-2_Cg38b+L*YXiFi+%2Nql|lLe7rlol+VJ=rf)nwtWhrbWcfx@EI&oW{ zNk{-8f!Isn*XEh00%pR0A7yIxhS(dDJL--Euz2b%L<o=2I^XA5uG@}cUsLX;m+m;! z3;ORK7-jW-P}WP3f%(Bx(5q0~wEp5|7-4k(0Vi^@VRDvYEq<CTUL~{$gmFq!pXZ&k zL$^9M>O8<Vc0!6sjjNH?q{`ir?tDA<x{g8a@zzUvs(~oc)f|jnz@NL#h|DfP<|a9$ zSx>QeuC$<=7R8dmw;-V#@)%&ulypQ*{roFX4mquDnhDGn!uzOi_cwznL7qlv{V4bO z-Q!vXYR8z^K^crRBGwdt6`M?%I3(?b@kks}lG09t(g_ojpH`zjlljUr?mc=Gbf34F zW;%Uul6JDL@ySnr7s_p2eUyI$@w-M{CBv4kpG&=a;~_V7&%t0nE#-PoW`hX%Y8Xd7 zu-YhEH>T^z@7XK@=KD?k*HCX0<A=gFUZO>g4T~350S>*ga`bNIH~+>Nvdt;>huW?7 z>Wt)2=`qmvR3VBdKKure8dDQ59R2B8XexubJW%kQ>CkA=5{}HE|5eWs=|y2S<~-gG z&QMo&2Cow>*ZvW(xb>R71@J(R{+cib+*Y-)eBFw7Y5#5lgoH0!iT#SYG=uLyy)J|L zNQ4h>UCO841Le~FN>dK}(DU4JclvaXhi)vb%klsUzERb#EB5ASZ||LF_Ccgoel}}` zuOn8moLjvaNXuKj1+27;JnY>lPh{yQ1naElc}rUN%9OEZ>Lj?EU#TsG1xa7++$E6a z((kFB$?iW0U>GzWlv%x}&#ly)6kO~s$~Cy;cOP)8N(vxoL3z5nbR`{U<!Wa^hQQ1} zQtpvj1qe%<@jJVigB)oW`2f$WY!57J&jye-obO)$`NA3~d=;q2^Sy)F3*i8<o|&Hv zYkHkrmublo&t|p6E9JJ3Q_Z-8kO3kG8MdxnkXnbFf_uCu2Ww6N`bDZjsx|3&Ie@P* z`%d}#hm!YeUjz*Lf_FR$B=oI-ME4_VbU!P!u2g*KOJT%QAdhG+e61#r=2v<N&d;{a z%cvOCumr&#jAF&}0sMO|s5OFt&?jaCz!&n#)@uh~A|$>cN7-k*`;00&{Qhajev->+ zfR%O^1X_uR{w4&CX-^Is{&apsdU9~wuSdE=Y!6Vo`wH3<o1$B*;j3x4D1$(xEnI~M z%Iu{Mf$e?6chvNlvaz|=Ou)wl6?B}v6`-k8*-Q@j*xMkh{C;uXU8Rd=U?$^q_Lo%y zVr}!+^fUIb(B>u~zzt9{2~Z5@9d@xtMZg3Zc*-A6+WvY1QG5M`Nx%_$&70&kCD}ka zbCF!8X1#v2=6rkf*!g2yzl&|1lYK1qvr|1_i|%*xK@pvH2}TFL468!#OmF%1I)|AZ zJaKKPi~%asA$n5SgkmWG$>&A)jw)iDzB6o%w_oc<^wJd=`riN$A)c3$XFM9I?_1!> z+}~5*!Qdu;ZK!tQkmPt-Wv)JnOC@b&Wf@kp`Kx?=ZrcHkR5dfZfUM?&Y|y01tql(H zV4r0?kcXVqGxt_~%ep|4cS2+7Anb;(`YuIx%_%t_weBv(QV_>r)u0B(d@|#5!H;&K zz6B~v8?g0P>Tlhw9!7=r)Hk4xD#uw<24Kp2qkAm}tbN0!4aQwbJ|TW}jjZd64u|jc zaf+n_0v5d?pfF%jqz;5P_iIP^*_~+YA4)u%-3VJsYlO%Hha2?MiGZ|btBp`Uat}~Y zFX4kN`B^#{x2hDh-NXIPw3`5(H9?D~-u<zgWK`K~^zJ*y-NCkP6GEwD2j<!Y)3=T@ zt2`FQ=oHVI#c?xr-x`ja^^uKXq1y$5(`J8*EdVzXwlZx;8}a%6_!&y*<J7GUHJcXe z9wk*`9jwl>^Q>Bc2Q;6RFU85YbNOb-4d72~iTwBHw=G9izA=Yf3or$(?{mhED#!4* z8}+P(jm=pZthRVA9sW)xBT5&4rQ8hPQX<nYywk-g`^~)mnfH#Tq3QWW8S$by_1O`E z|3JaPABHA;6*eBJ5;B%c*q(R1%cYb1i{_eA3(am8Q+u*NW0+0It!ODV3PE)d$Fgji zX8VSUW<RG7Bj)x_ALN|E<gVJjSAYHC%5^wxwv_C3dudLcMMci(R0}<w4?<s08m2X4 z{b6ZdJDTW$fLe55AZ}Vkx%m4`e^U=ZIiR-pq#muW%1<}ZU<dv7IO4z^(M3Dk1)p!( zuT<P5Vjmo}Zz^n9)P8-eAREadwS*d@_lc)jCtG?KBoE*$2s?H#vcr!r8yW9UwzJ`t z&|XyQ(9Im``ky!bF+a{i27rNd3OPor0yBY$TBTygpi1OQDOMGVj3d-Gmf{-tt3%zY zX{!yvSuqAQXG0#4NXgyPeD+bj_1N_@RqSWYwB)wW8e|8?2XZ$uT=nJp$WNI0KL#Ji z87eV;&$qH?A1oe<5F?A-k~^Xq+?Z^W#fYz7#Ri3T=Z9j%44;sSyJk_ohUAON%~7m? ztMmmRWW;Ep2x8b^_U5lolp|}ZhbTf0(_T(cDX;~jT6GnE(u-tLk_cOWE_|RbU=8u? zy&XdAn*p<Sj_^(-%<}Cj?~dcrOs63;;1o*V{JhBlC<vlS+-a1SwLPs4c;Hq1aj=KG zsVUWYa>8ptIZ(yf=<W}zl{Qbqz+o?Ybb%BiKj30CQa4j$$If?+0$`&3ZQV=q^{?Yu z@6CdZn1&N%&#i1>X>hp?_;&VilYsMT^^<Y03YA1_^(#JC{tnduyLE{i;zZ-tzwiv7 zD|HK@rV>Bc!YXV56TaD5hTXjKs}CbT(grw~WBr`?7CJa%<MnXvf$Zx;Ht4HNO&p_g zS%MtjU>DopGn70hvIGN~FqY)wQ|pzGYZi=@Ya1^RE6Y|_I_frzes4ES-%;@jS(UKF zGs}6=`hDCz;BoIq&E6Qj$P6&xCrMn1Cry3%)W+vN0$FmOu{-HN3wC)_ZbKPG8W=L; zif4exjF3<dsl|}csz4TuAnuaslciQt0ZrNg>_|d-j|?H%HNC{5L4)qt?5y0M@jxk0 zaG$+=ky!6Eg<7g(Txr_cu-x4W@i)Vjk;v^b%aQN$%&O_{J}Kkqd-8|$F{7vCBR#EV z|6thT*>j`t&9`Bi%N&g`wQ^dX84U;DR_&t6f%jiwT%Yt%F&2-fBzk1RmvIr+90d+P zhhD-BW|+{=DOODJJOKEUns#=LXr}&3r`4-Rl0@sO-ZF~9JhW#-@c8O7$Gf#_Gam-9 z!z&CclsY$0o!6(lOdda!@5ZiyzF!rdpBn8=_@kG-0b;fw(4rlv%GW-tjJ))JJgRK} zqux$);Nx|s_N!RhkZ3m_M!iQ@oTG>=YNM{s)Jt<}bLgCJ$38FXnC9hO9nacc!8xIx zLj;K88muQ_Lh0;+79k*)Bz3-4A@C%~UkjXxkXZQVS5rrq(qW#)5ont;yt^ntFEz2A zUbI;`nR<A<vpVuNO!1x3#;FG-@%(f+ZfE3!+vKbJ;FMHDID`(~rye{i-jK)NOJ`b} z_pOV5tl_J_#k`Ua*|CVXyD>zqj-wG9{1x`>$Q<HIY$4WSaG-16Nqm+i9H#Tv-BT&| z>G9wEk#4GIu+?ZYsu(X0%^*JN6!I94=+OC=v7#=lv{bPxkmxsKbr2FWq_Ij7w{x3o zP)w#gI45e!Z1(;rI59|&$Nrv3PQYsj)9ZojR0n0#$~4}u>+ZSteAYN80LUFGMAJO$ zQgDv^W9s$#hLoh4s#pZfRHXsqcHy?zG`71;wkkh`2MZXCc(J$#X{-utDGzj$xQv(I z;xM}z+y|yqc5!#rbDS{U5+krpMDDAf^^M`^`*j57f!=6Mcf$iey4f2Fl%SOAd+qK> z!+MTS#P{KpSzBPeI>7SXBCqVNOB{I+pzhZiak+PH>(m1^{br-ypqJ=rptXP0XI{3% z@BkVuW0mHu#Qb3;Xo~xfLlL`VoArj@cR95h*Bhc&ls4KtUNWkULd&!MI+c9xN(Ww< zhZUEc6QW*d2oh&DZ3QWE>Pj0Psr-<(m#-6W7K_!oLNlj43=me<MHfkTzkm7%h3tGg zk2SdD?K>uG6UKHnBy2W*W+l_b@6^v*Jiy;x`E580isN!a@1BX<Lc129xnSoVFCdIX zJlqODbvvxx;955$<t9*KvE=5z|5|r;B{exv4JP8<8@}<J+SlUHK)}10e)4iSCf#`b zfdtu-JXRjB9W$O_bI}-}<j?8%*>{v$tjzj%JiWh4?tGP1&lRrj-v=6-<gN=`u4KxR zJ+JRj+P4)&Yd86@l;0g7_C5o`2?UmPZ>0}3B>2aM@x}FLQ6GCiLKP?rPrk;k8}7o1 z6=1i(lO3h{o@jqpQiv#FN7g-Bu%2rDd096ZZ+433HZ*4^`Y8tWC!c20@W<pYoRF(x zA#d-6qjaF|%KVfl&ve6m;1IJ_!>D1BF9`?oO|Th1BTxlU7Jc3+yG3}*uztJeV!Uq! z%vve@^DL>x#j=e$OQXIRo6CehsRN6ez2_K==xr8i_89twn=VTL%dR!WeWXy{_mAEc zCLoL#NmN{?H@je2EvO2VNWUPvfb*XE?+@n>kgv&k6WZU%S*FmjhFNN8PF<(8#R~Mg z0WEt4Lh@7mQxm@H<+zxQd!M(Pi+*+lNH}}7RlC(~aXi3F{G%3$)Q>tI13$e4T>C9X zP+Rt}-vMfgMs>V>qD<E}+fsRNg5=h=nrriT%<bA_v>yMsCR?D{=HxhYDN2sdB&L=b zwbJEQ0S6dX?cv3tOs((~8$|viH`YgxR=HD0<yis5(RQxU^!U#Uu^=z{-rlZVmb$ZA znm^TkPu#6|XqH<2zL>qa8I0kzF#wYTJ+@s?6tbMe!7n%;bE~IjO=64!)T*@)7@d+< zNI7cmlUY>okLv}~uik`E=QfCq$2Rj-Nsc)I-hGIS`*>p*mDS7%5B1Yc1IA$g6n5fM zx`U;oTgE{kUw7k^6bIDgpN7i^musJpdUfBqY=OU|*^Cl2&<y^HEJFt!rzo_}W$5$U z1ib<DqvxV0lxQ+^Ud|Egx<h%SDz9CnHU@bXBA@Y_H9h0>agMiSF5x-FK~~(EXjM8J zg2i*p-)NBHULNf}#6TsRIW|xJ$6QgqVy#1X{UrT`&h)l^?nTN(OgjF|kmGnsA5;zO z&rI=sx+N;!cYAw_50<i28=a3#7aD&Ng$EIi6^%HtZ@TSp=9N21BH4D2m%p+}K-V)j z{AL{1c92in;nKx-5#0Mcgv(IJ<aTctLZouaF#F#E@^3*{rgd-mw|zwq7I>a3Mf+Vx zVhpUCDyL4rBp!4444vKD2mnYIPXUr`s~12qJo%7bLDZ7}_vQc2p=tW7=}$-0@p0)` zQ!bO+3M{}R%>q~V`flcpY1Wp_MemA-^LG0F0e&7E67;<z8mqrAF%6%%o2&V~TAqM= zfwJ(H93y_DuxE;VlqUhpyi4=0NIRfq;l-H;x59>M8pfKz9%O4T0Yj1YH!-p$lUbh8 zgl>2KQI*P(aRAU!-(4IOO({W2{cz6#XW{5fs8Cs;mnt6PRHg{f7bkbmS7;B^m)ljM z4vGafheC%XoDwD?XSh6?LTycm<e_dMM=Ih{`J<JPKyCj1*wDsrdbw!wi^OA2#vuP- zbSX)O>l_1KFvgu?v`g#+u+|K+=8AB5PPoQ@9P}6Vl>`co&8&a^pKD=D(Dw%XillWu z`?I{`b@OEI>FA}F+q*7w5k7MiTUrLXM@P>!iOv}Ujn;>J!=VyI`3eQX%|6SQV)u7W zRz38Jhy7QvYatLzFF*b%%}+6lt?lx!zWhI)t~;LU|NGl}MqRQsB(h5Ou9TfUFH$Ib zk84LtGD^0K?Cdh{HLelL%;?Ix_T_S|%e}ZRzxU_!{eFLshkyCQ>-~D2bDrlp(7IEF z5whW)%tv~bo?FTtTxsV=S8nQIifb%3W1&?~6{$k<+5SY#-TLQ5WIQj$&i^n7f?gqS zubYB`#`!G_yl4+Cj4x(09!K1b=z-2^szov$f98BG<rxIfau4Bym={wY0SjYb-b?xE zU}p(r1iuyBUd(t;?p0n|FUdtR<wj%g2gW>Ip_+yQlcdo-K|W`Ph{J)jc#6|g_#a;t zTeHhw?_LjQZ=HZ})quXZ$VS6KRY7z1E3sQDLEu3wQZ^cb%tOa*R||XiIE8b`{g^J% zrm<bRB<(!~EuqHWMvYOBb~kAM($4*2=A}uOUvBbRkuP7d9hG%JEh{6*_>wBzqLQ;# ztj9!-Ds^7}nv~w5Reg#Yqmh_>ol6Zz2xmlp@^7UG>$1pYI`DZXW-AQZ>vw>Q*E97R z+&WjxXyHvmi35TuNsrG+muD!NBVmFM-F7^lPl*w=u#Y8`GM*9fl6x}Kpve{d<wXf% zF^qCjh{ca9(<xiQ;mu3pwYs2|19(4u2c)=7Pr}ylR^Cj2khdfiLBAXS>%=N#PBFUG zm*`<lHx0nCRcwz$K6C@0#x679ix!83SkEaHj;SzTVT&cCC!-ig0S2>#UgVc=>V-Q) z{LE}sA`g|FtM=mqjZfVXR-Z@=55Wnc-5q|pqWu~phlx`n`o0lI+fP<(wtSX~4IrEM zBi>}oN~-+l@@h=;9|pecxW@e#$k^Q-bpEhV6j!bOjowE`>95XcJJz0O97^TL7HOEE zp1CUfn60mG#JfFQ=hr{KoynC7XN)<d=%IGmyrQ!?a=Q5ZPXnz)UVo9SAsVybUUXR{ zL=Rg%-Ex{7pIa+7I~8n0xqO5?nQ{HV?YX(S^Q#|h(JH|hyT<bQy?v!-uz(k@e06+x zAh!FrtO#KmE6In_jSrFxt5xdOrgXb*=tI*B_}SQ9v7$<E9f8s+IT`v~a;+~Op``sg z3U+uGBC92VA-O*e9~skp{W6DV+k(xml294HG|RdzN0#f9T8W6b(lRrK(G!ZgA7=wE z<mBkzxzH0D!yBwGNUPM-PshdvMFCE!le8GoMyAutBp8h6xZ<>o%SiIzODLD6Q8SKi z?<&%pD)WV;9|ByO`StJ<SP%+R{m%Iftx4eA-QJ1Y5iOCL^8y5_3t~y=Zam<(LIRB} zk;-JXkB0aNn*Ne0lGNK~<ZXuW6-tdZCO(OTHU7&n$5n=l{GJnacIl6Ty<8;t)^@pK zlQ!DPRSfT`!}#S975z6`MmQ8@vI<F7e~=j;CbaOcPIxcxtS%)ZUu*MhvnkZv&F6or zma`w&kh*DAL3V4#zu)lWox3Bhul?T<t1-nVRgi8=w}Gbfu!(2$GRkocbhi(Z{ch1> z+M2ZBJofnui0YhXujAi~eTVMTo-)dU^|3S+rFY2F|3np7y4^e}PJ5g9LjNVRXn1>} zN5Snq{@ewhzU>=--_kF+_S$^oUL07!xWRuTnyRCx^Q=GvNZjmKtQ=+RS)m`1^0U*6 zP_426I}VukKUcgwh(Rdq!S*sMH5RKb$Xe0^2f<t(wt%^yjKvV~3Cb%iy$=_~U8X1t zz(%77%yoKw{fHas8{}xKI*aIuu#yEz$UBKUi^!c?=TtGo3)ppsvTZFq-!UHIoWNbj zPH%!hwv9$C((^mB9Cv>n?3o)J)(C0qu`-~*&UNu^C~AalV~YE&5OuwmytC8XqTjxd zW#nCCqX95J`{>hmq1ikd`4b|hjG4=|e(Yn{#alZqqOaJcM`hlx7el{-4Bwao)9p}W ztJU|QjKA(StNCdX&f1cQ@NJCaFFT}I?Dmr%_2Dx=R`QlI7?)Zv8lk;+EH^+^JnFLz z!oi~nxQ_{fsw}+AgEweG;QJ?W5nT{#I;?INgtRa~)7H#WaQBT99Mp^Mbd|DIUqI!X znoLSSZNwlu%)SKzWvutaj%%KFju5mfNfm^~<0Ki+)|xl2@9CE<Y(_n}wf}3E1}DpE zwws5%791c+D`4qIcd;$LpTG~<Zes0AMcP#7@1LakWCGts%s;-ebt2VG1RVvcUSq0% zz8S$P#+ArAHph>3pQYRsb#_4h$><@48m-fErAi6O`%a2K;tdEryz@4}8Q$|j%CEv+ zBeie>r={_l_|u~-j)MM&r(a_TO&kqw%gezMu7sMsdZJB0OfsW}Qrwsw<vTHUEERIF z*FT#29w?exc!XSJjF*B4!a4?kyt7__$<lq76z^U;?UESe@+}OOn5+T&-0jb#4PZq2 zk{vtNk462mPav7m0{NiN%48jbHglm4126VLj-!pIFOR6k*4Qr{@5n+*hx>8mTUkq5 zi!G<<$vlMPIa7xEuyj9fUGmG)TYPq3gcquW*#NHUA0_yfb?A8aUlqU6^oI3C@Eab$ z|2IxuwUTZ!yltVY-6rj|8nor$RA3VC@=)Oo%Q4`<bqjR{^TI*8P7hCf%Ndt_3bU3Y zzA`QqMhXk@9DJH8lv2&AqfJcMIz;UCXPr(^j;kaIwgMdqpY)F9Nm{XeN?kVl6PeN; z(s5DIFzLyGf81KjpMeLsSA(qZJe{!?d*A=uy_EgWf~$<Dad&)Bh7EQ0Y)u@SN$p<E zDAFy!XqK)!=^yUOgYx`xo5_&>;3Ctq1GLfey220ZZkunJIyC)+Tf04caaZ*(SH5x4 z<+i14cFp}inMcMPBbC{d9mCnwJGW~>+Fh7U<n;}9tn?8(@A4ij+@qW8!QS$IP7pqv zd#d`C?r%G#($_VrT^L(~9Q|C;GOYag>B22KHO{MOmSsB_f*L;Xu+AlG1+c<maZxA1 zG5QhAyw1?tXe(z|a>!p@rdR1!&WMg4FrEV4vdsGj*RjP#oZ{T8f_>tN>Qyxa$!oo* zb7h~P!G9(3lEHF|A8sz9fF$d;cB&kqhqvNpkUnAritj^TtrqX?{>34_<&0bUf>9P$ zH_3_FDqg!}NA;nWcgWDkk$&{@KdmIlaropGs)BQoZEDDy8%$Dz_w01~w{Nj!qeJuo z72o&h?+_gc*BXX-+{#O#UINSJJDXq!2FIXV!G;O><s)-PR!cwgDf-T@XsP<}GMwYM zw4xy)%AByWMh{8l<OFP7wiDcE7AAa4lK26Lia~z1*E44~PP~LbZnhpTXQ#|2s(`c4 z$~yXez`IkSS)b`zm|s)x{d@}zD2eg0!^H@commXNf)4H9ralwnb9vu$y6TkJ7!ldp z)}DX>&#VS%zpVfFCazReOLbhLeX3!p^wF#X$uRrLm4o>7rA3b6Z7;&?^SPTVe2z*u z(6mULV4{*Zdn|pOX#ci}F$-WTy#XQ*@c~-(=_g(cp?a(z8n2{y{P|uiEA0HeuTwp( zT0>#;-AoC1!sS>{`_Ntec+E#LvzoX0rM<kOJF9_2($TI(Kp8&!6Z~MQjM8{z(2#cD zEN;KV39>QC4?=SGo2~j5_k3(ZvQeruck;z@&?0$6Tn*<#054bkRCCbwPHX;($}3Qp zGa%=%ZOx}5W|1C*(<t}bY|{#tPBFDAAM5MTX2I&@C1QX7jtZ51sPyjETHlLc*l2zG zRm0YPg^xCp)2g(^2DhN{jzMxkP^8FVZU?!%gA%arxp6KdNrp1Hc%w*z;rCo)S-i#S z%LFvqeh6L@y{Yltyp`}*Uz4^~?Z9K;0AIOiCm2v-G~`RKB(cgd0<m9lpNtvCKb*?F zqBvrrY+}4zMi|e^%Qk_S7hkK*ftf^zJ|B%c<UART!400baSp_f>|QOZaoZ3JeMtOC zgBMzn?@Y$z9MZWEp5zO`@Hv#5v74K_tT~Xwg{x|_{#vK~5Q7|9(dN&|?}tiz;aLU_ z2jKsP!MF#lf<DAHzSM@}NROGk16?4WBm9Wpva@wdj+@ScAMI|O{R|qI|M?l~EH3Q+ zFaKAweTXpC^UtCF)2VMs$?SsCJ<33#CyVXhxz{G4%%7pPF0i(-=9Brr8x*HLBa-ul zjk@vtVhaMC=+`tyE75CN`2?+IKH8=G^vgDsm>wlK1Rb<%45e1xT6jki(h<QM5Aa*$ z&XP{3VhFHLaF&t51nk$9U?lw<sI`Ef>gd{$3VJaD=m^g*M~rMCWCnW?FVY`JSK1cP z21dWPC0|$)wum-)9?0I(4TvYFZ|u~0MYWFFx}YeI-i4+iqd(2{)pqf(T7*%G&sJVX z@QO~Xo*%JG_48^E@Xa|1mi|ba^(03t40=VqsHp=5zxT?dO-h;J-=k#l=GvydGN4W} z4bPu-Fbp!(4HxL(!M2XhNweM=IWRHu2;d1KyJLMD)Do0M`K&Zk^i?4yj9;+`A{1&m zTf;a<LIn;3c*p=x0Tv&x8N^|Wjw7{eI@kw1BgEh<5UnbPK{_;ls3`DNfhuX5=Yc|* zWy=77bhavbz^58N)1^r!U@+k~#o6zNA-G>v&gi!q`gD1T38a~fF(e&r#;!z-6yU0B ze|%PGZ+??#Gj#O>ZQm1Zh`PduLG#@5%JVOXKmN8eI~=((8cnD7Z$mx)J;i}zo#}9_ zt+m1`iu=zBDFS{?b8$FC&W;p*#{da041bGjtGg<^DMIDAwEzXYw(z<<f8oXd^#JL6 z_KnqR*vaptK*Ak+zvgul;0MXEpzE9%WNp_vI5g({h`x2EQRzMp+ZWa{JEd&u%_%Ji zrHOozT-?^X_bVh8{?_jhQ+G4!jS@q+TCK!$7sUAio&TJ@WH|xdIM*b4U{@+ZUh{E` zQsVbBc6qJdkj3lXpmLk34{a29F!8P@t-(je-$#hkB5(Xi-YU<a*8HFkOBC!u1__a) zbvg@kf};+S)(h2@sujMtjQk|o5pTE%!oD<~vQN8UM?-jzQTyV}QK4X!;X4SMwsKGM zB;T|g4L*k?1qbV4DXpmr6xBZQ(4oCxzD(=}bq?nxj}@vdvn3^FP5ez-LW8$Cfsr#2 zc0(RYJ%U*Z2oUP<OR*4WS((pvf((<Z4zPa4h1J~SJYolUFGMzM+#YQGaA)@M3=lG; z)tNe3BM^9DE@Dm-=_IX1l$Z!I<hjX_!Xs#`#x;YwSK{^2@C4=?pWG2qeKQ8>7G?_C zc0Z)(aJ_u;k^O(f(kd3|y%fUx{e{^FWFmyP6!%#o@-c+1i8+*GXKQ}0rigDRt#j%a z6k^7p!F7S>jC}&lH{84tQ1%b7*-d3=eKK|f*nTVw#P>?m;%o$&t+0IlV}@dVm7bKt zyRiMtwI!1&$y)+xwSd?0pQvLRdJL^XJuAOUrsmfLPVmO#UFwYmM-}B7w~?*2K&Xqp z?n{skr!A6&3bz!Xn6iLAxfS=bwXRhg)PlI2!#G##&2pSwITU>kI&3`U_2vok=5xqg zm+@w{XrY~C#>nr+gwJ+VvyjKPnDbFe><jg)&sU6;qa8<Ik}_ee+w?^F(U_CO{8^r8 zWNyLPTg6ubR1!Yptr&D`uCx78E<feOwhN1CZbmYR8`zKauHmfsjf2Rv<%b*>Ws-9q z3f?r4>}poKJNg$;R5hZe+Y#^e_C=>b!FgL6^CMqKO!6br0i4^q28*gMB7ZLQ;hg~s zG5gCg2Xk2}fGutcXAB;eGOq+fckfoQ<)UXxyj4JLkkpXPdj7sosaBFkK-B>l{bITE z-!)VC-v}_^d%{BEy)PW+(WA+=pB7c=M&C0;w@LJ^+}sfRSa7jVc=Tz)aQ^R4M$A^) z(hCkkqrGYO?`tT5q1f<<7D0#ctw;GTWbWU(w=9m^EUv|31K|o4)yUqjbbkLuzBDYw z4l@}$nxDbquv##Wna@Mo?spO!;sYLZNdDyTxXYe5Y=Ab~N!MiS!?FOdb_Xuu6f?W^ z?*)Fmii;DZbBhgQo4++A;rfKfBth(5h3t}9<<XP3F^7+w-pJVw)G%i3IST!VlLE7b z&)$Eic=SN_>Id&3B(o+&(iW+q@W99i0FZWlj3^@DAJ(m#J8wTv1~ztp5|jrwe~q$c z%!%9bd8!lQ<;XP7p|f5@8W%>qIKgN9mK1`LMlK1E$(82>(^;-7SkRUNa`7?8+s8JN zWuL@9QixbyC+Dx4da{wmzvI{Kww2dwFGe+GrC*-M*gs)wS;KE6S1)i_q-bWLe#aL~ z;%Z4XY-OC(x9#EemeZc(_2$!-r`dKA01z*{%!=<*!U1dC!eE>hOth^J=l}e&5FGTj z?4e?%Ccc+`vb`)sG_zK*6{3B75L$%iVEEgvr4+}h!ihlg?NK_yWgAx(T2&J5kyQHt z4pKEb*_dX;wi}1nA4L^wu&Hf_*j<!FX;2(%B#J2u1m&hMw@8{_?O@5>iZAfATca8* zf0uA-$cVb9EFZANWti#yaMO0y=fSu4+T#Byr7==J<-;27+a6rKQFU2GG$ue}&evi_ zO=oxg@7vv56%CVozg1T|*kh}EBCkCJ-14^BW1qC7uJC?*W{CvJXAN-1VxQc8Sm#-r zckojkz(XNP?#v}dVI|$iPo2=G6T;bhu+yVz@)2wg)Hw7(oBpP4#iuY^rCFs#h|8IL z%SVUE!H_<e@Dc3OB1#A+9nud(C^ux=P1fpMRH>oIwx`_nOIlVD@mA~Sz2lIcq)3Nx z4rnLQ9Di>(X5QnCZ=n+ReaG+pv9^^C-(a_Rdyi#z=7t0Lu()@st}W#iNOCw&NBG>F zyBhgXVQ6fI`utFJ8-3tA*6k1@lWlYc;-g}(s*Vpa0=&k>wiXl7n5>|vp6fM>-t^{w z>&o#u{G;49y^*$j6$?2iSbd%X&#Sfw4CMRLtWm&_{E<~1V4o=B5QLEQkVWtgU?r69 zra<=!jCE3z8fJoUw>cC@un|6Pg7q_#IA9PUM{c6KqJ3u@8qFNH37+(d*$Qt1)1mIv z5V~>WODX{_acGxDoQ`%-5exN+bezM&1qE5$;=Ix)3xZ1{vCKbn@b*gJ#4$fO$W!1b z0?N$RZ80IWP3lVgt;F0f=|7f6L7Iy2Dpx|5xgF+dzLwQm=I*s#b2IMC+OyVgv(e|O zpX$_pnH4p+?sX(XEA%hunRF?(Iyf>hp3Ww&dRp>*&GYb0kKe=y<JTXsNf$e!?gGX3 zm#7@=_-TO>yeYEY3-$Y_3zN)@k@_}281DycKjz<pq^jpO!%dF^x{iZ)8}{E)n^>_W z@n@@=C`j^L>I~ffGuZz=u1NZq<D^V2Y_A=x3hd2WynV}rpG(GJOU6_>7nGU+cY>l{ z+zZHd%qqWZ@sv`6WW65nb_>5paF5LRIT-%+I(8;MLcZK*T%_>wrk3{twK8!Xb&vT3 za5i*i`jW?pY0K6wEE!1oIrp81KKQwg%o1)Jlg`z=?|It*&7C!DtLjA-;i$I8yJ4zU z*g+Nk{tt#ukMw?ja+m)!yb|nSt`hSsHC&m7*Miu}5}ZfLO9rGWdR6mR?i{F|Pby^P zBzy`pmTz?Vd=UTIpd2bMq<GndAm^qTvdaveaTYoDh5I*nU79mVH+hIK7%rT@N4HqH zW+;><Sv#T&FuLNqgY1e+QS~C6O~_fdjk5*+Hm3f2`~r<+foa!*Ws1FiUY*&h3zm6w zQC!D=X~erw&FOG11eR~vgVvW>BH|yNrR=_XW?9)>_TjAS*~y3y-R!>22cR8RMgr8c zagRS+%n`ev7i^{zu)a=@&GRB!BLkno+3sh2jzp!If9E-Aj*=_k`fs!vhVqDP@PFO3 z+ncaGE1r*b)(O=CA1kUFS5D<S`wJ~jO278ME#pioI?UXxV(2|WoNcmu&4oTzK05H! zw~R<7TBy}>cDRYeN)A>Wg0<sVu!ZXFoGk<;I5AVJ9}iRS(6f(-lu(Ec_{cbi6@D*H z>7p<wQyw(+TAWg#B7SN#D*4?py;PZVCPnC36t@vEtCSjlr_`0wJ2S+g)=#+;>Xt=$ zq;+(wKN?uHvjDWkUzhf{b<bjKTk@l3`oZfliou_(N=2!O+5p~6y*6H7>qG7eKWKfN z!L&^cD@Mp<w33N`^5z|CI~h==!-o>Two|8H_=KW^M$QV2X@kuJqC)~eDvN@nAIWgr zBII~!^n-D5xj<`ml`A)R1IssyJ2)CaKdHx3Z%kp03wEgYf&9ezzj?8{7ERyPH~1MQ zMVCeM{%Dnj@Z}0HtbZ3gg!#8)&OC1u4E`)0^7ALtY)i)NzWMq+ST@Yi8lKUgMaOf~ zpA{5qa6mQq3Z1Oe-?EYj#zxq^-yg1f^1+{)MUUsCI5`1-$9+fM>d{Xn@)NuJ|A5UY zK9lAT`-oc#G@P+{3!_P|(6bYCdJ**w)fjs&aKy7T^z3h`P+v6$rEJ;~x>z6ff8z5{ zttRakSfT$?MW`G<q|%o(3M~k4O2uX1PuHEo;&Bly($-_D;wpuU!FxQ-+#yi@ONN;p zODw}r_0<glX@}R=OaQyLwxD}06l6iQEgu~O#0LR{OK?=RScr5qnG(n#$cn~u1yIO| zqZO#|u_}(8S^cUnb`wVcUXHwnpi=@%30aW0)w-^#V()F=6IIzqCvi0!s_h+T?VlhU zywEE$J5|fJp06S$DJSaCsVdEzJnE5vkiYYd8mW0j;6*d3V=W%>{uaNnbWk)bH3>#8 z-wS4;pv~P=4Ln-h`mL0jv8f|Af>l+q6Y(C+T~ubK+S5np%mn_CeBNAG1P39uzJNuQ zNBy)<&hkZdhFTiXDiM<2uM7vzri~V$@%91Uta*R8Ms{9cbfN>ybEE)&z)~OK+X2QY z<&Ix&ROV&Ge`+N<8W)D%-+y3fH(jHxtk$1(I|1Mez@(v{jnlRNSak3_xwjtsSAKIQ zfg?jKkIi=L-89f7nd|B%sI$e|y-5@R5D2~dIFiIAM|5f3r?^?TmFpeN&CgSv;?LQd zPW_%-Nui4|+AIZV;5%yuNxITNW2|eRvSwyjevLyKz%l$!^Ln=yI-KoLx3>i9m!+L} z*3<<)cpC{kSg&zsK4~lE(J7O4KE;%9e@NMLY0PaneWeZZI$u~)0iA6nkb&jskfhH= zR9OA)U~G+8Ug=$t`y(6Vx&Y2R;+LwhsO*wS6Oa$H<D(_!&my-o5a=)+2Jso3E!9YQ zyaFSh7i3AX5XiD;e~?NdYZ;(EqOk0l$0PT!E9)Ujw5N<m^1I{~t-s6`O~A!l#+Rd2 zMnfd1*N%iT#9~Npts3*o2PGOR72pC|z2A-uEh7=0kqo@X@nn-ZXK$||#L=74t@CHo zU`EWBQ2TJ!;Lp1_sk5T8+ViJq-No2b?QP1A{@wk{Qh-MYnbdGvwhwjz$&*GwoTe`} zNo0;Yn%7K$QX8KcZ+KEThHMn?#9`*Ut=j#A3CMi1^tnJ&`Fa;XIeSkYO0y{?+kaB^ zIKwCA_^fUB@}?+=lS?pA!7!I>9^GlfQ7qEc&ZXD_3H_mxc{Kk$<OGwQqFfm(_tp~| zJSQbB^)o(1z+RGV{BDDNj`-X+<!_e>KdS`QNW@B#t&B#n%}dOS#u0)W2`psr?7z*G zU=?kS7*j@bZna*}dt`E($gaerspfRl)!9qe-7HbxCN<caK#>Cb0JSTanJt$7vD)4I zU4<L}Vfn<=y<VUT#Jl7_&j~MeuikgTyHlc04igS+O6(;%zp)ONx}u7B7mmg*C5R-d zh{X;#JHQT8&YJp$YFW!93TgqW(`x)CuKQ3qzlVC8jopNyqv*?=j&^WlL~wW(%Whj9 zBNQV3oe9_u0lNmYJR|-(YWfpndE}Ro3c0BFwu@I5Winc19<?6kI)xx_*0>NgZiG*c zo0X0>gG}5eN^e<6j^S_cF*NDFj^e2k@P;x?R?Q5Ks$b|u+Rsy<PLKp~-1)uUGua*J z8>`Yxa13{87P)htcSQEfQqf5ELacE<)&45Qj;TJ}|HW!I#;C4in`$p08nRBcQk^Xr z0b^@%i5r_^L^9Vk-;6bUkNc)0-xtz|jN5+67SV#`8@7pC=?uEkzcy$(^Qkr`2|i+I zdn2tIUkWpLBwynqt8rFNFMYv_Wod!*=c#|l1wlH=!W);8#Kw@6MB_faPS3X2H^V)@ ze?4P~c$AeoS~r}#v6Hl)IB&qQzg%$B-6e4-3uuwHU7zO)yW^XsG^Q(t4%<;%9we~X zXzkIiT8YZ`La1$E<g8MI?K5sKPo-kDOR;x8gjHR>$&>FtHEL?}@2ZgPmE@k%ZlgAM zHFkcac!a%LHbHKFtV65~ee|Y}CwX8O@E-fpU(TwQDpR8cXO;VEhnm#B&-X5`_&)cw zjxmjJOA@PJD1l}7XVhUxKXKB-twapX>h~=9R^D`gPuoeGjM~$O^7f_uEeAu?b-Lo{ zZa4U2#tq+emgyTEh0Ld+0qS-%5hG^K(cA&Cl<Gr<@<0w!0A)O)!vkd&AH_nPV)9Nk zY@wXg#>CIjgm%IV+bJ=!N5!E@0I$Drm`7bRnQBtQd6V-7MQ8Ct$pI9TAMY*P3rJXx zsF6wUbwmXI5;-yRCe8ZvAm>=u7>#0s854k!B-)YjuU>}JZLiegaA)!+>U!}kV~#rd z(b*+E;JU2JC-$`-<#d?+?g(G<ph5bv_9DgSU$sPC`{_qbWZdZTkh&s)T4v=?a%?u6 zYK=mdNZj`}ABtnxcZlp+FV?Gd@0;~8Han%=zZki5R^=-hx)e!!3i!m3pXsqPjF5Ne zgfCfiF1CeSn4&1&EgfDZcGRi;+}+*0oP>l?jw`r2+PEN2R*WSxu!~h7iQsAX(&uOG zKX?6XzMqM3cmC5G183j6|HnXjedA}jK?*^@G3OFBO25e%zNym*tKKCfnGRoR?VPat zy#PG$<nx~e^~N2bCic(!|A$h=dW<}}qxY9t&A*~wQM=adq{&?HIRUvPjY=$<31~%R zNUv0v*2<1sEkrU^K|#s4E~;)NpOab_N$(SIaDa+h;?VwN53C5+zU&C$<RvVv_v_oA zwF)YLo=Gau5*{8=PXOKVI7P>(9B*EKZoM`^nOWQ~lM=xhpG7+o?RV-a(JA`O8o^ne zu-9SltybRgZARLJ<0COtG;aRH%u0y2mZ95kDfB@OOS$1>?c^tf%b95&8NblFM1g+% z{jt)A?``)MXujC))!<=qG^GQqfUAInwCHpdTefywit-ImO27KL@)&&Nr^-ze51sfU zm|rNPlSwll!;DRw2^`dIvZ{71|M<XQuaImZBivf7Y?4p5acg3^rIQx76>20urPa9- z%57*)w@~rf=5Y>;Oc{ldjm^nNol#XVVzhtrPa`w?R11|f^4&M=gJmCc$vj4=c`Cm? z;HXY@3JuE3cg&N$G*m^PGD!a5*lh5?V~UzPOK+O7n`$N0itQVG0sT;3h)!l<2K+W; zu1`%QHc!`!rzAj0{P(-&O{Ts_48<?zT8}JucjIQU;ZAFe6fa_h>ALT4t^>8$b1gLK zF;I*D134$Yu{*jJ;rzZc@5i-ts;c;c;wPEPI{_rGj^CE(Dbcv4l^-@aEJpi#$L<#= zp<nzzA5GW`I98<+(JSxY`~Hl>WF;_k!8#=Xy9wYwBhhpeg*!M5i4KbZmF-+GsmM6I zlNfZ6RHP-4JawL3)u%X1Xg=X>fx>}w_eB6$<_H@Wu5$owP@qFHB=!{0SnfsPj41-5 z39Hq{xc(4Qq(X5Ty0Ai3@|yT$;S24dFKrMpl@#@(;H+bvuk<w@S^6+XbD)-g$smc6 zb;9xL_6m>^zE~Ij`o^Ni3wfrq+);TtjMEWC^Xr+iMRdWAS&+A+cT}V%mH${TLY)1M z5#)D6RQQ7(4nI9xQF{~i1jDsEw%9wlv$%7=tf8r7A<7&@!*o##FYql-TT*cRQ4$<w zA`*q#N^;?Hvn3AR-W;$MC>3L5Ytw?;FD}OI+aa^t_EZ928q9?}t@9Rio8FDvoq2K{ zLqV7>DFc>~o424a|IJ4lVYZ(>2GSlvj`lD?&t$%I@*<zMLp$)9B*zetOSsBXo&T|Y z)kfmUQ1*4wN}3j*+S4g($KaI<|DXnp%T%b$llH0~md_iH0JCDe$R~v&*^uPFqPykY zeZr&m|4{eBYdM?bUQ<<7-$@@SAJx%FiFjx!MnmfMggB61a3Bc=A)kN_e7ftgh=|^U z(~gs8qfh?VQfo{XX4X^9yDe?W7|=b%ZhvOjERtRb&*?s*0F=-&s>-~P^F%Gxc(=vZ z*2-RR?3F5OU})G`u?_~OKrgdw=fgvjfjHKw3YC9i#3kCfO>^hASoW->x;`m+p;>m` z`FTgik6K+1@>Zh-wCo}vqe!zmJ^-o}{T}fUK5&`rX!7m1-7#{-2O|o3f^sX(YIY5c zRo?C*1M&1{GvA+iW!a<mJY9}uwKeAZEL_Kux8R521?SfSvMiz>%p<fB%*q4G<tw}v zw9#7%2uBCC??dG5ca{t6ih~_Pt>wSDNVJQNiN)@G_6R7_t*zj*FZI7anm31AY1fPb z%YUux(KvgVg0g)J4hRNB)VgShl*5E3nSH<rKqL==$!z7#7jmW${f`o`4eJkf;`XPA zQlc27DF!~%zlQEQ*1Trd;MeJKHQDgbwRi&L{<nE&F}h}Gr-s^o6|!KowomCy#2a$$ z6#F69`<_<5B+p9yyq%*0<Nx<ohv6>YQ{&X&InNWDJwh(#RT7EqTBjfKGyuX5aAtG@ zy8yb?vfq!P33vol;#lU;r<bW5t5aANW9nuX)@Z`FKgfx`aE>kVsT3lGQrCxwoCWuy zcZ`*Jm><V;-wv)#wxaowK@Ht_eW3D0nS{)VMx#rd=K3$njcdSB{M6%K%nx)dsJ37? zEt6l306>Nvh~ikvzEE8rbiN*gxdFh=lHSokZ#9uiO}t#M0)#}GOMbPdY(8KjkY`M$ z`6)&wa=KQqTy_0R7(=j^PAPkT7VV(rwdkK_Jxg?HVLy%yx238X6Q+phQ80Lo{S7F- zOef|T96snq_TOO`@SAk5<;X_s{dVHs7%ODXU6Ij^D(t!B9nBAldMM#dZmQj0%TE^J zZePz>henyXRA)JlemTt}IbS{EWcBr>=Qol2dlw<iQlW)VUEfG0HaFh_T}@*FsKl`* zB2tD=UXvnny6II=_>oO8U9yrIX9t=hQ1Y!@lZ2~W*9mxUCvMY9(3U_9hcNYoe3h@| z%#QEZ>LPLrHW`f7<`&F5Uq%zA*P3|fX7xSpnFbu+2Uf>Mk`qdp@Egk4_`J_sIJ`+o z7&oN|u{<;mIO)*8Qw$|Nal-nC=3EOiok7{M%xbCR3ID#o03%~LXMBW|bVqY8?>(LL zn(8z^sWKH`7dKslO769Etp4>>$ESU^qVDLVHoC`{2}t+g(#S0CQZDKk^861+4;adB zs;f?|y2mHquKqIeB|4x2S#SG=UQ=M_xpJ0M(58P)zppFdd9>E4{64d<sla9Xd4U#L z89UMlF66{KZ?>Inp0V|=0YGyW<(<_nglw$tQ19LZH~=uniT9>FG=)qTLuKa>O)Zh4 z)UrzrUFY%4?my$h{eWgf-?jDc#=mOMd~<<}r2u28rk&Ei$$oHjNi#sb@pgQ$u>@93 zarqHqAn56bJ`6I;;Ze{3U2jbjQ1+@)Df&YCf~A@4PU+j|m!+mWna>im5MXCl%Iy0d zn(=4K9V~DDQB<ZVmJu4*I)H}*AXQ#+FN^DeJmM{e`<EJqcbJMy=hK`7Xa@2yOiftJ zpP#j?Pwxy$i(;z%!z5=T7O85Tr2tkJ?sz^B?iyJ-U85L>wt13Ti#g#}t2e!PH+vca z1?zLo@4!WdEyE*a3TmrS=u}y;&=GtL{JOH&*8%(c-&n1G`YAK}g6$rs$fo1Wg}75t zK5_SX@+7k?If4KEKR<=%3$g<z*0~>$@kyM~f{DY|HHnU>m15L%_CV0r`JbNb+q+Hp zc79w}Ox^MlU|7-3$BQ0IYU5aq0|Q8-#_b*>;39kckaF4c`CA1=F@CW)?Gm{fT9sYt zqt=kAS*L<gzNr7D^l_{HSF^-}<bJ);@>70Z`$>?!86AJ2Myq$VUz$ZB4np<dYua~h zjgvRCsg<KreEOP%uMS{P((l&0fy=yeaPil64wBM!sPOT8Y8YbTEJZGwM}9;WAqs(t zA&{5|3G%`FPAnS-5`Ks$BQv#8gZ@*=QIvT02<G)CIJThIr(vVKtmGM3z-!S@&yT0v z>e;<LHwm_<3^jKxaOW!fGJ^(EP(L|2A1>F4Qpz?&@(Hheud=TC5WxL-CfgG+jeB=q z2&11QDOZEZj#R+QkBlzVlB8&r3lBP*{TTfavb^hL<)m#FHK0k$nUhu%&L7yP*tb=O z;uTs&4i#E#b_)a)VZa8MLA;gp)JM7UhZ6(9C*%&I@DE5a-UEZ0h#sg%7>bk0wSJ`u zNVLy-?n;q^5V?l@yV=@791k&OjJ*RERcO@$RvTsfMoXXHPZ~+lJFe)I<il)?sTRV! zy+uy=m-%oOr+Tipk)Hv$@{OVYX&l$=heo}6`ANp^)rR7K#1GGv0jM(Z@#?#7mgjJK z4!BaA>K~o_Yca1JmBwcaKkl`7z0qTPvyb{m0Kv)wY>LJWhsq!w>HpGdfy(<}wSTLL z)>%t!H8a&1v+qh>?RIC}9^}A!=}WEo^n8A@1`FotQZL_!fym4S$0YnP@}btCbj_NZ zsT=q8Sh;JzkV>_Y+f8ad{b~~3xJb1-SFW$xGx!UcCJ)3-1uTW$ij~A&y39x?tcebk z^f$;$IlY@6ZD{GhF5jatLLqYe1{jIeDz7NehUvc_jk?Rbo;zs2k-LM-z1(jMaxvFS zO>EwC9MimH*ZVZ+17N&lrtQli|JkJgyyWSu(b<8ngK<Rc*6$8YH?N=UTm+5U-`^eW z`DpztkUahIG2LTnOu5Zl@3GI2{;8lHSNi}R<b#ne70_2VCi)ZFwXjYJs&)ElsIGl% zeQOaU!miTt?IQIiSP)o$whAufdolDM9fX;PUVIf?XpR^64rb-sYwroQodox3tB=k% ztA=$>3zlHczznGG9aovR$|Ahd4Ytj+@fw7%zF)bMgT(O++=l9C;t7@OtF6sU3l>GM zl!8L><|%!_q+h64)O$7>@@t^P?cR5JrEwF__=MbP|2(^Y9a=}=5Gn&Uxu+l0{yb~D zNvAnMYPvg?bF6w3wHtR7sx~bev*SLsR@bhh5qqpe>_|iRohDZQC=W#YJxEaJYE}Z! zj%i#~(qz&9VCWbriuPZX7CWDd<>cq}DX>0k_!2=IR(bF|3Iq2vJ#Gb(p{33u`f;Z` z-}$ed`QYYF4SIS6B+`;!F<zpfUjQ&?+bB<l!qAR+Nq54?_Cl*2EmAwKr?qC%9w6NI z?8kUvV}Hv>!=1S;1(zwNO%Mu;IcNE&@n3(u6nvI+Wo(Iy7<FxKP#-~yp&22Qn;~S< z%7kJR7gaizd=@P*Wwx}Z9_<Lf0v6omjA-s7vmL6@7ZOqW8^5U~DzzS@2{?@IMU?Qe z`b1H7;jON;GWffulEusSMmRuUZ_~mKTUO8UQ9&n}?;RqaLB9>|jV_$cw_{+`5k#*@ zqPC({6!+9Rje}&pBFih9;Q&O$J=&=IZ<54D-}+LBd{rnlOpQ$3U5Z<sp-1Adzzim} zMTJpe>KBbg-48$q*#@iYzvVYu);-N#T}k)^^PwPC0ox%E#q;O)nIymFffT=?mzr&} zziHO7mQc2N;W%FcW(fhq<O_^LWg9{3c!L8{xE+p!?3EJPXL6-o+K@i|rMNk!8Zu_~ z8h7_?@otrJ<Aj@3SKUYSoFMIqcem5so3TwZ57q?BnxBZgc}@Z77g<j#TmZ4tIFglH z5*V9E8Fe8?@(Y@8o_~6T8XsvQD9w7hRMI8FeIprw(R!yp^`C(mY;ONTyX60)U9`Av zgju=eA7^$69Db=ES5j2@MAxlim2VNOGViP&`lWDf2J>E9uGG&cbc=#eiffk&BfH(! zA?vJoI_U4M*v2-m8{UqCu_SG&7x0@k={iClh#pH`JPK#z?cUQ9`aYbCPy{UD0eZXb zVoW<(+Yq<)D$CAaWxT+2{zEmg4#8!!#czszj*GWPK@^*z;p=NI8?C;2+D)QYpTo@} zk8jbTCPyljnjjj@<Xf@x82TI~Xi#wcOCy|4WpY7)%{>pp5st_X^d~R1JZ+U<XiPnI zrg<}tW>4BKi9EiwTf-rt2^00|vM&3tT%I}=bOZF`%v}Avmq^?MOljxJ)#o)~<G;>p z?Nr+U=Qq3w-NL5?M7xcjw_My^$js_<0lFpq`qkxO2e?F3a?Doy;#>=Hp0lFD;6ZHn z@wb{vmfeRcGee&>FI1ea&cvZmd_EB*m<GXD(HtcwuS`>XjeC}02amXI^ZR>6^D;Vd z6CQ-TWIs}wcWk{$wcwe>r5m%Rzg%+NJ%0bN&c|K1^gFOz3Oo#ck-MLh=o0%Id;L?~ z%a}G+1~<*1*RvV&g1V7{hZ8)wiVkx^as#c#2HK0fA6PT_#NUmPqG$DOh8ZOMr}AsC z{W;MePE>Z{;#s5HTzO}~KAR$DHkmT&LydAvJwNxI{5&q;Lf&1lM}lr~ZJVmS`l)X2 z7o1GfYai4B7_<j0Z9vhLm`QMuZ!%>+pwQiYfh<jbg-UAoRtQL1x7Zk`h5%|M>&1KV zScS#6xF;8}k|#pmP=y+bjBTqc(Kw8>0fovl{HKctB=SW+gK2wmkfrHpbY4Bdhhhk_ zE<vOzXM`1X(AwSr?8#$ax6xtV>W*&VUqADSr-6laPYDWGSS{-q)g&Kq1^r`l5^WJ2 zFBi=?LLQ#QqrfCy!OaqL3O!|yS0_Dg?|)%bTlqeh@;oY*zivBsm1J*kKyMcs(mKmO zou(J}Uc61JP1o5(9ZpRJu7fI)!$A$&aRu{Ab!7(6^Db*1w=sRxytTtOeK!bv%akzt za`>kTXG@tWHMWqgV`p-Q0AQd;xU=P0n77Jzvo1I&Rzzd|4Y9olG861|#Q1BXqvUcA z5vzg5b9rfA<7XGp>h?0Q|AVBJRhUZFHBWPB_u`Q_d;Ds@R(76z$xu<~bIsGxrY$OS zFQ&4yc_WtYnM96eioaZ>M@<HPH#}aFfa@v~$}>mYHC=)x<^x6je!A=DcF!QjRmYF^ zWSpxCouB&bwvHH?|CTngURzNIdbGX$YjhkAsQN*?#Q)FBmU3^x6DpPToVSh*<bH~D zwWQQOa=QfOc<?u<Z^+(G-HZSc5U;yUy%n1HZSULgpSR6hp$bgCnYE0QgQ5J;QH_}6 zP}TO=;j1-LHP6pZUJ5#l#$hITX9rhIM<#ZZ=Ph<%AJrru;{gvb`nn;RK?ERUA<KQ1 z1&`to$1zV|{OWLs1n8H^tyH#46d-!)VKZ%ygtO;ybxJt}9vN$|ZW}DZb|dcokdACS zN80l#rbZ&la;Zq4JD#YqhHB)S1JX6-i!2z&@ne;tqJo{Z{yBPaKRr9zTr^vJ)XS+t z%7(Ws@N`!6^O_x+OK2{y+~yD+bN05Nyu~)oj~Oi33b=&7HzDQ_MhQplOy$ln_m!qm z5USV~A%$V<u`6r)Rc~)}8v1HPSS1ujsRmZ)%%wSPcW<_SOrA8%69mIg2LK8U<9awf zOZKtb*9%ufucjp3u-;hz2i5+nmR--lw9(s}d;#Y=-1mOVjy#wM)tl@6kq4LgV_nc_ zcT?)<N<IY&8&g|-ofq_G%0wLC;B-q|Gzoo#%^xu9QduhHKe%_pSKybQtM=z1b5BW? zih|{ih0NgICHvD0tQ1RXt%K4#Uno&6r5kVz1V4)X2?e6cl%^j3?|>b1*lQ<Tpc)j{ zzB4a09*!LxoLJ_wYFlr<8#fUVi=A<<Itu~p$A*r>j$hB{i@wD#W!KMWxjkrmsh=&7 zJYaA47=`gm`STf9<Ph1xXBLZ9WUJBc+P}5uk$ijUVdK5c?97(i-iDj0fJPB`z#Gu5 zbh%4{?;SdyjY!16p75=S@6kzqV``WlRdvWN;w4*H^H8OQ*{<_S4T7Dc?|Uc~tY-?5 z^RGz}$uqmj?ufkI`L-SVTZPHH9cHJZDSAtF)CN;2DDXb_dorgi(?r8Y%dxfkgZP&P z58sOd1WjHx_PdP!eoHObnGj<5q6S1njUu975(`K(h_FzmZAJ{svqhSkMuBKWM3?QN zr@aM`z<Bd!P|Q?Xw<negs}ivmhq(``g8&SmDs&PSJnfn52hZ3Ea+@8Ao=<1Nlt`)i zyGrscn5Z(249;)pY9F7?y@C(8UV>#1flO*!ju9eUl$mO%uhCvhqM=4IN=oZA${*4F z?zDY(e+0au_>J|81f8K6;dphl*cIsiJT|n<@e_Ya>y<Iros?e>eT6zY{}^p?JpAL@ zR)^=%oAra~#9o0jvM>CLsw9@heh^AE7b2Wo?NDPJ_x#h`Ia9Ib75F@yerwdgmG+%! zQQgfm+BqSBY90TtY9hWB*&+PjbrrzN{bkKKSR@O(pR+gN;bwGoTSX#&Snb>z^tka& z+Qcn%fXWx!b_6_f*P+n7Qoe?kZbr8&*l)mWSsKTYUc&z||Ddh>u_3>q?3wY{f{4F` z87-mwts!z5`T5Yo#@c+quYD!x83e(pD^AHy_(pa;ca7J3EMiy;5!oe&2@rHr>m-+H z%;zrXC)^&{Sn5@mh{B(|ebf}PGLE_){3o1|I=j6=OTfER3X#7{J=?n2@`GtR#M0gf z(iJgm6+v~Dfw?GGr9Ps|2XZOW`{ikDM+1O@a+$@4E7QcIhEiChTrNBS3Ofie*uMX? z|EEYBhmQ7<@ia6aoj1>s0k-pV-(4q8RT^;RU+E5NdksI*JTXeCd2+j(u=eF_{8vb! z7UYrW;RxY#3=X!aB6^T#Mujb0F*2jG|5NL;^eS5<9TRh0N_st#oM2ni)LBysmwN*c z>A5{kU`U;}H6nWGS8=N=YB!L9Gp?o~?x4t)E`tl1`P+0h9=x5WhXdU}W{l_P3N~Mo z+Ys0x*E{7kYEnS}O7o{`zhhyeg(svRo<6Zj36g)5SoeV}FYGW1a3{DKl1txxeXd&{ zb5-=eSx=6jA|6zgIX(n(EpI{OB*jYcqxQA&PMI#fhL|wz&utshgK}z;&S_3?Pfi#T zhwgFvz=nV<5d`B;s@5m@kA6tC<gG5rIJcB8-xC07ZhtKb>m0N5OEX@qA;#{!P}vYV zG7ZA)q<$?zeB@}6^j(l3BTnlw`A_N>BgAYQI>|jtdxTS_f1HIKaf-I?g{Irew*zD# zvwM5w_Vr}=OU-^{di}iLxi^T1e0XHkKVi5wAxWY@h7G^>n_b-fR-;)m+G#_jfqu>j zy^I`;VnABEdQK*brIXj1d_k6@ns>}wD*0&h?}!@)2RFTAkW*T9=o_T^P|&ekuQGbZ zgr*^{SLvoOwex(kXwchvA8ah@D30NTmXr=EsBGf!MH|~VnV@6&6`~;>D5WC9%iX?` z4}U@$0)<=&^&zxJLsuQL(m6`YBvd0K;KE1vFJYYpKNx59g^URG&Oi3+NXJTd#l|<| z4o}W|vB-xfFXDRIB?SP7^?Z~vxiM(Dm@*Xaiin{#?0z1z_mrb};$i65aFfX3VGi@6 z+(n3!s#xFU+aHvcl=#w+8y#V5qkoTrA0=sdJrk+jAGEl+2M83;^0fYiTtdzn-G+5Q z@>_SBultrYpez|YdFp>N()8Jp)#I+fs?OhMD;vgQ|3nVN%pQf_Pgar?d&JnSs66zK z7eOudC8Ry=b=~0OwS6(*le+dcXoImjRhq<7jcg>5u`#sM)|>CIX}YTTMC6RmevNZ_ z)b=AO$1oCn?+fp*y+d^&NU)uWS`p9AL^)oxJYo(R>81`Z&ll+1io@It-by|luW-{m zD)$A80ucb%r)-fbZB=ZC78ObXk`vd+VYV;m<p+h4lrHjvR&^rV+(g;wi%Hc{*62^R zi!23$57TYi-y~t*z*YjmHKJKIlMb%}zVgiGiH=(_M;h_SYLK#Y<}<B>-!N_0ZkOf0 z*}$oYOpQhd9gEg#ZmFSgl3~O(W#ymtPg%)>a2Z)NHD<{D8|7{aLyiT*_Kpm$6UNv# zM6pVRVuI8k-7Xv!71Ynstd213z6s3e0NGYc8xO8mtCVjmd!9>{!#VD6vTaDtpwV8T z&;(zJ6I^JixM9LRp#3B8=v3T$hZTn%-F+HlI+{RG*k!8~rS5KD>=@~J!b2>D6`7c> zLfSg2&sDARjchh!!JE&$%;%8z^PSB7=U=USh=~KOsJh+%2&)S-c4?_zXSzA!7bCa} zJlpP(t06$PV)27-wt@Pa0E#ku9MU#RRj~OsNX*ft<8Hq(Jf^Os6~M%~2(pjZZgQg+ zY9%Y-{~Nht?UF>Py0^r{UREDa&fQvipEcHX4Jy@dH5}5W)+Qt=zywA-1^LVU0P)vG z4&0->e!Q?5KE@i<cMV8w4tqfvyMKppA1a#`X?k*TUh&2`e*HXHQz%qaFZnbno&{Sv zopd$1-&Mq45=1w-`});Mu%qA34XAwdky&~xLoQkd6g6SH%(Pd~UbRDhggT%E(?;}4 zW>H9ZCx$Fa5h`+`?7t0&A=ua7MmZI~Vrj|G386U79X)26{C*l0$`KrmoWdbqpcl`X zT#lJGewQ#R_eVGv2y>_@6^GSM+ZN=Hl~NBKNbwbD0sBlLP-=7DghDY!K?-&EZXo$~ z0N#M;R2P|S@1U+SB+Tud^8R{M)B9ov!}6Zug3?SMmYsUPTLebduWQ?RQ|(47`+y_6 zD~hp+KFN)M9BhI=tn?#RSJ)!`K4QPe392%O@;+|0rB`E&y*MF#HtQZ_5DE<liLS}Z zhY^Kt=c2yrzz1Ie+SbJ|=EjG7OWjeW9kd^3NZ?Lr2Sn~pERG}6y(0D#^W$Ww{LtBg zfP};2SEGqfxU~ffc~+(<M~BTbS=wV<R&};sUZdV}{^I-CB2D1m>8eTOKp7M}uh~#^ zJ+#7f<4R;xG0&Axj}3z)f2O~}ja%pZdXWAA8#eASEwR>Ge`Hxf-g9A_V34``;xXIJ zB}XFV!pCR-J{G`Va|ok->;B9TcT{*@Scnn|^N4&Vfq|fT?FH3pINJEH+J7gDuxwwW z*ePG$dpcSx+Wj)365n4W%{L!UkCr7dl4H70T57>MA`rfY&hi06Q@TI6?}IB(*&?>_ zZX)iIx$|a|X#ZNCU)_wgCOKDPw)lZ~vGgcEz_o1JBzOIucVfo2T*0{^hKNBU$k#*I z$6i4d$iPBr);wRkx6;Ml1sXlOdF(ayz1{tT{>YZ&mUN>^$t=7=;g_3*+SHz~uysLX zvE)}$0o1~)LR$k{G)zQXYp|qoepyd7G_icUJft}sF*V8Q0k^FL@ulC*@?#Z?Lvyz} z%ttA%7H?#K14i%A9fW6YisGH?8=@%{FOf~gGU(Bro?$Zgkd7c<!jc8wg8mQD4u9WK zTg6+sGvV#e8_zTpx}E`2s)qF{{>vwuL4jVr=B&x_*fJy<0cNhvJ@&8wXrP>e4}NIA z{#p79$Uxb3`_|V1;Vg>iayRbp^bz3?b&7Yn$q>|@U$HVd5t=A=U&$WWQ?Zd(01J>r zB>)L+Cyl*|YYC-h{1%tDe?^F5>FC<kJ?hHlUvPb@hVk9q5#mdiBlCC40m#_&xjWtF zn12~%7R}yz|DC}ddD^4yD~Wl@1>)`@bbP@K&?8tMhhl8)s>fs^TP`bu9A_qLP&x7g zg-<@}W*4zo6Ibe6iylSx-YN_Y=?rz*Dz6>-VtxLV0Fkw|S1nvz@Ivy<;FKRpumB=h zVa`63IlCotaFBCf(aS49iN>;2n?n3D%MLn=<|su)iwQ4QIwf5f`NkrXW}#>}Pkk2Z zLcdXg-hO!S?guKx&~k_jZP{QE9du$l&&+#6hyvHz+S6BuRwPxC=vsi>A_`P_O(=zB zlU*pnDq=)DIJFU`#ph(7b%*FjG=3pH5P+f6j$-kcLCE3hR0@7vGC_zOJ_f?sGp6qC z2@CA8m6I^xV5*3b_qK0#&+}B&WbH?K^oPDmM%iSQFk>FcYBS7r%ZgJ%vYcsL72=Ou z%FD{V<p~CBDN41g|HRkak^`(Msb&kyAfrzP^z{Y35>`&mXBi#a2u5lfxr5&|r34gz zqD6mF4}}C<Jv0)K9|IwYL>X%1oYp`)d!t319mC(k+_%48sXPvWRvb#hn(~-8-qQ?B zVd)B68L0m{IY5}h&CHC{Lc6>4_Rc1|x}&GUzU?r#M3kt$uGBY_kvVJpNeJZP(6dgi z6#Dos*>2c?r?$C72LNgA$3i)y6N_T?Luym5h`8?tCGRPvhzm|{s-*wD+&Xl#gSHr; zsQ`RL98CP5!Th@lB>z7qLv(Pe6Db(aLTuCj@${bIZ2tfIe~p;6imKYx7F9x3?bubd zDQX2(wfEkmMkiV|TD$fPwMUF-Ma?Q2d(;RbiJ2hA|LXhu`TdW>;czQ=T)AG)*Lj}L z$Jv+opnk;5$*1>8IkflSOSj}))lz2#{k)dk_Y5^m&nA7&P$AiFmP$U%#kT>bP>tHR zWj~TRo=jX$N8sDM=O+fnQRZ8FE+@ZDf@)9<$H{bLp_|OuoS91Gd)6u~&DSm*o<CaW zwQ)Mj9pVEw*bXw*@>(<f%6C8dU9-JmPb+JHAfJ+ILb@#RTw#noLt$A7;!8Y{51BT6 z(<n3VP>wwrP#P?~v@H;pbq3j%t7a;5QSp0YlIB}ZS5fJ?eQ-zziMn03zfQ1XXg<yQ z5F7Euc86tKF5h-6C^k}a5mrNe2=elymVogt>D#4`&ryZ<xmh!9$ulYloIx8oG8rjx zlD~WpP3Wq0dV-dK7582MeAmU1wDADAwkK^tofkwc^-VVx#Nx0P0#9Xn0z>99)N!YP z3231wfnV7l**e_6clh=%gqCL-XaKNYP3$DyQS8DE<zB5;a@%eOWa>fDQHFrFKpRWe zp(v?!lfFi=fF>HJUm=q_Lbr--r<Ao9mBpu1O1DEHL0YuZzXNiQ7DAMl-TxGKgey;` zjuF26u4z0U5;L6D^YXeE^RMH`eIob;DT+ht{fZf99&K#x?%5b2_^p1k(S<NxGi&$3 z7i?MR<Ko9_=j?qg_+hHX*Ew>Ki;NJ{>mMY}y^R1z6kf?|obmrhmU#3#e(s{;QI*Bg z>sIzn<fFCLJBs}=5sLO_!cO}ovH|MOhkI{c`rrS-N1e2OzeuWLQtRx*xmzJXSi(ym zFt>jDK#7gidZu=;a`C&)S8y32J8B1I%tPk!7^5E_l<rXa_$+TQ3JXOyTjct&vyU81 z?)i-D|DpYq7D(=dU+Nq(tszItB8yLzQU|*;2%_RKC&`nSk<nQpZ*Hm7XNcInQFrB& z7}Q>%lEzRjDnCznATfAXZ0S0qUy3z!kz(eq1cNTS$qT2qB8hBMgAjrVU1e!>rE18C zPfBlED5{~KgR;Ro1i8v;BPlT`P(xiZDNsWZss2Klg7i(vYmtm3NK#~adA8{HAyHLn zMDuElpY{5U+B{8hGW2Kr>zTb%Ix3G5Y^}9Qwz^l!J0jmPfEJ3q8~mS*;zdnpCQbNn zt<eFUbbpgF7<Zs$wgK)k*J@u|bu%YqE#kFpPpMjfC70eEUH(y~-k-6-aDD~<rv`5H z>|4ly;X0rodIBD8YZCC-{mYx{w<j3!$MOZK*Q$mDz>3Ojs|FvFjEZ8U&Tnqi<*`^e zwBC<*da%u@5K8_`N@%Ysqp;(2>BQ`r%iE&f{_OwoVf{zinMV=olpY9AJ87(SdVSJj zo_jSq_rU9Sq`3jGA3ul#7~oB_^)~7KbeMPH?pJRk2-}JVkN=NQ#80D;ePZw&ma&MD zSU$Gwo8sYLB7A3!6u-Wz0g;Uw=B1d9_Gbuuk(^MXP{{)xx2NhuQzA5v^u7Zjf|3Gm zwVu#PF(^~NZN1$>UfzL?%gJBbL1o-qL5?!gY17;x9KeKY|AH<iy}?McOil0@><d1i z9bx)iIoBi|&pbn46LugB!YM6r*XoYulGpe~W1^jaEgZV+hx?FY4ZYk2V<?Y&F{^u6 zOcS`YBr0T}yG23iGOTs}b7v?~%+pZbw<jbw7lsX~0T_Z2#Zb_hP5=jo-PQ$j6u2En ztd30%X8!T1?WGlfw(z_p-TP6VPFD(fS3)z9k$LQ^X6NaWzPWgik-Q%%$|rBU&A{A} z<x6RdI$-<fQj#Cuogy4BVB+>(D=2qBD6*p4AtKomHi{4Y#O4jzn@GP*)C$5T>l87f zK_^WSvQ!&v#83+`B`IJxjCPoBB*6Bxm-KMdU#!7jO=$n*yZKo!kcY?&)g>bpk-ybW zSO07o)pmvIZ1u=et^}1cWhqM2dp|vuCezF$vT)0#ofX#OpQFqFAL^p^^GbaV1ZoAI zQMk$X%}#wvfBVz9i&Cf5s}z6HCe&D!6H^uHn1flUSWxeoRT4dLTKsW80_53z99q97 z?SDoqbKHQH>DjQWROCJV<g`CyA2r}#@BL!6L9MDl^yN>TCV?%?Z{3@7_a{u0I<>hc zvbH)pl|5yZ0csZm`I(_Cetf)QP3ZDsMwYU2(68h>$FE&?F^FRej@@|jAn+@%N<i|s zbABb8gKo7j|2*Q9Nghc|B%cnV^4|m;v{})+WKMEJm#4fk&4GCC=cYUg@RT{0x|@a9 zo-Eo=pZOvUewiEn@V>YHyb6=-;5dM@l0#}r5U0i!X}JFuDbZdf-Nut=v<|Twf-8`% zoEyK3>AAo0?FW1?Zux+2g$NUCSl7b{b$Jmgi9oH2$BS(tl`NMR(QXrBTjGXVtr?{5 z$N|_9`8Ja9ki@)`(x%4~s~kcK8eG&qH!Kg5UCN$NcA{-5^L$Qw6z$k}c{^a_zyxO! zS^D%F3o6oxAH({N>#<OPkRq77JqtJ=u&1HH1^kd|n+!@uEY%UiYlip(xSDg$Z%~lu z2D2@D1L-Kd^GX>vN;9(2Eo?2sKE%+vR1_8RyR);@Kh$dr9AWj!<H0v&4|yQCehqzU z^qf_`HaW0cl0tLk#rs@S3-u6`cGFaYc0=qz=Htk?M&5mQ<ZEf4`vANc80Gt1+N%|d z?l)0vKG1J(kl3W|+stUDXeYM6p8j<8iZ;GZjI{scjrNr4Y2`mUS+baFX0+dUl>5cR z+y7_CBE%hhg-~9JygWC(Ek*55?Z_tacdW26C=BfiscH9(@eU6|F#TB*czzNSAf~)X zurX&pdib8CC)R0Z+p@N69c~c-fn`)GFVw8H`@gzq+C5==>nTjUY$^vcrO~ZC76I*4 zeB@o(YP<{cnh%+Y-}e~)FfT7es7O)r-Aww#Q6m~OXBLO8Yljw^YHU2m_tvT4G?H~} zslJE1g{chQskx*hJQ9=Rz_i$%7v^;byFg9g&0V9}k=B_59c+9wl;35g$?ugvz+umA z%|7Ln%ePP`VJK%y@UWU6EAgk3N0^ai+2wj8;zu&ro`|`sQpx&cvfb$LNl_bP$;DDT zvL1)Gf;cK84Ywj0eU+HY)wihlm#=$LGRjgD8BKI4#L!C%zS1=ma-o|syz(VPz`t2l zJ2dR(rCWfTgl^Rkmy2s&WFf$?Qs!TaDjQX{^1Y>LzA$LUWZa2`PgGU`BhDi4WtbVp zRyWUiHnEWUK-HeKnWxfH;_H=w?%knH)XttYF?(Ro!;s0(<#6M>*}haR-xK*4=Ly9@ z(p4x*gZZAQ%G$_d_L#U@zZ4J%h{h>!aW-$S3w7|jKT&pgFi{ANB(o3Dup08Q3~fqV zpq?#_N(oJ6c}+7y($UO)j@ZeSTCHGvEpaYkz<k?H(vtVl|HbRF_AFE=ue+&+&0}0T zEPr#&iT~}yd@b;b4}BM$HR3fn&{JxVY;)DfHZ-e7rZIR%eZV2p4j$Pt&Y^$4SmiA- z`q_86NLq_<V&M2fIuTp0(gN+$r#>_WH@B#!<k7EHlHix-*$#~Y%!o-C3xOv=z|Hy> zFUQEXkLD3CP?<OYXsWYTJ-ZXd6J0VRY-(%i^h}cjqxI(fpqaX4uiVA39R<D_f8Iml zq<tiVVjt^W@>1CWt8Nz0pkr+pGL(b?eM=hGq$)pR3akoLW|viVo9g?q19&T!8VYg0 zcu_m$uY+1D8FAvwmGpDlu6HRsZ>>BlUf{hu^E`Ld`e<IT9x8k;`Ae`sOMD6UfqtaD z+b7BU5<#(Qap`U*^)Pt*to8tZLD=8e;=6Mwt99w9bpSNp>|6f^*fBMFW|tJv5Y1WQ z4CE=FnO}rN0Q0e7elD9@I9O-&4*A)q3EKIHF#Vj~uC5z-mU?q$R~vpQUbu{rN5D0f z_HvOl#nFmB<UuCioe(R3=zpt!j$H5@I9($}*gT0}mG|bANm~Jgl`=Z}`^9#U4y2xg zvVGqc(qHWSdH3;4>)+Igd97}J#Pi>mubxlDW3+7zI@)OesMLC9AuOt;GI&WHjj4jV zmgloC-M<D3(kPH39<4wA=jyqg)-5=wUGKvHal3ia^hjYiK9%Kf?U>)~c!{3&Axq^^ zv&gQ&yW^IP4kACRNvB^{+bbt7Zib{s+NO{mP8A^={}<NV*3e+?RC4iZ4J>MQRLFe- zY?+-e?>;ffc>e)9pHdUty{o!ercjGY4kK$0I!!vso~R_>4;0I;GJ9MtS;MqaZHorH zz=Eq21k&F9G~eB0Hx&20PEY6)oeXjAzi<^>lQ-;zU#+wG;RaLC0Dn9iNsv929#!}l zQm7VP6;qyneuF<iI$yhgZki?9mpmk_gzY<cXI6c2p@7d8K;=u9)(rJJu20izY%!0k zWMsU#YF|cz5fvJ;61wcO?y-Xd?|3ei{60T{6)v9`e#v=Twcn*Rg}m>bfSydv#~Cl8 zK}X~GzM!+3eUe#35zZ{RAajKbmFu|@v7`gQs-tI03H5xL&k{uP^;TyLx3>iSh|u-y z84}Md5YG{J9?g~t4d|*9;hZX3U(#oR3gkB*`vlprz(hJ$rGUDV!Tptam9MzLF`XHy zrNJ+NOVnN3c(SLqZ+rx$8&F4QmrXrj?`ef0+j^sN3}uyH4ds}#w>U*aEYx;3;C_{m zI?zaUgA|<h$w{rE`AOB0U2J%fX2c7wlPVjLv1>_ZvjTj;7rjz-p&b;G1WXZClTrZ= zp}qd}YfqV*W@Voj#-Dw=<hTd@;f^`*Vj$Z!JJqBOv1N|S`C&^XBY2y};c^$C51*gD zy_oCz9cBr{YyUfTrk?-xI1z6&qX%13K+u!%W1`x&8mTH!gVp;hIdkd-ExeXr7RW4_ z7?dm0!lEDn9}>%!Pf8XG>3XZt#;BSydbCbVgvbO_JjRDPchPI^(8v(tqu0%A5|ARJ z|CIM|&8$6Gc));~gh|2~3D^-)XEF3LcjDGR3>s*N7ZKD5r6Qm$vB$6ohJhbm^`|Yq z=F?TerPjhZwZJlQziBSH{w~ayDtICC2knv|TOL`|TRvYpXTMMC0KcjGN^M#0`W1;$ z=z26r{3Cg(oEI4QHOOJ-)tIr}XlLN_(X9vSwfL8#n_b+GbE5t<TP|M<a2zH&M_e+D zDdu_y=dOJ6gE<TJ$&DLS!c`I(J@^G1z0grM$9>%1K?t%XO$hMvm^$w-$-gIEm`k0s zbFC}(0yUI&v1d@+{jQCJVrUoXY)CrtN~3ylJbNu)eO6CRD@L~6-`gNZLJ`M0W8Pe- zqLNEKkI*^uN+mam-%%0-Wu;h9=z_?PDL2}@Z!{~j9hJr@ujM52wR@Pv*?MMKLJ&Vh zeY_)Elt0CAJys1<3qTaIZo>!)rUnEkwyi99;qt}L<<M~ZquRaKjkuKaZwra>VKWW~ zlZW9<^j%61`5+?G*N$@!N`J`sk&jc3!W+39pVvfqyr<Rlk!LpxOMd0A4gB|~T>6h5 zO^pD=<2w$M^8;o+cKF9q+>f>1*lnYIo3x2zf#HkT_m2V^5)N;y+*0i$R`OMD58+)6 z9v8CqMa|J6D5p?EU*Q)2dz9?mpRH1iyr{buL+tAioCL+a_~GRgsu5YyU}ne|>P&j@ z9_^^^Yr+wkxI3vl!KN0%&Y-7d(}EkUx9RsN?BjmOkoz6F!IR)H7viHA%Ln?nU!elu znuBtDPh2K>e|@~=KNb~7e&Q>jBJv2ufQ}KrdM7S6$fSQAka;U;<^p_dtiN9a?KZeF z;>CpsXz^UzRT36#tq9{7S!hjZ(McBf{;Xq7rSJE_Vkr*(h<ZEmuCLS-Ku*rKiV1qU zss(JWTMGo$mdk$|M-SzqNAJtmW?6F4!o293BZWTmTaVY~G&dTTVc~sFue4R>VWAyV zCmm4ZuDGLerNMAX2A*>*UA<mN$!CjL_)r~FrXxUx0f$WkZO&tiGdgAs;rJqG0MvkP zIk+<i#JI8WdH&LPd|_A!oTJYv|AnM0*e+WtY_lU*wlwgLTJQ=&=4RZi#c+X==s^3O zU?L&_{N2E9WE;A(P-r{F*s7wut<!NS0;nm*ZMGJRnRu$XW;0C(#GI9N1{vBq$D&mu z)S9K1PIvR9hBqte&q{CW5^K>jvMAz1?mSDh&v?tGwVT;i%Wc-_|HbobdGR0&_~j>j z58_3=@$%6_`cq3|QwM^Tn~CTR*#+*0ociwfb3CGypId$91#Tp93|j<{J^2Lbgsk!I z|8tbzbyxW+9X~cNYHkW|y^nUA+k1nmnyYYfjE@f4JDC*xjgFsu(ap74w$~3rF<lme z3BM{WSF~&lPe&cnqq!(I25h|CP?f)y;o_N0@oSEuU*E6>&mYfI#vV$*eZ-=CSQ2Y! z7Id5fO?<pj($q(W`8Z-Cf^aXp#dj_b<_4_n>oglAbKEbD{}nM!I|l<g2pCE?$!seU zH)2oTpM58&oF!(jSS%s4^FjWAI?$59HR-d&U3yH_|EPt|-@295RX=nOH1sV)B!5_S zJ?4Q4ZUw&X*YSvReF8$D-c%a&8=^jZFlyw<(3!8HQKP@-yD2doncw@)FJbhTUAw-7 zQm^KvL(ZT|w-}2s>Uz72=F?b(7~4HQNeYdT&yficuFA}k$N-h^_v=-@vw0xmX*zj| z*vUfvQm)mp79sUtbzUB^n5XZS64D^fw&r*ELq{>yCaj&MjUY0tBDb`9#rnYh_D9jh z{vUkoYKIl6;ahRLks@lyVr7Q#Eh!GBPq7CsLchSx_0JSwrPf!JLF@oE%N*Zq)d(p> zEu}!V-&!io*~4+QQt}aJ5x^`K@(wz$yOaG+OP7+t*VhuOF`_GGn+g;mSc(|c9Xty@ zopnTXwh!!P=^l8D`fQjL2v%$TdwV=w$*qok2OKI>q?s9cQLko_Ufc?o`caPB$x5Rj zl!B~&`uFi{^#=Q-j@P7A65<5)k^kMS%;5apD!Zp(K+%LvQ4s!b+uh#0Yl5~t=jj_e zoy82e7y-e}q&xbUXZ^5$MUQb~C1IB9LyfcDNtSZRBxwCb^myp!h11}xaiv`2MjS~d ztWV8BM?a(YIB$6q@v0f~=W9Sy1bt@Z$Ufw>?5b^7w2k?1&gGoH($RD|sQu9LgmL=Q z@rdx5G^_fZ4z?y_ToSR)uWb~DVX2&&e3>ldA1dS>o*e7laS4JIO|IyMBY|Mj6^}5G zyIL|ZdQ@6dSUct>#*|K6CQ^7ny^r6Dz7_bAJ<)qsa@&p<JCVymS0zHZFoF1ylf(Wu z82^Yj!74~?H2Vq3k@qiinMJ_cw#!?@$=TCOvXwO}a!U_**RGY#w#Hzh6()^pK<k+f zSDnWSursQ`i~c$M*6qO`m%P+A-{Iodb;PkB^s>9N-%xbGz}OLB4!_O(D^VZkGHkIZ zhpcR;C=HB?*qHDfz)aL7oE7tT`g@NONw$>vM~?Be1_ReAC+uaH;k=$qsWw@UyFRq~ zdNDc$+s^Xo=RA)et$ej*Ac-MkJ%+$5k7;*&_9VAI+XVfxt*ndYw1i+V+YM%g?{fGX zK8i?$L;+>%|E{d|7`>KXPnaKgyL+rfI5~BV)>J85V!?kM_ZFJ^@ZIf8kjB~FNG@Y= zMWc4oc5JQ1ipM5#xf!^>KJOJ%y~cGY9OMU>)&Gs43J1kc9wM#EAzvAenKv=;MomcA z7pk6s{j6*YpQGL#@-3g<a{Bp|1phSz##tr2WOP}vqelD}J_r~pHXjy*Za=Qb)whxT z$Z>3@AMH7RJYdV0zyXEP#vigThvoT&J^5rl84{Mle=hL20Djxw7e>DlAn+6>-=&p? z(V-@WN9i219k0~2Gu=npybjhPUdwh1{+ue&(e_J;34DhVS8yrxHLuMQUB(1MKJPan ztjLlMp|B@XBawH<9DCLQQXEp4qrc_}gq4@v!a%YJNE-cqDWHd-vY(O3_PB^g!(CyG z1}~Kc@0UiSgJbei6_B=63+OOK3jh6ssgSUj5#4FoWD8EYGO;IFFTTKg2#wrp*Yh>A zuI^l=|E`k!=~|2WJVGoVw*>Vh3rmH+2dgSoi0}Ft+E%89gT}lL$&sbgez4Gq5#2)G zzqI;dJ%U@2`V=yImwD{?NRLzkoX33{SsTDvz+Kq*7Y>B8s9U68GVxUnr^?U0?XyWh zoS%j-%G_pGZR7Zz5qth!Pbu@u4zQ+<g&yT9{3I%LCt?LfL4-f_8|vu8B4BT&u4H6d z=}tCKKaVXj_ytX?EoC@!4W7&Bt&I$x^0C#L|8N#!mhEM>b6MwhFtlp*rzFlm7{kJ9 zgpuo+V#DRflYh|7tfujyVyBu9yC?8p&-gvh8JbYc{jC%tMXQ0(+B>$qhKzt@FU88- z1@Wkv)y1J8aI)8!7v+j_RHc)0o3@KSz%bfBvh~#kuw}$L0UFjFEvB>GixUHE#(z3l z+~ijc8h#o%=(X{MhNHu_RVSqZ+I$-wpFhGPwh?Xe;<>7b1Eb~1_{EodCP?~v1;M}j zvG_l)R<H>>0=B=H=_VLhNOOe9p!rUIB}au}liWXq#8?NtR=XROVwBF4ak~Y&a$ngd z5|NekG+#S00VyLb%uQK9j|q4G^gi~&v`&bl0`27Q8XN4)(tg&;Wn?Y;T`T{q$|F9| z8jhHuKf@_9<=A!*Eoxmrk-ZevE3jm#KLuVMjZi#P#sU}={oHR%6mPlLl`dV~B&T*2 zE5!}z|3JaZ8BBBL1F-TY^cf#!OGX72=sW$E1FzF{9)c$tLa!1|jfJ){@?oaP$=>{P zGGxe=VCa0m{Sq$@O;ctiH)7-)LyBAy5b`c<Q&Cq^d8j7xoERk)s^9H-CkfZ)Jz+p! z9xNU{O6NqF6NBFY{y-lzd>pMh%ChfXzpxDmBqIF^+QH33#g$vpc^}K&ghBY~8&E9w z?D!l0g+)QQ+D@(xD)ny=_3y9il|W>2bPV2Vdry!wZI2u`rI|ts(9Z-kA)E#!{(ecF z@->83{v0hr8Jvu_h_tIeWqTd|80b~Z<Jyx}OF<U^8p&Jj(CA#YjN13pcj%oP?p~g* zI^n}`P-@h+*Aa8leKwMCeC@^!z$9Zu#?nHcDygZ{SbXi@OUix{SZaxrR?B8Zm7aFI z>u4m~g(b8(G?&&t#FpSR7A)=Mk}Ugw-7I2?|69NeFF%#17$^{b4x=AYI8Yc$7Bqy> zW3*@|F^u?fg$3HCfRu$QKt}$Pc2Y)<DNHzHDX0$<QB2+l3M8r#%9y*6KMp0!0tMWY z-(Y-~!{#^)I&I`z(6Nr{RIc(}BhcH$)I+~s05O#krBOVbbN<<4W@6W{<l*fdagGqi z{+0yJrQ71=a^?em-S&)<^!}L+*JZmQFQW0~NMPI7G3*WR4mnF=fBd0&^r-9)P(E<E zE;DG+;bE|xm=Aa8;%g|Zv|hVX{PH)$TrV*?6DU|-VQ*7;tVRt$Kt?DsTDs-z(&N}# zKGL6JwP)AOYMG|Ow%>MNu(w=mC=Z1<y(KW4b073R;8OJ%dnhhEN-P~YR;)O6|Hh#~ zoICW8xm7qHU=uXga+OPNGr06sZ_AEx2H_RkL<6uU9*_S0eEgZ}!;r4^F7BnA`F+3H zAF*`Ve&O3E3M=OiaiJH3WFhAz){rYfiTdr{?VbvEaEjOg!J49ah-&5AlQM!A{4aF$ z4w`Xmw(x6d&BYbUA7_%ZhqPJ2-_1Lxit80rk1TG1eb$0Y13hz8M+iToTW<d(-qaAR z;Y61EgwZ%2w7r+4RDDY7bP?s3Qj48?zsI1#9O%bXYvwoit@dGN-1F2K(g};#47`&I z-=U&X-N!i?)MS0q90<pD#~TDH%nP|4>)gSNDeHTz)O~pO1Q>Eu`_a1gzfoyVDMS8^ z$+g4NNl6~<_7%o`Plw&5$u5MEM59d)*lYyP`+$pvhv9!J0J$zd{AuJtivMKJFC`bf zOsD~JB6>eOJU}%xD!fhdw5*^>EhcpQxGmi?(;7%G#`m^SmC!B2Jm0}^%y`h6%W|;S z+<AYoEyo%Q-B(N!#%J=wJlZ;7E&%#P!8DFlt`5d=TZ>&a!t%S9>zYTlUl8wTgWnar zgdVl?m{ATWa<Dn<upGp;W#XBW=rH$%zGzaCkvzd%PCeBj45(0f8g=?axVA>N8q-<% z5>x&U<b~)xs-HPrXq{6?PfXg<x%(knzUIa8wTZ;7Tj-AS=HQ?4>9MZuJ6`4U&7JHA z7x&cI8nS)ADv6D}eRJS4@OrYvxp{$8Nx93)YH5WOGtp>>efB8377nTDcO`a-;0z@4 zvzKNFb01m=@9&77a|U%i7l*8zpOD0p%h75(BUmg#k~b(fNH&>H=;-ux2r#cdMw$Ff z<Qz-Z`l0mM)Kw7t!BgGV@p@PNJ0Zg)H&zHd0rLf6@U}fHIFw3H_%K1yYKU_5XYluW zA<H$dig#BoZ*-DEJ-S{eDI~f1w#^Q+>bDQ8n&_$ruDAcUo!Z~xK{SlCN{N?7936Be zd%4pCUDbb{&&4yPHl<gaExzcTIUacC3Onum=4)FGT8YTR)L1A?^PCk-?^u4aB}_3q z|0;R4>7-YUnLFydZ!>D*Earc64C0Fb>y6>>R%O-)@_)<~Z*-<LWwog&^0JHw+ecQW zcN!tO%M6ydrTbQThg}i7J1rcMSqaS+Jln~4kW};&nAt=BKcM~A=-D_xQ!SpACu;>T z1pcd(?Iqs2O!3>20DX<ELaXttfLZBokc|S=)0}6z5V5Otr>JXzR`IL<X%f9il=XDy zv<>QpnPhRalKA5XefZJAO15tFE*c3;I@UYz@4!SWX5GLM13MP%qyo4DQF|iZABe#; zN78(I*X%MK8K>O9=);1@AvW)5PN8d~#lsn`x=gZp7mf9EeaSI{*{e5qE;ISEwICd8 zqFpPAA;UI{AkuB7X)WvbTuaxX>uSX|x_-jW?H=-XKPa>`cS8jP$fVIXk)KILS(iAc zoQ@ORRJsZwPE?<aWGaQCGeV3bK&KpYBgANAi@FVccpr}<`CNhLYN%aO2;-%&O$oh# z9*R|<+3>0F$NdS~Et6(tpEZNJ9C?Ar$lRt@<|sK?aFB`2$g+|c_wre!i2}IFsSEy& zqfzLZVRHKp@4%=@vK$^*w{0T@>+Z^cweT&uZBO6N_O10&Mwp1lG2tWLMD{(os_^N| z0g8v$<<VM*L6ml;?fU?;{}^7E3+l}UpXprBD!Cpim@8D6tDUNA_fD$y+m+>aoV$uM zuiew~xKR`{X|>aMj=jk!8A19|kUa(>1G1M%?rjJsV_$`^{#iPU66IGLsrHNV+~eR2 zIAd&!GCMibz4{AywHTk%99g~rh8W3zO(o#X-(AxoTK`X5nRNdobsWep``pdCCQJIg z*+mOb5ZwFDhBs7GZfETSgELdfUy@=bRIEck&%w|1RSx4Lt;)bia`l|q0RDHd@tc>x z;~3C9^jgwen12bQa_1k=hW1VkH#Co3A2W%~RVcl!Xa)_2u8UT<lU81ntmKEor~^%C zWf*Rr6pV)h0ItzNz!=o@RJg(MZ5`eC=E#A=Qv4}O|9*C&`>T-Txn+f~)|Zw*xPsL1 z4L1D#wCKRkFaUE;o*){2>Du`X+n1B4dXRW^n8Dc(<yOw^#m3}asU?oPd)&W(CHU_1 zFSRZH*5C^Om+~Xt26eiiS3Mk;v|aK|&%1AlB!cma9(~hQkaGHfQHtV3AR;G}JQ9!F zhz@bi#h>eh)nw)ktCysQM3J%ARq@`k75+drzQs%(!zlKmKT49{y1{pHUdQkGP2lmd z-r<!i4aeWiTg<8>W##+zv=8s!U!g=Ralismn}~AAs6lgJ2U|7?<M%T}i1~Zia=5TH z9<;npPE<TC^L8zr;-i}h;4dTEHX-)Q<QhnU*EkN-C*xLUUi9o{>b8P}nx<LcGeV72 zimeazc8Ub^I9~j98mc{S-wvzT<VKad{-&*L+v)0*uw$+S%7z-hJl$WrTK%^<`H$Z~ zSmoJj%fHKzyW?uB2u-ZS#+i$Q<Lh#^<Ajb;PmYqJ0aQ7UyQk>m)$>%66HlI&LSx=1 zP%CgSss97Wappk48vpKP!ax5Qs@zEukF9OpenNK6UqE^o!8Z8tlbcibSjo95Of{lU z^fC%vXxjf-E2EHcZ|pjYt(ojgnY@f78X=6|!{j&n@D!!HDA_4K`I-!`5hE5}2E<`- zv^Sh>C>=pG%*3yJPIway;6A6$&P7nM;|LM>r#hfX!8=M=gUGmD;_ZxLrw+nW;yqCJ zz5;;bcJDVta$-d-kR>5N6!CF+a;kpNhaPSI(VKH*IS<7ChIEGAl6R;NITD)dR+Lar z7O_j`l<!vD*QLmib5I7=c*g|AoXzza*?keYFM-~2RUZG|E%zdm@wd-pU=DM8#)T=d z?vcp%2M15-wz{-5WQ38N8D0HnhiX$rK;5nHE<MEp+5tiVUFA)pK(@Z+Q{C%n25)I` z9AWvsTo^9aN6RCmws@B$lXkCp8}ckauv1R74)M<<pA^|*xRfPJcIGSaeDq@Ex1Y;n z`sI*~9iY|>mCUA(burX8V)1Of#2;{RNKd8~)6Q`qG{VwpJ(Z#}R^Pp>wD=(H%w-H( zK`MOK6{I^#ry3#dUpkfG`?b(&d-P6(2CM~NuNEE7H%a?3Z0?ZQw%@nufSJe{TlrEO zS>1>DnTgn)gpk6IZ(|O&tv4wrg@yW!%fv^*hS!9OZ@7Oyvg*A3Zx7_&IZGgi%SzT; ze)k`BCx5iK$IZ>VltdB&c+IPDkT-w)U)VhLh{|~6L4!!xYh{a(z^xenGY`d%Kb!n} zU>;sYw0$!|Y+?HzBkinq_cIqj*l*G=l4Wto(cq!IDpZhL{2G2A1JcGy_G%}7hfy~e z*bF*Nj={Hzcu|OI1te0lEg+LgI_;v-r4jlBne!Q>zuQZRIXt;`%bLizr!AlY>qCjh zo%Ycp3kMKnE06OP4cfgs>N~_on3`AAGI2b!g*U>%8l$~pIaBIRME&LM1#mc1&R=*m zWX_gh5tUl5tJ(PZE2zPF%m@D&3oPM|HD7QX0@Z@b%chXr#FybVcT08<&bHz}mF>X` z7>;Xu2zp*A-(`LQc26wXgqlL1hBZ1<6sst7)%bhMbZe$RrHasqD0{I)6puoOD9DTk zdCf^VLUOchMlaifyAOxT0HkykL6Vw#^^!<!hD%8dmrV$XwA802y8zVZ-Yil<$+c!6 z4sQmz2gUk<{ZYrZ7@kSE%7RX5yMDhui@|!_diiW#+fjH3PL$xZN`5@_!$CM6v({Br zmU#J*N2DU->HPjt!))GFM!cc^O~=O2$2Ki(1^9vZT~pQYi<SpmvMkOCNr_n?bm8qs z2mMY?4|duVb3!#oo6>aIxXhH7S^L^^S+_*E0E*+c*MN-*Ec5;+%uLA_?FEEd36O6z zsxRm?^H#E#!B9jh3yB9U9r2U(P_=!dMe~0Wu9*BBM;z_ZzQNh1@_B03|I3t}ymHG^ z)+k#XG7Iu{uO4%%a(^FrEPVY#uFpWdcIJGzf97~tR7abn5*y>H-lkN<<`{*sG0x*k zX`i%es0DO#AI?nD4q6zG_wzd^zWy>EYDUu+5qjoh;}ZzW<CESVjbAVtQ`S%o*_iRM zDIztq7lb~c8Liyi_@W;69e-!pm^Hh(){`{*<`U!~ODd@z9TjCxGw+c9(zH$i2GR&e z=5Vkx?n^RPwoE0dwC=cDKI%+G$VJe$bmO;g>~LPZyB7Q<YUs+8%(f$rg2WM=7P6#$ zHTY8I8o7>2pXQ~`zd9q)XH$_qoJ*0BeGDoYpBSgOwqFuTRk8%L$s>ozVSs|~SaT__ z96f<m0m?L&>`CgR%ke2TE(Bk{>37?lC6kSgVNb^Gl&MNgb-A9dKfG6KzJGN5hJu^Y znBd2}9YG*<P=zCOwm}O<w!R!?tXmx?w`#u!{fxeqk$dY(dXG4I)^$N{pxJux{m)k- zJj<6wUbl}ZGzhK66636oaunJ#5QOh?U5T-TqT9}>_}-91Mf?&}8D>tiocg6V%nVpy z_@ox-ZcH<-UJy1~EXa^9bhKhfmwtwzu%W?`IBtK6@Qv!4p+8~c({I5JHbV-G^LEM% z-aV%n!Ms0wmp#;4zDfImaa%77w3d3VaoTcxJuUguVZal<`;yYGvAS_A|E@d#e(u9< z-B+{JejokNXZ}MtdpfmsXm(vn*Ld_0uV_rfBu-Ca{UWLxZ!@$Do#g@hiTV%!wYy|n zov%dgccK0Vg|O#(_GiOyFpzZZ_jJiU(y%4}FCG?5%jTEwK2g~_-^i356@`^@$aae& zmKiznn{BFGQW)pGl_z1CiNDpQU6GNMvM@O%>=I;zXRMM~$a^CW#Q;b)JA?6sp}F-n ztXD|b6CYdNa@LPpF%IG42Y<wEA&LO1989@!ry|^4EPnIDTLW|MEld*DWoZJp!qkfg zjbIl-<`r5J)q=52v(D^fI{JW9TiGa@IMtXqwRRk3R!#&7vB00M3UTm*cd4D1u4K57 zDRtHfMSqV(uyHF&1}x@rgGk`njBUYg$A!P-b}irUd6xn1aBq`~tUfmQ;rwRKL#<#N z**$Z-snn`Ab6+02z}oRewwEl^nAC~GnfMNQqAc~|S!tO3Vs4h!k5kse2)l$RglK-r zL|$2YjNqvWBgJ@l1}Fczl{vVDkoHTEV?DH#aEezh)DqWa0<7svk$J2iiNMyv7SD`F ztq0r$IBSDPN3+BM&R2&%XxTB^M}ONS{$-R%{^-iFlYWaQol_8n|J-gFb3+yatJD=# zflg$^3AkW`k8ce<;a(z<vR%7mr2FcXJ4R9`LI((O%Gxk$*`ADJt}}PZ_oU&cqf7Vr zLchy81j~+nzjCts==R-FpWpPAwsy7iPnEUqepZ>&Us-JYdaLnY*0n#_c~Eer0o(KG zZbuqPdx~(jFZ`0y-eIw^8A@8H3jFM`NqW9Es`pQ+p%x?$vcLDt^0(`M!j10to-n6h z(>)=xbXX}X^w^r^d?J=sx!#c>7Ne*Xs=1jg<eaA$yXVvEVRBaX6qXmP(h5wqg)^4I zG%$rB;IgyZ<cef46$o!P`>IFsBMaUh7^I)bf*It*h4s;Ln>0VM?<*D-8xZWOF_G=e zV8lbB<R9TbvDONSqah2%-3z|4f!3Xs2!cMpH*u3D{sgN6bZ_I}z3nwTF!~vvSVB5b z7j@qwf2E0Gp<q6bPcAWtkM9Um__!m4^R5C}z$|UjY(utS_}eCWnOrpSE55@i3X*)H zW>bi}#JdhzxFqiL$sjt+S_vlzSOD#lV%gN|A=xyU4q%ot@MQZIsasp$=Xy&LNseYK zbf%%Fufx8JJoN532x=m<*%mq+jl^oz=%I;5+vjajgez~Ysb&Z_#FiABzpZYeF4fmi zy$C-W4~%lSA0GC$)oy_-tU9EJn~W6Ie34Qb13xt-(fu-RF4Kx>g7<ckf9L+o{Oj45 z&-uCcI1IM4XG$MEie5vAC~>qQ0hdz14xBw@lD~3JcmpCAQKo8`T^s=IJ@7*{=Gb+z zwPi5whJ<i(EDXo{wR3zcU5yO_3ozx(>Hvns{Y6hB8`+dU>DP`hXCY9D#fn277d`UD z0)O4a^Vj1outnEE6~6ld04flsbvLCfmGKlZ9v*SOXMaE<RIPeE<J`T<-{A4g(kJCp z(!|n1mA`JoXOnO)={gHA>}qT+3;xHRv;}bPP4#=(q`u#Ju6UEiD&Vq+?g=k^OoI@F zxgM!AGb$by2{V8nUORuU?PcutIw-i6zJ0AzEXw7XSXX6<aRb*3EO<q{o_6I;Y4J>) zWMU5BQE1%sZyvJKNg=D`uM)bUdo?Zx`8a+8?(wmUARbYXW!gCzOuc2~pBR@ypN4wj z{=lXEkk5Hm5Fu*w?(o&#wcJkC&L&5Bf7{Lb#f7Hs8EQe-$GP4QC3|wOJdEKA6|Ws0 zw*|*k6o#&sBz$|OP)RcxaSjhwp#94fzYj1~U!<x%t$7)F%hXgg)L8agDLWF-+*eK9 z(P}{Iq^%TanY1o4U^S7S$si}{YOaz4#n-J@QNGJZzHaSjHur?wiD)DMp<H*pJ9k?c z=_urn8}mc@Y42Vc)Sy2l^lqD<jDQZJD$*yXLxSH@43X7u@z+N$tBX(0=m>{1UZf-Q zaR<<IF?C6XWn+4w)8b3u2Hpv<bn&PS3^vJE2G56@5i4&U&HJslhpk^-a`Ai)E)$xx zH6HIK9_#2*B+B(){$&pyZvl~g>SC_deMtWNAiGvklzZB5Ii#~XCtr~^d(On%puo<i zeLqz#I+uPt4_q^tEg>Heksw03&v_h6g`dOr64i(jkVQ3Plz2G&7LNBojWCsy0UE(1 z>}8Oh#`4;*=A(G#16VxQaWB_9g*;kD-c2T&=PaVOlsdA7%jig9tPoLZmiHnp2Ij|A zo&y=sH7TjeaM;ZCmHbDY->S-ZaOqy&|9954J9eZ$@}W~Wh3hVyUh<qvYt=8}X$hKh ze_N!ELpDCYwRka<?w<Fsv$y{!An~wOA-StZ`4iRMcgh_caX+1Zs@NqeZ5KoS%~jRv zO%>>mvf`T_oDNO2_?vCZ@5|tQ_$P-xe;zBBYO*%rRY!L17qa3u4*eOg3qAZLyfI1z zJOJ4|L5dxN0nA#P!pgGe*8Mi@H5r=~bOVEt1>$yqI(FdQZu1sdTF>f^W}KVgUJB4; z<~v_76?RU}ei?REw$7YqPS9K*xHk8m3kQq7edA%GoybvZa_VsmBD(`bH0Q?V4(0Fs zW;I2;cQKN0&Oo^Gd2Yw;`v_EdU2QRsCqa0lA~fQ1g(3q+nYtpvc}X&@fulU#)YeE% zyPwd3_}MM7HlTdimsa)%r#MA|&OtQ2brC(`6?`1R@LbpL`VlB2n5m_o{qoMO(X!cS zaiC_cmjJM4-9$LOpJ3M(mLiYlI-QgQ*UDp7hWw_}UXqC`^gs@Nb>CW_VhWVJsN{8s z5vk>yF}eFPG(j_fep{{<?RW-Z-W{b_Ge~iY=?W279G%^Hr|_3&t^RBEG3E=tN1vaY zDH*AG_Q{LX+MShuxEAZh(}4bMq~wdeQ{8}SN_~|z6C1tLnQZOis4Cm$eI$e9UU@v( zd=)=|8)t0|cT9u!40acOp*Gphl`Uye2w#-=92EQ{tGm*m=>7O2X5b=Aa`X?oeWW76 z@21u6xHYxNP+zvV^OY+TvptsYZ+r#H4sNktcT-+2e(ChOwpGyd|E6&J`aZYwjQo!_ z;tHQYwF*S61N>Ra)p{Nr=I2b0>{;|Q;Z|J)?r2{86<?!7PnF-XmvuzHxp2r|`q*0a zMB7*iM%(GxqW=x_u{ZbB+HXk+CNpKMHa^(ce`Z57Z&MolxWG5fhldy;uT>1Lq-|9) zX$+={N9Sx~P|aG_w&I3mbd(B>Bp<m)wk8n(nz{YDfx;^xMI3O+8mz>QDx?Ly^=qt< zuMSg<crww&1isvbMi56f&FNc%Cwr6_Yu<{0_MqLlQ><wRuFX-c>B+@vPjUM;IFxD! zRCbPMX%)Ah2T}_pvc4oV@y~k*Nyy+ja$V)f!d5A_X3mC3_t8S0T|n)PP>@YF-y|ij zPtFNkfBB}hJxl*KYL4o8`13`prRE?f<*_b{XyrPYogPK*wOdJKHUNxiNJh3XF{(G+ zQVBZXukJ)JX0!_M2IGOIiXCQ9(9jO4ZiY8P9<r)4(wmDRDwg7?avPM_?2m9!&7}_O zXrs}J3s7lv-fq4;?G`WYxw7|rc@1D&pclFaqLeINQVbZ`NZ_SyT~Yw!fBPtb+D7c> z6)J`PC~R>BF@+!rRo?QWbF2@PlM&@gLB=v^9;sed_-#+RQo=p!mB0Ip*yRul0bODe z&SJTYSAL)LI=P5uF(d5iX`A|_k<#|;7VBHM<sutHif^f4ZonAb8c^OlHK-|?Dt>7~ za2&rcHxeKk(Z_h@Th;ya;V;p;4=46LH7QTIlsnU5NB_N#`h#_+Lb2W*X2MD52>no* zS@*92TW4Xj?q+(~v#9p);ij_0Cl!yU)Xw%Ti9WIXl)ZeaDM?TMdthRu*#dr4wski4 zLVHO$EyD>Dy)Boo<cG~v>W=X{O{o_A;lXOr{u$g)K(f+JW$kgaVlcbK5%_m~a&OEX zgf)vlyoFtla_bIp8TMJA|5?wUeY=zpdj9u3^hv==14lxms~YL9chMi!&>77Rqg`9@ zhd*gDF4*kB$`O1u;zOI_qQWmNRk=^d!pAMe-pa~dN_J7!tW8=!B5m_boeo==r_i&n z{nGP%eVj%%mF^4_`#(*l$=O?ZqaI<w*ybHQ8ozI`eBUG1pL8VpY&FD^`fFZh26}n4 z{1${Ny%jlWK0B#1OH10n`bTW<GrJmwP4>I}dJM0KlHC`2PgS)}wq<%qa~_#ZsDBJ6 z?_cT10-^NE#})GdpGB$hhKmIhx?^8KcgGw#Upc1&RgZ&_hElrqOtO8q(xY`+@Be{* zLmr7tX&vP%k#+PIDl&E;IkKq<zA5{5i;i#hyIDwbEE2uYbk#;@IrORV5--h+hcV4; z>fG@H52_~nG1;kk(I>>tcOD}Bl?K)l02bmRU<jj|4)Y|PeW{(Np9qWhR>HD2W!WkC z&RPg~mwv-?-1&qEFgXx9J}l-}EX;nyx7v}*78LfN??&}K#d+q1fn4>oP2LRmufe)M z$RZhPdlBXIJ?(;d8C(if!g(Q;S=aQN`pxfso?@pwE`AKWe>k0J5Phsa@4Xa@r`Zfz zzh(<;&qOY6idony#J3d8Ys<lu;9`o59C0}(cP}u;_kp@|3DwLvOp8^7;E(@qe(mdk zTDuh*a=0*ZI6L#;_?O#nsQF_j#J(2olu&hZ+odj%Q=bJoozjDfm&djKtEi+A1MyG1 zokIem+yi<Jr;!3`rJc5NS^=2sCQ}hRWm<o0dhMLr)-~S^&;=Gz&<->dl6#qKk2kIu zX};o9_!((UuO%Z}Aw#>hLbj{rNHSwF6$qQJQ}Xvk0i>mjESLy3Zf3#nT-^Mk&gu)0 z9WDieg3I3*zJe;SNzFOY^Yqj3d}X!?<R>+nmAGN^rzP}+D;%wtZf<#oU1_n4DqOH# zYL@vN1(yF7eZr*(!(}ICNQRRa=^J`VSO?rP4sfQXX!75KZ8Obem-EO_j0(MSG8`0} z)!L+iZ3e{>m%-kj#kWJ$Z4G%0`6}Heobu1558040dHZarm!X-|ExfXoo@n_cnnbzF z+kT8V<zhYh4K@G^&1?g=^z%f;Q-qoQiwV1Edg}{30fV;wF#*@lJ0^Z);fd(5(xa-B zY(PW(3)6dh5EmP;sDF}k(P&ll(KHT6xyJQJ+j5o=@NtrR2~*@iGglem6d4F^2@-1U zj06PULw>TuqTP7bIz5!0{D(r-d5MFgt&-V4voYmer_HDXyDJS&pPzB8!e4Y)B&B!c z(E)uG+GcQX+di(?+7n`O&PA~`WyWmAlbLaiesH@7hP3F}94~<jOZ(Vt0rb)^n`IMG zZ0ufz-xDIHFFuF!nltxZkNjV4FCstVa(xBHJn(Qe*7mrep7$`TR*7;4fb7mW_p}EU z@tAM$vfumVY<k#a!*gdiy7{+RUWzPGt0ObkR3bSya;=MvnQq{0v4vR?9k!z8jA<?$ zIIRAX->Taj6h|OGT0a_$2R#`XbR|0T`+HqRvTYKhDo1v2dt1W#V4@@Y9zqi+@xJ?` zb*>ypQv5}yk_`A#zw4U0jmj9Kl+<WYS83ic;X}xFa<CpBS?Ax-5sJaNKK3Q@yn34K z^~*N3PFT+L7-UEu1pp9Ox#G<<3VifH?%(^hLxp!K1`nQ+ABsYaWhe&yH)D@);b)Hd zZS%Z&3{;l`BVO|=nKMzz4vXlMi3#18(b)D|W1#?Aa485n;vdOSDZj~T9A1N#^q@<s zhA;`F*v@=AA>0m{lW6tXo_B(0XoqWwQM%NVI_Vyg#n<Twt}-ZxY__4_AHe_|`M(?b z#xz6l!ZwbNPVe=%p_#b{Ip%b~vYLF<P9z{;72?QF>!k?WHF*<1VAkJ!rmQK?&-Oj* z&98ZdA8sh{rxEPr`K^GF6+PCEB?Rt+vnGokKWPzMo4XCtYWhx})r)s%QzhjU0=Cj| z&es67>C&>Bv}dLBApHh;8upP}Jl+I>>+ZKssin_zimheu>U!PV!0-O&sq;6Y5vKu+ z@8?x<8_u8ZSdyLC7W%wycJt5Q5iyC}4@3(4>K3md^vlzaPvjEHx#HsI#58YiC)mFR z;IKXc*@DKG|DA7!0=LrDrubKT_txRE$vRGmQHE*x;M@(pyBW?P{8JzREfWv4+<Xpo z?qYAnWQ|IxZ&hl0L&3>+nPW-8h|>~Pxp+17y{I!a-#kwn7cU3|+|gNZ<A6X?2&Q(z z-_LE&oyeJ4v1B+|fh+`ybs8H&<;&D33zYngy+E6L%UX?rtaKA5K}GS)G_5;|-oEDI z)|e5Kg8lZOXTVuBS*Uh^%bCrgj$B^F=gj#z0jkS;9Lxtr!dPnP>vFI!qt`wuv<vAo z<KicEfKraFhgUz7ljJ-CC}m4MoA6>OLlLB~lT^^Q9)Sg#nMgd&7K;8P>L24G6f7OH z(>nbcKK)r~ZgFlzZ+JIi@4QHas@c&NEf{w7paW8lqmFnV`GhB?{NhL<xu`U1(KiJ- zVIsU>#N>N@VqURi<Pv($>Im}UbHLi7ZzG$Le2trsFrK5sgr$SD-=PAxl7$0h&`MR! z4c?JJhUaJ}n4H}{Jd>9rS8ulyUtFt1o4p7JddeCT(P<%NbhC{*T9y-Oc%j@1-5d?g ztpP_~w9RG8Wg>C7q|RW7im>)VbF|)HV^QI!hT*=Nz&uAT?-UZ2T_uqFJ~R57Qx9+D zU31RfnjfU!BX?t-mQ4SrLZ|r5q+j#$lGaGMwaxYiaY;KnG)ODLD_mIt>N@U`Dk?Vm z-p2Ced=}2X{p2+JxiVf#=!f9D#dnnU;i11@03Y!nuBl_dUG&+phPk~G=pySZ#!2Q) z>g}AA&8xX1D`TAFw9l^ybWBH|RA#*8covqpY_@#Llbi!pGU{lRfXf(e)VM)c4<kiI z`-llWYQ&zyZH$-OH>0j?JE{g^TP>vcjyqoiu(Z(+Z7M8do<PmUQmy5zDl|5&&gRvm zy#u(YBoj|<)h$KfJ$k829x|48z=<01AFJ_qI0+M+4M+e)9ms23Gv9FGc?z<Xz9mU? z=#qJ6F=(z^l0eR4KFzdsJ>b(>H@xE^b*6m+;|{rjFSWO^(hssFmMc(-_G|?p4|`k? zLBFxah}&X;uE?;ldJ=deO~U=hyF33X$@;FPrx=Uhly%~0x#T~27a$}=Uh!Ra;Fus| zyvGzia^J)bCxfzL2%Lfbz4{cg+wRGIQDD62@LDKF&{cb$af?gbPvMtif?zlI7Yn-? z+PVE(G{wDbB5^C_l`pM-Exdg5vRx!@`}3fm_z+GGuzO{zor=;h?^u78dUlB*Xme(O z&L<`y0;XW|_5hI6IPcY3<aN*Ar<<u)k-#RC2o7^+j(3P3Ihssl5hlP%gqK!U`WRz7 z@r_+cC`>TdeC!SgyB4gQd^t$0&vY~Tqg8djBRtfnYv%>G(6@O=ov>HYEdB8_fKvo` zSe;k;IHedu@u`b6^PgYY`3KD}isBu61AnJ}oqHCv`{xM4>fwFoqYZQcF%tS_;F?>6 zBx_z*fNPQHq|iIkwX1R3vJL=>@6A6c(S|yI&;RO!FNE|i@K=v0TY5RS-2v`uRpHPa zjFn8du=D#@lT{LYhfFNHamT~1<k+U`xg#gX)nvzvjxP)B+HfkibOof9aws13_Y8Q? zN+?v^WqakShAI2wdwE8@&B^mgdFj2}+d@ZyVy6x3&UsIG{^Wq=pXVdaAk+)fHVOs) zoVg+d^zL_YMV>w{0}u+SdbDPXpQ@Q(oZD?*A#kA^7DN<R9RSAHXW(n-G|~fKLF^*7 z%vd6oxNT%x!e0B(Sr7BfVL?|dDD}O+XfC}|`VkL`RJg!KRr6V?hy<v@?=g`w*F(E& zGaj^dAKxh!RFEdSA0r{ZIPm5cc|m^b;@Et1j;rjNTFe&5Csn?{!5uvhGF{#%QLxNe z`nj=V{(^Dx4n%i20<GJ2KuULdYHU!DX<`GVmew4w>5eoGpv=5w4{OicYszeWkoAFC z9tbt6hY33~@l2P~E;+@nw5H6<`UIQFcDL`<i4>>gBBtk`P;P6BMb7Q!>Y(50pwCtK z`RL{o<(d)?IoNkM|HYPP8(@)xC$3kT+B<u1M?{o=E*l-WUL)gnaF?N1`(eXi8pQ4Q z|3}lg$1}md|9>-#WXdsT9hE{lIL{$U&Zneu?3Qzw^I;BCNg{_7IgaE|V$P=-Lm_e& z!salHjm>ex9Dch$_wW1v9{Xq4uJ?6#UC-C&aB$S7B6;_kY_G5XJqt24U&#ZA4GK_C zSD-Gv(~Nodv{;!Yx<|V3z0Kd?OtAVzOsf<@fob+LP)dTAZqwWM=>u6%4Z}i>x<|+L zQ2!Ll@czFywhv>%fB%a$e^s_~N5(|XGw#}%Gf6vsU))fCBT|eXQHRpdD81SdT!5*G zg`)AZm{}8)s<^1iPIAK|8=GhC1#<T#FFtojs%sS-ACFlh%*T+ACLh8gE;rD-)U?Ax z8O%LcH{1GAad50!ZCA9J1DH5U*nlkOw1;9er%Upujbt^8mbM*Ctx2pK3Oj5fJ26~V zz(|##p<2f1@eKsi7F0p~>{47*6)|*cLjB;e#E_v@QtAQkeU)C`if$oWK+CK@b8poh z+5dP}0l#!^0;Sw>clIfM?gDH$ci|T7jZotW()BCWh>qqG%DG?|HF{6MX9D!$4ykmN zVBW*V?yAxi<2W@qFEg00$J3y1*XxC~FL#z-=RmGsghhY2TR{wcBRtD(QhAbAgL9>_ z*e`hpiXZ%H{Qwo!+=w-R4rt(6%I9QvPQmWr?(&S9L$(x|ZrIgYv5K-%L0mk;KnQt~ za{wM=rXF}_+qP*skR`~D@0*(I&N*9Z1vBy`uK1t@-@h<^%f@OI9sW@H2ZQ|WPS6P= z?fa=3*Hhhd#?Iz<&W6_)oqJ{qdJ4}y-hXu6|FEL`z~Bz<@71ry+!3b}bZ)(58^8eR zj*VUqcbb3SqkVKS?i5@>kRPf>H(5k8-58JR_8HS27TMk-;au(g;lUZtZ;2YFaJDBp zm$BMyh6}ygVRT;P$Z9hX@8EMEze7-d>iLHe_RhxQichGFPxSu%FP~YTj_i#i7+?OS z;^LT8T)k0s|Nn{>DGsM<bIqOG_wS=0K7Z|~gVJyOzNTjC`Eg~S6XxfmS^%9tcsfTq zJNN9TMKma4PH_=Unbo+Q8-nF!wG^WYdGMg|{5};{uJrFPgYgK+W*|5Sd8`dt1Bjb7 zI)$wuD1;>2rof8>lPYz39|QIdpEl7fR7<5z<|UZi2Z3T*!<*J88u{nZ^2OMEyFcP{ z7$-DjGgS@MB~ZK*RGD)OUFhFpAu%CNMx}lcwhNlUujz@qdx4MVnsbr?Oyn+0AouAj z69WxB*RG==*U?xX$=^q2va*iU>hY~f_3Xt<ym`IM&1b9!gj{H;A|Ow*IAaIR6<lN9 z=mc^o-F96+f|pJ9?^8WNXQZ);q)S3R5_mn@2fpw1p%S!%X9H&g`HPM>gQ-2<jEGV> z|D-UMpBDo)O<8)UQ55#Tj|F1DNt4;!!O!BOI`glV3va^Zt_?7aC)CQ|ZK1pzy-eAO zd{)hUpA%zT)2W$K7`gCP+aEs7r|?B>p_tFQBklQ6{`Rc)JxoBZlD6@lterA?hFIP! z^J3?FgSAmg(xv>+%ToO!jFm9tGj>|2mGn*%U$gM!c#@&wb^IUWGliuFe-`*m|9;x= z5|}}MNn3I=JPaW(o#(2y*7QzCZT>fSQGTwJ(n!^44?0uIHTBZ%_oP8##Of~b^W&~3 zsjlVIlA&r-_N{-;wqCgS{q;KrTSuzJMEh=s#(!hKfAh<ahx~Ouw>wYQCHWsdA+T*f z)(I#4Knk?4?eB$sr_FVEalc7FJJ&wT6ScE_FD5lO3f+5mFff)ru{Ll59MCOZfT_rF zjC#^rCRCm^8NvIuyu*u+;~--H{C?D4o)y}(ec!W(D)l5LHK_C)i_gxYE5}xi%jcw3 z+!l=4i55r8#VYe$Yx+>Pd<uBeXv8ndDUZOq>y_Sdg?0l}li@7FoX|EoqF@=$j+#RH z2no9>5bZ`EcX{?nSmFB30Z%`b;4pc?6GpxWCWBGY%OJWz=o6B_(u>s)e0<3Pkk_Ws z54UAwC`kI9-px2X+X`T~u2$1DD&%3W9-Em?&RhqFmr<N0C(;|bBOTKsezV9vVbb>; z-Xtf#e=s~Jj_W<NSI!+97A;caFE7U4yzLq+ua0tX_1IH-wpu9DfI6|rG#4qXz`gz- zYB!yWr$kIi;3=B()oLSi_1&mfHQWDHwIB<axcDHfs%EZ1c*61)^>!&`1KgEmBKCfu zE97fWXa7o`Ym@L+^W0o{dbP!}S?fpXc||7?<4craigIZ2X?;)T5zB-hfkV5~T2x8# zy`Y?tVw$~arN_B4Up-uXRbF>Jxr}yXT_+h@?wzyI_fX)0o}Um`d)lIp!D)`v03tIn z6tCWu)Bo3S>bdB`7G*4IC4K0TrntM1je5k;x2^ij+^@AHF{81YE~VS$K1p+u7QQmp zL%PKJ@9ydv*Rr1`QdSWAw<E?g=EI@aBDmX^zrj>J5~TeZYPUI?Op(FrDCCUa6h0bb z`5fNr%e;7#7sqiu#bEBN0A_-ss@s7Wk~&qKd3bcXPztJ3YUU>Kk#V)3v?i6KAz^Ga zL7_9&^8-ABS1O9*$pLfB>%-inY$<gagKI_1t1>@g;G#IrCMFfW(EcmuZ$yJQ5nwvY zkEGK3=dH8@lAP1p?3s>L(ejTLZor1^7lv6{G3#qlMO1q&Oj{`_BUJe}YFDB$Sv}~Y zt-vkooC(Ya6)yEjo%{g7ZYH}Arek&4?!@~DwVUrCl%h-7inrSWWbJ6T8K(>#C8{*% z0?ojGL}l0xga1V0fRL|D_50{kTBVS3XP1Xy!##0l$frOE#Y-AC{!^Z1;STN950!f9 zk85TCWV#-yzf`q>5!Um4hKf?^PiYN!o5absY6ae7I!cO&&l|cvm;a&kjc?TEq5r(n zvpW5W+&^OU_(&U!bw<<R?ffttFya#c%0D5kvp?#RAFjB0rRKeBi-dwgs>yZ&SBLmO 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%0D`N!LS}E^D^hz`kJLFSLO@xp1qn7EF)1XBL2| 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%0A{HsT0ynYs}=(7EM*zU8BWMSP|I1P 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%0DEIOY; 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%0Avz@b<r^T5iP`cFgwIE> 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%0A)3op_^(bXe%{v47b>;a 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%0D%vYn&4 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%0ACksRVXY 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%0D4zh~gA|K>bw86iKmgNT zrP0^&eZ9){3zP3FpV^F3{w52+53I&izmR7&Xgn5IjjrjF1lo`M&F5-;((`tVpXNO- ztP7Nu1rW5YEpgNJ**fd|(`KeC2V|>`?XsKo?56uZw)60&>o$sNAm%jV<gV)%-S4!h zk5fyZ&EwI0zgL~mQa8at)~uT?({>yCwgsA10c`88le7gc7rn=wI2o<o`i(>Vgb`Uf z4mBHR%>;Iv6Hjc~DZL(G^St5{7V7!WsuM!Y1pBI4?4V@as!DjN0-Waowr%axshLRQ zP|eJm9uMoDRA}m3QGOzfTQVNY68~d+qJT|*&m%&p>a$M4cr$5tvT~l5*FPd)d$``V z$N4LH$<2WOXE+x}*yH#&9nVLl8j>)(&qI9WY|#pTm7TQ3G3?ZRK$9W9?)YXBv#4#1 z_OU(DO3rb)ZO73fKU$}sr2W}O>$t1l*=tSak6qZOE#r9?I6B!r{?$=?o-G*vy@vIx z?`LF1oZ6N+z-iP^x{e=v>7_TNUZy^=RTTrd<%HF}hV?&R1-vdlUwDROgI-kzZuO6< zo35T{w4iV?1Oz>>czV(mP%P-^NXcG$spG$PLgsegZ|1)}x>^==FH-%@`+T&0yUL5C zA56EN-kjK3&~l@5+Wo(alQ?WPJZ*u|w)L&jYr%1g!p&-1+br|}!l}6s?o=>&rSFb5 z4`dDNaB|<7)weSASH7WHv;mo)s8CcgFU5E$ODsXApe%X%F*g!b!3IqbGh}5qxYO~! z2^1MK&qSY944fYS9Wny`M;a~z)<O;@Hv~?9%@>?u%v8Pt40QDQ3s!&=tmv<RH8$7) z?&X{q0UP0S6{{=)iXjfL9s+bX*dPE-v&u<e$WRY~k^Wvh46JgTHDDJbeHK__m380^ z{ek!b7;+yMfTIK~fw+S!kRVQ>xEvUU<=-O?a3Iu-0(NsCW?)yqe)e!arLUzilX|@2 zdVzH=ByBEk<3@2K2>|(HR{3S>d7~JRKDLLW>=pX~4-W?zvZB8PmKd-IEVIl2#1gw0 zfOF7!Ye51_yp064qE2l>4CL3Jahg>SSFpqiV}S7naHF`AMY#0NOD<bD0^$UBs9PYo za`TUy55eaBn=k6;LEOwO3}E577;oNOV2vTLTZ}ov_UJw1<N>iy902y~GkRR^b8G<b z>(BTG7>V7S192UP*av*dNBTH$jEBT)fC>Tmc|d-cWOO$f*8_v`+cyC336pyCyzKYV zc#m%|xhvznd5rK;e@O%E6TrR9d``+KCxH1Tqk0~bd(ywvgs(}bRQLw;UBU!Iecp3T zFE%Rh)kWKJ#Q=D_jjFl;`YM3JsB-j}4IrT@kYdzu9^%YJD&_W<t_d!>2P|)o^^Lk4 z>uvQkiw)zlnS9srYFBY}Q-E=uxJ}k-=kDXhI^}X}>br~nmYv7TsoHg0KyZ=%R1Lnr zD#mq{8!t7}hbm--RSoUk=_CQAs9d(p=BD1eBA#grWGjj%>)LM_kk+ZyKcYl`*{~l? zt|!#*q4|mCHkvO2l-ndS*!dlmYnN5_<W0<F?X==l0OThb+#Tz7QYGs*MTs^}&GlEW z!a|Bp*sHUSWKr*kDOOwV0}E+Q=ui%bPnTbX{;tZO7oAv=K9SIi8QZ0C5@dM)Pwv|# zfe-$4?BA%2PE_hy)nm>y;yabQLN}{<^nA|uZOYYUxr2fcEdeSwyML?V!dZ*gaXSqP z=2vY`LYgOgpT~aZ0E0k$zs@)Tx~<(0rX24CsU4K<C|v>U-CA#~Z~tCTyU|O1=>hJ& zw6h#l8Tghn+l3on{?&tL_y3-8Mt8J@ZUWn7K_Ijh19R6C6}1EUViY*`Ls6Rv$8>;L zy)^Z6YKPg^*87>>Zo6DKP%{nC)sE{Cy?u`DsCXROnT+xCJ<hu=7aVrN{Kn2sXRD94 z<(~!Mqlw;{Zah2jHOhK^A%R;BecW!jL3~^M-g5tBE`Pg~_EHR>C_2(PPp^bWU<MW2 z*>#z)%ytZ{H+;+WBn#dfF@2dwSE_iUR~f9&*$qi^Be80u)QJJ+DrCqSGWrC4_=lyx zKliur5?}BJa1FcIZL~+iVx9nWgUWuaCK#i$fZpt1Wo$D>8<`0Z836qOXHcLo3*qT^ zvM*D<H1Idg5N0xWtAg@G?@Y66r|Uh*1a1P8v-K@zl8^odM){%y1SS~WgYfzQ7~*Rm z#64Wa=b+!vuk#V;BYe*qh?C-eu?+e;UgcZhcHUtb*uz6ypDN$A9AOc})$C?B@DX2S z016|9_@H0qJ<fnoysu9HKZqB26~wJPCT;>=<2aX-J%T(7TsML3K}N3;AlxaqFDkFe z+#VPV@R8m4@%KRnz-_)KFc{X;0Q)>Zx}O5bL&UG2{O%Zbm+;`5{jnGzpB9tBKI<zI zeN_4CApa!C!gzdC$R(eBzxh7jdTc8K^b^0oZcL%3F!S{1CT8ka{pNYzxz*xsp=Hh@ zj%p5Y>~{4*b=)3mhVhmx(PxvmrwgWb)iKeFvh3%c#dBm!f6@ftZ6Bu=1HWa<=h^~e zo3uj}Lv@jz)lH!HO4E*;_v?XCkFNHUWXqERCiUuc>MvEz_NwwLUd?)%>jF0RSa%=W zhN-k_{l!boLTwT?icf}9R{gQavfYXV{i1TX*5kQdLQG)c2lMo#3_TQ=r#SJTX#K4$ z0VS}kzhjY@l6P`KDEj;G_Y*n&Kj(S+1lf}Us`^i0c><)eOaM^@i2`|kFnt1CVpn60 zoeAUHD9#PzaXk#R^v6^S^bt?@GO*NYbplS0ZOf6ENamZyaZWew=@s;!pkgJ#neYdy zllidIB2MZe0k!+}f?4m26#<eLtaaU`p1Q*OMf2%l<NngD94by3`>#8#Pj@R(O=f-R zaamfnV=ujQ?$&$hrJcArnc5{TZQ=9a&5iwln+jnal7%?8060IZfqW}~guQG>kE+Cc zW;{FEm?DWDXuQ2-E8EN6mZjeQfnzWB?UENb^#Rh(=&4-+doLbORld;BP=q^$eme!d z>#pkSb<T`9$vDzBf|o6NdDZ*fij8emlVQ<}qim0)c49!aV|9da@;+&`aT+~04csn^ z%M!-?$t(9;=*h9@uXPw8^WKxk@Tm#`?NPak?$4G>O|*}k01lW8W6{Q9{`*yYG_(&4 z8Q~v8{BOlg;uGLncC!b#oDqw_P29wlBn<9|D>)c`UIG+fvlke$&IYiTlPF*qE>$nG z#s~;PM)&>fVJ~9__YGi)0B>Ag;Q`Am@hD>;X8<@1!@py&@H66Gt_Sf1H*yrj@i7Cs zI>BkK0(P;)JAfZDxbMbeiDcp0$LDlPAE&|tvm-xrJvVR%3DA8%ORSOri+2-nige<| zz-U_)gJC6bjt#xenDNeK%q;&6<BeS>)Y}mB5C;!}Yd0U;+y^YNkNu$3=9ilaSQG~U zF1c*s-30}k4{ctfZimgs)$95&=mYu|B&aX-tNK0AFX@3EfPRH%`2gfc;vKOH@;h;q z0Jx4oFEeJeKMZ`vadrbER`5Ywsn=Nnb&B8VZ$bQ;z2Z&~PjM3mAh=!a<#XWQ<7HgX zPxB7PLAml?_qNkxz;!?xkgYNa2ZIR!`xtt?6x%29Ul=pkr<v5<)bpdBkWFw<@paMr z(np?q1&J34;6B=3P!ov}(fiDHPbXIRDZqT>R~3^Rj%ns~mFoX;f;m3=n@#u_#Q=sN z*O!ir_c#=7cqYC!?<7al7x@MN-%J#7a>gc=@|=Fb@5<T_2L<J-Kaa4P8@PqzWm_ge zyYh~Dn8#eiX7%T((`~nD0!(Cw&!`3r+Ck;oYO_5<ayc-htGGi}w1X|9arJz>S(~SQ zwWRqDr)_&w#XnsE$J23&-MUA;{i>$@)w7IC+XAiKoH(S79;=>HWQS#CE&+@-urDW` zpVjFDW+H4+yLv`Hv9)uB-N^*1&{yOG!BvI*=EdQ47~H)AD|2i5LzBTfsDS%aJ=ZZ3 z!Rz*m<U}=P+0XOs-j+DR1b9oMKQ-}_WqvwZZ;*v{lJCcg`mdLn?N>9bJ2i=39Lx2r zprGB0P8Rg3Vr-X%!1%I+4wceNUc!Ye(05R>K2-#?FIxYK0Ooe~SG<0f2C@gKb+4k6 zKqT3OG6~|cpMLY#68L`f{~UdnilZDZ$&Kqq{chlnl%QiGp04J9EhNT!cvIAy5|RJC zV#|Am>{fqP@uEHOxBkgKs$+X{C_b^K;(a<AA6}c2{;DeGA?}p>Z(SgJ(2(G)s*gtr zB`=rQkwbl=!s+83dt6N~ol6g*?WHRR<uq~FKe<u=ZtW3Jj+SvqB`Mx8cT1)d({zwQ z3LsF|aW@%QduQKv3OTDl$T2>{opY+UyNu7XD5u--NSa<|W3RU2r#xEUPSaf^*vbA< zO^NGo-feQm0bJ+6+>XQ=c-(|ZtBd*97WL20fa6oHubvm3xfKj(Za4i+H*C)u5%_HT zX&&&no&T!GsNz?g=oQIe0-zCXbgJC@WTBr(nC0^~Ftb}?d2wtu##Hh6uc*iHSOu)G zi)Cd6)1J);T>M;FIRBIJd|u|1HQ6{+8M`(&W{d11&1@copM4Nlb2XO%pKyWGK*0B@ zP5LwdR%OcR7|i1;X3WmEqo0b~l*Q~eFf1$0cn<I&SFjs6#Z{q=e4W{xH<{xD!)K=% z)z!qi(qsWDQy-IoJ^jAudYO5z$@p&e7n4~&DOZqsLJ$Jy(@gF@Fv7<N{cAqp6o{Yk zhPWB@cU;2|)Hmu@eFpS#eOd$Rgg%c03-^m%nfHFKkFy5)I0FLU8q9>54MxCo;yx|| zc|q(JzXSb-KBQNHM_2<8Pl$(jAZ+n8gL@F$YsBmx#I+p*&t;~)ikREe_oV^zeqp-@ zF%VplW_(u}0KExhPng-W!1W+(Und1XPcy?u<;=U!jPufGAeh%pZW<~hJ}d^x=iQe8 z?~BHq$sU;o*e8D6?AcZQR~7otvW>lwQSQ3)a{IADW!_ij@8^Av+e6?lju>|f;$-1= zvxlYC*3@t63A9~Vl`{oRG&za4Z2e6(EQM-tf727zx&nGPo#oekuUq4}vZ1}!iGx*5 zi*36OP(+wfx1UwTiFNHckLlEwk>7^FyeMw1>PL0-lK<Rx4EC~SJYLk^UW2(y9@BT; z{+C^%f@5tbd6udQ0K;BOzhT3mEo=BqWqC4y?MZM+IUTF#)?E)X0n(JLH|4jVDkz6j z$dqr6lV#&o1ZWQ`^y*ZMduhgeRZEYu)L*NLbiuNdMaoW6%(E|357~7nnd>(q+{v~4 zM?9M21BP)zOE!`mhM&EbanE*$=h}?ZTMd-#D)F{0qjKUOHm9l=CqY%kG0uSe6Exb0 zH!<EghE3b8`){?loy~8f8Vakc2Xms2;)Kuk{ibR@TlU$jG0&Bj?^7-Nuc8>w5Oj1x zQQO3ZpyLzByqe{=Jt@fMIXzmrm)gT$FTJ#z5R7G1FaSjvv_Tel@)yssy8bF4#Z&V7 zRA3PWdP!z`IY6PzAvUSUyaWQhv<)1ZO|-fSV0xLI?4<tFb*66HiEKa1*y;Xqz84(2 znxD+G{->e&yXMooio0j5A8(uVzq_~DXy(kUq|RLRE4MaNgENz!*!4zn(fegffQGU- znz*bTmBGALr5D?ykb?;zgRBIq*tSP@gVNS-O)mJ>*|;y_5mSZbm8Ba}wi}aXy;Xc< z^(1ru*q*XL+F=M44gu5pf1$tUB=AQra0XC}aDneQgAZI_6(4Z)_u=OieBhio&5$u8 z`w&>=0stE!WBZ781`zV8!wMcFzz=`l2!YchHuMNsXG1&;tTSW-7{&nTae2?-h(o{$ zM%=}C!zTc77gvY+`99>1AHQ*p^C3t3ST6(iv!67R_#*2WePxfv-e43%stNUSfi$o> z$bfOa<WoK(VcffqW8!|s8(<Ew!J_^eSY(L-u!m)qKrFM1CE!rV{T+mVH^d@~z%CB3 z1V4TjT)#O2t`L{=I>_Vlb#VpAkMvF41M<AwC3b^zME*g%30$V%5s!oa_U4EBGmsDJ z&shcr;vR7VIKerFzyOZ`SYnYOaGIgM0OA@BvJTwIDgfW|9p``*_OSx2vx{@UDO~+M z$PYJP_dh#0)}%`8D+X={p(Ta@a~*y!Lg2X$QULh8gaqFJpqoH=6Yw5=p9Z$4`&>X4 zIFE6k`5sc&tBl=b0ojub?316(_f7hOgbBXbKPm(0o-om;*9#}lWmE=3-lT6+IUX$m z{+Idqe89Z<9+f)_2>`^$HOEpjq3gYgdX$a`;-e|g+Ph{Tl&zWLdubO>%x1O4>u8m# z?Ni?GCY})QGy8R6X;J>5BVa*yOyY7P@vaMtb8Fj0eWD?0W!J^^?lMAGmhV>`0VRsH zD5nfKlLhr^UhX`=l-tl!iU8hT!*T^R82y`^5MaxoUiF+Rd-5s>1e*55y3GFe%<A<| z^p?4H+HT#Xib=Gp9Bu8f>O?%Rf`C9(Fll=Y*F%c^yq!HcmhVvoc2Q-gD#jfs%XYR) zpfT2ML`DDCM*9i3@Fb4>lDY+n4#j>$m7erq+D%Z2!%(#t*&RzjX%I3)dj%9Z33GII zo;La3{B}!DMw2-3Z@;_y4S5%E{qWv6uFS^2<p4>ub&3<RXD>b8WM}Ao8o*WCd8WHf z^ruKpvQbw4Yd*v)@EcndXLoI1YR*t0i#69(>c+j@?*pn#Tt962d}WysSae^}K3zmq zHKLbZW-dMSte5TvP?-r>WG0g;3@9#D&Sjgg!sdSXX*vK*0PWd@3Y9vlZ@LR{-S&m1 z0FGYjO?0Ql2)uJWzM5K_^maUbzcO!u%hm-<)2q3hYkQJAq+jezf8q9av7_vxY(q!w z5IgT?!`?Ca!S)%MiWrr;n&)?+U)v*7i^j!jW<jTu=c|T{kTx5n`3vmT%yH3%o3hY{ zisMncnU={^Q>LFX4I~@ms=^NJ5_r9W@u6&^Gp|0ArLJP0mj(4IYTs;q{175JLK1v} z-v7gufB*I0!Z$q66Tl7Z=MV{S)C2&V%;z$v4bsf#llo0t6^50KHzw2EVS#ZZ_BV`J z1iY9jygcGcY*$T`OBGz3{#6?FntX1tZpth*F!UFs`WX;Izyon028Ks~f1jAiU9QNN z#1)`@d_D&C2YnSsVDmb)tk*$4AdZQnARZJBi@<9J!}t~A5H5&o^!|_$KTCYD&Y0u+ zRsBAvfM>+72tfSrc#O+He8h^l3AkG9<pmOecmhBVGA9Rw_9U(fe?K~|x46<^SPvpT zED-|Zb(Z-(&0Jo_;2vF{*k$&2S#bY|Ne1<Zu|0<YUi)!rBLIKq_muqy1&l<hz#dhu zJ*5HtS^r=H@MR&O+~z2F6Hq;Qggg`dSXqoQe$IVe#NZ>NoYPpnn&!+akCA`7&RJ(2 z&uoXdbspkKxh3tBKX38owBD-W5$9@(`m0m^uJ=cpuCq2>N9+nH<1~(#n(4_cu>nbU z%<n~Z7_<aPoA-4ES4tA6Whdn_^e9^PM_rI$QF-#8xi1qm^c%En$EpMe8=!moia|ra zSoGYg@y|X%M#lP)o!DcuaUv*T!nUc`<a%DSgp9PGD=U8$z{>U{iJ}C9ssyE&`CJsl z>pEM)n8{Swtv^NUHkTIy*2n$%3PT@PRIax<mg9*D0Jr!5`TFdJao(};w_`uQCrmlt zTVS`l<L5~Wzw8x^=T3YQ+W0w-3_jYm0lek^PlroP0@K|%PIu;dj<0qA)~i_!iW#X@ z$vEYA^rk_)PPH>*-FdaDs(DORyG(1}uE}#{3wx-FQ`{-ro2p?qvcvdnp4NSwZQHx+ zoou6OJy+F=H+t!12MtfX%&SOa1Jut14|&&1fWdiv>)PFb`qAg^;_FfYjT672%OM~r zIfT85W1r79+Bu>w64-PT=7(OkU;FOt-a5U2wD*<MkzgCl0p+%`<LwcUPkZBd`}^hm zfP8l4a#|mPIgkCusoB4`q873fKaiAP&DgKyAC+CTneI0R*vOhI31vWvIvea|8@RR` z=(ZbolXk2sk6tX_@E<iChy79@NnM7$Nd`y1qTaH=&WJg%(*4}r)~*7MjbZ?DKyVE4 zw0KH93@mYoU5t-%b%EuOBW%O~Cl%Mr@XY}(Uieo59xfxs4CD^r;1VzfVk=;o#du?L z{JY2ExSho!pz!#4_*VieoCRQwH2{uskX^tEyKsRE1dM>QTwoO#F~kQw90T9Q<)Pjq z{R~53cm%)o436x{W5S)xdW=c|D+uc=p%BiiP!S|sjP;iVeEZ{a>J3Ktz=6;%Hpb<0 za9&zi2NW-`25MFOUR(gyc#d7b8Tp)8gC8FZ9#(sStMozr9;i3;Rr*@sQTFJsK|ZnY zio6HJDGsPdfF+*d55OvGoFie}-xzO6>3|h307pVT{83omJ?vr`^w0IWehTz)&hiB4 z&-hq>4Ei?x3VX-`&_h7E&N8J(Kz%X{>&jqYm%JJR-Cqv%{;H9vknrn|-xo|UxI-Ga z9%Pu|90O2qGOPy^%<b8Phcr-K0q=}0M86%D=RE@$FAF}Wy-rlFv`vnTb-}cMOf%#c z`|)DHxe1uB_D+)kcE94ed9$o^z3j#^d!V}CdJdp!m8)wR&1rlyt@_S7&X_mxwy4z2 z^(8xd|18(1R09U$dhOUuLqUVm)Vag0p`U32FT56UXP4!2rp%~r#v79-E6LVefO+wd z*OC1c#Yt|B7L(WmGCWIvR1tUSH*45^Uise1zf}Lxh`sX?$5pHTDQf}IZT)u_i3t+> z6WVP3Z*%5#r*z%0$$F~|;7gU<UshhHBw^n+QO1^NtbDz~vD8bJKp-zM)+rgkJWHl< z6~=RuCse+Y-{18sg?1xL*2}z_{;g`=X)*ys<*v&V^-p)={i?Fv3=y)ycvjT!RE7TB z0)Jb5(x6#ynVDa>#yIGONEF3?!HLu}oXW_yD1K_@_tcz5H*HTGx4l1^ugog$nazA} zt7Wl+XVmfE)0$7K7IBIy@z+7@pH%L+5+&LVsh8kabafE>^RBJTX%t^hoAKVGmoD{K zb%M|I*KMY|UeHS~wVhrsz1R<UDm*?ph?%R#8)}!wzbp9jhnHUW*Pp|sE^1T3=8XhD z{kR|~w_8A{4pgTtvt(kNhY3VK@NCEa*|%DmOmm~E*L?SZS${f1Rt8gVzn;Oqj|isk z54U5#-U`ceYw=pow|?am`oFVH>e&|1-9}$^jx@K~$hX-r_X_k9SZ;*6waY~&KCEKw znqY1dvR40b8#BF0qrCO(NmXprIyL)`S?;<(pJ*evx?FY(uR#nA4p5)KfBeH>^~~SG z%{;{&q=DE``66I%7ATxf#7_f-(~Rlqx+?>4oNgnPc|H>i)M?qxV9W+578wC2^_dLw z`6M%ZwjNcsCsRz`s^oW7*h9+4i{#!!BSA`kehd(gnA#%-avwizKOY#4KkHxU7xZyh zctE}-zJ!H`<*o8Os0Y=4eFPRhkR!eU`5n9D>!6pz*G6wYqfc=P^hv!KGPs}RNU9zV z9uBaVeJp|)@Rqm<c%N7FA>aY76jy;b!eI_E2`E=6ahN30LB;jW>L#(fgvmb*;12Cf zhu4Yl`C7${>tn9*G;p2Na~%UfpJHs+k>1noYXZYn4&c4$_o$y`KdW2@_F$sFs|f&j z9zZ^QeOk=>iUH<o;(k@?H&mhT$@|66IRU{gHZnIlyP7j7t2x{>nA26OatHLXlh<>) zpJC53j&f_3XI|GAoEGaL(>?h%J8x7SCKz;);4qE&F#p7_{L*?;YM&|w?Y6*?y88$& zv`Ub!63@~;>e`>vvRt$34~d?e0hK1Nm!0+xTgLFV>m>F-acRX|Y8$Ut&6T{uxJn9H z(;jW~qH6RPY1yBfoY+?NJf|k`J(x(0QC2IUAy8Jh<xKI~NFWe(fa!VbM&@<OvOQG6 z34ZB%r{`bQ?X5CQ@zw2GZi5l<*fv2Uz~K;+`%`JAd6nsZs*uS)zr59i64`z&OP^De zNaDnP(FyyaM8aRWfBBydZiRpKz`ywy{xK4oi6Q36fYLIK+n)PaE=7qXTe}iJjeX0q zlP-(>#cbl6LBo?;%dWRs$1ggm)%GNipyKn+kEgpiv#*G7EBSt*BRku=b%JK=6h9i{ zrrn7;^MacSQiN0uL`VJb%?9l%0ly;QD5!DXSeugvdg-MD=>hJ&)ODca4X*1`8?6ES zS!w6eTfn_fzyA*k2>kchPqHBv7#me4^LtT7aaR-5JV!mxAS<t7y?SXnvDn^;6TR5? zqxlGQ=A+%!ocqDPy>_Pk+t_9AU*}WGH;&}owg1IDZadphuhaFz(y-V0Y=0YIahK&* z7Dtyi17Z|2?%9>Ae8aA2p|@(`+}x;9+-wEhcZ}avOT9ZCufYTc6IJv6WXEWi+@HTN zYchzblJ*~$Ke{g<IEMa8zpUQ_ZsiH?1wLjM>%i-*>OTS(SYZ`7$_?VTz$z=O0Bhs_ z^aevVfah5YnYlL@0;{Y7Fl2}WoM#UJ8zBUDJ^a^@4Lt&u*bol_KI<qL^RYw7(+<z+ zSM(Ra8V~Ula6{O#_lj$9fT#HYKip9FfdhIJ-Z=(JJK`Glrq)81aAGj90zFIt&H-@{ zm!(W=tr;6_qYNN_kwMsp$M&(zvRDf3ZxL9+V*m`s%=Mdlf@d}_1D3|j=<MZnb^%K) zvJ3c%v#c;a;@5-VWN_Q&7|?JO2~M!^vKRu_a2N?ZByQpWaFi#w4%p2%d<(qBZ+IHS ze(|EX4xCq<T?+>w*d2Vk`7W@*Dh`M}Vn2sLY_P#W(D!hFA+XE|9MEs^9^Zl<a!9WM zo7~FJfb)FIao{p>TgZYL0oa2H;CepuI+^eN6d*lFtz$*N_RGWHkA&@XIKD0fRBM$1 zuonT`Q{Rg}Qp_knA`85p1hSjJ_rUO73P6YJVIq9K9!>ZumAh_73MdX~M)xe_d=z_$ zzyQ*l{-T<zE?o}u`$;brG+OVAnCeFr&o92eydEQ_BXt4ib;mHjkEVL5n8$6!ddjRf z*t-A_&#EWY0iJF(;KYpqXx+D~Ei>^f;=W0STBmh?YSK?kX5_Ydt!gi?VY#scR8=Kz z*IfS)75zmwWK4{KxJAJ8rhd~kB30G0J>8b&$y;Zrd*YkT`bgaqDvH{ztpC{nvd!x~ zs=-Flcwjs3*e2N60sIrrYgMD2-J1Q<ESGEuxOat<ix-IGkYQ&=dBsuVzC#7}<ks{b zb=oDX|LO$0yz$$fz`>a~2~HNaiH$$7d!8y-hbpRX8KZrE{mU8No%r7>odA*BKeOv* z*+c;+#pFJI?*ELJQe|)wI)=;&RuspNQvRVTVY%OjoyL4}Ht|O!gMyQoJj=M;uUz+^ zOt8;OV6q{E*-nI=Ziz;=O6GATB$<EfTJxy3IFLcb{H$vU;uA{E@yN+|)>+{;^4^nI zzUui{`FK7r_885R-HsykXp|2`bW+Ff`jy6B+M87`z0{CP4_&g0{V;M_U;Yv<`57-L zK>Pe+DGDgcn4)Z%%BJPO-5F2JcA{)2&CP1#!|lzYml^b{c?T%E{W8tAmSDykit{F3 zZ@-<}!93c{Ec}$MKi_JL>vCRQe|{#nr2V^&oVV&o`^kl`1Zb>k-B+*FHp_Npfb}BA zswVUJGDfYk_G`l2>CzqJXT)%3+s<|RlYK&hEi+aXV~|s--y(gP<xCi$eS%NWZ~t)Z zzxmnU!gnE{`F57sovb57jM-d)$}q7<8=8}V-$?f=SHsfyTT}Eiyu)$O*Xg%#fwy>w z>q^Jj;+9qxeM>d)7kTYr^46=ACL>^UbaLMqVC-j4@{2zwjPC)+lj22jCFnc!gZQv; z-@+r}Q}}TyxSu81d`a!m?}0cf_Ob#C!2;sJl>Ya!9Bx&NIjfF~agR~@eH>sVOj!6W zU+Uu^uMo$?8i;>ae9kctPl`XV2l!rZ@D=G32=f8vdBFEb-w`lA(o)2%p3<CF#&et$ z^Zodm<5|Ev7=ZU6lbGO>1;i)7Ygzbtd|#AS667+v2gduq4}tC9hQBArvF9_p`x8DO z>b0`KM+EWjS%&wZbmPB@**q}HRb~5rLC>@G;z5JM;;T+%DE9}mTq`RsS5xunWjo0% zP88Y+^ZhQ@<K#@rFQ?Ar-b9n`jP+B@>^i;pzK-77Cr&uE^kvJ?Ya53(T~|{r`cqj# zZ%copzoQ)3`hBxz(%&~^VlR&0yJ2Kk20+hi*dLTdf_WX!p(^y{RV2*YtY_LJdemJP zwPl{R??>f+%+@cv6%684{?n;x4`zAX8mki-fVKX<wA^I?^t}5Dt``PiU0b%h$YTgE z(~HT}UZyu$IuFV3FJ<dM>H2$>y)o+-Y!d*APBsWi#$lPGg`xzDBLD6c__N7tWo|-G ze7zX=l*KX7{jX2%I^|vqJU`saClhr~{<?9z?uUObiR1B$Rpb^wSMESP49ZWes68(+ z{Y+UR?sWC3O8wwg5zaNm6II>Ud>&YpP}(#yYc~HW`aLKh%qgDFwVQWU=~<CZf|_mr zu17GH-@?*TAB%<a^WyfF9q6}>o%hV|y>ui!z`d7RvatH&XycjE0WQ1Y6%8h%RKPzC zsSj9JxdZ8Tk?qPT+-zFgMs~&)o4do?y%)O)U(dK+6v*}dxT}$LYyI_X`_sJo`R!&0 z?dN0cNIROgU)nAJi!LKnIS2lzt1-ChDD(Q`N>Ho4UCT89)zB^{H`wy$<7<>}RC<>4 z_@IE<s)|{>Nbl8&0`-7Hw!rVM{f+$saXIseSEz@ebR$F->N&d+8>AVkk0Asn#HYX^ z?&VhCGM3o|+`%2<b`W>4$_j9Vz1$A$W(5~G!372&c84YYJxk%D?zkiamc#ZKGo9}a z%drt!${=JsS192E9!osRctdHtf$4>R$I$<K#Z6)l@H4L9R$zon0KB8WL4jW3JBGlJ z03XD4VL4>T^uEC=r$~Uh8|-FRq9$>WUGZ_)<F*-cA!Dmv2BN;m054^`k|FCPOl_;- zd%UpSBH*z<-hy3Ncb;E34`P{RhM<@9Yis}kdsqjxsNUQRLVF0nS#;iB7y*mpdIkr7 zeBeh1)cyK7PJnn<Tq*7bPUu(k8gP=^8G`sNS8+M;sJMq4fLA%qjbVLW1^kc$O)_E# z?AL3Y2R`JF_`t1U4R7ZraSd!P>)-Jb@W0ky@dfB7^fi12YPWt_{f-2H?`JG`5(pj` zjOtDd_YX1vc@wDqiIHewGQIo8dz@54K>EG};2y;5X)5L2Cz;u!_XXj4TNVHxwXZZ7 z=1gF?ice-Vy@CmJ4@!aVK?Tr#l=2N_!0PmM0mT4;U;^$H<UZe&k?}^E1AMQ#KkMJy z0~l29dx-66tLH4Uo&QyjjBPYNnsI%+PIXg058CPLM6y#|$}N3=-S-9so}g`le%o~{ z8^Fah^p*e@>g{QoiJPk9daH_l>NS3!Y^5i!MZKE5+0C5y(yShJn9JMPb6p1WChg|5 z=x60|a<l%NW}1{1{iLc~T>;9|&ubU|%9eK3EZ$dz&+BHr$F<Z;5fI#MXwS-kSe31l zl-X+$VA^(_#Y?4nmn9OEB@*Q@AnOl}-#?p3M9sBt{ZY<)WR3Mbw+7*Xlj^swWrBxC zIpE!#H@X(<Rr$d4VxW4ypK=NS@A(M>MFbgD_El7FQ$KEKZ-IU}^iyMdcX7t2KYHHs zEx_7H1)o5;ij>6V!`!hB<8+$Y%_F<spX_p<O6JUyywDCuwd?7$D#upN>$gH?O=LCL zqNsGS=E*Gc8rK%hW4hL>#O`F9uJ<?HoPH=fwRih@SF|o}lTcy$oq?tQbvvq$oQk#8 zA2(XqgNWYqZl;}jjB+oHr8k~lYRTrqm)!o-4;u#eQNWTty0{z18B`qEwH;+APqdwF zTDu-xymMr0GJt3ER<G|jy-<Hae%@r>P6SXp#xAxuQ@^+E+Ie=sYdMGdRdX`CwbhSn z{X98yKT!reRvj-`MemCe>)J9dnsJ&}yZ!Pv%-oW4mzA?F^LrA%GzY3z*`4h0c~$cQ zr^DyvmEZQdKxF4Bj#j8o;Oq~_|Nhk9!hZJg6bVzfj|xG$fx&>C03P!Iyh+=aGrOx8 za7@Adxv)y{40mz`2w&Vu02+OI!tTrZW>9lH3M{V6gK#B4<TPh{nn6F(s~`RiV!e<5 zMnG>LpE0Am4~$|)_wnEF*}#F|cyQ0=GVmo|iQ~X61lk9F$<O#1h&xzhA8<HT-T+v{ z;~)?)U>|9K*4UB`u$yHNzvLDUgLsakTnBm|kMbF?i_36e^PWFl@ej}ajSj6xKnyGo zCV=8;drAYj^BCU~pm^2}M_@3jPXgG}@6Tgc4@dybzVW;?;8~F+mIy$H8}1^!Uym>W z==uF4U7y5<CO~eJaXk&hud+K;V%xs)Yca4~rF2&{X5|6q%NgN|V8JrJzwSC$&<KEC z^&VNf9J7mDx_r~H58*qN!46wbE1O@=!e+fG_92Jaoj~e!)OXd?w%X0|);phQ+5{9) zd$}dGQw^UhJFv@XpPXO<34<Bgf!hI~J^fx2@a0)EjJIRJcROm2qV-<4Vfiilv+(Mb zU)Qt`;gzhjI5n)NhzYt(pQ`kIw*9YJ0uEFq>dRK+*dU(w%T7ibr(q&Na=$%b-^pnw zw`RYL`is}lKjgKy%$=7w1?^eyWIWR^nf+Z^GM`uZi{kYtr@}r}X?@Ld4RWq8yU$5Q zGEQk*Nh?3$PFyE5<Cu@c1qShTE-o>nJ1?;L7gvUN`he2o_&eZlQNZgH>j`#q&sitl zb}frDi#2PFBQZnyEB5h347|LY;*%Bvqi5N!!v}?lJIX5Yr?}isZb?)L!?wAu(`Gyv zRJL1Ie@?;s>W-Vy=;2q4%U#i4`UUgP==%Vj(P`6o(VJ+;s(G=gm+8el($KGDdi!5( z6EX%9dQz79&+q4L%U?A=nKh1QP~a!p>OCk-0PhJqdzqT_0QX*MiTLV=b8DaWdT1QL z?-VIopmKN6aMd%V_tIp--_3JoyRp?v-~XpE9?WYy_IBUi&ow(zZ@zn#+dvOH$%{=J z2;fZ(uv=B``A9HmVqa>C?Nr2o6|~%lEs6`OnBuDR>NaFLPZ*l&d7z*WkkIUCSY>%M zeH~!MH2QyiJC&C8l9_~wXyei0oN?uOI0k>umwW_#%GaC(mRaHg@GdXtmq4$v$|`V_ zTf|Gi3Tv!^-oRxY7_q@R@O#b!FbbK#Jv{b@WgP)7yVwgTT!w(ddG>{68!~2e-^&=l zJz&hl4lu+YZ<y&f^hrSRG`|II#$gG#TU>(#v70w>K@UUitcOoXGloZ&p@3xu8OsYM z+IoYH)ORO2#YvKlDu2urA8)MgV-JT&HgI>d%p&8BU<X*iWdICt@PHN0aT4?@>ns7g z*{3gzpC|T!KFyF3i2ZEf1K)6p4aUs%>)`BlPAn)0KHmIXT@CVK`78Mf_(y{i>J8vi zcJVRj>v@?WY_6&s^>0DHuN-wFi2FIm3UDolSp&USKgajL*W!q{54cgkt5<=&oWcYB zHlOf4@Fk0^1NU$vyMd+gR@3Hr^@+Zl1Q=}s#{IY*f(+A|iUI9Wd&{sb0t0X^<JL<t zjqC6|B4ldUX+V3nZ4-ugmGS*5Qy$*{nES@>(e*3g?`Oj6S11R#`>Di-JivPqK-wn) zn&$)5gU~Zb@&V~)eTsaW8#BL4E8pja&mGqEp-u^dd=sexxQ}W+x&G$ibR#pLK6$+t zyLG1Yct1O7m)bF{c&I7Udc>SN>o{7qTt5u9m?3{K;kRZ-v12pO_dAZa>dxD}j)^de z`nk$s2%b*=ley(+yY5$I$8O7ZvQ0#&!}Kg0l%_7j{Mia%ttsa!)`QIZ&o->DYpLhD zb~ebd3)!K6@Qn3>w*4YGA+4(u6WW!_EQf1plSS=kPe_sR`@*&JU%Ftt71fC;PU_UP z{Pm+eKV@?gO4D_vF#yxG(sLSsZnJI|z2B*MLV;^p{<4IGy!Fd62KszIk!6f`QuT3C zB^``E|K;rq?uLYa{iymMFOSy&{P>KtG%-NHLby&4#Bt#~N>GtdF|GMo-uvs!hz5=4 z)9va}<xi_l9%*vo=5{}UdLGI@2~3xjYf9O6i)yji^2Dq11R$?-!XjrX{iLfnS<S&o zYGu!hP69}uj@spVhF7q!q_(Kt@=iQ)m>w{_$d3m-R=Jn@(i=@LwPf$Vzx%u82Xh?Y zR_Ec&V!>DTJ%8>2YQ1c|%%g=gT@c$T(r-e~#%hxVzFxMYpV_MM&FOn+t3bZ3xLaOt zTYHu}+Aiy~zwD&lRm*njZro^Mm#VX)uE)|95XEWCq}hyF-1g}AybW-bQ=cm4cc)>y zl*M6f7~$(Ox|F>~w(=L%<sJiGvxyZ>ypE9Bc=Z42zrJ(r6VPAsC_~^^T*H;1BL?x+ zm@(UA%E~fkC-2T@pr*q9^NyCz5&ek%1K)wZMSsX5@G*~ZCHYM2s^mLW!t7Sw7mF5% zv-L=r#ASx5Ud8%JwrK;<A&^?^Gl1X;GkLU;8!_zr1Ry^WPl>}IUKgw4PEa4KBkGOt zIv==2Kh2kb!!f-AJR}t7NdVwqaheYy*ry)XUz28Z8n@F*2(W*NuQ>&BNnFMV#3kYl zZUlWqy}J1^EW9TV@H%Oxe-$$RW$TeJwFe<kJqrj=nA;<uy37FG1LOA(!~5P1zkfFd z&?nDLCpzRYvPbq!=KU(uo+dEgpJ0kt85>H&u1%(Ra-K8U4}!SAWC7yY{xwY97Xkle zsvLff{i+iCg?wgqvwWk8?}Oa_Zi;UJ=%pnPq3F4zLVpr$Nvv+x&*_ZIte0M9FL{h= zlKCWBX_5$8C0#R2Pa|%#VXU2299?%k!JCr)RKvtvr?o!X0oR)XwpGQ-K~<v5pt9dP zt>Tp=;o7|4X=QKK`jeg7RTqr;PU&yc0ony|Vny?Q?vy;Y$d2mjTNN-yyN&&kwDLdp zCj!{jrWz<GEg9C!+dr^maQ8~=Le{ihrz8R{(qr`g_bh?c@2B1;Q?+@oreAPt`mMl{ zVZLbGEB15Q7EJ(^<<BqLM=gGS7C2f4=yeMGTalgR^~>Z$0;fR#Dwh#j<*Z*y!w;r` z?lLZ~gA07d4`Cz~WRmDdVZ!@}G`sUSE>uQ5Y!grJbm<C6JE-j;?dI7Vh41U8wW4xw z7^R=~{5{c@J12JF)Up>frFml4^PXw-i>}J)%qUK?jl0bHcpcZbIDv5b`_K)_tE2V1 z6E&aXrLL7V_1+|Yqrz{g9wF1q^rbhlUh1t&yc6sVo@(UGRjUBK?~z?ijCy_d0ps=+ z`|zu`^IlpEbe4cGw^!BF{nvb!YdZdA8ulbF3OkujE$1OZl5?z|sC>>2ZT}|yvTA|8 zOFM9C=ts4%C#PeEKWWKSS2QlWHRrpk;=c5CvO>SIg&n#L+r6oMJ2UK8(&D}5hD5aC zE93v1^p>c&LcGb{z^%aDz+MI+d&(k9BtX%9>|q%q-gDuOA+CBOd_x3O2*S?^$aZW| z%j^+*0EZ1dBH4(P@rI=nmsA2v>|!ZZuRZMI0<c#s;{p!vG62>I!ed*#u)H$!+(;Ko z?BWOs(0qwq2GgbDdlH~;fC-v+VxaPP@!1LMJ$}lK+$?S*0kp4kmLSx>1XelCX<#GN z?>Z}-XMFJXBCs4X#*Y|;n{R#yBK8?Va47io=274<M>qn`XyGp5feskq1Is+1-++Z9 z3-8GnKpvC76mP=jQ=7ZhZ$N%WARmWIezUMDegT0B*pw-|I>;_|lQ8g|Wt9=IKioh* z#6A{5eW))m1pXP4-5~FiM;4BO_~6pFme>DI=m@y3QjFzkM)#l~Q6h)||M`ISAbd{Z zr?QCvX<&N#`F;wxZZi5q7HFQn4<>=_q^?Vt>1AvkX{LE;lt)f50%qScimgmdSY7%( zNgt2&m7mBVQ-FGv>$kGsn%Cv6C*}d$of3w4m;|8bG3(jfAGK2*X1+Refl;d7a*Jc6 zHt)-0;_qeqiZ{_uyNd+o%|c|wyn3vU`HtU<j!5@r;6<cGdFt9*dtYV;aGWehd%LOY zbK9Im*wr~6RgA?=f&4b{QXVj|ss7y*GjSLFEs1Ajr~O*x!0)G#XyG*k-rFWddnF0G zO%hUU0a$@$s=ZgxF3N&IwT_<%8l?W`B?zekKW_WH<|hCo?W9ueTKD~Bgj3SekCidp zs*?7TrRx*27UQz*NdR7r_D_$;b;rlDb-Fx;^QsdK&GJ^AT$nt!o_-z6e&<cBBgq2$ zE`E-aF!$>qe_d2KM!lm?(K?V56LCl!_$Py(NFD%Q_~C!RYa|K(#PPKsuM6bG&3+-J z!F1!Xw)2lRC;3Xc1BTCw%<3fTq7xWO=EovhqbNxp6w&?W`0CcAFs*ZKmH(+LP7S-X z9gVB}wwl_>#IiJQ*={oLc)wZc)h)2wX{`qYR_DxQ$Js7VCh&4jtdVoN&eO||ksjdQ zOD*}=|6=r*^WwG~Si51K*f~AFPc7(u`pyHu?^N-&U{PahWZnayzQ0UEsusG`)Z2Au z&V_egf|J_u?I>qzAF@Et+si|%DQnr;Vtc5&aPBp%ao&bqo%dA%%xzo3ToAKa=q_TC zuXD6=V*j$WJ<10COLgo;rU~4sSMF?ik`3Qvqi|wl@)LG%^1gWWZ{a*oWB|U&U*aux z)vAnv(RSI-er4?<Ao*471#vA`unhWvf>KE1x#@b8m#&#VH?K&Tvdy<9+ROt~gVGTY z`zg>7!1}3}xjl#(+()3F(68wg;25{D2jmq}iDzJQZPV92EPTFjyL<=aaW2<mR+^Xf z&n?<B0=h@`bckgJAa;qD#WCQI9M?Akmx+TcgY!%0!G*Vhk3$HuG?>zZ6c9Si<eo63 zCub7`@d`=;P**8HdqA>rHp0=0N#=MtVaI{--e^NTTh3^8Y7|<i6K{~q40C*xj*&3I zI~m|S26I30`-048z_`yb0POArgL~fhGR1h0@qJo+qdY~7?tY2^uS}wiV8`gsMgGB$ z(^ynPuPZZpZ|g&4?)f5#jJ9ZQR+L~ct(nxQ50STYy=j)wK%0cVS;Z5c^>eoV$n|XR zQw2aWITxCCD&qv%shtHAKua~FT9?<;ZK2I3ghp;d`%|?6n5vfDS3SQ9NMSywZtJ=Q zEu}g-!^@0=+Da9`v~K$bMqJj^e--Jgxt%-K3IBE0BdVCDC&wwLrX4A(epJ;<Oki@* z@Z`g^{nfLN?8$3Q$5Gevy+!LOUa3|m6ELdmqY5x>Ye%l-IuIf7)T~cnnJDCyw7)Ef zPi)4A;&zc%{-NmPf-*fytM$Zedpi~LMmKz}`TYms-;WCP@?mT*rv0c)d7V)6GOU?& zUj4WB0dmd%Q$TzIUi>#O;(RA_mYV&EVcSKz-hWc<5_4hz_X}H~i*lm0a@<kgyrw+C zB=>0|n%{nFF^^DNw6-wacy+qZb1m&sbym(~{noLsmxvOIo&>8CLb|YfSvu}^%dl^& zk2dpBXHst>+HX2nqaRPhp9EXbTb(J`joY7W-^=`%WG_2h{%YUSaB#XqN8Fs5u6KM* z7lyWSB0qZ%*W1a(Vb?n!cHH$*vlplI@bqT=i`qwrUW|62F4CUlY*U@hdjfznM?FbS zMgR4f1?Hu`b>|!IluBpMRMNgZWP|6|eV*G;zs9zmkoiy02D6uNt^I*a-!I&T_G4SG zSu(G8VTq1);*m1$lX3gyY$zW1cmC?au6yBMo%;KO>mPtVp`X{U0w;J(90%4}XB`-# zIKud7-!;%99CiaE95#S;RyhM~Fk}Pxif{OsF%S6=IL#qF1cnS50avky{Se*(yTvlQ zfOWlw11#f-y^NXU*FgV{S9lqCk8fE40+!hi+{Lx*172kxOCa_~jOJo5`xyhA17HO= zbL{9M*K#1EK|j{sm^p7Zdr1Jm*RYQpNCVQ(#E_mbu-FebRmb|>8#3NUjQInW@BkMN z4_IQEMPQLd7D<i-4}rVlI&R}$U_blV2i}=Wm3upIh=6qnZVc9cTm~*@4+@+c7k)0U z0PS#8e+FuxzR_>N=Aq4JHs1nym3&Ry0_+}_Q@_Q#d<)2sQT|Pia(T*5uHuN;4-7fY zA>c_~*WUr3=&SXO!2g`@_!juReu-7!2=8#7glS#H40%Be*oQ3eJ<X_|FurG*+Y>-~ z7O<Ya?|kO>AZ8j@nQ|n+_jLKv8{v6?`p72o%AYP*x}1<@ZjY{qNoIA&0GI~_z-He_ z+%U^!&hv_R)t!`n%;!brlbPoi&FS)=Kgk%ca^I8fb?Ns97QQ#{ImJxz)0p9mQq28* zY?C);?d(XcUk__06#$XBt8Y*U993JQPkX@UwBz^b0=sScTUYC4HYW$v)sJV{j$N#e z<ed-@SVZ>q5_1#AW7&cIxDDgrV!tA-^lrN@RR*k;E$z0-E@cP(z^w#E*8?(o9reo^ zz+|iErUB$_0fQ2((jcTozqTFUsu=b?YkPHaXOT?+=jC=@zAom}v=1+*AKNgnyKw?> zrTyu1<N?p^^x~z~1d7IqqILSb=T-No;`xTm(exy7L^W}RNq|sh*9r4`lCbR<ex^u2 zGNZ@1{vuB=j-gN2xL+DX4M*9G<Na|gz7WUzLF(@)RfqJtL)GZ+Yzc(1$$Dpzz0@oH z!1B7}WR_{iSIt&vy@GWG6@reT9DHBoN2BKsw^<A~$rRsheBv4{HS7I8*V>-iov31S zy_4usNAG*eLeH{!KZp}bepPb6YSfRmPa=@)&cBGr4}Q~;ebkMwZ0)>gUe`3?e?Tw2 z)RrFL-b*d{dw1={Kh46~Y&9UW=Qp3tK;Fyt^u(%TCY@g9wVii{c)j)Y($N050@ypR z^P*YlXP(BlY1Gf1p>LHl*4He`=T5<nXFdNZd4g!jsG)-nW|A^fjv_|sZXnohNBWHX zkXr&I$Xh6LjrvqA<P9id0&}eFYtVt6$}Q{Vll`PFkjez048oR=^zX!sTL4^f;h(<m zoq@mqc5T=CUeG6bQ9J~CO<%`R5X<5tu8Z$X0NW8$Y2F5J8c6Tc{wU6L|2v@X=R?p( zxt|M+H!|-GYi{0?2gL1a+1>=~W_i0O|5BNtkOg|1jO9Mj=BytxxceaA6HkaEz||ZS z_k-S}zf>;)kLkO)54e%XxDxau`Vaa`;58BOISCNio9JcP)><DYAn4!e4>$?p2DzUb zLEbDL<qqH(@fn|kbDe+xKlp#6LqNAk1Kjx)X{K~#Ft-O8;JOI_k2b0!;Ij#QcZ~Z( zfV~b3;JAwKQxosYd!A1MAeUs1JkOR#8jR~j!1w5PnR!oQmy=BDk$z;3y`}FCGVP~g z0K3ewJjc-Qq+MqL=_BJRNjboMWcgfE{K9pcdPmFq6+LZQ41Tr@=r-GpJ!M2M^B^|k zwk-_Eo6|Zr1=7?7y0(q`nyv%5wcj@#!lcNaypHtIcAdnl33%x$9(6nFPgVWXD;P)G z+LIZPIW^-W`-Ji0ky5rQv+N|HpeRl+X1KRM;kt?4RL3gao+Mc0H|w5UZR>x_^y**_ z<chAhIjK_BXg{wa4!8G@%F^G-g2V<@xPD}N;(?97GxbrowxORB9<@&X)1keHx{S+7 zKdL%s&M5`p7cr+-%?rx<OP*gXJCVVBe_3LOQ(-UWbMsC*$UAwlIKiR#J<*9SPZ{H{ z%o+b&qufqv{ZYby@3#X731{yA$N%P%C?57xado7XC;@q1nA;b_a;;A1@i8&Toh=_^ z_Jg|X(TfH4uh?ufhTD&yaw^Z=`Z#6QCl6PRr}l|pY76S)7TBTJupGg}e4tNopQW7_ zClZfaWze!-UPt-~N>ZmH59)W^PxIz)W%})<myV<dxc5@eXa2!|{U4s4!Hc$f!Fi_w zxBBTyZ!cvN?q25K&Sv|*-V4q`ydC2Sw}%8%I$Hf=wAby`?%OBknGUdiIwMHYhR1fC z7nLnk)vbS1d9~SX;<ds^KYO&Ut-R83-m5B(O0UmElCFUb1EC!d+@b!F?e+ZRbeI6= zZG5W3RFk*y?1pU-#Ee-Ij`9Eg;J?0U^%t<`j$KzSE`mHDuaZxKf8USm!IvOz<QlF5 zj<KK5fmK#n4VltiV1ofJ@B-Iz6|fO9vfsd76fg`K+&^O}{5;-jbaC)gf5)4j$zP8} zB(OB*W)?4sUvoQ%&v}iffg`-Z2zZsRxc~$#vWJ98eLsgd9JZ(euI31rrRMh+Smo=K zo|eQu4yNrukAIJ@Ulx1VLkx@-$2i4JBtYiN@%0!~Jl5}d)`UxPg!d?hB>SNr{IK3W zBVak+kR1cM7m@hDVEi|@W%Gs2Yk(sh<}k3xfB}d%#OLB|(3kNCz5;z*-_1RM&mwz4 z+#zliR{{Ym`g>p>SF!{g;xJ2q7c$B#p4IO%24G9zCBD=W^ppA~egVPy=41K|a9>@x zdEtBDzhtO?1^Q?DZXSf-fP350i+?9#0C~i49^^2trvcx|@8fTr2_SoTy$-(@<Ld%F z`MmUdb{p?Y1K6YIry1lU@0VtNPXX1nANO(dy%EED5c`01ITF8;v~L6)&rgsbbtrOD ze~kB=4D1o}dQu)T?=yY3UkUUWU$<DmD4+P3Ak>=-uP+}nf)Wo~28=h$RX3KGmXUT5 zvwf8;7LEzQOx74?!8h1%j%~kq#GIeby8P2V(bSxWb^)MPGi)c@6OLw0c;c1B_i9S| zC<4sQvOlSo@k`V9l<B=`93xxB5!FD-yz9Lh^_R8!N!9hu5+B@xF-|qKH!~g$I*L!b zP9#tTiR$&&4Wv~(-Xw7*KheEh{}q0+@?<!BhWvbhwaxlxIe=Q0GKLr1T{C-gE&JnS z;=NOQ+{$au<w|?XK7a4TeffZEx1i2d!2di3bXltRFrh$HJXa^zNlSlc(|(bk_bS>; z#RLb+iizGU90wdLJ()nepklnsOC(DZB_sqJ2~YAk!Rr6`<9g~{!|-20oRIFs1OZzW z*UWH7Bxa7j%X*$ruXIhvhe5*=Et<--Pl!@e(pTQRt<E@5)eb@GgoIg28F1OL>_h46 z1~v3Kj}jELK-f=&7uL68pDHF?dZuwX?E3!zGV7#O?do-AH?mQJL{K>o96$ABhY@!A ze%}}mZTD}TN`2Jx*Y1qQxLz(w=>hJ&)SIBb<-YWnpH5{!t+&K2>4AV{14h${W-s+7 zG8eBtdOPa<!1f8)dbzm7_Q=}akL{fCxt|}+kKgvTnVy3VnA4itTi13kTeOqvpr6Sa zD-K;90iI_5Ycg+jMLRvJiuyDM<acKu(>c1bnV(4*ud*A02?M*t`GnxHAMRRl|CT@f zXQRu0d=VC({>e3$J`UoSEb$A_=Xi=W;ODq_B!Fla#ds0kVHCb+{Ct@?bUJ-BxTKgt zQWnI63G>sK@om5On)^WP6<;y{jdm(*N~R9Eo&>H+%eGS!Ya`kI;21}6M@RRX0Lnl$ zzx9_D{vfe)6(7MpZr30NWc$fy{V8Wz0dXylaW(J=>kNSh#cf;;3%kWR`5s6mZqysF z`Ec-f@Br{8=kS30IaFHj_xTJ7JgR@k8Bl-Fw{aXc?^E}47qG!O0Pf;8aR+H2cT`>( z1HRMskOpIY1T0T6vg-^mUECI4cU!mxbX)lREFj)V0oSAVrI_8v=@KM>cvZkG9|6{# zuubnH%Q)|(fb*p4GYM?Zo-AO3S4IZ2d73FceP043H?2Ecj-+p8pPMdco^AW7>&wQf zpx`-^fbcA%ec70k1@t!^BZAy=_%)uOa>vtp%zvX9&$^133F`v%d)cXR+tvWjtLHV{ zSZ9-j>MnYyYt7W`bl#rr;-YRC(Cg~iZK;Q*<x>-ku+ypEBmlJA#M`Pkt_^VA)}HDz zsMcY;ZqmPHgZ>#bOqq!EHi%~{POJWDmb1zFNS(y@rhxrChU$9dk)7CUm7RK)c6YZm zfW4|bP1k?yfZ=)1kuBB{WrKAJnd8T**MFQ!ru4i-09yj0pa1|r`FvSXuSq+tv#v(G zE)kXY)`ET=`Wx}H@RwT)#z(vLwPJ>NL>)%`GN$@6M)gU%&93KoId*O)9;gz1CqQ<U zTTVB70^vUA-}-;J5;oPwt=vjFF+Mse%{P*kq!IU)>&b6?5^&uU4V*^v&AQ`w(|M(` zD8I7kXI;+YXCZ!v<?7-|#p7wSneCur{^rfyDnhe;gz5x4C!>#znUs9;{kDLAx3wL$ zv&QIzD9@Om*!Klx%rl+Rao*P7)L%c4me)C*tfSOVcyT6bS0_Pzqa*w5rI#rUX}w%b zvclT5jxVa5sP+!7msyL~xqa_UEAD}!y|j^_bwIOox6Au}HCsP6PyX8L?Q+Zg%XVT? zuQQ*Xr&v+VN&jfN!9MN&WWNwU-IFP7kEpKOZ&X}Qr<49zwDDE=JiTJ2Kd+(Q);n&W zSuxzGmWdx;PP;?^?9`FYF#z2aPRNEcwuImF2mO2a$1DEyvmbs2{;U4C!4dfBjeqg< zrFVe*Oq>vVLElQieIV`>Uvm)j6Zm`q{F?jN1^j_C_`n8htOF~Y=M-ZG_b~wedT|Bd zF=PW6@jZJPGnoVUA*1;y{2Q<l0+Pp9yrVznJP_~-4sb0;IRgBOW84C~h2(h>K<x?_ zI1eef@sXIJeXNfSPNnp=rq?okWrb6mO5J}>pJ6@qS&2~wNbIpYJZ@d#0*kop3fsW} zmRMo{c(}O0ZkAalVPaoonZ3X+mc=e$jS-(SW^i}F`DWqig>_(^!>q&Tj?w-f_W)mr zx5VWjelIR?6!?Vic^dRv>I;1v=<CH^eLpOml85DEAa9Y!<$a*P(!u8Ypik&?+yETm z7I6nj0>mDU=#N1xiu2-Ixa2zLDR~Cel73vD25~)yxE=VIcQ^y=VGp}VfaGZaIZQIR z`;cZxkAdJSz8^72U8hpO`81H+PoAgq7~M?(dyr*jpJ19d8RQe-y~+UfA(!br1tbq* zX8QE!biK)ZjsW2@mnkVK$Fc#KPyRi*-D5Jfn@JiGkl#!+35=&mikZ`;@#Z21^dkBK zzi>9BtmZ7Ein)!`@@V=zz`E-2`O}?KruAHJl#x@Y7diIVug}$ek6oPLZV_YqEaOQz z2kTQ!<KAhVDA*OjfZNggoAw*8#e2KZXAyI|EfJ3`P{piobdpvZe^MUj%1&D_C}8xh zTfU-x<S`xKif740Y2$xogML#t@!V}#9!lm{`D3!vxW6je69PofcUmUqoBh>oU`J&P z)OG#$B%oN;n)?+2<2?&Is|VaJw$Cy<uL3MLwGU~rK9bKcZuk74I)OvTl5wUekwjVA zOHc>|SC;b(75fJ-^^`)Q35pW{vH<z=#3HBi{_;dR^8|?^rg+m|MF|vM9G5ysSa@#n z%Uz!UtE>OR(cL+5nG?g?ryJMILb^<l>uP;}P;>sBB#c$hizG0t^v~^9Y?}gpi~8lX z2z|=R-$exEGFze+uOM#SsdyLL_#x<+@KaUz<D&U{(-W)$V;riA^DKebI*O~#6!gO> z?=Onzq{f%0?ALo-Trb-|dVqT`wM2iz3BH-*iE`eAXuC`-dg*27O_;YP5b*kb+)LlT ztnJn9RcWp7i(6zT_UK*Y{jN!@raCHlPPv7<?JO;+jhbP3oT=N@bQrh0*w~hhthOF= zn*IDPd!%VweLFQvRCH}I5JF9*U2XkScN+}KN*6^NGENHM?xa2sLSXekpAI)eJzU@m z4)F<a3%-6Ae)zi|f3tZDY<}^NKmYU3;otW5{`N2Lg<U8A@|QpT3eI2uuWwtu4RATj z>C|%*26s1RE_cIz;WOSajhW*~Hm=hf*a_!*@;6~UcaWeD=%4cm=)?LftAN7^amV;~ zeOvgRXe%>%o+59fT*iGT%j{*^k&MAg(X}d7E*U=`gSmd(LXlpQcF8i`JMrJ~M!JJ! zcR~B7fz(ksuj3F)pkLI-coA?ojspD-pK}^EzYShg&x3IERr&>x8{%DV4||f0eXp|4 z8t@A5>*FAQCk~4M_)fgX4Iu8~X<Xnzp3onW0KTJVn80!sYg-u%>=?}GSwMLNvJQ;z z)4=po#`i(0mg(#A%7t-Vnh`z?bSDL9he?2XVANj~Jm37Bu>42QO=~K7z6t1d4CZr5 zK7;!x_53_P<>$<T@)_Kf<py0)Ij1-ESZ5qCXC;26MNd9gH5f62Da9;Rv#e<W!bg3` zxg*3Y=+Co?$7ZoECky7k?d-VO5$J8>gi%GTGi^rBs`3p>$|0xPo=)cdvs-US*6HLF z>J?NlSr0oZe^vW<HT$=+Wc;s+f14&Ad(=IF!mj6xCK5qpqlEFI_Ux+PI2{A!@=i2p z0{m{v>|WK5bx(q<YIR$nmhDM(gTi$HyZ+*p^piRa>we4r<<wXYOD90MISC>~?ORsw zD*ZVY?N!CVU&l@+f%}d=RnnebifP<#e5<$qSJgfVK(U-@KMg1^drp;qnC$nm&@ZGD za{>#!OAEgl>0{mSk4by{yL^x;`zSTPQz^fn#Jl+=+o<TL^CIpx*)cQyTH^PAXcTWa z75*Rry#INs@lTV)T4~flPAT3hzh6!LMALjbn9dGQ-GtJu7d5l}C#PU7X{(Vm=8Ah+ zd6u@Qj8%;OUF$LNi^|&WrN!@F&G~mPy;y}0z4TH;#4dJmpw~m=iQB~@+a2iZ&5a&= z>1BF;Wv2r2`<czfH?CYv<F0$rwR`tHTFzB_s)l;$MxTQj)NvO2uDhTcY@rp%4*LJJ z{GsgvwpU_<%{Js6D?eAgaF@>%<ytSyIkn!~l%cch1$9|d@3#5~8Zy>71_PLrf`>bd z6BWil>p=``_kcy=;emKkTqRav;THLl`~z@Q+|P3mT)p{#8o;S9&OW~SGN=#KulNAe z`}#BwfqX#h<tq?hh<C&Tz+;@@X%M@4R~!T0)2rMCye@vpwZJk1yigwjW9IVY*!3|m zeq26h48&&<2N;Ddcr{mwBY?-r@R09Q_`rEq^%`TC+Fc}I-UxV~X0RTT0IZL5lCM)e z%|&vUB%$X<aWl83uD_Q3tdVREe8h*Dq@{D52sgsVEwGzI;`&s3EaBoYW^ngF9N{vq zAZBpaLA+6`QefvXuvtQI&F1enuK*5nm_y)waOpMfIoMoQ*Xy@o6#RJ5zZJNQ_gMyc zm)IxHgE}VuC{BP{R|9<v*dq?;H$b1!r@0Kcnt&nTa-Q!=(hJV9$_B6)e%`}?A@B-c zu>$;acC#1smz-b(JjpoWz&C*5CUbj`;y^bU-UHHra+SI!%k-Yd%%1ck6@ukWpu5U2 zqX!`b+hkNPdag2n_cDH8Fu~xS1?op_sd54D=I?PmbdbxqZk8*m&uGGj2C-jJxjt59 z05Xb6X7VgEyUdhB=6I|i$B$Jp=J}9G*vRvBWq^EB4_(dif(A@~(^yNAg?j5(u6mhf zyd-CC>$8Y&oEr1NX+|!}a{a|^@q9T2ZQC*j*L_3X1kt>!okn_cjB(zUKtR>foNXK; zY0e0)TG(w-0<vm(;+NOKIzU~ZXcPO7fN`#9djf&%bUm>N19uZ(oXNCp6R+B6swiQk z>AFf0K-zZwQdRV0Rluli-*?-2UAKaPyV(Bf0mIF9umRv#0i9*V^Q-!WtYH^kO?y-o zexsQ2ydEKjZTm%x{#Aqq=D6Wm`iWwIdiFh@5g+F1Q5LL+${c%BHJIULNj<94m(qSE z#Yq3x?ymparPly^{(QqQievNQ<9V6WwwXUVwd}Z=cs1rTj^+51p5sglXj}GNIfeOs z*@+F*m@f~Ezg6=vx1ip(C!iGD%e2lWR#V+KnZ^B1&G}3haZ;KI-LdHZv&NkSoe_j} z9mjUl-bo@`+r;y1t1Xs{LN@dGbi%xi-jWlyWWR#gOSi7QmtLwTl&<Y@9b4k?XEC5( zY(2OK?DsPLfVj7^`S9=a7Xb8j-pj0IngH@ySU}J>VaI;4-3I7(?Dw-Qv9m?~v8(xW z{c*0_jpp{{uE!kJ{C(vcNKQ>)hRNVxb<|{Dzf=ucstzNdoRa<3u{W=zd|maE^u|RV zL)Z9sCqDXjyfNv73$)`ci-8z#oh*+5<O}b}z2bUse|pJl3qCCT=L;XpXJGTd=23MH z{7ZiHf?MEU{wL?J{x{1Y|1)tD`{6HH{N~bK;C+ATE6&TX^w>|I`-}as@&2EVj~)S5 zaXAg*7Vh9GV8FM$1l+(;mH;<odiO)FrRcL80@Ixs@E-mZ<MQ7m2J8oJ;xqOF9^c2; zc^N&8f&5MgRgIoQ40Lu=hnkL=)yEre2}~&6Z=DHdGB?A-B;#^B@$W9+h_U`%{RM;6 z_fevO7X#m&Facm(t{~Klj2Yk)=J%B7-{^PrS>S2*au(!k@>k*z=#zXYt_5*gy)6C! z`YrvKUV(+@<-77bP!Fjy!37YHa-BE^&XaPV@F3VwujubmFNltw-h+z|e9s9^1F!Hs zr$KzcQ|t$BV=v2Of$EXAvyALPX0yg*WOq``>(PB<od*WMJIkz|u<K{v6Qr&VjORr2 zxHPcdPXXY~a>67-y9u061LhTz0Qvxvxm@KknLA={F7uoTJdZwk6Fxc!pC>1P>!hAH zzyv*Hnb#vfwpj4|Nc`N9FG*l2x^A&1uzeKUWip<r24ix%JQ9#vHM+n3{3r<RWc$ot z`;D=SCvIq7MmaYOagA(TOajf-7PW`8m`{2w`f^<$@GRDM5&%at?M^0WsG9G08rhX? zeASdtU=oO`3d^rrv~!|IRlD4_fOplh|KtHd>n0vd%I=JvCk)9=?O2wsceUw%vV(ZH zE#tTuf7;rwSFz4e*KR#aKWS?hPD^3~8+$CPpUNR3Xyd0n>-UxenDf?m>iGYv^(i-% z?pl?&VA`juu`ZOX6V&tb)mE-Ddhsfr7Z{dS#Eh>dV4_(D`LurR*3*gzDiZ%JEBtp= z|B)s3mR^0aCHlyFpE=JAKWlz+;;+60*tq`RTwi0HPRFZr80YB7ue><r7qulSnPn_0 zTm0U3el)H5e=>fwd*8I$#{|gwmXLbS;IA(xx{)p0#VMV42l0ubRq;nV{d$${Jl*KA zE$qDL<b~v~UHQE!^_P;w;W&c7+wS^W_GZhN-}GdGpzwrV)roh?o;ur0FD;#HFTL2v zmF$~1qIxGw4@kT?#O+nkSwPkI`(EZvyuLq9bwQ!`1Y2+4YN}drW@4Y)L1t0U$&Cbg zk@dQ6fDK-UOaQZNfuJ@slf7QMsC6A6dD#<HO(ss)!Vc;Izm=hPr?Ymq1MoLn;+=)R zjhMq#jdDc5E2p4coRG175Px<<fV&qmqaR=q*oDUc7S`pj<QZ^Skn$>U?sM*3aNs9* zy7xLygO;9q$qCrF;?GBa7{QPK?T>#59)y*b)@~eL3GS<xye6Lq=bt-|JBu)Q=qJnW z5fJ;tFXVX`y)e4rhc`gHB|hL8(6{S*c?EczR{^++y)k>V3j{)jHh7Xn#z5Kt^eg&x z{TXn(zLH-7x8ZRV#G~9Kjsi!-0ev$t#K#BDFys^o;Q1uSV@(CXKK652XpxFB5Ium9 zOC3(@lbj@BwmvWRvyo{J73*6uW{i)3?hbH`xSDGKmutrQ7uSkofH!7r=Y9R0ei;~q zO!lJ?;67jx4;J2W?ppW)^z-UT{Sk-*!Vzad?N={s{sA_xSC6T^z;F1LM_}QQyh{8M z{`|+yfqD&s{Q<$#FuLl8vp+r#&Sml=@i~ZZ^@HMBa1J_W7nVT1t3J_JfH<uW=-YrH zM|l?5#UZf=_?FMv1^V~;Jx+mE+`&V@CYSMZ;2FN-6mT=Etdao8M+U$>0-`$;fcGq5 z+&387Wz0~n3_!g3ydd*^U;yGx0J~2Dh))CDgB0VN$wZ&-lYvp5gwb6Y0QU&!oh`S_ z0mMf>AxP=Zlu_z^nGHrAO!$^`xs%UX&+ixd923AUbD87KF~nrb%R2%-4cJf08)V8^ z<(nfwc+gR*>4??1otls3`98kvIsU}FM0GZ{^wLY6`A#=+)#Uto-sWB9eKmZ$UdhyF zwB_yNl*X|mX2XP84d^HySDKWsj2Tc)q5a!3jkf`Y$p-z*FYLc^D*dfJ@F<F7x?S&z z5*oVd2R3oD)4_A<*1zg`4$YYBZLGU2A)$)7xynBT)||6N_O1%o7n<}hr^Y&m?6BR_ z>r-vsALR0ISKC`rxr^<p*dM6e{!*UEpj!BwCjQ$NXr09Sj@8U5us8`o=Cqd$VAqVx z^6!(4{D>-8Ka9Q~#r;^u`c^shaw^tWRUzZQ{raUO%}A><?+wCru(CKz#kwD_A58ni zo~@YIsww%WV!!1UM7GuQ!?X-6=TXsmc$cK0O-{1$rj*c|BzUMTwJT-xr+J81+Yr!r zDZ+_5?{VUIWYao+>2l2`N(5AKKhv%H^T4q0qIqpHKih0&$6F<JduQ9xU=Xi=_e|-% z>{#i+PQBC;eKU9IquZ>|+m%7Hm-(}!X-f~ZpLXEk%*}+Z_eeXh-*2^b^#Jx>>e)*^ z<JQi%BehLRS?@4k=c2XacB83R&>yx>`<K_N?R=vxaKL1~sxxxhF|SNAYt;c}7nQf} z#&%b8yeft>rfjcOJcCYA9rc}=^1DX-Ee)XiVhnJ1Ljd&{V7<%|1JJ+KXZ0Jvf5Dra z0sWS~RX+xNCteU&f?SpF$wy)NcR#)6C-;JWR)417f#DzjeB}=h!k?e~;kh5*g@5_( zf5+;5u=)Slyj|@F_dmJhnT7N4SO0A3%bz?A|Mac>-|l%8R&QOsYW;g~mKR*P0pc}& z%`Fhzu_@Il;1O{*R|9YHC1-&LxrP0}75X5rgIdz}>tn!G_~H}bcAjDYI4rUVIE)xE zUbtUmym9G62qPZ@V$+Q7(FSeAysm^hX8P8n35IuvWTW4U8P%ijy$l2UV4OgJ6GCs? zF>pO*ZjXTNZhW6)0378A3iNN)S9(8)--^q{?ci)UzgpM>JgI-V@E!Og|2h9P@ILU~ z^%mj3eeJ^He|Hz?Um)c-;NKP89Y~PpgfG4Vd5!!^Tp!l|S;jDb1@dWehmau8i-W=e z9^nI>Hn$BnSOcEtV@?83jJHI@zu*zB1hFJeatk<%Ki;-+@89SUSS}!Sq^km!Vy5aW z06b#GjeyE&rgcbw)r&dI>}kNbn*y8%5X0up>)r64=z0|ctCQ!Y8R(r9KtC#<0=&3B zSs=Wc0Kx}xe@&M^?FU02qw|>A6Yo9A^c|1@$VdEaf{8sUU%pQ>6OT+L_iR0!iP0n< ziaiOdQ8{ac$;O(WbG^;XaZpfh+q0Eyfb^05mOa<@In$nDry2fx>7}idG0@J}{N1)Z z&Q#Wsx}P69mA}qP|8@3t+$rg+Zrtg0Z2z`)@7C07+ql~4P>*fur5eU>9=8-S8mm@4 zBpYAmJ-1E7?>1b&Qz=Ht{5r|0_?HMs>efF0P8GIKRX>w8>`@tZR<|FSKqR-qA5;T~ z%K`GX2`qs%qiw$4Yyehy4CY1sy(%HYozRaRF@l!@6xXo>r@?xcjU5;HMHK^~>)EGc z>4!{x4=nt!EV*9gt^{T0FJ*~mD*W9%88u3rkR|@DXnjv+>?E-gC%1fd{YY6R7`O!x z#i+eyY)?-7S%P!_r6(@g1+0($X=U6RkR+sUH>m<x*I_d6V*Z;-yokrWLCN?WwdJf% zBI;ru*Jk{y8uxAMt0wxl)3DyE_IOynJ~Mvadd>O-BGib!VN2sk*Qo!j_N{^f3#>bT zcWcgb)x`W`XCS4T?$3EsZf(E8{IIS6>+w*%bSym>s+U?KzTpqz>5_$od63>w_R{r) zvX|*d59se@p8J2WL%hJCZ_;fo)3n1`TDUuB{d*ePRNJsV-i)lEib-j^*@avC`Ethg zXxHv)N{o6%y+hVa+^F`CSw<?ap;cA2Pgnh<>xAo~1@LK?&)kqT?~6A0k_}lIeis7W z#TanC90I8qQvmA$$ZO<1;%?x-<q#);8#u;65PLX-2YOB4qCW?5T0AXQLF|!ti8WYS zUHsZR0)P2m{`BNe?gsV$Qyc0F*!Zvhba-?*1pjRFGIav}{{OnR>rW@)!arYq>D2q+ z{x{D1@)`KI{+s0w{$d$^^7Bi-zT`y^Z;9Wr4B~ka$WP%fFZ}e5!Pl^PL4BaFf*;=v z?*H*l;C=nHS_MAfYrY0`mA;@~0I`S9ISTp(4)Q{%o3p?%uH$CLfc_D%&UsD%Ypik> z_?Ry_4Xo&MECYMR0WJevF}Cn)*vk^IpFOz1e)cf{{WLG>H$d#?a+ZNdxjF{4JHRSy ztOMWZZ~2A<c)f^X6}X&l*$?`8-sA%qd^<Soy#X7KY#bPV3Hk-T=GXAkU4L=ePws|) zdGg%V7w!W2kXYnikn7@c-iCj8Y<=TT?||oAy2pJ7^rzxZ@fdg?aQc$dpw`vb`W4_q zwYa$f3%7|k`8DVzex_Z<0QM2E$_f{N0qd*)Z}6=?19*(YLEu?#;V8(f#q+!j{CB*~ zx1iSbwLA;KtCxJX_|4ym80Z}Vf+GOCilO8tqj{E*++=u9`?ct~2{(N5ee!pb0Y1$T zp8(xeE)%;O1B7LU89vSU6r@Vw6)?(2z;*{ROzy5xj>xO}C_YG)(~b3zd>1`G(QZ;t zH}#w}(B9-za|!_D=JU;YL&D6ga_1BgK)_3tqipUQwYSs-fNYUJ&yy2O^|GNaF9(8; z3d&2(xmD3@wdv?Is)#X~o>tOUoSvs@?&DM0;Myvt#kPRr>eCvgGi&#0enL`yzw3rM z*j8Uv{jG{2yHd2Ob%ePT`HaElyjixiS=Eu1R{=g{<^4`4-m^-_K`C#teT`+#bDIF$ zRZWde5<JMt=QQarRlLfw;ktlZICqh?ZTS5hKa&SUZsW6^j@B8>{bnyt_^el+$>%id zb9s77_Z`=|9i&xT*_>ooR&FQ9E{mA4ZTgp&<A0>Zeacv`DH^A$lS+yixAXj%V+nYd zhM%)#DmLrk(kyYoD<FobI$<L{{z?nIdX{!mrEe_soZk;+#{U+*KS&WL<mo?QlrCzQ ze1e8aAZ}!rll@ATtb?fn#`yHfL1V&!qz8`I!~Q41g;f25H~~B`))}&=2}FP0IPQFY zTgMTD4(F$J5`MNy%zkN$qZ)J+c`RC-EHaHap{wUA>`tJVhF#VXH$|u+XKG*6-aqLw ze(t)Qv$CtY&-X3+ZPSE|Aoon%Br#S_x!!)w6Wo*e$3ksA*q!*(OE0y<?p}H+m#f81 zJl?Be>N4*R-RqmEmo1*a_F_(V`<Y2ETOauCq*8V1|LTZ)k=x@=KXJ$1a(lEp5_r4W zkvAoMOsk)FRd08T`;E!i-Sr4yGUvH9Yno>MQWgDDHmbkViRPyT#4Fq2tW$1tV<jl$ z<1bpsA9I`yV!J(t3wR80NdWGPA(Q*J9255dn|#L;fFClT2aNCmA0I#U`BwcrK8O?I zJN5x@@FL6LJiKs5-U@%UXKCMG+z8^ByoVQH^Pg;9p`HizQ}w<c!N#A5-k-05f4K7> zM}Phn{?&i}_ecM62<kF*wYmV8{4br`7v6-8|KP7K`{6#g^yW*RalQlnF^>Kg{^FfW z_c%jvA6|G)3_!oHzv5}oH*lDJ;GMnnkh>T3x<0}$K>bdi)R)2LQ^D^x&x5>IE{WfQ zenh{fS3o`^-<9_Rhgijf%{^*SJ;500yaDnFxg`Do@+PrYoCdxSC&dbg8`y^jKYky) zvw0)@#PROG^hwaa*N>}f;Lm4A(mxLBSL#c3BZz}yuh;;5RyhNI{``j*{JY@Cl^<UU zo`BW!YajpVR@k`bPcIMe1$k6>ya4Au*K2=&1$d8M`n2;rIPYF^o%06#WaZLlFZl{M z&3Vp%vp+baKLr1wA3xvpLH$wh(SHPSUhLMd0nh5|H{S*QE^qQC@Fhz;3+f5|rrrQ` zPVd%Z(BB>)Vc=R~5f{Y$;yU(#K8?>g(EkC?@(qY9_?|t$@7OQ)lLnRt8DMt=0{3HJ zca~v2Vrn;m?<xUG>-2_n1egyDru9jN_sQo)o9o%~sR@93#N3`OugWmD%gJ(P?vK1- z@|-LayJP$=jpz8r_vYtF(#-gIW2Gu!QpY$l+yrvVk|V`cj$a)WjL{}@Uc@+#I8bo? z-U$GY0ucK%_F46wD)B4k6tZL->|!JdET6j_4m$23?iX()Z_6;}%&DI09wqM1s9l;f z2=0sL@l`s?eXiJ78Xru`{!%^EO^7uUYP;}F(Y(0)y|PogayyQLZJ2JSvF>2QXxwDo z$!mFXnJSEenzf&;A9F3+$+o>cY=KfT11hezKUGjJr&T+8DgUGzSombZxYLQ<M)hhE z=gU$%ty>;hP*1zLQ<WWh7Iq>_?M+(0w`}}Y7Jx!Y7T~RF`Lk*wBw6AI>)MT1&|mT* zjmXaGC5q&iJ1792yO!&0QNorN$4ce(_X_-gdD4V~)QbEQD2ftlWWl;+o~5Nvgs=hL zc@r^gww_LWVnxQY{M+8{|MMjdaQ4spGYRiWf<+Yn`$n8Uj?jj2yx46dRukAOqWVAA zag1h9z%tz#e9`lx6EPw?Z#$22rc)0c+4G5l{y(jG-?a4JWPVJi{X=E?Uy<FK^N^|p z)@kWEeSe*kNy_GhUB<gk=)c^?1V!}{$-J8OG>Zg<E}uUyCsW(@U$=IOaxcA<xRYLb zsUv<orJi5u9btQ^nqc$?4R7s)e}3v|zf{+6F!p}Uc0#`0`@NduEq~SbpKW1B&F+)i zvd>&Bb`mX^_%rf%ZRR0rE^I*7dd5aPf9=i|W^?po@pvJv+E`7=F6wRUMohtO15K-n z$TR)EQN?@m7|4`GTRX;e_6z2IXMn<d#<jLq=ojjs9^kV0uzGXeBbhu>+=(~joVdPY zn;FI%e`Db8n8SF56Z$mp5ufug@Di&i&|h+rYk;p<WewPm!(L!9j7QFJP+Sk(qn}{} z{8qfqQP3lPtxtlup8euoa9&@yTmBlvozDH@KDhL4_k*844&s9N1y@7xe-9qrd>GV! zrhlWKg+IMAJT`g_{`A!_7_GwEbw6IU`3i7BxO@&jdDi{4d=dU)|D_KvEW!_0`rmBs zhTsKth58Nr<dAporTf9V`qH0W`Z}l^^oM#4g8jjx!2uA@@+N?@<g6^5gn#n<Uw^cF z9WH#Za`(SE1Htvdv%yP%&yaQaCm;Xy^6pPzW%T!VuKf-`oE2*j><cagZ@`Zq2EPpc z2;9d#@|U2|AE_^3c*mcA{lgu=5x!#t;x4Y>dSEXH7y);RKQe$zK66el?1P_fEZ#eK z1qM%gcmCyhkZ;N_#P`6L;{=6EjyMMvo&#}4e8s~c4(jLhvk<(zxp(vTAU+8m+`J!n zRy@f|;P3Ju3+@E@rTCS272G>6dEt_0Kz*;C-aG=EXEqOPN?;!z4sd|O>;aZJz)|34 z4zn9L!`C>VAJA{{9q4zsMc)rR!Cf2&ZfAqffeW0|XUPJ}(>5A}oaV{^ibnwP$lpu? z%@ct2S<-;=AakU+N&(IDnA}aEy9rPajQbtqIzMJ)&wd{mfc?qm1{pp02BW-6%_!5) zOMC4!Lww?|5<q$0IAt>6J2^o0GC=&u@F!^>9*_pamov2o1&r}Ue$g)|Pu1+jWOnyU z{JAO}jRULuMjg*jrp<tE%ShkL#U+yr%hR8S&)fP}8wS2<#l5xwgovqqnti#<KAJFD zcjGUc0U=f!#^Po@^MHp=tA0_=Fx*zZRe)J{O8wXtz^*JApR4>-oAqH?+J>^#x=)&c zxJ$nw3mA=?KEDX)Yg_Lez-;YtMOxUcTibuj+T%jr^MjWCs4jqOk`TZtTw^FpM5yy# z*}}fm1i-jn`&JVm<TE0B73C{Rm@2aKB7bZWKU6WjyA$I}`AHIP&iY!DgeG%5QZcYm zR-CFO^%<l6&W-<s@x3gaM+F5$97QJ<cqM)@Uym~P<O0Xgmm7W)on+{ZA<f$R$@#x> zfnejR)eR;R>2<UYad)_WkWQG+#^q6*c<G$RQ`=*wstTA{bpl9q|6+mm-J1T+HeL#9 zK;+w=TC^2$V3ofaRg`zT;&YlNaI~#&m7RLl*Ugqlswu<2${|#$7sn?pC1+swUESwS z5R*7Pp0bziDm}oxms+Ba>0jtacI<R^=gF)may_$qFIyQV_e}8@r?|cSZ@KjSZZ_k2 zo(wvE&vrTzY^T~?dP7rf3y#dKZx3a;QK+`5zUumWhiNf4)_ZE*4d0xFTw!ycm*M@b zey(k=syfPhUgEPNfRF0fP9r_KB^$7LOm2}+bHc3%C)|h`;Nk)9n895vjv3wc&Dvof z=##w89^eHI$AI23INlGzwE;db3O}cr-bbm=BZlF1BYe=$@*6$`@j4IS0&nseCxCld z=4x;bI<GH$4B}Bf;b(B^+sltF1|VMHNpT18g1Cx(AfDh}{Vj-J@hI1Ux7U$k12*3L z^SwWugoR@ZZ!O#ae>(N&=YRMH{`~gnx1-a*3fGF;VDknwQhOkHEBM*w<Dk!QPJaUb z@Yz4!J^U3gV8o5E`HFf+od?cvj&rc_(eV4xC%}#TnrlJ4Di*~@Ag>i~i{FBHQyk!S zSbAvj#Y?XO^@3j0F8qb}lXosX4e~m<CSM2nx^%^dfX_OsaLLQg2MgB$ijVjl^piZu z>%gkMgYQAVpbx8WL4Tlsp+5)Cvc#jnKE0nWK_AiI>fOMzJjZLm6XG*|3F1K>5{H0& zyvsMhSA5MGP><>j{acVXio3)gL7x#v!~oPQys9H+`5`c1e+Iz3iq8=Aw_MMgz+?J^ zcnQRR#5ejO5KH1Lw}PX7JhpM?-)P2L#UdV0Ws1o>0;Z=o-+cp6E)4*A1UUD?4doza zZl7dOPj5(@fcJ>GJ?g0u(_Ij6V5^wfDE<D3YQReY&9l$R0`y&jq1`nY<&%y2ERZ{T zpJOo6kK)f0jO^M>K#JZI0VRTre+_b>=q8|hlmakB?U$CMoTmTI0@?kPUoRUmB4EHM zXB@~YUy+Qs(HIX^Yo8nx{5yKStm)flL0aKYv~W-wzxP1*i#N`dR`IVhG0$vcFHVDU zI-S;A7MvJSJ->El(k?RYwRQmC8)jlJK`LRg-u$@j{987f*Sj6{3zbP9tzIX}i-YZ$ z6`h8f$i`(=?blS&afp-BZxyq@s_0{8xyzm>Yv^AZ<qmMfG=MBcfTExPh-qu@U7ggX zCgyw7Sxu>1-YO>fx=fR{_HE0QZwoN?ET2=Qf2X2tssO-=z01Oxb{&9w)rp10fO=Vb z-7Nwn*Xf5&{8w7}WwTT&C#EX1F;zmGB1_i6{CG`96|R@boVY1jXOpG<*{3M6Lgs#w z6LbIk>wFSM_^6yw8_1k;1~H&KKMrwI<EYGut7Jug8^!g^FRx0CqcV)Y$L~tYHD0TA zabeR3{t&J|1SARg(SH$R^dRg{P73f2lP7=4Ii)15yMDT8^tW`vf>Z0gO~<d<?zmR@ zoyE@M52u!IoSt2@n{SrIcX?|a$@?}tF8^lB_V1=8Jj*$rZ9Lm`+-o1_$(HfGDjl!t zoM<!)8FbYC>61wE;!wAtUu&8`U~m7u^wOfc_tHxZ5ij$Uc(Bz{!}b)f-)8BBK2f8W zrgpPE{Gr?T%U-sb$Sv(JvbWQV$bN#t4K&sF2OIkr?P5+(&sNV}kK0Y^pU>#6rc__2 zg{JDyA5;y7hzD}?;#z7=)zr6J(cibKUr&=yqt3><TjC${fbBudxGclXa%lkEJzQXE z3~=Yw5a|A;c#KCFZ}i*^>|zNQ*voGAhxdEHM;zxouo^PDD|Usz)DZ!&9zt=4AqTUA zA8vw<!p*=T>p;K;L&m^lA2`lBE^wdt8J7c}vd&51CT?Ii@SgsRRgf>pkyr)Sx#Y=( zv*5hHaKE@4mfyKVIWIzRbkkRNgZGK|JNE>zpFMmH9Ok_E3RvVSy$-y{8s~xUIL12Y zr}VA*XCNHb#A#q8-VZl-U3}nr_HsRNh}~hm23!r|aX#TP;8vdD2=JP?Ui=<dVT}>+ z7T<9YSm6R!0`KY5+zDJGuHZ6YMZczR1a9O;ZU$b^hxi4s$j2;#`c8kXKLZw7W*Nk3 z)>s3*&LWE-j&LCad5_o&`mDZ!R~ZBIF92sb!CBDP@Gu{N{=NQQp8@@xSl4d>-!T+7 zgBXg(cpt=~SQhsHd%03eV2!n~{l@>lf`crFcC`+C&sjD=yZUN=4S{>fyNe(GorpJr z)3EV0(|QDuOasy(3setMK4nnA_-<bB7y$S*!+3OknnB))H?&oT$vgqnlgj`<$YG{e zj2XnzKy|a+>F1@zH+~O{t-%5L%<c|~cbH`6_ENC?JSO-_&{dW}-ehz)x4WY9r1cvC z2(o~BGWD;LLF#&&F-02XYdc!!jrVEbeOs2OiTCMtfQV5J&||AMMY|m%gZ^a3IgVkJ zF>mjB-98YGbvZkY8z%gy-TS(>R#~&Wwv6i2U>KCS-^neBm4g)Xbk}y_6wK3Ag?{Sj zK$f(lY`HGhG?Cwik-CUkxB7ZJ`>DNtQ4lXVz&kDaVqL(mW330LQy-yn7?x#={$#uU zR-7=EPmolX(Y?xU-PB)MbA3^k=y*_2Pg{VXEU`<~z&|8}3bIyvI7T^a6Z1_#vb5Bn z+3udDf6Zfdtzv@B2m0r8rdK7<copj|dHzOL*n6HHs{ExgbRPk6tJ_Oj0pi>WKzZIe zRNhGj(ftGCIuj`A<=ig|#?LZF_oUpiwEj+NJ#VZ>HwL`Bu<+C+UkV2}yZY~qT+)f~ zejINHsd#)eqnV6tTo80j$YVP{><YN9ChRdyCom1YZhchQ6yQpZA1^vV$R-|>Gq&S0 zhIdsszs=4=x`>x$$+t}b)r%GLre3Q3Mppz>HqRMU&NH2v_>;VTYU_VzlW5dSFO||e zyIyLEeuG!^<1HpYTRW}krI%I%uIMw$E-rt!Re@)pPO~jV*fOxpzaQM0<8j}w>IS+r zVtU$%_OqR86fH1&^HvZ2N=v=Jx+VV2Z8l%*r2f;aSJ#Y&O&I3u*k@C}QnaDoH2}yf zDfes^?wg6zVqrGTq~sa(42=Hc7)LXw0q!0N(0vh43_#zYhx!+QHwI3}a8y48p!+c+ zbr1sBgOFX+#|J$Mf$UG=$Bgbn#<2D=v%4QMyN}`x!-xrf{QOb4u{Z|8`#Sty9M3Sp zj|dn6Z*rIc@FX9x3Su|EVjt-5xtgbe0gD8{UiNbZ@I9yWS-|B2-)7oygOea07smv^ zYwY77px6^LhMxsau?E29>|%VR^$-Q@;{dyWuQ|&Ka7PG*bwm9gW*>)vgX{xfQ5+&* zyiqy?HrQYTaKh_{;pa%!<Im&vTgPQ1b>9X<0>EX1RS@gqUG4zRaJT*?u*?QufqqM0 zq2B}f8}WrW0vzF>xCYe6ip|G>CGCgpc|)ihWdIDumNgjr68$A-SqJ`o&M*Wq6pF{d zdCq@m{l&l0A;4YWhvQ>lFt}p?!DS3cPqxg{0QVpUm}i;U&EHkLL7D}wI|hS#2#Al5 zB6kcRevsmn%LBMa&l{!QpY{zZ2Ea$}l^G`VbiK38<=LaqRRPdDFg#EMERXbO0?kz+ zpQD-paGQYmba^NJS+;zmoO0y><oya?Dhumf<s<Dp^T_g<PK}W(uzX)u9<CTKibvv$ zDaP`5NPXKd^6rE<&K{8SV59k8)46c{xUW9Y!s)2|RdGQbz+@M?vH>=>wIjEI9;)W= zO-krh+!b^ff5?)!*jB%F>*<v|zYX)Cn`580_dAs%Wcj**(@^^=r~FOZuLv;X)MO~1 zte;b=cduc&ZBOW{vNL7L$Zbnpk$#?CB1QKn8ssH(l|82p^Lx-RwcboLE7rTJNEUM% zd72{T(yB2fi2Lv4d#Vx?QsbN`c&}FF{ZOP&BDA&NGJ6dQ?6au9Q~~wen)aVMslw8Z zC)ej>$-0#){M{)9E>;2Mlka3H5H>m4LZ;Z-C#}^@y*Ha6Aj9w7a6Qc7_rM+ezb<_= zTy+SHb$|enT7~N@f6m1HUBzR0N#{-jzcj7&<5{ey%8Ku^{;lmiw@L#}>AFc*?V@Uq zmu>Yrm{JrS`SC%?2^HPMC2C41<=VwDi$?vL#&KRtKz-L*>Iwke6}f^prS>%E2hlir zwn6>;ocArp{h?cbT@*PaCqbx*1iopE8@=?>aG9u=UXs9Tz*1?J(RP)(N4fQKamrG! zf{V)EEp3~L)^tkQ&k*X#Vy}X!TK0C~&zsjd(oV^kR;`z#c3%5;(XPQ3FgJE{l%1MM ze^E0Z5$)>b)c_VubLKF~d}G&NRZII(mK&LM6Rz6;3EJp4=$I+6t=$DBN41*^n0Xth zD#hTQ2DrOp#wxrJNbTYY4_IP=2mD;zA?^d-<uqr2-|#gTfNMF%wZMgtvHd!(;>Pgv z3h1}_nqL9u*kA;l=K|}Df!7<rX)fRc8zGSW0z)KYz`Da2s6AxN{5}LmdJN}Y4`JO) z;opt$u;}M_i4Q>Epr6w3fPRwe#JwOc@Ei66pR<HR0`y&BB?P38HNB3^eBOnZVYyxl zf$K8fDE2e06fg|ImJyTpE)I|eKKl$wGlDxI6MP7#*DIV$wa<vxIL8=3?uPB<B>lm8 zXW_1e&w*u@SOVp!=hPao!H7lBU-AvBAg<)N_!i`w;xRD<9^e-7I$ZL$!@>yw4vRy; zr~3BbW8e&jI0$^p7rY93ppS7q=zaQ#ejLO#T+8>s+gv5~0`KxM1K>gZ8s7lVi*X{t z&Ftem=#%<JUWec&_ui#f|4yU;-dSL{p8}YxoZr(MiV;8^ih=6MePn>?K><_yDAn(L z;MVZ>k-;QSyuls)E_2`S7y$7=XTSFiX7~V%&nm-WH8OtpQ}50C36;CSt|kEHK_!4a z&BUJmKKs6W;CuAms{3Whb!B6P2_z^3oCl?TUQHZh-^C0eIjUYZx_^3ez0$YoQ6KL1 zQnDWBS@((U$%t472sWD)z|8Ztkq98V1VS{4tcv1QZwh*mY+Yh>SMRN|n<o86)@Zx7 z{nBk%?katICGmZ|b~0^RPNn}=F&x{z$Lv2QK)Q{c${O)#8IVhr_zSmVyK^eqqb@_I zTga&24(JsFfJHmT(5~#$X_$Cot{1pD^K)tG_sdRfDPp#FEr8^z<oCfu`(&@Wv7j8c z6wHhxpxUt#`>Zn#c?Ei|8sA*Y7(vDBICjtVDwz3AA_&LmF;yon6rBi}H?NX8ey>VT zjs@UeR*VPci38&k4W0P+<X`;t`Yy>gKrsC0f4ZA&f_xhAJ~R^5XBpQ`W8N9r)6nwz z#ffo774-jV0u?*I)oevLYX5-zb@H|+?Ns=Mc)tE^h2H%Z^NV@1qb}#kP3A==uzJwr z$XZ2xgE_MYFQ<P=ih=3TI5XIyep7VPK-&`t+=lJu&Z%GM<sx)0y<GI7ZxuH<KkM}{ zH_{*R(MvDPJg9FfUf)}%?9Y1rUQGSW-M0FZGwKgJOJqmT1-Ic5n$rMI$Zgi|yYSB! z+etV@8({MqnJdc$Zm-5z(1e-2>WI)h|B#kyppY^)x@O0OSVx>K@*>6hw?9HUyJ0C) zP<L=e7T~^w$L+v?0p1#VKVK~zT!a6OUgNW6P+ZF%5=N^awLzU`;8rPS_cY^G5Ceg; zpGh%wM*!dilAL_6Qh$TgUmu?U^fEW|3g``ei+&9_D~93$U>GsLhu057rgRkpl?R#4 zydi@OyRsj1P$#ua1KL9-d58hiqY#8U{(Y!N;q$`J;_4XGt5VlT?c;~f3-8xq`NbgI zijA%xh5&enVfc9%CJu~$KY+sk#O-1~U%|qQ3)hO{5G-##$uOmtAr2!@AE;gW0l;S; z_W>&*GyZCrh+xVE0ycmb#3Nh>;uG<ueh#>vcX$@WDe*l|g0uI>TQ~0e8yy0?McnHC z1Os{&=w8jFP96h$%FeQk=_<7`odwv(&(T53kEsHNcxk*h&A=X{`a|;lt+@bxKlUDx zolkC*r|X^g!65cJDr2Y00DhbA$pYm~ptv-i>!(J|ymI-5$Cm}=8cz7reAv19yu9m_ zaeclw4r<LWtLoWRY&I$!U*;pCJKWK8MmeKnV6;ykS50&Nn6;?ni28Q2f1A`lsL3?E z)$w8#<8mZN3_o#T>hsNdk&sQIv#iyQ%@Pf|O1M@rV`n`X)SS;ZP28RY-l|UQtZq9O z0a)v<=y($V%5E6<-9o!+zoL`{cy_a{m`)g19j^ZbF_hE3zc#U_^mApy=Shq8hARJ3 z)gEq5y-q&wmRjYk+drHFJ=*k(vXenn0YKfR-`n)_Nuq^(26@}WmpTmgCV;t#H%b9@ zg$*FrY>%pw4Dx{fvZCKg%YG{h+Skd6Gn6H>e9?T$Evc8xvEyO@d~xDH_Bl>P+soW5 zl(BA>#3V_AK$`eLhF3<P@4n=1R|3HgY9hgY{9NAvaVP5m)0*G5A%1BJs7&mj-iaAi zy)_w+H#_m0W{+;0h*l+a$N#$GwoH6$QZGsVdiyNmcDJ+k&mRxBK0b9i^8;<-g*GSp zOefx)Y_DL3cGq^^K1;DFhhLCT=+@k)yV&-Nd+9`afO{{sL@bJve6)ircrh`x_ZvLD zG!<{#_w(Lg^?s}Guk+f&R6jS}Hi2#vX>#;$@87zYV8TzxUY|5)(01p}KWuG1R0ZQv zku+rlwDpU{43FiBFKzv<xuHF;^S2^^dei#?gTZ|eGgqAw<0F~JK<UMhxqUGHD^}$* z;%(sX#Ydb34)8eF0avodVPKUNR)9zOj!%FUF0caPAiHouZ-l`4ee7iyV?ebF9A?OX zF;H6qd%{C(mtsKi3agBn(MLeQh*RO`b>KZ-*AD?3tg#LP@uhqL#GQQ3yC5FseSFYw z@C*H0;2C{_XT#?Nz!7mp#?D6g8BpdqR$0yHRk26{Om?&%mM;WWiz6Ypc?`+*;*Gnp zoZ*Z<M*`eG$f~$I_591k<y;-N5bW2laD;?m-{qT_G0_3`vy5WQ;65(@5+h*OnA_g@ zWZ@zC1q4@dxw-*(gs;T|Anp(c<$Ivt*Z1>l;HWsPUjpYk=T{2{A^0e`u=ynDHGNS0 z5m*+x^=@FuwFIEg@C9E3ce9~S03(KCFNimJglmAyxm-LA{I7Ukd!P^Mhxh{o$1eHy zr_SFAoH&ue$pFxU&_W}Y`iNo61ZD@ZZ*t;<h{#__5=QQ5!9HPhm+@yw0uXnMjcR2u z)%hr`QqPM3*DA%}KK?$bPr4k$-v=4LBf~9lKL+4u?InT%j8gvCAr1J?`t>44cfVjf zRt1qlU>q5pT&uzp5S)TjNFqHuxzCLfBNIk?#~5!^!BN$Y0nnfH*s5Rzlg52jbCm4+ zv*jCRN>l#+CL@Y00qTPt6MWq{*{s)K+^NiP0(Pcs&$w$^ad8nqZl2Z`r9~VwXsy?_ zC#T68eYBkxWP|sYl|!~@ji6y1<TV6Xs~QRXvQe)uN^q^mEL_}QtKu+O0Zg3)P{^9A z1G2_A*{nyU?M>EZinjr%r~Q{~P`)C)c@5WFf{Om?)vUiN^tF>|GP039SFazK{!v+$ z-zo7oX8)}-uBG)Dv`me6D;UhHo~H^4E$l{8v;1B~f3-bn&MZYy{SrT-ChAqzJ~@dp z!j4hDJdvQd9aJ0#N~?A;?XHU0!L<AQ@yujM_a<r}3++<nv{O<0coVUNoJg$BTA7?k z1TpW+vvap1A<M~WpUEgNFZRjyiy)4lv(cX$uM@=U2csy?&Js6dPhM+t5>}HDF3&D) z?XUn~Dk6aMyB606mGcEBod3?-&cEHbJZRaTb>pI0oj~l?m{+vXs(t-ct9jTq0pf~i zTzjgcIJ&F2J3TMjE<2Hq#kxUTeYsogw+1mVU3QwlUDfYYkM`+hI$g7uUM6Kl?cY4q z;ly~mNDsK{rCWRIMz#uQzTP+Cwh^0+uU@uSJJwx**tke_Ha$C6y+PIr&}Tb8>;vPb z?NqhV*Xz~B&$wHxvF40m`SZ&zy<OQxVV>V;Vu7}R60f#iWv%+v@sDlVbyoh)O})=< z!`3kv&Bp(&MGWpZ90FY7;Q`Abz<rqkgJr}$>gU0?%ZUFkS6^}%c*J0!4&tM|RlGr& z-LT9uZ>tF=_AFDj$#9))daBIz(qPmMpC^xr3*s>lKNDxgn3dbtk240ak2fOykm-EP zNG{_I$t=Kq4CYP5*9jy0_;)|c&>l0Kn~d(!?-@pRe1j2PrpgmBxCf~oqVV+?K<|nH z$;N8*92GOv`)Njdah<qYtbsfzPVgXX-n)7E=Ig*dM*J=;_Xrq;Ozke?&Ge<Po(EZC z5!lNzi%bG-_u#Pv;*a8ft^s|3k2ne1(?91^;A(LV*8>N5g<;BG5(e^Yy9X(tbNX{& zoD7iIU*vBRX0<#<_+a8aK>_o7)?OU~v5QHjc~w$Q!uJNoePMldRPHpBdXU2mPv-dv zk5P1@0jcYq6eD~3dueRAI|jph0GX2sqSj3V!&QzC^fR@e^oeHuie~OMJnQM__&L5_ zm5v4ZO!Z}Bhsj8v=VwPb-!>VeCmHHxP3HObbAhh7j(gc@t5n_3ciYat>dp{@8SERB z1M_T4U37H$bmAAUqWo&c_TZMhcNQ~ir@>of3+s&Z<F?RmlTx`2f&N&=9j<kG?Ggvv zhI*~j51QD&E%S8I`b5+IGpO`y&3dlW@T7#vxZlb6zoyK&s$@N<?Rr7Ygc4CF5#H^{ zPQ40XuC3ja0r%?w=ADM?E;98#$I73{-2PLguP6~@Py%RMHpbihexNE7SL&Q-SVS=4 zH1Mmkh8=nF+KE%hkShzuKUvZ~Zcch}-h8Vnp}|bBGV9}6>c^?ja{{E#KZ(ULp6eKl z{1Kr*$mIUl!@v69d*8#q3|9V?ACP4i4szlu^8~eeKG|mcsyDJWWo{qT_Pa^DIwjAG z^z9Yc3H(?(-*Js~k7<kTcvd}5Ppf>6RRTk?AC*(pOZSmy`SU!>awql9GXBfT{x|tN zhpoe_B>?rvgNZG%|E`}OOq~4U#Dp5EVLwq6CXmJn2q!J$dRxC5wU6J~2^jTf{dW6z zJ>IgH4whAV>7|a0!i~<0Pqs&`FLogQcFT-wE5qI;^>*CPE#_9HmC?P?tG4U@CfYD` zT|5y(v+>g3Hg@3bXbY%1a@y})pK@CLbuRQjD6oqnJ<fZ=jS2J^GV2osvKvsNj`~|r z%6rwmUk44j{Sv0NX}7NI<oQ9t6NADHzQ8C&#M~Z)3;S-&NG<_ijJMW@A>_fq!2|sO z-asM0DW7u+c#!=Bz*RV$16EjL6}XPexCXeu3TvQ$&eQrG-~~1q0xPVGbzmd>e1<iK zjDg%EV1)pW1UUPqeo_CDF;IL6DDk?u2UusFb-?2!_X6vzvIhEN{i^;9^b7osBftw> zU_XeDxrqay&+rXjGG=i1K^)S@IY|PbKPK+rvW#8$nIz&Rv4<rR!0)O)&FNIj?PZyR zVfzHYkYNbu9$(>wJv(9uzltllBGu2o=1aaN*^pglg$sZiGV3cG_NK<iQ>+jG%OMc{ zJjeA4aDa8O4>*P50_Z#SQGF}u-||bI1o4r$N!$RuAYS1C5Qlk$!@#Q?=WSrfH7teg z<b#mnEboB0T6p4d5La`hJ_<a_5wQ<A!ME%J{k(pklb~M$eK&9mhxiQmTz|!JV1@TN zN1Dkz+4#)^q6ayE_vpTWe1LqGNi7I<pAVo9K&OH3>GuaY<uuEa2BPOZ$2WlJ>F1v{ z>XX)knaGihwaJm^>FfMdf6v=cHv#Gi&^<7K<}&l1glWB;7t>FrsHE?k^lz%v_c@k8 zbhAFbrI#%N+WR#}cv+J%+)OyIA1!9PE;dabbk%Cq?1A&sn$LIfBxeWdBQLJ$j?vJW zYW!L^5mmJSvUIWjrdk56ZSA@Z&{%d-mT4ynm_Xoe5(J9uqbhNuF0*+8WUpsgLCur| zuZ16J0_blNk4AugRZ_mymhEZ+KD+7%PMql6lzCK^>a%WnO#k9E?tfCBDX}Np`c~P4 zxsJ7Fy)LS(7;Nj<;}~!%Gbdl!wu5Z~{v;5;8RM@q0P*V;?@>7?N7=o{sWsk~0j~4P zSL|=|*XN4II~D0cNQ?2#wH%L~g7#E7<DD$^Z$*s#iT`j6KbWVVJf{6}J!jwR6`YXa zO!$rDxiU4LyId0ft}+SVHgR4yL3}prxnaFUWKVZZ_%T_SDA8sHqhe<K>CCUp=Oy-2 zMI6)igzN0ON!|K12a<2?{+KE_0m3aD*S0QxFQ2!m*72+?_5b<LDzZEC`^kB7v-zpt zGD0u1w?!i*Evm0Kr|UKKab~iS=G2teC$g)(<%xP@Sty-P<(=>&bM3L0UTRAZLhGfL z=)2_2&RrIcb@l^DFY_Qhb81`t_0r4i0<E?(%?-HT6ZA4mxue7WQ#B6mWNVi@suy-! z8}}k@r&-Sn-I>*^?uKf2kg2*1Ty^R*t<lGJqrWRg7Pn*jE84L1m`_m^^|xJkwE>P4 zF<+(cPctTsKaT;_0|w#WTNnVl7~rj;&WleL4y?iVoa4eWNcM6dHG;|%<GM6HLmCJi z7|h6725iRw`r7y}Gf_x^KB6DgAA`PJudxrrdGTEaEZ{>1$gENf+G&ud`B{Zqk^vaZ z@g^`j+3*bFC*?7S6Te?(u8TG#v(HhPk|uxC0OKHaeFX5{$8rc*_gG@gRPO`Bm;pXu z%na|NKrYEs@+nXQ73i}dALmx_6v&Un9WmrPJ$Kp&6A+%~Q%(aew{iq{MLfu15Z8(a z_$4^!e!S`*-})OJZU~APC~UTaA2YO*tG6^WIurxq9RuJV<S?+`!X$&c9|P4RK)E#R zWc*y2IeQ=hW;?0tB6|+V0^Bj|Oy%?wnFCaZG~;??&&oI&J}`jkSzxw#lz8-g8i*Y* z3FHnYj-b!yUQgbe51CE_^vy9N?|CMZeU*=NjQW&~Q8vu)(@G3=N+JK#W2Bqb+@c4f z_i<L6dHJl?zv=={XLVAhJEivMx*f`xo~PB`dB8z;i}Yf)i#H{G7p=!O1&|a0ZmO6E z-G)ruc|dljMZc}PKJ6F)ob`s!EoMkol_emaOEvRnvVlJ+Dz9s4&u#pdZ1B7yyL2n; zvVK34ajSH(u3^rHy-G_c9*>lv$0lpjK_NiZj#!`yK<8P!KTl6i;T+VC5xy?KyJ%gd z4kM|P@q6`7R`GKDiVe`eE<=8#??Fj<ZqBg}w=y=c8(+=#&TA)G&>oWFL?^Fe9n!0? z_oRQzTs!yT?`1C2wKH+Tin)H~AmQJ6^e^FU*nI6rcs%u-VL?1pH|}z+`+fI2SxteR zPK)uncs%STt~8mR^BCft8uwS}L6!JT*-*c-hJUC#&j}2Ro457!s`|S*e#y>{I+pJ* zZ~vg99j~T9_5u-$;eAinp5L_VzvlQmn1Ovb4f<=9euFLCO|Lq!rp^7c98Y?=Xr(u% zUg`~4Pw{i^-qMLi51{U)-o(3?UW#O}g?8J`bNVrSo+kdi)SZE<sc63+7k0L7+XnvL zMb>_8?Y`^zwYS6cIqmV*&0#K(bKJw-+V<ykIv+BRBA!M<ie&!c&OAn`Y58zz@qV}P zNb_v@+<0Tp2{-V@0QczcZUzhhmn8-uE*C!+zXuL-m;=DA+`&zN&$}^0wF>WdQhz-L z;YkV#5BNfV%4fhv$ZUQ@uX6(M@fiVucqwCtd&PbZ03$tSc>k6a{XH-Y8Qd=i@l;rk z5wL_Ce!mwV*fVB|*Pn5UlfVg9SO-Rov=4fnHSve!ed4fwoA*+>TSoFt@=<@o3j0&n zFLRc&Bn<FhhfL)W!2B|Co+rYQG6FVlkN~bnY=oc3?XaTHb1H0=@h0tSal4J%X&}7u z-!M5LWZn<|F0(sKOxVQ$g2y*MQa1q4ae+k;mx&RlfmIIkC~%t7oCkdZheZfZ22XDu z1+EuI_zdJL@(yt`sAtsOVgP&vdaM_h5pbFnJpx83u>>6DAiF`lBySQQ1OF9=wGZ0U zNBK1bhc0>Vr|17pWMKLxkUh)5o&eR;z;r)mdQ+i(f*A0g&(t22CL*X*LPnM`Ug@-b z2Prsv8nEuC5*A23KMmkdCvqqfAUm1wRW7hS0jx)TI{QA8(cFAr@{arsci&)akHjw= zi}Qi<q{<5k(A_LY5kovieN8D!e6a;qk1C#TJ0=Dbyo1x>J}&}9_%j5O_mK5owmMdI zEl$3fr<q|jquSQ!w+K)+t9Y^Q{N1Hnpm<$7DL#t69gwK1eX9UnY2Zd1psrI`zixmN zUOZo_4|pyIGC7_40hIzichN746Panm=&mdom~F>wWy$dGRkTlCJFjA<uWMgL@wTc7 za4V{J1ZZo{NKd6*)nO=i8{4;2P(S<k+c3l{%Xak&{aShA*<@mZECilA#{5Cm^b@kc z9*p;to;WLO0u`MUEV~@oCQJLj`TQy%df9Vj4SOhKqBl<jumz^eoOaA>zw~>H>{}Kx z&^ra|m`>(ok@U%yGF6YKFFEnkkAb`V|8V0aiWAY(@oke61L{iMlWV-1e$%b+2W9h@ zGEe6k@%q-!=i33xyLf&V;!Uai_2UIO_4b&S9XO5Rfo{udoABYyxF5J3uNHY7>r+`L zGED2_gXylbBnepawSLpfMJ+uzu9sS(U*o;ZMr@bTJG@?cnf1iE?{%{jcbjh8_JHBG z`g7){9WN#s^!=yz_j3{v$-Z4I#>aMA-Ra|$Y`K9tJ<s7xFoAVhzN({?+s?1LK61YL zeX<k3G41}P8g4ulZ8SPDlUKy}?u4vy9xkxVA_EYMW1zc!Q{So|23)=s&yWCnl>x+! zHuQp=cdF7kP{i~eO#Gf^Om`-LyyRYgH3yNvmEl%e5O0_!0Od5$H~|Y~fy0VPhWNbu zF&M}(-V?;n3?_ii+2<vIAeB?zG=$pxJ_1Zf<rx1B^q4(di2*RgXUI6AAPE1CLBoEA z@jcK%*rs>JOyyDgMD3m4h>Q{=u3#T~Kn(B*fWPGw>mbgF&v_c0mw$ZZAH2WOA=9~- zU^)*B2LIU3v@)2@nE<q>pJOt;n?U!V00^&A%=gjf-={1yC}5mV1JKjYOWTvl>>iM1 zGMD55;e&}21=9T~%`l$r7x^b81QWhIpP^h%yf+`vT^FD}jP0cuU>+qfnEt>fc2W%z zb<=O~EoXo-$H&>eO@j6-%CW^FoOY$rBYN3}A{x%8^!8!=%3T2xZpqbZDy8Tq#&xYz zduFrprHr>tW1Y1LFwCYLUCi%;iUfi|2l}l8EN%+WuWL1Rdx<JN1E7AK)MVYp1_;uY zNwWxe+O#*8F~ZvDLDejGmnTR#VA<;R*6S4cCnz*yAeN2nujsv#Cp}2(xolOtHUTmf zwWsX~6ipf4g9;||B0>pe!Qk&ud}5ugp3{usvZnudu7RI$EfdYm-<vYLdlltLCrmjO z<7FPhdpV$9POQ7-ClHha<V`Co(wkGFsd4ha<h;otNx;do18Mj#2}mI`K=%><;X-lW zOXAx3nGIK;EI~s*DogxJq!Ygqa6esOdC|OWTF<FE`KQiFo_6E?bY}goWjol6!%pg2 zufji<*%KDyN|6k<U`M`9!rb)yfvlycqWP$Ka!ImgYo1i&v`!3hW)NqWwO8H=B~HtI zrCF_~1gXUDUV535^Z@r>>dD9YL;c%rQq~?a)Jre(Df2$Dakoi1x1;oadHc8DtO6mg zSN9I}|4kP#yYU}hukS4$U)2`rp*se=S&W0T1X6cVey3(_yJD7br|_OUW;SO^?cAh4 zs~OpoO=6CUpFeptcZN|;ND*y3Mhx!b4L%PKh=A=Mv&bTFfkT`IKI02c0k7cj6>uNx z90pccWd%6H1r7tNtg-=|<s1O(tTP1GLqPRL$U(f$IzBOjyZ$5Z=y!l28;n3atTzZ4 zGoAauBFo~kus>}8K11#R6hkENHgEG4@H%gC4)}y!Tn*wl$2bDK&SJ<oJ_hxE&DVTK znmPMM_NDB27rWS#s7)*qupe~7BDRs*6orH05R0+SVZa4(J!6LK@#pjU)3Bu!aFTPJ zBiRHv$r;X*Y|xIv>yjh6RR-9-7V3|2ot$SEZd~{T*v~#bhTspu7is|dsJ=?y4*XhQ z#ls*Re#1Q=e#URO3OLFkaTuImI=@?Z33#6qyamB(aBy=!sKfd}{V9mwir<Kj!1>hi z7A}X)bN=;uFYp$hFaTcWbIyUfOMRv91n%KMJ_h|M_wXtN2QRsE>BYYjDZqD@89hn_ z@Z<J~e!o4o^yv4oA5f{}fi#o4N~Him5Z<8-AiJNss*KTH8BFcwXU71tM*wptX6h$? zPaZ?NN-@<3q?yK51~@NM2@j@EP3tik2Lb~yo@H#ucrGd1RXHBpWTbO+7E(S+`KdJ1 zyP4oJiv4&{z{pOl-+JS$YQ)TL!e~Yr9>Mxj#Sp)5Mr$;(;oW;{&u_A_zYndprR=Vp zKjur*_MS#O)Z~dx%OAAdpl|8}su{lJO!QXl|Kt`iEIL;D=@KxKw+`pk04lWwnnwT= z)zGdapoE<^+}irHOMG{y;3s71bDd7?!O3C#?W+HD)j!jKQMaa_v1t!kGoF<eeyZtu zOHcu!w>_CpRRR_5%BgDlLDy10b=Mbyn!xSE4xNVWP?d;L4xo1}%Uk3Zs!r0Y%PgM; zUMq`so3tZU>Gve{PefG}K=0_ePRV+l%pE_g^^h$`dHvJzRbGOROZf>5ZYmme$WMHb zsc|=NUM5LS0#b$Jnl#Fhy)Su|4D0c;w0@TlFaO6#_*dsv|Jmr<+_nfB`?b9G_hx*8 zZqWMVlx}AHGPb{<bRMqa_04E~$bQ}{XBM$EpZ|H5?PJrfs)7B~nK#Ks^_4pc`=Lrs zSZ&gBZq2)9O*|FZ<6_HJjQres$9`*C{%|Krj}z*pbvWBgFEvE}oM(8k*TY3CJ(F`U zZ70^-NxT;Qq?esB$)0Bm4lYt}Jm~x1Ovm}1&M@w7yY|@{2IyJne^!9tHe<q8M(o?+ zBml32@u|tev|CdHs-+%1W_zUMwA$C9DYL#T=+BcIb^xw^M!!h1QRj@8%Ee*`a9<iT zxU)F^tMAiqX$ky;KE;~=+*hijAoZ^z#`Uya`mwE<9O%jS>FbiQQRS6GU#lPEL(u5m ztO1DkxWAF@tAfvy2c>73-c{yb3BWfCP>#M&Z5-?HP9Y7wDah4M83TFvS3E4P6T5(; z!WCD7Jht$V`~*1k;~uUF@AHY7#nr>=6@3Qub$UN<184LfxC=PLv$>mu8+iDj*YzE| z3;JI1xp*4HW8A9m0db9ZhZn$E{qg9=<$t5Y(uoX%c^Vk54B&Y5PCvtGKfW(p-{jXI z=Xr^q0-a@cR~f*)33&HY`cDI|ofMOMkg?-@rud}2f?Pm)(RJqUrahT}^faS;RIi9J zE&80cpDMt4(S2|<ZWqWusUh7D%3$AVhI_w8|5TROmjl|1$39iVKNQ_REk<+MfU~}i z_%n#$`WSKgYbV{u3A35ssu=;L*DL1FMe%r-@nM~HfU1pt+x60*B|~*r@nzTZ>5ZD} z3|*h(RP}zR<HU${%7L8K_Hd+8y9YT;`EBY|1XS}{GVoUcQJR)J4GfbF`lHH;B&HKD zO3U}#ug9eUxpja?d4N$<`|Az+otx92yXa>{y>+9ZJ>~(&W$iL0jHs^Vcvj_i-J12t z11hIwm^;TWTd%0HOF40(nq$?^WNANjCfd_3ai#i11*fz=UMgy{J=sB$0KS8ocH~%| zSy6nQDr8I#>mh7_#*==;$<;?%k7<T^Goi~&;Bd%4Ng*#WMdtPcIq`j(LEe0y8?U3q z-#Ra6`a$*h)x`;3p5=IF<6EliN!E&lo6UD+9EaM~C$Kn6Mq2qbS+TA<o2b?P#FeHe z!Z;1iyqkU8S-fx5?k&ZM5moa=YOPbvi*%I`VPi*CCz3c*=m%~4eGs;6-F-^WIA7Hq z7i{D3v|jvF`wR-k#VQ{j`LD(BzSVv?te4qK4{-0Lp0B=AEQ$kjRG=Pk-Agaq%!%|W zD4npIfx*toB<|b4@4w{>3R@v=4|muWGArh~ss)9eH}1%}^an}*Y(MVIn}3p9su$T> zpRz?cyGYC`-ynBdw|||ZvdjE}oM}HcrP&&f)382yj8D>da<n0r0=RQ!2yh>a8QfVO z1Ki~&;<xe_z<(?*=OD0`C%GKBjL+BuT)<@!_=?>uF;097fF%Z82;V(sO<&_I;IqLH z7;=H*z=%<}pnHL@0i{QbfPs`_c2zyZ0d_HnkI){oel5lIa)EofhwDIGDW2jK@QgUc zF5qsi<`nQ9SF;3+@EHQTxQs>8fa++Wd93$Q3X&T^njH|)^7n3*GQjgexP=gX{)W%> zCnP}UL+sD6U^}7Sq|rZR4E*<FhVtwd?f7}SSj1tRh#(=jZ}Y9q8-RW66??(?<HEi2 zE8sRx1Nct_H>e}P2Cs8F=y&k=4miRQ{T*<c{d^93nWOp^(6CRBfV;$gE(iU&dP3g} z!IQz^&0WAAzSAE8D{P3pz)RwukP-f6hQN26;|kEb^=_Vq&9^VP?x$D(onRDhAV>p% zu5uXE$9f>m%&x;$5h3HbE&{eEK=0)HsE1s|B)~ldfRBOeS*G@UAbkQ5&u54a3}Ctm zl$S68v?qLS`n~D;K(e9YOaS9mfnSKrq4SvBO}{fr`I>Zl1O>j_1YG+Q2_jh^X(p@` z`Mc4CUkt3ql(e0-8HE!D{GioXhM~_q{pHnnE9O{TNS*ETHs#)K8_lztZ&%L~=4TaX z8YhA&YhKCO%@4}}6<w`=sMhy8h4X7UMSWBOE~a(jTTqiR+ih4s)vz7Cnp#&40lrO` zkL&cOqW;-7F7zq@X{mCFdiv-#!6qn4IFJpWSBDY5X_`P4khkgjpl2{U+xj6@*e_Lu zJvxo-x9PZ2*3YD!y;k@kS?l_u{_HhOfWTl7cPr}AWZkCBp7Pqe447VZ5=s>yy=Xnf z)*jM)?y^R^yERXoaIArKljDoD@H1YCKe{sYoXLcR@`Q>a{YME%MS%V)yK@Wf3knE1 zLO(4GAiNICC!&)(l6hNV-xBsZyCg3Iw++>BT!x=!PBt5by7w&O!dc9(r$rDlOJ?_` z<B`{Jp66D~p-frKndeF?KSxEs$pT~Rw6oKZe(UIOr{fP2Yt~lv?%Mj5<$SnqJQGx& zY!m&yY24>_(ogHmC!5B%)3Jx?+xu+#Q;!<zrBS%kOE1=<f6p7d*XyB|IhVQ%_G*iK zVGpb9WmeKp5p4p)*@)M=yuDn^{cBzs)!mEU3RJ;D{d~q+Ud2Yu)@!pIsx)s4mTtwy z>2~Yqu0{LI!cQiQansR9kUC0Twra20jvnq7*?-v)-DL~u(FUkQh5%_d1dfjZ?#m&- zeGoFZzs*oT2OMCZ_&so%EJL)KcuxZ89fPwoCDqZ!>V0GxyfK~`q@I`lt%~jH9e%@& zAb!m$b_4MC7~*Z%M__yxq^uwdY|m#-Ppn2|fbJ^Z096_Ns2u%d8QkM1=;-^;QW{WW zV6qNS!UOSC2&7IR%_d{{n34T?{h?j~-s2tahRv@xZ&#PY!ciH>mtpgO8miwU*UP8G zZDJYp*W!>EfWC__0C+64m-8e{YNYICHy#7vk7K>-cln-W5V!Ld$6(=}A8+}G)xXgp zU|Ylh=%4`b9_TECdIa?TdHDOi@!v_N_B5bf8cgexfcSD?d-{5x1YjMNE00+|?|#R4 ze`0q*Y=7zg5*WaBX}mWLj8EIGZ}cY_+k0}|FO28qdC)uta+AqD-G0gY@`2!0O!1L_ zsMw?x1`t4}Pk<n&Usg#3IB;5w^s02+3^Mhf*Vxjr;1L|#SHFsJF^Mh1@jS#=-2mlP z>-x<0DEP7G^O((UVl_Z7^Q)-29-*fkPYQQx?NA@s+s1xu<36VaLwTKYd6ngD7C*Yy zc3BLFj(&NdV!dD*e$Acemv#)1_6)B1@nGA2lmIuo^@BFOq%Kf9YGbE^a^^8Qw<)g; zQ@X96cN+AQx~q$B4gX%oh@Mw|TmM*xLA}Tir2*4*=R1yNzb~@ydW^PCm_VXx`Gcaw zxMCosW3^sY1!z}Pp9E0Wev{>ug?3c*9>=g(Rq~uP06nigWWo3M#=ppTy$ay&c>OGU zSM;9fgqGkE={SJ=;V<}IjvbZ(+NW{SsaMc`fsv@9D#m@UV*Rm>f6RNI%AX~OXnwm< zqBDnP`?~q%uuDX;_usbjy5^^O=KIrZy?hIQYV+>Jf^oR3c~lY8_pES2DjZR#9m}~D z`d60i*HygGbRN2$*EgEPcV0}u;uzzBoeZpJj9Gh}wRk<!rI+T?1KfM5CvWLj^&`C+ zcBJ%MM>|h~zEyk4ojCR~5B@Re=U`J`D%jcpcDrb4wnv6vto_}sX^~wnsL6{+|8fRB zUv6oCO*ZURslCZ9saMrTq+6q&UHUE0dO>kIdUHE#f4RkWmp_lJ+7OoEg6v|vQRm{4 z0Ni(lT;#hLun2sl$Bfs1%^|J@Ugk}{0PzG*h<89=V3k$icdYUaaDjCK;2aw$V1o^O z(C67;1gwldv%)GP#*FGdFk-+m5QuR(&gwI403*&Z0u-ZggKHSJ;}91ZF=lxGJ<stv z@OwsVfc}Pq+z5=gmczhd_KAJKkdYpR<r_bDY>yXMVU1*?W`hf9V7xw!Vt4BLUHGgM z1Bb=OT+a2O<tpGcHn>0nNWNYi6Az^B55@@uacicJoR`1>_OOpJ)4L1eFnh%jz-7Q; z;3h8M0K>2yPjZ3L__H1XXE`T60d5{AD2e@?=Pi)m$R+VH$eZ*X;wF%<O1ZEHxKgid zu7dEyiueZP3Hg<{6E+{-d{W#D+S5nX?|}QoZEOI$#c6Q>cuT*?BJhxYo$r8~#K-s` z9^z&WfWCu=cmslKFM0GYpZhz3B+zLf`6#we6*GB{!QPL=+BBKZ$9kG%U{3?vBfz*S z0l=q$<q_07{hl-c9^?I!jO>8{Xb)mQaQZnB06a=!NC4~kjPE8KJTOica8MaW^yFx7 zm79p+rxFSzX<&RY06nUA0+!G7FF^@sdzwK%e@uz$aeamVyTM2hxS?`PC<nUx)?<gN zHNWv|j;+oVW=nPe|LM-s<kX+vpRhL%^A@iIz)LslIo$#%-Kn*soJ!wzJLyr~+2IYA zHICZt`YG9kms6f}f9SH`<pcJdmMv@h?)E3_IR$=0mBbx&ExHafvrYRHCE_Ox<aG&` z>M^)`4edxZ@ISJH_}H76pUF-<lw*0fJ%GO(;C|l8ylu)=w7%k4Ca_cyM|ceq%bGBq zm+gPpGI!h5*DGj;YNmQsx~@^xer`>>Rz~~UGZD*)ejpq87ca&4Eld1c9@Dvvf2F`5 z2J!QiHBda?{+$Z{Fj?<Bz;zK2KWUeIe_M8<fFzv|C@0=)+I#x?s7<|sa;g+@#Q55W z!+-r>e)t{9iDqUZvC{!UKz4jxnSV(G;++!zZvr@#h<^F&#&L_vlq+lTgNpdZOkA~{ zC%Xmn7FDrx9Hjbdy^}cX{Z;z=#TqlmIw!J3*H8c4W@S~+d6A+-53i*EOjmpJk7Fn+ z;b5DruM{Vc%^uAwX+k7hUjIdU>18HezL#DmMBl{|JlE@?myV??AoieFW$uDWFTHHV zguI{Q)Gh7odu*Qqvz_|m_H3;#PAu5ob}F~U`0UMXyR?HUZI%7FjV)t3^W*mRVQx$_ zvkj7QJLWS-b@e`TL3m*BXwTl?PiOv8HqU6c04t4+PxIL_+<bMz-^c%23IXmOOAHt@ zb1#DaBd_Y)0f&9DZyFl)Fd3ZlTFeC0n*KL$(=*HPp3h8eh`vexl23qR`T!1ax%iaB zxgI~+sEZiDR8CJ<6W&ivJSF{00J)6TGQ;7XTo*BHCd}7a<~e0N*D;=>GW_i^6MGDB z-h;~$$gAZm!hwZ7@`T(6!Hb)>s1@KSN7)tMiCR*(=$An)t8evb;5Zv>086Yh1a1mT z7|nxL8MA6#z-I&aIk&J6`1e_44~U_7Lc9Uag&!~b#~c1e6A*9=k*Zr3sBQw?O(ygp z^?Qn`e&RVn0k9nd;O@uTjGp6%*UJp!x)c5$OfbO*nfDU1(3-$^CoVsk>rKXY6R_^2 z5&@#?qtg+BoKacD^)&rzKEOQ4=~q#C$my>M^Lze$KpJmPGk)hWz>g>byyutK&w-Vw zocB`TPl}n;RiU4@WrDAoJ*laWRe9|`%UND8eH?7R3MA*WUiE;j-AG{l-ga8^Qu7zt zsov@V7nAvEH*rK;Ac@yd!%dlf>*}HFIK(Yv3bcFAdPO^X75<{F{W&%J=|;`?vu?j$ zw_HDP>4s@Mtyg8S-eC*CDPv-lG+&=88ZYbt#P;Kkq?%Y@y+Etgfa|I`rmUrxqUWtO zT(9(U0F$yodzk>}wPNcLvZ9~X@q^L(otAzzk4fFe{-b_sb0URP;x}FEbt|V-@00z= zsWpBDIV&q=2^p#a%Ia3Yb|>xHDeYIX#6D#WJF0q)Q@~7KmB<jy%iO~IWDNY4sc|X1 z{=a{A@&AB?&0~SgB$$ullf8=Kwz`p9Vn1~gbn;{n{ywZR9^1~#^42F4X6nreyEU2o z9hw75y@GyOKLM_rdEfNonWhP0#Xw%!(5|GF9W~!!Z8~2lvy*^Xos4DwmbT@QHOf)c zFPg_&brBZQsy%~>ai-~fcvez0-|!nEQdCF%psRSTmy1$*fO{{sM0~*;JiAQ_+dITw zW;c=Vx90kOeesEVk+!?)t+1Dw^sjcKN-zWNgMQrT&YyVJ*Z2Bw<A>+{WQ8^xtYtE- zlUstC8;Nb(qb*>;!*0WV*7jU=<g?n66gc~OJC#R>Cmd4}Si;FLxO-wzc*FpAahZ_f zI^bHa;!)sXZs%s;DHQKA-Z*p^GqJBR-nd(5d^B!!T80B+7t0JlZ!iou;@ohfP=)p& zQ;^yOh);Y3s1tt=Fklyl03VliU_S@h19%}|`#b|&;5=&#fi)KO1~6pE5Kt@|{U_n3 zQos`XIFPyGOvWY#Ea8y=r8ih-jRXMg#v7f<k<01&Eg~6^01yT&iRDcDpuc7k7@GjV zoeZ;5fX@i<Lq`0iSfAt1>kLEY{PV1Xv$pW~!WW?4RBxycVe`V~vi<|;E7Y}W7pSvp zq>h39t^TF{9>jCv_u}`!Yx*sY0C(#{41p1Eun1f$4zdf7TmayE&M^eNOCQj`gv|#p zS^Vi6e<z~y>x8*H0i=`CpNh2=0pGJg_UQgRAbS~OdjbFtCK%vNz<geL0+bGna;5M0 zk&H+H+CltZ5L$B(1Fcm~J$(cCZYDOEfb<b&;scrMOu)K1cL@rB>`6II-;;fh54lY7 z$@5KLI(dKg`9Z}|*Rm4Oo_D`rQ2wTKy-44qhWFb_)o9~0A2NST>hn57mvg73tt^r4 zymOWbrfuHj)hO>)=)KF;h%T6vohhv3$&&ZgjmuQyeq|SrISut(7f4$-{!GVVO%gs- z&335rLwStDUD$_b$q-%FPey=8FZZ|lqgL7alx?~Eobq+m4~m#)oto`pYu9cia9b8K z`a3noBh_HtM_Sr#lYSM{I0>RGfhE1pVG9T=x_@Zpud?-aTLQV2MXl`;Z^i(9TVSR$ z(Vt|TgkF^xQRh9TJ=UF1I2FKR8$VSxZWkp;<uRd`ty8)c_nZ2QBBG*kEhu1!cPpOn z6!<SS!PFj=$1&_xW)c)+416Cy*}dd*4gu%>#Of^OdBuLBi21&p`Mk(q6#3I&!d~+I zVcYqoms$teig>`a)Z?t?{ZV_gXR2<uuM<q!zSC=4HYajK_89E2-B`EdINqxnC$x`8 zo!tHt<ea#(of!UAyw1<WxS5tg&C*xRUsdWP*!=j#shA)3_^w_$?B2cfQbY8;{E`=X zJ@hiC;$5V}qw34w%N7LKy=>Q+ne6*r-_NG#&#ReU`tf1<?caQ%Q0+*&RW<FkyLqYF z68+g8RoccbWCwnsemU~r-!)vtF*a7FWhe9N-(;!2tLu|2YepM=5u=p@I3Wbv!D9gI z(!bO%fLLac0qA@6J9^xIJRA~`L=Znc$OX7YOw&G-94u*IZ}!`Su{`>>%;j${wv(&H zQT71m#em(wXZ*7Aew8VgsXsMQzUXt7Wjz5Zr|%3%7~<3Ssoa`RexF<~GhFRy;Pv=# z5dZZV1DXSnw}@*+0OEUbwFp4pqZfGsc$#bY74QJBWq{%llfT0to-0UTu>cyk9DeWP z;sM`riVfhaF{8U!=8xP53$Oh6&Od(mH#&Ta;I#>+bz)}pG{9RK*98UN%L#o2nde1% z8cqP;Rct@w--8T;e2{AY2&lfyBrrYA2%j#;B!E8wXouJ7><IvY!R(%mM@E>Sab@&_ zh{2zXJ(^5$PF&t>0>&f*d$u2%K<1J0p2_hqAJ{(moUA^}yrIGlu&zq|MZ}=j-FOu+ z$x!ca(byy#j>P_s97B6)8$Y<MZMZuEl4;J@-O4`h%y5mUetZ*jSgJ1c>{KwlPTQVM zFX+vP$*#!zIvwk`%FDMs5zclL@oMYGj`6?lI!Imnw`K0H(u1n0|0Eueje2Ym;4rA2 zfSn&vdpQa0s)K%9mwDgzeQw8$x<LZu7P1pRWOwpiHDJ$aH9o7#1o&otHC+x_VFBgs zSTyICmiA>woR9{J?Mi(=Xt{ppge}x`oyuuIRFNhCu(ih`K=))n$d;#S9W~OI4Wqmy z4<KALZddtvWdPZoIPP?E?IVBuaSQh4(y&08Du-hvZb+kkhQHf95})X2o=i5Djnvga zMLWtGe$4D&gO>9gFK3*Pnf6t={w`u_9~jSHYCJDeh4ThkVc)V~+-m~-v>kQ590HXt z=AFq25L*|A*J(F5rr(I{CbG;Qr&6{-h2931^-)`tXl*;bd)C*fTtA{J{L8!mpo<ga zrdzteA`!MM;m0Y_H(Stuy$Zdl9;4h#o8_NgdZ{B<%aL<>2Jh(^a_2+(jH+IGnIG|{ z*3bK1PNUGjmz^<AITgR|Tzilgm7Po{=JB?z-Opy+=(_i~bKf7GnYL%~0;E4xFJM_- z;TDu9ykFO!e^|A@@KXK0=~1cm^jUo5@J>hssj5}c25*q!ZU6tX_xG`u6<Plu_NnSU zdv=cRbA5Hyzjmh|+-_rx5$1;x!UPe-51|pk7-2#XLZb;DO(x^XXfhg&5F!YVMkDeB zj}e)m37H^_@Mtt52q82=6NCujAp|3Y5hjEn(r$J7*H63MZntjkb9{W}u)8XM?6=x= z_Dj{?``nlAy(Bn&&r9v9RjXE2t@^HSB?oUw$aO9C$RUb^xjkS4+`xj#7Wyf9F1T?E z{u92??{C1b`HXX*KjV9x20rD2z5sm5aq$7@bDZZq@C*wM0n>y#TAyM;44h7ZwKGCC zNC2{PU^_kfnlVp-_iJpV^_>H!IF~Y|Pl<u6Sm!9o!Ne5!1F!Ku@TvY4?*rTVHa39A z#d+=naV-<E0eZ$l&p=GXeS9ASV6DI4j}!pgGo0qM(HCbpZ}yD1o?Ez)0>JxR+P<v3 zbDZIf(UVaM95)%bXJm(>aFw`@TPT?8kL$O%8jyq{0KVe5zJlTa_B7|2L&_r$C-fP% zfT=i40Qze_;|z#^t2hSognUlk1manFQe6!f4}Np#;sWBQ;~Os?gKu4P;Lw3rf#1m= zic|2--+l9E{Q&SeU+ELTK{ipqZ^ciz6~q<d0-u9^Oh3sK^d0&oJ_SA#7dQ(1Lfpqe z;9Zd<PCTdIQa2jwxJ3<9du##5GYu*WsBSX8XTMvp%)A~O5Owo+H2`?6EGGBZs9#JO zKwoB(Uk0=*FxcjbdM53UbKiXf%Ru!-&eWd)`^(Jb3k$GeGOjm&ugpBY3~ZMr#&=o6 z{H_{+=xqRW7Y6xd|K$dJUw%LFeDj`bB3a9TzZzfPb-&}wWViR2*H<O+4nObGKHKTK zPL6u_VmBt;-R$jECV=|3J8IaMs~xn1<$9Hwv{${at}A~ChI_w+W7)co96}FG%(z3e zug$JQ1Nhb_A-gLhy*=B;9hv=AOZ|PB;3uv97WA@%u%?H6<8ZDC2(F0>F8Y@A^Osf3 z+ii(f6#ylDV@rSAfZo8{8khAK^#sCK#RYu&L)F+_=&1L4M(E~xs21RL*wN1|`yu~$ zs%+?E^LK4G1SsQsE{T6~Ii99tM~3$7chW7fM5p~CLeIpsHei0vWbSA;?TJCumM1IL zi4pY)Q09#ScAPS7m@kqzRhbdjPT&d3>zQu{-@5w140!Rc%lpgZNe4R4@7?wrQ6=1e zC(ommrEgh^@~#cAJ2m@V)!4^S687wuu=aO5vo2n>M0tG6e}7Qb?u;RO)^puaZ#%M+ z9S_Z@-gTWeyuIx1{?+w&6Gy+H!09HEp<)De{=i;0oAnPI*4<t0YD#?~!=>PFM%h&v z0q&#t$xroD`o&QVql_}jWhAQtFm~DKjtjm~E*I$<IP1CrljHdE618j3U2QM*xr+Hx z=&#*Oc=Ekkdgp7mJN?%0VBIcnH38WgKdgV&VqZTWxM$L1BK^}9TYw8d<kI&4vhe`e zX2i;_1kHfdYlI>M!jyq~gEb;xU97PN`duCAmw{jDXLuHnJkRqbn~kk!wK1-{2cDDl zNA)i=potaC*FWbE`fJb&PKXBq#XY6ps}c{o`94bwZ&h4NRSfLqF|10A)r%$W_vLn$ z8SQ0d`6hFGoa#L$VZJsQ$rm~UW+z->he+75jv`qDPO_bXVAqIAfcOj0pXob!3*^tm z{o+QDcgcsu1TH>&@%PMuGfXSNv*!|~cBV)cz|X|J90Kuga}P&=*9pbVz!CAO+@=Z; z9+v>@O$_KZqq_M%7C_$6yDkIS7kT*$mKfT_k181Q!33;l`nQ?o%k2uRdc?V3tY)Og zYBxrC<@I>^^S}VIXLcbCJr+K*8YrL1!g{}oVXn%KrSUnmGrb2(Eh>+Nf>A#9@*J)} z`MUCogn(h!+;vRq3qybL9+*euF6|`djItNwVta94;yR`S{1|Q3;A3fsb$j!EVYhZh zigqU0oz$BvGxDnR6I&XH2G(!exC;l53&}zEy$ZLRx2l*;`vA$8_oK?oo_y^kYUxMU z1QHuy-3D~_1iIG62TJwqf5(AYzHFU0q?dKd!N#?$&|@^v&51>M{puOF?C;&zsO|nk zI@YJ^`(dj;Yv*-uzw^S6`MoMW;`)4-bwSWFU#rR%xZ8D=Jd)H?{Geg}tt#n<);tnc zKT-U|_`V4Qc1^re4d2h~Cur$6S)u>1_IW|A9abe;1R%`!>*hDxZj|NEmfLTS)4)g` zFZ!u?-oM2r#Z7UmT&J1+*fg)on)sn?m=|3319b@x%6*-ovztz)R%s@1-DkZKR`|2M zw9o1*lRZ+8MQg%eztu)v;z{xTMbGtu>U1+g*ZFCvebc1p`oHV>lcM`sVb|xa^5!q| zMx_O-B(!Y5kzps!V3i}_ew0x<$Y?~Pc!@Zwue-Q5>S2_9D$%HdQTBzbW*I$ZMDA}1 z9s2ijlKpV=z&PI8=V5gj*~NachhU%9ey8WTb_Th<tvMwEM|)5!83#UB(aRn52Lb&U z5v%slm(qL?dbU4f@|vXFQj&-@5+?8nh?p<|4(jVz+u*>@^#|(l4S0~#@;cxMbG`#y zNyI^5omgxDS8<dN5~g$j9%qAygjr_+;;NJ@YMve`J-{RdXeS4m$2iO;FlEjhIGA#i zXUsh7T*)S|&5RHT*kX%>NqY+Xj^FVFi08RQ`~<|aoZ$vwjTiY8^h>PicY&9g@h&hS z;xGxIH~{?_Uvbi~k-vyfd4~e{8S1<E5d{EwLYRV76KHM7gf)_@b`xOvRU9=wUt^N` zpyc<5Im#`@IK04V-X~*qOPK7plm61%X}?}e0fs%yX4+pNAsl!qxbwgtfP)<3Ac!0E z5p@-$y!`N6-ql|KN`Ivf0e5mUPXI@`js<Whw{r!EKZ*PKDafznyHY~%Qt%q5Kz;tr zJpMEA8~r?wgMM0X@+I&-Z?Fd91Mv)Z0zXdlp#OLJ51a!1u6{`W04{zO{^D;Ie=qX6 zA+{LJbKtnP0q@dcbdQ&QUuI0tnA(fy{1lKWu)Sc8FBsO7zZcf;3t)RzmI+u_)^h{v z{W;5kce9<@=Yavww*l{90`)0<Pf`tlPl4<@)td;)2`JhIqR*|hUtm4YPG7MB<Z%mN zUA4?t3+kBHy93a{WW=NPcdExcJMT0H4nL1Cc4*JJDggZD!yv!6*VQ|<U)$+*csw8= z(q$h#MEzE=pA9?MfgIRwo8u3`j*f$ZF<$PdJ<5)NFn4?E2DtZSgl>;hwA;P!O#`xn z|Eg)1h#ck}S;Lg<pdr!5Z0_67(Nd!8u;V2h@CF4JCT8DxDXUL^M$@3B{jTK(jg}WV z+oRj}T$s!I#BXBH1ca!je_ZDw)sje4|NFp^fxg;~LeJ;f^F!p}->URjmxvX&w5zV) z+VpSwIqBdhL(g?UQv!>0__sZt+WIH!kEqt~1eN<M)35!6aw1Ea*<ID@!Cb#C`z5*5 z@70X%65#O1o9X*=W?K&SG%@T-d5w4f-IebR4@0hBl$8#%u<l&gDg4Otydk~y(6&zV z>4%}(y*9wwZJ2#o=I_4gwEy2}98ok-%4qDF=sA2lhTHecJ=kyIz|Y^ScpcmCL`&-_ zS!r)w^*>>hQM_dYxR2r``WHOO??ye0a+!$hMq`vwE++{`71a2P-DN%=W$%gH!{biv z8h7I5X}`+5zvU%q$E%Xq6Ce@p@&51ID@_Ma<(=IV1GO)3*2552y?1<`XbI%%cy+N6 z{apW*f{6CO`0}yPAZKuw`4Lib#d1gpY!VRyYpkb$_k_XyA%372!2d{`<rMHH_gQ^v zGfdO?_wpFbn9gPCv)Fjen7zyIXMo!{|D6Kyq4+KL0w0Sr90cxUjSCcjW-LZ^S;@t2 zGHKh4;i{5p+XNn)<;E7HyUE0EGL@N3?$RpH1Z2ng_cP#i0%2Ydr;OwU(|HW)IsJ}4 z3F=<;mR6vq`VAd|zEi!bFM#-(&sYO-NZdpO>WAu9{Q{_ox>a8fZ1N@xU^A_U-Jgeu z*aVIcunzhW{Q_Tteu&?30>n@FBlp9BCl_1)_~Jj)DIix=0JSr~`InfC>lx$s!q8ld z$&6kG#GC!JF!Z)C7~|ub-^IYp`ku0w*z4>dtEUZY$6}(l%aI0iJ(QW@sjx2$`#1HM z^-N|TkEP%HnFT<9JO{SRl0Jic94>ngli7V?joiSph`Hqvf+dJNrSV=@PWJx1qBhcF zPLGXx#NJ+WSr(0+t-6#U*Bpz6(ng^8DEn<6J`@nL&wilazAEUruTeYHzQFLYuC-rH zKfAOzTG9SD_5@^w1N4u?{|3aSeUa?gzNT`*j`rlce+mcN&qybR^R{w-=J>QHD)j79 z<DWbBpDSOwub--7QXYcoytoN$n0VDPQ?u+1knF;sTCZRC#184vFZFRD*LaefmV#El z(GA$%b^JyiezD0fcTL0yJnYM7yeh|jZzG7X=jkdYbGP|6u;M?e)vq@vGBlsV*Cn9T z0p){+@0H7wPUFX9<ZfmtZ%(WTYV0zw=AEoOY4lG}VJ9}DxCxM#Ky=`_Zvp%$o-fS( z^1>?5moa+H*}j|gt11AJvf}x6|1T=$&7fx8qT0t_o-j7c+ou}s$DB{vcI#dIe$#j} z*CnBqNKsegp>BxvS(Qnno|8O|8aS=n?HdBR)}zb$&u*TB4FPy|I~TL<rrKV7=ihjT z0qwpL?qEMuh;U6Xh?j2oXx=e~R-Cuv$QEJR_OG4S0p0XD648z_fQ$h5QT!b6m2xXM zKI&o5FN8)JrENhmwtJM_l4u9Kqr9Z-R*vIzlwKQiIojR6@86wfeA}-QJ2KVnexg=a zPuGn>EnInP`~uuvfgD`{6<Ofy%4WL}SMJjK!?k~o?Q#EIcK|5UgF2bMvra$+1S!M# zK@@Ai8ZnbC__;hA+^_}zAs_0uH{c~=)`3TOfGywxQ@suPD~^kIfODMZ0`MGL>6OA$ zV$dg9q|DXH>raT8kN~qKFe6SG+cTi>lsPbG&H|V*B>?7Z=dU3!P5*v{H~0Yb_w*n6 z8hD)>c^G((H^rkMeoZ8fk~75XE&cnHC_te=JRt7iIYVdHaup}Y5AVbu#9QKH3LyH; z{8B$gad7q!KNQy&<?$r5gfTq@5Fg<Rt}uQN0kZ~syMjaFFvY>@HLUCFNe*B`;4~*w z=6IDd;AeVCR`#b752dfvH|PgIA5z!oTS330-_{?4cuxLMY=U@~6XF)&27btAz@K@8 z6TlI!(NBTeR)GST^SO8kzV)MEcHjtHeEgg1;-kQG`WXVyKhl5TGvHzIDGJ0-xQm0J z@8zew1o5$NefMwv^!I{A3YAtC@PC<sy+}aF4hAv^w)wgFeG?d80M{2OBfioZa6C4~ zh)T;df$MeUS24F|^$IM&d|e`h%{VU&c)AII53Kj=fbfOijB64!SYm`P&tkTI%kR&Z zX1((7ml@!z8QqKZK)mFm>wxU4!Kd3y^mcje^Ox#$jdT56W9voj&|X+pGTr;ig54H5 z?m74H4zN2Ac5k$!&9<UO_{rXhe+4UISZ`ZDx>{$r;&_tk!2CT#J6-pCeQ)N7ogvTl z?d=L^rH5YQ4sj9LXfLv3KP}hWOe7t8{02SiX#)wP!N;-e6>o869Pb14_O-VzgjcTd zm#%(4#EmK5)xM&9{qK(vkrn=^FXM7oV7N+a5IAZ!t_4~vr+QcUjjH+GcU}n?4#+86 zepdwqSDrV~ge`ur&QFC7>x(QwA&Wmqhjm~R0A5z~S6H)tSO((BN`2bTi)#VU$&HTn zK>X^PH)QSirR8tr5`(ie^p=nBzaIN<AM4;RLMxHMb^TBfB@{PWelTF%H%e{S7nony z&N?8x?70pOJ=aHJ$C+X{!j{$UqJn{U;a&S@FB1644*Q2Xz_hvyu%B`O3%2z;$^Xg{ zhE%6=BF}#4o^Ucu0!`cR+Wc1J*uHqgB#$!WbTY~)9-<%BzvWMRs6u0=&nTmeveUBn zt_~Vuk3+9$MvY!d<8|!KDhV$WyKf65Tq@v}XrGKHwNLEKJ%Bab%(Iigk!Y8DA*LIn zpYwPXvRAv+z`eCwb|3Cwe^zNIGWeR3|ALg+D`9S*5D@`~SYtxM;Jyy(Iekq30QmRy z7d!*N54agh@K6&F?9zu-%<qyamayiYtoU3%%rkrfda9r081SAb^S0Z-Sw)$JN?GMA z!{3&H(*?6mOqrp(T(+{>qEh|a<rhya|3a1k&Y8Y5;C062zR3Sx<jn31kUtT($wMHn zm)}u8g5co;#|~_OzDhrI@iEY`cu5?EU|ZhJ^PmFtxcCiRJi%PN1Uljl)_|?_=sUKc z$mdwF4V+8s@iXq=D&Subw{aLmC~gtIhv3t1!hgK>pXn4>EDT2V;wsfDfOud5!p-lQ z!1DqiUx31se}_3R{wOd@InoLMdYCi1$9Zp><){+Zzsj!&#{#kkB>;T^#FnM{7Ql6x z+DlLZ$j4T{$Hwz%{5+_%yX^0b8E%<jy$mpy*7%H<0Mt}M)#rJ6L9Jg>h9|7MIbl&@ z_s!m4TJ=}8vqTf*yb3Vyw<eWdb6DJqORISYz8BZhuC<zvTS99eAzSAAy}OE+j^kq( z`*OE?xd-&&3Jl-r{hjhWC?9$~?F!@zSCoL@yRQx^XQbiu-30*LRM)OI1_rG)ZU)ji z-(*&!pFRNhs{ZZ^9IlH`#65w;%X*h9VGLEC03rANX9m<)y&ybwdTh5BoB+2~{U|%O zw;RB%8VK&PjtZRoO5kL7VMo7IRZcU&zZp0k80-F2Kf-7IU;?`P*hkngj+m9(^=5-O zXL$GXcNsw3^@ajlKape4n*igWVSO4qj4xSX?*$;e-k-_}zgyR??EQ&Vj(r1I2pnw~ z$ANWcg=+E7CV<_ncVLyD{hih`_|>;hh4%sT#lO-qzS!(NCJieV8tfvjiOnthxxlI4 zs{CUa2!GM~{Wp#CjO+Nd?L=0LKhr+LmISOOe<EvMoBVFH;{8cm0-}q*aq+LN`-ZOT zidD(b`<Td)Kw+n1HGBQMPdV7H&w8$IUE&%y8Dc*!2ejL;_NJ;}DIv~xeK^V}E0WR3 zM)4BymUw}u_ECjLUY=2gS}=^V`*Y2H0mhB8vm21hMWWseO}jsO#_@Y8k5gAhnb8V{ z94|vBaP()|y1eI+Rb6#o@7IHsv^4BshiU+OuBwOcfo$^q7aUios#gI0a`p3dS2@>x zKRblYn6CmtLSUT<5pXaCxNow~I>;Bq^WrS<Z?dT;zy_Nf1U8A70E&rN0}&DN9_Vv~ z%z-dHYKl_GYm{H{92nP07q7}<z?SLnWCGM?hGK5KhG~n#6q<S{8S&yauI3Q%8OJyT zoMoFSuuXEk@thfR;3OwFjtPcV9I{5V35}1*7^$QMye`AhGhp?NTrX~+U<415JZyZv z#wP2=I0^G()Ffbif%E!A{tj$#lpm(w3xF>;%W*@`F$>m!1q&8%;L!s&9rz=tQ%b5o z0e`u88#jYGsXx)LfPPN@m}i0K`8B_T_?H)7zW5#B25#gW$REnziwOjhKz<kWZ}b}~ zhKmbzt$rIg%>}09fN*hRqHq0MzT^y`^>NOCzF9w`pN5NfeJlK%=l@>h`pN)_CKGz5 z?F_Jwp=Xsqv~}_Q%uX_3c$pb~nlrV>Igs51nrF=Jac%=a%Jg2YS3sbX`V`h0Qylom zhJDOx>_g?h0!3scM8qY1EDQj@Ig@1HlX<&YVu%M5XkKP;UswmbaSf2W3NT;xBWelo zZjOLO&8!eu&zT#reLJDUe1Fj}Uo_1>^M>DbS(DTy0CZndy2WFbneAimCyjgeQTEQx zvsgd2t<(47zM>6qJ7j{hA48<uw^yBj?aSmH_TJC>F*w)jMS8Y#n0;jE1S=Y5zrU#1 zPYxZAY+|17!tkDrx1kcRn*g5u0NHZT@fNq-fDwAzyBnWo=s13r=S>np$62F&-1_-v z*Ky_wbas7?>}db?d|5S)edn(}cBBB-Kq<dE+PMoeyZ!mBW?Z=dM!Pfnck{PlM}KPD z*)p(yD8E<+9EUB57ry-*x0Ww!0e>d2U8OB*O6;nupImxc)i{!+dAF`#>k^BC8sK)e z?ujS^8||B4?L-V^)K>zptsuwO1X^ctR^Rw|RI!f^9Q;exui5K_ZcNxsa|k89E(7xW ztZ@1!*tO5=e*W6G99PnixWSY7GH&lCsxk6N93B?X?kDz*CT;c=?-2x5*z@yCFX}Oj z9hrV>m3KY#sqc6)H;T8L8)Xy^(Ld%%o*VVBZ)F5}U*0kTcrJYzd-&4yvt6&c9c3JE zJ2ii-`ik(;4u+k__fw*Q+(kXr>rd^f9)<)6v>iOS=y@n@M70Nf!(1J2`zy7_#`k^^ zoB69wU-m)TB!yVY6yQEd0q%!cV-46~gEi1E>w7r~ESPh&(f(ZPs~UeNml(|b7?p3} z2Cf2eo4A@Qfd~0?X@q2e=?oxUu8%7HtEzrkUCbKB1<!ZN<c(M}z7yB9Dlh=c=JS=M zkK(ySD{KI@3GiOzuM1|tpZU4C7WB^*dIsu{zCrz-0)QVAv!Dzxk3sxG+$#c*zYzC` z5aLHJo>1=rNAyWO1<vsYaS)htjv4R?C)olHaEL7sp?FpN01o{2n`{2@mVc&G;J7dt z!VCRmfbBBFeZg!lf#;T(@{<x4d4f#2oD9gG{Wr^j=GpVJzpLK|r7`qbFv}OfdK182 z0QlolyB3z6*a;H$_>lSc<I>?r)eQk<fO>2J&{YX2F0IiNTQ+V3#}`Y0b{lwK{H|)8 z&aEc~6*Fdx3Cyqlyvd(r;Gwva|8$=*yUeXJ2mV*>CHKafP7U7bWf_^-hgz5I%qqUi zx^5@!xvqZU4(&V2bMz4FxPtk3FYVcFV4}-@%eUS^LpgCvB5mYRuIku+RWpKAsUB*O z5g9uZ6x6q8h(zdRpql@_M0)5ytQgm-qu=t0i`grpu6{4H0F{0GkF2p_<yfxtu=l8< zzf_0zFY7I6(YyORW8PpCcvysT*f)2XUxN<ihMsyg$EWnN=dymPfRL)P-Sw8Ga8FpN znjbR8Zntq{zZW>#TlMpm!MrU!>?F+hk3p+FRgIg_5tv^$--IaPQs1hZ0IKY`uKlXw zMlZKLgBy@kS^hPwnHTC3X6$)EIgYRT@5y{mS>12T=X^HvdbLif=aFD3p(LpE7wNly ztN!K;SHi{3xXo|ZwJ+Om%GUKnVEh-h_^~=dldOGBOy*VgFtJLDthD;LwVZNdO55Il z&G7GCV+G~<4;%OIdt*l1JQRA?r=2jx7pUKTU%9vT&u-<Z<-{dtW^KjJGi*l<_3x9I zw_Boei~sL>?tf*e|JK+$=TQ9;cgFLyQC2P^z<m@yxsN-z(Q%?2WiL#$<3zF(5{|Ib zQ7#F8G5YPjv{4$)KaJ9DJjl`hFN66szC`@qs@HpyRz1o+Z(F;ew_uNt>y~~K(F(L9 zK|9)u=*~np45OpZyl^@1x7rvKWzHlO<gXdPeF7X}J!NoTV;#7e8(9PX&%DF?px@Ci z@fYA6FEIr!u&rmH&u~_}3!LUWGhjRAXr87J(v!p~gL=Zi{u#$P1I(DG%<MBrUlRuN zb8G|i^z&`bu>ht_)4wkOr2Opg2R`Ei(2o;v67-GwYaRq~t^6@R1g_-`K1rV!0t-$t zr2zPDu)zi<Ksrbn%2isQ?Gk|e9Oqe3Fn}+}!J<NvFvS-v+i;je95Mb@IkY~p)=ds` zW$LK{;0A6IcTgM%f524VfSHi6&JiF=|30qIumx<1g9H%&;^KQ39|3VQ*RToVyg1FX zaA0v@UH%-@Dg9&pHHdq}9pWI!KkC!G2I^&Xi@F28`Q62P)oIYT===38pdQj|`a#h5 z@}~Y3Fy%!~1BzIm2Obu8i3fqx{F*uNAB+3B7MO7*6W}ZdOAPt30Vq${@e{k9=Y66| z0Pi?wURNbxcWf~K$Cv=`YT$pyg<kZ1Tmr7!<tUUmOvc_{u8*pzr_C&H0^p_fy9Ma- z_my=}UkzX{0Ptl%ybWlFGUNCh8_*tCGQ6AL&)$z&P6$~n!J6XIb2FJ+^{Hc0Uj~A^ z0X|Itzc0hO%`7i#>euwUu3|Fo4_WSRujNJ=<0M_$5jQX_?+3ls11H@*l3eN7Y)()O zcSw)Q1IWD!J;feC;UVm>j=|V<J@4ydl?TIT(4n1O6RN|C1lIt!8^OBt)6o0Gssx&D ziU0M?!K;XuWcrP2`n{{Z3#MY#(=P?B_98o$+Z7<5#Xh8?J(caF`^}GC>g#)M6x6h& zsT^PCbm=&rTmbNGfc7dtp<moddXL|rqTTj9-!{%vLwxd(Lq8PHb<<a!p4t+$+8Frj zfcEWnEGy%LX1UGtLz$60ZUJW2F|(V1^d@}=HF}UW>na=2FRi~-ev_iifzA>R1i_*3 zndD-=#oYtUU#{mX%k7Yj^GVk|;i6@x3u~V2x{mTqI1Fpc**kmcrtw_G)Gi0Ki?;P# zTf#+~U$7bXef@W2*sJQ$-*tY}wAY>L=K-ITpYJ@~v4El4z1#SQ;m?<4ZNDw{aSTRv z9Dk#XQn}n3WfY$YYpxgSRmZ7mlu<4hiANQzbOATYYBs2@etQH+U!MMHyzyagd9v`5 zf)kYe)9$Vw<2~8`;T~({_9ZgD?11P{Oz3st%~e@f-Ic<2AlEhEUb9Znv(ENbt=Gvw z&u?QI%Ovo$n-$G_VwL{ehp})~&)v@difg}{9Vkm+K}3{}#|W4cG6A-USO;~leo);A z`rqby-UQ%YUaaV+`u>V5wP7*`D+j%~!oz;W%X|b}&lP;)xjrxdtt=qNGHbhXD%S?C zsuCli&7>VbiE%t$(!(;q*=B&xN>soRCL9JKd6pZ1FZmfygLqT?T&x4X=WGhpSHz%y z&2zjA;*Ub{8t5&(#UFuF%$WkGIl~M%&l%1ECz+<#PH(dXJjERx1o0@Ja~Q<?9N{|P z9V90x7{O(FKw1FZNdY)2XIC?s-4;2tdQs9%0U*!*3rfuI^YnKGa6ExvM@2vA1qDz% z&ig`IfcIrPh%p(^gA(Ap_?{~D>mq%AVFilg>H8)?y#THk^*2`}aS7UP_PewI@nw74 z$n{cq<_vHy({-Pjc(G=DEBRee>3gIF)v%f2*DWCayaE`n8ob+liD@uy8OzdI&(;I+ zscDgq?^slf(>}Ausu|wrOV8W62-*mM-#d}FuItpDi-!%{zNUTMZtm<|58#JLJeMo1 zU(^$j+SZS*b`uR|m;G81;0r{SUU8bP?e<MPZi<ftHRY=o>ysYsaAlBok3XndhU+25 zQBVsE?903;bKvB#e$thZnOY8Gm;HO#vAwhc%ey5qv?V|UppSRZqw=(GyCyyfD$-$I zumPzmy}`|A{PjuDi9Lby_I#&mpWobnt~a`<)_QaU&=)uCDX-@*ugm<NYbP26t>3Q$ zus1(f)%fLb3FzN!Z^2R`NgWWs-mdF_=S_h2$ckSzB_7F2|4?U@K_!qqwC3N4<r_Ps zW1qRK&)WM>E+tt6741~k=XLWy*6(x6Z`7^dOuu3P{PXvsC8l>b|J@hR+BVMOmWX6r zGk&|QubS!=F5T=n)Vf>M_=BC@B@GPt9^6jG_(HYSL`yeQO0S*kWS}@i=65C)<7Y@c zL^X+azN1X#315{7L^>M}ZEI53^R_mBk$oPISmjZ=g+E3a#eHsiL_8pWKk8wWeeUzd z46$J)8db0>G9K1m3fr>w1^#}Q@RGBJ{WbF9%Y3$5RbZ_Df#Ibs;oy4RJwLpY_UXe! z_4^&P+pJ!p!Em&SnYE6gC-Q`z*Iiv+zdINzuvvYu^}Wl)-_~9AE%SrM<X~w%X9S-R zkubNf0h_F|4ss?Rm+t|$@I!qyh}*^eyas&E5BL)hBE=erV;tsP(B}wqmS}18_!TLD zewu!EHOIJuf}uUk_l3zwyh>cdQDCO$EC9t?e)yL$n46&EAMqe}09Uid3E((au>gIO z{vodezd>?6Fhep24snQM6hPd!d58BXfX8=pH&<W+hY#g7Os?9Vlt8Fi-LiwrNt!r- zHBQr4vBn{;D#o9FkAO223}I(E&-wK4fP`6kX7t}0>nXS>>A%~=ZQKHEavKMMW1Qdu zFlE7M(6@4xJ__oW`br%F@9`NYfj{#lGvE<!Bm#mIKrT^i12-i+av~Ie<mVvX<YhL1 zHO}(|@DZOf2mOhDg|onw;#zJ7{eAr`Z-M&0{-M4DF8=&mKl+>Fe=kam>zVH{8QN{2 zx%vGv!}+3yd0mx&@No{z&iZ<>#0Y;a1t6X>gS(E6=bDV~*?)@)Ci%>dCCvUdlY7?g zxYXVP(66-0Yj2KURkESLXjk&Qq}3S^Tv~wf*mytDPO*-zN-!}KJd`z8RMpQ0WG`x% z+@<wy+%m_@ytm!vy1Mzp_4m?~NqynDW|2Kpw|uWxpYPI&t<V1KQeBhxS?}%Mz721t z##NkZsTDDxhXePkTFp&Mz3aK^_(L0mY#+V&{IU%OtyVmqLvMgXKLC6<fPa?`<1Fae zFLnFr(7S$t^E$wn;aqmI_j;z;A;yt8e&qoD8+ZV5R?L9iNDNTL^gl#mj!OcUY_XHR z{#iQAXJHL9wrhP{{j<*~kpuYGh<3n~9M;a30K{GVunEv@8mCqLT({n61JG7{ukt2E z<8$2vB$O35LB@`8&VY6xTva@^$#2=r=2tuUb+__NM&>5}9M&?>%gXt+ZvM6P7#fW1 zW{fCUiiXM(V{VYA^GGBF;kQ2JZs4}R{=<L&x})7TF=1zb^0*@5rK-=vrLvcAD6swP zkn8`VpJ=jchkbfb*^fgd`gLu$?FX~*yJ}=$*Zn|~pBy%!RXWFaTp6e3O7-csE}hiA z@3u3UG~DR4%A2_A66m5@LaCr}e5{HQf2eihUXk67g+(L6X_TFv5=Xg=MgN8ucxBYX zD5H$BFXi&$q~0s74fl*bM%nKoM{ls_$JyTZi^0C^`EZYUFyE`z_liUV*Dvk>jg~vo zPXDW*S1Ez_IPC|(h<Y+-xnAMjwSAY{`m+FuCs3S80+1GKDZu?;3UJ>@0PdXAzvgui z{{|0oA0T-*EvMksYr5LGFR;pm$=K*~@fZ(rHHZ^j$CbbnYz?wjjccq><_zTJzoo_G zZA09p!Ms#HFjTE$MV0<5Gqz&^z0b4YJaC2?7eIb0?&DRs_z17^JrIA#wOmaO(3TI1 zo5c*&D<Tjx5LXJAf;cA5ifxdm<p=T+kVo~5uR*P;E%hO=NFmKX;dwp*{vXWP1o5DF zg&)Cz$G&;!AAkPObgCs$0;ZdqsRFc@f$tgTdt3sxD+6e5GPchRj`#$aUH+X+>%GY9 zQwG*QVFByy@|S`7dHLEbH)AMY7|ih1fb%#_0<ra?YM9w=8&M@&t>Q&51MOL2MlUnG zXYZGvH^&C9E35pv@vJN$yj_nr-d9TcvPY{c^ZCO1<q(NgapUup1?U(7;9X>|-Ag*| z_l8|pD+i`tU;E$5HDTPcUR|}l43(H1Iy`5U*0BuO7><{+Pf0<?mUW49$(sGL&p7G| z_-Id9=m+FqW_Sz+^(T=r9#xNW>iRx(V5aW&3^_>qm-k^orQZ9F*g62Yi`{M4#6{$Q z^K6@)h9328D!0wP>-Tbjw_W#Pq<8ga3MqUOi(H5d>hv7eBwnZv<45+e@3sUb*Lam{ z;!$0qL7lxn-tychjQLVJ{64Pjk7hm9*;x~yyt&_HW5PwjxUMS4q1`VN$L9wPc2~Fl zr~-_K*3C6_{x%~lu>EJ4-zXyUcv=!$%lh$e2VcepMt#GjxNRa+tDoxpTVyeb2S$Q{ z**@EzqNRD{qSde8R5C6{R*%_C@Y(C4f!SVG^mpi~H*>rw5(14O)-iQ{X0qqbpN28Z zx^uOlmZ3iz7Z-c&GnK=7VW_)>huYt*VxJgyyfLQmbGxS*pW6;w)>}HZ7~i|@JHnQA z{7CRR%4HzqaqK8wBJLnz>KbK~RW69egPTju4#wrwYPTMvTn-YB)-uW-o#(p%X~TU2 zm)U;-fqn-yyOB9BccdQ!j~?Hh9d*Ae<@>cN>R3OYE3LcugP{^qs;-QdJL*S<xjKDl zS+w@KYHUa7=qF{)FfLO@se}Rit`y+D#yV@jK{i+i=0uzV{U7lr?}7eA|1o7A|AY-7 zP9UoKIA@pvr#Q!q1n@jJUQZCSpa2|y#tBXX^Za`m1N9sQoXdf~iDoXOM{QGP0DQoE zd<uHTlqnD-Kz#ixe#`>&uXu{vfSbinxC(exoMi&cbaDiBiW8ir01{ur4cvnnET8kW zp?Ap|$BYpqS<4yN6>yT1`jk=LZQ>5`V{#y}m~eOc-K6K%3`YH|f0gmh5jHtQan<!H zrc8|f3z)D;abWrdXSo0zOrgm)6LA#yQhXxb0`a*xBsM`T#K+>dAnxQl`dZ*luHkCn z6eoEF#9VCgHON=x@8y-Cf2to-+d#xR5%4-6@;->a@H`I!5uY;$e!@%oQ{XIDaS-^Q za4&ZOp-uqyinp0iFlpON=E^uQQR(+=;CdO@FH1o40@yEefI9gT3SfExFkhsvVJRU% zSwQzi-p49uVvi|+;5N`*rCjQZlx<Ju)+8;Uy3|=al+pil!yceWkdQe*pOU>Sa-e)+ zJ?8gpruQniSJwXIKsdAj=%npcE&eNRoMYlrDnQd3FVolZoL9|=9+%oP?+6`_YvAb% zkJ-tMSvKw!m&<-Tzs&YGffsN6>Loh}jk!E!=mga|{Vu=1+Wk!5{czhld{yH%bli!! z?i1z%?ZYF_{Zd`|^WOULXDoJIr%Mle?g|8%dyk(2XxU{?JZs%=mgm{9p+AF`@~g@- z?ML>|mn%bS=xL9!$Ns+xKv-{Ieu)X8v;UJ`cH|29v)ey&j&sP`^16)wI)Hf_aLbra zgpa=4;uo&<RR%+`>$q$KSgV@y0+0DLPH$XujZ4j~^6h!1?Z&~lA#UoEI52OCQ?;#I zW)1wrRW~8j&98AwKSj0rkd5)6cBbAS?++Jy&ThJ}`)l6fPwKQ>XP>ebAYT2Ppl00K z?W&7|%_{7<N^kMf9@8#Qru*XNa%{UZ-!J>qV9AaoFi(FG=KJs<2e=3Dx53~1xA6mT zkr*Cu*caE?TiCMB4MbMo|7Wfb+deV?f7TwKbx>Ubib>ue9m;bhw25;4cHe6^)u;YO z1yy-dg`H5<6-e86AGKE{ZcQ)>yl?W_8DO#6;d6|@ML!~2KmTgwb~JqZ1ItJ6%=x6> zjmBNXDnIqO=not9A39s1S<i`w{~M7lqpWBMk1~pz|2nSEs%J+%T=Fsk%tskz_ZGC{ za&KITjk4di{i7Iut?|HSvcvU>M?3JEVVVwH_fkD~Tb3Eb_ICSQ#(@Y|Q$MZTu96mQ z`tw~cDd&BSYQ4I;`l<a!M6^e&dp^*}uDXKSzM?x}P72e5#E=L$n*!W7nXyg+Bwqt{ zk9tH&;6<L~4d6z;%WFoDhdVUiJ2Ls}U+CZK4}iOQTD$<f?J<VB0b|RI>NR6ar$Krl zYwS19nXk%aNaH!>&&v$xHsg6#pCiB;aE^cps9&q^=tIDh+`u8=Pif*n2AF<`JH#Du z@$rkdUAzI*hPqR|2N$<4ex+jI0<Y=Qz*$c75a^REm;qN3G6jCdog4!GXWY&~;8~_@ z0jKzqcgPM$P3Ch|0;C&2b6o{&k1LqlO{VlDg`%vFgjq{fGQY=5e`n>E-(TbhljU-Q z8b<ewDL!j&Z2exMc$)(7Z!^5d7WaB!FxZy?=yHh(K4T=ef$C)-JT<^~`{shUalF_J z@seuLLhLZQ6lGw)%i72G{|nD?ES+lR#vHD8V7`()>Nm<LuCmknk0I6#a=>=_*FWf0 zk3RL4E7q$|yZXQ&<cjoV1LD*m{p}VrtYap2-&gtfQc^cLm_C~Th28gy&2|ye_a=zu zgoeKLc1aYmnSFiZ8LmKG7eDRm2V4^imiOz*DXz6$QO*$k9d&QFe%s5h^}8XV0KEG7 zqc*=2HUO~#ujfeb-?#ve+w~RH=*h1hK12r6KTg*={@N02!didhmjD*Ejz>43z0dfo zV(@i+Uf?;-o3t2I*jwn>FO$}JBe3T0YUcK;n@D8C{BI}PWdQQXh<}<4?gf*3KmZ3O z!Ij?%Af8`T-#k^)MeMvr53G1$pTs}g9|e?w>REf#Qk=e=@G!CLdEr?9z;oOd!2Gsx zESG-Qb=@cj{@zaRvqD3!%3*z>Eav{9*3qky;m<)c0uAlhuAPaOhb=c_*oho2>zY0_ zue*uEE;sD_TsKS4{O)pn+!9;X9Q;*R33}LP{S5`OaUJh-v(_l1^b7}$GD_LEKPYaK z&+UPVL}Oo!vX4dWW8XVM1xM);h}ccp>rByVpRdKnE3bCi2d~DSBd_gwvphH2-GF{_ z*el*ImHB_@#D!>&>1WkfaN6VO!H%tJ@kZjo2K|~PKj;8aago6AV{!$4BpmSS`O9hD zC-Z|jnFdfJLST{u+%pFEb=E<?Bwv${0{?5SR7Zh>;wT%y8Gg%Y;2h_<0NluxDG)ef zK?0x;fH*zM%7DN@%E=yB2a+KHAqi7S49s-GNIv5Na|(d+6vcvq2`go|;wVQs1mY$( zIS5?KCKKQ^=QstN(q{;PS;{mo+2F9Dp+#D5rmyUI(gF&TGhu}(Q(iJt-@wh{_VjZF ze8{WZka`dW;#Th9KH%20l#`s`4CM%5Xp~<Z1SjL?G$%Ph!PtHc$M}x%_kx(SMZJT^ z4qSiW51@{y>(sA7oaT`DF7OFwcmULK^|`teRIH!YF@(3sX9$3UY!U$p?>aitNA*3R z&uX{{ILB!|qyTaUDYSYW#S}Ql8O{Qy*vhYLj)4#L_tdX3nb4F4XjV(W^S`4E;EySo z!ZU_-WdY2yZ<vhiq~$Frfamej@5+Gpcqwrp&YzhvxMMuW1h8l9edYQp6L_xYX&V-~ z9^;%LUK!<Q4C)1dz4%-j7CASV;4^!!0<_x<@a7y)1z5LzNZfLeZZpl-&0aQBdpkor zxqf_no~&hN@3%*mj(~kzc8Yo32k<b;<tOn#H}dSnI=>r$aCNQgl9=2l{v=o8AKZ4j zL&wGH*7?yu{Wz4b+sT`z$_c2!O6{|5-yRJd*HJZ0w|(uT9<VNZ)xRx)w#$ur8Ng3D z*_-mLZ+pT-(81rD_4V72t496%+%RYSPE4w`r{h`%Q>S{1NyT`O1CG0J;P_Zr0sIbn z)HCa6mvfn*#SZOqd=n#r4&$q?|DzT=Y_~_{b>o8a0J2NZxM>rx-yf)ICuH~m>BE}m zwvD&YBN0Sa*tzR`5VXvHSwDphYlOhC=YnBhE&=Hk^@$hebIN<`AYXS?F`|do`$d9U zvLXoca<dh}=cWDRBEPv!I<19NiybOMC(`O4*)See3y^l{cOsi_{;SgOql(x>z%tM} z`#k&pq~net&ZBSD-<q_Pn!T<KumT-&#XV`Qk1G&(SXo`7H0ceQ{rAU1toc>XcKELQ zTvuAYH^;co#}}=!xj#;4RPT28UEis}Yv>B_A7zvk$p~;C#Y^;AeNI1j88vtW?p<yo z$0_%c?b&fg9c6dyLNOln@8|hCx=dC9mpkKqU;7yzSiU<4?0ePUhAZ;oyS2`5TW!`| zF}l+ddtALdg#T&l4|hO>^co*+j2+`m5Zz>AXwzVXBC-JPvy{Po&YX2nFX<Q5Ex>=t zb$c$UT~_@2T5$!Nz*RiT<^X;{8GjdS+*P(;&pcfo$IWAF8I~$5*RiSsfSp0E4dA!9 zTU;*|AWn)ah=H$oH|_6;39v=X1quN7>%6Vsg#(KNzmvy6ZC(8M;wQlOc}d40&hZ!V zec%Xl4TyWVmSZ4(DBci11pPMG>lyGjoZ{EOR+>g|jd)J{jO0Kz1A4<UfIR!#{GJI! zU!;(5o4H+C?Y9Bv+2?aZKN%3aiqRdbeEWTAF{;}P`UPM-E&<0=fV((iJU6p1vpzxo zcL7v4?av0N&n;klVNcaSXH^4mUsN!%8}I0NDdD3eB7MG|S#~RP2K{uOuFC-T_I>>_ zbG^$NOty|lmVg1S^%-&vxEOF=b7PW^8Rb&iH~B}tR>PP*{Q6jWtj|~39=XH)BzI8% zt4?@mWxN%A_m9%Y61;)41BnQhB0NFQcDvb0=m}`-YS%%J2$pmh-$U&|>~dueZ0+6; zfkQ+g==fRN%>xC4x%3`4KK&oHJm07HT@oM;RhK7@^sMipfuL8eH<<bASLJ|F1{qI5 z$9`G1(Qb((YKhs}cMaR_HGOU}sbl=7Wqh_JtVAs%K-DnRx6R+K_7K&^%>u`9sJ!Z1 z)qWiPfSE|(3!D!;i8DgS@@=N|Iy(w#>?8BjRX4{->WM$H?-vZ?GAD4z;&q9=1_bc! zqu-X_3V~qpKP~P1vwd=yC%P92@J;<{1KG3DI?stHWThVnD&`Lp2p{D0s%q_5Su>xh zqQ3bJqfb@LH)gD&?go;u)w9_82pau;yFYKfPowHa20I=h8}<#h9}Au9<+ncSJO8MC z1ay{;p9hWWz<%qVq90_f9m|$^uS*Zc9q?Ce`trLurkmZZITA?ioJh}gW8kHaY!wnY z_IF(4Z|W08<u2=QluJNHINm6J0kW^f8FA-;6T>L`Li9Mnj8f$f#+wu_ZBgT>@4aCi zrCs(C!~T#=Mwf%gePw5EW3r7=YwVwDsS8kr`^0|wuXEjgy;IBuU75^^2!ZPP{B8%i zs|bKsUD>WYuQ>Ld=Oc&b?QP!?JGS5L08{4u5T*xE33K`;6DGiR%HV!J0l165h_A&F z;J@I6{un_2j<<oI=QW$?7&ysk@dj{)3(SBS3qoL<IT0{TA@&(_@)@>SfL<^s25~B_ z*F5$7)0F9bmNRnC2|+KCa>dnL%?%)qu+0?oi~K=94m#4$i4TD%c$*oB6FkIiz)^9S zv%o@634ybG#7PPOF-Web01ih)tWf~YXUsWI0o0x5&|C!|uIE~=qX14{p<mOlrXxiG zkvJhfr2sUqr5r;t_17_TX6cBRm_X?yrQ<rT;ur-Z&R2ZQIf_Ju8#%-gV4V#%fR8v$ z3_P6b>j`l;*MWFeye3Y8cvqYfp8|otUf%_L%?W)5IL9`pKwqnG)87Yu4L{~BkbigJ z?15)NzN`;j`~@((cmuD3_=|X1Tn7h!CT|tj!#6)uCpZWE=UhtwTp(Zq{D23=cMXjx zgSk8blFQUSVvA8-S%CgU3D9o?%P|1$iiGjM41g~H@(Y%M@UaDSR|dm;`FU{;JhvI& zW2%_amjUbM?}~Ap1Lt*I8n*=?+`Lvewiw!NruSkViAx9F%imuHhRfX7=lvso)Z&-E zpFCImwBqv;KwUgkYFFD{tw;<}t#eG%H|Cyxwa+RfHvYZX<^7depHVK&ILCfi*@PCu z<bJ7l-8w58px@-6^^>*x?o~Xm-4{34r;rDCG(PnG>iC!VF{@2v_`v{ix4?Ri>NF0A z(W5Kiv1<R=FVS9gWVm#zcVD2X%l_II5bkFqwR#YJ{B3OAywyJ*BAxuHzrM@B%dP|| zuE71ifa~QriQn0UYn&(a?2o4UxwcETtOLwn`X+$c<23Gg6H1ityMm7M494!g&wRfO zD3+e%(-pYiL>v)%+OcwsAJ+MOvmb++-&LjjM=g4&i)+>~+1tNsvx_L-Tgk@tu3C!2 z$%<Re3gEuV)1_qoevtaHB!-u8-G9wD{E_7w>1LD@<z4L{r~r&tz1lLNopCx~8E6@% z-zeVyCI|Lc_1nyGzhFM6%1-JN9B@of>AsuZ$^Fi<f3I(MpLM?NHx_$jpF1=m&RQNv zQkCn?kWu=q|H$np@JN*^ZeZB0cI<W>!gqfhj>wo%RxcwsXB0nqiXZWC563pjz7+BF zu1%yPqxxQ!UygoY6sHBP-$r%sZHz{%9%cV*;KR{=_ep=bF)l@yY5#Ru`?+4(yBF%) zWn2!)q^`V5Z?{udJuBxcm}xvH>Z-^3dI!DjudGeg`>Oh#kfC>3bxc$C)yHduB?kA+ z6ySbHth0WSi?NKuznp~sqdxK1uaCiP{CTjx>94b8`4unoA?T;{+k6PTz>m0#j9shy z!Ao|yr&i{Pn(ZL2s7D6)&6viMr<Q@(>*-jHkW4^6Den^@i1)=Q5dgpDk0n6&j2Tl3 zz<pYd_#St2HK>E?R{buhU+bs!9Q1qo5&b5_A6~p#9Ru-^SeFMu{Ac1mt^mF(j&l(7 zwthp;C>X^HV81K@wd0hFELdV<&)CbuwC%D4NS`kO;DcNbG3A3U^LHw5H%s5on9*zi zyP^PGXMpv<U|`26KgePCIg^?;zi$HE&GIDyGf2}r>KWFTnb?E$d*$C{Gr}?hdst%B zpBtW{>^Cw7{PGMV4LdZ)<HGnnuJBAU*GIJk7UR1uZOrdM>j8B25znF($P^De;@xEK z0E<zT?~kzd%VVA14S>45uG{@+uiJrkx3e>!gI$+;Og*39wcgRn?51EI9YUhc_SbC% zTnBgwJ6fH}8AFGOhenliNFm!DYP#rQCvgj~)_*+N{VY3;k7Xv~>UD_kezI+Uw5r69 zto*wEn0eN}ZhS_b4D5iO)|4+>Y}LnKDh~!r*`SxY@_cWYt0-6a0;=uxX&Vqy^@yj; ztaf)z1nU}yZmZ{XsW!^_CW$10y&t2z?CHk}rf%i!r<xLsBFFiu&OQQ9i>&+hGO+_r zH;0(OW7l<zbQs@0i4%*4_SM^E5kK%r^k_@S*f!#3P0tT%0PD&~Sdb0zxy(*NWBrl+ zo!PqtW+~7;y|L!V!L@(kn}<ND_`l{!OrU#pLVMHvQpE@z)iA%?jO|!@T2$DJq5#6z z0aCN)#h&wWn|;--yR-Kv4i?%56gU5#R3uLHU8lP+i#MHT^?Pplh9uX0qWiieEB%{Y z+CQ%b|1cz>PSC^thnB8@@;ZHlHJ{iwro=S~RYU7R4Rqs;-R@vHkxXZ8`Dg`pF+?0@ zL@tc7$4qmSOI6~QNqUsgGYmV)4SOIk%KnfsvEkCP^MzBN?`?}*rR<jkfDtIY_kDw^ zT&JmBA3Y=R-hF*z2ZZB}{kPu%^h2^~yUs&R&khH!uQULZL#&JDEp>`o>#JIHDI4w7 z)N_;m<kEAb(>O5OS;chZ>R0S?v+=O7JZE3PyX!hu=D^Fnu?p(C{<hl@H(aUQtWycc zIB-n;<eNv1!H<I<@FDPB@g);rli#xqTwo%u1aUoA@D}K^oaa378QJ%?QNYpksBNB( zkSmE;fH($v0enO(J|sDqn*ke4*dRG5ngQEvAVI9Bz<kLGJ_BZKvkl@;;<w_@AWrfH z&w==%xSOv)Kc`>kZP0h>AF&P0c%K>Y8Ef1}!KA&xrZ`LiM81VvQ{5<?928#5&DlEu zY>L|r{k=w%GPq}e^R1jkD`A9Rl*Ywrw$d@GQiiT52mU4pm~qOgo%Gx^XDm<TI<CnX z-DRpTC=wNJXCr;0WDE3f^qYJRdR;4yfP6&WEN+6}bAE8(1>i^e+KVp$pL0^5f&;&o zSIaL!eD_;720w=R`NfaF`7Y>B^iTDxz<ZqH8PIQWo+<E~v|SJLeQ^x*zo-AAe**e> zeFZ-P^}@FgtzYr?B4-NE03xvg^v>p4X}ksolX`N%o6W~@ev}%N^qw)A$0?AaIFe2D zx5#}@0J>m;PmVfg#&ct%|Kc3L9+w!|s{ra5fIcw3pS5?99u&s;`#IyfE(7INB~!b( z9x<Prl{2^eYvBiMhIUo?eXOg^i+EJ^5$(cA1dug;CBQsrk86O~<*T`6+8@3wimpuQ zZ3q6g_nq(H9#Hj+!wnS=7-jcl^@*TvfTO(@^@&y-7g-h1A>82`$yDp-HuIp`Vf_R( z`{3?=&NVSYIrY~t7Uj!S?w=sgjWIYH&`%5zZ}LyXDfBy}orE>aoL$GQvf3RDG`^~s z&%5@NbkO7Se56DRz*}4Udm%mSuj|csZR2*C30id?pFRNjwsF`ev8IlJxu2huUUsEw z>@)0O*Di5U<=DD{!N0w|vWI<D%_~7of2)%HNN4@J`cs$ky4p!<7b0?Fn9pt@6QN`I zX?wC8>qUG2%i7gNL-`f!j&i-?+JvIAKUz-AQcJ&=4eLNf!Q5`vJ;-nJv&Uf;&&v|X zlN9D4Jj_#|7t>GwTLt{yxFOGs57_Mp8tl)s&+Ij8Ulx}&qcGBn3&@7?5*jx)sC3;Y z8~R5r{XSS?l&=D0s!|F;@%`8lP~CRZO??6jwSHnR?^7;Si94^3s&9@MdLO6u2={w9 zU_0IBp>F%4-IB!)A@g>!y>bu6eMY$?WCXa6;wAb9eUtuj)WayFToy6{S}*nf-CqmJ z@d~b?H{PS{71_;kxatjUS0({9_OoX{E?;TNC93%$m{r1kVlU0dx$f=iI^UasXX#{z zevD^T?9|e!eC5R4rabhu%B$Pk`%U)hr$KBDcc5mS)E!(&<BH?t;5RucTVs*}(l=NG zaaiBLI`E*rO??LZpSVTb1#IysKc^ia+E+5~=?lbsUpy}!1{A;HSHKs*GlTStTOy3a zzWTfWb4^{#it&^ItFtF2e<uL#DFNHS76DUWErsgFdAW)O2@pF59^nCTKj@SC3iT|g z8})tq&mf-W*W!Ip-_vjC$AGhGU5=()K1Yy*z`Z=9zW~0?HT)RFmHe5Xz=0or^Ugm$ z_s?{iP#_E-y0VzsGvIgu43CZWWq|aV0Wi-v(lY?NU0!VHqhK~me*Z(1Hs6me2K>OP zPiz6(l>ykcf%-88GkQ!JD4zkn7ZgDB6D%{b7YPAnMmF=n+6KUvZ6mG#pDY9BZ9x3I z22veZzns_jFPk|$t|_mMVSHW-TyRS@TsSh<)ji+Wzs<czw(9hpQAXLF_|$3`zIQra zrUnL>tm>+7SLRaRed&JHn_3Z*x2s+H0@YpD`gQ#>)Qwne`z<wa;)M;^3<ka-Edv}i z0h#;MKa1N$oe2%<fR#a`z4<fH2aOSzV4(hM8ZReW>VL|r?@5RL3O(xCrN4s~J8?}c zZvx0RjbmRX_8|yKWaYRI2Jt6d;w3`@@(Td4>^R<~m;EW4fz!4<bh(+qH4#Ks_^tYW zs*YgBRw9ZaB50_`Pb~e{N%p-TJH+*5&F{=leeBZbd1idf#qNTZa)a9VYsTcOmio_5 z#E?e3F7wMlzJ4kL;M4EL0Wk-G=V>Ry49fPAmMtsmAC&g?<-`$t9TQLhWmV3QUI##5 z_J?*Nhw*)#wfDD{T`pSYS$lsz>A4;bdorbm4R%*G&qq1&K;S$-%TE3<82BcepyX#G zi&()PpKB}LpTv6<ZLz9-i?3ap{$MYQ&kX{>F7~Hy;&{j~k(Qu!-{+gqI?5=6nc*m- zRBt+dD_#_%8b%pq6c`Q&6pqKNySlmQB4g^qr6ch^TMI^)pubR;!FW>xT$Q*Qd)nE4 zUNwMquO_BN12P@%r@3-@z2i2&76H*0ceD+W#V^*?US$pNvG}|@z@dCVBWtf}c4by< zs%KwD#V)_z?=zgT>|GlDon1J)mX3r8YbaoobrkSy`g)6aR7`-kIix=Yj_a5BKJZ`) zLA{VZ=K@n=V2ddV_=rzA4s5Z_6u3VH?rx{wKgl){^ddRx5MQ#*0+{PL3*emCVjEa6 zV-9R5<?1Oj6o~7%itB+XQ?@}rub<M-1NZZYR=~qtD_#fjtayT3K*ao>kANw20?==> z!4(t$;HY#|59c_gPmutQ&j1syF`&z^l|r;L9iQMhpBkS(BJL9pQ2?XA=2iZV0;qj3 zWn5QA|71s>0Gr|vn-qZg4Sk_Brp~iXZ1ksMngZ3c1J)b46*$OYt^@8Bw{isJoAM5E z0rbNhmal?*M*bah5Ra)(^z$HY7T0nUEFNBbq|Sk!>Vx`j(ARR8J__8#8>|B#5E6s9 zl0(dZcex!ve}`Xk9Qfb!FdKm6C=(#!>zs4UJR~g`%z_+9p7|w{30)bVnETbB%*c*P zq2JN~s+*t3>3?AXtQTSWycE!00=&z-$7JbmnI{s+62M*N!1y@7Nx{C`A_2b3B|n|r z{9~4H`e{XS0H`c~X4;_*0Jr_JwC2A$VElSopLxZ6p=f3lSB4!2R{6`o^|17Lrnl_f zW#D*Fd2nwt$cL44OaXj1f7v|8#rYU)0u1;b%+6Q5J`Bdx=`jv4fJ}C16=WYos~V>5 zzN1DO>&g1D(>)63$`Ic6JUQ_GICfwn>=XNlTJM@F<|78`!!G+f)yjA-JKY>s7tbix zI&!c!N+(-tXLj#1p86&Nw~hB`AUmk*_kf|8H_P@S9qq-|oAmTP-RtkxZ=tt;al2<A zYH6XXe~=x<eZTlYH4}K;x_)dU3aBT<=vv<@fNIxRhpGXP``$F*W3Nqw31LS+U?)U) z00Tt|)YYnSyeJ`YPjG3otE&1p#jS%D{irkny<)tGs6vmSRhFt{9&e9dN)JC6_K4R( zGb4G`{1Y_nWP_UWRpa_5sA1YKuLFW5|1X#HSq6wJqXs6UdWp&W+s}Ucx^Nqq{<Y1H z0;^uZl6}dF_;B{SP-MXS&(fReg39khnK8XshpH0bxnM@VSegf99!JP-4oKu_yFLwm zA*iT--ME{izq+u?=QnE}{;c2rW#`4mAMBPyrF$Be=ldb{>C$8Vay@Sk2fpiX&2#^B zDT_<u?dszsLCyJCzj#vHjaZWrA2v#t<=7~r_{eSC$n~Qdyf(D^LBdN$@1u+|E__G- zxxXax*3T%H!+2De*cv^!#4We)LDp`qlcF7aZrg#}?t1>Z0H+VLmm1)C!>{k<j?~BH zK+wle)?Kw5^{iK2Ij#&@{(f(md1I$WhwRO`S;v5!9gKxJu(-tFF4kEC4zn)SPonOS z*M(o7gnx^_{Pmq<a3>E{>aE>w+h(4iQ+urU^%MH{ybnCY^SlonBI?WvG}KzpmkG?( z!ZHANVAQdAP5!lkWCCKH<gnsJw)h;FF=a|}Q@|l|X7r0+s6c-g#CODdVhzM^#I@pg zAdZN0Vg~X#`8}}!{i%Ki;NqM5sJ<G$b?<>c%Lm|_b@d(o0Q@K1!$IIxCL96|GvSO; z_c>HDq-O#A4Dh`$+L^R#QDS1xpuCHm8A_$sqAyBJ><a_%Ud0Hn3`X{|MtLTad-fdj z=xdP!;jx(A%MA4kBR#@wx5?m6>F<o;eVMU61O7|n??ufhTR`dV0h=*AUOK`n+kMri zs${=Oy=E=8YctT-`H<r8YJm2_(=*yk_qNPCjAgZhJHmK{erc3TXI~ra@mj8WogMY8 z=}smVlmT6?3~zq*8%p18zzQ2MwCa8GWXV4UD;ZDizm+Q~x30W`sd(6ZbzAMDf$U0^ z(ntOG^>w~3ZdngR9erg}qDq(XYmS#LO#5wir8>qJBFBE~+W)J%nJrwZ*D!#;V4!_| z9dOqr@x&(%5p`s;x1Xm<{L=n@vnzwS`FrWvchbZD-Q#ad_O8#S|323|Ui4Yq<Ii<W zt+D645;m+8x{TAfBcpzp?=t;wo(XURX0|b|yV<D?a8{1vBdD7XMcEFMM2G+-f`;{5 zWbDe#ktdgK#4H2m3nurV1|Xljo@`hrnS0pKVw4ZdfbzU%K?TEnUHr<dr|kzaqLMgm zQC!mw#WK^obcj2Kd7MLb@_+8}O!xK9DsGzTy4sBfSbw?2Eo95SB1q#of8B}3=ZO*b z?2`WX3UFU}&YL^Eui9xDa^Ejk(0;4GMCRYVu37(%%<H4<AsGSgqjXz1?X-lKtUkwj zj55kzlFJENJp#%1hF={0@BSLs>M~h72bY;;?iYZ1oB!CWfOWac_EdlH=WZW+5x`!w zXSG+$*R3C18R^?3t{Hzj1!(tO4-ItydbzC&O}|jhI3?j2@=5i@;_NZ_f6FU53|z;p z+z4#&A*WLRlN?ZHOiCH!RFr~|7Aa$P^1ZeEHAEQ!+mG~=3&4ySGm?X|jFG$gYU2`< zmAIN~#4+GAF7PI>&V&H;7ktfm&~r|64p=Z{2At;l92g$6%xHOzbDT5YKb9Z7CGA^J z|1JQ_Wu~ePl0<>5>~oxFivqYE5tOcNKFC21ksQn=`k8PLlc8PZAm(HoW%`jNpmPSu z-XLHB;-vUk{29bU;&C1W@s@aoTR<OIbA1n74AisgJMgV_nRu?B>7VOgf_hVbpnnP6 zu7ArDaNv~#ugQ1dz?S^Ad=u28>Na%}f@yI3fk%Ni_>u>K-}17!8rVkZr+_&LBmevQ zyXr{_ptA|w&H(5c;M;6(kORNt{75)9^j-x}e-aZgUwl6X=K1dw84x}z)daB1ygaPu z6|nl)_<KPa;2s#jdb2!}G2LXCCx1>{0=&nDU1sH(e`B;lS?fkqpP8?<8PyjRe!(nf zZarVt99=FfNV>_WUIo&gR{-~2=E_CR>=rxvIk&ytyk&hP8xjF_YcHiLR-lXVUblTA zz6`&Y%f3#v0Bncef2?{RW&&X4F8BynM)@Ib<m(F@w)M6ez(D!=uJ+J3fuier-WA|% z?%(?C16}vyamP4KJ@9py1dh<LwSE1-5J2c^hG6%IU(m_^<q~`T5RuflgWv7~*bjTg z2ixqnYaFE=VC~j!-y1HX*7gQo{TtS%Zw6lDF>26{PYWg86C-4$-wAp}Tte$+MIV1v z9&`N?9qf6`_l83|(I#@JzjUyNprsyl32`oobS~|yd%kM9AtCg%SL6HoN$dN+OxmZP zq?(bwnz25p1a#XsrAW(vSq$#kr~hj3H{YGj;3DxyR(aL-XT{S>4EI&*c(Wc^qCf_` zPvU=Ne`_-UuUY*xaiy?m@$2;jDMkC6KCkn?ix&GUZk!9e{HE)C=)3ReDp8B}>-KT| z&oQbK7}~~PU4Iq8<!|=H{x|BOhqn3sQj(x!!grCdBpcT;zVqZ{z#Fg4+kCp-WTqHV z!=vn@;XKMH9-<%P$9h!5C_~726gEn+03WTPZsR=4D5Jk@7Js1XD3_xhw*_RPu^(1B z4~e~ysM>avAwf3<ZhL4#M3u0xA==cBNvm%d+@D!ZE&(u9jZWl1w%m5`l^sB+UggM@ z`j`C+JS&b1k^`p<V47IoTKdkW{z>x6I-Eouk>R($dlLR7{xbjbvE_L_ZoPs!DA{*$ z6|!u+;yQbO(K<d#PZ!s56^DRZxRQeae9d&1*Cevk{$ZFHUE6Y+vz!3VaE1k_H`IIj z7EoX4w>2Pc=jU7j`U-9pe*iw=Ro((_(QoThpkL%U{WDNo>NV~FX1u}off?I+3dAV! zAO$e{G&4fr6f+dCMFJi^EPf?^Y}6~V7|f#_7#^o~Rc2b31~YmLL^*)H3{0Od0o0XI zVsgL{Q!uh;pB9M+an6XI{oZ73&luUI0X<hn`IGcD1G*OnajFDd$0$E8*-DvlJhFi5 zQQl6h?<K#RTXwv*bj5O+(LGptzidJ4*86pUdE2krfO{J_Ugzf*R)4$hGh|IYr8974 z*zq4bl(q_gGoC1n(&d0W+Ql9DumEQ1<u`U~J*QfMmb=5O=eqs~SJa<zM`rY}cYlzl zP7M(U^S7&RfX8q^{klkTPM~TShy&-=x+GGofdT3^(72C2n(DtQ;89=z9)kh>fte_; z2K6U_rT^|b9NC~(S0-lHdREzuFM!xZPr<-9c!VwAtoyXB78B3;t7=^;2N>6NKy_Dt zAeZ{H+sy~EVqB`Fy^;TVpzA!=c5`EwxP$bFm&G*z;Ly?Uw8c%jucNA;9XE^vS+WyV zIezNwVUkA!>h&Qj%8?cRU0O9a<D)VkQ*y};llKE89JuFOGL%3x|M!>Tb<+4dV`$ID zX$G91Q2^%y<8x(w&n|ai#Qmh9kJtj_7tH_JuP>H>^2>S;^7;(1V{sv32^#Dqa$HwU z8rEa>O;Ukjw{<|>_QWQ?_2gui_J5J%dLwFif9C1GZ9m<n&!O~_`JJxon4x6Sd!Mwk z`}{V4z3TmZ-+syTJs&vkQLh)dQhkgvisQ0>lu`TwOryivdoluHN7>)@yMJXIdBe+4 zK*$lue0hi($8+O`vwl4{?s#^>K323o6X8A{v4%$U4&8|005F%SUe$1|E7^@)i5++4 z%`2`*^_`z(Et8nb)#|F|bMx?|AJDuVuwGaHE)4SZfjrr0Z>m<ms<-cvgO6B$KN&9p z3}op*Dq1?=%7E_@c?|LWi?7Y^I|l!*_yey1r+A6afor*qO>$tYKEWBLzzNPX1EwjL z(Ka(A@G)mNPr~Ru1^pGL^>+IAHi+ZQh)EdS6>y64oJl{QgFeM6P6MZy>M5|rmUteR zCXDR*1zymvf<D1SybC<f85D?T`3Vn#_yaevot8fb{Yp{~NCC~qIL0*;faZh9(%*+T z$fnT;C;2)(oXMDz7o4F0G9Tq?jv9Z@h|}P90es#ztYn)R7t;3w;EX=Om&WJotZ}!| zkDqdm^Tyv-Ff|TI;S07{1Fj-q4xHA%(+`4P(<k&1(9h{t^a6CGf35!jVpH9t{{TF# z-{l|(B~FPSL-728n-9DS>Kgsj#k+u;`2k0O!%Rc~;z4fW2cRF~N`41?$UXWr@SlpS z`2%o*Eh6B4?hy|d^<Ct^@-p+eGJwtI`&EqXPzJ)AfcMydrN^c67p3pVIpDp3!56IU z1#n(f0Pr(L@$&EE6o4*EOzz48Y{wP^T2U~hC;BODEvvsQ`MNk?*OY<eCNF(5w`YKU z^I7wy`7E{o;`Z@+T<MRRzNZ@E46cmm%fR*6>-)a4%#eR+$*OMf89IKnTPGuGj3)J7 zqsW@|>Rzaae>p*?{rc(;mYWZ-gOxwoO<%6->b~n`-~DSikRMd}UdivSy{KdRJ>nQ5 zsBE{pK2?W)2`l#ZvSUA0?*mnB+)WKImqZoi$^pkqumtEEdfp5M8BcZ%?L_6i{;&R~ z4%Hh7)%ONE>1kh?-3OlaR1Nm&0@&~3|Jo7^Vozd;x`Y&00DM?uXTJRtE+z5?y~b<M zlQF&+kFwXgAhYML_S*)0cl8rCfk)usMe2aw%{Qqu$4jGD0IzIWkJiP@+#<P=<MY~> zrnB)M)B;|M-%HD`su-_j9?vVs^%hj$Xb@G{i>#PW3TAhiGs|Z{c1d!hp;@nt(Ou>5 ztDMQ*yjdttHKeR~WnkHV<|h^v<Fv_tEb_!HS>qqRX<Qd&^~~yRGw7S~kH8^T8?ig* zn_<g3ugm$*D)$&s%{sfukGcY#SE2tnO#s=ce(SmqR=a+O^RWBlcEU8(x=uFtOp^-2 zj#chU6^OKa{ZY%T6YQe?N1*&DowlQ+jN&2U9o`pLj(QknpDaK|8D$igmB2XK_KS=? zwRdEv63e2|es^fyu{*Wvx)XbMm-VlDA7f_wik%r3?{wD3AnkOP(6c{R<%gCI+{Lg7 z&OuM+`K;Zp0l@;$FRd$<-7LCG0+H(ho?78J?PJlZNBLn*j~54Ep$LHuCPW}MSYr)X zXM-zGqHdHgeS7^R`XfI3>zBviHx*abCeM=2t(BBntCD&sXFptZ0G<8rm%PZkpkL6R zavV6%pSWe<{!$+Eh;;1df*C6)JwtXLmjLLG^_O}B)JOVDy$14^@?jZ)cuKscZ-Dsm zizhDr5;!O}c?u3(D_+;H15+{KZr~n$Jujyv#vq=O_lP;jTjkX(Kr4L(2{U^FSbmfT z#SsusfPM-1j<}M8pwX}CI!14kaXkZC7XWWnVjMRa(xCu67l8Mo{0#7J{$Ax*X~#KW zUQ#fa2c>TpzzLauuMEtN()X3c(7u-UgDTn1BK>}LkdiU3ha{baUz6|q_BTdKgGz_e zAT8aBpwiM^0!j})bd6AuR$5Z&ZWs>Ol$07G-61&|Mr;h8eSgn?u-EI}eV^xbT*vV~ zf<lJERUA1BxBcIUwdP(pgJ#8-We!{lvg%u^@&*QTb{1|@pUw-thhO*XxAWeW3l4-> zp<FOm2ME{lMc^Gr{eQX!A$x!@_>hep>0z_X+^hF4_ZJmvy@{47t-U(v7E%>3oj=f_ zONKpc(^*224vMk{M#O+&Ai2;dt`5M~n?G&0P9(U2)=%q8+rU==kK@W>sImwz+I(w^ zHjldf9gj3OA|Wj=uA9K@sF1pCyr71QRl?Se-QKh7-dj2>`o7o(ULtJpaBMpKwPUSV z&z!nK_?O!CyxiiPO}3_Zo^iD2;|lg#)3~y|PUhLi2WMIgDi&hKBsTt@DiIUD)(-u6 z_Q{88+%$08dZ4li5JHb+VRTm_F32<-=<S{chlw|?6Z?;j<W3McD$&hwfBB#xv>!u| zyJjU)`z+qi{@$Q+Q(GBBK$Heg`<|L4r)=AL%xCaM@$X)Cb5u-C-Ul`BFSC|r6SmoO zcC%p&=HR?nAMU;gUl<VmE0k#om_1{(K*^{FT?9MqSVurXV8X1xy|F{*q2QHKHaFw% zrQh##bkiQ37p8=1`lXvtx}Ch}x#UxtNjSj%z6Ep2L3s3nB?qf@ktvC|`IjbguVX#_ z;$;q5Ejf!(eg!+1tTL-ZZS0?S^Bat;r33u|`x#v=K9r)(C+(IO?R%pKx?@^C)RxiA zP?I$TW?mFkJ`d7t{927AK%Oi-2psqCd^jUf+`+DB3>qg7d6PuqeUQjJMM7Q|?oqpO zWaYl7*t@KC*2&sZvv2o0K2c5(HX%F6MIjJ~W+WM_aAPp#c&^A@zb&{bP?iUrzWy5U zit!HvXWc3dOA)dx^-m8gfn7eo(@R?}!ZPky(^xY;z?MME8lm_CH^oBp<d-iqMC3yw zr%V8OSf)SmIyjvBkfdN!3=Z<7ojDQo=9@Va5Zh2LLnzvZx<qr~O)r`49SFG|knL}& z^@g>S`Zal*V!QK#6WV%xKyHc;kEwx}uco?ymibRW1Q8M9Qb>98J`p4=LAXtT@jI`! z?7PtLFB_pA=NsZwzRmV5xvUQKW?J<3>oz$VRN+Mt0}BYU$6&f%ad4b)s!B$Cg2F1o zYm@I(h_pb(yK9!<+PAwtf_M*om2qVr2M;+}?Zc|AR2FV2({P+L1hSl`w7$K!a-$r6 zyB_dJRunl%9f|ETUFSS5JZAE>vySM`;#8(}!)$#i<Oj`fblPsT6b|FZAw;q6ZK!Rk zc>Vy-);aX!t`fGOX*rA7yL*JyR;<+pj?_peD@hSz+)0pTPz}wkRI2s@TA4odl{3NJ z_ag)KHD{UL7blv$Gr6Y^6F%!)giiDIm2O|xTKy0!HEj)8TYHXkWegek+z%=;xWEMe zyvz2HQotG0R{RGXI_Q7x#WdI^b7>6j3oos;?vWTJ%2<|SHnT;eGiw2QTCY*85eiwl zXbNJt_WxK-!#4(8?*4)Pp@|mT2eKyV8tPM4C@l}5)wb0xbsWD8tF82^e8ZdupnWun z2Wto}RpF)3X|D*+ta8_Nfy0xWt(?xivfiT7a2**=b<lNMk-vvX{&3dQCB)i5Hv6>1 zhv8(^i(r*aM;U_`a@PHyL|Ng=kuNVS9#yf<?w2FW0?Y7G!hOMW#&%E0#6>RY+dd48 z>K%vFRZ>;Vr}ZtJ_rPI8$Pd!boa_pm)G>(bY%{4@>n)YGzqd&Vgx!iJ7S8`6r+K8K zL(1UL-d@iI<Db3Z;$E7nk~CfSc9>hwL#(4-gX#5DR$&JLsGIaE&X2nrqM_3{O}_{N z?v1lqa=GxuJ>3+!>rM#w$KHHH1^Z1&x1_1xQ<kBjMBmQ{87^{sHqt<LeG(VIR0>Pf z-!!=SXLC5gM*_CtGV)Rxl3l~AFNa#PRYjK?Ax9pfnjJU&C%TfL!9NpoN@Du5s!IQO zYV<Y%`pa6uZ@M?MSB$SO-o7|9V;~mfz)|+S!^5aZExKzh76e#C9(j6s*?wf2ny}$e zP5Ezf-1D`am<A7texx!{3}Fl+_}6OPk>f8yGZ&qje03eF&Z~oR-Cv{Y9oNGHs;6Ww zN&a{rVAJGYk-5rsYo6pDm60(|NRWSnGw)-@k?nN@_AL{d0PnAVA^*<qbJknnM~zdM zL`qr<+BN4>_oB1$w^#{!J>pbP1(P!(MjpLxM56GQw~*RR=|P!I(O&!1h=(flnyNRS zs;^l8)vgPPlN9KE8$9Fwqk5+euLF%2qCVIFW=i$FG6<p~`l|DYanSG#LqvU0+6LaM zZG1wm%^5`S$c7Q{AH8=0aJ&>~H*gh}3g_6iJ9M=R$&2dA0v<6Tl*<6A3y5oqRS$xt zVZ@C@QJ6ih``B^_P<~%E{O|Ip|9wE<dmzm5{?56p`=jBNnX|88J&TKp?H|m8Y~;hI zet8RDDLX|MzOzhry(@RMe*QG9m@*E&*SgiDtdWi7uU^PH+|HGP0f4c(q3jkB9@XRC z446?8F~-Am_74levg1qHTNWsxuS_(tvq!|qSV0Dl7t6Rm6}C$gp0x5~mQ~x<#os_Q z4Jln8q&9pjPE5thFs1i8W+J4*ZJDsmkASvAw2(b^WW{oprV`F5H-8F53wDU|#9IFo z?+)Ei*FpLTAbAeI1uy?w-IK|rhZ~jqPa=DkYT+Z_561QdS=P-Aka3?+JH=nDY0#{} zJwHqNi(2-VE?_EaBQ^?9Y%?*$XS}pn4U(zxu}zk@QT_gNBRlAg*3jqAOj0=6#QQ2> zg@EjmlWv-fFFF;9;q)vg2|*Th`GYoqo#C@r#E_J~dQB%HzQmZK^C0&ZRPlk|pD0O6 z0}8jQmFjaL`t;tmF7UL6A^da-)j8LuVO+-at5%1RVXKcDB|p!hgNH9?{P{)b0&6r) zI*vZM(V2d%nQ`Tu#?dM6ZM`o%kr?T)EV~<zub)XNFUne~WIG|RK9&rdd4XRUY3Z1p z(#wc~Wut^bWKVG`cg0p?xIj79!ep&lgMRRMr#-91cW|ez$%b7!{w<_BNW(VS`j=1Z zkW48U6ffO7R%cr<4-k7yGHpBF*y3LV#kKDn`RM<NXzDAN-|xm$y@PG4C3PE>UpFL^ zRUTcrlN*U<wFj8+JC$*rojRCtY1i{oPt53-)Yq^*xAHytbS*WoszT#+;$k;897?tL z8&?CO1(J_%8{VFg3)Ewn#^^zkZRP-m3HE&6dW@p){e}$q*aR|dhJ3^v;JY<~zqfn1 zyY0KGxSbPS@V_JAi-K`v^lcR7iTuv?ReBm?WAP^%k<0ovDF$pquq`*d+fw)?x=T3h zBSCg3k7*o>IMc6<n+h$UOU_m#_{A@1w=Qt}Rvq3GdmrM;bNh?yK4jU^swd+<$;Ws( z4o3f$M^xhC7|-Vs=6iq7+&492=8hzbE(ij%L}iKAfhT|f$W@-oPPrPqgo_Hq5@SVu z^9KHtN#EtX6{C~tb<7n8Iu`MYV^CWh3R&kX;xHKySti<}moiu(viZli2wcI~AMZqR zL@7R&?f|TGRv%84Ln3HqPDxf@EOQbZu3CWU$vEc-Aq<dHGX{O1v^l(GdkqEI7$T@a zo*9^h>+1gm;C*Wh)0gRePi=_oWSEvV>GYKxnMD~_OTWeL%bndIWZfc|R1HF@0botc z<-z7R5l<PwRgSG7YM3A@0rfiKq4vp)Q8<$Lzk$p`H&BVoL3YrUi1Br|MO8cU2)BI% z^;>oe9&=dSwrT=*dcJC^lJPyTS%`hD*H!Cq*J6n6`w=snA3p<aliaCHTB8fAueC}M z&F~u4?Ab;A(Dk1USnQ`l%vYUyqShFy=w5rd%~3BM&K_9<pw{%QxlG9!X-ocWDW5gF zVEaZrnWvaBYG98TYG%f^EmJ6D5~hcOiTMYh15W7v!uBS&q(kE6364?gLXU3261(q_ zb?W!FE*Hig8IgN8)N#ZgVXr~PECXNiaq-b`&sHzf)rgs1<`uA=1b&<p&fN-BHDn>G z*(U^Uw_%4Athj`#KaNI6D(WnNwnO5ns^0WjJ7Ss0Z6YxxZituWN;oeC<a&MO5wY|{ zE?slr%eIyL_N#mX(gIo+e%g}FP<{LDAu|;h)$6ug3T=(R_d9<H=S5iubd20qrY=ZE z@m&uazX<nacr2usCcp3KinZjW{_$Y5Q?hlz1w)HfI9wy#cpsm4{2ACRW93lc@H-!< z;*4A?SDL2BUFvMk*P-(+_bwk;S6F{+7Mclr_I57k)p_&62}9PcSAyZ!Ti233#?tct zW8~szBu#s=>#T26VUC~19Gosm5Lz;jzvo?f&R-m1lM#a*VV-h=_Ge;;@Dy#mWZW8O zBS{+4(>8qP(nGF7iE=8Xy3W+JtaB@&%$o7{7bKt51rJ*!ky?*TE|oGDGWxXJzurQb zTB&aAP+~diK}zAKBdfW?>-aZzA?oUc?h<Pzc1cpad<N~TvR4P1df)Y$(K9M+(F3Q! z!<|c8z^@WR?FX}+^RglNEW#2wbL801Jh=G_w_OvJp9y&Vrc`B<5D@V%xGH<K8C2f1 zR23hd@c>DkcvSr+WY}t7S|Jgo=ABA1;lvlByEe0K1J2jyOddk1e;M~C0k~<$sgc}# zG2~QP&%!7mx)ytNijpgBt5Q@ux%A@jE9fxE*f3*n+DRDx#?Sn^C_6eHP5Thh^&40j z_=QB4a2@^(ObY#2>>k~1tanbCt-T{iwBbT=Oh)Kg@NCZGBbq|2doX7_A^PJ!PMr@- z2I+no!NQn$C_aq1{9Z$mYUBJ>2C#2ojt0_a>wXGS9>cyiM}+16(J`L2VM?uI?Y8YJ zw7CF(dLitZJsq8wpz=AWFEBx9NN8_!>)T%TGKy-_I`Z%URWen=P8r1d^zicX=+*_k zZyJR^5uUz;v3`6X#BbNW*m#>-fH7iQc<|pud9JO*%&VXG1_G4+`bFq1@)&R(lJ27{ z;C8C8|A6}+K<!8yy-WL@ixWu$J^0@?cIr-)XxI6+WrXd=n~LXMVSBa)EPqJGmovwg z{lnK$<=^kA&{Np8|5W`%(kCzDNO}~&^)a7+o$k)d;Ys}-ADobJ^C|ltW+vnJ3J+LS zO0nFd+h|Pvz7vbDlU+S3rD4-DjP8LoUHrVKbew`=<dc-*N6v#q0R(EOQ6`LqP{ADW zcs;1o1^1{nNFg_iZZ#-dqJyu#JbU*NB0#Q8=q%UR`#34TH>0tUVw{~B;U{_6{&GbW zf)>oTeajp{`UEz@IRAnExNAu-eL&M{qr*L{o#)hOlp&1qhYt3$iNeP?&@5&ruvov^ z#_9%1gX<7%^aAXx-(9@v>_LA_ybVs1l4-aIIrLnkuwvYaR<dL8Ad8PI$0c9kz14V3 zqtktk0ci>7QDVVmR-$Ple#sp3;?|fm-~FMMC3JpNY`uSw1J0`_|8()e-``X5ko_-a zd1A(sFNz|o|G|^F%OcaI^3B?yF}(?vS=%tNQpLy(zZG)kry?vZdj$MhQn!8G7VRF2 zL;cIfNwsw@gC`u9BAfik6O)-k@4nj#K=$y>&Zy$?y@{(RZf@C+i`{{nwkrxBugZTu znugelxqx~tPD8>(;HR=dNpYv9F99RG18@AL8YQT1qnNRY{8Z!nw^=c}k9=NIEcVte zQmpfKZ*i@X@#X=$S1A^XR5rPkx$Pl^!0nE-l`^ULNRP2*r%BXP7ugp;#^rVOv8w{L zuROy=ncCIu2{33<)Eb67-2Td9_BAz)({f#FOV{rZ$)4_EGSFNGBKEcNyEGl?R}fTM zOI}db9qE<QQ9M%BJzl1lpqIAsQJMED1IeMv@ndh@!nmW?mQtWCve>LpO+_J35bkTI zc^=V8+*M8>b8lXK-}_ZUnLUAH!|on~)q|E>Ti-}I@B4kMy$kC~Cro6%0R$2Sc+k6) zE~?|@0hfZAFzC+)ot<I@uwvlhbJ)m=s3bzGda>hYs3+*(@QNuOlU>wq;Xs#?RbWZ{ z%t#WxaMnwZo1wWma_+ny(-Q6_dGs>DG0f)c8EU(<@5@ngzRC29$3~0xlyAi5V7J{0 z&qFeg8&>?OiW5(`YeM|}0|JCiEp8?By=3;*ERa(NZa)sateM(PS!UiOQ#9hO+u}R2 zW0SAZD<!canH$4_3vWrn@IbnCc2~|6XUTy};L8rNnkoy8LC*tHl8NVGUtuBN4aV(5 zHQA<hIgAr0f5>W12Hn7t28xP5w2Ol^lM4)jBxl+{?ireJ;##+Z@LsAa$IgB!<w@y+ z9;#qZ;xA}e2j>_Nf$Nvj0(W>O?ze@*0+E6WU>6C`wv=(~){8l*lQP4{YLny0A+EYv zKV|BgYpw=TVS*AdPxqUJRj==XAQ9d5IMc|Ef+phLn}`WBwLE&-r=#tWv^v_Pl2MAu zd`ZC%J{bw7c;;}^T-?}86y_$LON%MC#PP(3Juf41nsX^DPsq4<$2W+n;fnftn~{W5 z9J$tddFK}b_Zx5xu>S@IRnA3NZ=u}T^+D%77FrJJbaTG9#Y#*GX2Y%CMN{<@jkc(e z<sBH_n-kd0pQ1^e5zb}vy5daB-8Wy8SE`q*IB`NC6pxrzmUu<|B|uAq6TO_?XnIkW z_?y3YpQo^>Uuu9qL+B6KQnL4JDBS58we?Kfg&uLZjiNsJzXF{Y?=A=bp!~WEXzi6E zQkgT3xMGwh(#m*4=~n^LRB9zF=(<NDfkf#*{5;%7L9BBR@;l>|zMoaf0F~*M^qum% zou58RZ&Pmflwrb>P`-LHF(uB|z$4(=t8)+uRRorS&psawzr8R!g*BVV0k?n_U`PqS zWWQslvxSA3hvCCBSWSmnr>>r++z27`i;x+~vTYN&xjYnKYRfY`GU42%18ZVhJh&C8 zGc+l+3(Zq0zga>+eL6<~^)*M+9LLpP3bk+Vh!^sr6Z9%9(XFZ@ZX=OFLz5ZeC8BRc zPECU{RHAPZLbU~<S37+&qRW827wE`>$RFk^-$D8_J8u7}0@ab>cmHE}DsK>4B4V1g z)j0mnlp$08ZX=;zW5nGvr(LMD|IWOi8nJn+>XR>4xc~sO46@4*43ld#McFSoC&m(z zdJ@cftaeyA#HAQIH%aIhERH2$Nt^s%Zg{;HAHb7nBv&ux)Aw>(LmK}xd@j`x7VWzF zgHo*i)IDd(RI+~f^$Lo>$n-t}CzTTRst`T;D~O8e@<lNe+5i0D?pN5~^{M^guYhg^ zV8s!PBZ2soMSQXbvQud*6}N<uP!F&+g((KSguQb-Wg|%C?!xeSk9!whWO}{bqpv5m zxZrp$;hKvvs9gTX8D1oJ0vAeaeXmm0e?$^J3Gd*5_48S^qU0ltN9on5RlX_WzM#4n z%W>f&Uzf6*Jrt7UuQs=W@kMrT-$yLSG(J9Iv5s80fRZY-6?=ry%k6d8hjHI{zVYVb z2Rrq8e4QbP1v6g0gpk(w7{!KvB2F$BUdY{-(p{Lyn%|fEPuq+vbN!|H&C_vHfWhmx zwA^5ophLtz%M=iUh-cW@lZH`ky~u32qcWwYmm3d1JBdyN8b3IZcz+Gd{iy_6#Pdqc z1ic)t+doW+GD*VnNm-_^GUTxoLf_wSK_%#)7$tS5$-Yb-SgXRhpkF4rPUm*ZK&kyU zVAjb;I>X(~8f=Jmx9=|b6k)gTE?o<!%Ky7kbk{krgOQo~pJM%FD9)FT4$@nuic#-A z)m)1_-JjL&1+Q$A^fL{5Hx+b`S>l%Xiz!67X5H_LUgv6Vso-MEHI)*ZNZ#f>h7FU3 zayW^;#u5j`45l=-o7DLfCRQ7SZfUl9VYLo-!PUX7&p+AOCgO2Z&?TpRQ;_vHO9rT$ z!pr}ZGO3fIXAq6b9%s+!x!%kMOS!i$|By)j&;mxl(5B<Z3Z@DNAns#I?%d9Uxs0E` z)l6TKK7RX5{TCto7r;`x8hn@}lxz{dA(COVY*rNzrg<(bvLn)X7>eZxK5;ijFgv~Q z1Yc<WYC7`0tGT6nIbt!UI#j{Qq)^<EY9w2NM9J|d>%Y;(z5s}vA(-!2Y3!IHE;dI3 zRAB$he%$MXb~_SI(@eb1R<L0}6D#|hV`BS7(aJVKxd31+9-o<kj2E7Mx{V>&`SJU~ zI&~>hWy8&fvoSnY1%-SC7!r?bmlI{z8#YGBiFkh`80`G55geFxKA`CG<MrDwysU$) zvz?!br_xpm*X~<tz&#}#^I2tU^?ZqDqGSi<SvbeyY(G`2DUL}26n_hpAs)C(M6R}h zP^SXWtFrm=fT%#Vo3FN!;bw3IJtClwvXfx_eZjWIcy6%u3iY}!SUr>!;~!?E0u1dZ z12aPlQExOb(SUXG6XN=x&pbjg^@V`4_i&HWdh<IyUxk-BOX$Z=BBqKSJCf3ji_MMi z2__t)E7?$3<9anJv8;#Q-FE-Q@@NElfOZ{+Ms^YwW2;&UrzXCAHV>cfNw}xy(H1aA z@<j5Bsd$TM&GzJV@`pwnZ*%bxCAjU*uvdONMUkm4n%QA=?H(<Y)6s$0CHBDxE~j?0 zVA6E9F}&yK^6O0bAF3&?3p1Iz*VN(ICvw?JLk|LDztL;-P;I>SACH(k`&h|~^=afN zJgI-@qFP(+vIr787;bQjtFXU6tyHZ0_<ZrMGIGFFIJ!d0Au1Vw^XK$v$3eT2QN!GI z7F&P5Vfc2KkiYjMCcw){ZaKyoT#-@kC(oDGS*rTkt+r&|qth%Gt8DL#M(>7P;i8}) z9>_XyS-H}N`cPvy4{=B%MY{hVWQlL+kcy6;$q2Q<z{w^{#96-SUccpjkfG{7aZzUo z*!Zlw624#7n+OaU1wb_s-?$I?Jnf@tWbcr7GJI)Q6Nv&vZ`LDIp>*7ejRkJYDrVi{ zO?KYYX5Fuz)-<M30GOYV$rffbFa3=8!TV#77`EKy+hzCa&bSGGnPMuoH(VeEGb#yR z-U~=>X7;F5(wZ}_C+Qn2fW1ZrIqjUux97gV9Mm6Nw<Ej%>%}HX=n@szytzF=?QFoq zoJcqrlPENb_lKff@^nS>Yk%U$B{JjBPOL^m!^~FSsc~$vv}rZ|U=RPN>Te><(YojM zz!Z5D1NZ##Y;sE1NY5^+wp>Iz+xTGTUUr?sh-=7?;i-On*n1Dt4jg$-5+=1fX9}M< zflSv#`0MY{aUS^=Z4+>k`QE*Kwv+&>Zx(2fr=xvzGa7b>JG(m;InKEfbTZH6;XPk3 z;)4-L@^^{Wg7!A6qhM^TPb3|9BH(2!Yi_I7%bVPQ_MlyD6S2-Lri%Comjg+rc2IQA zg7WMr6>COm*6D+xrstxfDad`fA%L<F4IW%gN_I*{OHRgMJJG1Ctd%`0lT$)c<VJ{K z8r#G7j*lJl$u<P7Uiwh&$%kc_6s242#LNj@<D`)ZxvGo5+rmk%E@h(#5B1>*E6b4W z*{wm1FRKk*MBB5@EYPAf!cXR3`5W^kM)c%*2vW&bt&zTvkepZ6n~8fL_;j;>dVCCU z+T{@mt2<qJaN$ZY3__i41cfy%n`lv-N<-L&5Ql=Qq4vH^V%-$!$hT^e{9t<^E(-@r zDqLuLAR2Utv2`XR*u+4u7mA25%M4KEWizSxl-`ig!UwfAOFxs_6!%r@#oTe}42Vv$ zmkkzWL32<lo2khEa{a%LCH7YRy%jFuXlT(=L=a*+_I|sxeNMvt_?kQXk$DrGVBJ=a z!b+wnq?f}h%&A$uKJB#3qTh6Uj<$ZO7sBz2Y9wrd=1jBme%3y_OZD<LcExOapk%qu zlmoVJk*pV$@E>FBH<!G+F<Z2b8TixD)3~@H^o5Q(SXZ%9z_c8F|MLd4%Ci3Hfx_Ei z`Em~{sa-#TNcF<1n=Y^Qmy>$+`Sj{l>u(i4Gd3+2)R8?#Bc7jKijX~SvS+7$0trg> zDb-V_JF?Uw6K?xo;asyFkadl~QZ;qJ@yn$PS!6W0XW2(l#8Dm(jRSqg;rPj-Vdi&H ze{i{-oe+t?3c43e>D}*-Y~#@mHX)zUJsR&>(+?bL?N_As<rOMIUA_!dn}qaikE4c+ zXPQw-DzJ9F`fj=5jB%l6treD%CPD_M&ew}$dR1>7rrOO4tyx3iO&seYWo#mf8w}OV zF5P(b2GeRF^8EjIQ_8O;N51fXrU6*n<f#L8;ang5ne8i13=c{V+uG=7;fcR~&&p8U zjGO|B|8uI`_AZ>SM9DXxfHlkwURDJAYF=SavrzZ$dpl`Ru=W2*1%&RBzNKOVT`8*` z3-VT6M6b9)UenvDNzZ;0ZML1Mh8mL_nq1sGfmEJWLku<eXv;>FfPcjQ`R*mbmwhQt zR5FpYAUz)i+vq_3#i0yDP+0OA=h!KcTM?2@f~3wNO%l;IYX_`36OWI{u>_*r<D@w8 zTu%fqN;}b?!!bIVGg;h)cyZ)mE;q%>BX7pvkL+><=xN||aGHR~>`x?D?A|KKQ|29^ zYc?-{sISVs?6OVUpAT4H3zMxfd(zBg?4$C+vj`e)i14HFPqFRk=UZ|j)hh}apG<<; zP=x?r1|kUNL%M(vNFSMvkBH1={F#7OJeA&e?SHsUX$k$x(lK1IA}|IfFw-jF^4uma zLxA{oBcY$N&UFy-wtIz9W^t)K2%#tEv~dvu;Icy^<;TwS_{yZT8`@s$bt3RX*)p4n z0kx&l<XxRrrSP6t;}QQHyQ4t=;~q*D)on7@0dNu90fdMnXab<Ous3&I(ypI37D6rn z!Q~Z5kcfCk3hbP@H|AfQv1XT<I#!=!2YkEIfd_&lnWCWSZxrr$1rSWM5%Nalp)btB zL0=R!<Aj099!X+@%2Ki|A=e)a;&a68RZ=GY?g0-c91?ABJD;4D2Jw03X)#a&;>$V$ z{zym;7x=dC9iwRXln-I1Javh`u^!fkP2mPY(;?KvF2x0|tG86as^u_o-ml8qlr=LI z5A?Z1RNCK1G{uLxONlktc2&)srGt)}t0TaF^#6Tc-RFwjP@bHsSJ#54bv<Tz;cy`4 zUlL5v@qUivqtg24iARTJitE%9jd#|;niEts$o@}zV&Sk6nDQpHpUJ9UZQ&|Q_~J;~ za}h9%4xgcfpqSzB&OpLoa$H7f;fC;qGdfNAu*0)qhR7w+XFfaEsRw$d6G}?_l?28Y zMWhvcAmQ0`F;&}cq{ZE8x9^$TJ`corlD)-w%2OuAREVIUn3&Wrh4&5S?odWYkBdhB zW8VV9OPt*>p~24`3A|VCqjm#81Xp~vx5IZQjT?wRXYHXKI=?oQiMD!c%CY;hN%Vsg z^7<m^lBJ_2hb~qo$T`Hx86$=Z{XF37u^Mc*EB<%2=EchBC%11sdE0gzK@KAydt@V{ za=Q0A+LWFG-C}uJ-%yHk|2-NI4)1khrEGLaP$(FAJI~>BNn7KsVnuRZNKupZE#Pg{ z^a@|4ow>vB{}A||*$*S*BbdHmqYMnsj=f4wA>*@OnYWBi=|HPx{^F;@yr|Z>nEy4? z@@F+AB2ZnzSTcSki-}uSythR!#AJQA=B_xbsD7zorjEp2!GlDEV&VBDpT9z!uZYSa zY4*-gs_7+65YV2WYz162CMgsl`R!q<H3MAELVXsupW(Pa$u^RelVOEE>W5T5arT}G zk|Uvu+jsphN8-oex!wCDfci^SZ#o<bl%igr7i0U018FNqES_@eHWEW*?%<7F&N6}L zByREghBTBMIAKrhiGwrwpbWjBb+Rpl5^LRc-4H#8Lvi@f6?L`JCbE=he(+WVG9kSY zl94}@2|8-4)-gsUkvRdbh@1tA<n8|nLKelv2ebN$*B_403=Q<EK?8Tz^R38O*Y80R zII0&Wx4log67Uykkm|ldb?vd$I^@m*I=4vWPr&KDV?nPIqMe*Ls>KeXnTAn!a*>9< zbi&zgBFs}ftt#(rf-v33OY_QtIk#W;Z2{8)z~SFa{X>9L*$81b-Zscd4*T|Xfcq*; z5S`QnS!yJr5DhmKyK&jf9oaQ66sd4Fst<u5yHrj1Ylp~0p8NSf_6?KP8Yg&HnC0G$ z3DAMdELb0aZm9e(_5|IOy@R-ZK1=gE!o7>0?+aV4%5FeS>$no3S%Xy`1kYwI0`)dv z$^&@e2dmhz4u*B=uDo{+ex;(}YO3^#`mQ#356=E>$4he*^0R0LnyHj?k$YiY7r={; zrH7sW*e@rjXZj|r_UK~2zTzQdzp!DVmvi4u^EvldiX8okOjU{h)?Zrw8r0>9Ki8qy z{YpA<p^!zG#H(7KV0&SIYrBkW$8~cwM~s8JN^4|IX4I3u(Ldeu4BeHl$4A}7W=<IW zJFh2rl6Q;SD==6LlqgRz!z@nux!S&c|Hd@wo2`pf8ueagTCu6^FI{c2>6ux8QJKGi zBhr#(s(EzOZ%-IMIN0}^pZ@p+dM~H<@64Lcmg4l957wcdIc;85qL&ueGr7_mj}#EH z$?Ri#=4Puu3(gT=?o*!kG#m81_)LY;2>71nA5odN4w(3Z+}ABB0a)4A)ci^P1Z(Om z51702ueF_Ya0x+&HY~4X2)~;c_uO@2n7XLsr)QiCw<9HE-rM+IE^=YqoH9OlrZ+Qf z98^!P$vT4XIig)vj?b#OJFic<?eW5&G$jxOo2Thuc@CFegMQj3TinI0f{wpDfue~= zgqjn?K2L9lQf!u-?(hqn)UFew2L2fpJj$W40?>uwf*<@%6SXVdwSy+D^`imPXh^-? zA#(VEi0J}JE$#<J_Im>Pic+BnRL*=g)%35-Z6Q4+=g75L+El}Vk_X3um?MIB1ueq6 z-;T;j-jvHG6WsdZT$V}76o17cOfgyx<1W`<e2b_{f5_z~=LtV#C2TVkDW!M!1!k9N z>u<}Jmvd`x{YFL6WS8l0dfZ>w-InCE%O7pAeng}y;#4s$x~FmiJhm>_6dpf16aS5` z*8cZs6<N~^)Q-z0C@f3dXM$W)44}6^CfBVo+tZPSj?7rS-;uOS6EdU(jhL4dZOW3o z(c=e9lJSNA3VZ;Hozuoj2#NBusehE?Gd>-&r}9Z9SiO-)o(U2mu=lpC^nQB#vC7_a zZ~ToeYQOFXyoaw3bOj!V*^HB~>c2sPs9DX@^gt_X0&Qx`Wp}#n02NwIC<%T}Zac71 zsh^UZitV_ZXXJr`Y;M(W*eV!AZTwDNkI$TZmZe-TjAtQ(SY9iU8Q#S_M+7A|6XpHc z&WThWW^zWn8f&D?+aSPak`0~jYacEMq=n?oYl6)<va+X)DT|aq$l1iBt)q-T@Hs3w zIix^IL1Dbs(Sf=~F3e!~#^$y_)Dad|B;MYc(*i-g2y-tSr!dR94z$F-oq1nd^xDQg zC~sCVf4n|Kef<0fH}Q!prVIO*+N^B_?Iy{0nBgx2e7H%qH|3Yle&Ok5i!hZ+9Wng@ zc!F1CD+&;1m*HlV8=bZF-m9kz0NBLex<z34p}z!STIeFJ_ZmS=#&WT94pZB(;Lk+9 zSum+BXAp~Ht4~`rg4V7)Z(a5ffpUgj<aoV(k7IdS;(j$6@q7dp#`G@?fN3hTH7Zu| zM47hx=}k)LRZiccWJD>6CX-p|0rNEi?%8l_&z4V_H~-BLmR-miEXeNo{{0~ee4e}X zq5$sI41afwo)*KI0y;t4vQ<yeu~rVAGAl?3YBwnfL+GXr;i>_}MPvS>E2oS7wCdn} zT<qorXuGq&upNV#GpFS22AvKG@FKY39lFMQQr`u4yR%gu)0S*tayxNAGI2=Dmdf1t zb9x~Yw|@4;Eto?=X41x_8&PHRwii`PN}5pIoBe;vdQ3QYe4tkPW#LY1cO~elX01%+ z4%-UH(E&80O3^ey5w~uW0o8o$B^Ku&t=8|Duiam<!*8AW8SgS^*8lM)B84Ln?@Uc+ zv&ytyo*-t$Q-cjIG*(yNoLR2DQ^r2?kAAOe^UJ^KZw~s89r^+n-tY#t!=mih6%VZr zhq1@pCt>Wlx*Pv{xW5f!H-bq#CK@JD#9%2miP=ZCJ;+Fmacjezwta8ST(X>3O{ZqH ztl@*i*xz-xADlR&YHiIwbEaC6)x@dYiT1g5lHYJTK_q~4YG9rwWtViXOiMrq>Y!Kg zSej|Pv`1DKU0gV>cP4nOg_E-d>H$;Q5?5Ts5+`@D-$!KYPvvuI9CAB^QC`MC9%*!= zyKU1&)oB&TE$5DpB?6CgLg!+9*&>5=BI-b^ge$*=xrxCF0Y2nbozInO0pMKO$74~m zGy~`FSABKC<iDq;9}yJ?`vgg?`>}7jt}2azfr0sMv%~~a2`h_`fb%FzY0j-D3AHgy z?!+U1qyJLOhDUmoA*9KjRrAu3Ps3~)2(?Y+ygTFHD~-(vfXRwHK@$uba%D;VwGjh6 zxlK9aI>cx}UjHe8J2ITlQn|crWi*&6am^xVB!y`sbmsagadfUnU?bD!cA}5Kt4UW| zE_&m?dy@?BS{N>pL=vaZ*eYUqeh~#q1uSw@vN_}xw%2&YCcDgi;%R2z_{&gKWoGT5 z!PZ=b>kJz3zn0KLT3)yu`kRd2S3aWMu8c>HD9ncW{)%ZCI&d*<%NUc-G;Qa|Q#g;( zB6zm5O9JEN90?g~_E&N#*nm;RE%s9!EbCRjQjE*PK`f(G-!0xu-Y@q7mY8O2^w4-6 z4!CG35NxIc?g!1Q?TZy)xG6@Mcn$2fn5ZSOFUrnJhGi>`vcj8}^*@0OgwB^d*atB# zf5hqqQi3(4a7zJfnNz;=z8nsG4<}2l38m2OpI$c|eYjq+7x0w)HX_lP(eEd+!+q<c zZ}s#3bi`HrU3J6(>5a_7-HnQ@9MMC$G;B@pKX%7u5yMF?-2sEQON)$56iZDl1#eoh z*s`l{M@etiCVZFnzoRg3{5pUByp!`R;50kwHm@a>b3nm2HS+SVF))Qr_>$=Mv4~8_ zQ#4AK?^kTW$v1gkzt(|N9eR}2V6xKN1I5GH+ZQDL*W$_2L#h(Lh&4~rR6g0BR2xv@ zQS>MY5kigkX={*ZpOJ5@riR7)J^;ir4ar8uq6=<zpXV1_MdV^^aN~>u%<1v~$jEmP zKb~;r$*45M9_&VL7F!$asw`V=S>DUD<1v*73+)tOndgw+sT}H_pSKn(!m_arJ}e8# z1y<^;KkToPx9eK!9zUf9hXYm?;onLFun6&*%Gf5xLhZ6mLfKp~=R4%JhzjU?I@fzH zr*I1wVIs+V`+NM(?rDG``f=}xsAzW|!fd*-!YnzG8FQCsK>d3Y#mf{gz2NL?Vww}% z+G<uvKP#e8!Mb&^qQH!l$bjoOJqXbyO&KN;ve0+1r~`}(|IE^1w{s+XJCgfb1ucXC z^DY`rnnu*vZnwXu7N8mEGhEEL%>Xo%hw2c7CP$_!bVU9Gh`nN!?aAt|@=JTpS|aN$ zkCdC{rz6}Nkuz<AyrLR1LA(#k+fY@{cD=x|zAjWDYLks44Exaifg^f(oP(agr2}E< zeKMD@J*5}9($tSexbYVdf%Eiw3n7|#rKCt@itl_F;ka1u6@#~=bL_CJB9=ObNf4rP zNd(<nq4%^48v!Rg90^E(dap2KvRo_NE^|SFhcnP!Y(2N0=|32tM2lQsM9be@G6#7k zRG$$<5BYf|B3#t@1i0gYfIjWdC4-0-@CiepBej~wf!}IucvpWCZl$THG=#HRMr;Gb ztclhtEt8&PIx8EW`qsVDPbdv~c9Cs8th_`xf;4HU`e9^xfqmrpKxDLjv{pZ>V{BuZ z5H?jm96KH}I#_37B6<`v@!AfyXH{sIdT~V{iRJx16X{i)xm0KI*@Fm#1#Uv!Qt~c~ zM^P7TP|tT)a1m{29i7}|nr%m9>5Ryy#Z6-`6@?3(&Wlz)m`z$K+GOEqVcjtNebkmR zY;>%o7$-!nBqa3nYw||fQiNY~by2(0@8pe&z&b4}O}Y8<)0+Cz^TKb9cU2R)?zph7 zaHE73e3q)@;1Zp<I*fiNXec+P(jA->j2UoJSwJTDjG>t4-rpM3$^^Hdn+sQxg}VRB zta-)VlDplwv8`IP)-+GPQT)znBDO(07g)fga1-;A6IkOSv+We2XZS42!})qN!R^V4 zUB!9ddC;BxXlH8Q&nP;vCC?-7JB0>}xc0)s$q`YtjUOH+jmUR<9Tfb`+n*C>-L@)o zY}MP810#_8$VH7EivciOS+M2)-`Q8`d|&-s_79s5C9&dw>51T)_&G(^@xzknQf=4y zoVj>PeOt6Z)sfD#mXRX`o~mukkN0<CL;P%6rTEFnE4num<b@9_;@@gy>F@(c@qW!Y zd_5%n(ZImw<Bk3*4$cewim}8h^CuoNEM?cYuu(<{Y23RFm`uC19=J^i@#W4qczWtt z@7nQWT0}Ew`jxzRps>nJ60qh~2yoamlXx`op`5Csduwbkz>Eq1ZzHj_kG^pFu-tr^ zk-<n~#Ckp)4|a$U`S8EuxO)CNO!w%q(WFAdJV!ZV@?Vi#8N(Au&w7}&Smc%j(V15C zi^UpSCb1MJ4jmbWt9|mCi+CZ~Uuvslb*rQRzAQ}nYdzynOwPCxW9nRkF1rfTQh4b} zz0ZP#ozFFy@db~N+Y_M(+oN{6)MdTi0Cm8r%}GY8_laki#(+k|z;5K0;s<}xml%~W zCGT~F<LT3eRRO9f3#(2Y9+ITrM}^xux}dwqw%)|hk61HEe6Qnasc;-RkGkEiKc}~Q z;<Onw;jx8ZEB%Qs6rG5*x@Cr$7LCaOaIteQf|U&(-b;y9C52gQ#)csJmxbu<Uj%If z563$JC5}_Yiwa;cqFkrq%|#IKiD^cceCgL$*1~g#63y7}>#&Iis37l^{J7x-><7{% z*{w-1un?Kp%J_~lu(B-Ws8`Ky2Kp=)K0l1z`-Yx3PN7GF|Fr2IYL%>pG%(Ab!`?DR zk<1}=(Tiq$+95N2)a$gCfTySEfvWvcQCj=?>yA2ADECj!({p-j`g`*ijm;m!zbLtj zS1}DJQw)pH8Hr^KvtuejUs{1@*1)^D;E)A__PX1Sr1!9dLYYXY<dM(%>n`on(@+%s z3?4XL*vq!{O|ai8MEUDBj|ejsE^=s}0+S~8<$#L_xlXa!)x04-+{0WU6PnKC2d&ab z9$-mk&^lRX9Z+5o+O{h<Q#+G?fN^}*AbYx>KAqv)FFZ6kooMoMH>K*r3FB>kB(?i{ zhI)E;&iUmLXf~_=w&O^?YxLI2lzUjlw<XC?rXK?>mA**I0VjnsOhYM?pkK6c?+M&f zw7@a@#QkS@#a4FYA#Foh+RP_eyn}i}aRDLCa86{G;E@a<F<iwa<`k4lU5~^eTMle9 z$z<-ScFZkv!kK7Ge!f$*p750$dzsW#{gp+{X!N(G+281IerY4>Z#Qq<q7M^b;VLyJ zg)Q6~16pUZ$0sqyg)>uqmtoVf)_X!Evm7#0j-=QVYneVJB!h8+P39#iT%o-J?Q0CP z@!>gOe1<_8l%c$^ij|z6C(R0T&|8zNMYi4IeMll_0p4rwp}gAjzbPy+1R>uUHvVov z1X{2aOKvu}=&E@vX;bIjqcG%(yVK>iIdF=2GeFbAa8rbgRG+zCF02&Ar;4wZIUnWk zP3felc@#Aq76r?VTcH;>0kE2`?>50T3RT(Tdv$r4QnyeF3NLbop@+^_u0^mGbcqW8 zTrDMOg+pkT5oilE&$K2%d`fZLxf-^GfRCBCMIx_Ln^m7o<2(CyCEcTxGbH4l>KC5O zasr=dt=`|BC1{&K&dlQDaX?>ZL{Qny!|ZYrC*S+DWJPjr?Q(hrn*<9lf-p+Tjx6VH z7#?MS@;_hQsKBJy4mR0mz2pd9!)JE7c@U@nd;kIZicdUc&V6`h_6(h{bO8nc`{&6! zwv55alwG_>dD}wqpl-P@D1NiSl!i=OEs;p_y!Eq50s_0A4_zp<6!@iQ`O$xi-3`UK zMc(KLlg6pRe{SayNt?M)tw#lB<f<z2+HBqzTZ?rEqWIfZ5o{!F|1MQkiah@u_4JjW zPc0H*<ZxBtgjZkndWSg+9-1a>6g|fYB?D0-a+G`FxVB|N9M|n*8^YTHk~hxvl=tJ> z`^wkDR-M5qfpoHiOkoduJ@U3F@B}OhJm5BOLs860LFr|Fnd+r%`!J!mEpY=0anS-{ zgAjR~r^GJ?<!S(QVUtkK(a^7hC=J#`Wk?Qd0B*jDc*HK6w0naa@@YC6&9Zw9{y;5K z0+=00^3C1lD*3~HCs%b-?ZkUk=Uce<)P(`3{CX<bv%W@C)XyP0bxK0)$p6OC0T6~+ z91^qY8WNfu$MTkiqrpkhFF?M|)yaulYpPhGmEc(R1H2_Xyn&oX&#%FA_kq{(k=O3- ziZ#~oVpe4!nXCpaqdRD`@st_bDT2wM3jZz|T2i+X1soDb(@`4fTEiJoTSZwm#Z+e% z?rdF4+mcfR-2Yv7xhC@cR~@Ugytl=*`EuV5*(@@0Wqe!ec2^y*F2<lx0~7e=m#<$w zQ{lu4op%{`ET|w*+yMWD{KrUL_X#L_p%)hMTkQtCp97fM+P2zG8voOry)m!rSO2)h zOm{HN<hz!}OWJ=Y1Aw?VQao2s=8o-tZVhOr`8Tn5`tx-f??g*E!n=Q8Bd+W3_GqDj zGF~V5j^`r$Hcekyc@3esV+fhju&lG%8=o3mLAH3Ve-JGGs-)_i+;CXWILR?5ye@IY zV^cM#on=Sc&ST%cP@1a?MS2u+JLCU%Pp}WI`(Rg2bbl+nZHVgQPWc*&jbb^%hk=Xc z&%K2?ufht8H_!dUL(!iM`Ke*^Iw6csw!@^ZOnpdEoQ6tu-CQ3TJ|wL%rv#=H>)+T} zl9agU<<H9Pf_cXFcdjb6Ar@P=FW~cMKIbb{+dmg<m?L};e%jFQx5fn|{@s`)rJJ&S z17w5A%4p>2CTOGxT{O3?D&YM#H7gnMwTNikvz^O*Eqf$8>=$u}hhsR2Iw@h1aDSk^ zB-4X~3TKCQG=~vuiB={((H=Sv_=%ynNK)hA4ip>6TkF)n$j-RQkCIY2u5r^ehA*ft zl-U?cjXaB3)lmlF#QDy*5w(k4?jNtqzz#j6QN-9UQohbp_+NW~8RS_SoCv5|7uTVf zpO6jKsY}$gN%59^B<4g<b`w+lM768Tiy?v-tPxtaLU>)K-bv|NRTfG)GUrT;p+vWK z-#a&o_?7~ItAiE8h6vPq&#Z{ny?R0JfZUsp_)N)^@W~c&XFt)T#?V!FhFJRmHyH_; zY}3eOcRqV6K3UZLl3LrCtfG!WBfwXfo&_U@cldJZ<m@W8b(gy`E_$qXlIfREx@?|C zGb4hDRkQBT#6Kr^T90x$3jq%g=@?HM%GCgKA)964u}cc~C5}2CXTZ9fmRPC<U}%w> zKh@)AMhfKB^8unCu6{3C79O6B>+UztyUO~xTMxQsZ)Blb%_iUpVIMS<jOuCIz1tFe zlrkf)hZ;wlp4VplOr10G|0iboGM2Ws#-hLWVtwHHkQ^#XCy~B=YY=Q%TGh}~<hZCU zb?atc|5;MK{aPa<=tDtn<mA-m+(ApuGS`541vICec~!}+k<Ylp$McdN+^5{``SfWP zgDIxGA)301IfC3RFP06nGI_Sh^s?S{pxpI1!l3r!(pExEUZpWL180}(WOY@N*W@+Z z)M`$q*K60iFhdn23*g*ybMQ-q1@YKGE7q#n??MM)@Iqx?oz%HQvidF;aHfN6-FLAT zZkhLb3f#^>M;MAOOdImno;jiw?NELb1d~!5N>f+?V_02FL^11)F7zq8(}ugm0EcWn zbB$bG<6eWwfG0L7NT|q0YVUV4Oc=@HPY~X*;^4MCbW_msl+}#+$@&9{qf1$|soGw| z7ulij|6<EWNM8Yt4eg$lw5ORilGTX6VqBsx3urUjCh$%cV1STo&+$I0%LbjX9@kM! zUt|0%-TS&K;$oe_$fBPd3r(K8e1D7A9Z*RXblH=$TAkm0t3OQr2wa8bWz9&cxe>mi zI?lVeg4hb7ro;L=!y6NV)&D_Nb_K)euQYZUkndR94N&jAdkzIZCskK>PM_fD1)^*) zEGLD<6rBI76&C%xLhI%L1c?UVgV5;)AFYdyv`7?0_Ago!A-mtCldIWC9F>ouXBC$S znBx)bTiUS%tDcCqZ^)+Lh*ObI16=}TFt6Z!R1+o|Dq?!nmPGHgTN%Eby6c6i@AhmX zHy)<3CE+)HaL~qtLV0pmILfzEujevu9jxT8V0C}B2p_iX`DXcvy#t*a-+O}0&TqoZ zt_T6JL`A)Cz3Uyvkr0@mTsB<*y%@=D`(nQz9x(S?dS_)f_KMv5tEe1^)iIg_D8@yQ z435#Ui}v95PV902BIXmTIwI`?A@c3wlvBkTVr~d!3t5G0HYpCl_l9%;V`(u#_xhq} zdY2Xld5`bU_)5jG1V%gJQ<sI;fGhEU21;$bvq^Wa{+d~z6`AwX<)a9duaT9<j#C11 zVp{+JHnPh3Sd&%|{6Rrh3!ECjKNaEcbWTj`_Awl9Iy#`7Hq8BUZ9KB2w#9&<UzY4v zq4fewZcQEjhQ>{N4v~7a4e@)nh2ZKOCZahyeHcM_?RKpRraKSm<o5(!CzE!N{3~AM zi6FtS313Ubal~UMyExeyR3<N@Zqr?^$anZZ06Obb{@AJ=TOId+M4yEs`;M9bWtgy9 ze1D<uh*};)VZ0m-zPjj`%dZ~n`c1;ayv)>BJp*u){&UUW2XdgfHGMhx<!H#$r|6%i zdtsAZ&Vi6)cssRkHDGOxP9Gj<+#hJ&GFCiij6MMWtm)Q)u!Pv8K2RO5>S}Tqs8?ip za;eAC<FYar(T$wm&6=n5t)jm?8LRiTW>gK3Uf#;AkV)^VT*g_EC^A+>{P^XUJJXAI z@*1PYXV)COUn#Lp=l_OT9DVKy{Le9azYTWJwR@A<rFEfH@nANf(1c|2{DegrTLay= z>g^f(kqARbezufrlkrKE=}$g^G(1YyM<=|X-m=-X6BPlsV_GZW*6I(V8>*JVuyejk z%3XD=Q}ajY_s^|8+bERi*Z1hYTW^KUIo^DHc-%q7Sjvi~Z8`UXvA_LMuWu67T6F?L z<1BPvzPs(JdSy;+xq1oK`tEGB;HffpR>Vu?gwph5mGQvVM9o>rk0v!nv%$pR(o4_{ zA74!?)SZ!A=vZmQ-oC6ELGa)AR(+Y9u;rE#SJbx5N?&p~f8C?HiUkhB2VnJFaV7p6 zNC8j1gEgN34Sl071s=A@YQ{C;YnM;HF6RAFs*GmoR3)+QTI3jgce$tnr_Vl#a3qhL z$Yqv<C_FijB7AqJ#i>p2ECJUif{uN+r^J10K9L_?VE6}bCsTc!V0{hH`g^pgx`XY! zY}{-;F0sdPo8zvH{)G;VihXGfm<E@3tgJt-lZkr~y>zaS*cG#{qo}>093~t@YaX@q z`$1o%RlqN|CwybCs*tf(^z*PjB>t-~@PDLNzJRk5S-C3vbOV!4PB#3fLWA>klg}fO zxOl%F+*+vN4ee?5AozDE8e%~y=FYFcCfKkZ^5Q~}-mj`|pMCH3{<=a_`!cACG4m^m zeml`?=vB&`+A~9lv;sto+AOO+o06jLJ8w~#66f-^>#;l__#Nw_l=V;MNrHb)PD<67 z)_X+-U9XE*wENF7;ey#a9!0P@n_SxEC*t<ETG=h-BRP@K=xkKv(TR(4iEQAP=}7l? z=grq02{^5JCgEseb~&<jH89@{f!@i-m!3bcQCWiLHnRm)Zw>3uEGOiZO<NC!AbVAx zKP{o-y>ldWD@}-luuJ;^_hy~@31pFZL~*v>Qjd;<zlt5-W00lJ<FeDpY1hLy=xJ&H zipv1>$xycWo)d+SfX5>?pDrM>Zj#B1co&~|twhB&SJV<T6m*HaIYdYOR%-5%bz&LL z{(k_rKuN#e3#N8OnZ+Cm=CZ(IDz_Qiv;JQ!F{)=5f|q|E7|e5uDkk>jgL%a=@1e5# zqi#$r8W`azwYSb@nxVvtitjhsWL;VFnsQ`|Z4b2`hzBTXrw@I6X7sLr{NNJWw|9a3 zwyjrGD}!FY_2(+J;IfYEx^ADf>>pH*QKcHzZ(YZIS3tfm)3<Aj<E4FU^X#k!_dlv} zeG#`X1$QU-P*%HSt1gw-{!DrGR@_j6?C>1-8>nbxI&S85ZnuSL#rTvh<#w^Jpn*BL zk3O69*lZ8g?TZ`ya&>vi$q!WdLFLe&E(t9zOxW)Jx?m``_XmB}Hrbj!G#GFD%-R_M zF>3jyY8lDP{jMDCa<LSzs9QJt*=5kGN3(xy3u$M5uP(6-FyCgc#XiO_k;PtzxUUx$ zd3#mOe!u)Xdz@Ai8x+sC_q&Tm?^HhqmDS&Ymz@^`0lw=Sm5yiGctc>jt;ovp>pIib z%^PuxChY|Cs&!FQLPXoVupFOM*0^f-pVfU{f5V8|{ASnB-k;Z(Q{}JgtxlEv@QiW- ze7qF%RV4tuw7ic@N2Dx4%+aZz7MtlxBhKSk1@XcKV2zM~gis*@PIG~Cz<JJc9$4oB zTfmHMHh~$7l(m0RVsa0x9eiYrYgrQqGqjxFcsX<2_XSp5CA40nd|%;~XwhfC&_yDA zZ=CH`zi35K5!Lf#s$+XZ#=w8?K=GNbdTpAoyCnK4Z+i#^?$14aQmW(B-cCE}JFM6r zbR7v@^b+?-z-^K`!lsas&~ucP$p{x3#ZUgsn|wN|;j)x*A{u4C$(Sgx-^7*CX<WOE zviBs~r#Z@MpO2@#8t4dn+Jo~|bo+RH=EBsoQwbSEjo!cmHX#Qd$8A7wpZeJL7kDzD z+2w?e_Rs_jmo4_ud~hk35;0W6bC<8m&ek8*2X~Qm)ooq-0!O<JTFQ|%Or>>pXadlS z?-W<W+Q4*^DL&JesV5VtUIuB~2>?L}a9zi!RsfEZgQyhXuHPhKA^9U)X<uBy&FOQ_ z0LS@?DR71@wt>@}XM=<RDq(I4nE;ElMVlPv8eomNxCS`KS$+o0nK1(vgz4|*Bn<B% z8-PlCSTbRqoatS^%O{)z{i6Oo?*i}fq5c}gYdkErfYW@+Cr0_7v&{#X2hz&&g8`AD z=aZb^L}9CXE4@TG1zL-@@`GMwF?A>JZ?RyT0$_cN2@|Rq#uBFeS)%v+{Y^GXEKd=V zL#5}f=T}Pyz@PN{ya%ka&KiiX#GTv@{7{@_1N2+^F1-QjY4w8s1jJ1;7N<ZT<4ye| z&{ykFZvbyGWed2DqZ|fq;aWC9-YX7@Ga&B^Za(lh#E-^5z4#YUzvnseB=CRbP6A-g zAtu04t`|3wF!*l*Q`W>LaENt%2E-xOSb#podg<UbNc&-y+QTHZ%S^MeaYc6mSkH8( zasayt47b5Fb%1yi(4P5SyL_yAl!5l;de~lKQS-j60JfXYvHkzNWeyE$I3^br$Lgxb z3_P!#L+Eilv>J)MX5!(abK|bLTlB&Is`LH43LkEr8m@T!4Sm&m)VUsV;E`IV&pPkW z1<ux|9{myo)BxjCGJJejIrdxFv%kCUXG7<GTfbdpRHK)n6R1Pa@grMmkd+hltY_?~ z_pb9vVZXji^|F_p#B>Fmt;X-Q-89zK5BvCW>Cm3g!+$iT)+mp8rVFsY?tZ_n>zBHC zNSFDd+wZ0K`n5@Kp~HA>BiLzTruX%G^tAuB_)nW(iaM_IeB*PzexnUY8+Y`B%1Hc^ z9u^p-{TugK&)IP~HNZOCj?cRG=W_q4nstO-zOu&Ia(uX&7$PVUX~bXx*F}`ZjUo{e zlH8CO0UK%jB_zmWk3q=-765;H_rLO={>xtjFaI~;|L+1YXPXPaCNmDDf6qt~vKAHb zlKS~hmDZVaGRE`96|Bhgbc^GB9@h|zR9R`CJ$%se`!4IoOEIPp?6J5}<Z+i)(t~1U z`{|vD!vr1sZS}-bzUxBiw4NTOwu=?@UpV*;3nQ9vlpS#6qm1G+?*!_qi+{O<8yJm! zJj$gwa7S-H%D8grl@YtsB0K42yaZ|#e|wV7<7aQpB0HVHw9`OxIlwoDXlJ-bZP)ke zc-QAdE9tB5<EH>xE6?8ro%}#p1EKK=fVu!sRLi(_Wx~%6K7xiB&<0>vzhCIBE>WNi zP%nV{P0U~_XCSH;8xSAW`kOMa-28o=UzDYKDq;7d1lDtgr68|ob^v8w#T+aF*QLey z9#npAUsY@Z5zOz;Qh+-tbM_=<{C-|Op|^lF?&bRx<D!b0ysn<6{uZUWw~r&$a-jSw z@957#f5-{(1#kxsag_Q*fF_GB*Qv~ewQR?3z)VRsi=(ohS1@6>C1AMvp`^T{Y!U+J zI7|e*&(~}LM}RF5-x1e}b0EJXBC!SB!Es^|p!6K%v+`j9sF(B+5rBS8$9e%QP&x(? z@>}so5P!qH1i<wK%t2hOpN(JLfH#02Z-7E+wUr!no=NR38v)s0+2678d2BH3nE>jU z0c1}Y)eHS(Oz`IZLoG28mYLgU*v#)`=Jo8?bwGCedv?FpG57{0EmZmHxU&Bj*3ASo zlw;OoUh+}h0qMb#Kea7y|L*DBR|rFW>(YvQRRPX|7Q3wKHy_=_d#3%a05#RP?v)*F zCtlG=DcYfG){m-_&BwLx2cDX4u6yLIM_KasE+gB=*Z2bG+W<mc{Y)EhUM?}^c6)9e zlbm#HQ|#eyl|v0&fzEM5dt7dsaM_QU>ta>O``Rv1%{Sv(UTZhY%k&x6?Emc>XiU3l zViFFPfO_q%b_2$%MqS4a)=|az-exZ`^}u-5A)dCVodder!?HiC_t!qa_@HIoS!Iu= zKMq>&qpGe~yrf@MsZVLyN!|Y5F2@xZudsoU&GTU0tTwl~iXD4As)^eyJm=#A5U(sf zw|hy|(2sHL+D4Z43!#HQZ_=}BiGM8`{Hk&om#RiTZTgi~9AN=ozYne7tBQH4jhUUA z@nQF~YM3|dr$i0&MfvxBdd|K#Z*57nT}8&cYy#xt2Ed?8{IZD4#g%@#uDmRc6)iE? zmv7{=?K%UlFN|_jY2Q!~W7zQoNpa(yNx5O@L#H?Ai8Y;!jG2g-m*%-?3M>!wHgJYe z90X)~^WP)^z+Zg*pImX>AAkq{;llB2fhpT;0oy5qdz{7-iyQ9ZQVcN`nMd4ejIU;K zQv3Z$(q0{>L=ktU?VqOKH{!)YHrSl0M>AfVy-sTGR*Q_ANrS>4i?#Igwer_>_MDG< zM_jOaw|W1mdL}0C^f_E`nE`Txj)_z5@fbf0N8kQdJA8s!+-&>T(*CT??yJr*0*Bu< z&3}87_-%jGbCiAV#zq;%L&UatU%Yz>H*kA}WseSglu<@m<w9|kwvEo{g-5w`=k0K1 z<0jan<N4BFSB13)Zowt9uIzS|ULw)Jt<SVQU2!Xe75SIt15SUx;KMi=;LrHf2JC2J zth0gS_V<<(GnTKKt~)SqVsN+h*tU+y%8M(Z?xy~#x!k9D8=J2bwVAk<0nKuWk?CEQ z89BDogN`8eEH>l53D7s6TeMS_4s;DbeTfm?2Aa>7055U=uLUq=#vJ%JxKbPh0uJ## zV9Iem1E!qeG_b{KPLeROpCh@t_(~woJ%l7o^_{iP3^*U;2#0_fGuD8ENY+T0%#+`p zVv*`6hV+8uoH0dQ!BIAW`#CEPgIH&akAMx%vkhz|0Bt>Iq36JdTp^yPV5|>WXT#9L zXMCnVG5mx?icL&_Pj=v?a=jLP1IM_U>kN%X>F3$OaX^$ZvKNpG^J??M9N{WV(3dP- zvl^sFs|5qqj0<T$2fzjqF|baUGV-hZDG9Uslm)Ps>pvm_aa_DD{s`hL5%CuAg7^V1 zgZPv9j(8p9t#T@!1#wP&#WBzmeUz8sz>5c>1Gj-*Q|sISJkL3O6Y#ejWC7x7o)NDD z*Ybm`JtAS8N1x6|N^#H|=Ho)9i8JM^+v6M{AWP#UWB3ZJtL9~HZ*eKfKpFj~jQ+_0 zS<(VBWZ#=FU6C&HdMT<BI^wi`vg9M=5`aXOlHujjL40QS_B;?T&7oDYuz+|`#TDtw zbFPLeK%40ScXlmb4TjoTXn7lR?B3s}uXb(e!}PjW^wpQy)@830)G#^je7jWRzEifA zIc)8R05~)yIJQ53xcHT{{I84M_}ZWB+|K%bmmQxg9rlq!0$5xap@)jsC{KHD1My3b zdBlI_!Gdl1`T44OTpFpf&E?6~^7=CBR^6!8)voIH@ym5rgN(_jr8L>Hk8kr^ZT{5P z4rGnp`<64DUvG}LD39^h<imXV^4sh;a2&<Tv%lj89(y-GE^GAD27Hv2?P{;TZ0VQg zda7Fg<hDL>A#iZjViRL*+;d+b9rV=H=W$D-Y2EM5IFzce&^9}BU3UdF{;dyxt@K!z zD(8L(8rxjo53<stmvw0a++}6lv1&dl-|#3)>$#vD4-|G{VQ9opGGKgSH%T08i#ai{ zmNK$$5iteM6R{0!CN~ChfeTy!rs<82b3J7W%=xD*fEfWPF@lv?UuM2uTS}k`8sp=! z5jkn@=j?kIy)3KgCKbOs-1^OXT?rFa=k-wK(?r%A8-wpx-CCDLmuGoDtmd3_x6V1& z2C@gM{`n0DkM3|>DC()tC{IiIU+n4lnePqGK`Zb+*pYq;8F7-M?64CbWt3F(uk>&E z-Kd9AMp=>U&*^>4z#HXKkm!=LVzp0dIj%)72mc-Il0ELk)qDFZ5kh&{#eNx|u68`x z1^XDvmgInC2LoL>Zv&#;$7LD99kx6_UIIu~*U!H4wVpA;KA4tHjA3C*JM8sD+<H}g zR<C9NLEDwofv8S=kxT88DZ^A*AIpIFGShl&0oRoUY|nt~MZ!S!^UZ^za=qdl5FG>a z6yW~%+{1(>2Ge2ZHRZu1nzV-$7=DNi;2@i<ld*GGfoY_r_vIsYo59`qTcrBbaehE& zU;UghZpl(V*1^>j{@|xNyKG|0jFBmWR>IJKFa_Etyzc0C^jCTV)Vo@;2J&_Bl=ujE zQ{2TV;C}96n*{JZ1!4}R_L3ZczRPJQz&k0k*T2q!^Pq3zW_=d;io^QPz<Ew{1~{uv z@&@R0oa8KUhBKT8&Zf*?Gp5Xed75yM*=4~<rt<M*G6ya!hTGU;j$8gaw*EG4rC?~c z8QbF;do-V`Jl-$txy-QMwxbBF@)oUgi5oNI!g+2|PQJi@-FSJ)ZmxocP4wHD)p)qe zdf4rR{m{E#niCjzN^ea-k=-4Ca;4(}&vr*Ee!lXA<#e@&u6E{|80`C;y7g()+F!$t zkBnhk89;G4VEIAC3@v+<Ycu>tp1|uiyPx2ixZRwHvu(Ab{f5nc_7ip-F<UiH?gK=x z9*4{Q<x_IqzTLOg?Fs7AvH$)0DQwY_FF=2pAi%G`w!t|8R65yFH=uuWgahaMQ+)lY z>kWaSgZ;QA0Q3WxD=VSeH{M~_J96%yW<7<i{<_-#Z#DFjJ%1~YcG?L$T@!wXi;tGa zci6KW*L8}-E#b~4ys+mpwWL>B<KN2TcgxVDsev^9r_bfyT$TthB7Hn176=JIqzvsj zfPE&`^q+t!n`{7c4s#HgbB-gh{-?h^chwQ#u?t)O#oqy2WB~UmGhmT&pl87O?8du5 z>ol%1&GqGCX92}+ePz8AjQO(HN>o)cJKO!g@bm{&{-YVF>~=@^(CbI{b@uM=h@*;| zC0u09tM{w);g?uz)^muM&ziG-hT1o_olDAE|2D*P+w4}+jZwYroOR;7uNm<aqg?hf z4uVnq<UCtTo03s39T^#pht}ulWk>0<Q5t18WP8AIzc>8P=zT61e<3fy@wFG$BfD9H zU}b(m?x}XJUN3S`Ki?HN8+cmTP>CmX4CP(zzm6%($NpTdTDK3h?Sq^xs=2qa-?=iB zMFwM0!194w9aFu10AjD(F4WW@vg#JsGTbkJ-q^4DLL;!fXphXtLBR5{a-1K`6bF%J ze`QzshB{?hO1X3*OD`tlyKJz-Oc(PU$eRG57kbJZ^yB)x{v+s^Yq%f8RpKe$0DW2~ zK;?J&8U<`KX91k$9CP4&%Jg)BZKl91{rdwx;VWRqOwWM}JS<)z0n{&m^C&JPpXUc* zNxhOIq(#ak6(_IyBfel8xSlulC!o(V6(@kF#qHvD;1fRP8W6WI7gvM+0q=4P#lhMU zj&RuMhclc?`#$;mNP3W$LTdE=`VpQ69!r0}CZ1+3{d57`z`fj@_CyT4$47ijkwEYe zKjI-n|HrtR>r>!7pg(2G`-c5oC5~~}`2L4Ho`RoMs`qWSNtp8`@F6GkDPY2cHQ+CN zmnVP)pRfkv9`S&ffH*9FA@2h5m^h{H27bYxxDP}mp5<4-qdYC{1NCG5TXiSs_q5Uv zfc{*4sSiW^*u`V&CE#WKsd^RkaegVk27WAlzy@#?Q`P{<Ra^_4VU{w?lfKH*>xHzv zliVf?F2Tf>%YgQRiJejkL110-9b032VSL+Ucwbly?{P)BW=ZDrRfF$d)O=R;xf!#V z)ckIq^TwAM<Z1X_GQR!h?@7yE%1+pr8-H~L)Qz&c@iOTU|5)X|U@zH;57Yc!j#IP) zlH{)F)$aE;Kyx^_K8I<yKj3XO`fj_K%5~g!-S<rL`8n8;o=}c<(Y1YTfVQZoK3)4G z^0fQ<_=55RlKR9en#=Wvm$`v`ef8g5>#+Cus0NOQj_vhL@QEDCbA$A^0i*lrCGrH2 z*N>MX!Moph4{GdG4VvKQ0u1+gUbv!i;*JR_VaGV84HO^3AIqNo)aUp0_3%$nk(OTi ztZzc=rcr;uZ9P$ibQo{Skr1P+zJu0ZbW0cuTddl>AEo2XB(gM)UHwK>O7l14e5x`| zY7%}_+<YM-V=N@!kMrNjG*XcO(NjtQv5^uFByqbqB_xQM>IKYR+x+gobp&|ozux|T z-2}{;GfV3`H{xZBw7k0bL}bKCvUW>q@f{)pA%UBL-&gpndCh)fVQ3^spWBeksIz{2 zpthfarE*>4E~Xx$J#wPm_dIO3i5T}15v1G)?cFV)_GE{i6LlU3YLNceEqioLP#a~G zU7RjPxy(fW@xb-pe#T+LJIbXdBlLZDv>xme4(3rt+1nes-IQ<~#koJ*t1{Z@-WV5M z`eDpi@2B@6#--fD<9gLVp|10t62Xql6E+Y#?AV{a3_|AftICaPn1GZ6<GHfxRmc2Q zS6&^Hy=)jSRer{1CU4SI+;Bi{GLnR~zi;lx;^20fiQNR4$2EY0xB-Y>W_Z6QZSVEz zr`ML4$W2CnN%=t8xT1LJ;AEaNxF@euu48r*@qa-st^{7nnXBUxa5%G_Mc$5K*8|G! z+j>sSI&cP+`x+a-k?FBYuLY~UwDd2H?^b_5si!KvuLkpL)yL+_7-ueC<S<84X8S{| z0Wb5J-U43NC%Fsc6$gGKz5_bczm+$Fd_^A9+aR~qbK(r}3dcAIEI7g;3J`e8m@X#b z1+D^dgg<ZuxK-TB6~Gbh;yb`ej*ACK7~{_Z6LGaZ4Pv5CaTfGxCY%G}6tEwr2@YYJ z+K@4RWen}Af~mdim&#XQ&(k_jmVok!#ja7u@b1RYF0J2X<6*7FmNTIGS_`B4!YY4K z>ARL?VF2Ondf4{m24rs@-xDWW?&A~oR~$?^aog{|bzb1<uZC;8+Vul+bG^PQ;K8cn zHp*Bhby-giZJ){$KokuGly!ZcYcKmUgRaV&qn78dnkhf*(Y|i+hi>~zcVK1U9Y^tb z&JaNNA?&LyQKPH9Mgx_zJP*l%#&>x?&^1n>8WQDQ^y@nc+RKw2^;+LP*+I{fmN<lO zkA*#MI%pa-K~MivW%n-na%H#<d-@MmJ1)Bc-0k>{FHk-5_QPEP?(O4K8vDYwxR39+ zbm<>iIe!M;iNaMkAa+jx>y`jS4!o|1oewb|n(@dcZTR2J;5NS7%JEO^k&Ousl;=-T z-24I(wB?^gP+P8j^J7LVAoE`a>E9UvKmz!l5CKto^B-Ixl9)n90Fe+y1RUW=8gaTC zm?s1m`T{d%!0TyDW6EFCn*>$L<St6Y1%>_t%dSH&zZK`>NLI$JCoSu_Nloc-4KYdI z^{%Twj8_m}=p%j30cGWSGwbL7&I^#MTJ$MvZhQ?^bdDK&COC9|PS^Vh+G0BHdI`Md ziDCD{s^@s>s_)Rbe!)unGi+FYD5w3IwB{KqZ~7f&lpfp2QAVj=16+_V%b)DPgZ6p` z&j{QcWt36&zSvirjdT9E;@baqeCf9G^0JUiE%8IO0AP3D|G4X0UPAVq1zhI-Tb>oK z`(MoKCoAeVG(aQkjoCnfyzHQN=DAPG!mU%s_SjdO&uYtWK2}#10C8EP?<yvvx&!vm z(O$ChrY+@6YYt9i%YjNAP(QE&+{yw-7tc@LpHc>b*ogv7OzmblGo#*Sz_PCYGluaD z=$<mDi+_j5#Y-Tb;TJptT*XtI0CAOA<1FwcZ*mK8lr<vY6*icX91Kl?Lr7-8cJeCj z;&!eFJ!dAa1K#2=e+MbQ6Wk=O;6`AkXDQ>;JG`7~ZU%%zDGR@10pdyV2v>r5lr8ZH zh$nefyb1dE`ltF`(9iI(z7?3IPk03-enxRP_zb_*FOUP+^_Ti9o~Aesdxs19Wr_o( z4W@jZYD@ud=o5TI0w|7wHSu#MWZ-W&#wG^=m44qoh&;+cHh`mfKNZYe3W)V~2~;e_ zvz*Vr0U;rA`WgZca3hC+HP*xg^g-^?cLC3Elx@(T>R4X@b(6YLKL_Ib;wk+hsB6?y z;tf!@>nGKFz>Cbd3B;4~QE?B5^Wv;{hlHvBd#S&iz_+dq)(-py;x)C#2IyOOQQr>y zXKWLJctN}@-Uc?fy_8_EX4t(sPJ;YzSsHi2(t%<zhT@8Oc5dBt5!L#*jGrv~e!Mh} ztAXsY#P}|AhA@@4!vxUVV?Io4Dq9i_i$m<#Yu?EK`wIu(?lY_T&gXKlb&YhG8CNON z``bgVSB7rgeq(A{)h@IRkh{}N+_JNNg2sOC3Zz_hze!_1Dpxp8>hvR9YA&tyuWwCM z58y%bdbgXtgB=(*as}2UJ2L;fjx*H&RBg5uImpN!8el7H-itiTbpbiFCH|@o<y6_3 z8lbQ1fGN_`ztkn34h7uxw-0{?co(3l@+e(W4VVERAdsw0fbZH`JJGw(+-%!nxMZj8 zdX*02!4=RhTkS?QGT6K7vFlBQcHF_YA7e{jk@Ji%o#xRxK)1?o?sA(4>(&`A{ZsYL z^4`*=e}Ycy3EQq@%Q~UX3o9$-Uv?PxF7rTLudAB)UtOCgH2`$g@LZSpZr%8-t4lf` ziIxO$9UH)Qv%K^_5m^2$u<Sahh%1`wDrqsuXWz?iatm^Ti|oHxF95|tYyeZ{BsVf9 zal1oInSpreU;5(Td>7dM=d+XBz=8==K<RIo12g_HE$@F&VsfvKud2#*N{|AVGoW>* z&uvTZcA|gAu$~bO%#3kdcaw-}9EY;kIPAI(_kEtKwZ~zI9m85b;YI?YYG$g!zkai; z@rY;zag|}?MZrq#%VnJ_E7#vUdoH;)VEk<-&y!V!-ZEkr>98`)685$k@sgwLxQuYC zQT*iU`0M}vPnSSDM&|iZ_P5AA2@P}!#*8w`D65*+F0F0EcyGvV%q*Ag&SjPMbSYYD zxX;F6_w|R|Q#)cc5VKcZOYOj8Q=&;5GmR;(jG}dnB6ZA<bpgp>DS@w!DZa3eCJ4Nw z?x3-5Tm+4Q)&D<x{~shtmF;<ApL^4ByrZ+TbF%a0<mA+=so^n94Pr5@3}X?7A%w9# zSTDj_2qDx$h-DGm+uPH_ux%`hu{^AoK?uVT){78^Aq*i5>qUsc5QbQUP#KF5gBT2} zW!TzMO-;ReIW_sR^X0^gj*bqzJnz*X?jGUp;Xkhbh{&ueKW2~>5$@NopL@>zaqjni zk1Pa~$lSh7WsK`dCc><ZZF_=wD0zK+t0}qxB~$D#$;3YSd@B{m9{rrJ5uYKu7XaK9 zLk0)X^K*x|5$K_~o-s3a_}5M7Mm5}HSvlXx@q3FOi9;*`5A&OVQEC&$Ojf!du`d}} z#U<@7$;>WOzK?#RGVY6R^hUwNS@{go7~@U)e>u@#rS}6zIms4qgf+S#KIJynfDI0b z{h+?q_vsrzU#}k5C%}7a=eeC<fqFpM`d1*HqAPv`VnrYhFitTYF#4;@^+{d>{R7?Q z1aOD`2nkAxXXQg(SYV5nyJIlAo2cg`b61>q%T3|oiZZNQ38r>y#MDkKnYTA$b|3p; z^m>_M*YWzq%O{fhTE*;2CA>=({GJYEFNSri)E4)swkb0-7{lt#xm0R<pB*!tdUw}> zYRQIcKde~JZUN)V+KZ{}y9Vv64Cdv#O}vtI0LG2X4^+W=Lr$e$MS!Sy|Cn{9UBXVX zX1?jAn?bpT88vqbw)bViic|@IS1I=87OWRd^<7tzeq&F}1M4vZr;T&Tb&R69Omta# zb0=DmiTAC>p)6C!>$KT!KCmtw@Re1AVWI|3LAlC+i8h&WMkeer2@IAcG~^~M*ou^6 z3cikBXT@fN<pJ+9VJ}I*`!Mm`A|Q~Q$ml0CdoPu14=Pdb{B|2AeoF%0vs$aj4u*** zJ0<%cNsO5|l0m6@oJd9N(5(o(Co#W=IN&|G4$g`T$cao->FaVg(k@YbnA%IUKTt8h z_HqI5dHsEKeQ(;XGO|vqa?oH5td%h$3TMJ2Rqi??sb@FR{wkxL(hf8vJ;I%+k7qc) z$Z8)o5sy#?^GrAKTss9Gnpci27)O%8XF0KcR}<sEOz7EU{LRw0n=#+X8$I&gcVNiW ztqe!-K>H$?k7zHY-%JDD2jh_*CIIXS5rH4*zz>9-@wRTnzvBJqIBwzl(PTW*CsYXh zCWxGcL>TiU;tM~cp3MLY*v4i6%+se2bm`IqwwPxgm}j02Fi)3lpsNS;fF1+w6JWUP z10-`n9o2|vBd`7J(ZK-U&K^tgt0Yl?MRrC86^SRR)ILlW_Hktnq!jlL%J6`zDm;|Z zY`g*^ziC>Ujyr_=8VNtup`ECT<$*TRpO<;Gsb0Gz?MW3Ld@{o`Ia7;&W%*&*cuzI! zw^Q1sibc;i9L?-h*0YS+Vb%ClOUT(u4QY+1m2$GdMrLrcl~(qGw2;W%m2;_oI9n!I z);Y$6Jo|QT`;Aui-kiFwT{;z?+4_C?*~T>WX78EzE&IIY4&q5eZ*!;g9!==Ysra5@ z+m&IShzH_TuAQo!l-nxxJyhy7%8<dyp4ebDd%m3lSV`LmuyVMD%P^vcfkr3CkD@>t zE3;m4VEE*7WXyiEHm0MgeX};G6=Mc<HL-CyzCKzrd$f@n4|vOojd(R`uQAAW4EPwg zZ@m1_ZtVi!9pD9<*lqw^9^eB1j5qaRV4eNk04!qhW1x#o2XKR$^@CFPvBWCS!^QzV z<x7qN1AhZdzsr02Bj9bHA)X#Li?{F@pawus`_COPL;?G`jH`iOuz@z@%U}ac;emcx zzr%6R&*%Y1f%o}De*@xu@t~LoR{2OQf;ixpuOHwj*D%`9(_4Cz;}MHg3<A~{|MLc4 z@p(i~pYa(V2bQCNlPuF?%z*zKukb41X<v^+@gny!X1-cvAr`z2ncl+<^$yO+mMvhP zIKV}b>xbOIHW7yRz=FfD{F{8iDPW$CUI%fMyLlM6jW1XL@ndnTa6sHHKM=Qrd_}y& zyC9G7DA#~~Q$8*ZfqY**DQr+b<URcwaE-W}WstYaj@Sb0!?~ZxUx7ZNH}r$RAwFjn zxPz-$1eTC&1N*sLTnY5~B-qHb17Gx+_@(eayLtl$KLxc5Sb<%+F`pO%UP3l8D*;@$ zMtY3{*OS2aF`zvCvyAi!X@|GGL@#F%XL5Hl`mAVulD(9QcxM_wKK=UevzOcdXFo6A z+sl$;V{uGE8qIU9g8J`uF_|A^%?qYI&u%6*Cri!oisrl12Fe$M9<7S@TyI`qw%tt_ zPV1Hv0$`e4*LpShhSTS1<<@ISKy96VEgz_m|K3hRy!o=ET_*3f8}C<S;qzsUb+joH zy(-X=Jq0_>^B1S0e`Y<?%Y1)XDGHYCuiT7yK^jwRxq8b=fc^2@L>l><X*;U|eW{GO zk!4tp%$aw|)b+bn$<Nc)rFF(rm9Xa`=5<rX?W}pHQ`7&wly;X!<)qJVz0Cef)@pYT za+&B&=Vfk&KR5-knCx*r8{S^V$6Z7Ji^8>KN_|zv{Y4r5vikv<8JjYhSB&E&s?>Nr zZYL||=cf0Ee&c1%XNvmacpND2AY6JmRwf8LO`l1E3$KtqA-}!SV}!-?E|n7JD^t$6 zpDNDak~iNEw4vR2y+R<mE;`^G{1)CXGKfKhl`)=1Go?iBD4AK(6LF??FA*P=#506S ztPur=71*~O_=y$t?-t_&1Kog%U@KsB@6cxmf3*C^|Mvqo!N2PM+28;3F3?5L2L_yB z01N|wyOpr#wDw3N0tw$e86S5jKj*e0HkNi!!2&TKeE*}8>u?h7d$^(Xbe7%LJ=j_V zY%cP9=RCznG#uX;*~`3fd(D-OU(K?m!u_4e11EcnIG~C5OtS|kbG%W;_GLx-;iCS+ zt{D4hrIiZO0^D0E7l-)q+|dg!Y4uPcfYWy4t+Y}_%u?gE(n>oXRP~=$nh|@?+S}O+ zY(5+H<;=Xk@~rF+tcvyAYx8NlLOo@Jc3PHczu3O5TK$<f0%EI@&$kNgB79Go;cr=~ zDAVfWWo+1n*QWsnqvaF<3he}ASXTR6IjOAujUX$Rxhc6BI4&o>9o1wiU=g>Y_;pT1 zpUHYhff!B-0A3cnU;LeXKz7LB?lRDWlkf*_JaYhenq$Gn*0_ct$T<4$UV_n1Mwqls z`XiH+r}6LnE#;5+QlA38WL+Eut^qEIl<Q91ClieBGNyMK<6@8B7j2JhrgswGtBG>s zJx3A<kj|7gwk|a)Um45;_OZ-7;IWJY@_uorya?nAVxWHl@>1~<KLPKG9h+-GJ}-YM zzXrLWKG64o_zlmn23*Mk`+_HIjqN~e@&v0O{=m(w09T2F%!9Z@-{rl!2=5_zcrmC< z*Q_6_G9U1EdG@1XTy$|;NCS`!3v69Q`ZM2-<9Zph9fcdxp3%H$NHV)XKBPfa979bR zcHNx*e7EPb(%`+O1z1;8eT(Yz6la&)q%HwM)pbVIc9t3aTa)cy<$cNm*1efoV0?aW z!T_Drmu#>;MZk5Fbyc}}yqP}jhT|V5>zF#g^`_R%_7v^4Ouy%)FtIn`2Ug8hY90_T zi@94?(2q)CR1f{24v@WUdsnrmBK}lWQQz4>c3HXI>WsUpK;L#nKk*EKp{D(6Q9oCH zoKyw<m#o$9S@DD_<G9Je1!YiPUOP9Hk<cXWCUf*)m%MNC`RVOsI<HFt*~`xFk{JXY zqn62LkhU}ZH7(+i9j}U(mt_H2%-Av~jy5^2%98d{FCME5GB3y){f%R&|AKKQ324_U zqjp(<=b}uPNk7h-7n>e{%ggW)T8m;#s9*;X7B|QlFl4BGLW+S{U`#}@Nf!rLz@ZDA z4w&4x=`jR`h=9pm1OWF77y=7~WCS5WffvgWG|5mcjqKS@%+F*^;+(4MM`w?&r*})L z&O7S1LsRQlZ^9m%-Ct@d-Z8B>&bVG@D#bVI#s})?*Q#L$PGTHXIrAN9I1k*7oz*P6 zauOMsT4|+(v;g;3N{Lt!eQ~VSLo2Pca-Pe%3>>y+yq&LF4*J&qTbZJNl}pLmw(o58 zW4a+~ouhuN3^rP$GW&xASplPREs{5$)&aO=iBtOh%<WJbw4=(@Lwp0V=m3D7^WN!< z{`uuu1?8kMvFF)sR_b>z!nAJEj!s5B#`PvwZ}tShMW${vdK3B`GiDu){U%fEliaYh zCa$xB`l{4}2Av4=b(Co=+&~Ib0^0$T`+$Ks2I4=}zv5od+uW>w1zb*tw*e>cEExfW zTfqDXVDD?@damOTu+4xza22P-LBD(k!24J{74vJK$z27%FR{uhJ`+?w(j&`}{<@q3 z_OmD?=ubJpm!P-wdwdFdgAet`k>|aRBYsT?&qpi-jOl^h>CgEjU}*QtKf+;-N7}E0 zVl&XB-*#W<ZvYh>47iU)@etsNB|O09*`V$Gjkr(wjIS91*Y!sn=8I9w!yEcNK4uJX z@9SRN-oy*+Pq70T*|1lP1JtM3VgM}Cr4Rbo`c1t7>L&Gsz8fTRQM>@y;!_@mx&3n| z<n7>n;(fStFYt|ckV}CFSl~;*3zD&J(xVUD#ntQswnvQjo47zXc>d?~xFo2l71+In zzd_({6ij{}XQuK0?~eL5HDX$~h%&CLM4D(7Fxia*^-+fQ&==BHKhf{Uo26<33X%Li z37pCYg?pLfg~}O`!|Pqc5ie_Xmj-w@oeSiZYclSo*ZSO;h1Q+Z&1z$CR`WTphDMs4 zA6Ey+HD4P!g>{8J@gB`S!K!Tsq|RgZ!g^;K4CiH^-*i9dl?1BS?H{~`4tiHPu$*VF zrht<u<7Jtw7iAfc!}6;DO{*L{x2J5cR*iDf+9#XA&@!xdx}K^snikoQ)zEky`cG#{ zeqV;kc6?~E__|JE`<ekYvs<|y;5=)cUbQ?GJHB3KhLFD+C>tL(&2W*|E@gn^W&L8Z zAC`@_pQ+zw#otZiZ&}RwlkYE$;*@q|m6q2Jn7(btpdXMWtkSMHPf{82xw7_>(24;A zda3?KEELwK{JuakE~kQe7tM20?#ryfh_FIPqyFE{=r6{^7;!=qD-t)2GNj8<d&<!r zA@N7_5dJWTe+>enj3Ipnz-I7w!H*aH&7c3R|N4(tfsZz?==vEMFVq9T<pMqj2Eh@1 z3!NI5ND#~DLGbyhQ6|#(!IeP-h$=~EHclf{$-1r#Be^u}r)G%;Y-(S{blp()z)^Y> z>%5oIL7BxV$3xC`#&mN(uu5Lvj8-}o{naU`L6T6)tLV?(#DO8%dSWYOr3JXRQf`2| zSYNAeZuQVgD^n4#?UP$+WoFVYV4If)0)VZYrR_TQtKDhe)~>SJqiEhCE4A}3h>#WD zy9v9HQ?l2pKm(I{Hpe(*rCwh&er5rk>;jK9eO~qkp2}r%kJiJ4QLe~8telP7B=fe) zEyv0&r^sH$8!zbx39JnJuoKMd<NB!BM%0+8eSCj9<9wV^B#%)ptdq~!9x^kH0PYMy zKgO>EW_HD6jG2|Z2mm<BU6y2U_ef`1Yhs+SV*2&8pB7$;FED3sjWS_HxzS}L13-9i zAi5b9WrB*@sTysh$yj|S?I2`gi*F>R)lntvSV9bLoyS@$M;m<uwt<1a(WpPt$Mq7Z z5A-4{F!vx~N@jxgQ-NJ56sQ;UCwd;#nqJZ!V1uh-?R^TDi-99}Tm<}meVR{!d2to@ z1AX@Ew}2k&oCY>I&D%g%ud@O4IL#(7@PYVj2L}>{0aKV4Y@B)tAiEkdo2P$2wo5PJ zt8qqjEBJkw2<V55=w5=UR7NZ@p0U77^|j=4^84&KfL$4l9r3H&3S(C?$3~U0*=^^6 zx$E5KR=xEAfBjvW?>057+l}Z!TIL!xrSi+lz))YRK_Eeu`VI@`kJas|Tz!%ow}X=9 zl+Tb<?!8ULG0c!rHoiSD_IFh|4j^mTv0Xur(!eg$*5y^~QI)pGWV=>7ppex6prD_! zQ|61(Ko7-sX{OKQ`wR`@39^Dd`vvO>r((HT-<!r2<b?e<a}X!X4zixz#6g8L=|tMU zj(*2>P(HI$UM2&l=6IIZPnZFV^8w_JvA)a>l4LQbmt~lD65p1+zbb#SDj+Dxl77Jx z9fNk32IEsz{f7N+Rz`uW79JLsYerC!)lXC*=n2b7gX&u){7Qn}3O;X7^ed`BuU1+= zp|?xU=e&|fG@L}d$Fv9aGBbB3>ZRAC<Dke`hv;GOdlo^5ouMb0h+~HFCN}|a?*%ik zj<B%-MMwVz7%<N~FkmrYW8Y>8kZiL8NV;Mb)D0`Wf9nI_<e&fB|MCl<&m04M!UGrR zb3s6ApeD#c)Hr?_9)RHSL_e1mch2iiqW!IH*t2HGuYCfGu#`39`EwkoUv}PZRm^;N zuF04nW4h9raU`OwJvhemqO{xy^~$do-!ZF=S2GjCUJzL$mgH0>8fo!vtxQc?<7%ax zysDpKxm80e=ZV;@3R*cwrG)^rfY@_+#@e=Q>nD4Cyf4q3u{Tb#XVu%DqWuN$t(Obx zC8uH+W*g(v@Dr0%!d^qqwJW@bDU-Sh;Knj!x>v!LiKA6&yNADzfhg$!oMfOj$xxvZ z8x)o?z&@XmJvp8g0Vawz4D5u)vzWss8LlP|0!X5O_sMpOG6;?9W2N>^Nx*!OeR%-{ z*ku@`9(EZ3-{)F3fd}-1yaf7reGT6Ln{2WHoD`cJ0yfyf1y0e$!%tQ0GdlUul40=o z2uJh@pzj0d+2oXX78o#O2=qBX2Onq*aDrnTXUxF9k0A=^2lafHqq+zB*BlmK0iV%l z6U0xrg6lynaX|bqxPAcoGM)=I+I)!qL2-y1BYN@llRT4S4~MvcI~fD0ZxJtw&lv;4 zpU{u%`|wjZyMQM=vB~&gfD>Wv4_nV;ys@|-mRV-JvACdzv6kKD7^folyZD=Dp?@4> z8yD#K`V~j`F&*GD-opZMk@%5V0pZDq#SI`H72oh2aFlEK8g`EF>{qV?59sUlSHN}p z4Sor{&TU+W&(Q7w2UuVU^s{<PUk$9$6JG;A6Ay3;FdwwwehzRM&<);iKKQ#7yx&$} zr{U*t!(wR!D2RXWMczB=$K&tS=)gccmAgH`?5-GZP`N=#PNJ_EM*K?>1%k`bbA2XD zQhPivxG(GX&~Lp&|I&%Hu{4;4BmwOm%z*JS<2lKZZfH0rIfY}^*?q8iTJv$IvHH;n zkgVx=M$-pxr@1bwQ?j)O>R;|X(!D;7xl8VXev|dEBK?SLpdQ8kl7D=%dAly}2Xz?e zRqYH5W_p;`L1$}9{aTS-I5ild^WH~g`eVKFi<tOq%4HN&hU;>Z1O8<!!zrjw)i{J* z;P2JTm5r36Dgs5b`ir`8IAsVR%svQIPcKD`{3hkeg1AY!I7)hboRa03AFMIsa94%; z%V)Ay#(tCjcB)_mwQI)F)F=~JHGfhCcADK!r|Y+<z0ET&n%&=Ye9^>b$}qyG*^>{< zPAx^7wnA8rUAo;TpBEYTQtG7=^_Rx_j>iM7QvKR^T$D!ROX5J)h^gL*%+F-XTUitH zIAZY@E5iI9mX{>r2><$f6K)WT2?+`OINxwYSkTvfz@;bl0o@=%*yjR<z&uWHy$%5G zZa})Aa{Hq30iJwdx}6aZ4)xv(-ZTqHoOKX!*1L2LoHM}Qy%yh5M%P(Wdj3@PqP@Ul zAKm5Fwo2G}{61^1+ueu=>}Ms`O^%^mjOQKAMpDoB12L^MDlNdhm2&;h$9hYz?aF|E zcG_y&VYkxC-jSBEyY088H9obLb#}=fuy5g<V^*_QnX=EOl~>h`$Gr@EFF#J3TZ>7+ zdAItNCV3sq0Api-q^hZhywu93^-J3jFT+HWnQByT2A{i$@>Sw@t8gBe-1tdjj4xv1 ziEiBG0kVpK>P1ZOUdBezNIxP!7512cU8XW5+7tGY-+pO8n5+%V<VJGZ7M?o-xCejr z02lOsCBD!P08et5K4V5Dl>p-VEZNhT2j>IK!VOm!#S#SUPh)_%sUKSzpRGuJ^6Fv5 zV9(Kw;4mQVCHkjiJIdJel6Cbau2+fYq`zO_6=FZjbbuqQVuQR@+$j%&cvu|OR|9u) zTt}GC#XIs>@-|SndB5KI6vV~c$n79p99DoYf-3`HwOAEzaRms;TO0!Z2jUP%L0ri_ z+zdR!DRBqjvBYU$5dIaH>rD{**kBXr=`KCcTfu<`#V}}7FGyWIer`0AK=}PI^4?LK zl!?p(O!U(#6?pDK>i0?im9dh?GECejGi=H9x=9}i0sHB{n~gQ`_me60Dyl~-)#eY5 zaetUT-<st-tIBh%67%C(&KJ!O0_0!i?2=6>!+D>nOp}SN-hlzth}Eiw?cXkG&1y>i zR~H~y_xaY84;Cv!z^AJDJX61^1Ej2y0j*5`RE06#DbatFIXG3{E>x^toSJiwqJF6C z{zTEb)G;onT>E7M#;sc8oD<0;*2Fm7)HSNaL859*yOeBqqvu6{vbh;9bV2(FyJ7#V z3*`3<;!;KjcZ4*&&uqOudA~G@!`V5Jg);N)GQ=18{ZQTZu}1z}=OB$L;U`tb>x<II zUvZJ~yf9vlsuuAT7bo<7QK5eF?b|#fXu0@o*1-`IyNe#M_cES49=ENDIC}V;DAZjB zjP4GX1qVzVVdDeT9bl1pI=~_e%mXW|una7*#tP73jUU0vU4K0Hw_gMf{dVy6L43ji zp9(`Wz$e~tgZNoA)1=IZHzvm~D@B7*hWg@zjLohi)j7(r9_neZN8hVcp&yiuK3`>i z-$cf(S;bLiwQuf3;;*xk^96S^YXXc`&O2!V?yZ!PxkGYU-rnlrteNPw(#qK+EwK7r zn3lG(m;9-Yv>7a>D_1qv&St4$+j-CKjzecF6MobEfLC*aY+80xok?*z{jyyEkF8^; zvgExc4D5Dk|B3@@v!0g)q@E~OWHWT60Z1k{Xsl@J*~s&ffKn^9zR3;xto9jSm*1Xw zfOx;&R$>EnF?C}otshEmOeF#Ok~C&YnF+884+^N1`i>6@<Ol3SfbI~53k+Gp1#whA zB3=RR=01K6T!No2dW#ioV8D@psok&fWn984FrY^tSYU|`AOlZdU;zuT@KYPFvBo0M z3mBd{bb{ag4YUsPqeCMuaFQ?h2<X$N4?Mz;#oZw8V@+7VZ}^&TK!3$L+rR;zxt(Fa zBz0||kt|@)B^>0+$oD_xQm$eQkiJM9U>R_=|M?T1;TYqC0TRVpr2klAl}qq9=u}`A z{>GgzE`t%fIl#8=vcdR(PLGqZqa-Wr=W@n?>|S6AcA)=N=CSZM8ZFS*@*3ZOzKkul zK;NZL>Jy+{eULujiv8RKEO812Y;cMVU=f=R=oj_-`UJ3_OU0ca?~|8E8^k?gN#6(F zb^0T<26Xg1p8+rM6%zQjQ8=KE?5ue!i>T8(hrKTs!QzxY-35zvHh_*^=SyHQ$OzEo z1byJLz#hDS!OIOcI=zuS$5U5_`bYxPgU>ny;wOOU+6%6b3E;bznX+7EGNb!8sxmp? zqJHKTj&|ul_kr=4p;GIYC2r}lXL?&8v)Wvdd!Tgl`N(YN)w7x}cc%1Sdu_g72B=+z z@p0C6A7#$1dyuoqb)CIS>lv@a0SH;!(kJKrh9azb9-&Pco3ox@1+d+uz1uT>UUVHW ztuZpXj%x~tRb;JY2?C1x38&%mOvcTo7?JbVXVv39<AdF@5j!zkzt^1?6qTz=_?<Mg z=d$gWS8f$MklB8rFEu<^by<cT2kS?DX+!-((~SQ`al4}N$>w;0eyRabs~!Nb$R<jl zRDV-%KOo9TuS(comfq8ttucrv7I}zMaXtk32L)A$b(5@U2PW-d)$9*E!*Mxze_CeC zqWP!H>4&p3f5iQ3#2hcI7;}3x9vOZwBk@fcSbPVIFM`iDun+*;mxI46Y_jD470bcr z6%fm8vIfdt+IR3c(A!%1@2&s_>;xGdeWC+v#0VcFI0)l9JXyH@lDYPg73WP}ANohq z&L=-x03y`uVhO)3lX;}<I&t1G=Fq7bg)yCPdNU>>+AA_^!bjD(o>ZlSA<m2<GffeG zHC2vzJi(fh-N;0|MCHzfb~~=q%2_Qfz`d1Hq8GVBU$@JZXgj)AS|;vR&SlxFCudt} zWg1fDM7BJ~{QX=X(e`3{H9e0g3iO=|3-u~YVY|ib*W5}ud&5c2;C+(w0Ta8G73|fn z82B@(Ur|6j4*-${jGh3@=qplz2aZ8`(dS1qvd9eGnrr}ADgAodhD8>0QgVaXHYg{p z9xCJhqLlMl8_RhcSa~UVqfG1R_ULaMIRQ|65d3|Wm-UZ<`?!;15P*%r4K|*<;JT36 zU5+-OCV|6d{_cxg!oMZ3j|DsstIXp8Cn1$FJ^76qw{mzyLq8h1-pa6t$<k!(ubQyp z^!83NxyzKh(zpOE!~P~@<USby{!g+%7xYlC=w;BSH7o<3@Y^qFPxWK<lzIo|_Q_A= zeQ@S+Y;_v+5q$z1xSCr>?F8tP`ZhiVeN^AZmB4%Y5jKEN^_JcSj%ukd2TpRDD?oq4 zDb|6L+@&{wQ*5vTY|*0!41xm*Ua+y*3xMtxV*q*xC?EUO7?>^@1KbsGZ&1&B6U^@S zO#s`y+_}Rr@qM&EjOb(H_oN@VDSlz%FK%idQ*Ki<DuY6QRBgnkk@;ykrr=JE=S-{q zP0p+Bnd`qEV5R)~$z7{=v+rSM4|VF<4B&ou*EN&Cq}kM?NblBY+^g4b-CM8KN<Y6i zgOAz$c1hc)3RF(^gPol9l&Wd}c?`m;!Gqw*%u~}C|4jRrs_j)KLrRr#tqNeeEFj-B zj$_6EpU+TTc6?VA0Mum;q?OHJXUaft8h<RS_fE|?+$7LFYu(!Hyrk?JqHMe8#WPH; zri$Mr>#HjIpF&pl<0cL)%7XV-HQV3RBUK`&ovD9%H4n6SB{NH8XS%2kpjVg!kuwgg zlpg0*$#_pu#*5Gov*L}mzBBe&CgO{B0^n|q{`wRPHda7P(Gd=?ghL0!GK(w%t1RmS zzyVfS0sTYPSOqR-A8R1q-~+nA7T?uj9Ozm=GS3j7=wKK`LcHMMCcxtpc5Vgn4OuV_ z$XvT{gZFEC|H#{g-KhM7C8aWGj53d`?&7+($#P7^$~gKmYhu%J7K8NtYp0~%oWg@y zGKjr4li{aq`)1i^$FP5_y5H<%j(<gVQmoH5uG-2uDlNdhl~SUg(?8SwRu8S51#&h4 z$yD1HpH<QxuxR^*R+^Xd0q9-E4%>dFo_^1kan+uYJ(<r(&R*upvhyuDqjr@I>bvd+ zS(QL}9DrUfb@I4gmhtnWKm-$pcZCUq+vLWI%+L=^ZWMb38>CqPiY%ag_J+F51R_Sh z5g~A>0Qe{Di~|MZe`jwvTaos*OSX455IbulLj@an3J<g!0E+)Ex3CR7!hO5}+{rDR z26}AM1y*qx0NZRc1WvL+pE1Mw7DGIs&j1B{!wI&5AudB;n{JF@eVx;s1_lgqfps=G z6)Dfg<1%~zz5?FlGrbM^DL&^U=)38PV<47!h--mM888p@17>)e4vR2iyFaGC<O5$P z`UAjblP@FfdpM|f=yiQP!~#5q2_|?o8uy|bVq0voHP$OjT*OL5?_K&MFu%lSzTb|t z)ha77_NQ%51&r=$WIyx4{LKQ6a+)DN6TSp-oL_JVc#9WV1+gHm5Dw52kLXu`U+XP? z1Z;5~zk#_s=9c86ppWWL^-I9V;#GbD40wxQf#@I^g8q@eVX5c!qkI8$*uVkq6qg4K z@;>AGs@N}lVEgM_$~d)j2ecQ|KV+;A0qo)T{y_?2-^YDDdQd=(+EfMeH^n$*auleY z?>jQ}Fh~?gANSEXuw730X#BomN;zr0x}11EiT=3S0TM>_ps*ghF$0zjKX<PjY?KlG zngHF0iO){S=S-{q$$HC*Ggj*?XumpkXf;%}%*Z%XuFaZX+sKLe8M|6PH3cR>RZ~y0 zA-zwd{mR@gQ{zSDo^4SUXg;1RRIPK>zC$&rCzJM24YX;~_5k)k3BNB#bE*7e2CAlh zsvctYBK1;Ju>U&kNrA?sVR^}QVm`C9nFUxS{mN9o7N!UL%h`<8aCv3@%`)t#n(B#@ z!~s@DzuQy>z%ui0nWLZLdsXhiev^X~%3z+97x_>I`Y0~P%<jzJt6YCvwT-=!{aW$L zQkH<q=f}BZ&eK#yKa@57HL33^G25#5%b1PH+;L%2Q?k(hR7!vCCBF9}@eLV^H^l$* zg5RT26Q3x+)k9#26iyJ&v+y%DTEGTfEWq(I4bo*E8}z-)w_dUeY@hzWtam|o{kWfA z2mtQSGYB$FdMMB#!N$|0cl9#jsKkKzu#>8vEc>XsPgF!evRiA`S?x2K?gQ?HIE`%Z ze$xXCCI@%Yu5hNLH#?)RP&E(M6-n6x0$$|<L(^hNuP0v0zE!ojQ+VfGs$JT&(#q7O z1y#0EO1}5MwvTgvtA{-&EkJs=_1^+#%S~Wg;AShWpSS(??uv7s*xB?&o>Tt2caK?^ z2kK@sj!(yO)GjfLSf%Yr&bYN@BmG1O1ouj&*3Rlbz0!&2r2)4@^m;4z_mFYD=s-aT zP|sqR4+FhUMmb($gVHobd^Gj6Njqn4NZ5(z{I7z~|6b(UG$_dbGSOZtgWE%4zM-Gj zYEEfC8gEoZZTjEC!#jX}(0zuBfM3%O+QA2+hX8byU~pG88J{ONoXqTdiw%0fX}a`D zZfY@+7hnRI>GQV>OK&9FL#66HS$=ZEyA1ohOtHHxz(^U8Mg;IJ4zk8P@Fx3N1hF7) zkw1pH>*R`h9P|M$MggCra6x=2J`yhjZ|Y~*0_n&bg#z`IUJ!u(NIBZy{P0j9ua~ch z9_;)F?w0xy@Q=l{d;<DTy-yzj^|ap7L*OWzoCcm?i&ub?Y_S2HWRp!`n;w09=B~lm z&h)^q*N9<VCG6D=K3jU6!a8i{NJ{GzCiU^WBMZ<T2gXk_wPW~u-uz~m(WcVSpFG1J zqb`6v>;8e^{nj2i!snGd8qg`(Z_R%GT<z(*xe6}BXkTZ2Io)=d?#6G^^Zu&L!d2|m zWIm!AVkWNYN6w7fFIf*$M(b(WZ4>q;r)YOo_2G$T?8+(Zhh-^$D64O8N|`4@yKlPu zpq+(d2o%i_onbG+E?J%`Y41)+hTpRNmtA`PW>#*p-d;(@=^{(D8p<RRuJbz$#Le>J zD4mk?GGz=vFXacN`xg_xFT>Ptasa@DiQ29>Qyj;A>W@!l%25S?>bm7j`d_}ir>*Nu z`v0no<5m4O+g~P`!Rz={nFBGVek2R*uuQ*FwH=arjK=-S^hZ`jKg$}wyhOWoGR85B zbmn<4!Pp+PFB!44P7pD+gC4`d)-Qp6j2<0efiCmFGCdZ7{q$J|E@H?khy(hlSOuQs zzvd@Ek1k!nqZ1Hi3>kn92{DF2M92*YFWlN0f5JGb%01kh)o;5E6ZnknsM<ki=Nv)D zcvL;CTIu~onEC0!U5@)$hWU$~8P{tXahe9#AtLnSjRy4~YsDp0>Oq<``?M<Bn`JQX znO0n-l~!s@Us^fOW$q67sCcr~Ln~937BJqlKJ&HNo~Uc(Z0#pnIs5ycvSROHdu+$8 z+1iafi|wU~$Qk&Zbq?4?mL13$)k{u6->RZD6m8^~ZlGBW%rEmc<i`R2FpzE;^{;jT zKqw7RpT%IFci_S<@Jm^+p&u<L^*KW3+J&0f*qPL;%4zq!6x}93iLx8BS>k5chsPM8 ztMHkoJ>YJ7NZ?}b<27K7RhID?!fn7|6C0Sv#ZO7RD)s>mLp=ztTMo1|0Osig2O@lZ z9c7*4_<-gi=##+LjDXGJ=PU;7-Q%s=aI?eT@H)k(zygXsJ^=p|=ui2C_dy?|r{4gE z{>B&&qQt{Q0Iott8L6}zfto1b9X8p35zM%c%VzMa2ds0PV~iN3xPq(21NcB}5BQR! zycc}-Q#UWh7~CD4zy@T@@4{Nl(}{sW_HzjrF$Q>V2OevUj-sdlEbZ5KogOZ*9khHO zg#&c3*$37S=ahU9yf1b()El6Vs*bt>*v}%Df_16o&fN;$mFgmOJ?JOA_w`S}dvIq( zy$W2;&-fvTPk4=ofa7$<3UHHtKrg}I759IyujpcZHg~yodlxoYWC_@2iACTvi!1}1 zEVBiAgDyQr8<`CJ3;<#Scf{uIZ)B>#&(!F%Z@-rZ`b!7EkNtBDM2`a4y%;C|_^%bT zh&usq^J3)=N87z##@HcaekfCb^l36oTwiTY61^`Uh~LU=qzsT^+5q}G^T6Fcux!Er zT5p{@{fI~WKwmQ}0cQ&JZZbnxRl*H#3YnnFFrB3_$~MUWIJu4}VsM^L|6t<h^;puI z1(uHGvPSwjy985ho%L~6rm3dlc#{V^(${%aG?m6&dAde@C5ZKey@&p|-oV_4oOP^e zxvJsyzd5t83fiw2&|XDPc0;3GU0`(dy_#gy^$PsiF}4_^b`u%()D;gPh{<-Z7q7Go z+Q-Cx?UEkiRUB7}{LZR*e^Gx>wjZ`=CM%U)GajFuPue+*>9U~o<UC0k-ES4>NoDBU zsx;r}1m$@(^;Y#@j~5}FkQMHuU_OvF54I-=8LWcwKmI&9L9}2cKFe4PZv1{$3;=Hj z7HeY#@j(X%SY)0K&}D%IpvN+cz>rn30(`?7Yw&}M_x;BQehM7f+V{`50grhUJ_CF| zhzkvZ2u2w1@)!{=;3j%TD-u_WGr5QMLJ%Jt+g)15hb-poFupsV0c34rJ-Zk7H_hK? z`a4;5^fA9{`kVa@-}$jGt}6OjdV9E|ezP9sTG-DHXWZWA2RmEbL@SL;3vh3xl$`lL zpZW2(2hZDKXzz=2jvHV*5Vq1vD|^46I=kjpR(n+7tP$DT{YdO7yusNtzo@G3Y@qPo z?gzX^IJ~9<xJlNt&iuXnJXe-#XUo6~${ZXqWfV+amjw?}h5E4yQ#{L*H=TTbe#+=# z;Cq}g-7aVuuL$7It+D&8)F)2*y_M*{R0j8d9+0t#gA94?k?$|#>!M88KGYZMOOEg= z=+nH;Vc;mYa|L4ncL*FFGis{>ODca*D9uh}oG)L@`zen37&`_SPufw~K9V?7dgymD z#hao}l0kh`B;|Toj)I9a&X9fpBClPeH4iu9yhQ(y+*Hm!xZ<}<$cXMT2+HyTK=+st z-3vZP+JAIKpFV@&Zy!(rKs~S_{iyz0Uklb()(^#1F#M;kaxVqvQ~M{K4?$V-J^2vO zVVw=YVqLET4(oIP$!Qh<iyl4DecfjW*m$^r3;^yjVrMEce-3rxjQ~J#CU++Ra1Zt3 z5C^tf<OANFgkKF4?K+=m<zWT`dne`FXnm8u(lPXxVUGW+lz!ea7~QIj*xp&PuCW@L zb=KL)t}?^O^7p*}G@tgmVjAlNZ)!~PveEi`Gg>7%hBFS6gLzG^yX}ejuX!ehCV}wb zbDfIsQKj9@fSJ=<jpsA1%SslYYWhc0jJ{RZi_`Q2+2Ht8WKT}*@~qVLy=|!Pv`hxF zgq^Dr?U4^?G_xOR>=)(NZ?eKQcIA1AOw0#mBmIR+%pIM=_R7{@N{vJT;8&Mqjux5i zUNaMfZQOqp0m-e@IH7G^jx}*$#Duv$E0U087S7U3Ry@wihzC|BRx$OnEWa(A0dErE zYUOA<I~!ZwdAw=7a6ZSbitHe+XJy<krs>Ja&{r8dBqu(X*PrL<+pekaqWg>HZ}vnv z#qrN*TwoHYJ~@v_kGINHJy{d|c|77aAGBcT-&TU*J+vzo5HGj^z<n4HIt&7!d!I$I z0Bp0uGO)l}K!ETXOQ5g+qkWg%1AO!s_kH~|(51^qz#xc2ISd0PcQ=S#Dnriea^r2@ zyk(jPTTScbRoqE#ia3Rme!Ux!iHZjgMl*mL8?MpWbzlL*ao)`sUuR#hI(BJ#0K$%} zf2!2Cs8&vmd!yrn>2-FCM`@+Lv;g;3O38u0_}d5mcDL0-D`%<fm0`2(d0Uya$aBJf z_x4+~e%+22)AUR0oIBp7cGbVF3bmCpZ}mFwry6Rd*)V$M0omjfo~{h-p{Yy)$>&V+ z^j5Q=^5JcnQbw_!tirY{W+0E2Sj2cP6MrW+Q1Z4*vKi0S1Vd0(>eVbg$=vso1^SdJ z_sLv+jq5LS>~`{fRc1M9dZ=zsl(J+s(eJB78gn&H`FoP>U#>g<av9vK&V0Ia4ETb# zS!Tqz&OsLG1H%9SeT+@r$7ee41Kj|U*T=&KI`jf2CLfBsO&1Rs`oL>paWV6t2aLhG z7E$21jRUv=N7HY3hm)Y+)h8GL$C;-G+`@jY0&x+?ae;x)Y_6AhLq8eOgUy229IHcE zLHU8`H-hJcI`UA=kN!Qji(!Pv%KuFUdhD~w7&yMjLM-U)2Kts0mhG3bDi&g!Pe-_t z&m%24;0_Kj+E~=5_>5!t4DB7@6Y&n00MGIi%fMw^!~%#*xQsQ>C-id+!MbSfz}zoE z9amTACqZ1q3Xj3?CHJl~Z-egZYq%feZ{%&V2lAk_^g4Jisu$G5pzq;*o&}ER5A<(9 z91yR|Ww_voxLp5ak#F~_>%7|+ea8LMU0C82w*$+Z<}@(mG@Fb7?qZFf=m>+mb_1aM z7<M1(Uybw_J!nBhi&5Zs_}PnTIm!T^J}!Ehfb@I@_B5t+l`~Hm7LH$@(OlUyRd*3Q zv<ddXbA6pM3x?lNn%sa&tBE(|m2^`;+*ts<n*`d<dVOVTm&HuZvt2o*0bQrN9xNAk za2f_mSG5nTX8SZ{kG5fnO#@%-48~WlMouo%{!21FAWxFP)o#%5bJq95HnRt9n#nAv zhj1FSN0WoVb^XyU;7u)KHFei@dF83h`j+o^q@jP8X}>J}cM3ATDZ_SL${v4(1hI<L z1#K0Bt}kcVfxbQWfU;@-t1^MP<;t5JA5|lS43?q46lDs?8XrC5{#B;FZyA4%$8+js z)Ciy7nTVU1)guI++9h*97L6}<VgF!uaBPzCyZHI}2ai;4e_qs%R?UMzUde+Brt=58 zu>T{I*dwn#S^cldc&<u~AWpVJQHCQcb6m9&_8X6ns)>1!9NiZscCaD<cc0nZ2{H#- zK_){#Ghv4XZU!8dSprm$A<|=wRlpOgtm0?-+X~`^U0|C&Jz#MJaQE;)_fgsfZbI=2 z#K<Ai?aeZrpU!su*7Si@yF|Zd?Sb`cRT=lwa}CeSt%Ma+*GRc_TDgO1O|QS}+N%lh zyUF*lCNkVuCEveZeXQbx&ZEPWmSOvw><`+N`vsM%C)FZqTB+j(t+Y}?e*01HHFvGm zLo2PEQ_|eY*;dXDY4aeonrL;{T0{N*zTQH7Z?@N7&lF=BbDy3ab})V~x$EyS4LdbS zxtsUgDv8>wFt;P}H-xO@cCE<Y_$vZzC+k_ns2+YVQ#N|z8y)$KLs|7o25yrK?UU`1 zzM-DK{e!S$Q1}VJhOi3sReUfYs~u%7V5K~xd$r!#8|iAy)2%=U0AC?}$gUou@cv9J zzxw^7optnYAK4!Kt_$iZy{;bt`G&Yvd>X4ye51$?AiY)XGs?^z)t^jllW|Joq4t6F z7GEY<)MaXF;z_2f$+Dv@D@P1fY6SjG^BaZvAr_f?P0>cRjBO-l>H7*UW*NjGE@BC^ z;^QbFTs^6tSD%BtTzn*M11+`E&jfFxfP?I36}X5Y3xLN4Lq@=D(d98#;M)t&JhyWU zSm!12EQp82mEw8e5tdm4PH>9Tz%kZY2TriAH-M9DunBt82e>m}z*qPHcNh33V3PL| zKz295=&llW<7P0ohi#MusLKd|KF#AKNv3s`(ictw>dExSe1QB!+v`cdJPA82*DvJX z<>r)gF2@|QGwn1pU!IokiVk>Xjz2=~Nqz6Nd20Fh$*-?HB|S}h9cMRQ&w6iFf1My3 z)xXow^Xh8Ko)~ZBOg+dhSQph@9~SA;YS=@H+RdSACJ$MuAF!J#Uw@TRe$tMQmaA`O zxpo77kk(GkWn@WTU)!0_F3OaZ4>&Yu^p>TF2#OiLs{yyIiuS7t-d|OqzDSg(zYO}h zuM+Ps3v9E@Q|yxcu`-M|nUqr|!=Fh#%*x9@2&W3-K2AlVjxq-WWU(I$hjK(734Q6r zdkQ<HylO!6^8S<$a4wGL<@<NN^-7WvUm4b;?l`V$X1Y;^^A$ToFQ)yVo%6o=u_7}+ zQW=>o!}VeG;DsbRBW5yVpqwD`2;-WgZ-o_UvGMO#KyYCP0C%6seLi4vUt@_SU^xJ~ zpJJJ1&>!i~SOs~}AMHDM6nOq${YQW909|^z4@mml62wu4qlk|mKTIPgP@|sg4~65D zU(ci;G`sI(%DnCs9(dWEXiV9I)csvrkGp|ISB>9<q$I<V_nEE-rXANfTMj5h*QcsR zKb|2XZ2xN$e!dqnAMSPw$wnhGt(?cw0^D0EC4cdc{^E(>-q`Bl92V6MD6O<oQL>mH zT4|+~^Kmq7X5*nq+LT^<Z=oKqPrbF4WAMIbo5%*o$EE=U)0{0gnTnGUpx5;3A_k{l z71-;OiH-Ira`jT=hmN5=WNq-Pf(^7W;M~f6@2riOq=YQjj-mZ{k(A!i-~VCazJHKt znSYc~u9vY9<xD)cI0dprIwM>eK&4j!IHZU&UWfPk4C4PN*bw>;10eA~z{UGpTKy*% zyz=|o!BTTSvsQrP`fhFqZWOOF53HhC0Q&TiK#x_ih!0F200&s)Iefsf1op9yd0@ye zNO61_7YEl5LBGT{U3`Z30kFV678o-^9pEai0tWQx13%(20CBIlmo4B~@jmYY&+`+W z2K_WAxd?EB@?Pg+@mxfIrx<X2tVR7CuksY*jlg#}5@T?`lxs)9aUTTTX9=I7-2?6u zKjmpgj8c5fFX%*mw-WZapM}7N!qm@W26tbdUMyq6RouXpk@_5CkzSx53&f2a;tG6* zEC=+u{xR<XHlMKx`Y=N_K_BG<z5#KSc!Cb-RecSwz|LFBRX4zyN6+-U0r0qfi<2Ps zi>r7TSVQRpAU_p{I0mxMyPO0qIVC;@@qO`}d>MFJysjSswI*(xd#ww<k+02JT{s#5 z+>dgKb<oH4X`Thv*<b_sCIGni=`#epAoX;A#H1fG-p3AT;0E7>4Cm4BeQkQNzHAcs z&II#&cpZuF;{f^WaZnM>Lg3|&es1FTOaQrfEwg`YVs2uZd1hdE-EITn%g#qT73W2J zg;BiveC*Yk>ODEnaY~gudp(;15uAqSxu*5?YHG%AsGh1JK=Zg>vhwq%VbAuAtuh-B zDre>`d5q;v$3MK905$XHl;ij<`<|*`-Ba~>%>%;C%PkX6vl}X>XdPr)u4iyCq0G86 zIZrI=SIYn)s{ojrYCl<%LAmU@K0AI;73f-&%Pu>vVFrAbrTSTWVw|papunl%|3yIA zYH_#8@wsZ8U1FAr!Q}ny9Abfp=p)8{l^#bs7QbA7T`&)?deE=x!7x>mp}$DqhI-Dt z!p@0Tma%6iabMNU8dZV($@g^(<F2aYygO??)G-|2#_gVeU@P%H!io@pNB|*&OfTc> zqyFnffbLI6`WI_de?Jmzj~LuTfV<D^ewqd5fhCq$1U7wuJDUNc`v&{OD$r${hk+h_ zy7)vIgCI`h6E67iA~%TlWE1DejDsEdnT@mbH!L?#9qIM62IteVf%wN>l(O}=X0+}u zvu<+>MmoiGGeeaXXU6U7RkUA4GkcI~f}y`!Tr2zi>`L{S{Hz+b)AWoZ@*L_vTA8`D z0QXkP^+T7dU+MK$53RIv)=s>OCK@eNGF$8xvfj!rEmT{XhF;IDIk1ztA=xevYuSmg z_Jkg7J-wb_8t>%^YsU6J?fybeMPGKw_NdELR>Z8OD%wvG16rBXz$Q#fmLZdzm%-4U zygmecr!mf1Id+hj8Z&DinO@Iyz>6t>J$ii>Fh0*7l<`J!*2a7}uW$oRh5*zdUI5nh zA-#P(hH#;Mp}O!H_#4ms(Wi@jIQ{d#IJSK!a2xYH4(#VZ(6$a1BcL^MbhIJPd@d)L z&@DsYMH*N3SPrm)1TJ9}34EDgd>^MzmJ`hEB)*p^^-lW9n0b4WSw3syJ}-cuWO0|H z=MjNu6UjfI67`d#`o-Vb->CeIqig~1;jqPcLpHp2Kpz($P(NUj3HmerH79{(e;nKy z?0D)r(26g_8mJfbb$DREXI(9CgPo_<-Rd*o8h(KbT*?7%ig=*quXn|z;v&EYxJ%HR zy30J!4N_05fWf^N*yos`U5yysA<pO?{_Zn)5o36d9_)y>gGvD0;|%Xa?hDIJw^J1Z zw#&pyB5B9&L_cgM!$f_j5j{v_Ks#T>s>pmfZ7Cj)<gV1yo5H-Tt}R!|<Wo0JP-kA; z<Uv$(J2#(?&z1>1y}f3&E=<m=iw~?ex89kypU4W&jXqzN>KB?}t~X&~Ra0n}vYD}} z_8WFh0JLfQTE;ah7sqRw;o98Z%CDpI4zAR-SEr(1WtHcRn2}W}drE7!EFiV2(7&oo zz#v9`ST??6H=Oe?dGI(pj-pE1RlRbO?Nk;3X&TqaispC){abd10BK@JBB;kWx+<(H zb}ekJkf1$Liz!~%g}sY1vfncEs5JdKHSaH)CsaKUW7oXjsu@2`GQ*pWt6Af;=>Z&- z(eioim3E&h^dB?(HI3I=8RKDAM#=E|%L2c;eAEwIgaj_lwD))%E$Rope(YF0a6b6# zVB-J_EYJZKBS81?ZwFXqkq-RPdw={N{Ovb@4}SYk{+qk;i7xz%f06+sqKp9KJ|;x) zMg#|LDpPS5z&NYl8D~8E+ok$ttK{6IvukmMa~Gp1EA%_le(o&mF-`l}>nNS^LG@}i zb*5++s)jvejZfwM*qYjVwsPJ`3vh3xl<4cN=Po=<3z#ZexV6$sE3Hgx;Zc2J-S*n8 z?2QFgE7M!xpDX=UbMv#h0I6pS`qgF_Zi?l(DUA!$>K~qM#F}<<y^*(3)YOJ?b-T7| zw_h6Yz^Q2`Y66g3?)lMmRT*YAJ7F)T8%lZQRRxNhysuS~!O=3@NK~WxNF#mQh2_c2 z_f2DfFT)HN0)Kt|h5%rnY23xd{WI~~|Izkye=$V=$^Yz+Us!no=H8Ld^8)DW^-s7Q z^g|q?2jUg(r4RJ5Sq$#Cfh`6A^aIXkn;sHy14j1&UA*9T57-_tG7WHnW1Qq9J^*_F z?27=K74R&t@g?Y&*q{%5tWR<p=<rJ%;7TrKH7IWgJiuG}z43eNxAg1cSB#kpKjQ<o zBA-9uQ~eENp!93J!O`IP9`F!D@iyRUAJQqs4KY@+ZTf7FGz^PkA?D-jdOsVH)>#m% ztOcJXu%=g8j9h<|FFDN^kZmJbjrjU8ws0Azf__E(l8Zsy%9AVsPX&zl2e_1rz<X`y zuzDQ0oKvj9+`K#_KLqL6S6px_44-vxII|4;7+3HpaHWu904#}1#C@Qi(L;4PsIT-_ z`fAX>WQ*&7e=64a0>sDa1Mi26;Hc9(*DZqL6sNo3a!Q{DTsAljddO+EfF3u{1ys;p zA%i;+2KOjnT}Dz-tB7BCqc%_@2z)pniT*AVOz&e~@g}Z|`nQ+xqcA1*B%_?l?aRju zXlkO|yuLpKI1Pf&Zq2!dmC<v^jQiblY&~li09K2}UlV4|Y0l%b82!8k%AQ6`7cso5 z#-7t0BYBm1xSCPDt1`P<6LzyV;$3#ddZ~tzy=Qr|UE;mv6n(B~=I!!!D1-5?9H6ia zLtfE_f0O?186Mb30+giTyLqJ<-IZZKQg8h(GoM<IDcVi=i`NkI^e}Revk9L{&gblk z{*mPe{fzOst{n~&&$kPDGE=`86!v%J4j8!^ag(f4P3!57=Htcl2($8JE^~TXJx#1^ zXfS?cF*oP6d)~Z58u;6=VB9r5z&6O755>p9^w<M>n6MM2ua6NOn6#e+J>W)v9j9+F ziesgfB0*=YqlBH`?%FV;o^TB2NiwH>s>Zuq!?;%2ay$dTxlEbIc@;9kMD1u;P;Wb@ z4$=PFHPo}r(6>z5FX;zKvgU<l+9h3&llsrow;efXFH_d>_Q?Jw55lE?FN1Q%UL+&q zm@`_3$^g)A1?Bh=ST`6EBpopiSj^J_IxMn)&*Z*@pULq`V4gMBK;63B`Fk${@1O3S z>;qk_7{Gmq#APz$URL~~e1@J$Ker6#>%qT8I3M_^@_NrIoJTZK&e<m3s3mu*+%B93 z))jTuTYG80Kg`_V>+{blzK?m1<K2|;Jl;-i@2q_**>Jq6e7()|)@l2PR%R!y(X>)d z?%^RGXw}flc`hwbxRqKH_IBiNrM3UIU)^JJt{&8zwq5O&1E2Pk{Btk)Wto~31?tKG z!sHC>rwOJtlRLeD`>{?&nlz@FvP|@zL4ZGx(X1>0-Xa~~t#a(f!kjrtVV3DZmIUND zhW(5eY}^!Wlz0(_j3P$+xc;)3!_tBJWjCtF%+qSb=<b33jeZ~CpZ@yDt0!KAe{25l z+_rWn{H6LgpZwK5u;ZzZ=mOik%n-1#vGF$=T*i#<_5>rkH1y3l6L%K#-KY9<jshR^ z1t;*CruIRErGAp3T}A96$}A6)jPF*2u{~OQnXz#xCx9R_!>>p@FC7q&ELl!G$qK$7 zGw91e{}Q;8OIQYR4F^~OHaI-`9biBQ2h=IOqJIhcG5wT&ALIw(5pgMqSHvcdgZ@xk z`dJW1#Y_AO^r!kFeKUxw#LL0~bw(d#1-OaJ83H$o>%^tNGrWWZwi)Ox{Ef(Ud<L#9 zU`U@$V4ER*pwEy2FboblxQT-eAtP4^IP(&KbRyqJKPS^xCl7dpzq+wLD2;i&$j?<K z5DviAc@X%heZ`@jZp8k~(z=^*u!rwEY}Ww=^P1_U2(F{~VP?Fc+B`!Uq|~0~{4#T+ zS;&fdo~{fs-ox6X{#3NV*{N*L^%$&+?zg9Eb>-j3rm8(QYZrE5d)Hq_ncVMW0N?AZ z(@o-5_7prm?SO4R<$arYj%T3PI(C+&|9(aPD$877<p7ZBfrC7T-Ln2XNQ{5xOv+}! ze3i4_HhKRdVhyLFT^C(%8@zuNzp_*Mi7Ngxn6L}kNN><j=-a6{-en(DFVDy>bNtsa zj6YO~-{l?TP#Jz?k5*MyZoDJQ53QO9WBLULAd3Ci&w#d_c+aGshh}lQQ8^}YqB`-` zqJE#8^}@JkEi(?seiwF1e{6D4q3@R^?3(idlX+TE<{DF?ki2<pFJt`9^CKCXhbtq$ z9VY6T*6uRm56Su@4_0Lzps*+U0hN*I(2C7#tP!wX24l7yWw`Kx?yf!!3~=cH13c#a zIEq*dt{dV5<XxbnH}QZi{^#`Yi8XqF8^n$J*bIS%AOm0+2^zDtd#S+ps`Gpmc#dLx zz(~dBcUHkVqRP?2vrkM9u+D1zRGis%?`Y1Nar?}2eOfesaSGaGuL7|>gA7+qT0z)$ z^Aqcts_XeSgJ&zHrG>e*Qce!@4)3>WXyq)CmU+09R%W^UX@Lo?On;%;)IzrPPjhKK zdv<oU8~x}kpJ-Khf4M9EVh*UN(r&6jdnuDr*!1}-gF&Zkz4GSc=>YY3px(|*U7eNU zJPtuq$PmgYvQn6*ZJZ`I%n}C>bOA6zWTytt@(XFQ0he+xpt$|w00ET%7+8htCYf@b zJ&{s9{drk>O=Gb4+ua)h-8~SOi7R*rxQAb|319#9<D38bQuymXUtGNKYWV)W3y;sg z3cWA-um9m1(2wap+aTT-53?V*OkB=&z>pqYz~$N)@Y)XEINT2E;EqxmTR}a-4Jx0J zDGo&cN`Jz8z>VS?wgH!Iwt)@$tO8$inv;wf+`;0ih#hRQ#TMg@^i}qAFrv3hI3%tO zw4;DE4(OACo;+Y(zr@3U$B9w>t|tmR_ciT>%=p>|a)+{y8(56I*L(VNPDI+}O0HpF zq?PP|@yd#9EZX=Ra5g@Zm4A4`KWNZnh!^Nlg5IJ_7sL@Bq7UMS!j(6Ic%GZ|m7w0$ z`;-KIP#@D@fwgLVHFp_U4_>f%fr8)P_LpD&)fb>&(_8uhnA@CtKt2S#%%kE1&>!h1 z)gvH09^etsC&YtugDyDoqq!Tp0PDO63^~O*Fyu6wz))|n33&8_jmkbl{0&bxX#FUI zyBGQETL-c4W#aoWQ+pg(t`eWejBN4y$zWI?mpkdRX?@KII4=$xjS<736bn^r?DBST z?lG$^l3Bb<zw&s#`|G1JOrg${nW3}o)Gsxg!Se7PStm?K4^B;=Da)vxCB2&Kh@z)f zjZYLaZq9Zc;7;`U)<l0jT|dhA7rWu-7p=40g6Es0TBiZKC_0$h)H=VP;t!JM;|OlT zUL9iwK63zW)Q;@h<;DTsgPiqEetBj<<)Q=LUd8s1nd`A;;|KNQ1y;%Dmh(feq(!Sj zAigRX=hF}J7st2K=jo<;E}B;i3=br#!g`J~>{QD*5tmNzenUe$%JPR!(9Xlc=UWB( zN^jq+cF1DBc1zlKvK*^$KAC^N8tEl2#da%m=SyD6`$u}sIN&)bZGTyrH_BO~Ln=^Q zo9H_l$4S&%4~_lH=NT>n#Ann;C-f{VLx0O6EQn@Sl(F_P%RreNuX+VzQ8EhaVwNeg zpZGmFU&>;3cN6cIj3dejGro+}&x%}cMQW}hL<|mK(ZL1=0h9YCi#!X=vl<XHtgr$s zvY&nM{agO#fBYwF@Z0D9{2!nE70@5WkL(~5q#MMMe1e4eAP%R{F`slN?9l9hN8UKP zmr;II50ce+o}5CtXPa14iiUX=*1a-!zFf_E?J3()({@@n!?>y5O`nr>(8Wm|Rm|2) za+lkqmGe$ofO{+D<Y9irqpccRX{D7ZFMQewkNL#C1(vrmivU3@dqcb$b9WgmRNFJr zyXPlfLu;=pfswuF|H>@2ZtZb$diAfjvFkLTzj6#o<9d{_lA?K8a)YAmyd(*THh<p4 zRXVv&eGHID{aDT$hs^dF3~BoQgnk}?yn_Y$0pd*ENj=(`{X=o8@~jl#CJacE^)L%a zS_Ri-m18G1puEI}Q`$Qy{0$)mVq5GJpMiW=+$uIepW;zIfQ|0IIXN7_1uxrgJI6sU z>34Vnge!bq-Ny}F3Ou53V;#6p+=K(nNBG9mnbpJkj~TV2z-1Nr8}+0401$5n+$B+F z_IT^W|5^z~^eDr7oKZc_^sW+5kR#s?nbcKG&(Uk5?I1I1n8qw0ZWzWH+I=8<_}3Zz zb?5-L&&-Y$93@a#!S^B4yKf<H@g{GBzLn4U7&y)<_rRI;Gk5RY0^dI5-RV9C-*(-r z&O8bBB^Rt(uYz@K?uT;^fWDXycpBs%%g^-&@ZOHn9&j^Pau9f*PQbw42{st#0|xea zJirqEXQ{iR3>O~$#%HKWFJcdj?113<bf)(3`(e-`$#HuOi1)>fv|IFhZ{qtnfMfi< zm)ehq8^cA6IK$w&@Bo98@adwlEenWbCH%W?j9{|gFe`P~(2Ch9kpZS?oj!{UF=b|n ziu4@<*>Jl_igzMRGwnDH)zfq~=NU4I7R|@)hT1s$Q@Q!6H^q6YnsU4<4lFB%SgDHb zmiK&Be!g1SezNX00aV)!zq`tKo|mZ))oA~sN*^dyjRNaU{K$-n+G@-fWQrd&<$vBp ze;^yRX)lv;nu&Q<nRT+4Gj5obm%ctt%LEoJ&oUf8l78T3=(AIzJd-xDBI}N3?4$UA zyQ16y2xSoO$vaS@a_!fwep&U9nd|0sovV@u__FNFt9cMmjn*ag<}FFR6qT2iQ7?I* z*D=h<=Vcs3v9sD$O!hB%^8vd=yOoKfnBMOtTGP&HS7k7MS%y7bay(Lrp2sQK4`lh5 zU2%2fCEnMbxKEYQlaSR2RwjVzw%Pr{E*STV<|!&?9;;I9WbCIZ(_f<NvZ!CFoEC}# z&5PD~DrY_AB<w{^_+LC@ik*nFj_1J1INA99!_1E1?|$sWXIyuK2+eRbUr+%Pz8erW z_&Ye8xH!NPLo8r}F55siAh;ONp$DiSBjA8x5UWuEVZzRccp@!BpKR<1TmC$u>i&Z& zSSx3b!@Ii=WjbD}66==fO4)hc?hq{%#czUk7vX`V2WrM+s>V&+QKns)QD3W}I9l;K zPu1`<MLeeOjEH!e5xZcA(5~obUW-C$W%|+r+*>In;$5EQp;iw$141jUv{Gh**GemA zvz*UUb?Y33N$-Vzsa*m#*`9GJ8=%_j<J4X`5N7WZ<L31ADjQol%LeOH6=;;lP^Sta z1t#_P3V`-m05p{W0MA-i6#@F~lnsr%jr2U`^fV?eQ#~h{iHhvOD^6uC(tzz*di63> zCC9H%V_sJ|`c5+5n*!aV8%oh~lI`Wjf#lYWb3c>!!`u(#K)wk2f6A5m6VU%xeL{Z% zfBsj0@%+Cz4s%E49byT7@J|-rcP@wT-8BEkcWwgxYyCssg)_IDx&6#jz@;1(R{=le zI=a9r2Y3z`(4!A@`J5imrOyD^!ea{<FrW|g=-}crGr6GO<8!uw=jkGW&439?;n4xE zVIND3QWxv@^pm_Z){XE)pZ$zC<a%^jkMuKEz#tyB%GLZx+={<V<^h`{V1RGuAM5w| z4KT!G2uSe;_c7i~cEo&ai+WpM!Zu?-dzZfMMxMVyhg%|_PjQTmz*;Qe0E&IV?-uBz zoMH<^#|OBJm-snX0*{Ixii03-5sUhLP;crxI11{Q`W@}U+!1jr3m{L)8{}2+2l<D` zzkMHixAdPG+y&}#^@Z+$ee8m#tS>=cFAs}H;LOjwd%Uke-XZUty9@Ncub$FZ0sDBD zw?J6x*_{s-;aX+yT)7CVth3RDCDu7j@EOF_Z0b#5n<wZ2+at#PAuj0ND8+RApo5oS zX19V3OLqhm9s|*%pIzcWb$8^0@zmAHl*-BN=3&BLlk;-7;P+6H<%IPr0;Id8Mw4n| zr%Ln>=YrS<K-b;LTq6tWy*u;Ss=&;qfbV(pp6S|2v-8KSby3qk>y)~>{5r1gy4oJK zU-`0SgL(?rm-a6Dxvb&es)2r`=s;(c=c}6QQPTtDRSvA1u9KSR|7si*ZnWRF8}paq zb&YAiZSck;0Aj(sMtg?L+F`jSz|cDVPSb$(tOL<ajhl8uc9xun+J=5;66cec$GwZn zOP10x&{Gwr{UqSG%)Bx!j$#_mD2j`e?dOa9w)o&sLXZ0K)cZ}2UC9E!GwZjN(Y(*p zF0<a(D%sA-+Kn0HWu^8_mS<P0&E#{OZ2J&0w{(@;PFGVdGeSV%Ag)V%Z(dGzJIP!> zNRH#O(0}v$hoW&-Wj-%2qlldmN1TisS{e2?j-y83AQ?vt%eOQ7xoAeiDA9v8B5tsP zOoV<-=5cU<4)Zv`DoZQ^`&niQSQ9>@`+oMZ1}k#kzCXSi*xdSO|Lr!=V}UN<bGrMP z0SAD`K>P8-Ip%{nlE)a(-ZcGGr{Q&j!)#>QQ69VDb$eDn?d<ZdS5;>9PK6e*V(TGY z$_~8}@vv$+lXpk#hU)3n%mCEn`(%AClaa|O@bQ-Dw3Qmtf(u(ICEC?*s^?ohWQyCW zpp{lyY2~aJSz-Zu_RRQN-tM!}?#@=(EB=xMi1g1<+fln@O;Mo8Ua<En;iM`I=ym;D zH3S75U<N2sDH{kT@9iW4SYC;dB*}=K)joOk2vY@HhMFIYHZoK$a6Ji3$phf0`IqU& z&@iJP%CgsCj=epfa{Ykx0}omK@3=l{VgofTm9oraR7&4?_fifRMBiVHHk8KgmA;kc zp+M{t$JqxLzJKAh)-ezd^Aw)~{|(2u5eE1C;qbRd;LK_7^_^3&`T4)O^Y=ZFU&yEA zaoBhAZ#?ybUxD|A_tTx5p+EfnV}E!7&fI(Eg!crn#QSUlw{l&;y&i4LvE`}};8$hz z3l7UfQyz!!IA%b%gTHR%8CHVn-AY)xjBu%kY%XEDMVZuP(2`R4pKa|18+IY%dU$`F z;oTd3j&JzM5hJ~fF~eJt@_gnPe<RQlPT&*w0q_EMi7SCSxd;jJMjp^lgLp*zLd?VW zUi<FD&O5O3`VVedycPa`SN)6UPA)?4so(7zoB;Kjeo)^A-@k6*qwj8jJ3MpDyAssf z`U8%@nODv{vGWU%zmY@z6!0KV>$`!kgddBU=L9zbud~V9z}Iy75;ze6+mCTtp9W5G ziVfftn|uknOP3z76)<k8;O{p9z}<=f+rx1$3Um*d)ZJi2l%wlqjA4D40Kkv^N2LPN zhYA0P0_o#E7zd^gCw$bK@Nkv+t+@<S)*EHntX0WzFWnEP!+d5cMS#b;8_vx$NttC_ zab~Q?y4!-*)Sh4&>$Q$Jwe4VcnB44wm5A5ix=>cCpKSDf>)N$l^L<R)vDm*=WA#V^ zM^!2BQZ<>}>j44mivC}<UsgGOQxr$3m#IQlwAlJ~Ugdqf8sn3!Fir>M>0<@uh4ngG zPCfdY3hixTZ=IA39<oNik!AH&>|N&Ahf{D6y{vVX?N?1_jZQ)TQuV-F5(t%T2dZSe zs+sXNWW29>P$m07m8{&(`9uhl4ET9O3Z2Y2QK|M6P8@!xD~=1IEZ{lezdEoV;gr0; z$e$GDfNW*w8K%~qbC5uPZt%YLh~c~LTt_yNdB!Q}*U9nAE@XO7C!TN$>XkL_*rVuJ z{&kK)zbJ`k08Jae(lXJcXOb9SpFBVsjXSCcuszH)X~p_?Kd!ZaAJ<xBK`a2L0-*bv z{*oo&B&)1|{z&X&A8>H_^1rtRdVAxm<6U5ZUO<>J2=<<a0aN^i0h7BL#c9kkm8pVu zwHg_Z&NbQV`}f|A>(`V%vNCb08sqvb;{vnN`|bm_Rjj|vVutq&XJlTD{mZsTYGumO z0^D0E*C)L;_r}~EtsYuAX9oP)NXzWs%Gu?Ya*x)lofx;$oH*yKJ)WC$`@O1fyJm>I zi1FsES|rr)!)XMX<V@`|42!FozDF`pY1OvJeC8;}*e|nEM(3wK%(4R$fOy)5XWqu0 zOtnKZ#xyI(Z_^pZih)%!)t=1soW+op1z@x@faq!Z%VK&@)4!EqP_h!g%LKz#GMws; zVddHb`CI*#0K{cnPY>oknEOO-z}%)hAYKILzqEhU>A@eaA3o~d55qrmAM`GPjsMMG zKJdF9{OkYY)=zt%z~A{F{;j9~`p2M;XiL2Z-@APN{qLNHzWe+8{xA>X5pf3#fWwdR zK)lA!xdrrL9_Ke8e#BK=1iZ|XJcFNdcmU!pK4%$thE3)HH`vhf0x0tlPBXv<JP(0O z@HfIj+2#ZrL>b%T9?+o^Fg^MIb(jxy?*p6{u<76foju@v{Tux<;PD$=|9bH?ekx=S zSj1;=55v>*EVCGS-V&Xld>Js(`^-~z(2|#NJqPibu57>-D|A47#1q^Ie8T4}fc=XL zJnJstZE+h<!|>4WKOKGyf3^R2&kpZ|Ki~M*FK-`#Q`f9N`me8r3l`_D77xN-yJzvM z`4iwRd!MPhVD6r|b+G|EH|;z<w+8BQ@9iBxd?Ozat01@Zidcr7=Xc)IpMXB2f6Z~= zO+Mv1&>zdY<_>n@q`YL#>B2EiGY|SC>s$hy(5Kl1*4faTz}o@iRzF~HcYOwThIpe5 z$*`Y|GPw_fzfrdJD4;#b*zQF>E20eUD(1Uh#+<-Q=}DpoF(&&IZ}d3|e4p%1Chv~| z>5Hy6oy!ahXR*5rRNo8pT`=E>EVG`eGB5Hb7*d;^CszlEHap96YS+)I)XuY7k2EpQ zmQ&Do6F`hQ_LJ<#tQpnAlv&?ts2-|j=7=T$j&<}`%+x!b_=i1l5KYzsw3lr~2O54} zc80P#p6D4e=Q~p>x5!Sa+M$zDA63%di`J8>;&_-39H&v>c$$8j$nZ9<uQK*;lk%*Z z2MLPotIqr*?Vv=RxO5sI+b%ga6~#ZC3jSKupPP(Rs?ct-?=!O#S;=n`?WW&L{Qd!D z8NvN>J}4NMi|p>>0AT;YL>#A_SQBf(dYP1}W>)bML<#2OT|7Q!dJsxwFp4{d>zJws zhRe<?vKZ2f?MxQT6XWd_=|_ajxh`+KOpd2{87Id~(&@ivWhhBz<n%^B_#kc*932@0 z+{c6t{=CEr$SG_r5S<{-wLpjcz!D4018V`$eT5a4flIlEWzes&k7b~z?_wKtpMOjb zcp}IU*~bmyN<xR3AlEP_1PJvqKc(G`aDBK}0pZS+BLPl@I7PX6l{KYy3u~cg-X^la zcurI6%4q@DRfSAA)AR$kK;LEO4ZAIA2NPS|Pb)R1t*x|DDEcaWJ9o8uXr+~z4D9E= zw9}S$M$t+ud$m8_{r+h$_mIw6*PeR=Kr_wvOB0*f1HJch>bXwIdNkSoRW>g2^eY>z zhpf2ql$0_XwP_nlrT~2}u_c+6Iy-B_(>849tQ3p|Dd|NJDA&;g1FBdLA`3X4twULQ z16Ss@TRt;;Rx0mkO6@4)(wISM#Hgh2WRhViEOX5C?{X*be_)$ufdj1h%t@@^g1%ng z!DqnTVxH@u^U`<jw1@EBL*Kc}egTF*`u2k}U%|KkzB_;B5jgSh{`n`HtKj{Ab{^d6 zz`o1=`rUu+4sbtlzdG|1`0nC&4%r=8zIy4Zg->8`#~(iV_Q&9@c<*=%pl(w?)*aAq zvWW%aMlQw!{Vea{0v6X}0V@GR(^jxiW@E=}(+L=%#(?#4a%RaGI6l^^9bB(QpPk@p z75QC`+Q$ht53R&!KNa#kc8t|+h@*cJu@9S$@KZ8dND%jNw|*A%tGvx&;7itVfnRbn z3m`rhmRJCK3^)bO&o6w?-Us4k`4c&W(+B?b)4%;W{BGai@o!h)cQ5_ng){r%J2yGo z_5v(D@cm=o{S92G>}#x>LH$%cqX#hebNQKi8+L9|OX@i2n|MKg3HrzM^b)YGw>SuN z*+&n!lqXmR`CZZBZO|X`a~=k|>}Ma~aezLceEo@iNF2~7#eN?Iq&MjR9eQ}cAm9k^ z2cDrA1}S*s4DKO>eaz_Yjry?=7@p4D9s=KG4ER3wH!lHrO5XsrM(wB)eO!E$aASR9 zIxsy1zROtoDu)#~tsgO+nPm5cZLX<l&YNW8>-Q$-)kW{=RIraG=Xqt@!7kOp)0vM} zJ9t{|;O%btY*PTN`u=I{+IlOm-R*{3#soMJpO>pf^jg&~O#my?@GB>Ce6$)}x24VV zRW1KlnSfK3(XW*Q_>==&I3>$9wU^?9K(f|>{Ve-c72Dg+$$(a+ycFPKt#Yd{_E*t+ z@qzDhagyu<9rgUkG`?UyKbc&|S1GSdJ5^!oE@D!z<M(-h*y8rBMkHd_JP>B;XQl)O z<^b)oamD=k(<I}4`T+zb%Jok*nd&3&WtAGqQx1ZNrZY#F^pi>bX3x9L?9eV@-$|m0 zq61cP)b_>wkT(L18_gp{f`MMEjNet}`gM|#KTfz20^0W{{BoQj(TZH}1Q{1sgBF>` z!NLc+`@b&+1QQE*fWtg4U^CAUzO%jd`QQB+z@Kfe-wSNhrw2Fzfr85p4loRI{iz^w z<VA=QyqxxL8VFhjczrG-H>SyK-sJVWp_k}<Dr=rLo>$K`y2kI6u5aCgx|Y#8Mb)O1 zYHqz>XEoWW5RbDe`GsFvzv1?3rInhd*~)n=;;?v;M_WC#GPMD>l~!h9ujQoEs;rgs z++WIU9JMkVX?o*Yopp9O`+0|)Y5UIhea_Z-Tv<JNGXe;esdrQTt2DeuHS~Vb4F|g- zj3R4ers#P^?LWyZo<6Q+G0i&#<>j@j1U~Yw5{Hd-DTDj+$KmmFq@lfAsX(W3c~$_F z&h8iDfc5x&;|=6wN?<i&<WFl~D`Sf+1ojSnK(_dI#k1mSV3U(P25hjzKHxJ>1shI> zSOtBZet|8Jj(kV_3choX)3q;#?>_yVMf(Ws{D<l%>NEJmZ-%Gb7vL{9{>{&ScN3iX zC*HF=*TeR~znbsA3E%$W%)2|U!@kQ`@BYD$LH<I#qi=_Pe{j|C5%}(l9nZNN2Cx0$ z)8PQle0`?xy$RwW@if<f7>I*(K;5U`*9xQ(Pm5<jJ*aNiYrws{!h660F6L6;AZuI_ zYu8RpSC?`rS2G4Ut4Pv$U;mw;4ZL8z;sfB_pxrL!at;Akvw{t{ICOyL^}G6O5RdXa zZvrcLY=M4G9O5z%mx~^szy)7e7hUi&@E8l+0^e@B-7{~3en#D(o`(MIzklP~7h&h_ zozHh{IDPdWz8X4Ut<60p9{}re>+88o;E&$_!LPr60KR*0_|%z4;KD-}zGXiL7p%>_ z%oiZm#gZ7n&g1H{ogV`aBKZvT1KQIM0jD_1dmuXElsE<AMscY=0P+R#ytoYXYjT6< zfd8D63_;w-ApmicdTQtGMYvkAGgyRG*7ar=mRaXCh->f}+)wcY?||N-OCKNLJ^%)| z_)J^L4aiZZfdI&^CK%QgQJ{P1TPnfKKFR1F?Wc#4&(S+nMjzo$lpOczuzWXjJWv6n zS^WE9LGLFgpzZkw-MrFc&AADCuRHIurc{IK^O5v+a%z+&8?=C?8LE{*W|mp5Kb#8f zxEnKnuY$g1L+x);np4w`n)Z9EG5wTd#x3I?vVr%kS`Sm^)VdOG(0j~^q0mY^zu7lb zQ(|&At)*QONM05oZW*o*%RawT@V-^XgXlWRYp9h~;$U)pu`<@9<#Gj>zMnZ`xMlQw zJCo79UWN%fL+|y+eA&o2n0P-?{eVh7uvb#Vcy1N+2dcnsEF%wdFk|G-t49;#iB;o3 zQ`Aq256-E={-|8$jC{abR)6B@$4kAhQ)50IKZsp6{urMxI7r?p*@K&8OsG09vP<}3 zUdG70w@J%Lkp)~;mB(+HJD&*kcPQ?+;@XVgZL$t($<)}kMS2EGYqYAAqvwPG_mCl7 zM&fOqfS95~2M1UQGAk~zEEa)_S!D&dNUX62T*Q9XfOY<k?gBmf+yZnM1o0)od=NKr zgZPn$Pkc~kEomFue~a6RO2=^i-Bg^R$=J@cTT({m3kwae-)04D&g<7q4pbKT*ZB(2 zR!j#?-1bkc%%JORr4_%w`E=*~o$Xc+t(+s`wFBr`BW+8SU%<A~%B&aUt+$`e{fdlO zLObrC?G{@HP-J%9?!I-|{>mv`zTEY8k8aR6#oU%15wL0j-?Q4oF1bOQO#NOQP)y%o znyimZP1T;Y(d%W@+o{p7#2L`bF=kjLEx}IN&`mE_rZNGA40ukCev<DK-C!DjKW21~ zZZs7E+&v#qtXK3y`gYj)_0D1a0$lK{^|rVfaM{8Iynr#?V;C^0`%v2_c#Y42$HX_R zf%Wj*?Q;iVVSfJ8?_3TGm&||Y+z#r0tXA}A@cZ82x#3svyNmjR!Bz0(|M#EY{8#tG z&eqN&O2Gxo)?;%Y!pgt+!Q%Hngt@Pz%k8jo&$738Ih^^?nK#e82;cqMIc(hpZqL2e zy$cqvT)6qWKZ4==?#E|_aORFPj`tq8TW7BFy1-%H=Y3$A1uh1**+Kz}tk41GgRPfk zR@eu0@xjJdvc@LxqHtIMt`4>yKHw2P19^wMRGtEHLVO{Pz}(`THTNFamtOFwbqBbQ zo%z_i3|#k&d*+w$o%stNzVLm}OWe&C^q%?Mr~R*>cm40=AKn43=T?3U-EVq#_YZ-5 zLp;nf$fM#KaXnmc@`9oDB>dq1zjpD$L9l*3cS;Vy?%2;>a3{FS-Zko4==|h6Psm?_ zI;3vbcfi~+d7roqSYwq{d`7Dwh>O|JLGV7<`BXg!T*S59j=%9Z0C6RUc@20&_w+J| zYs3K@&_CB-b2soNFR%<82<++@r}a0$I;ZjfZg3jdV3SSI8*H!zY|^8L&qzN62EhiT z7eL2lguy)uTrUQ+#~Id>pREbtc^ojG_I(s6pM?L0024v%zP{)dGL@=QbAYg(!-{i< zB!It2+;)9mYW$s5#+jn|)GXp_vVuPM>c&}?zB(n_e|qz6bH>zJ%$utMRP8D1K{nv; zs-bo$TOVf%eq5)Wtp=>5O6G>97_H0d(P`*;W!tL^AgUU$*7W^kt$xfl(6?;R4!37u zXQoWVGQ*yV7<sGoE5!`O)!xgl$Xr}pZuNdF512Zwam19Nep2tH7^U@QMt#ZxzQ`%Z zbiN=Bt-gqfKkq7Ke1BPcuxj~rStjt388Ae$y?R0Wm&{Nhtcv}$H0V#u*ts{#TvyIM zlH-?+8PP`>AbK6b7%OpyGCZ)8^h?jsf6De_(afB(#QM`NF<#~A%_`{UqH#<aduN%5 zzsBv>nuurm7TS$4yGx<~cMBWnGtWG*O;3Lbxb#^D2Ks~_#}aE|74{w2-(R~5=>GQa z{Z)rCgL@Cb0O$vC%V7|yaf67An|Tn+O4Zx2)?9nG>$O?RtoF4{3CEn8^ZumWCfmu` zWBRn1F50we`#L52y}HkLD!xxuW`EQ1T}2M~?1ji!i*IVB0cip5t(05q-!}KtxyxET zw9-l|XMyY{OtXdPnoML{EuAl(cs{hWcizmYn`LM`ciR2zuycEtfZJ*c9IW*K6xFSN z7QptRb~DkZtn_Tz2(X=$4U{TC0ISCH(ymC`fGM-FWy%Df{N1TIDi&?*<N@MM01Z|K zW7?RBJzalEy+t>`!q3qSCz-*Z#6&qhlTpZ+{onVV<p9tXOMD49ycFD{Mh6x`Kyeay z?Ej`vpnt~8`U?=3a=-W)h=;gSyad+T+%fS6eE-FT8#*qCPk4lFaPK^Gi}w(SUvnKl zgu&YIVb_D+Kl|PDzu$y!|K!X)-aBymf4k}Yn-g%szccr)_%(d*mhXIEb>VwI{_dO3 zI&|;(-4BPCfOuS7BP8ga{#qS}?{6#|p5G7ln-@HE!C~mX{`)I`e+hi&@OPxM4m%(0 zT&6yOxh46Dybg9gQ#Yy8z-hMF01k2p8{BVP<sJg>LGQDjJ3wE_K^_M29v_L1;oDo? zg)>*d1>an7r)7b-SDY4KfZKInJM$!T-|MaP?*p-q)8b{&CwNzX0CP9XN90ks;EN09 z=bizvE*=(N!w>HMYX`n}Jy=KNi}D?~@cIi6U2p>Ukn6Y_q$6Hu3B>)pDy{_{rOO(y zjKe%I2)5WyvCby2p9SWDH5OS6+O2~R-0lDy^cVn(bQu5yjOu+X9N4)`{ZawE$%Z@x z;y)9|L=U)|TlCAoewOw9z&pIdv%pDCvjH4qoej|IY_JJ@!zNomcMNdX1IEDiVPKCW z7~4aDxRtQGC{ubIz@A`w*FgzEf^<vA0rFA5NM~V7GQv+X!NYh1G;7otGscJgf>&w` z2qh0tKaDlHX@cOUfbz4*7_%F336<!-cRS8ew4N&3_-lHerV<D5%8FCMho-g4t_JXI z#;&HnuF0?0tXF3fz#h@i2C^<^DJp=bIaBhBvQ}m{*ncGFpUSXZ<dpo&q(5?I^t|Ny zVHSQVF^}t(wL=wQf^E8=tiy0_df=rYz^d`MQkOy8YRF#79DJ`<t}Gm{WQ}&L0;Dw= z&r{k>NQ3^gn0Y+Af2<;D>-jn(fK{S@FlnbwVSB_6?3?zFW#?6<nFPzOE4+#a`2s!b zuQTd<wBUIO`_xAb+c{}xPDwlQ3J!i`uU)N5>%^jdQWexg6<V}1@&i?}pK=WQ*)(8( z(Rwu>fNmZqjrPw~2~cFAcGKgL!S^DlhYs{0vidV?l&Mn2KFiVfHa0Ln`s?5T3qky9 zi)EI8Emm0uw)J8CIIzhIE1;fS-hXfvc>MIAp6mlI-y?`G>0uC6dOi5-8QQIiMQY2> z1KJ(<R(4xDHLY;30HO_n=sN7LZp`q*&RI$@H<{tLczlwKGm^E8?X5Iwj;*v(CZ6D^ z-p(bncu=eBR$6JLa{tjzlxP>U=bbpM3ihP^x0ynAN9<jGPSYELXH!4aM9Sl7tSg#H z8J*t#sv>h#(|y@200vD0MC^hMyyOO<tmt=k#s+fMhE6B39#uK8`YOzE>7aC9AF4uo zSq2+*(LiD+@^0~sa4U1eR+0@g8E*tl0@|a$k5gP*8U2U9y%Pf5pW{uQ1o<nmEv^E! zsc+B=Am0|ZiVb|`qmaoxWZL#q{<;CU*e^##7?M2DkMSbkfY=mI^8j!xxc(*%(uE7} zu<y671K#F<xDzgX#(wpJLm)hHJJ-U_f3B9)6QJ)<59vn$mlyTh;2gi;64`@q``^Cg zehuHgH++8hEVwUvpY9w2?`rR2bus+K-CJLFyD+ybt+@jLJc|PTJU`Qq0bl8NSO-25 zuZf$1Lwu;82Yr#gg+~F4OY{+tPm6EFr@$|GnA<_w>R0Lou!k2cUho-+w*))`bJxz@ zCzrr}<$|NuN1(6Km+&eqZ~e9F7cPdm-rRNa4v_cCqrw6f_5Cb?^{jPl&I0`te#xgG zR*<|0yv_+$fXDF}<lpBA1K<U2!U8RMS$_s}^$RQjZ}KJ&0bBHS9~d&^CSVZgec&^< zkJ`_Rw3`QP(G8&SUHXBghV2XJH~55Y(Ek&CT3-zOoQv`BQ;%DLoooi>ZU*IU;WM-c z-|Ma5_kK|BcJS8?p64+Jng<6bM$AoKg4x{~eINL<_JYq*UySrH0nlB=VDw|(O|o$& zH$J0G?kdH%qot{wxSJZ)yId^JiqxQPOfMbC@0CiOJ}u_=Vaa)*EPPkXSU*kABV_8o z)o2{po%jtSPN}`Tt}4qQ?ls^8O~t{=GO#r{PxYq6K(1z>S6QK-2<Nv_yA7>(RH^!e z&z+XP6f;97>XV#>>t<Jgo-hZx)p@R0d3|3Fc<j~H$7o(HQ~Ud-?ZPAfz;9iD90u>< zR4iF$^pEBM!|VgrDyQF2rI{e}4{U_j4+_`A)%@9w*iD^ruc&>LVWu(D-Y{=AWx_O_ zocE0TaaB^U`R_G|#LL2-aFgN#{6)`Cvzp}kzKrxo^;D(DFPSqhw+cDeG4fxppg&gy z?{CUpT+~l`)C0<U5k1RNHOzlv7W}oy&juO(Z{EMiupCk408vukeToi<c_W7R^j}qK zKUqXjF}XfYes4CP$YzU|mG1XSj$e5P#H7La=w)1=r59@y@5}GEOf!#}#y1o5tmN!c z5B=-HS)vZ~C_?7;;P(jNeGJjJf_RY(^x*{Bn8ydc_kk@e`uM=zeqe9CAl~USw|@r* z=;<B{K##`)CU-w$U>L8IxWV|YVuS@{)@^6wK9aL%5nwVgUpZ5Ao@_NTpQ;+CQ58oP zRWl->Qr>%->rm7AWO7{??vD&H%iNNXuwRK~dP?s<t;~ALpnX+^_c6`<XM=I>cB6Ph z$#xCjZ=s=8MJuh)0^D0EJG$Q}9-F(X)x%jYO{Z9GrIl7%sVYq}I<?Z|IML1#ix$+a z<oWgVG$hYcJDo=V=u80RtUblFJ`KOEld83;=T_BTlYW)A0akURI2y3av$ILP6a!N# z1R7&ZLU-l#<7o`*CL1bQ2ONsqTLwX9Q;wqe``Sh;x=co{Tn4;6=C>qJMopyrO=rmW z5)4Vv>*a(^`i$8MIKvBk4dM=QD^~+O{VMMOL-8aQu#aW7fvtdn`!rpE5gdA*ZMJ~{ z{eTI4I{+&CfcP$bpD|v$cp&zRE%8G@>2*91w~Avt1Pu6$P2egHa2d=!Aot04fxG1~ zIv{VBN5$u0zjMK*@<sUWJ>U7@!h>+;+MR8664Yz@r2Y};hxD!70B5$nkG)U9zUYFl zF1QZPyyktg^9k?@%lb;-YOdfAh+pxQut2}UPx%FKr+!dB4ty=H<0X*qiciI7pr6u@ z>(@YT$=Bsgz`fjv1sB|EowW7=%lsS#0&xqMf_{W+IR;#*@6?w7EBp{ZpX6eG3B0J6 z_yG7dPwU4({F+Nx1Fm3`4d8iR<0Nn~um*v4VVkX>1^jmXF;{aju+1@+fy+28mVnDy z(?10LnqEf%YhoV?!~t$&4LHbtR)H&6WeLQ(_*(o1#8HllW55x<=4#OI@(F7o9uRMF zF^FfyhkOEbIKbzC5^LgSV1-xtCD3D$4Pcr1;O`QffXkA&0g&{9jmdDs(Fff3MjMZD zfV&%EN{<5E!@u*PABjsRnAM{U@QgltseMfnmOl0qU*;!#d(0p|+3QT+Pr-FbaTE10 zi7=UrT*Jw+CdOGT@x-~XPE=Srv2m6AUQHZemWEfE0PFJB@lDQ)n%)R?YSweN2o!AN zdNu_>therU8n%O`;~6Ha96813S83l_Fpt{}wNLhQ55_-=OO5Qvyq`GOct6nu6LMMo zS7qR?!UU^o+1Dg6yJ$UDZJjC&^{0&d&{R*dpxiWok*sKEMfO#NLECC5(_0y4<~rkg z*?!PeUry!zs$73rmpMOKuGi3bZWS;kSM|U0z~wAIFndqWFhfY$ektvJs$|Yf#=A@a zh)powLw+U*+t6Q&{J=5jCz2)HP+}Y?>pym;7M0O~XuD+pog};{KVPbrDWV7{ZX4d0 z_&sDa*M{>NVMh)oNyC0e8rYj{Xis*5KCO&{9d_h-k`bU%ERP63#s}x3nP}vQ$=yGa zV+DUZ2_|=&MHT=VWFl0oun2f8vkWL!S%vRE^EX!yECYwOkNxu_p!-3*>9&C2!Np^U z4{Wy*aVB49-e{FBGy2a~nh>k>Rc#AQKQ7Z0@j@1$yde=`Kedsu{%<<&r5fJB3=cpw zvED6{sil=xX4ZMP(n=sZ@7phY?{vchN-M4Gb+OMgD5IJJ!0p`9Puq{Ra(0V6kKV@S z+ytYy{ZKi}XbPC(>_R*5uARx69=JDGpmpq_Ng$ePsCQ2G2X-c)+-jtJCqs|sj2YG5 z(=%l7O9HP=nVa&M;bnn6SLttT1G~&;o-^CvFJ?fJBfH59NZJ_y_oN=idY1t}R|dZ& zx1FtkxjqEshVACz9Y+5rgP;8NsXv9+xtq5E$qBZA1w57+GrfmU;W6{~xaR)%#DK}; z`o}r5RivEg#!|>69+v+J-yngzxQ<N_k8>~AgZ@|#c^<?!;#qzH`WyWteGr7l9k`&M zV}W(JV99#YdKtKsi@6Lg*s>1JT?VXiDNjb~*XK1BfX}&@Yk{BhIiCTWJc$S5GH#;} zyo%y35cA?^VhG&HPw{{*ecc64k90B=SAh5tm$462j}x4XwBw`tHSOzphy?l!c`RZ} z)(H6R|K|js!!{o<3_i;sK<)#?Z{$*zfNNM}33x2fql=0$wg-RpVZP#1upXFOlaGV` zMDJHW2HBI>hyi#@J3}6UxkK_6`6h@p@wIpe<iC^;iBll{rMQfnKzyR_<R-wQ%Q0Y+ zEjED-w%7nR*dG1e0=9z<$KL2YhuXtGaN$Pm#~T5_!wpDAb{749%-9|R9=w?SMS0J| z3<D&5$OodU7}HL2mF_0`-mLqwfa`9g-eu+@Cif+KC1o@|jG-{cA+Sat@P6zZnZF+= zcJM3py}X(Xj!lWxU}>@u{WSx)YHEE|m)X=Q&Cyq`-c2)?H>GE9%68=#+@%^^PZtB< z<P^Qsq&~$=$J1DcHv#ak+CRt&&s7chy-CZOGFCQ~`5-SdlWM@<ni@BX{n4sy$0m%{ zPQ`MI?YvwDfwKK$RtCMgz#uDyqc@}7N*_Rs0t#u+A7w#179G@2V_hz5Z>If&Nu1im zzKY^NRpLKs0Mqj0mdeOlS1%5fHLjZ8mmP<x);~F!fcSDidAo!i<<EbVaX%t+<3h5L z19qm&(nb2WGlA1Z`$4MGeaZH63^OVe#S2ws`?m};ndHVp^?LC8hFL$VHw?z7B=JYy zdc;Z8E9<%_F-H3Htkjkm>nR=hE)(?&o+E<zRmcD@I)oWEL!i481G;w^GVjORMt>K9 z9zB-u2_Tk%ZGD0j7<{m_`rlgthMTwlcRj!jC?bYI{A`Ga9f^;P<4kg<dqPbCisd=B z3me+^u;MscFu&EI-XG1GpXAAWPWdK1j@xL&XZPYn)3!rrmv!W1j0>TJOzwl)>uD=@ zq?-ir%S;P3A&zQMXsy&*uC~%j8H2h1%)R}MRu8S5r_urnTRE2&X04bnvYPOF@0?rW zw{kWu?92BP)3H`>7uO#0JhY!IAo5<CS53Ekb0#CXi|u5}Of@ZU$O3|w8Q=26DcB$@ zVk#@M;g|LvUcvK2V1QSUYCfx8WtpdnnbouHS?21c*#2dSa#cz>vY<V(nA+oWDw#+H zY$g1`LtT&fTjIDl4Ek6430?<IiCZ`X9OqFsfor&&efSLS9YC^y1N7;mfK^W701FIJ zz#@_@2-uRq#lZuH!o~%b*b3~x3)*Kfunm7i+{RCrtx)uVtGEao=(7}TNcjx$edZa0 zeuFPqC%SQUO~B|hW@fS?^UOZIfP3DTAzqL!)f?H1%NU^S1W;f%0FqxLZs2Cd!2fsn zEcQMs?x|vxee4@sxBeybVlmR5+jR9kk@_rP2lWdX%5C;X%DakdxHf243%HecIRbP! z#z|nEZG8gtZ&=|f*g2q{+<6kjJ|A!|PtCm|mq0(DUe`xJ-6Osh7Vs6v*auw4K^8$g zEv^^)K>kcVB7X$>3H>ow!p{F|r>BpAw)9*2F;Ewar{|vO!ms5Ub2oI+C)r>gIH^z5 z0Y2n3^T27gSOm5LfP0uSdWg$K_(1UxfFA{ls{~_vl9@dUfQL!Oc5Bqm<5bj9puCkh zkTHz-Q1YNg-q`A8a3>}=-Q0o^StjbAlnAqXf_c3O9?@bM?vYj2^cdBe0az6Q(W=Y? z>HtT|uTQEnTh4kNC2O_QZmoOdjAp~;aaEb&XKJeTDBCVp!|heoE}V)j=rvq_d&YLJ zQs(vk_ts2mV44xE?tX&G^oM%SD+_?NN&>c31;BP*`Bmdd_C#i^W~{(!=paI}UUk>! zMF*$t2Fts+Qh!(u0PJM=eN`Z^oucoi$NxGO<{7Tzv-MYxnY(NT8>eENr+8eImHJP+ zG$X1R!?bCfrmUY8#glBqcu$_5!~R53@1T|p+DBEme;fy^#*|+a-!(n(=@b%mNTYR_ zUD02X_3)@l93ze1H#yE1#UWJ+Q+iT6GG#n=3dY&AOqeQT-6k0WHoeSp();gZKkP;P zI_c*U^!vf*4}5*<cLQL%Ga^`#BcQttbVLUSSY)0Keult#5GyRP2&}TgGH`$umVg7? z%Mx%ur`ZC!4Cpfkx_bd6RR)v?Vf@JoB1nTE;xnvZCFe7arIU!GRUOA>C9^tsU3HZ= ztNq+CvvkK0VBINb|7o_@EbT%Xum7s89Et$+#r~!mvb0uOsjysVr4^I@^jdYr&V8*O zcE2H76`WJj0*+fbH~OV!1N*JCa<=r}@;vk3c0N>JoZ9bgoz?xRYD|x66j-lY=5FY5 z%t+pxCFgG_rR%9Ivs_yLVY;Cw3+y>+A0{d1i=Lac!IBRYFJ_dBGykN&ooQg%F3HT6 ztfy`8ybu(tGWwq^W<#0M4#_~LlWEuSdXB-|a`cVAQIu{!|C|%_fy-GA%38$%zKJlm z`{k<<Lp!5y;@_*t_hZPo7yDiX<qmOm02~*O;RDTmHf}cnlzRa{-Y;iA9b8~#^nLg@ zOg-!a(1#2oU}ta{1{+s005-cZkeNGrt_lFrZm^l`1shy$$TS|5?*@$M{@+3Hy*GNV zVQh0}5Nxc4jO&A-ys+Kf#Pvf|@Hu3-kN+M%H{1dZHs<tee9ST6Mz%N(T*a-i_e!Q> z4gp9G5(m_S`gMH@)MeV$U6^}a-XlK-rFI_Mc>s1^QIF|cL3~eK%|*Zl9xnh(xGdtQ zlJ@Ps6Ks??f!)pre+R(^su$bvw1S)hPVm<oG2%@E$fKZhIm$?&VvOr@;yxAgM=#-L zVan}c#LvQ1)zOVwnYeS9@F$soz`KchgwN?@jLjiyzZK~j)3*F08%Rk2wGIIMLNW%z z8;oVT%*Z(H4Xhc?k3^mMh=ok*O*A#XDSMDhWsDO|&$ncWdKAseo8A!4F0ZM~QcVH9 zr^DQ)a^{<5);rT88gWXli`A6vwkoi$Y#oz8EUSU_s%pe9^4Afnv@WUvE1lAS%JhDw zs@-PAm%PU9Uyl08S*(|>hRV+ZBs+%Xn)<h0v%KPVmYM6dy79@p^?6m_O{=eJVEnUc z%ro-Z$1yI)DrJ{WCg7?X@X#*tUS;Z8cT`Vic(9GzcVb?eYA+qba=grVk22~fO#9iY zer&?bJ&O#7S?!c{K-tTPU^#|;hF9?bjjDLCrEGkzj9z8#I3P>-OffM;c094%0XEMd z!(>wL(qQ&t8#1hi?>TQguTAd<vg4|8eOeiInspFp5}=<vz7U^BB<Dk6e9jK;jDGea zf5X^@htHZk2t3Qf#SY?YKI6NK4f3_We%YmKz{a2d-~MbHu;>OE1bu>z-iT<yk0<uS zc#;kY5&i^;4|t#Ed~H@TJV($0s^WfB@wj8v9HFxNk-eb#&J^0A>G+K)QB&T0rObL) z7WBVzO7`1C9K%hN<CUBjc`a7CmFa{RT4`k@!WCD@)tU?BR?Z*UZN~GnWuwz;O{JAq z&f0#a@%It!+-w%o6hpatp4sR0{aK!sK;@)3HSK10{on3nmMB~AtX^@@kd@5ZPs6~w zEU<^B0!?YpkK1FjspP}3-mqf*!uwsr_f#d@)5}RQT!zWh%4t6n2B**t+=Az+f_8K% zx3TJ`JSTqx%gQY;tDU>SedB{DV_3TtY3cEXTRgSpF?AcCfp|?k%=N%fzsx&;E1qQm zxSGou0^4lk0;kwwz?gx1gKdVvXBSwY7XYvQ8gJ{3fYIG!2w0-SJYXZmJa9QzaTstJ zFaTcR3BJVNcp3mlI7J^g5dgoxU<(EMFed<5;s!dw^DN*KwirhAuz=$~chr7v%yx$i z=rM-lALcDSU<{l-#Eo1W+!q4dL*{WeXz4-Ff<BNwwneLZfnFpM7x)DOJ!G5$d=ZDA zM{Hrh`sk2^zX3N4Huii5_)qwZqvQ4!10H1!#I1b8DsVmPtbn+l%UFiFQ}UI$2SG@& z#u})D>I(H9=pk?NB=8k4vJPCMzv2_%h~Cs2u=CbVM{R@t8ISN&;97pk?O;7PcfYXU z%pdJsq<;b8Ds|GkcM&dAFYnyCh`5XmHoNE(Ji-PrkKg{wZ0Rk=4DMdgzP;dJKzQ&# zr7*3>8QjOmF4BPPlML=^bP#~ZXD`FohNHesO~etB->VdVmxVwOm3f8Am_10wn=peM zIQsj+b?=rK-vQpE7<kpxd}^BGec7@4-J0>D_Y&jadsX6SA|2qcSLW$<WIW$X>#QP% z<!R2jr@^FbO?iH-Y6I}%43AarZ+d-`=l4bL-}HJUn<2FtP^_vw&N}gZvR`m!Xunl} zn8o&3?I5h(Xzx+}IjZ6Qxe3PYwDqH1GdeQXi<R5%s<a*Fdrrr&eVWclQ5VQ-SE!#f zYFpV5^J$#vx9Rb%Y`LaP^^Re=rT}`oA$tn#a`Iq+RoXwI2S6Odcu7`&WYuWTqRa}W z^JWtObX5lZs`F#pFivC|&nxT4UJgTh9cK6J_@OfHuVe*3irA@;ln4Adj1LsZ68Bk# z^E{PuAi0d5)7A;ns6DdQnP&B$B*;*sxMh-{Bg!-%&D<HrUt}cSX-DFcGV(cio^V3I zyM73VF{Aqe4i0e9h|%3=a^KG)i@*x2tN_cbvJ7<jKhXs&`fLM(0N_3d;&&=SjNuZ^ z95~&zq;;MkR8+wjU`=6Nv=^i*!?s;<eNmi|qj)T?v#u(dH_ti_GYgS5?KZ!?%w|qb zi-KrncG7~VS}7$v58C&C?~7Ist+digE3Fs?Jeru9oL^JppSMOd6FWWMWHw&ZW+bW3 zfW2EQKY1Ser(JR5Ww+X~h^bpO#t0ghx&Sh(LTc&ghKu>e)+BS3DxoijY(QV0omds@ zTjtndQ9H`S6;{b)@Z%J{MhyAFgn>&E<(G+T$r^18g@9OV#N_U${<TImvch^DM*qVz z*ZlULKSjUFV>|>JPO=HCqDE{{Q9$q*e4S)&57R!Y)V2r#<iin@`1pGj`Q96q=fxP~ z*BM{|rvoPNutYDo&Km)x89|`K>yjH)DyBa#_Wk%eHR7)KBJ~Ox<yGYSXg%B!^Sv+b z2>8yZG@n^s1_v)x?0ReT9znge&ny+TuP1I8l^4~+ja<eGa0Sa^1^6{eUmK}ssBb5z z=RMrbt)NfnFZ4Aa?v+>a3lQ^aQ)~lou@x}n`)t>n;z4l<s1Mc4{0jI7yd)k2aX&v4 zhk#31!UpF3<j-Qk-#FCkc)E|zJhmO!pU=EC2#!F+8T+ji#(5&`8f9)D_hE5hJVY7P zRjmJzqwC_WAC@y8{Ee1R%sx~`|LcE0i1n@U{)7~NG997A@;YK=^nQ7F$Py#f`I@z` z?mR@5C@*{7zHBspO?y^p)zn{80BTb)-8l93$n1L(fN9NiC20ak%bTAzT|ZUQe(b6B zU9yt>IkoE{8?r02lBcz9vKs0Ssxz?9s^5``j4Vw98S<IVI~6Uv48YcO+$+OWUM6!x z6(F*0puZ~Z6prss19lU=-Zp--YI-XRbTI{h7Wco^4)QoP`>EoCAk8qedo?qDWY@Fo z`{o0o%O038X_q_zxyeBsNgnWA70jE>GHI%U_q7czOBHC;D(UxGc3{`=%jgs8&O<^# zaaF&o%Y@%4=`W!jsp9@g4@&i$<;P`{%!@_ymMWPUGW03p_Mr0OjT7sVq5~ddruOuM zWyuUs$@dG&6#?K~ho7y89Yr%whVe^h^t&A}x!XZTN+*aP*#V)2g9r4n1ELK%iZi<K zN3ZVtSNpC2Zrj>E+64ymg3Nv2(r28B(G7?w!gykmV1P)hvz1w_aAqq>UikTp@oX|4 zp+^26_e;BA9a(J!>y(_2Dk#jvyq8d`S^Fjh>mU*8<@!WVW{)yPSVnsFQZo0Ji)S?Z z-gW#c@A~<+n`)(A*r%0N3T5t<GjIRymR1iH0tfBMrB=>;vCrFW=vntCEhBU*P1uoj z)_d%^<Oj}qV|UHA+qpEqs<I)pSG-J}MgG(zv(>aMHETn-$@*1g{3#<=34nZlYFo4C ztAbR`$>(G-lv_C)F{blkX>fn`My#rAMe&VFbB45VBPS{^X6h}hXZi+Rk^xU97~Jg< zV|)173O0x=<n@UEg?Llk3*r$h_Te+a+khQ-h71_X?GaPC6>D)PxPBZskEa}#!F3^U zd6RX08gPSh5m$&40NMwzyA0_EzYhQ__&gtQcRPV5+yH9arH6~p#54xY`}GK!xI)$% z32d;zdPGl0I2tgxhrsHEK<{BG;X#2ADD4G$_cg!HalT;;RG())+Bb?dmRV%9ai@RA zf>?;?afyz;FJY0L*z@DS{PF+&zgq!Ne2YFVut`@BL7!rst3fOaivh5Y{S3hSbZ1Gu z1mXa%vmfM9dAHnvxohMT`V&w+xuREL?*6$C=5B|b8`b6NRuE5cGgpFspCeene@Rb! zpx@;~{Vs4fH|R@%zR%dM`>eBxe_Y}fV89k3gZqFnV}E}H`1fKA?$+qwL-_9Tg9A#( zf$DAo7_UaWU~#~^i~#1-ncCAK?9qc9DrNpK%<%nW`B}j9qSeAM1MuF|EMpc7?W$y* zrV~f0R@Yh2%j+^SRhhrYsp_-Y`BcB*dFwO*3r!qcoOPV4Z#W-wW>l{_%*ah-;7Yz% zuY!NnVg9e1&!GsIry5?5r1fW#*{x&4OpRGUv?k+x`RjtZ<AdMw{eu3*DZyMH0@akU z2T%x$$*O;^gny)YN!|WL)?_U2XZT6g_{X4Ne6}n05aGAw^=-ah&+lJU#`-kBoF2so z0~OU6uJZu0b%-d^0N+)|K}FSrk=gS-Sz$hzw5mR486?VP7_dr=H?o2GanV6K(|A|W zn#(rOZ<UM-MeW-wh)Yc#EKtVvr~-Tsf$OI2GnlBAN{OcB`(Ivrn`YMOW!!IW?<)4* z$}kQ%_6y6<{wCwJK{@)B$as|;rzZU=>!5(je9t6sJ?%Z@MCOLr0TsO&{Mz+P(3>Gc zdz`s_;%`u{uto$Oe%!GWFuD(!XC81_U>+C*jP5SWVhI@PPg#YXH-4~oa1HqIFW&nX z4+1V{f{cuP2EdRGF6cfA7q~O<JTF4bQ8XtmJJVECjy;@P63!@u(KwO#U58`;%+?_V zeOdHiNYi_fdtn`3bv{{k-aoy#gH<rznZ-rM-z%eWzx?}8?#Hz_rdFmTEx^5%QnK^t z1;6~>m#rQemzMFgl~!7r<^rajNKSiM)k@y@rrMS`2l|V1y0yevwj$E1W-9Sn>o<>S zY&ZM!Y3avgBdFTjs)|4_tCGG=`va>YN8}{qj#<m*Z3GsjgihNa3iX=CAd&|>R|Q7_ zvSAnH83JX_{Z$!IO_}Yj%=Sy)*mM%iN!Cce;Rcu;Ft^JDusvizlE}m8SG?=C4*x0K z%sh8729Sr0+0j(JahvrfnBAkldkG+M6dtTV2fvGlBK8qsRuACIh|dX`$7R4=u3}8y z<9k#p!_pYgEMxUki55^XoyYH2DbG`h_lo|F*JFHt^gcNP$|rT_CF;qDNnR2KaL4cM z1{-u;dJF-@(ulb|T95G)ycm=I5I3--;pjP$_ZRPocg2e^cdvX=UIskPMfyDuH?YNP zLHl$AOB@6i*bn~t2NkT~poIUu7cjQl0b>>u_BP(2_20uD)m{No*s*qU5{&PocGPNA zPV{#x(ca<v+Cl#m1;$5xPbPrwZo(gvGGq*3myvp8^=0k|nD3?bCuV*A_&wV=*>q+- zPNE;*t$AQJ@K_nYOOrbC457Hr3|BxhQm>|f>~=%-uF7OAOVm@9xJT6lgqqgNs_@)t zt}pBcN~x4tOvuzSnq~^Fs%NL>^HmBUs)~J>XkXSSA*{DkP*>A~v!?6IGyrcC_N7wR zGpZrq4cj%zfU7F`r<Gd|C-VSwIs4A4M-el=SFv4+fRR?se#L6IziNu1JWKyh0>ElI z4wV6b%Yt@Pv3YzEfI3@GCh>NeQO|K5>K!Pu6LA6CpndZ6?3DC>FNMk3EKZaE_BQo0 zkYq8WtCIPU#^XWy_@xYdD~-sYY`+`&W!VfKUW%Uc>?F%BlV0l-j0bjsp6rx*$`ZC$ zcimMsE|{0uNEY;4Y2%FP{K(FU1E$Xxvn@@=`aQGpvFKocowB}4W5f>`?d?(g%8Ehg z?L-F3L}mbCMF={=43^Q%lpYEj7zFVohap3t%OLpN*BihReX)v91R;YsSr6!<>EdS; z>;rw|h*-mCboYYzsTU(&AR`{s%52w9yCq)f^~Kq>1DcnKLheF)?=}4?!*xp2&q=Q5 z&KG}cWlu>9aBroQ2)^C=tB+beG%jwdf;}<8Yo(f$WoBuml~&Fl8BT2hcYgKnyPYB9 zT<^b!Q?#!s=uHeq<L~YS2~<V>?k3~DoXHAUHlnYh_BUtbl1BY-Ri-XwSbmyVL^oEg z7$dT&4M&-kN-(9wHZn}!KbhioU@-s9W1MqK_V1oyDr`IR`I8K2S#6TkuPj)nCK<WX z%9kU?BP+Iv??Z}x{e%E_e-qh4UJu*)wB7*yrFOXk_>$+?0{t$Z-~cajBQCJTHZE|A zO?r$Ok2Z9d0saQj09X<~#{-58@qixP04(osIED9l0fYN7eT?IP%P|I^du-7KdclU% zmwdxEa5~r`{F*I1;4S?H>mVND0haL@t_Pq$V~zb0y&UIDK8)z+D?ZnUBfo#e5w;mK zfM3il;>JLG3b;yK%k}t-@;+01pN+`pF(BH9PVQrwrAYakiPXy-u@q%=XTSahi!nRw zvY$90!--tKJ=(bQA<WltF>8R!Wh?_1V~GV22U*frg8ocz0I(+3kYHUrw<+%iF2>;i zobkT>$(dh)x>DVyKLhopI;!`<&a*qt&SB6G=-c&v5I2d>#jBvc)|ac_fDqymJ_I({ zCw>fE%BA8ou*4FZAQo8Eo1oWOVheCtW()8F26u}ggWx?v26sO-bPQNO+CKDu8z1!X zG63x^ab|ZVE{$zKh5)l9qkH(fN-&s>%k?t)EtLy?SPDK3QhYj%>0KJetxUEzRE2fI zELnEXhWWK)s5A3=G&?`DE6yKh1t{(q+UPXqt@W7G(@Wbc>$FMWO|#6$ru|J30JN!t z0NM5}Yx|9?sDIUnogHlC;6YOi>*f2AdeVW|!OU6uO;x7#s_i6c?!Z9xek^Oum!%lp z?J3w}T6=gYfJ<4Uz3iII(OIL6U9ugs>_%0XhtvTC=h;aeyK^$uxpn=^&hX=^^Om{{ z>{<R(ozdMYc>ny7&oqwFDKVZ)BfF`VX~wQeBoaN~Uu8a+2Vl;xM}8bKkAOqg^dnPy z%4c#njsJz^Sfw&>dBN|Ul76lXGh3uFlIQ(y8(KxteV$>)f-;0B67zWZm?58neqfTI zL>kOr?Hpo{BvX6Jdx!+kKA;!yf$C`lB2mWwkXR%9UBW0fHqN9N2fRB$T+^W=oFKmG z0G)uz-DZ&mz-5(d0gHXCf^+Zc6MynG@b;;HxY5T4#1Df0a~Q<;ydV-20^OtWB`fl` zXe=vpsCpRDwO1idbFRj3&S!}p{74?sD>u{6U&mIdSMh<L`s@B`>vL-~uQPeS`I)t& zSvxry@iWUH-qOT8vz1nAh80?AWjqml|HAd}ueN$<rIl6;0s*bGBY!K?Uy!s?wcnCw zS$${Q-cIXX=ae1TGxjTWmb9o-vaYJ}4d_bs*YC~9PSZ9ls=R+PP-znAGTFec!jzxI zpk>1F<>c6dNlO%^z&5oXyCU<J8Zi=;^A}aHA(eGq$Y?YM<jNS+(L7E7Z1+?8h5&aP z3wap*_TZ;~dGnvbY2FAx#2fU1P6FU7Qy9`!?5~{I42#|u*ozJ~ZNlxNaHD8Ypzj{t z0EoWL)>P&x<_C$JT+?N3FUZ*O5MnUwD06#w-K`vA1;oX4SOpX(MlBTrx1$W{VVS{a z-Pav`4QN*{=rtyp`(NZ{B#0NeTigXatfgK6Zs2uRfiKwBp97op*ap2tkJG>gJvM{y zyTCU6;DE#+I56M_U~Vrs2;s%p>Bm5HZ&YU=5FZDGdx?$5@kXH+V}zFp0Q_(wfxF7I zV~B4+Mq9{BX~*dAS-|yV`B}Zo!1%suw(C_Kk#}oDwYVS8*G!dldJ{8&vH+LPlzODP z<D==kw>w4c)@hIO0L|UaWaJdIUvHPzKPm&@IlJ|=G}Kqq`Z0SutKr^J)#Pr@T4(f2 z%=7E4kCS%MH7vD0fIrC~Ivu|l`@?i1U|9_EPVI7Kp&gsNPZ{DPlX};QcT{0=F5BbS z4YhI>18$ywnlP4UU1yiJb2*WvE3dx2%<^O@rvJJ?;jCGpJ)vK#q@Sm^hE=nlECO7Y z?T517yGy-HAC5u%$P5^t-@g|F<Sj$J=G(PZGG69Q=%ZY`$TOU`^eV>DOb))5J9tp; zfM;0CZpnU26&x6nP<Rk8jDMK``m@FtC&QkVAt2rq*lv%WZ`NDL0zXU6PqQ<iSgG>| zRbX#+iv33J*BgoNH-qmtC)!7*0_N3-@jd?haa=R@S%d)h4n2Je=+nUl`V8s#f5l=D zpXmqp^#G;U>4Wa`pV0>%4H(_~Nc#8$8v~#}n$f5c0YeyHQbAlsrL5DF<4zdAO8%Yg zs_5Jo!+D|z{o<E1s+Zl+`mJeOP)rB2qC~jP`hQNW!*;`_(+&t!UAHtLox*XcxIR`x zdTFJVlG4K5S}7%SFP(YqcRy_P&`K+<oCD&u@ZeT<LF`rqxeL7WSL8X{uCo;9EYqWR z4%>Yd2D)N<l8xD=oQXZ=>qj+^%CE|MSyKe+N0}g;iv5F{sBd}3viP`bwmoRhtYmJF zCJabrf%3@>pQ;BhoRs;nEal(%z=H9$GO=-FkC?Y?pc4VMTjAg95#Q%94*>rTtNa2O zatU97ILLLZ01vQ42R|U|0^2ME8%KTsdr2(P0h|D$?r>kM9)0Gq@lyvY5X&s%04_r$ za35<d0eyc%NvyG-C45GBpF!T`1h5Z}1Hf{y0kw?H0CYD<Q5*o3#hUmbH!%h(KgrK| zDWabqn`|=PDBael*&bi7->0LW1BO1}T0Fs~cmkitX$U+l9^fg)4DN4?7^VCztFQP_ zzcFqWeS-b`aMVKZi2g#qAE{55=XfDvVIAxdlv@FIkV`_202G%7zUub?Cj&<PKF8>S z{+J_dfOc8O262#8Y+%j*tB&$DCqeA@A=7h%xi969!E<-I>QN9K(G&A9chlVZ+|OX= zP4!E)59o4_J_-6geV_gs^nQM*F9Lm!{zQKSe8LmF3=G&{3m9^mO<=$lo4_z&<{yjz z?tO+pKLFm#;K;)WSg*Ypz&+fsc1N)BI8Z+Xm|G)e_s}oWncjz^>*K!VO>9i2Gq_Iz z++}K?U?uJwW{gK!qm-M`hg+qOX2k2&1VjAUIbSyGeW$@ZoyD}5r|IDg>Q!gnH^>}6 z>&+zdHXNIH??L9gP1R`4>CJ-&h4U1vX8YHxXEKA7Jtcq1Tjxck-}w4f)dB=g_Aj!Q zUaET6uwuNd%KSBHzgYlQWvIux_E{y>dsV;4%Bbc{!R}>^cAa=%VRrDzG4B8J%PU)N zRnkv}1%9V$9;_Nh)?ZDIzykxIbGg#3MEO<6y>uY>ASW(UcHUE^T+d*}npdtJ$=uY$ zcpZ+%cI|#kX3qP~{KU$gM-<gB>uJM?-s%9xLObe=^lz2&`(!;-#d%}$KuFn)3Ejl~ zb|tTmjvH~kWa%yIeTN19U1aBj%znAtK@hv*LE51KKXIAN6^`M3YQnCv=3hnjC=2x* z9iPe)bJzwMgk(gIR;C@vSbIAYaoYIjK|(KHVt!|*@Jq{-@iEj(vfm9E;D?c?N6Yns zcw4~euKT0-uY(1m6T~}R=5YXzdHp;fgUpH+o2&p1r&)!4umACX^w-yb?)HE2SN8xt zZ2G`}VeoelJTJ&FsJ$R|@+UDug)nkt%_weSwb0a7YDk#_v9pLXbsBs|^1zQ(V*JVa zzGLWbUeGh{RfhByAJa-B!%r)%l#rcwFZj*(T1cq5oUZ`dc7ST7l~!7rjhyGeaACIx zRn9ScZoWOIX(84w`u*P5PW>m?Q`4KASv$#s_mjKe7ugJF%`m4X^=(zOk4fftGk}RQ z+|Y|MXXM+V%&ec;Mq2&`PFejrqYagMerII>UyIs3$u#LC?iuSfzJWE?qi+$Npk=J! zuM=EhVIvR2-#@ec+uonTiddlocs#>W<T>7mF<ix%+C9e1+EJ!<8DR{Mejl}!s7)j{ z>EsBAJpQX<{%IB1b5`ngv;N(S)I%ly))^;cM$M8y?d<Z?f!*Q1-{VWxfqfj&o4}1M zaVT=ViU7YA=<xIB{%0`|8{#ksS8RxR(5_a>3pBDH)FJ&gSAlp{>=O>~2R3;Z_=@-W z5?E%18^-0c8t8HmSf)3!(+(EUX8{*jjHG~$GPp~zmZ-P?rej9;@p}=oS1)E~$@X+J z+G7l)kC*3W0LfKGdrIO!{7ie$afW;o`$@Aox5E9VbBZ!|xXecC&R6QL=bD-)*oJK| z%Xxg+`FCtSAa-}1=;#E1M_7%t_q5kvR>^js);d8I_`6dR;G9(-ui{afrVe_jhTh9= zu>X)#@YnMFg{sKZE^FLf{{2n-sTu!}x${4#=JS*xgMC>bh*ui0yP9jy(b<r!@V;pP zb5+y+lT5IxVf#uR$W{&6kE~(0WizliHNDRCV7gb+-<+ELN7nmWjb&hwx&6K>@z&|} zG|L^6mWjfY0l$d&p{SfH2dwPM{ZZWB?TX`55^!c4Mk-at{ZYTFGf%e+$AcofathkT zlu^8_pG4cGPR2;v(EpSn^L^Rz&#o9ZbW#px<T1?KB@ghag3J&mdXzc#WM_<X$@|lY zI`Zr$?R{mWJ(B%_6L05W^@a}WC9FULA#p~M*?r99?&ow^#KHj<1451t3phdi$<Jiz zXSVeG5ohPFA9#QFL*U_m-Tkxuz<{0)aM%5S5ab^*1U!a8=0P>eJQych@Z)RYL4eOH z&qb%p@ZL&8afgu|H?vdOiFj(6^+8#wil4JH>zzMNmZ{fn9^I&`=Ohq5I{wt5PH<|r zb7-Glg9HSvoVU^f+*>In;=yl!-o2sKL*)UWl~!75rTm1}I#1s7{OUKI*0dXuU!H|^ z-c39A&ROoue6i2*d0Jhjuf5bR(|nI<1FzJS-@hmYZCyP&HT7lAvsN9r69)`fmHowx z$x0ceX0%Ic$~55Y7}~pM2pzHw^-|S-vw#v~2KSIpTnY;x$nG<!`+w(gg3U-9`+E4_ zaU-t)SLx3=23Wkv7U&N+%slWc*9Xk)+ql4Hz>PWxxSY0imp(oN`w&<WKMxqPeTeT- zj&MBqJOsL|a6M?3As&c(f|7>8{e6ZEfno6X2*>mmu*H(N9r%XR41xFgoZ}$wXMyVh z*Wd70Z|gUBdF(6Vi1?6R#2+r<GOmg0PTV0D@BzsR#Puk>jnB}ofE#%QpTXU~-=)WP z@ID^njq(uS+hH*VLK?Ss$Y>w8vHdKt82S7SCpg6zfW3kWe)q4~3YgFBfa(1@mRSY1 zxQs<$6;CV!t4MtX=npx?DPW&I#Sp}m{Fuvt0~`<sVCTJ^Th)u8rT#)+3(RwpZ-Ap5 zV+-W7@}T$<xKka_3iJVet$qW<f5nU9HsDV7@oQk64VFQlMzRg8W3ddZBiRBrvDpT; zu>uBnE7&L`0J!^`gCV18m;yS=j}-;BdkKJf^Z-V*uk;ek?co88;mA+a1Q0$dNkDuO z`0b_i$k784nZR#hn_U;Nm%M`(p$tvO2d!$4t>>!5m_cg-x9hG$s~*sr);uwL6rN4$ z?ac8|I1}~R3-j})7|ok%{~|!QJtKXXidEBpn_i!kNwHqUDBDE4XCLfrKCYQ(FVkH2 zC7GIMVXsB=bbHEvm^F@U7ubbr2)Lpulq(JD?=>7pu^K)|;pH%=%bM++?l)!QE2ix! zjSu##67Od<Y<DUV7ilhopft+tR&^fMsqmh8?{61aSr))Pul?(ee`)b5uVm&LJCm8+ zl!-n+Q(=++lsN!Z22hw4H}WcEh$_>*Dx)5%L_d|40Z^5=KRjSzdeAUSpH{&^gCgL# z6U(EPJ^xV!_vhJn`azU(nF4IX@zXOnK$CvZCVL*3b&$p^?mB*+O3|atn8#$rf31o6 z+}OV(KzzL(d|vl2)9b-|jQf>IhIczsU(2WT5FHeb9~Wa0pP79zh+i%PUHW1L=<7af zKu-(0z$PE-E<VtG32=irWthoP`9OEw3o;O{#q}@3x_&x}BgxTwMz0*y97BqT2(p0k zdueY@*7!BF;`y4<E7dUZ(5yt2nCF#=PdO!QQs(MQ8rg7Fd+FrVtIphSKG4{(A>XlP zY(;9+-^dm(*-F#W0^D0ECHj&JZ(e+))k7<1eb0C9Zj-hXg)$SYb_{H#l~%$9bF<@u zngXL-D`(GmmvxZ9KF8j3((ZSMfz;XK`cMrsQdF_WDt2X>dc11tWjiG`aTWWr4f|U) zu^y-fXz&VBw42&__WP96W0eihI`(O$)Gm)1%1SUA*;qV`4{-OHjhqp{-Dfhgun(gz z`2E4Zyy;Kj1nXQ0IBe)GU=1a%WRiJ3e5Oh;V&}nSqd?_wlg!JwJ^&Ky05~iji9A1i z*05Gj7T?BI3C4Jp!jzq4XiC~e2*GZuFOM?hXWgeFsht&w+qjbbAl9&113u@AiS~-V zO_Uj3f$nQZUkkdY7xiMWj`#4H)g{O`<N^5rSPxm(>U+R_X~)_*2wcwB41h;?hfSbM zk1b%EE}Qrpgj>LXF55t#J_De~kOANY2L*-!_qxgeva85vA}!@b;trAb8R<0%g!gp( zvz5XOKen+rusoePJr1CEbK)V<`^TxtJ>$N#nw4d3Ds^-3nH3}ZZcE|#ueXhRo3twi z4b`uS)l=RZl&xp-z?U=S`kB_VD!^#^^Kscoc}@*mFadB4D%P*+{A}9mRJ*2~l+jNv z5O+!$4hALL*)Cz%Ro9m$K<B#84c}`}(!;EV?NnB@KPYBWPHShA{-KV27us>fb?%@* zuXfEiM^QW3hV7N?A56zZs}xsrweepXXuYi87BN4YmRp9&IZcL!@f4?|{VGF7|FR6y zL&J8<vr}1O+_eh4uB^Y<hJe0)V}2`B?Z`1~$3X#5&Ni@vD)Yju@hofHu}16da{CjL z86TxlroW<o)iJb>toJPHwFVh+Hpg(?kkvAi>z;D+RTF}bGyr27W4ei574;welKRbR zk1T?eK9d<XWQllzRhSuZ@;#$*S|_9a1F{+5!+2%19qoiY$%G!PfO5qf#VM>9gL@bU z?f8Tqy649|#R5Zm_`vioJ`;NvP`LV-ALkOQuyDuUSo>RD_<irsx7WA*c$V$~HUn<Q z2gnccf$nY)UkWo1dXe}Ok@${`#fP#EdUyr#n0A-*To7ksKc?KwaJ&zsXIk&_^^9L% zb^P%v?pIAK{xsPRllPS&JW5`lMWp1F+)10vxD-Et6OIp`v@Y37d1=9Yt&|dR`M1_z zebMTnl~!75WoEKhQ}w8JL3>`v`Npi@O1WjW)!N5dDW)6DvjPU~Mg3H%_w0d5V=b!^ z<vNX}#5UE7Dbs8Edt?PLtMP7)?b69)@G57&mO(jH^r$j7Xqq`lVmIW+UIBn0+@P`| z7U2WiEgTRXpV0^#8z=n!diYE{!q0$z%A*_sY#iZl_&Zzy%m=y{jGk`=DSLfJ_+h|o zGzk8xAa$<_xP!bA^OMimEh9jDh;Cq6!N$}g3m}#Pi~dFMMxDT;Wbpi+4|UeZIL=AN zjPC<3;p&K9hHP*$GL9bSn-tCY8dktnTrIA}-@x*M_l<Idby#2_c%H|YA;k?s$n%Ln zv>kkw5k{5q=H0j-lnEakr>V6^dJ4VQ3a+z)cC{D-(zog10$Xg+1D1mOmPYjqf#4p% zoIUrEyc%}iQTOYYL42;h(EC9@rB7%N)WMy{R0rgb=5CyO9d<T%Ue+Ih{!jHueH8eR zO}+pQa*%x>E@g`j=u<2PDWaF?084B$4{QagpWRV=`862?8-!L0pgsE6iU82lzE1+x zRRY@Yii4?ro;%@#VR_^7(*f?|UN!cdQ5&ZN+!>{g%{uCl-+Q|`eTXXA=a^hSJj;m- zoSF=yvzl+10HbEJ@+caQErU0nT|G?zj%o^eFqsGJ<~+B|`b0M1S0?jMQ-7I8JkOhv ze<as;ii5l2r)hw#Y4ju}{wJqwztebrode-T^Lf>fouvVEy+*t++TTlKpr&c9r@^p2 zxel*do@F$S7ZG=u0#lOK(DcEaWScjUc_9frY-0YT3=g)OmuuzPWg7FbSq3*{9M3ZW zTB{P{Srdc~Ma<Ym<EJ@ucbow_O;2SGoMgXGF|fYM!7I~@j!wn?BdwpUG9qOGjZOX6 z^dMXjVS`<>AIOV0nlQ^pGeM{lW1cKIPY>fZj$vylOb^mXqw!r8901B2C(`<DRj__> zGWsbsiaV;*@12ZTgPqW0#ymqL8RD%({BWG9V@&K};b*M07%{nX2^}0@fqCYE6+h0% z3d<}4YpnWz#R?0+7XJl3phq`|WBGBbZa~bi6fn8NP7vpe6CKzSloH8!O4<2W{>Xo} z5fV6UzQA3VI?V50&DESYiho+U@r1JLY)bo8aU@GNxNgqcXY(3Z3Dubww$e%|w`rx7 z5~8;*T>bvdB^C_RlD30vWj7~Ot+digE3+1FkJQ6HPxar94YRiQ-A!FKYew+Ba*!lB zzwVtQ{Y(|WcvH`v_WM=|92K=|5!}13y_%%_HrbdQry^FR+C2&E%3>ZZ!%QbDw4-Op zyjy0Y0N+3$zp9Fbn`}^-+HsmaCK=qr$idJDxa)4fWHcXa^ni_X7+(MV+kg4+pTeK; zIV<=nZA0L7lrdXI7_*a%=21ZM_}#tObu#0Pvlz0yMB6(7bCYctTT_X)@<?Z3mm@%R zcwcg(F1zKun0<Mb=97~E<2WC@%JjQfYHqznk0G!SY{W_Y!wE9MoIh?SrM=)uU*j{c zyZFrOJ`)vqpu>7xs<!~-ZSo26L*N@uvklxKu4W#1o#%oB0UlnE8d`xqnP6n^BmnD9 z24lN7aedt0IwL*D+s`5ne2?lY-jBtZ7(0Qzx}yUKUaX%^0_Qsu_N8JzZzt?}m^lu} zk-tPOz%3Z-It4wEYXERlWT&uB%KTYB<5jipR1u(*8Bkp{ScCE1RmXFa`A`|ar7Hb4 z_1@koC~4eJ%SJ7wKG0fCFnaEV^^KLHUsb6*RWP1q-DMTDx2k2|c|IbkmSIxG>`=|n z`X|dWJ@~GsRF_F+*y01Is=@ZOE4)Ru=g0fqGW&7Lp#Ew7LUe{=mwt|l0nUmTtj&So z;XF(h00qs~-Kt`Hs2n@Y(_`5-lfeuuZM{*Z-c~R(REByf>VNa>CcfU3hW4mR>D$g6 zCspdYv}in-1T?A9y1mHGOxnS!m|1Hw?%>As?o_g=>~&$;@>Icl7u%O-<R_Lv98=}k z>pWQ*+sgTAr=*_K>`74`0PaoHLmJiB%Xs5405&^rR#bla{n`D!tTB&J8THSO$EnQu zUVL0L>y1=K`#J^pW*>-9#^X_1+|Bg*=v>pp&Q-~NKoyLCR^oY9Mm@6Xlm(QR6XTGV zS}!}LB~<`ekCdo`c#d!qwq-@$Lq_5$QF4gryi<<u@I5aHG#|!jG{%G-z2KW3wx3~8 zZ)3sVIIw?p-)*2bfBW{acYrkp^Z=IueLyh?2pYr$le+>P#(Tan9KVL6xKp+DR4cn9 zRWsSmDid?rxI@)?DG}&F@5@}jo6dWx0Pj@<Ft0Mk(=zocYHwAbH&e!YuVg$=8ML3t zyr!ysw9*PKz`d2S5;BHOe&0$f=by|fg>5UXv@#oM{V-c>!_=qK?{`}{f5zC^`)jzM zcU#+T?48mWl8R&&2Mng!-<J&xjZ>gj)3IvkZB0}8ChfI|IjQXXsu8nx{svg+smb!x z1lMuC42h?t&GXB=`t%JM-iq{|{B4+#0=p^$yJzT+P6>OLDf)`GN1Vwh48=OZhL6Mo z-46o5onS-eM!w`Y@Za(UUEm5%>1|+JpB7gFCwLSO=(2?Z);UcNbdP}^08h{t??JHL z<NvjQAubj$pi7@oYG2)D2@mK8@s3{b`;b0Ed`5WxZ<q?$7E8cs`rHEgD5vQI*K%AR z2XO_f{4#i+4f=zCS$({*?a^brAvVu~SdO&S8Vl?rx<NGwT#f?62W+z)JkL#df&^As zjDdkAofrrE0&6TWK8P^S5(|;*zwr+wjI75d+^kf=hPyXva|_tVG7gAqu~`9bWXJ&! zm(XVwc#bVj0BgZrS8yo@fc@+j`$6nyjU&JsKhsZveow!zyP)sq5r#1LLut#`f%n9t z+yLSs@d`fz`TrJAio?LQyvr59ak`uaHtDeq`ZPVZfD`oD0yg~b>CvYT^cVyigB~tE zqkI~JyBh(#N87_1ZCt96E|S3Z=zU|qjx(xziO(_ubdS%^!}ce2v<<IzBfqC@f_MhK zLOjK_Dm7mkZ-}NpXIAqrIin-PYL{c}cFECU)(0)?Fu~5Uo>oIlveTNsssaYlS+7B= z#z#9P>RE?b)!aT+t#+>B|FQwURx`3!yCFSStxq%)k!slQ%51bZow>`@>Z&pddL@`= ztF8y8Vc$jVVA?M@4FhYUnFyL;Qq1npr@{1Jw%n#N6g07q76qi{F;kb(l-<z0E$L@= z1N}pqT{<P_OGQlWO^z>l2UMyOnK%{uv8>E>ifX_$)69D2<A*YuM<|1SxeD>ccsw^_ zBv0#CRmpadDRDo$M7v1Rfr9w}e=GNZPM-c{iE&FAW+Ji-{4y^CfL$W)S2T{N*-e&S zvh?Vb^mEH_9cmZoGmGh7MeffbJkje3J+1rY>ysIoi=zh%)0p191hGf-I=^4Eu|UiR z87FP}*uWM;=7A-KYy(}CKJNcz8R+VDu?k}Qk5(_a4s`cl{hfcc2;3EB9@KvPZ>WX# zefj^vGHIFo%!mf|iVQhF#g4qcH0no-=c^?~1|8b@YRz@DbIw4Pt-StGhXC^KjN&In z2N`A+hiv*OyG?Z0$~oYit+Y}kZ*iEz=j5B6pWUaT1$4I3N-M4G#zM6n*V=Kel{)Pz z&-xXPJO}k|D$ZHz|4oPI>;`yKrva?7XP}p?)b&+?D*lE+2sE`ymlFc8o3guT`#3er zHR<o<4D7iG2%$2!;bf4KH=e4ugERWu0YV0M8yg3>MLf?T(EmcesqX+z@RHaDRuTzz z#|I+9&v78KN-%|w>zibDPhO`|+co+90v1D{lf%hp!V;JK>?P{qWz@jSv}u)DZ<TSq zOnq;aS-;SCq8r;*<T?f1E3Rihu)^o;2R`BB*k)Cf!9CutK7-aT#8sjX@~83|F$DGD z&h<J1$QJi-84A=%bx^+q;%|yC#X4Azsx`NJfN$^LdE?th55NZ7Y@bB@f(<r-b+*_B zwzU6uGXS`IqXP^cF6hBX^Z$SL{y$c->g@ByK5Mbx?VU=^nVK`_J#*%~Jw1I1Vn_=S zLVO7#zQiHOaU6?S$U?r3V<E>v7IJ)vFLID$`4aL9S-#F2V)-J+vMkFXTwg>GBE&+- zVGuzGAwm#Bq%UgqoVTZ^r_*!Zb8BiUrE+<*cK+CFSM9xO|5$79U3Kbo??-~u^=s|5 zp7pF}{rW!NM`;H6gh4%@*&SE{!e{lQjJB(#en^<o^O&=e_dTPWMWBw#%@809`d^j+ z)m4dI%?jqP;)_vL>XT<J_}r{t-0ZNybpg432c0!}deilmZ>bOE7%;i2^|)_Y$~vvk z7KpiN`xYBOR!~EiZ2>oBjq$bqeTJF?Y3lxZ75(eA(C$_ELA8PYt=)Qft<Q&9z+8FH z_Hx#ZZj9xgRZsaV8s9<Xyy>;lZ~l^=yqflw+rOd!upQO6=M11+1dT>^zCFnn&PmDu z?{=91>iLOk=4m_NYny(|24LErKU@ahwsAfYSo@Luyk@?oUP6m?NV#9M^D}-!ds}8I z_iB%3oAa+~;AFYqw4Fy50raxcKC0%0yw7JsR?J)3_SO#+khKB@e20vTGG|?1^-ME> zAt(fv=M#+-2X@GU3=_-as|=`{4qz!_aksHo6L_u)^kv$UpEHjnnP<|OL-Xn(4ga71 z+)I5kJ`at1`Vk#c<>_<JEdl~yz!rUApB=V=9d_9PZe*7aL7d{(>;PBzPq+h^F=oP? zumg|3$S}C;^C*#=Qodc7%VB+c)%<gtP03ll8tJuu@>0GY-?V#h*Zp#^;uDm>QD4d! z-{yKdDeuaP&rST6^rUj;W1IcZtR#ny?flnCC&zT$)JZ3?Z+_uV-}$$<bb9Ed6YGU$ z$2J@vOm+*LPCDu2WclxFV`COvr~S97feo8B8(vF0LAe3?4OVWCE{W@1)@keWi)8>D z)v)D3YW>}0L`tjV*LBAKYEy<*0fgFOkh5Wo&0{o@^S|+hj;}9rwluK4uV4EF^gfUL zpNcPvuL5^*a|}f0Ms|VQ#Toj*&HMnLIEAkdOxeK)aU)|908g;XtDyPUVW5+_$KYky zW}q3}W3KHX7x<W%0euSexrG5B2{eGc#}(phJP!zv(FoXOAie_PM)nARn;3{w5WUS+ zzN(+EfH!!T*He1gB4PKI^DD+>D06JliT%WWF4T<c{yfFH0{ZmX1_BMiexJ8^oy7%L zK**geF5tHe0Q{K4Iiq}hu{mQxHnsDF6k~ie<tmE{Jx`p`|CU;>vF6{1KIRJG@g@fl zy~jDGz&58N1>zKYVjrTAcR2@K<w|r8qK_HyE=0eNPVqg6yyzwrh&~~|1~pKj`Vz={ z<TvGmz<0Qf5TgG$dLjBPe0n6$`rkc(GdFzaGnWtGl4iKS$W;y@x)lFq$P)~S0qzqZ zoTqq>F96@vf73wr<TWXM$kgjF<2OwJe3G&@)UOtR_ISKx?I4eNU6Ge+e%Xq$!8Y;8 zov{pX&wJjo56J@c6RBd>$~z4y^Yybz-+#THuGr0+{>q-TSO*;EzGOM&@@m(8O#=Q_ zS+lBjK~PdZ)o6v;u06T0DpkvR^cwejTPfY;3hc4YIF=2@v1)Pk+@v01?H#VF<rmr< z_cs1FSkd?l9oP45pMTW#xAy)}Iope?9ZK5IY_I^%Ih_MUuN8d$T1`7L^gJ)WsDJA- z+qc6!@5(sdB(qGJzIr+3HO)NHMqs|lP+b*J;L23qcIF4a&|BLvU<Wz%wgGON&sRB_ z_1rRI)cgH1!?xYXDFO^v0sLJ3b{<gLW_I;0SBAyEx1E1~l(9G4c}*4g-?|wOs+j6+ z0xgQpz4L&V`gxJ<_dUDu80mTn-%@X?((aZS(@njU0Weh#upO3x=v2J#8|#W?VEh6Q zZ+@PAojv~y4Mz9ACj9X9-+&%HV2eHhu+KIF;tY)2z`ocOI}p7b1K$7g%3tmN)h_(2 z(Z%VNi9XMaf$kAAh-Ugc@IriI6eXDl-<!8$kylbx+Oqv@J#BHHc0Hc>tb%#F%@t|S zVLvD>+vTl9j}*=$*DyXwB!Kr(Oa1F=U%k0Ecgk!$pP$~KlTK=FlRN3eetvlCGvVLA ztJ8zCRBe314Vhj$5OUix>r~Lmb+i%de8|a`&Fnq@*zB|mPwMP>6?WT<(QI@5|7Pqd zZJ0mgG1{GKLDN-sCR^wySpre1I#I9-G*DLhNMBgE^q(q#NP5;iHM82M1<n>Q%d|%| z@F#Vc)Z3VMt1dqCE~1kQoj_kD`7!s02=MTMJ~IOSd3>=G;=h6V-sHP~_w;{)_&4Gi zaRoTTo_G*Ye8^c{gERy7;-V%CC{8oGr@v>~`+}`1pHX}99l2y53A=2NdEb_WOO-NS zhb6CVAg?mTsFHqOUVBZ3dpkcNGvyieh@RmOd;*c=Z9W06qBxzZM_Ny5=5pPC;=K5n zS3q19=Ltd0q6fJb<QaLR{1rrB=LJrKIvf2lItA+c(NT0iMECF_9|Aw)``ic&m=FRJ z0zwcw^avrkI)`X09WWu8==mfDvd=OA_k|s)InX?2c9-*cDBUiTv3&td_cJ<^^Y#}r zy2s_KT!6V(z}%j;lkDfqjOuy7_bLE;&#(t+aSEcW<{P`Yb9Rld*Zr26-qnhj<6W8J zk1HUtXx?5`ecE7tR%<$Uk&fS173;xOth<{AIJ6!3-8AsCdElXJRo{L~R-#(2N4Ro( z&hC@^HH{;ifYB!UwjCdJ7yx6ymgn?+zj9@{ykC_y^qvNywgDtw{JUMRYXb7x@&~3p z^lG0=*a2~EnbvLWMLPKFx|wkNhU<`GJv6tEynqu|rqQbYbq84IGdh>~E$P@#`R6~) z)@Pn0fZZHN0d*O5mw{cf#_#g<+vNPmZ#YjZ{CK|pY?<Eu+KltEG!SKZeV7pulm|jY z6?zcG>)Z0vn4okITxP#+>%0YXdX{Otuj{{6(C=m-dY^n?s?i>?qhD_=jZ;<VZ}P^o zs<5kN`;(=1D+|tzm+fbfkwoU`!CVif=WChs91}1vQ-KsR^&B~Ghp&O{-kkWuC(a0& z_>3T4|HeTCkzxRZVh0IKwa1t+Vg!tsFagFyO!WCkl94cBau4-6RQh};m=i99^K-0n zAJ7id`Yf}Sy!Ip^yma+;Z3KqdKC@(<C;~n251i}2o_%6o#-ld&ozt~h$RhKwWObR; zn(rv&O3E$j|DeNRbW&%z-$^GfGSQ4yow(|)lTPX#Aav46C)b~>(nFlIm0#WYv-7i^ zl-q|}O6rqrS0|~)MGQm!hTBb(-my8tDY}rFwAQY6Q*f6(r%5XABI~y8m%P-oO~%V~ z2|n8HxK#6t5$Rwp?si*Mf3If$rc({a40cjq0Qq<j4K>h3r)(92Inz-ruk$|Vfq%)n zTmjB<IT`{Zu82E<^BfTZLynk1biff)V8kSv0)N9;ys6JGJYuHzZQXA(;E1WdAd0V8 zju_7`enMcxh?o&+!VDN|fb@*9ejTSH9Wmi+5S`;PGvG8bx&-1Zdpxeomk|9_Gnyyx zo^AHoPU-6^N72<(`-k+zDXl>TjOk~9`!|YPxE)9snl5pgkBI@<GvW&>pT&jNF56-d z7aheHE}s58eqxVZeMy=0S2kI8K#zSEK=z*4%3Rt@cIoNzd|;Oy0uXm|3)>*zh&|u~ zuCfjMk*fgFyBZqvRc>SlIK?Tk0}SZ%7RcAdPvmDoek5Ou-T?WixG(Y{^2C975%@Ba z9T3m)Gx0u%bA;jo@OfV1H^2dhTmi0V2KUSH-{>Mo91=6T4}n9*jEPe`&r*6!UksXo z6IsA`XfU-W<3i=WZvx*v15oaz0su($LopDZ3;=)G2Po~g$o*Y9fI>OUR>|+D1%Ae} z1hfGeAb(wtRh0Vrq_0n#tRGgf9&8FcO3xFD_SRRcTBrNY{o|(fRRz2TE7a2}>f6@! zZhd{aF?6nCTvwITv|deshh{lJO@G^FraYSrMQs3`?fk4<`8Z!C;JRvm)!ulh3Xqk~ z<I80<d6jF3dVaete_ITo&TpA&IR5Jc;FtH+MeD$(c4EWOUp&6t^yORXt?7ImIs%J} z_v!6qkf;mHwzYTL^CKIec9U}<^IWYCQHQi_OL;x&5@TfB>DTNRm72$G+7Z_57u)l{ zpr+qU+ToRt^XNi>pHH59rQDB17njcG?E2f4D5EOFLr^ham1Q1~7Itcz8N!wczbx}W z8RLHufr`;T!XQM6%+I}o^+wVAX1j_4(bW80(|o-Qd{4i>2)s#v?b*M9&S<&Kgns-t zx&RCr$BgdLffxWsVuvI6s~?^IkM;(@?+#!6w<BPR&`j>rXd0hGibqoCo5^{Ur_Tqc zsS~EMxv|57wJ*nUH?LM$ZodC>4_M9q-Z%E0NhzNeu0z))d4axpft+6M`p>SOb>~I< z{i~{+&+P*AywduQy5Zi*wdG1XImz-%UgD)r4V|1&ksai*lTNOA2^%Ntbd#V{c_*FZ zjKkHBLR$u*Yf)5d<s9Ft$c3Tnxb=G+dXg>d)K^vSq6^Q^ivP=A%v7&s{Z$3gR=A`z zFTNmGOQlx(BinIM_n@<`UDO5I_!jnNUX&$_Qpw-+1x}wH0Ytwdpbzx)>(`>KXdk%5 zMLq<2Tww_8>Wdkf0v^ZuBbTvV8GvMEFtVF=8KxM{^H_z#rRzA!m^jt&1gzn_>1X6! zl*@ul2hv~?ukv3eU|FT!H|;q4iOMavnDI_6wMzkC7oX=0(C2N<-2TQK44vkr59jZx zbU#F1v>n|8ksobyFR&waISuS`fo%{!<P<*K5Z-W?_#tpA{Deo~hBKeO`={O+xaHFa z|MdGau+5O80~m0~5r{jYs~kdfi6KK^qyg?zP3VvS+^0DJ_q3+MRQ+Lbf#^X7puS*4 zS987V@*<V%Ps;)E=J#aEp3@v^Q)5iZB}V!D_sy|9E%AmnsjEW=|KH~2n>oIx91j4# zS1`Y*V_q-2t|R;v^iiF9+cOid&bG?x-Lzl5HTP><V=!p3f0a{vs0E-Z+s7UULw*wg zWSjLW18}WpA2zR*XacadXF9g^Cv7o4%a!?sqIFvnOR568mhE5a?K4&rK<wqLcx8*@ zC2gmwh5ex|!@qJLSGCX4+E~9-mERVCTsbq9m$%nzIRj1+LwnuwO<=4oKz(^#>RFts z*m*3wc~2Fbzj;pm7Z~R<vzjMqe#3wPwFHoL%S2JdJYJ#w$Qb7$uw3VrjpwR!Ntg4w zUV+`(1`QOQ4=Rg(aR~^>>(4sl+kPIE1q3{@;9SNl?YU+9lS}78Wx#D5M|qi@ON;r} zoS(`v1*E@s))+5m4M6Q}75eprwDR}qKnhu6AEEKu*WV8ffV)hckH$9bX$JQIkNAAF z2Mp+Gp!*hEz%JYT7TD%n>;QZ0Fn~{gI(Yq`?f~bn{ErUD`dlkMmz-+AdzQ(4rcZzZ z;~cBay`gKyzLP8_TYKK?9QzZ&2Div-u&=7}-zODE(Qm<y^Yq#)IoJ2}dd6aojFNTF zv}D~aOUAQmaXd(D0uH?nr`O3UhEyk=6w4jlHeVce(n-?;r%pQQq?3~-%fO~Cg;KXN zZbz=?jom5%J||JH{)W{0xB&2K&Hd)rv@3PO>}lQOEUW;?xXz!&7e8+H<H`)yw7jO{ zT(#UUw)35;dBMAUF)R%Rqxj-x3!i`((B1>K=+7^50^m#hfct^}86j_yzVHd?0aAb8 zW5yJ?!j<SMFlNjZ;E*dEu*g6c=oU-;H#trXHI$||KR8x%CZ*}(^XN!3fluQLBk@ZH z>;NG>eB#u?0YnO4Yy(@2c?g(lM)2FXlY3YIxQATiozysy#tL(v)7;DgSS`7YT_EA^ z4z#5%0L(JeuFHJFyDR|EH)m5!i&N~gyXf2KVfyT*?CmtCIK=|6{vPjfG4;7OFE7!f z%0Lvnc`D?%z9Y?$f25i4&#)`@fqnMa1I7#)17o(LiPqbjz)0(F#Dp<K4@BRMo`7h= z_jwffBziG=1Jv`;C(%Ac|F7uL=mq%n@(p)<=JEktzTx%HJa~|1YCq%%qD%aWBjBQD zb{{ih3=HQC?%|xtJ!HX{o@Q20zt6m%vOxCq7*;F*@r&1rZ)AK;8up)NNMA5+rDaBW zphofdR;5hs$#W-_J|&+?epblfXrG8WuYOZ!AE-8JP1tq-U9h6{Z`jg~$S=9DTNM*} z9qH9vk8TQmhHtrE+LV1oP}>fgSxOObe$|-{s-9mwzT08uZ3B?d);`j;9$$CZx2cu^ zsHR_8*sa&9T~_<!di&L;nFE5x&uc#;fhz#IEYm=ffL~d<Z<MtF?#0aQ(wU{cXkM2V z^K+f?En7HWvGo^TjdE=C+$%W8Xx@L>*3{9uZ27z}ZyW`+{gYQvKh=sInR;B-vu8El zJpH61|6Ntv-h6*18w1}Rem`d(w*^dJ&bBA|q$E(L3UF=fU+b=mO$O{b<IT798>U}& z{arO<etuw95wPEOz3y9%7gc#4mv8U7JfWWxRnLd<_k)skZk4~5CGGGn?Lk)P&CB^* zk{7`FOr{@-0!@R0dP`#+5g4zfaSrd#b>d~tM+1GbrZZi#H75dz{|@NW2d*%n5A3te zHgF{342`GQVFwuV-{o0grq4eoOqmjAe2o8wI$NI7L=IAuOeE)5GIO5O$!a952o+lf z$jg-g&ewGw<SMh4180}@=Cz`iY5=#Y^}HtiDjm*QZ2LE{*K|Oldk*O1v!_n3Y3Yor z6F0fY#rbBblTJG6WYr6^Yoq;LJYpxy8=P)jb<%VVuR6PMmcU~CZL<E<b-H)+DwFhX z)_km1ZpX`ZA&;^CUJC%0JPDWDU5|;)1<-Dnf>Ap5S3Uc6P0eg$H#PtXTR&qyH<(}i zdQ0|^W-9VDLs4>JlK|XzG+;fTPXJux4Xy%`&&@9)6JT+|^qmIw$^vF~X?$;C<H_gY zQp@szzu{8*Ltvj%oB?r)%glg7W_*}4mh#{!>5EoX@OfzHcV=9)N&{HFTyJGCb(>m{ znO3JS>Xc!Rs<gc9^OD~l%^}j`%<mWfDdSmTnuA~Lh?#f~<Y@u#0vFk43Je&t3w*#u zW*~0jCb19V-{)IG0Y8hL;&H&^Z9YdFzyOO2-^6eA=K%fq^PZk@!nwY^`8<?<KVeGm z8~v2{hn`_gq5j01m!FIeGM^`w(wkp2lBs7RGyS)>1Z)p8;||DW{Fh7REyF|7?PKXV zq@eIFelKqE#KOl&mI3#D=b5DWY@}BHg!a!}nyz>HEw!!eBCCzHlE><R@-}ReuKMv; zWUoa`jLpw2>aBaQ9^ZBC++<9ajqR#Urf-{dSDk)s62PHqjo)U060+dmL1nwWTE4=T zt=L~;LY1}K;;K)D8xwq8AY~n3a9vFo`OCohDQ<vx-%{UIK1f#VH}m$TszINX0r*@q zSLBVGvVEs*$e$~NylP;VW%i;R?5|qiZVdEQ<0Z|kEG_KK)<#?z#Fb?WyqYV+up|J+ z0tj0PXp-}GE35gS2zcpN<Y%Y~Ff$pLi)!js*t^#N0G|b5yN>^C`+8IZ+idhv+%M9~ zw*7|dD8I(}l&Wz)nf%V4@!rch%_;7;u%JG=6k)6vqoVbfF=q+SF`&vT2nf;j7Jk8e zTck^~KYJzpEepJpA`duTJzticYgFwI@)-TodI{&}MA_#{qg-XQXA#INjWT6soO&4= zkVWQ~^ts+Fb*?kf)B!#dBrws`9iwOxjexP(5j*gg`=|cHQx5^7zx(EY`7&@A6GX5d zjiV_r=D)+YNdw(OO-vB4aeSwod-gKp+K^S>w{GfvZdqVhlltZ{m%C&<Q}grP@_DRj zKeSEQ+HcWLT+T04?F>mOH$YYy=iXIBBsTMThiB--Q96KoCvI{@GhcPGTJbv-baEX@ z2gt0iw@y0gHUw20vFlqK1~W$|8#<o6W3KJ>KA-q294GP^>{S&q=em|v&oaV_i`k$i zv)T|lfVN**uC%;}FJ^dh>FrU&b+KP_+^%YU?N<OI7SH$Q?<I^zX$JSnoRMgjVay&d zBLH5E{=hllpYxUIBVfjPaT!q2ISzm;{0&oJ$dD;;5FKd-@G)cHs(23tIzcad#D~#` zz*Il)JQu{HEEtY15ON8aX$J30Tw)4LnJ@vygqjH{W<a{k6(+zgQXii8*(PQx?*U)t zUhZbW;67%`L8|9I;B8*l8j`?NUnnKkInpVGL(POPfn63Ug>U0FK9|y);tE6k{p^)l z%=mK?H*y9DL7V|TB8cuv^_nNPn5BMoTl6A(ss8*UK3iaf5iI(As`VIZ2C6gSG^c?t za|fpY#9iD1;x>K+z)v{j6<}W<k>Ac)P6Mad7pDM^9xp)j4IYl3fanw6<QWjJh@Oxj z-V{eX4g63%FWv@z#eQ^=m=XRo@M~V=4PcL3`4VXcOvMbuKJg*^A(9zHV|qwn$OJ#7 z*J&!HGy466Nj(9otJM251CSjWz<A~X3i*K<Cc}FX54*|GE{y<)h2IY|K>56RA-UMh z_hKs7=ggMi?fFdZMKWtRM|R9&?fQ9Du|8UV{iIWU+sJ$*8+^KMy_))6*I008boN@c z({#x;jKQh`z}4o;zbuo{x-*#;0SaA+7U}^4+;$p%OZ8Be>r(sYD<{3ywX48lAGNOi zZW{m)v-Lr1qn%Rb<-mD-*a3)x((utT`?u?VzrlF2D_=R<t!=sWneS~zi{Fy{nf>VM z&utm3{Z_nzeYtfrNO&nG(Ka#yR0Fx~XJ1)zKBOG<YSSNKMZ1dwT$}=-QjFNOn8`&@ zzzFU-FZ#~sN76Wla?hY7E6yKX0!@mT*7KOs^XI#I_U-ED^7L)NoIaPm?068TEc@*g z?twclfzV~+JRA6De?F+l2c9PN%ARAWrS_EpPs1hq&G$Fy_T}5xg5V%;Ug#OmGXrFT z!q;A=A50<;sTtgTeV!I*VvwHB-MFnO8+zJPZ3$n*&);Di^yw;}?*GHr|Jk>IbN^=c ziPGnhV?f1>?$Jc&8tm(n#bqLdxaP+NOqUk)0^K>#y85EdKFEH*y3T&g3wZR5wSmh# zVY~lOCG%mk{pO;4ujcx*P9~R@iPz?VRd05~trK_Y0PdYQN%Y0&tI^qGw9F2m)k!Cv zbkfNxH*D97oV5A03;gP&o}IVDWZBvCX84~~0e0I2p2#)oV^wyy>T$CQKu11Pp=`~L z()zGv<ZNoMRVll@V;-*waJ~5AbOEzYE^a)aKfkzHq}=TRef@V3GrEgs#cSLH(N=U9 zj{^t1%C~^C2Ecm3oSl_frtiq%Zx1s7<>mG*1BjLJ+?eSrzA)+$76f6Kzmuh(t0fy! znQtw=BQx!iOZqP#D_OX8Rx`3dA4xrIn8Nh8#KU}%n?VEw+@gPTF7=$G9~MmR8HV?0 zFS;dq0HUMlVsskho$_7r1qh$|^Q+O%LH<(SCw~v}J@K*pCWxQN+tj<@Js1A$&-b3; zPY-{3b@tR5xXg&r0bJ#fBVyu)L*O!p3_<)@heAwsV8Kj7&8LJ>m{Y%*{_8EhA7<<> z4RALvY$45@o_t?sEPH0yU%Fhg4@`i4o;^>EabfoFEZ6rHUn5Qn?MzwuNl6x9Pf2;5 zw7;&X4hU<%K26FEj!92-_2I9neydtX2Q}&^S7Oh0^;9cn#<s2Bf>BPbrJssgS5%JQ zsMNB0yJY}sBeP)w7;3`Y-*f!+ssQN487bt-#<wCH0K7_j^&9S7Yyr)F!*NvQM*>I2 zNmn3<ZRWbFa*NvE;yzs11scg#``vG8{1pKq>)W}^*~7W5Tco4jRspatVmu9NGk?0D zFUivJQO_S1F)O>C1DWSAMf;N{^cZ<E^?bYW5<l<9miAR<ztW-Kf*i(sTR$ob)?><H z{K$DGgd#@X>cF#jK6kSRRpA$v#X2;f5W`M?=6K7?1R)*ALB5^IN(TG%uf2-$!U~{y zl^xm46Ow8onxx#SbKjt#9%0UU-8}a-?Je=^GRLo_1Budhv8ZRZ9AE!(!RVd^xF>%- ze0*R_pPz0qq7P!g0Z#xs>@WcKMGSO5!<Ze2zCfSHfQcsTn9K<@LQPDemWUdX^P)CR zUdD6;Y@2;vR31Qj+|qLl)GXd7cqghq`XvF0b*PuB=AocsWu_><k5bnA*X}&Gla(Bw zbkd3a;l)qHBYdON!&)Y^PCDsiUE{5r3+rmG9wSmGopfR=;dOc(R5z8}_3d>}R{tg< zyYW>ifup{Tt6j^00_kkwcKznn(o50z%!{P9?9-JozHI#@H^_e!U3isUV8s_fzP`YT znTY!IG$T=uJ}_X59<WVM^g#R%#gE0az`x^W_5h!4`oNZEE*j_~?@$Ag_r-u7@x_e- z2E4%x^d%1LXlC$GGr0Hg`D&`Z1AT!s)&13Di$05srY*J@=+`kP{4n|i=<CbtkO?#3 zGUua<zy}QYEiqtv3V58=7gh1a(LSfSCDSkOX7t?0r_Tbob(+(h0%mgvv!??Gl2;2x zsF)ec%P?Uba4z~_QG9fO<aQPS?Qch)XyAFQk1M>c8Rv`az|){)IUh#}XTPt@ok8>w z2OL5)<RcCslI(CE7_kGuDYlWoM|{iyaKtb=0LJ*d4&r(7EAe9x2fQOb0)D`)(dU3i z`2uG^+%CSr7a{VaXQI!7_;2vIco07QK)&%8mk(fa!!P{c01g>4VgYc!$Pq`tq0Ue^ z)ByMKoQZzH;Qm_{fO542G|vL`!&LY|4kK1HgIu6G6fwA)zCam3_Usd;#@I{)$P++* zUNFRTZbz!rGZz8ji@xs_Fu+f1d24r|yDhu*Y)$i{`~1<ipKo^37&y*PZ3nJ3)%T`m z>In_t)hb0g)=M4ZdcOFg+SXoWD|Vl@AK8jOkhPz`j&ZW+|MiT6q<4C$^~5^HVO{3v zy8c>~*ITs5cwSnYNY_KupO@+dlK2(=#C6`Q1DLB*?gAL+#xPy16J-G6+Uxf=16pkS z&2O>KH0GLVA!w-YDuBOg+0V$<0z|6)lAXWt3ifaA0U8P$fK>7MfD6#sPX+3_0JP0| zgf)94&BSd72+p^sz*@g~CoI|iYO>A_s16Kr$v6?#T!(lyGp*RHkIRAU<@UY|oK%JT z9UHsy9oLO&$uD`OdNBd_RqODwOhS2nr)XZawfC|>mV9P^SuwAd_q!~dC(0T1Rf>7N ztiQYhKja(Z$F%RnPE3E~8Q)KU@Ft_XKmW!8=<WkO5r~Azy$8_?njmDC0b9Thw=n=t zv&#<1{lDD3`F7xUmnN5D0*5g(eV#ajXrj-%emJLSSPv%YddbA6D(w5Dh&d1W#~gs) zR{3GY3R!V&qGwlygR<?%V9ovC$u%t<sIL<@xsR{TqmMhezNMRZuH^-IC!KWmcfCr` zd3UGzugffRefx<`VrG=r@HlI}<Gnt{Y0(9jzh?a_i;FhfaV{Op&t6C<t9B{}=Eo+$ zfmO~IE)4Ihs)x_=g;qB8ZUVse=D_v<*oiM_7-&FwK)_#vIv@QY`VfQ?cZpvRGZQ_W zvG?VFnE>PXZ<t}APMFtC@NoM3>3Jrcmur46`P*j;@Y!O<G9WO`fUQ#FR22Yyl)+4o z!Qj4Nq|Y+GE2CaTb7h);J!An)U;JJ!G0H2Jfo@6tB@2jq`u9nDpW{s~0>kKS4uEg) z!=?Tp=XolIdW%C2#2-P7#k+g}>eWwoqwj$j%iG0wK|LK!qFso7%;%z8AUYF$7=0PU z5BaM29B{YjiBAAO8b%{P(I*6aeUTSvXt$@2`U4HnpUt7>vy9E88LpE42mx>2ewE1# z;LY2qP#RFCAkys?L0n!mo%_cGKrZ#~vyAWwqgKNBWdh}Uh7V1cxq>C1ksS}c3ZF7F zfb_mmPLa$C##zv4jwzn+q!T35eO@}QHIVH^l)vVkiK^r?&7UVWr9M^bkGA&3s<PkO z+aF2VTbFoivh~1nJ-h0C!@2>_6wIqt?Fw42PyRZ%ikYnr1G_Bg=X&1T8W<jh^>&1! zXrA*O_G7E?dtN;z<hj12<9G;Kw)-Og6Vxo<oF}D&wU?dmRRku?|6RoZ+?EyisrJei z{D5j<9+DRRyH~UQRe;jKa-LO|-?IfK*9ZE#{mMQ=LOYor>I7cM2IG3UUb0kQo@M=u zcte8{KO}36LuvvT{f7OXjQ_qhK}3ESg?%O`xwI}Q_j}Tc5w<8WNtLWaix}gp#<$FA zhv(>jdKG@ema)8S{FeuAc@^K!W(=%iV)rdGUdmK?Hsdd_oF4*9KVkyai{=@x#O|`d z@?|~9-1$Pz`(0+vtGwLv&-DJ$43x{$XYziS%6KVB1MofJ>DQh<Pwf#0X88J?B>*P6 zMq^!*q1Mnu|5c0`5feF#fvIM6m&~H6J_r1P{u{C&z>pd0g-(`jDp^r}y2{7Q*X=*r zaD6ldDw_dEu7U2Z`%>2oIGX~*4lLUl6!`n<06wp<f4!FMLR$2HC!N&VR&~-znOx$k zW-RNZ6Z-{0C!KWC$*LsWFs8Fku1yI#6*Q7f2?V&-BE#1OT<!voiu5n7?fxX$om_Ek ztC-5l>|55bTxD5)8^8?NqW!FLT-JGVUBJB5%tO8T#ZABr*uvM~+AS0?W(=TV?(o~_ zS>A!@|ISyV4}b@_D2@Q1D~y5jTxAN;5l2jcx1%FMV8WOXI1(SSO`IAx01g>320~`h z1UTYQe1n+5Xaacbv#aYH0(}OAfQ&yE0|tzM89r0sw|rIn0O+&Fy~Gzt?*bmX;uLTz zTRaWSG*|Uyu5cbw>_}mT#oEIYTdB{t+2+eEfW>FIm3#E-5X4=4j+-G$7~OvvJ<9iV zdqQAOJj3n87gaN0pHS>B>_+U<kM3GLKKdHFY^UsFpFORQgxNdblCHS|?&P!FlluHB zf8;Q3hX#u8Ac4<wmK`7zw{r@_%{<Hu_!UQ-2X^&H*kg|XIK{4BbHx{TXT%=cAa=!D z;sC^7^ElrI9^qB-S>UDUvFIDXHecq4z^&{ufar@n5d9K3j1Hr-z>p)Z0!MS^_QMQ= z`-l+}V5AxMlgt3qSl^Kbwu|J#PcybhvlK8tggO7!GSEHQx5QBNk=FYa{k>soT&F=e z=Cz`iVo*;93M4W$fbpiU2vdEW=R;=3^JL-vtL$=rxxS`MEj*Y_Idx@v%(HT^rj=D# zlQFTn{<5`ttYiP}*PQ1^$FxpXIhkrUVLwzg-}@`H>ozVzgO+!ss)co&tkKWo6`X_F z1ayQJIW%O8{p{I|ujq<p*@qV6PA>cBXt)Od?80DeU%s2ZeFwXB>Fpv$^tQ%VHIsX* zb}9<?Z_%ixy&FIhQRYW2>KzsM1<_XEfUW;G%N<qhC|v`=5+?jn&EE7Hp4TXc{k?2Z zo~bX-aRgS)6Fo;esOqO)LH$OK^R=JaUzKH!sAlT-a_7&g->dn4s#?!B4BdX^d5J1y zzAihD8Kvr5C&RL>{i~(*w7Z=r%+#ue9||4M2h|e5*lwPwnor8sUuDm;-H-W}<1G1| zXOXEWZC5scPFDu^JZ9&S<$7aS3GkPt09UVs!QBj?kU9R$WTwsw?2|eB4X@B%Waf+| z{W{G!pAG~_1Kbz9?Q?37=!#x9dB8Nfs^`6c0PsYd5p%>?^nod3odI&f7^3sc7{l)V zssHrUQ^1c7r~l;ynD8i5ea<;!k-2bj{<VA#a~vlp$IbM<s{6yX&Vg*p@vPe`uiLvn zxyJI+Ym2aj=Wk-aNvm~bJLf5#T-VY8+&giS=<ev=Xwd1QlTJG6<iyKyEg-wpL&qx} zP<wMWyeGp?cpH7daoqkS*f8zX0qCmhaQyiz952T^!!~Qbs>cLa%TDv28?4A4LPti< zwipPP{e@i1I9DqgZ@#0R7r$Gi+Kp4}`Wo;aU(5_NgL_{?+XwXMgLq6l#{<A1x{Zf{ zQ_-t@AGlduEU5DWc$}AFHw`$>um9pVS<ZB|^!qdjdCHipslP>i5f=88T>4xYeXU3{ zrib%(%2e4Zr`F177o;zWvd>pW-^-klnr4nSEloz6=}Gu$dk~NCMQ#EC0k`P-d}!EO zn(=+XMIOJto157KM%=_caFq)vV2d64z<0R=AK2rE;vV2T{0(0NZy0^}=kN@?`03$n z`wSd0WOM*m<^cDr41ueRI0A+`0Aez~=$q*az8N8iCv<&&r0r`KS6@7t>W`RVebG;( z-Zug1q0w%c0<Nd+AT;%Cl;<r0++*<!#`T%;dzS1W`CgV8K1U*5FJUm4M#{qTr<v$o z=Zd0nzlt@)?3mUY%K7`URX^X>ep0O{R8E1A4f;VLE9|sh`Kwr`D`Otrr2Ua?|E`M& zMb%_NZTnm#Y<WETE9#fJ{wQeB53AhAx%ffZQa{TLu<y1qVz>gB>j%iV2c+2aTj<P* zoo$azd1-k(|2g7^1@(8Gr+;MWzY2hT;)#OqKkjH}bpi3V{a!yKKsnIax2Ta#KfA7f zngHb`c>w}mD}Jm^X7?=M(Y_uw4DT+PXR7A&CINANf!|Rjc85iMY}P4Qj&mCzc@mHo z)C{-?sSX^H6+1KO;7{si6jCJs=)Ax^<vcFy`3bKAm|f&Qf)Wpx0IgMSzo=XQxA{cB zz)w~AFR$QiV0oP=EBmF$zRMWYs~F(}V||hi$dN2(stXH&?D^wG7Sz*A*@wx{UN(N@ zJcDAEQ914RJzaj12{Ueo)bIQFAObGo1ATft32f{0)E%+IHgK9L+rT4C*a6l12M?av z0j5XWfBO@l7sbR5Q~r;dC?w2e08F16t%J$k#<yLM0PJM`4IS@iUDuy&Aw}C@;y%v% zH2;|Dqnyus+Qs&o{pQo*cRJa4=>YDXxXHuZ&;6YmI_ae0f~8v^tY_=fiR*&BlTJF> zlzCz^Q=wg}{^;cCw|!vxakPKc0Rl}f;MEDRyShx7Y6WKi^?**YrT)qnZ^eLp!%qwU zc*kGVFswrO4efUs7?A*4Wh#kpd{LNO#00=V!~pl6zL43XPaniZafkReM1STKK5(lp zXNxU-Ac#kR2z0q0iyd9gSU=}2%_Q#4f42j8n#o+^aW4zNc!(q*KG=;fG-F1jgvDse zm@5!XG^6_q`ZIt2{XSdzIXCNa2U;^T(#%cqRnfhCnXjev^$8#Ihm>~@*kZr}2pzCR zK+Lcm0$=1y;sFp}(17f3;j;(KG_=}e^jf53R`ZK7FEd`4_gAbxx%9btp{G*)-V=RJ z0Uo`WVTuVOV8l=}=N~bF=!hO8;4R&61MSI%jF|xa_;)v4zTtQBR#3etRPRFcZZzg* zh`!I`JP5qcEP4~f3*spx$oIsJ{22IG;zx`iyd-|*-*y1c+;G|t58#LaW8f-%4Q%go z1YDXkxW~_*GG(UqoCdnji~tAo;!kSeduYJ)z4$kgW-Lz_;3IuWD5SvzFCjM&BYA&j zFtewF9J22xfcboYJoEAv@5`L^#e%7Q@$OIb-=~Z^{-mIub$neK$lsk3RL^%!*W0TG z#@6jYKWClrRKt>gQt|my4J^xBn=PtR#?dBrAy-t}b^*?^1#Pw0Ua!UR&_;cNhU@;e z_Qk5DeZGBta)E53W*|f43a~9`f7AUzR5Nfw*ap^y4f?wr09ovhWP|?qTg)Wj#%$~E zZ)^abRps0IFRw=ZT=W+d+K>I{v<c)<Ed_LWEqJj!z+=<EsIZ`BK?MVT*?E<;Ja3Z) z{ihtp&oZNPy#TYk`CK*_A0EvJ3Ic3_-(KOloNPGm68*{szhBma8^C)3?5;O{lJ#C- zJs$D_#eStd<+m%a)LRi#yD|d*tNeqRDWKTivjI<m<v2<7)2kQ{=Dgz-Sb$A{iA}(P zpQ>Mz@tw!SUZ#gKpt~&T|GW$YvSj=fwcj%s+0Fh`n9Tawc_c8NFP8xBi}%yz$T_gx z)9-tD5IrM&;p=nDG;zo_I}Ct5wiy7Y*k&8VKHKa7UtmQ1y9D5#WVD>=bIS#xL;5^s zw&4UxClvs13kX*<Lvt!4gFxO)QOENiH<6wy@TX=wLyJshb<R_ib^pl<J*vX@CHCi{ zO#%$s$mmqxJ~}S<PMoC!xOd_v?{I+&of<m1Mx<jh?&MmKRi&8jq?1loFPk1{vPwVE zd7#z%d3$?1{)0++4fRjefmpENcCsk1UP|(|>S=qS@2bx_KoMCzj-vODdEND1g`O+) z6us9{ea(v<FLhCq23GeqgZox=fgXsRIl#R~AEGCt%h9hv`202B0d6MCc&!X3>in8y zy<3_AT`mECv*m}D-ZIcF4G8q5@>JW|!rrpwE-u>AePl9whpG3|jPZ-#s$7P6^Secw zQK<lgbo-UTnPu{|r<vgwp#5S!UD3?wGe(S3zgGqQvtXc)`{^o2jDZ7=P#}LKzASp6 z&Iu_3;B0g`8Ul~<1MyW5FVPn}aKlygi$86jfv<mh^-rIifg?tY58x_?908X#llxT- za33<(K>QfsKAop%UR?AgdP)HANv#t=cbaj3(f=U|#6$Z1uWO+DH}&fWQ?Ju{n5CHA zO?yc9*DN(si!v6NDW+k;pstoa&szR02PRQ8e$p~288^z&=f?GDwrV-47oKhJ^Zin9 zx%%~8-Fc<A;(FTxVBFW;tI@3M#ie9D7uMm*;QZ|bQm$&fT=hi1=02-Epn0|wZ$<5F zx}Nu2X24H${$M?O7Z26Yb6!2Z?pTh|KjK?8{nmrd<6Sl$&$50yTN@t>z?p1lxAo^! zmw*iAW|!7>Uvod(*sq)I?^)PY6F=v*9KhtYoH0eU0Faj!^S}FfjD02+m-Z=(^77l| zruV>jzRkFkxqiZJJt^mVL9bH(u9+v|@nRR~V4l+{3p<b%>!Nc1<~ixvZ<r~;s~H$+ zGGbSa*CK+3vVL>PAds93E6M|WR7L+3|IUpmy}JMM0ozsn!>j0zA|`cJvQCv2{>o43 zEl<zO4E(B;X<ZrPD_CO2mrLzU0PN|E0igkKHv@x$lpo0h#HRu7Ch$FJR}4`94IdL{ z#*7I>0s;`*4A=s88HfQeAZB#GF9yEL-)-;w(_P@(|9bRqVnT`$Q(&Y4@96U{sVNJ* z%5&Fz>0A2NNq0L~Fn&%hc2lmQU8}}*1&-%0fpNaBDpr)Xfpxa)hvoTgITTE`bcQBN z_eb)&%(T$Su}BAS@5D`}3>kK6=zPI7W6zy*(n%+sG}~~u1-w-S+pcR{Cf9ktUppcj z+W)n`?vZP?&(%K7+n|1sYiPgUQhVyA?yl1R)S>-N0bXh5jIf1+yH#4MdGWRC@gEkX zR$g2jB|z}_LPlwZbT4Mgjz%$4kmzgX?2BBY2hr<%$T^7a;u9_c_cM&HLUe_ZcndgW z1i(kp5i?-Kgc)#Eysi5yzA_nU;Bu%hY>rTD5d)KBM))myfX7q=@I7Y01Yd)MC0n|k z9&o_Nyb0`c8>fi@9An@}+sJL~%^AU`#0TC%%07=c;z~+SGtIoTusdI;E{*}mWBvWv zoN+$XOyhBThWdLm4N30d>r15=(wtm$C9<vCo7iC>`udVEuHR1dhW<QZ0-rEp0j&23 z>BF4oeW;o0J>5c2UtQeC&Flb@A*Vr{VT%dy2!|+OPe1P#Zs9br$DY^&6dy#N0B7hi z0CBe%@ILS{xAFq;3NI4^_i_gT@DU$I??Ln*@tx>h`1D2jgn#P+JnuamoIZe~XcUcs zp$4`eXkhzc4uks?7|%J#6K3|%U_Q^La1Q7GDf|AyFR2W0eQ^=H9Do5tX=e3wV1!K7 z1F{V4*?@;E5Z?4T(*nS`H}7w9e_vKk{`bp)@Y516n9@fhAG?YR78CgIujv|Rm4R&1 zX<k&;^=)%jRL=F3E2`&u`fF7H#8s_Ng2HRm)o9v2VA3nKTeV`nRWr7&rar1Bhq2f4 z>bB-M5UwfW%QA4uTH{aU*55tTm#X>vX8R`P*iRnq&M%>b-M0zs$m>73g5D_t>b2>Q zvkb;wYktc$*r|^G{Dv9SR0X5BZ&_|wq9ZqEed%NuRrPEuqlworP$0C(T+n3v_?Go^ z0mSE(Q<eENNIk<Q;8Izht2F7aCVnrl<jyYx1l#DnNIy2fXWMhUB7mG-1_4|9@+#Lg zW+=C!I<O=8U1%8qRRv)89oKPQ$^BU#U^}o}m*oMttHzzI@OMS+loSJ97XcE>b}Uol zTIB%LCDnmXegPmpd0ts&k?iML0KYW87v!u9()BZ$=S>E8pDf^g5y0UI59kRmLm=YE z0QcxQ`t*PSeQpAFG^6`I0|p@W_!>LFgPP!B!bJa_>hrLfJ~v&QgN3Pcu4Il4t;ba( z5y^SZE}gWykFI+Y*<SCK`GLCUY`rM?{u!rTn(wghkS%J?7O?KEW_-2A_+AvyIkx<M zuN#t`)LCA4(us>aD}U)d+o_?GV_EWa(#dMY?^MwFkwzQC&f9g;?HIaoc76Lvzw0mE z?xy`A8;`?H3@B(Dz~jO^R!2W=1IB`e{S|J=c&cKWT4s#$=8Q(U4DLFWu4ZtLo~KW5 zh`L=o>>Ul^|I7!`!2ou+!q12g;uBzS$T9<Zk>1h_>1CD}8q7;oS|8vu(t4R>`c!3@ zu9Y>Pqq6cbs^ERwv6a5;SG7x723DJ_??2)JaU0;VAH4v)#Os{PJk4aNSDD{`o;x@V z?2FsQDTtot3w#@*Q|cGdF39KQOX3_vitlm>#9iFTBjDW^z47O#&mdk7kN))2GjTw{ zPY;N$aLADO^&xPHAtPX%y5O4<1K5**h;)kPG(0_hv9|!aCjkHnQ@Wa`6ILt(&l4EE zOnt6EJZ;#+)UXUW2cj>YR|I@d_w201&hjz`RC%je<%r7vwKRbAdEaXT<hd&Tps9m@ zKMCvLy6YC(b>BMR|27PxL2do1we_!D@qSDmqaFGys=wNhK;y6_;G)@H-x^@Ko^@hS z@T59G;WGJ&^*Kc|y}SB96NnMC?g!j5gZV9u^N{8NM6!l`ss`gzwqW-`$$m?=GG2=J zaZLa+Wx&BYvsV#7GH5uSZ3E9ehjuH6aTKh`Uzz~ea0LPOvc>(sE5O>eKLf{hF0x&D z&gUgI>m{!+kj)N2mY(Na?WGJ*-qf$u4QNQ(?Uw}jRWZcd_yc7*-d+30{C%)=Ze#bm zMZlWpIRD6sd5xT0XVvS<qI0yW)|l(eqVZRBB%NhklaJfQ7lgnlk(eN%64E7IDqxU` zh)9e^x};$Yr9n~Y9D;!4=#ZL{(nvQ_12%HxVDRks{NL>5K6`WTzOHkf^F5zxIT|oY zb=|&)DKgsohJeGv(_;~ww%x=X!AUm?UhF&Lzq<FY=7gMMP3x>J$sn3Pm2YQFbGr=j zRhSPz=UVdZ@2a!x-#l|SZ(GeAr=-Xwy~qA6M%%sPk^pep|E9yi58|)tLmI)_5x=h7 z)FJN3g3G}dX^{4@MgzZxr)m5m<!du?vW>_2t_3QF3VO`jk)~3xntJ*Lh@t>>hk42r zXlMKa-f6OV_L6@x{~drd<*7G!p-vqNBX!FejkPiz__O-$=R_Y26~vvphWXxc$Jd|o zYhBQCU@~|PrjEE#Pn%v-x-G1mJgkMc)P9Vtn_60ZR?6G>_N$XaTS<#c%oW7x_z{Uy zEB)cC|Nb)2<f)(;DJbpCbhX_b_vql!S>>t7p6a@&2TRBHTn7`{n#_u;<0B4#Tl{+@ zWe~S6BVab}Ia<XHuurbjZ_%1>aMmTFJRrj<{w<zTTYg!PrYl$C&OngrC<GTA{B3nW zEQe1xb)IKTZL=f{U823gDD^&&Q~+$VAvhejUztroc4&ai{>S1vz9zUN<H3J&9UNnA zaYUm;t$i&ITJiBZl9yJWZk>~RY#W-d^blFrAC8FWf`)h``5vBFH-1oTlv>d<x9<R* zZi8jFE|1@-63|*fY-T{s=0CgKgwI;(YnML92(!vQPIY>XLVu<X&cKn`y-g$47BeC+ zmo>LOPemR1gJwkL8ry;LXW!m778K%?eLwnCIm*{BP8D=z<az@Zxo5jyb+ry0!7j8Q z8!>=S(g>nAt$W+=&v%wQ->GM&`*VDZPTLv<oItC23y#Acr~=pdLm_|8Z5H_3=QwX7 zyzuXbrP%%@coyEXXnA&Ik{SRHzztHTj*lYVB`L16vX%+juOC6w0-rx~s8-RC%!}fI zD+@JFYnDN`*}z6ku8Hi1ZsQf^8X~ybv0WF*fW}f;oNsM+pM~2*PRtj-`SY7ey-Hpj z=L3QiFWhYJd-f$VjM+4}{_I6r{Vn4}dh)JF{MdLre$ZgNFkd?>sG+Q>e1b*<oPXQG zJn1_q0pzX;#pedRBxeizxUC~o<7611yJRf+a7BD4rYn}cy}@3Y&INJ5Zsl*Gd5)&H zs-Tlvb8M?Keop|Gig%F`N(APOJ{W7Y7LBgp+iP(&y#a2X?@B;A+E-t``CI62+3#z+ zT37UV+&@_wC%@P?MJ{=Ee;tbps3K%m4+cC-+Aw}|F?cxJhj(gh5gs>4JgHU<`BYOi zTcsvrECI7aik0DtoK*y{CrW64&Wbhx_l|a5w{?s^<oK(Snlc^|C|RwVAP{B#q5s^i z1C=}Z;z)}Uf8K?awhmMn9=B)YPE@g{J(R~THy?3=*28XF$?{#d%#l*qsU%q|?=<1i zh4mNhEg{DO;>1bR<#r@m+rITBVOJd~JkWF9_{qxd&raUa#oD-@4dXgjL&&uEF$OEQ z`-V*6=SeH(aGrd4Zq3*7k+bXHR=8ro_2_J$H#1yD(~pP$eOGW0y@hUJ;*b6`#*OnO z#ak0xHAx>V_208<svqFKCx94BDD-v9Q68LTg)0U(3UN(7H9Ya-<<F3!GU4}f{T8Z9 z3}-I|O8q6Klaoq|RWF#smm@?_r#grS4e$QdHuy!0Sy|cfsP`|G=Z2~{#{+l1st|!n z-$f%(5QZxkl`GbIkgR8fnVN?@SooEfnrmvPxG>w8&U|>0TmJb78JT@r|M>L}J{Nyl z8=_4@T^6j^5n4g7`-*K`l}#r<6@2`W?_&d98r7bOISkJb6jq$@oj7g}nvH86K>5+< zmNa(-0_IXocEvj@kcTCp>}c~9<tUYZwHtSqymy8H{^ShvT*Tx%OVmak%4qyWD70co zSDKsxx9_bcaeMf96DSo7{Lw+DvZTRO*$!ID7O&T%$`dz48pn93(7ro~Bj{lW{gTZ? z5Q>vwL_@|}&rAP;;DXRSz7OYPessLY<(^&L(vk6^yMZm&*{svZMF1z>rLzMjDMZgM zyXf7VkA^le#)iag>@3UYI@e&Vlon_AB^+u|^OLE?4l?bp^aWdjEFN2Nl)58r+YB@6 zx|4EbULE|P`ZII96*uzD{;8H!xL~)w@VFm`NcQ56S6`^J&WTQ)+Col*is{8~!9j@w z(1RHz)=J=8LHiclZy_z$?d&Im^WV)4DFjejjv__PyZ9`4oCiWgXCs|0O~=WvF%RfH z7&vPqZ64W{V{|zsp7vpmAsCbLl;SO8*&G8ZW8*>H%~O2x%pLaA`CPS#;cNN=*^!3i z9ma<J)<>_vmgLpGBLseTh<bI_RSa7jm@*_0GsyzCueVaR!RQsIj>lf883Hn4!=G}G z2_)B;aoWhUWR=N2Ww0>a>L2iOitX?owbYXy$i{5-Mexnx>|=UIPTdN~cfDsZq1(m} zzo;SWkEOpwq0;7<-hW)J{Trf8^iAx2D@W0lzHuj0s&S~Mm2|n=jL0hN>G~F)Q8`pU zA79iP@I&*wvFgZ17+L;ObyMnjMs=9}hQF|a;ZIR{{}*uB)a3Tf`!F{}(jOqTTtf2w zWRcPjiko3{gHzEZrfZUq{}UQ*I%%vLza4F{a8BluWl@tf`}F-$^6O>_mhkyS_i%HO zGi~!G9~QIb9o&O*?@W#fj&7Iji}=w6=d{4B#L;)nXC&&m-8p%i50dvDqEF0p?Skq$ zy*d{?7n^1Z6+(p2j|iQ*eb??K68PA|ac<+*0!B$)cAtth^jt1V6m+L+IXEgpp=0ag zMwEoOj;Kw?`C&A)f!96UWBvX5=YJ$OCB<Q5^!6AQI7@ghS>CNd*Kp0$?l;*Un>+QC zb)<_$h6|nLpd*}Bwo0R)n@g3SRv~f}=MmFM4tvtmn7F{w|5O6-6V=$O9U&dEqsj;I zmY0wVNCw92O6ClK7+N~Ht0^~Pe>L;-x(fyvNR4)ThSLP~fY^eC+}UIMB4S5)jG|D} zR!gT2gNTNdYFuclXO9lL8|Ovkmt7Kc4X0_O&)xb*RvtXpr4s1gp3iRn<@%WNh?`0a z<UsT&!jJy9k$+g>zfsn)cG4JH-zg&t=GuF97`PPje)ZLo*#c%|%DkcD{jcC(bMPb{ zaT~Ty$PQ&(=)a5GVq-<A_NKRKZ1li$_FDZr(*T;<j;U<&8vZt|C9=`{Nx_tF%4B!m z@l<BqRtpuhb(T%*9~g=Skgy?7x@tN?8VER2dq$s^2<C3Iv$)==)0=vh%_;ANH<M@T zCTi8UmFs1%`f8^<mrO&ZV}hm2++GZ=&^6F<q`jZzI_W$XFyR<F>aKMrUn+B4KfUH| z``L9d+h!B4U8i967jf#1E7V>$S*(J4JFQF}OKpP)hC1sw^Zcy(`}BWaUHr+t@Bz0b zPYM-333+AD!{;vl!zILLrnm2h75MNa%cUS{u2@aRP#*Sk`jNy{oAat{Oj=eFb3(nO z^sbS6)GPrnxl})YYM^-)*f?QA`yJKSBZlEt+gxf)?*3+mcrvdo#8Z`6sUqeT{xK`< zpNwsQuGIN@nUKvNzdb?dARcQ;Qv<W(5JURDj9#$$1D~!RGq|4foVmwYa#5(y+mZRR z3ODlUJkHl}n6vG3PDci^X%#5d{$5+}TOEQs=}gqg=!_r>rqw2908ZRFb1F}R3Bf}E zv{o?PBvPu8@{}PfHf@fC|M#gJ;+aK%QDJ5G>R`Mej$WOzUL97udj~jpIy}pa_RJk> zw=3d&d2>reYOs4EDb#HgaFoGUa<{OoNws0&`48`zT_c9U8)XK`Qk6yT&t;6AxNyeh z^bf7GCWQ8Pv))y8eH;ICB&_;5K0p;WHcS#tN{!1YEr=dqC~>gAoM!X7n%ORK5qI0l z?0P2JgI6#0R?QmC#E9$e&6{rBjiS^t6=nl3<ojylW-Vxm{z~x2bt(%7qVHK)OI0}4 zRfmV8)L=EvPV2`ii+Pl|zlExI3Av|hv`DVsA-&y7s-)XE#Mm_Rds=IPJ;p5e-U_jz zidLh4qVYBbnKpv*OC0;AsO7N%RFlc}?)z7os^L?T*ylg^tLc+EW1bgeo7qXJu4>I` zb2PX!At*A1zyjI*S}$OUn{a0OsOsfw9k-TWN!S3DQugm>oJKUHN%RD+v94}&hwyN| z!k`1?x313Cq@o_H65Em4a!gV$bm&L}U=O2v2k$3t1)HAu5hU1pU`gcxBZ$Y~FJvcL zwEae+kX?Y$PuNSo3JZl@F<Zb=HQ?+!y?q4H|0l*y3rbdne%DC$9ad+LZ>&NO8Wsev zB`*y?7yC3{5az{wm2^ZbG;P<$NvKI|PMw(khnv~0Q0_64zMvPK+{HI1+zbP#1&Qkf zqa5#<e<A~r?l!l3Ac~^6%gMf}T}P3HnDfeeOH-(kgSu`Qi`r^kQ;ltmcbT5P6w{;G zP%51h`kiA@lgh<n3`;HlTP0D6SIygTT5D_-oUh}pjX(1grUMmr&%JT#Z))ynj~mqK z!=D2_ILetj1I5OVH;o5V>b7gE<ubfKcXaLwY6UldC-Be;>~wXJDr&#E3X#=&)92<J z3c1vqFIgamGMq(EU=RMuebM!C9junYzBKkMw;gSh?A8r>9FoZDcWxb<mM`!~-Qp~> zn1om3^Dx|1(%-<No;2FRZ?xWVU#M0}(ZUWy{L0GrYL0z%SrC_Vm*%jJ<_KTYA_86- z@P0)ikg&~`fIt^ttG|Xxv}~A)?c#2Wvn`CS+@ret1X)(}vg^H)rmt8M^saxF&ER28 zcCbaxkXhj2CUDWRhoz$Lvx@~%xe|<%vZ9n*YU{K{t22e&)!t#UOLw=HQKhG$8FacK z?qlk!?X*kr^-WNO&R6e$!oQiktS1ItQ7uI5f&bf4?MA`L_?vJ|zZsRwXxm2D<iwPJ zdeDG``-d%CfrL-5YZGq%|7AKM(*HB1!hMpc;Vm}*J}-elGvR|snx`&ckIZsz&H7R6 zA-5X4_)~P;TYe{*KC$H^BzgbV`D2&N>=x@Hk6^p%0I3?sZ^*t2(=4$0bnfMETI=6# zCe5a=aaDJT!*?1v@awFiDjx6W!hW?-TIGc9DDJ~N!rfxJ0myS{rsrQBCz)m$XdC-? zNoqL+sBYRC*X0#aN+w5JF;r(K9-lU%YMB8@b&NP+yrW6*zBnWQgh-=MiVW+24JaML z19!nv5qKQUQ+XcuG$B)-fsWRck<>zYgTs)KyphQ~F%cCO`wq-0h(S{VKzJ}19T}DO z^`XUGz7hR46_6`Sy*tabyoPK_(|_-GqEDCmhYn|0h>hFNEK)}25^uK5I)53Q@nG^e zqmpXuUh^li&e`u{Jc?KSve_Jibuoa0*IctdiHd~XC`N-E6qw>=f2NrE>g2M=5_$Hr zU{t(60);s2j5<f)oBJSR(u7xsch#?w=^Ft5>O0*ot%B4J`)LbR@MFOLQg4M&piypW z<raoR5)=`a=TY3&^|P&z02(6u5m_|ppcZ&jE&DQCmXh>U?#kN0bDn|k*|u^pI}4J1 zjTN}McAeq9sphGA0W(r6gf3j$thhsQKp3!D{7YEMBoAdshb_=Cxr$(y**#2NcdLDl z&(n!WF+8q!d_7ck)TgjDKe6*CFALpT7upYZVm;oTz&3!TnIg2>fMEYocpb1~JOq9O zFMJA6Te#F5KQ*&BE2%@AwrZSh+w{AGBW8BmiN68Sc4;r2*X>h=*$usrriN{V{^hEX zhF-8~J+SA*vr9(`V2~U6vxBF1TE)g87}sU!t%fuSy!d^YsC#Tv{&)*?<UB!X+rJZ< z7hIIC4rEzTe+jH|+1gAxjQp6DT;}AAtBl!fDmEL3h969Nt^aJ^G8NtB7}8bE$G<t0 zC2;AnZq%yLkBn+IKFD8CYQIcOY9SQu+O(2vl79ydVkV3Y(Qwr7*5WSPR1iF+Osber zAG6;kU=S_{7%s^Suuq##s#KA|3>gq)|FR8DPf8v&Ne`>gy6b^H1qJW0A@h!}so|<M zkaFNPgxu%~eJK016{XLKE^%{AR9rqYGm!q8H$~s)dqDBnui9Ubqfq*G$ghXB@zhy^ zh6lJNoUcyR(mPL2jWV`-xpDYnZzk0;y?7hRCRa!0|3*;GiRcogZmu)y!U&R2gmgbs zkpIG-LPCW3q>;_ZOk|b1Dsf<*Y`&;T(qacJ8y=%VK)Ar9fP*sZq`4ahKU1@gqHW1> zZISlDS##{A>50d{If1%BRWE6_kbZ>b=F&o}m}xF@|JkA3@Er!#p}3IyZEAl2@VwPr zn_^&>hnZaw>}x;^VDA<1NQ*aJ+!7M>f$B~S{Rh1BM8uz7A;7~Q925d6U+OJdQ@lu> zrdhVCLLYDRZ`$`=55DENUdXs&Y9?5PaJ|2~$Ur`V9XWf;I>wcUe}3&EJ!5^XBa}jl zfCh4TQk^0n4;|c?+xtfNja*dxaC%t?BaCtlqCbD$2Xb7OBr8{!is;y-=TW%3is@i| z$7E3qruy1Ob6gQ*5twSlr#FlFZ$-<>&^{_?32#ih_7LnYN*m$#l*OG>^y3IQ_X2KG z>6N5c=8dP&;g-3}>NK{k(+k0J?F>eV*_``6ijV<U<w{5HRw}vTog`@YJ%0d$f9b1# zKL-u+u~ps_<~Er800Paca+Dom?@j6Bj1}pMofJdl<FH1!^E`CzA?3P!eL%nCwvicP z=dYDUG4(h5qb`HdICj43;<C<$+5F=E+p994e$UNN$Yb4_;9fMsdyZ3CLe^E-Yd&dh z#Kg<*qo+0JK0{wU0-$@!CEl)<i$gwZGlP?L$6J$`u#`R>#23puZEQD>s2o48Tb-AK zw2iW`6y)jDw?Ov}h&n#=E`3ouDRHNTT77@AX-+@+*lau{n>hXp8HRN_!|pE%U#U3R zcM^YiVqk{XDqn>M7_8c!>gR8pAA^g<+n-OUe9woauYp?HuZP^BZLytYVmU;a<%EgZ z?BM$Y$eB51ZV6asJXK$x%Fs(ro4!yINQ-n<IT4_~_BsFZ&m^(n#ieY<(}%VfK~}N_ zDlFRjjtj6&uSttb#e6EwWy#jq@ANnlD8FvM12ENYO(~~=ru)Hv^{d`>jvRjKyAmQn z!KYCDFRVyKEMq|GRsnQg`NQcqKQ3k#GS0Ot*WATzl($%5(DhP*rI2}bh#{GACs0X_ z>GgDCo~Ql6QC33H{X?&SE2n$ULC%ZDZ$gZ=PZBwiPDS?oSv4LUlYfo`chy6pvNuSB zA(p1@zgR#pdu%Rw0Bhv*pIV3A3<3UIJxIIb*YP1+Hc6aK1gjOlv{Mvo(~tJUI;vxX zyLGG+zhbal6Q)PfmYJmq2OgtDjin!p;qw7_nw-<Wymky*P827%2JUhW+sDd(P)s>X z6$7%ec`#3{T{jAiXVb(W@Ep-62#H5_Xn#?UYjO8i2+R?F9ommL-M@=j6cDV|qbey5 zx^~?>C<75FXtVFsUsgF_tE+vyu=PuNb+L2_iq;-3dCH(3$`KQ^Sx~6&5xxK&*!*ku z9`Pa+soD0d%-}KtxfeNxsTRoe3hI{OJ<3mx4BIe-cUP;iNqvtk%#-!Mb<IB(O8SM7 zuf+#X_KyC&yXat-AGmCeT)I)%xtUlCnTj#*Ijp9_Wp5o=1#7?CT7He;PU8+0^DLR7 zv@`u^4j?q^(EBCC#)aPEBSUY`bwMpM%qnRh{&xZ>b1Bb!4(~85u0qY<vyag(rl|SZ zp9*>KN4Z5ck@9OT7nw*PSB$+pE%JD6y6totID(g*J4oZ=>HwTmxpy$$S(2=GC*zQ` zA#2WoF0>1{cE95kV02{gEv<+4iyc@1pQQYFQfXlW11yYl^pr~yASr-NKBhoU_aF)i z10_6WwJg~17wJg%Sp!NmTVLr%#~MfPRszv_LMkV3UXPai^|z|-FsTk18hu>d&sQ?T zU(+{bQoG=3Mx3BRn}!#>r}nd*)&A!)?#m2yPZt+G@BS`kl7m`o5bcfmH&(z|((`%g z=T7;7V)1t|TbiL0b{x_c97t`HsnB{YXQN(PvKT;+0cg(#8?qoKTz3TqnoX5eS~Pv^ zwp8h_&2)$r-2iwn!)wz>$vHch)cBIaR~>OAR+)$tB(Rp?(%3oxDvC+1%$hXG{c&ZR zcQ#yqNF(EOTj-*$^fgMh5{%L;c(2qlW!E49XH|YIpECn-7prRj8G4&<c#4-Pj7q%x zX16HR_W<$N5N@#64C_#LbDGph6CV3}vfXO5rW(uE<1*2=uUP+*5Nw=d?-kVhbtt9# zqom4-XIf+eTynC^(lW5>sPxhduKFZKDlT<xO`_?X6z}s=Yu4VhW=zHKJh+SSjaS2} z(3MRWJf>$G9)(I%Dm}>D_XOZ7`smyvlzk9XDSoVM5+j(rYWckLm&n4w7yM8D$fwAv z?)DN^mnCj0Y`5#=M%ogKCr&)J%YBWA%>@{FpL7}_Ft==mqu9Q00tJcBOkAyfE7n_1 zH{z-P)U2gxAVKG(ZyjEjpqrUIlJ#zxdt}!?O;$nqzvFlf(yHb^-&f{G+*9VOFpmtO z$dcN+{4c@kV!j`onFGA*PCA21%kzBPsusOB>k}5}zpW^Uzc$$Zot_50U_Lr2n1-2A zJxl%GE7}33b=G5xfFPQta#3Qh>ki4a;#Jh^AJc0rk}br-IfGf{2Jjcs<FO8WF4dZw zzA>pkm~sqK3FEit-O_?>Rp+m(Fj=5W8Y7oA9F!AYH2;njH>OsS5{oIOOU?f^S048> z3{L=XL+o}pP`@k!h9*laDVLw_^SXj0)^81hLP)XHfpKiJ+4H}sUBqd6gCXPrE@~*| z(NfBn7>fST^JSsit47?MjIz=84=&jEGv(g5osutJ;YaOHN9|RK1SH&_;?rksIu^)I zqyUk1V0A|VXm@xYZMK=%R}CRC{KKKjKVE8v!m6H(WQrRN^hj1@>;`Hb7fTXN$n=rW z-9CAMs;W2sMHhG_&|sxegZQQcg2b@KbbX`2e8>8|BNC75cJW?=9x}EtV{&mvYvNs# zRtxU|vb9?o!9B0G9p`}%Z|t`0DN$i!63)Aa^#k!;SnD=&zLM0d$MTmPHVZEKZCrCc zblQ?F{gcYI#KOQ(*Y9WM%kdKU#wCs2Oj#qUTj~b*{Yx#MztT((?lU#bp1%6+Vu$BQ z-M0O>@R}k~2J4pa?Jou5PS#;%y8oDOsUG>L@1R_<pqRsSj@6tIkU_a*->hTRIb`t5 z_To>hd0RnSnbaV5FvF1OTn#V&i?WwkoS6#8$|Zloe=fG5MmhS9@BaSkaragmvOHwG z*|mBxVReze=j(1?3`Vfe!{WHmUc5B}d7g}KhKXliP`7;sbP_=nAuudI5&lB2Q<BuZ zVz98hifRaH_FpQhKfHL?qP^}nBqytFe&tG+8t<h+@Js)GhXE*oRv!GZIZElXKLzrj z{zE6xeoi-6aYe6szPk;IOzD0s3pUWyCWYZx(ikLp`Or_K8u>A1qyBskHfv=5V&tBC zE>ufR8ob^kisLz+`nzM7IdH4<cD2=uB`J-(KzGzu(2us?qfOq&@AUCD)~`}6zdHo? zm~|fuN&;qfs!5t9+xP#xS$CJ4{q(f|_xMbP{%~!qW7$Ws2X4s#vfja+%&xy%sjH@s zJhKfZ&T+b9<c^Fw)T-|tuaz}~jL(?py9{*~`5Wrf#CK}EK9~dtko6-(g1^JjEP&a4 zSmiDLZ>(*MiwyC=E7MHIS#()*haN)A>)9M|t{;2BDQ81NWon1e>kpF#xAL@hwRC9D zG35*e`*om|$el+?Fi<Uv4q!@@!D3g6MEwxz>vG>038Uz=nB~Og_6^CL+%!K(>K^4? z_aq^KrT2CMdZ`0$<7=YtR<J5MhY89(JJDhCDnM;j%MByDuK8q9Uj=&$E^%%O({638 zNbMKI+I+E^>s0rZU@5F=kj1u@8|T7^`A0!?f6S+7Ay?v{g(amFo}V2VL4f8?#b&y> z&U$?`oua@JmC7o}JxN&;Ei%Gf4!}%52BtLRrd@zR4VIV)Og`DZ0t$b7Pe5^wZjMWt zC7AN^f(%KF-2=cw+IQ^Dl@QT(?rpuFCEUaBd_s^+VB9yih6=s-iiZIW{A$NT_Nln` z8{ojNU!lp+UDg0y#A=_KuNsWbPAp(FZg2f<22|x9uwRd40bA=&Zq})T)9{rB<usou zquy`MCl3GmkPP!%4^hA-qiZJ~>8$S>7P#&VY_IzP>+7&i;|D6=%e<ZDFU=<5&uY=! z3+lhqA;m6ORE%+TQA-LiYFq-x-E!0SYn7$y<Tlszd)N;rex0uPQVDaL@P(P1NN-@j zVZb}y<>$-+N4L)No)l`V2*0ijsV7&+APN`JJ&Bt2(sMnl>mR7|$-7CRFWl?GZ*e>R zK~uD<0So$7Q@|^5ype<$1v8<t5_=n6rllHqKbkJ_Lomr3%`C1xZlhk$L7xkt<1{?{ z@T6vk9Rn#}(N@?BfiAhR0)7Y+&EAqa#UNF7h*CER)!v(z_Lf}Pmv9e2l=jDs+_*;? zc$_C7wC0WMs{z#Czvj&`yUa;>)Ds@-4R7cw1P&%OppLy@r{?!xTX>h_FEGWtT}Nw# z3}OmkI%!{F_l(AhG3|YGH|FEMe`z;fSkjU1o#p^sTkbkB#-%RQ09OIdyxwF*>Gweu zFX!HK_a>vga}bBVb}CTn(n(>~GF6@uzaG*ar&}ohlA8tLYwA_H#;E4}@VM1b;+3pO zeObWx{7^A<h-v5N1(pv#H^l;J-QHghxvBnC{;K8+-1Nx#`keHnmbdX{+zqTk3U>A9 zSGuKz=!}bGBQIz@>4|N~&tTBYKAj{-&eYy1HjyI9GS41Q@jW$Dd*t`tZpC$e*p#cz zowAMHmKHlNY&}>&5j57)pxt2-3XgA(C*vQc>pT1hU6d7j6JSi?OHjD~{~nWZ?H$;P zZxHChey&G_^y)TAy}%iFIV4HZGvk{uu=u<Ess+KKY+WC(hoi7Z#SvQ>K0k*|k0tw? zeG<~Z_ISXXHB;$6YFK?{!MksTO4;RyiW-wTf}J_Y%iskk@)5VZ$vhggo8K20u-^Dn zgMP?v?MARD$n8LJ5IifOD`EdE{xZTBm<v;veSGrp@UhA&wI7$p0#a439oc%k`M8=3 zNdmf#g5_-3XhVe{P>^**oLW!<m9<4_+7A}Mi9UF;9b^&sTR&+kP|m*my>w32LlOy! z))|_U4HwCC_V<TUA7m%gJ$_BmmGMek$l_B<SA&+#EAfQ`z@Gn6I?L&V!kNQX|Ixn) z!n};{qGvc>%>ZCOyM4_>w`cBHL1x#=GYfk`fXr9bN*H1OTt@7wwlD+MW~Y#4Gw>7@ zR;;~x%6%O7+aGR*l?ye@CU(bl?T{Hz_Uuf!o=4X=pKMkX+l&>*OLG0`f)lo4kQ}RA zA}q3KW`b*s_JWGK&nZ%V(d0cq#)L)`5V37nXG~#L9063&0PgiZMb_2sy(K{f%L=KM zyvN<<)sl0G^(EbUTeqZZDA`4lf$t1E{Vp|ILl_nXOj)}QKJOQ~)QPa8eb09DSL71B z81iV{2YJzD&dUE3+*p7+C7`8?7*D(;AIqke!c2$)cZr}{v7q<^=0kgZi6LPr+LC8E zL7X1~^i#jMa;kCnrmdAA4vgD!AR$PlZpi07YDo>hRjK)Na$@S#V+F8Ax`XPIX)o== zf3|G%fn@32ce%Ow0Gq&BXDL8sw~Qj1b9e9BMS|3M;H--KNr<;N2NQU%8!evx)+)X& z&gyrRoOSMBb;ds-R29uJ?hoE%bKOdDc8oxKPdZ4ns;?8na&n@gTO5xVSp43EI4E1P zvbEk;irs)-mX-wv>wkW_d^f6(Ac}L>B&~KA6C^U_!J9*?!*&wzuJrW<olhMj%~##> zA=+o8aGa+Ls=tJ8K@n*%qzBW&+v)$FN^mnM#$sL}M+Y^I3TA8#_(lwCoy;JIb!y2v zDaADX8e6tv?c6u+0(=?4bM=QBy$F%ID6v-rh8ETq&MflFlgzbAG-rw&NF{7T(!E2! znF0cpBo~zeS@gcfzKf&R&ZDAkc%<|vORXmkx(5u*1cD0sqoCvUK$ujyUaC8J>RZiS zDi3)k+Rp9jJIA3e6iUzfgKkK%bV81l%l8<UHV<I`IyX*={4ZSxql|lZ2EEWpiI)`V z@=qPmhb}?Mfzi+}%Ua*)*9k|6=;IC=O?Nj}r|VPW1Tz3KFztRfT@$`fipna*OjktZ zQ?}LhM}KM$H!F40zb%dib58Qx#83u(neE_okN&VBi{^3r3tm{#pA>?xr<_(b=uKKv zvfU<C)Y?y3vdeYToum2V_ILsm15^Si!^F&4<3BX(&G8O~l1c)5Fg%&j8CT1Sl<w;h zi>F3(%kVUi(KSD^+(#fyG!Kvj)04+BQCvm0lKN^nAJUHN9u`6(j>&qm#hrMyaf0L) z@#p+~OXcD~tfK>bfWq}q67o9Xj37aih#a_LzPXF_%nJfslv;_U1Bmt$*bm~Y*I?V{ zFNNSgT>l)T^6Wb5^pi}CSXtxhtnGn3|NApz0HW=>y4yBZcKTrmxf44*^AYpkKjts7 z0f%p@KKM+aytfN6uj7~ZnQN+Ak8XzllHq!+v&)+<=@Cc*r+3D+Z<AdJIuU>FDt><y z42r~y8t1`?%s4I`z6qI=db^g{Ia#epc+&j|FP}64T!5E+PEM9rXzu<(MAj<M`$L2e z%Nw$X(^>2#AcQ0H@VMwOufT@A?Z6F}$>J@*Ek$m#=M<2W{;#e8Y>jyzbZ7fQecV42 zOK2}tO3+AZnU=(}O8L#6Nh~@@vz(6$hOoRQglnAjI)<<f4$b1$4cgqV5+8?GK-lP0 z8iuQVuD^;iKm{pLw<+Nfdk0|h+sbt6`Xh^+drzW?1h0alT=Ce8WB+jYWCr&6`e`-V z!bdOOByIo7^G|#s5(_<&fzE@2%~LKWM}sFGF#?+Ur`~S_?!$B?EGeh#`(@PaeO#OJ zDV5GqSKEu9LK&HYKgp1SpVBcyCNPX$@Uc{%GG&R?3oaAFfN`&r`Orz)r37ZI_NWOf z$Lf@4I(b%n&#PHvsVSv6Bs=6;?<TX|CqcT4=OSZz%%vu?y&WXFy2z~*5@+byAxLcB zj$|WK*j$gH{p>`mKlNvs`#X5bX9Y(X#jiV^-JK1coHnr6ySLwT`L<RQPA)ZAP~XRA z=+56qsI|Xl2AEr+xk2k5Z%#UF1qW~+O9M;_yVhu1d&NRSShC_p!M+ES*%THb*;_Iu z_4>1Bbt;>EjnaU*I#jIKvqZb^DcT6&SExU$#Mxeb9r0oMkr{ORDYz_lrZ~>2-`(8J zaId8k+l<*<dAI+)0coOU%82r0@k<?Q+)(|Qr05UG)gry_QV{V7n%ID-#|<Cv?Xm9* z)Pt_>#aDns_LUYd@q3UE!gitW5Zs5aRX>9R%^ao44X1&GKDv8n-c4fVhC*jm<`u1h zPr?P}i+Fywr1dXd+ZmJ6Zg;wudQuxhJ=R#*MW7>^gQddTp>#X}5Gg)t;JJV-P<GO+ z6u7i`^Y&z2E`fZ}h<xSoI%ru3(5Q%XdJ(S>UF?F}ZNRwH{`C*^__A}WuYZz5&8eR5 zxzn4_Mk&s|7az$)Hc^|!MVs;n9mU>IY#k5V5nuuC6e{h=tIQzxDN<(0rI)RP$o$ba z172or?@jzsHC7Fqb*mZG+aZp8O7dgoWuA62Q=}CJ!pn#DZ%QgyH`4Fa+C*x+L1ld5 z76wSZ%0ebe2u)U=<WzBC2aH+`P)Q$aZ&Up98C2}|2}oX999IB$dzMI^oYKV&>kMw1 zvd!v5Yy?~mEbR17PS>eni@jKEZR^MTPu5z@l|H@P@p1+tLOtH(aCBEA@lBF_ho!#B z#_QN+BAGnDmMy+w8g>?1`alCsI(fZ-3uN{}A8V}Wvfw7SFG7tPcb=+Fwu|1;u?Q33 z#bZ!Mu1m6AKOfnu>eVVz)TtK2u6|my6i`bqF%Ks6g?c%-`+Sx{ZDFX1O;3>Q(Lt(h z98r89PyURQ^lt7tYlfEw6N;`g1)dzq8wTkrc2d?+ZG4!r`^_TGZIMAfOq90vK|GMQ zB<p9Bq|kg0c}IWds~w#-_s9wqeYf4RG%^gqb38nn>{B=DbaAX8XDQ3{O+!tW{jZR} zDlx1TAAp-lF`S#?#lIb%|L*N6snd|)^tyv-nKGz)^wEF8@8X(jXVTauLyGCmJ;iv- z_y@V#eQYTo(hd9Qrm#c|$Y_%-BiXXz+g2P=m?_S2|FkzRlB{0eyywAWx6c_2vWVnV zUW%6gaL%I4pvuA(t%$gK(7&OZ^DPw|a0o<Z+ufx0mIo699$t&Pou4*sJ$STwTVu1$ zV4zfGG;YVf;fq1hB&T~4xp)ZOHC^M^K@vB>$B%;5Rjo=N^gTT@AO_TR=)bfh=|BcP zslb<FU1ceuxyXMv><x}!reVCSEy43f&k8dKAI8Nu^xCdNb_6s{ZGgks;^WT$Jp4^M zQYiQ;4D$Wfth>%n{U47+-4kCnztPbG`RV&lGIAvKblHtkMLEB<bRlA6<?Zz>9+Gng z0PnXz?L5~j0(8X6h8^%mamI;i!cFN?{*C%}dR>-KiZ}n$xniXhw=RXwbt{26JUgzj zN&XG#)_xbF!*g>Wt@{zJ`H*C7i99&)tvJTMjg>{bfqyYWs+b)$@N&R%a6I6EBW=1b zZOyI^DcTZZQZVQ4a8b;w>LBTEIB?6D;v|6emYw`2Ak>vMtqtW?MW-)Bp;F(HP0ew5 zJN_H|m}r5NcVLp5_A4X7V)BoQ16{VL$;#SSXD0%h%ZQn!#$4g-6%`~#NEakw@R@-u z_(8%^h?-1l#UHr@k?F_*zjAs36h<r^G{s8Xt+moK#{%<>Tk7s#3B>ll7F`q4Lg!+p zcIt2f+P_YmfoT7gZ_0|o^h-qvUwDp!8OO54B=tVV?b0kBq!foEc%I_5KUhAx!YFX1 zg&I@)+U?#Z_Qaf(ToWjNHk7AS5+GywqW;!URkEsK{&q37@Jn)^R|8LWn8%FP%3r#G zttuc<Pg4^f^<@HE@8>9$q!a@f?oXx&oB96uO+;qRhbN_hn*SbSlvPy?!iBRIFMgk) z((l1YsfZzKcQO12^Uy`TS*+N*KzI>M)jF>I;_S6(R^fW>P`|LHWPQfaA8SuN5QS0> zYRIA98uWD|MPYPZ6kLZ;&aym6oU&%6ki8sVNV}C9^l$lU1vXzYMAMCajbzt7YP?HO zk{(0&u4Akutyiiuy^wW0Rr_Z)=Yb7|Pv+06dah(f(oBDy%np)Gdf{5?08@Qwrw8D} z5(3X_#_$IQcK)n^-mkl9R3A0{1uiQV@&3;!X&z_3T&7F^A8)Ht7}q3ULJ}P-=YPn| z0<t;Urht-)#!ncl2aoDb6diyjovd#&0@2mF=qBI(?M=jPbV%j)B97b|WV*2_#0CZb z*5LYo{Hxv-b1;Eno;_G3;Kp8OHV$l})NLS)2=-K&Xy+|BxHyw6iWjU2ZH`SW-aR=C zA7%-@D<QBj4$F5L_8yD8rzp~N?M)&|vdtu@VEyyjLAu=}*H>X|gEkNiEEl(-;E?<) z{DM!vsiE!0H5kO7U0shO8VPt-^p;*<iH^Z6&ZmK^V|y9Aue@}{4d;PVEg0nvU7l@0 z{dNsPeBNnN-sC`kp{Rk`vVBAdk+8j_^{Y1w8ijPQICmawZbj5Z3L}=O1cJUiP_t#j zGr0_|qjc7Nl3d;XVPfrzcms8MhXNPLx&phfw&=h*Rl9H%gCskpRF*`0tWKf)_F}2L zxU<7$o6Ll*ty<!d_z#pFk<l4VsG`d$-BfBV_I4Q^F(q$y@@i|Q1{?@V)=vSiIYS># z8jw_Z6O+rlC%f>0{i!Z^AsxCwghX7^8}>Xi9HM=-%Jr8h$o}c-z`H)BuX*-30F5g0 zu$6Zsqn&jN6gAu~j6tZC0~Q@M9Wp#{7&4!_FK7R{@dvg{ZMU=2>qn(}4L@FJnzend zi<JzfoLHLzqWVBm`5ISbBB!-v0&nb9w88qeAK+R;cXSZvD#sYhHT2$=8n46s?Co_u zBQ$&?HM)!AN)+3CTXU}%&9s?A($aJrY-GgK(6JXLNw;Qaii$9#_o2;ZT8ePRBzc7j z*R$3Ndc(cO`kHcGN|_#csesmOuvvA*Z=^7IyJZf(_d;X<G|LKgyX(+(vU;IwC+SS# zwM<7(uZ|7_u!&DVWv%&6ZWTZfqo!7rr{z;C9v1ykJmRan4!@&P{{-Iv&*yznF*+yl z4ida1hvc~M)OwzZ#^Z38EdJ*Y@)tc&I!#cz**}RaY?rxm)z5sgI0mD=tG)tG`0sv~ z&A$I9Qb+OOc4eZ3ThV)Tx-;iBgusb>^$urQ!nhVC3$Ej7$36dzTmO~hq^aLBc*mb* zO3$9}`jJ#4L%7|rj%&-nRIxAUrbmT5#Cb3g&hHwVj>hhLZv|!r9KD)r9gmL;&_-g@ zDGTqPkNG;sKikg^6lUvI4%YCBQ3KBvb^wmkTICv_xji`yyZGdbXSg&P@%NTSfX$cr z(SaPEK)E4}2sGm(O|(YWAwt4B@sb^2O-ocR5qo(ZaPZ~V5}bJ*8HpCBP>>o8;n!X{ z$U7|-WLUIKN&WZay42V1{?%E)+^+#=@HhD2ZgN-1U;4`IE{f)$Ul*K{-J@y*at4LI z#O!9Iotqxa&&6py@X(h(olzBPuZY`{-rC2y43xJ0aLW<vzD^1zm5pJT9!7MqI&yO7 z$vxd;J!P3iGw&N8hpN~^0V&Y8T^F}}5Q>dDnIlJXVA*D&5bicIT=9pE$2o)1upg}4 zKYLn~fS!EFM9v<Q4z~^ywA0*>6gQH=dY^8OJz%5^-L1qG{E6H;1mv!|8YNa}PVfC} z?P>o~w$<>E<nquut7oP10Hpjv`m^#t)K0#NUOclQz(N+L)noe}=6B1m7wrlf`UA|) zh&!;gRvM5-s;m@!9kyC9&|R3I`@9%o1nUmR{yd>K)JE{zn*DPb+|qke;=yfVa)OdY zsMT4)wr4}6M94%Yy$n~ny~etWiP5lX)tTZ+Nx+ZR%M6O0g0%UJQp`3W#(Xnq^?n7K z4+`D_Tg_*$8kIArO9W7AExO5m_~20J5<gni&*#l17dv?LA)-Xi@YkMG-=XuTcEQ+d zrQ3g9=5EA4Lor`XCi*w^=r%`OI>@7+k6W#ZRY}dN#Sj11bwPC2UFt*!;4`sGwtWIF zO*;?{tka;I?MjdB<=!*gi{!B(5<2iQt7HLOh47o*UosYN?aTCUcAN{-0_@$k!{g-j z9b4mehKi0n?I6Z8^aUZJ8QnIYT8cqhdxEJ~v4lk&vIBPGJYfwW?iKXsD<R;91THY` zKqv56Xv>9AG<=Oi;J^q@HQGdz(3DBJ^HeEHWeh4v+Nu<X8(Aqmx^z5Z%zO|ZHhgiv zFMnMw65DT`9*!*%TS9!P<dzKz5M$8m%pvillXt(JCPWHj;yv*iOV*)PQrV(n%z0(* zx?ZwAWK06am0X&CI4;*kExd95bL1boBHvdGVpF0Ferlb4r~As>4cek8U$9cCs{qXH zKGisMCM{Dpd+8OJN!PKR2fF-|DK#T2m$jC%Bi32+@8E^A#x9@DYOsa6F9NYoDkQn< z%o;r(X;zhR5+g3(8i1lrMSEo)6nxyCFXz&Z$jOfI<OiH^DvyAD-fhi3NdBX&z{*IZ z@Qd_4yVejNOJe%S+9H}AD7G(X=xuFFBqOJlc8@?Rj4)-LCokrEnWvMmJzw*!yKLM~ zAYI-DkN^H%$ls?4{&ff5k<!4}VfbB+Bn~}z2m2Jk3UE!b%Z*p*%NhYQ+|n3Qx7_j~ zitHmkU(l_#SP8=EtR6RaSaYk~SY$eRf6Cq}*4oLj#3{ly7jI>unD>?p(s@FPzDpp2 zWhkrcN5kyJ))RpiFu)8xZHAT5pUi%fh4m(~FeIh$s%T$X%-e%4L{#cX=zzWo!KgCt z)OC72M7Xk7+TDD-Y9T1FPs_Gt(<#DmhbE)uX`P%Z%EVV==J3-46sqhOb@TmMopGhb ziGW-YDv>nPZETU_bmexq_xw?*NFMR0FO^16nWOEUmLHr|`HYj!s!OOJoW0jKHfqH$ z&2X}BpSl?m4vcV=?^(7S@?=p*MAW-F)usd65)6#T6-a4Fd<)7f@tY%3pX+}@Pvm-i zs*{TP4oywM&-gb6!`qMEFfvT|I-6|B4VHlPU*;3F__;3+ex9BW;u~l__$0Lw->X!a zp~y><_mxY@o*1bPb(K3~9vI6n3}A#GoQCPxr8ldwW?b&k;PQV28zLM=7h*2Hp9Q0S z{k)CbYz|Ti3n!+lwi0>QmoDPuDE7?BDDoPU!w}E?ia5d~jl|5$+wKE#XVcu(Kq~*E z6D{0B(R%)Tl(W3&y(Kin=4;yS8NS7nWn;$y5$JYVuLr;lThlZkZ&9FIqe6E`uy9t_ zsp;vnle*CTwJY2fpy9es8o=Q48B$_k9pfbE?RsD8-79bNmLAg|rGud{Ql1gKQo~0= zE%!6|r}|ZiGd#y<m#(iqQ+<1zwZ?wgA_%D3Z5XA!HAvOG<wgEQg}yFrXjW+vf0NkS z&in4~a-{)(R-$~bhcw|Z;eX?s#52}uOzZHR@Fq*SOK+(`=n=)wgyXw!%R-tp?}at( z`&Hr04Evv6Qn{Q6p10h~v#9nEHTqeVdVdGw6A*01e|yEL<0@VYCqmDiW||r&4fcn@ z68*w5@7Rg%Vs~8_rNoXX=Ju|kev|>{e!*hBNM#6>^mFaEmSvWNW%ohic2SheTFc$b z526Ybcz5(VVw>rmHJBb+n5fD&GEC=3>OoEo(R7@_7BN;7IPsjJ_nSdC&HizSuTdK; zfmn0#XbsV*U0{>xu=W9$6on{W<#7kAoP_mrmMQk-O|6pGs@9sOR&XFw3untOCqxXe zciD1Z3JwfQe|`af2=4(QT1vz+?G$V`qe=*8-|W7htfxHY*(Wy)5Jh_0xcArx`yf@o zEPyr650Jc!$T8wgN=av`cnNisdb}4f7vIce2BO=<>y)8VLT_o}07Lt(@2IA1AL9Vv z!2^js-9sSH9#7jpjwt0Fd-gHeF)u;DnWBf`0(d0vBH2E4v9eQV4>Q~0du8RLb~wwf zasX366xl6biCA}`4I?0-jE~H3+u@Mc!T$>14DpEHe{nDJ9wL}!xU~lWFy=d{5oLuC z|LnHU^<|SAT;(>GifJ#T;BO3V4&f17HaIaZIi&axoqP5@2Zx4)(xqN^j}f-@fNcj} zr4r*9$62Rd!2*I#qD*KBwv~~zo^i_VHjRV6mJBuG5E6aIJL9f+!I|e|Par}(kytaX z^BP)rSNkkZQWo_4`LA(N+rE{yr-5_8rYghW0Fl|yl3;Rq0Lm~f#m0=Q^ex8?^07dn zDzQm5@VIAJOogUu&sU;<Lygd@iGUP3!t?vx(Z+4&)`4Hj$lRyO9|h6aZIGD#VgiNt zqym@T)*E8kP(0#oao?r};my6?UrX00)5&rE$(ZNkX&hS;=#q3`W_esuv0cG8L5slW zOP^g32oa_xPgAila_!kocu-N!B0g;`7Hgcm|A0B{+E36q@hkdwklk+XzUfiR?IrI< zv+vLYL*3|K7dL(htszcG4UDfX4^67LH^PdDCj|VWAsNT&xayE=OCsEGhoH$qP)s9H zai#1r<P5@WSUeWBuD#7C)!eUSbTeT8NZu9}8F2cWA5gchy#ppi>mxFt4E7dtd=x+3 zz>C(u>k%Z>sUB2<XHZ{$9HT!v=Ktp56w}QxUbw0C7X}&JcNJQppzwhis~Pu@ob{W` znKsWSp&hTE-}s!DEGg|rhtU(6(7QWCjMgAJE#$?l`tEK{KCPSFj`0E;R&edeXX4+< zebjyPzmu5~S4;2ge^H(93AD*{09cLMPI7$KSi+#ELgkTA)|L18Vy#4LdcT-=YOsPa z@nV5u*uv23)0=%c$WLRGtzsN-=vOA=6Ig0gwjJmh+Z?4caQ1NX(c#-e^+S^-3J>Ik zuzL)~@2l;S6R5&W+{Q`G?R&DE_RDD6@K4D}H9oM(^Bc2d=+NpGduY^F9IK(_A|KxG zV%Ju4M%=K#2AX&)<gp!G3{ymk6Yk3m?K8TI2BgI!>`#4M1M`6#lOdf#%NqNTy`O&J zs(?bjIG7aW+sBKm%nzeDW8l968I&33J2`u<2!(n>3yR=hg<=CL@_A{~^cFo)5*7KR zz%TYr*GQ@c;Fmghu3digh8MR#<FGQVwB7=erABOIx8EY0It79IH#bPa!VrkJHGLA~ z;b+7OE2UY9vJCXO6<3pKyh0$vXz9F$?CrO552Pub`13N*$4T$OoHuX8itkG)PHv-Q zfRWt}k)Dqx4f#Izs1{thfxf%sWm~p$ItGkzy(y5XpNuaazjDDn@4a}Dq3!Pj`CDSi zAyx%z%MZwy5ha-EH+YIp)(8R|$FlT(r-xEJ=!5@q9xBGs&mjtqkUS<-*Yt&~Ylc`S zAws=hqLqJ?ro1Z-fwuc6;Mq_Smj__Bt+UPBZ8iyCatHlfmSN75BYX&B=unx!gC6HL z_2SjQ@ymR<iYjLgzP5T=KZ&Ck<TxXFyt;YIL#=|-D)*R!#iv3c%Z4@$U&ztxIUSeZ z!&Qs>xKSJzZG9)jAV;M<GdsY8iZK%Qw}o2yETSv9yX*~UHDg7h4Q|XGkQUN+?3H}h z@|NR_c{gLl4(LY$+0BOixV`yBjp;R6a};H+Uc4L_gP=sXP(TnWvk(O5taH06q5X1D zbWiMq*41tvkNBs8xKOGqQ_^xn&~}vJkGl5JD^FukJ9o9&N%p>I)sY^Yn8wQm&kS5o zc=E*etLwvN+7T`DrOf_)@Xoo@B%Y-$2W~EeookNsku22PTJVaz^{O#pzz3XV%5;0k zf7kbo+&&FLSD`UE-@0bUChNM-!j*cA%d=hGxe1kjl^@$(^%D3m(?8*7IHmpow{dLQ z!I>|-8E)uzm9Lb;&iB190_rTC4MfC0@b!02mel-eurwFY3Vwe5<~=uN%r%nVzCoyN z3iPm2gS3>1_zyODT)XPqxZ^F3nDzUJ1Yz_?G?ti1B-Ci=TqJ|pM3EOglnL}$dk+C+ zy6gV-dq+#}Ybl>@#5!2iBb04Q39Pan6(1csB4xF{52cA9vHZF1IJlO;_VRrWOSkJi z?zq$YdPR_bIL9}4-eZAGn>Y_l?=f}drd8%q9bF^kZg9LsNre#TCZRtnZO^^~vBJPs z(T5;!KUb6b%P(~lW^M;@sV<z<^thTA*<pb_JC7w{9F6X=Q>6{i<E<$O(8oW6In|^! zL9nF~98fk|aSD7F*-5Fw)B1fzqY^yV(HaHj^qB&huLv5E%2OE-asw>jC{a&x`tSU0 zJde3A1>iy|Wc!JyEWW@tMkb%o5C)<^0Igrt<Gf%izT<oDY_w1&@N6JD>W*dyWas=p z7yr57xEM{rvG_CaI8(uqIE`uibvqwhz?2U6g)@BrrlVSOKY3V29Es)BZd!2EjQDtX zz8(%EfRt(aVVCCPt%|7Zg54hn)#hM8ou?e@=SjByc^~*myuY$-xo^6Crh~n!lfk0P z)~G6<Vo{U1%M7f5)3EQ(I45^dGtrz^2kJ9B719?$Y@${yx4LeIX?QC2rLGK9Hw1p! z2fPn&M^p8Aq>D3XTK26xK-p;wzgKxN6it07oIcoRxJ}O?71ltJJvEco-k4RfFIH^X zhNAuf>$o-_WIh10`j8F`EOs~dKq6f*#M?{Np2Ht#J_Mu@rEPzrKzy@XLhizknZ=(P z9hE-RY>MbQ#-A(BRBylx<wccoh=abkaTy?2Ib_?g|HLruwhO2Mhr8d#HHx=O3hBec zEIUs??P7*!RBmw2=ZRE3eOX2~`u>lk^KfVTecNy%MwJ>>t2JAttu1PAMO&+_s+zG? zZE8zIwMFgPGpO3c-Xyha*50FtAa-oRoA2+<Kak`&lH>C{_kCUG$tu??_B%O+toi13 z=H#v~9HxKjD;n%)=>K*Q>znejpZZ<42#LMt`>@+)LR^ao28~sat^5jJEsx!1szOpx z_r+|QO9?;W47<=Akg|EAq-u3^=0xlduzB<I@>mf4!%z+xfY-Dw)l^vP0Mnj)hO}D_ z<wIVr6o3`<enPt56X*h~Oy>2MueFZR)GriW8keg;zK)W4M<<+5CtZGBx#<VR7PX=H zqbP3SB%PD=@)TlEgR35%zfQzs8gu`%EM7>J#Obi{oOA1Hpm2x80^3t&9zMIq9VRAX zxozVrH?Eqrdx0}!vU#BkF~{YPOCFRgM$8^i{C=80<RvZFa;q}Vxiqu;Q+)Hmm+s}y z$b8|KeyP9$q~83_a5U@O&-@MLL$5=fL+U-5-936&NoE!jZb{o@Xm9f5Xvu0ZjsgM! z_-dLj$(g%;pd8Z#7ceInbZM0)nhCdZuE8{Hgv6MW>?p1DTkk*w9s~ACPdunx!xSVz zE^eZAfp0f0g$U=comF1*X#BD|;mn(Pk#2GA9dRbJv+|Cv4zE$Ge5tPRAd_TYb%A~e zzyKxl<ylZx`IPWL&N9pY(mO(fZI6z^x`WyI4=!He3#o1DnNCUy=u^{mOx#DqO42Wo zMi^L+wC|3poV9Rj)o!uYqBa)x217!2AVkNo1Z7itJ?K~mSWUX%MFKt`dP-L7gkqu( zr{W%B5SQ!*O_?a@l75w6@za{_TH7?H9u6sEWF7rQ;_~q$2WTH-)R+5&(|b8j_5WD6 z%s`{G;X#guE|u2WR=c#DJF?crD_s-9U-^3lhVNvV8qk_`%H&-6^y~m2QP-i0uaZQ| zFAanzw?gi7UGS3~?|;X5n1CE#9`~t$R_{xuy=ohT^co!}I)_w`HI!H=!n6aeS2%5g z57J1Vq<U?)r8}p+M%OArL%d#S1}?YFIVnum?F`vuRrOYQU`(QLjkC}N7xL#xQT^+E zSEGWXL3U4fv=z5yOYS*tHT7IyJiT;j&3FezrQ0-0q1%e57`nZT=b}nlNTp4V?3e2P zVTjS-Nldaw*dG5DzcBjwTJ4L(^S+#ZCaNxXo3T2%V7+0eW-LU|XqUA4S71JZZ($sP zGL=&78}s<grg`uN8wPs;wTa@~PfT8@I!g2~FYZ?|iHo=ey%n}QJW6_3-c|`hw8w&* zF3<|Ir+d0Pibp%g?dX4t1lXw<6}-u^XehRgS~(<z)otcLp}&fzqp7vSlXDsd*k48( z{DkrDwc16rn{}QAU$p*CyJ$+T=k;CG0f(cL0^hKH*nB#IvwiK$LnsEjs!_V4G>9}T zSKNOY;AP3nx0hM}?ZVP;Yyez{X^(?k(91f$4BjSobd5yW7-bdCoUCxT31;$Damu9l z<4;>Ptp_b^-!dKCXwu)Bm3)mnH1bkPH;ItzA^~KI)Sv8A!kvgrw$S9?reI*0OITCK znU5mF{Ee;AZVH_$UD_!dTFyPnJ>_)UXs1x#hz+2;p9*K9x*mFx`7x#IG$MaVyZ+Ov z9L9^fBRVdCm-)H>)*x$ZH#%cZP=OXruS=4-E=tbh?SMXf2KlQ6M!N}nCfv<iNb)&+ zZ&L8Z=kN%3+SZ+>%D6(6C&gGk7J*mDZ0-LZ)UClL#?vZwGw5DJq+Zr2P?gIWGofY> zCYyuUV`O^#opYINfh(g@s_$}sR8|}Ov|92S*29t`s;7?Tqkif!8pHjUZ}rC1NTRsy zZEZL_c50$D9mv3|rR*5SjSNl>>sxlFYg&fwQ$M5C5U!+<8<gJy>F$dUq4TdBq_(fu z;OkDiR9Bi5B4b+TA+P(njuLIroSP^Ot>pEq@4_=G15+q-OI@KkmHC6D=M+NLAfdOL z{xP=Z(KZqkjm2+~LIJPogZ1A;lU3=s0}I?Iy}<{p;{#ZtMeh?pg>l`YG5$&8Tz)F` zI}0b4oXUfLlODEFTa6|2XQ%a(lbKJ!`+nXE+LOL5cYZGLZu#pE?3N0{bEdC^U9I7z zvVNOj3rXBbxu@d&(#?OHlcvajgwIz-b&!t?J=-L?N5<uP_tY^qEq$rLr5&ukkdphx zx=Vm&>DV|@5M1wY#+!u<YlVz$Ln-U}DTEWw)7-f{GN?HuwhsjlCvrJw-=CCxmsYs- z>_~Is$P53Km@_O&#i^hw*<|6zV&?OLAT>twni-+3wck$&K8Yydy9UYwzETB$bs3j@ zQvS?%qz<*D;yqty1@}VR?z_%n(#vVM6htx^^6ERn4}}E>`A09<?JF`(MEtOU$nT=2 zc`T^WMR1qXp}MkSb6ly$p?Wq-2;%L}h<`rZ$WMtXx>^3%(ogr0iAkZ(=WWmJ3oVKd z@#Flrv<$jDY{J;rO8TDNEjJT~HT(KA!~IfZuH(+{o!9Ig`R3|I1E%i(4OG;iotpUa zu<1PgApWWebukx+x5zpXzCM8HDB&Brv6U~>2TuFJ=?p>w6#T0Q;X*C{Eibt~)|>dD ze3?RjjwP?1+eQeMsqM+hgnzT1S068$+iT=dwp4PxqNJ2c(04x0#D^EZ+_#Nf28yt& z)O=qrGMZN6vW$2y8%Pu~Z}SWve=#nTZI!*d<)C+|XH0Qx{`|yxT4Oe1Im7$=uS*#_ z4+7=|J4)MDZ#-uqJUMEFT1nKy|FRCrI)^2azOar#Q&D;g>fRbibzR^aNH#BgMMVEZ ztd_r~gF0>8fDz!Gh_~-KAnTDJUdIO64z_ErUaJ#|&I?cdEnY0<Dh^Oc6yH?xWR-<Z z`!x2(u(}ppGbKb1BmZ0^NsUl%tLD)`CC^j*7;+Yg?_kUo_yocX+~aTU^+0Rvdo&BH z(_Z=dk?+s%nIBK3oGv?h0YcbB$fLynUWL*>SPrkHe8zCgmFTqeKW`I!k)1xK$kV4p zOqM5uOhUv(<f)Vpzq(#uHjA_$I+HZ&16BP}_viBv1MYT(4&%*Qq&8m0Wa%N6=!Wgn zk{|Y+`1ycY-fhHts&WyjwKI|EAY>S+ATEEvvr`5<+ru~($oQ~c1kOp3)$n{#oAu-D zy~%N{{NfS_>w`_1iK8NtEH-f#{2BTo@|`qnz^Ixm^w!5?t9h6`$sI2%a%X1OoSOht z(YHZUfRyL<gOa~WF$_zB221SC-+!c%Tn8t1S!5Cln8Yo1GG>enzG}j?^c^xqfFHiK ze!bOR_@&34jcPH6!%K-@e<rHP-Gqdyw~BlW4^e|pG+v>;rzn)1HunfQ5m3dDp|ohz zwP3k5d*;A(gQ%o8=5^!edWj|72@kEBDP0HgNC_NdXylDP5HNfAz!&(AcTYw!hVQ~j z|AR(l77E`7SvTI?<yei9M7aiTV9L6+*6@{Qyo8JUD5Ix3#VngitZOYKfse35{sQ?K zFS5Rfg}xl|i$vw4gexO<7Dq|B&9p>RvcfcL#g|$*5i6BHgSMNfr^t0G`Xu()t`&rV z543-aMTQ9^+qXr1seh1;i2M2#YdY=030BR@zfL8k)%JeBoyo!jzhq4l{GF=PPJ;9F z1(U#u2=i1-ZC&)SL6Mt&EU=?Bqtcy%OAlWzCO7fofh*4X!T)HeJj=#%J<PKIE38by zO<a^Zge(t?DrTKQf5Ya#>6copv|MHMt)U}UpIY!8q<(B#Of`!tjy(7h)i+?0<cY_$ z6>a_sG0-8r{bcdyQblbuK0b)No{xHGU#*7;bdIhga(1r75ux2&erX0dAwgKyjrQvx zDUiwX%|KP^SD8wmzKTMZ#PkMkD2y=k=|M#qL7R4W%{e!VXH%|ZCk%f5Asbpojs)ft zp(1ng%T!4Zhz4!e@@@d-RwW-fT0R{k+0p+DyyRKQ{07`*qP^ji#IBQn=>33Lmwt6_ ziIvz{@(_SeJ}?`PSO*V$in_WNs6Zr+5D1S&{yq+l;|el8p4OIkL30q^a_&_8G)(^y zUW1;}>_5a5jh&}`w7q<WwBiXBcIWr!QuudYe#x%6zZ*^OAHcCkbW7GJ-0PIs|2jqU z3^j?7>*O#-bA#2<6ai?mrQ1mjtT~H&44D+Zh||wL3_hQ^>)@x?p>{qjQ@4pmO0G~_ z4_WQ=MZQ)Md`;(&67}I%6)BW!D!od)NH*W`(l5Z)3tx+mC4Zz>E=cyANETMye%KU< z0oTE%(F)UtL^MAS@dG}3ftk~6K?u2gB$Z13DcxX>(?5+AVGy%eiLP4QWNmF9=hPRi zq!2t)Hb(ip84{ey<O{a?*j;4sj_)zsn~A?DRQ9&Rpw>H+ouV!aX)e9moRC_UFQfRF z@Gp4Qd;-0o;Q8pcN6NM4-Y}djJKK>7jg(dA@lMU!SuO@Y2g|+*clX5drS01g#qiJb z3n;!JCz2+=x1?<!8y|ERHG4I{?ZSz$tns!)x4ChIzu=TEd*CDwD3p@gv!c!{4DuZ3 zZ$8~>76dZ^w>+Za#orG!A`7S+$g%)sh1l@gGW$bLV>e?mo}e8wJQE$bqWNQ*Z}x17 zwI09>5|r~IluZ-Q=ReWZe3WMb=Jp*Xuj|U3>c{;yPUx?yH0KaBLas&1)~s?mu}+2$ zF%O{049hvhPL7|9O9U=t-scKvWuGS1iMRRPQydtJ>Z^4y-2H)3;vIEX<p#6fxA`3^ zY}uGZrnU1iGfWhicZ}VB32yUm{6+AED~Ujoz7(RC?3Ws?$*<QbE&`h_=$<VqrbZxu z9M)~gQo)vY*A+(jv|*bakGbVuFev(vJ)<pt&tTwN6?FkU!fNSbzVY3`Z6bSk!zWR= z20onY^NbSZ|H%&V-F(B{n_>UI5qSEToqDsLd5L(29Fd%vp9$16@+GWMeDDJ9WK8XE z-TzJbVc1RVjdQOIw+WbG?MUpT;rvgE4eHxhX8z3B5eW<TA+h@15oTkw$a%6t0sGU_ zL$N)Lg*&<=*y-ia=C{3T4&%MlbZgbRHWPG|@aajkuOc&bc|a-q<~1L{DrHuK_ovr{ z?AuB2eS!d;Q6lfLX<0)m=<-($g$@eO16i|OBFU_$geTpvTG;SQ0qkCMlx_i<<T?Rg zgca^^2G#2wcCz@$_z9d#JagH5cF46S8tqP>bIo<m>kXn+BTi66*0gQW$)XP|ZO`bR zsS;5j)@+^1ByrLn{_el?;3wjG7b?-=FfDK`AN89|;0K7v27hox#>iy2Te2XZX{I#I z4=Qvs{g3XYOp(rZ5-v!ySFKgs!OgCJW1q84Cz4m%Z}!FWr@l5A*lXP+yfn>Pe_{|m zqAclz^PMM#>_wHa1g32}_KUdXqvoQ&$U1k~>e0H?NjuN%Cp#C-=AGN`o^Iy}!kw;6 zmPTCMomPJC_&D7?<#LddG^Fh%_j*lJ5HEOwf~p70X!RETKKoo!aqUUF>IQ0@p&%K< zBkywEZP}GF`*GZCU>0!5v6CX7JML}mL_%->k2AHu&u05baMr%B#GWMS;Q-uL4PTEt ze-xc!Digtg%4)rN0lzohc0R@Q!MHXmiRo%K57L|L!gwQ%n#z;VfMtVQPVQzu0Kt?A zYQRy~*MO-17H9R>+XSoB-_2U6N+slo#e%?1aY})1ml$whYLG&0|Do@8j3zo@jh{(> zWRWO<utXV+3+rp)^}RAg^07xgA4JL+T2iDDeOAdyDSkGrYufU~V{%E8obEe|tCtLj z&IV_Q|0{$!taX;cs}l}%4I-}3YI$p=s#^S449x?i&Y1NqRen4cxgYU~S8bnagq6Pi zm&erVqJ0zRy%aiTtPOA0B283g`iYZ~I!ZfX?=I?>y`PZ5z^mQV=?~IYUnpKL3lCb} z1F+d%zKBH#%XSxJC!NX7aL3Eqb7h=;TCTOb$~$cgDEsevWs)><Mdm=E+sKg%YV#g> zkp`>ZP{SSl^OZ%7MzxqYfPG(CHJ5ypuc;lF6<wdkZQ<WfZXP#2ZhTcXx!CzQb%pAy z%O>b`q42X>HClvJ!ZuTRI~)sFzBJ-kaNYQ(0iQjqZ3MB5*xgLO?d{Iznkej^n*1Aj z!!nw~MOpkl`TX(ph@h5``(?kHu5SK>Hh?PlPL(WL!i~^{rxMi-PJ;3_Hm_Rp0lu+` z0v9lZbt`j3wC`84_H!*zZXDHs{Bc9<A+RzD7%yBFv;1={tv)5qP~`4I1M|$*Jyx#$ zpu$X`>aDR%`>a~=a|d+daTp~Ws?xJe;!s3{CvLrZ0v;moQj1H6aJ?)=iSE%bOOp<| zMN#fatB|ANea)2A$(5kyPUTOeTVl6CbhC%7AjNQn)%$xKikSO*3>?@ru1p5h(mOg@ zeEf|dik}>)p!I}x1vB`b3uXs$xe6HcSv>9Er8O_%UQ`{};_L|QRCq9Os%U#JXZ5pF zo51%AehXUzR(PWrV8edN=dMrL8vIybW$g1X5o_K(N_`O4pCd4Ov3zp2;+NVus14a0 zxY-qWaQ5j+M&PipcSM&*>AKo3nTgc-j&H$z^YfDIYksOd=?&)OGI)c&98w!_RFs^9 zE4gO^-23-EB`?~6;5B#Af8X4ue9f=X=ohN;d>j<>R9kxSxZqI0xah9PKjUrYuL76z zGRb4mkg@%vt;dVPzJf>Pm85y+OQbCCq9QP`n*bY}Myhqhhtz-B^;blTh3Y_%>(0so zF;p_i!R&?3L>tj&j(Zd*=b3`Z?hI*clRNi(dj_BZ_`engM`UC?p~~CNIZ9BI)i!s_ zorB|Zgj`$g6{ioQZ*k3fz{)741}XjqTbqlb&YTHE_GB$ekC9c^F=$#JYx%<e7{C2K z{mCP2ymLt9;D`HyVBfcO1{M8#nRRsrDfp&Mw@jLjM|TZiQ5<-b!H!*v%4docS>Z1p zwr={3u#(EEN@^AxAgB@zDInqX!|T)kRbYRWbkYhbrvY!<ORL7DA{9rK3|w@YS6DGT zUmj9=v`A9aU!ZBA8HM;HpN^D=^2=J0`_j0wLBJW%YFR6WL21LIKBka2J$Ybgx^3*t zxGh;BrB2u}vcc3aQ+E37I?k==&LAi$7jvF#s%5`>7lZOPbtz8uw;qpK9yqJJZ%B4o zCK6Nlu@xV+&sG@c@bbThn9gnaKcjNSZd_xlfc*b%Sk|M&35eIopG|89mhVlTFY8w7 znYPZ1YOV0*1uenR&ccrQ566?a%ctv&cGq7g98Z-HMnCiQFxHqD1qxfRB-D&%G5_j` z63&!^(%%8KUkndXDp9YG@{!lOh}vC-UCEr=AJT;m?Hj5r8LE6kcasg#>TSPzSQ~G9 z@R*-(Xjy-7k=^f+`Q(xdE&pK&_50{vU!5!Bsy6l!f2N&+fnX#~AVS<!Ho+n3V_2{P zasjo%E~I)Wx~rZ9hk)u5qfR<#Rsvi4X9K94+i~e2-=6^n3bz7V&xWGE*8RSv7=!%I zsdUIQbilC(w38y;<t+SzSd;=So*phJ%KNG3%PGJgbVUSN^e^eOEx|gHDMMW}81nqm zVbN+z${c7@n=b8ueWt<oCvV9`GDUQKJ=U&ES_Y|=8VhOb%>m=8!6}G0=!^bGlL0yl zyKlQ(^oKHwKFKj&$lLrAPBWux6mv;gu_w|S7Y`gO9y7n}LxZN>&x)P%*+JWG>5>iA zP1_D@=4#tSd$H#{)VwKT@3vtT2X1P&PI_<?Sh5m+mE{E;lpWVF1a-|;QQW%_CV5xz zZ3a1#@3L)|D(XnV2(PQXd^bzvK}#L+qp*Vl!p4Uv{p}NnG9|~|IKsCh0ldLTMS5Pu zveT*T^qahIa%+n@KTrm$yRB9<L4U<uohZ44do=^4F5bv(mBT_ohj@bTJWP;0V)hI; zG|c(<!OA!2xA;rED5{dvrc`P8ubbKHM6K1#6`x}P5+my!KUMwX;7{*eiXQTAZ{mC9 zP@M0qdG`c#5Z1r(Hc^U0X|&cl@<l9*&|Z+m<()mFSmxwxv7x6Lre*+Trk>K96Q*X_ z^1X9M<pS#nHNxAlRwuyq5686-Ij9dF5bo$CcaXB#@=Ga2?b~;8`VdN=U7W`Phdhb7 zQnZ37x`oy<TCg?<dfY+d<1gDJxdW)`i@V-62&LrfLO%n|=YP>6=10IQ&Dxmb;t{M< zRX^<A#N70RjdK$Jl%{v3%!|um@q9kU0Z^MZ?L_gZ*U<g^*p!x0kB=@@$3Bd#&rJ*> z{y<+N!JRsroQj?!VF{tTd!DT$8`-g+lp1wp>^0gL7^sX};XAqbaAM5&?HDDeniD`) zM)8Lo^JHR1JkgR@VZ$f*^=J3K^?`I$joCf)Ej?R@k3aceDVPLBjrQv<q&LW0EZ}T} z6k30>&ee4$68GT46#E`#Owr1RG{S1p0OZKZ4IjnEo`*}JNT6%a4PxLgUT{eX91U6f zcn6%Ud(`<{ih`V<C{|m=vx<yC#Z|>X<kVASB%ja7G&z&kiz`{dQK2b|s!P=QEJWg7 z)v181up~bIiUaMS9^Iep`t%p_#5YY+Z*h8A-PzVH7SDm)uPoEJA@>}uDj+o0^~e_e z>{`3m)Wke5j^n}Sv9DZo85Rarr5%{<&9SyWE`EiJe2Jr)hI4OKV}A*qJok744Ktns z?%NEC0f+<=DN>s06*J-{1gJ1HzwAZ4<Lv;<vWH61PFt?Pn7K}NG>mQCwO#Mv-ocYl z;qL~%>>cx#Z5~`OzDz7D-F3t11G^w$@bZ1SkK`wXty1?ydoMH87<kdif0|LM^Mi+K zMjvutN~GkrNiRWTRip>jGi?KOXH`Ea{citE)wD74b%jL4MJzKPXT0VA_TNL_yU$(B z_P%Oz@LELG;dj)69%X}F+}`&go$s2@>+^P(FO*S<JKguZ_~T&l&X^3|_&o2{B&l+E zOZ|7IXw9w<XMV+Ix@AvdeluoO3;93(h+52HGJ(%azzQN$^?@6C2`lQ-C)ZE529RfS zMX*$91xStgaOG-)1!b0TnK|2OBB19!)F5GZFham#0IQ6Vvr&wGN!8?G8lufV!<l>V zy6`T3u-X+dJs6PpQEb=%_?<5j>ma7ps7?5od^5Ku1u?qvd}2?t>N}pthLujL^zPzt z{Rqr@uo)ve^I|x_Y8GM9E7VK!YKwJ8e@CjgXt(+!2OUQ1sFU!q`%)G>gOMGyvr*dI z^04{c*y9W}z)<w}(~Ocd-4FzSJ!L#A%G11><u9GKrVK5;*_-ec|5+e~w&nZoFR=5Y zc^9#K`QIacZ)_&$?a>YW6)Rr~<sX%Mj0%6#1e#-3y87=~9oHqraq^i48k&c^xF#h# z7AgIUS3$YkFT~!Vcuz)#|4#Wn<1X9_tlD;;*nv7XnB#OK?<w4g`w}a!K;P0EFCrw_ zc>APyitPM6z`6g~H9M|9#ZcY*&^I#`F_JxWVlA{Z?~H^<1o9Z2ecHGz4uG<ljh@8y zmSY!EjnX8M;*?o>zZyOybuz(C3C*@R)!E%?iqKls8oGDnW_?B%5jrw%b5X=IY4$VD zXPiYE|36{5^~<=o#AAh9mnde}d8dei*cE0yV>Tbj4BW8xz{&^SB0y-;n~n*+GP6nD zpFHH(wQJ%@2u2Cw44<aoe_|X0l)MXsFtsAIZE!f0ydPQuI!xj9lXjYfT(sQih3C<z zH+<4pPwrMa)|Q6f>DT$PGRDkb2v@Y(_5c{-e|q-@$6w?r?7X2UoA$Nl6}oK5hCIqd z(BkW&;hM(~?7(WD%$ZbSiP7!uX$(RQquZl^<=%g&K*Xu)Hc+wb-wrfchsg1eFEi39 zu5j=3gtng6#AJQjym(Ff>M{{o4yfmc1~F}-#J;o6#Z8J>s8gp$fjCq^Q)Se=UNwil z6CBLctGsmb!^VDP;wck$9?(a@g{C&ub%5Mr5~apJOPQtJ)vh!{Gn(|Oa`9CZ124CR zIu*Z?9l2+Cq$0j>PVN|${hGji%rI&+ccD7<lfy}40M8t%ge>})#wV@@T|Pjn$o-I` zpR<0!Uef^6D-+EU^ikh#$!9naK0jO(qS_o!ynZwpI4+eoA~YKC8b!e<!8uVI;;v-z z_s6v>*_8j+i!Yb3Vw}qeps~`^+7$JwbBe8YwY?ZV<B70}0%6u61N|lzVNl5mVdF07 z;`+&73zPV9W2Oj1c{b+>)!@M9X~yLNW(4*-kx~v<*9&Y1J1GA6`k9H0?rRjRi`1Q| z=0SBe0#o8R!aZx6%5BJ0tMM)!*%L3{pFU|vDe{i>*hoP!6)nRcB8Suv7a(Lv!@hT0 zDS&ER(wPg`E*?7siXf5f;3mmH-FH(EFAmxWs8{xUcmUipAtMcbf$@Y3WbD4}tlxhR zNYM{N+>G!FVLV5U{7fop>3^*IE4dwi8J=nf6UZF0(UG-#9GHC7B8^J!KdSodwvs>d zSaZ`(EGHxxfWJIX^AaG+(NXhf1pUL-mo;^d;JgmkXXj}flUM2VX12+5c19iyynfrV z<BiE9As;#-6hci^$l=yZEfoG&SAl`v_ijXYt!Sd(g61_0;Q`{~SPwh#Yz-B<e>l{S zq4oSfzxva7;fnGHwl&@$%5jy|asyXG&Z5XJ4}rCio{v}dxB%{g8#gLV>wXOhsiuRK z2HeQhfHh_Pn-f@t`wfL>v}{A+Vkrhcc|cthQMhx7U#fRLjlBBb>GS>$GbC~7fADY} znL<HWT|iS8=9vntbCUS`dEZ0G$o7(@FTQnrgh5Kmv-BdT!zV2jOTVX#s4b>(pqFF< z$@rb^hJ%jB&QFRGum-?o8_ia(;k0xJ>BigI`#PpgYKp*myj*#^QhxcoCDm#jW<_!i zcqu&fjusSTrhI~>-h&2Y>4pxGD2b0U-=b9YZIfLXMH22L5t)3Dc%Jj;LT1A5vHSuo zOY+Vc;MRv4n;b+0i><(S%#)weAfL<lX%nR0^NMNBfzLc1$XYp5h%~DFu}(^QfZ|Tm z-}<E=c)$K+P|43%5H|ZT9;`GH!J{nK`GsFVs4PJ4G9I#r?Z2E3hm*O=*w!kJMQAcO zZE&>e7;cG@)$S3?(9)Lm1umbyJ{Sb<Y9ytQgj{~+-v2sDJvEYgc6TuvMke>CSdKE_ zwZTfDASX9Ku58akNiDne6Pp?lh!R6DvI3`H5}j}i2hZ#35eOm{slB-c+VFMQ&3cYm z)3!$mWaZeiADxm!f!bJSpd;#EGbi!8$6vpC-1OdL#9Fu`fC+HgTyd9WNVs>)e2}V2 zh5S??uDR~8>9QuIWa){3k>t08)(<WGY}22w=W@r(9ny#?Bl~+nS3>9}&!e6qN@{Dh z3j@#0nj#5(QEv(9lbBnM`tM3KW@SPOQBkJk9Szm5YsYrg{9>eWCtf7ho4z6pT$@GS zhCQbm4{Vk7tLz*>qJ7C|%+0QtMb`kqUEkix$&KAc@()-bRq(efHO8^(n|qKsSRJ~g zmQZN0OyNXQZi2n#LTPE}EZo~B^aJ{uT`^bS2%EpTB4+zm`G(q(+;t+w*y+QSQEIkV zG%Lk+_69KJmV-6DBqadS`l`YPR>yu)**0j?>8sy($M6*-37(a+|Ac)@h3Q;A1xN9H zO;(tUTKM3eFTnhsq9AyszL}#J@aE(vRRdG19k%irr>(pe^!VnM%38^g)1{wOpcxDu zG!2I7==P<b^-!ljDncT_*F7etj6gI$p|pqdXE>ZArD})j4e(IxXVR+N>xA=3-==4+ z(6oqkGv({oK3+T?lPmu&=fIpXyZ1T(FIxP`a8Fb2YOK}wDqb7YrShaafO7F9U*CdL z5}RP!EahaDN$j;j4+!3Y{uf<NOPl`=ArVJs7U>qEM8Vz~E34gky3R&_dN`o6WTBl1 zx9;BcZEXG&n1a>ILkh}VKQVI<wD!BTXz<6O;P{CRRi*X3>7}pl^Tyr!&qwZJzRsV& zFg@Lfd6iM}{Qs|zrjbHwx}L=D&clX579#dMH;w_DEh9?%Mn+UJcm8rJGB}R!x2K)A zdzj!cPu(cQjgatQ&q9w#gkGsBY!N4m=xd8_+c|o~?^2tipbeUnM~4e713|<QW2CT5 zau`u9{vKSfcn7LK0Oz3nJ4x6{c%LQTo^HIDMm;?OmmwAXYev2P4+xR1rLU~7e<MxE ztj#Y`>^E`zzKZ9ISPXdz{hjckgS5V*@2--Wf`SeC@hu9I)f>dp4^7Z$7k<#Khq^<z z!@GgAKG@%v;}l-C%;rk#FGtzmv3-8uQDC|D7Px=g><(y-;LD|SJC*LEI%iy=yuF4L z%Dnwl?p8@AEA>_pd?Vx6q785>Jbrw7cPQd2;Ts}GnvT7SV|6Cd=q^N`8K!ppqgpfZ z^iN@Dy{K?T+UY-gClr%=dXAAyAFY6Ai;i&KO{a>;<FZ6USr_(78aOn;M^N57;espa z2efY_>O$P^cmLzbnME~B3W0fy1>tmDDTsH|lfB8_mF<|tS(RS?Yu^Q7X;%ADx0Chh z>PtAanYN<dHnIvZDnam1KqUw!8cXO{Q(>kf6gSFg3P<qnO3!71>S{ohqHM(qV1HvZ zSINI<8#UjeZ`ZFF@z3Tx<Eg+X$9jnFAzvX%Czb|qDz;R$Yff8fow05(#s~a6)BjT+ z_ye<2(45)1q9%AoX<t#f=b_`D+u7LRvCgN5QX?#jaVFW+7g#OA)a12f3(w8`I0ZBb za040IWLDZl5Xr&hq5{S)XTxh1*c^OQ-d}nJ6Bf^Tpt+_7-fK5O*|1LA&=@LvErcne z<g22dWJVu=X;N6ph-Uf>gWZ7ZCsdQhl`2D&Zr^&FkHv=Y*bdG=xa7Y)+$0;gNtxjM z7*TYFDPhto%?WLV2Cy8^KqzjjM5W~QCfgU07ZQE1w(h#{EnYaZ`O{#0HEvWLhnjxs z=TKV&IL_k2TaKrTF|^iJUC+M!$W$Hhru+t=hF>y0ngy8y*%JFMRmSl(A8~2+?{Y*A zSCV!mQ{v876HP0#(V??&hcm26_CEyj$mcBLV8zYoxnx2C2tX7+5#%r~TKW@UE3bc# z9S%B-X6myXix-h0zQ5n0et(<Qp7(lsB((V@YP|fwyVt&iN33+;U-Fs@ORY;(tszq; z{Yi-dK&W|0^pxe`s?dVPqjR*~>6=f0<{@o1l3hFytK5tpm?IyK;Z|J&3GIuC*!ELP zS@Hy!cZq*b3FMJyqWBY{B`zY>`e>u7TS8<wV#oN)7NAAi<5dCh^d-2VLrdjP#UWGE z7D%#Uh#f7sCCY8fk_yB&bYS8${pSYXb?w;L_UjyuhrJZ7&lj!}+T%uo^h~3<^}Y$f zr(fdqHzuuk+2|ppU%3L_lF!MSYk)Vq2{l6;c876sFwNPu_uz59Ngw8h{)bHcJH|ea zL8m#VBo}BKGb?5vN>(VKxlL^!P(F~%v3INX2v2cH9LXF88Fy}{lhmF{=Lc~!Z-6NJ zSwNio>8C<_6bk?Bm!!>Bot6wUu^_s-gLG#*>SvstTHC`h^gpL`SU?)f#*L`k-wIAI zz)rN`N^pU{roYVE#jO0LDAMhKxRFyBJzAEQjx*_}J60~mGF}(7GO%wJe=tSbi#_AR ztV{kl?;}@`o-Z3ehv-}FRGy4F^*d<W_Qu^U*kGPn-mkG65BgSXU#jcQo3TP&USOqI zyr3Jx2<JDZe7ASW>$N^vo@NUh)K)Bd*wQr7?ZDpSBuV4XKLat?7&fj@e37|Q_ued4 zzKNta&06WTAVtrqU<t(mFwJb^?A821F-sF}iik9eycJg!3HyB82k9WvEMUsFW=G>H zSoip^)36Y7jKeWyWt+7h@Bdo@uk-;r$V(N}CIK5IRbUp)VzR3}x6QjY#a4*_ZF<oK zT&!&AW2MX`vg}UOiY(`jZ(hC~j?-2wEb0E~#8ql=<BLFL`2C9^ssg;>V0z4MQoJTS ze9v8e(Ea+(g*NgN$AFcDFvyGlAY}<pB2bAVp2PKH{(N~~t#IUV%-~DC={~rQunE;Y zak&b}74x!;Qbb$=m{I6m3=lJVMDxh<J7P8|Mt~wl5IiEBJSPtoTHo;aEyZAs0GuZB z%1lRry(`;~+4d9wyG?;-J(06$!u3HQ-aF~&Z0;FiH0SyWbTDP?gF3ajt{6w^7usV( z=-dg@n<2J8yWQvZAe}t6lNO^`&dt&fh>t5sNquBts#?)6z;$lRN7(K^{W1uyn!lg2 zVAEA0V~mp|<I@|#WtWcVGw1*KA%A*wWf>ib%B9@!Mf)Lp1;55oWxjjdd{%Q;pV|qv zfo-KqrOg4prpB;xZh}wgNieG7cxo#woT@0!^O)X9_2I9lN_P%`Ilar?m9>$)g^n%K zasF*fam3*#E<Dod{E+ta?Y!$Mg2+h_@x$pVN`W*2%&I~QW~^o~Z8=&Hd+DJYl*4M@ ze9%KvLjgO|Cru^OI7})fmSREQC`NPWb)wNA|3BQ^Z-r1~c+(Uahbtbv4BT0x4%M7{ z;7kG=;2-vWb97Eat4<qqT6kJ^D(ae$HuZJ=WY}TYpU!kiwJcA4OoY7N!wfVRLWwp- zDW-wu63E?$#KG}@{+6xvzuq{}R`PojWdM+qWSzjnH+b9q7cRuQo$<*Ns(8YqSyW#N z+uIj22cLY4Vjf4OAEf1tC3p}DN3f>2;_JA(e+{dzZ@f&tfh42kPhpY#$vLNyljh^V zqFVXYFZCj3A{n99q&4e{i_C+s>hI!bZ@hZ_^g`77>3Q9F-L4~Q`z%dg4s}zixff2w zd~Gk*-#C-Bn<Y4n&U6B<dlF(NZ|nKRa_&1+&yp?OE$JB=x9O-mQniVgaXL4^{B5sX zu99K(99hvyI0asyS%s5Wn~ThzfNHdHnld%hM{@$7NF!#&Tqn2NYq1aXd+4_FqS5AG z24{&^5dKQn)<;z4uNi}Q!w;$e_WIKAD$$OHzJB+?O1LM`;@+dT6Epb32b!BM;N9n; zg9fKxU11CP?u6V_P|F{ikCNMO7}o{gpUY95O0e$PbWVv}Eb<@zJOczIFoed{x{N9i zew=lX{=kl@uFt4F!9wjV5O>yRiOnWB@43~cx7qiz`NLwji`$k_x#?ei%U{WwhjWPj zd!gc*9j4R4RL<ElAn{D~ipnd<J10y5e4)r4M)`<1mwx!=j+=ZNHNEPvkjTJc=EEmF znZk_GWRfp~UwoB3iIN5{<)wq3PD}CtRV!De<@;D+^l%=k3C6N*LB+GTg4>9L%6cX; zmdQU^?>c=J`QNkhEr<*BJg+E&`tVKW{%2{EneGT{j>D<SD0%#c!`kjW!Yu0aHt#?v z2<4gB9%r6Bo~iOH1xmsLN%Qo&*v1Pf^%$(rH@7!Hxc;^YU@3tyrg(kXN&V_!^qH*9 zWtlVQH!>@3JsjA_ZrtGNG6B5D=?_^_UV4IvOd0QlYH^>_)9z8aqC>e|6ZIm33dx`B zRx&&`&(WK4-l!!`_j+icx00igN?xx{1%$-aBUtlbv|u4XCb^O>WlHYMJ`mwbb4rQS zK#}Kd?RzjqY`(b`vfuv_3xm1;mQIF@0UYUxe@LAW)?42ibHA{DOk#H?X*<I+_5Zs$ zm6y-@et8#Ro5aqfw56GP278U-HsI=Pw>Ep`ul1Zlr2lYt<@U+bzt<<tLu#Qy>bq{F z&3{^!-z@>p0b3*38$OYB^(q0s8A)g>y6K;}9597snME!{keq%x+?d}qT{3e^mE|U` z*x`>0P7=QRp_>9S__?mATDu;gBjvhdNU3RlJ_1&E2ZluCoE|*`t9BCZ3?h4(l)Mry zBwvK3lQj>$X}tMItfm`bm-0)+>hc%JWF%rYdtWA&4BV8Gt&Ab*Wj?xq?%4D!`(w0r z#PVAtfMDAeCup64NZ_MQaN#W34buyp#q{PS=E`wHJh~d;kvniq5qY7@(L@+43|cH_ zFSd0Q9`PveawAtdOxJe`KXgmiI<WD(Wwb7DI2v6iN@MVJr-(#m#&+GTmU+59!;=L@ zU^=#tKx4CjR@vHFYV%r8diT9OQwp63Z;at4v-^u((!o?e>x)De=2@<Bkt<oY{>7K& z(eh}BbVL9uCS@+NLc!&7DniocwPG5UDe~T=60t2!`n1$1#lE4rwKif)Ir2=Fb8l@& z!{$$Y$xgRe)K)X>y){Vz!_=Ej7H3%(1JPA-Mz1oZ)#;$^<}Ljx6s1VrEv{axX9kR3 zdJ{S*OZKL}aY<=zZIaCsBiQ?h>E?p#wscQb)^_N^c_%44X@J%&+tjatde0W+L;h(I zFrkjb1vcyOx(fSc6v6K#%(|$-VTK}{$x7$q@Ta%nCo!zN-eJ)c)Hl|F!O6t91kuF| zFI~4Vk7lp^hiLWvSS}A=ZwizoAUVj?wJ6_UGt8chT0ZYjFB8LN{kx<tmoxre(m7`q z2r;i4O*Q*@5*37j)os9p-^*Md8rkRja<GmSAZ8nquy0zQUt$eIuqjt#Ri~K-KU;sS zG%4<^rpEurc#L~ir`9ywm%;I0GLoS=X5r3jQ@AQ0-}|y8rBa;d3ZvK6M(PjV$LYxK zGolTn)Lot~{S{Qwrqu;!dA4d)_|e2aE=XEXLhH};V)4w(AG?S|R$fjB#PRTkI1%at zU5>9d=JML8A{%xVf2T;^`Wv)Gf*i)OxyE8od)gLym!h4bFtV&7+~g76=JT42M<4CX zbcCGatri7tpRIu%UW8u>H*twAglC4D{bN|_z6=USL(yfbO^DD;jQkR<9D55$Zjcb* zuwUV$bXjvswpZ&D!WYE%)0+s8Gw4hrS{k7N(Hfx^o7^II7OhnJ=M+e2Si|bVK&)NF zGqBtDl~)wc`quzQ^_)F6&L=mCloXvr;Epv3v&xE!b0WiY%S4An#0l&@;1w;^dA~79 zmL2Ozc-MGIn=s==alrGC5{p^iqgY1p-^P?hVvE|89#BNXW#AmokqX=-FeMjZD66Rg zF-JzX;H{5e`7>Uu%P5_Ap4Q4}72@umWP?<l(vAvA0%}TK{JSisKje<v2pyIH!^{M` z)~n~o=d0>Zt7PD=vgQ?bq%5QB(%LEGeO(DuuTX!al@&zZBpll%WHgG|NMr=chaWf2 zlnPYbGq^A&mytNqAPO!@QWb;S4y=V<)%NPv+aB)So7r8ivJKKMOJOO3pG$Ob>%$fF zkTzG%p`wkwJA`!4hU(K+Cv>F464k?q>J7eMz(AKg7^@WW!6P!;*^>5ypgFURlUz)_ zaIa51*3J>jpJElF5FH-{L5jF4Cz8J+{R(6fGq~2j(h&q=F>e6Mn;zMdnz6knc5S3< zY52^#4)bmOO)#OUnte5rQ$Gu`D5V$cVeWs>w0b$oz_Db1KUxsV5kM<{t^@%$?TVNK zwkiey9lruu<_?J`m4ppcs*<>EFH{Kvn%CcK7J}|DZN}BUsuPg*PK|;4s6rPKZq+7r zNt+Ja!@IS>y^Bk1WAFJwz4d^*PTT(ans9G{$>6>f#R{yS>^l0uTmNG8%<w{vZS&eb zVi8l5N;)ju-)`7CSOfX}Zdb!54B-O%G5Ug!Mt$Z5pY;9ARd36`8`=M#BGxJMw|`Jm zq)Q<n9Y%n*yfl?f8q?;U4>P{5hL~l*s3bmB7fjG_Y!fcr28Eqo=qaHcofM2P$HOIU zNd~`<6M<!3x9<*79qNaMgy^RKkN}Y12iAA@%LkU~jp=keuDI3QUP#mgvXh&Tnnf=x zsnVfVZtVcR5h<k1^=Lf$IbRUF7!y#$=B{=S>kp27V68^~7&|CsB|KIXG{3--2V;=e z*_foX@`vCa*kW{GivM0Y$di(95$F9ky*C!SnT1f3kA23||9$A?-Utqe<_Hgu4+AD2 ze`;Z<chAv)puoza!$+F%X|U<_mxj!--MFzoFBG>ceoBw8D9mE-NLJP-YYI&_H<(5o z+Pu2-&EYG=`NkIa!!;V>pq4}*w|PXj{*pY8H>k<Sk%8hyfJ*<;4k+ocb1E|3mbrtu z!`_YFIYzQsU`WM>JN+^Iq9H?`F4~Qu?(=C`vuXff*e(a69v#H87v+3HO*ZW6+-E`D zmq*|!IrPwWd8|2?{a+0W0+U334Ml`kZ!`xo0dMS|v}u{cUy8;(BsfO(eY*BhKO135 zQlsAF{R^8$U@vY->kbPfU1}WrPaot9KtA&qfpk<TuGcmL_4&a@unS3Fd7gWNkDLb5 z(kS~A9X2$Oo&&X2JH}7V6&|tjIV&l+lzMT#m$!I|8{q|#;%;aOQ`q}N`8n2^l|_s@ zO-B~9Pwmh;u^JG^m03nshwm6KNL}pbUsJ57QN+I$Jg(Zk@vv03&PN<nZ2$@;0&NAe z7F{gn#(;wc#*syj41{Xxw6E7O0Eaa4+wV4vCDtjBU4BJ#w6A11oLJ`j0Nwfon{!4* zkVQ3T-3xh=aBS~4f}ID)n&DNevu#lM=f};-L3fLlGSt>?)e)U(!PjDFV%t+0Lkft$ z9t3ac8Aex$`PbUSBM*LN+AOIj1R6~h_m|r1b0s{nP}kLavuYz1a|gVJ1&%YQL^jix zrfjPzE2=eS<~)M`dSY(5A7FUiAiydKFy3#nEEh+0%a03}gN6BmzgL$dp5#HP$h~7H zn#3}bMB0VL6uPh#K?=fK{}^%yr9sfE$<aWDtbjLz^xS$&ZvzHdA7bkjxh(7vo2Y%t zseUP}*a@{>rINQ^9+Q6*`E*`R;mY~O=}<`7?)kVp;{76JIx)rj4V6?1L&oXceNK_K z-l46)H|Xy1pOB`3_nD`M67ghN$-V62IxhhX{rl%gM#zyB(CjebE>U4xOZ|(;7O6J! z5cYA{spCawYCn&aDxJ2=v>N)RiJ1|t$p_Yt<Ye}mN0^ytb&RxkQ~2FoY8@~<M@!5e z1_7bu6a_AQ!mzb1;N^*r`}q;r6<ylUSX4<U_e8{xw*wzIX|yxi`u5B;^)@3vMjncc zXNsd`prT0>K4mW#9kzrz+m}7Ih!1(Dd^piQaqswt5F{^o1js>$SfO@}Lbx-yqLtUY zqunLt>9Czm%Z79)?8AMr(ChG10T;jtp2TV`h-6t)>ju$9b&3uZ1&UbZg2-<3=1*T* zY6)%0yaeogbcR%&oxT9K@S#7t(BvkaLlgSuc3A07rf<WczRhc*)&3slezh*vMP?g| zeGj{i4~CMqMIAWxk7b{>LYT$#jJ}p)qw&=osi%1TmrGeq+BeyZ$46Tl5C>5$Lb&(H zaWWyNRE7AJ(Uzxm#r9cBe;Zq8EXqzM4=)=DD<o)R8)$RtyD<)sMU@t$_UOYbLSRTX z6Lb3RsaNI>a7zE;Q&sCRrr5;)rg3W^r8|l93~;&crJ^w(UAA<bHH<hHki<xFl#o1l zX1<{qKd&P{f}ujWo8qL;854@_Fg-o?4T~N^L!?pUOiCw}BhVSp@hllj;hVsX<?G(9 z$u5^Wz*h-2s5KB|el50W->Hdq|K>}f5rp`l@CfQjpU-mAp{4YLW~aQ!C$=Y-M_R8A zpnt@`u%)cYoL!74-oQp;?`0;R;DliI?|6tcXQx+nI;$vRL*95Hi8?U*=<&`Z5+!vl zhj^UvW60*uCF@!Qt>H3lG5jzbc5rj6x(9|GqPJODNUtM&cEjLmc?qn!hpDI8;^=ws z4PC#xcRAOIjuH+!hAe<%RWOOywEFMkjlgESK{V*+&y5C3(V%CkQ=nk3j!C5xN^S-F zobMuhA?DL(I#*{i9qR~tpj$`Y3wF6zRnSkK=n=O}#8b*o@0k4b(;e?PBhiaIMmS6a zZ4zwVl`ca(hGuT+&n6%Ge_a=yGRQviXKiNg!?QdmE*Yj1otY!qG9}aiX(*@UgGJtR zK^xJ<5{~x^&S#s+epTP;9pbi|pQyQ4otJo{?yV}7{|aWxW2{{rVEy&ypQTQnEGGaF z!8fXt_juu9O2y+8a#DlZCz6<L)>YNbX~h;F@~d|=K9R}OvRAg$Ur=zqWz9RncS-!W zDya@rL@eBZ8xE*{D+5js?RDGQ*aH>%h=QaPd-cQQlmLXh*BhkWc}}hdF%u;lyw1kl zaPu<LBc0Ed2BG{(===*+`0@Adj+T^gEPJpzTGur0;nK#lMF0ZB(MsC?398VxqP9$x zw$+KqCq_WI#)b2z?IiIX#0s0WTabT>_{y7}7;!pobN<mqcUX49m^YD2XRFl@R|I*j zk5V{WBlJ2Rht>t@vN*Jy8!a09pf!e*DP6<(8c0l5?=!=re@ZsoSe`w&Cr38dHJ={5 zZrn`Y0$AP+r&wi&FMEkzTvwf3S0vuCL-3vcDd2g*xp;DZ-g?raXG(mjR@FE<g{cel z`OsU^SsDuCYz(PHIie>m<wI)(qA^E)0v(k-?S6vD?shS=87o5$WQclb1zk8xS0zhV z4t={Abq>8M_$jrv0r53yZ0gdmfWxh<sJ>ghij7T)jipbC^*xwt)K7>ets9g+d$1hF zml^7_d~Y%2c2A(rbhm`DV;pcUA1z%w`godr%B04HMtMl@p5~3Rr!2GByH)-Ri@6hs zAC@5Px5=|#&tYXX#WY`rfP2#D8FK16Q4}cQBniglzhHt3ky!GFMu_xToZN3)?&itu z@&JuOs-Mdgk6ZcjlP4(%(^5K|x7?{qmBZeP1k}#wF>Ct1k)~FK(jEC<!=aU&=rQ@l z&6_@l{F8sdheE770W7W|!jKGBJ)vo#XT>KoXPz$iJPLPZ91F(n<o;eX&3Gf+eCeAa z<pi^3&DD$$i>*Ri@8VeQ0@K2~sM^T3Oh2(muFwEx6mVBlRUDNMRQ<+^Cf5#3S3d04 zL*%&YbqFi2nv^OO)h1p$-ZmGv{vpmq!t0JW7Ej;CafY#>cxGNd=Uno31nTrf`P~+X zLQ_(LhJP#eFey1rUa@-aF__Yn)Eq4q1lKu%$R&?H{qucQ!0zKTsX6AJ+jGcl8gwCJ zK5KVr-z4NH&6U+%{3S#_<v2;aACVfgslVo36*x{i7*8;Je~A0&J*!MRyPN%UZtY^0 zhNC`^Ig-NpemTi@`?p{U-+)729Q4@Cl4Ny&|BJ6F*WI8U>0tl2*2fWdJeqp<{?wF^ zI6P^`E(qwbI+p(?=ed}WENcLrZl_EurT{7RY|-($BoAM!<zTeZ9ro*fn5#_O;Jv+> z!rboG?HA*D`FEKrCi-I&+drD|zy{VfHj2li0dmrnprd;#%N4~Dl|6?(@vmi``+58M zpAQ#=yjE{mwU*<T?3H3*wTb;Y{^;kH?FQ|VsX)T1l*{|tz?<wV-<wO0<{78%7%n_a z95EXJ;HaJk#t0S~dc(|km@AiZE68S8!?cy`?{VqNyg?08nYa9zixaJPxpR-DxJ0Qu z4=|BdQt3{8#^{Dkh~^At+{u`CrMqug%fCC#PPhc5l>jcLt#2jc|8X5Bv&b+%Z7Lus z^!#>I1j~(!{d-v_?w4OOXX;G)@)9&-H_aRLsViQ3?|Zw>SK#F!h9#dkmtQ3{p1|^T z(6LefSbBIPb4}y7EIP37Xk#dd5~70~Kdc*wkY+8H2i3bgMqk9AJPJCMMz_py{j8*a zXXmbar@e{vM%(9od5X61o91(*wUc1Zw->QAA0{uX%raB{8E68atrZ_aoQLjqX*28z z-Xla2U=O^KVIP{2ksDZ+0Sa#u33-T5e~X-inD?xV@aC90v`YioH1e~_(QM9hW!I<f zoTey*`;dP7zAPjA*5g+6@egWh_zolrrd1P;<Zt89eQ%=pf(l)XY&qLI_98PnZ&uut zzI_Zuy;llU(CT|_BP1U%_uIDH()W0@i!1ZEUy5Gf=B3c$;$`NP9>R26fNe@hldE{I zxpE$s`%A7uLm212m$eW*+YFJ+@}GO72+<S;KNS~6)J8gJ1734}+g4clDm~b_Ag@*n zz-JukEdG+WQZ?zQv3B4M$_u_@N(@Jw5yWow%=oK0eZqruF4$e&Y;JzQQ3$ET9G@l5 zx7xIy{*yUfwOl{hf2mD<Pzw^)rg+$Y_9BkGdvIUd>+ZGbu{DRd2y3?~+GA9)mc6{9 zLmy-j-{;6YEQMr<!~-S+)b2){NF8$4TFbct*P!q#?Q`AlQphJsM#}0&(w<xa1&^fu z56D0_zv6<?J&O;=M8v=<D@@3k+*g22)>wt~O*U8u_N%{VILvLpHggrjo~gK4MpPoz z_Zfvo#;~3Mg0zUE<{21=&ic9AC2N;x(1=%T%xiozs|>yVO?D=3kS5BGH!R~%zj^0! z5i&ZHydEo^Xyd-{m`AnEFDEVb(KKHhWt5IG!pcVJCNs4mILauaT>R2EW#}lwPW&%- zNk$cnGD_zK`w+4l0ol=#mbA<AGrMmAzWjj5PT0-FTeI_C?JXD9!_M^{u>;mHyMXm; z_6K$?<aRi}Kzd!a%m=dFa??t-KG%MK8?$o`P^|)LMNyBE8Ane^oBR3gVnZVb5YH83 zjzk_LNY39lJ9-da4n9Hxr?`a((zkghJqqb2XM=U%Eaw1tgAdsTwiOfjSp|olGDQL> zIm-$4o;h$rZB0+r=WSK;dC@Pn6cbPmh@P`fxnZ)(J~n_A#T+k*m;fK8=Mcbsoa1V; zl({yav{@wK&E9)jZNTJuov_9}N(P|=9O61MAaz#8Gpe7<nr&oyU160hL%;+$#!21> zqylcA;Uphu?HL2xTKjFVm;ICnUP8sRRAvsC7n^W`67Zb^;7@Rt5V(ay?1kV9!A)ER z{E+Jb(jW64D-i5ugB9R@rHzcAAI=i923#8)Qg-ou_5pA62CI;M$eb8>j3cZ7-%lS) zpN8P-;OCrx^xsJz<QKpj91335>Y2y0&K6AW+sbZoX8z0`5@u<3eWJ0k>-DT2Ajlcs zkEm;}%6<$EYYgyu|1l4SBnH5}esH7;2+x7>!tfiRaU?+p$XCZn*$P;fjpIw{A7qRF z5f1+*Tl|mg;4g)zKU>mVF5M+D(%?d5WLYLN)ll>D3!SM(4hVo9vfZL3JXLzO(=zqZ zwxOQvves||fi9fAy86#fWU!Jw7@mhHUtj%4p7rYE4@FNs4CQzGFy}Ao-(CKp2^b+3 zu)BO8B<cw?_VqK19)QUKwO2J?9~|+tKvR#0h8Z`4BQ09Gy5;%tlKgfF^c219#C=^@ zwC^Hz==Q&|*SINLAh5Bwo%jN7n~y}e2pHP>ds8`#=LEv4x3E|L4HxtSNnsaVGsko% z@Mr?GE;=7_G2#2}AL{_uZsTe<z@02I_xUmEmrT~p?cw@9Y5@c{%@h2X)@5NwqNBYw z9f*lr4oD;phI(7M1?>k?BTxO*0rS%MJ+uPHrQ@KA4G>;!&*uBgcGC$_ZfNPP`az1s z0eBBvGN6Qx__uU0;>#M-dUJb7=dmAQWrUAh2T6kZsH$HtP2hW>{gTN&|C?pkEScOV zz#3OE0oF4@6gD!Td$5@S+^^W!c>7=7hCf~Vm-6@&*y58a-Zxco)tQP_eXPneS8=_- zlgL48wqK2t`Hbx|BQDlPG-LiQE>XmU?|3jt6J_uJIe?aLwS;MhmT}i-ek~0DE*<_} z;CEolXGC<ZGol9T^LcL4a~&xc{M|hsH;<>XqkcvirRQ{glu_z|ikE^ng2SU8Mj2(4 zQ7*ZK!=)-0enWfAkTA;VS9Yt!qo=e=auI7|Ie?vuyT8<#w?yyfT!``VLNR%ENzL5` z)D#_UST3b+Q~~Qg0d`&HHHPUbz%|qW?^Q<eDudKSG4$ljJZhtYmsw{W*vC4n$B-ZF zIdJ7;$4LLryz-~79wc4keGUL;HO6aSTV1BbyrH;qS2%^BWN>knMi_wflDWJY0Bzo1 ze{z+<z5LeA<gUM`1V%Tfq%O-}Wpvk{C$)a@d9Gz0*vl&GWE(XdG6Dvl<0cLPZ*#Ny z`?JagH?qzQg6{^u3O)zv(>%^+A^6XOH9iZ;4f7}exc6YmB(tRs63o;=h;z)C0`nrZ zakddQLvk-bIxjZBbfCJ<oUhkAKadcq&r_p+n80xxuw4)S&uVr;@g7@0wjE5-H%F$1 zf=y=k#PDbO#+qxx&Ti*+|6(%NFYc$83S4h}UaqY>jqhjdjF<p~+k1?c7u$?)Q2^_1 ziWBUH`Dqt@MoTNlP<Gf4xESw{y$($%5)L#YZeq?I;`x)_{dKwiA@b-SJ89>2W?8XA z{igc9c!&D0$*39*?pOSPhCA&y+W{q_6XSAQKPwNScF#>CJnXbd--|HwhfD5{Vb23C z?e@M{UJ2Kek`|`qu6p-jl<r~|GVrTuoHkow5`>)qRXTwD3tH*A_$A?7{dN~$26Oj3 zK{)+}Uks`FU`>~UWuj#~$oz^g&|Nz1&+j0YbiPkGu5ao$uKUA|2O`=4;eFO2O@Q#I zB~DZKbIm|#+xU?YiG+>uw5SCrU;1(31diJ3<6@Av)k8Fnv!Wy8d^;e$spo`_{*x#@ z)&c2mpna3yk1fC3`e|a=vF*T**+0#LGF8yJD^tSfEBCwlkq&gPwtLR(o_WqFyE9l( z@#3(E7iWO?6-D52jmrGF#s+J^7SD4Zq$+bHKWC~ke`ayMkn<`Il@o=eia;YN2qA<P zm&*a|iD8p^+)TIWP!U>)T0AT%e(w`!+U*iA`TG9jFaxcR7kkRYG47fDsQ)^u>O0!k z7x_W3q|(dhh6nR)r?6#w!=pUoKKv*PFXu)XrHdR-Pb;plQAQbMl;urCFJ&14&!db2 zLo?@$a$zL)Xg_fo+wbLW-^)%(m;{&4XxbETlDpU*^T4$)`^1nvPC8QU#=FJ?4ATZP zN7;N}47Mv02X|7*6kUashG`Y>J1;f{On`f~fiVekfcumQ*~UUbxltAoA`Y_WTjzf> zf9)W_$Ke(SAvnhdA#gHF1sWV=jSx78AO_Cz8Lk4RY%>L(W?gM&#X$(H5OcRG=Ujb` zC{qEi5E5(kk6BgshlTxaslVAqNxq>a6<~UcE#MTVI1RkZ>l~wG1izQNxQUVx9YQ9Q z8%77XhO0}R2R8+u32p^uBxwTtgy;E?j6r+`!9GqD4DmDIJDlN!_PJ^cu%eica^|AF zY_LHI5I&{KnU`pdm{m%KrKyo{b&ZvRu{}RnG^d(cc^i0@_t^qAImH~fof|j=!R@T@ zK5#n|Hh{M|nQj9c%z`ywl~v9{`VJp(4tSNfIS!oTBxfNw!U}UpUr6udhj9L3c}%_l zyq><#gCKt(zmT2-e$H|BkumgV^+*(BzbqKrGsdSxea`-yrnw!@3t)Sq>B|JX=bIB{ zKgc&7@{O~+)ujTi3u~HK9T+ZEd+YsmuFb8gj6*Jfxt(cU809j7>L###X7PG?{e1jV z;V(J>+jD*Tc*#Y5a-E6(QkkI*RS$7N=6S<wVY&L~D&da3X*u?>EXMJ8hw9UX>8)G& zWrL^b{+>mF@oid(I_CKCW%SKuYoMMM4G>on18OcDcpX-Ml0Or-#13TaQ{Sx?&ANf( zT^R(Ww>EqZK-ce=URrKncT2Bwmq3-p`fJnzgmM8q&vmrt*wBP;xwkBtqnh**d$uPY z?djs2b;TJ(kN)i%*J5vf<$kWu0qm%yyk@`N@;nF=dyYqKz<1|(m(HyvnK#&#wd9Ji zb>bQK+iKCjKYYs0K<@&ayZvm^=*OZ?p3mJs-3Q#H;TPH%+U@ms0r5<kXm%vL=2x;} ze{I0zdOObzJ=p!>mZRT<4O$bH_CsTO7cJwaEki_|AzpgT?;<T4U}LJU1Jq^F-<kmD z`S@bKcdJ&bq{2i_OFcp-u+dI<QTJ=2HjfZS``Pr9)PU}y_Fmz*&-R{J{gPOYSn1`g z1J<j2?4e;#+s6138_#t!<5%mkRhw^Rzn?Senb$+s4j3dwv`<*uD>3wFmb03fLKeXI zYQ1D(XQDFSNVIsEp5Zh9CCc8Ao=`f7nX0&P!UTd9H8yM`SOL}{Sc7<d?as|LK%V{w z+sA-yrW^)@iVH^ss()m0y>0fW*iRncOAK;|YQO7BToColHQV()%Ob{EG<Gp$l;T3g znYv{3F#T!LGVgI^{0R#`<X&IM4(ph>q1-;1PJ9{FlYy*4j#%YUcDG9!<r0wK+Tdxv zJ?deUQAQc%qL*ZZ*^e?xA<?LUo(s@&jyQUhPWl=|;-!^y*c9f=lc#p+in>2Ty4V$V z+ApR0P~~q6Y=s>e#fG%=A^PXCnSHzP^GVBm&`gC|GDg>#$R&^jPpf&Q%mJxs4$RE} zH=@Ff7V}gP0~1!6kTJHe0|(j5ruw@9!DjGHz6yLI_$eO&N4ZupZO;@4IVpg>iATMK zqus@V_HrwS)EpxF`&x_dPYk^##l}$e>RgY)!tm_^K-rnwF%BHmfA<-$q{F^sjgh=u zXGq{Bj&c^*P{993xq($j``ETHf0e$>hrsJR%F(KR0C<PfN*@`3|7||xGz4!3Uk+Y{ zXgl24qi@>I3xIpc*q#C0x0zEMAYjJhN^gm>x2opm1#^2+Y#ip-=fH72^>L^%MCrcL z#^`R^hy5Umol$CL@s~L;-n0jOYjkd0Z?^rsqkl;nlQ;X>o$TcI+?fub&Rl<?<}O2} zn!Z>zfcnmRC%xa-9nN{Nu3vnBzn5lW^V0s~T|R&A6K_~XJ$w%$L<`!XkACC=&y9Mw zOEYulve)5BSAeJY`(@*EmL2bnEOsvz>OakZ`e+G$#0Gp@bX=1yK>xV6{dQwY_8))! zfUHgSXS>h0yrScJzpK4T=Xe=5>ZtFy5_LTI<-_Q2_B%;;hH%-y055yhyO}B77ZBd& zm&^Y0nA5-Y8Q;2Q9Ef`ORXc#KU#0_n9P4wSNqS~5sy|0K`lo1pUzdX-_4bes{WU+| z^wV)+r+)SlHpD?h!yO_1nIBF4_hEX^54yV;b0cGZkT@9G%>ziTdd7}cF|Tj4i?F2~ z5_LtL@!t*rH|JL-6L~$8sjT#){CRB$79)!vZDKgb7`NT_A!?(MS$^Am&tzzKwND#! zeQ06OcQMQBzncdU5)H_1Z_ld#3e|rlvwO+sE+B{%qkBlGfbJPF$=)C$izBbG0<5vh zuhica;0%A4Enu5->M%gY<Q@?yqKho<H{%MmMxGl47A3WW)Z$`!`%G*4&90s)0KF{| zB`a~rws>`-=@e@lEE;3kjgqJyy~sSjDYJ#^;7`&r4|L6Uhg(Os9k{al;aKbUJ|*iK zH%w|f2X#G*4)d4X&&VE`q(&K~(;{}1QCcLOrnB_=Q4gc^6gdKFM;Ya^l(FYud~&$~ zzI_3Q<2dG?BVLI4;l%<>iI<eIV0y{U7njqnZGoMrXSij)>-5x3d(o2ZtZORwu$8&a z-#>RvAuk7<w`_ZF56eMqVg{YK%7l|?t}LIl*t;kIzOn+uO^{qq3H+TI4DNGedOZ*k zu|l?ykTZ$zC1Y^k3+YCBPEH{GPtzBJ*CE|bZ)XMgEf4WNq;GLLJxvBwJ`23g8IA%o zwQ&&v8_NIAfP)<5Fpwyw@@-CWl5!*CoccRef45bN+ZnThse4`3Kc--24`NnW1Lmx< z7dVYzF9cuZ&Vpfm4%}TkI3fxL^h`eyYufJ{><_Ni%6APn@{CrVYngFaeV(IlOxoe^ z5s_kK&jR^}xH>qLwPPxQO|It_)v^Lu<!w$=ZlLbvFjrURP5arPWPqBJ@KWhd(vyly z@@}qX1K3N*95}@>UWD{<-r_c3gAD}mAZtO^W@{?daK<2iI5^CHV9ulL1K#I#Vn{z= zix7hE2QTsv2*j4S9=MVF<SlUJKfB`1J*VLO@2*(eGojpwn<~qmD*N147M*|2`J2j= z#YvH}I5F%U?X%FB-ShADHb@MnEAxBd`0PAbVtlp%&?WWb59TK3+`{~hQ4ZnoTQ)#_ z8_;~-uvV0wKC2J&VcYZP{(d+$w%jk!0nbID%fhI~Fb7qm9h#LdK2Nl7JnvNb!hzm# zv96<{f$U$_a!)L`p6!{-#FEx8{q)+VpCR-jm*fxRLglOjeB{7=y$iE>Zm)6Y@yxFj zZO;e?uTOKk`5%m~1L|Z)KjJF4pS{};;>ESr>))?k0N1YlQMQcxCeyU+RIbD^*Rrpx zLvMeOSj#umxZn$viJbl<X|?mFxInaExm@q*k{QD1J)r^Q>_6(d51L5N_R{-#*8^WJ z2K**_Z?e0#dichbLeKZL*{9F@Y=?luhH+jr>Q;E$m91W--et?0Eo?lH*#xMUl{kjo z9{v4E^LXhCoY&_!Qd`-|mXS`>fRy%(iBe<8ZUSt|BEz7x+KC?b&c@|=Mc>lVpTZ)( z*L*Oq$?o(Ff39|poa3OZw4aM`A<`lix;8`OIr%-IBPP&v5CToV(&9%Y?gJ|&kUOc3 zs{;1{hos0DkhJ*EY6eZ+9|~iBrO(S;al+8KtKbI4w~Y@%dw*2KuSCUfOD!I%+tpDO zcZ*cZO$xi10R*eTL}i?mDsCwe@ISft;6MEI`|yVw{!*OV0wxOJ4yh{7O!b76IWSXk z)&$9%k}x815J#9cIV<cUt<-rs*m}2&T3l>9(W2w`eV;eP^K)W_sb_?yZCx5084uc@ z7kaPR!hs@zK5>oqb=7d0q{V{vG0J5tBfx!>PO|pK>Q^Vf8TByAD5ETKVmZp?C6^mu zcw`D6WrzjyGQIZ2e4;w!(j0e&;j6xI_8aa(-R%a=Mc#E-j45iUh`}<)YdsJjE}`v3 z2fbfv^AeX=pL>ou(!wAPC7`|Bd{i3&Y0?NBoCGm3u&x-~53(6-0B6|GK46Q3?1Ml1 zH-kq%`4yP|>W`28;T2$w&GaxZWfr^!%rwTG>ieXpUWAoFuA}{>Z*iI!c$-ts&A3cE zB}0?BK`p&}R#JeCO#rd}3>RRk+|Vol*{Kec*7=(9gA1baeKj?+tZ7?X+x<)2#3A4S z2NXd5IB)p(zu+Ej;%eYsZsuy>VScW^FIWlQ4}K28&A~n%hv3EFMQ(uLx7^E5;Qa4` zqgQ-*tbE|qU|2t=xRSQj-&p~5&NjT})dL)9;yBo00^Mb?L8j|I=ZUJbFU}49h1#~c z&bY3BhC0yQ1&pWGu2|nUbNG+)xh@~;3uJEwLL>vsN|hc`{eVpu=5*Qd_luP!d)f66 zJ5mR`$Bv!MuRE7<O76%z7OPFzp`2nzZF8}=MN4Xrq37dK51SGL>ZwgHZ5!Xof(J{x z=urnmCJQpb_iguhL3{Fz@5lz8STUf#@jW0C_0(e*`*Z<bUCg$9*7t6vYCj;c^z6^F zV|)9yW8@g`y1vH*s`wo67me$i=3I8|fP3jRuA9$qD|ZvHsEHfiUEXjJy$6a}IPG4p z=I4eT4q#Y-?y0heAnMqk>g&tq@uR&D2@kEi<43M?MLkCc+x?O%aMVX~rq!fpgsUyS zEnEC<>~X)athmA!O||JE?$}OsKPo)^K)36K=lmfD;`$tH^ldMbalPq4nCoDbyS~yW zN7z^npS~^BbA0p^IZBhaZ(P$uSR04*@z}MW;9_z&zn4x1a#wkU)eaNK`)DbTtNogQ z<ZT&jgtZ<faY9&IU-&ZCoBFgt;X|W+Wbr;b1APg^7sm6$;y^|9Ga5AtObP&e_M}OW z{r#DOB(JFJ*3{qC><w40?_E9gTi^%(bo*aC283KuFt~4%F|KDZwIo&X<ls3it{19! zw%|6ymXjh1DHj~S^O!`!?n7uM7l5#!?>b{A_pgokQZVsc&o7#JaYg-|_k2&^jLhcq zx@Im*2FrCl$|#M~<WWZPUpU_%91dO`^)SjPql~g^<w7$Wj||tN_(;?<2r$Z`(jLek zrLL(9wPL!Q{OKa8=r095=?o`B+TD<Vgm9qux)_6e+g)_n2(R{I+2Z#uxA{wz(K&Gf zU8>B~2~+^RvI2RBd2pn{d{b&Sd;WxLh$vIZ9$=GKfI}I;JvhX{U>}HoOFS*E2lgU( zPU|D9YO5_&%<Or~Mnnp{k~93omAS@5aWmx`EC<*}#*m&d`AiUmWGPH@My8xeNLv4f zYQrwGzp2vAj44}?o<Ooq#^9a+f(^wGl+|TM!jy6&=LE+%s_FB6-b>$rRNWuE%IV-u zN=Ep6Lo44D*<_PVV6N&TiVYzOedvsZS92gZq_xj6_NL$0+G&N5vy>ZdCBu?b?HE^j zq+p_g?;#-s2iV{mNPo&1#nd0N2CS>=4zK|bY-E4a8#tL}fbuX{17OZJaE>hmaEfzm zlcgM<LvUMg2cL!X`SdA%4CyoJQ@jJ|ZQRctu==x=JLB)d@BZ!d_4GZhp4&=4=h$XS znW}i2ZmX2VbJdPgX(~}0U|GGdS9YEMH#ho$G@$<`5MF0U*ZW6OV}h?|Sg<j*+paU8 zZ@$OY&%+82oxY}Q2CfUw>umnp;*ryN)f)#s+g7eCzOFrwfiq={D~F4sls3Rt`n5}6 zk7?I=v254d1=Y`j^ZYzpK@cyg?8%at+xsvY?}Qyj9{SkHei9Gx-bKnI8<>rk(f_+J z5|?B7V($?x_8@nlUxyy$6+PNFUV<GruS3JZ=NK7qY}kx}U4WZI^ro)Q_qCs}<w`S- z;0u?E96(H0Esm(a*Lw7)F70(~Yd;SgpL@MgK6lI6Gh=l1GiE<+IFRT7eA?S9bjH{G z;@`1@+1S^AhaUFn_ndbB(3HV3^f*o;umRWn>|O?Th;EchYx&ypT)CL6+W>(kFt%N< z!n+*=b>?b!#zQ+0zU|<F>)=?@FuwcfM`s*w^Itv;%cAvQf^hm5QL#%?FIE2;8w3jV z-<!vIQ3JSF{j}|R(WyS7HlFAG$RsVu$75-o2Q>So&{8f8JqnAx)DIBY?J}|0p{;&R zKz)<J-_>t~Wqxb|_7kK1OCWq$JTKJjHB7%qq~eenVaiG{0ajFeQN@>o4c1r%?&TkH zfDGV1q0D?a;|k_lTve+0-@J&oRf#|H%#JM?0n@3v?;hiaDb>SZv+A*;H2?gt<GDEj z#UqzV?5SlmD%SH~T<|>;&+$1~U}tU-0DoBYi%#z^^mD|qUUsjieb*7f>hDcIl<Rlf zQI5zU&>3ZvUfpDrQM!n}Q9Q~hql~g!Wt<v~a`7zO#MoEI8R=!?=XUah{cZpn3|}YN zQ}5wLX`kW1)^f4<+pt6V#X|b<Esq$ao!go3MDKct9{L>0F2Y^xpR2&uW@*}BwgF^K zVEa@h(-j&NzRF--ZdgQQ!0>F7CNxs%%2XahCVL)_etHbP$_v3=2jLYWjsd5z18Up+ zQOSNTD$GUZ21Zxe#~Kl^%^D%_p79i60R4xO`hkR`apXvFGrLRed2K1n%@oO{ZmTJx zbL%*zHj?JdNI<c;drSHer`ZDD;v`#^3(jOA^WbHE!Tlf(1y}JT{MEnl*T4G1=i&Sl zfA*04h4#EHX3T(dOckI#1GaDRWdq=z6ae=;b+L`H-NxW9q0$TV4J{J@Z)0TFKkI<@ zDoektwX(^uo{yt?ie(d!K5H3w=h!m_m@;per`Q=k?azC{xbDX-1~P93%scNF9zCo{ zW)1L?-3);D1t7%>*CHIe+<oLnyKJ2n?a*xDi3Rog*ae7xh$Y4Yp3v-J834+iSSJq2 z+#U^Nfl14O)xHuBU{8Jgo^LrMe!$6P#UW$|pxzMk%%Oq%ZOrM>lKjh}qf=Kqi+lC% z?&EmWQqDyQaJn2ISp>i{RGi7|AIoa*WoI^M^V59~VAz0=Lyafkf6zoa=Sg9wam58X zjJ)k%)Bvik{wsR4=OPUB&Et^pVs>w1oc14g@|t|fp_eZ^-v1>pKzV7`p<*_dUiGU3 z$K6cWqQ`2*ZKtBO{e6JquIt<Te`u6PI`nBW`U|7~_wUy_klU@_DiGXOJ^{g`+JjSL zo)wtD%ftcru8)sZc&WtAU|y}4UHkR>?FSEH=kLPmpKO^IH2qZU)pmWJ>90FOd{`OJ zOe>07)*m5NK)qRh(=J49d=`PQlrz-gwOO1oQb6~thARr-K4Fq>WPh2EWe8mX9%Gd? z*t@pxfqx~0^u@n=;P=}q9ytSMT&aNWNs$pWQIVxQ?q_BS#Trk`Ga)9O;z40coN3<R zBbJdlQ1;$uwD-TH_dzY!dSqw!GZV+bz{JtNBg=^7L$tIL^$=DYio8lx&Gy-Sy(U}d zKg(asj&jM%2qzk)lU)5bCvX1sU85dG8O3YDI!c$Y$ykF?Mj6F6Q}tvL8GGrjkUY)a z1(QIGE1XX4B?cSwF6JI6cF8*z*&ypvx3&W(VNV^kdF@3R_(ChcxL>X9DS4aq;0nNo z3-+^R*kE%I(ZxLFTHnY@W&xqWa&^#qqHPRFAW3DK1AO!Ev*+d;B^eXXN)QJV;8U!# z2Ei3<vH|R6ADh5$K6%&bCj7Ife*fdYIstr{+j$>&g{OECIKWLjO37+{lw(YRZN<cM zhI0z2oNZK`Qd?n(f~Ib(y5<1cqa5QnFwGdd(-(P(=gF9UrVxC{O&kQK%n5-l1&x=) ztO6&Qvk5%MN5l}k6+FWAl*~Yn^Qy9$l4)sPX@^iTpl3`zi7Hv5QsgGV@dEsu09$Nv zQq^Z>Y1eJea#nkP!i)(SA9=oUH&gGE!2V!Ov8-epjaQ|wb5+@H=_##W3Z-ZL^PF-+ zPynZuo^RzKE5QB&Q2kbV9QYi+3O)<zoop)R{p*mxh6<GnR@s2yMh+7LZ*qjazzeK1 z0X|4i6GHG&a2F3k`V-FZYe<i$d(*36{-s39+kl@MJunZ@3uO<pf(bw0;wypbxqaw% zA`7NKY4occkS+^-B$OL-bM3zTy%L={y_z6?ruAE?=~vWJQOlZts{-uH`=nOBQWsTV z{H(TdnU}ZjuVh6JRUOZ3ez%#Sv1GK8gUmy8#;tx&8Ro!MxRh<k?$UK*aJKNMBp3XB zcgzf<fq{avi%t)VwO;JhpWl3Br`A1fHT4DfCJXmd--E2OMel9z>0XW|jdneN-L@e< zrz?P5E;PTc_j6I}uVSH|;2Za9e%riws~qTnvuJD=(Qtfnn1dpA=H<C(e`|ZL3m}@b zJiqO^zJ4Nc=%GH2bUUzX`qlb)Ef=)I>N<SZ^4u=W-4YwXT6){9Py5HMaRR$ulNLQj z9qh<fzP9nN%}x`KcJ?_~H><^2q^G~I`^|an{oS5t!msA4rd=7~quO(t;~)Bg?9igG zx%c=ejsEH92ii0oYU^v)eLk50<}KxQ_X%?xOghCgbD;UW#S-ek-lP%4nbZLK(x|VC z!CYGBr%A{8MpX18>9qIiIxwsqOc#xIY>xN!HMZ0=5x0&v(s-_HjJHOWe1C4g6>8&y z4eDRMuL>ovGrLQK#!yWW2g&UyXSg=YEdc^$XJ+QApsAgz84O%UB}8pLAt*B}%$@C* zSl4^9$owdc_7#<X<)xZd>#3DURNCJx@7%aPtTE$P>mRD;%xm!iS(_J0&7R`IKUM84 zF4`|N>LrXgS_W)SwA$!EVQJ`980|DGEOcIp%!TTgm`K%W#vFpXHlDnC0=)Du@A@cb zZl3{3I#)pV>lK5$tYjjc)d(vRBLiZky@OEw{&{V_KIGaqEaI0tx8Ap9{1{p$*1VI= z<qCVOe_itmpEy~U3?pqaH-Pf}BahX3M@1Yu?9{%#BVc05$g#+QM&G!=D5H3VPevKV zL;jop)4w=*#iOGhMj2(4QM@G@fw!Y9b-{V@+Sk}KE=}n&PaJ+Bd(yf9AMN}?kAoM= zKkhdD4-a4;!p@|FxymK+f{gAaBY2;H*APsWZH#w2-M^RBPv$-QPFcq~lXT`^sW4m1 zg75k?-&g<2Hwtu_6dOFJcobM;g$eL)2WzYW`#HxN?EBZnXa41_@aes)-<h0&t@sbK z`Axu&)4RAEi1?Zc;3jGlSQHyiI`fZk{MFlC-`H&Hhvr87GrYw);6vWztom-FqptNn zu}oO0&u>jYWW9VzLwU80+~5Wd5JPZ~88Prm!}wg?V9x&D#m!s=!M)rR90IO^^hOBo z5w`{t;5hrZ3gW%dZQ-jR@0Qba25Bn4`={?h`dsq(pUxgEpZlU>ls`+T7~3PZfh{J? zfT`LTlZE{z3anmbW)GFc=Nn+s0E!EP*?n#>xhDqmc-!aD!T3HmT22)GFy97EjQ&iG z(Y-ova%V`WW^zcp?8@{XZP(+l!zL!HJ_mcua?Dw-hzkT{zS!1@(V#lNbo9Bb`D}Cv z+nwl9-`(6_sz9c2NA%UVy`v@DZTnc_2Yg*t|B|gxb&7ceOL}h?3-6ynYjNi1rY9r= zWe|%U_R^*NqQiTV0W+?-7*{1Y`4{`zvouyX@j&*OERhMl3j=l6{^P61s0H9Ul)sK0 z_S>huMZ>ywi1A+xFuzDFjK;nIEYaczd<Y<1*TpS*^(8jwlCiO=pU2+*-)+A>07kdo zx)aRk2TEd34V1^wo5yuGAhQJK+B1uVt>bl_yV|XvE^$U1<G7EVy7X>~lg2IWSu%M` zuZ$6~)8ADOAk^oB!WsvT92QjmZapxR{z`rSe6<|uGe*5_^%WNXofz}C*Z^FcOz=^Q zKMq?n%7iTkMWl0FsUE12mGVb5f``y*pRSB2vKB8j{ivwb!&Xj#izp`K$;vhL-W6)! zhl(I2w}gmDWdx0gftZ*Gf(^ywzQTkRV4aXvU@gc9NnpmafZ!8p9`8G+;&t=#Z<@#N zZc*{Rk~krc8zlu{ifv62cAFswIZ*yVBW|Qe`7Q)y!fNMvu^4ofnG{D={<DGRQK2zT zls2EBXPhX0F9_UDdDJlKctBh_=8MwdCvAQ??5W|l>%$K7=oR(%41W81viC9HQATMr z)lo)im(K);IW(%_qLaQ0-HUC2iN+yulu<?*NCYD=^>UWvB5(b8Y{JXluDZNwH=UU8 zyTQ548DQ6q!+0P)$bp~_i)_&5`t73!-!=^g1On*&ELyOvuCR2p%le5s6N4ONO=kjj z%V(O5HdR1xVtg*kC5lwD5wOaH7}(${CcuPMRu1yJ^z7;1O%C$u>;9G7Rt|&sg*eAO zz-_^t>w#<dEP@P>EP-_rR>&CEXTUKwSRv!>nF0G%NPDU@v&Nj5l9^{+rMgv{2f-cO z$(`!?Q{Z8a^9-=flqp#%Tmh_-um!9lH~}0$5<~h(`V?=f^30VUKT8Q{3W?OFLDqg- zoKpb#?DOgLET@2kvn0S#-s4@ZKKoebbL#UPSPj<M1Y!l?hKDQdI8lJ^{9uA$#u?2v zK1ko;t)hiU&u~m#CzPJoxK6XZ4c1tp+;}?3A+Dm_fSPfNDWos)K4&34kR3n^HrX3o z3xVK9t_C*QAcl0pD@;{8X2A2~d;q-08$`hSe84tv9V_eyCYi^&^1<l+E6zeHK7Kk4 zVf*`kym$H*@P7$5xed6ApL0DW;6W<=tgCk1X39)!*Sx*Z0Pgxhj>G|6&l#H%WnXjk zS!m4f`No*-`_g|&BOPqcgeA4Hp#;DS<9Rxhr`|6UhkvL8-V?{he+iiPi5VpwlO2Z! zbA4C8<r*#L4ddbv&%c;sXUmw6?e_K4ve)-R&kvGIFd89x%%3k7J>=s|yi5D1YhNJh z!FW8({I%OYMLf_tt!@77KQ1iRUW>fn4!rcwd^luU_;A7c^=-eBfp<9vl!wmX(RY2> z^}TLp^Tpx@zWp`qY}ulh-)RFp%ND?7m$*m<$n74NX&&#Svz-0>S@rH{uzqI;bPhG2 zi96OeaWYT0jbDEKIbLAA5Dn`F--AzP`C^ZFXEQK6?9H$$9pjzo(LQlYDO?#3qK50c z%qQ#2?{53)!ss4*mdE4?k39A1Ixu3(Xd!VQ7?KV<2rWQp+x);RuX`LTf!4O%II*Dz z>9FU};TNUDznSxIS3BAO_qP6)INl!_jN`uZ2K@km?YZTF4?D12TKbWGUsSwDR(fo` zAK5eYxej>6j&>48X2-U5P`!ObW&UUY?Srt$dzr-*Bjdd}z&%udC+hFIiYu=NlVAl{ zWtA0RjZIb{{Nkri{mnzb>@Pq0JDtfr&-j^e9y1fE)V|lfaMCj7*qGk?%^7#U_|7L1 z?{$HDo-DlPs}xM;cE2}JT%mx!|9((CNftxxN>4p4ur3Yqe*4IR>(OPbvqrhBWCXa6 z(oJsU8m=1EFv=*ST!u1Ev@W*x8e3~O%9wg;^oz|RE;;>RUGQI=?R>HO)t%xy+^Ha> zn-N8NkB4Fj_8oOh@!0kGVdru-1N7sLT39p?cd?CwbFIy)K-!YYS_g~fz}~O`^orUB zX=c0G*2P+}F_CRZtS})yhWx5{;L4vIBR&zIzVf|;tlhqP-O7D%;?=)=<?Q{ygg1jp zR-QCt;EvR@rDFXF)qCa|_fH1U)tTI-#_SHY)W=Ty6PYChU*~q#fMdMQ8t{;@-4lBD zV_9tEB!l#yp~f%Su|Jp_g)j3F+rR;iGX-p1KsKf))jsKu)8}~y<W;Ptk3jm9^v3iw z1RKH8;8$?vd+}Br!b#5j;LQE-@!w7EJ^v<z5A3;Fya~a9D}E5K9xFFQW@^J~S^(Q; z6`*^fHn?U5z<pk@npXks%?CP?v^)S(Wqzvm8#6OP4uB7}6v@^8C@THXd@jZPNpXGE zSJ@fWg|_9C1NC!zln%cj%YNXrmAt%tH};YR$5i3a-?C<@;v$E+FFMb=6hQt}K!;pV zALE`&HqUAXgzQ#vG4JY(j$#Mx(bivOqu!UjZZGY;&vV1h9PIA*%K@Gfb*}fafYq{> zT@F=_CgAOmc4T8H9cKM#pT)-=0jhPqH?OCo1@$nLowflvef_oXc-DO#?8g}0y?wH> z#DN%u$ucqgYt-96Re_Yt@IPXK_?K*mXLVyR?{}cZ1x)X5SN$0HWy^s8H-N6&K@uAv zxsN~b1=>fB`GSvLszBdvy(w(5%Qk(+9`<8vx2EU%*s*M7+V0kGV$b$+F@ZPrs611l zY$$IDnD%41kHG<~t}|=<*m2l0-xrqOg@-@P=RYxaV6_YQu0L02l2`i3d7@KC29_Xp zJWpu#vD-~^#=@}0UL%?r^23h$4=n(Cf%|}jtDo5pUf2#GxH54hH3s<V=WB}0oT9SM z5JmqA74W_KH&%ot6TZhYWPtaK(S3y#V1-pCz%l;5k*P5wxR`OC9QZybBfiLh??Dmg z(}C|%5%&&|kmm8RFZsF4bf&el9xvSO;-47@D^s~^-jH~E+Nw+(->>wmUXb7S^NS>2 zG4~v&liEI3*s>nzyAHFrVp|+&GKS1X=@U*GWt0wb<u|sz^G|;^>S2^oMj2&c85x#$ zmy8D(x-1_@8D)3&quu6Lld(T7MY?PNh78AqzLU~*qd2p-a7W(f+df1312c7_#BT#E zZ2UbmHm-*s0mTCC67MprofR7~NkzwHyGX6hbzpAUCv!%j4A{Oxs8Y;Mid3@`3V`~5 z|8M-0cm8q>{<Zu6uJ}9qAb2bIQSfEp?)2yB2f+KmPlHY17~6aU*kYTI46vLtyaSw5 z?K@K;;OzqFoNZjhtg%kUY@Tf}Y@q=32;dxBis^ca1YYBf^esrwu^r5Sx7i{De#T22 zgW#RuZZ?5=nr)E0#5o`X1`Enmv-w8NDNb;Tl6mP(-r`L%K=vFs%{fj|Znz|D6dF&^ zQ<`RfkMR-jYS*9UEC(nzW+L_6{EZu|vr4hy80_U-!Qc+0rwpbhsos<Wqh$ezN|2DA zWeWkk!U5KR>lEXC%t=l{dJn(h0I<OZbKn@)2Ui2@Y;ZLYv&mlIhTvKR1P3|70r<qd zadPGN;nRoL4z3=86Sw^HNB;6A_|r@Cw?EzsSN_B3bK%!u_P_tr-sDFRT+Ng0Q<f(* zOWkJ14AN=#H~(A!+~<V_&kNRj8<1Vqx5nt61Xop<)<XjbU-qHg4y0llssqt=z<bHG z-puG;GQOMFQTdF~n`e&SMKR7`?f>RB``kH4l#M=n?i|bg{h<VAsjSTfM8ow%&xK7r z>=xjApUfne+DvvC^+^V{qc{*3q#n!Cb24xbShl?`>tJZK<bFJqy@X3F#}ILZHej0A zq4I<S*Q>9-<AIsdecLr!u>M``$2ZQ?=O9fRpmeAM6vFeli`Y*%@IfLM18&#)`vQFX z#`DU!+d(gTZP#nJ1MTrZ{mP}+aKZjl2bPP0?4t_c4||S7(!!)HJLt(qK+qIVNjwf_ zHDzQ;I<{x%VP8J}ud9Fa1%jI;lNMmAPf6Ve1Ksn(Ce8Q){iUP5d=GGh9WqH|fM_rO zkgE3wk;go_&7U+8&a?rg&2dh))VFOMNwfnAqQMSgM~M^TK!a<1Xk%QD9QBP_?8`ie zp~yUg!;b3@TKt<?o@#mR4EAlnZ`VPTCcwIBPbRaw%`WQSht>=freB^|%C8fJwCPzo z^cXsT`-uj07uq~Z6j$WH_OM|7&oYF@1%XNiaL<TT*0Rrk<J!OZf7_dYoS&J0n8$-N zfO}fW<QNul*DKUoKPlpNIgv{i?@23qn>zY&Xb@5i4QLkw>_F}Yv}oL`?oH2=gJ=5c z^SmMEUCW67gj&XjzVQk{cOoe1F&`LZl#9S+jdBsmpKkuMTmJUusE1KT8D*4FM!6_u zSpeWm1sFdbbhx~wuN^Ogk@<44!=VEh@h;czP{GUY8??*u+i?ps`l9vqP2}8G|29VX zE~z5B^!x7ZA_ldKWy##3nKl4zu8;h`P_@h?h!xO1W88_d4T<Q%t?&KQCxII|m7atD z=70L%u7C7A{Q3W5mFPOybL*bh!=J+W?NqX%o;M*&S)08pQcUiN`kTKyQstYezoOW9 z7FzkknjP9(>oq<C;4O}+`W|UztZK3s^Wa6;&{La%SJKg5?az{pb{$r(FB$N2JBU<j z;d~?N5GxQIW{njf;$*QQs59vc%LY~m!M)thVYuSzD_*<eLHN{Ft2eJa4@ZxF_`>mT zfjpBONe;m3nU&jPVD`}busi|5mx2d)64D2fbF=pkW*c7-B@lgEY38Il2r*M5Qc^&? zGfODHuO=d%7yrsXC+d@|*iBMAr`j$$FS;;3qm@%<XcrY*NeZTQ7c)D6NVDta24FT! zUCi)FW4{*$Kp&&OC!PI#QUUJ!`d}B}y{!Lsr!mP@FJGDMh?l=G^ANd%>&a!#=f%Kt zvE|BEuXd43Zl5mmc6ovNg!Hu2z6TI5g#CmbWfDs+w+}Ei8o2%Z?`eh(E|Q7Chw)Yh zVW)aU=`dELzgG;<Ke}h^@$c6@<G0?PVgNghtRww!eWMO&6P@k5&w+zzfqpb}Kb9@y zh3Mg*w_5b$I}WuS{74q`Pws=0i)Z+g);Nn;xJ@KjV3#b^-=u>nx~rWh7UF>}^>i_j zM))0MX!8xRQ(x`vEgSk*7r?r(mPhomvnDSqS)6ITZN3#5>)=KFpK#cLXc%{-M@9wV zwy*Srqui14_Ot5xQx5y-0<3q9+qQDr##!0W9x;9g(QHiKP2;a)J!Z~cQllP0*fOuH z1HNUg{=#avqOts8i=T<K43PG6Re|c@W^@;hekEuJxJ$=<reCRN$nZNL5IU|ef4BED zTZY*jcwV(XQ31@$T3oUIK0RI=7V$_?jBBCxeW*sHSP_@3vQ0t;be{vO8L@>}U7POT z3+LtUX8$}Rx(F0=dq#XQRYVje;e{;XU3xq&B-j<}#bry}lQ=4>9q3pzV_;|<56U?D z&PLqK`Aeb!#yv_B<o)1n&p6DYnY`lG`IYFj?rWQu?^H&)Q7%gv0q&!8lTFqvNu@^_ zWt34y@t=r`r9Js_mS{AsQN{(+0CH(*EgJ3gqHNc2hiks9ak=lP9DCMF28%J%``TY* zFt`k5QMQ!OLjd)Cf#-6dRN=BGQ(m}WJ$GBr7FxjH{(BX`9OnRcHdQLw4B#FU6CEUY zKDlo8t%L9`FK`0VDL3;t{MA3$x@CR_HvZnH9t|XjpNL<D057H?$ARa9M-^jt6-d0o z8f$=H%9M;bK5K`tV0MQL&@6#7Y%wKcY@ew}$bR*_8E}>@#q^^9#EKF87{@sU>Av)B z#i0H+3Ggl`M)<7$XV_9~QMvuBtMcSw`LF=yXMRDb%_~uG1!eWixPv}O-{e(Qk2xTN zAMqJVI8US)^Ai<<UT0Np-sV8+u(qM3fu)0qVqjPQ1yXG!3HA4gDzC_n5TrA5hO>DA z;GO^*Y_bk~Mltqput5a8n=#|3PxE;CGz9Mi>s$-L$zVhL2&S*jem%bt{&?5yjkCAF z$9q2}ISHS>b@dCAhhX-^$8V+203UG&ry%`q`hI#R@Im@Zo(5Kwy(NWRWG%j3FxgL; z16wLpan8^*XI@E3Y%;i)%<f46G_U?HYYgkzb4_OVD#Q8A(y#R2^EOH>!0fy{nLM3c zmp*A+_jJYHW|)lZ)%PVW{XUnOV+=Hb^TGg{4Zz%<+JN!`>Egm31Y%eoK)BS`<$gf8 z%Xs}2EVJGcv5>vSyR=?iCAmNc0cCIIw{W1Iws1Q-`seTr?2G7IE_k4|Pk$JMIWB#& z;|)()_0)Nu@A+QYqVIS?W@-QaYkyAMgNeGU{fGtP3tiWF@j!Opet^5Vox0nzbks+* zmRk(qkMw>Z2ed;y-q45H-*-G(H161DXI(RwxW*q-w-XN_xli20KhDt)U?0&PSZ*(m z=scd-0K`#GyObVG_s#7pYJmAZjO?brk_~nwJ=!bQj(xY;i)iqd-I?*b*;7~Ii>~ce z9()olb|f77kXCy(`*X=yU(e(z8rxa4_+i=VKZH@grh`b1%mL}QHN6Vpp{kzJZ!0^G zE0hZEgA%rk3?@^#4ZtlO{va}*XZn>e5MIpmw((fB*nJc5T-U!1K<{Ewj~w-s1#nzi z$B+6!4_C$x^PoW0j?4@TvN$MEA1{O!pM^R@yx#9~V0&J}k|-mOqehC!Jt{JVW=!rY zOn^B1n|@2hPj6QY?(>4tJy8tqK{{7)w@1m~?$Q!JGi@a_;$PdBNYG=qF>U7nb4mZX ze&2a)lRu3;4)oIDdfU86dd!>T0>|K+$J6}2J+=0*`GrwNS%QoJ_ffjZ-e7~ZQ4OQ) z0vQL!QAQbMl*J{!MC)}qq_!Hz!QHf?5~H0AAoT!|FGJVG@1J}(_Nub(rAJ@u@ZIRM z1>Sr%#M-V89ZXJLH&orJVY}I3xM2SoI`z7{eY!EaE&Jfl+$dG3*?qRLQEoVdz^dAC z2vzFX6+*&euyMshadeF67S7CWK1ldq?Kv%e3m<>${O0*}IP-t}>!)U?;l{sr?W0!- z`1q>%3m@-;Q;+`3ul(+}kbZ}s^DYEWav#@_ZItB9J`r^$p%OS=WeyTGMkD<yIKn>G zfGK-fQ|*3|Dl<9g!0{5Itb@sgvC-pV8`jHZKG(*Gu9x4er*2m^wxnwLs`twR5MNCR ztTv7U1*lKA35kIl5o#kT-(bqFkJR4>`4Trlw0Xs&SKJ5b8NSH3;oRHjzV`bSIDPZk zt>16Jp1bzEBR&tGetPx$pS%UaZ-qCAGr;x97m|a(*ZCn|h2XyqWbiTsF9)yi6y?TN z2}mvh?AZoZxsjEq&xx|!3|wvk*Yk}nSxHqai;dQ#0&p)G&dY-rQfp&rq%6)E;=|$q zMU}r%6yH;^D*buV;w9$BbxP8t${}xpTGNCkP+9i=?4U^bKH1=j%-`o0JFk|%d1RX* zgJ&GSJxx6&G!Q(!&^Ug%A1z;W-hAn;XPz2he%`Qtb=voG;{<}IcY$tYhk4E-_S7Aa zz1X~L@%MC_Up4_pm)#GmjGcqXKs@LKQ8%W&!Pnuk#%$=fPF|!x2~YpLjQY9i6Zh1w z??IAs9V9)k4;S(;@j&a^Ha*)Iq2+@8TJ(%}4RH|2zkU1|hx_{Xu6EXyp|UT*LfE4B zuFs7<%Gd2cfq9@rc=gNn@mY9h+_UMU?}5xN_T&Rd&#xPTkU=!GUt+{Ln*5Y7?(3q7 zsMe2VCqEH(#3q&YB|7?ra$ehfpRo3~CV%77i@rW?1B}NV#!W#Ti0&$1<f*676R>Xc z8@7XjQH!3+dN(r#hlT!JK=j&ufxyi$o;V0rTnC}dQM`-~zgj7Ge%-`~d%D`$wIASW z2N!VN<=@J<tJ|LlYyZWe2lIGQHNNO-53|3@hH~40>}I=2E$UeXwAbUGp^7`^89XB( z3PJ^V&*RP$CJ=3`Z|+|K=BNJI@1~SQ7ztAq7rdf~8|HDrMD@cgz89$9lfrJ%;$m}W zj>MtjDoJhrcQK1A6F~oUPuS`E;nweVKeVFxH=AFZw9Gr=hA6Agfw%lx|M|A)HP2i& zVbmz2Faq31=_v8T+iS;PSi%B*lu<?*Wt34aCs~}~Wdt~1N;1x$E)9E*cAZ^?m!zJ% zuXyF)dfbiuAaXFT?1abBfGg?1PY*(G4lt{v1|v=o^=uDQpW%Y3xZUj}Ym9bsK)dQ{ z&*1=Ja-E4s6rU#rAUXq_M+M+H1VkVM0ek+v;Q8PbL@!<O>>dH~-t-6QPa!>;K9t@8 zZ~TpSzWO0>_|Cuc+P>Fe<)u&lD82{&@WJ%<KYa;!IJl2Z;9B12DDWg-XARh9m33fS zZRM5#=P3!Kuktc4lclJgLhuBVqrkRGSvv>TfK$j|6?mN!JO{kbNlrlUc5s9VFi$gR z^7Z_H-)OB7BH4$|U{q#G(80Y)u^}WCqfoY?a)NVwq?P+l_OVy{i~-m`#VJlx0;@MO zruBmD=5TPBBU<|$NZ;c)<%ZIStg)$$b92^%{ggoURpRt#6dOkAJOi``*K;t~0PbKj zeF9R_FQ(5x^78o)c^0nt;+_M+QTX#`{`^a834HSIPhR!Ocj4{#-jzq+hd=$~Psit9 zhQIjM`jOS&K>9@{yba<d@y*~c1W)iR4}zEmTftQj90-0Jd>zuec!m|=bspk&RZepw zPO5eYsRP2}Vq+>#1)CHM?)k=<)cS|X>@JGb$+BRw%7OJ6BN@eg`d^ARkOlX?)XFng z?==rh=-XyFQ<(X^zJ{Qv2S^3*(;2to>h(cn_$Aw647763tDYt`03Ly;KF<oE7uNBh z(I2HV$C}A}Zrk>s@bJ3=H}m``yL-NTq1MrD^P`=ZZT6^lu)_yQ(+hD>eE<Nq@BG*F ze*^X_;b2-_4ue|Pek6+VwY@)dN$KuWPM`i5@3<ea1A&%(Ak}vr5H4t^eb>*i1Mt!P z`Lgi<iVL8+2tdfjFx>`R9AZ4mfnGU#rRY@7W=R(8CvEktGgvNO-abs|eOL8nzm2{1 zA$qp6|MR-MAzGk(qVc!Ifby>K&A0z_$@JId;9=Yf$SN79rH8+BzrQ)2Yh(O20lrNZ zAJqWeVNd(%mx&_m2yBxU0D4>d+cQP9w|*6H=w}!D_!(B7(gs8~*Px<tUF_4ZnhpZE z^b|S#Vp!`(b-<(UpTY+JYGd$EtX%wA{6^_J5Dnv=u2<o(tEO?%w3FB|u0$>4O=#%L zmZ`)9a{KfL7x3K$WY38_V#oDmd0b5E<@dtj*Imr=w*D0w@y+^y0lU2>29VvfKO3`q zsA)_%^(iZv7jxnZndTWD|B;IK&eh*QkxxhkaL+S5=7bYh)QB6T@*8<PPK&!0nHGh0 zM(FQnma(?mNeMm2iF!ui^DXO$e(Ouux*~3!CpN#Q<-lwzRRrP#{=3F;RJ6R$bwDlh z93K~r-}x};+s0LS3E1)|7u=1EGK!z<O}FIzqZ&pTWt34a+R^q>Ing`HC_5>;g&}%8 z*l=moey7`U_W|$4C1Kz3g6%7pI3D-e*i9B=W=nHE`HhD6c46AfpS$6Bf7D`6`Stsa z=WQ1E<>7C+ke<5&Wc=+Tbj&G-0Y)XQOmyvf2|K(e*6zv}b!J6M*$_RIY^VaX*@nSQ z;@V&zFy+Z0hCh37^5K<Vf%89?*UM*M`|0U}vwPsbyZ#@)dGZ*9f3fEq!ExAk&*t@? zz7aN``}1F|uE1$|=IHN2;3P9*AY@&=w*-J?n=FDkb!K&w;XL1fxs7k9&qDf4`kmle z-~b0f_`V$;XN5Y0x|!;DraniSUaBdAbA6O>^$>kyF8@7I4B|o^6v%<iWqq>ibB@w^ zaeb8uUMOAUz@O>{QCy^A&fohB_54^JREX69g^a;HCME_x%O)|TPp7Lq0ax66#aF|_ z5FX!iH24lA4}6?_{3;y##_^Z`#a@^_^QQ;q*T9}b;m`NH1MAPO-S%g52)-rm7IR3V z^9SWOKz=AU<VoOUa3c5sxR1lE0+MUk3&D&x`3~^S;9&3+5D`~4r%ML+JoWIr_?s~` z$>R6yuL7K>^9rMTQe$?nZkU<h&$WK6e_!?&SpervhW0!aGE`F@>kRK<m5IFqz^(!x zrPUYBjptT<T?z0vzsD%2@&4djMmfG!^)JD9EakPyH;v~T5<F;pF?0H^#KQ;omstld zeWBLnLyRNwB@|V-5cAJumqdx;)_%965`5d3-z{r>V9tlXHE_9o^tls^^Dbu6om$UE zJ=a0YW>k+B?0<65(zJsYhVo}}hvHp{Cr~o#$oSjWkH(&Q>$}SG1vn1{aBpK+9ZJFl zfzz&fb^#uDjWdak&us(9Hf6pDd+VV)1Lly7@Zo~?@9RgpGQl@7OZT$hz#qWX#AM!e zzUu;ph6`juY_n^h_A?p4ZSNBu{7+xMBk0#IT>;ynXHU@qzHNTIsoqgX`wu;yYa_mJ z*_UkaOMMvLbGtBs&$jDKy;b{@T~9V<_v|@2!9e-@Qx(7445YTTm$ZzV`tzh?oN_Vj z+kow|1=#Ky_mYmlc3H#`WknBVJID%fJjVgF1K#TgEHZ)^(NgcKKFzqlH1uNv+oP8G za8lH_?AN05JYhM4QTByN5s&?bibH1%?s@!jEn{-ux9@NK$Lp(bKKb3X+cOmxoB=`s z+@}SRh*ZQVQW0PzmH1l6HA0%lo*%Z%aDC!U(+jkVR_<4v-_`M!Mdqu%<qdnRr(6JY zNeNgNJ@n|Buju_Q9AN$3^B{AOGt{pwY5h6MWhEoPeUxtNkAuOl#g|7tj55k4DMK(s zjxx>?M!7sh4#Md=$_1IsT@YU)FPnaGF}BY#=M{_Tv#UPDF0q5f03Y?|i6!f;xm-hT zn75@`?bEWdV94tVgp!qwo3Lj~$c7EjKAKBfm_vNpKlEt7r~^Zy^suj{6zBRzn^eH* z$Ve$`25@DT8a6n`jPC$PnD7jwFYq*{;ED&rm-qY@)_=2l-{h-s?yr9Tg+G25l7Hv? z@$(<S@lT!n^_kZo_z#2U*$Z5o{!soHuK2<guZNF7a{u`g^0N@U!1ve$p690|z@6O6 z3IsQCJ9h$8rp$n^v(70pV1Bk{nsO4jikP#&Vb(YY978aL^rz{I90L+wWDdN@2G>&p zg5TpbCpEo%#1=;>0mA1v#WAw&lLVM@j&s0F0kQ=VQ!)VjjBJA@rra>jH*Rv^{t>R? zASGZs;S?WHZp0ij0M7|C1%%JqWiR`K1KRTw_Hs2P13&8TqrtswLizyTB!=L4a5HQ0 ziB~`I>-bt&dvWd2PhAi1{Q4i=|G{-2-b;TZ*MS+&@*J!l`m?tu_dxhjcwhJhkT=Lp z`6QfwTpmqt2W~`g26%uQScmit?&UF%@1*<Er+`!3!TXT@kGPMo0`H}#xgUsvNp<rr zO%z}}+oqZpseO}zD_#G-+^#yV>R)GW&+iAFfj_A*hR>j~6`AXMt^woox9iOBGvjmV zFRIVc0q8n|`&{$5Ie=bh<q=d<sprqsnboVz@>QAF;t0~|1BI$@^-6!=uj^m`PWBqB z6Rou`pLzKxc6(U%{P%KSCv=^k`T~e9L>mv$UeQ3UDZQ`hx1NZXq|>2*_u+#5WLZG_ z*wZeC$XFm6=J`Hxyk!9EeGVe~+LCN(Khe`KGy~^{VJ^2lcc?gl^z@ser~eT>`nqhW zhfjIC_P3a>naX5G#>#Nv_=;%oJ6$ru$(Hr{(7=A*c5QmTuYZd@%OgFWQ+a=SywjKz z_w28xK3&IqWC#ByJo>40{#!Wp+Qft}oeZ#Taih=*5RO{?ifGZJZ-z>9-cp6@%a;24 z0PbymCN==ZuKQ#`>mVEboh_q<Ee<CG;hYai%lK%PG1lUsP34Ij`muTNz&s$K+e6gi z=XKz7Rd1qk+>(xQCNb(=)+2P-b?D{i^eC^y#$;aw%$xd1EP#2Nej~>`SsHd>0%UD= zEO8$UvFTmb=T+&eR5J&LGy~;zX8vkF5!M46`u#R0cm1xM=tF;RR1idjg+8l{{h}Dp zGiLROM8!`91glI)fE8Al!=8ISedfS-;r!Ow*+07uIL97EnlMwq_M{-Z$RbH82^oRH zoH~(39#b>gCCI<O+%f{nC1n=#ok!XL?6Tp$AqfdO)Hlfc%{z|wyY{f8;Xj8yFdpHb zDM~ERPNR&{GYmA!C~kQocs;mvRKqBvj55k7OO$bfyL%+M%<C^NBWoP{-A=5$WUqFS z<C<*{`;0EJex0;1<t*<1+ENM+^PD;ZdbdEFM0l643)5ZHq1;{dWR^pE+OOz1P6?0l z$PNs0)y<F4D^+-8w5KqD?WW`#1~X>NAo$OMclkE(wcwY$3h4*wPt%`3u*K(t`+)a? z&jsIv^)IY`F!=`XAM$GYW%&Jn`G=cl68`zWcj}F^Pr~{CQcAfEYya%eUWxC6|MAM- znf<Nr!0*5K`!8*O9_BxvKRgd1IedODk3jlMp5-OrMh>$dg2&mb$~`Zb=0gbH<`;Yg zf_H+iu};R6{wx{rJEYvOD1qSlMq4#`cvL_r67@N(Y*K~=Q~J!fKJx)_kOACD=W63D zVxrn?PRU>{iVc}aZ7O9OFDvT#<%ZToG2K&a3B{@;A+W7Rrdzpz3GhmAjfxXpm!1NC z7<?)C2)6J0!>xZj0;eDP-RJ)0H{s(SpI`sykHh4y_|+>`;8X9ce&Lg+Ao~0jFNW)o zzLXwF*Fk<aopKuZ8sFuYkiM1vmiK_i_&T>yY$ye%ImW9X9t$1{UI*^wLry~Qzu*Kf z0@pC*^FWktSA6A+?SgShXKqi_#?_P}g>X8j1imN5_EgTWF0G92=EhbDgr}Ag8Fa?> zDiixm+fK~ir++TT11dn7S>Xe!2Nz66c(d;&4sRq106*6I%<Ejt@on>=w)=#|W6751 znD@&C#>D!2x;<@3hTaRaF1oOU2+@*&pqJx1R_sW7UD)~mBAJrJ4%IL7tIKZ<(WBgQ zpo6H3uiF-5iXCnpzjOV`XTI-~Dt;*c(dA%k*YfzbYe@Hl3*CUsqPKqf*n^8<G3m`& zEgS7)DCT&xo>9k0S6>2yKJzExVTX&(D}3Vt(SZFzbnJ&+fadMxT`Uu0+{2&S54(y^ z2X*S@D;b^p^j{aC)AC*y6gica>)LveZ1E4VqrU#}9_g?j-%J_O`97ca>FWLTc&Kl? zRm<5<^x(^!FB|=1v;Da4lMZHa(ydPYDQp=RO(1pT;rC3Yc$>Y|0O^5n90ak&6zXwM zGc$|{P&Z2uIx-V9F}=6NOU-t*>EEUA*fQ@ImU)hJ{w^G`1z|0(E7MDP5X2sL4_n4J z*MWu5@%+Rnuc`l}H~><ue`K*Y?e{=kpQ`>8M8<)~#K@?b6L+i-s&{4a(7nu=02Aiv zL%?1nYrse8j9&q8B{N`_{)s81Gk(n!_-d*E?`Z~rpYkt?_+A!YO==k!WpjM07#BY4 z^fmf8v8VH#XeZ)0e&j*zG8tf<+Gjp)%SZvRV$45$*VEC0TK73fW%u~*aZ@_x4`IuF zwgWvK=k;k)Fu0HV+@lN-o*8A74ibExTR1Z6VUz_X7Nd-E;p}q+aE>y{C>KVeCHbLo z+}%C0n_D7W0N`;c>!nM->XU+cr}gP(x)eQX?4u_;vv<_<Act$?HTKkli-D*urF7E5 zRONcF&%u+XjjgVX8ZIWEwt26ap~-i{QFLHdF*lIvKB&48t#53U0N@;8n=yxPGh+(; z>%71z;N|pHJ^)_fyZjc?Cpo|e!0GfJP6LmL`?&>zU-7NrL-^E@KYMX<Cw%G?E4QcD z!S?@V`pRqz{&4RfPtG5N|KGp)_9OrOop8l}5dK0;;Lq>>)N7L!Sby`=kFI_m_Pi}_ z4xWSggYzfms}OvF2ZK8xiOxTN{v}ACN?+j}NGF_N6L^l(#K0*|vjV~U!58@qC1C$5 z9^!=77RUIIcQqZIWF`H85-5F&kAiPe0;{j)Iu4NmvFE^XuI3OhR}kq~S%^?cgkv65 z>`s}UPqD=o86&&|4iq8!Y|H5&2idQ+{58QLB=AD|9&Z5O<jZ^pIL&e1hRL@-`MFPA z3x9a>57$m_hS>|Vr#^lQ&Odklfn*MU{O%v0_|q#8Toe49U&7iqR+CSjh4ZhadxOuw zCyrhDohu|<@v}X@32p~I;-mEQz<qox_&o5L^bYw8;5NQT1i|%O%?9vQ)|i02UOpiY zK>E0NcF#SKewcob)4<R8T>1|1k9mxr0Q<N;{eX<ozRK=3SN1kn_9mHC>`xX9-&wmP z1yj2YSf@x$Tr#*<Kg&w+Upj#5(!$KHr#LoY*>mH$`h8U&AhlN3`)pngJ3zgBPu_=R z0|-a24=w(-S}yZBZXc5<#(B}3MKr5NV$@G`Do6MES8`d-iIZ`!VMpf4(ZI9&WwhIF zSO>&L#-591{o?}6Txk8uR=X4zR8OvXb+j~nh=uGU8sNQ)=rJ6yo}y#FwAoePgZ=Fp zrWOO{w$-=H2qu?e|4jh9W!P=FU_X`KO!cCX!P>Xnefs?nV6WJFJna{6>5~b;Pw(M^ z?Q0(o;+_X7WCP&Sum6b_CiG$ac-X-%)i>!;huwTojel9MYtv)cV;txMBsXg%JNls} zW_ZyuFBP5oo$wlG+x(L>#wp+UnGV49@oT;See<AS<ODp1MjX^NZxhz*+Vm58#xq@v z>7=iD*=^f=S0DlxK;6cyo*2Mqy}YvGCq(1CGAiOKp;2GiNK6zu4;F~V@z#~0M!!!O z^|y^1bpX3)^$Sf00;EyCxMrtSfUtR>BXrcSjgj6UPDx)-?|U(OV)`ORoH-Dc&t;~| zP!X2Iges0211pN)V}lh|AzJ(MoA=)cO#j97>^50u&nabw&pC6ZK*FAMuHuU?SK@`D zV0MQR=$`k6nTNNP)(9QeIN-%DZ2;@scEW*n!sCwGn=hDY*IY07j+5?jXQ@$uATP}q zy!9y>$K`lQjPj#g)-nd2N9pE&Z;;o?cLoXsjWWt8ql~fxj(Z&IN4Y>U&JQk}M3+>U zV+6|V{J4P%^bKQ2G6;92MJ{U{W7{CuP5#ry46_VBpJ=I(7ty~on0KO9W-B`o-It+j z(E|?dg9gp-Z`-hsJX@hHHFR65?a0b!)D9eQJvYM6L?jAEswxn8R-}I2W*hj3L)-$q z#k+ij4g{VT4BYu&3F+-T%)21IAH2`?z%PTlgAhJ-<j+3%#BH#;cV&P4EF@n#|LFPe zz}Ek;{o)^=gR}p$zdk#C4bJ}ie|`Nl0uBIQf=@rXdc$N6*SvD|kN(z;aQ2aNFKq3H zKR)xv+h?~z__aM>3}1pPZVK-f_kjGi{N?#mAife@7esLW1$kd8A^1`70Cxb-r(0YL zgz4@4K-FRc_#EF3jsPF>LHa(~fq__QE87@}R6sx92#VC^p(q&I^XuopL_yx?>iV;4 zL*@tv*Z>kvkN^>@9E9L2TpL^u>38{A`b(I+^NIUDaVPx#*!IR0SpV#&kFEX|j=%cP zr+@htocs0G&;D>V{BiQfc=j8Rht6Mj{zLf0YJ7Y2Cait$Q$Jrx;L1m?c>ap3;p4BJ zkL54mk1u_E@ci8nyv>_z13%}>Y(RQf`W1dc29#c*WIp;VH*pZy2yWym01oI(=;>N| zAiW8K=fpjH57^@6;M)-V{osw@RbYScrC@_B74f9fPjcq=%zmco;J`ecsSE;n%Ha~Q zE{)ISlS;t3ZqErN<Gaup+9f4mKHr#1ioQ_-;Hv=j5<s2<)Aj4idPygvdi8sgAzt?& z_4kx>13Lg7$Ni?v9nbNf4@%=rUB|3Ml|wka=`!Xk;xYrekMW1yIY0GXFJ6l6R|UG5 z^Y+~xwMZ7sIJ7)_9EK5i8Tt_emaDx#iq86MUPsD~&kF}@{~>{(eb%S>^TnWcT5YFj zY5k)8K+0n8a{&qa9VqDnnC_#uzT;S%KXb<gWlsk6Vd6A8Fj6k$Azb5Db6myueR4rN zZL@n*-@bKkk59D4dqkt3jT`hKdbCHlpg)WTipO;&Brx^WmBBs<sumNc(k~tth)&~8 z+dMQjH0Qft5IQ-!arjric^KFM#%<%i2@rOb$G6|g8X#CY2|7f>dcda7Dv;U1EKe0E z?$WDh$xsnG%Bhb>KWorWtkuJ&52+mlXd8c;%3a23?aymxy0^z)U3Ou{Q_Z-(wAiii z^gA|yd!jK_w*l|<0}Z-8>H3be10ziUdIQ)VDE+2N-+`$4<FKe#RWDyCo}WKAEbb_Q z?i0o2p2t%+SY-m-#!9dXoMFxv0l_v?vUqit?Qy1n?pLY|kTQ!WYVm0(2^vhoi)LR^ z{<~`&DJ<e$J0tOe_e)QI+@z~;q4#&6r-e&+ZeEYB^MV!Q@60joxDH+=s$V1>=dZ3z z0+WXEsmp=ZQAQc4D~>WsIiVnUpWlqmXOvM!8Repp3+1Py%Uthyiph~-dz4WYUv&(% zVu`?UQvTBGr(#!?<=u|{Gc?*?UR3pMDw~bzZCT@ITR=^;*nd2beq9@uv1j>Z3uAB8 z;v;lDhaPs-wxQ-`n(||m>&xdBIhb?WN)j4xbO8rMYxzw^AbY(;14EIGNh$}dh6SK_ zrh@TPwt$Gc`8qIR!URZIAtGbs&dL)P^~`|anZ0bKTbu#Dp@7{l1TS(ch|dK_f^~?v z;%DLO@E2>J{_US#1M=_4sXPS9ch8@e&%>77KK#eK;oObCKQetC{=wh;udn?_zl7j? zFymSfUktt$yaoFo+k4liV>q~P|N7<>e)rY0U-{h!z-PFX3CMkXpF3gl(@&iK#5*uO z_Qz}f_yq{B3!m6?6UZN=zfLD0L;3CW9EkVC6XKf?+=1X;I6sr$m4|^x_#xkcD}NEa z8h#IWpYH}MAP>v$$QkT;N_;3j10RRUUCEtr#Y0!T6-FRKd0YAr#J{+5Bl;G^XW}nh z`6Tcg-c3J(=^fK^vk=Zc^VhHa{xSIY*vF406F7J3uYdZ7C*cpjnBMotd*Cl0ICJ!O zkAXNLLh&$s>N_hpe&Pf8<bhB8VD%humN`$tl|PSO3h#qpogZ-vaE5a{0)*@*hG4?$ z!M7lMeb2XoeZWmz%{p+JZ3QgP+HcA>TfkXPvkiQ}ha3Y=a+=qG71p^IIK!4=ypMxh zK)fv;3GRmAm%&MX0Nl@v_koF#5;zBjZ>#T<bfy5^a|QfP3LtuBuO)N4Zn@j)bEGl6 zLkZ;0KhM;^LIbcKYE0^Rxv+fJna``Kj;nz0CLnyZPbY<cw)J@zkX$$z&_%;_k|scT z^M>8r;s3*qK=+x$OLy5Y90K@0bIx;j=fTvZ_vk<O8t2D(_j2v6>wH^p`95WgcX4~j zh3vUL58R1$NSA{KvS+z{>mhrVtIN8iOF7&0B$r@6ivVQB5`04mL`r(sS9H*u3qU3Z zsE-Mll^x?jqC@#z*Tg;aCh5<t?azEHdiM9`_LYPAL;HHKt8K`Zb}a3E-mCpx^P4^g z1iIRp>=@q>*7j<a*t2|zK^)-gho!Sz-GFHmhfT^38Jg@F>bl!NTLwCxc9%U4&NTUt zu9*|eI9qHfr|{_iX8SrB($i_{%0^hqAr)6~TR->BSRgHNvM&B5Y^i_k{-B+>!!}aM z!p>xCoU+=VrC}%bBNdSaXx`*E!j^Hcd~VpNZx^$;Ip22qrNm<Q)$81VZ6A9nf#;&; z@1!L@TAyDv*IQ>I)^p{V86Hf)Xgza{T@U5~g4p73rFA}N`Zs(1MJ=vumeXE-o4#{E zx!s=$BVts>i%sTyNj;N~I*^hcQ=d;|*Q6)3Oa?+5*CHe1LTF?(2#c1=YO<1D7li6_ zq{_LiO0b%Fu6?V2<3IZI6*wQC{rvVVz?K5KZ!3WNl$046%}5?O)Cn^3IAK^LqDUN3 z6#Mtvwf@|nKw)R%3}T??gbUtZ%@}N!tIVX)O)E()Q$%z@_a(an>iw>6TOZ}~y6J-D z8;O)h=^-P)eUwg;KF0GrKk8wWQAW8;WSm%yvdEY@j+c5ML|&Hl9vKWTZ|S-~@7qr< zMmyUL<7?EjG`k`2(!{8;EHO6}CJX8%F_?Lxjw#&}XNpMKQl2WqPTPBv7G}iQS^ut# z?0zX5eHg<+%8g&?U|=e*m4zP>4f+m^4GxnjC3G-3sg0mO=_xgTFPX8WV!p`$?&lOR z{oiGi4PY<ptO8pFka%8!3g?X9Nx_v<{X5IbmOjIq%s|}79c%(Kj<F4UzOiRjtiztY zdv4nE25dg_=l5T+0-Q}BN$-Y_XUR{`zYKr;zt3KohmfS_A3A>n{MFUJ`|j^QfZred z{hQk_Lv+iYyMoWd`Cp&kK7SR=?@WFyflq$xlUtKDkUve2$!|mWIdM?z1^Gn!aQY1h zzp!V%=LBqi_!sYf`Vlz&(3#`EdlB}9d)NNr`@lUM=Wh7x*Z%rDzyA)L|E2um`48bQ z&i?s3pZ*1$nf%qm=bnf8cRt=sUWM~7oxkDy)4=uI7JLtar-Ijmk096x_VXP4;TO|8 z{+Iw8{5tp&q#v=$>u|-l!YB4j;ZukH?9}9Ln4I~<N6`%+9tpl3JOtsF!;iwJf#32T zcR}!W@ES)TxRv*L1vr?#pWX@lEO?n1cmk1T`k(VFN{0SKF{UR5le*0Qra1%p*Ezvy z;DhuO=YZ?ET3Jih`qy%VgAhE$J?h}Y_c#sd%jv5;3!LF@ZX!Dnq4&9YkpUq4yB!>^ zl&7?td12T3MpX$Xo7cYA80Ixbb_)Bf0^RG^l|7{d*5`d@R`k830vs0xustcZ*F@!h z6S%IYOl|^{nN04bZ>Vn6&5ftn;40PYX}#X%lWflswfA@5z{?r*#Xw{A<+%ddnR)Z& zw4RjsZM=%hu>HGa&e<Jy=LazATc1VkVNvfl<o5oMgb{t$OUur`(RQGCkxX`d4ivbU zP5YO@-h!cLy%zNg-49H(0Wd;mJ1%0WvSa^?y6PurX1H#$%VzzEh4k8Xa6~TXKVr{* zBzk(9zWEb;Gh>7c*i)1L?4MyTY`osLzxgs^$DVPduKum7-;9fOTiDAE+uGB&AD2M9 zZsnH_V6acTv28x$n-S5^e+`?NuxVb>Oax;7dbsg^{h)(ihRQmRe48Ex{s-+s{4#db znYo+$Rog+cuqB=;je|vwxS@p*q~4xQ%=WVQ-9Ap68ByAp`a_FF2;9KfJpSqEC#iZ* z?RQiEdYsnuM>gj6vfYKF|I~rKdK_LFrH!;$hHkN;h4Eid1;7i7A2;=G#*ZVd-GpVF z)vwe0zgh3d@L!=}4^eSIBb$ldq>gk%iphOdF}bg(_~9C>M6hRV{iDBq6q5O0O^@#* z%Q!j(5(RMIQh@iFigT{2IN@B&_~?pbB?GQQrnHgaT$-5$eF5tI59G_1eWAo_T$U}L zyUq{h9cH3F2O-OSo9ycQXx>+Yv}GN(^YMdGE*lv^H=}fugKV-ss$rB-Mj2(40c4!I zUOaNCGV+fM`(wY{js2-D#qPLj?Q7d&$8@<9OpehK-)BpStt99QL^mWg>Jjv1YILO# z*87cb>iDJ&7+b2}KI2K$tXF4ABcsIa%>2H<_vVz=p@lJC-#7>x^qeze={nx8Hgc{q z>M09Aa0bbpGG_*Cv&9tBKk^!H17G89P5{5*S>6Ud$9=2-r`Tc}ILBG$z?S-Zk~1nr z>^3vteU7tD39vp(q(H~n2E=K_1pX_|rYC{hxHfngI1{`d{0gFbuJ}^87oyj%crknn zxQF}FmtfEKp6i1fA$l}i5ibD`q|eFEfPDV^x8={^Pe1+m*7MtN{#p4W`91jK!9UIA z7h%5d<2RFc;p61|1Lr>idGh?r>HF~42Y>(4^iBwV61>I>aBg$!hsW*!j_{e_5eV)I ze##F)d_{a1JP&8?KKsMpe;<N}cz~}#7=@4Sc^~30Ub*jzS0Vjr`cnEV#7E;tqL(4O zRy-+w1Aq4RC)eW}fOD(|Cm=i;-m~Wjq|frJ^ce`g!3tZzDYiKS=`Yj0d=dCHZ?Or% zz3k06+tOch0=O}_C;bQ@$Xfa&k8>P2$Z8M*Hw9Ov&jP17P6+9N^!t1Oth3HK1Sj|< zbJf4*5UjG71CTz(^&9}Ug6r51#Oz}g#9@($A3!h(J`5sANpF+S0#ByD=04yb@dHi( z-)EE0lcgZmederSR?0S>Cdv+G>a#31qLK=LT@=7_SxGURI6e!*zULL&*N<U{%JT^} zfci$5#M}@|D!+>gk68Ks{P$U<m+H@{GP|2s%nQHJ23WUm+|~S4T4k!o(2Lu@RRQ|* z&SRU4DNA_0-~T=1%xzrP?Pfi7KUlbodF;ioJ`+1=XNv;uYfQ?4xFB}b);||v`X8c3 z$$|$W7WF{B{a~mA%zf=O?rEQkGTMg&*UMGzc**|B^s|eWw@sVv_PgGxJzV+-2g+d4 z1{CfN;2kOs*Z*LR4!rAPx7`Ras4(Bk9t`wN{jM!O(ADom3;OfKkvXER-!uXH`@Gj> zM{PjfzJ9i=AB{ZA?Yckoj7z!vMA)&%)Z?16*Z9&#G$GsONgn#v8M}S$BcvU$Xs<`; z^lvV}uS-v^10pVlaof7URh~8gee8%InnWLM@zBVA;4Y{G&NHTO8*p5YkcQ59Z~Z`x zjZj4&&xK{aX4>_t_IB<1U|n6mQrz!mV7IlKti@x6)gPGOhhPQ9>i~bzQjVtb=}hXv zGESMm^Vled4tzI(`TBE8eafOgGy&p6t)zl7UM|%4LdC6P!XN}DtPlgML`;AcR@qSB zuc~;m&fq>HV5Z`7GZk6Nh+CuruS=b9rHJ3nRb(nE;(^U`nQ%$KbX|MPguYL9U@a;Z znE!R12k7%zX?*UIF}Lfyd8mW=(&4vc&)kx_UkQ8MH_9kIWCXa6(n-?O;dkR>7h%Ci zM>)zUqwE&hDWLGUtv<>qyIGdC!F8$n&E2Yn3p2yqjQ|lJJ%kr{WNJ!%yb~I2PiZ@J zd&^z`0_hC>XY0XJ9p^jd^UfOU%Tq0OBs$t#$;{%LGP}M3+w}aTg#pV4Sl<Q!axs0m zQpxHYCOPAVBd{8T8sm?wGpYx%qa68rMC*oL=(x{S4|L}Bbfy@zx7cF)7{T6jWxfim z@pk%Nc5m<^XuR(^ptcGW&Ka(!2Jl$cfXGSlr2Gjw6Z}bL>;sOl!5QE*Q}zMZu*wz$ zKjiV?4oE+jUdPYj3bE%idp3cu?0IC*>#*mU@RjgGkTQKay$(Kk`zPk{1He3ZCwLf` z@hZOnR`~|UKu+Zi@;e}YA#M@B1a9U-?t<X!!6U)@AU`V~Pp^Y;|DG=e$AMef;tt>o z!CLTT;AReTJp^Cii<|+j<7OlT_XhU{F9Ihx%xw@HW}W+hH6;5WeV<dj1HrZ28r%r{ zfH%@N02Finvpma3l)&Bm;6UyjrfP#H-*B228$MYwbHSA7r~<|{#&(Utol5)M!wp;w zY;Yr20l(&`dcQzI@Bk0+6%Y@L4}(L%w}MxB5X8S3{4jV3f-mz^t_31ugTXy10PZ=k zT?e>}Vk4@`&|WgRCx!h<tv+*1=5@Q>Q9P@(Ux^NMmr9RRfbTjGUH~%#7;h$m76t=+ zqHSAgV^5kGOzdS}tpm|z!?-@v`na?_r?@}3LzTxqPKO>_N;+WQ_MR?l;>0<(={9c} z8QXX3Z2j_BPYtyyxtMl}#1ixo_k7=?Vs4Q4XB5um_CeNfa&U%Xe|<NVM=r^Zq8;jI zo?>D66ie+lXzK`lUC?K2?NW|9!?0|%udZ>E>cQxR4s3e^K>8jil0CV>+YUxF#Y6hW zbHoDi3fbZpWKZC&+aHOgjC0Zf;2f$yxZ*7S<BRahNVn*Gqm6)ohB$*?KXTi%=+HlW z`mgZ(O)Sv9QLR79mN=B3KdS@&!^R#Mx3s5h^$YFx(F{Bkz3d|FcpyV~mdotVlNP%) z?I~<+N8#)zzRc^@_qScwMr`3Xzi4Bs&+RO#ae<fiD;n%I@6WO0zFfXs;Vdui5AIXn z-si{!(8e(DvZt`2-Shf3^|$=@dIr<_{7zbaw`5=l%nS>{@GG|1gzI2J9oR37_gA%& z1I`oUKGQpue%qe;LpXu?RsEXG`$GF%)ngR^Z!*4{c90XYl;sFHLdM{pWrmz6pnIGF z-GfzD;mVDT^#iLwa`J!qS7(9k0^mL`{?1hdZLT6@dVD#L&ou$oUE`XK;KAjicPcKm zTXA=ZVc)*%(y-Q_mlGTD$v_ge%mezYVoW`(Sga)U&}*5`bQpmAD5ESC_8MgrA8&Xx zcs#gs)Wbz1(Kwupa;Z3<Q3a!nvLhnLx#2EfqK`BF(F&F^U(D-!p~qV>P`fRs9&vAg zhghm!rFVZ9gX%3BxPGGN26pKAeixINFY}gVBROc=2nz8_HLO41hmoy`F-ZXLtFj%# z&OCHf(;E<cWIXSK7JY^dDTVWTG%*aB_0t*LB?KR;jeu>o(rw_Cl;C>c*Q!p}aSJDb zLwv|nWT{`z0W&77kpbfc@FDwI0alqJfLpkZgTS0AGvG~?l6Iyb$$M3%x<oO&&)DKL z8BlwwO1cF=!ZrkJYOCaNHkd;2Ah#$Rc{4Z!GLiSm0}#xau@};xrJv;u;C5a>g7{AG zZEh}AlFrk8%s?dKP4OtO%Dwy$c$3$73%HS+`5cHd;y1w^z-`2wB?D^Df$cQgIC+s7 zuLH+|?=b~F;5W>H6FkB_lz?)<j1Pdbnf}w`e3-sZv0)TE!IU#vzdXU|0^pu+Dor$d zJe9uBJ7@<Sf)@bz4exOZxF!9NIdCl@2O+p2_$lXrjf}ya7t(X-6j)~-tV4R5w|EWs zDen>jFY-KZ0n>DweZcEH&KH4wOt}i=OY&B(hV)SS7H1*(p}bjM3+cPec^g<EtZd%R z3PvTRzXHfUQ=sxh0jR47A7sJcUIOuTz<XGH&Ll~b%I8qo`&<LSXHOTEjjkC~0P-fU zdj9^<0H)81_vGcwH~JE*&(DGFU$6Zp4WOlc<e58wQs(;-C!ngC@qO+b6B4g6(FKz) znDQ5xt(bam2EvSSxr=#z9<!Vc;>+zIb6>!wdp;t2_1)bXFNp@XC$Us}?YrNwQ}HG@ zBW!=b{*dh}TYy&i{P2N+>^mudLelFw-&F7a>OlRZJHXqIIk?Gh_jzB}@ue%%z71gR z2e@f&??sus;}*Ladc+Pr;u8J(ndk|8_bYugfIslDvnc2W5MGqQUiPpj;SncGIs(x1 z>ugNYUD_?~m^r~!KCyuP3l?Xx_hqp6^<!acJNO+Si#_c{w)oAYGgG}UK)v11hy}(; zQ_pd0KMY&vQNqLT#-8n5GL46g^^G**izfYqsvp<=MD@r})G|JW&Vv|LruHVn4c(4y z{X_p=)cm$RLuJ_DzidqS(!mIC{vKHX=(-+V`!F$8M)Z1nkiLU$AHYsD64jW}>*W`X z<DH!ezOMf&u)KV>sEyNRy)6e20;9jDsyzbr{#2DWuravXK1<{MiNWALQP&BT`7ve^ z#J~nIF%YFcVFlP=jWsd`_l(g!P_esdL6|Yq<FqQKRmKVH^FV2}zmf`Lu{lTL_<p|h zeJauOzR-W2v{dnZZ#cm7;vLd^)A%NO)<Z0ylTk)lKt?kgrIQ5TOm6zqcSk*pGRi2U zTr@Ifuo!;fGRi1@B^vunqa<T5T#EjeZFiUII1}~I!%k|#6}XCewo7+_yIAP{+>R3q z(~n<yn;C+d?6he^BL7`F0`a<h*Yf-}=C;JyZp~prTk720Z+2y35}*>W+R7oF&&^Z3 zHhBQyD35e(d?f{NI0Mv9)0|0r%A*J2{~&(CyTC1cgByW!JY8YHu4<^NXQ(o~=RjeT zQ9B1P>&)Vb23*enYAI&Zc?OIRUI|X~V+f7}r-H|Tw-r!2XYNU~zcX~Elew{xIj;br zr|NyOU^<^GM)bL278lIP0Q;G~W);SusrEUcOr@LGXNqJ-32>e&;6DW;`;@6>g)_F* zXQ7zGXB9^OoUtfTJ$k0}z0Emhz&Z6-vT6Xv(LU9g&L86Eyb9^F=@aR1fk%NaYWLmC zU3?Ze60GwC@ETu9-v#k+2O)FdHyq_gAXZFFB|tpW!*<@T>8xm{TtC%vN`uKgN%ikd z=Jwpq5{_4Z=t;q}UInTrh9#Ro_YxSN_nl^-dtx%C8{eA%ZP~)$K6CW6e8Vh%-rNZ% zlolUbXJB_-Z}-tQ2CIGy?(>?jU1oyjQAWAg;z?nrb;yNW?}~-$*&W#0cmBH@)?e{J z>w#sj3w_rI{*1MY*;9Oh^x&#*wBUOeZSQD6Mtz@k+|d5TwT_AgD(~>|hJHZ&*t4CJ zj{d&>9%%*S^@;QOj5D$afV#>4qYi#UbhNWh?VWzq(m(x}orm(<Vdwe_ueo^aj1RRx zy@_Gj1h{(i!@w7??Z*_qXvS7ML4dEFwduF*KJd##;FD=U^tjJu&uu{LE^*K%0B)PU zU2(Lwcw*QJoDZEDWkf^V(QNNF`>pFqI_=m;?`=dSE@t#5zi2x^ppR4LK>^WV|2}ce zrh{0LI^e&lyiJ58wtkTVwT-xTYB0VBwu1}R`iD-vo8P;}X@UJ9h0d&>SeVys`ga{T z6D<JrydUh>>MJ0)TK#@N0o@O2pY!>LFzh1-`0ED?%=hI??j^H(L<CHT(ysxLVsc+& z!h|fp<tpsE=5MU7ufh5E&R+NXDR7P{+rW03#b+n{{VX0^#J8_1B7AzBId6@yh$#Av z9k!l(AtPAk!Ge{J^S#`DlNL|uTHlrT+YhFgeo(iQMdp!h<FRZ$uoT2;Hg7)4KW?30 z`;4!?^9=v>?C|Spp^b+l4ag`9xt&o)=^|U48KFm`j54r{0OV0Fbr~&u=Or3duq$P@ z%lhRADBpekPVAuF?Z)|sSWy2%21lkXYvr8+v_y_n;JGAA0&ui3XH9#yn=25PH0W6u zGf+QoX%8J(-3CNx+9;j1^dIy2bIWx$V0~WhS<6OsSq^jK!UT4^n0t)!q-Tu4q8spT zrk=0rDQvYZVc3n%B$OC|%_-*;Kzf@Hc!n3!H-V#Uq(^}F_;K(Q@N@3v8eql>Yrshb zB;Mj20B1O-0M=6^@D}fLf)a>5<!Y`b19E5gO%-5#Rsgaypz};^Jgl&(+HVG&QP+RK zSwcu(<R~$uFYpckM}r@6n3BQg43Ac9e8!A(TDwe{RyH^eagak~4B`@agV*_p4CtPL znm3B}%$c||0DQJl5-Xs#P}d*h1g9uBQr0+B3FuGM#!W7pY_O(UFuU%Q0<dT8ca|-c zt~>j6McGN-4^DFi2^`=$V&EpOA_T4u*4cveR_2^0V{iw8n7b6S5zHZ2=O9-@dIQ%X zfSb6UgTQ*Q!7A`!`Yl2TJ_w!*9)@5a&+;gU!{W>0ItacV+z~ttY;u}?lp9ky5Ion@ zYJLD9*sJO{FE*Sq0Cma0t^?kaGzs=oJrJP-^UL>?2P)96E1BD?Ozk>g9j*OCXaumE zeB_}5;Ol_%DsbNXURL~8*?;Xod6R+OB|7uGPwHgXwq9F`Wg8G5&oQO?oWu$ISoY>i z(*c7^Ij%LXM0T=$?98aczh`-=sh4Rl@h({}4Fxz}_IrHWtBFZ=xA-T~Lw|kkwXZ$( zjWZ-2fqU-$AwAzW3_v()onM537^L4z?{bR;>>%tpqWkvKlKECFR9+jCx9sFE>6BTm zO~2ui`d8P3Dt-NB)S+MYX}30}<34j?TfC(&k-=~WQ^L;k7y%?f*lNFdz4o=VlaIfu z>&gCpH{eV*#;1J8f7#RTi{5^tnZeste~*lb&i*4B`m>AvqMe9Bv@+~wzi$-dMpH(P zxPdsrxBrR8aV0bktlKmBge}iWYV{OeelTi?BMM`DwfpxftklI2AK97A1JMBBw&~Bs zyl&PnZn1~B#jcVb<;vo3mFESUhX35O)Wi0ixYoX5t&g`6t~AAaW$_H*ozYX*yIxM) zzNG$Kvpr0G>i0*MamV)joasI`G8l-0c|THs_ngT+Bg$AMW&*6TqB4c9u?l<cUO)G@ z=fLbQw@+tr=8RZm&bA^PnJNO3oQQ-<{4i&BpK5VkS!u7t(Qg7X{<kaQ4U;9U-(4B? z+Sez-b6gpAWg7ct8ZHh@{rCFU#Q~QOJZoZ>e`5H$xaWLu*>RY7j0TRf=;C0MQGC}c zpWE|N^ysLEQAQbMl#ADqU!wJj#tHE#qwM%Xba8)lVM-N^?XaucE!^epGj#n;hLoY( zMGnv(`W%RHF~xP=aMJ_fT~c#f80G^X2AOvM;g=%24CJ>nHJR<;V*K%8YP4;1_%d7R zjNGnv2|F-2*_e*X4b4z}pHu?*GZpyXW}DeD`2VCI%nk#mc!4co?}9Vg!~h!Wn#!4d zOon&R8Lo3ib%})Zy7a3&1>DGOJPSO`14NbQC$)`=yd)X(x2U{7DS*!9+qCyF(-__7 zlz?@`D33%cpnlFQo)paCRVMmGZGq$f?RjNOq+}E-KTArW%bbK6CF7A)@1Lu!&YanN zqVyRCp=$TlqCR>b()F&(=eV8&5ZuZ2!G2&J(!-@cN;lI3=}izk7krsb;PdQb9r)My zEQcU?n45VP5NczptlzBAkG|oQ>mk?stlHkC9)bsJc4D@({#n+5?Xtq$ZUWqe!L&ZN zSgWk~pzKNWVuLOTo}&uPwlT+-eKj$xQ`Ek%0@1Mo+)eK=H|p0k#^}$RbsU{T1L8mH z#CPe(*luHtA8KtbM((1{^Q&>?zufiEa#NOvgY}(dNZdMaqjvCbH%0K`j{Rz<fbM2_ zq6^&qvL|EhQ0q%y`-vL!6)nI2^#w97>d$@FPtOiuH*w2>?xFmmjbU{e<7Yf@zjn1_ zJdhue&UNE*<`J%pXhX++!Ug(==-4j>-40^<GUE?n|31w1UE*);gazj3?>O`)JQ>kx z0X#Qnu<+HR3$X8d@Fw=`S540l9%GC<gJkISKH1Q&UE*tcKWGAYx5d$PI~AV&4g3#| zMIHNl=-F<Gr@zmcu-*1mXFL}kb{JYCkh*`B#u`7g9Nlood1ax$=6L0UwfegN{h`qw z)$65YU1Y|;T|jHS|C-F<X!Vfx`EXzY?tPfzUBGhP?(7)^s^6RAp>zPjoBW0TT^$Ht z1>!dW;B~vo?Jc&{!xpa&YvmSNY^m;NbcSymz&(#|M(W970dUU%@2kNotH6X+Rv_5S zfbRT^|0^qG1S?y>S>_7po-ie2XrHS{m6jQlJYF0XnI5YQ?K2}@R>r%^IGEkHTpaPG zz6bAP%|9*o0KD{`zxW)$i&~!7who<ioKG#XuC?tWMYVO>o-WS|^7~gU`)Z?%(qp+b z$|&9voC;nGo*nhD@PIJNDCWX&lu<?*Wt8DWj&t0l$TAuK#AufTJpbZr_eJbuH}vx% zfDm#?OpC6K+aWSH*aBUPGLeNn8UKX0y$GJA9jIYT`D)X@)HZT5eM@Kix)|x2HsDPC znkkEAt$d-ioRM?GsQo^>euPo3X67JiFu;e#XB}9Y0NXjEHrq^r&!@L?9q<|xJ_0sb zV*<pggpv9y)L*IIJTX$wZm`KZkT7LNwqX&H1;n$IvDwB$&bSVeEmf*1u*L?5fNdsB zA=t+O4genzu|~#tz6$JRlMr|=eV_L!8R7Ty!-}2`bBMdN*8UK|CUt;!zJavLI(vag zl`l~}E-CbvunkZg5IDyfO2+y%*0_NZn7&HP8LfS`IL!&l4Wk6fs`hz{?esL|#!rk0 z4xuwAWg9f*24A9>^0W8nDOeA(pH1KcrkquJ6Of)|n*@S&BIb~8bB=A`o1A0|IK>$S zs-6*%rMykZQUOblFQ*e8h4g@YER~S{Z_^jK5je^!uaYq@>9VaL<B8g4nic^4qyUUd zP`vsUfIB7dyvp336u@;Iu&?Yq&4J-bk&4(3Y|okBLjwqp1^8aw*suOh0cfv&FSI^a zwKr*HYS(|a$y|$T$cDMetk^)5g>6fZv2X6&xT6&UC$#qHGRE{_R9^-Few3Y^^Iq6> z)`ixoSc-mkD&tX`UTw^latG{h==w)X0N~02>R~cH$Bqmj%Z>*mHI7LC{w4?RN50P$ zEKb<bmFd^EF6nABav-~x*cnmVtfC7ua@zr6xj;W@V^Hl=-nL#MJ;n{$A@bk?(#9S7 zr(7V;5qavj?YRzp2C==Isq9!zN4bK?*+;_8eok8Zr~4pA7rmL+M+?}0lO4sDgE>Cs zG2<(_OdR8hD?ZbvKUaNx{C9KwFKpGP^oTF{wr5n>nHv}_8~dH`(rewWMUi1lbg+}Q z42W*K5QhHTaVXh1&e-Exu5yPh{?}Gs8{oF79VJ*tZ@Ybl&bXsA;=L+fQ;gNZajjWT z+1OsfI0zxEwxa`@ZS{zYc!;RYDVmth%l5A`zDpxcskcXB8J8vXgAJuUi^?3wR$fuj zUufi{blZdReJZVfGy}f7<}Hz-FSIx-*Z}xw5OP~z7tRcz((v#30R~AmelCspa&A}B zXrCsg`>^G+`F(z{O9%9unM)=5L5iwf#*T7HA{E!9h&Q9+%>e7^ai+iuD+owm4b})@ zV}0+x`>#as`>hkVp4$cvsCagwnB2Ei#?85kY|RV6dzBC+2dr-!_B5}>iKV)(3WQ(I z>S~zvk?1f#tdB#v2Ml(!+)0mloNFHKs;6b-FXol+X#L4YPkR4aU|n1A%71YIJF*aE zrFpxrG2$ghSy)E!&nTTFP3F)2@rh9nql_}}L}`>!cEdtroLG)BivJ9Hr(hLgSM~Q1 zxU+Mz7(-az&cm$rl8dbV{riRJwNk!N{UTA!BBta4wCx^#!77df@KF(1?&??UDQLr% zmhokftLv%CC?y*hvg{k^)eT5jznX)Uv0b(>TD37d&2Vp&33P^JJFq3c-vmU>jQ5%w zl=|;BX0SPKz`Ncr%ngHC@mZ+ySDCMqB6aJO=|R%}NSx(P;8q^s#)_>~8E&eZEOmgY z4iuJFo0qNrPrENw<qg(@tJw>DjXMi~`q_%*l)z<kV=)Inn=C#0##5p($S2x!>kRYQ z80IUbNQ_z}R2k~^&j~uacy_hEaVQIDeOPSeOYJQf+k8oJUj^`80IKu<Ono2cG+U4! z=Tv$YxB>XAcFle^nSc<%OTitGKE}i8FCq9}2X_$z_wpX^0WqOsoR`X8LuF@KJ@VgY z1@nEjAuv%T&FyBcZD8u(OU;iY=$Qg2-Y6khF__%vhCQ2pAkmn~GrOyL=hf_QS~9W= z<GI=2m4Y9ty1|-npv?>~mAA`8dmhx8)?MSFi?MxzxgqX5pN=Z!P8OVphsHsIzH@0) zRyxj@W-X(p;L>I@+Nt<Me2Hl>S>j&K#S{;U@ng8WSY&AC+zY=>5=$+A8$<1~Gd%V^ zpd1a<Px~@UM?Kpl8R%d|8zX(!_=Rg6nOON^hZ%P)z~<BkNYantymDY8h*<Q%NR|P~ zq32)-26!L)v>k{Po%GRM&e$^ltgcT&fMC*dd^GKNW#IAI9N*gdg>QTH<vDF))V9ZC zx*fQ&0Wy8!M=tA;H9KfNxZkcfJZ9|e?GV@eQTtQ-GJ`j@U)b${h^4(3%M2rW`jObv z4qOL-eA?X>_ewnY?M07yT-a$QrDsGGjs3BW5x?mmmMhbU&P*&FK>xTwzrxcyh(`Mq z2J?HBi9NE+TTDh}y?&8pooLoyXQY=7CVQ#D-F+C?Wd)XQt$%vX;U`Ty6Bhqs#<fF@ zque}5ARPLaj&>6kYYqtmfjho$V~n@yL9dUk9HRDnXdU0om~dqDo2bFA^w>+NT^}kt z2vyuJCL<o%21sXY14*#PHn7DO8^Bq%*#f3)r`y1kEuJAGRLO}|@`&MFi~G&Am}scQ zt@5(z@hjOeezc5;NZ*W3dWPMfG|aE`{+!wGc|?bKPqN?v;ClZE2YHUWe(m*Y+Lv<a zJ1L^}!>qHU!+%KpGXak>%7QWi+(+pqYeB|LHp(cYbeRZ@1NbPTj55kH7J%c7d>pSv zJL)b`!-mGFw<aBkU2T`<MnpW=^EV6oux(gGJ?q!!IaxhjOy{l*1h?O9V-RU(G#9P@ zJjBghWY)V4s3RIUJF>vHu(BtWWf9K1Z5uzPT}2(+(Z=|0`#dk+lLLzr#h9~A2t3Ji z{1(!ec%4;9MfwWw03Y%gF>sQz#K0L&lK@*86FBFX69QZ6?^|R{JKG9Ce@69?se<-y zt8Ik2f}CzCOPi^`E3C3tX)<HtnIj>6K7EJNknT$-yank>I!WII9tm#ar@&05p#6Yv z7T^bfH+haz70vCd=sseNb+QeVjA6cH9M6Eqd)4(b)!%2uMoGRwf(FEYozt9F_h<S& zpbkHj0Czp*?@ink+(fyN^c?S}M>S7)Mm;Al&jweKF}i0V|1(T^7dXH=69{hMFzdh_ z+{gxSB)x<8fOR(60N&z<oPu;tlAZ##i1;ON9f#S3;FjQq-~e!t{proXDdpp?W`#Kf zF9kmd9s==5a9i+M2>y%U{@|;?ln3};QA6F{W~#k&ruLjaX|ArGSD26z4f?MGtabQ# z4pfH>xLj(MbZ!9q%fkcORa)OM0o;jdpKa}T3F#U2`_ur;m;JuZ2(OC^kUp>ZA3GGi z1n?(~K0m3z+U<U%`u?PrsY7~>H4?vrc`k-_(eT{aK-+>Q!~W$RD_g!y2by*59zuZm zu56Fk0U#S<eQGP$c8~H7*?!>;+KpVodtz-K=;vSMjxxl{V*V+6J%4*iEnEU-`qh8h zbDiXRUffaFQ_tQ}x2L%yuF$O?PA%&>mw)pCikfxKfh^Mn?a{UFNh-Og%6Zs1`Z06o zKrbJCNU(z5nt?@CX4U-qsl7eZvn}P7E$ipFVGh<sKZ$c)Jg>zK{FtXj<2c%v5nt9; z*j@)619#@Pu;?cy)4YfNf~dBB=pJdd9~h90jPx^aeN`EBUHaa}m)YAs|Hx(Lv<qRZ zm)h;r=4V{j#b5=9&Kmrm@bIr~nL4DU-CX0mPd!5iuy^YDoN$4I4$>0OoEguTEr9kZ z?F{c`1{G=CCq3eb`E}b30Q@S0yl{@ICO}#?JWo2}lvC&RVTF)m>KHF{KPwEqxZ;08 zi#M2n=15!j3d0_4jN5fRxPO;goYS<+Tz_VJ)(JSO&kvbbuHQD=tBh;bIn!;7{3Wnk zS_utGJ%kR%eWAsc%lhcd^m#dj7J1Q`^mVF($l@3B?`_Qbp(B!9emhUqeSzzMh_3Hx zjaj{#86c_w@vC}>4LeI}0QKs1Q)Ap|dawQ-q17`Z#K>weQ4zy!HNvi{cg)i>gz&E> z`#08(LbCl=Upgm%`xT&ln&$D^e_zFu^LS(ySDiwIC_@(U@ow|%(3pqp7Gll5tH`+H z^Wp{L0J6wbK;wLBQtWHUmU(iw1B<3i28<e-<C?J4XVLZ=Wt1J15#T;bCrN)9UKKwu z>S2^oE=jrACoUrc`6#0_F9=5n#prJqTjr1L*(T9NQ(ti@+IbMSFzU3ebCTV)HVzzs zj&vvnJ;(i8ifw;8X_9aOz*Ad_-zNKRW7;w|2qT9cZH$#Jz=Pc{h}wp#O&>Zi+_te% z0w9`GWJb<yePIo>>Kgz}^@^PBC#?0bwTG^E6W}fiM(jid__vuIga24=%%29{P2b}< za4n}*xooVD<=><h2mlm8>%JBR^R#`VG6%Su^>3D2`8vM@u3|O)1@Ia_3;OgKS#0FU zqO>|wwh8bR1t47-sfMfnlG=6E_erbX^6RVY?WMkjc7Ju_x?0{cXdbFQGqLoo^7_Ov zGJT#KxeD0eGh79{&hbjSd?R=$_!a~Y1;0tJ1AZMG4!#1x;oz3wJqZ4G@O<zf*@jf4 z)n{ATS(z~)JBW}Uuuu&3>AbkE&YZ7j9uSW2m7arhX_-MF+o-Cxvk7=NncWkES-rH+ zdV5#(Tes^R=$--o&EA|;uA3X>!qPunjP7<od>d!G=^qnoKXH#Y)$3>Ox1=tByHCHJ zEos&*#?{(I74I5btDK)KbEUb2b_>J~)f<+}xbN~KqR~%gvQ_9K+%=XjEc4HJ;O8!C zcOg5oKK8ZyXt4TrvxByS2W^bcecLS>xE}R&r|kXQZU;=V_ncj@ylwUqdF89>{yynA zSiiMkJgJ@ey=ysz*Y*AfHTq=&FyjoT%z8JEO2O%t_vLyy)pOizW5ORQvxx9)4`2K6 zC0g(yCJ+nQWz^FSrKf+Ben9cSi07ndTZk51&k@b<YdCNbBDJ`zKNGDe;#fZAl{LTJ zP5)5?LwM7BLyy^zu=by3#$EGCq6X=8`K{)R7A2s!`8hezIc|84=`U^ZL|4CX*>6<D zf$SMC+YU%HF_7bkYqrHJMMJ-<1KZn~=><)3=CU3(y}R1i##C<Fw`gd$q@g`A-fv@M zuE&+jc=30%h=#6D9grV6>_%7^@O?j<&)3_}#q1wiGR0Q)VG_M$J#&Rv5zJ)q#h3{( zu*C|izy?pT3Ri6X`NqLDAUQcblQFqx)GFr`F-cOytunxTsN#`{7LN=qeX@*q?dh~) zn_dPni7pw1bN`bA$hSP_?e6t{G|0hw>5(yH(fE~U@Q=$_$BIGPZIn@ZEel5(rSvsl z39b&3Q4gbxa#6`{0jTW+fPUO$9Hpy7qYB0a?&xnWh`-)#e&BK(KYRih@`AQYH#@u! zKPDoF1Yg-@EAjiB<#Y#%WH0?zLumJT#t3BV^QChGKzhtuLnqWvIs$<uLtWE*5{;3= z#rURk4cma*Re-76ZcU~j{d@CyHh_H2Z0357Zbz<-qtIZckqy7w#?R1EAN~HO@mCo4 zC&mV*DD;>pKy9J`$TJcM9uB_3J-{nL%n1l?3ueT?bKK8yG6wS*FlSArj}=6~8Y{); z1USM~Y>)w&XTaM`2q{y}uCh|3ng!U)DlsS?d3c$(d5LmkBIIhm4t$<#Sp`1F5%xjw zXz&HDf>g-g@BtZv`xIE``xQX?gjH_SbTu_vCNz?tO7%GhH0xzY)7wlzg5zvUESRYF z`iQ-3P;QuPvcJ%L&hed8-k)<jmP}A{%?dVHRkoRx>m0{;ABYKwfK{d6(-}8@dYn_t zf%`eY6gU$+!MzY{vcU$VC(^SSvytkXXL*Y^f!}h9P2g4D<RjptbVdjq;CoDgJJN5a zKZo-Voqt^30^F27pB{(v|HJt^<xe1eINjoTr4Jn>H&^wMiZN-Mxw4}&Rd51)x7c8+ z0oPOg`+3nWvbY}geRlmbhQG<KGXd>7<9hx)6KF0gzgM}@O~89t^ea1%-DHFk7Cv?p zz-}_V+Yeq~WrP<V@OHg^^$q{_u}6B2g-095=S1~O|Mw2Lju?UNm)`nj+_<yPw`?+T zu3HA%!%E-Z(e+k6?j&}Bo_(z}9_;zc?XS_m`j8zwaUURd`&hWRb_HEB4J@ZM-5H?5 zf#1^%lpD%lhf9i{B*v5Dfy&zlnA^p__}Wd}Ss&d1)lqAI7Yk*=h&=SWNDqqAr@Z<_ zcVNBf==c2mM6|#-&}29M87Z0x6kN~ou-CxHZ+ZgGEg1m&^<y2F+5|j*(D>rvhH^AL z=MhIe^KyKzWsdcr2hg{RT|^#!qT2qVmtTo$_JU_Shn@PVZ@)AF!ES$0&xjxz^b~dU z=jK5d>Cju7e#4d#)OFy*?RV_@G5x3sWR?~`VIvaJ<JmTSMGk$q4qW8Vj~m*@ULQMf z+l*5uwTvp#S})-^7+}V+iwpsQu<AW@^xp`3W*QyXZt72eeprilSAp!JR!&ntCV)M( z>d)1lXz^D4`C*ayG$e!|R6ReBGp;dV0<5sk8nDS4Yrq=+7B`T^p|^lJ+bZrkQ<*|% zY4&-}X(LXU$H%j{l&s8W1olG?Q&rxXXMD*dhzOS)huSF|hV)zmC8|U=c)IWW+RvYd zJ9a?Ym#Mz*Jk!SY9%+83ZT@fbe<Nf3C_Q8ZxR26F(woyS^Nmptm$8f+ZCxe=ql_}j zC>Khii@;xxOP8IK<PsXE#Ms})d5U2Vi|T*K{;|wV0LuvYR0HwS+g`eqB<#u5XELy~ zz2Aq?D^$;wmFvoFA>ptK(a_(MhK)G;MvH7@j&EXuH}4h>o!Eiy_WDRIrK?TPwhbkh zecBmvgmuF?-&mPz+ay^4KMUc{6u|oL^CS;Ka1FPx32gEXXDETc(gD2HnWc4Be77IS zpHT()ni~ev`0ttE5$=ZIw&0rJZr}(<IAJ^!+)UjVWs?RYdtz-9o!MPlo>Be1iK)6| z!ml$tRvFo4C8e{dyv<&Yyu7)6=}hp6N5nw_&+{tBAblx)BmEG#5xBFwH2n#W@<Rx| z8N|W2Aw9`;JPE;{f;V^wc#~=RFd5TQgwAB16u|bZOxeMQS;5#|Wp2-}pKGOiOZ#2_ zzPcfmzfD${)5`-L)pkt`Cj7F0Bo$33Mk;Kb8C_>;E1BS{sln&if$Md<mldBeGwjC( z{MPFgdZyG(Jb~|~l_VV_Rjv)YS<lFqa9FbF2vMJpOO;D(9e#0$9C&7VA=Vo{<&Ot? zmp*?K7qFhg&eE$sZyEK9Tjt9<z4mHaUo11;;0p+jJ3Ma@O-cM1YWuc9SElx;$6F<f zGif*V^Tqs*aIQCo1m4Hmy0y!}aNqZpz_4X8NxFe-ee@zbw0{?W;oJVP=k<O4;m|<) zy#Le>{)<8Uqwoe=wFAi{bwFyn{nq0{Eezr5n~ru8UhP0*=04L-<5s=+Mbb=$ZePZD z+qfgV=5x|IZb%R2ag2CdW`DBdIM<%BQBXgq*6#nqMy7Er@x3N{asjg4{ZQ7P>q|s| zbxqz3kT?5@@4*gVKNNcONBuq<aNgFAdi`AlA6?>}dIo`}@x;RL9@yJEH0C$<19&<> zU3#{!Xe@8FezG>tvI9xWOrgTM-jM0rmG`?2Xoy<-3#a`w1K`Vfhkl(|PJMmRbe}6O zU-z4#!QgIZm=7~1_w;oYVb6i?t3j-Q?yIZ<Ypk&fe{+4`dmHb-KbfBRPtS#rPMI<V z-ey}pugoNw6L9327!xgim=kHt3VRAF@vX2SK4*)o3EH!j_MO+Y5gIKLF^E0pqfP4) zVdy}UATQTx{Pziy+5s59aWLtbso3-fIRkyJm#IY$T>$H%WnXQP=#jVpafneaX&FJ8 zqjZyp($C4amKw?!Wt34y8D*4FcB@<}3y$c5>2I9%46*RNTqO^D$_@<MVzduu%I9d8 z+ilXau{d=3yD}!V)i>$E+~ngYT>*6$(~>P9=fjXCom(Gfo%~X5hn9XTI_lKi(6HU( z0`4S^6uah|rK6n^V*@9bxS`!mMxnNp!#aceJY%v+KS+=AIHVu4pA(RV=_|Yryw6ie z;54U@z!ql#*kTI_oM9V)ZT0s9jxhyhim7{>Yghxe)rP^AVrHMKzf-lbFjZR!*Ks2^ ztKapY@l)xWoPzYe^j!KDq+z-eya0SY_%b)E`{%%Ge32O?koP#ht$<o5%Hnb$`ALp* zQt2a6&&dGRbLK$InhMU(iVdEe(I`8}Q3WiY;w)z=f!i57eF=<?6@z^)o9ts%vyr`u zi70Qi50zeo+DbXdA+99@c7(uL5>5aISYrag9bC&k;5*#KwZLi`^Fv5CG6r|HxSt!< z`)0si4sr<i4A*iHg4?(@H~?G~>`QM3PNiRE0>SJ2f^Px`c$6PO@M7@e-~kZ73EmE# z1^y04xeADg0=<5-0<fN>8IXNmY%C?pVl%zV;xkkj+$#Y1I>5bpy?Njw(E#i^(|S@n zK!d^1l&JFSKB2UmvhP)y;mv~%C9uAF<if?YULHWHdR*5An(bIc(?N^5;~<9XdR;$F z&o|3&%DiF3ksj~&eNX+p7itYBcle#%fMKItEbCczjDc(?=H<~6dd4!cKD5;@ynuS{ zXTQyW%w=t$w@J7|dTH-RqEkO#v|sjF2QFe!ZSjm~fqHZWyo(*^Ct-`7%FaNSX283z zp8LKpE&x_yDg99gv<=b!O#o7?9l%_y--HgklD+idYX_mH9)><>($}7BK*B}*nQx{? zcR%rGR&Vk%VNbi4EsV{5?IUa$Po+osqK^Jadc=i92m9;FZ)*Zwef^4$zMBBqKJC-S zlr9_IYuaa`G7GrdTR1aQR<92`0o`4tG!G`o4*kOw&$PuOO}!@$J-OnX(s3}=#b7Qq zCVbH_uh8S0`zqzBx3k@E3z~rOk~(>baQH#d&@SfpQEl9_*Ei7^&`p2s0)RI$tDAZW zYvry3*ul=YZhKE?i8EJz4}>#bZfj>3pf@bu9~Sz{^qpm}jM=L)iB6b65G$bjURGIw z^cXWvlf|8<>TjeXLpjmLT*cAmDqa*(5@RG9kUjg?o+3V%XF#lGT1|>p*871;>@d^f zV!CWCc^w#g9;EY~cl14o*>@gj+!sugr9A4auT|3gIUfu(zwJ72Yr5Y&@Dp16)<pS{ zsqsA7QSXy6N;t|e%j;1_aY}lSJNV|PhfziuWgPiN8Re3ZOJNBy0>>}*_VZ)Jxs-aH z+(CU_Xo&{ZTwPi>R?|B!s2}yOf4ETUZ2$Hs8Dzu~>K!h~_!V~Eu(YR0b&V4~j9IP? z37_X;JiiPC+WWnQ3CP;cvEw}^AYD3B<%V7xtqpoizfL=Ilc~R`_FKuYqXWRocg+>B zc+R(gCwYkzK$ITi0B|E8)wHQIx#t@|2^bvXxxdKYmlS|cft!iB#owfN^KG7iG-S#_ z;5mNGLF;|CmTP*C4qn#psBR>hKz0|<*~L(AmPpsC$=EI}7B3B^c&S-?w$YLS-seSq zq*wiO`7AeaHLx1ozyZJ{TX=#Oc^iVS2FLjhu*xbA0}lkZa{z+>RX}hX8H4+6l{@FE zd`WOSC1X;O*<U&<bUUvA$aR3b&g`COfO7qF!PuTkE7Q8Ezq!GPZvxy+V0u#F&eyL? zDxdZC6&2r+6y=sydyvjqjQ-2a;d@P{_nE~D<p6)1%sfWRCQF)i7-hQv(>4E-E^|J& zQy|$<F70{vE|#EgMxKiy9+C{i)V-{F^<@xVcDY>{l>Eyl7wVsVfW|}WOZH%}_FHB4 zukTP9%KVst7b}Nt+#CS7Qu`FOF!3%D7wUI#MfL&&$=-I_Pp{#?{jY9kqH#UHXn&3x z%DD(reqyZm7oLX%)p)?72L+OW4#2cA&9`Ola{+_vaTE8r*9CAr6mzLq(68I#Dt!(T z+15dA^8_Eg*4rtpW!@6~$Dtr@@yil70JyDRTN$f6W<>BMvMA$i-424qNN%&#(*=mO z0i12+iahk+1az)n*F2tyRst7$d$uvJn|@9@nZbp3xthvjyH7OC52P{w32T`{?TqSX zrWzM<NL0jE>%GI?PNAcntNo<}sLKk#JSmvc?ekV2f)m|d%mV=?Q@i;*les;_1*p&U z@^z~pcE!hCdXoh)Mb6xwmoNJqskrAv5r_Pk2`glb?kjNBi~Ik{+6sJp!(YwLeP6{H zv$$c-;I4q~X&%Y@pBI4lgpv?r-f8Tp_r;Q6A}sVGml%gybR2D8x9wDXM|d-$H;u#Y z@k(lki<;(Ret`6y(udRz8dd#R_IZ1Zca5?<8DV~-bdun^!S}_xqaH>XWt34y8D|=! z>>?S#AG=p}1HdENHFg?aQhFVJypWyhCol35#%Due$o8(MG?l&XZ)%UOsiUjU6^-); z+lH1ju5a5gcL4@`7^)&meMO5syMP>BHkMqB>h<@zH(*>F8RmNhG$gnWy$&KJ4I4`O z21L2RAZozr1lUpm{ypg#J_EeZ1~IS?!BxO%Bu6PhyJ1nHNc}%yN(Mik0+C7`n=_>g z?P{rh*XI*C;5IDu5~+VDgb?gwgEa_NxrR*$R!BGiJjwMO0R%CpRlCf9{TyJTy?2WV z=d5;+m0+C-5gAZ9dw;e;k`O8e_pssz>l+XP0qH#Z8@xxvgdBVg>%l~UrzH}C!|DCO zP1@bB5wcHfCv*F5qDm}^jh@o(Gaz%eF|)1yN(3>m!74Fu6MKn)z3gQIoGYN++4ZYT z*#b^;hArR(=h!A=<j)xKU*QGdB)4-5q-WCWcoBl{ax-^9`nS?YI1K6Az$y?kQ5!>| zuv7(bS31f5&eH7fd#W6HMgbk*p6gI*_mu|@k_uybdEbdj-<%u2o8JqK`CacNC4k+| z^d1_(^F#xV+Zf_0+AsUQ&io|POi$9`!_0Ek{h-aG%$#FgGc)|$alOsQ+J2c@<{Mo` zLg9F3(s4W;f$O7OsP*zLI{=$*(;qN)A^T951Gkf1)^5J~j&|7o<OK%YCmjK8zIyX- zzoCKkZO_Xfu*m@H>8=@`hG}{GI%w#4N`8<qUeG>VcHqD6?El_A_The?==8qOyPRSn zfOza_U9xk3uEwYO^cUYuB8!f1)g#y^8vVHJ`Sg;3w_m-R?0uNb53+Tf_Bj9(JL=Qk z{<4voxlarDGMhKeOQN23)c3$)Qi~hO7XQ)+08HODH0EN+cD^qNz5HmLs`y>dt)GXj z8EM?a98K0B9SrrZV+vt|9rVe>=o7CL9(vH3yJgG$!rJeIV_X!i2T`g3X}euIfbW62 zFLnKH0H*Up??L1^2vEjDrPZ&s0rgEFw|RY{5mP`D(A-`=7tlYfWfZ8}rQS|vc_K%D z6$W59F5*?925{G7C*{F|>VW}SyFRSMeWU^5w;f;*xDR541wo52nBz+(_mGTOBa7E& zf7h8XBLlwA;EJPv{@H`y0`{Lu{_=-_P;u`(Q)eDWjSB$0R1Dcdk)Y&p!nBBo$x6E? zJ?9X^t*pBNz_Df?=zj1rvih_9xs#UpM82Oj8Au0h^OZ@*``rhCy6HQveIB;meao{G z2mMF6<Yk1NjnYZdz1))CH|k-OCCJEdG|DKWj55l_GA<++$*2{LW^_r&GBOm1OUz!x z4))WiXL-7`_aaR0JH-^}29$T*5UL0Gy8z=OPbROjZG=}!;>a`AuWZ>+%AY4K%slyX zUH#oBwXbfME=DW8Rb1_DOVQfa{%!W71MBtn(%YdPpp`1HJYxp@Cp^T{z>UEXZU+)h zvQ3@YIx*VH{5v<EZ_~Zq&T`nburlBr;VSk6E5LqqU~{Q|yX|!2mz1><*~_0$VcrgM z{k&`Fqc~QO=H-3BVq-d!xKN*~^}?c8{r9jqP#_)UZDzJV#aXt2Q=DdI@#{x8#6bwI z3VzK!5F84w3cdjRKlwIa0Ae2F1z@G%Di<1eTGp<*-sWmUdzzOcH39BPrJN>n{#-q` z)OBLjlh7F7b3N!lbCan(zhiE+k2HYVGtI9`t)8Zy%Yz72>su{*QkvZts_(0e@3}Mq z&ZTucmc{dI_Lj>`tG`b_)q($_;rG?n=g68r@gGZl%IP<wn>q9{%H=ly$D28GNIPA0 zetNOR0m2^hW4QzE-SvIZg6oH6wV%F0F9)#a{^b{*_8=E-UtuY8-}QX7uw6MBSG_Wj zSPs4hqQO49GKahDyA7~BgdI!z9XOXg>>=#oKZS=MFaf(!XN!0BujcYb9hso(<qnH? zHR(0-Y!BHHcptUuK`hknk>kFh;(DPaE+7YaZrIBXZT?w$jk9gfwKE~d4OUULi?G$N zNzXW$bd0-pdvrh7M(hw-`n9j!iHbiHz3nUqcFLZ9qsi`F-XSr7<Z+8Vv>gbt0sqYR zOByn81aYx`w)=5+Ic)WgJm$}B%-~J>Zab)y)BuvwEB+W+{FZR|A?ejFR$zM&X$;;L zNfqEUa1r6S;<ceO^Q8%t7uI=8uBVmk`(U+J@9e%cV{Wu*d@mjMx!PMenD=9&-Q2+K z>b%B`2fOAwE`7NUESSve7=#x(v59QZzy4WT{9b6RAN2V`6?mV&zse*XYkJh58>`QW z@qSs0pWFR=XpEOai<9Q{o@@0C3;oY4e<gon3e4DM2254_J7;pwEnr5%j0^~$$N#eI zn0pi<M;Q;d#ouPTKHlNKZs;?EN{r00ePShDcDN#CNs(W<gM2*tpkuwduA?KZ9&`K& zuUr`#y2Ou~_R(TST;M2!hw(-k#V$AR`NEZ>)m%Oz$Khp^QAWAMBpN;2MLHf`uJs;g zU8aaZ{lTR>PrDTST(|>z+Ku)nRcgzf((h1qWHPEWUDw127q(tkFL$=lDH>Z|wlKu! z&yls%<~W#>TmgS`+!BrTk34}IVe4~3Czx8Vmn$W*nbOsKk83=NoQ&_nn%Y+s^@*$i z_x#^8riA}A;D0AiBT0Ea{VneRD?H9Czy`-TNCte~0yYU*Cky09z!}aV)N=q%b55mx zohgR+?3XE1X25B-nX2FCz+pDn1f<$%SYw03z?2D7Kn4+OkUqpgUWfGM^bLLv+|D=H zfZ%RE&*#Y)c&5NNi1|>f=Zu826^+G}Ab6>d97vrr`Xq|se3Nyu4U#!oYFh<lPL&-5 zw-@kig5PkO6O@eONt&p4%?oDp747}|*~hxpW_hYzp@2>2m=aTN?5qYGtdKF`XZruL zDt}h1Te*%+2p$Q(&Ou1`admnRu*pWSsh)X1Ir|gr<7y58HxqFPNI1*}@G2)rfOD!{ zu469((vMQO8Mun8xekK=H+OIc1pi6$%h{U;GY0nw)s)AXp7K<`RVMeOfU>VwnA>$G zckOSQGq>m8=LZK$czRN7+~p~T1sNbap~}>*AKa)jwI{~G4q5Xu`hDg>g?Y`l<;?A7 zMvR1gmFEe=CnU9gTLsKFGqLAP@nOdqz76i)mUg~cPr1+-?}8^J7htU-FVVT*rMmtc z+oqrXeKOeW#QcAm@rc-&!AE$`pD*lsJKSZ~omdW(iY40TqV^Z}e7;W{smoEyE}6YH z8=lvl;aau;R-5(PRZr2texsEUxFJK=5aWY%u4~00<#+2b9K=rB^dApYe(7YUUCclB z>F0i#1BU6pb--`ftDa8(5LC-4Q|ZZAUwuy!h+gH&OA%LriD^#;{2=tukB{Gv7U<8y zqaQ4q5yDlkHiD4Yv;NZ4|4P=ZfPa@>;s!ewjdc^f`n4xO(aE&#nm@Xjx!a!K)}DPc zGn&t}WgKv2CTJqM5G~C1*EYwYgX`4q*R`~dJMP(jpDq4t(?d1hD=WX-;=9dyDQ!Yn z+QnAB99SJ%=DTstPRn`<%ls@V;)|gp^JhDgyJ%Pkm_YOrsBeBRiVUzqE04~sFDmn# zuvVVx@50H%uE(Wy{RxZyWNlwUSlc($>X8$>2sJ;-+A52SPKbzsiHi5GWO2#ASlihA z)DytT-~XfEPXVdo(us;6C(M*BBt_gZ(c+g0K@n%vV^UK~dnA^*qNq_-P>bK~#`uM- z9BpV`2M$qw^B`$gA}w?NG-(-EV$IJEkx{IPp}mO-KJspl{`2rrMp;ls(99^EB%P$! zreD~_1svIpMj2(4QAX*yFuGi&A7k%0(vGrxJG)f-^&(7l7pH#}7sNio9Zsz{w7rR% z-N;_{-*>~=4S){48Kj!ZpLBr2=o>Ts%pRf>AWAwm0L*gu0OU=(w*}Jme(hpHYI>gO zPZG~m!LC%6k!PxI;gNb-|21+P6et;r!a(1o(E;$;zvt;3_#qFb_W(B%ax-vy!H`}u zVdsAZb%yptD`C!nZDV{FElh4MVC((q57OU2`WoL4?goAg+^4-y)G`!EjeXnS^Gl-~ z<pxX%q)v?YnD5mYzop|p^Nr<3by0#;)hn1dN~?2BO%(&tQ~~k9o{rVUmwJf(tOCc` z&l(xPU6b^u{F*mm&k^wozXBfP8$1cY@nAc69(aWxaSs_le?qz8R4}#|?UX16q<LlI zXjbTUUewD1cn@AFHl9@51V1hq-*vkSiw(u9JqqpVRr{4SJFEidtIw%lSLORJf%B!m zw=<_V1Jq>;!|mL{+h^}rNew{X)DuF3TYcsQi*RQUn0K6ei4NTEvhtqg&W1yet+sIm zxAW_l<T775M?Gr493XOdLF{00=50JZ+)#R2Z2gh+(6d;goyjFZ@4Kd6zfc?cCQv8Z zp?bUOJ9H}gqy@4V^{!7hV0hG<@wi_Gwb;8o#6s;Ewmf$zV0-LftR2dKGy(aBjCT!v zP{nnCBVM4t3}aVjIUlRGNAS3ze?KAx$&VKrS6{9^H+ZG>Il>BjeWjyb!vXq76Hv6P z-RnTuE*TN&38=Ttvjp9kVVm072golP?9Dd|m~Z^eW=Bo+aL4=no}V-jP=uC9Rp{|N zmp>7X^^36hY1jNJEaF_v?GUyA<HOcWlENC-3>yxN+8C9Mat4N;Q)Ao+qN08wsDm^D zg8DdS&$Q_#NC~Z(2V4Xv(gMr|cU)U%RCkSEX8ViE`01`smGD4Vfyd^-Arpx10+dIz z1I}&0dtvxt)8Cswd8rOqg~kD`FbEC32y6YrTD`I(fH6YFyF<mEodMienJB>fgbAb@ zt1EwN1(=?_>R)`Hj36arXwTxP`R6SayGjazj68m+ym*?I@c&hbvz2))F>+B}n(?B% z-6sRg`h1_$XS}zKqq5<9(Xu`-53mU9IztEQi<WZP2#yA#;R+lXFm^EFG0G(*Bfx!> zZa)22@|KTpAN4TGD5H!r$|&ATt8s#UIkomMbL()l?@=rZ{YC97-u2eBJFV20xo3Ih z_GQ8nOV>{qrZd?Qc+i#--Nh*3%itGve16zrgED7qY5LvNcN=ghaRBvQ3E{(r)Q`ep z&#r!F1Ln7F^tEjah6dA(Amn!KcTq6#$bwP(j=!DqU+~>v9XP{vd<OVB8%%)Ld6@Tr zGm2q5;v5oKQ6=A0*G&|I`vJueHfKr*98-YjscPv})`@{wao((G+=K!+5FB7H86*4@ zSXIBj82m7}6M}QWj7NYMd5bSVdVu?R379EH`1iQK!t%Vu8BS{YdY^OYt6Ke!@j>uQ zO2G9h6Cz4L?^(r2pD0H9nX;&yiF}QH9D-n7F`a+FjT|HcYA3+k!PT6jWCDuQdwESO z&solJ4xNE1PnDas(>~UjXzhA3eTTQnQvOE3!Qh9?fo--(fTNsb4!o1T%V`L13X<Sn zU@sfo4xD5~0pYX%_VO-o1Fvz4{lE*n%=^H5=`l8eNBAB$1MhHFZPpwJZin<vzQYXU z-%Dls1>pK{D?W8B)8C3JUzPbvs*NF&$z2v(dI_Xc1K3^yv#SR#^7}%A(Y*xJ=lvzA z+$W2a$|gg*J_kUxUfBl|0}vn9nA)Xr_`uG9J~w{R8RSi-v8u0-m3q~FPpd$A7lXRX zd(LS;aAF6pORKMHf}vHJnRaHT;%2ySgRPBl^)Z^TxWo(E(N52chv{)UyDk?y(Ee?$ z7%eH2)iUgI5yt*x$<`CMtP5nYv%Mi|nRhR{U$+6f7iXXsy@9>W06+J^qb|Tq8rHGC z?bnAPvnw-Y<lQd*z<!_im>zVf@ggz~;0|SXVNU?OXkE{T)^S91^q_4S)ndyrWznMs zeHc7-CSKqE={^t;cJxE_aY^>@3qu`*h+2pT+S|9^fuzI&)b)s8rH+FSK^LNkZt*_9 z0}o-x_tZ1~2rvKIm)X7TK!_`oW7uLB(gGy*8D}ET`I)Jwwm7OQzG?a|mmc%}<n~X( zInUNJ3dA+$?Yf_`GqKwbAe4akilo;U_0DQ^lhI#pFzS1gcAxH_+uFlcUR@8;0pO1u z84~h1s?Y%Vl5RkE+W`PtnaoT7W7?G+P%f>^>e2!n&;6;*FD6uh>t(%4Vw@%>dQr2V zAF2ButHh-#zPFdpWN?o(t>wV>-;%-Ig%*d5h>3w!Vnx8QN(?0YhBtw2#pJ%C7~FGa zcbVpqz<*c8D?g#yIS0B^i9^=oV~JNBs;;wTuduwvHOsuGI_?e~mvF5IO#km54`gGe zt3~(y`_6-t1>fA|z;ho)_)$jLp)lPjm!YHw`CR&qQ4gbxGRg&(5l}hGD3_+lvAo8@ zdGvM{s$GZG{O)SUaM$SN!sxYcJ>r4-e4R;K4BozrrU>l9OlbPUzJU3@<%v8tysG*U zUiRSHkZIFrmyIhskR0u3LwkMQOhD%I?C&u*0(}_$gnxSl^^~<jJtHbMB6I-!T$LkH z!0`WoFYyF$V{n8UfrOKsq6F4T13;YDP2Xs@T_<V`(}`inRDj0ib94L1c<Nr_F}?%= z%=r>o3gw*H8>)=ycFXJrTr*+4!tn-CY}8Yf!^YO0Sgb?Wm(D~d8~d{TefgGF+|s8L z%kL8SC9m=>q%Wl}rSAd<5!_y0FTNC96`Tb5Y<g?D0bHM+NxuQX-Q3R|ke*;K_X8`e zI05b&ki7u7=jETN&!;p!=Zs0Z-jlRsYS-@%3jlbPxjiiGDXWRj<gNq8g~e|5gF1CU zysY>S{dv_43DS$nz3lgi@w@xDP!%ZtkzuFJcHqnWUT;6YK4fMnne`ag^NmBFk<P~4 zKIGcrLTxzqkkqr@!MO5ivb{@Z52p+B?oeU_wq8hki|Gz*l}psOuh;-<VySlDt^Cn~ z2Lk$gxeprW$KjIO&3FA3FAU)B=Z}V9o)$gqv@f8$3&2)7+GEjv;X2s8jDrQz0B8+u zd1kr81^kjv93}4E-~A8H`;;%~S<ALKa6(@of4BZ1JC?Vr-AiXVMQ^*-*A8({|C$6Q zgLOB%Oj?-97ajMa2BvBtJ<;-<yc}n=@@m(m$GztP{n|-*9OP{R2FAF7<+c^7Z+xyT zV}kUocVrpIgva<OJ@py-^|PRbDLz&D3}PpRMm^5y3(OamcC*dz&4W8O0De7w={}HB z&8#Aw4CA);j4bmUVZ;&i`Hyt?2U%kfua7VKH^KqLj-0@J;q;p>W^`M7M#lRR<9j#I zKCG2hSmzVX^>i_{n+()$X7^Gb(o#M>gQ%#~(>`vwfc#+rq__9K&_e8z+gn(<K2(h0 z5fLTOeI*0B$KU#kLkBm3qbFx)GUAUJtH2hrU~-?S_+%ajOe&vc!RRhkyiN|d_6e7q zlTa#)ajh>VMJ<8_-y<sallKv6^aHy2@!X$kd2Ra5KcvN9y2(cT>pS%NTMX9jWAty7 z1>DjoqjZtm_I&Be@wCk-ql~hfW#ls(Wt59sF2<$J<uaol7oNLYA{I-5e7XCBa2M*M zX#*izk{-=~nk?)~_Ih7EK-b+aZ5s=E`E1-j<%WZ7tY6&@q@(=O(eJu3y^GEV079?S z#ZeEtF*jmuDP>(Ls$Bq!sH(s8R)aw&f=Ylt5B%$}-3;iSApdE=2l5!FNI9Lp#M{7o z{De1vh?5)uPIHDCu&TJBw-jUeHfNbpGT@w2%<VJ9cz#xG1k4nqcEUQFl&N61)pb+# zT&cD~av<||koAZMc%0ut`WkO>0JxWXi6OX&ySY)lZw7poi1*Ne<<nwQ8Ay+&@AEbV zkUV%Uc!3Ye7}w{(GrY+wz*K#{i(l|n0L3`JhG2j8zF<EYQ21_20Q3pA*jAtCzzU%P zO=lY;5fKxud<WTIVK|zoRJytSyvLdJG$06r5V$V*44)y}P>O()+{r6sO!pGFg~O}? zM}m9UfOH>+c@NlRlT8Rt0-vP>i0|hbZU8>RAz}#jv8EW|Pw*k|<@77*<G_r^xC=PK z&D;RI7W_DP5V(t*xC(-QFPYEg2VqUMLr83Fa_0c^lDS>Abip_-H9e{JPh|mgmldG7 z&g7o^lSKQRGo=gdz=7VkY=CvWPu7{%?ErY4`8)??Lv^FeydUFxs57sd-`D+--`YIU zu9RNmf%B@giQ&C0f4i@h9cD)JmOA^-JKWHx-4N3lavO8*dEM*+);HSqk)-*Kzi|-@ zXktpfFl+Rr*L>7ROUq=k?kerfqDw1HuLCNPV_tiq*Ig#i=0f$S?u^-s#(UZivg-XQ z9*9Z1t6hd2^)7n@js5OSJTrOu_Fp=#zq;C8*hBw)2?Fxx4{87P`V7nH?kaE8aUI{a zUW;Z7X=}%>4CB%h_#Q8)*QS0x#5mR!aIDWpMF)H9GC%6#UtHx#0tHY`Wfyx-lfYVo zpi4Wt^z3U-O@7G@x1KxVef4;z@UpLd86hU#c4XGVum6=y;BNac<CW49=iBGdyQ+6^ zQ0a3oRG7cp^qV;SqstE^H9&BcSR*mY*Q}>d%Vnqk?&?>vU`$RNb|S6zn;6fD3<3+6 zp6UQ;yI!Q>mu>b|1(eI0J(&jyY>d*b{ewCazHl<jSHDkc?c`#Z*RRtvk>m#z^h}1K zb~He@$JnqtQDcU#K0mY^Y>*B1RWiQI!j7b2_f@8LD&>x-W-^I2ea+E<?y_<iU{#A3 z=JDK+EQ9BaEPrMe)0;9Ui(BV}9CIzAmd7PSBa>uU#5t>kCW$3_<uljX?l|r(I|h(k zzzo;T86raG_}3OM2x-m?A_mlVQj3y=p6wd8&K^hPz$h0a)Hli~Z3`fg9!~Ea^)O1$ zfq#@yMq9i1WCXO1vY7pherK#__jinbr=R3us%VGWbtl?sCoMsC(BE#d(?uE3+pcY6 zis^2r?He|FIrKod4#bR|97@&qlqpPQ<8#e^RNok}Z^+47J2Y#(&J5)Tkk=VwjP?&~ zU{ezqZ?eMc8wq*&MT1{41GO>sjZ`x*8fqI9+3z`ndv$|CXTr&XyE76<f5`XJqrhib z<#ynU>Y90RZIv0@rMsloj<WKEq-cjuGne!$>37p-f&0_9f-eE^KKEJPUuR;^?NNC4 z8?%4N#^23$H*G{X8RpH6J5kf4&U_Tso=270T>WcXX;`$BUl=9%42ReRj&co~z;Ae0 z-=ax>#;?;iAh?}JxCMfbIKUc+pNehqWk~;vbel~G)`AsP_N20LAPoTfEC;x!^8&D* zRP1Y791O@ynN*%r<?f$qen-y{U;^FE%mP!Y!1Ss5B{YEHCgXXTnpjqV-%|%LeQvRM z9a!)3M6!5)-7f7ZkxlzctYb}S4`${EcZs$t`e>f1xPbZ6@GD_gPtbAgGt=HPuC;cL z%r4=&UC0@$*`MQGQqQ4}3&@uF+_K4n^7n3c&{h}!5w+_(JvU&#GZ{Vo*F|zrdztn0 z)Gj-S7ql;3Z;SNnwu7<4bG_f!Z-yTA6btlU7Zb1V`aQpY+OuYT$9K#70@2`C<Bs;% zwr)UUKDFCTxBfMCtk2sd?igvA4wz9uG}wPvyNf#XYq7w%6t$F_+WNVhpJ?lsv(9?) zYu$NEJW01p;o+xTneANdC0olCI{b}n^%6pjFMjRds9(Abkj_+3bG)?%To>t<O%Lh3 zx!r=uZog^AgCs%ZVV`XW3q*tcnenbDumh%(mi`#E_-WYy^u`+hX$Ee`#&@%pNKs@k ziceeS9XUWZX_*h@fM8MBX}$m1h(u<!ejZwL7A8h{%#15@qb*Iw>{$zdeCinYXBPjg zGd7!m@6a;us@g}@US`JpHPqr^Ho$#k)K}IR)bnw)>e(Yl#*DCbeN_)L2QxXfI7t0_ zLG|E8HGU_G`U|6e`FnLe<?-QJO%GM3^vJMl;TT8COoc+#ziOX})*ktLMWsBVAVkOy z2nem*kuh$RdI~G`7RJ1%WRjPKeP++ke%V%kCuAOcn}jL+&D%ErtCd$EdFij`+Zki~ zQ`}4jY@d<=;OD@cJ&GJ8Q2=;Z0O0fb=zw?E*tSy{0qcHUS~CRb^WGm>$Nlq-{%g{C z)-GxX8ba#(A1i~$N4jEj-Se;^;ye>$JZWEv+DkYwtS$7cSu)}PMj0-gFv=+Q1<1<z zpZ)2xqaH>XWt34y=_t{-{eH>IxD?rm1??z9+FNv)YUN_}#?iobv6BGxu1r-Is@&BL zhHn0;ZDT9!$QV}o$xPw~p4%qoqp(F|W@_8GwLGFxZ%x-XZ8)`UxVlnpCkQ^<Vo!Y- z-MXZhZf^G~Kq+Ui(HY$JjT)W7eg3!8;1&)C2Z5NFtAQ0(SOZqs$6m6HgDfC=LIt8D zRo_T`&PLi;+hPbQ*-^q`qX-S^4<Qp))%-OCK1@I4ePG5%Oo3Q!SzXP3R)BMyWiRj% zXITTzvZXc_X6mi8%GSXd&T&T5al{7uC;`%udOt)Yz$OPdM8@PZE50p()>G!30p^O~ z2ZJGeLZlejg<^1DRrZtAxR%QFtYy1Ritn?luV!zsPkr75)>vVaj0rvh&M7AMoK0*+ zl{jV+#K27)<N&ajO=93lLN<Veh;<0o*-rxL&v=s+;AF<gpPpqa-2#3bJQQ3DY;b_L zAf0em`ZDk+Kjmj2-%W3qk3jJMz2Y13)5qW|Jj?_Ljik!?#^X!@+=co(<&gr4o^2GN z1K5N63eA^5_)MQw#`e60W`%v%ncl0wZfP*5$qMjYXLhdw)yw+i8(I%I?z8!pq;|xi z`aBzu9pnAdqE}PuK=)=w_?hE<E+6UQg%_S<SkhsJBs-0*roJwpb@6Vg>9|ha&GUQT z^~=S5ur|EFOlN&z-{A$;pKrUzJ@g@#V0SLY(?!~?FLSrKj=m7<<fujOecmHH>>%m6 z?i`{&_pvjVK4Reh0rZo20($#O8<TNgApVfd{zDKHM4ndFhdI6)PZ&0?7k0=v=Tk!y zz(|MrdQ%+6wQnRF%3)`mmMwbo>%lHyd9nb5yyy{UGxd{nJOK73DuflmS9;q27Y#tN zlHh)={Y~NnTT9&EF+OLr57A%;_5SowZ9MHVpGZ6oUWtnT5nlZ?YI$xAsPF0L<CcD$ zv;g^C`l%CQ2(S2~>wt@NlvA|m#TB;<YmDag@l-U7Tah)NrCuL<d)hK?HZiB?zl4qh zWwPjJReLWP>do?0f!Hnvc4|!LcE)wrx=hdv)R%VuP<$`6a!B+8235ehUbnnF<^c@- zedhQU)$}4N4D4a8PNDMvmafmxus8F$t^;ABC`ZoV9u>^|d7L_iU`54ASArG(|LpyL ztR=^l=ZSqX6rG)Y_s*L)Z{E~Y*VNS16gZp$%^?Vapb1(~6EasT$Z~^_WsR1QWkC=G zSrBAF7PPV;sAXBu%Cc703WD5_WkD+lf>xkqZm&iw6SS61$TXMc5;T{nC1|2dmusr4 z%hlCyp5ENPx}A*l9~qe$85xlonK$oyud4C@<g0sc{)jkn;zY!W@A<|Yes6d8EB|y0 z{`TE}`Q?izsN%c}4TvuQ?#q(NeN~GS+Q4?3*kb8v=f%Kv)p3`!JUO8Mx=!}IUO46( zN45Xlcix*g(~|nF2aaPbaFSb6CQ!{Jy(HVo9?U+l;g?Js50gwX$s|WJ;XMwM&S_?H z>&i5~PqN7c`k3~W+;;lhZ2wdn^6YWv#?{Sjr$Yi@V;tdJy?@w&$=yJA_no0fqsIg5 z7XtKlF|MhW4H)-(L=dw@A?8uKA$FoHrm(Jl5YBMs-hfIv1C;LekIVO00ss0*0J6s9 z-ed|&Ng;cluV>!`-o+pDZcJcs+5ohgK;sHHn_6Y71BNlm33WiRa_Y1G?fK|5CxLxl zVH>!}3$=2n7K>A?f7ECicwdt_J*|CK_?WHhjP4asx(fCS$MwF?si%y>vt_ua^|$c& z#Jjj7ItOpr5!d+@L|=(M!v{f}iXMxu1OF4wFbB4nGXrL|l#8l7D`R7*U~)H^-BtNt zT0#p<W_M+Ln_@DP+05>BAa%hIFG@H)rQPPha?!9?`*~Gq>c89VUogJA^qw~QZ~^?c zH%QY4)4GcR$_A`2%Z<%0Zg{udgwA1Bj{c@veX+9qNZ9*a&uNpfnWDqz1Zvt;n$|_P zoWvW{+fl|fLK)6Bo#;Aby`Tc;$%ko|sl_yT*zN3E{}#YYHH!VV15ZQO(Q2f6_I=K* zF<%_sU&VlaHAX*bW29CavMV{D{QVN`<wpF8>XA4zMj}Q?zaQFvh5(g@$7ARXuoi*O zRRhPB_7nKVnUDB^p<&Ne2B2_=KlRx`LMTCl=+u9^-)#3MNy~df;!v{Z`+WL}1N)0_ zEhPu|5tC`RdmL1H+!Y<|-GBTL9rL1)IGf9_huD|w1l+5}b#3pj7}@>vPSxU<($4Wv zc*f0kyG>et7x+&?j6J`k4My&|-fiZ6yWB~~@4j}79eNZk?Wr7k6rOt2+qD8>3x@?) z2`KgWc2z!UjdM*J3>PpyZX_1S8dJM#ejyxwIyHd6Hn6;YeXT!5vI79`ic6dASNQd` z(Vorcx_<YySF@c&jqoLj3O&gv2JU4>0&H=D7}#cum>k%?ASX^)kOSP8z&>wb39MLU z`Y#`+Vsy9T=FPsH>Jum3@wc|5j>BE|t6nGLY-YyaDN(VX^W}l_<iz8bHxX-CIo8W< zC(wm4w+~ylPBO`c!)KFBQpsn3?`MDTn@J6mOftzdhOI5iF=3x%l1Xk2xm6c#>X`W5 zWNNn!$>C<&%R{hOaZK#K&ymIb?RD58=rS1CAcN*HUHvq4!^Q?~+xj2E6yMe!qUVNg z6$n>B<x<wsylt)3#^~h_EV=>s(gMtP*>T+R+%Diq+s3#V_%}C13dR~~F}fGBBqja- zM7*$i{<o4Wdy<c3F9L7pwd^YJc24pE;5yeebNNNy02b_X032v&?t&EpxWqm&aG;rO zu4``S1q)K(Di^r|EcKDEl8d|!EIH5{3M)>NZyXeW=NR~6_Cub9?0bAJ`#EIy@qF}N zh)(k=kLmlCz&0;&!KmLVTe4^9+1^x3t(KK~qhh52(Q~$RIb&A9E{fB@l9|Ego!_s3 zt6DFsl0m!<=s#dl+rX%R-Ff?Mv0byl1D5(Y;9{fsWVA)jY%hTeEVCa`0mbj;4o*V! z7<ch7WS`)%?9U)N!HMVu`9?s&?!5xeMrXMTczgD1X246)UC}9sc6d5kL3TR(f%-M@ z9zKwr2eneq^I6Egmc7Irm~lP&4n+ThHy{1oN6+TvpBd#V+o9abS?PDDB>+9u?X4h7 zOUCw!(LALBysJ!=0P>>$rPP_)i@VcWJE!IK1@n4t4|U+R2~aP7$IzK{Fu}WgwQ>O5 zZHD#&;4Wwa;)^%SlE1$Gef6mh8DI6BbEOOglB-5NLf7Kd^gZqj$UY8!b*N{^9L}6> zlH)j&zuDKF74SfH*tWch>a&S;(P1;Ew*i@s+v-kkNMB<CnB&3km!oPjv>fS%AmctD z*AOBW5uoo)B?j5+olW&;7vON+dbBa$hS<rNCj|8OE2<YzJMK9*8fq_H%=POt%8OCU z+jpHm)DG5#ZKVzXDZSPjVl6+cI!~|*(}#-M0m$7a3x)yAn{lf__7Ul~WnK2*(R(!T z#K255;6^eyVL{gP7jjZWmp%Ca)2gQDFnjHa^Z6L*tLs(Jc$|3V3vEDq5zw!F%;UB` z;|{-<^yuHNgelq4jumiOdh65<=yb<JeJ5DjjOISQNY8w-I)Os8+NJU^mZzTjD<cur zw2RaOOivsqF_?B&#ir`@O)bEB!CY;>*Jhk|0n4%M&5Vnh`WL{5OD6TIoB|iKy>tTH z1$72`dwf+;J9*UZ2WG6!9yf)<4~Y`!{`oRd=mOP=n=@w2fE~7&!)*KSZ~vn?u>6a~ zLNmE%IVk-t{E+;l&^%6D1Gbm(%P(1s?#+0heG+3@Uhno3hZj{69e!(_eKy-KrVc;Z z<~Nn0JK>y1%f|K6Q{K(2<LR6s3f9{P57{U3l`C`}H_0R$3ZG4K8;W}R&7Zt^Vba4S zlic(&Wz0=7$u!fO<OnBJlNY`%$G>F5fuM9`Aok7Q&)W5Wm<bzV)Mp(IbEE39@fW%g zZ?;PuSRNIy!7c*c=eth@9xa}<`0<bpPBrid^SE{xYPY^*&kf5y441wmY1`goGUz}B zXirK@ZZf$;1vLKO^L1VazQPOK0VvJHtvmqWIzPEt&qCMkz<wRv-2~`@ljS`720!9C z;G5ac*#X|iowesxOx~iyQ;AL=mS5#&Tvr|UwY|~B%#%8<sWxS*-=(8m7}w=&La=9O z)Wz9pw__nE*kuNsVXI_?F~QP5%U<9z@L-hiQ{Y>Cgl&l49WD3*@IyYsTY)&=AZh^I zD}Z;NxUeVz=#`zM5dFviz8l|jpuZQ<r)zp#8MQT;-Yfm8#u37K-9&8zYH6e~x$dvD zXfwp8&h||$CjJV@juZH9_aEC13t3w2Cp-*LONTwHR{!LFUspfz0sPy?n)>}>z<qsZ zCMzc3`6QG0`c@ot)#0osHu)ym0pLA~1niI#q2dj_XY9C&JS08!KLUQ-_8z*<NH(nh z?sd!X_pF;p;9{m7%P+(M`Vk}8pBw-+8UjQgD^aAWxBfu-u(+7pUWUZu#DI8P+!MH@ zI)GJu`mLawLA<M;@reE0Zr475`M$&kihgmaWEfD}8yk?l``4#E%+;aw5{(!@2tYm! zj40Yb-S6dpqCa)?;t+rMy}({!)g$_${`CD||J$!!m6s8_YYiw$(u1&hl+BQ>yzx07 z@Ve{d1>cF6Z9v1M6ENQ#*V=&aqEr9EJI@!i1K54_v;o&`_Fe&?We}r!Tm6J*KHuj) z)xpRv=#JC70Qre$+!7u}{Mf-HU(D0YSfH6eB4{QqNUN4HHXC>Y;2ybv=OzH&)jkzq zT{Qscc|uIBB$<AH<YI(xXN+%WlvfV@73FlD6i~&zWeISX`g07-3nup{k9%)1=iR^o z|7Wg1wyz0Tp5XUb0Q;KJy&!5?mc%HllAt3s;*7)NSm@`h8xK1iNo%_e;q#w$*F{Od zNz)+-rRMe0=vS#V?=Sjy5i4KxSO>M0&o@3Lo_Uym{1Be!h{m`!$t1nQXp>CRL*DZ3 zxBTcWk4<_Q9C(^!l1V0+M)paj(P@%N+zb14Wpm8#;<nJ=QA>QA=w0;y6p!txT^k{N z0$qLkiRktG_6=@7L%Q$C+hIq=%YpV6vSI53fUnbzeK*u(AdtO{NxrKc>kLP#4EWa> zYw}QYT((sGNZJBu{J(zl69C-Li<|%+;I3!~IL`r(0z1qBxWNt0c#|`l?`X#ErLM<0 zW*Wep1Ff$x*YC;SyF-E`2NcJ^ot)<^uw=m!xE|ffoxn0XU<sV$baV!yFY-~I0)7#F zE_yFSck*673p~ctT%<Ze_7Se}qM?_a=<V!MZIE2cUgNUXpd#PMn3Dsg^Noa@(WhXj zK44D+tn-bGm?hVMm1giMHdI#n?`h`5RKVwyUAFb-RQn?ne5{$v4Tcp}epbLaPU`X( zj7cjNR2y)j{JhfTSg;S-MXquQ#4~(6ItM(>3C;mO<Fnef7R10_c8x2*v;2Yu@aycQ z><!2+^K1t2!{{r~J;3ScMsyMQadwb>6!<vLu?K2P-Jc1_{(JG|-`{!zwsU<(lDKBW znt?qlHi9Ub)Kd$XUIV<BfbvBFa5sSOHW0pGNLN%x|B4bYU-xYl;Jwc1UI5;UjVY7C z-TZxt8(?k&Fji&%Oq~f1F4(yVkZ-O(>wt3q##a;IjpZ-u*W<Zfl!++9`JP;s4FE>k zgRQfYwA?mMH@+$}nffQ0<W`h{44yZ^x>k1j$D@wSgq-M8t*g~QJq!iD%1%gt7%(pl zE$7(l&UjGkjKA*eN<>XJWOX6y`om5DA8MDIWEk|HfHlk_t3=c=;C|9mKWzX=F|a=j zO*C*Z8n=~q9eYa#^p`&GlLILXREJ%Ko;cTc+!%TSvCDq?F_wq*^DZk5P5e<K`RO6? zB@sA(3iUH>4C9J!Kz5&Y_W__o;(Ds3{<0&k*^EQ>*O$$R-Dd#cKp(&Umv~CloNv_Q z!K$<Wi6Fbw?}<F|!OWBR6NTz2ZW&)}W@{19E~=%!h!+3hVsv-Koo#0DHa}hiSVzKJ zZ+Cs0%+7VYa06Q7miee~wzmy<uj?_v4ZOCQ)9sUH6hvKdbXVd+rFYQ)<lFUf0qzT6 zdWvAn8V_CLV`{w5e80qIP?rGNA6xeJUfmDgW0lJWKv#fWQHxL84E$!lblHb+FzVO+ zW6{pCjECm{_eB4FZw_>43jyaI`^W$J@81Qh^!mYHFMvIMp93Ie!GbF8ywdSurT?a7 z+_4_tEa2~PkN8;Mv1iD9a@KKO+jte0(5o8E<*H+yqypCazV~&Fo34{KLJ~5ip)b`j ze-IA+b^`IE;-rp$&*KmJ&0i*>zezSA6AW&WUXq>5-j#iF(!(T^OftzN9Se(_U6N_y zJxS|A{P@_%WT}TI-N4RiJU9w_4E5LPG3+gyIKp{-0KN#a_t5&NMu56s{go#$?CW<v z0EHabZ(}dxQRCaFYa`BAzP9#D0`F_qS#&avwH?_V_qI1TfWEomB+H|BWBoa2beH8u zOAb8GpPjJHk03hB+2|DTK}434!&~3uXu*o1x(P4_EV!~+PF4Ojj~lJDqH2Dm01SUT zdOr_B^a-BfK0xtPr)^cw7gl-e$D1};;@#y<J#C>{ey=~zZU0p{sw04v^C>E5%!~E? z38@CyH_PW@jxYXR;u_b1i(D(g-i8l|KES)U4|p>AFz0}uayLH*wlz@xzvU%<1I%*< z_w4)n1OeM#zE=X*^NpWn`AhYEq2GLCD6O?j>H)T=7QkH?-@ELs*l3cT6AB6dyNmH1 zazMAq%#P8XF1t=GOA%Iof#z|#`FrZyK+<~7l6FRT+y2e#1b%?~vf+D_Cvm9B$UbDw zW&+Md51-gqq^EqVY3e=6ZL*#c$7KG#i8m#sAKnard93=Wk(iXnu8-;fQu)>gW0iL( z@K%o8ZbN|q$w2$=W~x?!?-w2K8P}fUj`iR=agO?X<VO30%@n$>etdSE1bc#Y?WNG0 z>eViN0rknq?V$qwp&BW1D{h4)4X>9RIk7AxUet$4z0bH4!hD(#ny?{){AX9(Bvh|< z!cj;fifApD=)Lyvo%q*hKGw~AubhDHrXJMV^AcC0n%xeuw_mr<%bIaV8LVT`W7Ld0 z5^?PM$o6*6zU?Xh4`>4I6=dJR4XE@1Muj87t8f9TE6B6!q=DFAj_+a=ceR^ue3UKm zTi5)o0SM0?FYR4)_*2`??1Zg)BEDz<;e`<|Yx+0oX%~0>?YOH=1S37)$B671XIxM; zfWY=RWhOw$5;!cJ{Zy6lURCQ)Hc^bpuy5+g<Y%|*DUA2a@;)~p-3F{X0RK+=GfyV9 z6JZ>Bk9-6;qGW8Z+pExV%2|{H++*S>0p`p#(0#@X;_vTnoqG;=^e+zn;(fr9B@1As znceqGz<XLUx)+f{WyCv+x-X1)URsO0iQ3<$A1JPV%UWxk*#_2)>)qch-<b0!AF#YD z(M&jI9HQm^)H>0^mq<PzIc_laI((8zT9-GIOwva_6@4gr@1%xFCOH-oPb!#XB)OR; zl2gX#BvU_~RvK;oK~3#)Y{U+zr^j&ZDK>16_5Pra#D07mF?|DTUC$3a64~{>E<ZAC z<E#A$SYJEz1*Dtxcn{rx^w5pZ;S6!Z5)@oV_x9;GX@ha3u7@HZYahj`41l{C=q~`d z{|(>c8f3rZH`%MeJ9#yF8c^KJ>*UPsH-Lm2EP;b;pA@(nJ<oOWBU=~1MK0&Rv&tFS zIjMonIi&bTd8F%7Grcc0&_3S?SY)XNDIc&RXNm{-cJ>pVh3u<*ou?psFRyS4qIX9> zkG`m%w*p?~JJ|;eeZ9zv>z4j~mY3^J)eiqW$+j-%N&}Fun+!nNWnSkMUB4wnzvg8U za;EhZxWr5PEjfevZ#c-Fu3jFU<l*RDMq8iYM6^w{@p6GBbE*xQEl#inB${#Pda1vB z<KsT=icUiGt?0q*gOGhZOS3NnC!*cx1Vl>fmuQ<6a4x!oyMec5kFx@vj_!_50oyzi zDd30M57aY|UE~wI75H@a1VHv3?#q4&;!%-CAA;!bzIpn0@@&rFp6js=Ns=WKyV6Ya zskX~i4P2g<EtG$|Fo5g@6H@-XR9|H$5)_})2Jjr3jO;FkcE~rF1SVs9wV_u4qRr2h zeWga<GObM27~Dmv2VdW>m&?4b?ho94!#55#0rBn3?5oC6)!pN($%rpnJbMU`602Ru z9M@Hk=SVj+Fk4Pj&`H*ps4rl66Z8Dzyv`CEV)EV8b5siu@F?}K0_NLpAhQa7{!r%b zuyMf6jCUA%Az(cby53^I`^129tn<E*att{UZb%7Cz?9fvzb*hN@d)J?LF>P9%kNvy z&Ww|xh63u_nL3BXIaJSatj|exW1YkhYTrZpXSzl?U3R2KnimX7_z*4rFK+O*4zs(V zKs6j|oDjxV6QJe>-nK)xRbax%5PP%jN~~e0ef_H{-z$6dcWSYg{`Q!3o(K>IxTj>Y z_Mc?q0<5PkO!;;qh-!&5#h!R>a~&U+I3`-Iv!BxzS4<l51?dHpyX*(g?}<TN;kG~7 znrh?&(5DuF+P+V80PpR@0DB%PJ%kx?%k{$W8@8XZ6Bt~8dr7s=CM|yzH|)E9T@^<Y z&i0BOcI;zRufNxB8(CvSm)3KWfO6Cs;_L01SihU)vipZH?DwfgdkW*U%Zf<H^e6cV zr@tul5as2|R~B2^Lgs9d0^jCevLugpFUjNAIZ4b?$JX-Csg8fIP?~V0PQ+0WX^1k8 zq<~!`F4yiqk9HR}d>+|v#gPQgFZ;$zy5>b8&yy|BDeQJOa=fOi+`g01D!(H<UVqwE zpJcF10QX7y`LV~}{6_lpq=x}LZ8~Cjl1U~RO`>V)H_0TO%hpUy{e3h^CX))ZyLEvF zx5nBmK4z&%#|2p5=O||}vVDjF<r<4I(-m+ZQqCdUtv&{sj`5?`pOb)g69MfcJGr8& z``b1y<IeYoF~qlRT$&piecIXgev@%W>Me`7{42`Og`MP^A~}Q1f5caK0r(EDavF@y znTi41)Pb`8Ga12sOyn5P6E!aP>U&uNn~Ucufb0i6#U<cdJeget-pT3ciy=0h72G}r z<96E6pUKEBtRt*_4CwY}--d(m9EmL~eN_EHHFO*z`??(uP!?#~=XdIIf?a07X?DuF z$in#jN7<9vOTbT~&+vVSp5ck;Gr;@#Q{E2zBTjN3`9{zdd18X=6p4!2DAkDrs%#hY zDBmI>LOGb)Q^TI50erU^-c1dp1~a^mS>1e(-A)BFd<Af??5O~%rw%)CG4L1Vb3s02 zS%0@rF&X9E_Lf=zb<;<8+iU9ez3nFntZ<)*5aNqn?-hY37x;XyPkey%fpNs><ALv; zWRf=daF4#S-aI|*>FcaVk78Y-9B0~u%&X++<v1KI#T;JZ@H&9xG0QPVoFHDaCSx(* zb*)o}tfz+nNz{l;(>~@^wZR_YV@w^(;(QE@iF0nYj^9$jOw@hsy>9|VyrF&>ca&ER zj5~ztY0S7^8}M;mk%5Umq4AjEey`m>gfjQ5K*sj2`lcP@QQR>ehbG?i0h)^*<KNK4 zA35-34ApXf$n$KbX9D#*>*<$lX7RT1u+Iq+LkKq7nA{Ub+^(&DvL%w*gBiZ&7uq0- zCKGpv{$i^IZJ>7C0d!BS{;jO%Di3pdmpw|)eaZo3$60^j^n<cvyh*IMaq7{Btp{J? zfD2eJtoe|AJ)Y}*_0jc+gu_nL27tf*9IJehZC|2cr?M79k_~{osJ+*=0~63**Q=-{ z0{EV*8t;)_Aic}}go9aL8qbT7IfHv7xet&eIkP)436SJW?*DN6#C+#6{J$4}vHa}; zaDUF+o-J6h04}l2R=|p7^l@ON30+dn?4F{sJb^Ohla-A}g;nf$;&o%J0S+sHddR+- z%U?^H2}q?s$an3t6@QHYzTxqY_IuM7fclV=!&I3VG_Jnd)@h=L4Rq~8O)|+5hIb~p zO+<X@Eq^K>oAfZrA<4wlJjo<(dH<w>o7k^Sa#%9Pd}Vf%_xDX6={}9nhcx-#$V%^c zwcc^{i`7PoI@WgY3(&<QF|@nh)0gSZ7x;HE<;no&s;~|BZdg$p1F#C(f~($=czKbA z^*qs&vC6LxxmG!R8?mtiHYz;tHv|0zGmS8q++#rMl8TbqCV&3__sw^51K8o0%z$kj zT1}WCfjLXPA#jj?ALSOX#mnsI=Pf|<cUK!ZiUrrnnQc}ztw{ZTY20A~WpjY*-Q2-l z5Iw-%+yQ)zJEK#;4l_OjT;c@|fR)}@NLlfbvSr~am$KIYvNuZoK8v|=7VAwC!IC@x z9#b-|H{`m0-byp{0MQ4H_S<64jEcd1i&+hrT^;3K{6DU3CYc*eIb(ZVZp27^|I)CF zrP050kWK#HBwKO-(LK=)3OLEhECt@mf}a4eARz~_?*V(<AO@~+g9BinMYe?O87}Y* z;D_A7BOtySy~?{Gx)6N<Ap2VO4L%6`Q6{sW09$OK$Tx<}jjM{WC^cFa3JCVX`dl%x zSE&;wFg!JY?ScwOzM^8{H-YX&;(#dMQe#xl3ZT2Fy{#(u%3xkHd#arXVl%@R&oBY< zE?|4=82`+Kj4nXCYaZIh)V}igG~dQrU!XjOp55gh24GLU<v#iuPKdu>9a>qYm9TGq za2OKb);b@r9b}LGB{sO`S)UPD97{cioOGlHmQ8H9fAu{9Yb>C(a@wgHw2m6fqs4*i z)v+QJ1t27`<||{3muU}xt{6>=RXySXcCH4LN(^p?CNQ#1|4G0}XKMZa9eMPYsZQqQ zAc+$E48&t5QVanWh3HB4IH_)k9j|*Lz`D;%y(j&x7iVksPZeB_5CEB}a~t3q(nc=k z>tY^0HXvPf#DPKp*giXQ>9vgrqUd)?%X<|5gon7JJ~)U7+7c|%0Ke`d%1|xyNYU}! zDy}Mmp64S3@g@Ew4m~Nyb<#6;F5<v#0C6W%dsL4vRrRduA*^|>3;15er$i8AeREuE z*3YbYY5+}z#~u_-#&$dac$+yqvF1I+oj$@5;Teyl$G@vGPU~)$>isgZ5)d+|GoQQs zpEQ8vb-T-f!k_WfqiPRX&T~y*ugwUbH0)8;=HF)f7yZgNKDvLGmY(bFQ32{z%@5lQ z`l8VvG<8JwSb0LH0_Mc5r~vPC9pO&-f3Tura8Ft2_;DWRPIW|4@junEwu-<-fsUd# z<8so9JI5Z%iRBt|hH=C_KF&s-m)nV>N%`q_t$rk}r83n0rl1Xok4|hT^gQl*IvsdY z*?8+7HvoQ;N!ITClT70CJ2&3^&6}&qf+v||l1V0+<d&CdVNquZU26h$lWOy*nA@j? z?YjDtN7|o<0uPSbU-|m!V&wA0BWow^VEpdx=c-r#v+ZjU*bdFGdUX_TA3c_V`^ev3 zV=%!t_26fM7x)=?yX;K%E=QR47v=0zu0Hl7JvFlJ!#o1E0J<yvO95=p1NHfRGYyz7 zfUYldj?2J%NVIQJ+U8V)*}C|gzo#z6^D3ThQ^QT>avF^8ZaKjgF|e)wQUayxZK#Zc zd+W^X&6cz`?((PhV`BGxmj*EWQ!)2sCWCvi5fozI(kfr^o#+YE+UI~3a6LQFzx<~5 z`);&L0_qdl$9WOBz$4MuAo^7FAwB?nF(P^gu)`K}ZEta{9t8lrU|>&;Zz|?_VF1}p zyIYicQCUhIxL#*)uQRoq&x2}nBdyz8^cBnglm%#Cd48{aN1f?i)M{5<C#~ynv|nM} zE{m(mZ}%&=EUBMdU_Ym6x2pB`X1_?w_k{Ed>DaJSgl{A@%hhk@pLRa)FlOG9Oso9k zx~^$wy4<9m)Df;z+fEP)-LO6ii%9|!Rgcn+;z7Lnn~z^83;43B9vk{}xv_eSj`kVH zPE|)rRlKI1r#%yy<DSgLY9NDSH?z7Jb!3QJm}bZHGjV|Zxa5oOucI#+{xXEI*;n2# z^wf7eT0a)OnZw0EyBJdL&_tT96Yl!jYus3a%if9o!Wkcv1MSw$v^;cH?(ic)C%&c@ z(6X=C{W_HC-j|Red)T?VecJ2UX2&*gSars_OhC5`9{0K!!rKTyLYV4>aeWf-+^!Qv zT!4Syu7X|v*t)_OZ?XZ$&F2X3Nej9CexP;yl@9oR9RRJY_Lp8iCmi-0d&d97(Ju9J zh52oNe{tU@yw^)d&+!Ap?f#(}dUcmyB6)kzb;5eCXuQvrP!L-T>Q$nSDCf(f^7E0d zSEl`KWCQH&xU}#v(#KYLB|hf<dO|{4_A}Y&M`k^Q1uT{xMth;3G%L#^HL*xiGP%d_ zPv<8eo4*Wyv-s=R{_PStV963FnB14f=b4Uou8er4EaR0zpZr+Grlb|WYl~N<Yn*gA zMA`_QLdKY+jDHHxxIb>pA?~pcC0phLeTn!?e<jQBntmfSBKYIRGsZiaYm!L@hASqS zB=>F~5<eH;ob+(h%5((CBsYUh6P-yWndIj8L${_Eo8}S6)m}Hhrt1fMRg?Y#`_Xzp z2r){#g>H0(>dDXG<lZRk>u;+Kgr5(pcQ}mO4cuOru`eCC(H+7h<+HaTb{5Js=3;s> z@3N18m53;3{*E>COu+;$%Pk9Yv*QNe<E_9`*;Bj(+4r+cTm`<Gy^9OLRjy}yz#Z9% z=<C2D2SjHtMZe|^V9A05;N7f9fR!%E74`tKMb6P3eUk+#Ig|Ga*waw>RS9%1eqWY> ze*xLI`57+)@5#QBJpnwF&7)62bT0Zn59RkqZw0>0R(20n1nyjPXLPrrDUn^u9;dlc zpvn!YrDo#E8QSlQ&N3t4sF1)j+2bX9Rl)S0KRf?>B|oyZWN?o)qkF75xM%D{cN*`W zv(0&kwl$N|=h-edXC!b#A8{*m&raFZ0P>t^{t|DXAbXn296)x8pJgvY^iuRFmmqr} z`x>tSCpgIshzb&gmENd5%U#hu5WS82vIX#^=x$Czbdq02yAYk_PF?^W&91Ny;>GBF zoB;0RgUld09bJun2+@~$GRhh2w`&aU&Hhy|&!;8uI;CQ8R|a=`0a(`n_Dn+;A`_rq z0makuvpGJd#@`edLwj0#j=nF`pCg?pk-3=J6($qCD4E`U*V&tx#r0L0%-^d764!lL zjPXrxRfoX)7~X}4A*zir9{j-YWrKk$9qbPYynh@f_*)BjKE-&(vz6OJgi}ZHXzTUy z+ANHbG;AInvW`-RQpav4(fa&cjiy^Mf*xJvQzPnb?Db>c_4B6IuW^rlIi@X2$0|&% z`Hc4ZiD0(zVSZc$muZYRKs@-2l==xiq3L;Yq;hxIQWSVnT-K9NBr?~>s>l4VukHI1 zDbxsw017w5uCI(k5+;V6_t2(So7oroGxnPa^YNg*=}tW8Q;yU#KWWCR+8M69JZv1$ zkJ6xa?Cgh;=wZ*QqyDb>f}#oh>>EFe@hA1y*{GZL(Pfvm-qVhGiSmpi1pwdu9_cJc zY^<V1!1$Lq>`8d~yuf6p7cG6F0$_#^Y}h&%mR^c+qH8{<T>USqm!pVr6`o#2b%1c( zGJX{&EEE9g5XSTB+3gJY(wlHq)n7U6&jeE2e$DMiM2#`u*AHU@@a?h#=}l;?+mEZi znRe+*6fpthw!cvLf$WJjudVt+{kq~llOf;q4?3YO`jWoqi&nyf&GheLaIf2ysGW=$ z!uVb!!W1Xd3d_#x@2~gYipjl7NJx#E&y15cm%vP~yz+BD`Gc*U<m9J-<zKFT`=XBf zu5^4e)p0))*j^EE6oegVd4gnqVy7tWp&u!cT63R^T7A3LL4EhB?F6a0{=46?4xRO! zMfFYibnTZNMT|&BqGy8QTh^+#??jbJCfVR}bduXt)GB^?>-?mLn^snn3MM%Yj$~57 zpn%RKlT5NXx!r-=p$o~?u`Bl^wjGNR+xvF!4`Tt*H`R|+0OMXrxtD9&OQ_uy^-c#q zuPDc|qkgVHe8{{@2G(~uvi+<&u1nWsep@>HrU<Z(xTih)H#bFXgJ6Z=4)P;CC2*h_ zwPXFc0KN-AJx%uL>eGMuwLgIuc%GjC?<QdmEE_=GI$&3nK;)tvHD>FqV0vF-234C( z?yA95UH|4KUgrR^7rDp*@Coi|9jnqFW0`9CHXS$)R!s7Brg`5+X9eb0t#%`f4J31e z<}rTE8<6h4`AD_^P5`@vM<UNgC!-U<8Qz+m(dBu=`2Ej#j;p{s^b?=piR@Rv+j)c! z1OH+4I1fU!!<=n$#-o@fvy{>sKTCt-zpxYYdu1@V=bu;6r;P8@^7}e~-3FYy7~PBh zWZJI@j8_o7qJO`jw|_4*?ib|-RlObEcD!mZwWX!sP>$<Uk1sWW@ooLZ^cyZ9x9IRQ zGJqM%)Z1{lmm1Kw+Sd9iXdF3w=Jvx8*)yTwc9(S8tLfeM+JV=Hw;mFQYA2%CJp8!C z7vdw*r|JN1#Ut9|n6=tOV)QVkZqcj%Z3_7A)928H7a#L&y0HX;I+N;{9?1o?+EhPF zJ&d^P`)_Hjv%34Ifaujge_6<jgaL`W%B$As&wW}Y)V>o>dDl&dkpbrv4P#2j(;xbc zEW**B`e-^WPm)tT?X|u9vS&F$#?8<KFwvtN3dtt}?YE72JT%_cRbSt8O#i6}XHt&` zFsZxB8|Yu6q|<JiOzAzIUozshjlXUFE$z@pXd;5>pbqgds+)FKFwob(|7n9E8$d;m z>u-Kqds-jn^)|hP-si8MeLACP^%t>6FGV6m(nx%$1HjGawE^~JPraD+vw`e_CL^-| z&vov3mCYcZlnDs+1Sm5h#018h2@7UBm;id$eRjQ4570dJ=u24di5&oXFd6h!qkT+W zHJScpS)M$RLzH$T4STAHVq|$DY7ESokpOS!AM+t{qL!8M7fp1ctdk^H`d>>UBA3=| z$3Af}ZH;GbLWFbv)%WD3I>C~ia1?sdiig=fDwx&3JYfAX=DOEazV`hnsfl31*LU@K zW#(Mx9IvR!B)6zcLDNb4jU_+-+h6_mos%9WnPie%P}DRg9@Cl11Yw=zm`#Qz6%6pN z;-+lhiLw6X96$SRB;9QKhzIt-q2;mzTU`u|=|E<txW`e@ZO@e+CZ(?Dm`9<mV=vuD z`>r?M^f^L&oB-)?CO<RaFD#~<nGVDkjNb*5dvWw?jDUxU{(1CF^iklGe48&o^ttFh zP6Ka^zQhlK8|+1Q0H>lQpC)Ho2cpybiaD@gfdJma7LYTrD~L|Btpol!Gy0d=Vg@WV z<adii9|4<NVjP`d8(3ybVql9c5{SOf7kL*%cSb*o9s&L|`X!%+>}vL>*~j$rmcYyW z8J{(D^8gR<pz-+>yEQhhd%2$nsWv2Lyw2-@)Sq9;UgL_cPYxD-nX}};=@r!mO%bTS zo0FUXl)nGE)<*%fKCM3&z}}_a1}T8*`}&)r9q(Y59i#pBc_n)ZNQk2Z*kv0ay1+-d z8|07P^7-gG{4H<pWKTo%%}DW4-~=b4UEr1M-t13-G`r3ccs-kEzlQ85*|XV6;LAMB zy^y`eE7>0KPR{WRa5v{T34D&1SOO1mf<4GCWY@CyLG~Z1Z>dKhdq=dzT-#mZu<MF> zeN}GZq`*5hWV-;gFS4|j`jD0kNXnUDp$x`%li|JUU&{G?S~4ls8R1O^^^^)YZU0{Q zzSM%YR{(hBtbfz@7jS=HLRJ3!g~OL(l&{H5UjN;eRlxPe@0pc27IpC&>T+hQFlP3s zC-6L5T8Si^n5!P;3OSwD=f_&Q7zvNh`r)_&v!#ovF-nfc?z6sn3Y_mpZAZIrwq0ad zuO1Q&S(k4*@q5g;!Pxy(j<l{A+J9#wuM^wKF?1cd&imsvf%RSQw;40zky9s94-hsP zsUBSn#PK2ZR~h(Q-xC9DfOg;V_CLW+IrTJFB1Y`(H^V)X2?!i3z7~7*&^>1s&i=cu zpSBs5`<A1vJw(rPgv1L~V2k+dduU=qs2%td(E7bMjbvxsvaKI=CGIE>HHI!{_D)Z` z_!3v-+WKfui0J|{Lz5XiEMY-(0PJNW?jRlWZI`}X@oO1y!lv2JDmzxK{?Z3%uHGv< z{9Jo~j~#mQokU@kKdJ-Wr89BGJ{i?_y{kWpmi9E`<1PSu^F*!k#Lk+(kwzTH1!Om` zb1~V+`iaUju1Je$Bev|P0@Mquz3Yj3X(Lgf$v7_@dXko&g`+&Cw=fe9Og~$^zkGW3 z$=dr0pnIY{fJqP&>+cgdJv%X<&tSFOTm80(<gFk(&~eLemM2wWF}hcAOEb>bHr9+8 zmrAU-S^xDfdLLo4afdEu^`vF~);6AZ&F8uR{$sD-<(f|`^sr|ooJ=ywhQl3`OyZU7 zAUl;kGU;KGNhX<Ol1bKF5KYtiqn17`5KrxOi}k;-_FqgZz*1i~e=pwD6Dmp8u*W{* z#A3~Q4&ClA`c2>W#{=pm0-on%sOswXs^v)Qg3-HAdkr5Sln2ltd+F1D&T?>RWH0|1 zYWEeRcb%DLr2*|lKt8pY+!y-#^PJ%l@Nje=cK|;@m9}C6h)vG*;#2W^uGfk!+x$K4 z0N|Pc6IJ_v{`ccN8r=oaN7&~P;CX&+*<5wK^4O$k?S;zuJd^QSwfYiOW2j#_p07N2 zs~+|s8h=HtZlVm_TTEOX&wYV6xDLFOy^&o9QeLe6{@LiU=sw`{B-t;4U-BH+fh)Ys zFCqI^d=~|5XWwOu{3u_k+q=HOnwFgQ`G!wg1GZCs{?i(;eW||}7PEV5F}N3>r3G}i zlW{6QdZDkh*1pQJhqQ5$LH)BV6BdegNNaYpD%+#Jfwk0@W^Zq=tmoKmDDW}HyFKZu z!v<`|cHapoUo)-;vacK0w>|&s9Zc=|ec6`+%4yc|8#N!&Ez7l6hE3-FNhUcil5T*h zxP4wC)?T|fW@6b_I_oJ$Uo#1sOmHJ5U}s-mlYzId*ya94;QREvA^Y-%?X*j;Y9OQX zSnJbxU@MKsq`tZOhcF_K$FSdS_k9yt`Z78<+f@zHXWzv2q<8tnTJ0#;Y=^Pq3`65U zaorD%>Muh9ltX&9tN(}*%IQBraOjCi?u3`ngpRalKkL(vL_j|><4fc8lO|Dv>|v*U z8PS{VI4l7v^u$3G-0wsOz}#KBvh>+^g8Z5d2<{)33y<fCRy*phZ^0NHLgZlsi+y%b z#6^?9gsrxO4i_*vX%GqsZ$EII6lf<}q%9{Lh?eL3;<Xi^S$X`Ok1-u5VA{OTcY=aw zncp-Sy~&<z882n2wb~Vt)sKrr*+{zEIn#GXiKl)N`_w*Rm0McnQWk)`Zf|D!ZD6=< zPj;eBok`uzxGr%g7$}2q1?#=S>Sv}Nq=&iPE{{21t^?ewIB1Qby=ecaULWCMpf`Z- zQT~jA7)EN~dqM)tnUg@gwLSa8r(t>U*KhmFbAZysE(HOL&;%wGK}xD)r1{?!?wIXi zo$Rd|{-oHi_**Bi+t*LUni$x0!1ykDj^iR=-jaA`e{Fty=*doP^PbT0z3apyIr92$ zlG{=yfcqr<<WU~xfyrhknPietC#+Kj-z1aVs*>E~<v+guY4VzzYVTt#(Z~z`Y*UPF zH=~FidcVmMl*)j$WYa)|dcbVmBNzP}6k&{$K4y*34c<_OtI(s1H)S_tGlq>_uGC^~ z7iFM7E*WSN@_>BKJR{2^Sb^;S&Ug7Z@XhQ6-hk}an&JB~?%*nLBiqaNfS8lf*U1^% z6=av$X9+Acr~A9v*9i<cr1u&JNMOZ+6u8bF3v!0@C2*Z<T+z>4k#BsO0OW#M{VV)9 zdls?}@kQ<gzMj1ry$_<x;v>-y$r;v{!1wr2_EtkbFR;grN*~cYI>8w#p!7v9aEUw- z0N_;47|())C2((ajveFqzs`Q4udKEQO{nWt4p{1PD`3lDGSBs~(sq(t$_aMLJ}iJ; zc5+U3ef=9;Cf9q;;C>G~(H0;`*aBYQC0>JUi_dTk(yzVwnd~$~yX<g3WaqP8UI9*U zBD(<5i@;OBLIc9jM0ayH@b>JdDB#KHd~_Pv<(VjNk2y~RH@Ked1Aof>JOzA;8=L?R zxX2u$bI~2qM}cj&3V?eQ<6<yNYru6#vs9O-fMS~o6(*29#Z077dPAt5*x+M!Hv!}I zgbg=<J+1ZWieahpflWqtYWLL>9+t-Ub${hf$XJzrFZKBCwxlgv+wF6&0<i5$JZdsU z)e}Be9dnp2AkMPWr>YiT>z7rJF;?9SGt+7HGObgNfdvg+m&6-rpMC&Uu@Ma=Bil;4 zVIcf)Ae=aq_DVYSBZHVu$L;}LjHH|P$#V1-ar?O;K=*a~VHYrv4fOM5L_Z>Wwp-i% zn_@N}TK-VIsX)kem%f{Tsqy^by1=6_hUwz@Y9xUBIEg1+dJMJGJ}29Sl*7-M-CmBg zr*@Np<#0VGG|tnWP%j3JV+BCCo1qqOYQzvbZ33yo-lGEJie2MsLOXCzb=YG7pgpqv zL)f@1f`E=TgLa#qeJ9oU>Mxq{^UQiqR3xIdC5V{ga2J!kk9l3RFp{^~x#(yg-w7_N z!A$P1pLE=3>)8beZ>v|q=&eA<6f1q-p|3yd)^BuPe|OgE*EaCK=oc>LbvuS(1G{bg znb*lkIQ^-~v~Du}n|{YESKI*B*MFA|AbT6Yz6mt1pYYWL##iH{8|YtW*00`nM~w(Z zS^e2Aw?OhyV5Xtl#R;edk;hB}-4kZafRrUqlE=YUz=CB-)Undv=l!uB?~Kd%Wa>N_ zvLd|ry;}PYB?=2o=#qi!vG8%Z-a}_=u3M^pqCE2j`@{v|jRne@{r2<Uedf<HKs&zc zmfCJ-j`?z*d2JF2<4u!HGB_MD$s}IMPRHriyViKX`T^vLk!X@hCYfZCTURD#_el<u zIqi0r^d<u;pBnjrrw7_!a(lH)c6!ZzEJyC`eK)?(>3W>;`i0GvLs@zdBicjK2|!O< z@9#ePd8nTi-lOIZ)BpPu0S>o+2`ey9xnYuOKs)7M3CuNMIz_<K@Ws^+uKn~+;4&9@ z27nWstkp-=IMvfk*E{;N8X!1rlq+X?*55~8Et#%W<N7*KSQu|3`#Dc>5%^H{G!l46 z&nSisBu*W_o8OxZ?ri~J)c_E?nc!V8V^eREIx~0^fFZo?ZvLtoNBN2l-;$T$Bqx{y zr`Tn#%YDPR_NUpec@6jsp9kQrJjh9i-WScH*CDzZJso`xNSQMSVrG1n>WE)c^Eo&> zE$krrobi2XwM1$i<!dvySD#bs<bbqfPB%A@Wcl8zeT4CR7c;sIaEJOS1#SR5W%;2A zq+VI=E6NQmo9U{~1iy6rt{hg98vm-lzb+>5KIACmRrwCp`rM|jx;?#W^>6kG8sYEn zJEz#hR?ie&ourQ(^$yZ;OR%-elLVGdjmY%wdgJ~`?W;NfKu6cU74StJsr?9#9UPWE zWXG>+ly!~oy<O!CWkO$<0o_;M?)S>I>^tdXUKgXZbKK%b#%k9(W2xAv9}*i{|Mmf1 z_e~&BPJOM{pF{N=_bj&$5E&ZJb0rFdYpPrSY490d?Qxrsa&5}i@)PK~Jx<%Z_BsHs z{j}Y#_t3ahh+S9qF)XnlG(jYGl()}`3w;v?;+}E3eJkD(+U_Q!bk}=6Ypm1afakgx z%T?gKPIf%c^c$`OC|kcbj08LZ(GBZ4SFCZzH&1DctJVR<?()YS<GyqNGV4HmbiB~X z$REXJJh2wpiYjJ*w;fjTwPyWnhH+QoR*V}UZ~Kwd1GvY*%<l3Fu@$jXmc5t>ZNgz+ zqEUb0WNw$n377@Y8{oiru5k2kAJe({es}z_e$u3m3En;#Ahyb5pLpRakFfMs2k6)9 zBOCX*8R?5S=CX`uN`2C99!HO(88IcH$?P3}|JgtM0<gOJPxs#mq^wv_5xEErbg!7) zi<2t-gbwKj<5Od-pIn}AHemkc@+0>8M)p|$Q!9t`%+JEcuj&L|QI<;p2c=(@jrpF` z^;z}QXK2FPCg;PGOwv0TGRY+N__ejVYyZNehtVaS`r;&$Oft#Q4Q`VPZd-{bYaV4G zJFSFn7JFAW#e6hAGz%ZApNQb{AEgISLA*)h>ATOyTibi%fbxeh)%9Wc+5{83?Aae} zKdeUTpJFt-4?VhDMD-1h;t16|053I@yU<KCf>?hq;9+<ydN8^N_#S`84<I_BfzBV~ zET@2ZbT&GzYxXHXM4AzuUm_t}=&iv-YkXBQZpQ#ov9a|vT^>~eRO^8Dl;%<L0yx7- zwtzc1!!B?pI>`?38}8*ba)$MS8OLNeT5^L+lp7@39yfB}cBW7ey&k>5Me>b?6nK_j z^Axbs8xJ400QrLI7}=%O)_Fib-{^>Sjpl6W`WByMZG&=)L<7pvzbCqF^Lp=ShWA9b z*A_8LAl6L$CU8Hc+6X8%G9Ta^Ghmk!#K5<>q{|)azY7k4Yg}gqTw_lM;?r_dAO&{V zWea$Mlrz9CF>_GgQL*|i@c$Ga%I*WU*=7#Rh@*ribCg2qb}E_Nb@GF%F&8O|$$wD- z)K$q|ZUD<Oo8euQ_p36Ipq@aH)&T1EG2}LLk}{qQE@q|5j?Kh@rPYU<%<rl7USaip z8`xbjuAA32{e~Z~ZpzBzbNs%@pU~ufU#j0Ddiu{a$a9C5qwPIM;n$Z;GD-KiKIS@e z+~<wAj_K2<<mfdC0}vnfI&n;Wj{`DP-tuf(Z$kjdht(gHWk2zV_9+I$5t5PZpbNm; zr$34{>^WvVKx*GsNk%TepAq+P5~O2>1F8GjtQ@Td!eQ^pn*FA$c4`g35&|HK2Qt$4 zWvm`rKKuF*;B=o8_*BnU^7NZ18CVW2WqN)*5FqBWmp=0d7t?g#`Cn@Fw>a3|yX{l- zXm{D7FBPEAxE4j})_YZkPHji+Oypre_N3EqgfZhQ3!3Rq+;aE#P+)va`$+@#$&Wt! zl%D<}TJ%=GPc`h-cLITc>^>bSd@D{sd3L}4{5I>p2dwr?TH*tB{kZ3`B0wLa#SU#? zdu+9Y&4At<=Tu|7HUZ&jBVk8ae#PCNn@sc-9f}JWZZhPXK=If*(Z~j(3urL0+vOEj zx$1g$1NW8new)$W1<dy`!@J63CoV{X5nme5NlM1}{QEfjpeB&X<F|8??5jY^f5}ti zjP6SvH(Wxt)F+respFOh)=8Bsi;!c}uy%Vrk@S9_T>JelyIwWuQAE%>NNpfeuwMP@ zaqv+6rk+IDEq(v8!)FamK$~Qejdk`(ZaaDN{F~cvzH8FMv5?8}Pcq3QldLZ{OQz`U z#JoL?Z<9=Z;&}J_;~sz*qrJpU&@Sr&dE(w%dUZ(yn1@^v&KMTXaM^y8yjaU_T}Q+o z<+wJ4VecsWs{r1G$si&$^I5EqP>nTEIw=9~1;AYZZ*Y)(Ti^Kv)cD#>fN=eo<NEh` zIqLQ<@_>D&pA&tpWXe{aqgU%d+TyAmwvfPfw5@GBt^t<K=N09$H>~<Hkh=a>{WA0k z{{E+0?&^Z=>gSXj^*e+zzStXT`Lp&pU<DlLM1hpzsMcK0L|Y`liubSpuIJZ_JH&6q zqrkt2-W8oB2e@x(dwWpV#15^S2@sG*4^d}k&l3u&jh%v_9pgGtXK;@`RBpIcOzbAp zdurK-YB0qY8+`@ydmRwJvVLEdpH+Fi+YVK^*;hM3AWNO#8nb=sCv()_WB)FU+PHz{ zZhKsMt~UVmS)IXM_^$K%r945wzE5@Z6t}Fb=ZZCEB4ccTt$KKbvHksYsPHsjH+$4! z&!5GS=vf2;rjAEEW#~y+GxvDE@%2q#pV9-+9Ss3&4{e8J4g1<$uk_o?I`3VFk$epM zvKc$o2K`7HiE@22rXOmqi<|2~HA4Bj7?lr;sk|?M$-}6-wqID6!9MO8w;5{Z(hD(N zZ(h&_#1sScVlv^5QNCil9g<+u1}qM>02feA0Phd9GY^0_`k?;D`>ps>csZ0O;U`QF zp>{nq{#XF4yZV<u@ushxi;nnUyPq1$WG@5W^PuB7iD$0k1AG^2_&Csyho<>diE&~5 z-)BuWK}X_k-#XL09iL7e>j=?e&$2@wNsC^EV_a3ds}(qImm_Hz2VDstsl)EvKyqcp z|D;uJRlB~~@7#dl)WJP%0;v`CIC$JrFY`KCi-}b2Y!XbUnk|b4kx0Ef^?JxgUvLA) zUG{7O)Klv|JJF;s&^;;Rzc!IZz5Rs|&lfelxS8Tz<uL1Qo|GyfnrjV69cQ2CL?>rv z|M1bj^AP;*oqJzDcpg~k_-a9*vdC7N(fytpu|~z{F3NZ*j<}-;IvermSNp1ApJ@A5 zfeC)~_8Bt{F@$I-G3Ld}_-y)9*=t@ZoGD(3V+`t}uSq7^c(8GjNxFROTi^1@w@d){ zNhUd-GEEpJndDdvnbQXU<R=eJ;;Csz=&>R8Gp(K4^mkl%32xSQ>dS0?*ohae4YGCm zli!ZUK8eD81Z!Wvkah$VkIvr5IZEC)W)5vvdxNRk5RoOYJ!h7QHM4jQaG&eH#ir!H zdh;dT0Di&Gc@eU&bAuJ|lk7FF0ejrY_JBA$h&~1^*=GUS8__Eq02f)XBxeAJoKamt zc3lJ0ud~wS*yRNIk*!PME*|6&@}paqz^}6J@G7w2br!&id;{PIJi!IXzMB1jJ>dP> zd0qfM8$Hkc<QoSI;0|_cdVP``>{A7X&5fYk-s%A86-qPh<Qoz9afXD78UA^SBS!@> zCPR3>A#u%M>RAD2NZ6qQbYJ73_Wm7qbeUAi*q*mb-hNkDavg|?HF$ZK86cUFXuYo> zyNF~7(TAd+M(+nC+w6cko&6yD1hC7F*31_)Lr`9Z`?)WA5Tdt753vG1&x6@Hh|Y5d z3&`$f&Pm{f><z8~pXAeAgy{Xz*P>4YpX6=q0RM!OoCmhq(hTke6TPsG0A7`h_^HuO zidD(LZtAlFrmt!V6=~UiX${COt^1V)q)tnw`1;0B>bb7!XKo<-s(dfHlsGq@(z3*Q z-4eZ3ze{xj-RpDfZXkOdknRS|3#+~>hY!;4i_W+BpVZ^cx&YWqORwunJD>gW1B8c{ zr~RrGlN|5)<gj_x&AyKAU;b|3(($ZkJ5V?|ay|EJ1-U^z-MNOHtjnl8=6cR%o>hZO zvwlDCVh$dA-I6#MS=Cw==Pqe%Jijgvjk;1(7C>bzp#PAQ)p`N_JMBVjr2MY>geBGv z(`uhY{q_3sc<X*&dy9d3Xg@h`ePF!V&q5LtL_j<+9-ukVBmScXw3i6%7a_oKIbgOP zauQ#kL@ygy>uQHkdys*8!4Yo?c~9B{(B1`v?@B~yJ82}8Dcx^((gQqKtut8V9k<&V z)T@7Y0p*308MqDj?&~*pqJn5d49qyMo7lu;09UpCSJ#g#vCNk!;R9sXpCcODcg2?z zhke>7@YI3o^^+0pcC#7tRX{rzaWUo8UmfsToD7&)b<_SL(*8CpJ~tWQMWbEJa;H}N z$5#9J0N=L%NIeYd_IncJvx|Y<1Q6GMuK@L?rlr*{MFYTI0ruSh{-%D+dfMfbC8K+8 z5$`ZgOwEDrRh)eWzn}cQU;W{|uvq=o!+(*VI9dSP7v+hTD@_Em0v<0<xJ)(KNS)Dr z!CM?-=a5-<ypefN*Lt{XoKuFbg*C5e8~N=7lGyRQ6hD)?vfkkHPxfa)^TeT}iZ{9v zdy)ygHpzH0fix!RHx7I}e%s&q(xit;CJCH4O+I##NhZ0~{aicq)y*!+P2WD#!tqv< zO&sZdT;M9|CToX2M?D``e;_sx8Bl@xi-V7X7JW1tdFqj=VeK3x$JD>}1w3@MZ#vkY zwEK~YU#>br)nsswHNbtYfyV{l9VGH;vj5ZS6W8wk6S7Y*;~MZ2&T$@-wcQ4`2&0c; zumq_FLw5dKYF$^?h$!!?|6crkI(w0ez&4-KcbqSo-c_wcHVe9PGJn;5jJs#49%F;@ zK4rM&h4pdw0k#&Ly1XX!JpDYUI04+nX-?|zUN^4$InQ$$_?X^sd5F8%0`bG>v1lKn z|5fx=z68J)TiQeCn{m=Qt~h_<tlX$67}@KL?ItsSTC=A*bCIw%eyYzE<5BV11c=L0 zAF19rtOM8+3rH>uW_Xi1Tw1@+C;;Pidz6h63v%%>vd^-DN#4C3AM2L18QAUimcg?S z)pF*5ACR3|{U{Xf7Y9B+Y>rTsLypq(j$*Ep1|@p+9dB;+IpR^x?}zHD$pb2TjWaik z-iDSxErAl+53V^M+w^>}i$_{*u%CwLxi5ojI#OJwsi$#TEnf4asImLA2)stM%s<y@ zb3f2hj#^LG{6YXCk{j_OqA^bxZ)`GwO~Nq`S+D%kX`5Y%2z}xUBEX-Bfxi`iMA30y zJaT#ItuHakcoTP&d+3-Kd-|gsX*}ysP~i4J1<-8f=vjRTNraW?8>%POk=Pao*rHhv z;caKtQ4ZPq{4VBi)$>G&xB)=*mtVBhr<gyQK)Zh9M?V4$A3)eQ{@c-)A%J)h@V>Mq zp~y8~^R<`o_#fBFL3IY|_PDPw?AwfiiOzOzpYNn4aNTF$6|h|d=sxzepIu+u?wj?i zzPCMfTRCJ$KeB<<#r|l5C{Hu=G2aWPUl!#$L$vhg*i&B<xZSlbumSo$`*5{)VqLGt zrxM6s#n)s_2Nf_|8QkB^d1*xe(gkF%N1|;e_@q{r%3e%6HG$@_angjD++g~{y2gc7 z-+KRuJq+<CK;3*^^MnE6WR{Q1`=!+{L|M|J-1*-e;I2xdk7t+z`#i&YsQ~W#nh0g7 z311ehv<~aQ_Tp4cJ5IK=?0Eqe5r;2sCwraTYy0)Ig>l@~j}mK~vlDN8GH)4QWZ?SK zeZoR}V$-aQAG`bGSnE&K@Mogu{p%4*O~kE}3|f9nGD#nw6R*zw_N8M`kO{Cg$;~7a zv+g95OmZvBivt!elT7oZO|48OI~#fO&v1sT4Ygh5+sNT~+fSx8%a|FhJKr4BZwNw; z_Fa!T(8rkJJHj{#Y;SwRKpw80IQ4Netyg@^ZL(ynkvf>42ihwp_k<Y`6Gt&RVE-`D z*Z3UYhUiJ2;YYypJj%nsi_uyB4A^Hc+6DG_o%aHB9eCf>&s*rvF>s*EvjSorxS#94 zyX>+JD9w;AQTqBk&_6?#4CYGLBL?0P-OnlDQ9j2R;BmH@0pH~pyhzR%za(c|H&4Pl z$2oQlTUuooEC7CDZ74{+iJfn8T;w_n<N2u$$*&B~Z%M`IbBZmtsTkaMm}{o@+{4dw zy^6cH%0z=)mK^B5nFqe_WX7B-L1D%o*MLMrpSLs+dMDaOLH3pG=h+3|M9$zIJ<c!q zC9uN@c7Yo#xIo2pbA{Kkmw;!p3!DLd&HcoXJ<rQr1>VP<Tm$am40GTYz%Fo^>l}dk zT=rac7P4ouEj|Klv#lB2<C4K$*8EWY2wt19z1W&bt>2Zwn69k*%+I3ad#854u$cNy z;Cl7e3TU5}8*X&~_Nq+CpvK@{0j=wwg$104IzZkoNAdfT9jm|BJ=Dr`pDk%1qq%)u z7vOy5N!9V)R{{EmF}4d&>Qp+iPhaO;us(M#r)lpbEiy*p_gEXSN4yppW&Nt6<C9>l z0XZ9;kB+@@owNYCHmRpB>ybyM7dJp6-cY~j!>Bz*KMRdVB-vK4`V3{-mci{SMxhq) z1FXjdpu`>RJeIvC1N9#sCy*N{cM||TjA6X_+;*nxc+GP5x2y2yik|&{Sie)w_)^;I zj6t(pB8VA%X#AtEy(tgib+}y)dw<uwPYt$T<-ISA(Ova=pZ(sD_t?NgMSli*8IU?> zCk`vZf%aW?Vl#)E&umM~QC|P-9&gM9i}wClwS#b6XOE6u4CB?mg-8F=1DLGO&s4`e z*afI}^(zN+diEjx?~mlaXCF4oA3NqVZa?o%B=98|R0&Hq<GT+?UtKR8{n0lMP`Cm1 zx}RmgHuNum-{haNr|>hvoBBww8O!bWP-Dif`nUUcY4!iaVoJ9`{U-2TQUR~y1`xi< z0AJLjenMokz9s{`%@8k)`)okGX@9Z=uIGsb(tyJk@0WTWlz%QxOwIpp=W*QGnVt9k z;T%Z+@;~{lc~WR`QYrfHfsRL;aZWStCW&t9_(trAg9)o2b&WrT-MHpGq45)!|8z0O z&ql7l{a)EKzTxvnU87oRoxC#PJtsNDFx(`!sbqJ@V(UGV9wwP&l1U~x;u**^@tvfv zOcrzdwXYiKD7JX&2S*~FjqL1>HR~525fA9yy~nv;BV~4Hd7sT(v0i=G8E^YA#M?*4 z_IbJsXt3@)!451>GSmh{jcKL`<j=HkE&iJ$NPsN_j}~`64gYqv{L6zsfx9`+X_^3J zlRvu-5T|6|&YxCsuh$vbRgINBr2+)I*wT~*guRzL*oNp{&M^b-a+IsMx3E<cV2rf^ z($t@ufjzbU+P}Mci)y(pZM;X-0PWyru}>S%tpll*#b~ZP^;5<MmBD<Sz0Q?v5BLn% zIA1Go{;Us04|5N&&!Zan{!ZQvyv`-Q4?M^noF@mkZ;|u27Yy!s0zmct)X>AS1h&_K z?`a7%w}I?+=5^@-x~CTK+y34Js4MF_v*m=>epRDg6)xa=vm7ql@B_@1bDS22MdpC` zrro=I?W)7>oAZNiW_I(JRp4`d{l*8#CpzES&%#EUX8qyjWGtUX%i}5PHmtK~UC$jC zK=hrX%**56@7;90#pvs5v7z#~899$eFMZ+>V#N1{+Dp>2z0?R1->`NW2Y?-q*j{0* z#bRT2Z!(a^8)IPf0SwpoKf<xTXxd{xpmksSk9+G&^t89IkvR>v{ILG22A*Bf1X_;k z-|V=-(Eg?@z|>Glo50mx?Vws1yw@p*-~QDgyYbm!+Or*Ord&TGuj(L}kU<vJw8wsD zl%_or3fk;T_4GSQM}2(bru66|#Lj%rwE_JEjN7pV5cZWs1h!+`F@6{CiCe}w*SMoR z{nwYUW&hrcr{mO*$@1Mkp0wA~=l7Jsc<;JT(oC2T&i6I}>I#1%f$#$G8;teN^7|4! zgo7bkR75=mAyDLFqPH2{g_Y3I#`ta~d8F1!0xm$kZ5O`Z>&)}+_bdF2^k%yyM)}P9 zW2=3I1*Ct#YB!<doQdv<LZ|#CB{9iN$K7+nl7hi~!IA?i2KSXFMkxqjitDQQr6}Wg zX8cn&;_pM}vGw+8_FEY=KBP6S|8dv#Zbo_O^!Lg*K|l={pVyt&2&+GI&Fg&a(X}2e z`c>i>cc+-)BqPfNaG#`~Twh-N>t9T2m}HVkj*%RfBWxzX^(2$ry0Shq^0a{4j7(a+ z8T-Rn{pWTWcjZX^VAFoc3=khi&+f~36snidji|{(h1zcw$SnfV()hcj0mlc-q8V^q zGrK1U<iqgavfu&8UguR_1pbtm%fJiSi`g5%J_qap^JqW%3~;~#fGZs6Kz$ydzs3Qn z{;Ys&EJ#5A3j16y0n97IHi`iLBhjP$F?ryB3C#E?JHQJ(frRW=<P7Ye<5BJczQO0X z8%SBOgy?OYtl8?fxWPWvMud!nW>hbL`7at}fCIguu+k-dh&$Oa%JU>Pa30M(l=qQ6 zZP`l$BEP5KpvW22&CRnSq+Y<4ciGW>Ja5O#EZNgnrN9k+eM~|MTx7ut*k(xz(LwaH z=zT!UE<2ze%)XV~ub;aED85iarkB8Z&PMk^bYGOG27Q+Mva=A~oin#*UynW#eHz$D z@D%U}@H}vtlOzzm$hY_m@bB_PegkYXXA4O5hE8?la0TBt0qkbNL;-v+pvdM%j-6Oh zF}kNU;CaEoUfh=~orfdU@BjYKag1a}C7Xx}*?SyCA*)CvduFd}ha)nwifoR(XEw*) zE63g(+2e5RgX8c!@6Y%5KfLbOeLtVqbv>>GM)?QrbJs?CNYx0JCF0nH0kWbq-+91~ z2MAir%i%rUjSv^v@1344`-$H}yB3K=FoMk`M*ht>?|e-$;8h8X(W&*wtH+1U3~pdP zP`srlF~FIchU``{n9tFVsTeXzXSr<BWcn;y?=W1@XYufbFM&(nL5v~ky|s!3%MxaC z6%i+p|K<Kiit&2&pOps#W(q^dvl~uoIjI^j7p$@4T`%?>I7e*KxI3i0c0rJ(C~^k? zJ*9@;{&dkN_jAlRE&^_lM=8{T&Nk-jI0&%rzPOP1E-P3x3F0zTu+#I&yI^Xgns`nZ z&YOB*S3Eb2Zr9o(^BgDN;eVrdT4zjuYQPxAJfC6iWcKrrCOItO21OuqwMlyBp|gC{ zN#XZ^MVijYx12kqaY6Od@ISeLbUmpf&NRg)*r(k(5j1I8C!TyX6b#)AC;7(pZrRhU zi07re#J<AR^5;1P*^Uk?nLgVB?aQt0-$#v(^;Of^VgieDzc_l+0j5GDsgbDin=OLe zh2cFhd^0bU4%SU&EAQ@x=dx^+fg06AysBZH_(&Nnj*X(<m!%*o(EE2E(t0?lBe_p= zq~0h9IlwrCd?=53;@qy4@hD|i`zapx5-(?3BVi+AOPx`u-=ec8(R$GI$3%o*<4x)j zRrAS)&uXwOb)$05tuht$l7<AHy*jPY&1;W{r~crVA+@QLwHM?bUOL@k{F^V;dzCI5 znCmGx7US{?-<(+X-y+FJ<y_0P5@LlXJ%FCTJ_rnO_UUu6O>@RYa@5;(4t0O^H`sq4 zO=%!Sj_X$l{v4j#(8k>|G*qZ0gk9iQTQCQjc3<o>?zDU6_ntY837+uJh4|=yK;C&u za4JZX?LCm$@))?8n?|r%DpCUH^iM&VlNdMO?1KZX8$JsU%e0HR6MIY~{0@C7%Lgua znCf%(tjti?da&HS$gKTiJCTtRkh@{hgtubBJMNw=zwVhhk>Y^isTPF^rD5t=@rJha zntP9&k;Cvp<jG$ex(vmAdICo0vNZB_iKOno=!p6>%Lsbsl%;u>(jMv73|uUoydQ^; zI5)fRQ(tS3huOxjjsNi~-sWsS!)L@)L5psik8SJ$&qi(Ty_1J&_o)Eg-<(TT!$||g z!K%19;>wcPxiI1r{4=ViBhty%(ekp6D-O=O;y52@L+22=m3?F+4lwjal~g5qur(Fd zzN*h78#0pWlN(wnBfut7%+^CLib;?*Ug2Gq4^Z6EAJ++UkYTyvm&JKx7aori=ERIy z+FDI<Y&G?T_b}&*CcbC-o{Fg?UYJjzOdlURy0zr%FF4RH|KWRiU72(`K|z30n6BP~ zISX(J%vz?}0{Sdrl~T=%?4tU_+lEnJ63szT_(>Opg?wQ)4_)pxtx62)jcN6G4>(G& zJ9o-3dKl>QzT^DybPCmjljt6092d(h__uXwEDYO4>)5%VEphf#bX50Dt=~<!#zQdC za|i5F>N&r>wVRloH(h)r_b<vn7;r%+s~K6DoC^1GzK2X?mNlS<T954__IPSK5xg?z za|yF+jEU;LC^ML`7yaLpi|kW^*)G6Axw{ghJW~lI<)qQaJCPDDW^Vb~7rlXqpk%Nd z5UnX#$QxK(j`3bf{IX--K7)InLVvR$Q=}+SI@0sSvA)Dspm+i5`iYVM!+@Sq{N$-> z(J$wBw~MI6v#THa>YVNX|3$#&U7mxF6;Af){hzvh=_sHryms&TW4`Y8^Z<-W#_811 z#pk|fH?wBn61&^K8Sl`3a9fReg3nM6Oh;cRsY<*HsBMT9ZqOY*P<187{7w_FeEopR z@Yq*0I|PqV5jBYtzVF2x+kan(a{lJ;DZ&wa0nhX<T)Ks<1yW=h$9u#Xw~g;7`)m$~ znYZlU#<85-t2SPxFBlKxfp^U(rmZI=kgmw7wAG%4`eV|Otxo^Lt+)nf=l{WnYrcUj z#o^tw)T?!8=m{Fk7i_Xb!Z|zT6bBP`e&36hFmqES+@_uRu4j7Go|t#V4OZ^j8NVf) zSakWUnY!`G<FqPUN8$8HE+_pvvBU$Vyw-Y?pJM^$G*(w`BR;>`SVKIIJ&b@>PhSw| zHUw$6lh)<%vAwand|y1HXB&{<)cFDE{|U=G6m{pdThM3?M;s6*!z~Hqb$#OjTPL0g zlyn=36aIx5pzpNC$8G*-dUx9;xW+QSHE})#S@~$^nlZ&ffBc9lO|(r_&#pO<A@oxa zZs-5>2cY5dL%aRQ_ZKIz5rB=}Zp(5I+23|y&;jA!UJ!}FUnAjpmk5cgpZ|;<D^1$+ z3;c2v5`J!4ei}E(xFo*wsr5*3OH)+)-7tAJT%wDza){J}4L&UTLZK#yewU7S7IZ$V z1jM5L1f%qC64CK!{?piOHmu(H1Al^D)j5p!y^EM?@ES*Zw3Rb|QbaE0REcYliKX*G zD*5X{g2);ArPOxJ4^o!l?hpbsn5_dT5BuY(G98jk@xZ;}O>?b1Pezj$<eQ$f@@+M8 zbXtPH;DP(&AbU;O$b-qj>CLW^t9sc!i#kjckwfHr9@zF%CHU=U$(4J>d2(59QJcQK z42%Wtlbn5aECGv~V`h_A1A&+_1T~~|fdhLfZ?bEpS@<I+(Ek-6PU*qz!$`QsUdfhM zZaoiTfZ*s0?kf|qUB;=p$y=WUf&GC;GP$f}N}Ma@Gff-kef-_}YeC2589h&Nc@B&B zN;8yai3ASzJmJ@g<m)uLfz}LMeC?B2YeA?#u)rJch*L?99*gpiAXLAGvz9EfP2=0| zl7Io|4X1w1eN3hFn3<;`n)Hay!N*fD4R61sZPI+KfBKY}r@NsG*_hO9=wUviL@dXD z1UQbjzDa#tO=pOEY^$k9z3ig=b-E<#a@oQUe_b~uofz)3&NQ?v0bInX@iZ3ojRtM0 zH!O^L2fHNmFREDeaId7UlMheHPOy^%b$t(4+V-2oLfpqH5m({FZ<R86_WNCB9`ap< zb&%>+4C(~LL|nF{zg)KRcOt;;D^kYIwS-wOAcO<4?l_$^^rcD>4e6L#0Bld<I#QDK z@LfXRC(jF{8DOdU+W<~;=)$$wJd`L)$>r6C)d))o&AVm$3%(O4Dd%QqAi{FAVN>;f zHTKfSg$U`jrW&a)nz?hfl`o4y>X5L@H*H2QMv{^Us5m9de~UXkDbc*Sv99+Q-7%H< zuHop5PquIk{Rb7DW`5~}pub#~bu#3UV8Dgn+vkO$+#Gx<#xiA2U8&}OMqSM-Ot6H` z#W7_u_omIToc)Rz;yBN$B1{T+v-g~;=AqjBXUj}TKJY*|t|L95`D(MaC!-zS80uhX zODCX5FTZ>(>z?l(C)z`Jw?I_FDUWVrg$Yq1UJ)oQ(WA1$R3I5Rprvj7LbHs+-H>s; zIIl09(#l@yQALS*u2evc^I>)B@X@$QF2Bew!P(uC>p>rJihKxfKE&4N`LgHF4aTS9 z4G5bdPuGyRcK4BA@~5t+=5kc46JzASYbwc(iFS|Q!W~Yudvebhq2Hx~Zi|VX`2qiI z5^VFa9~M3{&pLu89N4Z0$E|hHlcXQ&@eyEb_&o7=tQ0MLuGN8jw<vK8`L_lpCRVz; zq311z+K(#FGu^NP=Z|s8$v670@w%Uq{cA?HR={Q0{l8AR5k3f&Ni3szm`{JonVQPa zBFlko+RHp-$xGYIa@qQ|HdT*&bABa1(0ay@5X+%7lfl#@H-9QlEFf~)2uY@n4;B1c zc#&j2v3#a23mkH-sg3qEdLcI7HWfCE$qp4;8@pDQcGjZg4fta4c&7+6Ic6Tp$x;-! zvG3!w_>X_8{n0O`#<VH78S@og(5ei3xX6Pb+qSEGSttTR>+_1%iBP@W;IsGDDR$JS zNW=fgxfe3lMQMQuPRMR)N^%{-D4vOT2W~Ou!)R^ip}({HnzP6XGelM;syNtHBr{6% zuWRm%!uPs?n1*N4(}md+{)SiTl4G{FVwFZdt@ZoMV5f5Eh67C12j(OcQ~&oCbs4wR zS~bS;z5d!tIu+`q+ZiZJr55S`pp%oIk(+ID;jfjWhRjUflh<!Il>FM=;4-fz&34-% z|Ge7lXA_;dPCrB*PvJWMA%o9gtDdPY%f#(ueZJqvH1JO7+>E%L%dZx&cQ#x_AHyko zNQ))ouqqT&ny1JldYVn+S=?9=27qj-GPwTnqeE8o=HailG~Nx&;KjeY9FDt@A}Qyy zPKw2w?&FN!Wc0=~G2mUPOa1qn4R&1HBDAaXH0Tr$etpgP?P*O@>!r1@XToT|qVws( zr)ZK=*9T{*^%aeS*o_d4udwyH-~U~X;Kq)Z9s))G5)w(hkh;eIqmk8z2D9)<4!j@u zJ9l?NLaMx*u`0~QzaiN}>IFGUVPC#!pAYWRzZWM8crlj5*7azt_Q}Jj#pUEwpkCP- z%h=KNJ4kO-j?+nw7a7#IIOa`ypq2l?7K2+0`%wu>cg_vE?(Y$paVVv_LJ(6KjDkY` zF19Ml*Nu+O(KU7eC221R8d8LRTBp31ZR&mK87JJcMJ}>^{1m!v#Ink6k_Wn^yA;(8 z1pQqxvS*V)lo*g4tkX!hGmp`GuwD88K79F>7_*%?#-bZ};}2GK{g}JkzGMdC%Fr(R zDt#Yd)k9OI)9OOK)Q3wehGnz_MKr6m{{89nJU1mv1}t*Qp!#sVeczx@D_|sWj^8c> z^O&u*PfoW`On<~VA+Cw}$svPk`A<;dlS8?K6<$dN9|D7k{rcerVJTYK5iFFiZY~f7 znTzpyC~<G!6>zWlGgulE>FFwt0d8eapg>f|ln24vU1R2pBr?g6P%tsers7u;0dsCR z`Iy_7W{#%(IjzRw`xWp%1<8|l9#F#bw_fnSnIA}s`G*iiJ+m;SuJPCi$Od6mL6l;o z)H`Of!xyUU&6QBpd9VAt@?;^%AO&zPm7|Ym5UP;}a!p82<2*V;U5D3y96wO{icLcP zbq%@9^I&Vi-K;9_=~#bLcFAz{k2_~5x#|+pwg1>1rlvoU2GLhJuiaX6B`|N!+L}L^ z*kG?1wL~PJa80{q>q>`dK#CQj#ixKGyLxjDjOOK!Mp@yz8Fc~@C7H+58TCwGWW}nt zsBb5F*SCw2)Hc31Qo~ywmx-W#sh!4hBg#nyV>Z;g04-q8yyYA`qZUL7sWQ>)e2es2 zs<M{u1)VYO2E>if#{9Tp2L*mI^f&U_q%*}05nF{^^+>!!mb81Ieq4PYVYLWFesZ79 zs_KQ;9S09{G|@2XGM~Jh`}On{iCZax1)~7mkaGR>+iBqCyP>{0ShZ0JB|KJkU)lRn zjV=YG7LTxl`QP)LH}~~T#L3c>;rcwky&Nx0JOr$t+$KB(HOR^}pgz`|w=p<3j8W+* zbq1p?zSYqR5<0J_5JsrtBBpPg79yN~BYQ;Jga)k>JU5<U1_d?mPbT*p-pK6Z0RV&k z`XuFj@p;xHZ{QWBNBTaySq#vtV@y90n{mSML2(WLXXJ}s3>Wp1arC!;^EDHX<yxHq zX+%>4fq2sO9%8Qb2G@RJFVq-u?8Xw1XxSF&z9>o3%pc}H?2)x#krlXG6ivVBvi^9) zFLQ06gh4b+WjmJg2i>!nbk8R=`Fv|Z-4?tRd-Yx;YJJZjCykT8p04_=HS=PwtjRD$ zHxpVcpPlk=>}8+d%82qDU`-HOg9_0RYObFL{<n&f>4|6-Dl*+2zzZ>iLcqQM(k^GX z{+gfjxtzp_oi275m1){PW9Oe@I0RUVzB@g<t$e{ICs*T2X@0<9OOd6dE6wTa4P`D$ z@V4#qk@WSpFl^H*$tiB(p8WWcPq%d(kvP4pE7%uytgK5qr``LjkhIc}VCe)QbSsOc zZ(BXVC(pm5Xnr1REEC-y4f!qA|58L^jx2=f`?o@XkCE`B6^Bhb;foU9d<WC*SHQ%o zl2Yi*rPh8+5m96<{aAblFMrfl{0`w*MA_TA<Z1YPpB1_I8J!sMhwFW@u9l@fgUJ17 zdXX1{q)c^Sbk$#Si5`t0L*jne$_`4W|J*BO1{!k&5NzHM47`vCyS?01#iFq}k<1>m zkDu@JWX&J;?^QonwIrCwvtxCT@kCy_q9NILD~((xwxE|%!cF#z*1}olz_tA-W~{|G zslx@iqD<S+ntx7YY)wN(<Gqh;KnHssY|S@M0uoRXHYT4EN*ak^br*bdaW0Ul)5M_7 z=%THbR4Xf8yrI+wW)YjJZsv3wYYA?7K>u%pUGcc*%`W{2FXaCIbPqX8%yzn^iT72r z;M`BS1?a46(BA9Xx`6GzQ}M&~Ked;~p}qH-?kM)2`~MNoG7*kEZT-@&=R(K0A|)dD zq(;V-Ey&#%t_8d?(UZK&AZPn_9dUZKz<#w&&>KpFE|lLqqi)Og+2-CU&DdUw3E?ai zrKN2`qf;xzLNaJTwBHSITBns2<(E+83k!ZMy-<J<^1iabYR$}xH<xu=N!4^?tHwOw z>z?CA2X3`)%Vyrv3?77+-R&~!_Q0bqImx^PCMSD|%B$k`gg4ArP_UujKB^8Z7|*e; zZf&In1t)s9K++P7+FN{c>0tgg;J(B!S$LwycyR`!ywR7*7rGkb|A^bMr{-WKkuy3K zlAp$3We`0p<qU*OI@ircTAxZhPas-Bb9+z>zKb_{C{FD-?nB-Sh1kBWoM8Iv6DQP& z1X+YMWoyY=atXtsVZg{osmJG0v15icG_I%VZ5JrLGl@@m4z1Y)z3BvZkQ+)6f22L4 zMs1QQWBWPhOA*c&93a?M40bT&*7dT!oUjDX7<+bKcz`pW>Z${6bhAGb<I7&)foJ@t zYONMwG=x;zUpeh^<8Rz)zxOQg8;I{V?qfzpq4MJRer%lpi1|Bnq<1jZ^tY2&@?@AL z!;6v?f2|pOIGk&1JDLyb+i3t=v>t}?aUPpyi|5#l@k236F>l%cAN_t{K*-30O(8{$ z6?W`}bF8Y&-7(UZDfeW!glbRw4bW`)GbCE0YQ??(<5k!cUtJPN@EMOuL<@}oJJfrC z52o;T%cta@?AU??iA*P*1jsMmiJcAWcWw^Ln!j`5b^h@{pf??(MCD4b_H-T<&yXo$ zr3z{~IZj)lJovtyyR6*M9?@LBR}E-w&q)CW=s3#ro}zhHc)2B1DAzUEr8>k&@zqB} zFsnrR2hKi;k_&H~8b+SH*uElLDO((RF%_abxMx7DwFLW|vg1#tLLl=K5|0FM&sxzv z&PKR#JAXq|kr}Mst&sN!C!)EaL0D^o_$~OWKr&s@v&67r*vpsavT_|5HmRPz3z|bU zk7UN5IDyYcyv^PUke4`u$$&=zHhbT}F|$^wd=5^+qo3cu$>{&kIJJxC=23*4%aI=x z5h+)!9KQv%@nlNZ?&*{v@dWR^b`RP^`__Vs<|?_8hasMY!da=9ybxn8KL5_vihYb2 zINs;cDsJt={LpRqajU8SxNgi;2<|v(7zKHgrrzQn+x1|sONz?P3QoF-5*%X1lq1H< z$hx8Dx_ycW^_HQi^2DydqHIsFRHR~%;Pgv#K;PQEJvw50ly1hT&sU(r!eE&m>o&?< zQA3G1yB=uNlY$$tq)R0jFCYfEFs(GRR?1p=L-653Y}wt&N8RM0bq{d8A=oD72twO# z-<Z#O*h3V0>dCkw@sUaG)F&V*9Y1*9v+a9q(#q`%xcgdF_5&cN+_`z?b@#Yj1x*mP zjK_akRBrGWs*8l0ipV~3Mrn$a@p1d@Q=Y88skV8EneXDJL$WNh;pR7lMDO>I<=DT3 z-?{}g$PgFYOt|MRk?2l**bhG@kH?%Q82em#Pm~khc)<->RhW|;uqtq->>~r#LnEpA z)*CoIV=Qr3(|{hcFBJ7w81C89XLZcKdwJIp+9Z@Tx#yov`A&D^lI-vCeB{w<tg@19 z-urpCH;~t)r6b9U*6-G0`Jo3@*VjalY};1^1B}u$_2*E8f#Jax;M{Ux1$J9@NB+mf zZ<Xtpmo2+VG0)N0g$^xQk(b}~%x@ek#35>^aPu^mImouJHOt@oi1bf52jUT*y1(WY zdww;Q)s@NbnfwgZt2zT5YJZ!@s`w24cR?mv@Z)Y~>R{=3)Y<=me9K9(^FqMcm<%;O zp<1`X+#F$hb=Tk7#KNSIv#<r7GVgk(0e`G;b_Gar+cv`@(`x))bdrqPjxT57-W{Z1 zhl0u+S2lUBD%)5985C;(TCjc+=c{%ta*ZviFqFn}A5tDz(_L7;Z~L}mz{>7G;IbDf zC`Rks!|Dj~GsN)h`7_?}g-Is?w<JHah?fc^f7(U#NPU~J5^@siE4cFAkPw9u+r{Bj z&bFNf$Iyx(J%cS%%@)MdL4MoF%^y-GO#>(+Y--DJJc{^`XnBPlhpWp%QoVLs6H#Q1 z9046l4WY=|m8xbgpBxe(gh3vXqaKM)>6~*<?99)!)X_X-+vTTQdBCsy__!Q`C+Bpt zH(Cg=M-<dBP-%3!FnPhOmhbsq+NIs<RaGGBfj}!|ux1&;P~L-;TK3GqSh+_&LqAf> zaixi>(#WrkoayKXCNB`cI%I4G!zlX8x7?+VsB%x9dTlM~cy}N{$>8cw-!X?{#M8!> zk44F5Cj}fyS5e~2H)i)C!3#s9XZvHrL6&`YP5Mbq%qKZW4ca3A8Fxa-guX0^dPq6| z-d1J7GW9RrLhI2<P@EtQ$o|c|I$mgDGvC+qND=w?%=LrjJY9o~h+OQWJs!dA7W_gZ zZ@Nl+;=q7>5VFSp7jFQM?E%1b$gN*djp;7t1e}8$zk`lnB^8Il49r2&q361c?Q=64 zufn*mI1jq*rnx!aD-$;B63r(ssb0+|q6W4ZeL7W)^9>ja7d#BhmggALal?I+`;1$! z@eo2v*$7J95G4TOLJ&hW`e`_ZHdI#>xZ_fIGl=M%YjZHEE#sCU1+~&r-Zg{GY9A1a z$JJH>ZalsPQ!JhfPIE`Qhm<TC0M4W`Kks0#$q&wspOS5B)@e%TG|d^Qvo)2*YeQ*Q zi~&0(Sj)1EIRx!w;Bgf&xMFb2%)Wl81dV{rq&&xyKuNz(>#3EJeu<6!X+_HPMc%iV z)BvCGbLq^hS}pi1_wUC4p%;NBepNJ5%90rH`m$M0-We(N{CpVu9F8-rIC^$8*(D0L z<q236JlQX<->-kwhnsXeRuV*{(R0s-M2nj#{Ap5g^iBpG#GS^X?)suMeg0EF@%Gz? z@jIM>YtQT7zzd7modio3`yc90x_wVj4;SpKZzF4CjadDh4>M&HKfW_~Z~VmopJS-1 z(!vG7NUA-Z4bz_#*6$2^fG?EJ$mzgi`VxJ4+!2bd8IUV8%-kO1{fnoaXt~#Y1&Tuf z!aluW4MfQcLygx%D7*Rf0Ej~-gf`J?y;m5PeSVx=1ibb2>qEU=gs;ICJQJL(RP_*u zBjQ=nmFatJl9;Fhoj|d%UA;OrVi}#`5A@A>FhjBM*_j*ufm}vW(oJLR?lU^xO?303 zmhfm>ymZpuaqrI-+71G7+62J4yZXZ`$#APteu9(4*%ILBiO@&jmV?LXrpC>sPQoG^ z$sN@d=EV-1C79r0$aLJa6K77}C4joROUwe@-`b-Yxb!8_Fzi0^Y1Z{KXBa#O%ia`G zy$--k%q_JyZi~3Bl%pon@YFWLb(+e)AOqmR8oNgzzf#8LQhNZiYymySGuy#Lbs@C{ z_`%tqbyADXRUW>nj8J3qwFUlju<|sO>9G*86@nK;b(0FSo7ngf(@Gcxz`O|sY7y>l zJXvX*TJBj2_eF%LKPw3MHSP8hh8;#O9MtFSdzWL!{crfL9y$VUW@b_+l#uq5)g!a4 z&yC?bA2n<5Cv7iGOgewKyvjn<M1RFGM!BchFDlQvD0H@Z5H{_C^lsnG?V5T*_QU)X zS)s>VXLXdB-n87(XGHzIjE*rcT6#kbkfZMNUTVX8dv;-Reb3u8*Fy%KK)SJ_frW-G z8Wc4ObZo^f85HJ~Xflf^P{!|b<@Fs}r1Ff#ZjA4)=&2Na|L{^?D0QZ%vTv{5?=DL^ zNFUu4&?K5<HgBlyoIQmac#bk_GMeEJIV}(YusMQA<3;(&ZMJGGOb$G=gD6%a;aD3^ zf>Zl89rugCa$2oi66f8B91mH3${OotC_bn5gl{eO%TyftvWj@Nj<(&8oA|4s#)7;p zTt<bYQuouD3vk8|@U_g^*SKg_{KxZKoQgHJalS-Dk1cJV*6wdn@7dX{7KiDue|Zi| zRGd(59;;;}tHVak*%Mw92f-I3Oy}!TE;(~@RW%t>0xh=T;9jDio{38O@(!kx$Vl^i zVpcfm7rKX|vM(~&8D~_M{4d@AM9*xw7&2GfaxZX$;i91%yA^G&@7`J8chNYheja#u z7RO5m+6)~RWFf73xpp)h21+8o{0`QX1{~QSx;3W+H8q&rMHim&(Q@Z*AT75pJ_N)_ zAKWv_xZ&{_%aL8L$&ejz{@-zq>$|i(-}}F2D9(v6aJaBM{z+V)pRSoa`9j6kbaadp z`zgi)criD5--w>>CmTuNR~bgumibRiAX!Rgv>3&@6IsJ|W*vxKF3XwZ%T6m9md7Q_ z`>ct9>rAsOdr<F@#n!Uqg}7rUHS#&#3%~Q1EA%gp+}JkCP`h%uY(p;x)TLGJ1T3o$ z&d}O>*!=Pjsu@t-#(o;F@8Y&5#&MT;q^<KXhu!|K9qDXcyLL;upt`+k*Xxg%C;Lzn z`0`_F2HsMRFY$Syzq!`@5*?nesMU1g2gT1rYz;@g=fbc}o&M#1*uUqB=<tIGe^Rq2 zo2%YotyppJe_Xhy<`E7FikzHd<jTBvzT=@mCA`Q=6;Tse%a`d{vQIQ06@nJEDU>z& z-gvz{k~x8h<-jWsXe|S(1NYR4J+-$=gbV>_cRh54afa`;4hcwmcbkr@y-kY!l>{!@ zur;3U&W>ENnT@?}=#}WyYM%k7Nc8&f-L2I0V#`8Ig*aSd@Jd~1M8;;eS)<HUxIX5F z(#`)FWe4S|f+NzMJ~xhH2ia#(U*tdew}EG7x`ske+YX#(<S$ux`?XCoayDS~A<N9! zql&I8ZR3!Yf9?-BFcU9UcC4U+axDYD&Ne{9Tsi-_ffCPrepfKLuEZ&<S!4mwt>F?? zp~iRd_xzIMUN>k1aJ#hB_8eNO--YG^oi1;N_N>GS?475RHy{Y_bIYFXsw&^HY(?*J z`^hVx;K&TZrLt?my-~DGO^^0`V=CS+4A85yHK#(e&=PqvYY~WL%TVTds3j6Tg$<r@ zRIJ#lS%`sTNASO|<olxlK$c;Xx8YYR$mbQmmbb2w*1ww?*DaHQIr$I?Qdj15UGTr7 zXp7PrYX2h5b2W}n6RAaXMH$wx8XM4rI$SVtWE|M6`(b#ejyX@iT1=rOnfg6v{~c8@ z*Qov@@-xY2KX`|%4;1f`bis=-*~@=iUO~yA#=vNEocK%m-_&-UKlwf$k}L#No{`L~ zm|&3QH&!aI0o4K;HN$JC-s>kk(Q=F2M*}i}z03&P4CMXkr1C#TG%)wfA#hK$chTu& ziT`nD<tMw(-_({h*YsCa%(^`ndOMzXC`u0L&dq)Pb~Y3GJ|I@*%^f<tZ&tm^^X9Mg z%~iR||5X;o5fZ=sZ%vaE=cU#0>$2-}j$D0$v1YVhjCeI9?A~eWGUu6-P;9vQII%nN zRu_#gqvxFI-e0UkzCFE4m=&k;F^8sG`%xNwWgZYM%z4yxDB*czxpF%g<4qwkz<MIM zQo9|!%@Q_ZfkgqSgx4mhTjHOPv}-nW@~i`wvhA(pTTB@E#qRt-ypF1$T_u!sQ>Pq% zz|ioyR@vxAl4f@Lv!^O9foG0_vj0EUK{zj(orp@e!@$^4(W3ZcuWz=mcd%a&8_Ao1 zVDzu9;=g>aXg?kh{GyXzf9xXv_!DqpI6P{L`$>?xQ6FDA^xf=j8ojh-#HQNWTQL7L z4xB%~t)i;zQT_{3?w0;s{zm>Qth$}_uSGyQV~Qy_;7vz!0LM`BMa8k$!}dHBgP?P= zrZXrT+Zf}p^1zG|x;Mu{_D=Xr()~eIJ+6bqga6vQ8()}CVl~`oQDbaCys7(S^s{iC zTk?-1u&CAp5x_D*if;Q?+J0C<#<K;UJhSJ<@iRK9;&+v+CkbFPf!kF_{*hWqsU(j1 z&R97cS=P0iZ)1bRKSPCT@y1c)>qfebH>UHu#sa7Fq9L`w1uS-LavWPpm{Ye!_3HtC z>xM1U>?1sMGVA3I3LNf>>nbJfW@!Sp&AI2zu1qM<8yX6oaJ`EzqneZI?WcH>e`?xG z$8mO&MLI0^#;`Vo<rV$!K3jB`enBs#)!f-UqM*&07@OrH`De3%gJ9ElAY~&jZq94= zBKe%~2lspM=E*-&<^#gncUTpMy%bZd)}K&Q?`;XLDB<Q10fabxD^@TV+nbde+7b+t zsnjrgC3A@L_ucIi$)HRV><=WRHR~EaK37o;zsE{bc49fT%c?^re3=)$NBA$?pc5qO zL{RbCt_{VY8LSZVf@>|;oGFIcztka3gHOIn($0<~w!VTYcqZn<@D{#DC9>dk`K98F zi~@tf{HB{Z=n)T-#|lCJ52!~CJ%Wep2D66-XQF)r9AuQqAq_M_Y5=(NsT<DMB7@g# z{?|^uxzeS&mDfL$U{AquEZ}_H#6Y|vM)h;Caiab(`cF`!p#<!6TEp{``?08WDM!QZ z3eQ<HGOu&w&5Dz2XH0x_%tP+<^1%xmTgXS|wGxqOb(<ZMC2r8{{`6^(yRXjj4Xh2_ zE}VVYH|5j$YJ8mauh$n_&PPdS2g2I-`TQ%<tp(%$@<4t@L}DO%KPBLPE7zatJ=#%7 z?ASNfI5nE5W2ym%ok+OQ&OfoAHeUE6tHQM-ZJr{t#o1?gC0wQEn#SpPB)ckB*>{HY ztga83eFLdpKF*)E+a9a0Z-PYXV05_e*C4S?(4?Xc5pBY0eh@z+`2nfqiWEr$_xtQ* zv(<usN66N%xMXl(KxQD?%6WnOeu=UZlO@Sj%h}#=!pBMaX>~5!vDIXQ)T=+soz!o@ z!pRH!m`wVRumh*bo`$wNLe@M%JB-5=G)%Rft4I07ROKMoeUIW@G{N(NjgWBH-8?h- ziot*8_PPzg0j?Zxms<)-Jp%E5T4F6i>0WnhiGhdC(S~)!DPf*U1=--B?b`-F<T5Vc z_n#p#X~p-Q1{u`v07rS2bUa%92|fyM=+pLlh@(2xJ_xnywtK*DM7eSps-=^ZuC(A( zEG59%*QD_Jxg!U*#;PmprPc_HcrqdtQNOUzbNWJNzu{Of<;!e()!@reFe%1(@Yr|n z!vBHS@k`c#a)P&iq>k^Ggy-NqKCv&W!4+Hta$KdUH?5LS1~?4B;lJkXwwn!@vZwk& zQBJtC6VM=~Cxjztjb=^gTPToqRdm0>Y1Lh5_C=_m2u3zg-aAQe=GjKm@I2&HDi?AE zOio3x!rS0U?%3$^V$YWDr&mSm5Di=(2gZ#S+Mq%8mKpYb^fouShNFXbXUWkt@;Ymu z`R<CNc@-V#DsT5aOm2f=uoO)&dTx{Gjvabe@yj-Pz171a<CKo^=n1_5OLt&`<z-Q! zU2`=q<y0@2|K%X@N<DDryLFn|TuB8hx20^$J{_qNw(f~lEl@4bI$i4*y|TLe*bS`H z(eI|z?B?Ug$d~#zqi8CRF9e?;&>ODI7KluI^f`5{zd=Pk|2@t+Xh**By<Uu%LUYaO zyVHVi?-%@yzNOCHGDl(FIyHXJVG#p0SIW^Ls)74lfYz`ax-n7OB$f#ae@|RFd1i~q zGEb@NeW$mBd#g<NB4HOSy<1Y7U8}4#SwLgc5pv7h)hzM4dnk{%hX1QtWmw{TFk2^W z1;TQAbxUzyO2;k$&Ws-#ZU<9fi{a890ji}nb=ex#qFcYh^BC_*wBjo%$Kx%*H%G1R zei1)zZh(v7uWlq4eZuiUXCbd&vICsu;mr+}yZ^<Y|LasT%@#XfJW|TB@q=GlYLmeS z#G>b8!bH)m2yl36F}P5{vEUC(_&^_9NIx1UI><L&jIr9+X8@>T6LWrj-9OhYJF5j9 zxVLXtS%bH$PP)IOn+a#l&OVL)G4=AS(4<0xjVIazLdAc4_vfDq`Z@I0U1!P9KLI4D zUj)`wM8YN=1VniM|AWfO3@VX#Qd2+-<e_qZ0`D(s*&w!#MFHL<q?<Y~-p<4F(|CIe zkJ=icSaI+Red5gODMa#cY@snuX0(l<E_<k1Ybu_8OH#K-H=88K^EEn)klY$udVxpS z+YldZbNB?YS+_SvEM3c9Rg=m*1z^7IhOOA~idJjfG=Ix#0X#BZ&m^?nI{!!&nDLJi zPY((Rw`<m5d78M+2wwQ0cBtFfAy*mi)biRooArdnB$U|$im+<?C){4X`TbV^)I7cY zr&H!4LUxfXEkff&%9(`f55*#5x;0$`KlTwE&)s`n4t$1j1vCr$FmkiQ`LPd>L?hhB zSYNsu8M9EnI(E3KFjcr~mp~%uxyJQ<i3;|yA|exGn<$<3Qz>nD6%@_GbH-Ln160K4 zvlF;Q!WgJqzh}v6<3~$2-?319=Nccm1U&g&r7K`9qV8jeF*S?4&peP#69il>=B74G z*dnX}&n#PMfHKfQWAkUm=dhq61=iP&-*a_b;wE1$_41U<K}$Zj7+!%^#f)#{G=G9J z$|>iTr-A*BuIctdAD@en%{qY|_k|h+#NC7385OC?C}dHaPu;e5(X>LjU;Wu0W1W#T z6=hKY8=_gs4(H9pe;GMh*|tNne4@oCV;pYdON-Do+-`0d1DQhi>`}#}GvK1>hAn~E z0+L}Dyxx!FG!lMUVd57}f?@qvX8h%r+U~-7Bk72&iMHhfH<W*o)$<9%4;I`L`t7YI zXNh7{aiMo@WovIerp>8Tlo}nN-Y7s7&z6h^(aubwL~iM22-P-A{VAHH5S02l!Z37L z+7O3`j==Lu>Z!aAQmmWiUw@rVMR^-DcEJset6NgT?`B7mz}x?d<up=^iY9M=PMT>M z-haUcr??}w|Job6TJ@cDIbPr%<M6JDP{dFQu9)~lY8umdIa5PMTls>#*O}GL7w2R^ zQ1gT>`&$wh_~@%fCsPuwFbSm|3vZxhLf-=2HS5<!NDqy~XuvbgUNu#?fTklaRz=XQ zzs^>+b=-IJOd)?s6ep|95xBK>)l@8Nu_qD#mGjXY`m;CS_@j5)+Sd&4K>nA~U#~Hj z@uTjqOzXLFAhXSy8o54kr98ClkXZlYF%-w5c+vmo?qv#$mT}Y%<w_@$d&NS(UzMTS zCLI<v>Q4p_D}h`}&yMcdoE75wo6cBxI!u-XmTd|73&bw`+LkRF1=$Bct6V|Yv`-!} zH!>yu2)R@T>lpcS<lp5K9N@y-zjy6-JF@hS5m;{?&jMJqx~JLElr1@-Et;w`vUeA- zL*d94xVH!}p%l$@d0?Pfd$R`+NF{|^Xd!lom(+br6ZvbG?GkjSmJ66<CvLB8gEVV> zR84_pI*q0|3|Aj1A!K_^t0&Jql7Mh~JAhw0J5I%Dm6)wDf^puTGfZ_=dh8iBSg)lf zpw`UUx_rN6_HjhnRvz)sB@2e<NudeE+P)nZjs$BC0PG+^t8OIfH^7JJy5DTqSaP0j z@1#7d@5d+ES`E;<hjHFZ%RgL8$#2)CirCyE{a997NWzS)qcI3mtqky>AHx09>hpH0 z^Roa`v{PHawW8?M#I0t5u(~VLOsJBu^l$t}9<&v6{7zJ4S?1OmxOde4Kv!z{t{4r+ zcD?4elO&Hs5t_#JUd>il(DM&YvZXmO1b672l-s!8*+%+LZ-^@dVij=CpW(p(Wo)zc z9rLfZpQ3O1q_1vhWf$ybCRoh5@3;#_hRnXF83j)>a>Fwg&O=y<FSI+n)G*<Fx8&&+ zr3$B81X|ocG3M;>$$yxu-@+7xnVvgKGmc`FjTK;qq1LtN^X+2m=6u`&TGN+Ht{b@V zU<7TUw4U$iBqYyz=GzIql9LyqXi+Y}U7((vpT<p+0s6d&v&k#TSl=zpEORNqHNo*W zzYB1RO5c*~&lo$yzAA6wvVk?CsynJ*RG8&G+?q9|Hr2(PTjn%6yDXMV+e-f~Ey=sm zb=7|P(j>>iqa>XIfSAr@IdAt^{H~`34I}qGs6#B10N#uyPM~S^5YHJ%r*8nxM};Vo ze>bB~)%e94hE!mJ+iXN7sRNvPi{tYr#g-tKS0dIG1xVUkt-kW#u}Vlu%3~u?QK`<3 zYSrDXy1j_=$W6=NkPDW#dCUy-6EjJ375t-%=DWH?>!ZcPA!_hvo1nq!a`mA&mfzOQ z<F~>1B;W<ob4dqdlx!`_p0<YUo|GFX{MU?sY;v$}3bLe6{!hAawYN-ps^KafmeSBa zlb{kLUcvfN`!*T%tWq|{Ts4L$OzT%6^S%!cR#rEIpFUoAs^j|prtovFEtkAIi$ltj zfCHBSKpe?neUfkvL37_FW~^n*H(Qs@2kMqauslHT0oBcsl>hpC0fcWGl}1AQDFOc> zd-_4BOW#c?He-9`VL-M6?owsbC&(#JT+EE4CXMxvkKwIhtZ=64O8GX^=k{l<gG>$m zItlF+-a!!`$PX}IxID6D+HrC$W?5%(PHd>ezHoxEf$jV75Au7`7XZ@BUMRqE+x5j6 zQafQ;_u=6sIo$r&Nm~Wfusm*iOLZl3TJ29!C0+Uk?}L8aoAcL3qkPW;eepi;>wbOG zVG*e0^v1&Uc}*Vu4mcSX`yc1eGjMNgA!!fMxV-$A!X)C!-G*+W7k~<j3O9hk3i~EL zO+$tP`ub&Px3?^INv^zV?dUvd?iS93^;1@1<#Ag_nEG*Wj9%qmF#&7Ug~ZWRiENqS zT9fAp;7&>GpEf{ML6dk&JLa`FgveeTpAcKaO8qpZC*SQM)*o}+2Y5>FXWuMN&a)H) z&X$JvxJG4aGgrhiedqpJqcE3`RuZG)L{c>22p8mFQ|l12tkjkKEU}~=Qzl&z$4B}! zmBo#V?Rx*uLmA4G?9ue17bc@F$!nK^ZK-@av*EesK%c&f7(F}OQhtH2lAii(t1x|$ z&XoWnWZSytOmD^Q6*TS=`OkOivB@=xzzY+f`~K!HjEPNr@>ZM5Z9{JZv-7&V=vEFe zBRB{@kPy2skny#qdUq$W>1wNq8+acxz;cC3lpl?Gx!`{5gDV_aOeL%jNCMv_3NsgE z2)#071=N->FPu_a^|?QF@cfqIN?;m+eYIm_0ibRALeJm1(6v+!N!nA#okoGM*EV!+ zev58tzw_kgaf(mnjR`YWR;&~?n9r!oPCkvzQyH{l*hxj7<oHdNBN}pUI`=Aq<L~^l z{!-B=6+9)UF53`@>MY49zv0r~#WSl<q`DeQ<i6ihw~LlA7avd2@{SWL_%8)KS>8i6 zP2vZ63oE*J=?1Yo=i!|0Z!WnweAC}5`XtT$#U#!2B=}DpuYdS7@5_8)^rUVU&9lrw z5k+@|h44g!Cyr+JWun0uxEmB&jxwMY&kP7Sp>}S6NOtUX9V_E#nD*3`Ca6F9fj`k{ z`GU6apL(OVS-12#O-sJIY1jo!>Z*}E$@l}ecX&vKPOblwbXY@S+xE87AT57*OSniC z@T;fbFwZsjF1hrxw-UIq8co>&;;yhbwb&trG3m?W|Jn|dWo|j+2nTB<<pwxIClL90 znZ~iHYSKzu;ysgK%9pDOwgab+GL+fgjIBve`$RO^eAVK&0YO<>+}<r&^tr(UQ=b>U zdA*{2IO5v%ieRCiAqe}h`YA~RBKhS9fo5bn<kv|%IAU{*9<TW83ef+FfPT^cCZx{h z^k>HsbOEuS<oemrvgv*2{64obG!8`rN|b^A6Va<sN9HkY)C^e*6~guVt&Y!udf)R% zXiq7*6r_nU-e+Q_f=Q`Y#m0s<?<H%=<ULf})&gQnP&-wq5BrQQQPOh+Mn4YBNKqT? zC)+fd$Irs#&f!Yua+gY<YW`9RXMeLPR5MW?ipu`>63=>W$Q5nbK=KbZ6>OlNSrjim zECTF3<D&J~2jyewmmD&i#`k|F;3lV7cuI^H)b@K${M7c#_x8?H>#j=TbyzS-A5`c# znjL0JU^nW&uO7a{4L2j)LwSz4nb)^;3T8eq|JP==fNxT2g_Fv!Cp}gwt!R_`mo{XU z<4&=r|51th7o}tq{s&E+vt148erGRMS0SU8o*M1;)QO<00q|)m_Nky1SOpZ=aFlW` z%K7glc`3rQ8$8J{Ja>*=RBOXE?k;HXemOyyUxhaO)9jhYjrHX+7H7!$D@XfvW>Cnp z%ty16k1OCJGQktJU%)@tE<&HOyyHLJ(a+vGv7o{p11A(n<@~}KvplRp3)ta$&Mx}d z5~QL4tuL$Zi6DF58$T{iV4)q;pT0KEQO&n8y}y5r{v#;A(xAKt`v4WYo!JPrj0i}K zl9&mVm7n#<holZHqU*mG7{0dq_SU^BxWf1XxZk-G`oRH~p_g)cITufaH$KTDWnc!H z$yI@?gQmAukE19~AFyPWb^o0_NMVI16@h;zid-cf&DB*%X}8$_9_l$X0xnwGSX)7O z@?CX64XFTIn_26#G^wLd3NN}Rm4>zph_zEvm5z0mC-T{ASDGhn5w7DuiFlqvu|Gb< znNMmC8tk_5ATEo;vjR+~R2lYD9^qa~_L^oOGj`B)u*<hUcr`D4rk~CX@AicsvCK75 zI<ivH^gYP#iXlTRw%5=ZgKKbZ`g>#QZH!WmA-xo<(dYQ(%&!DC{8VX_>4;y`NJ^=2 zKk(vmjq_Xx{vRx8?iyvQf5*{dF(PJ^p_?!3Hit-`RUDEZY7t<?R)-ErlZy3VV08UZ z@m=N|mzyD5QyX`<Jw@1%AH5$TrCn`nNy@uiwfofC-J+z}K{1cGE0W&pfje;wO410g zF8K5NK8FL8<vOg{;VCVh?j{+Dk^s54!zz$lf`(2b`gg`aU#T?MNn+f7bp;ZxD1Rz~ z)dzd4qJ9aN(?xF4RnK@Or~QJE4re>L(KK|s6INCztfE&O>!1(~Hw|PPp+~lMGl8-O zJ9Ne?NOq7S7&U+rpQ8=AId7zveaUj8$?n5>MMD>PEHexljylfW2>9`Uh)0u1v8^{- z;%>r&pI_c!2?}vizLy4%hk%0-+ZF>O6wdm>+jReq5*zwUK19l)6~C-_JBreY2tZPw zJX1vf@TZZzn}#1YS2*VQy-B>ypnz6t2&+mfUWBK@OPK6Zbm^;ri$|CZQmQe-wBYSl z6g(}&zUPS}z~UK6JBLgs-ehKV*!L5M?;Ob4zsyjY^PGG6i~GZHr0bAtkc|$(iMokz z&k8IdZIkFwhNO9`EudiXtk}X#JR>o|BZkPnLKt4~u~XhQPh>V6#C5o61r^7h4HCdq zshk(B^o;dq;MWON&EHZ742hug&!LTE@>4`m-Im_eranVFn=&}hGoy6cBJE-5qsC9x ziy6?1P>xi+7^W@vH^yu=`k&iuIecXCtwwq|a=T&HgMSL-Qk9jr`|cYEDzI2Seko|I z@n+8$m-J&{TH7r5s#c}S3i2xX#~MXE(g|a#HfO62k5GD1kH)F2UAijZs#x8=7QQA2 zs!<iClZDks!+Ndyb(!1e8>}UD*jB`hstp`AP{ObaXhr$e>4aT1vSMo{<$RvxPT5+` z9ELby4ND2<TJhe*!mnHIBvlkfU#9K;`oc+o)0NJte`H}?Y)ueGPB;=u&<~lxBxf`N zrk<~?GmmNAN~}me&NTi}9{j5?T?KEPy{=9kgZNhx9L%>LdvIM&PH1X{KB*CuU84`M z=klB>tp`Z)Gy%^%+Nw3Hv}!U=O@-m9``g8#VD`-Cx{N_Bq}$@?2p7-_Up}TEh9Cv? zYm}wEUi>T>cv{RGg~fI1Q6+5%0C!`p9>3LLd4Iy1P55I$?NF=F`ZXypVy)m$tK17s z3rJAfm~3Fc@hIyJX!CG>)tH~oIOm5k53b(CwPH25Q)XatFMvlnp!#FXWZakR(k;$Q z-23+kO-3yBkGm31aut6Oscot;$otWaNkTqQdx+-tRnD?DEm|Tu07jvgk*UcExVW>V zhE_Od$5W=E|7#E(AgS(aIN^G_MR<yL@To+@Iq~HxbNv_GvK<l6rc7dOmOb=noD7W3 zY%^3C&VQ=mFnZ@1T?{dh_Hi8qMh8W&4zOSForirP2w#i+l<!}&Ls^ZIsf-6zR8!f$ zN#Z~GV^4B{@d8)8{P^3tV&v38;1d~H;b)TU`QZ(&QMtA^@$#SHO9tdKiB+<M&OuID z&<Q?VZn>sT!n;U(X_(qK7{}Y{yU?XR4Xw2(_9x2B7`TYe@8jIMMB3p~S@+CS;q`FJ zAMjajq{%(D@-Vbw!OQERDIP2xUZM;&Oi;9^$NNJ#{B=kl@k5u0Oj=rj+JcpIjH0g_ zwR75@k*yfXXeMw|6cU^JE<Ja?c`<nWfKi*M+IPuJz1Q<ZZsK48uwS<XpMOt}cDbCp z3MVx+$^oD-vO8=P4fF1=|1j4WEFfz49BPkTHoRgq;}%&?V5vPmt0RBZnX1pp_SV!* zc8<(A(N&0xux0c_wJp=pi)c%5^yll#2DSAn9b@xe@YQLT#b5sk*04h2I%6XFx%C0c z9R^=ql@f0JmjF??c%W87oxn)=9Y?GAKe#{Sem8n+c}%9vbG=_$UkLjoE^(F)tt_WQ z*PL=3%}8hg&p@@A1gIyZg^AlXcrfkRiIa*dyy&59$aa&{w?I|nJ%KE$oy)B7r~Yj# zXr*i=a5!j0r&QQF^xSQ%665}8P90iv{3XYsPl)gWt<i9A1heb^Iqm6BcNuOPKfZps zrbknjO5X7u?Mrf0v1KO!);RxNq69eB^s`xLX0p6Fx8EScDZGfv*euZQnuhO+mSv@h zY~^5F$qW)Ld(P~8?QCBgAp+PX@Jj87bWAYT+rX~??naEs)~z5OX#1r%8Zvk|5nSZG ze55T<U6SH&Npa}7hsQ)WZTUnFDTZD*$v9>xs<;U82+JR}{q(;6szcM4`vHns?N;3h zUw`t%t*tOUjC~OI-RG7T7JMhQ(b#)Ncw+!ySv>S?xI3>hu78}^&40;wgjf3fp5uHt zk5zh}+YQHO^Q8EeY5EE4`vrA_Mkn#3aq9Nqy!@pNmEO4j1xmalJx}`o_v-xboRr}y zpPCC7acWvrv*dd!aqVAU4VFF6Vk9&lxPSOb({K1&-|GsoL&2pLU$sxfBi?@ZvRlaq z@(=#X`*&OmO+@kwLw@hbqzHrRR73WIA7!&D>E=`rNc#oz%Zpe?5H@5c_a|OC-HWY= z=86(sQ`09SCIfvm`hNIN6gK4ldSs>b8%h!u(MrI34DdUZ*>bgV`^XEG{3ac^|3$S8 zlX?dda2K`L4(VVs?ua>Yg{>1xPhoSUb9{41C|X+jY5l?p#MIBF600KCBTsl%v=?dl zqOK4OKALv&xJHeqPsJSTh7jI}q}MJ{?0zFQ!iUW17Kv^j7@0mBY)UF1dTNO>eWNFp zrh9#YIGoU{Xh{$1_VVe@*5yNLqCPpi!OzhG%LJHd%wWXJkwStNx|a{}GR~hBnaa^f z+)P6U&;mRJLyQDoAy!H1U{@z$hIOA}x!(=<)B6oar4F{@I~EM$+s|r<q2fR^*JvA{ zTy;-!^F$3?DRdy*rkT}y=m_eGz~+)D^YP|;ZUBmTa&Y^i@8>(;88z#UT0k+E84sbJ zRze8fnTYAyl$e*02isIj=8A1tl8dh4oC;+Po^kxD00p*rRQc>jOyy5=fUUyxP96Vz zH@WAMw_7tiB)S6+CGZF-!!qVY^nMAwpq{sWI#I9Rb<nl&n!Mat@0MqGt`zY|{vSJZ zK@g|ZY;~zXYrd**9B?Gx5<2_xsksElEM##XJY9wHT0j1OB%Nhc)BoSbw^1SuA{{D% z(jnb~AW|YFAYCFQAkAP164D@@f{Ju^Y;-e1ItGmH9I!FC_xs;Z_Go82XXkwPd4Jy5 zb-k{6?5o&Cwkd@b*Hktwzm&dITu!_8Z+U3kuYw$h6=E9t+mf=jPONjIX?+|M^2%B0 z7|S_X&A1}42J=m(U|&L+QH=>GY0ch~RO{&b>k_95)@HwF`<*Tuc8IR1Dr_z4YM-Bf zQr}*MK@y!K;uyJ38*?tl2`TH_+Q7p*{B2~GKN=Xi7WUgmw0>{3*PlGG2}o#6KSQR_ z7~qO|KPUux$Wcq5e`@d0=ob!NiL~|R54&u}zEOAW+$nU<D`&fM!P`7=zrRIHAh*&~ z1btlYQg45~{5MeelN0ddm8unl%n9dsq_vDG6>93snmIv);@{5Quwf;kUlC<4zk;y% zzRYb}%!#{K&D+uA=^GI7A(SA)X35^C=!2LXOT1PZ7A{kXUeC##O)?BGJpxg>BUH6t z<`=tEUR@eq<eh7NatXbd7AWuT%D?Fq&^f_|%OJm=juze^*J{rs2Qq|#i(ETghD|AK zK-mFjKAK~@L^X2NKRIFp9I8)FoQ;pZoJxgnE^uj9Ov-nq_n?_AWk$qZVlQ6x_fEOt z<}AptpM@!zU#zx9m_0&dJ}t%&Z%==!kd;#V4Wxw^m#MT!FtsM;O{>CB{HOw&Q>}s9 zn-f~qtNn$*2CY5_v}+ewS+8K~j&OgB<-AO8B5^ZN=hnUqf!9ui=l|w%@&mNo%u~rq zw4576{`{RrC<Q}NEukG>T!pLDwbi}>SLzS6=;0-4|IWN*#%5SPk{GB&{eh8tU`GRn zEE7E3RJE1aq8>!tt$1JFWFl^K!fe7>9*5S8=QrB4Cv0MB^zaT!yl_3$V|yA0v>{+) zT+VgS-dJQPF}?IQKu5U9FnaGzoCoKMpG%$YhmgEXCKoZ?mQ$2#Qq_`+J=N@;y{+T| za7Bb-#S{Sd%h@|ieY9}`Cz;1iIkD5+aObgYMLs>;8i^a2t+h&YVDS&ImHuodF0z@t z8-L-uNNuqc9T_g3OBe1mV`YQ&j3E#MY|oL^mAqGX%@?_SqH;(CK4iPEahS-#-Y!}X zj?I3{0-{{j`}%?Dt*r)IVk}_Rybuxh>i8#aYovsHKT`J|dcsS7ehp5$S{lwNE&zx3 zAlC>Vc(tAO1{=`qnp-*M{QNZ5e|x~A%9=|eJHop;*B)prN^cV`gf1a`;%na4!cc=0 z#i~!}$G-OJp3{rZMNL&We|T_!qBMfd4o?b?GQRGUY2rC4i)m_%>5%yawk1I}9uS!x z*fm^cRpJxK<F%FUDErap{ibDlEpxCv5wsA{VPoKuX^2Vd)r3`tj4wArm*jC3Y@4F| zklHf)oohL<oYgn4Bh<s(nLZzCy^Sb?*9c2-8CP^!yeu@}6tB4%mWnJ)AJehl_u8o- z7p%Cci;^_^A~<R2mm*5`M$W1({WIwB;HawI+z8^O1L`hG60|Lv``-U6qG6DE`<4ib z_TCKIB461*x}}8zQ!>VsKjx>r$3y(SW!n4UH89}LQUKxLMlT_z(V5j~TM!w{|5m)B zDf+t`hD#J%7{+QEIfhaL)VHD1FN<0Cit9tE*typt3d>I9PtKR(ec!GE50XR!0*6Gk zJud6Lg2WFNv?g@_*G*z0Dw&}+ANKD*>#7)YRpF0Rwcg5nr0wdELqM(#USjl^RA0i+ zqhm~=L~X_rInv}(C7D#}({<$yysVOyR<`ynP<xWFCg+}yig8$-{(<jM?CD=Z@5H~r zbfrC8q6@<foq{QI!E`6RgJ$Q=ECRC?(Q-wU6b8^b>Iop1PymR(r^1VJQoG+u1y;q2 zrDJ^i0e_x=I-k$0iRAq!m2-Htx$wX}cLmSlAnjn0ao<B=%G_6i&yfWFFvmICk?mU% zs|dNl1xccStgYGcOMzf%wV}K+fZ2wAxsHpT4PCWi4INM2tC@Vm{J!T58y7fJ*Ex&R zqXF@I_#d71%miNTgaXcwE}mFgM+tFmYMcXT1^sggD3}f!P29`WA^RX6lqW_lqP;8H z^fV@#-shVv3R2bzE@(J?dI-c3V---A?XXF7Qw!{?q&*}}l31B-gMU;B_4x~zIHaX1 z$#muLzZ%YS1(fC}j;|-~i~0PO-iL^y8gCBVDuB6fLo@&my5tFBrP@2C^NK%BTh^m| zs{6hiL6L$MVOUBAu8T3uN8P<6deTC?ug$mOzX8{adG*=|=E9U$&PYt-5OcD$U*_xk zJ*J{|RW*5)&k2Glwhh?Elb}<Poey*k%td9ysZ&&fr><G2B$v-K3(7>}MpIZeSmZV} z>`67<Z>AAF#E%B5#>1H+s_A#GPY4J7>GuYGMoyhwmMH5-SwC%ohuS`FYu2S8E6?+% zBa}+}?!6}xF6%v^%l^%?>@8Ty`V%lOar`S|%-tLAvFKe6+BZG-i~D3-Z%)3g4Tg-@ z--efCG}%A+e{lGC=Z(kLa%e)Z(6YS|u3wP-@}ibC<c|P9m;Zc-DdO7}`e!soJv^6E z_OMV1THS@Xyl_>6pI)t7jG*d(MGo-GLRM)l=?iwLttXx1<PJm@()G(8V>(PdL?-EH zO2`S#yb1(cBXGR>1cSu6tHg~p=pSC!07zV=bvk$pbFUW;*)&yLr-YBp2zE*0z_WG6 z<2Lt?kU<&5(FbR9<$)Q-$ewCzEEUsCBqVVCjWSguv6cqpuv5f5o=n<17eBs!(Z0S! zmhHouy^Qz)U;XZuqhZp|MP9?C_iw}?&HO=@B7bq2f)Yl+1?O?=0S5r1{B;ei?)bsL z0Gt}e`upe1KM5+u27iv|z#qnNQ&IZc-+@8;jt>7^ErEx&16gK7VSO1ePCFISQg?{7 z`sQ#j-fc~gN9;}a=!5t4T&C#FR89ri(ffBPMjF^+CyMcExgUffEnkL}z>!s6(289X zsJY6wuv<KP>B;f%VfVk&C$PH@h>JmPC@gn{A;ZUX_F6+^HZ!mjg{Tg{!)*X_hLAXt zY--8c*8uRluK#x;h!=5)Tc#Hl-ChX`C2PC$s9%k5Dq)BI1vQKMV<Md*`7|EVxJWv< zvRlod{IiLhTUeq19?z5l=sZkl?}^6=Yrg0j5)+}e_#NEGvpEb&OO3qjXN|Kvy_UTq zk?T^eU;Qaesa0mitzJi-8WT!N)1S#Wyx7j_NH{-2Ms27mYAxZ<_|er}s3jeaMKFIO zq9zBY`IV$4E0e)WqEUt{M-_N&RXJ~=Ty<$Ecx4aitX+6_BeXKO&?k8hW@Pq=P^&5g z|73hSXIr0A-n6YfXp7Bu|8t1*<N7oqA{!jUqE4B__FPH)t!zV6elB-GASZyegjGGf zUDE<5Pi7Rp08TpJKDww4IR*TijHLk#C$Y^33fSyaI?Z@~E0xMy;bb?F+}q2X4CQ)5 z25gOjY=xbRn+IKQydWi?*n5ArrWUIbC|3z5TcTuP``CVnMGoUxk&_6@@;^b*OD8#N zRPEt1TKdp0914|uYT84(e!X&HmF-bYf-FB}l~r3p>oHOnUcf(nhpx_~jmS&uxgENm zh}%xjwT`zz3q<Tmr3^$Q1nB;R^M6Z6m|fNL`VP;FiBWt$sa)wV%v7?y8|5f%QahB; zjhfRHh2+@b&MI3cw)Jn_Q2dD^WuUO>U)c*yW*xFWTb1JV*?LqH%b!+=AN=H6>JQ85 znwLHFY5om=ZJv9fp%HBZcN2f`c{$l<(k34@hZ7c;MCDHwvOiuVX#zabf=HYZv({Vu zcaM#E%Y8>fs|TO>$54nN!B(awJ;9Noldi9~WLnV6vT?^#GlYLI^oQSYgFPe6bu~Me zcu#JUh&$w`Nv#aR4qv-0iRlNy2gB)szwLhN_};j$OMM7K*nIBOB|ifXM&!I1rZFxO zYNB(yecyN8-~quj9o=B>Br>`>Zae6{IN28=i;FojbYR>QB8N^5PToaOxH`I_?y}Gi zUw6ZPmDf9ytu$B0=&ns5mcw(n;@fZB4|xyQ4=Oxc5js+loIsh!jFs%j?tk|*HZ<ng z6#ZQmZL0ZxLoJpw`o+Kjhqf|elO%}|=Tv2UgnQwT<lW3yn@%oDjt$bz;Luw$Y2DIf zIBsYNXR;2_*L>1JH5&P&hf>%HzcRS0WOQ0D#(aTcLBC>IAOEc_@n`LbNAu&u{2pXZ zxqAvei9rHZRna+kx2ZCnc$7=<uS2k>qe4U|(aM_-UlM6?H>-oKYjP2bBFPnM_Z0pj z&qr#FTI98+z(~6cou>uEtcFFgZ?m5?QN-g=zp{OCk|Z+JOG9ext4zb}7;<<OD6oSJ zFoGbjIK59&3`1cghG<X89uf~1ED5KPSN2tSO6rbq2&5&6%=0PMK)b3J^Z3N>8Q^?6 zMZn)j$QSm1=~q+zkOfya^sZZS+zRK3sS;{URSDo^x<-X29qP6aQ>?$)ZQratF-L~l z9XWOVa~gW#o*7@(xBH(#`S#bO-oTcuvEf~|O;3w(XL5FoF#L@Bcxqp=96)^O##)WA z(RO30p1I=ZSs~Cm6Z{;E<HyTy^tA$aZ7-(x9emE@V=7#ovAz$Sg}4YdIgBf=r{BMG z30S`{(;+I&lsR-5LF>m@nx<URMFNV5IpANUmC;S<Bk?ZK20!gx0-u@Sb+P#Nt3ASE zb;l=eMxgyyA#*I@cOR|s>3T6A0GDEaJX7!POBTJX8xEN76|vk2YL)!<sn&4j25FZz z5Jjb46bm*Lmz>tFDH1y8bJdaU3k9af&W~zt_8=E4)|94o*$6)ieZpdZBWU556jQOT z0a||3ax7V6`O_1byVoXbRYR2EV&FkTQPqnnS^wznbV`elGRAj~ZBpOEccdNn%6dH> zOTN6}Kevey`-7E>l*?BQ+Og_CoN(;F`r}s%J?5B2P5H}=#ez}1CZ5|tfw^uPU#>(p z#?%_*NozVAt+CYPp^lu~-^wr<3Wl~*(%p#OU}D<A0`T0V_HS~3lE{|%6Qf*nEm@wr z*_uP%{R0>5k}TitZ=d$-Wq%O5;S)n@%RYxoI^y{d#l6C8J%uYVXtLK;Fh5otIC~pd zmUWR-c7|^V(#A^O`l=`juE{0n`yh5eay&dQ^%i;fz;rlB^_*UxNfp|8e*Y-Ju6<OG zLE59C##b0py)3}wr6*8v3K(#PIj_cPg!$?_ZgGw+a;U2Dtw6!K!Z#5WAIjm8zvagz zfO(^hW_3wSX|5=mnh%{;iQ>7L?|_xgF#l5ARn3aUK29w-TSoYbh|8<J;X;b}<_1l3 zC&e}O{P8Bbdz^R5Z6s-<WyDQa<(taG(LnL8><FMw@R8>VwAj}NA!C+IigK-wbu7P# z6Q1X)+JEsS=jQ?+&;GtfI^=DSHD>te15*1V$N)i~x4y}dm$g1SfN!4lD|f%-Y^RS? z6z9_8d%E-5IyeoG@}Ff-C_(e7mIf)rx(<%NpJuZp**AVUV=^0CP!!HuY{T8Zxo22b zDpYZVb?5`5E;v6M_^K}3u_ZrDdXuj-Aw*1Fy~i=kK5tbXCz$P!=dV$%iQ3Pk_-$Ap zc`NNYhi!x7eU(R^>A|e&DCc-}K1~(kQU+$9EEg-7{oYNV-CsH3=c0l!U@uj!TXGqe zT3^y@e{rbgTjlr?CAI$jAJW8`(`{zcID5`?YA`zmuG0o-MN7^_eHbjqV_Wwe-8s@u za1HteBl4Bzf*3aDG91g6R}zh56TSxm*2*`Q{3&jAda+J5nxVWj&uk7pn(MfHD4Hkq z{UlVDdGXo-G^VRAkDl3P#a=Jpd_S#mS`^@I`H1rV$e9<Rz#dSuw2(fb4=C{c^kc?b zuLa@ytBmQ&nTmAABNgaDMC<fziAy4yih{Vwx`!i)*_^?nU6y~vTcl=A3^1ru8Yo74 z`FeVKXmwxG02cH1j)w^JXlBx5En60oP9R>SC<y_AX|P5v5v$AM)4jb;Uz~!T7{B2X zw{w+KC}k`%6aM>QueBm)RyOOAu(G-Lr3U^uR?LsRlK--F;FztUw7Q2;MC(;j(WLBA zG7#()k;<}#AL&UA3(y$1Mq|G>8J2G7fQQGGwoDv`JkZl{Pjdu~vJ!3@LA&Ns;F_l5 z+t5ErW@q)aBbi``@Yft(wFUG=xmV~AMnQ@lyAKt6WjvMzzMT=LoNq2HmE+ouXr^U; zI%YLoEZJ;&O;wOp9_?zkqsk#je(k+jXn)R`025^CPs6NGED5}I20ySb=Bjqx*Az;3 z;VmF>&R#}CZ#87z47v1bGu4=%NP^ko^(XgyUiLIi7)v*Xcww4nPv(e1#rxctwp~CI zd+18wp(ojZ%Jq=)X8&*3Rm&6sEhk#ZpJXOFouso?QIg8i`;~Yy!}dP%mFtB5uo$N} zCKwPiCs(-+IntqOdMnsw@4AZ?7`iPamHlPV`MOj+=f%Fl6tx11?=F>IM@cu=t3sU- zX_Az%#CkW}=(7tbZ-@z+lHke;bf@)s7bd%$&PDhv?yj!SFjz$Aw~l#_Ph=@B9kAW; zN6m%BNQ2xyQO!jWCrWC#PY&qBy`mYrM%Bh;_L!iEucDrCuX2QQk8=ti#kKH?yDTNK zAT%btL*6l)k*Hz^H*5(<n*n?LDz(371R8;RMKquTHWPz~rA?qWTTtHfXznR(vt*oO z;Z#>9w~cTvDXSmFzOeQf0a#ukOw8&q1<lNI5k8zteBkp0?KKMMdP&snLHOlG$QW&T z(#t==6XW)hidH|AgzVMLvjLdWx3I@Ucbwz!*Z+x)w3TZBb~Gi$XV4Y(XWWP3G|E}~ z@J~t`v^X=|b?;Zes4Zrn3B3>(*!41%%iczyar<mbjo*VRUTOupLY}ftddMTIova7g z;z476+d0WA#EWdM!?w3@*{<kI^Ud!J{jscTiihIHC`Ra-Z!uXkt;zl_gFEQMlg$^E zk1a{^XRakkEaVYm{c=Od5BOS@U7#zKoMXtpOK7%#6G?uHByBcec_?z9RM}g33rF^G zM>&szQX2>Fr|nFGdA8COy}12VQEqSVQrAls1nzKWYSqX?$)vaK&)*{=)XJ12JFT1{ zEdy81=JtUp)1I&HYL0lwS4<rMF&o~((j72X-**&B=;B4l2@s)QVxQ2=#(R=YsYCR= zkmbp*<E!xBeM8^1K7u#EdXU@)%f4R`cSTgaS^9Zw|B=u-XDa$ULtZ>++(@#Cxpa{- zTbZa>%wvfjk5$7Htn_UQ12$u1o%iv>)_g^d8W}SHdDDc&<#!M6q_lkjde+xuOxp|< zLe){X^D*mwxSQ}SR!621JdtzK?*m!J{F7&`YIQz}QRQ|`wcpL8r`}avkJ#XY<ZxSL z?Q!Ss0;0<u<4zd=!+tdUJj1^`v#CIRveY^heay)c_=&}z<m@Qlu;u!kRw`F-x%=tV z9@zO{9wpau>jwALU6gqAPHcL|<>65vmwJD!`@#m!(&M-W&dHTry2xsL1($>PW`g_4 zv9+>&c8e~V-py$PN@%5Ad;ks1aTlI&ykVP_$|@Cg|1Td))vwLg#%hYy(!voOw-S0J zmD;XEzczB3aZt|eWzmrOxi)Tq^r*V)vDto&V@sC4uZ{1^pGCoq(L(dxtkr+w2I(S< zF&qyH+3!`b!fgJ`aQ)cjvC1K^$dtTaZ8-Pn+w}kfv2=U?W-27;<mfJwZ$(P{oVX;Y zi?y;Z5qwHxOa~J-+0mub_w6i#Yo~c-FcNz?Bh{^zwl2*l7~y+jrEfL^86=<%Amkoc z-xwPHG^cs<oKx*h@;&yD-k;s4B=uUl%6h{XTt#zg=9taPbgk<8|JNLIRdVAgwEjne z=4^7d)g{$ICc9>^BZd<-4#WreIQBS{qnBu0!mcqtBwoZMHH46Ulm8-gH3$oAcLIzo zD9RKOy?4YEulcHn$QP!GOfy(=P$c5TJgrO?skcYil&71zb6!dc4Y1-6qRHm7Azasj zN6TTC?=@CCt=<@J^ai=rIuP*kmsg1B7A1b0x0?{#`^kJzh+{%W2Jh{g1UuL1_|N`Z zT&BG-<lDHw?LpzX?~X9~1*DQnw_+YE94(R-@-6uX`wOLzLZ5FXutYl1_ePZzYx*Z6 z+YkCNhHTga!`o*_#m(W!{zvEf9RF<6;BoV1c;n9g&-X1I0R5(Z@66gy{}rYCpEr1$ zAP@`J-CwJoIoAoWQMUd)s-Be78@uTx;ML~4LrN1$+l;PD6DyF)RI#rIijJ9+#07GG z3RdH+!ldor^ftIi6jSNpPdT<-*E2WCWIl7fhqukS$-B32#~Hjq0*24-aW@5{XhO~( zFdk7d85zAH1VU%Z3v=hZ_r)s;8(Q!d=7`=x<txn*B4crVPx@*C4kp4S%}9L$ZMll8 z?2Ns$_VA()jl0V5(hfl>C9Ghve{oGYOeud?2)`F6P;*ZcIJHoFPfNSyLoccD+G4jI z;9o6IObq=8axNS|N9Zj06#i9T_SPEhhrR=>;!9Up3yA`=dv04!1>7Wb%ch=x6Dz3j z=LKZ+abBBk-cl2N7x-YcS{}2GH#ZmbO45}Uh+^Cof4M1uE1`7F`b9SD3bzkHS&8H> z`0arzG4u;1!ru)rqL}nJs-@rFJC-VOvToV477xW2x(b8nCZWFq*Ir&k<BFga{Hkzv z#R8{)Rc5TT`osI2A~-&e-u8IU-yFX*g!Kw>@m2lE1M_4Pzw;w|YViwAB}3oVpg-x0 zTh{|+PFtZ|;|^YP1SvO;tia_J>Qtal5)Uk9pK&G_eCzrESAl2I!&ccDeK|8EKKWGL z82!aR$oulil#e#H`PWSeuRM>sv{){UIQ5fVt`FU0(8nLn#{d33+EEEAZzv(Y@=l)I z2%mZMMqLJe;8DECk>vEuNqFFZn=Nh`UhuygWulrf-8`<+l6D2>+i~a-yhaqv%&f=7 zzDpc%adk8zBi*?M?ED1$D?Z{Wk!g3%m8$fbx>~~isU=-6F}Bd(ChL4p)ZCDs@D{XG z;Cq{DbPGQBSdM7NcRJB$CD?Ql!YkiVK);dq&eY8!u=$cmKzY{VUhv0)5YA8(_2i8; z<k>j-D!M#K2Wn+)T{P6vlO@Ss;N0eLOrr&C8J;8LASSj+ZMqK=S0~*6AWu^6NQjbo z0Z!4~r$<+&*GCnMyz>3!Y%Kh3>*CGqG*loM{H~l~#&lC^213h|0<&EnV-l4-8)4%0 z&H4W5R*T;)^8WjFO{-wz(021}&ET)k<r?B@vNrh(OwYs>6CPK+6n<jAnX7cpZa+t; zRXHSf>_zUQwD1#9{sbo^lJ5g&X04eTJ4DGLX=!|?$`SO9{hsB3ic_f>g{307Y*~t( zAcni`BN^0|&WoXi!t(~&u@67lO+Lv!D`3$eygY6Kv-G=)WG?`G&E>h#aTP&)L)Yo< zpv@9|GV?pVGG3LUzKW|~>e`ynjY-|qoMc@JQ;%$Zxp`Wwn30X@n)Y8_@fYnHq$j#r zI}#%vaZ<~PtclAnfgwMI9~K<X9@u~)#K>&u+SaJ8%C^d(IVN!(K{5+;OjSu@(0}A< zOnb7`9x@N{FzK@j@;lt#siwUhGU&ZmyK7oeEQRKt7bbNnBjN|z&VSkZ6CM}HaayIC zR%}7D6ndVG<<ykB`*ASd>l>B1*yDBm=s&~?SPO)p+|W_yGKJbLbjbMo$0p9C3+;a7 z&sF=c*g*@rl!Op+h6<&dzxQ@iEm3qt)2`cB%gn0ixjG6TweajAfIs!<iC!H_Df1Bm z-)v@Kifpl7og1X(emsH<fK&0EU2?n?`03#3hI12`Y>IL!)wzPH{O8pP<|~d{XNaN= zpB~R>u_tK-=>Qk>i2)Ut0=9Dr_iaA768ZGy_y#UMOEtNxDrg(o(u1Im-lLA}H2Tn4 zjM0}D=vtBf1qEN*5&0Pj9iBmC&nrytQ<yB!Yu1j*C(+bvB{vJ*m6R0<y<Rhyy<H%I zMI(?}E5aiDc&Sajq81&%=auYMYMvA8S^&%N7q<p}Ns1PGf0hi037T4W0>VayT^cge zU-L1ax!DfKf71z^nxOb*znI#4DWa-pP#fD9$oAAPTDARX(n0=9;_ClvjB)MP*XJck zjD7@YoE&2CW1#xK&UUpwzC*Q-)7LjE_kNzGm^jvp2(7ys7&sbzlz>fgfq_LmnYw)! z{C4Zf*8U5jf6E!${sgXn`f$rHnxtNeS0?F!DYtVE`iI}>nzVGisb0cWzY0xoySY!x zo=F}5L1-dV!QkxmmsdSk%LYf3va_U!NW$&D=Ecp6KY@D0?_KO+Ct$G!N#`d1f3ff2 z7(Jq-x{vtX`XQ^!HWm&0>|hPBI`-ZbIop;8jMep6N|W&NCCc+V?4=0m!G!<>jSDoA z<2IkDVC+7jKV^1IJ3W?p`Lt(h4<mn55Df=WR!wZE*XYR$1l<<a%F-%a=Chi5O^CkX zWkQX$%GaS?7gW@DpC@e3<)*T1q;8BuO$%(itu$Z1)FQZ{$QG~1+coSs`1KW$D$E=o zSb{ei$HRlIZEtLw$&Q>c>v=R6wp|ogkUiu2J+h@l7F|BmTbb!ezZ1(Hm{_~5=~BsD zT)@27>P-)u1z*08B%zI0XZ_Aq3Ct7D3vhqiwtJ+e!uUiVZjkJV0a7_}DWy;AQ<zg; z)`n>2?o-{b#lE)y%T1l$)Qf}j3vT3AZVF{C!KKz&`&Rsid#=hH(<mNK2(pp*JvXHS z(<d(X6}5YV{?#w#7c^O(ZueC#k8&K^$EE}$J3d>qXtRkah$|m~fv45>P|+ct?OcVY zQjk?tBbE2CG#FxqX(}SxKKLZCn$`D$q2=Iq+)_MYuc_U)ZlHfD<qf6yN?AM2nlexP zi^Gp}nGB0l@*Y7*yxu_-wj-;L;!vFQ|EqTMRdLo9w|!8&0q7-`7r>^_>er45rCn_^ zdqK?_svnq&sAiZuND|cW_rCDn8Otom@$zj3+_wA89qdPmv_$Z;mhY(UHU_;U9p_)z z2XJ|CdgIvHNrLhh-iHfPWHV;ilDilF1dXpd_izO6&v=cUo*b3zNPq;prJ~l`#N6(k z*d)%4z%VD-xz2hI>DAx96N+?#ZT?wsn(<Ii>c6C{hW9&jo1rOM(2sZrN?RkZf;3pT zp0988x5ChVP#1f6DpRbIhP(RUgTw4!M=#}bN;gwJ_Bk{*ve<xxHE|Kf@JEvo?t4Rj zM2h1`_U#$P<A!8BKR|`sFTQ6QR5U30XO?|Q^GtE9S3sPWGv2Bbv^9b9c?7KA%EF4X zZmU4;eNuuZM1c!!ztKD~U3Mja0IFm2WPnd(==KA9N#IS3Odo+os$nDOHR{F63!-P{ z)@mT;kI!!Pu^8?<*_LiHa>xrJ75nEz-FcQ1%H}I!fkDMX9<btORvpl+hsB4%?*zVi zroa{s9ng56k2D-~wDPI81OWwkNet1fGd-jBi7}M445-KJ74ec#8$Hi`C$t1V_w=sr z$|=V=RoK%Q;A(H1TYaU?Cp8Y=q}mrXwUN{xJ|&jcgIvfy@UKf*+!8en0?zF*+hCf+ z9utqdN(@A28Oajzd%!$b*n_mc@S{N#pd&czmSMc?kovt9_?4(XY%=4Kyk#$Qe%z^; z*CT(EFR?Sh(oG?JIO$N!3-SW<paKLxDYhGvhkLGk`0^dEzrM!R<|sVqO2AuAItWyL z>)PERfBUd<?7$Zm{yrXW+k-IAHl@M47`RoOKtB$zcz)#b^AlFp(~pc!p=}p_u%XMM zfgC(@wR~D$8}qeT%=`<67=bb5n`wZnFA>v$=T*z71kQkp26%n2TjYY<w;$T>5@&x3 zq6XP|NgI#+oR&OyXNjMQ0amvUeh<_>k3Gg_z7LNA9_`7;A@+@*kn{dzY`S~H^T^Xl z-V)D4Y)iZo;;D4-E9$4$uzPrlHmTE@XE{rYESU7i$vj+#OktjL)5cU`u<Ax}o+fX1 zQah+^dT!QP_LAs*l;W)+K|9ysz-Q;w;@zz{vU>X}mAh@Lu|tv3%d>D7qsvfgh86fC z^4;YCIe&|W)OoQCJet_Lx*>Na^%Bt&S_V2Kb%x*1n{&C;+&uCE1fBhQIJFCPmY)V| zMQm@+w4=^}k>6;x5weF@4unpy8a{8w7SB5S-DidO(h4#AN`8Zg<S~m={qW&Qr%lfd z-$19fkz@|LWi}Jh*KJ<>yb7hJtmB_ly}-_Q`*^XLmzko}F@7YD0q*jMY4eLkG)8xq zI7LqW39p@Z3v;I~g*g~gZW1MtA-MM2_xj+fND!@MCO|wlgjSxWajGF0XV4NNN*QOc zJJx2qBJw`&JKjaoZQfN>;KiK~s;@B4%zoV`bhV_o;x*yzCw^mqZj%&x)Ampuo&6lC z&Y}4xuOTQ@44e4uf(P)p=<Xtq3a-<O84jiM$hFxx-YdVPvymp558nS{E*y+4mI-dC zCfZ?+vpEO_wA|uc1R{=$*{D@6hDZB2ca0_Cnc6kq$^WV*)7LpuG=W99rpbMqYTWKd zF8yIxQf_)TpA`;#%bZv$wV8)?#s!egRxKmUMK^m7FMs7=bV(YUi@#MB5jc)qdsEeC zJFtK0fXK}NPFY5_<+vj4j#KW^Z{|$e@p0Ivrz`dZ9833Y41-bs2DBdY5?&VXUywEP zSHA0LH2r{skOOvP1I<2h{wnJNziaz9IR5VYEjy2;;F96*L&L{24TIJV-*ONSmpaIm zDb9qs*fC!;9W^Bf9(p*_c?`$wv}Wh7(v}0ipM4<ES~m$Fx6k)hHnhB(cZF6pHj<^@ z9(tC$c9D@+hsa8-K=4*nMoDuIYE}{hUD}26-{kotZg=d&iqYwgdwMU>$;Vm0Rs!R& zEzXzD3hrl@{Djb2yh^R>tWG$oI^}D;eZ#u*5?eSX0KNlSiR*c|ce(e?T#8!(Ga{$m zR+oN;9Zug(`RGd<kWK$W-jL}~a<BX>F=4Q18eau{gK?{j3wUCB&M4oDiaw3^ixNn9 z!dfIBmk=>V$3A;0E5@!)_SaQLf|bV0_MTvkwy!Dakrm7%96jK9@Vlke>Mhh2ttK=Z zcYflEy-d1qk)&HK8oa90s^VYwv^C8(;EBcZs=pcYcHc`RYrg#&WTdsZJUbk1B6`db z^432>R-2R{ltRskQN-;zxgGl9a&?60GTl5|7$;REkof*1R1q(%d|$G?H|Nr8&S-w1 zb~#5ODaHP=9-NkM{s-T<;P`yG=K^Im@%;m6IA`89WDzB?F<G!*sXo)%c`l-+%KX&j zhq@0sf$bw=qi>gV)>GC1HQw{_kZ{x+IG0JfeG&TgAD&E~2>(3+UC*|hDqvQ_!gzz$ zXQ8eIg#b&TOT!~tgS(=Jf^3B`4d(4s!4;-lL)ORfzZD<6ix%<B92u(njl@bjRgul% zz~P=akk~5}yWg|s%m+TnK?!Z-AJ*Ox;`kI!M6<}F<EIvp|CFCz-@;x(k3!3@tF4{W z=mV8kt*lbBk=26xJQwGxGuW@YHlP+<3c_Qka}5yY<-cr;iuxgebK|7;N4kY>7;^L! zJ^Yh{E+cZfThFBE)sQGtb3s@B;}DO$>AG7(G$po4?N}zR5Ul@K4w+?>A=u2d_z5Sp zHyGVz833>kH<L7Y5SpmTfkT&vY-OPN>clTyN7}MSq7~x7wLEYdFs@sy5_KsS;!d?v z4w~2W`Y2*yE(nJ6Lj0+YbA;ghGQ)_QwFU|m?UygCdq{m=y6Q837Waot01u8Hy-y?> zO@%p(x`kyaf{At9@Qdwi;!x=cFY8|>f<)?Hc)T$#x6!oAI>@pNBT%=p7=2z3sTo(J zw&<bIf$4s*C0HD}*bi%$BZ8T4J?DOy<KGySgbOl$|2~3W7A{%&PhpStY@0(84?~^i z5k^Z{WApPOF#WrvebGhL%Sw<}`VP9!&)V`g!~PjxM$7C|v3a-NL|ql%z+%w?@qm2k zbXAk)8xvSu<1lr6Gq`@1^Bd?#4*0A2nUu2m*3LE-hNJ6L!xheZ_T9W79swC7FgX+6 zM;IX7o#o2HD_C8jQw`@Pn%pNQ2XvgZ(lusI?t`Ff+;orp#r!#2NawodW~wVXpg0h+ z^ynh+ZfZ>cn#=bWaxgQ81XMHa<6@C!y5PsK!8cjQYK%VaFUQ#?Q*J-qI!@6;7a?C( zHN`*UjT`114e30a#7er0z>|I(V8Ki|+!0mTWFqxZ6G26y*a{N^*}iX@(bALLcRm%o zE*IBpoNpeuMmSs^PcvCEjjGm_Cx>rJD#N|Zp$%n8@7XcNdK{|b)&tvVzRPTp;|J!X z+pbE8ByyYBL&q6#@a4`tsz^mr61Ng_=(FY+B3FZLcLfN{1e90gfB^!gXlhyX^;=j4 zNu#ykk)5Foypi$dgMCwVNe8lkEuPo!>NyCFkmBO%*Sh00&V4ZWcWDG4Y6g9X$8d8{ zXLJ?t*BlgD9yGmbo!`#&;8}%fgyPvxIbtPFn8;46D~`$P;0^8#!A)a(3xGS}u^c4K z9Z<$aamCQlwacXB72=}Mc0S#5o6~5W!y?{(DHIho-OapFWippkgqR6xPTTk`O7rFE zV&m?NosuWO$Aj53Cg~@aVo$S~KdZkO<|E71p?02|(A<K;Y2!~rZ%`ab;~{8b0rj&K z{XC9k)>Cg|Ami3=^%?Zz`A{<p8gMpPO`@NZHh*5iuX6jV>uwI_r9bLDk+}9WPWR8o zk>{UFW{I}n$UCBpVAEY16_PgdVg4$DEvWBIo3|Mx$RBBSV}9_`OVec9Q7W*7V-xVc zYD}m%SuS1AAwSy>UywZd-XFr6=8rqNYDQ~NzKcR6dSmc_YBw^NQwe%4=YLDz2{XHq zbG?GLrictts8Ng$HlKOFGAL1Hq}{kPvo?JqwMn6??2!nZ#PzZhr`#ces(j*RbN(N& z>b@{^K-izjiQDc_^AD_VxiF^R%-2>!jSkub#)M?UJm1RhHtdfVE<kWcGrgf55B#V| z|C6Q64CxmP@VE!1UUkBrK<O+>zsS>jI5#<bv|+@5N8H*y#CtBX^#X6F^D2|*bh4LO zt8QENz}cICGC)1m|BpBiYREj<&6MDVj=wE+W`RkC77toYO_o87?;s%UNbxyJ3-G!P z>)cX#VfGL8)XbhD&7N)!Z>1*;n*nd^uiIz*{JbS&!y{@dO~-jwrrUHM<ez0p)Y!rL z{MfpEpl=n8xg9B_W19^LU8iWTClZ<1hXh#L5{%2ZrtjzN+xvDZ<sUfCRR$~^g$b1y zdT|;DneSk%wJ~}-bS`;*yOuw^lWT4R$x7qw>e92wN>%ULxhp<3&}1^maeh(yZMK}I zVDOTpI6-9<CPfE<?r?<xTLQQonCXm`ex2n+zO`Pw>UGN`8uav6e{kQE$(x@``jK`1 z%vrD5R*!1q{Re!vFP77?E8rT3)9;yIXoW7|niBst($yTimES!j%6whb%mADLr{{(P z{@EVyzdkQEWR}R4<PMr3ieRy$I56yyJ*cP91*hFTY|G*G|71A{b50HHW_0_T09^Vl z9<$^(00JBTOWiRh*!HLYY<!->mgX2^Bt0gbK@{u$^}>!63|#R7n<{)BFAn*MRU)l6 znd>rprEo_s>-OYdc{2ow@<%FQzi}!=z#i^`QoKi=kdwT3Nof#(Es9PIr1&Ze$w#nk z(6WF<!~nm`w-z90VzLduF;hg#{_>Gw@+5a?>WP^|`qsB8RxkOg;GO$Sg62@Uli@vO zE~S<Ow%sFL^35+I<olrFtz3ORH$6Y#6|T>bsSzRON)_8qn|kqgbdvY>DXzDdq?1M; zv~-a4+Lm~jPVYopAN0=yl!;s0#UB7kEVOA_c#Yy|Qh7yxsvDa@Cyq2@P6vQ`bk);w zHYM0=>KDVx)Z!jc@C2lG|BcxGJH|^xE~VEj@T84&#is0=I9cLfMYeH=G~;>$8s<X1 zB#yW+0#fN2KYO;<Z!RNOKgj`(jzk$OCa(J~2z4uOkhHdVhA+=R%dwN1iu8cXUM^;2 zWHe7rO^J%uIq~H)guQwg^Rc@!!qRAHh<&J<H<Z5jw7D&(h1JF=rO(lq@5prM^zrm5 zdqudVg8<UjD3nsECYovd;gH~q5kb<_=Tl|nCZ?thhfQ0oY;4fhR-0FcY}Y)(!cRnm z5dqrS#e=HcW}}$RxCpMCt;h(j_LCTCLRnJbes+&R!7mIp@f}Qi>+kHR*i>dihVAcC z0|lNFLK*!ccuFbmNlzE-NeWvQ#poSioTK5s?__R|93L_X0{3<hKY_4Ono6U`lBOD{ zweE5a>c4J-s2K*BteuOwI^b|fDCD~ER=a}&`$Q1Dj<oM;fNV8JTEi5@5-+>8<#PpF z;naj_B2HY9hs2MR?Iqy`xBf3|nb>AuOQb3N;icm0@A?(!_YOt6H4EY#P6MbDCt-ZW z(tw!vR>W8L#oh2{hf0>sPL(lK<Y&}w`Nja(6R|BC@D&WaT-;ERcd6T|(V9p5)jJEx zJehO(c<7$R;0uR>gO@Etb1&bQ=F(&#Kez|o%d+Uitdjs-KYu^VkfZqA3VRk5(MIgi z42UqZke+{R|0O8o=@C$Y!&Nq2p)1u2?4KDBWAX^ii->K%e-m%wOP1f~`^|afq???> z8g$&=X+KLbKEiyC0ui-|YD2uAu&H1mNDWDlOegV63wg(@74SgIj5MJ?6s2l^yCVL1 zwPYs1ZDUOSA~tkpI3EutMk7b$RF%#9qnm`|POV-+cqnbbTKXPI;F@2jVlu@a5}8i4 zi6nn0?a531tDuif=0<CY#k27MTS%*ss|kYAn111v^&<DDK~(!6pLD!hHqrCrm@tV? z)0g9;;FRWQJ7H;4^ds>v4snD%{0>9aOSeTrag@^QTyX}w&xpJNtW~$d%QbSHO|(ZO z%`?SEe*jJL3sEH%eXZSe#ZL;Fcxapvx6l0Qb&0bf`TPfyVIAhEb@Q`rX@b__u7BlH z>uSY-D`(&aKbP{qh4AXiq3=yjb;YI&A>>;pRO3-_;_$Lw{i9@-o7%XvN5<WF;~g%= zo_aY9zfP`$?5j%dx=-fr{#q|OG9hf9MpqgId3y0nUEI~zQ}Hbn>@<66Y?Lqf{t`PX z3*#;!lrA|^UC5GI`GdIboyt#8Y+Yv6|9!cA<VZIa`r9V|(eevtQtGEG?rpY_jIwEn z86mKv0&+X}p%*W+>Wsd|qVphE>4l4nxDIk>1NFCko=}F)g5dp3&wZVmNBM`o!cWAg zem7c5JLDB-D~BxoITFfs1<ec{yo(;n?+jFqK}38d`XT<}hq%-OV%y;p%c;w+H|xEB zXc($*tbX0Ut`Hp34tx5QF8dx=@;S#$72Q@)QqsFNywa-sHv*EwiYtiKKytjh4K}mO zBbH#pyAZ_9MGI7gYdYQbdY(ZrYU1V~_eX?5^ROf~j4x?3>{~jOcgXiyYfz^stT|P9 z8=+qb%w~^Rmla;ve!DpK@D9;EFYrsj6I$ukiC>BNhd1*LspbjJeJ$G0E~~*t*wnd^ z5m%lbjiT_Qw~3E>{ON56dkCp;^gRLM>t7F`;XCum{8n_=Tfgn&PVQ|ZJE94j@Z09U zshQUKmGFp2Pwy4eH+TSAjKpaAOYU#<$FcE&T$5AAw9bey{pq%HYK?DY){r9d-z@M0 zqKD=BGNa$FiVC<0gIAH_VsL>jxd)ey8#=Tk9r~mwF;fzCWl}zEL1;Dy1bwhx^S#JO zvbH8$R!wptGVp=ZHvP#0Tp;-;k&a(O;BVsE_L#l*z~$4}YS7>9Oap(s*)2XA0A@B5 z(sBBYiMX``lSL>tJ0$fPPuv~9{vS%4tI!hb9dvdT8GftygO}V#nfNo9g60pbZXluF zu!mHU;p}aBml5jjKBdkmuM23fByGCnW~x^ERl1@HBYa5wubzKE+8kIEdGo^LbCnQ% zWVC~tgmTW<v%aZ+xnJ3Zd!LJEwiwrxa|h)ZmAh6uv_LOMGD^KTQay@<E6kmmveFR? z(Z>Q)*G0c_zrCIEjk1(KlYuJvI=59f-U}3=KwduH?A|yX$ax`C;ryDY-|Ef{CUYvc z{nK-izQWc)rY7Phq6~~}x)75`1|f!5@{<CUUEB5bE6NS_2lL9AwVEke=2az?G!~|w zWMPJ>^oKq&*RMsmq~xuuo~6juKT6*2I69UY7s{!PRF~9sz@VoT%NJ6H9zyl@B&NH+ zm<AP=OyQFSiU+k)mGz1Q7O}d!n3Po8`(NAI3wTRXb$fNb8*`Vg8>H_{rg^>euK-~& zqkrpghAjS&dbDl7K}K4ADu)mnRVQkxldafo%3lQ!;+|u`z`rXKeP-Q<gsz!TbjnsZ zVW{ZGt0kMq;(Jf|0$o7xp-X*v?f2pu5pOKYd3#bnZQgK)-91J&7uVh`%GnOM6hlyt z@;~>c)w)ztJ_TFMW>?<uKf}A!k8G0VyAxNxC`SA}D;rFDt)zMM$j$5>QS%mxnx^%2 zyCz^+RH%xqq_i3oFbpIIKsVUKAwe4~8zu^{yCzBz&H?{F#AD!;4V-`OQgEoIH&^mZ z=7)B_W}jODqdXmLg23x`HV1f7v$n%9rpGN3KVl+@OCD#BIjbp_5dIXAt0>0GlM`*7 zLz#g-=uc!jso5$r24Eyg8idz^OaEElF0O?gS(NjYhkW=c3`-|;csl7C#2i>Hx@{S+ zNXTGgI3&o<Y(pvjT!i1u_*Nu(ooL7IlJ4>~x<i0)ZiKpiUuj>g;^DiTdW#LIc50SN z7k;U9je~21BvLn_>J<an@gma}q=8C;|6XrSUf<o|cv;rdz8_?bYMYCK#m#c!YpHNa zkTF{)0l<$GIR_?w1lx3S3W;DIv_c?&{Gt?#SehkabvIWo@344|B@c_r+z+|aK~V?1 z&vS(PLSYW|vxEk<1^V{gsztqks~_X`xOy8-jNX=R8H+)yr~yRqdv439)B@#i)%qNb zcb${JvI5_|OAsPWNEXLe8MqKuhr#1Bz<gX9Qryymp2i>H#F<Wc0?$TfIn4VPZL)Q{ zRVN5x_#F?0@}%&^?xh0)t83Ylsw+5VoH?R*Ehl2_=Pd5?stOT}aF*bFgBExMi&=}% zRDBf4KFuA+y(kUPcj|NvI%{FmmM1Z}b3AG~X}SCN<n<u!$6>Lb)5|+5-vX?Ad25iA zEbM{c4uML*f~LwTcTmKEK<UNan0s!_s%f13_kdMSqVI;PKR6+>88N#X@uE~UySM2N z<&~q-cz8GB$-TYj6kZ@FIO!-;WkPP^M;fWSy?$N(&XMQAi^4?d;NB$)oW!z#R9bc? zQ8yNr^Y4-&C;X^o)gf`<^#|Zr#Ua$*f;<MY_g(V5ViW(}GgU0NDki&-`4zyR0n_4F zg|KGk0Wrlj)H97+Xcxc2F1Xwymd>G?=%y^jU}Z?tJRw0s;Y)J|X6N&WYnHWmvPOnf z-QkV!!FSqFaU3pJKElB3nQ?E27guxI3=tVq+Pu?ECD5y7wgtdN?qh<*rkr$c8deu% zb6%jRrDJ{|F{CGqVh>)W7}e6f|HL3RYrWvs=Gu*_w38`bP@TPJL6`G6LO!s|W4Q6q zM4Z0=o%~bdZWBbuVJ2X;8H^@NDHQ37Vg#!@Tffa-x+X)~(Xg9{Yfm5p%-HlLb56@< z4EKs0@IpsFm*={%^GF~@yhOwwMtt{Kb<{YUnW}ZvZ#zFt$A$<WQjlUq55#13{_*C9 zf<ziIK4!G{q$lj*&#2qheOn|Ddt52#*I9-3&m{*u*&IuO7#bMnk!v^oZG=1;ULi+Z zd2xUsIhXmA23VYI^-lxuhCY>=3v-X?`?*0%P&D_AHO?L4o1x7MY6WYG3p*61Q;8G2 z%4>e6Om7*DdA@$B6hmP~yHAD}U%^N}bLQiO&g7kSHV%Rx;~6nD43o+IM21x;5~e@N z7VKvyn7fj9k-f#x5&dsO4*8N292pd^$Zzf@n~{`(KQ36%c;jpn|LUTGE;Z6EUfqL~ z(@XHQdDi~DTk5Vw&Ce$xmE_x{ep)$s{KDRu(S17z->)qh6~eFCw-pn|%m(RAQWA05 z`U(A%)~B;)gX`hYAc}QUe>nj&LNiMNE{MNmqGF777=6N1J$*Q~h$IP9y7|}sOwx)D zt+=qat3^KcbEZ=w!@&NAjv)K*%XhNLWj4r;AJ2gtQID!vu3?G>@4s#*Z!=|u>{QKZ zcebn)+-)OM<s?a#<yTY6r0*1!VG%-RUK}oFW(k1VLIM;<(3<(aI+M&7>D+gOemv(- zJ}Gr+7X$ZxemeuF#MJ!gA@8EbYvqoH>(x`eoT^Q&6l6$0umr8!$D$rHYCXPZGGE~6 zD(}4GVX8u9NyJ9Vu<lMR`NP+6#8p>--0OWI7|)$<E@ka;gDy)*VN1KMV@q0Ln4-G$ z>~lM8vHL?HBb|NVzVw1VA{xvM-09EREi)Dp!pQE8%f<fPR5;8mLU>w-52?_PSDAUj zNu>6)hsj=hM+y{sxMm7les5~6ab~{HxK^0qf1bw;)I2;WX9U!D`r%GMHk+Zwd`3~u z8edyBa6k^x&LNxK-KrIrGX$Z3<Omf~6`NJW_9nEiWdsUC_SX$BHm>|`R>3UX!Nr4} zHaUYcZ#Lc<VF`TVjF&N@QKnZc;-vj4$ow%}WP4QSwWB}6d~!Ju>2bhhxC^)$w1R6! zp9T_4)<@+&+l!>W#x?F_-`tl@<WqIjN9nj6Wl6TV;6a>lA}Z_6_bdI87Xo}60#~Y! z$n};|V;h`Llz+VV!<{~TaofWj6nP(mA`5y`AtIhO@a~T94bv-SXWtPrJQp|J7dEYW z^(T);x6o$sl=b-05y6M*D+jjUY%S9Fj0mRRTMH-?-OQvM;;pNC2XaIPAJABJCO#MH z(99~(03JPv(CCaFd-~;reL@(^Ch1P~TYIDJ+^<fp*7b(zL}rjw(AE+ETve{n5FIk9 zbT}yD`)RsYSuNBfujwyK>K4|tE;qbajio-xc@R5YiI(b*{nJ6%l(<nT@q~@-AMWW1 zA+6q9x8lqD?{*0uJUm^q{3F=CF*INvMrJoPK?nHgH((SsUv=q4P!B)5!D$AsR$Q(x ze_Z}zw8%gh+WdIP$ZjbAMy#KH5ih{v+f$VlJ|SDuecM6d&!NtN^#gr(9DZNme3`u1 zx+|U9_UPsu?DB(raia~*;}qYpOi0pr6Gt!$UNYQY{tcu}7qZ>7{VIpR>^1dr$#QCA zLe`FLRNJC*79~Znhf_7d-{?923_v6oahm+C42`oO9%xws&`_xY2o-wEmarH^qiXa- zD_(u2XS*kqN>+>4oJ}*oCL<8BL3Z?<eVz7Ygx0CzIsfMjHIM;$_q+U~(C2b~!bNeQ z>0@ictMyCoYeByd`q#2}ayFCFfZ=-ul#K+f*zMt?%&ZyS696WDzHtTLBx`1urZQ3R z7v^=uv}6d#RdPDhJFMa}iI4o25jm*OCyDA<n2WmQgyAXb1*pBBY#+~VIdB?+$E*zT z4)K<Cqy&pe4Y^r_n15z050sTS4F9}p=|Ttn8Ur3rN+Pm=Tf1}Q5UC7+2A)+(dsy<> zpApmG0-S*S`wHhqgkLB`6#NI{T|o0uW-JfWqMf2wtHab5TLn(4Uf;>Jxr7a9{3Zo} zMUOwc7wZotbNlt&eT4f^*Q0yNC{mkeUzA_`!aF~K$Bo{fwE8ODjHbr%bL6(&_}QO7 z->&W0ClAwRia=j}8{I_Nz|Z*K4-sI-TbZbDmM!P7pf+%Gw%%;r(gPnWa?IY~zlGjI zPm6*4eMGKOuGJ`N8rhYPOx|DJaX~#}LVhvlQf?I1_1=MJU~&Uxs>vG{h;;urI^3ij z9HJMqRt@T^GdF$888=DubupNzogf(~wb<Mo+q<yO6;b9<v2OV!B5f4e^#Lz>68`u& z5Op_?oc+K%^UXX>y(rBRpS?%aVi-%c98ggW;CDWwHf*{0xyr#}iv!!vlaZIBY={g} zwUyl&F8@+PnoSoIW`j}rJ!dvuNA+Y~V*V-fYU!R{|HsmKhO_;@Z$ClpRn(}hM(tU9 zwn~*sRTZ^&YmeFzQCfSeQ6()}d#g=U?LBIf*qg*AB<_5F|NBXvB#%DFk<a^mo#*R1 z&zZUvjkjS}QngBL)X!Z&Gq}h2?fCgwrq{FaSIRmpv#ch}$Jn^{Ewh%g;J*7RdozRg zzc&|+B{p$${njpaIP-mBJeMu83N1FCk_df%ATy0z&`~w5p^9Uvy>pW(ncW4wz&{_e zRpqM0dkA3r&;gqOzh<;goL6p$FtBwrrPcpyFH$yh(M@VnpCjp>pUpJr?TwU7&)S6U z%o7}w>CM#Y+q7MbPZnY_)%awuVA}oadKKB5POtiDh2#fuN98VwL%sW&?CAT2+o`jL zznCj7m0z*MECnL)I7s(N_<j66Hc6x69SiX{B>^}3;y>SO1`C!*SXP~Hk8Cncsj*A6 zN=tkn>hDguD13Ew-y9mU1RKqMSEH9NoiUu+?j?#Fq1<dbjiAr+B)YmJvIksjf66TW zWR%WA=z^fLyWEaWM7DY=#of9zjhcn4TnzX(v0v((zB-jhgFRMNG>4RVQyYt<oA;s} zXSzxzc3q@qGAiSNgQ-O53c{PGpW44NN?a=%e5YyoprW8|WM29F))tHyxa)DJF~M$p zvO_7$!brNYvZjZ0cJz5`6k8iz8&Sw`@V^$qfH1-k`U-`!V!4kbD^|D1m7tq5kUH)} zrF2#J`yt|l^~l@Scu+lwEewB8$&yA#koC2Zx*D4{#UMwY!?zB;5iG@q3Ja&U<OS$I zVOLj0dHjtCRK2LQyLU0iJnJ+I;(sZ+`h9rBF=2X&NX9?j*y1|2>Vm_D`3a?6{L(}3 znN~M{K-cx1i2-~amC1KTrf!+G?W^Mb>ZNPqw1)Bg-8t`pxNir*?<YMi`S*}n0CM*4 z(+wyFp!<?GY2MUtB_Ho_3aDFdkgVjN^Pdfl-yN+mU)69^Q>6!5WbiZMboaP@H`z3i zJb1SMlSmJsiQjKI1t+i@>b<SEu_#zuR*I8pBbON4@EbMCcN+@($?o73T6yRn&ImF0 z_lE9$W?H~jgxtJfjr_=QQx?<o_IH%HFZR=Q%hP;|*!wMRL9h>qzQ>QttUb8tO)9Dg zr-xI0&4J79KM_U%gb>$nx7IaQ(X#t;{KXR|n(=D0vJWp4)@%%Hq7R_kX_*71y~Q=t z9tDp$UV8)-H;;b0Qkkjk!}uF0h~4D_Q*fOYtmx)Vg#P@*ZNa=zRANOQ2Rbl+GYf_s zYaH>?|FEz!(g!OGi@+)J)uwzO{Ju1~m+`v4U9ZP8d3$ygdUzC_qw)B=lp~RdkDMJk zrS<T5qR<NNM;==1fqnZ3Sf42YoTiJ(K1H!@=Z0t%tEr^kO_#|z<&L}L?qj*Q$3z}P zZ>m%@(Zl9r@i;}YHh9Me#ph%_b9gZU*>qof|7t=0M`%e5W}EUb2yE}5oc8mk9g+L- z7!%_<cT3eYp&|C_?Ykslqr*gq*UHWJ&;Lz>|BZwNl1q|(-E1o~qEda!y%`lzg8`cy zZ{`v1?i9c6f()?f51s>?+??;<7v(KOmoSqmxdpVtcwaq&wg`lIrBqqk2<p5Rm(<1O z0td%ahtgL#e2+U-25*k=SFzh8V{2>=9E+PC?(k{tlJZpf2$0`Cz+?1okFB#%K!v1> zM*q0ID3%dB;!`Ek=s-(`s?O&F5&EPee1aEgS;C)}{_+-&M)2`g&6w#k+gQf&cbtT5 zw-GLOn2rz_{u-yeq;d+#k_V#*<pO7_Grj?Hw&m_K-~UxstMe@>F>HuimDeE>OZIn| zLG3HwXdojx^<3#ipCT>)nM$9~+Bz!p2PB5Gp<#=#m$~{^;2Qb0!uP8^JShtnRb1-I zyoa8+Q{^N-$SCorm&8LM>{a5LfL6mXn+Gs-!0`j!<(-c+VcJdMchQEH>qJ#U<n&RN zt9-oZtZjCEf(9?BQHN8iFD)ntdFuZ0XyVaI;UN^>9Ej~777RIsfm;<@I6mHvPFXeW z66wuUynU;P0ja#9C%%w;prxZ3&tyOG3GfBDD0svEHgnMkn5ilaz~D1y-+7V~zii*0 zkuCu){5S%Sm{$m0lb>8UhUAz6Pxxz<K3&YMj(r$uy!RF{DI-;Ff&7pXwcp2VrRG<H zLW()UrQ)oZ)R14D%>Az#Vp*Xz<wPo9oC>ufoFjYBVvi%O^@9%wpnF2?YuElU(Q4b( z;7vgfPQd7|_R5OfKOb)<h?i3-&hxE-8?Xl0U6t7k7jvquf1dO{HO@dN12wLpC|=b2 z501^5G7p?)WjdgQ(h|T=gVY<Pgi^*T4Q@^Iu7F+Jt-Oi$4RgPjcU%u_oxqaCrIasc z%GoUTE5!~66Hrq~q`h_tKcdb7QNLi<a<O~PtvH)S1$BYLEn4>cCJL-ptZ8gMEs>J6 z8B2mn$=is2%D;yHdG=<AWFF8ls91qa`YzM6=Nz2+GbB=!`koxYtB>+~eg=1D<v@zX z^>ChXoh9XG|LS685QSrZ=BHR`PLK5Ny<93QY?6E>(`9vnF@YG6y{?Rb=k=)RSqHxZ zoEQ-rwusEZ9|CGiGm&TBWK_&Bg0Zu2*=1GQ>>WA14-DSl)*lbV74hR71#t`XUY0Cs zrgA2Z>vw3&B^)V5f_2M)hPaDt!_`(C!)(IpsGxS{-7WZ<c_~lCL%rh`q@I+2>gS`! zZ{Y@i1Egi3x0uVf7pXVv0GmYtDV1(krh>Z}F@8&nYJJmKt$WrgXD1!^x7uDQEvz;k zszDr)o%CHpS2Tn$+a!&*pk88@t{0B3nuHzT|0zEI`#75L4GVJ2`c5sKtU(NKO561c zB*^>99K02ZJ0zz5JY9cSxF~&4yeB&UgN)S5y#eEp^AF<0lByq6P#Px-NYOl_+=x%{ z9;L%Z=ma`;)V9*807G&4@Wz!z;AQyj?!1*n8`JrXrfSHPBpR|V>O-SRl85qPY^6uQ z_|>=N4ODeswd`C!i8pPbQKBGaPL=*x=xZ!`V`FI@<7{9#HP&7$GH!_to~X!mr@;{D zC5aM6e-ujz9cK;cBSy<}R#As&t$9=mt?1}$XVWg-TVhh7X+3D$S0RB>XS6HgLv*jV zH!-MoYR;vj@wQ3vzrT&GPSnv<Q9a`iT>s>nIYmO`uq1Z}%c?&1KC}TGr^XXsJx(Bd zEiN?}dH-+luK4p>Q}#<S8F1ExM)HcXQ!)(&X7nsqsv`C||M}RZ<^9}m(!WbT%NGbO zD3w(`*kFz<8CaN3coM7HjM1<Nd>V_PlIlC;u$v20-jyn{x>og8-5hBjl=f&Uoj<c3 zVq)wDDBrdgWy{`hU{Yi^-Yen9$K6u#UzhyW-p1FyZVJd|stRP>D<c)d<@m3IR<1+v z5+9ByAJ8p1eW}}Vxv>M`nUq+FNAh=N+y|g_y<6okKhn)<P+QwTLi%?$kTsfpKn>(V zHlO1;@hLEv13&CR55+d9o}UW_$B-<^=`~77Hn4zZd&u0fRxLn{?+9Bxrc)nEE)6gq z@whUBt`dTz_XL#Y{qH?!efQp2EGUDxYH}ljTmwsX|D&vcMkB$ILmp_#TDwLj!BfGY zgE8@oK)D~6^Zeupyn+&buY7;B-r%2ql`uWP(t~CS<813XI_Tgs!vjUu17*J7U*6Bq z-xjHF=>I03no@}MdfWaT6EtcalQ_{@TFuRe?+3Yhqrw2(4Lo?dgAoGn1X_SOxa*Xk zkiQg{${y?teifVaxv)^(|A&e|8z>TjOad%wv(&bXDy`#pN0bMcsS|PUMAEHYju!;g z?)-9<26i%_b7@<XBpOq1ayE^hK54zrav+xKE%XHTAZF;$M(fmYk#^Z-=<xXo=gIn9 z9X4Dq@u>2_6J!v)5Ki+j?Fs%JGInyl^LZc-rt{bEvEAB7S7uHUttJAu+zlzt`}Rq9 zetjWsdfXlSvTVSZL`CE^@!`<_ov32JA$ARb=Nl5-_+K$Xl#rc$-Hf5{IyIc_Wivb) zfl^F@HtE}<1a=mKu<N?#(9P%9J&=r|F+0|(dNSGx=mE<zw`z<}nnZP6AXPvFUpll+ zq?Smex+{PlaaXNz7xUuZ<hU>_F8yk0fwS#CgmC)MJP>UN+z)(7gz#8S6$c-$2++_9 ze7FFb>D}#MGy}A<v<)wGi0FJsY$It>yD|f2yROhnH&Ps2o8~o@cjf)+FSPBXG)b%{ z4SQsHq1Ca~$|_IhdP3{cLAg^7)Rym~SdTl0CAPC-KguVIKu3>REd@r$u7+m$oy?KT zlmgI$hxX)b8|-fY{X=H)9?=l}_Kqr;q^^$2s{L_EgIaqoizn2<otMNKbS0r{u{DM@ zr>>H_Hd8;<s{wMGCY|V4C2kae!BHdLDWa=)qG?-UJ|u(7*cd^(<u?dhqSk@PXdHDF zEK?`+UTb92mwei#PHqqJD4Mq3)><z3W~dH?1Ls`Vj%iQ}J3!$eJNdmU^G-c9<|kqy z$LWfL4J&J$Lx)Xh;g`2Rg0?#;I)sFE%C+>ulIxebiXGnx9A&3HZHsBLV2(RfTni%i zoH6xx{KVID3AgzZ*|}~{M6MqA!;P(oARz;|@f3d^T(t{Y?s`>`eq&1a3Yc}~RjuuM zFmt(3XX88%X{V)<j@Iz|5dcmY{mX8BdFYf|lNqSP37r-CHJ!uCIbgZzhWiM_IcvBi z;2!HPE#cO`ZJ4ID$w_itOzDg1)pqZ7KVDN$ieJJUWt4dL$6!ABn0?&4e)=OfHWtP| z`9AdR2Vlrx?&+`l_|#x}>Ujc<mJBm_4BWX`V6LCjL09RkQwX;R)~02vsXM<yAbN-* ziAMUnl{>5?Qa+DTYdLW3DR~@K(0S-w4MbLn^erYUr`SSf=;<eX6<qq7PX?82g;%fm z)J*()gntx$o@4vL+xBm!^YO`udwrH9FU9Ng>$)PHxmqkiOwf>}%a*Uv*vNRVx39ni z>W0^`U*8!Z)L*m1!#}42CcIMK)w!4k+lCbde5~q{wn&5&!)fpIRagzgOcBlvUs;(r z&+PjB0}dNueRerL9Dhc^uJw;EvKd%LkuPwN-Z9;G4p64)7f+huJD7jKMMY1`Jn28N zojT>16FsefHgiFB^LNmlQ;)3R`iu(B0vJ%^TQ5je8<8nk)s-n2r`C9Wbi}lBGlScN zJ+<N+SyR*c1~=~Dy?Skm@OM-g*D%7oe+TFVe;7F{N#&36OM$W7zg3yu*JC~}z_M=u zJ_vziNa<-L<Vx0Ag-Y^2timh@^g>nmCtDxJYnNOf6jdGlIFL8={YFA1Mf%@yTVFF0 zI701=_cS$#i+4<0L>Y>0nC0+N)ak<~noXBpz5r_)oNQmKYU_13HKmc#E6~)DTn<aK zM;lX?$wcUTTSbRAoP7P$%xICU8mh|(SHh1hc4*6s_F=DCpSBCAzlyp1_jV>Q2_zJ6 zH*=~H%s^~TPp2Zof=yOvC05@MX*QslIiVNiG~P*UCTfFphfh7r=By&L9;>R+)h(Zl z6EC;|J*wDWtfJa{>TIIKr4L^>{QOWyVz3Z%a%@FGVF(vx{Hk+4>X~M={3bzySXRcm zQB3XJeM90>`$l_xP~vNRLL80(w=t1bc{^n}+v>Ad;dUof0(;sMz`AZ0thFkZsq$f^ zWfz}2dRDPUyMKkv{i4zvM)k&o-|;4z<-(zdh+&UUkCAjh-JiXvLT1yC{d<LUJ<~x! zfZAO0+Cb39kL`bYdd5^mfxymJ<|T?OJO!=5Ujqb=KV>T#631*c@;dYWehv^4T78Yg zehjn?vxM*Y&&}E<W0yCAUJY%?TPav(S``WZ!fpazihr!OJpYGq9`TQfwa;(^ypDCg z4cxi_@6@^}e7*U-N1R->^?T{NBWu~VgqYjHh&T1Gb20VTC+@$wKq+lIFBAxhuBS4F z4{vg%-5t~<v*w@v#a7&}NcejqWoA5Q$O*C92p#AjDFyMqgTP!J<RF#PX19y{#9PhB z7}3nBmQ(+epeOCg1xqKdb&1i3P`|mraH~g?zG?<9Cm`W3vr}2VuBKeEWy6{hO6|38 zk3?C8=cU>j*l%|zr^WoZ-nu_bPGHq4*ywlY@$$D0Q54%Dx2{}BvfER03p!;zwXcWQ ztmCuH=gx3C2BT;(m-)%xSj}PjU0LN!sQV=R1)!-$qGdtfQ)1zf#3pi6i{ECcNI+L% zoZ(@G$hm2EYek0fo6GVliIP2qpCzre4<$!qU7tLg`W!Z9ZJ9xg&MpYKA_LZ>S6ev8 z9SVN800`6|?c9$fQvl3-nj$ImM9ZS|0h0N_-?ofy_9z7K3a_-freG2lCQ#^6vfpK5 zl<J|opk|>)Duc~D;E(f*-#cJpzJ79`p!i*72zrxeEgp>x!kpDe;6^}1v|k{W2_#ai zg5eW9U$*6`OIpN-WGkK(?vb#p^ZeW-Zu-a@^t_ETm-Y02+OD@wpM*Nwx_7ehdwfvC zOGEfZCyutkztoCa>a-!FJwBRUXr}C!KrQgemY}wLp__iZ_bfg9MI3|&NLLuWC!@h` zPkBg>eq-WDzOSolY-(E*cd2ojPvIfzGo{w*-0Vc(1-6A>klx^|z^9%2PRkaY0!0}R z@8Qc`CykId`zN`d=H@__SbGA*Xh2sBJM$4G5N&Y?Vm7qr{*lYy^~9c-IzgkwhQK;k z0%*@5-EoaLDdQ#EVnIvAys*CSR!!|1WMxaADH;Du=NkU}+je?~_p4AfLPRM+<V(o9 z%eQ6KdpVnw5*spx==18XD0we&uI5KAN;u_FUK=QkE`{)Bvg=0U+&k&p9~G|Uvgw}E z{*#k83_5fw?pqs~#VTe{`J68cbtAKM4bny4LuYm0ltZJ92$q!>zL6x*do%VVTCF7_ z!qm(y0{3Vj<R~y|6ol&zuDUu#wclRPSZ}0nkW{J=<Ng}A)om$x+LX2TDJ&E1MSO>p zA>ybtE|KPE`7ShA!$gO4Q~iB6JxW*5-UC6YvOUU!!0Xf<xqmlL9A=oZ=6$$Yg#cY= z-AR`hV`u>*GIiJ&=%K<``*!SAG?mfJ)=|`3IHM`s%Q>vusugvBu}?QrQS}l6J#^PQ zkKOhc+mQVCg*pyJkt7|Ly7%<FOx!owS<rvXYF;Y*jm{V;S6kyzH|nbC1hdgPH0sOB zp;>s`I0a7(cuiGRL-=osfX7btvsqlmRr>Ffc8tb}LXCeY9YwVn_A2iOxVcMs<9maw zmu_PC3Fb@YgLc_o<fb2k&t)m~GAjIT>mp)FU$5#qwdnVQspBh+t<(p*Am*3lZ-1Dn z&G1346TJRB%DwXw6Qh6dmSmYpR7Q|Z%F!3wjy!Jrafej5_xv~q=|ZS1Jb1m!GTo9} zv^s%&<HknHp0(;GK$(e$&a>Ul8r&$wtc<NHyp??yB<$)_%fa^V^P$dY&N+!(S}N=t z-`n?g0U1=-_ttp6>eQ?q{&i>ZpIw$h+t;SI&PP86AVbIe^XHT;F>!CuB{%9$r}a6{ zY!WgG9P;&-e4DZBfDZ<<jn?k!uI-i#$5+o|D~&q*e{2-{sxi#_D$<(WA41`S*(w8S z9HFN%dnAx_{{&R*$@WfAXL#H!O&p8#N4O6L$>zg!6Byvw43_h1f8^jv6BZ5h1chcW z-lqoJh5wru>f2><z!+|;gOl-Xgzpmn;k4#1y5mU|0hT1Q*_2p}d?Trd+**mykc<7| zV*|{$J>h)?h<j$6ah``srpJvutsCV;I3?ghW4@nE-^cmo-~VW!KCX-;O2W;h2Q6S5 zBzzU@02Q%9;AUhwEOULH24>A)b?ehwh;&%anw9@$F9sQ^$@@h0mP`h>sDNb5r|LR3 zSmQ+3cz-JLSQEK+LD#k!2IIp1yGbMHbVY!2fh3t7x%sOt2)ax0E0^P-<;^V2I>XI5 z%AGTpBXYa?nWoz3FRYc=Z?_B~n4F^=m?Fi3E<7|aNB~V;7^o!Jo2Fc?B+dNq@7vO% z7=i9C@LLoct*A=!_U*kFG@aJX#kLwVOvA%=8Yd4djKU-zibx)=&lro=?NZz=&Ur2R zj`V<Z{?fzLdNV_(#L|(126Em|2^J@9<y(G_h{`4MYV#+QgUYYBtuE2*nw-`?gr4o) zZWa$Kt%y4odR)&Sp&<RwYKG#S1A8!tdkA$!(DQ@~Wk5)xT^XQ|rCOiZn#n)F1))^6 zCGM1nJsb|D#Rmdc#chd7Ki8)uC8yvE3}#|koE)YWBK#_h?>*hQc&gwNly#(X=7J5J z<IyURx;6fcEEzEINH1iT8_+v&{8mg{Hb~yl;LR*Izq(OYJ-W;2P?+G;S}}@J!l4*E zA(;XPBS+&u6%+NrT#XT@JbuYJa&t?ofF|tbpXRvQ1<CiZmiu+LS9xY&jH|X}WP92J zXc?%j0A=yozJy>vu+nNXWT8((tdaBmAlG8Og`2ukhVnBdYj07)`YrKiR^V>8DMh7U zLE|7Zbuau&>1-?Tbn^3Dn{Y=n1C8P|oRa834kfq=a5o;+(R5MrpBtOXnQLpt+V=*1 zIk1#>$o+a#8vWkVA*B9=fN0UcR!c6^__;luQodi7phaDjnH%Wwky00M5@!KOsOa$f z0!-bLizy<u_QT{fjrTUFHsq2mg;WNHz8pZwcu>+OjFw+7g;-90rZZJIE)L2qbFg)f z36<sdJ@H4r$~cX9f;?(6@&dg=Sbwd_Q+o$k<CNN8`xA4NO(s7L9NnN7f4WheA$y(r zQ@KK<>mDm~e)A$PtwC(s*!k*+=cG+$UcqU0ChUandE7xa$|3B^>ex^;pW_xs?UnmR z;B_+Dm<m=eYf<}>s7t^%0qW3$V8)+c0togFS@@__p=5aQjlv}KP*NkRi0@P<Y>nR# zVzD?)<~v0H@)dZvZhp@%$z$>5o$G<M??Mtok#C#qf8OebzlWQ+=lrk~x5^C2n~>Gt z1|1#6(G!$_>PXw_a{ccM0L(3~nl=1h6GN}L%Da?AA^dQq{|^@7xrAm?H(Rx5YIKxB znYy3JcJzZn)ed|WV%1DKD`KdW_-a4xycxzSX9(ztB1c;!AIR*Ezvggo5Yh$K$>#o+ zN=*i6vH0jxdtQWni7*IO0ycV7uZsc;S)>t~A%3IPrH4xqD0GryYh2^fb@~NwoE7^L zyD~W<G~xD$2y$x`dODR@89p3(>pzN@+?Ng_VTcP6^Aqg&b5GiO&abU%V9qY4R_(@n z=)f<4OCFd8ope-U7>neS>olDdbS}T1I5)j*&*|j_?VWLcyo_PTdMD1{vO~&cpHNHE zFwS4;T3-EIRU(sy>N=$Y?TueLg``Wk8-Ew&p7b(vu)@oL+rT%`EcF8F9Z_F2;nK?w zuNCya^}v985B1;qEep_YNdRqOgy}Ma$c%tj^8?y#Pv-IxiAJ=o?6jzfkiC%U6wGCZ z0%A?3ioq<xA8~D{N@3m$x?~J!2$l;}4Z-|6Qpy*w`GDH)2eE$)J=(sNz`+taa{XJC zu6RVSyYs9Sf%oz*X7}1?c4x*D^Cvs5$7k}g`<VCVMu9!c;Pkb9Le;IMVW4%VZYwd- zI1$-+7wZH1O>ow~m(J;>bQM27gs?k9KfJIqsG(iuJ4<|}9_aVajlmH@$A7VdOSXhb zmx5|<OFDgd2!~?H;W-YYqV7GUwN#WgZoCxns3$HreJZN^|454NoH3QubI!Ku?UWea zjv*Uc7q)E_DLec><gSlm+aX%f;QDKx-twA4OeE8|)<nFGbL4_<-9%zPbKz!9q^SpP zihXRMH-zU7Ln8s=qr$wg{O;eMo3f6R6}a*AWVv^99710|*t&X9tbZHlc!uPMQ2cdw zdQ?3m>Q{srPZrqvDzE_c<q6FDsgh@^<|QBqj@I!#ggkW^^>=`Jn87|0=Y8Xzc6%~V z=L_Bq3%9_uG)p=gs{EqLb&fTx`5^$C?z)u~(A_RyC-_zoTv3FEk8x8EGJ4sSIJ~uw zY_y&p{f#}?p#O5dJ`cOR=f`C>hb@yO)?>%MmX*i_u_BON4^?Y>CQTiR?d`yhzp>?Y zm_P_@@N?RGLFziC;-cM%uR_72poG+T96wa&Zx6JCxl%}&KIm?rg3C5?7-H*K?N3iS zFXJu^9R1Nv{bJeQkS*<DELMkN5?7YOGVi)IR%PaJ=F*b0(_vYQ^=_N%Ipa|P);5#W zxtSkHR~mk9f3aL02&>yROT+Xw#}hf;mX)!-`DvhPWZT8`snG%B%aIWwn^ztLA5n&F zvJ<Xdm~+;k&6AhZMAMXHm=~T9Zi}Tb()~pJ-B*EZvQ+1E5eeDUB+&97z`VN>Q@nf3 ztk-^%B&c9|L+`3k!-Mx5gq5G=GJ!zbl+qo+nQ0G3VnMpBZ+XdE)81oiS(YsWiaBxx zNc?oemj#Al*Y_U;oA0hh*Qhe9AK5Au`c)Dh+JTD(0#;d}_+6$nz)V|RTV-VD$-<_E z*1a_v_Lr#U71tz<&1bh%QqRgYUGU*~GTS!BeE=@j|M^!DKm;O{v9e6^sGA5!y_PYE zL`{tiuw(Ih{8nwOtGH6ri!xHZ-(Ljw&s6-Zi{FJjPZn%erJiGy^0uykNi;^XtoZ}V zX!-SorF)K$<1nCZL>zaJbkN%zK*c84=-*FP#l=C?>zLf$Zkpx!y~@DzT{HCq;|8lo zpGALTu{#X7$ZP#ppL6#l&V#_|YihQZJru+T>DKZ0h8M#f!k{0jdQCOtj$4lhaeUgA z&E1d*xbPym{*B3`Ky;e)=>U&}!tM{cUU578(mBh-S?GmiYq$N1-p}gE<aolJBA`7< zuogeYNP8@ofrLr#tpgOX9#*=UPevLOjv6YLU{c!!tV|)xcOV0U%i#FYV})go1TX4K zK|6j4+~Fhm%|D@#ppD5yarQ{H(1R|2eU&@eG#-#Wf3?WcT=?@o+BXOb>Yi+_>F)AX zX>|Vy)1fiyBOTNEQ#p-Op2Vj}ViXhGxg}w`{4jCVkmWg^Yfd9vE)Nz*bA2~?AxqTS zM{1%?m*gQK!FQ)%lrAytsg|FI^!Q$ri4(%n58O$-*_Oucn=O`B0QJKvvZHe`u@kGd zLGYbG{s$qJhnPmkcH>0iDaw7D1JnzzXTy>_o=T=X>F;9$I1f7^FNYMoU;X{OH4?P& zLRy`ETVd`_Ep$maFXP_1xZf9WlcX?-(kY^S(+3it6T^PI(0rb*v`%tDP$r;qWoF1x zO8L(~<#+i0Yxml^1&SeI(#TfhS^AT<rg1ylabqjodqUf}gO%>4-7VHpq^0MrJpupB z8jXjY{w<aC=3t)d`9IFD7&$->!teN7yuulMIwtvi;mOaRHziNmd}eefqdiJ|vDen8 z{&C`#e?Ny66+`N`<}shD9!R%&R9{qJ&8@2&4kb;8y6s`tMh%VSlszV!bxIjW*)sD_ z9?h1%o3o1k>iv)c(9{phzUd@hr(w-pz|wjCi|=n$fH3T}OwIClt}w{A<U9h-e|fT4 z><Fzy>~fW}zK>ap={PC??47i(`nKPln?Me(4Q!q>qz7i#Dfd2t6dV*dpFR{l!Nz#B z@z9#HK)78FD*D~QYr#f8n55fD%dJM_01PPqaowPtvZ(wR9-r&<J5iN{6=$eP#mgSw zAACp);`-RfxysLuN6h-2k}L#Lsa`^Yq~3Kda%}w|3~49QqvyZS(JQDu{d4>-kSO#F zbEVcqOE@o}Bj%f)lu)!^TkIquH@1C-jz33>3X~DgNB_W2{bhh(#**c_4<JL7Dv>`g z-%0iLrU2IRW!#b0m&s%GtK@$tp8g0)cKF66j1Sr-!8_C=AC|eo<)bf_wudPiXo4Eo z?X6$4|L=cqpR_c_iPH06GxrN(U4NAfNjz+C-7LXb_m|rnbX+I`nwm-5C5Iu#ZEb}d znU<|1I5s0w{TZA#D0G)nOz`i8{B<1tn6SuC?U))O5lP3oxJJPsOO<v?f4Z3b<)!W} zB~s<TvM|EjE#DES{U~^~6dl<h5_<a;P=AYCKijdn+*ZqMR|_V?b!Vxm9cOg>xb?dY zFID@b0*bo6<Op%z+qJ^bsGpu}Q;cU=pHG2CB0zx3Bi#go2JbjY30sERlz@EAN>I(0 ze@-k(M0#N_h_XBQ3-d3cfoSO{#4?*liYRG7qNftcSlF7`9nbDezUjU!$6p40uZ}O$ zGRMJLnKr79uV`u?ym?~%85YvR7@G9xO;p%|7lE4NkTHHmiTh1$S35z1H*~51ON6Ez zl^7lzH3_aH81cy!^h}rj7Fl{zYMIfX;c125D<xd!(+`YX5r-)UuU#=MWBoxPTSE^# zA07K3V$s_9YRV@&8OtRo%QNs5U4V3ZAND&Uc0^MZO(dW|)5-yc(y+x%Ujdi{FKVg2 zt@AF>Vq-){p!Z8rPgNss_e**!Rn9;v>83W>mtD}iR|fSd-^V6N3857=ROEsWf=9M< zca?Ce7fL_DFkFsw$cC-}#&-uP3kcz0T7x@$x@AO~iQ3$;ZXa0t8*{f*HzGv~yv4ru z2ncs#dSCXCov}kK^2l7?{;ty5fzt2f00CK9b3F<)>*gfWgV81GJ|&N95m_JF`|9!5 zHh%Moej6VT>PkT6BrjtS*g%e!Q>6tBwYXUv!QLGIh%9iwdAhLDd!{?~X-}zCRW0(^ z7}$i#niS&~d#JsfrvSJ3fP4O-tlA}%`E+q`R(7oDtGC}7exkuf5(9phx4In2t!;tF zUV(}si28MkrCzz3H<j&n=AKjeABe_e8w%Ow=PNj0nzq!<ZNDRUy3j6nr^NraZbraP zO|`y4T*gxpI5|7u&<#2H3+7IsXDsO>yepSZz6(0NJKs9s|BmD!c(fAzr^GMaeN;GJ z+9;pBWjOJsr?vv2JCK{cMYy(mQMQIGxqRbW6E~uHIMbzV5C|`;vvQbCEsOTpBqQOc z#T7WT^E$7lvoxHb+}5fvmjb$H2Ge_bJd6g7qiBjzqVKUO*aCo?A-prHA?SvIEVYU3 zQXl!?IWo30>a`=lKN*})xX_QtkV?O1dC&}kNR{DjY~6mOM#_bS{_&+DE`Hd^*5o?w zG9pU`mObrCti#wQ@18>Y6MMTAAJ1o#7cD`ULJ=Nq;doHkV5cgU{AFfiPaw};p?N9s zIX+zu-(V!${&VQEvyU)}yk!97`dseqskDa-79vw{kL11he`@<1I&6&b<?y}ND>fwK z|KXk|UQT%7y@?GtZ)=?H!n{RU6Womi!tp9$y3ERa2=7_9sDnx>J~}Y{d@D;<%|}E# zb#%6#EG<weW=KRz*Q7Uk%R!5%<DsL;(VH60)6Bb?0;XG3%dlYNGDSxON)v=fPC^*- zSo6e>T+k4Hj$<5UV`^}|Xyf_zBcWLm-P@x_{+3u`SBo}mPGT-p`nJCb%v!kIi8N;2 zW!`VWC0?Fxtsu$ImzsjaU6HrfDDVe1Ra{T6fLc3yr?^EUUl478P*7@W#{<L?8vxP~ z`3%jmY#FkA#_N?!a0&hx@#Tdkw-*m$R3=4wI7yWG*@MlExE(-PhD42a?d6rFcc_eR z1qUCcte34S7}BnOmse*mEn69<<UmAD%B)dOx+-v{v*44ad^@%6t50AE8NMH7+zpE+ z`O}iv&_q(9x`Arhbwam<FMwXO6Trbc{_w96=mu8SY<L^XIU5@8IhBKs^vC_#aR~+f zIlxI?iPF+|8-F0wEX+LCU1oe^N_>b<zfz%C><~A}@2jGxBgFPX*8z0$y~O0LYl!9x znLd9t1#C<BEtl;VGJ56oln1WiWseB#?$(lyrL$PKbu8yzg--wuc96}952?0udsr8U z(`ebBiA!0xjjeXp$<)g*$qd=082yYKjq`pKPwe#bvf!<@-3D!FONWMkjW|v4LzFw) ztyRA;;VPYT;nT!yadumVmDlc}y$hwtE5BgC*^Pk4&?KEV3HJL7o$%b7@6mIO<$VbU zQ^e062FJ0+DhmD~=FMh8BMay=s2<lu1{D)8TUaGm39BQ1n_B?0PA;!`R%5aDG5VB? z<!eP`&-QiIPR>JZdN0*R$;fOI8kf>n7E#>ouib9GP)QRQMJc#%=mG7)5;?I7EQ>z) zqKcNNbiZHHa@Pq#22>tjL<b!(227!M?>U^XpO&&=ysotf8jg~z#v$$kz7KopH3lw> z=5&2RMc%qSOQK#2b?EXjSPRAUFd3X2Hq%QJT@f><N+KJSM~Q+m)}j~sMJD9?M|&hH z7C`J_VI#8#-YJn(FHv%>AQIfy4cdDLMIv5CZ(h!9cOXj|D<8Vcj1A@s=?Cb*Y2tBa zM*r0M_J1;S+CL56L#0n)n*}JZJI1n0m~VGbatr-idSQ1homnSJcKPBV%3~GA+j<*W zuz<&<;qBDld)rQ%ItQ~B3{|=U-zOUc6@*^T=RnTCHEOPvDFeL_D$g((mw5jt0)3G_ zjf+)*haufOz>$2`DYU($j?Y$aig;9Y`0Bdi8MZ5>r%BBFj<4QdKZ}Vw>!vq;0ca^% zWd07TDv_=hm<bf*f_Qk3ikLa!<3bI_f*o4VURhtC@rCN>7!6SFV|qTZB#+aiW8aV* zF02M)nj$rbcOFei_HhMvWJhmR28E3MpT5}1%lz6?C%V~nx4I?0)+zkGg$xT93L72z z3FBc!N1Ys+#F3Zj?CYD+P~3!(d`chgb)@1LSor9onEb^vU4>ygi)?G<imZa-WWaEi zi7oUj&5OX3Q<A`Avm0>1^5El(*6j0EQLBZBTes8Cm?^1ok4pvVWmElX{h@ap1Wt2W zz(ll<$DLO3lZOo-FCHA8wi6CESX`e!jM#?7sm0}n?<jF1rGo)D%nlqogd(^cyxnRl zl>1e6i&3+D8%WxT`cw%%Rt?!TN4JKu-i(9ZK(IS<Hd46lshydX)Su{FwA)L=vu8wT z%anjy9^}(7d}ph~Jiu$HWn75}A<DMyd)(#S(X`L(4J`9aG7>#>tN!!wN{I-ie|V%y zG5)V5lJ=79T7i716)Y*Ch{<X<Su3YwU|xXh^)V{E3?ATLSO>WETPA$GU~TUf@=WKX z`*`teF*VvFmZsZSLxo|9sg0TmK?X12_zcRSMl@nnE=ys!Gu)ZkpX+M>)JyV^(_`&F zr$)@9S{`?1{%~@d2Jh2AND)fGkhU$0%q0%hA_(#B!NX;y4pu~Y2vsXzx(PvhhvYQ0 zq4h6<t_lVow_L^pghtE1wi)b}!TjF{scT_;`1wbI*hBQ{TF6!%XZdCppw)jeNkvjq zSN(lI<LEY$I6rvcB$aU0m)QRc*vj6U=20lVVS;JCv$JJ*Z{X-BDYT)xwWP(!p_P<k z)NSFx^L#c7{bf?6ZY#NG`i6l-Peu{{dX|{MQ`BEThx6wP!=-rdP~gMZiF;0RolWM_ z!HH|NHUCcg%@}fp#aTf=8V{gn1bs^IpnNNRSugy1&&L52^xox;#$ez#m(t9$bc$)K z?3<UI9gte{Kh#_Cy8$-c1UE|Wc8uMy#`OtuOKXl+YkbD)_M9rQ;QWq|AhL439=AR5 zx7Rk=L4FPxW6_4ZS(c<Fktt&317We(S6Jna5ctzT&C#_2+ctaM(1*J`0+ieL)rQ_M zj<6=X;_{sbg%yYC)9&<H_MVF0-{i})S$sW3)0i7PZV!7ggxm0nxDMzh`q0uPz9Zj$ zTn=Xvw6YIhvUTmF5L)#)Yc08KKmIIl@UYq~|Fg%CK#4wSb<U-=JJfS-+s*|gMc-0W zA8OIk_o||wx|ONtH@=@j_|&Akm1DXqR;Z2CF5du`Es`cM<(~;GG}3_mATHA17f~!; zswAuz41v)#wC1L1Gge$kL*?h1!~P-G9<<3PvTo}g<_={pt@(cT!t8W+iE8K-`5fr# zUWkhR>A}IV6CN~#srwPSM)KqT<S!<4u`3X_C(tn&C#l)Ov!tG&C@W|a6U)-%`Imb^ zdJDqUe;=M9e|OQnB0hcpK0j7yHvABY`OH|$<^ZqY@QO=8HoQ%YB|iPb)do@{VJUc% zXE@Hf`$K~!oYFgMP@<zT&E6!A(>{qiMeI3-_+8|aTd6+2ZI2Rv`28E}yHd4vX^l~C z2j}{ai~}P!oGmzgzux_MeQZ@4R#oDF^=|(vZ?Nm69owTFlaNAm8g*BbQ>)SmdI9*C zKL6UKLyckdn9Wm3y8Q{YD~xYQnA^}1k1Xin652<^749Is+Vugef=5vofsLE9+jFHJ z;YU9Cg_XG-`+fMGO5rN(&;EQ)Fq3MNcnGSK9xZnpaAFL%`nWSb7e-OpVYGF=xLW=f zdG#kO<2IhgdhZ8vsToUYem%V%T?!|IBjuWQ@>!QV!Av8TCSlvf+wV?^0u~VBZ6q3C zrB~w(VTQ_oS<w1uVHBRv>A4nD)r2K-B<cgyR#;R494opZ9Lz_|AV5s`B4C$d{JkX* zrHr(V&r}d{EMmE<eo8KWL>}PpCFc*^n$-f(cxK|eSVkt}G+I}&V@lM=+(-9NB1NbY zaqY?{=-N_`QxLE>Aj9o)j|8_l2gmXa{eqQ!_W!f4o64#Nq5QY7yK*M&Ieei7YYQUR zRlAP_pHZQAjC-|JeZ|pKs2~J>%SdgVIi$vK#brFPBRD3qt&qDpd?sI<UYsj}mJb?& zD(p|`472C08IZS$n(G5>aijTBUUViaq9Y&WHmT1EW~x5}aIBC&*yZw?PI8G6z@e1Q z{Dp9@BEP2v{|4Ek@6EXP1PH@hgU^wXJ+Gp#ZWYEBd%7%%It-7E9RS0nNWR@LRPr6y z!$&#t<6Prq4s47q0i_G>S+O(^V*J!M?(7bph_iqdcDUzPsOoYTf1K~-TY{ywnp<D| z_E2-mGDgML(T{6XDzVedOOzi*SY4ODt#1hU(PkvF-c&!GN)fYHf1aw+O=hfgMD=S{ z6{9nb&J{bD@%x*EG_|Tp7BtJ~sJ1+jI*^+Z*e^yNnQ7+*VH?$+I=j}Mtp925?X7@r zigjQs)WJsdg_!8r&acL<y#<zF@WPS0&kbGqse3T&L!(vQv0-@eq79J{K&|HV!g9{X zo&vxAO0Wy=ePcZB$0&Lr1_%AFy0>9{n>TU0xc`;~@OB3COnBK;elEv*HtK=r!aKWj zdS8rN49sX~``1s#uzwT%^jP9+%18Xp8D1aRlaT*%^J?I~e`g;Q5Yu;9p6i;L;uIY* z&Gf_tzRIR<+MUNYFYPjC!nXJUaLS<!Q!J4pRK+8sgbJvb4==h|AetT|NNRD$145}3 zgjM3Y5%N#@Kd2E_=^lb07yV)DoV=kVaVa1*8|hFUB?Ui91l^zru(b8--HsuEnyH3P zw6?t#WopVuR9sW;M_fKZc#8z!;FX=<j8CDIO9qcMf~ZS)?K<KQLN`?HWi`HEjOnK& zvh)U5#y;s~fx&f1sWG!a_=I{Ey0@YqgMGBF@~nuS$oeF8|EeZt;iX6Uta2aie#c)$ z@X-CBCGqkNSH?N1f1!xU(1Fw6*X~J!+KQ$pe1xR;*JIMjt$)3(k}KYi8W*z^pyWEJ zJ8J*Nt?H0o|7GwgeQlYV7=IUi52N^tm*NhT!jh@i&j|uJSELENp1VdpT28!djtPa` z1xVM=@{rUC^Wp~sgOGnk=tCY5Td#<?=7qM}iUayQXkn2`xr2=15_Hwj|Dq8ygUdfQ zK)0jXc9#fhrEAa7M6UXwOgP*Yy59vx#AFGD-$ZUDxZjXh1Q|g<tt8iY!{ug^Q<>(5 zhi;c>ziHSk7V!!63Dztca8FFR!16Wn)6wM2qP!yMg4_+B$P*6>(ZZRqg{yd=6q>h) zUpnOxj>|y_$IZsET!=Xze4#A?$V>Qw092ir&vnR%3ND0teRvo|e6Dw)4Bz4)y#OCu z2XNdtVFfBN98vcq>EO_v&E8SS4Q)uxX+O>12UVwEToM!EgiMgY6_B_&iBl-r_yRk; zx2&?wz5%)1-b}Q-y$o7rP+K*t+8WBWTUDxZaszQefTc9ID^BSgkt#INh20D{sm2GX z9)w$g_=HfWys7P4+9f)0WJ8D2)(ZO_gdHO|S$;)@aM}b9QtY{EOnmiJw8=y!$mU&U z&bGyc(d5xTw9cWbr&lr|8Szdyq0QN1Tj*F>N1-$Y@`JfC)Mg@tx^ZoMwvMn58eMWd ziO*}15_XN^kV?AGuz#H1Tp>M|^jVbX?);=ux$hD8%q)kH7B?V;p2CpiAEdmuxqQ@+ z23fk-z1$WM>n5=eF)}T96I7hm%HpUgXbPY=yE7r*CW#q&I?<cQ8&9Y)8dN(JnvXiD zY5nuF6McAL&1Xx}Ht)1`!YQV1c+2w}=Ddw6__X5<9Pc*k>Y*}gADpsmA^h>QlwP2D zljcmGdkc-^C)+ypKrT@SReQjHSZv;To=sO*S6XqFN`=}HhG!Fe(ek-&7`|Q1Tr;`| zcvTaACHpRFT0o*MS_!gu$rBteTte7kI?Q6VG$5!n=g+b&6m094k+c7McRlxUVBTZ` zB=8p<;Ms?P{@brN`oHU1IwV)K02sxV4|9$GloLu-k2K%bLuX~huBN@ooRsc9T7%Hb zySb>Pnzp{z7c%?CU_=5Hn_BQ$kjPJLh<C{k9tR250ekj9nl-=S@0~V@+p0cH7^;l5 zIp^9fWZJnuq`gu!EGUtq4oJr-zna6It$En6jApVDxMHStBv(;SMQdC7XAg~M%v$u{ zNd9#h6~+`lYy+hO`h&m@#MZK8Zkn4jn9qbiu7d9+nK9#$WQ~rsqoh8-;f~J-Xv+}k zhvQKI8oxCj1-+|@bj)(N4F9sRm!7`t(PcII&#;52o06{P+a>RORp&H8ew!wNXU11c zUJ3km$790t-qDn3vDh<?FyLjzr+DEXKh(ha;T64ipA!2o>HmG4W8cs5>5cwR$-%un z#b&VXz5w=-TNKsrcxpf}9y(-v->O0Uo_qXt&Ku-?JSOEJLOAC6pCXc(CzkwB#uYlt z?#%}X@1`XYyT0n4Ue^9A|AFbuRQB`A&Z65wLNR#S`a#90?w}}pCCzV!-z80|V8m;} zo|&B&j&VE$WaGTRMiR-6C9@+fGS(L%5$~7<^75zNJ!sBg285DkdZ_|wM^i>6Y+h&a zMQ=;k`N5K<+d%Y==?pyIBwV!Bwj6k)#687@)%#jp2`*|r6Wwy(Y9Gtr9MRmOr$BIO zgbzZlk<8KRa-CuY7KVYBwvAI&Vf#=G{2tJTbu3h{k26SZ)8g{r03IB0{Djo1#WN>} z;O6=Ug~d_NT7F%W4CGM7rn+Fq6_OJBtp-G2zEZiL6HbAA?O%lYYjiP)J!UiaRadRw z+Ur<ASfWUy3=yCJU@Lx^s8YRu8(+(W?x#@=lnr4OQ}$mO93O?Ef<2DiF1ODU+f|oH z5N-%Vgwx96$ri|sjrc0<CaaO;T)BDcdk9MxcGc#{sR}QF-`o_^ga`Dt%(M`$8(dB2 z`g1pfup-U$c}Pz+4}t}~Jf9BWuU3NnE&T+%yCRO3k<gWu7)qfcH6x1v3)?M&psV8| z<iHKlVBK}V@rfQC>wH3ebl56Msvo6K@Bq&hu_1odxAqTX!0mw9Q7-YciQ_%y>Mrp= ztb7~C!txcb&rg-F#OqK-E2!Co6p;9pD!Boo@_4V+{_k@c;kLs2+hR2r6oWeCPm6-- zrGw}@Y^U#5A!gXP7k^l)n@fV14vTiW&Am)0^HGOZPsXzr#p=z=Qd=+tLZ}bHy22NG zBXbT)(45_JbBZbkA41>t0rb2!8{?x5gA=#qm`$RwAYb(oD^UrtIp}MZorWZBL4qR9 zN^n{U%T^!9waNt*U<tb8w&vrnwdX#)JD>Q8J*>83=+Xw{HH4~4F41i(FsN+5mV`U( zVB~>$u^f7i3xR98EGCQPZ6%w&HBZc4Yb@s`^s{gNofX8D;L4-%NsixSS@nl5>PRl} zc!>$g_YrACQbNb}vH#MIb|6`jRLMog82y)yt$Km|hrL%ZEJ(sZd4&%|)_do3bv9b7 zkd#>Gv6eZI++5_y2lKRhx~*kS>mGI)V$k4E(qo9y1?$55fFr-pzS&@gy(>?tL#*?i zvE22GRbt{~bI#D)sBuKSpP!9;rL8^Fz55KaAl_s~Kr3=g)uHG7__HK?hpRio(WB4k zf4Q;h@8~bZDbDaTw(J+EpMyls7MF8YUFk!>QaJD9l6`v<DQGZ;g;u&z7vI3*^|+um z?b~+KP$u8<7hdu5Ox`_WFUz+QYorbzlV48i-n6USu?|iGqI{N{+qpYtxNeWges=1H zq2Rm%_XlLz?7c2ve4|EpM&-f|i*ZgrQG+x6G4lMZ`eQHOUI82fz8sm1k477WQ?ANW zve_qXYR-~*@NoS1)}Zym?*!Hs0o!FWqHMU7`?&6TZ5$IFT#7R4<G+|S-j6``-&we| zo&ygIjSDf}S$0hsJAOTmR;5qikWHIp(;hB6sdrvJD8rX4)u?t~!TvQqx7A8E?JS_9 z0|;a;6Y5%akhV&4tD^04PuwH6IgcBI$S<iYPkfdsk=g)yM>4x-t?SZ2k9+ci#J$lh zf1X%>@#U51e>E|=-Z#$tP|apDJ}gNh1`eYm5I>fsUsmLBARd<sfK4vno|c&Lbzm2} z{8#3UD*{h<gVjgQ*^b*OgA)RP7k>muI?;~-FulM2;;mFGgDdIH)D_A3zPARK&t7cw zCU$D0LQm&=Nw|WNS>(blz^F$kBT^Lg#-~W@Ycr<YS0Erwz)awv=NW}@Tho>oy8dM= zS;$l{%oy52b}3|jGG7ScP$tK(E$msJt{2MQ6k3mNbtQHm&@O_{B8^4E{ZnYJ?i9)8 zgBJ-G|M-}bAkqcqC_*^;88w}FSjquvN9~jyB;(+5ar(VkVia+L6h9$O6Ykha#N0i- zf{h85r$o@m_ggOa_7nVF2!Rs0A03|9b_BLAqZO#>0F?nQ{X9r!sFBvV!g4LbDS#s2 zZUDRd0HkMGrQ?7N;8E%SK#t&+y5R^|H6S$D#mbk?g~{q!78Bk#vmY`e&xuwUVxFI@ zHr@{db#bs^MXqpLU#*0rAYVgnrDLrG-9EoNF*8<g>7;%K^Nq6;I}zVth>Q%}+DKz+ zG>PlYNQHD$@3ky7YVMbuf77P1&6o`zvEQ<V@AAxM?S+^hq_jp@Ewzu2#_i?Ka;y9T zXsz{~ZIf;JRW>BU8tPaH0n94ZTrKX$;&3N$3qWeC`ZkbxlZhqcW;!TEbT9s%=d_lU z#hUuq%ZkG*CZn2I_n=pz*KXqh{+vgz&c{ZlVBaPeIep(}r5#PeY9nQ{GB*~Fp2}`+ zX_f}PA#}ke98B6**8KQZ!Uvr{b2f(4Y{o?n<iRThgo(bY_~mHG0K;Dd(>@B?|4PEh z4m~4yIZn|ZY*pm3vVHYjDJ22&L;Aa1d}QhVpPp?FS&3%jxyYhun*kuyatrjU?am7U z(%0*FuULtd{-X8Vrgp8Fino1fB%elPM(26lWv-2O^3%#(5B5riK{Lc9m-E5*V(jqM z=RC-RC#eXd`n!W{TeBERgKboCV|&8*(kXs+oEnTfoG2yeeDa9aD(LB^AF@%OWNZO& z*xYVU>^d5@wu5@lAqUYXcg<k=+d}OMVp+oS-YPqGF`GDM@m&TBy9@@WuQaR;uZ>4! zaydP3)tAs+^?C+*<)nZ+5CjbWtlv%6`p_04coG`4^zgl8vE=XTd8AFxOAv7q(<h{$ zM7?mi)nw&K>cv;AZjgobqPXzBIlc|-)p663L;{T{tJHty?9M3OoQ=KkMR6Z;{*TL+ z*FzIG$?&p$PW_MIbWr^xA{|I|AoJ`t=yi)d#k2%RX}YNsYqhv%@ksrvM;zHGmG^ng zWF11!DS7MnVx%6?HBTs3$RI8C#;#eybp{$=$xEd<aPR=yV?drU+fKm=R#=2!RDj(v zLL<i%Pr>N0%yE<OmQqHQ-9Apq6|;;y%G%WoO?cKGDi-vK2D*k|-6ye*t)(s3ghfLL z5dV*+vkHsq4ZHpfjil0&3W9W(w31RH(hbtx4MRvsNrRMtbaxFfbhmWpP{YtY@Xh~y z-|u7}%-O!?diM3)>t5@(#{6dW&>cs77esK+JzCnKnuMG`&9;=A5BJKhWpgkM;{=4U z^C$cdQ_4C~4@34__Z2pJtcH2K9DTx(&diBhmK;nKZ%-fO(>2pqQXY=8#!J@$Yais1 zmWZQ?T*Fw~exCu!U)dJJUNczpM%l22Q_x_*sbhWC0e;zLXreuBV1g-TnqAS;zR<`= zS$qacOw*_(6~NJ5u*;KY>l@>*r%hf`bOvei=@X8-Sc(w#H51Js&wNL70irzA;q8>Q zf!Fk=VKgsbuO;Aa_2X!Sej(USAQD*!^~$L8>60&9>sAu-x~!K8Ejsaa@94QySIVcD z13ir=0}CfI-MbktZhB0}5zR~8M=pcRG#v}8V4IYSb5RxZ`BLHS?<Dz;1^m~`)Dz8_ z1HLnJ_jZ`YEh_`O_CU~P=C)GHDITSN70=KTo?GSi=F`Y7k4t^i#c0cQR3xpviC*J5 zhU=0m?ZtZ?GXfVW7?dRu|Ds+1&@bSuTmKXD0+?r=NlOf4(kI*yWSdp@s2^brgXbCD zQ6r{TX;;&1pl3ZcVvQGysZZq`YiO?XpXU14z0=zb5WH1!HV1+ZVjfGKW0~+n(shg2 zvohP2&)Z3C2PKq=?%J<0FNrKIsNtG;yLP5ZCtIDX0@n+my}W$dxdHB*Ck^e#N%pvT zw^t!nx$_)|oFj}skmA&KvE!Qg<RQa<e)F@j-;Ri6mK>sAHHi86{5E`%lqH;^W%I<o zcUe|?{abiE%6{~^@oDtm=b1>xj(mwPC_80KiR6X+5O3;J5!>ocoikxW?OI3c=(ZP> z8KNWo{qKQuJ{puXNSBih+WpAaj!Gn#PJ4X%!S32T$_UvLSY_c=6$QV)K$ij3p*b+? zbC!edZ!@4T;QZ_KuKnjoQa6@Ys&3?Ytr8Jd$GCJhPyP|;G-**x2?S#?`$mv()E^zh z?#MiZ!&!qi@<a>1#N_NT3WpYvIRGsb7)9TVMiwfh)AB5F@}*5FOFj%5e<8pP^SI!( z>`)E5Z$TU>J-kJY#xc`pFMTZeMS#uhxIZ|;8SVAgk@x+zdR|`VXM|uoTwi$2tHj^0 z*gsWV5E(4?$#TKxiO_rN@ZUhe_ihxUaG0F1!GHXJt=jI`zeWr=<mm2_SF%$}4VM87 z_sCaj>wo^e*irR8p1-l^b@|K>;g%OzRk{mpF%;}>ehyY#;s-c<!>0u8ns@PklSsi= zwHOLpuBF`C^9K#q9dxYq87RSZ3<pxue`xM+eKF4h=sFJkUwYvjw4;i4y%a}PO5;H{ zG)}(>Qair^Y68=^qyV;T`Je){Kj54Kv<*?kh4s`tc2mh4&9AjwXYgM_++wJVScU(Y zEX_Bl%&t+27QS;<cX_X&i*JnW%Mil7gDFBC<sR~GTL|7l+J<~%LLfK!w6dOn{QcIy zYtRJ%&6eQ_+8XrJIA9r>F)e)j4K<!9+w$)KP{pS2(M#Nu`X;tDfy~xcS5T(HL&11k zBBCc^fKc!Nu4v8#(<pz93_LD<so`$rLxyf!dmnaV!#XVoN>6@W<`$cG9^zX!NaE)e z`D$O;lpdjfq(%q29pfmRz!md_7x%rsTUeTcCB<#-O|&O3p)A~mbYXyp9%&SzP6^Ul zG^JR8!z|HnmEEE}>3pJ?yvUk)@39@be>@+ddv8vF_%(HaDGBH?bULSW4}50U+7Sed zzYKKJ7Rppizw}>e+!Vkw+yS?JQ6zooUV0nO>t-2>yS){Qnf&V&Oclq(>Q@dW2(V;x zH9hFig*r}fv0+KZR>8E=x3BWOoYphGM-Z(5x7D?nY6A6Df$r!wX`du~xVI(ZNv1y9 z(|*gA5|n3C!1;=?zfpjLC1<87=4y6A0QgU1g2{T26#i0d*6}4GoCjjJdms5D*61;t z{3v5dt-+YV(TqT#?S&7EuSOsp^qB1HhMvr_w>#wN=WkhM59I%knRQgA%PpxDqu7=W zqGQ`V>W08YF3aqPnc1&bXR{GuXW_PYJDHTI)7LHysf@PC6%RUU({-$;hV{po27t?e zDCaNnZ(4DWJ%Dyc^F~IwO^~gu;SWzXv6g%Lj3!_Q^YBWK)Y#=imDWi?a%4Sb>8Qu4 z-jad_m?Q-{x2TB!r=W2)LqHsTC=t#Rpqdk?>hes@fBmgbzlsf}(MV}hQ3dHpm(H1p z{N21I7>%Rki(d}Y1b6<7?-=GNz^gt<mkdzzL4rDXtSRCf;s%i?bV;V)Gu@zyxAWn( zv1r3BITlClx<Bl}*(FOp!W~5xyJmb<LELZjRdx4^5kmV@BQBt!MH^&C<(z`?r4;$o zwq^8*4B!JrSKOuPp8&flvx-aRFB0he$n}TJrn;k`+Ti+5%Te<h@kk=~@pC6HV&sKy z%DyfCu6Gg-;GUU5?0pPG!#)$ca>H+#j*Oq5Z;*s-DrO2XrS-q0X5<b8dnj2{GUXGi z;S>+R023z;_UD<t2eai7rfN{=ti=aV_WW!?va3eD#Nq}v;^P7@r-=1@y*JbWJj+Nr z=?v65T^5WYOVQMF714&`bERC8_9Fm!1^c1|fWQG?5GL^Ur4f4))96|yuLWz!=4yGv z&~0r0ZT6wYyQ`?66YhMk;f<^{!Ow4t<;9DXhze7!69{t{A-CA-E{v(xC{p9k*(7ws zCf($`ifP+3>z4hl7tjH@l2V2<aRu^ObwJ>7H4S568Cr3Ucwo1*Sw(mxFnvvBIA@rl zOiFhxv&Mj7S2bwEByWPyE7nt(Kq=o-7!%^tAFcA0rv71l`_nio<<!GaSm*_tb>}+7 zq+fC{z;A<He1lDTeLHgBn=mdi(YFKZ*gS-U&bS2NG(jf$lk}CqlJC^o*S2}Y2ZP(< zB{cCdfwbb5E!BO(^{|>9F2j|Qvz=WL0$5>=H_)+*gEG7U{pYoNZTxzk-`3luwlN6= zb#<Hg5xdBoYti0IgP?VrE=nDJRrxQ}K~eRWA+7XVo_Wt_)G(<l3o^t*NO4WR0F!A1 z&2a-9kKH6BI~d=CDa&&0x_O2%Hn3B6WY0Bt{E6X1e@G+3@&S)7Pvco=9Rs7~&l6Le zR$jx}6)R2MlKQSIIOjtOoJrU3rRze-SY<(vEbi2s;ZfeFlqA7d&6jO?GM!}-tM;O5 z?d}EMpBOO;^jx3W+2LBQmu>b?Oc#6!*8U$3qZiW=ij^Mk^`af6Lty`Qix3$8#TbFr zz@)3AWv&*?6z3RrL-`TTMm&Hyq}^_XTxZ}PO_BgcM1R^Bt>@ac?-d>9ArkL#j8`5F zbdURY159dg+C4g)3#AsEf@AU0jQCH;7F5aO@d7y6*KzPP*`_Ywr5gi`UyO7FzNGnl z4!BAn(xLBTo)n-woYz8KMH;HldeMWhiwBGaZWKp%nE{3gsLhD)SzQy^Y>Doe>0Hfm zwO3&;tA8UI1Lf6dfsX66h==kn$D3ylktMW3I~nT$M92=WMTF|bii``LQJI{sxDo5X ztG83>m(w0m^YUN!?k>gS7qk9tWses-pllWtLUsDBRDoDI_no7U^2En1>%TTgQ^)S4 zGZI@udxWfz?q(%Dq`R5J(*;KmnIHB;{(`(-hkplX;MP+1t?#B#;1l&4Fnx;JcWy6^ zG5(^kzJ+()NEmq^@mNQS2p{>lQtsi+c=GZRI>t7iF8QEyKsQ_MWIjyD$pUC)28b$4 zvbu!*QuD~kVepd6R>gIqeaTz;SJIPKXc&V4<vDeqS{!Z8>+KTS+V{wbU#J~TSUMPu z*y$)xBARO$T3CCE<j<bJ=mNaPUbqbF--A_gu~dor0=_z;XIf^lyKLMmuMDC>UOc3s zjDRN$jYrc^A%^%~f<PjRDPpilGoDPQ6Bz_8hhUHh-Yt)tV;U0kH{gX(T9Ou5lm#TM zeN7OUo&=?$v_mm*S&eqZ28m&0clMQp0>vxg0h&UpewQ{_nI;+SI}pT?4l|XYPg*;= zuTU~qU(q_XF+cFMDDsd*lWq!Ytx0%`8YN)p^CkL*`5clx$-smK!2$cW>w$J}BeYMp zFrxuT&$48BE$*809GE{M+w_$fKGLmN6qMl&LK+Ank6M7*m~h4oiQR#60Q6PmJ&2ng zNk6uWgj~+t<59M*zduyvab1+>DI@1)v-m4KS{|lm>`PbOS?v-rqEu%gu^P9lUrLE@ z?=d%u#m<RM@Gl6b&42CPLJQtl<(bUY;4O#GwEF7BE`H;D-d64Y6nqJVxb3jL>OP!W zZ_=~e@&U@K=to>}a@blk;CQ+&b2SmLE5F2ES#P$*DdG7N_sFzsJB>wFe|9_VlQlqd z@sq^V4!etk|H1>_6bsEiRDM*b4-)$rAmFec;1XiBJ5jscY(%j=dFKP+$-nfAKFXut z_UYi3u5axqVM?O5Z|{u|wdC9qIh<+SlxbwEvJJF5qV<>i)0B0vjOPRsudIzb>dW-d z#@wj~ru)lvVzH0Hb^{DF`voZ>;31At7p*H*jr&wQc-^7~5q%3qPDnI%<`Q)IG6%KW z9QLTc)e)qCIgFX&@*~AtPun>-wc`!*s*uUyjAMy}wcUFj!10vc&<(u*M#fPct#J8~ z9&^L;Dr!702b5b2_R_`AJ@{k=%jIn@iaz1F=lb!_mpQ);!|7&P)DJWf;ni+}7TsPD zIwgkDT2+JG6JIVB%}XE%{rDCao)9-d3NCqv(a6ApGEp!^+^;k*Ig&#rW|Ui`Vm5u; zqfbDHk>8fXy)Y0s@ydoeanZnf^p-dvb<x#qqs?fLf8HL8oo9edFhxG3YZYzU?CfH) zcGK*a)Q5s?qzv{$no~wqt_lA?ez{a7-5F<{Ny_W68066Fwe<&<f`HJ8%&4^S*3>M6 zXH7mqxQz6Et!SRD)^BDPn)_<e*;=)i-s1_IwJkq<3NI@A30<Tpzwq7ajKZE%OK7Hk zDcuy$TO3Wn1hPP~ET!BN@5QABVJ)ma)PyTl)ISe63R6l2f=Lp=CY#HTP2`iJv*atO zk#V91Dgo=C1L7#=UHflt;W|N^q7uOk3*EWSM#W-PC%o+w*KN~J+1B$%(MR`)lC;30 zc_<G3!Gn42WP)LpTfZ+{0KX0wyhCkDLFZEoiKwy_MZ2y=UNm;tc~OWh(_iw=hC{-q zC>nz())~;Qoms`bZd{V+Aw4UDBaj!0Y>7F98%($-yJjIHI3~o$xn+F~iHn&vrT*Sz zvw<9pP`}-nk$=Gyfo%<mZeHgF1?DZk&aA7C4i`xY8GNpd8h*KO@X$n3+s!+fIJ=7X zAIPBG&Cnl`QByylq0ApxGFimd_SV1mwI?8Jf4}sSHNx<a-N)aM+I9c!m8Hn$$Hqgm z)irgz%%g$NJv0K}u?9R`rrOqZRAC^9)QA_!_~P@RY~kUZO7SW6aWO$>8LGfFH)mRE z2@Sg=x1)dA_Gbx*jmC_FebCcqTguL!$60hqHocUYxmbG@HbVB18FT$N6<1aRnKb`; z@tU5Ro1ODuUUY*hlSg|Jl?az~?xoqlrL4>Z6w{C}XgEJ5nsl9*Pi?E?Pqu65qQJ)m z!IOxkfXRBM^~EQd$l<>yVnMm#g+$DUTUtbBbxu}}l-tcuZHtaC6a$TBb20*;luV+b z1w<UhXek-6S94soNWyW)Gry`5m*8m{C8<5rr`wckZn)rsPKlVh)wXWVBN|Z3d0T$= zVvNYo4dA=!qe={dO#?!s%Ee?ZQ}(0|t_aMJ2%Kqz<j=c-a<4$XnVxF{rA;X1wW;k8 zPw#B^4bf-DBM1iVCMuGwM!e9!%|CqSmld=&f4FN&sk}9jjv;x|a80RJ&KdTkROrhC zXpj3lxWM^p&mTmjki9TLzJ=KF@2g`9H8+#9dNg(5!i}DNJ##2GTS+^H!Eqzis?3T+ zQ~8gdM|(*{{~yx$znE{Exl=935+8SewpK5_5mS7+&uhv7J@e+B)@#YiD)iowRgOdO zUwrvBO^X<~I^O71&0m18HDC&c$SAE)H5AvdMHLS5b8oQ>%PFzTRj?Rk7U%l>YUBX= zwYyp@Hjpg*$16c#VE5b)W+$8`Z%+UxuZ2YQSSYj8@0W0EA8a+Hh@hF0*pwHD^kL8< zl8Y6R`#p*J-D}=7+D)#r_`heas*G2k)6Gr&Gc8$B6PR#Mvl%SXkjt%lHl~T2IyC2+ zc5{!vR%z5hEJ!-}h;KBeko@SWIO@2ILARBJB4{n#D@tgJhPR{Y6v!Qdz!ieLiT#B- zbyK7CXR$X8<X$0a_89y`OvJc@!_Qh?qg6H`j0PP9et|PYUk0mn|2@fvi1fY&p3-F4 z*`Dp<X2=_dur~%N)Fatqu3^}x(r&TJbf>0V_oNx2gjpMWl#l?waR8Z6AKp&1Xn@N{ z$zSYPJ0+g{(vOOj>v){HDi6~u#WrSkZAne5KU+>nQf0*M>khYq{hi`L`~ETN8hB<q z4mPUuLZrvl)Xd=lHF$}3v@jNEgjPV*&2i}b61hU#tv&6#BzD`in=s5yOhA=ldj>$= z{~>WGl#0WPK6w57J2t<ZABY9w5J>-m^1?RfY(aC0F>JXKQF_-eUM}^azDdGTq^-Zs zI2P&wWH^FUir<HL3m)I%T^$E(1@HT{Y7t%VwJ&TuQi9zeH4>JHz13o3UGiVc(dtP( zUMid8)oX>K9HV<2XLGZG`Uss5DOJNA`k;$KlG1)?tM5m2E)k!_=~zyUg`CMs$Jc>_ zuNkkCaCA*DcfwQ7qSs9y)u~j8)4R)#b8S9JQUf~2pF&>y60>im*?qSlYd}QSgPZU{ zj>{0Wf}BD;qmFmtg*Tr^`~?C_N*!MiYmw~oT@~@c27f*c*`>08z}bQP!*Jwgu5B7{ zjB=WvxOfrONd|;}s1{?KQ*dW*zinrRh&@sHa!-xF7xzwTFLxo<HcRAR@VyzXn14ij z+FLO~pbMg8_+=7S*}dx(pdm62{*3i~3*2!z?ej!pwJVR1Cm%ieYUXtl19wLZ{T;Y! zxSmlRR#u%Jn<v`3O>7*%&d-t?x)QGQJ-N&CSV=g12v+aZh*dY0Q<bOOsZHwg!>|^t zLR8*|EeZbrxNg=72!jOIMJGZ#E$|qvnvVRnQ-m2#{dU$|hJ=;)6udgOXkFlImYuhS zz1i+}RCO3)xXa@kJxCn0T8kIAbf>-VHBSBti^yjU2{vAp_loEFQXyzw;3R(xv_Flr z2|llHbFPogWBh;`?C+<Grv-Dnj<W+Yc(h6xx~Ps^6ZA8lDigl*P?-7nFjx;yawy{N zowaoz!*Z`<#`h~H(^sRE;GbD@4CAUHGF1|B$9GmaAAMEhO|nC~#3bzaIykE0th-+1 z*%u-^146jPpS6trEVHnAjniRn+md|r80XK@tU2<28&pSjC`7RUuVrx8JTRV3`!6MK zW5W+}HLLY+aK@@OZFz7CyK8M5o;*ucMA`{Q?tF!NFm>s`-y+K~oJpM5v0v8xw>?`3 zeQV-WXJtw)YaSEvuZ%96^+z=%)QYtNoxiZJjNf0bH~JV}igsau7VR&{w8-yNdbug< zwpFe@UBb8XVuEU`?&p9}_vJ+u?cY^N9r|C+&NP3bP}O9o&slfIEum^2Y3q$+EZl+# zZ|%Poz#kUg`m;YNuHmtBo(cQyJO=i8iA3=GigNUm@muPrGi67_I_KLy9?U&&)l01; zn~1v|n`8i5m0<>IG^)hs{Nrb%M6u3&?>cT}HS=IX9~&b?Dk1X%qp;ychr{&Q5qJeg zK-q7oqP_rN;lFwu@;m&1rFtMEI$POqk6L>Mt}9~gOS@rdUym7C8D5U}m=A>b6ugun zzEcwV6e}>;7c_k>$7FRppT@q$(py8!!5h}CB<sM&7@LxgQow%q@Ufu-W|qk++MHIF z*PnSg@<7afgdPbl{DX7!0a;!iE!nSMxk(gj%8WNu8`-?QBagnSHV{vsoh8Wgmgi0( zoB4}hWGZ$9QcFU8Q+B41j~#^bA87hr<rew|S`I@mbEg@#_9hA?Bs7AVOBu`ZThiXy z^M|Rr9KduG;6@EYdm>Pk|M#3C)K4(zk!PeIDhj`MXAbc#jZ=SZ2IjjrDp@pBc~t)% zEhxwrx}*RI-cmr<a4z+8A?^9OLx(7`MBeZ|f=ilq{C$yL@ziMC)onU5RSd~%q}VCe zUqDo~Vk2RHE4Hv(<CrF7q<h`?9yxj6eQsbf0VHBBQXmSB$<;?LR^VDB#@D4C9GEuq zF$S)5ZFf`}0E}>w&LbbJ++Xq<I^6;m4yoAHVhk2v78y_dP7SXb+Z}<=Z+*mlfX&HT z3utTR{6Llg+!IO&50?~|LPuO+4x`e>8+y9Yr));tow`sU!VhIBmSU<%>6O0<5#&ms zZl{HJgO_SksJdS_VKDm@fM}c$1-ck*Dw|4?0g2IvQqzm`e3QK7U5m}0yF3#OU#L2O zvt`)D^H$UDVj$(?wV1Ur(3VNI!kP#YRxWPI?X;rzkvsT3MsAO9=6E(4O8CM6UrC@m zxXZX=@<gh(<&DFDo{)a^7y)^mQpYb5i%0+%O_HWPfx7Q?U_cCNdGL)eJ{Lx|>5q32 zD$b;|U~KySAzwL278SraDp{!O1ZIxA<{rAnBF*WInO_t%;1y2c^vnF?>B+8zW)LUx zf=Ma;Od+wsr<C2{0bdtW0V@$Mo8W&}6~y@ES7qa`q<PJxfyi{(mw0?tmG5@wYbRD( z)v%EVE$ZI9OSS3ONq$>U20r*sE5cv7Zy0xfHj}rfZj+k%_X{Q$8T%tI7)?x4&9K?< z+k;z;=dLl_-@zDWI+43w_b7ZQM)0dq;d{6jHz!>OyJTf+AZZq?TJaHyGG%`odza!> z=~HhjBOwWIz2WC(;QVc^iz&^F*|uM5)G2e<OV!BiyS8DBa`O0lfl;?H&KqG@dG=MX z&_u7LC-wsl8>rDK9B^Xrpq1QJuqRSto}Ku0srQHedSgIS7SnA*9rKNgC-v^)C9~M# zkmJZU-7HH$2?hc^c3J5IU{vp5U6lDxMGiAwMC#`k_gRg_Mj$;79UZ_%hnYz0e$Ciz zkvD3%lZBt)QeWBoPRp}-c}tJE;Vp$@r7n^i-;Pfb>X(=Y-?d6NL-pqG!j3RhmYWrY zmwv#FG4t}=Wtd}MFg@V%`fH$8*)!3-A0cO&lr?w1BGi=iP&*=1W+Fu+72Ch&d~I4? zY)?y6oz)ax8ndlU@vlsUBc6X<YdOEX-nQgU@sUI0&X8!bGTOO>r6KU0Ynw&qU4NLV z_fOE><heh-Y3h&j;c}XTb?31VyH84AgmgSON7!ESwp5{pd&Tk#x!s<MJ7D1Zh9i5- zGMJvOdw3yNkK9L+gR=@9{t1~%A4d99e){EqOpEDsk@W56GBW*}x`W1kcY}0_Kpq`X zMrV%9J<jcF(7(QYn+x0>%N~iQDkW6q5Srk0^F57v+KfrK@$aS!VYBn$8%*YCa*6Up z{2vxsGqUVI0mhOctw*(u%KihAMWY$Wuy;=I{BwT2kF<vVs)b6$hOn)AtZ1&bM8zG8 zndhhA(5UeSM_p?Y5Z?HzbjMp}&sKwlmY8V48HHbYun_lzyV`&80vkffYk?Mh*78I= zMX<A~CE@jRpKK~OPCSrsyl$G6*RYs7S!-6ruKr~_2pBTFeLRBuc-M4i`cY@%L%#QY z%u^G~<JS(AK#U)rCBxI{yI%`_JlB$Zn|<>ypu+TfXI4*nkSA-nHZYsrKnon0)0Fy7 zvNnYZozhW0tuJQ^d%PA~e*!tck!=0DtyqBoPaFS1y9rV^*(PcNg-f7?<4&}sLPwVT zOqBb$0?G(;qM2gr&g=Z))wC%)TuqZ*7ir(K3Y>P+fo&IrNH0Ekdn<1K-Z(m&AfkgD z<L2a|sc+6_ZTcR^rpPIETn`}(^DTnu8lqvG2;5`)1a=UC2BjPk{kfISGVcFoz#iHd zKly-w-H+@A)**VdXG-5h<xYOlE^I}Wb$S4$qtKV)9KAmpQRbtt07KiaiVOsZBg4Gy zXB!Lz=Ni!c1eV+O7sjt998r(mFEFQO6nOGnSDdWl8a;@R%4X%$q2PU68;!nT^S2Jp z4@Z0|xgk$UA!2g}s%+ZN8oN%bUa!bOOO4xR>oxuv0zUO(xusy|HT#f?iU28@z%7s9 zkcTjW5sbKfzaRWLTve(9PMMVfZf-A#Bn{iuww3%0+`1=?z6{IFEmydV9?8pD_-RQX zn{bZpVaKgCUFfHkO*uA$#S0fY2iRE2l&^K|z87OAu^#o~n8c*!eexBk@GW^&-6odr zTe`}^crp3nALq@82FOI?H<^Z`Xae4PhEHnB6J*7Tp~PZOU~`&r!|3(Za1|%YJTq`P z%6a^|L+a9n8=%P%Fi_CQv5A^tSBq9&*GF32MM@O0_A}BQygh|Y>=Zm>2e8cJ%>>F$ z(bi(yod=rXESMG&O(yj}GfRpga1+kaC;;n%0Zb<PoG8o5UG+2;OnW~+f)%PL<5Ab6 zJd`lJ=3#tdx%~eGUdUIp%MLv|+C1eq<@4>mxfiuGcA@>QLIF4laZ{wi=NT+u=rTW! zvyWZ+Uo=BMbI53sQBAc6CE#DwO?YJm6X~AOR$l)PR_ehD4{NIA)Z%~)(ha|(x>a%y zWf1tiQ}e>eZ<NgpQU}YF8>qrA6~GAZk_3IDZ4@xl7g~ld{kdv}XyQk{62X>1;ATtQ z1Xb@tm{1qA%QrlY{*Fd~;w5i|YLKP&mb-EAcMP_=Xf#=+(;$DgTo8=GybW37gqn!P z)jld@a-RKe6jm47ApVreWfGDWZ~i-p7tJw~t3#BGH-UGX5HskgdAyAz?cM01>UqZp zg%tT4WE9i!2OBrF|BMI(jT-bQP?Z2|QF{zd9i*6#d&LDT#Io3rmPG+hVf<vSPUnKa z%`>@n2JUHiRbnae>#kQ-bmf6%(FvhGeu#`rOGR540{f3dL)>5LJnICOKrO{TiV;uI zH~DptRjMtfUK}hGFsBQFZxCD-x(KjX<9Tx`O8Yh_af(?W$hrOnVf(lU(&xi2aL4cE zS=~*(u)zm?;}Z@Q#`cS`TnyVMX#UXzxK$TV{KwQd!&NuWH5GziU-dH*B~6EP<6Df8 zR0qiTVpiePqqS*l&Kz5=Mjz?AaAo9Qno@N?T-^@Kq6ewY8e08hp@O52DpoLw0@4^V zo$*Ee3ci|s-?IzA>{;dAv9YWO-SL*q`ZHEpEcSd(9rd?~(Ov^Nr(uvwRJLWWva@l* z-A&&rgqM?WW=y@cQ}CF%!^7Ud)y#5HrTfRd`HAQ1)%!gw{;7wsCL2gr+Q`gsU@}nL z06LM!)IR<h!Z9nAQ%7^GSAQ-t)yl6A=&Q36UA(?4B?GnU<Xso(VPRsKH{CM7xC?sX z@jzZHwZ!6PEL|Oih?BSRHtm{_lhE`^;6F!6{21?FE&#%LM}XQ7?;`uZj+{-UqfE22 z<L07t9~wI=Jd<KBOiUt)N?q0#`Et}3A3J<jN;8khNRNkCjV$`TI4!?;EH}Tig;MTa zXpDKkF%T5jbd}LNPgk=7j?UeL#YEp^zn|44-fDEJ#a;GNBA;hf1mjWnf6A+EUtaXT zxYZC+WBBWBpwnukVW>4lD?RggKX@G1{Z*uwlBh6J)|@$kbZMlHP*VB;UVFa-N{}df z#Rc{;EclGbDW=j2E%0D%oNVNFU?wX4@x!YUm+_{gz)!t2{g#OY;0m;}rOXKJtGc{D z+-7gj&NWG$=8?!!W4tHSy+heX6n2yp8@)W`sJjZO_uqQx`D}4R)yy7)2Yid_GP2`+ zaA0ndo3-^jmPk?Cl883Xy^*}<>FD`nlRn(oV~<ny(UbFI{U}o=YPLE3xGk^AM=;H= z?C8>j^L@zG%2$SfX%6Om-}oA_)9HutT*saFhT)AIbPdpg`3b&_*1v#=n`!t2>19E5 zqMS?@lRc%F-InFiXA3{tQ`?aG6yS!qJZq$3oZ+_{JfG&{?|>vEM0=OD2Y*n?qsbqC zPIy$>qbQ=wD9jmdzT~j=cCiWEeZ1Unb;9GIjz6JjK9@(O5xtYw%azSjzr3#ZxT+bR zdG{&M;}>ud(XIAJaViQ8c}^l;681vQ_6H7S3P6GN&?rCBTlMVEfRVQf(j%Wm5@YYV z-~D9|m12w%G>HsqKV%-xV@m9z3R%>*RN{OZsUk}5gg%ipb+XjEYMTk>Z3!2OK}Rf0 z(FnD|R+%@%#_O={oH$Gjt1Ns}k9>dfaznDLF{Ei<a(*8LX{02kHKIWjR9s2(pn0j@ z1mM6=Xy>dMPJ*=6E$K}&3}(RubuoCkxpBk*+8fF%IS<w&wb48meG|P~JJZXr1?aTC zR3$$VW4M<v(pto83EiFBk@d}|JcM5>Rzxy81>&Bjvz4d$o_g7grk$hqnSj(VU~1W7 z+WUAqNBz0YF_UADhW00VgCKrD`@Rc5Fb^@#Z=;2?yONEN7h(bl?VtHy)R$393a%^I z8X(G^Z!}N|5$Ja&!Zf9ZkHxU&BDmK(MUZxSR@yrsE6$cbc+$#BtEEs60^J9x<=cYS zppFZ3J_No8gKmRzC#7C1*Ufy~^G`T|ZmgEwMLDCzQ>$~$LXbxSdqb6t3&%zWP`crA zzH(cxv+I1xVTX`<yL3IT{cuUuZ2^)m(N|Tj{%{uVk1Ff0f8>(~vi~Hb4kl@^KOj|= zhTSgz+V=w*TZ=5p@n<gVbnh5N^E#XveK=%?srs#`GQLc{csa#ol+<w6Wsdssg=nR( zYwH=r(_uasDqY03E1L5dfbr7a>RnO{BG{>xcX4v!7SGv8pfT0zxXNB>zjQJVxIu9} z-3<KmnU(_=-hp1t8FT-mAmC54b2o-@Q=cypml0iWF4n*K^r15HmF<bQ+eq{6xLN;Y z!FMs!MDArssC{D)EVP+%_QH4QVtp5l3FPnB&AfpN&8vfW3wV<+?3gtUMcPjD9PR!L z+CRIO|K)ctKcQMFo~(~VHlSfuC7j>CR{Ju%Ux_+jFo)k!SVcEwEE(TrU<2_O3_3k1 zOnT&96(a2G6)=2}`MjNgNV|iXnEU?9{tjp+nEnhd0>jT^{!1t#6;<RT6<29Hgl(>) zHRg;A4~=5y{3lKn8pFKUVy85{)pJ3Lh;GNm+x;@u#7PGm=c!s4Y*aTlk<<c%9y~d$ z=I?LCm8hv`Rg%jB+|d96s!;vi`-!DMXqvA;Z8;1HS_u<L6o@Flbv=v#8vl3q%+j3a zEKEV+NYa?Gh=PzK%1Cdtu(*@JW>R{MGFGPY?Ld!oPlnP0S|N7+Fa{C+yZh6`3BW6D z_eX~0#|n`9T>8iQaYn#IT^E`*6jdNd-Oed2vu0Pe@&Z4Bw+uWSX_fV8HN~&l{^_@2 zU=QQ+cct?+_mx3=Lgnq=R?nmfFHh?U35ebl&JGA>Zk$>F2@APZdRc06{;-M$mcxJl zjAG_6^R#9<Y+bSHxas8a_#Tp>6Kq5WX$uJ{-@A&;mSTh*Zin0;`9S6yu2hi$0B|=? z8AM^cUto(`DOS<oE#PFwI1k$Jy{G35ez0egXTB$|w4<D$+yrp_v#hAxVidtz`^xBR zFF{vUIl6n2z<%ZpWrrOaW08`;r4y6$be@**-xB+j0Jp;Htw^+PZ9o-G9J*|rwa8cU zk?!)lY!-<2Z2a+FZT@<&PNjoMgED-(RgzMoiFR+ud!Wa=v&iQVPZ}OQ(dPjZa9BQw zISnXMTOW^2l))4mN9F1yr~lo!eG}!r6_594L;Ul}NZ@W}%JLkoN5Go-VcCSx2e>F* zTE;=s!&Pu!MP{SDYG=XPeJy3`%}*NGOclW6hJup}^VG4&>}ZXE-<}*-S6r)Mt+I*t ztd$i|H<V*QKKLMX@MfPKKT;EL<UQaUz*Oc|l|#KCKLEvsdVL|_$`QoJI`SK}NA85< z{O$jiEJv)!pi1@ci@<No^;Y-?=#?+{mi-%_3d@V`@AM|Q9Nb_{eylUi83sd*K9}E* z?(&OaMX+rPSJWs&bx%l(Q|(2yvzg3G!sU7Q(n4Ay{9O;21dPc&;^TPBUg!tanKsLs z^}*V%?!<47<;Cal+f+nDz$9_FdC1eKpRUF;JR#hsHs{Z#r^ygz7#^iilDU3qXVC{E zZ7}>xP4=1^>;XaAR#~flAvXLG{8Cq?{@+m{>T+_!b0x-L##2!a`B$(idGs0cOfz3L zQ=L%ylfx4=Z{~vn^6S*g1jc~8K&A&r*lH5|BrqOtX9AI%>A+_wBu@2Fi}s0JXv}&X zfV|^TFT6FyNn^NkjW6fjxrzoJNNJvLt()N?&(q=zT-m}SeU{Vm=ls<xi|A9C!hrSt zrs?yT=;jlV>l}+tN*hXo(hgdz515NVn>%z`t$yK9aQ^>wU;URNl*(js@sE_Si)kJ` z-kAn8UcT!}o~h4X_;KI4KmqCi1|SCJebU))5qW4NRVg3(VbXb}P^Fk7JII4hiU2-4 zOxs}mzh;ZwS&9$_uI`(yiO{YrXB0bC@|AXg_lsElE5Flx_0y_+c);aF$SHlS29M29 z_Ho;1&eFW6gHDPWG%PXxh0YPGll$Q8_x^Fokz%v?LvAXYuaoVqicO^_mfIIpa@9H~ zZ;5{hCR6N<c;wdqZ64pDeO}L6bG}9muBxN;s{P^_T?7%I(+0|}u_!_)v1eL8gAS1m z>}U&nqUy#m{3sh9aM{=(vf|Vp-jV8|45ifVA3qi?@a@)zK_@0(Et3Ho$y0&5IQM%W zYljvL&2xyhJ*`{T^!Hchj&+5iY5jUo?dIKe#B;)#moP%DFr5B*+hiQA_P;6YD0H<N zEfBT8&n?BnHMmcAK;%F4M|?>C(7(|!&=f^;qXaD<0Q)54WYenD0MYJekHM6mhvgs> z$es;emHGy#%Giy5-0jJX?jeZ2!_{|o<hzQ5?!U)67`U)3r!YX^fZXy?_(~8~OlvJV z#c!yjI}Y(1@c0sY#Vv>!rh%Dfd(_^I{2hpS6}3`Kcs)!3?@%*2r1IQb{$qTd=<lF3 znFC)EuVjKMYafS&M&@_6I7p`n&9Uw;z!&$-m3esAB;aAeCA$pKtx%0!F2>j^&sCwx z@0`rM9TR?(a!F?3-vSFpi5*PTf-gd2ueFoqihl|v3L_Sy9b+hgd9dKsrL8)9g!QyB zr_`8G;fa`qh>FdnT2W_o<U(Qt;$wPxTN?cLw`ik7z{5-m2vO)kMh$#We{hc<muxpb z%c-zwi)(x>fHYuS6?_UPa#$gGE2;(@RXr9$-}4P%Hk?I0v%hAeTpGfFAk!3$&Jjjt zajk|-bBPR4%#~%(wa?lR)q3&QXM-^vN1iT0;PKd_m2uMY-m{hThrJ6WjGJ4VbVMQQ znmQ6Rmf)Dp$P`wH#>4XFV?2c`a)gT9XAnPrzTV82>j2iZ2YT<oZh~eq6+tIjHTX)4 zv5dWF0=_r}spyP1Nm%lXq1@JEelZz_n8hQwe>iz0+x}g`Q^}7Kudk-z&*~vvVhHh3 z@?~WSvVBT=4&oD9b4t9VF1nnhWVU+8`7@+O#06Nv{GYn41HFHfP5&5C{yTxJ^sfXE zEIxsUDsw02X#p4^xs4=MaX)^po-{lKuhaXSN=$tcd!U4~F=iiMV*GOIf@$8Y)K|L0 z)A*A<Nfg%G1g)ZpV}C=k+WyeKw?X-HM9OyFRLlTmV<Cd>spWos5ckg(!g37t^ncu! zy7jy{hT@;jEy!Vsj=nN8W^FO+)mAj^`Fh>~+qo%VlgcUlG1FU}0~{~fk%a!@68Y@* zf{oWynA!0Q_qsxQ*F^PDDETRz2(`dW_HyjIGeZD8t$@v$`ltxY>t-kppg}m6us$=v zAIz}H!DB424{%mXOI1$ek+M9_sfn+*((hmwXt*{~0BteTd1PFD^q*fCVY#o#Z|VCh z_m0&?a$bj65n}N*@13mt1_qo^5#mwbh5L(*8(sX8h6!z)2^X;)8W||Iq>^@CrPzG2 z{oAqsK4wmMjPVr9G9J?8mEI1qT#%E@{xTmo9^)=La%t%x`TkzHrX$y6-8}5AYgfO% ze8P{;GSa6*($LZMvXq-u0BK&(LG`i_R|UKodS*s_G4u8wS{)x`Uqer2ZqmGT@YIqs z_G)ZboqeQXdGF=k$CCnHU;gdUlX595^R1Qi8lObXQk~=bI3kmQL8cEAAsXyNHp|`- z)%VG@{hL|j8Bm<tD3cS<tQ_{YWrk#_(yH(VU}kUTU7Gi@L^W5>4L=RG&G4euQHwp_ zw~8eNoh9b|T*MW0B=!v14frWwAm&%)bpdKksj05fHfLv1vwEKp=U#-W@^%kIm}V?B z$JJ8YA$uYM-{%zRE!HE6gNnT@UctZe*52(M(Eol-BDO=}AL89Kl6d(T|In=9RvSnO zsr9CzXLHWSP4b8-a=*?4H&ViXURgKR-Nwe(i4k8AT{~A7*RMA|>4q)FvcUQsCv8jP zs!e;Mok}g+sUu|{oar&Xkji>eo(0z~1)VO{n@#>oEwPbMyLV*Ft^nV;ezOQ{g}=T! zlO^#MoEiSPon^YlS6u9wn5BUbx2adx)33DnD!3hH1j0!j&}sCZ8+=Jv740(oRf3*n zI}F(p@-MOeQm?x@P6s1YGa1gwJCQn1QaZ2u9pwvI{|o6CgtYIxy*dFqYm8$e6KOzb zI@gbVzGb^0PyhNp(p${uifzFa?5V{>%jW@Ch~O<TCB!0OJ_Xy!kUaf?I8A&Qa2wEQ zxWV*W`8nlB=Z`c0jRGHEG-@HEQ6t3)%-O4yL%rA0@DCwvEcN+pxAC?C-78pIO9aTd zGI-`)i2fQWZ)iGF+5Kxjj6{Wbq`KpaEvg*)PF{=h0IE4D&U!bP=Fs0e56ynkPcXkB z`x2P?#0wt0YWs$eBUd!4BLy*EJe0~PQ__j6{{5*-2cAsZa1UcM0c&-3vUIV3#)g@i z&I&#;mPJWt26GPHR0Z4<AIHpz`<&5bzIkfe_j>(d+zr`moX#~dFUF~iHqS{{g5ugX zKAAmNb?X_gCeC+K$9<9kx?kzkm`)k?LMm(dHg5URi6~#&GTz~!u-p-o>`vxXcQJ6N z)+gH$Vi7&Wj!-b*5SW~|P;l}&F@6{kke-Oj8M+bN^euORGAbpmHzmg4EGzL~cxL4e zBqaeq+i(S}-nbMZE+ZCJXriJ&%1ES{L+%UdQ)Irv57FPwsA>qrvT*<kOnDR(iqZ-O z%x+?AHKHwGafM_!C~h}1>l0M#oyAYX7)face*<bo4U5+z2wj}t*|nHVqFLC%^Ss?@ zamyQTs|UT6n_R*xhTCVZ9Z>_6d^qJ6O2zy>5haepvl`e6%I!SYr^D;dSf^^*WnzrN z*^el$>l<GS*|Z$VTACwsCXZG%l-Q$qXo=ZtGxbt*b_WuryZxQ^P?ttZ&*r5*FeN}q zB8|-pRniF28RIPCb`3hbwl-zN7fG6VSG9FBSvBi8NSr+3PCX%b_vwS`Y9Xy;hvN`$ z{jBFO;p-3m@r3~lR?#ysz(vQdx4}gMPn048aN83b;D~w}&Yq(_*Ets3r$6C-70wrE zZu!d*bJ9_ShF5UG@|7~>1E$&(ereaTLC~>>2+v+YtfXJiQJ6#eV#r7{SN&Y`2P1BG zD%!yW!=vr`mX{y-_j5~fv|^uLr#y^V&AmBU09*@*=^T>Ti=Z5%#?0ljbPV2K+o4Uf z;>mN`Y&TTzOCTy~<l#;K65GLjE~7kR5lhh9f+r5@qVyXQij@q&<@8{P=~VdL<2gnt zF^F2iy6lohNB5@qgVc;*TK@&K|87m8-zqyr1pQw)_M+0Sol`T}8=VBs>zGG}kJ_*N zB|!vh6`2;;LVfA`#7<$V7iPvG$^xJZrF`t_6s{I%FIVlKD&hs2?@Swo(I+T5UOmB8 z2AsGUp7CO;7DudKZJ8v@bU6>1nL^cm;9(qG<#t6>HGd(uWM(%!2!uwT41X{rCo~VK zPx?>cX%qdoG`Fa3MD;%bF@0$YKwZeccUTw{p{98jzee7kOms@t?nj=JVLZ2fx6B~p zjjtUHu#J~1jWRF^v?n{}aOhUzi#E0-rE_`EwnjZ9t}0{I%7pyj)YMO9WVXbEXPL`= zgJSz<)%Z(8$RdHm^rjfs0Psto867g3s!a;UnUdJUd3=>;uc-zhTA8STkg7LE62a-u z(H?b73*j)dNxxX@?hWcso^xq=AnWs%E`~e*6hPK?LAk=$8H!~)l$o6t=)y2yI>4om zhpQj@{*=*DI7c+_#mbNg{_a&=_Kt@5zsob(OT)|TIYYQFr}snxu)E!iYFkKH@<9cT zAx<a0<%VH*#_%vizTNI0y{L$*MG#aZJR~6e34wu`faVSEZHh|{HP?IR6JMUl{oA+6 zHPhewLRLbRk3NRpcn0l`h1I9+T-jlp%ZXRe32-ZH%Z553XPGD$O933Fd<n?eMem1r zBe4|MKH=>ebf?#{O(0KIH>4{W5eng9`GB`ZO|=<?1PfAAVZvG0Y*#RlOrK?N(VHce zB{SBkZ6shQ?oXC3;DizN7hhV`D1Dwr;~&XL9r-xD+FtOtF|Q;}>8Q_ib@pBA0&L|k z2AosjPQ`8-ft%yEOs@wh^UMNwCkcF~cS~!fZ7Rjz5KVMq-NpXP))=_^n)A-h9E?Yb zn|Y#J*#RxM81?;!zc1tA_oM<nBSkhYUT%ftX$59m>Q~(`Mg1-+L%)kc++6@ygGp~Z zOLA-#GQ4(XyC3D){ylxd+%ugrYa2mdZi-qf9a$B4^<L4xSAW+*FYbit>*suff0-VP zEP`A2)H#bD`I7T7F_rf?y5jR!cL5_$UmC393O($XRa>(3H&QwiTvv?D2|D;OaG<y5 z%gyDww?VbHI+N2mN$%oBy4N?gU6r%?+cF1Mf|UWw0_)a1RGu~P))<dc*(&!@cxeMo zGB>B&#V^J`)x~E&Z|@~s4+jvkoiCH0Ds1liY})zlt;#UP=NDt6vL4tUu&uM^qhv)q zeY5@j4!S|`*N*OQBZ^or3tlfb6&Do-zy@Mr?5|-`+7~Rd^CZHjBhtiISJsJ8#VZ|t zj<1?~SBH2ejqC3`Y7<#Z3DjvDUC>FN8@cz8LH-&aLyd1MwB$#xtcP4SJYS&2@&1uQ z;iKj4#&jIhv%p>$sBOZfGN!eKxKr%_PTf1Y)U@@)-FlvnKWvPqr#=T-zFCTxTSTIp zB)(?|5l~lY6-PVC<nm69pg0+L2cWn;$F+Ymlc2+_e0ZJc^O}I6&z)Q$AUHC8Kvm)g z1}L2TmNPO4p0K4*hXS@WyOM<xiN)0mmDLBl8&#REh|>$fo&NYgWdYwCYus+(k2Xj@ zh1M@zgJYydHEkd2egGG-Z~DR#p4AwFi?GPgA?|bZMi>kFHx2kXUU|khOt|*CJv`ah z?7~I58kSYN(;DZJU2I0GH3vwD5Yf(UPj`)Q>2p~zU=`=+p<HaCTtI(LKEoXaZ|;OC zsE%x7JH*fTVsr?O`b+?C-$!$zZgL*%ibd;_w$E|?G~Z>B62ZZnAlQ&U4yLu)tu!?y zL)y5;k1Jo?ly!%NR6A)b#$G}{#ow*YoxI3;^O<6!a`HXF;sc47rwg(ni;T(~-3vF- z+K^<;6QZX;N*v28Ygw)Zm=YF91JVnmp)@fm%6PhDqHZ8u-EF<>(yfMVLr1vYFszJH zEHhD5`=@YS_5yCIdnMSTdjr{sLb}52q)bx!6cM2q)PSmln}cZnw--jPK^@J;W|*VI z>qIsaykx!Z{g0Eak|`W^&3%sP+_uT-SKpW|l5)26(jXRi$h}O&i7r<lpDh*bw@!ae z?n<KZ8U|lg^!03;DJD16{W4+TJqaX37<BLOF1>Lws`k>qv`+{OcP?XvyDzwWGOX^| zo~mYaC?<s+^ANnEhD}FH<b|{k{r1pmA7yRz{$oU|s@twL%1tx-FyIX(&Fi^cD0iH^ zh_<wemfN$=+3SE*;)#5!K13V!MBh=h{j)thWb_+wTUyhey#2V`*V*&i%hpz6sypGE zf@38>`37&ik0|8#R+*KC!)GQ$alZ)37$w*6ncv<DC#m2@q^!gj_Itf#p#3*9zi;># zUV4vL6_OK$-hSzeI`zk@8p_~If!>$Al|RFv>9DE4fr~=FzlIsjF6$VG9Io?m|9!wm z$T?@K83i2dhg6P^RDyisv%EA7C=Y}j1P}^3+qHb3)jMU}mW)+vH=ia?&FV;{K0W>x z7`^!0Bcy6|$D6@{I^exKdR|ukC-)0KqL2p^sXQk-0*IFx!@#>y#-X4wa2y`g8XOKl z9eG@g-m8<f<=m_4{%V-(L&e)5?QLxx{$*tHeQD6S&t0<2jrkuxb+Iypi{`ndj<9K# z<|U;DqS5=Dj>62f!CsXz==^O9zG6U$m4y1pP(sJMfFsClsh`d4P@+YrRu<>029Mvo zNvtE88sxBVqCqp94RN(7+sW6yBwU6h=it7?8paeq@IP6T;c1SN>?6<_?+AE?^G@sP zR#In8V&+h1RwB)N5;Exe^My$42t5w0DEhHN{;fv9bouZj|6JX_5fXcu46IX4@U9ik z=~=smvG5x^;U3{}RNDSf!8ObW+Q*v{)Vb%~yXO<C>ORJYAmzqIjBm0f`7b)y>zsp> zu!5z(s^}QoAcHlqyf3r}INu2lJN}O_LpQMjc*O}Ok-yvlf>JY3RaI1LrRrd&D%}&0 zCnEp9?w@-FQRD{sKkZt+DSj{+b@O=G$+d=$4={)6OZ9h&=`mKEp%Oq#)Rvdkn%uqK zXUGj$7?~z%ra7tgz|RcwH%H8JGcJ<ujna4guz3FbV3ESzm}(-ZA*qp7^8p>KXit@h zI&QuhG09ce#^cJ5`7+RFb7x>v3jAF4n0<rg6@G_%1Gr%rJxB~qM;N3KA*(>%Pqkyy z-g$hjY-b}%Kuy=ujs;!~y;=>>O!yHhR3K*YPGNdrGT7N~=RFY`{l<ID1%mRLOsYPb z`3r+WI}}W9Qwgpf%NO7-k<8&ExWPm&gANsMs|1|-RI}keFs#WdBf2XK+3OO3tu`$5 zw7btn%aHPtljrfnOa^G5DuLNKSR4&5ofofzvSFx5zN}uDX5Uzgj)#71-up`U&m$jY zx)|05-2iz$=X-mmfq}wkK^9+4EYaR5Fy0gnxKDv@$Al3QvPOLix!Z5q7v+jk@l}Md zuBoFzhV~gUAVMDqvx4?5r?54Hn(lDnAm{}@XrC>k{3GA4`CJhERA}O(o4Z?B8-()0 zqx+Qh$daCU*=5h@EwHsHN^sVxjwe5MsMm0;nFFtrq<^Y$*z2kIZJ1`C+PZecH&Ww{ zH-@hy@~g9RhZAQz<w`%$cpC_w-0`0w!{9}EsnE$UDh+?0rUbIBO{*zAeH#Ql{{1{^ z_FSo5yKv<Dn~+;Rakl+d4)=n~LJ-kGM4u(Y^Vf4W%4$<0iZjm6m{6m=-qYwJ7c%A8 z*3qQ;r+ESBn~0NU8L6`Si+Y`H&vfnvdfC|sBdYg{vk^8+7RzxoDXVhyt~^{c+{yH) zdi`j%hPS0m$<wx+o?)N}y=B=uhstC_%y{Ci)0r-)*I?)U)$gilZ8LwVI1ly98#ZuH z7Cet3Bn9mL+FPK(U8z_^`Z0H%cw|>yyM+<6S$Bpy1IqSWnv>j}miJQ2&ULk;5*ey& zwsW?r0redC{8@zgj`f~7IeT|K0v-n<ag@i~H9mXRf);1zuB$4N&gQyRWmWcmbk)4) zWy1G4Z}XelpNR{EeGGi}?l^ZRPlC3ad+J9Dn+reV9$cTrJJqiXWy^mG+`A4kZEJ}| zeGGGsw|g}Bcdxh#4?gcF$uP9{u7jMn6{opJgy}@uK4{*RS<B^5W0V{w3c7b(r^SmJ z<;ZV)y&zOgU-=<GMENd9SWQ)B|0Q$=N!T1?km#i5t(SwQRpWt2NS7fxb2^xF+HnFA z^SrTuWxs@%mG3|OKL8g&=)UiI{y1l1mj&Ru%*t21PH6dSsoA~M^3GK!ccyv&P&*Mu z6xuJ<=!Jq^gqeRd_2-K{iENN7LI!~QAgv_wqx0(9gB}JMWRO9wI2n!%x;Qdu{qmGy zhjM>$N$q0ayBylq^+?Qq+Ve_{sMR$O9GRSUizaLdEWbm`b}3)zXqmw-Pod3f65_G{ zg`F&FmMt)ZPWOq1t8yMA+p(&ukf7Irz;S}zPZF##b9=y;06afhCx9p*z&{1Yu6iK2 z=@fh_`r$_(9EA4~d_a+LMO4_2{;wFn>f68Vw!$DusRyOhdXv58@wAFrsq7QQ4F^J7 znn)SVi;Or*1DEK3E2EuLW*T8IsF$zP+gEAJS?1zfkwL3i-q$$6IshMVjuIn#fk8e5 zKHwzlz%tVUm^Fsx<6Xx=*1$W*VJ~KeKOL<?^jP$K^daz%_8gEeZ35g*xJi@({5O(? zgK6^jR`R}_nac#Y=V^SM5lCqMr32r~zEll>->v|_>(`}s>PHP1wJnSVB2}=fT%Uyn zrHnCrW*J8%<%?_#U9-%73mj@u17o8NFrPjzs){ArcU}{KWZH1@K;3w}u0INU>W>2p z<F&E^BUDnaZeyorK)!P9m)iByE&v-nZgrJuLrqj`0KeL?v8kZQu-4c7a#4VPQPYpj zJECs`Y;E^@^9dBL^Yw1|uvu-HXAbq553sK~`;$4o7qxM;o;kOx4^0|JqQ$?0j`Ipz zyUtpc-vyAbI@r_9vFEAcNmX;iCs#&)9e}S|*`cUCK|nRcxh4-X{b$;!Z{-w^l+m8% z{I}^u7TJQYT{%RTd4TqHo;r2(AKB=qsxj`g1KPXU^$b^leLF9)F`>`f-pVpQ3>!Sc zHZE2T%;Ga=D|GW4m;NMekFe4{!_pkSE-ssZcHc2hrv5r9)gZL`zo5Lq-+cen>W9h_ zKcr>cstN=E?fV<$G|te0^i4gssO%So^EkR){~k8>r~15UQt{qu26I{K2g))obp_5( zEhivKN8t3-KKHHl^IV_RcF?pDHMGQOpZOT<^^H0D7W}DYp5FwN4~^&fMlY$1@-&@T zP(Cps)t9JkhiM5&ZR@X9Wn3sT`YSCq+WSM_qPJ<u4^`#KWs}MbQkfy$4$KynnX#~u zdA{84`aIPJkT)5^gHk(}?NL!=7_S=dn85g{#lvMo9F<yjPgTV0lyTdyIEh46<OB6_ zs?8roP2Nsu%<^^2^Ha-cs{DIc$oTt)Uc>tQVP}9mMqagU-c)tsgL%KK7=P&Fnw+3S zWqBDzp3hC~BS=<YwzU}#5N$?VkTAJ#0;7b<{S@aI10S-?60na|R)7=C*Z@v)n!Ug( zXYqlM-x34eJvNi~#y&7J`jZ@pACF5?z<M>KyPw&iECA$FUy)g!Q)bT>Mtl&3d}vBs zBr8uz2r6QLD2z8mWt__GOb+;nLE6dya37?t#fTx$3^K?dgBSzsD`B^xxJ=$L$RN8T zZuH|1@-nP<+nBM~xG_Yfs+O}eDi!q=?m}&gU8&vbrH3?u==bP3ebnCuBsZV!J08*Q z4#cWwgcMf0tba~>AeflTf0|@O(^2Tn`mf@`2q+%DJ8L)!+FbAqEt>X?{wQCV5m|lG zcu>WJ;uoO9d7>5s;vmuL?E4?xe~{=uy6Q0|5S_$l3wV<Ixeb^mOEwz_#^em#8*Fn1 zn6k|TIL{W6n6W(s_9dUwgkfc!Ny6kZO&D0>rNT*)>Q9)^*-jYMU*Hv909FaO4%lX$ z!@yP&`99<vXX5uo6W|_>a*&KUC3=jfc#E7t=H2N1=zUGEPk4`cKhVlIVu|a(8zBjR zA9*)(gZBH&e4mgQ_8o#ZPL{k<CjKW`XA4k-Q3y=f_6{b$&w$mWC6iY6#_VO4EIAz= zFrWilC?;Az93+hR5{XZ|fgu1!3G@9IID`+}%^?EdJw}Xy7dS@%947E$Rv4cp;6ZNS zAg~z&*zvtX><8}-Z<S*ZJr}JoAqQ~X#C7Zk@3Y**DtLEst9L!{7t#BC9hh=2F9Wlr zMQ2Q+?N|@VVpH6%(<rQD%aWcbY|xk*%s1%<1m6I%>kA2JzlR2ZU1>+dRvjfgrMM8O zN()2zhL7U)X1|<82d@a$u=n3p0HLO%xh)b+OGk5?@vSzBS^@Vi^L2ClyvXrD(yw?X zKw#3?v$QIexgo%lrT)75Eqyb5`wg|4&ebb+?~z>r!PCy;fyIu>+A`Ztd$Zs9^8Rh- zr<0C;+;v>*TE4L7d3&=TxiOzlcgQkbt)TCXxVDWIeouDfVpm=4CTtm(?7CO2?1R$y zyWd%_Y?!}=t@T|mL17zVxhB)j&o`NoRckwH10<Fm{H4pu1ioW`&^4~tov@?lE9SL0 z-}02c`e)fw+)!5FmguElc3}#48#jxVeplU&^PYTX1DH+c%nQkmc}G>jm|Q<jw|Qc9 zKFPIx!a4nWGN(W5{@d+2qLrPihW<&m@SCdnrn#Xv>^NFW=Z6!k6{tqLtlALJcKjt< z>Q~o`()8IhF0pMWnl`kXYOvFg;s)`ixHEIS-gmVB&;Uly8v0pTqi5GVNLBw}+y3d= z9}9;K_PV`<j(+1?#|hPp{;C9=uO6Stns{4P9>4S+Dv3)}qu*AKN9y`PHzxJ=^R=e_ zvlt(mPV5j)&kY*JkE)?QGm1>+wsDNKZhTMkk3~SdS>9<yyy%0`er6eWOp_9u&k>s5 z_57}&nC~Tfe!3ySPx8QVo_iV-^+cP|hm646%WCu-aMC--eqfnx4g#ypyrb}`&-}^t zfBzUnXHJ~@^S!{${I8Py`Gsf$2=RCwn8eKQOcJ1bx-nv`)k_-Xj{o+PQu_tw_Wbu8 z_#U^KH0nz!f1T<fzAxV@rsc1_AZBon&QS!q2bMTlWtYRs`ye}%b{ymi7w>lOGu$}n zp*I;Akp~%Mke!P+gA6iAo{;F@Bg94V>tQT^DYVn>n*plJQXA@`y;nHdoxf}KCR+K8 z-*fwPoe#A?%3fTy{#*};x3#INi~_Tg?&>`&EHQmox4SgBQpWiB+GoIs0JuH*9O2`i zg2%23gO^XizscHk|3TQt@dS7+GA5BUah)b|tL!UZ(5+AKx0MMKX22F(iSCx?^v9Hm z-Q-CM3+<tQRxz!Y`PGZ<p=w&R&Tq^2>-_Nfr_N}kmD{_OBdh`MC!a51Zls{VG{27n ztO1h!-ZJnGljvyjo*8hSZDzojbtb?O_Ok}u<=x5w@czqaDLk>90O6No=B;ouwcL0^ zfFcLBtAx=#q_}w|Ony)8I0d|;F{`HwETW*7xW~;GSVaLim;#_@1~6V~-|GxSQ;qpX zXSND6fPK*tQl>F!wA&07h3E`Ys?rKVgePjo&C?QdRyFgVDlI&QiC)V6L0zOanW<z0 zVBTiQGpbokgB}6kDgopd<24POnr)dx3lhzW{hn85;8Tr#atENjje*~5!&KW<@5<rV zX=xrvL(jNV<4jdMKbcy_OMZ)|i;m@LSJ!%=nZE#iRej?M7@2AQ*k{S+1>jFh%)kBl zLN~uEGg|J<ysJ7+rTuIFv`bA<L==GBeh*KqA6E<Oc)Q6yl*0_GEx<mnw`lOcegO8< zY&))Ud`~+qho$~rIG0$p=uKyifckmcZ|WQ`%5mLger&h<e&VrN58HUNiZQgy$yt8G z-Oct@-9JtX+sNmOm#U_HO#5|fjpq7IH2o;2=ePmrXIkDyIoh>yYESdTD%bWbdTteP z&s~$n@++;M3OYynvVRMU|EU&FE&G9TvbUx<?N_{CIL0^Eex`c7r7BP8kj~y^_b*lX z9JlC`&QqH<Qa8;trpCs3*Zb<~=VHf`3O%aQOs(v<VMTtn+TV*$DaRdE3v|!llb=8+ z9JHY<jL;^NzpQyuRXxi6ud4N@iBbNh{xUTDtZKZX$eHW?>^urtTaUW9S7k>NgE`-f zqvnP;U&~*LLRm#+xlMZu4Z97s6Lxd}e!kIC8Tsbwyvo$bzhMFH&nn_Taf6nsoacrX zZTc2JOyk%rdq;I9Jv3TfR-Cw_jNgUf*ZLh*fcUsQ!a~34m-2_zaX}iH#+-q_>{p`V zIm*IVA6D3d{=3O&pT^y(cE+YE*j-USp)o=a4M4msalPjynF8BIKZ-VDLLKiA>udn0 z88HIhW6Wt_IsSY9zQZg3_7Z$@;xA9W6`y4Lse}l}<2*2BlPzGzN69;8*%}5~URf9? zh~_|cS^BKLt_Wn8*?d=2lF6m|@-=_cwW6~8vn)JEABXAdH@>kEX^=rW$N-8Nq`l1y zR@0vhAge*zd7tXd^3-61gA6jrMUdSyZMi(6pIBHsiHlNpe{hjqX*n0m9(J2us9mHl zU4l994;Oqwm){8UkPC@vzC(LlF5}=Tfb*=SeF)<yQk#BEK)uNrX#(eS2Bl&?!Os$| zF^9-lWB$%Q55l=mj(&9VARN7F>>UJFIe-r=vy>(0Ltw@lKCqQ6%>^-|inbsUXi4&z zsXb;!nKA`7Im<fnk)TuH9H%*}{eBR*UVGmS+{|sjUX}@o8O;@NhE2ACDO(9s_$&dy z&k}a|I5oV)2%kLBe24?=BTw-A83&63h<?UT`5`ci;_`%C&#mYSDq&%PU=}mZN6A8~ z_e+f-JWePV4@vg3rJA_CRv9xQUszC_XA6Dd*UyswDKkIXXR3Lbe15=IGyyi5@N4i! zNh<p>_Tv*TPy~s61i;Bek6YPN%VsnIK8((=0=yMXc@^05&T<aeNVxMSY$Z<_Glu9D zCVURq&xl`uw;I<s+9dSi(*;yC1$-~aHWs7{X+^&hg+zSHjAI_Tnl2b9gW+92s@r5{ zt6KQe;+H2VGw#`#-0ckSHh->-zn+YJH?jd@lKAcUErE1?$9^cNxUWk*mpw5-hZg3$ zd8J7ouH&NRn)Ya?FQ*ZZw`%n3OADIA_>FzyVozFe*ITy@11_Z%y*#HnFL<%X-SaXR zchy@PyAcZ*mxl`)mAZ_>cXB*jH$GovIl`73L>BFj(vcCi$qw7bJAV$pT<pmX{cJE> z)cj8^$bLdgd4f5;q3t+AEy(TzN4<7^zTY8^i&j3in5blq$NUyPZ?mJiYki0IbkUA# zX{RB5owU*|KKKP#RXa<sW6bqi*-*1x`Yrsr={bFjb8L+Csse!7#!u(TlZu)+tQ`H! z7MI!*arlk#s@*tNb(}BAhW@$fL=(U9ifVnxj`r?%9A8Msd8};NkN6EE6J@bG<yeov z(h|1*xov;uJH{6sz&h`EM>vkF>zTLBjTmyS`GUEjL|OX*d;8XJOcAwA^;pWM6EW1s z*`|K9tmmrw+8EZ&69*LYF{ih+zoxufU3=Bpo2rQe)qb1jYm0gD;(bypu@2xj0pvmQ zclwzD{G<4!*on7~IRCvFZ3Aan_YMJPILik3tN+%^H=c#)gA@PrKR*SLAAO3mz}NXd zuntW4IEsPpVY0q3GXVWLkX$cU6?41J#2y-q^+EC+-A?rSk0>&&hgt?%IK*4kct*j% z<UYs((+h(PqRUd_&~K1I1{q|K-6%UXP#jLC7-W#$EB<A&Gr9|N{ScXU!oGICpST>_ zbsoTl=&{{Y=llBw3JS-PG$l5x?5>Xuo)-)F)%J*ESsDXYdtRDMoFz5$YjmVD?d17^ z>g!aAStL(i#);Ax$UaJd=#l`R_~_3R;4V+WLszYgK7R@hv+tw*2VsI_n<C&ieSXR; zRGlC#0*%Xh%7NK!dYH673h2g=nlokRWv=7u3aw-O0%J}THu!aDL}X#%j}{tpP}N2X zq4`yj!##bES^hBl3=4M&!){XM<yi_m_Yzj~XsnfIKYQ5=tg@dFc!zjFVIyYL_nzg4 z-fa+_<zXbS!8Q}%G~3Yx*p4P_6K`agku$FeqvX<H^a)D<_M)Aqi)1FVP0IYP+o|p+ z`TMfJqKWZbeZeN6`bckS0ltUUBc)4L=Lv{TCEuT~VP;nloyHD?a9O~01-N$sNHo;5 z({q{tKJ9^GU4anpv8Ig#g)JBD%iq^*qfa1v-{VD{A-|7t?E=QLkp&3l`4_32%6i6& z`}lI6@~M`<J-dH2`<s~4UfcO=eK~eIKUdy1rFO(W<^dqKX-C&m_5J=u1KCyQ^B(Gf zgMHe66~L&E{>HWeQ1uiC({Y+=nV%Cqwp-x%+<7<J)B(g)CqHX?em^HnsM3b)e&UjO z@|EAy^P7QZ?m*^te$n(C(JEf_F^;Y-r<f}~C<|lk{NtV`KWXpZqPAV!@@r|k1aro1 z)iCdB-@bN0dz=1QI@(Q}jR^CM^JGu`dt3ii1_N)~@vGlryrSn_gPQTFvXs4gbAA)h z*`DteMpjVO>Z#iPZ245%__OVNz;9_6=6KuoKG%G`>$-%w(V%HORvsscN<Ev`)!DgA zoH6rJ(y=~G8x5MqA!P>idb^Y@+q-E)O_LqfS%WK(zZzig7ST;~p=xY5TfCB$aaoo0 zTeL4>$(!l`cm4gs_&p^$NeO#K_{@N10;UkX%QgzUgVBeCz`C~&1*|iPP5?7P?-)cc zCF>3!a1Cp~h^sjPoaG#6fo(2u9+<Eh=e`r78~9I?&4XzkzsSs<uBZ4}P4e>Ud1$G@ z@`d)hncoicbr&zy+#Q-8)4cb%)Xru*6yKl69ceJ;4>CxHw9_DixQw5dwyyt|cMf{E z=o0MEd%~ex8Dx+hmBHf%8Dx;lF)sDBus$%n&)W`{Mn5yJy_AnuzP$Qj<-{4XGyda} z;O|l{(X-tw;=~BGpg7m8b2XQ)W({?zTL4uR_sfbSuJ!lmz}gttE|TPMkR@P8z?cyM zu#^Gb{e)peF$SLCS>6O@jMxTFah!v|78`5<3ZH|(cCv&sAqL;atm&{t$TBg2c}mO- z9s`?WX7v>KJWYVkn`|>n{*I3zjTz1-$>(eQhBtwO_#7Zl>h5FA3PjIFXQI=<j47vq z?{Sh%^2F_1yvI3orj_$-kORC=C-q9-zmJ1l2TZ&J3G@6793^ImpAsLHJ4rOJz*|n3 z(8HL?ov(5xiW%7BdT%H7R0+_0KP#Dj;&xj}*jnPhZ(vl2JX6*)Rz5u;o-d%K4E19q z@LBeGJ}~8Q^g8ewD=YyYa25$1XN`Tp*jr)@-XomhI^f&hAy$DY2N(m=yO~w+zQr21 zLUe+k@H#}dMBii`xDU7ixP==z0Q_U#jn07gCB__sXgl{CZv+T$9K|*g>oMlMuLATZ ziGHuR&|w19O$K#gED)rrfBooN-FNhbghafmg*F`!U&Y9!tl#GgmwNflg`fbDF!<Lq zu$33I&FktH!punKx-ez~?gsVuMUMTG=R5Q>U7$n0r9HaFbX&BR3p%-^EhFE>nn(Dp zHP-I^HXzVW&ubd=;;mTpKVDFI!#SBb`<f?SEW(A*ktuX1=TEkicosDuS(N?H0|Zlz z<){Z3cdutVJqJep7Bz2IJG2qNrN8Lb-}QUKL)Q&sZ2@52{iOd5WG2vWG5Myx?aWP| zt{eBe_7i?jaml6pi`bwf99!I#aKP;M`aHoz&>!=>%?`UVXXpKC*{<e0>0;h_K|7$W zd)#gZNpI>mo1WKp<1-cgr%O45nsI*9z50B#uMK6cdC{<C|LO|dPXUu*O$4xQC~3nW zZ{{Oh^=0#4<#?i6AI#~Zg>RMt+p^X5O(*@>PV#fLw>BFsM2mTrD^NAm@@J}H+%IbS zcV+0wcZ|ob4CJCgFRCSzeG_2Y)}MwQnc`jg0i7_$HSW}HXspw>-fpU4zUtDS*!oS; zK<ts*l`7byd2%NPu?`uKTqf=0CwXtbz?eQsGW(O{gxF2C*#^$D#U^lu4K`r^?T7#3 z-#!7e7f;K#J_OEihBH9Oh3ur#_ypMPWPLzo1Ph8H;ZHH|Tx6bC*$KM2X3W2ZL;K21 zPkCGuz)WMd*Yzt)gf}vIPD&JXc@Xgpa#3UexDV1wK7Q-kXa3~LK@WorGRPo<400)m z*L)=Pu&v^9m7!%9CXwpbe?0#ZXsz8?!bPP)cFWQAi;C014!zILAX9H=%6UoEb%A?l z09UqhFFNBAW@UA+sd9R*a=K4v4$s@LYzI<fyiS=;B;b2RCiigyjP~Q}<jb3H{>6j9 ze=8I>18?#^uO-ikljOytIL)I)g^^%YMj7Rt_OFt1;CRxVu;^8FXpiD^!>k>Y<#%(5 zOjX!X-e#(@Y~}3?IWwHeWL$OMtsG?y@V%p~0wVH_>r}?%u7EXGJs+4bjz)lDt5Bxb z`Azg1M6ckp0eqEPc@(_cIKs`qf6qPMjX=N(KL+os#Ek9fhK6mny&n?;{-?my`+CVn z(CjPZ>xBi69N=GMa1V{|MTzOkO#GX6nOoD3DKD($M}(`&BX;$8s>j37!tkW53uZRI za62Lxt(;YHRTU2OZPQOxzwayc{fYNg$N2tLi@v({6RHCMq6>3p-y64@^d5A6uIyaC z>TyN85n;H)CkfdZjb$tS@5DH!-j39cmQO91A-nH!uw-{^3^$nrcY2;-wy$5a6-O;- z{#18j(N4{K%Rs}$oj9Q!^wo7kaoE7H>iWJeJmqbfz1!Gzd*<+dPn0nA;&*CwH-B~k zz%{i~-y6yMAT+SqYd;&NM6dar^0>I4xD#5(9qk#++W_kO-aw)n#!F$#4I_R>yR~0C zZ@(;B`JwA`T%Q-V&ZCJ=@ujI;VaK)zE9SXv`r)=4Q&ofiy8v>#_)pt7<9CdEvf~CU zl>rk~Cp!&VUN0Nkvy0zX<zr}Mw0GNxU$=qK#Xe-q>w}7N){O^+b3AOWuK+@?2vBZ2 z&Xmo5=QV9aX~X2+WcSANJ<Gf<GOzPnwy%D&hN!5IG{)Uc%>2sYPfZ(2n@_%SV|H(1 z*!Q)(XWP+|aExbFL>lJFJZ7A%IziLSf9mTBX_-bEfIR)(2gb>Iz?cyu;0ufs0-Og~ z0uHg4Rp2;Bcoe)_ILZ;=R<7q5Tz$u%-1P5W2Yh(quRb^r1Vp?HOri}|fMxzwv`tKK z6X&JP6GugX$z7J#Nz#0_ECBgUV1LR8A0`%(ejiZ1@dPf^wtv13Q*BSP<b4CoeUOgn zw?PJR7H@^+%45g}8Dx+_E;X5l;dQsj0AL-YNmd3GTvC2EY&hs1&v$Y>yszg6uJ!!9 z@G|v7-xF7?ABq+;cy*D=<+`jQTHCYel?gMP0~jbSK|6BUE>Lwv9aDRiOttH(f&M0= zb;|Iuk|l&=pu3-eZpA^oFNKeNbo)WP|IvR$90q>F+etef=LoRLCY!)ECy0U2O9)^& zslhZ!n6BXyCxjI<V3lQ-fo&#CfhEQSkQ^{dl8(+3@=M5s4L<)2lX8pXIU(>S=h+5t zzqiC*h^A4>2)|XR|8Wi_u|L+s`v!D;Z<2SJF~bMWbB4EoNfej&7`O2rFiXn6&4fu( zzc8;?l>F`eDHGO{-xaXQspupzkURv=vE+R@d3*f+m;pVtpR=4|iyR;}P8i+Og$G%R zPm@HGk{R#|K8QAefK!|zX6{$OJ={b9yvAwPfu-m)BZ!{#-r+sq6;4EFfh|Ndg6Pkp zx1uTVTqO8Bct^Zbd>+KA_ia{z6@1P^^lRSXL*S>}z&*g;WT8Q13_W4NKhkztN)`%2 z!;WPIBfB1-Wa%?!QYvn=C@!!IBjKOgeyA;*R57gw2GhIkXkK4?zP<pd1LI9UHDg27 z0+sD|)wm$)1~dqp#se+mZT`M)OsKYnMcFaVH*E;$YkcbpuuwbPzsX(FpSl8GE@sZC zZ@b&cadXg{Uo_p<Zf&cX0Dull@H;<`?P~*$YdO>oGxW<j-#c$R`n^P$`SdC1wsLD@ zNOZa0?>P>*$F*vWbzwxd0pFDIYo9%fn45W7Sv<h*r(Kxm`v)+0J8{5oWtH85pDy+} z&&hFpBP(2i&@O;rmut;-P>m7UEzSlF(XeZKNb45$cH<pa;GA%@1E2m*AasfQeVu60 zm2qAg8{NB(-(<&=DNQ}Np4^bnlTF5N;q-*iff2f?orObvx@slg;3!&;N4ktRs^V20 zBeN<2O1sZrT{h(8^G&z;e_H@}(?$hlu3to|x_`2-b9k<Kk2ZOEqyC=nV4orZcB=xQ zJE*R=G45;w05`82S>jL1?41&Gh|0K7uP0j`EtTbpI1hN{`rWuhe4&hSmvkC;yD-TM z2mg2VtH5Tr&L=q5kJEzWyY?G!+#+9?S)s51`0e9CJx(f$jPE9Myet90i+Nu^V@6K_ z?lK|tNuL+zm#0h#feBkoAX;aWE%0tmPI5iX*=PfzlhI%B0Yoyon$r-C_-jJoXtM4x zVH!<=86i&)pIoa7V;jG6-9`UQ%P*-qaWjrc63MHYenO2AUT+&^iL1WF&O^gqbSC&g z2I-hC8e|YRIq0pjI;dfgK?WIQkSj#gFjm?X;twjg;zac7$Cum20hP?;#3f&kc1JI- zUDVPBJwGp;b0NI{48URmWcmBW|DV18kFn&s@;tFmTwR4i+1WYioa~yM+Un|>nwpw2 zr(EW6xm+%nrU^nIWG+DygdoTot}F{$Sr)XKcCRdJwX#OgwgtH@w*`TawSvqQ2tkl# zS<uRYAk(tIC1jf5aI{>4%dM%YsmZRXsjbP$&dz!B`pwhp;0^x~H{Oeg7dP&Yh?n() zaR4$a^Sy|;aqqe3o_p^1d{6IM)CVxbeqg0~ZnwXG(GRy@aWB7Am{~(<Rn^*`COai- zfnYgjbdO7a2Vj@z%kdxl)`eZNzsgVk^$Vu}c8GyQGo=*Q7uQWnB{R#+)@2~E=|G{( zc;s3~Krv-PUV?P$Fc$Shfn~;f<ur<F>ENXD&1?ZUNh{AOnAVHmZA|@X$!@5I_ACJ7 zi{GnlQkC|;rh)89mj6^dRe7qKuM7F_SM>KLS**wE8taSkitgb;bPsSJ_o5*C1(R$Y z_%grd67T^&%bUQ*`6{olNCenp#2B)XP7s*Qf2NHL?rG^Dpy-dXUP1j}L?BAcPsMyU z0oa@Da}$uh&eUdNBwA*Osxy^UpCbZ+?TZ7yu+rJ?2h&w6=n7yEoq?y_08zdPRsKM8 zlfU8$3=`gKho4_@wElk|m0S8~hiWL{eKYq<M+I<oZI@4_o~HZB;Bi^ad&xk(SXKYV zhDs`-b|zH+U6`W95zK~o#q-<OP9Ajvg*~B2^sWIR`@KE^l3m_V1<Y^JgWgEb`?uLq z;StYJ20yE-9bE>TieB{~t|e}Ey>B1uwhx1I(fW7=_QwaP8k(3A_i(><J1H7`diU`y z=11b~pR~V+JCNE9_$@6nL^V(hw9jv49S<Kyec3UQ&ZmNv&CdBT2zRYy;nr`mC;g8N z`(~R3c1^G_C78G;9J>LMUG|s4qu)f!{!X;E*2dIr_M07;y<3>pYmz-%d(L;7@0)$c zq+i*W8(I~@(B2fE(e^R>p~E~9z>oF!e_*kLsuquE14Ntbt8g5zrWV`uyJ<XKzSkDV z5(c~8)Q|P|iXDj>q^19A<7yp$o4;dvzc|qDN$@=XYquLFi_tcoO%*ERntqBJ!AM+# zbT1gvi|gea3NL|;{9Gei5cq7c25dz+fz4TVI0jtcRCEHeFLIXCz$4k`IS0S{z?uK{ zZ{7pH`R>)VS1$ounjw9k>)ZgwjMxTdx+1AyM#=(6U-Z{Zw`ZLN(T9Ync)vfGGpARX z>dQ>_IU&)qXC_NM9?ugERPEeFLMb8U0#(8h*^nkPQ2q@PxNR6@5I2AOk4HcMlNW}5 z7-Wz^1{q|KK|JMF*r=p$Q{OipihbQydfLC<-x_a~+@U&?c4Qt}_58IT=*rIRI|{~4 z*ZxQYA@ufxp>E8Cp<)A)_h~1DhfXctwc5HF&4(RjrlkVlUM`^-Yt9ZeXQs{rw0j&f z0saBMA`kH1&3WJk2aJGy_BbRD;GPCXx<ym=8M6R1?=WMXoL77bY%xOt6V2s4=72Fd zv&xJ-U_1pT1p|BZ24i5N0qrp(4uL~vn%O-6{(3%M*)Ot-TmoL^B2(b3W|l7kzOQnT z>*OUsrM8a+h+F}?>@xyV-JWfZa|W12C-n0l<h1Vb88G6I19Cun3XvpbvS4uMN7>JL zksQFCLUu9w688a0_rsWDb6|Ns9vhl5DId*KoY7T*3PAhy`Mgk+OOF-_3~Q|GpKHL! zxi2~iyv#xN3a}TQV*;GYo{Sy>e#K^%Gpuj02GNt8;u!FS=w!|$ADxMgL-d7cGr9}- z5tHmm$aZ;_XCQkZ`wSz9o@AeUfX{J(lfVyoDf>Q<u*TyofcToJJzC4(C!5X_A<{}B zKz)A1)q{_y%;;0}PWixNQOdP?U?OV=D)oc71+YL?fb9!rsN(bHlI`__U0aD>8?dTg zs<&<n%8Wa02g$O*hBVvHqJP9Z^}%-V=m&sx1IoKHj<sD+tz97pd#*M)=@~$#9N(+! zb9{mJ-FI`V0ba&O)Sj+)2xUy{+y6B8<IyBsy7uBKq6fZ!)#iOww-HNw(!0=f&At;3 z;(&SG=kw)?=8@^SzJOd2Ja618frLKOx4)#rJnAyuiP2t&UNtHt0nevD;}zYvi+$`; zSs-z?>*4y;JevLZRY}8p`zBtr1Eoa=ZFK1;5j106nV9>s6VlTz*!^m|pDH}`SQ_*` zw31TdX^m_EVd-ois>A@c^+9w5-b=@M*|p-9Eg`s%gcQF7l;)Pi#`hPFdg!-$EhoOq z#&I=$zp#7mmBXt2?V6}9Jm-Ji{-nB{!f?fc@!3s(Rf!SW?fcS6&(xAWG>@Zcz9+Ts zyS|Tm#a7{6aiu*GLDuH8YW0WXhJI~ZAx&{E^Z2_bSeWLiYr<HwJ#(v|QBMr9ea|(K z!dAh?Y!_sWvAbXUX?jl+QHQkX?Q)#A%G{pJ^-9cv+lA%IWBUtBS&rpSbwqkkS3KR% z8Qs~{=Ns4a^Nn|X_2dKhz8Cn!<^S(Ld=awi{3$npPjQF@_L(pSwn+6EjH<l*y8b!S zKzmtAfRHRR(iiPZ=fHPWBFUi!<Im&Z0Po_h3d6gq_H$O)wF?dUEC{b8Gsqwe0QW&W zCHr9Z9(8r-hd~Az<TjVVaT=tn41nQ5ZbeCZX0RIM_O&lZG0v(nRD0*|e*3cjsdN7w zO$`E5Y0f??nYbK)*$%vw=Qzq0m7=fP+r)eR+}f2YTwzvqrt9gv-_zPS$jW<5Ly6A< zAfIX`k}-#jf&X9h3=ad>m@*~@#OHz9JaC-Wm`6m7aU1H)H$v-@upCg>^dMd8gT)B@ z0Ss(K;`4qf{=Hy4SEcbc0oKx%_fak5uUg)xXivd-U;ak9^r$Me^HB{vA8|LS{$3N~ zdvU;cnlsT3AUK&F2d;8hX~T=WnEeW}7uaM3e1Zq~G(?YZ4`(6DqEAHc1HRA8d=og- zOgD#&%Lx$CXLKS#suLcXc$dn7{o-$*t^w8yU`1L2XjhqRsC-WunA}YVET+%Z(m}AO zR3b1PGzueNz5Rg8WLHy5>0@XIcuP+^x!g`ara{rkMlSvz2ixstMzgm5aA}n<!>X+> zR8LIrWxePFfJDcBmvje#iC)?xt>beP?eYhjsui`%?gt7-z4mK|@LscpQ$MZVfAa;B zl>O~K{LxTgUO&$dONEg=Tbxiv!X)@@Wzh3n_p_>FB7(5aOA$1m?9Uaw=&5a7;~w-x zbg&zJ?Js?qxWf~d+(sev{{6vYngLSD3hYCd$|PMAE`g{^0%x1P`XzEIr#OxZusKcp zBVXIqC9y*QDst<Gq{s30VaRr0FGNRs)U85-!7fCJMT`6^g@yXV-4ddg<5a%!s3PHA zInFNGY9D+nf5}o5NO<gIV^6yw9qp+NfNOeQ?5)Rc73^&GSXpYUHUXO3-amG%1JGn2 zeVNQ%^xiyLsx{HZo{%G*_xm>c+LSmVN^!~Ney;Ch%>IL-oylGV`7_l@jrDdnjax{( zM>@`*x_%{r{;$aoa9tl{O9GI<9B-@>fyf4elBV+u=6}zxSkskeKc&wp5)xuygHMqF zJ8ZED9A}5G0B1SQ4n+5HmQ%pv(S6(vJi&d@-M}vY9%q4V{w3Fd1NKRPL-zAZr#ikp zCO=Ernx79)YiHcZ*uGX<f8tUlF453Ws-&l)Hl7XR5Eb_8p4xrt6-wg)=srld?Z+U4 z*yR;|6n%T>hCv1yWRM=^_Hy3_Soa`<y!|BPK<8GpY--s1EZOs0VVt@%l*>D!AMEq6 zdT_96efDKul`GfRMZhg|yqfwg90=9izPiX2_J`;+@0w-i-KWYE5Vi<pHU-8t1344T zOn$&Vhk#(h7lD%;V+%MQo#qTcw#NpbxXc=GpjRx#o(3=GsR)~z!(_q~0j%pIkugGp zw3Eu=z?^|3DwvesKms$(IFG(g>LaId&itKSW`qJRYo>UmfzwwRW#jz&kpRwW=J%M{ zoFOG;5i~xg-*cv~pCUK_W_gcAk8*|$a>n@t*sgl&Sz4RNcXOWm$Qj&o2CZts!Q%IP zJU8Y&R`~umIH>ebq2EOSJl6drY7FT4|F3Z{?~fD;e)#ADCy0SRBxVa(BW4{)NjR?c z;0<7+8TK!74F%aRvm5L}^wa3G90EHWvJYJ23{%KPOqoLVFFDDFfQy<*Ud{pEYCaE& zfc{kXZxe&NS~}1u-e1lS9-9E`a$b?Z1VE=1$li2)y<~3F{4z07Nh1?d^MUC?KkW0l zNm9dssO=zd*-i;hyCedEZ0*c=uIqs6xW1^4b{zU)ijOVv0JS0p+St;stB$-VOQJ?! z@en&;#ebZ{3fkt&EWX^nehw_tp580=oX@NFualPNs}=3D+Zg0!PxFY5{T%n)4qrgO zJ7cu__=WVFEcx4^dfErzIqms5ZGH*8*b8w>1C&GUOv}88eAa#C`JBEP7Nu8hANP5v zIwl@At$((D@?~Q88FyE`Rgv(n%(I4Df<wT#NBX{59|@8ry^cJ`HB-(0aFlrKn>&Mi zwcnCX^Sv(sc1*t&q+~~XkT&><zWz#~!|iqp0}+ASe6!g-TcxY6c2jt+yFT`>Jwe@8 zF;jRZpu4pr_VhQT15>uCKbn|?)0(Fh<If0h@|%Ri`k}z7!iRKZTu<kW@XC3g=eAE0 zt#P8%(!SWij`;w-P3Hurw{{&@<>?Q_j`Ku#tgYqq3)ch;X-#02P7Ly{`yN|8W7h;V zpZV{%9*Np|sv7NsD#dln;}_SM=gY(=#hqp8{)vvP7ZqyP<`r9|Cg>^dHPe-6b7G$Z zT@iMqncQ!1z#;tZ6My3$pHuLgi+?hCWf$0Ek9A<51NMQDCT>x>a&1A_vKU`AfB!Ob zd#cYhX0>>8nZcdX_v6xzv^=hf{`;CC?xW`StHxQ2#1B~`f*E9xfH27*gSg47yp|0N z?t=_+d&`{y@Qa6`yyG-;$kZHUkUM>r-&*U{u#PN?xFz(Y-&Q0Z`YCSFQK_>gyUYxE zi;Pbk+`rOkd}8YXjO?XEDjfj>t_*pq#;DfCzKIpit0wJK*a7mU1J+cBP-moB4sf4n zrtN(WAo@@FC|7}3xWp^ug+B9pRhd%?t(mc47B2_<MXlZOT-#Jl>!hca3Js`Nt$mPM z^+z?#`sIF3OZO`S$;DiU7C`rU8RI6V^}6mVgGP%I0KD9?CWfQp>hfXTL<jH%6aDNe zGrX$(`#|f#RENR^N(aO9cAV!lCxH`44f3Bd1+M0L!#~cx&zFG>B$u?_6p0D>&pc6K zU2DKh9|+8r#<^a?Rn-12mw@7BeT?UUdr@HsQnk{z#hvRVkdxX$f(gi;EX{Y-I`3SW z-Iw)v8CcL{Z`KX#tjQjQmdq~RFZBe3h6B*6&ynB^ED|m2d;Pgx89jyJ`H6>x_x1Bd zfIp&oXoVZlqF*NZuKOTczr?VzmAmUcsUPP0E?!{>EK;oGecTgTRs#?=wZq@<>!*U4 zI-<naCOrzZ^FGh<?bXnP0axI<?OREMe;4v5!vB4vkmvZ$XIDF^JoG3;f5j58O7x~5 zZGM(%%}}245MLms3$U}xx@7VvlAZw5^XsB^24B^|9<@E&9~f`DZ$*<Li(i_#w$sp( zXu(KpPVg5Ffb=HjRn_u6*LtP;d(oQVK4xuiPN-b-jvv~XsO<nmpRtJp*AMe&B5>w5 z&!5Co4@~b7JKG}>q(8QO)MB6BkDur3$C~z$v139?+df3J_FwZjm=aiR?;{P*v-#7m zz;5Zdo+xL#Z)Wgr`@Xb}w;K@HH&J*wjw3oHgeeDJep6*TpLoXdc(m)+GNFTLZNH7M zK{(hM(Hdu{#>rxf{ZNkcJ$9_=CmP}%!gD-B_9MQG{x*L&E)j?L#Px)=vO_iDqaK$m zDhw8hAxUi>tCEJ7$5G6`vxo;v$^<CIyQTX7GaYx%iEIuTF@bEKeMS)7pXJ0dSE9Sw z177Di*Wq1{|K9!g?EoMDN4po-AiK){imSjw8tA^qh%x9p=Ro%vXgZzp{#@3GTjV@G zC@Y_*ODA$=qM}8G(zkRaUfIg%u4)83eZ`Xod0Wc>a391^UgS-#4BhaymSN!;<n1aq z8-6_iF$WoBST_f`x%OHP`f<yQZ$AKF@wU)wxgx#u0Un0jQF#N5l_4N&K0=h0cJ>RD zFC=NXpFy%+r+!t=_q`Q0z0ix<e4Gk^`;05(r8cMJ4DNe?V4HKmGklJ30Auzz0bJt- zQ(zmR8Qd3qC<-_P{d2+wIfHu)957|V0!Tk1Ws{siC1*^Z0x;EF=!em(q`+7MvlC{- zz*HY$2qw&cb^Y9zxuV}A4=_K;<IzXS1Hl)7U-2f_wH=bc3H`kS;(k>#mZv)Kt*U|P z>|=a~7j=J4fgkX39xU~vKBS4Ho=H1gXQIEKClI70%md%i6P)8%>H2%wW^+C^a2~~k z1;AZ$U4!d$dwh!1+y%%;GuUKb;Rbn0)&y9G>=1Z_lO(`|<7`8=%XMOiz87t>3B;_k z4m=epjsX|4vup$FoX&q|hjS2pHhLcq1K;EKqtg(5oC{2V53!Lw4$*tL#u*TQB}>w) zoA7-0)LZY{%$ac}hxtLm7#K0h4*;@!#HVvTRF&YntTC?Fnc78EXIQV6woOZb^eW?6 z^+0WLz*1#|S2Qz~Etig62ELcCPa3Rc)A#H4L)MtR>Yt02&x_}S`@yuiv~l}^xXI4g zfb}-}ZDXnvj_Xuk{);Q%!`1(EEeU_rep}pQKlRb?(iwu{o)9N`U03}X(~e?)QuuSS z$5etIfPqoG;&v!+NJlrlH`zymTG2hhrtf}r1(c~3KVMmyBv-rtb73A90rNA|{<Yb$ zr!C_o0`^bJafPzoKkmSY@AsU=`>UXtY4ex*Nhnc{TGX{-NH`OAzxHRY&)E}Rv&ePb zjsra^U%wzWBp9D-*Q4kz$Nn_M%g#Fcm)-qJ;V~{rPkPeE+}mxu`q3{cyU6f0p#HqB z6|CydmcjPN)IR@l?dSd48K^@l5-6vAZu|AF_R^;JNyq)6!kk>y_Fl2)`YoO9jBH)! zF~kLA;666?+<(fz{i<}-Pc;YVy3M!cxR7%87lp^X6ib96?fqM}>#C)nOmQ-08TZ9~ z&525)LFekQYgM5<anp-7zeE|%9hUcL!fV}4JoYI*^TYLe-#Aa`yf9s7ii3)!1ce3R zNHc*+mG~r{*LN*qz483|g1No;yCkn<ngE-uu?`$#iw%gjqMc|PxSKPa0aW$?j{`IA z<~%UvZZ1G}kt;k8yv8oOz;*tDJz&fs6JUc8Bg*FpIRTHXRVXdk<m(lp6P7Ak&Qn2M zNHWrS+@~O5DS+|S#De9@sA4!DAH-J%fcqeR@{)Y;-Jc!0VUV6B9*U3*@-~!oaN7nM zWRMle?QB`Xfd+TRo<{L@2fQ~2(A3*x9(D}?_H74z1M{nVU!Q|*^8rfJj4S`<#tG)Z z#O`$vQrtfjAQT6-qwRjH<lwA>Jd_4rk2TZCm@yMzkA3!c;oWbgzxjc_qFh>2&3{%I zw5PS-i)WP?So*NL>70pWSr40aXu;54WtLZs{ZcTn*O}1$`+C8=t}M1yIs7{{@g!x% zbG}k}BmLCqF&>OgLp0+G2f)vHHQS(iD5_Wh?N75q{`n4@z<%j|3b>*Z3$8NGrofr# zJRb!f<5ye&{u^H5dk~%E1l!~Z3KPf<8Ifo`n*!tLqz1UB`cOkP&Tm;d=%_NfpV0kL z2g1wBe5wPTW$ge<)buiLU{Gtik7@o(gI!rLBQ+k#MRGoxjR)OPVz4vy64y4qsd8WW ztY%GseH*~O&JfwwF4t8y?%9u%f$O?*X5{uuFj&=ls15)VA4zJARsH!#VfrGEz@zP= zCrQtG(D(TJ0v=5(a4}C$u29c?`@avpOgidoU;9wm@h+;v_?F){S^4v2Ykzl{@1czD z-Qp^um-fmI^B`n=k`>)|Rl6Wl!rWTNb;p)?9;%PNOwz8;Qym$i<A!$nCJ?wJK%|}0 zhOodZ&G7*L`wJ&4<!;~HfV+w3`}(#c_K4TG#9dTR%;c#f^RfT?`X)$<R?Tp&Afh@} z_6hZ~Wlwq{dRo6?&k7OB!tCvD$Ls5x@S5+c<NOy6^ComWgoFKxt=~5%bhsqICk=Y9 z9NOuds4hJ1xh<h+dA_>MOOwBm80?wt{hRt%1lTiW=p*6j51Zl|<qDR9HirJ@>*IzB zx@|Q-q+>j4@qOWCUt-UGu@M}p#u|U^c1L*FF}uGeI#pgu<^&>c^Gnw3fnZVju{<Br zQe3sXE{YnHyD-FqW$Bxe9Qa;T;><r!h=Fxoi8f}9HHdbiji>;+Z|c97b$LdrE89*O z!O8dj^}l@PlQ8}CKfUx1z6#lO-p#jx$Jk>AB<yF0<b*z-15!=sGN}RF3%_~MJ~d~s z&)<Jmd@n0Jign#GS?R|rb9-FVuyoE}U-XAG>cfDP8f3-cxIy0LBJLH}qwfy=FvuW- z4ARAv4k;aj9Jvg@+1o>sp$l5|R}EUcf)(lJ?G*3y@wCn7v}eFo=y=P(R)qR8vZwcU zVH9ya7-=sxT>YMjdEGT(*9Jhal|;1x@ojwdzKn(n8HpZeyeM(g<nL1e2*^?v4C-Ue zuzkQD`w;z3wiR84=-XW93E&xi%?aRCbWR6kUjT9j_XL>cOel=B#+_l4F*$?#1UShK z$5=49Z)%8o!Q3to*+lo+1lVRXdOxs6%nT4Dq`(^Mnjt=apI>so6u4hAnosl{zrs(l zUln%-KEuO&n?;~}$`<P^fZJzv`=*+qeT!Yt&!0l{8XxB_-QFpnm=FVs6b0E-_p4^e zkDlNJ8_W|4qI<ZDljH&O6x4M_bN!IOS2Xi_0S3InUPbesWQ$WQ0{+*z%taQZS+_XG zHbm>Jvj#kkinby9IlI|9@E|HXfauda$w^>4`!rX9P1f0f?6X`(0pI6It^i|R<0@od z$X?72fmx<_45E|K0UHp#7=19>1U{a9Ejt6*OMIK3fchum8F}|1+%0DE7l&jAS&=v~ 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%0Drdyt7Y9*RUo%$3EA>*Ei0i<tAuK&4U1 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%0Amae*^$L@_<}kNwmH76D$*y%j3UapN<>s#- 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 Ww}ELm1R@K*zJq^&%8FT=CH)uINb{)x literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/n4.pdf b/OpenFAST/docs/source/user/beamdyn/figs/n4.pdf new file mode 100644 index 0000000000000000000000000000000000000000..177f721ea9b88aad15d06bf3b751cbd5469db338 GIT binary patch literal 8756 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 literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/figs/n8.pdf b/OpenFAST/docs/source/user/beamdyn/figs/n8.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a0e9b4830dbe82ff2d29b9d0e2b680cc6fed682c GIT binary patch literal 17141 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 OFkb;^X{A)80sjjdFT0lj literal 0 HcmV?d00001 diff --git a/OpenFAST/docs/source/user/beamdyn/future_work.rst b/OpenFAST/docs/source/user/beamdyn/future_work.rst new file mode 100644 index 000000000..5caef1945 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/future_work.rst @@ -0,0 +1,32 @@ +.. _bd-future-work: + +Future Work +=========== + +The following list contains future work on BeamDyn software: + +- Eliminating numerical problems in single precision. + +- Implementing eigenvalue analysis. + +- Improving input options for stand-alone version to make it more + user-friendly. + +- Implementing GEBT based on modal method for computational efficiency. + +- Adding more options for blade cross-sectional properties inputs. For + example, for general isotropic beams, engineering parameters + including sectional offsets, material properties, etc will be used to + generate the 6 :math:`\times` 6 matrices needed by BeamDyn. + +- Writing a general guidance on modeling composite beam structures + using BeamDyn, , for example, how to select a time step, how to + select the model discretization, how to define the blade reference + axis, where to get 6x6 mass/stiffness matrices, etc. + +- Extending applications in FAST to other slender structures in the + wind turbine system, for example, tower, mooring lines, and shaft. + +- Developing a simplified form of GEBT with only rotational DOFs + (bending, torsion) for computational efficiency. + diff --git a/OpenFAST/docs/source/user/beamdyn/index.rst b/OpenFAST/docs/source/user/beamdyn/index.rst new file mode 100644 index 000000000..073917ba0 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/index.rst @@ -0,0 +1,30 @@ +BeamDyn User Guide and Theory Manual +====================================== + +.. only:: html + + This document offers a quick reference guide for the BeamDyn software + program. It is intended to be used by the general user in combination + with other FAST manuals. The manual will be updated as new releases are + issued and as needed to provide further information on advancements or + modifications to the software. + + The authors are grateful to the U.S. Department of Energy Wind and Water + Power Program and the NREL Laboratory Directed Research and Development + (LDRD) program through the grant “High-Fidelity Computational Modeling + of Wind-Turbine Structural Dynamics” for supporting the development of + this software. + + +.. toctree:: + :maxdepth: 2 + + introduction.rst + running_bd.rst + input_files.rst + output_files.rst + theory.rst + future_work.rst + zrefs.rst + appendix.rst + diff --git a/OpenFAST/docs/source/user/beamdyn/input_files.rst b/OpenFAST/docs/source/user/beamdyn/input_files.rst new file mode 100644 index 000000000..f5802607e --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/input_files.rst @@ -0,0 +1,592 @@ +.. _bd-input-files: + +Input Files +=========== + +Users specify the blade model parameters; including its geometry, +cross-sectional properties, and FE and output control parameters; via a +primary BeamDyn input file and a blade property input file. When used in +stand-alone mode, an additional driver input file is required. This +driver file specifies inputs normally provided to BeamDyn by FAST, +including simulation range, root motions, and externally applied loads. + +No lines should be added or removed from the input files, except in +tables where the number of rows is specified. + +Units +----- + +BeamDyn uses the SI system (kg, m, s, N). Angles are assumed to be in +radians unless otherwise specified. + +.. _driver-input-file: + +BeamDyn Driver Input File +------------------------- + +The driver input file is needed only for the stand-alone version of +BeamDyn. It contains inputs that are normally set by FAST and that are +necessary to control the simulation for uncoupled models. + +The driver input file begins with two lines of header information, which +is for the user but is not used by the software. If BeamDyn is run in +the stand-alone mode, the results output file will be prefixed with the +same name of this driver input file. + +A sample BeamDyn driver input file is given in :numref:`bd_input_files`. + +Simulation Control Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``DynamicSolve`` is a logical variable that specifies if BeamDyn should use dynamic analysis (``DynamicSolve = true``) +or static analysis (``DynamicSolve = false``). +``t_initial`` and ``t_final`` specify the starting time of the simulation and ending time of the simulation, respectively. +``dt`` specifies the time step size. + +Gravity Parameters +~~~~~~~~~~~~~~~~~~ + +``Gx`` , ``Gy`` , and ``Gz`` specify the components of gravity vector along :math:`X`, :math:`Y`, and :math:`Z` directions in the global coordinate system, respectively. +In FAST, this is normally 0, 0, and -9.80665. + +Inertial Frame Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This section defines the relation between two inertial frames, the global coordinate system and initial blade reference coordinate system. +``GlbPos(1)``, ``GlbPos(2)``, and ``GlbPos(3)`` specify three components of the initial global position vector along :math:`X`, :math:`Y`, and :math:`Z` directions resolved in the global coordinate system, see Figure :numref:`frame`. +And the following :math:`3 \times 3` direction cosine matrix (``GlbDCM``) relates the rotations from the global coordinate system to the initial blade reference coordinate system. + +.. _frame: + +.. figure:: figs/frame.jpg + :width: 80% + :align: center + + Global and blade coordinate systems in BeamDyn. + + +Blade Floating Reference Frame Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This section specifies the parameters that define the blade floating reference frame, which is a body-attached floating frame; the blade root is cantilevered at the origin of this frame. +Based on the driver input file, the floating blade reference fame is assumed to be in a constant rigid-body rotation mode about the origin of the global coordinate system, that is, + +.. math:: + :label: rootvelocity + + v_{rt} = \omega_r \times r_t + +where :math:`v_{rt}` is the root (origin of the floating blade reference frame) translational velocity vector; :math:`\omega_r` is the constant root (origin of the floating blade reference frame) angular velocity vector; and :math:`r_t` is the global position vector introduced in the previous section at instant :math:`t`, see :numref:`frame`. +The floating blade reference frame coincides with the initial floating blade reference frame at the beginning :math:`t=0`. +``RootVel(4)``, ``RootVel(5)``, and ``RootVel(6)`` specify the three components of the constant root angular velocity vector about :math:`X`, :math:`Y`, and :math:`Z` axises in global coordinate system, respectively. +``RootVel(1)``, ``RootVel(2)``, and ``RootVel(3)``, which are the three components of the root translational velocity vector along :math:`X`, :math:`Y`, and :math:`Z` directions in global coordinate system, respectively, are calculated based on Eq. :eq:`rootvelocity`. + +BeamDyn can handle more complicated root motions by changing, for example, the ``BD_InputSolve`` subroutine in the ``Driver_Beam.f90`` +(requiring a recompile of stand-alone BeamDyn). + + +The blade is initialized in the rigid-body motion mode, i.e., based on the root velocity information defined in this section and the position information defined in the previous section, the motion of other points along the blade are initialized as + +.. math:: + :label: ini-rootacct-travel-angvel + + a_{0} &= \omega_r \times (\omega_r \times (r_0 + P)) \\ + v_0 &= v_{r0} + \omega_r \times P \\ + \omega_0 &= \omega_r + +where :math:`a_{0}` is the initial translational acceleration vector along the blade; :math:`v_0` and :math:`\omega_0` the initial translational and angular velocity vectors along the blade, respectively; and :math:`P` is the position vector along the blade relative to the root. +Note that these equations are actually implemented with a call to the NWTC Library's mesh mapping routines. + +Applied Load +~~~~~~~~~~~~ + +This section defines the applied loads, including distributed, point (lumped), and +tip-concentrated loads, for the stand-alone analysis. + +The first six entries ``DistrLoad(i)``, :math:`i \in [1,6]`, specify three +components of uniformly distributed force vector and three components of +uniformly distributed moment vector in the global coordinate systems, +respectively. + +The following six entries ``TipLoad(i)``, +:math:`i \in [1,6]`, specify three components of concentrated tip force +vector and three components of concentrated tip moment vector in the +global coordinate system, respectively. + +``NumPointLoads`` defines how many point loads along the blade will be applied. The table +following this input contains two header lines with seven columns and ``NumPointLoads`` rows. +The first column is the non-dimensional distance along the local blade reference axis, +ranging from :math:`[0.0,1.0]`. The next three columns, ``Fx``, ``Fy``, and ``Fz`` specify three +components of point-force vector. The remaining three columns, ``Mx``, ``My``, and ``Mz`` specify three +components of a moment vector. + +The distributed load defined in this section is assumed to be uniform along the blade and constant +throughout the simulation. The tip load is a constant concentrated load applied at the tip of a blade. + +It is noted that all the loads defined in +this section are dead loads, i.e., they are not rotating with the blade +following the rigid-body rotation defined in the previous section. + +BeamDyn is capable of handling more complex loading cases, e.g., +time-dependent loads, through customization of the source code +(requiring a recompile of stand-alone BeamDyn). The user can define such +loads in the ``BD_InputSolve`` subroutine in the ``Driver_Beam.f90`` file, +which is called every time step. The following section can be modified +to define the concentrated load at each FE node: + +.. code-block:: fortran + + u%PointLoad%Force(1:3,u%PointLoad%NNodes) = u%PointLoad%Force(1:3,u%PointLoad%NNodes) + DvrData%TipLoad(1:3) + u%PointLoad%Moment(1:3,u%PointLoad%NNodes) = u%PointLoad%Moment(1:3,u%PointLoad%NNodes) + DvrData%TipLoad(4:6) + +where the first index in each array ranges from 1 to 3 for load vector +components along three global directions and the second index of each +array ranges from 1 to ``u%PointLoad%NNodes``, where the latter is the total +number of FE nodes. Note that ``u%PointLoad%Force(1:3,:)`` and ``u%PointLoad%Moment(1:3,:)`` +have been populated with the point-load loads read from the BeamDyn driver input file +using the call to ``Transfer_Point_to_Point`` earlier in the subroutine. + +For example, a time-dependent sinusoidal force +acting along the :math:`X` direction applied at the :math:`2^{nd}` FE +node can be defined as + +.. code-block:: fortran + + u%PointLoad%Force(:,:) = 0.0D0 + u%PointLoad%Force(1,2) = 1.0D+03*SIN((2.0*pi)*t/6.0 ) + u%PointLoad%Moment(:,:) = 0.0D0 + +with ``1.0D+03`` being the amplitude and ``6.0`` being the +period. Note that this particular implementation overrides the tip-load and point-loads +defined in the driver input file. + +Similar to the concentrated load, the distributed loads can be defined +in the same subroutine + +.. code-block:: fortran + + DO i=1,u%DistrLoad%NNodes + u%DistrLoad%Force(1:3,i) = DvrData%DistrLoad(1:3) + u%DistrLoad%Moment(1:3,i)= DvrData%DistrLoad(4:6) + ENDDO + +where ``u%DistrLoad%NNodes`` is the number of nodes input to BeamDyn (on the quadrature points), +and ``DvrData%DistrLoad(:)`` is the constant uniformly distributed load BeamDyn reads from the driver +input file. The user can modify ``DvrData%DistrLoad(:)`` to define the loads based on need. + +We note that the distributed loads are defined at the quadrature points +for numerical integrations. For example, if Gauss quadrature is chosen, +then the distributed loads are defined at +Gauss points plus the two end points of the beam (root and tip). For +trapezoidal quadrature, ``p%ngp`` stores the number of trapezoidal +quadrature points. + +Primary Input File +~~~~~~~~~~~~~~~~~~ + +``InputFile`` is the file name of the primary BeamDyn input file. This +name should be in quotations and can contain an absolute path or a +relative path. + +BeamDyn Primary Input File +-------------------------- + +The BeamDyn primary input file defines the blade geometry, +LSFE-discretization and simulation options, output channels, and name of +the blade input file. The geometry of the blade is defined by key-point +coordinates and initial twist angles (in units of degree) in the blade +local coordinate system (IEC standard blade system where :math:`Z_r` +is along blade axis from root to tip, :math:`X_r` directs normally +toward the suction side, and :math:`Y_r` directs normally toward the +trailing edge). + +The file is organized into several functional sections. Each section +corresponds to an aspect of the BeamDyn model. + +A sample BeamDyn primary input file is given in :numref:`bd_appendix`. + +The primary input file begins with two lines of header information, +which are for the user but are not used by the software. + +Simulation Controls +~~~~~~~~~~~~~~~~~~~ + +The user can set the ``Echo`` flag to ``TRUE`` to have BeamDyn echo the +contents of the BeamDyn input file (useful for debugging errors in the +input file). + +The ``QuasiStaticInit`` flag indicates if BeamDyn should perform a quasi-static +solution at initialization to better initialize its states. In general, this should +be set to true for better numerical performance (it reduces startup transients). + +``rhoinf`` specifies the numerical damping parameter (spectral radius +of the amplification matrix) in the range of :math:`[0.0,1.0]` used in +the generalized-\ :math:`\alpha` time integrator implemented in BeamDyn +for dynamic analysis. For ``rhoinf = 1.0``, no +numerical damping is introduced and the generalized-\ :math:`\alpha` +scheme is identical to the Newmark scheme; for +``rhoinf = 0.0``, maximum numerical damping is +introduced. Numerical damping may help produce numerically stable +solutions. + +``Quadrature`` specifies the spatial numerical integration scheme. +There are two options: 1) Gauss quadrature; and 2) Trapezoidal +quadrature. We note that in the current version, Gauss quadrature is +implemented in reduced form to improve efficiency and avoid shear +locking. In the trapezoidal quadrature, only one member (FE element) can +be defined in the following GEOMETRY section of the primary input file. +Trapezoidal quadrature is appropriate when the number of “blade input +stations” (described below) is significantly greater than the order of +the LSFE. + +``Refine`` specifies a refinement parameter used in trapezoidal +quadrature. An integer value greater than unity will split the space +between two input stations into “Refine factor” of segments. The keyword +“DEFAULT” may be used to set it to 1, i.e., no refinement is needed. +This entry is not used in Gauss quadrature. + +``N_Fact`` specifies a parameter used in the modified Newton-Raphson +scheme. If ``N_Fact = 1`` a full Newton +iteration scheme is used, i.e., the global tangent stiffness matrix is +computed and factorized at each iteration; if +``N_Fact > 1`` a modified Newton iteration +scheme is used, i.e., the global stiffness matrix is computed and +factorized every ``N_Fact`` iterations within each time step. The +keyword “DEFAULT” sets ``N_Fact = 5``. + +``DTBeam`` specifies the constant time increment of the +time-integration in seconds. The keyword “DEFAULT” may be used to +indicate that the module should employ the time increment prescribed by +the driver code (FAST/stand-alone driver program). + +``load_retries`` specifies the maximum number of load retries allowed. This option +currently works only for static analysis. For every load retry, the applied load is +halved to promote convergence of the Newton-Raphson scheme in iteration of smaller +load steps as opposed to one single large load step which may cause divergence of the +Newton-Raphson scheme. The keyword “DEFAULT” sets ``load_retries = 20``. + +``NRMax`` specifies the maximum number of iterations per time step in +the Newton-Raphson scheme. If convergence is not reached within this +number of iterations, BeamDyn returns an error message and terminates +the simulation. The keyword “DEFAULT” sets +``NRMax = 10``. + +``Stop_Tol`` specifies a tolerance parameter used in convergence +criteria of a nonlinear solution that is used for the termination of the +iteration. The keyword “DEFAULT” sets +``Stop_Tol = 1.0E-05``. Please refer to +:numref:`convergence-criterion` for more details. + +``tngt_stf_fd`` is a boolean that sets the flag to compute the tangent stiffness +matrix using finite differencing instead of analytical differentiation. The +finite differencing is performed using a central scheme. The keyword “DEFAULT” +sets ``tngt_stf_fd = FALSE``. + +``tngt_stf_comp`` is a boolean that sets the flag to compare the analytical tangent +stiffness matrix against the finite differenced tangent stiffness matrix. Information is +written to the terminal regarding the dof where the maximum difference is observed. If +``tngt_stf_fd = FALSE`` and ``tngt_stf_comp = TRUE``, the analytical tangent stiffness +matrix is used to solve the system of equations while the finite difference tangent stiffness +matrix is used only to perform the comparison of the two matrices. The keyword “DEFAULT” +sets ``tngt_stf_comp = FALSE``. + +``tngt_stf_pert`` sets the perturbation size for finite differencing. The “DEFAULT” value +based on experience is set to ``1e-06``. + +``tngt_stf_difftol`` is the maximum allowable relative difference between the analytical +and finite differenced tangent stiffness matrices. If for any entry in the matrices, +the relative difference exceeds this value the simulation will terminate. The “DEFAULT” value +is currently set to ``1e-01``. + +``RotStates`` is a flag that indicates if BeamDyn's continuous states should be +oriented in the rotating frame during linearization analysis when coupled to OpenFAST. +If multi-blade coordinate (MBC3) analysis is performed, ``RotStates`` must be ``true``. + +Geometry Parameter +~~~~~~~~~~~~~~~~~~ + +The blade geometry is defined by a curvilinear local blade reference +axis. The blade reference axis locates the origin and orientation of +each a local coordinate system where the cross-sectional 6x6 stiffness +and mass matrices are defined in the BeamDyn blade input file. It should +not really matter where in the cross section the 6x6 stiffness and mass +matrices are defined relative to, as long as the reference axis is +consistently defined and closely follows the natural geometry of the +blade. + +The blade beam model is composed of several *members* in contiguous +series and each member is defined by at least three key points in +BeamDyn. A cubic-spline-fit pre-processor implemented in BeamDyn +automatically generates the member based on the key points and then +interconnects the members into a blade. There is always a shared key +point at adjacent members; therefore the total number of key points is +related to number of members and key points in each member. + +``member_total`` specifies the total number of beam members used in +the structure. With the LSFE discretization, a single member and a +sufficiently high element order, ``order_elem`` below, may well be +sufficient. + +``kp_total`` specifies the total number of key points used to define +the beam members. + +The following section contains ``member_total`` lines. Each line has +two integers providing the member number (must be 1, 2, 3, etc., +sequentially) and the number of key points in this member, respectively. +It is noted that the number of key points in each member is not +independent of the total number of key points and they should satisfy +the following equality: + +.. math:: + :label: keypoint + + kp\_total = \sum_{i=1}^{member\_total} n_i - member\_total +1 + +where :math:`n_i` is the number of key points in the :math:`i^{th}` +member. Because cubic splines are implemented in BeamDyn, :math:`n_i` +must be greater than or equal to three. Figures :numref:`geometry1-case1` and :numref:`geometry1-case2` show two +cases for member and key-point definition. + +.. _geometry1-case1: + +.. figure:: figs/geometry_member1.png + :width: 60% + :align: center + + Member and key point definition: one member defined by four key points; + +.. _geometry1-case2: + +.. figure:: figs/geometry_member2.png + :width: 60% + :align: center + + Member and key point definition: two members defined by six key points. + +The next section defines the key-point information, preceded by two +header lines. Each key point is defined by three physical coordinates +(``kp_xr``, ``kp_yr``, ``kp_zr``) in the IEC standard blade +coordinate system (the blade reference coordinate system) along with a +structural twist angle (``initial_twist``) in the unit of degrees. +The structural twist angle is also following the IEC standard which is +defined as the twist about the negative :math:`Z_l` axis. The key points +are entered sequentially (from the root to tip) and there should be a +total of ``kp_total`` lines for BeamDyn to read in the information, +after two header lines. Please refer to Figure :numref:`blade-geometry` for +more details on the blade geometry definition. + +.. _blade-geometry: + +.. figure:: figs/blade_geometry.jpg + :width: 100% + :align: center + + BeamDyn Blade Geometry - Top: Side View; Middle: Front View (Looking Downwind); Bottom: Cross Section View (Looking Toward the Tip, from the Root) + + +Mesh Parameter +~~~~~~~~~~~~~~ + +``Order_Elem`` specifies the order of shape functions for each finite +element. Each LSFE will have ``Order_Elem``\ +1 nodes located at the +GLL quadrature points. All LSFEs will have the same order. With the LSFE +discretization, an increase in accuracy will, in general, be better +achieved by increasing ``Order_Elem`` (i.e., :math:`p`-refinement) +rather than increasing the number of members (i.e., +:math:`h`-refinement). For Gauss quadrature, ``Order_Elem`` should be +greater than one. + +Material Parameter +~~~~~~~~~~~~~~~~~~ + +``BldFile`` is the file name of the blade input file. This name should +be in quotations and can contain an absolute path or a relative path. + +Pitch Actuator Parameter +~~~~~~~~~~~~~~~~~~~~~~~~ + +In this release, the pitch actuator implemented in BeamDyn is not +available. The ``UsePitchAct`` should be set to “FALSE” in this +version, whereby the input blade-pitch angle prescribed by the driver +code is used to orient the blade directly. ``PitchJ``, ``PitchK``, +and ``PitchC`` specify the pitch actuator inertial, stiffness, and +damping coefficient, respectively. In future releases, specifying +``UsePitchAct`` :math:`=` TRUE will enable a second-order pitch +actuator, whereby the pitch angular orientation, velocity, and +acceleration are determined by the actuator based on the input +blade-pitch angle prescribed by the driver code. + +.. _BD-Outputs: + +Outputs +~~~~~~~ + +In this section of the primary input file, the user sets flags and +switches for the desired output behavior. + +Specifying ``SumPrint = TRUE`` causes BeamDyn to generate a +summary file with name ``InputFile.sum``. See +:numref:`sum-file` for summary file details. + +``OutFmt`` parameter controls the formatting of the results within the +stand-alone BeamDyn output file. It needs to be a valid Fortran format +string, but BeamDyn currently does not check the validity. This input is +unused when BeamDyn is used coupled to FAST. + +``NNodeOuts`` specifies the number of nodes where output can be +written to a file. Currently, BeamDyn can output quantities at a maximum +of nine nodes. + +``OutNd`` is a list ``NNodeOuts`` long of node numbers between 1 and the number of +nodes on the output mesh, separated by any +combination of commas, semicolons, spaces, and/or tabs. The nodal +positions are given in the summary file, if output. +For Gassian quadrature, the number of nodes on the output mesh is the total number of FE nodes; +for trapezoidal quadrature, this is the number of quadrature nodes. + +The ``OutList`` block contains a list of output parameters. Enter one +or more lines containing quoted strings that in turn contain one or more +output parameter names. Separate output parameter names by any +combination of commas, semicolons, spaces, and/or tabs. If you prefix a +parameter name with a minus sign, “-", underscore, “\_”, or the +characters “m” or “M”, BeamDyn will multiply the value for that channel +by -1 before writing the data. The parameters are written in the order +they are listed in the input file. BeamDyn allows you to use multiple +lines so that you can break your list into meaningful groups and so the +lines can be shorter. You may enter comments after the closing quote on +any of the lines. Entering a line with the string “END” at the beginning +of the line or at the beginning of a quoted string found at the +beginning of the line will cause BeamDyn to quit scanning for more lines +of channel names. Node-related quantities are generated for the +requested nodes identified through the OutNd list above. If BeamDyn +encounters an unknown/invalid channel name, it warns the users but will +remove the suspect channel from the output file. Please refer to +Appendix :numref:`app-output-channel` for a complete list of possible output +parameters and their names. + +.. _BD-Nodal-Outputs: + +.. include:: BDNodalOutputs.rst + +Blade Input File +---------------- + +The blade input file defines the cross-sectional properties at various +stations along a blade and six damping coefficient for the whole blade. +A sample BeamDyn blade input file is given in :numref:`bd_appendix`. +The blade input file begins with two lines of header information, which +is for the user but is not used by the software. + +Blade Parameters +~~~~~~~~~~~~~~~~ + +``Station_Total`` specifies the number cross-sectional stations along +the blade axis used in the analysis. + +``Damp_Type`` specifies if structural damping is considered in the +analysis. If ``Damp_Type = 0``, then no damping is +considered in the analysis and the six damping coefficient in the next +section will be ignored. If ``Damp_Type = 1``, structural +damping will be included in the analysis. + +Damping Coefficient +~~~~~~~~~~~~~~~~~~~ + +This section specifies six damping coefficients, :math:`\mu_{ii}` with +:math:`i \in [1,6]`, for six DOFs (three translations and three +rotations). Viscous damping is implemented in BeamDyn where the damping +forces are proportional to the strain rate. These are +stiffness-proportional damping coefficients, whereby the +:math:`6\times6` damping matrix at each cross section is scaled from the +:math:`6 \times 6` stiffness matrix by these diagonal entries of a +:math:`6 \times 6` scaling matrix: + +.. math:: + :label: damping-force + + \mathcal{\underline{F}}^{Damp} = \underline{\underline{\mu}}~\underline{\underline{S}}~\dot{\underline{\epsilon}} + +where :math:`\mathcal{\underline{F}}^{Damp}` is the damping force, +:math:`\underline{\underline{S}}` is the :math:`6 \times 6` +cross-sectional stiffness matrix, :math:`\dot{\underline{\epsilon}}` is +the strain rate, and :math:`\underline{\underline{\mu}}` is the damping +coefficient matrix defined as + +.. math:: + :label: damp-matrix + + \underline{\underline{\mu}} = + \begin{bmatrix} + \mu_{11} & 0 & 0 & 0 & 0 & 0 \\ + 0 & \mu_{22} & 0 & 0 & 0 & 0 \\ + 0 & 0 & \mu_{33} & 0 & 0 & 0 \\ + 0 & 0 & 0 & \mu_{44} & 0 & 0 \\ + 0 & 0 & 0 & 0 & \mu_{55} & 0 \\ + 0 & 0 & 0 & 0 & 0 & \mu_{66} \\ + \end{bmatrix} + +Distributed Properties +~~~~~~~~~~~~~~~~~~~~~~ + +This section specifies the cross-sectional properties at each of the +``Station_Total`` stations. For each station, a non-dimensional +parameter :math:`\eta` specifies the station location along the local +blade reference axis ranging from :math:`[0.0,1.0]`. The first and last +station parameters must be set to :math:`0.0` (for the blade root) and +:math:`1.0` (for the blade tip), respectively. + +Following the station location parameter :math:`\eta`, there are two +:math:`6 \times 6` matrices providing the structural and inertial +properties for this cross-section. First is the stiffness matrix and +then the mass matrix. We note that these matrices are defined in a local +coordinate system along the blade axis with :math:`Z_{l}` directing +toward the unit tangent vector of the blade reference axis. For a +cross-section without coupling effects, for example, the stiffness +matrix is given as follows: + +.. math:: + :label: Stiffness + + \begin{bmatrix} + K_{ShrFlp} & 0 & 0 & 0 & 0 & 0 \\ + 0 & K_{ShrEdg} & 0 & 0 & 0 & 0 \\ + 0 & 0& EA & 0 & 0 & 0 \\ + 0 & 0 & 0 & EI_{Edg} & 0 & 0 \\ + 0 & 0 & 0 & 0 & EI_{Flp} & 0 \\ + 0 & 0 & 0 & 0 & 0 & GJ + \end{bmatrix} + +where :math:`K_{ShrEdg}` and :math:`K_{ShrFlp}` are the edge and flap +shear stiffnesses, respectively; :math:`EA` is the extension stiffness; +:math:`EI_{Edg}` and :math:`EI_{Flp}` are the edge and flap stiffnesses, +respectively; and :math:`GJ` is the torsional stiffness. It is pointed +out that for a generic cross-section, the sectional property matrices +can be derived from a sectional analysis tool, e.g. VABS, BECAS, or +NuMAD/BPE. + +A generalized sectional mass matrix is given by: + +.. math:: + :label: Mass + + \begin{bmatrix} + m & 0 & 0 & 0 & 0 & -m Y_{cm} \\ + 0 & m & 0 & 0 & 0 & m X_{cm}\\ + 0 & 0& m & m Y_{cm} & -m X_{cm} & 0 \\ + 0 & 0 & m Y_{cm} & i_{Edg} & -i_{cp} & 0 \\ + 0 & 0 &-m X_{cm} & -i_{cp} & i_{Flp} & 0 \\ + -m Y_{cm} & m X_{cm} & 0 & 0 & 0 & i_{plr} + \end{bmatrix} + +where :math:`m` is the mass density per unit span; :math:`X_{cm}` and +:math:`Y_{cm}` are the local coordinates of the sectional center of +mass, respectively; :math:`i_{Edg}` and :math:`i_{Flp}` are the edge and +flap mass moments of inertia per unit span, respectively; +:math:`i_{plr}` is the polar moment of inertia per unit span; and +:math:`i_{cp}` is the sectional cross-product of inertia per unit span. +We note that for beam structure, the :math:`i_{plr}` is given as +(although this relationship is not checked by BeamDyn) + +.. math:: + :label: PolarMOI + + i_{plr} = i_{Edg} + i_{Flp} diff --git a/OpenFAST/docs/source/user/beamdyn/introduction.rst b/OpenFAST/docs/source/user/beamdyn/introduction.rst new file mode 100644 index 000000000..95e54cfc3 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/introduction.rst @@ -0,0 +1,111 @@ +.. _bd_intro: + +Introduction +============ + +BeamDyn is a time-domain structural-dynamics module for slender +structures created by the National Renewable Energy Laboratory (NREL) +through support from the U.S. Department of Energy Wind and Water Power +Program and the NREL Laboratory Directed Research and Development (LDRD) +program through the grant “High-Fidelity Computational Modeling of +Wind-Turbine Structural Dynamics”, see References :cite:`Wang:SFE2013,Wang:GEBT2013,Wang:GEBT2014,Wang:2015`. +The module has been coupled into the FAST aero-hydro-servo-elastic wind +turbine multi-physics engineering tool where it used to model blade +structural dynamics. The BeamDyn module follows the requirements of the +FAST modularization framework, see References :cite:`Jonkman:2013`; +:cite:`Sprague:2013,Sprague:2014,website:FASTModularizationFramework`, +couples to FAST version 8, and provides new capabilities for modeling +initially curved and twisted composite wind turbine blades undergoing +large deformation. BeamDyn can also be driven as a stand-alone code to +compute the static and dynamic responses of slender structures (blades +or otherwise) under prescribed boundary and applied loading conditions +uncoupled from FAST. + +The model underlying BeamDyn is the geometrically exact beam theory +(GEBT) :cite:`HodgesBeamBook`. GEBT supports full geometric +nonlinearity and large deflection, with bending, torsion, shear, and +extensional degree-of-freedom (DOFs); anisotropic composite material +couplings (using full :math:`6 \times 6` mass and stiffness matrices, +including bend-twist coupling); and a reference axis that permits blades +that are not straight (supporting built-in curve, sweep, and sectional +offsets). The GEBT beam equations are discretized in space with Legendre +spectral finite elements (LSFEs). LFSEs are *p*-type elements that +combine the accuracy of global spectral methods with the geometric +modeling flexibility of the *h*-type finite elements (FEs) +:cite:`Patera:1984`. For smooth solutions, LSFEs have +exponential convergence rates compared to low-order elements that have +algebraic convergence :cite:`Sprague:2003,Wang:SFE2013` . +Two spatial numerical integration schemes are implemented for the finite +element inner products: reduced Gauss quadrature and trapezoidal-rule +integration. Trapezoidal-rule integration is appropriate when a large +number of sectional properties are specified along the beam axis, for +example, in a long wind turbine blade with material properties that vary +dramatically over the length. Time integration of the BeamDyn equations +of motion is achieved through the implicit generalized- :math:`\alpha` +solver, with user-specified numerical damping. The combined GEBT-LSFE +approach permits users to model a long, flexible, composite wind turbine +blade with a single high-order element. Given the theoretical foundation +and powerful numerical tools introduced above, BeamDyn can solve the +complicated nonlinear composite beam problem in an efficient manner. For +example, it was recently shown that a grid-independent dynamic solution +of a 50-m composite wind turbine blade and with dozens of cross-section +stations could be achieved with a single :math:`7^{th}`-order LSFE +:cite:`Wang:2016`. + +When coupled with FAST, loads and responses are transferred between +BeamDyn, ElastoDyn, ServoDyn, and AeroDyn via the FAST driver program +(glue code) to enable aero-elasto-servo interaction at each coupling +time step. There is a separate instance of BeamDyn for each blade. At +the root node, the inputs to BeamDyn are the six displacements (three +translations and three rotations), six velocities, and six +accelerations; the root node outputs from BeamDyn are the six reaction +loads (three translational forces and three moments). BeamDyn also +outputs the blade displacements, velocities, and accelerations along the +beam length, which are used by AeroDyn to calculate the local +aerodynamic loads (distributed along the length) that are used as inputs +for BeamDyn. In addition, BeamDyn can calculate member internal reaction +loads, as requested by the user. Please refers to Figure [fig:FlowChart] +for the coupled interactions between BeamDyn and other modules in FAST. +When coupled to FAST, BeamDyn replaces the more simplified blade +structural model of ElastoDyn that is still available as an option, but +is only applicable to straight isotropic blades dominated by bending. +When uncoupled from FAST, the root motion (boundary condition) and +applied loads are specified via a stand-alone BeamDyn driver code. + +.. _flow-chart: + +.. figure:: figs/flow_chart.jpg + :width: 100% + + Coupled interaction between BeamDyn and FAST + +The BeamDyn input file defines the blade geometry; cross-sectional +material mass, stiffness, and damping properties; FE resolution; and +other simulation- and output-control parameters. The blade geometry is +defined through a curvilinear blade reference axis by a series of key +points in three-dimensional (3D) space along with the initial twist +angles at these points. Each *member* contains at least three key points +for the cubic spline fit implemented in BeamDyn; each member is +discretized with a single LSFE with a parameter defining the order of +the element. Note that the number of key points defining the member and +the order (:math:`N`) of the LSFE are independent. LSFE nodes, which are +located at the :math:`N+1` Gauss-Legendre-Lobatto points, are not evenly +spaced along the element; node locations are generated by the module +based on the mesh information. Blade properties are specified in a +non-dimensional coordinate ranging from 0.0 to 1.0 along the blade +reference axis and are linearly interpolated between two stations if +needed by the spatial integration method. The BeamDyn applied loads can +be either distributed loads specified at quadrature points, concentrated +loads specified at FE nodes, or a combination of the two. When BeamDyn +is coupled to FAST, the blade analysis node discretization may be +independent between BeamDyn and AeroDyn. + +This document is organized as follows. Section :ref:`running-beamdyn` details how to +obtain the BeamDyn and FAST software archives and run either the +stand-alone version of BeamDyn or BeamDyn coupled to FAST. +Section :ref:`bd-input-files` describes the BeamDyn input files. +Section :ref:`bd-output-files` discusses the output files generated by +BeamDyn. Section :ref:`beamdyn-theory` summarizes the BeamDyn theory. +Section :ref:`bd-future-work` outlines potential future work. Example input +files are shown in Appendix :numref:`bd_input_files`. +A summary of available output channels is found in Appendix :ref:`app-output-channel`. diff --git a/OpenFAST/docs/source/user/beamdyn/output_files.rst b/OpenFAST/docs/source/user/beamdyn/output_files.rst new file mode 100644 index 000000000..82a13535f --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/output_files.rst @@ -0,0 +1,109 @@ +.. _bd-output-files: + +Output Files +============ + +BeamDyn produces three types of output files, depending on the options +selected: an echo file, a summary file, and a time-series results file. +The following sections detail the purpose and contents of these files. + +Echo File +--------- + +If the user sets the ``Echo`` flag to TRUE in the BeamDyn primary +input file, the contents of this file will be echoed to a file with the +naming convention ``InputFile.ech``. The echo file is helpful for +debugging the input files. The contents of an echo file will be +truncated if BeamDyn encounters an error while parsing an input file. +The error usually corresponds to the line after the last successfully +echoed line. + +.. _sum-file: + +Summary File +------------ + +In stand-alone mode, BeamDyn generates a summary file with the naming +convention, ``InputFile.sum`` if the ``SumPrint`` parameter is set +to TRUE. When coupled to FAST, the summary file is named +``InputFile.BD.sum``. This file summarizes key information about the +simulation, including: + +- Blade mass. + +- Blade length. + +- Blade center of mass. + +- Initial global position vector in BD coordinate system. + +- Initial global rotation tensor in BD coordinate system. + +- Analysis type. + +- Numerical damping coefficients. + +- Time step size. + +- Maximum number of iterations in the Newton-Raphson solution. + +- Convergence parameter in the stopping criterion. + +- Factorization frequency in the Newton-Raphson solution. + +- Numerical integration (quadrature) method. + +- FE mesh refinement factor used in trapezoidal quadrature. + +- Number of elements. + +- Number of FE nodes. + +- Initial position vectors of FE nodes in BD coordinate system. + +- Initial rotation vectors of FE nodes in BD coordinate system. + +- Quadrature point position vectors in BD coordinate system. For Gauss + quadrature, the physical coordinates of Gauss points are listed. For + trapezoidal quadrature, the physical coordinates of the quadrature + points are listed. + +- Sectional stiffness and mass matrices at quadrature points in local + blade reference coordinate system. These are the data being used in + calculations at quadrature points and they can be different from the + section in Blade Input File since BeamDyn linearly interpolates the + sectional properties into quadrature points based on need. + +- Initial displacement vectors of FE nodes in BD coordinate system. + +- Initial rotational displacement vectors of FE nodes in BD coordinate + system. + +- Initial translational velocity vectors of FE nodes in BD coordinate + system. + +- Initial angular velocity vectors of FE nodes in BD coordinate system. + +- Requested output information. + +All of these quantities are output in this file in the BD coordinate +system, the one being used internally in BeamDyn calculations. The +initial blade reference coordinate system, denoted by a subscript +:math:`r0` that follows the IEC standard, is related to the internal BD +coordinate system by :numref:`IECBD` in :numref:`beamdyn-theory`. + +Results File +------------ + +The BeamDyn time-series results are written to a text-based file with +the naming convention ``DriverInputFile.out`` where +``DriverInputFile`` is the name of the driver input file when BeamDyn +is run in the stand-alone mode. If BeamDyn is coupled to FAST, then FAST +will generate a master results file that includes the BeamDyn results. +The results in ``DriverInputFile.out`` are in table format, where each +column is a data channel (the first column always being the simulation +time), and each row corresponds to a simulation time step. The data +channel are specified in the OUTPUT section of the primary input file. +The column format of the BeamDyn-generated file is specified using the +``OutFmt`` parameters of the primary input file. + diff --git a/OpenFAST/docs/source/user/beamdyn/references.bib b/OpenFAST/docs/source/user/beamdyn/references.bib new file mode 100644 index 000000000..3f5a07247 --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/references.bib @@ -0,0 +1,223 @@ +%% This BibTeX bibliography file was created using BibDesk. +%% http://bibdesk.sourceforge.net/ + + +%% Created for Clifton, Andrew at 2014-07-30 18:45:30 -0600 + + +%% Saved with string encoding Unicode (UTF-8) + +@book{HodgesBeamBook, + author = "Dewey H. Hodges", + title = "Nonlinear Composite Beam Theory", + year = "2006", + publisher = "AIAA" +} + +@book{Bauchau:2010, + author = "O. A. Bauchau", + title = "Flexible Multibody Dynamics", + year = "2010", + publisher = "Springer", + doi = "10.1007/978-94-007-0335-3" +} + +@article{Bauchau-etal:2008, + author = "Bauchau, O.A. and Epple, A. and Heo, S.D.", + title = "Interpolation of finite rotations in flexible multibody dynamics simulations", + year = "2008", + journal = "Proceedings of the Institution of Mechanical Engineers, Part K: Journal of Multi-body Dynamics", + volume = "222", + pages = "353--366" +} + +@article{Crisfield1999, + author = "G. Jeleni\'{c} and M. A. Crisfield", + title = "Geometrically exact 3D beam theory: implementation of a strain-invariant finite element for statics and dynamics", + year = "1999", + journal = "Computer Methods in Applied Mechanics and Engineering", + volume = "171", + pages = "141--171" +} + +@inproceedings{Wang:GEBT2013, + author = "Q. Wang and W. Yu and M.A. Sprague", + title = "Gemoetrically nonlinear analysis of composite beams using Wiener-Milenkovi\'c parameters", + month = "April", + year = "2013", + booktitle = "Proceedings of the 54th Structures, Structural Dynamics, and Materials Conference", + address = "Boston, Massachusetts" +} + +@inproceedings{Wang:SFE2013, + author = "Q. Wang and M.A. Sprague", + title = "A Legendre spectral finite element implementation of geometrically exact beam theory", + month = "April", + year = "2013", + booktitle = "Proceedings of the 54th Structures, Structural Dynamics, and Materials Conference", + address = "Boston, Massachusetts" +} + +@inproceedings{Wang:GEBT2014, + author = "Q. Wang and M.A. Sprague and J. Jonkman and N. Johnson", + title = "Nonlinear Legendre spectral finite elements for wind turbine blade dynamics", + month = "January", + year = "2014", + booktitle = "Proceedings of the 32nd ASME Wind Energy Symposium", + address = "National Harbor, Maryland" +} + +@inproceedings{Wang:2015, + author = "Q. Wang and N. Johnson and M.A. Sprague and J. Jonkman", + title = "BeamDyn: a high-fidelity wind turbine blade solver in the FAST modular framework", + month = "January", + year = "2015", + booktitle = "Proceedings of the 33rd ASME Wind Energy Symposium", + address = "Kissimmee, Florida", + note = "https://www.nrel.gov/docs/fy15osti/63165.pdf" +} + +@inproceedings{Wang:2016, + author = "Q. Wang and M.A. Sprague and J. Jonkman and B. Jonkman", + title = "Partitioned nonlinear structural analysis of wind turbines using BeamDyn", + month = "January", + year = "2016", + booktitle = "Proceedings of the 34th ASME Wind Energy Symposium", + address = "San Diego, California" +} + +@inproceedings{Jonkman:2013, + author = "J.M. Jonkman", + title = "The new modularization framework for the FAST wind turbine CAE tool", + month = "January", + year = "2013", + booktitle = "Proceedings of the 51st AIAA Aerospace Sciences Meeting including the New Horizons Forum and Aerospace Exposition", + address = "Grapevine, Texas" +} + +@inproceedings{Sprague:2013, + author = "Gasmi, A. and Sprague, M.A. and Jonkman, J.M.", + title = "Numerical stability and accuracy of temporally coupled multi physics modules in wind-turbine CAE tools", + month = "January", + year = "2013", + booktitle = "Proceedings of the 51st AIAA Aerospace Sciences Meeting including the New Horizons Forum and Aerospace Exposition", + address = "Grapevine, Texas" +} + +@inproceedings{Sprague:2014, + author = "Sprague, M.A. and Jonkman, J.M. and Jonkman, B.J.", + title = "FAST modular wind turbine CAE tool: non matching spatial and temporal meshes", + month = "January", + year = "2014", + booktitle = "Proceedings of the 32nd ASME Wind Energy Symposium", + address = "National Harbor, Maryland" +} + +@misc{website:FASTModularizationFramework, + author = "Jason Jonkman and Bonnie Jonkman", + title = "FAST v8", + howpublished = "\url{https://nwtc.nrel.gov/FAST8}", + month = "October", + year = "2013", + note = "[Online; accessed 29-OCTOBER-2014]" +} + +@article{Patera:1984, + author = "Patera, A. T. ", + title = "A spectral element method for fluid dynamics: Laminar flow in a channel expansion", + year = "1984", + journal = "Journal of Computational Physics", + volume = "54", + pages = "468--488" +} + +@article{Ronquist:1987, + author = "Ronquist, E. M. and Patera, A. T. ", + title = "A Legendre spectral element method for the Stefan problem", + year = "1987", + journal = "International Journal for Numerical Methods in Engineering", + volume = "24", + pages = "2273--2299" +} + +@article{Sprague:2003, + author = "M. A. Sprague and T. L. Geers ", + title = "Spectral elements and field separation for an acoustic fluid subject to cavitation", + year = "2003", + journal = "Journal of Computational Physics", + volume = "184", + pages = "149--162" +} + +@article{Sprague:2004, + author = "M. A. Sprague and T. L. Geers ", + title = "A spectral-element method for modeling cavitation in transient fluid-structure interaction", + year = "2004", + journal = "International Journal for Numerical Methods in Engineering", + volume = "60", + pages = "2467--2499" +} + +@article{Bathe-Cimento:1980, + author = "K. J. Bathe and A. P. Cimento", + title = "Some practical procedures for the solution of nonlinear finite element equations", + year = "1980", + journal = "Computer Methods in Applied Mechanics and Engineering", + volume = "22", + pages = "59--85", + note = "\url{http://web.mit.edu/kjb/www/Publications_Prior_to_1998/Some_Practical_Procedures_for_the_Solution_of_Nonlinear_Finite_Element_Equations.pdf}", + doi = "10.1016/0045-7825(80)90051-1" +} + +@article{Chung-Hulbert:1993, + author = "J. Chung and G. M. Hulbert", + title = "A time integration algorithm for structural dynamics with improved numerical dissipation: the generalized-$\alpha$ method", + year = "1993", + journal = "Journal of Applied Mechanics", + volume = "60", + pages = "371--375", + doi = "10.1115/1.2900803" +} + +@techreport{TechReportTest, + Author = {A. N. Other and Y. A. Nother}, + Date-Added = {2014-07-30 00:01:12 +0000}, + Date-Modified = {2014-07-30 00:04:56 +0000}, + Howpublished = {Accessed July 21, 2014: \url{http:www.nrel.gov}}, + Institution = {National Renewable Energy Laboratory}, + Title = {A technical report}, + Year = {2014}} + +@misc{texstackexchange, + Author = {Anon.}, + Date-Added = {2014-07-29 21:38:55 +0000}, + Date-Modified = {2014-07-31 00:45:25 +0000}, + Howpublished = {Accessed July 21, 2014: \href{http://tex.stackexchange.com}{http://tex.stackexchange.com}}, + Title = {\TeX -- \LaTeX Stack Exchange}, + Year = {2014}} + +@inbook{chicago, + Date-Added = {2013-03-29 20:33:11 +0000}, + Date-Modified = {2013-03-29 20:33:11 +0000}, + Edition = {Thirteenth}, + Key = {Chicago}, + Pages = {400--401}, + Publisher = {University of Chicago Press}, + Title = {The Chicago Manual of Style}, + Year = 1982} + +@book{Knuth_1984_a, + Author = {Donald E. Knuth}, + Date-Added = {2013-03-29 20:33:11 +0000}, + Date-Modified = {2013-03-29 20:36:20 +0000}, + Publisher = {Addison-Wesley}, + Title = {The {{\TeX}book}}, + Year = 1984} + +@book{Lamport_1986_a, + Author = {Leslie Lamport}, + Date-Added = {2013-03-29 20:33:11 +0000}, + Date-Modified = {2013-03-29 20:33:57 +0000}, + Publisher = {Addison-Wesley}, + Title = {{\LaTeX \rm:} {A} Document Preparation System}, + Year = 1986} diff --git a/OpenFAST/docs/source/user/beamdyn/running_bd.rst b/OpenFAST/docs/source/user/beamdyn/running_bd.rst new file mode 100644 index 000000000..a2885315f --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/running_bd.rst @@ -0,0 +1,92 @@ +.. _running-beamdyn: + +Running BeamDyn +=============== + +This section discusses how to obtain and execute BeamDyn from a personal +computer. Both the stand-alone version and the FAST-coupled version of +the software are considered. + +Downloading the BeamDyn Software +-------------------------------- + +There are two forms of the BeamDyn software to choose from: stand-alone +and coupled to the FAST simulator. Although the user may not necessarily +need both forms, he/she would likely need to be familiar with and run +the stand-alone model if building a model of the blade from scratch. The +stand-alone version is also helpful for model troubleshooting, even if +the goal is to conduct aero-hydro-servo-elastic simulations of +onshore/offshore wind turbines within FAST. + +Stand-Alone BeamDyn Archive +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Users can download the stand-alone BeamDyn archive from our Web server +at https://nwtc.nrel.gov/BeamDyn. The file has a name similar to +``BD_v1.00.00a.exe``, but may have a different version number. The user +can then download the self-extracting archive (*.exe*) to expand the +archive into a folder he/she specifies. + +The archive contains the ``bin``, ``CertTest``, ``Compiling``, +``Docs``, and ``Source`` folders. The ``bin`` folder includes the +main executable file, ``BeamDyn_Driver.exe``, which is used to execute +the stand-alone BeamDyn program. The ``CertTest`` folder contains a +collection of sample BeamDyn input files and driver input files that can +be used as templates for the user’s own models. This document may be +found in the ``Docs`` folder. The ``Compiling`` folder contains files +for compiling the stand-alone ``BeamDyn_v1.00.00.exe`` file with either +Visual Studio or gFortran. The Fortran source code is located in the +``Source`` folder. + +FAST Archive +~~~~~~~~~~~~ + +Download the FAST archive, which includes BeamDyn, from our Web server +at https://nwtc.nrel.gov/FAST8. The file has a name similar to +``FAST_v8.12.00.exe``, but may have a different version number. Run the +downloaded self-extracting archive (``.exe``) to expand the archive into a +user-specified folder. The FAST executable file is located in the +archive’s ``bin`` folder. An example model using the NREL 5-MW +reference turbine is located in the ``CertTest`` folder. + +Running BeamDyn +--------------- + +Running the Stand-Alone BeamDyn Program +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The stand-alone BeamDyn program, ``BeamDyn_Driver.exe``, simulates static +and dynamic responses of the user’s input model, without coupling to +FAST. Unlike the coupled version, the stand-alone software requires the +use of a driver file in addition to the primary and blade BeamDyn input +files. This driver file specifies inputs normally provided to BeamDyn by +FAST, including motions of the blade root and externally applied loads. +Both the BeamDyn summary file and the results output file are available +when using the stand-alone BeamDyn (see Section :ref:`bd-output-files` for +more information regarding the BeamDyn output files). + +Run the stand-alone BeamDyn software from a DOS command prompt by +typing, for example: + +.. code-block:: bash + + >BeamDyn_Driver.exe Dvr_5MW_Dynamic.inp + +where, ``Dvr_5MW_Dynamic.inp`` is the name of the BeamDyn driver input +file, as described in Section :ref:`driver-input-file`. + +Running BeamDyn Coupled to FAST +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Run the coupled FAST software from a DOS command prompt by typing, for +example: + +.. code-block:: bash + + >FAST_Win32.exe Test26.fst + +where ``Test26.fst`` is the name of the primary FAST input file. This +input file has a feature switch to enable or disable the BeamDyn +capabilities within FAST, and a corresponding reference to the BeamDyn +input file. See the documentation supplied with FAST for further +information. diff --git a/OpenFAST/docs/source/user/beamdyn/theory.rst b/OpenFAST/docs/source/user/beamdyn/theory.rst new file mode 100644 index 000000000..15ccb380b --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/theory.rst @@ -0,0 +1,712 @@ +.. _beamdyn-theory: + +BeamDyn Theory +============== + +This section focuses on the theory behind the BeamDyn module. The +theoretical foundation, numerical tools, and some special handling in +the implementation will be introduced. References will be provided in +each section detailing the theories and numerical tools. + +In this chapter, matrix notation is used to denote vectorial or +vectorial-like quantities. For example, an underline denotes a vector +:math:`\underline{u}`, an over bar denotes unit vector :math:`\bar{n}`, +and a double underline denotes a tensor +:math:`\underline{\underline{\Delta}}`. Note that sometimes the +underlines only denote the dimension of the corresponding matrix. + +Coordinate Systems +------------------ + +:numref:`blade-geometry` (in :numref:`bd-input-files`) and +:numref:`bd-frame` show the coordinate system used in BeamDyn. + +.. _bd-frame: + +.. figure:: figs/bd_frame.pdf + :width: 100% + :align: center + + Global, blade reference, and internal coordinate systems in BeamDyn. Illustration by Al Hicks, NREL. + + +Global Coordinate System +~~~~~~~~~~~~~~~~~~~~~~~~ + +The global coordinate system is denoted as ``X``, ``Y``, and ``Z`` +in :numref:`bd-frame`. This is an inertial frame and in FAST its +origin is usually placed at the bottom of the tower as shown. + +BD Coordinate System +~~~~~~~~~~~~~~~~~~~~ + +The BD coordinate system is denoted as :math:`x_1`, :math:`x_2`, and +:math:`x_3` respectively in :numref:`bd-frame`. This is an inertial +frame used internally in BeamDyn (i.e., doesn’t rotate with the rotor) +and its origin is placed at the initial position of the blade root +point. + +Blade Reference Coordinate System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The blade reference coordinate system is denoted as +:math:`X_{rt}`, :math:`Y_{rt}`, and +:math:`Z_{rt}` in :numref:`bd-frame` at initialization +(:math:`t = 0`). The blade reference coordinate system is a floating +frame that attaches at the blade root and is rotating with the blade. +Its origin is at the blade root and the directions of axes following the +IEC standard, i.e., :math:`Z_r` is pointing along the blade axis +from root to tip; :math:`Y_r` pointing nominally towards the +trailing edge of the blade and parallel with the chord line at the +zero-twist blade station; and :math:`X_r` is orthogonal with the +:math:`Y_r` and :math:`Z_r` axes, such that they form a +right-handed coordinate system (pointing nominally downwind). We note +that the initial blade reference coordinate system, denoted by subscript +:math:`r0`, coincides with the BD coordinate system, which is used +internally in BeamDyn and introduced in the previous section. The axis +convention relations between the initial blade reference coordinate +system and the BD coordinate system can be found in :numref:`IECBD`. + +.. _IECBD: + +.. table:: Transformation between blade coordinate system and BD coordinate system. + + +---------------+------------------+------------------+------------------+ + | Blade Frame | :math:`X_{r0}` | :math:`Y_{r0}` | :math:`Z_{r0}` | + +---------------+------------------+------------------+------------------+ + | BD Frame | :math:`x_2` | :math:`x_3` | :math:`x_1` | + +---------------+------------------+------------------+------------------+ + +Local blade coordinate system +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The local blade coordinate system is used for some input and output +quantities, for example, the cross-sectional mass and stiffness matrices +and the the sectional force and moment resultants. This coordinate +system is different from the blade reference coordinate system in that +its :math:`Z_l` axis is always tangent to the blade axis as the blade +deflects. Note that a subscript :math:`l` denotes the local blade +coordinate system. + +Geometrically Exact Beam Theory +------------------------------- + +The theoretical foundation of BeamDyn is the geometrically exact beam +theory. This theory features the capability of beams that are initially +curved and twisted and subjected to large displacement and rotations. +Along with a proper two-dimensional (2D) cross-sectional analysis, the +coupling effects between all six DOFs, including extension, bending, +shear, and torsion, can be captured by GEBT as well . The term, +“geometrically exact” refer to the fact that there is no approximation +made on the geometries, including both initial and deformed geometries, +in formulating the equations :cite:`HodgesBeamBook`. + +The governing equations of motion for geometrically exact beam theory +can be written as :cite:`Bauchau:2010` + +.. math:: + :label: GovernGEBT-1-2 + + \dot{\underline{h}} - \underline{F}^\prime &= \underline{f} \\ + \dot{\underline{g}} + \dot{\tilde{u}} \underline{h} - \underline{M}^\prime + (\tilde{x}_0^\prime + \tilde{u}^\prime)^T \underline{F} &= \underline{m} + +where :math:`{\underline{h}}` and :math:`{\underline{g}}` are the +linear and angular momenta resolved in the inertial coordinate system, +respectively; :math:`{\underline{F}}` and :math:`{\underline{M}}` are +the beam’s sectional force and moment resultants, respectively; +:math:`{\underline{u}}` is the one-dimensional (1D) displacement of a +point on the reference line; :math:`{\underline{x}}_0` is the position +vector of a point along the beam’s reference line; and +:math:`{\underline{f}}` and :math:`{\underline{m}}` are the distributed +force and moment applied to the beam structure. The notation +:math:`(\bullet)^\prime` indicates a derivative with respect to beam +axis :math:`x_1` and :math:`\dot{(\bullet)}` indicates a derivative with +respect to time. The tilde operator :math:`({\widetilde{\bullet}})` +defines a skew-symmetric tensor corresponding to the given vector. In +the literature, it is also termed as “cross-product matrix”. For +example, + +.. math:: + + {\widetilde{n}} = + \begin{bmatrix} + 0 & -n_3 & n_2 \\ + n_3 & 0 & -n_1 \\ + -n_2 & n_1 & 0\\ + \end{bmatrix} + +The constitutive equations relate the velocities to the momenta and the +1D strain measures to the sectional resultants as + +.. math:: + :label: ConstitutiveMass-Stiff + + \begin{Bmatrix} + \underline{h} \\ + \underline{g} + \end{Bmatrix} + = \underline{\underline{\mathcal{M}}} \begin{Bmatrix} + \dot{\underline{u}} \\ + \underline{\omega} + \end{Bmatrix} \\ + + \begin{Bmatrix} + \underline{F} \\ + \underline{M} + \end{Bmatrix} + = \underline{\underline{\mathcal{C}}} \begin{Bmatrix} + \underline{\epsilon} \\ + \underline{\kappa} + \end{Bmatrix} + +where :math:`\underline{\underline{\mathcal{M}}}` and +:math:`\underline{\underline{\mathcal{C}}}` are the :math:`6 \times 6` +sectional mass and stiffness matrices, respectively (note that they are +not really tensors); :math:`\underline{\epsilon}` and +:math:`\underline{\kappa}` are the 1D strains and curvatures, +respectively; and, :math:`\underline{\omega}` is the angular velocity +vector that is defined by the rotation tensor +:math:`\underline{\underline{R}}` as :math:`\underline{\omega} = +axial(\dot{\underline{\underline{R}}}~\underline{\underline{R}}^T)`. The +axial vector :math:`{\underline{a}}` associated with a second-order +tensor :math:`{\underline{\underline{A}}}` is denoted +:math:`{\underline{a}}=axial({\underline{\underline{A}}})` and its +components are defined as + +.. math:: + :label: axial + + {\underline{a}} = axial({\underline{\underline{A}}})=\begin{Bmatrix} + a_1 \\ + a_2 \\ + a_3 + \end{Bmatrix} + =\frac{1}{2} + \begin{Bmatrix} + A_{32}-A_{23} \\ + A_{13}-A_{31} \\ + A_{21}-A_{12} + \end{Bmatrix} + +The 1D strain measures are defined as + +.. math:: + :label: 1DStrain + + \begin{Bmatrix} + {\underline{\epsilon}} \\ + {\underline{\kappa}} + \end{Bmatrix} + = + \begin{Bmatrix} + {\underline{x}}^\prime_0 + {\underline{u}}^\prime - ({\underline{\underline{R}}} ~{\underline{\underline{R}}}_0) \bar{\imath}_1 \\ + {\underline{k}} + \end{Bmatrix} + +where :math:`{\underline{k}} = axial [({\underline{\underline{R R_0}}})^\prime ({\underline{\underline{R R_0}}})^T]` is the sectional curvature vector resolved in the inertial basis; :math:`{\underline{\underline{R}}}_0` is the initial rotation tensor; and :math:`\bar{\imath}_1` is the unit vector along :math:`x_1` direction in the inertial basis. These three sets of equations, including equations of motion Eq. :eq:`GovernGEBT-1-2`, constitutive equations Eq. :eq:`ConstitutiveMass-Stiff`, and kinematical equations Eq. :eq:`1DStrain`, provide a full mathematical description of the beam elasticity problems. + +.. _num-imp: + +Numerical Implementation with Legendre Spectral Finite Elements +--------------------------------------------------------------- + +For a displacement-based finite element implementation, there are six +degree-of-freedoms at each node: three displacement components and three +rotation components. Here we use :math:`{\underline{q}}` to denote the +elemental displacement array as :math:`\underline{q}=\left[ +\underline{u}^T~~\underline{c}^T\right]` where :math:`{\underline{u}}` +is the displacement and :math:`{\underline{c}}` is the +rotation-parameter vector. The acceleration array can thus be defined as +:math:`\underline{a}=\left[ \ddot{\underline{u}}^T~~ \dot{\underline{\omega}}^T \right]`. +For nonlinear finite-element analysis, the discretized and incremental +forms of displacement, velocity, and acceleration are written as + +.. math:: + :label: Discretized + + \underline{q} (x_1) &= \underline{\underline{N}} ~\hat{\underline{q}}~~~~\Delta \underline{q}^T = \left[ \Delta \underline{u}^T~~\Delta \underline{c}^T \right] \\ + \underline{v}(x_1) &= \underline{\underline{N}}~\hat{\underline{v}}~~~~\Delta \underline{v}^T = \left[\Delta \underline{\dot{u}}^T~~\Delta \underline{\omega}^T \right] \\ + \underline{a}(x_1) &= \underline{\underline{N}}~ \hat{\underline{a}}~~~~\Delta \underline{a}^T = \left[ \Delta \ddot{\underline{u}}^T~~\Delta \dot{\underline{\omega}}^T \right] + +where :math:`{\underline{\underline{N}}}` is the shape function matrix +and :math:`(\hat{\cdot})` denotes a column matrix of nodal values. + +The displacement fields in an element are approximated as + +.. math:: + :label: InterpolateDisp + + {\underline{u}}(\xi) &= h^k(\xi) {\underline{\hat{u}}}^k \\ + {\underline{u}}^\prime(\xi) &= h^{k\prime}(\xi) {\underline{\hat{u}}}^k + +where :math:`h^k(\xi)`, the component of shape function matrix +:math:`{\underline{\underline{N}}}`, is the :math:`p^{th}`-order +polynomial Lagrangian-interpolant shape function of node :math:`k`, +:math:`k=\{1,2,...,p+1\}`, :math:`{\underline{\hat{u}}}^k` is the +:math:`k^{th}` nodal value, and :math:`\xi \in \left[-1,1\right]` is the +element natural coordinate. However, as discussed in +:cite:`Bauchau-etal:2008`, the 3D rotation field cannot +simply be interpolated as the displacement field in the form of + +.. math:: + :label: InterpolateRot + + {\underline{c}}(\xi) &= h^k(\xi) {\underline{\hat{c}}}^k \\ + {\underline{c}}^\prime(\xi) &= h^{k \prime}(\xi) {\underline{\hat{c}}}^k + +where :math:`{\underline{c}}` is the rotation field in an element and +:math:`{\underline{\hat{c}}}^k` is the nodal value at the :math:`k^{th}` +node, for three reasons: + +1) rotations do not form a linear space so that they must be “composed” rather than added; +2) a rescaling operation is needed to eliminate the singularity existing in the vectorial rotation parameters; +3) the rotation field lacks objectivity, which, as defined by :cite:`Crisfield1999`, refers to the invariance of strain measures computed through interpolation to the addition of a rigid-bodymotion. + +Therefore, we adopt the more robust interpolation approach +proposed by :cite:`Crisfield1999` to deal with the finite +rotations. Our approach is described as follows + +Step 1: + Compute the nodal relative rotations, + :math:`{\underline{\hat{r}}}^k`, by removing the reference rotation, + :math:`{\underline{\hat{c}}}^1`, from the finite rotation at each + node, + :math:`{\underline{\hat{r}}}^k = ({\underline{\hat{c}}}^{1-}) \oplus + {\underline{\hat{c}}}^k`. It is noted that the minus sign on + :math:`{\underline{\hat{c}}}^1` denotes that the relative rotation + is calculated by removing the reference rotation from each node. The + composition in that equation is an equivalent of + :math:`{\underline{\underline{R}}}({\underline{\hat{r}}}^k) = {\underline{\underline{R}}}^T({\underline{\hat{c}}}^1)~{\underline{\underline{R}}}({\underline{{\underline{c}}}}^k).` + +Step 2: + Interpolate the relative-rotation field: + :math:`{\underline{r}}(\xi) = h^k(\xi) {\underline{\hat{r}}}^k` and + :math:`{\underline{r}}^\prime(\xi) = h^{k \prime}(\xi) {\underline{\hat{r}}}^k`. + Find the curvature field + :math:`{\underline{\kappa}}(\xi) = {\underline{\underline{R}}}({\underline{\hat{c}}}^1) {\underline{\underline{H}}}({\underline{r}}) {\underline{r}}^\prime`, + where :math:`{\underline{\underline{H}}}` is the tangent tensor that + relates the curvature vector :math:`{\underline{k}}` and rotation + vector :math:`{\underline{c}}` as + + .. math:: + :label: Tensor + + {\underline{k}} = {\underline{\underline{H}}}~ {\underline{c}}^\prime + +Step 3: + Restore the rigid-body rotation removed in Step 1: + :math:`{\underline{c}}(\xi) = {\underline{\hat{c}}}^1 \oplus {\underline{r}}(\xi)`. + +Note that the relative-rotation field can be computed with respect to +any of the nodes of the element; we choose node 1 as the reference node +for convenience. In the LSFE approach, shape functions (i.e., those +composing :math:`{\underline{\underline{N}}}`) are :math:`p^{th}`-order +Lagrangian interpolants, where nodes are located at the :math:`p+1` +Gauss-Lobatto-Legendre (GLL) points in the :math:`[-1,1]` element +natural-coordinate domain. :numref:`N4_lsfe` shows representative +LSFE basis functions for fourth- and eighth-order elements. Note that +nodes are clustered near element endpoints. More details on the LSFE and +its applications can be found in +References :cite:`Patera:1984,Ronquist:1987,Sprague:2003,Sprague:2004`. + + +.. _N4_lsfe: + +.. figure:: figs/n4.pdf + :width: 47% + :align: center + + Representative :math:`p+1` Lagrangian-interpolant shape functions in the element natural coordinates for a fourth-order LSFEs, where nodes are located at the Gauss-Lobatto-Legendre points. + +.. _N8_lsfe: + +.. figure:: figs/n8.pdf + :width: 47% + :align: center + + Representative :math:`p+1` Lagrangian-interpolant shape functions in the element natural coordinates for a eighth-order LSFEs, where nodes are located at the Gauss-Lobatto-Legendre points. + + + +Wiener-Milenković Rotation Parameter +------------------------------------ + +In BeamDyn, the 3D rotations are represented as Wiener-Milenković +parameters defined in the following equation: + +.. math:: + :label: WMParameter + + {\underline{c}} = 4 \tan\left(\frac{\phi}{4} \right) \bar{n} + +where :math:`\phi` is the rotation angle and :math:`\bar{n}` is the +unit vector of the rotation axis. It can be observed that the valid +range for this parameter is :math:`|\phi| < 2 \pi`. The singularities +existing at integer multiples of :math:`\pm 2 \pi` can be removed by a +rescaling operation at :math:`\pi` as: + +.. math:: + :label: RescaledWM + + {\underline{r}} = \begin{cases} + 4(q_0{\underline{p}} + p_0 {\underline{q}} + \tilde{p} {\underline{q}} ) / (\Delta_1 + \Delta_2), & \text{if } \Delta_2 \geq 0 \\ + -4(q_0{\underline{p}} + p_0 {\underline{q}} + \tilde{p} {\underline{q}} ) / (\Delta_1 - \Delta_2), & \text{if } \Delta_2 < 0 + \end{cases} + +where :math:`{\underline{p}}`, :math:`{\underline{q}}`, and +:math:`{\underline{r}}` are the vectorial parameterization of three +finite rotations such that +:math:`{\underline{\underline{R}}}({\underline{r}}) = {\underline{\underline{R}}}({\underline{p}}) {\underline{\underline{R}}}({\underline{q}})`, +:math:`p_0 = 2 - {\underline{p}}^T {\underline{p}}/8`, +:math:`q_0 = 2 - {\underline{q}}^T {\underline{q}}/8`, +:math:`\Delta_1 = (4-p_0)(4-q_0)`, and +:math:`\Delta_2 = p_0 q_0 - {\underline{p}}^T {\underline{q}}`. It is +noted that the rescaling operation could cause a discontinuity of the +interpolated rotation field; therefore a more robust interpolation +algorithm has been introduced in Section :ref:`num-imp` where the +rescaling-independent relative-rotation field is interpolated. + +The rotation tensor expressed in terms of Wiener-Milenković parameters is + +.. math:: + :label: eqn:RotTensorWM + + {\underline{\underline{R}}} ({\underline{c}}) = \frac{1}{(4-c_0)^2} + \begin{bmatrix} + c_0^2 + c_1^2 - c_2^2 - c_3^2 & 2(c_1 c_2 - c_0 c_3) & 2(c_1 c_3 + c_0 c_2) \\ + 2(c_1 c_2 + c_0 c_3) & c_0^2 - c_1^2 + c_2^2 - c_3^2 & 2(c_2 c_3 - c_0 c_1) \\ + 2(c_1 c_3 - c_0 c_2) & 2(c_2 c_3 + c_0 c_1) & c_0^2 - c_1^2 - c_2^2 + c_3^2 \\ + \end{bmatrix} + +where :math:`{\underline{c}} = \left[ c_1~~c_2~~c_3\right]^T` is the +Wiener-Milenković parameter and +:math:`c_0 = 2 - \frac{1}{8}{\underline{c}}^T {\underline{c}}`. The +relation between rotation tensor and direction cosine matrix (DCM) is + +.. math:: + :label: RT2DCM + + {\underline{\underline{R}}} = ({\underline{\underline{DCM}}})^T + +Interested users are referred to :cite:`Bauchau-etal:2008` +and :cite:`Wang:GEBT2013` for more details on the rotation +parameter and its implementation with GEBT. + +Linearization Process +--------------------- + +The nonlinear governing equations introduced in the previous section are +solved by Newton-Raphson method, where a linearization process is +needed. The linearization of each term in the governing equations are +presented in this section. + +According to :cite:`Bauchau:2010`, the linearized governing +equations in Eq.  :eq:`GovernGEBT-1-2` are in the form of + +.. math:: + :label: LinearizedEqn + + \hat{\underline{\underline{M}}} \Delta \hat{\underline{a}} +\hat{\underline{\underline{G}}} \Delta \hat{\underline{v}}+ \hat{\underline{\underline{K}}} \Delta \hat{\underline{q}} = \hat{\underline{F}}^{ext} - \hat{\underline{F}} + +where the :math:`\hat{{\underline{\underline{M}}}}`, +:math:`\hat{{\underline{\underline{G}}}}`, and +:math:`\hat{{\underline{\underline{K}}}}` are the elemental mass, +gyroscopic, and stiffness matrices, respectively; +:math:`\hat{{\underline{F}}}` and :math:`\hat{{\underline{F}}}^{ext}` +are the elemental forces and externally applied loads, respectively. +They are defined for an element of length :math:`l` along :math:`x_1` as +follows + +.. math:: + :label: hatMGKFFext + + \hat{{\underline{\underline{M}}}}&= \int_0^l \underline{\underline{N}}^T \mathcal{\underline{\underline{M}}} ~\underline{\underline{N}} dx_1 \\ + \hat{{\underline{\underline{G}}}} &= \int_0^l {\underline{\underline{N}}}^T {\underline{\underline{\mathcal{G}}}}^I~{\underline{\underline{N}}} dx_1\\ + \hat{{\underline{\underline{K}}}}&=\int_0^l \left[ {\underline{\underline{N}}}^T ({\underline{\underline{\mathcal{K}}}}^I + \mathcal{{\underline{\underline{Q}}}})~ {\underline{\underline{N}}} + {\underline{\underline{N}}}^T \mathcal{{\underline{\underline{P}}}}~ {\underline{\underline{N}}}^\prime + {\underline{\underline{N}}}^{\prime T} \mathcal{{\underline{\underline{C}}}}~ {\underline{\underline{N}}}^\prime + {\underline{\underline{N}}}^{\prime T} \mathcal{{\underline{\underline{O}}}}~ {\underline{\underline{N}}} \right] d x_1 \\ + \hat{{\underline{F}}} &= \int_0^l ({\underline{\underline{N}}}^T {\underline{\mathcal{F}}}^I + {\underline{\underline{N}}}^T \mathcal{{\underline{F}}}^D + {\underline{\underline{N}}}^{\prime T} \mathcal{{\underline{F}}}^C)dx_1 \\ + \hat{{\underline{F}}}^{ext}& = \int_0^l {\underline{\underline{N}}}^T \mathcal{{\underline{F}}}^{ext} dx_1 + +where :math:`\mathcal{{\underline{F}}}^{ext}` is the applied load +vector. The new matrix notations in Eqs. :eq:`hatMGKFFext` to are briefly introduced +here. :math:`\mathcal{{\underline{F}}}^C` and +:math:`\mathcal{{\underline{F}}}^D` are elastic forces obtained from +Eq. :eq:`GovernGEBT-1-2` as + +.. math:: + :label: FCD + + \mathcal{{\underline{F}}}^C &= \begin{Bmatrix} + {\underline{F}} \\ + {\underline{M}} + \end{Bmatrix} = {\underline{\underline{\mathcal{C}}}} \begin{Bmatrix} + {\underline{\epsilon}} \\ + {\underline{\kappa}} + \end{Bmatrix} \\ + \mathcal{{\underline{F}}}^D & = \begin{bmatrix} + \underline{\underline{0}} & \underline{\underline{0}}\\ + (\tilde{x}_0^\prime+\tilde{u}^\prime)^T & \underline{\underline{0}} + \end{bmatrix} + \mathcal{{\underline{F}}}^C \equiv {\underline{\underline{\Upsilon}}}~ \mathcal{{\underline{F}}}^C + +where :math:`\underline{\underline{0}}` denotes a :math:`3 \times 3` +null matrix. The :math:`{\underline{\underline{\mathcal{G}}}}^I`, +:math:`{\underline{\underline{\mathcal{K}}}}^I`, +:math:`\mathcal{{\underline{\underline{O}}}}`, +:math:`\mathcal{{\underline{\underline{P}}}}`, +:math:`\mathcal{{\underline{\underline{Q}}}}`, and +:math:`{\underline{\mathcal{F}}}^I` in Eqs. :eq:`hatMGKFFext`  are defined as + +.. math:: + :label: mathcalGKOPFI + + {\underline{\underline{\mathcal{G}}}}^I &= \begin{bmatrix} + {\underline{\underline{0}}} & (\widetilde{\tilde{\omega} m {\underline{\eta}}})^T+\tilde{\omega} m \tilde{\eta}^T \\ + {\underline{\underline{0}}} & \tilde{\omega} {\underline{\underline{\varrho}}}-\widetilde{{\underline{\underline{\varrho}}} {\underline{\omega}}} + \end{bmatrix} \\ + {\underline{\underline{\mathcal{K}}}}^I &= \begin{bmatrix} + {\underline{\underline{0}}} & \dot{\tilde{\omega}}m\tilde{\eta}^T + \tilde{\omega} \tilde{\omega}m\tilde{\eta}^T \\ + {\underline{\underline{0}}} & \ddot{\tilde{u}}m\tilde{\eta} + {\underline{\underline{\varrho}}} \dot{\tilde{\omega}}-\widetilde{{\underline{\underline{\varrho}}} {\underline{\dot{\omega}}}}+\tilde{\omega} {\underline{\underline{\varrho}}} \tilde{\omega} - \tilde{\omega} \widetilde{{\underline{\underline{\varrho}}} {\underline{\omega}}} + \end{bmatrix}\\ + \mathcal{{\underline{\underline{O}}}} &= \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{C}}}_{11} \tilde{E_1} - \tilde{F} \\ + {\underline{\underline{0}}}& {\underline{\underline{C}}}_{21} \tilde{E_1} - \tilde{M} + \end{bmatrix} \\ + \mathcal{{\underline{\underline{P}}}} &= \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{0}}} \\ + \tilde{F} + ({\underline{\underline{C}}}_{11} \tilde{E_1})^T & ({\underline{\underline{C}}}_{21} \tilde{E_1})^T + \end{bmatrix} \\ + \mathcal{{\underline{\underline{Q}}}} &= {\underline{\underline{\Upsilon}}}~ \mathcal{{\underline{\underline{O}}}} \\ + {\underline{\mathcal{F}}}^I &= \begin{Bmatrix} + m \ddot{{\underline{u}}} + (\dot{\tilde{\omega}} + \tilde{\omega} \tilde{\omega})m {\underline{\eta}} \\ + m \tilde{\eta} \ddot{{\underline{u}}} +{\underline{\underline{\varrho}}}\dot{{\underline{\omega}}}+\tilde{\omega}{\underline{\underline{\varrho}}}{\underline{\omega}} + \end{Bmatrix} + +where :math:`m` is the mass density per unit length, +:math:`{\underline{\eta}}` is the location of the sectional center of +mass, :math:`{\underline{\underline{\varrho}}}` is the moment of inertia +tensor, and the following notations were introduced to simplify the +above expressions + +.. math:: + :label: E1-PartC + + {\underline{E}}_1 &= {\underline{x}}_0^\prime + {\underline{u}}^\prime \\ + {\underline{\underline{\mathcal{C}}}} &= \begin{bmatrix} + {\underline{\underline{C}}}_{11} & {\underline{\underline{C}}}_{12} \\ + {\underline{\underline{C}}}_{21} & {\underline{\underline{C}}}_{22} + \end{bmatrix} + +Damping Forces and Linearization +-------------------------------- + +A viscous damping model has been implemented into BeamDyn to account for +the structural damping effect. The damping force is defined as + +.. math:: + :label: Damping + + {\underline{f}}_d = {\underline{\underline{\mu}}}~ {\underline{\underline{\mathcal{C}}}} \begin{Bmatrix} + \dot{\epsilon} \\ + \dot{\kappa} + \end{Bmatrix} + +where :math:`{\underline{\underline{\mu}}}` is a user-defined +damping-coefficient diagonal matrix. The damping force can be recast in +two separate parts, like :math:`{\underline{\mathcal{F}}}^C` and +:math:`{\underline{\mathcal{F}}}^D` in the elastic force, as + +.. math:: + :label: DampingForce-1-2 + + {\underline{\mathcal{F}}}^C_d &= \begin{Bmatrix} + {\underline{F}}_d \\ + {\underline{M}}_d + \end{Bmatrix} \\ + {\underline{\mathcal{F}}}^D_d &= \begin{Bmatrix} + {\underline{0}} \\ + (\tilde{x}^\prime_0 + \tilde{u}^\prime)^T \underline{F}_d + \end{Bmatrix} + +The linearization of the structural damping forces are as follows: + +.. math:: + :label: DampingForceLinear-1-2 + + \Delta {\underline{\mathcal{F}}}^C_d &= {\underline{\underline{\mathcal{S}}}}_d \begin{Bmatrix} + \Delta {\underline{u}}^\prime \\ + \Delta {\underline{c}}^\prime + \end{Bmatrix} + {\underline{\underline{\mathcal{O}}}}_d \begin{Bmatrix} + \Delta {\underline{u}} \\ + \Delta {\underline{c}} + \end{Bmatrix} + {\underline{\underline{\mathcal{G}}}}_d \begin{Bmatrix} + \Delta {\underline{\dot{u}}} \\ + \Delta {\underline{\omega}} + \end{Bmatrix} + {\underline{\underline{\mu}}} ~{\underline{\underline{C}}} \begin{Bmatrix} + \Delta {\underline{\dot{u}}}^\prime \\ + \Delta {\underline{\omega}}^\prime + \end{Bmatrix} \\ + \Delta {\underline{\mathcal{F}}}^D_d &= {\underline{\underline{\mathcal{P}}}}_d \begin{Bmatrix} + \Delta {\underline{u}}^\prime \\ + \Delta {\underline{c}}^\prime + \end{Bmatrix} + {\underline{\underline{\mathcal{Q}}}}_d \begin{Bmatrix} + \Delta {\underline{u}} \\ + \Delta {\underline{c}} + \end{Bmatrix} + {\underline{\underline{\mathcal{X}}}}_d \begin{Bmatrix} + \Delta {\underline{\dot{u}}} \\ + \Delta {\underline{\omega}} + \end{Bmatrix} + {\underline{\underline{\mathcal{Y}}}}_d \begin{Bmatrix} + \Delta {\underline{\dot{u}}}^\prime \\ + \Delta {\underline{\omega}}^\prime + \end{Bmatrix} + +where the newly introduced matrices are defined as + +.. math:: + :label: DampingSd-Od-Gd-Pd-Qd-Xd-Yd + + {\underline{\underline{\mathcal{S}}}}_d &= + {\underline{\underline{\mu}}} {\underline{\underline{\mathcal{C}}}} \begin{bmatrix} + \tilde{\omega}^T & {\underline{\underline{0}}} \\ + {\underline{\underline{0}}} & \tilde{\omega}^T + \end{bmatrix} \\ + {\underline{\underline{\mathcal{O}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{\mu}}} {\underline{\underline{C}}}_{11} (\dot{\tilde{u}}^\prime - \tilde{\omega} \tilde{E}_1) - \tilde{F}_d \\ + {\underline{\underline{0}}} &{\underline{\underline{\mu}}} {\underline{\underline{C}}}_{21} (\dot{\tilde{u}}^\prime - \tilde{\omega} \tilde{E}_1) - \tilde{M}_d + \end{bmatrix} \\ + {\underline{\underline{\mathcal{G}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{C}}}_{11}^T {\underline{\underline{\mu}}}^T \tilde{E}_1 \\ + {\underline{\underline{0}}} & {\underline{\underline{C}}}_{12}^T {\underline{\underline{\mu}}}^T \tilde{E}_1 + \end{bmatrix} \\ + {\underline{\underline{\mathcal{P}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{0}}} \\ + \tilde{F}_d + \tilde{E}_1^T {\underline{\underline{\mu}}} {\underline{\underline{C}}}_{11} \tilde{\omega}^T & \tilde{E}_1^T {\underline{\underline{\mu}}} {\underline{\underline{C}}}_{12} \tilde{\omega}^T + \end{bmatrix} \\ + {\underline{\underline{\mathcal{Q}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{0}}} \\ + {\underline{\underline{0}}} & \tilde{E}_1^T {\underline{\underline{O}}}_{12} + \end{bmatrix} \\ + {\underline{\underline{\mathcal{X}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{0}}} \\ + {\underline{\underline{0}}} & \tilde{E}_1^T {\underline{\underline{G}}}_{12} + \end{bmatrix} \\ + {\underline{\underline{\mathcal{Y}}}}_d &= + \begin{bmatrix} + {\underline{\underline{0}}} & {\underline{\underline{0}}} \\ + \tilde{E}_1^T {\underline{\underline{\mu}}} {\underline{\underline{C}}}_{11} & \tilde{E}_1^T {\underline{\underline{\mu}}} {\underline{\underline{C}}}_{12} + \end{bmatrix} \\ + +where :math:`{\underline{\underline{O}}}_{12}` and +:math:`{\underline{\underline{G}}}_{12}` are the :math:`3 \times 3` sub +matrices of :math:`\mathcal{{\underline{\underline{O}}}}` and +:math:`\mathcal{{\underline{\underline{G}}}}` as +:math:`{\underline{\underline{C}}}_{12}` in Eq. :eq:`E1-PartC`. + +.. _convergence-criterion: + +Convergence Criterion and Generalized-\ :math:`\alpha` Time Integrator +---------------------------------------------------------------------- + +The system of nonlinear equations in Eqs. :eq:`GovernGEBT-1-2` are solved using the +Newton-Raphson method with the linearized form in Eq. :eq:`LinearizedEqn`. In the present +implementation, an energy-like stopping criterion has been chosen, which +is calculated as + +.. math:: + :label: StoppingCriterion + + | \Delta \mathbf{U}^{(i)T} \left( {^{t+\Delta t}} \mathbf{R} - {^{t+\Delta t}} \mathbf{F}^{(i-1)} \right) | \leq | \epsilon_E \left( \Delta \mathbf{U}^{(1)T} \left( {^{t+\Delta t}} \mathbf{R} - {^t}\mathbf{F} \right) \right) | + +where :math:`|\cdot|` denotes the absolute value, +:math:`\Delta \mathbf{U}` is the incremental displacement vector, +:math:`\mathbf{R}` is the vector of externally applied nodal point +loads, :math:`\mathbf{F}` is the vector of nodal point forces +corresponding to the internal element stresses, and :math:`\epsilon_E` +is the user-defined energy tolerance. The superscript on the left side +of a variable denotes the time-step number (in a dynamic analysis), +while the one on the right side denotes the Newton-Raphson iteration +number. As pointed out by :cite:`Bathe-Cimento:1980`, this +criterion provides a measure of when both the displacements and the +forces are near their equilibrium values. + +Time integration is performed using the generalized-\ :math:`\alpha` +scheme in BeamDyn, which is an unconditionally stable (for linear +systems), second-order accurate algorithm. The scheme allows for users +to choose integration parameters that introduce high-frequency numerical +dissipation. More details regarding the generalized-\ :math:`\alpha` +method can be found in :cite:`Chung-Hulbert:1993,Bauchau:2010`. + +Calculation of Reaction Loads +----------------------------- + +Since the root motion of the wind turbine blade, including displacements +and rotations, translational and angular velocities, and translational +and angular accelerates, are prescribed as inputs to BeamDyn either by +the driver (in stand-alone mode) or by FAST glue code (in FAST-coupled +mode), the reaction loads at the root are needed to satisfy equality of +the governing equations. The reaction loads at the root are also the +loads passing from blade to hub in a full turbine analysis. + +The governing equations in Eq. :eq:`GovernGEBT-1-2` can be recast in a compact form + +.. math:: + :label: CompactGovern + + {\underline{\mathcal{F}}}^I - {\underline{\mathcal{F}}}^{C\prime} + {\underline{\mathcal{F}}}^D = {\underline{\mathcal{F}}}^{ext} + +with all the vectors defined in Section [sec:LinearProcess]. At the +blade root, the governing equation is revised as + +.. math:: + :label: CompactGovernRoot + + {\underline{\mathcal{F}}}^I - {\underline{\mathcal{F}}}^{C\prime} + {\underline{\mathcal{F}}}^D = {\underline{\mathcal{F}}}^{ext}+{\underline{\mathcal{F}}}^R + +where :math:`{\underline{\mathcal{F}}}^R = \left[ {\underline{F}}^R~~~{\underline{M}}^R\right]^T` +is the reaction force vector and it can be solved from +Eq. :eq:`CompactGovernRoot` given that the motion fields are known at this +point. + +Calculation of Blade Loads +-------------------------- + +BeamDyn can also calculate the blade loads at each finite element node +along the blade axis. The governing equation in Eq. :eq:`CompactGovern` are +recast as + +.. math:: + :label: GovernBF + + {\underline{\mathcal{F}}}^A + {\underline{\mathcal{F}}}^V - {\underline{\mathcal{F}}}^{C\prime} + {\underline{\mathcal{F}}}^D = {\underline{\mathcal{F}}}^{ext} + +where the inertial force vector :math:`{\underline{\mathcal{F}}}^I` is +split into :math:`{\underline{\mathcal{F}}}^A` and :math:`{\underline{\mathcal{F}}}^V`: + +.. math:: + :label: mathcalFA-FV + + {\underline{\mathcal{F}}}^A &= \begin{Bmatrix} + m \ddot{{\underline{u}}} + \dot{\tilde{\omega}}m {\underline{\eta}}\\ + m \tilde{\eta} \ddot{{\underline{u}}} + {\underline{\underline{\rho}}} \dot{{\underline{\omega}}} + \end{Bmatrix} \\ + {\underline{\mathcal{F}}}^V &= \begin{Bmatrix} + \tilde{\omega} \tilde{\omega} m {\underline{\eta}}\\ + \tilde{\omega} {\underline{\underline{\rho}}} {\underline{\omega}} + \end{Bmatrix} \\ + +The blade loads are thus defined as + +.. math:: + :label: BladeForce + + {\underline{\mathcal{F}}}^{BF} \equiv {\underline{\mathcal{F}}}^V - {\underline{\mathcal{F}}}^{C\prime} + {\underline{\mathcal{F}}}^D + +We note that if structural damping is considered in the analysis, the +:math:`{\underline{\mathcal{F}}}^{C}_d` and +:math:`{\underline{\mathcal{F}}}^D_d` are incorporated into the internal +elastic forces, :math:`{\underline{\mathcal{F}}}^C` and +:math:`{\underline{\mathcal{F}}}^D`, for calculation. diff --git a/OpenFAST/docs/source/user/beamdyn/zrefs.rst b/OpenFAST/docs/source/user/beamdyn/zrefs.rst new file mode 100644 index 000000000..c434bde8a --- /dev/null +++ b/OpenFAST/docs/source/user/beamdyn/zrefs.rst @@ -0,0 +1,9 @@ +.. only:: html + + References + ---------- + +.. bibliography:: references.bib + + + diff --git a/OpenFAST/docs/source/user/cppapi/files/cDriver.i b/OpenFAST/docs/source/user/cppapi/files/cDriver.i new file mode 100644 index 000000000..6a1391219 --- /dev/null +++ b/OpenFAST/docs/source/user/cppapi/files/cDriver.i @@ -0,0 +1,53 @@ +# -*- mode: yaml -*- +# +# C++ glue-code for OpenFAST - Example input file +# + +#Total number of turbines in the simulation +nTurbinesGlob: 3 +#Enable debug outputs if set to true +debug: False +#The simulation will not run if dryRun is set to true +dryRun: False +#Flag indicating whether the simulation starts from scratch or restart +simStart: init # init/trueRestart/restartDriverInitFAST +#Start time of the simulation +tStart: 0.0 +#End time of the simulation. tEnd <= tMax +tEnd: 1.0 +#Max time of the simulation +tMax: 4.0 +#Time step for FAST. All turbines should have the same time step. +dtFAST: 0.00625 +#Restart files will be written every so many time steps +nEveryCheckPoint: 160 + +Turbine0: + #The position of the turbine base for actuator-line simulations + turbine_base_pos: [ 0.0, 0.0, 0.0 ] + #The number of actuator points along each blade for actuator-line simulations + num_force_pts_blade: 0 + #The number of actuator points along the tower for actuator-line simulations. + num_force_pts_tower: 0 + #The checkpoint file for this turbine when restarting a simulation + restart_filename: "banana" + #The FAST input file for this turbine + FAST_input_filename: "t1_Test05.fst" + #A unique turbine id for each turbine + turb_id: 1 + +Turbine1: + turbine_base_pos: [ 0.0, 0.0, 0.0 ] + num_force_pts_blade: 0 + num_force_pts_tower: 0 + restart_filename: "banana" + FAST_input_filename: "t2_Test05.fst" + turb_id: 2 + +Turbine2: + turbine_base_pos: [ 0.0, 0.0, 0.0 ] + num_force_pts_blade: 0 + num_force_pts_tower: 0 + restart_filename: "banana" + FAST_input_filename: "t3_Test05.fst" + turb_id: 3 diff --git a/OpenFAST/docs/source/user/cppapi/index.rst b/OpenFAST/docs/source/user/cppapi/index.rst new file mode 100644 index 000000000..f36446556 --- /dev/null +++ b/OpenFAST/docs/source/user/cppapi/index.rst @@ -0,0 +1,94 @@ +C++ API Users Guide +=================== + +.. only:: html + + This document offers a quick reference guide for the C++ API and glue + code. It is intended to be used by the general user in combination + with other OpenFAST manuals. The manual will be updated as new releases are + issued and as needed to provide further information on advancements or + modifications to the software. + +The C++ API provides a high level API to run OpenFAST through a C++ gluecode. The primary purpose of the C++ API is to help interface OpenFAST to external programs like CFD solvers that are typically written in C++. The installation of C++ API is enabled via CMake by turning on the :cmakeval:`BUILD_OPENFAST_CPP_API` flag. + +A sample glue-code `FAST_Prog.cpp <https://github.com/OpenFAST/openfast/blob/dev/glue-codes/openfast-cpp/src/FAST_Prog.cpp>`_ is provided as a demonstration of the usage of the C++ API. The glue-code allows for the simulation of multiple turbines using OpenFAST in parallel over multiple processors. The glue-code takes a single input file named ``cDriver.i`` (:download:`download <files/cDriver.i>`). + +.. literalinclude:: files/cDriver.i + :language: yaml + +Command line invocation +----------------------- + +.. code-block:: bash + + mpiexec -np <N> openfastcpp + +Common input file options +------------------------- + +.. confval:: nTurbinesGlob + + Total number of turbines in the simulation. The input file must contain a number of turbine specific sections (`Turbine0`, `Turbine1`, ..., `Turbine(n-1)`) that is consistent with `nTurbinesGlob`. + +.. confval:: debug + + Enable debug outputs if set to true + +.. confval:: dryRun + + The simulation will not run if dryRun is set to true. However, the simulation will read the input files, allocate turbines to processors and prepare to run the individual turbine instances. This flag is useful to test the setup of the simulation before running it. + +.. confval:: simStart + + Flag indicating whether the simulation starts from scratch or restart. ``simStart`` takes on one of three values: + + * ``init`` - Use this option when starting a simulation from `t=0s`. + * ``trueRestart`` - While OpenFAST allows for restart of a turbine simulation, external components like the Bladed style controller may not. Use this option when all components of the simulation are known to restart. + * ``restartDriverInitFAST`` - When the ``restartDriverInitFAST`` option is selected, the individual turbine models start from `t=0s` and run up to the specified restart time using the inflow data stored at the actuator nodes from a hdf5 file. The C++ API stores the inflow data at the actuator nodes in a hdf5 file at every OpenFAST time step and then reads it back when using this restart option. This restart option is especially useful when the glue code is a CFD solver. + +.. confval:: tStart + + Start time of the simulation + +.. confval:: tEnd + + End time of the simulation. tEnd <= tMax + +.. confval:: tMax + + Max time of the simulation + +.. confval:: dtFAST + + Time step for FAST. All turbines should have the same time step. + +.. confval:: nEveryCheckPoint + + Restart files will be written every so many time steps + +Turbine specific input options +------------------------------ + +.. confval:: turbine_base_pos + + The position of the turbine base for actuator-line simulations + +.. confval:: num_force_pts_blade + + The number of actuator points along each blade for actuator-line simulations + +.. confval:: num_force_pts_tower + + The number of actuator points along the tower for actuator-line simulations. + +.. confval:: restart_filename + + The checkpoint file for this turbine when restarting a simulation + +.. confval:: FAST_input_filename + + The FAST input file for this turbine + +.. confval:: turb_id + + A unique turbine id for each turbine diff --git a/OpenFAST/docs/source/user/elastodyn/EDNodalOutputs.rst b/OpenFAST/docs/source/user/elastodyn/EDNodalOutputs.rst new file mode 100644 index 000000000..6c0a4abd2 --- /dev/null +++ b/OpenFAST/docs/source/user/elastodyn/EDNodalOutputs.rst @@ -0,0 +1,41 @@ + +Nodal Outputs +~~~~~~~~~~~~~ + +In addition to the named outputs in :numref:`ED-Outputs` above, ElastoDyn allows +for outputting the full set blade node motions and loads (tower nodes +unavailable at present). Please refer to the ElastoDyn_Nodes tab in the +Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` +for a complete list of possible output parameters. + +This section follows the `END` statement from normal Outputs section described +above, and includes a separator description line followed by the following +optinos. + +**BldNd_BladesOut** specifies the number of blades to output. Possible values +are 0 through the number of blades ElastoDyn is modeling. If the value is set to +1, only blade 1 will be output, and if the value is 2, blades 1 and 2 will be +output. + +**BldNd_BlOutNd** specifies which nodes to output. This is currently unused. + +The **OutList** section controls the nodal output quantities generated by +ElastoDyn. In this section, the user specifies the name of the channel family to +output. The output name for each channel is then created internally by ElastoDyn +by combining the blade number, node number, and channel family name. For +example, if the user specifies **TDx** as the channel family name, the output +channels will be named with the convention of **B**\ :math:`\mathbf{\beta}`\ +**N###TDx** where :math:`\mathbf{\beta}` is the blade number, and **###** is the +three digit node number. + + +Sample Nodal Outputs section +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This sample includes the ``END`` statement from the regular outputs section. + +.. container:: + :name: File:EDNodalOutputs + + .. literalinclude:: exampleInput/NodalOutpus.txt + :linenos: diff --git a/OpenFAST/docs/source/user/elastodyn/exampleInput/NodalOutpus.txt b/OpenFAST/docs/source/user/elastodyn/exampleInput/NodalOutpus.txt new file mode 100644 index 000000000..db15b8e79 --- /dev/null +++ b/OpenFAST/docs/source/user/elastodyn/exampleInput/NodalOutpus.txt @@ -0,0 +1,26 @@ +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +---------------------- NODE OUTPUTS -------------------------------------------- + 3 BldNd_BladesOut - Blades to output + 99 BldNd_BlOutNd - Blade nodes on each blade (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx, ElastoDyn_Nodes tab for a listing of available output channels, (-) +"ALx" - local flapwise acceleration (absolute) of node +"ALy" - local flapwise acceleration (absolute) of node +"ALz" - local flapwise acceleration (absolute) of node +"TDx" - local flapwise (translational) deflection (relative to the undeflected position) of node +"TDy" - local edgewise (translational) deflection (relative to the undeflected position) of node +"TDz" - local axial (translational) deflection (relative to the undeflected position) of node +"RDx" - Local rotational displacement about x-axis (relative to undeflected) +"RDy" - Local rotational displacement about y-axis (relative to undeflected) +"RDz" - Local rotational displacement about z-axis (relative to undeflected) +"MLx" - local edgewise moment at node +"MLy" - local flapwise moment at node +"MLz" - local pitching moment at node +"FLx" - local flapwise shear force at node +"FLy" - local edgewise shear force at node +"FLz" - local axial force at node +"MLxNT" - Edgewise moment in local coordinate system (initial structural twist removed) +"MlyNT" - Flapwise shear moment in local coordinate system (initial structural twist removed) +"FLxNT" - Flapwise shear force in local coordinate system (initial structural twist removed) +"FlyNT" - Edgewise shear force in local coordinate system (initial structural twist removed) +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/docs/source/user/elastodyn/index.rst b/OpenFAST/docs/source/user/elastodyn/index.rst new file mode 100644 index 000000000..d3ef2bdb8 --- /dev/null +++ b/OpenFAST/docs/source/user/elastodyn/index.rst @@ -0,0 +1,18 @@ +ElastoDyn Users Guide and Theory Manual +======================================= + +.. only:: html + + This document offers a quick reference guide for the ElastoDyn software + program. It is intended to be used by the general user in combination + with other OpenFAST manuals. The manual will be updated as new releases are + issued and as needed to provide further information on advancements or + modifications to the software. + + The documentation here is incomplete. + + +.. toctree:: + + input.rst + diff --git a/OpenFAST/docs/source/user/elastodyn/input.rst b/OpenFAST/docs/source/user/elastodyn/input.rst new file mode 100644 index 000000000..14e7accc1 --- /dev/null +++ b/OpenFAST/docs/source/user/elastodyn/input.rst @@ -0,0 +1,366 @@ +.. _ed_input: + +Input Files +=========== + +The user configures the structural model parameters via a primary ElastoDyn +input file, as well as separate input files for the tower and *other stuff that +will be documented here later.* + +No lines should be added or removed from the input files. + +Units +----- + +ElastoDyn uses the SI system (kg, m, s, N). Angles are assumed to be in +radians unless otherwise specified. + +ElastoDyn Primary Input File +---------------------------- + +The primary ElastoDyn input file defines modeling options and geometries for the +OpenFAST structure including the tower, nacelle, drivetrain, and blades (if +BeamDyn is not used). It also sets the initial conditions for the structure. + +Simulation Control +~~~~~~~~~~~~~~~~~~ + +Set the **Echo** flag to TRUE if you wish to have ElastoDyn echo the +contents of the ElastoDyn primary, airfoil, and blade input files (useful +for debugging errors in the input files). The echo file has the naming +convention of *OutRootFile.ED.ech*. **OutRootFile** is either +specified in the I/O SETTINGS section of the driver input file when +running ElastoDyn standalone, or by the OpenFAST program when running a +coupled simulation. + +**Method** + +**dT** + +Environmental Condition +~~~~~~~~~~~~~~~~~~~~~~~ + +**gravity** + +Degrees of Freedom +~~~~~~~~~~~~~~~~~~ + +**FlapDOF1** - First flapwise blade mode DOF (flag) + +**FlapDOF2** - Second flapwise blade mode DOF (flag) + +**EdgeDOF** - First edgewise blade mode DOF (flag) + +**TeetDOF** - Rotor-teeter DOF (flag) [unused for 3 blades] + +**DrTrDOF** - Drivetrain rotational-flexibility DOF (flag) + +**GenDOF** - Generator DOF (flag) + +**YawDOF** - Yaw DOF (flag) + +**TwFADOF1** - First fore-aft tower bending-mode DOF (flag) + +**TwFADOF2** - Second fore-aft tower bending-mode DOF (flag) + +**TwSSDOF1** - First side-to-side tower bending-mode DOF (flag) + +**TwSSDOF2** - Second side-to-side tower bending-mode DOF (flag) + +**PtfmSgDOF** - Platform horizontal surge translation DOF (flag) + +**PtfmSwDOF** - Platform horizontal sway translation DOF (flag) + +**PtfmHvDOF** - Platform vertical heave translation DOF (flag) + +**PtfmRDOF** - Platform roll tilt rotation DOF (flag) + +**PtfmPDOF** - Platform pitch tilt rotation DOF (flag) + +**PtfmYDOF** - Platform yaw rotation DOF (flag) + + + +Initial Conditions +~~~~~~~~~~~~~~~~~~ + +**OoPDefl** - Initial out-of-plane blade-tip displacement (meters) + +**IPDefl** - Initial in-plane blade-tip deflection (meters) + +**BlPitch(1)** - Blade 1 initial pitch (degrees) + +**BlPitch(2)** - Blade 2 initial pitch (degrees) + +**BlPitch(3)** - Blade 3 initial pitch (degrees) [unused for 2 blades] + +**TeetDefl** - Initial or fixed teeter angle (degrees) [unused for 3 blades] + +**Azimuth** - Initial azimuth angle for blade 1 (degrees) + +**RotSpeed** - Initial or fixed rotor speed (rpm) + +**NacYaw** - Initial or fixed nacelle-yaw angle (degrees) + +**TTDspFA** - Initial fore-aft tower-top displacement (meters) + +**TTDspSS** - Initial side-to-side tower-top displacement (meters) + +**PtfmSurge** - Initial or fixed horizontal surge translational displacement of platform (meters) + +**PtfmSway** - Initial or fixed horizontal sway translational displacement of platform (meters) + +**PtfmHeave** - Initial or fixed vertical heave translational displacement of platform (meters) + +**PtfmRoll** - Initial or fixed roll tilt rotational displacement of platform (degrees) + +**PtfmPitch** - Initial or fixed pitch tilt rotational displacement of platform (degrees) + +**PtfmYaw** - Initial or fixed yaw rotational displacement of platform (degrees) + +Turbine Configuration +~~~~~~~~~~~~~~~~~~~~~ + +**NumBl** - Number of blades (-) + +**TipRad** - The distance from the rotor apex to the blade tip (meters) + +**HubRad** - The distance from the rotor apex to the blade root (meters) + +**PreCone(1)** - Blade 1 cone angle (degrees) + +**PreCone(2)** - Blade 2 cone angle (degrees) + +**PreCone(3)** - Blade 3 cone angle (degrees) [unused for 2 blades] + +**HubCM** - Distance from rotor apex to hub mass [positive downwind] (meters) + +**UndSling** - Undersling length [distance from teeter pin to the rotor apex] (meters) [unused for 3 blades] + +**Delta3** - Delta-3 angle for teetering rotors (degrees) [unused for 3 blades] + +**AzimB1Up** - Azimuth value to use for I/O when blade 1 points up (degrees) + +**OverHang** - Distance from yaw axis to rotor apex [3 blades] or teeter pin [2 blades] (meters) + +**ShftGagL** - Distance from rotor apex [3 blades] or teeter pin [2 blades] to shaft strain gages [positive for upwind rotors] (meters) + +**ShftTilt** - Rotor shaft tilt angle (degrees) + +**NacCMxn** - Downwind distance from the tower-top to the nacelle CM (meters) + +**NacCMyn** - Lateral distance from the tower-top to the nacelle CM (meters) + +**NacCMzn** - Vertical distance from the tower-top to the nacelle CM (meters) + +**NcIMUxn** - Downwind distance from the tower-top to the nacelle IMU (meters) + +**NcIMUyn** - Lateral distance from the tower-top to the nacelle IMU (meters) + +**NcIMUzn** - Vertical distance from the tower-top to the nacelle IMU (meters) + +**Twr2Shft** - Vertical distance from the tower-top to the rotor shaft (meters) + +**TowerHt** - Height of tower above ground level [onshore] or MSL [offshore] (meters) + +**TowerBsHt** - Height of tower base above ground level [onshore] or MSL [offshore] (meters) + +**PtfmCMxt** - Downwind distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters) + +**PtfmCMyt** - Lateral distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters) + +**PtfmCMzt** - Vertical distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters) + +**PtfmRefzt** - Vertical distance from the ground level [onshore] or MSL [offshore] to the platform reference point (meters) + + + +Mass and Inertia +~~~~~~~~~~~~~~~~ + +**TipMass(1)** - Tip-brake mass, blade 1 (kg) + +**TipMass(2)** - Tip-brake mass, blade 2 (kg) + +**TipMass(3)** - Tip-brake mass, blade 3 (kg) [unused for 2 blades] + +**HubMass** - Hub mass (kg) + +**HubIner** - Hub inertia about rotor axis [3 blades] or teeter axis [2 blades] (kg m^2) + +**GenIner** - Generator inertia about HSS (kg m^2) + +**NacMass** - Nacelle mass (kg) + +**NacYIner** - Nacelle inertia about yaw axis (kg m^2) + +**YawBrMass** - Yaw bearing mass (kg) + +**PtfmMass** - Platform mass (kg) + +**PtfmRIner** - Platform inertia for roll tilt rotation about the platform CM (kg m^2) + +**PtfmPIner** - Platform inertia for pitch tilt rotation about the platform CM (kg m^2) + +**PtfmYIner** - Platform inertia for yaw rotation about the platform CM (kg m^2) + + + +Blade +~~~~~ + +**BldNodes** - Number of blade nodes (per blade) used for analysis (-) + +**BldFile(1)** - Name of file containing properties for blade 1 (quoted string) + +**BldFile(2)** - Name of file containing properties for blade 2 (quoted string) + +**BldFile(3)** - Name of file containing properties for blade 3 (quoted string) [unused for 2 blades] + + +Rotor-Teeter +~~~~~~~~~~~~ + +**TeetMod** - Rotor-teeter spring/damper model {0: none, 1: standard, 2: user-defined from routine UserTeet} (switch) [unused for 3 blades] + +**TeetDmpP** - Rotor-teeter damper position (degrees) [used only for 2 blades and when TeetMod=1] + +**TeetDmp** - Rotor-teeter damping constant (N-m/(rad/s)) [used only for 2 blades and when TeetMod=1] + +**TeetCDmp** - Rotor-teeter rate-independent Coulomb-damping moment (N-m) [used only for 2 blades and when TeetMod=1] + +**TeetSStP** - Rotor-teeter soft-stop position (degrees) [used only for 2 blades and when TeetMod=1] + +**TeetHStP** - Rotor-teeter hard-stop position (degrees) [used only for 2 blades and when TeetMod=1] + +**TeetSSSp** - Rotor-teeter soft-stop linear-spring constant (N-m/rad) [used only for 2 blades and when TeetMod=1] + +**TeetHSSp** - Rotor-teeter hard-stop linear-spring constant (N-m/rad) [used only for 2 blades and when TeetMod=1] + + + +Drivetrain +~~~~~~~~~~ + +**GBoxEff** - Gearbox efficiency (%) + +**GBRatio** - Gearbox ratio (-) + +**DTTorSpr** - Drivetrain torsional spring (N-m/rad) + +**DTTorDmp** - Drivetrain torsional damper (N-m/(rad/s)) + + + +Furling +~~~~~~~ + +**Furling** - Read in additional model properties for furling turbine (flag) [must currently be FALSE) + +**FurlFile** - Name of file containing furling properties (quoted string) [unused when Furling=False] + + +Tower +~~~~~ + +**TwrNodes** - Number of tower nodes used for analysis (-) + +**TwrFile** - Name of file containing tower properties (quoted string) + + +.. _ED-Outputs: + +Outputs +~~~~~~~ + +**SumPrint** [flag] Set this value to TRUE if you want ElastoDyn to generate a +summary file with the name **OutFileRoot**.ED.sum*. **OutFileRoot** is specified +by the OpenFAST program when running a coupled simulation. + +**OutFile** [switch] is currently unused. The eventual purpose is to allow +output from ElastoDyn to be written to a module output file (option 1), or the +main OpenFAST output file (option 2), or both. At present this switch is +ignored. + +**TabDelim** [flag] is currently unused. Setting this to True will set the +delimeter for text files to the tab character for the ElastoDyn module +**OutFile**. + +**OutFmt** [quoted string] is currently unused. ElastoDyn will use this string +as the numerical format specifier for output of floating-point values in its +local output specified by **OutFile**. The length of this string must not exceed +20 characters and must be enclosed in apostrophes or double quotes. You may not +specify an empty string. To ensure that fixed-width column data align properly +with the column titles, you should ensure that the width of the field is 10 +characters. Using an E, EN, or ES specifier will guarantee that you will never +overflow the field because the number is too big, but such numbers are harder to +read. Using an F specifier will give you numbers that are easier to read, but +you may overflow the field. Please refer to any Fortran manual for details for +format specifiers. + +**TStart** [s] sets the start time for **OutFile**. This is currenlty unused. + +**DecFact** [-] This parameter sets the decimation factor for output. ElastoDyn +will output data to **OutFile** only once each DecFact integration time steps. +For instance, a value of 5 will cause FAST to generate output only every fifth +time step. This value must be an integer greater than zero. + +**NTwGages** [-] The number of strain-gage locations along the tower indicates +the number of input values on the next line. Valid values are integers from 0 to +5 (inclusive). + +**TwrGagNd** [-] The virtual strain-gage locations along the tower are assigned +to the tower analysis nodes specified on this line. Possible values are 1 to +TwrNodes (inclusive), where 1 corresponds to the node closest to the tower base +(but not at the base) and a value of TwrNodes corresponds to the node closest to +the tower top. The exact elevations of each analysis node in the undeflected +tower, relative to the base of the tower, are determined as follows: + + Elev. of node J = TwrRBHt + ( J – 1⁄2 ) • [ ( TowerHt + TwrDraft – TwrRBHt ) / TwrNodes ] + (for J = 1,2,...,TwrNodes) + +You must enter at least NTwGages values on this line. +If NTwGages is 0, this line will be skipped, but you must have a line taking up +space in the input file. You can separate the values with combinations of tabs, +spaces, and commas, but you may use only one comma between numbers. + +**NBlGages** [-] specifies the number of strain-gague locations along the blade, +and indicates the number of input values expected in **BldGagNd**. This is only +used when the blade structure is modeled in ElastoDyn. + +**BldGagNd** [-] specifies the virtual strain-gage locations along the blade +that should be output. Possible values are 1 to **BldNodes** (inclusive), where +1 corresponds to the node closest to the blade root (but not at the root) and a +value of BldNodes corresponds to the node closest to the blade tip. The node +locations are specified by the ElastoDyn blade input files. You must enter at +least NBlGages values on this line. If NBlGages is 0, this line will be skipped, +but you must have a line taking up space in the input file. You can separate the +values with combinations of tabs, spaces, and commas, but you may use only one +comma between numbers. This is only used when the blade structure is modeled in +ElastoDyn. + + +The **OutList** section controls output quantities generated by +ElastoDyn. Enter one or more lines containing quoted strings that in turn +contain one or more output parameter names. Separate output parameter +names by any combination of commas, semicolons, spaces, and/or tabs. If +you prefix a parameter name with a minus sign, “-”, underscore, “_”, or +the characters “m” or “M”, ElastoDyn will multiply the value for that +channel by –1 before writing the data. The parameters are written in the +order they are listed in the input file. ElastoDyn allows you to use +multiple lines so that you can break your list into meaningful groups +and so the lines can be shorter. You may enter comments after the +closing quote on any of the lines. Entering a line with the string “END” +at the beginning of the line or at the beginning of a quoted string +found at the beginning of the line will cause ElastoDyn to quit scanning +for more lines of channel names. Blade and tower node-related quantities +are generated for the requested nodes identified through the +**BldGagNd** and **TwrGagNd** lists above. If ElastoDyn encounters an +unknown/invalid channel name, it warns the users but will remove the +suspect channel from the output file. Please refer to the ElastoDyn tab in the +Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` +for a complete list of possible output parameters. + +.. _ED-Nodal-Outputs: + +.. include:: EDNodalOutputs.rst diff --git a/OpenFAST/docs/source/user/fast_to_openfast.rst b/OpenFAST/docs/source/user/fast_to_openfast.rst new file mode 100644 index 000000000..9f84b18b3 --- /dev/null +++ b/OpenFAST/docs/source/user/fast_to_openfast.rst @@ -0,0 +1,200 @@ +.. _fast_to_openfast: + +FAST v8 and the transition to OpenFAST +====================================== + +This page describes the transition from FAST v8, a computer-aided engineering tool for simulating the coupled dynamic response of wind turbines, to OpenFAST. OpenFAST was established by researchers at the National Renewable Energy Laboratory (NREL) in 2017, who were supported by the U.S. Department of Energy Wind Energy Technology Office (DOE-WETO). + +FAST v8 +------- + +FAST v8 is a computer-aided engineering tool for simulating the coupled dynamic response of wind turbines. FAST joins aerodynamics models, hydrodynamics models for offshore structures, control and electrical system (servo) dynamics models, and structural (elastic) dynamics models to enable coupled nonlinear aero-hydro-servo-elastic simulation in the time domain. The FAST tool enables the analysis of a range of wind turbine configurations, including two- or three-blade horizontal-axis rotor, pitch or stall regulation, rigid or teetering hub, upwind or downwind rotor, and lattice or tubular tower. The wind turbine can be modeled on land or offshore on fixed-bottom or floating substructures. FAST is based on advanced engineering models derived from fundamental laws, but with appropriate simplifications and assumptions, and supplemented where applicable with computational solutions and test data. + +The aerodynamic models use wind-inflow data and solve for the rotor-wake effects and blade-element aerodynamic loads, including dynamic stall. The hydrodynamics models simulate the regular or irregular incident waves and currents and solve for the hydrostatic, radiation, diffraction, and viscous loads on the offshore substructure. The control and electrical system models simulate the controller logic, sensors, and actuators of the blade-pitch, generator-torque, nacelle-yaw, and other control devices, as well as the generator and power-converter components of the electrical drive. The structural-dynamics models apply the control and electrical system reactions, apply the aerodynamic and hydrodynamic loads, adds gravitational loads, and simulate the elasticity of the rotor, drivetrain, and support structure. Coupling between all models is achieved through a modular interface and coupler. + +Transition to OpenFAST +---------------------- + +The release of OpenFAST represents a transition to better support an open-source +developer community across research laboratories, industry, and academia +around FAST-based aero-hydro-servo-elastic engineering models of wind-turbines +and wind-plants. OpenFAST aims to provide a solid software-engineering framework +for FAST development including well documented source code, extensive automated +regression and unit testing, and a robust multi-platform and compiler build system. + +OpenFAST includes the following organizational changes relative to FAST v8.16: + +* A new GitHub organization has been established at https://github.com/openfast + +* The OpenFAST glue codes, modules, module drivers, and compiling tools are contained within a single repository: https://github.com/openfast/openfast + +* The FAST program has been renamed OpenFAST (starting from OpenFAST v1.0.0) + +* Version numbering has been updated for OpenFAST (starting from OpenFAST v1.0.0), e.g., OpenFAST-v1.0.0-123-gabcd1234-dirty, where: + + * v1.0.0 is the major-minor-bugfix numbering system and corresponds to a tagged commit made by NREL on GitHub + + * 123-g is the number of additional commits after the most recent tag for a build [the ‘-g’ is for ‘git’] + + * abcd1234 is the first 8 characters of the current commit hash + + * dirty denotes that local changes have been made but not committed + +* Because all modules are contained in the same repository, the version numbers of each module have been eliminated and now use the OpenFAST version number (starting from OpenFAST v1.0.0) though old documentation may still refer to old version numbers + +* The OpenFAST regression test baseline solutions (formerly the Certification Tests or CertTest) reside in a standalone repository: https://github.com/openfast/r-test (starting from OpenFAST v1.0.0) + +* Unit testing has been introduced at the subroutine level (starting with BeamDyn from OpenFAST v1.0.0). + +* An online documentation system has been established to replace existing documentation of FAST v8: http://openfast.readthedocs.io/; during the transition to OpenFAST, most user-related documentation is still provided through the NWTC Information Portal, https://nwtc.nrel.gov + +* Cross platform compiling is accomplished with CMake on macOS, Linux, and Cygwin (Windows) systems + +* Visual Studio Projects (VS-Build) are provided for compiling OpenFAST on Windows (starting from OpenFAST v1.0.0), but the development team is working to automate the generation of Visual Studio build files via CMake in a future release + +* `GitHub Issues <https://github.com/openfast/openfast/issues>`__ has been made the primary platform for developers to report and track bugs, request feature enhancements, and to ask questions related to the source code, compiling, and regression/unit testing; general user-related questions on OpenFAST theory and usage should still be handled through the forum at https://wind.nrel.gov/forum/wind + +* A new API has been added that provides a high level interface to run OpenFAST through a C++ driver code helping to interface OpenFAST with external programs like CFD solvers written in C++ (starting in OpenFAST v1.0.0) + + +Release Notes for OpenFAST +-------------------------- + +This section outlines significant modifications to OpenFAST made with each tagged release. + +v0.1.0 (April 2017) +``````````````````` + +Algorithmically, OpenFAST v0.1.0 is the release most closely related to FAST v8.16. + +* Organizational changes: + + * A new GitHub organization has been established at https://github.com/openfast + + * The OpenFAST glue codes, modules, module drivers, and compiling tools are contained within a single repository: https://github.com/openfast/openfast + + * Cross platform compiling is accomplished with CMake on macOS, Linux, and Cygwin (Windows) systems + + * An online documentation system has been established to replace existing documentation of FAST v8: http://openfast.readthedocs.io/ + + * `GitHub Issues <https://github.com/openfast/openfast/issues>`__ has been made the primary platform for developers to report and track bugs, request feature enhancements, and to ask questions related to the source code, compiling, and regression/unit testing; general user-related questions on OpenFAST theory and usage should still be handled through the forum at https://wind.nrel.gov/forum/wind + +* The AeroDyn v15 aerodynamics module has been significantly updated. The blade-element/momentum theory (BEMT) solution algorithm has been improved as follows: + + * BEMT now functions for the case where the undisturbed velocity along the x-direction of the local blade coordinate system (Vx) is less than zero + + * BEMT no longer aborts when a valid value of the inflow angle (:math:`\phi`) cannot be found; in this case, the inflow angle is computed geometrically (without induction) + + * The inflow angle (:math:`\phi`) is now initialized on the first call instead of defaulting to using :math:`\phi` = 0, giving better results during simulation start up + + * When hub- and/or tip-loss are enabled (HubLoss = True and/or TipLoss = True), tangential induction (a’) is set to 0 instead of -1 at the root and/or tip, respectively (axial induction (a) is still set to 1 at the root and/or tip) + + * The BEMT solution has been made more efficient + + * In addition, several bugs in AeroDyn v15 have been fixed, including: + + * Fixed a bug whereby when hub- and/or tip-loss are enabled (HubLoss = True and/or TipLoss = True) along with the Pitt/Peters skewed-wake correction (SkewMod = 2), BEMT no longer modifies the induction factors at the hub and/or tip, respectively + + * Fixed a bug whereby the time series was affected after the linearization analysis with AeroDyn coupled to OpenFAST when frozen wake is enabled (FrozenWake = True) + +* The BeamDyn finite-element blade structural-dynamics model has undergone an extensive cleanup of the source code. A bug in an off-diagonal term in the structural damping-induced stiffness (i.e., representing a change in the damping force with beam displacement) has been corrected. + +* A new module for user-specified platform loading (ExtPtfm) has been introduced. ExtPtfm allows the user to specify 6x6 added mass, damping, and stiffness matrices, as well as a 6x1 load vector to define loads to be applied to ElastoDyn’s tower base/platform, e.g., to support the modeling of substructures or foundations through a super-element representation (with super-element derived from external software). ExtPtfm also provides the user with a module to customize with more advanced platform applied loads. Module ExtPtfm can be enabled by setting CompSub to 2 in the FAST primary input file (a new option) and setting SubFile to the name of the file containing the platform matrices and load time history, but setting CompSub to 2 requires one to disable hydrodynamics (by setting CompHydro to 0). Please note that the introduction of option 2 for CompSub represents a minor input file change (the only input file change in OpenFAST v0.1.0), but the MATLAB conversion scripts have not yet been updated. + +* In the ServoDyn control and electrical-system module, the units and sign of output parameter YawMom have been corrected + +* In the InflowWind wind-inflow module, the ability to use TurbSim-generated tower wind data files in Bladed-style format was corrected + +* Minor fixes were made to the error checking in ElastoDyn + + +v1.0.0 (September 2017) +``````````````````````` + +* Organizational changes: + + * The FAST program has been renamed OpenFAST + + * Version numbering has been updated for OpenFAST (see Section 4.3.2 for details) + + * The OpenFAST regression test baseline solutions (formerly the Certification Tests or CertTest) reside in a standalone repository: https://github.com/openfast/r-test + + * Unit testing has been introduced at the subroutine level (starting with BeamDyn) + + * The online documentation (http://openfast.readthedocs.io/en/latest/index.html) has been extensively updated with additions for installation, testing, user (AeroDyn BeamDyn, transition from FAST v8, release notes), and developer guides, etc + + * The scripts for compiling OpenFAST using CMake on macOS, Linux, and Cygwin (Windows) systems have been updated, including the ability to compile in single precision and building with Spack + + * Visual Studio Projects (VS-Build) are provided for compiling OpenFAST on Windows + + * TurbSim has been included in the OpenFAST repository + +* The AeroDyn aerodynamics module has been updated: + + * Added a cavitation check for marine hydrokinetic (MHK) turbines. This includes the additions of new input parameters CavitCheck, Patm, Pvap, and FluidDepth in the AeroDyn primary input file, the addition of the Cpmin to the airfoil data files (required when CavitCheck = True), and new output channels for the minimum pressure coefficient, critical cavitation, and local cavitation numbers at the blade nodes. Please note that this input file changes represent the only input file change in OpenFAST v1.0.0, but the MATLAB conversion scripts have not yet been updated. + + * Fixed a bug in the calculation of wind loads on the tower whereby the tower displacement was used in place of the tower velocity + + * Tower strikes detected by the models to calculate the influence of the tower on the wind local to the blade are now treated as fatal errors instead of severe errors + + * Fixed minor bugs in the unsteady airfoil aerodynamics model + +* The BeamDyn finite-element blade structural-dynamics module has undergone additional changes: + + * The source-code has further undergone clean up, including changing the internal coordinate system to match IEC (with the local z axis along the pitch axis) + + * Trapezoidal points are now correctly defined by blade stations instead of key points + + * The tip rotation outputs were corrected as per GitHub issue #10 (https://github.com/OpenFAST/openfast/issues/10) + + * The BeamDyn driver has been fixed for cases involving spinning blades + + * BeamDyn no longer produces numerical “spikes” in single precision, so, it is no longer necessary to compile OpenFAST in double precision when using BeamDyn + +* The ElastoDyn structural-dynamics model was slightly updated: + + * The precision on some module-level outputs used as input to the BeamDyn module were increased from single to double to avoid numerical “spikes” when running BeamDyn in single precision + + * Minor fixes were made to the error checking + +* The ServoDyn control and electrical system module was slightly updated: + + * Fixed the values of the generator torque and electrical power sent from ServoDyn to Bladed-style DLL controllers as per GitHub issue # 40 (https://github.com/OpenFAST/openfast/issues/40) + + * Minor fixes were made to the error checking + +* The OpenFAST driver/glue code has been updated: + + * Correction steps have been added to the OpenFAST driver during the first few time steps to address initialization problems with BeamDyn (even with NumCrctn = 0) + + * Fixed a bug in the Line2-to-Point mapping of loads as per GitHub issue #8 (https://github.com/OpenFAST/openfast/issues/8). Previously, the augmented mesh was being formed using an incorrect projection, thus causing strange transfer of loads in certain cases. This could cause issues in the coupling between ElastoDyn and AeroDyn and/or in the coupling between HydroDyn and SubDyn + + * Added an otherwise undocumented feature for writing binary output without compression to support the new regression testing. The new format is available by setting OutFileFmt to 0 in the FAST primary input file. + +* A new API has been added that provides a high level interface to run OpenFAST through a C++ driver code. The primary purpose of the C++ API is to help interface OpenFAST to external programs like CFD solvers that are typically written in C++. + +* The TurbSim wind-inflow turbulence preprocessor was updated: + + * The API spectra was corrected + + * Several minor bugs were fixed. + + +OpenFAST: Looking forward +------------------------- + +Our goal is to continually improve OpenFAST documentation and to increase the coverage of automated unit and regression testing. +In order to increase testing coverage and to maintain robust software, we will require that + +* new modules be equipped by the module developer(s) with sufficient module-specific unit and regression testing along with appropriate OpenFAST regression tests; + +* bug fixes include appropriate unit tests; + +* new features/capabilities include appropriate unit and regression tests. We are in the process of better instrumenting the BeamDyn module with extensive testing as a demonstration of requirements for new modules. + +For unit testing, we will employ the pFUnit framework (https://sourceforge.net/projects/pfunit). + +For the time being OpenFAST provides project and solution files to support users developing and compiling using Visual Studio. However, the team is continually working to automate the generation of Visual Studio build files via CMake in future releases. + +Please contact `Michael.A.Sprague@NREL.gov <mailto:Michael.A.Sprague@NREL.gov>`_ with questions regarding the OpenFAST +development plan. diff --git a/OpenFAST/docs/source/user/index.rst b/OpenFAST/docs/source/user/index.rst new file mode 100644 index 000000000..8a94dcaf9 --- /dev/null +++ b/OpenFAST/docs/source/user/index.rst @@ -0,0 +1,24 @@ +.. _user_guide: + +User Documentation +================== + +This section contains documentation for the OpenFAST module-coupling environment and its underlying modules. +Documentation covers usage of models, underlying theory, and in some cases module verification. + +We are in the process of transitioning legacy FAST v8 documentation, which can be found at https://nwtc.nrel.gov/. +Details on the transition from FAST v8 to OpenFAST may be found in :numref:`fast_to_openfast` + +.. toctree:: + :maxdepth: 1 + + api_change.rst + aerodyn/index.rst + aerodyn-olaf/index.rst + aerodyn-aeroacoustics/index.rst + beamdyn/index.rst + elastodyn/index.rst + inflowwind/index.rst + fast_to_openfast.rst + cppapi/index.rst + diff --git a/OpenFAST/docs/source/user/inflowwind/appendix.rst b/OpenFAST/docs/source/user/inflowwind/appendix.rst new file mode 100644 index 000000000..3461c11db --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/appendix.rst @@ -0,0 +1,44 @@ +.. _ifw_appendix: + +Appendix +======== + +.. _ifw_input_files: + +InflowWind Input Files +---------------------- + +In this appendix we describe the InflowWind input-file structure and provide examples. + +1) InflowWind Driver Input File +:download:`(driver input file example) <examples/inflowwind_driver_example.inp>`: + +The driver input file is needed only for the standalone version of InflowWind. It contains inputs regarding the InflowWind file, interpolation parameters, and the desired output files. +The InflowWind driver can also be run without this file by using command-line arguments instead. + +2) InflowWind Primary Input File +:download:`(primary input file example) <examples/inflowwind_example.dat>`: + +The primary InflowWind input file defines the inflow that is generated or read from other files. The InflowWind file contains sections for each type of wind-file format. + +3) Native Bladed Scaling File +:download:`(primary input file example) <examples/inflowwind_bladedscaling_example.dat>`: + +This file includes lines that determine how to scale the non-dimensional full-field +turbulence files from Bladed. + +4) Uniform Wind Data File +:download:`(uniform wind input file example) <examples/inflowwind_uniform_example.dat>`: + +This file includes lines that define uniform (deterministic) wind data files. + + +.. _ifw_output_channels: + +InflowWind List of Output Channels +---------------------------------- + +This is a list of all possible output parameters for the InflowWind module. +See the InflowWind tab of the +:download:`(OutListParameters.xlsx file) <../../../OtherSupporting/OutListParameters.xlsx>`: + diff --git a/OpenFAST/docs/source/user/inflowwind/driver.rst b/OpenFAST/docs/source/user/inflowwind/driver.rst new file mode 100644 index 000000000..b0ef7a017 --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/driver.rst @@ -0,0 +1,115 @@ +InflowWind Driver +================= +Example input files are +included in :numref:`ifw_appendix`. + +Command-line syntax for InflowWind driver: + +:: + + InlowWind_Driver <filename> [options] + + where: <filename> -- Name of driver input file to use + options: /ifw -- treat <filename> 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 + /vtk -- convert wind file specified in InflowWind to VTK format + /help -- print this help menu and exit + +:: + + Notes: + - Unspecified ranges and resolutions default to what is in the file. + - If no XRange is specified, assumed to be only at X=0 + - Options are not case sensitive. + +The `InflowWind Manual <https://wind.nrel.gov/nwtc/docs/InflowWind_Manual.pdf>`__ +contains a description of file formats that it can read. + +Specifying the InflowWind Input File +------------------------------------ + +The InflowWind driver input file requires that an InflowWind input file +be specified within it. See an example InflowWind input +file in :numref:`ifw_appendix`. + +Within the InflowWind input file, if the wind file being specified is +Bladed native format (``WindType = 7``), please also see +:numref:`ifw_native_bladed`. + +Wind-file output formats +------------------------ + +The InflowWind driver is capable of writing the wind data read from the +input wind file into wind files of various formats. + +HAWC2 +~~~~~ + +This format generates the following files: + +- three binary files, one for each component: + ``<RootName>-HAWC.u``, ``<RootName>-HAWC.v``, and ``<RootName>-HAWC.w`` + +- a text summary file in the style of HAWC2 input files: + ``<RootName>-HAWC.sum`` + +In the conversion script, the u component will have the (approximate) +mean removed at each height. The mean value that was removed is +displayed as comments in the text summary file. The turbulence is not +scaled, so it will have the same scaling as the original file. + +Bladed +~~~~~~ + +This format generates a packed binary file and a text summary file. + +This output format is in the Bladed-style format that TurbSim generates. That +means that **the shear is included** in the file. + +VTK +~~~ + +This format creates files in a subdirectory called ``vtk``. There is one +vtk file for each time in the full-field data structure, and the entire +Y-Z grid is printed in each file. This format can be used to visualize +the wind field using a viewer such as ParaView. + +Converting uniform wind to full-field wind format +------------------------------------------------- + +When converting from a uniform wind file to a full-field wind format, +the following assumptions are used: - The advection speed is the +time-averaged horizontal wind speed in the uniform wind file (it does +not include the gust speed). - The constant time-step used in the output +file is the smallest difference between any two entries in the +hub-height file. - The maximum time in the uniform wind file will be +used as the maximum time in the FF binary file. - The grid is generated +with 5-m resolution in the lateral (Y) and horizontal (Z) directions. - +The size of the grid is based on the ``RefLength`` parameter in the +InflowWind input file. The converter adds approximately 10% to the grid +width, with the exact size determined by achieving the desired grid +resolution. The grid is centered in the lateral direction; it extends +vertically above ``RefHt`` by the same distance as the grid width, and +extends below ``RefHt`` to the ground (or within one grid point of the +ground). + +Note that there is a potential time shift between the uniform and +full-field wind files, equal to the time it takes to travel the distance +of half the grid width. When using the resulting full-field files, care +must be taken that the aeroelastic code does not treat it as periodic. + diff --git a/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_bladedscaling_example.dat b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_bladedscaling_example.dat new file mode 100644 index 000000000..77c407d3e --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_bladedscaling_example.dat @@ -0,0 +1,10 @@ +UBAR 12 +REFHT 90 +TI 0.033333 +TI_V 0.026667 +TI_W 0.016667 +WDIR 0 +FLINC .139626222222222 +WINDF "../tw06_80hh_s200.wnd" +WSHEAR .2 +XOFFSET 0 \ No newline at end of file diff --git a/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp new file mode 100644 index 000000000..6e84d1667 --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp @@ -0,0 +1,24 @@ +Example file +InflowWind driver input file. + t echo -- whether this input file should be echoed to a file (flag) +=============================================================================== +"inflowwind_example.dat" IfWFileName -- Name of InflowWind input file (-) +===================== File Conversion Options ================================= + false WrHAWC -- Convert all data to HAWC2 format? (flag) + false WrBladed -- Convert all data to Bladed format? (flag) + false WrVTK -- Convert all data to VTK format? (flag) +===================== Tests of Interpolation Options ========================= + DEFAULT NumTSteps -- number of timesteps to run (DEFAULT for all) (-) + 0.0 TStart -- Start time (s) + 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) +---- 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) +---- 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) + 1,1,0 GridDx,GridDY,GridDZ -- Step size of grid (m) + 1,1,0 GridNx,GridNY,GridNZ -- number of grid points in X, Y and Z directions (-) +END of driver input file diff --git a/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_example.dat b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_example.dat new file mode 100644 index 000000000..a2159a4aa --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_example.dat @@ -0,0 +1,57 @@ +------- InflowWind INPUT FILE ------------------------------------------------------------------------- +Example of InflowWind input file for OpenFAST +--------------------------------------------------------------------------------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) + 3 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 (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) + 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) +================== Parameters for Steady Wind Conditions [used only for WindType = 1] ========================= + 0 HWindSpeed - Horizontal wind speed (m/s) + 90 RefHt - Reference height for horizontal wind speed (m) + 0.2 PLexp - Power law exponent (-) +================== Parameters for Uniform wind file [used only for WindType = 2] ============================ +"Wind/90m_12mps_twr.hh" Filename - Filename of time series data for uniform wind field. (-) + 90 RefHt - Reference height for horizontal wind speed (m) + 125.88 RefLength - Reference length for linear horizontal and vertical sheer (-) +================== Parameters for Binary TurbSim Full-Field files [used only for WindType = 3] ============== +"Wind/90m_12mps_twr.bts" Filename - Name of the Full field wind file to use (.bts) +================== Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4 or WindType = 7] ========= +"Wind/90m_12mps_twr" FilenameRoot - WindType=4: Rootname of the full-field wind file to use (.wnd, .sum); WindType=7: name of the intermediate file with wind scaling values +False TowerFile - Have tower file (.twr) (flag) ignored when WindType = 7 +================== Parameters for HAWC-format binary files [Only used with WindType = 5] ===================== +"wasp\Output\basic_5u.bin" FileName_u - name of the file containing the u-component fluctuating wind (.bin) +"wasp\Output\basic_5v.bin" FileName_v - name of the file containing the v-component fluctuating wind (.bin) +"wasp\Output\basic_5w.bin" FileName_w - name of the file containing the w-component fluctuating wind (.bin) + 64 nx - number of grids in the x direction (in the 3 files above) (-) + 32 ny - number of grids in the y direction (in the 3 files above) (-) + 32 nz - number of grids in the z direction (in the 3 files above) (-) + 16 dx - distance (in meters) between points in the x direction (m) + 3 dy - distance (in meters) between points in the y direction (m) + 3 dz - distance (in meters) between points in the z direction (m) + 90 RefHt - reference height; the height (in meters) of the vertical center of the grid (m) + ------------- Scaling parameters for turbulence --------------------------------------------------------- + 2 ScaleMethod - Turbulence scaling method [0 = none, 1 = direct scaling, 2 = calculate scaling factor based on a desired standard deviation] + 1 SFx - Turbulence scaling factor for the x direction (-) [ScaleMethod=1] + 1 SFy - Turbulence scaling factor for the y direction (-) [ScaleMethod=1] + 1 SFz - Turbulence scaling factor for the z direction (-) [ScaleMethod=1] + 1.2 SigmaFx - Turbulence standard deviation to calculate scaling from in x direction (m/s) [ScaleMethod=2] + .8 SigmaFy - Turbulence standard deviation to calculate scaling from in y direction (m/s) [ScaleMethod=2] + .2 SigmaFz - Turbulence standard deviation to calculate scaling from in z direction (m/s) [ScaleMethod=2] + ------------- Mean wind profile parameters (added to HAWC-format files) --------------------------------- + 12 URef - Mean u-component wind speed at the reference height (m/s) + 2 WindProfile - Wind profile type (0=constant;1=logarithmic,2=power law) + 0.2 PLExp - 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 InitPosition(x) - Initial offset in +x direction (shift of wind box) +====================== OUTPUT ================================================== +False SumPrint - Print summary data to <RootName>.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" X-direction wind velocity at point WindList(1) +"Wind1VelY" Y-direction wind velocity at point WindList(1) +"Wind1VelZ" Z-direction wind velocity at point WindList(1) +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_uniform_example.dat b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_uniform_example.dat new file mode 100644 index 000000000..4cc7a6909 --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/examples/inflowwind_uniform_example.dat @@ -0,0 +1,14 @@ +! OpenFAST Deterministic Wind File +# +# Comment lines begin with "!" or "#" or "%", then the data lines must contain the following columns: +# +# If there are only 8 columns, upflow is assumed to be 0. +# +# Parameters are interpolated linearly between time steps; using nearest neighbor before the first time +# listed in this file and after the last time listed in the file. +# +! Time Wind Wind Vertical Horiz. Pwr.Law Lin.Vert. Gust Upflow +! Speed Dir Speed Shear Vert.Shr Shear Speed Angle +! (sec) (m/s) (Deg) (m/s) (m/s) (deg) + 0.000000 10 0.000000 0 0.000000 0.300000 0.000000 0.000000 8 +10.000000 12 0.000000 0 0.000000 0.300000 0.000000 0.000000 8 diff --git a/OpenFAST/docs/source/user/inflowwind/index.rst b/OpenFAST/docs/source/user/inflowwind/index.rst new file mode 100644 index 000000000..07c59bbda --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/index.rst @@ -0,0 +1,22 @@ +InflowWind Users Guide and Theory Manual +======================================== + +.. only:: html + + This document offers a quick reference guide for the InflowWind software. + It is intended to be used by the general user in combination + with other OpenFAST manuals. The manual will be updated as new releases are + issued and as needed to provide further information on advancements or + modifications to the software. + + The information here is incomplete. Please see the + `InflowWind Manual <https://wind.nrel.gov/nwtc/docs/InflowWind_Manual.pdf>`__ + until it has been converted to OpenFAST's documentation style. + + +.. toctree:: + :maxdepth: 2 + + driver.rst + input.rst + appendix.rst diff --git a/OpenFAST/docs/source/user/inflowwind/input.rst b/OpenFAST/docs/source/user/inflowwind/input.rst new file mode 100644 index 000000000..cbf70c62b --- /dev/null +++ b/OpenFAST/docs/source/user/inflowwind/input.rst @@ -0,0 +1,113 @@ + +.. _ifw_input: + +InflowWind Input Files +====================== + +.. _ifw_native_bladed: + +Native Bladed wind file support in InflowWind +--------------------------------------------- + +The ability to read native Bladed wind files (without scaling) has been added to InflowWind. +To use this feature, the ``WindType`` must be set to ``7`` on line 5 of the primary +InflowWind input file. An example of this file is given inAn example of this Native Bladed scaling file is included in +:numref:`ifw_appendix`. + +:: + + 7 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=Bladed native) + +In the section for ``WindType = 4``, the name of an intermediate Bladed +wind file should be given (including the file extension). The tower file +flag is ignored. + +:: + + ================== Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4] ========= + "tw06_80hh_s200.BladedWind.ipt" FilenameRoot - Name of the Full field wind file to use (.wnd, .sum) + F TowerFile - Have tower file (.twr) (flag) + + +The intermediate Bladed wind scaling file must contain the following information, which can be retrieved +directly from the Bladed project simulation file from the +``MSTART WINDSEL`` and ``MSTART WINDV`` sections. Additionally, the file +may include an ``XOFFSET`` line, which allows the wind to be shifted by +a given distance. If not included, ``XOFFSET`` is assumed to be 0. +An example of this Native Bladed scaling file is included in +:numref:`ifw_appendix`. + + +:: + + UBAR 12 + REFHT 90 + TI 0.033333 + TI_V 0.026667 + TI_W 0.016667 + WDIR 0 + FLINC .139626222222222 + WINDF "../tw06_80hh_s200.wnd" + WSHEAR .2 + XOFFSET 0 + +In the above file, the names correspond to the following: + ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| Line | Variable Name | Units | Description | ++========+=================+=========+=================================================================================================================================================+ +| 1 | ``UBAR`` | (m/s) | Mean wind speed | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 2 | ``REFHT`` | (m) | Reference height (turbine hub height) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 3 | ``TI`` | (-) | Turbulence intensity in longitudinal (mean wind flow) direction | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 4 | ``TI_V`` | (-) | Turbulence intensity in horizontal direction (orthogonal to mean flow direction) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 5 | ``TI_W`` | (-) | Turbulence intensity in vertical direction (orthogonal to mean flow direction) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 6 | ``WDIR`` | (rad) | Wind direction (meteorological rotation direction) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 7 | ``FLINC`` | (rad) | Upflow angle (positive is up) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 8 | ``WINDF`` | (-) | Name of native Bladed wind file (absolute or relative path, 200 character limit) | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 9 | ``WSHEAR`` | (-) | Power law wind shear exponent | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ +| 10 | ``XOFFSET`` | (m) | Turbulence box offset in the X direction (how far ahead of the turbine the turbulence box starts). If missing, this value is assumed to be 0. | ++--------+-----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------+ + +Limitations: - Wind file is centered on hub height ("Best fit for rotor +and tower" not implemented) - Always allow wind file to wrap around +(unchecked box not implemented) - Only power-law wind profile is +implemented (not logarithmic, none, or user-defined) + + +.. _ifw_angles: + +Angles Specified in InflowWind +============================== +Wind direction and upflow angles can be specified in the InflowWind input file. +When using Native Bladed wind file support in InflowWind, the angles from the InflowWind input are overwritten +with the values specified in the Native Bladed Input Files. +InflowWind rotates the wind box about the hub-height tower center line by these wind direction and upflow angles. + +The uniform wind files also specify wind direction and upflow angles. +The angles specified in uniform wind files DO NOT rotate the wind box, but just convert the local wind speed into global coordinates. + +When converting from local ``[u v w]`` to global ``[U V W]`` reference systems, the upflow rotation, ``R(upflow)`` occurs +before the wind direction rotation, ``R(wind direction)``: + +:: + +[U V W] = R(wind direction) * R(upflow) * [u v w] + +When using a combination of angles in InflowWind and UniformWind files, the UniformWind angles are applied first. + +Note: This means that if you have upflow specified in InflowWind and wind direction specified in UniformWind, the rotation will +be performed in a different order than if both angles are specified in the same file. + +:: + +[U V W] = R(wind direction: InflowWind) * R(upflow: InflowWind) * R(wind direction: UniformWind) * R(upflow: UniformWind) * [u v w] + diff --git a/OpenFAST/glue-codes/CMakeLists.txt b/OpenFAST/glue-codes/CMakeLists.txt new file mode 100644 index 000000000..9c1f8e3b5 --- /dev/null +++ b/OpenFAST/glue-codes/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_subdirectory(openfast) + +if(BUILD_OPENFAST_CPP_API) + add_subdirectory(openfast-cpp) +endif() diff --git a/OpenFAST/glue-codes/labview/src/OPENFAST_RT_DLL.f90 b/OpenFAST/glue-codes/labview/src/OPENFAST_RT_DLL.f90 new file mode 100644 index 000000000..50cee2773 --- /dev/null +++ b/OpenFAST/glue-codes/labview/src/OPENFAST_RT_DLL.f90 @@ -0,0 +1,125 @@ +! OPENFAST_RT_DLL.f90 +! (c) 2009, 2012 National Renewable Energy Laboratory +! Paul Fleming, National Wind Technology Center, September 2009, 2012 +! Bonnie Jonkman, National Wind Technology Center, October 2012 +! +! Modification of OPENFAST for Labview RT +! Also includes code from OPENFAST_Simulink Adaptation +!==================================================================================== + +subroutine OPENFAST_RT_DLL_INIT (FileName_RT_Byte, FLen) + + ! Expose subroutine OPENFAST_RT_DLL_INIT to users of this DLL + ! + !DEC$ ATTRIBUTES DLLEXPORT::FAST_RT_DLL_INIT + +USE NWTC_Library +USE General, ONLY : PriFile, Cmpl4LV + +USE OPENFAST_IO_Subs ! OPENFAST_Input(), OPENFAST_Begin() +USE OPENFASTSubs ! OPENFAST_Initialize() + + ! This sub-routine is called by RT to initialize all internal variables + +IMPLICIT NONE + +INTEGER, PARAMETER :: MaxFileNameLen = 100 +INTEGER(B1Ki) :: FileName_RT_Byte(MaxFileNameLen) ! FileName_RT_Byte + +CHARACTER(MaxFileNameLen) :: FileName_RT_Char ! FileName_RT_Byte converted to ASCII characters +INTEGER :: FLen ! trim length of FileName_RT_Byte +INTEGER :: I ! temporary loop counter + + +IF ( FLen > MaxFileNameLen ) CALL ProgAbort('File name is too long in OPENFAST_RT_DLL_INIT.') +DO I=1,FLen + FileName_RT_Char(I:I) = ACHAR(FileName_RT_Byte(I)) +END DO +!EQUIVALENCE(FileName_RT_Byte2,FileName_RT_Char) !Make the character filename equivalent to incoming filename byte array + +!FileName_RT_Byte2(:) = FileName_RT_Byte(:) + + + +!Assign PriFile based on passed in string +PriFile = FileName_RT_Char(1:FLen) + + + ! Open and read input files, initialize global parameters. +CALL OPENFAST_Begin( PriFile, RootName, DirRoot ) + + +!Set compiler flag for Simulink +Cmpl4LV = .TRUE. + +CALL OPENFAST_Input() + + ! Set up initial values for all degrees of freedom. +CALL OPENFAST_Initialize(p,x,y,OtherState) + + +end subroutine OPENFAST_RT_DLL_INIT + + + + +!==================================================================================== +subroutine OPENFAST_RT_DLL_SIM (BlPitchCom_RT, YawPosCom_RT, YawRateCom_RT, ElecPwr_RT, GenTrq_RT, OutData_RT, Time_RT, HSSBrFrac_RT) + + + ! Expose subroutine OPENFAST_RT_DLL_SIM to users of this DLL + ! + !DEC$ ATTRIBUTES DLLEXPORT::FAST_RT_DLL_SIM + + +USE SimCont !ZTime + +! These are needed for FirstTime = .FALSE. +USE DriveTrain ! GenTrq and now also HSSBrFrac +USE TurbCont ! BlPitch +USE TurbConf ! NumBl +USE Blades ! TipNode +USE Precision ! ReKi +USE Features ! CompAero +USE Output ! for WrOutHdr + +USE OPENFASTSubs ! TimeMarch() + +IMPLICIT NONE + + ! This sub-routine implements n-iterations of time step and returns outputs to Labview RT + + ! Variables +REAL(ReKi), INTENT(IN) :: GenTrq_RT ! Mechanical generator torque. +REAL(ReKi), INTENT(IN) :: ElecPwr_RT ! Electrical power +REAL(ReKi), INTENT(IN) :: YawPosCom_RT ! Yaw position +REAL(ReKi), INTENT(IN) :: YawRateCom_RT ! Yaw rate +REAL(ReKi), INTENT(IN) :: BlPitchCom_RT (*) +REAL(ReKi), INTENT(OUT) :: OutData_RT (*) +REAL(ReKi), INTENT(OUT) :: Time_RT +REAL(ReKi), INTENT(IN) :: HSSBrFrac_RT ! Brake Fraction + + !Copy in inputs from RT + BlPitchCom = BlPitchCom_RT(1:NumBl) + YawPosCom = YawPosCom_RT + YawRateCom = YawRateCom_RT + ElecPwr = ElecPwr_RT + GenTrq= GenTrq_RT + HSSBrFrac = HSSBrFrac_RT + + ! Set the command pitch angles to the actual pitch angles since we have no + ! built-in pitch actuator: + BlPitch = BlPitchCom + + +!Run simulation +Call TimeMarch( p_StrD, x_StrD, OtherSt_StrD, y_StrD, ErrStat, ErrMsg ) + + +!Copy outputs +OutData_RT(1:p_StrD%NumOuts) = OutData(1:p_StrD%NumOuts) +Time_RT = ZTime; +OutData_RT(p_StrD%NumOuts+1) = TMax; +OutData_RT(p_StrD%NumOuts+2) = Time_RT; + +end subroutine OPENFAST_RT_DLL_SIM diff --git a/OpenFAST/glue-codes/openfast-cpp/CMakeLists.txt b/OpenFAST/glue-codes/openfast-cpp/CMakeLists.txt new file mode 100644 index 000000000..c4dab07b4 --- /dev/null +++ b/OpenFAST/glue-codes/openfast-cpp/CMakeLists.txt @@ -0,0 +1,86 @@ +# +# Copyright 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. +# + +if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0") + cmake_policy(SET CMP0074 NEW) +endif() + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(MPI REQUIRED) +find_package(LibXml2 REQUIRED) +find_package(ZLIB REQUIRED) +find_package(HDF5 REQUIRED COMPONENTS C HL) +find_package(YAMLCPP REQUIRED) + +include_directories(${YAML_INCLUDES}) +include_directories(${HDF5_INCLUDES}) +include_directories(${HDF5_INCLUDE_DIR}) +include_directories(${ZLIB_INCLUDES}) +include_directories(${LIBXML2_INCLUDE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/modules/openfast-library/src/) +include_directories(${CMAKE_BINARY_DIR}/modules/openfoam/) +include_directories(${CMAKE_BINARY_DIR}/modules/supercontroller/) +include_directories(${MPI_INCLUDE_PATH}) + +add_library(openfastcpplib + src/OpenFAST.cpp) +set_property(TARGET openfastcpplib PROPERTY POSITION_INDEPENDENT_CODE ON) +target_link_libraries(openfastcpplib + openfastlib + ${HDF5_C_LIBRARIES} + ${HDF5_HL_LIBRARIES} + ${ZLIB_LIBRARIES} + ${LIBXML2_LIBRARIES} + ${MPI_LIBRARIES} + ${CMAKE_DL_LIBS}) + +add_executable(openfastcpp + src/FAST_Prog.cpp) + +target_link_libraries(openfastcpp openfastcpplib openfastlib + ${MPI_LIBRARIES} ${YAML_LIBRARIES} + ${HDF5_C_LIBRARIES} + ${HDF5_HL_LIBRARIES} + ${ZLIB_LIBRARIES} + ${LIBXML2_LIBRARIES} + ${CMAKE_DL_LIBS}) + +if(MPI_COMPILE_FLAGS) + set_target_properties(openfastcpp PROPERTIES + COMPILE_FLAGS "${MPI_COMPILE_FLAGS}") +endif(MPI_COMPILE_FLAGS) + +if(MPI_LINK_FLAGS) + set_target_properties(openfastcpp PROPERTIES + LINK_FLAGS "${MPI_LINK_FLAGS}") +endif(MPI_LINK_FLAGS) + +set_property(TARGET openfastcpp PROPERTY LINKER_LANGUAGE CXX) + +install(TARGETS openfastcpplib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +install(FILES + src/OpenFAST.H src/SC.h + DESTINATION include) + +install(TARGETS openfastcpp + RUNTIME DESTINATION bin) diff --git a/OpenFAST/glue-codes/openfast-cpp/src/FAST_Prog.cpp b/OpenFAST/glue-codes/openfast-cpp/src/FAST_Prog.cpp new file mode 100644 index 000000000..b7af79562 --- /dev/null +++ b/OpenFAST/glue-codes/openfast-cpp/src/FAST_Prog.cpp @@ -0,0 +1,149 @@ +#include "OpenFAST.H" +#include "yaml-cpp/yaml.h" +#include <iostream> +#include <mpi.h> + +inline bool checkFileExists(const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +void readTurbineData(int iTurb, fast::fastInputs & fi, YAML::Node turbNode) { + + //Read turbine data for a given turbine using the YAML node + fi.globTurbineData[iTurb].TurbID = turbNode["turb_id"].as<int>(); + fi.globTurbineData[iTurb].FASTInputFileName = turbNode["FAST_input_filename"].as<std::string>() ; + fi.globTurbineData[iTurb].FASTRestartFileName = turbNode["restart_filename"].as<std::string>() ; + if (turbNode["turbine_base_pos"].IsSequence() ) { + fi.globTurbineData[iTurb].TurbineBasePos = turbNode["turbine_base_pos"].as<std::vector<double> >() ; + } + if (turbNode["turbine_hub_pos"].IsSequence() ) { + fi.globTurbineData[iTurb].TurbineHubPos = turbNode["turbine_hub_pos"].as<std::vector<double> >() ; + } + fi.globTurbineData[iTurb].numForcePtsBlade = turbNode["num_force_pts_blade"].as<int>(); + fi.globTurbineData[iTurb].numForcePtsTwr = turbNode["num_force_pts_tower"].as<int>(); + if (turbNode["nacelle_cd"]) {fi.globTurbineData[iTurb].nacelle_cd = turbNode["nacelle_cd"].as<float>();} + if (turbNode["nacelle_area"]) {fi.globTurbineData[iTurb].nacelle_area = turbNode["nacelle_area"].as<float>();} + if (turbNode["air_density"]) {fi.globTurbineData[iTurb].air_density = turbNode["air_density"].as<float>();} +} + +void readInputFile(fast::fastInputs & fi, std::string cInterfaceInputFile, double * tEnd) { + + fi.comm = MPI_COMM_WORLD; + + // Check if the input file exists and read it + if ( checkFileExists(cInterfaceInputFile) ) { + + YAML::Node cDriverInp = YAML::LoadFile(cInterfaceInputFile); + + fi.nTurbinesGlob = cDriverInp["nTurbinesGlob"].as<int>(); + + if (fi.nTurbinesGlob > 0) { + + if(cDriverInp["dryRun"]) { + fi.dryRun = cDriverInp["dryRun"].as<bool>(); + } + + if(cDriverInp["debug"]) { + fi.debug = cDriverInp["debug"].as<bool>(); + } + + if(cDriverInp["simStart"]) { + if (cDriverInp["simStart"].as<std::string>() == "init") { + fi.simStart = fast::init; + } else if(cDriverInp["simStart"].as<std::string>() == "trueRestart") { + fi.simStart = fast::trueRestart; + } else if(cDriverInp["simStart"].as<std::string>() == "restartDriverInitFAST") { + fi.simStart = fast::restartDriverInitFAST; + } else { + throw std::runtime_error("simStart is not well defined in the input file"); + } + } + + fi.tStart = cDriverInp["tStart"].as<double>(); + *tEnd = cDriverInp["tEnd"].as<double>(); + fi.nEveryCheckPoint = cDriverInp["nEveryCheckPoint"].as<int>(); + fi.dtFAST = cDriverInp["dtFAST"].as<double>(); + fi.tMax = cDriverInp["tMax"].as<double>(); // tMax is the total duration to which you want to run FAST. This should be the same or greater than the max time given in the FAST fst file. Choose this carefully as FAST writes the output file only at this point if you choose the binary file output. + + if(cDriverInp["superController"]) { + fi.scStatus = cDriverInp["superController"].as<bool>(); + fi.scLibFile = cDriverInp["scLibFile"].as<std::string>(); + fi.numScInputs = cDriverInp["numScInputs"].as<int>(); + fi.numScOutputs = cDriverInp["numScOutputs"].as<int>(); + } + + fi.globTurbineData.resize(fi.nTurbinesGlob); + for (int iTurb=0; iTurb < fi.nTurbinesGlob; iTurb++) { + if (cDriverInp["Turbine" + std::to_string(iTurb)]) { + readTurbineData(iTurb, fi, cDriverInp["Turbine" + std::to_string(iTurb)] ); + } else { + throw std::runtime_error("Node for Turbine" + std::to_string(iTurb) + " not present in input file or I cannot read it"); + } + } + + } else { + throw std::runtime_error("Number of turbines <= 0 "); + } + + } else { + throw std::runtime_error("Input file " + cInterfaceInputFile + " does not exist or I cannot access it"); + } + +} + +int main() { + int iErr; + int nProcs; + int rank; + std::vector<double> torque (3, 0.0); + std::vector<double> thrust (3, 0.0); + + iErr = MPI_Init(NULL, NULL); + iErr = MPI_Comm_size( MPI_COMM_WORLD, &nProcs); + iErr = MPI_Comm_rank( MPI_COMM_WORLD, &rank); + + double tEnd ; // This doesn't belong in the FAST - C++ interface + int ntEnd ; // This doesn't belong in the FAST - C++ interface + + std::string cDriverInputFile="cDriver.i"; + fast::OpenFAST FAST; + fast::fastInputs fi ; + try { + readInputFile(fi, cDriverInputFile, &tEnd); + } + catch( const std::runtime_error & ex) { + std::cerr << ex.what() << std::endl ; + std::cerr << "Program quitting now" << std::endl ; + return 1; + } + ntEnd = tEnd/fi.dtFAST; //Calculate the last time step + + FAST.setInputs(fi); + FAST.allocateTurbinesToProcsSimple(); + // Or allocate turbines to procs by calling "setTurbineProcNo(iTurbGlob, procId)" for turbine. + + FAST.init(); + if (FAST.isTimeZero()) { + FAST.solution0(); + } + + if( !FAST.isDryRun() ) { + for (int nt = FAST.get_ntStart(); nt < ntEnd; nt++) { + FAST.step(); + if (FAST.isDebug()) { + FAST.computeTorqueThrust(0,torque,thrust); + std::cout.precision(16); + std::cout << "Torque = " << torque[0] << " " << torque[1] << " " << torque[2] << std::endl ; + std::cout << "Thrust = " << thrust[0] << " " << thrust[1] << " " << thrust[2] << std::endl ; + } + } + } + + FAST.end() ; + MPI_Finalize() ; + + return 0; + +} + diff --git a/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.H b/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.H new file mode 100644 index 000000000..7cd6789d5 --- /dev/null +++ b/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.H @@ -0,0 +1,311 @@ +#ifndef OpenFAST_h +#define OpenFAST_h +#include "FAST_Library.h" +#include "sys/stat.h" +#include <string> +#include <cstring> +#include <stdexcept> +#include <vector> +#include <set> +#include <map> +#include "dlfcn.h" +//TODO: The skip MPICXX is put in place primarily to get around errors in OpenFOAM. This will cause problems if the driver program uses C++ API for MPI. +#ifndef OMPI_SKIP_MPICXX + #define OMPI_SKIP_MPICXX +#endif +#ifndef MPICH_SKIP_MPICXX + #define MPICH_SKIP_MPICXX +#endif +#include "mpi.h" +#include "SC.h" + + +namespace fast { + +struct globTurbineDataType { + int TurbID; + std::string FASTInputFileName; + std::string FASTRestartFileName; + std::vector<double> TurbineBasePos; + std::vector<double> TurbineHubPos; + int numForcePtsBlade; + int numForcePtsTwr; + float nacelle_cd{0.0}; + float nacelle_area{0.0}; + float air_density{0.0}; +}; + +enum ActuatorNodeType { + HUB = 0, + BLADE = 1, + TOWER = 2, + ActuatorNodeType_END +}; + +enum simStartType { + init = 0, + trueRestart = 1, + restartDriverInitFAST = 2, + simStartType_END +}; + + +class fastInputs { + + public: + + MPI_Comm comm; + int nTurbinesGlob; + bool dryRun; + bool debug; + double tStart; + simStartType simStart; + int nEveryCheckPoint; + double tMax; + double dtFAST; + + bool scStatus; + std::string scLibFile; + int numScInputs, numScOutputs; + + std::vector<globTurbineDataType> globTurbineData; + + // Constructor + fastInputs() ; + + // Destructor + ~fastInputs() {} ; + +}; + + +class OpenFAST { + + private: + + MPI_Comm mpiComm; + bool dryRun; // If this is true, class will simply go through allocation and deallocation of turbine data + bool debug; // Write out extra information if this flags is turned on + std::vector<globTurbineDataType> globTurbineData; + int nTurbinesProc; + int nTurbinesGlob; + simStartType simStart; + bool timeZero; + double dtFAST; + double tMax; + std::vector<std::vector<float> > TurbineBasePos; + std::vector<std::vector<float> > TurbineHubPos; + std::vector<int> TurbID; + std::vector<std::string > FASTInputFileName; + std::vector<std::string > CheckpointFileRoot; + std::vector<float> nacelle_cd; + std::vector<float> nacelle_area; + std::vector<float> air_density; + double tStart; + int nt_global; + int ntStart; // The time step to start the FAST simulation + int nEveryCheckPoint; // Check point files will be written every 'nEveryCheckPoint' time steps + std::vector<int> numBlades; // Number of blades + std::vector<int> numForcePtsBlade; + std::vector<int> numForcePtsTwr; + std::vector<int> numVelPtsBlade; + std::vector<int> numVelPtsTwr; + int numScOutputs; // # outputs from the supercontroller == # inputs to the controller == NumSC2Ctrl + int numScInputs; // # inputs to the supercontroller == # outputs from the controller == NumCtrl2SC + std::vector<double> scOutputsGlob; // # outputs from the supercontroller for all turbines + std::vector<double> scInputsGlob; // # inputs to the supercontroller for all turbines + + std::vector<std::vector<std::vector<double> > > forceNodeVel; // Velocity at force nodes - Store temporarily to interpolate to the velocity nodes + std::vector<std::vector<double> > velNodeData; // Position and velocity data at the velocity (aerodyn) nodes - (nTurbines, nTimesteps * nPoints * 6) + hid_t velNodeDataFile; // HDF-5 tag of file containing velocity (aerodyn) node data file + + std::vector<OpFM_InputType_t> cDriver_Input_from_FAST; + std::vector<OpFM_OutputType_t> cDriver_Output_to_FAST; + + std::vector<SC_InputType_t> cDriverSC_Input_from_FAST; + std::vector<SC_OutputType_t> cDriverSC_Output_to_FAST; + + // Turbine Number is DIFFERENT from TurbID. Turbine Number simply runs from 0:n-1 locally and globally. + std::map<int, int> turbineMapGlobToProc; // Mapping global turbine number to processor number + std::map<int, int> turbineMapProcToGlob; // Mapping local to global turbine number + std::map<int, int> reverseTurbineMapProcToGlob; // Reverse Mapping global turbine number to local turbine number + std::set<int> turbineSetProcs; // Set of processors containing atleast one turbine + std::vector<int> turbineProcs; // Same as the turbineSetProcs, but as an integer array + + //Supercontroller stuff + bool scStatus; + std::string scLibFile; + // Dynamic load stuff copied from 'C++ dlopen mini HOWTO' on tldp.org + void *scLibHandle ; + typedef SuperController* create_sc_t(); + create_sc_t * create_SuperController; + typedef void destroy_sc_t(SuperController *); + destroy_sc_t * destroy_SuperController; + SuperController * sc; + + int fastMPIGroupSize; + MPI_Group fastMPIGroup; + MPI_Comm fastMPIComm; + int fastMPIRank; + + MPI_Group worldMPIGroup; + int worldMPIRank; + + static int AbortErrLev; + int ErrStat; + char ErrMsg[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 + + public: + + // Constructor + OpenFAST() ; + + // Destructor + ~OpenFAST() ; + + void setInputs(const fastInputs &); + + void init(); + void solution0(); + void step(); + void stepNoWrite(); + void end(); + + // Compute the nacelle force + void calc_nacelle_force(const float & u, + const float & v, + const float & w, + const float & cd, + const float & area, + const float & rho, + float & fx, + float & fy, + float & fz); + + hid_t openVelocityDataFile(bool createFile); + void readVelocityData(int nTimesteps); + void writeVelocityData(hid_t h5file, int iTurb, int iTimestep, OpFM_InputType_t iData, OpFM_OutputType_t oData); + herr_t closeVelocityDataFile(int nt_global, hid_t velDataFile); + void backupVelocityDataFile(int curTimeStep, hid_t & velDataFile); + + void setTurbineProcNo(int iTurbGlob, int procNo) { turbineMapGlobToProc[iTurbGlob] = procNo; } + void allocateTurbinesToProcsSimple(); + void getApproxHubPos(double* currentCoords, int iTurbGlob, int nSize=3); + void getHubPos(double* currentCoords, int iTurbGlob, int nSize=3); + void getHubShftDir(double* hubShftVec, int iTurbGlob, int nSize=3); + + ActuatorNodeType getVelNodeType(int iTurbGlob, int iNode); + void getVelNodeCoordinates(double* currentCoords, int iNode, int iTurbGlob, int nSize=3); + void setVelocity(double* velocity, int iNode, int iTurbGlob, int nSize=3); + void setVelocityForceNode(double* velocity, int iNode, int iTurbGlob, int nSize=3); + void interpolateVel_ForceToVelNodes(); + ActuatorNodeType getForceNodeType(int iTurbGlob, int iNode); + void getForceNodeCoordinates(double* currentCoords, int iNode, int iTurbGlob, int nSize=3); + void getForceNodeOrientation(double* currentOrientation, int iNode, int iTurbGlob, int nSize=9); + void getForce(double* force, int iNode, int iTurbGlob, int nSize=3); + void getRelativeVelForceNode(double* vel, int iNode, int iTurbGlob, int nSize=3); + double getChord(int iNode, int iTurbGlob); + + int get_ntStart() { return ntStart; } + bool isDryRun() { return dryRun; } + bool isDebug() { return debug; } + simStartType get_simStartType() { return simStart; } + bool isTimeZero() { return timeZero; } + int get_procNo(int iTurbGlob) { return turbineMapGlobToProc[iTurbGlob] ; } // Get processor number of a turbine with global id 'iTurbGlob' + int get_localTurbNo(int iTurbGlob) { return reverseTurbineMapProcToGlob[iTurbGlob]; } + int get_nTurbinesGlob() { return nTurbinesGlob; } + + float get_nacelleArea(int iTurbGlob) { return get_nacelleAreaLoc(get_localTurbNo(iTurbGlob)); } + float get_nacelleCd(int iTurbGlob) { return get_nacelleCdLoc(get_localTurbNo(iTurbGlob)); } + float get_airDensity(int iTurbGlob) { return get_airDensityLoc(get_localTurbNo(iTurbGlob)); } + int get_numBlades(int iTurbGlob) { return get_numBladesLoc(get_localTurbNo(iTurbGlob)); } + int get_numVelPtsBlade(int iTurbGlob) { return get_numVelPtsBladeLoc(get_localTurbNo(iTurbGlob)); } + int get_numVelPtsTwr(int iTurbGlob) { return get_numVelPtsTwrLoc(get_localTurbNo(iTurbGlob)); } + int get_numVelPts(int iTurbGlob) { return get_numVelPtsLoc(get_localTurbNo(iTurbGlob)); } + int get_numForcePtsBlade(int iTurbGlob) { return get_numForcePtsBladeLoc(get_localTurbNo(iTurbGlob)); } + int get_numForcePtsTwr(int iTurbGlob) { return get_numForcePtsTwrLoc(get_localTurbNo(iTurbGlob)); } + int get_numForcePts(int iTurbGlob) { return get_numForcePtsLoc(get_localTurbNo(iTurbGlob)); } + + void computeTorqueThrust(int iTurGlob, std::vector<double> & torque, std::vector<double> & thrust); + + + inline + void getHubPos(std::vector<double> & currentCoords, int iTurbGlob) { + getHubPos(currentCoords.data(), iTurbGlob, currentCoords.size()); + } + + inline + void getApproxHubPos(std::vector<double>& currentCoords, int iTurbGlob) { + getApproxHubPos(currentCoords.data(), iTurbGlob, currentCoords.size()); + } + + inline + void getHubShftDir(std::vector<double> & hubShftVec, int iTurbGlob) { + getHubShftDir(hubShftVec.data(), iTurbGlob, hubShftVec.size()); + } + + inline + void getVelNodeCoordinates(std::vector<double> & currentCoords, int iNode, int iTurbGlob) { + getVelNodeCoordinates(currentCoords.data(), iNode, iTurbGlob, currentCoords.size()); + } + + inline + void setVelocity(std::vector<double> & currentVelocity, int iNode, int iTurbGlob) { + setVelocity(currentVelocity.data(), iNode, iTurbGlob, currentVelocity.size()); + } + + inline + void setVelocityForceNode(std::vector<double> & currentVelocity, int iNode, int iTurbGlob) { + setVelocityForceNode(currentVelocity.data(), iNode, iTurbGlob, currentVelocity.size()); + } + + inline + void getForceNodeCoordinates(std::vector<double> & currentCoords, int iNode, int iTurbGlob) { + getForceNodeCoordinates(currentCoords.data(), iNode, iTurbGlob, currentCoords.size()); + } + + inline + void getForceNodeOrientation(std::vector<double> & currentOrientation, int iNode, int iTurbGlob) { + getForceNodeOrientation(currentOrientation.data(), iNode, iTurbGlob, currentOrientation.size()); + } + + inline + void getForce(std::vector<double> & currentForce, int iNode, int iTurbGlob) { + getForce(currentForce.data(), iNode, iTurbGlob, currentForce.size()); + } + + inline + void getRelativeVelForceNode(std::vector<double> & currentVelocity, int iNode, int iTurbGlob) { + getRelativeVelForceNode(currentVelocity.data(), iNode, iTurbGlob, currentVelocity.size()); + } + + private: + + void checkError(const int ErrStat, const char * ErrMsg); + inline bool checkFileExists(const std::string& name); + + void allocateMemory(); + + float get_nacelleCdLoc(int iTurbLoc) { return nacelle_cd[iTurbLoc]; } + float get_nacelleAreaLoc(int iTurbLoc) { return nacelle_area[iTurbLoc]; } + float get_airDensityLoc(int iTurbLoc) { return air_density[iTurbLoc]; } + int get_numBladesLoc(int iTurbLoc) { return numBlades[iTurbLoc]; } + int get_numVelPtsBladeLoc(int iTurbLoc) { return numVelPtsBlade[iTurbLoc]; } + int get_numVelPtsTwrLoc(int iTurbLoc) { return numVelPtsTwr[iTurbLoc]; } + int get_numVelPtsLoc(int iTurbLoc) { return 1 + numBlades[iTurbLoc]*numVelPtsBlade[iTurbLoc] + numVelPtsTwr[iTurbLoc]; } + int get_numForcePtsBladeLoc(int iTurbLoc) { return numForcePtsBlade[iTurbLoc]; } + int get_numForcePtsTwrLoc(int iTurbLoc) { return numForcePtsTwr[iTurbLoc]; } + int get_numForcePtsLoc(int iTurbLoc) { return 1 + numBlades[iTurbLoc]*numForcePtsBlade[iTurbLoc] + numForcePtsTwr[iTurbLoc]; } + + void loadSuperController(const fastInputs & fi); + void fillScInputsGlob() ; + void fillScOutputsLoc() ; + + void setOutputsToFAST(OpFM_InputType_t cDriver_Input_from_FAST, OpFM_OutputType_t cDriver_Output_to_FAST) ; // An example to set velocities at the Aerodyn nodes + void applyVelocityData(int iPrestart, int iTurb, OpFM_OutputType_t cDriver_Output_to_FAST, std::vector<double> & velData) ; + +}; + +} + +#endif diff --git a/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.cpp b/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.cpp new file mode 100644 index 000000000..c2901fec4 --- /dev/null +++ b/OpenFAST/glue-codes/openfast-cpp/src/OpenFAST.cpp @@ -0,0 +1,1147 @@ +#include "OpenFAST.H" +#include <iostream> +#include <fstream> +#include <cmath> +#include <algorithm> +#include <cassert> + +int fast::OpenFAST::AbortErrLev = ErrID_Fatal; // abort error level; compare with NWTC Library + +//Constructor +fast::fastInputs::fastInputs(): +nTurbinesGlob(0), +dryRun(false), +debug(false), +tStart(-1.0), +nEveryCheckPoint(-1), +tMax(0.0), +dtFAST(0.0), +scStatus(false), +scLibFile(""), +numScInputs(0), +numScOutputs(0) +{ + //Nothing to do here +} + + +//Constructor +fast::OpenFAST::OpenFAST(): +nTurbinesGlob(0), +nTurbinesProc(0), +scStatus(false), +simStart(fast::init), +timeZero(false) +{ +} + +inline bool fast::OpenFAST::checkFileExists(const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +void fast::OpenFAST::init() { + // Temporary buffer to pass filenames to OpenFAST fortran subroutines + char currentFileName[INTERFACE_STRING_LENGTH]; + + allocateMemory(); + + if (!dryRun) { + switch (simStart) { + + case fast::trueRestart: + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + /* note that this will set nt_global inside the FAST library */ + std::copy(CheckpointFileRoot[iTurb].data(), + CheckpointFileRoot[iTurb].data() + (CheckpointFileRoot[iTurb].size() + 1), + currentFileName); + FAST_OpFM_Restart( + &iTurb, currentFileName, &AbortErrLev, &dtFAST, &numBlades[iTurb], + &numVelPtsBlade[iTurb], &ntStart, &cDriver_Input_from_FAST[iTurb], + &cDriver_Output_to_FAST[iTurb], &cDriverSC_Input_from_FAST[iTurb], + &cDriverSC_Output_to_FAST[iTurb], &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + nt_global = ntStart; + + int nfpts = get_numForcePtsLoc(iTurb); + forceNodeVel[iTurb].resize(nfpts); + for (int k = 0; k < nfpts; k++) forceNodeVel[iTurb][k].resize(3) ; + + } + + if (nTurbinesProc > 0) velNodeDataFile = openVelocityDataFile(false); + + if(scStatus) { + sc->readRestartFile(nt_global); + } + + break ; + + case fast::init: + + // this calls the Init() routines of each module + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + std::copy(FASTInputFileName[iTurb].data(), + FASTInputFileName[iTurb].data() + (FASTInputFileName[iTurb].size() + 1), + currentFileName); + FAST_OpFM_Init(&iTurb, &tMax, currentFileName, &TurbID[iTurb], + &numScOutputs, &numScInputs, &numForcePtsBlade[iTurb], + &numForcePtsTwr[iTurb], TurbineBasePos[iTurb].data(), + &AbortErrLev, &dtFAST, &numBlades[iTurb], + &numVelPtsBlade[iTurb], &cDriver_Input_from_FAST[iTurb], + &cDriver_Output_to_FAST[iTurb], + &cDriverSC_Input_from_FAST[iTurb], + &cDriverSC_Output_to_FAST[iTurb], &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + + timeZero = true; + + numVelPtsTwr[iTurb] = cDriver_Output_to_FAST[iTurb].u_Len - numBlades[iTurb]*numVelPtsBlade[iTurb] - 1; + if(numVelPtsTwr[iTurb] == 0) { + numForcePtsTwr[iTurb] = 0; + std::cout << "Aerodyn doesn't want to calculate forces on the tower. All actuator points on the tower are turned off for turbine " << turbineMapProcToGlob[iTurb] << "." << std::endl ; + } + + + int nfpts = get_numForcePtsLoc(iTurb); + forceNodeVel[iTurb].resize(nfpts); + for (int k = 0; k < nfpts; k++) forceNodeVel[iTurb][k].resize(3) ; + + if ( isDebug() ) { + for (int iNode=0; iNode < get_numVelPtsLoc(iTurb); iNode++) { + std::cout << "Node " << iNode << " Position = " << cDriver_Input_from_FAST[iTurb].pxVel[iNode] << " " << cDriver_Input_from_FAST[iTurb].pyVel[iNode] << " " << cDriver_Input_from_FAST[iTurb].pzVel[iNode] << " " << std::endl ; + } + } + } + + if (nTurbinesProc > 0) velNodeDataFile = openVelocityDataFile(true); + + break ; + + case fast::restartDriverInitFAST: + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + std::copy(FASTInputFileName[iTurb].data(), + FASTInputFileName[iTurb].data() + (FASTInputFileName[iTurb].size() + 1), + currentFileName); + FAST_OpFM_Init(&iTurb, &tMax, currentFileName, &TurbID[iTurb], + &numScOutputs, &numScInputs, &numForcePtsBlade[iTurb], + &numForcePtsTwr[iTurb], TurbineBasePos[iTurb].data(), + &AbortErrLev, &dtFAST, &numBlades[iTurb], + &numVelPtsBlade[iTurb], &cDriver_Input_from_FAST[iTurb], + &cDriver_Output_to_FAST[iTurb], + &cDriverSC_Input_from_FAST[iTurb], + &cDriverSC_Output_to_FAST[iTurb], &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + + timeZero = true; + + numVelPtsTwr[iTurb] = cDriver_Output_to_FAST[iTurb].u_Len - numBlades[iTurb]*numVelPtsBlade[iTurb] - 1; + + int nfpts = get_numForcePtsLoc(iTurb); + forceNodeVel[iTurb].resize(nfpts); + for (int k = 0; k < nfpts; k++) forceNodeVel[iTurb][k].resize(3) ; + + if ( isDebug() ) { + for (int iNode=0; iNode < get_numVelPtsLoc(iTurb); iNode++) { + std::cout << "Node " << iNode << " Position = " << cDriver_Input_from_FAST[iTurb].pxVel[iNode] << " " << cDriver_Input_from_FAST[iTurb].pyVel[iNode] << " " << cDriver_Input_from_FAST[iTurb].pzVel[iNode] << " " << std::endl ; + } + } + } + + int nTimesteps; + + if (nTurbinesProc > 0) { + readVelocityData(ntStart); + } + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + applyVelocityData(0, iTurb, cDriver_Output_to_FAST[iTurb], velNodeData[iTurb]); + } + solution0() ; + + for (int iPrestart=0 ; iPrestart < ntStart; iPrestart++) { + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + applyVelocityData(iPrestart, iTurb, cDriver_Output_to_FAST[iTurb], velNodeData[iTurb]); + } + stepNoWrite(); + } + + if (nTurbinesProc > 0) velNodeDataFile = openVelocityDataFile(false); + + break; + + case fast::simStartType_END: + + break; + + } + + } +} + +void fast::OpenFAST::solution0() { + + if (!dryRun) { + // set wind speeds at initial locations + // for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + // setOutputsToFAST(cDriver_Input_from_FAST[iTurb], cDriver_Output_to_FAST[iTurb]); + // } + + if(scStatus) { + + sc->init(nTurbinesGlob, numScInputs, numScOutputs); + + sc->calcOutputs(scOutputsGlob); + fillScOutputsLoc(); + } + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + + FAST_OpFM_Solution0(&iTurb, &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + + } + + timeZero = false; + + if (scStatus) { + fillScInputsGlob(); // Update inputs to super controller + } + } + +} + +void fast::OpenFAST::step() { + + /* ****************************** + set inputs from this code and call FAST: + ********************************* */ + + if(scStatus) { + sc->calcOutputs(scOutputsGlob); + fillScOutputsLoc(); + } + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + + // set wind speeds at original locations + // setOutputsToFAST(cDriver_Input_from_FAST[iTurb], cDriver_Output_to_FAST[iTurb]); + + // this advances the states, calls CalcOutput, and solves for next inputs. Predictor-corrector loop is imbeded here: + // (note OpenFOAM could do subcycling around this step) + + writeVelocityData(velNodeDataFile, iTurb, nt_global, cDriver_Input_from_FAST[iTurb], cDriver_Output_to_FAST[iTurb]); + + if ( isDebug() ) { + + std::ofstream fastcpp_velocity_file; + fastcpp_velocity_file.open("fastcpp_velocity.csv") ; + fastcpp_velocity_file << "# x, y, z, Vx, Vy, Vz" << std::endl ; + for (int iNode=0; iNode < get_numVelPtsLoc(iTurb); iNode++) { + fastcpp_velocity_file << cDriver_Input_from_FAST[iTurb].pxVel[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pyVel[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pzVel[iNode] << ", " << cDriver_Output_to_FAST[iTurb].u[iNode] << ", " << cDriver_Output_to_FAST[iTurb].v[iNode] << ", " << cDriver_Output_to_FAST[iTurb].w[iNode] << " " << std::endl ; + } + fastcpp_velocity_file.close() ; + + } + + FAST_OpFM_Step(&iTurb, &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + + // Compute the force from the nacelle only if the drag coefficient is + // greater than zero + if (nacelle_cd[iTurb]>0.) { + + calc_nacelle_force ( + + cDriver_Output_to_FAST[iTurb].u[0], + cDriver_Output_to_FAST[iTurb].v[0], + cDriver_Output_to_FAST[iTurb].w[0], + nacelle_cd[iTurb], + nacelle_area[iTurb], + air_density[iTurb], + cDriver_Input_from_FAST[iTurb].fx[0], + cDriver_Input_from_FAST[iTurb].fy[0], + cDriver_Input_from_FAST[iTurb].fz[0] + + ); + + } + + if ( isDebug() ) { + std::ofstream actuatorForcesFile; + actuatorForcesFile.open("actuator_forces.csv") ; + actuatorForcesFile << "# x, y, z, fx, fy, fz" << std::endl ; + for (int iNode=0; iNode < get_numForcePtsLoc(iTurb); iNode++) { + actuatorForcesFile << cDriver_Input_from_FAST[iTurb].pxForce[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pyForce[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pzForce[iNode] << ", " << cDriver_Input_from_FAST[iTurb].fx[iNode] << ", " << cDriver_Input_from_FAST[iTurb].fy[iNode] << ", " << cDriver_Input_from_FAST[iTurb].fz[iNode] << " " << std::endl ; + } + actuatorForcesFile.close() ; + } + + } + + if(scStatus) { + sc->updateStates(scInputsGlob); // Go from 'n' to 'n+1' based on input at previous time step + fillScInputsGlob(); // Update inputs to super controller for 'n+1' + } + + nt_global = nt_global + 1; + + if ( (((nt_global - ntStart) % nEveryCheckPoint) == 0 ) && (nt_global != ntStart) ) { + // Use default FAST naming convention for checkpoint file + // <RootName>.<nt_global> + char dummyCheckPointRoot[INTERFACE_STRING_LENGTH] = " "; + // Ensure that we have a null character + dummyCheckPointRoot[1] = 0; + + if (nTurbinesProc > 0) backupVelocityDataFile(nt_global, velNodeDataFile); + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + FAST_CreateCheckpoint(&iTurb, dummyCheckPointRoot, &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + } + if(scStatus) { + if (fastMPIRank == 0) { + sc->writeRestartFile(nt_global); + } + } + } + +} + +void fast::OpenFAST::stepNoWrite() { + + /* ****************************** + set inputs from this code and call FAST: + ********************************* */ + + if(scStatus) { + sc->calcOutputs(scOutputsGlob); + fillScOutputsLoc(); + } + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + + // set wind speeds at original locations + // setOutputsToFAST(cDriver_Input_from_FAST[iTurb], cDriver_Output_to_FAST[iTurb]); + + // this advances the states, calls CalcOutput, and solves for next inputs. Predictor-corrector loop is imbeded here: + // (note OpenFOAM could do subcycling around this step) + FAST_OpFM_Step(&iTurb, &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + + } + + if(scStatus) { + sc->updateStates(scInputsGlob); // Go from 'n' to 'n+1' based on input at previous time step + fillScInputsGlob(); // Update inputs to super controller for 'n+1' + } + + nt_global = nt_global + 1; + +} + +fast::OpenFAST::~OpenFAST(){ +} + +void fast::OpenFAST::calc_nacelle_force( + const float & u, + const float & v, + const float & w, + const float & cd, + const float & area, + const float & rho, + float & fx, + float & fy, + float & fz) { + // Calculate the force on the nacelle (fx,fy,fz) given the + // velocity sampled at the nacelle point (u,v,w), + // drag coefficient 'cd' and nacelle area 'area' + + // The velocity magnitude + float Vmag = std::sqrt(u * u + v * v + w * w); + + // Velocity correction based on Martinez-Tossas PhD Thesis 2017 + // The correction samples the velocity at the center of the + // Gaussian kernel and scales it to obtain the inflow velocity + float epsilon_d = std::sqrt(2.0 / M_PI * cd * area); + float correction = 1. / (1.0 - cd * area / + (4.0 * M_PI * epsilon_d * epsilon_d)); + + // Compute the force for each velocity component + fx = rho * 1./2. * cd * area * Vmag * u * correction * correction; + fy = rho * 1./2. * cd * area * Vmag * v * correction * correction; + fz = rho * 1./2. * cd * area * Vmag * w * correction * correction; + } + +void fast::OpenFAST::setInputs(const fast::fastInputs & fi ) { + + + mpiComm = fi.comm; + + MPI_Comm_rank(mpiComm, &worldMPIRank); + MPI_Comm_group(mpiComm, &worldMPIGroup); + + nTurbinesGlob = fi.nTurbinesGlob; + + if (nTurbinesGlob > 0) { + + dryRun = fi.dryRun; + + debug = fi.debug; + + tStart = fi.tStart; + simStart = fi.simStart; + nEveryCheckPoint = fi.nEveryCheckPoint; + tMax = fi.tMax; + loadSuperController(fi); + dtFAST = fi.dtFAST; + + ntStart = int(tStart/dtFAST); + + if (simStart == fast::restartDriverInitFAST) { + nt_global = 0; + } else { + nt_global = ntStart; + } + + globTurbineData.resize(nTurbinesGlob); + globTurbineData = fi.globTurbineData; + + } else { + throw std::runtime_error("Number of turbines < 0 "); + } + +} + +void fast::OpenFAST::checkError(const int ErrStat, const char * ErrMsg){ + + if (ErrStat != ErrID_None){ + + if (ErrStat >= AbortErrLev){ + throw std::runtime_error(ErrMsg); + } + + } + +} + +void fast::OpenFAST::setOutputsToFAST(OpFM_InputType_t cDriver_Input_from_FAST, OpFM_OutputType_t cDriver_Output_to_FAST){ + + // routine sets the u-v-w wind speeds used in FAST and the SuperController inputs + + for (int j = 0; j < cDriver_Output_to_FAST.u_Len; j++){ + cDriver_Output_to_FAST.u[j] = (float) 10.0*pow((cDriver_Input_from_FAST.pzVel[j] / 90.0), 0.2); // 0.2 power law wind profile using reference 10 m/s at 90 meters + cDriver_Output_to_FAST.v[j] = 0.0; + cDriver_Output_to_FAST.w[j] = 0.0; + } + + // // call supercontroller + // for (int j = 0; j < cDriver_Output_to_FAST.SuperController_Len; j++){ + // cDriver_Output_to_FAST.SuperController[j] = (float) j; // set it somehow.... (would be set from the SuperController outputs) + // } + +} + +void fast::OpenFAST::getApproxHubPos(double* currentCoords, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Get hub position of Turbine 'iTurbGlob' + for(int i =0; i<nSize; ++i){ + currentCoords[i] = globTurbineData[iTurbGlob].TurbineHubPos[i]; + } +} + + +void fast::OpenFAST::getHubPos(double* currentCoords, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Get hub position of Turbine 'iTurbGlob' + int iTurbLoc = get_localTurbNo(iTurbGlob); + currentCoords[0] = cDriver_Input_from_FAST[iTurbLoc].pxVel[0] + TurbineBasePos[iTurbLoc][0] ; + currentCoords[1] = cDriver_Input_from_FAST[iTurbLoc].pyVel[0] + TurbineBasePos[iTurbLoc][1] ; + currentCoords[2] = cDriver_Input_from_FAST[iTurbLoc].pzVel[0] + TurbineBasePos[iTurbLoc][2] ; + +} + +void fast::OpenFAST::getHubShftDir(double* hubShftVec, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Get hub shaft direction of current turbine - pointing downwind + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int i=0; i<nSize; i++){ + hubShftVec[i] = cDriver_Input_from_FAST[iTurbLoc].pOrientation[i*3] ; + } +} + + +void fast::OpenFAST::getVelNodeCoordinates(double* currentCoords, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Set coordinates at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numVelPtsLoc(iTurbLoc); + currentCoords[0] = cDriver_Input_from_FAST[iTurbLoc].pxVel[iNode] + TurbineBasePos[iTurbLoc][0] ; + currentCoords[1] = cDriver_Input_from_FAST[iTurbLoc].pyVel[iNode] + TurbineBasePos[iTurbLoc][1] ; + currentCoords[2] = cDriver_Input_from_FAST[iTurbLoc].pzVel[iNode] + TurbineBasePos[iTurbLoc][2] ; + +} + +void fast::OpenFAST::getForceNodeCoordinates(double* currentCoords, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Set coordinates at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + currentCoords[0] = cDriver_Input_from_FAST[iTurbLoc].pxForce[iNode] + TurbineBasePos[iTurbLoc][0] ; + currentCoords[1] = cDriver_Input_from_FAST[iTurbLoc].pyForce[iNode] + TurbineBasePos[iTurbLoc][1] ; + currentCoords[2] = cDriver_Input_from_FAST[iTurbLoc].pzForce[iNode] + TurbineBasePos[iTurbLoc][2] ; + +} + +void fast::OpenFAST::getForceNodeOrientation(double* currentOrientation, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==9); + // Set orientation at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbLoc); + for(int i=0;i<9;i++) { + currentOrientation[i] = cDriver_Input_from_FAST[iTurbLoc].pOrientation[iNode*9+i] ; + } + +} + +void fast::OpenFAST::getRelativeVelForceNode(double* currentVelocity, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Get relative velocity at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbLoc); + + currentVelocity[0] = forceNodeVel[iTurbLoc][iNode][0] - cDriver_Input_from_FAST[iTurbLoc].xdotForce[iNode]; + currentVelocity[1] = forceNodeVel[iTurbLoc][iNode][1] - cDriver_Input_from_FAST[iTurbLoc].ydotForce[iNode]; + currentVelocity[2] = forceNodeVel[iTurbLoc][iNode][2] - cDriver_Input_from_FAST[iTurbLoc].zdotForce[iNode]; +} + + +void fast::OpenFAST::getForce(double* currentForce, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Set forces at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbLoc); + currentForce[0] = -cDriver_Input_from_FAST[iTurbLoc].fx[iNode] ; + currentForce[1] = -cDriver_Input_from_FAST[iTurbLoc].fy[iNode] ; + currentForce[2] = -cDriver_Input_from_FAST[iTurbLoc].fz[iNode] ; + +} + +double fast::OpenFAST::getChord(int iNode, int iTurbGlob) { + + // Return blade chord/tower diameter at current node of current turbine + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbLoc); + return cDriver_Input_from_FAST[iTurbLoc].forceNodesChord[iNode] ; + +} + +void fast::OpenFAST::setVelocity(double* currentVelocity, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Set velocity at current node of current turbine - + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numVelPtsLoc(iTurbLoc); + cDriver_Output_to_FAST[iTurbLoc].u[iNode] = currentVelocity[0]; + cDriver_Output_to_FAST[iTurbLoc].v[iNode] = currentVelocity[1]; + cDriver_Output_to_FAST[iTurbLoc].w[iNode] = currentVelocity[2]; +} + +void fast::OpenFAST::setVelocityForceNode(double* currentVelocity, int iNode, int iTurbGlob, int nSize) { + + assert(nSize==3); + // Set velocity at current node of current turbine - + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbLoc); + + for(int i=0; i<nSize; ++i){ + forceNodeVel[iTurbLoc][iNode][i] = currentVelocity[i]; + } +} + +void fast::OpenFAST::interpolateVel_ForceToVelNodes() { + + // Interpolates the velocity from the force nodes to the velocity nodes + + for(int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + // Hub location + cDriver_Output_to_FAST[iTurb].u[0] = forceNodeVel[iTurb][0][0]; + cDriver_Output_to_FAST[iTurb].v[0] = forceNodeVel[iTurb][0][1]; + cDriver_Output_to_FAST[iTurb].w[0] = forceNodeVel[iTurb][0][2]; + + if ( isDebug() ) { + std::ofstream actuatorVelFile; + actuatorVelFile.open("actuator_velocity.csv") ; + actuatorVelFile << "# x, y, z, Vx, Vy, Vz" << std::endl ; + for (int iNode=0; iNode < get_numForcePtsLoc(iTurb); iNode++) { + actuatorVelFile << cDriver_Input_from_FAST[iTurb].pxForce[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pyForce[iNode] << ", " << cDriver_Input_from_FAST[iTurb].pzForce[iNode] << ", " << forceNodeVel[iTurb][iNode][0] << ", " << forceNodeVel[iTurb][iNode][1] << ", " << forceNodeVel[iTurb][iNode][2] << " " << std::endl ; + } + actuatorVelFile.close() ; + } + + // Do the blades first + int nBlades = get_numBladesLoc(iTurb); + for(int iBlade=0; iBlade < nBlades; iBlade++) { + + // Create interpolating parameter - Distance from hub + int nForcePtsBlade = get_numForcePtsBladeLoc(iTurb); + std::vector<double> rDistForce(nForcePtsBlade) ; + for(int j=0; j < nForcePtsBlade; j++) { + int iNodeForce = 1 + iBlade * nForcePtsBlade + j ; //The number of actuator force points is always the same for all blades + rDistForce[j] = std::sqrt( + (cDriver_Input_from_FAST[iTurb].pxForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pxForce[0])*(cDriver_Input_from_FAST[iTurb].pxForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pxForce[0]) + + (cDriver_Input_from_FAST[iTurb].pyForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pyForce[0])*(cDriver_Input_from_FAST[iTurb].pyForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pyForce[0]) + + (cDriver_Input_from_FAST[iTurb].pzForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pzForce[0])*(cDriver_Input_from_FAST[iTurb].pzForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pzForce[0]) + ); + } + + // Interpolate to the velocity nodes + int nVelPtsBlade = get_numVelPtsBladeLoc(iTurb); + for(int j=0; j < nVelPtsBlade; j++) { + int iNodeVel = 1 + iBlade * nVelPtsBlade + j ; //Assumes the same number of velocity (Aerodyn) nodes for all blades + double rDistVel = std::sqrt( + (cDriver_Input_from_FAST[iTurb].pxVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pxVel[0])*(cDriver_Input_from_FAST[iTurb].pxVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pxVel[0]) + + (cDriver_Input_from_FAST[iTurb].pyVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pyVel[0])*(cDriver_Input_from_FAST[iTurb].pyVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pyVel[0]) + + (cDriver_Input_from_FAST[iTurb].pzVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pzVel[0])*(cDriver_Input_from_FAST[iTurb].pzVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pzVel[0]) + ); + //Find nearest two force nodes + int jForceLower = 0; + while ( (rDistForce[jForceLower+1] < rDistVel) && ( jForceLower < (nForcePtsBlade-2)) ) { + jForceLower = jForceLower + 1; + } + int iNodeForceLower = 1 + iBlade * nForcePtsBlade + jForceLower ; + double rInterp = (rDistVel - rDistForce[jForceLower])/(rDistForce[jForceLower+1]-rDistForce[jForceLower]); + cDriver_Output_to_FAST[iTurb].u[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][0] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][0] - forceNodeVel[iTurb][iNodeForceLower][0] ); + cDriver_Output_to_FAST[iTurb].v[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][1] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][1] - forceNodeVel[iTurb][iNodeForceLower][1] ); + cDriver_Output_to_FAST[iTurb].w[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][2] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][2] - forceNodeVel[iTurb][iNodeForceLower][2] ); + } + } + + // Now the tower if present and used + int nVelPtsTower = get_numVelPtsTwrLoc(iTurb); + if ( nVelPtsTower > 0 ) { + + // Create interpolating parameter - Distance from first node from ground + int nForcePtsTower = get_numForcePtsTwrLoc(iTurb); + std::vector<double> hDistForce(nForcePtsTower) ; + int iNodeBotTowerForce = 1 + nBlades * get_numForcePtsBladeLoc(iTurb); // The number of actuator force points is always the same for all blades + for(int j=0; j < nForcePtsTower; j++) { + int iNodeForce = iNodeBotTowerForce + j ; + hDistForce[j] = std::sqrt( + (cDriver_Input_from_FAST[iTurb].pxForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pxForce[iNodeBotTowerForce])*(cDriver_Input_from_FAST[iTurb].pxForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pxForce[iNodeBotTowerForce]) + + (cDriver_Input_from_FAST[iTurb].pyForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pyForce[iNodeBotTowerForce])*(cDriver_Input_from_FAST[iTurb].pyForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pyForce[iNodeBotTowerForce]) + + (cDriver_Input_from_FAST[iTurb].pzForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pzForce[iNodeBotTowerForce])*(cDriver_Input_from_FAST[iTurb].pzForce[iNodeForce] - cDriver_Input_from_FAST[iTurb].pzForce[iNodeBotTowerForce]) + ); + } + + + int iNodeBotTowerVel = 1 + nBlades * get_numVelPtsBladeLoc(iTurb); // Assumes the same number of velocity (Aerodyn) nodes for all blades + for(int j=0; j < nVelPtsTower; j++) { + int iNodeVel = iNodeBotTowerVel + j ; + double hDistVel = std::sqrt( + (cDriver_Input_from_FAST[iTurb].pxVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pxVel[iNodeBotTowerVel])*(cDriver_Input_from_FAST[iTurb].pxVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pxVel[iNodeBotTowerVel]) + + (cDriver_Input_from_FAST[iTurb].pyVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pyVel[iNodeBotTowerVel])*(cDriver_Input_from_FAST[iTurb].pyVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pyVel[iNodeBotTowerVel]) + + (cDriver_Input_from_FAST[iTurb].pzVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pzVel[iNodeBotTowerVel])*(cDriver_Input_from_FAST[iTurb].pzVel[iNodeVel] - cDriver_Input_from_FAST[iTurb].pzVel[iNodeBotTowerVel]) + ); + //Find nearest two force nodes + int jForceLower = 0; + while ( (hDistForce[jForceLower+1] < hDistVel) && ( jForceLower < (nForcePtsTower-2)) ) { + jForceLower = jForceLower + 1; + } + int iNodeForceLower = iNodeBotTowerForce + jForceLower ; + double rInterp = (hDistVel - hDistForce[jForceLower])/(hDistForce[jForceLower+1]-hDistForce[jForceLower]); + cDriver_Output_to_FAST[iTurb].u[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][0] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][0] - forceNodeVel[iTurb][iNodeForceLower][0] ); + cDriver_Output_to_FAST[iTurb].v[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][1] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][1] - forceNodeVel[iTurb][iNodeForceLower][1] ); + cDriver_Output_to_FAST[iTurb].w[iNodeVel] = forceNodeVel[iTurb][iNodeForceLower][2] + rInterp * (forceNodeVel[iTurb][iNodeForceLower+1][2] - forceNodeVel[iTurb][iNodeForceLower][2] ); + } + } + + } + +} + +void fast::OpenFAST::computeTorqueThrust(int iTurbGlob, std::vector<double> & torque, std::vector<double> & thrust) { + + //Compute the torque and thrust based on the forces at the actuator nodes + std::vector<double> relLoc(3,0.0); + std::vector<double> rPerpShft(3); + thrust[0] = 0.0; thrust[1] = 0.0; thrust[2] = 0.0; + torque[0] = 0.0; torque[1] = 0.0; torque[2] = 0.0; + + std::vector<double> hubShftVec(3); + getHubShftDir(hubShftVec, iTurbGlob); + + int iTurbLoc = get_localTurbNo(iTurbGlob) ; + for (int k=0; k < get_numBladesLoc(iTurbLoc); k++) { + for (int j=0; j < numForcePtsBlade[iTurbLoc]; j++) { + int iNode = 1 + numForcePtsBlade[iTurbLoc]*k + j ; + + thrust[0] = thrust[0] + cDriver_Input_from_FAST[iTurbLoc].fx[iNode] ; + thrust[1] = thrust[1] + cDriver_Input_from_FAST[iTurbLoc].fy[iNode] ; + thrust[2] = thrust[2] + cDriver_Input_from_FAST[iTurbLoc].fz[iNode] ; + + relLoc[0] = cDriver_Input_from_FAST[iTurbLoc].pxForce[iNode] - cDriver_Input_from_FAST[iTurbLoc].pxForce[0] ; + relLoc[1] = cDriver_Input_from_FAST[iTurbLoc].pyForce[iNode] - cDriver_Input_from_FAST[iTurbLoc].pyForce[0]; + relLoc[2] = cDriver_Input_from_FAST[iTurbLoc].pzForce[iNode] - cDriver_Input_from_FAST[iTurbLoc].pzForce[0]; + + double rDotHubShftVec = relLoc[0]*hubShftVec[0] + relLoc[1]*hubShftVec[1] + relLoc[2]*hubShftVec[2]; + for (int j=0; j < 3; j++) rPerpShft[j] = relLoc[j] - rDotHubShftVec * hubShftVec[j]; + + torque[0] = torque[0] + rPerpShft[1] * cDriver_Input_from_FAST[iTurbLoc].fz[iNode] - rPerpShft[2] * cDriver_Input_from_FAST[iTurbLoc].fy[iNode] + cDriver_Input_from_FAST[iTurbLoc].momentx[iNode] ; + torque[1] = torque[1] + rPerpShft[2] * cDriver_Input_from_FAST[iTurbLoc].fx[iNode] - rPerpShft[0] * cDriver_Input_from_FAST[iTurbLoc].fz[iNode] + cDriver_Input_from_FAST[iTurbLoc].momenty[iNode] ; + torque[2] = torque[2] + rPerpShft[0] * cDriver_Input_from_FAST[iTurbLoc].fy[iNode] - rPerpShft[1] * cDriver_Input_from_FAST[iTurbLoc].fx[iNode] + cDriver_Input_from_FAST[iTurbLoc].momentz[iNode] ; + + } + } +} + +fast::ActuatorNodeType fast::OpenFAST::getVelNodeType(int iTurbGlob, int iNode) { + // Return the type of velocity node for the given node number. The node ordering (from FAST) is + // Node 0 - Hub node + // Blade 1 nodes + // Blade 2 nodes + // Blade 3 nodes + // Tower nodes + + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numVelPtsLoc(iTurbGlob); + if (iNode) { + if ( (iNode + 1 - (get_numVelPts(iTurbLoc) - get_numVelPtsTwr(iTurbLoc)) ) > 0) { + return TOWER; + } + else { + return BLADE; + } + } + else { + return HUB; + } + +} + +fast::ActuatorNodeType fast::OpenFAST::getForceNodeType(int iTurbGlob, int iNode) { + // Return the type of actuator force node for the given node number. The node ordering (from FAST) is + // Node 0 - Hub node + // Blade 1 nodes + // Blade 2 nodes + // Blade 3 nodes + // Tower nodes + + int iTurbLoc = get_localTurbNo(iTurbGlob); + for(int j=0; j < iTurbLoc; j++) iNode = iNode - get_numForcePtsLoc(iTurbGlob); + if (iNode) { + if ( (iNode + 1 - (get_numForcePts(iTurbLoc) - get_numForcePtsTwr(iTurbLoc)) ) > 0) { + return TOWER; + } + else { + return BLADE; + } + } + else { + return HUB; + } + +} + +void fast::OpenFAST::allocateMemory() { + + for (int iTurb=0; iTurb < nTurbinesGlob; iTurb++) { + if (dryRun) { + if(worldMPIRank == 0) { + std::cout << "iTurb = " << iTurb << " turbineMapGlobToProc[iTurb] = " << turbineMapGlobToProc[iTurb] << std::endl ; + } + } + if(worldMPIRank == turbineMapGlobToProc[iTurb]) { + turbineMapProcToGlob[nTurbinesProc] = iTurb; + reverseTurbineMapProcToGlob[iTurb] = nTurbinesProc; + nTurbinesProc++ ; + } + turbineSetProcs.insert(turbineMapGlobToProc[iTurb]); + } + + int nProcsWithTurbines=0; + turbineProcs.resize(turbineSetProcs.size()); + + for (std::set<int>::const_iterator p = turbineSetProcs.begin(); p != turbineSetProcs.end(); p++) { + turbineProcs[nProcsWithTurbines] = *p; + nProcsWithTurbines++ ; + } + + if (dryRun) { + if (nTurbinesProc > 0) { + std::ofstream turbineAllocFile; + turbineAllocFile.open("turbineAlloc." + std::to_string(worldMPIRank) + ".txt") ; + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + turbineAllocFile << "Proc " << worldMPIRank << " loc iTurb " << iTurb << " glob iTurb " << turbineMapProcToGlob[iTurb] << std::endl ; + } + turbineAllocFile.flush(); + turbineAllocFile.close() ; + } + + } + + + // Construct a group containing all procs running atleast 1 turbine in FAST + MPI_Group_incl(worldMPIGroup, nProcsWithTurbines, &turbineProcs[0], &fastMPIGroup) ; + int fastMPIcommTag = MPI_Comm_create(mpiComm, fastMPIGroup, &fastMPIComm); + if (MPI_COMM_NULL != fastMPIComm) { + MPI_Comm_rank(fastMPIComm, &fastMPIRank); + } + + TurbID.resize(nTurbinesProc); + TurbineBasePos.resize(nTurbinesProc); + FASTInputFileName.resize(nTurbinesProc); + CheckpointFileRoot.resize(nTurbinesProc); + nacelle_cd.resize(nTurbinesProc); + nacelle_area.resize(nTurbinesProc); + air_density.resize(nTurbinesProc); + numBlades.resize(nTurbinesProc); + numForcePtsBlade.resize(nTurbinesProc); + numForcePtsTwr.resize(nTurbinesProc); + numVelPtsBlade.resize(nTurbinesProc); + numVelPtsTwr.resize(nTurbinesProc); + forceNodeVel.resize(nTurbinesProc); + + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + + TurbineBasePos[iTurb].resize(3); + + int globProc = turbineMapProcToGlob[iTurb]; + TurbID[iTurb] = globTurbineData[globProc].TurbID; + FASTInputFileName[iTurb] = globTurbineData[globProc].FASTInputFileName ; + CheckpointFileRoot[iTurb] = globTurbineData[globProc].FASTRestartFileName ; + for(int i=0;i<3;i++) { + TurbineBasePos[iTurb][i] = globTurbineData[globProc].TurbineBasePos[i]; + } + numForcePtsBlade[iTurb] = globTurbineData[globProc].numForcePtsBlade; + numForcePtsTwr[iTurb] = globTurbineData[globProc].numForcePtsTwr; + nacelle_cd[iTurb] = globTurbineData[globProc].nacelle_cd; + nacelle_area[iTurb] = globTurbineData[globProc].nacelle_area; + air_density[iTurb] = globTurbineData[globProc].air_density; + + } + + // Allocate memory for Turbine datastructure for all turbines + FAST_AllocateTurbines(&nTurbinesProc, &ErrStat, ErrMsg); + + // Allocate memory for OpFM Input types in FAST + cDriver_Input_from_FAST.resize(nTurbinesProc) ; + cDriver_Output_to_FAST.resize(nTurbinesProc) ; + + cDriverSC_Input_from_FAST.resize(nTurbinesProc) ; + cDriverSC_Output_to_FAST.resize(nTurbinesProc) ; + +} + +void fast::OpenFAST::allocateTurbinesToProcsSimple() { + + // Allocate turbines to each processor - round robin fashion + int nProcs ; + MPI_Comm_size(mpiComm, &nProcs); + for(int j = 0; j < nTurbinesGlob; j++) turbineMapGlobToProc[j] = j % nProcs ; + +} + +void fast::OpenFAST::end() { + + // Deallocate types we allocated earlier + + if (nTurbinesProc > 0) closeVelocityDataFile(nt_global, velNodeDataFile); + + if ( !dryRun) { + bool stopTheProgram = false; + for (int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + FAST_End(&iTurb, &stopTheProgram); + } + FAST_DeallocateTurbines(&ErrStat, ErrMsg); + } + + MPI_Group_free(&fastMPIGroup); + if (MPI_COMM_NULL != fastMPIComm) { + MPI_Comm_free(&fastMPIComm); + } + MPI_Group_free(&worldMPIGroup); + + if(scStatus) { + + destroy_SuperController(sc) ; + + if(scLibHandle != NULL) { + // close the library + std::cout << "Closing library...\n"; + dlclose(scLibHandle); + } + + } + +} + +void fast::OpenFAST::readVelocityData(int nTimesteps) { + + int nTurbines; + + hid_t velDataFile = H5Fopen(("velDatafile." + std::to_string(worldMPIRank) + ".h5").c_str(), H5F_ACC_RDWR, H5P_DEFAULT); + + { + hid_t attr = H5Aopen(velDataFile, "nTurbines", H5P_DEFAULT); + herr_t ret = H5Aread(attr, H5T_NATIVE_INT, &nTurbines) ; + H5Aclose(attr); + + } + + // Allocate memory and read the velocity data. + velNodeData.resize(nTurbines); + for (int iTurb=0; iTurb < nTurbines; iTurb++) { + int nVelPts = get_numVelPtsLoc(iTurb) ; + velNodeData[iTurb].resize(nTimesteps*nVelPts*6) ; + hid_t dset_id = H5Dopen2(velDataFile, ("/turbine" + std::to_string(iTurb)).c_str(), H5P_DEFAULT); + hid_t dspace_id = H5Dget_space(dset_id); + + hsize_t start[3]; start[1] = 0; start[2] = 0; + hsize_t count[3]; count[0] = 1; count[1] = nVelPts; count[2] = 6; + hid_t mspace_id = H5Screate_simple(3, count, NULL); + + for (int iStep=0; iStep < nTimesteps; iStep++) { + start[0] = iStep; + H5Sselect_hyperslab(dspace_id, H5S_SELECT_SET, start, NULL, count, NULL); + herr_t status = H5Dread(dset_id, H5T_NATIVE_DOUBLE, mspace_id, dspace_id, H5P_DEFAULT, &velNodeData[iTurb][iStep*nVelPts*6] ); + } + herr_t status = H5Dclose(dset_id); + + + } + +} + +hid_t fast::OpenFAST::openVelocityDataFile(bool createFile) { + + hid_t velDataFile; + if (createFile) { + // Open the file in create mode + velDataFile = H5Fcreate(("velDatafile." + std::to_string(worldMPIRank) + ".h5").c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + { + hsize_t dims[1]; + dims[0] = 1; + hid_t dataSpace = H5Screate_simple(1, dims, NULL); + hid_t attr = H5Acreate2(velDataFile, "nTurbines", H5T_NATIVE_INT, dataSpace, H5P_DEFAULT, H5P_DEFAULT) ; + herr_t status = H5Awrite(attr, H5T_NATIVE_INT, &nTurbinesProc); + status = H5Aclose(attr); + status = H5Sclose(dataSpace); + + dataSpace = H5Screate_simple(1, dims, NULL); + attr = H5Acreate2(velDataFile, "nTimesteps", H5T_NATIVE_INT, dataSpace, H5P_DEFAULT, H5P_DEFAULT) ; + status = H5Aclose(attr); + status = H5Sclose(dataSpace); + } + + int ntMax = tMax/dtFAST ; + + for (int iTurb = 0; iTurb < nTurbinesProc; iTurb++) { + int nVelPts = get_numVelPtsLoc(iTurb); + hsize_t dims[3]; + dims[0] = ntMax; dims[1] = nVelPts; dims[2] = 6 ; + + hsize_t chunk_dims[3]; + chunk_dims[0] = 1; chunk_dims[1] = nVelPts; chunk_dims[2] = 6; + hid_t dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + H5Pset_chunk(dcpl_id, 3, chunk_dims); + + hid_t dataSpace = H5Screate_simple(3, dims, NULL); + hid_t dataSet = H5Dcreate(velDataFile, ("/turbine" + std::to_string(iTurb)).c_str(), H5T_NATIVE_DOUBLE, dataSpace, H5P_DEFAULT, dcpl_id, H5P_DEFAULT); + + herr_t status = H5Pclose(dcpl_id); + status = H5Dclose(dataSet); + status = H5Sclose(dataSpace); + } + + } else { + // Open the file in append mode + velDataFile = H5Fopen(("velDatafile." + std::to_string(worldMPIRank) + ".h5").c_str(), H5F_ACC_RDWR, H5P_DEFAULT); + } + + return velDataFile; + +} + +herr_t fast::OpenFAST::closeVelocityDataFile(int nt_global, hid_t velDataFile) { + + herr_t status = H5Fclose(velDataFile) ; + return status; +} + + +void fast::OpenFAST::backupVelocityDataFile(int curTimeStep, hid_t & velDataFile) { + + closeVelocityDataFile(curTimeStep, velDataFile); + + std::ifstream source("velDatafile." + std::to_string(worldMPIRank) + ".h5", std::ios::binary); + std::ofstream dest("velDatafile." + std::to_string(worldMPIRank) + ".h5." + std::to_string(curTimeStep) + ".bak", std::ios::binary); + + dest << source.rdbuf(); + source.close(); + dest.close(); + + velDataFile = openVelocityDataFile(false); +} + +void fast::OpenFAST::writeVelocityData(hid_t h5File, int iTurb, int iTimestep, OpFM_InputType_t iData, OpFM_OutputType_t oData) { + + hsize_t start[3]; start[0] = iTimestep; start[1] = 0; start[2] = 0; + int nVelPts = get_numVelPtsLoc(iTurb) ; + hsize_t count[3]; count[0] = 1; count[1] = nVelPts; count[2] = 6; + + std::vector<double> tmpVelData; + tmpVelData.resize(nVelPts * 6); + + for (int iNode=0 ; iNode < nVelPts; iNode++) { + tmpVelData[iNode*6 + 0] = iData.pxVel[iNode]; + tmpVelData[iNode*6 + 1] = iData.pyVel[iNode]; + tmpVelData[iNode*6 + 2] = iData.pzVel[iNode]; + tmpVelData[iNode*6 + 3] = oData.u[iNode]; + tmpVelData[iNode*6 + 4] = oData.v[iNode]; + tmpVelData[iNode*6 + 5] = oData.w[iNode]; + } + + hid_t dset_id = H5Dopen2(h5File, ("/turbine" + std::to_string(iTurb)).c_str(), H5P_DEFAULT); + hid_t dspace_id = H5Dget_space(dset_id); + H5Sselect_hyperslab(dspace_id, H5S_SELECT_SET, start, NULL, count, NULL); + hid_t mspace_id = H5Screate_simple(3, count, NULL); + H5Dwrite(dset_id, H5T_NATIVE_DOUBLE, mspace_id, dspace_id, H5P_DEFAULT, tmpVelData.data()); + + H5Dclose(dset_id); + H5Sclose(dspace_id); + H5Sclose(mspace_id); + + hid_t attr_id = H5Aopen_by_name(h5File, ".", "nTimesteps", H5P_DEFAULT, H5P_DEFAULT); + herr_t status = H5Awrite(attr_id, H5T_NATIVE_INT, &iTimestep); + status = H5Aclose(attr_id); + +} + +void fast::OpenFAST::applyVelocityData(int iPrestart, int iTurb, OpFM_OutputType_t cDriver_Output_to_FAST, std::vector<double> & velData) { + + int nVelPts = get_numVelPtsLoc(iTurb); + for (int j = 0; j < nVelPts; j++){ + cDriver_Output_to_FAST.u[j] = velData[(iPrestart*nVelPts+j)*6 + 3]; + cDriver_Output_to_FAST.v[j] = velData[(iPrestart*nVelPts+j)*6 + 4]; + cDriver_Output_to_FAST.w[j] = velData[(iPrestart*nVelPts+j)*6 + 5]; + } + +} + +void fast::OpenFAST::loadSuperController(const fast::fastInputs & fi) { + + if(fi.scStatus) { + + scStatus = fi.scStatus; + scLibFile = fi.scLibFile; + + // open the library + scLibHandle = dlopen(scLibFile.c_str(), RTLD_LAZY); + if (!scLibHandle) { + std::cerr << "Cannot open library: " << dlerror() << '\n'; + } + + create_SuperController = (create_sc_t*) dlsym(scLibHandle, "create_sc"); + // reset errors + dlerror(); + const char *dlsym_error = dlerror(); + if (dlsym_error) { + std::cerr << "Cannot load symbol 'create_sc': " << dlsym_error << '\n'; + dlclose(scLibHandle); + } + + destroy_SuperController = (destroy_sc_t*) dlsym(scLibHandle, "destroy_sc"); + // reset errors + dlerror(); + const char *dlsym_error_us = dlerror(); + if (dlsym_error_us) { + std::cerr << "Cannot load symbol 'destroy_sc': " << dlsym_error_us << '\n'; + dlclose(scLibHandle); + } + + sc = create_SuperController() ; + + numScInputs = fi.numScInputs; + numScOutputs = fi.numScOutputs; + + if ( (numScInputs > 0) && (numScOutputs > 0)) { + scOutputsGlob.resize(nTurbinesGlob*numScOutputs) ; + scInputsGlob.resize(nTurbinesGlob*numScInputs) ; + for (int iTurb=0; iTurb < nTurbinesGlob; iTurb++) { + for(int iInput=0; iInput < numScInputs; iInput++) { + scInputsGlob[iTurb*numScInputs + iInput] = 0.0 ; // Initialize to zero + } + for(int iOutput=0; iOutput < numScOutputs; iOutput++) { + scOutputsGlob[iTurb*numScOutputs + iOutput] = 0.0 ; // Initialize to zero + } + } + + } else { + std::cerr << "Make sure numScInputs and numScOutputs are greater than zero" << std::endl; + } + + } else { + scStatus = false; + numScInputs = 0; + numScOutputs = 0; + } + +} + + +void fast::OpenFAST::fillScInputsGlob() { + + // Fills the global array containing inputs to the supercontroller from all turbines + + for(int iTurb=0; iTurb < nTurbinesGlob; iTurb++) { + for(int iInput=0; iInput < numScInputs; iInput++) { + scInputsGlob[iTurb*numScInputs + iInput] = 0.0; // Initialize to zero + } + } + + for(int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + for(int iInput=0; iInput < numScInputs; iInput++) { + scInputsGlob[turbineMapProcToGlob[iTurb]*numScInputs + iInput] = cDriverSC_Input_from_FAST[iTurb].toSC[iInput] ; + } + } + + if (MPI_COMM_NULL != fastMPIComm) { + MPI_Allreduce(MPI_IN_PLACE, scInputsGlob.data(), numScInputs*nTurbinesGlob, MPI_DOUBLE, MPI_SUM, fastMPIComm) ; + } + +} + + +void fast::OpenFAST::fillScOutputsLoc() { + + // Fills the local array containing outputs from the supercontroller to each turbine + + for(int iTurb=0; iTurb < nTurbinesProc; iTurb++) { + for(int iOutput=0; iOutput < numScOutputs; iOutput++) { + cDriverSC_Output_to_FAST[iTurb].fromSC[iOutput] = scOutputsGlob[turbineMapProcToGlob[iTurb]*numScOutputs + iOutput] ; + } + } + +} + + + + + + + + + + + diff --git a/OpenFAST/glue-codes/openfast-cpp/src/SC.h b/OpenFAST/glue-codes/openfast-cpp/src/SC.h new file mode 100644 index 000000000..423d0b78a --- /dev/null +++ b/OpenFAST/glue-codes/openfast-cpp/src/SC.h @@ -0,0 +1,39 @@ + +#include "SuperController_Types.h" +#include <sstream> +#include <iostream> +#include "hdf5.h" +#include <string> + +class SuperController { + + private: + + int nTurbines; + int nScInputs; + int nScOutputs; + + int nGlobStates; // Global states like time + double * globStates; + + int nTurbineStates; // States for each turbine + double ** turbineStates ; + + double d2R = 0.01745329251 ; //Degrees to Radians + + public: + + SuperController(); + + virtual ~SuperController() ; + + virtual void init(int n, int numScInputs, int numScOutputs); + + virtual void calcOutputs(std::vector<double> & scOutputsGlob) ; + + virtual void updateStates(std::vector<double> & scInputsGlob) ; + + virtual int writeRestartFile(int n_t_global); + + virtual int readRestartFile(int n_t_global); +}; diff --git a/OpenFAST/glue-codes/openfast/CMakeLists.txt b/OpenFAST/glue-codes/openfast/CMakeLists.txt new file mode 100644 index 000000000..f4e4e4485 --- /dev/null +++ b/OpenFAST/glue-codes/openfast/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 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. +# + +add_executable(openfast src/FAST_Prog.f90) +target_link_libraries(openfast openfast_postlib foamfastlib) +set_property(TARGET openfast PROPERTY LINKER_LANGUAGE Fortran) + +string(TOUPPER ${CMAKE_Fortran_COMPILER_ID} _compiler_id) +string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type) +if (${_compiler_id} STREQUAL "GNU" AND ${_build_type} STREQUAL "RELEASE") + # With variable tracking enabled, the compile step frequently aborts on large modules and + # restarts with this option off. Disabling in Release mode avoids this problem when compiling with + # full optimizations, but leaves it enabled for RelWithDebInfo which adds both -O2 and -g flags. + # https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html + set_source_files_properties(src/FAST_Prog.f90 PROPERTIES COMPILE_FLAGS "-fno-var-tracking -fno-var-tracking-assignments") +endif() + +install(TARGETS openfast + RUNTIME DESTINATION bin) diff --git a/OpenFAST/glue-codes/openfast/src/FAST_Prog.c b/OpenFAST/glue-codes/openfast/src/FAST_Prog.c new file mode 100644 index 000000000..998218021 --- /dev/null +++ b/OpenFAST/glue-codes/openfast/src/FAST_Prog.c @@ -0,0 +1,185 @@ + +#include "FAST_Library.h" +#include "stdio.h" +#include <string.h> +#include <math.h> +#include <stdlib.h> +#include <malloc.h> + +int checkError(const int ErrStat, const char * ErrMsg); +void setOutputsToFAST(OpFM_InputType_t* OpFM_Input_from_FAST, OpFM_OutputType_t* OpFM_Output_to_FAST); + + +int +main(int argc, char *argv[], char *env[]) +{ + double dt; + double TMax=10.0; + float TurbinePos[3]; + int TurbID; + int ErrStat = 0; + char ErrMsg[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 + char InputFileName[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 + char CheckpointFileRoot[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 + + OpFM_InputType_t* OpFM_Input_from_FAST = NULL; + OpFM_OutputType_t* OpFM_Output_to_FAST = NULL; + + int n_t_global = -2; + int i = 0; + int j = 0; + int k = 0; + int n_t_global_start = 0; + int NumBlades = 0; + int NumElementsPerBlade = 0; + int NumTwrElements = 0; + int n_checkpoint = 10; + int NumScOutputs = 4; // 5; // # outputs from the supercontroller == # inputs to the controller == NumSC2Ctrl + int NumScInputs = 2; // 2; // # inputs to the supercontroller == # outputs from the controller == NumCtrl2SC + + OpFM_Input_from_FAST = malloc(sizeof(OpFM_InputType_t)); + OpFM_Output_to_FAST = malloc(sizeof(OpFM_OutputType_t)); + if (OpFM_Input_from_FAST == NULL || OpFM_Output_to_FAST == NULL) { + fprintf(stderr, "Error allocating space for OpFM interface types.\n"); + return 1; + } + + + + if (0){ // restart from checkpoint file + + /* ****************************** + restart + ********************************* */ + /* note that this will set n_t_global inside the FAST library */ + strcpy(CheckpointFileRoot, "../../../CertTest/Test18.1200"); + FAST_OpFM_Restart(CheckpointFileRoot, &AbortErrLev, &dt, &NumBlades, &NumElementsPerBlade, &n_t_global_start, OpFM_Input_from_FAST, OpFM_Output_to_FAST, &ErrStat, ErrMsg); + if (checkError(ErrStat, ErrMsg)) return 1; + + } + else{ + /* ****************************** + initialization + ********************************* */ + + // this calls the Init() routines of each module + strcpy(InputFileName, "../../../CertTest/Test18.fst"); + TurbID = 1; + TurbinePos[0] = 0.0; // x location of turbine + TurbinePos[1] = 0.0; // y location of turbine + TurbinePos[2] = 0.0; // z location of turbine + + FAST_OpFM_Init(&TMax, InputFileName, &TurbID, &NumScOutputs, &NumScInputs, TurbinePos, &AbortErrLev, &dt, &NumBlades, &NumElementsPerBlade, + OpFM_Input_from_FAST, OpFM_Output_to_FAST, &ErrStat, ErrMsg); + if (checkError(ErrStat, ErrMsg)) return 1; + + NumTwrElements = OpFM_Output_to_FAST->u_Len - NumBlades*NumElementsPerBlade - 1; + + + // set wind speeds at initial locations + setOutputsToFAST(OpFM_Input_from_FAST, OpFM_Output_to_FAST); + + FAST_OpFM_Solution0(&ErrStat, ErrMsg); + if (checkError(ErrStat, ErrMsg)) return 1; + + } + + // determine subcycling number + + /* ****************************** + call FAST once per time step + ********************************* */ + + for (n_t_global = n_t_global_start; n_t_global < 20; n_t_global++){ + + /* ****************************** + if you want to create a checkpoint file: + ********************************* */ + if (n_t_global == n_checkpoint){ + //sprintf(CheckpointFileRoot, "../../CertTest/Test18.%d", n_t_global); + sprintf(CheckpointFileRoot, " "); // if blank, it will use FAST convention <RootName>.n_t_global + FAST_CreateCheckpoint(CheckpointFileRoot, &ErrStat, ErrMsg); + checkError(ErrStat, ErrMsg); + } + + + /* ****************************** + set inputs from this code and call FAST: + ********************************* */ + + // set wind speeds at original locations + setOutputsToFAST(OpFM_Input_from_FAST, OpFM_Output_to_FAST); + + + // this advances the states, calls CalcOutput, and solves for next inputs. Predictor-corrector loop is imbeded here: + // (note OpenFOAM could do subcycling around this step) + FAST_OpFM_Step(&ErrStat, ErrMsg); + if (checkError(ErrStat, ErrMsg)) return 1; + + + // do something with + //OpFM_Input_from_FAST->px[j] + //OpFM_Input_from_FAST->py[j] + //OpFM_Input_from_FAST->pz[j] + //OpFM_Input_from_FAST->fx[j] + //OpFM_Input_from_FAST->fy[j] + //OpFM_Input_from_FAST->fz[j] + //OpFM_Input_from_FAST->SuperController[j] + } + + /* ****************************** + End the program + ********************************* */ + + FAST_End(); + + // deallocate types we allocated earlier + if (OpFM_Input_from_FAST != NULL) { + free(OpFM_Input_from_FAST); + OpFM_Input_from_FAST = NULL; + } + if (OpFM_Output_to_FAST != NULL) { + free(OpFM_Output_to_FAST); + OpFM_Output_to_FAST = NULL; + } + +} + +int +checkError(const int ErrStat, const char * ErrMsg){ + + if (ErrStat != ErrID_None){ + fprintf(stderr, "%s\n", ErrMsg); + + if (ErrStat >= AbortErrLev){ + FAST_End(); + return 1; + } + + } + + return 0; + +} + +void +setOutputsToFAST(OpFM_InputType_t* OpFM_Input_from_FAST, OpFM_OutputType_t* OpFM_Output_to_FAST){ + int j; + + // routine sets the u-v-w wind speeds used in FAST and the SuperController inputs + + for (j = 0; j < OpFM_Output_to_FAST->u_Len; j++){ + OpFM_Output_to_FAST->u[j] = (float) 10.0*pow((OpFM_Input_from_FAST->pz[j] / 90.0), 0.2); // 0.2 power law wind profile using reference 10 m/s at 90 meters + OpFM_Output_to_FAST->v[j] = 0.0; + OpFM_Output_to_FAST->w[j] = 0.0; + } + + // call supercontroller + + for (j = 0; j < OpFM_Output_to_FAST->SuperController_Len; j++){ + OpFM_Output_to_FAST->SuperController[j] = (float) j; // set it somehow.... (would be set from the SuperController outputs) + } + + + return; +} diff --git a/OpenFAST/glue-codes/openfast/src/FAST_Prog.f90 b/OpenFAST/glue-codes/openfast/src/FAST_Prog.f90 new file mode 100644 index 000000000..990b6b496 --- /dev/null +++ b/OpenFAST/glue-codes/openfast/src/FAST_Prog.f90 @@ -0,0 +1,209 @@ +!********************************************************************************************************************************** +! FAST_Solver.f90, FAST_Subs.f90, FAST_Lin.f90, and FAST_Mods.f90 make up the FAST glue code in the FAST Modularization Framework. +! FAST_Prog.f90, FAST_Library.f90, FAST_Prog.c are different drivers for this code. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST. +! +! 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. +! +!********************************************************************************************************************************** +PROGRAM FAST +! This program models 2- or 3-bladed turbines of a standard configuration. +! +! noted compilation switches: +! OUTPUT_ADDEDMASS (outputs a file called "<RootName>.AddedMass" that contains HydroDyn's added-mass matrix. +! OUTPUT_JACOBIAN +! FPE_TRAP_ENABLED (use with gfortran when checking for floating point exceptions) +! DOUBLE_PRECISION (compile in double precision) +!................................................................................................. + + +USE FAST_Subs ! all of the ModuleName and ModuleName_types modules are inherited from FAST_Subs + +IMPLICIT NONE + + ! Local parameters: +REAL(DbKi), PARAMETER :: t_initial = 0.0_DbKi ! Initial time +INTEGER(IntKi), PARAMETER :: NumTurbines = 1 ! Note that CalcSteady linearization analysis and WrVTK_Modes should be performed with only 1 turbine + + ! Other/Misc variables +TYPE(FAST_TurbineType) :: Turbine(NumTurbines) ! Data for each turbine instance + +INTEGER(IntKi) :: i_turb ! current turbine number +INTEGER(IntKi) :: n_t_global ! simulation time step, loop counter for global (FAST) simulation +INTEGER(IntKi) :: ErrStat ! Error status +CHARACTER(ErrMsgLen) :: ErrMsg ! Error message + + ! data for restart: +CHARACTER(1000) :: InputFile ! String to hold the intput file name +CHARACTER(1024) :: CheckpointRoot ! Rootname of the checkpoint file +CHARACTER(20) :: FlagArg ! flag argument from command line +INTEGER(IntKi) :: Restart_step ! step to start on (for restart) + + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! determine if this is a restart from checkpoint + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + CALL NWTC_Init() ! open console for writing + ProgName = 'OpenFAST' + InputFile = "" + CheckpointRoot = "" + + CALL CheckArgs( InputFile, Flag=FlagArg, Arg2=CheckpointRoot ) + + IF ( TRIM(FlagArg) == 'RESTART' ) THEN ! Restart from checkpoint file + CALL FAST_RestoreFromCheckpoint_Tary(t_initial, Restart_step, Turbine, CheckpointRoot, ErrStat, ErrMsg ) + CALL CheckError( ErrStat, ErrMsg, 'during restore from checkpoint' ) + + ELSE IF ( TRIM(FlagArg) == 'VTKLIN' ) THEN ! Read checkpoint file to output linearization analysis, but don't continue time-marching + CALL FAST_RestoreForVTKModeShape_Tary(t_initial, Turbine, CheckpointRoot, ErrStat, ErrMsg ) + CALL CheckError( ErrStat, ErrMsg, 'during restore from checkpoint for mode shapes' ) + + ! Note that this works only when NumTurbines==1 (we don't have files for each of the turbines...) + Restart_step = Turbine(1)%p_FAST%n_TMax_m1 + 1 + CALL ExitThisProgram_T( Turbine(1), ErrID_None, .true., SkipRunTimeMsg = .TRUE. ) + + ELSEIF ( LEN( TRIM(FlagArg) ) > 0 ) THEN ! Any other flag, end normally + CALL NormStop() + + + ELSE + Restart_step = 0 + + DO i_turb = 1,NumTurbines + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! initialization + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + CALL FAST_InitializeAll_T( t_initial, i_turb, Turbine(i_turb), ErrStat, ErrMsg ) ! bjj: we need to get the input files for each turbine (not necessarily the same one) + CALL CheckError( ErrStat, ErrMsg, 'during module initialization' ) + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! loose coupling + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + !............................................................................................................................... + ! Initialization: (calculate outputs based on states at t=t_initial as well as guesses of inputs and constraint states) + !............................................................................................................................... + CALL FAST_Solution0_T( Turbine(i_turb), ErrStat, ErrMsg ) + CALL CheckError( ErrStat, ErrMsg, 'during simulation initialization' ) + + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! linearization (bjj: we want to call FAST_Linearize_T whenever WriteOutputToFile is called, but I'll put it at the driver level for now) + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! if we need to do linarization analysis at t=0, do it at this operating point + CALL FAST_Linearize_T(t_initial, 0, Turbine(i_turb), ErrStat, ErrMsg) + CALL CheckError( ErrStat, ErrMsg ) + + + END DO + END IF + + + + !............................................................................................................................... + ! Time Stepping: + !............................................................................................................................... + +TIME_STEP_LOOP: DO n_t_global = Restart_step, Turbine(1)%p_FAST%n_TMax_m1 + + ! bjj: we have to make sure the n_TMax_m1 and n_ChkptTime are the same for all turbines or have some different logic here + + + ! write checkpoint file if requested + IF (mod(n_t_global, Turbine(1)%p_FAST%n_ChkptTime) == 0 .AND. Restart_step /= n_t_global .and. .not. Turbine(1)%m_FAST%Lin%FoundSteady) then + CheckpointRoot = TRIM(Turbine(1)%p_FAST%OutFileRoot)//'.'//TRIM(Num2LStr(n_t_global)) + + CALL FAST_CreateCheckpoint_Tary(t_initial, n_t_global, Turbine, CheckpointRoot, ErrStat, ErrMsg) + IF(ErrStat >= AbortErrLev .and. AbortErrLev >= ErrID_Severe) THEN + ErrStat = MIN(ErrStat,ErrID_Severe) ! We don't need to stop simulation execution on this error + ErrMsg = TRIM(ErrMsg)//Newline//'WARNING: Checkpoint file could not be generated. Simulation continuing.' + END IF + CALL CheckError( ErrStat, ErrMsg ) + END IF + + + ! this takes data from n_t_global and gets values at n_t_global + 1 + DO i_turb = 1,NumTurbines + + CALL FAST_Solution_T( t_initial, n_t_global, Turbine(i_turb), ErrStat, ErrMsg ) + CALL CheckError( ErrStat, ErrMsg ) + + + ! if we need to do linarization analysis, do it at this operating point (which is now n_t_global + 1) + ! put this at the end of the loop so that we can output linearization analysis at last OP if desired + CALL FAST_Linearize_T(t_initial, n_t_global+1, Turbine(i_turb), ErrStat, ErrMsg) + CALL CheckError( ErrStat, ErrMsg ) + + IF ( Turbine(i_turb)%m_FAST%Lin%FoundSteady) EXIT TIME_STEP_LOOP + END DO + + END DO TIME_STEP_LOOP ! n_t_global + + DO i_turb = 1,NumTurbines + if ( Turbine(i_turb)%p_FAST%CalcSteady .and. .not. Turbine(i_turb)%m_FAST%Lin%FoundSteady) then + CALL CheckError( ErrID_Fatal, "Unable to find steady-state solution." ) + end if + END DO + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Write simulation times and stop + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + DO i_turb = 1,NumTurbines + CALL ExitThisProgram_T( Turbine(i_turb), ErrID_None, i_turb==NumTurbines ) + END DO + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg,ErrLocMsg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + CHARACTER(*), INTENT(IN), OPTIONAL :: ErrLocMsg ! an optional message describing the location of the error + + CHARACTER(1024) :: SimMsg + integer(IntKi) :: i_turb2 + + + IF ( ErrID /= ErrID_None ) THEN + CALL WrScr( NewLine//TRIM(Msg)//NewLine ) + + IF ( ErrID >= AbortErrLev ) THEN + IF (PRESENT(ErrLocMsg)) THEN + SimMsg = ErrLocMsg + ELSE + SimMsg = 'at simulation time '//TRIM(Num2LStr(Turbine(1)%m_FAST%t_global))//' of '//TRIM(Num2LStr(Turbine(1)%p_FAST%TMax))//' seconds' + END IF + + DO i_turb2 = 1,NumTurbines + CALL ExitThisProgram_T( Turbine(i_turb2), ErrID, i_turb2==NumTurbines, SimMsg ) + END DO + + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END PROGRAM FAST +!======================================================================= diff --git a/OpenFAST/glue-codes/python/OpenFAST.py b/OpenFAST/glue-codes/python/OpenFAST.py new file mode 100644 index 000000000..a0f6e0e2c --- /dev/null +++ b/OpenFAST/glue-codes/python/OpenFAST.py @@ -0,0 +1,49 @@ + +from ctypes import ( + byref, + create_string_buffer, + pointer, + c_int, + c_double, + c_char, + c_bool +) +import openfast_library + +project_root = '/Users/rmudafor/Development/weis' +library_path = project_root + '/build/modules/openfast-library/libopenfastlib.dylib' +t_max = c_double(11.0) + +## Serial +# input_file_name = create_string_buffer(b"/Users/rmudafor/Development/weis/reg_tests/r-test/glue-codes/openfast/AOC_YFix_WSt/AOC_YFix_WSt.fst") +# openfastlib = openfast_library.FastLibAPI(library_path, input_file_name, t_max) +# openfastlib.fast_run() + +# Display the outputs +# for i, c in enumerate(openfastlib.output_channel_names): +# print(i, c) +# print(openfastlib.output_channel_names) +# print(openfastlib.output_values) +# print(openfastlib.output_values[:,0]) # Prints the time steps + +## Parallel with MPI +from mpi4py import MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() + +if rank == 0: + input_file_name = "{}/reg_tests/r-test/glue-codes/openfast/AOC_WSt/AOC_WSt.fst".format(project_root) + openfastlib = openfast_library.FastLibAPI(library_path, create_string_buffer(input_file_name.encode('utf-8')), t_max) + openfastlib.fast_run() +elif rank == 1: + input_file_name = "{}/reg_tests/r-test/glue-codes/openfast/AOC_YFix_WSt/AOC_YFix_WSt.fst".format(project_root) + openfastlib = openfast_library.FastLibAPI(library_path, create_string_buffer(input_file_name.encode('utf-8')), t_max) + openfastlib.fast_run() +elif rank == 2: + input_file_name = "{}/reg_tests/r-test/glue-codes/openfast/AOC_YFree_WTurb/AOC_YFree_WTurb.fst".format(project_root) + openfastlib = openfast_library.FastLibAPI(library_path, create_string_buffer(input_file_name.encode('utf-8')), t_max) + openfastlib.fast_run() +elif rank == 3: + input_file_name = "{}/reg_tests/r-test/glue-codes/openfast/AWT_YFix_WSt/AWT_YFix_WSt.fst".format(project_root) + openfastlib = openfast_library.FastLibAPI(library_path, create_string_buffer(input_file_name.encode('utf-8')), t_max) + openfastlib.fast_run() diff --git a/OpenFAST/glue-codes/python/openfast_library.py b/OpenFAST/glue-codes/python/openfast_library.py new file mode 100644 index 000000000..0788d3525 --- /dev/null +++ b/OpenFAST/glue-codes/python/openfast_library.py @@ -0,0 +1,204 @@ +from ctypes import ( + CDLL, + POINTER, + create_string_buffer, + byref, + c_int, + c_double, + c_char, + c_bool +) +import numpy as np + + +class FastLibAPI(CDLL): + def __init__(self, library_path, input_file_name, t_max): + super().__init__(library_path) + self.library_path = library_path + self.input_file_name = input_file_name + self.t_max = t_max + + self._initialize_routines() + + # Create buffers for class data + self.n_turbines = c_int(1) + self.i_turb = c_int(0) + self.dt = c_double(0.0) + self.abort_error_level = c_int(99) + self.num_outs = c_int(0) + self._channel_names = create_string_buffer(20 * 4000) + self.output_array = None + + self.error_status = c_int(0) + self.error_message = create_string_buffer(1025) + + # The inputs are meant to be from Simulink. + # If < 8, FAST_SetExternalInputs simply returns, + # but this behavior may change to an error + ### MAKE THIS 8 OR 11 + self._num_inputs = c_int(8) + self._inp_array = (c_double * 10)(0.0, ) # 10 is hard-coded in FAST_Library as MAXInitINPUTS + + self.output_values = None + self.ended = False + + def _initialize_routines(self): + self.FAST_AllocateTurbines.argtypes = [ + POINTER(c_int), + POINTER(c_int), + POINTER(c_char) + ] + self.FAST_AllocateTurbines.restype = c_int + + self.FAST_Sizes.argtype = [ + POINTER(c_int), # iTurb IN + POINTER(c_double), # TMax IN + POINTER(c_double), # InitInpAry IN; 10 is hard coded in the C++ interface + POINTER(c_char), # InputFileName_c IN + POINTER(c_int), # AbortErrLev_c OUT + POINTER(c_int), # NumOuts_c OUT + POINTER(c_double), # dt_c OUT + POINTER(c_int), # ErrStat_c OUT + POINTER(c_char), # ErrMsg_c OUT + POINTER(c_char) # ChannelNames_c OUT + ] + self.FAST_Sizes.restype = c_int + + self.FAST_Start.argtype = [ + POINTER(c_int), # iTurb IN + POINTER(c_int), # NumInputs_c IN + POINTER(c_int), # NumOutputs_c IN + POINTER(c_double), # InputAry IN + POINTER(c_double), # OutputAry OUT + POINTER(c_int), # ErrStat_c OUT + POINTER(c_char) # ErrMsg_c OUT + ] + self.FAST_Start.restype = c_int + + self.FAST_Update.argtype = [ + POINTER(c_int), # iTurb IN + POINTER(c_int), # NumInputs_c IN + POINTER(c_int), # NumOutputs_c IN + POINTER(c_double), # InputAry IN + POINTER(c_double), # OutputAry OUT + POINTER(c_int), # ErrStat_c OUT + POINTER(c_char) # ErrMsg_c OUT + ] + self.FAST_Update.restype = c_int + + self.FAST_DeallocateTurbines.argtypes = [ + POINTER(c_int), # ErrStat_c OUT + POINTER(c_char), # ErrMsg_c OUT + ] + self.FAST_DeallocateTurbines.restype = c_int + + self.FAST_End.argtypes = [ + POINTER(c_int), # iTurb IN + POINTER(c_bool), # StopTheProgram IN + ] + self.FAST_End.restype = c_int + + @property + def fatal_error(self): + return self.error_status.value >= self.abort_error_level.value + + def fast_init(self): + self.FAST_AllocateTurbines( + byref(self.n_turbines), + byref(self.error_status), + self.error_message + ) + if self.fatal_error: + print(f"Error {self.error_status.value}: {self.error_message.value}") + return + + self.FAST_Sizes( + byref(self.i_turb), + byref(self.t_max), + byref(self._inp_array), + self.input_file_name, + byref(self.abort_error_level), + byref(self.num_outs), + byref(self.dt), + byref(self.error_status), + self.error_message, + self._channel_names + ) + if self.fatal_error: + print(f"Error {self.error_status.value}: {self.error_message.value}") + return + + # Allocate the data for the outputs + # NOTE: The ctypes array allocation (output_array) must be after the output_values + # allocation, or otherwise seg fault. + self.output_values = np.empty( (self.total_time_steps, self.num_outs.value) ) + self.output_array = (c_double * self.num_outs.value)(0.0, ) + + def fast_sim(self): + self.FAST_Start( + byref(self.i_turb), + byref(self._num_inputs), + byref(self.num_outs), + byref(self._inp_array), + byref(self.output_array), + byref(self.error_status), + self.error_message + ) + self.output_values[0] = self.output_array[:] + if self.fatal_error: + self.fast_deinit() + print(f"Error {self.error_status.value}: {self.error_message.value}") + return + + for i in range( 1, self.total_time_steps ): + self.FAST_Update( + byref(self.i_turb), + byref(self._num_inputs), + byref(self.num_outs), + byref(self._inp_array), + byref(self.output_array), + byref(self.error_status), + self.error_message + ) + self.output_values[i] = self.output_array[:] + if self.fatal_error: + self.fast_deinit() + print(f"Error {self.error_status.value}: {self.error_message.value}") + return + + def fast_deinit(self): + if not self.ended: + self.ended = True + + # Deallocate all the internal variables and allocatable arrays + # Despite the name, this does not actually end the program + self.FAST_End( + byref(self.i_turb), + byref(c_bool(False)) + ) + + # Deallocate the Turbine array + self.FAST_DeallocateTurbines( + byref(self.error_status), + self.error_message + ) + if self.fatal_error: + print(f"Error {self.error_status.value}: {self.error_message.value}") + return + + def fast_run(self): + self.fast_init() + if self.fatal_error: return + self.fast_sim() + if self.fatal_error: return + self.fast_deinit() + + @property + def total_time_steps(self): + return int(self.t_max.value / self.dt.value) + 1 + + @property + def output_channel_names(self): + output_channel_names = self._channel_names.value.split() + output_channel_names = [n.decode('UTF-8') for n in output_channel_names] + return output_channel_names diff --git a/OpenFAST/glue-codes/simulink/examples/OpenLoop.mdl b/OpenFAST/glue-codes/simulink/examples/OpenLoop.mdl new file mode 100644 index 000000000..47faf19de --- /dev/null +++ b/OpenFAST/glue-codes/simulink/examples/OpenLoop.mdl @@ -0,0 +1,1261 @@ +Model { + Name "OpenLoop" + Version 7.9 + MdlSubVersion 0 + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.87" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SavedCharacterEncoding "windows-1252" + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + FPTRunName "Run 1" + MaxMDLFileLineLength 120 + Created "Mon Feb 09 16:59:21 2004" + Creator "bjonkman" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%<Auto>" + LastModifiedBy "bjonkman" + ModifiedDateFormat "%<Auto>" + LastModifiedDate "Thu Feb 26 12:27:50 2015" + RTWModifiedTimeStamp 346852301 + ModelVersionFormat "1.%<AutoIncrement:87>" + ConfigurationManager "None" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "none" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowDesignRanges off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock on + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 1 + Version "1.12.0" + Array { + Type "Handle" + Dimension 8 + Simulink.SolverCC { + $ObjectID 2 + Version "1.12.0" + StartTime "0.0" + StopTime "TMax" + AbsTol "auto" + FixedStep "DT" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "DT" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + EnableConcurrentExecution off + ConcurrentTasks off + Solver "ode4" + SolverName "ode4" + SolverJacobianMethodControl "auto" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 3 + Version "1.12.0" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints on + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SignalLoggingSaveFormat "ModelDataLogs" + SaveOutput off + SaveState off + SignalLogging on + DSMLogging on + InspectSignalLogs off + SaveTime off + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "sigsOut" + DSMLoggingName "dsmout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 4 + Version "1.12.0" + Array { + Type "Cell" + Dimension 8 + Cell "BooleansAsBitfields" + Cell "PassReuseOutputArgsAs" + Cell "PassReuseOutputArgsThreshold" + Cell "ZeroExternalMemoryAtStartup" + Cell "ZeroInternalMemoryAtStartup" + Cell "OptimizeModelRefInitCode" + Cell "NoFixptDivByZeroProtection" + Cell "UseSpecifiedMinMax" + PropName "DisabledProps" + } + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + UseFloatMulNetSlope off + UseSpecifiedMinMax off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + StrengthReduction off + ExpressionFolding on + BooleansAsBitfields off + BitfieldContainerType "uint_T" + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 2147483647 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero off + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + MaxStackSize "Inherit from target" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + ParallelExecutionInRapidAccelerator on + } + Simulink.DebuggingCC { + $ObjectID 5 + Version "1.12.0" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "none" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Classic" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "TryResolveAllWithWarning" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + MaskedZcDiagnostic "warning" + IgnoredZcDiagnostic "warning" + SolverPrmCheckMsg "none" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "warning" + MultiTaskCondExecSysMsg "none" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "Enable All" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + FrameProcessingCompatibilityMsg "warning" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceMultiInstanceNormalModeStructChecksumCheck "error" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "warning" + SimStateInterfaceChecksumMismatchMsg "warning" + SimStateOlderReleaseMsg "error" + InitInArrayFormatMsg "warning" + StrictBusMsg "None" + BusNameAdapt "WarnAndRepair" + NonBusSignalsTreatedAsBus "none" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + SFUnusedDataAndEventsDiag "warning" + SFUnexpectedBacktrackingDiag "warning" + SFInvalidInputDataAccessInChartInitDiag "warning" + SFNoUnconditionalDefaultTransitionDiag "warning" + SFTransitionOutsideNaturalParentDiag "warning" + SFUnconditionalTransitionShadowingDiag "warning" + } + Simulink.HardwareCC { + $ObjectID 6 + Version "1.12.0" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdBitPerFloat 32 + ProdBitPerDouble 64 + ProdBitPerPointer 32 + ProdLargestAtomicInteger "Char" + ProdLargestAtomicFloat "None" + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetBitPerFloat 32 + TargetBitPerDouble 64 + TargetBitPerPointer 32 + TargetLargestAtomicInteger "Char" + TargetLargestAtomicFloat "None" + TargetShiftRightIntArith on + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown on + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 7 + Version "1.12.0" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + EnableParallelModelReferenceBuilds off + ParallelModelReferenceErrorOnInvalidPool on + ParallelModelReferenceMATLABWorkerInit "None" + ModelReferenceNumInstancesAllowed "Multi" + PropagateVarSize "Infer from blocks in model" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + PropagateSignalLabelsOutOfModel off + SupportModelReferenceSimTargetCustomCode off + } + Simulink.SFSimCC { + $ObjectID 8 + Version "1.12.0" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimParseCustomCode on + SimBuildMode "sf_incremental_build" + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 9 + Version "1.12.0" + Array { + Type "Cell" + Dimension 9 + Cell "IncludeHyperlinkInReport" + Cell "GenerateTraceInfo" + Cell "GenerateTraceReport" + Cell "GenerateTraceReportSl" + Cell "GenerateTraceReportSf" + Cell "GenerateTraceReportEml" + Cell "GenerateWebview" + Cell "GenerateCodeMetricsReport" + Cell "GenerateCodeReplacementReport" + PropName "DisabledProps" + } + SystemTargetFile "grt.tlc" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + TemplateMakefile "grt_default_tmf" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + IncludeHyperlinkInReport off + LaunchReport off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime on + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + GenerateWebview off + GenerateCodeMetricsReport off + GenerateCodeReplacementReport off + RTWCompilerOptimization "Off" + CheckMdlBeforeBuild "Off" + CustomRebuildMode "OnUpdate" + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 10 + Version "1.12.0" + Array { + Type "Cell" + Dimension 21 + Cell "IgnoreCustomStorageClasses" + Cell "IgnoreTestpoints" + Cell "InsertBlockDesc" + Cell "InsertPolySpaceComments" + Cell "SFDataObjDesc" + Cell "MATLABFcnDesc" + Cell "SimulinkDataObjDesc" + Cell "DefineNamingRule" + Cell "SignalNamingRule" + Cell "ParamNamingRule" + Cell "InlinedPrmAccess" + Cell "CustomSymbolStr" + Cell "CustomSymbolStrGlobalVar" + Cell "CustomSymbolStrType" + Cell "CustomSymbolStrField" + Cell "CustomSymbolStrFcn" + Cell "CustomSymbolStrFcnArg" + Cell "CustomSymbolStrBlkIO" + Cell "CustomSymbolStrTmpVar" + Cell "CustomSymbolStrMacro" + Cell "ReqsInCode" + PropName "DisabledProps" + } + ForceParamTrailComments off + GenerateComments on + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + MATLABFcnDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + InsertPolySpaceComments off + SimulinkBlockComments on + MATLABSourceComments off + EnableCustomComments off + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 11 + Version "1.12.0" + Array { + Type "Cell" + Dimension 16 + Cell "GeneratePreprocessorConditionals" + Cell "IncludeMdlTerminateFcn" + Cell "CombineOutputUpdateFcns" + Cell "SuppressErrorStatus" + Cell "ERTCustomFileBanners" + Cell "GenerateSampleERTMain" + Cell "GenerateTestInterfaces" + Cell "ModelStepFunctionPrototypeControlCompliant" + Cell "CPPClassGenCompliant" + Cell "MultiInstanceERTCode" + Cell "PurelyIntegerCode" + Cell "SupportComplex" + Cell "SupportAbsoluteTime" + Cell "SupportContinuousTime" + Cell "SupportNonInlinedSFcns" + Cell "PortableWordSizes" + PropName "DisabledProps" + } + TargetFcnLib "ansi_tfl_table_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + CodeReplacementLibrary "ANSI_C" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + CodeExecutionProfiling off + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + IsPILTarget off + ModelReferenceCompliant on + ParMdlRefBuildCompliant on + CompOptLevelCompliant on + ConcurrentExecutionCompliant on + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns off + CombineSignalStateStructs off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging on + MultiInstanceERTCode off + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + PortableWordSizes off + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant off + AutosarCompliant off + GRTInterface on + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + RTWCAPIRootIO off + GenerateASAP2 off + } + PropName "Components" + } + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition [ 520, 285, 1400, 915 ] + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 1 + } + ExplicitPartitioning off + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Helvetica" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + BlockParameterDefaults { + Block { + BlockType Clock + DisplayTime off + Decimation "10" + } + Block { + BlockType Constant + Value "1" + VectorParams1D on + SamplingMode "Sample based" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Inherit from 'Constant value'" + LockScale off + SampleTime "inf" + FramePeriod "inf" + PreserveConstantTs off + } + Block { + BlockType Inport + Port "1" + OutputFunctionCall off + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + LatchByDelayingOutsideSignal off + LatchInputForFeedbackSignals off + Interpolate on + } + Block { + BlockType Mux + Inputs "4" + DisplayOption "none" + UseBusObject off + BusObject "BusObject" + NonVirtualBus off + } + Block { + BlockType Outport + Port "1" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + SourceOfInitialOutputValue "Dialog" + OutputWhenDisabled "held" + InitialOutput "[]" + } + Block { + BlockType S-Function + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType SignalSpecification + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + Dimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + } + Block { + BlockType SubSystem + ShowPortLabels "FromPortIcon" + Permissions "ReadWrite" + PermitHierarchicalResolution "All" + TreatAsAtomicUnit off + CheckFcnCallInpInsideContextMsg off + SystemSampleTime "-1" + RTWFcnNameOpts "Auto" + RTWFileNameOpts "Auto" + RTWMemSecFuncInitTerm "Inherit from model" + RTWMemSecFuncExecute "Inherit from model" + RTWMemSecDataConstants "Inherit from model" + RTWMemSecDataInternal "Inherit from model" + RTWMemSecDataParameters "Inherit from model" + SimViewingDevice off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + SFBlockType "NONE" + Variant off + GeneratePreprocessorConditionals off + } + Block { + BlockType ToWorkspace + VariableName "simulink_output" + MaxDataPoints "1000" + Decimation "1" + SampleTime "0" + SaveFormat "Array" + FixptAsFi off + NumInputs "1" + } + } + System { + Name "OpenLoop" + Location [2, 93, 1900, 1047] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "243" + ReportName "simulink-default.rpt" + SIDHighWatermark "34" + Block { + BlockType Clock + Name "Clock" + SID "1" + Position [30, 25, 50, 45] + } + Block { + BlockType SubSystem + Name "FAST Nonlinear Wind Turbine" + SID "2" + Ports [4, 1] + Position [200, 73, 420, 317] + BackgroundColor "darkGreen" + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + MaskType "FAST Nonlinear Wind Turbine" + MaskDescription "This block contains the FAST S-Function." + MaskInitialization "clear FAST_SFunc\n" + MaskIconFrame on + MaskIconOpaque on + MaskIconRotate "none" + MaskPortRotate "default" + MaskIconUnits "autoscale" + System { + Name "FAST Nonlinear Wind Turbine" + Location [2, 93, 1900, 1047] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "243" + Block { + BlockType Inport + Name "Gen. Torque (Nm) and Power (W)" + SID "3" + Position [80, 43, 110, 57] + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "Yaw Position (rad) and Rate (rad/s)" + SID "4" + Position [80, 98, 110, 112] + Port "2" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "Blade Pitch Angles (rad)" + SID "5" + Position [80, 153, 110, 167] + Port "3" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "High-Speed Shaft Braking Fraction (-)" + SID "31" + Position [80, 208, 110, 222] + Port "4" + IconDisplay "Port number" + } + Block { + BlockType Mux + Name "Mux1" + SID "9" + Ports [4, 1] + Position [335, 21, 340, 244] + ShowName off + DisplayOption "bar" + } + Block { + BlockType S-Function + Name "S-Function" + SID "10" + Ports [1, 1] + Position [380, 96, 450, 174] + BackgroundColor "magenta" + FunctionName "FAST_SFunc" + Parameters "FAST_InputFileName, TMax, 0" + EnableBusSupport off + } + Block { + BlockType SignalSpecification + Name "Signal Specification1" + SID "11" + Position [200, 40, 300, 60] + OutDataTypeStr "double" + Dimensions "2" + SignalType "real" + } + Block { + BlockType SignalSpecification + Name "Signal Specification2" + SID "12" + Position [200, 93, 300, 117] + OutDataTypeStr "double" + Dimensions "2" + SignalType "real" + } + Block { + BlockType Outport + Name "OutData" + SID "13" + Position [500, 127, 530, 143] + BackgroundColor "yellow" + IconDisplay "Port number" + } + Line { + SrcBlock "Gen. Torque (Nm) and Power (W)" + SrcPort 1 + DstBlock "Signal Specification1" + DstPort 1 + } + Line { + SrcBlock "S-Function" + SrcPort 1 + DstBlock "OutData" + DstPort 1 + } + Line { + SrcBlock "Mux1" + SrcPort 1 + DstBlock "S-Function" + DstPort 1 + } + Line { + SrcBlock "Blade Pitch Angles (rad)" + SrcPort 1 + DstBlock "Mux1" + DstPort 3 + } + Line { + SrcBlock "Yaw Position (rad) and Rate (rad/s)" + SrcPort 1 + DstBlock "Signal Specification2" + DstPort 1 + } + Line { + SrcBlock "Signal Specification1" + SrcPort 1 + DstBlock "Mux1" + DstPort 1 + } + Line { + SrcBlock "Signal Specification2" + SrcPort 1 + DstBlock "Mux1" + DstPort 2 + } + Line { + SrcBlock "High-Speed Shaft Braking Fraction (-)" + SrcPort 1 + DstBlock "Mux1" + DstPort 4 + } + } + } + Block { + BlockType SubSystem + Name "High-Speed Shaft Brake" + SID "32" + Ports [0, 1] + Position [30, 264, 130, 306] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "High-Speed Shaft Brake" + Location [433, 403, 916, 674] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Constant + Name "High-Speed Shaft Braking Fraction" + SID "33" + Position [55, 35, 85, 65] + Value "0" + } + Block { + BlockType Outport + Name "Out1" + SID "34" + Position [140, 43, 170, 57] + IconDisplay "Port number" + } + Line { + SrcBlock "High-Speed Shaft Braking Fraction" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + } + } + Block { + BlockType SubSystem + Name "Pitch Controller" + SID "16" + Ports [0, 1] + Position [30, 204, 130, 246] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Pitch Controller" + Location [433, 403, 916, 538] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Constant + Name "Blade Pitch Angles" + SID "17" + Position [55, 35, 85, 65] + Value "zeros(1,3)'" + } + Block { + BlockType Outport + Name "Out1" + SID "18" + Position [140, 43, 170, 57] + IconDisplay "Port number" + } + Line { + SrcBlock "Blade Pitch Angles" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + } + } + Block { + BlockType ToWorkspace + Name "To Workspace" + SID "19" + Ports [1] + Position [70, 20, 130, 50] + VariableName "Time" + MaxDataPoints "inf" + SampleTime "-1" + } + Block { + BlockType SubSystem + Name "Torque Controller" + SID "20" + Ports [0, 1] + Position [30, 84, 130, 126] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Torque Controller" + Location [433, 403, 919, 560] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Constant + Name "Electrical Power" + SID "21" + Position [55, 85, 85, 115] + Value "1000" + } + Block { + BlockType Constant + Name "Generator Torque" + SID "22" + Position [55, 30, 85, 60] + Value "1000" + } + Block { + BlockType Mux + Name "Mux" + SID "23" + Ports [2, 1] + Position [200, 51, 205, 89] + ShowName off + Inputs "2" + DisplayOption "bar" + } + Block { + BlockType Outport + Name "Out1" + SID "24" + Position [255, 63, 285, 77] + IconDisplay "Port number" + } + Line { + SrcBlock "Mux" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + Line { + SrcBlock "Generator Torque" + SrcPort 1 + Points [45, 0; 0, 15] + DstBlock "Mux" + DstPort 1 + } + Line { + SrcBlock "Electrical Power" + SrcPort 1 + Points [45, 0; 0, -20] + DstBlock "Mux" + DstPort 2 + } + } + } + Block { + BlockType SubSystem + Name "Yaw Controller" + SID "25" + Ports [0, 1] + Position [30, 144, 130, 186] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Yaw Controller" + Location [433, 403, 907, 565] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Mux + Name "Mux" + SID "26" + Ports [2, 1] + Position [190, 56, 195, 94] + ShowName off + Inputs "2" + DisplayOption "bar" + } + Block { + BlockType Constant + Name "Yaw Position" + SID "27" + Position [45, 30, 75, 60] + Value "0" + } + Block { + BlockType Constant + Name "Yaw rate" + SID "28" + Position [45, 90, 75, 120] + Value "0" + } + Block { + BlockType Outport + Name "Out1" + SID "29" + Position [245, 68, 275, 82] + IconDisplay "Port number" + } + Line { + SrcBlock "Mux" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + Line { + SrcBlock "Yaw Position" + SrcPort 1 + Points [45, 0; 0, 20] + DstBlock "Mux" + DstPort 1 + } + Line { + SrcBlock "Yaw rate" + SrcPort 1 + Points [45, 0; 0, -20] + DstBlock "Mux" + DstPort 2 + } + } + } + Block { + BlockType ToWorkspace + Name "qdotdot_out" + SID "30" + Ports [1] + Position [485, 183, 555, 207] + BackgroundColor "yellow" + ShowName off + VariableName "OutData" + MaxDataPoints "inf" + SampleTime "-1" + } + Line { + SrcBlock "Clock" + SrcPort 1 + DstBlock "To Workspace" + DstPort 1 + } + Line { + SrcBlock "FAST Nonlinear Wind Turbine" + SrcPort 1 + DstBlock "qdotdot_out" + DstPort 1 + } + Line { + SrcBlock "Torque Controller" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 1 + } + Line { + SrcBlock "Yaw Controller" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 2 + } + Line { + SrcBlock "Pitch Controller" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 3 + } + Line { + SrcBlock "High-Speed Shaft Brake" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 4 + } + } +} diff --git a/OpenFAST/glue-codes/simulink/examples/Run_OpenLoop.m b/OpenFAST/glue-codes/simulink/examples/Run_OpenLoop.m new file mode 100644 index 000000000..2df5fb485 --- /dev/null +++ b/OpenFAST/glue-codes/simulink/examples/Run_OpenLoop.m @@ -0,0 +1,12 @@ +% make sure the OpenFAST directory where the FAST_SFunc.mex* file is located +% is in the MATLAB path (also make sure any other OpenFAST library files that +% are needed are on the MATLAB path) +% (relative path names are not recommended in addpath()): +% addpath('../../../build/bin'); % install location for Windows Visual Studio builds +% addpath(genpath('../../../install')); % cmake default install location + +% these variables are defined in the OpenLoop model's FAST_SFunc block: +FAST_InputFileName = '../../../reg_tests/r-test/glue-codes/openfast/5MW_Land_DLL_WTurb/5MW_Land_DLL_WTurb.fst'; +TMax = 60; % seconds + +sim('OpenLoop.mdl',[0,TMax]); diff --git a/OpenFAST/glue-codes/simulink/examples/Run_Test01_SIG.m b/OpenFAST/glue-codes/simulink/examples/Run_Test01_SIG.m new file mode 100644 index 000000000..77b9062c4 --- /dev/null +++ b/OpenFAST/glue-codes/simulink/examples/Run_Test01_SIG.m @@ -0,0 +1,39 @@ +% make sure the OpenFAST directory where the FAST_SFunc.mex* file is located +% is in the MATLAB path (also make sure any other OpenFAST library files that +% are needed are on the MATLAB path) +% (relative path names are not recommended in addpath()): +% addpath('../../../build/bin'); % install location for Windows Visual Studio builds +% addpath(genpath('../../../install')); % cmake default install location + + +% Simple Induction Generator Example ====================================== +% To model a simple induction generator in Simulink use model Test01_SIG.mdl. +% The following parameters duplicate those used in Certification Test #01. + +% Change AWT_YFix_WSt.fst (formerly Test01.fst) as follows: +% set VSContrl = 4 in ../../../reg_tests/r-test/glue-codes/openfast/AWT_YFix_WSt/AWT_YFix_WSt_ServoDyn.dat + + +GenEff = 100.0; % - Generator efficiency [ignored by the Thevenin and user-defined generator models] (%) +GBRatio = 22.5; % - Gearbox ratio (-) +SIG_SlPc = 1.5125; % - Rated generator slip percentage [>0] (%) Now HSS side! +SIG_SySp = 1200.0; % - Synchronous (zero-torque) generator speed [>0] (rpm) Now HSS side! +SIG_RtTq = 1367.9; % - Rated torque [>0] (N-m) Now HSS side! +SIG_PORt = 2.0; % - Pull-out ratio (Tpullout/Trated) [>1] (-)% +SIG_SySp = SIG_SySp*pi/30; % convert to rad/s +SIG_RtSp = SIG_SySp*(1.0+0.01*SIG_SlPc); +SIG_POS1=SIG_PORt*(SIG_RtSp-SIG_SySp); +SIG_POTq=SIG_RtTq*SIG_PORt; +SIG_Slop=SIG_RtTq/(SIG_RtSp - SIG_SySp); + + +% parameters required for the S-Function block: +OpenFASTRoot = '../../../reg_tests/r-test/glue-codes/openfast/AWT_YFix_WSt/'; +FAST_InputFileName = [ OpenFASTRoot 'AWT_YFix_WSt.fst' ]; +TMax = 20; + +% run the model +sim('Test01_SIG.mdl',[0,TMax]); + +% look at results: +% PlotFASToutput({[ OpenFASTRoot 'AWT_YFix_WSt.SFunc.out'],[ OpenFASTRoot 'windows-intel/AWT_YFix_WSt.out']},{'SFunc','exe'}); \ No newline at end of file diff --git a/OpenFAST/glue-codes/simulink/examples/Test01_SIG.mdl b/OpenFAST/glue-codes/simulink/examples/Test01_SIG.mdl new file mode 100644 index 000000000..c1bb4ac28 --- /dev/null +++ b/OpenFAST/glue-codes/simulink/examples/Test01_SIG.mdl @@ -0,0 +1,1498 @@ +Model { + Name "Test01_SIG" + Version 7.9 + MdlSubVersion 0 + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.81" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SavedCharacterEncoding "windows-1252" + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + FPTRunName "Run 1" + MaxMDLFileLineLength 120 + Created "Mon Feb 09 16:59:21 2004" + Creator "bjonkman" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%<Auto>" + LastModifiedBy "bjonkman" + ModifiedDateFormat "%<Auto>" + LastModifiedDate "Thu Feb 26 12:32:59 2015" + RTWModifiedTimeStamp 346854631 + ModelVersionFormat "1.%<AutoIncrement:81>" + ConfigurationManager "None" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "none" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowDesignRanges off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock on + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 1 + Version "1.12.0" + Array { + Type "Handle" + Dimension 8 + Simulink.SolverCC { + $ObjectID 2 + Version "1.12.0" + StartTime "0.0" + StopTime "TMax" + AbsTol "auto" + FixedStep "DT" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "DT" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + EnableConcurrentExecution off + ConcurrentTasks off + Solver "ode4" + SolverName "ode4" + SolverJacobianMethodControl "auto" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 3 + Version "1.12.0" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints off + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SignalLoggingSaveFormat "ModelDataLogs" + SaveOutput off + SaveState off + SignalLogging on + DSMLogging on + InspectSignalLogs off + SaveTime off + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "sigsOut" + DSMLoggingName "dsmout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 4 + Version "1.12.0" + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + UseFloatMulNetSlope off + UseSpecifiedMinMax off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + StrengthReduction off + ExpressionFolding on + BooleansAsBitfields off + BitfieldContainerType "uint_T" + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 2147483647 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero off + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + MaxStackSize "Inherit from target" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + ParallelExecutionInRapidAccelerator on + } + Simulink.DebuggingCC { + $ObjectID 5 + Version "1.12.0" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "none" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Classic" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "TryResolveAllWithWarning" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + MaskedZcDiagnostic "warning" + IgnoredZcDiagnostic "warning" + SolverPrmCheckMsg "none" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "warning" + MultiTaskCondExecSysMsg "none" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "Use local settings" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + FrameProcessingCompatibilityMsg "warning" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceMultiInstanceNormalModeStructChecksumCheck "error" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "warning" + SimStateInterfaceChecksumMismatchMsg "warning" + SimStateOlderReleaseMsg "error" + InitInArrayFormatMsg "warning" + StrictBusMsg "None" + BusNameAdapt "WarnAndRepair" + NonBusSignalsTreatedAsBus "none" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + SFUnusedDataAndEventsDiag "warning" + SFUnexpectedBacktrackingDiag "warning" + SFInvalidInputDataAccessInChartInitDiag "warning" + SFNoUnconditionalDefaultTransitionDiag "warning" + SFTransitionOutsideNaturalParentDiag "warning" + SFUnconditionalTransitionShadowingDiag "warning" + } + Simulink.HardwareCC { + $ObjectID 6 + Version "1.12.0" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdBitPerFloat 32 + ProdBitPerDouble 64 + ProdBitPerPointer 32 + ProdLargestAtomicInteger "Char" + ProdLargestAtomicFloat "None" + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetBitPerFloat 32 + TargetBitPerDouble 64 + TargetBitPerPointer 32 + TargetLargestAtomicInteger "Char" + TargetLargestAtomicFloat "None" + TargetShiftRightIntArith on + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown on + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 7 + Version "1.12.0" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + EnableParallelModelReferenceBuilds off + ParallelModelReferenceErrorOnInvalidPool on + ParallelModelReferenceMATLABWorkerInit "None" + ModelReferenceNumInstancesAllowed "Multi" + PropagateVarSize "Infer from blocks in model" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + PropagateSignalLabelsOutOfModel off + SupportModelReferenceSimTargetCustomCode off + } + Simulink.SFSimCC { + $ObjectID 8 + Version "1.12.0" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimParseCustomCode on + SimBuildMode "sf_incremental_build" + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 9 + Version "1.12.0" + SystemTargetFile "grt.tlc" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + TemplateMakefile "grt_default_tmf" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + IncludeHyperlinkInReport off + LaunchReport off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime on + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + GenerateWebview off + GenerateCodeMetricsReport off + GenerateCodeReplacementReport off + RTWCompilerOptimization "Off" + CheckMdlBeforeBuild "Off" + CustomRebuildMode "OnUpdate" + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 10 + Version "1.12.0" + ForceParamTrailComments off + GenerateComments on + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + MATLABFcnDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + InsertPolySpaceComments off + SimulinkBlockComments on + MATLABSourceComments off + EnableCustomComments off + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 11 + Version "1.12.0" + TargetFcnLib "ansi_tfl_table_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + CodeReplacementLibrary "ANSI_C" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + CodeExecutionProfiling off + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + IsPILTarget off + ModelReferenceCompliant off + ParMdlRefBuildCompliant off + CompOptLevelCompliant off + ConcurrentExecutionCompliant off + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns off + CombineSignalStateStructs off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging off + MultiInstanceERTCode off + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + PortableWordSizes off + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant off + AutosarCompliant off + GRTInterface on + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + RTWCAPIRootIO off + GenerateASAP2 off + } + PropName "Components" + } + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition [ 520, 285, 1400, 915 ] + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 1 + } + ExplicitPartitioning off + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Helvetica" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + BlockParameterDefaults { + Block { + BlockType Clock + DisplayTime off + Decimation "10" + } + Block { + BlockType Constant + Value "1" + VectorParams1D on + SamplingMode "Sample based" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Inherit from 'Constant value'" + LockScale off + SampleTime "inf" + FramePeriod "inf" + PreserveConstantTs off + } + Block { + BlockType DotProduct + SampleTime "-1" + InputSameDT on + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Same as first input" + LockScale off + RndMeth "Floor" + SaturateOnIntegerOverflow off + } + Block { + BlockType Fcn + Expr "sin(u[1])" + SampleTime "-1" + } + Block { + BlockType Gain + Gain "1" + Multiplication "Element-wise(K.*u)" + ParamMin "[]" + ParamMax "[]" + ParamDataTypeStr "Inherit: Same as input" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Same as input" + LockScale off + RndMeth "Floor" + SaturateOnIntegerOverflow on + SampleTime "-1" + } + Block { + BlockType Inport + Port "1" + OutputFunctionCall off + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + LatchByDelayingOutsideSignal off + LatchInputForFeedbackSignals off + Interpolate on + } + Block { + BlockType Mux + Inputs "4" + DisplayOption "none" + UseBusObject off + BusObject "BusObject" + NonVirtualBus off + } + Block { + BlockType Outport + Port "1" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + SourceOfInitialOutputValue "Dialog" + OutputWhenDisabled "held" + InitialOutput "[]" + } + Block { + BlockType S-Function + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType Saturate + UpperLimitSource "Dialog" + UpperLimit "0.5" + LowerLimitSource "Dialog" + LowerLimit "-0.5" + LinearizeAsGain on + ZeroCross on + SampleTime "-1" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Same as input" + LockScale off + RndMeth "Floor" + } + Block { + BlockType SignalSpecification + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + Dimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + } + Block { + BlockType SubSystem + ShowPortLabels "FromPortIcon" + Permissions "ReadWrite" + PermitHierarchicalResolution "All" + TreatAsAtomicUnit off + CheckFcnCallInpInsideContextMsg off + SystemSampleTime "-1" + RTWFcnNameOpts "Auto" + RTWFileNameOpts "Auto" + RTWMemSecFuncInitTerm "Inherit from model" + RTWMemSecFuncExecute "Inherit from model" + RTWMemSecDataConstants "Inherit from model" + RTWMemSecDataInternal "Inherit from model" + RTWMemSecDataParameters "Inherit from model" + SimViewingDevice off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + SFBlockType "NONE" + Variant off + GeneratePreprocessorConditionals off + } + Block { + BlockType Sum + IconShape "rectangular" + Inputs "++" + CollapseMode "All dimensions" + CollapseDim "1" + InputSameDT on + AccumDataTypeStr "Inherit: Inherit via internal rule" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Same as first input" + LockScale off + RndMeth "Floor" + SaturateOnIntegerOverflow on + SampleTime "-1" + } + Block { + BlockType Switch + Criteria "u2 >= Threshold" + Threshold "0" + InputSameDT on + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: Inherit via internal rule" + LockScale off + RndMeth "Floor" + SaturateOnIntegerOverflow on + ZeroCross on + SampleTime "-1" + AllowDiffInputSizes off + } + Block { + BlockType ToWorkspace + VariableName "simulink_output" + MaxDataPoints "1000" + Decimation "1" + SampleTime "0" + SaveFormat "Array" + FixptAsFi off + NumInputs "1" + } + } + System { + Name "Test01_SIG" + Location [2, 93, 1900, 1047] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "156" + ReportName "simulink-default.rpt" + SIDHighWatermark "57" + Block { + BlockType Clock + Name "Clock" + SID "1" + Position [50, 20, 70, 40] + } + Block { + BlockType SubSystem + Name "FAST Nonlinear Wind Turbine" + SID "2" + Ports [4, 1] + Position [460, 77, 680, 313] + BackgroundColor "darkGreen" + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + MaskType "FAST Nonlinear Wind Turbine" + MaskDescription "This block contains the FAST S-Function." + MaskInitialization "clear FAST_SFunc\n" + MaskIconFrame on + MaskIconOpaque on + MaskIconRotate "none" + MaskPortRotate "default" + MaskIconUnits "autoscale" + System { + Name "FAST Nonlinear Wind Turbine" + Location [2, 93, 1900, 1047] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "156" + Block { + BlockType Inport + Name "Gen. Torque (Nm) and Power (W)" + SID "3" + Position [80, 48, 110, 62] + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "Yaw Position (rad) and Rate (rad/s)" + SID "4" + Position [80, 108, 110, 122] + Port "2" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "Blade Pitch Angles (rad)" + SID "5" + Position [80, 168, 110, 182] + Port "3" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "High-Speed Shaft Braking Fraction (-)" + SID "54" + Position [80, 228, 110, 242] + Port "4" + IconDisplay "Port number" + } + Block { + BlockType Mux + Name "Mux1" + SID "9" + Ports [4, 1] + Position [340, 20, 345, 270] + ShowName off + DisplayOption "bar" + } + Block { + BlockType S-Function + Name "S-Function" + SID "10" + Ports [1, 1] + Position [390, 106, 460, 184] + BackgroundColor "magenta" + FunctionName "FAST_SFunc" + Parameters "FAST_InputFileName, TMax, 0" + EnableBusSupport off + } + Block { + BlockType SignalSpecification + Name "Signal Specification1" + SID "11" + Position [200, 45, 300, 65] + OutDataTypeStr "double" + Dimensions "2" + SignalType "real" + } + Block { + BlockType SignalSpecification + Name "Signal Specification2" + SID "12" + Position [200, 103, 300, 127] + OutDataTypeStr "double" + Dimensions "2" + SignalType "real" + } + Block { + BlockType Outport + Name "OutData" + SID "13" + Position [500, 137, 530, 153] + BackgroundColor "yellow" + IconDisplay "Port number" + } + Line { + SrcBlock "Gen. Torque (Nm) and Power (W)" + SrcPort 1 + DstBlock "Signal Specification1" + DstPort 1 + } + Line { + SrcBlock "S-Function" + SrcPort 1 + DstBlock "OutData" + DstPort 1 + } + Line { + SrcBlock "Mux1" + SrcPort 1 + DstBlock "S-Function" + DstPort 1 + } + Line { + SrcBlock "Blade Pitch Angles (rad)" + SrcPort 1 + DstBlock "Mux1" + DstPort 3 + } + Line { + SrcBlock "Yaw Position (rad) and Rate (rad/s)" + SrcPort 1 + DstBlock "Signal Specification2" + DstPort 1 + } + Line { + SrcBlock "Signal Specification1" + SrcPort 1 + DstBlock "Mux1" + DstPort 1 + } + Line { + SrcBlock "Signal Specification2" + SrcPort 1 + DstBlock "Mux1" + DstPort 2 + } + Line { + SrcBlock "High-Speed Shaft Braking Fraction (-)" + SrcPort 1 + DstBlock "Mux1" + DstPort 4 + } + } + } + Block { + BlockType Fcn + Name "Fcn" + SID "16" + Position [405, 340, 465, 370] + BlockMirror on + NamePlacement "alternate" + Expr "u(strmatch('LSSGagVxa',OutList))" + } + Block { + BlockType SubSystem + Name "High-Speed Shaft Brake" + SID "55" + Ports [0, 1] + Position [295, 264, 395, 306] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "High-Speed Shaft Brake" + Location [433, 403, 916, 674] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Constant + Name "High-Speed Shaft Braking Fraction" + SID "56" + Position [55, 35, 85, 65] + Value "0" + } + Block { + BlockType Outport + Name "Out1" + SID "57" + Position [140, 43, 170, 57] + IconDisplay "Port number" + } + Line { + SrcBlock "High-Speed Shaft Braking Fraction" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + } + } + Block { + BlockType SubSystem + Name "Pitch Controller" + SID "17" + Ports [0, 1] + Position [295, 204, 395, 246] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Pitch Controller" + Location [433, 403, 916, 538] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Constant + Name "Blade Pitch Angles" + SID "18" + Position [55, 35, 85, 65] + Value "zeros(1,3)'" + } + Block { + BlockType Outport + Name "Out1" + SID "19" + Position [140, 43, 170, 57] + IconDisplay "Port number" + } + Line { + SrcBlock "Blade Pitch Angles" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + } + } + Block { + BlockType SubSystem + Name "Simple Induction Generator" + SID "20" + Ports [1, 1] + Position [80, 79, 290, 131] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Simple Induction Generator" + Location [117, 208, 976, 620] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Inport + Name "Gen speed\nwrt LSS (RPM)" + SID "21" + Position [30, 78, 60, 92] + NamePlacement "alternate" + IconDisplay "Port number" + } + Block { + BlockType Gain + Name "100/GenEff1" + SID "22" + Position [520, 215, 550, 245] + BlockRotation 270 + BlockMirror on + Gain "100/GenEff" + } + Block { + BlockType DotProduct + Name "Dot Product" + SID "23" + Position [516, 140, 549, 175] + BlockRotation 270 + BlockMirror on + NamePlacement "alternate" + ShowName off + OutDataTypeStr "Inherit: Inherit via internal rule" + } + Block { + BlockType DotProduct + Name "Dot Product1" + SID "24" + Position [452, 140, 483, 175] + BlockRotation 270 + BlockMirror on + NamePlacement "alternate" + ShowName off + OutDataTypeStr "Inherit: Inherit via internal rule" + } + Block { + BlockType Gain + Name "GBRatio" + SID "25" + Position [145, 70, 175, 100] + NamePlacement "alternate" + Gain "GBRatio" + } + Block { + BlockType Gain + Name "GenEff/100" + SID "26" + Position [455, 215, 485, 245] + BlockRotation 270 + BlockMirror on + NamePlacement "alternate" + Gain "GenEff/100" + } + Block { + BlockType Mux + Name "Mux" + SID "27" + Ports [2, 1] + Position [715, 76, 720, 114] + ShowName off + Inputs "2" + DisplayOption "bar" + } + Block { + BlockType Gain + Name "RPM to rad/s" + SID "28" + Position [95, 70, 125, 100] + Gain "pi/30" + } + Block { + BlockType Gain + Name "SIG_Slop" + SID "29" + Position [320, 70, 350, 100] + Gain "SIG_Slop" + } + Block { + BlockType Constant + Name "SIG_SySp" + SID "30" + Position [210, 135, 240, 165] + BlockRotation 270 + Value "SIG_SySp" + } + Block { + BlockType Saturate + Name "Saturation" + SID "31" + Ports [1, 1] + Position [400, 70, 430, 100] + InputPortMap "u0" + UpperLimit "SIG_POTq" + LowerLimit "-(SIG_POTq)" + } + Block { + BlockType Sum + Name "Sum" + SID "32" + Ports [2, 1] + Position [215, 75, 235, 95] + ShowName off + IconShape "round" + Inputs "|+-" + InputSameDT off + OutDataTypeStr "Inherit: Inherit via internal rule" + } + Block { + BlockType Switch + Name "Switch" + SID "33" + Position [480, 305, 510, 335] + BlockRotation 270 + BlockMirror on + NamePlacement "alternate" + Criteria "u2 > Threshold" + InputSameDT off + } + Block { + BlockType Outport + Name "GenTrq, ElecPwr" + SID "34" + Position [755, 88, 785, 102] + IconDisplay "Port number" + } + Line { + SrcBlock "SIG_SySp" + SrcPort 1 + DstBlock "Sum" + DstPort 2 + } + Line { + SrcBlock "GBRatio" + SrcPort 1 + Points [0, 0; 10, 0] + Branch { + DstBlock "Sum" + DstPort 1 + } + Branch { + Points [0, -55; 270, 0] + Branch { + Points [65, 0] + DstBlock "Dot Product" + DstPort 1 + } + Branch { + DstBlock "Dot Product1" + DstPort 1 + } + } + } + Line { + SrcBlock "Sum" + SrcPort 1 + DstBlock "SIG_Slop" + DstPort 1 + } + Line { + SrcBlock "SIG_Slop" + SrcPort 1 + DstBlock "Saturation" + DstPort 1 + } + Line { + SrcBlock "Dot Product" + SrcPort 1 + DstBlock "100/GenEff1" + DstPort 1 + } + Line { + SrcBlock "100/GenEff1" + SrcPort 1 + Points [0, 20; -30, 0] + DstBlock "Switch" + DstPort 3 + } + Line { + SrcBlock "GenEff/100" + SrcPort 1 + Points [0, 20; 15, 0] + DstBlock "Switch" + DstPort 1 + } + Line { + SrcBlock "Dot Product1" + SrcPort 1 + DstBlock "GenEff/100" + DstPort 1 + } + Line { + SrcBlock "Saturation" + SrcPort 1 + Points [0, 0; 40, 0] + Branch { + DstBlock "Dot Product1" + DstPort 2 + } + Branch { + Points [20, 0] + Branch { + Points [45, 0] + Branch { + DstBlock "Dot Product" + DstPort 2 + } + Branch { + DstBlock "Mux" + DstPort 1 + } + } + Branch { + DstBlock "Switch" + DstPort 2 + } + } + } + Line { + SrcBlock "Mux" + SrcPort 1 + DstBlock "GenTrq, ElecPwr" + DstPort 1 + } + Line { + SrcBlock "RPM to rad/s" + SrcPort 1 + DstBlock "GBRatio" + DstPort 1 + } + Line { + SrcBlock "Switch" + SrcPort 1 + Points [0, 15; 150, 0; 0, -250] + DstBlock "Mux" + DstPort 2 + } + Line { + SrcBlock "Gen speed\nwrt LSS (RPM)" + SrcPort 1 + DstBlock "RPM to rad/s" + DstPort 1 + } + Annotation { + SID "35" + Name "HSS_Spd" + Position [186, 102] + } + Annotation { + SID "36" + Name "Slip" + Position [272, 101] + } + } + } + Block { + BlockType ToWorkspace + Name "To Workspace" + SID "37" + Ports [1] + Position [90, 15, 150, 45] + VariableName "Time" + MaxDataPoints "inf" + SampleTime "-1" + } + Block { + BlockType SubSystem + Name "Yaw Controller" + SID "38" + Ports [0, 1] + Position [295, 144, 395, 186] + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + RTWSystemCode "Auto" + FunctionWithSeparateData off + Opaque off + RequestExecContextInheritance off + MaskHideContents off + System { + Name "Yaw Controller" + Location [433, 403, 907, 565] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Mux + Name "Mux" + SID "39" + Ports [2, 1] + Position [190, 56, 195, 94] + ShowName off + Inputs "2" + DisplayOption "bar" + } + Block { + BlockType Constant + Name "Yaw Position" + SID "40" + Position [45, 30, 75, 60] + Value "0" + } + Block { + BlockType Constant + Name "Yaw rate" + SID "41" + Position [45, 90, 75, 120] + Value "0" + } + Block { + BlockType Outport + Name "Out1" + SID "42" + Position [245, 68, 275, 82] + IconDisplay "Port number" + } + Line { + SrcBlock "Mux" + SrcPort 1 + DstBlock "Out1" + DstPort 1 + } + Line { + SrcBlock "Yaw Position" + SrcPort 1 + Points [45, 0; 0, 20] + DstBlock "Mux" + DstPort 1 + } + Line { + SrcBlock "Yaw rate" + SrcPort 1 + Points [45, 0; 0, -20] + DstBlock "Mux" + DstPort 2 + } + } + } + Block { + BlockType ToWorkspace + Name "qdotdot_out" + SID "43" + Ports [1] + Position [750, 183, 820, 207] + BackgroundColor "yellow" + ShowName off + VariableName "OutData" + MaxDataPoints "inf" + SampleTime "-1" + } + Line { + SrcBlock "Clock" + SrcPort 1 + DstBlock "To Workspace" + DstPort 1 + } + Line { + SrcBlock "FAST Nonlinear Wind Turbine" + SrcPort 1 + Points [30, 0] + Branch { + DstBlock "qdotdot_out" + DstPort 1 + } + Branch { + Points [0, 160] + DstBlock "Fcn" + DstPort 1 + } + } + Line { + SrcBlock "Simple Induction Generator" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 1 + } + Line { + SrcBlock "Yaw Controller" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 2 + } + Line { + SrcBlock "Pitch Controller" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 3 + } + Line { + SrcBlock "Fcn" + SrcPort 1 + Points [-360, 0; 0, -250] + DstBlock "Simple Induction Generator" + DstPort 1 + } + Line { + SrcBlock "High-Speed Shaft Brake" + SrcPort 1 + DstBlock "FAST Nonlinear Wind Turbine" + DstPort 4 + } + Annotation { + SID "44" + Name "Select LSS speed at entrance to gearbox (rpm)" + Position [451, 383] + } + } +} diff --git a/OpenFAST/glue-codes/simulink/src/FAST_SFunc.c b/OpenFAST/glue-codes/simulink/src/FAST_SFunc.c new file mode 100644 index 000000000..5d0cb01a0 --- /dev/null +++ b/OpenFAST/glue-codes/simulink/src/FAST_SFunc.c @@ -0,0 +1,473 @@ +/* + * TEMPLATE File: sfuntmpl_gate_fortran.c + * TEMPLATE Copyright 1990-2013 The MathWorks, Inc. + * + * Modified by B. Jonkman, National Renewable Energy Laboratory + * for use with FAST v8 + * 20-Jan-2015 + */ + + +/* + * You must specify the S_FUNCTION_NAME as the name of your S-function + * (i.e. replace sfungate with the name of your S-function, which has + * to match the name of the final mex file, e.g., if the S_FUNCTION_NAME + * is my_sfuntmpl_gate_fortran, the mex filename will have to be + * my_sfuntmpl_gate_fortran.mexXXX where XXX is the 3 letter + * mex extension code for your platform). + */ + +#define S_FUNCTION_LEVEL 2 + +#ifndef S_FUNCTION_NAME +#define S_FUNCTION_NAME FAST_SFunc +#endif +/* + * Need to include simstruc.h for the definition of the SimStruct and + * its associated macro definitions. + */ +#include "simstruc.h" +#include "mex.h" // for mexPutVariable +#include "matrix.h" // for mxCreateDoubleScalar +#include "FAST_Library.h" +#include <math.h> +#define min(a,b) fmin(a,b) + + +#define PARAM_FILENAME 0 +#define PARAM_TMAX 1 +#define PARAM_ADDINPUTS 2 +#define NUM_PARAM 3 + +// two DWork arrays: +#define WORKARY_OUTPUT 0 +#define WORKARY_INPUT 1 + + +static double dt = 0; +static double TMax = 0; +static int NumInputs = NumFixedInputs; +static int NumAddInputs = 0; // number of additional inputs +static int NumOutputs = 1; +static int ErrStat = 0; +static char ErrMsg[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 +static int ErrStat2 = 0; +static char ErrMsg2[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 +static char InputFileName[INTERFACE_STRING_LENGTH]; // make sure this is the same size as IntfStrLen in FAST_Library.f90 +static int n_t_global = -2; // counter to determine which fixed-step simulation time we are at currently (start at -2 for initialization) +static int AbortErrLev = ErrID_Fatal; // abort error level; compare with NWTC Library + +// function definitions +static int checkError(SimStruct *S); +static void mdlTerminate(SimStruct *S); // defined here so I can call it from checkError +static void getInputs(SimStruct *S, double *InputAry); +static void setOutputs(SimStruct *S, double *OutputAry); +// Hard coding single Turbine +static int iTurb = 0; //zero based +static int nTurbines = 1; + +/* Error handling +* -------------- +* +* You should use the following technique to report errors encountered within +* an S-function: +* +* ssSetErrorStatus(S,"Error encountered due to ..."); +* return; +* +* Note that the 2nd argument to ssSetErrorStatus must be persistent memory. +* It cannot be a local variable. +*/ +static int +checkError(SimStruct *S){ + + if (ErrStat >= AbortErrLev){ + ssPrintf("\n"); + ssSetErrorStatus(S, ErrMsg); + mdlTerminate(S); // terminate on error (in case Simulink doesn't do so itself) + return 1; + } + else if (ErrStat >= ErrID_Warn){ + ssPrintf("\n"); + ssWarning(S, ErrMsg); + } + else if (ErrStat != ErrID_None){ + ssPrintf("\n%s\n", ErrMsg); + } + return 0; + +} + +static void +getInputs(SimStruct *S, double *InputAry){ + + int k; + InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S, 0); + + for (k = 0; k < ssGetDWorkWidth(S, WORKARY_INPUT); k++) { + InputAry[k] = (double)(*uPtrs[k]); + } + +} + +static void +setOutputs(SimStruct *S, double *OutputAry){ + + int k; + double *y = ssGetOutputPortRealSignal(S, 0); + + for (k = 0; k < ssGetOutputPortWidth(S, WORKARY_OUTPUT); k++) { + y[k] = OutputAry[k]; + } + +} + + + +/*====================* + * S-function methods * + *====================*/ + +/* Function: mdlInitializeSizes =============================================== + * Abstract: + * The sizes information is used by Simulink to determine the S-function + * block's characteristics (number of inputs, outputs, states, etc.). + */ +static void mdlInitializeSizes(SimStruct *S) +{ + + int i = 0; + int j = 0; + int k = 0; + static char ChannelNames[CHANNEL_LENGTH * MAXIMUM_OUTPUTS + 1]; + static double InitInputAry[MAXInitINPUTS]; + //static char OutList[MAXIMUM_OUTPUTS][CHANNEL_LENGTH + 1]; + static char OutList[CHANNEL_LENGTH + 1]; + double *AdditionalInitInputs; + mxArray *pm, *chrAry; + mwSize m, n; + mwIndex indx; + + if (n_t_global == -2) { + + /* Expected S-Function Input Parameter(s) */ + ssSetNumSFcnParams(S, NUM_PARAM); /* Number of expected parameters */ + if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { + /* Return if number of expected != number of actual parameters */ + return; + } + + // The parameters should not be changed during the course of a simulation + ssSetSFcnParamTunable(S, PARAM_FILENAME, SS_PRM_NOT_TUNABLE); + mxGetString(ssGetSFcnParam(S, PARAM_FILENAME), InputFileName, INTERFACE_STRING_LENGTH); + + ssSetSFcnParamTunable(S, PARAM_TMAX, SS_PRM_NOT_TUNABLE); + TMax = mxGetScalar(ssGetSFcnParam(S, PARAM_TMAX)); + + ssSetSFcnParamTunable(S, PARAM_ADDINPUTS, SS_PRM_NOT_TUNABLE); + NumAddInputs = (int)(mxGetScalar(ssGetSFcnParam(S, PARAM_ADDINPUTS)) + 0.5); // add 0.5 for rounding from double + + if (NumAddInputs < 0){ + ErrStat = ErrID_Fatal; + strcpy(ErrMsg, "Parameter specifying number of additional inputs to the FAST SFunc must not be negative.\n"); + checkError(S); + return; + } + NumInputs = NumFixedInputs + NumAddInputs; + + // now see if there are other inputs that need to be processed... + if (NumAddInputs > 0){ + + k = (int)mxGetNumberOfElements(ssGetSFcnParam(S, PARAM_ADDINPUTS)); + k = min( k , MAXInitINPUTS ); + + AdditionalInitInputs = (double *)mxGetData(ssGetSFcnParam(S, PARAM_ADDINPUTS)); + for (i = 0; i < k; i++){ + InitInputAry[i] = AdditionalInitInputs[i + 1]; + } + } + else{ + InitInputAry[0] = SensorType_None; // tell it not to use lidar (shouldn't be necessary, but we'll cover our bases) + } + + // set this before possibility of error in Fortran library: + + ssSetOptions(S, + SS_OPTION_CALL_TERMINATE_ON_EXIT); + + + /* --------------------------------------------- */ + // strcpy(InputFileName, "../../CertTest/Test01.fst"); + FAST_AllocateTurbines(&nTurbines, &ErrStat, ErrMsg); + if (checkError(S)) return; + + FAST_Sizes(&iTurb, &TMax, InitInputAry, InputFileName, &AbortErrLev, &NumOutputs, &dt, &ErrStat, ErrMsg, ChannelNames); + n_t_global = -1; + if (checkError(S)) return; + + + // set DT in the Matlab workspace (necessary for Simulink block solver options) + pm = mxCreateDoubleScalar(dt); + ErrStat = mexPutVariable("base", "DT", pm); + mxDestroyArray(pm); + if (ErrStat != 0){ + ErrStat = ErrID_Fatal; + strcpy(ErrMsg, "Error copying string array to 'DT' variable in the base Matlab workspace."); + checkError(S); + return; + } + + + // put the names of the output channels in a cell-array variable called "OutList" in the base matlab workspace + m = NumOutputs; + n = 1; + pm = mxCreateCellMatrix(m, n); + for (i = 0; i < NumOutputs; i++){ + j = CHANNEL_LENGTH - 1; + while (ChannelNames[i*CHANNEL_LENGTH + j] == ' '){ + j--; + } + strncpy(&OutList[0], &ChannelNames[i*CHANNEL_LENGTH], j+1); + OutList[j + 1] = '\0'; + + chrAry = mxCreateString(OutList); + indx = i; + mxSetCell(pm, indx, chrAry); + //mxDestroyArray(chrAry); + } + ErrStat = mexPutVariable("base", "OutList", pm); + mxDestroyArray(pm); + + if (ErrStat != 0){ + ErrStat = ErrID_Fatal; + strcpy(ErrMsg, "Error copying string array to 'OutList' variable in the base Matlab workspace."); + checkError(S); + return; + } + // --------------------------------------------- + + + ssSetNumContStates(S, 0); /* how many continuous states? */ + ssSetNumDiscStates(S, 0); /* how many discrete states?*/ + + /* sets input port characteristics */ + if (!ssSetNumInputPorts(S, 1)) return; + ssSetInputPortWidth(S, 0, NumInputs); // width of first input port + + /* + * Set direct feedthrough flag (1=yes, 0=no). + * A port has direct feedthrough if the input is used in either + * the mdlOutputs or mdlGetTimeOfNextVarHit functions. + */ + ssSetInputPortDirectFeedThrough(S, 0, 0); // no direct feedthrough because we're just putting everything in one update routine (acting like a discrete system) + + if (!ssSetNumOutputPorts(S, 1)) return; + ssSetOutputPortWidth(S, 0, NumOutputs); + + ssSetNumSampleTimes(S, 1); // -> setting this > 0 calls mdlInitializeSampleTimes() + + /* + * If your Fortran code uses REAL for the state, input, and/or output + * datatypes, use these DWorks as work areas to downcast continuous + * states from double to REAL before calling your code. You could + * also put the work vectors in hard-coded local (stack) variables. + * + * For fixed step code, keep a copy of the variables to be output + * in a DWork vector so the mdlOutputs() function can provide output + * data when needed. You can use as many DWork vectors as you like + * for both input and output (or hard-code local variables). + */ + if(!ssSetNumDWork( S, 2)) return; + + ssSetDWorkWidth( S, WORKARY_OUTPUT, ssGetOutputPortWidth(S, 0)); + ssSetDWorkDataType(S, WORKARY_OUTPUT, SS_DOUBLE); /* use SS_DOUBLE if needed */ + + ssSetDWorkWidth( S, WORKARY_INPUT, ssGetInputPortWidth(S, 0)); + ssSetDWorkDataType(S, WORKARY_INPUT, SS_DOUBLE); + + ssSetNumNonsampledZCs(S, 0); + + /* Specify the sim state compliance to be same as a built-in block */ + /* see sfun_simstate.c for example of other possible settings */ + ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE); + + // ssSetOptions(S, 0); // bjj: what does this do? (not sure what 0 means: no options?) set option to call Terminate earlier... + + } +} + +/* Function: mdlInitializeSampleTimes ========================================= + * Abstract: + * This function is used to specify the sample time(s) for your + * S-function. You must register the same number of sample times as + * specified in ssSetNumSampleTimes. + */ +static void mdlInitializeSampleTimes(SimStruct *S) +{ + + /* + * If the Fortran code implicitly steps time + * at a fixed rate and you don't want to change + * the code, you need to use a discrete (fixed + * step) sample time, 1 second is chosen below. + */ + + ssSetSampleTime(S, 0, dt); /* Choose the sample time here if discrete */ + ssSetOffsetTime(S, 0, 0.0); + + ssSetModelReferenceSampleTimeDefaultInheritance(S); +} + +#undef MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */ + +#define MDL_START /* Change to #undef to remove function */ +#if defined(MDL_START) + /* Function: mdlStart ======================================================= + * Abstract: + * This function is called once at start of model execution. If you + * have states that should be initialized once, this is the place + * to do it. + */ + static void mdlStart(SimStruct *S) + { + + /* bjj: this is really the initial output; I'd really like to have the inputs from Simulink here.... maybe if we put it in mdlOutputs? + but then do we need to say we have direct feed-through? + */ + double *InputAry = (double *)ssGetDWork(S, WORKARY_INPUT); //malloc(NumInputs*sizeof(double)); + double *OutputAry = (double *)ssGetDWork(S, WORKARY_OUTPUT); + + //n_t_global is -1 here; maybe use this fact in mdlOutputs + if (n_t_global == -1){ // first time to compute outputs: + +// getInputs(S, InputAry); + + FAST_Start(&iTurb, &NumInputs, &NumOutputs, InputAry, OutputAry, &ErrStat, ErrMsg); + n_t_global = 0; + if (checkError(S)) return; + + } + } +#endif /* MDL_START */ + +/* Function: mdlOutputs ======================================================= + * Abstract: + * In this function, you compute the outputs of your S-function + * block. The default datatype for signals in Simulink is double, + * but you can use other intrinsic C datatypes or even custom + * datatypes if you wish. See Simulink document "Writing S-functions" + * for details on datatype topics. + */ +static void mdlOutputs(SimStruct *S, int_T tid) +{ + + /* + * For Fixed Step Code + * ------------------- + * If the Fortran code implements discrete states (implicitly or + * registered with Simulink, it doesn't matter), call the code + * from mdlUpdates() and save the output values in a DWork vector. + * The variable step solver may call mdlOutputs() several + * times in between calls to mdlUpdate, and you must extract the + * values from the DWork vector and copy them to the block output + * variables. + * + * Be sure that the ssSetDWorkDataType(S,0) declaration in + * mdlInitializeSizes() uses SS_DOUBLE for the datatype when + * this code is active. + */ + + double *InputAry = (double *)ssGetDWork(S, WORKARY_INPUT); + double *OutputAry = (double *)ssGetDWork(S, WORKARY_OUTPUT); + + if (n_t_global == -1){ // first time to compute outputs: + + getInputs(S, InputAry); + + FAST_Start(&iTurb, &NumInputs, &NumOutputs, InputAry, OutputAry, &ErrStat, ErrMsg); + n_t_global = 0; + if (checkError(S)) return; + + } + + setOutputs(S, OutputAry); + +} + + +#define MDL_UPDATE /* Change to #undef to remove function */ +#if defined(MDL_UPDATE) +/* Function: mdlUpdate ====================================================== + * Abstract: + * This function is called once for every major integration time step. + * Discrete states are typically updated here, but this function is useful + * for performing any tasks that should only take place once per + * integration step. + */ +static void mdlUpdate(SimStruct *S, int_T tid) +{ + + /* + * For Fixed Step Code Only + * ------------------------ + * If your Fortran code runs at a fixed time step that advances + * each time you call it, it is best to call it here instead of + * in mdlOutputs(). The states in the Fortran code need not be + * continuous if you call your code from here. + */ + double *InputAry = (double *)ssGetDWork(S, WORKARY_INPUT); + double *OutputAry = (double *)ssGetDWork(S, WORKARY_OUTPUT); + + //time_T t = ssGetSampleTime(S, 0); + + getInputs(S, InputAry); + + /* ==== Call the Fortran routine (args are pass-by-reference) */ + + FAST_Update(&iTurb, &NumInputs, &NumOutputs, InputAry, OutputAry, &ErrStat, ErrMsg); + n_t_global = n_t_global + 1; + + if (checkError(S)) return; + + setOutputs(S, OutputAry); + +} +#endif /* MDL_UPDATE */ + +#undef MDL_DERIVATIVES /* Change to #undef to remove function */ + + +/* Function: mdlTerminate ===================================================== + * Abstract: + * In this function, you should perform any actions that are necessary + * at the termination of a simulation. For example, if memory was + * allocated in mdlStart, this is the place to free it. + */ +static void mdlTerminate(SimStruct *S) +{ + if (n_t_global > -2){ // just in case we've never initialized, check this time step + bool tr = 1; // Yes, stoptheprogram + FAST_End(&iTurb, &tr); + n_t_global = -2; + } + + FAST_DeallocateTurbines(&ErrStat2, ErrMsg2); + if (ErrStat2 != ErrID_None){ + ssPrintf("\n%s\n", ErrMsg2); + } + +} + + + + +/*=============================* + * Required S-function trailer * + *=============================*/ + +#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ +#include "simulink.c" /* MEX-file interface mechanism */ +#else +#include "cg_sfun.h" /* Code generation registration function */ +#endif + diff --git a/OpenFAST/glue-codes/simulink/src/create_FAST_SFunc.m b/OpenFAST/glue-codes/simulink/src/create_FAST_SFunc.m new file mode 100644 index 000000000..1892c1846 --- /dev/null +++ b/OpenFAST/glue-codes/simulink/src/create_FAST_SFunc.m @@ -0,0 +1,70 @@ +%% INSTRUCTIONS +% Before running this script, you must have compiled OpenFAST for Simulink to create a DLL (i.e., a shared library like .so, .dylib, .lib, etc.). +% - If cmake was used, make sure the install directory is specified properly in the `installDir` variable below, +% and if using Windows, set `built_with_visualStudio` to false. +% - If the Visual Studio Solution file contained in the vs-build directory was used to create the DLL on Windows, +% make sure `built_with_visualStudio` is set to true. +% - The name of the library that was generated must match the `libname` variable below +% and should be located in the directory specified by `libDir`. +% - The `includeDir` variable must specify the directory that contains the following header files: +% "FAST_Library.h", "OpenFOAM_Types.h", and "SuperController_Types.h" +% - The `outDir` variable indicates where the resulting mex file will reside. +% +% Run `mex -setup` in Matlab to configure a C compiler if you have not already done so. + + +mexname = 'FAST_SFunc'; % base name of the resulting mex file + +built_with_visualStudio = true; %if the libraries were built with cmake, set to false + + +if (ispc && built_with_visualStudio) +%% defaults for visual studio builds: + + libDir = '../../../build/bin'; + includeDir = '../../../modules/openfast-library/src'; % needed for visual studio builds to find "FAST_Library.h" + outDir = libDir; + + switch computer('arch') + case 'win64' + % this is set up for files generated using the x64 configuration of vs-build + libName = 'OpenFAST-Simulink_x64'; + + case 'win32' + % this is set up for files generated using the x86 + % configuration of vs-build (win32 will work only on older versions of Matlab) + libName = 'OpenFAST-Simulink_Win32'; + end + +else +%% defaults for cmake builds: + + if ( ispc ) % Windows PC + installDir = '../../../install'; + outDir = fullfile(installDir, 'lib'); + % If there are shared libraries does it work for outDir to be the local directory? + else + installDir = '/usr/local'; + outDir = '.'; + end + + libDir = fullfile(installDir, 'lib'); + includeDir = fullfile(installDir, 'include'); + libName = 'openfastlib'; +end + +%% BUILD COMMAND +fprintf( '\n----------------------------\n' ); +fprintf( 'Creating %s\n\n', [outDir filesep mexname '.' mexext] ); + +mex('-largeArrayDims', ... + ... % '-v', ... %add this line for "verbose" output (for debugging) + ['-L' libDir], ... + ['-l' libName], ... + ['-I' includeDir], ... + '-I../../../modules/supercontroller/src', ... % needed for visual studio builds to find "SuperController_Types.h" + '-I../../../modules/openfoam/src', ... % needed for visual studio builds to find "OpenFOAM_Types.h" + '-outdir', outDir, ... + ['COMPFLAGS=$COMPFLAGS -MT -DS_FUNCTION_NAME=' mexname], ... + '-output', mexname, ... + 'FAST_SFunc.c'); diff --git a/OpenFAST/modules/aerodyn/CMakeLists.txt b/OpenFAST/modules/aerodyn/CMakeLists.txt new file mode 100644 index 000000000..5e426d99a --- /dev/null +++ b/OpenFAST/modules/aerodyn/CMakeLists.txt @@ -0,0 +1,117 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/AeroAcoustics_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/AeroAcoustics_Types.f90) + generate_f90_types(src/AeroDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/AeroDyn_Types.f90) + generate_f90_types(src/AirfoilInfo_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/AirfoilInfo_Types.f90) + generate_f90_types(src/BEMT_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/BEMT_Types.f90) + generate_f90_types(src/DBEMT_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/DBEMT_Types.f90) + generate_f90_types(src/UnsteadyAero_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/UnsteadyAero_Types.f90) + generate_f90_types(src/AeroDyn_Driver_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/AeroDyn_Driver_Types.f90 -noextrap) + generate_f90_types(src/FVW_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/FVW_Types.f90) +endif() + + +# AeroAcoustics - Main +set(AEROACOUSTIC_SOURCES + src/AeroAcoustics_TNO.f90 + src/AeroAcoustics.f90 + src/AeroAcoustics_IO.f90 + src/AeroAcoustics_Types.f90 +) + +# AeroDyn lib +set(AD_LIBS_SOURCES + src/AeroDyn.f90 + src/AeroDyn_IO.f90 + src/AeroDyn_AllBldNdOuts_IO.f90 + src/BEMT.f90 + src/DBEMT.f90 + src/BEMTUncoupled.f90 + src/mod_root1dim.f90 + src/AeroDyn_Types.f90 + src/BEMT_Types.f90 + src/DBEMT_Types.f90 +) + +# UnsteadyAero lib +set(UA_LIBS_SOURCES + src/UnsteadyAero.f90 + src/UnsteadyAero_Types.f90 +) + +# AirFoil Info lib +set(AFINFO_LIBS_SOURCES + src/AirfoilInfo.f90 + src/AirfoilInfo_Types.f90 +) + +# FVW lib +set(FVW_LIBS_SOURCES + src/FVW.f90 + src/FVW_IO.f90 + src/FVW_VortexTools.f90 + src/FVW_Wings.f90 + src/FVW_Subs.f90 + src/FVW_BiotSavart.f90 + src/FVW_Tests.f90 + src/FVW_Types.f90 + src/FVW_VTK.f90 +) + +# UnsteadyAero lib +add_library(uaaerolib ${UA_LIBS_SOURCES}) +target_link_libraries(uaaerolib afinfolib nwtclibs) + +# AirfoilInfo lib +add_library(afinfolib ${AFINFO_LIBS_SOURCES}) +target_link_libraries(afinfolib nwtclibs) + +# this lib is only for the ctest +add_library(fvwlib ${FVW_LIBS_SOURCES}) +target_link_libraries(fvwlib uaaerolib afinfolib nwtclibs) + +# Aero acoustics +add_library(aeroacoustics ${AEROACOUSTIC_SOURCES}) +target_link_libraries(aeroacoustics afinfolib nwtclibs) + +add_library(aerodynlib ${AD_LIBS_SOURCES}) +target_link_libraries(aerodynlib fvwlib uaaerolib afinfolib nwtclibs aeroacoustics) + +# AeroDyn driver +set(AD_DRIVER_SOURCES + src/AeroDyn_Driver.f90 + src/AeroDyn_Driver_Subs.f90 + src/AeroDyn_Driver_Types.f90 +) + +add_executable(aerodyn_driver ${AD_DRIVER_SOURCES}) +target_link_libraries(aerodyn_driver aerodynlib fvwlib uaaerolib afinfolib nwtclibs versioninfolib aeroacoustics ${CMAKE_DL_LIBS}) + +# UnsteadyAero driver +set(UA_DRIVER_SOURCES + src/UnsteadyAero_Driver.f90 + src/UA_Dvr_Subs.f90 +) +add_executable(unsteadyaero_driver ${UA_DRIVER_SOURCES}) +target_link_libraries(unsteadyaero_driver aerodynlib fvwlib uaaerolib afinfolib nwtclibs versioninfolib ${CMAKE_DL_LIBS}) + +install(TARGETS unsteadyaero_driver aerodyn_driver aerodynlib fvwlib uaaerolib afinfolib aeroacoustics + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/aerodyn/README.md b/OpenFAST/modules/aerodyn/README.md new file mode 100644 index 000000000..96c14d904 --- /dev/null +++ b/OpenFAST/modules/aerodyn/README.md @@ -0,0 +1,14 @@ +# AeroDyn Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/AeroDyn/). + +## Overview +AeroDyn is a time-domain wind and MHK turbine aerodynamics module that can be +coupled into the OpenFAST multi-physics engineering tool to enable aero-elastic +simulation of horizontal-axis wind turbines. AeroDyn can also be driven as a +standalone code to compute wind turbine aerodynamic response uncoupled from +OpenFAST. + +## Manual +AeroDyn documentation is available on the OpenFAST +[ReadTheDocs](https://openfast.readthedocs.io/en/master/source/user/aerodyn/index.html) site. diff --git a/OpenFAST/modules/aerodyn/src/AeroAcoustics.f90 b/OpenFAST/modules/aerodyn/src/AeroAcoustics.f90 new file mode 100644 index 000000000..429b8edd9 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroAcoustics.f90 @@ -0,0 +1,2468 @@ +!********************************************************************************************************************************** +! File last committed: 2020-02-12 +!********************************************************************************************************************************** +module AeroAcoustics + + use NWTC_Library + use AeroAcoustics_Types + use AeroAcoustics_IO + use NWTC_LAPACK + USE NWTC_FFTPACK + implicit none + + private + ! ..... Public Subroutines ................................................................................................... + public :: AA_Init ! Initialization routine + public :: AA_End ! Ending routine (includes clean up) + public :: AA_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + public :: AA_CalcOutput ! Routine for computing outputs + + 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. +!! The initial states and initial guess for the input are defined. +subroutine AA_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + type(AA_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(AA_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(AA_ParameterType), intent( out) :: p !< Parameters + type(AA_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(AA_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(AA_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(AA_OtherStateType), intent( out) :: OtherState !< Initial other states + type(AA_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(AA_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + real(DbKi), intent(inout) :: interval !< Coupling interval in seconds: the rate that + !! (1) AA_UpdateStates() is called in loose coupling & + !! (2) AA_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(AA_InitOutputType), intent( out) :: InitOut !< Output for initialization routine + 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 ! loop counter + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + type(AA_InputFile) :: InputFileData ! Data stored in the module's input file + integer(IntKi) :: UnEcho ! Unit number for the echo file + character(*), parameter :: RoutineName = 'AA_Init' + + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + UnEcho = -1 + ! Initialize the NWTC Subroutine Library + call NWTC_Init( EchoLibVer=.FALSE. ) + ! Display the module information + call DispNVD( AA_Ver ) + + ! To get rid of a compiler warning. + x%DummyContState = 0.0_SiKi + z%DummyConstrState = 0.0_SiKi + OtherState%DummyOtherState = 0.0_SiKi + + !bjj: note that we haven't validated p%NumBlades before using it below! + p%NumBlades = InitInp%NumBlades ! need this before reading the AD input file so that we know how many blade files to read + p%RootName = TRIM(InitInp%RootName)//'.NN' + + ! Read the primary AeroAcoustics input file in AeroAcoustics_IO + call ReadInputFiles( InitInp%InputFile, InitInp%AFInfo%BL_file, InputFileData, interval, p%RootName, p%NumBlades, UnEcho, ErrStat2, ErrMsg2 ) + if (Failed()) return + + ! Validate the inputs + call ValidateInputData(InputFileData, p%NumBlades, ErrStat2, ErrMsg2); if (Failed()) return + + ! Validate Initialization Input data ( not found in the AeroAcoustics input file ) + if (InitInp%AirDens <= 0.0) call SetErrStat ( ErrID_Fatal, 'The air density (AirDens) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InitInp%KinVisc <= 0.0) call SetErrStat ( ErrID_Fatal, 'The kinesmatic viscosity (KinVisc) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InitInp%SpdSound <= 0.0) call SetErrStat ( ErrID_Fatal, 'The speed of sound (SpdSound) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! Define parameters + call SetParameters( InitInp, InputFileData, p, ErrStat2, ErrMsg2 ); if(Failed()) return + ! Define and initialize inputs + call Init_u( u, p, InputFileData, InitInp, errStat2, errMsg2 ); if(Failed()) return + + ! Define outputs here + call Init_y(y, u, p, errStat2, errMsg2); if(Failed()) return + + ! Initialize states and misc vars + call Init_MiscVars(m, p, u, y, errStat2, errMsg2); if(Failed()) return + call Init_States(xd, p, errStat2, errMsg2); if(Failed()) return + + ! Define initialization output here + call AA_SetInitOut(p, InputFileData, InitOut, errStat2, errMsg2); if(Failed()) return + call AA_InitializeOutputFile(p, InputFileData,InitOut,errStat2, errMsg2); if(Failed()) return + call Cleanup() + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup() + end function Failed + + subroutine Cleanup() + CALL AA_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + end subroutine Cleanup +end subroutine AA_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets AeroAcoustics parameters for use during the simulation; these variables are not changed after AA_Init. +subroutine SetParameters( InitInp, InputFileData, p, ErrStat, ErrMsg ) + TYPE(AA_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine, out is needed because of copy below + TYPE(AA_InputFile), INTENT(IN ) :: InputFileData !< Data stored in the module's input file -- intent(out) only for move_alloc statements + TYPE(AA_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 + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat / = ErrID_None + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + INTEGER(IntKi) :: simcou,coun ! simple loop counter + INTEGER(IntKi) :: I,J,whichairfoil,K + character(*), parameter :: RoutineName = 'SetParameters' + LOGICAL :: tr,tri,exist + REAL(ReKi) :: val1,val2,f2,f4,lefttip,rightip,jumpreg + ! Initialize variables for this routine + ErrStat = ErrID_None + ErrMsg = "" + !!Assign input fiel data to parameters + p%DT = InputFileData%DT_AA ! seconds + p%AA_Bl_Prcntge = InputFileData%AA_Bl_Prcntge ! % + p%fsample = 1/p%DT ! Hz + p%total_sample = 2**( ceiling(log(1*p%fsample)/log(2.0d0)))! 1 stands for the 1 seconds. Every 1 second Vrel spectra will be calculated for the dissipation calculation (change if more needed & recompile ) + p%total_sampleTI = 5/p%DT ! 10 seconds for TI sampling + p%AAStart = InputFileData%AAStart + p%IBLUNT = InputFileData%IBLUNT + p%ILAM = InputFileData%ILAM + p%ITIP = InputFileData%ITIP + p%ITRIP = InputFileData%ITRIP + p%ITURB = InputFileData%ITURB + p%IInflow = InputFileData%IInflow + p%X_BLMethod = InputFileData%X_BLMethod + p%TICalcMeth = InputFileData%TICalcMeth + p%AweightFlag = InputFileData%AweightFlag + p%ROUND = InputFileData%ROUND + p%alprat = InputFileData%ALPRAT + p%NrOutFile = InputFileData%NrOutFile + p%delim = Tab + p%outFmt = "ES15.6E3" + p%NumBlNds = InitInp%NumBlNds + p%AirDens = InitInp%AirDens + p%KinVisc = InitInp%KinVisc + p%SpdSound = InitInp%SpdSound + p%HubHeight = InitInp%HubHeight + p%z0_AA = InputFileData%z0_AA + p%dy_turb_in = InputFileData%dy_turb_in + p%dz_turb_in = InputFileData%dz_turb_in + p%NrObsLoc = InputFileData%NrObsLoc + p%FTitle = InputFileData%FTitle + + call AllocAry(p%TI_Grid_In,size(InputFileData%TI_Grid_In,1), size(InputFileData%TI_Grid_In,2), 'p%TI_Grid_In', errStat2, errMsg2); if(Failed()) return + p%TI_Grid_In=InputFileData%TI_Grid_In + + ! Copy AFInfo into AA module + ! TODO Allocate AFInfo and AFindx variables (DONE AND DONE) + ALLOCATE(p%AFInfo( size(InitInp%AFInfo) ), STAT=ErrStat2) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating memory for the InitInp%AFInfo array.', ErrStat2, ErrMsg2, RoutineName) + RETURN + ENDIF + + do i=1,size(InitInp%AFInfo) + call AFI_CopyParam(InitInp%AFInfo(i), p%AFInfo(i), MESH_NEWCOPY, errStat2, errMsg2); if(Failed()) return + end do + + ! Check 1 + tri=.true. + IF( (p%ITURB.eq.2) .or. (p%IInflow.gt.1) )then + ! if tno is on or one of the guidati models is on, check if we have airfoil coordinates + DO k=1,size(p%AFInfo) ! if any of the airfoil coordinates are missing change calculation method + IF( (size(p%AFInfo(k)%X_Coord) .lt. 5) .or. (size(p%AFInfo(k)%Y_Coord).lt.5) )then + IF (tri) then ! Print the message for once only + print*, 'Airfoil coordinates are missing: If Full or Simplified Guidati or Bl Calculation is on coordinates are needed ' + print*, 'Calculation methods enforced as BPM for TBLTE and only Amiet for inflow ' + p%ITURB = 1 + p%IInflow = 1 + tri=.false. + ENDIF + ENDIF + ENDDO + ENDIF + + ! Check 2 + ! if passed the first check and if tno, turn on boundary layer calculation + IF( (p%ITURB.eq.2)) then + p%X_BLMethod=2 + ENDIF + + ! Check 3 + ! if boundary layer is tripped then laminar b.l. vortex shedding mechanism is turned off + IF( p%ITRIP.gt.0 )then + p%ILAM=0 + ENDIF + + ! set 1/3 octave band frequency as parameter and A weighting. + CALL AllocAry( p%FreqList, 34, 'FreqList', ErrStat2, ErrMsg2); if(Failed()) return + p%FreqList = (/10.,12.5,16.,20.,25.,31.5,40.,50.,63.,80., & + 100.,125.,160.,200.,250.,315.,400.,500.,630.,800., & + 1000.,1250.,1600.,2000.,2500.,3150.,4000.,5000.,6300.,8000., & + 10000.,12500.,16000.,20000./) ! TODO this should be fortran parameter + + + CALL AllocAry(p%Aweight, size(p%Freqlist), 'Aweight', ErrStat2, ErrMsg2); if(Failed()) return + Do I=1,size(p%Freqlist) + f2 = p%Freqlist(I)**2; + f4 = p%Freqlist(I)**4; + p%Aweight(I)= 10 * log(1.562339 * f4 / ((f2 + 107.65265**2) & + * (f2 + 737.86223 **2))) / log(10.0_Reki) & + + 10 * log(2.242881E+16 * f4 / ((f2 + 20.598997**2)**2 & + * (f2 + 12194.22**2)**2)) / log(10.0_Reki) + enddo + + ! Observer Locations + call AllocAry(p%ObsX, p%NrObsLoc, 'p%ObsX', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(p%ObsY, p%NrObsLoc, 'p%ObsY', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(p%ObsZ, p%NrObsLoc, 'p%ObsZ', ErrStat2, ErrMsg2); if(Failed()) return + p%ObsX = InputFileData%ObsX + p%ObsY = InputFileData%ObsY + p%ObsZ = InputFileData%ObsZ + ! + call AllocAry(p%BlAFID, p%NumBlNds, p%numBlades, 'p%BlAFID' , ErrStat2, ErrMsg2); if(Failed()) return + p%BlAFID=InitInp%BlAFID + + ! Blade Characteristics chord,span,trailing edge angle and thickness,airfoil ID for each segment + call AllocAry(p%TEThick ,p%NumBlNds,p%NumBlades,'p%TEThick' ,ErrStat2,ErrMsg2); if(Failed()) return + call AllocAry(p%TEAngle ,p%NumBlNds,p%NumBlades,'p%TEAngle' ,ErrStat2,ErrMsg2); if(Failed()) return + call AllocAry(p%StallStart,p%NumBlNds,p%NumBlades,'p%StallStart',ErrStat2,ErrMsg2); if(Failed()) return + p%StallStart(:,:) = 0.0_ReKi + + do i=1,p%NumBlades + p%TEThick(:,i) = InputFileData%BladeProps(i)%TEThick(:) ! + p%TEAngle(:,i) = InputFileData%BladeProps(i)%TEAngle(:) ! + do j=1,p%NumBlNds + whichairfoil = p%BlAFID(j,i) + if(p%AFInfo(whichairfoil)%NumTabs /=1 ) then + call SetErrStat(ErrID_Fatal, 'Number of airfoil tables within airfoil file different than 1, which is not supported.', ErrStat2, ErrMsg2, RoutineName ) + if(Failed()) return + endif + p%StallStart(j,i) = p%AFInfo(whichairfoil)%Table(1)%UA_BL%alpha1*180/PI ! approximate stall angle of attack [deg] (alpha1 in [rad]) + enddo + end do + + call AllocAry(p%BlSpn, p%NumBlNds, p%NumBlades, 'p%BlSpn' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(p%BlChord, p%NumBlNds, p%NumBlades, 'p%BlChord', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(p%AerCent, 2, p%NumBlNds, p%NumBlades, 'p%AerCent', ErrStat2, ErrMsg2); if(Failed()) return + p%BlSpn = InitInp%BlSpn + p%BlChord = InitInp%BlChord + + do j=p%NumBlNds,2,-1 + IF ( p%BlSpn(j,1) .lt. p%BlSpn(p%NumBlNds,1)*(100-p%AA_Bl_Prcntge)/100 )THEN ! assuming + p%startnode=j + exit ! exit the loop + endif + enddo + + IF (p%startnode.lt.2) THEN + p%startnode=2 + ENDIF + + !print*, 'AeroAcoustics Module is using the blade nodes starting from ' ,p%startnode,' Radius in meter ',p%BlSpn(p%startnode,1) + !AerodYnamic center extraction for each segment + do i=1,p%numBlades + do j=1,p%NumBlNds + whichairfoil = p%BlAFID(j,i) ! just a temporary variable for clear coding + ! airfoil coordinates read by AeroDyn. First value is the aerodynamic center + p%AerCent(1,J,I) = p%AFInfo(whichairfoil)%X_Coord(1) ! assigned here corresponding airfoil. + p%AerCent(2,J,I) = p%AFInfo(whichairfoil)%Y_Coord(1) ! assigned here corresponding airfoil. + enddo + enddo + + ! Dimensionalize Leading and trailing edge coordinates for later usage + call AllocAry( p%AFTeCo, 3, p%NumBlNds,p%numBlades, 'p%AFTeCo', errStat2, errMsg2 ); if(Failed())return + call AllocAry( p%AFLeCo, 3, p%NumBlNds,p%numBlades, 'p%AFLeCo', errStat2, errMsg2 ); if(Failed())return + p%AFTeCo=0.0_Reki + p%AFLeCo=0.0_Reki + + ! Normalized Leading edge coordinates (0,0,0) + ! Normalized Trailing edge coordinates (1,0,0) -- > changed to 0,1,0 + DO i=1,p%numBlades + DO j=1,p%NumBlNds + p%AFLeCo(1,j,i) = ( 0.0_Reki - p%AerCent(2,J,I) ) * p%BlChord(j,i) ! (y_LE - y_AC) *Chord + p%AFLeCo(2,j,i) = ( 0.0_Reki - p%AerCent(1,J,I) ) * p%BlChord(j,i) ! (x_LE - x_AC) *Chord + p%AFLeCo(3,j,i) = ( 0.0_Reki - 0.0_Reki ) * p%BlChord(j,i) ! this is always zero at the moment ( kept for 3d consistency ) + p%AFTeCo(1,j,i) = ( 0.0_Reki - p%AerCent(2,J,I) ) * p%BlChord(j,i) ! (y_TE - y_AC) *Chord + p%AFTeCo(2,j,i) = ( 1.0_Reki - p%AerCent(1,J,I) ) * p%BlChord(j,i) ! (x_TE - x_AC) *Chord + p%AFTeCo(3,j,i) = ( 0.0_Reki - 0.0_Reki ) * p%BlChord(j,i) ! this is always zero at the moment ( kept for 3d consistency ) + ENDDO + ENDDO + + if (p%X_BLMethod.eq.2) then + + ! Copying inputdata list of AOA and Reynolds to parameters + call AllocAry( p%AOAListBL, size(InputFileData%AOAListBL), 'p%AOAListBL', errStat2, errMsg2); if(Failed()) return + call AllocAry( p%ReListBL, size(InputFileData%ReListBL) , 'p%ReListBL' , errStat2, errMsg2); if(Failed()) return + p%AOAListBL=InputFileData%AOAListBL + p%ReListBL=InputFileData%ReListBL + ! Allocate the suction and pressure side boundary layer parameters for output - will be used as tabulated data + call AllocAry(p%dstarall1 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%dstarall1' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%dstarall2 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%dstarall2' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%d99all1 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%d99all1' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%d99all2 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%d99all2' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%Cfall1 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%Cfall1' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%Cfall2 ,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%Cfall2' , errStat2, errMsg2); if(Failed()) return + call AllocAry(p%EdgeVelRat1,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%EdgeVelRat1', errStat2, errMsg2); if(Failed()) return + call AllocAry(p%EdgeVelRat2,size(p%AOAListBL), size(p%ReListBL),size(p%AFInfo),'p%EdgeVelRat2', errStat2, errMsg2); if(Failed()) return + p%dstarall1 =0.0_ReKi + p%dstarall2 =0.0_ReKi + p%d99all1 =0.0_ReKi + p%d99all2 =0.0_ReKi + p%Cfall1 =0.0_ReKi + p%Cfall2 =0.0_ReKi + p%EdgeVelRat1 =0.0_ReKi + p%EdgeVelRat2 =0.0_ReKi + + + ! --- BL data are read from files and just copy what was read from the files + p%dstarall1 = InputFileData%Suct_DispThick + p%dstarall2 = InputFileData%Pres_DispThick + p%d99all1 = InputFileData%Suct_BLThick + p%d99all2 = InputFileData%Pres_BLThick + p%Cfall1 = InputFileData%Suct_Cf + p%Cfall2 = InputFileData%Pres_Cf + p%EdgeVelRat1 = InputFileData%Suct_EdgeVelRat + p%EdgeVelRat2 = InputFileData%Pres_EdgeVelRat + + if(Failed()) return + endif + + ! If simplified guidati is on, calculate the airfoil thickness from input airfoil coordinates + IF (p%IInflow .EQ. 2) THEN + ! Calculate the Thickness @ 1% chord and @ 10% chord (normalized thickness) + call AllocAry(p%AFThickGuida,2,size(p%AFInfo), 'p%AFThickGuida', errStat2, errMsg2); if(Failed()) return + p%AFThickGuida=0.0_Reki + + DO k=1,size(p%AFInfo) ! for each airfoil interpolation + tri=.true.;tr=.true.; + do i=2,size(p%AFInfo(k)%X_Coord) + if ( (p%AFInfo(k)%X_Coord(i)+p%AFInfo(k)%Y_Coord(i)) .eq. 0) then + !print*,i + goto 174 + endif + if ( p%AFInfo(k)%X_Coord(i) .eq. 0.1) then + val1=p%AFInfo(k)%Y_Coord(i) + elseif ( (p%AFInfo(k)%X_Coord(i) .lt. 0.1) .and. (tri) ) then + val1=( abs(p%AFInfo(k)%X_Coord(i-1)-0.1)*p%AFInfo(k)%Y_Coord(i) + & + abs(p%AFInfo(k)%X_Coord(i)-0.1)*p%AFInfo(k)%Y_Coord(i-1))/ & + (abs(p%AFInfo(k)%X_Coord(i-1)-0.1)+abs(p%AFInfo(k)%X_Coord(i)-0.1)) + + tri=.false. + elseif (p%AFInfo(k)%X_Coord(i) .eq. 0.01) then + val2=p%AFInfo(k)%Y_Coord(i) + elseif ( (p%AFInfo(k)%X_Coord(i) .lt. 0.01) .and. (tr) ) then + val2=( abs(p%AFInfo(k)%X_Coord(i-1)-0.01)*p%AFInfo(k)%Y_Coord(i) + & + abs(p%AFInfo(k)%X_Coord(i)-0.01)*p%AFInfo(k)%Y_Coord(i-1))/ & + (abs(p%AFInfo(k)%X_Coord(i-1)-0.01)+abs(p%AFInfo(k)%X_Coord(i)-0.01)) + tr=.false. + endif + enddo + + 174 tri=.true.;tr=.true.; + do j=i,size(p%AFInfo(k)%X_Coord) + if ( p%AFInfo(k)%X_Coord(j) .eq. 0.1) then + val1=abs(p%AFInfo(k)%Y_Coord(j)) + abs(val1) + elseif ( (p%AFInfo(k)%X_Coord(j) .gt. 0.1) .and. (tri) ) then + val1=abs(val1)+abs((abs(p%AFInfo(k)%X_Coord(j-1)-0.1)*p%AFInfo(k)%Y_Coord(j)+ & + abs(p%AFInfo(k)%X_Coord(j)-0.1)*p%AFInfo(k)%Y_Coord(j-1))/& + (abs(p%AFInfo(k)%X_Coord(j-1)-0.1)+abs(p%AFInfo(k)%X_Coord(j)-0.1))); + tri=.false. + elseif (p%AFInfo(k)%X_Coord(j) .eq. 0.01) then + val2=abs(p%AFInfo(k)%Y_Coord(j)) + abs(val2) + elseif ( (p%AFInfo(k)%X_Coord(j) .gt. 0.01) .and. (tr) ) then + val2=abs(val2)+abs((abs(p%AFInfo(k)%X_Coord(j-1)-0.01)*p%AFInfo(k)%Y_Coord(j)+ & + abs(p%AFInfo(k)%X_Coord(j)-0.01)*p%AFInfo(k)%Y_Coord(j-1))/& + (abs(p%AFInfo(k)%X_Coord(j-1)-0.01)+abs(p%AFInfo(k)%X_Coord(j)-0.01))); + tr=.false. + endif + enddo + + p%AFThickGuida(1,k)=val2 ! 1 % chord thickness + p%AFThickGuida(2,k)=val1 ! 10 % chord thickness + ENDDO + ENDIF ! If simplified guidati is on, calculate the airfoil thickness + + !! for turbulence intensity calculations on the fly every 5 meter the whole rotor area is divided vertically to store flow fields in each region + jumpreg=7 + p%toptip = CEILING(p%HubHeight+maxval(p%BlSpn(:,1)))+2 !Top Tip Height = Hub height plus radius + p%bottip = FLOOR(p%HubHeight-maxval(p%BlSpn(:,1)))-2 !Bottom Tip Height = Hub height minus radius + call AllocAry(p%rotorregionlimitsVert,ceiling(((p%toptip)-(p%bottip))/jumpreg), 'p%rotorregionlimitsVert', errStat2, errMsg2); if(Failed()) return + do i=0,size(p%rotorregionlimitsVert)-1 + p%rotorregionlimitsVert(i+1)=(p%bottip)+jumpreg*i + enddo + !! for turbulence intensity calculations on the fly every 5 meter the whole rotor area is divided horizontally to store flow fields in each region + jumpreg=7 + lefttip = 2*maxval(p%BlSpn(:,1))+5 ! + rightip = 0 ! + call AllocAry( p%rotorregionlimitsHorz,ceiling(((lefttip)-(rightip))/jumpreg), 'p%rotorregionlimitsHorz', errStat2, errMsg2); if(Failed()) return + do i=0,size(p%rotorregionlimitsHorz)-1 + p%rotorregionlimitsHorz(i+1)=rightip+jumpreg*i + enddo + jumpreg=60 ! 10 ! must be divisable to 360 + call AllocAry(p%rotorregionlimitsalph,INT((360/jumpreg)+1), 'p%rotorregionlimitsalph', errStat2, errMsg2); if(Failed()) return + do i=0,size(p%rotorregionlimitsalph)-1 + p%rotorregionlimitsalph(i+1)=jumpreg*i + enddo + jumpreg=5 + call AllocAry( p%rotorregionlimitsrad, (CEILING( maxval(p%BlSpn(:,1))/jumpreg )+2), 'p%rotorregionlimitsrad', errStat2, errMsg2); if(Failed()) return + do i=1,size(p%rotorregionlimitsrad)-1 + p%rotorregionlimitsrad(i+1)=jumpreg*i + enddo + p%rotorregionlimitsrad(1)=0.0_reki + p%rotorregionlimitsrad(size(p%rotorregionlimitsrad)-1)=p%rotorregionlimitsrad(size(p%rotorregionlimitsrad)-1)+3 + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes AeroAcoustics module input array variables for use during the simulation. +subroutine Init_u( u, p, InputFileData, InitInp, errStat, errMsg ) + type(AA_InputType), intent( out) :: u !< Input data + type(AA_ParameterType), intent(in ) :: p !< Parameters + type(AA_InputFile), intent(in ) :: InputFileData !< Data stored in the module's input file + type(AA_InitInputType), intent(in ) :: InitInp !< Input data for AD initialization routine + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_u' + + call AllocAry(u%AoANoise , p%NumBlNds, p%numBlades, 'u%AoANoise', errStat2 , errMsg2); if(Failed()) return + call AllocAry(u%Vrel , p%NumBlNds, p%numBlades, 'u%Vrel' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(u%AeroCent_G, 3 , p%NumBlNds , p%numBlades , 'u%AeroCent_G', errStat2 , errMsg2); if(Failed()) return + call AllocAry(u%Inflow , 3_IntKi , p%NumBlNds , p%numBlades , 'u%Inflow' , ErrStat2 , ErrMsg2); if(Failed()) return + call AllocAry(u%RotGtoL , 3 , 3 , p%NumBlNds , p%numBlades , 'u%RotGtoL' , errStat2 , errMsg2); if(Failed()) return + u%AoANoise = 0.0_Reki + u%Vrel = 0.0_Reki + u%RotGtoL = 0.0_Reki + u%AeroCent_G = 0.0_Reki + u%Inflow = 0.0_Reki +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine Init_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes AeroAcoustics output array variables for use during the simulation. +subroutine Init_y(y, u, p, errStat, errMsg) + type(AA_OutputType), intent( out) :: y !< Module outputs + type(AA_InputType), intent(inout) :: u !< Module inputs -- intent(out) because of mesh sibling copy + type(AA_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(intKi) :: k ! loop counter for blades + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_y' + integer(intKi) :: nNoiseMechanism ! loop counter for blades + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + nNoiseMechanism = 7! 7 noise mechanisms + p%numOuts = p%NrObsLoc + p%NumOutsForSep = p%NrObsLoc*size(p%FreqList)*nNoiseMechanism + p%NumOutsForPE = p%NrObsLoc*size(p%Freqlist) + p%NumOutsForNodes = p%NrObsLoc*p%NumBlNds*p%NumBlades + call AllocAry(y%WriteOutput , p%numOuts , 'y%WriteOutput' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%WriteOutputSep , p%NumOutsForSep , 'y%WriteOutputSep' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%WriteOutputForPE , p%numOutsForPE , 'y%WriteOutputForPE' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%DirectiviOutput , p%NrObsLoc , 'y%DirectiviOutput' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%WriteOutputNode , p%NumOutsForNodes , 'y%WriteOutputSepFreq' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%OASPL , p%NrObsLoc , p%NumBlNds , p%NumBlades , 'y%OASPL' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%SumSpecNoise , size(p%FreqList) , p%NrObsLoc , p%NumBlades , 'y%SumSpecNoise' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%SumSpecNoiseSep , 7 , p%NrObsLoc , size(p%FreqList) , 'y%SumSpecNoiseSep' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%OASPL_Mech , nNoiseMechanism , p%NrObsLoc , p%NumBlNds , p%NumBlades , 'y%OASPL_Mech' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%OutLECoords , 3 , size(p%FreqList) , p%NrObsLoc , p%NumBlades , 'y%OutLECoords' , errStat2 , errMsg2); if(Failed()) return + call AllocAry(y%PtotalFreq , p%NrObsLoc , size(p%FreqList) , 'y%PtotalFreq' , errStat2 , errMsg2); if(Failed()) return + + y%WriteOutput = 0.0_reki + y%WriteOutputSep = 0.0_reki + y%WriteOutputForPE = 0.0_reki + y%DirectiviOutput = 0.0_reki + y%WriteOutputNode = 0.0_reki + y%OASPL = 0.0_reki + y%OASPL_Mech = 0.0_reki + y%SumSpecNoise = 0.0_reki + y%SumSpecNoiseSep = 0.0_reki + y%OutLECoords = 0.0_reki + y%PtotalFreq = 0.0_reki + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine Init_y +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes (allocates) the misc variables for use during the simulation. +subroutine Init_MiscVars(m, p, u, y, errStat, errMsg) + type(AA_MiscVarType), intent(inout) :: m !< misc/optimization data (not defined in submodules) + type(AA_ParameterType), intent(in ) :: p !< Parameters + type(AA_InputType), intent(inout) :: u !< input for HubMotion mesh (create sibling mesh here) + type(AA_OutputType), intent(in ) :: y !< output (create mapping between output and otherstate mesh here) + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + integer(intKi) :: k + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_MiscVars' + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + call AllocAry(m%ChordAngleLE, p%NrObsLoc, p%NumBlNds, p%numBlades, 'ChordAngleLE', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%SpanAngleLE , p%NrObsLoc, p%NumBlNds, p%numBlades, 'SpanAngleLE' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%ChordAngleTE, p%NrObsLoc, p%NumBlNds, p%numBlades, 'ChordAngleTE', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%SpanAngleTE , p%NrObsLoc, p%NumBlNds, p%numBlades, 'SpanAngleTE' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%rTEtoObserve, p%NrObsLoc, p%NumBlNds, p%numBlades, 'rTEtoObserve', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%rLEtoObserve, p%NrObsLoc, p%NumBlNds, p%numBlades, 'rLEtoObserve', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%SPLLBL , size(p%FreqList), 'SPLLBL' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLP , size(p%FreqList), 'SPLP' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLS , size(p%FreqList), 'SPLS' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLALPH , size(p%FreqList), 'SPLALPH' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLTBL , size(p%FreqList), 'SPLTBL' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLBLUNT , size(p%FreqList), 'SPLBLUNT' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLTIP , size(p%FreqList), 'SPLTIP' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLTI , size(p%FreqList), 'SPLTI' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%SPLTIGui , size(p%FreqList), 'SPLTIGui' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%CfVar , 2 , 'CfVar' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%d99Var , 2 , 'd99Var' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%dstarVar , 2 , 'dstarVar' , errStat2, errMsg2); if(Failed()) return + call AllocAry(m%EdgeVelVar , 2 , 'EdgeVelVar', errStat2, errMsg2); if(Failed()) return + call AllocAry(m%LE_Location, 3, p%NumBlNds, p%numBlades, 'LE_Location', ErrStat2, ErrMsg2); if(Failed()) return + m%ChordAngleLE = 0.0_ReKi + m%SpanAngleLE = 0.0_ReKi + m%ChordAngleTE = 0.0_ReKi + m%SpanAngleTE = 0.0_ReKi + m%rTEtoObserve = 0.0_ReKi + m%rLEtoObserve = 0.0_ReKi + m%SPLLBL = 0.0_ReKi + m%SPLP = 0.0_ReKi + m%SPLS = 0.0_ReKi + m%SPLALPH = 0.0_ReKi + m%SPLTBL = 0.0_ReKi + m%SPLBLUNT = 0.0_ReKi + m%SPLTIP = 0.0_ReKi + m%SPLTI = 0.0_ReKi + m%SPLTIGui = 0.0_ReKi + m%CfVar = 0.0_ReKi + m%d99Var = 0.0_ReKi + m%dstarVar = 0.0_ReKi + m%EdgeVelVar = 0.0_ReKi + m%LE_Location = 0.0_ReKi + m%speccou = 0 + m%filesopen = 0 +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine Init_MiscVars +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes (allocates) the misc variables for use during the simulation. +subroutine Init_states(xd, p, errStat, errMsg) + type(AA_DiscreteStateType), intent(inout) :: xd ! + type(AA_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 + integer(intKi) :: k,ji + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_DiscrStates' + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + + call AllocAry(xd%MeanVrel, p%NumBlNds, p%numBlades, 'xd%MeanVrel' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%VrelSq, p%NumBlNds, p%numBlades, 'xd%VrelSq' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%TIVrel, p%NumBlNds, p%numBlades, 'xd%TIVrel' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%MeanVxVyVz, p%NumBlNds, p%numBlades, 'xd%MeanVxVyVz', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%TIVx, p%NumBlNds, p%numBlades, 'xd%TIVx' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%VxSq, p%NumBlNds, p%numBlades, 'xd%VxSq' , ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(xd%VrelStore, p%total_sample+1, p%NumBlNds, p%numBlades,'xd%VrelStore', ErrStat2, ErrMsg2) ! plus one just in case + if(Failed()) return + DO ji=1,size(xd%MeanVrel,2) + DO k=1,size(xd%MeanVrel,1) + xd%VrelSq (k,ji) = 0.0_ReKi ! Relative Velocity Squared for TI calculation (on the fly) + xd%MeanVrel (k,ji) = 0.0_ReKi ! Relative Velocity Mean calculation (on the fly) + xd%TIVrel(k,ji) = 0.0_ReKi ! Turbulence Intensity (for on the fly calculation) + xd%MeanVxVyVz (k,ji) = 0.0_ReKi ! + xd%TIVx (k,ji) = 0.0_ReKi ! + xd%VxSq (k,ji) = 0.0_ReKi ! + xd%VrelStore (1:size(xd%VrelStore,1),k,ji) = 0.0_ReKi ! + ENDDO + ENDDO + call AllocAry(xd%RegVxStor,p%total_sampleTI,size(p%rotorregionlimitsrad)-1,size(p%rotorregionlimitsalph)-1,'xd%Vxst',ErrStat2,ErrMsg2) + if(Failed()) return + call AllocAry(xd%allregcounter ,size(p%rotorregionlimitsrad)-1,size(p%rotorregionlimitsalph)-1,'xd%allregcounter',ErrStat2,ErrMsg2 ) + if(Failed()) return + call AllocAry(xd%VxSqRegion ,size(p%rotorregionlimitsrad)-1,size(p%rotorregionlimitsalph)-1,'xd%VxSqRegion' , ErrStat2, ErrMsg2) + if(Failed()) return + call AllocAry(xd%RegionTIDelete,size(p%rotorregionlimitsrad)-1,size(p%rotorregionlimitsalph)-1,'xd%RegionTIDelete', ErrStat2, ErrMsg2) + do ji=1,size(xd%allregcounter,2) + do k=1,size(xd%allregcounter,1) + xd%allregcounter(k,ji) = 2.0_Reki ! + xd%VxSqRegion(k,ji) = 0.0_ReKi ! + xd%RegionTIDelete(k,ji) = 0.0_ReKi ! + xd%RegVxStor(1:size(xd%RegVxStor,1),k,ji)=0.0_reki + enddo + enddo +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine Init_states +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AA_UpdateStates( t, n, m, u, p, xd, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current simulation time step n = 0,1,... + type(AA_InputType), intent(in ) :: u !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Parameters + type(AA_DiscreteStateType), intent(inout) :: xd !< Input: Discrete states at t; + type(AA_MiscVarType), intent(inout) :: m !< misc/optimization data + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'AA_UpdateStates' + REAL(ReKi),DIMENSION(p%NumBlNds,p%numBlades) :: TEMPSTD ! temporary standard deviation variable + REAL(ReKi) :: tempsingle,tempmean,angletemp,abs_le_x ! temporary standard deviation variable + integer(intKi) :: i,j,k,rco, y0_a,y1_a,z0_a,z1_a + logical :: exist + REAL(ReKi) :: yi_a,zi_a,yd_a,zd_a,c00_a,c10_a + + ErrStat = ErrID_None + ErrMsg = "" + ! Cumulative mean and standard deviation, states are updated as Vx Vy Vz changes at each time step + TEMPSTD = sqrt( u%Inflow(1,:,:)**2+u%Inflow(2,:,:)**2+u%Inflow(3,:,:)**2 ) + xd%MeanVxVyVz = (TEMPSTD + xd%MeanVxVyVz*n) / (n+1) + ! xd%VxSq = TEMPSTD**2 + xd%VxSq + ! TEMPSTD = sqrt( (xd%VxSq/(n+1)) - (xd%MeanVxVyVz**2) ) + ! xd%TIVx = (TEMPSTD / xd%MeanVxVyVz ) ! check inflow noise input for multiplication with 100 or not + + m%speccou= m%speccou+1 + IF( (p%TICalcMeth.eq.2) ) THEN + do i=1,p%NumBlades + do j=1,p%NumBlNds + abs_le_x=m%LE_Location(3,j,i)-p%hubheight + IF ((abs_le_x.lt.0).and.(m%LE_Location(2,j,i).lt.0)) THEN + angletemp=180+ATAN( ABS( m%LE_Location(2,j,i)/abs_le_x ) ) * R2D_D + ELSEIF ((abs_le_x.lt.0).and.(m%LE_Location(2,j,i).gt.0)) THEN + angletemp=180-ATAN( ABS( m%LE_Location(2,j,i)/abs_le_x ) ) * R2D_D + ELSEIF ((abs_le_x.gt.0).and.(m%LE_Location(2,j,i).lt.0)) THEN + angletemp=360-ATAN( ABS( m%LE_Location(2,j,i)/abs_le_x ) ) * R2D_D + ELSEIF ((abs_le_x.gt.0).and.(m%LE_Location(2,j,i).gt.0)) THEN + angletemp=ATAN( m%LE_Location(2,j,i)/abs_le_x ) * R2D_D + ELSE + print*, 'problem in angletemp Aeroacoustics module' + ENDIF + !abs_le_x=ABS(abs_le_x) + do k=1,size(p%rotorregionlimitsrad) + IF (p%BlSpn(j,i)-p%rotorregionlimitsrad(k).lt.0) THEN ! it means location is in the k-1 region + !print*, abs_le_x,p%rotorregionlimitsrad(k),k-1 + GOTO 4758 + ENDIF + enddo + 4758 do rco=1,size(p%rotorregionlimitsalph) + IF (angletemp-p%rotorregionlimitsalph(rco).lt.0) THEN ! it means location is in the k-1 region + GOTO 9815 + ENDIF + enddo + 9815 xd%allregcounter(k-1,rco-1)=CEILING(xd%allregcounter(k-1,rco-1)+1.0_Reki) ! increase the sample amount in that specific 5 meter height vertical region + tempsingle = sqrt( u%Inflow(1,j,i)**2+u%Inflow(2,j,i)**2+u%Inflow(3,j,i)**2 ) ! + ! with storage region dependent moving average and TI + IF (INT(xd%allregcounter(k-1,rco-1)) .lt. (size(xd%RegVxStor,1)+1)) THEN + xd%RegVxStor(INT(xd%allregcounter(k-1,rco-1)),k-1,rco-1)=tempsingle + xd%TIVx(j,i) = 0 + xd%RegionTIDelete(k-1,rco-1)=0 + ELSE + xd%RegVxStor((mod(INT(xd%allregcounter(k-1,rco-1))-size(xd%RegVxStor,1),size(xd%RegVxStor,1)))+1,k-1,rco-1)=tempsingle + tempmean=SUM(xd%RegVxStor(:,k-1,rco-1)) + tempmean=tempmean/size(xd%RegVxStor,1) + xd%RegionTIDelete(k-1,rco-1)=SQRT((SUM((xd%RegVxStor(:,k-1,rco-1)-tempmean)**2)) / size(xd%RegVxStor,1) ) + xd%TIVx(j,i) = xd%RegionTIDelete(k-1,rco-1) ! only the fluctuation + ENDIF + enddo + enddo + + ELSE! interpolate from the user given ti values + do i=1,p%NumBlades + do j=1,p%NumBlNds + zi_a=ABS(m%LE_Location(3,j,i) - (FLOOR(p%HubHeight-maxval(p%BlSpn(:,1)))) ) /p%dz_turb_in + z0_a=floor(zi_a) + z1_a=ceiling(zi_a) + zd_a=zi_a-z0_a + yi_a=ABS(m%LE_Location(2,j,i) + maxval(p%BlSpn(:,1)) ) /p%dy_turb_in + y0_a=floor(yi_a) + y1_a=ceiling(yi_a) + yd_a=yi_a-y0_a + c00_a=(1.0_ReKi-yd_a)*p%TI_Grid_In(z0_a+1,y0_a+1)+yd_a*p%TI_Grid_In(z0_a+1,y1_a+1) + c10_a=(1.0_ReKi-yd_a)*p%TI_Grid_In(z1_a+1,y0_a+1)+yd_a*p%TI_Grid_In(z1_a+1,y1_a+1) + ! 2 points + xd%TIVx(j,i)=(1.0_ReKi-zd_a)*c00_a+zd_a*c10_a + if (i.eq.p%NumBlades) then + if (j.eq.p%NumBlNds) then + endif + endif + enddo + enddo + endif +end subroutine AA_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +subroutine AA_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + TYPE(AA_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(AA_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(AA_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(AA_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(AA_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(AA_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(AA_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(AA_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 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! Destroy the input data: + CALL AA_DestroyInput( u, ErrStat, ErrMsg ) + ! Destroy the parameter data: + CALL AA_DestroyParam( p, ErrStat, ErrMsg ) + ! Destroy the state data: + CALL AA_DestroyContState( x, ErrStat, ErrMsg ) + CALL AA_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL AA_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL AA_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + CALL AA_DestroyMisc( m, ErrStat, ErrMsg ) + ! Destroy the output data: + CALL AA_DestroyOutput( y, ErrStat, ErrMsg ) + +END SUBROUTINE AA_End + +!> Routine for computing outputs, used in both loose and tight coupling. +!! This subroutine is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! The descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +subroutine AA_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg) + ! NOTE: no matter how many channels are selected for output, all of the outputs are calcalated + ! All of the calculated output channels are placed into the m%AllOuts(:), while the channels selected for outputs are + ! placed in the y%WriteOutput(:) array. + !.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(AA_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AA_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(AA_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(AA_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(AA_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(AA_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + type(AA_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 + ! Local variables + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer(intKi) :: i + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AA_CalcOutput' + ErrStat = ErrID_None + ErrMsg = "" + ! assume integer divide is possible + call CalcObserve(t,p,m,u,xd,errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (t >= p%AAStart) THEN + IF (mod(t + 1E-10,p%DT) .lt. 1E-6) THEN + call CalcAeroAcousticsOutput(u,p,m,xd,y,errStat2,errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call Calc_WriteOutput( p, u, m, y, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AA_WriteOutputLine(y, t, p, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ENDIF + ENDIF +end subroutine AA_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!----------------------------------------------------------------------------------------------------------------------------------! +SUBROUTINE CalcObserve(t,p,m,u,xd,errStat,errMsg) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(AA_DiscreteStateType), INTENT(IN ) :: xd !< discrete state type + TYPE(AA_ParameterType), intent(in ) :: p !< Parameters + TYPE(AA_InputType), intent(in ) :: u !< NN Inputs at Time + TYPE(AA_MiscVarType), intent(inout) :: m !< misc/optimization data (not defined in submodules) + INTEGER(IntKi), intent( out) :: errStat !< Error status of the operation + CHARACTER(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + ! Local variables. + REAL(ReKi) :: RLEObserve (3) ! Position vector from leading edge to observer in trailing edge coordinate system + REAL(ReKi) :: RTEObserve (3) ! Position vector from trailing edge to observer in trailing edge coordinate system + REAL(ReKi) :: RTEObserveG (3) ! Position vector from trailing edge to observer in the coordinate system located at the trailing edge and rotated as the global + REAL(ReKi) :: RLEObserveG (3) ! Position vector from leading edge to observer in the coordinate system located at the leading edge and rotated as the global + REAL(ReKi) :: RTEObservereal (3) ! Location of trailing edge in global coordinate system + REAL(ReKi) :: RLEObservereal (3) ! Location of leading edge in global coordinate system + REAL(ReKi) :: LocalToGlobal(3,3) ! Transformation matrix + REAL(ReKi) :: timeLE ! Time of sound propagation from leading edge to observer + REAL(ReKi) :: timeTE ! Time of sound propagation from trailing edge to observer + REAL(ReKi) :: phi_e ! Spanwise directivity angle + REAL(ReKi) :: theta_e ! Chordwise directivity angle + INTEGER(intKi) :: I ! I A generic index for DO loops. + INTEGER(intKi) :: J ! J A generic index for DO loops. + INTEGER(intKi) :: K ! K A generic index for DO loops. + INTEGER(intKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), parameter :: RoutineName = 'CalcObserveDist' + LOGICAL :: exist + + ErrStat = ErrID_None + ErrMsg = "" + ! Loop through the blades + DO I = 1,p%numBlades + ! Loop through the nodes along blade span + DO J = 1,p%NumBlNds + ! Transpose the rotational vector GlobalToLocal to obtain the rotation LocalToGlobal + LocalToGlobal = TRANSPOSE(u%RotGtoL(:,:,J,I)) + ! Rotate the coordinates of leading and trailing edge from the local reference system to the global. Then add the coordinates of the aerodynamic center in the global coordinate system + ! The global coordinate system is located on the ground, has x pointing downwind, y pointing laterally, and z pointing vertically upwards + RTEObservereal = MATMUL(LocalToGlobal, p%AFTeCo(:,J,I)) + u%AeroCent_G(:,J,I) + RLEObservereal = MATMUL(LocalToGlobal, p%AFLeCo(:,J,I)) + u%AeroCent_G(:,J,I) + ! Compute the coordinates of the leading edge in the global coordinate system + m%LE_Location(1,J,I) = RLEObservereal(1) + m%LE_Location(2,J,I) = RLEObservereal(2) + m%LE_Location(3,J,I) = RLEObservereal(3) + ! If the time step is set to generate AA outputs + IF (t >= p%AAStart) THEN + IF ( mod(t + 1E-10,p%DT) .lt. 1E-6) THEN + ! Loop through the observers + DO K = 1,p%NrObsLoc + ! Calculate the position of the observer K in a reference system located at the trailing edge and oriented as the global reference system + RTEObserveG(1)=p%Obsx(K)-RTEObservereal(1) + RTEObserveG(2)=p%Obsy(K)-RTEObservereal(2) + RTEObserveG(3)=p%Obsz(K)-RTEObservereal(3) + ! Calculate the position of the observer K in a reference system located at the leading edge and oriented as the global reference system + RLEObserveG(1)=p%Obsx(K)-RLEObservereal(1) + RLEObserveG(2)=p%Obsy(K)-RLEObservereal(2) + RLEObserveG(3)=p%Obsz(K)-RLEObservereal(3) + ! Rotate back the two reference systems from global to local. + RTEObserve = MATMUL(u%RotGtoL(:,:,J,I), RTEObserveG) + RLEObserve = MATMUL(u%RotGtoL(:,:,J,I), RLEObserveG) + + ! Calculate absolute distance between node and observer + m%rTEtoObserve(K,J,I) = SQRT (RTEObserve(1)**2+RTEObserve(2)**2+RTEObserve(3)**2) + m%rLEtoObserve(K,J,I) = SQRT (RLEObserve(1)**2+RLEObserve(2)**2+RLEObserve(3)**2) + + ! Calculate time of noise propagation to observer + timeTE = m%rTEtoObserve(K,J,I) / p%SpdSound + timeLE = m%rLEtoObserve(K,J,I) / p%SpdSound + + ! The local system has y alinged with the chord, x pointing towards the airfoil suction side, and z aligned with blade span from root towards tip + ! x ---> z_e + ! y ---> x_e + ! z ---> y_e + + ! Compute spanwise directivity angle phi for the trailing edge + phi_e = ATAN2 (RTEObserve(1) , RTEObserve(3)) + m%SpanAngleTE(K,J,I) = phi_e * R2D + + ! Compute chordwise directivity angle theta for the trailing edge + theta_e = ATAN2 ((RTEObserve(3) * COS (phi_e) + RTEObserve(1) * SIN (phi_e) ) , RTEObserve(2)) + m%ChordAngleTE(K,J,I) = theta_e * R2D + + ! Compute spanwise directivity angle phi for the leading edge (it's the same angle for the trailing edge) + phi_e = ATAN2 (RLEObserve(1) , RLEObserve(3)) + m%SpanAngleLE(K,J,I) = phi_e * R2D + + ! Compute chordwise directivity angle theta for the leading edge + theta_e = ATAN2 ((RLEObserve(3) * COS (phi_e) + RLEObserve(1) * SIN (phi_e) ) , RLEObserve(2)) + m%ChordAngleLE(K,J,I) = theta_e * R2D + + ENDDO !K, observers + ENDIF ! every Xth time step or so.. + ENDIF ! only if the time step is more than user input value run this part + ENDDO !J, blade nodes + ENDDO !I , number of blades +END SUBROUTINE CalcObserve +!----------------------------------------------------------------------------------------------------------------------------------! +SUBROUTINE CalcAeroAcousticsOutput(u,p,m,xd,y,errStat,errMsg) + TYPE(AA_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AA_OutputType), INTENT(INOUT) :: y !< + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AA_MiscVarType), INTENT(INOUT) :: m !< misc/optimization data (not defined in submodules) + TYPE(AA_DiscreteStateType), INTENT(IN ) :: xd !< discrete state type + integer(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + character(*), INTENT( OUT) :: errMsg !< Error message if ErrStat /= ErrID_None + ! Local variables. + integer(intKi) :: III !III A generic index for DO loops. + integer(intKi) :: I !I A generic index for DO loops. + integer(intKi) :: J !J A generic index for DO loops. + integer(intKi) :: K,liop,cou ,JTEMP !K A generic index for DO loops. + integer(intKi) :: oi !K A generic index for DO loops. + REAL(ReKi) :: AlphaNoise ! + REAL(ReKi) :: UNoise ! + REAL(ReKi) :: elementspan ! + REAL(ReKi),DIMENSION(p%NumBlNds) ::tempdel + REAL(ReKi),DIMENSION(p%NrObsLoc,p%NumBlNds,p%numBlades) ::OASPLTBLAll + REAL(ReKi),DIMENSION(p%NrObsLoc,p%NumBlNds,p%numBlades,size(p%FreqList)) ::ForMaxLoc + REAL(ReKi),DIMENSION(size(y%OASPL_Mech,1),size(p%FreqList),p%NrObsLoc,p%NumBlNds,p%numBlades) :: ForMaxLoc3 + REAL(ReKi),DIMENSION(size(p%FreqList),p%NrObsLoc,p%numBlades) ::SPL_Out + REAL(ReKi),DIMENSION(p%NumBlNds,p%numBlades) ::temp_dispthick + REAL(ReKi),DIMENSION(p%NumBlNds,p%numBlades) ::temp_dispthickchord + + real(ReKi) :: Ptotal + real(ReKi) :: PtotalLBL + real(ReKi) :: PtotalTBLP + real(ReKi) :: PtotalTBLS + real(ReKi) :: PtotalSep + real(ReKi) :: PtotalTBLAll + real(ReKi) :: PtotalBlunt + real(ReKi) :: PtotalTip + real(ReKi) :: PtotalInflow + real(ReKi) :: PLBL + real(ReKi) :: PTBLP + real(ReKi) :: PTBLS + real(ReKi) :: PTBLALH + real(ReKi) :: PTip + real(ReKi) :: PTI + real(ReKi) :: PBLNT,adforma + REAL(ReKi),DIMENSION(2) :: Cf ,d99, d_star + TYPE(FFT_DataType) :: FFT_Data !< the instance of the FFT module we're using + REAL(ReKi),DIMENSION(p%total_sample) :: spect_signal + REAL(ReKi),DIMENSION(p%total_sample/2) :: spectra + real(ReKi),ALLOCATABLE :: fft_freq(:) + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'CalcAeroAcousticsOutput' + logical :: exist + + ErrStat = ErrID_None + ErrMsg = "" + + !------------------- Fill with zeros -------------------------! + DO I = 1,p%numBlades;DO J = 1,p%NumBlNds;DO K = 1,p%NrObsLoc; + y%OASPL(k,j,i) = 0.0_Reki + DO oi=1,size(y%OASPL_Mech,1) + y%OASPL_Mech(oi,k,j,i)= 0.0_Reki + ENDDO; + ENDDO;ENDDO;ENDDO + + DO K = 1,p%NrObsLoc; + y%DirectiviOutput(K) = 0.0_Reki + DO I=1,p%NumBlades;DO III=1,size(p%FreqList); + y%SumSpecNoise(III,K,I) = 0.0_Reki + ForMaxLoc(K,1:p%NumBlNds,I,III)=0.0_Reki + DO oi=1,size(y%OASPL_Mech,1) + y%SumSpecNoiseSep(oi,K,III) = 0.0_Reki + ForMaxLoc3(oi,III,K,1:p%NumBlNds,I)=0.0_Reki + m%SPLLBL(III)=0.0_Reki + m%SPLP(III)=0.0_Reki + m%SPLS(III)=0.0_Reki + m%SPLALPH(III)=0.0_Reki + m%SPLBLUNT(III)=0.0_Reki + m%SPLTIP(III)=0.0_Reki + m%SPLti(III)=0.0_Reki + ENDDO + ENDDO;ENDDO + ENDDO + + DO K = 1,p%NrObsLoc; + DO III = 1,size(p%FreqList); + y%PtotalFreq(K,III) = 0.0_ReKi + ENDDO + ENDDO + + !------------------- initialize FFT -------------------------! + !!!IF (m%speccou .eq. p%total_sample)THEN + !!!CALL InitFFT ( p%total_sample, FFT_Data, ErrStat=ErrStat2 ) + !!! CALL SetErrStat(ErrStat2, 'Error in InitFFT', ErrStat, ErrMsg, 'CalcAeroAcousticsOutput' ) + !!!CALL AllocAry( fft_freq, size(spect_signal)/2-1, 'fft_freq', ErrStat2, ErrMsg2 ) + !!! CALL SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + !!!do liop=1,size(fft_freq) + !!! fft_freq(liop)=p%fsample*liop ! fRequncy x axis + !!! fft_freq(liop)=fft_freq(liop)/size(spect_signal) + !!!enddo + !!!ENDIF + + + + DO I = 1,p%numBlades + DO J = p%startnode,p%NumBlNds ! starts loop from startnode. + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + !--------Calculate Spectrum for dissipation calculation-------------------------! + !IF (m%speccou .eq. p%total_sample)THEN + !spect_signal=xd%VrelStore( 1:p%total_sample,J,I ) + ! CALL ApplyFFT_f( spect_signal, FFT_Data, ErrStat2 ) + ! IF (ErrStat2 /= ErrID_None ) THEN + ! CALL SetErrStat(ErrStat2, 'Error in ApplyFFT .', ErrStat, ErrMsg, 'CalcAeroAcousticsOutput' ) + ! ENDIF + !cou=1 + !O liop=2,size(spect_signal)-1,2 + !cou=cou+1 + !spectra(cou) = spect_signal(liop)*spect_signal(liop) + spect_signal(1+liop)*spect_signal(1+liop) + !ENDDO + !spectra(1)=spect_signal(1)*spect_signal(1) + !spectra=spectra/(size(spectra)*2) + ! m%speccou=0 + !ENDIF + + Unoise = u%Vrel(J,I) + IF (EqualRealNos(Unoise,0.0_ReKi)) then + Unoise = 0.1 ! TODO TODO a value consistent with the test above should be used + ENDIF + IF (J .EQ. p%NumBlNds) THEN + elementspan = (p%BlSpn(J,I)-p%BlSpn(J-1,I))/2 + ELSE + elementspan = (p%BlSpn(J,I)-p%BlSpn(J-1,I))/2 + (p%BlSpn(J+1,I)-p%BlSpn(J,I))/2 + ENDIF + AlphaNoise= u%AoANoise(J,I) * R2D_D + + + !--------Read in Boundary Layer Data-------------------------! + IF (p%X_BLMethod .EQ. 2) THEN + call BL_Param_Interp(p,m,Unoise,AlphaNoise,p%BlChord(J,I),p%BlAFID(J,I), errStat2, errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + temp_dispthick(J,I) = m%d99Var(1) + m%d99Var = m%d99Var*p%BlChord(J,I) + m%dstarVar = m%dstarVar*p%BlChord(J,I) + temp_dispthickchord(J,I)=m%d99Var(1) + ENDIF + + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + !------------------------------!!------------------------------!!------------------------------!!------------------------------! + DO K = 1,p%NrObsLoc + !--------Laminar Boundary Layer Vortex Shedding Noise----------------------------! + IF ( (p%ILAM .EQ. 1) .AND. (p%ITRIP .EQ. 0) ) THEN + CALL LBLVS(AlphaNoise,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + elementspan,m%rTEtoObserve(K,J,I), & + p,m%d99Var(2),m%dstarVar(1),m%dstarVar(2),m%SPLLBL,p%StallStart(J,I),errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + !--------Turbulent Boundary Layer Trailing Edge Noise----------------------------! + IF ( (p%ITURB .EQ. 1) .or. (p%ITURB .EQ. 2) ) THEN + CALL TBLTE(AlphaNoise,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + elementspan,m%rTEtoObserve(K,J,I), p, j,i,k,m%d99Var(2),m%dstarVar(1),m%dstarVar(2),p%StallStart(J,I), & + m%SPLP,m%SPLS,m%SPLALPH,m%SPLTBL,errStat2,errMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (p%ITURB .EQ. 2) THEN + m%SPLP=0.0_ReKi;m%SPLS=0.0_ReKi;m%SPLTBL=0.0_ReKi; + m%EdgeVelVar(1)=1.000d0;m%EdgeVelVar(2)=m%EdgeVelVar(1); + CALL TBLTE_TNO(AlphaNoise,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + elementspan,m%rTEtoObserve(K,J,I),m%CfVar,m%d99var,m%EdgeVelVar ,p, & + m%SPLP,m%SPLS,m%SPLALPH,m%SPLTBL,errStat2 ,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + ENDIF + !--------Blunt Trailing Edge Noise----------------------------------------------! + IF ( p%IBLUNT .EQ. 1 ) THEN + CALL BLUNT(AlphaNoise,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + elementspan,m%rTEtoObserve(K,J,I),p%TEThick(J,I),p%TEAngle(J,I), & + p, m%d99Var(2),m%dstarVar(1),m%dstarVar(2),m%SPLBLUNT,p%StallStart(J,I),errStat2,errMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + !--------Tip Noise--------------------------------------------------------------! + IF ( (p%ITIP .EQ. 1) .AND. (J .EQ. p%NumBlNds) ) THEN + CALL TIPNOIS(AlphaNoise,p%ALpRAT,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + m%rTEtoObserve(K,J,I), p, m%SPLTIP,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + !--------Inflow Turbulence Noise ------------------------------------------------! + ! important checks to be done inflow tubulence inputs + IF (p%IInflow.gt.0) then + + ! Amiet's Inflow Noise Model is Calculated as long as InflowNoise is On + CALL InflowNoise(AlphaNoise,p%BlChord(J,I),Unoise,m%ChordAngleLE(K,J,I),m%SpanAngleLE(K,J,I),& + elementspan,m%rLEtoObserve(K,J,I),xd%MeanVxVyVz(J,I),xd%TIVx(J,I),m%LE_Location(3,J,I),0.050,p,m%SPLti,errStat2,errMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! If Guidati model (simplified or full version) is also on then the 'SPL correction' to Amiet's model will be added + IF ( p%IInflow .EQ. 2 ) THEN + CALL Simple_Guidati(UNoise,p%BlChord(J,I),p%AFThickGuida(2,p%BlAFID(J,I)), & + p%AFThickGuida(1,p%BlAFID(J,I)),p,m%SPLTIGui,errStat2,errMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + m%SPLti=m%SPLti+m%SPLTIGui + 10. ! +10 is fudge factor to match NLR data + ELSEIF ( p%IInflow .EQ. 3 ) THEN + print*,'Full Guidati removed' + STOP + ENDIF + ENDIF + !----------------------------------------------------------------------------------------------------------------------------------! + ! ADD IN THIS SEGMENT'S CONTRIBUTION ON A MEAN-SQUARE + ! PRESSURE BASIS + !----------------------------------------------------------------------------------------------------------------------------------! + Ptotal = 0.0_ReKi ! Total Sound Pressure - All (7) mechanisms, All Frequencies + PtotalLBL= 0.0_ReKi ! Total Sound Pressure - Laminar Boundary Layer, All Frequencies + PtotalTBLP= 0.0_ReKi ! Total Sound Pressure - Turbulent Boundary Layer, Pressure Contribution, All Frequencies + PtotalTBLS= 0.0_ReKi ! Total Sound Pressure - Turbulent Boundary Layer, Suction Contribution, All Frequencies + PtotalSep= 0.0_ReKi ! Total Sound Pressure - Separation, All Frequencies + PtotalTBLAll = 0.0_ReKi ! Total Sound Pressure - Turbulent Boundary Layer, All Frequencies + PtotalBlunt= 0.0_ReKi ! Total Sound Pressure - Blunt Trailing Edge, All Frequencies + PtotalTip= 0.0_ReKi ! Total Sound Pressure - Tip Noise, All Frequencies + PtotalInflow= 0.0_ReKi ! Total Sound Pressure - Turbulent Inflow, All Frequencies + PLBL= 0.0_ReKi ! Laminar Boundary Layer - Current Iteration + PTBLP= 0.0_ReKi ! Turbulent Boundary Layer, Pressure Contribution - Current Iteration + PTBLS= 0.0_ReKi ! Turbulent Boundary Layer, Suction Contribution - Current Iteration + PTBLALH= 0.0_ReKi ! Turbulent Boundary Layer, Angle of Attack Contribution - Current Iteration (Feeds into PTotalSep. Consider renaming.) + PTip= 0.0_ReKi ! Tip Noise - Current Iteration + PTI= 0.0_ReKi ! Turbulent Inflow - Current Iteration + PBLNT= 0.0_ReKi ! Blunt Trailing Edge - Current Iteration + + + DO III=1,size(p%FreqList) ! Loops through each 1/3rd octave center frequency + + ! If flag for LBL is ON and Boundary Layer Trip is OFF, then compute LBL + IF ( (p%ILAM .EQ. 1) .AND. (p%ITRIP .EQ. 0) ) THEN + IF (p%AweightFlag .eqv. .TRUE.) THEN + m%SPLLBL(III) = m%SPLLBL(III) + p%Aweight(III) ! A-weighting + ENDIF + + PLBL = 10.0_ReKi**(m%SPLLBL(III)/10.0_ReKi) ! SPL to Sound Pressure (P) Conversion for III Frequency + + PtotalLBL = PtotalLBL + PLBL ! Sum of Current LBL with LBL Running Total + Ptotal = Ptotal + PLBL ! Sum of Current LBL with Overall Running Total + y%PtotalFreq(K,III) = y%PtotalFreq(K,III) + PLBL ! Running sum of observer and frequency dependent sound pressure + + y%SumSpecNoiseSep(1,K,III) = PLBL + y%SumSpecNoiseSep(1,K,III) ! Assigns Current LBL to Appropriate Mechanism (1), Observer (K), and Frequency (III) + ENDIF + + ! If flag for TBL is ON, compute Pressure, Suction, and AoA contributions + IF ( p%ITURB .GT. 0 ) THEN + IF (p%AweightFlag .eqv. .TRUE.) THEN + m%SPLP(III) = m%SPLP(III) + p%Aweight(III) ! A-weighting + m%SPLS(III) = m%SPLS(III) + p%Aweight(III) ! A-weighting + m%SPLALPH(III) = m%SPLALPH(III) + p%Aweight(III) ! A-weighting + ENDIF + + PTBLP = 10.0_ReKi**(m%SPLP(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + PTBLS = 10.0_ReKi**(m%SPLS(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + PTBLALH = 10.0_ReKi**(m%SPLALPH(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + + PtotalTBLP = PtotalTBLP + PTBLP ! Sum of Current TBLP with TBLP Running Total + PtotalTBLS = PtotalTBLS + PTBLS ! Sum of Current TBLS with TBLS Running Total + PtotalSep = PtotalSep + PTBLALH ! Sum of Current TBLALH with TBLALH Running Total + + Ptotal = Ptotal + PTBLP + PTBLS + PTBLALH ! Sum of Current TBL with Overall Running Total + y%PtotalFreq(K,III) = y%PtotalFreq(K,III) + PTBLP + PTBLS + PTBLALH ! Running sum of observer and frequency dependent sound pressure + PtotalTBLAll = PtotalTBLAll + 10.0_ReKi**(m%SPLTBL(III)/10.0_ReKi) ! SPLTBL from comment on line 1794 is the mean-square sum of SPLP, SPLS, and SPLALPH. + ! So this should be equal to PTBLP+PTBLS+TBLALH + y%SumSpecNoiseSep(2,K,III) = PTBLP + y%SumSpecNoiseSep(2,K,III) ! Assigns Current TBLP to Appropriate Mechanism (2), Observer (K), and Frequency (III) + y%SumSpecNoiseSep(3,K,III) = PTBLS + y%SumSpecNoiseSep(3,K,III) ! Assigns Current TBLS to Appropriate Mechanism (2), Observer (K), and Frequency (III) + y%SumSpecNoiseSep(4,K,III) = PTBLALH + y%SumSpecNoiseSep(4,K,III) ! Assigns Current TBLALH to Appropriate Mechanism (2), Observer (K), and Frequency (III) + ENDIF + + ! If flag for Blunt TE is ON, compute Blunt contribution + IF ( p%IBLUNT .GT. 0 ) THEN ! NOTE: .EQ. 1 would be more accurate since only options are 0 and 1 + IF (p%AweightFlag .eqv. .TRUE.) THEN + m%SPLBLUNT(III) = m%SPLBLUNT(III) + p%Aweight(III) ! A-weighting + ENDIF + + PBLNT = 10.0_ReKi**(m%SPLBLUNT(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + + PtotalBlunt = PtotalBlunt + PBLNT ! Sum of Current Blunt with Blunt Running Total + Ptotal = Ptotal + PBLNT ! Sum of Current Blunt with Overall Running Total + y%PtotalFreq(K,III) = y%PtotalFreq(K,III) + PBLNT ! Running sum of observer and frequency dependent sound pressure + + y%SumSpecNoiseSep(5,K,III) = PBLNT + y%SumSpecNoiseSep(5,K,III) ! Assigns Current Blunt to Appropriate Mechanism (5), Observer (K), and Frequency (III) + ENDIF + + ! If flag for Tip is ON and the current blade node (J) is the last node (tip), compute Tip contribution + IF ( (p%ITIP .GT. 0) .AND. (J .EQ. p%NumBlNds) ) THEN ! NOTE: .EQ. 1 would again be more accurate + IF (p%AweightFlag .eqv. .TRUE.) THEN + m%SPLTIP(III) = m%SPLTIP(III) + p%Aweight(III) ! A-weighting + ENDIF + + PTip = 10.0_ReKi**(m%SPLTIP(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + + PtotalTip = PtotalTip + PTip ! Sum of Current Tip with Tip Running Total + Ptotal = Ptotal + PTip ! Sum of Current Tip with Overall Running Total + y%PtotalFreq(K,III) = y%PtotalFreq(K,III) + PTip ! Running sum of observer and frequency dependent sound pressure + + y%SumSpecNoiseSep(6,K,III) = PTip + y%SumSpecNoiseSep(6,K,III) ! Assigns Current Tip to Appropriate Mechanism (6), Observer (K), and Frequency (III) + ENDIF + + ! If flag for TI is ON, compute Turbulent Inflow contribution + IF ( (p%IInflow .GT. 0) ) THEN + IF (p%AweightFlag .eqv. .TRUE.) THEN + m%SPLti(III) = m%SPLti(III) + p%Aweight(III) ! A-weighting + ENDIF + + PTI = 10.0_ReKi**(m%SPLti(III)/10.0_ReKi) ! SPL to P Conversion for III Frequency + + PtotalInflow = PtotalInflow + PTI ! Sum of Current TI with TI Running Total + Ptotal = Ptotal + PTI ! Sum of Current TI with Overall Running Total + y%PtotalFreq(K,III) = y%PtotalFreq(K,III) + PTI ! Running sum of observer and frequency dependent sound pressure + + y%SumSpecNoiseSep(7,K,III) = PTI + y%SumSpecNoiseSep(7,K,III) ! Assigns Current TI to Appropriate Mechanism (7), Observer (K), and Frequency (III) + ENDIF + + ENDDO ! III = 1, size(p%FreqList) + + y%DirectiviOutput(K) = Ptotal + y%DirectiviOutput(K) ! Assigns Overall Pressure to Appropriate Observer for Directivity + IF (y%DirectiviOutput(K) .EQ. 0.) y%DirectiviOutput(K) = 1 ! Since these will all be converted via LOG10, they will produce an error if .EQ. 0. + ! Set .EQ. to 1 instead (LOG10(1)=0) + y%OASPL(K,J,I) = Ptotal + y%OASPL(K,J,I) ! Assigns Overall Pressure to Appropriate Observer/Blade/Node for Directivity + ENDDO ! Loop on observers + ENDDO ! Loop on blade nodes + ENDDO ! Loop on blades + + ! If any Output file is wanted, convert DirectiviOutput from Directivity Factor to Directivity Index + ! Ref: Fundamentals of Acoustics by Colin Hansen (1951) + y%DirectiviOutput = 10.*LOG10(y%DirectiviOutput) !! DirectiviOutput is used as total observer OASPL for Output File 1 + ! Since these will all be converted via LOG10, they will produce an error if .EQ. 0., Set .EQ. to 1 instead (LOG10(1)=0) + DO I = 1,p%numBlades + DO J = 1,p%NumBlNds + DO K = 1,p%NrObsLoc + IF (y%OASPL(K,J,I) .EQ. 0.) y%OASPL(K,J,I) = 1 + ENDDO + ENDDO + ENDDO + IF (p%NrOutFile .gt. 0) y%OASPL = 10.*LOG10(y%OASPL) !! OASPL is used as observer/blade/node OASPL for Output File 4 + + ! Procedure for Output file 2 + IF (p%NrOutFile .gt. 1) THEN + DO K = 1,p%NrObsLoc + DO III=1,size(p%FreqList) + IF (y%PtotalFreq(K,III) .EQ. 0.) y%PtotalFreq(K,III) = 1 + y%PtotalFreq(K,III) = 10.*LOG10(y%PtotalFreq(K,III)) ! P to SPL conversion + ENDDO + ENDDO + ENDIF + + ! If 3rd Output file is needed, these will need to be converted via LOG10. Change to equal 1 to avoid error. + DO K = 1,p%NrObsLoc + DO III = 1,size(p%FreqList) + DO oi = 1,7 + IF (y%SumSpecNoiseSep(oi,K,III) .EQ. 0.) y%SumSpecNoiseSep(oi,K,III) = 1 + ENDDO + ENDDO + ENDDO + + ! Procedure for Output file 3 + IF (p%NrOutFile .gt. 2) THEN + y%SumSpecNoiseSep = 10.*LOG10(y%SumSpecNoiseSep) ! P to SPL Conversion + ENDIF + +END SUBROUTINE CalcAeroAcousticsOutput +!==================================================================================================================================! +SUBROUTINE LBLVS(ALPSTAR,C,U,THETA,PHI,L,R,p,d99Var2,dstarVar1,dstarVar2,SPLLAM,StallVal,errStat,errMsg) + REAL(ReKi), INTENT(IN ) :: ALPSTAR ! AOA + REAL(ReKi), INTENT(IN ) :: C ! Chord Length + REAL(ReKi), INTENT(IN ) :: U ! Unoise FREESTREAM VELOCITY METERS/SEC + REAL(ReKi), INTENT(IN ) :: THETA ! DIRECTIVITY ANGLE DEGREES + REAL(ReKi), INTENT(IN ) :: PHI ! DIRECTIVITY ANGLE DEGREES + REAL(ReKi), INTENT(IN ) :: L ! SPAN METERS + REAL(ReKi), INTENT(IN ) :: R ! OBSERVER DISTANCE FROM SEGMENT METERS + REAL(ReKi), INTENT(IN ) :: d99Var2 ! + REAL(ReKi), INTENT(IN ) :: dstarVar1 ! + REAL(ReKi), INTENT(IN ) :: dstarVar2 ! + REAL(ReKi), INTENT(IN ) :: StallVal ! + TYPE(AA_ParameterType), INTENT(IN ) :: p ! Noise module Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLLAM ! + INTEGER(IntKi), INTENT( OUT) :: errStat ! Error status of the operation + character(*), INTENT( OUT) :: errMsg ! Error message if ErrStat /= ErrID_None + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'LBLVS' + ! Local variables + real(ReKi) :: STPRIM ! STROUHAL NUMBER BASED ON PRESSURE SIDE BOUNDARY LAYER THICKNESS --- + real(ReKi) :: M ! MACH NUMBER + real(ReKi) :: RC ! REYNOLDS NUMBER BASED ON CHORD + real(ReKi) :: DELTAP ! PRESSURE SIDE BOUNDARY LAYER THICKNESS METERS + real(ReKi) :: DSTRS ! SUCTION SIDE BOUNDARY LAYER DISPLACEMENT THICKNESS METERS + real(ReKi) :: DSTRP ! PRESSURE SIDE BOUNDARY LAYER DISPLACEMENT THICKNESS METERS + real(ReKi) :: DBARH ! HIGH FREQUENCY DIRECTIVITY --- + real(ReKi) :: ST1PRIM ! REFERENCE STROUHAL NUMBER --- + real(ReKi) :: STPKPRM ! PEAK STROUHAL NUMBER --- + real(ReKi) :: RC0 ! REFERENCE REYNOLDS NUMBER --- + real(ReKi) :: D ! REYNOLDS NUMBER RATIO --- + real(ReKi) :: G1 ! SOUND PRESSURE LEVEL FUNCTION DB + real(ReKi) :: G2 ! OVERALL SOUND PRESSURE LEVEL FUNCTION DB + real(ReKi) :: G3 ! OVERALL SOUND PRESSURE LEVEL FUNCTION DB + real(ReKi) :: E ! STROUHAL NUMBER RATIO --- + real(ReKi) :: SCALE ! GEOMETRIC SCALING TERM + integer(intKi) :: I ! I A generic index for DO loops. + ErrStat = ErrID_None + ErrMsg = "" + !compute reynolds number and mach number + M = U / p%SpdSound ! MACH NUMBER + RC = U * C/p%KinVisc ! REYNOLDS NUMBER BASED ON CHORD + ! compute boundary layer thicknesses + IF (p%X_BLMethod .eq. 2) THEN + DELTAP = d99Var2 + DSTRS = dstarVar1 + DSTRP = dstarVar2 + ELSE + CALL THICK(C,M,RC,ALPSTAR,p,DELTAP,DSTRS,DSTRP,StallVal,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + ! compute directivity function + CALL DIRECTH(M,THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (DBARH <= 0) THEN + SPLLAM = 0. + RETURN + ENDIF + ! compute reference strouhal number ! Eq 55 from BPM Airfoil Self-noise and Prediction paper + IF (RC .LE. 1.3E+05) ST1PRIM = .18 + IF((RC .GT. 1.3E+05).AND.(RC.LE.4.0E+05))ST1PRIM=.001756*RC**.3931 + IF (RC .GT. 4.0E+05) ST1PRIM = .28 + STPKPRM = 10.**(-.04*ALPSTAR) * ST1PRIM ! Eq 56 from BPM Airfoil Self-noise and Prediction paper + + ! compute reference reynolds number ! Eq 59 from BPM Airfoil Self-noise and Prediction paper + IF (ALPSTAR .LE. 3.0) RC0=10.**(.215*ALPSTAR+4.978) + IF (ALPSTAR .GT. 3.0) RC0=10.**(.120*ALPSTAR+5.263) + ! compute peak scaled spectrum level + D = RC / RC0 ! Used in Eq 58 from BPM Airfoil Self-noise and Prediction paper + IF (D .LE. .3237) G2 =77.852*LOG10(D)+15.328 ! Begin Eq 58 from BPM Airfoil Self-noise and Prediction paper + IF ((D .GT. .3237).AND.(D .LE. .5689)) G2 = 65.188*LOG10(D) + 9.125 + IF ((D .GT. .5689).AND.(D .LE. 1.7579)) G2 = -114.052 * LOG10(D)**2. + IF ((D .GT. 1.7579).AND.(D .LE. 3.0889)) G2 = -65.188*LOG10(D)+9.125 + IF (D .GT. 3.0889) G2 =-77.852*LOG10(D)+15.328 ! end + ! compute angle-dependent level for shape curve + G3 = 171.04 - 3.03 * ALPSTAR ! Eq 60 from BPM Airfoil Self-noise and Prediction paper + SCALE = 10. * LOG10(DELTAP*M**5*DBARH*L/R**2) ! From Eq 53 from BPM Airfoil Self-noise and Prediction paper + ! Compute scaled sound pressure levels for each strouhal number + DO I=1,SIZE(p%FreqList) + STPRIM = p%FreqList(I) * DELTAP / U ! Eq 54 from BPM Airfoil Self-noise and Prediction paper + E = STPRIM / STPKPRM ! Used in Eq 57 from BPM Airfoil Self-noise and Prediction paper + IF (E .LE. .5974) G1 = 39.8*LOG10(E)-11.12 ! Begin Eq 57 from BPM Airfoil Self-noise and Prediction paper + IF ((E .GT. .5974).AND.(E .LE. .8545)) G1 = 98.409 * LOG10(E) + 2.0 + IF ((E .GT. .8545).AND.(E .LE. 1.17)) G1 = -5.076+SQRT(2.484-506.25*(LOG10(E))**2.) + IF ((E .GT. 1.17).AND.(E .LE. 1.674)) G1 = -98.409 * LOG10(E) + 2.0 + IF (E .GT. 1.674) G1 = -39.80*LOG10(E)-11.12 ! end + SPLLAM(I) = G1 + G2 + G3 + SCALE ! Eq 53 from BPM Airfoil Self-noise and Prediction paper + ENDDO +END SUBROUTINE LBLVS +!==================================================================================================================================! +SUBROUTINE TBLTE(ALPSTAR,C,U,THETA,PHI,L,R,p,jj,ii,kk,d99Var2,dstarVar1,dstarVar2,StallVal,SPLP,SPLS,SPLALPH,SPLTBL,errStat,errMsg) + REAL(ReKi), INTENT(IN ) :: ALPSTAR ! AOA(deg) + REAL(ReKi), INTENT(IN ) :: C ! Chord Length (m) +! REAL(ReKi), INTENT(IN ) :: U ! Unoise(m/s) +! REAL(ReKi), INTENT(IN ) :: THETA ! DIRECTIVITY ANGLE (deg) +! REAL(ReKi), INTENT(IN ) :: PHI ! DIRECTIVITY ANGLE (deg) + REAL(ReKi), INTENT(IN ) :: L ! SPAN(m) + REAL(ReKi), INTENT(IN ) :: R ! SOURCE TO OBSERVER DISTANCE (m) + +! REAL(ReKi) :: ALPSTAR ! AOA(deg) +! REAL(ReKi) :: C ! Chord Length (m) + REAL(ReKi) :: U ! Unoise(m/s) + REAL(ReKi) :: THETA ! DIRECTIVITY ANGLE (deg) + REAL(ReKi) :: PHI ! DIRECTIVITY ANGLE (deg) +! REAL(ReKi) :: L ! SPAN(m) +! REAL(ReKi) :: R ! SOURCE TO OBSERVER DISTANCE (m) + + REAL(ReKi), INTENT(IN ) :: d99Var2 ! + REAL(ReKi), INTENT(IN ) :: dstarVar1 ! + REAL(ReKi), INTENT(IN ) :: dstarVar2 ! + REAL(ReKi), INTENT(IN ) :: StallVal ! + INTEGER(IntKi), INTENT( IN) :: jj ! Error status of the operation + INTEGER(IntKi), INTENT( IN) :: ii ! Error status of the operation + + INTEGER(IntKi), INTENT( IN) :: kk ! Error status of the operation + TYPE(AA_ParameterType), INTENT(IN ) :: p ! Noise Module Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLP ! SOUND PRESSURE LEVEL DUE TO PRESSURE SIDE OF AIRFOIL (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLS ! SOUND PRESSURE LEVEL DUE TO SUCTION SIDE OF AIRFOIL (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLTBL ! TOTAL SOUND PRESSURE LEVEL DUE TO TBLTE MECHANISM (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLALPH ! SOUND PRESSURE LEVEL DUE TO ANGLE OF ATTACK CONTRIBUTION (db) + INTEGER(IntKi), INTENT( OUT) :: errStat ! Error status of the operation + character(*), INTENT( OUT) :: errMsg ! Error message if ErrStat /= ErrID_None + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'TBLTE' + ! Local variables + real(ReKi) :: STP ! PRESSURE SIDE STROUHAL NUMBER --- + real(ReKi) :: STS ! SUCTION SIDE STROUHAL NUMBER --- + real(ReKi) :: DSTRS ! SUCTION SIDE DISPLACEMENT THICKNESS METERS + real(ReKi) :: DSTRP ! PRESSURE SIDE DISPLACEMENT THICKNESS METERS + real(ReKi) :: RDSTRS ! REYNOLDS NUMBER BASED ON SUCTION SIDE DISPLACEMENT THICKNESS + real(ReKi) :: RDSTRP ! REYNOLDS NUMBER BASED ON PRESSURE SIDE DISPLACEMENT THICKNESS + real(ReKi) :: ST1 ! PEAK STROUHAL NUMBER --- + real(ReKi) :: ST2 ! PEAK STROUHAL NUMBER --- + real(ReKi) :: ST1PRIM ! PEAK STROUHAL NUMBER --- + real(ReKi) :: A0 ! FUNCTION USED IN 'A' CALCULATION + real(ReKi) :: A02 ! FUNCTION USED IN 'A' CALCULATION + real(ReKi) :: ARA0 ! INTERPOLATION FACTOR + real(ReKi) :: ARA02 ! INTERPOLATION FACTOR + real(ReKi) :: B0 ! FUNCTION USED IN 'B' CALCULATION + real(ReKi) :: BMINB0 ! MINIMUM 'B' EVALUATED AT B0 DB + real(ReKi) :: BMINB ! MINIMUM 'B' EVALUATED AT B DB + real(ReKi) :: BMAXB0 ! MAXIMUM 'B' EVALUATED AT B0 DB + real(ReKi) :: BMAXB ! MAXIMUM 'B' EVALUATED AT B DB + real(ReKi) :: BRB0 ! INTERPOLATION FACTOR DB + real(ReKi) :: STPEAK ! PEAK STROUHAL NUMBER --- + real(ReKi) :: AMINA ! MINIMUM 'A' CURVE EVALUATED AT STROUHAL NUMBER RATIO DB + real(ReKi) :: AMINB ! MINIMUM 'A' CURVE EVALUATED AT B DB + real(ReKi) :: AMAXA ! MAXIMUM 'A' CURVE EVALUATED AT STROUHAL NUMBER RATIO (DB) + real(ReKi) :: AMAXB ! MAXIMUM 'A' CURVE EVALUATED AT B DB + real(ReKi) :: AMINA0 ! MAXIMUM 'B' EVALUATED AT B0 DB + real(ReKi) :: AMINA02 ! MINIMUM 'A' CURVE EVALUATED AT A02 DB + real(ReKi) :: AMAXA0 ! MAXIMUM 'A' CURVE EVALUATED AT A0 DB + real(ReKi) :: AMAXA02 ! MAXIMUM 'A' CURVE EVALUATED AT A02 DB + real(ReKi) :: A ! STROUHAL NUMBER RATIO --- + real(ReKi) :: B ! STROUHAL NUMBER RATIO --- + real(ReKi) :: AA ! 'A' SPECTRUM SHAPE EVALUATED AT STROUHAL NUMBER RATIO DB + real(ReKi) :: BB ! 'B' SPECTRUM SHAPE EVALUATED AT STROUHAL NUMBER RATIO DB + real(ReKi) :: DELK1 ! CORRECTION TO AMPLITUDE FUNCTION DB + real(ReKi) :: GAMMA ! USED IN 'B' COMPUTATION --- + real(ReKi) :: BETA ! USED IN 'B' COMPUTATION --- + real(ReKi) :: GAMMA0 ! USED IN 'B' COMPUTATION --- + real(ReKi) :: BETA0 ! USED IN 'B' COMPUTATION --- + real(ReKi) :: K1 ! AMPLITUDE FUNCTION (DB) + real(ReKi) :: K2 ! AMPLITUDE FUNCTION (DB) + real(ReKi) :: P1 ! PRESSURE SIDE PRESSURE (NT/M2) + real(ReKi) :: P2 ! SUCTION SIDE PRESSURE (NT/M2) + real(ReKi) :: P4 ! PRESSURE FROM ANGLE OF ATTACK CONTRIBUTION (NT/M2) + real(ReKi) :: M ! MACH NUMBER + real(ReKi) :: RC ! REYNOLDS NUMBER BASED ON CHORD + real(ReKi) :: DELTAP ! PRESSURE SIDE BOUNDARY LAYER THICKNESS METERS + real(ReKi) :: XCHECK ! USED TO CHECK FOR ANGLE OF ATTACK CONTRIBUTION + real(ReKi) :: DBARH ! HIGH FREQUENCY DIRECTIVITY --- + real(ReKi) :: DBARL ! LOW FREQUENCY DIRECTIVITY --- + + integer(intKi) :: I ! I A generic index for DO loops. + + LOGICAL :: SWITCH !!LOGICAL FOR COMPUTATION OF ANGLE OF ATTACK CONTRIBUTION + + + + ErrStat = ErrID_None + ErrMsg = "" + ! Compute reynolds number and mach number + M = U / p%SpdSound + RC = U * C/p%KinVisc + ! Compute boundary layer thicknesses + IF (p%X_BLMethod .eq. 2) THEN + DELTAP = d99Var2 + DSTRS = dstarVar1 + DSTRP = dstarVar2 + ELSE + CALL THICK(C,M,RC,ALPSTAR,p,DELTAP,DSTRS,DSTRP,StallVal,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + ! Compute directivity function + CALL DIRECTL(M,THETA,PHI,DBARL,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL DIRECTH(M,THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! IF (DBARH <= 0) THEN + ! SPLP = 0. + ! SPLS = 0. + ! SPLALPH = 0. + ! RETURN + ! ENDIF + ! Calculate the reynolds numbers based on pressure and suction displacement thickness + RDSTRS = DSTRS * U / p%KinVisc + RDSTRP = DSTRP * U / p%KinVisc + ! Determine peak strouhal numbers to be used for 'a' and 'b' curve calculations + ST1 = .02 * M ** (-.6) ! Eq 32 from BPM Airfoil Self-noise and Prediction paper + ! Eq 34 from BPM Airfoil Self-noise and Prediction paper + IF (ALPSTAR .LE. 1.333) ST2 = ST1 + IF ((ALPSTAR .GT. 1.333).AND.(ALPSTAR .LE. StallVal)) ST2 = ST1*10.**(.0054*(ALPSTAR-1.333)**2.) + IF (ALPSTAR .GT. StallVal) ST2 = 4.72 * ST1 + ST1PRIM = (ST1+ST2)/2. ! Eq 33 from BPM Airfoil Self-noise and Prediction paper + CALL A0COMP(RC,A0) ! compute -20 dB dropout (returns A0) + CALL A0COMP(3.*RC,A02) ! compute -20 dB dropout for AoA > AoA_0 (returns A02) + ! Evaluate minimum and maximum 'a' curves at a0 + CALL AMIN(A0,AMINA0) + CALL AMAX(A0,AMAXA0) + CALL AMIN(A02,AMINA02) + CALL AMAX(A02,AMAXA02) + ! Compute 'a' max/min ratio ! Eq 39 from BPM Airfoil Self-noise and Prediction paper + ARA0 = (20. + AMINA0) / (AMINA0 - AMAXA0) + ARA02 = (20. + AMINA02)/ (AMINA02- AMAXA02) + ! Compute b0 to be used in 'b' curve calculations ! Eq 44 from BPM Airfoil Self-noise and Prediction paper + IF (RC .LT. 9.52E+04) B0 = .30 + IF ((RC .GE. 9.52E+04).AND.(RC .LT. 8.57E+05)) & + B0 = (-4.48E-13)*(RC-8.57E+05)**2. + .56 + IF (RC .GE. 8.57E+05) B0 = .56 + ! Evaluate minimum and maximum 'b' curves at b0 + CALL BMIN(B0,BMINB0) + CALL BMAX(B0,BMAXB0) + ! Compute 'b' max/min ratio + BRB0 = (20. + BMINB0) / (BMINB0 - BMAXB0) + + ! For each center frequency, compute an 'a' prediction for the pressure side + STPEAK = ST1 + IF (RC .LT. 2.47E+05) K1 = -4.31 * LOG10(RC) + 156.3 ! Begin Eq 47 from BPM Airfoil Self-noise and Prediction paper + IF((RC .GE. 2.47E+05).AND.(RC .LE. 8.0E+05)) K1 = -9.0 * LOG10(RC) + 181.6 + IF (RC .GT. 8.0E+05) K1 = 128.5 ! end + IF (RDSTRP .LE. 5000.) DELK1 = -ALPSTAR*(5.29-1.43*LOG10(RDSTRP)) ! Begin Eq 48 from BPM Airfoil Self-noise and Prediction paper + IF (RDSTRP .GT. 5000.) DELK1 = 0.0 ! end + + GAMMA = 27.094 * M + 3.31 ! Begin Eq 49 from BPM Airfoil Self-noise and Prediction paper + BETA = 72.650 * M + 10.74 + GAMMA0 = 23.430 * M + 4.651 + BETA0 =-34.190 * M - 13.820 ! end + + IF (ALPSTAR .LE. (GAMMA0-GAMMA)) K2 = -1000.0 ! Begin Eq 49 from BPM Airfoil Self-noise and Prediction paper + IF ((ALPSTAR.GT.(GAMMA0-GAMMA)).AND.(ALPSTAR.LE.(GAMMA0+GAMMA))) & + K2=SQRT(BETA**2.-(BETA/GAMMA)**2.*(ALPSTAR-GAMMA0)**2.)+BETA0 + IF (ALPSTAR .GT. (GAMMA0+GAMMA)) K2 = -12.0 + K2 = K2 + K1 ! end + ! Check for 'a' computation for suction side + XCHECK = GAMMA0 + SWITCH = .FALSE. + !older version: + ! IF ((ALPSTAR .GE. XCHECK).OR.(ALPSTAR .GT. 12.5))SWITCH=.TRUE. + ! newer version + IF ((ALPSTAR .GE. XCHECK).OR.(ALPSTAR .GT. StallVal))SWITCH=.TRUE. + DO I=1,size(p%FreqList) + STP= p%FreqList(I) * DSTRP / U ! Eq 31 from BPM Airfoil Self-noise and Prediction paper + A = LOG10( STP / STPEAK ) ! Eq 37 from BPM Airfoil Self-noise and Prediction paper + CALL AMIN(A,AMINA) + CALL AMAX(A,AMAXA) + AA = AMINA + ARA0 * (AMAXA - AMINA) ! Eq 40 from BPM Airfoil Self-noise and Prediction paper + + SPLP(I)=AA+K1-3.+10.*LOG10(DSTRP*M**5.*DBARH*L/R**2.)+DELK1 ! Eq 25 from BPM Airfoil Self-noise and Prediction paper + STS = p%FreqList(I) * DSTRS / U ! Eq 31 from BPM Airfoil Self-noise and Prediction paper + + IF (.NOT. SWITCH) THEN + A = LOG10( STS / ST1PRIM ) + CALL AMIN(A,AMINA) + CALL AMAX(A,AMAXA) + AA = AMINA + ARA0 * (AMAXA - AMINA) + SPLS(I) = AA+K1-3.+10.*LOG10(DSTRS*M**5.*DBARH* L/R**2.) ! Eq 26 from BPM Airfoil Self-noise and Prediction paper + ! 'B' CURVE COMPUTATION + ! B = ABS(LOG10(STS / ST2)) + B = LOG10(STS / ST2) ! abs not needed absolute taken in the AMAX,AMIN ! Eq 43 from BPM Airfoil Self-noise and Prediction paper + CALL BMIN(B,BMINB) + CALL BMAX(B,BMAXB) + BB = BMINB + BRB0 * (BMAXB-BMINB) ! Eq 46 from BPM Airfoil Self-noise and Prediction paper + SPLALPH(I)=BB+K2+10.*LOG10(DSTRS*M**5.*DBARH*L/R**2.) ! Eq 27 from BPM Airfoil Self-noise and Prediction paper + ELSE + ! The 'a' computation is dropped if 'switch' is true + SPLS(I) = 10.*LOG10(DSTRS*M**5.*DBARL*L/R**2.) + ! SPLP(I) = 0.0 + 10.*LOG10(DSTRS*M**5.*DBARL*L/R**2.) ! changed the line below because the SPLP should be calculatd with DSTRP not with DSTRS + SPLP(I) = 10.*LOG10(DSTRP*M**5.*DBARL*L/R**2.) ! this is correct + ! B = ABS(LOG10(STS / ST2)) + B = LOG10(STS / ST2) ! abs not needed absolute taken in the AMAX,AMIN + CALL AMIN(B,AMINB) + CALL AMAX(B,AMAXB) + BB = AMINB + ARA02 * (AMAXB-AMINB) + SPLALPH(I)=BB+K2+10.*LOG10(DSTRS*M**5.*DBARL*L/R**2.) + ENDIF + ! Sum all contributions from 'a' and 'b' on both pressure and suction side on a mean-square pressure basis + IF (SPLP(I) .LT. -100.) SPLP(I) = -100. ! Similar to Eq 28 of BPM Airfoil Self-noise and Prediction paper + IF (SPLS(I) .LT. -100.) SPLS(I) = -100. ! Similar to Eq 29 of BPM Airfoil Self-noise and Prediction paper + IF (SPLALPH(I) .LT. -100.) SPLALPH(I) = -100. ! Eq 30 of BPM Airfoil Self-noise and Prediction paper recommends SPLALPH = 10log(stuff) + A' + K2, where A' is calculated same as A but with x3 Rc + + P1 = 10.**(SPLP(I) / 10.) ! SPL_Pressure + P2 = 10.**(SPLS(I) / 10.) ! SPL_Suction + P4 = 10.**(SPLALPH(I) / 10.) ! SPL_AoA + SPLTBL(I) = 10. * LOG10(P1 + P2 + P4) ! Eq 24 from BPM Airfoil Self-noise and Prediction paper + + + + ENDDO + +END SUBROUTINE TBLTE +!==================================================================================================================================! +SUBROUTINE TIPNOIS(ALPHTIP,ALPRAT2,C,U ,THETA,PHI, R,p,SPLTIP, errStat, errMsg) + REAL(ReKi), INTENT(IN ) :: ALPHTIP !< AOA + REAL(ReKi), INTENT(IN ) :: ALPRAT2 !< TIP LIFT CURVE SLOPE --- + REAL(ReKi), INTENT(IN ) :: C !< Chord Length + REAL(ReKi), INTENT(IN ) :: U !< FREESTREAM VELOCITY METERS/SEC + REAL(ReKi), INTENT(IN ) :: THETA !< DIRECTIVITY ANGLE DEGREES + REAL(ReKi), INTENT(IN ) :: PHI !< DIRECTIVITY ANGLE DEGREES + REAL(ReKi), INTENT(IN ) :: R !< SOURCE TO OBSERVER DISTANCE METERS + TYPE(AA_ParameterType) , INTENT(IN ) :: p !< Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLTIP !< + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'tipnoise' + REAL(ReKi) :: M ! MACH NUMBER --- + REAL(ReKi) :: MM ! MAXIMUM MACH NUMBER --- + REAL(ReKi) :: ALPTIPP ! CORRECTED TIP ANGLE OF ATTACK DEGREES + REAL(ReKi) :: DBARH ! DIRECTIVITY --- + REAL(ReKi) :: SCALE ! SCALING TERM --- + REAL(ReKi) :: STPP ! STROUHAL NUMBER --- + REAL(ReKi) :: UM ! MAXIMUM VELOCITY METERS/SEC + REAL(ReKi) :: L ! CHARACTERISTIC LENGTH FOR TIP METERS + REAL(ReKi) :: TERM ! SCALING TERM --- + integer(intKi) :: I !I A generic index for DO loops. + ErrStat = ErrID_None + ErrMsg = "" + IF (alphtip.eq.0.) THEN + SPLTIP= 0 + RETURN + ELSEIF (alphtip.lt.0.) THEN + ! alphtip = ABS (alphtip) ! (EB_DTU) NOT possible to change inten(in) variable, INSTEAD + ! ALPTIPP is equal to abs(alphtip) - see next equation + ENDIF + !! used to be ALPTIPP = ALPHTIP * ALPRAT2 + ALPTIPP = ABS(ALPHTIP) * ALPRAT2 + M = U / p%SpdSound ! MACH NUMBER + ! Compute directivity function + CALL DIRECTH(M,THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (p%ROUND) THEN + L = .008 * ALPTIPP * C ! Eq 63 from BPM Airfoil Self-noise and Prediction paper + ELSE + IF (ABS(ALPTIPP) .LE. 2.) THEN ! not sure where this comes from + L = (.023 + .0169*ALPTIPP) * C + ELSE + L = (.0378 + .0095*ALPTIPP) * C + ENDIF + ENDIF + MM = (1. + .036*ALPTIPP) * M ! Eq 64 from BPM Airfoil Self-noise and Prediction paper + UM = MM * p%SpdSound ! Eq 65 from BPM Airfoil Self-noise and Prediction paper + TERM = M*M*MM**3.*L**2.*DBARH/R**2. ! TERM = M^2 * M_max^5 *l^2 *D / r^2 according to Semi-Empirical Aeroacoustic Noise Prediction Code for Wind Turbines paper + ! Term is correct according to Eq 61 from BPM Airfoil self-noise and Prediction paper + IF (TERM .NE. 0.0) THEN + SCALE = 10.*LOG10(TERM) + ELSE + SCALE = 0.0 + ENDIF + DO I=1,size(p%FreqList) + STPP = p%FreqList(I) * L / UM ! Eq 62 from BPM Airfoil Self-noise and Prediction paper + SPLTIP(I) = 126.-30.5*(LOG10(STPP)+.3)**2. + SCALE ! Eq 61 from BPM Airfoil Self-noise and Prediction paper + ENDDO +END SUBROUTINE TipNois +!==================================================================================================================================! +SUBROUTINE InflowNoise(AlphaNoise,Chord,U,THETA,PHI,d,RObs,MeanVNoise,TINoise,LE_Location,dissip,p,SPLti,errStat,errMsg) +! REAL(ReKi), INTENT(IN ) :: AlphaNoise ! AOA +! REAL(ReKi), INTENT(IN ) :: Chord ! Chord Length +! REAL(ReKi), INTENT(IN ) :: U ! +! REAL(ReKi), INTENT(IN ) :: d ! element span +! REAL(ReKi), INTENT(IN ) :: RObs ! distance to observer +! REAL(ReKi), INTENT(IN ) :: THETA ! +! REAL(ReKi), INTENT(IN ) :: PHI ! Spanwise directivity angle +! REAL(ReKi), INTENT(IN ) :: MeanVNoise ! +! REAL(ReKi), INTENT(IN ) :: TINoise ! +! REAL(ReKi), INTENT(IN ) :: LE_Location ! + + REAL(ReKi) :: AlphaNoise ! AOA + REAL(ReKi) :: Chord ! Chord Length + REAL(ReKi) :: U ! + REAL(ReKi) :: d ! element span + REAL(ReKi) :: RObs ! distance to observer + REAL(ReKi) :: THETA ! + REAL(ReKi) :: PHI ! Spanwise directivity angle + REAL(ReKi) :: MeanVNoise ! + REAL(ReKi) :: TINoise ! + REAL(ReKi) :: LE_Location ! + + REAL(ReKi), INTENT(IN ) :: dissip ! + TYPE(AA_ParameterType), INTENT(IN ) :: p ! Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLti ! + INTEGER(IntKi), INTENT( OUT) :: errStat ! Error status of the operation + character(*), INTENT( OUT) :: errMsg ! Error message if ErrStat /= ErrID_None + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'InflowNoise' +! local variables + REAL(ReKi) :: Beta2 ! Prandtl-Glauert correction factor + REAL(ReKi) :: DBARH ! High-frequency directivity correction factor + REAL(ReKi) :: DBARL ! Low-frequency directivity correction factor + REAL(ReKi) :: Directivity ! Directivity correction factor + REAL(ReKi) :: Frequency_cutoff ! Cutoff frequency between + REAL(ReKi) :: LFC ! low-frequency correction factor + REAL(ReKi) :: LTurb ! turbulence length scale (isotropic integral scale parameter from IEC standard (Von Karman)) + REAL(ReKi) :: Mach ! local mach number + REAL(ReKi) :: Sears ! Sears function + REAL(ReKi) :: SPLhigh ! predicted high frequency sound pressure level + REAL(ReKi) :: Ums ! mean square turbulence level + REAL(ReKi) :: WaveNumber ! wave number - non-dimensional frequency + REAL(ReKi) :: Kbar ! nafnoise + REAL(ReKi) :: khat,Kh ! nafnoise + REAL(ReKi) :: ke ! nafnoise + REAL(ReKi) :: alpstar ! nafnoise + REAL(ReKi) :: mu ! nafnoise + REAL(ReKi) :: tinooisess ! nafnoise + ! REAL(ReKi) :: L_Gammas ! nafnoise + + INTEGER(intKi) :: I !I A generic index for DO loops. + ErrStat = ErrID_None + ErrMsg = "" + + !!!--- NAF NOISE IDENTICAL + Mach = U/p%SpdSound + + ! This part is recently added for height and surface roughness dependent estimation of turbulence intensity and turbulence scales + !%Lturb=300*(Z/300)^(0.46+0.074*log(p%z0_aa)); !% Gives larger length scale + Lturb=25.d0*LE_Location**(0.35)*p%z0_aa**(-0.063) !% Gives smaller length scale ! Wei Jun Zhu, Modeling of Aerodynamically generated Noise From Wind Turbines + ! L_Gammas=0.24+0.096*log10(p%z0_aa)+0.016*(log10(p%z0_aa))**2; !% Can be computed or just give it a value. ! Wei Jun Zhu, Modeling of Aerodynamically generated Noise From Wind Turbines + !tinooisess=L_Gammas*log(30.d0/p%z0_aa)/log(LE_Location/p%z0_aa) !% F.E. 16% is 0.16 which is the correct input for SPLhIgh, no need to divide 100 ! ! Wei Jun Zhu, Modeling of Aerodynamically generated Noise From Wind Turbines + tinooisess=TINoise + + !tinooisess=0.1 + !Ums = (tinooisess*U)**2 + !Ums = (tinooisess*8)**2 + CALL DIRECTL(Mach,THETA,PHI,DBARL,errStat2,errMsg2) !yes, assume that noise is low-freq in nature because turbulence length scale is large + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL DIRECTH(Mach,THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (DBARH <= 0) THEN + SPLti = 0. + RETURN + ENDIF + + ! In the following lines, bibliography will be referenced as: a) Moriarty, Guidati, Migliore, Recent Improvement of a Semi-Empirical Aeroacoustic + ! Prediction Code for Wind Turbines + ! ref b) Lowson, Assessment and Prediction of Wind Turbine Noise + + !*********************************************** Model 1: + !!! Nafnoise source code version see below + Frequency_cutoff = 10*U/PI/Chord + Ke = 3.0/(4.0*LTurb) + Beta2 = 1-Mach*Mach + ALPSTAR = AlphaNoise*PI/180. + + DO I=1,size(p%FreqList) + IF (p%FreqList(I) <= Frequency_cutoff) THEN + Directivity = DBARL + ELSE + Directivity = DBARH + ENDIF + + WaveNumber = 2.0*PI*p%FreqList(I)/U + Kbar = WaveNumber*Chord/2.0 + Khat = WaveNumber/Ke + ! mu = Mach*WaveNumber*Chord/2.0/Beta2 + + SPLhigh = 10.*LOG10(p%AirDens*p%AirDens*p%SpdSound**4*LTurb*(d/2.)/ & + (RObs*RObs)*(Mach**5)*tinooisess*tinooisess*(Khat**3)* & + (1+Khat**2)**(-7./3.)*Directivity) + 78.4 ! ref a) + !!! SPLhigh = 10.*LOG10(LTurb*(d/2.)/ & + !!! (RObs*RObs)*(Mach**5)*tinooisess*tinooisess*(WaveNumber**3) & + !!! *(1+WaveNumber**2)**(-7./3.)*Directivity) + 181.3 + + SPLhigh = SPLhigh + 10.*LOG10(1+ 9.0*ALPSTAR*ALPSTAR) ! Component due to angles of attack, ref a) + + Sears = 1/(2.*PI*Kbar/Beta2+1/(1+2.4*Kbar/Beta2)) ! ref a) + + !!! Sears = 1/(2.*PI*WaveNumber/Beta2+1/(1+2.4*WaveNumber/Beta2)) ! ref b) + + LFC = 10*Sears*Mach*Kbar*Kbar/Beta2 ! ref a) + !!! LFC = 10*Sears*Mach*WaveNumber*WaveNumber/Beta2 ! ref b) + + !!! IF (mu<(PI/4.0)) THEN ! ref b) + !!! SPLti(I) = SPLhigh + 10.*ALOG10(LFC) ! ref b) + !!! ELSE ! ref b) + !!! SPLti(I) = SPLhigh ! ref b) + !!!ENDIF + SPLti(I) = SPLhigh + 10.*LOG10(LFC/(1+LFC)) + + ENDDO + !!!*********************************************** end of Model 1 + +! ! ********************************* Model 2: +! !Wei Jun Zhu et al - !Modeling of Aerodynamically Generated Noise From Wind Turbines 2005 paper +! Beta2 = 1.d0-Mach**2; ! corresponding line: Bsq = 1.d0 - Ma**2; +! DO I=1,size(p%FreqList) +! WaveNumber = PI*p%FreqList(I)*p%SpdSound/U !corresponding line: K = pi*Freq(i)*c/Vrel; ! CarloS: This is a Mistake, c in this case is the Local Chord +! Sears = (2.d0*PI*WaveNumber/Beta2 + (1.d0+2.4d0*WaveNumber/Beta2)**(-1))**(-1); +! ! corresponding line: Ssq = (2.d0*pi*K/Bsq + (1.d0+2.4d0*K/Bsq)**(-1))**(-1); +! LFC = 10.d0 * Sears*Mach*WaveNumber**2*Beta2**(-1); +! ! corresponding line: LFC = 10.d0 * Ssq*Ma*K**2*Bsq**(-1); +! SPLti(I)=(p%AirDens*p%AirDens*p%SpdSound*p%SpdSound*Lturb*d)/(2*RObs*RObs) +! ! SPLti(I)=SPLti(I)*(Mach**3)*(MeanVnoise**2)*(tinooisess**2) +! SPLti(I)=SPLti(I)*(Mach**3)*(tinooisess**2) +! ! SPLti(I)=SPLti(I)*(Mach**3)*ufluct**2 +! SPLti(I)=(SPLti(I)*(WaveNumber**3)) / ((1+WaveNumber**2)**(7/3)) +! SPLti(I)=SPLti(I)*DBARH +! SPLti(I)=10*log10(SPLti(I))+58.4 +! SPLti(I) = SPLti(I) + 10.*LOG10(LFC/(1+LFC)) +! ! SPLti(I)=10.d0*log10(DBARH*p%AirDens**2*p%SpdSound**2*Lturb*d/2.0*Mach**3*tinooisess**2* & +! !WaveNumber**3*(1.d0+WaveNumber**2)**(-7.d0/3.d0)/RObs**2)+58.4d0 + 10.d0*log10(LFC/(1+LFC)) +! ! corresponding line: SPLti(i)=10.d0*log10(Di_hi_fr*Density**2*co**2*Tbscale*L/2.0*Ma +! ! & **3*Tbinten**2*K**3*(1.d0+K**2)**(-7.d0/3.d0)/Distance**2)+58.4d0 +! ! & + 10.d0*log10(LFC/(1+LFC)); +! ! !% ver2.! +! ! Kh = 8.d0*pi*p%FreqList(i)*Lturb/(3.d0*U); +! ! SPLti(i) = 10*log10(DBARH*Lturb*0.5*d*Mach**5*tinooisess**2*Kh**3*(1+Kh**2)**(-7/3)/RObs**2) +& +! ! 10*log10(10**18.13) + 10*log10(DBARH*LFC/(1+LFC)); +! +! ENDDO +! ! ********************************* End of Model 2/ CarloSucameli: I think this model is wrong + + + +!!!! ! ********************************* Model 3: +!!!! ! ref b) Lowson, Assessment and Prediction of Wind Turbine Noise +!!!! Beta2 = 1.d0-Mach**2; ! corresponding line: Bsq = 1.d0 - Ma**2; +!!!! DO I=1,size(p%FreqList) +!!!! WaveNumber = PI*p%FreqList(I)*Chord/U !corresponding line: K = pi*Freq(i)*c/Vrel; +!!!! Sears = (2.d0*PI*WaveNumber/Beta2 + (1.d0+2.4d0*WaveNumber/Beta2)**(-1))**(-1); +!!!! ! corresponding line: Ssq = (2.d0*pi*K/Bsq + (1.d0+2.4d0*K/Bsq)**(-1))**(-1); +!!!! LFC = 10.d0 * Sears*Mach*WaveNumber**2*Beta2**(-1); +!!!! ! corresponding line: LFC = 10.d0 * Ssq*Ma*K**2*Bsq**(-1); +!!!! SPLti(I)=(p%AirDens*p%AirDens*p%SpdSound*p%SpdSound*Lturb*d)/(2*RObs*RObs) +!!!! SPLti(I)=SPLti(I)*(Mach**3)*(MeanVnoise**2)*(tinooisess**2) +!!!! SPLti(I)=(SPLti(I)*(WaveNumber**3)) / ((1+WaveNumber**2)**(7./3.)) +!!!! SPLti(I)=SPLti(I)*DBARH +!!!! SPLti(I)=10*log10(SPLti(I))+58.4 +!!!! SPLti(I) = SPLti(I) + 10.*LOG10(LFC/(1+LFC)) +!!!! +!!!! +!!!! ENDDO +!!!! ! ********************************* End of Model 3 + +!!Buck&Oerlamans&Palo - !Experimental validation of a wind turbine turbulent inflow noise prediction code 2016 paper +!DO I=1,size(p%FreqList) + ! IF (p%FreqList(I) <= Frequency_cutoff) THEN + ! Directivity = DBARL + ! ELSE + ! Directivity = DBARH + ! ENDIF + ! WaveNumber = 2.0*PI*p%FreqList(I)/U ! (K) + ! Kbar = WaveNumber*Chord/2.0 + ! Khat = WaveNumber/Ke + ! SPLhigh = ( (p%AirDens**2) * (p%SpdSound**2) *d ) / (2*RObs*RObs) +! SPLhigh = SPLhigh * (Mach**3) * (dissip**(2/3)) * (WaveNumber**(-5/3)) * Directivity + ! SPLhigh = 10.*LOG10(SPLhigh) + 77.6 + ! Sears = 1/(2.*PI*Kbar/Beta2+1/(1+2.4*Kbar/Beta2)) + ! LFC = 10*Sears*(1+9.0*ALPSTAR*ALPSTAR)*Mach*Kbar*Kbar/Beta2 + ! SPLti(I) = SPLhigh + 10.*LOG10(LFC/(1+LFC)) + !ENDDO + +! double commented lines are from FAST v4.0 aeroacoustics module. But Nafnoise version is used see above +!! Mach = U/p%SpdSound +!! +!!IF (TINoise > 0) THEN +!! Ums = (TINoise*MeanVNoise/100.)**2 ! mean square turbulence level +!!ELSE +!! SPLti = 0. +!! RETURN +!!ENDIF +!! +!! LTurb=60 +!! LTurb=0.06 +!!! temporarily commented +!!! IF (FASTHH < 30.0) THEN +!!! LTurb = 3.5*0.7*FASTHH ! Prediction sensitive to this parameter! +!!! ELSE +!!! LTurb = 3.5*21. +!!! ENDIF +!! +!!!LTurb = LTurb/100 +!! +!!! Calculate directivity...? +!!!!! ---------------------------- +!! CALL DIRECTL(Mach,THETA,PHI,DBARL,errStat2,errMsg2) !yes, assume that noise is low-freq in nature because turbulence length scale is large +!! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) +!! CALL DIRECTH(Mach,THETA,PHI,DBARH,errStat2,errMsg2) +!! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) +!! IF (DBARH <= 0) THEN +!! SPLti = 0. +!! RETURN +!! ENDIF +!! +!! Frequency_cutoff = 10*U/PI/Chord +!! +!! IF (DBARL <= 0.) THEN +!! SPLti = 0. +!! RETURN +!! ENDIF +!! +!!DO I=1,size(p%FreqList) +!! IF (p%FreqList(I) <= Frequency_cutoff) THEN +!! Directivity = DBARL +!! ELSE +!! Directivity = DBARH +!! ENDIF +!! WaveNumber = PI*p%FreqList(I)*Chord/U +!! Beta2 = 1-Mach*Mach +!! SPLhigh = 10.*LOG10(p%AirDens*p%AirDens*p%SpdSound*p%SpdSound*LTurb*(d/2.)/(RObs*RObs)*(Mach**3)*Ums* & +!! (WaveNumber**3)*(1+WaveNumber**2)**(-7./3.)*Directivity) + 58.4 +!! Sears = 1/(2*PI*WaveNumber/Beta2+1/(1+2.4*WaveNumber/Beta2)) +!! LFC = 10*Sears*Mach*WaveNumber*WaveNumber/Beta2 +!! SPLti(I) = SPLhigh + 10.*LOG10(LFC/(1+LFC)) +!! +!!ENDDO + +END SUBROUTINE InflowNoise +!==================================================================================================== +SUBROUTINE BLUNT(ALPSTAR,C,U ,THETA,PHI,L,R,H,PSI,p,d99Var2,dstarVar1,dstarVar2,SPLBLUNT,StallVal,errStat,errMsg) + REAL(ReKi), INTENT(IN ) :: ALPSTAR ! AOA + REAL(ReKi), INTENT(IN ) :: C ! Chord Length + REAL(ReKi), INTENT(IN ) :: U ! Unoise + REAL(ReKi), INTENT(IN ) :: THETA ! DIRECTIVITY ANGLE --- + REAL(ReKi), INTENT(IN ) :: PHI ! DIRECTIVITY ANGLE --- + REAL(ReKi), INTENT(IN ) :: L ! SPAN METERS + REAL(ReKi), INTENT(IN ) :: R ! SOURCE TO OBSERVER DISTANCE METERS + REAL(ReKi), INTENT(IN ) :: H ! TRAILING EDGE BLUNTNESS METERS + REAL(ReKi), INTENT(IN ) :: PSI ! TRAILING EDGE ANGLE DEGREES + REAL(ReKi), INTENT(IN ) :: d99Var2 ! + REAL(ReKi), INTENT(IN ) :: dstarVar1 ! + REAL(ReKi), INTENT(IN ) :: dstarVar2 ! + REAL(ReKi), INTENT(IN ) :: StallVal !< Stall angle at station i + TYPE(AA_ParameterType), INTENT(IN ) :: p ! Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLBLUNT ! + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'BLUNT' + real(ReKi) :: STPPP ! STROUHAL NUMBER --- + real(ReKi) :: M ! MACH NUMBER --- + real(ReKi) :: RC ! REYNOLDS NUMBER BASED ON CHORD --- + integer(intKi) :: I ! I A generic index for DO loops. + real(ReKi) :: DELTAP ! PRESSURE SIDE BOUNDARY LAYER THICKNESS METERS + real(ReKi) :: DSTRS ! SUCTION SIDE DISPLACEMENT THICKNESS METERS + real(ReKi) :: DSTRP ! PRESSURE SIDE DISPLACEMENT THICKNESS METERS + real(ReKi) :: DBARH ! HIGH FREQUENCY DIRECTIVITY --- + real(ReKi) :: DSTRAVG ! AVERAGE DISPLACEMENT THICKNESS METERS + real(ReKi) :: HDSTAR ! BLUNTNESS OVER AVERAGE DISPLACEMENT THICKNESS --- + real(ReKi) :: DSTARH ! AVERAGE DISPLACEMENT THICKNESS OVER TRAILING EDGE BLUNTNESS --- + real(ReKi) :: ATERM ! USED TO COMPUTE PEAK STROUHAL NO. --- + real(ReKi) :: STPEAK ! PEAK STROUHAL NUMBER --- + real(ReKi) :: ETA ! RATIO OF STROUHAL NUMBERS --- + real(ReKi) :: HDSTARL ! MINIMUM ALLOWED VALUE OF HDSTAR --- + real(ReKi) :: G514 ! G5 EVALUATED AT PSI=14.0 DB + real(ReKi) :: HDSTARP ! MODIFIED VALUE OF HDSTAR --- + real(ReKi) :: G50 ! G5 EVALUATED AT PSI=0.0 DB + real(ReKi) :: G4 ! SCALED SPECTRUM LEVEL DB + ! real(ReKi) :: G5 ! SPECTRUM SHAPE FUNCTION DB + REAL(ReKi),DIMENSION(size(p%FreqList)) :: G5 ! SPECTRUM SHAPE FUNCTION DB ! corrected (EB_DTU) + real(ReKi) :: G5Sum ! SPECTRUM SHAPE FUNCTION DB + real(ReKi) :: F4TEMP ! G5 EVALUATED AT MINIMUM HDSTARP DB + real(ReKi) :: SCALE ! SCALING FACTOR --- + + ErrStat = ErrID_None + ErrMsg = "" + + ! Reynolds number and mach number + M = U / p%SpdSound + RC = U * C/p%KinVisc + ! Compute boundary layer thicknesses + IF (p%X_BLMethod .eq. 2) THEN + DELTAP = d99Var2 + DSTRS = dstarVar1 + DSTRP = dstarVar2 + ELSE + CALL THICK(C,M,RC,ALPSTAR,p,DELTAP,DSTRS,DSTRP,StallVal,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + ! Compute average displacement thickness + DSTRAVG = (DSTRS + DSTRP) / 2. + HDSTAR = H / DSTRAVG + DSTARH = 1. /HDSTAR + ! Compute directivity function + CALL DIRECTH(M,THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (DBARH <= 0) THEN + SPLBLUNT = 0. + RETURN + ENDIF + ! Compute peak strouhal number eq 72 in BPM Airfoil Self-noise and Prediction paper + ATERM = .212 - .0045 * PSI + IF (HDSTAR .GE. .2) & + STPEAK = ATERM / (1.+.235*DSTARH-.0132*DSTARH**2.) ! this is what it used to be in nafnoise and fast noise module + !! STPEAK = ATERM / (1+0.235*(DSTARH)**(-1)-0.0132*DSTARH**(-2)) ! check if this one is correct (EB_DTU) + IF (HDSTAR .LT. .2) & + STPEAK = .1 * HDSTAR + .095 - .00243 * PSI + ! Compute scaled spectrum level eq 74 of BPM Airfoil Self-noise and Prediction paper + IF (HDSTAR .LE. 5.) G4=17.5*LOG10(HDSTAR)+157.5-1.114*PSI + IF (HDSTAR .GT. 5.) G4=169.7 - 1.114 * PSI + ! For each frequency, compute spectrum shape referenced to 0 db + SCALE = 10. * LOG10(M**5.5*H*DBARH*L/R**2.) + G5Sum=0.0_Reki + DO I=1,SIZE(p%FreqList) + STPPP = p%FreqList(I) * H / U + ETA = LOG10(STPPP/STPEAK) + HDSTARL = HDSTAR + CALL G5COMP(HDSTARL,ETA,G514,errStat2,errMsg2 ) ! compute G5 for Phi=14deg + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + HDSTARP = 6.724 * HDSTAR **2.-4.019*HDSTAR+1.107 ! eq 82 from BPM Airfoil Self-noise and Prediction paper + CALL G5COMP(HDSTARP,ETA,G50,errStat2,errMsg2 ) ! recompute G5 for Phi=0deg + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + G5(I) = G50 + .0714 * PSI * (G514-G50) ! interpolate G5 from G50 and G514 + IF (G5(I) .GT. 0.) G5(I) = 0. + G5Sum = 10**(G5(I)/10)+G5Sum ! to be subtracted + SPLBLUNT(I) = G4 + G5(I) + SCALE - 10*log10(1/G5Sum) ! equation mentioned there is plus but it is stated subtract, thus ''- 10*log10(1/G5Sum)'' + end do +END SUBROUTINE Blunt +!==================================================================================================== +SUBROUTINE G5COMP(HDSTAR,ETA,G5,errStat,errMsg) + REAL(ReKi), INTENT(IN ) :: HDSTAR !< + REAL(ReKi), INTENT(IN ) :: ETA !< + REAL(ReKi), INTENT( OUT) :: G5 !< + 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 ! temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message + CHARACTER(*), parameter :: RoutineName = 'BLUNT' + real(ReKi) :: K + real(ReKi) :: M + real(ReKi) :: MU + real(ReKi) :: ETALIMIT + real(ReKi) :: ETA0 + ErrStat = ErrID_None + ErrMsg = "" + IF ( HDSTAR .LT. .25) MU = .1211 ! begin eq 78 from BPM Airfoil Self-noise and Prediction paper + IF ((HDSTAR .GT. .25).AND.(HDSTAR .LE. .62)) MU =-.2175*HDSTAR + .1755 + IF ((HDSTAR .GT. .62).AND.(HDSTAR .LT. 1.15)) MU =-.0308*HDSTAR + .0596 + IF ( HDSTAR .GE. 1.15) MU = .0242 ! end + IF ( HDSTAR .LE. .02 ) M = 0.0 ! begin eq 79 from BPM Airfoil Self-noise and Prediction paper + IF ((HDSTAR .GE. .02 ).AND.(HDSTAR .LT. .5)) M = 68.724*HDSTAR - 1.35 + IF ((HDSTAR .GT. .5 ).AND.(HDSTAR .LE. .62)) M = 308.475*HDSTAR - 121.23 + IF ((HDSTAR .GT. .62 ).AND.(HDSTAR .LE. 1.15)) M = 224.811*HDSTAR - 69.354 + IF ((HDSTAR .GT. 1.15).AND.(HDSTAR .LT. 1.2)) M = 1583.28*HDSTAR - 1631.592 + IF ( HDSTAR .GT. 1.2 ) M = 268.344 + IF ( M .LT. 0.0 ) M = 0.0 ! end + ETA0 = -SQRT((M*M*MU**4)/(6.25+M*M*MU*MU)) ! eq 80 from BPM Airfoil Self-noise and Prediction paper + K = 2.5*SQRT(1.-(ETA0/MU)**2.)-2.5-M*ETA0 ! eq 81 from BPM Airfoil Self-noise and Prediction paper + ETALIMIT = 0.03615995 ! one of the bounds given in eq 76 of BPM Airfoil Self-noise and Prediction paper + IF (ETA .LE. ETA0) G5 = M * ETA + K ! begin eq 76 from BPM Airfoil Self-noise and Prediction paper + IF((ETA.GT.ETA0).AND.(ETA .LE. 0.)) G5 = 2.5*SQRT(1.-(ETA/MU)**2.)-2.5 + IF((ETA.GT.0. ).AND.(ETA.LE.ETALIMIT)) G5 = SQRT(1.5625-1194.99*ETA**2.)-1.25 + IF (ETA.GT.ETALIMIT) G5 = -155.543 * ETA + 4.375 ! end +END SUBROUTINE G5Comp +!==================================================================================================== +!> This subroutine defines the curve fit corresponding to the a-curve for the minimum allowed reynolds number. +SUBROUTINE AMIN(A,AMINA) + REAL(ReKi), INTENT(IN ) :: A + REAL(ReKi), INTENT(OUT ) :: AMINA + REAL(ReKi) :: X1 + X1 = ABS(A) + IF (X1 .LE. .204) AMINA=SQRT(67.552-886.788*X1**2.)-8.219 + IF((X1 .GT. .204).AND.(X1 .LE. .244))AMINA=-32.665*X1+3.981 + IF (X1 .GT. .244)AMINA=-142.795*X1**3.+103.656*X1**2.-57.757*X1+6.006 +END SUBROUTINE AMIN +!==================================================================================================== +!> This subroutine defines the curve fit corresponding to the a-curve for the maximum allowed reynolds number. +SUBROUTINE AMAX(A,AMAXA) + REAL(ReKi), INTENT(IN ) :: A + REAL(ReKi), INTENT(OUT ) :: AMAXA + REAL(ReKi) :: X1 + X1 = ABS(A) + IF (X1 .LE. .13)AMAXA=SQRT(67.552-886.788*X1**2.)-8.219 + IF((X1 .GT. .13).AND.(X1 .LE. .321))AMAXA=-15.901*X1+1.098 + IF (X1 .GT. .321)AMAXA=-4.669*X1**3.+3.491*X1**2.-16.699*X1+1.149 +END SUBROUTINE AMAX +!==================================================================================================== +!> This subroutine defines the curve fit corresponding to the b-curve for the minimum allowed reynolds number. +SUBROUTINE BMIN(B,BMINB) + REAL(ReKi), INTENT(IN ) :: B + REAL(ReKi), INTENT(OUT ) :: BMINB + REAL(ReKi) :: X1 + X1 = ABS(B) + IF (X1 .LE. .13)BMINB=SQRT(16.888-886.788*X1**2.)-4.109 + IF((X1 .GT. .13).AND.(X1 .LE. .145))BMINB=-83.607*X1+8.138 + IF (X1.GT..145)BMINB=-817.81*X1**3.+355.21*X1**2.-135.024*X1+10.619 +END SUBROUTINE BMin +!==================================================================================================== +!> Define the curve fit corresponding to the b-curve for the maximum allowed reynolds number. +SUBROUTINE BMAX(B,BMAXB) + REAL(ReKi), INTENT(IN ) :: B + REAL(ReKi), INTENT(OUT ) :: BMAXB + REAL(ReKi) :: X1 + X1 = ABS(B) + IF (X1 .LE. .1) BMAXB=SQRT(16.888-886.788*X1**2.)-4.109 + IF((X1 .GT. .1).AND.(X1 .LE. .187))BMAXB=-31.313*X1+1.854 + IF (X1.GT..187)BMAXB=-80.541*X1**3.+44.174*X1**2.-39.381*X1+2.344 +END SUBROUTINE BMax +!==================================================================================================== +!> Determine where the a-curve takes on a value of -20 db. +SUBROUTINE A0COMP(RC,A0) + REAL(ReKi), INTENT(IN ) :: RC + REAL(ReKi), INTENT(OUT ) :: A0 + IF (RC .LT. 9.52E+04) A0 = .57 + IF ((RC .GE. 9.52E+04).AND.(RC .LT. 8.57E+05)) & + A0 = (-9.57E-13)*(RC-8.57E+05)**2. + 1.13 + IF (RC .GE. 8.57E+05) A0 = 1.13 +END SUBROUTINE A0COMP +!==================================================================================================== +!> Compute zero angle of attack boundary layer thickness (meters) and reynolds number +SUBROUTINE THICK(C,M,RC,ALPSTAR,p,DELTAP,DSTRS,DSTRP,StallVal,errStat,errMsg) +!! VARIABLE NAME DEFINITION UNITS +!! ------------- ---------- ----- +!! ALPSTAR ANGLE OF ATTACK DEGREES +!! C CHORD LENGTH METERS +!! C0 SPEED OF SOUND METERS/SEC +!! DELTA0 BOUNDARY LAYER THICKNESS AT +!! ZERO ANGLE OF ATTACK METERS +!! DELTAP PRESSURE SIDE BOUNDARY LAYER +!! THICKNESS METERS +!! DSTR0 DISPLACEMENT THICKNESS AT ZERO +!! ANGLE OF ATTACK METERS +!! DSTRP PRESSURE SIDE DISPLACEMENT +!! THICKNESS METERS +!! DSTRS SUCTION SIDE DISPLACEMENT +!! THICKNESS METERS +!! ITRIP TRIGGER FOR BOUNDARY LAYER TRIPPING --- +!! M MACH NUMBER --- +!! RC REYNOLDS NUMBER BASED ON CHORD --- +!! U FREESTREAM VELOCITY METERS/SEC +!! KinViscosity KINEMATIC VISCOSITY M2/SEC + REAL(ReKi), INTENT(IN ) :: ALPSTAR !< AOA + REAL(ReKi), INTENT(IN ) :: C !< Chord Length + REAL(ReKi), INTENT(IN ) :: RC !< RC= U*C/KinViscosity + REAL(ReKi), INTENT(IN ) :: M !< M = U/C0 + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(ReKi), INTENT( OUT) :: DELTAP !< + REAL(ReKi), INTENT( OUT) :: DSTRS !< + REAL(ReKi), INTENT( OUT) :: DSTRP !< + REAL(ReKi), INTENT(IN ) :: StallVal !< Stall angle at station i + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Thick' + real(ReKi) :: DELTA0 ! BOUNDARY LAYER THICKNESS AT ZERO ANGLE OF ATTACK METERS + real(ReKi) :: DSTR0 ! DISPLACEMENT THICKNESS AT ZERO ANGLE OF ATTACK METERS + ErrStat = ErrID_None + ErrMsg = "" + ! + DELTA0 = 10.**(1.6569-.9045*LOG10(RC)+.0596*LOG10(RC)**2.)*C + IF (p%ITRIP .GT. 0) DELTA0 = 10.**(1.892-0.9045*LOG(RC)+0.0596*LOG(RC)**2.)*C + IF (p%ITRIP .EQ. 2) DELTA0=.6*DELTA0 + ! Pressure side boundary layer thickness + DELTAP = 10.**(-.04175*ALPSTAR+.00106*ALPSTAR**2.)*DELTA0 + ! Compute zero angle of attack displacement thickness + IF ((p%ITRIP .EQ. 1) .OR. (p%ITRIP .EQ. 2)) THEN + IF (RC .LE. .3E+06) DSTR0 = .0601 * RC **(-.114)*C + IF (RC .GT. .3E+06) & + DSTR0=10.**(3.411-1.5397*LOG10(RC)+.1059*LOG10(RC)**2.)*C + IF (p%ITRIP .EQ. 2) DSTR0 = DSTR0 * .6 + ELSE + DSTR0=10.**(3.0187-1.5397*LOG10(RC)+.1059*LOG10(RC)**2.)*C + ENDIF + ! Pressure side displacement thickness + DSTRP = 10.**(-.0432*ALPSTAR+.00113*ALPSTAR**2.)*DSTR0 + ! IF (p%ITRIP .EQ. 3) DSTRP = DSTRP * 1.48 ! commented since itrip is never 3 check if meant 2.(EB_DTU) + ! Suction side displacement thickness + IF (p%ITRIP .EQ. 1) THEN + IF (ALPSTAR .LE. 5.) DSTRS=10.**(.0679*ALPSTAR)*DSTR0 + IF((ALPSTAR .GT. 5.).AND.(ALPSTAR .LE. StallVal)) & + DSTRS = .381*10.**(.1516*ALPSTAR)*DSTR0 + IF (ALPSTAR .GT. StallVal)DSTRS=14.296*10.**(.0258*ALPSTAR)*DSTR0 + ELSE + IF (ALPSTAR .LE. 7.5)DSTRS =10.**(.0679*ALPSTAR)*DSTR0 + IF((ALPSTAR .GT. 7.5).AND.(ALPSTAR .LE. StallVal)) & + DSTRS = .0162*10.**(.3066*ALPSTAR)*DSTR0 + IF (ALPSTAR .GT. StallVal) DSTRS = 52.42*10.**(.0258*ALPSTAR)*DSTR0 + ENDIF +END SUBROUTINE Thick +!==================================================================================================== +!> This subroutine computes the high frequency directivity function for the input observer location +SUBROUTINE DIRECTH(M,THETA,PHI,DBAR, errStat, errMsg) + REAL(ReKi), INTENT(IN ) :: THETA ! + REAL(ReKi), INTENT(IN ) :: PHI ! + REAL(ReKi), INTENT(IN ) :: M ! + REAL(ReKi), INTENT( OUT) :: DBAR ! + 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 = 'Directh' + real(ReKi) :: MC + real(ReKi) :: DEGRAD + real(ReKi) :: PHIR + real(ReKi) :: THETAR + ErrStat = ErrID_None + ErrMsg = "" + DEGRAD = .017453 + MC = .8 * M + THETAR = THETA * DEGRAD + PHIR = PHI * DEGRAD + DBAR = 2.*SIN(THETAR/2.)**2.*SIN(PHIR)**2./((1.+M*COS(THETAR))* (1.+(M-MC)*COS(THETAR))**2.) ! eq B1 in BPM Airfoil Self-noise and Prediction paper +END SUBROUTINE DirectH +!==================================================================================================== +!> This subroutine computes the high frequency directivity function for the input observer location +! Paper: +SUBROUTINE DIRECTL(M,THETA,PHI,DBAR, errStat, errMsg) + REAL(ReKi), INTENT(IN ) :: THETA !< + REAL(ReKi), INTENT(IN ) :: PHI !< + REAL(ReKi), INTENT(IN ) :: M !< + REAL(ReKi), INTENT( OUT) :: DBAR !< + 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 = 'DirectL' + real(ReKi) :: MC + real(ReKi) :: DEGRAD + real(ReKi) :: PHIR + real(ReKi) :: THETAR + ErrStat = ErrID_None + ErrMsg = "" + ! This subroutine computes the low frequency directivity function for the input observer location + DEGRAD = .017453 + MC = .8 * M + THETAR = THETA * DEGRAD + PHIR = PHI * DEGRAD + DBAR = (SIN(THETAR)*SIN(PHIR))**2/(1.+M*COS(THETAR))**4 ! eq B2 in BPM Airfoil Self-noise and Prediction paper +END SUBROUTINE DirectL +!==================================================================================================================================! +!=============================== Simplified Guidati Inflow Turbulence Noise Addition =============================================! +!==================================================================================================================================! +! Uses simple correction for turbulent inflow noise from Moriarty et. al 2005 +! Paper: Prediction of Turbulent Inflow and Trailing-Edge Noise for Wind Turbines, by Moriarty, Guidati, and Migliore +SUBROUTINE Simple_Guidati(U,Chord,thick_10p,thick_1p,p,SPLti,errStat,errMsg) + REAL(ReKi), INTENT(IN ) :: U ! Vrel + REAL(ReKi), INTENT(IN ) :: Chord ! Chord Length + REAL(ReKi), INTENT(IN ) :: thick_10p ! + REAL(ReKi), INTENT(IN ) :: thick_1p ! + TYPE(AA_ParameterType), INTENT(IN ) :: p ! Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLti ! + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Simple_Guidati' + INTEGER(intKi) :: loop1 ! temporary + REAL(ReKi) :: TI_Param ! Temporary variable thickness ratio dependent + REAL(ReKi) :: slope ! Temporary variable thickness ratio dependent + ErrStat = ErrID_None + ErrMsg = "" + + TI_Param = thick_1p + thick_10p ! Eq 2 + slope = 1.123*TI_Param + 5.317*TI_Param*TI_Param ! Eq 3 + do loop1 =1,size(p%FreqList) + SPLti(loop1) = -slope*(2*PI*p%FreqList(loop1)*chord/U + 5.0d0) ! Eq 4 + enddo ! Outputs Delta_SPL, the difference in SPL between the airfoil and a flat plate. +END SUBROUTINE Simple_Guidati +!==================================================================================================================================! +!================================ Turbulent Boundary Layer Trailing Edge Noise ====================================================! +!=================================================== TNO START ====================================================================! +SUBROUTINE TBLTE_TNO(ALPSTAR,C,U,THETA,PHI,D,R,Cfall,d99all,EdgeVelAll,p,SPLP,SPLS,SPLALPH,SPLTBL,errStat,errMsgn) + USE TNO, only: SPL_integrate + REAL(ReKi), INTENT(IN ) :: ALPSTAR !< AOA (deg) + REAL(ReKi), INTENT(IN ) :: C !< Chord Length (m) + REAL(ReKi), INTENT(IN ) :: U !< Unoise (m/s) + REAL(ReKi), INTENT(IN ) :: THETA !< DIRECTIVITY ANGLE (deg) + REAL(ReKi), INTENT(IN ) :: PHI !< DIRECTIVITY ANGLE (deg) + REAL(ReKi), INTENT(IN ) :: D !< SPAN (m) + REAL(ReKi), INTENT(IN ) :: R !< SOURCE TO OBSERVER DISTANCE (m) + REAL(ReKi),DIMENSION(2), INTENT(IN ) :: Cfall !< Skin friction coefficient (-) + REAL(ReKi),DIMENSION(2), INTENT(IN ) :: d99all !< + REAL(ReKi),DIMENSION(2), INTENT(IN ) :: EdgeVelAll !< + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Noise Module Parameters + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT(IN ) :: SPLALPH !< SOUND PRESSURE LEVEL DUE TO ANGLE OF ATTACK CONTRIBUTION (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLP !< SOUND PRESSURE LEVEL DUE TO PRESSURE SIDE OF AIRFOIL (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLS !< SOUND PRESSURE LEVEL DUE TO SUCTION SIDE OF AIRFOIL (db) + REAL(ReKi),DIMENSION(size(p%FreqList)), INTENT( OUT) :: SPLTBL !< TOTAL SOUND PRESSURE LEVEL DUE TO TBLTE MECHANISM (db) + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + character(*), INTENT( OUT) :: errMsgn !< Error message if ErrStat /= ErrID_None + ! Local variables + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'TBLTE_TNO' + REAL(ReKi) :: answer + REAL(ReKi) :: Spectrum + REAL(ReKi) :: freq(size(p%FreqList)) + REAL(ReKi) :: SPL_press,SPL_suction + REAL(ReKi) :: band_width,band_ratio + REAL(ReKi) :: DBARH + REAL(ReKi) :: P1,P2,P4 + INTEGER (4) :: n_freq + INTEGER (4) :: i_omega + + ! Variables passed to integration routine + real(ReKi) :: int_limits(2) !< Lower and upper integration limits + real(ReKi) :: Mach !< Mach number + real(ReKi) :: omega + + ! Init + n_freq = size(p%FreqList) + freq = p%FreqList + ErrStat = ErrID_None + ErrMsgn = "" + ! Body of TNO + band_ratio = 2.**(1./3.) + + ! Mach number + Mach = U / p%SpdSound + + ! Directivity function + CALL DIRECTH(REAL(Mach),THETA,PHI,DBARH,errStat2,errMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsgn, RoutineName ) + + do i_omega = 1,n_freq + omega = 2.*pi*freq(i_omega) + !integration limits + int_limits(1) = 0.0e0 + int_limits(2) = 10*omega/(Mach*p%SpdSound) + ! Convert to third octave + band_width = freq(i_omega)*(sqrt(band_ratio)-1./sqrt(band_ratio)) * 4. * pi + IF (Cfall(1) .GT. 0.) THEN + answer = SPL_integrate(omega=omega,limits=int_limits,ISSUCTION=.true., & + Mach=Mach,SpdSound=p%SpdSound,AirDens=p%AirDens,KinVisc=p%KinVisc, & + Cfall=Cfall,d99all=d99all,EdgeVelAll=EdgeVelAll) + Spectrum = D/(4.*pi*R**2.)*answer + SPL_suction = 10.*log10(Spectrum*DBARH/2.e-5/2.e-5) + SPLS(i_omega) = SPL_suction + 10.*log10(band_width) + ENDIF + + IF (Cfall(2) .GT. 0.) THEN + answer = SPL_integrate(omega=omega,limits=int_limits,ISSUCTION=.FALSE., & + Mach=Mach,SpdSound=p%SpdSound,AirDens=p%AirDens,KinVisc=p%KinVisc, & + Cfall=Cfall,d99all=d99all,EdgeVelAll=EdgeVelAll) + Spectrum = D/(4.*pi*R**2.)*answer + SPL_press = 10.*log10(Spectrum*DBARH/2.e-5/2.e-5) + SPLP(i_omega) = SPL_press + 10.*log10(band_width) + ENDIF + + ! Sum the noise sources SPLALPH is BPM value + IF (SPLP(i_omega) .LT. -100.) SPLP(i_omega) = -100. + IF (SPLS(i_omega) .LT. -100.) SPLS(i_omega) = -100. + + P1 = 10.**(SPLP(i_omega) / 10.) + P2 = 10.**(SPLS(i_omega) / 10.) + P4 = 10.**(SPLALPH(i_omega) / 10.) + SPLTBL(i_omega) = 10. * LOG10(P1 + P2 + P4) + enddo +END SUBROUTINE TBLTE_TNO + + +!==================================================================================================== +SUBROUTINE BL_Param_Interp(p,m,U,AlphaNoise,C,whichairfoil, errStat, errMsg) + TYPE(AA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AA_MiscVarType), INTENT(INOUT) :: m !< misc/optimization data (not defined in submodules) + REAL(ReKi), INTENT(IN ) :: U !< METERS/SEC + REAL(ReKi), INTENT(IN ) :: AlphaNoise !< Angle of Attack DEG + REAL(ReKi), INTENT(IN ) :: C !< Chord METERS + integer(intKi), INTENT(IN ) :: whichairfoil !< whichairfoil + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'BL_Param_Interp' + REAL(ReKi) :: redif1,redif2,aoadif1,aoadif2,xx1,xx2,RC + INTEGER(intKi) :: loop1,loop2 + logical :: re_flag + ErrStat = ErrID_None + ErrMsg = "" + + !!!! this if is not used but if necessary two sets of tables can be populated for tripped and untripped cases + RC = U * C/p%KinVisc ! REYNOLDS NUMBER BASED ON CHORD + + re_flag = .FALSE. + DO loop1=1,size(p%ReListBL)-1 + IF ( (RC.le.p%ReListBL(loop1+1)) .and. (RC.gt.p%ReListBL(loop1)) ) then + re_flag = .TRUE. + redif1=abs(RC-p%ReListBL(loop1+1)) + redif2=abs(RC-p%ReListBL(loop1)) + DO loop2=1,size(p%AOAListBL)-1 + + if ( (AlphaNoise.le.p%AOAListBL(loop2+1)) .and. (AlphaNoise.gt.p%AOAListBL(loop2)) ) then + aoadif1=abs(AlphaNoise-p%AOAListBL(loop2+1)) + aoadif2=abs(AlphaNoise-p%AOAListBL(loop2)) + + xx1=( p%dstarall1(loop2,loop1+1,whichairfoil)*redif2+p%dstarall1(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%dstarall1(loop2+1,loop1+1,whichairfoil)*redif2+p%dstarall1(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%dstarVar(1)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%dstarall2(loop2,loop1+1,whichairfoil)*redif2+p%dstarall2(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%dstarall2(loop2+1,loop1+1,whichairfoil)*redif2+p%dstarall2(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%dstarVar(2)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%d99all1(loop2,loop1+1,whichairfoil)*redif2+p%d99all1(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%d99all1(loop2+1,loop1+1,whichairfoil)*redif2+p%d99all1(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%d99Var(1)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%d99all2(loop2,loop1+1,whichairfoil)*redif2+p%d99all2(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%d99all2(loop2+1,loop1+1,whichairfoil)*redif2+p%d99all2(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%d99Var(2)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%Cfall1(loop2,loop1+1,whichairfoil)*redif2+p%Cfall1(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%Cfall1(loop2+1,loop1+1,whichairfoil)*redif2+p%Cfall1(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%CfVar(1)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%Cfall2(loop2,loop1+1,whichairfoil)*redif2+p%Cfall2(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%Cfall2(loop2+1,loop1+1,whichairfoil)*redif2+p%Cfall2(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%CfVar(2)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%EdgeVelRat1(loop2,loop1+1,whichairfoil)*redif2+p%EdgeVelRat1(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%EdgeVelRat1(loop2+1,loop1+1,whichairfoil)*redif2+p%EdgeVelRat1(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%EdgeVelVar(1)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + xx1=( p%EdgeVelRat2(loop2,loop1+1,whichairfoil)*redif2+p%EdgeVelRat2(loop2,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + xx2=( p%EdgeVelRat2(loop2+1,loop1+1,whichairfoil)*redif2+p%EdgeVelRat2(loop2+1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%EdgeVelVar(2)=(xx1*aoadif1+xx2*aoadif2) / (aoadif1+aoadif2) + + return ! We exit the routine ! + endif + if (loop2 .eq. (size(p%AOAListBL)-1) ) then + + if (AlphaNoise .gt. p%AOAListBL(size(p%AOAListBL))) then + print*, 'Warning AeroAcoustics Module - Angle of attack (AoA) range is not in the range provided by the user' + print*, 'Station ',whichairfoil + print*, 'Airfoil AoA ',AlphaNoise,' Using the closest AoA ',p%AOAListBL(loop2+1) + m%dStarVar (1) = ( p%dstarall1 (loop2+1,loop1+1,whichairfoil)*redif2 + p%dstarall1 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%dStarVar (2) = ( p%dstarall2 (loop2+1,loop1+1,whichairfoil)*redif2 + p%dstarall2 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%d99Var (1) = ( p%d99all1 (loop2+1,loop1+1,whichairfoil)*redif2 + p%d99all1 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%d99Var (2) = ( p%d99all2 (loop2+1,loop1+1,whichairfoil)*redif2 + p%d99all2 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%CfVar (1) = ( p%Cfall1 (loop2+1,loop1+1,whichairfoil)*redif2 + p%Cfall1 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%CfVar (2) = ( p%Cfall2 (loop2+1,loop1+1,whichairfoil)*redif2 + p%Cfall2 (loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%EdgeVelVar(1) = ( p%EdgeVelRat1(loop2+1,loop1+1,whichairfoil)*redif2 + p%EdgeVelRat1(loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + m%EdgeVelVar(2) = ( p%EdgeVelRat2(loop2+1,loop1+1,whichairfoil)*redif2 + p%EdgeVelRat2(loop2+1,loop1,whichairfoil)*redif1 )/(redif1+redif2) + elseif (AlphaNoise .lt. p%AOAListBL(1)) then + print*, 'Warning AeroAcoustics Module - Angle of attack (AoA) range is not in the range provided by the user' + print*, 'Station ',whichairfoil + print*, 'Airfoil AoA ',AlphaNoise,' Using the closest AoA ',p%AOAListBL(1) + m%dStarVar(1) = ( p%dstarall1 (1,loop1+1,whichairfoil)*redif2 + p%dstarall1 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%dStarVar(2) = ( p%dstarall2 (1,loop1+1,whichairfoil)*redif2 + p%dstarall2 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%d99Var(1) = ( p%d99all1 (1,loop1+1,whichairfoil)*redif2 + p%d99all1 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%d99Var(2) = ( p%d99all2 (1,loop1+1,whichairfoil)*redif2 + p%d99all2 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%CfVar(1) = ( p%Cfall1 (1,loop1+1,whichairfoil)*redif2 + p%Cfall1 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%CfVar(2) = ( p%Cfall2 (1,loop1+1,whichairfoil)*redif2 + p%Cfall2 (1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%EdgeVelVar(1) = ( p%EdgeVelRat1(1,loop1+1,whichairfoil)*redif2 + p%EdgeVelRat1(1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + m%EdgeVelVar(2) = ( p%EdgeVelRat2(1,loop1+1,whichairfoil)*redif2 + p%EdgeVelRat2(1,loop1,whichairfoil)*redif1 ) / (redif1+redif2) + endif + endif + enddo + endif + enddo + if (.not. re_flag) then + call SetErrStat( ErrID_Fatal, 'Warning AeroAcoustics Module - the Reynolds number is not in the range provided by the user. Code stopping.', ErrStat, ErrMsg, RoutineName ) + stop + endif +END SUBROUTINE BL_Param_Interp + + +SUBROUTINE Aero_Tests() + !--------Laminar Boundary Layer Vortex Shedding Noise----------------------------! + !CALL LBLVS(AlphaNoise,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + ! elementspan,m%rTEtoObserve(K,J,I), & + ! p,m%d99Var(2),m%dstarVar(1),m%dstarVar(2),m%SPLLBL,ErrStat2,errMsg2) + !--------Turbulent Boundary Layer Trailing Edge Noise----------------------------! + !CALL TBLTE(3.0d0,0.22860d0,63.920d0,90.0d0,90.0d0,0.5090d0,1.220d0, & + ! p, m%d99Var(2),m%dstarVar(1),m%dstarVar(2),p%StallStart(J,I),m%SPLP,m%SPLS,m%SPLALPH,m%SPLTBL,ErrStat2,errMsg2 ) + !m%SPLP=0.0_ReKi;m%SPLS=0.0_ReKi;m%SPLTBL=0.0_ReKi; + !m%EdgeVelVar(1)=1.000d0;m%EdgeVelVar(2)=m%EdgeVelVar(1); + !m%CfVar(1) = 0.0003785760d0;m%CfVar(2) = 0.001984380d0;m%d99var(1)= 0.01105860d0; m%d99var(2)= 0.007465830d0;m%EdgeVelVar(1)=1.000d0;m%EdgeVelVar(2)=m%EdgeVelVar(1); + !CALL TBLTE_TNO(3.0_Reki,0.22860_Reki,63.9200_Reki,90.00_Reki,90.0_Reki,0.5090_Reki,1.220_Reki, & + ! m%CfVar,m%d99var,m%EdgeVelVar, p, m%SPLP,m%SPLS,m%SPLALPH,m%SPLTBL,ErrStat2 ,errMsg2) + !--------Blunt Trailing Edge Noise----------------------------------------------! + !CALL BLUNT(3.0d0,0.22860d0,63.920d0,90.0d0,90.0d0,0.5090d0,1.220d0,& + ! p%TEThick(J,I),p%TEAngle(J,I),p, m%d99Var(2),m%dstarVar(1),m%dstarVar(2),m%SPLBLUNT,ErrStat2,errMsg2 ) + !--------Tip Noise--------------------------------------------------------------! + !CALL TIPNOIS(AlphaNoise,p%ALpRAT,p%BlChord(J,I),UNoise,m%ChordAngleTE(K,J,I),m%SpanAngleTE(K,J,I), & + ! m%rTEtoObserve(K,J,I), p, m%SPLTIP,ErrStat2,errMsg2) + !--------Inflow Turbulence Noise ------------------------------------------------! + !CALL InflowNoise(3.0d0,0.22860d0,63.920d0,90.0d0,90.0d0,0.5090d0,1.220d0, & + ! xd%MeanVrel(J,I),0.050d0,0.050d0,p,m%SPLti,ErrStat2,errMsg2 ) + !CALL FullGuidati(3.0d0,63.920d0,0.22860d0,0.5090d0,1.220d0,90.0d0,90.0d0,xd%MeanVrel(J,I),xd%TIVrel(J,I), & + ! p,p%BlAFID(J,I),m%SPLTIGui,ErrStat2 ) + !CALL Simple_Guidati(UNoise,0.22860d0,0.120d0,0.020d0,p,m%SPLTIGui,ErrStat2,errMsg2 ) +END SUBROUTINE +END MODULE AeroAcoustics + diff --git a/OpenFAST/modules/aerodyn/src/AeroAcoustics_IO.f90 b/OpenFAST/modules/aerodyn/src/AeroAcoustics_IO.f90 new file mode 100644 index 000000000..76e4e02c6 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroAcoustics_IO.f90 @@ -0,0 +1,988 @@ +!********************************************************************************************************************************** +! File last committed: 2020-02-12 +!********************************************************************************************************************************** +MODULE AeroAcoustics_IO + + use NWTC_Library + use AeroAcoustics_Types + + implicit none + + type(ProgDesc), parameter :: AA_Ver = ProgDesc( 'AeroAcoustics', 'v1.00.00', '18-Aug-2016' ) + character(*), parameter :: AA_Nickname = 'AA' + + + + INTEGER(IntKi), PARAMETER :: Time = 0 + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + INTEGER(IntKi), PARAMETER :: MaxBl = 3 ! Maximum number of blades allowed in simulation + + ! model identifiers + integer(intKi), parameter :: ModelUnknown = -1 + +! FLAG TO COMPUTE BLUNTNESS NOISE = 0 No, =1 Yes + integer(intKi), parameter :: IBLUNT_None = 0 + integer(intKi), parameter :: IBLUNT_BPM = 1 + +! FLAG TO COMPUTE Laminar Boundary Layer Noise = 0 No, =1 Yes + integer(intKi), parameter :: ILAM_None = 0 ! steady model + integer(intKi), parameter :: ILAM_BPM = 1 ! + +! FLAG TO COMPUTE Tip Noise = 0 No, =1 Yes + integer(intKi), parameter :: ITIP_None = 0 ! + integer(intKi), parameter :: ITIP_On = 1 ! + + integer(intKi), parameter :: ITRIP_None = 0 ! not tripped boundary layer + integer(intKi), parameter :: ITRIP_Heavy = 1 ! heavily tripped boundary layer + integer(intKi), parameter :: ITRIP_Light = 2 ! light tripped boundary layer + +! calculation method for boundary layer properties, = 1 BPM = 2 Pretabulated BL values + integer(intKi), parameter :: X_BLMethod_BPM = 1 ! + integer(intKi), parameter :: X_BLMethod_Tables = 2 ! + + integer(intKi), parameter :: TICalc_Interp = 1 ! interpolate from pretabulated + integer(intKi), parameter :: TICalc_Every = 2 ! calculate ti automatically + + integer(intKi), parameter :: ITURB_None = 0 ! TBLTE noise is not calculated + integer(intKi), parameter :: ITURB_BPM = 1 ! TBLTE noise is calculated with BPM + integer(intKi), parameter :: ITURB_TNO = 2 ! TBLTE noise is calculated with TNO + + integer(intKi), parameter :: IInflow_None = 0 ! IInflow noise is not calculated + integer(intKi), parameter :: IInflow_BPM = 1 ! IInflow noise is calculated with BPM + integer(intKi), parameter :: IInflow_FullGuidati = 2 ! IInflow noise is calculated with FullGuidati + integer(intKi), parameter :: IInflow_SimpleGuidati = 3 ! IInflow noise is calculated with SimpleGuidati + +contains +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadInputFiles( InputFileName, BL_Files, InputFileData, Default_DT, OutFileRoot, NumBlades, UnEcho, ErrStat, ErrMsg ) + ! This subroutine reads the input file and stores all the data in the AA_InputFile structure. + ! It does not perform data validation. + !.................................................................................................................................. + ! Passed variables + REAL(DbKi), INTENT(IN) :: Default_DT ! The default DT (from glue code) + CHARACTER(*), INTENT(IN) :: InputFileName ! Name of the aeroacoustics input file + CHARACTER(*), dimension(:), INTENT(IN) :: BL_Files ! Name of the BL input file + CHARACTER(*), INTENT(IN) :: OutFileRoot ! The rootname of all the output files written by this routine. + TYPE(AA_InputFile), INTENT(OUT) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi), INTENT(IN) :: NumBlades ! Number of blades for this model + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + ! local variables + INTEGER(IntKi) :: I + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(1024) :: AABlFile(MaxBl) ! File that contains the blade information (specified in the primary input file) + CHARACTER(*), PARAMETER :: RoutineName = 'ReadInputFiles' + ! initialize values: + ErrStat = ErrID_None + ErrMsg = '' + UnEcho = -1 + + + ! Reads the module input-file data + CALL ReadPrimaryFile( InputFileName, InputFileData, AABlFile, Default_DT, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) + if(Failed()) return + + ! get the blade input-file data + ALLOCATE( InputFileData%BladeProps( NumBlades ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for BladeProps.", ErrStat, ErrMsg, RoutineName) + return + END IF + + do i = 1,NumBlades + CALL ReadBladeInputs ( AABlFile(i), InputFileData%BladeProps(i), UnEcho, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName//TRIM(':Blade')//TRIM(Num2LStr(I))) + if(Failed()) return + end do + + if ((InputFileData%ITURB.eq.2) .or. (InputFileData%X_BLMethod.eq.2)) then + ! We need to read the BL tables + CALL ReadBLTables( InputFileName, BL_Files, InputFileData, InputFileData%BladeProps(1)%NumBlNds, ErrStat2, ErrMsg2 ) + if (Failed())return + endif + + IF( (InputFileData%TICalcMeth.eq.1) ) THEN + CALL REadTICalcTables(InputFileName,InputFileData, ErrStat2, ErrMsg2); if(Failed()) return + ENDIF + +CONTAINS + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed + +END SUBROUTINE ReadInputFiles +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary Noise input file and places the values it reads in the InputFileData structure. +! It opens and prints to an echo file if requested. +SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, AABlFile, Default_DT, OutFileRoot, UnEc, ErrStat, ErrMsg ) + integer(IntKi), intent(out) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + integer(IntKi), intent(out) :: ErrStat ! Error status + REAL(DbKi), INTENT(IN) :: Default_DT ! The default DT (from glue code) + character(*), intent(out) :: AABlFile(MaxBl) ! name of the files containing blade inputs + character(*), intent(in) :: InputFile ! Name of the file containing the primary input data + character(*), intent(out) :: ErrMsg ! Error message + character(*), intent(in) :: OutFileRoot ! The rootname of the echo file, possibly opened in this routine + type(AA_InputFile), intent(inout) :: InputFileData ! All the data in the Noise input file + ! Local variables: + real(ReKi) :: TmpAry(3) ! array to help read tower properties table + integer(IntKi) :: I ! loop counter + integer(IntKi) :: UnIn,UnIn2 ! Unit number for reading file + integer(IntKi) :: loop1 ! loop counter + character(1024) :: ObserverFile ! name of the files containing obesever location + integer(IntKi) :: ErrStat2, IOS,cou ! Temporary Error status + logical :: Echo ! Determines if an echo file should be written + character(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(1024) :: PriPath ! Path name of the primary file + character(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + character(*), parameter :: RoutineName = 'ReadPrimaryFile' + integer(IntKi) :: n ! dummy integer + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + ! Open the Primary input file. + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ); call check + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ); call check + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + I = 1 !set the number of times we've read the file + DO + !----------- HEADER ------------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ); call check + CALL ReadStr( UnIn, InputFile, InputFileData%FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ); call check + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !----------- GENERAL OPTIONS ---------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: General Options', ErrStat2, ErrMsg2, UnEc ); call check + ! Echo - Echo input to "<RootName>.AD.ech". + CALL ReadVar( UnIn, InputFile, Echo, 'Echo', 'Echo flag', ErrStat2, ErrMsg2, UnEc); call check + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, AA_Ver ); call check + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(AA_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + END DO + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr( ' Heading of the '//TRIM(AA_Ver%Name)//' input file: ' ) + CALL WrScr( ' '//TRIM( InputFileData%FTitle ) ) + END IF + + ! DT_AA - Time interval for aerodynamic calculations {or default} (s): + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "DT_AA", "Time interval for aeroacoustics calculations {or default} (s)", ErrStat2, ErrMsg2, UnEc); call check + CALL Conv2UC( Line ) + + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If DT_AA is not "default", read it and make sure it is a multiple of DTAero from AeroDyn. Else, just use DTAero + READ( Line, *, IOSTAT=IOS) InputFileData%DT_AA + CALL CheckIOS ( IOS, InputFile, 'DT_AA', NumType, ErrStat2, ErrMsg2 ); call check + + IF (abs(InputFileData%DT_AA / Default_DT - NINT(InputFileData%DT_AA / Default_DT)) .gt. 1E-10) THEN + CALL SetErrStat(ErrID_Fatal,"The Aeroacoustics input DT_AA must be a multiple of DTAero.", ErrStat, ErrMsg, RoutineName) + return + END IF + ELSE + InputFileData%DT_AA = Default_DT + END IF + + CALL ReadVar(UnIn,InputFile,InputFileData%AAStart ,"AAStart" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%AA_Bl_Prcntge,"BldPrcnt" ,"-",ErrStat2,ErrMsg2,UnEc); call check + CALL ReadCom( UnIn, InputFile, 'Section Header: Aeroacoustic Models', ErrStat2, ErrMsg2, UnEc ); call check + CALL ReadVar(UnIn,InputFile,InputFileData%IInflow ,"InflowMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%TICalcMeth ,"TICalcMeth" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVAr(UnIn,InputFile,InputFileData%TICalcTabFile,"TICalcTabFile","" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%z0_AA ,"SurfRoughness","" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ITURB ,"TurbMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check ! ITURB - TBLTE NOISE + CALL ReadVar(UnIn,InputFile,InputFileData%X_BLMethod ,"BLMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ITRIP ,"TripMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ILAM ,"LamMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ITIP ,"TipMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ROUND ,"RoundTip" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%ALPRAT ,"ALPRAT" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar(UnIn,InputFile,InputFileData%IBLUNT ,"BluntMod" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + + ! AABlFile - Names of files containing distributed aerodynamic properties for each blade (see AA_BladeInputFile type): + DO I = 1,MaxBl + CALL ReadVar ( UnIn, InputFile, AABlFile(I), 'AABlFile('//TRIM(Num2Lstr(I))//')', 'Name of file containing distributed aerodynamic properties for blade '//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ); call check + IF ( PathIsRelative( AABlFile(I) ) ) AABlFile(I) = TRIM(PriPath)//TRIM(AABlFile(I)) + END DO + + ! Return on error at end of section + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !----------- OBSERVER INPUT ------------------------------ + CALL ReadCom( UnIn, InputFile, 'Section Header: Observer Input ', ErrStat2, ErrMsg2, UnEc ); call check + !----- read from observer file + CALL ReadVar ( UnIn, InputFile, ObserverFile, ObserverFile, 'Name of file observer locations', ErrStat2, ErrMsg2, UnEc ); call check + IF ( PathIsRelative( ObserverFile ) ) ObserverFile = TRIM(PriPath)//TRIM(ObserverFile) + + CALL GetNewUnit( UnIn2, ErrStat2, ErrMsg2 ); call check + + CALL OpenFInpFile ( UnIn2, ObserverFile, ErrStat2, ErrMsg2 ); call check + IF ( ErrStat >= AbortErrLev ) RETURN + + ! NrObsLoc - Nr of Observers (-): + CALL ReadVar( UnIn2, ObserverFile, InputFileData%NrObsLoc, "NrObsLoc", "Nr of Observers (-)", ErrStat2, ErrMsg2, UnEc); call check + + ! Observer location in tower-base coordinate (m): + CALL AllocAry( InputFileData%ObsX,InputFileData%NrObsLoc, 'ObsX', ErrStat2, ErrMsg2); call check + CALL AllocAry( InputFileData%ObsY,InputFileData%NrObsLoc, 'ObsY', ErrStat2, ErrMsg2); call check + CALL AllocAry( InputFileData%ObsZ,InputFileData%NrObsLoc, 'ObsZ', ErrStat2, ErrMsg2); call check + + CALL ReadCom( UnIn2, InputFile, ' Header', ErrStat2, ErrMsg2, UnEc ); call check + + DO cou=1,InputFileData%NrObsLoc + READ( UnIn2, *, IOStat=IOS ) InputFileData%ObsX(cou), InputFileData%ObsY(cou), InputFileData%ObsZ(cou) + CALL CheckIOS( IOS, ObserverFile, 'Obeserver Locations '//TRIM(Num2LStr(cou)), NumType, ErrStat2, ErrMsg2 ); call check + ! Return on error if we couldn't read this line + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + ENDDO + CLOSE ( UnIn2 ) + !----- end read from observer file + + !----------- OUTPUTS ----------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Outputs', ErrStat2, ErrMsg2, UnEc); call check + CALL ReadVar( UnIn,InputFile,InputFileData%aweightflag ,"AWeighting" ,"" ,ErrStat2,ErrMsg2,UnEc); call check + CALL ReadVar( UnIn, InputFile, InputFileData%NrOutFile, "NrOutFile", "Nr of Output Files (-)", ErrStat2, ErrMsg2, UnEc); call check + CALL AllocAry( InputFileData%AAOutFile,InputFileData%NrOutFile, 'AAOutFile', ErrStat2, ErrMsg2); call check + CALL ReadVar ( UnIn, InputFile, InputFileData%AAOutFile(1), 'AAOutFile', 'Name of output file ', ErrStat2, ErrMsg2, UnEc ); call check + DO I=InputFileData%NrOutFile,1,-1 + ! one file name is given by the user and the XXFile1.out XXFile2.out XXFile3.out is generated + IF ( PathIsRelative( InputFileData%AAOutFile(I) ) ) InputFileData%AAOutFile(I) = TRIM(PriPath)//TRIM(InputFileData%AAOutFile(1))//TRIM(Num2Lstr(I))//".out" + ENDDO + + ! Return on error at end of section + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + !---------------------- END OF FILE ----------------------------------------- + CALL Cleanup( ) + +CONTAINS + SUBROUTINE Check() + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE Check + + !............................................................................................................................... + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE ( UnIn ) + END SUBROUTINE Cleanup + !............................................................................................................................... +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads a blade input file. +SUBROUTINE ReadBladeInputs ( AABlFile, BladeKInputFileData, UnEc, ErrStat, ErrMsg ) + TYPE(AA_BladePropsType), INTENT(INOUT) :: BladeKInputFileData ! Data for Blade K stored in the module's input file + CHARACTER(*), INTENT(IN) :: AABlFile ! Name of the blade input file data + INTEGER(IntKi), INTENT(IN) :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + ! Local variables: + INTEGER(IntKi) :: I ! A generic DO index. + INTEGER( IntKi ) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 , IOS ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName = 'ReadBladeInputs' + ErrStat = ErrID_None + ErrMsg = "" + UnIn = -1 + ! Allocate space for these variables + CALL GetNewUnit (UnIn, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL OpenFInpFile (UnIn, AABlFile, ErrStat2, ErrMsg2 ); if(Failed()) return + ! -------------- HEADER ------------------------------------------------------- + ! Skip the header. + CALL ReadCom ( UnIn, AABlFile, 'unused blade file header line 1', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, AABlFile, 'unused blade file header line 2', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ! -------------- Blade properties table ------------------------------------------ + CALL ReadCom ( UnIn, AABlFile, 'Section header: Blade Properties', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ! NumBlNds - Number of blade nodes used in the analysis (-): + CALL ReadVar( UnIn, AABlFile, BladeKInputFileData%NumBlNds, "NumBlNds", "Number of blade nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc); if(Failed()) return + CALL ReadCom ( UnIn, AABlFile, 'Table header: names', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, AABlFile, 'Table header: units', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ! allocate space for blade inputs: + CALL AllocAry(BladeKInputFileData%TEAngle ,BladeKInputFileData%NumBlNds,'TEAngle' ,ErrStat2,ErrMsg2); if(Failed()) return + CALL AllocAry(BladeKInputFileData%TEThick ,BladeKInputFileData%NumBlNds,'TEThick' ,ErrStat2,ErrMsg2); if(Failed()) return + CALL AllocAry(BladeKInputFileData%StallStart,BladeKInputFileData%NumBlNds,'StallStart',ErrStat2,ErrMsg2); if(Failed()) return + DO I=1,BladeKInputFileData%NumBlNds + READ( UnIn, *, IOStat=IOS ) BladeKInputFileData%TEAngle(I), BladeKInputFileData%TEThick(I) + CALL CheckIOS( IOS, AABlFile, 'Blade properties row '//TRIM(Num2LStr(I)), NumType, ErrStat2, ErrMsg2); if(Failed()) return + IF (UnEc > 0) THEN + WRITE( UnEc, "(6(F9.4,1x),I9)", IOStat=IOS) BladeKInputFileData%TEAngle(I), BladeKInputFileData%TEThick(I) + END IF + END DO + ! -------------- END OF FILE -------------------------------------------- + CALL Cleanup() +CONTAINS + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE(UnIn) + END SUBROUTINE Cleanup +END SUBROUTINE ReadBladeInputs + +! ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +subroutine ReadRealMatrix(fid, FileName, Mat, VarName, nLines,nRows, iStat, Msg, iLine ) + integer, intent(in) :: fid + real(DbKi), dimension(:,:), allocatable :: Mat + character(len=*), intent(in) :: FileName + character(len=*), intent(in) :: VarName + integer, intent(in) :: nLines + integer, intent(in) :: nRows + integer, intent(out) :: iStat + integer, intent(inout) :: iLine + character(len=*), intent(inout) :: Msg + ! local variables + integer :: i + if (allocated(Mat)) deallocate(Mat) + call allocAry( Mat, nLines, nRows, VarName, iStat, Msg); + if (iStat /= 0) return + !Read Stiffness + DO I =1,nLines + iLine=iLine+1 + ! TODO use ReadCAryFromStr when available in the NWTCIO, it performs more checks + CALL ReadAry( fid, FileName, Mat(I,:), nRows, trim(VarName)//' Line '//Num2LStr(iLine), VarName, iStat, Msg) ! From NWTC_Library + if (iStat /= 0) return + ENDDO +end subroutine + + + +SUBROUTINE ReadBLTables( InputFile,BL_Files,InputFileData, nAirfoils, ErrStat, ErrMsg ) + ! Passed variables + character(*), intent(in) :: InputFile ! Name of the file containing the primary input data + character(*), dimension(:), intent(in) :: BL_Files ! Name of the file containing the primary input data +type(AA_InputFile), intent(inout) :: InputFileData ! All the data in the Noise input file + integer(IntKi), intent(in) :: nAirfoils ! Number of Airfoil tables + integer(IntKi), intent(out) :: ErrStat ! Error status + character(*), intent(out) :: ErrMsg ! Error message + ! Local variables: + integer(IntKi) :: UnIn,UnIn2 ! Unit number for reading file + character(1024) :: FileName ! name of the files containing obesever location + integer(IntKi) :: ErrStat2 ! Temporary Error status + logical :: Echo ! Determines if an echo file should be written + character(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(1024) :: PriPath ! Path name of the primary file + character(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + character(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + character(*), parameter :: RoutineName = 'readbltable' + integer(IntKi) :: nRe, nAoA ! Number of Reynolds number and angle of attack listed + integer(IntKi) :: iAF , iRe, iAoA, iDummy, iBuffer ! loop counters + real(DbKi),dimension(:,:),ALLOCATABLE :: Buffer + integer :: iLine + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + do iAF=1,nAirfoils + + FileName = trim(BL_Files(iAF)) + + print*,'AeroAcoustics_IO: reading BL table:'//trim(Filename) + + CALL GetNewUnit(UnIn, ErrStat2, ErrMsg2); if(Failed()) return + CALL OpenFInpFile(UnIn, FileName, ErrStat2, ErrMsg2); if(Failed()) return + + CALL ReadCom(UnIn, FileName, "! Boundary layer", ErrStat2, ErrMsg2); if(Failed()) return + CALL ReadCom(UnIn, FileName, "! Legend: aoa", ErrStat2, ErrMsg2); if(Failed()) return + + CALL ReadVar(UnIn, FileName, nRe, "ReListBL", "", ErrStat2, ErrMsg2); if(Failed()) return + CALL ReadVar(UnIn, FileName, nAoA, "aoaListBL", "", ErrStat2, ErrMsg2); if(Failed()) return + + if (iAF==1) then + CALL AllocAry(InputFileData%Pres_DispThick ,nAoA,nRe,nAirfoils,'InputFileData%Pres_DispThick' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Suct_DispThick ,nAoA,nRe,nAirfoils,'InputFileData%Suct_DispThick' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Pres_BLThick ,nAoA,nRe,nAirfoils,'InputFileData%Pres_BLThick' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Suct_BLThick ,nAoA,nRe,nAirfoils,'InputFileData%Suct_BLThick' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Pres_Cf ,nAoA,nRe,nAirfoils,'InputFileData%Pres_Cf' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Suct_Cf ,nAoA,nRe,nAirfoils,'InputFileData%Suct_Cf' ,ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Pres_EdgeVelRat,nAoA,nRe,nAirfoils,'InputFileData%Pres_EdgeVelRat',ErrStat2,ErrMsg2); if (Failed())return + CALL AllocAry(InputFileData%Suct_EdgeVelRat,nAoA,nRe,nAirfoils,'InputFileData%Suct_EdgeVelRat',ErrStat2,ErrMsg2); if (Failed())return + + CALL AllocAry(InputFileData%ReListBL,nRe,'InputFileData%ReListBL',ErrStat2,ErrMsg2); if (Failed())return + + + CALL AllocAry(Buffer,nAoA,9, 'Buffer', ErrStat2, ErrMsg2); if(Failed()) return + endif + iLine=8 + do iRe=1,nRe + CALL ReadVar(UnIn, FileName, InputFileData%ReListBL(iRe), 'InputFileData%ReListBL','ReListBL', ErrStat2, ErrMsg2); if(Failed()) return + InputFileData%ReListBL(iRe) = InputFileData%ReListBL(iRe) * 1.e+006 + CALL ReadCom(UnIn, FileName, "aoa Ue_Vinf_SS Ue_Vinf_PS Dstar_SS Dstar_PS Theta_SS Theta_PS Cf_SS Cf_PS", ErrStat2, ErrMsg2); if(Failed()) return + CALL ReadCom(UnIn, FileName, "(deg) (-) (-) (-) (-) (-) (-) (-) (-)", ErrStat2, ErrMsg2); if(Failed()) return + + call ReadRealMatrix(UnIn, FileName, Buffer, 'BL Matrix', nAoA, 9, ErrStat2, ErrMsg2, iLine) + + if(Failed()) return + do iAoA=1,nAoA + InputFileData%Suct_EdgeVelRat(iAoA,iRe,iAF)= Buffer(iAoA, 2) ! EdgeVelRat1 Suction + InputFileData%Pres_EdgeVelRat(iAoA,iRe,iAF)= Buffer(iAoA, 3) ! EdgeVelRat2 Pressure + InputFileData%Suct_DispThick (iAoA,iRe,iAF)= Buffer(iAoA, 4) ! dStarAll1 Suction + InputFileData%Pres_DispThick (iAoA,iRe,iAF)= Buffer(iAoA, 5) ! dStarAll2 Pressure + InputFileData%Suct_BLThick (iAoA,iRe,iAF)= Buffer(iAoA, 6) ! d99All1 Suction + InputFileData%Pres_BLThick (iAoA,iRe,iAF)= Buffer(iAoA, 7) ! d99All2 Pressure + InputFileData%Suct_Cf (iAoA,iRe,iAF)= Buffer(iAoA, 8) ! CfAll1 Suction + InputFileData%Pres_Cf (iAoA,iRe,iAF)= Buffer(iAoA, 9) ! CfAll2 Pressure + enddo + enddo + + if (iAF == 1) then + CALL AllocAry(InputFileData%AoAListBL,nAoA, 'InputFileData%AoAListBL', ErrStat2, ErrMsg2); if(Failed()) return + do iAoA=1,nAoA + InputFileData%AoAListBL(iAoA)= Buffer(iAoA, 1) ! AoA + enddo + endif + if (UnIn > 0) CLOSE(UnIn) + + enddo + CALL Cleanup( ) +CONTAINS + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE ( UnIn ) + END SUBROUTINE Cleanup +END SUBROUTINE ReadBLTables +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadTICalcTables(InputFile, InputFileData, ErrStat, ErrMsg) + ! Passed variables + integer(IntKi), intent(out) :: ErrStat ! Error status + character(*), intent(out) :: ErrMsg ! Error message + type(AA_InputFile), intent(inout) :: InputFileData ! All the data in the Noise input file + character(*), intent(in) :: InputFile ! Name of the file containing the primary input data + ! Local variables: + integer(IntKi) :: I ! loop counter + integer(IntKi) :: UnIn,UnIn2 ! Unit number for reading file + integer(IntKi) :: loop1 ! loop counter + character(1024) :: FileName ! name of the files containing obesever location + integer(IntKi) :: ErrStat2, IOS,cou ! Temporary Error status + logical :: Echo ! Determines if an echo file should be written + character(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(1024) :: PriPath ! Path name of the primary file + character(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + character(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + character(*), parameter :: RoutineName = 'REadTICalcTables' + integer(IntKi) :: GridY ! + integer(IntKi) :: GridZ ! + integer(IntKi) :: cou1 + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + FileName = TRIM(PriPath)//InputFileData%TICalcTabFile + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2); call check() + CALL OpenFInpFile ( UnIn, FileName, ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL ReadCom(UnIn, FileName, 'Text Line', ErrStat2, ErrMsg2); call check + CALL ReadVar(UnIn, FileName, GridY, 'GridY', 'Echo flag', ErrStat2, ErrMsg2); call check + CALL ReadCom(UnIn, FileName, 'Text Line', ErrStat2, ErrMsg2);call check + CALL ReadVar(UnIn, FileName, GridZ, 'GridZ', 'Echo flag', ErrStat2, ErrMsg2); call check + CALL ReadCom(UnIn, FileName, 'Text Line', ErrStat2, ErrMsg2); call check + CALL ReadVar(UnIn, FileName, InputFileData%dy_turb_in, 'InputFileData%dy_turb_in', 'Echo flag', ErrStat2, ErrMsg2); call check + CALL ReadCom(UnIn, FileName, 'Text Line', ErrStat2, ErrMsg2); call check + CALL ReadVar(UnIn, FileName, InputFileData%dz_turb_in, 'InputFileData%dz_turb_in', 'Echo flag', ErrStat2, ErrMsg2); call check + if(Failed()) return + + CALL AllocAry( InputFileData%TI_Grid_In,GridZ,GridY,'InputFileData%TI_Grid_In', ErrStat2, ErrMsg2); + if(Failed()) return + DO cou1=1,size(InputFileData%TI_Grid_In,1) + read(UnIn,*) InputFileData%TI_Grid_In(cou1,:) + ENDDO + !---------------------- END OF FILE ----------------------------------------- + CALL Cleanup( ) + +CONTAINS + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + SUBROUTINE Check() + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE Check + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE ( UnIn ) + END SUBROUTINE Cleanup +END SUBROUTINE REadTICalcTables +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the AeroDyn input files. +SUBROUTINE ValidateInputData( InputFileData, NumBl, ErrStat, ErrMsg ) + type(AA_InputFile), intent(in) :: InputFileData !< All the data in the AeroDyn input file + integer(IntKi), intent(in) :: NumBl !< Number of blades + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + ! local variables + integer(IntKi) :: k ! Blade number + integer(IntKi) :: j ! node number + character(*), parameter :: RoutineName = 'ValidateInputData' + ErrStat = ErrID_None + ErrMsg = "" + if (NumBl > MaxBl .or. NumBl < 1) call SetErrStat( ErrID_Fatal, 'Number of blades must be between 1 and '//trim(num2lstr(MaxBl))//'.', ErrSTat, ErrMsg, RoutineName ) + if (InputFileData%DT_AA <= 0.0) call SetErrStat ( ErrID_Fatal, 'DT_AA must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%IBLUNT /= IBLUNT_None .and. InputFileData%IBLUNT /= IBLUNT_BPM) then + call SetErrStat ( ErrID_Fatal, & + 'IBLUNT must '//trim(num2lstr(IBLUNT_None))//' (none) or '//trim(num2lstr(IBLUNT_BPM))//' (Bluntness noise calculated).', ErrStat, ErrMsg, RoutineName ) + endif + if (InputFileData%ILAM /= ILAM_None .and. InputFileData%ilam /= ILAM_BPM) then + call SetErrStat ( ErrID_Fatal, 'ILAM must be '//trim(num2lstr(ILAM_None))//' No calculation '//& + trim(num2lstr(ILAM_BPM))//' (ILAM Calculated).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%ITIP /= ITIP_None .and. InputFileData%ITIP /= ITIP_ON) then + call SetErrStat ( ErrID_Fatal, 'ITIP must be '//trim(num2lstr(ITIP_None))//' (Off) or '//& + trim(num2lstr(ITIP_On))//' (ITIP On).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%ITRIP /= ITRIP_None .and. InputFileData%ITRIP /= ITRIP_Heavy .and. InputFileData%ITRIP /= ITRIP_Light) then + call SetErrStat ( ErrID_Fatal,'ITRIP must be '//trim(num2lstr(ITRIP_None))//' (none) or '//trim(num2lstr(ITRIP_Heavy))//& + ' (heavily tripped BL Calculation) or '//trim(num2lstr(ITRIP_Light))//' (lightly tripped BL)' ,ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%ITURB /= ITURB_None .and. InputFileData%ITURB /= ITURB_BPM .and. InputFileData%ITURB /= ITURB_TNO) then + call SetErrStat ( ErrID_Fatal, 'ITURB must be 0 (off) or 1 (BPM) or 2 (TNO) .', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%IInflow /= IInflow_None .and. InputFileData%IInflow /= IInflow_BPM & + .and. InputFileData%IInflow /= IInflow_FullGuidati .and. InputFileData%IInflow /= IInflow_SimpleGuidati ) then + call SetErrStat ( ErrID_Fatal, 'IInflow must be 0 (off) or 1 (only Amiet) or 2 (Full Guidati)'//& + 'or 3 (Simple Guidati).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%TICalcMeth /= TICalc_Every .and. InputFileData%TICalcMeth /= TICalc_Interp ) then + call SetErrStat ( ErrID_Fatal, 'TICalcMeth must be '//trim(num2lstr(TICalc_Every))//' TICalc automatic or '//& + trim(num2lstr(TICalc_Interp))//' (TICalcMeth interp).', ErrStat, ErrMsg, RoutineName ) + end if + + if (InputFileData%X_BLMethod /= X_BLMethod_BPM .and. InputFileData%X_BLMethod /= X_BLMethod_Tables) then + call SetErrStat ( ErrID_Fatal, 'X_BLMethod must be '//trim(num2lstr(X_BLMethod_BPM))//' X_BLMethod_ with BPM or '//& + trim(num2lstr(X_BLMethod_Tables))//' (X_BLMethod with BL tables).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%NrObsLoc <= 0.0) call SetErrStat ( ErrID_Fatal, 'Number of Observer Locations should be greater than zero', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%NrOutFile /= 1 .and. InputFileData%NrOutFile /= 2 .and. InputFileData%NrOutFile /= 3 & + .and. InputFileData%NrOutFile /= 4) then + call SetErrStat ( ErrID_Fatal, ' NrOutFile must be 1 or 2 or 3 or 4', ErrStat, ErrMsg, RoutineName ) + end if +END SUBROUTINE ValidateInputData + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AA_PrintSum( InputFileData, p, u, y, ErrStat, ErrMsg ) + ! This routine generates the summary file, which contains a summary of input file options. + ! passed variables + TYPE(AA_InputFile), INTENT(IN) :: InputFileData ! Input-file data + TYPE(AA_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AA_InputType), INTENT(IN) :: u ! inputs + TYPE(AA_OutputType), INTENT(IN) :: y ! outputs + INTEGER(IntKi), INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMsg + ! Local variables. + INTEGER(IntKi) :: I ! Index for the nodes. + INTEGER(IntKi) :: UnSu ! I/O unit number for the summary output file + CHARACTER(*), PARAMETER :: FmtDat = '(A,T35,1(:,F13.3))' ! Format for outputting mass and modal data. + CHARACTER(*), PARAMETER :: FmtDatT = '(A,T35,1(:,F13.8))' ! Format for outputting time steps. + CHARACTER(30) :: OutPFmt ! Format to print list of selected output channels to summary file + CHARACTER(100) :: Msg ! temporary string for writing appropriate text to summary file + ! Open the summary file and give it a heading. + ErrStat = ErrID_None + ErrMsg = "" + RETURN +END SUBROUTINE AA_PrintSum +!.................................................................................................................................. +!> This subroutine sets the initialization output data structure, which contains data to be returned to the calling program (e.g., +!! FAST or AeroAcoustics_Driver) +subroutine AA_SetInitOut(p, InputFileData, InitOut, errStat, errMsg) + type(AA_InitOutputType), intent( out) :: InitOut ! output data + type(AA_InputFile), intent(in ) :: InputFileData ! input file data (for setting airfoil shape outputs) + type(AA_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 + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'AA_SetInitOut' + integer(IntKi) :: i, j, k,m,oi + integer(IntKi) :: NumCoords + character(500) :: chanPrefix + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + InitOut%AirDens = p%AirDens + ! FIRST FILE HEADER,UNIT + call AllocAry(InitOut%WriteOutputHdr, p%numOuts, 'WriteOutputHdr', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitOut%WriteOutputUnt, p%numOuts, 'WriteOutputUnt', errStat2, errMsg2); if(Failed()) return + do j=1,p%NrObsLoc + InitOut%WriteOutputHdr(j)="Obs"//trim(num2lstr(j)) + InitOut%WriteOutputUnt(j) = "OASPL" + enddo + + ! SECOND FILE HEADER,UNIT + call AllocAry(InitOut%WriteOutputHdrforPE, p%numOutsforPE, 'WriteOutputHdrforPE', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitOut%WriteOutputUntforPE, p%numOutsforPE, 'WriteOutputUntforPE', errStat2, errMsg2); if(Failed()) return + i=0 + do j=1,p%NrObsLoc + do k=1,size(p%FreqList) + i=i+1 + InitOut%WriteOutputHdrforPE(i) = "Obs"//trim(num2lstr(j))//"_Freq"//trim(num2lstr(p%FreqList(k))) + if(p%aweightflag .eqv. .TRUE.) then + InitOut%WriteOutputUntforPE(i) = "SPL_A" + else + InitOut%WriteOutputUntforPE(i) = "SPL" + endif + end do + enddo + ! THIRD FILE HEADER,UNIT + call AllocAry(InitOut%WriteOutputHdrSep, p%NumOutsForSep, 'WriteOutputHdrSep', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitOut%WriteOutputUntSep, p%NumOutsForSep, 'WriteOutputUntSep', errStat2, errMsg2); if(Failed()) return + i=0 + do j=1,p%NrObsLoc + do k=1,size(p%FreqList) + do oi=1,7 + i=i+1 + InitOut%WriteOutputHdrSep(i) = "Obs"//trim(num2lstr(j))//"_Freq"//trim(num2lstr(p%FreqList(k)))//"_Type"//trim(num2lstr(oi)) + InitOut%WriteOutputHdrSep(i)=trim(InitOut%WriteOutputHdrSep(i)) + if(p%aweightflag .eqv. .TRUE.) then + InitOut%WriteOutputUntSep(i) = "SPL_A" + else + InitOut%WriteOutputUntSep(i) = "SPL" + endif + enddo + enddo + enddo + + ! FOURTH FILE HEADER,UNIT + call AllocAry(InitOut%WriteOutputHdrNodes,p%numBlades*p%NumBlNds*p%NrObsLoc, 'InitOut%WriteOutputHdrNodes', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitOut%WriteOutputUntNodes,p%numBlades*p%NumBlNds*p%NrObsLoc, 'InitOut%WriteOutputUntNodes', errStat2, errMsg2); if(Failed()) return + i=0 + do oi = 1,p%numBlades + do k = 1,p%NumBlNds + do j = 1,p%NrObsLoc + i=i+1 + InitOut%WriteOutputHdrNodes(i) = "Bld"//trim(num2lstr(oi))//"Node"//trim(num2lstr(k))//"Obs"//trim(num2lstr(j)) + InitOut%WriteOutputUntNodes(i) = "SPL" + enddo + enddo + enddo + InitOut%Ver = AA_Ver + InitOut%delim = Tab + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine AA_SetInitOut +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AA_InitializeOutputFile(p, InputFileData,InitOut,errStat, errMsg) + type(AA_InputFile), intent(in ) :: InputFileData !< All the data in the AeroDyn input file + type(AA_ParameterType) , intent(inout) :: p !< + type(AA_InitOutputType), intent(in ) :: InitOut !< output data + integer(IntKi) , intent(inout) :: errStat !< Status of error message + character(*) , intent(inout) :: errMsg !< Error message if ErrStat /= ErrID_None + ! locals + integer(IntKi) :: i + integer(IntKi) :: numOuts + character(200) :: frmt ! A string to hold a format specifier + character(15) :: tmpStr ! temporary string to print the time output as text + ! FIRST FILE + IF (InputFileData%NrOutFile .gt.0) THEN + call GetNewUnit( p%unOutFile, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) then + p%unOutFile = -1 + return + end if + + call OpenFOutFile ( p%unOutFile, trim(InputFileData%AAOutFile(1)), ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return + + write (p%unOutFile,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using AA '//trim(GetNVD(InitOut%ver)) + write (p%unOutFile,'(A)') '' + write( p%unOutFile,'(A,I5)' ) 'Number of observers :', p%NrObsLoc + write (p%unOutFile,'(A)') 'Description from AA input file, line2: '//trim(InputFileData%FTitle) + write (p%unOutFile,'(A)') '' + numOuts = size(InitOut%WriteOutputHdr) + !...................................................... + ! Write the names of the output parameters on one line: line 7 + !...................................................... + call WrFileNR ( p%unOutFile, ' Time ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile, InitOut%delim//InitOut%WriteOutputHdr(i) ) + end do ! i + write (p%unOutFile,'()') + !...................................................... + ! Write the units of the output parameters on one line: line 8 + !...................................................... + call WrFileNR ( p%unOutFile, ' (s) ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile, InitOut%delim//InitOut%WriteOutputUnt(i) ) + end do ! i + write (p%unOutFile,'()') + ENDIF + ! SECOND FILE + IF (InputFileData%NrOutFile .gt. 1) THEN + call GetNewUnit( p%unOutFile2, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) then + p%unOutFile = -1 + return + end if + call OpenFOutFile ( p%unOutFile2, trim(InputFileData%AAOutFile(2)), ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return + write (p%unOutFile2,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using AA '//trim(GetNVD(InitOut%Ver)) + write (p%unOutFile2,'(A)') '' + write( p%unOutFile2,'(A,I5,A,I5)' ) 'Number of observers :', p%NrObsLoc,'; Number of frequencies :', size(p%FreqList) + write (p%unOutFile2,'(A)') 'Description from AA input file, line2: '//trim(InputFileData%FTitle) + write (p%unOutFile2,'(A)') '' + numOuts = size(InitOut%WriteOutputHdrforPE) + !...................................................... + ! Write the names of the output parameters on one line: line 7 + !...................................................... + call WrFileNR ( p%unOutFile2, ' Time ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile2, InitOut%delim//InitOut%WriteOutputHdrforPE(i) ) + end do ! i + write (p%unOutFile2,'()') + !...................................................... + ! Write the units of the output parameters on one line: line 8 + !...................................................... + call WrFileNR ( p%unOutFile2, ' (s) ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile2, InitOut%delim//InitOut%WriteOutputUntforPE(i) ) + end do ! i + write (p%unOutFile2,'()') + !frmt = '"'//p%delim//'"'//trim(p%outFmt) ! format for array elements from individual modules + !call WrNumAryFileNR ( p%unOutFile2, p%FreqList, frmt, errStat, errMsg ) + !if ( errStat >= AbortErrLev ) return + !write (p%unOutFile2,'()') + ENDIF + ! THIRD FILE + IF (InputFileData%NrOutFile .gt. 2) THEN + call GetNewUnit( p%unOutFile3, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) then + p%unOutFile = -1 + return + end if + call OpenFOutFile ( p%unOutFile3, trim(InputFileData%AAOutFile(3)), ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return + write (p%unOutFile3,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using AA '//trim(GetNVD(InitOut%Ver)) + write (p%unOutFile3,'(A)') '' + write( p%unOutFile3,'(A,I5,A,I5)' ) 'Number of observers :', p%NrObsLoc,'; Number of frequencies :', size(p%FreqList) + write (p%unOutFile3,'(A)') 'Description from AA input file, line2: '//trim(InputFileData%FTitle) + numOuts = size(InitOut%WriteOutputHdrSep) + !...................................................... + ! Write the names of the output parameters on one line: line 7 + !...................................................... + call WrFileNR ( p%unOutFile3, "1-LBL 2-TBLPres 3-TBLSuc 4-Sep 5-BLUNT 6-TIP 7-Inflow") + write (p%unOutFile3,'()') + call WrFileNR ( p%unOutFile3, ' Time ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile3, InitOut%delim//InitOut%WriteOutputHdrSep(i) ) + end do ! i + write (p%unOutFile3,'()') + !...................................................... + ! Write the units of the output parameters on one line: line 8 + !...................................................... + call WrFileNR ( p%unOutFile3, ' (s) ' ) + + do i=1,NumOuts + call WrFileNR ( p%unOutFile3, InitOut%delim//InitOut%WriteOutputUntSep(i) ) + end do ! i + write (p%unOutFile3,'()') + ENDIF + ! FOURTH FILE + IF (InputFileData%NrOutFile .gt. 3) THEN + call GetNewUnit( p%unOutFile4, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) then + p%unOutFile = -1 + return + end if + call OpenFOutFile ( p%unOutFile4, trim(InputFileData%AAOutFile(4)), ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return + write (p%unOutFile4,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using AA '//trim(GetNVD(InitOut%Ver)) + write (p%unOutFile4,'()') + write( p%unOutFile4,'(A,I5)' ) 'Number of observers :', p%NrObsLoc, '; Number of blades :', p%numBlades,' Number of nodes per blade:', p%NumBlNds + write (p%unOutFile4,'(A)') 'Description from AA input file, line2: '//trim(InputFileData%FTitle) + numOuts = size(InitOut%WriteOutputHdrNodes) + !...................................................... + ! Write the names of the output parameters on one line: line 7 + !...................................................... + write (p%unOutFile4,'()') + call WrFileNR ( p%unOutFile4, ' Time ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile4, InitOut%delim//InitOut%WriteOutputHdrNodes(i) ) + end do ! i + write (p%unOutFile4,'()') + !...................................................... + ! Write the units of the output parameters on one line: line 8 + !...................................................... + call WrFileNR ( p%unOutFile4, ' (s) ' ) + do i=1,NumOuts + call WrFileNR ( p%unOutFile4, InitOut%delim//InitOut%WriteOutputUntNodes(i) ) + end do ! i + write (p%unOutFile4,'()') + ENDIF +end subroutine AA_InitializeOutputFile +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AA_WriteOutputLine(y, t, p, errStat, errMsg) + real(DbKi) , intent(in ) :: t ! simulation time (s) + type(AA_OutputType) , intent(in ) :: y + type(AA_ParameterType) , intent(in ) :: p + integer(IntKi) , intent(inout) :: errStat ! Status of error message + character(*) , intent(inout) :: errMsg ! Error message if ErrStat /= ErrID_None + ! Local variables. + character(200) :: frmt ! A string to hold a format specifier + character(15) :: tmpStr ! temporary string to print the time output as text + integer :: numOuts + errStat = ErrID_None + errMsg = '' + ! FIRST FILE + IF (p%NrOutFile .gt. 0) THEN + numOuts = size(y%WriteOutput) + frmt = '"'//p%delim//'"'//trim(p%outFmt) ! format for array elements from individual modules + ! time + write( tmpStr, '(F15.4)' ) t + call WrFileNR( p%unOutFile, tmpStr ) + call WrNumAryFileNR ( p%unOutFile, y%WriteOutput, frmt, errStat, errMsg ) + if ( errStat >= AbortErrLev ) return + ! write a new line (advance to the next line) + write (p%unOutFile,'()') + ENDIF + + !! SECOND FILE + IF (p%NrOutFile .gt. 1) THEN + numOuts = size(y%WriteOutputforPE) + frmt = '"'//p%delim//'"'//trim(p%outFmt) ! format for array elements from individual modules + ! time + write( tmpStr, '(F15.4)' ) t + call WrFileNR( p%unOutFile2, tmpStr ) + call WrNumAryFileNR ( p%unOutFile2, y%WriteOutputforPE, frmt, errStat, errMsg ) + if ( errStat >= AbortErrLev ) return + ! write a new line (advance to the next line) + write (p%unOutFile2,'()') + ENDIF + ! THIRD FILE + IF (p%NrOutFile .gt. 2) THEN + numOuts = size(y%WriteOutputSep) + frmt = '"'//p%delim//'"'//trim(p%outFmt) ! format for array elements from individual modules + ! time + write( tmpStr, '(F15.4)' ) t + call WrFileNR( p%unOutFile3, tmpStr ) + call WrNumAryFileNR ( p%unOutFile3, y%WriteOutputSep, frmt, errStat, errMsg ) + if ( errStat >= AbortErrLev ) return + ! write a new line (advance to the next line) + write (p%unOutFile3,'()') + ENDIF + ! Fourth FILE + IF (p%NrOutFile .gt. 3) THEN + numOuts = size(y%WriteOutputNode) + frmt = '"'//p%delim//'"'//trim(p%outFmt) ! format for array elements from individual modules + ! time + write( tmpStr, '(F15.4)' ) t + call WrFileNR( p%unOutFile4, tmpStr ) + call WrNumAryFileNR ( p%unOutFile4, y%WriteOutputNode, frmt, errStat, errMsg ) + if ( errStat >= AbortErrLev ) return + ! write a new line (advance to the next line) + write (p%unOutFile4,'()') + ENDIF +end subroutine AA_WriteOutputLine +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Calc_WriteOutput( p, u, m, y, ErrStat, ErrMsg ) + TYPE(AA_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(AA_InputType), INTENT(IN ) :: u ! inputs + TYPE(AA_MiscVarType), INTENT(INOUT) :: m ! misc variables + TYPE(AA_OutputType), INTENT(INOUT) :: y ! outputs + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + ! local variables + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteOutput' + INTEGER(intKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: j,k,counter,i,oi,III + ! start routine: + ErrStat = ErrID_None + ErrMsg = "" + + ! FOR THE FIRST OUTPUT FILE + IF (p%NrOutFile .gt. 0) THEN + y%WriteOutput(1:p%NrObsLoc)=y%DirectiviOutput + endif + + ! FOR THE SECOND OUTPUT FILE + IF (p%NrOutFile .gt. 1) THEN + counter=0 + DO K = 1,p%NrObsLoc + DO III = 1,size(p%FreqList) + counter=counter+1 + y%WriteOutputforPE(counter) = y%PtotalFreq(K,III) + END DO ! + END DO ! + ENDIF + + ! FOR THE THIRD OUTPUT FILE + IF (p%NrOutFile .gt. 2) THEN + counter=0 + do K = 1,p%NrObsLoc + do III = 1,size(p%FreqList) + do oi=1,size(y%OASPL_Mech,1) + counter=counter+1 + y%WriteOutputSep(counter) = y%SumSpecNoiseSep(oi,K,III) + enddo + enddo + enddo + ENDIF + + ! FOR THE FOURTH OUTPUT FILE + IF (p%NrOutFile .gt. 3) THEN + counter=0 + DO I = 1,p%numBlades + DO J = 1,p%NumBlNds + DO K = 1,p%NrObsLoc + counter=counter+1 + y%WriteOutputNode(counter) = y%OASPL(K,J,I) + END DO ! + END DO ! + ENDDO + ENDIF +END SUBROUTINE Calc_WriteOutput +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE AeroAcoustics_IO diff --git a/OpenFAST/modules/aerodyn/src/AeroAcoustics_Registry.txt b/OpenFAST/modules/aerodyn/src/AeroAcoustics_Registry.txt new file mode 100644 index 000000000..b5d1a865e --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroAcoustics_Registry.txt @@ -0,0 +1,252 @@ +################################################################################################################################### +# Registry for AeroAcoustics module in the FAST Modularization Framework +# This Registry file is used to create AeroDyn_Types which contains data used in the AeroDyn module. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# File last committed $Date: 2016-03-14 12:13:10 -0600 (Mon, 14 Mar 2016) $ +# (File) Revision #: $Rev: 201 $ +# URL: $HeadURL: https://windsvn.nrel.gov/WT_Perf/branches/v4.x/Source/dependencies/AeroDyn/AeroDyn_Registry.txt $ +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt +usefrom AirfoilInfo_Registry.txt +# +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Blade Input file data ..................................................................................................... +typedef AeroAcoustics/AA AA_BladePropsType IntKi NumBlNds - - - "Number of blade nodes used in the analysis" - +typedef ^ AA_BladePropsType ReKi TEThick {:} - - "" - +typedef ^ AA_BladePropsType ReKi StallStart {:} - - "" - +typedef ^ AA_BladePropsType ReKi TEAngle {:} - - "" - +typedef ^ AA_BladePropsType ReKi AerCent {:} - - "" - +# +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef AeroAcoustics/AA InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ InitInputType IntKi NumBlades - - - "Number of blades on the turbine" +typedef ^ InitInputType IntKi NumBlNds - - - "Number of blades on the turbine" +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ InitInputType ReKi BlSpn {:}{:} - - "Span at blade node" m +typedef ^ InitInputType ReKi BlChord {:}{:} - - "Chord at blade node" m +typedef ^ InitInputType ReKi AirDens - - - "Air density" kg/m^3 +typedef ^ InitInputType ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ InitInputType ReKi SpdSound - - - "Speed of sound" m/s +typedef ^ InitInputType ReKi HubHeight - - - "Hub Height" m +typedef ^ InitInputType IntKi BlAFID {:}{:} - - "Index of airfoil data file for blade node location [array of numBladeNodes by numBlades]" - +typedef ^ InitInputType AFI_ParameterType AFInfo {:} - - "Airfoil information structure containing the aerodynamic center and airfoil shape coordinates" +# +# Define outputs from the initialization routine here: +typedef ^ InitOutputType CHARACTER(20) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(20) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(20) WriteOutputHdrforPE {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(20) WriteOutputUntforPE {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(25) WriteOutputHdrSep {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(25) WriteOutputUntSep {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(25) WriteOutputHdrNodes {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(25) WriteOutputUntNodes {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType character(1) delim - - - "column delimiter" "-" +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType ReKi AirDens - - - "Air density" kg/m^3 +# + +# ..... Primary Input file data ................................................................................................... +typedef ^ AA_InputFile DbKi DT_AA - - - "Time interval for aerodynamic calculations {or "default"}" s +typedef ^ AA_InputFile IntKi IBLUNT - - - "FLAG TO COMPUTE BLUNTNESS NOISE" - +typedef ^ AA_InputFile IntKi ILAM - - - "FLAG TO COMPUTE LBL NOISE {1=steady model, 2=Beddoes-Leishman unsteady model}" - +typedef ^ AA_InputFile IntKi ITIP - - - "FLAG TO COMPUTE TIP NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ AA_InputFile IntKi ITRIP - - - "FLAG TO TRIP BOUNDARY LAYER {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ AA_InputFile IntKi ITURB - - - "FLAG TO COMPUTE TBLTE NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ AA_InputFile IntKi IInflow - - - "FLAG TO COMPUTE Turbulent Inflow NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ AA_InputFile IntKi X_BLMethod - - - "Integer describing calculation method for boundary layer properties, = 1 BPM = 2 Pretabulated" - +typedef ^ AA_InputFile IntKi TICalcMeth - - - "TICalcMeth" - +typedef ^ AA_InputFile IntKi NReListBL - - - "Number of values of ReListBL" - +typedef ^ AA_InputFile Logical aweightflag - - - "Integer a weighting call" - +typedef ^ AA_InputFile Logical ROUND - - - "LOGICAL INDICATING ROUNDED TIP" - +typedef ^ AA_InputFile ReKi ALPRAT - - - "TIP LIFT CURVE SLOPE" - +typedef ^ AA_InputFile IntKi AA_Bl_Prcntge - - - "see the AeroAcoustics input file for description " - +typedef ^ AA_InputFile IntKi NrObsLoc - - - "Number of observer locations " - +typedef ^ AA_InputFile ReKi ObsX {:} - - "Observer location in tower-base coordinate X horizontal" m +typedef ^ AA_InputFile ReKi ObsY {:} - - "Observer location in tower-base coordinate Y lateral" m +typedef ^ AA_InputFile ReKi ObsZ {:} - - "Observer location in tower-base coordinate Z vertical" m +typedef ^ AA_InputFile AA_BladePropsType BladeProps {:} - - "blade property information from blade input files" - +typedef ^ AA_InputFile IntKi NrOutFile - - - "Nr of output files" - +typedef ^ AA_InputFile CHARACTER(1024) AAoutfile {:} - - "AAoutfile for writing output files" - +typedef ^ AA_InputFile CHARACTER(1024) TICalcTabFile - - - "Name of the file containing the table for incident turbulence intensity" - +typedef ^ AA_InputFile CHARACTER(1024) FTitle - - - "File Title: the 2nd line of the input file, which contains a description of its contents" - +typedef ^ AA_InputFile DBKi AAStart - - - "Time after which to calculate AA" s +typedef ^ AA_InputFile ReKi z0_AA - - - "Surface roughness" - +typedef ^ AA_InputFile ReKi ReListBL {:} - - "" +typedef ^ AA_InputFile ReKi AoAListBL {:} - - "" deg +typedef ^ AA_InputFile ReKi Pres_DispThick {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Suct_DispThick {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Pres_BLThick {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Suct_BLThick {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Pres_Cf {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Suct_Cf {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Pres_EdgeVelRat {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi Suct_EdgeVelRat {:}{:}{:} - - "" +typedef ^ AA_InputFile ReKi TI_Grid_In {:}{:} - - "" +typedef ^ AA_InputFile ReKi dz_turb_in - - - "" m +typedef ^ AA_InputFile ReKi dy_turb_in - - - "" m + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - +# +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi MeanVrel {:}{:} - - "Vrel Cumu. Mean" - +typedef ^ DiscreteStateType ReKi VrelSq {:}{:} - - "Vrel Squared Store" - +typedef ^ DiscreteStateType ReKi TIVrel {:}{:} - - "Vrel St. deviat" - +typedef ^ DiscreteStateType ReKi VrelStore {:}{:}{:} - - "Vrel Store for fft - dissipation" - +typedef ^ DiscreteStateType ReKi TIVx {:}{:} - - "Vx St. deviat" - +typedef ^ DiscreteStateType ReKi MeanVxVyVz {:}{:} - - "Vrel Cumu. Mean" - +typedef ^ DiscreteStateType ReKi VxSq {:}{:} - - "Vxl Squared Store" - +typedef ^ DiscreteStateType ReKi allregcounter {:}{:} - - "" - +typedef ^ DiscreteStateType ReKi VxSqRegion {:}{:} - - "" - +typedef ^ DiscreteStateType ReKi RegVxStor {:}{:}{:} - - "VxVyVz Store for fft or TI - dissipation" - +typedef ^ DiscreteStateType ReKi RegionTIDelete {:}{:} - - "" - +# +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have states" - +# +# Define "other" states here: +typedef ^ OtherStateType SiKi DummyOtherState - - - "Remove this variable if you have states" - +# +# Define misc/optimization variables (any data that are not considered actual states) here: +##typedef ^ MiscVarType ReKi DisturbedInflow {:}{:}{:} - - "InflowOnBlade values modified by tower influence" m/s +typedef ^ MiscVarType ReKi AllOuts {:} - - "An array holding the value of all of the calculated (not only selected) output channels" - +typedef ^ MiscVarType ReKi ChordAngleTE {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi SpanAngleTE {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi ChordAngleLE {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi SpanAngleLE {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi rTEtoObserve {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi rLEtoObserve {:}{:}{:} - - "C" - +typedef ^ MiscVarType ReKi LE_Location {:}{:}{:} - - "Height of Leading Edge for calculation of TI and Scales if needed" - +typedef ^ MiscVarType ReKi RotSpeedAoA - - - "C" - +typedef ^ MiscVarType ReKi SPLLBL {:} - - "C" - +typedef ^ MiscVarType ReKi SPLP {:} - - "C" - +typedef ^ MiscVarType ReKi SPLS {:} - - "C" - +typedef ^ MiscVarType ReKi SPLALPH {:} - - "C" - +typedef ^ MiscVarType ReKi SPLTBL {:} - - "C" - +typedef ^ MiscVarType ReKi SPLTIP {:} - - "C" - +typedef ^ MiscVarType ReKi SPLTI {:} - - "C" - +typedef ^ MiscVarType ReKi SPLTIGui {:} - - "C" - +typedef ^ MiscVarType ReKi SPLBLUNT {:} - - "C" - +typedef ^ MiscVarType ReKi CfVar {:} - - "Output Skin friction coef Pressure Side" - +typedef ^ MiscVarType ReKi d99Var {:} - - "BL Output " - +typedef ^ MiscVarType ReKi dStarVar {:} - - "BL Output " - +typedef ^ MiscVarType ReKi EdgeVelVar {:} - - "BL Output " - +typedef ^ MiscVarType IntKi speccou - - - "Secptrum counter every XX seconds new spectrum" - +typedef ^ MiscVarType IntKi filesopen - - - "check if file is open" - +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ParameterType IntKi IBLUNT - - - "Bluntness noise model" - +typedef ^ ParameterType IntKi ILAM - - - "LBL noise model " - +typedef ^ ParameterType IntKi ITIP - - - "Tip noise model" - +typedef ^ ParameterType IntKi ITRIP - - - "Trip boundary layer" - +typedef ^ ParameterType IntKi ITURB - - - "Tblte noise model" - +typedef ^ ParameterType IntKi IInflow - - - "Turbulent inflow noise model" - +typedef ^ ParameterType IntKi X_BLMethod - - - "Integer describing calculation method for boundary layer properties, = 1 BPM = 2 Pretabulated" - +typedef ^ ParameterType IntKi TICalcMeth - - - "" - +typedef ^ ParameterType Logical ROUND - - - "Logical indicating rounded tip" - +typedef ^ ParameterType ReKi ALPRAT - - - "TIP LIFT CURVE SLOPE" - +typedef ^ ParameterType IntKi NumBlades - - - "Number of blades on the turbine" - +typedef ^ ParameterType IntKi NumBlNds - - - "Number of nodes on each blade" - +typedef ^ ParameterType ReKi AirDens - - - "Air density" kg/m^3 +typedef ^ ParameterType ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ ParameterType ReKi SpdSound - - - "Speed of sound" m/s +typedef ^ ParameterType ReKi HubHeight - - - "Hub height" m +typedef ^ ParameterType ReKi toptip - - - "Top Tip Height = Hub height plus radius" m +typedef ^ ParameterType ReKi bottip - - - "Bottom Tip Height = Hub height minus radius" m +typedef ^ ParameterType ReKi rotorregionlimitsVert {:} - - "" +typedef ^ ParameterType ReKi rotorregionlimitsHorz {:} - - "" +typedef ^ ParameterType ReKi rotorregionlimitsalph {:} - - "" +typedef ^ ParameterType ReKi rotorregionlimitsrad {:} - - "" +typedef ^ ParameterType IntKi NrObsLoc - - - "Number of observer locations " - +typedef ^ ParameterType Logical aweightflag - - - " " - +typedef ^ ParameterType Logical TxtFileOutput - - - " " - +typedef ^ ParameterType DBKi AAStart - - - "Time after which to calculate AA" s +typedef ^ ParameterType ReKi ObsX {:} - - "Observer location in tower-base coordinate X horizontal" m +typedef ^ ParameterType ReKi ObsY {:} - - "Observer location in tower-base coordinate Y lateral" m +typedef ^ ParameterType ReKi ObsZ {:} - - "Observer location in tower-base coordinate Z vertical" m +typedef ^ ParameterType ReKi FreqList {:} - - "List of Acoustic Frequencies to Calculate" Hz +typedef ^ ParameterType ReKi Aweight {:} - - "List of Acoustic Frequencies a weighting" dB +typedef ^ ParameterType ReKi Fsample - - - "Sampling Frequency 1/delta(t) - 1/(simulation time step)" Hz +typedef ^ ParameterType IntKi total_sample - - - "Total FFT Sample amount for dissipation calculation" - +typedef ^ ParameterType IntKi total_sampleTI - - - "Total FFT Sample amount for dissipation calculation" - +typedef ^ ParameterType IntKi AA_Bl_Prcntge - - - "The Percentage of the Blade which the noise is calculated" % +typedef ^ ParameterType IntKi startnode - - - "Corersponding node to the noise calculation percentage of the blade" - +typedef ^ ParameterType ReKi z0_aa - - - "Surface roughness" m +typedef ^ ParameterType ReKi dz_turb_in - - - "" m +typedef ^ ParameterType ReKi dy_turb_in - - - "" m +typedef ^ ParameterType ReKi TI_Grid_In {:}{:} - - "" +typedef ^ ParameterType CHARACTER(1024) FTitle - - - "File Title: the 2nd line of the input file, which contains a description of its contents" - + +# parameters for output +typedef ^ ParameterType character(20) outFmt - - - "Format specifier" "-" +typedef ^ ParameterType IntKi NrOutFile - - - "Nr of output files" - +typedef ^ ParameterType character(1) delim - - - "column delimiter" "-" +typedef ^ ParameterType IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType IntKi NumOutsForPE - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType IntKi NumOutsForSep - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType IntKi NumOutsForNodes - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType IntKi unOutFile - - - "unit number for writing output file" "-" +typedef ^ ParameterType IntKi unOutFile2 - - - "unit number for writing output file" "-" +typedef ^ ParameterType IntKi unOutFile3 - - - "unit number for writing output file" "-" +typedef ^ ParameterType IntKi unOutFile4 - - - "unit number for writing output file" "-" +typedef ^ ParameterType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType ReKi StallStart {:}{:} - - "ation" - +typedef ^ ParameterType ReKi TEThick {:}{:} - - "ation" - +typedef ^ ParameterType ReKi TEAngle {:}{:} - - "ation" - +typedef ^ ParameterType ReKi AerCent {:}{:}{:} - - "ation" - +typedef ^ ParameterType IntKi BlAFID {:}{:} - - "Index of airfoil data file for blade node location [array of numBladeNodes by numBlades]" - +typedef ^ ParameterType AFI_ParameterType AFInfo {:} - - "Airfoil information structure containing the aerodynamic center and airfoil shape coordinates" +typedef ^ ParameterType ReKi AFLECo {:}{:}{:} - - "Dimensionalized " +typedef ^ ParameterType ReKi AFTECo {:}{:}{:} - - +typedef ^ ParameterType ReKi BlSpn {:}{:} - - "Span at blade node" m +typedef ^ ParameterType ReKi BlChord {:}{:} - - "Chord at blade node" m +typedef ^ ParameterType ReKi ReListBL {:} - - "BL list of Reynolds" - +typedef ^ ParameterType ReKi AOAListBL {:} - - "BL list of Angle Of Attack " deg +typedef ^ ParameterType ReKi dStarAll1 {:}{:}{:} - - "Output Disp Thickness Suction Side" m +typedef ^ ParameterType ReKi dStarAll2 {:}{:}{:} - - "Output Disp Thickness Pressure Side" m +typedef ^ ParameterType ReKi d99All1 {:}{:}{:} - - "Output B.L. Thickness Suction Side" m +typedef ^ ParameterType ReKi d99All2 {:}{:}{:} - - "Output B.L. Thickness Pressure Side" m +typedef ^ ParameterType ReKi CfAll1 {:}{:}{:} - - "Output Skin friction coef Suction Side" - +typedef ^ ParameterType ReKi CfAll2 {:}{:}{:} - - "Output Skin friction coef Pressure Side" - +typedef ^ ParameterType ReKi EdgeVelRat1 {:}{:}{:} - - "Output Edge Velocity Ratio Suction" - +typedef ^ ParameterType ReKi EdgeVelRat2 {:}{:}{:} - - "Output Edge Velocity Ratio Pressure Side" - +typedef ^ ParameterType ReKi AFThickGuida {:}{:} - - "1 and 10 percent thickness t/c used for Simplified Guidati" +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: + +typedef ^ InputType ReKi RotGtoL {:}{:}{:}{:} - - "3x3 rotation matrix transform a vector from the local airfoil coordinate system to the global inertial coordinate system" - +typedef ^ InputType ReKi AeroCent_G {:}{:}{:} - - "location in global coordinates of the blade element aerodynamic center. 1st index = vector components, 2nd index = blade node, 3rd index = blade" - +typedef ^ InputType ReKi Vrel {:}{:} - - "Vrel" - +typedef ^ InputType ReKi AoANoise {:}{:} - - "Angle of attack" - +typedef ^ InputType ReKi Inflow {:}{:}{:} - - "atmospheric undisturbed flow on blade" + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType ReKi SumSpecNoise {:}{:}{:} - - "Spectra of summed noise level of each blade and blade nodes for each receiver and frequency" SPL +typedef ^ OutputType ReKi SumSpecNoiseSep {:}{:}{:} - - "Spectra of summed noise level of all blades and blade nodes for each receiver and frequency" SPL +typedef ^ OutputType ReKi OASPL {:}{:}{:} - - "summed noise level for each blade and blade nodes and receiver " SPL +typedef ^ OutputType ReKi OASPL_Mech {:}{:}{:}{:} - - "5 different mechanism noise level for each blade and blade nodes and receiver " SPL +typedef ^ OutputType ReKi DirectiviOutput {:} - - " " SPL +typedef ^ OutputType ReKi OutLECoords {:}{:}{:}{:} - - " " m +typedef ^ OutputType ReKi PtotalFreq {:}{:} - - "SPL for each observer and frequency" + +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi WriteOutputForPE {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ OutputType ReKi WriteOutputSep {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ OutputType ReKi WriteOutputNode {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" diff --git a/OpenFAST/modules/aerodyn/src/AeroAcoustics_TNO.f90 b/OpenFAST/modules/aerodyn/src/AeroAcoustics_TNO.f90 new file mode 100644 index 000000000..a2d9ab2b8 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroAcoustics_TNO.f90 @@ -0,0 +1,198 @@ +MODULE TNO + + + use NWTC_Library ! ReKi, DBKi, R8Ki + use NWTC_SLATEC ! slatec_qk61 -- which is all that is in that library right now. + + implicit none + PUBLIC :: SPL_integrate + + INTEGER, PARAMETER :: TNOKi = ReKi + + REAL (TNOKi), PARAMETER :: Cnuk = 5.5 + REAL (TNOKi), PARAMETER :: kappa = 0.41 + REAL (TNOKi), PARAMETER :: Cmu = 0.09 +! INTEGER(IntKi),PARAMETER :: limit = 5000 + + !TNO variables + REAL (TNOKi) :: Omega_TNO ! NOTE: not a constant and used by function f_int1 and f_int2 + + !atmosphere variables + REAL (TNOKi) :: nu + REAL (TNOKi) :: co + REAL (TNOKi) :: rho + + ! Wavenumber variables + REAL (TNOKi) :: k + REAL (TNOKi) :: k1 + REAL (TNOKi) :: k3 + + ! Blade params + REAL (TNOKi) :: d99(2) + REAL (TNOKi) :: Cf(2) + REAL (TNOKi) :: edgevel(2) + + ! Airfoil + REAL(TNOKi) :: Mach_TNO + LOGICAL :: ISSUCTION_TNO + + +contains + +!> Solve the spl generated at this location and frequency +function SPL_integrate(Omega,limits,ISSUCTION, & + Mach,SpdSound,AirDens,KinVisc, & + Cfall,d99all,EdgeVelAll) result(integrand) + real(ReKi), intent(in ) :: Omega !< frequency + real(ReKi), intent(in ) :: limits(2) !< integration limits + logical, intent(in ) :: ISSUCTION !< Is it the suction edge + real(ReKi), intent(in ) :: Mach !< Mach number + real(ReKi), intent(in ) :: SpdSound !< Speed of sound + real(ReKi), intent(in ) :: AirDens !< Air density + real(ReKi), intent(in ) :: KinVisc !< Kinetic air viscosity + real(ReKi), intent(in ) :: Cfall(2) !< Skin friction coefficient (-) + real(ReKi), intent(in ) :: d99all(2) !< + real(ReKi), intent(in ) :: EdgeVelAll(2) !< + real(ReKi) :: integrand !< integrand result + + real(TNOKi) :: answer !< value returned from qk61, NOTE the typing + + ! local variables that are ignored + real(TNOKi) :: abserr,resabs,resasc !< accuracy estimates and residuals. Currently ignored + + ! Set module values from input + ISSUCTION_TNO = ISSUCTION + Omega_TNO = real(Omega,TNOKi) + ! Mach number of segment + Mach_TNO = real(Mach,TNOKi) + ! Atmospheric values + co = real(SpdSound, TNOKi) + rho = real(AirDens, TNOKi) + nu = real(KinVisc, TNOKi) + ! Blade node values + Cf = real(Cfall, TNOKi) + d99 = real(d99all, TNOKi) + edgevel = real(ABS(EdgeVelAll),TNOKi) + + call slatec_qk61(f_int2,limits(1),limits(2),answer,abserr,resabs,resasc) + integrand = real( answer, ReKi ) + +end function SPL_integrate + + + +FUNCTION f_int1(x2) + REAL(TNOKi):: alpha + REAL(TNOKi):: alpha_gauss + REAL(TNOKi):: Cfin + REAL(TNOKi):: delta + REAL(TNOKi):: dudx + REAL(TNOKi):: ke + REAL(TNOKi):: k1_hat + REAL(TNOKi):: k3_hat + REAL(TNOKi):: kT + REAL(TNOKi):: L + REAL(TNOKi):: Nut + REAL(TNOKi):: phi22 + REAL(TNOKi):: phim + REAL(TNOKi):: ums + REAL(TNOKi):: u_star + REAL(TNOKi):: U + REAL(TNOKi):: Uc + REAL(TNOKi):: Uo + REAL(TNOKi):: W + REAL(TNOKi), intent(in) :: x2 + REAL(TNOKi):: f_int1 + + ! changed and being multiplied with edge velocity taken from xfoil output + ! Uo=Mach_TNO*co ISSUCTION_TNO use edgevel(1) + + !constants from xfoil + if (ISSUCTION_TNO) then + alpha = 0.45 ! = 0.3 pressure, = 0.45 suction + Cfin = Cf(1) + delta = d99(1) + Uo=Mach_TNO*co*edgevel(1) + else + alpha = 0.30 + Cfin = Cf(2) + delta = d99(2) + Uo=Mach_TNO*co*edgevel(2) + endif + if (Cfin .le. 0.) then + write(*,*) 'Cf is less than zero, Cf = ',Cfin + stop + endif + u_star = Uo*sqrt(Cfin/2.) + + L = 0.085*delta*tanh(kappa*x2/(0.085*delta)) + + if (x2 .gt. delta)then + U = Uo + dudx = 0. + f_int1 = 0. + RETURN + else + W = 1.-cos(pi*x2/delta); + U = u_star*(1./kappa*log(u_star*x2/nu) +Cnuk+ (Uo/u_star-1./kappa*log(u_star*delta/nu)-Cnuk)*0.5*W) + dudx = u_star*(1./(kappa*x2)+(Uo/u_star-1./kappa*log(u_star*delta/nu)-Cnuk)* & + 0.5*(pi/delta)*sin(pi*x2/delta)) + endif + + ke=sqrt(pi)/L*0.4213560764 !gamma(5./6.)/gamma(1./3.) + k1_hat = k1/ke + k3_hat = k3/ke + + Nut = (L*kappa)**2.*abs(dudx) + kT = sqrt((Nut*dudx)**2./Cmu) + ums = alpha*kT + + Uc = 0.7*U + alpha_gauss = 0.05*Uc/L + + phim = 1./(alpha_gauss*sqrt(pi))*exp(-((Omega_TNO-Uc*k1)/alpha_gauss)**2.) + phi22 = 4./9./pi*1/ke**2.*(k1_hat**2.+k3_hat**2.)/(1.+k1_hat**2.+k3_hat**2.)**(7./3.) + f_int1 = L*ums*(dudx)**2*phi22*phim*exp(-2*abs(k)*x2) + + RETURN +END FUNCTION f_int1 + + +FUNCTION f_int2(k1) ! changed name from 'int2' to avoid conflicts with intrinsic of same name + REAL (TNOKi), intent(in) :: k1 + REAL (TNOKi) :: f_int2 + f_int2 = Omega_TNO/co/k1*Pressure(k1) + RETURN +END FUNCTION f_int2 + + +FUNCTION Pressure(k1_in) + ! Variables + REAL(TNOKi) :: a,b,answer + REAL(TNOKi) :: omega + REAL(TNOKi) :: abserr,resabs,resasc + REAL(TNOKi) :: k1_in + real(TNOKi) :: Pressure + + ! Set variables used in f_int1 + k1 = k1_in + + a = 0.0_TNOKi !1e-4*d99(1) + IF (ISSUCTION_TNO)THEN + b = d99(1) + ELSE + b = d99(2) + ENDIF + + k3 = 0. + k= sqrt(k1**2+k3**2) + + CALL slatec_qk61(f_int1,a,b,answer,abserr,resabs,resasc) + + Pressure = 4.*rho**2*k1**2./(k1**2.+k3**2.)*answer + + RETURN +END FUNCTION Pressure + + +END MODULE TNO diff --git a/OpenFAST/modules/aerodyn/src/AeroAcoustics_Types.f90 b/OpenFAST/modules/aerodyn/src/AeroAcoustics_Types.f90 new file mode 100644 index 000000000..9ed3b64f5 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroAcoustics_Types.f90 @@ -0,0 +1,10536 @@ +!STARTOFREGISTRYGENERATEDFILE 'AeroAcoustics_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 +!********************************************************************************************************************************* +! AeroAcoustics_Types +!................................................................................................................................. +! This file is part of AeroAcoustics. +! +! 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 AeroAcoustics. 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 AeroAcoustics_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE NWTC_Library +IMPLICIT NONE +! ========= AA_BladePropsType ======= + TYPE, PUBLIC :: AA_BladePropsType + INTEGER(IntKi) :: NumBlNds !< Number of blade nodes used in the analysis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TEThick !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StallStart !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TEAngle !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AerCent !< [-] + END TYPE AA_BladePropsType +! ======================= +! ========= AA_InitInputType ======= + TYPE, PUBLIC :: AA_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + INTEGER(IntKi) :: NumBlNds !< Number of blades on the turbine [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BlSpn !< Span at blade node [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BlChord !< Chord at blade node [m] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + REAL(ReKi) :: SpdSound !< Speed of sound [m/s] + REAL(ReKi) :: HubHeight !< Hub Height [m] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BlAFID !< Index of airfoil data file for blade node location [array of numBladeNodes by numBlades] [-] + TYPE(AFI_ParameterType) , DIMENSION(:), ALLOCATABLE :: AFInfo !< Airfoil information structure containing the aerodynamic center and airfoil shape coordinates [-] + END TYPE AA_InitInputType +! ======================= +! ========= AA_InitOutputType ======= + TYPE, PUBLIC :: AA_InitOutputType + CHARACTER(20) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(20) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + CHARACTER(20) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdrforPE !< Names of the output-to-file channels [-] + CHARACTER(20) , DIMENSION(:), ALLOCATABLE :: WriteOutputUntforPE !< Units of the output-to-file channels [-] + CHARACTER(25) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdrSep !< Names of the output-to-file channels [-] + CHARACTER(25) , DIMENSION(:), ALLOCATABLE :: WriteOutputUntSep !< Units of the output-to-file channels [-] + CHARACTER(25) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdrNodes !< Names of the output-to-file channels [-] + CHARACTER(25) , DIMENSION(:), ALLOCATABLE :: WriteOutputUntNodes !< Units of the output-to-file channels [-] + character(1) :: delim !< column delimiter [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + END TYPE AA_InitOutputType +! ======================= +! ========= AA_InputFile ======= + TYPE, PUBLIC :: AA_InputFile + REAL(DbKi) :: DT_AA !< Time interval for aerodynamic calculations {or "default"} [s] + INTEGER(IntKi) :: IBLUNT !< FLAG TO COMPUTE BLUNTNESS NOISE [-] + INTEGER(IntKi) :: ILAM !< FLAG TO COMPUTE LBL NOISE {1=steady model, 2=Beddoes-Leishman unsteady model} [-] + INTEGER(IntKi) :: ITIP !< FLAG TO COMPUTE TIP NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: ITRIP !< FLAG TO TRIP BOUNDARY LAYER {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: ITURB !< FLAG TO COMPUTE TBLTE NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: IInflow !< FLAG TO COMPUTE Turbulent Inflow NOISE {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: X_BLMethod !< Integer describing calculation method for boundary layer properties, = 1 BPM = 2 Pretabulated [-] + INTEGER(IntKi) :: TICalcMeth !< TICalcMeth [-] + INTEGER(IntKi) :: NReListBL !< Number of values of ReListBL [-] + LOGICAL :: aweightflag !< Integer a weighting call [-] + LOGICAL :: ROUND !< LOGICAL INDICATING ROUNDED TIP [-] + REAL(ReKi) :: ALPRAT !< TIP LIFT CURVE SLOPE [-] + INTEGER(IntKi) :: AA_Bl_Prcntge !< see the AeroAcoustics input file for description [-] + INTEGER(IntKi) :: NrObsLoc !< Number of observer locations [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsX !< Observer location in tower-base coordinate X horizontal [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsY !< Observer location in tower-base coordinate Y lateral [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsZ !< Observer location in tower-base coordinate Z vertical [m] + TYPE(AA_BladePropsType) , DIMENSION(:), ALLOCATABLE :: BladeProps !< blade property information from blade input files [-] + INTEGER(IntKi) :: NrOutFile !< Nr of output files [-] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: AAoutfile !< AAoutfile for writing output files [-] + CHARACTER(1024) :: TICalcTabFile !< Name of the file containing the table for incident turbulence intensity [-] + CHARACTER(1024) :: FTitle !< File Title: the 2nd line of the input file, which contains a description of its contents [-] + REAL(DbKi) :: AAStart !< Time after which to calculate AA [s] + REAL(ReKi) :: z0_AA !< Surface roughness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ReListBL !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AoAListBL !< [deg] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Pres_DispThick !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Suct_DispThick !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Pres_BLThick !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Suct_BLThick !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Pres_Cf !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Suct_Cf !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Pres_EdgeVelRat !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Suct_EdgeVelRat !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI_Grid_In !< [-] + REAL(ReKi) :: dz_turb_in !< [m] + REAL(ReKi) :: dy_turb_in !< [m] + END TYPE AA_InputFile +! ======================= +! ========= AA_ContinuousStateType ======= + TYPE, PUBLIC :: AA_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE AA_ContinuousStateType +! ======================= +! ========= AA_DiscreteStateType ======= + TYPE, PUBLIC :: AA_DiscreteStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MeanVrel !< Vrel Cumu. Mean [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: VrelSq !< Vrel Squared Store [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIVrel !< Vrel St. deviat [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: VrelStore !< Vrel Store for fft - dissipation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIVx !< Vx St. deviat [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MeanVxVyVz !< Vrel Cumu. Mean [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: VxSq !< Vxl Squared Store [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: allregcounter !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: VxSqRegion !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: RegVxStor !< VxVyVz Store for fft or TI - dissipation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: RegionTIDelete !< [-] + END TYPE AA_DiscreteStateType +! ======================= +! ========= AA_ConstraintStateType ======= + TYPE, PUBLIC :: AA_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have states [-] + END TYPE AA_ConstraintStateType +! ======================= +! ========= AA_OtherStateType ======= + TYPE, PUBLIC :: AA_OtherStateType + REAL(SiKi) :: DummyOtherState !< Remove this variable if you have states [-] + END TYPE AA_OtherStateType +! ======================= +! ========= AA_MiscVarType ======= + TYPE, PUBLIC :: AA_MiscVarType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: ChordAngleTE !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SpanAngleTE !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: ChordAngleLE !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SpanAngleLE !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: rTEtoObserve !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: rLEtoObserve !< C [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: LE_Location !< Height of Leading Edge for calculation of TI and Scales if needed [-] + REAL(ReKi) :: RotSpeedAoA !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLLBL !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLP !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLS !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLALPH !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLTBL !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLTIP !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLTI !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLTIGui !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SPLBLUNT !< C [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CfVar !< Output Skin friction coef Pressure Side [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: d99Var !< BL Output [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dStarVar !< BL Output [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EdgeVelVar !< BL Output [-] + INTEGER(IntKi) :: speccou !< Secptrum counter every XX seconds new spectrum [-] + INTEGER(IntKi) :: filesopen !< check if file is open [-] + END TYPE AA_MiscVarType +! ======================= +! ========= AA_ParameterType ======= + TYPE, PUBLIC :: AA_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + INTEGER(IntKi) :: IBLUNT !< Bluntness noise model [-] + INTEGER(IntKi) :: ILAM !< LBL noise model [-] + INTEGER(IntKi) :: ITIP !< Tip noise model [-] + INTEGER(IntKi) :: ITRIP !< Trip boundary layer [-] + INTEGER(IntKi) :: ITURB !< Tblte noise model [-] + INTEGER(IntKi) :: IInflow !< Turbulent inflow noise model [-] + INTEGER(IntKi) :: X_BLMethod !< Integer describing calculation method for boundary layer properties, = 1 BPM = 2 Pretabulated [-] + INTEGER(IntKi) :: TICalcMeth !< [-] + LOGICAL :: ROUND !< Logical indicating rounded tip [-] + REAL(ReKi) :: ALPRAT !< TIP LIFT CURVE SLOPE [-] + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + INTEGER(IntKi) :: NumBlNds !< Number of nodes on each blade [-] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + REAL(ReKi) :: SpdSound !< Speed of sound [m/s] + REAL(ReKi) :: HubHeight !< Hub height [m] + REAL(ReKi) :: toptip !< Top Tip Height = Hub height plus radius [m] + REAL(ReKi) :: bottip !< Bottom Tip Height = Hub height minus radius [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rotorregionlimitsVert !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rotorregionlimitsHorz !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rotorregionlimitsalph !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rotorregionlimitsrad !< [-] + INTEGER(IntKi) :: NrObsLoc !< Number of observer locations [-] + LOGICAL :: aweightflag !< [-] + LOGICAL :: TxtFileOutput !< [-] + REAL(DbKi) :: AAStart !< Time after which to calculate AA [s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsX !< Observer location in tower-base coordinate X horizontal [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsY !< Observer location in tower-base coordinate Y lateral [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ObsZ !< Observer location in tower-base coordinate Z vertical [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FreqList !< List of Acoustic Frequencies to Calculate [Hz] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Aweight !< List of Acoustic Frequencies a weighting [dB] + REAL(ReKi) :: Fsample !< Sampling Frequency 1/delta(t) - 1/(simulation time step) [Hz] + INTEGER(IntKi) :: total_sample !< Total FFT Sample amount for dissipation calculation [-] + INTEGER(IntKi) :: total_sampleTI !< Total FFT Sample amount for dissipation calculation [-] + INTEGER(IntKi) :: AA_Bl_Prcntge !< The Percentage of the Blade which the noise is calculated [%] + INTEGER(IntKi) :: startnode !< Corersponding node to the noise calculation percentage of the blade [-] + REAL(ReKi) :: z0_aa !< Surface roughness [m] + REAL(ReKi) :: dz_turb_in !< [m] + REAL(ReKi) :: dy_turb_in !< [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI_Grid_In !< [-] + CHARACTER(1024) :: FTitle !< File Title: the 2nd line of the input file, which contains a description of its contents [-] + character(20) :: outFmt !< Format specifier [-] + INTEGER(IntKi) :: NrOutFile !< Nr of output files [-] + character(1) :: delim !< column delimiter [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + INTEGER(IntKi) :: NumOutsForPE !< Number of parameters in the output list (number of outputs requested) [-] + INTEGER(IntKi) :: NumOutsForSep !< Number of parameters in the output list (number of outputs requested) [-] + INTEGER(IntKi) :: NumOutsForNodes !< Number of parameters in the output list (number of outputs requested) [-] + INTEGER(IntKi) :: unOutFile !< unit number for writing output file [-] + INTEGER(IntKi) :: unOutFile2 !< unit number for writing output file [-] + INTEGER(IntKi) :: unOutFile3 !< unit number for writing output file [-] + INTEGER(IntKi) :: unOutFile4 !< unit number for writing output file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: StallStart !< ation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TEThick !< ation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TEAngle !< ation [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AerCent !< ation [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BlAFID !< Index of airfoil data file for blade node location [array of numBladeNodes by numBlades] [-] + TYPE(AFI_ParameterType) , DIMENSION(:), ALLOCATABLE :: AFInfo !< Airfoil information structure containing the aerodynamic center and airfoil shape coordinates [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AFLECo !< Dimensionalized [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AFTECo + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BlSpn !< Span at blade node [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BlChord !< Chord at blade node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ReListBL !< BL list of Reynolds [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AOAListBL !< BL list of Angle Of Attack [deg] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: dStarAll1 !< Output Disp Thickness Suction Side [m] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: dStarAll2 !< Output Disp Thickness Pressure Side [m] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: d99All1 !< Output B.L. Thickness Suction Side [m] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: d99All2 !< Output B.L. Thickness Pressure Side [m] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CfAll1 !< Output Skin friction coef Suction Side [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CfAll2 !< Output Skin friction coef Pressure Side [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: EdgeVelRat1 !< Output Edge Velocity Ratio Suction [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: EdgeVelRat2 !< Output Edge Velocity Ratio Pressure Side [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AFThickGuida !< 1 and 10 percent thickness t/c used for Simplified Guidati [-] + END TYPE AA_ParameterType +! ======================= +! ========= AA_InputType ======= + TYPE, PUBLIC :: AA_InputType + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: RotGtoL !< 3x3 rotation matrix transform a vector from the local airfoil coordinate system to the global inertial coordinate system [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AeroCent_G !< location in global coordinates of the blade element aerodynamic center. 1st index = vector components, 2nd index = blade node, 3rd index = blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vrel !< Vrel [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AoANoise !< Angle of attack [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Inflow !< atmospheric undisturbed flow on blade [-] + END TYPE AA_InputType +! ======================= +! ========= AA_OutputType ======= + TYPE, PUBLIC :: AA_OutputType + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SumSpecNoise !< Spectra of summed noise level of each blade and blade nodes for each receiver and frequency [SPL] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SumSpecNoiseSep !< Spectra of summed noise level of all blades and blade nodes for each receiver and frequency [SPL] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: OASPL !< summed noise level for each blade and blade nodes and receiver [SPL] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: OASPL_Mech !< 5 different mechanism noise level for each blade and blade nodes and receiver [SPL] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DirectiviOutput !< [SPL] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: OutLECoords !< [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PtotalFreq !< SPL for each observer and frequency [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutputForPE !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutputSep !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutputNode !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE AA_OutputType +! ======================= +CONTAINS + SUBROUTINE AA_CopyBladePropsType( SrcBladePropsTypeData, DstBladePropsTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_BladePropsType), INTENT(IN) :: SrcBladePropsTypeData + TYPE(AA_BladePropsType), INTENT(INOUT) :: DstBladePropsTypeData + 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 = 'AA_CopyBladePropsType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladePropsTypeData%NumBlNds = SrcBladePropsTypeData%NumBlNds +IF (ALLOCATED(SrcBladePropsTypeData%TEThick)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%TEThick,1) + i1_u = UBOUND(SrcBladePropsTypeData%TEThick,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%TEThick)) THEN + ALLOCATE(DstBladePropsTypeData%TEThick(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%TEThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%TEThick = SrcBladePropsTypeData%TEThick +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%StallStart)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%StallStart,1) + i1_u = UBOUND(SrcBladePropsTypeData%StallStart,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%StallStart)) THEN + ALLOCATE(DstBladePropsTypeData%StallStart(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%StallStart.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%StallStart = SrcBladePropsTypeData%StallStart +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%TEAngle)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%TEAngle,1) + i1_u = UBOUND(SrcBladePropsTypeData%TEAngle,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%TEAngle)) THEN + ALLOCATE(DstBladePropsTypeData%TEAngle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%TEAngle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%TEAngle = SrcBladePropsTypeData%TEAngle +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%AerCent)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%AerCent,1) + i1_u = UBOUND(SrcBladePropsTypeData%AerCent,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%AerCent)) THEN + ALLOCATE(DstBladePropsTypeData%AerCent(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%AerCent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%AerCent = SrcBladePropsTypeData%AerCent +ENDIF + END SUBROUTINE AA_CopyBladePropsType + + SUBROUTINE AA_DestroyBladePropsType( BladePropsTypeData, ErrStat, ErrMsg ) + TYPE(AA_BladePropsType), INTENT(INOUT) :: BladePropsTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyBladePropsType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladePropsTypeData%TEThick)) THEN + DEALLOCATE(BladePropsTypeData%TEThick) +ENDIF +IF (ALLOCATED(BladePropsTypeData%StallStart)) THEN + DEALLOCATE(BladePropsTypeData%StallStart) +ENDIF +IF (ALLOCATED(BladePropsTypeData%TEAngle)) THEN + DEALLOCATE(BladePropsTypeData%TEAngle) +ENDIF +IF (ALLOCATED(BladePropsTypeData%AerCent)) THEN + DEALLOCATE(BladePropsTypeData%AerCent) +ENDIF + END SUBROUTINE AA_DestroyBladePropsType + + SUBROUTINE AA_PackBladePropsType( 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(AA_BladePropsType), 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 = 'AA_PackBladePropsType' + ! 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 ! NumBlNds + Int_BufSz = Int_BufSz + 1 ! TEThick allocated yes/no + IF ( ALLOCATED(InData%TEThick) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TEThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TEThick) ! TEThick + END IF + Int_BufSz = Int_BufSz + 1 ! StallStart allocated yes/no + IF ( ALLOCATED(InData%StallStart) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StallStart upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StallStart) ! StallStart + END IF + Int_BufSz = Int_BufSz + 1 ! TEAngle allocated yes/no + IF ( ALLOCATED(InData%TEAngle) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TEAngle upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TEAngle) ! TEAngle + END IF + Int_BufSz = Int_BufSz + 1 ! AerCent allocated yes/no + IF ( ALLOCATED(InData%AerCent) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AerCent upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AerCent) ! AerCent + 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%NumBlNds + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TEThick) ) 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%TEThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEThick,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TEThick,1), UBOUND(InData%TEThick,1) + ReKiBuf(Re_Xferred) = InData%TEThick(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StallStart) ) 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%StallStart,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StallStart,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StallStart,1), UBOUND(InData%StallStart,1) + ReKiBuf(Re_Xferred) = InData%StallStart(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TEAngle) ) 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%TEAngle,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEAngle,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TEAngle,1), UBOUND(InData%TEAngle,1) + ReKiBuf(Re_Xferred) = InData%TEAngle(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AerCent) ) 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%AerCent,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AerCent,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AerCent,1), UBOUND(InData%AerCent,1) + ReKiBuf(Re_Xferred) = InData%AerCent(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AA_PackBladePropsType + + SUBROUTINE AA_UnPackBladePropsType( 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(AA_BladePropsType), 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 = 'AA_UnPackBladePropsType' + ! 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%NumBlNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TEThick 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%TEThick)) DEALLOCATE(OutData%TEThick) + ALLOCATE(OutData%TEThick(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TEThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TEThick,1), UBOUND(OutData%TEThick,1) + OutData%TEThick(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StallStart 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%StallStart)) DEALLOCATE(OutData%StallStart) + ALLOCATE(OutData%StallStart(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StallStart.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StallStart,1), UBOUND(OutData%StallStart,1) + OutData%StallStart(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TEAngle 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%TEAngle)) DEALLOCATE(OutData%TEAngle) + ALLOCATE(OutData%TEAngle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TEAngle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TEAngle,1), UBOUND(OutData%TEAngle,1) + OutData%TEAngle(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AerCent 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%AerCent)) DEALLOCATE(OutData%AerCent) + ALLOCATE(OutData%AerCent(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AerCent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AerCent,1), UBOUND(OutData%AerCent,1) + OutData%AerCent(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AA_UnPackBladePropsType + + SUBROUTINE AA_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(AA_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 = 'AA_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%NumBlades = SrcInitInputData%NumBlades + DstInitInputData%NumBlNds = SrcInitInputData%NumBlNds + DstInitInputData%RootName = SrcInitInputData%RootName +IF (ALLOCATED(SrcInitInputData%BlSpn)) THEN + i1_l = LBOUND(SrcInitInputData%BlSpn,1) + i1_u = UBOUND(SrcInitInputData%BlSpn,1) + i2_l = LBOUND(SrcInitInputData%BlSpn,2) + i2_u = UBOUND(SrcInitInputData%BlSpn,2) + IF (.NOT. ALLOCATED(DstInitInputData%BlSpn)) THEN + ALLOCATE(DstInitInputData%BlSpn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BlSpn = SrcInitInputData%BlSpn +ENDIF +IF (ALLOCATED(SrcInitInputData%BlChord)) THEN + i1_l = LBOUND(SrcInitInputData%BlChord,1) + i1_u = UBOUND(SrcInitInputData%BlChord,1) + i2_l = LBOUND(SrcInitInputData%BlChord,2) + i2_u = UBOUND(SrcInitInputData%BlChord,2) + IF (.NOT. ALLOCATED(DstInitInputData%BlChord)) THEN + ALLOCATE(DstInitInputData%BlChord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BlChord = SrcInitInputData%BlChord +ENDIF + DstInitInputData%AirDens = SrcInitInputData%AirDens + DstInitInputData%KinVisc = SrcInitInputData%KinVisc + DstInitInputData%SpdSound = SrcInitInputData%SpdSound + DstInitInputData%HubHeight = SrcInitInputData%HubHeight +IF (ALLOCATED(SrcInitInputData%BlAFID)) THEN + i1_l = LBOUND(SrcInitInputData%BlAFID,1) + i1_u = UBOUND(SrcInitInputData%BlAFID,1) + i2_l = LBOUND(SrcInitInputData%BlAFID,2) + i2_u = UBOUND(SrcInitInputData%BlAFID,2) + IF (.NOT. ALLOCATED(DstInitInputData%BlAFID)) THEN + ALLOCATE(DstInitInputData%BlAFID(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BlAFID = SrcInitInputData%BlAFID +ENDIF +IF (ALLOCATED(SrcInitInputData%AFInfo)) THEN + i1_l = LBOUND(SrcInitInputData%AFInfo,1) + i1_u = UBOUND(SrcInitInputData%AFInfo,1) + IF (.NOT. ALLOCATED(DstInitInputData%AFInfo)) THEN + ALLOCATE(DstInitInputData%AFInfo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%AFInfo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%AFInfo,1), UBOUND(SrcInitInputData%AFInfo,1) + CALL AFI_CopyParam( SrcInitInputData%AFInfo(i1), DstInitInputData%AFInfo(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + END SUBROUTINE AA_CopyInitInput + + SUBROUTINE AA_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(AA_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%BlSpn)) THEN + DEALLOCATE(InitInputData%BlSpn) +ENDIF +IF (ALLOCATED(InitInputData%BlChord)) THEN + DEALLOCATE(InitInputData%BlChord) +ENDIF +IF (ALLOCATED(InitInputData%BlAFID)) THEN + DEALLOCATE(InitInputData%BlAFID) +ENDIF +IF (ALLOCATED(InitInputData%AFInfo)) THEN +DO i1 = LBOUND(InitInputData%AFInfo,1), UBOUND(InitInputData%AFInfo,1) + CALL AFI_DestroyParam( InitInputData%AFInfo(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%AFInfo) +ENDIF + END SUBROUTINE AA_DestroyInitInput + + SUBROUTINE AA_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(AA_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 = 'AA_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumBlNds + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! BlSpn allocated yes/no + IF ( ALLOCATED(InData%BlSpn) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlSpn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlSpn) ! BlSpn + END IF + Int_BufSz = Int_BufSz + 1 ! BlChord allocated yes/no + IF ( ALLOCATED(InData%BlChord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlChord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlChord) ! BlChord + END IF + Re_BufSz = Re_BufSz + 1 ! AirDens + Re_BufSz = Re_BufSz + 1 ! KinVisc + Re_BufSz = Re_BufSz + 1 ! SpdSound + Re_BufSz = Re_BufSz + 1 ! HubHeight + Int_BufSz = Int_BufSz + 1 ! BlAFID allocated yes/no + IF ( ALLOCATED(InData%BlAFID) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlAFID upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BlAFID) ! BlAFID + END IF + Int_BufSz = Int_BufSz + 1 ! AFInfo allocated yes/no + IF ( ALLOCATED(InData%AFInfo) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AFInfo upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%AFInfo,1), UBOUND(InData%AFInfo,1) + Int_BufSz = Int_BufSz + 3 ! AFInfo: size of buffers for each call to pack subtype + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFInfo(i1), ErrStat2, ErrMsg2, .TRUE. ) ! AFInfo + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AFInfo + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AFInfo + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AFInfo + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlNds + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%BlSpn) ) 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%BlSpn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSpn,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlSpn,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSpn,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlSpn,2), UBOUND(InData%BlSpn,2) + DO i1 = LBOUND(InData%BlSpn,1), UBOUND(InData%BlSpn,1) + ReKiBuf(Re_Xferred) = InData%BlSpn(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlChord) ) 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%BlChord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlChord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlChord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlChord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlChord,2), UBOUND(InData%BlChord,2) + DO i1 = LBOUND(InData%BlChord,1), UBOUND(InData%BlChord,1) + ReKiBuf(Re_Xferred) = InData%BlChord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdSound + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubHeight + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlAFID) ) 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%BlAFID,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAFID,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlAFID,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAFID,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlAFID,2), UBOUND(InData%BlAFID,2) + DO i1 = LBOUND(InData%BlAFID,1), UBOUND(InData%BlAFID,1) + IntKiBuf(Int_Xferred) = InData%BlAFID(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFInfo) ) 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%AFInfo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFInfo,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AFInfo,1), UBOUND(InData%AFInfo,1) + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFInfo(i1), ErrStat2, ErrMsg2, OnlySize ) ! AFInfo + 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 + END SUBROUTINE AA_PackInitInput + + SUBROUTINE AA_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(AA_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 = 'AA_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlSpn 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%BlSpn)) DEALLOCATE(OutData%BlSpn) + ALLOCATE(OutData%BlSpn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlSpn,2), UBOUND(OutData%BlSpn,2) + DO i1 = LBOUND(OutData%BlSpn,1), UBOUND(OutData%BlSpn,1) + OutData%BlSpn(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlChord 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%BlChord)) DEALLOCATE(OutData%BlChord) + ALLOCATE(OutData%BlChord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlChord,2), UBOUND(OutData%BlChord,2) + DO i1 = LBOUND(OutData%BlChord,1), UBOUND(OutData%BlChord,1) + OutData%BlChord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpdSound = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlAFID 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%BlAFID)) DEALLOCATE(OutData%BlAFID) + ALLOCATE(OutData%BlAFID(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlAFID,2), UBOUND(OutData%BlAFID,2) + DO i1 = LBOUND(OutData%BlAFID,1), UBOUND(OutData%BlAFID,1) + OutData%BlAFID(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFInfo 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%AFInfo)) DEALLOCATE(OutData%AFInfo) + ALLOCATE(OutData%AFInfo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFInfo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AFInfo,1), UBOUND(OutData%AFInfo,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 AFI_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%AFInfo(i1), ErrStat2, ErrMsg2 ) ! AFInfo + 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 DO + END IF + END SUBROUTINE AA_UnPackInitInput + + SUBROUTINE AA_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(AA_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 = 'AA_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdrforPE)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdrforPE,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdrforPE,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdrforPE)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdrforPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdrforPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdrforPE = SrcInitOutputData%WriteOutputHdrforPE +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUntforPE)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUntforPE,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUntforPE,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUntforPE)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUntforPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUntforPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUntforPE = SrcInitOutputData%WriteOutputUntforPE +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdrSep)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdrSep,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdrSep,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdrSep)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdrSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdrSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdrSep = SrcInitOutputData%WriteOutputHdrSep +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUntSep)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUntSep,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUntSep,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUntSep)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUntSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUntSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUntSep = SrcInitOutputData%WriteOutputUntSep +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdrNodes)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdrNodes,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdrNodes,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdrNodes)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdrNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdrNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdrNodes = SrcInitOutputData%WriteOutputHdrNodes +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUntNodes)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUntNodes,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUntNodes,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUntNodes)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUntNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUntNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUntNodes = SrcInitOutputData%WriteOutputUntNodes +ENDIF + DstInitOutputData%delim = SrcInitOutputData%delim + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%AirDens = SrcInitOutputData%AirDens + END SUBROUTINE AA_CopyInitOutput + + SUBROUTINE AA_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(AA_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputHdrforPE)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdrforPE) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUntforPE)) THEN + DEALLOCATE(InitOutputData%WriteOutputUntforPE) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputHdrSep)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdrSep) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUntSep)) THEN + DEALLOCATE(InitOutputData%WriteOutputUntSep) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputHdrNodes)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdrNodes) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUntNodes)) THEN + DEALLOCATE(InitOutputData%WriteOutputUntNodes) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE AA_DestroyInitOutput + + SUBROUTINE AA_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(AA_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 = 'AA_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdrforPE allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdrforPE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdrforPE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdrforPE)*LEN(InData%WriteOutputHdrforPE) ! WriteOutputHdrforPE + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUntforPE allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUntforPE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUntforPE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUntforPE)*LEN(InData%WriteOutputUntforPE) ! WriteOutputUntforPE + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdrSep allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdrSep) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdrSep upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdrSep)*LEN(InData%WriteOutputHdrSep) ! WriteOutputHdrSep + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUntSep allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUntSep) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUntSep upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUntSep)*LEN(InData%WriteOutputUntSep) ! WriteOutputUntSep + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdrNodes allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdrNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdrNodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdrNodes)*LEN(InData%WriteOutputHdrNodes) ! WriteOutputHdrNodes + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUntNodes allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUntNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUntNodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUntNodes)*LEN(InData%WriteOutputUntNodes) ! WriteOutputUntNodes + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%delim) ! delim + ! 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 + 1 ! AirDens + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputHdrforPE) ) 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%WriteOutputHdrforPE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdrforPE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdrforPE,1), UBOUND(InData%WriteOutputHdrforPE,1) + DO I = 1, LEN(InData%WriteOutputHdrforPE) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdrforPE(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUntforPE) ) 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%WriteOutputUntforPE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUntforPE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUntforPE,1), UBOUND(InData%WriteOutputUntforPE,1) + DO I = 1, LEN(InData%WriteOutputUntforPE) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUntforPE(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputHdrSep) ) 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%WriteOutputHdrSep,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdrSep,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdrSep,1), UBOUND(InData%WriteOutputHdrSep,1) + DO I = 1, LEN(InData%WriteOutputHdrSep) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdrSep(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUntSep) ) 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%WriteOutputUntSep,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUntSep,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUntSep,1), UBOUND(InData%WriteOutputUntSep,1) + DO I = 1, LEN(InData%WriteOutputUntSep) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUntSep(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputHdrNodes) ) 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%WriteOutputHdrNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdrNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdrNodes,1), UBOUND(InData%WriteOutputHdrNodes,1) + DO I = 1, LEN(InData%WriteOutputHdrNodes) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdrNodes(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUntNodes) ) 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%WriteOutputUntNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUntNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUntNodes,1), UBOUND(InData%WriteOutputUntNodes,1) + DO I = 1, LEN(InData%WriteOutputUntNodes) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUntNodes(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_PackInitOutput + + SUBROUTINE AA_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(AA_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 = 'AA_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdrforPE 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%WriteOutputHdrforPE)) DEALLOCATE(OutData%WriteOutputHdrforPE) + ALLOCATE(OutData%WriteOutputHdrforPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdrforPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdrforPE,1), UBOUND(OutData%WriteOutputHdrforPE,1) + DO I = 1, LEN(OutData%WriteOutputHdrforPE) + OutData%WriteOutputHdrforPE(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUntforPE 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%WriteOutputUntforPE)) DEALLOCATE(OutData%WriteOutputUntforPE) + ALLOCATE(OutData%WriteOutputUntforPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUntforPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUntforPE,1), UBOUND(OutData%WriteOutputUntforPE,1) + DO I = 1, LEN(OutData%WriteOutputUntforPE) + OutData%WriteOutputUntforPE(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdrSep 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%WriteOutputHdrSep)) DEALLOCATE(OutData%WriteOutputHdrSep) + ALLOCATE(OutData%WriteOutputHdrSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdrSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdrSep,1), UBOUND(OutData%WriteOutputHdrSep,1) + DO I = 1, LEN(OutData%WriteOutputHdrSep) + OutData%WriteOutputHdrSep(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUntSep 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%WriteOutputUntSep)) DEALLOCATE(OutData%WriteOutputUntSep) + ALLOCATE(OutData%WriteOutputUntSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUntSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUntSep,1), UBOUND(OutData%WriteOutputUntSep,1) + DO I = 1, LEN(OutData%WriteOutputUntSep) + OutData%WriteOutputUntSep(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdrNodes 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%WriteOutputHdrNodes)) DEALLOCATE(OutData%WriteOutputHdrNodes) + ALLOCATE(OutData%WriteOutputHdrNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdrNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdrNodes,1), UBOUND(OutData%WriteOutputHdrNodes,1) + DO I = 1, LEN(OutData%WriteOutputHdrNodes) + OutData%WriteOutputHdrNodes(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUntNodes 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%WriteOutputUntNodes)) DEALLOCATE(OutData%WriteOutputUntNodes) + ALLOCATE(OutData%WriteOutputUntNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUntNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUntNodes,1), UBOUND(OutData%WriteOutputUntNodes,1) + DO I = 1, LEN(OutData%WriteOutputUntNodes) + OutData%WriteOutputUntNodes(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%delim) + OutData%delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_UnPackInitOutput + + SUBROUTINE AA_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(AA_InputFile), INTENT(INOUT) :: DstInputFileData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DT_AA = SrcInputFileData%DT_AA + DstInputFileData%IBLUNT = SrcInputFileData%IBLUNT + DstInputFileData%ILAM = SrcInputFileData%ILAM + DstInputFileData%ITIP = SrcInputFileData%ITIP + DstInputFileData%ITRIP = SrcInputFileData%ITRIP + DstInputFileData%ITURB = SrcInputFileData%ITURB + DstInputFileData%IInflow = SrcInputFileData%IInflow + DstInputFileData%X_BLMethod = SrcInputFileData%X_BLMethod + DstInputFileData%TICalcMeth = SrcInputFileData%TICalcMeth + DstInputFileData%NReListBL = SrcInputFileData%NReListBL + DstInputFileData%aweightflag = SrcInputFileData%aweightflag + DstInputFileData%ROUND = SrcInputFileData%ROUND + DstInputFileData%ALPRAT = SrcInputFileData%ALPRAT + DstInputFileData%AA_Bl_Prcntge = SrcInputFileData%AA_Bl_Prcntge + DstInputFileData%NrObsLoc = SrcInputFileData%NrObsLoc +IF (ALLOCATED(SrcInputFileData%ObsX)) THEN + i1_l = LBOUND(SrcInputFileData%ObsX,1) + i1_u = UBOUND(SrcInputFileData%ObsX,1) + IF (.NOT. ALLOCATED(DstInputFileData%ObsX)) THEN + ALLOCATE(DstInputFileData%ObsX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ObsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ObsX = SrcInputFileData%ObsX +ENDIF +IF (ALLOCATED(SrcInputFileData%ObsY)) THEN + i1_l = LBOUND(SrcInputFileData%ObsY,1) + i1_u = UBOUND(SrcInputFileData%ObsY,1) + IF (.NOT. ALLOCATED(DstInputFileData%ObsY)) THEN + ALLOCATE(DstInputFileData%ObsY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ObsY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ObsY = SrcInputFileData%ObsY +ENDIF +IF (ALLOCATED(SrcInputFileData%ObsZ)) THEN + i1_l = LBOUND(SrcInputFileData%ObsZ,1) + i1_u = UBOUND(SrcInputFileData%ObsZ,1) + IF (.NOT. ALLOCATED(DstInputFileData%ObsZ)) THEN + ALLOCATE(DstInputFileData%ObsZ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ObsZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ObsZ = SrcInputFileData%ObsZ +ENDIF +IF (ALLOCATED(SrcInputFileData%BladeProps)) THEN + i1_l = LBOUND(SrcInputFileData%BladeProps,1) + i1_u = UBOUND(SrcInputFileData%BladeProps,1) + IF (.NOT. ALLOCATED(DstInputFileData%BladeProps)) THEN + ALLOCATE(DstInputFileData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputFileData%BladeProps,1), UBOUND(SrcInputFileData%BladeProps,1) + CALL AA_Copybladepropstype( SrcInputFileData%BladeProps(i1), DstInputFileData%BladeProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInputFileData%NrOutFile = SrcInputFileData%NrOutFile +IF (ALLOCATED(SrcInputFileData%AAoutfile)) THEN + i1_l = LBOUND(SrcInputFileData%AAoutfile,1) + i1_u = UBOUND(SrcInputFileData%AAoutfile,1) + IF (.NOT. ALLOCATED(DstInputFileData%AAoutfile)) THEN + ALLOCATE(DstInputFileData%AAoutfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%AAoutfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%AAoutfile = SrcInputFileData%AAoutfile +ENDIF + DstInputFileData%TICalcTabFile = SrcInputFileData%TICalcTabFile + DstInputFileData%FTitle = SrcInputFileData%FTitle + DstInputFileData%AAStart = SrcInputFileData%AAStart + DstInputFileData%z0_AA = SrcInputFileData%z0_AA +IF (ALLOCATED(SrcInputFileData%ReListBL)) THEN + i1_l = LBOUND(SrcInputFileData%ReListBL,1) + i1_u = UBOUND(SrcInputFileData%ReListBL,1) + IF (.NOT. ALLOCATED(DstInputFileData%ReListBL)) THEN + ALLOCATE(DstInputFileData%ReListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ReListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ReListBL = SrcInputFileData%ReListBL +ENDIF +IF (ALLOCATED(SrcInputFileData%AoAListBL)) THEN + i1_l = LBOUND(SrcInputFileData%AoAListBL,1) + i1_u = UBOUND(SrcInputFileData%AoAListBL,1) + IF (.NOT. ALLOCATED(DstInputFileData%AoAListBL)) THEN + ALLOCATE(DstInputFileData%AoAListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%AoAListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%AoAListBL = SrcInputFileData%AoAListBL +ENDIF +IF (ALLOCATED(SrcInputFileData%Pres_DispThick)) THEN + i1_l = LBOUND(SrcInputFileData%Pres_DispThick,1) + i1_u = UBOUND(SrcInputFileData%Pres_DispThick,1) + i2_l = LBOUND(SrcInputFileData%Pres_DispThick,2) + i2_u = UBOUND(SrcInputFileData%Pres_DispThick,2) + i3_l = LBOUND(SrcInputFileData%Pres_DispThick,3) + i3_u = UBOUND(SrcInputFileData%Pres_DispThick,3) + IF (.NOT. ALLOCATED(DstInputFileData%Pres_DispThick)) THEN + ALLOCATE(DstInputFileData%Pres_DispThick(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Pres_DispThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Pres_DispThick = SrcInputFileData%Pres_DispThick +ENDIF +IF (ALLOCATED(SrcInputFileData%Suct_DispThick)) THEN + i1_l = LBOUND(SrcInputFileData%Suct_DispThick,1) + i1_u = UBOUND(SrcInputFileData%Suct_DispThick,1) + i2_l = LBOUND(SrcInputFileData%Suct_DispThick,2) + i2_u = UBOUND(SrcInputFileData%Suct_DispThick,2) + i3_l = LBOUND(SrcInputFileData%Suct_DispThick,3) + i3_u = UBOUND(SrcInputFileData%Suct_DispThick,3) + IF (.NOT. ALLOCATED(DstInputFileData%Suct_DispThick)) THEN + ALLOCATE(DstInputFileData%Suct_DispThick(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Suct_DispThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Suct_DispThick = SrcInputFileData%Suct_DispThick +ENDIF +IF (ALLOCATED(SrcInputFileData%Pres_BLThick)) THEN + i1_l = LBOUND(SrcInputFileData%Pres_BLThick,1) + i1_u = UBOUND(SrcInputFileData%Pres_BLThick,1) + i2_l = LBOUND(SrcInputFileData%Pres_BLThick,2) + i2_u = UBOUND(SrcInputFileData%Pres_BLThick,2) + i3_l = LBOUND(SrcInputFileData%Pres_BLThick,3) + i3_u = UBOUND(SrcInputFileData%Pres_BLThick,3) + IF (.NOT. ALLOCATED(DstInputFileData%Pres_BLThick)) THEN + ALLOCATE(DstInputFileData%Pres_BLThick(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Pres_BLThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Pres_BLThick = SrcInputFileData%Pres_BLThick +ENDIF +IF (ALLOCATED(SrcInputFileData%Suct_BLThick)) THEN + i1_l = LBOUND(SrcInputFileData%Suct_BLThick,1) + i1_u = UBOUND(SrcInputFileData%Suct_BLThick,1) + i2_l = LBOUND(SrcInputFileData%Suct_BLThick,2) + i2_u = UBOUND(SrcInputFileData%Suct_BLThick,2) + i3_l = LBOUND(SrcInputFileData%Suct_BLThick,3) + i3_u = UBOUND(SrcInputFileData%Suct_BLThick,3) + IF (.NOT. ALLOCATED(DstInputFileData%Suct_BLThick)) THEN + ALLOCATE(DstInputFileData%Suct_BLThick(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Suct_BLThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Suct_BLThick = SrcInputFileData%Suct_BLThick +ENDIF +IF (ALLOCATED(SrcInputFileData%Pres_Cf)) THEN + i1_l = LBOUND(SrcInputFileData%Pres_Cf,1) + i1_u = UBOUND(SrcInputFileData%Pres_Cf,1) + i2_l = LBOUND(SrcInputFileData%Pres_Cf,2) + i2_u = UBOUND(SrcInputFileData%Pres_Cf,2) + i3_l = LBOUND(SrcInputFileData%Pres_Cf,3) + i3_u = UBOUND(SrcInputFileData%Pres_Cf,3) + IF (.NOT. ALLOCATED(DstInputFileData%Pres_Cf)) THEN + ALLOCATE(DstInputFileData%Pres_Cf(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Pres_Cf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Pres_Cf = SrcInputFileData%Pres_Cf +ENDIF +IF (ALLOCATED(SrcInputFileData%Suct_Cf)) THEN + i1_l = LBOUND(SrcInputFileData%Suct_Cf,1) + i1_u = UBOUND(SrcInputFileData%Suct_Cf,1) + i2_l = LBOUND(SrcInputFileData%Suct_Cf,2) + i2_u = UBOUND(SrcInputFileData%Suct_Cf,2) + i3_l = LBOUND(SrcInputFileData%Suct_Cf,3) + i3_u = UBOUND(SrcInputFileData%Suct_Cf,3) + IF (.NOT. ALLOCATED(DstInputFileData%Suct_Cf)) THEN + ALLOCATE(DstInputFileData%Suct_Cf(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Suct_Cf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Suct_Cf = SrcInputFileData%Suct_Cf +ENDIF +IF (ALLOCATED(SrcInputFileData%Pres_EdgeVelRat)) THEN + i1_l = LBOUND(SrcInputFileData%Pres_EdgeVelRat,1) + i1_u = UBOUND(SrcInputFileData%Pres_EdgeVelRat,1) + i2_l = LBOUND(SrcInputFileData%Pres_EdgeVelRat,2) + i2_u = UBOUND(SrcInputFileData%Pres_EdgeVelRat,2) + i3_l = LBOUND(SrcInputFileData%Pres_EdgeVelRat,3) + i3_u = UBOUND(SrcInputFileData%Pres_EdgeVelRat,3) + IF (.NOT. ALLOCATED(DstInputFileData%Pres_EdgeVelRat)) THEN + ALLOCATE(DstInputFileData%Pres_EdgeVelRat(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Pres_EdgeVelRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Pres_EdgeVelRat = SrcInputFileData%Pres_EdgeVelRat +ENDIF +IF (ALLOCATED(SrcInputFileData%Suct_EdgeVelRat)) THEN + i1_l = LBOUND(SrcInputFileData%Suct_EdgeVelRat,1) + i1_u = UBOUND(SrcInputFileData%Suct_EdgeVelRat,1) + i2_l = LBOUND(SrcInputFileData%Suct_EdgeVelRat,2) + i2_u = UBOUND(SrcInputFileData%Suct_EdgeVelRat,2) + i3_l = LBOUND(SrcInputFileData%Suct_EdgeVelRat,3) + i3_u = UBOUND(SrcInputFileData%Suct_EdgeVelRat,3) + IF (.NOT. ALLOCATED(DstInputFileData%Suct_EdgeVelRat)) THEN + ALLOCATE(DstInputFileData%Suct_EdgeVelRat(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Suct_EdgeVelRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Suct_EdgeVelRat = SrcInputFileData%Suct_EdgeVelRat +ENDIF +IF (ALLOCATED(SrcInputFileData%TI_Grid_In)) THEN + i1_l = LBOUND(SrcInputFileData%TI_Grid_In,1) + i1_u = UBOUND(SrcInputFileData%TI_Grid_In,1) + i2_l = LBOUND(SrcInputFileData%TI_Grid_In,2) + i2_u = UBOUND(SrcInputFileData%TI_Grid_In,2) + IF (.NOT. ALLOCATED(DstInputFileData%TI_Grid_In)) THEN + ALLOCATE(DstInputFileData%TI_Grid_In(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TI_Grid_In.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TI_Grid_In = SrcInputFileData%TI_Grid_In +ENDIF + DstInputFileData%dz_turb_in = SrcInputFileData%dz_turb_in + DstInputFileData%dy_turb_in = SrcInputFileData%dy_turb_in + END SUBROUTINE AA_CopyInputFile + + SUBROUTINE AA_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(AA_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%ObsX)) THEN + DEALLOCATE(InputFileData%ObsX) +ENDIF +IF (ALLOCATED(InputFileData%ObsY)) THEN + DEALLOCATE(InputFileData%ObsY) +ENDIF +IF (ALLOCATED(InputFileData%ObsZ)) THEN + DEALLOCATE(InputFileData%ObsZ) +ENDIF +IF (ALLOCATED(InputFileData%BladeProps)) THEN +DO i1 = LBOUND(InputFileData%BladeProps,1), UBOUND(InputFileData%BladeProps,1) + CALL AA_Destroybladepropstype( InputFileData%BladeProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputFileData%BladeProps) +ENDIF +IF (ALLOCATED(InputFileData%AAoutfile)) THEN + DEALLOCATE(InputFileData%AAoutfile) +ENDIF +IF (ALLOCATED(InputFileData%ReListBL)) THEN + DEALLOCATE(InputFileData%ReListBL) +ENDIF +IF (ALLOCATED(InputFileData%AoAListBL)) THEN + DEALLOCATE(InputFileData%AoAListBL) +ENDIF +IF (ALLOCATED(InputFileData%Pres_DispThick)) THEN + DEALLOCATE(InputFileData%Pres_DispThick) +ENDIF +IF (ALLOCATED(InputFileData%Suct_DispThick)) THEN + DEALLOCATE(InputFileData%Suct_DispThick) +ENDIF +IF (ALLOCATED(InputFileData%Pres_BLThick)) THEN + DEALLOCATE(InputFileData%Pres_BLThick) +ENDIF +IF (ALLOCATED(InputFileData%Suct_BLThick)) THEN + DEALLOCATE(InputFileData%Suct_BLThick) +ENDIF +IF (ALLOCATED(InputFileData%Pres_Cf)) THEN + DEALLOCATE(InputFileData%Pres_Cf) +ENDIF +IF (ALLOCATED(InputFileData%Suct_Cf)) THEN + DEALLOCATE(InputFileData%Suct_Cf) +ENDIF +IF (ALLOCATED(InputFileData%Pres_EdgeVelRat)) THEN + DEALLOCATE(InputFileData%Pres_EdgeVelRat) +ENDIF +IF (ALLOCATED(InputFileData%Suct_EdgeVelRat)) THEN + DEALLOCATE(InputFileData%Suct_EdgeVelRat) +ENDIF +IF (ALLOCATED(InputFileData%TI_Grid_In)) THEN + DEALLOCATE(InputFileData%TI_Grid_In) +ENDIF + END SUBROUTINE AA_DestroyInputFile + + SUBROUTINE AA_PackInputFile( 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(AA_InputFile), 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 = 'AA_PackInputFile' + ! 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 + Db_BufSz = Db_BufSz + 1 ! DT_AA + Int_BufSz = Int_BufSz + 1 ! IBLUNT + Int_BufSz = Int_BufSz + 1 ! ILAM + Int_BufSz = Int_BufSz + 1 ! ITIP + Int_BufSz = Int_BufSz + 1 ! ITRIP + Int_BufSz = Int_BufSz + 1 ! ITURB + Int_BufSz = Int_BufSz + 1 ! IInflow + Int_BufSz = Int_BufSz + 1 ! X_BLMethod + Int_BufSz = Int_BufSz + 1 ! TICalcMeth + Int_BufSz = Int_BufSz + 1 ! NReListBL + Int_BufSz = Int_BufSz + 1 ! aweightflag + Int_BufSz = Int_BufSz + 1 ! ROUND + Re_BufSz = Re_BufSz + 1 ! ALPRAT + Int_BufSz = Int_BufSz + 1 ! AA_Bl_Prcntge + Int_BufSz = Int_BufSz + 1 ! NrObsLoc + Int_BufSz = Int_BufSz + 1 ! ObsX allocated yes/no + IF ( ALLOCATED(InData%ObsX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsX) ! ObsX + END IF + Int_BufSz = Int_BufSz + 1 ! ObsY allocated yes/no + IF ( ALLOCATED(InData%ObsY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsY) ! ObsY + END IF + Int_BufSz = Int_BufSz + 1 ! ObsZ allocated yes/no + IF ( ALLOCATED(InData%ObsZ) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsZ) ! ObsZ + END IF + Int_BufSz = Int_BufSz + 1 ! BladeProps allocated yes/no + IF ( ALLOCATED(InData%BladeProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeProps upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + Int_BufSz = Int_BufSz + 3 ! BladeProps: size of buffers for each call to pack subtype + CALL AA_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BladeProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NrOutFile + Int_BufSz = Int_BufSz + 1 ! AAoutfile allocated yes/no + IF ( ALLOCATED(InData%AAoutfile) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AAoutfile upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AAoutfile)*LEN(InData%AAoutfile) ! AAoutfile + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%TICalcTabFile) ! TICalcTabFile + Int_BufSz = Int_BufSz + 1*LEN(InData%FTitle) ! FTitle + Db_BufSz = Db_BufSz + 1 ! AAStart + Re_BufSz = Re_BufSz + 1 ! z0_AA + Int_BufSz = Int_BufSz + 1 ! ReListBL allocated yes/no + IF ( ALLOCATED(InData%ReListBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ReListBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ReListBL) ! ReListBL + END IF + Int_BufSz = Int_BufSz + 1 ! AoAListBL allocated yes/no + IF ( ALLOCATED(InData%AoAListBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AoAListBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AoAListBL) ! AoAListBL + END IF + Int_BufSz = Int_BufSz + 1 ! Pres_DispThick allocated yes/no + IF ( ALLOCATED(InData%Pres_DispThick) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Pres_DispThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Pres_DispThick) ! Pres_DispThick + END IF + Int_BufSz = Int_BufSz + 1 ! Suct_DispThick allocated yes/no + IF ( ALLOCATED(InData%Suct_DispThick) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Suct_DispThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Suct_DispThick) ! Suct_DispThick + END IF + Int_BufSz = Int_BufSz + 1 ! Pres_BLThick allocated yes/no + IF ( ALLOCATED(InData%Pres_BLThick) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Pres_BLThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Pres_BLThick) ! Pres_BLThick + END IF + Int_BufSz = Int_BufSz + 1 ! Suct_BLThick allocated yes/no + IF ( ALLOCATED(InData%Suct_BLThick) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Suct_BLThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Suct_BLThick) ! Suct_BLThick + END IF + Int_BufSz = Int_BufSz + 1 ! Pres_Cf allocated yes/no + IF ( ALLOCATED(InData%Pres_Cf) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Pres_Cf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Pres_Cf) ! Pres_Cf + END IF + Int_BufSz = Int_BufSz + 1 ! Suct_Cf allocated yes/no + IF ( ALLOCATED(InData%Suct_Cf) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Suct_Cf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Suct_Cf) ! Suct_Cf + END IF + Int_BufSz = Int_BufSz + 1 ! Pres_EdgeVelRat allocated yes/no + IF ( ALLOCATED(InData%Pres_EdgeVelRat) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Pres_EdgeVelRat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Pres_EdgeVelRat) ! Pres_EdgeVelRat + END IF + Int_BufSz = Int_BufSz + 1 ! Suct_EdgeVelRat allocated yes/no + IF ( ALLOCATED(InData%Suct_EdgeVelRat) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Suct_EdgeVelRat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Suct_EdgeVelRat) ! Suct_EdgeVelRat + END IF + Int_BufSz = Int_BufSz + 1 ! TI_Grid_In allocated yes/no + IF ( ALLOCATED(InData%TI_Grid_In) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI_Grid_In upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI_Grid_In) ! TI_Grid_In + END IF + Re_BufSz = Re_BufSz + 1 ! dz_turb_in + Re_BufSz = Re_BufSz + 1 ! dy_turb_in + 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 + + DbKiBuf(Db_Xferred) = InData%DT_AA + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IBLUNT + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ILAM + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITIP + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITRIP + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITURB + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IInflow + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%X_BLMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TICalcMeth + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NReListBL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%aweightflag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ROUND, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ALPRAT + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AA_Bl_Prcntge + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NrObsLoc + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ObsX) ) 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%ObsX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsX,1), UBOUND(InData%ObsX,1) + ReKiBuf(Re_Xferred) = InData%ObsX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ObsY) ) 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%ObsY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsY,1), UBOUND(InData%ObsY,1) + ReKiBuf(Re_Xferred) = InData%ObsY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ObsZ) ) 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%ObsZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsZ,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsZ,1), UBOUND(InData%ObsZ,1) + ReKiBuf(Re_Xferred) = InData%ObsZ(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BladeProps) ) 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%BladeProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + CALL AA_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! BladeProps + 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 + IntKiBuf(Int_Xferred) = InData%NrOutFile + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AAoutfile) ) 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%AAoutfile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AAoutfile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AAoutfile,1), UBOUND(InData%AAoutfile,1) + DO I = 1, LEN(InData%AAoutfile) + IntKiBuf(Int_Xferred) = ICHAR(InData%AAoutfile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%TICalcTabFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%TICalcTabFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%FTitle) + IntKiBuf(Int_Xferred) = ICHAR(InData%FTitle(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%AAStart + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%z0_AA + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ReListBL) ) 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%ReListBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ReListBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ReListBL,1), UBOUND(InData%ReListBL,1) + ReKiBuf(Re_Xferred) = InData%ReListBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AoAListBL) ) 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%AoAListBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AoAListBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AoAListBL,1), UBOUND(InData%AoAListBL,1) + ReKiBuf(Re_Xferred) = InData%AoAListBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pres_DispThick) ) 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%Pres_DispThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_DispThick,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_DispThick,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_DispThick,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_DispThick,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_DispThick,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Pres_DispThick,3), UBOUND(InData%Pres_DispThick,3) + DO i2 = LBOUND(InData%Pres_DispThick,2), UBOUND(InData%Pres_DispThick,2) + DO i1 = LBOUND(InData%Pres_DispThick,1), UBOUND(InData%Pres_DispThick,1) + ReKiBuf(Re_Xferred) = InData%Pres_DispThick(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Suct_DispThick) ) 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%Suct_DispThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_DispThick,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_DispThick,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_DispThick,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_DispThick,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_DispThick,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Suct_DispThick,3), UBOUND(InData%Suct_DispThick,3) + DO i2 = LBOUND(InData%Suct_DispThick,2), UBOUND(InData%Suct_DispThick,2) + DO i1 = LBOUND(InData%Suct_DispThick,1), UBOUND(InData%Suct_DispThick,1) + ReKiBuf(Re_Xferred) = InData%Suct_DispThick(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pres_BLThick) ) 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%Pres_BLThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_BLThick,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_BLThick,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_BLThick,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_BLThick,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_BLThick,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Pres_BLThick,3), UBOUND(InData%Pres_BLThick,3) + DO i2 = LBOUND(InData%Pres_BLThick,2), UBOUND(InData%Pres_BLThick,2) + DO i1 = LBOUND(InData%Pres_BLThick,1), UBOUND(InData%Pres_BLThick,1) + ReKiBuf(Re_Xferred) = InData%Pres_BLThick(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Suct_BLThick) ) 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%Suct_BLThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_BLThick,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_BLThick,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_BLThick,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_BLThick,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_BLThick,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Suct_BLThick,3), UBOUND(InData%Suct_BLThick,3) + DO i2 = LBOUND(InData%Suct_BLThick,2), UBOUND(InData%Suct_BLThick,2) + DO i1 = LBOUND(InData%Suct_BLThick,1), UBOUND(InData%Suct_BLThick,1) + ReKiBuf(Re_Xferred) = InData%Suct_BLThick(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pres_Cf) ) 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%Pres_Cf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_Cf,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_Cf,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_Cf,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_Cf,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_Cf,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Pres_Cf,3), UBOUND(InData%Pres_Cf,3) + DO i2 = LBOUND(InData%Pres_Cf,2), UBOUND(InData%Pres_Cf,2) + DO i1 = LBOUND(InData%Pres_Cf,1), UBOUND(InData%Pres_Cf,1) + ReKiBuf(Re_Xferred) = InData%Pres_Cf(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Suct_Cf) ) 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%Suct_Cf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_Cf,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_Cf,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_Cf,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_Cf,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_Cf,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Suct_Cf,3), UBOUND(InData%Suct_Cf,3) + DO i2 = LBOUND(InData%Suct_Cf,2), UBOUND(InData%Suct_Cf,2) + DO i1 = LBOUND(InData%Suct_Cf,1), UBOUND(InData%Suct_Cf,1) + ReKiBuf(Re_Xferred) = InData%Suct_Cf(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pres_EdgeVelRat) ) 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%Pres_EdgeVelRat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_EdgeVelRat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_EdgeVelRat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_EdgeVelRat,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pres_EdgeVelRat,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pres_EdgeVelRat,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Pres_EdgeVelRat,3), UBOUND(InData%Pres_EdgeVelRat,3) + DO i2 = LBOUND(InData%Pres_EdgeVelRat,2), UBOUND(InData%Pres_EdgeVelRat,2) + DO i1 = LBOUND(InData%Pres_EdgeVelRat,1), UBOUND(InData%Pres_EdgeVelRat,1) + ReKiBuf(Re_Xferred) = InData%Pres_EdgeVelRat(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Suct_EdgeVelRat) ) 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%Suct_EdgeVelRat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_EdgeVelRat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_EdgeVelRat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_EdgeVelRat,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Suct_EdgeVelRat,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Suct_EdgeVelRat,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Suct_EdgeVelRat,3), UBOUND(InData%Suct_EdgeVelRat,3) + DO i2 = LBOUND(InData%Suct_EdgeVelRat,2), UBOUND(InData%Suct_EdgeVelRat,2) + DO i1 = LBOUND(InData%Suct_EdgeVelRat,1), UBOUND(InData%Suct_EdgeVelRat,1) + ReKiBuf(Re_Xferred) = InData%Suct_EdgeVelRat(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TI_Grid_In) ) 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%TI_Grid_In,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_Grid_In,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI_Grid_In,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_Grid_In,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TI_Grid_In,2), UBOUND(InData%TI_Grid_In,2) + DO i1 = LBOUND(InData%TI_Grid_In,1), UBOUND(InData%TI_Grid_In,1) + ReKiBuf(Re_Xferred) = InData%TI_Grid_In(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%dz_turb_in + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dy_turb_in + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_PackInputFile + + SUBROUTINE AA_UnPackInputFile( 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(AA_InputFile), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_UnPackInputFile' + ! 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%DT_AA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%IBLUNT = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ILAM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITIP = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITRIP = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITURB = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IInflow = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%X_BLMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TICalcMeth = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NReListBL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%aweightflag = TRANSFER(IntKiBuf(Int_Xferred), OutData%aweightflag) + Int_Xferred = Int_Xferred + 1 + OutData%ROUND = TRANSFER(IntKiBuf(Int_Xferred), OutData%ROUND) + Int_Xferred = Int_Xferred + 1 + OutData%ALPRAT = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AA_Bl_Prcntge = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NrObsLoc = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsX 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%ObsX)) DEALLOCATE(OutData%ObsX) + ALLOCATE(OutData%ObsX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsX,1), UBOUND(OutData%ObsX,1) + OutData%ObsX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsY 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%ObsY)) DEALLOCATE(OutData%ObsY) + ALLOCATE(OutData%ObsY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsY,1), UBOUND(OutData%ObsY,1) + OutData%ObsY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsZ 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%ObsZ)) DEALLOCATE(OutData%ObsZ) + ALLOCATE(OutData%ObsZ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsZ,1), UBOUND(OutData%ObsZ,1) + OutData%ObsZ(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeProps 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%BladeProps)) DEALLOCATE(OutData%BladeProps) + ALLOCATE(OutData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeProps,1), UBOUND(OutData%BladeProps,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 AA_Unpackbladepropstype( Re_Buf, Db_Buf, Int_Buf, OutData%BladeProps(i1), ErrStat2, ErrMsg2 ) ! BladeProps + 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 DO + END IF + OutData%NrOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AAoutfile 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%AAoutfile)) DEALLOCATE(OutData%AAoutfile) + ALLOCATE(OutData%AAoutfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AAoutfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AAoutfile,1), UBOUND(OutData%AAoutfile,1) + DO I = 1, LEN(OutData%AAoutfile) + OutData%AAoutfile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%TICalcTabFile) + OutData%TICalcTabFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%FTitle) + OutData%FTitle(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%AAStart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%z0_AA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ReListBL 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%ReListBL)) DEALLOCATE(OutData%ReListBL) + ALLOCATE(OutData%ReListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ReListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ReListBL,1), UBOUND(OutData%ReListBL,1) + OutData%ReListBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AoAListBL 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%AoAListBL)) DEALLOCATE(OutData%AoAListBL) + ALLOCATE(OutData%AoAListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AoAListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AoAListBL,1), UBOUND(OutData%AoAListBL,1) + OutData%AoAListBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pres_DispThick 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%Pres_DispThick)) DEALLOCATE(OutData%Pres_DispThick) + ALLOCATE(OutData%Pres_DispThick(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%Pres_DispThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Pres_DispThick,3), UBOUND(OutData%Pres_DispThick,3) + DO i2 = LBOUND(OutData%Pres_DispThick,2), UBOUND(OutData%Pres_DispThick,2) + DO i1 = LBOUND(OutData%Pres_DispThick,1), UBOUND(OutData%Pres_DispThick,1) + OutData%Pres_DispThick(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Suct_DispThick 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%Suct_DispThick)) DEALLOCATE(OutData%Suct_DispThick) + ALLOCATE(OutData%Suct_DispThick(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%Suct_DispThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Suct_DispThick,3), UBOUND(OutData%Suct_DispThick,3) + DO i2 = LBOUND(OutData%Suct_DispThick,2), UBOUND(OutData%Suct_DispThick,2) + DO i1 = LBOUND(OutData%Suct_DispThick,1), UBOUND(OutData%Suct_DispThick,1) + OutData%Suct_DispThick(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pres_BLThick 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%Pres_BLThick)) DEALLOCATE(OutData%Pres_BLThick) + ALLOCATE(OutData%Pres_BLThick(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%Pres_BLThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Pres_BLThick,3), UBOUND(OutData%Pres_BLThick,3) + DO i2 = LBOUND(OutData%Pres_BLThick,2), UBOUND(OutData%Pres_BLThick,2) + DO i1 = LBOUND(OutData%Pres_BLThick,1), UBOUND(OutData%Pres_BLThick,1) + OutData%Pres_BLThick(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Suct_BLThick 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%Suct_BLThick)) DEALLOCATE(OutData%Suct_BLThick) + ALLOCATE(OutData%Suct_BLThick(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%Suct_BLThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Suct_BLThick,3), UBOUND(OutData%Suct_BLThick,3) + DO i2 = LBOUND(OutData%Suct_BLThick,2), UBOUND(OutData%Suct_BLThick,2) + DO i1 = LBOUND(OutData%Suct_BLThick,1), UBOUND(OutData%Suct_BLThick,1) + OutData%Suct_BLThick(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pres_Cf 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%Pres_Cf)) DEALLOCATE(OutData%Pres_Cf) + ALLOCATE(OutData%Pres_Cf(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%Pres_Cf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Pres_Cf,3), UBOUND(OutData%Pres_Cf,3) + DO i2 = LBOUND(OutData%Pres_Cf,2), UBOUND(OutData%Pres_Cf,2) + DO i1 = LBOUND(OutData%Pres_Cf,1), UBOUND(OutData%Pres_Cf,1) + OutData%Pres_Cf(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Suct_Cf 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%Suct_Cf)) DEALLOCATE(OutData%Suct_Cf) + ALLOCATE(OutData%Suct_Cf(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%Suct_Cf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Suct_Cf,3), UBOUND(OutData%Suct_Cf,3) + DO i2 = LBOUND(OutData%Suct_Cf,2), UBOUND(OutData%Suct_Cf,2) + DO i1 = LBOUND(OutData%Suct_Cf,1), UBOUND(OutData%Suct_Cf,1) + OutData%Suct_Cf(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pres_EdgeVelRat 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%Pres_EdgeVelRat)) DEALLOCATE(OutData%Pres_EdgeVelRat) + ALLOCATE(OutData%Pres_EdgeVelRat(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%Pres_EdgeVelRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Pres_EdgeVelRat,3), UBOUND(OutData%Pres_EdgeVelRat,3) + DO i2 = LBOUND(OutData%Pres_EdgeVelRat,2), UBOUND(OutData%Pres_EdgeVelRat,2) + DO i1 = LBOUND(OutData%Pres_EdgeVelRat,1), UBOUND(OutData%Pres_EdgeVelRat,1) + OutData%Pres_EdgeVelRat(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Suct_EdgeVelRat 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%Suct_EdgeVelRat)) DEALLOCATE(OutData%Suct_EdgeVelRat) + ALLOCATE(OutData%Suct_EdgeVelRat(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%Suct_EdgeVelRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Suct_EdgeVelRat,3), UBOUND(OutData%Suct_EdgeVelRat,3) + DO i2 = LBOUND(OutData%Suct_EdgeVelRat,2), UBOUND(OutData%Suct_EdgeVelRat,2) + DO i1 = LBOUND(OutData%Suct_EdgeVelRat,1), UBOUND(OutData%Suct_EdgeVelRat,1) + OutData%Suct_EdgeVelRat(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI_Grid_In 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%TI_Grid_In)) DEALLOCATE(OutData%TI_Grid_In) + ALLOCATE(OutData%TI_Grid_In(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI_Grid_In.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TI_Grid_In,2), UBOUND(OutData%TI_Grid_In,2) + DO i1 = LBOUND(OutData%TI_Grid_In,1), UBOUND(OutData%TI_Grid_In,1) + OutData%TI_Grid_In(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%dz_turb_in = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dy_turb_in = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_UnPackInputFile + + SUBROUTINE AA_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(AA_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 = 'AA_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE AA_CopyContState + + SUBROUTINE AA_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(AA_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AA_DestroyContState + + SUBROUTINE AA_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(AA_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 = 'AA_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 AA_PackContState + + SUBROUTINE AA_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(AA_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 = 'AA_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_UnPackContState + + SUBROUTINE AA_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(AA_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcDiscStateData%MeanVrel)) THEN + i1_l = LBOUND(SrcDiscStateData%MeanVrel,1) + i1_u = UBOUND(SrcDiscStateData%MeanVrel,1) + i2_l = LBOUND(SrcDiscStateData%MeanVrel,2) + i2_u = UBOUND(SrcDiscStateData%MeanVrel,2) + IF (.NOT. ALLOCATED(DstDiscStateData%MeanVrel)) THEN + ALLOCATE(DstDiscStateData%MeanVrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%MeanVrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%MeanVrel = SrcDiscStateData%MeanVrel +ENDIF +IF (ALLOCATED(SrcDiscStateData%VrelSq)) THEN + i1_l = LBOUND(SrcDiscStateData%VrelSq,1) + i1_u = UBOUND(SrcDiscStateData%VrelSq,1) + i2_l = LBOUND(SrcDiscStateData%VrelSq,2) + i2_u = UBOUND(SrcDiscStateData%VrelSq,2) + IF (.NOT. ALLOCATED(DstDiscStateData%VrelSq)) THEN + ALLOCATE(DstDiscStateData%VrelSq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%VrelSq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%VrelSq = SrcDiscStateData%VrelSq +ENDIF +IF (ALLOCATED(SrcDiscStateData%TIVrel)) THEN + i1_l = LBOUND(SrcDiscStateData%TIVrel,1) + i1_u = UBOUND(SrcDiscStateData%TIVrel,1) + i2_l = LBOUND(SrcDiscStateData%TIVrel,2) + i2_u = UBOUND(SrcDiscStateData%TIVrel,2) + IF (.NOT. ALLOCATED(DstDiscStateData%TIVrel)) THEN + ALLOCATE(DstDiscStateData%TIVrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%TIVrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%TIVrel = SrcDiscStateData%TIVrel +ENDIF +IF (ALLOCATED(SrcDiscStateData%VrelStore)) THEN + i1_l = LBOUND(SrcDiscStateData%VrelStore,1) + i1_u = UBOUND(SrcDiscStateData%VrelStore,1) + i2_l = LBOUND(SrcDiscStateData%VrelStore,2) + i2_u = UBOUND(SrcDiscStateData%VrelStore,2) + i3_l = LBOUND(SrcDiscStateData%VrelStore,3) + i3_u = UBOUND(SrcDiscStateData%VrelStore,3) + IF (.NOT. ALLOCATED(DstDiscStateData%VrelStore)) THEN + ALLOCATE(DstDiscStateData%VrelStore(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%VrelStore.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%VrelStore = SrcDiscStateData%VrelStore +ENDIF +IF (ALLOCATED(SrcDiscStateData%TIVx)) THEN + i1_l = LBOUND(SrcDiscStateData%TIVx,1) + i1_u = UBOUND(SrcDiscStateData%TIVx,1) + i2_l = LBOUND(SrcDiscStateData%TIVx,2) + i2_u = UBOUND(SrcDiscStateData%TIVx,2) + IF (.NOT. ALLOCATED(DstDiscStateData%TIVx)) THEN + ALLOCATE(DstDiscStateData%TIVx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%TIVx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%TIVx = SrcDiscStateData%TIVx +ENDIF +IF (ALLOCATED(SrcDiscStateData%MeanVxVyVz)) THEN + i1_l = LBOUND(SrcDiscStateData%MeanVxVyVz,1) + i1_u = UBOUND(SrcDiscStateData%MeanVxVyVz,1) + i2_l = LBOUND(SrcDiscStateData%MeanVxVyVz,2) + i2_u = UBOUND(SrcDiscStateData%MeanVxVyVz,2) + IF (.NOT. ALLOCATED(DstDiscStateData%MeanVxVyVz)) THEN + ALLOCATE(DstDiscStateData%MeanVxVyVz(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%MeanVxVyVz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%MeanVxVyVz = SrcDiscStateData%MeanVxVyVz +ENDIF +IF (ALLOCATED(SrcDiscStateData%VxSq)) THEN + i1_l = LBOUND(SrcDiscStateData%VxSq,1) + i1_u = UBOUND(SrcDiscStateData%VxSq,1) + i2_l = LBOUND(SrcDiscStateData%VxSq,2) + i2_u = UBOUND(SrcDiscStateData%VxSq,2) + IF (.NOT. ALLOCATED(DstDiscStateData%VxSq)) THEN + ALLOCATE(DstDiscStateData%VxSq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%VxSq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%VxSq = SrcDiscStateData%VxSq +ENDIF +IF (ALLOCATED(SrcDiscStateData%allregcounter)) THEN + i1_l = LBOUND(SrcDiscStateData%allregcounter,1) + i1_u = UBOUND(SrcDiscStateData%allregcounter,1) + i2_l = LBOUND(SrcDiscStateData%allregcounter,2) + i2_u = UBOUND(SrcDiscStateData%allregcounter,2) + IF (.NOT. ALLOCATED(DstDiscStateData%allregcounter)) THEN + ALLOCATE(DstDiscStateData%allregcounter(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%allregcounter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%allregcounter = SrcDiscStateData%allregcounter +ENDIF +IF (ALLOCATED(SrcDiscStateData%VxSqRegion)) THEN + i1_l = LBOUND(SrcDiscStateData%VxSqRegion,1) + i1_u = UBOUND(SrcDiscStateData%VxSqRegion,1) + i2_l = LBOUND(SrcDiscStateData%VxSqRegion,2) + i2_u = UBOUND(SrcDiscStateData%VxSqRegion,2) + IF (.NOT. ALLOCATED(DstDiscStateData%VxSqRegion)) THEN + ALLOCATE(DstDiscStateData%VxSqRegion(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%VxSqRegion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%VxSqRegion = SrcDiscStateData%VxSqRegion +ENDIF +IF (ALLOCATED(SrcDiscStateData%RegVxStor)) THEN + i1_l = LBOUND(SrcDiscStateData%RegVxStor,1) + i1_u = UBOUND(SrcDiscStateData%RegVxStor,1) + i2_l = LBOUND(SrcDiscStateData%RegVxStor,2) + i2_u = UBOUND(SrcDiscStateData%RegVxStor,2) + i3_l = LBOUND(SrcDiscStateData%RegVxStor,3) + i3_u = UBOUND(SrcDiscStateData%RegVxStor,3) + IF (.NOT. ALLOCATED(DstDiscStateData%RegVxStor)) THEN + ALLOCATE(DstDiscStateData%RegVxStor(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%RegVxStor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%RegVxStor = SrcDiscStateData%RegVxStor +ENDIF +IF (ALLOCATED(SrcDiscStateData%RegionTIDelete)) THEN + i1_l = LBOUND(SrcDiscStateData%RegionTIDelete,1) + i1_u = UBOUND(SrcDiscStateData%RegionTIDelete,1) + i2_l = LBOUND(SrcDiscStateData%RegionTIDelete,2) + i2_u = UBOUND(SrcDiscStateData%RegionTIDelete,2) + IF (.NOT. ALLOCATED(DstDiscStateData%RegionTIDelete)) THEN + ALLOCATE(DstDiscStateData%RegionTIDelete(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%RegionTIDelete.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%RegionTIDelete = SrcDiscStateData%RegionTIDelete +ENDIF + END SUBROUTINE AA_CopyDiscState + + SUBROUTINE AA_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(AA_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(DiscStateData%MeanVrel)) THEN + DEALLOCATE(DiscStateData%MeanVrel) +ENDIF +IF (ALLOCATED(DiscStateData%VrelSq)) THEN + DEALLOCATE(DiscStateData%VrelSq) +ENDIF +IF (ALLOCATED(DiscStateData%TIVrel)) THEN + DEALLOCATE(DiscStateData%TIVrel) +ENDIF +IF (ALLOCATED(DiscStateData%VrelStore)) THEN + DEALLOCATE(DiscStateData%VrelStore) +ENDIF +IF (ALLOCATED(DiscStateData%TIVx)) THEN + DEALLOCATE(DiscStateData%TIVx) +ENDIF +IF (ALLOCATED(DiscStateData%MeanVxVyVz)) THEN + DEALLOCATE(DiscStateData%MeanVxVyVz) +ENDIF +IF (ALLOCATED(DiscStateData%VxSq)) THEN + DEALLOCATE(DiscStateData%VxSq) +ENDIF +IF (ALLOCATED(DiscStateData%allregcounter)) THEN + DEALLOCATE(DiscStateData%allregcounter) +ENDIF +IF (ALLOCATED(DiscStateData%VxSqRegion)) THEN + DEALLOCATE(DiscStateData%VxSqRegion) +ENDIF +IF (ALLOCATED(DiscStateData%RegVxStor)) THEN + DEALLOCATE(DiscStateData%RegVxStor) +ENDIF +IF (ALLOCATED(DiscStateData%RegionTIDelete)) THEN + DEALLOCATE(DiscStateData%RegionTIDelete) +ENDIF + END SUBROUTINE AA_DestroyDiscState + + SUBROUTINE AA_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(AA_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 = 'AA_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 + Int_BufSz = Int_BufSz + 1 ! MeanVrel allocated yes/no + IF ( ALLOCATED(InData%MeanVrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MeanVrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MeanVrel) ! MeanVrel + END IF + Int_BufSz = Int_BufSz + 1 ! VrelSq allocated yes/no + IF ( ALLOCATED(InData%VrelSq) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! VrelSq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VrelSq) ! VrelSq + END IF + Int_BufSz = Int_BufSz + 1 ! TIVrel allocated yes/no + IF ( ALLOCATED(InData%TIVrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TIVrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TIVrel) ! TIVrel + END IF + Int_BufSz = Int_BufSz + 1 ! VrelStore allocated yes/no + IF ( ALLOCATED(InData%VrelStore) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! VrelStore upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VrelStore) ! VrelStore + END IF + Int_BufSz = Int_BufSz + 1 ! TIVx allocated yes/no + IF ( ALLOCATED(InData%TIVx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TIVx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TIVx) ! TIVx + END IF + Int_BufSz = Int_BufSz + 1 ! MeanVxVyVz allocated yes/no + IF ( ALLOCATED(InData%MeanVxVyVz) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MeanVxVyVz upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MeanVxVyVz) ! MeanVxVyVz + END IF + Int_BufSz = Int_BufSz + 1 ! VxSq allocated yes/no + IF ( ALLOCATED(InData%VxSq) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! VxSq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VxSq) ! VxSq + END IF + Int_BufSz = Int_BufSz + 1 ! allregcounter allocated yes/no + IF ( ALLOCATED(InData%allregcounter) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! allregcounter upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%allregcounter) ! allregcounter + END IF + Int_BufSz = Int_BufSz + 1 ! VxSqRegion allocated yes/no + IF ( ALLOCATED(InData%VxSqRegion) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! VxSqRegion upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VxSqRegion) ! VxSqRegion + END IF + Int_BufSz = Int_BufSz + 1 ! RegVxStor allocated yes/no + IF ( ALLOCATED(InData%RegVxStor) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! RegVxStor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RegVxStor) ! RegVxStor + END IF + Int_BufSz = Int_BufSz + 1 ! RegionTIDelete allocated yes/no + IF ( ALLOCATED(InData%RegionTIDelete) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RegionTIDelete upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RegionTIDelete) ! RegionTIDelete + 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%MeanVrel) ) 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%MeanVrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeanVrel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MeanVrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeanVrel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MeanVrel,2), UBOUND(InData%MeanVrel,2) + DO i1 = LBOUND(InData%MeanVrel,1), UBOUND(InData%MeanVrel,1) + ReKiBuf(Re_Xferred) = InData%MeanVrel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VrelSq) ) 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%VrelSq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VrelSq,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VrelSq,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VrelSq,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%VrelSq,2), UBOUND(InData%VrelSq,2) + DO i1 = LBOUND(InData%VrelSq,1), UBOUND(InData%VrelSq,1) + ReKiBuf(Re_Xferred) = InData%VrelSq(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TIVrel) ) 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%TIVrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIVrel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TIVrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIVrel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TIVrel,2), UBOUND(InData%TIVrel,2) + DO i1 = LBOUND(InData%TIVrel,1), UBOUND(InData%TIVrel,1) + ReKiBuf(Re_Xferred) = InData%TIVrel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VrelStore) ) 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%VrelStore,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VrelStore,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VrelStore,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VrelStore,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VrelStore,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VrelStore,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%VrelStore,3), UBOUND(InData%VrelStore,3) + DO i2 = LBOUND(InData%VrelStore,2), UBOUND(InData%VrelStore,2) + DO i1 = LBOUND(InData%VrelStore,1), UBOUND(InData%VrelStore,1) + ReKiBuf(Re_Xferred) = InData%VrelStore(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TIVx) ) 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%TIVx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIVx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TIVx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIVx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TIVx,2), UBOUND(InData%TIVx,2) + DO i1 = LBOUND(InData%TIVx,1), UBOUND(InData%TIVx,1) + ReKiBuf(Re_Xferred) = InData%TIVx(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MeanVxVyVz) ) 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%MeanVxVyVz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeanVxVyVz,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MeanVxVyVz,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeanVxVyVz,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MeanVxVyVz,2), UBOUND(InData%MeanVxVyVz,2) + DO i1 = LBOUND(InData%MeanVxVyVz,1), UBOUND(InData%MeanVxVyVz,1) + ReKiBuf(Re_Xferred) = InData%MeanVxVyVz(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VxSq) ) 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%VxSq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VxSq,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VxSq,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VxSq,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%VxSq,2), UBOUND(InData%VxSq,2) + DO i1 = LBOUND(InData%VxSq,1), UBOUND(InData%VxSq,1) + ReKiBuf(Re_Xferred) = InData%VxSq(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%allregcounter) ) 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%allregcounter,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%allregcounter,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%allregcounter,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%allregcounter,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%allregcounter,2), UBOUND(InData%allregcounter,2) + DO i1 = LBOUND(InData%allregcounter,1), UBOUND(InData%allregcounter,1) + ReKiBuf(Re_Xferred) = InData%allregcounter(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VxSqRegion) ) 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%VxSqRegion,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VxSqRegion,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VxSqRegion,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VxSqRegion,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%VxSqRegion,2), UBOUND(InData%VxSqRegion,2) + DO i1 = LBOUND(InData%VxSqRegion,1), UBOUND(InData%VxSqRegion,1) + ReKiBuf(Re_Xferred) = InData%VxSqRegion(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RegVxStor) ) 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%RegVxStor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RegVxStor,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RegVxStor,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RegVxStor,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RegVxStor,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RegVxStor,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%RegVxStor,3), UBOUND(InData%RegVxStor,3) + DO i2 = LBOUND(InData%RegVxStor,2), UBOUND(InData%RegVxStor,2) + DO i1 = LBOUND(InData%RegVxStor,1), UBOUND(InData%RegVxStor,1) + ReKiBuf(Re_Xferred) = InData%RegVxStor(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RegionTIDelete) ) 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%RegionTIDelete,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RegionTIDelete,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RegionTIDelete,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RegionTIDelete,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RegionTIDelete,2), UBOUND(InData%RegionTIDelete,2) + DO i1 = LBOUND(InData%RegionTIDelete,1), UBOUND(InData%RegionTIDelete,1) + ReKiBuf(Re_Xferred) = InData%RegionTIDelete(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AA_PackDiscState + + SUBROUTINE AA_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(AA_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MeanVrel 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%MeanVrel)) DEALLOCATE(OutData%MeanVrel) + ALLOCATE(OutData%MeanVrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MeanVrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MeanVrel,2), UBOUND(OutData%MeanVrel,2) + DO i1 = LBOUND(OutData%MeanVrel,1), UBOUND(OutData%MeanVrel,1) + OutData%MeanVrel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VrelSq 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%VrelSq)) DEALLOCATE(OutData%VrelSq) + ALLOCATE(OutData%VrelSq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VrelSq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%VrelSq,2), UBOUND(OutData%VrelSq,2) + DO i1 = LBOUND(OutData%VrelSq,1), UBOUND(OutData%VrelSq,1) + OutData%VrelSq(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TIVrel 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%TIVrel)) DEALLOCATE(OutData%TIVrel) + ALLOCATE(OutData%TIVrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TIVrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TIVrel,2), UBOUND(OutData%TIVrel,2) + DO i1 = LBOUND(OutData%TIVrel,1), UBOUND(OutData%TIVrel,1) + OutData%TIVrel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VrelStore 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%VrelStore)) DEALLOCATE(OutData%VrelStore) + ALLOCATE(OutData%VrelStore(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%VrelStore.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%VrelStore,3), UBOUND(OutData%VrelStore,3) + DO i2 = LBOUND(OutData%VrelStore,2), UBOUND(OutData%VrelStore,2) + DO i1 = LBOUND(OutData%VrelStore,1), UBOUND(OutData%VrelStore,1) + OutData%VrelStore(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TIVx 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%TIVx)) DEALLOCATE(OutData%TIVx) + ALLOCATE(OutData%TIVx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TIVx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TIVx,2), UBOUND(OutData%TIVx,2) + DO i1 = LBOUND(OutData%TIVx,1), UBOUND(OutData%TIVx,1) + OutData%TIVx(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MeanVxVyVz 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%MeanVxVyVz)) DEALLOCATE(OutData%MeanVxVyVz) + ALLOCATE(OutData%MeanVxVyVz(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MeanVxVyVz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MeanVxVyVz,2), UBOUND(OutData%MeanVxVyVz,2) + DO i1 = LBOUND(OutData%MeanVxVyVz,1), UBOUND(OutData%MeanVxVyVz,1) + OutData%MeanVxVyVz(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VxSq 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%VxSq)) DEALLOCATE(OutData%VxSq) + ALLOCATE(OutData%VxSq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VxSq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%VxSq,2), UBOUND(OutData%VxSq,2) + DO i1 = LBOUND(OutData%VxSq,1), UBOUND(OutData%VxSq,1) + OutData%VxSq(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! allregcounter 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%allregcounter)) DEALLOCATE(OutData%allregcounter) + ALLOCATE(OutData%allregcounter(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%allregcounter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%allregcounter,2), UBOUND(OutData%allregcounter,2) + DO i1 = LBOUND(OutData%allregcounter,1), UBOUND(OutData%allregcounter,1) + OutData%allregcounter(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VxSqRegion 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%VxSqRegion)) DEALLOCATE(OutData%VxSqRegion) + ALLOCATE(OutData%VxSqRegion(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VxSqRegion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%VxSqRegion,2), UBOUND(OutData%VxSqRegion,2) + DO i1 = LBOUND(OutData%VxSqRegion,1), UBOUND(OutData%VxSqRegion,1) + OutData%VxSqRegion(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RegVxStor 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%RegVxStor)) DEALLOCATE(OutData%RegVxStor) + ALLOCATE(OutData%RegVxStor(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%RegVxStor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%RegVxStor,3), UBOUND(OutData%RegVxStor,3) + DO i2 = LBOUND(OutData%RegVxStor,2), UBOUND(OutData%RegVxStor,2) + DO i1 = LBOUND(OutData%RegVxStor,1), UBOUND(OutData%RegVxStor,1) + OutData%RegVxStor(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RegionTIDelete 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%RegionTIDelete)) DEALLOCATE(OutData%RegionTIDelete) + ALLOCATE(OutData%RegionTIDelete(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RegionTIDelete.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RegionTIDelete,2), UBOUND(OutData%RegionTIDelete,2) + DO i1 = LBOUND(OutData%RegionTIDelete,1), UBOUND(OutData%RegionTIDelete,1) + OutData%RegionTIDelete(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AA_UnPackDiscState + + SUBROUTINE AA_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(AA_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 = 'AA_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE AA_CopyConstrState + + SUBROUTINE AA_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(AA_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AA_DestroyConstrState + + SUBROUTINE AA_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(AA_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 = 'AA_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 AA_PackConstrState + + SUBROUTINE AA_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(AA_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 = 'AA_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_UnPackConstrState + + SUBROUTINE AA_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(AA_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 = 'AA_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE AA_CopyOtherState + + SUBROUTINE AA_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(AA_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AA_DestroyOtherState + + SUBROUTINE AA_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(AA_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 = 'AA_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 AA_PackOtherState + + SUBROUTINE AA_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(AA_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 = 'AA_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AA_UnPackOtherState + + SUBROUTINE AA_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(AA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%AllOuts)) THEN + i1_l = LBOUND(SrcMiscData%AllOuts,1) + i1_u = UBOUND(SrcMiscData%AllOuts,1) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF +IF (ALLOCATED(SrcMiscData%ChordAngleTE)) THEN + i1_l = LBOUND(SrcMiscData%ChordAngleTE,1) + i1_u = UBOUND(SrcMiscData%ChordAngleTE,1) + i2_l = LBOUND(SrcMiscData%ChordAngleTE,2) + i2_u = UBOUND(SrcMiscData%ChordAngleTE,2) + i3_l = LBOUND(SrcMiscData%ChordAngleTE,3) + i3_u = UBOUND(SrcMiscData%ChordAngleTE,3) + IF (.NOT. ALLOCATED(DstMiscData%ChordAngleTE)) THEN + ALLOCATE(DstMiscData%ChordAngleTE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ChordAngleTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ChordAngleTE = SrcMiscData%ChordAngleTE +ENDIF +IF (ALLOCATED(SrcMiscData%SpanAngleTE)) THEN + i1_l = LBOUND(SrcMiscData%SpanAngleTE,1) + i1_u = UBOUND(SrcMiscData%SpanAngleTE,1) + i2_l = LBOUND(SrcMiscData%SpanAngleTE,2) + i2_u = UBOUND(SrcMiscData%SpanAngleTE,2) + i3_l = LBOUND(SrcMiscData%SpanAngleTE,3) + i3_u = UBOUND(SrcMiscData%SpanAngleTE,3) + IF (.NOT. ALLOCATED(DstMiscData%SpanAngleTE)) THEN + ALLOCATE(DstMiscData%SpanAngleTE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SpanAngleTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SpanAngleTE = SrcMiscData%SpanAngleTE +ENDIF +IF (ALLOCATED(SrcMiscData%ChordAngleLE)) THEN + i1_l = LBOUND(SrcMiscData%ChordAngleLE,1) + i1_u = UBOUND(SrcMiscData%ChordAngleLE,1) + i2_l = LBOUND(SrcMiscData%ChordAngleLE,2) + i2_u = UBOUND(SrcMiscData%ChordAngleLE,2) + i3_l = LBOUND(SrcMiscData%ChordAngleLE,3) + i3_u = UBOUND(SrcMiscData%ChordAngleLE,3) + IF (.NOT. ALLOCATED(DstMiscData%ChordAngleLE)) THEN + ALLOCATE(DstMiscData%ChordAngleLE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ChordAngleLE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ChordAngleLE = SrcMiscData%ChordAngleLE +ENDIF +IF (ALLOCATED(SrcMiscData%SpanAngleLE)) THEN + i1_l = LBOUND(SrcMiscData%SpanAngleLE,1) + i1_u = UBOUND(SrcMiscData%SpanAngleLE,1) + i2_l = LBOUND(SrcMiscData%SpanAngleLE,2) + i2_u = UBOUND(SrcMiscData%SpanAngleLE,2) + i3_l = LBOUND(SrcMiscData%SpanAngleLE,3) + i3_u = UBOUND(SrcMiscData%SpanAngleLE,3) + IF (.NOT. ALLOCATED(DstMiscData%SpanAngleLE)) THEN + ALLOCATE(DstMiscData%SpanAngleLE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SpanAngleLE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SpanAngleLE = SrcMiscData%SpanAngleLE +ENDIF +IF (ALLOCATED(SrcMiscData%rTEtoObserve)) THEN + i1_l = LBOUND(SrcMiscData%rTEtoObserve,1) + i1_u = UBOUND(SrcMiscData%rTEtoObserve,1) + i2_l = LBOUND(SrcMiscData%rTEtoObserve,2) + i2_u = UBOUND(SrcMiscData%rTEtoObserve,2) + i3_l = LBOUND(SrcMiscData%rTEtoObserve,3) + i3_u = UBOUND(SrcMiscData%rTEtoObserve,3) + IF (.NOT. ALLOCATED(DstMiscData%rTEtoObserve)) THEN + ALLOCATE(DstMiscData%rTEtoObserve(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%rTEtoObserve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%rTEtoObserve = SrcMiscData%rTEtoObserve +ENDIF +IF (ALLOCATED(SrcMiscData%rLEtoObserve)) THEN + i1_l = LBOUND(SrcMiscData%rLEtoObserve,1) + i1_u = UBOUND(SrcMiscData%rLEtoObserve,1) + i2_l = LBOUND(SrcMiscData%rLEtoObserve,2) + i2_u = UBOUND(SrcMiscData%rLEtoObserve,2) + i3_l = LBOUND(SrcMiscData%rLEtoObserve,3) + i3_u = UBOUND(SrcMiscData%rLEtoObserve,3) + IF (.NOT. ALLOCATED(DstMiscData%rLEtoObserve)) THEN + ALLOCATE(DstMiscData%rLEtoObserve(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%rLEtoObserve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%rLEtoObserve = SrcMiscData%rLEtoObserve +ENDIF +IF (ALLOCATED(SrcMiscData%LE_Location)) THEN + i1_l = LBOUND(SrcMiscData%LE_Location,1) + i1_u = UBOUND(SrcMiscData%LE_Location,1) + i2_l = LBOUND(SrcMiscData%LE_Location,2) + i2_u = UBOUND(SrcMiscData%LE_Location,2) + i3_l = LBOUND(SrcMiscData%LE_Location,3) + i3_u = UBOUND(SrcMiscData%LE_Location,3) + IF (.NOT. ALLOCATED(DstMiscData%LE_Location)) THEN + ALLOCATE(DstMiscData%LE_Location(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LE_Location.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LE_Location = SrcMiscData%LE_Location +ENDIF + DstMiscData%RotSpeedAoA = SrcMiscData%RotSpeedAoA +IF (ALLOCATED(SrcMiscData%SPLLBL)) THEN + i1_l = LBOUND(SrcMiscData%SPLLBL,1) + i1_u = UBOUND(SrcMiscData%SPLLBL,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLLBL)) THEN + ALLOCATE(DstMiscData%SPLLBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLLBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLLBL = SrcMiscData%SPLLBL +ENDIF +IF (ALLOCATED(SrcMiscData%SPLP)) THEN + i1_l = LBOUND(SrcMiscData%SPLP,1) + i1_u = UBOUND(SrcMiscData%SPLP,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLP)) THEN + ALLOCATE(DstMiscData%SPLP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLP = SrcMiscData%SPLP +ENDIF +IF (ALLOCATED(SrcMiscData%SPLS)) THEN + i1_l = LBOUND(SrcMiscData%SPLS,1) + i1_u = UBOUND(SrcMiscData%SPLS,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLS)) THEN + ALLOCATE(DstMiscData%SPLS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLS = SrcMiscData%SPLS +ENDIF +IF (ALLOCATED(SrcMiscData%SPLALPH)) THEN + i1_l = LBOUND(SrcMiscData%SPLALPH,1) + i1_u = UBOUND(SrcMiscData%SPLALPH,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLALPH)) THEN + ALLOCATE(DstMiscData%SPLALPH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLALPH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLALPH = SrcMiscData%SPLALPH +ENDIF +IF (ALLOCATED(SrcMiscData%SPLTBL)) THEN + i1_l = LBOUND(SrcMiscData%SPLTBL,1) + i1_u = UBOUND(SrcMiscData%SPLTBL,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLTBL)) THEN + ALLOCATE(DstMiscData%SPLTBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLTBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLTBL = SrcMiscData%SPLTBL +ENDIF +IF (ALLOCATED(SrcMiscData%SPLTIP)) THEN + i1_l = LBOUND(SrcMiscData%SPLTIP,1) + i1_u = UBOUND(SrcMiscData%SPLTIP,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLTIP)) THEN + ALLOCATE(DstMiscData%SPLTIP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLTIP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLTIP = SrcMiscData%SPLTIP +ENDIF +IF (ALLOCATED(SrcMiscData%SPLTI)) THEN + i1_l = LBOUND(SrcMiscData%SPLTI,1) + i1_u = UBOUND(SrcMiscData%SPLTI,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLTI)) THEN + ALLOCATE(DstMiscData%SPLTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLTI = SrcMiscData%SPLTI +ENDIF +IF (ALLOCATED(SrcMiscData%SPLTIGui)) THEN + i1_l = LBOUND(SrcMiscData%SPLTIGui,1) + i1_u = UBOUND(SrcMiscData%SPLTIGui,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLTIGui)) THEN + ALLOCATE(DstMiscData%SPLTIGui(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLTIGui.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLTIGui = SrcMiscData%SPLTIGui +ENDIF +IF (ALLOCATED(SrcMiscData%SPLBLUNT)) THEN + i1_l = LBOUND(SrcMiscData%SPLBLUNT,1) + i1_u = UBOUND(SrcMiscData%SPLBLUNT,1) + IF (.NOT. ALLOCATED(DstMiscData%SPLBLUNT)) THEN + ALLOCATE(DstMiscData%SPLBLUNT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SPLBLUNT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SPLBLUNT = SrcMiscData%SPLBLUNT +ENDIF +IF (ALLOCATED(SrcMiscData%CfVar)) THEN + i1_l = LBOUND(SrcMiscData%CfVar,1) + i1_u = UBOUND(SrcMiscData%CfVar,1) + IF (.NOT. ALLOCATED(DstMiscData%CfVar)) THEN + ALLOCATE(DstMiscData%CfVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CfVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CfVar = SrcMiscData%CfVar +ENDIF +IF (ALLOCATED(SrcMiscData%d99Var)) THEN + i1_l = LBOUND(SrcMiscData%d99Var,1) + i1_u = UBOUND(SrcMiscData%d99Var,1) + IF (.NOT. ALLOCATED(DstMiscData%d99Var)) THEN + ALLOCATE(DstMiscData%d99Var(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%d99Var.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%d99Var = SrcMiscData%d99Var +ENDIF +IF (ALLOCATED(SrcMiscData%dStarVar)) THEN + i1_l = LBOUND(SrcMiscData%dStarVar,1) + i1_u = UBOUND(SrcMiscData%dStarVar,1) + IF (.NOT. ALLOCATED(DstMiscData%dStarVar)) THEN + ALLOCATE(DstMiscData%dStarVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%dStarVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%dStarVar = SrcMiscData%dStarVar +ENDIF +IF (ALLOCATED(SrcMiscData%EdgeVelVar)) THEN + i1_l = LBOUND(SrcMiscData%EdgeVelVar,1) + i1_u = UBOUND(SrcMiscData%EdgeVelVar,1) + IF (.NOT. ALLOCATED(DstMiscData%EdgeVelVar)) THEN + ALLOCATE(DstMiscData%EdgeVelVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%EdgeVelVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%EdgeVelVar = SrcMiscData%EdgeVelVar +ENDIF + DstMiscData%speccou = SrcMiscData%speccou + DstMiscData%filesopen = SrcMiscData%filesopen + END SUBROUTINE AA_CopyMisc + + SUBROUTINE AA_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(AA_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF +IF (ALLOCATED(MiscData%ChordAngleTE)) THEN + DEALLOCATE(MiscData%ChordAngleTE) +ENDIF +IF (ALLOCATED(MiscData%SpanAngleTE)) THEN + DEALLOCATE(MiscData%SpanAngleTE) +ENDIF +IF (ALLOCATED(MiscData%ChordAngleLE)) THEN + DEALLOCATE(MiscData%ChordAngleLE) +ENDIF +IF (ALLOCATED(MiscData%SpanAngleLE)) THEN + DEALLOCATE(MiscData%SpanAngleLE) +ENDIF +IF (ALLOCATED(MiscData%rTEtoObserve)) THEN + DEALLOCATE(MiscData%rTEtoObserve) +ENDIF +IF (ALLOCATED(MiscData%rLEtoObserve)) THEN + DEALLOCATE(MiscData%rLEtoObserve) +ENDIF +IF (ALLOCATED(MiscData%LE_Location)) THEN + DEALLOCATE(MiscData%LE_Location) +ENDIF +IF (ALLOCATED(MiscData%SPLLBL)) THEN + DEALLOCATE(MiscData%SPLLBL) +ENDIF +IF (ALLOCATED(MiscData%SPLP)) THEN + DEALLOCATE(MiscData%SPLP) +ENDIF +IF (ALLOCATED(MiscData%SPLS)) THEN + DEALLOCATE(MiscData%SPLS) +ENDIF +IF (ALLOCATED(MiscData%SPLALPH)) THEN + DEALLOCATE(MiscData%SPLALPH) +ENDIF +IF (ALLOCATED(MiscData%SPLTBL)) THEN + DEALLOCATE(MiscData%SPLTBL) +ENDIF +IF (ALLOCATED(MiscData%SPLTIP)) THEN + DEALLOCATE(MiscData%SPLTIP) +ENDIF +IF (ALLOCATED(MiscData%SPLTI)) THEN + DEALLOCATE(MiscData%SPLTI) +ENDIF +IF (ALLOCATED(MiscData%SPLTIGui)) THEN + DEALLOCATE(MiscData%SPLTIGui) +ENDIF +IF (ALLOCATED(MiscData%SPLBLUNT)) THEN + DEALLOCATE(MiscData%SPLBLUNT) +ENDIF +IF (ALLOCATED(MiscData%CfVar)) THEN + DEALLOCATE(MiscData%CfVar) +ENDIF +IF (ALLOCATED(MiscData%d99Var)) THEN + DEALLOCATE(MiscData%d99Var) +ENDIF +IF (ALLOCATED(MiscData%dStarVar)) THEN + DEALLOCATE(MiscData%dStarVar) +ENDIF +IF (ALLOCATED(MiscData%EdgeVelVar)) THEN + DEALLOCATE(MiscData%EdgeVelVar) +ENDIF + END SUBROUTINE AA_DestroyMisc + + SUBROUTINE AA_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(AA_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 = 'AA_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 ! AllOuts allocated yes/no + IF ( ALLOCATED(InData%AllOuts) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AllOuts upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + END IF + Int_BufSz = Int_BufSz + 1 ! ChordAngleTE allocated yes/no + IF ( ALLOCATED(InData%ChordAngleTE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! ChordAngleTE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ChordAngleTE) ! ChordAngleTE + END IF + Int_BufSz = Int_BufSz + 1 ! SpanAngleTE allocated yes/no + IF ( ALLOCATED(InData%SpanAngleTE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SpanAngleTE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SpanAngleTE) ! SpanAngleTE + END IF + Int_BufSz = Int_BufSz + 1 ! ChordAngleLE allocated yes/no + IF ( ALLOCATED(InData%ChordAngleLE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! ChordAngleLE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ChordAngleLE) ! ChordAngleLE + END IF + Int_BufSz = Int_BufSz + 1 ! SpanAngleLE allocated yes/no + IF ( ALLOCATED(InData%SpanAngleLE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SpanAngleLE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SpanAngleLE) ! SpanAngleLE + END IF + Int_BufSz = Int_BufSz + 1 ! rTEtoObserve allocated yes/no + IF ( ALLOCATED(InData%rTEtoObserve) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rTEtoObserve upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rTEtoObserve) ! rTEtoObserve + END IF + Int_BufSz = Int_BufSz + 1 ! rLEtoObserve allocated yes/no + IF ( ALLOCATED(InData%rLEtoObserve) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rLEtoObserve upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rLEtoObserve) ! rLEtoObserve + END IF + Int_BufSz = Int_BufSz + 1 ! LE_Location allocated yes/no + IF ( ALLOCATED(InData%LE_Location) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! LE_Location upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LE_Location) ! LE_Location + END IF + Re_BufSz = Re_BufSz + 1 ! RotSpeedAoA + Int_BufSz = Int_BufSz + 1 ! SPLLBL allocated yes/no + IF ( ALLOCATED(InData%SPLLBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLLBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLLBL) ! SPLLBL + END IF + Int_BufSz = Int_BufSz + 1 ! SPLP allocated yes/no + IF ( ALLOCATED(InData%SPLP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLP) ! SPLP + END IF + Int_BufSz = Int_BufSz + 1 ! SPLS allocated yes/no + IF ( ALLOCATED(InData%SPLS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLS) ! SPLS + END IF + Int_BufSz = Int_BufSz + 1 ! SPLALPH allocated yes/no + IF ( ALLOCATED(InData%SPLALPH) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLALPH upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLALPH) ! SPLALPH + END IF + Int_BufSz = Int_BufSz + 1 ! SPLTBL allocated yes/no + IF ( ALLOCATED(InData%SPLTBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLTBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLTBL) ! SPLTBL + END IF + Int_BufSz = Int_BufSz + 1 ! SPLTIP allocated yes/no + IF ( ALLOCATED(InData%SPLTIP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLTIP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLTIP) ! SPLTIP + END IF + Int_BufSz = Int_BufSz + 1 ! SPLTI allocated yes/no + IF ( ALLOCATED(InData%SPLTI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLTI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLTI) ! SPLTI + END IF + Int_BufSz = Int_BufSz + 1 ! SPLTIGui allocated yes/no + IF ( ALLOCATED(InData%SPLTIGui) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLTIGui upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLTIGui) ! SPLTIGui + END IF + Int_BufSz = Int_BufSz + 1 ! SPLBLUNT allocated yes/no + IF ( ALLOCATED(InData%SPLBLUNT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SPLBLUNT upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SPLBLUNT) ! SPLBLUNT + END IF + Int_BufSz = Int_BufSz + 1 ! CfVar allocated yes/no + IF ( ALLOCATED(InData%CfVar) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CfVar upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CfVar) ! CfVar + END IF + Int_BufSz = Int_BufSz + 1 ! d99Var allocated yes/no + IF ( ALLOCATED(InData%d99Var) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! d99Var upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%d99Var) ! d99Var + END IF + Int_BufSz = Int_BufSz + 1 ! dStarVar allocated yes/no + IF ( ALLOCATED(InData%dStarVar) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dStarVar upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dStarVar) ! dStarVar + END IF + Int_BufSz = Int_BufSz + 1 ! EdgeVelVar allocated yes/no + IF ( ALLOCATED(InData%EdgeVelVar) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EdgeVelVar upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgeVelVar) ! EdgeVelVar + END IF + Int_BufSz = Int_BufSz + 1 ! speccou + Int_BufSz = Int_BufSz + 1 ! filesopen + 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%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ChordAngleTE) ) 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%ChordAngleTE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleTE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ChordAngleTE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleTE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ChordAngleTE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleTE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%ChordAngleTE,3), UBOUND(InData%ChordAngleTE,3) + DO i2 = LBOUND(InData%ChordAngleTE,2), UBOUND(InData%ChordAngleTE,2) + DO i1 = LBOUND(InData%ChordAngleTE,1), UBOUND(InData%ChordAngleTE,1) + ReKiBuf(Re_Xferred) = InData%ChordAngleTE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SpanAngleTE) ) 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%SpanAngleTE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleTE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SpanAngleTE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleTE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SpanAngleTE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleTE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SpanAngleTE,3), UBOUND(InData%SpanAngleTE,3) + DO i2 = LBOUND(InData%SpanAngleTE,2), UBOUND(InData%SpanAngleTE,2) + DO i1 = LBOUND(InData%SpanAngleTE,1), UBOUND(InData%SpanAngleTE,1) + ReKiBuf(Re_Xferred) = InData%SpanAngleTE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ChordAngleLE) ) 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%ChordAngleLE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleLE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ChordAngleLE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleLE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ChordAngleLE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChordAngleLE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%ChordAngleLE,3), UBOUND(InData%ChordAngleLE,3) + DO i2 = LBOUND(InData%ChordAngleLE,2), UBOUND(InData%ChordAngleLE,2) + DO i1 = LBOUND(InData%ChordAngleLE,1), UBOUND(InData%ChordAngleLE,1) + ReKiBuf(Re_Xferred) = InData%ChordAngleLE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SpanAngleLE) ) 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%SpanAngleLE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleLE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SpanAngleLE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleLE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SpanAngleLE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SpanAngleLE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SpanAngleLE,3), UBOUND(InData%SpanAngleLE,3) + DO i2 = LBOUND(InData%SpanAngleLE,2), UBOUND(InData%SpanAngleLE,2) + DO i1 = LBOUND(InData%SpanAngleLE,1), UBOUND(InData%SpanAngleLE,1) + ReKiBuf(Re_Xferred) = InData%SpanAngleLE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rTEtoObserve) ) 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%rTEtoObserve,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rTEtoObserve,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rTEtoObserve,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rTEtoObserve,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rTEtoObserve,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rTEtoObserve,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rTEtoObserve,3), UBOUND(InData%rTEtoObserve,3) + DO i2 = LBOUND(InData%rTEtoObserve,2), UBOUND(InData%rTEtoObserve,2) + DO i1 = LBOUND(InData%rTEtoObserve,1), UBOUND(InData%rTEtoObserve,1) + ReKiBuf(Re_Xferred) = InData%rTEtoObserve(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rLEtoObserve) ) 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%rLEtoObserve,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLEtoObserve,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLEtoObserve,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLEtoObserve,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLEtoObserve,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLEtoObserve,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rLEtoObserve,3), UBOUND(InData%rLEtoObserve,3) + DO i2 = LBOUND(InData%rLEtoObserve,2), UBOUND(InData%rLEtoObserve,2) + DO i1 = LBOUND(InData%rLEtoObserve,1), UBOUND(InData%rLEtoObserve,1) + ReKiBuf(Re_Xferred) = InData%rLEtoObserve(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LE_Location) ) 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%LE_Location,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE_Location,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LE_Location,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE_Location,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LE_Location,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE_Location,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%LE_Location,3), UBOUND(InData%LE_Location,3) + DO i2 = LBOUND(InData%LE_Location,2), UBOUND(InData%LE_Location,2) + DO i1 = LBOUND(InData%LE_Location,1), UBOUND(InData%LE_Location,1) + ReKiBuf(Re_Xferred) = InData%LE_Location(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%RotSpeedAoA + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SPLLBL) ) 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%SPLLBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLLBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLLBL,1), UBOUND(InData%SPLLBL,1) + ReKiBuf(Re_Xferred) = InData%SPLLBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLP) ) 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%SPLP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLP,1), UBOUND(InData%SPLP,1) + ReKiBuf(Re_Xferred) = InData%SPLP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLS) ) 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%SPLS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLS,1), UBOUND(InData%SPLS,1) + ReKiBuf(Re_Xferred) = InData%SPLS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLALPH) ) 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%SPLALPH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLALPH,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLALPH,1), UBOUND(InData%SPLALPH,1) + ReKiBuf(Re_Xferred) = InData%SPLALPH(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLTBL) ) 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%SPLTBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLTBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLTBL,1), UBOUND(InData%SPLTBL,1) + ReKiBuf(Re_Xferred) = InData%SPLTBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLTIP) ) 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%SPLTIP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLTIP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLTIP,1), UBOUND(InData%SPLTIP,1) + ReKiBuf(Re_Xferred) = InData%SPLTIP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLTI) ) 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%SPLTI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLTI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLTI,1), UBOUND(InData%SPLTI,1) + ReKiBuf(Re_Xferred) = InData%SPLTI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLTIGui) ) 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%SPLTIGui,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLTIGui,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLTIGui,1), UBOUND(InData%SPLTIGui,1) + ReKiBuf(Re_Xferred) = InData%SPLTIGui(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SPLBLUNT) ) 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%SPLBLUNT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SPLBLUNT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SPLBLUNT,1), UBOUND(InData%SPLBLUNT,1) + ReKiBuf(Re_Xferred) = InData%SPLBLUNT(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CfVar) ) 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%CfVar,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfVar,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CfVar,1), UBOUND(InData%CfVar,1) + ReKiBuf(Re_Xferred) = InData%CfVar(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%d99Var) ) 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%d99Var,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99Var,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%d99Var,1), UBOUND(InData%d99Var,1) + ReKiBuf(Re_Xferred) = InData%d99Var(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dStarVar) ) 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%dStarVar,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarVar,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dStarVar,1), UBOUND(InData%dStarVar,1) + ReKiBuf(Re_Xferred) = InData%dStarVar(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgeVelVar) ) 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%EdgeVelVar,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelVar,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EdgeVelVar,1), UBOUND(InData%EdgeVelVar,1) + ReKiBuf(Re_Xferred) = InData%EdgeVelVar(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%speccou + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%filesopen + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AA_PackMisc + + SUBROUTINE AA_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(AA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_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 ! AllOuts 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%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChordAngleTE 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%ChordAngleTE)) DEALLOCATE(OutData%ChordAngleTE) + ALLOCATE(OutData%ChordAngleTE(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%ChordAngleTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%ChordAngleTE,3), UBOUND(OutData%ChordAngleTE,3) + DO i2 = LBOUND(OutData%ChordAngleTE,2), UBOUND(OutData%ChordAngleTE,2) + DO i1 = LBOUND(OutData%ChordAngleTE,1), UBOUND(OutData%ChordAngleTE,1) + OutData%ChordAngleTE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SpanAngleTE 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%SpanAngleTE)) DEALLOCATE(OutData%SpanAngleTE) + ALLOCATE(OutData%SpanAngleTE(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%SpanAngleTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SpanAngleTE,3), UBOUND(OutData%SpanAngleTE,3) + DO i2 = LBOUND(OutData%SpanAngleTE,2), UBOUND(OutData%SpanAngleTE,2) + DO i1 = LBOUND(OutData%SpanAngleTE,1), UBOUND(OutData%SpanAngleTE,1) + OutData%SpanAngleTE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChordAngleLE 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%ChordAngleLE)) DEALLOCATE(OutData%ChordAngleLE) + ALLOCATE(OutData%ChordAngleLE(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%ChordAngleLE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%ChordAngleLE,3), UBOUND(OutData%ChordAngleLE,3) + DO i2 = LBOUND(OutData%ChordAngleLE,2), UBOUND(OutData%ChordAngleLE,2) + DO i1 = LBOUND(OutData%ChordAngleLE,1), UBOUND(OutData%ChordAngleLE,1) + OutData%ChordAngleLE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SpanAngleLE 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%SpanAngleLE)) DEALLOCATE(OutData%SpanAngleLE) + ALLOCATE(OutData%SpanAngleLE(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%SpanAngleLE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SpanAngleLE,3), UBOUND(OutData%SpanAngleLE,3) + DO i2 = LBOUND(OutData%SpanAngleLE,2), UBOUND(OutData%SpanAngleLE,2) + DO i1 = LBOUND(OutData%SpanAngleLE,1), UBOUND(OutData%SpanAngleLE,1) + OutData%SpanAngleLE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rTEtoObserve 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%rTEtoObserve)) DEALLOCATE(OutData%rTEtoObserve) + ALLOCATE(OutData%rTEtoObserve(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%rTEtoObserve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rTEtoObserve,3), UBOUND(OutData%rTEtoObserve,3) + DO i2 = LBOUND(OutData%rTEtoObserve,2), UBOUND(OutData%rTEtoObserve,2) + DO i1 = LBOUND(OutData%rTEtoObserve,1), UBOUND(OutData%rTEtoObserve,1) + OutData%rTEtoObserve(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rLEtoObserve 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%rLEtoObserve)) DEALLOCATE(OutData%rLEtoObserve) + ALLOCATE(OutData%rLEtoObserve(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%rLEtoObserve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rLEtoObserve,3), UBOUND(OutData%rLEtoObserve,3) + DO i2 = LBOUND(OutData%rLEtoObserve,2), UBOUND(OutData%rLEtoObserve,2) + DO i1 = LBOUND(OutData%rLEtoObserve,1), UBOUND(OutData%rLEtoObserve,1) + OutData%rLEtoObserve(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LE_Location 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%LE_Location)) DEALLOCATE(OutData%LE_Location) + ALLOCATE(OutData%LE_Location(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%LE_Location.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%LE_Location,3), UBOUND(OutData%LE_Location,3) + DO i2 = LBOUND(OutData%LE_Location,2), UBOUND(OutData%LE_Location,2) + DO i1 = LBOUND(OutData%LE_Location,1), UBOUND(OutData%LE_Location,1) + OutData%LE_Location(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%RotSpeedAoA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLLBL 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%SPLLBL)) DEALLOCATE(OutData%SPLLBL) + ALLOCATE(OutData%SPLLBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLLBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLLBL,1), UBOUND(OutData%SPLLBL,1) + OutData%SPLLBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLP 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%SPLP)) DEALLOCATE(OutData%SPLP) + ALLOCATE(OutData%SPLP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLP,1), UBOUND(OutData%SPLP,1) + OutData%SPLP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLS 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%SPLS)) DEALLOCATE(OutData%SPLS) + ALLOCATE(OutData%SPLS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLS,1), UBOUND(OutData%SPLS,1) + OutData%SPLS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLALPH 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%SPLALPH)) DEALLOCATE(OutData%SPLALPH) + ALLOCATE(OutData%SPLALPH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLALPH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLALPH,1), UBOUND(OutData%SPLALPH,1) + OutData%SPLALPH(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLTBL 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%SPLTBL)) DEALLOCATE(OutData%SPLTBL) + ALLOCATE(OutData%SPLTBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLTBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLTBL,1), UBOUND(OutData%SPLTBL,1) + OutData%SPLTBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLTIP 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%SPLTIP)) DEALLOCATE(OutData%SPLTIP) + ALLOCATE(OutData%SPLTIP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLTIP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLTIP,1), UBOUND(OutData%SPLTIP,1) + OutData%SPLTIP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLTI 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%SPLTI)) DEALLOCATE(OutData%SPLTI) + ALLOCATE(OutData%SPLTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLTI,1), UBOUND(OutData%SPLTI,1) + OutData%SPLTI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLTIGui 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%SPLTIGui)) DEALLOCATE(OutData%SPLTIGui) + ALLOCATE(OutData%SPLTIGui(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLTIGui.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLTIGui,1), UBOUND(OutData%SPLTIGui,1) + OutData%SPLTIGui(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SPLBLUNT 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%SPLBLUNT)) DEALLOCATE(OutData%SPLBLUNT) + ALLOCATE(OutData%SPLBLUNT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SPLBLUNT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SPLBLUNT,1), UBOUND(OutData%SPLBLUNT,1) + OutData%SPLBLUNT(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CfVar 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%CfVar)) DEALLOCATE(OutData%CfVar) + ALLOCATE(OutData%CfVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CfVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CfVar,1), UBOUND(OutData%CfVar,1) + OutData%CfVar(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! d99Var 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%d99Var)) DEALLOCATE(OutData%d99Var) + ALLOCATE(OutData%d99Var(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%d99Var.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%d99Var,1), UBOUND(OutData%d99Var,1) + OutData%d99Var(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dStarVar 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%dStarVar)) DEALLOCATE(OutData%dStarVar) + ALLOCATE(OutData%dStarVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dStarVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dStarVar,1), UBOUND(OutData%dStarVar,1) + OutData%dStarVar(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgeVelVar 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%EdgeVelVar)) DEALLOCATE(OutData%EdgeVelVar) + ALLOCATE(OutData%EdgeVelVar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EdgeVelVar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EdgeVelVar,1), UBOUND(OutData%EdgeVelVar,1) + OutData%EdgeVelVar(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%speccou = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%filesopen = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AA_UnPackMisc + + SUBROUTINE AA_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_ParameterType), INTENT(IN) :: SrcParamData + TYPE(AA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%IBLUNT = SrcParamData%IBLUNT + DstParamData%ILAM = SrcParamData%ILAM + DstParamData%ITIP = SrcParamData%ITIP + DstParamData%ITRIP = SrcParamData%ITRIP + DstParamData%ITURB = SrcParamData%ITURB + DstParamData%IInflow = SrcParamData%IInflow + DstParamData%X_BLMethod = SrcParamData%X_BLMethod + DstParamData%TICalcMeth = SrcParamData%TICalcMeth + DstParamData%ROUND = SrcParamData%ROUND + DstParamData%ALPRAT = SrcParamData%ALPRAT + DstParamData%NumBlades = SrcParamData%NumBlades + DstParamData%NumBlNds = SrcParamData%NumBlNds + DstParamData%AirDens = SrcParamData%AirDens + DstParamData%KinVisc = SrcParamData%KinVisc + DstParamData%SpdSound = SrcParamData%SpdSound + DstParamData%HubHeight = SrcParamData%HubHeight + DstParamData%toptip = SrcParamData%toptip + DstParamData%bottip = SrcParamData%bottip +IF (ALLOCATED(SrcParamData%rotorregionlimitsVert)) THEN + i1_l = LBOUND(SrcParamData%rotorregionlimitsVert,1) + i1_u = UBOUND(SrcParamData%rotorregionlimitsVert,1) + IF (.NOT. ALLOCATED(DstParamData%rotorregionlimitsVert)) THEN + ALLOCATE(DstParamData%rotorregionlimitsVert(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rotorregionlimitsVert.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rotorregionlimitsVert = SrcParamData%rotorregionlimitsVert +ENDIF +IF (ALLOCATED(SrcParamData%rotorregionlimitsHorz)) THEN + i1_l = LBOUND(SrcParamData%rotorregionlimitsHorz,1) + i1_u = UBOUND(SrcParamData%rotorregionlimitsHorz,1) + IF (.NOT. ALLOCATED(DstParamData%rotorregionlimitsHorz)) THEN + ALLOCATE(DstParamData%rotorregionlimitsHorz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rotorregionlimitsHorz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rotorregionlimitsHorz = SrcParamData%rotorregionlimitsHorz +ENDIF +IF (ALLOCATED(SrcParamData%rotorregionlimitsalph)) THEN + i1_l = LBOUND(SrcParamData%rotorregionlimitsalph,1) + i1_u = UBOUND(SrcParamData%rotorregionlimitsalph,1) + IF (.NOT. ALLOCATED(DstParamData%rotorregionlimitsalph)) THEN + ALLOCATE(DstParamData%rotorregionlimitsalph(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rotorregionlimitsalph.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rotorregionlimitsalph = SrcParamData%rotorregionlimitsalph +ENDIF +IF (ALLOCATED(SrcParamData%rotorregionlimitsrad)) THEN + i1_l = LBOUND(SrcParamData%rotorregionlimitsrad,1) + i1_u = UBOUND(SrcParamData%rotorregionlimitsrad,1) + IF (.NOT. ALLOCATED(DstParamData%rotorregionlimitsrad)) THEN + ALLOCATE(DstParamData%rotorregionlimitsrad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rotorregionlimitsrad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rotorregionlimitsrad = SrcParamData%rotorregionlimitsrad +ENDIF + DstParamData%NrObsLoc = SrcParamData%NrObsLoc + DstParamData%aweightflag = SrcParamData%aweightflag + DstParamData%TxtFileOutput = SrcParamData%TxtFileOutput + DstParamData%AAStart = SrcParamData%AAStart +IF (ALLOCATED(SrcParamData%ObsX)) THEN + i1_l = LBOUND(SrcParamData%ObsX,1) + i1_u = UBOUND(SrcParamData%ObsX,1) + IF (.NOT. ALLOCATED(DstParamData%ObsX)) THEN + ALLOCATE(DstParamData%ObsX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ObsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ObsX = SrcParamData%ObsX +ENDIF +IF (ALLOCATED(SrcParamData%ObsY)) THEN + i1_l = LBOUND(SrcParamData%ObsY,1) + i1_u = UBOUND(SrcParamData%ObsY,1) + IF (.NOT. ALLOCATED(DstParamData%ObsY)) THEN + ALLOCATE(DstParamData%ObsY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ObsY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ObsY = SrcParamData%ObsY +ENDIF +IF (ALLOCATED(SrcParamData%ObsZ)) THEN + i1_l = LBOUND(SrcParamData%ObsZ,1) + i1_u = UBOUND(SrcParamData%ObsZ,1) + IF (.NOT. ALLOCATED(DstParamData%ObsZ)) THEN + ALLOCATE(DstParamData%ObsZ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ObsZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ObsZ = SrcParamData%ObsZ +ENDIF +IF (ALLOCATED(SrcParamData%FreqList)) THEN + i1_l = LBOUND(SrcParamData%FreqList,1) + i1_u = UBOUND(SrcParamData%FreqList,1) + IF (.NOT. ALLOCATED(DstParamData%FreqList)) THEN + ALLOCATE(DstParamData%FreqList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FreqList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FreqList = SrcParamData%FreqList +ENDIF +IF (ALLOCATED(SrcParamData%Aweight)) THEN + i1_l = LBOUND(SrcParamData%Aweight,1) + i1_u = UBOUND(SrcParamData%Aweight,1) + IF (.NOT. ALLOCATED(DstParamData%Aweight)) THEN + ALLOCATE(DstParamData%Aweight(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Aweight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Aweight = SrcParamData%Aweight +ENDIF + DstParamData%Fsample = SrcParamData%Fsample + DstParamData%total_sample = SrcParamData%total_sample + DstParamData%total_sampleTI = SrcParamData%total_sampleTI + DstParamData%AA_Bl_Prcntge = SrcParamData%AA_Bl_Prcntge + DstParamData%startnode = SrcParamData%startnode + DstParamData%z0_aa = SrcParamData%z0_aa + DstParamData%dz_turb_in = SrcParamData%dz_turb_in + DstParamData%dy_turb_in = SrcParamData%dy_turb_in +IF (ALLOCATED(SrcParamData%TI_Grid_In)) THEN + i1_l = LBOUND(SrcParamData%TI_Grid_In,1) + i1_u = UBOUND(SrcParamData%TI_Grid_In,1) + i2_l = LBOUND(SrcParamData%TI_Grid_In,2) + i2_u = UBOUND(SrcParamData%TI_Grid_In,2) + IF (.NOT. ALLOCATED(DstParamData%TI_Grid_In)) THEN + ALLOCATE(DstParamData%TI_Grid_In(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TI_Grid_In.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TI_Grid_In = SrcParamData%TI_Grid_In +ENDIF + DstParamData%FTitle = SrcParamData%FTitle + DstParamData%outFmt = SrcParamData%outFmt + DstParamData%NrOutFile = SrcParamData%NrOutFile + DstParamData%delim = SrcParamData%delim + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOutsForPE = SrcParamData%NumOutsForPE + DstParamData%NumOutsForSep = SrcParamData%NumOutsForSep + DstParamData%NumOutsForNodes = SrcParamData%NumOutsForNodes + DstParamData%unOutFile = SrcParamData%unOutFile + DstParamData%unOutFile2 = SrcParamData%unOutFile2 + DstParamData%unOutFile3 = SrcParamData%unOutFile3 + DstParamData%unOutFile4 = SrcParamData%unOutFile4 + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%StallStart)) THEN + i1_l = LBOUND(SrcParamData%StallStart,1) + i1_u = UBOUND(SrcParamData%StallStart,1) + i2_l = LBOUND(SrcParamData%StallStart,2) + i2_u = UBOUND(SrcParamData%StallStart,2) + IF (.NOT. ALLOCATED(DstParamData%StallStart)) THEN + ALLOCATE(DstParamData%StallStart(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StallStart.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StallStart = SrcParamData%StallStart +ENDIF +IF (ALLOCATED(SrcParamData%TEThick)) THEN + i1_l = LBOUND(SrcParamData%TEThick,1) + i1_u = UBOUND(SrcParamData%TEThick,1) + i2_l = LBOUND(SrcParamData%TEThick,2) + i2_u = UBOUND(SrcParamData%TEThick,2) + IF (.NOT. ALLOCATED(DstParamData%TEThick)) THEN + ALLOCATE(DstParamData%TEThick(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TEThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TEThick = SrcParamData%TEThick +ENDIF +IF (ALLOCATED(SrcParamData%TEAngle)) THEN + i1_l = LBOUND(SrcParamData%TEAngle,1) + i1_u = UBOUND(SrcParamData%TEAngle,1) + i2_l = LBOUND(SrcParamData%TEAngle,2) + i2_u = UBOUND(SrcParamData%TEAngle,2) + IF (.NOT. ALLOCATED(DstParamData%TEAngle)) THEN + ALLOCATE(DstParamData%TEAngle(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TEAngle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TEAngle = SrcParamData%TEAngle +ENDIF +IF (ALLOCATED(SrcParamData%AerCent)) THEN + i1_l = LBOUND(SrcParamData%AerCent,1) + i1_u = UBOUND(SrcParamData%AerCent,1) + i2_l = LBOUND(SrcParamData%AerCent,2) + i2_u = UBOUND(SrcParamData%AerCent,2) + i3_l = LBOUND(SrcParamData%AerCent,3) + i3_u = UBOUND(SrcParamData%AerCent,3) + IF (.NOT. ALLOCATED(DstParamData%AerCent)) THEN + ALLOCATE(DstParamData%AerCent(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%AerCent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AerCent = SrcParamData%AerCent +ENDIF +IF (ALLOCATED(SrcParamData%BlAFID)) THEN + i1_l = LBOUND(SrcParamData%BlAFID,1) + i1_u = UBOUND(SrcParamData%BlAFID,1) + i2_l = LBOUND(SrcParamData%BlAFID,2) + i2_u = UBOUND(SrcParamData%BlAFID,2) + IF (.NOT. ALLOCATED(DstParamData%BlAFID)) THEN + ALLOCATE(DstParamData%BlAFID(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BlAFID = SrcParamData%BlAFID +ENDIF +IF (ALLOCATED(SrcParamData%AFInfo)) THEN + i1_l = LBOUND(SrcParamData%AFInfo,1) + i1_u = UBOUND(SrcParamData%AFInfo,1) + IF (.NOT. ALLOCATED(DstParamData%AFInfo)) THEN + ALLOCATE(DstParamData%AFInfo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AFInfo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%AFInfo,1), UBOUND(SrcParamData%AFInfo,1) + CALL AFI_CopyParam( SrcParamData%AFInfo(i1), DstParamData%AFInfo(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%AFLECo)) THEN + i1_l = LBOUND(SrcParamData%AFLECo,1) + i1_u = UBOUND(SrcParamData%AFLECo,1) + i2_l = LBOUND(SrcParamData%AFLECo,2) + i2_u = UBOUND(SrcParamData%AFLECo,2) + i3_l = LBOUND(SrcParamData%AFLECo,3) + i3_u = UBOUND(SrcParamData%AFLECo,3) + IF (.NOT. ALLOCATED(DstParamData%AFLECo)) THEN + ALLOCATE(DstParamData%AFLECo(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%AFLECo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AFLECo = SrcParamData%AFLECo +ENDIF +IF (ALLOCATED(SrcParamData%AFTECo)) THEN + i1_l = LBOUND(SrcParamData%AFTECo,1) + i1_u = UBOUND(SrcParamData%AFTECo,1) + i2_l = LBOUND(SrcParamData%AFTECo,2) + i2_u = UBOUND(SrcParamData%AFTECo,2) + i3_l = LBOUND(SrcParamData%AFTECo,3) + i3_u = UBOUND(SrcParamData%AFTECo,3) + IF (.NOT. ALLOCATED(DstParamData%AFTECo)) THEN + ALLOCATE(DstParamData%AFTECo(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%AFTECo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AFTECo = SrcParamData%AFTECo +ENDIF +IF (ALLOCATED(SrcParamData%BlSpn)) THEN + i1_l = LBOUND(SrcParamData%BlSpn,1) + i1_u = UBOUND(SrcParamData%BlSpn,1) + i2_l = LBOUND(SrcParamData%BlSpn,2) + i2_u = UBOUND(SrcParamData%BlSpn,2) + IF (.NOT. ALLOCATED(DstParamData%BlSpn)) THEN + ALLOCATE(DstParamData%BlSpn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BlSpn = SrcParamData%BlSpn +ENDIF +IF (ALLOCATED(SrcParamData%BlChord)) THEN + i1_l = LBOUND(SrcParamData%BlChord,1) + i1_u = UBOUND(SrcParamData%BlChord,1) + i2_l = LBOUND(SrcParamData%BlChord,2) + i2_u = UBOUND(SrcParamData%BlChord,2) + IF (.NOT. ALLOCATED(DstParamData%BlChord)) THEN + ALLOCATE(DstParamData%BlChord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BlChord = SrcParamData%BlChord +ENDIF +IF (ALLOCATED(SrcParamData%ReListBL)) THEN + i1_l = LBOUND(SrcParamData%ReListBL,1) + i1_u = UBOUND(SrcParamData%ReListBL,1) + IF (.NOT. ALLOCATED(DstParamData%ReListBL)) THEN + ALLOCATE(DstParamData%ReListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ReListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ReListBL = SrcParamData%ReListBL +ENDIF +IF (ALLOCATED(SrcParamData%AOAListBL)) THEN + i1_l = LBOUND(SrcParamData%AOAListBL,1) + i1_u = UBOUND(SrcParamData%AOAListBL,1) + IF (.NOT. ALLOCATED(DstParamData%AOAListBL)) THEN + ALLOCATE(DstParamData%AOAListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AOAListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AOAListBL = SrcParamData%AOAListBL +ENDIF +IF (ALLOCATED(SrcParamData%dStarAll1)) THEN + i1_l = LBOUND(SrcParamData%dStarAll1,1) + i1_u = UBOUND(SrcParamData%dStarAll1,1) + i2_l = LBOUND(SrcParamData%dStarAll1,2) + i2_u = UBOUND(SrcParamData%dStarAll1,2) + i3_l = LBOUND(SrcParamData%dStarAll1,3) + i3_u = UBOUND(SrcParamData%dStarAll1,3) + IF (.NOT. ALLOCATED(DstParamData%dStarAll1)) THEN + ALLOCATE(DstParamData%dStarAll1(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%dStarAll1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%dStarAll1 = SrcParamData%dStarAll1 +ENDIF +IF (ALLOCATED(SrcParamData%dStarAll2)) THEN + i1_l = LBOUND(SrcParamData%dStarAll2,1) + i1_u = UBOUND(SrcParamData%dStarAll2,1) + i2_l = LBOUND(SrcParamData%dStarAll2,2) + i2_u = UBOUND(SrcParamData%dStarAll2,2) + i3_l = LBOUND(SrcParamData%dStarAll2,3) + i3_u = UBOUND(SrcParamData%dStarAll2,3) + IF (.NOT. ALLOCATED(DstParamData%dStarAll2)) THEN + ALLOCATE(DstParamData%dStarAll2(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%dStarAll2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%dStarAll2 = SrcParamData%dStarAll2 +ENDIF +IF (ALLOCATED(SrcParamData%d99All1)) THEN + i1_l = LBOUND(SrcParamData%d99All1,1) + i1_u = UBOUND(SrcParamData%d99All1,1) + i2_l = LBOUND(SrcParamData%d99All1,2) + i2_u = UBOUND(SrcParamData%d99All1,2) + i3_l = LBOUND(SrcParamData%d99All1,3) + i3_u = UBOUND(SrcParamData%d99All1,3) + IF (.NOT. ALLOCATED(DstParamData%d99All1)) THEN + ALLOCATE(DstParamData%d99All1(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%d99All1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%d99All1 = SrcParamData%d99All1 +ENDIF +IF (ALLOCATED(SrcParamData%d99All2)) THEN + i1_l = LBOUND(SrcParamData%d99All2,1) + i1_u = UBOUND(SrcParamData%d99All2,1) + i2_l = LBOUND(SrcParamData%d99All2,2) + i2_u = UBOUND(SrcParamData%d99All2,2) + i3_l = LBOUND(SrcParamData%d99All2,3) + i3_u = UBOUND(SrcParamData%d99All2,3) + IF (.NOT. ALLOCATED(DstParamData%d99All2)) THEN + ALLOCATE(DstParamData%d99All2(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%d99All2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%d99All2 = SrcParamData%d99All2 +ENDIF +IF (ALLOCATED(SrcParamData%CfAll1)) THEN + i1_l = LBOUND(SrcParamData%CfAll1,1) + i1_u = UBOUND(SrcParamData%CfAll1,1) + i2_l = LBOUND(SrcParamData%CfAll1,2) + i2_u = UBOUND(SrcParamData%CfAll1,2) + i3_l = LBOUND(SrcParamData%CfAll1,3) + i3_u = UBOUND(SrcParamData%CfAll1,3) + IF (.NOT. ALLOCATED(DstParamData%CfAll1)) THEN + ALLOCATE(DstParamData%CfAll1(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%CfAll1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CfAll1 = SrcParamData%CfAll1 +ENDIF +IF (ALLOCATED(SrcParamData%CfAll2)) THEN + i1_l = LBOUND(SrcParamData%CfAll2,1) + i1_u = UBOUND(SrcParamData%CfAll2,1) + i2_l = LBOUND(SrcParamData%CfAll2,2) + i2_u = UBOUND(SrcParamData%CfAll2,2) + i3_l = LBOUND(SrcParamData%CfAll2,3) + i3_u = UBOUND(SrcParamData%CfAll2,3) + IF (.NOT. ALLOCATED(DstParamData%CfAll2)) THEN + ALLOCATE(DstParamData%CfAll2(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%CfAll2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CfAll2 = SrcParamData%CfAll2 +ENDIF +IF (ALLOCATED(SrcParamData%EdgeVelRat1)) THEN + i1_l = LBOUND(SrcParamData%EdgeVelRat1,1) + i1_u = UBOUND(SrcParamData%EdgeVelRat1,1) + i2_l = LBOUND(SrcParamData%EdgeVelRat1,2) + i2_u = UBOUND(SrcParamData%EdgeVelRat1,2) + i3_l = LBOUND(SrcParamData%EdgeVelRat1,3) + i3_u = UBOUND(SrcParamData%EdgeVelRat1,3) + IF (.NOT. ALLOCATED(DstParamData%EdgeVelRat1)) THEN + ALLOCATE(DstParamData%EdgeVelRat1(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%EdgeVelRat1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%EdgeVelRat1 = SrcParamData%EdgeVelRat1 +ENDIF +IF (ALLOCATED(SrcParamData%EdgeVelRat2)) THEN + i1_l = LBOUND(SrcParamData%EdgeVelRat2,1) + i1_u = UBOUND(SrcParamData%EdgeVelRat2,1) + i2_l = LBOUND(SrcParamData%EdgeVelRat2,2) + i2_u = UBOUND(SrcParamData%EdgeVelRat2,2) + i3_l = LBOUND(SrcParamData%EdgeVelRat2,3) + i3_u = UBOUND(SrcParamData%EdgeVelRat2,3) + IF (.NOT. ALLOCATED(DstParamData%EdgeVelRat2)) THEN + ALLOCATE(DstParamData%EdgeVelRat2(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%EdgeVelRat2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%EdgeVelRat2 = SrcParamData%EdgeVelRat2 +ENDIF +IF (ALLOCATED(SrcParamData%AFThickGuida)) THEN + i1_l = LBOUND(SrcParamData%AFThickGuida,1) + i1_u = UBOUND(SrcParamData%AFThickGuida,1) + i2_l = LBOUND(SrcParamData%AFThickGuida,2) + i2_u = UBOUND(SrcParamData%AFThickGuida,2) + IF (.NOT. ALLOCATED(DstParamData%AFThickGuida)) THEN + ALLOCATE(DstParamData%AFThickGuida(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AFThickGuida.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AFThickGuida = SrcParamData%AFThickGuida +ENDIF + END SUBROUTINE AA_CopyParam + + SUBROUTINE AA_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(AA_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%rotorregionlimitsVert)) THEN + DEALLOCATE(ParamData%rotorregionlimitsVert) +ENDIF +IF (ALLOCATED(ParamData%rotorregionlimitsHorz)) THEN + DEALLOCATE(ParamData%rotorregionlimitsHorz) +ENDIF +IF (ALLOCATED(ParamData%rotorregionlimitsalph)) THEN + DEALLOCATE(ParamData%rotorregionlimitsalph) +ENDIF +IF (ALLOCATED(ParamData%rotorregionlimitsrad)) THEN + DEALLOCATE(ParamData%rotorregionlimitsrad) +ENDIF +IF (ALLOCATED(ParamData%ObsX)) THEN + DEALLOCATE(ParamData%ObsX) +ENDIF +IF (ALLOCATED(ParamData%ObsY)) THEN + DEALLOCATE(ParamData%ObsY) +ENDIF +IF (ALLOCATED(ParamData%ObsZ)) THEN + DEALLOCATE(ParamData%ObsZ) +ENDIF +IF (ALLOCATED(ParamData%FreqList)) THEN + DEALLOCATE(ParamData%FreqList) +ENDIF +IF (ALLOCATED(ParamData%Aweight)) THEN + DEALLOCATE(ParamData%Aweight) +ENDIF +IF (ALLOCATED(ParamData%TI_Grid_In)) THEN + DEALLOCATE(ParamData%TI_Grid_In) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%StallStart)) THEN + DEALLOCATE(ParamData%StallStart) +ENDIF +IF (ALLOCATED(ParamData%TEThick)) THEN + DEALLOCATE(ParamData%TEThick) +ENDIF +IF (ALLOCATED(ParamData%TEAngle)) THEN + DEALLOCATE(ParamData%TEAngle) +ENDIF +IF (ALLOCATED(ParamData%AerCent)) THEN + DEALLOCATE(ParamData%AerCent) +ENDIF +IF (ALLOCATED(ParamData%BlAFID)) THEN + DEALLOCATE(ParamData%BlAFID) +ENDIF +IF (ALLOCATED(ParamData%AFInfo)) THEN +DO i1 = LBOUND(ParamData%AFInfo,1), UBOUND(ParamData%AFInfo,1) + CALL AFI_DestroyParam( ParamData%AFInfo(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%AFInfo) +ENDIF +IF (ALLOCATED(ParamData%AFLECo)) THEN + DEALLOCATE(ParamData%AFLECo) +ENDIF +IF (ALLOCATED(ParamData%AFTECo)) THEN + DEALLOCATE(ParamData%AFTECo) +ENDIF +IF (ALLOCATED(ParamData%BlSpn)) THEN + DEALLOCATE(ParamData%BlSpn) +ENDIF +IF (ALLOCATED(ParamData%BlChord)) THEN + DEALLOCATE(ParamData%BlChord) +ENDIF +IF (ALLOCATED(ParamData%ReListBL)) THEN + DEALLOCATE(ParamData%ReListBL) +ENDIF +IF (ALLOCATED(ParamData%AOAListBL)) THEN + DEALLOCATE(ParamData%AOAListBL) +ENDIF +IF (ALLOCATED(ParamData%dStarAll1)) THEN + DEALLOCATE(ParamData%dStarAll1) +ENDIF +IF (ALLOCATED(ParamData%dStarAll2)) THEN + DEALLOCATE(ParamData%dStarAll2) +ENDIF +IF (ALLOCATED(ParamData%d99All1)) THEN + DEALLOCATE(ParamData%d99All1) +ENDIF +IF (ALLOCATED(ParamData%d99All2)) THEN + DEALLOCATE(ParamData%d99All2) +ENDIF +IF (ALLOCATED(ParamData%CfAll1)) THEN + DEALLOCATE(ParamData%CfAll1) +ENDIF +IF (ALLOCATED(ParamData%CfAll2)) THEN + DEALLOCATE(ParamData%CfAll2) +ENDIF +IF (ALLOCATED(ParamData%EdgeVelRat1)) THEN + DEALLOCATE(ParamData%EdgeVelRat1) +ENDIF +IF (ALLOCATED(ParamData%EdgeVelRat2)) THEN + DEALLOCATE(ParamData%EdgeVelRat2) +ENDIF +IF (ALLOCATED(ParamData%AFThickGuida)) THEN + DEALLOCATE(ParamData%AFThickGuida) +ENDIF + END SUBROUTINE AA_DestroyParam + + SUBROUTINE AA_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(AA_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 = 'AA_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! IBLUNT + Int_BufSz = Int_BufSz + 1 ! ILAM + Int_BufSz = Int_BufSz + 1 ! ITIP + Int_BufSz = Int_BufSz + 1 ! ITRIP + Int_BufSz = Int_BufSz + 1 ! ITURB + Int_BufSz = Int_BufSz + 1 ! IInflow + Int_BufSz = Int_BufSz + 1 ! X_BLMethod + Int_BufSz = Int_BufSz + 1 ! TICalcMeth + Int_BufSz = Int_BufSz + 1 ! ROUND + Re_BufSz = Re_BufSz + 1 ! ALPRAT + Int_BufSz = Int_BufSz + 1 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumBlNds + Re_BufSz = Re_BufSz + 1 ! AirDens + Re_BufSz = Re_BufSz + 1 ! KinVisc + Re_BufSz = Re_BufSz + 1 ! SpdSound + Re_BufSz = Re_BufSz + 1 ! HubHeight + Re_BufSz = Re_BufSz + 1 ! toptip + Re_BufSz = Re_BufSz + 1 ! bottip + Int_BufSz = Int_BufSz + 1 ! rotorregionlimitsVert allocated yes/no + IF ( ALLOCATED(InData%rotorregionlimitsVert) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rotorregionlimitsVert upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rotorregionlimitsVert) ! rotorregionlimitsVert + END IF + Int_BufSz = Int_BufSz + 1 ! rotorregionlimitsHorz allocated yes/no + IF ( ALLOCATED(InData%rotorregionlimitsHorz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rotorregionlimitsHorz upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rotorregionlimitsHorz) ! rotorregionlimitsHorz + END IF + Int_BufSz = Int_BufSz + 1 ! rotorregionlimitsalph allocated yes/no + IF ( ALLOCATED(InData%rotorregionlimitsalph) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rotorregionlimitsalph upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rotorregionlimitsalph) ! rotorregionlimitsalph + END IF + Int_BufSz = Int_BufSz + 1 ! rotorregionlimitsrad allocated yes/no + IF ( ALLOCATED(InData%rotorregionlimitsrad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rotorregionlimitsrad upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rotorregionlimitsrad) ! rotorregionlimitsrad + END IF + Int_BufSz = Int_BufSz + 1 ! NrObsLoc + Int_BufSz = Int_BufSz + 1 ! aweightflag + Int_BufSz = Int_BufSz + 1 ! TxtFileOutput + Db_BufSz = Db_BufSz + 1 ! AAStart + Int_BufSz = Int_BufSz + 1 ! ObsX allocated yes/no + IF ( ALLOCATED(InData%ObsX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsX) ! ObsX + END IF + Int_BufSz = Int_BufSz + 1 ! ObsY allocated yes/no + IF ( ALLOCATED(InData%ObsY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsY) ! ObsY + END IF + Int_BufSz = Int_BufSz + 1 ! ObsZ allocated yes/no + IF ( ALLOCATED(InData%ObsZ) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ObsZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ObsZ) ! ObsZ + END IF + Int_BufSz = Int_BufSz + 1 ! FreqList allocated yes/no + IF ( ALLOCATED(InData%FreqList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FreqList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FreqList) ! FreqList + END IF + Int_BufSz = Int_BufSz + 1 ! Aweight allocated yes/no + IF ( ALLOCATED(InData%Aweight) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Aweight upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Aweight) ! Aweight + END IF + Re_BufSz = Re_BufSz + 1 ! Fsample + Int_BufSz = Int_BufSz + 1 ! total_sample + Int_BufSz = Int_BufSz + 1 ! total_sampleTI + Int_BufSz = Int_BufSz + 1 ! AA_Bl_Prcntge + Int_BufSz = Int_BufSz + 1 ! startnode + Re_BufSz = Re_BufSz + 1 ! z0_aa + Re_BufSz = Re_BufSz + 1 ! dz_turb_in + Re_BufSz = Re_BufSz + 1 ! dy_turb_in + Int_BufSz = Int_BufSz + 1 ! TI_Grid_In allocated yes/no + IF ( ALLOCATED(InData%TI_Grid_In) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI_Grid_In upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI_Grid_In) ! TI_Grid_In + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%FTitle) ! FTitle + Int_BufSz = Int_BufSz + 1*LEN(InData%outFmt) ! outFmt + Int_BufSz = Int_BufSz + 1 ! NrOutFile + Int_BufSz = Int_BufSz + 1*LEN(InData%delim) ! delim + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutsForPE + Int_BufSz = Int_BufSz + 1 ! NumOutsForSep + Int_BufSz = Int_BufSz + 1 ! NumOutsForNodes + Int_BufSz = Int_BufSz + 1 ! unOutFile + Int_BufSz = Int_BufSz + 1 ! unOutFile2 + Int_BufSz = Int_BufSz + 1 ! unOutFile3 + Int_BufSz = Int_BufSz + 1 ! unOutFile4 + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! StallStart allocated yes/no + IF ( ALLOCATED(InData%StallStart) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StallStart upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StallStart) ! StallStart + END IF + Int_BufSz = Int_BufSz + 1 ! TEThick allocated yes/no + IF ( ALLOCATED(InData%TEThick) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TEThick upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TEThick) ! TEThick + END IF + Int_BufSz = Int_BufSz + 1 ! TEAngle allocated yes/no + IF ( ALLOCATED(InData%TEAngle) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TEAngle upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TEAngle) ! TEAngle + END IF + Int_BufSz = Int_BufSz + 1 ! AerCent allocated yes/no + IF ( ALLOCATED(InData%AerCent) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AerCent upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AerCent) ! AerCent + END IF + Int_BufSz = Int_BufSz + 1 ! BlAFID allocated yes/no + IF ( ALLOCATED(InData%BlAFID) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlAFID upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BlAFID) ! BlAFID + END IF + Int_BufSz = Int_BufSz + 1 ! AFInfo allocated yes/no + IF ( ALLOCATED(InData%AFInfo) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AFInfo upper/lower bounds for each dimension + DO i1 = LBOUND(InData%AFInfo,1), UBOUND(InData%AFInfo,1) + Int_BufSz = Int_BufSz + 3 ! AFInfo: size of buffers for each call to pack subtype + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFInfo(i1), ErrStat2, ErrMsg2, .TRUE. ) ! AFInfo + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AFInfo + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AFInfo + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AFInfo + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! AFLECo allocated yes/no + IF ( ALLOCATED(InData%AFLECo) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AFLECo upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AFLECo) ! AFLECo + END IF + Int_BufSz = Int_BufSz + 1 ! AFTECo allocated yes/no + IF ( ALLOCATED(InData%AFTECo) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AFTECo upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AFTECo) ! AFTECo + END IF + Int_BufSz = Int_BufSz + 1 ! BlSpn allocated yes/no + IF ( ALLOCATED(InData%BlSpn) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlSpn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlSpn) ! BlSpn + END IF + Int_BufSz = Int_BufSz + 1 ! BlChord allocated yes/no + IF ( ALLOCATED(InData%BlChord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BlChord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlChord) ! BlChord + END IF + Int_BufSz = Int_BufSz + 1 ! ReListBL allocated yes/no + IF ( ALLOCATED(InData%ReListBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ReListBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ReListBL) ! ReListBL + END IF + Int_BufSz = Int_BufSz + 1 ! AOAListBL allocated yes/no + IF ( ALLOCATED(InData%AOAListBL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AOAListBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AOAListBL) ! AOAListBL + END IF + Int_BufSz = Int_BufSz + 1 ! dStarAll1 allocated yes/no + IF ( ALLOCATED(InData%dStarAll1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! dStarAll1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dStarAll1) ! dStarAll1 + END IF + Int_BufSz = Int_BufSz + 1 ! dStarAll2 allocated yes/no + IF ( ALLOCATED(InData%dStarAll2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! dStarAll2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dStarAll2) ! dStarAll2 + END IF + Int_BufSz = Int_BufSz + 1 ! d99All1 allocated yes/no + IF ( ALLOCATED(InData%d99All1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! d99All1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%d99All1) ! d99All1 + END IF + Int_BufSz = Int_BufSz + 1 ! d99All2 allocated yes/no + IF ( ALLOCATED(InData%d99All2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! d99All2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%d99All2) ! d99All2 + END IF + Int_BufSz = Int_BufSz + 1 ! CfAll1 allocated yes/no + IF ( ALLOCATED(InData%CfAll1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CfAll1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CfAll1) ! CfAll1 + END IF + Int_BufSz = Int_BufSz + 1 ! CfAll2 allocated yes/no + IF ( ALLOCATED(InData%CfAll2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CfAll2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CfAll2) ! CfAll2 + END IF + Int_BufSz = Int_BufSz + 1 ! EdgeVelRat1 allocated yes/no + IF ( ALLOCATED(InData%EdgeVelRat1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! EdgeVelRat1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgeVelRat1) ! EdgeVelRat1 + END IF + Int_BufSz = Int_BufSz + 1 ! EdgeVelRat2 allocated yes/no + IF ( ALLOCATED(InData%EdgeVelRat2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! EdgeVelRat2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgeVelRat2) ! EdgeVelRat2 + END IF + Int_BufSz = Int_BufSz + 1 ! AFThickGuida allocated yes/no + IF ( ALLOCATED(InData%AFThickGuida) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFThickGuida upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AFThickGuida) ! AFThickGuida + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IBLUNT + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ILAM + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITIP + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITRIP + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ITURB + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IInflow + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%X_BLMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TICalcMeth + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ROUND, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ALPRAT + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlNds + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdSound + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%toptip + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%bottip + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%rotorregionlimitsVert) ) 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%rotorregionlimitsVert,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rotorregionlimitsVert,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rotorregionlimitsVert,1), UBOUND(InData%rotorregionlimitsVert,1) + ReKiBuf(Re_Xferred) = InData%rotorregionlimitsVert(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rotorregionlimitsHorz) ) 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%rotorregionlimitsHorz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rotorregionlimitsHorz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rotorregionlimitsHorz,1), UBOUND(InData%rotorregionlimitsHorz,1) + ReKiBuf(Re_Xferred) = InData%rotorregionlimitsHorz(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rotorregionlimitsalph) ) 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%rotorregionlimitsalph,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rotorregionlimitsalph,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rotorregionlimitsalph,1), UBOUND(InData%rotorregionlimitsalph,1) + ReKiBuf(Re_Xferred) = InData%rotorregionlimitsalph(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rotorregionlimitsrad) ) 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%rotorregionlimitsrad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rotorregionlimitsrad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rotorregionlimitsrad,1), UBOUND(InData%rotorregionlimitsrad,1) + ReKiBuf(Re_Xferred) = InData%rotorregionlimitsrad(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NrObsLoc + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%aweightflag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TxtFileOutput, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%AAStart + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ObsX) ) 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%ObsX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsX,1), UBOUND(InData%ObsX,1) + ReKiBuf(Re_Xferred) = InData%ObsX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ObsY) ) 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%ObsY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsY,1), UBOUND(InData%ObsY,1) + ReKiBuf(Re_Xferred) = InData%ObsY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ObsZ) ) 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%ObsZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ObsZ,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ObsZ,1), UBOUND(InData%ObsZ,1) + ReKiBuf(Re_Xferred) = InData%ObsZ(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FreqList) ) 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%FreqList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FreqList,1), UBOUND(InData%FreqList,1) + ReKiBuf(Re_Xferred) = InData%FreqList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Aweight) ) 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%Aweight,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Aweight,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Aweight,1), UBOUND(InData%Aweight,1) + ReKiBuf(Re_Xferred) = InData%Aweight(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Fsample + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%total_sample + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%total_sampleTI + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AA_Bl_Prcntge + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%startnode + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%z0_aa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dz_turb_in + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dy_turb_in + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TI_Grid_In) ) 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%TI_Grid_In,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_Grid_In,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI_Grid_In,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_Grid_In,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TI_Grid_In,2), UBOUND(InData%TI_Grid_In,2) + DO i1 = LBOUND(InData%TI_Grid_In,1), UBOUND(InData%TI_Grid_In,1) + ReKiBuf(Re_Xferred) = InData%TI_Grid_In(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO I = 1, LEN(InData%FTitle) + IntKiBuf(Int_Xferred) = ICHAR(InData%FTitle(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%outFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%outFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NrOutFile + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutsForPE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutsForSep + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutsForNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%unOutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%unOutFile2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%unOutFile3 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%unOutFile4 + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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%StallStart) ) 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%StallStart,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StallStart,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StallStart,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StallStart,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StallStart,2), UBOUND(InData%StallStart,2) + DO i1 = LBOUND(InData%StallStart,1), UBOUND(InData%StallStart,1) + ReKiBuf(Re_Xferred) = InData%StallStart(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TEThick) ) 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%TEThick,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEThick,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TEThick,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEThick,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TEThick,2), UBOUND(InData%TEThick,2) + DO i1 = LBOUND(InData%TEThick,1), UBOUND(InData%TEThick,1) + ReKiBuf(Re_Xferred) = InData%TEThick(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TEAngle) ) 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%TEAngle,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEAngle,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TEAngle,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TEAngle,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TEAngle,2), UBOUND(InData%TEAngle,2) + DO i1 = LBOUND(InData%TEAngle,1), UBOUND(InData%TEAngle,1) + ReKiBuf(Re_Xferred) = InData%TEAngle(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AerCent) ) 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%AerCent,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AerCent,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AerCent,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AerCent,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AerCent,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AerCent,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AerCent,3), UBOUND(InData%AerCent,3) + DO i2 = LBOUND(InData%AerCent,2), UBOUND(InData%AerCent,2) + DO i1 = LBOUND(InData%AerCent,1), UBOUND(InData%AerCent,1) + ReKiBuf(Re_Xferred) = InData%AerCent(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlAFID) ) 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%BlAFID,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAFID,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlAFID,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAFID,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlAFID,2), UBOUND(InData%BlAFID,2) + DO i1 = LBOUND(InData%BlAFID,1), UBOUND(InData%BlAFID,1) + IntKiBuf(Int_Xferred) = InData%BlAFID(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFInfo) ) 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%AFInfo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFInfo,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AFInfo,1), UBOUND(InData%AFInfo,1) + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFInfo(i1), ErrStat2, ErrMsg2, OnlySize ) ! AFInfo + 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%AFLECo) ) 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%AFLECo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFLECo,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFLECo,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFLECo,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFLECo,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFLECo,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AFLECo,3), UBOUND(InData%AFLECo,3) + DO i2 = LBOUND(InData%AFLECo,2), UBOUND(InData%AFLECo,2) + DO i1 = LBOUND(InData%AFLECo,1), UBOUND(InData%AFLECo,1) + ReKiBuf(Re_Xferred) = InData%AFLECo(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFTECo) ) 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%AFTECo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFTECo,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFTECo,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFTECo,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFTECo,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFTECo,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AFTECo,3), UBOUND(InData%AFTECo,3) + DO i2 = LBOUND(InData%AFTECo,2), UBOUND(InData%AFTECo,2) + DO i1 = LBOUND(InData%AFTECo,1), UBOUND(InData%AFTECo,1) + ReKiBuf(Re_Xferred) = InData%AFTECo(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlSpn) ) 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%BlSpn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSpn,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlSpn,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSpn,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlSpn,2), UBOUND(InData%BlSpn,2) + DO i1 = LBOUND(InData%BlSpn,1), UBOUND(InData%BlSpn,1) + ReKiBuf(Re_Xferred) = InData%BlSpn(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlChord) ) 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%BlChord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlChord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BlChord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlChord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BlChord,2), UBOUND(InData%BlChord,2) + DO i1 = LBOUND(InData%BlChord,1), UBOUND(InData%BlChord,1) + ReKiBuf(Re_Xferred) = InData%BlChord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ReListBL) ) 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%ReListBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ReListBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ReListBL,1), UBOUND(InData%ReListBL,1) + ReKiBuf(Re_Xferred) = InData%ReListBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AOAListBL) ) 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%AOAListBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOAListBL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AOAListBL,1), UBOUND(InData%AOAListBL,1) + ReKiBuf(Re_Xferred) = InData%AOAListBL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dStarAll1) ) 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%dStarAll1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dStarAll1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dStarAll1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%dStarAll1,3), UBOUND(InData%dStarAll1,3) + DO i2 = LBOUND(InData%dStarAll1,2), UBOUND(InData%dStarAll1,2) + DO i1 = LBOUND(InData%dStarAll1,1), UBOUND(InData%dStarAll1,1) + ReKiBuf(Re_Xferred) = InData%dStarAll1(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dStarAll2) ) 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%dStarAll2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dStarAll2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dStarAll2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dStarAll2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%dStarAll2,3), UBOUND(InData%dStarAll2,3) + DO i2 = LBOUND(InData%dStarAll2,2), UBOUND(InData%dStarAll2,2) + DO i1 = LBOUND(InData%dStarAll2,1), UBOUND(InData%dStarAll2,1) + ReKiBuf(Re_Xferred) = InData%dStarAll2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%d99All1) ) 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%d99All1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%d99All1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%d99All1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%d99All1,3), UBOUND(InData%d99All1,3) + DO i2 = LBOUND(InData%d99All1,2), UBOUND(InData%d99All1,2) + DO i1 = LBOUND(InData%d99All1,1), UBOUND(InData%d99All1,1) + ReKiBuf(Re_Xferred) = InData%d99All1(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%d99All2) ) 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%d99All2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%d99All2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%d99All2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%d99All2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%d99All2,3), UBOUND(InData%d99All2,3) + DO i2 = LBOUND(InData%d99All2,2), UBOUND(InData%d99All2,2) + DO i1 = LBOUND(InData%d99All2,1), UBOUND(InData%d99All2,1) + ReKiBuf(Re_Xferred) = InData%d99All2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CfAll1) ) 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%CfAll1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CfAll1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CfAll1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CfAll1,3), UBOUND(InData%CfAll1,3) + DO i2 = LBOUND(InData%CfAll1,2), UBOUND(InData%CfAll1,2) + DO i1 = LBOUND(InData%CfAll1,1), UBOUND(InData%CfAll1,1) + ReKiBuf(Re_Xferred) = InData%CfAll1(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CfAll2) ) 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%CfAll2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CfAll2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CfAll2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CfAll2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CfAll2,3), UBOUND(InData%CfAll2,3) + DO i2 = LBOUND(InData%CfAll2,2), UBOUND(InData%CfAll2,2) + DO i1 = LBOUND(InData%CfAll2,1), UBOUND(InData%CfAll2,1) + ReKiBuf(Re_Xferred) = InData%CfAll2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgeVelRat1) ) 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%EdgeVelRat1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EdgeVelRat1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EdgeVelRat1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%EdgeVelRat1,3), UBOUND(InData%EdgeVelRat1,3) + DO i2 = LBOUND(InData%EdgeVelRat1,2), UBOUND(InData%EdgeVelRat1,2) + DO i1 = LBOUND(InData%EdgeVelRat1,1), UBOUND(InData%EdgeVelRat1,1) + ReKiBuf(Re_Xferred) = InData%EdgeVelRat1(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgeVelRat2) ) 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%EdgeVelRat2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EdgeVelRat2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EdgeVelRat2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgeVelRat2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%EdgeVelRat2,3), UBOUND(InData%EdgeVelRat2,3) + DO i2 = LBOUND(InData%EdgeVelRat2,2), UBOUND(InData%EdgeVelRat2,2) + DO i1 = LBOUND(InData%EdgeVelRat2,1), UBOUND(InData%EdgeVelRat2,1) + ReKiBuf(Re_Xferred) = InData%EdgeVelRat2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFThickGuida) ) 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%AFThickGuida,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFThickGuida,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFThickGuida,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFThickGuida,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFThickGuida,2), UBOUND(InData%AFThickGuida,2) + DO i1 = LBOUND(InData%AFThickGuida,1), UBOUND(InData%AFThickGuida,1) + ReKiBuf(Re_Xferred) = InData%AFThickGuida(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AA_PackParam + + SUBROUTINE AA_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(AA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AA_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%IBLUNT = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ILAM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITIP = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITRIP = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ITURB = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IInflow = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%X_BLMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TICalcMeth = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ROUND = TRANSFER(IntKiBuf(Int_Xferred), OutData%ROUND) + Int_Xferred = Int_Xferred + 1 + OutData%ALPRAT = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpdSound = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%toptip = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%bottip = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rotorregionlimitsVert 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%rotorregionlimitsVert)) DEALLOCATE(OutData%rotorregionlimitsVert) + ALLOCATE(OutData%rotorregionlimitsVert(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rotorregionlimitsVert.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rotorregionlimitsVert,1), UBOUND(OutData%rotorregionlimitsVert,1) + OutData%rotorregionlimitsVert(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rotorregionlimitsHorz 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%rotorregionlimitsHorz)) DEALLOCATE(OutData%rotorregionlimitsHorz) + ALLOCATE(OutData%rotorregionlimitsHorz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rotorregionlimitsHorz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rotorregionlimitsHorz,1), UBOUND(OutData%rotorregionlimitsHorz,1) + OutData%rotorregionlimitsHorz(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rotorregionlimitsalph 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%rotorregionlimitsalph)) DEALLOCATE(OutData%rotorregionlimitsalph) + ALLOCATE(OutData%rotorregionlimitsalph(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rotorregionlimitsalph.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rotorregionlimitsalph,1), UBOUND(OutData%rotorregionlimitsalph,1) + OutData%rotorregionlimitsalph(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rotorregionlimitsrad 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%rotorregionlimitsrad)) DEALLOCATE(OutData%rotorregionlimitsrad) + ALLOCATE(OutData%rotorregionlimitsrad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rotorregionlimitsrad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rotorregionlimitsrad,1), UBOUND(OutData%rotorregionlimitsrad,1) + OutData%rotorregionlimitsrad(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NrObsLoc = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%aweightflag = TRANSFER(IntKiBuf(Int_Xferred), OutData%aweightflag) + Int_Xferred = Int_Xferred + 1 + OutData%TxtFileOutput = TRANSFER(IntKiBuf(Int_Xferred), OutData%TxtFileOutput) + Int_Xferred = Int_Xferred + 1 + OutData%AAStart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsX 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%ObsX)) DEALLOCATE(OutData%ObsX) + ALLOCATE(OutData%ObsX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsX,1), UBOUND(OutData%ObsX,1) + OutData%ObsX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsY 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%ObsY)) DEALLOCATE(OutData%ObsY) + ALLOCATE(OutData%ObsY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsY,1), UBOUND(OutData%ObsY,1) + OutData%ObsY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ObsZ 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%ObsZ)) DEALLOCATE(OutData%ObsZ) + ALLOCATE(OutData%ObsZ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ObsZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ObsZ,1), UBOUND(OutData%ObsZ,1) + OutData%ObsZ(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FreqList 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%FreqList)) DEALLOCATE(OutData%FreqList) + ALLOCATE(OutData%FreqList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FreqList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FreqList,1), UBOUND(OutData%FreqList,1) + OutData%FreqList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Aweight 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%Aweight)) DEALLOCATE(OutData%Aweight) + ALLOCATE(OutData%Aweight(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Aweight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Aweight,1), UBOUND(OutData%Aweight,1) + OutData%Aweight(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Fsample = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%total_sample = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%total_sampleTI = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AA_Bl_Prcntge = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%startnode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%z0_aa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dz_turb_in = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dy_turb_in = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI_Grid_In 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%TI_Grid_In)) DEALLOCATE(OutData%TI_Grid_In) + ALLOCATE(OutData%TI_Grid_In(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI_Grid_In.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TI_Grid_In,2), UBOUND(OutData%TI_Grid_In,2) + DO i1 = LBOUND(OutData%TI_Grid_In,1), UBOUND(OutData%TI_Grid_In,1) + OutData%TI_Grid_In(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO I = 1, LEN(OutData%FTitle) + OutData%FTitle(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%outFmt) + OutData%outFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NrOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%delim) + OutData%delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutsForPE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutsForSep = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutsForNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%unOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%unOutFile2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%unOutFile3 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%unOutFile4 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StallStart 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%StallStart)) DEALLOCATE(OutData%StallStart) + ALLOCATE(OutData%StallStart(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StallStart.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StallStart,2), UBOUND(OutData%StallStart,2) + DO i1 = LBOUND(OutData%StallStart,1), UBOUND(OutData%StallStart,1) + OutData%StallStart(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TEThick 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%TEThick)) DEALLOCATE(OutData%TEThick) + ALLOCATE(OutData%TEThick(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TEThick.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TEThick,2), UBOUND(OutData%TEThick,2) + DO i1 = LBOUND(OutData%TEThick,1), UBOUND(OutData%TEThick,1) + OutData%TEThick(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TEAngle 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%TEAngle)) DEALLOCATE(OutData%TEAngle) + ALLOCATE(OutData%TEAngle(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TEAngle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TEAngle,2), UBOUND(OutData%TEAngle,2) + DO i1 = LBOUND(OutData%TEAngle,1), UBOUND(OutData%TEAngle,1) + OutData%TEAngle(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AerCent 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%AerCent)) DEALLOCATE(OutData%AerCent) + ALLOCATE(OutData%AerCent(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%AerCent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AerCent,3), UBOUND(OutData%AerCent,3) + DO i2 = LBOUND(OutData%AerCent,2), UBOUND(OutData%AerCent,2) + DO i1 = LBOUND(OutData%AerCent,1), UBOUND(OutData%AerCent,1) + OutData%AerCent(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlAFID 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%BlAFID)) DEALLOCATE(OutData%BlAFID) + ALLOCATE(OutData%BlAFID(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlAFID,2), UBOUND(OutData%BlAFID,2) + DO i1 = LBOUND(OutData%BlAFID,1), UBOUND(OutData%BlAFID,1) + OutData%BlAFID(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFInfo 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%AFInfo)) DEALLOCATE(OutData%AFInfo) + ALLOCATE(OutData%AFInfo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFInfo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AFInfo,1), UBOUND(OutData%AFInfo,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 AFI_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%AFInfo(i1), ErrStat2, ErrMsg2 ) ! AFInfo + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFLECo 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%AFLECo)) DEALLOCATE(OutData%AFLECo) + ALLOCATE(OutData%AFLECo(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%AFLECo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AFLECo,3), UBOUND(OutData%AFLECo,3) + DO i2 = LBOUND(OutData%AFLECo,2), UBOUND(OutData%AFLECo,2) + DO i1 = LBOUND(OutData%AFLECo,1), UBOUND(OutData%AFLECo,1) + OutData%AFLECo(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFTECo 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%AFTECo)) DEALLOCATE(OutData%AFTECo) + ALLOCATE(OutData%AFTECo(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%AFTECo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AFTECo,3), UBOUND(OutData%AFTECo,3) + DO i2 = LBOUND(OutData%AFTECo,2), UBOUND(OutData%AFTECo,2) + DO i1 = LBOUND(OutData%AFTECo,1), UBOUND(OutData%AFTECo,1) + OutData%AFTECo(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlSpn 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%BlSpn)) DEALLOCATE(OutData%BlSpn) + ALLOCATE(OutData%BlSpn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlSpn,2), UBOUND(OutData%BlSpn,2) + DO i1 = LBOUND(OutData%BlSpn,1), UBOUND(OutData%BlSpn,1) + OutData%BlSpn(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlChord 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%BlChord)) DEALLOCATE(OutData%BlChord) + ALLOCATE(OutData%BlChord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BlChord,2), UBOUND(OutData%BlChord,2) + DO i1 = LBOUND(OutData%BlChord,1), UBOUND(OutData%BlChord,1) + OutData%BlChord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ReListBL 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%ReListBL)) DEALLOCATE(OutData%ReListBL) + ALLOCATE(OutData%ReListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ReListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ReListBL,1), UBOUND(OutData%ReListBL,1) + OutData%ReListBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AOAListBL 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%AOAListBL)) DEALLOCATE(OutData%AOAListBL) + ALLOCATE(OutData%AOAListBL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AOAListBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AOAListBL,1), UBOUND(OutData%AOAListBL,1) + OutData%AOAListBL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dStarAll1 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%dStarAll1)) DEALLOCATE(OutData%dStarAll1) + ALLOCATE(OutData%dStarAll1(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%dStarAll1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%dStarAll1,3), UBOUND(OutData%dStarAll1,3) + DO i2 = LBOUND(OutData%dStarAll1,2), UBOUND(OutData%dStarAll1,2) + DO i1 = LBOUND(OutData%dStarAll1,1), UBOUND(OutData%dStarAll1,1) + OutData%dStarAll1(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dStarAll2 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%dStarAll2)) DEALLOCATE(OutData%dStarAll2) + ALLOCATE(OutData%dStarAll2(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%dStarAll2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%dStarAll2,3), UBOUND(OutData%dStarAll2,3) + DO i2 = LBOUND(OutData%dStarAll2,2), UBOUND(OutData%dStarAll2,2) + DO i1 = LBOUND(OutData%dStarAll2,1), UBOUND(OutData%dStarAll2,1) + OutData%dStarAll2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! d99All1 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%d99All1)) DEALLOCATE(OutData%d99All1) + ALLOCATE(OutData%d99All1(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%d99All1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%d99All1,3), UBOUND(OutData%d99All1,3) + DO i2 = LBOUND(OutData%d99All1,2), UBOUND(OutData%d99All1,2) + DO i1 = LBOUND(OutData%d99All1,1), UBOUND(OutData%d99All1,1) + OutData%d99All1(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! d99All2 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%d99All2)) DEALLOCATE(OutData%d99All2) + ALLOCATE(OutData%d99All2(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%d99All2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%d99All2,3), UBOUND(OutData%d99All2,3) + DO i2 = LBOUND(OutData%d99All2,2), UBOUND(OutData%d99All2,2) + DO i1 = LBOUND(OutData%d99All2,1), UBOUND(OutData%d99All2,1) + OutData%d99All2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CfAll1 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%CfAll1)) DEALLOCATE(OutData%CfAll1) + ALLOCATE(OutData%CfAll1(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%CfAll1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CfAll1,3), UBOUND(OutData%CfAll1,3) + DO i2 = LBOUND(OutData%CfAll1,2), UBOUND(OutData%CfAll1,2) + DO i1 = LBOUND(OutData%CfAll1,1), UBOUND(OutData%CfAll1,1) + OutData%CfAll1(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CfAll2 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%CfAll2)) DEALLOCATE(OutData%CfAll2) + ALLOCATE(OutData%CfAll2(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%CfAll2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CfAll2,3), UBOUND(OutData%CfAll2,3) + DO i2 = LBOUND(OutData%CfAll2,2), UBOUND(OutData%CfAll2,2) + DO i1 = LBOUND(OutData%CfAll2,1), UBOUND(OutData%CfAll2,1) + OutData%CfAll2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgeVelRat1 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%EdgeVelRat1)) DEALLOCATE(OutData%EdgeVelRat1) + ALLOCATE(OutData%EdgeVelRat1(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%EdgeVelRat1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%EdgeVelRat1,3), UBOUND(OutData%EdgeVelRat1,3) + DO i2 = LBOUND(OutData%EdgeVelRat1,2), UBOUND(OutData%EdgeVelRat1,2) + DO i1 = LBOUND(OutData%EdgeVelRat1,1), UBOUND(OutData%EdgeVelRat1,1) + OutData%EdgeVelRat1(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgeVelRat2 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%EdgeVelRat2)) DEALLOCATE(OutData%EdgeVelRat2) + ALLOCATE(OutData%EdgeVelRat2(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%EdgeVelRat2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%EdgeVelRat2,3), UBOUND(OutData%EdgeVelRat2,3) + DO i2 = LBOUND(OutData%EdgeVelRat2,2), UBOUND(OutData%EdgeVelRat2,2) + DO i1 = LBOUND(OutData%EdgeVelRat2,1), UBOUND(OutData%EdgeVelRat2,1) + OutData%EdgeVelRat2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFThickGuida 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%AFThickGuida)) DEALLOCATE(OutData%AFThickGuida) + ALLOCATE(OutData%AFThickGuida(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFThickGuida.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFThickGuida,2), UBOUND(OutData%AFThickGuida,2) + DO i1 = LBOUND(OutData%AFThickGuida,1), UBOUND(OutData%AFThickGuida,1) + OutData%AFThickGuida(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AA_UnPackParam + + SUBROUTINE AA_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_InputType), INTENT(IN) :: SrcInputData + TYPE(AA_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) :: 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 = 'AA_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%RotGtoL)) THEN + i1_l = LBOUND(SrcInputData%RotGtoL,1) + i1_u = UBOUND(SrcInputData%RotGtoL,1) + i2_l = LBOUND(SrcInputData%RotGtoL,2) + i2_u = UBOUND(SrcInputData%RotGtoL,2) + i3_l = LBOUND(SrcInputData%RotGtoL,3) + i3_u = UBOUND(SrcInputData%RotGtoL,3) + i4_l = LBOUND(SrcInputData%RotGtoL,4) + i4_u = UBOUND(SrcInputData%RotGtoL,4) + IF (.NOT. ALLOCATED(DstInputData%RotGtoL)) THEN + ALLOCATE(DstInputData%RotGtoL(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 DstInputData%RotGtoL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%RotGtoL = SrcInputData%RotGtoL +ENDIF +IF (ALLOCATED(SrcInputData%AeroCent_G)) THEN + i1_l = LBOUND(SrcInputData%AeroCent_G,1) + i1_u = UBOUND(SrcInputData%AeroCent_G,1) + i2_l = LBOUND(SrcInputData%AeroCent_G,2) + i2_u = UBOUND(SrcInputData%AeroCent_G,2) + i3_l = LBOUND(SrcInputData%AeroCent_G,3) + i3_u = UBOUND(SrcInputData%AeroCent_G,3) + IF (.NOT. ALLOCATED(DstInputData%AeroCent_G)) THEN + ALLOCATE(DstInputData%AeroCent_G(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%AeroCent_G.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%AeroCent_G = SrcInputData%AeroCent_G +ENDIF +IF (ALLOCATED(SrcInputData%Vrel)) THEN + i1_l = LBOUND(SrcInputData%Vrel,1) + i1_u = UBOUND(SrcInputData%Vrel,1) + i2_l = LBOUND(SrcInputData%Vrel,2) + i2_u = UBOUND(SrcInputData%Vrel,2) + IF (.NOT. ALLOCATED(DstInputData%Vrel)) THEN + ALLOCATE(DstInputData%Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Vrel = SrcInputData%Vrel +ENDIF +IF (ALLOCATED(SrcInputData%AoANoise)) THEN + i1_l = LBOUND(SrcInputData%AoANoise,1) + i1_u = UBOUND(SrcInputData%AoANoise,1) + i2_l = LBOUND(SrcInputData%AoANoise,2) + i2_u = UBOUND(SrcInputData%AoANoise,2) + IF (.NOT. ALLOCATED(DstInputData%AoANoise)) THEN + ALLOCATE(DstInputData%AoANoise(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%AoANoise.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%AoANoise = SrcInputData%AoANoise +ENDIF +IF (ALLOCATED(SrcInputData%Inflow)) THEN + i1_l = LBOUND(SrcInputData%Inflow,1) + i1_u = UBOUND(SrcInputData%Inflow,1) + i2_l = LBOUND(SrcInputData%Inflow,2) + i2_u = UBOUND(SrcInputData%Inflow,2) + i3_l = LBOUND(SrcInputData%Inflow,3) + i3_u = UBOUND(SrcInputData%Inflow,3) + IF (.NOT. ALLOCATED(DstInputData%Inflow)) THEN + ALLOCATE(DstInputData%Inflow(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Inflow.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Inflow = SrcInputData%Inflow +ENDIF + END SUBROUTINE AA_CopyInput + + SUBROUTINE AA_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(AA_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%RotGtoL)) THEN + DEALLOCATE(InputData%RotGtoL) +ENDIF +IF (ALLOCATED(InputData%AeroCent_G)) THEN + DEALLOCATE(InputData%AeroCent_G) +ENDIF +IF (ALLOCATED(InputData%Vrel)) THEN + DEALLOCATE(InputData%Vrel) +ENDIF +IF (ALLOCATED(InputData%AoANoise)) THEN + DEALLOCATE(InputData%AoANoise) +ENDIF +IF (ALLOCATED(InputData%Inflow)) THEN + DEALLOCATE(InputData%Inflow) +ENDIF + END SUBROUTINE AA_DestroyInput + + SUBROUTINE AA_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(AA_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 = 'AA_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 ! RotGtoL allocated yes/no + IF ( ALLOCATED(InData%RotGtoL) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! RotGtoL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RotGtoL) ! RotGtoL + END IF + Int_BufSz = Int_BufSz + 1 ! AeroCent_G allocated yes/no + IF ( ALLOCATED(InData%AeroCent_G) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AeroCent_G upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AeroCent_G) ! AeroCent_G + END IF + Int_BufSz = Int_BufSz + 1 ! Vrel allocated yes/no + IF ( ALLOCATED(InData%Vrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vrel) ! Vrel + END IF + Int_BufSz = Int_BufSz + 1 ! AoANoise allocated yes/no + IF ( ALLOCATED(InData%AoANoise) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AoANoise upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AoANoise) ! AoANoise + END IF + Int_BufSz = Int_BufSz + 1 ! Inflow allocated yes/no + IF ( ALLOCATED(InData%Inflow) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Inflow upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Inflow) ! Inflow + 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%RotGtoL) ) 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%RotGtoL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotGtoL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotGtoL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotGtoL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotGtoL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotGtoL,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotGtoL,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotGtoL,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%RotGtoL,4), UBOUND(InData%RotGtoL,4) + DO i3 = LBOUND(InData%RotGtoL,3), UBOUND(InData%RotGtoL,3) + DO i2 = LBOUND(InData%RotGtoL,2), UBOUND(InData%RotGtoL,2) + DO i1 = LBOUND(InData%RotGtoL,1), UBOUND(InData%RotGtoL,1) + ReKiBuf(Re_Xferred) = InData%RotGtoL(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AeroCent_G) ) 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%AeroCent_G,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AeroCent_G,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AeroCent_G,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AeroCent_G,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AeroCent_G,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AeroCent_G,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AeroCent_G,3), UBOUND(InData%AeroCent_G,3) + DO i2 = LBOUND(InData%AeroCent_G,2), UBOUND(InData%AeroCent_G,2) + DO i1 = LBOUND(InData%AeroCent_G,1), UBOUND(InData%AeroCent_G,1) + ReKiBuf(Re_Xferred) = InData%AeroCent_G(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vrel) ) 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%Vrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vrel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vrel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vrel,2), UBOUND(InData%Vrel,2) + DO i1 = LBOUND(InData%Vrel,1), UBOUND(InData%Vrel,1) + ReKiBuf(Re_Xferred) = InData%Vrel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AoANoise) ) 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%AoANoise,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AoANoise,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AoANoise,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AoANoise,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AoANoise,2), UBOUND(InData%AoANoise,2) + DO i1 = LBOUND(InData%AoANoise,1), UBOUND(InData%AoANoise,1) + ReKiBuf(Re_Xferred) = InData%AoANoise(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Inflow) ) 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%Inflow,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Inflow,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Inflow,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Inflow,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Inflow,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Inflow,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Inflow,3), UBOUND(InData%Inflow,3) + DO i2 = LBOUND(InData%Inflow,2), UBOUND(InData%Inflow,2) + DO i1 = LBOUND(InData%Inflow,1), UBOUND(InData%Inflow,1) + ReKiBuf(Re_Xferred) = InData%Inflow(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AA_PackInput + + SUBROUTINE AA_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(AA_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) :: 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 = 'AA_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 ! RotGtoL 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%RotGtoL)) DEALLOCATE(OutData%RotGtoL) + ALLOCATE(OutData%RotGtoL(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%RotGtoL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%RotGtoL,4), UBOUND(OutData%RotGtoL,4) + DO i3 = LBOUND(OutData%RotGtoL,3), UBOUND(OutData%RotGtoL,3) + DO i2 = LBOUND(OutData%RotGtoL,2), UBOUND(OutData%RotGtoL,2) + DO i1 = LBOUND(OutData%RotGtoL,1), UBOUND(OutData%RotGtoL,1) + OutData%RotGtoL(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AeroCent_G 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%AeroCent_G)) DEALLOCATE(OutData%AeroCent_G) + ALLOCATE(OutData%AeroCent_G(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%AeroCent_G.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AeroCent_G,3), UBOUND(OutData%AeroCent_G,3) + DO i2 = LBOUND(OutData%AeroCent_G,2), UBOUND(OutData%AeroCent_G,2) + DO i1 = LBOUND(OutData%AeroCent_G,1), UBOUND(OutData%AeroCent_G,1) + OutData%AeroCent_G(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vrel 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%Vrel)) DEALLOCATE(OutData%Vrel) + ALLOCATE(OutData%Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vrel,2), UBOUND(OutData%Vrel,2) + DO i1 = LBOUND(OutData%Vrel,1), UBOUND(OutData%Vrel,1) + OutData%Vrel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AoANoise 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%AoANoise)) DEALLOCATE(OutData%AoANoise) + ALLOCATE(OutData%AoANoise(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AoANoise.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AoANoise,2), UBOUND(OutData%AoANoise,2) + DO i1 = LBOUND(OutData%AoANoise,1), UBOUND(OutData%AoANoise,1) + OutData%AoANoise(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Inflow 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%Inflow)) DEALLOCATE(OutData%Inflow) + ALLOCATE(OutData%Inflow(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%Inflow.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Inflow,3), UBOUND(OutData%Inflow,3) + DO i2 = LBOUND(OutData%Inflow,2), UBOUND(OutData%Inflow,2) + DO i1 = LBOUND(OutData%Inflow,1), UBOUND(OutData%Inflow,1) + OutData%Inflow(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AA_UnPackInput + + SUBROUTINE AA_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AA_OutputType), INTENT(IN) :: SrcOutputData + TYPE(AA_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'AA_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%SumSpecNoise)) THEN + i1_l = LBOUND(SrcOutputData%SumSpecNoise,1) + i1_u = UBOUND(SrcOutputData%SumSpecNoise,1) + i2_l = LBOUND(SrcOutputData%SumSpecNoise,2) + i2_u = UBOUND(SrcOutputData%SumSpecNoise,2) + i3_l = LBOUND(SrcOutputData%SumSpecNoise,3) + i3_u = UBOUND(SrcOutputData%SumSpecNoise,3) + IF (.NOT. ALLOCATED(DstOutputData%SumSpecNoise)) THEN + ALLOCATE(DstOutputData%SumSpecNoise(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%SumSpecNoise.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%SumSpecNoise = SrcOutputData%SumSpecNoise +ENDIF +IF (ALLOCATED(SrcOutputData%SumSpecNoiseSep)) THEN + i1_l = LBOUND(SrcOutputData%SumSpecNoiseSep,1) + i1_u = UBOUND(SrcOutputData%SumSpecNoiseSep,1) + i2_l = LBOUND(SrcOutputData%SumSpecNoiseSep,2) + i2_u = UBOUND(SrcOutputData%SumSpecNoiseSep,2) + i3_l = LBOUND(SrcOutputData%SumSpecNoiseSep,3) + i3_u = UBOUND(SrcOutputData%SumSpecNoiseSep,3) + IF (.NOT. ALLOCATED(DstOutputData%SumSpecNoiseSep)) THEN + ALLOCATE(DstOutputData%SumSpecNoiseSep(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%SumSpecNoiseSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%SumSpecNoiseSep = SrcOutputData%SumSpecNoiseSep +ENDIF +IF (ALLOCATED(SrcOutputData%OASPL)) THEN + i1_l = LBOUND(SrcOutputData%OASPL,1) + i1_u = UBOUND(SrcOutputData%OASPL,1) + i2_l = LBOUND(SrcOutputData%OASPL,2) + i2_u = UBOUND(SrcOutputData%OASPL,2) + i3_l = LBOUND(SrcOutputData%OASPL,3) + i3_u = UBOUND(SrcOutputData%OASPL,3) + IF (.NOT. ALLOCATED(DstOutputData%OASPL)) THEN + ALLOCATE(DstOutputData%OASPL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%OASPL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%OASPL = SrcOutputData%OASPL +ENDIF +IF (ALLOCATED(SrcOutputData%OASPL_Mech)) THEN + i1_l = LBOUND(SrcOutputData%OASPL_Mech,1) + i1_u = UBOUND(SrcOutputData%OASPL_Mech,1) + i2_l = LBOUND(SrcOutputData%OASPL_Mech,2) + i2_u = UBOUND(SrcOutputData%OASPL_Mech,2) + i3_l = LBOUND(SrcOutputData%OASPL_Mech,3) + i3_u = UBOUND(SrcOutputData%OASPL_Mech,3) + i4_l = LBOUND(SrcOutputData%OASPL_Mech,4) + i4_u = UBOUND(SrcOutputData%OASPL_Mech,4) + IF (.NOT. ALLOCATED(DstOutputData%OASPL_Mech)) THEN + ALLOCATE(DstOutputData%OASPL_Mech(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 DstOutputData%OASPL_Mech.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%OASPL_Mech = SrcOutputData%OASPL_Mech +ENDIF +IF (ALLOCATED(SrcOutputData%DirectiviOutput)) THEN + i1_l = LBOUND(SrcOutputData%DirectiviOutput,1) + i1_u = UBOUND(SrcOutputData%DirectiviOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%DirectiviOutput)) THEN + ALLOCATE(DstOutputData%DirectiviOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%DirectiviOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%DirectiviOutput = SrcOutputData%DirectiviOutput +ENDIF +IF (ALLOCATED(SrcOutputData%OutLECoords)) THEN + i1_l = LBOUND(SrcOutputData%OutLECoords,1) + i1_u = UBOUND(SrcOutputData%OutLECoords,1) + i2_l = LBOUND(SrcOutputData%OutLECoords,2) + i2_u = UBOUND(SrcOutputData%OutLECoords,2) + i3_l = LBOUND(SrcOutputData%OutLECoords,3) + i3_u = UBOUND(SrcOutputData%OutLECoords,3) + i4_l = LBOUND(SrcOutputData%OutLECoords,4) + i4_u = UBOUND(SrcOutputData%OutLECoords,4) + IF (.NOT. ALLOCATED(DstOutputData%OutLECoords)) THEN + ALLOCATE(DstOutputData%OutLECoords(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 DstOutputData%OutLECoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%OutLECoords = SrcOutputData%OutLECoords +ENDIF +IF (ALLOCATED(SrcOutputData%PtotalFreq)) THEN + i1_l = LBOUND(SrcOutputData%PtotalFreq,1) + i1_u = UBOUND(SrcOutputData%PtotalFreq,1) + i2_l = LBOUND(SrcOutputData%PtotalFreq,2) + i2_u = UBOUND(SrcOutputData%PtotalFreq,2) + IF (.NOT. ALLOCATED(DstOutputData%PtotalFreq)) THEN + ALLOCATE(DstOutputData%PtotalFreq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%PtotalFreq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%PtotalFreq = SrcOutputData%PtotalFreq +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutputForPE)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutputForPE,1) + i1_u = UBOUND(SrcOutputData%WriteOutputForPE,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutputForPE)) THEN + ALLOCATE(DstOutputData%WriteOutputForPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutputForPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutputForPE = SrcOutputData%WriteOutputForPE +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutputSep)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutputSep,1) + i1_u = UBOUND(SrcOutputData%WriteOutputSep,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutputSep)) THEN + ALLOCATE(DstOutputData%WriteOutputSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutputSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutputSep = SrcOutputData%WriteOutputSep +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutputNode)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutputNode,1) + i1_u = UBOUND(SrcOutputData%WriteOutputNode,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutputNode)) THEN + ALLOCATE(DstOutputData%WriteOutputNode(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutputNode.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutputNode = SrcOutputData%WriteOutputNode +ENDIF + END SUBROUTINE AA_CopyOutput + + SUBROUTINE AA_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(AA_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AA_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%SumSpecNoise)) THEN + DEALLOCATE(OutputData%SumSpecNoise) +ENDIF +IF (ALLOCATED(OutputData%SumSpecNoiseSep)) THEN + DEALLOCATE(OutputData%SumSpecNoiseSep) +ENDIF +IF (ALLOCATED(OutputData%OASPL)) THEN + DEALLOCATE(OutputData%OASPL) +ENDIF +IF (ALLOCATED(OutputData%OASPL_Mech)) THEN + DEALLOCATE(OutputData%OASPL_Mech) +ENDIF +IF (ALLOCATED(OutputData%DirectiviOutput)) THEN + DEALLOCATE(OutputData%DirectiviOutput) +ENDIF +IF (ALLOCATED(OutputData%OutLECoords)) THEN + DEALLOCATE(OutputData%OutLECoords) +ENDIF +IF (ALLOCATED(OutputData%PtotalFreq)) THEN + DEALLOCATE(OutputData%PtotalFreq) +ENDIF +IF (ALLOCATED(OutputData%WriteOutputForPE)) THEN + DEALLOCATE(OutputData%WriteOutputForPE) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF +IF (ALLOCATED(OutputData%WriteOutputSep)) THEN + DEALLOCATE(OutputData%WriteOutputSep) +ENDIF +IF (ALLOCATED(OutputData%WriteOutputNode)) THEN + DEALLOCATE(OutputData%WriteOutputNode) +ENDIF + END SUBROUTINE AA_DestroyOutput + + SUBROUTINE AA_PackOutput( 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(AA_OutputType), 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 = 'AA_PackOutput' + ! 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 ! SumSpecNoise allocated yes/no + IF ( ALLOCATED(InData%SumSpecNoise) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SumSpecNoise upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SumSpecNoise) ! SumSpecNoise + END IF + Int_BufSz = Int_BufSz + 1 ! SumSpecNoiseSep allocated yes/no + IF ( ALLOCATED(InData%SumSpecNoiseSep) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SumSpecNoiseSep upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SumSpecNoiseSep) ! SumSpecNoiseSep + END IF + Int_BufSz = Int_BufSz + 1 ! OASPL allocated yes/no + IF ( ALLOCATED(InData%OASPL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! OASPL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OASPL) ! OASPL + END IF + Int_BufSz = Int_BufSz + 1 ! OASPL_Mech allocated yes/no + IF ( ALLOCATED(InData%OASPL_Mech) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! OASPL_Mech upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OASPL_Mech) ! OASPL_Mech + END IF + Int_BufSz = Int_BufSz + 1 ! DirectiviOutput allocated yes/no + IF ( ALLOCATED(InData%DirectiviOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DirectiviOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DirectiviOutput) ! DirectiviOutput + END IF + Int_BufSz = Int_BufSz + 1 ! OutLECoords allocated yes/no + IF ( ALLOCATED(InData%OutLECoords) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! OutLECoords upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OutLECoords) ! OutLECoords + END IF + Int_BufSz = Int_BufSz + 1 ! PtotalFreq allocated yes/no + IF ( ALLOCATED(InData%PtotalFreq) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PtotalFreq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtotalFreq) ! PtotalFreq + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputForPE allocated yes/no + IF ( ALLOCATED(InData%WriteOutputForPE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputForPE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutputForPE) ! WriteOutputForPE + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputSep allocated yes/no + IF ( ALLOCATED(InData%WriteOutputSep) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputSep upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutputSep) ! WriteOutputSep + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputNode allocated yes/no + IF ( ALLOCATED(InData%WriteOutputNode) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputNode upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutputNode) ! WriteOutputNode + 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%SumSpecNoise) ) 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%SumSpecNoise,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoise,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SumSpecNoise,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoise,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SumSpecNoise,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoise,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SumSpecNoise,3), UBOUND(InData%SumSpecNoise,3) + DO i2 = LBOUND(InData%SumSpecNoise,2), UBOUND(InData%SumSpecNoise,2) + DO i1 = LBOUND(InData%SumSpecNoise,1), UBOUND(InData%SumSpecNoise,1) + ReKiBuf(Re_Xferred) = InData%SumSpecNoise(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SumSpecNoiseSep) ) 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%SumSpecNoiseSep,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoiseSep,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SumSpecNoiseSep,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoiseSep,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SumSpecNoiseSep,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SumSpecNoiseSep,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SumSpecNoiseSep,3), UBOUND(InData%SumSpecNoiseSep,3) + DO i2 = LBOUND(InData%SumSpecNoiseSep,2), UBOUND(InData%SumSpecNoiseSep,2) + DO i1 = LBOUND(InData%SumSpecNoiseSep,1), UBOUND(InData%SumSpecNoiseSep,1) + ReKiBuf(Re_Xferred) = InData%SumSpecNoiseSep(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OASPL) ) 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%OASPL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OASPL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OASPL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%OASPL,3), UBOUND(InData%OASPL,3) + DO i2 = LBOUND(InData%OASPL,2), UBOUND(InData%OASPL,2) + DO i1 = LBOUND(InData%OASPL,1), UBOUND(InData%OASPL,1) + ReKiBuf(Re_Xferred) = InData%OASPL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OASPL_Mech) ) 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%OASPL_Mech,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL_Mech,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OASPL_Mech,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL_Mech,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OASPL_Mech,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL_Mech,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OASPL_Mech,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OASPL_Mech,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%OASPL_Mech,4), UBOUND(InData%OASPL_Mech,4) + DO i3 = LBOUND(InData%OASPL_Mech,3), UBOUND(InData%OASPL_Mech,3) + DO i2 = LBOUND(InData%OASPL_Mech,2), UBOUND(InData%OASPL_Mech,2) + DO i1 = LBOUND(InData%OASPL_Mech,1), UBOUND(InData%OASPL_Mech,1) + ReKiBuf(Re_Xferred) = InData%OASPL_Mech(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DirectiviOutput) ) 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%DirectiviOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DirectiviOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DirectiviOutput,1), UBOUND(InData%DirectiviOutput,1) + ReKiBuf(Re_Xferred) = InData%DirectiviOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OutLECoords) ) 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%OutLECoords,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutLECoords,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutLECoords,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutLECoords,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutLECoords,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutLECoords,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutLECoords,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutLECoords,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%OutLECoords,4), UBOUND(InData%OutLECoords,4) + DO i3 = LBOUND(InData%OutLECoords,3), UBOUND(InData%OutLECoords,3) + DO i2 = LBOUND(InData%OutLECoords,2), UBOUND(InData%OutLECoords,2) + DO i1 = LBOUND(InData%OutLECoords,1), UBOUND(InData%OutLECoords,1) + ReKiBuf(Re_Xferred) = InData%OutLECoords(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtotalFreq) ) 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%PtotalFreq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtotalFreq,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtotalFreq,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtotalFreq,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PtotalFreq,2), UBOUND(InData%PtotalFreq,2) + DO i1 = LBOUND(InData%PtotalFreq,1), UBOUND(InData%PtotalFreq,1) + ReKiBuf(Re_Xferred) = InData%PtotalFreq(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputForPE) ) 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%WriteOutputForPE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputForPE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputForPE,1), UBOUND(InData%WriteOutputForPE,1) + ReKiBuf(Re_Xferred) = InData%WriteOutputForPE(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputSep) ) 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%WriteOutputSep,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputSep,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputSep,1), UBOUND(InData%WriteOutputSep,1) + ReKiBuf(Re_Xferred) = InData%WriteOutputSep(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputNode) ) 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%WriteOutputNode,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputNode,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputNode,1), UBOUND(InData%WriteOutputNode,1) + ReKiBuf(Re_Xferred) = InData%WriteOutputNode(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AA_PackOutput + + SUBROUTINE AA_UnPackOutput( 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(AA_OutputType), 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 = 'AA_UnPackOutput' + ! 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 ! SumSpecNoise 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%SumSpecNoise)) DEALLOCATE(OutData%SumSpecNoise) + ALLOCATE(OutData%SumSpecNoise(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%SumSpecNoise.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SumSpecNoise,3), UBOUND(OutData%SumSpecNoise,3) + DO i2 = LBOUND(OutData%SumSpecNoise,2), UBOUND(OutData%SumSpecNoise,2) + DO i1 = LBOUND(OutData%SumSpecNoise,1), UBOUND(OutData%SumSpecNoise,1) + OutData%SumSpecNoise(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SumSpecNoiseSep 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%SumSpecNoiseSep)) DEALLOCATE(OutData%SumSpecNoiseSep) + ALLOCATE(OutData%SumSpecNoiseSep(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%SumSpecNoiseSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SumSpecNoiseSep,3), UBOUND(OutData%SumSpecNoiseSep,3) + DO i2 = LBOUND(OutData%SumSpecNoiseSep,2), UBOUND(OutData%SumSpecNoiseSep,2) + DO i1 = LBOUND(OutData%SumSpecNoiseSep,1), UBOUND(OutData%SumSpecNoiseSep,1) + OutData%SumSpecNoiseSep(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OASPL 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%OASPL)) DEALLOCATE(OutData%OASPL) + ALLOCATE(OutData%OASPL(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%OASPL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%OASPL,3), UBOUND(OutData%OASPL,3) + DO i2 = LBOUND(OutData%OASPL,2), UBOUND(OutData%OASPL,2) + DO i1 = LBOUND(OutData%OASPL,1), UBOUND(OutData%OASPL,1) + OutData%OASPL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OASPL_Mech 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%OASPL_Mech)) DEALLOCATE(OutData%OASPL_Mech) + ALLOCATE(OutData%OASPL_Mech(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%OASPL_Mech.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%OASPL_Mech,4), UBOUND(OutData%OASPL_Mech,4) + DO i3 = LBOUND(OutData%OASPL_Mech,3), UBOUND(OutData%OASPL_Mech,3) + DO i2 = LBOUND(OutData%OASPL_Mech,2), UBOUND(OutData%OASPL_Mech,2) + DO i1 = LBOUND(OutData%OASPL_Mech,1), UBOUND(OutData%OASPL_Mech,1) + OutData%OASPL_Mech(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DirectiviOutput 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%DirectiviOutput)) DEALLOCATE(OutData%DirectiviOutput) + ALLOCATE(OutData%DirectiviOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DirectiviOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DirectiviOutput,1), UBOUND(OutData%DirectiviOutput,1) + OutData%DirectiviOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutLECoords 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%OutLECoords)) DEALLOCATE(OutData%OutLECoords) + ALLOCATE(OutData%OutLECoords(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%OutLECoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%OutLECoords,4), UBOUND(OutData%OutLECoords,4) + DO i3 = LBOUND(OutData%OutLECoords,3), UBOUND(OutData%OutLECoords,3) + DO i2 = LBOUND(OutData%OutLECoords,2), UBOUND(OutData%OutLECoords,2) + DO i1 = LBOUND(OutData%OutLECoords,1), UBOUND(OutData%OutLECoords,1) + OutData%OutLECoords(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtotalFreq 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%PtotalFreq)) DEALLOCATE(OutData%PtotalFreq) + ALLOCATE(OutData%PtotalFreq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtotalFreq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PtotalFreq,2), UBOUND(OutData%PtotalFreq,2) + DO i1 = LBOUND(OutData%PtotalFreq,1), UBOUND(OutData%PtotalFreq,1) + OutData%PtotalFreq(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputForPE 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%WriteOutputForPE)) DEALLOCATE(OutData%WriteOutputForPE) + ALLOCATE(OutData%WriteOutputForPE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputForPE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputForPE,1), UBOUND(OutData%WriteOutputForPE,1) + OutData%WriteOutputForPE(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputSep 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%WriteOutputSep)) DEALLOCATE(OutData%WriteOutputSep) + ALLOCATE(OutData%WriteOutputSep(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputSep.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputSep,1), UBOUND(OutData%WriteOutputSep,1) + OutData%WriteOutputSep(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputNode 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%WriteOutputNode)) DEALLOCATE(OutData%WriteOutputNode) + ALLOCATE(OutData%WriteOutputNode(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputNode.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputNode,1), UBOUND(OutData%WriteOutputNode,1) + OutData%WriteOutputNode(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AA_UnPackOutput + + + SUBROUTINE AA_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AA_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(AA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL AA_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AA_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AA_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AA_Input_ExtrapInterp + + + SUBROUTINE AA_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(AA_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(AA_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(AA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%RotGtoL) .AND. ALLOCATED(u1%RotGtoL)) THEN + DO i4 = LBOUND(u_out%RotGtoL,4),UBOUND(u_out%RotGtoL,4) + DO i3 = LBOUND(u_out%RotGtoL,3),UBOUND(u_out%RotGtoL,3) + DO i2 = LBOUND(u_out%RotGtoL,2),UBOUND(u_out%RotGtoL,2) + DO i1 = LBOUND(u_out%RotGtoL,1),UBOUND(u_out%RotGtoL,1) + b = -(u1%RotGtoL(i1,i2,i3,i4) - u2%RotGtoL(i1,i2,i3,i4)) + u_out%RotGtoL(i1,i2,i3,i4) = u1%RotGtoL(i1,i2,i3,i4) + b * ScaleFactor + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%AeroCent_G) .AND. ALLOCATED(u1%AeroCent_G)) THEN + DO i3 = LBOUND(u_out%AeroCent_G,3),UBOUND(u_out%AeroCent_G,3) + DO i2 = LBOUND(u_out%AeroCent_G,2),UBOUND(u_out%AeroCent_G,2) + DO i1 = LBOUND(u_out%AeroCent_G,1),UBOUND(u_out%AeroCent_G,1) + b = -(u1%AeroCent_G(i1,i2,i3) - u2%AeroCent_G(i1,i2,i3)) + u_out%AeroCent_G(i1,i2,i3) = u1%AeroCent_G(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vrel) .AND. ALLOCATED(u1%Vrel)) THEN + DO i2 = LBOUND(u_out%Vrel,2),UBOUND(u_out%Vrel,2) + DO i1 = LBOUND(u_out%Vrel,1),UBOUND(u_out%Vrel,1) + b = -(u1%Vrel(i1,i2) - u2%Vrel(i1,i2)) + u_out%Vrel(i1,i2) = u1%Vrel(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%AoANoise) .AND. ALLOCATED(u1%AoANoise)) THEN + DO i2 = LBOUND(u_out%AoANoise,2),UBOUND(u_out%AoANoise,2) + DO i1 = LBOUND(u_out%AoANoise,1),UBOUND(u_out%AoANoise,1) + b = -(u1%AoANoise(i1,i2) - u2%AoANoise(i1,i2)) + u_out%AoANoise(i1,i2) = u1%AoANoise(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Inflow) .AND. ALLOCATED(u1%Inflow)) THEN + DO i3 = LBOUND(u_out%Inflow,3),UBOUND(u_out%Inflow,3) + DO i2 = LBOUND(u_out%Inflow,2),UBOUND(u_out%Inflow,2) + DO i1 = LBOUND(u_out%Inflow,1),UBOUND(u_out%Inflow,1) + b = -(u1%Inflow(i1,i2,i3) - u2%Inflow(i1,i2,i3)) + u_out%Inflow(i1,i2,i3) = u1%Inflow(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated + END SUBROUTINE AA_Input_ExtrapInterp1 + + + SUBROUTINE AA_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(AA_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(AA_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(AA_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(AA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%RotGtoL) .AND. ALLOCATED(u1%RotGtoL)) THEN + DO i4 = LBOUND(u_out%RotGtoL,4),UBOUND(u_out%RotGtoL,4) + DO i3 = LBOUND(u_out%RotGtoL,3),UBOUND(u_out%RotGtoL,3) + DO i2 = LBOUND(u_out%RotGtoL,2),UBOUND(u_out%RotGtoL,2) + DO i1 = LBOUND(u_out%RotGtoL,1),UBOUND(u_out%RotGtoL,1) + b = (t(3)**2*(u1%RotGtoL(i1,i2,i3,i4) - u2%RotGtoL(i1,i2,i3,i4)) + t(2)**2*(-u1%RotGtoL(i1,i2,i3,i4) + u3%RotGtoL(i1,i2,i3,i4)))* scaleFactor + c = ( (t(2)-t(3))*u1%RotGtoL(i1,i2,i3,i4) + t(3)*u2%RotGtoL(i1,i2,i3,i4) - t(2)*u3%RotGtoL(i1,i2,i3,i4) ) * scaleFactor + u_out%RotGtoL(i1,i2,i3,i4) = u1%RotGtoL(i1,i2,i3,i4) + b + c * t_out + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%AeroCent_G) .AND. ALLOCATED(u1%AeroCent_G)) THEN + DO i3 = LBOUND(u_out%AeroCent_G,3),UBOUND(u_out%AeroCent_G,3) + DO i2 = LBOUND(u_out%AeroCent_G,2),UBOUND(u_out%AeroCent_G,2) + DO i1 = LBOUND(u_out%AeroCent_G,1),UBOUND(u_out%AeroCent_G,1) + b = (t(3)**2*(u1%AeroCent_G(i1,i2,i3) - u2%AeroCent_G(i1,i2,i3)) + t(2)**2*(-u1%AeroCent_G(i1,i2,i3) + u3%AeroCent_G(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*u1%AeroCent_G(i1,i2,i3) + t(3)*u2%AeroCent_G(i1,i2,i3) - t(2)*u3%AeroCent_G(i1,i2,i3) ) * scaleFactor + u_out%AeroCent_G(i1,i2,i3) = u1%AeroCent_G(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vrel) .AND. ALLOCATED(u1%Vrel)) THEN + DO i2 = LBOUND(u_out%Vrel,2),UBOUND(u_out%Vrel,2) + DO i1 = LBOUND(u_out%Vrel,1),UBOUND(u_out%Vrel,1) + b = (t(3)**2*(u1%Vrel(i1,i2) - u2%Vrel(i1,i2)) + t(2)**2*(-u1%Vrel(i1,i2) + u3%Vrel(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Vrel(i1,i2) + t(3)*u2%Vrel(i1,i2) - t(2)*u3%Vrel(i1,i2) ) * scaleFactor + u_out%Vrel(i1,i2) = u1%Vrel(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%AoANoise) .AND. ALLOCATED(u1%AoANoise)) THEN + DO i2 = LBOUND(u_out%AoANoise,2),UBOUND(u_out%AoANoise,2) + DO i1 = LBOUND(u_out%AoANoise,1),UBOUND(u_out%AoANoise,1) + b = (t(3)**2*(u1%AoANoise(i1,i2) - u2%AoANoise(i1,i2)) + t(2)**2*(-u1%AoANoise(i1,i2) + u3%AoANoise(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%AoANoise(i1,i2) + t(3)*u2%AoANoise(i1,i2) - t(2)*u3%AoANoise(i1,i2) ) * scaleFactor + u_out%AoANoise(i1,i2) = u1%AoANoise(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Inflow) .AND. ALLOCATED(u1%Inflow)) THEN + DO i3 = LBOUND(u_out%Inflow,3),UBOUND(u_out%Inflow,3) + DO i2 = LBOUND(u_out%Inflow,2),UBOUND(u_out%Inflow,2) + DO i1 = LBOUND(u_out%Inflow,1),UBOUND(u_out%Inflow,1) + b = (t(3)**2*(u1%Inflow(i1,i2,i3) - u2%Inflow(i1,i2,i3)) + t(2)**2*(-u1%Inflow(i1,i2,i3) + u3%Inflow(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*u1%Inflow(i1,i2,i3) + t(3)*u2%Inflow(i1,i2,i3) - t(2)*u3%Inflow(i1,i2,i3) ) * scaleFactor + u_out%Inflow(i1,i2,i3) = u1%Inflow(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated + END SUBROUTINE AA_Input_ExtrapInterp2 + + + SUBROUTINE AA_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AA_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(AA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL AA_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AA_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AA_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AA_Output_ExtrapInterp + + + SUBROUTINE AA_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(AA_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(AA_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(AA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%SumSpecNoise) .AND. ALLOCATED(y1%SumSpecNoise)) THEN + DO i3 = LBOUND(y_out%SumSpecNoise,3),UBOUND(y_out%SumSpecNoise,3) + DO i2 = LBOUND(y_out%SumSpecNoise,2),UBOUND(y_out%SumSpecNoise,2) + DO i1 = LBOUND(y_out%SumSpecNoise,1),UBOUND(y_out%SumSpecNoise,1) + b = -(y1%SumSpecNoise(i1,i2,i3) - y2%SumSpecNoise(i1,i2,i3)) + y_out%SumSpecNoise(i1,i2,i3) = y1%SumSpecNoise(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%SumSpecNoiseSep) .AND. ALLOCATED(y1%SumSpecNoiseSep)) THEN + DO i3 = LBOUND(y_out%SumSpecNoiseSep,3),UBOUND(y_out%SumSpecNoiseSep,3) + DO i2 = LBOUND(y_out%SumSpecNoiseSep,2),UBOUND(y_out%SumSpecNoiseSep,2) + DO i1 = LBOUND(y_out%SumSpecNoiseSep,1),UBOUND(y_out%SumSpecNoiseSep,1) + b = -(y1%SumSpecNoiseSep(i1,i2,i3) - y2%SumSpecNoiseSep(i1,i2,i3)) + y_out%SumSpecNoiseSep(i1,i2,i3) = y1%SumSpecNoiseSep(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OASPL) .AND. ALLOCATED(y1%OASPL)) THEN + DO i3 = LBOUND(y_out%OASPL,3),UBOUND(y_out%OASPL,3) + DO i2 = LBOUND(y_out%OASPL,2),UBOUND(y_out%OASPL,2) + DO i1 = LBOUND(y_out%OASPL,1),UBOUND(y_out%OASPL,1) + b = -(y1%OASPL(i1,i2,i3) - y2%OASPL(i1,i2,i3)) + y_out%OASPL(i1,i2,i3) = y1%OASPL(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OASPL_Mech) .AND. ALLOCATED(y1%OASPL_Mech)) THEN + DO i4 = LBOUND(y_out%OASPL_Mech,4),UBOUND(y_out%OASPL_Mech,4) + DO i3 = LBOUND(y_out%OASPL_Mech,3),UBOUND(y_out%OASPL_Mech,3) + DO i2 = LBOUND(y_out%OASPL_Mech,2),UBOUND(y_out%OASPL_Mech,2) + DO i1 = LBOUND(y_out%OASPL_Mech,1),UBOUND(y_out%OASPL_Mech,1) + b = -(y1%OASPL_Mech(i1,i2,i3,i4) - y2%OASPL_Mech(i1,i2,i3,i4)) + y_out%OASPL_Mech(i1,i2,i3,i4) = y1%OASPL_Mech(i1,i2,i3,i4) + b * ScaleFactor + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%DirectiviOutput) .AND. ALLOCATED(y1%DirectiviOutput)) THEN + DO i1 = LBOUND(y_out%DirectiviOutput,1),UBOUND(y_out%DirectiviOutput,1) + b = -(y1%DirectiviOutput(i1) - y2%DirectiviOutput(i1)) + y_out%DirectiviOutput(i1) = y1%DirectiviOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OutLECoords) .AND. ALLOCATED(y1%OutLECoords)) THEN + DO i4 = LBOUND(y_out%OutLECoords,4),UBOUND(y_out%OutLECoords,4) + DO i3 = LBOUND(y_out%OutLECoords,3),UBOUND(y_out%OutLECoords,3) + DO i2 = LBOUND(y_out%OutLECoords,2),UBOUND(y_out%OutLECoords,2) + DO i1 = LBOUND(y_out%OutLECoords,1),UBOUND(y_out%OutLECoords,1) + b = -(y1%OutLECoords(i1,i2,i3,i4) - y2%OutLECoords(i1,i2,i3,i4)) + y_out%OutLECoords(i1,i2,i3,i4) = y1%OutLECoords(i1,i2,i3,i4) + b * ScaleFactor + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%PtotalFreq) .AND. ALLOCATED(y1%PtotalFreq)) THEN + DO i2 = LBOUND(y_out%PtotalFreq,2),UBOUND(y_out%PtotalFreq,2) + DO i1 = LBOUND(y_out%PtotalFreq,1),UBOUND(y_out%PtotalFreq,1) + b = -(y1%PtotalFreq(i1,i2) - y2%PtotalFreq(i1,i2)) + y_out%PtotalFreq(i1,i2) = y1%PtotalFreq(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputForPE) .AND. ALLOCATED(y1%WriteOutputForPE)) THEN + DO i1 = LBOUND(y_out%WriteOutputForPE,1),UBOUND(y_out%WriteOutputForPE,1) + b = -(y1%WriteOutputForPE(i1) - y2%WriteOutputForPE(i1)) + y_out%WriteOutputForPE(i1) = y1%WriteOutputForPE(i1) + b * ScaleFactor + 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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputSep) .AND. ALLOCATED(y1%WriteOutputSep)) THEN + DO i1 = LBOUND(y_out%WriteOutputSep,1),UBOUND(y_out%WriteOutputSep,1) + b = -(y1%WriteOutputSep(i1) - y2%WriteOutputSep(i1)) + y_out%WriteOutputSep(i1) = y1%WriteOutputSep(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputNode) .AND. ALLOCATED(y1%WriteOutputNode)) THEN + DO i1 = LBOUND(y_out%WriteOutputNode,1),UBOUND(y_out%WriteOutputNode,1) + b = -(y1%WriteOutputNode(i1) - y2%WriteOutputNode(i1)) + y_out%WriteOutputNode(i1) = y1%WriteOutputNode(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE AA_Output_ExtrapInterp1 + + + SUBROUTINE AA_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(AA_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(AA_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(AA_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(AA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AA_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%SumSpecNoise) .AND. ALLOCATED(y1%SumSpecNoise)) THEN + DO i3 = LBOUND(y_out%SumSpecNoise,3),UBOUND(y_out%SumSpecNoise,3) + DO i2 = LBOUND(y_out%SumSpecNoise,2),UBOUND(y_out%SumSpecNoise,2) + DO i1 = LBOUND(y_out%SumSpecNoise,1),UBOUND(y_out%SumSpecNoise,1) + b = (t(3)**2*(y1%SumSpecNoise(i1,i2,i3) - y2%SumSpecNoise(i1,i2,i3)) + t(2)**2*(-y1%SumSpecNoise(i1,i2,i3) + y3%SumSpecNoise(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%SumSpecNoise(i1,i2,i3) + t(3)*y2%SumSpecNoise(i1,i2,i3) - t(2)*y3%SumSpecNoise(i1,i2,i3) ) * scaleFactor + y_out%SumSpecNoise(i1,i2,i3) = y1%SumSpecNoise(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%SumSpecNoiseSep) .AND. ALLOCATED(y1%SumSpecNoiseSep)) THEN + DO i3 = LBOUND(y_out%SumSpecNoiseSep,3),UBOUND(y_out%SumSpecNoiseSep,3) + DO i2 = LBOUND(y_out%SumSpecNoiseSep,2),UBOUND(y_out%SumSpecNoiseSep,2) + DO i1 = LBOUND(y_out%SumSpecNoiseSep,1),UBOUND(y_out%SumSpecNoiseSep,1) + b = (t(3)**2*(y1%SumSpecNoiseSep(i1,i2,i3) - y2%SumSpecNoiseSep(i1,i2,i3)) + t(2)**2*(-y1%SumSpecNoiseSep(i1,i2,i3) + y3%SumSpecNoiseSep(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%SumSpecNoiseSep(i1,i2,i3) + t(3)*y2%SumSpecNoiseSep(i1,i2,i3) - t(2)*y3%SumSpecNoiseSep(i1,i2,i3) ) * scaleFactor + y_out%SumSpecNoiseSep(i1,i2,i3) = y1%SumSpecNoiseSep(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OASPL) .AND. ALLOCATED(y1%OASPL)) THEN + DO i3 = LBOUND(y_out%OASPL,3),UBOUND(y_out%OASPL,3) + DO i2 = LBOUND(y_out%OASPL,2),UBOUND(y_out%OASPL,2) + DO i1 = LBOUND(y_out%OASPL,1),UBOUND(y_out%OASPL,1) + b = (t(3)**2*(y1%OASPL(i1,i2,i3) - y2%OASPL(i1,i2,i3)) + t(2)**2*(-y1%OASPL(i1,i2,i3) + y3%OASPL(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%OASPL(i1,i2,i3) + t(3)*y2%OASPL(i1,i2,i3) - t(2)*y3%OASPL(i1,i2,i3) ) * scaleFactor + y_out%OASPL(i1,i2,i3) = y1%OASPL(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OASPL_Mech) .AND. ALLOCATED(y1%OASPL_Mech)) THEN + DO i4 = LBOUND(y_out%OASPL_Mech,4),UBOUND(y_out%OASPL_Mech,4) + DO i3 = LBOUND(y_out%OASPL_Mech,3),UBOUND(y_out%OASPL_Mech,3) + DO i2 = LBOUND(y_out%OASPL_Mech,2),UBOUND(y_out%OASPL_Mech,2) + DO i1 = LBOUND(y_out%OASPL_Mech,1),UBOUND(y_out%OASPL_Mech,1) + b = (t(3)**2*(y1%OASPL_Mech(i1,i2,i3,i4) - y2%OASPL_Mech(i1,i2,i3,i4)) + t(2)**2*(-y1%OASPL_Mech(i1,i2,i3,i4) + y3%OASPL_Mech(i1,i2,i3,i4)))* scaleFactor + c = ( (t(2)-t(3))*y1%OASPL_Mech(i1,i2,i3,i4) + t(3)*y2%OASPL_Mech(i1,i2,i3,i4) - t(2)*y3%OASPL_Mech(i1,i2,i3,i4) ) * scaleFactor + y_out%OASPL_Mech(i1,i2,i3,i4) = y1%OASPL_Mech(i1,i2,i3,i4) + b + c * t_out + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%DirectiviOutput) .AND. ALLOCATED(y1%DirectiviOutput)) THEN + DO i1 = LBOUND(y_out%DirectiviOutput,1),UBOUND(y_out%DirectiviOutput,1) + b = (t(3)**2*(y1%DirectiviOutput(i1) - y2%DirectiviOutput(i1)) + t(2)**2*(-y1%DirectiviOutput(i1) + y3%DirectiviOutput(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%DirectiviOutput(i1) + t(3)*y2%DirectiviOutput(i1) - t(2)*y3%DirectiviOutput(i1) ) * scaleFactor + y_out%DirectiviOutput(i1) = y1%DirectiviOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%OutLECoords) .AND. ALLOCATED(y1%OutLECoords)) THEN + DO i4 = LBOUND(y_out%OutLECoords,4),UBOUND(y_out%OutLECoords,4) + DO i3 = LBOUND(y_out%OutLECoords,3),UBOUND(y_out%OutLECoords,3) + DO i2 = LBOUND(y_out%OutLECoords,2),UBOUND(y_out%OutLECoords,2) + DO i1 = LBOUND(y_out%OutLECoords,1),UBOUND(y_out%OutLECoords,1) + b = (t(3)**2*(y1%OutLECoords(i1,i2,i3,i4) - y2%OutLECoords(i1,i2,i3,i4)) + t(2)**2*(-y1%OutLECoords(i1,i2,i3,i4) + y3%OutLECoords(i1,i2,i3,i4)))* scaleFactor + c = ( (t(2)-t(3))*y1%OutLECoords(i1,i2,i3,i4) + t(3)*y2%OutLECoords(i1,i2,i3,i4) - t(2)*y3%OutLECoords(i1,i2,i3,i4) ) * scaleFactor + y_out%OutLECoords(i1,i2,i3,i4) = y1%OutLECoords(i1,i2,i3,i4) + b + c * t_out + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%PtotalFreq) .AND. ALLOCATED(y1%PtotalFreq)) THEN + DO i2 = LBOUND(y_out%PtotalFreq,2),UBOUND(y_out%PtotalFreq,2) + DO i1 = LBOUND(y_out%PtotalFreq,1),UBOUND(y_out%PtotalFreq,1) + b = (t(3)**2*(y1%PtotalFreq(i1,i2) - y2%PtotalFreq(i1,i2)) + t(2)**2*(-y1%PtotalFreq(i1,i2) + y3%PtotalFreq(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%PtotalFreq(i1,i2) + t(3)*y2%PtotalFreq(i1,i2) - t(2)*y3%PtotalFreq(i1,i2) ) * scaleFactor + y_out%PtotalFreq(i1,i2) = y1%PtotalFreq(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputForPE) .AND. ALLOCATED(y1%WriteOutputForPE)) THEN + DO i1 = LBOUND(y_out%WriteOutputForPE,1),UBOUND(y_out%WriteOutputForPE,1) + b = (t(3)**2*(y1%WriteOutputForPE(i1) - y2%WriteOutputForPE(i1)) + t(2)**2*(-y1%WriteOutputForPE(i1) + y3%WriteOutputForPE(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%WriteOutputForPE(i1) + t(3)*y2%WriteOutputForPE(i1) - t(2)*y3%WriteOutputForPE(i1) ) * scaleFactor + y_out%WriteOutputForPE(i1) = y1%WriteOutputForPE(i1) + b + c * t_out + 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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputSep) .AND. ALLOCATED(y1%WriteOutputSep)) THEN + DO i1 = LBOUND(y_out%WriteOutputSep,1),UBOUND(y_out%WriteOutputSep,1) + b = (t(3)**2*(y1%WriteOutputSep(i1) - y2%WriteOutputSep(i1)) + t(2)**2*(-y1%WriteOutputSep(i1) + y3%WriteOutputSep(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%WriteOutputSep(i1) + t(3)*y2%WriteOutputSep(i1) - t(2)*y3%WriteOutputSep(i1) ) * scaleFactor + y_out%WriteOutputSep(i1) = y1%WriteOutputSep(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutputNode) .AND. ALLOCATED(y1%WriteOutputNode)) THEN + DO i1 = LBOUND(y_out%WriteOutputNode,1),UBOUND(y_out%WriteOutputNode,1) + b = (t(3)**2*(y1%WriteOutputNode(i1) - y2%WriteOutputNode(i1)) + t(2)**2*(-y1%WriteOutputNode(i1) + y3%WriteOutputNode(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%WriteOutputNode(i1) + t(3)*y2%WriteOutputNode(i1) - t(2)*y3%WriteOutputNode(i1) ) * scaleFactor + y_out%WriteOutputNode(i1) = y1%WriteOutputNode(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE AA_Output_ExtrapInterp2 + +END MODULE AeroAcoustics_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn.f90 new file mode 100644 index 000000000..e293053fc --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn.f90 @@ -0,0 +1,5112 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2019 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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. +! +!********************************************************************************************************************************** +!> AeroDyn is a time-domain aerodynamics module for horizontal-axis wind turbines. +module AeroDyn + + use NWTC_Library + use AeroDyn_Types + use AeroDyn_IO + use BEMT + use AirfoilInfo + use NWTC_LAPACK + use AeroAcoustics + use UnsteadyAero + use FVW + use FVW_Subs, only: FVW_AeroOuts + + implicit none + + private + + + ! ..... Public Subroutines ................................................................................................... + + public :: AD_Init ! Initialization routine + public :: AD_ReInit ! Routine to reinitialize driver (re-initializes the states) + public :: AD_End ! Ending routine (includes clean up) + public :: AD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + public :: AD_CalcOutput ! Routine for computing outputs + public :: AD_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + + + PUBLIC :: AD_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 :: AD_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 :: AD_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 :: AD_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 :: AD_GetOP !< Routine to pack the operating point values (for linearization) into arrays + +contains +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets the initialization output data structure, which contains data to be returned to the calling program (e.g., +!! FAST or AeroDyn_Driver) +subroutine AD_SetInitOut(p, InputFileData, InitOut, errStat, errMsg) + + type(AD_InitOutputType), intent( out) :: InitOut ! output data + type(AD_InputFile), intent(in ) :: InputFileData ! input file data (for setting airfoil shape outputs) + type(AD_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 + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'AD_SetInitOut' + + + + integer(IntKi) :: i, j, k, f + integer(IntKi) :: NumCoords + + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + + InitOut%AirDens = p%AirDens + + call AllocAry( InitOut%WriteOutputHdr, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputHdr', errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call AllocAry( InitOut%WriteOutputUnt, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputUnt', errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) return + + + do i=1,p%NumOuts + InitOut%WriteOutputHdr(i) = p%OutParam(i)%Name + InitOut%WriteOutputUnt(i) = p%OutParam(i)%Units + end do + + + ! Set the info in WriteOutputHdr and WriteOutputUnt + CALL AllBldNdOuts_InitOut( InitOut, p, InputFileData, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + InitOut%Ver = AD_Ver + +! set visualization data: + ! this check is overly restrictive, but it would be a lot of work to ensure that only the *used* airfoil + ! tables have the same number of coordinates. + if ( allocated(p%AFI) ) then + + if ( p%AFI(1)%NumCoords > 0 ) then + NumCoords = p%AFI(1)%NumCoords + do i=2,size(p%AFI) + if (p%AFI(i)%NumCoords /= NumCoords) then + call SetErrStat( ErrID_Info, 'Airfoil files do not contain the same number of x-y coordinates.', ErrStat, ErrMsg, RoutineName ) + NumCoords = -1 + exit + end if + end do + + if (NumCoords > 0) then + if (NumCoords < 3) then + call SetErrStat( ErrID_Info, 'Airfoil files with NumCoords > 0 must contain at least 2 coordinates.', ErrStat, ErrMsg, RoutineName ) + return + end if + + allocate( InitOut%BladeShape( p%numBlades ), STAT=ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Info, 'Error allocationg InitOut%AD_BladeShape', ErrStat, ErrMsg, RoutineName ) + return + end if + + do k=1,p%numBlades + call allocAry( InitOut%BladeShape(k)%AirfoilCoords, 2, NumCoords-1, InputFileData%BladeProps(k)%NumBlNds, 'AirfoilCoords', ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + do j=1,InputFileData%BladeProps(k)%NumBlNds + f = InputFileData%BladeProps(k)%BlAFID(j) + + do i=1,NumCoords-1 + InitOut%BladeShape(k)%AirfoilCoords(1,i,j) = InputFileData%BladeProps(k)%BlChord(j)*( p%AFI(f)%Y_Coord(i+1) - p%AFI(f)%Y_Coord(1) ) + InitOut%BladeShape(k)%AirfoilCoords(2,i,j) = InputFileData%BladeProps(k)%BlChord(j)*( p%AFI(f)%X_Coord(i+1) - p%AFI(f)%X_Coord(1) ) + end do + end do + + end do + + end if + end if + + end if + + + ! set blade properties data ! bjj: I would probably do a move_alloc() at the end of the init routine rather than make a copy like this.... + ALLOCATE(InitOut%BladeProps(p%numBlades), STAT = ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for BladeProps.", ErrStat, ErrMsg, RoutineName) + RETURN + END IF + do k=1,p%numBlades + ! allocate space and copy blade data: + CALL AD_CopyBladePropsType(InputFileData%BladeProps(k), InitOut%BladeProps(k), MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do + + !Tower data + IF ( p%NumTwrNds > 0 ) THEN + ALLOCATE(InitOut%TwrElev(p%NumTwrNds), STAT = ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for TwrElev.", ErrStat, ErrMsg, RoutineName) + RETURN + END IF + InitOut%TwrElev(:) = InputFileData%TwrElev(:) + + ALLOCATE(InitOut%TwrDiam(p%NumTwrNds), STAT = ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for TwrDiam.", ErrStat, ErrMsg, RoutineName) + RETURN + END IF + InitOut%TwrDiam(:) = p%TwrDiam(:) + END IF + +end subroutine AD_SetInitOut + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + type(AD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(AD_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(AD_ParameterType), intent( out) :: p !< Parameters + type(AD_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(AD_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(AD_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(AD_OtherStateType), intent( out) :: OtherState !< Initial other states + type(AD_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(AD_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + real(DbKi), intent(inout) :: interval !< Coupling interval in seconds: the rate that + !! (1) AD_UpdateStates() is called in loose coupling & + !! (2) AD_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(AD_InitOutputType), intent( out) :: InitOut !< Output for initialization routine + 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 ! loop counter + + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + + type(FileInfoType) :: FileInfo_In !< The derived type for holding the full input file for parsing -- we may pass this in the future + type(AD_InputFile) :: InputFileData ! Data stored in the module's input file after parsing + character(1024) :: PriPath !< Primary path + character(1024) :: EchoFileName + integer(IntKi) :: UnEcho ! Unit number for the echo file + + character(*), parameter :: RoutineName = 'AD_Init' + + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + UnEcho = -1 + + ! Initialize the NWTC Subroutine Library + + call NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + + call DispNVD( AD_Ver ) + + + ! set a few parameters needed while reading the input file + call ValidateNumBlades( InitInp%NumBlades, ErrStat2, ErrMsg2 ) + if (Failed()) return; + p%NumBlades = InitInp%NumBlades + p%RootName = TRIM(InitInp%RootName)//'.AD' + + CALL GetPath( InitInp%InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + ! ----------------------------------------------------------------- + ! Read the primary AeroDyn input file, or copy from passed input + if (InitInp%UsePrimaryInputFile) then + ! Read the entire input file, minus any comment lines, into the FileInfo_In + ! data structure in memory for further processing. + call ProcessComFile( InitInp%InputFile, FileInfo_In, ErrStat2, ErrMsg2 ) + else + call NWTC_Library_CopyFileInfoType( InitInp%PassedPrimaryInputData, FileInfo_In, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + endif + if (Failed()) return; + + + ! For diagnostic purposes, the following can be used to display the contents + ! of the FileInfo_In data structure. + ! call Print_FileInfo_Struct( CU, FileInfo_In ) ! CU is the screen -- different number on different systems. + + ! Parse the FileInfo_In structure of data from the inputfile into the InitInp%InputFile structure + CALL ParsePrimaryFileInfo( PriPath, InitInp%InputFile, p%RootName, p%NumBlades, interval, FileInfo_In, InputFileData, UnEcho, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + + ! ----------------------------------------------------------------- + ! Read the AeroDyn blade files, or copy from passed input +!FIXME: add handling for passing of blade files and other types of files. + call ReadInputFiles( InitInp%InputFile, InputFileData, interval, p%RootName, p%NumBlades, UnEcho, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + + ! Validate the inputs + call ValidateInputData( InitInp, InputFileData, p%NumBlades, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + !............................................................................................ + ! Define parameters + !............................................................................................ + + ! Initialize AFI module (read Airfoil tables) + call Init_AFIparams( InputFileData, p%AFI, UnEcho, p%NumBlades, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + + ! set the rest of the parameters + call SetParameters( InitInp, InputFileData, p, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + !............................................................................................ + ! Define and initialize inputs here + !............................................................................................ + + call Init_u( u, p, InputFileData, InitInp, errStat2, errMsg2 ) + if (Failed()) return; + + + !............................................................................................ + ! Initialize the BEMT module (also sets other variables for sub module) + !............................................................................................ + + ! initialize BEMT after setting parameters and inputs because we are going to use the already- + ! calculated node positions from the input meshes + + if (p%WakeMod /= WakeMod_FVW) then + call Init_BEMTmodule( InputFileData, u, m%BEMT_u(1), p, x%BEMT, xd%BEMT, z%BEMT, & + OtherState%BEMT, m%BEMT_y, m%BEMT, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + call BEMT_CopyInput( m%BEMT_u(1), m%BEMT_u(2), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !............................................................................................ + ! Initialize the AeroAcoustics Module if the CompAA flag is set + !............................................................................................ + if (p%CompAA) then + call Init_AAmodule( InitInp, InputFileData, u, m%AA_u, p, x%AA, xd%AA, z%AA, OtherState%AA, m%AA_y, m%AA, ErrStat2, ErrMsg2 ) + if (Failed()) return; + end if + endif + + !------------------------------------------------------------------------------------------------- + ! Initialize FVW module if it is used + !------------------------------------------------------------------------------------------------- + ! Unfortunately we do not know the interpolation order used by OpenFAST glue code at this point, + ! so we can't size things exactly. This means that we either must size too big here, or we must + ! resize in the FVW code at the first CalcOutput call. This is a bit problematic for efficiency + ! but not a complete deal-breaker. + if (p%WakeMod == WakeMod_FVW) then + if (.not. allocated(m%FVW_u)) Allocate(m%FVW_u(3)) !size(u))) + call Init_FVWmodule( InputFileData, u, m%FVW_u(1), p, x%FVW, xd%FVW, z%FVW, & + OtherState%FVW, m%FVW_y, m%FVW, ErrStat2, ErrMsg2 ) + if (Failed()) return; + ! populate the rest of the FVW_u so that extrap-interp will work + do i=2,3 !size(u) + call FVW_CopyInput( m%FVW_u(1), m%FVW_u(i), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + if (Failed()) return; + enddo + endif + + + !............................................................................................ + ! Define outputs here + !............................................................................................ + call Init_y(y, u, p, errStat2, errMsg2) ! do this after input meshes have been initialized + if (Failed()) return; + + + !............................................................................................ + ! Initialize states and misc vars + !............................................................................................ + + ! many states are in the BEMT module, which were initialized in BEMT_Init() + + call Init_MiscVars(m, p, u, y, errStat2, errMsg2) + if (Failed()) return; + + !............................................................................................ + ! Initialize other states + !............................................................................................ + ! The wake from FVW is stored in other states. This may not be the best place to put it! + call Init_OtherStates(m, p, OtherState, errStat2, errMsg2) + if (Failed()) return; + + !............................................................................................ + ! Define initialization output here + !............................................................................................ + call AD_SetInitOut(p, InputFileData, InitOut, errStat2, errMsg2) + if (Failed()) return; + + ! after setting InitOut variables, we really don't need the airfoil coordinates taking up + ! space in AeroDyn + if ( allocated(p%AFI) ) then + do i=1,size(p%AFI) + if (allocated(p%AFI(i)%X_Coord)) deallocate( p%AFI(i)%X_Coord) + if (allocated(p%AFI(i)%Y_Coord)) deallocate( p%AFI(i)%Y_Coord) + end do + end if + + !............................................................................................ + ! Initialize Jacobian: + !............................................................................................ + if (InitInp%Linearize) then + call Init_Jacobian(InputFileData, p, u, y, m, InitOut, ErrStat2, ErrMsg2) + if (Failed()) return; + end if + + !............................................................................................ + ! Print the summary file if requested: + !............................................................................................ + if (InputFileData%SumPrint) then + call AD_PrintSum( InputFileData, p, u, y, ErrStat2, ErrMsg2 ) + if (Failed()) return; + end if + + !............................................................................................ + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + !............................................................................................ + + Interval = p%DT + + + call Cleanup() + +contains + logical function Failed() + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup() + end function Failed + subroutine Cleanup() + CALL AD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + end subroutine Cleanup + +end subroutine AD_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reinitializes BEMT and UA, assuming that we will start the simulation over again, with only the inputs being different. +!! This allows us to bypass reading input files and allocating arrays because p is already set. +subroutine AD_ReInit(p, x, xd, z, OtherState, m, Interval, ErrStat, ErrMsg ) + + type(AD_ParameterType), intent(in ) :: p !< Parameters + type(AD_ContinuousStateType), intent(inout) :: x !< Initial continuous states + type(AD_DiscreteStateType), intent(inout) :: xd !< Initial discrete states + type(AD_ConstraintStateType), intent(inout) :: z !< Initial guess of the constraint states + type(AD_OtherStateType), intent(inout) :: OtherState !< Initial other states + type(AD_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + real(DbKi), intent(in ) :: interval !< Coupling interval in seconds: the rate that + !! (1) AD_UpdateStates() is called in loose coupling & + !! (2) AD_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = 'AD_ReInit' + + + ErrStat = ErrID_None + ErrMsg = '' + + if ( .not. EqualRealNos(p%DT, interval) ) then + call SetErrStat( ErrID_Fatal, 'When AD is reinitialized, DT must not change.', ErrStat, ErrMsg, RoutineName ) + return + ! we could get around this by figuring out what needs to change when we modify the dt parameter... probably just some unused-parameters + ! and the UA filter + end if + + if (p%WakeMod /= WakeMod_FVW) & + call BEMT_ReInit(p%BEMT,x%BEMT,xd%BEMT,z%BEMT,OtherState%BEMT,m%BEMT,p%AFI,ErrStat,ErrMsg) + +end subroutine AD_ReInit +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes (allocates) the misc variables for use during the simulation. +subroutine Init_MiscVars(m, p, u, y, errStat, errMsg) + type(AD_MiscVarType), intent(inout) :: m !< misc/optimization data (not defined in submodules) + type(AD_ParameterType), intent(in ) :: p !< Parameters + type(AD_InputType), intent(inout) :: u !< input for HubMotion mesh (create sibling mesh here) + type(AD_OutputType), intent(in ) :: y !< output (create mapping between output and otherstate mesh here) + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + integer(intKi) :: k + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_MiscVars' + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + call AllocAry( m%DisturbedInflow, 3_IntKi, p%NumBlNds, p%numBlades, 'OtherState%DisturbedInflow', ErrStat2, ErrMsg2 ) ! must be same size as u%InflowOnBlade + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%WithoutSweepPitchTwist, 3_IntKi, 3_IntKi, p%NumBlNds, p%numBlades, 'OtherState%WithoutSweepPitchTwist', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call allocAry( m%SigmaCavit, p%NumBlNds, p%numBlades, 'm%SigmaCavit', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( m%SigmaCavitCrit, p%NumBlNds, p%numBlades, 'm%SigmaCavitCrit', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( m%CavitWarnSet, p%NumBlNds, p%numBlades, 'm%CavitWarnSet', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + m%SigmaCavit = 0.0_ReKi !Init to zero for output files in case a cavit check isnt done but output is requested + m%SigmaCavitCrit = 0.0_ReKi + m%CavitWarnSet = .false. + ! arrays for output + allocate( m%AllOuts(0:MaxOutPts), STAT=ErrStat2 ) ! allocate starting at zero to account for invalid output channels + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, "Error allocating AllOuts.", errStat, errMsg, RoutineName ) + return + end if + m%AllOuts = 0.0_ReKi + + ! save these tower calculations for output: + call AllocAry( m%W_Twr, p%NumTwrNds, 'm%W_Twr', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%X_Twr, p%NumTwrNds, 'm%X_Twr', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%Y_Twr, p%NumTwrNds, 'm%Y_Twr', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + ! save blade calculations for output: +if (p%TwrPotent /= TwrPotent_none .or. p%TwrShadow /= TwrShadow_none) then + call AllocAry( m%TwrClrnc, p%NumBlNds, p%NumBlades, 'm%TwrClrnc', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) +end if + call AllocAry( m%Curve, p%NumBlNds, p%NumBlades, 'm%Curve', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%X, p%NumBlNds, p%NumBlades, 'm%X', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%Y, p%NumBlNds, p%NumBlades, 'm%Y', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( m%M, p%NumBlNds, p%NumBlades, 'm%M', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + ! mesh mapping data for integrating load over entire rotor: + allocate( m%B_L_2_H_P(p%NumBlades), Stat = ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, "Error allocating B_L_2_H_P mapping structure.", errStat, errMsg, RoutineName ) + return + end if + + call MeshCopy ( SrcMesh = u%HubMotion & + , DestMesh = m%HubLoad & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , force = .TRUE. & + , moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) RETURN + + do k=1,p%NumBlades + CALL MeshMapCreate( y%BladeLoad(k), m%HubLoad, m%B_L_2_H_P(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':B_L_2_H_P('//TRIM(Num2LStr(K))//')' ) + end do + + if (ErrStat >= AbortErrLev) RETURN + + ! + if (p%NumTwrNds > 0) then + m%W_Twr = 0.0_ReKi + m%X_Twr = 0.0_ReKi + m%Y_Twr = 0.0_ReKi + end if + + + +end subroutine Init_MiscVars +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes (allocates) the misc variables for use during the simulation. +subroutine Init_OtherStates(m, p, OtherState, errStat, errMsg) + type(AD_MiscVarType), intent(in ) :: m !< misc/optimization data (not defined in submodules) + type(AD_ParameterType), intent(in ) :: p !< Parameters + type(AD_OtherStateType), intent(inout) :: OtherState !< Discrete states + 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 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_OtherStates' + + errStat = ErrID_None + errMsg = "" + ! store Wake positions in otherstates. This may not be the best location + if (allocated(m%FVW%r_wind)) then + call AllocAry( OtherState%WakeLocationPoints, 3_IntKi, size(m%FVW%r_wind,DIM=2), ' OtherState%WakeLocationPoints', ErrStat2, ErrMsg2 ) ! must be same size as m%r_wind from FVW + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + OtherState%WakeLocationPoints = m%FVW%r_wind + endif +end subroutine Init_OtherStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes AeroDyn meshes and output array variables for use during the simulation. +subroutine Init_y(y, u, p, errStat, errMsg) + type(AD_OutputType), intent( out) :: y !< Module outputs + type(AD_InputType), intent(inout) :: u !< Module inputs -- intent(out) because of mesh sibling copy + type(AD_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 + integer(intKi) :: k ! loop counter for blades + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_y' + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + + if (p%TwrAero) then + + call MeshCopy ( SrcMesh = u%TowerMotion & + , DestMesh = y%TowerLoad & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , force = .TRUE. & + , moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) RETURN + + !y%TowerLoad%force = 0.0_ReKi ! shouldn't have to initialize this + !y%TowerLoad%moment= 0.0_ReKi ! shouldn't have to initialize this + else + y%TowerLoad%nnodes = 0 + end if + + + allocate( y%BladeLoad(p%numBlades), stat=ErrStat2 ) + if (errStat2 /= 0) then + call SetErrStat( ErrID_Fatal, 'Error allocating y%BladeLoad.', ErrStat, ErrMsg, RoutineName ) + return + end if + + + do k = 1, p%numBlades + + call MeshCopy ( SrcMesh = u%BladeMotion(k) & + , DestMesh = y%BladeLoad(k) & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , force = .TRUE. & + , moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + end do + + call AllocAry( y%WriteOutput, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutput', errStat2, errMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) RETURN + + + +end subroutine Init_y +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes AeroDyn meshes and input array variables for use during the simulation. +subroutine Init_u( u, p, InputFileData, InitInp, errStat, errMsg ) +!.................................................................................................................................. + + type(AD_InputType), intent( out) :: u !< Input data + type(AD_ParameterType), intent(in ) :: p !< Parameters + type(AD_InputFile), intent(in ) :: InputFileData !< Data stored in the module's input file + type(AD_InitInputType), intent(in ) :: InitInp !< Input data for AD initialization routine + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + real(reKi) :: position(3) ! node reference position + real(reKi) :: positionL(3) ! node local position + real(R8Ki) :: theta(3) ! Euler angles + real(R8Ki) :: orientation(3,3) ! node reference orientation + real(R8Ki) :: orientationL(3,3) ! node local orientation + + integer(intKi) :: j ! counter for nodes + integer(intKi) :: k ! counter for blades + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_u' + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Arrays for InflowWind inputs: + + call AllocAry( u%InflowOnBlade, 3_IntKi, p%NumBlNds, p%numBlades, 'u%InflowOnBlade', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( u%InflowOnTower, 3_IntKi, p%NumTwrNds, 'u%InflowOnTower', ErrStat2, ErrMsg2 ) ! could be size zero + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call AllocAry( u%UserProp, p%NumBlNds, p%numBlades, 'u%UserProp', ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + u%InflowOnBlade = 0.0_ReKi + u%UserProp = 0.0_ReKi + + ! Meshes for motion inputs (ElastoDyn and/or BeamDyn) + !................ + ! tower + !................ + if (p%NumTwrNds > 0) then + + u%InflowOnTower = 0.0_ReKi + + call MeshCreate ( BlankMesh = u%TowerMotion & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NumTwrNds & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + ! set node initial position/orientation + position = 0.0_ReKi + do j=1,p%NumTwrNds + position(3) = InputFileData%TwrElev(j) + + call MeshPositionNode(u%TowerMotion, j, position, errStat2, errMsg2) ! orientation is identity by default + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + ! create line2 elements + do j=1,p%NumTwrNds-1 + call MeshConstructElement( u%TowerMotion, ELEMENT_LINE2, errStat2, errMsg2, p1=j, p2=j+1 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + call MeshCommit(u%TowerMotion, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + + u%TowerMotion%Orientation = u%TowerMotion%RefOrientation + u%TowerMotion%TranslationDisp = 0.0_R8Ki + u%TowerMotion%TranslationVel = 0.0_ReKi + + end if ! we compute tower loads + + !................ + ! hub + !................ + + call MeshCreate ( BlankMesh = u%HubMotion & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,RotationVel = .true. & + ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + call MeshPositionNode(u%HubMotion, 1, InitInp%HubPosition, errStat2, errMsg2, InitInp%HubOrientation) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshConstructElement( u%HubMotion, ELEMENT_POINT, errStat2, errMsg2, p1=1 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshCommit(u%HubMotion, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + + u%HubMotion%Orientation = u%HubMotion%RefOrientation + u%HubMotion%TranslationDisp = 0.0_R8Ki + u%HubMotion%RotationVel = 0.0_ReKi + + + !................ + ! blade roots + !................ + + allocate( u%BladeRootMotion(p%NumBlades), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, 'Error allocating u%BladeRootMotion array.', ErrStat, ErrMsg, RoutineName ) + return + end if + + do k=1,p%NumBlades + call MeshCreate ( BlankMesh = u%BladeRootMotion(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orientation = .true. & + ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + call MeshPositionNode(u%BladeRootMotion(k), 1, InitInp%BladeRootPosition(:,k), errStat2, errMsg2, InitInp%BladeRootOrientation(:,:,k)) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshConstructElement( u%BladeRootMotion(k), ELEMENT_POINT, errStat2, errMsg2, p1=1 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshCommit(u%BladeRootMotion(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + + u%BladeRootMotion(k)%Orientation = u%BladeRootMotion(k)%RefOrientation + + end do !k=numBlades + + + !................ + ! blades + !................ + + allocate( u%BladeMotion(p%NumBlades), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, 'Error allocating u%BladeMotion array.', ErrStat, ErrMsg, RoutineName ) + return + end if + + do k=1,p%NumBlades + call MeshCreate ( BlankMesh = u%BladeMotion(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = InputFileData%BladeProps(k)%NumBlNds & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ,RotationVel = .true. & + ,TranslationAcc = .true. & + ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + + do j=1,InputFileData%BladeProps(k)%NumBlNds + + ! reference position of the jth node in the kth blade, relative to the root in the local blade coordinate system: + positionL(1) = InputFileData%BladeProps(k)%BlCrvAC(j) + positionL(2) = InputFileData%BladeProps(k)%BlSwpAC(j) + positionL(3) = InputFileData%BladeProps(k)%BlSpn( j) + + ! reference position of the jth node in the kth blade: + position = u%BladeRootMotion(k)%Position(:,1) + matmul(positionL,u%BladeRootMotion(k)%RefOrientation(:,:,1)) ! note that because positionL is a 1-D array, we're doing the transpose of matmul(transpose(u%BladeRootMotion(k)%RefOrientation),positionL) + + + ! reference orientation of the jth node in the kth blade, relative to the root in the local blade coordinate system: + theta(1) = 0.0_R8Ki + theta(2) = InputFileData%BladeProps(k)%BlCrvAng(j) + theta(3) = -InputFileData%BladeProps(k)%BlTwist( j) + orientationL = EulerConstruct( theta ) + + ! reference orientation of the jth node in the kth blade + orientation = matmul( orientationL, u%BladeRootMotion(k)%RefOrientation(:,:,1) ) + + + call MeshPositionNode(u%BladeMotion(k), j, position, errStat2, errMsg2, orientation) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + end do ! j=blade nodes + + ! create line2 elements + do j=1,InputFileData%BladeProps(k)%NumBlNds-1 + call MeshConstructElement( u%BladeMotion(k), ELEMENT_LINE2, errStat2, errMsg2, p1=j, p2=j+1 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + call MeshCommit(u%BladeMotion(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (errStat >= AbortErrLev) return + + + u%BladeMotion(k)%Orientation = u%BladeMotion(k)%RefOrientation + u%BladeMotion(k)%TranslationDisp = 0.0_R8Ki + u%BladeMotion(k)%TranslationVel = 0.0_ReKi + + end do !k=numBlades + + +end subroutine Init_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets AeroDyn parameters for use during the simulation; these variables are not changed after AD_Init. +subroutine SetParameters( InitInp, InputFileData, p, ErrStat, ErrMsg ) + TYPE(AD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine, out is needed because of copy below + TYPE(AD_InputFile), INTENT(INout) :: InputFileData !< Data stored in the module's input file -- intent(out) only for move_alloc statements + TYPE(AD_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 + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + !INTEGER(IntKi) :: i, j + character(*), parameter :: RoutineName = 'SetParameters' + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + p%DT = InputFileData%DTAero + p%WakeMod = InputFileData%WakeMod + p%TwrPotent = InputFileData%TwrPotent + p%TwrShadow = InputFileData%TwrShadow + p%TwrAero = InputFileData%TwrAero + p%CavitCheck = InputFileData%CavitCheck + p%Gravity = InitInp%Gravity + + + + if (InitInp%Linearize .and. InputFileData%WakeMod == WakeMod_BEMT) then + p%FrozenWake = InputFileData%FrozenWake + else + p%FrozenWake = .FALSE. + end if + + p%CompAA = InputFileData%CompAA + + ! p%numBlades = InitInp%numBlades ! this was set earlier because it was necessary + p%NumBlNds = InputFileData%BladeProps(1)%NumBlNds + if (p%TwrPotent == TwrPotent_none .and. p%TwrShadow == TwrShadow_none .and. .not. p%TwrAero) then + p%NumTwrNds = 0 + else + p%NumTwrNds = InputFileData%NumTwrNds + + call move_alloc( InputFileData%TwrDiam, p%TwrDiam ) + call move_alloc( InputFileData%TwrCd, p%TwrCd ) + call move_alloc( InputFileData%TwrTI, p%TwrTI ) + end if + + p%AirDens = InputFileData%AirDens + p%KinVisc = InputFileData%KinVisc + p%Patm = InputFileData%Patm + p%Pvap = InputFileData%Pvap + p%FluidDepth = InputFileData%FluidDepth + p%SpdSound = InputFileData%SpdSound + + !p%AFI ! set in call to AFI_Init() [called early because it wants to use the same echo file as AD] + !p%BEMT ! set in call to BEMT_Init() + + !p%RootName = TRIM(InitInp%RootName)//'.AD' ! set earlier to it could be used + + p%numOuts = InputFileData%NumOuts + p%NBlOuts = InputFileData%NBlOuts + p%BlOutNd = InputFileData%BlOutNd + + if (p%NumTwrNds > 0) then + p%NTwOuts = InputFileData%NTwOuts + p%TwOutNd = InputFileData%TwOutNd + else + p%NTwOuts = 0 + end if + + call SetOutParam(InputFileData%OutList, p, ErrStat2, ErrMsg2 ) ! requires: p%NumOuts, p%numBlades, p%NumBlNds, p%NumTwrNds; sets: p%OutParam. + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + + + + ! Set the nodal output parameters. Note there is some validation in this, so we might get an error from here. + CALL AllBldNdOuts_SetParameters( InitInp, InputFileData, p, ErrStat2, ErrMsg2 ) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + + +end subroutine SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +subroutine AD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(AD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(AD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(AD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(AD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(AD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(AD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! End the FVW submodule + if (p%WakeMod == WakeMod_FVW ) then + call FVW_End( m%FVW_u, p%FVW, x%FVW, xd%FVW, z%FVW, OtherState%FVW, m%FVW_y, m%FVW, ErrStat, ErrMsg ) + endif + + ! Close files here: + + + + ! Destroy the input data: + + CALL AD_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL AD_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL AD_DestroyContState( x, ErrStat, ErrMsg ) + CALL AD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL AD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL AD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + CALL AD_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL AD_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE AD_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. +!! Continuous, constraint, discrete, and other states are updated for t + Interval +subroutine AD_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, errStat, errMsg ) +!.................................................................................................................................. + + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current simulation time step n = 0,1,... + type(AD_InputType), intent(inout) :: u(:) !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + real(DbKi), intent(in ) :: utimes(:) !< Times associated with u(:), in seconds + type(AD_ParameterType), intent(in ) :: p !< Parameters + type(AD_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + type(AD_DiscreteStateType), intent(inout) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + type(AD_ConstraintStateType), intent(inout) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t+dt + type(AD_OtherStateType), intent(inout) :: OtherState !< Input: Other states at t; + !! Output: Other states at t+dt + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + type(AD_InputType) :: uInterp ! Interpolated/Extrapolated input + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'AD_UpdateStates' + + ErrStat = ErrID_None + ErrMsg = "" + + + call AD_CopyInput( u(1), uInterp, MESH_NEWCOPY, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! set values of m%BEMT_u(2) from inputs interpolated at t+dt: + ! NOTE: this is different than OpenFAST, which has t+dt at u(1) + call AD_Input_ExtrapInterp(u,utimes,uInterp,t+p%DT, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call SetInputs(p, uInterp, m, 2, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! set values of m%BEMT_u(1) from inputs (uInterp) interpolated at t: + ! NOTE: this is different than OpenFAST, which has t at u(2) + ! I'm doing this second in case we want the other misc vars at t as before, but I don't think it matters + call AD_Input_ExtrapInterp(u,utimes,uInterp, t, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call SetInputs(p, uInterp, m, 1, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + if (p%WakeMod /= WakeMod_FVW) then + ! Call into the BEMT update states NOTE: This is a non-standard framework interface!!!!! GJH + ! Also note BEMT_u(1) and BEMT_u(2) are not following the OpenFAST convention for t+dt, t + call BEMT_UpdateStates(t, n, m%BEMT_u(1), m%BEMT_u(2), p%BEMT, x%BEMT, xd%BEMT, z%BEMT, OtherState%BEMT, p%AFI, m%BEMT, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Call AeroAcoustics updates states + if ( p%CompAA ) then + ! We need the outputs from BEMT as inputs to AeroAcoustics module + ! Also, SetInputs() [called above] calls SetInputsForBEMT() which in turn establishes current versions of the Global to local transformations we need as inputs to AA + call SetInputsForAA(p, u(1), m, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AA_UpdateStates(t, n,m%AA, m%AA_u, p%AA, xd%AA, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + else ! Call the FVW sub module + ! This needs to extract the inputs from the AD data types (mesh) and copy pieces for the FVW module + call SetInputsForFVW(p, u, m, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! Note: the setup is handled above in the SetInputs routine + call FVW_UpdateStates( t, n, m%FVW_u, utimes, p%FVW, x%FVW, xd%FVW, z%FVW, OtherState%FVW, p%AFI, m%FVW, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! The wind points are passed out as other states. These really correspond to the propogation of the vortex to the next wind position. + if (allocated(OtherState%WakeLocationPoints)) then + OtherState%WakeLocationPoints = m%FVW%r_wind + endif + ! UA TODO + !call UA_UpdateState_Wrapper(p%AFI, n, p%FVW, x%FVW, xd%FVW, OtherState%FVW, m%FVW, ErrStat2, ErrMsg2) + ! call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + + call Cleanup() + +contains + subroutine Cleanup() + call AD_DestroyInput( uInterp, errStat2, errMsg2) + end subroutine Cleanup +end subroutine AD_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! This subroutine is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! The descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +subroutine AD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, NeedWriteOutput ) +! NOTE: no matter how many channels are selected for output, all of the outputs are calculated +! All of the calculated output channels are placed into the m%AllOuts(:), while the channels selected for outputs are +! placed in the y%WriteOutput(:) array. +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(AD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL, OPTIONAL, INTENT(IN ) :: NeedWriteOutput !< Flag to determine if WriteOutput values need to be calculated in this call + + + ! NOTE: m%BEMT_u(i) indices are set differently from the way OpenFAST typically sets up the u and uTimes arrays + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer(intKi) :: i + integer(intKi) :: j + + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AD_CalcOutput' + real(ReKi) :: SigmaCavitCrit, SigmaCavit + LOGICAL :: CalcWriteOutput + + ErrStat = ErrID_None + ErrMsg = "" + +#ifdef UA_OUTS + ! if ( mod(REAL(t,ReKi),.1) < p%dt) then + if (allocated(m%FVW%y_UA%WriteOutput)) m%FVW%y_UA%WriteOutput = 0.0 !reset to zero in case UA shuts off mid-simulation + ! endif +#endif + + if (present(NeedWriteOutput)) then + CalcWriteOutput = NeedWriteOutput + else + CalcWriteOutput = .true. ! by default, calculate WriteOutput unless told that we do not need it + end if + + + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (p%WakeMod /= WakeMod_FVW) then + ! Call the BEMT module CalcOutput. Notice that the BEMT outputs are purposely attached to AeroDyn's MiscVar structure to + ! avoid issues with the coupling code + + call BEMT_CalcOutput(t, m%BEMT_u(indx), p%BEMT, x%BEMT, xd%BEMT, z%BEMT, OtherState%BEMT, p%AFI, m%BEMT_y, m%BEMT, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call SetOutputsFromBEMT(p, m, y ) + + if ( p%CompAA ) then + ! We need the outputs from BEMT as inputs to AeroAcoustics module + ! Also, SetInputs() [called above] calls SetInputsForBEMT() which in turn establishes current versions of the Global to local transformations we need as inputs to AA + call SetInputsForAA(p, u, m, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AA_CalcOutput(t, m%AA_u, p%AA, x%AA, xd%AA, z%AA, OtherState%AA, m%AA_y, m%AA, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + else !(p%WakeMod == WakeMod_FVW) + ! This needs to extract the inputs from the AD data types (mesh) and copy pieces for the FVW module + call SetInputsForFVW(p, (/u/), m, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! Calculate Outputs at time t + CALL FVW_CalcOutput( t, m%FVW_u(1), p%FVW, x%FVW, xd%FVW, z%FVW, OtherState%FVW, p%AFI, m%FVW_y, m%FVW, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call SetOutputsFromFVW( u, p, OtherState, x, xd, m, y, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + + if ( p%TwrAero ) then + call ADTwr_CalcOutput(p, u, m, y, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + if ( p%CavitCheck ) then ! Calculate the cavitation number for the airfoil at the node in quesiton, and compare to the critical cavitation number based on the vapour pressure and submerged depth + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%NumBlNds ! Loop through all nodes + + if ( EqualRealNos( m%BEMT_y%Vrel(i,j), 0.0_ReKi ) ) call SetErrStat( ErrID_Fatal, 'Vrel cannot be zero to do a cavitation check', ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + SigmaCavit= -1* m%BEMT_y%Cpmin(i,j) ! Local cavitation number on node j + SigmaCavitCrit= ( ( p%Patm + ( p%Gravity * (p%FluidDepth - ( u%BladeMotion(j)%Position(3,i) + u%BladeMotion(j)%TranslationDisp(3,i) - u%HubMotion%Position(3,1))) * p%airDens) - p%Pvap ) / ( 0.5_ReKi * p%airDens * m%BEMT_y%Vrel(i,j)**2)) ! Critical value of Sigma, cavitation occurs if local cavitation number is greater than this + + if ( (SigmaCavitCrit < SigmaCavit) .and. (.not. (m%CavitWarnSet(i,j)) ) ) then + call WrScr( NewLine//'Cavitation occurred at blade '//trim(num2lstr(j))//' and node '//trim(num2lstr(i))//'.' ) + m%CavitWarnSet(i,j) = .true. + end if + + m%SigmaCavit(i,j)= SigmaCavit + m%SigmaCavitCrit(i,j)=SigmaCavitCrit + + end do ! p%NumBlNds + end do ! p%numBlades + end if ! Cavitation check + + + !------------------------------------------------------- + ! get values to output to file: + !------------------------------------------------------- + if (CalcWriteOutput) then + if (p%NumOuts > 0) then + call Calc_WriteOutput( p, u, m, y, OtherState, xd, indx, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) array with the proper sign: + !............................................................................................................................... + + do i = 1,p%NumOuts ! Loop through all selected output channels + y%WriteOutput(i) = p%OutParam(i)%SignM * m%AllOuts( p%OutParam(i)%Indx ) + end do ! i - All selected output channels + + end if + + y%WriteOutput(p%NumOuts+1:) = 0.0_ReKi + + ! Now we need to populate the blade node outputs here + call Calc_WriteAllBldNdOutput( p, u, m, y, OtherState, indx, ErrStat2, ErrMsg2 ) ! Call after normal writeoutput. Will just postpend data on here. + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + +#ifdef UA_OUTS + ! if ( mod(REAL(t,ReKi),.1) < p%dt) then + if (allocated(m%FVW%y_UA%WriteOutput)) & + WRITE (69, '(F20.6,'//trim(num2lstr(size(m%FVW%y_UA%WriteOutput)))//'(:,1x,ES19.5E3))') t, ( m%FVW%y_UA%WriteOutput(i), i=1,size(m%FVW%y_UA%WriteOutput)) + ! end if +#endif + + +end subroutine AD_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +subroutine AD_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(AD_ConstraintStateType), INTENT(INOUT) :: 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 + + + + ! Local variables + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AD_CalcConstrStateResidual' + + + + ErrStat = ErrID_None + ErrMsg = "" + + if (.not. allocated(Z_residual%BEMT%phi)) then ! BEMT_CalcConstrStateResidual expects memory to be allocated, so let's make sure it is + call AD_CopyConstrState( z, Z_residual, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + call BEMT_CalcConstrStateResidual( Time, m%BEMT_u(indx), p%BEMT, x%BEMT, xd%BEMT, z%BEMT, OtherState%BEMT, m%BEMT, & + Z_residual%BEMT, p%AFI, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + +end subroutine AD_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +! Tight coupling routine for computing derivatives of continuous states +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(AD_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(AD_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at t + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + TYPE(AD_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD_ContinuousStateType), INTENT(INOUT) :: dxdt ! Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(*), PARAMETER :: RoutineName = 'AD_CalcContStateDeriv' + + INTEGER(IntKi), parameter :: InputIndex = 1 + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + call SetInputs(p, u, m, InputIndex, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call BEMT_CalcContStateDeriv( t, m%BEMT_u(InputIndex), p%BEMT, x%BEMT, xd%BEMT, z%BEMT, OtherState%BEMT, m%BEMT, dxdt%BEMT, p%AFI, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +END SUBROUTINE AD_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine converts the AeroDyn inputs into values that can be used for its submodules. It calculates the disturbed inflow +!! on the blade if tower shadow or tower influence are enabled, then uses these values to set m%BEMT_u(indx). +subroutine SetInputs(p, u, m, indx, errStat, errMsg) + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer, intent(in ) :: indx !< index into m%BEMT_u(indx) array; 1=t and 2=t+dt (but not checked here) + 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 + character(*), parameter :: RoutineName = 'SetInputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + if (p%TwrPotent /= TwrPotent_none .or. p%TwrShadow /= TwrShadow_none) then + call TwrInfl( p, u, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + m%DisturbedInflow = u%InflowOnBlade + end if + + if (p%WakeMod /= WakeMod_FVW) then + ! This needs to extract the inputs from the AD data types (mesh) and massage them for the BEMT module + call SetInputsForBEMT(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + + +end subroutine SetInputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets m%BEMT_u(indx). +subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg) + + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer, intent(in ) :: indx !< index into m%BEMT_u array; must be 1 or 2 (but not checked here) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(R8Ki) :: x_hat(3) + real(R8Ki) :: y_hat(3) + real(R8Ki) :: z_hat(3) + real(R8Ki) :: x_hat_disk(3) + real(R8Ki) :: y_hat_disk(3) + real(R8Ki) :: z_hat_disk(3) + real(ReKi) :: tmp(3) + real(ReKi) :: tmp_sz, tmp_sz_y + real(ReKi) :: rmax + real(R8Ki) :: thetaBladeNds(p%NumBlNds,p%NumBlades) + real(R8Ki) :: Azimuth(p%NumBlades) + + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'SetInputsForBEMT' + + ! note ErrStat and ErrMsg are set in GeomWithoutSweepPitchTwist: + + ! Get disk average values and orientations + call DiskAvgValues(p, u, m, x_hat_disk, y_hat_disk, z_hat_disk, Azimuth) + call GeomWithoutSweepPitchTwist(p,u,m,thetaBladeNds,ErrStat,ErrMsg) + if (ErrStat >= AbortErrLev) return + + ! Velocity in disk normal + m%BEMT_u(indx)%Un_disk = m%V_dot_x + + ! "Angular velocity of rotor" rad/s + m%BEMT_u(indx)%omega = dot_product( u%HubMotion%RotationVel(:,1), x_hat_disk ) + + ! "Angle between the vector normal to the rotor plane and the wind vector (e.g., the yaw angle in the case of no tilt)" rad + tmp_sz = TwoNorm( m%V_diskAvg ) + if ( EqualRealNos( tmp_sz, 0.0_ReKi ) ) then + m%BEMT_u(indx)%chi0 = 0.0_ReKi + else + ! make sure we don't have numerical issues that make the ratio outside +/-1 + tmp_sz_y = min( 1.0_ReKi, m%V_dot_x / tmp_sz ) + tmp_sz_y = max( -1.0_ReKi, tmp_sz_y ) + + m%BEMT_u(indx)%chi0 = acos( tmp_sz_y ) + + end if + + ! "Azimuth angle" rad + m%bemt_u(indx)%psi = Azimuth + + ! theta, "Twist angle (includes all sources of twist)" rad + ! Vx, "Local axial velocity at node" m/s + ! Vy, "Local tangential velocity at node" m/s + do k=1,p%NumBlades + do j=1,p%NumBlNds + + m%BEMT_u(indx)%theta(j,k) = thetaBladeNds(j,k) ! local pitch + twist (aerodyanmic + elastic) angle of the jth node in the kth blade + + x_hat = m%WithoutSweepPitchTwist(1,:,j,k) + y_hat = m%WithoutSweepPitchTwist(2,:,j,k) + tmp = m%DisturbedInflow(:,j,k) - u%BladeMotion(k)%TranslationVel(:,j) ! rel_V(j)_Blade(k) + + m%BEMT_u(indx)%Vx(j,k) = dot_product( tmp, x_hat ) ! normal component (normal to the plane, not chord) of the inflow velocity of the jth node in the kth blade + m%BEMT_u(indx)%Vy(j,k) = dot_product( tmp, y_hat ) ! tangential component (tangential to the plane, not chord) of the inflow velocity of the jth node in the kth blade + + + !jmj says omega_z and PitchRate are the same things + ! inputs for DBEMT (DBEMT_Mod == DBEMT_cont_tauConst) + if (allocated(m%BEMT_u(indx)%Vx_elast_dot)) then + m%BEMT_u(indx)%Vx_elast_dot(j,k) = dot_product( u%BladeMotion(k)%TranslationAcc(:,j), x_hat ) ! normal component (normal to the plane, not chord) of the inflow velocity of the jth node in the kth blade + m%BEMT_u(indx)%Vy_elast_dot(j,k) = dot_product( u%BladeMotion(k)%TranslationAcc(:,j), y_hat ) ! tangential component (tangential to the plane, not chord) of the inflow velocity of the jth node in the kth blade + end if + ! inputs for CUA (and CDBEMT): + m%BEMT_u(indx)%omega_z(j,k) = dot_product( u%BladeMotion(k)%RotationVel( :,j), m%WithoutSweepPitchTwist(3,:,j,k) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade + + end do !j=nodes + end do !k=blades + + + ! "Radial distance from center-of-rotation to node" m + + do k=1,p%NumBlades + do j=1,p%NumBlNds + + ! displaced position of the jth node in the kth blade relative to the hub: + tmp = u%BladeMotion(k)%Position(:,j) + u%BladeMotion(k)%TranslationDisp(:,j) & + - u%HubMotion%Position(:,1) - u%HubMotion%TranslationDisp(:,1) + + ! local radius (normalized distance from rotor centerline) + tmp_sz_y = dot_product( tmp, y_hat_disk )**2 + tmp_sz = dot_product( tmp, z_hat_disk )**2 + m%BEMT_u(indx)%rLocal(j,k) = sqrt( tmp_sz + tmp_sz_y ) + + end do !j=nodes + end do !k=blades + + m%BEMT_u(indx)%UserProp = u%UserProp + + ! ................ TSR ..................... + + if ( EqualRealNos( m%V_dot_x, 0.0_ReKi ) ) then + m%BEMT_u(indx)%TSR = 0.0_ReKi + else + rmax = 0.0_ReKi + do k=1,min(p%NumBlades,MaxBl) + do j=1,p%NumBlNds + rmax = max(rmax, m%BEMT_u(indx)%rLocal(j,k) ) + end do !j=nodes + end do !k=blades + m%BEMT_u(indx)%TSR = m%BEMT_u(indx)%omega * rmax / m%V_dot_x + end if + +end subroutine SetInputsForBEMT +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine DiskAvgValues(p, u, m, x_hat_disk, y_hat_disk, z_hat_disk, Azimuth) + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + real(R8Ki), intent( out) :: x_hat_disk(3) + real(R8Ki), intent( out) :: y_hat_disk(3) + real(R8Ki), intent( out) :: z_hat_disk(3) + real(R8Ki), intent( out) :: Azimuth(p%NumBlades) + real(ReKi) :: z_hat(3) + real(ReKi) :: tmp(3) + real(ReKi) :: tmp_sz, tmp_sz_y + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + + ! calculate disk-averaged relative wind speed, V_DiskAvg + m%V_diskAvg = 0.0_ReKi + do k=1,p%NumBlades + do j=1,p%NumBlNds + tmp = m%DisturbedInflow(:,j,k) - u%BladeMotion(k)%TranslationVel(:,j) + m%V_diskAvg = m%V_diskAvg + tmp + end do + end do + m%V_diskAvg = m%V_diskAvg / real( p%NumBlades * p%NumBlNds, ReKi ) + + ! orientation vectors: + x_hat_disk = u%HubMotion%Orientation(1,:,1) !actually also x_hat_hub + + m%V_dot_x = dot_product( m%V_diskAvg, x_hat_disk ) + tmp = m%V_dot_x * x_hat_disk - m%V_diskAvg + tmp_sz = TwoNorm(tmp) + if ( EqualRealNos( tmp_sz, 0.0_ReKi ) ) then + y_hat_disk = u%HubMotion%Orientation(2,:,1) + z_hat_disk = u%HubMotion%Orientation(3,:,1) + else + y_hat_disk = tmp / tmp_sz + z_hat_disk = cross_product( m%V_diskAvg, x_hat_disk ) / tmp_sz + end if + + ! "Azimuth angle" rad + do k=1,p%NumBlades + z_hat = u%BladeRootMotion(k)%Orientation(3,:,1) + tmp_sz_y = -1.0*dot_product(z_hat,y_hat_disk) + tmp_sz = dot_product(z_hat,z_hat_disk) + if ( EqualRealNos(tmp_sz_y,0.0_ReKi) .and. EqualRealNos(tmp_sz,0.0_ReKi) ) then + Azimuth(k) = 0.0_ReKi + else + Azimuth(k) = atan2( tmp_sz_y, tmp_sz ) + end if + end do +end subroutine DiskAvgValues +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine GeomWithoutSweepPitchTwist(p,u,m,thetaBladeNds,ErrStat,ErrMsg) + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + real(R8Ki), intent( out) :: thetaBladeNds(p%NumBlNds,p%NumBlades) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(R8Ki) :: theta(3) + real(R8Ki) :: orientation(3,3) + real(R8Ki) :: orientation_nopitch(3,3) + + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'GeomWithoutSweepPitchTwist' + + ErrStat = ErrID_None + ErrMsg = "" + + ! theta, "Twist angle (includes all sources of twist)" rad + ! Vx, "Local axial velocity at node" m/s + ! Vy, "Local tangential velocity at node" m/s + do k=1,p%NumBlades + + ! construct system equivalent to u%BladeRootMotion(k)%Orientation, but without the blade-pitch angle: + + call LAPACK_gemm( 'n', 't', 1.0_R8Ki, u%BladeRootMotion(k)%Orientation(:,:,1), u%HubMotion%Orientation(:,:,1), 0.0_R8Ki, orientation, errStat2, errMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + theta = EulerExtract( orientation ) !hub_theta_root(k) + m%AllOuts( BPitch( k) ) = -theta(3)*R2D ! save this value of pitch for potential output + theta(3) = 0.0_ReKi + m%hub_theta_x_root(k) = theta(1) ! save this value for FAST.Farm + + orientation = EulerConstruct( theta ) + orientation_nopitch = matmul( orientation, u%HubMotion%Orientation(:,:,1) ) ! withoutPitch_theta_Root(k) + + do j=1,p%NumBlNds + + ! form coordinate system equivalent to u%BladeMotion(k)%Orientation(:,:,j) but without live sweep (due to in-plane + ! deflection), blade-pitch and twist (aerodynamic + elastic) angles: + + ! orientation = matmul( u%BladeMotion(k)%Orientation(:,:,j), transpose(orientation_nopitch) ) + call LAPACK_gemm( 'n', 't', 1.0_R8Ki, u%BladeMotion(k)%Orientation(:,:,j), orientation_nopitch, 0.0_R8Ki, orientation, errStat2, errMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + theta = EulerExtract( orientation ) !root(k)WithoutPitch_theta(j)_blade(k) + + thetaBladeNds(j,k) = -theta(3) ! local pitch + twist (aerodyanmic + elastic) angle of the jth node in the kth blade + + + theta(1) = 0.0_ReKi + theta(3) = 0.0_ReKi + m%Curve(j,k) = theta(2) ! save value for possible output later + m%WithoutSweepPitchTwist(:,:,j,k) = matmul( EulerConstruct( theta ), orientation_nopitch ) ! WithoutSweepPitch+Twist_theta(j)_Blade(k) + + end do !j=nodes + end do !k=blades +end subroutine GeomWithoutSweepPitchTwist +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets m%FVW_u(indx). +subroutine SetInputsForFVW(p, u, m, errStat, errMsg) + + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u(:) !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + real(R8Ki) :: x_hat_disk(3) + real(R8Ki) :: y_hat_disk(3) + real(R8Ki) :: z_hat_disk(3) + real(R8Ki) :: thetaBladeNds(p%NumBlNds,p%NumBlades) + real(R8Ki) :: Azimuth(p%NumBlades) + + integer(intKi) :: tIndx + integer(intKi) :: k ! loop counter for blades + character(*), parameter :: RoutineName = 'SetInputsForFVW' + + do tIndx=1,size(u) + ! Get disk average values and orientations + ! NOTE: needed because it sets m%V_diskAvg and m%V_dot_x, needed by CalcOutput.. + call DiskAvgValues(p, u(tIndx), m, x_hat_disk, y_hat_disk, z_hat_disk, Azimuth) + call GeomWithoutSweepPitchTwist(p,u(tIndx),m,thetaBladeNds,ErrStat,ErrMsg) + if (ErrStat >= AbortErrLev) return + + ! Rather than use a meshcopy, we will just copy what we need to the WingsMesh + ! NOTE: MeshCopy requires the source mesh to be INOUT intent + ! NOTE2: If we change the WingsMesh to not be identical to the BladeMotion mesh, add the mapping stuff here. + do k=1,p%NumBlades + if ( u(tIndx)%BladeMotion(k)%nNodes /= m%FVW_u(tIndx)%WingsMesh(k)%nNodes ) then + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//": WingsMesh contains different number of nodes than the BladeMotion mesh" + return + endif + m%FVW%PitchAndTwist(:,k) = thetaBladeNds(:,k) ! local pitch + twist (aerodyanmic + elastic) angle of the jth node in the kth blade + m%FVW_u(tIndx)%WingsMesh(k)%TranslationDisp = u(tIndx)%BladeMotion(k)%TranslationDisp + m%FVW_u(tIndx)%WingsMesh(k)%Orientation = u(tIndx)%BladeMotion(k)%Orientation + m%FVW_u(tIndx)%WingsMesh(k)%TranslationVel = u(tIndx)%BladeMotion(k)%TranslationVel + m%FVW_u(tIndx)%HubPosition = u(tIndx)%HubMotion%Position(:,1) + u(tIndx)%HubMotion%TranslationDisp(:,1) + m%FVW_u(tIndx)%HubOrientation = u(tIndx)%HubMotion%Orientation(:,:,1) + enddo + if (ALLOCATED(m%FVW_u(tIndx)%V_wind)) then + m%FVW_u(tIndx)%V_wind = u(tIndx)%InflowWakeVel + ! Applying tower shadow to V_wind based on r_wind positions + ! NOTE: m%DisturbedInflow also contains tower shadow and we need it for CalcOutput + if (p%TwrPotent /= TwrPotent_none .or. p%TwrShadow /= TwrShadow_none) then + if (p%FVW%TwrShadowOnWake) then + call TwrInflArray( p, u(tIndx), m, m%FVW%r_wind, m%FVW_u(tIndx)%V_wind, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + endif + end if + endif + enddo + m%FVW%Vwnd_ND = m%DisturbedInflow ! Nasty transfer for UA, but this is temporary, waiting for AeroDyn to handle UA +end subroutine SetInputsForFVW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets m%AA_u. +subroutine SetInputsForAA(p, u, m, errStat, errMsg) + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + integer(intKi) :: i ! loop counter for nodes + integer(intKi) :: j ! loop counter for blades + + ErrStat = ErrID_None + ErrMsg = "" + + do j=1,p%NumBlades + do i = 1,p%NumBlNds + ! Get local orientation matrix to transform from blade element coordinates to global coordinates + m%AA_u%RotGtoL(:,:,i,j) = u%BladeMotion(j)%Orientation(:,:,i) + + ! Get blade element aerodynamic center in global coordinates + m%AA_u%AeroCent_G(:,i,j) = u%BladeMotion(j)%Position(:,i) + u%BladeMotion(j)%TranslationDisp(:,i) + + ! Set the blade element relative velocity (including induction) + m%AA_u%Vrel(i,j) = m%BEMT_y%Vrel(i,j) + + ! Set the blade element angle of attack + m%AA_u%AoANoise(i,j) = m%BEMT_y%AOA(i,j) + + ! Set the blade element undisturbed flow + m%AA_u%Inflow(1,i,j) = u%InflowonBlade(1,i,j) + m%AA_u%Inflow(2,i,j) = u%InflowonBlade(2,i,j) + m%AA_u%Inflow(3,i,j) = u%InflowonBlade(3,i,j) + end do + end do +end subroutine SetInputsForAA +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine converts outputs from BEMT (stored in m%BEMT_y) into values on the AeroDyn BladeLoad output mesh. +subroutine SetOutputsFromBEMT(p, m, y ) + + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_OutputType), intent(inout) :: y !< AD outputs + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + !type(BEMT_OutputType), intent(in ) :: BEMT_y ! BEMT outputs + !real(ReKi), intent(in ) :: WithoutSweepPitchTwist(:,:,:,:) ! modified orientation matrix + + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + real(reki) :: force(3) + real(reki) :: moment(3) + real(reki) :: q + + + + force(3) = 0.0_ReKi + moment(1:2) = 0.0_ReKi + do k=1,p%NumBlades + do j=1,p%NumBlNds + + q = 0.5 * p%airDens * m%BEMT_y%Vrel(j,k)**2 ! dynamic pressure of the jth node in the kth blade + force(1) = m%BEMT_y%cx(j,k) * q * p%BEMT%chord(j,k) ! X = normal force per unit length (normal to the plane, not chord) of the jth node in the kth blade + force(2) = -m%BEMT_y%cy(j,k) * q * p%BEMT%chord(j,k) ! Y = tangential force per unit length (tangential to the plane, not chord) of the jth node in the kth blade + moment(3)= m%BEMT_y%cm(j,k) * q * p%BEMT%chord(j,k)**2 ! M = pitching moment per unit length of the jth node in the kth blade + + ! save these values for possible output later: + m%X(j,k) = force(1) + m%Y(j,k) = force(2) + m%M(j,k) = moment(3) + + ! note: because force and moment are 1-d arrays, I'm calculating the transpose of the force and moment outputs + ! so that I don't have to take the transpose of WithoutSweepPitchTwist(:,:,j,k) + y%BladeLoad(k)%Force(:,j) = matmul( force, m%WithoutSweepPitchTwist(:,:,j,k) ) ! force per unit length of the jth node in the kth blade + y%BladeLoad(k)%Moment(:,j) = matmul( moment, m%WithoutSweepPitchTwist(:,:,j,k) ) ! moment per unit length of the jth node in the kth blade + + end do !j=nodes + end do !k=blades + + +end subroutine SetOutputsFromBEMT + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine converts outputs from FVW (stored in m%FVW_y) into values on the AeroDyn BladeLoad output mesh. +subroutine SetOutputsFromFVW(u, p, OtherState, x, xd, m, y, ErrStat, ErrMsg) + TYPE(AD_InputType), intent(in ) :: u !< Inputs at Time t + type(AD_ParameterType), intent(in ) :: p !< AD parameters + type(AD_OtherStateType), intent(in ) :: OtherState !< OtherState + type(AD_ContinuousStateType),intent(in ) :: x !< continuous states + type(AD_DiscreteStateType),intent(in ) :: xd !< Discrete states + type(AD_OutputType), intent(inout) :: y !< AD outputs + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + real(reki) :: force(3) + real(reki) :: moment(3) + real(reki) :: q + REAL(ReKi) :: cp, sp ! cosine, sine of phi + + ! Local vars for readability + real(ReKi) :: Vind(3) + real(ReKi) :: Vstr(3) + real(ReKi) :: Vwnd(3) + real(ReKi) :: theta + ! Local variables that we store in misc for nodal outputs + real(ReKi) :: AxInd, TanInd, Vrel, phi, alpha, Re + + type(AFI_OutputType) :: AFI_interp ! Resulting values from lookup table + real(ReKi) :: UrelWind_s(3) ! Relative wind (wind+str) in section coords + real(ReKi) :: Cx, Cy + real(ReKi) :: Cl_Static, Cd_Static, Cm_Static + real(ReKi) :: Cl_dyn, Cd_dyn, Cm_dyn + type(UA_InputType) :: u_UA + + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = 0 + ErrMsg = "" + + ! zero forces + force(3) = 0.0_ReKi + moment(1:2) = 0.0_ReKi + + ! set all blade outputs for all nodes (needed in nodal outputs) + ! This loop is separated from below in case we want to move it later. + do k=1,p%numBlades + do j=1,p%NumBlNds + ! --- Computing main aero variables from induction - setting local variables + Vind = m%FVW_y%Vind(1:3,j,k) + Vstr = u%BladeMotion(k)%TranslationVel(1:3,j) + Vwnd = m%DisturbedInflow(1:3,j,k) ! NOTE: contains tower shadow + theta = m%FVW%PitchAndTwist(j,k) + call FVW_AeroOuts( m%WithoutSweepPitchTwist(1:3,1:3,j,k), u%BladeMotion(k)%Orientation(1:3,1:3,j), & ! inputs + theta, Vstr(1:3), Vind(1:3), VWnd(1:3), p%KinVisc, p%FVW%Chord(j,k), & ! inputs + AxInd, TanInd, Vrel, phi, alpha, Re, UrelWind_s(1:3), ErrStat2, ErrMsg2 ) ! outputs + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetOutputsFromFVW') + + ! Compute steady Airfoil Coefs no matter what.. + call AFI_ComputeAirfoilCoefs( alpha, Re, 0.0_ReKi, p%AFI(p%FVW%AFindx(j,k)), AFI_interp, ErrStat, ErrMsg ) + Cl_Static = AFI_interp%Cl + Cd_Static = AFI_interp%Cd + Cm_Static = AFI_interp%Cm + + ! Set dynamic to the (will be same as static if UA_Flag is false) + Cl_dyn = AFI_interp%Cl + Cd_dyn = AFI_interp%Cd + Cm_dyn = AFI_interp%Cm + + if (m%FVW%UA_Flag) then + if ((OtherState%FVW%UA_Flag(j,k)) .and. ( .not. EqualRealNos(Vrel,0.0_ReKi) ) ) then + + ! ....... compute inputs to UA ........... + u_UA%alpha = alpha + u_UA%U = Vrel + u_UA%Re = Re + u_UA%UserProp = 0.0_ReKi ! FIX ME + + ! FIX ME: this is copied 3 times!!!! + u_UA%v_ac(1) = sin(u_UA%alpha)*u_UA%U + u_UA%v_ac(2) = cos(u_UA%alpha)*u_UA%U + u_UA%omega = dot_product( u%BladeMotion(k)%RotationVel( :,j), m%WithoutSweepPitchTwist(3,:,j,k) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade + + call UA_CalcOutput(j, k, u_UA, m%FVW%p_UA, x%FVW%UA, xd%FVW%UA, OtherState%FVW%UA, p%AFI(p%FVW%AFindx(j,k)), m%FVW%y_UA, m%FVW%m_UA, errStat2, errMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetOutputsFromFVW') + Cl_dyn = m%FVW%y_UA%Cl + Cd_dyn = m%FVW%y_UA%Cd + Cm_dyn = m%FVW%y_UA%Cm + + end if + end if + + cp = cos(phi) + sp = sin(phi) + Cx = Cl_dyn*cp + Cd_dyn*sp + Cy = Cl_dyn*sp - Cd_dyn*cp + + q = 0.5 * p%airDens * Vrel**2 ! dynamic pressure of the jth node in the kth blade + force(1) = Cx * q * p%FVW%Chord(j,k) ! X = normal force per unit length (normal to the plane, not chord) of the jth node in the kth blade + force(2) = -Cy * q * p%FVW%Chord(j,k) ! Y = tangential force per unit length (tangential to the plane, not chord) of the jth node in the kth blade + moment(3)= Cm_dyn * q * p%FVW%Chord(j,k)**2 ! M = pitching moment per unit length of the jth node in the kth blade + + ! save these values for possible output later: + m%X(j,k) = force(1) + m%Y(j,k) = force(2) + m%M(j,k) = moment(3) + + ! note: because force and moment are 1-d arrays, I'm calculating the transpose of the force and moment outputs + ! so that I don't have to take the transpose of WithoutSweepPitchTwist(:,:,j,k) + y%BladeLoad(k)%Force(:,j) = matmul( force, m%WithoutSweepPitchTwist(:,:,j,k) ) ! force per unit length of the jth node in the kth blade + y%BladeLoad(k)%Moment(:,j) = matmul( moment, m%WithoutSweepPitchTwist(:,:,j,k) ) ! moment per unit length of the jth node in the kth blade + + ! Save results for outputs so we don't have to recalculate them all when we write outputs + m%FVW%BN_AxInd(j,k) = AxInd + m%FVW%BN_TanInd(j,k) = TanInd + m%FVW%BN_Vrel(j,k) = Vrel + m%FVW%BN_alpha(j,k) = alpha + m%FVW%BN_phi(j,k) = phi + m%FVW%BN_Re(j,k) = Re + m%FVW%BN_UrelWind_s(1:3,j,k) = UrelWind_s(1:3) + m%FVW%BN_Cl_Static(j,k) = Cl_Static + m%FVW%BN_Cd_Static(j,k) = Cd_Static + m%FVW%BN_Cm_Static(j,k) = Cm_Static + m%FVW%BN_Cl(j,k) = Cl_dyn + m%FVW%BN_Cd(j,k) = Cd_dyn + m%FVW%BN_Cm(j,k) = Cm_dyn + m%FVW%BN_Cx(j,k) = Cx + m%FVW%BN_Cy(j,k) = Cy + end do !j=nodes + end do !k=blades + + +end subroutine SetOutputsFromFVW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the AeroDyn input files. +SUBROUTINE ValidateNumBlades( NumBl, ErrStat, ErrMsg ) + integer(IntKi), intent(in) :: NumBl !< Number of blades + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + ErrStat = ErrID_None + ErrMsg = '' + if (NumBl > MaxBl .or. NumBl < 1) call SetErrStat( ErrID_Fatal, 'Number of blades must be between 1 and '//trim(num2lstr(MaxBl))//'.', ErrStat, ErrMsg, 'ValidateNumBlades' ) +END SUBROUTINE ValidateNumBlades +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the AeroDyn input files. +SUBROUTINE ValidateInputData( InitInp, InputFileData, NumBl, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + type(AD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(AD_InputFile), intent(in) :: InputFileData !< All the data in the AeroDyn input file + integer(IntKi), intent(in) :: NumBl !< Number of blades + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + + + ! local variables + integer(IntKi) :: k ! Blade number + integer(IntKi) :: j ! node number + character(*), parameter :: RoutineName = 'ValidateInputData' + + ErrStat = ErrID_None + ErrMsg = "" + + + if (InputFileData%DTAero <= 0.0) call SetErrStat ( ErrID_Fatal, 'DTAero must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%WakeMod /= WakeMod_None .and. InputFileData%WakeMod /= WakeMod_BEMT .and. InputFileData%WakeMod /= WakeMod_DBEMT .and. InputFileData%WakeMod /= WakeMod_FVW) then + call SetErrStat ( ErrID_Fatal, 'WakeMod must be '//trim(num2lstr(WakeMod_None))//' (none), '//trim(num2lstr(WakeMod_BEMT))//' (BEMT), '// & + trim(num2lstr(WakeMod_DBEMT))//' (DBEMT), or '//trim(num2lstr(WakeMod_FVW))//' (FVW).',ErrStat, ErrMsg, RoutineName ) + end if + + if (InputFileData%AFAeroMod /= AFAeroMod_Steady .and. InputFileData%AFAeroMod /= AFAeroMod_BL_unsteady) then + call SetErrStat ( ErrID_Fatal, 'AFAeroMod must be '//trim(num2lstr(AFAeroMod_Steady))//' (steady) or '//& + trim(num2lstr(AFAeroMod_BL_unsteady))//' (Beddoes-Leishman unsteady).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%TwrPotent /= TwrPotent_none .and. InputFileData%TwrPotent /= TwrPotent_baseline .and. InputFileData%TwrPotent /= TwrPotent_Bak) then + call SetErrStat ( ErrID_Fatal, 'TwrPotent must be 0 (none), 1 (baseline potential flow), or 2 (potential flow with Bak correction).', ErrStat, ErrMsg, RoutineName ) + end if + if (InputFileData%TwrShadow /= TwrShadow_none .and. InputFileData%TwrShadow /= TwrShadow_Powles .and. InputFileData%TwrShadow /= TwrShadow_Eames) then + call SetErrStat ( ErrID_Fatal, 'TwrShadow must be 0 (none), 1 (Powles tower shadow modle), or 2 (Eames tower shadow model).', ErrStat, ErrMsg, RoutineName ) + end if + + ! The following limits are recommended by Juliet Simpson (University of Virginia) + ! E-mail recommendation: + ! To test the limits of the model, I've been running steady simulations + ! with a range of TI inputs. It looks like the model starts to break down + ! (or at least break the trend of higher TI's) when the TI drops below + ! 0.05. On the other end, the model seems to work up to TI~1 without + ! breaking down (I checked up to TI=0.99). However, the results aren't + ! very physically realistic after ~0.35 because it approaches a constant + ! velocity deficit across the rotor plane, rather than returning to zero + ! deficit a short distance laterally from the tower. I'm not sure what + ! the goal of the limits would be, so it's hard for me to say what the + ! upper cut off should be. If you want it to be physical, perhaps a low + ! cut off (around 0.4?). If you want it to just not break, and let people + ! interpret for themselves if it's physical for their scenario, then it + ! could go to TI~1. I'd recommend imposing limits of 0.05<TI<1, personally. + if (InputFileData%TwrShadow == TwrShadow_Eames) then + if ( minval(InputFileData%TwrTI) <= 0.05 .or. maxval(InputFileData%TwrTI) >= 1.0) call SetErrStat ( ErrID_Fatal, 'The turbulence intensity for the Eames tower shadow model must be greater than 0.05 and less than 1.', ErrStat, ErrMsg, RoutineName ) + if ( maxval(InputFileData%TwrTI) > 0.4 .and. maxval(InputFileData%TwrTI) < 1.0) call SetErrStat ( ErrID_Warn, 'The turbulence intensity for the Eames tower shadow model above 0.4 may return unphysical results. Interpret with caution.', ErrStat, ErrMsg, RoutineName ) + endif + + if (InputFileData%AirDens <= 0.0) call SetErrStat ( ErrID_Fatal, 'The air density (AirDens) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%KinVisc <= 0.0) call SetErrStat ( ErrID_Fatal, 'The kinesmatic viscosity (KinVisc) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%SpdSound <= 0.0) call SetErrStat ( ErrID_Fatal, 'The speed of sound (SpdSound) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%Pvap <= 0.0) call SetErrStat ( ErrID_Fatal, 'The vapour pressure (Pvap) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%Patm <= 0.0) call SetErrStat ( ErrID_Fatal, 'The atmospheric pressure (Patm) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + if (InputFileData%FluidDepth <= 0.0) call SetErrStat ( ErrID_Fatal, 'Fluid depth (FluidDepth) must be greater than zero', ErrStat, ErrMsg, RoutineName ) + + + + ! BEMT/DBEMT inputs + ! bjj: these checks should probably go into BEMT where they are used... + if (InputFileData%WakeMod /= WakeMod_none .and. InputFileData%WakeMod /= WakeMod_FVW) then + if ( InputFileData%MaxIter < 1 ) call SetErrStat( ErrID_Fatal, 'MaxIter must be greater than 0.', ErrStat, ErrMsg, RoutineName ) + + if ( InputFileData%IndToler < 0.0 .or. EqualRealNos(InputFileData%IndToler, 0.0_ReKi) ) & + call SetErrStat( ErrID_Fatal, 'IndToler must be greater than 0.', ErrStat, ErrMsg, RoutineName ) + + if ( InputFileData%SkewMod /= SkewMod_Uncoupled .and. InputFileData%SkewMod /= SkewMod_PittPeters) & ! .and. InputFileData%SkewMod /= SkewMod_Coupled ) + call SetErrStat( ErrID_Fatal, 'SkewMod must be 1, or 2. Option 3 will be implemented in a future version.', ErrStat, ErrMsg, RoutineName ) + + end if !BEMT/DBEMT checks + + + if ( InputFileData%CavitCheck .and. InputFileData%AFAeroMod == AFAeroMod_BL_unsteady) then + call SetErrStat( ErrID_Fatal, 'Cannot use unsteady aerodynamics module with a cavitation check', ErrStat, ErrMsg, RoutineName ) + end if + + if (InputFileData%InCol_Cpmin == 0 .and. InputFileData%CavitCheck) call SetErrStat( ErrID_Fatal, 'InCol_Cpmin must not be 0 to do a cavitation check.', ErrStat, ErrMsg, RoutineName ) + + ! validate the number of airfoils + if (InputFileData%NumAFfiles < 1) call SetErrStat( ErrID_Fatal, 'The number of unique airfoil tables (NumAFfiles) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + + ! ............................. + ! check blade mesh data: + ! ............................. + if ( InputFileData%BladeProps(1)%NumBlNds < 2 ) call SetErrStat( ErrID_Fatal, 'There must be at least two nodes per blade.',ErrStat, ErrMsg, RoutineName ) + do k=2,NumBl + if ( InputFileData%BladeProps(k)%NumBlNds /= InputFileData%BladeProps(k-1)%NumBlNds ) then + call SetErrStat( ErrID_Fatal, 'All blade property files must have the same number of blade nodes.', ErrStat, ErrMsg, RoutineName ) + exit ! exit do loop + end if + end do + + ! Check the list of airfoil tables for blades to make sure they are all within limits. + do k=1,NumBl + do j=1,InputFileData%BladeProps(k)%NumBlNds + if ( ( InputFileData%BladeProps(k)%BlAFID(j) < 1 ) .OR. ( InputFileData%BladeProps(k)%BlAFID(j) > InputFileData%NumAFfiles ) ) then + call SetErrStat( ErrID_Fatal, 'Blade '//trim(Num2LStr(k))//' node '//trim(Num2LStr(j))//' must be a number between 1 and NumAFfiles (' & + //TRIM(Num2LStr(InputFileData%NumAFfiles))//').', ErrStat, ErrMsg, RoutineName ) + end if + end do ! j=nodes + end do ! k=blades + + ! Check that the blade chord is > 0. + do k=1,NumBl + do j=1,InputFileData%BladeProps(k)%NumBlNds + if ( InputFileData%BladeProps(k)%BlChord(j) <= 0.0_ReKi ) then + call SetErrStat( ErrID_Fatal, 'The chord for blade '//trim(Num2LStr(k))//' node '//trim(Num2LStr(j)) & + //' must be greater than 0.', ErrStat, ErrMsg, RoutineName ) + endif + end do ! j=nodes + end do ! k=blades + + do k=1,NumBl + if ( .not. EqualRealNos(InputFileData%BladeProps(k)%BlSpn(1), 0.0_ReKi) ) call SetErrStat( ErrID_Fatal, 'Blade '//trim(Num2LStr(k))//' span location must start at 0.0 m', ErrStat, ErrMsg, RoutineName) + do j=2,InputFileData%BladeProps(k)%NumBlNds + if ( InputFileData%BladeProps(k)%BlSpn(j) <= InputFileData%BladeProps(k)%BlSpn(j-1) ) then + call SetErrStat( ErrID_Fatal, 'Blade '//trim(Num2LStr(k))//' nodes must be entered in increasing elevation.', ErrStat, ErrMsg, RoutineName ) + exit + end if + end do ! j=nodes + end do ! k=blades + + ! ............................. + ! check tower mesh data: + ! ............................. + if (InputFileData%TwrPotent /= TwrPotent_none .or. InputFileData%TwrShadow /= TwrShadow_none .or. InputFileData%TwrAero ) then + + if (InputFileData%NumTwrNds < 2) call SetErrStat( ErrID_Fatal, 'There must be at least two nodes on the tower.',ErrStat, ErrMsg, RoutineName ) + + ! Check that the tower diameter is > 0. + do j=1,InputFileData%NumTwrNds + if ( InputFileData%TwrDiam(j) <= 0.0_ReKi ) then + call SetErrStat( ErrID_Fatal, 'The diameter for tower node '//trim(Num2LStr(j))//' must be greater than 0.' & + , ErrStat, ErrMsg, RoutineName ) + end if + end do ! j=nodes + + ! check that the elevation is increasing: + do j=2,InputFileData%NumTwrNds + if ( InputFileData%TwrElev(j) <= InputFileData%TwrElev(j-1) ) then + call SetErrStat( ErrID_Fatal, 'The tower nodes must be entered in increasing elevation.', ErrStat, ErrMsg, RoutineName ) + exit + end if + end do ! j=nodes + + end if + + ! ............................. + ! check outputs: + ! ............................. + + if ( ( InputFileData%NTwOuts < 0_IntKi ) .OR. ( InputFileData%NTwOuts > 9_IntKi ) ) then + call SetErrStat( ErrID_Fatal, 'NTwOuts must be between 0 and 9 (inclusive).', ErrStat, ErrMsg, RoutineName ) + else + ! Check to see if all TwOutNd(:) analysis points are existing analysis points: + + do j=1,InputFileData%NTwOuts + if ( InputFileData%TwOutNd(j) < 1_IntKi .OR. InputFileData%TwOutNd(j) > InputFileData%NumTwrNds ) then + call SetErrStat( ErrID_Fatal, ' All TwOutNd values must be between 1 and '//& + trim( Num2LStr( InputFileData%NumTwrNds ) )//' (inclusive).', ErrStat, ErrMsg, RoutineName ) + exit ! stop checking this loop + end if + end do + + end if + + + if ( ( InputFileData%NBlOuts < 0_IntKi ) .OR. ( InputFileData%NBlOuts > 9_IntKi ) ) then + call SetErrStat( ErrID_Fatal, 'NBlOuts must be between 0 and 9 (inclusive).', ErrStat, ErrMsg, RoutineName ) + else + + ! Check to see if all BlOutNd(:) analysis points are existing analysis points: + + do j=1,InputFileData%NBlOuts + if ( InputFileData%BlOutNd(j) < 1_IntKi .OR. InputFileData%BlOutNd(j) > InputFileData%BladeProps(1)%NumBlNds ) then + call SetErrStat( ErrID_Fatal, ' All BlOutNd values must be between 1 and '//& + trim( Num2LStr( InputFileData%BladeProps(1)%NumBlNds ) )//' (inclusive).', ErrStat, ErrMsg, RoutineName ) + exit ! stop checking this loop + end if + end do + + end if + + !.................. + ! check for linearization + !.................. + if (InitInp%Linearize) then + if (InputFileData%AFAeroMod /= AFAeroMod_Steady) then + if (InputFileData%UAMod /= UA_HGM) then + call SetErrStat( ErrID_Fatal, 'When AFAeroMod=2, UAMod must be 4 for linearization. Set AFAeroMod=1 or UAMod=4.', ErrStat, ErrMsg, RoutineName ) + end if + end if + + if (InputFileData%WakeMod == WakeMod_FVW) then + call SetErrStat( ErrID_Fatal, 'FVW cannot currently be used for linearization. Set WakeMod=0 or WakeMod=1.', ErrStat, ErrMsg, RoutineName ) + else if (InputFileData%WakeMod == WakeMod_DBEMT) then + if (InputFileData%DBEMT_Mod /= DBEMT_cont_tauConst) then + call SetErrStat( ErrID_Fatal, 'DBEMT requires the continuous formulation with constant tau1 for linearization. Set DBEMT_Mod=3 or set WakeMod to 0 or 1.', ErrStat, ErrMsg, RoutineName ) + end if + end if + end if + + +END SUBROUTINE ValidateInputData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets up the data structures and initializes AirfoilInfo to get the necessary AFI parameters. It then verifies +!! that the UA parameters are included in the AFI tables if UA is being used. +SUBROUTINE Init_AFIparams( InputFileData, p_AFI, UnEc, NumBl, ErrStat, ErrMsg ) + + + ! Passed variables + type(AD_InputFile), intent(inout) :: InputFileData !< All the data in the AeroDyn input file (intent(out) only because of the call to MOVE_ALLOC) + type(AFI_ParameterType), allocatable, intent( out) :: p_AFI(:) !< parameters returned from the AFI (airfoil info) module + integer(IntKi), intent(in ) :: UnEc !< I/O unit for echo file. If > 0, file is open for writing. + integer(IntKi), intent(in ) :: NumBl !< number of blades (for performing check on valid airfoil data read in) + integer(IntKi), intent( out) :: ErrStat !< Error status + character(*), intent( out) :: ErrMsg !< Error message + + ! local variables + type(AFI_InitInputType) :: AFI_InitInputs ! initialization data for the AFI routines + + integer(IntKi) :: j ! loop counter for nodes + integer(IntKi) :: k ! loop counter for blades + integer(IntKi) :: File ! loop counter for airfoil files + logical, allocatable :: fileUsed(:) + + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Init_AFIparams' + + + ErrStat = ErrID_None + ErrMsg = "" + + allocate(p_AFI( InputFileData%NumAFfiles), STAT = ErrStat2) + if ( ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal,'Error allocating p_AFI.',ErrStat,ErrMsg,RoutineName) + return + end if + + + ! Setup Airfoil InitInput data structure: + AFI_InitInputs%InCol_Alfa = InputFileData%InCol_Alfa + AFI_InitInputs%InCol_Cl = InputFileData%InCol_Cl + AFI_InitInputs%InCol_Cd = InputFileData%InCol_Cd + AFI_InitInputs%InCol_Cm = InputFileData%InCol_Cm + IF (.not. InputFileData%UseBlCm) AFI_InitInputs%InCol_Cm = 0 ! Don't try to use Cm if flag set to false + AFI_InitInputs%InCol_Cpmin = InputFileData%InCol_Cpmin + AFI_InitInputs%AFTabMod = InputFileData%AFTabMod !AFITable_1 + + ! Call AFI_Init to read in and process the airfoil files. + ! This includes creating the spline coefficients to be used for interpolation. + + do File = 1, InputFileData%NumAFfiles + + AFI_InitInputs%FileName = InputFileData%AFNames(File) + + call AFI_Init ( AFI_InitInputs, p_AFI(File), ErrStat2, ErrMsg2, UnEc ) + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) exit + end do + + + call AFI_DestroyInitInput( AFI_InitInputs, ErrStat2, ErrMsg2 ) + if (ErrStat >= AbortErrLev) return + + + ! check that we read the correct airfoil parameters for UA: + if ( InputFileData%AFAeroMod == AFAeroMod_BL_unsteady ) then + + ! determine which airfoil files will be used + call AllocAry( fileUsed, InputFileData%NumAFfiles, 'fileUsed', errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (errStat >= AbortErrLev) return + fileUsed = .false. + + do k=1,NumBl + do j=1,InputFileData%BladeProps(k)%NumBlNds + fileUsed ( InputFileData%BladeProps(k)%BlAFID(j) ) = .true. + end do ! j=nodes + end do ! k=blades + + ! make sure all files in use have proper UA input parameters: + do File = 1,InputFileData%NumAFfiles + + if (fileUsed(File)) then + call UA_ValidateAFI(InputFileData%UAMod, p_AFI(File), InputFileData%AFNames(File), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (errStat >= AbortErrLev) return + end if + + end do + + if ( allocated(fileUsed) ) deallocate(fileUsed) + + end if + + +END SUBROUTINE Init_AFIparams +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Airfoil Noise module from within AeroDyn. +SUBROUTINE Init_AAmodule( DrvInitInp, AD_InputFileData, u_AD, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + type(AD_InitInputType), intent(in ) :: DrvInitInp !< AeroDyn-level initialization inputs + type(AD_InputFile), intent(in ) :: AD_InputFileData !< All the data in the AeroDyn input file + type(AD_InputType), intent(in ) :: u_AD !< AD inputs - used for input mesh node positions + type(AA_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(AD_ParameterType), intent(inout) :: p !< Parameters ! intent out b/c we set the AA parameters here + type(AA_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(AA_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(AA_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(AA_OtherStateType), intent( out) :: OtherState !< Initial other states + type(AA_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(AA_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + real(DbKi) :: Interval ! Coupling interval in seconds: the rate that + ! (1) BEMT_UpdateStates() is called in loose coupling & + ! (2) BEMT_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + type(AA_InitInputType) :: InitInp ! Input data for initialization routine + type(AA_InitOutputType) :: InitOut ! Output for initialization routine + integer(intKi) :: i ! airfoil file index + integer(intKi) :: j ! node index + integer(intKi) :: k ! blade index + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Init_AAmodule' + ErrStat = ErrID_None + ErrMsg = "" + + ! Transfer from parameters and input file to init input + Interval = p%DT + InitInp%NumBlades = p%NumBlades + InitInp%NumBlNds = p%NumBlNds + InitInp%airDens = AD_InputFileData%AirDens + InitInp%kinVisc = AD_InputFileData%KinVisc + InitInp%InputFile = AD_InputFileData%AA_InputFile + InitInp%RootName = DrvInitInp%RootName + InitInp%SpdSound = AD_InputFileData%SpdSound + InitInp%HubHeight = DrvInitInp%HubPosition(3) + + ! --- Transfer of airfoil info + ALLOCATE ( InitInp%AFInfo( size(p%AFI) ), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for the InitInp%AFInfo array.', ErrStat2, ErrMsg2, RoutineName ) + RETURN + ENDIF + do i=1,size(p%AFI) + call AFI_CopyParam( p%AFI(i), InitInp%AFInfo(i), MESH_NEWCOPY, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do + + ! --- Allocate and set AirfoilID, chord and Span for each blades + ! note here that each blade is required to have the same number of nodes + call AllocAry( InitInp%BlAFID, p%NumBlNds, p%NumBlades,'InitInp%BlAFID', errStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( InitInp%BlChord, p%NumBlNds, p%NumBlades, 'BlChord', errStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( InitInp%BlSpn, p%NumBlNds, p%NumBlades, 'BlSpn', errStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + do k = 1, p%NumBlades + do j=1, AD_InputFileData%BladeProps(k)%NumBlNds + InitInp%BlChord(j,k) = AD_InputFileData%BladeProps(k)%BlChord( j) + InitInp%BlSpn (j,k) = AD_InputFileData%BladeProps(k)%BlSpn(j) + InitInp%BlAFID(j,k) = AD_InputFileData%BladeProps(k)%BlAFID(j) + end do + end do + + ! --- AeroAcoustics initialization call + call AA_Init(InitInp, u, p%AA, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (.not. equalRealNos(Interval, p%DT) ) then + call SetErrStat( ErrID_Fatal, "DTAero was changed in Init_AAmodule(); this is not allowed.", ErrStat2, ErrMsg2, RoutineName) + endif + + call Cleanup() + +contains + + subroutine Cleanup() + call AA_DestroyInitInput ( InitInp, ErrStat2, ErrMsg2 ) + call AA_DestroyInitOutput( InitOut, ErrStat2, ErrMsg2 ) + end subroutine Cleanup + +END SUBROUTINE Init_AAmodule +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the BEMT module from within AeroDyn. +SUBROUTINE Init_BEMTmodule( InputFileData, u_AD, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + type(AD_InputFile), intent(in ) :: InputFileData !< All the data in the AeroDyn input file + type(AD_InputType), intent(in ) :: u_AD !< AD inputs - used for input mesh node positions + type(BEMT_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(AD_ParameterType), intent(inout) :: p !< Parameters ! intent out b/c we set the BEMT parameters here + type(BEMT_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(BEMT_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(BEMT_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(BEMT_OtherStateType), intent( out) :: OtherState !< Initial other states + type(BEMT_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(BEMT_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + real(DbKi) :: Interval ! Coupling interval in seconds: the rate that + ! (1) BEMT_UpdateStates() is called in loose coupling & + ! (2) BEMT_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + type(BEMT_InitInputType) :: InitInp ! Input data for initialization routine + type(BEMT_InitOutputType) :: InitOut ! Output for initialization routine + + integer(intKi) :: j ! node index + integer(intKi) :: k ! blade index + real(ReKi) :: tmp(3), tmp_sz_y, tmp_sz + real(ReKi) :: y_hat_disk(3) + real(ReKi) :: z_hat_disk(3) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Init_BEMTmodule' + + ! note here that each blade is required to have the same number of nodes + + ErrStat = ErrID_None + ErrMsg = "" + + + ! set initialization data here: + Interval = p%DT + InitInp%numBlades = p%NumBlades + + InitInp%airDens = InputFileData%AirDens + InitInp%kinVisc = InputFileData%KinVisc + InitInp%skewWakeMod = InputFileData%SkewMod + InitInp%yawCorrFactor = InputFileData%SkewModFactor + InitInp%aTol = InputFileData%IndToler + InitInp%useTipLoss = InputFileData%TipLoss + InitInp%useHubLoss = InputFileData%HubLoss + InitInp%useInduction = InputFileData%WakeMod /= WakeMod_none + InitInp%useTanInd = InputFileData%TanInd + InitInp%useAIDrag = InputFileData%AIDrag + InitInp%useTIDrag = InputFileData%TIDrag + InitInp%numBladeNodes = p%NumBlNds + InitInp%numReIterations = 1 ! This is currently not available in the input file and is only for testing + InitInp%maxIndIterations = InputFileData%MaxIter + + call AllocAry(InitInp%chord, InitInp%numBladeNodes,InitInp%numBlades,'chord', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%AFindx,InitInp%numBladeNodes,InitInp%numBlades,'AFindx',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zHub, InitInp%numBlades,'zHub', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zLocal,InitInp%numBladeNodes,InitInp%numBlades,'zLocal',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%rLocal,InitInp%numBladeNodes,InitInp%numBlades,'rLocal',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zTip, InitInp%numBlades,'zTip', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + + + do k=1,p%numBlades + + InitInp%zHub(k) = TwoNorm( u_AD%BladeRootMotion(k)%Position(:,1) - u_AD%HubMotion%Position(:,1) ) + if (EqualRealNos(InitInp%zHub(k),0.0_ReKi) ) & + call SetErrStat( ErrID_Fatal, "zHub for blade "//trim(num2lstr(k))//" is zero.", ErrStat, ErrMsg, RoutineName) + + ! zLocal is the distance along blade curve -- NOTE: this is an approximation. + InitInp%zLocal(1,k) = InitInp%zHub(k) + TwoNorm( u_AD%BladeMotion(k)%Position(:,1) - u_AD%BladeRootMotion(k)%Position(:,1) ) + do j=2,p%NumBlNds + InitInp%zLocal(j,k) = InitInp%zLocal(j-1,k) + TwoNorm( u_AD%BladeMotion(k)%Position(:,j) - u_AD%BladeMotion(k)%Position(:,j-1) ) + end do !j=nodes + + InitInp%zTip(k) = InitInp%zLocal(p%NumBlNds,k) + + y_hat_disk = u_AD%HubMotion%Orientation(2,:,1) + z_hat_disk = u_AD%HubMotion%Orientation(3,:,1) + + do j=1,p%NumBlNds + ! displaced position of the jth node in the kth blade relative to the hub: + tmp = u_AD%BladeMotion(k)%Position(:,j) - u_AD%HubMotion%Position(:,1) + ! local radius (normalized distance from rotor centerline) + tmp_sz_y = dot_product( tmp, y_hat_disk )**2 + tmp_sz = dot_product( tmp, z_hat_disk )**2 + InitInp%rLocal(j,k) = sqrt( tmp_sz + tmp_sz_y ) + end do !j=nodes + end do !k=blades + + + do k=1,p%numBlades + do j=1,p%NumBlNds + InitInp%chord (j,k) = InputFileData%BladeProps(k)%BlChord(j) + InitInp%AFindx(j,k) = InputFileData%BladeProps(k)%BlAFID(j) + end do + end do + + InitInp%UA_Flag = InputFileData%AFAeroMod == AFAeroMod_BL_unsteady + InitInp%UAMod = InputFileData%UAMod + InitInp%Flookup = InputFileData%Flookup + InitInp%a_s = InputFileData%SpdSound + + if (InputFileData%WakeMod == WakeMod_DBEMT) then + InitInp%DBEMT_Mod = InputFileData%DBEMT_Mod + else + InitInp%DBEMT_Mod = DBEMT_none + end if + InitInp%tau1_const = InputFileData%tau1_const + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + call BEMT_Init(InitInp, u, p%BEMT, x, xd, z, OtherState, p%AFI, y, m, Interval, InitOut, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (.not. equalRealNos(Interval, p%DT) ) & + call SetErrStat( ErrID_Fatal, "DTAero was changed in Init_BEMTmodule(); this is not allowed.", ErrStat2, ErrMsg2, RoutineName) + + !m%UseFrozenWake = .FALSE. !BJJ: set this in BEMT + + call Cleanup() + return + +contains + subroutine Cleanup() + call BEMT_DestroyInitInput( InitInp, ErrStat2, ErrMsg2 ) + call BEMT_DestroyInitOutput( InitOut, ErrStat2, ErrMsg2 ) + end subroutine Cleanup +END SUBROUTINE Init_BEMTmodule + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the FVW module from within AeroDyn. +SUBROUTINE Init_FVWmodule( InputFileData, u_AD, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + type(AD_InputFile), intent(in ) :: InputFileData !< All the data in the AeroDyn input file + type(AD_InputType), intent(inout) :: u_AD !< AD inputs - used for input mesh node positions (intent out for meshcopy) + type(FVW_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(AD_ParameterType), intent(inout) :: p !< Parameters ! intent out b/c we set the FVW parameters here + type(FVW_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(FVW_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(FVW_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(FVW_OtherStateType), intent( out) :: OtherState !< Initial other states + type(FVW_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(FVW_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + real(DbKi) :: Interval ! Coupling interval in seconds: the rate that + ! (1) FVW_UpdateStates() is called in loose coupling & + ! (2) FVW_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + type(FVW_InitInputType) :: InitInp ! Input data for initialization routine + type(FVW_InitOutputType) :: InitOut ! Output for initialization routine + + integer(intKi) :: j ! node index + integer(intKi) :: IB ! blade index + real(ReKi) :: tmp(3), tmp_sz_y, tmp_sz + real(ReKi) :: y_hat_disk(3) + real(ReKi) :: z_hat_disk(3) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Init_FVWmodule' + + ! note here that each blade is required to have the same number of nodes + + ErrStat = ErrID_None + ErrMsg = "" + + ! set initialization data here: + InitInp%FVWFileName = InputFileData%FVWFileName + InitInp%numBlades = p%numBlades + InitInp%numBladeNodes = p%numBlNds + InitInp%DTaero = p%DT ! NOTE: FVW can run a lower timestep internally + InitInp%KinVisc = p%KinVisc + InitInp%RootName = p%RootName(1:len_trim(p%RootName)-2) ! Removing "AD" + + ! NOTE: The following are not meshes + ! It's just the spanwise location. + ! Also, it is off compared to the initial position of the blade + ! Also, it's centered on the hub, but that's fine for now + call AllocAry(InitInp%Chord, InitInp%numBladeNodes,InitInp%numBlades,'chord', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%AFindx,InitInp%numBladeNodes,InitInp%numBlades,'AFindx',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zHub, InitInp%numBlades,'zHub', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zLocal,InitInp%numBladeNodes,InitInp%numBlades,'zLocal',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%rLocal,InitInp%numBladeNodes,InitInp%numBlades,'rLocal',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitInp%zTip, InitInp%numBlades,'zTip', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + + + ! Hub + do IB=1,p%numBlades + InitInp%zHub(IB) = TwoNorm( u_AD%BladeRootMotion(IB)%Position(:,1) - u_AD%HubMotion%Position(:,1) ) + if (EqualRealNos(InitInp%zHub(IB),0.0_ReKi) ) & + call SetErrStat( ErrID_Fatal, "zHub for blade "//trim(num2lstr(IB))//" is zero.", ErrStat, ErrMsg, RoutineName) + enddo + if (ErrStat >= AbortErrLev) then + call CleanUp() + RETURN + endif + + ! Distance along blade curve -- NOTE: this is an approximation. + do IB=1,p%numBlades + InitInp%zLocal(1,IB) = InitInp%zHub(IB) + TwoNorm( u_AD%BladeMotion(IB)%Position(:,1) - u_AD%BladeRootMotion(IB)%Position(:,1) ) + do j=2,p%NumBlNds + InitInp%zLocal(j,IB) = InitInp%zLocal(j-1,IB) + TwoNorm( u_AD%BladeMotion(IB)%Position(:,j) - u_AD%BladeMotion(IB)%Position(:,j-1) ) + end do !j=nodes + end do !IB=blades + + ! Blade tip curve distance + do IB=1,p%numBlades + InitInp%zTip(IB) = InitInp%zLocal(p%NumBlNds,IB) + end do !IB=blades + + ! Distance from blade to hub axis (includes hub radius) + y_hat_disk = u_AD%HubMotion%Orientation(2,:,1) + z_hat_disk = u_AD%HubMotion%Orientation(3,:,1) + do IB=1,p%numBlades + do j=1,p%NumBlNds + ! displaced position of the jth node in the kth blade relative to the hub: + tmp = u_AD%BladeMotion(IB)%Position(:,j) - u_AD%HubMotion%Position(:,1) + ! local radius (normalized distance from rotor centerline) + tmp_sz_y = dot_product( tmp, y_hat_disk )**2 + tmp_sz = dot_product( tmp, z_hat_disk )**2 + InitInp%rLocal(j,IB) = sqrt( tmp_sz + tmp_sz_y ) + end do !j=nodes + end do !IB=blades + + + ! Copy over chord information + do IB=1,p%numBlades + do j=1,p%NumBlNds + InitInp%Chord (j,IB) = InputFileData%BladeProps(IB)%BlChord(j) + InitInp%AFindx(j,IB) = InputFileData%BladeProps(IB)%BlAFID(j) + end do + end do + + ! Unsteady Aero Data + InitInp%UA_Flag = InputFileData%AFAeroMod == AFAeroMod_BL_unsteady + InitInp%UAMod = InputFileData%UAMod + InitInp%Flookup = InputFileData%Flookup + InitInp%a_s = InputFileData%SpdSound + + ! Copy the mesh over for InitInp to FVW. We would not need to copy this if we decided to break the Framework + ! by passing u_AD%BladeMotion directly into FVW_Init, but nothing is really gained by doing that. + ALLOCATE( InitInp%WingsMesh(p%NumBlades), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat ( ErrID_Fatal, 'Could not allocate InitInp%WingsMesh (meshes)', ErrStat,ErrMsg,RoutineName ) + RETURN + END IF + DO IB = 1, p%NumBlades + CALL MeshCopy ( SrcMesh = u_AD%BladeMotion(IB) & + ,DestMesh = InitInp%WingsMesh(IB) & + ,CtrlCode = MESH_COUSIN & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + ENDDO + + ! NOTE: not passing p%AFI at present. We are not storing it in FVW's parameters. + call FVW_Init(p%AFI, InitInp, u, p%FVW, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! set the size of the input and xd arrays for passing wind info to FVW. + if (ALLOCATED(m%r_wind)) then + call AllocAry(u_AD%InflowWakeVel, 3, size(m%r_wind,DIM=2), 'InflowWakeVel', ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + endif + + if (.not. equalRealNos(Interval, p%DT) ) & + call SetErrStat( ErrID_Fatal, "DTAero was changed in Init_FVWmodule(); this is not allowed yet.", ErrStat2, ErrMsg2, RoutineName) + +contains + subroutine Cleanup() + call FVW_DestroyInitInput( InitInp, ErrStat2, ErrMsg2 ) + call FVW_DestroyInitOutput( InitOut, ErrStat2, ErrMsg2 ) + end subroutine Cleanup +END SUBROUTINE Init_FVWmodule +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the tower loads for the AeroDyn TowerLoad output mesh. +SUBROUTINE ADTwr_CalcOutput(p, u, m, y, ErrStat, ErrMsg ) + + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(AD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + INTEGER(IntKi) :: j + real(ReKi) :: q + real(ReKi) :: V_rel(3) ! relative wind speed on a tower node + real(ReKi) :: VL(2) ! relative local x- and y-components of the wind speed on a tower node + real(ReKi) :: tmp(3) + + !integer(intKi) :: ErrStat2 + !character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'ADTwr_CalcOutput' + + + ErrStat = ErrID_None + ErrMsg = "" + + + do j=1,p%NumTwrNds + + V_rel = u%InflowOnTower(:,j) - u%TowerMotion%TranslationVel(:,j) ! relative wind speed at tower node + + tmp = u%TowerMotion%Orientation(1,:,j) + VL(1) = dot_product( V_Rel, tmp ) ! relative local x-component of wind speed of the jth node in the tower + tmp = u%TowerMotion%Orientation(2,:,j) + VL(2) = dot_product( V_Rel, tmp ) ! relative local y-component of wind speed of the jth node in the tower + + m%W_Twr(j) = TwoNorm( VL ) ! relative wind speed normal to the tower at node j + q = 0.5 * p%TwrCd(j) * p%AirDens * p%TwrDiam(j) * m%W_Twr(j) + + ! force per unit length of the jth node in the tower + tmp(1) = q * VL(1) + tmp(2) = q * VL(2) + tmp(3) = 0.0_ReKi + + y%TowerLoad%force(:,j) = matmul( tmp, u%TowerMotion%Orientation(:,:,j) ) ! note that I'm calculating the transpose here, which is okay because we have 1-d arrays + m%X_Twr(j) = tmp(1) + m%Y_Twr(j) = tmp(2) + + + ! moment per unit length of the jth node in the tower + y%TowerLoad%moment(:,j) = 0.0_ReKi + + end do + + +END SUBROUTINE ADTwr_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks for invalid inputs to the tower influence models. +SUBROUTINE CheckTwrInfl(u, ErrStat, ErrMsg ) + + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(reKi) :: ElemSize + real(reKi) :: tmp(3) + integer(intKi) :: j + character(*), parameter :: RoutineName = 'CheckTwrInfl' + + + ErrStat = ErrID_None + ErrMsg = "" + + !! the tower-influence models (tower potential flow and tower shadow) are valid only for small tower deflections; + !! so, first throw an error to avoid a division-by-zero error if any line2 elements on the tower mesh are colocated. + + do j = 2,u%TowerMotion%Nnodes + tmp = u%TowerMotion%Position(:,j ) + u%TowerMotion%TranslationDisp(:,j ) & + - u%TowerMotion%Position(:,j-1) - u%TowerMotion%TranslationDisp(:,j-1) + + ElemSize = TwoNorm(tmp) + if ( EqualRealNos(ElemSize,0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal, "Division by zero:Elements "//trim(num2lstr(j))//' and '//trim(num2lstr(j-1))//' are colocated.', ErrStat, ErrMsg, RoutineName ) + exit + end if + end do + + +END SUBROUTINE CheckTwrInfl +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates m%DisturbedInflow, the influence of tower shadow and/or potential flow on the inflow velocities +SUBROUTINE TwrInfl( p, u, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(ReKi) :: xbar ! local x^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: ybar ! local y^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: zbar ! local z^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: theta_tower_trans(3,3) ! transpose of local tower orientation expressed as a DCM + real(ReKi) :: TwrCd ! local tower drag coefficient + real(ReKi) :: TwrTI ! local tower TI (for Eames tower shadow model) + real(ReKi) :: W_tower ! local relative wind speed normal to the tower + + real(ReKi) :: BladeNodePosition(3) ! local blade node position + + + real(ReKi) :: u_TwrShadow ! axial velocity deficit fraction from tower shadow + real(ReKi) :: u_TwrPotent ! axial velocity deficit fraction from tower potential flow + real(ReKi) :: v_TwrPotent ! transverse velocity deficit fraction from tower potential flow + + real(ReKi) :: denom ! denominator + real(ReKi) :: exponential ! exponential term + real(ReKi) :: v(3) ! temp vector + + integer(IntKi) :: j, k ! loop counters for elements, blades + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'TwrInfl' + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! these models are valid for only small tower deflections; check for potential division-by-zero errors: + call CheckTwrInfl( u, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + do k = 1, p%NumBlades + do j = 1, u%BladeMotion(k)%NNodes + + ! for each line2-element node of the blade mesh, a nearest-neighbor line2 element or node of the tower + ! mesh is found in the deflected configuration, returning theta_tower, W_tower, xbar, ybar, zbar, and TowerCd: + + BladeNodePosition = u%BladeMotion(k)%Position(:,j) + u%BladeMotion(k)%TranslationDisp(:,j) + + call getLocalTowerProps(p, u, BladeNodePosition, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, m%TwrClrnc(j,k), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + + ! calculate tower influence: + if ( abs(zbar) < 1.0_ReKi .and. p%TwrPotent /= TwrPotent_none ) then + if ( p%TwrPotent == TwrPotent_baseline ) then + + denom = (xbar**2 + ybar**2)**2 + + u_TwrPotent = ( -1.0*xbar**2 + ybar**2 ) / denom + v_TwrPotent = ( -2.0*xbar * ybar ) / denom + + elseif (p%TwrPotent == TwrPotent_Bak) then + + xbar = xbar + 0.1 + + denom = (xbar**2 + ybar**2)**2 + u_TwrPotent = ( -1.0*xbar**2 + ybar**2 ) / denom + v_TwrPotent = ( -2.0*xbar * ybar ) / denom + + denom = TwoPi*(xbar**2 + ybar**2) + u_TwrPotent = u_TwrPotent + TwrCd*xbar / denom + v_TwrPotent = v_TwrPotent + TwrCd*ybar / denom + + end if + else + u_TwrPotent = 0.0_ReKi + v_TwrPotent = 0.0_ReKi + end if + + u_TwrShadow = 0.0_ReKi + select case (p%TwrShadow) + case (TwrShadow_Powles) + if ( xbar > 0.0_ReKi .and. abs(zbar) < 1.0_ReKi) then + denom = sqrt( sqrt( xbar**2 + ybar**2 ) ) + if ( abs(ybar) < denom ) then + u_TwrShadow = -TwrCd / denom * cos( PiBy2*ybar / denom )**2 + end if + end if + case (TwrShadow_Eames) + if ( xbar > 0.0_ReKi .and. abs(zbar) < 1.0_ReKi) then + exponential = ( ybar / (TwrTI * xbar) )**2 + denom = TwrTI * xbar * sqrt( TwoPi ) + u_TwrShadow = -TwrCd / denom * exp ( -0.5_ReKi * exponential ) + end if + end select + + v(1) = (u_TwrPotent + u_TwrShadow)*W_tower + v(2) = v_TwrPotent*W_tower + v(3) = 0.0_ReKi + + m%DisturbedInflow(:,j,k) = u%InflowOnBlade(:,j,k) + matmul( theta_tower_trans, v ) + + end do !j=NumBlNds + end do ! NumBlades + + +END SUBROUTINE TwrInfl +!---------------------------------------------------------------------------------------------------------------------------------- +!> Calculate the tower influence on a array of points `Positions` (3xn) +!! The subroutine has side effecs and modifies the inflow +!! Relies heavily (i.e. unfortunate copy pasting), on TwrInfl +SUBROUTINE TwrInflArray( p, u, m, Positions, Inflow, ErrStat, ErrMsg ) + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + real(ReKi), dimension(:,:), INTENT(IN ) :: Positions !< Positions where tower influence is to be computed + real(ReKi), dimension(:,:), INTENT(INOUT) :: Inflow !< Undisturbed inflow (in) -> disturbed inflow (out) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + real(ReKi) :: xbar ! local x^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: ybar ! local y^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: zbar ! local z^ component of r_TowerBlade (distance from tower to blade) normalized by tower radius + real(ReKi) :: theta_tower_trans(3,3) ! transpose of local tower orientation expressed as a DCM + real(ReKi) :: TwrCd ! local tower drag coefficient + real(ReKi) :: TwrTI ! local tower TI (for Eames tower shadow model) + real(ReKi) :: W_tower ! local relative wind speed normal to the tower + real(ReKi) :: Pos(3) ! current point + real(ReKi) :: u_TwrShadow ! axial velocity deficit fraction from tower shadow + real(ReKi) :: u_TwrPotent ! axial velocity deficit fraction from tower potential flow + real(ReKi) :: v_TwrPotent ! transverse velocity deficit fraction from tower potential flow + real(ReKi) :: denom ! denominator + real(ReKi) :: exponential ! exponential term + real(ReKi) :: v(3) ! temp vector + integer(IntKi) :: i ! loop counters for points + real(ReKi) :: TwrClrnc ! local tower clearance + real(ReKi) :: r_TowerBlade(3) ! distance vector from tower to blade + real(ReKi) :: TwrDiam ! local tower diameter + logical :: found + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'TwrInflArray' + ErrStat = ErrID_None + ErrMsg = "" + + ! these models are valid for only small tower deflections; check for potential division-by-zero errors: + call CheckTwrInfl( u, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); if (ErrStat >= AbortErrLev) return + + !$OMP PARALLEL default(shared) + !$OMP do private(i,Pos,r_TowerBlade,theta_tower_trans,W_tower,xbar,ybar,zbar,TwrCd,TwrTI,TwrClrnc,TwrDiam,found,denom,u_TwrPotent,v_TwrPotent,u_TwrShadow,v) schedule(runtime) + do i = 1, size(Positions,2) + Pos=Positions(1:3,i) + + ! Find nearest line2 element or node of the tower (see getLocalTowerProps) + ! values are found for the deflected tower, returning theta_tower, W_tower, xbar, ybar, zbar, and TowerCd: + ! option 1: nearest line2 element + call TwrInfl_NearestLine2Element(p, u, Pos, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam, found) + if ( .not. found) then + ! option 2: nearest node + call TwrInfl_NearestPoint(p, u, Pos, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam) + end if + TwrClrnc = TwoNorm(r_TowerBlade) - 0.5_ReKi*TwrDiam + + if ( TwrClrnc>20*TwrDiam) then + ! Far away, we skip the computation and keep undisturbed inflow + elseif ( TwrClrnc<=0.01_ReKi*TwrDiam) then + ! Inside the tower, or very close, (will happen for vortex elements) we keep undisturbed inflow + ! We don't want to reach the stagnation points + else + ! calculate tower influence: + if ( abs(zbar) < 1.0_ReKi .and. p%TwrPotent /= TwrPotent_none ) then + + if ( p%TwrPotent == TwrPotent_baseline ) then + denom = (xbar**2 + ybar**2)**2 + u_TwrPotent = ( -1.0*xbar**2 + ybar**2 ) / denom + v_TwrPotent = ( -2.0*xbar * ybar ) / denom + + elseif (p%TwrPotent == TwrPotent_Bak) then + xbar = xbar + 0.1 + denom = (xbar**2 + ybar**2)**2 + u_TwrPotent = ( -1.0*xbar**2 + ybar**2 ) / denom + v_TwrPotent = ( -2.0*xbar * ybar ) / denom + denom = TwoPi*(xbar**2 + ybar**2) + u_TwrPotent = u_TwrPotent + TwrCd*xbar / denom + v_TwrPotent = v_TwrPotent + TwrCd*ybar / denom + + end if + else + u_TwrPotent = 0.0_ReKi + v_TwrPotent = 0.0_ReKi + end if + + u_TwrShadow = 0.0_ReKi + select case (p%TwrShadow) + case (TwrShadow_Powles) + if ( xbar > 0.0_ReKi .and. abs(zbar) < 1.0_ReKi) then + denom = sqrt( sqrt( xbar**2 + ybar**2 ) ) + if ( abs(ybar) < denom ) then + u_TwrShadow = -TwrCd / denom * cos( PiBy2*ybar / denom )**2 + end if + end if + case (TwrShadow_Eames) + if ( xbar > 0.0_ReKi .and. abs(zbar) < 1.0_ReKi) then + exponential = ( ybar / (TwrTI * xbar) )**2 + denom = TwrTI * xbar * sqrt( TwoPi ) + u_TwrShadow = -TwrCd / denom * exp ( -0.5_ReKi * exponential ) + end if + end select + + v(1) = (u_TwrPotent + u_TwrShadow)*W_tower + v(2) = v_TwrPotent*W_tower + v(3) = 0.0_ReKi + + Inflow(1:3,i) = Inflow(1:3,i) + matmul( theta_tower_trans, v ) + endif ! Check if point far away or in tower + enddo ! loop on points + !$OMP END DO + !$OMP END PARALLEL +END SUBROUTINE TwrInflArray +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the tower constants necessary to compute the tower influence. +!! if u%TowerMotion does not have any nodes there will be serious problems. I assume that has been checked earlier. +SUBROUTINE getLocalTowerProps(p, u, BladeNodePosition, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrClrnc, ErrStat, ErrMsg) +!.................................................................................................................................. + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(ReKi) ,INTENT(IN ) :: BladeNodePosition(3) !< local blade node position + REAL(ReKi) ,INTENT( OUT) :: theta_tower_trans(3,3) !< transpose of local tower orientation expressed as a DCM + REAL(ReKi) ,INTENT( OUT) :: W_tower !< local relative wind speed normal to the tower + REAL(ReKi) ,INTENT( OUT) :: xbar !< local x^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: ybar !< local y^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: zbar !< local z^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: TwrCd !< local tower drag coefficient + REAL(ReKi) ,INTENT( OUT) :: TwrTI !< local tower TI (for Eames tower shadow model) + REAL(ReKi) ,INTENT( OUT) :: TwrClrnc !< tower clearance for potential output + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(ReKi) :: r_TowerBlade(3) ! distance vector from tower to blade + real(ReKi) :: TwrDiam ! local tower diameter + logical :: found + character(*), parameter :: RoutineName = 'getLocalTowerProps' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! .............................................. + ! option 1: nearest line2 element + ! .............................................. + call TwrInfl_NearestLine2Element(p, u, BladeNodePosition, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam, found) + + if ( .not. found) then + ! .............................................. + ! option 2: nearest node + ! .............................................. + call TwrInfl_NearestPoint(p, u, BladeNodePosition, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam) + + end if + + TwrClrnc = TwoNorm(r_TowerBlade) - 0.5_ReKi*TwrDiam + if ( TwrClrnc <= 0.0_ReKi ) then + call SetErrStat(ErrID_Fatal, "Tower strike.", ErrStat, ErrMsg, RoutineName) + end if + + +END SUBROUTINE getLocalTowerProps +!---------------------------------------------------------------------------------------------------------------------------------- +!> Option 1: Find the nearest-neighbor line2 element of the tower mesh for which the blade line2-element node projects orthogonally onto +!! the tower line2-element domain (following an approach similar to the line2_to_line2 mapping search for motion and scalar quantities). +!! That is, for each node of the blade mesh, an orthogonal projection is made onto all possible Line2 elements of the tower mesh and +!! the line2 element of the tower mesh that is the minimum distance away is found. +!! Adapted from modmesh_mapping::createmapping_projecttoline2() +SUBROUTINE TwrInfl_NearestLine2Element(p, u, BladeNodePosition, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam, found) +!.................................................................................................................................. + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(ReKi) ,INTENT(IN ) :: BladeNodePosition(3) !< local blade node position + REAL(ReKi) ,INTENT( OUT) :: r_TowerBlade(3) !< distance vector from tower to blade + REAL(ReKi) ,INTENT( OUT) :: theta_tower_trans(3,3) !< transpose of local tower orientation expressed as a DCM + REAL(ReKi) ,INTENT( OUT) :: W_tower !< local relative wind speed normal to the tower + REAL(ReKi) ,INTENT( OUT) :: xbar !< local x^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: ybar !< local y^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: zbar !< local z^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: TwrCd !< local tower drag coefficient + REAL(ReKi) ,INTENT( OUT) :: TwrTI !< local tower TI (Eames tower shadow model) + REAL(ReKi) ,INTENT( OUT) :: TwrDiam !< local tower diameter + logical ,INTENT( OUT) :: found !< whether a mapping was found with this option + + ! local variables + REAL(ReKi) :: denom + REAL(ReKi) :: dist + REAL(ReKi) :: min_dist + REAL(ReKi) :: elem_position, elem_position2 + REAL(SiKi) :: elem_position_SiKi + + REAL(ReKi) :: p1(3), p2(3) ! position vectors for nodes on tower line 2 element + + REAL(ReKi) :: V_rel_tower(3) + + REAL(ReKi) :: n1_n2_vector(3) ! vector going from node 1 to node 2 in Line2 element + REAL(ReKi) :: n1_Point_vector(3) ! vector going from node 1 in Line 2 element to Destination Point + REAL(ReKi) :: tmp(3) ! temporary vector for cross product calculation + + INTEGER(IntKi) :: jElem ! do-loop counter for elements on tower mesh + + INTEGER(IntKi) :: n1, n2 ! nodes associated with an element + + LOGICAL :: on_element + + + found = .false. + min_dist = HUGE(min_dist) + + do jElem = 1, u%TowerMotion%ElemTable(ELEMENT_LINE2)%nelem ! number of elements on TowerMesh + ! grab node numbers associated with the jElem_th element + n1 = u%TowerMotion%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(1) + n2 = u%TowerMotion%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(2) + + p1 = u%TowerMotion%Position(:,n1) + u%TowerMotion%TranslationDisp(:,n1) + p2 = u%TowerMotion%Position(:,n2) + u%TowerMotion%TranslationDisp(:,n2) + + ! Calculate vectors used in projection operation + n1_n2_vector = p2 - p1 + n1_Point_vector = BladeNodePosition - p1 + + denom = DOT_PRODUCT( n1_n2_vector, n1_n2_vector ) ! we've already checked that these aren't zero + + ! project point onto line defined by n1 and n2 + + elem_position = DOT_PRODUCT(n1_n2_vector,n1_Point_vector) / denom + + ! note: i forumlated it this way because Fortran doesn't necessarially do shortcutting and I don't want to call EqualRealNos if we don't need it: + if ( elem_position .ge. 0.0_ReKi .and. elem_position .le. 1.0_ReKi ) then !we're ON the element (between the two nodes) + on_element = .true. + else + elem_position_SiKi = REAL( elem_position, SiKi ) + if (EqualRealNos( elem_position_SiKi, 1.0_SiKi )) then !we're ON the element (at a node) + on_element = .true. + elem_position = 1.0_ReKi + elseif (EqualRealNos( elem_position_SiKi, 0.0_SiKi )) then !we're ON the element (at a node) + on_element = .true. + elem_position = 0.0_ReKi + else !we're not on the element + on_element = .false. + end if + + end if + + if (on_element) then + + ! calculate distance between point and line (note: this is actually the distance squared); + ! will only store information once we have determined the closest element + elem_position2 = 1.0_ReKi - elem_position + + r_TowerBlade = BladeNodePosition - elem_position2*p1 - elem_position*p2 + dist = dot_product( r_TowerBlade, r_TowerBlade ) + + if (dist .lt. min_dist) then + found = .true. + min_dist = dist + + V_rel_tower = ( u%InflowOnTower(:,n1) - u%TowerMotion%TranslationVel(:,n1) ) * elem_position2 & + + ( u%InflowOnTower(:,n2) - u%TowerMotion%TranslationVel(:,n2) ) * elem_position + + TwrDiam = elem_position2*p%TwrDiam(n1) + elem_position*p%TwrDiam(n2) + TwrCd = elem_position2*p%TwrCd( n1) + elem_position*p%TwrCd( n2) + TwrTI = elem_position2*p%TwrTI( n1) + elem_position*p%TwrTI( n2) + + + ! z_hat + theta_tower_trans(:,3) = n1_n2_vector / sqrt( denom ) ! = n1_n2_vector / twoNorm( n1_n2_vector ) + + tmp = V_rel_tower - dot_product(V_rel_tower,theta_tower_trans(:,3)) * theta_tower_trans(:,3) + denom = TwoNorm( tmp ) + if (.not. EqualRealNos( denom, 0.0_ReKi ) ) then + ! x_hat + theta_tower_trans(:,1) = tmp / denom + + ! y_hat + tmp = cross_product( theta_tower_trans(:,3), V_rel_tower ) + theta_tower_trans(:,2) = tmp / denom + + W_tower = dot_product( V_rel_tower,theta_tower_trans(:,1) ) + xbar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,1) ) + ybar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,2) ) + zbar = 0.0_ReKi + + else + ! there is no tower influence because dot_product(V_rel_tower,x_hat) = 0 + ! thus, we don't need to set the other values (except we don't want the sum of xbar^2 and ybar^2 to be 0) + theta_tower_trans = 0.0_ReKi + W_tower = 0.0_ReKi + xbar = 1.0_ReKi + ybar = 0.0_ReKi + zbar = 0.0_ReKi + end if + + + end if !the point is closest to this line2 element + + end if + + end do !jElem + +END SUBROUTINE TwrInfl_NearestLine2Element +!---------------------------------------------------------------------------------------------------------------------------------- +!> Option 2: used when the blade node does not orthogonally intersect a tower element. +!! Find the nearest-neighbor node in the tower Line2-element domain (following an approach similar to the point_to_point mapping +!! search for motion and scalar quantities). That is, for each node of the blade mesh, the node of the tower mesh that is the minimum +!! distance away is found. +SUBROUTINE TwrInfl_NearestPoint(p, u, BladeNodePosition, r_TowerBlade, theta_tower_trans, W_tower, xbar, ybar, zbar, TwrCd, TwrTI, TwrDiam) +!.................................................................................................................................. + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(ReKi) ,INTENT(IN ) :: BladeNodePosition(3) !< local blade node position + REAL(ReKi) ,INTENT( OUT) :: r_TowerBlade(3) !< distance vector from tower to blade + REAL(ReKi) ,INTENT( OUT) :: theta_tower_trans(3,3) !< transpose of local tower orientation expressed as a DCM + REAL(ReKi) ,INTENT( OUT) :: W_tower !< local relative wind speed normal to the tower + REAL(ReKi) ,INTENT( OUT) :: xbar !< local x^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: ybar !< local y^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: zbar !< local z^ component of r_TowerBlade normalized by tower radius + REAL(ReKi) ,INTENT( OUT) :: TwrCd !< local tower drag coefficient + REAL(ReKi) ,INTENT( OUT) :: TwrTI !< local tower TI (for Eeames tower shadow model) + REAL(ReKi) ,INTENT( OUT) :: TwrDiam !< local tower diameter + + ! local variables + REAL(ReKi) :: denom + REAL(ReKi) :: dist + REAL(ReKi) :: min_dist + REAL(ReKi) :: cosTaper + + REAL(ReKi) :: p1(3) ! position vectors for nodes on tower + REAL(ReKi) :: V_rel_tower(3) + + REAL(ReKi) :: tmp(3) ! temporary vector for cross product calculation + + INTEGER(IntKi) :: n1 ! node + INTEGER(IntKi) :: node_with_min_distance + + + + !................. + ! find the closest node + !................. + + min_dist = HUGE(min_dist) + node_with_min_distance = 0 + + do n1 = 1, u%TowerMotion%NNodes ! number of nodes on TowerMesh + + p1 = u%TowerMotion%Position(:,n1) + u%TowerMotion%TranslationDisp(:,n1) + + ! calculate distance between points (note: this is actually the distance squared); + ! will only store information once we have determined the closest node + r_TowerBlade = BladeNodePosition - p1 + dist = dot_product( r_TowerBlade, r_TowerBlade ) + + if (dist .lt. min_dist) then + min_dist = dist + node_with_min_distance = n1 + + end if !the point is (so far) closest to this blade node + + end do !n1 + + !................. + ! calculate the values to be returned: + !.................. + if (node_with_min_distance == 0) then + node_with_min_distance = 1 + if (NWTC_VerboseLevel == NWTC_Verbose) call WrScr( 'AD:TwrInfl_NearestPoint:Error finding minimum distance. Positions may be invalid.' ) + end if + + n1 = node_with_min_distance + + r_TowerBlade = BladeNodePosition - u%TowerMotion%Position(:,n1) - u%TowerMotion%TranslationDisp(:,n1) + V_rel_tower = u%InflowOnTower(:,n1) - u%TowerMotion%TranslationVel(:,n1) + TwrDiam = p%TwrDiam(n1) + TwrCd = p%TwrCd( n1) + TwrTI = p%TwrTI( n1) + + ! z_hat + theta_tower_trans(:,3) = u%TowerMotion%Orientation(3,:,n1) + + tmp = V_rel_tower - dot_product(V_rel_tower,theta_tower_trans(:,3)) * theta_tower_trans(:,3) + denom = TwoNorm( tmp ) + + if (.not. EqualRealNos( denom, 0.0_ReKi ) ) then + + ! x_hat + theta_tower_trans(:,1) = tmp / denom + + ! y_hat + tmp = cross_product( theta_tower_trans(:,3), V_rel_tower ) + theta_tower_trans(:,2) = tmp / denom + + W_tower = dot_product( V_rel_tower,theta_tower_trans(:,1) ) + + if ( n1 == 1 .or. n1 == u%TowerMotion%NNodes) then + ! option 2b + zbar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,3) ) + if (abs(zbar) < 1) then + cosTaper = cos( PiBy2*zbar ) + xbar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,1) ) / cosTaper + ybar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,2) ) / cosTaper + else ! we check that zbar < 1 before using xbar and ybar later, but I'm going to set them here anyway: + xbar = 1.0_ReKi + ybar = 0.0_ReKi + end if + else + ! option 2a + xbar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,1) ) + ybar = 2.0/TwrDiam * dot_product( r_TowerBlade, theta_tower_trans(:,2) ) + zbar = 0.0_ReKi + end if + + else + + ! there is no tower influence because W_tower = dot_product(V_rel_tower,x_hat) = 0 + ! thus, we don't need to set the other values (except we don't want the sum of xbar^2 and ybar^2 to be 0) + W_tower = 0.0_ReKi + theta_tower_trans = 0.0_ReKi + xbar = 1.0_ReKi + ybar = 0.0_ReKi + zbar = 0.0_ReKi + + end if + +END SUBROUTINE TwrInfl_NearestPoint +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in AD_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 AD_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(AD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(AD_OutputType), INTENT(INOUT) :: 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(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdu(:,:) !< Partial derivatives of output functions (Y) with respect + !! to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + ! local variables + TYPE(AD_OutputType) :: y_p + TYPE(AD_OutputType) :: y_m + TYPE(AD_ContinuousStateType) :: x_p + TYPE(AD_ContinuousStateType) :: x_m + TYPE(AD_ContinuousStateType) :: x_init + TYPE(AD_ConstraintStateType) :: z_copy + TYPE(AD_OtherStateType) :: OtherState_copy + TYPE(AD_OtherStateType) :: OtherState_init + TYPE(AD_InputType) :: u_perturb + REAL(R8Ki) :: delta_p, delta_m ! delta change in input + INTEGER(IntKi) :: i + + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AD_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + ! get OP values here (i.e., set inputs for BEMT): + if ( p%FrozenWake ) then + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! compare m%BEMT_y arguments with call to BEMT_CalcOutput + call computeFrozenWake(m%BEMT_u(indx), p%BEMT, m%BEMT_y, m%BEMT ) + m%BEMT%UseFrozenWake = .true. + end if + + + call AD_CopyContState( x, x_init, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOtherState( OtherState, OtherState_init, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! initialize x_init so that we get accurrate values for first step + if (.not. OtherState%BEMT%nodesInitialized ) then + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call BEMT_InitStates(t, m%BEMT_u(indx), p%BEMT, x_init%BEMT, xd%BEMT, z%BEMT, OtherState_init%BEMT, m%BEMT, p%AFI, ErrStat2, ErrMsg2 ) ! changes values only if states haven't been initialized + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + + ! make a copy of the inputs to perturb + call AD_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + IF ( PRESENT( dYdu ) ) THEN + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate dYdu + if (.not. allocated(dYdu) ) then + call AllocAry(dYdu,p%Jac_ny, size(p%Jac_u_indx,1),'dYdu', ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call AD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! make a copy of the states to perturb + call AD_CopyConstrState( z, z_copy, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOtherState( OtherState_init, OtherState_copy, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta_p u + call AD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, 1, u_perturb, delta_p ) + + call AD_CopyConstrState( z, z_copy, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOtherState( OtherState_init, OtherState_copy, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get updated z%phi values: + !call AD_UpdateStates( t, 1, (/u_perturb/), (/t/), p, x_copy, xd_copy, z_copy, OtherState_copy, m, errStat2, errMsg2 ) + ! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + !bjj: this is what we want to do instead of the overkill of calling AD_UpdateStates + call SetInputs(p, u_perturb, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call UpdatePhi( m%BEMT_u(indx), p%BEMT, z_copy%BEMT%phi, p%AFI, m%BEMT, OtherState_copy%BEMT%ValidPhi, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! compute y at u_op + delta_p u + call AD_CalcOutput( t, u_perturb, p, x_init, xd, z_copy, OtherState_copy, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get u_op - delta_m u + call AD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, -1, u_perturb, delta_m ) + + call AD_CopyConstrState( z, z_copy, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOtherState( OtherState, OtherState_copy, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get updated z%phi values: + !call AD_UpdateStates( t, 1, (/u_perturb/), (/t/), p, x_copy, xd_copy, z_copy, OtherState_copy, m, errStat2, errMsg2 ) + ! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SetInputs(p, u_perturb, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call UpdatePhi( m%BEMT_u(indx), p%BEMT, z_copy%BEMT%phi, p%AFI, m%BEMT, OtherState_copy%BEMT%ValidPhi, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! compute y at u_op - delta_m u + call AD_CalcOutput( t, u_perturb, p, x_init, xd, z_copy, OtherState_copy, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta_p, delta_m, dYdu(:,i) ) + + end do + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + END IF + + IF ( PRESENT( dXdu ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate dXdu if necessary + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, size(p%dx), size(p%Jac_u_indx,1), 'dXdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta u + call AD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, 1, u_perturb, delta_p ) + + ! compute x at u_op + delta u + ! note that this routine updates z%phi instead of using the actual state value, so we don't need to call UpdateStates/UpdatePhi here to get z_op + delta_z: + call AD_CalcContStateDeriv( t, u_perturb, p, x_init, xd, z, OtherState_init, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get u_op - delta u + call AD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, -1, u_perturb, delta_m ) + + ! compute x at u_op - delta u + ! note that this routine updates z%phi instead of using the actual state value, so we don't need to call UpdateStates here to get z_op + delta_z: + call AD_CalcContStateDeriv( t, u_perturb, p, x_init, xd, z, OtherState_init, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! get central difference: + call Compute_dX( p, x_p, x_m, delta_p, delta_m, dXdu(:,i) ) + + end do + + call AD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call AD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + END IF + + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF + + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + call cleanup() +contains + subroutine cleanup() + m%BEMT%UseFrozenWake = .false. + + call AD_DestroyOutput( y_p, ErrStat2, ErrMsg2) + call AD_DestroyOutput( y_m, ErrStat2, ErrMsg2) + call AD_DestroyContState( x_p, ErrStat2, ErrMsg2) + call AD_DestroyContState( x_m, ErrStat2, ErrMsg2) + call AD_DestroyContState( x_init, ErrStat2, ErrMsg2) + call AD_DestroyConstrState( z_copy, ErrStat2, ErrMsg2) + call AD_DestroyOtherState( OtherState_copy, ErrStat2, ErrMsg2) + call AD_DestroyOtherState( OtherState_init, ErrStat2, ErrMsg2) + + call AD_DestroyInput( u_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE AD_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 AD_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(AD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(AD_OutputType), INTENT(INOUT) :: 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(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + 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] + + ! local variables + TYPE(AD_OutputType) :: y_p + TYPE(AD_OutputType) :: y_m + TYPE(AD_ContinuousStateType) :: x_p + TYPE(AD_ContinuousStateType) :: x_m + TYPE(AD_ContinuousStateType) :: x_perturb + TYPE(AD_ContinuousStateType) :: x_init + TYPE(AD_OtherStateType) :: OtherState_init + REAL(R8Ki) :: delta_p, delta_m ! delta change in state + INTEGER(IntKi) :: i, k + + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AD_JacobianPContState' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + if ( p%FrozenWake ) then + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! compare arguments with call to BEMT_CalcOutput + call computeFrozenWake(m%BEMT_u(indx), p%BEMT, m%BEMT_y, m%BEMT ) + m%BEMT%UseFrozenWake = .true. + end if + + + call AD_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call AD_CopyContState( x, x_init, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOtherState( OtherState, OtherState_init, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! initialize x_init so that we get accurrate values for + if (.not. OtherState%BEMT%nodesInitialized ) then + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call BEMT_InitStates(t, m%BEMT_u(indx), p%BEMT, x_init%BEMT, xd%BEMT, z%BEMT, OtherState_init%BEMT, m%BEMT, p%AFI, ErrStat2, ErrMsg2 ) ! changes values only if states haven't been initialized + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + + IF ( PRESENT( dYdx ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + + ! allocate dYdx if necessary + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%Jac_ny, size(p%dx), 'dYdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call AD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do i=1,size(p%dx) + + ! get x_op + delta_p x + call AD_CopyContState( x_init, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_x( p, i, 1, x_perturb, delta_p ) + + + ! compute y at x_op + delta_p x + ! NOTE: z_op is the same as z because x_perturb does not affect the values of phi, thus I am not updating the states or calling UpdatePhi to get z_perturb. + call AD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState_init, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get x_op - delta_m x + call AD_CopyContState( x_init, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_x( p, i, -1, x_perturb, delta_m ) + + ! compute y at x_op - delta_m x + ! NOTE: z_op is the same as z because x_perturb does not affect the values of phi, thus I am not updating the states or calling UpdatePhi to get z_perturb. + call AD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState_init, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta_p, delta_m, dYdx(:,i) ) + + end do + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call AD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call AD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + 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 + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate dXdx if necessary + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, size(p%dx), size(p%dx), 'dXdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + do i=1,size(p%dx,1) + + ! get x_op + delta x + call AD_CopyContState( x_init, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_x( p, i, 1, x_perturb, delta_p ) + + ! compute X at x_op + delta x + ! NOTE: z_op is the same as z because x_perturb does not affect the values of phi, thus I am not updating the states or calling UpdatePhi to get z_perturb. + call AD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState_init, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get x_op - delta x + call AD_CopyContState( x_init, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_x( p, i, -1, x_perturb, delta_m ) + + ! compute x at u_op - delta u + ! NOTE: z_op is the same as z because x_perturb does not affect the values of phi, thus I am not updating the states or calling UpdatePhi to get z_perturb. + call AD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState_init, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! get central difference: + call Compute_dX( p, x_p, x_m, delta_p, delta_m, dXdx(:,i) ) + + end do + + call AD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call AD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + 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 + + call cleanup() +contains + subroutine cleanup() + m%BEMT%UseFrozenWake = .false. + + call AD_DestroyOutput( y_p, ErrStat2, ErrMsg2) + call AD_DestroyOutput( y_m, ErrStat2, ErrMsg2) + call AD_DestroyContState( x_p, ErrStat2, ErrMsg2) + call AD_DestroyContState( x_m, ErrStat2, ErrMsg2) + + call AD_DestroyContState( x_perturb, ErrStat2, ErrMsg2 ) + call AD_DestroyContState( x_init, ErrStat2, ErrMsg2 ) + call AD_DestroyOtherState( OtherState_init, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE AD_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 AD_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(AD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(AD_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(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + 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 AD_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 AD_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(AD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(AD_OutputType), INTENT(INOUT) :: 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(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + 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] + + ! local variables + TYPE(AD_OutputType) :: y_p + TYPE(AD_OutputType) :: y_m + TYPE(AD_ConstraintStateType) :: Z_p + TYPE(AD_ConstraintStateType) :: Z_m + TYPE(AD_ConstraintStateType) :: z_perturb + REAL(R8Ki) :: delta_p, delta_m ! delta change in state + INTEGER(IntKi) :: i, j, k, n, k2, j2 + + integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt + integer, parameter :: op_indx = 2 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt or the input at OP + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'AD_JacobianPConstrState' + + + ! local variables + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + ! get OP values here: + !call AD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ) ! (bjj: is this necessary? if not, still need to get BEMT inputs) + call SetInputs(p, u, m, indx, errStat2, errMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call BEMT_CopyInput( m%BEMT_u(indx), m%BEMT_u(op_indx), MESH_UPDATECOPY, ErrStat2, ErrMsg2) ! copy the BEMT OP inputs to a temporary location that won't be overwritten + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + if ( p%FrozenWake ) then + ! compare arguments with call to BEMT_CalcOutput + call computeFrozenWake(m%BEMT_u(op_indx), p%BEMT, m%BEMT_y, m%BEMT ) + m%BEMT%UseFrozenWake = .true. + end if + + + ! make a copy of the constraint states to perturb + call AD_CopyConstrState( z, z_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + 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 + if (.not. allocated(dYdz) ) then + call AllocAry(dYdz,p%Jac_ny, size(z%BEMT%phi),'dYdz', ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call AD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + do k=1,p%NumBlades ! size(z%BEMT%Phi,2) + do j=1,p%NumBlNds ! size(z%BEMT%Phi,1) + i = (k-1)*p%NumBlNds + j + + ! need a check if F = 0 for this case: + + if ( p%BEMT%FixedInductions(j,k) ) then + ! F is zero, we we need to skip this perturbation + dYdz(:,i) = 0.0_ReKi + else + + call Get_phi_perturbations(p%BEMT, m%BEMT, z%BEMT%phi(j,k), delta_p, delta_m) + + ! get z_op + delta_p z + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) + delta_p + + ! compute y at z_op + delta_p z + call AD_CalcOutput( t, u, p, x, xd, z_perturb, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get z_op - delta_m z + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) - delta_m + + ! compute y at z_op - delta_m z + call AD_CalcOutput( t, u, p, x, xd, z_perturb, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta_p, delta_m, dYdz(:,i) ) + + + ! put z_perturb back (for next iteration): + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) + end if + + end do + end do + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call AD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call AD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + END IF + + IF ( PRESENT( dXdz ) ) THEN + if (allocated(dXdz)) deallocate(dXdz) + END IF + + IF ( PRESENT( dXddz ) ) THEN + if (allocated(dXddz)) deallocate(dXddz) + END IF + + IF ( PRESENT(dZdz) ) THEN + + call CheckLinearizationInput(p%BEMT, m%BEMT_u(op_indx), z%BEMT, m%BEMT, OtherState%BEMT, ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! Calculate the partial derivative of the constraint state functions (Z) with respect to the constraint states (z) here: + + ! allocate and set dZdz + if (.not. allocated(dZdz)) then + call AllocAry(dZdz,size(z%BEMT%phi), size(z%BEMT%phi),'dZdz', ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + call AD_CopyConstrState( z, z_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + + do k=1,p%NumBlades ! size(z%BEMT%Phi,2) + do j=1,p%NumBlNds ! size(z%BEMT%Phi,1) + i = (k-1)*p%NumBlNds + j + + if ( p%BEMT%FixedInductions(j,k) ) then + ! F is zero, we we need to skip this perturbation + dZdz(:,i) = 0.0_ReKi + dZdz(i,i) = 1.0_ReKi + else + + call Get_phi_perturbations(p%BEMT, m%BEMT, z%BEMT%phi(j,k), delta_p, delta_m) + + ! get z_op + delta_p z + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) + delta_p + + ! compute z_p at z_op + delta_p z + call AD_CalcConstrStateResidual( t, u, p, x, xd, z_perturb, OtherState, m, z_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get z_op - delta_m z + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) - delta_m + + ! compute z_m at u_op - delta_m u + call AD_CalcConstrStateResidual( t, u, p, x, xd, z_perturb, OtherState, m, z_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! get central difference: + + do k2=1,p%NumBlades ! size(z%BEMT%Phi,2) + do j2=1,p%NumBlNds ! size(z%BEMT%Phi,1) + n = (k2-1)*p%NumBlNds + j2 + dZdz(n,i) = z_p%BEMT%Phi(j2,k2) - z_m%BEMT%Phi(j2,k2) + end do + end do + + dZdz(:,i) = dZdz(:,i) / (delta_p + delta_m) + + ! put z_perturb back (for next iteration): + z_perturb%BEMT%phi(j,k) = z%BEMT%phi(j,k) + + end if + + end do + end do + + call AD_DestroyConstrState( z_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call AD_DestroyConstrState( z_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + END IF + + call cleanup() + +contains + subroutine cleanup() + m%BEMT%UseFrozenWake = .false. + + call AD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call AD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call AD_DestroyConstrState( z_p, ErrStat2, ErrMsg2 ) + call AD_DestroyConstrState( z_m, ErrStat2, ErrMsg2 ) + call AD_DestroyConstrState( z_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE AD_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE AD_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(AD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(AD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(AD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(AD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(AD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(AD_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(AD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + 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, k + INTEGER(IntKi) :: nu + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_GetOP' + LOGICAL :: FieldMask(FIELDMASK_SIZE) + TYPE(AD_ContinuousStateType) :: dxdt + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( u_op ) ) THEN + + nu = size(p%Jac_u_indx,1) + u%TowerMotion%NNodes * 6 & ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM + + u%hubMotion%NNodes * 6 ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM + do i=1,p%NumBlades + nu = nu + u%BladeMotion(i)%NNodes * 6 & ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM + + u%BladeRootMotion(i)%NNodes * 6 ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM + end do + + if (.not. allocated(u_op)) then + call AllocAry(u_op, nu, 'u_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + index = 1 + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + call PackMotionMesh(u%TowerMotion, u_op, index, FieldMask=FieldMask) + + FieldMask(MASKID_TRANSLATIONVel) = .false. + FieldMask(MASKID_RotationVel) = .true. + call PackMotionMesh(u%HubMotion, u_op, index, FieldMask=FieldMask) + + FieldMask = .false. + FieldMask(MASKID_Orientation) = .true. + do k = 1,p%NumBlades + call PackMotionMesh(u%BladeRootMotion(k), u_op, index, FieldMask=FieldMask) + end do + + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TRANSLATIONAcc) = .true. + do k=1,p%NumBlades + call PackMotionMesh(u%BladeMotion(k), u_op, index, FieldMask=FieldMask) + end do + + do k=1,p%NumBlades + do i=1,p%NumBlNds + do j=1,3 + u_op(index) = u%InflowOnBlade(j,i,k) + index = index + 1 + end do + end do + end do + + do i=1,p%NumTwrNds + do j=1,3 + u_op(index) = u%InflowOnTower(j,i) + index = index + 1 + end do + end do + + END IF + + IF ( PRESENT( y_op ) ) THEN + + if (.not. allocated(y_op)) then + call AllocAry(y_op, p%Jac_ny, 'y_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + + index = 1 + call PackLoadMesh(y%TowerLoad, y_op, index) + do k=1,p%NumBlades + call PackLoadMesh(y%BladeLoad(k), y_op, index) + end do + + index = index - 1 + do i=1,p%NumOuts + p%BldNd_TotNumOuts + y_op(i+index) = y%WriteOutput(i) + end do + + + END IF + + IF ( PRESENT( x_op ) ) THEN + + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%BEMT%DBEMT%lin_nx + p%BEMT%UA%lin_nx,'x_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + index = 1 + ! set linearization operating points: + if (p%BEMT%DBEMT%lin_nx>0) then + do j=1,p%NumBlades ! size(x%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(x%BEMT%DBEMT%element,1) + do k=1,size(x%BEMT%DBEMT%element(i,j)%vind) + x_op(index) = x%BEMT%DBEMT%element(i,j)%vind(k) + index = index + 1 + end do + end do + end do + + do j=1,p%NumBlades ! size(x%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(x%BEMT%DBEMT%element,1) + do k=1,size(x%BEMT%DBEMT%element(i,j)%vind_dot) + x_op(index) = x%BEMT%DBEMT%element(i,j)%vind_dot(k) + index = index + 1 + end do + end do + end do + + end if + + if (p%BEMT%UA%lin_nx>0) then + do j=1,p%NumBlades ! size(x%BEMT%UA%element,2) + do i=1,p%NumBlNds ! size(x%BEMT%UA%element,1) + do k=1,size(x%BEMT%UA%element(i,j)%x) + x_op(index) = x%BEMT%UA%element(i,j)%x(k) + index = index + 1 + end do + end do + end do + + end if + + END IF + + IF ( PRESENT( dx_op ) ) THEN + + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%BEMT%DBEMT%lin_nx + p%BEMT%UA%lin_nx,'dx_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + call AD_CalcContStateDeriv(t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call AD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + return + end if + + index = 1 + ! set linearization operating points: + if (p%BEMT%DBEMT%lin_nx>0) then + + do j=1,p%NumBlades ! size(dxdt%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(dxdt%BEMT%DBEMT%element,1) + do k=1,size(dxdt%BEMT%DBEMT%element(i,j)%vind) + dx_op(index) = dxdt%BEMT%DBEMT%element(i,j)%vind(k) + index = index + 1 + end do + end do + end do + + do j=1,p%NumBlades ! size(dxdt%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(dxdt%BEMT%DBEMT%element,1) + do k=1,size(dxdt%BEMT%DBEMT%element(i,j)%vind_dot) + dx_op(index) = dxdt%BEMT%DBEMT%element(i,j)%vind_dot(k) + index = index + 1 + end do + end do + end do + + end if + + if (p%BEMT%UA%lin_nx>0) then + do j=1,p%NumBlades ! size(dxdt%BEMT%UA%element,2) + do i=1,p%NumBlNds ! size(dxdt%BEMT%UA%element,1) + do k=1,size(dxdt%BEMT%UA%element(i,j)%x) + dx_op(index) = dxdt%BEMT%UA%element(i,j)%x(k) + index = index + 1 + end do + end do + end do + end if + + call AD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + + END IF + + IF ( PRESENT( xd_op ) ) THEN + + END IF + + IF ( PRESENT( z_op ) ) THEN + + if (.not. allocated(z_op)) then + call AllocAry(z_op, p%NumBlades*p%NumBlNds, 'z_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + index = 1 + do k=1,p%NumBlades ! size(z%BEMT%Phi,2) + do i=1,p%NumBlNds ! size(z%BEMT%Phi,1) + z_op(index) = z%BEMT%phi(i,k) + index = index + 1 + end do + end do + + END IF + +END SUBROUTINE AD_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +SUBROUTINE Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) + + TYPE(AD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(AD_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(AD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + + 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, j, k, indx_next, indx_last + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian_y' + logical, allocatable :: AllOut(:) + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! determine how many outputs there are in the Jacobians + p%Jac_ny = y%TowerLoad%NNodes * 6 & ! 3 forces + 3 moments at each node + + p%NumOuts + p%BldNd_TotNumOuts ! WriteOutput values + + do k=1,p%NumBlades + p%Jac_ny = p%Jac_ny + y%BladeLoad(k)%NNodes * 6 ! 3 forces + 3 moments at each node + end do + + + ! get the names of the linearized outputs: + call AllocAry(InitOut%LinNames_y, p%Jac_ny,'LinNames_y',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitOut%RotFrame_y, p%Jac_ny,'RotFrame_y',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + + InitOut%RotFrame_y = .false. ! default all to false, then set the true ones below + indx_next = 1 + call PackLoadMesh_Names(y%TowerLoad, 'Tower', InitOut%LinNames_y, indx_next) + + indx_last = indx_next + do k=1,p%NumBlades + call PackLoadMesh_Names(y%BladeLoad(k), 'Blade '//trim(num2lstr(k)), InitOut%LinNames_y, indx_next) + end do + ! InitOut%RotFrame_y(indx_last:indx_next-1) = .true. ! The mesh fields are in the global frame, so are not in the rotating frame + + do i=1,p%NumOuts + p%BldNd_TotNumOuts + InitOut%LinNames_y(i+indx_next-1) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) !trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + end do + + + ! check for all the WriteOutput values that are functions of blade number: + allocate( AllOut(0:MaxOutPts), STAT=ErrStat2 ) ! allocate starting at zero to account for invalid output channels + if (ErrStat2 /=0 ) then + call SetErrStat(ErrID_Info, 'error allocating temporary space for AllOut',ErrStat,ErrMsg,RoutineName) + return; + end if + + AllOut = .false. + do k=1,3 + AllOut( BAzimuth(k)) = .true. + AllOut( BPitch (k)) = .true. + do j=1,9 + AllOut(BNVUndx(j,k)) = .true. + AllOut(BNVUndy(j,k)) = .true. + AllOut(BNVUndz(j,k)) = .true. + AllOut(BNVDisx(j,k)) = .true. + AllOut(BNVDisy(j,k)) = .true. + AllOut(BNVDisz(j,k)) = .true. + AllOut(BNSTVx (j,k)) = .true. + AllOut(BNSTVy (j,k)) = .true. + AllOut(BNSTVz (j,k)) = .true. + AllOut(BNVRel (j,k)) = .true. + AllOut(BNDynP (j,k)) = .true. + AllOut(BNRe (j,k)) = .true. + AllOut(BNM (j,k)) = .true. + AllOut(BNVIndx(j,k)) = .true. + AllOut(BNVIndy(j,k)) = .true. + AllOut(BNAxInd(j,k)) = .true. + AllOut(BNTnInd(j,k)) = .true. + AllOut(BNAlpha(j,k)) = .true. + AllOut(BNTheta(j,k)) = .true. + AllOut(BNPhi (j,k)) = .true. + AllOut(BNCurve(j,k)) = .true. + AllOut(BNCl (j,k)) = .true. + AllOut(BNCd (j,k)) = .true. + AllOut(BNCm (j,k)) = .true. + AllOut(BNCx (j,k)) = .true. + AllOut(BNCy (j,k)) = .true. + AllOut(BNCn (j,k)) = .true. + AllOut(BNCt (j,k)) = .true. + AllOut(BNFl (j,k)) = .true. + AllOut(BNFd (j,k)) = .true. + AllOut(BNMm (j,k)) = .true. + AllOut(BNFx (j,k)) = .true. + AllOut(BNFy (j,k)) = .true. + AllOut(BNFn (j,k)) = .true. + AllOut(BNFt (j,k)) = .true. + AllOut(BNClrnc(j,k)) = .true. + end do + end do + + + do i=1,p%NumOuts + InitOut%RotFrame_y(i+indx_next-1) = AllOut( p%OutParam(i)%Indx ) + end do + + do i=1,p%BldNd_TotNumOuts + InitOut%RotFrame_y(i+p%NumOuts+indx_next-1) = .true. + !AbsCant, AbsToe, AbsTwist should probably be set to .false. + end do + + + deallocate(AllOut) + +END SUBROUTINE Init_Jacobian_y +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat, ErrMsg) + + TYPE(AD_InputFile) , INTENT(IN ) :: InputFileData !< input file data (for default blade perturbation) + TYPE(AD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(AD_InputType) , INTENT(IN ) :: u !< inputs + TYPE(AD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + + 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, j, k, index, index_last, nu, i_meshField + REAL(ReKi) :: perturb, perturb_t, perturb_b(MaxBl) + LOGICAL :: FieldMask(FIELDMASK_SIZE) + CHARACTER(1), PARAMETER :: UVW(3) = (/'U','V','W'/) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian_u' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! determine how many inputs there are in the Jacobians + nu = u%TowerMotion%NNodes * 9 & ! 3 Translation Displacements + 3 orientations + 3 Translation velocities at each node + + u%hubMotion%NNodes * 9 & ! 3 Translation Displacements + 3 orientations + 3 Rotation velocities at each node + + size( u%InflowOnBlade) & + + size( u%InflowOnTower) + + do i=1,p%NumBlades + nu = nu + u%BladeMotion(i)%NNodes * 15 & ! 3 Translation Displacements + 3 orientations + 3 Translation velocities + 3 Rotation velocities + 3 TranslationAcc at each node + + u%BladeRootMotion(i)%NNodes * 3 ! 3 orientations at each node + end do + + ! all other inputs ignored + + + !............................ + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! (see aerodyn::perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index (x-y-z component) of the field + ! column 3 is the node + !............................ + + call allocAry( p%Jac_u_indx, nu, 3, 'p%Jac_u_indx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !............... + ! AD input mappings stored in p%Jac_u_indx: + !............... + index = 1 + !Module/Mesh/Field: u%TowerMotion%TranslationDisp = 1; + !Module/Mesh/Field: u%TowerMotion%Orientation = 2; + !Module/Mesh/Field: u%TowerMotion%TranslationVel = 3; + do i_meshField = 1,3 + do i=1,u%TowerMotion%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + !Module/Mesh/Field: u%HubMotion%TranslationDisp = 4; + !Module/Mesh/Field: u%HubMotion%Orientation = 5; + !Module/Mesh/Field: u%HubMotion%RotationVel = 6; + do i_meshField = 4,6 + do i=1,u%HubMotion%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + !bjj: if MaxBl (max blades) changes, we need to modify this + !Module/Mesh/Field: u%BladeRootMotion(1)%Orientation = 7; + !Module/Mesh/Field: u%BladeRootMotion(2)%Orientation = 8; + !Module/Mesh/Field: u%BladeRootMotion(3)%Orientation = 9; + do k=1,p%NumBlades + do i_meshField = 6,6 + do i=1,u%BladeRootMotion(k)%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + k + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !i_meshField + end do !k + + !bjj: if MaxBl (max blades) changes, we need to modify this + !Module/Mesh/Field: u%BladeMotion(1)%TranslationDisp = 10; + !Module/Mesh/Field: u%BladeMotion(1)%Orientation = 11; + !Module/Mesh/Field: u%BladeMotion(1)%TranslationVel = 12; + !Module/Mesh/Field: u%BladeMotion(1)%RotationVel = 13; + !Module/Mesh/Field: u%BladeMotion(1)%TranslationAcc = 14; + + !Module/Mesh/Field: u%BladeMotion(2)%TranslationDisp = 15; + !Module/Mesh/Field: u%BladeMotion(2)%Orientation = 16; + !Module/Mesh/Field: u%BladeMotion(2)%TranslationVel = 17; + !Module/Mesh/Field: u%BladeMotion(2)%RotationVel = 18; + !Module/Mesh/Field: u%BladeMotion(2)%TranslationAcc = 19; + + !Module/Mesh/Field: u%BladeMotion(3)%TranslationDisp = 20; + !Module/Mesh/Field: u%BladeMotion(3)%Orientation = 21; + !Module/Mesh/Field: u%BladeMotion(3)%TranslationVel = 22; + !Module/Mesh/Field: u%BladeMotion(3)%RotationVel = 23; + !Module/Mesh/Field: u%BladeMotion(3)%TranslationAcc = 24; + do k=1,p%NumBlades + do i_meshField = 1,5 + do i=1,u%BladeMotion(k)%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = 9 + i_meshField + (k-1)*5 + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !i_meshField + end do !k + + !Module/Mesh/Field: u%InflowOnBlade(:,:,1) = 25; + !Module/Mesh/Field: u%InflowOnBlade(:,:,2) = 26; + !Module/Mesh/Field: u%InflowOnBlade(:,:,3) = 27; + do k=1,size(u%InflowOnBlade,3) ! p%NumBlades + do i=1,size(u%InflowOnBlade,2) ! numNodes + do j=1,3 + p%Jac_u_indx(index,1) = 24 + k + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do !k + + !Module/Mesh/Field: u%InflowOnTower(:,:) = 28; + do i=1,size(u%InflowOnTower,2) ! numNodes + do j=1,3 + p%Jac_u_indx(index,1) = 28 + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + + !...................................... + ! default perturbations, p%du: + !...................................... + call allocAry( p%du, 28, 'p%du', ErrStat2, ErrMsg2) ! 28 = number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + perturb = 2*D2R + + do k=1,p%NumBlades + perturb_b(k) = 0.2_ReKi*D2R * InputFileData%BladeProps(k)%BlSpn( InputFileData%BladeProps(k)%NumBlNds ) + end do + + if ( u%TowerMotion%NNodes > 0) then + perturb_t = 0.2_ReKi*D2R * u%TowerMotion%Position( 3, u%TowerMotion%NNodes ) + else + perturb_t = 0.0_ReKi + end if + + p%du(1) = perturb_t ! u%TowerMotion%TranslationDisp = 1 + p%du(2) = perturb ! u%TowerMotion%Orientation = 2 + p%du(3) = perturb_t ! u%TowerMotion%TranslationVel = 3 + p%du(4) = perturb_b(1) ! u%HubMotion%TranslationDisp = 4 + p%du(5) = perturb ! u%HubMotion%Orientation = 5 + p%du(6) = perturb ! u%HubMotion%RotationVel = 6 + do i_meshField = 7,9 + p%du(i_meshField) = perturb ! u%BladeRootMotion(k)%Orientation = 6+k, for k in [1, 3] + end do + do k=1,p%NumBlades + p%du(10 + (k-1)*5) = perturb_b(k) ! u%BladeMotion(k)%TranslationDisp = 10 + (k-1)*5 + p%du(11 + (k-1)*5) = perturb ! u%BladeMotion(k)%Orientation = 11 + (k-1)*5 + p%du(12 + (k-1)*5) = perturb_b(k) ! u%BladeMotion(k)%TranslationVel = 12 + (k-1)*5 + p%du(13 + (k-1)*5) = perturb ! u%BladeMotion(k)%RotationVel = 13 + (k-1)*5 + p%du(14 + (k-1)*5) = perturb_b(k) ! u%BladeMotion(k)%TranslationAcc = 14 + (k-1)*5 !bjj: is the correct???? + end do + do k=1,p%NumBlades + p%du(24 + k) = perturb_b(k) ! u%InflowOnBlade(:,:,k) = 24 + k + end do + p%du(28) = perturb_t ! u%InflowOnTower(:,:) = 22 + + + !..................... + ! get names of linearized inputs + !..................... + call AllocAry(InitOut%LinNames_u, nu, 'LinNames_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%RotFrame_u, nu, 'RotFrame_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%IsLoad_u, nu, 'IsLoad_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%IsLoad_u = .false. ! None of AeroDyn's inputs are loads + InitOut%RotFrame_u = .false. + + index = 1 + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + call PackMotionMesh_Names(u%TowerMotion, 'Tower', InitOut%LinNames_u, index, FieldMask=FieldMask) + + FieldMask(MASKID_TRANSLATIONVel) = .false. + FieldMask(MASKID_RotationVel) = .true. + call PackMotionMesh_Names(u%HubMotion, 'Hub', InitOut%LinNames_u, index, FieldMask=FieldMask) + + index_last = index + FieldMask = .false. + FieldMask(MASKID_Orientation) = .true. + do k = 1,p%NumBlades + call PackMotionMesh_Names(u%BladeRootMotion(k), 'Blade root '//trim(num2lstr(k)), InitOut%LinNames_u, index, FieldMask=FieldMask) + end do + + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TRANSLATIONAcc) = .true. + do k=1,p%NumBlades + call PackMotionMesh_Names(u%BladeMotion(k), 'Blade '//trim(num2lstr(k)), InitOut%LinNames_u, index, FieldMask=FieldMask) + end do + + do k=1,p%NumBlades + do i=1,p%NumBlNds + do j=1,3 + InitOut%LinNames_u(index) = UVW(j)//'-component inflow on blade '//trim(num2lstr(k))//', node '//trim(num2lstr(i))//', m/s' + index = index + 1 + end do + end do + end do + !InitOut%RotFrame_u(index_last:index-1) = .true. ! values on the mesh (and from IfW) are in global coordinates, thus not in the rotating frame + + do i=1,p%NumTwrNds + do j=1,3 + InitOut%LinNames_u(index) = UVW(j)//'-component inflow on tower node '//trim(num2lstr(i))//', m/s' + index = index + 1 + end do + end do + + END SUBROUTINE Init_Jacobian_u +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) + + TYPE(AD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(AD_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian_x' + + ! local variables: + INTEGER(IntKi) :: i, j, k + INTEGER(IntKi) :: nx + INTEGER(IntKi) :: nx1 + CHARACTER(25) :: NodeTxt + + ErrStat = ErrID_None + ErrMsg = "" + + + nx = p%BEMT%DBEMT%lin_nx + p%BEMT%UA%lin_nx + + ! allocate space for the row/column names and for perturbation sizes + ! always allocate this in case it is size zero ... (we use size(p%dx) for many calculations) + CALL AllocAry(p%dx, nx, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (nx==0) return + + CALL AllocAry(InitOut%LinNames_x, nx, 'LinNames_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%RotFrame_x, nx, 'RotFrame_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%DerivOrder_x, nx, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! All DBEMT continuous states are order = 2; UA states are order 1 + + ! set default perturbation sizes: p%dx + p%dx = 2.0_R8Ki * D2R_D + + ! set linearization output names: + nx1 = p%BEMT%DBEMT%lin_nx/2 + if (nx1>0) then + InitOut%DerivOrder_x(1:p%BEMT%DBEMT%lin_nx) = 2 + InitOut%RotFrame_x( 1:p%BEMT%DBEMT%lin_nx) = .true. + + k = 1 + do j=1,p%NumBlades ! size(x%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(x%BEMT%DBEMT%element,1) + NodeTxt = 'blade '//trim(num2lstr(j))//', node '//trim(num2lstr(i)) + InitOut%LinNames_x(k) = 'vind (axial) at '//trim(NodeTxt)//', m/s' + k = k + 1 + + InitOut%LinNames_x(k) = 'vind (tangential) at '//trim(NodeTxt)//', m/s' + k = k + 1 + end do + end do + + do i=1,nx1 + InitOut%LinNames_x(i+nx1) = 'First time derivative of '//trim(InitOut%LinNames_x(i))//'/s' + InitOut%RotFrame_x(i+nx1) = InitOut%RotFrame_x(i) + end do + end if + + if (p%BEMT%UA%lin_nx>0) then + InitOut%DerivOrder_x(1+p%BEMT%DBEMT%lin_nx:nx) = 1 + InitOut%RotFrame_x( 1+p%BEMT%DBEMT%lin_nx:nx) = .true. + + k = 1 + p%BEMT%DBEMT%lin_nx + do j=1,p%NumBlades ! size(x%BEMT%DBEMT%element,2) + do i=1,p%NumBlNds ! size(x%BEMT%DBEMT%element,1) + NodeTxt = 'blade '//trim(num2lstr(j))//', node '//trim(num2lstr(i)) + + InitOut%LinNames_x(k) = 'x1 '//trim(NodeTxt)//', rad' + k = k + 1 + + InitOut%LinNames_x(k) = 'x2 '//trim(NodeTxt)//', rad' + k = k + 1 + + InitOut%LinNames_x(k) = 'x3 '//trim(NodeTxt)//', -' + k = k + 1 + + InitOut%LinNames_x(k) = 'x4 '//trim(NodeTxt)//', -' + p%dx(k) = 0.001 ! x4 is a number between 0 and 1, so we need this to be small + k = k + 1 + end do + end do + + end if + +END SUBROUTINE Init_Jacobian_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing corresponding parts of AD linearization ! +SUBROUTINE Init_Jacobian( InputFileData, p, u, y, m, InitOut, ErrStat, ErrMsg) + + type(AD_InputFile) , intent(in ) :: InputFileData !< input file data (for default blade perturbation) + TYPE(AD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(AD_InputType) , INTENT(IN ) :: u !< inputs + TYPE(AD_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(AD_MiscVarType) , INTENT(IN ) :: m !< miscellaneous variable + TYPE(AD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian' + + + ErrStat = ErrID_None + ErrMsg = "" + +!FIXME: add logic to check that p%NumBlades is not greater than MaxBl. Cannot linearize if that is true. + call Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) + + ! these matrices will be needed for linearization with frozen wake feature + if (p%FrozenWake) then + call AllocAry(m%BEMT%AxInd_op,p%NumBlNds,p%numBlades,'m%BEMT%AxInd_op', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(m%BEMT%TnInd_op,p%NumBlNds,p%numBlades,'m%BEMT%TnInd_op', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + call Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call Init_Jacobian_x( p, InitOut, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +END SUBROUTINE Init_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine aerodyn::init_jacobian is consistant with this routine! +SUBROUTINE Perturb_u( p, n, perturb_sign, u, du ) + + TYPE(AD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(AD_InputType) , INTENT(INOUT) :: u !< perturbed AD inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + + + ! local variables + INTEGER :: fieldIndx + INTEGER :: node + + fieldIndx = p%Jac_u_indx(n,2) + node = p%Jac_u_indx(n,3) + + du = p%du( p%Jac_u_indx(n,1) ) + + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( p%Jac_u_indx(n,1) ) + + CASE ( 1) !Module/Mesh/Field: u%TowerMotion%TranslationDisp = 1; + u%TowerMotion%TranslationDisp( fieldIndx,node) = u%TowerMotion%TranslationDisp( fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%TowerMotion%Orientation = 2; + CALL PerturbOrientationMatrix( u%TowerMotion%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%TowerMotion%TranslationVel = 3; + u%TowerMotion%TranslationVel( fieldIndx,node ) = u%TowerMotion%TranslationVel( fieldIndx,node) + du * perturb_sign + + CASE ( 4) !Module/Mesh/Field: u%HubMotion%TranslationDisp = 4; + u%HubMotion%TranslationDisp(fieldIndx,node) = u%HubMotion%TranslationDisp(fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%HubMotion%Orientation = 5; + CALL PerturbOrientationMatrix( u%HubMotion%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 6) !Module/Mesh/Field: u%HubMotion%RotationVel = 6; + u%HubMotion%RotationVel(fieldIndx,node) = u%HubMotion%RotationVel(fieldIndx,node) + du * perturb_sign + + CASE ( 7) !Module/Mesh/Field: u%BladeRootMotion(1)%Orientation = 7; + CALL PerturbOrientationMatrix( u%BladeRootMotion(1)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + + CASE ( 8) !Module/Mesh/Field: u%BladeRootMotion(2)%Orientation = 8; + CALL PerturbOrientationMatrix( u%BladeRootMotion(2)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + + CASE ( 9) !Module/Mesh/Field: u%BladeRootMotion(3)%Orientation = 9; + CALL PerturbOrientationMatrix( u%BladeRootMotion(3)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + + CASE (10) !Module/Mesh/Field: u%BladeMotion(1)%TranslationDisp = 10; + u%BladeMotion(1)%TranslationDisp(fieldIndx,node) = u%BladeMotion(1)%TranslationDisp(fieldIndx,node) + du * perturb_sign + CASE (11) !Module/Mesh/Field: u%BladeMotion(1)%Orientation = 11; + CALL PerturbOrientationMatrix( u%BladeMotion(1)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (12) !Module/Mesh/Field: u%BladeMotion(1)%TranslationVel = 12; + u%BladeMotion(1)%TranslationVel(fieldIndx,node) = u%BladeMotion(1)%TranslationVel(fieldIndx,node) + du * perturb_sign + CASE (13) !Module/Mesh/Field: u%BladeMotion(1)%RotationVel = 13; + u%BladeMotion(1)%RotationVel(fieldIndx,node) = u%BladeMotion(1)%RotationVel(fieldIndx,node) + du * perturb_sign + CASE (14) !Module/Mesh/Field: u%BladeMotion(1)%TranslationAcc = 14; + u%BladeMotion(1)%TranslationAcc(fieldIndx,node) = u%BladeMotion(1)%TranslationAcc(fieldIndx,node) + du * perturb_sign + + CASE (15) !Module/Mesh/Field: u%BladeMotion(2)%TranslationDisp = 15; + u%BladeMotion(2)%TranslationDisp( fieldIndx,node) = u%BladeMotion(2)%TranslationDisp( fieldIndx,node) + du * perturb_sign + CASE (16) !Module/Mesh/Field: u%BladeMotion(2)%Orientation = 16; + CALL PerturbOrientationMatrix( u%BladeMotion(2)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (17) !Module/Mesh/Field: u%BladeMotion(2)%TranslationVel = 17; + u%BladeMotion(2)%TranslationVel(fieldIndx,node) = u%BladeMotion(2)%TranslationVel(fieldIndx,node) + du * perturb_sign + CASE (18) !Module/Mesh/Field: u%BladeMotion(2)%RotationVel = 18; + u%BladeMotion(2)%RotationVel(fieldIndx,node) = u%BladeMotion(2)%RotationVel(fieldIndx,node) + du * perturb_sign + CASE (19) !Module/Mesh/Field: u%BladeMotion(2)%TranslationAcc = 19; + u%BladeMotion(2)%TranslationAcc(fieldIndx,node) = u%BladeMotion(2)%TranslationAcc(fieldIndx,node) + du * perturb_sign + + CASE (20) !Module/Mesh/Field: u%BladeMotion(3)%TranslationDisp = 20; + u%BladeMotion(3)%TranslationDisp( fieldIndx,node) = u%BladeMotion(3)%TranslationDisp( fieldIndx,node) + du * perturb_sign + CASE (21) !Module/Mesh/Field: u%BladeMotion(3)%Orientation = 21; + CALL PerturbOrientationMatrix( u%BladeMotion(3)%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (22) !Module/Mesh/Field: u%BladeMotion(3)%TranslationVel = 22; + u%BladeMotion(3)%TranslationVel(fieldIndx,node) = u%BladeMotion(3)%TranslationVel(fieldIndx,node) + du * perturb_sign + CASE (23) !Module/Mesh/Field: u%BladeMotion(3)%RotationVel = 23; + u%BladeMotion(3)%RotationVel(fieldIndx,node) = u%BladeMotion(3)%RotationVel(fieldIndx,node) + du * perturb_sign + CASE (24) !Module/Mesh/Field: u%BladeMotion(3)%TranslationAcc = 24; + u%BladeMotion(3)%TranslationAcc(fieldIndx,node) = u%BladeMotion(3)%TranslationAcc(fieldIndx,node) + du * perturb_sign + + CASE (25) !Module/Mesh/Field: u%InflowOnBlade(:,:,1) = 25; + u%InflowOnBlade(fieldIndx,node,1) = u%InflowOnBlade(fieldIndx,node,1) + du * perturb_sign + CASE (26) !Module/Mesh/Field: u%InflowOnBlade(:,:,2) = 26; + u%InflowOnBlade(fieldIndx,node,2) = u%InflowOnBlade(fieldIndx,node,2) + du * perturb_sign + CASE (27) !Module/Mesh/Field: u%InflowOnBlade(:,:,3) = 27; + u%InflowOnBlade(fieldIndx,node,3) = u%InflowOnBlade(fieldIndx,node,3) + du * perturb_sign + + CASE (28) !Module/Mesh/Field: u%InflowOnTower(:,:) = 28; + u%InflowOnTower(fieldIndx,node) = u%InflowOnTower(fieldIndx,node) + du * perturb_sign + + END SELECT + +END SUBROUTINE Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine aerodyn::init_jacobian is consistant with this routine! +SUBROUTINE Perturb_x( p, n, perturb_sign, x, dx ) + + TYPE(AD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(AD_ContinuousStateType) , INTENT(INOUT) :: x !< perturbed AD continuous states + REAL( R8Ki ) , INTENT( OUT) :: dx !< amount that specific input was perturbed + + + ! local variables + INTEGER(IntKi) :: Blade ! loop over blade nodes + INTEGER(IntKi) :: BladeNode ! loop over blades + INTEGER(IntKi) :: StateIndex ! loop over blades + + + dx = p%dx( n ) + + if (n <= p%BEMT%DBEMT%lin_nx) then + + if (n <= p%BEMT%DBEMT%lin_nx/2) then ! x_p%BEMT%DBEMT%element(i,j)%vind, else x_p%BEMT%DBEMT%element(i,j)%vind_dot + call GetStateIndices( n, size(x%BEMT%DBEMT%element,2), size(x%BEMT%DBEMT%element,1), size(x%BEMT%DBEMT%element(1,1)%vind), Blade, BladeNode, StateIndex ) + x%BEMT%DBEMT%element(BladeNode,Blade)%vind(StateIndex) = x%BEMT%DBEMT%element(BladeNode,Blade)%vind(StateIndex) + dx * perturb_sign + else + call GetStateIndices( n - p%BEMT%DBEMT%lin_nx/2, size(x%BEMT%DBEMT%element,2), size(x%BEMT%DBEMT%element,1), size(x%BEMT%DBEMT%element(1,1)%vind_dot), Blade, BladeNode, StateIndex ) + x%BEMT%DBEMT%element(BladeNode,Blade)%vind_dot(StateIndex) = x%BEMT%DBEMT%element(BladeNode,Blade)%vind_dot(StateIndex) + dx * perturb_sign + endif + + else + call GetStateIndices( n - p%BEMT%DBEMT%lin_nx, size(x%BEMT%UA%element,2), size(x%BEMT%UA%element,1), size(x%BEMT%UA%element(1,1)%x), Blade, BladeNode, StateIndex ) + x%BEMT%UA%element(BladeNode,Blade)%x(StateIndex) = x%BEMT%UA%element(BladeNode,Blade)%x(StateIndex) + dx * perturb_sign + + end if + +contains + subroutine GetStateIndices( Indx, NumberOfBlades, NumberOfElementsPerBlade, NumberOfStatesPerElement, Blade, BladeNode, StateIndex ) + + integer(IntKi), intent(in ) :: Indx + integer(IntKi), intent(in ) :: NumberOfBlades !< how many blades (size of array) + integer(IntKi), intent(in ) :: NumberOfElementsPerBlade !< how many nodes per blades (size of array) + integer(IntKi), intent(in ) :: NumberOfStatesPerElement !< how many states at each blade element + + integer(IntKi), intent( out) :: Blade + integer(IntKi), intent( out) :: BladeNode + integer(IntKi), intent( out) :: StateIndex + + integer(IntKi) :: CheckNum + + + StateIndex = mod(Indx-1, NumberOfStatesPerElement ) + 1 ! returns a number in [1,NumberOfStatesPerElement] + + CheckNum = (Indx - StateIndex)/NumberOfStatesPerElement + BladeNode = mod(CheckNum, NumberOfElementsPerBlade ) + 1 ! returns a number in [1,NumberOfElementsPerBlade] + + Blade = (CheckNum - BladeNode + 1)/NumberOfElementsPerBlade + 1 + + end subroutine GetStateIndices +END SUBROUTINE Perturb_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine aerodyn::init_jacobian is consistant with this routine! +SUBROUTINE Compute_dY(p, y_p, y_m, delta_p, delta_m, dY) + + TYPE(AD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(AD_OutputType) , INTENT(IN ) :: y_p !< AD outputs at \f$ u + \Delta_p u \f$ or \f$ x + \Delta_p x \f$ (p=plus) + TYPE(AD_OutputType) , INTENT(IN ) :: y_m !< AD outputs at \f$ u - \Delta_m u \f$ or \f$ x - \Delta_m x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta_p !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(IN ) :: delta_m !< difference in inputs or states \f$ delta_m = \Delta_m u \f$ or \f$ delta_m = \Delta_m x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial x_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + INTEGER(IntKi) :: k ! loop over blades + INTEGER(IntKi) :: indx_first ! index indicating next value of dY to be filled + + + + indx_first = 1 + call PackLoadMesh_dY(y_p%TowerLoad, y_m%TowerLoad, dY, indx_first) + + do k=1,p%NumBlades + call PackLoadMesh_dY(y_p%BladeLoad(k), y_m%BladeLoad(k), dY, indx_first) + end do + + + do k=1,p%NumOuts + p%BldNd_TotNumOuts + dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) + end do + + + dY = dY / (delta_p + delta_m) + +END SUBROUTINE Compute_dY +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two continuous state types to compute an array of differences. +!! Do not change this packing without making sure subroutine aerodyn::init_jacobian is consistant with this routine! +SUBROUTINE Compute_dX(p, x_p, x_m, delta_p, delta_m, dX) + + TYPE(AD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(AD_ContinuousStateType) , INTENT(IN ) :: x_p !< AD continuous states at \f$ u + \Delta_p u \f$ or \f$ x + \Delta_p x \f$ (p=plus) + TYPE(AD_ContinuousStateType) , INTENT(IN ) :: x_m !< AD continuous states at \f$ u - \Delta_m u \f$ or \f$ x - \Delta_m x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta_p !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(IN ) :: delta_m !< difference in inputs or states \f$ delta_m = \Delta_m u \f$ or \f$ delta_m = \Delta_m x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dX(:) !< column of dXdu or dXdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial x_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + INTEGER(IntKi) :: i ! loop over blade nodes + INTEGER(IntKi) :: j ! loop over blades + INTEGER(IntKi) :: indx_first ! index indicating next value of dY to be filled + + + indx_first = 1 + + if (p%BEMT%DBEMT%lin_nx > 0) then + + do j=1,size(x_p%BEMT%DBEMT%element,2) ! number of blades + do i=1,size(x_p%BEMT%DBEMT%element,1) ! number of nodes per blade + dX(indx_first:indx_first+1) = x_p%BEMT%DBEMT%element(i,j)%vind - x_m%BEMT%DBEMT%element(i,j)%vind + indx_first = indx_first + size(x_p%BEMT%DBEMT%element(i,j)%vind) !+= 2 + end do + end do + + do j=1,size(x_p%BEMT%DBEMT%element,2) ! number of blades + do i=1,size(x_p%BEMT%DBEMT%element,1) ! number of nodes per blade + dX(indx_first:indx_first+1) = x_p%BEMT%DBEMT%element(i,j)%vind_dot - x_m%BEMT%DBEMT%element(i,j)%vind_dot + indx_first = indx_first + size(x_p%BEMT%DBEMT%element(i,j)%vind_dot) !+=2 + end do + end do + + end if + + if (p%BEMT%UA%lin_nx>0) then + + do j=1,size(x_p%BEMT%UA%element,2) ! number of blades + do i=1,size(x_p%BEMT%UA%element,1) ! number of nodes per blade + dX(indx_first:indx_first+3) = x_p%BEMT%UA%element(i,j)%x - x_m%BEMT%UA%element(i,j)%x + indx_first = indx_first + size(x_p%BEMT%UA%element(i,j)%x) ! = index_first += 4 + end do + end do + + end if + + dX = dX / (delta_p + delta_m) + +END SUBROUTINE Compute_dX +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE AeroDyn diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 new file mode 100644 index 000000000..34ba3b9ff --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 @@ -0,0 +1,1291 @@ +! This module is an add on to AeroDyn 15 to allow output of Aerodynamic data at each blade node. +! +! Copyright 2016 Envision Energy +! +MODULE AeroDyn_AllBldNdOuts_IO + + USE NWTC_Library + USE NWTC_LAPACK + USE AeroDyn_Types + + IMPLICIT NONE + + PRIVATE + + PUBLIC :: AllBldNdOuts_InitOut + PUBLIC :: Calc_WriteAllBldNdOutput + PUBLIC :: AllBldNdOuts_SetParameters + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 6 ! The NREL allowed channel name length is usually 20. We are making these of the form B#N##namesuffix + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 02-Jul-2020 11:33:13. + + + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + + + ! Blade: + + INTEGER(IntKi), PARAMETER :: BldNd_VUndx = 1 + INTEGER(IntKi), PARAMETER :: BldNd_VUndy = 2 + INTEGER(IntKi), PARAMETER :: BldNd_VUndz = 3 + INTEGER(IntKi), PARAMETER :: BldNd_VDisx = 4 + INTEGER(IntKi), PARAMETER :: BldNd_VDisy = 5 + INTEGER(IntKi), PARAMETER :: BldNd_VDisz = 6 + INTEGER(IntKi), PARAMETER :: BldNd_STVx = 7 + INTEGER(IntKi), PARAMETER :: BldNd_STVy = 8 + INTEGER(IntKi), PARAMETER :: BldNd_STVz = 9 + INTEGER(IntKi), PARAMETER :: BldNd_VRel = 10 + INTEGER(IntKi), PARAMETER :: BldNd_DynP = 11 + INTEGER(IntKi), PARAMETER :: BldNd_Re = 12 + INTEGER(IntKi), PARAMETER :: BldNd_M = 13 + INTEGER(IntKi), PARAMETER :: BldNd_Vindx = 14 + INTEGER(IntKi), PARAMETER :: BldNd_Vindy = 15 + INTEGER(IntKi), PARAMETER :: BldNd_AxInd = 16 + INTEGER(IntKi), PARAMETER :: BldNd_TnInd = 17 + INTEGER(IntKi), PARAMETER :: BldNd_Alpha = 18 + INTEGER(IntKi), PARAMETER :: BldNd_Theta = 19 + INTEGER(IntKi), PARAMETER :: BldNd_Phi = 20 + INTEGER(IntKi), PARAMETER :: BldNd_Curve = 21 + INTEGER(IntKi), PARAMETER :: BldNd_Cl = 22 + INTEGER(IntKi), PARAMETER :: BldNd_Cd = 23 + INTEGER(IntKi), PARAMETER :: BldNd_Cm = 24 + INTEGER(IntKi), PARAMETER :: BldNd_Cx = 25 + INTEGER(IntKi), PARAMETER :: BldNd_Cy = 26 + INTEGER(IntKi), PARAMETER :: BldNd_Cn = 27 + INTEGER(IntKi), PARAMETER :: BldNd_Ct = 28 + INTEGER(IntKi), PARAMETER :: BldNd_Fl = 29 + INTEGER(IntKi), PARAMETER :: BldNd_Fd = 30 + INTEGER(IntKi), PARAMETER :: BldNd_Mm = 31 + INTEGER(IntKi), PARAMETER :: BldNd_Fx = 32 + INTEGER(IntKi), PARAMETER :: BldNd_Fy = 33 + INTEGER(IntKi), PARAMETER :: BldNd_Fn = 34 + INTEGER(IntKi), PARAMETER :: BldNd_Ft = 35 + INTEGER(IntKi), PARAMETER :: BldNd_Clrnc = 36 + INTEGER(IntKi), PARAMETER :: BldNd_Vx = 37 + INTEGER(IntKi), PARAMETER :: BldNd_Vy = 38 + INTEGER(IntKi), PARAMETER :: BldNd_GeomPhi = 39 + INTEGER(IntKi), PARAMETER :: BldNd_Chi = 40 + INTEGER(IntKi), PARAMETER :: BldNd_UA_Flag = 41 + INTEGER(IntKi), PARAMETER :: BldNd_CpMin = 42 + INTEGER(IntKi), PARAMETER :: BldNd_SgCav = 43 + INTEGER(IntKi), PARAMETER :: BldNd_SigCr = 44 + INTEGER(IntKi), PARAMETER :: BldNd_Gam = 45 + INTEGER(IntKi), PARAMETER :: BldNd_Cl_Static = 46 + INTEGER(IntKi), PARAMETER :: BldNd_Cd_Static = 47 + INTEGER(IntKi), PARAMETER :: BldNd_Cm_Static = 48 + INTEGER(IntKi), PARAMETER :: BldNd_Uin = 49 + INTEGER(IntKi), PARAMETER :: BldNd_Uit = 50 + INTEGER(IntKi), PARAMETER :: BldNd_Uir = 51 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER, PUBLIC :: BldNd_MaxOutPts = 51 + +!End of code generated by Matlab script +! =================================================================================================== + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is blade:node:channel (channel iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteAllBldNdOutput routine as well. +SUBROUTINE AllBldNdOuts_InitOut( InitOut, p, InputFileData, ErrStat, ErrMsg ) + + TYPE(AD_InitOutputType), INTENT(INOUT) :: InitOut ! output data + TYPE(AD_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(AD_InputFile), INTENT(IN ) :: InputFileData ! All the data in the AeroDyn input file (want Blade Span for channel name) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + INTEGER(IntKi) :: INDX ! Index count within WriteOutput + INTEGER(IntKi) :: IdxBlade ! Counter to which blade we are on + INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(16) :: ChanPrefix ! Name prefix (AB#N###) + CHARACTER(6) :: TmpChar ! Temporary char array to hold the node digits (3 places only!!!!) + CHARACTER(*), PARAMETER :: RoutineName = ('AllBldNdOuts_InitOut') + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + + ! Warn if we will run into issues with more than 99 nodes. + IF (p%NumBlNds > 999 ) CALL SetErrStat(ErrID_Severe,'More than 999 blade nodes in use. Output channel headers will not '// & + 'correctly reflect blade stations beyond 999. Modifications to the variable ChanLen in FAST are required.',ErrStat,ErrMsg,RoutineName) + + + ! Populate the header an unit lines for all blades and nodes + ! First set a counter so we know where in the output array we are in + ! NOTE: we populate invalid names as well (some names are not valid outputs for certain configurations). That means we will have zeros in those values. + INDX = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal AeroDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts) + + DO IdxChan=1,p%BldNd_NumOuts + + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + + ! Create the name prefix: + WRITE (TmpChar,'(I3.3)') IdxNode ! 3 digit number + ChanPrefix = 'AB' // TRIM(Num2LStr(IdxBlade)) // 'N' // TRIM(TmpChar) ! // '_' ! note that I added an "AB" to indicate "Aero B1" in case of confusion with structural nodal outputs with the same name + ! Now write to the header + InitOut%WriteOutputHdr(INDX) = trim(ChanPrefix) // p%BldNd_OutParam(IdxChan)%Name + InitOut%WriteOutputUnt(INDX) = p%BldNd_OutParam(IdxChan)%Units + + ! Increment the index to the Header arrays + INDX = INDX + 1 + + ENDDO + ENDDO + + ENDDO + +END SUBROUTINE AllBldNdOuts_InitOut + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is channel:blade:node (node iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteAllBldNdOutput routine as well. +!! +!! NOTE: the equations here came from the output section of AeroDyn_IO.f90. If anything changes in there, it needs to be reflected +!! here. + +SUBROUTINE Calc_WriteAllBldNdOutput( p, u, m, y, OtherState, Indx, ErrStat, ErrMsg ) + TYPE(AD_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(AD_InputType), INTENT(IN ) :: u ! inputs + TYPE(AD_MiscVarType), INTENT(IN ) :: m ! misc variables + TYPE(AD_OutputType), INTENT(INOUT) :: y ! outputs (updates y%WriteOutput) + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState ! other states + INTEGER, INTENT(IN ) :: Indx ! index into m%BEMT_u(Indx) array; 1=t and 2=t+dt (but not checked here) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: OutIdx ! Index count within WriteOutput + INTEGER(IntKi) :: IdxBlade ! Counter to which blade we are on + INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteAllBldNdOutput' + REAL(ReKi) :: ct, st ! cosine, sine of theta + REAL(ReKi) :: cp, sp ! cosine, sine of phi + real(ReKi) :: M_ph(3,3) ! Transformation from hub to "blade-rotor-plane": n,t,r (not the same as AeroDyn) + real(ReKi) :: M_pg(3,3,p%NumBlades) ! Transformation from global to "blade-rotor-plane" (n,t,r), with same x at hub coordinate system + real(ReKi) :: psi_hub ! Azimuth wrt hub + real(ReKi) :: Vind_g(3) ! Induced velocity vector in global coordinates + real(ReKi) :: Vind_s(3) ! Induced velocity vector in section coordinates (AeroDyn "x-y") + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + ! Precalculate the M_ph matrix -- no reason to recalculate for each output + DO IdxBlade=1,p%NumBlades + psi_hub = TwoPi*(real(IdxBlade-1,ReKi))/real(p%NumBlades,ReKi) + M_ph(1,1:3) = (/ 1.0_ReKi, 0.0_ReKi , 0.0_ReKi /) + M_ph(2,1:3) = (/ 0.0_ReKi, cos(psi_hub), sin(psi_hub) /) + M_ph(3,1:3) = (/ 0.0_ReKi,-sin(psi_hub), cos(psi_hub) /) + M_pg(1:3,1:3,IdxBlade) = matmul(M_ph, u%HubMotion%Orientation(1:3,1:3,1) ) + ENDDO + + + ! Populate the header an unit lines for all blades and nodes + ! First set a counter so we know where in the output array we are in + OutIdx = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal AeroDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts) + + + ! Case to assign output to this channel and populate based on Indx value (this indicates what the channel is) + ! Logic and mathematics used here come from Calc_WriteOutput + DO IdxChan=1,p%BldNd_NumOuts + + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (0) ! Invalid channel + ! We still have headers for invalid channels. Need to account for that + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + CYCLE + + ! ***** Undisturbed wind velocity in local blade coord system ***** + CASE ( BldNd_VUndx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(1,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + + CASE ( BldNd_VUndy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(2,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_VUndz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(3,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + + + ! ***** Disturbed wind velocity in the local blade coordinate system ***** + CASE ( BldNd_VDisx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(1,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_VDisy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(2,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_VDisz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(3,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + + + ! ***** Structural translational velocity in the local blade coordinate system ***** + CASE ( BldNd_STVx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(1,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_STVy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(2,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_STVz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = dot_product( m%WithoutSweepPitchTwist(3,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) ) + OutIdx = OutIdx + 1 + END DO + END DO + + + ! Relative wind speed + CASE ( BldNd_VRel ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Vrel(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Vrel(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Dynamic pressure + CASE ( BldNd_DynP ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 0.5 * p%airDens * m%BEMT_y%Vrel(IdxNode,IdxBlade)**2 + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 0.5 * p%airDens * m%FVW%BN_Vrel(IdxNode,IdxBlade)**2 + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Reynolds number (in millions) + CASE ( BldNd_Re ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = p%BEMT%chord(IdxNode,IdxBlade) * m%BEMT_y%Vrel(IdxNode,IdxBlade) / p%KinVisc / 1.0E6 + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Re(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Mach number + CASE ( BldNd_M ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Vrel(IdxNode,IdxBlade) / p%SpdSound + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Vrel(IdxNode,IdxBlade) / p%SpdSound + OutIdx = OutIdx + 1 + END DO + END DO + endif + + + + ! Axial and tangential induced wind velocity + CASE ( BldNd_Vindx ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = - m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade) * m%BEMT_y%axInduction( IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = -m%FVW%BN_UrelWind_s(1,IdxNode,IdxBlade) * m%FVW%BN_AxInd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Vindy ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade) * m%BEMT_y%tanInduction(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_UrelWind_s(2,IdxNode,IdxBlade) * m%FVW%BN_TanInd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + + ! Axial and tangential induction factors + CASE ( BldNd_AxInd ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%axInduction(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_AxInd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_TnInd ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%tanInduction(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_TanInd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + + ! AoA, pitch+twist angle, inflow angle, and curvature angle + CASE ( BldNd_Alpha ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = Rad2M180to180Deg( m%BEMT_y%phi(IdxNode,IdxBlade) - m%BEMT_u(Indx)%theta(IdxNode,IdxBlade) ) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_alpha(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Theta ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%PitchAndTwist(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Phi ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%phi(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) =m%FVW%BN_phi(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Curve ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%Curve(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds +!NOT available in FVW yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + endif + + + ! Lift force, drag force, pitching moment coefficients + CASE ( BldNd_Cl ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Cl(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Cl(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Cd ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Cd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Cd(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Cm ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Cm(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Cm(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Normal force (to plane), tangential force (to plane) coefficients + CASE ( BldNd_Cx ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Cx(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Cx(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Cy ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%Cy(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_Cy(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Normal force (to chord), and tangential force (to chord) coefficients + CASE ( BldNd_Cn ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%BEMT_y%Cx(IdxNode,IdxBlade)*ct + m%BEMT_y%Cy(IdxNode,IdxBlade)*st + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! cos(theta) + st=sin(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! sin(theta) + y%WriteOutput( OutIdx ) = m%FVW%BN_Cx(IdxNode,IdxBlade)*ct + m%FVW%BN_Cy(IdxNode,IdxBlade)*st + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Ct ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = -m%BEMT_y%Cx(IdxNode,IdxBlade)*st + m%BEMT_y%Cy(IdxNode,IdxBlade)*ct + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! cos(theta) + st=sin(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! sin(theta) + y%WriteOutput( OutIdx ) = -m%FVW%BN_Cx(IdxNode,IdxBlade)*st + m%FVW%BN_Cy(IdxNode,IdxBlade)*ct + OutIdx = OutIdx + 1 + END DO + END DO + endif + + + ! Lift force, drag force, pitching moment + CASE ( BldNd_Fl ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + cp=cos(m%BEMT_y%phi(IdxNode,IdxBlade)) + sp=sin(m%BEMT_y%phi(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*cp - m%Y(IdxNode,IdxBlade)*sp + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + cp=cos(m%FVW%BN_phi(IdxNode,IdxBlade)) + sp=sin(m%FVW%BN_phi(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*cp - m%Y(IdxNode,IdxBlade)*sp + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Fd ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + cp=cos(m%BEMT_y%phi(IdxNode,IdxBlade)) + sp=sin(m%BEMT_y%phi(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*sp + m%Y(IdxNode,IdxBlade)*cp + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + cp=cos(m%FVW%BN_phi(IdxNode,IdxBlade)) + sp=sin(m%FVW%BN_phi(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*sp + m%Y(IdxNode,IdxBlade)*cp + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Mm ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%M(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + + ! Normal force (to plane), tangential force (to plane) + CASE ( BldNd_Fx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_Fy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = -m%Y(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + + ! Normal force (to chord), and tangential force (to chord) per unit length + CASE ( BldNd_Fn ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*ct - m%Y(IdxNode,IdxBlade)*st + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! cos(theta) + st=sin(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! sin(theta) + y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*ct - m%Y(IdxNode,IdxBlade)*st + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Ft ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = -m%X(IdxNode,IdxBlade)*st - m%Y(IdxNode,IdxBlade)*ct + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + ct=cos(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! cos(theta) + st=sin(m%FVW%PitchAndTwist(IdxNode,IdxBlade)) ! sin(theta) + y%WriteOutput( OutIdx ) = -m%X(IdxNode,IdxBlade)*st - m%Y(IdxNode,IdxBlade)*ct + OutIdx = OutIdx + 1 + END DO + END DO + endif + + ! Tower clearance (requires tower influence calculation): + CASE ( BldNd_Clrnc ) + if (.not. allocated(m%TwrClrnc)) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%TwrClrnc(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + end if + + + CASE ( BldNd_Vx ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_UrelWind_s(1,IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_Vy ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%FVW%BN_UrelWind_s(2,IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_GeomPhi ) + if (p%WakeMod /= WakeMod_FVW) then + if (allocated(OtherState%BEMT%ValidPhi)) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + if (OtherState%BEMT%ValidPhi(IdxNode,IdxBlade)) then + y%WriteOutput( OutIdx ) = 1.0_ReKi - m%BEMT%BEM_weight + else + y%WriteOutput( OutIdx ) = 1.0_ReKi + end if + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 1.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + end if + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = 0.0_ReKi ! Not valid for FVW + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_chi ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds + y%WriteOutput( OutIdx ) = m%BEMT_y%chi(IdxNode,IdxBlade)*R2D + OutIdx = OutIdx + 1 + END DO + END DO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%NumBlNds +!NOT available in FVW yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + endif + + CASE ( BldNd_UA_Flag ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + IF ( OtherState%BEMT%UA_Flag(IdxNode, IdxBlade) ) THEN + y%WriteOutput( OutIdx ) = 1.0_ReKi + ELSE + y%WriteOutput( OutIdx ) = 0.0_ReKi + ENDIF + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + IF ( OtherState%FVW%UA_Flag(IdxNode, IdxBlade) ) THEN + y%WriteOutput( OutIdx ) = 1.0_ReKi + ELSE + y%WriteOutput( OutIdx ) = 0.0_ReKi + ENDIF + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! CpMin + CASE ( BldNd_CpMin ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%BEMT_y%Cpmin(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes +!NOT available in FVW yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! Cavitation + CASE ( BldNd_SgCav ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%SigmaCavit(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + + CASE ( BldNd_SigCr ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%SigmaCavitCrit(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + + ! circulation on blade + CASE ( BldNd_Gam ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = 0.5_ReKi * p%BEMT%chord(IdxNode,IdxBlade) * m%BEMT_y%Vrel(IdxNode,IdxBlade) * m%BEMT_y%Cl(IdxNode,IdxBlade) ! "Gam" [m^2/s] + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = 0.5_ReKi * p%FVW%Chord(IdxNode,IdxBlade) * m%FVW%BN_Vrel(IdxNode,IdxBlade) * m%FVW%BN_Cl(IdxNode,IdxBlade) ! "Gam" [m^2/s] + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + + !================================================ + ! Static portion of Cl, Cd, Cm (ignoring unsteady effects) + ! Cl_Static + CASE ( BldNd_Cl_Static ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes +!NOT available in BEMT/DBEMT yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%FVW%BN_Cl_Static(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! Cd_Static + CASE ( BldNd_Cd_Static ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes +!NOT available in BEMT/DBEMT yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%FVW%BN_Cd_Static(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! Cm_Static + CASE ( BldNd_Cm_Static ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes +!NOT available in BEMT/DBEMT yet + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = m%FVW%BN_Cm_Static(IdxNode,IdxBlade) + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + + + !================================================ + ! Inductions in polar rotating hub coordinates + ! Axial induction, polar rotating hub coordinates + CASE ( BldNd_Uin ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /) + Vind_g = matmul(Vind_s, m%WithoutSweepPitchTwist(:,:,IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = dot_product(M_pg(1,1:3,IdxBlade), Vind_g(1:3) ) ! Uihn, hub normal + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = dot_product(M_pg(1,1:3,IdxBlade), m%FVW_y%Vind(1:3,IdxNode,IdxBlade) ) ! Uihn, hub normal + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! Tangential induction, polar rotating hub coordinates + CASE ( BldNd_Uit ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /) + Vind_g = matmul(Vind_s, m%WithoutSweepPitchTwist(:,:,IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = dot_product(M_pg(2,1:3,IdxBlade), Vind_g(1:3) ) ! Uiht, hub tangential + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = dot_product(M_pg(2,1:3,IdxBlade), m%FVW_y%Vind(1:3,IdxNode,IdxBlade) ) ! Uiht, hub tangential + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + ! Radial induction, polar rotating hub coordinates + CASE ( BldNd_Uir ) + if (p%WakeMod /= WakeMod_FVW) then + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /) + Vind_g = matmul(Vind_s, m%WithoutSweepPitchTwist(:,:,IdxNode,IdxBlade)) + y%WriteOutput( OutIdx ) = dot_product(M_pg(3,1:3,IdxBlade), Vind_g(1:3) ) ! Uihr, hub radial + OutIdx = OutIdx + 1 + ENDDO + ENDDO + else + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes + y%WriteOutput( OutIdx ) = dot_product(M_pg(3,1:3,IdxBlade), m%FVW_y%Vind(1:3,IdxNode,IdxBlade) ) ! Uihr, hub radial + OutIdx = OutIdx + 1 + ENDDO + ENDDO + endif + + + END SELECT + + END DO ! each channel + + +END SUBROUTINE Calc_WriteAllBldNdOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates and sets the parameters for the nodal outputs. +SUBROUTINE AllBldNdOuts_SetParameters( InitInp, InputFileData, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + + ! Passed variables: + + TYPE(AD_InitInputType), intent(IN ) :: InitInp !< Input data for initialization routine, out is needed because of copy below + TYPE(AD_InputFile), INTENT(IN ) :: InputFileData !< Data stored in the module's input file + TYPE(AD_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 + character(*), parameter :: RoutineName = 'AllBldNdOuts_SetParameters' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Check if the requested blades exist + IF ( (InputFileData%BldNd_BladesOut < 0_IntKi) .OR. (InputFileData%BldNd_BladesOut > p%NumBlades) ) THEN + CALL SetErrStat( ErrID_Warn, " Number of blades to output data at all blade nodes (BldNd_BladesOut) must be between 0 and "//TRIM(Num2LStr(p%NumBlades))//".", ErrStat, ErrMsg, RoutineName) + p%BldNd_BladesOut = 0_IntKi + ELSE + p%BldNd_BladesOut = InputFileData%BldNd_BladesOut + ENDIF + + + ! Check if the requested blade nodes are valid + ! InputFileData%BldNd_BlOutNd + + + ! Set the parameter to store number of requested Blade Node output sets + p%BldNd_NumOuts = InputFileData%BldNd_NumOuts + + ! Set the total number of outputs ( requested channel groups * number requested nodes * number requested blades ) + p%BldNd_TotNumOuts = p%BldNd_NumOuts*p%NumBlNds*p%BldNd_BladesOut ! p%BldNd_NumOuts * size(p%BldNd_BlOutNd) * size(p%BldNd_BladesOut) + +! ! Check if the blade node array to output is valid: p%BldNd_BlOutNd +! ! TODO: this value is not read in by the input file reading yet, so setting to all blade nodes +! ! -- check if list handed in is of nodes that exist (not sure this is ever checked) +! ! -- copy values over +! +! ! Temporary workaround here: +! ALLOCATE ( p%BldNd_BlOutNd(1:p%NumBlNds) , STAT=ErrStat2 ) +! IF ( ErrStat2 /= 0_IntKi ) THEN +! CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the AeroDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) +! RETURN +! ENDIF +! DO I=1,p%NumBlNds ! put all nodes in the list +! p%BldNd_BlOutNd(i) = i +! ENDDO + + +! ! Check if the requested blades are actually in use: +! ! TODO: this value is not read in by the input file reading yet, so setting to all blades +! ! -- check if list handed in is of blades that exist (not sure this is ever checked) +! ! -- copy values over +! ALLOCATE ( p%BldNd_BladesOut(1:p%NumBlades), STAT=ErrStat2 ) +! IF ( ErrStat2 /= 0_IntKi ) THEN +! CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the AeroDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) +! RETURN +! ENDIF +! DO I=1,p%NumBlades ! put all blades in the list +! p%BldNd_BladesOut(i) = i +! ENDDO + + if (p%BldNd_TotNumOuts > 0) then + call BldNdOuts_SetOutParam(InputFileData%BldNd_OutList, p, ErrStat, ErrMsg ) ! requires: p%NumOuts, p%numBlades, p%NumBlNds, p%NumTwrNds; sets: p%BldNdOutParam. + if (ErrStat >= AbortErrLev) return + end if + + + +END SUBROUTINE AllBldNdOuts_SetParameters + + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 02-Jul-2020 11:33:13. +SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: BldNd_OutList(:) !< The list out user-requested outputs + TYPE(AD_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 + + ! Local variables + + 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 :: InvalidOutput(1:BldNd_MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "BldNdOuts_SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(51) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ALPHA ","AXIND ","CD ","CD_STATIC","CHI ","CL ","CLRNC ","CL_STATIC", & + "CM ","CM_STATIC","CN ","CPMIN ","CT ","CURVE ","CX ","CY ", & + "DYNP ","FD ","FL ","FN ","FT ","FX ","FY ","GAM ", & + "GEOMPHI ","M ","MM ","PHI ","RE ","SGCAV ","SIGCR ","STVX ", & + "STVY ","STVZ ","THETA ","TNIND ","UA_FLAG ","UIN ","UIR ","UIT ", & + "VDISX ","VDISY ","VDISZ ","VINDX ","VINDY ","VREL ","VUNDX ","VUNDY ", & + "VUNDZ ","VX ","VY "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(51) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + BldNd_Alpha , BldNd_AxInd , BldNd_Cd , BldNd_Cd_Static , BldNd_Chi , BldNd_Cl , BldNd_Clrnc , BldNd_Cl_Static , & + BldNd_Cm , BldNd_Cm_Static , BldNd_Cn , BldNd_CpMin , BldNd_Ct , BldNd_Curve , BldNd_Cx , BldNd_Cy , & + BldNd_DynP , BldNd_Fd , BldNd_Fl , BldNd_Fn , BldNd_Ft , BldNd_Fx , BldNd_Fy , BldNd_Gam , & + BldNd_GeomPhi , BldNd_M , BldNd_Mm , BldNd_Phi , BldNd_Re , BldNd_SgCav , BldNd_SigCr , BldNd_STVx , & + BldNd_STVy , BldNd_STVz , BldNd_Theta , BldNd_TnInd , BldNd_UA_Flag , BldNd_Uin , BldNd_Uir , BldNd_Uit , & + BldNd_VDisx , BldNd_VDisy , BldNd_VDisz , BldNd_Vindx , BldNd_Vindy , BldNd_VRel , BldNd_VUndx , BldNd_VUndy , & + BldNd_VUndz , BldNd_Vx , BldNd_Vy /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(51) = (/ & ! This lists the units corresponding to the allowed parameters + "(deg) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(m) ","(-) ", & + "(-) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)", & + "(1/0) ","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ", & + "(m/s) ","(m/s) ","(m/s) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + + ! The following are valid only for BEMT/DBEMT + if (p%WakeMod /= WakeMod_FVW) then + InvalidOutput( BldNd_Cl_Static ) = .true. + InvalidOutput( BldNd_Cd_Static ) = .true. + InvalidOutput( BldNd_Cm_Static ) = .true. + else + ! The following are invalid for free vortex wake + InvalidOutput( BldNd_Chi ) = .true. + InvalidOutput( BldNd_Curve ) = .true. + InvalidOutput( BldNd_CpMin ) = .true. + endif + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%BldNd_OutParam(1:p%BldNd_NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the AeroDyn BldNd_OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%BldNd_NumOuts + + p%BldNd_OutParam(I)%Name = BldNd_OutList(I) + OutListTmp = BldNd_OutList(I) + p%BldNd_OutParam(I)%SignM = 1 ! this won't be used + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + IF ( Indx > 0 ) THEN ! we found the channel name + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 + ELSE + p%BldNd_OutParam(I)%Indx = ParamIndxAry(Indx) + p%BldNd_OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%BldNd_OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE BldNdOuts_SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** +END MODULE AeroDyn_AllBldNdOuts_IO diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Driver.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver.f90 new file mode 100644 index 000000000..7fbbe4929 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver.f90 @@ -0,0 +1,180 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! +! This file is part of AeroDyn. +! +! 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. +! +!********************************************************************************************************************************** +program AeroDyn_Driver + + use AeroDyn_Driver_Subs + + implicit none + + ! Program variables + + real(DbKi) :: time !< Variable for storing time, in seconds + real(DbKi) :: dT_Dvr !< copy of DT, to make sure AD didn't change it + + type(Dvr_SimData) :: DvrData ! The data required for running the AD driver + type(AeroDyn_Data) :: AD ! AeroDyn data + + integer(IntKi) :: iCase ! loop counter (for driver case) + integer(IntKi) :: nt ! loop counter (for time step) + integer(IntKi) :: j ! loop counter (for array of inputs) + integer(IntKi) :: errStat ! Status of error message + character(ErrMsgLen) :: errMsg ! Error message if ErrStat /= ErrID_None + + !integer :: StrtTime (8) ! Start time of simulation (including intialization) + !integer :: SimStrtTime (8) ! Start time of simulation (after initialization) + !real(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds + !real :: UsrTime1 ! User CPU time for simulation initialization + !real :: UsrTime2 ! User CPU time for simulation (without intialization) + !real :: UsrTimeDiff ! Difference in CPU time from start to finish of program execution + !real(DbKi) :: TiLstPrn ! The simulation time of the last print + !real(DbKi) :: SttsTime ! Amount of time between screen status messages (sec) + !integer :: n_SttsTime ! Number of time steps between screen status messages (-) + logical :: AD_Initialized + + real(ReKi) :: RotAzimuth ! Rotor Azimuth (aligned with blade 1) + !real(ReKi) :: TeetAng ! Teeter angle + !real(ReKi) :: TeetAngVel ! Teeter angular velocity + + + + errStat = ErrID_None + errMsg = '' + AD_Initialized = .false. + + time = 0.0 ! seconds + + + ! Get the current time + !call date_and_time ( Values=StrtTime ) ! Let's time the whole simulation + !call cpu_time ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + + + ! initialize this driver: + call Dvr_Init( DvrData, ErrStat, ErrMsg) + call CheckError() + + + do iCase = 1, DvrData%NumCases + +! call WrScr( NewLine//'Running case '//trim(num2lstr(iCase))//' of '//trim(num2lstr(DvrData%NumCases))//'.' ) + + ! Set the Initialization input data for AeroDyn based on the Driver input file data, and initialize AD + ! (this also initializes inputs to AD for first time step) + dT_Dvr = DvrData%Cases(iCase)%dT + call Init_AeroDyn(iCase, DvrData, AD, dT_Dvr, errStat, errMsg) + call CheckError() + AD_Initialized = .true. + + if (.not. EqualRealNos( dT_Dvr, DvrData%Cases(iCase)%dT ) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'AeroDyn changed the time step for case '//trim(num2lstr(iCase))//'. Change DTAero to "default".' + call CheckError() + end if + + if (iCase.eq.1) then + call Dvr_InitializeOutputFile(DvrData%numBlades, iCase, DvrData%Cases(iCase), DvrData%OutFileData, errStat, errMsg) + call CheckError() + endif + + RotAzimuth = 0.0_ReKi + do nt = 1, DvrData%Cases(iCase)%numSteps + + !............................... + ! set AD inputs for nt (and keep values at nt-1 as well) + !............................... + + call Set_AD_Inputs(iCase,nt,RotAzimuth,DvrData,AD,errStat,errMsg) ! u(1) is at nt+1, u(2) is at nt + call CheckError() + + time = AD%InputTime(2) + + ! Calculate outputs at nt - 1 + + call AD_CalcOutput( time, AD%u(2), AD%p, AD%x, AD%xd, AD%z, AD%OtherState, AD%y, AD%m, errStat, errMsg ) + call CheckError() + + + + + call Dvr_WriteOutputLine(DvrData%OutFileData, nt, RotAzimuth, AD%y%WriteOutput, DvrData%Cases(iCase), iCase, errStat, errMsg) + call CheckError() + + + + + ! Get state variables at next step: INPUT at step nt - 1, OUTPUT at step nt + + call AD_UpdateStates( time, nt-1, AD%u, AD%InputTime, AD%p, AD%x, AD%xd, AD%z, AD%OtherState, AD%m, errStat, errMsg ) + call CheckError() + + + end do !nt=1,numSteps + + end do !iCase = 1, DvrData%NumCases + + call Dvr_End() + +contains +!................................ + subroutine CheckError() + + if (ErrStat /= ErrID_None) then + call WrScr(TRIM(ErrMsg)) + + if (ErrStat >= AbortErrLev) then + call Dvr_End() + end if + end if + + end subroutine CheckError +!................................ + subroutine Dvr_End() + + ! Local variables + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + + character(*), parameter :: RoutineName = 'Dvr_End' + ! Close the output file + if (DvrData%OutFileData%unOutFile > 0) close(DvrData%OutFileData%unOutFile) + + if ( AD_Initialized ) then + call AD_End( AD%u(1), AD%p, AD%x, AD%xd, AD%z, AD%OtherState, AD%y, AD%m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end if + + call AD_Dvr_DestroyDvr_SimData( DvrData, ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call AD_Dvr_DestroyAeroDyn_Data( AD, ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + CALL ProgAbort( 'AeroDyn Driver encountered simulation error level: '& + //TRIM(GetErrStr(ErrStat)), TrapErrors=.FALSE., TimeWait=3._ReKi ) ! wait 3 seconds (in case they double-clicked and got an error) + else + call NormStop() + end if + + + end subroutine Dvr_End +!................................ +end program AeroDyn_Driver + diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Registry.txt b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Registry.txt new file mode 100644 index 000000000..76f0f95c8 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Registry.txt @@ -0,0 +1,74 @@ +################################################################################################################################### +# Registry for AeroDyn 15 Driver in the FAST Modularization Framework +# This Registry file is used to create AeroDyn_Driver_Types. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt +usefrom AeroDyn_Registry.txt + +# +# ..... Table of cases to run ....................................................................................................... +typedef AeroDyn_Driver/AD_Dvr Dvr_Case ReKi WndSpeed {:} - - "Wind Speed" "m/s" +typedef ^ ^ ReKi ShearExp {:} - - "Power Law Wind-Shear Exponent" "-" +typedef ^ ^ ReKi RotSpeed {:} - - "Rotor Speed" "rad/s" +typedef ^ ^ ReKi Pitch {:} - - "Pitch angle" "rad" +typedef ^ ^ ReKi Yaw {:} - - "Yaw angle" "rad" +typedef ^ ^ DbKi time {:} - - "time increment" "s" +typedef ^ ^ DbKi dT - - - "time increment" "s" +typedef ^ ^ IntKi numSteps - - - "number of steps in this case" "-" + + + +# +# ..... Data for driver output file ....................................................................................................... +typedef ^ Dvr_OutputFile ProgDesc AD_ver - - - "AeroDyn version information" - +typedef ^ ^ IntKi unOutFile - - - "unit number for writing output file" "-" +typedef ^ ^ IntKi ActualChanLen - - - "Actual length of channels written to text file (less than or equal to ChanLen)" "-" +typedef ^ ^ character(20) Fmt_t - - - "Format specifier for time channel" "-" +typedef ^ ^ character(25) Fmt_a - - - "Format specifier for each column (including delimiter)" "-" +typedef ^ ^ character(20) Fmt_i - - - "Format specifier for integer column" "-" +typedef ^ ^ character(1) delim - - - "column delimiter" "-" +typedef ^ ^ character(20) outFmt - - - "Format specifier" "-" +typedef ^ ^ character(1024) Root - - - "Output file rootname" "-" +typedef ^ ^ character(1024) runTitle - - - "Description string from input file" "-" +typedef ^ ^ character(ChanLen) WriteOutputHdr {:} - - "Channel headers" "-" +typedef ^ ^ character(ChanLen) WriteOutputUnt {:} - - "Channel units" "-" +typedef ^ ^ logical AllFiles - - - "Output file for each case" "-" +typedef ^ ^ logical SumFile - - - "Output summary file for all cases with last timestep" "-" + +# +# ..... AeroDyn data ....................................................................................................... +param ^ - INTEGER numInp - 2 - "Determines order of interpolation for input-output extrap (2=linear;3=quadratic)" +typedef ^ AeroDyn_Data AD_ContinuousStateType x - - - "Continuous states" +typedef ^ ^ AD_DiscreteStateType xd - - - "Discrete states" +typedef ^ ^ AD_ConstraintStateType z - - - "Constraint states" +typedef ^ ^ AD_OtherStateType OtherState - - - "Other states" +typedef ^ ^ AD_MiscVarType m - - - "misc/optimization variables" +typedef ^ ^ AD_ParameterType p - - - "Parameters" +typedef ^ ^ AD_InputType u {numInp} - - "Array of system inputs" +typedef ^ ^ AD_OutputType y - - - "System outputs" +typedef ^ ^ DbKi InputTime {numInp} - - "Array of times associated with u array" + + +# +# ..... Data for driver simulation ....................................................................................................... +typedef ^ Dvr_SimData character(1024) AD_InputFile - - - "Name of AeroDyn input file" - +typedef ^ ^ IntKi numBlades - - - "number of blades on turbine" "-" +typedef ^ ^ ReKi hubRad - - - "Hub radius" "m" +typedef ^ ^ ReKi hubHt - - - "Hub height" "m" +typedef ^ ^ ReKi overhang - - - "overhang" "m" +typedef ^ ^ ReKi ShftTilt - - - "Shaft tilt angle" "rad" +typedef ^ ^ ReKi Precone - - - "Precone angle (all blades)" "rad" +typedef ^ ^ IntKi NumCases - - - "number of time-marching cases to run" "-" +typedef ^ ^ Dvr_Case Cases {:} - - "table of cases to run" "-" +typedef ^ ^ Dvr_OutputFile OutFileData - - - "data for driver output file" "-" +#typedef ^ ^ AeroDyn_Data AD - - - "data for the AeroDyn module" +#typedef ^ ^ Dvr_RootInfo RootForceMom 3 - - "blade root forces and moments (blade coords)" "-" + diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 new file mode 100644 index 000000000..86a0d9423 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -0,0 +1,969 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2018 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 AeroDyn_Driver_Subs + + use AeroDyn_Driver_Types + use AeroDyn + use VersionInfo + + implicit none + + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'AeroDyn_driver', '', '' ) ! The version number of this program. + + contains + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_Init(DvrData,errStat,errMsg ) + + type(Dvr_SimData), intent( out) :: DvrData ! driver data + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + integer(IntKi) :: errStat2 ! local status of error message + character(ErrMsgLen) :: errMsg2 ! local error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'Dvr_Init' + + CHARACTER(1000) :: inputFile ! String to hold the file name. + CHARACTER(200) :: git_commit ! String containing the current git commit hash + CHARACTER(20) :: FlagArg ! flag argument from command line + + + ErrStat = ErrID_None + ErrMsg = "" + + + DvrData%OutFileData%unOutFile = -1 + + CALL NWTC_Init( ProgNameIN=version%Name ) + + InputFile = "" ! initialize to empty string to make sure it's input from the command line + CALL CheckArgs( InputFile, Flag=FlagArg ) + IF ( LEN( TRIM(FlagArg) ) > 0 ) CALL NormStop() + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + ! Read the AeroDyn driver input file + call Dvr_ReadInputFile(inputFile, DvrData, errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName) + if (errStat >= AbortErrLev) return + + ! validate the inputs + call ValidateInputs(DvrData, errStat2, errMsg2) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName) + +end subroutine Dvr_Init +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Init_AeroDyn(iCase, DvrData, AD, dt, errStat, errMsg) + + integer(IntKi), intent(in ) :: iCase ! driver case + type(Dvr_SimData), intent(inout) :: DvrData ! Input data for initialization (intent out for getting AD WriteOutput names/units) + type(AeroDyn_Data), intent(inout) :: AD ! AeroDyn data + real(DbKi), intent(inout) :: dt ! interval + + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + ! locals + real(reKi) :: theta(3) + integer(IntKi) :: j, k + integer(IntKi) :: errStat2 ! local status of error message + character(ErrMsgLen) :: errMsg2 ! local error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'Init_AeroDyn' + + ! local data + type(AD_InitInputType) :: InitInData ! Input data for initialization + type(AD_InitOutputType) :: InitOutData ! Output data from initialization + real(ReKi) :: RotAzimuth ! Rotor azimuth -- aligned with blade 1 (deg) + + + + errStat = ErrID_None + errMsg = '' + + if (iCase.EQ.1) then + + InitInData%InputFile = DvrData%AD_InputFile + InitInData%NumBlades = DvrData%numBlades + InitInData%RootName = DvrData%outFileData%Root + InitInData%Gravity = 9.80665_ReKi + + + ! set initialization data: + call AllocAry( InitInData%BladeRootPosition, 3, InitInData%NumBlades, 'BladeRootPosition', errStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call AllocAry( InitInData%BladeRootOrientation, 3, 3, InitInData%NumBlades, 'BladeRootOrientation', errStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + InitInData%HubPosition = (/ DvrData%Overhang * cos(DvrData%shftTilt), 0.0_ReKi, DvrData%HubHt /) + theta(1) = 0.0_ReKi + theta(2) = -DvrData%shftTilt + theta(3) = 0.0_ReKi + InitInData%HubOrientation = EulerConstruct( theta ) + + + do k=1,InitInData%numBlades + + theta(1) = (k-1)*TwoPi/real(InitInData%numBlades,ReKi) + theta(2) = DvrData%precone + theta(3) = 0.0_ReKi + InitInData%BladeRootOrientation(:,:,k) = matmul( EulerConstruct( theta ), InitInData%HubOrientation ) + + InitInData%BladeRootPosition(:,k) = InitInData%HubPosition + DvrData%hubRad * InitInData%BladeRootOrientation(3,:,k) + + end do + + + call AD_Init(InitInData, AD%u(1), AD%p, AD%x, AD%xd, AD%z, AD%OtherState, AD%y, AD%m, dt, InitOutData, ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + do j = 2, numInp + call AD_CopyInput (AD%u(1), AD%u(j), MESH_NEWCOPY, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + + ! move AD initOut data to AD Driver + call move_alloc( InitOutData%WriteOutputHdr, DvrData%OutFileData%WriteOutputHdr ) + call move_alloc( InitOutData%WriteOutputUnt, DvrData%OutFileData%WriteOutputUnt ) + + DvrData%OutFileData%AD_ver = InitOutData%ver + + call cleanup() ! destroy init input/output data + + else + + call AD_ReInit(AD%p, AD%x, AD%xd, AD%z, AD%OtherState, AD%m, dt, ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + end if + + + ! we know exact values, so we're going to initialize inputs this way (instead of using the input guesses from AD_Init) + AD%InputTime = -999 + RotAzimuth = 0.0 + DO j = 1-numInp, 0 + call Set_AD_Inputs(iCase,j,RotAzimuth,DvrData,AD,errStat2,errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + + +contains + + subroutine cleanup() + call AD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ) + call AD_DestroyInitOutput( InitOutData, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +end subroutine Init_AeroDyn +!---------------------------------------------------------------------------------------------------------------------------------- +!> this routine cycles values in the input array AD%InputTime and AD%u. +!! it then sets the inputs for nt * DvrData%Cases(iCase)%dT, which are index values 1 in the arrays. +subroutine Set_AD_Inputs(iCase,nt,RotAzimuth,DvrData,AD,errStat,errMsg) + + integer(IntKi) , intent(in ) :: iCase ! case number + integer(IntKi) , intent(in ) :: nt ! time step number + + real(ReKi) , intent(inout) :: RotAzimuth ! Rotor azimuth at time nt-1 -- aligned with blade 1 (deg) + type(Dvr_SimData), intent(in ) :: DvrData ! Driver data + type(AeroDyn_Data), intent(inout) :: AD ! AeroDyn data + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + integer(IntKi) :: errStat2 ! local status of error message + character(ErrMsgLen) :: errMsg2 ! local error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'Set_AD_Inputs' + + integer(intKi) :: j ! loop counter for nodes + integer(intKi) :: k ! loop counter for blades + integer(intKi) :: timeIndex ! index for time + + real(ReKi) :: z ! height (m) + !real(ReKi) :: angle + real(R8Ki) :: theta(3) + real(R8Ki) :: position(3) + real(R8Ki) :: orientation(3,3) + real(R8Ki) :: rotateMat(3,3) + + + errStat = ErrID_None + errMsg = "" + + ! note that this initialization is a little different than the general algorithm in FAST because here + ! we can get exact values, so we are going to ignore initial guesses and not extrapolate + + timeIndex = min( max(1,nt+1), DvrData%Cases(iCase)%numSteps ) + + !................ + ! shift previous calculations: + !................ + do j = numInp-1,1,-1 + call AD_CopyInput (AD%u(j), AD%u(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + AD%InputTime(j+1) = AD%InputTime(j) + end do + + if (nt <= 0) then + ! save the azimuth at t (not t+dt) for output to file: + ! compare to theta(1) for calculate of HubMotion%Orientation below + RotAzimuth = MODULO( REAL( DvrData%Cases(iCase)%dT * (nt-1) * DvrData%Cases(iCase)%RotSpeed(1), ReKi) * R2D, 360.0_ReKi ) + + AD%inputTime(1) = DvrData%Cases(iCase)%time(1) + DvrData%Cases(iCase)%dT * nt ! time at nt+1 + else + + if (nt==1) then + RotAzimuth = 0.0_ReKi + else + RotAzimuth = MODULO( RotAzimuth + REAL(DvrData%Cases(iCase)%dt * DvrData%Cases(iCase)%RotSpeed(nt), ReKi) * R2D, 360.0_ReKi ) ! add a delta angle to the previous azimuth + end if + + if (nt == DvrData%Cases(iCase)%numSteps) then + AD%inputTime(1) = DvrData%Cases(iCase)%time(timeIndex) + DvrData%Cases(iCase)%dT + else + AD%inputTime(1) = DvrData%Cases(iCase)%time(timeIndex) + end if + + end if + + !................ + ! calculate new values + !................ + + ! Tower motions: + do j=1,AD%u(1)%TowerMotion%nnodes + AD%u(1)%TowerMotion%Orientation( :,:,j) = AD%u(1)%TowerMotion%RefOrientation(:,:,j) ! identity + AD%u(1)%TowerMotion%TranslationDisp(:,j) = 0.0_ReKi + AD%u(1)%TowerMotion%TranslationVel( :,j) = 0.0_ReKi + end do !j=nnodes + + ! Hub motions: + theta(1) = 0.0_ReKi + theta(2) = 0.0_ReKi + theta(3) = DvrData%Cases(iCase)%Yaw(timeIndex) + orientation = EulerConstruct(theta) + + AD%u(1)%HubMotion%TranslationDisp(:,1) = matmul( AD%u(1)%HubMotion%Position(:,1), orientation ) - AD%u(1)%HubMotion%Position(:,1) ! = matmul( transpose(orientation) - eye(3), AD%u(1)%HubMotion%Position(:,1) ) + + theta(1) = RotAzimuth*D2R + DvrData%Cases(iCase)%dt * DvrData%Cases(iCase)%RotSpeed(timeIndex) ! AD%inputTime(1) * DvrData%Cases(iCase)%RotSpeed + theta(2) = 0.0_ReKi + theta(3) = 0.0_ReKi + AD%u(1)%HubMotion%Orientation( :,:,1) = matmul( AD%u(1)%HubMotion%RefOrientation(:,:,1), orientation ) + orientation = EulerConstruct( theta ) + AD%u(1)%HubMotion%Orientation( :,:,1) = matmul( orientation, AD%u(1)%HubMotion%Orientation( :,:,1) ) + + AD%u(1)%HubMotion%RotationVel( :,1) = AD%u(1)%HubMotion%Orientation(1,:,1) * DvrData%Cases(iCase)%RotSpeed(timeIndex) + + ! Blade motions: + do k=1,DvrData%numBlades + theta(1) = (k-1)*TwoPi/real(DvrData%numBlades,ReKi) + theta(2) = DvrData%precone + theta(3) = -DvrData%Cases(iCase)%pitch(timeIndex) + orientation = EulerConstruct(theta) + + AD%u(1)%BladeRootMotion(k)%Orientation( :,:,1) = matmul( orientation, AD%u(1)%HubMotion%Orientation( :,:,1) ) + end do !k=numBlades + + ! Blade and blade root motions: + do k=1,DvrData%numBlades + rotateMat = transpose( AD%u(1)%BladeRootMotion(k)%Orientation( :,:,1) ) + rotateMat = matmul( rotateMat, AD%u(1)%BladeRootMotion(k)%RefOrientation( :,:,1) ) + orientation = transpose(rotateMat) + + rotateMat(1,1) = rotateMat(1,1) - 1.0_ReKi + rotateMat(2,2) = rotateMat(2,2) - 1.0_ReKi + rotateMat(3,3) = rotateMat(3,3) - 1.0_ReKi + + + position = AD%u(1)%BladeRootMotion(k)%Position(:,1) - AD%u(1)%HubMotion%Position(:,1) + AD%u(1)%BladeRootMotion(k)%TranslationDisp(:,1) = AD%u(1)%HubMotion%TranslationDisp(:,1) + matmul( rotateMat, position ) + + position = AD%u(1)%BladeRootMotion(k)%Position(:,1) + AD%u(1)%BladeRootMotion(k)%TranslationDisp(:,1) & + - AD%u(1)%HubMotion%Position(:,1) - AD%u(1)%HubMotion%TranslationDisp(:,1) + AD%u(1)%BladeRootMotion(k)%TranslationVel( :,1) = cross_product( AD%u(1)%HubMotion%RotationVel(:,1), position ) + + do j=1,AD%u(1)%BladeMotion(k)%nnodes + position = AD%u(1)%BladeMotion(k)%Position(:,j) - AD%u(1)%HubMotion%Position(:,1) + AD%u(1)%BladeMotion(k)%TranslationDisp(:,j) = AD%u(1)%HubMotion%TranslationDisp(:,1) + matmul( rotateMat, position ) + + AD%u(1)%BladeMotion(k)%Orientation( :,:,j) = matmul( AD%u(1)%BladeMotion(k)%RefOrientation(:,:,j), orientation ) + + + position = AD%u(1)%BladeMotion(k)%Position(:,j) + AD%u(1)%BladeMotion(k)%TranslationDisp(:,j) & + - AD%u(1)%HubMotion%Position(:,1) - AD%u(1)%HubMotion%TranslationDisp(:,1) + AD%u(1)%BladeMotion(k)%TranslationVel( :,j) = cross_product( AD%u(1)%HubMotion%RotationVel(:,1), position ) + + AD%u(1)%BladeMotion(k)%RotationVel(:,j) = AD%u(1)%HubMotion%Orientation(1,:,1) * DvrData%Cases(iCase)%RotSpeed(timeIndex) ! simplification (without pitch rate) + AD%u(1)%BladeMotion(k)%TranslationAcc(:,j) = 0.0_ReKi ! simplification + end do !j=nnodes + + end do !k=numBlades + + ! Inflow wind velocities: + ! InflowOnBlade + do k=1,DvrData%numBlades + do j=1,AD%u(1)%BladeMotion(k)%nnodes + z = AD%u(1)%BladeMotion(k)%Position(3,j) + AD%u(1)%BladeMotion(k)%TranslationDisp(3,j) + AD%u(1)%InflowOnBlade(1,j,k) = GetU( DvrData%Cases(iCase)%WndSpeed(timeIndex), DvrData%HubHt, DvrData%Cases(iCase)%ShearExp(timeIndex), z ) + AD%u(1)%InflowOnBlade(2,j,k) = 0.0_ReKi !V + AD%u(1)%InflowOnBlade(3,j,k) = 0.0_ReKi !W + end do !j=nnodes + end do !k=numBlades + + !InflowOnTower + do j=1,AD%u(1)%TowerMotion%nnodes + z = AD%u(1)%TowerMotion%Position(3,j) + AD%u(1)%TowerMotion%TranslationDisp(3,j) + AD%u(1)%InflowOnTower(1,j) = GetU( DvrData%Cases(iCase)%WndSpeed(timeIndex), DvrData%HubHt, DvrData%Cases(iCase)%ShearExp(timeIndex), z ) + AD%u(1)%InflowOnTower(2,j) = 0.0_ReKi !V + AD%u(1)%InflowOnTower(3,j) = 0.0_ReKi !W + end do !j=nnodes + +end subroutine Set_AD_Inputs +!---------------------------------------------------------------------------------------------------------------------------------- +function GetU( URef, ZRef, PLExp, z ) result (U) + real(ReKi), intent(in) :: URef + real(ReKi), intent(in) :: ZRef + real(ReKi), intent(in) :: PLExp + real(ReKi), intent(in) :: z + real(ReKi) :: U + + U = URef*(z/ZRef)**PLExp + +end function GetU +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_ReadInputFile(fileName, DvrData, errStat, errMsg ) + ! This routine opens the gets the data from the input files. + + character(*), intent( in ) :: fileName + type(Dvr_SimData), intent( out ) :: DvrData + integer, intent( out ) :: errStat ! returns a non-zero value when an error occurs + character(*), intent( out ) :: errMsg ! Error message if errStat /= ErrID_None + + + ! Local variables + character(1024) :: PriPath + character(1024) :: inpVersion ! String containing the input-version information. + character(1024) :: Line ! String containing a line of input. + integer :: unIn, unEc + integer :: ICase + integer :: nt, Ind + integer :: Sttus + character( 11) :: DateNow ! Date shortly after the start of execution. + character( 8) :: TimeNow ! Time of day shortly after the start of execution. + + integer, parameter :: NumCols = 7 ! number of columns to be read from the input file + real(DbKi) :: InpCase(NumCols) ! Temporary array to hold combined-case input parameters. (note that we store in double precision so the time is read correctly) + logical :: TabDel + logical :: echo + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName = 'Dvr_ReadInputFile' + + + ErrStat = ErrID_None + ErrMsg = '' + UnIn = -1 + UnEc = -1 + + ! Open the input file + CALL GetPath( fileName, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + call GetNewUnit( unIn ) + call OpenFInpFile( unIn, fileName, errStat2, ErrMsg2 ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + + call WrScr( 'Opening input file: '//fileName ) + + ! Skip a line, read the run title information. + + CALL ReadStr( UnIn, fileName, inpVersion, 'inpVersion', 'File Header: (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadStr( UnIn, fileName, DvrData%OutFileData%runTitle, 'runTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + call WrScr1 ( ' '//DvrData%OutFileData%runTitle ) + + ! Read in the title line for the input-configuration subsection. + CALL ReadStr( UnIn, fileName, line, 'line', 'File Header: (line 3)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! See if we should echo the output. + call ReadVar ( unIn, fileName, echo, 'Echo', 'Echo Input', errStat2, errMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if ( echo ) then + ! Get date and time. + dateNow = CurDate() + timeNow = CurTime() + call GetNewUnit( unEc ) + call getroot(fileName,DvrData%OutFileData%Root) + call OpenFOutFile ( unEc, trim( DvrData%OutFileData%Root )//'.ech', errStat2, errMsg2 ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + write (unEc,'(A)') 'Echo of Input File:' + write (unEc,'(A)') ' "'//fileName//'"' + write (unEc,'(A)') 'Generated on: '//trim( dateNow )//' at '//trim( timeNow )//'.' + write (unEc,'(A)') inpVersion + write (unEc,'(A)') DvrData%OutFileData%runTitle + write (unEc,'(A)') line + write (unEc,Ec_LgFrmt) echo, 'Echo', 'Echo input parameters to "rootname.ech"?' + end if + + + ! Read the rest of input-configuration section. + + call ReadVar ( unIn, fileName, DvrData%AD_InputFile, 'AD_InputFile', 'Name of the AeroDyn input file', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + IF ( PathIsRelative( DvrData%AD_InputFile ) ) DvrData%AD_InputFile = TRIM(PriPath)//TRIM(DvrData%AD_InputFile) + + + ! Read the turbine-data section. + + call ReadCom ( unIn, fileName, 'the turbine-data subtitle', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%numBlades,'NumBlades','Number of blades', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%HubRad, 'HubRad', 'Hub radius (m)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%HubHt, 'HubHt', 'Hub height (m)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%Overhang, 'Overhang', 'Overhang (m)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%ShftTilt, 'ShftTilt', 'Shaft tilt (deg)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + DvrData%ShftTilt = DvrData%ShftTilt*D2R + call ReadVar ( unIn, fileName, DvrData%precone, 'Precone', 'Precone (deg)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + DvrData%precone = DvrData%precone*D2R + + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + + ! Read the I/O-configuration section. + + call ReadCom ( unIn, fileName, 'the I/O-configuration subtitle', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%OutFileData%Root, 'OutFileRoot', 'Root name for any output files', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + IF ( PathIsRelative( DvrData%OutFileData%Root ) ) DvrData%OutFileData%Root = TRIM(PriPath)//TRIM(DvrData%OutFileData%Root) + if (len_trim(DvrData%OutFileData%Root) == 0) then + call getroot(fileName,DvrData%OutFileData%Root) + end if + + call ReadVar ( unIn, fileName, TabDel, 'TabDel', 'Make output tab-delimited (fixed-width otherwise)?', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + if (TabDel) then + DvrData%OutFileData%delim = TAB + else + DvrData%OutFileData%delim = " " + end if + + ! OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (-): + call ReadVar( UnIn, fileName, DvrData%OutFileData%OutFmt, "OutFmt", "Format used for text tabular output (except time). Resulting field should be 10 characters. (-)", ErrStat2, ErrMsg2, UnEc) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) !bjj: this is a global variable in NWTC_Library + call ReadVar ( unIn, fileName, Beep, 'Beep', 'Beep on exit?', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) !bjj: this is a global variable in NWTC_Library + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + + + ! Read the combined-case section. + + call ReadCom ( unIn, fileName, 'the combined-case subtitle', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadVar ( unIn, fileName, DvrData%NumCases, 'NumCases', 'Number of cases to run', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadCom ( unIn, fileName, 'the combined-case-block header (names)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call ReadCom ( unIn, fileName, 'the combined-case-block header (units)', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + if ( DvrData%NumCases < 1 ) then + call setErrStat( ErrID_Fatal,'Variable "NumCases" must be > 0.' ,errstat,errmsg,routinename) + call cleanup() + return + end if + + allocate ( DvrData%Cases(DvrData%NumCases) , STAT=Sttus ) + if ( Sttus /= 0 ) then + call setErrStat( ErrID_Fatal,'Error allocating memory for the Cases array.',errstat,errmsg,routinename) + call cleanup() + return + end if + + do ICase=1,DvrData%NumCases + + CALL ReadStr( UnIn, fileName, line, 'line', 'Input data for case #'//trim( Int2LStr( ICase ) ), ErrStat2, ErrMsg2, UnEc ) + CALL setErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + Line = ADJUSTL( Line ) ! remove leading spaces + + if (Line(1:1) == '@') then + Line = Line(2:) ! remove leading character + call ReadTimeHistoryFile(Line, PriPath, DvrData%Cases(iCase), ErrStat2, ErrMsg2, UnEc ) + call setErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + else + + READ (Line,*,IOSTAT=Sttus) InpCase ! read whole array (hopefully!) + + ! check errors + CALL CheckIOS ( Sttus, fileName, 'InpCase', NumType, ErrStat2, ErrMsg2 ) + call setErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + DO Ind=1,NumCols + CALL CheckRealVar( InpCase(Ind), 'InpCase', ErrStat2, ErrMsg2) + CALL setErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_ReAryFrmt ) TRIM( 'InpCase' ), 'Parameters for Case #'//trim( Int2LStr( ICase ) ), InpCase + END IF + + ! set data + DvrData%Cases(iCase)%numSteps = ceiling( InpCase( 7) / InpCase( 6) ) + call AllocateCase(DvrData%Cases(iCase), ErrStat2, ErrMsg2) ! needs %numSteps set prior to call + if (ErrStat2>=AbortErrLev) then + call SetErrStat( ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName ) + call Cleanup() + return + end if + + DvrData%Cases(iCase)%WndSpeed = InpCase( 1) + DvrData%Cases(ICase)%ShearExp = InpCase( 2) + DvrData%Cases(ICase)%RotSpeed = InpCase( 3)*RPM2RPS + DvrData%Cases(ICase)%Pitch = InpCase( 4)*D2R + DvrData%Cases(ICase)%Yaw = InpCase( 5)*D2R + DvrData%Cases(iCase)%dT = InpCase( 6) + !DvrData%Cases(iCase)%Tmax = InpCase( 7) + + do nt = 1,DvrData%Cases(iCase)%numSteps + DvrData%Cases(iCase)%time(nt) = (nt-1) * DvrData%Cases(iCase)%dT + end do + + end if + + end do ! ICase + + call cleanup ( ) + + + RETURN +contains + subroutine cleanup() + if (UnIn>0) close(UnIn) + if (UnEc>0) close(UnEc) + end subroutine cleanup +end subroutine Dvr_ReadInputFile +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine ReadTimeHistoryFile(FileName, PriPath, CaseData, ErrStat, ErrMsg, UnEc ) + character(*), intent(inout) :: FileName + character(*), intent(in ) :: PriPath + type(Dvr_Case), intent(inout) :: CaseData + integer, intent( out) :: ErrStat ! returns a non-zero value when an error occurs + character(*), intent( out) :: ErrMsg ! Error message if errStat /= ErrID_None + integer, intent(in ) :: UnEc + + integer :: UnIn + integer :: i + integer, parameter :: NumHeaderLines = 2 + + character(*), parameter :: RoutineName = 'AllocateCase' + integer :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + integer, parameter :: NumCols = 6 ! number of columns to be read from the input file + real(DbKi) :: InpCase(NumCols) ! Temporary array to hold combined-case input parameters. (note that we store in double precision so the time is read correctly) + + + + ! Open the input file + IF ( PathIsRelative( FileName ) ) FileName = TRIM(PriPath)//TRIM(FileName) + + + call GetNewUnit( UnIn ) + call OpenFInpFile( UnIn, FileName, errStat2, ErrMsg2 ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + if ( errStat >= AbortErrLev ) then + call cleanup() + return + end if + + + DO I=1,NumHeaderLines + call ReadCom(UnIn, FileName, 'Header', ErrStat2, ErrMsg2, UnEc) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + IF (ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END DO + + + ! find out how many rows there are to the end of the file + CaseData%NumSteps = -1 + ErrStat2 = 0 + DO WHILE ( ErrStat2 == 0 ) + + CaseData%NumSteps = CaseData%NumSteps + 1 + READ(UnIn, *, IOSTAT=ErrStat2) InpCase(1) + + END DO + + CALL WrScr( ' Found '//TRIM(Num2LStr(CaseData%NumSteps))//' lines of time-series data.' ) + + IF (CaseData%NumSteps < 2) THEN + CALL SetErrStat(ErrID_Fatal, 'The user time-series input file must contain at least 2 rows of time data.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + + call AllocateCase(CaseData, ErrStat2, ErrMsg2) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + IF (ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! now rewind and skip the first few lines. + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(FileName)//'".', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + END IF + + !IMPORTANT: any changes to the number of lines in the header must be reflected in NumHeaderLines + DO I=1,NumHeaderLines + call ReadCom(UnIn, FileName, 'Header', ErrStat2, ErrMsg2, UnEc) ! I'm going to ignore this error because we should have caught any issues the first time we read the file. + END DO + + + DO i=1,CaseData%NumSteps + + call ReadAry ( unIn, fileName, InpCase, NumCols, 'InpCase', 'parameters for Case', errStat2, errMsg2, UnEc ) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + + if (ErrStat>=AbortErrLev) then + call Cleanup() + return + end if + + CaseData%time(i) = InpCase( 1) + CaseData%WndSpeed(i) = InpCase( 2) + CaseData%ShearExp(i) = InpCase( 3) + CaseData%RotSpeed(i) = InpCase( 4)*RPM2RPS + CaseData%Pitch(i) = InpCase( 5)*D2R + CaseData%Yaw(i) = InpCase( 6)*D2R + + END DO + + CaseData%dT = CaseData%time(2) - CaseData%time(1) + + do i=3,CaseData%NumSteps + if (.not. EqualRealNos( CaseData%time(i), CaseData%time(i-1) + CaseData%dT ) ) then + call SetErrStat(ErrID_Fatal,'Time history file must contain time constant deltas in the time channel.', ErrStat, ErrMsg, RoutineName) + call cleanup() + return + end if + end do + + call cleanup() + +contains + subroutine cleanup + close(UnIn) + end subroutine cleanup +end subroutine ReadTimeHistoryFile +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AllocateCase(CaseData, ErrStat, ErrMsg) + type(Dvr_Case), intent(inout) :: CaseData + integer, intent( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent( out) :: errMsg ! Error message if errStat /= ErrID_None + + character(*), parameter :: routineName = 'AllocateCase' + integer :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + CaseData%numSteps = max(1, CaseData%numSteps) + + call AllocAry( CaseData%time, CaseData%numSteps, 'time', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call AllocAry( CaseData%WndSpeed, CaseData%numSteps, 'WndSpeed', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call AllocAry( CaseData%ShearExp, CaseData%numSteps, 'ShearExp', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call AllocAry( CaseData%RotSpeed, CaseData%numSteps, 'RotSpeed', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call AllocAry( CaseData%Pitch, CaseData%numSteps, 'Pitch', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + call AllocAry( CaseData%Yaw, CaseData%numSteps, 'Yaw', ErrStat2,ErrMsg2); call setErrStat( ErrStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + +end subroutine AllocateCase +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine ValidateInputs(DvrData, errStat, errMsg) + + type(Dvr_SimData), intent(inout) :: DvrData ! intent(out) only so that we can save FmtWidth in DvrData%OutFileData%ActualChanLen + integer, intent( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent( out) :: errMsg ! Error message if errStat /= ErrID_None + + ! local variables: + integer(intKi) :: i + integer(intKi) :: FmtWidth ! number of characters in string produced by DvrData%OutFmt + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'ValidateInputs' + + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Turbine Data: + if ( DvrData%numBlades < 1 ) call SetErrStat( ErrID_Fatal, "There must be at least 1 blade (numBlades).", ErrStat, ErrMsg, RoutineName) +! if ( DvrData%numBlades > 3 ) call SetErrStat( ErrID_Fatal, "There can be no more than 3 blades (numBlades).", ErrStat, ErrMsg, RoutineName) + if ( DvrData%HubRad < 0.0_ReKi .or. EqualRealNos(DvrData%HubRad, 0.0_ReKi) ) call SetErrStat( ErrID_Fatal, "HubRad must be a positive number.", ErrStat, ErrMsg, RoutineName) + if ( DvrData%HubHt < DvrData%HubRad ) call SetErrStat( ErrID_Fatal, "HubHt must be at least HubRad.", ErrStat, ErrMsg, RoutineName) + + + ! I-O Settings: + ! Check that DvrData%OutFileData%OutFmt is a valid format specifier and will fit over the column headings + call ChkRealFmtStr( DvrData%OutFileData%OutFmt, 'OutFmt', FmtWidth, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !if ( FmtWidth /= ChanLen ) call SetErrStat( ErrID_Warn, 'OutFmt produces a column width of '// & + ! TRIM(Num2LStr(FmtWidth))//' instead of '//TRIM(Num2LStr(ChanLen))//' characters.', ErrStat, ErrMsg, RoutineName ) + if ( FmtWidth < MinChanLen ) call SetErrStat( ErrID_Warn, 'OutFmt produces a column less than '//trim(num2lstr(MinChanLen))//' characters wide ('// & + TRIM(Num2LStr(FmtWidth))//'), which may be too small.', ErrStat, ErrMsg, RoutineName ) + DvrData%OutFileData%ActualChanLen = FmtWidth + + ! Combined-Case Analysis: + do i=1,DvrData%NumCases + + if (DvrData%Cases(i)%DT < epsilon(0.0_ReKi) ) call SetErrStat(ErrID_Fatal,'dT must be larger than 0 in case '//trim(num2lstr(i))//'.',ErrStat, ErrMsg,RoutineName) + + end do + + + +end subroutine ValidateInputs +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_WriteOutputLine(OutFileData, nt, RotAzimuth, output, CaseData, iCase, errStat, errMsg) + + integer(IntKi) , intent(in ) :: nt ! simulation time step (-) + integer(IntKi) , intent(in ) :: iCase ! case # to write to file + type(Dvr_OutputFile) , intent(in ) :: OutFileData + type(Dvr_Case), intent(in ) :: CaseData + real(ReKi) , intent(in ) :: RotAzimuth ! Rotor azimuth -- aligned with blade 1 (deg) + real(ReKi) , intent(in ) :: output(:) ! array of requested outputs + integer(IntKi) , intent(inout) :: errStat ! Status of error message + character(*) , intent(inout) :: errMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + character(ChanLen) :: tmpStr ! temporary string to print the time output as text + + errStat = ErrID_None + errMsg = '' + + ! time + write( tmpStr, OutFileData%Fmt_t ) CaseData%time(nt) ! '(F15.4)' + call WrFileNR( OutFileData%unOutFile, tmpStr(1:OutFileData%ActualChanLen) ) + + call WrNumAryFileNR ( OutFileData%unOutFile, (/iCase/), OutFileData%Fmt_i, errStat, errMsg ) + call WrNumAryFileNR ( OutFileData%unOutFile, (/CaseData%WNDSPEED(nt), CaseData%SHEAREXP(nt), RotAzimuth, CaseData%Yaw(nt)*R2D/), OutFileData%Fmt_a, errStat, errMsg ) + call WrNumAryFileNR ( OutFileData%unOutFile, output, OutFileData%Fmt_a, errStat, errMsg ) + if ( errStat >= AbortErrLev ) return + + ! write a new line (advance to the next line) + write (OutFileData%unOutFile,'()') + +end subroutine Dvr_WriteOutputLine +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_InitializeOutputFile(numBlades, iCase, CaseData, OutFileData, errStat, errMsg) !TODO:ADP -- how do we tell this routine that we are creating the summary file right now + integer(IntKi), intent(in ) :: numBlades ! driver data. neeeded for number of blades + type(Dvr_OutputFile), intent(inout) :: OutFileData + + integer(IntKi) , intent(in ) :: iCase ! case number (to write in file description line and use for file name) + type(Dvr_Case), intent(in ) :: CaseData + + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + ! locals + integer(IntKi) :: i + integer(IntKi) :: numSpaces + integer(IntKi) :: numOuts + character(ChanLen) :: colTxt + character(ChanLen) :: caseTxt + + + + call GetNewUnit( OutFileData%unOutFile, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) then + OutFileData%unOutFile = -1 + return + end if + + numOuts = size(OutFileData%WriteOutputHdr) + + ! compute the width of the column output + numSpaces = OutFileData%ActualChanLen ! the size of column produced by OutFmt + OutFileData%ActualChanLen = max( OutFileData%ActualChanLen, MinChanLen ) ! set this to at least MinChanLen , or the size of the column produced by OutFmt + do i=1,NumOuts + OutFileData%ActualChanLen = max(OutFileData%ActualChanLen, LEN_TRIM(OutFileData%WriteOutputHdr(i))) + OutFileData%ActualChanLen = max(OutFileData%ActualChanLen, LEN_TRIM(OutFileData%WriteOutputUnt(i))) + end do + + ! create format statements for time and the array outputs: + OutFileData%Fmt_t = '(F'//trim(num2lstr(OutFileData%ActualChanLen))//'.4)' + OutFileData%Fmt_i = '(I'//trim(num2lstr(OutFileData%ActualChanLen))//')' + OutFileData%Fmt_a = '"'//OutFileData%delim//'"'//trim(OutFileData%outFmt) ! format for array elements from individual modules + numSpaces = OutFileData%ActualChanLen - numSpaces ! the difference between the size of the headers and what is produced by OutFmt + if (numSpaces > 0) then + OutFileData%Fmt_a = trim(OutFileData%Fmt_a)//','//trim(num2lstr(numSpaces))//'x' + end if + + +! call OpenFOutFile ( OutFileData%unOutFile, trim(outFileData%Root)//'.'//trim(num2lstr(iCase))//'.out', ErrStat, ErrMsg ) + call OpenFOutFile ( OutFileData%unOutFile, trim(outFileData%Root)//'.out', ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return + + write (OutFileData%unOutFile,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using '//trim( version%Name ) + write (OutFileData%unOutFile,'(1X,A)') trim(GetNVD(OutFileData%AD_ver)) + write (OutFileData%unOutFile,'()' ) !print a blank line + write (OutFileData%unOutFile,'()' ) !print a blank line + + write (OutFileData%unOutFile,'()' ) !print a blank line + + + !...................................................... + ! Write the names of the output parameters on one line: + !...................................................... + + colTxt = 'Time' + call WrFileNR ( OutFileData%unOutFile, colTxt(1:OutFileData%ActualChanLen)) + + colTxt = 'Case' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen)) + + colTxt = 'WindSpeed' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = 'ShearExp' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = 'RotAzimuth' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = 'Yaw' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + do i=1,NumOuts + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//OutFileData%WriteOutputHdr(i)(1:OutFileData%ActualChanLen) ) + end do ! i + + write (OutFileData%unOutFile,'()') + + !...................................................... + ! Write the units of the output parameters on one line: + !...................................................... + colTxt = '(s)' + call WrFileNR ( OutFileData%unOutFile, colTxt(1:OutFileData%ActualChanLen)) + + colTxt = '(-)' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = '(m/s)' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = '(-)' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = '(deg)' + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + colTxt = '(deg)' ! Yaw + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//colTxt(1:OutFileData%ActualChanLen) ) + + do i=1,NumOuts + call WrFileNR ( OutFileData%unOutFile, OutFileData%delim//OutFileData%WriteOutputUnt(i)(1:OutFileData%ActualChanLen) ) + end do ! i + + write (OutFileData%unOutFile,'()') + +end subroutine Dvr_InitializeOutputFile +!---------------------------------------------------------------------------------------------------------------------------------- +end module AeroDyn_Driver_Subs diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Types.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Types.f90 new file mode 100644 index 000000000..5d5a85517 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Driver_Types.f90 @@ -0,0 +1,2236 @@ +!STARTOFREGISTRYGENERATEDFILE 'AeroDyn_Driver_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 +!********************************************************************************************************************************* +! AeroDyn_Driver_Types +!................................................................................................................................. +! This file is part of AeroDyn_Driver. +! +! 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 AeroDyn_Driver. 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 AeroDyn_Driver_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE UnsteadyAero_Types +USE DBEMT_Types +USE BEMT_Types +USE FVW_Types +USE AeroAcoustics_Types +USE AeroDyn_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: numInp = 2 ! Determines order of interpolation for input-output extrap (2=linear;3=quadratic) [-] +! ========= Dvr_Case ======= + TYPE, PUBLIC :: Dvr_Case + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WndSpeed !< Wind Speed [m/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShearExp !< Power Law Wind-Shear Exponent [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RotSpeed !< Rotor Speed [rad/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Pitch !< Pitch angle [rad] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Yaw !< Yaw angle [rad] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: time !< time increment [s] + REAL(DbKi) :: dT !< time increment [s] + INTEGER(IntKi) :: numSteps !< number of steps in this case [-] + END TYPE Dvr_Case +! ======================= +! ========= Dvr_OutputFile ======= + TYPE, PUBLIC :: Dvr_OutputFile + TYPE(ProgDesc) :: AD_ver !< AeroDyn version information [-] + INTEGER(IntKi) :: unOutFile !< unit number for writing output file [-] + INTEGER(IntKi) :: ActualChanLen !< Actual length of channels written to text file (less than or equal to ChanLen) [-] + character(20) :: Fmt_t !< Format specifier for time channel [-] + character(25) :: Fmt_a !< Format specifier for each column (including delimiter) [-] + character(20) :: Fmt_i !< Format specifier for integer column [-] + character(1) :: delim !< column delimiter [-] + character(20) :: outFmt !< Format specifier [-] + character(1024) :: Root !< Output file rootname [-] + character(1024) :: runTitle !< Description string from input file [-] + character(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Channel headers [-] + character(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Channel units [-] + LOGICAL :: AllFiles !< Output file for each case [-] + LOGICAL :: SumFile !< Output summary file for all cases with last timestep [-] + END TYPE Dvr_OutputFile +! ======================= +! ========= AeroDyn_Data ======= + TYPE, PUBLIC :: AeroDyn_Data + TYPE(AD_ContinuousStateType) :: x !< Continuous states [-] + TYPE(AD_DiscreteStateType) :: xd !< Discrete states [-] + TYPE(AD_ConstraintStateType) :: z !< Constraint states [-] + TYPE(AD_OtherStateType) :: OtherState !< Other states [-] + TYPE(AD_MiscVarType) :: m !< misc/optimization variables [-] + TYPE(AD_ParameterType) :: p !< Parameters [-] + TYPE(AD_InputType) , DIMENSION(numInp) :: u !< Array of system inputs [-] + TYPE(AD_OutputType) :: y !< System outputs [-] + REAL(DbKi) , DIMENSION(numInp) :: InputTime !< Array of times associated with u array [-] + END TYPE AeroDyn_Data +! ======================= +! ========= Dvr_SimData ======= + TYPE, PUBLIC :: Dvr_SimData + character(1024) :: AD_InputFile !< Name of AeroDyn input file [-] + INTEGER(IntKi) :: numBlades !< number of blades on turbine [-] + REAL(ReKi) :: hubRad !< Hub radius [m] + REAL(ReKi) :: hubHt !< Hub height [m] + REAL(ReKi) :: overhang !< overhang [m] + REAL(ReKi) :: ShftTilt !< Shaft tilt angle [rad] + REAL(ReKi) :: Precone !< Precone angle (all blades) [rad] + INTEGER(IntKi) :: NumCases !< number of time-marching cases to run [-] + TYPE(Dvr_Case) , DIMENSION(:), ALLOCATABLE :: Cases !< table of cases to run [-] + TYPE(Dvr_OutputFile) :: OutFileData !< data for driver output file [-] + END TYPE Dvr_SimData +! ======================= +CONTAINS + SUBROUTINE AD_Dvr_CopyDvr_Case( SrcDvr_CaseData, DstDvr_CaseData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Dvr_Case), INTENT(IN) :: SrcDvr_CaseData + TYPE(Dvr_Case), INTENT(INOUT) :: DstDvr_CaseData + 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 = 'AD_Dvr_CopyDvr_Case' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcDvr_CaseData%WndSpeed)) THEN + i1_l = LBOUND(SrcDvr_CaseData%WndSpeed,1) + i1_u = UBOUND(SrcDvr_CaseData%WndSpeed,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%WndSpeed)) THEN + ALLOCATE(DstDvr_CaseData%WndSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%WndSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%WndSpeed = SrcDvr_CaseData%WndSpeed +ENDIF +IF (ALLOCATED(SrcDvr_CaseData%ShearExp)) THEN + i1_l = LBOUND(SrcDvr_CaseData%ShearExp,1) + i1_u = UBOUND(SrcDvr_CaseData%ShearExp,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%ShearExp)) THEN + ALLOCATE(DstDvr_CaseData%ShearExp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%ShearExp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%ShearExp = SrcDvr_CaseData%ShearExp +ENDIF +IF (ALLOCATED(SrcDvr_CaseData%RotSpeed)) THEN + i1_l = LBOUND(SrcDvr_CaseData%RotSpeed,1) + i1_u = UBOUND(SrcDvr_CaseData%RotSpeed,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%RotSpeed)) THEN + ALLOCATE(DstDvr_CaseData%RotSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%RotSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%RotSpeed = SrcDvr_CaseData%RotSpeed +ENDIF +IF (ALLOCATED(SrcDvr_CaseData%Pitch)) THEN + i1_l = LBOUND(SrcDvr_CaseData%Pitch,1) + i1_u = UBOUND(SrcDvr_CaseData%Pitch,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%Pitch)) THEN + ALLOCATE(DstDvr_CaseData%Pitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%Pitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%Pitch = SrcDvr_CaseData%Pitch +ENDIF +IF (ALLOCATED(SrcDvr_CaseData%Yaw)) THEN + i1_l = LBOUND(SrcDvr_CaseData%Yaw,1) + i1_u = UBOUND(SrcDvr_CaseData%Yaw,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%Yaw)) THEN + ALLOCATE(DstDvr_CaseData%Yaw(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%Yaw.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%Yaw = SrcDvr_CaseData%Yaw +ENDIF +IF (ALLOCATED(SrcDvr_CaseData%time)) THEN + i1_l = LBOUND(SrcDvr_CaseData%time,1) + i1_u = UBOUND(SrcDvr_CaseData%time,1) + IF (.NOT. ALLOCATED(DstDvr_CaseData%time)) THEN + ALLOCATE(DstDvr_CaseData%time(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_CaseData%time.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_CaseData%time = SrcDvr_CaseData%time +ENDIF + DstDvr_CaseData%dT = SrcDvr_CaseData%dT + DstDvr_CaseData%numSteps = SrcDvr_CaseData%numSteps + END SUBROUTINE AD_Dvr_CopyDvr_Case + + SUBROUTINE AD_Dvr_DestroyDvr_Case( Dvr_CaseData, ErrStat, ErrMsg ) + TYPE(Dvr_Case), INTENT(INOUT) :: Dvr_CaseData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Dvr_DestroyDvr_Case' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Dvr_CaseData%WndSpeed)) THEN + DEALLOCATE(Dvr_CaseData%WndSpeed) +ENDIF +IF (ALLOCATED(Dvr_CaseData%ShearExp)) THEN + DEALLOCATE(Dvr_CaseData%ShearExp) +ENDIF +IF (ALLOCATED(Dvr_CaseData%RotSpeed)) THEN + DEALLOCATE(Dvr_CaseData%RotSpeed) +ENDIF +IF (ALLOCATED(Dvr_CaseData%Pitch)) THEN + DEALLOCATE(Dvr_CaseData%Pitch) +ENDIF +IF (ALLOCATED(Dvr_CaseData%Yaw)) THEN + DEALLOCATE(Dvr_CaseData%Yaw) +ENDIF +IF (ALLOCATED(Dvr_CaseData%time)) THEN + DEALLOCATE(Dvr_CaseData%time) +ENDIF + END SUBROUTINE AD_Dvr_DestroyDvr_Case + + SUBROUTINE AD_Dvr_PackDvr_Case( 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(Dvr_Case), 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 = 'AD_Dvr_PackDvr_Case' + ! 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 ! WndSpeed allocated yes/no + IF ( ALLOCATED(InData%WndSpeed) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WndSpeed upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WndSpeed) ! WndSpeed + END IF + Int_BufSz = Int_BufSz + 1 ! ShearExp allocated yes/no + IF ( ALLOCATED(InData%ShearExp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ShearExp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ShearExp) ! ShearExp + END IF + Int_BufSz = Int_BufSz + 1 ! RotSpeed allocated yes/no + IF ( ALLOCATED(InData%RotSpeed) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotSpeed upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RotSpeed) ! RotSpeed + END IF + Int_BufSz = Int_BufSz + 1 ! Pitch allocated yes/no + IF ( ALLOCATED(InData%Pitch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Pitch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Pitch) ! Pitch + END IF + Int_BufSz = Int_BufSz + 1 ! Yaw allocated yes/no + IF ( ALLOCATED(InData%Yaw) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Yaw upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Yaw) ! Yaw + END IF + 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 + Db_BufSz = Db_BufSz + SIZE(InData%time) ! time + END IF + Db_BufSz = Db_BufSz + 1 ! dT + Int_BufSz = Int_BufSz + 1 ! numSteps + 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%WndSpeed) ) 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%WndSpeed,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WndSpeed,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WndSpeed,1), UBOUND(InData%WndSpeed,1) + ReKiBuf(Re_Xferred) = InData%WndSpeed(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ShearExp) ) 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%ShearExp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShearExp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ShearExp,1), UBOUND(InData%ShearExp,1) + ReKiBuf(Re_Xferred) = InData%ShearExp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotSpeed) ) 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%RotSpeed,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotSpeed,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotSpeed,1), UBOUND(InData%RotSpeed,1) + ReKiBuf(Re_Xferred) = InData%RotSpeed(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pitch) ) 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%Pitch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pitch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Pitch,1), UBOUND(InData%Pitch,1) + ReKiBuf(Re_Xferred) = InData%Pitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Yaw) ) 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%Yaw,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Yaw,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Yaw,1), UBOUND(InData%Yaw,1) + ReKiBuf(Re_Xferred) = InData%Yaw(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + 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) + DbKiBuf(Db_Xferred) = InData%time(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%dT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numSteps + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_Dvr_PackDvr_Case + + SUBROUTINE AD_Dvr_UnPackDvr_Case( 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(Dvr_Case), 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 = 'AD_Dvr_UnPackDvr_Case' + ! 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 ! WndSpeed 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%WndSpeed)) DEALLOCATE(OutData%WndSpeed) + ALLOCATE(OutData%WndSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WndSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WndSpeed,1), UBOUND(OutData%WndSpeed,1) + OutData%WndSpeed(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShearExp 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%ShearExp)) DEALLOCATE(OutData%ShearExp) + ALLOCATE(OutData%ShearExp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShearExp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ShearExp,1), UBOUND(OutData%ShearExp,1) + OutData%ShearExp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotSpeed 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%RotSpeed)) DEALLOCATE(OutData%RotSpeed) + ALLOCATE(OutData%RotSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotSpeed,1), UBOUND(OutData%RotSpeed,1) + OutData%RotSpeed(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pitch 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%Pitch)) DEALLOCATE(OutData%Pitch) + ALLOCATE(OutData%Pitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Pitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Pitch,1), UBOUND(OutData%Pitch,1) + OutData%Pitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Yaw 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%Yaw)) DEALLOCATE(OutData%Yaw) + ALLOCATE(OutData%Yaw(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Yaw.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Yaw,1), UBOUND(OutData%Yaw,1) + OutData%Yaw(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + 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) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%dT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%numSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_Dvr_UnPackDvr_Case + + SUBROUTINE AD_Dvr_CopyDvr_OutputFile( SrcDvr_OutputFileData, DstDvr_OutputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Dvr_OutputFile), INTENT(IN) :: SrcDvr_OutputFileData + TYPE(Dvr_OutputFile), INTENT(INOUT) :: DstDvr_OutputFileData + 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 = 'AD_Dvr_CopyDvr_OutputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Copyprogdesc( SrcDvr_OutputFileData%AD_ver, DstDvr_OutputFileData%AD_ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstDvr_OutputFileData%unOutFile = SrcDvr_OutputFileData%unOutFile + DstDvr_OutputFileData%ActualChanLen = SrcDvr_OutputFileData%ActualChanLen + DstDvr_OutputFileData%Fmt_t = SrcDvr_OutputFileData%Fmt_t + DstDvr_OutputFileData%Fmt_a = SrcDvr_OutputFileData%Fmt_a + DstDvr_OutputFileData%Fmt_i = SrcDvr_OutputFileData%Fmt_i + DstDvr_OutputFileData%delim = SrcDvr_OutputFileData%delim + DstDvr_OutputFileData%outFmt = SrcDvr_OutputFileData%outFmt + DstDvr_OutputFileData%Root = SrcDvr_OutputFileData%Root + DstDvr_OutputFileData%runTitle = SrcDvr_OutputFileData%runTitle +IF (ALLOCATED(SrcDvr_OutputFileData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcDvr_OutputFileData%WriteOutputHdr,1) + i1_u = UBOUND(SrcDvr_OutputFileData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstDvr_OutputFileData%WriteOutputHdr)) THEN + ALLOCATE(DstDvr_OutputFileData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_OutputFileData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_OutputFileData%WriteOutputHdr = SrcDvr_OutputFileData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcDvr_OutputFileData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcDvr_OutputFileData%WriteOutputUnt,1) + i1_u = UBOUND(SrcDvr_OutputFileData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstDvr_OutputFileData%WriteOutputUnt)) THEN + ALLOCATE(DstDvr_OutputFileData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_OutputFileData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDvr_OutputFileData%WriteOutputUnt = SrcDvr_OutputFileData%WriteOutputUnt +ENDIF + DstDvr_OutputFileData%AllFiles = SrcDvr_OutputFileData%AllFiles + DstDvr_OutputFileData%SumFile = SrcDvr_OutputFileData%SumFile + END SUBROUTINE AD_Dvr_CopyDvr_OutputFile + + SUBROUTINE AD_Dvr_DestroyDvr_OutputFile( Dvr_OutputFileData, ErrStat, ErrMsg ) + TYPE(Dvr_OutputFile), INTENT(INOUT) :: Dvr_OutputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Dvr_DestroyDvr_OutputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( Dvr_OutputFileData%AD_ver, ErrStat, ErrMsg ) +IF (ALLOCATED(Dvr_OutputFileData%WriteOutputHdr)) THEN + DEALLOCATE(Dvr_OutputFileData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(Dvr_OutputFileData%WriteOutputUnt)) THEN + DEALLOCATE(Dvr_OutputFileData%WriteOutputUnt) +ENDIF + END SUBROUTINE AD_Dvr_DestroyDvr_OutputFile + + SUBROUTINE AD_Dvr_PackDvr_OutputFile( 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(Dvr_OutputFile), 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 = 'AD_Dvr_PackDvr_OutputFile' + ! 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 ! AD_ver: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%AD_ver, ErrStat2, ErrMsg2, .TRUE. ) ! AD_ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AD_ver + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AD_ver + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AD_ver + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! unOutFile + Int_BufSz = Int_BufSz + 1 ! ActualChanLen + Int_BufSz = Int_BufSz + 1*LEN(InData%Fmt_t) ! Fmt_t + Int_BufSz = Int_BufSz + 1*LEN(InData%Fmt_a) ! Fmt_a + Int_BufSz = Int_BufSz + 1*LEN(InData%Fmt_i) ! Fmt_i + Int_BufSz = Int_BufSz + 1*LEN(InData%delim) ! delim + Int_BufSz = Int_BufSz + 1*LEN(InData%outFmt) ! outFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Root) ! Root + Int_BufSz = Int_BufSz + 1*LEN(InData%runTitle) ! runTitle + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! AllFiles + Int_BufSz = Int_BufSz + 1 ! SumFile + 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%AD_ver, ErrStat2, ErrMsg2, OnlySize ) ! AD_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 + IntKiBuf(Int_Xferred) = InData%unOutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ActualChanLen + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Fmt_t) + IntKiBuf(Int_Xferred) = ICHAR(InData%Fmt_t(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Fmt_a) + IntKiBuf(Int_Xferred) = ICHAR(InData%Fmt_a(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Fmt_i) + IntKiBuf(Int_Xferred) = ICHAR(InData%Fmt_i(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%outFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%outFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Root) + IntKiBuf(Int_Xferred) = ICHAR(InData%Root(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%runTitle) + IntKiBuf(Int_Xferred) = ICHAR(InData%runTitle(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%AllFiles, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_Dvr_PackDvr_OutputFile + + SUBROUTINE AD_Dvr_UnPackDvr_OutputFile( 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(Dvr_OutputFile), 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 = 'AD_Dvr_UnPackDvr_OutputFile' + ! 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%AD_ver, ErrStat2, ErrMsg2 ) ! AD_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%unOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ActualChanLen = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Fmt_t) + OutData%Fmt_t(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Fmt_a) + OutData%Fmt_a(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Fmt_i) + OutData%Fmt_i(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%delim) + OutData%delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%outFmt) + OutData%outFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Root) + OutData%Root(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%runTitle) + OutData%runTitle(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%AllFiles = TRANSFER(IntKiBuf(Int_Xferred), OutData%AllFiles) + Int_Xferred = Int_Xferred + 1 + OutData%SumFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumFile) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_Dvr_UnPackDvr_OutputFile + + SUBROUTINE AD_Dvr_CopyAeroDyn_Data( SrcAeroDyn_DataData, DstAeroDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AeroDyn_Data), INTENT(INOUT) :: SrcAeroDyn_DataData + TYPE(AeroDyn_Data), INTENT(INOUT) :: DstAeroDyn_DataData + 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 = 'AD_Dvr_CopyAeroDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL AD_CopyContState( SrcAeroDyn_DataData%x, DstAeroDyn_DataData%x, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyDiscState( SrcAeroDyn_DataData%xd, DstAeroDyn_DataData%xd, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyConstrState( SrcAeroDyn_DataData%z, DstAeroDyn_DataData%z, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyOtherState( SrcAeroDyn_DataData%OtherState, DstAeroDyn_DataData%OtherState, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyMisc( SrcAeroDyn_DataData%m, DstAeroDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyParam( SrcAeroDyn_DataData%p, DstAeroDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DO i1 = LBOUND(SrcAeroDyn_DataData%u,1), UBOUND(SrcAeroDyn_DataData%u,1) + CALL AD_CopyInput( SrcAeroDyn_DataData%u(i1), DstAeroDyn_DataData%u(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL AD_CopyOutput( SrcAeroDyn_DataData%y, DstAeroDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstAeroDyn_DataData%InputTime = SrcAeroDyn_DataData%InputTime + END SUBROUTINE AD_Dvr_CopyAeroDyn_Data + + SUBROUTINE AD_Dvr_DestroyAeroDyn_Data( AeroDyn_DataData, ErrStat, ErrMsg ) + TYPE(AeroDyn_Data), INTENT(INOUT) :: AeroDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Dvr_DestroyAeroDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL AD_DestroyContState( AeroDyn_DataData%x, ErrStat, ErrMsg ) + CALL AD_DestroyDiscState( AeroDyn_DataData%xd, ErrStat, ErrMsg ) + CALL AD_DestroyConstrState( AeroDyn_DataData%z, ErrStat, ErrMsg ) + CALL AD_DestroyOtherState( AeroDyn_DataData%OtherState, ErrStat, ErrMsg ) + CALL AD_DestroyMisc( AeroDyn_DataData%m, ErrStat, ErrMsg ) + CALL AD_DestroyParam( AeroDyn_DataData%p, ErrStat, ErrMsg ) +DO i1 = LBOUND(AeroDyn_DataData%u,1), UBOUND(AeroDyn_DataData%u,1) + CALL AD_DestroyInput( AeroDyn_DataData%u(i1), ErrStat, ErrMsg ) +ENDDO + CALL AD_DestroyOutput( AeroDyn_DataData%y, ErrStat, ErrMsg ) + END SUBROUTINE AD_Dvr_DestroyAeroDyn_Data + + SUBROUTINE AD_Dvr_PackAeroDyn_Data( 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(AeroDyn_Data), 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 = 'AD_Dvr_PackAeroDyn_Data' + ! 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 ! x: size of buffers for each call to pack subtype + CALL AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x, ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd, ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z, ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OtherState: size of buffers for each call to pack subtype + CALL AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherState, ErrStat2, ErrMsg2, .TRUE. ) ! OtherState + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherState + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherState + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherState + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL AD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL AD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Db_BufSz = Db_BufSz + SIZE(InData%InputTime) ! InputTime + 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 AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x, ErrStat2, ErrMsg2, OnlySize ) ! x + 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 AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd, ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z, ErrStat2, ErrMsg2, OnlySize ) ! z + 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 AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherState, ErrStat2, ErrMsg2, OnlySize ) ! OtherState + 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 AD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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 AD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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%u,1), UBOUND(InData%u,1) + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, OnlySize ) ! u + 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 + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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%InputTime,1), UBOUND(InData%InputTime,1) + DbKiBuf(Db_Xferred) = InData%InputTime(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE AD_Dvr_PackAeroDyn_Data + + SUBROUTINE AD_Dvr_UnPackAeroDyn_Data( 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(AeroDyn_Data), 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 = 'AD_Dvr_UnPackAeroDyn_Data' + ! 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 AD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x, ErrStat2, ErrMsg2 ) ! x + 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 AD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd, ErrStat2, ErrMsg2 ) ! xd + 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 AD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z, ErrStat2, ErrMsg2 ) ! z + 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 AD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherState, ErrStat2, ErrMsg2 ) ! OtherState + 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 AD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 AD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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%u,1) + i1_u = UBOUND(OutData%u,1) + DO i1 = LBOUND(OutData%u,1), UBOUND(OutData%u,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 AD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u(i1), ErrStat2, ErrMsg2 ) ! u + 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 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 AD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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%InputTime,1) + i1_u = UBOUND(OutData%InputTime,1) + DO i1 = LBOUND(OutData%InputTime,1), UBOUND(OutData%InputTime,1) + OutData%InputTime(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE AD_Dvr_UnPackAeroDyn_Data + + SUBROUTINE AD_Dvr_CopyDvr_SimData( SrcDvr_SimDataData, DstDvr_SimDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Dvr_SimData), INTENT(IN) :: SrcDvr_SimDataData + TYPE(Dvr_SimData), INTENT(INOUT) :: DstDvr_SimDataData + 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 = 'AD_Dvr_CopyDvr_SimData' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDvr_SimDataData%AD_InputFile = SrcDvr_SimDataData%AD_InputFile + DstDvr_SimDataData%numBlades = SrcDvr_SimDataData%numBlades + DstDvr_SimDataData%hubRad = SrcDvr_SimDataData%hubRad + DstDvr_SimDataData%hubHt = SrcDvr_SimDataData%hubHt + DstDvr_SimDataData%overhang = SrcDvr_SimDataData%overhang + DstDvr_SimDataData%ShftTilt = SrcDvr_SimDataData%ShftTilt + DstDvr_SimDataData%Precone = SrcDvr_SimDataData%Precone + DstDvr_SimDataData%NumCases = SrcDvr_SimDataData%NumCases +IF (ALLOCATED(SrcDvr_SimDataData%Cases)) THEN + i1_l = LBOUND(SrcDvr_SimDataData%Cases,1) + i1_u = UBOUND(SrcDvr_SimDataData%Cases,1) + IF (.NOT. ALLOCATED(DstDvr_SimDataData%Cases)) THEN + ALLOCATE(DstDvr_SimDataData%Cases(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDvr_SimDataData%Cases.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcDvr_SimDataData%Cases,1), UBOUND(SrcDvr_SimDataData%Cases,1) + CALL AD_Dvr_Copydvr_case( SrcDvr_SimDataData%Cases(i1), DstDvr_SimDataData%Cases(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL AD_Dvr_Copydvr_outputfile( SrcDvr_SimDataData%OutFileData, DstDvr_SimDataData%OutFileData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_Dvr_CopyDvr_SimData + + SUBROUTINE AD_Dvr_DestroyDvr_SimData( Dvr_SimDataData, ErrStat, ErrMsg ) + TYPE(Dvr_SimData), INTENT(INOUT) :: Dvr_SimDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Dvr_DestroyDvr_SimData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Dvr_SimDataData%Cases)) THEN +DO i1 = LBOUND(Dvr_SimDataData%Cases,1), UBOUND(Dvr_SimDataData%Cases,1) + CALL AD_Dvr_Destroydvr_case( Dvr_SimDataData%Cases(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(Dvr_SimDataData%Cases) +ENDIF + CALL AD_Dvr_Destroydvr_outputfile( Dvr_SimDataData%OutFileData, ErrStat, ErrMsg ) + END SUBROUTINE AD_Dvr_DestroyDvr_SimData + + SUBROUTINE AD_Dvr_PackDvr_SimData( 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(Dvr_SimData), 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 = 'AD_Dvr_PackDvr_SimData' + ! 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%AD_InputFile) ! AD_InputFile + Int_BufSz = Int_BufSz + 1 ! numBlades + Re_BufSz = Re_BufSz + 1 ! hubRad + Re_BufSz = Re_BufSz + 1 ! hubHt + Re_BufSz = Re_BufSz + 1 ! overhang + Re_BufSz = Re_BufSz + 1 ! ShftTilt + Re_BufSz = Re_BufSz + 1 ! Precone + Int_BufSz = Int_BufSz + 1 ! NumCases + Int_BufSz = Int_BufSz + 1 ! Cases allocated yes/no + IF ( ALLOCATED(InData%Cases) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Cases upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Cases,1), UBOUND(InData%Cases,1) + Int_BufSz = Int_BufSz + 3 ! Cases: size of buffers for each call to pack subtype + CALL AD_Dvr_Packdvr_case( Re_Buf, Db_Buf, Int_Buf, InData%Cases(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Cases + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Cases + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Cases + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Cases + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! OutFileData: size of buffers for each call to pack subtype + CALL AD_Dvr_Packdvr_outputfile( Re_Buf, Db_Buf, Int_Buf, InData%OutFileData, ErrStat2, ErrMsg2, .TRUE. ) ! OutFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutFileData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutFileData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutFileData + 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%AD_InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%AD_InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%numBlades + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%hubRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%hubHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%overhang + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShftTilt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Precone + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCases + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Cases) ) 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%Cases,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cases,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Cases,1), UBOUND(InData%Cases,1) + CALL AD_Dvr_Packdvr_case( Re_Buf, Db_Buf, Int_Buf, InData%Cases(i1), ErrStat2, ErrMsg2, OnlySize ) ! Cases + 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 + CALL AD_Dvr_Packdvr_outputfile( Re_Buf, Db_Buf, Int_Buf, InData%OutFileData, ErrStat2, ErrMsg2, OnlySize ) ! OutFileData + 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 AD_Dvr_PackDvr_SimData + + SUBROUTINE AD_Dvr_UnPackDvr_SimData( 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(Dvr_SimData), 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 = 'AD_Dvr_UnPackDvr_SimData' + ! 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%AD_InputFile) + OutData%AD_InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%numBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%hubRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%hubHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%overhang = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShftTilt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Precone = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumCases = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cases 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%Cases)) DEALLOCATE(OutData%Cases) + ALLOCATE(OutData%Cases(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cases.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Cases,1), UBOUND(OutData%Cases,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 AD_Dvr_Unpackdvr_case( Re_Buf, Db_Buf, Int_Buf, OutData%Cases(i1), ErrStat2, ErrMsg2 ) ! Cases + 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 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 AD_Dvr_Unpackdvr_outputfile( Re_Buf, Db_Buf, Int_Buf, OutData%OutFileData, ErrStat2, ErrMsg2 ) ! OutFileData + 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 AD_Dvr_UnPackDvr_SimData + +END MODULE AeroDyn_Driver_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_IO.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_IO.f90 new file mode 100644 index 000000000..f66e3a93d --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_IO.f90 @@ -0,0 +1,3443 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 AeroDyn_IO + + use NWTC_Library + use AeroDyn_Types + use BEMTUncoupled, only : SkewMod_Uncoupled, SkewMod_PittPeters, VelocityIsZero + use AirFoilInfo, only : AFI_ComputeAirfoilCoefs + use FVW_Subs, only : FVW_AeroOuts + + USE AeroDyn_AllBldNdOuts_IO + + implicit none + + type(ProgDesc), parameter :: AD_Ver = ProgDesc( 'AeroDyn', '', '' ) + character(*), parameter :: AD_Nickname = 'AD' + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 31-Aug-2020 13:14:21. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Tower: + + INTEGER(IntKi), PARAMETER :: TwN1VUndx = 1 + INTEGER(IntKi), PARAMETER :: TwN1VUndy = 2 + INTEGER(IntKi), PARAMETER :: TwN1VUndz = 3 + INTEGER(IntKi), PARAMETER :: TwN2VUndx = 4 + INTEGER(IntKi), PARAMETER :: TwN2VUndy = 5 + INTEGER(IntKi), PARAMETER :: TwN2VUndz = 6 + INTEGER(IntKi), PARAMETER :: TwN3VUndx = 7 + INTEGER(IntKi), PARAMETER :: TwN3VUndy = 8 + INTEGER(IntKi), PARAMETER :: TwN3VUndz = 9 + INTEGER(IntKi), PARAMETER :: TwN4VUndx = 10 + INTEGER(IntKi), PARAMETER :: TwN4VUndy = 11 + INTEGER(IntKi), PARAMETER :: TwN4VUndz = 12 + INTEGER(IntKi), PARAMETER :: TwN5VUndx = 13 + INTEGER(IntKi), PARAMETER :: TwN5VUndy = 14 + INTEGER(IntKi), PARAMETER :: TwN5VUndz = 15 + INTEGER(IntKi), PARAMETER :: TwN6VUndx = 16 + INTEGER(IntKi), PARAMETER :: TwN6VUndy = 17 + INTEGER(IntKi), PARAMETER :: TwN6VUndz = 18 + INTEGER(IntKi), PARAMETER :: TwN7VUndx = 19 + INTEGER(IntKi), PARAMETER :: TwN7VUndy = 20 + INTEGER(IntKi), PARAMETER :: TwN7VUndz = 21 + INTEGER(IntKi), PARAMETER :: TwN8VUndx = 22 + INTEGER(IntKi), PARAMETER :: TwN8VUndy = 23 + INTEGER(IntKi), PARAMETER :: TwN8VUndz = 24 + INTEGER(IntKi), PARAMETER :: TwN9VUndx = 25 + INTEGER(IntKi), PARAMETER :: TwN9VUndy = 26 + INTEGER(IntKi), PARAMETER :: TwN9VUndz = 27 + INTEGER(IntKi), PARAMETER :: TwN1STVx = 28 + INTEGER(IntKi), PARAMETER :: TwN1STVy = 29 + INTEGER(IntKi), PARAMETER :: TwN1STVz = 30 + INTEGER(IntKi), PARAMETER :: TwN2STVx = 31 + INTEGER(IntKi), PARAMETER :: TwN2STVy = 32 + INTEGER(IntKi), PARAMETER :: TwN2STVz = 33 + INTEGER(IntKi), PARAMETER :: TwN3STVx = 34 + INTEGER(IntKi), PARAMETER :: TwN3STVy = 35 + INTEGER(IntKi), PARAMETER :: TwN3STVz = 36 + INTEGER(IntKi), PARAMETER :: TwN4STVx = 37 + INTEGER(IntKi), PARAMETER :: TwN4STVy = 38 + INTEGER(IntKi), PARAMETER :: TwN4STVz = 39 + INTEGER(IntKi), PARAMETER :: TwN5STVx = 40 + INTEGER(IntKi), PARAMETER :: TwN5STVy = 41 + INTEGER(IntKi), PARAMETER :: TwN5STVz = 42 + INTEGER(IntKi), PARAMETER :: TwN6STVx = 43 + INTEGER(IntKi), PARAMETER :: TwN6STVy = 44 + INTEGER(IntKi), PARAMETER :: TwN6STVz = 45 + INTEGER(IntKi), PARAMETER :: TwN7STVx = 46 + INTEGER(IntKi), PARAMETER :: TwN7STVy = 47 + INTEGER(IntKi), PARAMETER :: TwN7STVz = 48 + INTEGER(IntKi), PARAMETER :: TwN8STVx = 49 + INTEGER(IntKi), PARAMETER :: TwN8STVy = 50 + INTEGER(IntKi), PARAMETER :: TwN8STVz = 51 + INTEGER(IntKi), PARAMETER :: TwN9STVx = 52 + INTEGER(IntKi), PARAMETER :: TwN9STVy = 53 + INTEGER(IntKi), PARAMETER :: TwN9STVz = 54 + INTEGER(IntKi), PARAMETER :: TwN1Vrel = 55 + INTEGER(IntKi), PARAMETER :: TwN2Vrel = 56 + INTEGER(IntKi), PARAMETER :: TwN3Vrel = 57 + INTEGER(IntKi), PARAMETER :: TwN4Vrel = 58 + INTEGER(IntKi), PARAMETER :: TwN5Vrel = 59 + INTEGER(IntKi), PARAMETER :: TwN6Vrel = 60 + INTEGER(IntKi), PARAMETER :: TwN7Vrel = 61 + INTEGER(IntKi), PARAMETER :: TwN8Vrel = 62 + INTEGER(IntKi), PARAMETER :: TwN9Vrel = 63 + INTEGER(IntKi), PARAMETER :: TwN1DynP = 64 + INTEGER(IntKi), PARAMETER :: TwN2DynP = 65 + INTEGER(IntKi), PARAMETER :: TwN3DynP = 66 + INTEGER(IntKi), PARAMETER :: TwN4DynP = 67 + INTEGER(IntKi), PARAMETER :: TwN5DynP = 68 + INTEGER(IntKi), PARAMETER :: TwN6DynP = 69 + INTEGER(IntKi), PARAMETER :: TwN7DynP = 70 + INTEGER(IntKi), PARAMETER :: TwN8DynP = 71 + INTEGER(IntKi), PARAMETER :: TwN9DynP = 72 + INTEGER(IntKi), PARAMETER :: TwN1Re = 73 + INTEGER(IntKi), PARAMETER :: TwN2Re = 74 + INTEGER(IntKi), PARAMETER :: TwN3Re = 75 + INTEGER(IntKi), PARAMETER :: TwN4Re = 76 + INTEGER(IntKi), PARAMETER :: TwN5Re = 77 + INTEGER(IntKi), PARAMETER :: TwN6Re = 78 + INTEGER(IntKi), PARAMETER :: TwN7Re = 79 + INTEGER(IntKi), PARAMETER :: TwN8Re = 80 + INTEGER(IntKi), PARAMETER :: TwN9Re = 81 + INTEGER(IntKi), PARAMETER :: TwN1M = 82 + INTEGER(IntKi), PARAMETER :: TwN2M = 83 + INTEGER(IntKi), PARAMETER :: TwN3M = 84 + INTEGER(IntKi), PARAMETER :: TwN4M = 85 + INTEGER(IntKi), PARAMETER :: TwN5M = 86 + INTEGER(IntKi), PARAMETER :: TwN6M = 87 + INTEGER(IntKi), PARAMETER :: TwN7M = 88 + INTEGER(IntKi), PARAMETER :: TwN8M = 89 + INTEGER(IntKi), PARAMETER :: TwN9M = 90 + INTEGER(IntKi), PARAMETER :: TwN1Fdx = 91 + INTEGER(IntKi), PARAMETER :: TwN2Fdx = 92 + INTEGER(IntKi), PARAMETER :: TwN3Fdx = 93 + INTEGER(IntKi), PARAMETER :: TwN4Fdx = 94 + INTEGER(IntKi), PARAMETER :: TwN5Fdx = 95 + INTEGER(IntKi), PARAMETER :: TwN6Fdx = 96 + INTEGER(IntKi), PARAMETER :: TwN7Fdx = 97 + INTEGER(IntKi), PARAMETER :: TwN8Fdx = 98 + INTEGER(IntKi), PARAMETER :: TwN9Fdx = 99 + INTEGER(IntKi), PARAMETER :: TwN1Fdy = 100 + INTEGER(IntKi), PARAMETER :: TwN2Fdy = 101 + INTEGER(IntKi), PARAMETER :: TwN3Fdy = 102 + INTEGER(IntKi), PARAMETER :: TwN4Fdy = 103 + INTEGER(IntKi), PARAMETER :: TwN5Fdy = 104 + INTEGER(IntKi), PARAMETER :: TwN6Fdy = 105 + INTEGER(IntKi), PARAMETER :: TwN7Fdy = 106 + INTEGER(IntKi), PARAMETER :: TwN8Fdy = 107 + INTEGER(IntKi), PARAMETER :: TwN9Fdy = 108 + + + ! Blade: + + INTEGER(IntKi), PARAMETER :: B1Azimuth = 109 + INTEGER(IntKi), PARAMETER :: B2Azimuth = 110 + INTEGER(IntKi), PARAMETER :: B3Azimuth = 111 + INTEGER(IntKi), PARAMETER :: B1Pitch = 112 + INTEGER(IntKi), PARAMETER :: B2Pitch = 113 + INTEGER(IntKi), PARAMETER :: B3Pitch = 114 + INTEGER(IntKi), PARAMETER :: B1N1VUndx = 115 + INTEGER(IntKi), PARAMETER :: B1N2VUndx = 116 + INTEGER(IntKi), PARAMETER :: B1N3VUndx = 117 + INTEGER(IntKi), PARAMETER :: B1N4VUndx = 118 + INTEGER(IntKi), PARAMETER :: B1N5VUndx = 119 + INTEGER(IntKi), PARAMETER :: B1N6VUndx = 120 + INTEGER(IntKi), PARAMETER :: B1N7VUndx = 121 + INTEGER(IntKi), PARAMETER :: B1N8VUndx = 122 + INTEGER(IntKi), PARAMETER :: B1N9VUndx = 123 + INTEGER(IntKi), PARAMETER :: B1N1VUndy = 124 + INTEGER(IntKi), PARAMETER :: B1N2VUndy = 125 + INTEGER(IntKi), PARAMETER :: B1N3VUndy = 126 + INTEGER(IntKi), PARAMETER :: B1N4VUndy = 127 + INTEGER(IntKi), PARAMETER :: B1N5VUndy = 128 + INTEGER(IntKi), PARAMETER :: B1N6VUndy = 129 + INTEGER(IntKi), PARAMETER :: B1N7VUndy = 130 + INTEGER(IntKi), PARAMETER :: B1N8VUndy = 131 + INTEGER(IntKi), PARAMETER :: B1N9VUndy = 132 + INTEGER(IntKi), PARAMETER :: B1N1VUndz = 133 + INTEGER(IntKi), PARAMETER :: B1N2VUndz = 134 + INTEGER(IntKi), PARAMETER :: B1N3VUndz = 135 + INTEGER(IntKi), PARAMETER :: B1N4VUndz = 136 + INTEGER(IntKi), PARAMETER :: B1N5VUndz = 137 + INTEGER(IntKi), PARAMETER :: B1N6VUndz = 138 + INTEGER(IntKi), PARAMETER :: B1N7VUndz = 139 + INTEGER(IntKi), PARAMETER :: B1N8VUndz = 140 + INTEGER(IntKi), PARAMETER :: B1N9VUndz = 141 + INTEGER(IntKi), PARAMETER :: B2N1VUndx = 142 + INTEGER(IntKi), PARAMETER :: B2N2VUndx = 143 + INTEGER(IntKi), PARAMETER :: B2N3VUndx = 144 + INTEGER(IntKi), PARAMETER :: B2N4VUndx = 145 + INTEGER(IntKi), PARAMETER :: B2N5VUndx = 146 + INTEGER(IntKi), PARAMETER :: B2N6VUndx = 147 + INTEGER(IntKi), PARAMETER :: B2N7VUndx = 148 + INTEGER(IntKi), PARAMETER :: B2N8VUndx = 149 + INTEGER(IntKi), PARAMETER :: B2N9VUndx = 150 + INTEGER(IntKi), PARAMETER :: B2N1VUndy = 151 + INTEGER(IntKi), PARAMETER :: B2N2VUndy = 152 + INTEGER(IntKi), PARAMETER :: B2N3VUndy = 153 + INTEGER(IntKi), PARAMETER :: B2N4VUndy = 154 + INTEGER(IntKi), PARAMETER :: B2N5VUndy = 155 + INTEGER(IntKi), PARAMETER :: B2N6VUndy = 156 + INTEGER(IntKi), PARAMETER :: B2N7VUndy = 157 + INTEGER(IntKi), PARAMETER :: B2N8VUndy = 158 + INTEGER(IntKi), PARAMETER :: B2N9VUndy = 159 + INTEGER(IntKi), PARAMETER :: B2N1VUndz = 160 + INTEGER(IntKi), PARAMETER :: B2N2VUndz = 161 + INTEGER(IntKi), PARAMETER :: B2N3VUndz = 162 + INTEGER(IntKi), PARAMETER :: B2N4VUndz = 163 + INTEGER(IntKi), PARAMETER :: B2N5VUndz = 164 + INTEGER(IntKi), PARAMETER :: B2N6VUndz = 165 + INTEGER(IntKi), PARAMETER :: B2N7VUndz = 166 + INTEGER(IntKi), PARAMETER :: B2N8VUndz = 167 + INTEGER(IntKi), PARAMETER :: B2N9VUndz = 168 + INTEGER(IntKi), PARAMETER :: B3N1VUndx = 169 + INTEGER(IntKi), PARAMETER :: B3N2VUndx = 170 + INTEGER(IntKi), PARAMETER :: B3N3VUndx = 171 + INTEGER(IntKi), PARAMETER :: B3N4VUndx = 172 + INTEGER(IntKi), PARAMETER :: B3N5VUndx = 173 + INTEGER(IntKi), PARAMETER :: B3N6VUndx = 174 + INTEGER(IntKi), PARAMETER :: B3N7VUndx = 175 + INTEGER(IntKi), PARAMETER :: B3N8VUndx = 176 + INTEGER(IntKi), PARAMETER :: B3N9VUndx = 177 + INTEGER(IntKi), PARAMETER :: B3N1VUndy = 178 + INTEGER(IntKi), PARAMETER :: B3N2VUndy = 179 + INTEGER(IntKi), PARAMETER :: B3N3VUndy = 180 + INTEGER(IntKi), PARAMETER :: B3N4VUndy = 181 + INTEGER(IntKi), PARAMETER :: B3N5VUndy = 182 + INTEGER(IntKi), PARAMETER :: B3N6VUndy = 183 + INTEGER(IntKi), PARAMETER :: B3N7VUndy = 184 + INTEGER(IntKi), PARAMETER :: B3N8VUndy = 185 + INTEGER(IntKi), PARAMETER :: B3N9VUndy = 186 + INTEGER(IntKi), PARAMETER :: B3N1VUndz = 187 + INTEGER(IntKi), PARAMETER :: B3N2VUndz = 188 + INTEGER(IntKi), PARAMETER :: B3N3VUndz = 189 + INTEGER(IntKi), PARAMETER :: B3N4VUndz = 190 + INTEGER(IntKi), PARAMETER :: B3N5VUndz = 191 + INTEGER(IntKi), PARAMETER :: B3N6VUndz = 192 + INTEGER(IntKi), PARAMETER :: B3N7VUndz = 193 + INTEGER(IntKi), PARAMETER :: B3N8VUndz = 194 + INTEGER(IntKi), PARAMETER :: B3N9VUndz = 195 + INTEGER(IntKi), PARAMETER :: B1N1VDisx = 196 + INTEGER(IntKi), PARAMETER :: B1N2VDisx = 197 + INTEGER(IntKi), PARAMETER :: B1N3VDisx = 198 + INTEGER(IntKi), PARAMETER :: B1N4VDisx = 199 + INTEGER(IntKi), PARAMETER :: B1N5VDisx = 200 + INTEGER(IntKi), PARAMETER :: B1N6VDisx = 201 + INTEGER(IntKi), PARAMETER :: B1N7VDisx = 202 + INTEGER(IntKi), PARAMETER :: B1N8VDisx = 203 + INTEGER(IntKi), PARAMETER :: B1N9VDisx = 204 + INTEGER(IntKi), PARAMETER :: B1N1VDisy = 205 + INTEGER(IntKi), PARAMETER :: B1N2VDisy = 206 + INTEGER(IntKi), PARAMETER :: B1N3VDisy = 207 + INTEGER(IntKi), PARAMETER :: B1N4VDisy = 208 + INTEGER(IntKi), PARAMETER :: B1N5VDisy = 209 + INTEGER(IntKi), PARAMETER :: B1N6VDisy = 210 + INTEGER(IntKi), PARAMETER :: B1N7VDisy = 211 + INTEGER(IntKi), PARAMETER :: B1N8VDisy = 212 + INTEGER(IntKi), PARAMETER :: B1N9VDisy = 213 + INTEGER(IntKi), PARAMETER :: B1N1VDisz = 214 + INTEGER(IntKi), PARAMETER :: B1N2VDisz = 215 + INTEGER(IntKi), PARAMETER :: B1N3VDisz = 216 + INTEGER(IntKi), PARAMETER :: B1N4VDisz = 217 + INTEGER(IntKi), PARAMETER :: B1N5VDisz = 218 + INTEGER(IntKi), PARAMETER :: B1N6VDisz = 219 + INTEGER(IntKi), PARAMETER :: B1N7VDisz = 220 + INTEGER(IntKi), PARAMETER :: B1N8VDisz = 221 + INTEGER(IntKi), PARAMETER :: B1N9VDisz = 222 + INTEGER(IntKi), PARAMETER :: B2N1VDisx = 223 + INTEGER(IntKi), PARAMETER :: B2N2VDisx = 224 + INTEGER(IntKi), PARAMETER :: B2N3VDisx = 225 + INTEGER(IntKi), PARAMETER :: B2N4VDisx = 226 + INTEGER(IntKi), PARAMETER :: B2N5VDisx = 227 + INTEGER(IntKi), PARAMETER :: B2N6VDisx = 228 + INTEGER(IntKi), PARAMETER :: B2N7VDisx = 229 + INTEGER(IntKi), PARAMETER :: B2N8VDisx = 230 + INTEGER(IntKi), PARAMETER :: B2N9VDisx = 231 + INTEGER(IntKi), PARAMETER :: B2N1VDisy = 232 + INTEGER(IntKi), PARAMETER :: B2N2VDisy = 233 + INTEGER(IntKi), PARAMETER :: B2N3VDisy = 234 + INTEGER(IntKi), PARAMETER :: B2N4VDisy = 235 + INTEGER(IntKi), PARAMETER :: B2N5VDisy = 236 + INTEGER(IntKi), PARAMETER :: B2N6VDisy = 237 + INTEGER(IntKi), PARAMETER :: B2N7VDisy = 238 + INTEGER(IntKi), PARAMETER :: B2N8VDisy = 239 + INTEGER(IntKi), PARAMETER :: B2N9VDisy = 240 + INTEGER(IntKi), PARAMETER :: B2N1VDisz = 241 + INTEGER(IntKi), PARAMETER :: B2N2VDisz = 242 + INTEGER(IntKi), PARAMETER :: B2N3VDisz = 243 + INTEGER(IntKi), PARAMETER :: B2N4VDisz = 244 + INTEGER(IntKi), PARAMETER :: B2N5VDisz = 245 + INTEGER(IntKi), PARAMETER :: B2N6VDisz = 246 + INTEGER(IntKi), PARAMETER :: B2N7VDisz = 247 + INTEGER(IntKi), PARAMETER :: B2N8VDisz = 248 + INTEGER(IntKi), PARAMETER :: B2N9VDisz = 249 + INTEGER(IntKi), PARAMETER :: B3N1VDisx = 250 + INTEGER(IntKi), PARAMETER :: B3N2VDisx = 251 + INTEGER(IntKi), PARAMETER :: B3N3VDisx = 252 + INTEGER(IntKi), PARAMETER :: B3N4VDisx = 253 + INTEGER(IntKi), PARAMETER :: B3N5VDisx = 254 + INTEGER(IntKi), PARAMETER :: B3N6VDisx = 255 + INTEGER(IntKi), PARAMETER :: B3N7VDisx = 256 + INTEGER(IntKi), PARAMETER :: B3N8VDisx = 257 + INTEGER(IntKi), PARAMETER :: B3N9VDisx = 258 + INTEGER(IntKi), PARAMETER :: B3N1VDisy = 259 + INTEGER(IntKi), PARAMETER :: B3N2VDisy = 260 + INTEGER(IntKi), PARAMETER :: B3N3VDisy = 261 + INTEGER(IntKi), PARAMETER :: B3N4VDisy = 262 + INTEGER(IntKi), PARAMETER :: B3N5VDisy = 263 + INTEGER(IntKi), PARAMETER :: B3N6VDisy = 264 + INTEGER(IntKi), PARAMETER :: B3N7VDisy = 265 + INTEGER(IntKi), PARAMETER :: B3N8VDisy = 266 + INTEGER(IntKi), PARAMETER :: B3N9VDisy = 267 + INTEGER(IntKi), PARAMETER :: B3N1VDisz = 268 + INTEGER(IntKi), PARAMETER :: B3N2VDisz = 269 + INTEGER(IntKi), PARAMETER :: B3N3VDisz = 270 + INTEGER(IntKi), PARAMETER :: B3N4VDisz = 271 + INTEGER(IntKi), PARAMETER :: B3N5VDisz = 272 + INTEGER(IntKi), PARAMETER :: B3N6VDisz = 273 + INTEGER(IntKi), PARAMETER :: B3N7VDisz = 274 + INTEGER(IntKi), PARAMETER :: B3N8VDisz = 275 + INTEGER(IntKi), PARAMETER :: B3N9VDisz = 276 + INTEGER(IntKi), PARAMETER :: B1N1STVx = 277 + INTEGER(IntKi), PARAMETER :: B1N2STVx = 278 + INTEGER(IntKi), PARAMETER :: B1N3STVx = 279 + INTEGER(IntKi), PARAMETER :: B1N4STVx = 280 + INTEGER(IntKi), PARAMETER :: B1N5STVx = 281 + INTEGER(IntKi), PARAMETER :: B1N6STVx = 282 + INTEGER(IntKi), PARAMETER :: B1N7STVx = 283 + INTEGER(IntKi), PARAMETER :: B1N8STVx = 284 + INTEGER(IntKi), PARAMETER :: B1N9STVx = 285 + INTEGER(IntKi), PARAMETER :: B1N1STVy = 286 + INTEGER(IntKi), PARAMETER :: B1N2STVy = 287 + INTEGER(IntKi), PARAMETER :: B1N3STVy = 288 + INTEGER(IntKi), PARAMETER :: B1N4STVy = 289 + INTEGER(IntKi), PARAMETER :: B1N5STVy = 290 + INTEGER(IntKi), PARAMETER :: B1N6STVy = 291 + INTEGER(IntKi), PARAMETER :: B1N7STVy = 292 + INTEGER(IntKi), PARAMETER :: B1N8STVy = 293 + INTEGER(IntKi), PARAMETER :: B1N9STVy = 294 + INTEGER(IntKi), PARAMETER :: B1N1STVz = 295 + INTEGER(IntKi), PARAMETER :: B1N2STVz = 296 + INTEGER(IntKi), PARAMETER :: B1N3STVz = 297 + INTEGER(IntKi), PARAMETER :: B1N4STVz = 298 + INTEGER(IntKi), PARAMETER :: B1N5STVz = 299 + INTEGER(IntKi), PARAMETER :: B1N6STVz = 300 + INTEGER(IntKi), PARAMETER :: B1N7STVz = 301 + INTEGER(IntKi), PARAMETER :: B1N8STVz = 302 + INTEGER(IntKi), PARAMETER :: B1N9STVz = 303 + INTEGER(IntKi), PARAMETER :: B2N1STVx = 304 + INTEGER(IntKi), PARAMETER :: B2N2STVx = 305 + INTEGER(IntKi), PARAMETER :: B2N3STVx = 306 + INTEGER(IntKi), PARAMETER :: B2N4STVx = 307 + INTEGER(IntKi), PARAMETER :: B2N5STVx = 308 + INTEGER(IntKi), PARAMETER :: B2N6STVx = 309 + INTEGER(IntKi), PARAMETER :: B2N7STVx = 310 + INTEGER(IntKi), PARAMETER :: B2N8STVx = 311 + INTEGER(IntKi), PARAMETER :: B2N9STVx = 312 + INTEGER(IntKi), PARAMETER :: B2N1STVy = 313 + INTEGER(IntKi), PARAMETER :: B2N2STVy = 314 + INTEGER(IntKi), PARAMETER :: B2N3STVy = 315 + INTEGER(IntKi), PARAMETER :: B2N4STVy = 316 + INTEGER(IntKi), PARAMETER :: B2N5STVy = 317 + INTEGER(IntKi), PARAMETER :: B2N6STVy = 318 + INTEGER(IntKi), PARAMETER :: B2N7STVy = 319 + INTEGER(IntKi), PARAMETER :: B2N8STVy = 320 + INTEGER(IntKi), PARAMETER :: B2N9STVy = 321 + INTEGER(IntKi), PARAMETER :: B2N1STVz = 322 + INTEGER(IntKi), PARAMETER :: B2N2STVz = 323 + INTEGER(IntKi), PARAMETER :: B2N3STVz = 324 + INTEGER(IntKi), PARAMETER :: B2N4STVz = 325 + INTEGER(IntKi), PARAMETER :: B2N5STVz = 326 + INTEGER(IntKi), PARAMETER :: B2N6STVz = 327 + INTEGER(IntKi), PARAMETER :: B2N7STVz = 328 + INTEGER(IntKi), PARAMETER :: B2N8STVz = 329 + INTEGER(IntKi), PARAMETER :: B2N9STVz = 330 + INTEGER(IntKi), PARAMETER :: B3N1STVx = 331 + INTEGER(IntKi), PARAMETER :: B3N2STVx = 332 + INTEGER(IntKi), PARAMETER :: B3N3STVx = 333 + INTEGER(IntKi), PARAMETER :: B3N4STVx = 334 + INTEGER(IntKi), PARAMETER :: B3N5STVx = 335 + INTEGER(IntKi), PARAMETER :: B3N6STVx = 336 + INTEGER(IntKi), PARAMETER :: B3N7STVx = 337 + INTEGER(IntKi), PARAMETER :: B3N8STVx = 338 + INTEGER(IntKi), PARAMETER :: B3N9STVx = 339 + INTEGER(IntKi), PARAMETER :: B3N1STVy = 340 + INTEGER(IntKi), PARAMETER :: B3N2STVy = 341 + INTEGER(IntKi), PARAMETER :: B3N3STVy = 342 + INTEGER(IntKi), PARAMETER :: B3N4STVy = 343 + INTEGER(IntKi), PARAMETER :: B3N5STVy = 344 + INTEGER(IntKi), PARAMETER :: B3N6STVy = 345 + INTEGER(IntKi), PARAMETER :: B3N7STVy = 346 + INTEGER(IntKi), PARAMETER :: B3N8STVy = 347 + INTEGER(IntKi), PARAMETER :: B3N9STVy = 348 + INTEGER(IntKi), PARAMETER :: B3N1STVz = 349 + INTEGER(IntKi), PARAMETER :: B3N2STVz = 350 + INTEGER(IntKi), PARAMETER :: B3N3STVz = 351 + INTEGER(IntKi), PARAMETER :: B3N4STVz = 352 + INTEGER(IntKi), PARAMETER :: B3N5STVz = 353 + INTEGER(IntKi), PARAMETER :: B3N6STVz = 354 + INTEGER(IntKi), PARAMETER :: B3N7STVz = 355 + INTEGER(IntKi), PARAMETER :: B3N8STVz = 356 + INTEGER(IntKi), PARAMETER :: B3N9STVz = 357 + INTEGER(IntKi), PARAMETER :: B1N1VRel = 358 + INTEGER(IntKi), PARAMETER :: B1N2VRel = 359 + INTEGER(IntKi), PARAMETER :: B1N3VRel = 360 + INTEGER(IntKi), PARAMETER :: B1N4VRel = 361 + INTEGER(IntKi), PARAMETER :: B1N5VRel = 362 + INTEGER(IntKi), PARAMETER :: B1N6VRel = 363 + INTEGER(IntKi), PARAMETER :: B1N7VRel = 364 + INTEGER(IntKi), PARAMETER :: B1N8VRel = 365 + INTEGER(IntKi), PARAMETER :: B1N9VRel = 366 + INTEGER(IntKi), PARAMETER :: B2N1VRel = 367 + INTEGER(IntKi), PARAMETER :: B2N2VRel = 368 + INTEGER(IntKi), PARAMETER :: B2N3VRel = 369 + INTEGER(IntKi), PARAMETER :: B2N4VRel = 370 + INTEGER(IntKi), PARAMETER :: B2N5VRel = 371 + INTEGER(IntKi), PARAMETER :: B2N6VRel = 372 + INTEGER(IntKi), PARAMETER :: B2N7VRel = 373 + INTEGER(IntKi), PARAMETER :: B2N8VRel = 374 + INTEGER(IntKi), PARAMETER :: B2N9VRel = 375 + INTEGER(IntKi), PARAMETER :: B3N1VRel = 376 + INTEGER(IntKi), PARAMETER :: B3N2VRel = 377 + INTEGER(IntKi), PARAMETER :: B3N3VRel = 378 + INTEGER(IntKi), PARAMETER :: B3N4VRel = 379 + INTEGER(IntKi), PARAMETER :: B3N5VRel = 380 + INTEGER(IntKi), PARAMETER :: B3N6VRel = 381 + INTEGER(IntKi), PARAMETER :: B3N7VRel = 382 + INTEGER(IntKi), PARAMETER :: B3N8VRel = 383 + INTEGER(IntKi), PARAMETER :: B3N9VRel = 384 + INTEGER(IntKi), PARAMETER :: B1N1DynP = 385 + INTEGER(IntKi), PARAMETER :: B1N2DynP = 386 + INTEGER(IntKi), PARAMETER :: B1N3DynP = 387 + INTEGER(IntKi), PARAMETER :: B1N4DynP = 388 + INTEGER(IntKi), PARAMETER :: B1N5DynP = 389 + INTEGER(IntKi), PARAMETER :: B1N6DynP = 390 + INTEGER(IntKi), PARAMETER :: B1N7DynP = 391 + INTEGER(IntKi), PARAMETER :: B1N8DynP = 392 + INTEGER(IntKi), PARAMETER :: B1N9DynP = 393 + INTEGER(IntKi), PARAMETER :: B2N1DynP = 394 + INTEGER(IntKi), PARAMETER :: B2N2DynP = 395 + INTEGER(IntKi), PARAMETER :: B2N3DynP = 396 + INTEGER(IntKi), PARAMETER :: B2N4DynP = 397 + INTEGER(IntKi), PARAMETER :: B2N5DynP = 398 + INTEGER(IntKi), PARAMETER :: B2N6DynP = 399 + INTEGER(IntKi), PARAMETER :: B2N7DynP = 400 + INTEGER(IntKi), PARAMETER :: B2N8DynP = 401 + INTEGER(IntKi), PARAMETER :: B2N9DynP = 402 + INTEGER(IntKi), PARAMETER :: B3N1DynP = 403 + INTEGER(IntKi), PARAMETER :: B3N2DynP = 404 + INTEGER(IntKi), PARAMETER :: B3N3DynP = 405 + INTEGER(IntKi), PARAMETER :: B3N4DynP = 406 + INTEGER(IntKi), PARAMETER :: B3N5DynP = 407 + INTEGER(IntKi), PARAMETER :: B3N6DynP = 408 + INTEGER(IntKi), PARAMETER :: B3N7DynP = 409 + INTEGER(IntKi), PARAMETER :: B3N8DynP = 410 + INTEGER(IntKi), PARAMETER :: B3N9DynP = 411 + INTEGER(IntKi), PARAMETER :: B1N1Re = 412 + INTEGER(IntKi), PARAMETER :: B1N2Re = 413 + INTEGER(IntKi), PARAMETER :: B1N3Re = 414 + INTEGER(IntKi), PARAMETER :: B1N4Re = 415 + INTEGER(IntKi), PARAMETER :: B1N5Re = 416 + INTEGER(IntKi), PARAMETER :: B1N6Re = 417 + INTEGER(IntKi), PARAMETER :: B1N7Re = 418 + INTEGER(IntKi), PARAMETER :: B1N8Re = 419 + INTEGER(IntKi), PARAMETER :: B1N9Re = 420 + INTEGER(IntKi), PARAMETER :: B2N1Re = 421 + INTEGER(IntKi), PARAMETER :: B2N2Re = 422 + INTEGER(IntKi), PARAMETER :: B2N3Re = 423 + INTEGER(IntKi), PARAMETER :: B2N4Re = 424 + INTEGER(IntKi), PARAMETER :: B2N5Re = 425 + INTEGER(IntKi), PARAMETER :: B2N6Re = 426 + INTEGER(IntKi), PARAMETER :: B2N7Re = 427 + INTEGER(IntKi), PARAMETER :: B2N8Re = 428 + INTEGER(IntKi), PARAMETER :: B2N9Re = 429 + INTEGER(IntKi), PARAMETER :: B3N1Re = 430 + INTEGER(IntKi), PARAMETER :: B3N2Re = 431 + INTEGER(IntKi), PARAMETER :: B3N3Re = 432 + INTEGER(IntKi), PARAMETER :: B3N4Re = 433 + INTEGER(IntKi), PARAMETER :: B3N5Re = 434 + INTEGER(IntKi), PARAMETER :: B3N6Re = 435 + INTEGER(IntKi), PARAMETER :: B3N7Re = 436 + INTEGER(IntKi), PARAMETER :: B3N8Re = 437 + INTEGER(IntKi), PARAMETER :: B3N9Re = 438 + INTEGER(IntKi), PARAMETER :: B1N1M = 439 + INTEGER(IntKi), PARAMETER :: B1N2M = 440 + INTEGER(IntKi), PARAMETER :: B1N3M = 441 + INTEGER(IntKi), PARAMETER :: B1N4M = 442 + INTEGER(IntKi), PARAMETER :: B1N5M = 443 + INTEGER(IntKi), PARAMETER :: B1N6M = 444 + INTEGER(IntKi), PARAMETER :: B1N7M = 445 + INTEGER(IntKi), PARAMETER :: B1N8M = 446 + INTEGER(IntKi), PARAMETER :: B1N9M = 447 + INTEGER(IntKi), PARAMETER :: B2N1M = 448 + INTEGER(IntKi), PARAMETER :: B2N2M = 449 + INTEGER(IntKi), PARAMETER :: B2N3M = 450 + INTEGER(IntKi), PARAMETER :: B2N4M = 451 + INTEGER(IntKi), PARAMETER :: B2N5M = 452 + INTEGER(IntKi), PARAMETER :: B2N6M = 453 + INTEGER(IntKi), PARAMETER :: B2N7M = 454 + INTEGER(IntKi), PARAMETER :: B2N8M = 455 + INTEGER(IntKi), PARAMETER :: B2N9M = 456 + INTEGER(IntKi), PARAMETER :: B3N1M = 457 + INTEGER(IntKi), PARAMETER :: B3N2M = 458 + INTEGER(IntKi), PARAMETER :: B3N3M = 459 + INTEGER(IntKi), PARAMETER :: B3N4M = 460 + INTEGER(IntKi), PARAMETER :: B3N5M = 461 + INTEGER(IntKi), PARAMETER :: B3N6M = 462 + INTEGER(IntKi), PARAMETER :: B3N7M = 463 + INTEGER(IntKi), PARAMETER :: B3N8M = 464 + INTEGER(IntKi), PARAMETER :: B3N9M = 465 + INTEGER(IntKi), PARAMETER :: B1N1Vindx = 466 + INTEGER(IntKi), PARAMETER :: B1N2Vindx = 467 + INTEGER(IntKi), PARAMETER :: B1N3Vindx = 468 + INTEGER(IntKi), PARAMETER :: B1N4Vindx = 469 + INTEGER(IntKi), PARAMETER :: B1N5Vindx = 470 + INTEGER(IntKi), PARAMETER :: B1N6Vindx = 471 + INTEGER(IntKi), PARAMETER :: B1N7Vindx = 472 + INTEGER(IntKi), PARAMETER :: B1N8Vindx = 473 + INTEGER(IntKi), PARAMETER :: B1N9Vindx = 474 + INTEGER(IntKi), PARAMETER :: B2N1Vindx = 475 + INTEGER(IntKi), PARAMETER :: B2N2Vindx = 476 + INTEGER(IntKi), PARAMETER :: B2N3Vindx = 477 + INTEGER(IntKi), PARAMETER :: B2N4Vindx = 478 + INTEGER(IntKi), PARAMETER :: B2N5Vindx = 479 + INTEGER(IntKi), PARAMETER :: B2N6Vindx = 480 + INTEGER(IntKi), PARAMETER :: B2N7Vindx = 481 + INTEGER(IntKi), PARAMETER :: B2N8Vindx = 482 + INTEGER(IntKi), PARAMETER :: B2N9Vindx = 483 + INTEGER(IntKi), PARAMETER :: B3N1Vindx = 484 + INTEGER(IntKi), PARAMETER :: B3N2Vindx = 485 + INTEGER(IntKi), PARAMETER :: B3N3Vindx = 486 + INTEGER(IntKi), PARAMETER :: B3N4Vindx = 487 + INTEGER(IntKi), PARAMETER :: B3N5Vindx = 488 + INTEGER(IntKi), PARAMETER :: B3N6Vindx = 489 + INTEGER(IntKi), PARAMETER :: B3N7Vindx = 490 + INTEGER(IntKi), PARAMETER :: B3N8Vindx = 491 + INTEGER(IntKi), PARAMETER :: B3N9Vindx = 492 + INTEGER(IntKi), PARAMETER :: B1N1Vindy = 493 + INTEGER(IntKi), PARAMETER :: B1N2Vindy = 494 + INTEGER(IntKi), PARAMETER :: B1N3Vindy = 495 + INTEGER(IntKi), PARAMETER :: B1N4Vindy = 496 + INTEGER(IntKi), PARAMETER :: B1N5Vindy = 497 + INTEGER(IntKi), PARAMETER :: B1N6Vindy = 498 + INTEGER(IntKi), PARAMETER :: B1N7Vindy = 499 + INTEGER(IntKi), PARAMETER :: B1N8Vindy = 500 + INTEGER(IntKi), PARAMETER :: B1N9Vindy = 501 + INTEGER(IntKi), PARAMETER :: B2N1Vindy = 502 + INTEGER(IntKi), PARAMETER :: B2N2Vindy = 503 + INTEGER(IntKi), PARAMETER :: B2N3Vindy = 504 + INTEGER(IntKi), PARAMETER :: B2N4Vindy = 505 + INTEGER(IntKi), PARAMETER :: B2N5Vindy = 506 + INTEGER(IntKi), PARAMETER :: B2N6Vindy = 507 + INTEGER(IntKi), PARAMETER :: B2N7Vindy = 508 + INTEGER(IntKi), PARAMETER :: B2N8Vindy = 509 + INTEGER(IntKi), PARAMETER :: B2N9Vindy = 510 + INTEGER(IntKi), PARAMETER :: B3N1Vindy = 511 + INTEGER(IntKi), PARAMETER :: B3N2Vindy = 512 + INTEGER(IntKi), PARAMETER :: B3N3Vindy = 513 + INTEGER(IntKi), PARAMETER :: B3N4Vindy = 514 + INTEGER(IntKi), PARAMETER :: B3N5Vindy = 515 + INTEGER(IntKi), PARAMETER :: B3N6Vindy = 516 + INTEGER(IntKi), PARAMETER :: B3N7Vindy = 517 + INTEGER(IntKi), PARAMETER :: B3N8Vindy = 518 + INTEGER(IntKi), PARAMETER :: B3N9Vindy = 519 + INTEGER(IntKi), PARAMETER :: B1N1AxInd = 520 + INTEGER(IntKi), PARAMETER :: B1N2AxInd = 521 + INTEGER(IntKi), PARAMETER :: B1N3AxInd = 522 + INTEGER(IntKi), PARAMETER :: B1N4AxInd = 523 + INTEGER(IntKi), PARAMETER :: B1N5AxInd = 524 + INTEGER(IntKi), PARAMETER :: B1N6AxInd = 525 + INTEGER(IntKi), PARAMETER :: B1N7AxInd = 526 + INTEGER(IntKi), PARAMETER :: B1N8AxInd = 527 + INTEGER(IntKi), PARAMETER :: B1N9AxInd = 528 + INTEGER(IntKi), PARAMETER :: B2N1AxInd = 529 + INTEGER(IntKi), PARAMETER :: B2N2AxInd = 530 + INTEGER(IntKi), PARAMETER :: B2N3AxInd = 531 + INTEGER(IntKi), PARAMETER :: B2N4AxInd = 532 + INTEGER(IntKi), PARAMETER :: B2N5AxInd = 533 + INTEGER(IntKi), PARAMETER :: B2N6AxInd = 534 + INTEGER(IntKi), PARAMETER :: B2N7AxInd = 535 + INTEGER(IntKi), PARAMETER :: B2N8AxInd = 536 + INTEGER(IntKi), PARAMETER :: B2N9AxInd = 537 + INTEGER(IntKi), PARAMETER :: B3N1AxInd = 538 + INTEGER(IntKi), PARAMETER :: B3N2AxInd = 539 + INTEGER(IntKi), PARAMETER :: B3N3AxInd = 540 + INTEGER(IntKi), PARAMETER :: B3N4AxInd = 541 + INTEGER(IntKi), PARAMETER :: B3N5AxInd = 542 + INTEGER(IntKi), PARAMETER :: B3N6AxInd = 543 + INTEGER(IntKi), PARAMETER :: B3N7AxInd = 544 + INTEGER(IntKi), PARAMETER :: B3N8AxInd = 545 + INTEGER(IntKi), PARAMETER :: B3N9AxInd = 546 + INTEGER(IntKi), PARAMETER :: B1N1TnInd = 547 + INTEGER(IntKi), PARAMETER :: B1N2TnInd = 548 + INTEGER(IntKi), PARAMETER :: B1N3TnInd = 549 + INTEGER(IntKi), PARAMETER :: B1N4TnInd = 550 + INTEGER(IntKi), PARAMETER :: B1N5TnInd = 551 + INTEGER(IntKi), PARAMETER :: B1N6TnInd = 552 + INTEGER(IntKi), PARAMETER :: B1N7TnInd = 553 + INTEGER(IntKi), PARAMETER :: B1N8TnInd = 554 + INTEGER(IntKi), PARAMETER :: B1N9TnInd = 555 + INTEGER(IntKi), PARAMETER :: B2N1TnInd = 556 + INTEGER(IntKi), PARAMETER :: B2N2TnInd = 557 + INTEGER(IntKi), PARAMETER :: B2N3TnInd = 558 + INTEGER(IntKi), PARAMETER :: B2N4TnInd = 559 + INTEGER(IntKi), PARAMETER :: B2N5TnInd = 560 + INTEGER(IntKi), PARAMETER :: B2N6TnInd = 561 + INTEGER(IntKi), PARAMETER :: B2N7TnInd = 562 + INTEGER(IntKi), PARAMETER :: B2N8TnInd = 563 + INTEGER(IntKi), PARAMETER :: B2N9TnInd = 564 + INTEGER(IntKi), PARAMETER :: B3N1TnInd = 565 + INTEGER(IntKi), PARAMETER :: B3N2TnInd = 566 + INTEGER(IntKi), PARAMETER :: B3N3TnInd = 567 + INTEGER(IntKi), PARAMETER :: B3N4TnInd = 568 + INTEGER(IntKi), PARAMETER :: B3N5TnInd = 569 + INTEGER(IntKi), PARAMETER :: B3N6TnInd = 570 + INTEGER(IntKi), PARAMETER :: B3N7TnInd = 571 + INTEGER(IntKi), PARAMETER :: B3N8TnInd = 572 + INTEGER(IntKi), PARAMETER :: B3N9TnInd = 573 + INTEGER(IntKi), PARAMETER :: B1N1Alpha = 574 + INTEGER(IntKi), PARAMETER :: B1N2Alpha = 575 + INTEGER(IntKi), PARAMETER :: B1N3Alpha = 576 + INTEGER(IntKi), PARAMETER :: B1N4Alpha = 577 + INTEGER(IntKi), PARAMETER :: B1N5Alpha = 578 + INTEGER(IntKi), PARAMETER :: B1N6Alpha = 579 + INTEGER(IntKi), PARAMETER :: B1N7Alpha = 580 + INTEGER(IntKi), PARAMETER :: B1N8Alpha = 581 + INTEGER(IntKi), PARAMETER :: B1N9Alpha = 582 + INTEGER(IntKi), PARAMETER :: B2N1Alpha = 583 + INTEGER(IntKi), PARAMETER :: B2N2Alpha = 584 + INTEGER(IntKi), PARAMETER :: B2N3Alpha = 585 + INTEGER(IntKi), PARAMETER :: B2N4Alpha = 586 + INTEGER(IntKi), PARAMETER :: B2N5Alpha = 587 + INTEGER(IntKi), PARAMETER :: B2N6Alpha = 588 + INTEGER(IntKi), PARAMETER :: B2N7Alpha = 589 + INTEGER(IntKi), PARAMETER :: B2N8Alpha = 590 + INTEGER(IntKi), PARAMETER :: B2N9Alpha = 591 + INTEGER(IntKi), PARAMETER :: B3N1Alpha = 592 + INTEGER(IntKi), PARAMETER :: B3N2Alpha = 593 + INTEGER(IntKi), PARAMETER :: B3N3Alpha = 594 + INTEGER(IntKi), PARAMETER :: B3N4Alpha = 595 + INTEGER(IntKi), PARAMETER :: B3N5Alpha = 596 + INTEGER(IntKi), PARAMETER :: B3N6Alpha = 597 + INTEGER(IntKi), PARAMETER :: B3N7Alpha = 598 + INTEGER(IntKi), PARAMETER :: B3N8Alpha = 599 + INTEGER(IntKi), PARAMETER :: B3N9Alpha = 600 + INTEGER(IntKi), PARAMETER :: B1N1Theta = 601 + INTEGER(IntKi), PARAMETER :: B1N2Theta = 602 + INTEGER(IntKi), PARAMETER :: B1N3Theta = 603 + INTEGER(IntKi), PARAMETER :: B1N4Theta = 604 + INTEGER(IntKi), PARAMETER :: B1N5Theta = 605 + INTEGER(IntKi), PARAMETER :: B1N6Theta = 606 + INTEGER(IntKi), PARAMETER :: B1N7Theta = 607 + INTEGER(IntKi), PARAMETER :: B1N8Theta = 608 + INTEGER(IntKi), PARAMETER :: B1N9Theta = 609 + INTEGER(IntKi), PARAMETER :: B2N1Theta = 610 + INTEGER(IntKi), PARAMETER :: B2N2Theta = 611 + INTEGER(IntKi), PARAMETER :: B2N3Theta = 612 + INTEGER(IntKi), PARAMETER :: B2N4Theta = 613 + INTEGER(IntKi), PARAMETER :: B2N5Theta = 614 + INTEGER(IntKi), PARAMETER :: B2N6Theta = 615 + INTEGER(IntKi), PARAMETER :: B2N7Theta = 616 + INTEGER(IntKi), PARAMETER :: B2N8Theta = 617 + INTEGER(IntKi), PARAMETER :: B2N9Theta = 618 + INTEGER(IntKi), PARAMETER :: B3N1Theta = 619 + INTEGER(IntKi), PARAMETER :: B3N2Theta = 620 + INTEGER(IntKi), PARAMETER :: B3N3Theta = 621 + INTEGER(IntKi), PARAMETER :: B3N4Theta = 622 + INTEGER(IntKi), PARAMETER :: B3N5Theta = 623 + INTEGER(IntKi), PARAMETER :: B3N6Theta = 624 + INTEGER(IntKi), PARAMETER :: B3N7Theta = 625 + INTEGER(IntKi), PARAMETER :: B3N8Theta = 626 + INTEGER(IntKi), PARAMETER :: B3N9Theta = 627 + INTEGER(IntKi), PARAMETER :: B1N1Phi = 628 + INTEGER(IntKi), PARAMETER :: B1N2Phi = 629 + INTEGER(IntKi), PARAMETER :: B1N3Phi = 630 + INTEGER(IntKi), PARAMETER :: B1N4Phi = 631 + INTEGER(IntKi), PARAMETER :: B1N5Phi = 632 + INTEGER(IntKi), PARAMETER :: B1N6Phi = 633 + INTEGER(IntKi), PARAMETER :: B1N7Phi = 634 + INTEGER(IntKi), PARAMETER :: B1N8Phi = 635 + INTEGER(IntKi), PARAMETER :: B1N9Phi = 636 + INTEGER(IntKi), PARAMETER :: B2N1Phi = 637 + INTEGER(IntKi), PARAMETER :: B2N2Phi = 638 + INTEGER(IntKi), PARAMETER :: B2N3Phi = 639 + INTEGER(IntKi), PARAMETER :: B2N4Phi = 640 + INTEGER(IntKi), PARAMETER :: B2N5Phi = 641 + INTEGER(IntKi), PARAMETER :: B2N6Phi = 642 + INTEGER(IntKi), PARAMETER :: B2N7Phi = 643 + INTEGER(IntKi), PARAMETER :: B2N8Phi = 644 + INTEGER(IntKi), PARAMETER :: B2N9Phi = 645 + INTEGER(IntKi), PARAMETER :: B3N1Phi = 646 + INTEGER(IntKi), PARAMETER :: B3N2Phi = 647 + INTEGER(IntKi), PARAMETER :: B3N3Phi = 648 + INTEGER(IntKi), PARAMETER :: B3N4Phi = 649 + INTEGER(IntKi), PARAMETER :: B3N5Phi = 650 + INTEGER(IntKi), PARAMETER :: B3N6Phi = 651 + INTEGER(IntKi), PARAMETER :: B3N7Phi = 652 + INTEGER(IntKi), PARAMETER :: B3N8Phi = 653 + INTEGER(IntKi), PARAMETER :: B3N9Phi = 654 + INTEGER(IntKi), PARAMETER :: B1N1Curve = 655 + INTEGER(IntKi), PARAMETER :: B1N2Curve = 656 + INTEGER(IntKi), PARAMETER :: B1N3Curve = 657 + INTEGER(IntKi), PARAMETER :: B1N4Curve = 658 + INTEGER(IntKi), PARAMETER :: B1N5Curve = 659 + INTEGER(IntKi), PARAMETER :: B1N6Curve = 660 + INTEGER(IntKi), PARAMETER :: B1N7Curve = 661 + INTEGER(IntKi), PARAMETER :: B1N8Curve = 662 + INTEGER(IntKi), PARAMETER :: B1N9Curve = 663 + INTEGER(IntKi), PARAMETER :: B2N1Curve = 664 + INTEGER(IntKi), PARAMETER :: B2N2Curve = 665 + INTEGER(IntKi), PARAMETER :: B2N3Curve = 666 + INTEGER(IntKi), PARAMETER :: B2N4Curve = 667 + INTEGER(IntKi), PARAMETER :: B2N5Curve = 668 + INTEGER(IntKi), PARAMETER :: B2N6Curve = 669 + INTEGER(IntKi), PARAMETER :: B2N7Curve = 670 + INTEGER(IntKi), PARAMETER :: B2N8Curve = 671 + INTEGER(IntKi), PARAMETER :: B2N9Curve = 672 + INTEGER(IntKi), PARAMETER :: B3N1Curve = 673 + INTEGER(IntKi), PARAMETER :: B3N2Curve = 674 + INTEGER(IntKi), PARAMETER :: B3N3Curve = 675 + INTEGER(IntKi), PARAMETER :: B3N4Curve = 676 + INTEGER(IntKi), PARAMETER :: B3N5Curve = 677 + INTEGER(IntKi), PARAMETER :: B3N6Curve = 678 + INTEGER(IntKi), PARAMETER :: B3N7Curve = 679 + INTEGER(IntKi), PARAMETER :: B3N8Curve = 680 + INTEGER(IntKi), PARAMETER :: B3N9Curve = 681 + INTEGER(IntKi), PARAMETER :: B1N1Cl = 682 + INTEGER(IntKi), PARAMETER :: B1N2Cl = 683 + INTEGER(IntKi), PARAMETER :: B1N3Cl = 684 + INTEGER(IntKi), PARAMETER :: B1N4Cl = 685 + INTEGER(IntKi), PARAMETER :: B1N5Cl = 686 + INTEGER(IntKi), PARAMETER :: B1N6Cl = 687 + INTEGER(IntKi), PARAMETER :: B1N7Cl = 688 + INTEGER(IntKi), PARAMETER :: B1N8Cl = 689 + INTEGER(IntKi), PARAMETER :: B1N9Cl = 690 + INTEGER(IntKi), PARAMETER :: B2N1Cl = 691 + INTEGER(IntKi), PARAMETER :: B2N2Cl = 692 + INTEGER(IntKi), PARAMETER :: B2N3Cl = 693 + INTEGER(IntKi), PARAMETER :: B2N4Cl = 694 + INTEGER(IntKi), PARAMETER :: B2N5Cl = 695 + INTEGER(IntKi), PARAMETER :: B2N6Cl = 696 + INTEGER(IntKi), PARAMETER :: B2N7Cl = 697 + INTEGER(IntKi), PARAMETER :: B2N8Cl = 698 + INTEGER(IntKi), PARAMETER :: B2N9Cl = 699 + INTEGER(IntKi), PARAMETER :: B3N1Cl = 700 + INTEGER(IntKi), PARAMETER :: B3N2Cl = 701 + INTEGER(IntKi), PARAMETER :: B3N3Cl = 702 + INTEGER(IntKi), PARAMETER :: B3N4Cl = 703 + INTEGER(IntKi), PARAMETER :: B3N5Cl = 704 + INTEGER(IntKi), PARAMETER :: B3N6Cl = 705 + INTEGER(IntKi), PARAMETER :: B3N7Cl = 706 + INTEGER(IntKi), PARAMETER :: B3N8Cl = 707 + INTEGER(IntKi), PARAMETER :: B3N9Cl = 708 + INTEGER(IntKi), PARAMETER :: B1N1Cd = 709 + INTEGER(IntKi), PARAMETER :: B1N2Cd = 710 + INTEGER(IntKi), PARAMETER :: B1N3Cd = 711 + INTEGER(IntKi), PARAMETER :: B1N4Cd = 712 + INTEGER(IntKi), PARAMETER :: B1N5Cd = 713 + INTEGER(IntKi), PARAMETER :: B1N6Cd = 714 + INTEGER(IntKi), PARAMETER :: B1N7Cd = 715 + INTEGER(IntKi), PARAMETER :: B1N8Cd = 716 + INTEGER(IntKi), PARAMETER :: B1N9Cd = 717 + INTEGER(IntKi), PARAMETER :: B2N1Cd = 718 + INTEGER(IntKi), PARAMETER :: B2N2Cd = 719 + INTEGER(IntKi), PARAMETER :: B2N3Cd = 720 + INTEGER(IntKi), PARAMETER :: B2N4Cd = 721 + INTEGER(IntKi), PARAMETER :: B2N5Cd = 722 + INTEGER(IntKi), PARAMETER :: B2N6Cd = 723 + INTEGER(IntKi), PARAMETER :: B2N7Cd = 724 + INTEGER(IntKi), PARAMETER :: B2N8Cd = 725 + INTEGER(IntKi), PARAMETER :: B2N9Cd = 726 + INTEGER(IntKi), PARAMETER :: B3N1Cd = 727 + INTEGER(IntKi), PARAMETER :: B3N2Cd = 728 + INTEGER(IntKi), PARAMETER :: B3N3Cd = 729 + INTEGER(IntKi), PARAMETER :: B3N4Cd = 730 + INTEGER(IntKi), PARAMETER :: B3N5Cd = 731 + INTEGER(IntKi), PARAMETER :: B3N6Cd = 732 + INTEGER(IntKi), PARAMETER :: B3N7Cd = 733 + INTEGER(IntKi), PARAMETER :: B3N8Cd = 734 + INTEGER(IntKi), PARAMETER :: B3N9Cd = 735 + INTEGER(IntKi), PARAMETER :: B1N1Cm = 736 + INTEGER(IntKi), PARAMETER :: B1N2Cm = 737 + INTEGER(IntKi), PARAMETER :: B1N3Cm = 738 + INTEGER(IntKi), PARAMETER :: B1N4Cm = 739 + INTEGER(IntKi), PARAMETER :: B1N5Cm = 740 + INTEGER(IntKi), PARAMETER :: B1N6Cm = 741 + INTEGER(IntKi), PARAMETER :: B1N7Cm = 742 + INTEGER(IntKi), PARAMETER :: B1N8Cm = 743 + INTEGER(IntKi), PARAMETER :: B1N9Cm = 744 + INTEGER(IntKi), PARAMETER :: B2N1Cm = 745 + INTEGER(IntKi), PARAMETER :: B2N2Cm = 746 + INTEGER(IntKi), PARAMETER :: B2N3Cm = 747 + INTEGER(IntKi), PARAMETER :: B2N4Cm = 748 + INTEGER(IntKi), PARAMETER :: B2N5Cm = 749 + INTEGER(IntKi), PARAMETER :: B2N6Cm = 750 + INTEGER(IntKi), PARAMETER :: B2N7Cm = 751 + INTEGER(IntKi), PARAMETER :: B2N8Cm = 752 + INTEGER(IntKi), PARAMETER :: B2N9Cm = 753 + INTEGER(IntKi), PARAMETER :: B3N1Cm = 754 + INTEGER(IntKi), PARAMETER :: B3N2Cm = 755 + INTEGER(IntKi), PARAMETER :: B3N3Cm = 756 + INTEGER(IntKi), PARAMETER :: B3N4Cm = 757 + INTEGER(IntKi), PARAMETER :: B3N5Cm = 758 + INTEGER(IntKi), PARAMETER :: B3N6Cm = 759 + INTEGER(IntKi), PARAMETER :: B3N7Cm = 760 + INTEGER(IntKi), PARAMETER :: B3N8Cm = 761 + INTEGER(IntKi), PARAMETER :: B3N9Cm = 762 + INTEGER(IntKi), PARAMETER :: B1N1Cx = 763 + INTEGER(IntKi), PARAMETER :: B1N2Cx = 764 + INTEGER(IntKi), PARAMETER :: B1N3Cx = 765 + INTEGER(IntKi), PARAMETER :: B1N4Cx = 766 + INTEGER(IntKi), PARAMETER :: B1N5Cx = 767 + INTEGER(IntKi), PARAMETER :: B1N6Cx = 768 + INTEGER(IntKi), PARAMETER :: B1N7Cx = 769 + INTEGER(IntKi), PARAMETER :: B1N8Cx = 770 + INTEGER(IntKi), PARAMETER :: B1N9Cx = 771 + INTEGER(IntKi), PARAMETER :: B2N1Cx = 772 + INTEGER(IntKi), PARAMETER :: B2N2Cx = 773 + INTEGER(IntKi), PARAMETER :: B2N3Cx = 774 + INTEGER(IntKi), PARAMETER :: B2N4Cx = 775 + INTEGER(IntKi), PARAMETER :: B2N5Cx = 776 + INTEGER(IntKi), PARAMETER :: B2N6Cx = 777 + INTEGER(IntKi), PARAMETER :: B2N7Cx = 778 + INTEGER(IntKi), PARAMETER :: B2N8Cx = 779 + INTEGER(IntKi), PARAMETER :: B2N9Cx = 780 + INTEGER(IntKi), PARAMETER :: B3N1Cx = 781 + INTEGER(IntKi), PARAMETER :: B3N2Cx = 782 + INTEGER(IntKi), PARAMETER :: B3N3Cx = 783 + INTEGER(IntKi), PARAMETER :: B3N4Cx = 784 + INTEGER(IntKi), PARAMETER :: B3N5Cx = 785 + INTEGER(IntKi), PARAMETER :: B3N6Cx = 786 + INTEGER(IntKi), PARAMETER :: B3N7Cx = 787 + INTEGER(IntKi), PARAMETER :: B3N8Cx = 788 + INTEGER(IntKi), PARAMETER :: B3N9Cx = 789 + INTEGER(IntKi), PARAMETER :: B1N1Cy = 790 + INTEGER(IntKi), PARAMETER :: B1N2Cy = 791 + INTEGER(IntKi), PARAMETER :: B1N3Cy = 792 + INTEGER(IntKi), PARAMETER :: B1N4Cy = 793 + INTEGER(IntKi), PARAMETER :: B1N5Cy = 794 + INTEGER(IntKi), PARAMETER :: B1N6Cy = 795 + INTEGER(IntKi), PARAMETER :: B1N7Cy = 796 + INTEGER(IntKi), PARAMETER :: B1N8Cy = 797 + INTEGER(IntKi), PARAMETER :: B1N9Cy = 798 + INTEGER(IntKi), PARAMETER :: B2N1Cy = 799 + INTEGER(IntKi), PARAMETER :: B2N2Cy = 800 + INTEGER(IntKi), PARAMETER :: B2N3Cy = 801 + INTEGER(IntKi), PARAMETER :: B2N4Cy = 802 + INTEGER(IntKi), PARAMETER :: B2N5Cy = 803 + INTEGER(IntKi), PARAMETER :: B2N6Cy = 804 + INTEGER(IntKi), PARAMETER :: B2N7Cy = 805 + INTEGER(IntKi), PARAMETER :: B2N8Cy = 806 + INTEGER(IntKi), PARAMETER :: B2N9Cy = 807 + INTEGER(IntKi), PARAMETER :: B3N1Cy = 808 + INTEGER(IntKi), PARAMETER :: B3N2Cy = 809 + INTEGER(IntKi), PARAMETER :: B3N3Cy = 810 + INTEGER(IntKi), PARAMETER :: B3N4Cy = 811 + INTEGER(IntKi), PARAMETER :: B3N5Cy = 812 + INTEGER(IntKi), PARAMETER :: B3N6Cy = 813 + INTEGER(IntKi), PARAMETER :: B3N7Cy = 814 + INTEGER(IntKi), PARAMETER :: B3N8Cy = 815 + INTEGER(IntKi), PARAMETER :: B3N9Cy = 816 + INTEGER(IntKi), PARAMETER :: B1N1Cn = 817 + INTEGER(IntKi), PARAMETER :: B1N2Cn = 818 + INTEGER(IntKi), PARAMETER :: B1N3Cn = 819 + INTEGER(IntKi), PARAMETER :: B1N4Cn = 820 + INTEGER(IntKi), PARAMETER :: B1N5Cn = 821 + INTEGER(IntKi), PARAMETER :: B1N6Cn = 822 + INTEGER(IntKi), PARAMETER :: B1N7Cn = 823 + INTEGER(IntKi), PARAMETER :: B1N8Cn = 824 + INTEGER(IntKi), PARAMETER :: B1N9Cn = 825 + INTEGER(IntKi), PARAMETER :: B2N1Cn = 826 + INTEGER(IntKi), PARAMETER :: B2N2Cn = 827 + INTEGER(IntKi), PARAMETER :: B2N3Cn = 828 + INTEGER(IntKi), PARAMETER :: B2N4Cn = 829 + INTEGER(IntKi), PARAMETER :: B2N5Cn = 830 + INTEGER(IntKi), PARAMETER :: B2N6Cn = 831 + INTEGER(IntKi), PARAMETER :: B2N7Cn = 832 + INTEGER(IntKi), PARAMETER :: B2N8Cn = 833 + INTEGER(IntKi), PARAMETER :: B2N9Cn = 834 + INTEGER(IntKi), PARAMETER :: B3N1Cn = 835 + INTEGER(IntKi), PARAMETER :: B3N2Cn = 836 + INTEGER(IntKi), PARAMETER :: B3N3Cn = 837 + INTEGER(IntKi), PARAMETER :: B3N4Cn = 838 + INTEGER(IntKi), PARAMETER :: B3N5Cn = 839 + INTEGER(IntKi), PARAMETER :: B3N6Cn = 840 + INTEGER(IntKi), PARAMETER :: B3N7Cn = 841 + INTEGER(IntKi), PARAMETER :: B3N8Cn = 842 + INTEGER(IntKi), PARAMETER :: B3N9Cn = 843 + INTEGER(IntKi), PARAMETER :: B1N1Ct = 844 + INTEGER(IntKi), PARAMETER :: B1N2Ct = 845 + INTEGER(IntKi), PARAMETER :: B1N3Ct = 846 + INTEGER(IntKi), PARAMETER :: B1N4Ct = 847 + INTEGER(IntKi), PARAMETER :: B1N5Ct = 848 + INTEGER(IntKi), PARAMETER :: B1N6Ct = 849 + INTEGER(IntKi), PARAMETER :: B1N7Ct = 850 + INTEGER(IntKi), PARAMETER :: B1N8Ct = 851 + INTEGER(IntKi), PARAMETER :: B1N9Ct = 852 + INTEGER(IntKi), PARAMETER :: B2N1Ct = 853 + INTEGER(IntKi), PARAMETER :: B2N2Ct = 854 + INTEGER(IntKi), PARAMETER :: B2N3Ct = 855 + INTEGER(IntKi), PARAMETER :: B2N4Ct = 856 + INTEGER(IntKi), PARAMETER :: B2N5Ct = 857 + INTEGER(IntKi), PARAMETER :: B2N6Ct = 858 + INTEGER(IntKi), PARAMETER :: B2N7Ct = 859 + INTEGER(IntKi), PARAMETER :: B2N8Ct = 860 + INTEGER(IntKi), PARAMETER :: B2N9Ct = 861 + INTEGER(IntKi), PARAMETER :: B3N1Ct = 862 + INTEGER(IntKi), PARAMETER :: B3N2Ct = 863 + INTEGER(IntKi), PARAMETER :: B3N3Ct = 864 + INTEGER(IntKi), PARAMETER :: B3N4Ct = 865 + INTEGER(IntKi), PARAMETER :: B3N5Ct = 866 + INTEGER(IntKi), PARAMETER :: B3N6Ct = 867 + INTEGER(IntKi), PARAMETER :: B3N7Ct = 868 + INTEGER(IntKi), PARAMETER :: B3N8Ct = 869 + INTEGER(IntKi), PARAMETER :: B3N9Ct = 870 + INTEGER(IntKi), PARAMETER :: B1N1Fl = 871 + INTEGER(IntKi), PARAMETER :: B1N2Fl = 872 + INTEGER(IntKi), PARAMETER :: B1N3Fl = 873 + INTEGER(IntKi), PARAMETER :: B1N4Fl = 874 + INTEGER(IntKi), PARAMETER :: B1N5Fl = 875 + INTEGER(IntKi), PARAMETER :: B1N6Fl = 876 + INTEGER(IntKi), PARAMETER :: B1N7Fl = 877 + INTEGER(IntKi), PARAMETER :: B1N8Fl = 878 + INTEGER(IntKi), PARAMETER :: B1N9Fl = 879 + INTEGER(IntKi), PARAMETER :: B2N1Fl = 880 + INTEGER(IntKi), PARAMETER :: B2N2Fl = 881 + INTEGER(IntKi), PARAMETER :: B2N3Fl = 882 + INTEGER(IntKi), PARAMETER :: B2N4Fl = 883 + INTEGER(IntKi), PARAMETER :: B2N5Fl = 884 + INTEGER(IntKi), PARAMETER :: B2N6Fl = 885 + INTEGER(IntKi), PARAMETER :: B2N7Fl = 886 + INTEGER(IntKi), PARAMETER :: B2N8Fl = 887 + INTEGER(IntKi), PARAMETER :: B2N9Fl = 888 + INTEGER(IntKi), PARAMETER :: B3N1Fl = 889 + INTEGER(IntKi), PARAMETER :: B3N2Fl = 890 + INTEGER(IntKi), PARAMETER :: B3N3Fl = 891 + INTEGER(IntKi), PARAMETER :: B3N4Fl = 892 + INTEGER(IntKi), PARAMETER :: B3N5Fl = 893 + INTEGER(IntKi), PARAMETER :: B3N6Fl = 894 + INTEGER(IntKi), PARAMETER :: B3N7Fl = 895 + INTEGER(IntKi), PARAMETER :: B3N8Fl = 896 + INTEGER(IntKi), PARAMETER :: B3N9Fl = 897 + INTEGER(IntKi), PARAMETER :: B1N1Fd = 898 + INTEGER(IntKi), PARAMETER :: B1N2Fd = 899 + INTEGER(IntKi), PARAMETER :: B1N3Fd = 900 + INTEGER(IntKi), PARAMETER :: B1N4Fd = 901 + INTEGER(IntKi), PARAMETER :: B1N5Fd = 902 + INTEGER(IntKi), PARAMETER :: B1N6Fd = 903 + INTEGER(IntKi), PARAMETER :: B1N7Fd = 904 + INTEGER(IntKi), PARAMETER :: B1N8Fd = 905 + INTEGER(IntKi), PARAMETER :: B1N9Fd = 906 + INTEGER(IntKi), PARAMETER :: B2N1Fd = 907 + INTEGER(IntKi), PARAMETER :: B2N2Fd = 908 + INTEGER(IntKi), PARAMETER :: B2N3Fd = 909 + INTEGER(IntKi), PARAMETER :: B2N4Fd = 910 + INTEGER(IntKi), PARAMETER :: B2N5Fd = 911 + INTEGER(IntKi), PARAMETER :: B2N6Fd = 912 + INTEGER(IntKi), PARAMETER :: B2N7Fd = 913 + INTEGER(IntKi), PARAMETER :: B2N8Fd = 914 + INTEGER(IntKi), PARAMETER :: B2N9Fd = 915 + INTEGER(IntKi), PARAMETER :: B3N1Fd = 916 + INTEGER(IntKi), PARAMETER :: B3N2Fd = 917 + INTEGER(IntKi), PARAMETER :: B3N3Fd = 918 + INTEGER(IntKi), PARAMETER :: B3N4Fd = 919 + INTEGER(IntKi), PARAMETER :: B3N5Fd = 920 + INTEGER(IntKi), PARAMETER :: B3N6Fd = 921 + INTEGER(IntKi), PARAMETER :: B3N7Fd = 922 + INTEGER(IntKi), PARAMETER :: B3N8Fd = 923 + INTEGER(IntKi), PARAMETER :: B3N9Fd = 924 + INTEGER(IntKi), PARAMETER :: B1N1Mm = 925 + INTEGER(IntKi), PARAMETER :: B1N2Mm = 926 + INTEGER(IntKi), PARAMETER :: B1N3Mm = 927 + INTEGER(IntKi), PARAMETER :: B1N4Mm = 928 + INTEGER(IntKi), PARAMETER :: B1N5Mm = 929 + INTEGER(IntKi), PARAMETER :: B1N6Mm = 930 + INTEGER(IntKi), PARAMETER :: B1N7Mm = 931 + INTEGER(IntKi), PARAMETER :: B1N8Mm = 932 + INTEGER(IntKi), PARAMETER :: B1N9Mm = 933 + INTEGER(IntKi), PARAMETER :: B2N1Mm = 934 + INTEGER(IntKi), PARAMETER :: B2N2Mm = 935 + INTEGER(IntKi), PARAMETER :: B2N3Mm = 936 + INTEGER(IntKi), PARAMETER :: B2N4Mm = 937 + INTEGER(IntKi), PARAMETER :: B2N5Mm = 938 + INTEGER(IntKi), PARAMETER :: B2N6Mm = 939 + INTEGER(IntKi), PARAMETER :: B2N7Mm = 940 + INTEGER(IntKi), PARAMETER :: B2N8Mm = 941 + INTEGER(IntKi), PARAMETER :: B2N9Mm = 942 + INTEGER(IntKi), PARAMETER :: B3N1Mm = 943 + INTEGER(IntKi), PARAMETER :: B3N2Mm = 944 + INTEGER(IntKi), PARAMETER :: B3N3Mm = 945 + INTEGER(IntKi), PARAMETER :: B3N4Mm = 946 + INTEGER(IntKi), PARAMETER :: B3N5Mm = 947 + INTEGER(IntKi), PARAMETER :: B3N6Mm = 948 + INTEGER(IntKi), PARAMETER :: B3N7Mm = 949 + INTEGER(IntKi), PARAMETER :: B3N8Mm = 950 + INTEGER(IntKi), PARAMETER :: B3N9Mm = 951 + INTEGER(IntKi), PARAMETER :: B1N1Fx = 952 + INTEGER(IntKi), PARAMETER :: B1N2Fx = 953 + INTEGER(IntKi), PARAMETER :: B1N3Fx = 954 + INTEGER(IntKi), PARAMETER :: B1N4Fx = 955 + INTEGER(IntKi), PARAMETER :: B1N5Fx = 956 + INTEGER(IntKi), PARAMETER :: B1N6Fx = 957 + INTEGER(IntKi), PARAMETER :: B1N7Fx = 958 + INTEGER(IntKi), PARAMETER :: B1N8Fx = 959 + INTEGER(IntKi), PARAMETER :: B1N9Fx = 960 + INTEGER(IntKi), PARAMETER :: B2N1Fx = 961 + INTEGER(IntKi), PARAMETER :: B2N2Fx = 962 + INTEGER(IntKi), PARAMETER :: B2N3Fx = 963 + INTEGER(IntKi), PARAMETER :: B2N4Fx = 964 + INTEGER(IntKi), PARAMETER :: B2N5Fx = 965 + INTEGER(IntKi), PARAMETER :: B2N6Fx = 966 + INTEGER(IntKi), PARAMETER :: B2N7Fx = 967 + INTEGER(IntKi), PARAMETER :: B2N8Fx = 968 + INTEGER(IntKi), PARAMETER :: B2N9Fx = 969 + INTEGER(IntKi), PARAMETER :: B3N1Fx = 970 + INTEGER(IntKi), PARAMETER :: B3N2Fx = 971 + INTEGER(IntKi), PARAMETER :: B3N3Fx = 972 + INTEGER(IntKi), PARAMETER :: B3N4Fx = 973 + INTEGER(IntKi), PARAMETER :: B3N5Fx = 974 + INTEGER(IntKi), PARAMETER :: B3N6Fx = 975 + INTEGER(IntKi), PARAMETER :: B3N7Fx = 976 + INTEGER(IntKi), PARAMETER :: B3N8Fx = 977 + INTEGER(IntKi), PARAMETER :: B3N9Fx = 978 + INTEGER(IntKi), PARAMETER :: B1N1Fy = 979 + INTEGER(IntKi), PARAMETER :: B1N2Fy = 980 + INTEGER(IntKi), PARAMETER :: B1N3Fy = 981 + INTEGER(IntKi), PARAMETER :: B1N4Fy = 982 + INTEGER(IntKi), PARAMETER :: B1N5Fy = 983 + INTEGER(IntKi), PARAMETER :: B1N6Fy = 984 + INTEGER(IntKi), PARAMETER :: B1N7Fy = 985 + INTEGER(IntKi), PARAMETER :: B1N8Fy = 986 + INTEGER(IntKi), PARAMETER :: B1N9Fy = 987 + INTEGER(IntKi), PARAMETER :: B2N1Fy = 988 + INTEGER(IntKi), PARAMETER :: B2N2Fy = 989 + INTEGER(IntKi), PARAMETER :: B2N3Fy = 990 + INTEGER(IntKi), PARAMETER :: B2N4Fy = 991 + INTEGER(IntKi), PARAMETER :: B2N5Fy = 992 + INTEGER(IntKi), PARAMETER :: B2N6Fy = 993 + INTEGER(IntKi), PARAMETER :: B2N7Fy = 994 + INTEGER(IntKi), PARAMETER :: B2N8Fy = 995 + INTEGER(IntKi), PARAMETER :: B2N9Fy = 996 + INTEGER(IntKi), PARAMETER :: B3N1Fy = 997 + INTEGER(IntKi), PARAMETER :: B3N2Fy = 998 + INTEGER(IntKi), PARAMETER :: B3N3Fy = 999 + INTEGER(IntKi), PARAMETER :: B3N4Fy = 1000 + INTEGER(IntKi), PARAMETER :: B3N5Fy = 1001 + INTEGER(IntKi), PARAMETER :: B3N6Fy = 1002 + INTEGER(IntKi), PARAMETER :: B3N7Fy = 1003 + INTEGER(IntKi), PARAMETER :: B3N8Fy = 1004 + INTEGER(IntKi), PARAMETER :: B3N9Fy = 1005 + INTEGER(IntKi), PARAMETER :: B1N1Fn = 1006 + INTEGER(IntKi), PARAMETER :: B1N2Fn = 1007 + INTEGER(IntKi), PARAMETER :: B1N3Fn = 1008 + INTEGER(IntKi), PARAMETER :: B1N4Fn = 1009 + INTEGER(IntKi), PARAMETER :: B1N5Fn = 1010 + INTEGER(IntKi), PARAMETER :: B1N6Fn = 1011 + INTEGER(IntKi), PARAMETER :: B1N7Fn = 1012 + INTEGER(IntKi), PARAMETER :: B1N8Fn = 1013 + INTEGER(IntKi), PARAMETER :: B1N9Fn = 1014 + INTEGER(IntKi), PARAMETER :: B2N1Fn = 1015 + INTEGER(IntKi), PARAMETER :: B2N2Fn = 1016 + INTEGER(IntKi), PARAMETER :: B2N3Fn = 1017 + INTEGER(IntKi), PARAMETER :: B2N4Fn = 1018 + INTEGER(IntKi), PARAMETER :: B2N5Fn = 1019 + INTEGER(IntKi), PARAMETER :: B2N6Fn = 1020 + INTEGER(IntKi), PARAMETER :: B2N7Fn = 1021 + INTEGER(IntKi), PARAMETER :: B2N8Fn = 1022 + INTEGER(IntKi), PARAMETER :: B2N9Fn = 1023 + INTEGER(IntKi), PARAMETER :: B3N1Fn = 1024 + INTEGER(IntKi), PARAMETER :: B3N2Fn = 1025 + INTEGER(IntKi), PARAMETER :: B3N3Fn = 1026 + INTEGER(IntKi), PARAMETER :: B3N4Fn = 1027 + INTEGER(IntKi), PARAMETER :: B3N5Fn = 1028 + INTEGER(IntKi), PARAMETER :: B3N6Fn = 1029 + INTEGER(IntKi), PARAMETER :: B3N7Fn = 1030 + INTEGER(IntKi), PARAMETER :: B3N8Fn = 1031 + INTEGER(IntKi), PARAMETER :: B3N9Fn = 1032 + INTEGER(IntKi), PARAMETER :: B1N1Ft = 1033 + INTEGER(IntKi), PARAMETER :: B1N2Ft = 1034 + INTEGER(IntKi), PARAMETER :: B1N3Ft = 1035 + INTEGER(IntKi), PARAMETER :: B1N4Ft = 1036 + INTEGER(IntKi), PARAMETER :: B1N5Ft = 1037 + INTEGER(IntKi), PARAMETER :: B1N6Ft = 1038 + INTEGER(IntKi), PARAMETER :: B1N7Ft = 1039 + INTEGER(IntKi), PARAMETER :: B1N8Ft = 1040 + INTEGER(IntKi), PARAMETER :: B1N9Ft = 1041 + INTEGER(IntKi), PARAMETER :: B2N1Ft = 1042 + INTEGER(IntKi), PARAMETER :: B2N2Ft = 1043 + INTEGER(IntKi), PARAMETER :: B2N3Ft = 1044 + INTEGER(IntKi), PARAMETER :: B2N4Ft = 1045 + INTEGER(IntKi), PARAMETER :: B2N5Ft = 1046 + INTEGER(IntKi), PARAMETER :: B2N6Ft = 1047 + INTEGER(IntKi), PARAMETER :: B2N7Ft = 1048 + INTEGER(IntKi), PARAMETER :: B2N8Ft = 1049 + INTEGER(IntKi), PARAMETER :: B2N9Ft = 1050 + INTEGER(IntKi), PARAMETER :: B3N1Ft = 1051 + INTEGER(IntKi), PARAMETER :: B3N2Ft = 1052 + INTEGER(IntKi), PARAMETER :: B3N3Ft = 1053 + INTEGER(IntKi), PARAMETER :: B3N4Ft = 1054 + INTEGER(IntKi), PARAMETER :: B3N5Ft = 1055 + INTEGER(IntKi), PARAMETER :: B3N6Ft = 1056 + INTEGER(IntKi), PARAMETER :: B3N7Ft = 1057 + INTEGER(IntKi), PARAMETER :: B3N8Ft = 1058 + INTEGER(IntKi), PARAMETER :: B3N9Ft = 1059 + INTEGER(IntKi), PARAMETER :: B1N1Clrnc = 1060 + INTEGER(IntKi), PARAMETER :: B1N2Clrnc = 1061 + INTEGER(IntKi), PARAMETER :: B1N3Clrnc = 1062 + INTEGER(IntKi), PARAMETER :: B1N4Clrnc = 1063 + INTEGER(IntKi), PARAMETER :: B1N5Clrnc = 1064 + INTEGER(IntKi), PARAMETER :: B1N6Clrnc = 1065 + INTEGER(IntKi), PARAMETER :: B1N7Clrnc = 1066 + INTEGER(IntKi), PARAMETER :: B1N8Clrnc = 1067 + INTEGER(IntKi), PARAMETER :: B1N9Clrnc = 1068 + INTEGER(IntKi), PARAMETER :: B2N1Clrnc = 1069 + INTEGER(IntKi), PARAMETER :: B2N2Clrnc = 1070 + INTEGER(IntKi), PARAMETER :: B2N3Clrnc = 1071 + INTEGER(IntKi), PARAMETER :: B2N4Clrnc = 1072 + INTEGER(IntKi), PARAMETER :: B2N5Clrnc = 1073 + INTEGER(IntKi), PARAMETER :: B2N6Clrnc = 1074 + INTEGER(IntKi), PARAMETER :: B2N7Clrnc = 1075 + INTEGER(IntKi), PARAMETER :: B2N8Clrnc = 1076 + INTEGER(IntKi), PARAMETER :: B2N9Clrnc = 1077 + INTEGER(IntKi), PARAMETER :: B3N1Clrnc = 1078 + INTEGER(IntKi), PARAMETER :: B3N2Clrnc = 1079 + INTEGER(IntKi), PARAMETER :: B3N3Clrnc = 1080 + INTEGER(IntKi), PARAMETER :: B3N4Clrnc = 1081 + INTEGER(IntKi), PARAMETER :: B3N5Clrnc = 1082 + INTEGER(IntKi), PARAMETER :: B3N6Clrnc = 1083 + INTEGER(IntKi), PARAMETER :: B3N7Clrnc = 1084 + INTEGER(IntKi), PARAMETER :: B3N8Clrnc = 1085 + INTEGER(IntKi), PARAMETER :: B3N9Clrnc = 1086 + INTEGER(IntKi), PARAMETER :: B1N1Cpmin = 1087 + INTEGER(IntKi), PARAMETER :: B1N2Cpmin = 1088 + INTEGER(IntKi), PARAMETER :: B1N3Cpmin = 1089 + INTEGER(IntKi), PARAMETER :: B1N4Cpmin = 1090 + INTEGER(IntKi), PARAMETER :: B1N5Cpmin = 1091 + INTEGER(IntKi), PARAMETER :: B1N6Cpmin = 1092 + INTEGER(IntKi), PARAMETER :: B1N7Cpmin = 1093 + INTEGER(IntKi), PARAMETER :: B1N8Cpmin = 1094 + INTEGER(IntKi), PARAMETER :: B1N9Cpmin = 1095 + INTEGER(IntKi), PARAMETER :: B2N1Cpmin = 1096 + INTEGER(IntKi), PARAMETER :: B2N2Cpmin = 1097 + INTEGER(IntKi), PARAMETER :: B2N3Cpmin = 1098 + INTEGER(IntKi), PARAMETER :: B2N4Cpmin = 1099 + INTEGER(IntKi), PARAMETER :: B2N5Cpmin = 1100 + INTEGER(IntKi), PARAMETER :: B2N6Cpmin = 1101 + INTEGER(IntKi), PARAMETER :: B2N7Cpmin = 1102 + INTEGER(IntKi), PARAMETER :: B2N8Cpmin = 1103 + INTEGER(IntKi), PARAMETER :: B2N9Cpmin = 1104 + INTEGER(IntKi), PARAMETER :: B3N1Cpmin = 1105 + INTEGER(IntKi), PARAMETER :: B3N2Cpmin = 1106 + INTEGER(IntKi), PARAMETER :: B3N3Cpmin = 1107 + INTEGER(IntKi), PARAMETER :: B3N4Cpmin = 1108 + INTEGER(IntKi), PARAMETER :: B3N5Cpmin = 1109 + INTEGER(IntKi), PARAMETER :: B3N6Cpmin = 1110 + INTEGER(IntKi), PARAMETER :: B3N7Cpmin = 1111 + INTEGER(IntKi), PARAMETER :: B3N8Cpmin = 1112 + INTEGER(IntKi), PARAMETER :: B3N9Cpmin = 1113 + INTEGER(IntKi), PARAMETER :: B1N1SigCr = 1114 + INTEGER(IntKi), PARAMETER :: B1N2SigCr = 1115 + INTEGER(IntKi), PARAMETER :: B1N3SigCr = 1116 + INTEGER(IntKi), PARAMETER :: B1N4SigCr = 1117 + INTEGER(IntKi), PARAMETER :: B1N5SigCr = 1118 + INTEGER(IntKi), PARAMETER :: B1N6SigCr = 1119 + INTEGER(IntKi), PARAMETER :: B1N7SigCr = 1120 + INTEGER(IntKi), PARAMETER :: B1N8SigCr = 1121 + INTEGER(IntKi), PARAMETER :: B1N9SigCr = 1122 + INTEGER(IntKi), PARAMETER :: B2N1SigCr = 1123 + INTEGER(IntKi), PARAMETER :: B2N2SigCr = 1124 + INTEGER(IntKi), PARAMETER :: B2N3SigCr = 1125 + INTEGER(IntKi), PARAMETER :: B2N4SigCr = 1126 + INTEGER(IntKi), PARAMETER :: B2N5SigCr = 1127 + INTEGER(IntKi), PARAMETER :: B2N6SigCr = 1128 + INTEGER(IntKi), PARAMETER :: B2N7SigCr = 1129 + INTEGER(IntKi), PARAMETER :: B2N8SigCr = 1130 + INTEGER(IntKi), PARAMETER :: B2N9SigCr = 1131 + INTEGER(IntKi), PARAMETER :: B3N1SigCr = 1132 + INTEGER(IntKi), PARAMETER :: B3N2SigCr = 1133 + INTEGER(IntKi), PARAMETER :: B3N3SigCr = 1134 + INTEGER(IntKi), PARAMETER :: B3N4SigCr = 1135 + INTEGER(IntKi), PARAMETER :: B3N5SigCr = 1136 + INTEGER(IntKi), PARAMETER :: B3N6SigCr = 1137 + INTEGER(IntKi), PARAMETER :: B3N7SigCr = 1138 + INTEGER(IntKi), PARAMETER :: B3N8SigCr = 1139 + INTEGER(IntKi), PARAMETER :: B3N9SigCr = 1140 + INTEGER(IntKi), PARAMETER :: B1N1SgCav = 1141 + INTEGER(IntKi), PARAMETER :: B1N2SgCav = 1142 + INTEGER(IntKi), PARAMETER :: B1N3SgCav = 1143 + INTEGER(IntKi), PARAMETER :: B1N4SgCav = 1144 + INTEGER(IntKi), PARAMETER :: B1N5SgCav = 1145 + INTEGER(IntKi), PARAMETER :: B1N6SgCav = 1146 + INTEGER(IntKi), PARAMETER :: B1N7SgCav = 1147 + INTEGER(IntKi), PARAMETER :: B1N8SgCav = 1148 + INTEGER(IntKi), PARAMETER :: B1N9SgCav = 1149 + INTEGER(IntKi), PARAMETER :: B2N1SgCav = 1150 + INTEGER(IntKi), PARAMETER :: B2N2SgCav = 1151 + INTEGER(IntKi), PARAMETER :: B2N3SgCav = 1152 + INTEGER(IntKi), PARAMETER :: B2N4SgCav = 1153 + INTEGER(IntKi), PARAMETER :: B2N5SgCav = 1154 + INTEGER(IntKi), PARAMETER :: B2N6SgCav = 1155 + INTEGER(IntKi), PARAMETER :: B2N7SgCav = 1156 + INTEGER(IntKi), PARAMETER :: B2N8SgCav = 1157 + INTEGER(IntKi), PARAMETER :: B2N9SgCav = 1158 + INTEGER(IntKi), PARAMETER :: B3N1SgCav = 1159 + INTEGER(IntKi), PARAMETER :: B3N2SgCav = 1160 + INTEGER(IntKi), PARAMETER :: B3N3SgCav = 1161 + INTEGER(IntKi), PARAMETER :: B3N4SgCav = 1162 + INTEGER(IntKi), PARAMETER :: B3N5SgCav = 1163 + INTEGER(IntKi), PARAMETER :: B3N6SgCav = 1164 + INTEGER(IntKi), PARAMETER :: B3N7SgCav = 1165 + INTEGER(IntKi), PARAMETER :: B3N8SgCav = 1166 + INTEGER(IntKi), PARAMETER :: B3N9SgCav = 1167 + INTEGER(IntKi), PARAMETER :: B1N1Gam = 1168 + INTEGER(IntKi), PARAMETER :: B1N2Gam = 1169 + INTEGER(IntKi), PARAMETER :: B1N3Gam = 1170 + INTEGER(IntKi), PARAMETER :: B1N4Gam = 1171 + INTEGER(IntKi), PARAMETER :: B1N5Gam = 1172 + INTEGER(IntKi), PARAMETER :: B1N6Gam = 1173 + INTEGER(IntKi), PARAMETER :: B1N7Gam = 1174 + INTEGER(IntKi), PARAMETER :: B1N8Gam = 1175 + INTEGER(IntKi), PARAMETER :: B1N9Gam = 1176 + INTEGER(IntKi), PARAMETER :: B2N1Gam = 1177 + INTEGER(IntKi), PARAMETER :: B2N2Gam = 1178 + INTEGER(IntKi), PARAMETER :: B2N3Gam = 1179 + INTEGER(IntKi), PARAMETER :: B2N4Gam = 1180 + INTEGER(IntKi), PARAMETER :: B2N5Gam = 1181 + INTEGER(IntKi), PARAMETER :: B2N6Gam = 1182 + INTEGER(IntKi), PARAMETER :: B2N7Gam = 1183 + INTEGER(IntKi), PARAMETER :: B2N8Gam = 1184 + INTEGER(IntKi), PARAMETER :: B2N9Gam = 1185 + INTEGER(IntKi), PARAMETER :: B3N1Gam = 1186 + INTEGER(IntKi), PARAMETER :: B3N2Gam = 1187 + INTEGER(IntKi), PARAMETER :: B3N3Gam = 1188 + INTEGER(IntKi), PARAMETER :: B3N4Gam = 1189 + INTEGER(IntKi), PARAMETER :: B3N5Gam = 1190 + INTEGER(IntKi), PARAMETER :: B3N6Gam = 1191 + INTEGER(IntKi), PARAMETER :: B3N7Gam = 1192 + INTEGER(IntKi), PARAMETER :: B3N8Gam = 1193 + INTEGER(IntKi), PARAMETER :: B3N9Gam = 1194 + + + ! Rotor: + + INTEGER(IntKi), PARAMETER :: RtSpeed = 1195 + INTEGER(IntKi), PARAMETER :: RtTSR = 1196 + INTEGER(IntKi), PARAMETER :: RtVAvgxh = 1197 + INTEGER(IntKi), PARAMETER :: RtVAvgyh = 1198 + INTEGER(IntKi), PARAMETER :: RtVAvgzh = 1199 + INTEGER(IntKi), PARAMETER :: RtSkew = 1200 + INTEGER(IntKi), PARAMETER :: RtAeroFxh = 1201 + INTEGER(IntKi), PARAMETER :: RtAeroFyh = 1202 + INTEGER(IntKi), PARAMETER :: RtAeroFzh = 1203 + INTEGER(IntKi), PARAMETER :: RtAeroMxh = 1204 + INTEGER(IntKi), PARAMETER :: RtAeroMyh = 1205 + INTEGER(IntKi), PARAMETER :: RtAeroMzh = 1206 + INTEGER(IntKi), PARAMETER :: RtAeroPwr = 1207 + INTEGER(IntKi), PARAMETER :: RtArea = 1208 + INTEGER(IntKi), PARAMETER :: RtAeroCp = 1209 + INTEGER(IntKi), PARAMETER :: RtAeroCq = 1210 + INTEGER(IntKi), PARAMETER :: RtAeroCt = 1211 + INTEGER(IntKi), PARAMETER :: DBEMTau1 = 1212 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 1212 + +!End of code generated by Matlab script +! =================================================================================================== + + INTEGER, PARAMETER :: TwNVUnd(3, 9) = RESHAPE( (/ & ! Undisturbed wind velocity + TwN1VUndx,TwN1VUndy,TwN1VUndz, & + TwN2VUndx,TwN2VUndy,TwN2VUndz, & + TwN3VUndx,TwN3VUndy,TwN3VUndz, & + TwN4VUndx,TwN4VUndy,TwN4VUndz, & + TwN5VUndx,TwN5VUndy,TwN5VUndz, & + TwN6VUndx,TwN6VUndy,TwN6VUndz, & + TwN7VUndx,TwN7VUndy,TwN7VUndz, & + TwN8VUndx,TwN8VUndy,TwN8VUndz, & + TwN9VUndx,TwN9VUndy,TwN9VUndz & + /), (/3, 9/) ) + INTEGER, PARAMETER :: TwNSTV(3, 9) = RESHAPE( (/ & ! Structural translational velocity + TwN1STVx,TwN1STVy,TwN1STVz, & + TwN2STVx,TwN2STVy,TwN2STVz, & + TwN3STVx,TwN3STVy,TwN3STVz, & + TwN4STVx,TwN4STVy,TwN4STVz, & + TwN5STVx,TwN5STVy,TwN5STVz, & + TwN6STVx,TwN6STVy,TwN6STVz, & + TwN7STVx,TwN7STVy,TwN7STVz, & + TwN8STVx,TwN8STVy,TwN8STVz, & + TwN9STVx,TwN9STVy,TwN9STVz & + /), (/3, 9/) ) + INTEGER, PARAMETER :: TwNVRel(9) = (/TwN1VRel,TwN2VRel,TwN3VRel,TwN4VRel,TwN5VRel,TwN6VRel,TwN7VRel,TwN8VRel,TwN9VRel/) ! relative wind speed + INTEGER, PARAMETER :: TwNDynP(9) = (/TwN1DynP,TwN2DynP,TwN3DynP,TwN4DynP,TwN5DynP,TwN6DynP,TwN7DynP,TwN8DynP,TwN9DynP/) ! dynamic pressure + INTEGER, PARAMETER :: TwNRe(9) = (/TwN1Re,TwN2Re,TwN3Re,TwN4Re,TwN5Re,TwN6Re,TwN7Re,TwN8Re,TwN9Re/) ! Reynolds number + INTEGER, PARAMETER :: TwNM(9) = (/TwN1M,TwN2M,TwN3M,TwN4M,TwN5M,TwN6M,TwN7M,TwN8M,TwN9M/) ! Mach number + INTEGER, PARAMETER :: TwNFdx(9) = (/TwN1Fdx,TwN2Fdx,TwN3Fdx,TwN4Fdx,TwN5Fdx,TwN6Fdx,TwN7Fdx,TwN8Fdx,TwN9Fdx/) ! x-component drag force per unit length + INTEGER, PARAMETER :: TwNFdy(9) = (/TwN1Fdy,TwN2Fdy,TwN3Fdy,TwN4Fdy,TwN5Fdy,TwN6Fdy,TwN7Fdy,TwN8Fdy,TwN9Fdy/) ! y-component drag force per unit length + INTEGER, PARAMETER :: BAzimuth(3) = (/B1Azimuth,B2Azimuth,B3Azimuth/) ! azimuth angle + INTEGER, PARAMETER :: BPitch(3) = (/B1Pitch, B2Pitch, B3Pitch/) ! pitch + + INTEGER, PARAMETER :: BNVUndx(9, 3) = RESHAPE( (/ & ! undisturbed wind velocity (x component) + B1N1VUndx,B1N2VUndx,B1N3VUndx,B1N4VUndx,B1N5VUndx,B1N6VUndx,B1N7VUndx,B1N8VUndx,B1N9VUndx, & + B2N1VUndx,B2N2VUndx,B2N3VUndx,B2N4VUndx,B2N5VUndx,B2N6VUndx,B2N7VUndx,B2N8VUndx,B2N9VUndx, & + B3N1VUndx,B3N2VUndx,B3N3VUndx,B3N4VUndx,B3N5VUndx,B3N6VUndx,B3N7VUndx,B3N8VUndx,B3N9VUndx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVUndy(9, 3) = RESHAPE( (/ & ! undisturbed wind velocity (y component) + B1N1VUndy,B1N2VUndy,B1N3VUndy,B1N4VUndy,B1N5VUndy,B1N6VUndy,B1N7VUndy,B1N8VUndy,B1N9VUndy, & + B2N1VUndy,B2N2VUndy,B2N3VUndy,B2N4VUndy,B2N5VUndy,B2N6VUndy,B2N7VUndy,B2N8VUndy,B2N9VUndy, & + B3N1VUndy,B3N2VUndy,B3N3VUndy,B3N4VUndy,B3N5VUndy,B3N6VUndy,B3N7VUndy,B3N8VUndy,B3N9VUndy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVUndz(9, 3) = RESHAPE( (/ & ! undisturbed wind velocity (z component) + B1N1VUndz,B1N2VUndz,B1N3VUndz,B1N4VUndz,B1N5VUndz,B1N6VUndz,B1N7VUndz,B1N8VUndz,B1N9VUndz, & + B2N1VUndz,B2N2VUndz,B2N3VUndz,B2N4VUndz,B2N5VUndz,B2N6VUndz,B2N7VUndz,B2N8VUndz,B2N9VUndz, & + B3N1VUndz,B3N2VUndz,B3N3VUndz,B3N4VUndz,B3N5VUndz,B3N6VUndz,B3N7VUndz,B3N8VUndz,B3N9VUndz & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNVDisx(9, 3) = RESHAPE( (/ & ! disturbed wind velocity (x component) + B1N1VDisx,B1N2VDisx,B1N3VDisx,B1N4VDisx,B1N5VDisx,B1N6VDisx,B1N7VDisx,B1N8VDisx,B1N9VDisx, & + B2N1VDisx,B2N2VDisx,B2N3VDisx,B2N4VDisx,B2N5VDisx,B2N6VDisx,B2N7VDisx,B2N8VDisx,B2N9VDisx, & + B3N1VDisx,B3N2VDisx,B3N3VDisx,B3N4VDisx,B3N5VDisx,B3N6VDisx,B3N7VDisx,B3N8VDisx,B3N9VDisx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVDisy(9, 3) = RESHAPE( (/ & ! disturbed wind velocity (y component) + B1N1VDisy,B1N2VDisy,B1N3VDisy,B1N4VDisy,B1N5VDisy,B1N6VDisy,B1N7VDisy,B1N8VDisy,B1N9VDisy, & + B2N1VDisy,B2N2VDisy,B2N3VDisy,B2N4VDisy,B2N5VDisy,B2N6VDisy,B2N7VDisy,B2N8VDisy,B2N9VDisy, & + B3N1VDisy,B3N2VDisy,B3N3VDisy,B3N4VDisy,B3N5VDisy,B3N6VDisy,B3N7VDisy,B3N8VDisy,B3N9VDisy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVDisz(9, 3) = RESHAPE( (/ & ! disturbed wind velocity (z component) + B1N1VDisz,B1N2VDisz,B1N3VDisz,B1N4VDisz,B1N5VDisz,B1N6VDisz,B1N7VDisz,B1N8VDisz,B1N9VDisz, & + B2N1VDisz,B2N2VDisz,B2N3VDisz,B2N4VDisz,B2N5VDisz,B2N6VDisz,B2N7VDisz,B2N8VDisz,B2N9VDisz, & + B3N1VDisz,B3N2VDisz,B3N3VDisz,B3N4VDisz,B3N5VDisz,B3N6VDisz,B3N7VDisz,B3N8VDisz,B3N9VDisz & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNSTVx(9, 3) = RESHAPE( (/ & ! structural translational velocity (x component) + B1N1STVx,B1N2STVx,B1N3STVx,B1N4STVx,B1N5STVx,B1N6STVx,B1N7STVx,B1N8STVx,B1N9STVx, & + B2N1STVx,B2N2STVx,B2N3STVx,B2N4STVx,B2N5STVx,B2N6STVx,B2N7STVx,B2N8STVx,B2N9STVx, & + B3N1STVx,B3N2STVx,B3N3STVx,B3N4STVx,B3N5STVx,B3N6STVx,B3N7STVx,B3N8STVx,B3N9STVx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNSTVy(9, 3) = RESHAPE( (/ & ! structural translational velocity (y component) + B1N1STVy,B1N2STVy,B1N3STVy,B1N4STVy,B1N5STVy,B1N6STVy,B1N7STVy,B1N8STVy,B1N9STVy, & + B2N1STVy,B2N2STVy,B2N3STVy,B2N4STVy,B2N5STVy,B2N6STVy,B2N7STVy,B2N8STVy,B2N9STVy, & + B3N1STVy,B3N2STVy,B3N3STVy,B3N4STVy,B3N5STVy,B3N6STVy,B3N7STVy,B3N8STVy,B3N9STVy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNSTVz(9, 3) = RESHAPE( (/ & ! structural translational velocity (z component) + B1N1STVz,B1N2STVz,B1N3STVz,B1N4STVz,B1N5STVz,B1N6STVz,B1N7STVz,B1N8STVz,B1N9STVz, & + B2N1STVz,B2N2STVz,B2N3STVz,B2N4STVz,B2N5STVz,B2N6STVz,B2N7STVz,B2N8STVz,B2N9STVz, & + B3N1STVz,B3N2STVz,B3N3STVz,B3N4STVz,B3N5STVz,B3N6STVz,B3N7STVz,B3N8STVz,B3N9STVz & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNVRel(9, 3) = RESHAPE( (/ & ! relative wind speed + B1N1VRel,B1N2VRel,B1N3VRel,B1N4VRel,B1N5VRel,B1N6VRel,B1N7VRel,B1N8VRel,B1N9VRel, & + B2N1VRel,B2N2VRel,B2N3VRel,B2N4VRel,B2N5VRel,B2N6VRel,B2N7VRel,B2N8VRel,B2N9VRel, & + B3N1VRel,B3N2VRel,B3N3VRel,B3N4VRel,B3N5VRel,B3N6VRel,B3N7VRel,B3N8VRel,B3N9VRel & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNDynP(9, 3) = RESHAPE( (/ & ! dynamic pressure + B1N1DynP,B1N2DynP,B1N3DynP,B1N4DynP,B1N5DynP,B1N6DynP,B1N7DynP,B1N8DynP,B1N9DynP, & + B2N1DynP,B2N2DynP,B2N3DynP,B2N4DynP,B2N5DynP,B2N6DynP,B2N7DynP,B2N8DynP,B2N9DynP, & + B3N1DynP,B3N2DynP,B3N3DynP,B3N4DynP,B3N5DynP,B3N6DynP,B3N7DynP,B3N8DynP,B3N9DynP & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNRe(9, 3) = RESHAPE( (/ & ! Reynolds number + B1N1Re,B1N2Re,B1N3Re,B1N4Re,B1N5Re,B1N6Re,B1N7Re,B1N8Re,B1N9Re, & + B2N1Re,B2N2Re,B2N3Re,B2N4Re,B2N5Re,B2N6Re,B2N7Re,B2N8Re,B2N9Re, & + B3N1Re,B3N2Re,B3N3Re,B3N4Re,B3N5Re,B3N6Re,B3N7Re,B3N8Re,B3N9Re & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNM(9, 3) = RESHAPE( (/ & ! Mach number + B1N1M,B1N2M,B1N3M,B1N4M,B1N5M,B1N6M,B1N7M,B1N8M,B1N9M, & + B2N1M,B2N2M,B2N3M,B2N4M,B2N5M,B2N6M,B2N7M,B2N8M,B2N9M, & + B3N1M,B3N2M,B3N3M,B3N4M,B3N5M,B3N6M,B3N7M,B3N8M,B3N9M & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVIndx(9, 3) = RESHAPE( (/ & ! axial induced wind velocity + B1N1VIndx,B1N2VIndx,B1N3VIndx,B1N4VIndx,B1N5VIndx,B1N6VIndx,B1N7VIndx,B1N8VIndx,B1N9VIndx, & + B2N1VIndx,B2N2VIndx,B2N3VIndx,B2N4VIndx,B2N5VIndx,B2N6VIndx,B2N7VIndx,B2N8VIndx,B2N9VIndx, & + B3N1VIndx,B3N2VIndx,B3N3VIndx,B3N4VIndx,B3N5VIndx,B3N6VIndx,B3N7VIndx,B3N8VIndx,B3N9VIndx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNVIndy(9, 3) = RESHAPE( (/ & ! tangential induced wind velocity + B1N1VIndy,B1N2VIndy,B1N3VIndy,B1N4VIndy,B1N5VIndy,B1N6VIndy,B1N7VIndy,B1N8VIndy,B1N9VIndy, & + B2N1VIndy,B2N2VIndy,B2N3VIndy,B2N4VIndy,B2N5VIndy,B2N6VIndy,B2N7VIndy,B2N8VIndy,B2N9VIndy, & + B3N1VIndy,B3N2VIndy,B3N3VIndy,B3N4VIndy,B3N5VIndy,B3N6VIndy,B3N7VIndy,B3N8VIndy,B3N9VIndy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNAxInd(9, 3) = RESHAPE( (/ & ! axial induction factor + B1N1AxInd,B1N2AxInd,B1N3AxInd,B1N4AxInd,B1N5AxInd,B1N6AxInd,B1N7AxInd,B1N8AxInd,B1N9AxInd, & + B2N1AxInd,B2N2AxInd,B2N3AxInd,B2N4AxInd,B2N5AxInd,B2N6AxInd,B2N7AxInd,B2N8AxInd,B2N9AxInd, & + B3N1AxInd,B3N2AxInd,B3N3AxInd,B3N4AxInd,B3N5AxInd,B3N6AxInd,B3N7AxInd,B3N8AxInd,B3N9AxInd & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNTnInd(9, 3) = RESHAPE( (/ & ! tangential induction factor + B1N1TnInd,B1N2TnInd,B1N3TnInd,B1N4TnInd,B1N5TnInd,B1N6TnInd,B1N7TnInd,B1N8TnInd,B1N9TnInd, & + B2N1TnInd,B2N2TnInd,B2N3TnInd,B2N4TnInd,B2N5TnInd,B2N6TnInd,B2N7TnInd,B2N8TnInd,B2N9TnInd, & + B3N1TnInd,B3N2TnInd,B3N3TnInd,B3N4TnInd,B3N5TnInd,B3N6TnInd,B3N7TnInd,B3N8TnInd,B3N9TnInd & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNAlpha(9, 3) = RESHAPE( (/ & ! angle of attach + B1N1Alpha,B1N2Alpha,B1N3Alpha,B1N4Alpha,B1N5Alpha,B1N6Alpha,B1N7Alpha,B1N8Alpha,B1N9Alpha, & + B2N1Alpha,B2N2Alpha,B2N3Alpha,B2N4Alpha,B2N5Alpha,B2N6Alpha,B2N7Alpha,B2N8Alpha,B2N9Alpha, & + B3N1Alpha,B3N2Alpha,B3N3Alpha,B3N4Alpha,B3N5Alpha,B3N6Alpha,B3N7Alpha,B3N8Alpha,B3N9Alpha & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNTheta(9, 3) = RESHAPE( (/ & ! pitch+twist angle + B1N1Theta,B1N2Theta,B1N3Theta,B1N4Theta,B1N5Theta,B1N6Theta,B1N7Theta,B1N8Theta,B1N9Theta, & + B2N1Theta,B2N2Theta,B2N3Theta,B2N4Theta,B2N5Theta,B2N6Theta,B2N7Theta,B2N8Theta,B2N9Theta, & + B3N1Theta,B3N2Theta,B3N3Theta,B3N4Theta,B3N5Theta,B3N6Theta,B3N7Theta,B3N8Theta,B3N9Theta & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNPhi(9, 3) = RESHAPE( (/ & ! inflow angle + B1N1Phi,B1N2Phi,B1N3Phi,B1N4Phi,B1N5Phi,B1N6Phi,B1N7Phi,B1N8Phi,B1N9Phi, & + B2N1Phi,B2N2Phi,B2N3Phi,B2N4Phi,B2N5Phi,B2N6Phi,B2N7Phi,B2N8Phi,B2N9Phi, & + B3N1Phi,B3N2Phi,B3N3Phi,B3N4Phi,B3N5Phi,B3N6Phi,B3N7Phi,B3N8Phi,B3N9Phi & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCurve(9, 3) = RESHAPE( (/ & ! curvature angle + B1N1Curve,B1N2Curve,B1N3Curve,B1N4Curve,B1N5Curve,B1N6Curve,B1N7Curve,B1N8Curve,B1N9Curve, & + B2N1Curve,B2N2Curve,B2N3Curve,B2N4Curve,B2N5Curve,B2N6Curve,B2N7Curve,B2N8Curve,B2N9Curve, & + B3N1Curve,B3N2Curve,B3N3Curve,B3N4Curve,B3N5Curve,B3N6Curve,B3N7Curve,B3N8Curve,B3N9Curve & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCl(9, 3) = RESHAPE( (/ & ! lift force coefficient + B1N1Cl,B1N2Cl,B1N3Cl,B1N4Cl,B1N5Cl,B1N6Cl,B1N7Cl,B1N8Cl,B1N9Cl, & + B2N1Cl,B2N2Cl,B2N3Cl,B2N4Cl,B2N5Cl,B2N6Cl,B2N7Cl,B2N8Cl,B2N9Cl, & + B3N1Cl,B3N2Cl,B3N3Cl,B3N4Cl,B3N5Cl,B3N6Cl,B3N7Cl,B3N8Cl,B3N9Cl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCd(9, 3) = RESHAPE( (/ & ! drag force coefficient + B1N1Cd,B1N2Cd,B1N3Cd,B1N4Cd,B1N5Cd,B1N6Cd,B1N7Cd,B1N8Cd,B1N9Cd, & + B2N1Cd,B2N2Cd,B2N3Cd,B2N4Cd,B2N5Cd,B2N6Cd,B2N7Cd,B2N8Cd,B2N9Cd, & + B3N1Cd,B3N2Cd,B3N3Cd,B3N4Cd,B3N5Cd,B3N6Cd,B3N7Cd,B3N8Cd,B3N9Cd & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCm(9, 3) = RESHAPE( (/ & ! pitching moment coefficient + B1N1Cm,B1N2Cm,B1N3Cm,B1N4Cm,B1N5Cm,B1N6Cm,B1N7Cm,B1N8Cm,B1N9Cm, & + B2N1Cm,B2N2Cm,B2N3Cm,B2N4Cm,B2N5Cm,B2N6Cm,B2N7Cm,B2N8Cm,B2N9Cm, & + B3N1Cm,B3N2Cm,B3N3Cm,B3N4Cm,B3N5Cm,B3N6Cm,B3N7Cm,B3N8Cm,B3N9Cm & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNCpmin(9, 3) = RESHAPE( (/ & ! pressure coefficient + B1N1Cpmin,B1N2Cpmin,B1N3Cpmin,B1N4Cpmin,B1N5Cpmin,B1N6Cpmin,B1N7Cpmin,B1N8Cpmin,B1N9Cpmin, & + B2N1Cpmin,B2N2Cpmin,B2N3Cpmin,B2N4Cpmin,B2N5Cpmin,B2N6Cpmin,B2N7Cpmin,B2N8Cpmin,B2N9Cpmin, & + B3N1Cpmin,B3N2Cpmin,B3N3Cpmin,B3N4Cpmin,B3N5Cpmin,B3N6Cpmin,B3N7Cpmin,B3N8Cpmin,B3N9Cpmin & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNSigCr(9, 3) = RESHAPE( (/ & ! Critical cavitation number + B1N1SigCr,B1N2SigCr,B1N3SigCr,B1N4SigCr,B1N5SigCr,B1N6SigCr,B1N7SigCr,B1N8SigCr,B1N9SigCr, & + B2N1SigCr,B2N2SigCr,B2N3SigCr,B2N4SigCr,B2N5SigCr,B2N6SigCr,B2N7SigCr,B2N8SigCr,B2N9SigCr, & + B3N1SigCr,B3N2SigCr,B3N3SigCr,B3N4SigCr,B3N5SigCr,B3N6SigCr,B3N7SigCr,B3N8SigCr,B3N9SigCr & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNSgCav(9, 3) = RESHAPE( (/ & ! Cavitation number + B1N1SgCav,B1N2SgCav,B1N3SgCav,B1N4SgCav,B1N5SgCav,B1N6SgCav,B1N7SgCav,B1N8SgCav,B1N9SgCav, & + B2N1SgCav,B2N2SgCav,B2N3SgCav,B2N4SgCav,B2N5SgCav,B2N6SgCav,B2N7SgCav,B2N8SgCav,B2N9SgCav, & + B3N1SgCav,B3N2SgCav,B3N3SgCav,B3N4SgCav,B3N5SgCav,B3N6SgCav,B3N7SgCav,B3N8SgCav,B3N9SgCav & + /), (/9, 3/) ) + + INTEGER, PARAMETER :: BNCx(9, 3) = RESHAPE( (/ & ! normal force (to plane) coefficient + B1N1Cx,B1N2Cx,B1N3Cx,B1N4Cx,B1N5Cx,B1N6Cx,B1N7Cx,B1N8Cx,B1N9Cx, & + B2N1Cx,B2N2Cx,B2N3Cx,B2N4Cx,B2N5Cx,B2N6Cx,B2N7Cx,B2N8Cx,B2N9Cx, & + B3N1Cx,B3N2Cx,B3N3Cx,B3N4Cx,B3N5Cx,B3N6Cx,B3N7Cx,B3N8Cx,B3N9Cx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCy(9, 3) = RESHAPE( (/ & ! tangential force (to plane) coefficient + B1N1Cy,B1N2Cy,B1N3Cy,B1N4Cy,B1N5Cy,B1N6Cy,B1N7Cy,B1N8Cy,B1N9Cy, & + B2N1Cy,B2N2Cy,B2N3Cy,B2N4Cy,B2N5Cy,B2N6Cy,B2N7Cy,B2N8Cy,B2N9Cy, & + B3N1Cy,B3N2Cy,B3N3Cy,B3N4Cy,B3N5Cy,B3N6Cy,B3N7Cy,B3N8Cy,B3N9Cy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCn(9, 3) = RESHAPE( (/ & ! normal force (to chord) coefficient + B1N1Cn,B1N2Cn,B1N3Cn,B1N4Cn,B1N5Cn,B1N6Cn,B1N7Cn,B1N8Cn,B1N9Cn, & + B2N1Cn,B2N2Cn,B2N3Cn,B2N4Cn,B2N5Cn,B2N6Cn,B2N7Cn,B2N8Cn,B2N9Cn, & + B3N1Cn,B3N2Cn,B3N3Cn,B3N4Cn,B3N5Cn,B3N6Cn,B3N7Cn,B3N8Cn,B3N9Cn & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNCt(9, 3) = RESHAPE( (/ & ! tangential force (to chord) coefficient + B1N1Ct,B1N2Ct,B1N3Ct,B1N4Ct,B1N5Ct,B1N6Ct,B1N7Ct,B1N8Ct,B1N9Ct, & + B2N1Ct,B2N2Ct,B2N3Ct,B2N4Ct,B2N5Ct,B2N6Ct,B2N7Ct,B2N8Ct,B2N9Ct, & + B3N1Ct,B3N2Ct,B3N3Ct,B3N4Ct,B3N5Ct,B3N6Ct,B3N7Ct,B3N8Ct,B3N9Ct & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFl(9, 3) = RESHAPE( (/ & ! lift force per unit length + B1N1Fl,B1N2Fl,B1N3Fl,B1N4Fl,B1N5Fl,B1N6Fl,B1N7Fl,B1N8Fl,B1N9Fl, & + B2N1Fl,B2N2Fl,B2N3Fl,B2N4Fl,B2N5Fl,B2N6Fl,B2N7Fl,B2N8Fl,B2N9Fl, & + B3N1Fl,B3N2Fl,B3N3Fl,B3N4Fl,B3N5Fl,B3N6Fl,B3N7Fl,B3N8Fl,B3N9Fl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFd(9, 3) = RESHAPE( (/ & ! drag force per unit length + B1N1Fd,B1N2Fd,B1N3Fd,B1N4Fd,B1N5Fd,B1N6Fd,B1N7Fd,B1N8Fd,B1N9Fd, & + B2N1Fd,B2N2Fd,B2N3Fd,B2N4Fd,B2N5Fd,B2N6Fd,B2N7Fd,B2N8Fd,B2N9Fd, & + B3N1Fd,B3N2Fd,B3N3Fd,B3N4Fd,B3N5Fd,B3N6Fd,B3N7Fd,B3N8Fd,B3N9Fd & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNMm(9, 3) = RESHAPE( (/ & ! pitching moment per unit length + B1N1Mm,B1N2Mm,B1N3Mm,B1N4Mm,B1N5Mm,B1N6Mm,B1N7Mm,B1N8Mm,B1N9Mm, & + B2N1Mm,B2N2Mm,B2N3Mm,B2N4Mm,B2N5Mm,B2N6Mm,B2N7Mm,B2N8Mm,B2N9Mm, & + B3N1Mm,B3N2Mm,B3N3Mm,B3N4Mm,B3N5Mm,B3N6Mm,B3N7Mm,B3N8Mm,B3N9Mm & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFx(9, 3) = RESHAPE( (/ & ! normal force (to plane) per unit length + B1N1Fx,B1N2Fx,B1N3Fx,B1N4Fx,B1N5Fx,B1N6Fx,B1N7Fx,B1N8Fx,B1N9Fx, & + B2N1Fx,B2N2Fx,B2N3Fx,B2N4Fx,B2N5Fx,B2N6Fx,B2N7Fx,B2N8Fx,B2N9Fx, & + B3N1Fx,B3N2Fx,B3N3Fx,B3N4Fx,B3N5Fx,B3N6Fx,B3N7Fx,B3N8Fx,B3N9Fx & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFy(9, 3) = RESHAPE( (/ & ! tangential force (to plane) per unit length + B1N1Fy,B1N2Fy,B1N3Fy,B1N4Fy,B1N5Fy,B1N6Fy,B1N7Fy,B1N8Fy,B1N9Fy, & + B2N1Fy,B2N2Fy,B2N3Fy,B2N4Fy,B2N5Fy,B2N6Fy,B2N7Fy,B2N8Fy,B2N9Fy, & + B3N1Fy,B3N2Fy,B3N3Fy,B3N4Fy,B3N5Fy,B3N6Fy,B3N7Fy,B3N8Fy,B3N9Fy & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFn(9, 3) = RESHAPE( (/ & ! normal force (to chord) per unit length + B1N1Fn,B1N2Fn,B1N3Fn,B1N4Fn,B1N5Fn,B1N6Fn,B1N7Fn,B1N8Fn,B1N9Fn, & + B2N1Fn,B2N2Fn,B2N3Fn,B2N4Fn,B2N5Fn,B2N6Fn,B2N7Fn,B2N8Fn,B2N9Fn, & + B3N1Fn,B3N2Fn,B3N3Fn,B3N4Fn,B3N5Fn,B3N6Fn,B3N7Fn,B3N8Fn,B3N9Fn & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNFt(9, 3) = RESHAPE( (/ & ! tangential force (to chord) per unit length + B1N1Ft,B1N2Ft,B1N3Ft,B1N4Ft,B1N5Ft,B1N6Ft,B1N7Ft,B1N8Ft,B1N9Ft, & + B2N1Ft,B2N2Ft,B2N3Ft,B2N4Ft,B2N5Ft,B2N6Ft,B2N7Ft,B2N8Ft,B2N9Ft, & + B3N1Ft,B3N2Ft,B3N3Ft,B3N4Ft,B3N5Ft,B3N6Ft,B3N7Ft,B3N8Ft,B3N9Ft & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNClrnc(9, 3) = RESHAPE( (/ & ! tower clearance + B1N1Clrnc,B1N2Clrnc,B1N3Clrnc,B1N4Clrnc,B1N5Clrnc,B1N6Clrnc,B1N7Clrnc,B1N8Clrnc,B1N9Clrnc, & + B2N1Clrnc,B2N2Clrnc,B2N3Clrnc,B2N4Clrnc,B2N5Clrnc,B2N6Clrnc,B2N7Clrnc,B2N8Clrnc,B2N9Clrnc, & + B3N1Clrnc,B3N2Clrnc,B3N3Clrnc,B3N4Clrnc,B3N5Clrnc,B3N6Clrnc,B3N7Clrnc,B3N8Clrnc,B3N9Clrnc & + /), (/9, 3/) ) + INTEGER, PARAMETER :: BNGam(9,3) = RESHAPE( (/ & ! Vorticity gamma + B1N1Gam,B1N2Gam,B1N3Gam,B1N4Gam,B1N5Gam,B1N6Gam,B1N7Gam,B1N8Gam,B1N9Gam, & + B2N1Gam,B2N2Gam,B2N3Gam,B2N4Gam,B2N5Gam,B2N6Gam,B2N7Gam,B2N8Gam,B2N9Gam, & + B3N1Gam,B3N2Gam,B3N3Gam,B3N4Gam,B3N5Gam,B3N6Gam,B3N7Gam,B3N8Gam,B3N9Gam & + /), (/9,3/) ) + + + INTEGER(IntKi), PARAMETER :: MaxBl = 3 ! Maximum number of blades allowed in simulation + + +contains + +!> Compute maximum radius over all blades (contains hub radius), in "projected rotor plane" +!! Solely based on AD inputs, needed for FVW since rLocal is not stored +PURE REAL(ReKi) FUNCTION Calc_MaxRadius(p, u) result(rmax) + implicit none + TYPE(AD_ParameterType), INTENT(IN ) :: p !< The module parameters + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs + real(ReKi) :: y_hat_disk(3), z_hat_disk(3), dr_gl(3), rLocal + integer(IntKi) :: iB, j + y_hat_disk = u%HubMotion%Orientation(2,:,1) + z_hat_disk = u%HubMotion%Orientation(3,:,1) + rmax = 0.0_ReKi + do iB=1,p%numBlades + do j=1,p%NumBlNds + dr_gl = u%BladeMotion(iB)%Position(:,j) - u%HubMotion%Position(:,1) ! vector hub center to node j in global coord + rLocal = sqrt( dot_product(dr_gl, y_hat_disk)**2 + dot_product(dr_gl, z_hat_disk)**2 ) + rmax = max(rmax, rLocal) + end do !j=nodes + end do !iB=blades +END FUNCTION Calc_MaxRadius + +!> Rotor speed +PURE REAL(ReKi) FUNCTION Calc_Omega(u) + TYPE(AD_InputType), INTENT(IN ) :: u !< Inputs + Calc_Omega = dot_product(u%HubMotion%RotationVel(:,1), u%HubMotion%Orientation(1,:,1)) +END FUNCTION Calc_Omega + +!> Mean skew angle +REAL(ReKi) FUNCTION Calc_Chi0(V_diskAvg, V_dot_x) + implicit none + REAL(ReKi), INTENT(IN ) :: V_diskAvg(3) + REAL(ReKi), INTENT(IN ) :: V_dot_x + REAL(ReKi) :: V_norm, sy + V_norm = TwoNorm( V_diskAvg ) + if ( EqualRealNos( V_norm, 0.0_ReKi ) ) then + Calc_Chi0 = 0.0_ReKi + else + ! make sure we don't have numerical issues that make the ratio outside +/-1 + sy = min( 1.0_ReKi, V_dot_x / V_norm ) + sy = max( -1.0_ReKi, sy ) + Calc_Chi0 = acos( sy ) + end if +END FUNCTION Calc_Chi0 + + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Calc_WriteOutput( p, u, m, y, OtherState, xd, indx, ErrStat, ErrMsg ) + + TYPE(AD_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(AD_InputType), INTENT(IN ) :: u ! inputs + TYPE(AD_MiscVarType), INTENT(INOUT) :: m ! misc variables + TYPE(AD_OutputType), INTENT(IN ) :: y ! outputs + TYPE(AD_OtherStateType), INTENT(IN ) :: OtherState ! other states at t (for DBEMT and UA) + TYPE(AD_DiscreteStateType),INTENT(IN ) :: xd ! Discrete states + integer, intent(in ) :: indx ! index into m%BEMT_u(indx) array; 1=t and 2=t+dt (but not checked here) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteOutput' + INTEGER(intKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + INTEGER(IntKi) :: j,k,beta + REAL(ReKi) :: tmp(3) + REAL(ReKi) :: force(3) + REAL(ReKi) :: moment(3) + REAL(ReKi) :: denom, rmax + REAL(ReKi) :: ct, st ! cosine, sine of theta + REAL(ReKi) :: cp, sp ! cosine, sine of phi + + + + ! start routine: + ErrStat = ErrID_None + ErrMsg = "" + + ! tower outputs + do beta=1,p%NTwOuts + j = p%TwOutNd(beta) + + tmp = matmul( u%TowerMotion%Orientation(:,:,j) , u%InflowOnTower(:,j) ) + m%AllOuts( TwNVUnd(:,beta) ) = tmp + + tmp = matmul( u%TowerMotion%Orientation(:,:,j) , u%TowerMotion%TranslationVel(:,j) ) + m%AllOuts( TwNSTV(:,beta) ) = tmp + + m%AllOuts( TwNVrel(beta) ) = m%W_Twr(j) ! relative velocity + m%AllOuts( TwNDynP(beta) ) = 0.5 * p%AirDens * m%W_Twr(j)**2 ! dynamic pressure + m%AllOuts( TwNRe( beta) ) = p%TwrDiam(j) * m%W_Twr(j) / p%KinVisc / 1.0E6 ! reynolds number (in millions) + m%AllOuts( TwNM( beta) ) = m%W_Twr(j) / p%SpdSound ! Mach number + m%AllOuts( TwNFdx( beta) ) = m%X_Twr(j) + m%AllOuts( TwNFdy( beta) ) = m%Y_Twr(j) + + end do ! out nodes + + if (p%WakeMod /= WakeMod_FVW) then + call Calc_WriteOutput_BEMT + else + call Calc_WriteOutput_FVW + endif + + ! blade node tower clearance (requires tower influence calculation): + if (p%TwrPotent /= TwrPotent_none .or. p%TwrShadow /= TwrShadow_none) then + do k=1,p%numBlades + do beta=1,p%NBlOuts + j=p%BlOutNd(beta) + m%AllOuts( BNClrnc( beta,k) ) = m%TwrClrnc(j,k) + end do + end do + end if + +CONTAINS + !.......................................................................................... + subroutine Calc_WriteOutput_BEMT + ! blade outputs + do k=1,p%numBlades + m%AllOuts( BAzimuth(k) ) = MODULO( m%BEMT_u(indx)%psi(k)*R2D, 360.0_ReKi ) + ! m%AllOuts( BPitch( k) ) = calculated in SetInputsForBEMT + + do beta=1,p%NBlOuts + + j=p%BlOutNd(beta) + + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), u%InflowOnBlade(:,j,k) ) + m%AllOuts( BNVUndx(beta,k) ) = tmp(1) + m%AllOuts( BNVUndy(beta,k) ) = tmp(2) + m%AllOuts( BNVUndz(beta,k) ) = tmp(3) + + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), m%DisturbedInflow(:,j,k) ) + m%AllOuts( BNVDisx(beta,k) ) = tmp(1) + m%AllOuts( BNVDisy(beta,k) ) = tmp(2) + m%AllOuts( BNVDisz(beta,k) ) = tmp(3) + + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), u%BladeMotion(k)%TranslationVel(:,j) ) + m%AllOuts( BNSTVx( beta,k) ) = tmp(1) + m%AllOuts( BNSTVy( beta,k) ) = tmp(2) + m%AllOuts( BNSTVz( beta,k) ) = tmp(3) + + m%AllOuts( BNVrel( beta,k) ) = m%BEMT_y%Vrel(j,k) + m%AllOuts( BNDynP( beta,k) ) = 0.5 * p%airDens * m%BEMT_y%Vrel(j,k)**2 + m%AllOuts( BNRe( beta,k) ) = p%BEMT%chord(j,k) * m%BEMT_y%Vrel(j,k) / p%KinVisc / 1.0E6 + m%AllOuts( BNM( beta,k) ) = m%BEMT_y%Vrel(j,k) / p%SpdSound + + m%AllOuts( BNVIndx(beta,k) ) = - m%BEMT_u(indx)%Vx(j,k) * m%BEMT_y%axInduction( j,k) + m%AllOuts( BNVIndy(beta,k) ) = m%BEMT_u(indx)%Vy(j,k) * m%BEMT_y%tanInduction(j,k) + + m%AllOuts( BNAxInd(beta,k) ) = m%BEMT_y%axInduction(j,k) + m%AllOuts( BNTnInd(beta,k) ) = m%BEMT_y%tanInduction(j,k) + + m%AllOuts( BNAlpha(beta,k) ) = Rad2M180to180Deg( m%BEMT_y%phi(j,k) - m%BEMT_u(indx)%theta(j,k) ) + m%AllOuts( BNTheta(beta,k) ) = m%BEMT_u(indx)%theta(j,k)*R2D + m%AllOuts( BNPhi( beta,k) ) = m%BEMT_y%phi(j,k)*R2D + m%AllOuts( BNCurve(beta,k) ) = m%Curve(j,k)*R2D + + !m%AllOuts( BNCl( beta,k) ) = m%BEMT_y%Cl(j,k) + !m%AllOuts( BNCd( beta,k) ) = m%BEMT_y%Cd(j,k) + + m%AllOuts( BNCpmin( beta,k) ) = m%BEMT_y%Cpmin(j,k) + m%AllOuts( BNSigCr( beta,k) ) = m%SigmaCavitCrit(j,k) + m%AllOuts( BNSgCav( beta,k) ) = m%SigmaCavit(j,k) + + cp=cos(m%BEMT_y%phi(j,k)) + sp=sin(m%BEMT_y%phi(j,k)) + m%AllOuts( BNCl( beta,k) ) = m%BEMT_y%Cx(j,k)*cp + m%BEMT_y%Cy(j,k)*sp + m%AllOuts( BNCd( beta,k) ) = m%BEMT_y%Cx(j,k)*sp - m%BEMT_y%Cy(j,k)*cp + m%AllOuts( BNCm( beta,k) ) = m%BEMT_y%Cm(j,k) + m%AllOuts( BNCx( beta,k) ) = m%BEMT_y%Cx(j,k) + m%AllOuts( BNCy( beta,k) ) = m%BEMT_y%Cy(j,k) + + ct=cos(m%BEMT_u(indx)%theta(j,k)) + st=sin(m%BEMT_u(indx)%theta(j,k)) + m%AllOuts( BNCn( beta,k) ) = m%BEMT_y%Cx(j,k)*ct + m%BEMT_y%Cy(j,k)*st + m%AllOuts( BNCt( beta,k) ) =-m%BEMT_y%Cx(j,k)*st + m%BEMT_y%Cy(j,k)*ct + + m%AllOuts( BNFl( beta,k) ) = m%X(j,k)*cp - m%Y(j,k)*sp + m%AllOuts( BNFd( beta,k) ) = m%X(j,k)*sp + m%Y(j,k)*cp + m%AllOuts( BNMm( beta,k) ) = m%M(j,k) + m%AllOuts( BNFx( beta,k) ) = m%X(j,k) + m%AllOuts( BNFy( beta,k) ) = -m%Y(j,k) + m%AllOuts( BNFn( beta,k) ) = m%X(j,k)*ct - m%Y(j,k)*st + m%AllOuts( BNFt( beta,k) ) = -m%X(j,k)*st - m%Y(j,k)*ct + + m%AllOuts( BNGam( beta,k) ) = 0.5_ReKi * p%BEMT%chord(j,k) * m%BEMT_y%Vrel(j,k) * m%BEMT_y%Cl(j,k) ! "Gam" [m^2/s] + end do ! nodes + end do ! blades + + ! rotor outputs: + rmax = 0.0_ReKi + do k=1,p%NumBlades + do j=1,p%NumBlNds + rmax = max(rmax, m%BEMT_u(indx)%rLocal(j,k) ) + end do !j=nodes + end do !k=blades + + m%AllOuts( RtSpeed ) = m%BEMT_u(indx)%omega*RPS2RPM + m%AllOuts( RtArea ) = pi*rmax**2 + + tmp = matmul( u%HubMotion%Orientation(:,:,1), m%V_DiskAvg ) + m%AllOuts( RtVAvgxh ) = tmp(1) + m%AllOuts( RtVAvgyh ) = tmp(2) + m%AllOuts( RtVAvgzh ) = tmp(3) + + m%AllOuts( RtSkew ) = m%BEMT_u(indx)%chi0*R2D + + ! integrate force/moments over blades by performing mesh transfer to hub point: + force = 0.0_ReKi + moment = 0.0_ReKi + do k=1,p%NumBlades + call Transfer_Line2_to_Point( y%BladeLoad(k), m%HubLoad, m%B_L_2_H_P(k), ErrStat2, ErrMsg2, u%BladeMotion(k), u%HubMotion ) + force = force + m%HubLoad%force( :,1) + moment = moment + m%HubLoad%moment(:,1) + end do + tmp = matmul( u%HubMotion%Orientation(:,:,1), force ) + m%AllOuts( RtAeroFxh ) = tmp(1) + m%AllOuts( RtAeroFyh ) = tmp(2) + m%AllOuts( RtAeroFzh ) = tmp(3) + + tmp = matmul( u%HubMotion%Orientation(:,:,1), moment ) + m%AllOuts( RtAeroMxh ) = tmp(1) + m%AllOuts( RtAeroMyh ) = tmp(2) + m%AllOuts( RtAeroMzh ) = tmp(3) + + m%AllOuts( RtAeroPwr ) = m%BEMT_u(indx)%omega * m%AllOuts( RtAeroMxh ) + + m%AllOuts( RtTSR ) = m%BEMT_u(indx)%TSR + + if ( EqualRealNos( m%V_dot_x, 0.0_ReKi ) ) then + m%AllOuts( RtTSR ) = 0.0_ReKi + m%AllOuts( RtAeroCp ) = 0.0_ReKi + m%AllOuts( RtAeroCq ) = 0.0_ReKi + m%AllOuts( RtAeroCt ) = 0.0_ReKi + else + denom = 0.5*p%AirDens*m%AllOuts( RtArea )*m%V_dot_x**2 + m%AllOuts( RtTSR ) = m%BEMT_u(indx)%omega * rmax / m%V_dot_x + + m%AllOuts( RtAeroCp ) = m%AllOuts( RtAeroPwr ) / (denom * m%V_dot_x) + m%AllOuts( RtAeroCq ) = m%AllOuts( RtAeroMxh ) / (denom * rmax) + m%AllOuts( RtAeroCt ) = m%AllOuts( RtAeroFxh ) / denom + end if + + m%AllOuts( DBEMTau1 ) = OtherState%BEMT%DBEMT%tau1 + + end subroutine Calc_WriteOutput_BEMT + + !.......................................................................................... + !> Similar to Calc_WriteOutput_BEMT. TODO Merge me + !! NOTE: relies on the prior calculation of m%V_dot_x, and m%V_diskAvg (done in DiskAvgValues) + !! m%DisturbedInflow (done in SetInputs) + !! Make sure these are set! + subroutine Calc_WriteOutput_FVW + + real(ReKi) :: rmax, omega + + ! blade outputs + do k=1,p%numBlades + do beta=1,p%NBlOuts + j=p%BlOutNd(beta) + + ! --- Setting AD outputs + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), u%InflowOnBlade(:,j,k) ) + m%AllOuts( BNVUndx(beta,k) ) = tmp(1) + m%AllOuts( BNVUndy(beta,k) ) = tmp(2) + m%AllOuts( BNVUndz(beta,k) ) = tmp(3) + + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), m%DisturbedInflow(:,j,k) ) + m%AllOuts( BNVDisx(beta,k) ) = tmp(1) + m%AllOuts( BNVDisy(beta,k) ) = tmp(2) + m%AllOuts( BNVDisz(beta,k) ) = tmp(3) + + tmp = matmul( m%WithoutSweepPitchTwist(:,:,j,k), u%BladeMotion(k)%TranslationVel(:,j) ) + m%AllOuts( BNSTVx( beta,k) ) = tmp(1) + m%AllOuts( BNSTVy( beta,k) ) = tmp(2) + m%AllOuts( BNSTVz( beta,k) ) = tmp(3) + + m%AllOuts( BNVrel( beta,k) ) = m%FVW%BN_Vrel(j,k) + m%AllOuts( BNDynP( beta,k) ) = 0.5 * p%airDens * m%FVW%BN_Vrel(j,k)**2 + m%AllOuts( BNRe( beta,k) ) = m%FVW%BN_Re(j,k) + m%AllOuts( BNM( beta,k) ) = m%FVW%BN_Vrel(j,k) / p%SpdSound + + m%AllOuts( BNVIndx(beta,k) ) = -m%FVW%BN_UrelWind_s(1,j,k) * m%FVW%BN_AxInd(j,k) + m%AllOuts( BNVIndy(beta,k) ) = m%FVW%BN_UrelWind_s(2,j,k) * m%FVW%BN_TanInd(j,k) + + m%AllOuts( BNAxInd(beta,k) ) = m%FVW%BN_AxInd(j,k) + m%AllOuts( BNTnInd(beta,k) ) = m%FVW%BN_TanInd(j,k) + + m%AllOuts( BNAlpha(beta,k) ) = m%FVW%BN_alpha(j,k)*R2D + m%AllOuts( BNTheta(beta,k) ) = m%FVW%PitchAndTwist(j,k)*R2D + m%AllOuts( BNPhi( beta,k) ) = m%FVW%BN_phi(j,k)*R2D +! m%AllOuts( BNCurve(beta,k) ) = m%Curve(j,k)*R2D ! TODO + +! m%AllOuts( BNCpmin( beta,k) ) = m%BEMT_y%Cpmin(j,k) ! TODO + m%AllOuts( BNSigCr( beta,k) ) = m%SigmaCavitCrit(j,k) + m%AllOuts( BNSgCav( beta,k) ) = m%SigmaCavit(j,k) + + m%AllOuts( BNCl( beta,k) ) = m%FVW%BN_Cl(j,k) + m%AllOuts( BNCd( beta,k) ) = m%FVW%BN_Cd(j,k) + m%AllOuts( BNCm( beta,k) ) = m%FVW%BN_Cm(j,k) + m%AllOuts( BNCx( beta,k) ) = m%FVW%BN_Cx(j,k) + m%AllOuts( BNCy( beta,k) ) = m%FVW%BN_Cy(j,k) + + ct=cos(m%FVW%PitchAndTwist(j,k)) ! cos(theta) + st=sin(m%FVW%PitchAndTwist(j,k)) ! sin(theta) + m%AllOuts( BNCn( beta,k) ) = m%FVW%BN_Cx(j,k)*ct + m%FVW%BN_Cy(j,k)*st + m%AllOuts( BNCt( beta,k) ) =-m%FVW%BN_Cx(j,k)*st + m%FVW%BN_Cy(j,k)*ct + + cp=cos(m%FVW%BN_phi(j,k)) + sp=sin(m%FVW%BN_phi(j,k)) + m%AllOuts( BNFl( beta,k) ) = m%X(j,k)*cp - m%Y(j,k)*sp + m%AllOuts( BNFd( beta,k) ) = m%X(j,k)*sp + m%Y(j,k)*cp + m%AllOuts( BNMm( beta,k) ) = m%M(j,k) + m%AllOuts( BNFx( beta,k) ) = m%X(j,k) + m%AllOuts( BNFy( beta,k) ) = -m%Y(j,k) + m%AllOuts( BNFn( beta,k) ) = m%X(j,k)*ct - m%Y(j,k)*st + m%AllOuts( BNFt( beta,k) ) = -m%X(j,k)*st - m%Y(j,k)*ct + + m%AllOuts( BNGam( beta,k) ) = 0.5_ReKi * p%FVW%Chord(j,k) * m%FVW%BN_Vrel(j,k) * m%FVW%BN_Cl(j,k) ! "Gam" [m^2/s] + end do ! nodes + end do ! blades + + ! Compute max radius and rotor speed + rmax = Calc_MaxRadius(p, u) + omega = Calc_Omega(u) + + m%AllOuts( RtSpeed ) = omega*RPS2RPM + m%AllOuts( RtArea ) = pi*rmax**2 + + tmp = matmul( u%HubMotion%Orientation(:,:,1), m%V_DiskAvg ) + m%AllOuts( RtVAvgxh ) = tmp(1) + m%AllOuts( RtVAvgyh ) = tmp(2) + m%AllOuts( RtVAvgzh ) = tmp(3) + + m%AllOuts( RtSkew ) = Calc_Chi0(m%V_diskAvg, m%V_dot_x) * R2D + + ! integrate force/moments over blades by performing mesh transfer to hub point: + force = 0.0_ReKi + moment = 0.0_ReKi + do k=1,p%NumBlades + call Transfer_Line2_to_Point( y%BladeLoad(k), m%HubLoad, m%B_L_2_H_P(k), ErrStat2, ErrMsg2, u%BladeMotion(k), u%HubMotion ) + force = force + m%HubLoad%force( :,1) + moment = moment + m%HubLoad%moment(:,1) + end do + tmp = matmul( u%HubMotion%Orientation(:,:,1), force ) + m%AllOuts( RtAeroFxh ) = tmp(1) + m%AllOuts( RtAeroFyh ) = tmp(2) + m%AllOuts( RtAeroFzh ) = tmp(3) + + tmp = matmul( u%HubMotion%Orientation(:,:,1), moment ) + m%AllOuts( RtAeroMxh ) = tmp(1) + m%AllOuts( RtAeroMyh ) = tmp(2) + m%AllOuts( RtAeroMzh ) = tmp(3) + + m%AllOuts( RtAeroPwr ) = omega * m%AllOuts( RtAeroMxh ) + + if ( EqualRealNos( m%V_dot_x, 0.0_ReKi ) ) then + m%AllOuts( RtTSR ) = 0.0_ReKi + m%AllOuts( RtAeroCp ) = 0.0_ReKi + m%AllOuts( RtAeroCq ) = 0.0_ReKi + m%AllOuts( RtAeroCt ) = 0.0_ReKi + else + denom = 0.5*p%AirDens*m%AllOuts( RtArea )*m%V_dot_x**2 + m%AllOuts( RtTSR ) = omega * rmax / m%V_dot_x + m%AllOuts( RtAeroCp ) = m%AllOuts( RtAeroPwr ) / (denom * m%V_dot_x) + m%AllOuts( RtAeroCq ) = m%AllOuts( RtAeroMxh ) / (denom * rmax) + m%AllOuts( RtAeroCt ) = m%AllOuts( RtAeroFxh ) / denom + end if + + end subroutine Calc_WriteOutput_FVW + +END SUBROUTINE Calc_WriteOutput +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadInputFiles( InputFileName, InputFileData, Default_DT, OutFileRoot, NumBlades, UnEcho, ErrStat, ErrMsg ) +! This subroutine reads the input file and stores all the data in the AD_InputFile structure. +! It does not perform data validation. +!.................................................................................................................................. + + ! Passed variables + REAL(DbKi), INTENT(IN) :: Default_DT ! The default DT (from glue code) + + CHARACTER(*), INTENT(IN) :: InputFileName ! Name of the input file + CHARACTER(*), INTENT(IN) :: OutFileRoot ! The rootname of all the output files written by this routine. + + TYPE(AD_InputFile), INTENT(INOUT) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: UnEcho ! Unit number for the echo file + + INTEGER(IntKi), INTENT(IN) :: NumBlades ! Number of blades for this model + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: I + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + + CHARACTER(1024) :: ADBlFile(MaxBl) ! File that contains the blade information (specified in the primary input file) + CHARACTER(*), PARAMETER :: RoutineName = 'ReadInputFiles' + + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = '' + UnEcho = -1 + InputFileData%DTAero = Default_DT ! the glue code's suggested DT for the module (may be overwritten in ReadPrimaryFile()) + + + ! get the blade input-file data + + ALLOCATE( InputFileData%BladeProps( NumBlades ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for BladeProps.", ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + +!FIXME: add options for passing the blade files. This routine will need restructuring to handle that. + DO I=1,NumBlades + CALL ReadBladeInputs ( InputFileData%ADBlFile(I), InputFileData%BladeProps(I), UnEcho, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName//TRIM(':Blade')//TRIM(Num2LStr(I))) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END DO + + + + CALL Cleanup ( ) + + +CONTAINS + !............................................................................................................................... + SUBROUTINE Cleanup() + ! This subroutine cleans up before exiting this subroutine + !............................................................................................................................... + + ! IF ( UnEcho > 0 ) CLOSE( UnEcho ) + + END SUBROUTINE Cleanup + +END SUBROUTINE ReadInputFiles +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine parses the input file data stored in FileInfo_In and places it in the InputFileData structure for validating. +SUBROUTINE ParsePrimaryFileInfo( PriPath, InputFile, RootName, NumBlades, interval, FileInfo_In, InputFileData, UnEc, ErrStat, ErrMsg ) + implicit none + + ! Passed variables + character(*), intent(in ) :: PriPath !< primary path + CHARACTER(*), intent(in ) :: InputFile !< Name of the file containing the primary input data + CHARACTER(*), intent(in ) :: RootName !< The rootname of the echo file, possibly opened in this routine + integer(IntKi), intent(in ) :: NumBlades !< Number of blades we expect -- from InitInp + real(DBKi), intent(in ) :: interval !< timestep + type(AD_InputFile), intent(inout) :: InputFileData !< All the data in the AD15 primary input file + type(FileInfoType), intent(in ) :: FileInfo_In !< The derived type for holding the file information. + integer(IntKi), intent( out) :: UnEc !< The local unit number for this module's echo file + integer(IntKi), intent( out) :: ErrStat !< Error status + CHARACTER(ErrMsgLen), intent( out) :: ErrMsg !< Error message + + ! Local variables: + integer(IntKi) :: i !< generic counter + integer(IntKi) :: ErrStat2, IOS !< Temporary Error status + character(ErrMsgLen) :: ErrMsg2 !< Temporary Error message + character(ErrMsgLen) :: ErrMsg_NoAllBldNdOuts + integer(IntKi) :: CurLine !< current entry in FileInfo_In%Lines array + real(ReKi) :: TmpRe4(4) !< temporary 4 number array for reading values in + + character(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + character(*), parameter :: RoutineName = 'ParsePrimaryFileInfo' + + ! Initialization + ErrStat = 0 + ErrMsg = "" + UnEc = -1 ! Echo file unit. >0 when used + + + CALL AllocAry( InputFileData%OutList, MaxOutPts, "Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Allocate array for holding the list of node outputs + CALL AllocAry( InputFileData%BldNd_OutList, BldNd_MaxOutPts, "BldNd_Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !------------------------------------------------------------------------------------------------- + ! General settings + !------------------------------------------------------------------------------------------------- + + CurLine = 4 ! Skip the first three lines as they are known to be header lines and separators + call ParseVar( FileInfo_In, CurLine, 'Echo', InputFileData%Echo, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + if ( InputFileData%Echo ) then + CALL OpenEcho ( UnEc, TRIM(RootName)//'.ech', ErrStat2, ErrMsg2 ) + if (Failed()) return; + WRITE(UnEc, '(A)') 'Echo file for AeroDyn 15 primary input file: '//trim(InputFile) + ! Write the first three lines into the echo file + WRITE(UnEc, '(A)') FileInfo_In%Lines(1) + WRITE(UnEc, '(A)') FileInfo_In%Lines(2) + WRITE(UnEc, '(A)') FileInfo_In%Lines(3) + + CurLine = 4 + call ParseVar( FileInfo_In, CurLine, 'Echo', InputFileData%Echo, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + endif + + + ! DTAero - Time interval for aerodynamic calculations {or default} (s): + call ParseVarWDefault ( FileInfo_In, CurLine, "DTAero", InputFileData%DTAero, interval, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT, 2=DBEMT, 3=OLAF} [WakeMod cannot be 2 or 3 when linearizing] + call ParseVar( FileInfo_In, CurLine, "WakeMod", InputFileData%WakeMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AFAeroMod - Type of blade airfoil aerodynamics model (switch) {1=steady model, 2=Beddoes-Leishman unsteady model} [AFAeroMod must be 1 when linearizing] + call ParseVar( FileInfo_In, CurLine, "AFAeroMod", InputFileData%AFAeroMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrPotent - Type tower influence on wind based on potential flow around the tower (switch) {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} + call ParseVar( FileInfo_In, CurLine, "TwrPotent", InputFileData%TwrPotent, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrShadow - Calculate tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model} + call ParseVar( FileInfo_In, CurLine, "TwrShadow", InputFileData%TwrShadow, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrAero - Calculate tower aerodynamic loads? (flag) + call ParseVar( FileInfo_In, CurLine, "TwrAero", InputFileData%TwrAero, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FrozenWake - Assume frozen wake during linearization? (flag) [used only when WakeMod=1 and when linearizing] + call ParseVar( FileInfo_In, CurLine, "FrozenWake", InputFileData%FrozenWake, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! CavitCheck - Perform cavitation check? (flag) [AFAeroMod must be 1 when CavitCheck=true] + call ParseVar( FileInfo_In, CurLine, "CavitCheck", InputFileData%CavitCheck, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! CompAA - Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2] + call ParseVar( FileInfo_In, CurLine, "CompAA", InputFileData%CompAA, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AA_InputFile - Aeroacoustics input file + call ParseVar( FileInfo_In, CurLine, "AA_InputFile", InputFileData%AA_InputFile, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%AA_InputFile ) ) InputFileData%AA_InputFile = TRIM(PriPath)//TRIM(InputFileData%AA_InputFile) + + !====== Environmental Conditions =================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! AirDens - Air density (kg/m^3) + call ParseVar( FileInfo_In, CurLine, "AirDens", InputFileData%AirDens, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! KinVisc - Kinematic air viscosity (m^2/s) + call ParseVar( FileInfo_In, CurLine, "KinVisc", InputFileData%KinVisc, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! SpdSound - Speed of sound (m/s) + call ParseVar( FileInfo_In, CurLine, "SpdSound", InputFileData%SpdSound, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Patm - Atmospheric pressure (Pa) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "Patm", InputFileData%Patm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Pvap - Vapour pressure of fluid (Pa) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "Pvap", InputFileData%Pvap, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FluidDepth - Water depth above mid-hub height (m) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "FluidDepth", InputFileData%FluidDepth, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Blade-Element/Momentum Theory Options ====================================================== [unused when WakeMod=0 or 3] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! SkewMod - Type of skewed-wake correction model (switch) {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "SkewMod", InputFileData%SkewMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! SkewModFactor - Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0 or 3] + call ParseVarWDefault( FileInfo_In, CurLine, "SkewModFactor", InputFileData%SkewModFactor, (15.0_ReKi * pi / 32.0_ReKi), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TipLoss - Use the Prandtl tip-loss model? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "TipLoss", InputFileData%TipLoss, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! HubLoss - Use the Prandtl hub-loss model? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "HubLoss", InputFileData%HubLoss, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TanInd - Include tangential induction in BEMT calculations? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "TanInd", InputFileData%TanInd, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AIDrag - Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "AIDrag", InputFileData%AIDrag, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TIDrag - Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod=0,3 or TanInd=FALSE] + call ParseVar( FileInfo_In, CurLine, "TIDrag", InputFileData%TIDrag, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! IndToler - Convergence tolerance for BEMT nonlinear solve residual equation {or "default"} (-) [unused when WakeMod=0 or 3] + if (ReKi==SiKi) then + call ParseVarWDefault( FileInfo_In, CurLine, "IndToler", InputFileData%IndToler, real(5E-5,ReKi), ErrStat2, ErrMsg2, UnEc ) + else + call ParseVarWDefault( FileInfo_In, CurLine, "IndToler", InputFileData%IndToler, real(5D-10,ReKi), ErrStat2, ErrMsg2, UnEc ) + end if + if (Failed()) return + ! MaxIter - Maximum number of iteration steps (-) [unused when WakeMod=0] + call ParseVar( FileInfo_In, CurLine, "MaxIter", InputFileData%MaxIter, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Dynamic Blade-Element/Momentum Theory Options ============================================== [used only when WakeMod=2] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2] + call ParseVar( FileInfo_In, CurLine, "DBEMT_Mod", InputFileData%DBEMT_Mod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! tau1_const - Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1] + call ParseVar( FileInfo_In, CurLine, "tau1_const", InputFileData%tau1_const, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] + call ParseVar( FileInfo_In, CurLine, "OLAFInputFileName", InputFileData%FVWFileName, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%FVWFileName ) ) InputFileData%FVWFileName = TRIM(PriPath)//TRIM(InputFileData%FVWFileName) + + !====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! UAMod - Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2] + call ParseVar( FileInfo_In, CurLine, "UAMod", InputFileData%UAMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FLookup - Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2] + call ParseVar( FileInfo_In, CurLine, "FLookup", InputFileData%FLookup, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Airfoil Information ========================================================================= + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! AFTabMod - Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-) + call ParseVar( FileInfo_In, CurLine, "AFTabMod", InputFileData%AFTabMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Alfa - The column in the airfoil tables that contains the angle of attack (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Alfa", InputFileData%InCol_Alfa, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cl - The column in the airfoil tables that contains the lift coefficient (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cl", InputFileData%InCol_Cl, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cd - The column in the airfoil tables that contains the drag coefficient (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cd", InputFileData%InCol_Cd, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cm - The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cm", InputFileData%InCol_Cm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cpmin - The column in the airfoil tables that contains the Cpmin coefficient; use zero if there is no Cpmin column (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cpmin", InputFileData%InCol_Cpmin, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! NumAFfiles - Number of airfoil files used (-) + call ParseVar( FileInfo_In, CurLine, "NumAFfiles", InputFileData%NumAFfiles, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Allocate space to hold AFNames + ALLOCATE( InputFileData%AFNames(InputFileData%NumAFfiles), STAT=ErrStat2) + IF (ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, "Error allocating AFNames.", ErrStat, ErrMsg, RoutineName) + RETURN + END IF + ! AFNames - Airfoil file names (NumAFfiles lines) (quoted strings): -- NOTE: this line may not have a keyname with it + DO I = 1,InputFileData%NumAFfiles ! ParseChVar allows empty keynames. + call ParseVar( FileInfo_In, CurLine, "", InputFileData%AFNames(I), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%AFNames(I) ) ) InputFileData%AFNames(I) = TRIM(PriPath)//TRIM(InputFileData%AFNames(I)) + END DO + + !====== Rotor/Blade Properties ===================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! UseBlCm - Include aerodynamic pitching moment in calculations? (flag) + call ParseVar( FileInfo_In, CurLine, "UseBlCm", InputFileData%UseBlCm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Allocate space for AD blade file names -- MaxBl is usually set to 3, but if we specify more blades, this will work still. + call AllocAry( InputFileData%ADBlFile, max(MaxBl,NumBlades), 'ADBlFile', ErrStat2, ErrMsg2) + if (Failed()) return + do I =1,size(InputFileData%ADBlFile) ! We expect MaxBl blade file lines. We may want to revisit this idea later if we allow more thn 3 blades + call ParseVar( FileInfo_In, CurLine, "", InputFileData%ADBlFile(i), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%ADBlFile(I) ) ) InputFileData%ADBlFile(I) = TRIM(PriPath)//TRIM(InputFileData%ADBlFile(I)) + enddo + + !====== Tower Influence and Aerodynamics ============================================================= [used only when TwrPotent/=0, TwrShadow/=0, or TwrAero=True] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! NumTwrNds - Number of tower nodes used in the analysis (-) [used only when TwrPotent/=0, TwrShadow/=0, or TwrAero=True] + call ParseVar( FileInfo_In, CurLine, "NumTwrNds", InputFileData%NumTwrNds, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + !TwrElev TwrDiam TwrCd + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Tower Table Header: '//FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + !(m) (m) (-) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Tower Table Header: '//FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! Allocate space for tower table + CALL AllocAry( InputFileData%TwrElev, InputFileData%NumTwrNds, 'TwrElev', ErrStat2, ErrMsg2) + if (Failed()) return + CALL AllocAry( InputFileData%TwrDiam, InputFileData%NumTwrNds, 'TwrDiam', ErrStat2, ErrMsg2) + if (Failed()) return + CALL AllocAry( InputFileData%TwrCd, InputFileData%NumTwrNds, 'TwrCd', ErrStat2, ErrMsg2) + if (Failed()) return + CALL AllocAry( InputFileData%TwrTI, InputFileData%NumTwrNds, 'TwrTI', ErrStat2, ErrMsg2) + if (Failed()) return + + do I=1,InputFileData%NumTwrNds + call ParseAry ( FileInfo_In, CurLine, 'Properties for tower node '//trim( Int2LStr( I ) )//'.', TmpRe4, 4, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + InputFileData%TwrElev(I) = TmpRe4( 1) + InputFileData%TwrDiam(I) = TmpRe4( 2) + InputFileData%TwrCd(I) = TmpRe4( 3) + InputFileData%TwrTI(I) = TmpRe4( 4) + end do + + !====== Outputs ==================================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! SumPrint - Generate a summary file listing input options and interpolated properties to "<rootname>.AD.sum"? (flag) + call ParseVar( FileInfo_In, CurLine, "SumPrint", InputFileData%SumPrint, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + ! NBlOuts - Number of blade node outputs [0 - 9] (-) + call ParseVar( FileInfo_In, CurLine, "NBlOuts", InputFileData%NBlOuts, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Make sure we don't try to read in more than will fit in the pre-allocated BlOutNd array + if ( InputFileData%NBlOuts > SIZE(InputFileData%BlOutNd) ) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: number of blade output nodes exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%BlOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) + InputFileData%NBlOuts = SIZE(InputFileData%BlOutNd) + endif + ! BlOutNd - Blade nodes whose values will be output (-): + call ParseAry( FileInfo_In, CurLine, "BlOutNd", InputFileData%BlOutNd, InputFileData%NBlOuts, ErrStat2, ErrMsg2, UnEc) + + ! NTwOuts - Number of blade node outputs [0 - 9] (-) + call ParseVar( FileInfo_In, CurLine, "NTwOuts", InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Make sure we don't try to read in more than will fit in the pre-allocated TwOutNd array + if ( InputFileData%NTwOuts > SIZE(InputFileData%TwOutNd) ) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: number of blade output nodes exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%TwOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) + InputFileData%NTwOuts = SIZE(InputFileData%TwOutNd) + endif + ! TwOutNd - Tower nodes whose values will be output (-): + call ParseAry( FileInfo_In, CurLine, "TwOutNd", InputFileData%TwOutNd, InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc) + + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + call ReadOutputListFromFileInfo( FileInfo_In, CurLine, InputFileData%OutList, & + InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + + !====== Nodal Outputs ============================================================================== + ! In case there is something ill-formed in the additional nodal outputs section, we will simply ignore it. + ! Expecting at least 5 more lines in the input file for this section + if (FileInfo_In%NumLines < CurLine + 5) then + ErrStat2 = ErrID_Fatal + ErrMsg2 = '' + if (FailedNodal()) return; + endif + + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + + ! BldNd_BladesOut - Number of blades to output all node information at. Up to number of blades on turbine. (-) + ! TODO: In a future release, allow this to be an array of N blade numbers (change BldNd_BladesOut to an array if we do that). + ! Will likely require reading this line in as a string (BldNd_BladesOut_Str) and parsing it + call ParseVar( FileInfo_In, CurLine, "BldNd_BladesOut", InputFileData%BldNd_BladesOut, ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return + ! BldNd_BlOutNd - Future feature will allow selecting a portion of the nodes to output. Not implemented yet. (-) + ! TODO: Parse this string into an array of nodes to output at (one idea is to set an array of boolean to T/F for which nodes to output). At present, we ignore it entirely. + call ParseVar( FileInfo_In, CurLine, "BldNd_BlOutNd", InputFileData%BldNd_BlOutNd_Str, ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return + ! OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + + call ReadOutputListFromFileInfo( FileInfo_In, CurLine, InputFileData%BldNd_OutList, & + InputFileData%BldNd_NumOuts, 'BldNd_OutList', "List of user-requested output nodal channel groups", ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return; + + RETURN +CONTAINS + !------------------------------------------------------------------------------------------------- + logical function Failed() + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ParsePrimaryFileInfo' ) + Failed = ErrStat >= AbortErrLev + if (Failed) then + if (UnEc > -1_IntKi) CLOSE( UnEc ) + endif + end function Failed + logical function FailedNodal() + ErrMsg_NoAllBldNdOuts='AD15 Nodal Outputs: Nodal output section of AeroDyn input file not found or improperly formatted. Skipping nodal outputs.' + if (ErrStat2 >= AbortErrLev ) then + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + endif + FailedNodal = ErrStat2 >= AbortErrLev + end function FailedNodal + !------------------------------------------------------------------------------------------------- +END SUBROUTINE ParsePrimaryFileInfo +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, UnEc, ErrStat, ErrMsg ) +! This routine reads a blade input file. +!.................................................................................................................................. + + + ! Passed variables: + + TYPE(AD_BladePropsType), INTENT(INOUT) :: BladeKInputFileData ! Data for Blade K stored in the module's input file + CHARACTER(*), INTENT(IN) :: ADBlFile ! Name of the blade input file data + INTEGER(IntKi), INTENT(IN) :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + + ! Local variables: + + INTEGER(IntKi) :: I ! A generic DO index. + INTEGER( IntKi ) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 , IOS ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName = 'ReadBladeInputs' + + ErrStat = ErrID_None + ErrMsg = "" + UnIn = -1 + + ! Allocate space for these variables + + + + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! Open the input file for blade K. + + CALL OpenFInpFile ( UnIn, ADBlFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! -------------- HEADER ------------------------------------------------------- + + ! Skip the header. + + CALL ReadCom ( UnIn, ADBlFile, 'unused blade file header line 1', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom ( UnIn, ADBlFile, 'unused blade file header line 2', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! -------------- Blade properties table ------------------------------------------ + CALL ReadCom ( UnIn, ADBlFile, 'Section header: Blade Properties', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! NumBlNds - Number of blade nodes used in the analysis (-): + CALL ReadVar( UnIn, ADBlFile, BladeKInputFileData%NumBlNds, "NumBlNds", "Number of blade nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadCom ( UnIn, ADBlFile, 'Table header: names', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom ( UnIn, ADBlFile, 'Table header: units', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! allocate space for blade inputs: + CALL AllocAry( BladeKInputFileData%BlSpn, BladeKInputFileData%NumBlNds, 'BlSpn', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlCrvAC, BladeKInputFileData%NumBlNds, 'BlCrvAC', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlSwpAC, BladeKInputFileData%NumBlNds, 'BlSwpAC', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlCrvAng,BladeKInputFileData%NumBlNds, 'BlCrvAng',ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlTwist, BladeKInputFileData%NumBlNds, 'BlTwist', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlChord, BladeKInputFileData%NumBlNds, 'BlChord', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( BladeKInputFileData%BlAFID, BladeKInputFileData%NumBlNds, 'BlAFID', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Return on error if we didn't allocate space for the next inputs + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + DO I=1,BladeKInputFileData%NumBlNds + READ( UnIn, *, IOStat=IOS ) BladeKInputFileData%BlSpn(I), BladeKInputFileData%BlCrvAC(I), BladeKInputFileData%BlSwpAC(I), & + BladeKInputFileData%BlCrvAng(I), BladeKInputFileData%BlTwist(I), BladeKInputFileData%BlChord(I), & + BladeKInputFileData%BlAFID(I) + CALL CheckIOS( IOS, ADBlFile, 'Blade properties row '//TRIM(Num2LStr(I)), NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! Return on error if we couldn't read this line + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + IF (UnEc > 0) THEN + WRITE( UnEc, "(6(F9.4,1x),I9)", IOStat=IOS) BladeKInputFileData%BlSpn(I), BladeKInputFileData%BlCrvAC(I), BladeKInputFileData%BlSwpAC(I), & + BladeKInputFileData%BlCrvAng(I), BladeKInputFileData%BlTwist(I), BladeKInputFileData%BlChord(I), & + BladeKInputFileData%BlAFID(I) + END IF + END DO + BladeKInputFileData%BlCrvAng = BladeKInputFileData%BlCrvAng*D2R + BladeKInputFileData%BlTwist = BladeKInputFileData%BlTwist*D2R + + ! -------------- END OF FILE -------------------------------------------- + + CALL Cleanup() + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE Cleanup() + ! This subroutine cleans up local variables and closes files + !............................................................................................................................... + + IF (UnIn > 0) CLOSE(UnIn) + + END SUBROUTINE Cleanup + +END SUBROUTINE ReadBladeInputs +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AD_PrintSum( InputFileData, p, u, y, ErrStat, ErrMsg ) +! This routine generates the summary file, which contains a summary of input file options. + + ! passed variables + TYPE(AD_InputFile), INTENT(IN) :: InputFileData ! Input-file data + TYPE(AD_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD_InputType), INTENT(IN) :: u ! inputs + TYPE(AD_OutputType), INTENT(IN) :: y ! outputs + INTEGER(IntKi), INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMsg + + + ! Local variables. + + INTEGER(IntKi) :: I ! Index for the nodes. + INTEGER(IntKi) :: UnSu ! I/O unit number for the summary output file + + CHARACTER(*), PARAMETER :: FmtDat = '(A,T35,1(:,F13.3))' ! Format for outputting mass and modal data. + CHARACTER(*), PARAMETER :: FmtDatT = '(A,T35,1(:,F13.8))' ! Format for outputting time steps. + + CHARACTER(30) :: OutPFmt ! Format to print list of selected output channels to summary file + CHARACTER(100) :: Msg ! temporary string for writing appropriate text to summary file + + ! Open the summary file and give it a heading. + + CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) + CALL OpenFOutFile ( UnSu, TRIM( p%RootName )//'.sum', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Heading: + WRITE (UnSu,'(/,A)') 'This summary information was generated by '//TRIM( GetNVD(AD_Ver) )// & + ' on '//CurDate()//' at '//CurTime()//'.' + + WRITE (UnSu,'(/,A)') '====== General Options ============================================================================' + ! WakeMod + select case (p%WakeMod) + case (WakeMod_BEMT) + Msg = 'Blade-Element/Momentum Theory' + case (WakeMod_DBEMT) + Msg = 'Dynamic Blade-Element/Momentum Theory' + case (WakeMod_FVW) + Msg = 'Free Vortex Wake Theory' + case (WakeMod_None) + Msg = 'steady' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) p%WakeMod, 'WakeMod', 'Type of wake/induction model: '//TRIM(Msg) + + + ! AFAeroMod + select case (InputFileData%AFAeroMod) + case (AFAeroMod_BL_unsteady) + Msg = 'Beddoes-Leishman unsteady model' + case (AFAeroMod_steady) + Msg = 'steady' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) InputFileData%AFAeroMod, 'AFAeroMod', 'Type of blade airfoil aerodynamics model: '//TRIM(Msg) + + + ! TwrPotent + select case (p%TwrPotent) + case (TwrPotent_baseline) + Msg = 'baseline potential flow' + case (TwrPotent_Bak) + Msg = 'potential flow with Bak correction' + case (TwrPotent_none) + Msg = 'none' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) p%TwrPotent, 'TwrPotent', 'Type tower influence on wind based on potential flow around the tower: '//TRIM(Msg) + + + ! TwrShadow + select case (p%TwrShadow) + case (TwrShadow_Powles) + Msg = 'Powles tower shadow model' + case (TwrShadow_Eames) + Msg = 'Eames tower shadow model with TI values from the table' + case (TwrShadow_none) + Msg = 'none' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) p%TwrShadow, 'TwrShadow', 'Calculate tower influence on wind based on downstream tower shadow: '//TRIM(Msg) + + + ! TwrAero + if (p%TwrAero) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) p%TwrAero, 'TwrAero', 'Calculate tower aerodynamic loads? '//TRIM(Msg) + + + if (p%WakeMod/=WakeMod_none) then + WRITE (UnSu,'(A)') '====== Blade-Element/Momentum Theory Options ======================================================' + + ! SkewMod + select case (InputFileData%SkewMod) + case (SkewMod_Uncoupled) + Msg = 'uncoupled' + case (SkewMod_PittPeters) + Msg = 'Pitt/Peters' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) InputFileData%SkewMod, 'SkewMod', 'Type of skewed-wake correction model: '//TRIM(Msg) + + + ! TipLoss + if (InputFileData%TipLoss) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%TipLoss, 'TipLoss', "Use the Prandtl tip-loss model? "//TRIM(Msg) + + + ! HubLoss + if (InputFileData%HubLoss) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%HubLoss, 'HubLoss', "Use the Prandtl hub-loss model? "//TRIM(Msg) + + + ! TanInd + if (InputFileData%TanInd) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%TanInd, 'TanInd', "Include tangential induction in BEMT calculations? "//TRIM(Msg) + + + ! AIDrag + if (InputFileData%AIDrag) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%AIDrag, 'AIDrag', "Include the drag term in the axial-induction calculation? "//TRIM(Msg) + + ! TIDrag + if (InputFileData%TIDrag .and. InputFileData%TanInd) then + Msg = 'Yes' + else + Msg = 'No' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%AIDrag, 'AIDrag', "Include the drag term in the tangential-induction calculation? "//TRIM(Msg) + + ! IndToler + WRITE (UnSu,Ec_ReFrmt) InputFileData%IndToler, 'IndToler', "Convergence tolerance for BEM induction factors (radians)" + + ! MaxIter + + + if (p%WakeMod == WakeMod_DBEMT) then + select case (InputFileData%DBEMT_Mod) + case (DBEMT_tauConst) + Msg = 'constant tau1' + case (DBEMT_tauVaries) + Msg = 'time-dependent tau1' + case (DBEMT_cont_tauConst) + Msg = 'continuous formulation with constant tau1' + case default + Msg = 'unknown' + end select + + WRITE (UnSu,Ec_IntFrmt) InputFileData%DBEMT_Mod, 'DBEMT_Mod', 'Type of dynamic BEMT (DBEMT) model: '//TRIM(Msg) + + if (InputFileData%DBEMT_Mod==DBEMT_tauConst) & + WRITE (UnSu,Ec_ReFrmt) InputFileData%tau1_const, 'tau1_const', 'Time constant for DBEMT (s)' + + end if + + end if + + if (InputFileData%AFAeroMod==AFAeroMod_BL_unsteady) then + WRITE (UnSu,'(A)') '====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options =====================================' + + ! UAMod + select case (InputFileData%UAMod) + case (1) + Msg = 'baseline model (original)' + case (2) + Msg = "Gonzalez's variant (changes in Cn, Cc, and Cm)" + case (3) + Msg = 'Minnema/Pierce variant (changes in Cc and Cm)' + !case (4) + ! Msg = 'DYSTOOL' + case default + Msg = 'unknown' + end select + WRITE (UnSu,Ec_IntFrmt) InputFileData%UAMod, 'UAMod', 'Unsteady Aero Model: '//TRIM(Msg) + + + ! FLookup + if (InputFileData%FLookup) then + Msg = 'Yes' + else + Msg = 'No, use best-fit exponential equations instead' + end if + WRITE (UnSu,Ec_LgFrmt) InputFileData%FLookup, 'FLookup', "Use a lookup for f'? "//TRIM(Msg) + + end if + + WRITE (UnSu,'(A)') '====== Outputs ====================================================================================' + + OutPFmt = '( 49X, I11, 2X, I13 )' + + WRITE(UnSu,Ec_IntFrmt) p%NBlOuts,'NBlOuts','Number of blade nodes selected for output' + if (p%NBlOuts > 0) then + WRITE(UnSu,Ec_IntFrmt) p%NumBlNds,'NumBlNds','Number of blade nodes in the analysis' + + WRITE (UnSu,"(15x,A)") 'Blade nodes selected for output: Output node Analysis node' + WRITE (UnSu,"(15x,A)") ' ----------- -------------' + DO I = 1,p%NBlOuts + WRITE (UnSu,OutPFmt) I, p%BlOutNd(I) + END DO + end if + + WRITE(UnSu,Ec_IntFrmt) p%NTwOuts,'NTwOuts','Number of tower nodes selected for output' + if (p%NTwOuts > 0) then + WRITE(UnSu,Ec_IntFrmt) p%NumTwrNds,'NumTwrNds','Number of tower nodes in the analysis' + WRITE (UnSu,"(15x,A)") 'Tower nodes selected for output: Output node Analysis node' + WRITE (UnSu,"(15x,A)") ' ----------- -------------' + DO I = 1,p%NTwOuts + WRITE (UnSu,OutPFmt) I, p%TwOutNd(I) + END DO + end if + + + OutPFmt = '( 15x, I4, 2X, A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + WRITE (UnSu,'(15x,A)') 'Requested Output Channels:' + WRITE (UnSu,'(15x,A)') 'Col Parameter Units' + WRITE (UnSu,'(15x,A)') '---- -------------- -----' + + DO I = 0,p%NumOuts + WRITE (UnSu,OutPFmt) I, p%OutParam(I)%Name, p%OutParam(I)%Units + END DO + + WRITE (UnSu,'(15x,A)') + WRITE (UnSu,'(15x,A)') + WRITE (UnSu,'(15x,A)') 'Requested Output Channels at each blade station:' + WRITE (UnSu,'(15x,A)') 'Col Parameter Units' + WRITE (UnSu,'(15x,A)') '---- -------------- -----' + DO I = 1,p%BldNd_NumOuts + WRITE (UnSu,OutPFmt) I, p%BldNd_OutParam(I)%Name, p%BldNd_OutParam(I)%Units + END DO + + CLOSE(UnSu) + +RETURN +END SUBROUTINE AD_PrintSum +!---------------------------------------------------------------------------------------------------------------------------------- + + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 31-Aug-2020 13:14:21. +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + TYPE(AD_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 + + ! Local variables + + 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(1212) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "B1AZIMUTH","B1N1ALPHA","B1N1AXIND","B1N1CD ","B1N1CL ","B1N1CLRNC","B1N1CM ","B1N1CN ", & + "B1N1CPMIN","B1N1CT ","B1N1CURVE","B1N1CX ","B1N1CY ","B1N1DYNP ","B1N1FD ","B1N1FL ", & + "B1N1FN ","B1N1FT ","B1N1FX ","B1N1FY ","B1N1GAM ","B1N1M ","B1N1MM ","B1N1PHI ", & + "B1N1RE ","B1N1SGCAV","B1N1SIGCR","B1N1STVX ","B1N1STVY ","B1N1STVZ ","B1N1THETA","B1N1TNIND", & + "B1N1VDISX","B1N1VDISY","B1N1VDISZ","B1N1VINDX","B1N1VINDY","B1N1VREL ","B1N1VUNDX","B1N1VUNDY", & + "B1N1VUNDZ","B1N2ALPHA","B1N2AXIND","B1N2CD ","B1N2CL ","B1N2CLRNC","B1N2CM ","B1N2CN ", & + "B1N2CPMIN","B1N2CT ","B1N2CURVE","B1N2CX ","B1N2CY ","B1N2DYNP ","B1N2FD ","B1N2FL ", & + "B1N2FN ","B1N2FT ","B1N2FX ","B1N2FY ","B1N2GAM ","B1N2M ","B1N2MM ","B1N2PHI ", & + "B1N2RE ","B1N2SGCAV","B1N2SIGCR","B1N2STVX ","B1N2STVY ","B1N2STVZ ","B1N2THETA","B1N2TNIND", & + "B1N2VDISX","B1N2VDISY","B1N2VDISZ","B1N2VINDX","B1N2VINDY","B1N2VREL ","B1N2VUNDX","B1N2VUNDY", & + "B1N2VUNDZ","B1N3ALPHA","B1N3AXIND","B1N3CD ","B1N3CL ","B1N3CLRNC","B1N3CM ","B1N3CN ", & + "B1N3CPMIN","B1N3CT ","B1N3CURVE","B1N3CX ","B1N3CY ","B1N3DYNP ","B1N3FD ","B1N3FL ", & + "B1N3FN ","B1N3FT ","B1N3FX ","B1N3FY ","B1N3GAM ","B1N3M ","B1N3MM ","B1N3PHI ", & + "B1N3RE ","B1N3SGCAV","B1N3SIGCR","B1N3STVX ","B1N3STVY ","B1N3STVZ ","B1N3THETA","B1N3TNIND", & + "B1N3VDISX","B1N3VDISY","B1N3VDISZ","B1N3VINDX","B1N3VINDY","B1N3VREL ","B1N3VUNDX","B1N3VUNDY", & + "B1N3VUNDZ","B1N4ALPHA","B1N4AXIND","B1N4CD ","B1N4CL ","B1N4CLRNC","B1N4CM ","B1N4CN ", & + "B1N4CPMIN","B1N4CT ","B1N4CURVE","B1N4CX ","B1N4CY ","B1N4DYNP ","B1N4FD ","B1N4FL ", & + "B1N4FN ","B1N4FT ","B1N4FX ","B1N4FY ","B1N4GAM ","B1N4M ","B1N4MM ","B1N4PHI ", & + "B1N4RE ","B1N4SGCAV","B1N4SIGCR","B1N4STVX ","B1N4STVY ","B1N4STVZ ","B1N4THETA","B1N4TNIND", & + "B1N4VDISX","B1N4VDISY","B1N4VDISZ","B1N4VINDX","B1N4VINDY","B1N4VREL ","B1N4VUNDX","B1N4VUNDY", & + "B1N4VUNDZ","B1N5ALPHA","B1N5AXIND","B1N5CD ","B1N5CL ","B1N5CLRNC","B1N5CM ","B1N5CN ", & + "B1N5CPMIN","B1N5CT ","B1N5CURVE","B1N5CX ","B1N5CY ","B1N5DYNP ","B1N5FD ","B1N5FL ", & + "B1N5FN ","B1N5FT ","B1N5FX ","B1N5FY ","B1N5GAM ","B1N5M ","B1N5MM ","B1N5PHI ", & + "B1N5RE ","B1N5SGCAV","B1N5SIGCR","B1N5STVX ","B1N5STVY ","B1N5STVZ ","B1N5THETA","B1N5TNIND", & + "B1N5VDISX","B1N5VDISY","B1N5VDISZ","B1N5VINDX","B1N5VINDY","B1N5VREL ","B1N5VUNDX","B1N5VUNDY", & + "B1N5VUNDZ","B1N6ALPHA","B1N6AXIND","B1N6CD ","B1N6CL ","B1N6CLRNC","B1N6CM ","B1N6CN ", & + "B1N6CPMIN","B1N6CT ","B1N6CURVE","B1N6CX ","B1N6CY ","B1N6DYNP ","B1N6FD ","B1N6FL ", & + "B1N6FN ","B1N6FT ","B1N6FX ","B1N6FY ","B1N6GAM ","B1N6M ","B1N6MM ","B1N6PHI ", & + "B1N6RE ","B1N6SGCAV","B1N6SIGCR","B1N6STVX ","B1N6STVY ","B1N6STVZ ","B1N6THETA","B1N6TNIND", & + "B1N6VDISX","B1N6VDISY","B1N6VDISZ","B1N6VINDX","B1N6VINDY","B1N6VREL ","B1N6VUNDX","B1N6VUNDY", & + "B1N6VUNDZ","B1N7ALPHA","B1N7AXIND","B1N7CD ","B1N7CL ","B1N7CLRNC","B1N7CM ","B1N7CN ", & + "B1N7CPMIN","B1N7CT ","B1N7CURVE","B1N7CX ","B1N7CY ","B1N7DYNP ","B1N7FD ","B1N7FL ", & + "B1N7FN ","B1N7FT ","B1N7FX ","B1N7FY ","B1N7GAM ","B1N7M ","B1N7MM ","B1N7PHI ", & + "B1N7RE ","B1N7SGCAV","B1N7SIGCR","B1N7STVX ","B1N7STVY ","B1N7STVZ ","B1N7THETA","B1N7TNIND", & + "B1N7VDISX","B1N7VDISY","B1N7VDISZ","B1N7VINDX","B1N7VINDY","B1N7VREL ","B1N7VUNDX","B1N7VUNDY", & + "B1N7VUNDZ","B1N8ALPHA","B1N8AXIND","B1N8CD ","B1N8CL ","B1N8CLRNC","B1N8CM ","B1N8CN ", & + "B1N8CPMIN","B1N8CT ","B1N8CURVE","B1N8CX ","B1N8CY ","B1N8DYNP ","B1N8FD ","B1N8FL ", & + "B1N8FN ","B1N8FT ","B1N8FX ","B1N8FY ","B1N8GAM ","B1N8M ","B1N8MM ","B1N8PHI ", & + "B1N8RE ","B1N8SGCAV","B1N8SIGCR","B1N8STVX ","B1N8STVY ","B1N8STVZ ","B1N8THETA","B1N8TNIND", & + "B1N8VDISX","B1N8VDISY","B1N8VDISZ","B1N8VINDX","B1N8VINDY","B1N8VREL ","B1N8VUNDX","B1N8VUNDY", & + "B1N8VUNDZ","B1N9ALPHA","B1N9AXIND","B1N9CD ","B1N9CL ","B1N9CLRNC","B1N9CM ","B1N9CN ", & + "B1N9CPMIN","B1N9CT ","B1N9CURVE","B1N9CX ","B1N9CY ","B1N9DYNP ","B1N9FD ","B1N9FL ", & + "B1N9FN ","B1N9FT ","B1N9FX ","B1N9FY ","B1N9GAM ","B1N9M ","B1N9MM ","B1N9PHI ", & + "B1N9RE ","B1N9SGCAV","B1N9SIGCR","B1N9STVX ","B1N9STVY ","B1N9STVZ ","B1N9THETA","B1N9TNIND", & + "B1N9VDISX","B1N9VDISY","B1N9VDISZ","B1N9VINDX","B1N9VINDY","B1N9VREL ","B1N9VUNDX","B1N9VUNDY", & + "B1N9VUNDZ","B1PITCH ","B2AZIMUTH","B2N1ALPHA","B2N1AXIND","B2N1CD ","B2N1CL ","B2N1CLRNC", & + "B2N1CM ","B2N1CN ","B2N1CPMIN","B2N1CT ","B2N1CURVE","B2N1CX ","B2N1CY ","B2N1DYNP ", & + "B2N1FD ","B2N1FL ","B2N1FN ","B2N1FT ","B2N1FX ","B2N1FY ","B2N1GAM ","B2N1M ", & + "B2N1MM ","B2N1PHI ","B2N1RE ","B2N1SGCAV","B2N1SIGCR","B2N1STVX ","B2N1STVY ","B2N1STVZ ", & + "B2N1THETA","B2N1TNIND","B2N1VDISX","B2N1VDISY","B2N1VDISZ","B2N1VINDX","B2N1VINDY","B2N1VREL ", & + "B2N1VUNDX","B2N1VUNDY","B2N1VUNDZ","B2N2ALPHA","B2N2AXIND","B2N2CD ","B2N2CL ","B2N2CLRNC", & + "B2N2CM ","B2N2CN ","B2N2CPMIN","B2N2CT ","B2N2CURVE","B2N2CX ","B2N2CY ","B2N2DYNP ", & + "B2N2FD ","B2N2FL ","B2N2FN ","B2N2FT ","B2N2FX ","B2N2FY ","B2N2GAM ","B2N2M ", & + "B2N2MM ","B2N2PHI ","B2N2RE ","B2N2SGCAV","B2N2SIGCR","B2N2STVX ","B2N2STVY ","B2N2STVZ ", & + "B2N2THETA","B2N2TNIND","B2N2VDISX","B2N2VDISY","B2N2VDISZ","B2N2VINDX","B2N2VINDY","B2N2VREL ", & + "B2N2VUNDX","B2N2VUNDY","B2N2VUNDZ","B2N3ALPHA","B2N3AXIND","B2N3CD ","B2N3CL ","B2N3CLRNC", & + "B2N3CM ","B2N3CN ","B2N3CPMIN","B2N3CT ","B2N3CURVE","B2N3CX ","B2N3CY ","B2N3DYNP ", & + "B2N3FD ","B2N3FL ","B2N3FN ","B2N3FT ","B2N3FX ","B2N3FY ","B2N3GAM ","B2N3M ", & + "B2N3MM ","B2N3PHI ","B2N3RE ","B2N3SGCAV","B2N3SIGCR","B2N3STVX ","B2N3STVY ","B2N3STVZ ", & + "B2N3THETA","B2N3TNIND","B2N3VDISX","B2N3VDISY","B2N3VDISZ","B2N3VINDX","B2N3VINDY","B2N3VREL ", & + "B2N3VUNDX","B2N3VUNDY","B2N3VUNDZ","B2N4ALPHA","B2N4AXIND","B2N4CD ","B2N4CL ","B2N4CLRNC", & + "B2N4CM ","B2N4CN ","B2N4CPMIN","B2N4CT ","B2N4CURVE","B2N4CX ","B2N4CY ","B2N4DYNP ", & + "B2N4FD ","B2N4FL ","B2N4FN ","B2N4FT ","B2N4FX ","B2N4FY ","B2N4GAM ","B2N4M ", & + "B2N4MM ","B2N4PHI ","B2N4RE ","B2N4SGCAV","B2N4SIGCR","B2N4STVX ","B2N4STVY ","B2N4STVZ ", & + "B2N4THETA","B2N4TNIND","B2N4VDISX","B2N4VDISY","B2N4VDISZ","B2N4VINDX","B2N4VINDY","B2N4VREL ", & + "B2N4VUNDX","B2N4VUNDY","B2N4VUNDZ","B2N5ALPHA","B2N5AXIND","B2N5CD ","B2N5CL ","B2N5CLRNC", & + "B2N5CM ","B2N5CN ","B2N5CPMIN","B2N5CT ","B2N5CURVE","B2N5CX ","B2N5CY ","B2N5DYNP ", & + "B2N5FD ","B2N5FL ","B2N5FN ","B2N5FT ","B2N5FX ","B2N5FY ","B2N5GAM ","B2N5M ", & + "B2N5MM ","B2N5PHI ","B2N5RE ","B2N5SGCAV","B2N5SIGCR","B2N5STVX ","B2N5STVY ","B2N5STVZ ", & + "B2N5THETA","B2N5TNIND","B2N5VDISX","B2N5VDISY","B2N5VDISZ","B2N5VINDX","B2N5VINDY","B2N5VREL ", & + "B2N5VUNDX","B2N5VUNDY","B2N5VUNDZ","B2N6ALPHA","B2N6AXIND","B2N6CD ","B2N6CL ","B2N6CLRNC", & + "B2N6CM ","B2N6CN ","B2N6CPMIN","B2N6CT ","B2N6CURVE","B2N6CX ","B2N6CY ","B2N6DYNP ", & + "B2N6FD ","B2N6FL ","B2N6FN ","B2N6FT ","B2N6FX ","B2N6FY ","B2N6GAM ","B2N6M ", & + "B2N6MM ","B2N6PHI ","B2N6RE ","B2N6SGCAV","B2N6SIGCR","B2N6STVX ","B2N6STVY ","B2N6STVZ ", & + "B2N6THETA","B2N6TNIND","B2N6VDISX","B2N6VDISY","B2N6VDISZ","B2N6VINDX","B2N6VINDY","B2N6VREL ", & + "B2N6VUNDX","B2N6VUNDY","B2N6VUNDZ","B2N7ALPHA","B2N7AXIND","B2N7CD ","B2N7CL ","B2N7CLRNC", & + "B2N7CM ","B2N7CN ","B2N7CPMIN","B2N7CT ","B2N7CURVE","B2N7CX ","B2N7CY ","B2N7DYNP ", & + "B2N7FD ","B2N7FL ","B2N7FN ","B2N7FT ","B2N7FX ","B2N7FY ","B2N7GAM ","B2N7M ", & + "B2N7MM ","B2N7PHI ","B2N7RE ","B2N7SGCAV","B2N7SIGCR","B2N7STVX ","B2N7STVY ","B2N7STVZ ", & + "B2N7THETA","B2N7TNIND","B2N7VDISX","B2N7VDISY","B2N7VDISZ","B2N7VINDX","B2N7VINDY","B2N7VREL ", & + "B2N7VUNDX","B2N7VUNDY","B2N7VUNDZ","B2N8ALPHA","B2N8AXIND","B2N8CD ","B2N8CL ","B2N8CLRNC", & + "B2N8CM ","B2N8CN ","B2N8CPMIN","B2N8CT ","B2N8CURVE","B2N8CX ","B2N8CY ","B2N8DYNP ", & + "B2N8FD ","B2N8FL ","B2N8FN ","B2N8FT ","B2N8FX ","B2N8FY ","B2N8GAM ","B2N8M ", & + "B2N8MM ","B2N8PHI ","B2N8RE ","B2N8SGCAV","B2N8SIGCR","B2N8STVX ","B2N8STVY ","B2N8STVZ ", & + "B2N8THETA","B2N8TNIND","B2N8VDISX","B2N8VDISY","B2N8VDISZ","B2N8VINDX","B2N8VINDY","B2N8VREL ", & + "B2N8VUNDX","B2N8VUNDY","B2N8VUNDZ","B2N9ALPHA","B2N9AXIND","B2N9CD ","B2N9CL ","B2N9CLRNC", & + "B2N9CM ","B2N9CN ","B2N9CPMIN","B2N9CT ","B2N9CURVE","B2N9CX ","B2N9CY ","B2N9DYNP ", & + "B2N9FD ","B2N9FL ","B2N9FN ","B2N9FT ","B2N9FX ","B2N9FY ","B2N9GAM ","B2N9M ", & + "B2N9MM ","B2N9PHI ","B2N9RE ","B2N9SGCAV","B2N9SIGCR","B2N9STVX ","B2N9STVY ","B2N9STVZ ", & + "B2N9THETA","B2N9TNIND","B2N9VDISX","B2N9VDISY","B2N9VDISZ","B2N9VINDX","B2N9VINDY","B2N9VREL ", & + "B2N9VUNDX","B2N9VUNDY","B2N9VUNDZ","B2PITCH ","B3AZIMUTH","B3N1ALPHA","B3N1AXIND","B3N1CD ", & + "B3N1CL ","B3N1CLRNC","B3N1CM ","B3N1CN ","B3N1CPMIN","B3N1CT ","B3N1CURVE","B3N1CX ", & + "B3N1CY ","B3N1DYNP ","B3N1FD ","B3N1FL ","B3N1FN ","B3N1FT ","B3N1FX ","B3N1FY ", & + "B3N1GAM ","B3N1M ","B3N1MM ","B3N1PHI ","B3N1RE ","B3N1SGCAV","B3N1SIGCR","B3N1STVX ", & + "B3N1STVY ","B3N1STVZ ","B3N1THETA","B3N1TNIND","B3N1VDISX","B3N1VDISY","B3N1VDISZ","B3N1VINDX", & + "B3N1VINDY","B3N1VREL ","B3N1VUNDX","B3N1VUNDY","B3N1VUNDZ","B3N2ALPHA","B3N2AXIND","B3N2CD ", & + "B3N2CL ","B3N2CLRNC","B3N2CM ","B3N2CN ","B3N2CPMIN","B3N2CT ","B3N2CURVE","B3N2CX ", & + "B3N2CY ","B3N2DYNP ","B3N2FD ","B3N2FL ","B3N2FN ","B3N2FT ","B3N2FX ","B3N2FY ", & + "B3N2GAM ","B3N2M ","B3N2MM ","B3N2PHI ","B3N2RE ","B3N2SGCAV","B3N2SIGCR","B3N2STVX ", & + "B3N2STVY ","B3N2STVZ ","B3N2THETA","B3N2TNIND","B3N2VDISX","B3N2VDISY","B3N2VDISZ","B3N2VINDX", & + "B3N2VINDY","B3N2VREL ","B3N2VUNDX","B3N2VUNDY","B3N2VUNDZ","B3N3ALPHA","B3N3AXIND","B3N3CD ", & + "B3N3CL ","B3N3CLRNC","B3N3CM ","B3N3CN ","B3N3CPMIN","B3N3CT ","B3N3CURVE","B3N3CX ", & + "B3N3CY ","B3N3DYNP ","B3N3FD ","B3N3FL ","B3N3FN ","B3N3FT ","B3N3FX ","B3N3FY ", & + "B3N3GAM ","B3N3M ","B3N3MM ","B3N3PHI ","B3N3RE ","B3N3SGCAV","B3N3SIGCR","B3N3STVX ", & + "B3N3STVY ","B3N3STVZ ","B3N3THETA","B3N3TNIND","B3N3VDISX","B3N3VDISY","B3N3VDISZ","B3N3VINDX", & + "B3N3VINDY","B3N3VREL ","B3N3VUNDX","B3N3VUNDY","B3N3VUNDZ","B3N4ALPHA","B3N4AXIND","B3N4CD ", & + "B3N4CL ","B3N4CLRNC","B3N4CM ","B3N4CN ","B3N4CPMIN","B3N4CT ","B3N4CURVE","B3N4CX ", & + "B3N4CY ","B3N4DYNP ","B3N4FD ","B3N4FL ","B3N4FN ","B3N4FT ","B3N4FX ","B3N4FY ", & + "B3N4GAM ","B3N4M ","B3N4MM ","B3N4PHI ","B3N4RE ","B3N4SGCAV","B3N4SIGCR","B3N4STVX ", & + "B3N4STVY ","B3N4STVZ ","B3N4THETA","B3N4TNIND","B3N4VDISX","B3N4VDISY","B3N4VDISZ","B3N4VINDX", & + "B3N4VINDY","B3N4VREL ","B3N4VUNDX","B3N4VUNDY","B3N4VUNDZ","B3N5ALPHA","B3N5AXIND","B3N5CD ", & + "B3N5CL ","B3N5CLRNC","B3N5CM ","B3N5CN ","B3N5CPMIN","B3N5CT ","B3N5CURVE","B3N5CX ", & + "B3N5CY ","B3N5DYNP ","B3N5FD ","B3N5FL ","B3N5FN ","B3N5FT ","B3N5FX ","B3N5FY ", & + "B3N5GAM ","B3N5M ","B3N5MM ","B3N5PHI ","B3N5RE ","B3N5SGCAV","B3N5SIGCR","B3N5STVX ", & + "B3N5STVY ","B3N5STVZ ","B3N5THETA","B3N5TNIND","B3N5VDISX","B3N5VDISY","B3N5VDISZ","B3N5VINDX", & + "B3N5VINDY","B3N5VREL ","B3N5VUNDX","B3N5VUNDY","B3N5VUNDZ","B3N6ALPHA","B3N6AXIND","B3N6CD ", & + "B3N6CL ","B3N6CLRNC","B3N6CM ","B3N6CN ","B3N6CPMIN","B3N6CT ","B3N6CURVE","B3N6CX ", & + "B3N6CY ","B3N6DYNP ","B3N6FD ","B3N6FL ","B3N6FN ","B3N6FT ","B3N6FX ","B3N6FY ", & + "B3N6GAM ","B3N6M ","B3N6MM ","B3N6PHI ","B3N6RE ","B3N6SGCAV","B3N6SIGCR","B3N6STVX ", & + "B3N6STVY ","B3N6STVZ ","B3N6THETA","B3N6TNIND","B3N6VDISX","B3N6VDISY","B3N6VDISZ","B3N6VINDX", & + "B3N6VINDY","B3N6VREL ","B3N6VUNDX","B3N6VUNDY","B3N6VUNDZ","B3N7ALPHA","B3N7AXIND","B3N7CD ", & + "B3N7CL ","B3N7CLRNC","B3N7CM ","B3N7CN ","B3N7CPMIN","B3N7CT ","B3N7CURVE","B3N7CX ", & + "B3N7CY ","B3N7DYNP ","B3N7FD ","B3N7FL ","B3N7FN ","B3N7FT ","B3N7FX ","B3N7FY ", & + "B3N7GAM ","B3N7M ","B3N7MM ","B3N7PHI ","B3N7RE ","B3N7SGCAV","B3N7SIGCR","B3N7STVX ", & + "B3N7STVY ","B3N7STVZ ","B3N7THETA","B3N7TNIND","B3N7VDISX","B3N7VDISY","B3N7VDISZ","B3N7VINDX", & + "B3N7VINDY","B3N7VREL ","B3N7VUNDX","B3N7VUNDY","B3N7VUNDZ","B3N8ALPHA","B3N8AXIND","B3N8CD ", & + "B3N8CL ","B3N8CLRNC","B3N8CM ","B3N8CN ","B3N8CPMIN","B3N8CT ","B3N8CURVE","B3N8CX ", & + "B3N8CY ","B3N8DYNP ","B3N8FD ","B3N8FL ","B3N8FN ","B3N8FT ","B3N8FX ","B3N8FY ", & + "B3N8GAM ","B3N8M ","B3N8MM ","B3N8PHI ","B3N8RE ","B3N8SGCAV","B3N8SIGCR","B3N8STVX ", & + "B3N8STVY ","B3N8STVZ ","B3N8THETA","B3N8TNIND","B3N8VDISX","B3N8VDISY","B3N8VDISZ","B3N8VINDX", & + "B3N8VINDY","B3N8VREL ","B3N8VUNDX","B3N8VUNDY","B3N8VUNDZ","B3N9ALPHA","B3N9AXIND","B3N9CD ", & + "B3N9CL ","B3N9CLRNC","B3N9CM ","B3N9CN ","B3N9CPMIN","B3N9CT ","B3N9CURVE","B3N9CX ", & + "B3N9CY ","B3N9DYNP ","B3N9FD ","B3N9FL ","B3N9FN ","B3N9FT ","B3N9FX ","B3N9FY ", & + "B3N9GAM ","B3N9M ","B3N9MM ","B3N9PHI ","B3N9RE ","B3N9SGCAV","B3N9SIGCR","B3N9STVX ", & + "B3N9STVY ","B3N9STVZ ","B3N9THETA","B3N9TNIND","B3N9VDISX","B3N9VDISY","B3N9VDISZ","B3N9VINDX", & + "B3N9VINDY","B3N9VREL ","B3N9VUNDX","B3N9VUNDY","B3N9VUNDZ","B3PITCH ","DBEMTAU1 ","RTAEROCP ", & + "RTAEROCQ ","RTAEROCT ","RTAEROFXH","RTAEROFYH","RTAEROFZH","RTAEROMXH","RTAEROMYH","RTAEROMZH", & + "RTAEROPWR","RTAREA ","RTSKEW ","RTSPEED ","RTTSR ","RTVAVGXH ","RTVAVGYH ","RTVAVGZH ", & + "TWN1DYNP ","TWN1FDX ","TWN1FDY ","TWN1M ","TWN1RE ","TWN1STVX ","TWN1STVY ","TWN1STVZ ", & + "TWN1VREL ","TWN1VUNDX","TWN1VUNDY","TWN1VUNDZ","TWN2DYNP ","TWN2FDX ","TWN2FDY ","TWN2M ", & + "TWN2RE ","TWN2STVX ","TWN2STVY ","TWN2STVZ ","TWN2VREL ","TWN2VUNDX","TWN2VUNDY","TWN2VUNDZ", & + "TWN3DYNP ","TWN3FDX ","TWN3FDY ","TWN3M ","TWN3RE ","TWN3STVX ","TWN3STVY ","TWN3STVZ ", & + "TWN3VREL ","TWN3VUNDX","TWN3VUNDY","TWN3VUNDZ","TWN4DYNP ","TWN4FDX ","TWN4FDY ","TWN4M ", & + "TWN4RE ","TWN4STVX ","TWN4STVY ","TWN4STVZ ","TWN4VREL ","TWN4VUNDX","TWN4VUNDY","TWN4VUNDZ", & + "TWN5DYNP ","TWN5FDX ","TWN5FDY ","TWN5M ","TWN5RE ","TWN5STVX ","TWN5STVY ","TWN5STVZ ", & + "TWN5VREL ","TWN5VUNDX","TWN5VUNDY","TWN5VUNDZ","TWN6DYNP ","TWN6FDX ","TWN6FDY ","TWN6M ", & + "TWN6RE ","TWN6STVX ","TWN6STVY ","TWN6STVZ ","TWN6VREL ","TWN6VUNDX","TWN6VUNDY","TWN6VUNDZ", & + "TWN7DYNP ","TWN7FDX ","TWN7FDY ","TWN7M ","TWN7RE ","TWN7STVX ","TWN7STVY ","TWN7STVZ ", & + "TWN7VREL ","TWN7VUNDX","TWN7VUNDY","TWN7VUNDZ","TWN8DYNP ","TWN8FDX ","TWN8FDY ","TWN8M ", & + "TWN8RE ","TWN8STVX ","TWN8STVY ","TWN8STVZ ","TWN8VREL ","TWN8VUNDX","TWN8VUNDY","TWN8VUNDZ", & + "TWN9DYNP ","TWN9FDX ","TWN9FDY ","TWN9M ","TWN9RE ","TWN9STVX ","TWN9STVY ","TWN9STVZ ", & + "TWN9VREL ","TWN9VUNDX","TWN9VUNDY","TWN9VUNDZ"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(1212) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + B1Azimuth , B1N1Alpha , B1N1AxInd , B1N1Cd , B1N1Cl , B1N1Clrnc , B1N1Cm , B1N1Cn , & + B1N1Cpmin , B1N1Ct , B1N1Curve , B1N1Cx , B1N1Cy , B1N1DynP , B1N1Fd , B1N1Fl , & + B1N1Fn , B1N1Ft , B1N1Fx , B1N1Fy , B1N1Gam , B1N1M , B1N1Mm , B1N1Phi , & + B1N1Re , B1N1SgCav , B1N1SigCr , B1N1STVx , B1N1STVy , B1N1STVz , B1N1Theta , B1N1TnInd , & + B1N1VDisx , B1N1VDisy , B1N1VDisz , B1N1Vindx , B1N1Vindy , B1N1VRel , B1N1VUndx , B1N1VUndy , & + B1N1VUndz , B1N2Alpha , B1N2AxInd , B1N2Cd , B1N2Cl , B1N2Clrnc , B1N2Cm , B1N2Cn , & + B1N2Cpmin , B1N2Ct , B1N2Curve , B1N2Cx , B1N2Cy , B1N2DynP , B1N2Fd , B1N2Fl , & + B1N2Fn , B1N2Ft , B1N2Fx , B1N2Fy , B1N2Gam , B1N2M , B1N2Mm , B1N2Phi , & + B1N2Re , B1N2SgCav , B1N2SigCr , B1N2STVx , B1N2STVy , B1N2STVz , B1N2Theta , B1N2TnInd , & + B1N2VDisx , B1N2VDisy , B1N2VDisz , B1N2Vindx , B1N2Vindy , B1N2VRel , B1N2VUndx , B1N2VUndy , & + B1N2VUndz , B1N3Alpha , B1N3AxInd , B1N3Cd , B1N3Cl , B1N3Clrnc , B1N3Cm , B1N3Cn , & + B1N3Cpmin , B1N3Ct , B1N3Curve , B1N3Cx , B1N3Cy , B1N3DynP , B1N3Fd , B1N3Fl , & + B1N3Fn , B1N3Ft , B1N3Fx , B1N3Fy , B1N3Gam , B1N3M , B1N3Mm , B1N3Phi , & + B1N3Re , B1N3SgCav , B1N3SigCr , B1N3STVx , B1N3STVy , B1N3STVz , B1N3Theta , B1N3TnInd , & + B1N3VDisx , B1N3VDisy , B1N3VDisz , B1N3Vindx , B1N3Vindy , B1N3VRel , B1N3VUndx , B1N3VUndy , & + B1N3VUndz , B1N4Alpha , B1N4AxInd , B1N4Cd , B1N4Cl , B1N4Clrnc , B1N4Cm , B1N4Cn , & + B1N4Cpmin , B1N4Ct , B1N4Curve , B1N4Cx , B1N4Cy , B1N4DynP , B1N4Fd , B1N4Fl , & + B1N4Fn , B1N4Ft , B1N4Fx , B1N4Fy , B1N4Gam , B1N4M , B1N4Mm , B1N4Phi , & + B1N4Re , B1N4SgCav , B1N4SigCr , B1N4STVx , B1N4STVy , B1N4STVz , B1N4Theta , B1N4TnInd , & + B1N4VDisx , B1N4VDisy , B1N4VDisz , B1N4Vindx , B1N4Vindy , B1N4VRel , B1N4VUndx , B1N4VUndy , & + B1N4VUndz , B1N5Alpha , B1N5AxInd , B1N5Cd , B1N5Cl , B1N5Clrnc , B1N5Cm , B1N5Cn , & + B1N5Cpmin , B1N5Ct , B1N5Curve , B1N5Cx , B1N5Cy , B1N5DynP , B1N5Fd , B1N5Fl , & + B1N5Fn , B1N5Ft , B1N5Fx , B1N5Fy , B1N5Gam , B1N5M , B1N5Mm , B1N5Phi , & + B1N5Re , B1N5SgCav , B1N5SigCr , B1N5STVx , B1N5STVy , B1N5STVz , B1N5Theta , B1N5TnInd , & + B1N5VDisx , B1N5VDisy , B1N5VDisz , B1N5Vindx , B1N5Vindy , B1N5VRel , B1N5VUndx , B1N5VUndy , & + B1N5VUndz , B1N6Alpha , B1N6AxInd , B1N6Cd , B1N6Cl , B1N6Clrnc , B1N6Cm , B1N6Cn , & + B1N6Cpmin , B1N6Ct , B1N6Curve , B1N6Cx , B1N6Cy , B1N6DynP , B1N6Fd , B1N6Fl , & + B1N6Fn , B1N6Ft , B1N6Fx , B1N6Fy , B1N6Gam , B1N6M , B1N6Mm , B1N6Phi , & + B1N6Re , B1N6SgCav , B1N6SigCr , B1N6STVx , B1N6STVy , B1N6STVz , B1N6Theta , B1N6TnInd , & + B1N6VDisx , B1N6VDisy , B1N6VDisz , B1N6Vindx , B1N6Vindy , B1N6VRel , B1N6VUndx , B1N6VUndy , & + B1N6VUndz , B1N7Alpha , B1N7AxInd , B1N7Cd , B1N7Cl , B1N7Clrnc , B1N7Cm , B1N7Cn , & + B1N7Cpmin , B1N7Ct , B1N7Curve , B1N7Cx , B1N7Cy , B1N7DynP , B1N7Fd , B1N7Fl , & + B1N7Fn , B1N7Ft , B1N7Fx , B1N7Fy , B1N7Gam , B1N7M , B1N7Mm , B1N7Phi , & + B1N7Re , B1N7SgCav , B1N7SigCr , B1N7STVx , B1N7STVy , B1N7STVz , B1N7Theta , B1N7TnInd , & + B1N7VDisx , B1N7VDisy , B1N7VDisz , B1N7Vindx , B1N7Vindy , B1N7VRel , B1N7VUndx , B1N7VUndy , & + B1N7VUndz , B1N8Alpha , B1N8AxInd , B1N8Cd , B1N8Cl , B1N8Clrnc , B1N8Cm , B1N8Cn , & + B1N8Cpmin , B1N8Ct , B1N8Curve , B1N8Cx , B1N8Cy , B1N8DynP , B1N8Fd , B1N8Fl , & + B1N8Fn , B1N8Ft , B1N8Fx , B1N8Fy , B1N8Gam , B1N8M , B1N8Mm , B1N8Phi , & + B1N8Re , B1N8SgCav , B1N8SigCr , B1N8STVx , B1N8STVy , B1N8STVz , B1N8Theta , B1N8TnInd , & + B1N8VDisx , B1N8VDisy , B1N8VDisz , B1N8Vindx , B1N8Vindy , B1N8VRel , B1N8VUndx , B1N8VUndy , & + B1N8VUndz , B1N9Alpha , B1N9AxInd , B1N9Cd , B1N9Cl , B1N9Clrnc , B1N9Cm , B1N9Cn , & + B1N9Cpmin , B1N9Ct , B1N9Curve , B1N9Cx , B1N9Cy , B1N9DynP , B1N9Fd , B1N9Fl , & + B1N9Fn , B1N9Ft , B1N9Fx , B1N9Fy , B1N9Gam , B1N9M , B1N9Mm , B1N9Phi , & + B1N9Re , B1N9SgCav , B1N9SigCr , B1N9STVx , B1N9STVy , B1N9STVz , B1N9Theta , B1N9TnInd , & + B1N9VDisx , B1N9VDisy , B1N9VDisz , B1N9Vindx , B1N9Vindy , B1N9VRel , B1N9VUndx , B1N9VUndy , & + B1N9VUndz , B1Pitch , B2Azimuth , B2N1Alpha , B2N1AxInd , B2N1Cd , B2N1Cl , B2N1Clrnc , & + B2N1Cm , B2N1Cn , B2N1Cpmin , B2N1Ct , B2N1Curve , B2N1Cx , B2N1Cy , B2N1DynP , & + B2N1Fd , B2N1Fl , B2N1Fn , B2N1Ft , B2N1Fx , B2N1Fy , B2N1Gam , B2N1M , & + B2N1Mm , B2N1Phi , B2N1Re , B2N1SgCav , B2N1SigCr , B2N1STVx , B2N1STVy , B2N1STVz , & + B2N1Theta , B2N1TnInd , B2N1VDisx , B2N1VDisy , B2N1VDisz , B2N1Vindx , B2N1Vindy , B2N1VRel , & + B2N1VUndx , B2N1VUndy , B2N1VUndz , B2N2Alpha , B2N2AxInd , B2N2Cd , B2N2Cl , B2N2Clrnc , & + B2N2Cm , B2N2Cn , B2N2Cpmin , B2N2Ct , B2N2Curve , B2N2Cx , B2N2Cy , B2N2DynP , & + B2N2Fd , B2N2Fl , B2N2Fn , B2N2Ft , B2N2Fx , B2N2Fy , B2N2Gam , B2N2M , & + B2N2Mm , B2N2Phi , B2N2Re , B2N2SgCav , B2N2SigCr , B2N2STVx , B2N2STVy , B2N2STVz , & + B2N2Theta , B2N2TnInd , B2N2VDisx , B2N2VDisy , B2N2VDisz , B2N2Vindx , B2N2Vindy , B2N2VRel , & + B2N2VUndx , B2N2VUndy , B2N2VUndz , B2N3Alpha , B2N3AxInd , B2N3Cd , B2N3Cl , B2N3Clrnc , & + B2N3Cm , B2N3Cn , B2N3Cpmin , B2N3Ct , B2N3Curve , B2N3Cx , B2N3Cy , B2N3DynP , & + B2N3Fd , B2N3Fl , B2N3Fn , B2N3Ft , B2N3Fx , B2N3Fy , B2N3Gam , B2N3M , & + B2N3Mm , B2N3Phi , B2N3Re , B2N3SgCav , B2N3SigCr , B2N3STVx , B2N3STVy , B2N3STVz , & + B2N3Theta , B2N3TnInd , B2N3VDisx , B2N3VDisy , B2N3VDisz , B2N3Vindx , B2N3Vindy , B2N3VRel , & + B2N3VUndx , B2N3VUndy , B2N3VUndz , B2N4Alpha , B2N4AxInd , B2N4Cd , B2N4Cl , B2N4Clrnc , & + B2N4Cm , B2N4Cn , B2N4Cpmin , B2N4Ct , B2N4Curve , B2N4Cx , B2N4Cy , B2N4DynP , & + B2N4Fd , B2N4Fl , B2N4Fn , B2N4Ft , B2N4Fx , B2N4Fy , B2N4Gam , B2N4M , & + B2N4Mm , B2N4Phi , B2N4Re , B2N4SgCav , B2N4SigCr , B2N4STVx , B2N4STVy , B2N4STVz , & + B2N4Theta , B2N4TnInd , B2N4VDisx , B2N4VDisy , B2N4VDisz , B2N4Vindx , B2N4Vindy , B2N4VRel , & + B2N4VUndx , B2N4VUndy , B2N4VUndz , B2N5Alpha , B2N5AxInd , B2N5Cd , B2N5Cl , B2N5Clrnc , & + B2N5Cm , B2N5Cn , B2N5Cpmin , B2N5Ct , B2N5Curve , B2N5Cx , B2N5Cy , B2N5DynP , & + B2N5Fd , B2N5Fl , B2N5Fn , B2N5Ft , B2N5Fx , B2N5Fy , B2N5Gam , B2N5M , & + B2N5Mm , B2N5Phi , B2N5Re , B2N5SgCav , B2N5SigCr , B2N5STVx , B2N5STVy , B2N5STVz , & + B2N5Theta , B2N5TnInd , B2N5VDisx , B2N5VDisy , B2N5VDisz , B2N5Vindx , B2N5Vindy , B2N5VRel , & + B2N5VUndx , B2N5VUndy , B2N5VUndz , B2N6Alpha , B2N6AxInd , B2N6Cd , B2N6Cl , B2N6Clrnc , & + B2N6Cm , B2N6Cn , B2N6Cpmin , B2N6Ct , B2N6Curve , B2N6Cx , B2N6Cy , B2N6DynP , & + B2N6Fd , B2N6Fl , B2N6Fn , B2N6Ft , B2N6Fx , B2N6Fy , B2N6Gam , B2N6M , & + B2N6Mm , B2N6Phi , B2N6Re , B2N6SgCav , B2N6SigCr , B2N6STVx , B2N6STVy , B2N6STVz , & + B2N6Theta , B2N6TnInd , B2N6VDisx , B2N6VDisy , B2N6VDisz , B2N6Vindx , B2N6Vindy , B2N6VRel , & + B2N6VUndx , B2N6VUndy , B2N6VUndz , B2N7Alpha , B2N7AxInd , B2N7Cd , B2N7Cl , B2N7Clrnc , & + B2N7Cm , B2N7Cn , B2N7Cpmin , B2N7Ct , B2N7Curve , B2N7Cx , B2N7Cy , B2N7DynP , & + B2N7Fd , B2N7Fl , B2N7Fn , B2N7Ft , B2N7Fx , B2N7Fy , B2N7Gam , B2N7M , & + B2N7Mm , B2N7Phi , B2N7Re , B2N7SgCav , B2N7SigCr , B2N7STVx , B2N7STVy , B2N7STVz , & + B2N7Theta , B2N7TnInd , B2N7VDisx , B2N7VDisy , B2N7VDisz , B2N7Vindx , B2N7Vindy , B2N7VRel , & + B2N7VUndx , B2N7VUndy , B2N7VUndz , B2N8Alpha , B2N8AxInd , B2N8Cd , B2N8Cl , B2N8Clrnc , & + B2N8Cm , B2N8Cn , B2N8Cpmin , B2N8Ct , B2N8Curve , B2N8Cx , B2N8Cy , B2N8DynP , & + B2N8Fd , B2N8Fl , B2N8Fn , B2N8Ft , B2N8Fx , B2N8Fy , B2N8Gam , B2N8M , & + B2N8Mm , B2N8Phi , B2N8Re , B2N8SgCav , B2N8SigCr , B2N8STVx , B2N8STVy , B2N8STVz , & + B2N8Theta , B2N8TnInd , B2N8VDisx , B2N8VDisy , B2N8VDisz , B2N8Vindx , B2N8Vindy , B2N8VRel , & + B2N8VUndx , B2N8VUndy , B2N8VUndz , B2N9Alpha , B2N9AxInd , B2N9Cd , B2N9Cl , B2N9Clrnc , & + B2N9Cm , B2N9Cn , B2N9Cpmin , B2N9Ct , B2N9Curve , B2N9Cx , B2N9Cy , B2N9DynP , & + B2N9Fd , B2N9Fl , B2N9Fn , B2N9Ft , B2N9Fx , B2N9Fy , B2N9Gam , B2N9M , & + B2N9Mm , B2N9Phi , B2N9Re , B2N9SgCav , B2N9SigCr , B2N9STVx , B2N9STVy , B2N9STVz , & + B2N9Theta , B2N9TnInd , B2N9VDisx , B2N9VDisy , B2N9VDisz , B2N9Vindx , B2N9Vindy , B2N9VRel , & + B2N9VUndx , B2N9VUndy , B2N9VUndz , B2Pitch , B3Azimuth , B3N1Alpha , B3N1AxInd , B3N1Cd , & + B3N1Cl , B3N1Clrnc , B3N1Cm , B3N1Cn , B3N1Cpmin , B3N1Ct , B3N1Curve , B3N1Cx , & + B3N1Cy , B3N1DynP , B3N1Fd , B3N1Fl , B3N1Fn , B3N1Ft , B3N1Fx , B3N1Fy , & + B3N1Gam , B3N1M , B3N1Mm , B3N1Phi , B3N1Re , B3N1SgCav , B3N1SigCr , B3N1STVx , & + B3N1STVy , B3N1STVz , B3N1Theta , B3N1TnInd , B3N1VDisx , B3N1VDisy , B3N1VDisz , B3N1Vindx , & + B3N1Vindy , B3N1VRel , B3N1VUndx , B3N1VUndy , B3N1VUndz , B3N2Alpha , B3N2AxInd , B3N2Cd , & + B3N2Cl , B3N2Clrnc , B3N2Cm , B3N2Cn , B3N2Cpmin , B3N2Ct , B3N2Curve , B3N2Cx , & + B3N2Cy , B3N2DynP , B3N2Fd , B3N2Fl , B3N2Fn , B3N2Ft , B3N2Fx , B3N2Fy , & + B3N2Gam , B3N2M , B3N2Mm , B3N2Phi , B3N2Re , B3N2SgCav , B3N2SigCr , B3N2STVx , & + B3N2STVy , B3N2STVz , B3N2Theta , B3N2TnInd , B3N2VDisx , B3N2VDisy , B3N2VDisz , B3N2Vindx , & + B3N2Vindy , B3N2VRel , B3N2VUndx , B3N2VUndy , B3N2VUndz , B3N3Alpha , B3N3AxInd , B3N3Cd , & + B3N3Cl , B3N3Clrnc , B3N3Cm , B3N3Cn , B3N3Cpmin , B3N3Ct , B3N3Curve , B3N3Cx , & + B3N3Cy , B3N3DynP , B3N3Fd , B3N3Fl , B3N3Fn , B3N3Ft , B3N3Fx , B3N3Fy , & + B3N3Gam , B3N3M , B3N3Mm , B3N3Phi , B3N3Re , B3N3SgCav , B3N3SigCr , B3N3STVx , & + B3N3STVy , B3N3STVz , B3N3Theta , B3N3TnInd , B3N3VDisx , B3N3VDisy , B3N3VDisz , B3N3Vindx , & + B3N3Vindy , B3N3VRel , B3N3VUndx , B3N3VUndy , B3N3VUndz , B3N4Alpha , B3N4AxInd , B3N4Cd , & + B3N4Cl , B3N4Clrnc , B3N4Cm , B3N4Cn , B3N4Cpmin , B3N4Ct , B3N4Curve , B3N4Cx , & + B3N4Cy , B3N4DynP , B3N4Fd , B3N4Fl , B3N4Fn , B3N4Ft , B3N4Fx , B3N4Fy , & + B3N4Gam , B3N4M , B3N4Mm , B3N4Phi , B3N4Re , B3N4SgCav , B3N4SigCr , B3N4STVx , & + B3N4STVy , B3N4STVz , B3N4Theta , B3N4TnInd , B3N4VDisx , B3N4VDisy , B3N4VDisz , B3N4Vindx , & + B3N4Vindy , B3N4VRel , B3N4VUndx , B3N4VUndy , B3N4VUndz , B3N5Alpha , B3N5AxInd , B3N5Cd , & + B3N5Cl , B3N5Clrnc , B3N5Cm , B3N5Cn , B3N5Cpmin , B3N5Ct , B3N5Curve , B3N5Cx , & + B3N5Cy , B3N5DynP , B3N5Fd , B3N5Fl , B3N5Fn , B3N5Ft , B3N5Fx , B3N5Fy , & + B3N5Gam , B3N5M , B3N5Mm , B3N5Phi , B3N5Re , B3N5SgCav , B3N5SigCr , B3N5STVx , & + B3N5STVy , B3N5STVz , B3N5Theta , B3N5TnInd , B3N5VDisx , B3N5VDisy , B3N5VDisz , B3N5Vindx , & + B3N5Vindy , B3N5VRel , B3N5VUndx , B3N5VUndy , B3N5VUndz , B3N6Alpha , B3N6AxInd , B3N6Cd , & + B3N6Cl , B3N6Clrnc , B3N6Cm , B3N6Cn , B3N6Cpmin , B3N6Ct , B3N6Curve , B3N6Cx , & + B3N6Cy , B3N6DynP , B3N6Fd , B3N6Fl , B3N6Fn , B3N6Ft , B3N6Fx , B3N6Fy , & + B3N6Gam , B3N6M , B3N6Mm , B3N6Phi , B3N6Re , B3N6SgCav , B3N6SigCr , B3N6STVx , & + B3N6STVy , B3N6STVz , B3N6Theta , B3N6TnInd , B3N6VDisx , B3N6VDisy , B3N6VDisz , B3N6Vindx , & + B3N6Vindy , B3N6VRel , B3N6VUndx , B3N6VUndy , B3N6VUndz , B3N7Alpha , B3N7AxInd , B3N7Cd , & + B3N7Cl , B3N7Clrnc , B3N7Cm , B3N7Cn , B3N7Cpmin , B3N7Ct , B3N7Curve , B3N7Cx , & + B3N7Cy , B3N7DynP , B3N7Fd , B3N7Fl , B3N7Fn , B3N7Ft , B3N7Fx , B3N7Fy , & + B3N7Gam , B3N7M , B3N7Mm , B3N7Phi , B3N7Re , B3N7SgCav , B3N7SigCr , B3N7STVx , & + B3N7STVy , B3N7STVz , B3N7Theta , B3N7TnInd , B3N7VDisx , B3N7VDisy , B3N7VDisz , B3N7Vindx , & + B3N7Vindy , B3N7VRel , B3N7VUndx , B3N7VUndy , B3N7VUndz , B3N8Alpha , B3N8AxInd , B3N8Cd , & + B3N8Cl , B3N8Clrnc , B3N8Cm , B3N8Cn , B3N8Cpmin , B3N8Ct , B3N8Curve , B3N8Cx , & + B3N8Cy , B3N8DynP , B3N8Fd , B3N8Fl , B3N8Fn , B3N8Ft , B3N8Fx , B3N8Fy , & + B3N8Gam , B3N8M , B3N8Mm , B3N8Phi , B3N8Re , B3N8SgCav , B3N8SigCr , B3N8STVx , & + B3N8STVy , B3N8STVz , B3N8Theta , B3N8TnInd , B3N8VDisx , B3N8VDisy , B3N8VDisz , B3N8Vindx , & + B3N8Vindy , B3N8VRel , B3N8VUndx , B3N8VUndy , B3N8VUndz , B3N9Alpha , B3N9AxInd , B3N9Cd , & + B3N9Cl , B3N9Clrnc , B3N9Cm , B3N9Cn , B3N9Cpmin , B3N9Ct , B3N9Curve , B3N9Cx , & + B3N9Cy , B3N9DynP , B3N9Fd , B3N9Fl , B3N9Fn , B3N9Ft , B3N9Fx , B3N9Fy , & + B3N9Gam , B3N9M , B3N9Mm , B3N9Phi , B3N9Re , B3N9SgCav , B3N9SigCr , B3N9STVx , & + B3N9STVy , B3N9STVz , B3N9Theta , B3N9TnInd , B3N9VDisx , B3N9VDisy , B3N9VDisz , B3N9Vindx , & + B3N9Vindy , B3N9VRel , B3N9VUndx , B3N9VUndy , B3N9VUndz , B3Pitch , DBEMTau1 , RtAeroCp , & + RtAeroCq , RtAeroCt , RtAeroFxh , RtAeroFyh , RtAeroFzh , RtAeroMxh , RtAeroMyh , RtAeroMzh , & + RtAeroPwr , RtArea , RtSkew , RtSpeed , RtTSR , RtVAvgxh , RtVAvgyh , RtVAvgzh , & + TwN1DynP , TwN1Fdx , TwN1Fdy , TwN1M , TwN1Re , TwN1STVx , TwN1STVy , TwN1STVz , & + TwN1Vrel , TwN1VUndx , TwN1VUndy , TwN1VUndz , TwN2DynP , TwN2Fdx , TwN2Fdy , TwN2M , & + TwN2Re , TwN2STVx , TwN2STVy , TwN2STVz , TwN2Vrel , TwN2VUndx , TwN2VUndy , TwN2VUndz , & + TwN3DynP , TwN3Fdx , TwN3Fdy , TwN3M , TwN3Re , TwN3STVx , TwN3STVy , TwN3STVz , & + TwN3Vrel , TwN3VUndx , TwN3VUndy , TwN3VUndz , TwN4DynP , TwN4Fdx , TwN4Fdy , TwN4M , & + TwN4Re , TwN4STVx , TwN4STVy , TwN4STVz , TwN4Vrel , TwN4VUndx , TwN4VUndy , TwN4VUndz , & + TwN5DynP , TwN5Fdx , TwN5Fdy , TwN5M , TwN5Re , TwN5STVx , TwN5STVy , TwN5STVz , & + TwN5Vrel , TwN5VUndx , TwN5VUndy , TwN5VUndz , TwN6DynP , TwN6Fdx , TwN6Fdy , TwN6M , & + TwN6Re , TwN6STVx , TwN6STVy , TwN6STVz , TwN6Vrel , TwN6VUndx , TwN6VUndy , TwN6VUndz , & + TwN7DynP , TwN7Fdx , TwN7Fdy , TwN7M , TwN7Re , TwN7STVx , TwN7STVy , TwN7STVz , & + TwN7Vrel , TwN7VUndx , TwN7VUndy , TwN7VUndz , TwN8DynP , TwN8Fdx , TwN8Fdy , TwN8M , & + TwN8Re , TwN8STVx , TwN8STVy , TwN8STVz , TwN8Vrel , TwN8VUndx , TwN8VUndy , TwN8VUndz , & + TwN9DynP , TwN9Fdx , TwN9Fdy , TwN9M , TwN9Re , TwN9STVx , TwN9STVy , TwN9STVz , & + TwN9Vrel , TwN9VUndx , TwN9VUndy , TwN9VUndz /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(1212) = (/ & ! This lists the units corresponding to the allowed parameters + "(deg) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ","(-) ","(-) ", & + "(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ","(N-m/m)","(deg) ", & + "(-) ","(-) ","(-) ","(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) ","(deg) ","(deg) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ","(-) ","(m) ", & + "(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(-) ", & + "(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(deg) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(-) ","(-) ", & + "(-) ","(m) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ", & + "(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(m^2/s)","(-) ","(N-m/m)","(deg) ","(-) ","(-) ","(-) ","(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) ","(deg) ","(s) ","(-) ", & + "(-) ","(-) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(W) ","(m^2) ","(deg) ","(rpm) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(Pa) ","(N/m) ","(N/m) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(-) ", & + "(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(Pa) ","(N/m) ","(N/m) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(-) ", & + "(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(Pa) ","(N/m) ","(N/m) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(-) ", & + "(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(Pa) ","(N/m) ","(N/m) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(-) ", & + "(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(Pa) ","(N/m) ","(N/m) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + !bjj: do we want to avoid outputting this if we haven't used tower aero? + + if ( p%TwrPotent == TwrPotent_none .and. p%TwrShadow == TwrShadow_none ) then + + ! BNClrnc is set only when we're computing the tower influence + do i = 1,size(BNClrnc,2) ! all blades (need to do this in a loop because we need the index of InvalidOutput to be an array of rank one) + InvalidOutput( BNClrnc(:,i) ) = .true. + end do + + end if + + if (p%WakeMod /= WakeMod_DBEMT) then + InvalidOutput( DBEMTau1 ) = .true. + end if + + DO i = p%NTwOuts+1,9 ! Invalid tower nodes + + InvalidOutput( TwNVUnd(:,i) ) = .true. + InvalidOutput( TwNSTV( :,i) ) = .true. + InvalidOutput( TwNVRel( i) ) = .true. + InvalidOutput( TwNDynP( i) ) = .true. + InvalidOutput( TwNRe( i) ) = .true. + InvalidOutput( TwNM( i) ) = .true. + InvalidOutput( TwNFdx( i) ) = .true. + InvalidOutput( TwNFdy( i) ) = .true. + + END DO + + DO I = p%NumBlades+1,size(BAzimuth,1) ! Invalid blades + + InvalidOutput( BAzimuth( i) ) = .true. + InvalidOutput( BPitch( i) ) = .true. + InvalidOutput( BNVUndx(:,i) ) = .true. + InvalidOutput( BNVUndy(:,i) ) = .true. + InvalidOutput( BNVUndz(:,i) ) = .true. + InvalidOutput( BNVDisx(:,i) ) = .true. + InvalidOutput( BNVDisy(:,i) ) = .true. + InvalidOutput( BNVDisz(:,i) ) = .true. + InvalidOutput( BNSTVx( :,i) ) = .true. + InvalidOutput( BNSTVy( :,i) ) = .true. + InvalidOutput( BNSTVz( :,i) ) = .true. + InvalidOutput( BNVRel( :,i) ) = .true. + InvalidOutput( BNDynP( :,i) ) = .true. + InvalidOutput( BNRe( :,i) ) = .true. + InvalidOutput( BNM( :,i) ) = .true. + InvalidOutput( BNVIndx(:,i) ) = .true. + InvalidOutput( BNVIndy(:,i) ) = .true. + InvalidOutput( BNAxInd(:,i) ) = .true. + InvalidOutput( BNTnInd(:,i) ) = .true. + InvalidOutput( BNAlpha(:,i) ) = .true. + InvalidOutput( BNTheta(:,i) ) = .true. + InvalidOutput( BNPhi( :,i) ) = .true. + InvalidOutput( BNCurve(:,i) ) = .true. + InvalidOutput( BNCl( :,i) ) = .true. + InvalidOutput( BNCd( :,i) ) = .true. + InvalidOutput( BNCm( :,i) ) = .true. + InvalidOutput( BNCx( :,i) ) = .true. + InvalidOutput( BNCy( :,i) ) = .true. + InvalidOutput( BNCn( :,i) ) = .true. + InvalidOutput( BNCt( :,i) ) = .true. + InvalidOutput( BNFl( :,i) ) = .true. + InvalidOutput( BNFd( :,i) ) = .true. + InvalidOutput( BNMm( :,i) ) = .true. + InvalidOutput( BNFx( :,i) ) = .true. + InvalidOutput( BNFy( :,i) ) = .true. + InvalidOutput( BNFn( :,i) ) = .true. + InvalidOutput( BNFt( :,i) ) = .true. + InvalidOutput( BNClrnc(:,i) ) = .true. + InvalidOutput( BNGam( :,i) ) = .true. + InvalidOutput( BNSgCav(:,i) ) = .true. + InvalidOutput( BNSigCr(:,i) ) = .true. + InvalidOutput( BNCpMin(:,i) ) = .true. + + END DO + + DO I = p%NBlOuts+1,9 ! Invalid blade nodes + + InvalidOutput( BNVUndx(i,:) ) = .true. + InvalidOutput( BNVUndy(i,:) ) = .true. + InvalidOutput( BNVUndz(i,:) ) = .true. + InvalidOutput( BNVDisx(i,:) ) = .true. + InvalidOutput( BNVDisy(i,:) ) = .true. + InvalidOutput( BNVDisz(i,:) ) = .true. + InvalidOutput( BNSTVx( i,:) ) = .true. + InvalidOutput( BNSTVy( i,:) ) = .true. + InvalidOutput( BNSTVz( i,:) ) = .true. + InvalidOutput( BNVRel( i,:) ) = .true. + InvalidOutput( BNDynP( i,:) ) = .true. + InvalidOutput( BNRe( i,:) ) = .true. + InvalidOutput( BNM( i,:) ) = .true. + InvalidOutput( BNVIndx(i,:) ) = .true. + InvalidOutput( BNVIndy(i,:) ) = .true. + InvalidOutput( BNAxInd(i,:) ) = .true. + InvalidOutput( BNTnInd(i,:) ) = .true. + InvalidOutput( BNAlpha(i,:) ) = .true. + InvalidOutput( BNTheta(i,:) ) = .true. + InvalidOutput( BNPhi( i,:) ) = .true. + InvalidOutput( BNCurve(i,:) ) = .true. + InvalidOutput( BNCl( i,:) ) = .true. + InvalidOutput( BNCd( i,:) ) = .true. + InvalidOutput( BNCm( i,:) ) = .true. + InvalidOutput( BNCx( i,:) ) = .true. + InvalidOutput( BNCy( i,:) ) = .true. + InvalidOutput( BNCn( i,:) ) = .true. + InvalidOutput( BNCt( i,:) ) = .true. + InvalidOutput( BNFl( i,:) ) = .true. + InvalidOutput( BNFd( i,:) ) = .true. + InvalidOutput( BNMm( i,:) ) = .true. + InvalidOutput( BNFx( i,:) ) = .true. + InvalidOutput( BNFy( i,:) ) = .true. + InvalidOutput( BNFn( i,:) ) = .true. + InvalidOutput( BNFt( i,:) ) = .true. + InvalidOutput( BNClrnc(i,:) ) = .true. + InvalidOutput( BNGam( i,:) ) = .true. + InvalidOutput( BNSgCav(i,:) ) = .true. + InvalidOutput( BNSigCr(i,:) ) = .true. + InvalidOutput( BNCpMin(i,:) ) = .true. + + END DO + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the AeroDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Indx = ParamIndxAry(Indx) + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + + + +END MODULE AeroDyn_IO diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Registry.txt b/OpenFAST/modules/aerodyn/src/AeroDyn_Registry.txt new file mode 100644 index 000000000..67998aa73 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Registry.txt @@ -0,0 +1,269 @@ +################################################################################################################################### +# Registry for AeroDyn 15 in the FAST Modularization Framework +# This Registry file is used to create AeroDyn_Types which contains data used in the AeroDyn module. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt +usefrom AirfoilInfo_Registry.txt +usefrom BEMT_Registry.txt +usefrom FVW_Registry.txt +usefrom UnsteadyAero_Registry.txt +usefrom AeroAcoustics_Registry.txt + +param AeroDyn/AD - IntKi ModelUnknown - -1 - "" - +param ^ - IntKi WakeMod_none - 0 - "Wake model - none" - +param ^ - IntKi WakeMod_BEMT - 1 - "Wake model - BEMT (blade elememnt momentum theory)" - +param ^ - IntKi WakeMod_DBEMT - 2 - "Wake model - DBEMT (dynamic elememnt momentum theory)" - +param ^ - IntKi WakeMod_FVW - 3 - "Wake model - FVW (free vortex wake, OLAF)" - + +param ^ - IntKi AFAeroMod_steady - 1 - "steady model" - +param ^ - IntKi AFAeroMod_BL_unsteady - 2 - "Beddoes-Leishman unsteady model" - + +param ^ - IntKi TwrPotent_none - 0 - "no tower potential flow" - +param ^ - IntKi TwrPotent_baseline - 1 - "baseline tower potential flow" - +param ^ - IntKi TwrPotent_Bak - 2 - "tower potential flow with Bak correction" - + +param ^ - IntKi TwrShadow_none - 0 - "no tower shadow" - +param ^ - IntKi TwrShadow_Powles - 1 - "Powles tower shadow model" - +param ^ - IntKi TwrShadow_Eames - 2 - "Eames tower shadow model" - + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef AeroDyn/AD InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ InitInputType IntKi NumBlades - - - "Number of blades on the turbine" - +typedef ^ InitInputType ReKi Gravity - - - "Gravity force" Nm/s^2 +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ InitInputType ReKi HubPosition {3} - - "X-Y-Z reference position of hub" m +typedef ^ InitInputType R8Ki HubOrientation {3}{3} - - "DCM reference orientation of hub" - +typedef ^ InitInputType ReKi BladeRootPosition {:}{:} - - "X-Y-Z reference position of each blade root (3 x NumBlades)" m +typedef ^ InitInputType R8Ki BladeRootOrientation {:}{:}{:} - - "DCM reference orientation of blade roots (3x3 x NumBlades)" - +typedef ^ InitInputType LOGICAL UsePrimaryInputFile - .TRUE. - "Read input file instead of passed data" - +typedef ^ InitInputType FileInfoType PassedPrimaryInputData - - - "Primary input file as FileInfoType (set by driver/glue code)" - + + + +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Blade Input file data ..................................................................................................... +typedef ^ AD_BladePropsType IntKi NumBlNds - - - "Number of blade nodes used in the analysis" - +typedef ^ AD_BladePropsType ReKi BlSpn {:} - - "Span at blade node" m +typedef ^ AD_BladePropsType ReKi BlCrvAC {:} - - "Curve at blade node" m +typedef ^ AD_BladePropsType ReKi BlSwpAC {:} - - "Sweep at blade node" m +typedef ^ AD_BladePropsType ReKi BlCrvAng {:} - - "Curve angle at blade node" radians +typedef ^ AD_BladePropsType ReKi BlTwist {:} - - "Twist at blade node" radians +typedef ^ AD_BladePropsType ReKi BlChord {:} - - "Chord at blade node" m +typedef ^ AD_BladePropsType IntKi BlAFID {:} - - "ID of Airfoil at blade node" - + +# Define outputs from the initialization routine here: +typedef ^ AD_BladeShape SiKi AirfoilCoords {:}{:}{:} - - "x-y coordinates for airfoils, relative to node" m +# Define outputs from the initialization routine here: +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType ReKi AirDens - - - "Air density" kg/m^3 +typedef ^ InitOutputType AD_BladeShape BladeShape {:} - - "airfoil coordinates for each blade" m +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states 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" - +typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ InitOutputType AD_BladePropsType BladeProps {:} - - "blade property information from blade input files" - +typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - +typedef ^ InitOutputType ReKi TwrElev {:} - - "Elevation at tower node" m +typedef ^ InitOutputType ReKi TwrDiam {:} - - "Diameter of tower at node" m + +# ..... Input file data ........................................................................................................... + +# ..... Primary Input file data ................................................................................................... +typedef ^ AD_InputFile Logical Echo - - - "Echo input file to echo file" - +typedef ^ AD_InputFile DbKi DTAero - - - "Time interval for aerodynamic calculations {or "default"}" s +typedef ^ AD_InputFile IntKi WakeMod - - - "Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW}" - +typedef ^ AD_InputFile IntKi AFAeroMod - - - "Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model}" - +typedef ^ AD_InputFile IntKi TwrPotent - - - "Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ AD_InputFile IntKi TwrShadow - - - "Calculate tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model}" - +typedef ^ AD_InputFile LOGICAL TwrAero - - - "Calculate tower aerodynamic loads?" flag +typedef ^ AD_InputFile Logical FrozenWake - - - "Flag that tells this module it should assume a frozen wake during linearization." - +typedef ^ AD_InputFile Logical CavitCheck - - - "Flag that tells us if we want to check for cavitation" - +typedef ^ AD_InputFile Logical CompAA - - - "Compute AeroAcoustic noise" flag +typedef ^ AD_InputFile CHARACTER(1024) AA_InputFile - - - "AeroAcoustics input file name" "quoted strings" +typedef ^ AD_InputFile CHARACTER(1024) ADBlFile {:} - - "AD blade file (NumBl filenames)" "quoted strings" +typedef ^ AD_InputFile ReKi AirDens - - - "Air density" kg/m^3 +typedef ^ AD_InputFile ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ AD_InputFile ReKi Patm - - - "Atmospheric pressure" Pa +typedef ^ AD_InputFile ReKi Pvap - - - "Vapour pressure" Pa +typedef ^ AD_InputFile ReKi FluidDepth - - - "Submerged hub depth" m +typedef ^ AD_InputFile ReKi SpdSound - - - "Speed of sound" m/s +typedef ^ AD_InputFile IntKi SkewMod - - - "Type of skewed-wake correction model {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0]" - +typedef ^ AD_InputFile ReKi SkewModFactor - - - "Constant used in Pitt/Peters skewed wake model (default is 15*pi/32)" - +typedef ^ AD_InputFile LOGICAL TipLoss - - - "Use the Prandtl tip-loss model? [unused when WakeMod=0]" flag +typedef ^ AD_InputFile LOGICAL HubLoss - - - "Use the Prandtl hub-loss model? [unused when WakeMod=0]" flag +typedef ^ AD_InputFile LOGICAL TanInd - - - "Include tangential induction in BEMT calculations? [unused when WakeMod=0]" flag +typedef ^ AD_InputFile LOGICAL AIDrag - - - "Include the drag term in the axial-induction calculation? [unused when WakeMod=0]" flag +typedef ^ AD_InputFile LOGICAL TIDrag - - - "Include the drag term in the tangential-induction calculation? [unused when WakeMod=0 or TanInd=FALSE]" flag +typedef ^ AD_InputFile ReKi IndToler - - - "Convergence tolerance for BEM induction factors [unused when WakeMod=0]" - +typedef ^ AD_InputFile ReKi MaxIter - - - "Maximum number of iteration steps [unused when WakeMod=0]" - +typedef ^ AD_InputFile IntKi UAMod - - - "Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2]" - +typedef ^ AD_InputFile LOGICAL FLookup - - - "Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files [used only when AFAeroMod=2]" flag +typedef ^ AD_InputFile ReKi InCol_Alfa - - - "The column in the airfoil tables that contains the angle of attack" - +typedef ^ AD_InputFile ReKi InCol_Cl - - - "The column in the airfoil tables that contains the lift coefficient" - +typedef ^ AD_InputFile ReKi InCol_Cd - - - "The column in the airfoil tables that contains the drag coefficient" - +typedef ^ AD_InputFile ReKi InCol_Cm - - - "The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column" - +typedef ^ AD_InputFile ReKi InCol_Cpmin - - - "The column in the airfoil tables that contains the drag coefficient; use zero if there is no Cpmin column" - +typedef ^ AD_InputFile INTEGER AFTabMod - - - "Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp}" - +typedef ^ AD_InputFile IntKi NumAFfiles - - - "Number of airfoil files used" - +typedef ^ AD_InputFile CHARACTER(1024) FVWFileName - - - "FVW input filename" "quoted string" +typedef ^ AD_InputFile CHARACTER(1024) AFNames {:} - - "Airfoil file names (NumAF lines)" "quoted strings" +typedef ^ AD_InputFile LOGICAL UseBlCm - - - "Include aerodynamic pitching moment in calculations?" flag +#typedef ^ AD_InputFile IntKi NumBlNds - - - "Number of blade nodes used in the analysis" - +typedef ^ AD_InputFile AD_BladePropsType BladeProps {:} - - "blade property information from blade input files" - +typedef ^ AD_InputFile IntKi NumTwrNds - - - "Number of tower nodes used in the analysis" - +typedef ^ AD_InputFile ReKi TwrElev {:} - - "Elevation at tower node" m +typedef ^ AD_InputFile ReKi TwrDiam {:} - - "Diameter of tower at node" m +typedef ^ AD_InputFile ReKi TwrCd {:} - - "Coefficient of drag at tower node" - +typedef ^ AD_InputFile ReKi TwrTI {:} - - "Turbulence intensity for tower shadow at tower node" - +typedef ^ AD_InputFile LOGICAL SumPrint - - - "Generate a summary file listing input options and interpolated properties to "<rootname>.AD.sum"?" flag +typedef ^ AD_InputFile IntKi NBlOuts - - - "Number of blade node outputs [0 - 9]" - +typedef ^ AD_InputFile IntKi BlOutNd {9} - - "Blade nodes whose values will be output" - +typedef ^ AD_InputFile IntKi NTwOuts - - - "Number of tower node outputs [0 - 9]" - +typedef ^ AD_InputFile IntKi TwOutNd {9} - - "Tower nodes whose values will be output" - +typedef ^ AD_InputFile IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ AD_InputFile CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - +typedef ^ AD_InputFile ReKi tau1_const - - - "time constant for DBEMT [used only when WakeMod=2 and DBEMT_Mod/=2]" s +typedef ^ AD_InputFile IntKi DBEMT_Mod - - - "Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1}" - +typedef ^ AD_InputFile IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (AD_AllBldNdOuts)" - +typedef ^ AD_InputFile CHARACTER(ChanLen) BldNd_OutList {:} - - "List of user-requested output channels (AD_AllBldNdOuts)" - +#typedef ^ AD_InputFile IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (AD_AllBldNdOuts)" - +typedef ^ AD_InputFile CHARACTER(1024) BldNd_BlOutNd_Str - - - "String to parse for the blade nodes to actually output (AD_AllBldNdOuts)" - +typedef ^ AD_InputFile IntKi BldNd_BladesOut - - - "The blades to output (AD_AllBldNdOuts)" - +#typedef ^ AD_InputFile CHARACTER(1024) BldNd_BladesOut_Str - - - "String to parse for the he blades to output (AD_AllBldNdOuts)" - + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType BEMT_ContinuousStateType BEMT - - - "Continuous states from the BEMT module" - +typedef ^ ContinuousStateType FVW_ContinuousStateType FVW - - - "Continuous states from the FVW module" - +typedef ^ ContinuousStateType AA_ContinuousStateType AA - - - "Continuous states from the AA module" - + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType BEMT_DiscreteStateType BEMT - - - "Discrete states from the BEMT module" - +typedef ^ DiscreteStateType FVW_DiscreteStateType FVW - - - "Discrete states from the FVW module" - +typedef ^ DiscreteStateType AA_DiscreteStateType AA - - - "Discrete states from the AA module" - + +# Define constraint states here: +typedef ^ ConstraintStateType BEMT_ConstraintStateType BEMT - - - "Constraint states from the BEMT module" - +typedef ^ ConstraintStateType FVW_ConstraintStateType FVW - - - "Constraint states from the FVW module" - +typedef ^ ConstraintStateType AA_ConstraintStateType AA - - - "Constraint states from the AA module" - + +# Define "other" states here: +typedef ^ OtherStateType BEMT_OtherStateType BEMT - - - "OtherStates from the BEMT module" - +typedef ^ OtherStateType FVW_OtherStateType FVW - - - "OtherStates from the FVW module" - +typedef ^ OtherStateType ReKi WakeLocationPoints {:}{:} - - "wake points velocity" m/s +typedef ^ OtherStateType AA_OtherStateType AA - - - "OtherStates from the AA module" - + +# Define misc/optimization variables (any data that are not considered actual states) here: +typedef ^ MiscVarType BEMT_MiscVarType BEMT - - - "MiscVars from the BEMT module" - +typedef ^ MiscVarType BEMT_OutputType BEMT_y - - - "Outputs from the BEMT module" - +typedef ^ MiscVarType BEMT_InputType BEMT_u 2 - - "Inputs to the BEMT module" - +typedef ^ MiscVarType FVW_MiscVarType FVW - - - "MiscVars from the FVW module" - +typedef ^ MiscVarType FVW_OutputType FVW_y - - - "Outputs from the FVW module" - +typedef ^ MiscVarType FVW_InputType FVW_u : - - "Inputs to the FVW module" - +typedef ^ MiscVarType AA_MiscVarType AA - - - "MiscVars from the AA module" - +typedef ^ MiscVarType AA_OutputType AA_y - - - "Outputs from the AA module" - +typedef ^ MiscVarType AA_InputType AA_u - - - "Inputs to the AA module" - + +typedef ^ MiscVarType ReKi DisturbedInflow {:}{:}{:} - - "InflowOnBlade values modified by tower influence" m/s +typedef ^ MiscVarType ReKi WithoutSweepPitchTwist {:}{:}{:}{:} - - "Coordinate system equivalent to BladeMotion Orientation, but without live sweep, blade-pitch, and twist angles" - +typedef ^ MiscVarType ReKi AllOuts {:} - - "An array holding the value of all of the calculated (not only selected) output channels" - +typedef ^ MiscVarType ReKi W_Twr {:} - - "relative wind speed normal to the tower at node j" m/s +typedef ^ MiscVarType ReKi X_Twr {:} - - "local x-component of force per unit length of the jth node in the tower" m/s +typedef ^ MiscVarType ReKi Y_Twr {:} - - "local y-component of force per unit length of the jth node in the tower" m/s +typedef ^ MiscVarType ReKi Curve {:}{:} - - "curvature angle, saved for possible output to file" rad +typedef ^ MiscVarType ReKi TwrClrnc {:}{:} - - "Distance between tower (including tower radius) and blade node (not including blade width), saved for possible output to file" m +typedef ^ MiscVarType ReKi X {:}{:} - - "normal force per unit length (normal to the plane, not chord) of the jth node in the kth blade" N/m +typedef ^ MiscVarType ReKi Y {:}{:} - - "tangential force per unit length (tangential to the plane, not chord) of the jth node in the kth blade" N/m +typedef ^ MiscVarType ReKi M {:}{:} - - "pitching moment per unit length of the jth node in the kth blade" Nm/m +typedef ^ MiscVarType ReKi V_DiskAvg {3} - - "disk-average relative wind speed" m/s +typedef ^ MiscVarType ReKi hub_theta_x_root {3} - - "angles saved for FAST.Farm" rad +typedef ^ MiscVarType ReKi V_dot_x - - - +typedef ^ MiscVarType MeshType HubLoad - - - "mesh at hub; used to compute an integral for mapping the output blade loads to a single point (for writing to file only)" - +typedef ^ MiscVarType MeshMapType B_L_2_H_P {:} - - "mapping data structure to map each bladeLoad output mesh to the MiscVar%HubLoad mesh" +typedef ^ MiscVarType ReKi SigmaCavitCrit {:}{:} - - "critical cavitation number- inception value (above which cavit will occur)" - +typedef ^ MiscVarType ReKi SigmaCavit {:}{:} - - "cavitation number at node " - +typedef ^ MiscVarType Logical CavitWarnSet {:}{:} - - "cavitation warning issued " - + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ParameterType IntKi WakeMod - - - "Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW}" - +typedef ^ ParameterType IntKi TwrPotent - - - "Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - +typedef ^ ParameterType IntKi TwrShadow - - - "Calculate tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model}" - +typedef ^ ParameterType LOGICAL TwrAero - - - "Calculate tower aerodynamic loads?" flag +typedef ^ ParameterType Logical FrozenWake - - - "Flag that tells this module it should assume a frozen wake during linearization." - +typedef ^ ParameterType Logical CavitCheck - - - "Flag that tells us if we want to check for cavitation" - +typedef ^ ParameterType Logical CompAA - - - "Compute AeroAcoustic noise" flag +typedef ^ ParameterType IntKi NumBlades - - - "Number of blades on the turbine" - +typedef ^ ParameterType IntKi NumBlNds - - - "Number of nodes on each blade" - +typedef ^ ParameterType IntKi NumTwrNds - - - "Number of nodes on the tower" - +typedef ^ ParameterType ReKi TwrDiam {:} - - "Diameter of tower at node" m +typedef ^ ParameterType ReKi TwrCd {:} - - "Coefficient of drag at tower node" - +typedef ^ ParameterType ReKi TwrTI {:} - - "Turbulence intensity for tower shadow at tower node" - +typedef ^ ParameterType ReKi AirDens - - - "Air density" kg/m^3 +typedef ^ ParameterType ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ ParameterType ReKi SpdSound - - - "Speed of sound" m/s +typedef ^ ParameterType ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ ParameterType ReKi Patm - - - "Atmospheric pressure" Pa +typedef ^ ParameterType ReKi Pvap - - - "Vapour pressure" Pa +typedef ^ ParameterType ReKi FluidDepth - - - "Submerged hub height" m +typedef ^ ParameterType AFI_ParameterType AFI {:} - - "AirfoilInfo parameters" +typedef ^ ParameterType BEMT_ParameterType BEMT - - - "Parameters for BEMT module" +typedef ^ ParameterType FVW_ParameterType FVW - - - "Parameters for FVW module" +typedef ^ ParameterType AA_ParameterType AA - - - "Parameters for AA module" +# parameters for output +typedef ^ ParameterType IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType IntKi NBlOuts - - - "Number of blade node outputs [0 - 9]" - +typedef ^ ParameterType IntKi BlOutNd {9} - - "Blade nodes whose values will be output" - +typedef ^ ParameterType IntKi NTwOuts - - - "Number of tower node outputs [0 - 9]" - +typedef ^ ParameterType IntKi TwOutNd {9} - - "Tower nodes whose values will be output" - + +typedef ^ ParameterType IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (AD_AllBldNdOuts)" - +typedef ^ ParameterType IntKi BldNd_TotNumOuts - - - "Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- AD_AllBldNdOuts)" - +typedef ^ ParameterType OutParmType BldNd_OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (AD_AllBldNdOuts)" - +typedef ^ ParameterType IntKi BldNd_BladesOut - - - "The blades to output (AD_AllBldNdOuts)" - + + +typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ParameterType ReKi du {:} - - "vector that determines size of perturbation for u (inputs)" +typedef ^ ParameterType ReKi dx {:} - - "vector that determines size of perturbation for x (continuous states)" +typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef ^ InputType MeshType TowerMotion - - - "motion on the tower" - +typedef ^ InputType MeshType HubMotion - - - "motion on the hub" - +typedef ^ InputType MeshType BladeRootMotion {:} - - "motion on each blade root" - +typedef ^ InputType MeshType BladeMotion {:} - - "motion on each blade" - +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi InflowOnBlade {:}{:}{:} - - "U,V,W at nodes on each blade (note if we change the requirement that NumNodes is the same for each blade, this will need to change)" m/s +typedef ^ InputType ReKi InflowOnTower {:}{:} - - "U,V,W at nodes on the tower" m/s +typedef ^ InputType ReKi UserProp {:}{:} - - "Optional user property for interpolating airfoils (per element per blade)" - +typedef ^ InputType ReKi InflowWakeVel {:}{:} - - "U,V,W at wake points" m/s + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType TowerLoad - - - "loads on the tower" - +typedef ^ OutputType MeshType BladeLoad {:} - - "loads on each blade" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" diff --git a/OpenFAST/modules/aerodyn/src/AeroDyn_Types.f90 b/OpenFAST/modules/aerodyn/src/AeroDyn_Types.f90 new file mode 100644 index 000000000..c3ac68c37 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AeroDyn_Types.f90 @@ -0,0 +1,10477 @@ +!STARTOFREGISTRYGENERATEDFILE 'AeroDyn_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 +!********************************************************************************************************************************* +! AeroDyn_Types +!................................................................................................................................. +! This file is part of AeroDyn. +! +! 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 AeroDyn. 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 AeroDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE UnsteadyAero_Types +USE DBEMT_Types +USE BEMT_Types +USE FVW_Types +USE AeroAcoustics_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: ModelUnknown = -1 ! [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: WakeMod_none = 0 ! Wake model - none [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: WakeMod_BEMT = 1 ! Wake model - BEMT (blade elememnt momentum theory) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: WakeMod_DBEMT = 2 ! Wake model - DBEMT (dynamic elememnt momentum theory) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: WakeMod_FVW = 3 ! Wake model - FVW (free vortex wake, OLAF) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: AFAeroMod_steady = 1 ! steady model [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: AFAeroMod_BL_unsteady = 2 ! Beddoes-Leishman unsteady model [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrPotent_none = 0 ! no tower potential flow [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrPotent_baseline = 1 ! baseline tower potential flow [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrPotent_Bak = 2 ! tower potential flow with Bak correction [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrShadow_none = 0 ! no tower shadow [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrShadow_Powles = 1 ! Powles tower shadow model [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TwrShadow_Eames = 2 ! Eames tower shadow model [-] +! ========= AD_InitInputType ======= + TYPE, PUBLIC :: AD_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + REAL(ReKi) :: Gravity !< Gravity force [Nm/s^2] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(1:3) :: HubPosition !< X-Y-Z reference position of hub [m] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: HubOrientation !< DCM reference orientation of hub [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BladeRootPosition !< X-Y-Z reference position of each blade root (3 x NumBlades) [m] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: BladeRootOrientation !< DCM reference orientation of blade roots (3x3 x NumBlades) [-] + LOGICAL :: UsePrimaryInputFile = .TRUE. !< Read input file instead of passed data [-] + TYPE(FileInfoType) :: PassedPrimaryInputData !< Primary input file as FileInfoType (set by driver/glue code) [-] + END TYPE AD_InitInputType +! ======================= +! ========= AD_BladePropsType ======= + TYPE, PUBLIC :: AD_BladePropsType + INTEGER(IntKi) :: NumBlNds !< Number of blade nodes used in the analysis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlSpn !< Span at blade node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlCrvAC !< Curve at blade node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlSwpAC !< Sweep at blade node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlCrvAng !< Curve angle at blade node [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlTwist !< Twist at blade node [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlChord !< Chord at blade node [m] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: BlAFID !< ID of Airfoil at blade node [-] + END TYPE AD_BladePropsType +! ======================= +! ========= AD_BladeShape ======= + TYPE, PUBLIC :: AD_BladeShape + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: AirfoilCoords !< x-y coordinates for airfoils, relative to node [m] + END TYPE AD_BladeShape +! ======================= +! ========= AD_InitOutputType ======= + TYPE, PUBLIC :: AD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + TYPE(AD_BladeShape) , DIMENSION(:), ALLOCATABLE :: BladeShape !< airfoil coordinates for each blade [m] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + TYPE(AD_BladePropsType) , DIMENSION(:), ALLOCATABLE :: BladeProps !< blade property information from blade input files [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrElev !< Elevation at tower node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrDiam !< Diameter of tower at node [m] + END TYPE AD_InitOutputType +! ======================= +! ========= AD_InputFile ======= + TYPE, PUBLIC :: AD_InputFile + LOGICAL :: Echo !< Echo input file to echo file [-] + REAL(DbKi) :: DTAero !< Time interval for aerodynamic calculations {or "default"} [s] + INTEGER(IntKi) :: WakeMod !< Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} [-] + INTEGER(IntKi) :: AFAeroMod !< Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model} [-] + INTEGER(IntKi) :: TwrPotent !< Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: TwrShadow !< Calculate tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model} [-] + LOGICAL :: TwrAero !< Calculate tower aerodynamic loads? [flag] + LOGICAL :: FrozenWake !< Flag that tells this module it should assume a frozen wake during linearization. [-] + LOGICAL :: CavitCheck !< Flag that tells us if we want to check for cavitation [-] + LOGICAL :: CompAA !< Compute AeroAcoustic noise [flag] + CHARACTER(1024) :: AA_InputFile !< AeroAcoustics input file name [quoted strings] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: ADBlFile !< AD blade file (NumBl filenames) [quoted strings] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + REAL(ReKi) :: Patm !< Atmospheric pressure [Pa] + REAL(ReKi) :: Pvap !< Vapour pressure [Pa] + REAL(ReKi) :: FluidDepth !< Submerged hub depth [m] + REAL(ReKi) :: SpdSound !< Speed of sound [m/s] + INTEGER(IntKi) :: SkewMod !< Type of skewed-wake correction model {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0] [-] + REAL(ReKi) :: SkewModFactor !< Constant used in Pitt/Peters skewed wake model (default is 15*pi/32) [-] + LOGICAL :: TipLoss !< Use the Prandtl tip-loss model? [unused when WakeMod=0] [flag] + LOGICAL :: HubLoss !< Use the Prandtl hub-loss model? [unused when WakeMod=0] [flag] + LOGICAL :: TanInd !< Include tangential induction in BEMT calculations? [unused when WakeMod=0] [flag] + LOGICAL :: AIDrag !< Include the drag term in the axial-induction calculation? [unused when WakeMod=0] [flag] + LOGICAL :: TIDrag !< Include the drag term in the tangential-induction calculation? [unused when WakeMod=0 or TanInd=FALSE] [flag] + REAL(ReKi) :: IndToler !< Convergence tolerance for BEM induction factors [unused when WakeMod=0] [-] + REAL(ReKi) :: MaxIter !< Maximum number of iteration steps [unused when WakeMod=0] [-] + INTEGER(IntKi) :: UAMod !< Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2] [-] + LOGICAL :: FLookup !< Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files [used only when AFAeroMod=2] [flag] + REAL(ReKi) :: InCol_Alfa !< The column in the airfoil tables that contains the angle of attack [-] + REAL(ReKi) :: InCol_Cl !< The column in the airfoil tables that contains the lift coefficient [-] + REAL(ReKi) :: InCol_Cd !< The column in the airfoil tables that contains the drag coefficient [-] + REAL(ReKi) :: InCol_Cm !< The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column [-] + REAL(ReKi) :: InCol_Cpmin !< The column in the airfoil tables that contains the drag coefficient; use zero if there is no Cpmin column [-] + INTEGER(IntKi) :: AFTabMod !< Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp} [-] + INTEGER(IntKi) :: NumAFfiles !< Number of airfoil files used [-] + CHARACTER(1024) :: FVWFileName !< FVW input filename [quoted string] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: AFNames !< Airfoil file names (NumAF lines) [quoted strings] + LOGICAL :: UseBlCm !< Include aerodynamic pitching moment in calculations? [flag] + TYPE(AD_BladePropsType) , DIMENSION(:), ALLOCATABLE :: BladeProps !< blade property information from blade input files [-] + INTEGER(IntKi) :: NumTwrNds !< Number of tower nodes used in the analysis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrElev !< Elevation at tower node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrDiam !< Diameter of tower at node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrCd !< Coefficient of drag at tower node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrTI !< Turbulence intensity for tower shadow at tower node [-] + LOGICAL :: SumPrint !< Generate a summary file listing input options and interpolated properties to "<rootname>.AD.sum"? [flag] + INTEGER(IntKi) :: NBlOuts !< Number of blade node outputs [0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: BlOutNd !< Blade nodes whose values will be output [-] + INTEGER(IntKi) :: NTwOuts !< Number of tower node outputs [0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: TwOutNd !< Tower nodes whose values will be output [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + REAL(ReKi) :: tau1_const !< time constant for DBEMT [used only when WakeMod=2 and DBEMT_Mod/=2] [s] + INTEGER(IntKi) :: DBEMT_Mod !< Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} [-] + INTEGER(IntKi) :: BldNd_NumOuts !< Number of requested output channels per blade node (AD_AllBldNdOuts) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: BldNd_OutList !< List of user-requested output channels (AD_AllBldNdOuts) [-] + CHARACTER(1024) :: BldNd_BlOutNd_Str !< String to parse for the blade nodes to actually output (AD_AllBldNdOuts) [-] + INTEGER(IntKi) :: BldNd_BladesOut !< The blades to output (AD_AllBldNdOuts) [-] + END TYPE AD_InputFile +! ======================= +! ========= AD_ContinuousStateType ======= + TYPE, PUBLIC :: AD_ContinuousStateType + TYPE(BEMT_ContinuousStateType) :: BEMT !< Continuous states from the BEMT module [-] + TYPE(FVW_ContinuousStateType) :: FVW !< Continuous states from the FVW module [-] + TYPE(AA_ContinuousStateType) :: AA !< Continuous states from the AA module [-] + END TYPE AD_ContinuousStateType +! ======================= +! ========= AD_DiscreteStateType ======= + TYPE, PUBLIC :: AD_DiscreteStateType + TYPE(BEMT_DiscreteStateType) :: BEMT !< Discrete states from the BEMT module [-] + TYPE(FVW_DiscreteStateType) :: FVW !< Discrete states from the FVW module [-] + TYPE(AA_DiscreteStateType) :: AA !< Discrete states from the AA module [-] + END TYPE AD_DiscreteStateType +! ======================= +! ========= AD_ConstraintStateType ======= + TYPE, PUBLIC :: AD_ConstraintStateType + TYPE(BEMT_ConstraintStateType) :: BEMT !< Constraint states from the BEMT module [-] + TYPE(FVW_ConstraintStateType) :: FVW !< Constraint states from the FVW module [-] + TYPE(AA_ConstraintStateType) :: AA !< Constraint states from the AA module [-] + END TYPE AD_ConstraintStateType +! ======================= +! ========= AD_OtherStateType ======= + TYPE, PUBLIC :: AD_OtherStateType + TYPE(BEMT_OtherStateType) :: BEMT !< OtherStates from the BEMT module [-] + TYPE(FVW_OtherStateType) :: FVW !< OtherStates from the FVW module [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WakeLocationPoints !< wake points velocity [m/s] + TYPE(AA_OtherStateType) :: AA !< OtherStates from the AA module [-] + END TYPE AD_OtherStateType +! ======================= +! ========= AD_MiscVarType ======= + TYPE, PUBLIC :: AD_MiscVarType + TYPE(BEMT_MiscVarType) :: BEMT !< MiscVars from the BEMT module [-] + TYPE(BEMT_OutputType) :: BEMT_y !< Outputs from the BEMT module [-] + TYPE(BEMT_InputType) , DIMENSION(1:2) :: BEMT_u !< Inputs to the BEMT module [-] + TYPE(FVW_MiscVarType) :: FVW !< MiscVars from the FVW module [-] + TYPE(FVW_OutputType) :: FVW_y !< Outputs from the FVW module [-] + TYPE(FVW_InputType) , DIMENSION(:), ALLOCATABLE :: FVW_u !< Inputs to the FVW module [-] + TYPE(AA_MiscVarType) :: AA !< MiscVars from the AA module [-] + TYPE(AA_OutputType) :: AA_y !< Outputs from the AA module [-] + TYPE(AA_InputType) :: AA_u !< Inputs to the AA module [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: DisturbedInflow !< InflowOnBlade values modified by tower influence [m/s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: WithoutSweepPitchTwist !< Coordinate system equivalent to BladeMotion Orientation, but without live sweep, blade-pitch, and twist angles [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: W_Twr !< relative wind speed normal to the tower at node j [m/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: X_Twr !< local x-component of force per unit length of the jth node in the tower [m/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Y_Twr !< local y-component of force per unit length of the jth node in the tower [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Curve !< curvature angle, saved for possible output to file [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TwrClrnc !< Distance between tower (including tower radius) and blade node (not including blade width), saved for possible output to file [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: X !< normal force per unit length (normal to the plane, not chord) of the jth node in the kth blade [N/m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Y !< tangential force per unit length (tangential to the plane, not chord) of the jth node in the kth blade [N/m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< pitching moment per unit length of the jth node in the kth blade [Nm/m] + REAL(ReKi) , DIMENSION(1:3) :: V_DiskAvg !< disk-average relative wind speed [m/s] + REAL(ReKi) , DIMENSION(1:3) :: hub_theta_x_root !< angles saved for FAST.Farm [rad] + REAL(ReKi) :: V_dot_x + TYPE(MeshType) :: HubLoad !< mesh at hub; used to compute an integral for mapping the output blade loads to a single point (for writing to file only) [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: B_L_2_H_P !< mapping data structure to map each bladeLoad output mesh to the MiscVar%HubLoad mesh [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SigmaCavitCrit !< critical cavitation number- inception value (above which cavit will occur) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SigmaCavit !< cavitation number at node [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: CavitWarnSet !< cavitation warning issued [-] + END TYPE AD_MiscVarType +! ======================= +! ========= AD_ParameterType ======= + TYPE, PUBLIC :: AD_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + INTEGER(IntKi) :: WakeMod !< Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} [-] + INTEGER(IntKi) :: TwrPotent !< Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] + INTEGER(IntKi) :: TwrShadow !< Calculate tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model} [-] + LOGICAL :: TwrAero !< Calculate tower aerodynamic loads? [flag] + LOGICAL :: FrozenWake !< Flag that tells this module it should assume a frozen wake during linearization. [-] + LOGICAL :: CavitCheck !< Flag that tells us if we want to check for cavitation [-] + LOGICAL :: CompAA !< Compute AeroAcoustic noise [flag] + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + INTEGER(IntKi) :: NumBlNds !< Number of nodes on each blade [-] + INTEGER(IntKi) :: NumTwrNds !< Number of nodes on the tower [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrDiam !< Diameter of tower at node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrCd !< Coefficient of drag at tower node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrTI !< Turbulence intensity for tower shadow at tower node [-] + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + REAL(ReKi) :: SpdSound !< Speed of sound [m/s] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) :: Patm !< Atmospheric pressure [Pa] + REAL(ReKi) :: Pvap !< Vapour pressure [Pa] + REAL(ReKi) :: FluidDepth !< Submerged hub height [m] + TYPE(AFI_ParameterType) , DIMENSION(:), ALLOCATABLE :: AFI !< AirfoilInfo parameters [-] + TYPE(BEMT_ParameterType) :: BEMT !< Parameters for BEMT module [-] + TYPE(FVW_ParameterType) :: FVW !< Parameters for FVW module [-] + TYPE(AA_ParameterType) :: AA !< Parameters for AA module [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + INTEGER(IntKi) :: NBlOuts !< Number of blade node outputs [0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: BlOutNd !< Blade nodes whose values will be output [-] + INTEGER(IntKi) :: NTwOuts !< Number of tower node outputs [0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: TwOutNd !< Tower nodes whose values will be output [-] + INTEGER(IntKi) :: BldNd_NumOuts !< Number of requested output channels per blade node (AD_AllBldNdOuts) [-] + INTEGER(IntKi) :: BldNd_TotNumOuts !< Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- AD_AllBldNdOuts) [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: BldNd_OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: BldNd_BlOutNd !< The blade nodes to actually output (AD_AllBldNdOuts) [-] + INTEGER(IntKi) :: BldNd_BladesOut !< The blades to output (AD_AllBldNdOuts) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dx !< vector that determines size of perturbation for x (continuous states) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-] + END TYPE AD_ParameterType +! ======================= +! ========= AD_InputType ======= + TYPE, PUBLIC :: AD_InputType + TYPE(MeshType) :: TowerMotion !< motion on the tower [-] + TYPE(MeshType) :: HubMotion !< motion on the hub [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladeRootMotion !< motion on each blade root [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladeMotion !< motion on each blade [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: InflowOnBlade !< U,V,W at nodes on each blade (note if we change the requirement that NumNodes is the same for each blade, this will need to change) [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: InflowOnTower !< U,V,W at nodes on the tower [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: UserProp !< Optional user property for interpolating airfoils (per element per blade) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: InflowWakeVel !< U,V,W at wake points [m/s] + END TYPE AD_InputType +! ======================= +! ========= AD_OutputType ======= + TYPE, PUBLIC :: AD_OutputType + TYPE(MeshType) :: TowerLoad !< loads on the tower [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladeLoad !< loads on each blade [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE AD_OutputType +! ======================= +CONTAINS + SUBROUTINE AD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(AD_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 = 'AD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%NumBlades = SrcInitInputData%NumBlades + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%HubPosition = SrcInitInputData%HubPosition + DstInitInputData%HubOrientation = SrcInitInputData%HubOrientation +IF (ALLOCATED(SrcInitInputData%BladeRootPosition)) THEN + i1_l = LBOUND(SrcInitInputData%BladeRootPosition,1) + i1_u = UBOUND(SrcInitInputData%BladeRootPosition,1) + i2_l = LBOUND(SrcInitInputData%BladeRootPosition,2) + i2_u = UBOUND(SrcInitInputData%BladeRootPosition,2) + IF (.NOT. ALLOCATED(DstInitInputData%BladeRootPosition)) THEN + ALLOCATE(DstInitInputData%BladeRootPosition(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BladeRootPosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BladeRootPosition = SrcInitInputData%BladeRootPosition +ENDIF +IF (ALLOCATED(SrcInitInputData%BladeRootOrientation)) THEN + i1_l = LBOUND(SrcInitInputData%BladeRootOrientation,1) + i1_u = UBOUND(SrcInitInputData%BladeRootOrientation,1) + i2_l = LBOUND(SrcInitInputData%BladeRootOrientation,2) + i2_u = UBOUND(SrcInitInputData%BladeRootOrientation,2) + i3_l = LBOUND(SrcInitInputData%BladeRootOrientation,3) + i3_u = UBOUND(SrcInitInputData%BladeRootOrientation,3) + IF (.NOT. ALLOCATED(DstInitInputData%BladeRootOrientation)) THEN + ALLOCATE(DstInitInputData%BladeRootOrientation(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BladeRootOrientation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BladeRootOrientation = SrcInitInputData%BladeRootOrientation +ENDIF + DstInitInputData%UsePrimaryInputFile = SrcInitInputData%UsePrimaryInputFile + CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%PassedPrimaryInputData, DstInitInputData%PassedPrimaryInputData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_CopyInitInput + + SUBROUTINE AD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(AD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%BladeRootPosition)) THEN + DEALLOCATE(InitInputData%BladeRootPosition) +ENDIF +IF (ALLOCATED(InitInputData%BladeRootOrientation)) THEN + DEALLOCATE(InitInputData%BladeRootOrientation) +ENDIF + CALL NWTC_Library_Destroyfileinfotype( InitInputData%PassedPrimaryInputData, ErrStat, ErrMsg ) + END SUBROUTINE AD_DestroyInitInput + + SUBROUTINE AD_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(AD_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 = 'AD_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1 ! NumBlades + Re_BufSz = Re_BufSz + 1 ! Gravity + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + SIZE(InData%HubPosition) ! HubPosition + Db_BufSz = Db_BufSz + SIZE(InData%HubOrientation) ! HubOrientation + Int_BufSz = Int_BufSz + 1 ! BladeRootPosition allocated yes/no + IF ( ALLOCATED(InData%BladeRootPosition) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BladeRootPosition upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BladeRootPosition) ! BladeRootPosition + END IF + Int_BufSz = Int_BufSz + 1 ! BladeRootOrientation allocated yes/no + IF ( ALLOCATED(InData%BladeRootOrientation) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! BladeRootOrientation upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%BladeRootOrientation) ! BladeRootOrientation + END IF + Int_BufSz = Int_BufSz + 1 ! UsePrimaryInputFile + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PassedPrimaryInputData: size of buffers for each call to pack subtype + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedPrimaryInputData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedPrimaryInputData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PassedPrimaryInputData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PassedPrimaryInputData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PassedPrimaryInputData + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%HubPosition,1), UBOUND(InData%HubPosition,1) + ReKiBuf(Re_Xferred) = InData%HubPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%HubOrientation,2), UBOUND(InData%HubOrientation,2) + DO i1 = LBOUND(InData%HubOrientation,1), UBOUND(InData%HubOrientation,1) + DbKiBuf(Db_Xferred) = InData%HubOrientation(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%BladeRootPosition) ) 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%BladeRootPosition,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootPosition,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BladeRootPosition,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootPosition,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BladeRootPosition,2), UBOUND(InData%BladeRootPosition,2) + DO i1 = LBOUND(InData%BladeRootPosition,1), UBOUND(InData%BladeRootPosition,1) + ReKiBuf(Re_Xferred) = InData%BladeRootPosition(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BladeRootOrientation) ) 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%BladeRootOrientation,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootOrientation,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BladeRootOrientation,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootOrientation,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BladeRootOrientation,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootOrientation,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%BladeRootOrientation,3), UBOUND(InData%BladeRootOrientation,3) + DO i2 = LBOUND(InData%BladeRootOrientation,2), UBOUND(InData%BladeRootOrientation,2) + DO i1 = LBOUND(InData%BladeRootOrientation,1), UBOUND(InData%BladeRootOrientation,1) + DbKiBuf(Db_Xferred) = InData%BladeRootOrientation(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%UsePrimaryInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedPrimaryInputData, ErrStat2, ErrMsg2, OnlySize ) ! PassedPrimaryInputData + 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 AD_PackInitInput + + SUBROUTINE AD_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(AD_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 = 'AD_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%HubPosition,1) + i1_u = UBOUND(OutData%HubPosition,1) + DO i1 = LBOUND(OutData%HubPosition,1), UBOUND(OutData%HubPosition,1) + OutData%HubPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%HubOrientation,1) + i1_u = UBOUND(OutData%HubOrientation,1) + i2_l = LBOUND(OutData%HubOrientation,2) + i2_u = UBOUND(OutData%HubOrientation,2) + DO i2 = LBOUND(OutData%HubOrientation,2), UBOUND(OutData%HubOrientation,2) + DO i1 = LBOUND(OutData%HubOrientation,1), UBOUND(OutData%HubOrientation,1) + OutData%HubOrientation(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeRootPosition 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%BladeRootPosition)) DEALLOCATE(OutData%BladeRootPosition) + ALLOCATE(OutData%BladeRootPosition(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeRootPosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BladeRootPosition,2), UBOUND(OutData%BladeRootPosition,2) + DO i1 = LBOUND(OutData%BladeRootPosition,1), UBOUND(OutData%BladeRootPosition,1) + OutData%BladeRootPosition(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeRootOrientation 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%BladeRootOrientation)) DEALLOCATE(OutData%BladeRootOrientation) + ALLOCATE(OutData%BladeRootOrientation(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%BladeRootOrientation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%BladeRootOrientation,3), UBOUND(OutData%BladeRootOrientation,3) + DO i2 = LBOUND(OutData%BladeRootOrientation,2), UBOUND(OutData%BladeRootOrientation,2) + DO i1 = LBOUND(OutData%BladeRootOrientation,1), UBOUND(OutData%BladeRootOrientation,1) + OutData%BladeRootOrientation(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%UsePrimaryInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UsePrimaryInputFile) + 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%PassedPrimaryInputData, ErrStat2, ErrMsg2 ) ! PassedPrimaryInputData + 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 AD_UnPackInitInput + + SUBROUTINE AD_CopyBladePropsType( SrcBladePropsTypeData, DstBladePropsTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_BladePropsType), INTENT(IN) :: SrcBladePropsTypeData + TYPE(AD_BladePropsType), INTENT(INOUT) :: DstBladePropsTypeData + 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 = 'AD_CopyBladePropsType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladePropsTypeData%NumBlNds = SrcBladePropsTypeData%NumBlNds +IF (ALLOCATED(SrcBladePropsTypeData%BlSpn)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlSpn,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlSpn,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlSpn)) THEN + ALLOCATE(DstBladePropsTypeData%BlSpn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlSpn = SrcBladePropsTypeData%BlSpn +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlCrvAC)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlCrvAC,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlCrvAC,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlCrvAC)) THEN + ALLOCATE(DstBladePropsTypeData%BlCrvAC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlCrvAC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlCrvAC = SrcBladePropsTypeData%BlCrvAC +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlSwpAC)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlSwpAC,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlSwpAC,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlSwpAC)) THEN + ALLOCATE(DstBladePropsTypeData%BlSwpAC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlSwpAC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlSwpAC = SrcBladePropsTypeData%BlSwpAC +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlCrvAng)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlCrvAng,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlCrvAng,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlCrvAng)) THEN + ALLOCATE(DstBladePropsTypeData%BlCrvAng(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlCrvAng.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlCrvAng = SrcBladePropsTypeData%BlCrvAng +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlTwist)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlTwist,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlTwist,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlTwist)) THEN + ALLOCATE(DstBladePropsTypeData%BlTwist(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlTwist = SrcBladePropsTypeData%BlTwist +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlChord)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlChord,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlChord,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlChord)) THEN + ALLOCATE(DstBladePropsTypeData%BlChord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlChord = SrcBladePropsTypeData%BlChord +ENDIF +IF (ALLOCATED(SrcBladePropsTypeData%BlAFID)) THEN + i1_l = LBOUND(SrcBladePropsTypeData%BlAFID,1) + i1_u = UBOUND(SrcBladePropsTypeData%BlAFID,1) + IF (.NOT. ALLOCATED(DstBladePropsTypeData%BlAFID)) THEN + ALLOCATE(DstBladePropsTypeData%BlAFID(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladePropsTypeData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladePropsTypeData%BlAFID = SrcBladePropsTypeData%BlAFID +ENDIF + END SUBROUTINE AD_CopyBladePropsType + + SUBROUTINE AD_DestroyBladePropsType( BladePropsTypeData, ErrStat, ErrMsg ) + TYPE(AD_BladePropsType), INTENT(INOUT) :: BladePropsTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyBladePropsType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladePropsTypeData%BlSpn)) THEN + DEALLOCATE(BladePropsTypeData%BlSpn) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlCrvAC)) THEN + DEALLOCATE(BladePropsTypeData%BlCrvAC) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlSwpAC)) THEN + DEALLOCATE(BladePropsTypeData%BlSwpAC) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlCrvAng)) THEN + DEALLOCATE(BladePropsTypeData%BlCrvAng) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlTwist)) THEN + DEALLOCATE(BladePropsTypeData%BlTwist) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlChord)) THEN + DEALLOCATE(BladePropsTypeData%BlChord) +ENDIF +IF (ALLOCATED(BladePropsTypeData%BlAFID)) THEN + DEALLOCATE(BladePropsTypeData%BlAFID) +ENDIF + END SUBROUTINE AD_DestroyBladePropsType + + SUBROUTINE AD_PackBladePropsType( 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(AD_BladePropsType), 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 = 'AD_PackBladePropsType' + ! 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 ! NumBlNds + Int_BufSz = Int_BufSz + 1 ! BlSpn allocated yes/no + IF ( ALLOCATED(InData%BlSpn) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlSpn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlSpn) ! BlSpn + END IF + Int_BufSz = Int_BufSz + 1 ! BlCrvAC allocated yes/no + IF ( ALLOCATED(InData%BlCrvAC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlCrvAC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlCrvAC) ! BlCrvAC + END IF + Int_BufSz = Int_BufSz + 1 ! BlSwpAC allocated yes/no + IF ( ALLOCATED(InData%BlSwpAC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlSwpAC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlSwpAC) ! BlSwpAC + END IF + Int_BufSz = Int_BufSz + 1 ! BlCrvAng allocated yes/no + IF ( ALLOCATED(InData%BlCrvAng) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlCrvAng upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlCrvAng) ! BlCrvAng + END IF + Int_BufSz = Int_BufSz + 1 ! BlTwist allocated yes/no + IF ( ALLOCATED(InData%BlTwist) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlTwist upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlTwist) ! BlTwist + END IF + Int_BufSz = Int_BufSz + 1 ! BlChord allocated yes/no + IF ( ALLOCATED(InData%BlChord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlChord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlChord) ! BlChord + END IF + Int_BufSz = Int_BufSz + 1 ! BlAFID allocated yes/no + IF ( ALLOCATED(InData%BlAFID) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlAFID upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BlAFID) ! BlAFID + 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%NumBlNds + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlSpn) ) 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%BlSpn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSpn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlSpn,1), UBOUND(InData%BlSpn,1) + ReKiBuf(Re_Xferred) = InData%BlSpn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlCrvAC) ) 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%BlCrvAC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlCrvAC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlCrvAC,1), UBOUND(InData%BlCrvAC,1) + ReKiBuf(Re_Xferred) = InData%BlCrvAC(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlSwpAC) ) 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%BlSwpAC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlSwpAC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlSwpAC,1), UBOUND(InData%BlSwpAC,1) + ReKiBuf(Re_Xferred) = InData%BlSwpAC(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlCrvAng) ) 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%BlCrvAng,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlCrvAng,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlCrvAng,1), UBOUND(InData%BlCrvAng,1) + ReKiBuf(Re_Xferred) = InData%BlCrvAng(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlTwist) ) 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%BlTwist,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlTwist,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlTwist,1), UBOUND(InData%BlTwist,1) + ReKiBuf(Re_Xferred) = InData%BlTwist(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlChord) ) 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%BlChord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlChord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlChord,1), UBOUND(InData%BlChord,1) + ReKiBuf(Re_Xferred) = InData%BlChord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlAFID) ) 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%BlAFID,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAFID,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlAFID,1), UBOUND(InData%BlAFID,1) + IntKiBuf(Int_Xferred) = InData%BlAFID(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_PackBladePropsType + + SUBROUTINE AD_UnPackBladePropsType( 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(AD_BladePropsType), 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 = 'AD_UnPackBladePropsType' + ! 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%NumBlNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlSpn 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%BlSpn)) DEALLOCATE(OutData%BlSpn) + ALLOCATE(OutData%BlSpn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlSpn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlSpn,1), UBOUND(OutData%BlSpn,1) + OutData%BlSpn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlCrvAC 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%BlCrvAC)) DEALLOCATE(OutData%BlCrvAC) + ALLOCATE(OutData%BlCrvAC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlCrvAC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlCrvAC,1), UBOUND(OutData%BlCrvAC,1) + OutData%BlCrvAC(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlSwpAC 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%BlSwpAC)) DEALLOCATE(OutData%BlSwpAC) + ALLOCATE(OutData%BlSwpAC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlSwpAC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlSwpAC,1), UBOUND(OutData%BlSwpAC,1) + OutData%BlSwpAC(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlCrvAng 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%BlCrvAng)) DEALLOCATE(OutData%BlCrvAng) + ALLOCATE(OutData%BlCrvAng(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlCrvAng.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlCrvAng,1), UBOUND(OutData%BlCrvAng,1) + OutData%BlCrvAng(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlTwist 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%BlTwist)) DEALLOCATE(OutData%BlTwist) + ALLOCATE(OutData%BlTwist(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlTwist,1), UBOUND(OutData%BlTwist,1) + OutData%BlTwist(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlChord 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%BlChord)) DEALLOCATE(OutData%BlChord) + ALLOCATE(OutData%BlChord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlChord,1), UBOUND(OutData%BlChord,1) + OutData%BlChord(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlAFID 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%BlAFID)) DEALLOCATE(OutData%BlAFID) + ALLOCATE(OutData%BlAFID(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlAFID.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlAFID,1), UBOUND(OutData%BlAFID,1) + OutData%BlAFID(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_UnPackBladePropsType + + SUBROUTINE AD_CopyBladeShape( SrcBladeShapeData, DstBladeShapeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_BladeShape), INTENT(IN) :: SrcBladeShapeData + TYPE(AD_BladeShape), INTENT(INOUT) :: DstBladeShapeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_CopyBladeShape' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcBladeShapeData%AirfoilCoords)) THEN + i1_l = LBOUND(SrcBladeShapeData%AirfoilCoords,1) + i1_u = UBOUND(SrcBladeShapeData%AirfoilCoords,1) + i2_l = LBOUND(SrcBladeShapeData%AirfoilCoords,2) + i2_u = UBOUND(SrcBladeShapeData%AirfoilCoords,2) + i3_l = LBOUND(SrcBladeShapeData%AirfoilCoords,3) + i3_u = UBOUND(SrcBladeShapeData%AirfoilCoords,3) + IF (.NOT. ALLOCATED(DstBladeShapeData%AirfoilCoords)) THEN + ALLOCATE(DstBladeShapeData%AirfoilCoords(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeShapeData%AirfoilCoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeShapeData%AirfoilCoords = SrcBladeShapeData%AirfoilCoords +ENDIF + END SUBROUTINE AD_CopyBladeShape + + SUBROUTINE AD_DestroyBladeShape( BladeShapeData, ErrStat, ErrMsg ) + TYPE(AD_BladeShape), INTENT(INOUT) :: BladeShapeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyBladeShape' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladeShapeData%AirfoilCoords)) THEN + DEALLOCATE(BladeShapeData%AirfoilCoords) +ENDIF + END SUBROUTINE AD_DestroyBladeShape + + SUBROUTINE AD_PackBladeShape( 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(AD_BladeShape), 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 = 'AD_PackBladeShape' + ! 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 ! AirfoilCoords allocated yes/no + IF ( ALLOCATED(InData%AirfoilCoords) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AirfoilCoords upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AirfoilCoords) ! AirfoilCoords + 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%AirfoilCoords) ) 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%AirfoilCoords,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AirfoilCoords,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AirfoilCoords,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AirfoilCoords,3), UBOUND(InData%AirfoilCoords,3) + DO i2 = LBOUND(InData%AirfoilCoords,2), UBOUND(InData%AirfoilCoords,2) + DO i1 = LBOUND(InData%AirfoilCoords,1), UBOUND(InData%AirfoilCoords,1) + ReKiBuf(Re_Xferred) = InData%AirfoilCoords(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AD_PackBladeShape + + SUBROUTINE AD_UnPackBladeShape( 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(AD_BladeShape), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_UnPackBladeShape' + ! 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 ! AirfoilCoords 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%AirfoilCoords)) DEALLOCATE(OutData%AirfoilCoords) + ALLOCATE(OutData%AirfoilCoords(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%AirfoilCoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AirfoilCoords,3), UBOUND(OutData%AirfoilCoords,3) + DO i2 = LBOUND(OutData%AirfoilCoords,2), UBOUND(OutData%AirfoilCoords,2) + DO i1 = LBOUND(OutData%AirfoilCoords,1), UBOUND(OutData%AirfoilCoords,1) + OutData%AirfoilCoords(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AD_UnPackBladeShape + + SUBROUTINE AD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(AD_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 = 'AD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%AirDens = SrcInitOutputData%AirDens +IF (ALLOCATED(SrcInitOutputData%BladeShape)) THEN + i1_l = LBOUND(SrcInitOutputData%BladeShape,1) + i1_u = UBOUND(SrcInitOutputData%BladeShape,1) + IF (.NOT. ALLOCATED(DstInitOutputData%BladeShape)) THEN + ALLOCATE(DstInitOutputData%BladeShape(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%BladeShape.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitOutputData%BladeShape,1), UBOUND(SrcInitOutputData%BladeShape,1) + CALL AD_Copybladeshape( SrcInitOutputData%BladeShape(i1), DstInitOutputData%BladeShape(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%BladeProps)) THEN + i1_l = LBOUND(SrcInitOutputData%BladeProps,1) + i1_u = UBOUND(SrcInitOutputData%BladeProps,1) + IF (.NOT. ALLOCATED(DstInitOutputData%BladeProps)) THEN + ALLOCATE(DstInitOutputData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitOutputData%BladeProps,1), UBOUND(SrcInitOutputData%BladeProps,1) + CALL AD_Copybladepropstype( SrcInitOutputData%BladeProps(i1), DstInitOutputData%BladeProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%TwrElev)) THEN + i1_l = LBOUND(SrcInitOutputData%TwrElev,1) + i1_u = UBOUND(SrcInitOutputData%TwrElev,1) + IF (.NOT. ALLOCATED(DstInitOutputData%TwrElev)) THEN + ALLOCATE(DstInitOutputData%TwrElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%TwrElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%TwrElev = SrcInitOutputData%TwrElev +ENDIF +IF (ALLOCATED(SrcInitOutputData%TwrDiam)) THEN + i1_l = LBOUND(SrcInitOutputData%TwrDiam,1) + i1_u = UBOUND(SrcInitOutputData%TwrDiam,1) + IF (.NOT. ALLOCATED(DstInitOutputData%TwrDiam)) THEN + ALLOCATE(DstInitOutputData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%TwrDiam = SrcInitOutputData%TwrDiam +ENDIF + END SUBROUTINE AD_CopyInitOutput + + SUBROUTINE AD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(AD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%BladeShape)) THEN +DO i1 = LBOUND(InitOutputData%BladeShape,1), UBOUND(InitOutputData%BladeShape,1) + CALL AD_Destroybladeshape( InitOutputData%BladeShape(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitOutputData%BladeShape) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF +IF (ALLOCATED(InitOutputData%BladeProps)) THEN +DO i1 = LBOUND(InitOutputData%BladeProps,1), UBOUND(InitOutputData%BladeProps,1) + CALL AD_Destroybladepropstype( InitOutputData%BladeProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitOutputData%BladeProps) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF +IF (ALLOCATED(InitOutputData%TwrElev)) THEN + DEALLOCATE(InitOutputData%TwrElev) +ENDIF +IF (ALLOCATED(InitOutputData%TwrDiam)) THEN + DEALLOCATE(InitOutputData%TwrDiam) +ENDIF + END SUBROUTINE AD_DestroyInitOutput + + SUBROUTINE AD_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(AD_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 = 'AD_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + 1 ! AirDens + Int_BufSz = Int_BufSz + 1 ! BladeShape allocated yes/no + IF ( ALLOCATED(InData%BladeShape) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeShape upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeShape,1), UBOUND(InData%BladeShape,1) + Int_BufSz = Int_BufSz + 3 ! BladeShape: size of buffers for each call to pack subtype + CALL AD_Packbladeshape( Re_Buf, Db_Buf, Int_Buf, InData%BladeShape(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BladeShape + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeShape + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeShape + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeShape + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + END IF + Int_BufSz = Int_BufSz + 1 ! BladeProps allocated yes/no + IF ( ALLOCATED(InData%BladeProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeProps upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + Int_BufSz = Int_BufSz + 3 ! BladeProps: size of buffers for each call to pack subtype + CALL AD_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BladeProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF + Int_BufSz = Int_BufSz + 1 ! TwrElev allocated yes/no + IF ( ALLOCATED(InData%TwrElev) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrElev) ! TwrElev + END IF + Int_BufSz = Int_BufSz + 1 ! TwrDiam allocated yes/no + IF ( ALLOCATED(InData%TwrDiam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrDiam upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrDiam) ! TwrDiam + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BladeShape) ) 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%BladeShape,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeShape,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeShape,1), UBOUND(InData%BladeShape,1) + CALL AD_Packbladeshape( Re_Buf, Db_Buf, Int_Buf, InData%BladeShape(i1), ErrStat2, ErrMsg2, OnlySize ) ! BladeShape + 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%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) 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%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) 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%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BladeProps) ) 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%BladeProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + CALL AD_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! BladeProps + 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%DerivOrder_x) ) 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%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrElev) ) 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%TwrElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrElev,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrElev,1), UBOUND(InData%TwrElev,1) + ReKiBuf(Re_Xferred) = InData%TwrElev(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrDiam) ) 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%TwrDiam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrDiam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrDiam,1), UBOUND(InData%TwrDiam,1) + ReKiBuf(Re_Xferred) = InData%TwrDiam(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_PackInitOutput + + SUBROUTINE AD_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(AD_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 = 'AD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeShape 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%BladeShape)) DEALLOCATE(OutData%BladeShape) + ALLOCATE(OutData%BladeShape(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeShape.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeShape,1), UBOUND(OutData%BladeShape,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 AD_Unpackbladeshape( Re_Buf, Db_Buf, Int_Buf, OutData%BladeShape(i1), ErrStat2, ErrMsg2 ) ! BladeShape + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x 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%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x 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%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeProps 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%BladeProps)) DEALLOCATE(OutData%BladeProps) + ALLOCATE(OutData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeProps,1), UBOUND(OutData%BladeProps,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 AD_Unpackbladepropstype( Re_Buf, Db_Buf, Int_Buf, OutData%BladeProps(i1), ErrStat2, ErrMsg2 ) ! BladeProps + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x 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%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrElev 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%TwrElev)) DEALLOCATE(OutData%TwrElev) + ALLOCATE(OutData%TwrElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrElev,1), UBOUND(OutData%TwrElev,1) + OutData%TwrElev(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrDiam 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%TwrDiam)) DEALLOCATE(OutData%TwrDiam) + ALLOCATE(OutData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrDiam,1), UBOUND(OutData%TwrDiam,1) + OutData%TwrDiam(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_UnPackInitOutput + + SUBROUTINE AD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(AD_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'AD_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%Echo = SrcInputFileData%Echo + DstInputFileData%DTAero = SrcInputFileData%DTAero + DstInputFileData%WakeMod = SrcInputFileData%WakeMod + DstInputFileData%AFAeroMod = SrcInputFileData%AFAeroMod + DstInputFileData%TwrPotent = SrcInputFileData%TwrPotent + DstInputFileData%TwrShadow = SrcInputFileData%TwrShadow + DstInputFileData%TwrAero = SrcInputFileData%TwrAero + DstInputFileData%FrozenWake = SrcInputFileData%FrozenWake + DstInputFileData%CavitCheck = SrcInputFileData%CavitCheck + DstInputFileData%CompAA = SrcInputFileData%CompAA + DstInputFileData%AA_InputFile = SrcInputFileData%AA_InputFile +IF (ALLOCATED(SrcInputFileData%ADBlFile)) THEN + i1_l = LBOUND(SrcInputFileData%ADBlFile,1) + i1_u = UBOUND(SrcInputFileData%ADBlFile,1) + IF (.NOT. ALLOCATED(DstInputFileData%ADBlFile)) THEN + ALLOCATE(DstInputFileData%ADBlFile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ADBlFile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ADBlFile = SrcInputFileData%ADBlFile +ENDIF + DstInputFileData%AirDens = SrcInputFileData%AirDens + DstInputFileData%KinVisc = SrcInputFileData%KinVisc + DstInputFileData%Patm = SrcInputFileData%Patm + DstInputFileData%Pvap = SrcInputFileData%Pvap + DstInputFileData%FluidDepth = SrcInputFileData%FluidDepth + DstInputFileData%SpdSound = SrcInputFileData%SpdSound + DstInputFileData%SkewMod = SrcInputFileData%SkewMod + DstInputFileData%SkewModFactor = SrcInputFileData%SkewModFactor + DstInputFileData%TipLoss = SrcInputFileData%TipLoss + DstInputFileData%HubLoss = SrcInputFileData%HubLoss + DstInputFileData%TanInd = SrcInputFileData%TanInd + DstInputFileData%AIDrag = SrcInputFileData%AIDrag + DstInputFileData%TIDrag = SrcInputFileData%TIDrag + DstInputFileData%IndToler = SrcInputFileData%IndToler + DstInputFileData%MaxIter = SrcInputFileData%MaxIter + DstInputFileData%UAMod = SrcInputFileData%UAMod + DstInputFileData%FLookup = SrcInputFileData%FLookup + DstInputFileData%InCol_Alfa = SrcInputFileData%InCol_Alfa + DstInputFileData%InCol_Cl = SrcInputFileData%InCol_Cl + DstInputFileData%InCol_Cd = SrcInputFileData%InCol_Cd + DstInputFileData%InCol_Cm = SrcInputFileData%InCol_Cm + DstInputFileData%InCol_Cpmin = SrcInputFileData%InCol_Cpmin + DstInputFileData%AFTabMod = SrcInputFileData%AFTabMod + DstInputFileData%NumAFfiles = SrcInputFileData%NumAFfiles + DstInputFileData%FVWFileName = SrcInputFileData%FVWFileName +IF (ALLOCATED(SrcInputFileData%AFNames)) THEN + i1_l = LBOUND(SrcInputFileData%AFNames,1) + i1_u = UBOUND(SrcInputFileData%AFNames,1) + IF (.NOT. ALLOCATED(DstInputFileData%AFNames)) THEN + ALLOCATE(DstInputFileData%AFNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%AFNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%AFNames = SrcInputFileData%AFNames +ENDIF + DstInputFileData%UseBlCm = SrcInputFileData%UseBlCm +IF (ALLOCATED(SrcInputFileData%BladeProps)) THEN + i1_l = LBOUND(SrcInputFileData%BladeProps,1) + i1_u = UBOUND(SrcInputFileData%BladeProps,1) + IF (.NOT. ALLOCATED(DstInputFileData%BladeProps)) THEN + ALLOCATE(DstInputFileData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputFileData%BladeProps,1), UBOUND(SrcInputFileData%BladeProps,1) + CALL AD_Copybladepropstype( SrcInputFileData%BladeProps(i1), DstInputFileData%BladeProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInputFileData%NumTwrNds = SrcInputFileData%NumTwrNds +IF (ALLOCATED(SrcInputFileData%TwrElev)) THEN + i1_l = LBOUND(SrcInputFileData%TwrElev,1) + i1_u = UBOUND(SrcInputFileData%TwrElev,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwrElev)) THEN + ALLOCATE(DstInputFileData%TwrElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwrElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwrElev = SrcInputFileData%TwrElev +ENDIF +IF (ALLOCATED(SrcInputFileData%TwrDiam)) THEN + i1_l = LBOUND(SrcInputFileData%TwrDiam,1) + i1_u = UBOUND(SrcInputFileData%TwrDiam,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwrDiam)) THEN + ALLOCATE(DstInputFileData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwrDiam = SrcInputFileData%TwrDiam +ENDIF +IF (ALLOCATED(SrcInputFileData%TwrCd)) THEN + i1_l = LBOUND(SrcInputFileData%TwrCd,1) + i1_u = UBOUND(SrcInputFileData%TwrCd,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwrCd)) THEN + ALLOCATE(DstInputFileData%TwrCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwrCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwrCd = SrcInputFileData%TwrCd +ENDIF +IF (ALLOCATED(SrcInputFileData%TwrTI)) THEN + i1_l = LBOUND(SrcInputFileData%TwrTI,1) + i1_u = UBOUND(SrcInputFileData%TwrTI,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwrTI)) THEN + ALLOCATE(DstInputFileData%TwrTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwrTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwrTI = SrcInputFileData%TwrTI +ENDIF + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%NBlOuts = SrcInputFileData%NBlOuts + DstInputFileData%BlOutNd = SrcInputFileData%BlOutNd + DstInputFileData%NTwOuts = SrcInputFileData%NTwOuts + DstInputFileData%TwOutNd = SrcInputFileData%TwOutNd + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + DstInputFileData%tau1_const = SrcInputFileData%tau1_const + DstInputFileData%DBEMT_Mod = SrcInputFileData%DBEMT_Mod + DstInputFileData%BldNd_NumOuts = SrcInputFileData%BldNd_NumOuts +IF (ALLOCATED(SrcInputFileData%BldNd_OutList)) THEN + i1_l = LBOUND(SrcInputFileData%BldNd_OutList,1) + i1_u = UBOUND(SrcInputFileData%BldNd_OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%BldNd_OutList)) THEN + ALLOCATE(DstInputFileData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BldNd_OutList = SrcInputFileData%BldNd_OutList +ENDIF + DstInputFileData%BldNd_BlOutNd_Str = SrcInputFileData%BldNd_BlOutNd_Str + DstInputFileData%BldNd_BladesOut = SrcInputFileData%BldNd_BladesOut + END SUBROUTINE AD_CopyInputFile + + SUBROUTINE AD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(AD_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%ADBlFile)) THEN + DEALLOCATE(InputFileData%ADBlFile) +ENDIF +IF (ALLOCATED(InputFileData%AFNames)) THEN + DEALLOCATE(InputFileData%AFNames) +ENDIF +IF (ALLOCATED(InputFileData%BladeProps)) THEN +DO i1 = LBOUND(InputFileData%BladeProps,1), UBOUND(InputFileData%BladeProps,1) + CALL AD_Destroybladepropstype( InputFileData%BladeProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputFileData%BladeProps) +ENDIF +IF (ALLOCATED(InputFileData%TwrElev)) THEN + DEALLOCATE(InputFileData%TwrElev) +ENDIF +IF (ALLOCATED(InputFileData%TwrDiam)) THEN + DEALLOCATE(InputFileData%TwrDiam) +ENDIF +IF (ALLOCATED(InputFileData%TwrCd)) THEN + DEALLOCATE(InputFileData%TwrCd) +ENDIF +IF (ALLOCATED(InputFileData%TwrTI)) THEN + DEALLOCATE(InputFileData%TwrTI) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF +IF (ALLOCATED(InputFileData%BldNd_OutList)) THEN + DEALLOCATE(InputFileData%BldNd_OutList) +ENDIF + END SUBROUTINE AD_DestroyInputFile + + SUBROUTINE AD_PackInputFile( 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(AD_InputFile), 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 = 'AD_PackInputFile' + ! 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 ! Echo + Db_BufSz = Db_BufSz + 1 ! DTAero + Int_BufSz = Int_BufSz + 1 ! WakeMod + Int_BufSz = Int_BufSz + 1 ! AFAeroMod + Int_BufSz = Int_BufSz + 1 ! TwrPotent + Int_BufSz = Int_BufSz + 1 ! TwrShadow + Int_BufSz = Int_BufSz + 1 ! TwrAero + Int_BufSz = Int_BufSz + 1 ! FrozenWake + Int_BufSz = Int_BufSz + 1 ! CavitCheck + Int_BufSz = Int_BufSz + 1 ! CompAA + Int_BufSz = Int_BufSz + 1*LEN(InData%AA_InputFile) ! AA_InputFile + Int_BufSz = Int_BufSz + 1 ! ADBlFile allocated yes/no + IF ( ALLOCATED(InData%ADBlFile) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ADBlFile upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ADBlFile)*LEN(InData%ADBlFile) ! ADBlFile + END IF + Re_BufSz = Re_BufSz + 1 ! AirDens + Re_BufSz = Re_BufSz + 1 ! KinVisc + Re_BufSz = Re_BufSz + 1 ! Patm + Re_BufSz = Re_BufSz + 1 ! Pvap + Re_BufSz = Re_BufSz + 1 ! FluidDepth + Re_BufSz = Re_BufSz + 1 ! SpdSound + Int_BufSz = Int_BufSz + 1 ! SkewMod + Re_BufSz = Re_BufSz + 1 ! SkewModFactor + Int_BufSz = Int_BufSz + 1 ! TipLoss + Int_BufSz = Int_BufSz + 1 ! HubLoss + Int_BufSz = Int_BufSz + 1 ! TanInd + Int_BufSz = Int_BufSz + 1 ! AIDrag + Int_BufSz = Int_BufSz + 1 ! TIDrag + Re_BufSz = Re_BufSz + 1 ! IndToler + Re_BufSz = Re_BufSz + 1 ! MaxIter + Int_BufSz = Int_BufSz + 1 ! UAMod + Int_BufSz = Int_BufSz + 1 ! FLookup + Re_BufSz = Re_BufSz + 1 ! InCol_Alfa + Re_BufSz = Re_BufSz + 1 ! InCol_Cl + Re_BufSz = Re_BufSz + 1 ! InCol_Cd + Re_BufSz = Re_BufSz + 1 ! InCol_Cm + Re_BufSz = Re_BufSz + 1 ! InCol_Cpmin + Int_BufSz = Int_BufSz + 1 ! AFTabMod + Int_BufSz = Int_BufSz + 1 ! NumAFfiles + Int_BufSz = Int_BufSz + 1*LEN(InData%FVWFileName) ! FVWFileName + Int_BufSz = Int_BufSz + 1 ! AFNames allocated yes/no + IF ( ALLOCATED(InData%AFNames) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AFNames upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AFNames)*LEN(InData%AFNames) ! AFNames + END IF + Int_BufSz = Int_BufSz + 1 ! UseBlCm + Int_BufSz = Int_BufSz + 1 ! BladeProps allocated yes/no + IF ( ALLOCATED(InData%BladeProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeProps upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + Int_BufSz = Int_BufSz + 3 ! BladeProps: size of buffers for each call to pack subtype + CALL AD_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BladeProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumTwrNds + Int_BufSz = Int_BufSz + 1 ! TwrElev allocated yes/no + IF ( ALLOCATED(InData%TwrElev) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrElev) ! TwrElev + END IF + Int_BufSz = Int_BufSz + 1 ! TwrDiam allocated yes/no + IF ( ALLOCATED(InData%TwrDiam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrDiam upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrDiam) ! TwrDiam + END IF + Int_BufSz = Int_BufSz + 1 ! TwrCd allocated yes/no + IF ( ALLOCATED(InData%TwrCd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrCd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrCd) ! TwrCd + END IF + Int_BufSz = Int_BufSz + 1 ! TwrTI allocated yes/no + IF ( ALLOCATED(InData%TwrTI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrTI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrTI) ! TwrTI + END IF + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! NBlOuts + Int_BufSz = Int_BufSz + SIZE(InData%BlOutNd) ! BlOutNd + Int_BufSz = Int_BufSz + 1 ! NTwOuts + Int_BufSz = Int_BufSz + SIZE(InData%TwOutNd) ! TwOutNd + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + END IF + Re_BufSz = Re_BufSz + 1 ! tau1_const + Int_BufSz = Int_BufSz + 1 ! DBEMT_Mod + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutList allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_OutList)*LEN(InData%BldNd_OutList) ! BldNd_OutList + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%BldNd_BlOutNd_Str) ! BldNd_BlOutNd_Str + Int_BufSz = Int_BufSz + 1 ! BldNd_BladesOut + 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%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTAero + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WakeMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AFAeroMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrPotent + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrShadow + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrAero, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FrozenWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CavitCheck, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompAA, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%AA_InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%AA_InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%ADBlFile) ) 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%ADBlFile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADBlFile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ADBlFile,1), UBOUND(InData%ADBlFile,1) + DO I = 1, LEN(InData%ADBlFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%ADBlFile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Patm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Pvap + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FluidDepth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdSound + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SkewMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SkewModFactor + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TipLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%HubLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TanInd, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%AIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%IndToler + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MaxIter + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UAMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FLookup, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InCol_Alfa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InCol_Cl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InCol_Cd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InCol_Cm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InCol_Cpmin + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AFTabMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumAFfiles + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%FVWFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%FVWFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%AFNames) ) 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%AFNames,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFNames,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AFNames,1), UBOUND(InData%AFNames,1) + DO I = 1, LEN(InData%AFNames) + IntKiBuf(Int_Xferred) = ICHAR(InData%AFNames(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseBlCm, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BladeProps) ) 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%BladeProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeProps,1), UBOUND(InData%BladeProps,1) + CALL AD_Packbladepropstype( Re_Buf, Db_Buf, Int_Buf, InData%BladeProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! BladeProps + 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 + IntKiBuf(Int_Xferred) = InData%NumTwrNds + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TwrElev) ) 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%TwrElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrElev,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrElev,1), UBOUND(InData%TwrElev,1) + ReKiBuf(Re_Xferred) = InData%TwrElev(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrDiam) ) 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%TwrDiam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrDiam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrDiam,1), UBOUND(InData%TwrDiam,1) + ReKiBuf(Re_Xferred) = InData%TwrDiam(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrCd) ) 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%TwrCd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrCd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrCd,1), UBOUND(InData%TwrCd,1) + ReKiBuf(Re_Xferred) = InData%TwrCd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrTI) ) 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%TwrTI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrTI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrTI,1), UBOUND(InData%TwrTI,1) + ReKiBuf(Re_Xferred) = InData%TwrTI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBlOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%BlOutNd,1), UBOUND(InData%BlOutNd,1) + IntKiBuf(Int_Xferred) = InData%BlOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NTwOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TwOutNd,1), UBOUND(InData%TwOutNd,1) + IntKiBuf(Int_Xferred) = InData%TwOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + ReKiBuf(Re_Xferred) = InData%tau1_const + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DBEMT_Mod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_OutList) ) 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%BldNd_OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutList,1), UBOUND(InData%BldNd_OutList,1) + DO I = 1, LEN(InData%BldNd_OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%BldNd_BlOutNd_Str) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_BlOutNd_Str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%BldNd_BladesOut + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_PackInputFile + + SUBROUTINE AD_UnPackInputFile( 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(AD_InputFile), 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 = 'AD_UnPackInputFile' + ! 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%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 + OutData%DTAero = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WakeMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AFAeroMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrPotent = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrShadow = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrAero = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrAero) + Int_Xferred = Int_Xferred + 1 + OutData%FrozenWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%FrozenWake) + Int_Xferred = Int_Xferred + 1 + OutData%CavitCheck = TRANSFER(IntKiBuf(Int_Xferred), OutData%CavitCheck) + Int_Xferred = Int_Xferred + 1 + OutData%CompAA = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompAA) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%AA_InputFile) + OutData%AA_InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ADBlFile 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%ADBlFile)) DEALLOCATE(OutData%ADBlFile) + ALLOCATE(OutData%ADBlFile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ADBlFile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ADBlFile,1), UBOUND(OutData%ADBlFile,1) + DO I = 1, LEN(OutData%ADBlFile) + OutData%ADBlFile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Patm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Pvap = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FluidDepth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpdSound = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SkewMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SkewModFactor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TipLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%TipLoss) + Int_Xferred = Int_Xferred + 1 + OutData%HubLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%HubLoss) + Int_Xferred = Int_Xferred + 1 + OutData%TanInd = TRANSFER(IntKiBuf(Int_Xferred), OutData%TanInd) + Int_Xferred = Int_Xferred + 1 + OutData%AIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%AIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%TIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%TIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%IndToler = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MaxIter = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UAMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FLookup = TRANSFER(IntKiBuf(Int_Xferred), OutData%FLookup) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Alfa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InCol_Cl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InCol_Cd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InCol_Cm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InCol_Cpmin = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AFTabMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumAFfiles = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%FVWFileName) + OutData%FVWFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFNames 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%AFNames)) DEALLOCATE(OutData%AFNames) + ALLOCATE(OutData%AFNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AFNames,1), UBOUND(OutData%AFNames,1) + DO I = 1, LEN(OutData%AFNames) + OutData%AFNames(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%UseBlCm = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseBlCm) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeProps 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%BladeProps)) DEALLOCATE(OutData%BladeProps) + ALLOCATE(OutData%BladeProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeProps,1), UBOUND(OutData%BladeProps,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 AD_Unpackbladepropstype( Re_Buf, Db_Buf, Int_Buf, OutData%BladeProps(i1), ErrStat2, ErrMsg2 ) ! BladeProps + 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 DO + END IF + OutData%NumTwrNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrElev 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%TwrElev)) DEALLOCATE(OutData%TwrElev) + ALLOCATE(OutData%TwrElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrElev,1), UBOUND(OutData%TwrElev,1) + OutData%TwrElev(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrDiam 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%TwrDiam)) DEALLOCATE(OutData%TwrDiam) + ALLOCATE(OutData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrDiam,1), UBOUND(OutData%TwrDiam,1) + OutData%TwrDiam(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrCd 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%TwrCd)) DEALLOCATE(OutData%TwrCd) + ALLOCATE(OutData%TwrCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrCd,1), UBOUND(OutData%TwrCd,1) + OutData%TwrCd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrTI 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%TwrTI)) DEALLOCATE(OutData%TwrTI) + ALLOCATE(OutData%TwrTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrTI,1), UBOUND(OutData%TwrTI,1) + OutData%TwrTI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%NBlOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%BlOutNd,1) + i1_u = UBOUND(OutData%BlOutNd,1) + DO i1 = LBOUND(OutData%BlOutNd,1), UBOUND(OutData%BlOutNd,1) + OutData%BlOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NTwOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TwOutNd,1) + i1_u = UBOUND(OutData%TwOutNd,1) + DO i1 = LBOUND(OutData%TwOutNd,1), UBOUND(OutData%TwOutNd,1) + OutData%TwOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%tau1_const = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DBEMT_Mod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutList 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%BldNd_OutList)) DEALLOCATE(OutData%BldNd_OutList) + ALLOCATE(OutData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutList,1), UBOUND(OutData%BldNd_OutList,1) + DO I = 1, LEN(OutData%BldNd_OutList) + OutData%BldNd_OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%BldNd_BlOutNd_Str) + OutData%BldNd_BlOutNd_Str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%BldNd_BladesOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_UnPackInputFile + + SUBROUTINE AD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(AD_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 = 'AD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_CopyContState( SrcContStateData%BEMT, DstContStateData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyContState( SrcContStateData%FVW, DstContStateData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyContState( SrcContStateData%AA, DstContStateData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_CopyContState + + SUBROUTINE AD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(AD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_DestroyContState( ContStateData%BEMT, ErrStat, ErrMsg ) + CALL FVW_DestroyContState( ContStateData%FVW, ErrStat, ErrMsg ) + CALL AA_DestroyContState( ContStateData%AA, ErrStat, ErrMsg ) + END SUBROUTINE AD_DestroyContState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + 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 BEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 FVW_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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 AA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 AD_PackContState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + 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 BEMT_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 FVW_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 AA_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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 AD_UnPackContState + + SUBROUTINE AD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(AD_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 = 'AD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_CopyDiscState( SrcDiscStateData%BEMT, DstDiscStateData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyDiscState( SrcDiscStateData%FVW, DstDiscStateData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyDiscState( SrcDiscStateData%AA, DstDiscStateData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_CopyDiscState + + SUBROUTINE AD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(AD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_DestroyDiscState( DiscStateData%BEMT, ErrStat, ErrMsg ) + CALL FVW_DestroyDiscState( DiscStateData%FVW, ErrStat, ErrMsg ) + CALL AA_DestroyDiscState( DiscStateData%AA, ErrStat, ErrMsg ) + END SUBROUTINE AD_DestroyDiscState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + 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 BEMT_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 FVW_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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 AA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 AD_PackDiscState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + 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 BEMT_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 FVW_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 AA_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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 AD_UnPackDiscState + + SUBROUTINE AD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(AD_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 = 'AD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_CopyConstrState( SrcConstrStateData%BEMT, DstConstrStateData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyConstrState( SrcConstrStateData%FVW, DstConstrStateData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyConstrState( SrcConstrStateData%AA, DstConstrStateData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_CopyConstrState + + SUBROUTINE AD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(AD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_DestroyConstrState( ConstrStateData%BEMT, ErrStat, ErrMsg ) + CALL FVW_DestroyConstrState( ConstrStateData%FVW, ErrStat, ErrMsg ) + CALL AA_DestroyConstrState( ConstrStateData%AA, ErrStat, ErrMsg ) + END SUBROUTINE AD_DestroyConstrState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + 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 BEMT_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 FVW_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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 AA_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 AD_PackConstrState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + 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 BEMT_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 FVW_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 AA_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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 AD_UnPackConstrState + + SUBROUTINE AD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(AD_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) :: 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 = 'AD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_CopyOtherState( SrcOtherStateData%BEMT, DstOtherStateData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyOtherState( SrcOtherStateData%FVW, DstOtherStateData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOtherStateData%WakeLocationPoints)) THEN + i1_l = LBOUND(SrcOtherStateData%WakeLocationPoints,1) + i1_u = UBOUND(SrcOtherStateData%WakeLocationPoints,1) + i2_l = LBOUND(SrcOtherStateData%WakeLocationPoints,2) + i2_u = UBOUND(SrcOtherStateData%WakeLocationPoints,2) + IF (.NOT. ALLOCATED(DstOtherStateData%WakeLocationPoints)) THEN + ALLOCATE(DstOtherStateData%WakeLocationPoints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%WakeLocationPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%WakeLocationPoints = SrcOtherStateData%WakeLocationPoints +ENDIF + CALL AA_CopyOtherState( SrcOtherStateData%AA, DstOtherStateData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD_CopyOtherState + + SUBROUTINE AD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(AD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_DestroyOtherState( OtherStateData%BEMT, ErrStat, ErrMsg ) + CALL FVW_DestroyOtherState( OtherStateData%FVW, ErrStat, ErrMsg ) +IF (ALLOCATED(OtherStateData%WakeLocationPoints)) THEN + DEALLOCATE(OtherStateData%WakeLocationPoints) +ENDIF + CALL AA_DestroyOtherState( OtherStateData%AA, ErrStat, ErrMsg ) + END SUBROUTINE AD_DestroyOtherState + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! WakeLocationPoints allocated yes/no + IF ( ALLOCATED(InData%WakeLocationPoints) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WakeLocationPoints upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WakeLocationPoints) ! WakeLocationPoints + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + 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 BEMT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 FVW_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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%WakeLocationPoints) ) 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%WakeLocationPoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WakeLocationPoints,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WakeLocationPoints,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WakeLocationPoints,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WakeLocationPoints,2), UBOUND(InData%WakeLocationPoints,2) + DO i1 = LBOUND(InData%WakeLocationPoints,1), UBOUND(InData%WakeLocationPoints,1) + ReKiBuf(Re_Xferred) = InData%WakeLocationPoints(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + CALL AA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 AD_PackOtherState + + SUBROUTINE AD_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(AD_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) :: 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 = 'AD_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 + 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 BEMT_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 FVW_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 ! WakeLocationPoints 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%WakeLocationPoints)) DEALLOCATE(OutData%WakeLocationPoints) + ALLOCATE(OutData%WakeLocationPoints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WakeLocationPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WakeLocationPoints,2), UBOUND(OutData%WakeLocationPoints,2) + DO i1 = LBOUND(OutData%WakeLocationPoints,1), UBOUND(OutData%WakeLocationPoints,1) + OutData%WakeLocationPoints(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 AA_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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 AD_UnPackOtherState + + SUBROUTINE AD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_MiscVarType), INTENT(INOUT) :: SrcMiscData + TYPE(AD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_CopyMisc( SrcMiscData%BEMT, DstMiscData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL BEMT_CopyOutput( SrcMiscData%BEMT_y, DstMiscData%BEMT_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DO i1 = LBOUND(SrcMiscData%BEMT_u,1), UBOUND(SrcMiscData%BEMT_u,1) + CALL BEMT_CopyInput( SrcMiscData%BEMT_u(i1), DstMiscData%BEMT_u(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL FVW_CopyMisc( SrcMiscData%FVW, DstMiscData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyOutput( SrcMiscData%FVW_y, DstMiscData%FVW_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMiscData%FVW_u)) THEN + i1_l = LBOUND(SrcMiscData%FVW_u,1) + i1_u = UBOUND(SrcMiscData%FVW_u,1) + IF (.NOT. ALLOCATED(DstMiscData%FVW_u)) THEN + ALLOCATE(DstMiscData%FVW_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FVW_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%FVW_u,1), UBOUND(SrcMiscData%FVW_u,1) + CALL FVW_CopyInput( SrcMiscData%FVW_u(i1), DstMiscData%FVW_u(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL AA_CopyMisc( SrcMiscData%AA, DstMiscData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyOutput( SrcMiscData%AA_y, DstMiscData%AA_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyInput( SrcMiscData%AA_u, DstMiscData%AA_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMiscData%DisturbedInflow)) THEN + i1_l = LBOUND(SrcMiscData%DisturbedInflow,1) + i1_u = UBOUND(SrcMiscData%DisturbedInflow,1) + i2_l = LBOUND(SrcMiscData%DisturbedInflow,2) + i2_u = UBOUND(SrcMiscData%DisturbedInflow,2) + i3_l = LBOUND(SrcMiscData%DisturbedInflow,3) + i3_u = UBOUND(SrcMiscData%DisturbedInflow,3) + IF (.NOT. ALLOCATED(DstMiscData%DisturbedInflow)) THEN + ALLOCATE(DstMiscData%DisturbedInflow(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%DisturbedInflow.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DisturbedInflow = SrcMiscData%DisturbedInflow +ENDIF +IF (ALLOCATED(SrcMiscData%WithoutSweepPitchTwist)) THEN + i1_l = LBOUND(SrcMiscData%WithoutSweepPitchTwist,1) + i1_u = UBOUND(SrcMiscData%WithoutSweepPitchTwist,1) + i2_l = LBOUND(SrcMiscData%WithoutSweepPitchTwist,2) + i2_u = UBOUND(SrcMiscData%WithoutSweepPitchTwist,2) + i3_l = LBOUND(SrcMiscData%WithoutSweepPitchTwist,3) + i3_u = UBOUND(SrcMiscData%WithoutSweepPitchTwist,3) + i4_l = LBOUND(SrcMiscData%WithoutSweepPitchTwist,4) + i4_u = UBOUND(SrcMiscData%WithoutSweepPitchTwist,4) + IF (.NOT. ALLOCATED(DstMiscData%WithoutSweepPitchTwist)) THEN + ALLOCATE(DstMiscData%WithoutSweepPitchTwist(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 DstMiscData%WithoutSweepPitchTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%WithoutSweepPitchTwist = SrcMiscData%WithoutSweepPitchTwist +ENDIF +IF (ALLOCATED(SrcMiscData%AllOuts)) THEN + i1_l = LBOUND(SrcMiscData%AllOuts,1) + i1_u = UBOUND(SrcMiscData%AllOuts,1) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF +IF (ALLOCATED(SrcMiscData%W_Twr)) THEN + i1_l = LBOUND(SrcMiscData%W_Twr,1) + i1_u = UBOUND(SrcMiscData%W_Twr,1) + IF (.NOT. ALLOCATED(DstMiscData%W_Twr)) THEN + ALLOCATE(DstMiscData%W_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%W_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%W_Twr = SrcMiscData%W_Twr +ENDIF +IF (ALLOCATED(SrcMiscData%X_Twr)) THEN + i1_l = LBOUND(SrcMiscData%X_Twr,1) + i1_u = UBOUND(SrcMiscData%X_Twr,1) + IF (.NOT. ALLOCATED(DstMiscData%X_Twr)) THEN + ALLOCATE(DstMiscData%X_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%X_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%X_Twr = SrcMiscData%X_Twr +ENDIF +IF (ALLOCATED(SrcMiscData%Y_Twr)) THEN + i1_l = LBOUND(SrcMiscData%Y_Twr,1) + i1_u = UBOUND(SrcMiscData%Y_Twr,1) + IF (.NOT. ALLOCATED(DstMiscData%Y_Twr)) THEN + ALLOCATE(DstMiscData%Y_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Y_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Y_Twr = SrcMiscData%Y_Twr +ENDIF +IF (ALLOCATED(SrcMiscData%Curve)) THEN + i1_l = LBOUND(SrcMiscData%Curve,1) + i1_u = UBOUND(SrcMiscData%Curve,1) + i2_l = LBOUND(SrcMiscData%Curve,2) + i2_u = UBOUND(SrcMiscData%Curve,2) + IF (.NOT. ALLOCATED(DstMiscData%Curve)) THEN + ALLOCATE(DstMiscData%Curve(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Curve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Curve = SrcMiscData%Curve +ENDIF +IF (ALLOCATED(SrcMiscData%TwrClrnc)) THEN + i1_l = LBOUND(SrcMiscData%TwrClrnc,1) + i1_u = UBOUND(SrcMiscData%TwrClrnc,1) + i2_l = LBOUND(SrcMiscData%TwrClrnc,2) + i2_u = UBOUND(SrcMiscData%TwrClrnc,2) + IF (.NOT. ALLOCATED(DstMiscData%TwrClrnc)) THEN + ALLOCATE(DstMiscData%TwrClrnc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%TwrClrnc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%TwrClrnc = SrcMiscData%TwrClrnc +ENDIF +IF (ALLOCATED(SrcMiscData%X)) THEN + i1_l = LBOUND(SrcMiscData%X,1) + i1_u = UBOUND(SrcMiscData%X,1) + i2_l = LBOUND(SrcMiscData%X,2) + i2_u = UBOUND(SrcMiscData%X,2) + IF (.NOT. ALLOCATED(DstMiscData%X)) THEN + ALLOCATE(DstMiscData%X(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%X.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%X = SrcMiscData%X +ENDIF +IF (ALLOCATED(SrcMiscData%Y)) THEN + i1_l = LBOUND(SrcMiscData%Y,1) + i1_u = UBOUND(SrcMiscData%Y,1) + i2_l = LBOUND(SrcMiscData%Y,2) + i2_u = UBOUND(SrcMiscData%Y,2) + IF (.NOT. ALLOCATED(DstMiscData%Y)) THEN + ALLOCATE(DstMiscData%Y(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Y = SrcMiscData%Y +ENDIF +IF (ALLOCATED(SrcMiscData%M)) THEN + i1_l = LBOUND(SrcMiscData%M,1) + i1_u = UBOUND(SrcMiscData%M,1) + i2_l = LBOUND(SrcMiscData%M,2) + i2_u = UBOUND(SrcMiscData%M,2) + IF (.NOT. ALLOCATED(DstMiscData%M)) THEN + ALLOCATE(DstMiscData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%M = SrcMiscData%M +ENDIF + DstMiscData%V_DiskAvg = SrcMiscData%V_DiskAvg + DstMiscData%hub_theta_x_root = SrcMiscData%hub_theta_x_root + DstMiscData%V_dot_x = SrcMiscData%V_dot_x + CALL MeshCopy( SrcMiscData%HubLoad, DstMiscData%HubLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMiscData%B_L_2_H_P)) THEN + i1_l = LBOUND(SrcMiscData%B_L_2_H_P,1) + i1_u = UBOUND(SrcMiscData%B_L_2_H_P,1) + IF (.NOT. ALLOCATED(DstMiscData%B_L_2_H_P)) THEN + ALLOCATE(DstMiscData%B_L_2_H_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%B_L_2_H_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%B_L_2_H_P,1), UBOUND(SrcMiscData%B_L_2_H_P,1) + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%B_L_2_H_P(i1), DstMiscData%B_L_2_H_P(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%SigmaCavitCrit)) THEN + i1_l = LBOUND(SrcMiscData%SigmaCavitCrit,1) + i1_u = UBOUND(SrcMiscData%SigmaCavitCrit,1) + i2_l = LBOUND(SrcMiscData%SigmaCavitCrit,2) + i2_u = UBOUND(SrcMiscData%SigmaCavitCrit,2) + IF (.NOT. ALLOCATED(DstMiscData%SigmaCavitCrit)) THEN + ALLOCATE(DstMiscData%SigmaCavitCrit(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SigmaCavitCrit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SigmaCavitCrit = SrcMiscData%SigmaCavitCrit +ENDIF +IF (ALLOCATED(SrcMiscData%SigmaCavit)) THEN + i1_l = LBOUND(SrcMiscData%SigmaCavit,1) + i1_u = UBOUND(SrcMiscData%SigmaCavit,1) + i2_l = LBOUND(SrcMiscData%SigmaCavit,2) + i2_u = UBOUND(SrcMiscData%SigmaCavit,2) + IF (.NOT. ALLOCATED(DstMiscData%SigmaCavit)) THEN + ALLOCATE(DstMiscData%SigmaCavit(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SigmaCavit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SigmaCavit = SrcMiscData%SigmaCavit +ENDIF +IF (ALLOCATED(SrcMiscData%CavitWarnSet)) THEN + i1_l = LBOUND(SrcMiscData%CavitWarnSet,1) + i1_u = UBOUND(SrcMiscData%CavitWarnSet,1) + i2_l = LBOUND(SrcMiscData%CavitWarnSet,2) + i2_u = UBOUND(SrcMiscData%CavitWarnSet,2) + IF (.NOT. ALLOCATED(DstMiscData%CavitWarnSet)) THEN + ALLOCATE(DstMiscData%CavitWarnSet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CavitWarnSet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CavitWarnSet = SrcMiscData%CavitWarnSet +ENDIF + END SUBROUTINE AD_CopyMisc + + SUBROUTINE AD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(AD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL BEMT_DestroyMisc( MiscData%BEMT, ErrStat, ErrMsg ) + CALL BEMT_DestroyOutput( MiscData%BEMT_y, ErrStat, ErrMsg ) +DO i1 = LBOUND(MiscData%BEMT_u,1), UBOUND(MiscData%BEMT_u,1) + CALL BEMT_DestroyInput( MiscData%BEMT_u(i1), ErrStat, ErrMsg ) +ENDDO + CALL FVW_DestroyMisc( MiscData%FVW, ErrStat, ErrMsg ) + CALL FVW_DestroyOutput( MiscData%FVW_y, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%FVW_u)) THEN +DO i1 = LBOUND(MiscData%FVW_u,1), UBOUND(MiscData%FVW_u,1) + CALL FVW_DestroyInput( MiscData%FVW_u(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%FVW_u) +ENDIF + CALL AA_DestroyMisc( MiscData%AA, ErrStat, ErrMsg ) + CALL AA_DestroyOutput( MiscData%AA_y, ErrStat, ErrMsg ) + CALL AA_DestroyInput( MiscData%AA_u, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%DisturbedInflow)) THEN + DEALLOCATE(MiscData%DisturbedInflow) +ENDIF +IF (ALLOCATED(MiscData%WithoutSweepPitchTwist)) THEN + DEALLOCATE(MiscData%WithoutSweepPitchTwist) +ENDIF +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF +IF (ALLOCATED(MiscData%W_Twr)) THEN + DEALLOCATE(MiscData%W_Twr) +ENDIF +IF (ALLOCATED(MiscData%X_Twr)) THEN + DEALLOCATE(MiscData%X_Twr) +ENDIF +IF (ALLOCATED(MiscData%Y_Twr)) THEN + DEALLOCATE(MiscData%Y_Twr) +ENDIF +IF (ALLOCATED(MiscData%Curve)) THEN + DEALLOCATE(MiscData%Curve) +ENDIF +IF (ALLOCATED(MiscData%TwrClrnc)) THEN + DEALLOCATE(MiscData%TwrClrnc) +ENDIF +IF (ALLOCATED(MiscData%X)) THEN + DEALLOCATE(MiscData%X) +ENDIF +IF (ALLOCATED(MiscData%Y)) THEN + DEALLOCATE(MiscData%Y) +ENDIF +IF (ALLOCATED(MiscData%M)) THEN + DEALLOCATE(MiscData%M) +ENDIF + CALL MeshDestroy( MiscData%HubLoad, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%B_L_2_H_P)) THEN +DO i1 = LBOUND(MiscData%B_L_2_H_P,1), UBOUND(MiscData%B_L_2_H_P,1) + CALL NWTC_Library_Destroymeshmaptype( MiscData%B_L_2_H_P(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%B_L_2_H_P) +ENDIF +IF (ALLOCATED(MiscData%SigmaCavitCrit)) THEN + DEALLOCATE(MiscData%SigmaCavitCrit) +ENDIF +IF (ALLOCATED(MiscData%SigmaCavit)) THEN + DEALLOCATE(MiscData%SigmaCavit) +ENDIF +IF (ALLOCATED(MiscData%CavitWarnSet)) THEN + DEALLOCATE(MiscData%CavitWarnSet) +ENDIF + END SUBROUTINE AD_DestroyMisc + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! BEMT_y: size of buffers for each call to pack subtype + CALL BEMT_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%BEMT_y, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + DO i1 = LBOUND(InData%BEMT_u,1), UBOUND(InData%BEMT_u,1) + Int_BufSz = Int_BufSz + 3 ! BEMT_u: size of buffers for each call to pack subtype + CALL BEMT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%BEMT_u(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BEMT_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW_y: size of buffers for each call to pack subtype + CALL FVW_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%FVW_y, ErrStat2, ErrMsg2, .TRUE. ) ! FVW_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! FVW_u allocated yes/no + IF ( ALLOCATED(InData%FVW_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FVW_u upper/lower bounds for each dimension + DO i1 = LBOUND(InData%FVW_u,1), UBOUND(InData%FVW_u,1) + Int_BufSz = Int_BufSz + 3 ! FVW_u: size of buffers for each call to pack subtype + CALL FVW_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%FVW_u(i1), ErrStat2, ErrMsg2, .TRUE. ) ! FVW_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA_y: size of buffers for each call to pack subtype + CALL AA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%AA_y, ErrStat2, ErrMsg2, .TRUE. ) ! AA_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA_u: size of buffers for each call to pack subtype + CALL AA_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%AA_u, ErrStat2, ErrMsg2, .TRUE. ) ! AA_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! DisturbedInflow allocated yes/no + IF ( ALLOCATED(InData%DisturbedInflow) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! DisturbedInflow upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DisturbedInflow) ! DisturbedInflow + END IF + Int_BufSz = Int_BufSz + 1 ! WithoutSweepPitchTwist allocated yes/no + IF ( ALLOCATED(InData%WithoutSweepPitchTwist) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! WithoutSweepPitchTwist upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WithoutSweepPitchTwist) ! WithoutSweepPitchTwist + END IF + 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 + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + END IF + Int_BufSz = Int_BufSz + 1 ! W_Twr allocated yes/no + IF ( ALLOCATED(InData%W_Twr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! W_Twr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%W_Twr) ! W_Twr + END IF + Int_BufSz = Int_BufSz + 1 ! X_Twr allocated yes/no + IF ( ALLOCATED(InData%X_Twr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! X_Twr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X_Twr) ! X_Twr + END IF + Int_BufSz = Int_BufSz + 1 ! Y_Twr allocated yes/no + IF ( ALLOCATED(InData%Y_Twr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Y_Twr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Y_Twr) ! Y_Twr + END IF + Int_BufSz = Int_BufSz + 1 ! Curve allocated yes/no + IF ( ALLOCATED(InData%Curve) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Curve upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Curve) ! Curve + END IF + Int_BufSz = Int_BufSz + 1 ! TwrClrnc allocated yes/no + IF ( ALLOCATED(InData%TwrClrnc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TwrClrnc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrClrnc) ! TwrClrnc + END IF + Int_BufSz = Int_BufSz + 1 ! X allocated yes/no + IF ( ALLOCATED(InData%X) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! X upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X) ! X + END IF + Int_BufSz = Int_BufSz + 1 ! Y allocated yes/no + IF ( ALLOCATED(InData%Y) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Y upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Y) ! Y + END IF + Int_BufSz = Int_BufSz + 1 ! M allocated yes/no + IF ( ALLOCATED(InData%M) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + END IF + Re_BufSz = Re_BufSz + SIZE(InData%V_DiskAvg) ! V_DiskAvg + Re_BufSz = Re_BufSz + SIZE(InData%hub_theta_x_root) ! hub_theta_x_root + Re_BufSz = Re_BufSz + 1 ! V_dot_x + Int_BufSz = Int_BufSz + 3 ! HubLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! B_L_2_H_P allocated yes/no + IF ( ALLOCATED(InData%B_L_2_H_P) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! B_L_2_H_P upper/lower bounds for each dimension + DO i1 = LBOUND(InData%B_L_2_H_P,1), UBOUND(InData%B_L_2_H_P,1) + Int_BufSz = Int_BufSz + 3 ! B_L_2_H_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%B_L_2_H_P(i1), ErrStat2, ErrMsg2, .TRUE. ) ! B_L_2_H_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! B_L_2_H_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! B_L_2_H_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! B_L_2_H_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! SigmaCavitCrit allocated yes/no + IF ( ALLOCATED(InData%SigmaCavitCrit) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SigmaCavitCrit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SigmaCavitCrit) ! SigmaCavitCrit + END IF + Int_BufSz = Int_BufSz + 1 ! SigmaCavit allocated yes/no + IF ( ALLOCATED(InData%SigmaCavit) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SigmaCavit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SigmaCavit) ! SigmaCavit + END IF + Int_BufSz = Int_BufSz + 1 ! CavitWarnSet allocated yes/no + IF ( ALLOCATED(InData%CavitWarnSet) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CavitWarnSet upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%CavitWarnSet) ! CavitWarnSet + 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 BEMT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 BEMT_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%BEMT_y, ErrStat2, ErrMsg2, OnlySize ) ! BEMT_y + 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%BEMT_u,1), UBOUND(InData%BEMT_u,1) + CALL BEMT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%BEMT_u(i1), ErrStat2, ErrMsg2, OnlySize ) ! BEMT_u + 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 + CALL FVW_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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 FVW_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%FVW_y, ErrStat2, ErrMsg2, OnlySize ) ! FVW_y + 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%FVW_u) ) 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%FVW_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FVW_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FVW_u,1), UBOUND(InData%FVW_u,1) + CALL FVW_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%FVW_u(i1), ErrStat2, ErrMsg2, OnlySize ) ! FVW_u + 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 + CALL AA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 AA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%AA_y, ErrStat2, ErrMsg2, OnlySize ) ! AA_y + 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 AA_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%AA_u, ErrStat2, ErrMsg2, OnlySize ) ! AA_u + 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%DisturbedInflow) ) 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%DisturbedInflow,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisturbedInflow,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DisturbedInflow,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisturbedInflow,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DisturbedInflow,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisturbedInflow,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%DisturbedInflow,3), UBOUND(InData%DisturbedInflow,3) + DO i2 = LBOUND(InData%DisturbedInflow,2), UBOUND(InData%DisturbedInflow,2) + DO i1 = LBOUND(InData%DisturbedInflow,1), UBOUND(InData%DisturbedInflow,1) + ReKiBuf(Re_Xferred) = InData%DisturbedInflow(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WithoutSweepPitchTwist) ) 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%WithoutSweepPitchTwist,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WithoutSweepPitchTwist,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WithoutSweepPitchTwist,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WithoutSweepPitchTwist,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WithoutSweepPitchTwist,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WithoutSweepPitchTwist,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WithoutSweepPitchTwist,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WithoutSweepPitchTwist,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%WithoutSweepPitchTwist,4), UBOUND(InData%WithoutSweepPitchTwist,4) + DO i3 = LBOUND(InData%WithoutSweepPitchTwist,3), UBOUND(InData%WithoutSweepPitchTwist,3) + DO i2 = LBOUND(InData%WithoutSweepPitchTwist,2), UBOUND(InData%WithoutSweepPitchTwist,2) + DO i1 = LBOUND(InData%WithoutSweepPitchTwist,1), UBOUND(InData%WithoutSweepPitchTwist,1) + ReKiBuf(Re_Xferred) = InData%WithoutSweepPitchTwist(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%W_Twr) ) 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%W_Twr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%W_Twr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%W_Twr,1), UBOUND(InData%W_Twr,1) + ReKiBuf(Re_Xferred) = InData%W_Twr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X_Twr) ) 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%X_Twr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X_Twr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%X_Twr,1), UBOUND(InData%X_Twr,1) + ReKiBuf(Re_Xferred) = InData%X_Twr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Y_Twr) ) 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%Y_Twr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y_Twr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Y_Twr,1), UBOUND(InData%Y_Twr,1) + ReKiBuf(Re_Xferred) = InData%Y_Twr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Curve) ) 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%Curve,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Curve,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Curve,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Curve,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Curve,2), UBOUND(InData%Curve,2) + DO i1 = LBOUND(InData%Curve,1), UBOUND(InData%Curve,1) + ReKiBuf(Re_Xferred) = InData%Curve(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrClrnc) ) 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%TwrClrnc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrClrnc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrClrnc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrClrnc,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TwrClrnc,2), UBOUND(InData%TwrClrnc,2) + DO i1 = LBOUND(InData%TwrClrnc,1), UBOUND(InData%TwrClrnc,1) + ReKiBuf(Re_Xferred) = InData%TwrClrnc(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X) ) 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%X,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%X,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%X,2), UBOUND(InData%X,2) + DO i1 = LBOUND(InData%X,1), UBOUND(InData%X,1) + ReKiBuf(Re_Xferred) = InData%X(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Y) ) 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%Y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Y,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Y,2), UBOUND(InData%Y,2) + DO i1 = LBOUND(InData%Y,1), UBOUND(InData%Y,1) + ReKiBuf(Re_Xferred) = InData%Y(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M) ) 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%M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M,2), UBOUND(InData%M,2) + DO i1 = LBOUND(InData%M,1), UBOUND(InData%M,1) + ReKiBuf(Re_Xferred) = InData%M(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%V_DiskAvg,1), UBOUND(InData%V_DiskAvg,1) + ReKiBuf(Re_Xferred) = InData%V_DiskAvg(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%hub_theta_x_root,1), UBOUND(InData%hub_theta_x_root,1) + ReKiBuf(Re_Xferred) = InData%hub_theta_x_root(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%V_dot_x + Re_Xferred = Re_Xferred + 1 + CALL MeshPack( InData%HubLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubLoad + 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%B_L_2_H_P) ) 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%B_L_2_H_P,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B_L_2_H_P,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%B_L_2_H_P,1), UBOUND(InData%B_L_2_H_P,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%B_L_2_H_P(i1), ErrStat2, ErrMsg2, OnlySize ) ! B_L_2_H_P + 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%SigmaCavitCrit) ) 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%SigmaCavitCrit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SigmaCavitCrit,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SigmaCavitCrit,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SigmaCavitCrit,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SigmaCavitCrit,2), UBOUND(InData%SigmaCavitCrit,2) + DO i1 = LBOUND(InData%SigmaCavitCrit,1), UBOUND(InData%SigmaCavitCrit,1) + ReKiBuf(Re_Xferred) = InData%SigmaCavitCrit(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SigmaCavit) ) 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%SigmaCavit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SigmaCavit,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SigmaCavit,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SigmaCavit,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SigmaCavit,2), UBOUND(InData%SigmaCavit,2) + DO i1 = LBOUND(InData%SigmaCavit,1), UBOUND(InData%SigmaCavit,1) + ReKiBuf(Re_Xferred) = InData%SigmaCavit(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CavitWarnSet) ) 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%CavitWarnSet,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CavitWarnSet,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CavitWarnSet,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CavitWarnSet,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CavitWarnSet,2), UBOUND(InData%CavitWarnSet,2) + DO i1 = LBOUND(InData%CavitWarnSet,1), UBOUND(InData%CavitWarnSet,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%CavitWarnSet(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD_PackMisc + + SUBROUTINE AD_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(AD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_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 + 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 BEMT_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 BEMT_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT_y, ErrStat2, ErrMsg2 ) ! BEMT_y + 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%BEMT_u,1) + i1_u = UBOUND(OutData%BEMT_u,1) + DO i1 = LBOUND(OutData%BEMT_u,1), UBOUND(OutData%BEMT_u,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 BEMT_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT_u(i1), ErrStat2, ErrMsg2 ) ! BEMT_u + 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 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 FVW_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 FVW_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%FVW_y, ErrStat2, ErrMsg2 ) ! FVW_y + 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 ! FVW_u 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%FVW_u)) DEALLOCATE(OutData%FVW_u) + ALLOCATE(OutData%FVW_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FVW_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FVW_u,1), UBOUND(OutData%FVW_u,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 FVW_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%FVW_u(i1), ErrStat2, ErrMsg2 ) ! FVW_u + 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 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 AA_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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 AA_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%AA_y, ErrStat2, ErrMsg2 ) ! AA_y + 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 AA_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%AA_u, ErrStat2, ErrMsg2 ) ! AA_u + 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 ! DisturbedInflow 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%DisturbedInflow)) DEALLOCATE(OutData%DisturbedInflow) + ALLOCATE(OutData%DisturbedInflow(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%DisturbedInflow.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%DisturbedInflow,3), UBOUND(OutData%DisturbedInflow,3) + DO i2 = LBOUND(OutData%DisturbedInflow,2), UBOUND(OutData%DisturbedInflow,2) + DO i1 = LBOUND(OutData%DisturbedInflow,1), UBOUND(OutData%DisturbedInflow,1) + OutData%DisturbedInflow(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WithoutSweepPitchTwist 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%WithoutSweepPitchTwist)) DEALLOCATE(OutData%WithoutSweepPitchTwist) + ALLOCATE(OutData%WithoutSweepPitchTwist(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%WithoutSweepPitchTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%WithoutSweepPitchTwist,4), UBOUND(OutData%WithoutSweepPitchTwist,4) + DO i3 = LBOUND(OutData%WithoutSweepPitchTwist,3), UBOUND(OutData%WithoutSweepPitchTwist,3) + DO i2 = LBOUND(OutData%WithoutSweepPitchTwist,2), UBOUND(OutData%WithoutSweepPitchTwist,2) + DO i1 = LBOUND(OutData%WithoutSweepPitchTwist,1), UBOUND(OutData%WithoutSweepPitchTwist,1) + OutData%WithoutSweepPitchTwist(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOuts 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%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! W_Twr 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%W_Twr)) DEALLOCATE(OutData%W_Twr) + ALLOCATE(OutData%W_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%W_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%W_Twr,1), UBOUND(OutData%W_Twr,1) + OutData%W_Twr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X_Twr 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%X_Twr)) DEALLOCATE(OutData%X_Twr) + ALLOCATE(OutData%X_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%X_Twr,1), UBOUND(OutData%X_Twr,1) + OutData%X_Twr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Y_Twr 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%Y_Twr)) DEALLOCATE(OutData%Y_Twr) + ALLOCATE(OutData%Y_Twr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Y_Twr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Y_Twr,1), UBOUND(OutData%Y_Twr,1) + OutData%Y_Twr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Curve 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%Curve)) DEALLOCATE(OutData%Curve) + ALLOCATE(OutData%Curve(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Curve.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Curve,2), UBOUND(OutData%Curve,2) + DO i1 = LBOUND(OutData%Curve,1), UBOUND(OutData%Curve,1) + OutData%Curve(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrClrnc 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%TwrClrnc)) DEALLOCATE(OutData%TwrClrnc) + ALLOCATE(OutData%TwrClrnc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrClrnc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TwrClrnc,2), UBOUND(OutData%TwrClrnc,2) + DO i1 = LBOUND(OutData%TwrClrnc,1), UBOUND(OutData%TwrClrnc,1) + OutData%TwrClrnc(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X 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%X)) DEALLOCATE(OutData%X) + ALLOCATE(OutData%X(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%X,2), UBOUND(OutData%X,2) + DO i1 = LBOUND(OutData%X,1), UBOUND(OutData%X,1) + OutData%X(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Y 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%Y)) DEALLOCATE(OutData%Y) + ALLOCATE(OutData%Y(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Y,2), UBOUND(OutData%Y,2) + DO i1 = LBOUND(OutData%Y,1), UBOUND(OutData%Y,1) + OutData%Y(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M 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%M)) DEALLOCATE(OutData%M) + ALLOCATE(OutData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M,2), UBOUND(OutData%M,2) + DO i1 = LBOUND(OutData%M,1), UBOUND(OutData%M,1) + OutData%M(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%V_DiskAvg,1) + i1_u = UBOUND(OutData%V_DiskAvg,1) + DO i1 = LBOUND(OutData%V_DiskAvg,1), UBOUND(OutData%V_DiskAvg,1) + OutData%V_DiskAvg(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%hub_theta_x_root,1) + i1_u = UBOUND(OutData%hub_theta_x_root,1) + DO i1 = LBOUND(OutData%hub_theta_x_root,1), UBOUND(OutData%hub_theta_x_root,1) + OutData%hub_theta_x_root(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%V_dot_x = 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 MeshUnpack( OutData%HubLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubLoad + 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 ! B_L_2_H_P 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%B_L_2_H_P)) DEALLOCATE(OutData%B_L_2_H_P) + ALLOCATE(OutData%B_L_2_H_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%B_L_2_H_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%B_L_2_H_P,1), UBOUND(OutData%B_L_2_H_P,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%B_L_2_H_P(i1), ErrStat2, ErrMsg2 ) ! B_L_2_H_P + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SigmaCavitCrit 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%SigmaCavitCrit)) DEALLOCATE(OutData%SigmaCavitCrit) + ALLOCATE(OutData%SigmaCavitCrit(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SigmaCavitCrit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SigmaCavitCrit,2), UBOUND(OutData%SigmaCavitCrit,2) + DO i1 = LBOUND(OutData%SigmaCavitCrit,1), UBOUND(OutData%SigmaCavitCrit,1) + OutData%SigmaCavitCrit(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SigmaCavit 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%SigmaCavit)) DEALLOCATE(OutData%SigmaCavit) + ALLOCATE(OutData%SigmaCavit(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SigmaCavit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SigmaCavit,2), UBOUND(OutData%SigmaCavit,2) + DO i1 = LBOUND(OutData%SigmaCavit,1), UBOUND(OutData%SigmaCavit,1) + OutData%SigmaCavit(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CavitWarnSet 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%CavitWarnSet)) DEALLOCATE(OutData%CavitWarnSet) + ALLOCATE(OutData%CavitWarnSet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CavitWarnSet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CavitWarnSet,2), UBOUND(OutData%CavitWarnSet,2) + DO i1 = LBOUND(OutData%CavitWarnSet,1), UBOUND(OutData%CavitWarnSet,1) + OutData%CavitWarnSet(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%CavitWarnSet(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD_UnPackMisc + + SUBROUTINE AD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(AD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%WakeMod = SrcParamData%WakeMod + DstParamData%TwrPotent = SrcParamData%TwrPotent + DstParamData%TwrShadow = SrcParamData%TwrShadow + DstParamData%TwrAero = SrcParamData%TwrAero + DstParamData%FrozenWake = SrcParamData%FrozenWake + DstParamData%CavitCheck = SrcParamData%CavitCheck + DstParamData%CompAA = SrcParamData%CompAA + DstParamData%NumBlades = SrcParamData%NumBlades + DstParamData%NumBlNds = SrcParamData%NumBlNds + DstParamData%NumTwrNds = SrcParamData%NumTwrNds +IF (ALLOCATED(SrcParamData%TwrDiam)) THEN + i1_l = LBOUND(SrcParamData%TwrDiam,1) + i1_u = UBOUND(SrcParamData%TwrDiam,1) + IF (.NOT. ALLOCATED(DstParamData%TwrDiam)) THEN + ALLOCATE(DstParamData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwrDiam = SrcParamData%TwrDiam +ENDIF +IF (ALLOCATED(SrcParamData%TwrCd)) THEN + i1_l = LBOUND(SrcParamData%TwrCd,1) + i1_u = UBOUND(SrcParamData%TwrCd,1) + IF (.NOT. ALLOCATED(DstParamData%TwrCd)) THEN + ALLOCATE(DstParamData%TwrCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TwrCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwrCd = SrcParamData%TwrCd +ENDIF +IF (ALLOCATED(SrcParamData%TwrTI)) THEN + i1_l = LBOUND(SrcParamData%TwrTI,1) + i1_u = UBOUND(SrcParamData%TwrTI,1) + IF (.NOT. ALLOCATED(DstParamData%TwrTI)) THEN + ALLOCATE(DstParamData%TwrTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TwrTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwrTI = SrcParamData%TwrTI +ENDIF + DstParamData%AirDens = SrcParamData%AirDens + DstParamData%KinVisc = SrcParamData%KinVisc + DstParamData%SpdSound = SrcParamData%SpdSound + DstParamData%Gravity = SrcParamData%Gravity + DstParamData%Patm = SrcParamData%Patm + DstParamData%Pvap = SrcParamData%Pvap + DstParamData%FluidDepth = SrcParamData%FluidDepth +IF (ALLOCATED(SrcParamData%AFI)) THEN + i1_l = LBOUND(SrcParamData%AFI,1) + i1_u = UBOUND(SrcParamData%AFI,1) + IF (.NOT. ALLOCATED(DstParamData%AFI)) THEN + ALLOCATE(DstParamData%AFI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AFI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%AFI,1), UBOUND(SrcParamData%AFI,1) + CALL AFI_CopyParam( SrcParamData%AFI(i1), DstParamData%AFI(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL BEMT_CopyParam( SrcParamData%BEMT, DstParamData%BEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FVW_CopyParam( SrcParamData%FVW, DstParamData%FVW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AA_CopyParam( SrcParamData%AA, DstParamData%AA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NBlOuts = SrcParamData%NBlOuts + DstParamData%BlOutNd = SrcParamData%BlOutNd + DstParamData%NTwOuts = SrcParamData%NTwOuts + DstParamData%TwOutNd = SrcParamData%TwOutNd + DstParamData%BldNd_NumOuts = SrcParamData%BldNd_NumOuts + DstParamData%BldNd_TotNumOuts = SrcParamData%BldNd_TotNumOuts +IF (ALLOCATED(SrcParamData%BldNd_OutParam)) THEN + i1_l = LBOUND(SrcParamData%BldNd_OutParam,1) + i1_u = UBOUND(SrcParamData%BldNd_OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%BldNd_OutParam)) THEN + ALLOCATE(DstParamData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%BldNd_OutParam,1), UBOUND(SrcParamData%BldNd_OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%BldNd_OutParam(i1), DstParamData%BldNd_OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%BldNd_BlOutNd)) THEN + i1_l = LBOUND(SrcParamData%BldNd_BlOutNd,1) + i1_u = UBOUND(SrcParamData%BldNd_BlOutNd,1) + IF (.NOT. ALLOCATED(DstParamData%BldNd_BlOutNd)) THEN + ALLOCATE(DstParamData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldNd_BlOutNd = SrcParamData%BldNd_BlOutNd +ENDIF + DstParamData%BldNd_BladesOut = SrcParamData%BldNd_BladesOut +IF (ALLOCATED(SrcParamData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcParamData%Jac_u_indx,1) + i1_u = UBOUND(SrcParamData%Jac_u_indx,1) + i2_l = LBOUND(SrcParamData%Jac_u_indx,2) + i2_u = UBOUND(SrcParamData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstParamData%Jac_u_indx)) THEN + ALLOCATE(DstParamData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jac_u_indx = SrcParamData%Jac_u_indx +ENDIF +IF (ALLOCATED(SrcParamData%du)) THEN + i1_l = LBOUND(SrcParamData%du,1) + i1_u = UBOUND(SrcParamData%du,1) + IF (.NOT. ALLOCATED(DstParamData%du)) THEN + ALLOCATE(DstParamData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%du = SrcParamData%du +ENDIF +IF (ALLOCATED(SrcParamData%dx)) THEN + i1_l = LBOUND(SrcParamData%dx,1) + i1_u = UBOUND(SrcParamData%dx,1) + IF (.NOT. ALLOCATED(DstParamData%dx)) THEN + ALLOCATE(DstParamData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%dx = SrcParamData%dx +ENDIF + DstParamData%Jac_ny = SrcParamData%Jac_ny + END SUBROUTINE AD_CopyParam + + SUBROUTINE AD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(AD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%TwrDiam)) THEN + DEALLOCATE(ParamData%TwrDiam) +ENDIF +IF (ALLOCATED(ParamData%TwrCd)) THEN + DEALLOCATE(ParamData%TwrCd) +ENDIF +IF (ALLOCATED(ParamData%TwrTI)) THEN + DEALLOCATE(ParamData%TwrTI) +ENDIF +IF (ALLOCATED(ParamData%AFI)) THEN +DO i1 = LBOUND(ParamData%AFI,1), UBOUND(ParamData%AFI,1) + CALL AFI_DestroyParam( ParamData%AFI(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%AFI) +ENDIF + CALL BEMT_DestroyParam( ParamData%BEMT, ErrStat, ErrMsg ) + CALL FVW_DestroyParam( ParamData%FVW, ErrStat, ErrMsg ) + CALL AA_DestroyParam( ParamData%AA, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%BldNd_OutParam)) THEN +DO i1 = LBOUND(ParamData%BldNd_OutParam,1), UBOUND(ParamData%BldNd_OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%BldNd_OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%BldNd_OutParam) +ENDIF +IF (ALLOCATED(ParamData%BldNd_BlOutNd)) THEN + DEALLOCATE(ParamData%BldNd_BlOutNd) +ENDIF +IF (ALLOCATED(ParamData%Jac_u_indx)) THEN + DEALLOCATE(ParamData%Jac_u_indx) +ENDIF +IF (ALLOCATED(ParamData%du)) THEN + DEALLOCATE(ParamData%du) +ENDIF +IF (ALLOCATED(ParamData%dx)) THEN + DEALLOCATE(ParamData%dx) +ENDIF + END SUBROUTINE AD_DestroyParam + + SUBROUTINE AD_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(AD_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 = 'AD_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! WakeMod + Int_BufSz = Int_BufSz + 1 ! TwrPotent + Int_BufSz = Int_BufSz + 1 ! TwrShadow + Int_BufSz = Int_BufSz + 1 ! TwrAero + Int_BufSz = Int_BufSz + 1 ! FrozenWake + Int_BufSz = Int_BufSz + 1 ! CavitCheck + Int_BufSz = Int_BufSz + 1 ! CompAA + Int_BufSz = Int_BufSz + 1 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumBlNds + Int_BufSz = Int_BufSz + 1 ! NumTwrNds + Int_BufSz = Int_BufSz + 1 ! TwrDiam allocated yes/no + IF ( ALLOCATED(InData%TwrDiam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrDiam upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrDiam) ! TwrDiam + END IF + Int_BufSz = Int_BufSz + 1 ! TwrCd allocated yes/no + IF ( ALLOCATED(InData%TwrCd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrCd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrCd) ! TwrCd + END IF + Int_BufSz = Int_BufSz + 1 ! TwrTI allocated yes/no + IF ( ALLOCATED(InData%TwrTI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrTI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrTI) ! TwrTI + END IF + Re_BufSz = Re_BufSz + 1 ! AirDens + Re_BufSz = Re_BufSz + 1 ! KinVisc + Re_BufSz = Re_BufSz + 1 ! SpdSound + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! Patm + Re_BufSz = Re_BufSz + 1 ! Pvap + Re_BufSz = Re_BufSz + 1 ! FluidDepth + Int_BufSz = Int_BufSz + 1 ! AFI allocated yes/no + IF ( ALLOCATED(InData%AFI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AFI upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%AFI,1), UBOUND(InData%AFI,1) + Int_BufSz = Int_BufSz + 3 ! AFI: size of buffers for each call to pack subtype + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFI(i1), ErrStat2, ErrMsg2, .TRUE. ) ! AFI + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AFI + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AFI + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AFI + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! BEMT: size of buffers for each call to pack subtype + CALL BEMT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, .TRUE. ) ! BEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FVW: size of buffers for each call to pack subtype + CALL FVW_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, .TRUE. ) ! FVW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FVW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FVW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FVW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AA: size of buffers for each call to pack subtype + CALL AA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, .TRUE. ) ! AA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NBlOuts + Int_BufSz = Int_BufSz + SIZE(InData%BlOutNd) ! BlOutNd + Int_BufSz = Int_BufSz + 1 ! NTwOuts + Int_BufSz = Int_BufSz + SIZE(InData%TwOutNd) ! TwOutNd + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_TotNumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutParam allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutParam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutParam upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + Int_BufSz = Int_BufSz + 3 ! BldNd_OutParam: size of buffers for each call to pack subtype + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BldNd_OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BldNd_OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BldNd_OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BldNd_OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BldNd_BlOutNd allocated yes/no + IF ( ALLOCATED(InData%BldNd_BlOutNd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_BlOutNd upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_BlOutNd) ! BldNd_BlOutNd + END IF + Int_BufSz = Int_BufSz + 1 ! BldNd_BladesOut + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 1 ! du allocated yes/no + IF ( ALLOCATED(InData%du) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! du upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%du) ! du + END IF + Int_BufSz = Int_BufSz + 1 ! dx allocated yes/no + IF ( ALLOCATED(InData%dx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dx) ! dx + END IF + Int_BufSz = Int_BufSz + 1 ! Jac_ny + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WakeMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrPotent + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrShadow + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrAero, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FrozenWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CavitCheck, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompAA, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlNds + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumTwrNds + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TwrDiam) ) 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%TwrDiam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrDiam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrDiam,1), UBOUND(InData%TwrDiam,1) + ReKiBuf(Re_Xferred) = InData%TwrDiam(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrCd) ) 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%TwrCd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrCd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrCd,1), UBOUND(InData%TwrCd,1) + ReKiBuf(Re_Xferred) = InData%TwrCd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrTI) ) 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%TwrTI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrTI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrTI,1), UBOUND(InData%TwrTI,1) + ReKiBuf(Re_Xferred) = InData%TwrTI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdSound + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Patm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Pvap + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FluidDepth + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AFI) ) 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%AFI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AFI,1), UBOUND(InData%AFI,1) + CALL AFI_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AFI(i1), ErrStat2, ErrMsg2, OnlySize ) ! AFI + 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 + CALL BEMT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%BEMT, ErrStat2, ErrMsg2, OnlySize ) ! BEMT + 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 FVW_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FVW, ErrStat2, ErrMsg2, OnlySize ) ! FVW + 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 AA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%AA, ErrStat2, ErrMsg2, OnlySize ) ! AA + 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 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 + IntKiBuf(Int_Xferred) = InData%NBlOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%BlOutNd,1), UBOUND(InData%BlOutNd,1) + IntKiBuf(Int_Xferred) = InData%BlOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NTwOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TwOutNd,1), UBOUND(InData%TwOutNd,1) + IntKiBuf(Int_Xferred) = InData%TwOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_TotNumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_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%BldNd_OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! BldNd_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%BldNd_BlOutNd) ) 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%BldNd_BlOutNd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_BlOutNd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_BlOutNd,1), UBOUND(InData%BldNd_BlOutNd,1) + IntKiBuf(Int_Xferred) = InData%BldNd_BlOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%BldNd_BladesOut + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%du) ) 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%du,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%du,1), UBOUND(InData%du,1) + ReKiBuf(Re_Xferred) = InData%du(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dx) ) 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%dx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dx,1), UBOUND(InData%dx,1) + ReKiBuf(Re_Xferred) = InData%dx(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_PackParam + + SUBROUTINE AD_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(AD_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 = 'AD_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WakeMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrPotent = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrShadow = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrAero = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrAero) + Int_Xferred = Int_Xferred + 1 + OutData%FrozenWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%FrozenWake) + Int_Xferred = Int_Xferred + 1 + OutData%CavitCheck = TRANSFER(IntKiBuf(Int_Xferred), OutData%CavitCheck) + Int_Xferred = Int_Xferred + 1 + OutData%CompAA = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompAA) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumTwrNds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrDiam 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%TwrDiam)) DEALLOCATE(OutData%TwrDiam) + ALLOCATE(OutData%TwrDiam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrDiam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrDiam,1), UBOUND(OutData%TwrDiam,1) + OutData%TwrDiam(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrCd 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%TwrCd)) DEALLOCATE(OutData%TwrCd) + ALLOCATE(OutData%TwrCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrCd,1), UBOUND(OutData%TwrCd,1) + OutData%TwrCd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrTI 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%TwrTI)) DEALLOCATE(OutData%TwrTI) + ALLOCATE(OutData%TwrTI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrTI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrTI,1), UBOUND(OutData%TwrTI,1) + OutData%TwrTI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpdSound = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Patm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Pvap = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FluidDepth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFI 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%AFI)) DEALLOCATE(OutData%AFI) + ALLOCATE(OutData%AFI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AFI,1), UBOUND(OutData%AFI,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 AFI_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%AFI(i1), ErrStat2, ErrMsg2 ) ! AFI + 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 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 BEMT_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%BEMT, ErrStat2, ErrMsg2 ) ! BEMT + 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 FVW_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%FVW, ErrStat2, ErrMsg2 ) ! FVW + 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 AA_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%AA, ErrStat2, ErrMsg2 ) ! AA + 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%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NBlOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%BlOutNd,1) + i1_u = UBOUND(OutData%BlOutNd,1) + DO i1 = LBOUND(OutData%BlOutNd,1), UBOUND(OutData%BlOutNd,1) + OutData%BlOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NTwOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TwOutNd,1) + i1_u = UBOUND(OutData%TwOutNd,1) + DO i1 = LBOUND(OutData%TwOutNd,1), UBOUND(OutData%TwOutNd,1) + OutData%TwOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_TotNumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutParam 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%BldNd_OutParam)) DEALLOCATE(OutData%BldNd_OutParam) + ALLOCATE(OutData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutParam,1), UBOUND(OutData%BldNd_OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%BldNd_OutParam(i1), ErrStat2, ErrMsg2 ) ! BldNd_OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_BlOutNd 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%BldNd_BlOutNd)) DEALLOCATE(OutData%BldNd_BlOutNd) + ALLOCATE(OutData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_BlOutNd,1), UBOUND(OutData%BldNd_BlOutNd,1) + OutData%BldNd_BlOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%BldNd_BladesOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du 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%du)) DEALLOCATE(OutData%du) + ALLOCATE(OutData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%du,1), UBOUND(OutData%du,1) + OutData%du(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dx 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%dx)) DEALLOCATE(OutData%dx) + ALLOCATE(OutData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dx,1), UBOUND(OutData%dx,1) + OutData%dx(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD_UnPackParam + + SUBROUTINE AD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(AD_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) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%TowerMotion, DstInputData%TowerMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%HubMotion, DstInputData%HubMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%BladeRootMotion)) THEN + i1_l = LBOUND(SrcInputData%BladeRootMotion,1) + i1_u = UBOUND(SrcInputData%BladeRootMotion,1) + IF (.NOT. ALLOCATED(DstInputData%BladeRootMotion)) THEN + ALLOCATE(DstInputData%BladeRootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%BladeRootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%BladeRootMotion,1), UBOUND(SrcInputData%BladeRootMotion,1) + CALL MeshCopy( SrcInputData%BladeRootMotion(i1), DstInputData%BladeRootMotion(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInputData%BladeMotion)) THEN + i1_l = LBOUND(SrcInputData%BladeMotion,1) + i1_u = UBOUND(SrcInputData%BladeMotion,1) + IF (.NOT. ALLOCATED(DstInputData%BladeMotion)) THEN + ALLOCATE(DstInputData%BladeMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%BladeMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%BladeMotion,1), UBOUND(SrcInputData%BladeMotion,1) + CALL MeshCopy( SrcInputData%BladeMotion(i1), DstInputData%BladeMotion(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInputData%InflowOnBlade)) THEN + i1_l = LBOUND(SrcInputData%InflowOnBlade,1) + i1_u = UBOUND(SrcInputData%InflowOnBlade,1) + i2_l = LBOUND(SrcInputData%InflowOnBlade,2) + i2_u = UBOUND(SrcInputData%InflowOnBlade,2) + i3_l = LBOUND(SrcInputData%InflowOnBlade,3) + i3_u = UBOUND(SrcInputData%InflowOnBlade,3) + IF (.NOT. ALLOCATED(DstInputData%InflowOnBlade)) THEN + ALLOCATE(DstInputData%InflowOnBlade(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%InflowOnBlade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%InflowOnBlade = SrcInputData%InflowOnBlade +ENDIF +IF (ALLOCATED(SrcInputData%InflowOnTower)) THEN + i1_l = LBOUND(SrcInputData%InflowOnTower,1) + i1_u = UBOUND(SrcInputData%InflowOnTower,1) + i2_l = LBOUND(SrcInputData%InflowOnTower,2) + i2_u = UBOUND(SrcInputData%InflowOnTower,2) + IF (.NOT. ALLOCATED(DstInputData%InflowOnTower)) THEN + ALLOCATE(DstInputData%InflowOnTower(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%InflowOnTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%InflowOnTower = SrcInputData%InflowOnTower +ENDIF +IF (ALLOCATED(SrcInputData%UserProp)) THEN + i1_l = LBOUND(SrcInputData%UserProp,1) + i1_u = UBOUND(SrcInputData%UserProp,1) + i2_l = LBOUND(SrcInputData%UserProp,2) + i2_u = UBOUND(SrcInputData%UserProp,2) + IF (.NOT. ALLOCATED(DstInputData%UserProp)) THEN + ALLOCATE(DstInputData%UserProp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%UserProp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%UserProp = SrcInputData%UserProp +ENDIF +IF (ALLOCATED(SrcInputData%InflowWakeVel)) THEN + i1_l = LBOUND(SrcInputData%InflowWakeVel,1) + i1_u = UBOUND(SrcInputData%InflowWakeVel,1) + i2_l = LBOUND(SrcInputData%InflowWakeVel,2) + i2_u = UBOUND(SrcInputData%InflowWakeVel,2) + IF (.NOT. ALLOCATED(DstInputData%InflowWakeVel)) THEN + ALLOCATE(DstInputData%InflowWakeVel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%InflowWakeVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%InflowWakeVel = SrcInputData%InflowWakeVel +ENDIF + END SUBROUTINE AD_CopyInput + + SUBROUTINE AD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(AD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%TowerMotion, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%HubMotion, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%BladeRootMotion)) THEN +DO i1 = LBOUND(InputData%BladeRootMotion,1), UBOUND(InputData%BladeRootMotion,1) + CALL MeshDestroy( InputData%BladeRootMotion(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%BladeRootMotion) +ENDIF +IF (ALLOCATED(InputData%BladeMotion)) THEN +DO i1 = LBOUND(InputData%BladeMotion,1), UBOUND(InputData%BladeMotion,1) + CALL MeshDestroy( InputData%BladeMotion(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%BladeMotion) +ENDIF +IF (ALLOCATED(InputData%InflowOnBlade)) THEN + DEALLOCATE(InputData%InflowOnBlade) +ENDIF +IF (ALLOCATED(InputData%InflowOnTower)) THEN + DEALLOCATE(InputData%InflowOnTower) +ENDIF +IF (ALLOCATED(InputData%UserProp)) THEN + DEALLOCATE(InputData%UserProp) +ENDIF +IF (ALLOCATED(InputData%InflowWakeVel)) THEN + DEALLOCATE(InputData%InflowWakeVel) +ENDIF + END SUBROUTINE AD_DestroyInput + + SUBROUTINE AD_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(AD_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 = 'AD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! TowerMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%TowerMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TowerMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TowerMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TowerMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TowerMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HubMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! BladeRootMotion allocated yes/no + IF ( ALLOCATED(InData%BladeRootMotion) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeRootMotion upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeRootMotion,1), UBOUND(InData%BladeRootMotion,1) + Int_BufSz = Int_BufSz + 3 ! BladeRootMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeRootMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeRootMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeRootMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeRootMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BladeMotion allocated yes/no + IF ( ALLOCATED(InData%BladeMotion) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeMotion upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeMotion,1), UBOUND(InData%BladeMotion,1) + Int_BufSz = Int_BufSz + 3 ! BladeMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InflowOnBlade allocated yes/no + IF ( ALLOCATED(InData%InflowOnBlade) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! InflowOnBlade upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InflowOnBlade) ! InflowOnBlade + END IF + Int_BufSz = Int_BufSz + 1 ! InflowOnTower allocated yes/no + IF ( ALLOCATED(InData%InflowOnTower) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InflowOnTower upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InflowOnTower) ! InflowOnTower + END IF + Int_BufSz = Int_BufSz + 1 ! UserProp allocated yes/no + IF ( ALLOCATED(InData%UserProp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! UserProp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UserProp) ! UserProp + END IF + Int_BufSz = Int_BufSz + 1 ! InflowWakeVel allocated yes/no + IF ( ALLOCATED(InData%InflowWakeVel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InflowWakeVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InflowWakeVel) ! InflowWakeVel + 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 MeshPack( InData%TowerMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TowerMotion + 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 MeshPack( InData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubMotion + 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%BladeRootMotion) ) 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%BladeRootMotion,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootMotion,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeRootMotion,1), UBOUND(InData%BladeRootMotion,1) + CALL MeshPack( InData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeRootMotion + 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%BladeMotion) ) 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%BladeMotion,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeMotion,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeMotion,1), UBOUND(InData%BladeMotion,1) + CALL MeshPack( InData%BladeMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeMotion + 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%InflowOnBlade) ) 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%InflowOnBlade,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowOnBlade,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InflowOnBlade,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowOnBlade,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InflowOnBlade,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowOnBlade,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%InflowOnBlade,3), UBOUND(InData%InflowOnBlade,3) + DO i2 = LBOUND(InData%InflowOnBlade,2), UBOUND(InData%InflowOnBlade,2) + DO i1 = LBOUND(InData%InflowOnBlade,1), UBOUND(InData%InflowOnBlade,1) + ReKiBuf(Re_Xferred) = InData%InflowOnBlade(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InflowOnTower) ) 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%InflowOnTower,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowOnTower,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InflowOnTower,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowOnTower,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InflowOnTower,2), UBOUND(InData%InflowOnTower,2) + DO i1 = LBOUND(InData%InflowOnTower,1), UBOUND(InData%InflowOnTower,1) + ReKiBuf(Re_Xferred) = InData%InflowOnTower(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UserProp) ) 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%UserProp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UserProp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UserProp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UserProp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%UserProp,2), UBOUND(InData%UserProp,2) + DO i1 = LBOUND(InData%UserProp,1), UBOUND(InData%UserProp,1) + ReKiBuf(Re_Xferred) = InData%UserProp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InflowWakeVel) ) 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%InflowWakeVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowWakeVel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InflowWakeVel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowWakeVel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InflowWakeVel,2), UBOUND(InData%InflowWakeVel,2) + DO i1 = LBOUND(InData%InflowWakeVel,1), UBOUND(InData%InflowWakeVel,1) + ReKiBuf(Re_Xferred) = InData%InflowWakeVel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD_PackInput + + SUBROUTINE AD_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(AD_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) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_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 + 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 MeshUnpack( OutData%TowerMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TowerMotion + 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 MeshUnpack( OutData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubMotion + 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 ! BladeRootMotion 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%BladeRootMotion)) DEALLOCATE(OutData%BladeRootMotion) + ALLOCATE(OutData%BladeRootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeRootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeRootMotion,1), UBOUND(OutData%BladeRootMotion,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 MeshUnpack( OutData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeRootMotion + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeMotion 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%BladeMotion)) DEALLOCATE(OutData%BladeMotion) + ALLOCATE(OutData%BladeMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeMotion,1), UBOUND(OutData%BladeMotion,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 MeshUnpack( OutData%BladeMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeMotion + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InflowOnBlade 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%InflowOnBlade)) DEALLOCATE(OutData%InflowOnBlade) + ALLOCATE(OutData%InflowOnBlade(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%InflowOnBlade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%InflowOnBlade,3), UBOUND(OutData%InflowOnBlade,3) + DO i2 = LBOUND(OutData%InflowOnBlade,2), UBOUND(OutData%InflowOnBlade,2) + DO i1 = LBOUND(OutData%InflowOnBlade,1), UBOUND(OutData%InflowOnBlade,1) + OutData%InflowOnBlade(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InflowOnTower 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%InflowOnTower)) DEALLOCATE(OutData%InflowOnTower) + ALLOCATE(OutData%InflowOnTower(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InflowOnTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InflowOnTower,2), UBOUND(OutData%InflowOnTower,2) + DO i1 = LBOUND(OutData%InflowOnTower,1), UBOUND(OutData%InflowOnTower,1) + OutData%InflowOnTower(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UserProp 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%UserProp)) DEALLOCATE(OutData%UserProp) + ALLOCATE(OutData%UserProp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UserProp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%UserProp,2), UBOUND(OutData%UserProp,2) + DO i1 = LBOUND(OutData%UserProp,1), UBOUND(OutData%UserProp,1) + OutData%UserProp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InflowWakeVel 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%InflowWakeVel)) DEALLOCATE(OutData%InflowWakeVel) + ALLOCATE(OutData%InflowWakeVel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InflowWakeVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InflowWakeVel,2), UBOUND(OutData%InflowWakeVel,2) + DO i1 = LBOUND(OutData%InflowWakeVel,1), UBOUND(OutData%InflowWakeVel,1) + OutData%InflowWakeVel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD_UnPackInput + + SUBROUTINE AD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(AD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'AD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%TowerLoad, DstOutputData%TowerLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%BladeLoad)) THEN + i1_l = LBOUND(SrcOutputData%BladeLoad,1) + i1_u = UBOUND(SrcOutputData%BladeLoad,1) + IF (.NOT. ALLOCATED(DstOutputData%BladeLoad)) THEN + ALLOCATE(DstOutputData%BladeLoad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BladeLoad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOutputData%BladeLoad,1), UBOUND(SrcOutputData%BladeLoad,1) + CALL MeshCopy( SrcOutputData%BladeLoad(i1), DstOutputData%BladeLoad(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE AD_CopyOutput + + SUBROUTINE AD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(AD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%TowerLoad, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%BladeLoad)) THEN +DO i1 = LBOUND(OutputData%BladeLoad,1), UBOUND(OutputData%BladeLoad,1) + CALL MeshDestroy( OutputData%BladeLoad(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OutputData%BladeLoad) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE AD_DestroyOutput + + SUBROUTINE AD_PackOutput( 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(AD_OutputType), 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 = 'AD_PackOutput' + ! 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 ! TowerLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%TowerLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TowerLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TowerLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TowerLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TowerLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! BladeLoad allocated yes/no + IF ( ALLOCATED(InData%BladeLoad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeLoad upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeLoad,1), UBOUND(InData%BladeLoad,1) + Int_BufSz = Int_BufSz + 3 ! BladeLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeLoad(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%TowerLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TowerLoad + 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%BladeLoad) ) 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%BladeLoad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeLoad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeLoad,1), UBOUND(InData%BladeLoad,1) + CALL MeshPack( InData%BladeLoad(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeLoad + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_PackOutput + + SUBROUTINE AD_UnPackOutput( 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(AD_OutputType), 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 = 'AD_UnPackOutput' + ! 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 MeshUnpack( OutData%TowerLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TowerLoad + 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 ! BladeLoad 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%BladeLoad)) DEALLOCATE(OutData%BladeLoad) + ALLOCATE(OutData%BladeLoad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeLoad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeLoad,1), UBOUND(OutData%BladeLoad,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 MeshUnpack( OutData%BladeLoad(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeLoad + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD_UnPackOutput + + + SUBROUTINE AD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(AD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL AD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD_Input_ExtrapInterp + + + SUBROUTINE AD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(AD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(AD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(AD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%TowerMotion, u2%TowerMotion, tin, u_out%TowerMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%HubMotion, u2%HubMotion, tin, u_out%HubMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%BladeRootMotion) .AND. ALLOCATED(u1%BladeRootMotion)) THEN + DO i1 = LBOUND(u_out%BladeRootMotion,1),UBOUND(u_out%BladeRootMotion,1) + CALL MeshExtrapInterp1(u1%BladeRootMotion(i1), u2%BladeRootMotion(i1), tin, u_out%BladeRootMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%BladeMotion) .AND. ALLOCATED(u1%BladeMotion)) THEN + DO i1 = LBOUND(u_out%BladeMotion,1),UBOUND(u_out%BladeMotion,1) + CALL MeshExtrapInterp1(u1%BladeMotion(i1), u2%BladeMotion(i1), tin, u_out%BladeMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowOnBlade) .AND. ALLOCATED(u1%InflowOnBlade)) THEN + DO i3 = LBOUND(u_out%InflowOnBlade,3),UBOUND(u_out%InflowOnBlade,3) + DO i2 = LBOUND(u_out%InflowOnBlade,2),UBOUND(u_out%InflowOnBlade,2) + DO i1 = LBOUND(u_out%InflowOnBlade,1),UBOUND(u_out%InflowOnBlade,1) + b = -(u1%InflowOnBlade(i1,i2,i3) - u2%InflowOnBlade(i1,i2,i3)) + u_out%InflowOnBlade(i1,i2,i3) = u1%InflowOnBlade(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowOnTower) .AND. ALLOCATED(u1%InflowOnTower)) THEN + DO i2 = LBOUND(u_out%InflowOnTower,2),UBOUND(u_out%InflowOnTower,2) + DO i1 = LBOUND(u_out%InflowOnTower,1),UBOUND(u_out%InflowOnTower,1) + b = -(u1%InflowOnTower(i1,i2) - u2%InflowOnTower(i1,i2)) + u_out%InflowOnTower(i1,i2) = u1%InflowOnTower(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%UserProp) .AND. ALLOCATED(u1%UserProp)) THEN + DO i2 = LBOUND(u_out%UserProp,2),UBOUND(u_out%UserProp,2) + DO i1 = LBOUND(u_out%UserProp,1),UBOUND(u_out%UserProp,1) + b = -(u1%UserProp(i1,i2) - u2%UserProp(i1,i2)) + u_out%UserProp(i1,i2) = u1%UserProp(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowWakeVel) .AND. ALLOCATED(u1%InflowWakeVel)) THEN + DO i2 = LBOUND(u_out%InflowWakeVel,2),UBOUND(u_out%InflowWakeVel,2) + DO i1 = LBOUND(u_out%InflowWakeVel,1),UBOUND(u_out%InflowWakeVel,1) + b = -(u1%InflowWakeVel(i1,i2) - u2%InflowWakeVel(i1,i2)) + u_out%InflowWakeVel(i1,i2) = u1%InflowWakeVel(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + END SUBROUTINE AD_Input_ExtrapInterp1 + + + SUBROUTINE AD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(AD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(AD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(AD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(AD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%TowerMotion, u2%TowerMotion, u3%TowerMotion, tin, u_out%TowerMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%HubMotion, u2%HubMotion, u3%HubMotion, tin, u_out%HubMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%BladeRootMotion) .AND. ALLOCATED(u1%BladeRootMotion)) THEN + DO i1 = LBOUND(u_out%BladeRootMotion,1),UBOUND(u_out%BladeRootMotion,1) + CALL MeshExtrapInterp2(u1%BladeRootMotion(i1), u2%BladeRootMotion(i1), u3%BladeRootMotion(i1), tin, u_out%BladeRootMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%BladeMotion) .AND. ALLOCATED(u1%BladeMotion)) THEN + DO i1 = LBOUND(u_out%BladeMotion,1),UBOUND(u_out%BladeMotion,1) + CALL MeshExtrapInterp2(u1%BladeMotion(i1), u2%BladeMotion(i1), u3%BladeMotion(i1), tin, u_out%BladeMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowOnBlade) .AND. ALLOCATED(u1%InflowOnBlade)) THEN + DO i3 = LBOUND(u_out%InflowOnBlade,3),UBOUND(u_out%InflowOnBlade,3) + DO i2 = LBOUND(u_out%InflowOnBlade,2),UBOUND(u_out%InflowOnBlade,2) + DO i1 = LBOUND(u_out%InflowOnBlade,1),UBOUND(u_out%InflowOnBlade,1) + b = (t(3)**2*(u1%InflowOnBlade(i1,i2,i3) - u2%InflowOnBlade(i1,i2,i3)) + t(2)**2*(-u1%InflowOnBlade(i1,i2,i3) + u3%InflowOnBlade(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*u1%InflowOnBlade(i1,i2,i3) + t(3)*u2%InflowOnBlade(i1,i2,i3) - t(2)*u3%InflowOnBlade(i1,i2,i3) ) * scaleFactor + u_out%InflowOnBlade(i1,i2,i3) = u1%InflowOnBlade(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowOnTower) .AND. ALLOCATED(u1%InflowOnTower)) THEN + DO i2 = LBOUND(u_out%InflowOnTower,2),UBOUND(u_out%InflowOnTower,2) + DO i1 = LBOUND(u_out%InflowOnTower,1),UBOUND(u_out%InflowOnTower,1) + b = (t(3)**2*(u1%InflowOnTower(i1,i2) - u2%InflowOnTower(i1,i2)) + t(2)**2*(-u1%InflowOnTower(i1,i2) + u3%InflowOnTower(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%InflowOnTower(i1,i2) + t(3)*u2%InflowOnTower(i1,i2) - t(2)*u3%InflowOnTower(i1,i2) ) * scaleFactor + u_out%InflowOnTower(i1,i2) = u1%InflowOnTower(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%UserProp) .AND. ALLOCATED(u1%UserProp)) THEN + DO i2 = LBOUND(u_out%UserProp,2),UBOUND(u_out%UserProp,2) + DO i1 = LBOUND(u_out%UserProp,1),UBOUND(u_out%UserProp,1) + b = (t(3)**2*(u1%UserProp(i1,i2) - u2%UserProp(i1,i2)) + t(2)**2*(-u1%UserProp(i1,i2) + u3%UserProp(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%UserProp(i1,i2) + t(3)*u2%UserProp(i1,i2) - t(2)*u3%UserProp(i1,i2) ) * scaleFactor + u_out%UserProp(i1,i2) = u1%UserProp(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowWakeVel) .AND. ALLOCATED(u1%InflowWakeVel)) THEN + DO i2 = LBOUND(u_out%InflowWakeVel,2),UBOUND(u_out%InflowWakeVel,2) + DO i1 = LBOUND(u_out%InflowWakeVel,1),UBOUND(u_out%InflowWakeVel,1) + b = (t(3)**2*(u1%InflowWakeVel(i1,i2) - u2%InflowWakeVel(i1,i2)) + t(2)**2*(-u1%InflowWakeVel(i1,i2) + u3%InflowWakeVel(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%InflowWakeVel(i1,i2) + t(3)*u2%InflowWakeVel(i1,i2) - t(2)*u3%InflowWakeVel(i1,i2) ) * scaleFactor + u_out%InflowWakeVel(i1,i2) = u1%InflowWakeVel(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + END SUBROUTINE AD_Input_ExtrapInterp2 + + + SUBROUTINE AD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(AD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL AD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD_Output_ExtrapInterp + + + SUBROUTINE AD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(AD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(AD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(AD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%TowerLoad, y2%TowerLoad, tin, y_out%TowerLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%BladeLoad) .AND. ALLOCATED(y1%BladeLoad)) THEN + DO i1 = LBOUND(y_out%BladeLoad,1),UBOUND(y_out%BladeLoad,1) + CALL MeshExtrapInterp1(y1%BladeLoad(i1), y2%BladeLoad(i1), tin, y_out%BladeLoad(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE AD_Output_ExtrapInterp1 + + + SUBROUTINE AD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(AD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(AD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(AD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(AD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%TowerLoad, y2%TowerLoad, y3%TowerLoad, tin, y_out%TowerLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%BladeLoad) .AND. ALLOCATED(y1%BladeLoad)) THEN + DO i1 = LBOUND(y_out%BladeLoad,1),UBOUND(y_out%BladeLoad,1) + CALL MeshExtrapInterp2(y1%BladeLoad(i1), y2%BladeLoad(i1), y3%BladeLoad(i1), tin, y_out%BladeLoad(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE AD_Output_ExtrapInterp2 + +END MODULE AeroDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/AirfoilInfo.f90 b/OpenFAST/modules/aerodyn/src/AirfoilInfo.f90 new file mode 100644 index 000000000..8648733e2 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AirfoilInfo.f90 @@ -0,0 +1,1181 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2018 National Renewable Energy Laboratory +! +! This file is part of AeroDyn. +! +! 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 AirfoilInfo + + + ! This module contains airfoil-related routines with non-system-specific logic and references. + +! Redo this routing to get rid of some of the phases. For instance, AFI_Init should be calle directly. + + USE AirfoilInfo_Types + USE :: ISO_FORTRAN_ENV , ONLY : IOSTAT_EOR + + IMPLICIT NONE + + PRIVATE + + PUBLIC :: AFI_Init ! routine to initialize AirfoilInfo parameters + PUBLIC :: AFI_ComputeUACoefs ! routine to calculate Airfoil BL parameters for UA + PUBLIC :: AFI_ComputeAirfoilCoefs ! routine to perform 1D (AOA) or 2D (AOA, Re) or (AOA, UserProp) lookup of the airfoil coefs + TYPE(ProgDesc), PARAMETER :: AFI_Ver = ProgDesc( 'AirfoilInfo', '', '') ! The name, version, and date of AirfoilInfo. + + integer, parameter :: MaxNumAFCoeffs = 6 !cl,cd,cm,cpMin, UA_HGM:f_st, UA_HGM:cl_fs + +CONTAINS + + + function CheckValuesAreUniqueMonotonicIncreasing(secondVals) + + real(ReKi), intent(in ) :: secondVals(:) + logical CheckValuesAreUniqueMonotonicIncreasing + + + integer(IntKi) :: i + + CheckValuesAreUniqueMonotonicIncreasing = .true. + + do i = 2, size(secondVals) + if ( EqualRealNos(secondVals(i), secondVals(i-1)) .or. (secondVals(i) < secondVals(i-1))) then + CheckValuesAreUniqueMonotonicIncreasing = .false. + exit + end if + end do + + + end function CheckValuesAreUniqueMonotonicIncreasing + + !============================================================================= + SUBROUTINE AFI_Init ( InitInput, p, ErrStat, ErrMsg, UnEcho ) + + + ! This routine initializes AirfoilInfo by reading the airfoil files and generating the spline coefficients. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status. + INTEGER, INTENT(IN), OPTIONAL :: UnEcho ! I/O unit for echo file. If present and > 0, write to UnEcho. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. + TYPE (AFI_InitInputType), INTENT(IN ) :: InitInput ! This structure stores values that are set by the calling routine during the initialization phase. + TYPE (AFI_ParameterType), INTENT( OUT) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + + ! Local declarations. + + REAL(ReKi), ALLOCATABLE :: Coef (:) ! The coefficients to send to the regrid routine for 2D splines. + + INTEGER :: Co ! The index into the coefficients array. + INTEGER :: UnEc ! Local echo file unit number + INTEGER :: NumCoefs ! The number of aerodynamic coefficients to be stored + integer :: iTable ! Iterator for airfoil tables + + INTEGER :: ErrStat2 ! Local error status. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_Init' + + ErrStat = ErrID_None + ErrMsg = "" + + ! Display the version for this module. + + !CALL DispNVD ( AFI_Ver ) + + CALL AFI_ValidateInitInput(InitInput, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + IF ( PRESENT(UnEcho) ) THEN + UnEc = UnEcho + ELSE + UnEc = -1 + END IF + + ! Set the lookup model: 1 = 1D, 2 = 2D based on (AoA,Re), 3 = 2D based on (AoA,UserProp) + p%AFTabMod = InitInput%AFTabMod + + ! Set the column indices for the various airfoil coefficients as they will be stored in our data structures, + ! NOT as they are recorded in the airfoil input file (InitInput%InCol_*) ! + p%ColCl = 1 + p%ColCd = 2 + p%ColCm = 0 ! These may or may not be used; initialize to zero in case they aren't used + p%ColCpmin = 0 ! These may or may not be used; initialize to zero in case they aren't used + p%ColUAf = 0 ! These may or may not be used; initialize to zero in case they aren't used + + IF ( InitInput%InCol_Cm > 0 ) THEN + p%ColCm = 3 + IF ( InitInput%InCol_Cpmin > 0 ) THEN + p%ColCpmin = 4 + END IF + ELSE IF ( InitInput%InCol_Cpmin > 0 ) THEN + p%ColCpmin = 3 + END IF + NumCoefs = MAX(p%ColCd, p%ColCm,p%ColCpmin) ! number of non-zero coefficient columns + + + ! Process the airfoil file. + + + IF ( UnEc > 0 ) THEN + WRITE (UnEc,'("--",/,A)') 'Contents of "'//TRIM( InitInput%FileName )//'":' + END IF + + + CALL ReadAFfile ( InitInput%FileName, NumCoefs, InitInput%InCol_Alfa & + , InitInput%InCol_Cl, InitInput%InCol_Cd, InitInput%InCol_Cm, InitInput%InCol_Cpmin, p & + , ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup ( ) + RETURN + ENDIF + + + ! Make sure that all the tables meet the current restrictions. + + IF ( p%NumTabs > 1 ) THEN + + IF ( p%AFTabMod == AFITable_1 ) THEN + ! 1D interpolation was specified even though multiple tables exist in the file + + p%NumTabs = 1 + CALL SetErrStat ( ErrID_Warn, 'DimModel = 1D, therefore using only the first airfoil table in the file: "'//TRIM( InitInput%FileName ), ErrStat, ErrMsg, RoutineName ) + + ELSE !IF ( p%AFTabMod /= AFITable_1 ) THEN + + !-------------- + ! Check that secondary values are unique and monotonically increasing: + !-------------- + ALLOCATE(p%secondVals(p%NumTabs), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for the secondVals array.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + IF (p%AFTabMod == AFITable_2Re) THEN + ! Ctrl Value must be the same, Re must be monotonic increasing without repeats + + DO iTable=2,p%NumTabs + + IF ( p%Table(iTable)%UserProp /= p%Table(1)%UserProp ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal Error: airfoil file "'//TRIM( InitInput%FileName ) & + //'", Table #'//TRIM( Num2LStr( iTable ) ) & + //' does not have the same value for Ctrl Property (UserProp) as the first table.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + END DO ! iTable + + DO iTable=1,p%NumTabs + if (p%Table(iTable)%Re < 0.0_ReKi) then + CALL SetErrStat ( ErrID_Fatal, 'Fatal Error: airfoil file "'//TRIM( InitInput%FileName ) & + //'", Table #'//TRIM( Num2LStr( iTable ) ) & + //' has a negative Reynolds Number.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + end if + + p%Table(iTable)%Re = max( p%Table(iTable)%Re, 0.001_ReKi ) + +#ifndef AFI_USE_LINEAR_RE + p%secondVals(iTable) = log( p%Table(iTable)%Re ) +#else + p%secondVals(iTable) = p%Table(iTable)%Re +#endif + END DO ! iTable + + ELSE IF (p%AFTabMod == AFITable_2User) THEN + ! Re must be the same, Ctrl must be different + + p%secondVals(1) = p%Table(1)%UserProp + + DO iTable=2,p%NumTabs + IF ( p%Table(iTable)%Re /= p%Table(1)%Re ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal Error: airfoil file "'//TRIM( InitInput%FileName ) & + //'", Table #'//TRIM( Num2LStr( iTable ) ) & + //' does not have the same value for Re Property (Re) as the first table.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + p%secondVals(iTable) = p%Table(iTable)%UserProp + END DO ! iTable + + END IF + + + IF (.NOT. CheckValuesAreUniqueMonotonicIncreasing(p%secondVals)) THEN + + ErrMsg2 = 'Fatal Error: airfoil file "'//TRIM( InitInput%FileName ) & + //'", is not monotonic and increasing in the ' + IF (p%AFTabMod == AFITable_2Re) THEN + ErrMsg2 = trim(ErrMsg2)//' Re Property (Re).' + ELSE + ErrMsg2 = trim(ErrMsg2)//' Ctrl Property (UserProp).' + END IF + + CALL SetErrStat ( ErrID_Fatal, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + + END IF + + + END IF + ELSE + p%AFTabMod = AFITable_1 + ENDIF ! ( p%NumTabs > 1 ) + + +! We need to deal with constant data. + + + do iTable = 1, p%NumTabs + ! Allocate the arrays to hold spline coefficients. + + allocate ( p%Table(iTable)%SplineCoefs( p%Table(iTable)%NumAlf-1 & + , NumCoefs, 0:3 ), STAT=ErrStat2 ) + if ( ErrStat2 /= 0 ) then + call SetErrStat ( ErrStat2, 'Error allocating memory for the SplineCoefs array.', ErrStat, ErrMsg, RoutineName ) + call Cleanup() + return + end if + + ! Check that the second dimensions of the SplineCoefs table and the Coefs table match. If they don't, it may indicate + ! that the number of columns in each table in the AF input file are different. This will result in array bounds issues + ! in the CubicSplineInitM routine. + if ( size(p%Table(iTable)%SplineCoefs, DIM=2) /= size(p%Table(iTable)%Coefs, DIM=2) ) then + call SetErrStat ( ErrID_Fatal, 'Number of columns in the SplineCoefs table and Coefs tables do not match in size.'// & + ' Check that all tables in airfoil input file "'//TRIM( InitInput%FileName )//'" have the same number of columns.', & + ErrStat, ErrMsg, RoutineName ) + call Cleanup() + return + end if + + ! Compute the one set of coefficients of the piecewise polynomials for the irregularly-spaced data. + ! Unlike the 2-D interpolation in which we use diffent knots for each airfoil coefficient, we can do + ! the 1-D stuff all at once. + + + + if ( p%InterpOrd == 3_IntKi ) then + + ! bjj: what happens at the end points (these are periodic, so we should maybe extend the tables to make sure the end point?) + + ! use this for cubic splines: + call CubicSplineInitM ( p%Table(iTable)%Alpha & + , p%Table(iTable)%Coefs & + , p%Table(iTable)%SplineCoefs & + , ErrStat2, ErrMsg2 ) + call SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + else if ( p%InterpOrd == 1_IntKi ) then + + ! use this for linear interpolation (sets the higher order coeffs to zero): + + ! This is not the greatest way to get linear interpolation, but then we can use the same cubic spline routine + ! later without checking interp order there + call CubicLinSplineInitM ( p%Table(iTable)%Alpha & + , p%Table(iTable)%Coefs & + , p%Table(iTable)%SplineCoefs & + , ErrStat2, ErrMsg2 ) + call SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + else + + call SetErrStat ( ErrID_FATAL, 'Airfoil file "'//trim( InitInput%FileName ) & + //'": InterpOrd must be 1 (linear) or 3 (cubic spline).', ErrStat, ErrMsg, RoutineName ) + call Cleanup() + return + + end if + + end do + + + ! Compute the spline coefficients of the piecewise cubic polynomials for the irregularly-spaced airfoil data in each file. + ! Unless the data are constant. + + DO Co=1,NumCoefs + + ! We use 1D cubic spline interpolation if the data are not constant. + IF ( p%Table(1)%ConstData ) THEN + + ! We need to deal with constant data. + + CALL SetErrStat ( ErrID_FATAL, 'The part to deal with constant data in AFI_Init is not written yet!', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + + ENDIF ! p%Table(1)%ConstData + + END DO ! Co + + + CALL Cleanup ( ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE Cleanup ( ) + + ! This subroutine cleans up the parent routine before exiting. + ! Deallocate the temporary Coef array. + + IF ( ALLOCATED( Coef ) ) DEALLOCATE( Coef ) + + RETURN + + END SUBROUTINE Cleanup + + END SUBROUTINE AFI_Init + + !============================================================================= + !> This routine checks the init input values for AFI and makes sure they are valid + !! before using them. + SUBROUTINE AFI_ValidateInitInput(InitInput, ErrStat, ErrMsg) + TYPE (AFI_InitInputType), INTENT(IN ) :: InitInput ! This structure stores values that are set by the calling routine during the initialization phase. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_Validate' + + ErrStat = ErrID_None + ErrMsg = "" + + if (InitInput%InCol_Alfa < 0) call SetErrStat( ErrID_Fatal, 'InCol_Alfa must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + if (InitInput%InCol_Cl < 0) call SetErrStat( ErrID_Fatal, 'InCol_Cl must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + if (InitInput%InCol_Cd < 0) call SetErrStat( ErrID_Fatal, 'InCol_Cd must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + if (InitInput%InCol_Cm < 0) call SetErrStat( ErrID_Fatal, 'InCol_Cm must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + if (InitInput%InCol_Cpmin < 0) call SetErrStat( ErrID_Fatal, 'InCol_Cpmin must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + if (InitInput%AFTabMod /= AFITable_1 .and. InitInput%AFTabMod /= AFITable_2Re .and. InitInput%AFTabMod /= AFITable_2User) then + call SetErrStat( ErrID_Fatal, 'AFTabMod must be 1, 2, or 3.', ErrStat, ErrMsg, RoutineName ) + end if + + + END SUBROUTINE AFI_ValidateInitInput + + !============================================================================= + SUBROUTINE ReadAFfile ( AFfile, NumCoefs, InCol_Alfa, InCol_Cl, InCol_Cd, InCol_Cm, InCol_Cpmin, p & + , ErrStat, ErrMsg, UnEc ) + + + ! This routine reads an airfoil file. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: InCol_Alfa ! The airfoil-table input column for angle of attack. + INTEGER(IntKi), INTENT(IN) :: InCol_Cd ! The airfoil-table input column for drag coefficient. + INTEGER(IntKi), INTENT(IN) :: InCol_Cl ! The airfoil-table input column for lift coefficient. + INTEGER(IntKi), INTENT(IN) :: InCol_Cm ! The airfoil-table input column for pitching-moment coefficient. + INTEGER(IntKi), INTENT(IN) :: InCol_Cpmin ! The airfoil-table input column for minimum pressure coefficient. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status. + INTEGER(IntKi), INTENT(INOUT) :: NumCoefs ! The number of aerodynamic coefficients to be stored. + + INTEGER, INTENT(IN) :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. CHARACTER(*), INTENT(IN) :: AFfile ! The file to be read. + + CHARACTER(*), INTENT(IN) :: AFfile ! The file to read in. + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message. + + TYPE (AFI_ParameterType), INTENT(INOUT) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + + + ! Local declarations. + + REAL(ReKi) :: Coords (2) ! An array to hold data from the airfoil-shape table. + REAL(ReKi), ALLOCATABLE :: SiAry (:) ! A temporary array to hold data from a table. + + INTEGER :: Coef ! A DO index that points into the coefficient array. + INTEGER :: Cols2Parse ! The number of columns that must be read from the coefficient tables. + INTEGER :: CurLine ! The current line to be parsed in the FileInfo structure. + INTEGER :: NumAlf ! The number of rows in the current table. + INTEGER :: Row ! The row of a table to be parsed in the FileInfo structure. + INTEGER :: iTable ! The DO index for the tables. + + LOGICAL :: BadVals ! A flag that indicates if the values in a table are invalid. + + TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. + INTEGER(IntKi) :: NumCoefsIn ! The number of aerodynamic coefficients input to routine + INTEGER(IntKi) :: NumCoefsTab ! The number of aerodynamic coefficients to be stored for this table. + + INTEGER(IntKi) :: DefaultInterpOrd ! value of default interp order + INTEGER(IntKi) :: ErrStat2 ! Error status local to this routine. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ReadAFfile' + CHARACTER(10) :: defaultStr + CHARACTER(1024) :: PriPath + + ErrStat = ErrID_None + ErrMsg = "" + defaultStr = "" + + ! store NumCoefs passed in + NumCoefsIn = NumCoefs + + ! Getting parent folder of airfoils data (e.g. "Arifoils/") + CALL GetPath( AFFile, PriPath ) + ! Process the (possibly) nested set of files. This copies the decommented contents of + ! AFI_FileInfo%FileName and the files it includes (both directly and indirectly) into + ! the FileInfo structure that we can then parse. + + CALL ProcessComFile ( AFfile, FileInfo, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + ! Process the airfoil shape information if it is included. + + CurLine = 1 + + ! Default to linear interpolation + DefaultInterpOrd = 1 + + CALL ParseVarWDefault ( FileInfo, CurLine, 'InterpOrd', p%InterpOrd, DefaultInterpOrd, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! NonDimArea is currently unused by AirfoilInfo or codes using AirfoilInfo. GJH 9/13/2017 + CALL ParseVar ( FileInfo, CurLine, 'NonDimArea', p%NonDimArea, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! NumCoords, with the Coords data, is used for determining the blade shape (currently used + ! for visualization only). This data (blade coordinates) is passed to the caller via + ! the InitOut%BladeShape data structure, and stored in p%XCoord, etc., + ! but is currently unused by AFI module. GJH 9/13/2017 + CALL ParseVar ( FileInfo, CurLine, 'NumCoords' , p%NumCoords , ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( p%NumCoords > 0 ) THEN + + ALLOCATE ( p%X_Coord( p%NumCoords ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for p%X_Coord.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( p%Y_Coord( p%NumCoords ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for p%Y_Coord.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + DO Row=1,p%NumCoords + CALL ParseAry ( FileInfo, CurLine, 'X_Coord/Y_Coord', Coords, 2, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + p%X_Coord(Row) = Coords(1) + p%Y_Coord(Row) = Coords(2) + ENDDO ! Row + + ENDIF + + ! Reading Boundary layer file for aeroacoustics + CALL ParseVar ( FileInfo, CurLine, 'BL_file' , p%BL_file , ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( PathIsRelative( p%BL_file ) ) p%BL_file=trim(PriPath)//trim(p%BL_file) + + ! How many columns do we need to read in the input and how many total coefficients will be used? + + Cols2Parse = MAX( InCol_Alfa, InCol_Cl, InCol_Cd, InCol_Cm, InCol_Cpmin ) + ALLOCATE ( SiAry( Cols2Parse ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for SiAry.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + + ! Work through the multiple tables. + + CALL ParseVar ( FileInfo, CurLine, 'NumTabs' , p%NumTabs , ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( p%NumTabs < 1 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'NumTabs must be > 0.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( p%Table( p%NumTabs ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating memory for p%Table.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + DO iTable=1,p%NumTabs + NumCoefsTab = NumCoefsIn ! Reset this counter for each table + + CALL ParseVar ( FileInfo, CurLine, 'Re', p%Table(iTable)%Re, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + p%Table(iTable)%Re = p%Table(iTable)%Re * 1.0e6 ! Entered in millions, so multiply here + IF ( p%Table(iTable)%Re <= 0.0 ) THEN + CALL SetErrStat ( ErrID_Severe, 'Re must be > 0 in "'//TRIM( AFfile ) & + //'".'//NewLine//' >> The error occurred on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(CurLine-1) ) )//'.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF ! ( p%Table(iTable)%Re <= 0.0 ) + + CALL ParseVar ( FileInfo, CurLine, 'UserProp', p%Table(iTable)%UserProp, ErrStat2, ErrMsg2, UnEc ) + if (ErrStat2 >= AbortErrLev) then ! for backward compatibility of input files + CALL ParseVar ( FileInfo, CurLine, 'Ctrl', p%Table(iTable)%UserProp, ErrStat2, ErrMsg2, UnEc ) + end if + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL ParseVar ( FileInfo, CurLine, 'InclUAdata', p%Table(iTable)%InclUAdata, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( p%Table(iTable)%InclUAdata ) THEN + + CALL ParseVar ( FileInfo, CurLine, 'alpha0', p%Table(iTable)%UA_BL%alpha0, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + p%Table(iTable)%UA_BL%alpha0 = p%Table(iTable)%UA_BL%alpha0*D2R + + CALL ParseVar ( FileInfo, CurLine, 'alpha1', p%Table(iTable)%UA_BL%alpha1, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + p%Table(iTable)%UA_BL%alpha1 = p%Table(iTable)%UA_BL%alpha1*D2R + + CALL ParseVar ( FileInfo, CurLine, 'alpha2', p%Table(iTable)%UA_BL%alpha2, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + p%Table(iTable)%UA_BL%alpha2 = p%Table(iTable)%UA_BL%alpha2*D2R + + CALL ParseVar ( FileInfo, CurLine, 'eta_e', p%Table(iTable)%UA_BL%eta_e, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'C_nalpha', p%Table(iTable)%UA_BL%C_nalpha, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +!>>> add after this feature gets tested better: +! CALL ParseVar ( FileInfo, CurLine, 'C_lalpha', p%Table(iTable)%UA_BL%C_lalpha, ErrStat2, ErrMsg2, UnEc ) +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) +!<<< +!>>> remove after this feature gets tested better: +p%Table(iTable)%UA_BL%C_lalpha = p%Table(iTable)%UA_BL%C_nalpha +!<<< + + CALL ParseVarWDefault ( FileInfo, CurLine, 'T_f0', p%Table(iTable)%UA_BL%T_f0, 3.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'T_V0', p%Table(iTable)%UA_BL%T_V0, 6.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'T_p', p%Table(iTable)%UA_BL%T_p, 1.7_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'T_VL', p%Table(iTable)%UA_BL%T_VL, 11.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'b1', p%Table(iTable)%UA_BL%b1, .14_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'b2', p%Table(iTable)%UA_BL%b2, .53_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'b5', p%Table(iTable)%UA_BL%b5, 5.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'A1', p%Table(iTable)%UA_BL%A1, .3_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'A2', p%Table(iTable)%UA_BL%A2, .7_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'A5', p%Table(iTable)%UA_BL%A5, 1.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'S1', p%Table(iTable)%UA_BL%S1, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'S2', p%Table(iTable)%UA_BL%S2, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'S3', p%Table(iTable)%UA_BL%S3, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'S4', p%Table(iTable)%UA_BL%S4, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'Cn1', p%Table(iTable)%UA_BL%Cn1, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'Cn2', p%Table(iTable)%UA_BL%Cn2, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'St_sh', p%Table(iTable)%UA_BL%St_sh, .19_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'Cd0', p%Table(iTable)%UA_BL%Cd0, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'Cm0', p%Table(iTable)%UA_BL%Cm0, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'k0', p%Table(iTable)%UA_BL%k0, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'k1', p%Table(iTable)%UA_BL%k1, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'k2', p%Table(iTable)%UA_BL%k2, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'k3', p%Table(iTable)%UA_BL%k3, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVar ( FileInfo, CurLine, 'k1_hat', p%Table(iTable)%UA_BL%k1_hat, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'x_cp_bar', p%Table(iTable)%UA_BL%x_cp_bar, .2_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ParseVarWDefault ( FileInfo, CurLine, 'UACutout', p%Table(iTable)%UA_BL%UACutout, 45.0_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + p%Table(iTable)%UA_BL%UACutout = p%Table(iTable)%UA_BL%UACutout*D2R + + CALL ParseVarWDefault ( FileInfo, CurLine, 'filtCutOff', p%Table(iTable)%UA_BL%filtCutOff, 0.5_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + p%ColUAf = NumCoefsTab + 1 ! column for f_st + NumCoefsTab = p%ColUAf + 1 ! precompute f_st and cl_fs for the HGM model + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ELSE !ELSEIF ( UA_Model == 1 ) THEN + + !CALL SetErrStat ( ErrID_Fatal & + !, 'You must supply Beddoes-Leishman unsteady aerodynamics parameters for all airfoils if you want to use that' & + !//' model. You did not do so for Table #'//TRIM( Num2LStr( iTable ) )//' in the "'//TRIM( AFfile )//'" airfoil file.', ErrStat, ErrMsg, RoutineName ) + !CALL Cleanup() + !RETURN + + ENDIF ! ( p%Table(iTable)%InclUAdata ) + + CALL ParseVar ( FileInfo, CurLine, 'NumAlf', p%Table(iTable)%NumAlf, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( p%Table(iTable)%NumAlf < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'NumAlf must be a positive number on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(CurLine-1) ) )//' in "'//TRIM( AFfile )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ELSEIF ( p%Table(iTable)%NumAlf < 3 ) THEN + p%Table(iTable)%ConstData = .TRUE. + ELSE + p%Table(iTable)%ConstData = .FALSE. + ENDIF ! ( Test for valid values for NumAlf ) + + + ! Allocate the arrays for the airfoil coefficients. + + ALLOCATE ( p%Table(iTable)%Alpha( p%Table(iTable)%NumAlf ), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for p%Table%Alpha.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( p%Table(iTable)%Coefs( p%Table(iTable)%NumAlf, NumCoefsTab ), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for p%Table%Coefs.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + DO Row=1,p%Table(iTable)%NumAlf + + CALL ParseAry ( FileInfo, CurLine, 'CoeffData', SiAry, Cols2Parse, ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + p%Table(iTable)%Alpha(Row ) = SiAry(InCol_Alfa)*D2R + p%Table(iTable)%Coefs(Row,p%ColCl) = SiAry(InCol_Cl ) + p%Table(iTable)%Coefs(Row,p%ColCd) = SiAry(InCol_Cd ) + + IF ( InCol_Cm > 0 ) p%Table(iTable)%Coefs(Row,p%ColCm ) = SiAry(InCol_Cm) + IF ( InCol_Cpmin > 0 ) p%Table(iTable)%Coefs(Row,p%ColCpmin) = SiAry(InCol_Cpmin) + + ENDDO ! Row + + call CalculateUACoeffs(p%Table(iTable), p%ColCl, p%ColUAf) + + ! Let's make sure that the data go from -Pi to Pi and that the values are the same for both + ! unless there is only one point. + + IF ( .NOT. p%Table(iTable)%ConstData ) THEN + NumAlf = p%Table(iTable)%NumAlf + BadVals = .FALSE. + IF ( .NOT. EqualRealNos( p%Table(iTable)%Alpha(1), -Pi ) ) THEN + BadVals = .TRUE. + ENDIF + IF ( .NOT. EqualRealNos( p%Table(iTable)%Alpha(NumAlf), Pi ) ) THEN + BadVals = .TRUE. + ENDIF + DO Coef=1,NumCoefsTab + IF ( .NOT. EqualRealNos( p%Table(iTable)%Coefs(1,Coef), p%Table(iTable)%Coefs(NumAlf,Coef) ) ) THEN + BadVals = .TRUE. + ENDIF + ENDDO ! Coef + IF ( BadVals ) THEN +! CALL SetErrStat( ErrID_Fatal & + CALL SetErrStat( ErrID_Warn, & + 'Airfoil data should go from -180 degrees to 180 degrees and the coefficients at the ends should be the same.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + ENDIF ! ( .NOT. p%Table(iTable)%ConstData ) + + ! Set the NumCoefs value we return based on tables so far + NumCoefs = max(NumCoefs, NumCoefsTab) + + ENDDO ! iTable + + + CALL Cleanup( ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + + SUBROUTINE Cleanup () + + ! This subroutine cleans up all the allocatable arrays, sets the error status/message and closes the binary file + + CALL NWTC_Library_DestroyFileInfoType (FileInfo, ErrStat2, ErrMsg2) + IF ( ALLOCATED(SiAry) ) DEALLOCATE(SiAry) + + END SUBROUTINE Cleanup + + + END SUBROUTINE ReadAFfile +!---------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE CalculateUACoeffs(p,ColCl,ColUAf) + TYPE (AFI_Table_Type), intent(inout) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + integer(IntKi), intent(in ) :: ColCl ! column for cl + integer(IntKi), intent(in ) :: ColUAf ! column for UA f_st + + INTEGER(IntKi) :: Row ! The row of a table to be parsed in the FileInfo structure. + INTEGER(IntKi) :: col_clFs ! column for UA cl_fs + + REAL(ReKi) :: cl_ratio, cl_inv + REAL(ReKi) :: f_st, cl_fs + REAL(ReKi) :: f_iHigh, f_iLow + INTEGER(IntKi) :: iHigh, iLow + + col_clFs = ColUAf + 1 + + if ( p%InclUAdata ) then + + if (EqualRealNos(p%UA_BL%c_lalpha,0.0_ReKi)) then + p%Coefs(:,ColUAf) = 0.0_ReKi ! Eq. 59 + p%Coefs(:,col_clFs) = p%Coefs(:,ColCl) ! Eq. 61 + else + + f_iHigh = huge(f_iHigh) + f_iLow = f_iHigh + iHigh = 0 + iLow = 0 + + do Row=1,p%NumAlf + + if (EqualRealNos( p%alpha(Row), p%UA_BL%alpha0)) then + f_st = 1.0_ReKi ! Eq. 59 + p%Coefs(Row,col_clFs) = p%Coefs(Row,ColCl) / 2.0_ReKi ! Eq. 61 (which should be very close to 0 because definition of alpha0 says cl(alpha0) = 0 ) + else + + cl_ratio = p%Coefs(Row,ColCl) / ( p%UA_BL%c_lalpha*(p%alpha(Row) - p%UA_BL%alpha0)) + cl_ratio = max(0.0_ReKi, cl_ratio) + + f_st = ( 2.0_ReKi * sqrt(cl_ratio) - 1.0_ReKi )**2 + + if (f_st < 1.0_ReKi) then + ! Region where f_st<1, merge + f_st = max(0.0_ReKi, f_st) ! make sure it is not negative + cl_fs = (p%Coefs(Row,ColCl) - p%UA_BL%c_lalpha* (p%alpha(Row) - p%UA_BL%alpha0)*f_st) / (1.0_ReKi - f_st) ! Eq 61 + else + ! Initialize to linear region (in fact only at singularity, where f_st=1) + f_st = 1.0_ReKi + cl_fs = p%Coefs(Row,ColCl) / 2.0_ReKi ! Eq. 61 + end if + + if (p%alpha(Row) < p%UA_BL%alpha0) then + if (f_st <= f_iLow) then + f_iLow = f_st + iLow = Row + end if + else !p%alpha(Row) > p%UA_BL%alpha0 (note that they can't be equal) + if (f_st < f_iHigh) then + f_iHigh = f_st + iHigh = Row + end if + end if + end if + + p%Coefs(Row,ColUAf) = f_st + p%Coefs(Row,col_clFs) = cl_fs + end do + if (iLow >0) p%Coefs(1:iLow,col_clFs) = p%Coefs(1:iLow,ColCl) + if (iHigh>0) p%Coefs(iHigh:,col_clFs) = p%Coefs(iHigh:,ColCl) + + + ! Ensuring everything is in harmony + do Row=1,p%NumAlf + cl_fs = p%Coefs(Row,col_clFs) + + cl_inv = p%UA_BL%c_lalpha*(p%alpha(Row) - p%UA_BL%alpha0) ! Eq. 64 + if (.not. EqualRealNos(cl_inv, cl_fs)) then + f_st=(p%Coefs(Row,ColCl) - cl_fs) / (cl_inv-cl_fs); ! Eq. 60 + f_st = max(0.0_ReKi, f_st) + f_st = min(1.0_ReKi, f_st) + + p%Coefs(Row,ColUAf) = f_st + else + p%Coefs(Row,ColUAf) = 1.0_ReKi + end if + + end do + end if ! c_lalpha == 0 + + end if + + + + + END SUBROUTINE CalculateUACoeffs +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine FindBoundingTables(p, secondaryDepVal, lowerTable, upperTable, xVals) + + TYPE (AFI_ParameterType), intent(in ) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + real(ReKi), intent(in ) :: secondaryDepVal ! Interpolate secondary values (Re or UserProp) based on this value + + integer(IntKi), intent( out) :: lowerTable ! index of the lower airfoil table p%secondVals(lowerTable) <= secondaryDepVal <= p%secondVals(upperTable) + integer(IntKi), intent( out) :: upperTable ! index of the upper airfoil table ( = lowerTable+1 ) + real(ReKi), intent( out) :: xVals(2) ! this takes the place of time in the extrapInterp routines generated by the Registry + + integer(IntKi) :: iMid + + ! compare algorithm with InterpBinReal + lowerTable = 1 + upperTable = p%NumTabs + + DO WHILE ( upperTable-lowerTable > 1 ) + + iMid = ( upperTable + lowerTable )/2 + + IF ( secondaryDepVal >= p%secondVals(iMid) ) THEN + lowerTable = iMid + ELSE + upperTable = iMid + END IF + + END DO + + xVals(1) = p%secondVals(lowerTable) + xVals(2) = p%secondVals(upperTable) + +end subroutine FindBoundingTables +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AFI_ComputeUACoefs2D( secondaryDepVal, p, UA_BL, errStat, errMsg ) +! This routine is calculates the UA parameters for a set of tables which are dependent a 2nd user-defined varible, could be Re or Cntrl, etc. +! If the requested yVar is not associated with a given table, then the two tables which contain yVar are found and, a cubic spline interpolation is performed at the requested AOA. +! for each of those two tables. Then a linear intepolation is performed on the 2nd dimension to find the final Cl,Cd,Cm, and Cpmin values. +! If the requested yVar corresponds to a table, then only a single cubic interpolation based on the requested AOA is performed. +!.................................................................................................................................. + real(ReKi), intent(in ) :: secondaryDepVal ! Interpolate based on this value + TYPE (AFI_ParameterType), intent(in ) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + type(AFI_UA_BL_Type), intent( out) :: UA_BL + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + real(ReKi) :: xVals(2) ! secondary interpolation values associated with the tables (this takes the place of time in the extrapInterp routines generated by the Registry) + + integer :: lowerTable, upperTable + character(*), parameter :: RoutineName = 'AFI_ComputeUACoefs2D' + + + ErrStat = ErrID_None + ErrMsg = '' + + ! find boundaries for + + ! Let's check the limits first. + + IF ( secondaryDepVal <= p%secondVals( 1 ) ) THEN + ! was call SetErrStat (ErrID_Fatal, "Specified Reynold's number, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of Re specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + ! or call SetErrStat (ErrID_Fatal, "Specified User Property's value, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of User Property values specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + call AFI_CopyUA_BL_Type( p%Table(1)%UA_BL, UA_BL, MESH_NEWCOPY, errStat, errMsg ) ! this doesn't have a mesh, so the control code is irrelevant + return + ELSE IF ( secondaryDepVal >= p%secondVals( p%NumTabs ) ) THEN + ! was call SetErrStat (ErrID_Fatal, "Specified Reynold's number, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of Re specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + ! or call SetErrStat (ErrID_Fatal, "Specified User Property's value, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of User Property values specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + call AFI_CopyUA_BL_Type( p%Table(p%NumTabs)%UA_BL, UA_BL, MESH_NEWCOPY, errStat, errMsg ) ! this doesn't have a mesh, so the control code is irrelevant + return + END IF + + call FindBoundingTables(p, secondaryDepVal, lowerTable, upperTable, xVals) + + ! linearly interpolate + call AFI_UA_BL_Type_ExtrapInterp1(p%Table(lowerTable)%UA_BL, p%Table(upperTable)%UA_BL, xVals, UA_BL, secondaryDepVal, ErrStat, ErrMsg ) + + +end subroutine AFI_ComputeUACoefs2D +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AFI_ComputeAirfoilCoefs2D( AOA, secondaryDepVal, p, AFI_interp, errStat, errMsg ) +! This routine is calculates Cl, Cd, Cm, (and Cpmin) for a set of tables which are dependent on AOA as well as a 2nd user-defined varible, could be Re or Cntrl, etc. +! If the requested yVar is not associated with a given table, then the two tables which contain yVar are found and, a cubic spline interpolation is performed at the requested AOA. +! for each of those two tables. Then a linear intepolation is performed on the 2nd dimension to find the final Cl,Cd,Cm, and Cpmin values. +! If the requested yVar corresponds to a table, then only a single cubic interpolation based on the requested AOA is performed. +!.................................................................................................................................. + real(ReKi), intent(in ) :: AOA + real(ReKi), intent(in ) :: secondaryDepVal ! Unused in the current version! + TYPE (AFI_ParameterType), intent(in ) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + type(AFI_OutputType), intent( out) :: AFI_interp ! contains real(ReKi), intent( out) :: Cl, Cd, Cm, Cpmin + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + integer :: lowerTable, upperTable + real(ReKi) :: xVals(2) + type(AFI_OutputType) :: AFI_lower + type(AFI_OutputType) :: AFI_upper + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( secondaryDepVal <= p%secondVals( 1 ) ) THEN + ! was call SetErrStat (ErrID_Fatal, "Specified Reynold's number, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of Re specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + ! or call SetErrStat (ErrID_Fatal, "Specified User Property's value, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of User Property values specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + call AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_interp, errStat, errMsg, 1 ) + return + ELSE IF ( secondaryDepVal >= p%secondVals( p%NumTabs ) ) THEN + ! was call SetErrStat (ErrID_Fatal, "Specified Reynold's number, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of Re specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + ! or call SetErrStat (ErrID_Fatal, "Specified User Property's value, "//trim(num2lstr(secondaryDepVal))//" , is outside the range of User Property values specified in the airfoil input file tables.", ErrStat, ErrMsg, RoutineName ) + call AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_interp, errStat, errMsg, p%NumTabs ) + return + END IF + + call FindBoundingTables(p, secondaryDepVal, lowerTable, upperTable, xVals) + +!fixme ERROR HANDLING! + call AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_lower, errStat, errMsg, lowerTable ) + if (ErrStat >= AbortErrLev) return + call AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_upper, errStat, errMsg, upperTable ) + if (ErrStat >= AbortErrLev) return + + ! linearly interpolate these values + call AFI_Output_ExtrapInterp1(AFI_lower, AFI_upper, xVals, AFI_interp, secondaryDepVal, ErrStat, ErrMsg ) + + +end subroutine AFI_ComputeAirfoilCoefs2D + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_interp, errStat, errMsg, TableNum ) +! If the requested yVar is not associated with a given table, then the two tables which contain yVar are found and, a cubic spline interpolation is performed at the requested AOA. +! for each of those two tables. Then a linear intepolation is performed on the 2nd dimension to find the final Cl,Cd,Cm, and Cpmin values. +! If the requested yVar corresponds to a table, then only a single cubic interpolation based on the requested AOA is performed. +!.................................................................................................................................. + real(ReKi), intent(in ) :: AOA + TYPE (AFI_ParameterType), intent(in ) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + type(AFI_OutputType) :: AFI_interp ! Cl, Cd, Cm, Cpmin + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + integer(IntKi), optional, intent(in ) :: TableNum + + + real :: IntAFCoefs(MaxNumAFCoeffs) ! The interpolated airfoil coefficients. + real(reki) :: Alpha + integer :: s1 + integer :: iTab + + + ErrStat = ErrID_None + ErrMsg = '' + + if (present(TableNum)) then + iTab = TableNum + else + iTab = 1 + end if + + IntAFCoefs = 0.0_ReKi ! initialize in case we only don't have MaxNumAFCoeffs columns in the airfoil data (e.g., so cm is zero if not in the file) + + s1 = size(p%Table(iTab)%Coefs,2) + + Alpha = AOA + call MPi2Pi ( Alpha ) ! change AOA into range of -pi to pi + + + ! Spline interpolation of lower table based on requested AOA + + IntAFCoefs(1:s1) = CubicSplineInterpM( Alpha & + , p%Table(iTab)%Alpha & + , p%Table(iTab)%Coefs & + , p%Table(iTab)%SplineCoefs & + , ErrStat, ErrMsg ) + + + AFI_interp%Cl = IntAFCoefs(p%ColCl) + AFI_interp%Cd = IntAFCoefs(p%ColCd) + + if ( p%ColCm > 0 ) then + AFI_interp%Cm = IntAFCoefs(p%ColCm) + else + AFI_interp%Cm = 0.0_Reki !Set these to zero unless there is data to be read in + end if + + if ( p%ColCpmin > 0 ) then + AFI_interp%Cpmin = IntAFCoefs(p%ColCpmin) + else + AFI_interp%Cpmin = 0.0_Reki + end if + + if ( p%ColUAf > 0 ) then + AFI_interp%f_st = IntAFCoefs(p%ColUAf) + AFI_interp%cl_fs = IntAFCoefs(p%ColUAf+1) + else + AFI_interp%f_st = 0.0_ReKi + AFI_interp%cl_fs = 0.0_ReKi + end if + + ! needed if using UnsteadyAero: + if (p%Table(iTab)%InclUAdata) then + AFI_interp%Cd0 = p%Table(iTab)%UA_BL%Cd0 + AFI_interp%Cm0 = p%Table(iTab)%UA_BL%Cm0 + else + AFI_interp%Cd0 = 0.0_ReKi + AFI_interp%Cm0 = 0.0_ReKi + end if + +end subroutine AFI_ComputeAirfoilCoefs1D + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates Cl, Cd, Cm, (and Cpmin) for a set of tables which are dependent on AOA as well as a 2nd user-defined varible, could be Re or Cntrl, etc. +subroutine AFI_ComputeAirfoilCoefs( AOA, Re, UserProp, p, AFI_interp, errStat, errMsg ) + + real(ReKi), intent(in ) :: AOA + real(ReKi), intent(in ) :: Re ! Reynold's Number + real(ReKi), intent(in ) :: UserProp !< User property for interpolating airfoil tables + TYPE (AFI_ParameterType), intent(in ) :: p ! This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + type(AFI_OutputType), intent( out) :: AFI_interp ! contains real(ReKi), intent( out) :: Cl, Cd, Cm, Cpmin + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + real(ReKi) :: ReInterp + + ! These coefs are stored in the p data structures based on Re + + if ( p%AFTabMod == AFITable_1 ) then + call AFI_ComputeAirfoilCoefs1D( AOA, p, AFI_interp, errStat, errMsg, 1 ) + elseif ( p%AFTabMod == AFITable_2Re ) then +#ifndef AFI_USE_LINEAR_RE + ReInterp = log( Re ) +#else + ReInterp = Re +#endif + call AFI_ComputeAirfoilCoefs2D( AOA, ReInterp, p, AFI_interp, errStat, errMsg ) + else !if ( p%AFTabMod == AFITable_2User ) then + call AFI_ComputeAirfoilCoefs2D( AOA, UserProp, p, AFI_interp, errStat, errMsg ) + end if + +end subroutine AFI_ComputeAirfoilCoefs + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates Cl, Cd, Cm, (and Cpmin) for a set of tables which are dependent on AOA as well as a 2nd user-defined varible, could be Re or Cntrl, etc. +subroutine AFI_ComputeUACoefs( p, Re, UserProp, UA_BL, errMsg, errStat ) + + type(AFI_ParameterType), intent(in ) :: p !< This structure stores all the module parameters that are set by AirfoilInfo during the initialization phase. + real(ReKi), intent(in ) :: Re !< Reynold's number + real(ReKi), intent(in ) :: UserProp !< User property for interpolating airfoil tables + type(AFI_UA_BL_Type), intent( out) :: UA_BL !< airfoil constants (UA Beddoes-Leishman parameters ) + + integer(IntKi), intent( out) :: errStat !< Error status + character(*), intent( out) :: errMsg !< Error message + + real(ReKi) :: ReInterp + + + ! These coefs are stored in the p data structures based on Re + + if ( p%AFTabMod == AFITable_1 ) then + call AFI_CopyUA_BL_Type( p%Table(1)%UA_BL, UA_BL, MESH_NEWCOPY, errStat, errMsg ) ! this doesn't have a mesh, so the control code is irrelevant + return + elseif ( p%AFTabMod == AFITable_2Re ) then +#ifndef AFI_USE_LINEAR_RE + ReInterp = log( Re ) +#else + ReInterp = Re +#endif + call AFI_ComputeUACoefs2D( ReInterp, p, UA_BL, errStat, errMsg ) + else !if ( p%AFTabMod == AFITable_2User ) then + call AFI_ComputeUACoefs2D( UserProp, p, UA_BL, errStat, errMsg ) + end if + + call MPi2Pi( UA_BL%alpha0 ) + call MPi2Pi( UA_BL%alpha1 ) + call MPi2Pi( UA_BL%alpha2 ) + + ! Cn1=1.9 Tp=1.7 Tf=3., Tv=6 Tvl=11, Cd0=0.012 + +end subroutine AFI_ComputeUACoefs + +!============================================================================= +END MODULE AirfoilInfo diff --git a/OpenFAST/modules/aerodyn/src/AirfoilInfo_Registry.txt b/OpenFAST/modules/aerodyn/src/AirfoilInfo_Registry.txt new file mode 100644 index 000000000..be71570d7 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AirfoilInfo_Registry.txt @@ -0,0 +1,120 @@ +################################################################################################################################### +# Registry for AirfoilInfo in the FAST Modularization Framework +# This Registry file is used to create MODULE AFinfo_Types, which contains all of the user-defined types needed in AirfoilInfo. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# NOTE: All variables initialized here should be double-checked that they are properly initialized in the new framework (i.e. can run twice) +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +param AirfoilInfo/AFI - INTEGER AFITable_1 - 1 - "1D interpolation on AoA (first table only)" - +param AirfoilInfo/AFI - INTEGER AFITable_2Re - 2 - "2D interpolation on AoA and Re" - +param AirfoilInfo/AFI - INTEGER AFITable_2User - 3 - "2D interpolation on AoA and UserProp" - + + +# ..... Airfoil data ............................................................................................................... +# The following derived type stores Beddoes-Leishman unsteady-aero data for an airfoil at a single combination of Re and control setting. The data can be computed internally of not read from the input file. +typedef AirfoilInfo/AFI AFI_UA_BL_Type ReKi alpha0 - - 2pi "Angle of attack for zero lift (also used in HGM)" "input in degrees; stored as radians" +typedef ^ ^ ReKi alpha1 - - 2pi "angle of attack at f = 0.7, approximately the stall angle; for alpha >= alpha0" "input in degrees; stored as radians" +typedef ^ ^ ReKi alpha2 - - 2pi "angle of attack at f = 0.7, approximately the stall angle; for alpha < alpha0" "input in degrees; stored as radians" +typedef ^ ^ ReKi eta_e - - - "Recovery factor in the range [0.85 - 0.95]" - +typedef ^ ^ ReKi C_nalpha - - - "Cn slope for zero lift (used for Beddoes-Leishman unsteady aero)" 1/rad +typedef ^ ^ ReKi C_lalpha - - - "Cl slope for zero lift (used for HGM unsteady aero only) -> calculated" 1/rad +typedef ^ ^ ReKi T_f0 - - - "initial value of T_f, airfoil specific, used to compute D_f and fprimeprime (also used in HGM)" - +typedef ^ ^ ReKi T_V0 - - - "initial value of T_V, airfoil specific, time parameter associated with the vortex lift decay process, used in Cn_v" - +typedef ^ ^ ReKi T_p - - - "boundary-layer, leading edge pressure gradient time parameter; used in D_p; airfoil specific (also used in HGM)" - +typedef ^ ^ ReKi T_VL - - - "Initial value of the time constant associated with the vortex advection process; it represents the non-dimensional time in semi-chords, needed for a vortex to travel from LE to trailing edge (TE); it is used in the expression of Cvn. It depends on Re, M (weakly), and airfoil. [valid range = 6 - 13]" - +typedef ^ ^ ReKi b1 - - - "airfoil constant derived from experimental results (also used in HGM), usually 0.14" - +typedef ^ ^ ReKi b2 - - - "airfoil constant derived from experimental results (also used in HGM), usually 0.53" - +typedef ^ ^ ReKi b5 - - - "airfoil constant derived from experimental results, usually 5.0" - +typedef ^ ^ ReKi A1 - - - "airfoil constant derived from experimental results (also used in HGM), usually 0.3" - +typedef ^ ^ ReKi A2 - - - "airfoil constant derived from experimental results (also used in HGM), usually 0.7" - +typedef ^ ^ ReKi A5 - - - "airfoil constant derived from experimental results, usually 1.0" - +typedef ^ ^ ReKi S1 - - - "Constant in the f curve best-fit for alpha0<=AOA<=alpha1" - +typedef ^ ^ ReKi S2 - - - "Constant in the f curve best-fit for AOA> alpha1" - +typedef ^ ^ ReKi S3 - - - "Constant in the f curve best-fit for alpha2<=AOA< alpha0" - +typedef ^ ^ ReKi S4 - - - "Constant in the f curve best-fit for AOA< alpha2" - +typedef ^ ^ ReKi Cn1 - - - "Cn at stall value for positive angle of attack [or critical value of Cn_prime at LE separation for alpha >= alpha0]" - +typedef ^ ^ ReKi Cn2 - - - "Cn at stall value for negative angle of attack [or critical value of Cn_prime at LE separation for alpha < alpha0]" - +typedef ^ ^ ReKi St_sh - - - "Strouhal's shedding frequency constant." - +typedef ^ ^ ReKi Cd0 - - - "Minimum Cd value" - +typedef ^ ^ ReKi Cm0 - - - "2D pitching moment coefficient at zero lift, positive if nose is up" - +typedef ^ ^ ReKi k0 - - - "airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1]" - +typedef ^ ^ ReKi k1 - - - "airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1]" - +typedef ^ ^ ReKi k2 - - - "airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1]" - +typedef ^ ^ ReKi k3 - - - "airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1]" - +typedef ^ ^ ReKi k1_hat - - - "Constant in the expression of Cc due to leading edge vortex effects. [ignored if UAMod<>1]" - +typedef ^ ^ ReKi x_cp_bar - - - "Constant in the expression of \hat(x)_cp^v [ignored if UAMod<>1, default = 0.2]" - +typedef ^ ^ ReKi UACutout - - - "Angle of attack above which unsteady aerodynamics are disabled" "input in degrees; stored as radians" +typedef ^ ^ ReKi filtCutOff - - - "Reduced frequency cutoff used to calculate the dynamic low pass filter cut-off frequency for the pitching rate and accelerations [default = 0.5]" - + +# The following derived type stores data for an airfoil at a single combination of Re and control setting. +typedef ^ AFI_Table_Type ReKi Alpha {:} - - "Angle-of-attack vector that matches the Coefs matrix" rad +typedef ^ ^ ReKi Coefs {:}{:} - - "Airfoil coefficients for Cd, Cl, and maybe Cm and/or Cpmin" - +typedef ^ ^ ReKi SplineCoefs {:}{:}{:} - - "Spline coefficients for Cd, Cl, and maybe Cm and/or Cpmin" - +typedef ^ ^ ReKi UserProp - - - "User Property for a table, for example a Control setting" - +typedef ^ ^ ReKi Re - - - "Reynolds number" - +typedef ^ ^ INTEGER NumAlf - - - "Length of the Alpha and Coefs arrays" - +typedef ^ ^ LOGICAL ConstData - - - "Flag that tells if aerodynamic coefficients are the same for all alphas" - +typedef ^ ^ LOGICAL InclUAdata - - - "Flag that tells if UA data is included in the input file" - +typedef ^ ^ AFI_UA_BL_Type UA_BL - - - "The tables of Leishman-Beddoes unsteady-aero data for given Re and control setting" - + +# ..... Initialization data ....................................................................................................... +# The following derived type stores information that comes from the calling module (say, AeroDyn): +typedef ^ InitInputType CHARACTER(1024) FileName - - - "The name of the file the data is read from" - +typedef ^ ^ INTEGER AFTabMod - - - "Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp}" - +typedef ^ ^ INTEGER InCol_Alfa - - - "The column of the coefficient tables that holds the angle of attack" - +typedef ^ ^ INTEGER InCol_Cl - - - "The column of the coefficient tables that holds the lift coefficient" - +typedef ^ ^ INTEGER InCol_Cd - - - "The column of the coefficient tables that holds the minimum pressure coefficient" - +typedef ^ ^ INTEGER InCol_Cm - - - "The column of the coefficient tables that holds the pitching-moment coefficient" - +typedef ^ ^ INTEGER InCol_Cpmin - - - "The column of the coefficient tables that holds the minimum pressure coefficient" - + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + + +# ..... Parameters ................................................................................................................ +# Define parameters here: +typedef ^ ParameterType INTEGER ColCd - - - "The column in the p%Coefs arrays that contains Cd data" - +typedef ^ ^ INTEGER ColCl - - - "The column in the p%Coefs arrays that contains Cl data" - +typedef ^ ^ INTEGER ColCm - - - "The column in the p%Coefs arrays that contains Cm data" - +typedef ^ ^ INTEGER ColCpmin - - - "The column in the p%Coefs arrays that contains Cpmin data" - +typedef ^ ^ INTEGER ColUAf - - - "The column in the p%Coefs arrays that contains f_st data for UA" - +typedef ^ ^ INTEGER AFTabMod - - - "Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp}" - +typedef ^ ^ ReKi secondVals {:} - - "The values of the 2nd dependent variable when using multiple airfoil tables (Re or UserProp, saved in an array so that the logic in the interpolation scheme is cleaner)" - +typedef ^ ^ IntKi InterpOrd - - - "Interpolation order" - +typedef ^ ^ ReKi NonDimArea - - - "The non-dimensional area of the airfoil (area/chord^2) [unused]" - +typedef ^ ^ IntKi NumCoords - - - "The number of coordinates which define the airfoil shape" - +typedef ^ ^ ReKi X_Coord {:} - - "X-coordinate for the airfoil shape [unused]" - +typedef ^ ^ ReKi Y_Coord {:} - - "Y-coordinate for the airfoil shape [unused]" - +typedef ^ ^ INTEGER NumTabs - - - "The number of airfoil tables in the airfoil file" - +typedef ^ ^ AFI_Table_Type Table {:} - - "The tables of airfoil data for given Re and control setting" - +typedef ^ ^ CHARACTER(1024) BL_file - - - "The name of the file with the boundary layer data" + +# ..... Inputs .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi AoA - - 2pi "The angle of attack" radians +typedef ^ ^ ReKi UserProp - - - "The user-defined control setting" - +typedef ^ ^ ReKi Re - - - "Reynolds number" - + +# ..... Outputs ................................................................................................................... +# Define outputs that are not contained on the mesh here: +typedef ^ OutputType ReKi Cl - 0. - "Dimensionless coefficient of lift" - +typedef ^ ^ ReKi Cd - 0. - "Dimensionless coefficient of drag" - +typedef ^ ^ ReKi Cm - 0. - "Dimensionless coefficient of pitching moment" - +typedef ^ ^ ReKi Cpmin - 0. - "Dimensionless coefficient of minimum pressure" - +typedef ^ ^ ReKi Cd0 - 0. - "Minimum Cd value (used for Beddoes-Leishman unsteady aero)" - +typedef ^ ^ ReKi Cm0 - 0. - "2D pitching moment coefficient at zero lift, positive if nose is up" - +typedef ^ ^ ReKi f_st - 0. - "separation function (used for UA HGM model)" - +typedef ^ ^ ReKi cl_fs - 0. - "fully separated polar function (used for UA HGM model)" - + + diff --git a/OpenFAST/modules/aerodyn/src/AirfoilInfo_Types.f90 b/OpenFAST/modules/aerodyn/src/AirfoilInfo_Types.f90 new file mode 100644 index 000000000..aa3fb2a01 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/AirfoilInfo_Types.f90 @@ -0,0 +1,2575 @@ +!STARTOFREGISTRYGENERATEDFILE 'AirfoilInfo_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 +!********************************************************************************************************************************* +! AirfoilInfo_Types +!................................................................................................................................. +! This file is part of AirfoilInfo. +! +! 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 AirfoilInfo. 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 AirfoilInfo_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: AFITable_1 = 1 ! 1D interpolation on AoA (first table only) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: AFITable_2Re = 2 ! 2D interpolation on AoA and Re [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: AFITable_2User = 3 ! 2D interpolation on AoA and UserProp [-] +! ========= AFI_UA_BL_Type ======= + TYPE, PUBLIC :: AFI_UA_BL_Type + REAL(ReKi) :: alpha0 !< Angle of attack for zero lift (also used in HGM) [input in degrees; stored as radians] + REAL(ReKi) :: alpha1 !< angle of attack at f = 0.7, approximately the stall angle; for alpha >= alpha0 [input in degrees; stored as radians] + REAL(ReKi) :: alpha2 !< angle of attack at f = 0.7, approximately the stall angle; for alpha < alpha0 [input in degrees; stored as radians] + REAL(ReKi) :: eta_e !< Recovery factor in the range [0.85 - 0.95] [-] + REAL(ReKi) :: C_nalpha !< Cn slope for zero lift (used for Beddoes-Leishman unsteady aero) [1/rad] + REAL(ReKi) :: C_lalpha !< Cl slope for zero lift (used for HGM unsteady aero only) -> calculated [1/rad] + REAL(ReKi) :: T_f0 !< initial value of T_f, airfoil specific, used to compute D_f and fprimeprime (also used in HGM) [-] + REAL(ReKi) :: T_V0 !< initial value of T_V, airfoil specific, time parameter associated with the vortex lift decay process, used in Cn_v [-] + REAL(ReKi) :: T_p !< boundary-layer, leading edge pressure gradient time parameter; used in D_p; airfoil specific (also used in HGM) [-] + REAL(ReKi) :: T_VL !< Initial value of the time constant associated with the vortex advection process; it represents the non-dimensional time in semi-chords, needed for a vortex to travel from LE to trailing edge (TE); it is used in the expression of Cvn. It depends on Re, M (weakly), and airfoil. [valid range = 6 - 13] [-] + REAL(ReKi) :: b1 !< airfoil constant derived from experimental results (also used in HGM), usually 0.14 [-] + REAL(ReKi) :: b2 !< airfoil constant derived from experimental results (also used in HGM), usually 0.53 [-] + REAL(ReKi) :: b5 !< airfoil constant derived from experimental results, usually 5.0 [-] + REAL(ReKi) :: A1 !< airfoil constant derived from experimental results (also used in HGM), usually 0.3 [-] + REAL(ReKi) :: A2 !< airfoil constant derived from experimental results (also used in HGM), usually 0.7 [-] + REAL(ReKi) :: A5 !< airfoil constant derived from experimental results, usually 1.0 [-] + REAL(ReKi) :: S1 !< Constant in the f curve best-fit for alpha0<=AOA<=alpha1 [-] + REAL(ReKi) :: S2 !< Constant in the f curve best-fit for AOA> alpha1 [-] + REAL(ReKi) :: S3 !< Constant in the f curve best-fit for alpha2<=AOA< alpha0 [-] + REAL(ReKi) :: S4 !< Constant in the f curve best-fit for AOA< alpha2 [-] + REAL(ReKi) :: Cn1 !< Cn at stall value for positive angle of attack [or critical value of Cn_prime at LE separation for alpha >= alpha0] [-] + REAL(ReKi) :: Cn2 !< Cn at stall value for negative angle of attack [or critical value of Cn_prime at LE separation for alpha < alpha0] [-] + REAL(ReKi) :: St_sh !< Strouhal's shedding frequency constant. [-] + REAL(ReKi) :: Cd0 !< Minimum Cd value [-] + REAL(ReKi) :: Cm0 !< 2D pitching moment coefficient at zero lift, positive if nose is up [-] + REAL(ReKi) :: k0 !< airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1] [-] + REAL(ReKi) :: k1 !< airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1] [-] + REAL(ReKi) :: k2 !< airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1] [-] + REAL(ReKi) :: k3 !< airfoil parameter in the x_cp_hat curve best-fit [ignored if UAMod<>1] [-] + REAL(ReKi) :: k1_hat !< Constant in the expression of Cc due to leading edge vortex effects. [ignored if UAMod<>1] [-] + REAL(ReKi) :: x_cp_bar !< Constant in the expression of \hat(x)_cp^v [ignored if UAMod<>1, default = 0.2] [-] + REAL(ReKi) :: UACutout !< Angle of attack above which unsteady aerodynamics are disabled [input in degrees; stored as radians] + REAL(ReKi) :: filtCutOff !< Reduced frequency cutoff used to calculate the dynamic low pass filter cut-off frequency for the pitching rate and accelerations [default = 0.5] [-] + END TYPE AFI_UA_BL_Type +! ======================= +! ========= AFI_Table_Type ======= + TYPE, PUBLIC :: AFI_Table_Type + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Alpha !< Angle-of-attack vector that matches the Coefs matrix [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Coefs !< Airfoil coefficients for Cd, Cl, and maybe Cm and/or Cpmin [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SplineCoefs !< Spline coefficients for Cd, Cl, and maybe Cm and/or Cpmin [-] + REAL(ReKi) :: UserProp !< User Property for a table, for example a Control setting [-] + REAL(ReKi) :: Re !< Reynolds number [-] + INTEGER(IntKi) :: NumAlf !< Length of the Alpha and Coefs arrays [-] + LOGICAL :: ConstData !< Flag that tells if aerodynamic coefficients are the same for all alphas [-] + LOGICAL :: InclUAdata !< Flag that tells if UA data is included in the input file [-] + TYPE(AFI_UA_BL_Type) :: UA_BL !< The tables of Leishman-Beddoes unsteady-aero data for given Re and control setting [-] + END TYPE AFI_Table_Type +! ======================= +! ========= AFI_InitInputType ======= + TYPE, PUBLIC :: AFI_InitInputType + CHARACTER(1024) :: FileName !< The name of the file the data is read from [-] + INTEGER(IntKi) :: AFTabMod !< Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp} [-] + INTEGER(IntKi) :: InCol_Alfa !< The column of the coefficient tables that holds the angle of attack [-] + INTEGER(IntKi) :: InCol_Cl !< The column of the coefficient tables that holds the lift coefficient [-] + INTEGER(IntKi) :: InCol_Cd !< The column of the coefficient tables that holds the minimum pressure coefficient [-] + INTEGER(IntKi) :: InCol_Cm !< The column of the coefficient tables that holds the pitching-moment coefficient [-] + INTEGER(IntKi) :: InCol_Cpmin !< The column of the coefficient tables that holds the minimum pressure coefficient [-] + END TYPE AFI_InitInputType +! ======================= +! ========= AFI_InitOutputType ======= + TYPE, PUBLIC :: AFI_InitOutputType + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE AFI_InitOutputType +! ======================= +! ========= AFI_ParameterType ======= + TYPE, PUBLIC :: AFI_ParameterType + INTEGER(IntKi) :: ColCd !< The column in the p%Coefs arrays that contains Cd data [-] + INTEGER(IntKi) :: ColCl !< The column in the p%Coefs arrays that contains Cl data [-] + INTEGER(IntKi) :: ColCm !< The column in the p%Coefs arrays that contains Cm data [-] + INTEGER(IntKi) :: ColCpmin !< The column in the p%Coefs arrays that contains Cpmin data [-] + INTEGER(IntKi) :: ColUAf !< The column in the p%Coefs arrays that contains f_st data for UA [-] + INTEGER(IntKi) :: AFTabMod !< Interpolation method for multiple airfoil tables {1 = 1D on AoA (only first table is used); 2 = 2D on AoA and Re; 3 = 2D on AoA and UserProp} [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: secondVals !< The values of the 2nd dependent variable when using multiple airfoil tables (Re or UserProp, saved in an array so that the logic in the interpolation scheme is cleaner) [-] + INTEGER(IntKi) :: InterpOrd !< Interpolation order [-] + REAL(ReKi) :: NonDimArea !< The non-dimensional area of the airfoil (area/chord^2) [unused] [-] + INTEGER(IntKi) :: NumCoords !< The number of coordinates which define the airfoil shape [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: X_Coord !< X-coordinate for the airfoil shape [unused] [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Y_Coord !< Y-coordinate for the airfoil shape [unused] [-] + INTEGER(IntKi) :: NumTabs !< The number of airfoil tables in the airfoil file [-] + TYPE(AFI_Table_Type) , DIMENSION(:), ALLOCATABLE :: Table !< The tables of airfoil data for given Re and control setting [-] + CHARACTER(1024) :: BL_file !< The name of the file with the boundary layer data [-] + END TYPE AFI_ParameterType +! ======================= +! ========= AFI_InputType ======= + TYPE, PUBLIC :: AFI_InputType + REAL(ReKi) :: AoA !< The angle of attack [radians] + REAL(ReKi) :: UserProp !< The user-defined control setting [-] + REAL(ReKi) :: Re !< Reynolds number [-] + END TYPE AFI_InputType +! ======================= +! ========= AFI_OutputType ======= + TYPE, PUBLIC :: AFI_OutputType + REAL(ReKi) :: Cl = 0. !< Dimensionless coefficient of lift [-] + REAL(ReKi) :: Cd = 0. !< Dimensionless coefficient of drag [-] + REAL(ReKi) :: Cm = 0. !< Dimensionless coefficient of pitching moment [-] + REAL(ReKi) :: Cpmin = 0. !< Dimensionless coefficient of minimum pressure [-] + REAL(ReKi) :: Cd0 = 0. !< Minimum Cd value (used for Beddoes-Leishman unsteady aero) [-] + REAL(ReKi) :: Cm0 = 0. !< 2D pitching moment coefficient at zero lift, positive if nose is up [-] + REAL(ReKi) :: f_st = 0. !< separation function (used for UA HGM model) [-] + REAL(ReKi) :: cl_fs = 0. !< fully separated polar function (used for UA HGM model) [-] + END TYPE AFI_OutputType +! ======================= +CONTAINS + SUBROUTINE AFI_CopyUA_BL_Type( SrcUA_BL_TypeData, DstUA_BL_TypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_UA_BL_Type), INTENT(IN) :: SrcUA_BL_TypeData + TYPE(AFI_UA_BL_Type), INTENT(INOUT) :: DstUA_BL_TypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_CopyUA_BL_Type' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUA_BL_TypeData%alpha0 = SrcUA_BL_TypeData%alpha0 + DstUA_BL_TypeData%alpha1 = SrcUA_BL_TypeData%alpha1 + DstUA_BL_TypeData%alpha2 = SrcUA_BL_TypeData%alpha2 + DstUA_BL_TypeData%eta_e = SrcUA_BL_TypeData%eta_e + DstUA_BL_TypeData%C_nalpha = SrcUA_BL_TypeData%C_nalpha + DstUA_BL_TypeData%C_lalpha = SrcUA_BL_TypeData%C_lalpha + DstUA_BL_TypeData%T_f0 = SrcUA_BL_TypeData%T_f0 + DstUA_BL_TypeData%T_V0 = SrcUA_BL_TypeData%T_V0 + DstUA_BL_TypeData%T_p = SrcUA_BL_TypeData%T_p + DstUA_BL_TypeData%T_VL = SrcUA_BL_TypeData%T_VL + DstUA_BL_TypeData%b1 = SrcUA_BL_TypeData%b1 + DstUA_BL_TypeData%b2 = SrcUA_BL_TypeData%b2 + DstUA_BL_TypeData%b5 = SrcUA_BL_TypeData%b5 + DstUA_BL_TypeData%A1 = SrcUA_BL_TypeData%A1 + DstUA_BL_TypeData%A2 = SrcUA_BL_TypeData%A2 + DstUA_BL_TypeData%A5 = SrcUA_BL_TypeData%A5 + DstUA_BL_TypeData%S1 = SrcUA_BL_TypeData%S1 + DstUA_BL_TypeData%S2 = SrcUA_BL_TypeData%S2 + DstUA_BL_TypeData%S3 = SrcUA_BL_TypeData%S3 + DstUA_BL_TypeData%S4 = SrcUA_BL_TypeData%S4 + DstUA_BL_TypeData%Cn1 = SrcUA_BL_TypeData%Cn1 + DstUA_BL_TypeData%Cn2 = SrcUA_BL_TypeData%Cn2 + DstUA_BL_TypeData%St_sh = SrcUA_BL_TypeData%St_sh + DstUA_BL_TypeData%Cd0 = SrcUA_BL_TypeData%Cd0 + DstUA_BL_TypeData%Cm0 = SrcUA_BL_TypeData%Cm0 + DstUA_BL_TypeData%k0 = SrcUA_BL_TypeData%k0 + DstUA_BL_TypeData%k1 = SrcUA_BL_TypeData%k1 + DstUA_BL_TypeData%k2 = SrcUA_BL_TypeData%k2 + DstUA_BL_TypeData%k3 = SrcUA_BL_TypeData%k3 + DstUA_BL_TypeData%k1_hat = SrcUA_BL_TypeData%k1_hat + DstUA_BL_TypeData%x_cp_bar = SrcUA_BL_TypeData%x_cp_bar + DstUA_BL_TypeData%UACutout = SrcUA_BL_TypeData%UACutout + DstUA_BL_TypeData%filtCutOff = SrcUA_BL_TypeData%filtCutOff + END SUBROUTINE AFI_CopyUA_BL_Type + + SUBROUTINE AFI_DestroyUA_BL_Type( UA_BL_TypeData, ErrStat, ErrMsg ) + TYPE(AFI_UA_BL_Type), INTENT(INOUT) :: UA_BL_TypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyUA_BL_Type' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AFI_DestroyUA_BL_Type + + SUBROUTINE AFI_PackUA_BL_Type( 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(AFI_UA_BL_Type), 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 = 'AFI_PackUA_BL_Type' + ! 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 ! alpha0 + Re_BufSz = Re_BufSz + 1 ! alpha1 + Re_BufSz = Re_BufSz + 1 ! alpha2 + Re_BufSz = Re_BufSz + 1 ! eta_e + Re_BufSz = Re_BufSz + 1 ! C_nalpha + Re_BufSz = Re_BufSz + 1 ! C_lalpha + Re_BufSz = Re_BufSz + 1 ! T_f0 + Re_BufSz = Re_BufSz + 1 ! T_V0 + Re_BufSz = Re_BufSz + 1 ! T_p + Re_BufSz = Re_BufSz + 1 ! T_VL + Re_BufSz = Re_BufSz + 1 ! b1 + Re_BufSz = Re_BufSz + 1 ! b2 + Re_BufSz = Re_BufSz + 1 ! b5 + Re_BufSz = Re_BufSz + 1 ! A1 + Re_BufSz = Re_BufSz + 1 ! A2 + Re_BufSz = Re_BufSz + 1 ! A5 + Re_BufSz = Re_BufSz + 1 ! S1 + Re_BufSz = Re_BufSz + 1 ! S2 + Re_BufSz = Re_BufSz + 1 ! S3 + Re_BufSz = Re_BufSz + 1 ! S4 + Re_BufSz = Re_BufSz + 1 ! Cn1 + Re_BufSz = Re_BufSz + 1 ! Cn2 + Re_BufSz = Re_BufSz + 1 ! St_sh + Re_BufSz = Re_BufSz + 1 ! Cd0 + Re_BufSz = Re_BufSz + 1 ! Cm0 + Re_BufSz = Re_BufSz + 1 ! k0 + Re_BufSz = Re_BufSz + 1 ! k1 + Re_BufSz = Re_BufSz + 1 ! k2 + Re_BufSz = Re_BufSz + 1 ! k3 + Re_BufSz = Re_BufSz + 1 ! k1_hat + Re_BufSz = Re_BufSz + 1 ! x_cp_bar + Re_BufSz = Re_BufSz + 1 ! UACutout + Re_BufSz = Re_BufSz + 1 ! filtCutOff + 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%alpha0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%eta_e + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_nalpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_lalpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_f0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_V0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_p + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_VL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%b1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%b2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%b5 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%A1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%A2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%A5 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%S1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%S2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%S3 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%S4 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%St_sh + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k3 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k1_hat + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%x_cp_bar + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UACutout + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%filtCutOff + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_PackUA_BL_Type + + SUBROUTINE AFI_UnPackUA_BL_Type( 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(AFI_UA_BL_Type), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_UnPackUA_BL_Type' + ! 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%alpha0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%eta_e = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_nalpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_lalpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_f0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_V0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_p = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_VL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%b1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%b2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%b5 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%A1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%A2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%A5 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%S1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%S2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%S3 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%S4 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%St_sh = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k3 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k1_hat = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%x_cp_bar = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UACutout = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%filtCutOff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_UnPackUA_BL_Type + + SUBROUTINE AFI_CopyTable_Type( SrcTable_TypeData, DstTable_TypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_Table_Type), INTENT(IN) :: SrcTable_TypeData + TYPE(AFI_Table_Type), INTENT(INOUT) :: DstTable_TypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_CopyTable_Type' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcTable_TypeData%Alpha)) THEN + i1_l = LBOUND(SrcTable_TypeData%Alpha,1) + i1_u = UBOUND(SrcTable_TypeData%Alpha,1) + IF (.NOT. ALLOCATED(DstTable_TypeData%Alpha)) THEN + ALLOCATE(DstTable_TypeData%Alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTable_TypeData%Alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTable_TypeData%Alpha = SrcTable_TypeData%Alpha +ENDIF +IF (ALLOCATED(SrcTable_TypeData%Coefs)) THEN + i1_l = LBOUND(SrcTable_TypeData%Coefs,1) + i1_u = UBOUND(SrcTable_TypeData%Coefs,1) + i2_l = LBOUND(SrcTable_TypeData%Coefs,2) + i2_u = UBOUND(SrcTable_TypeData%Coefs,2) + IF (.NOT. ALLOCATED(DstTable_TypeData%Coefs)) THEN + ALLOCATE(DstTable_TypeData%Coefs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTable_TypeData%Coefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTable_TypeData%Coefs = SrcTable_TypeData%Coefs +ENDIF +IF (ALLOCATED(SrcTable_TypeData%SplineCoefs)) THEN + i1_l = LBOUND(SrcTable_TypeData%SplineCoefs,1) + i1_u = UBOUND(SrcTable_TypeData%SplineCoefs,1) + i2_l = LBOUND(SrcTable_TypeData%SplineCoefs,2) + i2_u = UBOUND(SrcTable_TypeData%SplineCoefs,2) + i3_l = LBOUND(SrcTable_TypeData%SplineCoefs,3) + i3_u = UBOUND(SrcTable_TypeData%SplineCoefs,3) + IF (.NOT. ALLOCATED(DstTable_TypeData%SplineCoefs)) THEN + ALLOCATE(DstTable_TypeData%SplineCoefs(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTable_TypeData%SplineCoefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTable_TypeData%SplineCoefs = SrcTable_TypeData%SplineCoefs +ENDIF + DstTable_TypeData%UserProp = SrcTable_TypeData%UserProp + DstTable_TypeData%Re = SrcTable_TypeData%Re + DstTable_TypeData%NumAlf = SrcTable_TypeData%NumAlf + DstTable_TypeData%ConstData = SrcTable_TypeData%ConstData + DstTable_TypeData%InclUAdata = SrcTable_TypeData%InclUAdata + CALL AFI_Copyua_bl_type( SrcTable_TypeData%UA_BL, DstTable_TypeData%UA_BL, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AFI_CopyTable_Type + + SUBROUTINE AFI_DestroyTable_Type( Table_TypeData, ErrStat, ErrMsg ) + TYPE(AFI_Table_Type), INTENT(INOUT) :: Table_TypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyTable_Type' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Table_TypeData%Alpha)) THEN + DEALLOCATE(Table_TypeData%Alpha) +ENDIF +IF (ALLOCATED(Table_TypeData%Coefs)) THEN + DEALLOCATE(Table_TypeData%Coefs) +ENDIF +IF (ALLOCATED(Table_TypeData%SplineCoefs)) THEN + DEALLOCATE(Table_TypeData%SplineCoefs) +ENDIF + CALL AFI_Destroyua_bl_type( Table_TypeData%UA_BL, ErrStat, ErrMsg ) + END SUBROUTINE AFI_DestroyTable_Type + + SUBROUTINE AFI_PackTable_Type( 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(AFI_Table_Type), 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 = 'AFI_PackTable_Type' + ! 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 ! Alpha allocated yes/no + IF ( ALLOCATED(InData%Alpha) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Alpha upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Alpha) ! Alpha + END IF + Int_BufSz = Int_BufSz + 1 ! Coefs allocated yes/no + IF ( ALLOCATED(InData%Coefs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Coefs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Coefs) ! Coefs + END IF + Int_BufSz = Int_BufSz + 1 ! SplineCoefs allocated yes/no + IF ( ALLOCATED(InData%SplineCoefs) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SplineCoefs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SplineCoefs) ! SplineCoefs + END IF + Re_BufSz = Re_BufSz + 1 ! UserProp + Re_BufSz = Re_BufSz + 1 ! Re + Int_BufSz = Int_BufSz + 1 ! NumAlf + Int_BufSz = Int_BufSz + 1 ! ConstData + Int_BufSz = Int_BufSz + 1 ! InclUAdata + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA_BL: size of buffers for each call to pack subtype + CALL AFI_Packua_bl_type( Re_Buf, Db_Buf, Int_Buf, InData%UA_BL, ErrStat2, ErrMsg2, .TRUE. ) ! UA_BL + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA_BL + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA_BL + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA_BL + 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 + + IF ( .NOT. ALLOCATED(InData%Alpha) ) 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%Alpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Alpha,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Alpha,1), UBOUND(InData%Alpha,1) + ReKiBuf(Re_Xferred) = InData%Alpha(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Coefs) ) 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%Coefs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Coefs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Coefs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Coefs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Coefs,2), UBOUND(InData%Coefs,2) + DO i1 = LBOUND(InData%Coefs,1), UBOUND(InData%Coefs,1) + ReKiBuf(Re_Xferred) = InData%Coefs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SplineCoefs) ) 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%SplineCoefs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SplineCoefs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SplineCoefs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SplineCoefs,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SplineCoefs,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SplineCoefs,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SplineCoefs,3), UBOUND(InData%SplineCoefs,3) + DO i2 = LBOUND(InData%SplineCoefs,2), UBOUND(InData%SplineCoefs,2) + DO i1 = LBOUND(InData%SplineCoefs,1), UBOUND(InData%SplineCoefs,1) + ReKiBuf(Re_Xferred) = InData%SplineCoefs(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%UserProp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Re + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumAlf + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ConstData, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%InclUAdata, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL AFI_Packua_bl_type( Re_Buf, Db_Buf, Int_Buf, InData%UA_BL, ErrStat2, ErrMsg2, OnlySize ) ! UA_BL + 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 AFI_PackTable_Type + + SUBROUTINE AFI_UnPackTable_Type( 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(AFI_Table_Type), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_UnPackTable_Type' + ! 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 ! Alpha 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%Alpha)) DEALLOCATE(OutData%Alpha) + ALLOCATE(OutData%Alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Alpha,1), UBOUND(OutData%Alpha,1) + OutData%Alpha(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Coefs 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%Coefs)) DEALLOCATE(OutData%Coefs) + ALLOCATE(OutData%Coefs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Coefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Coefs,2), UBOUND(OutData%Coefs,2) + DO i1 = LBOUND(OutData%Coefs,1), UBOUND(OutData%Coefs,1) + OutData%Coefs(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SplineCoefs 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%SplineCoefs)) DEALLOCATE(OutData%SplineCoefs) + ALLOCATE(OutData%SplineCoefs(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%SplineCoefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SplineCoefs,3), UBOUND(OutData%SplineCoefs,3) + DO i2 = LBOUND(OutData%SplineCoefs,2), UBOUND(OutData%SplineCoefs,2) + DO i1 = LBOUND(OutData%SplineCoefs,1), UBOUND(OutData%SplineCoefs,1) + OutData%SplineCoefs(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%UserProp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Re = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumAlf = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ConstData = TRANSFER(IntKiBuf(Int_Xferred), OutData%ConstData) + Int_Xferred = Int_Xferred + 1 + OutData%InclUAdata = TRANSFER(IntKiBuf(Int_Xferred), OutData%InclUAdata) + 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 AFI_Unpackua_bl_type( Re_Buf, Db_Buf, Int_Buf, OutData%UA_BL, ErrStat2, ErrMsg2 ) ! UA_BL + 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 AFI_UnPackTable_Type + + SUBROUTINE AFI_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(AFI_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 = 'AFI_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%FileName = SrcInitInputData%FileName + DstInitInputData%AFTabMod = SrcInitInputData%AFTabMod + DstInitInputData%InCol_Alfa = SrcInitInputData%InCol_Alfa + DstInitInputData%InCol_Cl = SrcInitInputData%InCol_Cl + DstInitInputData%InCol_Cd = SrcInitInputData%InCol_Cd + DstInitInputData%InCol_Cm = SrcInitInputData%InCol_Cm + DstInitInputData%InCol_Cpmin = SrcInitInputData%InCol_Cpmin + END SUBROUTINE AFI_CopyInitInput + + SUBROUTINE AFI_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(AFI_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AFI_DestroyInitInput + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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%FileName) ! FileName + Int_BufSz = Int_BufSz + 1 ! AFTabMod + Int_BufSz = Int_BufSz + 1 ! InCol_Alfa + Int_BufSz = Int_BufSz + 1 ! InCol_Cl + Int_BufSz = Int_BufSz + 1 ! InCol_Cd + Int_BufSz = Int_BufSz + 1 ! InCol_Cm + Int_BufSz = Int_BufSz + 1 ! InCol_Cpmin + 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%AFTabMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InCol_Alfa + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InCol_Cl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InCol_Cd + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InCol_Cm + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InCol_Cpmin + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AFI_PackInitInput + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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%FileName) + OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%AFTabMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Alfa = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Cl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Cd = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Cm = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InCol_Cpmin = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AFI_UnPackInitInput + + SUBROUTINE AFI_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(AFI_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 = 'AFI_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 AFI_CopyInitOutput + + SUBROUTINE AFI_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(AFI_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE AFI_DestroyInitOutput + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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 AFI_PackInitOutput + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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 AFI_UnPackInitOutput + + SUBROUTINE AFI_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_ParameterType), INTENT(IN) :: SrcParamData + TYPE(AFI_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 = 'AFI_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%ColCd = SrcParamData%ColCd + DstParamData%ColCl = SrcParamData%ColCl + DstParamData%ColCm = SrcParamData%ColCm + DstParamData%ColCpmin = SrcParamData%ColCpmin + DstParamData%ColUAf = SrcParamData%ColUAf + DstParamData%AFTabMod = SrcParamData%AFTabMod +IF (ALLOCATED(SrcParamData%secondVals)) THEN + i1_l = LBOUND(SrcParamData%secondVals,1) + i1_u = UBOUND(SrcParamData%secondVals,1) + IF (.NOT. ALLOCATED(DstParamData%secondVals)) THEN + ALLOCATE(DstParamData%secondVals(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%secondVals.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%secondVals = SrcParamData%secondVals +ENDIF + DstParamData%InterpOrd = SrcParamData%InterpOrd + DstParamData%NonDimArea = SrcParamData%NonDimArea + DstParamData%NumCoords = SrcParamData%NumCoords +IF (ALLOCATED(SrcParamData%X_Coord)) THEN + i1_l = LBOUND(SrcParamData%X_Coord,1) + i1_u = UBOUND(SrcParamData%X_Coord,1) + IF (.NOT. ALLOCATED(DstParamData%X_Coord)) THEN + ALLOCATE(DstParamData%X_Coord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%X_Coord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%X_Coord = SrcParamData%X_Coord +ENDIF +IF (ALLOCATED(SrcParamData%Y_Coord)) THEN + i1_l = LBOUND(SrcParamData%Y_Coord,1) + i1_u = UBOUND(SrcParamData%Y_Coord,1) + IF (.NOT. ALLOCATED(DstParamData%Y_Coord)) THEN + ALLOCATE(DstParamData%Y_Coord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Y_Coord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Y_Coord = SrcParamData%Y_Coord +ENDIF + DstParamData%NumTabs = SrcParamData%NumTabs +IF (ALLOCATED(SrcParamData%Table)) THEN + i1_l = LBOUND(SrcParamData%Table,1) + i1_u = UBOUND(SrcParamData%Table,1) + IF (.NOT. ALLOCATED(DstParamData%Table)) THEN + ALLOCATE(DstParamData%Table(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Table.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%Table,1), UBOUND(SrcParamData%Table,1) + CALL AFI_Copytable_type( SrcParamData%Table(i1), DstParamData%Table(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%BL_file = SrcParamData%BL_file + END SUBROUTINE AFI_CopyParam + + SUBROUTINE AFI_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(AFI_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%secondVals)) THEN + DEALLOCATE(ParamData%secondVals) +ENDIF +IF (ALLOCATED(ParamData%X_Coord)) THEN + DEALLOCATE(ParamData%X_Coord) +ENDIF +IF (ALLOCATED(ParamData%Y_Coord)) THEN + DEALLOCATE(ParamData%Y_Coord) +ENDIF +IF (ALLOCATED(ParamData%Table)) THEN +DO i1 = LBOUND(ParamData%Table,1), UBOUND(ParamData%Table,1) + CALL AFI_Destroytable_type( ParamData%Table(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%Table) +ENDIF + END SUBROUTINE AFI_DestroyParam + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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 ! ColCd + Int_BufSz = Int_BufSz + 1 ! ColCl + Int_BufSz = Int_BufSz + 1 ! ColCm + Int_BufSz = Int_BufSz + 1 ! ColCpmin + Int_BufSz = Int_BufSz + 1 ! ColUAf + Int_BufSz = Int_BufSz + 1 ! AFTabMod + Int_BufSz = Int_BufSz + 1 ! secondVals allocated yes/no + IF ( ALLOCATED(InData%secondVals) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! secondVals upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%secondVals) ! secondVals + END IF + Int_BufSz = Int_BufSz + 1 ! InterpOrd + Re_BufSz = Re_BufSz + 1 ! NonDimArea + Int_BufSz = Int_BufSz + 1 ! NumCoords + Int_BufSz = Int_BufSz + 1 ! X_Coord allocated yes/no + IF ( ALLOCATED(InData%X_Coord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! X_Coord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X_Coord) ! X_Coord + END IF + Int_BufSz = Int_BufSz + 1 ! Y_Coord allocated yes/no + IF ( ALLOCATED(InData%Y_Coord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Y_Coord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Y_Coord) ! Y_Coord + END IF + Int_BufSz = Int_BufSz + 1 ! NumTabs + Int_BufSz = Int_BufSz + 1 ! Table allocated yes/no + IF ( ALLOCATED(InData%Table) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Table upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Table,1), UBOUND(InData%Table,1) + Int_BufSz = Int_BufSz + 3 ! Table: size of buffers for each call to pack subtype + CALL AFI_Packtable_type( Re_Buf, Db_Buf, Int_Buf, InData%Table(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Table + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Table + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Table + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Table + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%BL_file) ! BL_file + 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%ColCd + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ColCl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ColCm + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ColCpmin + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ColUAf + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AFTabMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%secondVals) ) 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%secondVals,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%secondVals,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%secondVals,1), UBOUND(InData%secondVals,1) + ReKiBuf(Re_Xferred) = InData%secondVals(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%InterpOrd + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NonDimArea + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCoords + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%X_Coord) ) 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%X_Coord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X_Coord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%X_Coord,1), UBOUND(InData%X_Coord,1) + ReKiBuf(Re_Xferred) = InData%X_Coord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Y_Coord) ) 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%Y_Coord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y_Coord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Y_Coord,1), UBOUND(InData%Y_Coord,1) + ReKiBuf(Re_Xferred) = InData%Y_Coord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumTabs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Table) ) 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%Table,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Table,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Table,1), UBOUND(InData%Table,1) + CALL AFI_Packtable_type( Re_Buf, Db_Buf, Int_Buf, InData%Table(i1), ErrStat2, ErrMsg2, OnlySize ) ! Table + 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 + DO I = 1, LEN(InData%BL_file) + IntKiBuf(Int_Xferred) = ICHAR(InData%BL_file(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE AFI_PackParam + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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%ColCd = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ColCl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ColCm = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ColCpmin = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ColUAf = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AFTabMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! secondVals 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%secondVals)) DEALLOCATE(OutData%secondVals) + ALLOCATE(OutData%secondVals(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%secondVals.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%secondVals,1), UBOUND(OutData%secondVals,1) + OutData%secondVals(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%InterpOrd = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NonDimArea = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumCoords = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X_Coord 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%X_Coord)) DEALLOCATE(OutData%X_Coord) + ALLOCATE(OutData%X_Coord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X_Coord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%X_Coord,1), UBOUND(OutData%X_Coord,1) + OutData%X_Coord(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Y_Coord 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%Y_Coord)) DEALLOCATE(OutData%Y_Coord) + ALLOCATE(OutData%Y_Coord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Y_Coord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Y_Coord,1), UBOUND(OutData%Y_Coord,1) + OutData%Y_Coord(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NumTabs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Table 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%Table)) DEALLOCATE(OutData%Table) + ALLOCATE(OutData%Table(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Table.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Table,1), UBOUND(OutData%Table,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 AFI_Unpacktable_type( Re_Buf, Db_Buf, Int_Buf, OutData%Table(i1), ErrStat2, ErrMsg2 ) ! Table + 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 DO + END IF + DO I = 1, LEN(OutData%BL_file) + OutData%BL_file(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE AFI_UnPackParam + + SUBROUTINE AFI_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_InputType), INTENT(IN) :: SrcInputData + TYPE(AFI_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%AoA = SrcInputData%AoA + DstInputData%UserProp = SrcInputData%UserProp + DstInputData%Re = SrcInputData%Re + END SUBROUTINE AFI_CopyInput + + SUBROUTINE AFI_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(AFI_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AFI_DestroyInput + + SUBROUTINE AFI_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(AFI_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 = 'AFI_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 + Re_BufSz = Re_BufSz + 1 ! AoA + Re_BufSz = Re_BufSz + 1 ! UserProp + Re_BufSz = Re_BufSz + 1 ! Re + 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%AoA + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UserProp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Re + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_PackInput + + SUBROUTINE AFI_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(AFI_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_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 + OutData%AoA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UserProp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Re = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_UnPackInput + + SUBROUTINE AFI_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AFI_OutputType), INTENT(IN) :: SrcOutputData + TYPE(AFI_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'AFI_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%Cl = SrcOutputData%Cl + DstOutputData%Cd = SrcOutputData%Cd + DstOutputData%Cm = SrcOutputData%Cm + DstOutputData%Cpmin = SrcOutputData%Cpmin + DstOutputData%Cd0 = SrcOutputData%Cd0 + DstOutputData%Cm0 = SrcOutputData%Cm0 + DstOutputData%f_st = SrcOutputData%f_st + DstOutputData%cl_fs = SrcOutputData%cl_fs + END SUBROUTINE AFI_CopyOutput + + SUBROUTINE AFI_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(AFI_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AFI_DestroyOutput + + SUBROUTINE AFI_PackOutput( 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(AFI_OutputType), 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 = 'AFI_PackOutput' + ! 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 ! Cl + Re_BufSz = Re_BufSz + 1 ! Cd + Re_BufSz = Re_BufSz + 1 ! Cm + Re_BufSz = Re_BufSz + 1 ! Cpmin + Re_BufSz = Re_BufSz + 1 ! Cd0 + Re_BufSz = Re_BufSz + 1 ! Cm0 + Re_BufSz = Re_BufSz + 1 ! f_st + Re_BufSz = Re_BufSz + 1 ! cl_fs + 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%Cl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cpmin + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%f_st + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%cl_fs + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_PackOutput + + SUBROUTINE AFI_UnPackOutput( 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(AFI_OutputType), 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 = 'AFI_UnPackOutput' + ! 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%Cl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cpmin = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%f_st = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%cl_fs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AFI_UnPackOutput + + + SUBROUTINE AFI_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AFI_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(ReKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(AFI_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(ReKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL AFI_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AFI_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AFI_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AFI_Output_ExtrapInterp + + + SUBROUTINE AFI_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(AFI_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(AFI_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(ReKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(AFI_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: t(2) ! Times associated with the Outputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(y1%Cl - y2%Cl) + y_out%Cl = y1%Cl + b * ScaleFactor + b = -(y1%Cd - y2%Cd) + y_out%Cd = y1%Cd + b * ScaleFactor + b = -(y1%Cm - y2%Cm) + y_out%Cm = y1%Cm + b * ScaleFactor + b = -(y1%Cpmin - y2%Cpmin) + y_out%Cpmin = y1%Cpmin + b * ScaleFactor + b = -(y1%Cd0 - y2%Cd0) + y_out%Cd0 = y1%Cd0 + b * ScaleFactor + b = -(y1%Cm0 - y2%Cm0) + y_out%Cm0 = y1%Cm0 + b * ScaleFactor + b = -(y1%f_st - y2%f_st) + y_out%f_st = y1%f_st + b * ScaleFactor + b = -(y1%cl_fs - y2%cl_fs) + y_out%cl_fs = y1%cl_fs + b * ScaleFactor + END SUBROUTINE AFI_Output_ExtrapInterp1 + + + SUBROUTINE AFI_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(AFI_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(AFI_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(AFI_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(ReKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(AFI_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: t(3) ! Times associated with the Outputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(y1%Cl - y2%Cl) + t(2)**2*(-y1%Cl + y3%Cl))* scaleFactor + c = ( (t(2)-t(3))*y1%Cl + t(3)*y2%Cl - t(2)*y3%Cl ) * scaleFactor + y_out%Cl = y1%Cl + b + c * t_out + b = (t(3)**2*(y1%Cd - y2%Cd) + t(2)**2*(-y1%Cd + y3%Cd))* scaleFactor + c = ( (t(2)-t(3))*y1%Cd + t(3)*y2%Cd - t(2)*y3%Cd ) * scaleFactor + y_out%Cd = y1%Cd + b + c * t_out + b = (t(3)**2*(y1%Cm - y2%Cm) + t(2)**2*(-y1%Cm + y3%Cm))* scaleFactor + c = ( (t(2)-t(3))*y1%Cm + t(3)*y2%Cm - t(2)*y3%Cm ) * scaleFactor + y_out%Cm = y1%Cm + b + c * t_out + b = (t(3)**2*(y1%Cpmin - y2%Cpmin) + t(2)**2*(-y1%Cpmin + y3%Cpmin))* scaleFactor + c = ( (t(2)-t(3))*y1%Cpmin + t(3)*y2%Cpmin - t(2)*y3%Cpmin ) * scaleFactor + y_out%Cpmin = y1%Cpmin + b + c * t_out + b = (t(3)**2*(y1%Cd0 - y2%Cd0) + t(2)**2*(-y1%Cd0 + y3%Cd0))* scaleFactor + c = ( (t(2)-t(3))*y1%Cd0 + t(3)*y2%Cd0 - t(2)*y3%Cd0 ) * scaleFactor + y_out%Cd0 = y1%Cd0 + b + c * t_out + b = (t(3)**2*(y1%Cm0 - y2%Cm0) + t(2)**2*(-y1%Cm0 + y3%Cm0))* scaleFactor + c = ( (t(2)-t(3))*y1%Cm0 + t(3)*y2%Cm0 - t(2)*y3%Cm0 ) * scaleFactor + y_out%Cm0 = y1%Cm0 + b + c * t_out + b = (t(3)**2*(y1%f_st - y2%f_st) + t(2)**2*(-y1%f_st + y3%f_st))* scaleFactor + c = ( (t(2)-t(3))*y1%f_st + t(3)*y2%f_st - t(2)*y3%f_st ) * scaleFactor + y_out%f_st = y1%f_st + b + c * t_out + b = (t(3)**2*(y1%cl_fs - y2%cl_fs) + t(2)**2*(-y1%cl_fs + y3%cl_fs))* scaleFactor + c = ( (t(2)-t(3))*y1%cl_fs + t(3)*y2%cl_fs - t(2)*y3%cl_fs ) * scaleFactor + y_out%cl_fs = y1%cl_fs + b + c * t_out + END SUBROUTINE AFI_Output_ExtrapInterp2 + + + SUBROUTINE AFI_UA_BL_Type_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) UA_BL_Type u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u(:) ! UA_BL_Type at t1 > t2 > t3 + REAL(ReKi), INTENT(IN ) :: t(:) ! Times associated with the UA_BL_Types + TYPE(AFI_UA_BL_Type), INTENT(INOUT) :: u_out ! UA_BL_Type at tin_out + REAL(ReKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_UA_BL_Type_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL AFI_CopyUA_BL_Type(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AFI_UA_BL_Type_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AFI_UA_BL_Type_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AFI_UA_BL_Type_ExtrapInterp + + + SUBROUTINE AFI_UA_BL_Type_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) UA_BL_Type u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u1 ! UA_BL_Type at t1 > t2 + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u2 ! UA_BL_Type at t2 + REAL(ReKi), INTENT(IN ) :: tin(2) ! Times associated with the UA_BL_Types + TYPE(AFI_UA_BL_Type), INTENT(INOUT) :: u_out ! UA_BL_Type at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: t(2) ! Times associated with the UA_BL_Types + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_UA_BL_Type_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL Angles_ExtrapInterp( u1%alpha0, u2%alpha0, tin, u_out%alpha0, tin_out ) + CALL Angles_ExtrapInterp( u1%alpha1, u2%alpha1, tin, u_out%alpha1, tin_out ) + CALL Angles_ExtrapInterp( u1%alpha2, u2%alpha2, tin, u_out%alpha2, tin_out ) + b = -(u1%eta_e - u2%eta_e) + u_out%eta_e = u1%eta_e + b * ScaleFactor + b = -(u1%C_nalpha - u2%C_nalpha) + u_out%C_nalpha = u1%C_nalpha + b * ScaleFactor + b = -(u1%C_lalpha - u2%C_lalpha) + u_out%C_lalpha = u1%C_lalpha + b * ScaleFactor + b = -(u1%T_f0 - u2%T_f0) + u_out%T_f0 = u1%T_f0 + b * ScaleFactor + b = -(u1%T_V0 - u2%T_V0) + u_out%T_V0 = u1%T_V0 + b * ScaleFactor + b = -(u1%T_p - u2%T_p) + u_out%T_p = u1%T_p + b * ScaleFactor + b = -(u1%T_VL - u2%T_VL) + u_out%T_VL = u1%T_VL + b * ScaleFactor + b = -(u1%b1 - u2%b1) + u_out%b1 = u1%b1 + b * ScaleFactor + b = -(u1%b2 - u2%b2) + u_out%b2 = u1%b2 + b * ScaleFactor + b = -(u1%b5 - u2%b5) + u_out%b5 = u1%b5 + b * ScaleFactor + b = -(u1%A1 - u2%A1) + u_out%A1 = u1%A1 + b * ScaleFactor + b = -(u1%A2 - u2%A2) + u_out%A2 = u1%A2 + b * ScaleFactor + b = -(u1%A5 - u2%A5) + u_out%A5 = u1%A5 + b * ScaleFactor + b = -(u1%S1 - u2%S1) + u_out%S1 = u1%S1 + b * ScaleFactor + b = -(u1%S2 - u2%S2) + u_out%S2 = u1%S2 + b * ScaleFactor + b = -(u1%S3 - u2%S3) + u_out%S3 = u1%S3 + b * ScaleFactor + b = -(u1%S4 - u2%S4) + u_out%S4 = u1%S4 + b * ScaleFactor + b = -(u1%Cn1 - u2%Cn1) + u_out%Cn1 = u1%Cn1 + b * ScaleFactor + b = -(u1%Cn2 - u2%Cn2) + u_out%Cn2 = u1%Cn2 + b * ScaleFactor + b = -(u1%St_sh - u2%St_sh) + u_out%St_sh = u1%St_sh + b * ScaleFactor + b = -(u1%Cd0 - u2%Cd0) + u_out%Cd0 = u1%Cd0 + b * ScaleFactor + b = -(u1%Cm0 - u2%Cm0) + u_out%Cm0 = u1%Cm0 + b * ScaleFactor + b = -(u1%k0 - u2%k0) + u_out%k0 = u1%k0 + b * ScaleFactor + b = -(u1%k1 - u2%k1) + u_out%k1 = u1%k1 + b * ScaleFactor + b = -(u1%k2 - u2%k2) + u_out%k2 = u1%k2 + b * ScaleFactor + b = -(u1%k3 - u2%k3) + u_out%k3 = u1%k3 + b * ScaleFactor + b = -(u1%k1_hat - u2%k1_hat) + u_out%k1_hat = u1%k1_hat + b * ScaleFactor + b = -(u1%x_cp_bar - u2%x_cp_bar) + u_out%x_cp_bar = u1%x_cp_bar + b * ScaleFactor + b = -(u1%UACutout - u2%UACutout) + u_out%UACutout = u1%UACutout + b * ScaleFactor + b = -(u1%filtCutOff - u2%filtCutOff) + u_out%filtCutOff = u1%filtCutOff + b * ScaleFactor + END SUBROUTINE AFI_UA_BL_Type_ExtrapInterp1 + + + SUBROUTINE AFI_UA_BL_Type_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) UA_BL_Type u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u1 ! UA_BL_Type at t1 > t2 > t3 + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u2 ! UA_BL_Type at t2 > t3 + TYPE(AFI_UA_BL_Type), INTENT(IN) :: u3 ! UA_BL_Type at t3 + REAL(ReKi), INTENT(IN ) :: tin(3) ! Times associated with the UA_BL_Types + TYPE(AFI_UA_BL_Type), INTENT(INOUT) :: u_out ! UA_BL_Type at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: t(3) ! Times associated with the UA_BL_Types + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AFI_UA_BL_Type_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL Angles_ExtrapInterp( u1%alpha0, u2%alpha0, u3%alpha0, tin, u_out%alpha0, tin_out ) + CALL Angles_ExtrapInterp( u1%alpha1, u2%alpha1, u3%alpha1, tin, u_out%alpha1, tin_out ) + CALL Angles_ExtrapInterp( u1%alpha2, u2%alpha2, u3%alpha2, tin, u_out%alpha2, tin_out ) + b = (t(3)**2*(u1%eta_e - u2%eta_e) + t(2)**2*(-u1%eta_e + u3%eta_e))* scaleFactor + c = ( (t(2)-t(3))*u1%eta_e + t(3)*u2%eta_e - t(2)*u3%eta_e ) * scaleFactor + u_out%eta_e = u1%eta_e + b + c * t_out + b = (t(3)**2*(u1%C_nalpha - u2%C_nalpha) + t(2)**2*(-u1%C_nalpha + u3%C_nalpha))* scaleFactor + c = ( (t(2)-t(3))*u1%C_nalpha + t(3)*u2%C_nalpha - t(2)*u3%C_nalpha ) * scaleFactor + u_out%C_nalpha = u1%C_nalpha + b + c * t_out + b = (t(3)**2*(u1%C_lalpha - u2%C_lalpha) + t(2)**2*(-u1%C_lalpha + u3%C_lalpha))* scaleFactor + c = ( (t(2)-t(3))*u1%C_lalpha + t(3)*u2%C_lalpha - t(2)*u3%C_lalpha ) * scaleFactor + u_out%C_lalpha = u1%C_lalpha + b + c * t_out + b = (t(3)**2*(u1%T_f0 - u2%T_f0) + t(2)**2*(-u1%T_f0 + u3%T_f0))* scaleFactor + c = ( (t(2)-t(3))*u1%T_f0 + t(3)*u2%T_f0 - t(2)*u3%T_f0 ) * scaleFactor + u_out%T_f0 = u1%T_f0 + b + c * t_out + b = (t(3)**2*(u1%T_V0 - u2%T_V0) + t(2)**2*(-u1%T_V0 + u3%T_V0))* scaleFactor + c = ( (t(2)-t(3))*u1%T_V0 + t(3)*u2%T_V0 - t(2)*u3%T_V0 ) * scaleFactor + u_out%T_V0 = u1%T_V0 + b + c * t_out + b = (t(3)**2*(u1%T_p - u2%T_p) + t(2)**2*(-u1%T_p + u3%T_p))* scaleFactor + c = ( (t(2)-t(3))*u1%T_p + t(3)*u2%T_p - t(2)*u3%T_p ) * scaleFactor + u_out%T_p = u1%T_p + b + c * t_out + b = (t(3)**2*(u1%T_VL - u2%T_VL) + t(2)**2*(-u1%T_VL + u3%T_VL))* scaleFactor + c = ( (t(2)-t(3))*u1%T_VL + t(3)*u2%T_VL - t(2)*u3%T_VL ) * scaleFactor + u_out%T_VL = u1%T_VL + b + c * t_out + b = (t(3)**2*(u1%b1 - u2%b1) + t(2)**2*(-u1%b1 + u3%b1))* scaleFactor + c = ( (t(2)-t(3))*u1%b1 + t(3)*u2%b1 - t(2)*u3%b1 ) * scaleFactor + u_out%b1 = u1%b1 + b + c * t_out + b = (t(3)**2*(u1%b2 - u2%b2) + t(2)**2*(-u1%b2 + u3%b2))* scaleFactor + c = ( (t(2)-t(3))*u1%b2 + t(3)*u2%b2 - t(2)*u3%b2 ) * scaleFactor + u_out%b2 = u1%b2 + b + c * t_out + b = (t(3)**2*(u1%b5 - u2%b5) + t(2)**2*(-u1%b5 + u3%b5))* scaleFactor + c = ( (t(2)-t(3))*u1%b5 + t(3)*u2%b5 - t(2)*u3%b5 ) * scaleFactor + u_out%b5 = u1%b5 + b + c * t_out + b = (t(3)**2*(u1%A1 - u2%A1) + t(2)**2*(-u1%A1 + u3%A1))* scaleFactor + c = ( (t(2)-t(3))*u1%A1 + t(3)*u2%A1 - t(2)*u3%A1 ) * scaleFactor + u_out%A1 = u1%A1 + b + c * t_out + b = (t(3)**2*(u1%A2 - u2%A2) + t(2)**2*(-u1%A2 + u3%A2))* scaleFactor + c = ( (t(2)-t(3))*u1%A2 + t(3)*u2%A2 - t(2)*u3%A2 ) * scaleFactor + u_out%A2 = u1%A2 + b + c * t_out + b = (t(3)**2*(u1%A5 - u2%A5) + t(2)**2*(-u1%A5 + u3%A5))* scaleFactor + c = ( (t(2)-t(3))*u1%A5 + t(3)*u2%A5 - t(2)*u3%A5 ) * scaleFactor + u_out%A5 = u1%A5 + b + c * t_out + b = (t(3)**2*(u1%S1 - u2%S1) + t(2)**2*(-u1%S1 + u3%S1))* scaleFactor + c = ( (t(2)-t(3))*u1%S1 + t(3)*u2%S1 - t(2)*u3%S1 ) * scaleFactor + u_out%S1 = u1%S1 + b + c * t_out + b = (t(3)**2*(u1%S2 - u2%S2) + t(2)**2*(-u1%S2 + u3%S2))* scaleFactor + c = ( (t(2)-t(3))*u1%S2 + t(3)*u2%S2 - t(2)*u3%S2 ) * scaleFactor + u_out%S2 = u1%S2 + b + c * t_out + b = (t(3)**2*(u1%S3 - u2%S3) + t(2)**2*(-u1%S3 + u3%S3))* scaleFactor + c = ( (t(2)-t(3))*u1%S3 + t(3)*u2%S3 - t(2)*u3%S3 ) * scaleFactor + u_out%S3 = u1%S3 + b + c * t_out + b = (t(3)**2*(u1%S4 - u2%S4) + t(2)**2*(-u1%S4 + u3%S4))* scaleFactor + c = ( (t(2)-t(3))*u1%S4 + t(3)*u2%S4 - t(2)*u3%S4 ) * scaleFactor + u_out%S4 = u1%S4 + b + c * t_out + b = (t(3)**2*(u1%Cn1 - u2%Cn1) + t(2)**2*(-u1%Cn1 + u3%Cn1))* scaleFactor + c = ( (t(2)-t(3))*u1%Cn1 + t(3)*u2%Cn1 - t(2)*u3%Cn1 ) * scaleFactor + u_out%Cn1 = u1%Cn1 + b + c * t_out + b = (t(3)**2*(u1%Cn2 - u2%Cn2) + t(2)**2*(-u1%Cn2 + u3%Cn2))* scaleFactor + c = ( (t(2)-t(3))*u1%Cn2 + t(3)*u2%Cn2 - t(2)*u3%Cn2 ) * scaleFactor + u_out%Cn2 = u1%Cn2 + b + c * t_out + b = (t(3)**2*(u1%St_sh - u2%St_sh) + t(2)**2*(-u1%St_sh + u3%St_sh))* scaleFactor + c = ( (t(2)-t(3))*u1%St_sh + t(3)*u2%St_sh - t(2)*u3%St_sh ) * scaleFactor + u_out%St_sh = u1%St_sh + b + c * t_out + b = (t(3)**2*(u1%Cd0 - u2%Cd0) + t(2)**2*(-u1%Cd0 + u3%Cd0))* scaleFactor + c = ( (t(2)-t(3))*u1%Cd0 + t(3)*u2%Cd0 - t(2)*u3%Cd0 ) * scaleFactor + u_out%Cd0 = u1%Cd0 + b + c * t_out + b = (t(3)**2*(u1%Cm0 - u2%Cm0) + t(2)**2*(-u1%Cm0 + u3%Cm0))* scaleFactor + c = ( (t(2)-t(3))*u1%Cm0 + t(3)*u2%Cm0 - t(2)*u3%Cm0 ) * scaleFactor + u_out%Cm0 = u1%Cm0 + b + c * t_out + b = (t(3)**2*(u1%k0 - u2%k0) + t(2)**2*(-u1%k0 + u3%k0))* scaleFactor + c = ( (t(2)-t(3))*u1%k0 + t(3)*u2%k0 - t(2)*u3%k0 ) * scaleFactor + u_out%k0 = u1%k0 + b + c * t_out + b = (t(3)**2*(u1%k1 - u2%k1) + t(2)**2*(-u1%k1 + u3%k1))* scaleFactor + c = ( (t(2)-t(3))*u1%k1 + t(3)*u2%k1 - t(2)*u3%k1 ) * scaleFactor + u_out%k1 = u1%k1 + b + c * t_out + b = (t(3)**2*(u1%k2 - u2%k2) + t(2)**2*(-u1%k2 + u3%k2))* scaleFactor + c = ( (t(2)-t(3))*u1%k2 + t(3)*u2%k2 - t(2)*u3%k2 ) * scaleFactor + u_out%k2 = u1%k2 + b + c * t_out + b = (t(3)**2*(u1%k3 - u2%k3) + t(2)**2*(-u1%k3 + u3%k3))* scaleFactor + c = ( (t(2)-t(3))*u1%k3 + t(3)*u2%k3 - t(2)*u3%k3 ) * scaleFactor + u_out%k3 = u1%k3 + b + c * t_out + b = (t(3)**2*(u1%k1_hat - u2%k1_hat) + t(2)**2*(-u1%k1_hat + u3%k1_hat))* scaleFactor + c = ( (t(2)-t(3))*u1%k1_hat + t(3)*u2%k1_hat - t(2)*u3%k1_hat ) * scaleFactor + u_out%k1_hat = u1%k1_hat + b + c * t_out + b = (t(3)**2*(u1%x_cp_bar - u2%x_cp_bar) + t(2)**2*(-u1%x_cp_bar + u3%x_cp_bar))* scaleFactor + c = ( (t(2)-t(3))*u1%x_cp_bar + t(3)*u2%x_cp_bar - t(2)*u3%x_cp_bar ) * scaleFactor + u_out%x_cp_bar = u1%x_cp_bar + b + c * t_out + b = (t(3)**2*(u1%UACutout - u2%UACutout) + t(2)**2*(-u1%UACutout + u3%UACutout))* scaleFactor + c = ( (t(2)-t(3))*u1%UACutout + t(3)*u2%UACutout - t(2)*u3%UACutout ) * scaleFactor + u_out%UACutout = u1%UACutout + b + c * t_out + b = (t(3)**2*(u1%filtCutOff - u2%filtCutOff) + t(2)**2*(-u1%filtCutOff + u3%filtCutOff))* scaleFactor + c = ( (t(2)-t(3))*u1%filtCutOff + t(3)*u2%filtCutOff - t(2)*u3%filtCutOff ) * scaleFactor + u_out%filtCutOff = u1%filtCutOff + b + c * t_out + END SUBROUTINE AFI_UA_BL_Type_ExtrapInterp2 + +END MODULE AirfoilInfo_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/BEMT.f90 b/OpenFAST/modules/aerodyn/src/BEMT.f90 new file mode 100644 index 000000000..2e44dacc9 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/BEMT.f90 @@ -0,0 +1,2488 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 BEMT + + use NWTC_Library + + use BEMT_Types + use BEMTUncoupled + use DBEMT + + use UnsteadyAero + !USE AeroDyn_Types + use AirfoilInfo + + + implicit none + + + private + + type(ProgDesc), parameter :: BEMT_Ver = ProgDesc( 'BEM', '', '' ) + character(*), parameter :: BEMT_Nickname = 'BEM' + + + ! ..... Public Subroutines ................................................................................................... + + public :: BEMT_Init ! Initialization routine + public :: BEMT_End ! Ending routine (includes clean up) + + public :: BEMT_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + public :: BEMT_CalcOutput ! Routine for computing outputs + + public :: BEMT_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + public :: BEMT_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + public :: BEMT_UpdateDiscState ! Tight coupling routine for updating discrete states + + public :: BEMT_ReInit + ! routines for linearization + public :: Get_phi_perturbations + public :: ComputeFrozenWake + public :: CheckLinearizationInput + public :: UpdatePhi + public :: BEMT_InitStates + + contains + + + +!---------------------------------------------------------------------------------------------------------------------------------- +real(ReKi) function ComputePhiWithInduction( Vx, Vy, a, aprime ) +! This routine is used to compute the inflow angle, phi, from the local velocities and the induction factors. +!.................................................................................................................................. + real(ReKi), intent(in ) :: Vx ! Local velocity component along the thrust direction + real(ReKi), intent(in ) :: Vy ! Local velocity component along the rotor plane-of-rotation direction + real(ReKi), intent(in ) :: a ! Axial induction factor + real(ReKi), intent(in ) :: aprime ! Tangential induction factor + + real(ReKi) :: x + real(ReKi) :: y + + x = Vx*(1.0_ReKi-a) + y = Vy*(1.0_ReKi + aprime) + + if ( EqualRealNos(y, 0.0_ReKi) .AND. EqualRealNos(x, 0.0_ReKi) ) then + ComputePhiWithInduction = 0.0_ReKi + else + ComputePhiWithInduction = atan2( x , y ) + end if + + +end function ComputePhiWithInduction + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_Set_UA_InitData( InitInp, interval, Init_UA_Data, errStat, errMsg ) +! This routine is called from BEMT_Init. +! The parameters are set here and not changed during the simulation. +!.................................................................................................................................. + type(BEMT_InitInputType), intent(in ) :: InitInp ! Input data for initialization routine + real(DbKi), intent(in ) :: interval ! time interval + type(UA_InitInputType), intent( out) :: Init_UA_Data ! Parameters + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + integer :: i,j + integer(intKi) :: ErrStat2 ! temporary Error status + + ! Set up initialization data + + Allocate(Init_UA_Data%c(InitInp%numBladeNodes,InitInp%numBlades), STAT = errStat2) + if (ErrStat2 /= 0) then + ErrStat = ErrID_Fatal + ErrMsg = "BEMT_Set_UA_InitData:Error allocating Init_UA_Data%c." + return + else + ErrStat = ErrID_None + ErrMsg = "" + end if + + do j = 1,InitInp%numBlades + do i = 1,InitInp%numBladeNodes + Init_UA_Data%c(i,j) = InitInp%chord(i,j) + end do + end do + + ! TODO:: Fully implement these initialization inputs + + Init_UA_Data%dt = interval + Init_UA_Data%OutRootName = '' + + Init_UA_Data%numBlades = InitInp%numBlades + Init_UA_Data%nNodesPerBlade = InitInp%numBladeNodes + + Init_UA_Data%NumOuts = 0 + Init_UA_Data%UAMod = InitInp%UAMod + Init_UA_Data%Flookup = InitInp%Flookup + Init_UA_Data%a_s = InitInp%a_s ! m/s + +end subroutine BEMT_Set_UA_InitData + + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_SetParameters( InitInp, p, errStat, errMsg ) +! This routine is called from BEMT_Init. +! The parameters are set here and not changed during the simulation. +!.................................................................................................................................. + type(BEMT_InitInputType), intent(in ) :: InitInp ! Input data for initialization routine + type(BEMT_ParameterType), intent( out) :: 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(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_SetParameters' + integer(IntKi) :: i, j + + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + p%numBladeNodes = InitInp%numBladeNodes + p%numBlades = InitInp%numBlades + p%UA_Flag = InitInp%UA_Flag + p%DBEMT_Mod = InitInp%DBEMT_Mod + + allocate ( p%chord(p%numBladeNodes, p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%chord.', errStat, errMsg, RoutineName ) + return + end if + + allocate ( p%zHub(p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%zHub.', errStat, errMsg, RoutineName ) + return + end if + + allocate ( p%AFindx(p%numBladeNodes,p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%AFindx.', errStat, errMsg, RoutineName ) + return + end if + + allocate ( p%tipLossConst(p%numBladeNodes, p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%tipLossConst.', errStat, errMsg, RoutineName ) + return + end if + + allocate ( p%hubLossConst(p%numBladeNodes, p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%hubLossConst.', errStat, errMsg, RoutineName ) + return + end if + + allocate ( p%FixedInductions(p%numBladeNodes, p%numBlades), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for p%numBladeNodes.', errStat, errMsg, RoutineName ) + return + end if + + p%AFindx = InitInp%AFindx + + ! Compute the tip and hub loss constants using the distances along the blade (provided as input for now) + do j=1,p%numBlades + p%zHub(j) = InitInp%zHub(j) + do i=1,p%numBladeNodes + p%chord(i,j) = InitInp%chord(i,j) + p%tipLossConst(i,j) = p%numBlades*(InitInp%zTip (j) - InitInp%zLocal(i,j)) / (2.0*InitInp%zLocal(i,j)) + p%hubLossConst(i,j) = p%numBlades*(InitInp%zLocal(i,j) - InitInp%zHub (j)) / (2.0*InitInp%zHub (j)) + end do + end do + + + !p%DT = InitInp%DT + p%airDens = InitInp%airDens + p%kinVisc = InitInp%kinVisc + p%skewWakeMod = InitInp%skewWakeMod + p%yawCorrFactor = InitInp%yawCorrFactor + p%useTipLoss = InitInp%useTipLoss + p%useHubLoss = InitInp%useHubLoss + p%useInduction = InitInp%useInduction + p%useTanInd = InitInp%useTanInd + p%useAIDrag = InitInp%useAIDrag + p%useTIDrag = InitInp%useTIDrag + p%numReIterations = InitInp%numReIterations + p%maxIndIterations = InitInp%maxIndIterations + p%aTol = InitInp%aTol + + + ! setting this condition here so we don't have to do some many EqualRealNos() checks later in the code. + do j=1,p%numBlades + do i=1,p%numBladeNodes + p%FixedInductions(i,j) = ( p%useTiploss .and. EqualRealNos(p%tipLossConst(i,j),0.0_ReKi) ) .or. ( p%useHubloss .and. EqualRealNos(p%hubLossConst(i,j),0.0_ReKi) ) + end do + end do + +end subroutine BEMT_SetParameters + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_InitContraintStates( z, p, errStat, errMsg ) +! This routine is called from BEMT_Init. +! The constraint state data is allocated and set to zero. +!.................................................................................................................................. + + type(BEMT_ConstraintStateType), intent( out) :: z ! Input data for initialization routine + type(BEMT_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(*), parameter :: RoutineName = 'BEMT_InitContraintStates' + integer(IntKi) :: errStat2 ! temporary Error status of the operation + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + allocate ( z%phi( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for z%phi.', errStat, errMsg, RoutineName ) + return + end if + +end subroutine BEMT_InitContraintStates + + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_InitOtherStates( OtherState, p, errStat, errMsg ) +! This routine is called from BEMT_Init. +! The OtherState data is allocated and set to zero. +!.................................................................................................................................. + + type(BEMT_OtherStateType), intent(inout) :: OtherState ! OtherState data + type(BEMT_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(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_InitOtherStates' + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + ! We need to set an other state version so that we can change this during execution if the AOA is too large! + allocate ( OtherState%UA_Flag( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for OtherState%UA_Flag.', errStat, errMsg, RoutineName ) + return + end if + + if (p%UseInduction) then + + allocate ( OtherState%ValidPhi( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for OtherState%ValidPhi.', errStat, errMsg, RoutineName ) + return + end if + + end if + + ! values of the OtherStates are initialized in BEMT_ReInit() + +end subroutine BEMT_InitOtherStates + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_AllocInput( u, p, errStat, errMsg ) +! This routine is called from BEMT_Init. +! +! +!.................................................................................................................................. + + type(BEMT_InputType), intent( out) :: u ! Input data + type(BEMT_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 + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_AllocInput' + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + allocate ( u%theta( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%theta.', errStat, errMsg, RoutineName ) + return + end if + u%theta = 0.0_ReKi + + allocate ( u%psi( p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%psi.', errStat, errMsg, RoutineName ) + return + end if + u%psi = 0.0_ReKi + + allocate ( u%Vx( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%Vx.', errStat, errMsg, RoutineName ) + return + end if + u%Vx = 0.0_ReKi + + allocate ( u%Vy( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%Vy.', errStat, errMsg, RoutineName ) + return + end if + u%Vy = 0.0_ReKi + + if (p%DBEMT_Mod==DBEMT_cont_tauConst) then + allocate ( u%Vx_elast_dot( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%Vx_dot.', errStat, errMsg, RoutineName ) + return + end if + u%Vx_elast_dot = 0.0_ReKi + + allocate ( u%Vy_elast_dot( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%Vy_dot.', errStat, errMsg, RoutineName ) + return + end if + u%Vy_elast_dot = 0.0_ReKi + end if + + allocate ( u%omega_z( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%omega_z.', errStat, errMsg, RoutineName ) + return + end if + u%omega_z = 0.0_ReKi + + allocate ( u%rLocal( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%rLocal.', errStat, errMsg, RoutineName ) + return + end if + u%rLocal = 0.0_ReKi + + allocate ( u%UserProp( p%numBladeNodes, p%numBlades ), STAT = errStat2 ) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%UserProp.', errStat, errMsg, RoutineName ) + return + end if + u%UserProp = 0.0_ReKi + + + u%omega = 0.0_ReKi + +end subroutine BEMT_AllocInput + + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_AllocOutput( y, p, errStat, errMsg ) +! This routine is called from BEMT_Init. +! +! +!.................................................................................................................................. + + type(BEMT_OutputType), intent( out) :: y ! output data + type(BEMT_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(ErrMsgLen ) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_AllocOutput' + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + call allocAry( y%Vrel, p%numBladeNodes, p%numBlades, 'y%Vrel', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%phi, p%numBladeNodes, p%numBlades, 'y%phi', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%chi, p%numBladeNodes, p%numBlades, 'y%chi', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Re, p%numBladeNodes, p%numBlades, 'y%Re', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%axInduction, p%numBladeNodes, p%numBlades, 'y%axInduction', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%tanInduction, p%numBladeNodes, p%numBlades, 'y%tanInduction', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%AOA, p%numBladeNodes, p%numBlades, 'y%AOA', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cx, p%numBladeNodes, p%numBlades, 'y%Cx', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cy, p%numBladeNodes, p%numBlades, 'y%Cy', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cm, p%numBladeNodes, p%numBlades, 'y%Cm', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cl, p%numBladeNodes, p%numBlades, 'y%Cl', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cd, p%numBladeNodes, p%numBlades, 'y%Cd', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call allocAry( y%Cpmin, p%numBladeNodes, p%numBlades, 'm%Cpmin', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + if (ErrStat >= AbortErrLev) RETURN + + ! outputs documented in AeroDyn + y%Vrel = 0.0_ReKi + y%phi = 0.0_ReKi + y%Cx = 0.0_ReKi + y%Cy = 0.0_ReKi + y%Cm = 0.0_ReKi + + ! others: + y%chi = 0.0_ReKi + y%Re = 0.0_ReKi + y%axInduction = 0.0_ReKi + y%tanInduction = 0.0_ReKi + y%AOA = 0.0_ReKi + y%Cl = 0.0_ReKi + y%Cd = 0.0_ReKi + y%Cpmin = 0.0_ReKi +end subroutine BEMT_AllocOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_Init( InitInp, u, p, x, xd, z, OtherState, AFInfo, y, misc, Interval, InitOut, ErrStat, ErrMsg ) +! 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. +! The initial states and initial guess for the input are defined. +!.................................................................................................................................. + + type(BEMT_InitInputType), intent(inout) :: InitInp ! Input data for initialization routine; intent out so that we can use MOVE_ALLOC + type(BEMT_InputType), intent( out) :: u ! An initial guess for the input; input mesh must be defined + type(BEMT_ParameterType), intent( out) :: p ! Parameters + type(BEMT_ContinuousStateType), intent( out) :: x ! Initial continuous states + type(BEMT_DiscreteStateType), intent( out) :: xd ! Initial discrete states + type(BEMT_ConstraintStateType), intent( out) :: z ! Initial guess of the constraint states + type(BEMT_OtherStateType), intent( out) :: OtherState ! Initial other states + type(BEMT_MiscVarType), intent( out) :: misc ! Initial misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + type(BEMT_OutputType), intent( out) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + real(DbKi), intent(in ) :: interval ! Coupling interval in seconds: the rate that + ! (1) BEMT_UpdateStates() is called in loose coupling & + ! (2) BEMT_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + type(BEMT_InitOutputType), intent( out) :: InitOut ! Output for initialization routine + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_Init' + type(UA_InitInputType) :: Init_UA_Data + type(UA_InitOutputType) :: InitOutData_UA + + type(DBEMT_InitInputType) :: InitInp_DBEMT + type(DBEMT_InitOutputType) :: InitOut_DBEMT + +#ifdef UA_OUTS + integer(IntKi) :: i +#endif + + ! Initialize variables for this routine + errStat = ErrID_None + errMsg = "" + + + ! Initialize the NWTC Subroutine Library + call NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information +! call DispNVD( BEMT_Ver ) + + + !............................................................................................ + ! Define parameters here + !............................................................................................ + + call BEMT_SetParameters( InitInp, p, errStat, errMsg ) + if (errStat >= AbortErrLev) return + p%DT = interval + !............................................................................................ + ! Define states here + !............................................................................................ + + + ! initialize the constraint states + call BEMT_InitContraintStates( z, p, errStat2, errMsg2 ) ! initialize the constraint states + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + ! initialize the continuous states in DBEMT and/or UA + + ! Initialize other states + call BEMT_InitOtherStates( OtherState, p, errStat, errMsg ) ! initialize the other states + if (errStat >= AbortErrLev) return + + if ( p%DBEMT_Mod /= DBEMT_none ) then + InitInp_DBEMT%DBEMT_Mod = p%DBEMT_Mod + InitInp_DBEMT%numBlades = p%numBlades + InitInp_DBEMT%numNodes = p%numBladeNodes + InitInp_DBEMT%tau1_const = InitInp%tau1_const + + allocate(misc%u_DBEMT(2),stat=errStat2) + if (errStat2 /= 0) then + call SetErrStat(ErrID_Fatal,"Error allocating u_DBEMT",errStat,errMsg,RoutineName) + return + end if + + if (allocated(InitInp%rlocal)) then + call MOVE_ALLOC( InitInp%rlocal, InitInp_DBEMT%rlocal ) + else + ! If not allocated we have a problem! Issue an error and return + call SetErrStat( ErrID_FATAL, " An InitInp%rlocal array has not been allocated and is required for DBEMT_Mod /= 0.", errStat, errMsg, RoutineName ) + end if + if (errStat>=AbortErrLev) return + + call DBEMT_Init(InitInp_DBEMT, misc%u_DBEMT(1), p%DBEMT, x%DBEMT, OtherState%DBEMT, misc%DBEMT, interval, InitOut_DBEMT, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + call MOVE_ALLOC( InitInp_DBEMT%rlocal, InitInp%rlocal ) + + call DBEMT_CopyInput(misc%u_DBEMT(1),misc%u_DBEMT(2), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + else + p%DBEMT%lin_nx = 0 + end if + + + ! in calcOutput, we will use the UA inputs for output calculations, so we must allocate them regardless of UA_Flag: + allocate(misc%u_UA( p%numBladeNodes, p%numBlades, 2), stat=errStat2) + if (errStat2 /= 0) then + call SetErrStat(ErrID_Fatal,"Error allocating u_UA",errStat,errMsg,RoutineName) + call cleanup() + return + end if + + if ( p%UA_Flag ) then + call BEMT_Set_UA_InitData( InitInp, interval, Init_UA_Data, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) then + call cleanup() + return + end if + + call UA_Init( Init_UA_Data, misc%u_UA(1,1,1), p%UA, x%UA, xd%UA, OtherState%UA, misc%y_UA, misc%UA, interval, InitOutData_UA, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) then + call cleanup() + return + end if + p%UA%ShedEffect=.True. ! This should be true when coupled to BEM. True in registry as default. + + + ! note: we check the validity of using UA in BEMT_ReInit() + +# ifdef UA_OUTS + !CALL GetNewUnit( UnUAOuts, ErrStat, ErrMsg ) + !IF ( ErrStat /= ErrID_None ) RETURN + + CALL OpenFOutFile ( 69, 'Debug.UA.out', errStat, errMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! Heading: + WRITE (69,'(/,A)') 'This output information was generated by '//TRIM( GetNVD(BEMT_Ver) )// & + ' on '//CurDate()//' at '//CurTime()//'.' + WRITE (69,'(:,A20)', ADVANCE='no' ) 'Time' + do i=1,size(InitOutData_UA%WriteOutputHdr) + WRITE (69,'(:,A20)', ADVANCE='no' ) trim(InitOutData_UA%WriteOutputHdr(i)) + end do + write (69,'(A)') ' ' + + WRITE (69,'(:,A20)', ADVANCE='no' ) '(s)' + do i=1,size(InitOutData_UA%WriteOutputUnt) + WRITE (69,'(:,A20)', ADVANCE='no' ) trim(InitOutData_UA%WriteOutputUnt(i)) + end do + write (69,'(A)') ' ' +# endif + else + p%UA%lin_nx = 0 + end if ! unsteady aero is used + + + !............................................................................................ + ! Define initial guess for the system inputs here: + !............................................................................................ + + ! allocate all the arrays that store data in the input type: + call BEMT_AllocInput( u, p, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) then + call cleanup() + return + end if + + + call BEMT_AllocOutput(y, p, errStat2, errMsg2) !u is sent so we can create sibling meshes + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) then + call cleanup() + return + end if + + + InitOut%Version = BEMT_Ver + + + call AllocAry(misc%AxInduction, p%numBladeNodes,p%numBlades,'misc%AxInduction', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + call AllocAry(misc%TanInduction,p%numBladeNodes,p%numBlades,'misc%TanInduction', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + call AllocAry(misc%Rtip,p%numBlades,'misc%Rtip', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + call AllocAry(misc%phi,p%numBladeNodes,p%numBlades,'misc%phi', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + call AllocAry(misc%chi,p%numBladeNodes,p%numBlades,'misc%chi', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + call AllocAry(misc%ValidPhi,p%numBladeNodes,p%numBlades,'misc%ValidPhi', errStat2,errMsg2); call SetErrStat(errStat2,errMsg2,errStat,errMsg,RoutineName) + + if (errStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! set initial values for states and misc vars + call BEMT_ReInit(p,x,xd,z,OtherState,misc,AFinfo,ErrStat2,ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + call Cleanup() + +CONTAINS + !............................................................................................................................... + SUBROUTINE Cleanup() + ! This subroutine cleans up local variables that may have allocatable arrays + !............................................................................................................................... + + call UA_DestroyInitInput( Init_UA_Data, ErrStat2, ErrMsg2 ) + call UA_DestroyInitOutput( InitOutData_UA, ErrStat2, ErrMsg2 ) + + END SUBROUTINE Cleanup + +END SUBROUTINE BEMT_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reinitializes BEMT and UA, assuming that we will start the simulation over again, with only the inputs being different. +!! This allows us to bypass reading input files and allocating arrays. +subroutine BEMT_ReInit(p,x,xd,z,OtherState,misc,AFinfo,ErrStat,ErrMsg) + + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(inout) :: x ! Initial continuous states + type(BEMT_DiscreteStateType), intent(inout) :: xd ! Initial discrete states + type(BEMT_ConstraintStateType), intent(inout) :: z ! Initial guess of the constraint states + type(BEMT_OtherStateType), intent(inout) :: OtherState ! Initial other states + type(BEMT_MiscVarType), intent(inout) :: misc ! Initial misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_ReInit' + + ErrStat = ErrID_None + ErrMsg = "" + + misc%useFrozenWake = .FALSE. + misc%FirstWarn_Skew = .true. + misc%FirstWarn_Phi = .true. + misc%FirstWarn_BEMoff = .true. + misc%BEM_weight = 0.0_ReKi + + OtherState%DBEMT%tau1 = 0.0_ReKi !we're going to output this value, so let's initialize it + + if (p%UseInduction) then + OtherState%ValidPhi = .true. + + if (p%DBEMT_Mod /= DBEMT_none ) then + call DBEMT_ReInit(p%DBEMT, x%DBEMT, OtherState%DBEMT, misc%DBEMT) + end if + + else + misc%AxInduction = 0.0_ReKi + misc%TanInduction = 0.0_ReKi + end if + + z%phi = 0.0_ReKi + OtherState%nodesInitialized = .false. ! z%phi hasn't been initialized properly, so make sure we compute a value for phi until we've updated them in the first call to BEMT_UpdateStates() + + OtherState%UA_Flag = p%UA_Flag + if (p%UA_Flag) then + call UA_ReInit( p%UA, x%UA, xd%UA, OtherState%UA, misc%UA, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call BEMT_CheckInitUA(p, OtherState, AFInfo, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + + +end subroutine BEMT_ReInit +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine finds C_nalpha for each node, and turns off unsteady aero for that node if C_nalpha=0. It is called only during initialization. +subroutine BEMT_CheckInitUA(p, OtherState, AFInfo, ErrStat, ErrMsg) + + type(BEMT_ParameterType), intent(in ) :: p !< Parameters + type(BEMT_OtherStateType), intent(inout) :: OtherState !< Initial other states + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + integer(IntKi) :: i,j ! node and blade loop counters + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + + + + ErrStat = ErrID_None + ErrMsg = "" + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes ! Loop over blades and nodes + + call UA_TurnOff_param(p%UA, AFInfo(p%AFindx(i,j)), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + call WrScr( 'Warning: Turning off Unsteady Aerodynamics because '//trim(ErrMsg2)//" "//trim(NodeText(i,j)) ) + OtherState%UA_Flag(i,j) = .false. + end if + + end do + end do + +end subroutine BEMT_CheckInitUA +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_End( u, p, x, xd, z, OtherState, y, ErrStat, ErrMsg ) +! This routine is called at the end of the simulation. +!.................................................................................................................................. + + TYPE(BEMT_InputType), INTENT(INOUT) :: u ! System inputs + TYPE(BEMT_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(BEMT_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states + TYPE(BEMT_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states + TYPE(BEMT_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states + TYPE(BEMT_OtherStateType), INTENT(INOUT) :: OtherState ! Other states + TYPE(BEMT_OutputType), INTENT(INOUT) :: y ! System outputs + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL BEMT_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL BEMT_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL BEMT_DestroyContState( x, ErrStat, ErrMsg ) + CALL BEMT_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL BEMT_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL BEMT_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL BEMT_DestroyOutput( y, ErrStat, ErrMsg ) + +#ifdef UA_OUTS + CLOSE(69) +#endif + + +END SUBROUTINE BEMT_End + + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_UpdateStates( t, n, u1, u2, p, x, xd, z, OtherState, AFInfo, m, errStat, errMsg ) +! Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states +! Continuous, constraint, discrete, and other states are updated for t + Interval +! +! NOTE: This is a non-standard framework interface!!!!! GJH +!.................................................................................................................................. + + real(DbKi), intent(in ) :: t ! Current simulation time in seconds + integer(IntKi), intent(in ) :: n ! Current simulation time step n = 0,1,... + type(BEMT_InputType), intent(in ) :: u1,u2 ! Input at t and t+ dt + !real(DbKi), intent(in ) :: utime ! Times associated with u(:), in seconds + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(inout) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + Interval + type(BEMT_DiscreteStateType), intent(inout) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + type(BEMT_ConstraintStateType), intent(inout) :: z ! Input: Constraint states at t; + ! Output: Constraint states at t + Interval + type(BEMT_OtherStateType), intent(inout) :: OtherState ! Input: Other states at t; + ! Output: Other states at t + Interval + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + integer(IntKi) :: i,j + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_UpdateStates' + real(DbKi) :: uTimes(2) + + ErrStat = ErrID_None + ErrMsg = "" + + uTimes(1) = t + uTimes(2) = t+p%dt + + !............................................................................................................................... + ! if we haven't initialized z%phi, we want to get a better guess as to what the actual values of phi at t are: + !............................................................................................................................... + + if (.not. OtherState%nodesInitialized) then + call UpdatePhi( u1, p, z%phi, AFInfo, m, OtherState%ValidPhi, errStat2, errMsg2 ) + OtherState%nodesInitialized = .true. ! otherState updated to t+dt (i.e., n+1) + end if + + !............................................................................................................................... + ! compute inputs to DBEMT at step n (also setting inductions--including DBEMT and skewed wake corrections--at time n) + !............................................................................................................................... + call BEMT_CalcOutput_Inductions( 1, t, .true., .true., z%phi, u1, p, x, xd, z, OtherState, AFInfo, m%axInduction, m%tanInduction, m%chi, m, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + +#ifdef DEBUG_BEMT_RESIDUAL + if (p%useInduction) call WriteDEBUGValuesToFile(t, u1, p, x, xd, z, OtherState, m, AFInfo) +#endif + !............................................................................................................................... + ! compute inputs to UA at step n + !............................................................................................................................... + if (p%UA_Flag) then + call CalculateInputsAndOtherStatesForUA(1, u1, p, x, xd, z, OtherState, AFInfo, m) + end if + + !............................................................................................................................... + ! update BEMT states to step n+1 + !............................................................................................................................... + call UpdatePhi( u2, p, z%phi, AFInfo, m, OtherState%ValidPhi, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (errStat >= AbortErrLev) return + + + !............................................................................................................................... + ! compute inputs to DBEMT at step n+1 (also setting inductions--WITHOUT DBEMT or skewed wake corrections--at step n+1) + !............................................................................................................................... + call BEMT_CalcOutput_Inductions( 2, t, .true., .false., z%phi, u2, p, x, xd, z, OtherState, AFInfo, m%axInduction, m%tanInduction, m%chi, m, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + !............................................................................................................................... + ! update DBEMT states to step n+1 + !............................................................................................................................... + if (p%DBEMT_Mod /= DBEMT_none) then + + !........................ + ! update DBEMT states to t+dt + !........................ + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + call DBEMT_UpdateStates(i, j, t, n, m%u_DBEMT, p%DBEMT, x%DBEMT, OtherState%DBEMT, m%DBEMT, errStat2, errMsg2) + if (ErrStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j))) + if (errStat >= AbortErrLev) return + end if + end do + end do + + end if + + + !............................................................................................................................... + ! compute inputs to UA at time n+1 (also applying corrections to inductions--including DBEMT and skewed wake corrections) + !............................................................................................................................... + if (p%UA_Flag) then + ! after updating DBEMT states, we can now apply the corrections we omitted on the last call to BEMT_CalcOutput_Inductions() + if ( p%useInduction .and. .not. m%UseFrozenWake) then + !............................................ + ! apply DBEMT correction to axInduction and tanInduction: + !............................................ + if (p%DBEMT_Mod /= DBEMT_none) then + call calculate_Inductions_from_DBEMT_AllNodes(2, uTimes(2), u2, p, x, OtherState, m, m%axInduction, m%tanInduction) + end if + + call ApplySkewedWakeCorrection_AllNodes(p, u2, m, m%axInduction, m%chi) + + !............................................ + ! If TSR is too low, (start to) turn off induction + !............................................ + call check_turnOffBEMT(p, u2, m%BEM_weight, m%axInduction, m%tanInduction, m%FirstWarn_BEMoff) + + end if + + call CalculateInputsAndOtherStatesForUA(2, u2, p, x, xd, z, OtherState, AFInfo, m) + + !............................................................................................................................... + ! compute UA states at t+dt + !............................................................................................................................... + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + + ! We only update the UnsteadyAero states if we have unsteady aero turned on for this node + if (OtherState%UA_Flag(i,j)) then + ! COMPUTE: x%UA and/or xd%UA, OtherState%UA + call UA_UpdateStates( i, j, t, n, m%u_UA(i,j,:), uTimes, p%UA, x%UA, xd%UA, OtherState%UA, AFInfo(p%AFIndx(i,j)), m%UA, errStat2, errMsg2 ) + if (ErrStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j))) + if (errStat >= AbortErrLev) return + end if + + end if + + end do + end do + + end if ! is UA used? + +end subroutine BEMT_UpdateStates +!.................................................................................................................................. +subroutine SetInputs_For_DBEMT(u_DBEMT, u, p, axInduction, tanInduction, Rtip) + ! note that this subroutine inherits all data from BEMT_UpdateStates + type(BEMT_InputType), intent(in ) :: u ! BEMT Input + type(BEMT_ParameterType), intent(in ) :: p ! BEMT parameters + type(DBEMT_InputType), intent(inout) :: u_DBEMT ! DBEMT Input + real(ReKi), intent(in ) :: axInduction(:,:) + real(ReKi), intent(in ) :: tanInduction(:,:) + real(ReKi), intent(in ) :: Rtip(:) + + integer :: i, j + + + ! Locate the maximum rlocal value for all blades. + u_DBEMT%R_disk = Rtip(1) + do j = 2,p%numBlades + u_DBEMT%R_disk = max( u_DBEMT%R_disk , Rtip(j) ) + end do + + if (p%DBEMT_Mod == DBEMT_tauVaries ) then + + ! We need to generate a disk-averaged axial induction for this timestep + u_DBEMT%AxInd_disk = 0.0_ReKi + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + u_DBEMT%AxInd_disk = u_DBEMT%AxInd_disk + axInduction(i,j) + + u_DBEMT%element(i,j)%spanRatio = u%rlocal(i,j)/u_DBEMT%R_disk + end do + end do + u_DBEMT%AxInd_disk = u_DBEMT%AxInd_disk / (p%numBladeNodes*p%numBlades) + + u_DBEMT%Un_disk = u%Un_disk + end if + + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + u_DBEMT%element(i,j)%vind_s(1) = -axInduction( i,j)*u%Vx(i,j) ! Eq. 38 + u_DBEMT%element(i,j)%vind_s(2) = tanInduction(i,j)*u%Vy(i,j) ! Eq. 38 + end do + end do + + if( allocated(u%Vx_elast_dot)) then ! only for DBEMT_Mod=DBEMT_cont_tauConst + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + u_DBEMT%element(i,j)%vind_s_dot(1) = axInduction( i,j)*u%Vx_elast_dot(i,j) - u%omega_z(i,j)*tanInduction(i,j)*u%Vy(i,j) ! Eq. 41 + u_DBEMT%element(i,j)%vind_s_dot(2) = -tanInduction(i,j)*u%Vy_elast_dot(i,j) - u%omega_z(i,j)*axInduction( i,j)*u%Vx(i,j) ! Eq. 41 + end do + end do + end if + + +end subroutine SetInputs_For_DBEMT +!.................................................................................................................................. +subroutine CalculateInputsAndOtherStatesForUA(InputIndex, u, p, x, xd, z, OtherState, AFInfo, m) + integer(IntKi), intent(in ) :: InputIndex ! InputIndex= 1 or 2, depending on time step we are calculating inputs for + type(BEMT_InputType), intent(in ) :: u ! Input + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + Interval + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + type(BEMT_ConstraintStateType), intent(in ) :: z ! Input: Constraint states at t; + ! Output: Constraint states at t + Interval + type(BEMT_OtherStateType), intent(inout) :: OtherState ! Input: Other states at t; + ! Output: Other states at t + Interval + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + + + integer(IntKi) :: i,j + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + + + + !............................................................................................................................... + ! compute inputs to UA at time n (also setting inductions--including DBEMT and skewed wake corrections--at time n) + !............................................................................................................................... + m%phi = z%phi + call SetInputs_for_UA_AllNodes(u, p, m%phi, m%axInduction, m%tanInduction, m%u_UA(:,:,InputIndex)) + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + + ! We only update the UnsteadyAero states if we have unsteady aero turned on for this node + if (OtherState%UA_Flag(i,j)) then + ! ....... check inputs to UA ........... + call UA_TurnOff_input(p%UA, AFInfo(p%AFIndx(i,j)), m%u_UA(i,j,InputIndex), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + OtherState%UA_Flag(i,j) = .FALSE. + call WrScr( 'Warning: Turning off Unsteady Aerodynamics due to '//trim(ErrMsg2)//" "//trim(NodeText(i,j)) ) + end if + end if + + end do + end do + +end subroutine CalculateInputsAndOtherStatesForUA + +!.................................................................................................................................. +subroutine UpdatePhi( u, p, phi, AFInfo, m, ValidPhi, errStat, errMsg ) +!.................................................................................................................................. + + type(BEMT_InputType), intent(in ) :: u ! Input at t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + real(ReKi), intent(inout) :: phi(:,:) + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + logical, intent(inout) :: ValidPhi(:,:) ! if this is a valid BEM solution of phi + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + integer(IntKi) :: i,j + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'UpdatePhi' + + + ErrStat = ErrID_None + ErrMsg = "" + + !............................................................................................................................... + ! take the current guess of z%phi and update it using inputs + ! [called if we haven't initialized z%phi, we want to get a better guess as to what the actual values of phi at t are + ! *or* if we are updating the BEMT states] + !............................................................................................................................... + + if (p%useInduction) then + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + + call BEMT_UnCoupledSolve(p, u, i, j, phi(i,j), AFInfo(p%AFIndx(i,j)), & + ValidPhi(i,j), m%FirstWarn_Phi,errStat2, errMsg2) + + if (errStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j))) + if (errStat >= AbortErrLev) return + end if + end do + end do + else + ! We'll simply compute a geometrical phi based on both induction factors being 0.0 + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + phi(i,j) = ComputePhiWithInduction(u%Vx(i,j), u%Vy(i,j), 0.0_ReKi, 0.0_ReKi) + end do + end do + + end if + + return + +end subroutine UpdatePhi +!.................................................................................................................................. +subroutine GetRTip( u, p, RTip ) +!.................................................................................................................................. + + type(BEMT_InputType), intent(in ) :: u ! Input at t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + real(ReKi), intent( out) :: Rtip(:) + + integer(IntKi) :: i,j + + do j = 1,p%numBlades + + ! Locate the maximum rlocal value for this time step and this blade. This is passed to the solve as Rtip. + Rtip(j) = u%rlocal(1,j) + do i = 2,p%numBladeNodes + Rtip(j) = max( Rtip(j), u%rlocal(i,j) ) + end do + + end do + + return + +end subroutine GetRTip +!.................................................................................................................................. +subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,tanInduction, ErrStat,ErrMsg) + + type(BEMT_ParameterType), intent(in ) :: p !< Parameters + real(ReKi), intent(in ) :: phi(:,:) !< phi + type(BEMT_InputType), intent(in ) :: u !< Inputs at t + type(BEMT_OtherStateType), intent(in ) :: OtherState !< Other/logical states at t + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + real(ReKi), intent(inout) :: axInduction(:,:) !< axial induction + real(ReKi), intent(inout) :: tanInduction(:,:) !< tangential induction + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + integer(IntKi) :: i !< blade node counter + integer(IntKi) :: j !< blade counter + + real(ReKi) :: fzero !< residual from induction equation (not used here) + logical :: IsValidSolution !< this indicates BEMT found a geometric solution because a BEMT solution could not be found + integer(IntKi) :: errStat2 !< Error status of the operation + character(ErrMsgLen) :: errMsg2 !< Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'calculate_Inductions_from_BEMT' + + ErrStat = ErrID_None + ErrMsg = "" + + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + + if (OtherState%ValidPhi(i,j)) then + + ! Need to get the induction factors for these conditions without skewed wake correction and without UA + ! COMPUTE: axInduction, tanInduction + fzero = BEMTU_InductionWithResidual(p, u, i, j, phi(i,j), AFInfo(p%AFIndx(i,j)), IsValidSolution, ErrStat2, ErrMsg2, a=axInduction(i,j), ap=tanInduction(i,j)) + + if (ErrStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j))) + if (errStat >= AbortErrLev) return + end if + + ! modify inductions based on max/min allowed values (note that we do this before calling DBEMT so that its disk-averaged induction input isn't dominated by very large values here + if (.not. IsValidSolution) then + axInduction(i,j) = 0.0_ReKi + tanInduction(i,j) = 0.0_ReKi + else + call limitInductionFactors(axInduction(i,j), tanInduction(i,j)) + end if + + else + + axInduction(i,j) = 0.0_ReKi + tanInduction(i,j) = 0.0_ReKi + + end if + + end do + end do + +end subroutine calculate_Inductions_from_BEMT +!.................................................................................................................................. +subroutine calculate_Inductions_from_DBEMT(i, j, Vx, Vy, t, p, u, x, OtherState, m, axInduction, tanInduction) + + integer(IntKi), intent(in ) :: i !< blade node counter + integer(IntKi), intent(in ) :: j !< blade counter + real(ReKi), intent(in ) :: Vx !< Velocity + real(ReKi), intent(in ) :: Vy !< Velocity + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_InputType), intent(in ) :: u !< Inputs for DBEMT module (note that there aren't any allocatable arrays or pointers); CalcOutput needs only vind_s to be set, and only at initialization + type(DBEMT_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(DBEMT_OtherStateType), intent(in ) :: OtherState !< Other/logical states at t + real(ReKi), intent(inout) :: axInduction !< axial induction + real(ReKi), intent(inout) :: tanInduction !< tangential induction + + real(ReKi) :: dbemt_vind(2) + + ! DBEMT doesn't set ErrStat/ErrMsg to anything but ErrStat=ErrID_None so these are local variables + integer(IntKi) :: errStat !< Error status of the operation + character(ErrMsgLen) :: errMsg !< Error message if ErrStat /= ErrID_None + + ! Note that the outputs of DBEMT are the state variables x%vind, except on the first call when they uninitialized and use the inputs in place of the states + + call DBEMT_CalcOutput( i, j, t, u, dbemt_vind, p, x, OtherState, m, errStat, errMsg ) + + if ( EqualRealnos(Vx, 0.0_ReKi) ) then + axInduction = 0.0_ReKi + else + axInduction = -dbemt_vind(1)/Vx + end if + + if ( EqualRealnos(Vy, 0.0_ReKi) ) then + tanInduction = 0.0_ReKi + else + tanInduction = dbemt_vind(2)/Vy + end if + + call limitInductionFactors(axInduction, tanInduction) + +end subroutine calculate_Inductions_from_DBEMT +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine check_turnOffBEMT(p, u, Weight, axInduction, tanInduction, FirstWarn) + + type(BEMT_ParameterType), intent(in ) :: p !< Parameters + type(BEMT_InputType), intent(in ) :: u !< Inputs at t + real(ReKi), intent( out) :: Weight !< scaling value from BEM-to-non_BEM solution (blends inductions from BEMT and non-BEMT[zeros]) + real(ReKi), intent(inout) :: axInduction(:,:) !< axial induction + real(ReKi), intent(inout) :: tanInduction(:,:) !< tangential induction + logical, intent(inout) :: FirstWarn !< Whether BEM had a warning about being shut off + + integer(IntKi) :: i !< blade node counter + integer(IntKi) :: j !< blade counter + + if( u%TSR < BEMT_upperBoundTSR ) then + + Weight = BlendCosine( u%TSR, BEMT_lowerBoundTSR, BEMT_upperBoundTSR ) + + if (FirstWarn) then + if (Weight < 1.0_ReKi) then + call WrScr( 'The BEM solution is being turned off due to low TSR. (TSR = ' & + //TRIM(Num2Lstr(u%TSR))//'). This warning will not be repeated though the condition may persist. (See GeomPhi output channel.)' ) + FirstWarn = .false. + end if + end if + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + ! weighted average with BEM turned off (if TSR falls in certain range): + axInduction( i,j) = axInduction( i,j)*Weight + tanInduction(i,j) = tanInduction(i,j)*Weight + end do + end do + + else + Weight = 1.0_ReKi + end if + +end subroutine check_turnOffBEMT +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_CalcOutput( t, u, p, x, xd, z, OtherState, AFInfo, y, m, errStat, errMsg ) +! Routine for computing outputs, used in both loose and tight coupling. +!.................................................................................................................................. + + + real(DbKi), intent(in ) :: t ! Current simulation time in seconds + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at t + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at t + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at t + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + type(BEMT_OutputType), intent(inout) :: y ! Outputs computed at t (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + 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 ! Generic index + integer(IntKi) :: j ! Loops through nodes / elements + integer(IntKi), parameter :: InputIndex=1 ! we will always use values at t in this routine + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_CalcOutput' + + type(AFI_OutputType) :: AFI_interp + + +#ifdef UA_OUTS + integer(IntKi) :: k +#endif + + ! Initialize some output values + errStat = ErrID_None + errMsg = "" + + +#ifdef UA_OUTS + ! if ( mod(REAL(t,ReKi),.1) < p%dt) then + if (allocated(m%y_UA%WriteOutput)) m%y_UA%WriteOutput = 0.0 !reset to zero in case UA shuts off mid-simulation +#endif + +!!#ifdef DEBUG_BEMT_RESIDUAL +!! call WriteDEBUGValuesToFile(t, u, p, x, xd, z, OtherState, m, AFInfo) +!!#endif + + y%phi = z%phi ! set this before possibly calling UpdatePhi() because phi is intent(inout) in the solve + + !............................................................................................................................... + ! if we haven't initialized z%phi, we want to get a better guess as to what the actual values of phi are: + !............................................................................................................................... + if (.not. OtherState%nodesInitialized) then + call UpdatePhi( u, p, y%phi, AFInfo, m, m%ValidPhi, errStat2, errMsg2 ) + end if + + !............................................ + ! calculate inductions using BEMT, applying the DBEMT, and/or skewed wake corrections as applicable: + !............................................ + call BEMT_CalcOutput_Inductions( InputIndex, t, .false., .true., y%phi, u, p, x, xd, z, OtherState, AFInfo, y%axInduction, y%tanInduction, y%chi, m, errStat, errMsg ) + + !............................................ + ! update phi if necessary (consistent with inductions) and calculate inputs to UA: + !............................................ + call SetInputs_for_UA_AllNodes(u, p, y%phi, y%axInduction, y%tanInduction, m%u_UA(:,:,InputIndex)) + + !............................................ + ! unsteady aero and related outputs (cl, cd, cm, AoA, Vrel, Re) + !............................................ + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + + ! set output values: + y%AOA( i,j) = m%u_UA(i,j,InputIndex)%alpha + y%Vrel(i,j) = m%u_UA(i,j,InputIndex)%U + y%Re( i,j) = m%u_UA(i,j,InputIndex)%Re + + ! Now depending on the option for UA get the airfoil coefs, Cl, Cd, Cm for unsteady or steady implementation + if (OtherState%UA_Flag(i,j) ) then + call UA_CalcOutput(i, j, m%u_UA(i,j,InputIndex), p%UA, x%UA, xd%UA, OtherState%UA, AFInfo(p%AFindx(i,j)), m%y_UA, m%UA, errStat2, errMsg2 ) + y%Cl(i,j) = m%y_UA%Cl + y%Cd(i,j) = m%y_UA%Cd + y%Cm(i,j) = m%y_UA%Cm + else + ! compute steady Airfoil Coefs + call AFI_ComputeAirfoilCoefs( y%AOA(i,j), y%Re(i,j), u%UserProp(i,j), AFInfo(p%AFindx(i,j)), AFI_interp, errStat2, errMsg2 ) + y%Cl(i,j) = AFI_interp%Cl + y%Cd(i,j) = AFI_interp%Cd + y%Cm(i,j) = AFI_interp%Cm + y%Cpmin(i,j) = AFI_interp%Cpmin + end if + if (ErrStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j))) + if (errStat >= AbortErrLev) return + end if + + enddo ! I - Blade nodes / elements + enddo ! J - All blades + + + !............................................ + ! Compute Cx, Cy given Cl, Cd and phi + !............................................ + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + ! NOTE: For these calculations we force the useAIDrag and useTIDrag flags to .TRUE. + call Transform_ClCd_to_CxCy( y%phi(i,j), .TRUE., .TRUE., y%Cl(i,j), y%Cd(i,j),y%Cx(i,j), y%Cy(i,j) ) + + enddo ! I - Blade nodes / elements + enddo ! J - All blades + +#ifdef UA_OUTS + ! if ( mod(REAL(t,ReKi),.1) < p%dt) then + if (allocated(m%y_UA%WriteOutput)) & + WRITE (69, '(F20.6,'//trim(num2lstr(size(m%y_UA%WriteOutput)))//'(:,1x,ES19.5E3))') t, ( m%y_UA%WriteOutput(k), k=1,size(m%y_UA%WriteOutput)) + ! end if +#endif + + return + + +end subroutine BEMT_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine used in linearization to get the states initialized properly at t=0 (before perturbing things) +subroutine BEMT_InitStates(t, u, p, x, xd, z, OtherState, m, AFInfo, ErrStat, ErrMsg ) + REAL(DbKi), intent(in ) :: t ! current simulation time + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(inout) :: x ! Continuous states at t + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at t + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at t + type(BEMT_OtherStateType), intent(inout) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: i, j + INTEGER(IntKi), parameter :: InputIndex = 1 + LOGICAL, parameter :: CalculateDBEMTInputs = .true. + LOGICAL, parameter :: ApplyCorrections = .true. + + integer(IntKi) :: errStat2 ! Error status of the operation + character(ErrMsgLen) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'BEMT_InitStates' + + + ErrStat = ErrID_None + ErrMsg = "" + + if (OtherState%nodesInitialized) return + + m%phi = z%phi + call BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, ApplyCorrections, m%phi, u, p, x, xd, z, OtherState, AFInfo, m%axInduction, m%tanInduction, m%chi, m, errStat, errMsg ) + + if (p%DBEMT_Mod /= DBEMT_none) then + call DBEMT_InitStates_AllNodes( m%u_DBEMT(InputIndex), p%DBEMT, x%DBEMT, OtherState%DBEMT ) + end if + + if (p%UA_Flag) then + call CalculateInputsAndOtherStatesForUA(InputIndex, u, p, x, xd, z, OtherState, AFInfo, m) + call UA_InitStates_AllNodes( m%u_UA(i,j,InputIndex), p%UA, x%UA, OtherState%UA, OtherState%UA_Flag, AFInfo, p%AFIndx ) + end if ! is UA used? + + +end subroutine BEMT_InitStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing inductions outputs, used in both loose and tight coupling. +subroutine BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, ApplyCorrections, phi, u, p, x, xd, z, OtherState, AFInfo, axInduction, tanInduction, chi, m, errStat, errMsg ) +!.................................................................................................................................. + + REAL(DbKi), intent(in ) :: t ! current simulation time + INTEGER(IntKi), intent(in ) :: InputIndex ! index into m%u_DEBMT (1 or 2) + LOGICAL, intent(in ) :: CalculateDBEMTInputs ! if called from UpdateStates, we'd want the DBEMT inputs calculated. Otherwise it saves time not to calculate them + LOGICAL, intent(in ) :: ApplyCorrections ! if called from UpdateStates and we haven't updated DBEMT states, we'd want to avoid applying DBEMT and the skewed wake corrections + REAL(ReKi), intent(in ) :: phi(:,:) + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at t + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at t + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at t + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + REAL(ReKi), intent(inout) :: axInduction(:,:) + REAL(ReKi), intent(inout) :: tanInduction(:,:) + REAL(ReKi), intent(inout) :: chi(:,:) ! value used in skewed wake correction + 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 ! Generic index + integer(IntKi) :: j ! Loops through nodes / elements + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_CalcOutput_Inductions' + + + ! Initialize some output values + errStat = ErrID_None + errMsg = "" + + + chi = u%chi0 ! with no induction, chi = chi0 at all nodes (overwritten in ApplySkewedWakeCorrection) + + if ( p%useInduction ) then + + if (m%UseFrozenWake) then ! note that this is used only when DBEMT_Mod==DBEMT_none + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + ! note that we've already checked if these velocities are zero before calling this routine in linearization + !BJJ: THIS ISN'T NECESSARIALLY TRUE ANYMORE + if (EqualRealNos(u%Vx(i,j),0.0_ReKi)) then + axInduction(i,j) = 0.0_ReKi ! does this violate the frozen wake requirements???? + else + axInduction(i,j) = -m%AxInd_op(i,j) / u%Vx(i,j) + end if + if (EqualRealNos(u%Vy(i,j),0.0_ReKi)) then + tanInduction(i,j) = 0.0_ReKi ! does this violate the frozen wake requirements???? + else + tanInduction(i,j) = m%TnInd_op(i,j) / u%Vy(i,j) + end if + enddo ! I - Blade nodes / elements + enddo ! J - All blades + + else + + ! Locate the maximum rlocal value for this time step and this blade. This is passed to the solve as Rtip. + call GetRTip( u, p, m%Rtip ) + + !............................................ + ! get BEMT inductions (axInduction and tanInduction): + !............................................ + call calculate_Inductions_from_BEMT(p, phi, u, OtherState, AFInfo, axInduction, tanInduction, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (errStat >= AbortErrLev) return + + !............................................ + ! apply DBEMT correction to axInduction and tanInduction: + !............................................ + if (p%DBEMT_Mod /= DBEMT_none) then + ! If we are using DBEMT, then we will obtain the time-filtered versions of axInduction(i,j), tanInduction(i,j) + + ! Note that the outputs of DBEMT are the state variables x%vind, so we don't NEED to set the inputs except on initialization step (when we output the inputs instead of the states) + ! If calling from UpdateStates, we'd want to have a copy of the DBEMT inputs for updating its states later + if (CalculateDBEMTInputs .or. .not. OtherState%nodesInitialized) then + call SetInputs_For_DBEMT(m%u_DBEMT(InputIndex), u, p, axInduction, tanInduction, m%Rtip) ! DBEMT inputs at InputIndex time (1=n; 2=n+1) + end if + + if (ApplyCorrections) then ! avoid updating inductions when called before updating DBEMT states + call calculate_Inductions_from_DBEMT_AllNodes(InputIndex, t, u, p, x, OtherState, m, axInduction, tanInduction) + end if + end if ! DBEMT + + if (ApplyCorrections) then ! avoid updating inductions when called before updating DBEMT states + !............................................ + ! Apply skewed wake correction to the axial induction (axInduction) + !............................................ + call ApplySkewedWakeCorrection_AllNodes(p, u, m, axInduction, chi) + + !............................................ + ! If TSR is too low, (start to) turn off induction + !............................................ + call check_turnOffBEMT(p, u, m%BEM_weight, axInduction, tanInduction, m%FirstWarn_BEMoff) + end if + + end if ! UseFrozenWake + + else ! no induction: + axInduction = 0.0_ReKi ! all nodes + tanInduction = 0.0_ReKi ! all nodes + end if ! UseInduction + + return +end subroutine BEMT_CalcOutput_Inductions +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine calculate_Inductions_from_DBEMT_AllNodes(InputIndex, t, u, p, x, OtherState, m, axInduction, tanInduction) + INTEGER(IntKi), intent(in ) :: InputIndex ! index into m%u_DEBMT (1 or 2) + REAL(DbKi), intent(in ) :: t ! current simulation time + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at t + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + REAL(ReKi), intent(inout) :: axInduction(:,:) + REAL(ReKi), intent(inout) :: tanInduction(:,:) + + + ! Local variables: + + integer(IntKi) :: i ! Generic index + integer(IntKi) :: j ! Loops through nodes / elements + + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + if ( .not. p%FixedInductions(i,j) ) then + call calculate_Inductions_from_DBEMT(i, j, u%Vx(i,j), u%Vy(i,j), t, p%DBEMT, m%u_DBEMT(InputIndex), x%DBEMT, OtherState%DBEMT, m%DBEMT, axInduction(i,j), tanInduction(i,j)) + end if ! .not. p%FixedInductions (special case for tip and/or hub loss) + enddo ! I - Blade nodes / elements + enddo ! J - All blades + + +end subroutine calculate_Inductions_from_DBEMT_AllNodes +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine ApplySkewedWakeCorrection_AllNodes(p, u, m, axInduction, chi) + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + REAL(ReKi), intent(inout) :: axInduction(:,:) + REAL(ReKi), intent(inout) :: chi(:,:) ! value used in skewed wake correction + + integer(IntKi) :: i ! Generic index + integer(IntKi) :: j ! Loops through nodes / elements + + !............................................ + ! Apply skewed wake correction to the axial induction (y%axInduction) + !............................................ + if ( p%skewWakeMod == SkewMod_PittPeters ) then + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + if ( .not. p%FixedInductions(i,j) ) then + call ApplySkewedWakeCorrection( p%yawCorrFactor, u%psi(j), u%chi0, u%rlocal(i,j)/m%Rtip(j), axInduction(i,j), chi(i,j), m%FirstWarn_Skew ) + end if ! .not. p%FixedInductions (special case for tip and/or hub loss) + enddo ! I - Blade nodes / elements + enddo ! J - All blades + end if + +end subroutine ApplySkewedWakeCorrection_AllNodes + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, AFInfo, ErrStat, ErrMsg ) +! Tight coupling routine for computing derivatives of continuous states +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(BEMT_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(BEMT_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(BEMT_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(BEMT_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at t + TYPE(BEMT_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(BEMT_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + TYPE(BEMT_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(BEMT_ContinuousStateType), INTENT(INOUT) :: dxdt ! Continuous state derivatives at t + TYPE(AFI_ParameterType), INTENT(IN ) :: AFInfo(:) ! The airfoil parameter data + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_CalcContStateDeriv' + + INTEGER(IntKi), parameter :: InputIndex = 1 + INTEGER(IntKi) :: i, j + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + m%phi = z%phi ! set this before possibly calling InitPhi() because phi is intent(inout) in the solve + + !............................................................................................................................... + ! THIS IS CALLED ONLY DURING LINEARIZATION, where we want to treat z%phi as an implied input, thus we need to recalculate phi + ! consistent with the inputs: + !............................................................................................................................... + call UpdatePhi( u, p, m%phi, AFInfo, m, m%ValidPhi, errStat2, errMsg2 ) + + !............................................................................................................................... + ! compute inputs to DBEMT (also setting inductions needed for UA inputs--including DBEMT and skewed wake corrections) + !............................................................................................................................... + call BEMT_CalcOutput_Inductions( InputIndex, t, .true., .true., m%phi, u, p, x, xd, z, OtherState, AFInfo, m%axInduction, m%tanInduction, m%chi, m, errStat2, errMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + !............................................................................................................................... + ! compute derivatives for DBEMT continuous states: + !............................................................................................................................... + if (p%DBEMT_Mod /= DBEMT_none) then + if (.not. allocated(dxdt%DBEMT%element)) then + call DBEMT_CopyContState( x%DBEMT, dxdt%DBEMT, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + call DBEMT_CalcContStateDeriv( i, j, t, m%u_DBEMT(InputIndex)%element(i,j), p%DBEMT, x%DBEMT%element(i,j), OtherState%DBEMT, m%DBEMT, dxdt%DBEMT%element(i,j), ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + enddo ! I - Blade nodes / elements + enddo ! J - All blades + end if + + + + !............................................................................................................................... + ! compute inputs to UA + !............................................................................................................................... + if (p%UA_Flag) then + call SetInputs_for_UA_AllNodes(u, p, m%phi, m%axInduction, m%tanInduction, m%u_UA(:,:,InputIndex)) + + !............................................................................................................................... + ! compute derivatives for UA continuous states: + !............................................................................................................................... + if (.not. allocated(dxdt%UA%element)) then + call UA_CopyContState( x%UA, dxdt%UA, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + ! We only update the UnsteadyAero states if we have unsteady aero turned on for this node + if (OtherState%UA_Flag(i,j)) then + call UA_CalcContStateDeriv( i, j, t, m%u_UA(i,j,InputIndex), p%UA, x%UA%element(i,j), OtherState%UA, AFInfo(p%AFIndx(i,j)), m%UA, dxdt%UA%element(i,j), ErrStat2, ErrMsg2 ) + else + dxdt%UA%element(i,j)%x = 0.0_R8Ki + end if + end do + end do + + end if + +END SUBROUTINE BEMT_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +! Tight coupling routine for updating discrete states +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n ! Current step of the simulation: t = n*Interval + TYPE(BEMT_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(BEMT_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(BEMT_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(BEMT_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + TYPE(BEMT_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(BEMT_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + type(BEMT_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + + ! StateData%DiscState = + +END SUBROUTINE BEMT_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine BEMT_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, AFInfo, ErrStat, ErrMsg ) +! Tight coupling routine for solving for the residual of the constraint state equations +!.................................................................................................................................. + + real(DbKi), intent(in ) :: Time ! Current simulation time in seconds + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at Time + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at Time + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at Time (possibly a guess) + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at Time + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(BEMT_ConstraintStateType), intent(inout) :: z_residual ! Residual of the constraint state equations using + ! the input values described above + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + !# set epsilon + !REAL(ReKi), PARAMETER ::epsilon = 1e-6 + + ! Local variables + INTEGER :: i,j + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_CalcConstrStateResidual' + logical :: IsValidSolution ! placeholder for flag to determine if the residual solution is invalid + + + ErrStat = ErrID_None + ErrMsg = "" + + + if (p%useInduction) then + + if ( m%UseFrozenWake ) then ! we are linearizing with frozen wake assumption; i.e., p%FrozenWake is true and this was called from the linearization routine + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + Z_residual%phi(i,j) = sin(z%phi(i,j)) * (u%Vy(i,j) + m%TnInd_op(i,j)) - cos(z%phi(i,j)) * (u%Vx(i,j) + m%AxInd_op(i,j)) + end do + end do + + else + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + + ! Solve for the constraint states here: + Z_residual%phi(i,j) = BEMTU_InductionWithResidual(p, u, i, j, z%phi(i,j), AFInfo(p%AFindx(i,j)), IsValidSolution, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + end do + end do + + end if ! not frozen wake + + else + + do j = 1,p%numBlades + do i = 1,p%numBladeNodes + Z_residual%Phi(i,j) = sin(z%phi(i,j)) * u%Vy(i,j) - cos(z%phi(i,j)) * u%Vx(i,j) + end do + end do + + + end if + + +END SUBROUTINE BEMT_CalcConstrStateResidual + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the BEMT inductions that are frozen when linearizing with the FrozenWake flag. +!> It first calls BEMT_CalcOutput to compute y%tanInduction and y%axInduction at this operating point. +!SUBROUTINE computeFrozenWake( t, u, p, x, xd, z, OtherState, AFInfo, y, m, errStat, errMsg ) +SUBROUTINE computeFrozenWake( u, p, y, m ) +!.................................................................................................................................. + + + !real(DbKi), intent(in ) :: t ! Current simulation time in seconds + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + !type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at t + !type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at t + !type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at t + !type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(inout) :: m ! Misc/optimization variables + !type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + type(BEMT_OutputType), intent(inout) :: y ! Outputs computed at t + !integer(IntKi), intent( out) :: errStat ! Error status of the operation + !character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + ! local variables + INTEGER(IntKi) :: j,k ! loop counters + character(*), parameter :: RoutineName = 'computeFrozenWake' + + ! get a and aprime + !call BEMT_CalcOutput(t, u, p, x, xd, z, OtherState, AFInfo, y, m, errStat, errMsg) + + do k = 1,p%numBlades + do j = 1,p%numBladeNodes + + m%AxInd_op(j,k) = - u%Vx(j,k) * y%axInduction( j,k) + m%TnInd_op(j,k) = u%Vy(j,k) * y%tanInduction(j,k) + + end do + end do + + + +END SUBROUTINE computeFrozenWake +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine checks for BEMT inputs that are invalid when linearizing constraint state equations. +SUBROUTINE CheckLinearizationInput(p, u, z, m, OtherState, ErrStat, ErrMsg) + + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_InputType), intent(in ) :: u ! Inputs at the operating point + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at the operating point + type(BEMT_MiscVarType), intent(in ) :: m ! Misc/optimization variables + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other state at the operating point + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: j,k ! loop counters + character(*), parameter :: RoutineName = 'CheckLinearizationInput' + + + ErrStat = ErrID_None + ErrMsg = '' + + if (p%UseInduction) then + + do k = 1,p%numBlades + do j = 1,p%numBladeNodes + if (.not. OtherState%ValidPhi(j,k)) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": Current operating point does not contain a valid value of phi.",ErrStat,ErrMsg,RoutineName) + return + end if + + end do + end do + + + + if ( m%UseFrozenWake ) then ! we are linearizing with frozen wake assumption (i.e., p%FrozenWake is true and this is called from linearization routine) + + do k = 1,p%numBlades + do j = 1,p%numBladeNodes + + if ( VelocityIsZero( u%Vy(j,k)+m%TnInd_op(j,k)) .and. VelocityIsZero( u%Vx(j,k)+m%AxInd_op(j,k) ) ) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": residual is undefined because u%Vy + TnInd_op = u%Vx + AxInd_op = 0.",ErrStat,ErrMsg,RoutineName) + return + end if + + end do + end do + + else + + do k = 1,p%numBlades + do j = 1,p%numBladeNodes + + if ( EqualRealNos(z%phi(j,k), 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": residual is discontinuous or undefined because z%phi = 0.",ErrStat,ErrMsg,RoutineName) + return + else if ( VelocityIsZero(u%Vy(j,k)) ) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": residual is discontinuous or undefined because u%Vy = 0.",ErrStat,ErrMsg,RoutineName) + return + else if ( VelocityIsZero(u%Vx(j,k)) ) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": residual is discontinuous or undefined because u%Vx = 0.",ErrStat,ErrMsg,RoutineName) + return + end if + + end do + end do + + end if + + + + else ! .not. p%UseInduction: + + do k = 1,p%numBlades + do j = 1,p%numBladeNodes + + if ( EqualRealNos( u%Vy(j,k), 0.0_ReKi ) .and. EqualRealNos( u%Vx(j,k), 0.0_ReKi ) ) then + call SetErrStat(ErrID_Fatal,"Blade"//trim(num2lstr(k))//', node '//trim(num2lstr(j))//& + ": residual is undefined because u%Vy = u%Vx = 0.",ErrStat,ErrMsg,RoutineName) + return + end if + + end do + end do + + + + end if + +END SUBROUTINE CheckLinearizationInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This gets the constraint-state perturbations for linearization about a given operating point. This returns two deltas (one plus +!! and one minus) such that z_op+dz_p and z_op-dz_m are in the same solution region (or that they are in adjacent regions that have +!! continuous solution regions [i.e, the pi/2 boundary is okay because it is continuous across the momentum/empirical regions]). +SUBROUTINE Get_phi_perturbations(p, m, z_op, dz_p, dz_m) + + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_MiscVarType), intent(in ) :: m ! Misc/optimization variables + + REAL(ReKi), intent(in ) :: z_op !< value of z%phi(i,j) at the operating point + REAL(R8Ki), intent( out) :: dz_p !< change in z_op in the plus direction + REAL(R8Ki), intent( out) :: dz_m !< change in z_op in the minus direction + + ! local variables + real(R8Ki) :: dz ! size of perturbation + real(R8Ki) :: zp ! z_op+dz + real(R8Ki) :: zm ! z_op-dz + + + dz = 2.0_R8Ki*D2R_D + + ! we'll assume a central difference unless we are on the boundaries below [default] + dz_p = dz + dz_m = dz + + + if (p%UseInduction .and. .not. m%UseFrozenWake) then + + zp = z_op+dz + zm = z_op-dz + + ! check if it goes past the pi-eps upper boundary + if ( zp > pi_D - BEMT_epsilon2 ) then + ! 1-sided difference + dz_p = 0.0_R8Ki + dz_m = dz + + ! next we care about the -pi/4-eps boundary: + else if ( zm < -pi_D/4.0_R8Ki - BEMT_epsilon2) then + ! 1-sided difference + dz_p = dz + dz_m = 0.0_R8Ki + + ! next let's check the +eps boundaries: + else if ( z_op > 0.0_R8Ki .and. zm < BEMT_epsilon2 ) then + ! 1-sided difference + dz_p = dz + dz_m = 0.0_R8Ki + + ! next let's check the -eps boundaries: + else if ( z_op < 0.0_ReKi .and. zp > -BEMT_epsilon2 ) then + ! 1-sided difference + dz_p = 0.0_R8Ki + dz_m = dz + + ! else ! we don't care about the pi/2 boundary, so let's do a central difference for everything else + end if + + end if + + +END SUBROUTINE Get_phi_perturbations +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine GetSolveRegionOrdering(Vx, phiIn, test_lower, test_upper) + real(ReKi), intent(in ) :: Vx + real(ReKi), intent(in ) :: phiIn + real(ReKi), intent( out) :: test_lower(3) + real(ReKi), intent( out) :: test_upper(3) + + + if (Vx > 0) then + + test_lower(1) = BEMT_epsilon2 + test_upper(1) = PiBy2 - BEMT_epsilon2 + + if (phiIn < pi/4.0_ReKi .and. phiIn > -pi/4.0_ReKi) then !bjj: added the negative for those cases where the previously calculated non-BEMT phi is in the [-pi,-pi/4] range + test_lower(2) = -pi/4.0_ReKi + test_upper(2) = -BEMT_epsilon2 + + test_lower(3) = PiBy2 + BEMT_epsilon2 + test_upper(3) = pi - BEMT_epsilon2 + else + test_lower(3) = -pi/4.0_ReKi + test_upper(3) = -BEMT_epsilon2 + + test_lower(2) = PiBy2 + BEMT_epsilon2 + test_upper(2) = pi - BEMT_epsilon2 + end if + + else + + test_lower(1) = -BEMT_epsilon2 + test_upper(1) = -PiBy2 + BEMT_epsilon2 + + if (phiIn > -pi/4.0_ReKi .and. phiIn < pi/4.0_ReKi) then !bjj: added the negative for those cases where the previously calculated non-BEMT phi is in the [-pi,-pi/4] range + test_lower(2) = pi/4.0_ReKi + test_upper(2) = BEMT_epsilon2 + + test_lower(3) = -PiBy2 - BEMT_epsilon2 + test_upper(3) = -pi + BEMT_epsilon2 + else + test_lower(3) = pi/4.0_ReKi + test_upper(3) = BEMT_epsilon2 + + test_lower(2) = -PiBy2 - BEMT_epsilon2 + test_upper(2) = -pi + BEMT_epsilon2 + end if + + end if + + +end subroutine GetSolveRegionOrdering + +integer function FindTestRegion(p, u, iBladeNode, jBlade, phiLower, phiUpper, AFInfo, & + phiIn_IsValidSolution, phiIn, f_phiIn, f1, f2, errStat, errMsg) result(TestRegion) + + type(BEMT_ParameterType),intent(in ) :: p + type(BEMT_InputType), intent(in ) :: u + integer(IntKi), intent(in ) :: iBladeNode !< index for blade node + integer(IntKi), intent(in ) :: jBlade !< index for blade + real(ReKi), intent(inout) :: phiLower !intent "out" in case the previous solution can alter the test region bounds + real(ReKi), intent(inout) :: phiUpper !intent "out" in case the previous solution can alter the test region bounds + !integer, intent(in ) :: numBladeNodes + type(AFI_ParameterType),intent(in ) :: AFInfo + logical, intent(in ) :: phiIn_IsValidSolution + real(ReKi), intent(in ) :: phiIn + real(ReKi), intent(in ) :: f_phiIn + real(ReKi), intent( out) :: f1 !< value of residual at phiLower + real(ReKi), intent( out) :: f2 !< value of residual at phiUpper + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + character(errMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName='TestRegion' + logical :: IsValidSolution, IsValidSolution2 ! placeholder for flag to determine if the residual solution is invalid (we'll handle that after the brent solve) + + + ErrStat = ErrID_None + ErrMsg = "" + + + f1 = BEMTU_InductionWithResidual(p, u, iBladeNode, jBlade, phiLower, AFInfo, IsValidSolution, errStat2, errMsg2) + + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + f2 = BEMTU_InductionWithResidual(p, u, iBladeNode, jBlade, phiUpper, AFInfo, IsValidSolution2, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + + ! Look for zero-crossing + if ( EqualRealNos(f1, 0.0_ReKi) .and. EqualRealNos(f2, 0.0_ReKi) .and. IsValidSolution .and. IsValidSolution2) then + TestRegion = 0 ! all solutions yield zero -- special case + return + else + if ( abs(f1) < p%aTol ) then + if ( abs(f2) < abs(f1) .and. IsValidSolution2 ) then + TestRegion = 4 ! special case: upper end point is a zero (and it's smaller than the solution at the lower end point) + return + elseif ( IsValidSolution ) then + TestRegion = 3 ! special case: lower end point is a zero + return + end if + elseif ( abs(f2) < p%aTol .and. IsValidSolution2 ) then + TestRegion = 4 ! special case: upper end point is a zero + return + end if + + end if + + if ( sign(1.0_ReKi,f1) /= sign(1.0_ReKi,f2) ) then + TestRegion = 1 + + if (phiIn_IsValidSolution) then + if ( (phiLower < phiIn .and. phiIn < phiUpper ) .or. (phiUpper < phiIn .and. phiIn < phiLower ) ) then + + ! the previous solution was in this region + if ( sign(1.0_ReKi,f1) /= sign(1.0_ReKi,f_phiIn) ) then + phiUpper = phiIn + f2 = f_phiIn + else + phiLower = phiIn + f1 = f_phiIn + end if + + end if + end if + + + else + TestRegion = 2 ! No zero + end if + +end function FindTestRegion + +subroutine BEMT_UnCoupledSolve(p, u, iBladeNode, jBlade, phi, AFInfo, ValidPhi, FirstWarn, ErrStat, ErrMsg) + + use mod_root1dim + !use fminMod + type(BEMT_ParameterType),intent(in ) :: p + type(BEMT_InputType), intent(in ) :: u + integer(IntKi), intent(in ) :: iBladeNode !< index for blade node + integer(IntKi), intent(in ) :: jBlade !< index for blade + real(ReKi), intent(inout) :: phi + TYPE(AFI_ParameterType),INTENT(IN ) :: AFInfo + logical, intent(inout) :: ValidPhi + logical, intent(inout) :: FirstWarn + integer(IntKi), intent( out) :: errStat ! Error status of the operation + character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None + + + + ! Local variables + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'BEMT_UnCoupledSolve' + real(ReKi), parameter :: MsgLimit = 0.07_ReKi !BEMT_epsilon2*100.0_ReKi don't print a message if we're within about 4 degrees of 0 or +/- pi/2 [bjj arbitrary number] + + real(ReKi) :: f1, f_lower, f_upper, phiIn + real(ReKi) :: phi_lower(3), phi_upper(3) ! upper and lower bounds for region of phi in which we are trying to find a solution to the BEM equations + integer :: i, TestRegionResult + logical :: IsValidSolution + + ErrStat = ErrID_None + ErrMsg = "" + + + if ( VelocityIsZero(u%Vx(iBladeNode,jBlade)) ) then + phi = 0.0_ReKi + ValidPhi = .true. + return + else if ( VelocityIsZero(u%Vy(iBladeNode,jBlade)) ) then + if (u%Vx(iBladeNode,jBlade) > 0.0_ReKi) then + phi = PiBy2 + else + phi = -PiBy2 + end if + ValidPhi = .true. + return + end if + + + + !# ------ BEM solution method see (Ning, doi:10.1002/we.1636) ------ + + ! See if the previous value of phi still satisfies the residual equation. + ! (If the previous phi wasn't a valid solution to BEMT equations, skip this check and just perform the solve) + if (ValidPhi .and. .NOT. EqualRealNos(phi, 0.0_ReKi) .and. .not. EqualRealNos(abs(phi),PiBy2) ) then + f1 = BEMTU_InductionWithResidual(p, u, iBladeNode, jBlade, phi, AFInfo, IsValidSolution, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + if ( abs(f1) < p%aTol .and. IsValidSolution ) then + !phiStar = phiIn + return + end if + else + IsValidSolution = .false. + end if + + + + ! + ValidPhi = .false. ! initialize to false while we try to find a new valid solution + + call GetSolveRegionOrdering(u%Vx(iBladeNode,jBlade), phi, phi_lower, phi_upper) + phiIn = phi + + do i = 1,size(phi_upper) ! Need to potentially test 4 regions + TestRegionResult = FindTestRegion(p, u, iBladeNode, jBlade, phi_lower(i), phi_upper(i), AFInfo, & + IsValidSolution, phiIn, f1, f_lower, f_upper, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + if ( TestRegionResult == 1 ) then + !............ + ! There is a zero in the solution region [phi_lower(i), phi_upper(i)] because the endpoints have residuals with different signs (SolutionRegion=1) + ! We use Brent's Method to find the zero-residual solution in this region + + call sub_brent(p, u, iBladeNode, jBlade, phi, phi_lower(i), phi_upper(i), AFInfo, IsValidSolution, ErrStat2, ErrMsg2, f_lower, f_upper) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (IsValidSolution) then ! we have a valid BEMT solution + ValidPhi = .true. + exit + end if + elseif (TestRegionResult == 3) then + phi = phi_lower(i) !this boundary is a solution + ValidPhi = .true. + exit + elseif (TestRegionResult == 4) then + phi = phi_upper(i) !this boundary is a solution + ValidPhi = .true. + exit + elseif (TestRegionResult == 0) then ! Special case where both end points return 0 residual; return value closest to 0 as the solution + if (phi_lower(i) > 0.0_ReKi) then + phi = phi_lower(i) !this boundary is a solution + ValidPhi = .true. + exit + else + phi = phi_upper(i) !this boundary is a solution + ValidPhi = .true. + exit + end if + end if + + end do + + + if (.not. ValidPhi) then + phi = ComputePhiWithInduction(u%Vx(iBladeNode,jBlade), u%Vy(iBladeNode,jBlade), 0.0_ReKi, 0.0_ReKi) + + if (abs(phi)>MsgLimit .and. abs(abs(phi)-PiBy2) > MsgLimit ) then + if (FirstWarn) then + call SetErrStat( ErrID_Info, 'There is no valid value of phi for these operating conditions: Vx = '//TRIM(Num2Lstr(u%Vx(iBladeNode,jBlade)))//& + ', Vy = '//TRIM(Num2Lstr(u%Vy(iBladeNode,jBlade)))//', rlocal = '//TRIM(Num2Lstr(u%rLocal(iBladeNode,jBlade)))//', theta = '//TRIM(Num2Lstr(u%theta(iBladeNode,jBlade)))//', geometric phi = '//TRIM(Num2Lstr(phi)) & + //'. This warning will not be repeated though the condition may persist. (See GeomPhi output channel.)', errStat, errMsg, RoutineName ) + FirstWarn = .false. + end if !FirstWarn + end if + end if + + +end subroutine BEMT_UnCoupledSolve +!---------------------------------------------------------------------------------------------------------------------------------- +function NodeText(i,j) + integer(IntKi), intent(in) :: i ! node number + integer(IntKi), intent(in) :: j ! blade number + character(25) :: NodeText + + NodeText = '(node '//trim(num2lstr(i))//', blade '//trim(num2lstr(j))//')' +end function NodeText +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine SetInputs_for_UA(phi, theta, axInduction, tanInduction, Vx, Vy, omega, chord, kinVisc, UserProp, u_UA) + real(ReKi), intent(in ) :: UserProp ! User property (for 2D Airfoil interp) + real(ReKi), intent(in ) :: phi + real(ReKi), intent(in ) :: theta + real(ReKi), intent(in ) :: axInduction + real(ReKi), intent(in ) :: tanInduction + real(ReKi), intent(in ) :: Vx + real(ReKi), intent(in ) :: Vy + real(ReKi), intent(in ) :: omega ! aka PitchRate + real(ReKi), intent(in ) :: chord + real(ReKi), intent(in ) :: kinVisc + type(UA_InputType), intent( out) :: u_UA + + + ! ....... compute inputs to UA ........... + u_UA%alpha = phi - theta ! angle of attack + u_UA%UserProp = UserProp + + ! Need to compute relative velocity at the aerodynamic center, including both axial and tangential induction + ! COMPUTE: u_UA%U, u_UA%Re, u_UA%v_ac + call GetRelativeVelocity( axInduction, tanInduction, Vx, Vy, u_UA%U, u_UA%v_ac ) + call GetReynoldsNumber( axInduction, tanInduction, Vx, Vy, chord, kinVisc, u_UA%Re) + + u_UA%v_ac(1) = sin(u_UA%alpha)*u_UA%U + u_UA%v_ac(2) = cos(u_UA%alpha)*u_UA%U + + u_UA%omega = omega + +end subroutine SetInputs_for_UA +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine SetInputs_for_UA_AllNodes(u, p, phi, axInduction, tanInduction, u_UA) + type(BEMT_InputType), intent(in ) :: u + type(BEMT_ParameterType), intent(in ) :: p + real(ReKi), intent(inout) :: phi(:,:) + real(ReKi), intent(in ) :: axInduction(:,:) + real(ReKi), intent(in ) :: tanInduction(:,:) + type(UA_InputType), intent( out) :: u_UA(:,:) + + INTEGER(IntKi) :: i, j + + if ( p%useInduction ) then + !............................................ + ! we're recomputing phi because it may not be consistent with the computed axInduction or tanInduction values + !............................................ + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + phi(i,j) = ComputePhiWithInduction( u%Vx(i,j), u%Vy(i,j), axInduction(i,j), tanInduction(i,j) ) + enddo ! I - Blade nodes / elements + enddo ! J - All blades + end if + + !............................................ + ! unsteady aero inputs (AoA, Vrel, Re) + !............................................ + do j = 1,p%numBlades ! Loop through all blades + do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements + + ! Compute AoA, Re, Vrel (inputs to UA) based on current values of axInduction, tanInduction: + call SetInputs_for_UA(phi(i,j), u%theta(i,j), axInduction(i,j), tanInduction(i,j), u%Vx(i,j), u%Vy(i,j), u%omega_z(i,j), p%chord(i,j), p%kinVisc, u%UserProp(i,j), u_UA(i,j)) + + end do + end do + +end subroutine SetInputs_for_UA_AllNodes +!---------------------------------------------------------------------------------------------------------------------------------- +#ifdef DEBUG_BEMT_RESIDUAL +subroutine WriteDEBUGValuesToFile(t, u, p, x, xd, z, OtherState, m, AFInfo) + real(DbKi), intent(in ) :: t ! Current simulation time in seconds + type(BEMT_InputType), intent(in ) :: u ! Inputs at Time t + type(BEMT_ParameterType), intent(in ) :: p ! Parameters + type(BEMT_ContinuousStateType), intent(in ) :: x ! Continuous states at t + type(BEMT_DiscreteStateType), intent(in ) :: xd ! Discrete states at t + type(BEMT_ConstraintStateType), intent(in ) :: z ! Constraint states at t + type(BEMT_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(BEMT_MiscVarType), intent(in ) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data + + character(ErrMsgLen) :: errMsg ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat ! temporary Error status of the operation + integer(IntKi) :: OutInt + integer(IntKi) :: UnOut + logical :: ValidPhi + integer(IntKi) :: ii + integer(IntKi), parameter :: numPhi = 3001 + real(ReKi) :: phi + real(ReKi) :: fzero + real(ReKi) :: delta_phi + real(ReKi) :: axInd, tnInd + + ! I'm using persistent data.... don't copy this code anywhere else :) + integer, save :: DEBUG_BLADE + integer, save :: DEBUG_BLADENODE + integer, save :: DEBUG_nStep = 1 + integer, save :: DEBUG_FILE_UNIT + +! character(*), parameter :: RoutineName = 'BEMT_UnCoupledSolve' + + DEBUG_BLADE = 1 !size(u%Vx,2) + DEBUG_BLADENODE = 23 !max(1, size(u%Vx,1) / 2 ) + + if (DEBUG_nStep == 1) then + call GetNewUnit(DEBUG_FILE_UNIT, ErrStat, ErrMsg ) + call OpenFOutFile ( DEBUG_FILE_UNIT, "CheckBEMT.inputs.out", ErrStat, ErrMsg ) + + WRITE(DEBUG_FILE_UNIT,'(A7,200(1x,A15))') "Step","IsGeomPhi","Time", "GeomPhi", "phi" & + , "chi0", "omega", "Un_disk", "TSR" & + , "theta" , "psi" & + , "Vx" , "Vy" & + , "omega_z" & + , "rLocal" , "UserProp" & + , "AxInd", "TanInd" +! , "Vx_elast_dot" , "Vy_elast_dot" & + + end if + + ! get geometric phi for these inputs: + phi = ComputePhiWithInduction(u%Vx(DEBUG_BLADENODE,DEBUG_BLADE), u%Vy(DEBUG_BLADENODE,DEBUG_BLADE), 0.0_ReKi, 0.0_ReKi) + + if (OtherState%ValidPhi(DEBUG_BLADENODE,DEBUG_BLADE)) then + OutInt = 0 + else + OutInt = 1 + end if + + WRITE(DEBUG_FILE_UNIT, '(I7,1x,I15,200(1x,ES15.6))') DEBUG_nStep, OutInt, t, phi*R2D & + , z%phi( DEBUG_BLADENODE,DEBUG_BLADE)*R2D & ! remember this does not have any corrections + , u%chi0, u%omega, u%Un_disk, u%TSR & + , u%theta( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%psi( DEBUG_BLADE) & + , u%Vx( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%Vy( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%Vz( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%omega_z( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%rLocal( DEBUG_BLADENODE,DEBUG_BLADE) & + , u%UserProp( DEBUG_BLADENODE,DEBUG_BLADE) & + , m%axInduction( DEBUG_BLADENODE,DEBUG_BLADE) & + , m%tanInduction(DEBUG_BLADENODE,DEBUG_BLADE) +! these are not always allocated +! , u%Vx_elast_dot(DEBUG_BLADENODE,DEBUG_BLADE) & +! , u%Vy_elast_dot(DEBUG_BLADENODE,DEBUG_BLADE) & + + ! now write the residual function to a separate file: + if ((DEBUG_nStep >= 0).AND.(DEBUG_nStep <= 450000).AND.(MOD(DEBUG_nStep,25) == 0)) then + + call GetNewUnit( UnOut, ErrStat, ErrMsg ) + call OpenFOutFile ( UnOut, "CheckBEMT.residual."//trim(num2lstr(DEBUG_nStep))//".out", ErrStat, ErrMsg ) + !WRITE(UnOut, '(2(A15,1x),A2,5(1x,A15))') 'phi', 'residual', 'OK', 'AxialInd', 'TangentialInd', 'k', 'kp' + + do ii = 1, numPhi + + ! nonlinear mapping of ii --> phi + phi = smoothStep( real(ii,ReKi), 1.0, -pi+BEMT_epsilon2, real(numPhi,ReKi)/2.0, 0.0_ReKi ) + smoothStep( real(ii,ReKi), real(numPhi,ReKi)/2.0, 0.0_ReKi, real(numPhi,ReKi), pi-BEMT_epsilon2 ) + + fzero = BEMTU_InductionWithResidual(p, u, DEBUG_BLADENODE, DEBUG_BLADE, phi, AFInfo(p%AFIndx(DEBUG_BLADENODE,DEBUG_BLADE)), ValidPhi, errStat, errMsg, a=axInd, ap=tnInd ) + if (ValidPhi) then + OutInt = 0 + else + OutInt = 1 + end if + + WRITE(UnOut, '(2(ES15.6,1x),I2,8(1x,ES15.6))') phi, fzero, OutInt, axInd, tnInd + + end do + + CLOSE(UnOut) + end if + + DEBUG_nStep = DEBUG_nStep + 1 + +end subroutine WriteDEBUGValuesToFile +#endif +!---------------------------------------------------------------------------------------------------------------------------------- +end module BEMT + diff --git a/OpenFAST/modules/aerodyn/src/BEMTUncoupled.f90 b/OpenFAST/modules/aerodyn/src/BEMTUncoupled.f90 new file mode 100644 index 000000000..ea760fd74 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/BEMTUncoupled.f90 @@ -0,0 +1,486 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 BEMTUnCoupled + + use NWTC_Library + use AirfoilInfo + use AirfoilInfo_Types + use UnsteadyAero + use UnsteadyAero_Types + use BEMT_Types + + + implicit none + + integer(IntKi), public, parameter :: SkewMod_Uncoupled = 1 ! Uncoupled (no correction) [-] + integer(IntKi), public, parameter :: SkewMod_PittPeters = 2 ! Pitt/Peters [-] + integer(IntKi), public, parameter :: SkewMod_Coupled = 3 ! Coupled [-] + + real(ReKi), public, parameter :: BEMT_MaxInduction(2) = (/1.5_ReKi, 1.0_ReKi /) ! largest magnitude of axial (1) and tangential (2) induction factors + real(ReKi), public, parameter :: BEMT_MinInduction(2) = -1.0_ReKi + + real(ReKi), public, parameter :: BEMT_lowerBoundTSR = 1.0_ReKi + real(ReKi), public, parameter :: BEMT_upperBoundTSR = 2.0_ReKi + + !1e-6 works for double precision, but not single precision + real(ReKi), public, parameter :: BEMT_epsilon2 = 10.0_ReKi*sqrt(epsilon(1.0_ReKi)) !this is the tolerance in radians for values around singularities in phi (i.e., phi=0 and phi=pi/2); must be large enough so that EqualRealNos(BEMT_epsilon2, 0.0_ReKi) is false + + + private + + public :: GetRelativeVelocity + public :: GetReynoldsNumber + public :: BEMTU_InductionWithResidual + public :: ApplySkewedWakeCorrection + public :: Transform_ClCd_to_CxCy + public :: getHubTipLossCorrection + public :: limitInductionFactors + + public :: VelocityIsZero +contains + +!.................................................................................................................................. + function VelocityIsZero ( v ) + + ! passed variables + + REAL(ReKi), INTENT(IN ) :: v !< the velocity that needs to be compared with zero + + LOGICAL :: VelocityIsZero !< .true. if and only if the velocity is (almost) equal to zero + + + + VelocityIsZero = abs(v) < 0.001_ReKi ! tolerance in m/s for what we consider zero velocity for BEM computations + + end function VelocityIsZero +!.................................................................................................................................. + + subroutine GetReynoldsNumber( axInduction, tanInduction, Vx, Vy, chord, nu, Re ) + + ! in + real(ReKi), intent(in) :: axInduction, tanInduction, Vx, Vy + real(ReKi), intent(in) :: chord, nu + + ! out + real(ReKi), intent(out) :: Re ! Reynolds number + + real(ReKi) :: W ! relative velocity + + W = sqrt((Vx*(1-axInduction))**2 + (Vy*(1+tanInduction))**2) + + Re = W * chord / nu + if ( EqualRealNos(Re, 0.0_ReKi) ) Re = 0.001 ! Do this to avoid a singularity when we take log(Re) in the airfoil lookup. + + end subroutine GetReynoldsNumber +!.................................................................................................................................. + subroutine GetRelativeVelocity( axInduction, tanInduction, Vx, Vy, Vrel, v_ac ) + + ! in + real(ReKi), intent(in) :: axInduction, tanInduction, Vx, Vy + + ! out + real(ReKi), intent(out) :: Vrel ! relative velocity + real(ReKi), intent(out) :: v_ac(2) ! components of relative velocity + + v_ac(1) = Vx*(1-axInduction) + v_ac(2) = Vy*(1+tanInduction) + + Vrel = TwoNorm(v_ac) + + end subroutine GetRelativeVelocity +!.................................................................................................................................. +subroutine Transform_ClCd_to_CxCy( phi, useAIDrag, useTIDrag, Cl, Cd, Cx, Cy ) + real(ReKi), intent(in ) :: phi + logical, intent(in ) :: useAIDrag + logical, intent(in ) :: useTIDrag + real(ReKi), intent(in ) :: Cl + real(ReKi), intent(in ) :: Cd + real(ReKi), intent( out) :: Cx + real(ReKi), intent( out) :: Cy + + real(ReKi) cphi, sphi + + cphi = cos(phi) + sphi = sin(phi) + + ! resolve into normal (x) and tangential (y) forces + if ( useAIDrag ) then + Cx = Cl*cphi + Cd*sphi + else + Cx = Cl*cphi + end if + + if ( useTIDrag ) then + Cy = Cl*sphi - Cd*cphi + else + Cy = Cl*sphi + end if + +end subroutine Transform_ClCd_to_CxCy +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!>This is the residual calculation for the uncoupled BEM solve +real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValidSolution, ErrStat, ErrMsg, a, ap ) result (ResidualVal) + + + type(BEMT_ParameterType),intent(in ) :: p !< parameters + type(BEMT_InputType), intent(in ) :: u !< Inputs at t + integer(IntKi), intent(in ) :: i !< index for blade node + integer(IntKi), intent(in ) :: j !< index for blade + + real(ReKi), intent(in ) :: phi + type(AFI_ParameterType),intent(in ) :: AFInfo + logical, intent( out) :: IsValidSolution !< this is set to false if k<=1 in the propeller brake region or k<-1 in the momentum region, indicating an invalid solution + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(ReKi), optional, intent( out) :: a ! computed axial induction + real(ReKi), optional, intent( out) :: ap ! computed tangential induction + + ! Local variables + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'BEMTU_InductionWithResidual' + + real(ReKi) :: AOA ! angle of attack + real(ReKi) :: axInduction + real(ReKi) :: tanInduction + + real(ReKi) :: Re + real(ReKi) :: Cx, Cy + TYPE(AFI_OutputType) :: AFI_interp + + + ErrStat = ErrID_None + ErrMsg = "" + ResidualVal = 0.0_ReKi + IsValidSolution = .true. + + ! make these return values consistent with what is returned in inductionFactors routine: + + ! Set the local version of the induction factors + if ( p%FixedInductions(i,j) ) then + ! We are simply going to bail if we are using tiploss and tipLossConst = 0 or using hubloss and hubLossConst=0, regardless of phi! [do this before checking if Vx or Vy is zero or you'll get jumps in the induction and loads] + axInduction = 1.0_ReKi + tanInduction = 0.0_ReKi + elseif ( EqualRealNos(phi, 0.0_ReKi) .or. VelocityIsZero(u%Vx(i,j)) .OR. VelocityIsZero(u%Vy(i,j)) ) then + axInduction = 0.0_ReKi + tanInduction = 0.0_ReKi + else !if ( (.NOT. VelocityIsZero(Vx)) .AND. (.NOT. VelocityIsZero(Vy)) ) then + + AOA = phi - u%theta(i,j) + + ! FIX ME: Note that the Re used here is computed assuming axInduction and tanInduction are 0. Is that a problem for 2D Re interpolation on airfoils? or should update solve method to take this into account? + call GetReynoldsNumber( 0.0_ReKi, 0.0_ReKi, u%Vx(i,j), u%Vy(i,j), p%chord(i,j), p%kinVisc, Re) + + call AFI_ComputeAirfoilCoefs( AOA, Re, u%UserProp(i,j), AFInfo, AFI_interp, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + ! Compute Cx, Cy given Cl, Cd and phi, we honor the useAIDrag and useTIDrag flag because Cx,Cy are only used for the solution of inductions + call Transform_ClCd_to_CxCy( phi, p%useAIDrag, p%useTIDrag, AFI_interp%Cl, AFI_interp%Cd, Cx, Cy ) + + + ! Determine axInduction, tanInduction for the current Cl, Cd, phi + call inductionFactors( u%rlocal(i,j), p%chord(i,j), phi, Cx, Cy, p%numBlades, & + u%Vx(i,j), u%Vy(i,j), p%useTanInd, p%useHubLoss, p%useTipLoss, p%hubLossConst(i,j), p%tipLossConst(i,j), & + ResidualVal, axInduction, tanInduction, IsValidSolution) + + end if + + if (present(a )) a = axInduction + if (present(ap)) ap = tanInduction + +end function BEMTU_InductionWithResidual +!----------------------------------------------------------------------------------------- +subroutine ApplySkewedWakeCorrection( yawCorrFactor, azimuth, chi0, tipRatio, a, chi, FirstWarn ) + + real(ReKi), intent(in ) :: yawCorrFactor ! set to 15*pi/32 previously; now allowed to be input (to better match data) + real(ReKi), intent(in ) :: azimuth + real(ReKi), intent(in ) :: chi0 + real(ReKi), intent(in ) :: tipRatio ! r/Rtip + real(ReKi), intent(inout) :: a + real(ReKi), intent( out) :: chi + logical(IntKi), intent(inout) :: FirstWarn ! If this is the first warning about invalid skew + + ! Local variables + real(ReKi) :: yawCorr + real(ReKi) :: yawCorr_tan ! magnitude of the tan(chi/2) correction term (with possible limits) + + + ! Skewed wake correction + + chi = (0.6_ReKi*a + 1.0_ReKi)*chi0 + + call MPi2Pi( chi ) ! make sure chi is in [-pi, pi] before testing if it's outside a valid range + + if (abs(chi) > piBy2) then + + if (FirstWarn) then + call WrScr( 'Warning: SkewedWakeCorrection encountered a large value of chi ('//trim(num2lstr(chi*R2D))// & + ' deg), so the yaw correction will be limited. This warning will not be repeated though the condition may persist. See the AD15 chi output channels, and'// & + ' consider turning off the Pitt/Peters skew model (set SkewMod=1) if this condition persists.'//NewLine) + FirstWarn = .false. + end if + + yawCorr_tan = sign( 1.0_ReKi, chi ) ! set to +/- 1 = +/- tan( pi/4 ) + else + yawCorr_tan = tan(chi/2.0_ReKi) + end if + + !bjj: modified 22-Sep-2015: RRD recommends 32 instead of 64 in the denominator (like AD14) + yawCorr = ( yawCorrFactor * yawCorr_tan * (tipRatio) * sin(azimuth) ) ! bjj: note that when chi gets close to +/-pi this blows up + + a = a * (1.0 + yawCorr) + + +end subroutine ApplySkewedWakeCorrection +!----------------------------------------------------------------------------------------- +!> This subroutine computes the induction factors (a) and (ap) along with the residual (fzero) +subroutine inductionFactors(r, chord, phi, cn, ct, B, Vx, Vy, wakerotation, useHubLoss, useTipLoss, hubLossConst, tipLossConst, & + fzero, a, ap, IsValidSolution) + + implicit none + + ! in + real(ReKi), intent(in) :: r !< local radial position [u%rlocal] + real(ReKi), intent(in) :: chord !< chord [p%chord] + real(ReKi), intent(in) :: phi !< angle between the plane of rotation and the direction of the local wind [y%phi]; must be in range [-pi,pi] + real(ReKi), intent(in) :: cn !< normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade; [y%cx] + real(ReKi), intent(in) :: ct !< tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade; [y%cy] + integer, intent(in) :: B !< number of blades [p%numBlades] + real(ReKi), intent(in) :: Vx !< velocity component [u%Vx] + real(ReKi), intent(in) :: Vy !< velocity component [u%Vy] + real(ReKi), intent(in) :: hubLossConst !< hub loss constant [p%hubLossConst] + real(ReKi), intent(in) :: tipLossConst !< tip loss constant [p%tipLossConst] + logical, intent(in) :: useHubLoss !< hub-loss flag [p%useHubLoss] + logical, intent(in) :: useTipLoss !< tip-loss flag [p%useTipLoss] + logical, intent(in) :: wakerotation !< Include tangential induction in BEMT calculations [flag] [p%useTanInd] + + ! out + real(ReKi), intent(out) :: fzero !< residual of BEM equations + real(ReKi), intent(out) :: a !< axial induction [y%axInduction] + real(ReKi), intent(out) :: ap !< tangential induction, i.e., a-prime [y%tanInduction] + logical, intent(out) :: IsValidSolution !< this is set to false if k<=1 in the propeller brake region or k<-1 in the momentum region, indicating an invalid solution + + ! local + + real(ReKi) :: sigma_p ! local solidity (B*chord/(TwoPi*r)) + real(ReKi) :: sphi, cphi, lambda_r + real(ReKi) :: k, kp ! non-dimensional parameters + real(ReKi) :: F ! hub/tip loss correction factor + real(ReKi) :: g1, g2, g3 + real(ReKi) :: temp ! temporary variable so we don't have to calculate 2.0_ReKi*F*k multiple times + real(ReKi), parameter :: InductionLimit = 1000000.0_ReKi + + logical :: momentumRegion + + + IsValidSolution = .true. + + !..................................................... + ! Some special cases have already been taken care of in BEMTU_InductionWithResidual, the only routine that calls this function + !..................................................... + + !..................................................... + ! Temporary variables: + !..................................................... + sphi = sin(phi) + cphi = cos(phi) + + + !..................................................... + ! Prandtl's tip and hub loss factor: + !..................................................... + + F = getHubTipLossCorrection(sphi, useHubLoss, useTipLoss, hubLossConst, tipLossConst) ! Prandtl's tip and hub loss factor + + + !..................................................... + ! compute axial induction factor: + !..................................................... + sigma_p = B*chord/(TwoPi*r) ! local solidity + k = sigma_p*cn/4.0_ReKi/F/sphi/sphi + + + momentumRegion = (phi > 0.0_ReKi .and. Vx >= 0.0_ReKi) .or. (phi < 0.0_ReKi .and. Vx < 0.0_ReKi) + if (momentumRegion) then ! momentum/empirical + + + ! update axial induction factor + if (k <= 2.0_ReKi/3.0_ReKi) then ! momentum state for a < 0.4 + + if ( EqualRealNos(k,-1.0_ReKi) ) then + a = -sign(InductionLimit, 1.0_ReKi+k) + else + a = k/(1.0_ReKi+k) + end if + + if (k<-1.0_ReKi) then ! k < -1 cannot be a solution in momentum region (this is equivalent to a>1.0) + IsValidSolution = .false. + end if + + + ! note that we'll put a max on the magnitude of 'a' later + + else ! Glauert(Buhl) correction for 0.4<a<1 + + temp = 2.0_ReKi*F*k + g1 = temp - (10.0_ReKi/9.0_ReKi-F) + g2 = temp - ( 4.0_ReKi/3.0_ReKi-F)*F + g3 = temp - (25.0_ReKi/9.0_ReKi-2.0_ReKi*F) + + if (abs(g3) < 1e-6_ReKi) then ! avoid singularity + a = 1.0_ReKi - 0.5_ReKi/sqrt(g2) + else + a = (g1 - sqrt(abs(g2))) / g3 ! bjj: g2 should always be > 0, but just in case there are numerical issues, I will add the abs() here + end if + + end if + + else ! propeller brake + + + if ( EqualRealNos(k,1.0_ReKi) ) then + IsValidSolution = .false. + a = InductionLimit + else + a = k/(k-1.0_ReKi) + end if + + + if (k<=1.0_ReKi) then ! k <= 1 cannot be a solution in propeller brake region (this is equivalent to a<1.0) + IsValidSolution = .false. + end if + + end if + + !..................................................... + ! compute tangential induction factor: + !..................................................... + + if (wakerotation) then + + ! compute tangential induction factor + if ( EqualRealNos(cphi,0.0_ReKi) ) then + + ap = -1.0_ReKi + kp = sign(InductionLimit, ct*sphi)*sign(1.0_ReKi,Vx) + + else + + kp = sigma_p*ct/4.0_ReKi/F/sphi/cphi + if (Vx < 0.0_ReKi) then + kp = -kp + end if + + + if ( EqualRealNos(kp,1.0_ReKi) ) then + ap = sign(InductionLimit, 1.0_ReKi-kp) + else + ap = kp/(1.0_ReKi-kp) + end if + + endif + + else + + ! we're not computing tangential induction: + ap = 0.0_ReKi + kp = 0.0_ReKi + + end if + + + !..................................................... + ! error function (residual) + !..................................................... + lambda_r = Vy/Vx + + if (momentumRegion) then ! momentum/empirical + if ( EqualRealNos(a, 1.0_ReKi) ) then + fzero = - cphi/lambda_r*(1-kp) + else + fzero = sphi/(1-a) - cphi/lambda_r*(1-kp) + end if + + else ! propeller brake region + fzero = sphi*(1-k) - cphi/lambda_r*(1-kp) + end if + +end subroutine inductionFactors +!----------------------------------------------------------------------------------------- +subroutine limitInductionFactors(a,ap) + real(ReKi), intent(inout) :: a ! axial induction + real(ReKi), intent(inout), optional :: ap ! tangential induction + + ! Impose limits on axial induction + a = max( a, BEMT_MinInduction(1) ) + a = min( a, BEMT_MaxInduction(1) ) + + if (present(ap)) then + ! Impose limits on tangential induction + ap = max( ap, BEMT_MinInduction(2) ) + ap = min( ap, BEMT_MaxInduction(2) ) + end if + +end subroutine limitInductionFactors +!----------------------------------------------------------------------------------------- +!> This function computes \f$F\f$, the hub/tip loss correction +real(reKi) function getHubTipLossCorrection(sphi, useHubLoss, useTipLoss, hubLossConst, tipLossConst) result(F) + + real(ReKi), intent(in) :: sphi !< sine of local inflow angle, sin(phi) + real(ReKi), intent(in) :: hubLossConst !< hub loss constant [p%hubLossConst] + real(ReKi), intent(in) :: tipLossConst !< tip loss constant [p%tipLossConst] + logical, intent(in) :: useHubLoss !< hub-loss flag [p%useHubLoss] + logical, intent(in) :: useTipLoss !< tip-loss flag [p%useTipLoss] + + + real(ReKi) :: factortip, Ftip, factorhub, Fhub + + !..................................................... + ! Prandtl's tip and hub loss factor: + !..................................................... + + Ftip = 1.0_ReKi ! default tip loss value + Fhub = 1.0_ReKi ! default hub loss value + + if (.not. EqualRealNos(sphi,0.0_ReKi)) then + if ( useTipLoss ) then + factortip = tipLossConst/abs(sphi) + Ftip = TwoByPi*acos(min(1.0_ReKi,exp(-factortip))) + ! else Ftip = 1.0_ReKi ! TwoByPi*Pi/2 + end if + + if ( useHubLoss ) then + factorhub = hubLossConst/abs(sphi) + Fhub = TwoByPi*acos(min(1.0_ReKi,exp(-factorhub))) + ! else Ftip = 1.0_ReKi ! TwoByPi*Pi/2 + end if + end if + + F = Ftip * Fhub + +end function getHubTipLossCorrection +!----------------------------------------------------------------------------------------- + +end module BEMTUncoupled diff --git a/OpenFAST/modules/aerodyn/src/BEMT_Registry.txt b/OpenFAST/modules/aerodyn/src/BEMT_Registry.txt new file mode 100644 index 000000000..d0c198497 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/BEMT_Registry.txt @@ -0,0 +1,175 @@ +################################################################################################################################### +# Registry for BEMT in the FAST Modularization Framework +# This Registry file is used to create MODULE BEMT which contains all of the user-defined types needed in BEMT. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt +usefrom AirfoilInfo_Registry.txt +usefrom UnsteadyAero_Registry.txt +usefrom DBEMT_Registry.txt + +#param BEMT/BEMT - INTEGER SkewMod_Uncoupled - 1 - "Uncoupled (no correction)" - +#param BEMT/BEMT - INTEGER SkewMod_PittPeters - 2 - "Pitt/Peters" - +#param BEMT/BEMT - INTEGER SkewMod_Coupled - 3 - "Coupled" - + + +# +# +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef BEMT/BEMT InitInputType ReKi chord {:}{:} - - "Chord length at node" m +typedef ^ ^ INTEGER numBlades - - - "Number of blades" - +typedef ^ ^ ReKi airDens - - - "Air density" kg/m^3 +typedef ^ ^ ReKi kinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ ^ INTEGER skewWakeMod - - - "Type of skewed-wake correction model [switch] {1=uncoupled, 2=Pitt/Peters, 3=coupled}" - +typedef ^ ^ ReKi aTol - - - "Tolerance for the induction solution" - +typedef ^ ^ LOGICAL useTipLoss - - - "Use the Prandtl tip-loss model? [flag]" - +typedef ^ ^ LOGICAL useHubLoss - - - "Use the Prandtl hub-loss model? [flag]" - +typedef ^ ^ LOGICAL useInduction - - - "Include induction in BEMT calculations [flag] { If FALSE then useTanInd will be set to FALSE}" - +typedef ^ ^ LOGICAL useTanInd - - - "Include tangential induction in BEMT calculations [flag]" - +typedef ^ ^ LOGICAL useAIDrag - - - "Include the drag term in the axial-induction calculation? [flag]" - +typedef ^ ^ LOGICAL useTIDrag - - - "Include the drag term in the tangential-induction calculation? Ignored if TanInd is False. [flag]" - +typedef ^ ^ INTEGER numBladeNodes - - - "Number of blade nodes used in the analysis" - +typedef ^ ^ INTEGER numReIterations - - - "Number of iterations for finding the Reynolds number" - +typedef ^ ^ INTEGER maxIndIterations - - - "Maximum number of iterations of induction factor solve" - +typedef ^ ^ INTEGER AFindx {:}{:} - - "Index of airfoil data file for blade node location [array of numBladeNodes]" - +typedef ^ ^ ReKi zHub {:} - - "Distance to hub for each blade" m +typedef ^ ^ ReKi zLocal {:}{:} - - "Distance to blade node, measured along the blade" m +typedef ^ ^ ReKi zTip {:} - - "Distance to blade tip, measured along the blade" m +typedef ^ ^ ReKi rLocal {:}{:} - - "Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT" m +typedef ^ ^ INTEGER UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - +typedef ^ ^ LOGICAL UA_Flag - - - "logical flag indicating whether to use UnsteadyAero" - +typedef ^ ^ LOGICAL Flookup - - - "Use table lookup for f' and f'' " - +typedef ^ ^ ReKi a_s - - - "speed of sound" m/s +typedef ^ ^ IntKi DBEMT_Mod - - - "DBEMT model. 1 = constant tau1, 2 = time dependent tau1" - +typedef ^ ^ ReKi tau1_const - - - "DBEMT time constant (when DBEMT_Mod=1)" s +typedef ^ ^ ReKi yawCorrFactor - - - "constant used in Pitt/Peters skewed wake model (default is 15*pi/32)" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType ProgDesc Version - - - "" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType UA_ContinuousStateType UA - - - "UA module continuous states" - +typedef ^ ContinuousStateType DBEMT_ContinuousStateType DBEMT - - - "DBEMT module continuous states" - +# +# +# Define discrete (non-differentiable) states here: +# +typedef ^ DiscreteStateType UA_DiscreteStateType UA - - - "states for UnsteadyAero" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType ReKi phi {:}{:} - - "angle between the plane of rotation and the direction of the local wind" rad +# +# +# Define any other states, including integer or logical states here: +# +typedef ^ OtherStateType UA_OtherStateType UA - - - "other states for UnsteadyAero" - +typedef ^ OtherStateType DBEMT_OtherStateType DBEMT - - - "other states for DBEMT" - +typedef ^ ^ LOGICAL UA_Flag {:}{:} - - "logical flag indicating whether to use UnsteadyAero" - +typedef ^ ^ LOGICAL ValidPhi {:}{:} - - "set to indicate when there is no valid Phi for this node at this time (temporarially turn off induction when this is false)" - +typedef ^ OtherStateType Logical nodesInitialized - - - "the node states have been initialized properly" - + +# ..... 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 Logical FirstWarn_Skew - - - "flag so invalid skew warning doesn't get repeated forever" - +typedef ^ MiscVarType Logical FirstWarn_Phi - - - "flag so Invalid Phi warning doesn't get repeated forever" - +typedef ^ MiscVarType Logical FirstWarn_BEMoff - - - "flag to warn the BEM was turned off" - +typedef ^ MiscVarType UA_MiscVarType UA - - - "misc vars for UnsteadyAero" - +typedef ^ MiscVarType DBEMT_MiscVarType DBEMT - - - "misc vars for DBEMT" - +typedef ^ MiscVarType UA_OutputType y_UA - - - "outputs from UnsteadyAero" - +typedef ^ MiscVarType UA_InputType u_UA {:}{:}{:} - - "inputs to UnsteadyAero at t and t+dt" - +typedef ^ MiscVarType DBEMT_InputType u_DBEMT {:} - - "inputs to DBEMT" - +typedef ^ MiscVarType ReKi TnInd_op {:}{:} - - "tangential induction at the operating point (for linearization with frozen wake assumption)" +typedef ^ MiscVarType ReKi AxInd_op {:}{:} - - "axial induction at the operating point (for linearization) with frozen wake assumption" +typedef ^ MiscVarType ReKi AxInduction {:}{:} - - "axial induction used for code run-time optimization" - +typedef ^ MiscVarType ReKi TanInduction {:}{:} - - "tangential induction used for code run-time optimization" - +typedef ^ MiscVarType Logical UseFrozenWake - - - "flag set to determine if frozen values of TnInd_op and AxInd_op should be used for this calculation in the linearization process" +typedef ^ MiscVarType ReKi Rtip {:} - - "maximum rlocal value for each blade (typically the value at the tip)" m +typedef ^ MiscVarType ReKi phi {:}{:} - - "temp variable used in update states for returning phi (to allow computing inputs and states at multiple times)" - +typedef ^ MiscVarType ReKi chi {:}{:} - - "temp variable used in update states for returning chi (to allow calling same routine from CalcOutput and UpdateStates)" - +typedef ^ MiscVarType Logical ValidPhi {:}{:} - - "temp variable used in calcOutput for ValidPhi (to allow calling same routine from CalcOutput and UpdateStates)" - +typedef ^ MiscVarType ReKi BEM_weight - - "temp variable used to turn off BEM for low TSR and/or large skew angles" - + +# ..... 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 DbKi DT - - - "time step" s +typedef ^ ^ ReKi chord {:}{:} - - "Chord length at node" m +typedef ^ ^ INTEGER numBlades - - - "Number of blades" - +typedef ^ ^ ReKi airDens - - - "Air density" kg/m^3 +typedef ^ ^ ReKi kinVisc - - - "Kinematic air viscosity" m^2/s +typedef ^ ^ INTEGER skewWakeMod - - - "Type of skewed-wake correction model [switch] {1=uncoupled, 2=Pitt/Peters, 3=coupled}" - +typedef ^ ^ ReKi aTol - - - "Tolerance for the induction solution" - +typedef ^ ^ LOGICAL useTipLoss - - - "Use the Prandtl tip-loss model? [flag]" - +typedef ^ ^ LOGICAL useHubLoss - - - "Use the Prandtl hub-loss model? [flag]" - +typedef ^ ^ LOGICAL useInduction - - - "Include induction in BEMT calculations [flag] { If FALSE then useTanInd will be set to FALSE}" - +typedef ^ ^ LOGICAL useTanInd - - - "Include tangential induction in BEMT calculations [flag]" - +typedef ^ ^ LOGICAL useAIDrag - - - "Include the drag term in the axial-induction calculation? [flag]" - +typedef ^ ^ LOGICAL useTIDrag - - - "Include the drag term in the tangential-induction calculation? Ignored if TanInd is False. [flag]" - +typedef ^ ^ INTEGER numBladeNodes - - - "Number of blade nodes used in the analysis" - +typedef ^ ^ INTEGER numReIterations - - - "Number of iterations for finding the Reynolds number" - +typedef ^ ^ INTEGER maxIndIterations - - - "Maximum number of iterations of induction factor solve" - +typedef ^ ^ INTEGER AFindx {:}{:} - - "Index of airfoil data file for blade node location [array of numBladeNodes]" - +typedef ^ ^ ReKi tipLossConst {:}{:} - - "A constant computed during initialization based on B*(zTip-zLocal)/(2*zLocal)" - +typedef ^ ^ ReKi hubLossConst {:}{:} - - "A constant computed during initialization based on B*(zLocal-zHub)/(2*zHub)" - +typedef ^ ^ ReKi zHub {:} - - "Distance to hub for each blade" m +typedef ^ ^ UA_ParameterType UA - - - "parameters for UnsteadyAero" - +typedef ^ ^ DBEMT_ParameterType DBEMT - - - "parameters for DBEMT" - +typedef ^ ^ LOGICAL UA_Flag - - - "logical flag indicating whether to use UnsteadyAero" - +typedef ^ ^ IntKi DBEMT_Mod - - - "DBEMT Model. 0 = constant tau1, 1 = time dependent tau1" - +typedef ^ ^ ReKi yawCorrFactor - - - "constant used in Pitt/Peters skewed wake model (default is 15*pi/32)" - +typedef ^ ^ LOGICAL FixedInductions {:}{:} - - "flag to determine if BEM inductions should be fixed and not modified by dbemt or skewed wake" - +# + +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType ReKi theta {:}{:} - - "Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)]" rad +typedef ^ ^ ReKi chi0 - - - "Angle between the vector normal to the rotor plane and the wind vector (e.g., the yaw angle in the case of no tilt)" rad +typedef ^ ^ ReKi psi {:} - - "Azimuth angle" rad +typedef ^ ^ ReKi omega - - - "Angular velocity of rotor" rad/s +typedef ^ ^ ReKi TSR - - - "Tip-speed ratio (to check if BEM should be turned off)" - +typedef ^ ^ ReKi Vx {:}{:} - - "Local axial velocity at node" m/s +typedef ^ ^ ReKi Vy {:}{:} - - "Local tangential velocity at node" m/s +typedef ^ ^ ReKi Vx_elast_dot {:}{:} - - "Local relative axial acceleration at node (for CDBEMT)" "m/s^2" +typedef ^ ^ ReKi Vy_elast_dot {:}{:} - - "Local relative tangential acceleration at node (for CDBEMT)" "m/s^2" +typedef ^ ^ ReKi omega_z {:}{:} - - "rotation of no-sweep-pitch-twist coordinate system around z (for CDBEMT and CUA)" "rad/s" +typedef ^ ^ ReKi rLocal {:}{:} - - "Radial distance from center-of-rotation to node" m +typedef ^ InputType ReKi Un_disk - - - "disk-averaged velocity normal to the rotor disk (for input to DBEMT)" m/s +typedef ^ ^ ReKi UserProp {:}{:} - - "Optional user property for interpolating airfoils (per element per blade)" - +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType ReKi Vrel {:}{:} - - "Total local relative velocity" m/s +typedef ^ ^ ReKi phi {:}{:} - - "angle between the plane of rotation and the direction of the local wind" rad +typedef ^ ^ ReKi axInduction {:}{:} - - "axial induction" - +typedef ^ ^ ReKi tanInduction {:}{:} - - "tangential induction" - +typedef ^ ^ ReKi Re {:}{:} - - "Reynold's number" - +typedef ^ ^ ReKi AOA {:}{:} - - "angle of attack" rad +typedef ^ ^ ReKi Cx {:}{:} - - "normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade" - +typedef ^ ^ ReKi Cy {:}{:} - - "tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade" - +typedef ^ ^ ReKi Cm {:}{:} - - "pitching moment coefficient of the jth node in the kth blade" - +typedef ^ ^ ReKi Cl {:}{:} - - "lift coefficient" - +typedef ^ ^ ReKi Cd {:}{:} - - "drag coefficient" - +typedef ^ ^ ReKi chi {:}{:} - - "wake skew angle" rad +typedef ^ ^ ReKi Cpmin {:}{:} - - "min Cpressure" - diff --git a/OpenFAST/modules/aerodyn/src/BEMT_Types.f90 b/OpenFAST/modules/aerodyn/src/BEMT_Types.f90 new file mode 100644 index 000000000..385866ddd --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/BEMT_Types.f90 @@ -0,0 +1,6580 @@ +!STARTOFREGISTRYGENERATEDFILE 'BEMT_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 +!********************************************************************************************************************************* +! BEMT_Types +!................................................................................................................................. +! This file is part of BEMT. +! +! 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 BEMT. 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 BEMT_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE UnsteadyAero_Types +USE DBEMT_Types +USE NWTC_Library +IMPLICIT NONE +! ========= BEMT_InitInputType ======= + TYPE, PUBLIC :: BEMT_InitInputType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chord !< Chord length at node [m] + INTEGER(IntKi) :: numBlades !< Number of blades [-] + REAL(ReKi) :: airDens !< Air density [kg/m^3] + REAL(ReKi) :: kinVisc !< Kinematic air viscosity [m^2/s] + INTEGER(IntKi) :: skewWakeMod !< Type of skewed-wake correction model [switch] {1=uncoupled, 2=Pitt/Peters, 3=coupled} [-] + REAL(ReKi) :: aTol !< Tolerance for the induction solution [-] + LOGICAL :: useTipLoss !< Use the Prandtl tip-loss model? [flag] [-] + LOGICAL :: useHubLoss !< Use the Prandtl hub-loss model? [flag] [-] + LOGICAL :: useInduction !< Include induction in BEMT calculations [flag] { If FALSE then useTanInd will be set to FALSE} [-] + LOGICAL :: useTanInd !< Include tangential induction in BEMT calculations [flag] [-] + LOGICAL :: useAIDrag !< Include the drag term in the axial-induction calculation? [flag] [-] + LOGICAL :: useTIDrag !< Include the drag term in the tangential-induction calculation? Ignored if TanInd is False. [flag] [-] + INTEGER(IntKi) :: numBladeNodes !< Number of blade nodes used in the analysis [-] + INTEGER(IntKi) :: numReIterations !< Number of iterations for finding the Reynolds number [-] + INTEGER(IntKi) :: maxIndIterations !< Maximum number of iterations of induction factor solve [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: AFindx !< Index of airfoil data file for blade node location [array of numBladeNodes] [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zHub !< Distance to hub for each blade [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: zLocal !< Distance to blade node, measured along the blade [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zTip !< Distance to blade tip, measured along the blade [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rLocal !< Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT [m] + INTEGER(IntKi) :: UAMod !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] + LOGICAL :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + LOGICAL :: Flookup !< Use table lookup for f' and f'' [-] + REAL(ReKi) :: a_s !< speed of sound [m/s] + INTEGER(IntKi) :: DBEMT_Mod !< DBEMT model. 1 = constant tau1, 2 = time dependent tau1 [-] + REAL(ReKi) :: tau1_const !< DBEMT time constant (when DBEMT_Mod=1) [s] + REAL(ReKi) :: yawCorrFactor !< constant used in Pitt/Peters skewed wake model (default is 15*pi/32) [-] + END TYPE BEMT_InitInputType +! ======================= +! ========= BEMT_InitOutputType ======= + TYPE, PUBLIC :: BEMT_InitOutputType + TYPE(ProgDesc) :: Version !< [-] + END TYPE BEMT_InitOutputType +! ======================= +! ========= BEMT_ContinuousStateType ======= + TYPE, PUBLIC :: BEMT_ContinuousStateType + TYPE(UA_ContinuousStateType) :: UA !< UA module continuous states [-] + TYPE(DBEMT_ContinuousStateType) :: DBEMT !< DBEMT module continuous states [-] + END TYPE BEMT_ContinuousStateType +! ======================= +! ========= BEMT_DiscreteStateType ======= + TYPE, PUBLIC :: BEMT_DiscreteStateType + TYPE(UA_DiscreteStateType) :: UA !< states for UnsteadyAero [-] + END TYPE BEMT_DiscreteStateType +! ======================= +! ========= BEMT_ConstraintStateType ======= + TYPE, PUBLIC :: BEMT_ConstraintStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: phi !< angle between the plane of rotation and the direction of the local wind [rad] + END TYPE BEMT_ConstraintStateType +! ======================= +! ========= BEMT_OtherStateType ======= + TYPE, PUBLIC :: BEMT_OtherStateType + TYPE(UA_OtherStateType) :: UA !< other states for UnsteadyAero [-] + TYPE(DBEMT_OtherStateType) :: DBEMT !< other states for DBEMT [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: ValidPhi !< set to indicate when there is no valid Phi for this node at this time (temporarially turn off induction when this is false) [-] + LOGICAL :: nodesInitialized !< the node states have been initialized properly [-] + END TYPE BEMT_OtherStateType +! ======================= +! ========= BEMT_MiscVarType ======= + TYPE, PUBLIC :: BEMT_MiscVarType + LOGICAL :: FirstWarn_Skew !< flag so invalid skew warning doesn't get repeated forever [-] + LOGICAL :: FirstWarn_Phi !< flag so Invalid Phi warning doesn't get repeated forever [-] + LOGICAL :: FirstWarn_BEMoff !< flag to warn the BEM was turned off [-] + TYPE(UA_MiscVarType) :: UA !< misc vars for UnsteadyAero [-] + TYPE(DBEMT_MiscVarType) :: DBEMT !< misc vars for DBEMT [-] + TYPE(UA_OutputType) :: y_UA !< outputs from UnsteadyAero [-] + TYPE(UA_InputType) , DIMENSION(:,:,:), ALLOCATABLE :: u_UA !< inputs to UnsteadyAero at t and t+dt [-] + TYPE(DBEMT_InputType) , DIMENSION(:), ALLOCATABLE :: u_DBEMT !< inputs to DBEMT [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TnInd_op !< tangential induction at the operating point (for linearization with frozen wake assumption) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AxInd_op !< axial induction at the operating point (for linearization) with frozen wake assumption [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AxInduction !< axial induction used for code run-time optimization [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TanInduction !< tangential induction used for code run-time optimization [-] + LOGICAL :: UseFrozenWake !< flag set to determine if frozen values of TnInd_op and AxInd_op should be used for this calculation in the linearization process [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Rtip !< maximum rlocal value for each blade (typically the value at the tip) [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: phi !< temp variable used in update states for returning phi (to allow computing inputs and states at multiple times) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chi !< temp variable used in update states for returning chi (to allow calling same routine from CalcOutput and UpdateStates) [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: ValidPhi !< temp variable used in calcOutput for ValidPhi (to allow calling same routine from CalcOutput and UpdateStates) [-] + REAL(ReKi) :: BEM_weight + END TYPE BEMT_MiscVarType +! ======================= +! ========= BEMT_ParameterType ======= + TYPE, PUBLIC :: BEMT_ParameterType + REAL(DbKi) :: DT !< time step [s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chord !< Chord length at node [m] + INTEGER(IntKi) :: numBlades !< Number of blades [-] + REAL(ReKi) :: airDens !< Air density [kg/m^3] + REAL(ReKi) :: kinVisc !< Kinematic air viscosity [m^2/s] + INTEGER(IntKi) :: skewWakeMod !< Type of skewed-wake correction model [switch] {1=uncoupled, 2=Pitt/Peters, 3=coupled} [-] + REAL(ReKi) :: aTol !< Tolerance for the induction solution [-] + LOGICAL :: useTipLoss !< Use the Prandtl tip-loss model? [flag] [-] + LOGICAL :: useHubLoss !< Use the Prandtl hub-loss model? [flag] [-] + LOGICAL :: useInduction !< Include induction in BEMT calculations [flag] { If FALSE then useTanInd will be set to FALSE} [-] + LOGICAL :: useTanInd !< Include tangential induction in BEMT calculations [flag] [-] + LOGICAL :: useAIDrag !< Include the drag term in the axial-induction calculation? [flag] [-] + LOGICAL :: useTIDrag !< Include the drag term in the tangential-induction calculation? Ignored if TanInd is False. [flag] [-] + INTEGER(IntKi) :: numBladeNodes !< Number of blade nodes used in the analysis [-] + INTEGER(IntKi) :: numReIterations !< Number of iterations for finding the Reynolds number [-] + INTEGER(IntKi) :: maxIndIterations !< Maximum number of iterations of induction factor solve [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: AFindx !< Index of airfoil data file for blade node location [array of numBladeNodes] [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tipLossConst !< A constant computed during initialization based on B*(zTip-zLocal)/(2*zLocal) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: hubLossConst !< A constant computed during initialization based on B*(zLocal-zHub)/(2*zHub) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zHub !< Distance to hub for each blade [m] + TYPE(UA_ParameterType) :: UA !< parameters for UnsteadyAero [-] + TYPE(DBEMT_ParameterType) :: DBEMT !< parameters for DBEMT [-] + LOGICAL :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + INTEGER(IntKi) :: DBEMT_Mod !< DBEMT Model. 0 = constant tau1, 1 = time dependent tau1 [-] + REAL(ReKi) :: yawCorrFactor !< constant used in Pitt/Peters skewed wake model (default is 15*pi/32) [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: FixedInductions !< flag to determine if BEM inductions should be fixed and not modified by dbemt or skewed wake [-] + END TYPE BEMT_ParameterType +! ======================= +! ========= BEMT_InputType ======= + TYPE, PUBLIC :: BEMT_InputType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: theta !< Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)] [rad] + REAL(ReKi) :: chi0 !< Angle between the vector normal to the rotor plane and the wind vector (e.g., the yaw angle in the case of no tilt) [rad] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: psi !< Azimuth angle [rad] + REAL(ReKi) :: omega !< Angular velocity of rotor [rad/s] + REAL(ReKi) :: TSR !< Tip-speed ratio (to check if BEM should be turned off) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vx !< Local axial velocity at node [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vy !< Local tangential velocity at node [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vx_elast_dot !< Local relative axial acceleration at node (for CDBEMT) [m/s^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vy_elast_dot !< Local relative tangential acceleration at node (for CDBEMT) [m/s^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: omega_z !< rotation of no-sweep-pitch-twist coordinate system around z (for CDBEMT and CUA) [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rLocal !< Radial distance from center-of-rotation to node [m] + REAL(ReKi) :: Un_disk !< disk-averaged velocity normal to the rotor disk (for input to DBEMT) [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: UserProp !< Optional user property for interpolating airfoils (per element per blade) [-] + END TYPE BEMT_InputType +! ======================= +! ========= BEMT_OutputType ======= + TYPE, PUBLIC :: BEMT_OutputType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vrel !< Total local relative velocity [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: phi !< angle between the plane of rotation and the direction of the local wind [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: axInduction !< axial induction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tanInduction !< tangential induction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Re !< Reynold's number [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AOA !< angle of attack [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cx !< normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cy !< tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cm !< pitching moment coefficient of the jth node in the kth blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cl !< lift coefficient [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cd !< drag coefficient [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chi !< wake skew angle [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cpmin !< min Cpressure [-] + END TYPE BEMT_OutputType +! ======================= +CONTAINS + SUBROUTINE BEMT_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(BEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitInputData%chord)) THEN + i1_l = LBOUND(SrcInitInputData%chord,1) + i1_u = UBOUND(SrcInitInputData%chord,1) + i2_l = LBOUND(SrcInitInputData%chord,2) + i2_u = UBOUND(SrcInitInputData%chord,2) + IF (.NOT. ALLOCATED(DstInitInputData%chord)) THEN + ALLOCATE(DstInitInputData%chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%chord = SrcInitInputData%chord +ENDIF + DstInitInputData%numBlades = SrcInitInputData%numBlades + DstInitInputData%airDens = SrcInitInputData%airDens + DstInitInputData%kinVisc = SrcInitInputData%kinVisc + DstInitInputData%skewWakeMod = SrcInitInputData%skewWakeMod + DstInitInputData%aTol = SrcInitInputData%aTol + DstInitInputData%useTipLoss = SrcInitInputData%useTipLoss + DstInitInputData%useHubLoss = SrcInitInputData%useHubLoss + DstInitInputData%useInduction = SrcInitInputData%useInduction + DstInitInputData%useTanInd = SrcInitInputData%useTanInd + DstInitInputData%useAIDrag = SrcInitInputData%useAIDrag + DstInitInputData%useTIDrag = SrcInitInputData%useTIDrag + DstInitInputData%numBladeNodes = SrcInitInputData%numBladeNodes + DstInitInputData%numReIterations = SrcInitInputData%numReIterations + DstInitInputData%maxIndIterations = SrcInitInputData%maxIndIterations +IF (ALLOCATED(SrcInitInputData%AFindx)) THEN + i1_l = LBOUND(SrcInitInputData%AFindx,1) + i1_u = UBOUND(SrcInitInputData%AFindx,1) + i2_l = LBOUND(SrcInitInputData%AFindx,2) + i2_u = UBOUND(SrcInitInputData%AFindx,2) + IF (.NOT. ALLOCATED(DstInitInputData%AFindx)) THEN + ALLOCATE(DstInitInputData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%AFindx = SrcInitInputData%AFindx +ENDIF +IF (ALLOCATED(SrcInitInputData%zHub)) THEN + i1_l = LBOUND(SrcInitInputData%zHub,1) + i1_u = UBOUND(SrcInitInputData%zHub,1) + IF (.NOT. ALLOCATED(DstInitInputData%zHub)) THEN + ALLOCATE(DstInitInputData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zHub = SrcInitInputData%zHub +ENDIF +IF (ALLOCATED(SrcInitInputData%zLocal)) THEN + i1_l = LBOUND(SrcInitInputData%zLocal,1) + i1_u = UBOUND(SrcInitInputData%zLocal,1) + i2_l = LBOUND(SrcInitInputData%zLocal,2) + i2_u = UBOUND(SrcInitInputData%zLocal,2) + IF (.NOT. ALLOCATED(DstInitInputData%zLocal)) THEN + ALLOCATE(DstInitInputData%zLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zLocal = SrcInitInputData%zLocal +ENDIF +IF (ALLOCATED(SrcInitInputData%zTip)) THEN + i1_l = LBOUND(SrcInitInputData%zTip,1) + i1_u = UBOUND(SrcInitInputData%zTip,1) + IF (.NOT. ALLOCATED(DstInitInputData%zTip)) THEN + ALLOCATE(DstInitInputData%zTip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zTip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zTip = SrcInitInputData%zTip +ENDIF +IF (ALLOCATED(SrcInitInputData%rLocal)) THEN + i1_l = LBOUND(SrcInitInputData%rLocal,1) + i1_u = UBOUND(SrcInitInputData%rLocal,1) + i2_l = LBOUND(SrcInitInputData%rLocal,2) + i2_u = UBOUND(SrcInitInputData%rLocal,2) + IF (.NOT. ALLOCATED(DstInitInputData%rLocal)) THEN + ALLOCATE(DstInitInputData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%rLocal = SrcInitInputData%rLocal +ENDIF + DstInitInputData%UAMod = SrcInitInputData%UAMod + DstInitInputData%UA_Flag = SrcInitInputData%UA_Flag + DstInitInputData%Flookup = SrcInitInputData%Flookup + DstInitInputData%a_s = SrcInitInputData%a_s + DstInitInputData%DBEMT_Mod = SrcInitInputData%DBEMT_Mod + DstInitInputData%tau1_const = SrcInitInputData%tau1_const + DstInitInputData%yawCorrFactor = SrcInitInputData%yawCorrFactor + END SUBROUTINE BEMT_CopyInitInput + + SUBROUTINE BEMT_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(BEMT_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%chord)) THEN + DEALLOCATE(InitInputData%chord) +ENDIF +IF (ALLOCATED(InitInputData%AFindx)) THEN + DEALLOCATE(InitInputData%AFindx) +ENDIF +IF (ALLOCATED(InitInputData%zHub)) THEN + DEALLOCATE(InitInputData%zHub) +ENDIF +IF (ALLOCATED(InitInputData%zLocal)) THEN + DEALLOCATE(InitInputData%zLocal) +ENDIF +IF (ALLOCATED(InitInputData%zTip)) THEN + DEALLOCATE(InitInputData%zTip) +ENDIF +IF (ALLOCATED(InitInputData%rLocal)) THEN + DEALLOCATE(InitInputData%rLocal) +ENDIF + END SUBROUTINE BEMT_DestroyInitInput + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 ! chord allocated yes/no + IF ( ALLOCATED(InData%chord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chord) ! chord + END IF + Int_BufSz = Int_BufSz + 1 ! numBlades + Re_BufSz = Re_BufSz + 1 ! airDens + Re_BufSz = Re_BufSz + 1 ! kinVisc + Int_BufSz = Int_BufSz + 1 ! skewWakeMod + Re_BufSz = Re_BufSz + 1 ! aTol + Int_BufSz = Int_BufSz + 1 ! useTipLoss + Int_BufSz = Int_BufSz + 1 ! useHubLoss + Int_BufSz = Int_BufSz + 1 ! useInduction + Int_BufSz = Int_BufSz + 1 ! useTanInd + Int_BufSz = Int_BufSz + 1 ! useAIDrag + Int_BufSz = Int_BufSz + 1 ! useTIDrag + Int_BufSz = Int_BufSz + 1 ! numBladeNodes + Int_BufSz = Int_BufSz + 1 ! numReIterations + Int_BufSz = Int_BufSz + 1 ! maxIndIterations + Int_BufSz = Int_BufSz + 1 ! AFindx allocated yes/no + IF ( ALLOCATED(InData%AFindx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFindx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AFindx) ! AFindx + END IF + Int_BufSz = Int_BufSz + 1 ! zHub allocated yes/no + IF ( ALLOCATED(InData%zHub) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zHub upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zHub) ! zHub + END IF + Int_BufSz = Int_BufSz + 1 ! zLocal allocated yes/no + IF ( ALLOCATED(InData%zLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! zLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zLocal) ! zLocal + END IF + Int_BufSz = Int_BufSz + 1 ! zTip allocated yes/no + IF ( ALLOCATED(InData%zTip) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zTip upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zTip) ! zTip + END IF + Int_BufSz = Int_BufSz + 1 ! rLocal allocated yes/no + IF ( ALLOCATED(InData%rLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rLocal) ! rLocal + END IF + Int_BufSz = Int_BufSz + 1 ! UAMod + Int_BufSz = Int_BufSz + 1 ! UA_Flag + Int_BufSz = Int_BufSz + 1 ! Flookup + Re_BufSz = Re_BufSz + 1 ! a_s + Int_BufSz = Int_BufSz + 1 ! DBEMT_Mod + Re_BufSz = Re_BufSz + 1 ! tau1_const + Re_BufSz = Re_BufSz + 1 ! yawCorrFactor + 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%chord) ) 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%chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chord,2), UBOUND(InData%chord,2) + DO i1 = LBOUND(InData%chord,1), UBOUND(InData%chord,1) + ReKiBuf(Re_Xferred) = InData%chord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numBlades + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%airDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%kinVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%skewWakeMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%aTol + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTipLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useHubLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useInduction, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTanInd, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useAIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numBladeNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numReIterations + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%maxIndIterations + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AFindx) ) 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%AFindx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFindx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFindx,2), UBOUND(InData%AFindx,2) + DO i1 = LBOUND(InData%AFindx,1), UBOUND(InData%AFindx,1) + IntKiBuf(Int_Xferred) = InData%AFindx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zHub) ) 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%zHub,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zHub,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zHub,1), UBOUND(InData%zHub,1) + ReKiBuf(Re_Xferred) = InData%zHub(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zLocal) ) 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%zLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%zLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%zLocal,2), UBOUND(InData%zLocal,2) + DO i1 = LBOUND(InData%zLocal,1), UBOUND(InData%zLocal,1) + ReKiBuf(Re_Xferred) = InData%zLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zTip) ) 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%zTip,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zTip,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zTip,1), UBOUND(InData%zTip,1) + ReKiBuf(Re_Xferred) = InData%zTip(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rLocal) ) 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%rLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rLocal,2), UBOUND(InData%rLocal,2) + DO i1 = LBOUND(InData%rLocal,1), UBOUND(InData%rLocal,1) + ReKiBuf(Re_Xferred) = InData%rLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%UAMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UA_Flag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Flookup, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%a_s + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DBEMT_Mod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tau1_const + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%yawCorrFactor + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BEMT_PackInitInput + + SUBROUTINE BEMT_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(BEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chord 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%chord)) DEALLOCATE(OutData%chord) + ALLOCATE(OutData%chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chord,2), UBOUND(OutData%chord,2) + DO i1 = LBOUND(OutData%chord,1), UBOUND(OutData%chord,1) + OutData%chord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%numBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%airDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%kinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%skewWakeMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%aTol = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%useTipLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTipLoss) + Int_Xferred = Int_Xferred + 1 + OutData%useHubLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%useHubLoss) + Int_Xferred = Int_Xferred + 1 + OutData%useInduction = TRANSFER(IntKiBuf(Int_Xferred), OutData%useInduction) + Int_Xferred = Int_Xferred + 1 + OutData%useTanInd = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTanInd) + Int_Xferred = Int_Xferred + 1 + OutData%useAIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%useAIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%useTIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%numBladeNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%numReIterations = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%maxIndIterations = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFindx 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%AFindx)) DEALLOCATE(OutData%AFindx) + ALLOCATE(OutData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFindx,2), UBOUND(OutData%AFindx,2) + DO i1 = LBOUND(OutData%AFindx,1), UBOUND(OutData%AFindx,1) + OutData%AFindx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zHub 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%zHub)) DEALLOCATE(OutData%zHub) + ALLOCATE(OutData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%zHub,1), UBOUND(OutData%zHub,1) + OutData%zHub(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zLocal 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%zLocal)) DEALLOCATE(OutData%zLocal) + ALLOCATE(OutData%zLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%zLocal,2), UBOUND(OutData%zLocal,2) + DO i1 = LBOUND(OutData%zLocal,1), UBOUND(OutData%zLocal,1) + OutData%zLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zTip 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%zTip)) DEALLOCATE(OutData%zTip) + ALLOCATE(OutData%zTip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zTip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%zTip,1), UBOUND(OutData%zTip,1) + OutData%zTip(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rLocal 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%rLocal)) DEALLOCATE(OutData%rLocal) + ALLOCATE(OutData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rLocal,2), UBOUND(OutData%rLocal,2) + DO i1 = LBOUND(OutData%rLocal,1), UBOUND(OutData%rLocal,1) + OutData%rLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%UAMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UA_Flag = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag) + Int_Xferred = Int_Xferred + 1 + OutData%Flookup = TRANSFER(IntKiBuf(Int_Xferred), OutData%Flookup) + Int_Xferred = Int_Xferred + 1 + OutData%a_s = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DBEMT_Mod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%tau1_const = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%yawCorrFactor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BEMT_UnPackInitInput + + SUBROUTINE BEMT_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(BEMT_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 = 'BEMT_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Version, DstInitOutputData%Version, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE BEMT_CopyInitOutput + + SUBROUTINE BEMT_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(BEMT_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Version, ErrStat, ErrMsg ) + END SUBROUTINE BEMT_DestroyInitOutput + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 ! Version: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Version, ErrStat2, ErrMsg2, .TRUE. ) ! Version + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Version + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Version + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Version + 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%Version, ErrStat2, ErrMsg2, OnlySize ) ! Version + 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 BEMT_PackInitOutput + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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%Version, ErrStat2, ErrMsg2 ) ! Version + 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 BEMT_UnPackInitOutput + + SUBROUTINE BEMT_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(BEMT_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 = 'BEMT_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_CopyContState( SrcContStateData%UA, DstContStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DBEMT_CopyContState( SrcContStateData%DBEMT, DstContStateData%DBEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE BEMT_CopyContState + + SUBROUTINE BEMT_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(BEMT_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyContState( ContStateData%UA, ErrStat, ErrMsg ) + CALL DBEMT_DestroyContState( ContStateData%DBEMT, ErrStat, ErrMsg ) + END SUBROUTINE BEMT_DestroyContState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DBEMT: size of buffers for each call to pack subtype + CALL DBEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, .TRUE. ) ! DBEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DBEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DBEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DBEMT + 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 UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 DBEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, OnlySize ) ! DBEMT + 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 BEMT_PackContState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + 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 UA_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 DBEMT_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%DBEMT, ErrStat2, ErrMsg2 ) ! DBEMT + 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 BEMT_UnPackContState + + SUBROUTINE BEMT_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(BEMT_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 = 'BEMT_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_CopyDiscState( SrcDiscStateData%UA, DstDiscStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE BEMT_CopyDiscState + + SUBROUTINE BEMT_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(BEMT_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyDiscState( DiscStateData%UA, ErrStat, ErrMsg ) + END SUBROUTINE BEMT_DestroyDiscState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + 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 UA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 BEMT_PackDiscState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + 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 UA_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 BEMT_UnPackDiscState + + SUBROUTINE BEMT_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(BEMT_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) :: 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 = 'BEMT_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcConstrStateData%phi)) THEN + i1_l = LBOUND(SrcConstrStateData%phi,1) + i1_u = UBOUND(SrcConstrStateData%phi,1) + i2_l = LBOUND(SrcConstrStateData%phi,2) + i2_u = UBOUND(SrcConstrStateData%phi,2) + IF (.NOT. ALLOCATED(DstConstrStateData%phi)) THEN + ALLOCATE(DstConstrStateData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstConstrStateData%phi = SrcConstrStateData%phi +ENDIF + END SUBROUTINE BEMT_CopyConstrState + + SUBROUTINE BEMT_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(BEMT_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ConstrStateData%phi)) THEN + DEALLOCATE(ConstrStateData%phi) +ENDIF + END SUBROUTINE BEMT_DestroyConstrState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + Int_BufSz = Int_BufSz + 1 ! phi allocated yes/no + IF ( ALLOCATED(InData%phi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! phi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%phi) ! phi + 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%phi) ) 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%phi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%phi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%phi,2), UBOUND(InData%phi,2) + DO i1 = LBOUND(InData%phi,1), UBOUND(InData%phi,1) + ReKiBuf(Re_Xferred) = InData%phi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_PackConstrState + + SUBROUTINE BEMT_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(BEMT_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) :: 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 = 'BEMT_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! phi 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%phi)) DEALLOCATE(OutData%phi) + ALLOCATE(OutData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%phi,2), UBOUND(OutData%phi,2) + DO i1 = LBOUND(OutData%phi,1), UBOUND(OutData%phi,1) + OutData%phi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_UnPackConstrState + + SUBROUTINE BEMT_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(BEMT_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) :: 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 = 'BEMT_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_CopyOtherState( SrcOtherStateData%UA, DstOtherStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DBEMT_CopyOtherState( SrcOtherStateData%DBEMT, DstOtherStateData%DBEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOtherStateData%UA_Flag)) THEN + i1_l = LBOUND(SrcOtherStateData%UA_Flag,1) + i1_u = UBOUND(SrcOtherStateData%UA_Flag,1) + i2_l = LBOUND(SrcOtherStateData%UA_Flag,2) + i2_u = UBOUND(SrcOtherStateData%UA_Flag,2) + IF (.NOT. ALLOCATED(DstOtherStateData%UA_Flag)) THEN + ALLOCATE(DstOtherStateData%UA_Flag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%UA_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%UA_Flag = SrcOtherStateData%UA_Flag +ENDIF +IF (ALLOCATED(SrcOtherStateData%ValidPhi)) THEN + i1_l = LBOUND(SrcOtherStateData%ValidPhi,1) + i1_u = UBOUND(SrcOtherStateData%ValidPhi,1) + i2_l = LBOUND(SrcOtherStateData%ValidPhi,2) + i2_u = UBOUND(SrcOtherStateData%ValidPhi,2) + IF (.NOT. ALLOCATED(DstOtherStateData%ValidPhi)) THEN + ALLOCATE(DstOtherStateData%ValidPhi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%ValidPhi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%ValidPhi = SrcOtherStateData%ValidPhi +ENDIF + DstOtherStateData%nodesInitialized = SrcOtherStateData%nodesInitialized + END SUBROUTINE BEMT_CopyOtherState + + SUBROUTINE BEMT_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(BEMT_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyOtherState( OtherStateData%UA, ErrStat, ErrMsg ) + CALL DBEMT_DestroyOtherState( OtherStateData%DBEMT, ErrStat, ErrMsg ) +IF (ALLOCATED(OtherStateData%UA_Flag)) THEN + DEALLOCATE(OtherStateData%UA_Flag) +ENDIF +IF (ALLOCATED(OtherStateData%ValidPhi)) THEN + DEALLOCATE(OtherStateData%ValidPhi) +ENDIF + END SUBROUTINE BEMT_DestroyOtherState + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DBEMT: size of buffers for each call to pack subtype + CALL DBEMT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, .TRUE. ) ! DBEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DBEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DBEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DBEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! UA_Flag allocated yes/no + IF ( ALLOCATED(InData%UA_Flag) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! UA_Flag upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%UA_Flag) ! UA_Flag + END IF + Int_BufSz = Int_BufSz + 1 ! ValidPhi allocated yes/no + IF ( ALLOCATED(InData%ValidPhi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ValidPhi upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ValidPhi) ! ValidPhi + END IF + Int_BufSz = Int_BufSz + 1 ! nodesInitialized + 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 UA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 DBEMT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, OnlySize ) ! DBEMT + 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%UA_Flag) ) 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%UA_Flag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UA_Flag,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UA_Flag,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UA_Flag,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%UA_Flag,2), UBOUND(InData%UA_Flag,2) + DO i1 = LBOUND(InData%UA_Flag,1), UBOUND(InData%UA_Flag,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%UA_Flag(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ValidPhi) ) 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%ValidPhi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ValidPhi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ValidPhi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ValidPhi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ValidPhi,2), UBOUND(InData%ValidPhi,2) + DO i1 = LBOUND(InData%ValidPhi,1), UBOUND(InData%ValidPhi,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%ValidPhi(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%nodesInitialized, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BEMT_PackOtherState + + SUBROUTINE BEMT_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(BEMT_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) :: 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 = 'BEMT_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 + 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 UA_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 DBEMT_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%DBEMT, ErrStat2, ErrMsg2 ) ! DBEMT + 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 ! UA_Flag 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%UA_Flag)) DEALLOCATE(OutData%UA_Flag) + ALLOCATE(OutData%UA_Flag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UA_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%UA_Flag,2), UBOUND(OutData%UA_Flag,2) + DO i1 = LBOUND(OutData%UA_Flag,1), UBOUND(OutData%UA_Flag,1) + OutData%UA_Flag(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ValidPhi 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%ValidPhi)) DEALLOCATE(OutData%ValidPhi) + ALLOCATE(OutData%ValidPhi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ValidPhi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ValidPhi,2), UBOUND(OutData%ValidPhi,2) + DO i1 = LBOUND(OutData%ValidPhi,1), UBOUND(OutData%ValidPhi,1) + OutData%ValidPhi(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%ValidPhi(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%nodesInitialized = TRANSFER(IntKiBuf(Int_Xferred), OutData%nodesInitialized) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BEMT_UnPackOtherState + + SUBROUTINE BEMT_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(BEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%FirstWarn_Skew = SrcMiscData%FirstWarn_Skew + DstMiscData%FirstWarn_Phi = SrcMiscData%FirstWarn_Phi + DstMiscData%FirstWarn_BEMoff = SrcMiscData%FirstWarn_BEMoff + CALL UA_CopyMisc( SrcMiscData%UA, DstMiscData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DBEMT_CopyMisc( SrcMiscData%DBEMT, DstMiscData%DBEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL UA_CopyOutput( SrcMiscData%y_UA, DstMiscData%y_UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMiscData%u_UA)) THEN + i1_l = LBOUND(SrcMiscData%u_UA,1) + i1_u = UBOUND(SrcMiscData%u_UA,1) + i2_l = LBOUND(SrcMiscData%u_UA,2) + i2_u = UBOUND(SrcMiscData%u_UA,2) + i3_l = LBOUND(SrcMiscData%u_UA,3) + i3_u = UBOUND(SrcMiscData%u_UA,3) + IF (.NOT. ALLOCATED(DstMiscData%u_UA)) THEN + ALLOCATE(DstMiscData%u_UA(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%u_UA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i3 = LBOUND(SrcMiscData%u_UA,3), UBOUND(SrcMiscData%u_UA,3) + DO i2 = LBOUND(SrcMiscData%u_UA,2), UBOUND(SrcMiscData%u_UA,2) + DO i1 = LBOUND(SrcMiscData%u_UA,1), UBOUND(SrcMiscData%u_UA,1) + CALL UA_CopyInput( SrcMiscData%u_UA(i1,i2,i3), DstMiscData%u_UA(i1,i2,i3), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%u_DBEMT)) THEN + i1_l = LBOUND(SrcMiscData%u_DBEMT,1) + i1_u = UBOUND(SrcMiscData%u_DBEMT,1) + IF (.NOT. ALLOCATED(DstMiscData%u_DBEMT)) THEN + ALLOCATE(DstMiscData%u_DBEMT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%u_DBEMT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%u_DBEMT,1), UBOUND(SrcMiscData%u_DBEMT,1) + CALL DBEMT_CopyInput( SrcMiscData%u_DBEMT(i1), DstMiscData%u_DBEMT(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%TnInd_op)) THEN + i1_l = LBOUND(SrcMiscData%TnInd_op,1) + i1_u = UBOUND(SrcMiscData%TnInd_op,1) + i2_l = LBOUND(SrcMiscData%TnInd_op,2) + i2_u = UBOUND(SrcMiscData%TnInd_op,2) + IF (.NOT. ALLOCATED(DstMiscData%TnInd_op)) THEN + ALLOCATE(DstMiscData%TnInd_op(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%TnInd_op.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%TnInd_op = SrcMiscData%TnInd_op +ENDIF +IF (ALLOCATED(SrcMiscData%AxInd_op)) THEN + i1_l = LBOUND(SrcMiscData%AxInd_op,1) + i1_u = UBOUND(SrcMiscData%AxInd_op,1) + i2_l = LBOUND(SrcMiscData%AxInd_op,2) + i2_u = UBOUND(SrcMiscData%AxInd_op,2) + IF (.NOT. ALLOCATED(DstMiscData%AxInd_op)) THEN + ALLOCATE(DstMiscData%AxInd_op(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AxInd_op.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AxInd_op = SrcMiscData%AxInd_op +ENDIF +IF (ALLOCATED(SrcMiscData%AxInduction)) THEN + i1_l = LBOUND(SrcMiscData%AxInduction,1) + i1_u = UBOUND(SrcMiscData%AxInduction,1) + i2_l = LBOUND(SrcMiscData%AxInduction,2) + i2_u = UBOUND(SrcMiscData%AxInduction,2) + IF (.NOT. ALLOCATED(DstMiscData%AxInduction)) THEN + ALLOCATE(DstMiscData%AxInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AxInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AxInduction = SrcMiscData%AxInduction +ENDIF +IF (ALLOCATED(SrcMiscData%TanInduction)) THEN + i1_l = LBOUND(SrcMiscData%TanInduction,1) + i1_u = UBOUND(SrcMiscData%TanInduction,1) + i2_l = LBOUND(SrcMiscData%TanInduction,2) + i2_u = UBOUND(SrcMiscData%TanInduction,2) + IF (.NOT. ALLOCATED(DstMiscData%TanInduction)) THEN + ALLOCATE(DstMiscData%TanInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%TanInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%TanInduction = SrcMiscData%TanInduction +ENDIF + DstMiscData%UseFrozenWake = SrcMiscData%UseFrozenWake +IF (ALLOCATED(SrcMiscData%Rtip)) THEN + i1_l = LBOUND(SrcMiscData%Rtip,1) + i1_u = UBOUND(SrcMiscData%Rtip,1) + IF (.NOT. ALLOCATED(DstMiscData%Rtip)) THEN + ALLOCATE(DstMiscData%Rtip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Rtip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Rtip = SrcMiscData%Rtip +ENDIF +IF (ALLOCATED(SrcMiscData%phi)) THEN + i1_l = LBOUND(SrcMiscData%phi,1) + i1_u = UBOUND(SrcMiscData%phi,1) + i2_l = LBOUND(SrcMiscData%phi,2) + i2_u = UBOUND(SrcMiscData%phi,2) + IF (.NOT. ALLOCATED(DstMiscData%phi)) THEN + ALLOCATE(DstMiscData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%phi = SrcMiscData%phi +ENDIF +IF (ALLOCATED(SrcMiscData%chi)) THEN + i1_l = LBOUND(SrcMiscData%chi,1) + i1_u = UBOUND(SrcMiscData%chi,1) + i2_l = LBOUND(SrcMiscData%chi,2) + i2_u = UBOUND(SrcMiscData%chi,2) + IF (.NOT. ALLOCATED(DstMiscData%chi)) THEN + ALLOCATE(DstMiscData%chi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%chi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%chi = SrcMiscData%chi +ENDIF +IF (ALLOCATED(SrcMiscData%ValidPhi)) THEN + i1_l = LBOUND(SrcMiscData%ValidPhi,1) + i1_u = UBOUND(SrcMiscData%ValidPhi,1) + i2_l = LBOUND(SrcMiscData%ValidPhi,2) + i2_u = UBOUND(SrcMiscData%ValidPhi,2) + IF (.NOT. ALLOCATED(DstMiscData%ValidPhi)) THEN + ALLOCATE(DstMiscData%ValidPhi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ValidPhi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ValidPhi = SrcMiscData%ValidPhi +ENDIF + DstMiscData%BEM_weight = SrcMiscData%BEM_weight + END SUBROUTINE BEMT_CopyMisc + + SUBROUTINE BEMT_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(BEMT_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyMisc( MiscData%UA, ErrStat, ErrMsg ) + CALL DBEMT_DestroyMisc( MiscData%DBEMT, ErrStat, ErrMsg ) + CALL UA_DestroyOutput( MiscData%y_UA, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%u_UA)) THEN +DO i3 = LBOUND(MiscData%u_UA,3), UBOUND(MiscData%u_UA,3) +DO i2 = LBOUND(MiscData%u_UA,2), UBOUND(MiscData%u_UA,2) +DO i1 = LBOUND(MiscData%u_UA,1), UBOUND(MiscData%u_UA,1) + CALL UA_DestroyInput( MiscData%u_UA(i1,i2,i3), ErrStat, ErrMsg ) +ENDDO +ENDDO +ENDDO + DEALLOCATE(MiscData%u_UA) +ENDIF +IF (ALLOCATED(MiscData%u_DBEMT)) THEN +DO i1 = LBOUND(MiscData%u_DBEMT,1), UBOUND(MiscData%u_DBEMT,1) + CALL DBEMT_DestroyInput( MiscData%u_DBEMT(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%u_DBEMT) +ENDIF +IF (ALLOCATED(MiscData%TnInd_op)) THEN + DEALLOCATE(MiscData%TnInd_op) +ENDIF +IF (ALLOCATED(MiscData%AxInd_op)) THEN + DEALLOCATE(MiscData%AxInd_op) +ENDIF +IF (ALLOCATED(MiscData%AxInduction)) THEN + DEALLOCATE(MiscData%AxInduction) +ENDIF +IF (ALLOCATED(MiscData%TanInduction)) THEN + DEALLOCATE(MiscData%TanInduction) +ENDIF +IF (ALLOCATED(MiscData%Rtip)) THEN + DEALLOCATE(MiscData%Rtip) +ENDIF +IF (ALLOCATED(MiscData%phi)) THEN + DEALLOCATE(MiscData%phi) +ENDIF +IF (ALLOCATED(MiscData%chi)) THEN + DEALLOCATE(MiscData%chi) +ENDIF +IF (ALLOCATED(MiscData%ValidPhi)) THEN + DEALLOCATE(MiscData%ValidPhi) +ENDIF + END SUBROUTINE BEMT_DestroyMisc + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 ! FirstWarn_Skew + Int_BufSz = Int_BufSz + 1 ! FirstWarn_Phi + Int_BufSz = Int_BufSz + 1 ! FirstWarn_BEMoff + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DBEMT: size of buffers for each call to pack subtype + CALL DBEMT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, .TRUE. ) ! DBEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DBEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DBEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DBEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y_UA: size of buffers for each call to pack subtype + CALL UA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_UA, ErrStat2, ErrMsg2, .TRUE. ) ! y_UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! u_UA allocated yes/no + IF ( ALLOCATED(InData%u_UA) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! u_UA upper/lower bounds for each dimension + DO i3 = LBOUND(InData%u_UA,3), UBOUND(InData%u_UA,3) + DO i2 = LBOUND(InData%u_UA,2), UBOUND(InData%u_UA,2) + DO i1 = LBOUND(InData%u_UA,1), UBOUND(InData%u_UA,1) + Int_BufSz = Int_BufSz + 3 ! u_UA: size of buffers for each call to pack subtype + CALL UA_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_UA(i1,i2,i3), ErrStat2, ErrMsg2, .TRUE. ) ! u_UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_DBEMT allocated yes/no + IF ( ALLOCATED(InData%u_DBEMT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_DBEMT upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_DBEMT,1), UBOUND(InData%u_DBEMT,1) + Int_BufSz = Int_BufSz + 3 ! u_DBEMT: size of buffers for each call to pack subtype + CALL DBEMT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_DBEMT(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_DBEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_DBEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_DBEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_DBEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! TnInd_op allocated yes/no + IF ( ALLOCATED(InData%TnInd_op) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TnInd_op upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TnInd_op) ! TnInd_op + END IF + Int_BufSz = Int_BufSz + 1 ! AxInd_op allocated yes/no + IF ( ALLOCATED(InData%AxInd_op) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AxInd_op upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxInd_op) ! AxInd_op + END IF + Int_BufSz = Int_BufSz + 1 ! AxInduction allocated yes/no + IF ( ALLOCATED(InData%AxInduction) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AxInduction upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxInduction) ! AxInduction + END IF + Int_BufSz = Int_BufSz + 1 ! TanInduction allocated yes/no + IF ( ALLOCATED(InData%TanInduction) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TanInduction upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TanInduction) ! TanInduction + END IF + Int_BufSz = Int_BufSz + 1 ! UseFrozenWake + Int_BufSz = Int_BufSz + 1 ! Rtip allocated yes/no + IF ( ALLOCATED(InData%Rtip) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Rtip upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Rtip) ! Rtip + END IF + Int_BufSz = Int_BufSz + 1 ! phi allocated yes/no + IF ( ALLOCATED(InData%phi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! phi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%phi) ! phi + END IF + Int_BufSz = Int_BufSz + 1 ! chi allocated yes/no + IF ( ALLOCATED(InData%chi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chi) ! chi + END IF + Int_BufSz = Int_BufSz + 1 ! ValidPhi allocated yes/no + IF ( ALLOCATED(InData%ValidPhi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ValidPhi upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ValidPhi) ! ValidPhi + END IF + Re_BufSz = Re_BufSz + 1 ! BEM_weight + 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%FirstWarn_Skew, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstWarn_Phi, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstWarn_BEMoff, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL UA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 DBEMT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, OnlySize ) ! DBEMT + 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 UA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_UA, ErrStat2, ErrMsg2, OnlySize ) ! y_UA + 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%u_UA) ) 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%u_UA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_UA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%u_UA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_UA,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%u_UA,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_UA,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%u_UA,3), UBOUND(InData%u_UA,3) + DO i2 = LBOUND(InData%u_UA,2), UBOUND(InData%u_UA,2) + DO i1 = LBOUND(InData%u_UA,1), UBOUND(InData%u_UA,1) + CALL UA_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_UA(i1,i2,i3), ErrStat2, ErrMsg2, OnlySize ) ! u_UA + 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 DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%u_DBEMT) ) 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%u_DBEMT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_DBEMT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_DBEMT,1), UBOUND(InData%u_DBEMT,1) + CALL DBEMT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_DBEMT(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_DBEMT + 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%TnInd_op) ) 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%TnInd_op,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TnInd_op,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TnInd_op,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TnInd_op,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TnInd_op,2), UBOUND(InData%TnInd_op,2) + DO i1 = LBOUND(InData%TnInd_op,1), UBOUND(InData%TnInd_op,1) + ReKiBuf(Re_Xferred) = InData%TnInd_op(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxInd_op) ) 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%AxInd_op,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxInd_op,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxInd_op,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxInd_op,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AxInd_op,2), UBOUND(InData%AxInd_op,2) + DO i1 = LBOUND(InData%AxInd_op,1), UBOUND(InData%AxInd_op,1) + ReKiBuf(Re_Xferred) = InData%AxInd_op(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxInduction) ) 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%AxInduction,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxInduction,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxInduction,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxInduction,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AxInduction,2), UBOUND(InData%AxInduction,2) + DO i1 = LBOUND(InData%AxInduction,1), UBOUND(InData%AxInduction,1) + ReKiBuf(Re_Xferred) = InData%AxInduction(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TanInduction) ) 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%TanInduction,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TanInduction,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TanInduction,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TanInduction,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TanInduction,2), UBOUND(InData%TanInduction,2) + DO i1 = LBOUND(InData%TanInduction,1), UBOUND(InData%TanInduction,1) + ReKiBuf(Re_Xferred) = InData%TanInduction(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseFrozenWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Rtip) ) 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%Rtip,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Rtip,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Rtip,1), UBOUND(InData%Rtip,1) + ReKiBuf(Re_Xferred) = InData%Rtip(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%phi) ) 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%phi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%phi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%phi,2), UBOUND(InData%phi,2) + DO i1 = LBOUND(InData%phi,1), UBOUND(InData%phi,1) + ReKiBuf(Re_Xferred) = InData%phi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%chi) ) 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%chi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chi,2), UBOUND(InData%chi,2) + DO i1 = LBOUND(InData%chi,1), UBOUND(InData%chi,1) + ReKiBuf(Re_Xferred) = InData%chi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ValidPhi) ) 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%ValidPhi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ValidPhi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ValidPhi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ValidPhi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ValidPhi,2), UBOUND(InData%ValidPhi,2) + DO i1 = LBOUND(InData%ValidPhi,1), UBOUND(InData%ValidPhi,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%ValidPhi(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BEM_weight + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BEMT_PackMisc + + SUBROUTINE BEMT_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(BEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_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%FirstWarn_Skew = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_Skew) + Int_Xferred = Int_Xferred + 1 + OutData%FirstWarn_Phi = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_Phi) + Int_Xferred = Int_Xferred + 1 + OutData%FirstWarn_BEMoff = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_BEMoff) + 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 UA_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 DBEMT_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%DBEMT, ErrStat2, ErrMsg2 ) ! DBEMT + 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 UA_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_UA, ErrStat2, ErrMsg2 ) ! y_UA + 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 ! u_UA 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%u_UA)) DEALLOCATE(OutData%u_UA) + ALLOCATE(OutData%u_UA(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%u_UA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%u_UA,3), UBOUND(OutData%u_UA,3) + DO i2 = LBOUND(OutData%u_UA,2), UBOUND(OutData%u_UA,2) + DO i1 = LBOUND(OutData%u_UA,1), UBOUND(OutData%u_UA,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 UA_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_UA(i1,i2,i3), ErrStat2, ErrMsg2 ) ! u_UA + 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 DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_DBEMT 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%u_DBEMT)) DEALLOCATE(OutData%u_DBEMT) + ALLOCATE(OutData%u_DBEMT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_DBEMT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_DBEMT,1), UBOUND(OutData%u_DBEMT,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 DBEMT_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_DBEMT(i1), ErrStat2, ErrMsg2 ) ! u_DBEMT + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TnInd_op 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%TnInd_op)) DEALLOCATE(OutData%TnInd_op) + ALLOCATE(OutData%TnInd_op(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TnInd_op.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TnInd_op,2), UBOUND(OutData%TnInd_op,2) + DO i1 = LBOUND(OutData%TnInd_op,1), UBOUND(OutData%TnInd_op,1) + OutData%TnInd_op(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxInd_op 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%AxInd_op)) DEALLOCATE(OutData%AxInd_op) + ALLOCATE(OutData%AxInd_op(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxInd_op.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AxInd_op,2), UBOUND(OutData%AxInd_op,2) + DO i1 = LBOUND(OutData%AxInd_op,1), UBOUND(OutData%AxInd_op,1) + OutData%AxInd_op(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxInduction 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%AxInduction)) DEALLOCATE(OutData%AxInduction) + ALLOCATE(OutData%AxInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AxInduction,2), UBOUND(OutData%AxInduction,2) + DO i1 = LBOUND(OutData%AxInduction,1), UBOUND(OutData%AxInduction,1) + OutData%AxInduction(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TanInduction 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%TanInduction)) DEALLOCATE(OutData%TanInduction) + ALLOCATE(OutData%TanInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TanInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TanInduction,2), UBOUND(OutData%TanInduction,2) + DO i1 = LBOUND(OutData%TanInduction,1), UBOUND(OutData%TanInduction,1) + OutData%TanInduction(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%UseFrozenWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseFrozenWake) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Rtip 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%Rtip)) DEALLOCATE(OutData%Rtip) + ALLOCATE(OutData%Rtip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Rtip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Rtip,1), UBOUND(OutData%Rtip,1) + OutData%Rtip(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! phi 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%phi)) DEALLOCATE(OutData%phi) + ALLOCATE(OutData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%phi,2), UBOUND(OutData%phi,2) + DO i1 = LBOUND(OutData%phi,1), UBOUND(OutData%phi,1) + OutData%phi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chi 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%chi)) DEALLOCATE(OutData%chi) + ALLOCATE(OutData%chi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chi,2), UBOUND(OutData%chi,2) + DO i1 = LBOUND(OutData%chi,1), UBOUND(OutData%chi,1) + OutData%chi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ValidPhi 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%ValidPhi)) DEALLOCATE(OutData%ValidPhi) + ALLOCATE(OutData%ValidPhi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ValidPhi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ValidPhi,2), UBOUND(OutData%ValidPhi,2) + DO i1 = LBOUND(OutData%ValidPhi,1), UBOUND(OutData%ValidPhi,1) + OutData%ValidPhi(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%ValidPhi(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%BEM_weight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BEMT_UnPackMisc + + SUBROUTINE BEMT_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_ParameterType), INTENT(IN) :: SrcParamData + TYPE(BEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT +IF (ALLOCATED(SrcParamData%chord)) THEN + i1_l = LBOUND(SrcParamData%chord,1) + i1_u = UBOUND(SrcParamData%chord,1) + i2_l = LBOUND(SrcParamData%chord,2) + i2_u = UBOUND(SrcParamData%chord,2) + IF (.NOT. ALLOCATED(DstParamData%chord)) THEN + ALLOCATE(DstParamData%chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%chord = SrcParamData%chord +ENDIF + DstParamData%numBlades = SrcParamData%numBlades + DstParamData%airDens = SrcParamData%airDens + DstParamData%kinVisc = SrcParamData%kinVisc + DstParamData%skewWakeMod = SrcParamData%skewWakeMod + DstParamData%aTol = SrcParamData%aTol + DstParamData%useTipLoss = SrcParamData%useTipLoss + DstParamData%useHubLoss = SrcParamData%useHubLoss + DstParamData%useInduction = SrcParamData%useInduction + DstParamData%useTanInd = SrcParamData%useTanInd + DstParamData%useAIDrag = SrcParamData%useAIDrag + DstParamData%useTIDrag = SrcParamData%useTIDrag + DstParamData%numBladeNodes = SrcParamData%numBladeNodes + DstParamData%numReIterations = SrcParamData%numReIterations + DstParamData%maxIndIterations = SrcParamData%maxIndIterations +IF (ALLOCATED(SrcParamData%AFindx)) THEN + i1_l = LBOUND(SrcParamData%AFindx,1) + i1_u = UBOUND(SrcParamData%AFindx,1) + i2_l = LBOUND(SrcParamData%AFindx,2) + i2_u = UBOUND(SrcParamData%AFindx,2) + IF (.NOT. ALLOCATED(DstParamData%AFindx)) THEN + ALLOCATE(DstParamData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AFindx = SrcParamData%AFindx +ENDIF +IF (ALLOCATED(SrcParamData%tipLossConst)) THEN + i1_l = LBOUND(SrcParamData%tipLossConst,1) + i1_u = UBOUND(SrcParamData%tipLossConst,1) + i2_l = LBOUND(SrcParamData%tipLossConst,2) + i2_u = UBOUND(SrcParamData%tipLossConst,2) + IF (.NOT. ALLOCATED(DstParamData%tipLossConst)) THEN + ALLOCATE(DstParamData%tipLossConst(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%tipLossConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%tipLossConst = SrcParamData%tipLossConst +ENDIF +IF (ALLOCATED(SrcParamData%hubLossConst)) THEN + i1_l = LBOUND(SrcParamData%hubLossConst,1) + i1_u = UBOUND(SrcParamData%hubLossConst,1) + i2_l = LBOUND(SrcParamData%hubLossConst,2) + i2_u = UBOUND(SrcParamData%hubLossConst,2) + IF (.NOT. ALLOCATED(DstParamData%hubLossConst)) THEN + ALLOCATE(DstParamData%hubLossConst(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%hubLossConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%hubLossConst = SrcParamData%hubLossConst +ENDIF +IF (ALLOCATED(SrcParamData%zHub)) THEN + i1_l = LBOUND(SrcParamData%zHub,1) + i1_u = UBOUND(SrcParamData%zHub,1) + IF (.NOT. ALLOCATED(DstParamData%zHub)) THEN + ALLOCATE(DstParamData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%zHub = SrcParamData%zHub +ENDIF + CALL UA_CopyParam( SrcParamData%UA, DstParamData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DBEMT_CopyParam( SrcParamData%DBEMT, DstParamData%DBEMT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%UA_Flag = SrcParamData%UA_Flag + DstParamData%DBEMT_Mod = SrcParamData%DBEMT_Mod + DstParamData%yawCorrFactor = SrcParamData%yawCorrFactor +IF (ALLOCATED(SrcParamData%FixedInductions)) THEN + i1_l = LBOUND(SrcParamData%FixedInductions,1) + i1_u = UBOUND(SrcParamData%FixedInductions,1) + i2_l = LBOUND(SrcParamData%FixedInductions,2) + i2_u = UBOUND(SrcParamData%FixedInductions,2) + IF (.NOT. ALLOCATED(DstParamData%FixedInductions)) THEN + ALLOCATE(DstParamData%FixedInductions(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FixedInductions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FixedInductions = SrcParamData%FixedInductions +ENDIF + END SUBROUTINE BEMT_CopyParam + + SUBROUTINE BEMT_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(BEMT_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%chord)) THEN + DEALLOCATE(ParamData%chord) +ENDIF +IF (ALLOCATED(ParamData%AFindx)) THEN + DEALLOCATE(ParamData%AFindx) +ENDIF +IF (ALLOCATED(ParamData%tipLossConst)) THEN + DEALLOCATE(ParamData%tipLossConst) +ENDIF +IF (ALLOCATED(ParamData%hubLossConst)) THEN + DEALLOCATE(ParamData%hubLossConst) +ENDIF +IF (ALLOCATED(ParamData%zHub)) THEN + DEALLOCATE(ParamData%zHub) +ENDIF + CALL UA_DestroyParam( ParamData%UA, ErrStat, ErrMsg ) + CALL DBEMT_DestroyParam( ParamData%DBEMT, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%FixedInductions)) THEN + DEALLOCATE(ParamData%FixedInductions) +ENDIF + END SUBROUTINE BEMT_DestroyParam + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! chord allocated yes/no + IF ( ALLOCATED(InData%chord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chord) ! chord + END IF + Int_BufSz = Int_BufSz + 1 ! numBlades + Re_BufSz = Re_BufSz + 1 ! airDens + Re_BufSz = Re_BufSz + 1 ! kinVisc + Int_BufSz = Int_BufSz + 1 ! skewWakeMod + Re_BufSz = Re_BufSz + 1 ! aTol + Int_BufSz = Int_BufSz + 1 ! useTipLoss + Int_BufSz = Int_BufSz + 1 ! useHubLoss + Int_BufSz = Int_BufSz + 1 ! useInduction + Int_BufSz = Int_BufSz + 1 ! useTanInd + Int_BufSz = Int_BufSz + 1 ! useAIDrag + Int_BufSz = Int_BufSz + 1 ! useTIDrag + Int_BufSz = Int_BufSz + 1 ! numBladeNodes + Int_BufSz = Int_BufSz + 1 ! numReIterations + Int_BufSz = Int_BufSz + 1 ! maxIndIterations + Int_BufSz = Int_BufSz + 1 ! AFindx allocated yes/no + IF ( ALLOCATED(InData%AFindx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFindx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AFindx) ! AFindx + END IF + Int_BufSz = Int_BufSz + 1 ! tipLossConst allocated yes/no + IF ( ALLOCATED(InData%tipLossConst) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tipLossConst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%tipLossConst) ! tipLossConst + END IF + Int_BufSz = Int_BufSz + 1 ! hubLossConst allocated yes/no + IF ( ALLOCATED(InData%hubLossConst) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! hubLossConst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%hubLossConst) ! hubLossConst + END IF + Int_BufSz = Int_BufSz + 1 ! zHub allocated yes/no + IF ( ALLOCATED(InData%zHub) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zHub upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zHub) ! zHub + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DBEMT: size of buffers for each call to pack subtype + CALL DBEMT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, .TRUE. ) ! DBEMT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DBEMT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DBEMT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DBEMT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! UA_Flag + Int_BufSz = Int_BufSz + 1 ! DBEMT_Mod + Re_BufSz = Re_BufSz + 1 ! yawCorrFactor + Int_BufSz = Int_BufSz + 1 ! FixedInductions allocated yes/no + IF ( ALLOCATED(InData%FixedInductions) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FixedInductions upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FixedInductions) ! FixedInductions + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%chord) ) 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%chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chord,2), UBOUND(InData%chord,2) + DO i1 = LBOUND(InData%chord,1), UBOUND(InData%chord,1) + ReKiBuf(Re_Xferred) = InData%chord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numBlades + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%airDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%kinVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%skewWakeMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%aTol + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTipLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useHubLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useInduction, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTanInd, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useAIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%useTIDrag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numBladeNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numReIterations + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%maxIndIterations + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AFindx) ) 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%AFindx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFindx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFindx,2), UBOUND(InData%AFindx,2) + DO i1 = LBOUND(InData%AFindx,1), UBOUND(InData%AFindx,1) + IntKiBuf(Int_Xferred) = InData%AFindx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tipLossConst) ) 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%tipLossConst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tipLossConst,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tipLossConst,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tipLossConst,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tipLossConst,2), UBOUND(InData%tipLossConst,2) + DO i1 = LBOUND(InData%tipLossConst,1), UBOUND(InData%tipLossConst,1) + ReKiBuf(Re_Xferred) = InData%tipLossConst(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%hubLossConst) ) 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%hubLossConst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%hubLossConst,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%hubLossConst,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%hubLossConst,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%hubLossConst,2), UBOUND(InData%hubLossConst,2) + DO i1 = LBOUND(InData%hubLossConst,1), UBOUND(InData%hubLossConst,1) + ReKiBuf(Re_Xferred) = InData%hubLossConst(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zHub) ) 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%zHub,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zHub,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zHub,1), UBOUND(InData%zHub,1) + ReKiBuf(Re_Xferred) = InData%zHub(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + CALL UA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 DBEMT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%DBEMT, ErrStat2, ErrMsg2, OnlySize ) ! DBEMT + 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) = TRANSFER(InData%UA_Flag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DBEMT_Mod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%yawCorrFactor + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FixedInductions) ) 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%FixedInductions,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FixedInductions,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FixedInductions,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FixedInductions,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FixedInductions,2), UBOUND(InData%FixedInductions,2) + DO i1 = LBOUND(InData%FixedInductions,1), UBOUND(InData%FixedInductions,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedInductions(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_PackParam + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chord 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%chord)) DEALLOCATE(OutData%chord) + ALLOCATE(OutData%chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chord,2), UBOUND(OutData%chord,2) + DO i1 = LBOUND(OutData%chord,1), UBOUND(OutData%chord,1) + OutData%chord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%numBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%airDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%kinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%skewWakeMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%aTol = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%useTipLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTipLoss) + Int_Xferred = Int_Xferred + 1 + OutData%useHubLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%useHubLoss) + Int_Xferred = Int_Xferred + 1 + OutData%useInduction = TRANSFER(IntKiBuf(Int_Xferred), OutData%useInduction) + Int_Xferred = Int_Xferred + 1 + OutData%useTanInd = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTanInd) + Int_Xferred = Int_Xferred + 1 + OutData%useAIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%useAIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%useTIDrag = TRANSFER(IntKiBuf(Int_Xferred), OutData%useTIDrag) + Int_Xferred = Int_Xferred + 1 + OutData%numBladeNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%numReIterations = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%maxIndIterations = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFindx 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%AFindx)) DEALLOCATE(OutData%AFindx) + ALLOCATE(OutData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFindx,2), UBOUND(OutData%AFindx,2) + DO i1 = LBOUND(OutData%AFindx,1), UBOUND(OutData%AFindx,1) + OutData%AFindx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tipLossConst 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%tipLossConst)) DEALLOCATE(OutData%tipLossConst) + ALLOCATE(OutData%tipLossConst(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tipLossConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tipLossConst,2), UBOUND(OutData%tipLossConst,2) + DO i1 = LBOUND(OutData%tipLossConst,1), UBOUND(OutData%tipLossConst,1) + OutData%tipLossConst(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! hubLossConst 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%hubLossConst)) DEALLOCATE(OutData%hubLossConst) + ALLOCATE(OutData%hubLossConst(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%hubLossConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%hubLossConst,2), UBOUND(OutData%hubLossConst,2) + DO i1 = LBOUND(OutData%hubLossConst,1), UBOUND(OutData%hubLossConst,1) + OutData%hubLossConst(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zHub 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%zHub)) DEALLOCATE(OutData%zHub) + ALLOCATE(OutData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%zHub,1), UBOUND(OutData%zHub,1) + OutData%zHub(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 UA_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 DBEMT_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%DBEMT, ErrStat2, ErrMsg2 ) ! DBEMT + 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%UA_Flag = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag) + Int_Xferred = Int_Xferred + 1 + OutData%DBEMT_Mod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%yawCorrFactor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FixedInductions 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%FixedInductions)) DEALLOCATE(OutData%FixedInductions) + ALLOCATE(OutData%FixedInductions(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FixedInductions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FixedInductions,2), UBOUND(OutData%FixedInductions,2) + DO i1 = LBOUND(OutData%FixedInductions,1), UBOUND(OutData%FixedInductions,1) + OutData%FixedInductions(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedInductions(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_UnPackParam + + SUBROUTINE BEMT_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_InputType), INTENT(IN) :: SrcInputData + TYPE(BEMT_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 = 'BEMT_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%theta)) THEN + i1_l = LBOUND(SrcInputData%theta,1) + i1_u = UBOUND(SrcInputData%theta,1) + i2_l = LBOUND(SrcInputData%theta,2) + i2_u = UBOUND(SrcInputData%theta,2) + IF (.NOT. ALLOCATED(DstInputData%theta)) THEN + ALLOCATE(DstInputData%theta(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%theta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%theta = SrcInputData%theta +ENDIF + DstInputData%chi0 = SrcInputData%chi0 +IF (ALLOCATED(SrcInputData%psi)) THEN + i1_l = LBOUND(SrcInputData%psi,1) + i1_u = UBOUND(SrcInputData%psi,1) + IF (.NOT. ALLOCATED(DstInputData%psi)) THEN + ALLOCATE(DstInputData%psi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%psi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%psi = SrcInputData%psi +ENDIF + DstInputData%omega = SrcInputData%omega + DstInputData%TSR = SrcInputData%TSR +IF (ALLOCATED(SrcInputData%Vx)) THEN + i1_l = LBOUND(SrcInputData%Vx,1) + i1_u = UBOUND(SrcInputData%Vx,1) + i2_l = LBOUND(SrcInputData%Vx,2) + i2_u = UBOUND(SrcInputData%Vx,2) + IF (.NOT. ALLOCATED(DstInputData%Vx)) THEN + ALLOCATE(DstInputData%Vx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Vx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Vx = SrcInputData%Vx +ENDIF +IF (ALLOCATED(SrcInputData%Vy)) THEN + i1_l = LBOUND(SrcInputData%Vy,1) + i1_u = UBOUND(SrcInputData%Vy,1) + i2_l = LBOUND(SrcInputData%Vy,2) + i2_u = UBOUND(SrcInputData%Vy,2) + IF (.NOT. ALLOCATED(DstInputData%Vy)) THEN + ALLOCATE(DstInputData%Vy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Vy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Vy = SrcInputData%Vy +ENDIF +IF (ALLOCATED(SrcInputData%Vx_elast_dot)) THEN + i1_l = LBOUND(SrcInputData%Vx_elast_dot,1) + i1_u = UBOUND(SrcInputData%Vx_elast_dot,1) + i2_l = LBOUND(SrcInputData%Vx_elast_dot,2) + i2_u = UBOUND(SrcInputData%Vx_elast_dot,2) + IF (.NOT. ALLOCATED(DstInputData%Vx_elast_dot)) THEN + ALLOCATE(DstInputData%Vx_elast_dot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Vx_elast_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Vx_elast_dot = SrcInputData%Vx_elast_dot +ENDIF +IF (ALLOCATED(SrcInputData%Vy_elast_dot)) THEN + i1_l = LBOUND(SrcInputData%Vy_elast_dot,1) + i1_u = UBOUND(SrcInputData%Vy_elast_dot,1) + i2_l = LBOUND(SrcInputData%Vy_elast_dot,2) + i2_u = UBOUND(SrcInputData%Vy_elast_dot,2) + IF (.NOT. ALLOCATED(DstInputData%Vy_elast_dot)) THEN + ALLOCATE(DstInputData%Vy_elast_dot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Vy_elast_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Vy_elast_dot = SrcInputData%Vy_elast_dot +ENDIF +IF (ALLOCATED(SrcInputData%omega_z)) THEN + i1_l = LBOUND(SrcInputData%omega_z,1) + i1_u = UBOUND(SrcInputData%omega_z,1) + i2_l = LBOUND(SrcInputData%omega_z,2) + i2_u = UBOUND(SrcInputData%omega_z,2) + IF (.NOT. ALLOCATED(DstInputData%omega_z)) THEN + ALLOCATE(DstInputData%omega_z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%omega_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%omega_z = SrcInputData%omega_z +ENDIF +IF (ALLOCATED(SrcInputData%rLocal)) THEN + i1_l = LBOUND(SrcInputData%rLocal,1) + i1_u = UBOUND(SrcInputData%rLocal,1) + i2_l = LBOUND(SrcInputData%rLocal,2) + i2_u = UBOUND(SrcInputData%rLocal,2) + IF (.NOT. ALLOCATED(DstInputData%rLocal)) THEN + ALLOCATE(DstInputData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%rLocal = SrcInputData%rLocal +ENDIF + DstInputData%Un_disk = SrcInputData%Un_disk +IF (ALLOCATED(SrcInputData%UserProp)) THEN + i1_l = LBOUND(SrcInputData%UserProp,1) + i1_u = UBOUND(SrcInputData%UserProp,1) + i2_l = LBOUND(SrcInputData%UserProp,2) + i2_u = UBOUND(SrcInputData%UserProp,2) + IF (.NOT. ALLOCATED(DstInputData%UserProp)) THEN + ALLOCATE(DstInputData%UserProp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%UserProp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%UserProp = SrcInputData%UserProp +ENDIF + END SUBROUTINE BEMT_CopyInput + + SUBROUTINE BEMT_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(BEMT_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%theta)) THEN + DEALLOCATE(InputData%theta) +ENDIF +IF (ALLOCATED(InputData%psi)) THEN + DEALLOCATE(InputData%psi) +ENDIF +IF (ALLOCATED(InputData%Vx)) THEN + DEALLOCATE(InputData%Vx) +ENDIF +IF (ALLOCATED(InputData%Vy)) THEN + DEALLOCATE(InputData%Vy) +ENDIF +IF (ALLOCATED(InputData%Vx_elast_dot)) THEN + DEALLOCATE(InputData%Vx_elast_dot) +ENDIF +IF (ALLOCATED(InputData%Vy_elast_dot)) THEN + DEALLOCATE(InputData%Vy_elast_dot) +ENDIF +IF (ALLOCATED(InputData%omega_z)) THEN + DEALLOCATE(InputData%omega_z) +ENDIF +IF (ALLOCATED(InputData%rLocal)) THEN + DEALLOCATE(InputData%rLocal) +ENDIF +IF (ALLOCATED(InputData%UserProp)) THEN + DEALLOCATE(InputData%UserProp) +ENDIF + END SUBROUTINE BEMT_DestroyInput + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 ! theta allocated yes/no + IF ( ALLOCATED(InData%theta) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! theta upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%theta) ! theta + END IF + Re_BufSz = Re_BufSz + 1 ! chi0 + Int_BufSz = Int_BufSz + 1 ! psi allocated yes/no + IF ( ALLOCATED(InData%psi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! psi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%psi) ! psi + END IF + Re_BufSz = Re_BufSz + 1 ! omega + Re_BufSz = Re_BufSz + 1 ! TSR + Int_BufSz = Int_BufSz + 1 ! Vx allocated yes/no + IF ( ALLOCATED(InData%Vx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vx) ! Vx + END IF + Int_BufSz = Int_BufSz + 1 ! Vy allocated yes/no + IF ( ALLOCATED(InData%Vy) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vy upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vy) ! Vy + END IF + Int_BufSz = Int_BufSz + 1 ! Vx_elast_dot allocated yes/no + IF ( ALLOCATED(InData%Vx_elast_dot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vx_elast_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vx_elast_dot) ! Vx_elast_dot + END IF + Int_BufSz = Int_BufSz + 1 ! Vy_elast_dot allocated yes/no + IF ( ALLOCATED(InData%Vy_elast_dot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vy_elast_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vy_elast_dot) ! Vy_elast_dot + END IF + Int_BufSz = Int_BufSz + 1 ! omega_z allocated yes/no + IF ( ALLOCATED(InData%omega_z) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! omega_z upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%omega_z) ! omega_z + END IF + Int_BufSz = Int_BufSz + 1 ! rLocal allocated yes/no + IF ( ALLOCATED(InData%rLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rLocal) ! rLocal + END IF + Re_BufSz = Re_BufSz + 1 ! Un_disk + Int_BufSz = Int_BufSz + 1 ! UserProp allocated yes/no + IF ( ALLOCATED(InData%UserProp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! UserProp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UserProp) ! UserProp + 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%theta) ) 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%theta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%theta,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%theta,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%theta,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%theta,2), UBOUND(InData%theta,2) + DO i1 = LBOUND(InData%theta,1), UBOUND(InData%theta,1) + ReKiBuf(Re_Xferred) = InData%theta(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%chi0 + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%psi) ) 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%psi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%psi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%psi,1), UBOUND(InData%psi,1) + ReKiBuf(Re_Xferred) = InData%psi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%omega + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TSR + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Vx) ) 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%Vx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vx,2), UBOUND(InData%Vx,2) + DO i1 = LBOUND(InData%Vx,1), UBOUND(InData%Vx,1) + ReKiBuf(Re_Xferred) = InData%Vx(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vy) ) 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%Vy,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vy,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vy,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vy,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vy,2), UBOUND(InData%Vy,2) + DO i1 = LBOUND(InData%Vy,1), UBOUND(InData%Vy,1) + ReKiBuf(Re_Xferred) = InData%Vy(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vx_elast_dot) ) 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%Vx_elast_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vx_elast_dot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vx_elast_dot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vx_elast_dot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vx_elast_dot,2), UBOUND(InData%Vx_elast_dot,2) + DO i1 = LBOUND(InData%Vx_elast_dot,1), UBOUND(InData%Vx_elast_dot,1) + ReKiBuf(Re_Xferred) = InData%Vx_elast_dot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vy_elast_dot) ) 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%Vy_elast_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vy_elast_dot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vy_elast_dot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vy_elast_dot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vy_elast_dot,2), UBOUND(InData%Vy_elast_dot,2) + DO i1 = LBOUND(InData%Vy_elast_dot,1), UBOUND(InData%Vy_elast_dot,1) + ReKiBuf(Re_Xferred) = InData%Vy_elast_dot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%omega_z) ) 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%omega_z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%omega_z,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%omega_z,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%omega_z,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%omega_z,2), UBOUND(InData%omega_z,2) + DO i1 = LBOUND(InData%omega_z,1), UBOUND(InData%omega_z,1) + ReKiBuf(Re_Xferred) = InData%omega_z(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rLocal) ) 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%rLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rLocal,2), UBOUND(InData%rLocal,2) + DO i1 = LBOUND(InData%rLocal,1), UBOUND(InData%rLocal,1) + ReKiBuf(Re_Xferred) = InData%rLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Un_disk + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%UserProp) ) 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%UserProp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UserProp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UserProp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UserProp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%UserProp,2), UBOUND(InData%UserProp,2) + DO i1 = LBOUND(InData%UserProp,1), UBOUND(InData%UserProp,1) + ReKiBuf(Re_Xferred) = InData%UserProp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_PackInput + + SUBROUTINE BEMT_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(BEMT_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 = 'BEMT_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 ! theta 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%theta)) DEALLOCATE(OutData%theta) + ALLOCATE(OutData%theta(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%theta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%theta,2), UBOUND(OutData%theta,2) + DO i1 = LBOUND(OutData%theta,1), UBOUND(OutData%theta,1) + OutData%theta(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%chi0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! psi 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%psi)) DEALLOCATE(OutData%psi) + ALLOCATE(OutData%psi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%psi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%psi,1), UBOUND(OutData%psi,1) + OutData%psi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%omega = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TSR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vx 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%Vx)) DEALLOCATE(OutData%Vx) + ALLOCATE(OutData%Vx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vx,2), UBOUND(OutData%Vx,2) + DO i1 = LBOUND(OutData%Vx,1), UBOUND(OutData%Vx,1) + OutData%Vx(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vy 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%Vy)) DEALLOCATE(OutData%Vy) + ALLOCATE(OutData%Vy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vy,2), UBOUND(OutData%Vy,2) + DO i1 = LBOUND(OutData%Vy,1), UBOUND(OutData%Vy,1) + OutData%Vy(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vx_elast_dot 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%Vx_elast_dot)) DEALLOCATE(OutData%Vx_elast_dot) + ALLOCATE(OutData%Vx_elast_dot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vx_elast_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vx_elast_dot,2), UBOUND(OutData%Vx_elast_dot,2) + DO i1 = LBOUND(OutData%Vx_elast_dot,1), UBOUND(OutData%Vx_elast_dot,1) + OutData%Vx_elast_dot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vy_elast_dot 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%Vy_elast_dot)) DEALLOCATE(OutData%Vy_elast_dot) + ALLOCATE(OutData%Vy_elast_dot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vy_elast_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vy_elast_dot,2), UBOUND(OutData%Vy_elast_dot,2) + DO i1 = LBOUND(OutData%Vy_elast_dot,1), UBOUND(OutData%Vy_elast_dot,1) + OutData%Vy_elast_dot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! omega_z 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%omega_z)) DEALLOCATE(OutData%omega_z) + ALLOCATE(OutData%omega_z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%omega_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%omega_z,2), UBOUND(OutData%omega_z,2) + DO i1 = LBOUND(OutData%omega_z,1), UBOUND(OutData%omega_z,1) + OutData%omega_z(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rLocal 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%rLocal)) DEALLOCATE(OutData%rLocal) + ALLOCATE(OutData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rLocal,2), UBOUND(OutData%rLocal,2) + DO i1 = LBOUND(OutData%rLocal,1), UBOUND(OutData%rLocal,1) + OutData%rLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%Un_disk = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UserProp 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%UserProp)) DEALLOCATE(OutData%UserProp) + ALLOCATE(OutData%UserProp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UserProp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%UserProp,2), UBOUND(OutData%UserProp,2) + DO i1 = LBOUND(OutData%UserProp,1), UBOUND(OutData%UserProp,1) + OutData%UserProp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_UnPackInput + + SUBROUTINE BEMT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BEMT_OutputType), INTENT(IN) :: SrcOutputData + TYPE(BEMT_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'BEMT_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%Vrel)) THEN + i1_l = LBOUND(SrcOutputData%Vrel,1) + i1_u = UBOUND(SrcOutputData%Vrel,1) + i2_l = LBOUND(SrcOutputData%Vrel,2) + i2_u = UBOUND(SrcOutputData%Vrel,2) + IF (.NOT. ALLOCATED(DstOutputData%Vrel)) THEN + ALLOCATE(DstOutputData%Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Vrel = SrcOutputData%Vrel +ENDIF +IF (ALLOCATED(SrcOutputData%phi)) THEN + i1_l = LBOUND(SrcOutputData%phi,1) + i1_u = UBOUND(SrcOutputData%phi,1) + i2_l = LBOUND(SrcOutputData%phi,2) + i2_u = UBOUND(SrcOutputData%phi,2) + IF (.NOT. ALLOCATED(DstOutputData%phi)) THEN + ALLOCATE(DstOutputData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%phi = SrcOutputData%phi +ENDIF +IF (ALLOCATED(SrcOutputData%axInduction)) THEN + i1_l = LBOUND(SrcOutputData%axInduction,1) + i1_u = UBOUND(SrcOutputData%axInduction,1) + i2_l = LBOUND(SrcOutputData%axInduction,2) + i2_u = UBOUND(SrcOutputData%axInduction,2) + IF (.NOT. ALLOCATED(DstOutputData%axInduction)) THEN + ALLOCATE(DstOutputData%axInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%axInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%axInduction = SrcOutputData%axInduction +ENDIF +IF (ALLOCATED(SrcOutputData%tanInduction)) THEN + i1_l = LBOUND(SrcOutputData%tanInduction,1) + i1_u = UBOUND(SrcOutputData%tanInduction,1) + i2_l = LBOUND(SrcOutputData%tanInduction,2) + i2_u = UBOUND(SrcOutputData%tanInduction,2) + IF (.NOT. ALLOCATED(DstOutputData%tanInduction)) THEN + ALLOCATE(DstOutputData%tanInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%tanInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%tanInduction = SrcOutputData%tanInduction +ENDIF +IF (ALLOCATED(SrcOutputData%Re)) THEN + i1_l = LBOUND(SrcOutputData%Re,1) + i1_u = UBOUND(SrcOutputData%Re,1) + i2_l = LBOUND(SrcOutputData%Re,2) + i2_u = UBOUND(SrcOutputData%Re,2) + IF (.NOT. ALLOCATED(DstOutputData%Re)) THEN + ALLOCATE(DstOutputData%Re(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Re.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Re = SrcOutputData%Re +ENDIF +IF (ALLOCATED(SrcOutputData%AOA)) THEN + i1_l = LBOUND(SrcOutputData%AOA,1) + i1_u = UBOUND(SrcOutputData%AOA,1) + i2_l = LBOUND(SrcOutputData%AOA,2) + i2_u = UBOUND(SrcOutputData%AOA,2) + IF (.NOT. ALLOCATED(DstOutputData%AOA)) THEN + ALLOCATE(DstOutputData%AOA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%AOA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%AOA = SrcOutputData%AOA +ENDIF +IF (ALLOCATED(SrcOutputData%Cx)) THEN + i1_l = LBOUND(SrcOutputData%Cx,1) + i1_u = UBOUND(SrcOutputData%Cx,1) + i2_l = LBOUND(SrcOutputData%Cx,2) + i2_u = UBOUND(SrcOutputData%Cx,2) + IF (.NOT. ALLOCATED(DstOutputData%Cx)) THEN + ALLOCATE(DstOutputData%Cx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cx = SrcOutputData%Cx +ENDIF +IF (ALLOCATED(SrcOutputData%Cy)) THEN + i1_l = LBOUND(SrcOutputData%Cy,1) + i1_u = UBOUND(SrcOutputData%Cy,1) + i2_l = LBOUND(SrcOutputData%Cy,2) + i2_u = UBOUND(SrcOutputData%Cy,2) + IF (.NOT. ALLOCATED(DstOutputData%Cy)) THEN + ALLOCATE(DstOutputData%Cy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cy = SrcOutputData%Cy +ENDIF +IF (ALLOCATED(SrcOutputData%Cm)) THEN + i1_l = LBOUND(SrcOutputData%Cm,1) + i1_u = UBOUND(SrcOutputData%Cm,1) + i2_l = LBOUND(SrcOutputData%Cm,2) + i2_u = UBOUND(SrcOutputData%Cm,2) + IF (.NOT. ALLOCATED(DstOutputData%Cm)) THEN + ALLOCATE(DstOutputData%Cm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cm = SrcOutputData%Cm +ENDIF +IF (ALLOCATED(SrcOutputData%Cl)) THEN + i1_l = LBOUND(SrcOutputData%Cl,1) + i1_u = UBOUND(SrcOutputData%Cl,1) + i2_l = LBOUND(SrcOutputData%Cl,2) + i2_u = UBOUND(SrcOutputData%Cl,2) + IF (.NOT. ALLOCATED(DstOutputData%Cl)) THEN + ALLOCATE(DstOutputData%Cl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cl = SrcOutputData%Cl +ENDIF +IF (ALLOCATED(SrcOutputData%Cd)) THEN + i1_l = LBOUND(SrcOutputData%Cd,1) + i1_u = UBOUND(SrcOutputData%Cd,1) + i2_l = LBOUND(SrcOutputData%Cd,2) + i2_u = UBOUND(SrcOutputData%Cd,2) + IF (.NOT. ALLOCATED(DstOutputData%Cd)) THEN + ALLOCATE(DstOutputData%Cd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cd = SrcOutputData%Cd +ENDIF +IF (ALLOCATED(SrcOutputData%chi)) THEN + i1_l = LBOUND(SrcOutputData%chi,1) + i1_u = UBOUND(SrcOutputData%chi,1) + i2_l = LBOUND(SrcOutputData%chi,2) + i2_u = UBOUND(SrcOutputData%chi,2) + IF (.NOT. ALLOCATED(DstOutputData%chi)) THEN + ALLOCATE(DstOutputData%chi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%chi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%chi = SrcOutputData%chi +ENDIF +IF (ALLOCATED(SrcOutputData%Cpmin)) THEN + i1_l = LBOUND(SrcOutputData%Cpmin,1) + i1_u = UBOUND(SrcOutputData%Cpmin,1) + i2_l = LBOUND(SrcOutputData%Cpmin,2) + i2_u = UBOUND(SrcOutputData%Cpmin,2) + IF (.NOT. ALLOCATED(DstOutputData%Cpmin)) THEN + ALLOCATE(DstOutputData%Cpmin(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cpmin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cpmin = SrcOutputData%Cpmin +ENDIF + END SUBROUTINE BEMT_CopyOutput + + SUBROUTINE BEMT_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(BEMT_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%Vrel)) THEN + DEALLOCATE(OutputData%Vrel) +ENDIF +IF (ALLOCATED(OutputData%phi)) THEN + DEALLOCATE(OutputData%phi) +ENDIF +IF (ALLOCATED(OutputData%axInduction)) THEN + DEALLOCATE(OutputData%axInduction) +ENDIF +IF (ALLOCATED(OutputData%tanInduction)) THEN + DEALLOCATE(OutputData%tanInduction) +ENDIF +IF (ALLOCATED(OutputData%Re)) THEN + DEALLOCATE(OutputData%Re) +ENDIF +IF (ALLOCATED(OutputData%AOA)) THEN + DEALLOCATE(OutputData%AOA) +ENDIF +IF (ALLOCATED(OutputData%Cx)) THEN + DEALLOCATE(OutputData%Cx) +ENDIF +IF (ALLOCATED(OutputData%Cy)) THEN + DEALLOCATE(OutputData%Cy) +ENDIF +IF (ALLOCATED(OutputData%Cm)) THEN + DEALLOCATE(OutputData%Cm) +ENDIF +IF (ALLOCATED(OutputData%Cl)) THEN + DEALLOCATE(OutputData%Cl) +ENDIF +IF (ALLOCATED(OutputData%Cd)) THEN + DEALLOCATE(OutputData%Cd) +ENDIF +IF (ALLOCATED(OutputData%chi)) THEN + DEALLOCATE(OutputData%chi) +ENDIF +IF (ALLOCATED(OutputData%Cpmin)) THEN + DEALLOCATE(OutputData%Cpmin) +ENDIF + END SUBROUTINE BEMT_DestroyOutput + + SUBROUTINE BEMT_PackOutput( 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(BEMT_OutputType), 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 = 'BEMT_PackOutput' + ! 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 ! Vrel allocated yes/no + IF ( ALLOCATED(InData%Vrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vrel) ! Vrel + END IF + Int_BufSz = Int_BufSz + 1 ! phi allocated yes/no + IF ( ALLOCATED(InData%phi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! phi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%phi) ! phi + END IF + Int_BufSz = Int_BufSz + 1 ! axInduction allocated yes/no + IF ( ALLOCATED(InData%axInduction) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! axInduction upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%axInduction) ! axInduction + END IF + Int_BufSz = Int_BufSz + 1 ! tanInduction allocated yes/no + IF ( ALLOCATED(InData%tanInduction) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tanInduction upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%tanInduction) ! tanInduction + END IF + Int_BufSz = Int_BufSz + 1 ! Re allocated yes/no + IF ( ALLOCATED(InData%Re) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Re upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Re) ! Re + END IF + Int_BufSz = Int_BufSz + 1 ! AOA allocated yes/no + IF ( ALLOCATED(InData%AOA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AOA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AOA) ! AOA + END IF + Int_BufSz = Int_BufSz + 1 ! Cx allocated yes/no + IF ( ALLOCATED(InData%Cx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cx) ! Cx + END IF + Int_BufSz = Int_BufSz + 1 ! Cy allocated yes/no + IF ( ALLOCATED(InData%Cy) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cy upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cy) ! Cy + END IF + Int_BufSz = Int_BufSz + 1 ! Cm allocated yes/no + IF ( ALLOCATED(InData%Cm) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cm) ! Cm + END IF + Int_BufSz = Int_BufSz + 1 ! Cl allocated yes/no + IF ( ALLOCATED(InData%Cl) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cl upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cl) ! Cl + END IF + Int_BufSz = Int_BufSz + 1 ! Cd allocated yes/no + IF ( ALLOCATED(InData%Cd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cd) ! Cd + END IF + Int_BufSz = Int_BufSz + 1 ! chi allocated yes/no + IF ( ALLOCATED(InData%chi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chi) ! chi + END IF + Int_BufSz = Int_BufSz + 1 ! Cpmin allocated yes/no + IF ( ALLOCATED(InData%Cpmin) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cpmin upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cpmin) ! Cpmin + 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%Vrel) ) 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%Vrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vrel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vrel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vrel,2), UBOUND(InData%Vrel,2) + DO i1 = LBOUND(InData%Vrel,1), UBOUND(InData%Vrel,1) + ReKiBuf(Re_Xferred) = InData%Vrel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%phi) ) 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%phi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%phi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%phi,2), UBOUND(InData%phi,2) + DO i1 = LBOUND(InData%phi,1), UBOUND(InData%phi,1) + ReKiBuf(Re_Xferred) = InData%phi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%axInduction) ) 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%axInduction,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%axInduction,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%axInduction,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%axInduction,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%axInduction,2), UBOUND(InData%axInduction,2) + DO i1 = LBOUND(InData%axInduction,1), UBOUND(InData%axInduction,1) + ReKiBuf(Re_Xferred) = InData%axInduction(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tanInduction) ) 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%tanInduction,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tanInduction,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tanInduction,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tanInduction,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tanInduction,2), UBOUND(InData%tanInduction,2) + DO i1 = LBOUND(InData%tanInduction,1), UBOUND(InData%tanInduction,1) + ReKiBuf(Re_Xferred) = InData%tanInduction(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Re) ) 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%Re,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Re,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Re,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Re,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Re,2), UBOUND(InData%Re,2) + DO i1 = LBOUND(InData%Re,1), UBOUND(InData%Re,1) + ReKiBuf(Re_Xferred) = InData%Re(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AOA) ) 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%AOA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AOA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AOA,2), UBOUND(InData%AOA,2) + DO i1 = LBOUND(InData%AOA,1), UBOUND(InData%AOA,1) + ReKiBuf(Re_Xferred) = InData%AOA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cx) ) 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%Cx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cx,2), UBOUND(InData%Cx,2) + DO i1 = LBOUND(InData%Cx,1), UBOUND(InData%Cx,1) + ReKiBuf(Re_Xferred) = InData%Cx(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cy) ) 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%Cy,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cy,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cy,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cy,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cy,2), UBOUND(InData%Cy,2) + DO i1 = LBOUND(InData%Cy,1), UBOUND(InData%Cy,1) + ReKiBuf(Re_Xferred) = InData%Cy(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cm) ) 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%Cm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cm,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cm,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cm,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cm,2), UBOUND(InData%Cm,2) + DO i1 = LBOUND(InData%Cm,1), UBOUND(InData%Cm,1) + ReKiBuf(Re_Xferred) = InData%Cm(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cl) ) 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%Cl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cl,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cl,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cl,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cl,2), UBOUND(InData%Cl,2) + DO i1 = LBOUND(InData%Cl,1), UBOUND(InData%Cl,1) + ReKiBuf(Re_Xferred) = InData%Cl(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cd) ) 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%Cd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cd,2), UBOUND(InData%Cd,2) + DO i1 = LBOUND(InData%Cd,1), UBOUND(InData%Cd,1) + ReKiBuf(Re_Xferred) = InData%Cd(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%chi) ) 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%chi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chi,2), UBOUND(InData%chi,2) + DO i1 = LBOUND(InData%chi,1), UBOUND(InData%chi,1) + ReKiBuf(Re_Xferred) = InData%chi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cpmin) ) 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%Cpmin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cpmin,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cpmin,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cpmin,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cpmin,2), UBOUND(InData%Cpmin,2) + DO i1 = LBOUND(InData%Cpmin,1), UBOUND(InData%Cpmin,1) + ReKiBuf(Re_Xferred) = InData%Cpmin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_PackOutput + + SUBROUTINE BEMT_UnPackOutput( 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(BEMT_OutputType), 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 = 'BEMT_UnPackOutput' + ! 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 ! Vrel 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%Vrel)) DEALLOCATE(OutData%Vrel) + ALLOCATE(OutData%Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vrel,2), UBOUND(OutData%Vrel,2) + DO i1 = LBOUND(OutData%Vrel,1), UBOUND(OutData%Vrel,1) + OutData%Vrel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! phi 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%phi)) DEALLOCATE(OutData%phi) + ALLOCATE(OutData%phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%phi,2), UBOUND(OutData%phi,2) + DO i1 = LBOUND(OutData%phi,1), UBOUND(OutData%phi,1) + OutData%phi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! axInduction 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%axInduction)) DEALLOCATE(OutData%axInduction) + ALLOCATE(OutData%axInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%axInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%axInduction,2), UBOUND(OutData%axInduction,2) + DO i1 = LBOUND(OutData%axInduction,1), UBOUND(OutData%axInduction,1) + OutData%axInduction(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tanInduction 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%tanInduction)) DEALLOCATE(OutData%tanInduction) + ALLOCATE(OutData%tanInduction(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tanInduction.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tanInduction,2), UBOUND(OutData%tanInduction,2) + DO i1 = LBOUND(OutData%tanInduction,1), UBOUND(OutData%tanInduction,1) + OutData%tanInduction(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Re 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%Re)) DEALLOCATE(OutData%Re) + ALLOCATE(OutData%Re(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Re.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Re,2), UBOUND(OutData%Re,2) + DO i1 = LBOUND(OutData%Re,1), UBOUND(OutData%Re,1) + OutData%Re(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AOA 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%AOA)) DEALLOCATE(OutData%AOA) + ALLOCATE(OutData%AOA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AOA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AOA,2), UBOUND(OutData%AOA,2) + DO i1 = LBOUND(OutData%AOA,1), UBOUND(OutData%AOA,1) + OutData%AOA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cx 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%Cx)) DEALLOCATE(OutData%Cx) + ALLOCATE(OutData%Cx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cx,2), UBOUND(OutData%Cx,2) + DO i1 = LBOUND(OutData%Cx,1), UBOUND(OutData%Cx,1) + OutData%Cx(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cy 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%Cy)) DEALLOCATE(OutData%Cy) + ALLOCATE(OutData%Cy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cy,2), UBOUND(OutData%Cy,2) + DO i1 = LBOUND(OutData%Cy,1), UBOUND(OutData%Cy,1) + OutData%Cy(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cm 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%Cm)) DEALLOCATE(OutData%Cm) + ALLOCATE(OutData%Cm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cm,2), UBOUND(OutData%Cm,2) + DO i1 = LBOUND(OutData%Cm,1), UBOUND(OutData%Cm,1) + OutData%Cm(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cl 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%Cl)) DEALLOCATE(OutData%Cl) + ALLOCATE(OutData%Cl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cl,2), UBOUND(OutData%Cl,2) + DO i1 = LBOUND(OutData%Cl,1), UBOUND(OutData%Cl,1) + OutData%Cl(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cd 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%Cd)) DEALLOCATE(OutData%Cd) + ALLOCATE(OutData%Cd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cd,2), UBOUND(OutData%Cd,2) + DO i1 = LBOUND(OutData%Cd,1), UBOUND(OutData%Cd,1) + OutData%Cd(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chi 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%chi)) DEALLOCATE(OutData%chi) + ALLOCATE(OutData%chi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chi,2), UBOUND(OutData%chi,2) + DO i1 = LBOUND(OutData%chi,1), UBOUND(OutData%chi,1) + OutData%chi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cpmin 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%Cpmin)) DEALLOCATE(OutData%Cpmin) + ALLOCATE(OutData%Cpmin(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cpmin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cpmin,2), UBOUND(OutData%Cpmin,2) + DO i1 = LBOUND(OutData%Cpmin,1), UBOUND(OutData%Cpmin,1) + OutData%Cpmin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BEMT_UnPackOutput + + + SUBROUTINE BEMT_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(BEMT_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(BEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL BEMT_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL BEMT_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL BEMT_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE BEMT_Input_ExtrapInterp + + + SUBROUTINE BEMT_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(BEMT_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(BEMT_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(BEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%theta) .AND. ALLOCATED(u1%theta)) THEN + DO i2 = LBOUND(u_out%theta,2),UBOUND(u_out%theta,2) + DO i1 = LBOUND(u_out%theta,1),UBOUND(u_out%theta,1) + b = -(u1%theta(i1,i2) - u2%theta(i1,i2)) + u_out%theta(i1,i2) = u1%theta(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + b = -(u1%chi0 - u2%chi0) + u_out%chi0 = u1%chi0 + b * ScaleFactor +IF (ALLOCATED(u_out%psi) .AND. ALLOCATED(u1%psi)) THEN + DO i1 = LBOUND(u_out%psi,1),UBOUND(u_out%psi,1) + b = -(u1%psi(i1) - u2%psi(i1)) + u_out%psi(i1) = u1%psi(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + b = -(u1%omega - u2%omega) + u_out%omega = u1%omega + b * ScaleFactor + b = -(u1%TSR - u2%TSR) + u_out%TSR = u1%TSR + b * ScaleFactor +IF (ALLOCATED(u_out%Vx) .AND. ALLOCATED(u1%Vx)) THEN + DO i2 = LBOUND(u_out%Vx,2),UBOUND(u_out%Vx,2) + DO i1 = LBOUND(u_out%Vx,1),UBOUND(u_out%Vx,1) + b = -(u1%Vx(i1,i2) - u2%Vx(i1,i2)) + u_out%Vx(i1,i2) = u1%Vx(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vy) .AND. ALLOCATED(u1%Vy)) THEN + DO i2 = LBOUND(u_out%Vy,2),UBOUND(u_out%Vy,2) + DO i1 = LBOUND(u_out%Vy,1),UBOUND(u_out%Vy,1) + b = -(u1%Vy(i1,i2) - u2%Vy(i1,i2)) + u_out%Vy(i1,i2) = u1%Vy(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vx_elast_dot) .AND. ALLOCATED(u1%Vx_elast_dot)) THEN + DO i2 = LBOUND(u_out%Vx_elast_dot,2),UBOUND(u_out%Vx_elast_dot,2) + DO i1 = LBOUND(u_out%Vx_elast_dot,1),UBOUND(u_out%Vx_elast_dot,1) + b = -(u1%Vx_elast_dot(i1,i2) - u2%Vx_elast_dot(i1,i2)) + u_out%Vx_elast_dot(i1,i2) = u1%Vx_elast_dot(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vy_elast_dot) .AND. ALLOCATED(u1%Vy_elast_dot)) THEN + DO i2 = LBOUND(u_out%Vy_elast_dot,2),UBOUND(u_out%Vy_elast_dot,2) + DO i1 = LBOUND(u_out%Vy_elast_dot,1),UBOUND(u_out%Vy_elast_dot,1) + b = -(u1%Vy_elast_dot(i1,i2) - u2%Vy_elast_dot(i1,i2)) + u_out%Vy_elast_dot(i1,i2) = u1%Vy_elast_dot(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%omega_z) .AND. ALLOCATED(u1%omega_z)) THEN + DO i2 = LBOUND(u_out%omega_z,2),UBOUND(u_out%omega_z,2) + DO i1 = LBOUND(u_out%omega_z,1),UBOUND(u_out%omega_z,1) + b = -(u1%omega_z(i1,i2) - u2%omega_z(i1,i2)) + u_out%omega_z(i1,i2) = u1%omega_z(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%rLocal) .AND. ALLOCATED(u1%rLocal)) THEN + DO i2 = LBOUND(u_out%rLocal,2),UBOUND(u_out%rLocal,2) + DO i1 = LBOUND(u_out%rLocal,1),UBOUND(u_out%rLocal,1) + b = -(u1%rLocal(i1,i2) - u2%rLocal(i1,i2)) + u_out%rLocal(i1,i2) = u1%rLocal(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + b = -(u1%Un_disk - u2%Un_disk) + u_out%Un_disk = u1%Un_disk + b * ScaleFactor +IF (ALLOCATED(u_out%UserProp) .AND. ALLOCATED(u1%UserProp)) THEN + DO i2 = LBOUND(u_out%UserProp,2),UBOUND(u_out%UserProp,2) + DO i1 = LBOUND(u_out%UserProp,1),UBOUND(u_out%UserProp,1) + b = -(u1%UserProp(i1,i2) - u2%UserProp(i1,i2)) + u_out%UserProp(i1,i2) = u1%UserProp(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + END SUBROUTINE BEMT_Input_ExtrapInterp1 + + + SUBROUTINE BEMT_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(BEMT_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(BEMT_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(BEMT_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(BEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%theta) .AND. ALLOCATED(u1%theta)) THEN + DO i2 = LBOUND(u_out%theta,2),UBOUND(u_out%theta,2) + DO i1 = LBOUND(u_out%theta,1),UBOUND(u_out%theta,1) + b = (t(3)**2*(u1%theta(i1,i2) - u2%theta(i1,i2)) + t(2)**2*(-u1%theta(i1,i2) + u3%theta(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%theta(i1,i2) + t(3)*u2%theta(i1,i2) - t(2)*u3%theta(i1,i2) ) * scaleFactor + u_out%theta(i1,i2) = u1%theta(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + b = (t(3)**2*(u1%chi0 - u2%chi0) + t(2)**2*(-u1%chi0 + u3%chi0))* scaleFactor + c = ( (t(2)-t(3))*u1%chi0 + t(3)*u2%chi0 - t(2)*u3%chi0 ) * scaleFactor + u_out%chi0 = u1%chi0 + b + c * t_out +IF (ALLOCATED(u_out%psi) .AND. ALLOCATED(u1%psi)) THEN + DO i1 = LBOUND(u_out%psi,1),UBOUND(u_out%psi,1) + b = (t(3)**2*(u1%psi(i1) - u2%psi(i1)) + t(2)**2*(-u1%psi(i1) + u3%psi(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%psi(i1) + t(3)*u2%psi(i1) - t(2)*u3%psi(i1) ) * scaleFactor + u_out%psi(i1) = u1%psi(i1) + b + c * t_out + END DO +END IF ! check if allocated + b = (t(3)**2*(u1%omega - u2%omega) + t(2)**2*(-u1%omega + u3%omega))* scaleFactor + c = ( (t(2)-t(3))*u1%omega + t(3)*u2%omega - t(2)*u3%omega ) * scaleFactor + u_out%omega = u1%omega + b + c * t_out + b = (t(3)**2*(u1%TSR - u2%TSR) + t(2)**2*(-u1%TSR + u3%TSR))* scaleFactor + c = ( (t(2)-t(3))*u1%TSR + t(3)*u2%TSR - t(2)*u3%TSR ) * scaleFactor + u_out%TSR = u1%TSR + b + c * t_out +IF (ALLOCATED(u_out%Vx) .AND. ALLOCATED(u1%Vx)) THEN + DO i2 = LBOUND(u_out%Vx,2),UBOUND(u_out%Vx,2) + DO i1 = LBOUND(u_out%Vx,1),UBOUND(u_out%Vx,1) + b = (t(3)**2*(u1%Vx(i1,i2) - u2%Vx(i1,i2)) + t(2)**2*(-u1%Vx(i1,i2) + u3%Vx(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Vx(i1,i2) + t(3)*u2%Vx(i1,i2) - t(2)*u3%Vx(i1,i2) ) * scaleFactor + u_out%Vx(i1,i2) = u1%Vx(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vy) .AND. ALLOCATED(u1%Vy)) THEN + DO i2 = LBOUND(u_out%Vy,2),UBOUND(u_out%Vy,2) + DO i1 = LBOUND(u_out%Vy,1),UBOUND(u_out%Vy,1) + b = (t(3)**2*(u1%Vy(i1,i2) - u2%Vy(i1,i2)) + t(2)**2*(-u1%Vy(i1,i2) + u3%Vy(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Vy(i1,i2) + t(3)*u2%Vy(i1,i2) - t(2)*u3%Vy(i1,i2) ) * scaleFactor + u_out%Vy(i1,i2) = u1%Vy(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vx_elast_dot) .AND. ALLOCATED(u1%Vx_elast_dot)) THEN + DO i2 = LBOUND(u_out%Vx_elast_dot,2),UBOUND(u_out%Vx_elast_dot,2) + DO i1 = LBOUND(u_out%Vx_elast_dot,1),UBOUND(u_out%Vx_elast_dot,1) + b = (t(3)**2*(u1%Vx_elast_dot(i1,i2) - u2%Vx_elast_dot(i1,i2)) + t(2)**2*(-u1%Vx_elast_dot(i1,i2) + u3%Vx_elast_dot(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Vx_elast_dot(i1,i2) + t(3)*u2%Vx_elast_dot(i1,i2) - t(2)*u3%Vx_elast_dot(i1,i2) ) * scaleFactor + u_out%Vx_elast_dot(i1,i2) = u1%Vx_elast_dot(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Vy_elast_dot) .AND. ALLOCATED(u1%Vy_elast_dot)) THEN + DO i2 = LBOUND(u_out%Vy_elast_dot,2),UBOUND(u_out%Vy_elast_dot,2) + DO i1 = LBOUND(u_out%Vy_elast_dot,1),UBOUND(u_out%Vy_elast_dot,1) + b = (t(3)**2*(u1%Vy_elast_dot(i1,i2) - u2%Vy_elast_dot(i1,i2)) + t(2)**2*(-u1%Vy_elast_dot(i1,i2) + u3%Vy_elast_dot(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Vy_elast_dot(i1,i2) + t(3)*u2%Vy_elast_dot(i1,i2) - t(2)*u3%Vy_elast_dot(i1,i2) ) * scaleFactor + u_out%Vy_elast_dot(i1,i2) = u1%Vy_elast_dot(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%omega_z) .AND. ALLOCATED(u1%omega_z)) THEN + DO i2 = LBOUND(u_out%omega_z,2),UBOUND(u_out%omega_z,2) + DO i1 = LBOUND(u_out%omega_z,1),UBOUND(u_out%omega_z,1) + b = (t(3)**2*(u1%omega_z(i1,i2) - u2%omega_z(i1,i2)) + t(2)**2*(-u1%omega_z(i1,i2) + u3%omega_z(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%omega_z(i1,i2) + t(3)*u2%omega_z(i1,i2) - t(2)*u3%omega_z(i1,i2) ) * scaleFactor + u_out%omega_z(i1,i2) = u1%omega_z(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%rLocal) .AND. ALLOCATED(u1%rLocal)) THEN + DO i2 = LBOUND(u_out%rLocal,2),UBOUND(u_out%rLocal,2) + DO i1 = LBOUND(u_out%rLocal,1),UBOUND(u_out%rLocal,1) + b = (t(3)**2*(u1%rLocal(i1,i2) - u2%rLocal(i1,i2)) + t(2)**2*(-u1%rLocal(i1,i2) + u3%rLocal(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%rLocal(i1,i2) + t(3)*u2%rLocal(i1,i2) - t(2)*u3%rLocal(i1,i2) ) * scaleFactor + u_out%rLocal(i1,i2) = u1%rLocal(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + b = (t(3)**2*(u1%Un_disk - u2%Un_disk) + t(2)**2*(-u1%Un_disk + u3%Un_disk))* scaleFactor + c = ( (t(2)-t(3))*u1%Un_disk + t(3)*u2%Un_disk - t(2)*u3%Un_disk ) * scaleFactor + u_out%Un_disk = u1%Un_disk + b + c * t_out +IF (ALLOCATED(u_out%UserProp) .AND. ALLOCATED(u1%UserProp)) THEN + DO i2 = LBOUND(u_out%UserProp,2),UBOUND(u_out%UserProp,2) + DO i1 = LBOUND(u_out%UserProp,1),UBOUND(u_out%UserProp,1) + b = (t(3)**2*(u1%UserProp(i1,i2) - u2%UserProp(i1,i2)) + t(2)**2*(-u1%UserProp(i1,i2) + u3%UserProp(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%UserProp(i1,i2) + t(3)*u2%UserProp(i1,i2) - t(2)*u3%UserProp(i1,i2) ) * scaleFactor + u_out%UserProp(i1,i2) = u1%UserProp(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + END SUBROUTINE BEMT_Input_ExtrapInterp2 + + + SUBROUTINE BEMT_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(BEMT_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(BEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL BEMT_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL BEMT_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL BEMT_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE BEMT_Output_ExtrapInterp + + + SUBROUTINE BEMT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(BEMT_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(BEMT_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(BEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%Vrel) .AND. ALLOCATED(y1%Vrel)) THEN + DO i2 = LBOUND(y_out%Vrel,2),UBOUND(y_out%Vrel,2) + DO i1 = LBOUND(y_out%Vrel,1),UBOUND(y_out%Vrel,1) + b = -(y1%Vrel(i1,i2) - y2%Vrel(i1,i2)) + y_out%Vrel(i1,i2) = y1%Vrel(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%phi) .AND. ALLOCATED(y1%phi)) THEN + DO i2 = LBOUND(y_out%phi,2),UBOUND(y_out%phi,2) + DO i1 = LBOUND(y_out%phi,1),UBOUND(y_out%phi,1) + b = -(y1%phi(i1,i2) - y2%phi(i1,i2)) + y_out%phi(i1,i2) = y1%phi(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%axInduction) .AND. ALLOCATED(y1%axInduction)) THEN + DO i2 = LBOUND(y_out%axInduction,2),UBOUND(y_out%axInduction,2) + DO i1 = LBOUND(y_out%axInduction,1),UBOUND(y_out%axInduction,1) + b = -(y1%axInduction(i1,i2) - y2%axInduction(i1,i2)) + y_out%axInduction(i1,i2) = y1%axInduction(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%tanInduction) .AND. ALLOCATED(y1%tanInduction)) THEN + DO i2 = LBOUND(y_out%tanInduction,2),UBOUND(y_out%tanInduction,2) + DO i1 = LBOUND(y_out%tanInduction,1),UBOUND(y_out%tanInduction,1) + b = -(y1%tanInduction(i1,i2) - y2%tanInduction(i1,i2)) + y_out%tanInduction(i1,i2) = y1%tanInduction(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Re) .AND. ALLOCATED(y1%Re)) THEN + DO i2 = LBOUND(y_out%Re,2),UBOUND(y_out%Re,2) + DO i1 = LBOUND(y_out%Re,1),UBOUND(y_out%Re,1) + b = -(y1%Re(i1,i2) - y2%Re(i1,i2)) + y_out%Re(i1,i2) = y1%Re(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%AOA) .AND. ALLOCATED(y1%AOA)) THEN + DO i2 = LBOUND(y_out%AOA,2),UBOUND(y_out%AOA,2) + DO i1 = LBOUND(y_out%AOA,1),UBOUND(y_out%AOA,1) + b = -(y1%AOA(i1,i2) - y2%AOA(i1,i2)) + y_out%AOA(i1,i2) = y1%AOA(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cx) .AND. ALLOCATED(y1%Cx)) THEN + DO i2 = LBOUND(y_out%Cx,2),UBOUND(y_out%Cx,2) + DO i1 = LBOUND(y_out%Cx,1),UBOUND(y_out%Cx,1) + b = -(y1%Cx(i1,i2) - y2%Cx(i1,i2)) + y_out%Cx(i1,i2) = y1%Cx(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cy) .AND. ALLOCATED(y1%Cy)) THEN + DO i2 = LBOUND(y_out%Cy,2),UBOUND(y_out%Cy,2) + DO i1 = LBOUND(y_out%Cy,1),UBOUND(y_out%Cy,1) + b = -(y1%Cy(i1,i2) - y2%Cy(i1,i2)) + y_out%Cy(i1,i2) = y1%Cy(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cm) .AND. ALLOCATED(y1%Cm)) THEN + DO i2 = LBOUND(y_out%Cm,2),UBOUND(y_out%Cm,2) + DO i1 = LBOUND(y_out%Cm,1),UBOUND(y_out%Cm,1) + b = -(y1%Cm(i1,i2) - y2%Cm(i1,i2)) + y_out%Cm(i1,i2) = y1%Cm(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cl) .AND. ALLOCATED(y1%Cl)) THEN + DO i2 = LBOUND(y_out%Cl,2),UBOUND(y_out%Cl,2) + DO i1 = LBOUND(y_out%Cl,1),UBOUND(y_out%Cl,1) + b = -(y1%Cl(i1,i2) - y2%Cl(i1,i2)) + y_out%Cl(i1,i2) = y1%Cl(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cd) .AND. ALLOCATED(y1%Cd)) THEN + DO i2 = LBOUND(y_out%Cd,2),UBOUND(y_out%Cd,2) + DO i1 = LBOUND(y_out%Cd,1),UBOUND(y_out%Cd,1) + b = -(y1%Cd(i1,i2) - y2%Cd(i1,i2)) + y_out%Cd(i1,i2) = y1%Cd(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%chi) .AND. ALLOCATED(y1%chi)) THEN + DO i2 = LBOUND(y_out%chi,2),UBOUND(y_out%chi,2) + DO i1 = LBOUND(y_out%chi,1),UBOUND(y_out%chi,1) + b = -(y1%chi(i1,i2) - y2%chi(i1,i2)) + y_out%chi(i1,i2) = y1%chi(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cpmin) .AND. ALLOCATED(y1%Cpmin)) THEN + DO i2 = LBOUND(y_out%Cpmin,2),UBOUND(y_out%Cpmin,2) + DO i1 = LBOUND(y_out%Cpmin,1),UBOUND(y_out%Cpmin,1) + b = -(y1%Cpmin(i1,i2) - y2%Cpmin(i1,i2)) + y_out%Cpmin(i1,i2) = y1%Cpmin(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + END SUBROUTINE BEMT_Output_ExtrapInterp1 + + + SUBROUTINE BEMT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(BEMT_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(BEMT_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(BEMT_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(BEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BEMT_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%Vrel) .AND. ALLOCATED(y1%Vrel)) THEN + DO i2 = LBOUND(y_out%Vrel,2),UBOUND(y_out%Vrel,2) + DO i1 = LBOUND(y_out%Vrel,1),UBOUND(y_out%Vrel,1) + b = (t(3)**2*(y1%Vrel(i1,i2) - y2%Vrel(i1,i2)) + t(2)**2*(-y1%Vrel(i1,i2) + y3%Vrel(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Vrel(i1,i2) + t(3)*y2%Vrel(i1,i2) - t(2)*y3%Vrel(i1,i2) ) * scaleFactor + y_out%Vrel(i1,i2) = y1%Vrel(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%phi) .AND. ALLOCATED(y1%phi)) THEN + DO i2 = LBOUND(y_out%phi,2),UBOUND(y_out%phi,2) + DO i1 = LBOUND(y_out%phi,1),UBOUND(y_out%phi,1) + b = (t(3)**2*(y1%phi(i1,i2) - y2%phi(i1,i2)) + t(2)**2*(-y1%phi(i1,i2) + y3%phi(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%phi(i1,i2) + t(3)*y2%phi(i1,i2) - t(2)*y3%phi(i1,i2) ) * scaleFactor + y_out%phi(i1,i2) = y1%phi(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%axInduction) .AND. ALLOCATED(y1%axInduction)) THEN + DO i2 = LBOUND(y_out%axInduction,2),UBOUND(y_out%axInduction,2) + DO i1 = LBOUND(y_out%axInduction,1),UBOUND(y_out%axInduction,1) + b = (t(3)**2*(y1%axInduction(i1,i2) - y2%axInduction(i1,i2)) + t(2)**2*(-y1%axInduction(i1,i2) + y3%axInduction(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%axInduction(i1,i2) + t(3)*y2%axInduction(i1,i2) - t(2)*y3%axInduction(i1,i2) ) * scaleFactor + y_out%axInduction(i1,i2) = y1%axInduction(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%tanInduction) .AND. ALLOCATED(y1%tanInduction)) THEN + DO i2 = LBOUND(y_out%tanInduction,2),UBOUND(y_out%tanInduction,2) + DO i1 = LBOUND(y_out%tanInduction,1),UBOUND(y_out%tanInduction,1) + b = (t(3)**2*(y1%tanInduction(i1,i2) - y2%tanInduction(i1,i2)) + t(2)**2*(-y1%tanInduction(i1,i2) + y3%tanInduction(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%tanInduction(i1,i2) + t(3)*y2%tanInduction(i1,i2) - t(2)*y3%tanInduction(i1,i2) ) * scaleFactor + y_out%tanInduction(i1,i2) = y1%tanInduction(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Re) .AND. ALLOCATED(y1%Re)) THEN + DO i2 = LBOUND(y_out%Re,2),UBOUND(y_out%Re,2) + DO i1 = LBOUND(y_out%Re,1),UBOUND(y_out%Re,1) + b = (t(3)**2*(y1%Re(i1,i2) - y2%Re(i1,i2)) + t(2)**2*(-y1%Re(i1,i2) + y3%Re(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Re(i1,i2) + t(3)*y2%Re(i1,i2) - t(2)*y3%Re(i1,i2) ) * scaleFactor + y_out%Re(i1,i2) = y1%Re(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%AOA) .AND. ALLOCATED(y1%AOA)) THEN + DO i2 = LBOUND(y_out%AOA,2),UBOUND(y_out%AOA,2) + DO i1 = LBOUND(y_out%AOA,1),UBOUND(y_out%AOA,1) + b = (t(3)**2*(y1%AOA(i1,i2) - y2%AOA(i1,i2)) + t(2)**2*(-y1%AOA(i1,i2) + y3%AOA(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%AOA(i1,i2) + t(3)*y2%AOA(i1,i2) - t(2)*y3%AOA(i1,i2) ) * scaleFactor + y_out%AOA(i1,i2) = y1%AOA(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cx) .AND. ALLOCATED(y1%Cx)) THEN + DO i2 = LBOUND(y_out%Cx,2),UBOUND(y_out%Cx,2) + DO i1 = LBOUND(y_out%Cx,1),UBOUND(y_out%Cx,1) + b = (t(3)**2*(y1%Cx(i1,i2) - y2%Cx(i1,i2)) + t(2)**2*(-y1%Cx(i1,i2) + y3%Cx(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cx(i1,i2) + t(3)*y2%Cx(i1,i2) - t(2)*y3%Cx(i1,i2) ) * scaleFactor + y_out%Cx(i1,i2) = y1%Cx(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cy) .AND. ALLOCATED(y1%Cy)) THEN + DO i2 = LBOUND(y_out%Cy,2),UBOUND(y_out%Cy,2) + DO i1 = LBOUND(y_out%Cy,1),UBOUND(y_out%Cy,1) + b = (t(3)**2*(y1%Cy(i1,i2) - y2%Cy(i1,i2)) + t(2)**2*(-y1%Cy(i1,i2) + y3%Cy(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cy(i1,i2) + t(3)*y2%Cy(i1,i2) - t(2)*y3%Cy(i1,i2) ) * scaleFactor + y_out%Cy(i1,i2) = y1%Cy(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cm) .AND. ALLOCATED(y1%Cm)) THEN + DO i2 = LBOUND(y_out%Cm,2),UBOUND(y_out%Cm,2) + DO i1 = LBOUND(y_out%Cm,1),UBOUND(y_out%Cm,1) + b = (t(3)**2*(y1%Cm(i1,i2) - y2%Cm(i1,i2)) + t(2)**2*(-y1%Cm(i1,i2) + y3%Cm(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cm(i1,i2) + t(3)*y2%Cm(i1,i2) - t(2)*y3%Cm(i1,i2) ) * scaleFactor + y_out%Cm(i1,i2) = y1%Cm(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cl) .AND. ALLOCATED(y1%Cl)) THEN + DO i2 = LBOUND(y_out%Cl,2),UBOUND(y_out%Cl,2) + DO i1 = LBOUND(y_out%Cl,1),UBOUND(y_out%Cl,1) + b = (t(3)**2*(y1%Cl(i1,i2) - y2%Cl(i1,i2)) + t(2)**2*(-y1%Cl(i1,i2) + y3%Cl(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cl(i1,i2) + t(3)*y2%Cl(i1,i2) - t(2)*y3%Cl(i1,i2) ) * scaleFactor + y_out%Cl(i1,i2) = y1%Cl(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cd) .AND. ALLOCATED(y1%Cd)) THEN + DO i2 = LBOUND(y_out%Cd,2),UBOUND(y_out%Cd,2) + DO i1 = LBOUND(y_out%Cd,1),UBOUND(y_out%Cd,1) + b = (t(3)**2*(y1%Cd(i1,i2) - y2%Cd(i1,i2)) + t(2)**2*(-y1%Cd(i1,i2) + y3%Cd(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cd(i1,i2) + t(3)*y2%Cd(i1,i2) - t(2)*y3%Cd(i1,i2) ) * scaleFactor + y_out%Cd(i1,i2) = y1%Cd(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%chi) .AND. ALLOCATED(y1%chi)) THEN + DO i2 = LBOUND(y_out%chi,2),UBOUND(y_out%chi,2) + DO i1 = LBOUND(y_out%chi,1),UBOUND(y_out%chi,1) + b = (t(3)**2*(y1%chi(i1,i2) - y2%chi(i1,i2)) + t(2)**2*(-y1%chi(i1,i2) + y3%chi(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%chi(i1,i2) + t(3)*y2%chi(i1,i2) - t(2)*y3%chi(i1,i2) ) * scaleFactor + y_out%chi(i1,i2) = y1%chi(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cpmin) .AND. ALLOCATED(y1%Cpmin)) THEN + DO i2 = LBOUND(y_out%Cpmin,2),UBOUND(y_out%Cpmin,2) + DO i1 = LBOUND(y_out%Cpmin,1),UBOUND(y_out%Cpmin,1) + b = (t(3)**2*(y1%Cpmin(i1,i2) - y2%Cpmin(i1,i2)) + t(2)**2*(-y1%Cpmin(i1,i2) + y3%Cpmin(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cpmin(i1,i2) + t(3)*y2%Cpmin(i1,i2) - t(2)*y3%Cpmin(i1,i2) ) * scaleFactor + y_out%Cpmin(i1,i2) = y1%Cpmin(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + END SUBROUTINE BEMT_Output_ExtrapInterp2 + +END MODULE BEMT_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/DBEMT.f90 b/OpenFAST/modules/aerodyn/src/DBEMT.f90 new file mode 100644 index 000000000..e01d33462 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/DBEMT.f90 @@ -0,0 +1,932 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2017 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 DBEMT + + use NWTC_Library + use DBEMT_Types + + implicit none + +private + + + public :: DBEMT_Init + public :: DBEMT_UpdateStates + public :: DBEMT_CalcOutput + public :: DBEMT_End + PUBLIC :: DBEMT_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + + + public :: DBEMT_ReInit + public :: DBEMT_InitStates_AllNodes + + contains + + +subroutine DBEMT_ValidateInitInp(interval, InitInp, errStat, errMsg) + real(DbKi), intent(in ) :: interval !< Coupling interval in seconds + type(DBEMT_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = 'DBEMT_ValidateInitInp' + real(ReKi) :: rlocalMax + integer(IntKi) :: i,j + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + if ( interval <= sqrt(epsilon(1.0_ReKi)) ) call SetErrStat( ErrID_Fatal, " The timestep size for DBEMT (interval) must be larger than sqrt(epsilon).", ErrStat, ErrMsg, RoutineName) + + !>>> remove after this feature gets tested better: + if (InitInp%DBEMT_Mod == DBEMT_cont_tauConst ) then + call SetErrStat( ErrID_Fatal, "DBEMT_Mod cannot be 3 in this version of OpenFAST.", ErrStat, ErrMsg, RoutineName ) + return + end if + !<<< + + if ( (InitInp%DBEMT_Mod .ne. DBEMT_tauConst) .and. (InitInp%DBEMT_Mod .ne. DBEMT_tauVaries) .and. (InitInp%DBEMT_Mod .ne. DBEMT_cont_tauConst)) then + call SetErrStat( ErrID_Fatal, " DBEMT_Mod must be set to 1, 2, or 3.", ErrStat, ErrMsg, RoutineName) + end if + + if (InitInp%numBlades < 1) call SetErrStat( ErrID_Fatal, " InitInp%numBlades must set to 1 or more.", ErrStat, ErrMsg, RoutineName) + if (InitInp%numNodes < 2) call SetErrStat( ErrID_Fatal, " InitInp%numNodes must set to 2 or more.", ErrStat, ErrMsg, RoutineName) + + + if ( InitInp%DBEMT_Mod == DBEMT_tauConst .or. InitInp%DBEMT_Mod == DBEMT_cont_tauConst ) then + + if (InitInp%tau1_const <= 0.0_ReKi) call SetErrStat( ErrID_Fatal, " InitInp%tau1_const must be greater than zero.", ErrStat, ErrMsg, RoutineName) + ! Default = 0.33_ReKi + + if (.not. allocated(InitInp%rlocal) ) then + call SetErrStat( ErrID_Fatal, " InitInput%rlocal must be allocated to size (InitInp%numNodes,InitInp%numBlades).", ErrStat, ErrMsg, RoutineName) + return + end if + + do j = 1,InitInp%numBlades + rlocalMax = 0.0_ReKi + do i= 1,InitInp%numNodes + if (InitInp%rlocal(i,j) <= 0.0_ReKi ) then + call SetErrStat( ErrID_Fatal, " Blades nodes must be located at a positive radial distance (rlocal) greater than zero.", ErrStat, ErrMsg, RoutineName) + return + end if + + rlocalMax = max(rlocalMax,InitInp%rlocal(i,j)) + end do + if ( EqualRealNos(rlocalMax, 0.0_ReKi) ) call SetErrStat( ErrID_Fatal, " Blades must have nodes located at a radial distance (rlocal) greater than zero. ", ErrStat, ErrMsg, RoutineName) + end do + + end if + +end subroutine DBEMT_ValidateInitInp + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +subroutine DBEMT_Init( InitInp, u, p, x, OtherState, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + type(DBEMT_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType), intent( out) :: p !< Parameters + type(DBEMT_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(DBEMT_OtherStateType), intent( out) :: OtherState !< Initial other/logical states + type(DBEMT_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + real(DbKi), intent(in ) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType), intent( out) :: InitOut !< Output for initialization routine + 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,j ! loop counter + real(ReKi) :: rTip ! Maximum tip radius for all blades + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_Init' + + + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + ! initialize InitOut to avoid compiler warnings + InitOut%Ver = ProgDesc( 'DBEMT', '', '' ) + + + !if (p%DBEMT_Mod == DBEMT_none) return ! DBEMT is turned off. + + ! Validate the Initialization inputs + call DBEMT_ValidateInitInp(interval, InitInp, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, ErrStat, ErrMsg, RoutineName) + if (errStat >= AbortErrLev) return + + ! Set parameter data using the initialization inputs + + p%DBEMT_Mod = InitInp%DBEMT_Mod + + + p%dt = interval + p%numBlades = InitInp%numBlades + p%numNodes = InitInp%numNodes + p%k_0ye = 0.6_ReKi + !>>>>> bjj: these are unused: + !p%c5 = 1.1_ReKi + !p%c6 = 1.0_ReKi + !p%c7 = 1.3_ReKi + !p%c8 = 0.39_ReKi + !p%c9 = 0.26_ReKi + !<<<<<< + p%tau1_const = InitInp%tau1_const ! Default = 0.33_ReKi + + allocate(u%element(p%numNodes, p%numBlades), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating u%element.", ErrStat, ErrMsg, RoutineName) + return + end if + + if (p%DBEMT_Mod == DBEMT_tauConst .or. p%DBEMT_Mod == DBEMT_cont_tauConst) then + ! DBEMT_Mod = 1 and 3 use constant tau1 and tau2 + allocate( p%spanRatio(p%numNodes, p%numBlades), STAT=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating p%spanRatio. ", ErrStat, ErrMsg, RoutineName) + return + end if + ! compute the largest tip radius of all blades + rTip = 0.0_ReKi + do j = 1,p%numBlades + do i= 1,p%numNodes + rTip = max(rTip, InitInp%rlocal(i,j)) + end do + end do + + do j = 1,p%numBlades + do i= 1,p%numNodes + p%spanRatio(i,j) = InitInp%rlocal(i,j)/rTip ! normalized radial distance from center of rotation to node + end do + end do + end if + + ! Initialize the continuous states + allocate( x%element(p%numNodes, p%numBlades), STAT=ErrStat2) ! This is the axial and tangential induced velocity at node i on blade j + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating x%element. ", ErrStat, ErrMsg, RoutineName) + return + end if + + if (p%DBEMT_Mod == DBEMT_cont_tauConst) then + allocate( OtherState%n(p%numNodes, p%numBlades), STAT=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating OtherState%n.", ErrStat, ErrMsg, RoutineName) + return + end if + + do i=1,size(OtherState%xdot) + call DBEMT_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating OtherState%xdot.", ErrStat, ErrMsg, RoutineName) + return + end if + end do + + p%lin_nx = p%numNodes*p%numBlades*4 ! vind and vind_dot + else + p%lin_nx = 0 + end if + + allocate( OtherState%areStatesInitialized(p%numNodes, p%numBlades), STAT=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, " Error allocating OtherState%areStatesInitialized. ", ErrStat, ErrMsg, RoutineName) + return + end if + + call DBEMT_ReInit(p, x,OtherState,m) + +end subroutine DBEMT_Init + +!.................................................................................................................................. +subroutine DBEMT_ReInit( p, x, OtherState, m ) + + type(DBEMT_ParameterType), intent(in ) :: p !< parameters + type(DBEMT_ContinuousStateType), intent(inout) :: x !< Initial continuous states + type(DBEMT_OtherStateType), intent(inout) :: OtherState !< Initial other/logical states + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + + integer :: i + integer :: j + integer :: n + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Initialize variables for this routine + + do j=1,size(x%element,2) + do i=1,size(x%element,1) + x%element(i,j)%vind = 0.0_ReKi + x%element(i,j)%vind_dot = 0.0_ReKi + x%element(i,j)%vind_1 = 0.0_ReKi + end do + end do + + OtherState%areStatesInitialized = .false. + + if (p%DBEMT_Mod == DBEMT_tauConst .or. p%DBEMT_Mod == DBEMT_cont_tauConst) then + OtherState%tau1 = p%tau1_const + else + OtherState%tau1 = 0.0_ReKi + end if + + if (allocated(OtherState%n)) then + OtherState%n = -1 + + do n=1,size(OtherState%xdot) + do j=1,size(x%element,2) + do i=1,size(x%element,1) + call DBEMT_CopyElementContinuousStateType( x%element(i,j), OtherState%xdot(n)%element(i,j), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + end do + end do + end do + end if + + m%FirstWarn_tau1 = .true. + +end subroutine DBEMT_ReInit +!!---------------------------------------------------------------------------------------------------------------------------------- +!> routine to initialize the states based on inputs +subroutine DBEMT_InitStates_AllNodes( u, p, x, OtherState ) + type(DBEMT_InputType), intent(in ) :: u !< Inputs at t + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + type(DBEMT_OtherStateType), intent(inout) :: OtherState !< Other/logical states at t on input; at t+dt on output + + integer(IntKi) :: i !< blade node counter + integer(IntKi) :: j !< blade counter + + + do j=1,size(x%element,2) + do i=1,size(x%element,1) + call DBEMT_InitStates( i, j, u, p, x, OtherState ) + end do + end do + +end subroutine DBEMT_InitStates_AllNodes +!!---------------------------------------------------------------------------------------------------------------------------------- +!> routine to initialize the states based on inputs +subroutine DBEMT_InitStates( i, j, u, p, x, OtherState ) + integer(IntKi), intent(in ) :: i !< blade node counter + integer(IntKi), intent(in ) :: j !< blade counter + type(DBEMT_InputType), intent(in ) :: u !< Inputs at t + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + type(DBEMT_OtherStateType), intent(inout) :: OtherState !< Other/logical states at t on input; at t+dt on output + + if ( .not. OtherState%areStatesInitialized(i,j) ) then + x%element(i,j)%vind(1) = u%element(i,j)%vind_s(1) + x%element(i,j)%vind(2) = u%element(i,j)%vind_s(2) + + if (p%DBEMT_Mod == DBEMT_cont_tauConst) then + x%element(i,j)%vind_dot(1) = u%element(i,j)%vind_s_dot(1) + x%element(i,j)%vind_dot(2) = u%element(i,j)%vind_s_dot(2) + else + x%element(i,j)%vind_1(1) = u%element(i,j)%vind_s(1) + x%element(i,j)%vind_1(2) = u%element(i,j)%vind_s(2) + end if + + OtherState%areStatesInitialized(i,j) = .true. + return + end if + +end subroutine DBEMT_InitStates +!!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. +!! Continuous, constraint, discrete, and other states are updated for t + Interval +subroutine DBEMT_UpdateStates( i, j, t, n, u, p, x, OtherState, m, errStat, errMsg ) +!.................................................................................................................................. + integer(IntKi), intent(in ) :: i !< blade node counter + integer(IntKi), intent(in ) :: j !< blade counter + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current simulation time step n = 0,1,... + type(DBEMT_InputType), intent(in ) :: u(2) !< Inputs at t and t+dt + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(DBEMT_OtherStateType), intent(inout) :: OtherState !< Other/logical states at t on input; at t+dt on output + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(ReKi) :: A, B, C0, k_tau, C0_2 ! tau1_plus1, C_tau1, C, K1 + integer(IntKi) :: indx + real(DbKi) :: utimes(2) + + TYPE(DBEMT_ElementInputType) :: u_elem(2) !< Inputs at utimes + + character(*), parameter :: RoutineName = 'DBEMT_UpdateStates' + + ErrStat = ErrID_None + ErrMsg = "" + + !if (p%DBEMT_Mod == DBEMT_none) return ! DBEMT is turned off. + + call ComputeTau1(u(1), p, m, OtherState%tau1, errStat, errMsg) ! place this here for DBEMTau1 output reasons + if (errStat >= AbortErrLev) return + call ComputeTau2(i, j, u(1)%element(i,j), p, OtherState%tau1, OtherState%tau2, k_tau) + + call DBEMT_InitStates( i, j, u(1), p, x, OtherState ) + + if (p%DBEMT_Mod == DBEMT_cont_tauConst) then ! continuous formulation: + utimes(1) = t + utimes(2) = t + p%dt + + u_elem(1) = u(1)%element(i,j) + u_elem(2) = u(2)%element(i,j) + call DBEMT_ABM4( i, j, t, n, u_elem, utimes, p, x, OtherState, m, ErrStat, ErrMsg ) + + else ! finite difference formulation: + + do indx=1,2 !Axial and tangential components. jmj questions if this should be done for tangential induction. + + B = ( u(2)%element(i,j)%vind_s(indx) - u(1)%element(i,j)%vind_s(indx) ) / p%dt ! Eqn. 1.17c ! bjj: note that interpOrder will affect this numerical derivative + A = u(1)%element(i,j)%vind_s(indx) + B*p%k_0ye*OtherState%tau1 ! Eqn. 1.17b + + C0 = x%element(i,j)%vind_1(indx) - A + B*OtherState%tau1 ! Eqn. 1.21b + + x%element(i,j)%vind_1(indx) = C0*exp(-p%dt/OtherState%tau1) + A + B*(p%dt-OtherState%tau1) ! Eqn. 1.21a, but this is using p%dt instead of t + + C0_2 = x%element(i,j)%vind(indx) - C0/(1-k_tau) - A + B*(OtherState%tau1 + OtherState%tau2) ! Eqn. 1.24c + x%element(i,j)%vind(indx) = C0_2*exp(-p%dt/OtherState%tau2) + A + B*(p%dt-OtherState%tau1-OtherState%tau2) & + + (C0/(1-k_tau))*exp(-p%dt/OtherState%tau1) ! Eqn. 1.25 + + + !C = (u(2)%element(i,j)%vind_s(indx) - u(1)%element(i,j)%vind_s(indx))/p%dt ! v_ind_s_future could come from BEMT update states, but this seems to violate the framework !Eqn. 1.27C + !A = u(1)%element(i,j)%vind_s(indx) + C*p%k_0ye*tau1 ! + !B = C*(p%k_0ye*C_tau1+1) + !K1 = (A + A*C_tau1 - B*tau1) / (1+C_tau1) + !C0 = ( x%element(i,j)%vind_1(indx) - K1 )*tau1**(1.0/C_tau1) + !C0_2 = ( x%element(i,j)%vind(indx) - K1 - C0 / ((1-k_tau)**(1.0/C_tau1)) + B*k_tau*tau1/((1+C_tau1)*(1+k_tau*C_tau1)) ) * tau1**(1.0/(k_tau*C_tau1)) + !x%element(i,j)%vind(indx) = K1 + B*(p%dt-k_tau*tau1)/((1+C_tau1)*(1+k_tau*C_tau1)) + C0 / ((1-k_tau)*(tau1+C_tau1*p%dt)**(1.0/C_tau1)) + C0_2 / ((tau1 + C_tau1*p%dt)**(1.0/(k_tau*C_tau1))) + end do + + end if +end subroutine DBEMT_UpdateStates + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the (rotor) value of tau1 for DBEMT +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine ComputeTau1(u, p, m, tau1, errStat, errMsg) + type(DBEMT_InputType), intent(in ) :: u !< Inputs at u(1) + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + real(ReKi) , intent( out) :: tau1 !< tau1 value used in DBEMT filter + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(ReKi) :: temp + + real(ReKi) :: AxInd_disk + real(ReKi), parameter :: max_AxInd = 0.5_ReKi + + real(ReKi) :: Un_disk + real(ReKi), parameter :: min_Un = 0.1_ReKi + + character(*), parameter :: RoutineName = 'ComputeTau' + + + ErrStat = ErrID_None + ErrMsg = "" + + if ( p%DBEMT_Mod == DBEMT_tauConst .or. p%DBEMT_Mod == DBEMT_cont_tauConst) then + tau1 = p%tau1_const + else + + ! We need to extrapolate the radius and disk velocity to the i+1 timestep + ! We will grab the i+1 version of vind,s and the disk averaged induction by using the + ! the already updated states of the BEMT module. + + !bjj: I believe u(1) is at t, which seems inconsistant with this comment + + ! Check if input values are valid for this formulation: + if ( u%AxInd_disk > max_AxInd ) then + AxInd_disk = max_AxInd + if (m%FirstWarn_tau1) then + call setErrStat( ErrID_Severe, 'Rotor-averaged axial induction factor is greater than '//trim(num2lstr(max_AxInd)) & + //'; limiting time-varying tau1. This message will not be repeated though the condition may persist.', & + ErrStat, ErrMsg, RoutineName ) ! don't print this error more than one time + m%FirstWarn_tau1 = .false. + end if + else + AxInd_disk = u%AxInd_disk + end if + + if ( u%Un_disk < min_Un ) then + Un_disk = min_Un + if (m%FirstWarn_tau1) then + call setErrStat( ErrID_Severe, 'Uninduced axial relative air speed, Un, is less than '//trim(num2lstr(min_Un)) & + // ' m/s; limiting time-varying tau1. This message will not be repeated though the ' & + //'condition may persist.', ErrStat, ErrMsg, RoutineName ) ! don't print this error more than one time + m%FirstWarn_tau1 = .false. + end if + else + Un_disk = u%Un_disk + end if + + temp = (1.0-1.3*AxInd_disk)*Un_disk + + tau1 = 1.1*u%R_disk/temp ! Eqn. 1.2 (note that we've eliminated possibility of temp being 0) + tau1 = min(tau1, 100.0_ReKi) ! put a limit on this time constant so it isn't unrealistically long (particularly at initialization) + + end if + +end subroutine ComputeTau1 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the (rotor) value of tau1, tau2, and k_tau for DBEMT +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine ComputeTau2(i, j, u, p, tau1, tau2, k_tau_out) + integer(IntKi), intent(in ) :: i !< blade node counter + integer(IntKi), intent(in ) :: j !< blade counter + type(DBEMT_ElementInputType), intent(in ) :: u !< element inputs at u(1) + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + real(ReKi) , intent(in ) :: tau1 !< tau1 value used in DBEMT filter + real(ReKi) , intent( out) :: tau2 !< tau2 value used in DBEMT filter + real(ReKi), optional , intent( out) :: k_tau_out !< k_tau value used in DBEMT filter + + ! local variables + real(ReKi) :: spanRatio ! local version of r / R + real(ReKi) :: k_tau + + + if ( p%DBEMT_Mod == DBEMT_tauConst .or. p%DBEMT_Mod == DBEMT_cont_tauConst ) then + spanRatio = p%spanRatio(i,j) + else + spanRatio = u%spanRatio + end if + + k_tau = 0.39 - 0.26*spanRatio**2 ! Eqn. 1.23b + tau2 = k_tau*tau1 ! Eqn. 1.7 or Eqn 1.23a + + if (present(k_tau_out) ) k_tau_out = k_tau + +end subroutine ComputeTau2 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! This subroutine is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! The descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +subroutine DBEMT_CalcOutput( i, j, t, u, y_vind, p, x, OtherState, m, errStat, errMsg ) +! NOTE: no matter how many channels are selected for output, all of the outputs are calculated +! All of the calculated output channels are placed into the m%AllOuts(:), while the channels selected for outputs are +! placed in the y%WriteOutput(:) array. +!.................................................................................................................................. + integer(IntKi), intent(in ) :: i !< blade node counter + integer(IntKi), intent(in ) :: j !< blade counter + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(DBEMT_InputType), intent(in ) :: u !< Inputs at t + real(ReKi), intent( out) :: y_vind(2) + !type(DBEMT_OutputType), intent(inout) :: y !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + type(DBEMT_ParameterType), intent(in ) :: p !< Parameters + type(DBEMT_ContinuousStateType), intent(in ) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(DBEMT_OtherStateType), intent(in ) :: OtherState !< Other/logical states at t + + 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 = 'DBEMT_CalcOutput' + + ErrStat = ErrID_None + ErrMsg = "" + + if ( .not. OtherState%areStatesInitialized(i,j) ) then + y_vind = u%element(i,j)%vind_s + else + y_vind = x%element(i,j)%vind ! array copy + end if + + +end subroutine DBEMT_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +SUBROUTINE DBEMT_CalcContStateDeriv( i, j, t, u, p, x, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + INTEGER(IntKi), INTENT(IN ) :: i !< blade node counter + INTEGER(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(DBEMT_ElementInputType), INTENT(IN ) :: u !< Inputs at t + TYPE(DBEMT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(DBEMT_ElementContinuousStateType), INTENT(IN ) :: x !< Continuous states at t (and i and j) + TYPE(DBEMT_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(DBEMT_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(DBEMT_ElementContinuousStateType), INTENT(OUT) :: dxdt !< Continuous state derivatives at t (note that since we are operating on only a portion of the continuous states, I have made a separate, smaller type to avoid excessive memory allocation/deallocation) + 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 = 'DBEMT_CalcContStateDeriv' + + REAL(ReKi) :: tauConst + REAL(ReKi) :: tau1 + REAL(ReKi) :: tau2 + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Compute the first time derivatives of the continuous states here: + + if (p%DBEMT_Mod /= DBEMT_cont_tauConst) then + call SetErrStat(ErrID_Fatal,"Continuous state derivatives cannot be calculated unless DBEMT_Mod is 3.",ErrStat,ErrMsg,RoutineName) + return + end if + + tau1 = p%tau1_const + !call ComputeTau1( u, p, m, tau1, errStat, errMsg) + call ComputeTau2(i, j, u, p, tau1, tau2) + + ! Implement Equation 37 from E.Branlard 16-Dec-2019 doc: + + dxdt%vind = x%vind_dot + + tauConst = -1.0_ReKi/(tau1 * tau2) + + dxdt%vind_dot = tauConst * ( x%vind(:) + (tau1 + tau2)*x%vind_dot(:) & + - u%vind_s(:) - p%k_0ye*tau1*u%vind_s_dot(:) ) + +END SUBROUTINE DBEMT_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." Sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE DBEMT_RK4( i, j, t, n, u, utimes, p, x, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(DBEMT_ElementInputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(DBEMT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(DBEMT_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(DBEMT_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(DBEMT_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 + + ! local variables + + TYPE(DBEMT_ElementContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(DBEMT_ElementContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(DBEMT_ElementContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(DBEMT_ElementContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(DBEMT_ElementContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(DBEMT_ElementInputType) :: u_interp ! interpolated value of inputs + + REAL(DbKi) :: TPlusHalfDt + REAL(DbKi) :: TPlusDt + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_RK4' + + + !NOTE: the error handling here assumes that we do not have any allocatable data in the inputs (u_interp) to be concerned with. + ! Also, We assume that if there is going to be an error in DBEMT_CalcContStateDeriv, it will happen only on the first call + ! to the routine. + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! interpolate u to find u_interp = u(t) + CALL DBEMT_ElementInputType_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + x_tmp = x%element(i,j) + + ! find xdot at t + CALL DBEMT_CalcContStateDeriv( i, j, t, u_interp, p, x_tmp, OtherState, m, k1, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + k1%vind = p%dt * k1%vind + k1%vind_dot = p%dt * k1%vind_dot + + x_tmp%vind = x%element(i,j)%vind + 0.5 * k1%vind + x_tmp%vind_dot = x%element(i,j)%vind_dot + 0.5 * k1%vind_dot + + ! interpolate u to find u_interp = u(t + dt/2) + TPlusHalfDt = t+0.5_DbKi*p%dt + CALL DBEMT_ElementInputType_ExtrapInterp(u, utimes, u_interp, TPlusHalfDt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt/2 + CALL DBEMT_CalcContStateDeriv( i, j, TPlusHalfDt, u_interp, p, x_tmp, OtherState, m, k2, ErrStat2, ErrMsg2 ) + + k2%vind = p%dt * k2%vind + k2%vind_dot = p%dt * k2%vind_dot + + x_tmp%vind = x%element(i,j)%vind + 0.5 * k2%vind + x_tmp%vind_dot = x%element(i,j)%vind_dot + 0.5 * k2%vind_dot + + ! find xdot at t + dt/2 (note x_tmp has changed) + CALL DBEMT_CalcContStateDeriv( i, j, TPlusHalfDt, u_interp, p, x_tmp, OtherState, m, k3, ErrStat2, ErrMsg2 ) + + k3%vind = p%dt * k3%vind + k3%vind_dot = p%dt * k3%vind_dot + + x_tmp%vind = x%element(i,j)%vind + k3%vind + x_tmp%vind_dot = x%element(i,j)%vind_dot + k3%vind_dot + + ! interpolate u to find u_interp = u(t + dt) + TPlusDt = t + p%dt + CALL DBEMT_ElementInputType_ExtrapInterp(u, utimes, u_interp, TPlusDt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt + CALL DBEMT_CalcContStateDeriv( i, j, TPlusDt, u_interp, p, x_tmp, OtherState, m, k4, ErrStat2, ErrMsg2 ) + + k4%vind = p%dt * k4%vind + k4%vind_dot = p%dt * k4%vind_dot + + x%element(i,j)%vind = x%element(i,j)%vind + ( k1%vind + 2. * k2%vind + 2. * k3%vind + k4%vind ) / 6. + x%element(i,j)%vind_dot = x%element(i,j)%vind_dot + ( k1%vind_dot + 2. * k2%vind_dot + 2. * k3%vind_dot + k4%vind_dot ) / 6. + +END SUBROUTINE DBEMT_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE DBEMT_AB4( i, j, t, n, u, utimes, p, x, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(DBEMT_ElementInputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(DBEMT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(DBEMT_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(DBEMT_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(DBEMT_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 + + + ! local variables + TYPE(DBEMT_ElementInputType) :: u_interp + TYPE(DBEMT_ElementContinuousStateType) :: x_tmp + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_AB4' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + if (OtherState%n(i,j) < n) then + + OtherState%n(i,j) = n + ! these types don't contain pointers or allocatable arrays, so we can copy them directly here: + OtherState%xdot(4)%element(i,j) = OtherState%xdot(3)%element(i,j) + OtherState%xdot(3)%element(i,j) = OtherState%xdot(2)%element(i,j) + OtherState%xdot(2)%element(i,j) = OtherState%xdot(1)%element(i,j) + + elseif (OtherState%n(i,j) > n) then + + CALL SetErrStat(ErrID_Fatal,'Backing up in time is not supported with a multistep method.',ErrStat,ErrMsg,RoutineName) + RETURN + + endif + + ! need xdot at t, get inputs at t + CALL DBEMT_ElementInputType_ExtrapInterp(u, utimes, u_interp, t, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + x_tmp = x%element(i,j) + + ! calculate OtherState%xdot( 1 )%element(i,j) + CALL DBEMT_CalcContStateDeriv( i, j, t, u_interp, p, x_tmp, OtherState, m, OtherState%xdot( 1 )%element(i,j), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + if (n <= 2) then + + CALL DBEMT_RK4(i, j, t, n, u, utimes, p, x, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + else + + x%element(i,j)%vind = x%element(i,j)%vind + p%DT/24. * ( 55.*OtherState%xdot(1)%element(i,j)%vind - 59.*OtherState%xdot(2)%element(i,j)%vind & + + 37.*OtherState%xdot(3)%element(i,j)%vind - 9.*OtherState%xdot(4)%element(i,j)%vind ) + + x%element(i,j)%vind_dot = x%element(i,j)%vind_dot + p%DT/24. * ( 55.*OtherState%xdot(1)%element(i,j)%vind_dot - 59.*OtherState%xdot(2)%element(i,j)%vind_dot & + + 37.*OtherState%xdot(3)%element(i,j)%vind_dot - 9.*OtherState%xdot(4)%element(i,j)%vind_dot ) + + endif + + +END SUBROUTINE DBEMT_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: \n +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: \n +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE DBEMT_ABM4( i, j, t, n, u, utimes, p, x, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(DBEMT_ElementInputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(DBEMT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(DBEMT_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(DBEMT_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(DBEMT_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 + + ! local variables + + TYPE(DBEMT_ElementInputType) :: u_interp ! Inputs at t + TYPE(DBEMT_ElementContinuousStateType) :: x_in ! Continuous states at t + TYPE(DBEMT_ElementContinuousStateType) :: xdot_pred ! Derivative of continuous states at t + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_ABM4' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! save copy of x(t): + x_in = x%element(i,j) + + + ! predict: (note that we are overwritting x%element(i,j)%vind and x%element(i,j)%vind_dot here): + CALL DBEMT_AB4( i, j, t, n, u, utimes, p, x, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + if (n > 2_IntKi) then + + ! correct: + + CALL DBEMT_ElementInputType_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL DBEMT_CalcContStateDeriv(i, j, t + p%dt, u_interp, p, x%element(i,j), OtherState, m, xdot_pred, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + x%element(i,j)%vind = x_in%vind + p%DT/24. * ( 9. * xdot_pred%vind + 19. * OtherState%xdot(1)%element(i,j)%vind & + - 5. * OtherState%xdot(2)%element(i,j)%vind & + + 1. * OtherState%xdot(3)%element(i,j)%vind ) + + x%element(i,j)%vind_dot = x_in%vind_dot + p%DT/24. * ( 9. * xdot_pred%vind_dot + 19. * OtherState%xdot(1)%element(i,j)%vind_dot & + - 5. * OtherState%xdot(2)%element(i,j)%vind_dot & + + 1. * OtherState%xdot(3)%element(i,j)%vind_dot ) + endif + +END SUBROUTINE DBEMT_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +subroutine DBEMT_End( u, p, x, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(DBEMT_InputType), INTENT(INOUT) :: u(2) !< System inputs + TYPE(DBEMT_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(DBEMT_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + type(DBEMT_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(DBEMT_OtherStateType), intent(inout) :: OtherState !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL DBEMT_DestroyInput( u(1), ErrStat, ErrMsg ) + CALL DBEMT_DestroyInput( u(2), ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL DBEMT_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL DBEMT_DestroyContState( x, ErrStat, ErrMsg ) + + + CALL DBEMT_DestroyMisc( m, ErrStat, ErrMsg ) + CALL DBEMT_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + +END SUBROUTINE DBEMT_End + +end module DBEMT \ No newline at end of file diff --git a/OpenFAST/modules/aerodyn/src/DBEMT_Registry.txt b/OpenFAST/modules/aerodyn/src/DBEMT_Registry.txt new file mode 100644 index 000000000..c5fa20f52 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/DBEMT_Registry.txt @@ -0,0 +1,89 @@ +################################################################################################################################### +# Registry for DBEMT in the FAST Modularization Framework +# This Registry file is used to create DBEMT_Types which contains data used in the DBEMT module. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + +param DBEMT/DBEMT - INTEGER DBEMT_none - 0 - "use BEMT instead (not DBEMT)" - +param DBEMT/DBEMT - INTEGER DBEMT_tauConst - 1 - "use constant tau1" - +param DBEMT/DBEMT - INTEGER DBEMT_tauVaries - 2 - "use time-dependent tau1" - +param DBEMT/DBEMT - INTEGER DBEMT_cont_tauConst - 3 - "use continuous formulation with constant tau1" - + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef DBEMT/DBEMT InitInputType IntKi NumBlades - - - "Number of blades on the turbine" - +typedef ^ InitInputType IntKi NumNodes - - - "Number of nodes on each blade" - +typedef ^ InitInputType ReKi tau1_const - - - "delay value based on disk-averaged quantities" - +typedef ^ InitInputType IntKi DBEMT_Mod - - - "DBEMT Model. 1 = constant tau1, 2 = time dependent tau1, 3=continuous form with constant tau1" - +typedef ^ ^ ReKi rLocal {:}{:} - - "Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT" m + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +typedef ^ DBEMT_ElementContinuousStateType R8Ki vind {2} - - "The filtered induced velocity, [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tantential induced velocity (Vy*a')" m/s +typedef ^ DBEMT_ElementContinuousStateType R8Ki vind_dot {2} - - "Time derivative of the filtered induced velocity, x%vind in CCSD" "m/s^2" +typedef ^ DBEMT_ElementContinuousStateType R8Ki vind_1 {2} - - "The filtered intermediate induced velocity" "m/s" + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType DBEMT_ElementContinuousStateType element {:}{:} - - "The filtered induced velocity [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tantential induced velocity (Vy*a') at node i on blade j" m/s +# +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType SiKi DummyState - - - "Remove this variable if you have continuous states" - +# +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyState - - - "Remove this variable if you have constraint states" - +# +# Define "other" states here: +typedef ^ OtherStateType Logical areStatesInitialized {:}{:} - - "Flag indicating whether the module's states have been initialized properly" - +typedef ^ OtherStateType ReKi tau1 - - - "value of tau1 used in updateStates (for output-to-file only)" - +typedef ^ OtherStateType ReKi tau2 - - - "value of tau2 used in updateStates (equal to k_tau * tau1, not used between time steps)" - +typedef ^ OtherStateType IntKi n {:}{:} - - "time step # value used for continuous state integrator" - +typedef ^ OtherStateType DBEMT_ContinuousStateType xdot {4} - - "derivative history for continuous state integrators" - + +# +# Define misc/optimization variables (any data that are not considered actual states) here: +typedef ^ MiscVarType Logical FirstWarn_tau1 - - - "flag so tau1 limit warning doesn't get repeated forever" - + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ParameterType IntKi lin_nx - 0 - "Number of continuous states for linearization" - +typedef ^ ParameterType IntKi NumBlades - - - "Number of blades on the turbine" - +typedef ^ ParameterType IntKi NumNodes - - - "Number of nodes on each blade" - +typedef ^ ParameterType ReKi k_0ye - - - "Filter dynamics constant [default = 0.6 ]" - +#typedef ^ ParameterType ReKi c5 - - - "Filter dynamics constant [default = 1.1 ]" - +#typedef ^ ParameterType ReKi c6 - - - "Filter dynamics constant [default = 1.0 ]" - +#typedef ^ ParameterType ReKi c7 - - - "Filter dynamics constant [default = 1.3 ]" - +#typedef ^ ParameterType ReKi c8 - - - "Filter dynamics constant [default = 0.39]" - +#typedef ^ ParameterType ReKi c9 - - - "Filter dynamics constant [default = 0.26]" - +typedef ^ ParameterType ReKi tau1_const - - - "constant version of the delay value" - +typedef ^ ParameterType ReKi spanRatio {:}{:} - - "static span ratio of each blade node" +typedef ^ ParameterType IntKi DBEMT_Mod - - - "DBEMT Model. 1 = constant tau1, 2 = time dependent tau1, 3=continuous form of constant tau1" - + + +# ..... Inputs .................................................................................................................... +typedef ^ DBEMT_ElementInputType ReKi vind_s {2} - - "The unfiltered induced velocity, [1] is the axial induced velocity (-Vx*a) and [2] is the tangential induced velocity (Vy*a') at node i on blade j. Note that the inputs are used only operated on at a particular node and blade, so we don't store all elements" "m/s" +typedef ^ DBEMT_ElementInputType ReKi vind_s_dot {2} - - "The first time derivative of the unfiltered induced velocity, u%vind_s" "m/s^2" +typedef ^ DBEMT_ElementInputType ReKi spanRatio - - - "Normalized span location of blade node" - +# Define inputs that are contained on the mesh here: +# +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi AxInd_disk - - - "Disk-averaged axial induction (for time-varying tau)" - +typedef ^ InputType ReKi Un_disk - - - "Disk-averaged normal relative inflow velocity (for time-varying tau)" m/s +typedef ^ InputType ReKi R_disk - - - "Disk-averaged rotor radius (for time-varying tau)" m +typedef ^ InputType DBEMT_ElementInputType element {:}{:} - - "The element-level inputs at each blade node" - +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +# +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi vind {:}{:}{:} - - "The filtered induced velocity, [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tangential induced velocity (Vy*a') at node i on blade j" m/s diff --git a/OpenFAST/modules/aerodyn/src/DBEMT_Test.f90 b/OpenFAST/modules/aerodyn/src/DBEMT_Test.f90 new file mode 100644 index 000000000..6f01d56d7 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/DBEMT_Test.f90 @@ -0,0 +1,729 @@ +! DBEMT_Test.f90 +! +! FUNCTIONS: +! DBEMT_Test - Entry point of console application. +! + +!**************************************************************************** +! +! PROGRAM: DBEMT_Test +! +! PURPOSE: Entry point for the console application. +! +!**************************************************************************** + +program DBEMT_Test + use DBEMT + use NWTC_Library + + implicit none + + ! Variables + integer(IntKi) :: errStat !< Error status of the operation + character(ErrMsgLen) :: errMsg !< Error message if ErrStat /= ErrID_None + logical :: result + ! Initialize the NWTC Subroutine Library + + call NWTC_Init( EchoLibVer=.FALSE. ) + + ! Body of DBEMT_Test + print *, 'Beginning DBEMT Testing' + errStat = ErrID_None + errMsg = "" + + result = DBEMT_TEST01(errStat, errMsg) + print *, 'Test01: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + result = DBEMT_TEST02(errStat, errMsg) + print *, 'Test02: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + +result = DBEMT_TEST03(errStat, errMsg) + print *, 'Test03: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + + result = DBEMT_TEST04(errStat, errMsg) + print *, 'Test04: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + + result = DBEMT_TEST05(errStat, errMsg) + print *, 'Test05: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + + result = DBEMT_TEST06(errStat, errMsg) + print *, 'Test06: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + + result = DBEMT_TEST07(errStat, errMsg) + print *, 'Test07: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + + result = DBEMT_TEST08(errStat, errMsg) + print *, 'Test08: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + +result = DBEMT_TEST09(errStat, errMsg) + print *, 'Test09: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + +result = DBEMT_TEST10(errStat, errMsg) + print *, 'Test10: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + +result = DBEMT_TEST11(errStat, errMsg) + print *, 'Test11: ', result +#ifdef PRINT_ERRMSG + print *, trim(errMsg) + print * +#endif + +contains + +logical function DBEMT_TEST01(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + + + DBEMT_TEST01 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = -1 + + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + if (errStat == AbortErrLev) DBEMT_TEST01 = .true. + +end function DBEMT_TEST01 + +logical function DBEMT_TEST02(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u(2) !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_TEST02' + + ! Initialize variables for this routine + + errStat2 = ErrID_None + errMsg2 = "" + + + DBEMT_TEST02 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 0 + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + call DBEMT_UpdateStates(1, 1, interval, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + ! Since DBEMT is turned off, their should be no errors, even though other initialization data is missing + if (errStat == ErrID_None) DBEMT_TEST02 = .true. + +end function DBEMT_TEST02 + +logical function DBEMT_TEST03(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + + + DBEMT_TEST03 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + + ! The InitInp%numBlades has not been set. This should produce a fatal error. + ! The InitInp%numNodes has not been set. This should produce a fatal error. + ! The InitInp%rlocal array has not been allocated. This should produce a fatal error. + + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + if (errStat == AbortErrLev) DBEMT_TEST03 = .true. + +end function DBEMT_TEST03 + +logical function DBEMT_TEST04(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + + + DBEMT_TEST04 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + ! The InitInp%numNodes has not been set. This should produce a fatal error. + ! The InitInp%rlocal array has not been allocated. This should produce a fatal error. + if (errStat == AbortErrLev) DBEMT_TEST04 = .true. + +end function DBEMT_TEST04 + +logical function DBEMT_TEST05(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + + + DBEMT_TEST05 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 3 + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + ! The InitInp%rlocal array has not been allocated. This should produce a fatal error. + if (errStat == AbortErrLev) DBEMT_TEST05 = .true. + +end function DBEMT_TEST05 + +logical function DBEMT_TEST06(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + + + DBEMT_TEST06 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + + ! The rlocal values have been allocated, but not initialized. This should produce a fatal error, but the values + ! that are set are indeterminate, so we will never know if an error is triggered or not. + + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + if (errStat == AbortErrLev) DBEMT_TEST06 = .true. + +end function DBEMT_TEST06 + +logical function DBEMT_TEST07(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: i,j + + DBEMT_TEST07 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + do j=1,InitInp%numBlades + do i=1,InitInp%numNodes + InitInp%rlocal(i,j) = real(i,ReKi) + end do + end do + + call DBEMT_Init(InitInp, u, p, x, m, Interval, InitOut, errStat, errMsg) + + if (errStat == AbortErrLev) DBEMT_TEST07 = .true. + +end function DBEMT_TEST07 + +logical function DBEMT_TEST08(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u(2) !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: i,j + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_TEST08' + + ! Initialize variables for this routine + + errStat2 = ErrID_None + errMsg2 = "" + DBEMT_TEST08 = .false. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + do j=1,InitInp%numBlades + do i=1,InitInp%numNodes + InitInp%rlocal(i,j) = real(i,ReKi) + end do + end do + Interval = 0.1_ReKi + InitInp%tau1_const = 0.0_ReKi + + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + u(1)%vind_s(1) = 10.0_ReKi + u(1)%vind_s(2) = 0.0_ReKi + + u(2)%vind_s(1) = 12.0_ReKi + u(2)%vind_s(2) = 0.0_ReKi + + call DBEMT_UpdateStates(1, 1, 0.0_DbKi, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + if ( (errStat == ErrID_None) .and. (EqualRealNos(u(1)%vind_s(1),x%vind(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(1),x%vind_1(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind(2,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind_1(2,1,1)) )) then + DBEMT_TEST08 = .true. + else + DBEMT_TEST08 = .false. + end if + + call DBEMT_End(u, p, x, m, ErrStat, ErrMsg ) + + InitInp%tau1_const = 1.0_ReKi + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + u(1)%vind_s(1) = 10.0_ReKi + u(1)%vind_s(2) = 0.0_ReKi + + u(2)%vind_s(1) = 12.0_ReKi + u(2)%vind_s(2) = 0.0_ReKi + + call DBEMT_UpdateStates(1, 1, 0.0_DbKi, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + if ( (errStat == ErrID_None) .and. (EqualRealNos(u(1)%vind_s(1),x%vind(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(1),x%vind_1(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind(2,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind_1(2,1,1)) )) then + DBEMT_TEST08 = (.true. .and. DBEMT_TEST08) + else + DBEMT_TEST08 = .false. + + end if + + call DBEMT_End(u, p, x, m, ErrStat, ErrMsg ) + +end function DBEMT_TEST08 + +logical function DBEMT_TEST09(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u(2) !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: i,j,n + real(DbKi) :: t + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_TEST09' + + ! Initialize variables for this routine + + errStat2 = ErrID_None + errMsg2 = "" + DBEMT_TEST09 = .true. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + do j=1,InitInp%numBlades + do i=1,InitInp%numNodes + InitInp%rlocal(i,j) = real(i,ReKi) + end do + end do + Interval = 0.1_ReKi + InitInp%tau1_const = 0.0_ReKi + + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + u(1)%vind_s(1) = 10.0_ReKi + u(1)%vind_s(2) = 0.0_ReKi + + u(2)%vind_s(1) = 10.0_ReKi + u(2)%vind_s(2) = 0.0_ReKi + do n=1,10 + t = n*Interval + call DBEMT_UpdateStates(1, 1, t, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + if ( (errStat == ErrID_None) .and. (EqualRealNos(u(1)%vind_s(1),x%vind(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(1),x%vind_1(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind(2,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind_1(2,1,1)) )) then + DBEMT_TEST09 = .true. .and. DBEMT_TEST09 + else + DBEMT_TEST09 = .false. + end if + end do + call DBEMT_End(u, p, x, m, ErrStat, ErrMsg ) + + + +end function DBEMT_TEST09 + + +logical function DBEMT_TEST10(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u(2) !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: i,j,n + real(DbKi) :: t + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_TEST10' + + ! Initialize variables for this routine + + errStat2 = ErrID_None + errMsg2 = "" + DBEMT_TEST10 = .true. + + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + do j=1,InitInp%numBlades + do i=1,InitInp%numNodes + InitInp%rlocal(i,j) = real(i,ReKi) + end do + end do + Interval = 0.1_ReKi + InitInp%tau1_const = 0.0_ReKi + + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + u(1)%vind_s(1) = 10.0_ReKi + u(1)%vind_s(2) = 0.0_ReKi + + u(2)%vind_s(1) = 12.0_ReKi + u(2)%vind_s(2) = 1.0_ReKi + do n=0,10 + t = n*Interval + call DBEMT_UpdateStates(1, 1, t, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + if ( (errStat == ErrID_None) .and. (EqualRealNos(u(1)%vind_s(1),x%vind(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(1),x%vind_1(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind(2,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind_1(2,1,1)) )) then + DBEMT_TEST10 = .true. .and. DBEMT_TEST10 + else + DBEMT_TEST10 = .false. + end if + + u(1)%vind_s(1) = 12.0_ReKi + u(1)%vind_s(2) = 1.0_ReKi + + end do + call DBEMT_End(u, p, x, m, ErrStat, ErrMsg ) + + + +end function DBEMT_TEST10 + +logical function DBEMT_TEST11(errStat, errMsg) + + + integer(IntKi), INTENT(out) :: errStat !< Error status of the operation + character(ErrMsgLen), INTENT(out) :: errMsg !< Error message if ErrStat /= ErrID_None + type(DBEMT_InitInputType) :: InitInp !< Input data for initialization routine + type(DBEMT_InputType) :: u(2) !< An initial guess for the input; input mesh must be defined + type(DBEMT_ParameterType) :: p !< Parameters + type(DBEMT_ContinuousStateType) :: x !< Initial continuous states + type(DBEMT_MiscVarType) :: m !< Initial misc/optimization variables + real(DbKi) :: interval !< Coupling interval in seconds: the rate that + !! (1) DBEMT_UpdateStates() is called in loose coupling & + !! (2) DBEMT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(DBEMT_InitOutputType) :: InitOut !< Output for initialization routine + + integer(IntKi) :: i,j,n + real(DbKi) :: t + integer(IntKi) :: errStat2 ! temporary error status of the operation + character(ErrMsgLen) :: errMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'DBEMT_TEST11' + real(ReKi) :: maxVind1 + ! Initialize variables for this routine + + errStat2 = ErrID_None + errMsg2 = "" + DBEMT_TEST11 = .true. + maxVind1 = 0.0 + ! This test will evaluate the initialization of the module + + errStat = ErrID_None + errMsg = "" + + InitInp%DBEMT_Mod = 1 + InitInp%numBlades = 1 + InitInp%numNodes = 2 + allocate(InitInp%rlocal(InitInp%numNodes,InitInp%numBlades)) + do j=1,InitInp%numBlades + do i=1,InitInp%numNodes + InitInp%rlocal(i,j) = real(i,ReKi) + end do + end do + Interval = 0.1_ReKi + InitInp%tau1_const = .01000_ReKi + + call DBEMT_Init(InitInp, u(1), p, x, m, Interval, InitOut, errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + u(1)%vind_s(1) = 10.0_ReKi + u(1)%vind_s(2) = 0.0_ReKi + + u(2)%vind_s(1) = 12.0_ReKi + u(2)%vind_s(2) = 1.0_ReKi + do n=0,10000 + t = n*Interval + call DBEMT_UpdateStates(1, 1, t, u, p, x, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName) + + if ( x%vind(1,1,1) > maxVind1 ) maxVind1 = x%vind(1,1,1) + + u(1)%vind_s(1) = 12.0_ReKi + u(1)%vind_s(2) = 1.0_ReKi + + end do + if ( (errStat == ErrID_None) .and. (EqualRealNos(u(1)%vind_s(1),x%vind(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(1),x%vind_1(1,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind(2,1,1)) ) & + .and. (EqualRealNos(u(1)%vind_s(2),x%vind_1(2,1,1)) )) then + DBEMT_TEST11 = (.true. .and. DBEMT_TEST11) + else + DBEMT_TEST11 = .false. + end if + call DBEMT_End(u, p, x, m, ErrStat, ErrMsg ) + + + +end function DBEMT_TEST11 + + + end program DBEMT_Test + diff --git a/OpenFAST/modules/aerodyn/src/DBEMT_Types.f90 b/OpenFAST/modules/aerodyn/src/DBEMT_Types.f90 new file mode 100644 index 000000000..04f0fb3af --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/DBEMT_Types.f90 @@ -0,0 +1,3199 @@ +!STARTOFREGISTRYGENERATEDFILE 'DBEMT_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 +!********************************************************************************************************************************* +! DBEMT_Types +!................................................................................................................................. +! This file is part of DBEMT. +! +! 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 DBEMT. 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 DBEMT_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: DBEMT_none = 0 ! use BEMT instead (not DBEMT) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: DBEMT_tauConst = 1 ! use constant tau1 [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: DBEMT_tauVaries = 2 ! use time-dependent tau1 [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: DBEMT_cont_tauConst = 3 ! use continuous formulation with constant tau1 [-] +! ========= DBEMT_InitInputType ======= + TYPE, PUBLIC :: DBEMT_InitInputType + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + INTEGER(IntKi) :: NumNodes !< Number of nodes on each blade [-] + REAL(ReKi) :: tau1_const !< delay value based on disk-averaged quantities [-] + INTEGER(IntKi) :: DBEMT_Mod !< DBEMT Model. 1 = constant tau1, 2 = time dependent tau1, 3=continuous form with constant tau1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rLocal !< Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT [m] + END TYPE DBEMT_InitInputType +! ======================= +! ========= DBEMT_InitOutputType ======= + TYPE, PUBLIC :: DBEMT_InitOutputType + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE DBEMT_InitOutputType +! ======================= +! ========= DBEMT_ElementContinuousStateType ======= + TYPE, PUBLIC :: DBEMT_ElementContinuousStateType + REAL(R8Ki) , DIMENSION(1:2) :: vind !< The filtered induced velocity, [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tantential induced velocity (Vy*a') [m/s] + REAL(R8Ki) , DIMENSION(1:2) :: vind_dot !< Time derivative of the filtered induced velocity, x%vind in CCSD [m/s^2] + REAL(R8Ki) , DIMENSION(1:2) :: vind_1 !< The filtered intermediate induced velocity [m/s] + END TYPE DBEMT_ElementContinuousStateType +! ======================= +! ========= DBEMT_ContinuousStateType ======= + TYPE, PUBLIC :: DBEMT_ContinuousStateType + TYPE(DBEMT_ElementContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: element !< The filtered induced velocity [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tantential induced velocity (Vy*a') at node i on blade j [m/s] + END TYPE DBEMT_ContinuousStateType +! ======================= +! ========= DBEMT_DiscreteStateType ======= + TYPE, PUBLIC :: DBEMT_DiscreteStateType + REAL(SiKi) :: DummyState !< Remove this variable if you have continuous states [-] + END TYPE DBEMT_DiscreteStateType +! ======================= +! ========= DBEMT_ConstraintStateType ======= + TYPE, PUBLIC :: DBEMT_ConstraintStateType + REAL(SiKi) :: DummyState !< Remove this variable if you have constraint states [-] + END TYPE DBEMT_ConstraintStateType +! ======================= +! ========= DBEMT_OtherStateType ======= + TYPE, PUBLIC :: DBEMT_OtherStateType + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: areStatesInitialized !< Flag indicating whether the module's states have been initialized properly [-] + REAL(ReKi) :: tau1 !< value of tau1 used in updateStates (for output-to-file only) [-] + REAL(ReKi) :: tau2 !< value of tau2 used in updateStates (equal to k_tau * tau1, not used between time steps) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: n !< time step value used for continuous state integrator [-] + TYPE(DBEMT_ContinuousStateType) , DIMENSION(1:4) :: xdot !< derivative history for continuous state integrators [-] + END TYPE DBEMT_OtherStateType +! ======================= +! ========= DBEMT_MiscVarType ======= + TYPE, PUBLIC :: DBEMT_MiscVarType + LOGICAL :: FirstWarn_tau1 !< flag so tau1 limit warning doesn't get repeated forever [-] + END TYPE DBEMT_MiscVarType +! ======================= +! ========= DBEMT_ParameterType ======= + TYPE, PUBLIC :: DBEMT_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + INTEGER(IntKi) :: lin_nx = 0 !< Number of continuous states for linearization [-] + INTEGER(IntKi) :: NumBlades !< Number of blades on the turbine [-] + INTEGER(IntKi) :: NumNodes !< Number of nodes on each blade [-] + REAL(ReKi) :: k_0ye !< Filter dynamics constant [default = 0.6 ] [-] + REAL(ReKi) :: tau1_const !< constant version of the delay value [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: spanRatio !< static span ratio of each blade node [-] + INTEGER(IntKi) :: DBEMT_Mod !< DBEMT Model. 1 = constant tau1, 2 = time dependent tau1, 3=continuous form of constant tau1 [-] + END TYPE DBEMT_ParameterType +! ======================= +! ========= DBEMT_ElementInputType ======= + TYPE, PUBLIC :: DBEMT_ElementInputType + REAL(ReKi) , DIMENSION(1:2) :: vind_s !< The unfiltered induced velocity, [1] is the axial induced velocity (-Vx*a) and [2] is the tangential induced velocity (Vy*a') at node i on blade j. Note that the inputs are used only operated on at a particular node and blade, so we don't store all elements [m/s] + REAL(ReKi) , DIMENSION(1:2) :: vind_s_dot !< The first time derivative of the unfiltered induced velocity, u%vind_s [m/s^2] + REAL(ReKi) :: spanRatio !< Normalized span location of blade node [-] + END TYPE DBEMT_ElementInputType +! ======================= +! ========= DBEMT_InputType ======= + TYPE, PUBLIC :: DBEMT_InputType + REAL(ReKi) :: AxInd_disk !< Disk-averaged axial induction (for time-varying tau) [-] + REAL(ReKi) :: Un_disk !< Disk-averaged normal relative inflow velocity (for time-varying tau) [m/s] + REAL(ReKi) :: R_disk !< Disk-averaged rotor radius (for time-varying tau) [m] + TYPE(DBEMT_ElementInputType) , DIMENSION(:,:), ALLOCATABLE :: element !< The element-level inputs at each blade node [-] + END TYPE DBEMT_InputType +! ======================= +! ========= DBEMT_OutputType ======= + TYPE, PUBLIC :: DBEMT_OutputType + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: vind !< The filtered induced velocity, [1,i,j] is the axial induced velocity (-Vx*a) at node i on blade j and [2,i,j] is the tangential induced velocity (Vy*a') at node i on blade j [m/s] + END TYPE DBEMT_OutputType +! ======================= +CONTAINS + SUBROUTINE DBEMT_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(DBEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%NumBlades = SrcInitInputData%NumBlades + DstInitInputData%NumNodes = SrcInitInputData%NumNodes + DstInitInputData%tau1_const = SrcInitInputData%tau1_const + DstInitInputData%DBEMT_Mod = SrcInitInputData%DBEMT_Mod +IF (ALLOCATED(SrcInitInputData%rLocal)) THEN + i1_l = LBOUND(SrcInitInputData%rLocal,1) + i1_u = UBOUND(SrcInitInputData%rLocal,1) + i2_l = LBOUND(SrcInitInputData%rLocal,2) + i2_u = UBOUND(SrcInitInputData%rLocal,2) + IF (.NOT. ALLOCATED(DstInitInputData%rLocal)) THEN + ALLOCATE(DstInitInputData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%rLocal = SrcInitInputData%rLocal +ENDIF + END SUBROUTINE DBEMT_CopyInitInput + + SUBROUTINE DBEMT_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(DBEMT_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%rLocal)) THEN + DEALLOCATE(InitInputData%rLocal) +ENDIF + END SUBROUTINE DBEMT_DestroyInitInput + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumNodes + Re_BufSz = Re_BufSz + 1 ! tau1_const + Int_BufSz = Int_BufSz + 1 ! DBEMT_Mod + Int_BufSz = Int_BufSz + 1 ! rLocal allocated yes/no + IF ( ALLOCATED(InData%rLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rLocal) ! rLocal + 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%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumNodes + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tau1_const + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DBEMT_Mod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%rLocal) ) 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%rLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rLocal,2), UBOUND(InData%rLocal,2) + DO i1 = LBOUND(InData%rLocal,1), UBOUND(InData%rLocal,1) + ReKiBuf(Re_Xferred) = InData%rLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE DBEMT_PackInitInput + + SUBROUTINE DBEMT_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(DBEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_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%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%tau1_const = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DBEMT_Mod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rLocal 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%rLocal)) DEALLOCATE(OutData%rLocal) + ALLOCATE(OutData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rLocal,2), UBOUND(OutData%rLocal,2) + DO i1 = LBOUND(OutData%rLocal,1), UBOUND(OutData%rLocal,1) + OutData%rLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE DBEMT_UnPackInitInput + + SUBROUTINE DBEMT_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(DBEMT_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 = 'DBEMT_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 DBEMT_CopyInitOutput + + SUBROUTINE DBEMT_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(DBEMT_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE DBEMT_DestroyInitOutput + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 DBEMT_PackInitOutput + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 DBEMT_UnPackInitOutput + + SUBROUTINE DBEMT_CopyElementContinuousStateType( SrcElementContinuousStateTypeData, DstElementContinuousStateTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_ElementContinuousStateType), INTENT(IN) :: SrcElementContinuousStateTypeData + TYPE(DBEMT_ElementContinuousStateType), INTENT(INOUT) :: DstElementContinuousStateTypeData + 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 = 'DBEMT_CopyElementContinuousStateType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElementContinuousStateTypeData%vind = SrcElementContinuousStateTypeData%vind + DstElementContinuousStateTypeData%vind_dot = SrcElementContinuousStateTypeData%vind_dot + DstElementContinuousStateTypeData%vind_1 = SrcElementContinuousStateTypeData%vind_1 + END SUBROUTINE DBEMT_CopyElementContinuousStateType + + SUBROUTINE DBEMT_DestroyElementContinuousStateType( ElementContinuousStateTypeData, ErrStat, ErrMsg ) + TYPE(DBEMT_ElementContinuousStateType), INTENT(INOUT) :: ElementContinuousStateTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyElementContinuousStateType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DBEMT_DestroyElementContinuousStateType + + SUBROUTINE DBEMT_PackElementContinuousStateType( 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(DBEMT_ElementContinuousStateType), 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 = 'DBEMT_PackElementContinuousStateType' + ! 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 + Db_BufSz = Db_BufSz + SIZE(InData%vind) ! vind + Db_BufSz = Db_BufSz + SIZE(InData%vind_dot) ! vind_dot + Db_BufSz = Db_BufSz + SIZE(InData%vind_1) ! vind_1 + 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%vind,1), UBOUND(InData%vind,1) + DbKiBuf(Db_Xferred) = InData%vind(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%vind_dot,1), UBOUND(InData%vind_dot,1) + DbKiBuf(Db_Xferred) = InData%vind_dot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%vind_1,1), UBOUND(InData%vind_1,1) + DbKiBuf(Db_Xferred) = InData%vind_1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE DBEMT_PackElementContinuousStateType + + SUBROUTINE DBEMT_UnPackElementContinuousStateType( 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(DBEMT_ElementContinuousStateType), 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 = 'DBEMT_UnPackElementContinuousStateType' + ! 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%vind,1) + i1_u = UBOUND(OutData%vind,1) + DO i1 = LBOUND(OutData%vind,1), UBOUND(OutData%vind,1) + OutData%vind(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%vind_dot,1) + i1_u = UBOUND(OutData%vind_dot,1) + DO i1 = LBOUND(OutData%vind_dot,1), UBOUND(OutData%vind_dot,1) + OutData%vind_dot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%vind_1,1) + i1_u = UBOUND(OutData%vind_1,1) + DO i1 = LBOUND(OutData%vind_1,1), UBOUND(OutData%vind_1,1) + OutData%vind_1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE DBEMT_UnPackElementContinuousStateType + + SUBROUTINE DBEMT_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(DBEMT_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 = 'DBEMT_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%element)) THEN + i1_l = LBOUND(SrcContStateData%element,1) + i1_u = UBOUND(SrcContStateData%element,1) + i2_l = LBOUND(SrcContStateData%element,2) + i2_u = UBOUND(SrcContStateData%element,2) + IF (.NOT. ALLOCATED(DstContStateData%element)) THEN + ALLOCATE(DstContStateData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcContStateData%element,2), UBOUND(SrcContStateData%element,2) + DO i1 = LBOUND(SrcContStateData%element,1), UBOUND(SrcContStateData%element,1) + CALL DBEMT_Copyelementcontinuousstatetype( SrcContStateData%element(i1,i2), DstContStateData%element(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF + END SUBROUTINE DBEMT_CopyContState + + SUBROUTINE DBEMT_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(DBEMT_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%element)) THEN +DO i2 = LBOUND(ContStateData%element,2), UBOUND(ContStateData%element,2) +DO i1 = LBOUND(ContStateData%element,1), UBOUND(ContStateData%element,1) + CALL DBEMT_Destroyelementcontinuousstatetype( ContStateData%element(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(ContStateData%element) +ENDIF + END SUBROUTINE DBEMT_DestroyContState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + Int_BufSz = Int_BufSz + 1 ! element allocated yes/no + IF ( ALLOCATED(InData%element) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! element upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + Int_BufSz = Int_BufSz + 3 ! element: size of buffers for each call to pack subtype + CALL DBEMT_Packelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! element + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! element + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! element + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! element + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + 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%element) ) 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%element,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%element,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + CALL DBEMT_Packelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! element + 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 DO + END IF + END SUBROUTINE DBEMT_PackContState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! element 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%element)) DEALLOCATE(OutData%element) + ALLOCATE(OutData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%element,2), UBOUND(OutData%element,2) + DO i1 = LBOUND(OutData%element,1), UBOUND(OutData%element,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 DBEMT_Unpackelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, OutData%element(i1,i2), ErrStat2, ErrMsg2 ) ! element + 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 DO + END DO + END IF + END SUBROUTINE DBEMT_UnPackContState + + SUBROUTINE DBEMT_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(DBEMT_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 = 'DBEMT_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyState = SrcDiscStateData%DummyState + END SUBROUTINE DBEMT_CopyDiscState + + SUBROUTINE DBEMT_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(DBEMT_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DBEMT_DestroyDiscState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 ! DummyState + 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%DummyState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_PackDiscState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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%DummyState = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_UnPackDiscState + + SUBROUTINE DBEMT_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(DBEMT_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 = 'DBEMT_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyState = SrcConstrStateData%DummyState + END SUBROUTINE DBEMT_CopyConstrState + + SUBROUTINE DBEMT_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(DBEMT_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DBEMT_DestroyConstrState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 ! DummyState + 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%DummyState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_PackConstrState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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%DummyState = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_UnPackConstrState + + SUBROUTINE DBEMT_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(DBEMT_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) :: 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 = 'DBEMT_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%areStatesInitialized)) THEN + i1_l = LBOUND(SrcOtherStateData%areStatesInitialized,1) + i1_u = UBOUND(SrcOtherStateData%areStatesInitialized,1) + i2_l = LBOUND(SrcOtherStateData%areStatesInitialized,2) + i2_u = UBOUND(SrcOtherStateData%areStatesInitialized,2) + IF (.NOT. ALLOCATED(DstOtherStateData%areStatesInitialized)) THEN + ALLOCATE(DstOtherStateData%areStatesInitialized(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%areStatesInitialized.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%areStatesInitialized = SrcOtherStateData%areStatesInitialized +ENDIF + DstOtherStateData%tau1 = SrcOtherStateData%tau1 + DstOtherStateData%tau2 = SrcOtherStateData%tau2 +IF (ALLOCATED(SrcOtherStateData%n)) THEN + i1_l = LBOUND(SrcOtherStateData%n,1) + i1_u = UBOUND(SrcOtherStateData%n,1) + i2_l = LBOUND(SrcOtherStateData%n,2) + i2_u = UBOUND(SrcOtherStateData%n,2) + IF (.NOT. ALLOCATED(DstOtherStateData%n)) THEN + ALLOCATE(DstOtherStateData%n(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%n.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%n = SrcOtherStateData%n +ENDIF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL DBEMT_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + END SUBROUTINE DBEMT_CopyOtherState + + SUBROUTINE DBEMT_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(DBEMT_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%areStatesInitialized)) THEN + DEALLOCATE(OtherStateData%areStatesInitialized) +ENDIF +IF (ALLOCATED(OtherStateData%n)) THEN + DEALLOCATE(OtherStateData%n) +ENDIF +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL DBEMT_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + END SUBROUTINE DBEMT_DestroyOtherState + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + Int_BufSz = Int_BufSz + 1 ! areStatesInitialized allocated yes/no + IF ( ALLOCATED(InData%areStatesInitialized) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! areStatesInitialized upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%areStatesInitialized) ! areStatesInitialized + END IF + Re_BufSz = Re_BufSz + 1 ! tau1 + Re_BufSz = Re_BufSz + 1 ! tau2 + Int_BufSz = Int_BufSz + 1 ! n allocated yes/no + IF ( ALLOCATED(InData%n) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! n upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%n) ! n + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL DBEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%areStatesInitialized) ) 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%areStatesInitialized,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%areStatesInitialized,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%areStatesInitialized,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%areStatesInitialized,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%areStatesInitialized,2), UBOUND(InData%areStatesInitialized,2) + DO i1 = LBOUND(InData%areStatesInitialized,1), UBOUND(InData%areStatesInitialized,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%areStatesInitialized(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%tau1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tau2 + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%n) ) 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%n,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%n,2), UBOUND(InData%n,2) + DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) + IntKiBuf(Int_Xferred) = InData%n(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL DBEMT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 SUBROUTINE DBEMT_PackOtherState + + SUBROUTINE DBEMT_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(DBEMT_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) :: 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 = 'DBEMT_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! areStatesInitialized 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%areStatesInitialized)) DEALLOCATE(OutData%areStatesInitialized) + ALLOCATE(OutData%areStatesInitialized(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%areStatesInitialized.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%areStatesInitialized,2), UBOUND(OutData%areStatesInitialized,2) + DO i1 = LBOUND(OutData%areStatesInitialized,1), UBOUND(OutData%areStatesInitialized,1) + OutData%areStatesInitialized(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%areStatesInitialized(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%tau1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tau2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! n 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%n)) DEALLOCATE(OutData%n) + ALLOCATE(OutData%n(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%n.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%n,2), UBOUND(OutData%n,2) + DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) + OutData%n(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%xdot,1) + i1_u = UBOUND(OutData%xdot,1) + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 DBEMT_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END SUBROUTINE DBEMT_UnPackOtherState + + SUBROUTINE DBEMT_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(DBEMT_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 = 'DBEMT_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%FirstWarn_tau1 = SrcMiscData%FirstWarn_tau1 + END SUBROUTINE DBEMT_CopyMisc + + SUBROUTINE DBEMT_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(DBEMT_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DBEMT_DestroyMisc + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 ! FirstWarn_tau1 + 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%FirstWarn_tau1, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DBEMT_PackMisc + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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%FirstWarn_tau1 = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_tau1) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DBEMT_UnPackMisc + + SUBROUTINE DBEMT_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_ParameterType), INTENT(IN) :: SrcParamData + TYPE(DBEMT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%lin_nx = SrcParamData%lin_nx + DstParamData%NumBlades = SrcParamData%NumBlades + DstParamData%NumNodes = SrcParamData%NumNodes + DstParamData%k_0ye = SrcParamData%k_0ye + DstParamData%tau1_const = SrcParamData%tau1_const +IF (ALLOCATED(SrcParamData%spanRatio)) THEN + i1_l = LBOUND(SrcParamData%spanRatio,1) + i1_u = UBOUND(SrcParamData%spanRatio,1) + i2_l = LBOUND(SrcParamData%spanRatio,2) + i2_u = UBOUND(SrcParamData%spanRatio,2) + IF (.NOT. ALLOCATED(DstParamData%spanRatio)) THEN + ALLOCATE(DstParamData%spanRatio(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%spanRatio.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%spanRatio = SrcParamData%spanRatio +ENDIF + DstParamData%DBEMT_Mod = SrcParamData%DBEMT_Mod + END SUBROUTINE DBEMT_CopyParam + + SUBROUTINE DBEMT_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(DBEMT_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%spanRatio)) THEN + DEALLOCATE(ParamData%spanRatio) +ENDIF + END SUBROUTINE DBEMT_DestroyParam + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! lin_nx + Int_BufSz = Int_BufSz + 1 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumNodes + Re_BufSz = Re_BufSz + 1 ! k_0ye + Re_BufSz = Re_BufSz + 1 ! tau1_const + Int_BufSz = Int_BufSz + 1 ! spanRatio allocated yes/no + IF ( ALLOCATED(InData%spanRatio) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! spanRatio upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%spanRatio) ! spanRatio + END IF + Int_BufSz = Int_BufSz + 1 ! DBEMT_Mod + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%lin_nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumNodes + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k_0ye + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tau1_const + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%spanRatio) ) 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%spanRatio,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%spanRatio,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%spanRatio,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%spanRatio,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%spanRatio,2), UBOUND(InData%spanRatio,2) + DO i1 = LBOUND(InData%spanRatio,1), UBOUND(InData%spanRatio,1) + ReKiBuf(Re_Xferred) = InData%spanRatio(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%DBEMT_Mod + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DBEMT_PackParam + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%lin_nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%k_0ye = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tau1_const = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! spanRatio 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%spanRatio)) DEALLOCATE(OutData%spanRatio) + ALLOCATE(OutData%spanRatio(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%spanRatio.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%spanRatio,2), UBOUND(OutData%spanRatio,2) + DO i1 = LBOUND(OutData%spanRatio,1), UBOUND(OutData%spanRatio,1) + OutData%spanRatio(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%DBEMT_Mod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DBEMT_UnPackParam + + SUBROUTINE DBEMT_CopyElementInputType( SrcElementInputTypeData, DstElementInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_ElementInputType), INTENT(IN) :: SrcElementInputTypeData + TYPE(DBEMT_ElementInputType), INTENT(INOUT) :: DstElementInputTypeData + 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 = 'DBEMT_CopyElementInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElementInputTypeData%vind_s = SrcElementInputTypeData%vind_s + DstElementInputTypeData%vind_s_dot = SrcElementInputTypeData%vind_s_dot + DstElementInputTypeData%spanRatio = SrcElementInputTypeData%spanRatio + END SUBROUTINE DBEMT_CopyElementInputType + + SUBROUTINE DBEMT_DestroyElementInputType( ElementInputTypeData, ErrStat, ErrMsg ) + TYPE(DBEMT_ElementInputType), INTENT(INOUT) :: ElementInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyElementInputType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DBEMT_DestroyElementInputType + + SUBROUTINE DBEMT_PackElementInputType( 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(DBEMT_ElementInputType), 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 = 'DBEMT_PackElementInputType' + ! 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%vind_s) ! vind_s + Re_BufSz = Re_BufSz + SIZE(InData%vind_s_dot) ! vind_s_dot + Re_BufSz = Re_BufSz + 1 ! spanRatio + 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%vind_s,1), UBOUND(InData%vind_s,1) + ReKiBuf(Re_Xferred) = InData%vind_s(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%vind_s_dot,1), UBOUND(InData%vind_s_dot,1) + ReKiBuf(Re_Xferred) = InData%vind_s_dot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%spanRatio + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_PackElementInputType + + SUBROUTINE DBEMT_UnPackElementInputType( 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(DBEMT_ElementInputType), 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 = 'DBEMT_UnPackElementInputType' + ! 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%vind_s,1) + i1_u = UBOUND(OutData%vind_s,1) + DO i1 = LBOUND(OutData%vind_s,1), UBOUND(OutData%vind_s,1) + OutData%vind_s(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%vind_s_dot,1) + i1_u = UBOUND(OutData%vind_s_dot,1) + DO i1 = LBOUND(OutData%vind_s_dot,1), UBOUND(OutData%vind_s_dot,1) + OutData%vind_s_dot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%spanRatio = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DBEMT_UnPackElementInputType + + SUBROUTINE DBEMT_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_InputType), INTENT(IN) :: SrcInputData + TYPE(DBEMT_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 = 'DBEMT_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%AxInd_disk = SrcInputData%AxInd_disk + DstInputData%Un_disk = SrcInputData%Un_disk + DstInputData%R_disk = SrcInputData%R_disk +IF (ALLOCATED(SrcInputData%element)) THEN + i1_l = LBOUND(SrcInputData%element,1) + i1_u = UBOUND(SrcInputData%element,1) + i2_l = LBOUND(SrcInputData%element,2) + i2_u = UBOUND(SrcInputData%element,2) + IF (.NOT. ALLOCATED(DstInputData%element)) THEN + ALLOCATE(DstInputData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcInputData%element,2), UBOUND(SrcInputData%element,2) + DO i1 = LBOUND(SrcInputData%element,1), UBOUND(SrcInputData%element,1) + CALL DBEMT_Copyelementinputtype( SrcInputData%element(i1,i2), DstInputData%element(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF + END SUBROUTINE DBEMT_CopyInput + + SUBROUTINE DBEMT_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(DBEMT_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%element)) THEN +DO i2 = LBOUND(InputData%element,2), UBOUND(InputData%element,2) +DO i1 = LBOUND(InputData%element,1), UBOUND(InputData%element,1) + CALL DBEMT_Destroyelementinputtype( InputData%element(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(InputData%element) +ENDIF + END SUBROUTINE DBEMT_DestroyInput + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + Re_BufSz = Re_BufSz + 1 ! AxInd_disk + Re_BufSz = Re_BufSz + 1 ! Un_disk + Re_BufSz = Re_BufSz + 1 ! R_disk + Int_BufSz = Int_BufSz + 1 ! element allocated yes/no + IF ( ALLOCATED(InData%element) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! element upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + Int_BufSz = Int_BufSz + 3 ! element: size of buffers for each call to pack subtype + CALL DBEMT_Packelementinputtype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! element + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! element + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! element + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! element + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + 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%AxInd_disk + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Un_disk + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%R_disk + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%element) ) 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%element,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%element,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + CALL DBEMT_Packelementinputtype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! element + 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 DO + END IF + END SUBROUTINE DBEMT_PackInput + + SUBROUTINE DBEMT_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(DBEMT_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 = 'DBEMT_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 + OutData%AxInd_disk = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Un_disk = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%R_disk = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! element 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%element)) DEALLOCATE(OutData%element) + ALLOCATE(OutData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%element,2), UBOUND(OutData%element,2) + DO i1 = LBOUND(OutData%element,1), UBOUND(OutData%element,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 DBEMT_Unpackelementinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%element(i1,i2), ErrStat2, ErrMsg2 ) ! element + 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 DO + END DO + END IF + END SUBROUTINE DBEMT_UnPackInput + + SUBROUTINE DBEMT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DBEMT_OutputType), INTENT(IN) :: SrcOutputData + TYPE(DBEMT_OutputType), INTENT(INOUT) :: DstOutputData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%vind)) THEN + i1_l = LBOUND(SrcOutputData%vind,1) + i1_u = UBOUND(SrcOutputData%vind,1) + i2_l = LBOUND(SrcOutputData%vind,2) + i2_u = UBOUND(SrcOutputData%vind,2) + i3_l = LBOUND(SrcOutputData%vind,3) + i3_u = UBOUND(SrcOutputData%vind,3) + IF (.NOT. ALLOCATED(DstOutputData%vind)) THEN + ALLOCATE(DstOutputData%vind(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%vind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%vind = SrcOutputData%vind +ENDIF + END SUBROUTINE DBEMT_CopyOutput + + SUBROUTINE DBEMT_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(DBEMT_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%vind)) THEN + DEALLOCATE(OutputData%vind) +ENDIF + END SUBROUTINE DBEMT_DestroyOutput + + SUBROUTINE DBEMT_PackOutput( 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(DBEMT_OutputType), 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 = 'DBEMT_PackOutput' + ! 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 ! vind allocated yes/no + IF ( ALLOCATED(InData%vind) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! vind upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%vind) ! vind + 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%vind) ) 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%vind,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vind,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vind,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vind,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vind,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vind,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%vind,3), UBOUND(InData%vind,3) + DO i2 = LBOUND(InData%vind,2), UBOUND(InData%vind,2) + DO i1 = LBOUND(InData%vind,1), UBOUND(InData%vind,1) + ReKiBuf(Re_Xferred) = InData%vind(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE DBEMT_PackOutput + + SUBROUTINE DBEMT_UnPackOutput( 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(DBEMT_OutputType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_UnPackOutput' + ! 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 ! vind 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%vind)) DEALLOCATE(OutData%vind) + ALLOCATE(OutData%vind(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%vind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%vind,3), UBOUND(OutData%vind,3) + DO i2 = LBOUND(OutData%vind,2), UBOUND(OutData%vind,2) + DO i1 = LBOUND(OutData%vind,1), UBOUND(OutData%vind,1) + OutData%vind(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE DBEMT_UnPackOutput + + + SUBROUTINE DBEMT_ElementInputType_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) ElementInputType u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u(:) ! ElementInputType at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the ElementInputTypes + TYPE(DBEMT_ElementInputType), INTENT(INOUT) :: u_out ! ElementInputType at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_ElementInputType_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL DBEMT_CopyElementInputType(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL DBEMT_ElementInputType_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL DBEMT_ElementInputType_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE DBEMT_ElementInputType_ExtrapInterp + + + SUBROUTINE DBEMT_ElementInputType_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) ElementInputType u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u1 ! ElementInputType at t1 > t2 + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u2 ! ElementInputType at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the ElementInputTypes + TYPE(DBEMT_ElementInputType), INTENT(INOUT) :: u_out ! ElementInputType at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the ElementInputTypes + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_ElementInputType_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(u_out%vind_s,1),UBOUND(u_out%vind_s,1) + b = -(u1%vind_s(i1) - u2%vind_s(i1)) + u_out%vind_s(i1) = u1%vind_s(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%vind_s_dot,1),UBOUND(u_out%vind_s_dot,1) + b = -(u1%vind_s_dot(i1) - u2%vind_s_dot(i1)) + u_out%vind_s_dot(i1) = u1%vind_s_dot(i1) + b * ScaleFactor + END DO + b = -(u1%spanRatio - u2%spanRatio) + u_out%spanRatio = u1%spanRatio + b * ScaleFactor + END SUBROUTINE DBEMT_ElementInputType_ExtrapInterp1 + + + SUBROUTINE DBEMT_ElementInputType_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) ElementInputType u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u1 ! ElementInputType at t1 > t2 > t3 + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u2 ! ElementInputType at t2 > t3 + TYPE(DBEMT_ElementInputType), INTENT(IN) :: u3 ! ElementInputType at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the ElementInputTypes + TYPE(DBEMT_ElementInputType), INTENT(INOUT) :: u_out ! ElementInputType at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the ElementInputTypes + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_ElementInputType_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(u_out%vind_s,1),UBOUND(u_out%vind_s,1) + b = (t(3)**2*(u1%vind_s(i1) - u2%vind_s(i1)) + t(2)**2*(-u1%vind_s(i1) + u3%vind_s(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%vind_s(i1) + t(3)*u2%vind_s(i1) - t(2)*u3%vind_s(i1) ) * scaleFactor + u_out%vind_s(i1) = u1%vind_s(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%vind_s_dot,1),UBOUND(u_out%vind_s_dot,1) + b = (t(3)**2*(u1%vind_s_dot(i1) - u2%vind_s_dot(i1)) + t(2)**2*(-u1%vind_s_dot(i1) + u3%vind_s_dot(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%vind_s_dot(i1) + t(3)*u2%vind_s_dot(i1) - t(2)*u3%vind_s_dot(i1) ) * scaleFactor + u_out%vind_s_dot(i1) = u1%vind_s_dot(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%spanRatio - u2%spanRatio) + t(2)**2*(-u1%spanRatio + u3%spanRatio))* scaleFactor + c = ( (t(2)-t(3))*u1%spanRatio + t(3)*u2%spanRatio - t(2)*u3%spanRatio ) * scaleFactor + u_out%spanRatio = u1%spanRatio + b + c * t_out + END SUBROUTINE DBEMT_ElementInputType_ExtrapInterp2 + + + SUBROUTINE DBEMT_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(DBEMT_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(DBEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL DBEMT_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL DBEMT_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL DBEMT_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE DBEMT_Input_ExtrapInterp + + + SUBROUTINE DBEMT_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(DBEMT_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(DBEMT_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(DBEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%AxInd_disk - u2%AxInd_disk) + u_out%AxInd_disk = u1%AxInd_disk + b * ScaleFactor + b = -(u1%Un_disk - u2%Un_disk) + u_out%Un_disk = u1%Un_disk + b * ScaleFactor + b = -(u1%R_disk - u2%R_disk) + u_out%R_disk = u1%R_disk + b * ScaleFactor +IF (ALLOCATED(u_out%element) .AND. ALLOCATED(u1%element)) THEN + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + DO i1 = LBOUND(u_out%element(i01,i02)%vind_s,1),UBOUND(u_out%element(i01,i02)%vind_s,1) + b = -(u1%element(i01,i02)%vind_s(i1) - u2%element(i01,i02)%vind_s(i1)) + u_out%element(i01,i02)%vind_s(i1) = u1%element(i01,i02)%vind_s(i1) + b * ScaleFactor + END DO + ENDDO + ENDDO + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + DO i1 = LBOUND(u_out%element(i01,i02)%vind_s_dot,1),UBOUND(u_out%element(i01,i02)%vind_s_dot,1) + b = -(u1%element(i01,i02)%vind_s_dot(i1) - u2%element(i01,i02)%vind_s_dot(i1)) + u_out%element(i01,i02)%vind_s_dot(i1) = u1%element(i01,i02)%vind_s_dot(i1) + b * ScaleFactor + END DO + ENDDO + ENDDO + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + b = -(u1%element(i01,i02)%spanRatio - u2%element(i01,i02)%spanRatio) + u_out%element(i01,i02)%spanRatio = u1%element(i01,i02)%spanRatio + b * ScaleFactor + ENDDO + ENDDO +END IF ! check if allocated + END SUBROUTINE DBEMT_Input_ExtrapInterp1 + + + SUBROUTINE DBEMT_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(DBEMT_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(DBEMT_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(DBEMT_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(DBEMT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%AxInd_disk - u2%AxInd_disk) + t(2)**2*(-u1%AxInd_disk + u3%AxInd_disk))* scaleFactor + c = ( (t(2)-t(3))*u1%AxInd_disk + t(3)*u2%AxInd_disk - t(2)*u3%AxInd_disk ) * scaleFactor + u_out%AxInd_disk = u1%AxInd_disk + b + c * t_out + b = (t(3)**2*(u1%Un_disk - u2%Un_disk) + t(2)**2*(-u1%Un_disk + u3%Un_disk))* scaleFactor + c = ( (t(2)-t(3))*u1%Un_disk + t(3)*u2%Un_disk - t(2)*u3%Un_disk ) * scaleFactor + u_out%Un_disk = u1%Un_disk + b + c * t_out + b = (t(3)**2*(u1%R_disk - u2%R_disk) + t(2)**2*(-u1%R_disk + u3%R_disk))* scaleFactor + c = ( (t(2)-t(3))*u1%R_disk + t(3)*u2%R_disk - t(2)*u3%R_disk ) * scaleFactor + u_out%R_disk = u1%R_disk + b + c * t_out +IF (ALLOCATED(u_out%element) .AND. ALLOCATED(u1%element)) THEN + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + DO i1 = LBOUND(u_out%element(i01,i02)%vind_s,1),UBOUND(u_out%element(i01,i02)%vind_s,1) + b = (t(3)**2*(u1%element(i01,i02)%vind_s(i1) - u2%element(i01,i02)%vind_s(i1)) + t(2)**2*(-u1%element(i01,i02)%vind_s(i1) + u3%element(i01,i02)%vind_s(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%element(i01,i02)%vind_s(i1) + t(3)*u2%element(i01,i02)%vind_s(i1) - t(2)*u3%element(i01,i02)%vind_s(i1) ) * scaleFactor + u_out%element(i01,i02)%vind_s(i1) = u1%element(i01,i02)%vind_s(i1) + b + c * t_out + END DO + ENDDO + ENDDO + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + DO i1 = LBOUND(u_out%element(i01,i02)%vind_s_dot,1),UBOUND(u_out%element(i01,i02)%vind_s_dot,1) + b = (t(3)**2*(u1%element(i01,i02)%vind_s_dot(i1) - u2%element(i01,i02)%vind_s_dot(i1)) + t(2)**2*(-u1%element(i01,i02)%vind_s_dot(i1) + u3%element(i01,i02)%vind_s_dot(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%element(i01,i02)%vind_s_dot(i1) + t(3)*u2%element(i01,i02)%vind_s_dot(i1) - t(2)*u3%element(i01,i02)%vind_s_dot(i1) ) * scaleFactor + u_out%element(i01,i02)%vind_s_dot(i1) = u1%element(i01,i02)%vind_s_dot(i1) + b + c * t_out + END DO + ENDDO + ENDDO + DO i02 = LBOUND(u_out%element,2),UBOUND(u_out%element,2) + DO i01 = LBOUND(u_out%element,1),UBOUND(u_out%element,1) + b = (t(3)**2*(u1%element(i01,i02)%spanRatio - u2%element(i01,i02)%spanRatio) + t(2)**2*(-u1%element(i01,i02)%spanRatio + u3%element(i01,i02)%spanRatio))* scaleFactor + c = ( (t(2)-t(3))*u1%element(i01,i02)%spanRatio + t(3)*u2%element(i01,i02)%spanRatio - t(2)*u3%element(i01,i02)%spanRatio ) * scaleFactor + u_out%element(i01,i02)%spanRatio = u1%element(i01,i02)%spanRatio + b + c * t_out + ENDDO + ENDDO +END IF ! check if allocated + END SUBROUTINE DBEMT_Input_ExtrapInterp2 + + + SUBROUTINE DBEMT_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(DBEMT_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(DBEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL DBEMT_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL DBEMT_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL DBEMT_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE DBEMT_Output_ExtrapInterp + + + SUBROUTINE DBEMT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(DBEMT_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(DBEMT_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(DBEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%vind) .AND. ALLOCATED(y1%vind)) THEN + DO i3 = LBOUND(y_out%vind,3),UBOUND(y_out%vind,3) + DO i2 = LBOUND(y_out%vind,2),UBOUND(y_out%vind,2) + DO i1 = LBOUND(y_out%vind,1),UBOUND(y_out%vind,1) + b = -(y1%vind(i1,i2,i3) - y2%vind(i1,i2,i3)) + y_out%vind(i1,i2,i3) = y1%vind(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated + END SUBROUTINE DBEMT_Output_ExtrapInterp1 + + + SUBROUTINE DBEMT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(DBEMT_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(DBEMT_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(DBEMT_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(DBEMT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DBEMT_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%vind) .AND. ALLOCATED(y1%vind)) THEN + DO i3 = LBOUND(y_out%vind,3),UBOUND(y_out%vind,3) + DO i2 = LBOUND(y_out%vind,2),UBOUND(y_out%vind,2) + DO i1 = LBOUND(y_out%vind,1),UBOUND(y_out%vind,1) + b = (t(3)**2*(y1%vind(i1,i2,i3) - y2%vind(i1,i2,i3)) + t(2)**2*(-y1%vind(i1,i2,i3) + y3%vind(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%vind(i1,i2,i3) + t(3)*y2%vind(i1,i2,i3) - t(2)*y3%vind(i1,i2,i3) ) * scaleFactor + y_out%vind(i1,i2,i3) = y1%vind(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated + END SUBROUTINE DBEMT_Output_ExtrapInterp2 + +END MODULE DBEMT_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/FVW.f90 b/OpenFAST/modules/aerodyn/src/FVW.f90 new file mode 100644 index 000000000..4a984e362 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW.f90 @@ -0,0 +1,1181 @@ +!> +!! +!! Abbreviations: +!! - FVW: Free Vortex Wake +!! - LL : Lifting Line +!! - CP : Control point +!! - NW : Near Wake +!! - FW : Far Wake +!! +module FVW + use NWTC_Library + use FVW_Types + use FVW_Subs + use FVW_IO + use FVW_Wings + use FVW_BiotSavart + use FVW_Tests + use AirFoilInfo + + IMPLICIT NONE + + PRIVATE + + type(ProgDesc), parameter :: FVW_Ver = ProgDesc( 'FVW', '', '' ) + + public :: FVW_Init ! Initialization routine + public :: FVW_End + + public :: FVW_CalcOutput + public :: FVW_UpdateStates + + ! parameter for deciding if enough time has elapsed (Wake calculation, and vtk output) + real(DbKi), parameter :: OneMinusEpsilon = 1 - 10000*EPSILON(1.0_DbKi) + +contains + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +subroutine FVW_Init(AFInfo, InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + use OMP_LIB ! wrap with #ifdef _OPENMP if this causes an issue + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data, temporary, for UA.. + type(FVW_InitInputType), intent(inout) :: InitInp !< Input data for initialization routine (inout so we can use MOVE_ALLOC) + type(FVW_InputType), intent( out) :: u !< An initial guess for the input; input mesh must be defined + type(FVW_ParameterType), intent( out) :: p !< Parameters + type(FVW_ContinuousStateType), intent( out) :: x !< Initial continuous states + type(FVW_DiscreteStateType), intent( out) :: xd !< Initial discrete states + type(FVW_ConstraintStateType), intent( out) :: z !< Initial guess of the constraint states + type(FVW_OtherStateType), intent( out) :: OtherState !< Initial other states + type(FVW_OutputType), intent( out) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + type(FVW_MiscVarType), intent( out) :: m !< Initial misc/optimization variables + real(DbKi), intent(inout) :: interval !< Coupling interval in seconds: the rate that + !! (1) FVW_UpdateStates() is called in loose coupling & + !! (2) FVW_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + type(FVW_InitOutputType), intent( out) :: InitOut !< Output for initialization routine + 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 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + integer(IntKi) :: UnEcho ! Unit number for the echo file + character(*), parameter :: RoutineName = 'FVW_Init' + type(FVW_InputFile) :: InputFileData !< Data stored in the module's input file + character(len=1054) :: DirName + + ! Initialize variables for this routine + ErrStat = ErrID_None + ErrMsg = "" + UnEcho = -1 + + ! Initialize the NWTC Subroutine Library + call NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + call DispNVD( FVW_Ver ) + ! Display convenient info to screen, until this is one day displayed by OpenFAST + call getcwd(DirName) + call WrScr(' - Directory: '//trim(DirName)) + call WrScr(' - RootName: '//trim(InitInp%RootName)) +#ifdef _OPENMP + call WrScr(' - Compiled with OpenMP') + !$OMP PARALLEL default(shared) + if (omp_get_thread_num()==0) then + call WrScr(' Number of threads: '//trim(Num2LStr(omp_get_num_threads()))//'/'//trim(Num2LStr(omp_get_max_threads()))) + endif + !$OMP END PARALLEL +#else + call WrScr(' - No OpenMP support') +#endif + if (DEV_VERSION) then + CALL FVW_RunTests(ErrStat2, ErrMsg2); if (Failed()) return + endif + + ! Set Parameters and *Misc* from inputs + CALL FVW_SetParametersFromInputs(InitInp, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Read and parse the input file here to get other parameters and info + CALL FVW_ReadInputFile(InitInp%FVWFileName, p, InputFileData, ErrStat2, ErrMsg2); if(Failed()) return + + ! Trigger required before allocations + p%nNWMax = max(InputFileData%nNWPanels,0)+1 ! +1 since LL panel included in NW + p%nFWMax = max(InputFileData%nFWPanels,0) + p%nFWFree = max(InputFileData%nFWPanelsFree,0) + p%DTfvw = InputFileData%DTfvw + p%DTvtk = InputFileData%DTvtk + + ! Initialize Misc Vars (may depend on input file) + CALL FVW_InitMiscVars( p, m, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Move the InitInp%WingsMesh to u + CALL MOVE_ALLOC( InitInp%WingsMesh, u%WingsMesh ) ! Move from InitInp to u + +!NOTE: We do not have the windspeed until after the FVW initialization (IfW is not initialized until after AD15) + ! Wind Speed hack, TODO temporary NOTE: it is still needed? + m%Vwnd_LL(:,:,:) = 0 + m%Vwnd_NW(:,:,:,:) = 0 + m%Vwnd_FW(:,:,:,:) = 0 + + ! This mesh is passed in as a cousin of the BladeMotion mesh. + CALL Wings_Panelling_Init(u%WingsMesh, p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Set parameters from InputFileData (need Misc allocated) + CALL FVW_SetParametersFromInputFile(InputFileData, p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Initialize Misc Vars (after input file params) + CALL FVW_InitMiscVarsPostParam( p, m, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Initialize States Vars + CALL FVW_InitStates( x, p, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Initialize Constraints Vars + CALL FVW_InitConstraint( z, p, m, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Panelling wings based on initial input mesh provided + ! This mesh is now a cousin of the BladeMotion mesh from AD. + CALL Wings_Panelling (u%WingsMesh, p, m, ErrStat2, ErrMsg2); if(Failed()) return + CALL FVW_InitRegularization(p, m, ErrStat2, ErrMsg2); if(Failed()) return + CALL FVW_ToString(p, m) ! Print to screen + + ! Mapping NW and FW (purely for esthetics, and maybe wind) ! TODO, just points + call Map_LL_NW(p, m, z, x, 1.0_ReKi, ErrStat2, ErrMsg2); if(Failed()) return + call Map_NW_FW(p, m, z, x, ErrStat2, ErrMsg2); if(Failed()) return + + ! Initialize output + CALL FVW_Init_Y( p, u, y, ErrStat2, ErrMsg2); if(Failed()) return + + ! Returned guessed locations where wind will be required + CALL SetRequestedWindPoints(m%r_wind, x, p, m ) + ! Return anything in FVW_InitOutput that should be passed back to the calling code here + + + ! --- UA + ! NOTE: quick and dirty since this should belong to AD + interval = InitInp%DTAero ! important, UA, needs proper interval + call UA_Init_Wrapper(AFInfo, InitInp, interval, p, x, xd, OtherState, m, ErrStat2, ErrMsg2); if (Failed()) return + + ! Framework types unused + Interval = InitInp%DTAero + OtherState%NULL = 0 + xd%NULL = 0 + InitOut%NULL = 0 +CONTAINS + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_Init') + Failed = ErrStat >= AbortErrLev + !if (Failed) call CleanUp() + end function Failed + +end subroutine FVW_Init + +! ============================================================================== +subroutine FVW_InitMiscVars( p, m, ErrStat, ErrMsg ) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: nMax ! Total number of wind points possible + integer(IntKi) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'FVW_InitMiscVars' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + m%FirstCall = .True. + m%nNW = iNWStart-1 ! Number of active nearwake panels + m%nFW = 0 ! Number of active farwake panels + m%iStep = 0 ! Current step number + m%VTKStep = -1 ! Counter of VTK outputs + m%VTKlastTime = -HUGE(1.0_DbKi) + m%tSpent = 0 + + call AllocAry( m%LE , 3 , p%nSpan+1 , p%nWings, 'Leading Edge Points', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%LE = -999999_ReKi; + call AllocAry( m%TE , 3 , p%nSpan+1 , p%nWings, 'TrailingEdge Points', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%TE = -999999_ReKi; + call AllocAry( m%s_LL , p%nSpan+1 , p%nWings, 'Spanwise coord LL ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%s_LL= -999999_ReKi; + call AllocAry( m%chord_LL , p%nSpan+1 , p%nWings, 'Chord on LL ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%chord_LL= -999999_ReKi; + call AllocAry( m%PitchAndTwist , p%nSpan+1 , p%nWings, 'Pitch and twist ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%PitchAndTwist= -999999_ReKi; + call AllocAry( m%alpha_LL, p%nSpan , p%nWings, 'Wind on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%alpha_LL= -999999_ReKi; + call AllocAry( m%Vreln_LL, p%nSpan , p%nWings, 'Wind on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vreln_LL = -999999_ReKi; + ! Variables at control points/elements + call AllocAry( m%Gamma_LL, p%nSpan , p%nWings, 'Lifting line Circulation', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Gamma_LL = -999999_ReKi; + call AllocAry( m%chord_CP_LL , p%nSpan , p%nWings, 'Chord on CP LL ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%chord_CP_LL= -999999_ReKi; + call AllocAry( m%s_CP_LL , p%nSpan , p%nWings, 'Spanwise coord CPll', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%s_CP_LL= -999999_ReKi; + call AllocAry( m%CP_LL , 3 , p%nSpan , p%nWings, 'Control points LL ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%CP_LL= -999999_ReKi; + call AllocAry( m%Tang , 3 , p%nSpan , p%nWings, 'Tangential vector ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Tang= -999999_ReKi; + call AllocAry( m%Norm , 3 , p%nSpan , p%nWings, 'Normal vector ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Norm= -999999_ReKi; + call AllocAry( m%Orth , 3 , p%nSpan , p%nWings, 'Orthogonal vector ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Orth= -999999_ReKi; + call AllocAry( m%dl , 3 , p%nSpan , p%nWings, 'Orthogonal vector ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%dl= -999999_ReKi; + call AllocAry( m%Area , p%nSpan , p%nWings, 'LL Panel area ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Area = -999999_ReKi; + call AllocAry( m%diag_LL , p%nSpan , p%nWings, 'LL Panel diagonals ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%diag_LL = -999999_ReKi; + call AllocAry( m%Vind_LL , 3 , p%nSpan , p%nWings, 'Vind on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vind_LL= -999999_ReKi; + call AllocAry( m%Vtot_LL , 3 , p%nSpan , p%nWings, 'Vtot on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vtot_LL= -999999_ReKi; + call AllocAry( m%Vstr_LL , 3 , p%nSpan , p%nWings, 'Vstr on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vstr_LL= -999999_ReKi; + call AllocAry( m%Vwnd_LL , 3 , p%nSpan , p%nWings, 'Wind on CP ll ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vwnd_LL= -999999_ReKi; + ! Variables at panels points + call AllocAry( m%r_LL , 3 , p%nSpan+1 , 2 , p%nWings, 'Lifting Line Panels', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%r_LL= -999999_ReKi; + call AllocAry( m%Vwnd_NW , 3 , p%nSpan+1 ,p%nNWMax+1, p%nWings, 'Wind on NW ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vwnd_NW= -999_ReKi; + call AllocAry( m%Vwnd_FW , 3 , FWnSpan+1 ,p%nFWMax+1, p%nWings, 'Wind on FW ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vwnd_FW= -999_ReKi; + call AllocAry( m%Vind_NW , 3 , p%nSpan+1 ,p%nNWMax+1, p%nWings, 'Vind on NW ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vind_NW= -999_ReKi; + call AllocAry( m%Vind_FW , 3 , FWnSpan+1 ,p%nFWMax+1, p%nWings, 'Vind on FW ', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%Vind_FW= -999_ReKi; + call AllocAry( m%dxdt_NW , 3 , p%nSpan+1 , p%nNWMax+1, p%nWings, 'NW dxdt' , ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%dxdt_NW = -999999_ReKi; + call AllocAry( m%dxdt_FW , 3 , FWnSpan+1 , p%nFWMax+1, p%nWings, 'FW dxdt' , ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%dxdt_FW = -999999_ReKi; + ! Variables for optimizing outputs at blade nodes + call AllocAry( m%BN_UrelWind_s, 3, p%nSpan+1 , p%nWings, 'Relative wind in section coordinates', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_UrelWind_s= -999999_ReKi; + call AllocAry( m%BN_AxInd , p%nSpan+1 , p%nWings, 'Axial induction', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_AxInd = -999999_ReKi; + call AllocAry( m%BN_TanInd , p%nSpan+1 , p%nWings, 'Tangential induction', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_TanInd = -999999_ReKi; + call AllocAry( m%BN_Vrel , p%nSpan+1 , p%nWings, 'Relative velocity', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Vrel = -999999_ReKi; + call AllocAry( m%BN_alpha , p%nSpan+1 , p%nWings, 'Angle of attack', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_alpha = -999999_ReKi; + call AllocAry( m%BN_phi , p%nSpan+1 , p%nWings, 'angle between the plane local wind dir', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_phi = -999999_ReKi; + call AllocAry( m%BN_Re , p%nSpan+1 , p%nWings, 'Reynolds number', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Re = -999999_ReKi; + call AllocAry( m%BN_Cl_Static , p%nSpan+1 , p%nWings, 'Coefficient lift - no UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cl_Static = -999999_ReKi; + call AllocAry( m%BN_Cd_Static , p%nSpan+1 , p%nWings, 'Coefficient drag - no UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cd_Static = -999999_ReKi; + call AllocAry( m%BN_Cm_Static , p%nSpan+1 , p%nWings, 'Coefficient moment - no UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cm_Static = -999999_ReKi; + call AllocAry( m%BN_Cl , p%nSpan+1 , p%nWings, 'Coefficient lift - with UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cl = -999999_ReKi; + call AllocAry( m%BN_Cd , p%nSpan+1 , p%nWings, 'Coefficient drag - with UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cd = -999999_ReKi; + call AllocAry( m%BN_Cm , p%nSpan+1 , p%nWings, 'Coefficient moment - with UA', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cm = -999999_ReKi; + call AllocAry( m%BN_Cx , p%nSpan+1 , p%nWings, 'Coefficient normal (to plane)', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cx = -999999_ReKi; + call AllocAry( m%BN_Cy , p%nSpan+1 , p%nWings, 'Coefficient tangential (to plane)', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%BN_Cy = -999999_ReKi; + + + ! Wind request points + nMax = 0 + nMax = nMax + p%nSpan * p%nWings ! Lifting line Control Points + nMax = nMax + (p%nSpan+1) * (p%nNWMax+1) * p%nWings ! Nearwake points + nMax = nMax + (FWnSpan+1) * (p%nFWMax+1) * p%nWings ! Far wake points + call AllocAry( m%r_wind, 3, nMax, 'Requested wind points', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ) + m%r_wind = 0.0_ReKi ! set to zero so InflowWind can shortcut calculations + m%OldWakeTime = -HUGE(1.0_DbKi) + ! Temporary UA + call AllocAry( m%Vwnd_ND, 3, p%nSpan+1, p%nWings, 'Vwnd_ND', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ); m%TE = -999999_ReKi; + +end subroutine FVW_InitMiscVars +! ============================================================================== +subroutine FVW_InitMiscVarsPostParam( p, m, ErrStat, ErrMsg ) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'FVW_InitMiscVarsPostParam' + integer(IntKi) :: nSeg, nSegP, nSegNW !< Total number of segments after packing + integer(IntKi) :: nCPs !< Total number of control points + logical :: bMirror + ErrStat = ErrID_None + ErrMsg = "" + ! --- Counting maximum number of segments and Control Points expected for the whole simulation + call CountSegments(p, p%nNWMax, p%nFWMax, 1, nSeg, nSegP, nSegNW) + nCPs = CountCPs(p, p%nNWMax, p%nFWFree) + + bMirror = p%ShearModel==idShearMirror ! Whether or not we mirror the vorticity wrt ground + if (bMirror) then + nSeg = nSeg*2 + nSegP = nSegP*2 + endif + call AllocAry( m%SegConnct, 4, nSeg , 'SegConnct' , ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%SegConnct = -999; + call AllocAry( m%SegPoints, 3, nSegP, 'SegPoints' , ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%SegPoints = -999999_ReKi; + call AllocAry( m%SegGamma , nSeg, 'SegGamma' , ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%SegGamma = -999999_ReKi; + call AllocAry( m%SegEpsilon, nSeg, 'SegEpsilon', ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%SegEpsilon= -999999_ReKi; + + call AllocAry( m%CPs , 3, nCPs, 'CPs' , ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%CPs= -999999_ReKi; + call AllocAry( m%Uind , 3, nCPs, 'Uind' , ErrStat2, ErrMsg2 );call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); m%Uind= -999999_ReKi; + +end subroutine FVW_InitMiscVarsPostParam +! ============================================================================== +subroutine FVW_InitStates( x, p, ErrStat, ErrMsg ) + type(FVW_ContinuousStateType), intent( out) :: x !< States + type(FVW_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) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'FVW_InitMiscVars' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + call AllocAry( x%Gamma_NW, p%nSpan , p%nNWMax , p%nWings, 'NW Panels Circulation', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_InitStates' ); + call AllocAry( x%Gamma_FW, FWnSpan , p%nFWMax , p%nWings, 'FW Panels Circulation', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_InitStates' ); + ! set x%r_NW and x%r_FW to (0,0,0) so that InflowWind can shortcut the calculations + call AllocAry( x%r_NW , 3, p%nSpan+1 , p%nNWMax+1, p%nWings, 'NW Panels Points' , ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_InitStates' ); + call AllocAry( x%r_FW , 3, FWnSpan+1 , p%nFWMax+1, p%nWings, 'FW Panels Points' , ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_InitStates' ); + !if (DEV_VERSION) then + ! x%r_NW = -9999999_ReKi; + ! x%r_FW = -9999999_ReKi; + ! x%Gamma_NW = -999999_ReKi; + ! x%Gamma_FW = -999999_ReKi; + !else + x%r_NW = 0.0_ReKi + x%r_FW = 0.0_ReKi + x%Gamma_NW = 0.0_ReKi ! First call of calcoutput, states might not be set + x%Gamma_FW = 0.0_ReKi ! NOTE, these values might be mapped from z%Gamma_LL at init + !endif + if (ErrStat >= AbortErrLev) return +end subroutine FVW_InitStates +! ============================================================================== +subroutine FVW_InitConstraint( z, p, m, ErrStat, ErrMsg ) + type(FVW_ConstraintStateType), intent( out) :: z !< Constraints + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'FVW_InitMiscVars' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! + call AllocAry( z%Gamma_LL, p%nSpan, p%nWings, 'Lifting line Circulation', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_InitConstraint' ); + !z%Gamma_LL = -999999_ReKi + z%Gamma_LL = 0.0_ReKi + + if (ErrStat >= AbortErrLev) return + if(.false.) print*,m%nNW ! unused var for now +end subroutine FVW_InitConstraint +! ============================================================================== +subroutine FVW_Init_Y( p, u, y, ErrStat, ErrMsg ) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_InputType), intent(inout) :: u !< An initial guess for the input; input mesh must be defined + type(FVW_OutputType), intent( out) :: y !< Constraints + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: nMax ! Total number of wind points possible + integer(IntKi) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + character(*), parameter :: RoutineName = 'FVW_Init_Y' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! + nMax = 0 + nMax = nMax + p%nSpan * p%nWings ! Lifting line Control Points + nMax = nMax + (p%nSpan+1) * (p%nNWMax+1) * p%nWings ! Nearwake points + nMax = nMax + (FWnSpan+1) * (p%nFWMax+1) * p%nWings ! Far wake points + + call AllocAry( u%V_wind, 3, nMax, 'Wind Velocity at points', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ) + call AllocAry( y%Vind , 3, p%nSpan+1, p%nWings, 'Induced velocity vector', ErrStat2, ErrMsg2 ); ! TODO potentially nSpan+1 for AD15 + !call AllocAry( y%Cl_KJ , 1, 1, 'Lift coefficient from circulation (Kutta-Joukowski)', ErrStat2, ErrMsg2 );call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName ) + if (ErrStat >= AbortErrLev) return + y%Vind = 0.0_ReKi + return +end subroutine FVW_Init_Y + + +! ============================================================================== +!> Setting parameters *and misc* from module inputs +SUBROUTINE FVW_SetParametersFromInputs( InitInp, p, ErrStat, ErrMsg ) + type(FVW_InitInputType), intent(inout) :: InitInp !< Input data for initialization routine (inout so we can use MOVE_ALLOC) + type(FVW_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 + character(1024) :: rootDir, baseName ! Simulation root dir and basename + !integer(IntKi) :: ErrStat2 + !character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'FVW_SetParametersFromInputs' + ErrStat = ErrID_None + ErrMsg = "" + ! + p%nWings = InitInp%NumBlades + p%nSpan = InitInp%numBladeNodes-1 ! NOTE: temporary limitation, all wings have the same nspan + p%DTaero = InitInp%DTaero ! AeroDyn Time step + p%KinVisc = InitInp%KinVisc ! Kinematic air viscosity + p%RootName = InitInp%RootName ! Rootname for outputs + call GetPath( p%RootName, rootDir, baseName ) + p%VTK_OutFileRoot = trim(rootDir) // 'vtk_fvw' ! Directory for VTK outputs + p%VTK_OutFileBase = trim(rootDir) // 'vtk_fvw' // PathSep // trim(baseName) ! Basename for VTK files + ! Set indexing to AFI tables -- this is set from the AD15 calling code. + call AllocAry(p%AFindx,size(InitInp%AFindx,1),size(InitInp%AFindx,2),'AFindx',ErrStat,ErrMsg) + p%AFindx = InitInp%AFindx ! Copying in case AD15 still needs these + + ! Set the Chord values + call move_alloc(InitInp%Chord, p%Chord) + +end subroutine FVW_SetParametersFromInputs +! ============================================================================== +!> +SUBROUTINE FVW_SetParametersFromInputFile( InputFileData, p, m, ErrStat, ErrMsg ) + type(FVW_InputFile), intent(in ) :: InputFileData !< Data stored in the module's input file + type(FVW_ParameterType), intent(inout) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Misc + 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 = "" + + ! Set parameters from input file + p%IntMethod = InputFileData%IntMethod + p%CirculationMethod = InputFileData%CirculationMethod + p%CircSolvConvCrit = InputFileData%CircSolvConvCrit + p%CircSolvRelaxation = InputFileData%CircSolvRelaxation + p%CircSolvMaxIter = InputFileData%CircSolvMaxIter + p%FreeWakeStart = InputFileData%FreeWakeStart + p%CircSolvPolar = InputFileData%CircSolvPolar + p%FullCirculationStart = InputFileData%FullCirculationStart + p%FWShedVorticity = InputFileData%FWShedVorticity + p%DiffusionMethod = InputFileData%DiffusionMethod + p%RegFunction = InputFileData%RegFunction + p%RegDeterMethod = InputFileData%RegDeterMethod + p%WakeRegMethod = InputFileData%WakeRegMethod + p%WakeRegParam = InputFileData%WakeRegParam + p%WingRegParam = InputFileData%WingRegParam + p%CoreSpreadEddyVisc = InputFileData%CoreSpreadEddyVisc + p%ShearModel = InputFileData%ShearModel + p%TwrShadowOnWake = InputFileData%TwrShadowOnWake + p%VelocityMethod = InputFileData%VelocityMethod + p%TreeBranchFactor = InputFileData%TreeBranchFactor + p%PartPerSegment = InputFileData%PartPerSegment + p%WrVTK = InputFileData%WrVTK + p%VTKBlades = min(InputFileData%VTKBlades,p%nWings) ! Note: allowing it to be negative for temporary hack + p%VTKCoord = InputFileData%VTKCoord + + if (allocated(p%PrescribedCirculation)) deallocate(p%PrescribedCirculation) + if (InputFileData%CirculationMethod==idCircPrescribed) then + call AllocAry( p%PrescribedCirculation, p%nSpan, 'Prescribed Circulation', ErrStat2, ErrMsg2 ); call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_SetParameters' ); p%PrescribedCirculation = -999999_ReKi; + if (.not. allocated(m%s_CP_LL)) then + ErrMsg = 'Spanwise coordinate not allocated.' + ErrStat = ErrID_Fatal + return + endif + call ReadAndInterpGamma(trim(InputFileData%CirculationFile), m%s_CP_LL(1:p%nSpan,1), m%s_LL(p%nSpan+1,1), p%PrescribedCirculation, ErrStat2, ErrMsg2) + call SetErrStat ( ErrStat2, ErrMsg2, ErrStat,ErrMsg,'FVW_SetParameters' ); + endif + +end subroutine FVW_SetParametersFromInputFile + +subroutine FVW_ToString(p,m) + type(FVW_ParameterType), intent(in) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Misc + if (DEV_VERSION) then + print*,'-----------------------------------------------------------------------------------------' + if(.false.) print*,m%nNW ! unused var for now + endif +end subroutine FVW_ToString + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +subroutine FVW_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + type(FVW_InputType),allocatable, intent(inout) :: u(:) !< System inputs + type(FVW_ParameterType), intent(inout) :: p !< Parameters + type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states + type(FVW_DiscreteStateType), intent(inout) :: xd !< Discrete states + type(FVW_ConstraintStateType), intent(inout) :: z !< Constraint states + type(FVW_OtherStateType), intent(inout) :: OtherState !< Other states + type(FVW_OutputType), intent(inout) :: y !< System outputs + type(FVW_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 + + integer(IntKi) :: i + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! Place any last minute operations or calculations here: + ! Close files here: + ! Destroy the input data: + if (allocated(u)) then + do i=1,size(u) + call FVW_DestroyInput( u(i), ErrStat, ErrMsg ) + enddo + endif + + ! Destroy the parameter data: + call FVW_DestroyParam( p, ErrStat, ErrMsg ) + + ! Destroy the state data: + call FVW_DestroyContState( x, ErrStat, ErrMsg ) + call FVW_DestroyDiscState( xd, ErrStat, ErrMsg ) + call FVW_DestroyConstrState( z, ErrStat, ErrMsg ) + call FVW_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + call FVW_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + call FVW_DestroyOutput( y, ErrStat, ErrMsg ) + +#ifdef UA_OUTS + CLOSE(69) +#endif +end subroutine FVW_End + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. +!! Continuous, constraint, discrete, and other states are updated for t + Interval +subroutine FVW_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, AFInfo, m, errStat, errMsg ) +!.................................................................................................................................. + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current simulation time step n = 0,1,... + type(FVW_InputType), intent(inout) :: u(:) !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + real(DbKi), intent(in ) :: utimes(:) !< Times associated with u(:), in seconds + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; Output: at t+DTaero + type(FVW_DiscreteStateType), intent(inout) :: xd !< Input: Discrete states at t; Output: at t+DTaero + type(FVW_ConstraintStateType), intent(inout) :: z !< Input: Constraint states at t; Output: at t+DTaero + type(FVW_OtherStateType), intent(inout) :: OtherState !< Input: Other states at t; Output: at t+DTaero + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + type(FVW_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 + ! local variables + type(FVW_InputType) :: uInterp ! Interpolated/Extrapolated input + integer(IntKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + type(FVW_ConstraintStateType) :: z_guess ! < + integer(IntKi) :: nP, nFWEff + integer, dimension(8) :: time1, time2, time_diff + real(ReKi) :: ShedScale !< Scaling factor for shed vorticity (for sub-cycling), 1 if no subcycling + logical :: bReevaluation + + ErrStat = ErrID_None + ErrMsg = "" + + + ! --- Handling of time step, and time compared to previous call + m%iStep = n + ! Reevaluation: two repetitive calls starting from the same time, we will roll back the wake emission + bReevaluation=.False. + if (abs(t-m%OldWakeTime)<0.25_ReKi* p%DTaero) then + bReevaluation=.True. + endif + ! Compute Induced wake effects only if time since last compute is > DTfvw + if ( (( t - m%OldWakeTime ) >= p%DTfvw*OneMinusEpsilon) ) then + m%OldWakeTime = t + m%ComputeWakeInduced = .TRUE. ! It's time to update the induced velocities from wake + else + m%ComputeWakeInduced = .FALSE. + endif + if (bReevaluation) then + print*,'[INFO] FVW: Update States: reevaluation at the same starting time' + call RollBackPreviousTimeStep() ! Cancel wake emission done in previous call + m%ComputeWakeInduced = .TRUE. + endif + if (m%ComputeWakeInduced) then + call date_and_time(values=time1) + endif + + + nP = p%nWings * ( (p%nSpan+1)*(m%nNW-1+2) +(FWnSpan+1)*(m%nFW+1) ) + nFWEff = min(m%nFW, p%nFWFree) + ! --- Display some status to screen +!FIXME: this conflicts with the SimStatus WrOver from the FAST_Subs.f90. Leaving out for now. +! Ideally we put this into a log file. +! if (mod(n,10)==0) print'(A,F10.3,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,F7.2,A)','FVW status - t:',t,' n:',n,' nNW:',m%nNW-1,'/',p%nNWMax-1,' nFW:',nFWEff, '+',m%nFW-nFWEff,'=',m%nFW,'/',p%nFWMax,' nP:',nP,' spent:', m%tSpent, 's' + if (DEV_VERSION) print'(A,F10.3,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A,F7.2,A,L1)','FVW status - t:',t,' n:',n,' nNW:',m%nNW-1,'/',p%nNWMax-1,' nFW:',nFWEff, '+',m%nFW-nFWEff,'=',m%nFW,'/',p%nFWMax,' nP:',nP,' spent:', m%tSpent, 's Comp:',m%ComputeWakeInduced + + ! --- Evaluation at t + ! Inputs at t + call FVW_CopyInput( u(2), uInterp, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + call FVW_Input_ExtrapInterp(u(1:size(utimes)),utimes(:),uInterp,t, ErrStat2, ErrMsg2); if(Failed()) return + call Wings_Panelling(uInterp%WingsMesh, p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Distribute the Wind we requested to Inflow wind to storage Misc arrays + CALL DistributeRequestedWind(u(1)%V_wind, p, m) + + ! --- Solve for circulation at t + ! Returns: z%Gamma_LL (at t) + call AllocAry( z_guess%Gamma_LL, p%nSpan, p%nWings, 'Lifting line Circulation', ErrStat, ErrMsg ); + z_guess%Gamma_LL = m%Gamma_LL + call FVW_CalcConstrStateResidual(t, uInterp, p, x, xd, z_guess, OtherState, m, z, AFInfo, ErrStat2, ErrMsg2, 1); if(Failed()) return + + call UA_UpdateState_Wrapper(AFInfo,t, n, uInterp, p, x, xd, OtherState, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Map circulation and positions between LL and NW and then NW and FW + ! Changes: x only + ShedScale = 1.0_ReKi + call Map_LL_NW(p, m, z, x, ShedScale, ErrStat2, ErrMsg2); if(Failed()) return + call Map_NW_FW(p, m, z, x, ErrStat2, ErrMsg2); if(Failed()) return + !call print_x_NW_FW(p, m, x,'Map_') + + ! --- Integration between t and t+DTaero + ! NOTE: when sub-cycling, the previous convection velocity is used + ! If dtfvw = n dtaero, we assume xdot_local dtaero = xdot_stored * dtfvw/n + if (p%IntMethod .eq. idEuler1) then + call FVW_Euler1( t, uInterp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2); if(Failed()) return + !elseif (p%IntMethod .eq. idRK4) then + ! call FVW_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + !elseif (p%IntMethod .eq. idAB4) then + ! call FVW_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + !elseif (p%IntMethod .eq. idABM4) then + ! call FVW_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + else + call SetErrStat(ErrID_Fatal,'Invalid time integration method:'//Num2LStr(p%IntMethod),ErrStat,ErrMsg,'FVW_UpdateState') + end IF + !call print_x_NW_FW(p, m, x,'Conv') + + if (m%ComputeWakeInduced) then + ! We extend the wake length, i.e. we emit a new panel of vorticity at the TE + ! NOTE: this will be rolled back if UpdateState is called at the same starting time again + call PrepareNextTimeStep() + ! --- t+DTaero + ! Propagation/creation of new layer of panels + call PropagateWake(p, m, z, x, ErrStat2, ErrMsg2); if(Failed()) return + !call print_x_NW_FW(p, m, x,'Prop_') + endif + + ! Inputs at t+DTaero + call FVW_Input_ExtrapInterp(u(1:size(utimes)),utimes,uInterp,t+p%DTaero, ErrStat2, ErrMsg2); if(Failed()) return + + ! Panelling wings based on input mesh at t+p%DTaero + call Wings_Panelling(uInterp%WingsMesh, p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Updating positions of first NW and FW panels (Circulation also updated but irrelevant) + ! Changes: x only + ShedScale = (t+p%DTaero - m%OldWakeTime)/p%DTfvw + call Map_LL_NW(p, m, z, x, ShedScale, ErrStat2, ErrMsg2); if(Failed()) return + call Map_NW_FW(p, m, z, x, ErrStat2, ErrMsg2); if(Failed()) return + + !call print_x_NW_FW(p, m, x,'Map2') + + ! --- Solve for circulation at t+p%DTaero + ! Returns: z%Gamma_LL (at t+p%DTaero) + z_guess%Gamma_LL = z%Gamma_LL ! We use as guess the circulation from the previous time step (see above) + call FVW_CalcConstrStateResidual(t+p%DTaero, uInterp, p, x, xd, z_guess, OtherState, m, z, AFInfo, ErrStat2, ErrMsg2, 2); if(Failed()) return +! print*,'US: z_Gamma',x%Gamma_NW(1,1,1) +! print*,'US: x_Gamma',z%Gamma_LL(1,1) + + ! Updating circulation of near wake panel (and position but irrelevant) + ! Changes: x only + call Map_LL_NW(p, m, z, x, ShedScale, ErrStat2, ErrMsg2); if(Failed()) return + call Map_NW_FW(p, m, z, x, ErrStat2, ErrMsg2); if(Failed()) return + !call print_x_NW_FW(p, m, x,'Map3') + + ! --- Fake handling of ground effect + call FakeGroundEffect(p, x, m, ErrStat, ErrMsg) + + ! set the wind points required for t+p%DTaero timestep + CALL SetRequestedWindPoints(m%r_wind, x, p, m) + + if (m%FirstCall) then + m%FirstCall=.False. + endif + if (m%ComputeWakeInduced) then + ! Profiling of expensive time step + call date_and_time(values=time2) + time_diff=time2-time1 + m%tSpent = time_diff(5)*3600+time_diff(6)*60 +time_diff(7)+0.001*time_diff(8) + endif + call FVW_DestroyConstrState(z_guess, ErrStat2, ErrMsg2); if(Failed()) return + +contains + subroutine PrepareNextTimeStep() + ! --- Increase wake length if maximum not reached + if (m%nNW==p%nNWMax) then ! a far wake exist + m%nFW=min(m%nFW+1, p%nFWMax) + endif + m%nNW=min(m%nNW+1, p%nNWMax) + end subroutine PrepareNextTimeStep + + subroutine RollBackPreviousTimeStep() + ! --- Decrease wake length if maximum not reached + if (m%nNW==p%nNWMax) then ! a far wake exist + m%nFW=max(m%nFW-1, 0) + endif + m%nNW=max(m%nNW-1, 0) + end subroutine RollBackPreviousTimeStep + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_UpdateStates') + Failed = ErrStat >= AbortErrLev + !if (Failed) call CleanUp() + end function Failed + +end subroutine FVW_UpdateStates + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for computing derivatives of continuous states. +subroutine FVW_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(FVW_InputType), intent(in ) :: u !< Inputs at t + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(FVW_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraint states at t + type(FVW_OtherStateType), intent(in ) :: OtherState !< Other states at t + type(FVW_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + type(FVW_ContinuousStateType), intent( out) :: dxdt !< Continuous state derivatives at t + 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 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + integer(IntKi) :: nFWEff ! Number of farwake panels that are free at current time step + integer(IntKi) :: i,j,k + real(ReKi), dimension(3) :: VmeanFW, VmeanNW ! Mean velocity of the near wake and far wake + + ErrStat = ErrID_None + ErrMsg = "" + + call AllocAry( dxdt%r_NW , 3 , p%nSpan+1 ,p%nNWMax+1, p%nWings, 'Wind on NW ', ErrStat2, ErrMsg2); dxdt%r_NW= -999999_ReKi; + call AllocAry( dxdt%r_FW , 3 , FWnSpan+1 ,p%nFWMax+1, p%nWings, 'Wind on FW ', ErrStat2, ErrMsg2); dxdt%r_FW= -999999_ReKi; + if(Failed()) return + + ! Only calculate freewake after start time and if on a timestep when it should be calculated. + if ((t>= p%FreeWakeStart)) then + nFWEff = min(m%nFW, p%nFWFree) + + ! --- Compute Induced velocities on the Near wake and far wake based on the marker postions: + ! (expensive N^2 call) + ! In : x%r_NW, r%r_FW + ! Out: m%Vind_NW, m%Vind_FW + call WakeInducedVelocities(p, x, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Mean induced velocity over the near wake (NW) + VmeanNW(1:3)=0 + if (m%nNW >1) then + do i=1,size(m%Vind_NW,4); do j=2,m%nNW+1; do k=1,size(m%Vind_NW,2); + VmeanNW(1:3) = VmeanNW(1:3) + m%Vind_NW(1:3, k, j, i) + enddo; enddo; enddo; + VmeanNW(1:3) = VmeanNW(1:3) / (size(m%Vind_NW,4)*m%nNW*size(m%Vind_NW,2)) + endif + ! --- Induced velocity over the free far wake (FWEff) + VmeanFW(1:3)=0 + if (nFWEff >0) then + do i=1,size(m%Vind_FW,4); do j=1,nFWEff; do k=1,size(m%Vind_FW,2); + VmeanFW(1:3) = VmeanFW(1:3) + m%Vind_FW(1:3, k, j, i) + enddo; enddo; enddo; + VmeanFW(1:3) = VmeanFW(1:3) / (size(m%Vind_FW,4)*nFWEff*size(m%Vind_FW,2)) + else + VmeanFW=VmeanNW + ! Since we convect the first FW point, we need a reasonable velocity there + ! NOTE: mostly needed for sub-cycling and when no NW + m%Vind_FW(1, 1:FWnSpan+1, 1, 1:p%nWings) = VmeanFW(1) + m%Vind_FW(2, 1:FWnSpan+1, 1, 1:p%nWings) = VmeanFW(2) + m%Vind_FW(3, 1:FWnSpan+1, 1, 1:p%nWings) = VmeanFW(3) + endif + + ! --- Convecting non-free FW with a constant induced velocity (and free stream) + m%Vind_FW(1, 1:FWnSpan+1, p%nFWFree+1:p%nFWMax+1, 1:p%nWings) = VmeanFW(1) ! + m%Vind_FW(2, 1:FWnSpan+1, p%nFWFree+1:p%nFWMax+1, 1:p%nWings) = VmeanFW(2) ! + m%Vind_FW(3, 1:FWnSpan+1, p%nFWFree+1:p%nFWMax+1, 1:p%nWings) = VmeanFW(3) ! + + if (DEV_VERSION) then + call print_mean_4d( m%Vind_NW(:,:, 1:m%nNW+1,:), 'Mean induced vel. NW') + if (nFWEff>0) then + call print_mean_4d( m%Vind_FW(:,:, 1:nFWEff ,:), 'Mean induced vel. FW') + endif + print'(A25,3F12.4)','MeanFW (non free)',VmeanFW + call print_mean_4d( m%Vwnd_NW(:,:, 1:m%nNW+1,:), 'Mean wind vel. NW') + call print_mean_4d( m%Vwnd_FW(:,:, 1:nFWEff+1,:), 'Mean wind vel. FWEff') + call print_mean_4d( m%Vwnd_FW(:,:, (p%nFWFree+1):m%nFW+1,:), 'Mean wind vel. FWNF') + call print_mean_4d( m%Vwnd_FW(:,:, 1:m%nFW+1,:), 'Mean wind vel. FW') + endif + + ! --- Vortex points are convected with the free stream and induced velocity + dxdt%r_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) = m%Vwnd_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) + m%Vind_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) + dxdt%r_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) = m%Vwnd_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) + m%Vind_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) + else + if(DEV_VERSION) then + call print_mean_4d( m%Vwnd_NW(:,:,1:m%nNW+1,:), 'Mean wind vel. NW') + !call print_mean_4d( m%Vwnd_FW(:,:,1:m%nFW+1,:), 'Mean wind vel. FW') + endif + + ! --- Vortex points are convected with the free stream + dxdt%r_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) = m%Vwnd_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) + dxdt%r_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) = m%Vwnd_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) + endif + ! First NW point does not convect (bound to LL) + dxdt%r_NW(1:3, :, 1:iNWStart-1, :)=0 + ! First FW point always convects (even if bound to NW) + ! This is done for subcycling + !dxdt%r_FW(1:3, :, 1, :)=0 +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_CalcContStateDeriv') + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine FVW_CalcContStateDeriv + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine FVW_Euler1( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(FVW_InputType), intent(in ) :: u !< Input at t + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states at t on input at t + dt on output + type(FVW_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraint states at t (possibly a guess) + type(FVW_OtherStateType), intent(inout) :: OtherState !< Other states at t on input at t + dt on output + type(FVW_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 + ! local variables + type(FVW_ContinuousStateType) :: dxdt ! time derivatives of continuous states + real(ReKi) :: dt + integer(IntKi) :: ErrStat2 ! temporary error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + dt = real(p%DTaero,ReKi) ! NOTE: this is DTaero not DTfvw since we integrate at each sub time step + ! Compute "right hand side" + if (m%ComputeWakeInduced) then + CALL FVW_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2); if (Failed()) return + ! Storage of convection velocity, purely for sub-cycling for now + ! Since Euler1 is linear we use partial increments of dtaero<dtfvw + m%dxdt_NW = dxdt%r_NW + m%dxdt_FW = dxdt%r_FW + endif + + if (DEV_VERSION) then + ! Additional checks + if (any(m%dxdt_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings)<-999)) then + print*,'FVW_Euler1: Attempting to convect NW with a wrong velocity' + STOP + endif + if ( m%nFW>0) then + if (any(m%dxdt_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings)<-999)) then + call print_x_NW_FW(p, m, x, 'STP') + print*,'FVW_Euler1: Attempting to convect FW with a wrong velocity' + STOP + endif + endif + endif + + ! Update of positions + x%r_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) = x%r_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) + dt * m%dxdt_NW(1:3, 1:p%nSpan+1, 1:m%nNW+1, 1:p%nWings) + if ( m%nFW>0) then + x%r_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) = x%r_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) + dt * m%dxdt_FW(1:3, 1:FWnSpan+1, 1:m%nFW+1, 1:p%nWings) + endif + ! Update of Gamma + ! TODO, viscous diffusion, stretching + + call FVW_DestroyContState(dxdt, ErrStat2, ErrMsg2); if(Failed()) return +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_Euler1') + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine FVW_Euler1 +!---------------------------------------------------------------------------------------------------------------------------------- + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for solving for the residual of the constraint state functions. +subroutine FVW_CalcConstrStateResidual( t, u, p, x, xd, z_guess, OtherState, m, z_out, AFInfo, ErrStat, ErrMsg, iLabel) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(FVW_InputType), intent(in ) :: u !< Inputs at t + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(FVW_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(FVW_ConstraintStateType), intent(in ) :: z_guess !< Constraint states at t (possibly a guess) + type(FVW_OtherStateType), intent(in ) :: OtherState !< Other states at t + type(FVW_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + type(FVW_ConstraintStateType), intent( out) :: z_out !< Residual of the constraint state functions using + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + integer(IntKi), intent(in ) :: iLabel + integer(IntKi), intent( OUT) :: ErrStat !< Error status of the operation + character(*), intent( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! Solve for the residual of the constraint state functions here: + !z%residual = 0.0_ReKi + !z%Gamma_LL = 0.0_ReKi + call AllocAry( z_out%Gamma_LL, p%nSpan, p%nWings, 'Lifting line Circulation', ErrStat, ErrMsg ); + z_out%Gamma_LL = -999999_ReKi; + + CALL Wings_ComputeCirculation(t, z_out%Gamma_LL, z_guess%Gamma_LL, u, p, x, m, AFInfo, ErrStat, ErrMsg, iLabel) + +end subroutine FVW_CalcConstrStateResidual + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! This subroutine is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! The descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +! NOTE: no matter how many channels are selected for output, all of the outputs are calculated +! All of the calculated output channels are placed into the m%AllOuts(:), while the channels selected for outputs are +! placed in the y%WriteOutput(:) array. +subroutine FVW_CalcOutput( t, u, p, x, xd, z, OtherState, AFInfo, y, m, ErrStat, ErrMsg ) + use FVW_VTK, only: set_vtk_coordinate_transform + use FVW_VortexTools, only: interpextrap_cp2node + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(FVW_InputType), intent(in ) :: u !< Inputs at Time t + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(FVW_DiscreteStateType), intent(in ) :: xd !< Discrete states at t +!FIXME:TODO: AD15_CalcOutput has constraint states as intent(in) only. This is forcing me to store z in the AD15 miscvars for now. + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraint states at t + type(FVW_OtherStateType), intent(in ) :: OtherState !< Other states at t + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + type(FVW_OutputType), intent(inout) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + type(FVW_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 + ! Local variables + integer(IntKi) :: iW, n, i0, i1, i2 + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'FVW_CalcOutput' + + ErrStat = ErrID_None + ErrMsg = "" + + if (DEV_VERSION) then + print'(A,F10.3,A,L1,A,I0,A,I0)','CalcOutput t:',t,' ',m%FirstCall,' nNW:',m%nNW,' nFW:',m%nFW + endif + + ! Set the wind velocity at vortex + CALL DistributeRequestedWind(u%V_wind, p, m) + + ! if we are on a correction step, CalcOutput may be called again with different inputs + ! Compute m%Gamma_LL + CALL Wings_ComputeCirculation(t, m%Gamma_LL, z%Gamma_LL, u, p, x, m, AFInfo, ErrStat2, ErrMsg2, 0); if(Failed()) return ! For plotting only + + + ! Induction on the lifting line control point + ! Set m%Vind_LL + m%Vind_LL=-9999.0_ReKi + call LiftingLineInducedVelocities(p, x, 1, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! Induction on the mesh points (AeroDyn nodes) + n=p%nSpan + y%Vind(1:3,:,:) = 0.0_ReKi + do iW=1,p%nWings + ! --- Linear interpolation for interior points and extrapolations at boundaries + call interpextrap_cp2node(m%s_CP_LL(:,iW), m%Vind_LL(1,:,iW), m%s_LL(:,iW), y%Vind(1,:,iW)) + call interpextrap_cp2node(m%s_CP_LL(:,iW), m%Vind_LL(2,:,iW), m%s_LL(:,iW), y%Vind(2,:,iW)) + call interpextrap_cp2node(m%s_CP_LL(:,iW), m%Vind_LL(3,:,iW), m%s_LL(:,iW), y%Vind(3,:,iW)) + enddo + + ! For plotting only + m%Vtot_ll = m%Vind_LL + m%Vwnd_LL - m%Vstr_ll + if (DEV_VERSION) then + call print_mean_3d(m%Vind_LL,'Mean induced vel. LL') + call print_mean_3d(m%Vtot_LL,'Mean relativevel. LL') + endif + + ! --- Write to local VTK at fps requested + if (p%WrVTK==1) then + if (m%VTKStep==-1) then + m%VTKStep = 0 ! Has never been called, special handling for init + else + m%VTKStep = m%iStep+1 ! We use glue code step number for outputs + endif + if (m%FirstCall) then + call MKDIR(p%VTK_OutFileRoot) + endif + if ( ( t - m%VTKlastTime ) >= p%DTvtk*OneMinusEpsilon ) then + m%VTKlastTime = t + if ((p%VTKCoord==2).or.(p%VTKCoord==3)) then + ! Hub reference coordinates, for export only, ALL VTK Will be exported in this coordinate system! + ! Note: hubOrientation and HubPosition are optional, but required for bladeFrame==TRUE + call WrVTK_FVW(p, x, z, m, trim(p%VTK_OutFileBase)//'FVW_Hub', m%VTKStep, 9, bladeFrame=.TRUE., & + HubOrientation=real(u%HubOrientation,ReKi),HubPosition=real(u%HubPosition,ReKi)) + endif + if ((p%VTKCoord==1).or.(p%VTKCoord==3)) then + ! Global coordinate system, ALL VTK will be exported in global + call WrVTK_FVW(p, x, z, m, trim(p%VTK_OutFileBase)//'FVW_Glb', m%VTKStep, 9, bladeFrame=.FALSE.) + endif + endif + endif + + +contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_CalcOutput') + Failed = ErrStat >= AbortErrLev + end function Failed + +end subroutine FVW_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +! --- UA related, should be merged with AeroDyn +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine UA_Init_Wrapper(AFInfo, InitInp, interval, p, x, xd, OtherState, m, ErrStat, ErrMsg ) + use UnsteadyAero, only: UA_Init, UA_TurnOff_param + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data, temporary, for UA.. + type(FVW_InitInputType), intent(inout) :: InitInp !< Input data for initialization routine (inout so we can use MOVE_ALLOC) + real(DbKi), intent(inout) :: interval !< time interval + type(FVW_ParameterType), intent(inout) :: p !< Parameters + type(FVW_ContinuousStateType), intent(inout) :: x !< Initial continuous states + type(FVW_DiscreteStateType), intent(inout) :: xd !< Initial discrete states + type(FVW_OtherStateType), intent(inout) :: OtherState !< Initial other states + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! + type(UA_InitInputType) :: Init_UA_Data + type(UA_InputType) :: u_UA + type(UA_InitOutputType):: InitOutData_UA + integer :: i,j + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + m%UA_Flag=InitInp%UA_Flag + ! --- Condensed version of BEMT_Init_Otherstate + allocate ( OtherState%UA_Flag( InitInp%numBladeNodes, InitInp%NumBlades ), STAT = ErrStat2 ) + OtherState%UA_Flag=m%UA_Flag + if ( m%UA_Flag ) then + ErrMsg2='Unsteady aerodynamic (`AFAeroMod>1`) cannot be used with the free wake code (`WakeMod=3`) for now.'; ErrStat2=ErrID_Fatal; + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'UA_Init_Wrapper'); return + + ! ---Condensed version of "BEMT_Set_UA_InitData" + allocate(Init_UA_Data%c(InitInp%numBladeNodes,InitInp%numBlades), STAT = errStat2) + do j = 1,InitInp%NumBlades; do i = 1,InitInp%numBladeNodes; + Init_UA_Data%c(i,j) = p%chord(i,j) ! NOTE: InitInp chord move-allocd to p + end do; end do + Init_UA_Data%dt = interval + Init_UA_Data%OutRootName = '' + Init_UA_Data%numBlades = InitInp%NumBlades + Init_UA_Data%nNodesPerBlade = InitInp%numBladeNodes + Init_UA_Data%NumOuts = 0 + Init_UA_Data%UAMod = InitInp%UAMod + Init_UA_Data%Flookup = InitInp%Flookup + Init_UA_Data%a_s = InitInp%a_s ! m/s + ! --- UA init + call UA_Init( Init_UA_Data, u_UA, m%p_UA, x%UA, xd%UA, OtherState%UA, m%y_UA, m%m_UA, interval, InitOutData_UA, ErrStat2, ErrMsg2); if(Failed())return + m%p_UA%ShedEffect=.False. !< Important, when coupling UA wih vortex code, shed vorticity is inherently accounted for + ! --- Condensed version of "BEMT_CheckInitUA" + do j = 1,InitInp%numBlades; do i = 1,InitInp%numBladeNodes; ! Loop over blades and nodes + call UA_TurnOff_param(m%p_UA, AFInfo(p%AFindx(i,j)), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + call WrScr( 'Warning: Turning off Unsteady Aerodynamics because '//trim(ErrMsg2)//' BladeNode = '//trim(num2lstr(i))//', Blade = '//trim(num2lstr(j)) ) + OtherState%UA_Flag(i,j) = .false. + end if + end do; end do; +#ifdef UA_OUTS + CALL OpenFOutFile ( 69, 'Debug.UA.out', errStat, errMsg ); IF (ErrStat >= AbortErrLev) RETURN + WRITE (69,'(/,A)') 'This output information was generated by FVW'// ' on '//CurDate()//' at '//CurTime()//'.' + WRITE (69,'(:,A20)', ADVANCE='no' ) 'Time' + do i=1,size(InitOutData_UA%WriteOutputHdr) + WRITE (69,'(:,A20)', ADVANCE='no' ) trim(InitOutData_UA%WriteOutputHdr(i)) + end do + write (69,'(A)') ' ' + WRITE (69,'(:,A20)', ADVANCE='no' ) '(s)' + do i=1,size(InitOutData_UA%WriteOutputUnt) + WRITE (69,'(:,A20)', ADVANCE='no' ) trim(InitOutData_UA%WriteOutputUnt(i)) + end do + write (69,'(A)') ' ' +#endif + call UA_DestroyInput( u_UA, ErrStat2, ErrMsg2 ); if(Failed())return + call UA_DestroyInitInput( Init_UA_Data, ErrStat2, ErrMsg2 ); if(Failed())return + call UA_DestroyInitOutput( InitOutData_UA, ErrStat2, ErrMsg2 ); if(Failed())return + + ! --- FVW specific + if (p%CirculationMethod/=idCircPolarData) then + ErrMsg2='Unsteady aerodynamic (`AFAeroMod>1`) is only available with a circulation solving using profile data (`CircSolvingMethod=1`)'; ErrStat2=ErrID_Fatal; + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'UA_Init_Wrapper'); return + endif + endif +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'UA_Init_Wrapper') + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine UA_Init_Wrapper + +subroutine UA_UpdateState_Wrapper(AFInfo, t, n, u, p, x, xd, OtherState, m, ErrStat, ErrMsg ) + use FVW_VortexTools, only: interpextrap_cp2node + use UnsteadyAero, only: UA_UpdateStates, UA_TurnOff_input + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data, temporary, for UA.. + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< time step + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_InputType), intent(in ) :: u !< Inputs + type(FVW_ContinuousStateType), intent(inout) :: x !< Initial continuous states + type(FVW_DiscreteStateType), intent(inout) :: xd !< Initial discrete states + type(FVW_OtherStateType), intent(inout) :: OtherState !< Initial other states + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local + type(UA_InputType) :: u_UA(1) + REAL(DbKi) :: uTimes(1) + integer :: i,j + integer, parameter :: k=1 ! index for u_UA (in case it is ever dimensioned differently) + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 + real(ReKi), dimension(:,:), allocatable :: Vind_node + ErrStat = ErrID_None + ErrStat2 = ErrID_None + ErrMsg = "" + ErrMsg2 = "" + + uTimes = t + + if (m%UA_Flag) then + + ! --- Induction on the lifting line control point + ! NOTE: this is expensive since it's an output for FVW but here we have to use it for UA + ! Set m%Vind_LL + m%Vind_LL=-9999.0_ReKi + call LiftingLineInducedVelocities(p, x, 1, m, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'UA_UpdateState_Wrapper'); if (ErrStat >= AbortErrLev) return + + allocate(Vind_node(3,1:p%nSpan+1)) + + ! --- Condensed version of BEMT_Update States + do j = 1,p%nWings + ! Induced velocity at Nodes (NOTE: we rely on storage done when computing Circulation) + if (m%nNW>1) then + call interpextrap_cp2node(m%s_CP_LL(:,j), m%Vind_LL(1,:,j), m%s_LL(:,j), Vind_node(1,:)) + call interpextrap_cp2node(m%s_CP_LL(:,j), m%Vind_LL(2,:,j), m%s_LL(:,j), Vind_node(2,:)) + call interpextrap_cp2node(m%s_CP_LL(:,j), m%Vind_LL(3,:,j), m%s_LL(:,j), Vind_node(3,:)) + else + Vind_node=0.0_ReKi + endif + + do i = 1,p%nSpan+1 + ! We only update the UnsteadyAero states if we have unsteady aero turned on for this node + if (OtherState%UA_Flag(i,j) .and. n > 0) then + !! ....... compute inputs to UA ........... + ! NOTE: To be consistent with CalcOutput we take Vwind_ND that was set using m%DisturbedInflow from AeroDyn.. + ! This is not clean, but done to be consistent, waiting for AeroDyn to handle UA + call AlphaVrel_Generic(u%WingsMesh(j)%Orientation(1:3,1:3,i), u%WingsMesh(j)%TranslationVel(1:3,i), Vind_node(:,i), m%Vwnd_ND(:,i,j), & + p%KinVisc, p%Chord(i,j), u_UA(k)%U, u_UA(k)%alpha, u_UA(k)%Re) + ! FIX ME: this is copied 3 times!!!! + u_UA%v_ac(1) = sin(u_UA%alpha)*u_UA%U + u_UA%v_ac(2) = cos(u_UA%alpha)*u_UA%U + u_UA%omega = 0.0_ReKi ! FIX ME!!!! dot_product( u%BladeMotion(j)%RotationVel( :,i), m%WithoutSweepPitchTwist(3,:,i,j) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade + u_UA(k)%UserProp = 0 ! u1%UserProp(i,j) ! TODO + + !! ....... check inputs to UA ........... + call UA_TurnOff_input(m%p_UA, AFInfo(p%AFIndx(i,j)), u_UA(k), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + OtherState%UA_Flag(i,j) = .FALSE. + call WrScr( 'Warning: Turning off dynamic stall due to '//trim(ErrMsg2)//' '//trim(NodeText(i,j))) + else + ! COMPUTE: xd%UA, OtherState%UA + call UA_UpdateStates( i, j, t, n, u_UA, uTimes, m%p_UA, x%UA, xd%UA, OtherState%UA, AFInfo(p%AFIndx(i,j)), m%m_UA, ErrStat2, ErrMsg2 ) + if (ErrStat2 /= ErrID_None) then + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'UA_UpdateState_Wrapper'//trim(NodeText(i,j))) + call WrScr(trim(ErrMsg)) + if (ErrStat >= AbortErrLev) return + end if + end if + end if + end do + end do + call UA_DestroyInput( u_UA(k), ErrStat2, ErrMsg2 ); + deallocate(Vind_node) + endif + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'UA_UpdateState_Wrapper') +contains + function NodeText(i,j) + integer(IntKi), intent(in) :: i ! node number + integer(IntKi), intent(in) :: j ! blade number + character(25) :: NodeText + NodeText = '(nd:'//trim(num2lstr(i))//' bld:'//trim(num2lstr(j))//')' + end function NodeText +end subroutine UA_UpdateState_Wrapper + +end module FVW diff --git a/OpenFAST/modules/aerodyn/src/FVW_BiotSavart.f90 b/OpenFAST/modules/aerodyn/src/FVW_BiotSavart.f90 new file mode 100644 index 000000000..cb15a379e --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_BiotSavart.f90 @@ -0,0 +1,430 @@ +module FVW_BiotSavart + + use NWTC_Library, only: ReKi, IntKi + use OMP_LIB ! wrap with #ifdef _OPENMP if this causes an issue + + implicit none + + real(ReKi),parameter :: PRECISION_UI = epsilon(1.0_ReKi)/100 !< NOTE assuming problem of size 1 + real(ReKi),parameter :: MIN_EXP_VALUE=-10.0_ReKi + real(ReKi),parameter :: MINDENOM=0.0_ReKi +! real(ReKi),parameter :: MINDENOM=1e-15_ReKi + real(ReKi),parameter :: MINNORM=1e-4 + + integer(IntKi), parameter :: idRegNone = 0 + integer(IntKi), parameter :: idRegRankine = 1 + integer(IntKi), parameter :: idRegLambOseen = 2 + integer(IntKi), parameter :: idRegVatistas = 3 + integer(IntKi), parameter :: idRegOffset = 4 + integer(IntKi), parameter :: idRegExp = 1 + integer(IntKi), parameter :: idRegCompact = 2 + integer(IntKi), parameter, dimension(5) :: idRegVALID = (/idRegNone,idRegRankine,idRegLambOseen,idRegVatistas,idRegOffset/) + integer(IntKi), parameter, dimension(3) :: idRegPartVALID = (/idRegNone,idRegExp,idRegCompact/) + + real(ReKi),parameter :: fourpi_inv = 0.25_ReKi / ACOS(-1.0_Reki ) + +contains + + +!> Induced velocity from one segment at one control points +subroutine ui_seg_11(DeltaPa, DeltaPb, SegGamma, RegFunction, RegParam1, Uind) + ! Input/output arguments + real(ReKi), dimension(3), intent(in) :: DeltaPa !< 3 x 1 Pcp-P1 [m] + real(ReKi), dimension(3), intent(in) :: DeltaPb !< 3 x 1 Pcp-P2 [m] + real(ReKi), intent(in) :: SegGamma !< Circulation [m^2/s] + integer, intent(in) :: RegFunction!< Regularization model + real(ReKi), intent(in) :: RegParam1 !< Regularization parameter (core radius) [m] + real(ReKi), dimension(3),intent(out) :: Uind !< Induced velocity (no side effects) [m/s] + ! Variables declaration + real(ReKi),dimension(3) :: crossprod !< + real(ReKi) :: denominator !< + real(ReKi) :: r_bar2 !< (r/rc)^2 + real(ReKi) :: Kv !< + real(ReKi) :: norm_a, norm_b !< + real(ReKi) :: norm2_r0 !< Squared length of the segment + real(ReKi) :: norm2_orth !< Squared distance orthogonal to the segment + real(ReKi) :: xa, ya, za, xb, yb, zb !< Coordinates of X-Xa and X-Xb + real(ReKi) :: exp_value !< + ! + Uind(1:3)=0.0_ReKi + xa=DeltaPa(1); ya=DeltaPa(2); za=DeltaPa(3) + xb=DeltaPb(1); yb=DeltaPb(2); zb=DeltaPb(3) + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) ! |r1|*|r2|*(|r1|*|r2| + r1.r2) + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then ! segment of zero length + ! --- Far field TODO + ! --- Regularization (close field) + norm2_orth = norm2_orth/norm2_r0 ! d = (r1xr2)/r0 + select case (RegFunction) ! + case ( idRegNone ) ! No vortex core model + Kv=1.0_ReKi + case ( idRegRankine ) ! Rankine + r_bar2 = norm2_orth/ RegParam1**2 + if (r_bar2<1) then + Kv=r_bar2 + else + Kv=1.0_ReKi + end if + case ( idRegLambOseen ) ! Lamb-Oseen + r_bar2 = norm2_orth/ RegParam1**2 + exp_value = -1.25643_ReKi*r_bar2 + if(exp_value<MIN_EXP_VALUE) then ! Remove me when Far distance implemented + Kv = 1.0_ReKi + else + Kv = 1.0_ReKi-exp(exp_value) + endif + case ( idRegVatistas ) ! Vatistas n=2 + r_bar2 = norm2_orth/ RegParam1**2 + Kv = r_bar2/sqrt(1.0_ReKi+r_bar2**2) + case ( idRegOffset ) ! Cut-off radius + Kv = 1.0_ReKi + denominator=denominator+RegParam1**2*norm2_r0 + case default + Kv=1.0_ReKi !< Should be an error + end select + Kv=SegGamma*fourpi_inv*Kv*(norm_a+norm_b)/denominator + Uind(1:3) = Kv*crossprod(1:3) + endif + endif + endif +end subroutine ui_seg_11 + + +!> Induced velocity from a list of segments defined by Connectivity (SegConnct) and Points (SegPoints) +!! NOTE: this function has side effects and expects Uind_out to be initialized! +!! The function can compute the velocity on part of the segments and part of the control points. +!! This feature is useful if some parallelization is used, while common storage vectors are used. +subroutine ui_seg(iCPStart, iCPEnd, CPs, & + iSegStart, iSegEnd, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, & + RegFunction, RegParam, Uind_out) + real(ReKi), dimension(:,:), intent(in) :: CPs !< Control points (3 x nCPs++) + integer(IntKi), intent(in) :: iCPStart !< Index where we start in Control points array + integer(IntKi), intent(in) :: iCPEnd !< Index where we end in Control points array + real(ReKi), dimension(:,:), intent(in) :: SegPoints !< Segment points (3 x nSegPTot) + integer(IntKi), dimension(:,:), intent(in) :: SegConnct !< Connectivity, indices of segments points iSeg1, iSeg2, iDepth, iSpan + real(ReKi), dimension(:), intent(in) :: SegGamma !< Segment circulation (nSegTot) + integer(IntKi), intent(in) :: iSegStart !< Index in SegConnct, and SegGamma where we start + integer(IntKi), intent(in) :: iSegEnd !< Index in SegConnct, and SegGamma where we end + integer(IntKi), intent(in) :: nSegTot !< Total number of segments + integer(IntKi), intent(in) :: nSegPTot !< Total number of segment points + integer(IntKi), intent(in) :: RegFunction !< Regularization model + real(ReKi), dimension(:), intent(in) :: RegParam !< Regularization parameter (nSegTot) + real(ReKi), dimension(:,:) , intent(inout) :: Uind_out !< Induced velocity vector - Side effects!!! (3 x nCPs++) + ! Variables + integer(IntKi) :: icp, is + real(ReKi), dimension(3) :: Uind !< + real(ReKi), dimension(3) :: P1, P2 !< Extremities of a given segment + ! Variables declaration + real(ReKi),dimension(3) :: crossprod !< + real(ReKi) :: denominator !< + real(ReKi) :: r_bar2 !< (r/rc)^2 + real(ReKi) :: Kv !< + real(ReKi) :: norm_a, norm_b !< + real(ReKi) :: norm2_orth !< + real(ReKi) :: norm2_r0 !< Squared length of the segment d = (r1xr2)/r0 + real(ReKi) :: xa, ya, za, xb, yb, zb !< Coordinates of X-Xa and X-Xb + real(ReKi) :: exp_value !< + + ! Branching based on regularization model + ! NOTE: copy paste of code is done for optimization! + ! The only thing changing is the part labelled "regularization" + select case (RegFunction) + case ( idRegNone ) ! No vortex core + !$OMP PARALLEL default(shared) + !$OMP do private(icp,is,Uind,P1,P2,crossprod,denominator,Kv,norm_a,norm_b,norm2_r0,norm2_orth,xa,ya,za,xb,yb,zb) schedule(runtime) + do icp=iCPStart,iCPEnd ! loop on CPs + do is=iSegStart,iSegEnd ! loop on selected segments + Uind = 0.0_ReKi + P1 = SegPoints(1:3, SegConnct(1,is)) ! Segment extremity points + P2 = SegPoints(1:3, SegConnct(2,is)) + xa=CPs(1,icp)-P1(1); ya=CPs(2,icp)-P1(2); za=CPs(3,icp)-P1(3); + xb=CPs(1,icp)-P2(1); yb=CPs(2,icp)-P2(2); zb=CPs(3,icp)-P2(3); + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) + ! --- Far field TODO + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then + ! --- Far field TODO + ! --- NO Regularization (close field) + Kv = SegGamma(is)*fourpi_inv*(norm_a+norm_b)/(denominator + MINDENOM) + Uind(1:3) = Kv*crossprod(1:3) + end if + end if + end if + Uind_out(1:3,icp) = Uind_out(1:3,icp)+Uind(1:3) + end do ! Loop on segments + enddo ! Loop on control points + !$OMP END DO + !$OMP END PARALLEL + + case ( idRegRankine ) ! Rankine + !$OMP PARALLEL default(shared) + !$OMP do private(icp,is,Uind,P1,P2,crossprod,denominator,r_bar2,Kv,norm_a,norm_b,norm2_r0,norm2_orth,xa,ya,za,xb,yb,zb) schedule(runtime) + do icp=iCPStart,iCPEnd ! loop on CPs + do is=iSegStart,iSegEnd ! loop on selected segments + Uind = 0.0_ReKi + P1 = SegPoints(1:3, SegConnct(1,is)) ! Segment extremity points + P2 = SegPoints(1:3, SegConnct(2,is)) + xa=CPs(1,icp)-P1(1); ya=CPs(2,icp)-P1(2); za=CPs(3,icp)-P1(3); + xb=CPs(1,icp)-P2(1); yb=CPs(2,icp)-P2(2); zb=CPs(3,icp)-P2(3); + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then + ! --- Far field TODO + ! --- Regularization (close field) --- Rankine + norm2_orth = norm2_orth/norm2_r0 ! d = (r1xr2)/r0 + r_bar2 = norm2_orth/ RegParam(is)**2 + if (r_bar2<1) then + Kv=r_bar2 + else + Kv=1.0_ReKi + end if + Kv = SegGamma(is)*fourpi_inv*Kv*(norm_a+norm_b)/(denominator + MINDENOM) + Uind(1:3) = Kv*crossprod(1:3) + end if + end if ! denominator size or distances too small + end if ! + Uind_out(1:3,icp) = Uind_out(1:3,icp)+Uind(1:3) + end do ! Loop on segments + enddo ! Loop on control points + !$OMP END DO + !$OMP END PARALLEL + + case ( idRegLambOseen ) ! LambOseen + !$OMP PARALLEL default(shared) + !$OMP do private(icp,is,Uind,P1,P2,crossprod,denominator,r_bar2,Kv,norm_a,norm_b,norm2_r0,norm2_orth,xa,ya,za,xb,yb,zb,exp_value) schedule(runtime) + do icp=iCPStart,iCPEnd ! loop on CPs + do is=iSegStart,iSegEnd ! loop on selected segments + Uind = 0.0_ReKi + P1 = SegPoints(1:3, SegConnct(1,is)) ! Segment extremity points + P2 = SegPoints(1:3, SegConnct(2,is)) + xa=CPs(1,icp)-P1(1); ya=CPs(2,icp)-P1(2); za=CPs(3,icp)-P1(3); + xb=CPs(1,icp)-P2(1); yb=CPs(2,icp)-P2(2); zb=CPs(3,icp)-P2(3); + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then + ! --- Far field TODO + ! --- Regularization (close field) --- Lamb Oseen + norm2_orth = norm2_orth/norm2_r0 ! d = (r1xr2)/r0 + r_bar2 = norm2_orth/ RegParam(is)**2 + exp_value = -1.25643_ReKi*r_bar2 + if(exp_value<MIN_EXP_VALUE) then ! Remove me when Far distance implemented + Kv = 1.0_ReKi + else + Kv = 1.0_ReKi-exp(exp_value) + endif + Kv = SegGamma(is)*fourpi_inv*Kv*(norm_a+norm_b)/(denominator + MINDENOM) + Uind(1:3) = Kv*crossprod(1:3) + endif + end if ! denominator size or distances too small + end if ! + Uind_out(1:3,icp) = Uind_out(1:3,icp)+Uind(1:3) + end do ! Loop on segments + enddo ! Loop on control points + !$OMP END DO + !$OMP END PARALLEL + + case ( idRegVatistas ) ! Vatistas n=2 + !$OMP PARALLEL default(shared) + !$OMP do private(icp,is,Uind,P1,P2,crossprod,denominator,r_bar2,Kv,norm_a,norm_b,norm2_r0,norm2_orth,xa,ya,za,xb,yb,zb) schedule(runtime) + do icp=iCPStart,iCPEnd ! loop on CPs + do is=iSegStart,iSegEnd ! loop on selected segments + Uind = 0.0_ReKi + P1 = SegPoints(1:3, SegConnct(1,is)) ! Segment extremity points + P2 = SegPoints(1:3, SegConnct(2,is)) + xa=CPs(1,icp)-P1(1); ya=CPs(2,icp)-P1(2); za=CPs(3,icp)-P1(3); + xb=CPs(1,icp)-P2(1); yb=CPs(2,icp)-P2(2); zb=CPs(3,icp)-P2(3); + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then + ! --- Far field TODO + ! --- Regularization (close field) --- Vatistas + norm2_orth = norm2_orth/norm2_r0 ! d = (r1xr2)/r0 + r_bar2 = norm2_orth/RegParam(is)**2 + Kv = r_bar2/sqrt(1+r_bar2**2) + Kv = SegGamma(is)*fourpi_inv*Kv*(norm_a+norm_b)/(denominator + MINDENOM) + Uind(1:3) = Kv*crossprod(1:3) + end if + end if ! denominator size or distances too small + end if ! + Uind_out(1:3,icp) = Uind_out(1:3,icp)+Uind(1:3) + end do ! Loop on segments + enddo ! Loop on control points + !$OMP END DO + !$OMP END PARALLEL + + case ( idRegOffset ) ! Denominator offset + !$OMP PARALLEL default(shared) + !$OMP do private(icp,is,Uind,P1,P2,crossprod,denominator,r_bar2,Kv,norm_a,norm_b,norm2_r0,norm2_orth,xa,ya,za,xb,yb,zb) schedule(runtime) + do icp=iCPStart,iCPEnd ! loop on CPs + do is=iSegStart,iSegEnd ! loop on selected segments + Uind = 0.0_ReKi + P1 = SegPoints(1:3, SegConnct(1,is)) ! Segment extremity points + P2 = SegPoints(1:3, SegConnct(2,is)) + xa=CPs(1,icp)-P1(1); ya=CPs(2,icp)-P1(2); za=CPs(3,icp)-P1(3); + xb=CPs(1,icp)-P2(1); yb=CPs(2,icp)-P2(2); zb=CPs(3,icp)-P2(3); + norm_a = sqrt(xa*xa + ya*ya + za*za) + norm_b = sqrt(xb*xb + yb*yb + zb*zb) + denominator = norm_a*norm_b*(norm_a*norm_b + xa*xb+ya*yb+za*zb) + if (denominator>PRECISION_UI) then + crossprod(1) = ya*zb-za*yb; crossprod(2) = za*xb-xa*zb; crossprod(3) = xa*yb-ya*xb + norm2_orth = crossprod(1)**2 + crossprod(2)**2 + crossprod(3)**2 + if (norm2_orth>PRECISION_UI) then ! On the singularity, Uind(1:3)=0.0_ReKi + norm2_r0 = (xa-xb)*(xa-xb) + (ya-yb)*(ya-yb) +(za-zb)*(za-zb) + if (norm2_r0>PRECISION_UI) then + ! --- Far field TODO + ! --- Regularization (close field) -- Offset + denominator = denominator+RegParam(is)**2*norm2_r0 + Kv = SegGamma(is)*fourpi_inv*(norm_a+norm_b)/(denominator + MINDENOM) + Uind(1:3) = Kv*crossprod(1:3) + end if + end if ! denominator size or distances too small + end if ! + Uind_out(1:3,icp) = Uind_out(1:3,icp)+Uind(1:3) + end do ! Loop on segments + enddo ! Loop on control points + !$OMP END DO + !$OMP END PARALLEL + case default + print*,'[ERROR] Unknown RegFunction for segment',RegFunction + STOP + end select +end subroutine ui_seg + +!> Induced velocity from `nPart` particles at `nCPs` control points. The velocity gradient is not computed +subroutine ui_part_nograd(CPs, Part, Alpha, RegFunction, RegParam, UIout, nCPs, nPart) + integer(IntKi), intent(in) :: nCPs + integer(IntKi), intent(in) :: nPart + real(ReKi), dimension(:,:), intent(in) :: CPs !< Control points (3 x nCPs) + real(ReKi), dimension(:,:), intent(inout) :: UIout !< Induced velocity, with side effects! (3 x nCPs) + real(ReKi), dimension(:,:), intent(in) :: Part !< Particle positions (3 x nPart) + real(ReKi), dimension(:,:), intent(in) :: Alpha !< Particle intensity [m^3/s] (3 x nPart) omega dV= alpha + integer(IntKi), intent(in) :: RegFunction !< Regularization function + real(ReKi), dimension(:), intent(in) :: RegParam !< Regularization parameter (nPart) + real(ReKi), dimension(3) :: UItmp !< + real(ReKi), dimension(3) :: DP !< + integer :: icp,ip + ! TODO: inlining of regularization + !$OMP PARALLEL DEFAULT(SHARED) + !$OMP DO PRIVATE(icp,ip, DP, UItmp) schedule(runtime) + do icp=1,nCPs ! loop on CPs + do ip=1,nPart ! loop on particles + UItmp(1:3) = 0.0_ReKi + DP(1:3) = CPs(1:3,icp)-Part(1:3,ip) + call ui_part_nograd_11(DP, Alpha(1:3,ip), RegFunction , RegParam(ip), UItmp) + UIout(1:3,icp)=UIout(1:3,icp)+UItmp(1:3) + enddo! loop on particles + enddo ! loop CPs + !$OMP END DO + !$OMP END PARALLEL +end subroutine ui_part_nograd + +!> Induced velocity from 1 particle at 1 control point. The velocity gradient is not computed +subroutine ui_part_nograd_11(DeltaP, Alpha, RegFunction, RegParam, Ui) + real(ReKi), dimension(3), intent(out) :: Ui !< no side effects + real(ReKi), dimension(3), intent(in) :: DeltaP !< CP-PP "control point - particle point" + real(ReKi), dimension(3), intent(in) :: Alpha !< Particle intensity [m^2/s] alpha=om.dV + integer(IntKi), intent(in) :: RegFunction !< + real(ReKi), intent(in) :: RegParam !< + real(ReKi),dimension(3) :: C !< Cross product of Alpha and r + real(ReKi) :: E !< Exponential poart for the mollifider + real(ReKi) :: r3_inv !< + real(ReKi) :: rDeltaP !< norm , distance between point and particle + real(ReKi) :: ScalarPart !< the part containing the inverse of the distance, but not 4pi, Mollifier + rDeltaP=sqrt(DeltaP(1)**2+ DeltaP(2)**2+ DeltaP(3)**2)! norm + if (rDeltaP<MINNORM) then !--- Exactly on the Singularity + Ui(1:3) = 0.0_ReKi + return + else !--- Normal Procedure + C(1) = Alpha(2) * DeltaP(3) - Alpha(3) * DeltaP(2) + C(2) = Alpha(3) * DeltaP(1) - Alpha(1) * DeltaP(3) + C(3) = Alpha(1) * DeltaP(2) - Alpha(2) * DeltaP(1) + select case (RegFunction) ! + case (idRegNone) ! No mollification + r3_inv = 1._ReKi/(rDeltaP**3) + ScalarPart = r3_inv*fourpi_inv + case (idRegExp) ! Exponential mollifier + r3_inv = 1._ReKi/(rDeltaP**3) + E = exp(-rDeltaP**3/RegParam**3) + ScalarPart = (1._ReKi-E)*r3_inv*fourpi_inv + case (idRegCompact) ! Compact support + r3_inv = 1._ReKi/sqrt(RegParam**6+rDeltaP**6) + ScalarPart = r3_inv*fourpi_inv + case default + print*,'[ERROR] Wrong regularization function for particles',RegFunction + STOP + end select + Ui(1:3)=C*ScalarPart + end if ! not on singularity +end subroutine ui_part_nograd_11 + +!> Velocity induced by one vortex quad on nCPs Control Points +subroutine ui_quad_n1(CPs, nCPs, P1, P2, P3, P4, Gamm, RegFunction, RegParam, Uind) + integer, intent(in) :: nCPs !< + real(ReKi), dimension(:,:), intent(in) :: CPs !< 3 x "nCPs"++ + real(ReKi), dimension(3), intent(in) :: P1,P2,P3,P4 !< Coordinates of vortex quadrilateral + real(ReKi), intent(in) :: Gamm + integer(IntKi) , intent(in) :: RegFunction !< Regularization model (e.g. LambOseen) + real(ReKi), intent(in) :: RegParam !< Regularization parameter [m] + real(ReKi), dimension(:,:), intent(inout) :: Uind !< side effects!!! 3 x "nCPs++" + real(ReKi), dimension(3) :: CP !< + real(ReKi), dimension(3) :: Uindtmp !< + real(ReKi), dimension(3) :: DP1 !< + real(ReKi), dimension(3) :: DP2 !< + integer :: icp + ! + !OMP PARALLEL DEFAULT(SHARED) + !OMP DO PRIVATE(icp,CP,Uindtmp,DP1,DP2) schedule(runtime) + do icp=1,nCPs + CP(1:3)=CPs(1:3,icp) + ! 1-2 segment + DP1=CP-P1; DP2=CP-P2; + call ui_seg_11 ( DP1, DP2, Gamm, RegFunction, RegParam, Uindtmp) + Uind(1:3,icp) = Uind(1:3,icp)+Uindtmp(1:3) + ! 3-4 segment + DP1=CP-P3; DP2=CP-P4; + call ui_seg_11 ( DP1, DP2, Gamm, RegFunction, RegParam, Uindtmp) + Uind(1:3,icp) = Uind(1:3,icp)+Uindtmp(1:3) + ! 2-3 segment + DP1=CP-P2; DP2=CP-P3; + call ui_seg_11 ( DP1, DP2, Gamm, RegFunction, RegParam, Uindtmp) + Uind(1:3,icp) = Uind(1:3,icp)+Uindtmp(1:3) + ! 4-1 segment + DP1=CP-P4; DP2=CP-P1; + call ui_seg_11 ( DP1, DP2, Gamm, RegFunction, RegParam, Uindtmp) + Uind(1:3,icp) = Uind(1:3,icp)+Uindtmp(1:3) + end do ! loop on CPs + !OMP END DO + !OMP END PARALLEL +end subroutine ui_quad_n1 + +end module FVW_BiotSavart diff --git a/OpenFAST/modules/aerodyn/src/FVW_IO.f90 b/OpenFAST/modules/aerodyn/src/FVW_IO.f90 new file mode 100644 index 000000000..9dc0f23db --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_IO.f90 @@ -0,0 +1,411 @@ +module FVW_IO + + USE FVW_Types + USE FVW_Subs + use FVW_VortexTools + implicit none + +contains + +! ============================================================================== +!> Reads the input file for FVW +SUBROUTINE FVW_ReadInputFile( FileName, p, Inp, ErrStat, ErrMsg ) + character(len=*), intent(in) :: FileName !< Input file name for FVW + type( FVW_ParameterType ), intent(inout) :: p !< Parameters + type(FVW_InputFile), intent(out) :: Inp !< Data stored in the module's input file + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + character(1024) :: PriPath ! the path to the primary input file + character(1024) :: VTK_fps_line ! string to temporarially hold value of read line for VTK_fps + integer(IntKi) :: UnIn + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + ! Open file + CALL GetNewUnit( UnIn ) + CALL OpenFInpfile(UnIn, TRIM(FileName), ErrStat2, ErrMsg2) + if (Check( ErrStat2 /= ErrID_None , 'Could not open input file')) return + CALL GetPath( FileName, PriPath ) ! Input files will be relative to the path where the primary input file is located. + !------------------------------------- HEADER --------------------------------------------------- + CALL ReadCom(UnIn, FileName, 'FVW input file header line 1', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL ReadCom(UnIn, FileName, 'FVW input file header line 2', ErrStat2, ErrMsg2 ); if(Failed()) return + !------------------------ GENERAL OPTIONS ------------------------------------------- + CALL ReadCom (UnIn,FileName, '--- General option header' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%IntMethod ,'Integration method' ,'', idEuler1 , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%DTfvw ,'DTfvw' ,'', p%DTaero , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%FreeWakeStart ,'FreeWakeStart' ,'', 0.0_ReKi , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%FullCirculationStart,'FullCirculationStart','', real(20.0_ReKi*Inp%DTfvw,ReKi), ErrStat2,ErrMsg2); if(Failed())return + !------------------------ CIRCULATION SPECIFICATIONS ------------------------------------------- + CALL ReadCom(UnIn,FileName, '--- Circulation specification header' , ErrStat2, ErrMsg2 ); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%CirculationMethod ,'CirculationMethod' ,'', idCircPolarData, ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%CircSolvConvCrit ,'CircSolvConvCrit ' ,'', 0.001 , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%CircSolvRelaxation,'CircSolvRelaxation','', 0.1 , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%CircSolvMaxIter ,'CircSolvMaxIter' ,'', 30 , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVar(UnIn,FileName,Inp%CirculationFile ,'CirculationFile' ,'',ErrStat2,ErrMsg2); if(Failed())return + !------------------------ WAKE OPTIONS ------------------------------------------- + CALL ReadCom (UnIn,FileName, '=== Separator' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadCom (UnIn,FileName, '--- Wake options header' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadCom (UnIn,FileName, '--- Wake extent header' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVar (UnIn,FileName,Inp%nNWPanels ,'nNWPanels' ,'' , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVar (UnIn,FileName,Inp%nFWPanels ,'nFWPanels' ,'' , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%nFWPanelsFree ,'nFWPanelsFree' ,'', Inp%nFWPanels , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%FWShedVorticity ,'FWShedVorticity' ,'', .False. , ErrStat2,ErrMsg2); if(Failed())return + + CALL ReadCom (UnIn,FileName, '--- Wake regularization header' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%DiffusionMethod ,'DiffusionMethod' ,'',idDiffusionNone , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%RegDeterMethod ,'RegDeterMethod' ,'',idRegDeterManual, ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%RegFunction ,'RegFunction' ,'',idRegVatistas , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%WakeRegMethod ,'WakeRegMethod' ,'',idRegConstant , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVar (UnIn,FileName,Inp%WakeRegParam ,'WakeRegParam' ,'' , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVar (UnIn,FileName,Inp%WingRegParam ,'WingRegParam' ,'' , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%CoreSpreadEddyVisc ,'CoreSpreadEddyVisc','',100.0_ReKi , ErrStat2,ErrMsg2); if(Failed())return + + CALL ReadCom (UnIn,FileName, '--- Wake treatment header' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%TwrShadowOnWake ,'TwrShadowOnWake' ,'',.false. , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%ShearModel ,'ShearModel' ,'',idShearNone , ErrStat2,ErrMsg2); if(Failed())return + + CALL ReadCom (UnIn,FileName, '--- Speed up header ' , ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%VelocityMethod ,'VelocityMethod' ,'',idVelocityBasic , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%TreeBranchFactor ,'TreeBranchFactor' ,'',2.0_ReKi , ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%PartPerSegment ,'PartPerSegment' ,'', 1 , ErrStat2,ErrMsg2); if(Failed())return +! Inp%TwrShadowOnWake = .False. +! Inp%VelocityMethod = idVelocityBasic +! Inp%TreeBranchFactor = 3.0_ReKi +! Inp%PartPerSegment = 1 + !------------------------ OUTPUT OPTIONS ----------------------------------------- + CALL ReadCom (UnIn,FileName, '=== Separator' ,ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadCom (UnIn,FileName, '--- Output options header' ,ErrStat2,ErrMsg2); if(Failed()) return + CALL ReadVarWDefault(UnIn,FileName,Inp%WrVTK , 'WrVTK' ,'', 0 ,ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%VTKBlades , 'VTKBlades' ,'', 1 ,ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVarWDefault(UnIn,FileName,Inp%VTKCoord , 'VTKCoord' ,'', 1 ,ErrStat2,ErrMsg2); if(Failed())return + CALL ReadVar (UnIn,FileName,VTK_fps_line , 'VTK_fps' ,'' ,ErrStat2,ErrMsg2); if(Failed())return + + ! --- Validation of inputs + if (PathIsRelative(Inp%CirculationFile)) Inp%CirculationFile = TRIM(PriPath)//TRIM(Inp%CirculationFile) + + if (Check(.not.(ANY(idCircVALID ==Inp%CirculationMethod)), 'Circulation method (CircSolvingMethod) not implemented: '//trim(Num2LStr(Inp%CirculationMethod)))) return + if (Check(.not.(ANY(idIntMethodVALID==Inp%IntMethod )) , 'Time integration method (IntMethod) not yet implemented. Use Euler 1st order method for now.')) return + if (Check(.not.(ANY(idDiffusionVALID==Inp%DiffusionMethod)) , 'Diffusion method (DiffusionMethod) not implemented: '//trim(Num2LStr(Inp%DiffusionMethod)))) return + if (Check(.not.(ANY(idRegDeterVALID ==Inp%RegDeterMethod)) , 'Regularization determination method (RegDeterMethod) not yet implemented: '//trim(Num2LStr(Inp%RegDeterMethod)))) return + if (Check(.not.(ANY(idRegVALID ==Inp%RegFunction )), 'Regularization function (RegFunction) not implemented: '//trim(Num2LStr(Inp%RegFunction)))) return + if (Check(.not.(ANY(idRegMethodVALID==Inp%WakeRegMethod)), 'Wake regularization method (WakeRegMethod) not implemented: '//trim(Num2LStr(Inp%WakeRegMethod)))) return + if (Check(.not.(ANY(idShearVALID ==Inp%ShearModel )), 'Shear model (ShearModel) not valid: '//trim(Num2LStr(Inp%ShearModel)))) return + if (Check(.not.(ANY(idVelocityVALID ==Inp%VelocityMethod )), 'Velocity method (VelocityMethod) not valid: '//trim(Num2LStr(Inp%VelocityMethod)))) return + + if (Check( Inp%DTfvw < p%DTaero, 'DTfvw must be >= DTaero from AD15.')) return + if (abs(Inp%DTfvw-p%DTaero)>epsilon(1.0_ReKi)) then + ! subcycling + if (Check(Inp%IntMethod/=idEuler1 , 'Sub-cycling (DTfvw>DTaro) is only possible with Forward Euler `IntMethod`')) return + endif + if (Inp%CirculationMethod == idCircPolarData) then + if (Check( Inp%nNWPanels<1 , 'Number of near wake panels (`nNWPanels`) must be >=1 when using circulation solving with polar data (`CircSolvingMethod=1`)')) return + endif + + if (Check( Inp%nNWPanels<0 , 'Number of near wake panels must be >=0')) return + if (Check( Inp%nFWPanels<0 , 'Number of far wake panels must be >=0')) return + if (Check( Inp%nFWPanelsFree<0 , 'Number of free far wake panels must be >=0')) return + if (Check( Inp%nFWPanelsFree>Inp%nFWPanels , 'Number of free far wake panels must be <=Number of far wake panels')) return + + if (Check(Inp%WakeRegParam<0 , 'Wake regularization parameter (WakeRegParam) should be positive')) return + if (Check(Inp%WingRegParam<0 , 'Wing regularization parameter (WakeRegParam) should be positive')) return + if (Check(Inp%CoreSpreadEddyVisc<0 , 'Core spreading eddy viscosity (CoreSpreadEddyVisc) should be positive')) return + + ! Removing the shed vorticity is a dangerous option if this is done too close to the blades. + ! To be safe, we will no matter what ensure that the last segments of NW are 0 if FWShedVorticity is False (see PackPanelsToSegments) + ! Still we force the user to be responsible. + if (Check((.not.(Inp%FWShedVorticity)) .and. Inp%nNWPanels<30, '`FWShedVorticity` should be true if `nNWPanels`<30. Alternatively, use a larger number of NWPanels ')) return + + Inp%DTvtk = Get_DTvtk( VTK_fps_line, p%DTaero, Inp%DTfvw ) + + ! At least one NW panel if FW, this shoudln't be a problem since the LL is in NW, but safety for now + !if (Check( (Inp%nNWPanels<=0).and.(Inp%nFWPanels>0) , 'At least one near wake panel is required if the number of far wake panel is >0')) return + call CleanUp() + +CONTAINS + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'FVW_ReadInputFile') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + logical function Check(Condition, ErrMsg_in) + logical, intent(in) :: Condition + character(len=*), intent(in) :: ErrMsg_in + Check=Condition + if (Check) then + call SetErrStat(ErrID_Fatal, 'Error in file '//TRIM(FileName)//': '//trim(ErrMsg_in), ErrStat, ErrMsg, 'FVW_ReadInputFile'); + call CleanUp() + endif + end function Check + + subroutine CleanUp() + close( UnIn ) + end subroutine + + real(DbKi) function Get_DTvtk( VTK_fps_line, DTaero, DTfvw ) + character(len=*), intent(inout) :: VTK_fps_line + real(DbKi), intent(in ) :: DTaero + real(DbKi), intent(in ) :: DTfvw + real(DbKi) :: VTK_fps + integer(IntKi) :: IOS + integer(IntKi) :: TmpRate + real(DbKi) :: TmpTime + + call Conv2UC( VTK_fps_line ) + if ( index(VTK_fps_line, "DEFAULT" ) == 1 ) then ! at DTfvw frequency + Get_DTvtk = DTfvw + elseif ( index(VTK_fps_line, "ALL" ) == 1 ) then ! at DTaero frequency + Get_DTvtk = DTaero + else ! read a number. Calculate this later. {will use closest integer multiple of DT} + read( VTK_fps_line, *, IOSTAT=IOS) VTK_fps + CALL CheckIOS ( IOS, FileName, 'VTK_fps', NumType, ErrStat2, ErrMsg2 ); if (Failed()) return; + + ! convert frames-per-second to seconds per sample: + if ( EqualRealNos(VTK_fps, 0.0_DbKi) ) then + Get_DTvtk = HUGE(1.0_DbKi) + else + TmpTime = 1.0_DbKi / VTK_fps + TmpRate = max( NINT( TmpTime / DTaero ),1_IntKi ) ! Can't be smaller that DTaero + Get_DTvtk = TmpRate * DTaero + ! warn if DTvtk is not TmpTime + if (.not. EqualRealNos(Get_DTvtk, TmpTime)) then + call SetErrStat(ErrID_Info, '1/VTK_fps is not an integer multiple of DT. FVW will output VTK information at '//& + trim(num2lstr(1.0_DbKi/(TmpRate*DTaero)))//' fps, the closest rate possible.',ErrStat,ErrMsg,'FVW_ReadInputFile') + end if + end if + end if + end function Get_DTvtk + + +END SUBROUTINE FVW_ReadInputFile + +!================================================= +!> Export FVW variables to VTK +!! NOTE: when entering this function nNW and nFW has been incremented by 1 +subroutine WrVTK_FVW(p, x, z, m, FileRootName, VTKcount, Twidth, bladeFrame, HubOrientation, HubPosition) + use FVW_VTK ! for all the vtk_* functions + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< States + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraints + type(FVW_MiscVarType), intent(in ) :: m !< MiscVars + character(*), intent(in) :: FileRootName !< Name of the file to write the output in (excluding extension) + integer(IntKi), intent(in) :: VTKcount !< Indicates number for VTK output file (when 0, the routine will also write reference information) + integer(IntKi), intent(in) :: Twidth !< Number of digits in the maximum write-out step (used to pad the VTK write-out in the filename with zeros) + logical, intent(in ) :: bladeFrame !< Output in blade coordinate frame + real(ReKi),optional,dimension(3,3), intent(in) :: HubOrientation + real(ReKi),optional,dimension(3) , intent(in) :: HubPosition + + ! local variables + integer:: iW + character(1024) :: FileName + character(255) :: Label + character(Twidth) :: Tstr ! string for current VTK write-out step (padded with zeros) + character(1), dimension(3) :: I2ABC =(/'A','B','C'/) + integer(IntKi) :: nSeg, nSegP, nSegNW + logical :: bMirror + !integer(IntKi) :: ErrStat2 + !character(ErrMsgLen) :: ErrMsg2 + real(Reki), dimension(:,:,:), allocatable :: dxdt_0 !< + + type(FVW_VTK_Misc) :: mvtk + + call vtk_misc_init(mvtk) + + if (bladeFrame) then + if (present(HubOrientation) .and. present(HubPosition)) then + call set_vtk_coordinate_transform(HubOrientation,HubPosition,mvtk) + else + Call ProgAbort('Programming error in WrVTK_FVW call: Cannot use the WrVTK_FVW with bladeFrame==TRUE without the optional arguments of HubOrientation and HubPosition') + endif + endif + + if (DEV_VERSION) then + print*,'------------------------------------------------------------------------------' + print'(A,L1,A,I0,A,I0,A,I0)','VTK Output - First call ',m%FirstCall, ' nNW:',m%nNW,' nFW:',m%nFW,' i:',VTKCount + endif + ! + call set_vtk_binary_format(.false.,mvtk) ! TODO binary fails + + ! TimeStamp + write(Tstr, '(i' // trim(Num2LStr(Twidth)) //'.'// trim(Num2LStr(Twidth)) // ')') VTKcount + + ! --------------------------------------------------------------------------------} + ! --- Blade + ! --------------------------------------------------------------------------------{ + ! --- Blade Quarter chord points (AC) + do iW=1,p%VTKBlades + write(Label,'(A,A)') 'BldPointCP.Bld', i2ABC(iW) + Filename = TRIM(FileRootName)//'.'//trim(Label)//'.'//Tstr//'.vtk' + if ( vtk_new_ascii_file(trim(filename),Label,mvtk) ) then + call vtk_dataset_polydata(m%CP_LL(1:3,1:p%nSpan,iW),mvtk,bladeFrame) + call vtk_point_data_init(mvtk) + call vtk_point_data_scalar(m%Gamma_ll( 1:p%nSpan,iW),'Gamma_ll',mvtk) + call vtk_point_data_vector(m%Vind_ll (1:3,1:p%nSpan,iW),'Vind_ll',mvtk) + call vtk_point_data_vector(m%Vtot_ll (1:3,1:p%nSpan,iW),'Vtot_ll',mvtk) + call vtk_point_data_vector(m%Vstr_ll (1:3,1:p%nSpan,iW),'Vstr_ll',mvtk) + call vtk_point_data_vector(m%Vwnd_ll (1:3,1:p%nSpan,iW),'Vwnd_ll',mvtk) + call vtk_point_data_vector(m%Tang (1:3,1:p%nSpan,iW),'Tangent',mvtk) + call vtk_point_data_vector(m%Norm (1:3,1:p%nSpan,iW),'Normal',mvtk) + call vtk_point_data_vector(m%Orth (1:3,1:p%nSpan,iW),'Orth',mvtk) + call vtk_close_file(mvtk) + endif + enddo + ! --- Lifting line panels + do iW=1,p%VTKBlades + write(Label,'(A,A)') 'LL.Bld', i2ABC(iW) + Filename = TRIM(FileRootName)//'.'//trim(Label)//'.'//Tstr//'.vtk' + call WrVTK_Lattice(FileName, mvtk, m%r_LL(1:3,:,:,iW), m%Gamma_LL(:,iW:iW), bladeFrame=bladeFrame) + enddo + ! --------------------------------------------------------------------------------} + ! --- Near wake + ! --------------------------------------------------------------------------------{ + ! --- Near wake panels + do iW=1,p%VTKBlades + write(Label,'(A,A)') 'NW.Bld', i2ABC(iW) + Filename = TRIM(FileRootName)//'.'//trim(Label)//'.'//Tstr//'.vtk' + if (m%FirstCall) then ! Small Hack - At t=0, NW not set, but first NW panel is the LL panel + allocate(dxdt_0(3, size(m%dxdt_NW,2) , m%nNW+1)); dxdt_0=0.0_ReKi + call WrVTK_Lattice(FileName, mvtk, m%r_LL(1:3,:,1:2,iW), m%Gamma_LL(:,iW:iW),dxdt_0, bladeFrame=bladeFrame) + deallocate(dxdt_0) + else + call WrVTK_Lattice(FileName, mvtk, x%r_NW(1:3,:,1:m%nNW+1,iW), x%Gamma_NW(:,1:m%nNW,iW), m%dxdt_NW(:,:,1:m%nNW+1,iW), bladeFrame=bladeFrame) + endif + enddo + ! --------------------------------------------------------------------------------} + ! --- Far wake + ! --------------------------------------------------------------------------------{ + ! --- Far wake panels + do iW=1,p%VTKBlades + write(Label,'(A,A)') 'FW.Bld', i2ABC(iW) + Filename = TRIM(FileRootName)//'.'//trim(Label)//'.'//Tstr//'.vtk' + call WrVTK_Lattice(FileName, mvtk, x%r_FW(1:3,1:FWnSpan+1,1:m%nFW+1,iW), x%Gamma_FW(1:FWnSpan,1:m%nFW,iW),m%dxdt_FW(:,:,1:m%nFW+1,iW), bladeFrame=bladeFrame) + enddo + ! --------------------------------------------------------------------------------} + ! --- All Segments + ! --------------------------------------------------------------------------------{ + ! NOTE: now we rely on the fact that the segments in Misc are well set + ! These segments are correct after a call to CalcOutput + ! The alternative is to call PackPanelsToSegments as was done before + ! This would require to allocate some local SegPoints,SegConnct here. + ! False below is to avoid writing the mirrored vorticity, this could be an option though + bMirror= (p%ShearModel==idShearMirror) .and. (p%VTKBlades<0) ! NOTE: temporary hack to output mirrored vorticity + call CountSegments(p, m%nNW, m%nFW, 1, nSeg, nSegP, nSegNW) + if (bMirror) then + nSeg = 2*nSeg + nSegP = 2*nSegP + endif + Filename = TRIM(FileRootName)//'.AllSeg.'//Tstr//'.vtk' + CALL WrVTK_Segments(Filename, mvtk, m%SegPoints(:,1:nSegP), m%SegConnct(:,1:nSeg), m%SegGamma(1:nSeg), m%SegEpsilon(1:nSeg), bladeFrame) + + if(.false.) print*,z%Gamma_LL(1,1) ! unused var for now +end subroutine WrVTK_FVW + + +subroutine WrVTK_Segments(filename, mvtk, SegPoints, SegConnct, SegGamma, SegEpsilon, bladeFrame) + use FVW_VTK + character(len=*),intent(in) :: filename + type(FVW_VTK_Misc), intent(inout) :: mvtk !< miscvars for VTK output + real(ReKi), dimension(:,:), intent(in) :: SegPoints !< + integer(IntKi), dimension(:,:), intent(in) :: SegConnct !< + real(ReKi), dimension(:) , intent(in) :: SegGamma !< + real(ReKi), dimension(:) , intent(in) :: SegEpsilon !< + logical, intent(in ) :: bladeFrame !< Output in blade coordinate frame + if ( vtk_new_ascii_file(filename,'Sgmt',mvtk) ) then + call vtk_dataset_polydata(SegPoints(1:3,:),mvtk,bladeFrame) + call vtk_lines(SegConnct(1:2,:)-1,mvtk) ! NOTE: VTK indexing at 0 + call vtk_cell_data_init(mvtk) + call vtk_cell_data_scalar(SegGamma ,'Gamma',mvtk) + call vtk_cell_data_scalar(SegEpsilon,'Epsilon',mvtk) +! call vtk_cell_data_scalar(real(SegConnct(3,:), ReKi),'Age',mvtk) + !call vtk_cell_data_scalar(real(SegConnct(4,:), ReKi),'Span',mvtk) + call vtk_close_file(mvtk) + endif +end subroutine + +subroutine WrVTK_Lattice(filename, mvtk, LatticePoints, LatticeGamma, LatticeData3d, bladeFrame) + use FVW_VTK ! for all the vtk_* functions + character(len=*), intent(in) :: filename + type(FVW_VTK_Misc), intent(inout) :: mvtk !< miscvars for VTK output + real(Reki), dimension(:,:,:), intent(in ) :: LatticePoints !< Array of points 3 x nSpan x nDepth + real(Reki), dimension(:,:), intent(in ) :: LatticeGamma !< Array of nSpan x nDepth + real(Reki), dimension(:,:,:), intent(in ), optional :: LatticeData3d !< Array of n x nSpan x nDepth KEEP ME + logical, intent(in ) :: bladeFrame !< Output in blade coordinate frame + ! + integer(IntKi), dimension(:,:), allocatable :: Connectivity + real(ReKi), dimension(:,:), allocatable :: Points + + CALL LatticeToPanlConnectivity(LatticePoints, Connectivity, Points) + + if ( vtk_new_ascii_file(filename,'',mvtk)) then + call vtk_dataset_polydata(Points,mvtk,bladeFrame) + call vtk_quad(Connectivity,mvtk) + call vtk_cell_data_init(mvtk) + call vtk_cell_data_scalar(LatticeGamma,'Gamma',mvtk) + if (present(LatticeData3d)) then + call vtk_point_data_init(mvtk) + call vtk_point_data_vector(LatticeData3d,'Uconv',mvtk) + endif + call vtk_close_file(mvtk) + endif + +end subroutine WrVTK_Lattice + +subroutine LatticeToPanlConnectivity(LatticePoints, Connectivity, Points) + real(Reki), dimension(:,:,:), intent(in ) :: LatticePoints !< Array of points 3 x nSpan x nDepth + integer(IntKi), dimension(:,:), allocatable :: Connectivity + real(ReKi), dimension(:,:), allocatable :: Points + ! Local + integer(IntKi) :: nSpan, nDepth + integer(IntKi) :: iSpan, iDepth, k + nSpan = size(LatticePoints,2) + nDepth = size(LatticePoints,3) + + if (allocated(Connectivity)) deallocate(Connectivity) + allocate(Connectivity(1:4, 1:(nSpan-1)*(nDepth-1))) + if (allocated(Points)) deallocate(Points) + allocate(Points(1:3, 1:nSpan*nDepth)) + + k=1 + do iDepth=1,nDepth-1; do iSpan=1,nSpan-1 + Connectivity(1,k)=(iDepth-1)*nSpan+(iSpan-1) + Connectivity(2,k)=(iDepth-1)*nSpan+(iSpan ) + Connectivity(3,k)=(iDepth )*nSpan+(iSpan) + Connectivity(4,k)=(iDepth )*nSpan+(iSpan-1) + k=k+1 + enddo; enddo + + k=1 + do iDepth=1,nDepth; do iSpan=1,nSpan + Points(1:3,k) = LatticePoints(1:3,iSpan,iDepth) + k=k+1 + enddo; enddo + +! do iWing=1,p%NumBlades +! if ( vtk_new_ascii_file(trim(filename),Label,mvtk) ) then +! ! Buffer for points +! k=1; do iNW=1,nNW; do iSpan=1,nSpan +! Buffer(1:3,k) = Misc%NWake%r_nearj(1:3,iSpan,iNW,iWing) +! k=k+1 +! enddo; enddo +! call vtk_dataset_polydata(Buffer,mvtk) +! call vtk_quad(Connectivity) +! call vtk_cell_data_init() +! ! Buffer for Gammas m1 +! k=1; do iNW=1,(nNW-1); do iSpan=1,(nSpan-1) +! if (iSpan<p%NumBlNds_start) then +! Buffer1d(k)=0 +! else if (iSpan==p%NumBlNds_start) then +! Buffer1d(k)=-Misc%NWake%Gamma_nearjm1(iNW,iSpan,iWing) +! else +! Buffer1d(k)=-Misc%NWake%Gamma_nearjm1(iNW,iSpan,iWing)+Buffer1d(k-1) +! endif +! k=k+1 +! enddo; enddo +! call vtk_cell_data_scalar(Buffer1d,'Gamma_NW_p1') +end subroutine + + + +END MODULE FVW_IO diff --git a/OpenFAST/modules/aerodyn/src/FVW_Registry.txt b/OpenFAST/modules/aerodyn/src/FVW_Registry.txt new file mode 100644 index 000000000..fb513c41c --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_Registry.txt @@ -0,0 +1,233 @@ +################################################################################################################################## +# Registry for FVW +# Entries are of the form +# keyword <modulename/modname> <TypeBeingDefined> <FieldType> <FieldName> <Dims> <InitialValue> <Ctrl> "<DESCRIP>" "<UNITS>" +################################################################################################################################## +include Registry_NWTC_Library.txt +usefrom AirfoilInfo_Registry.txt +usefrom UnsteadyAero_Registry.txt + + +##################### Registry for FVW ############### +# ..... PARAMETERS ............. +#FVW_ParameterType +typedef FVW/FVW ParameterType IntKi nWings - - - "Number of Wings" - +typedef ^ ^ IntKi nSpan - - - "TODO, should be defined per wing. Number of spanwise element" - +typedef ^ ^ IntKi AFindx :: - - "Index to the airfoils from AD15 [idx1= BladeNode, idx2=Blade number]" - +typedef ^ ^ ReKi Chord :: - - "Chord of each blade element from input file [idx1=BladeNode, idx2=Blade number]" - +typedef ^ ^ IntKi nNWMax - - - "Maximum number of nw panels, per wing" - +typedef ^ ^ IntKi nFWMax - - - "Maximum number of fw panels, per wing" - +typedef ^ ^ IntKi nFWFree - - - "Number of fw panels that are free, per wing" - +typedef ^ ^ Logical FWShedVorticity - - - "Include shed vorticity in the far wake" - +typedef ^ ^ IntKi IntMethod - - - "Integration Method (1=RK4, 2=AB4, 3=ABM4, 5=Euler1)" - +typedef ^ ^ ReKi FreeWakeStart - - - "Time when wake starts convecting (rolling up)" s +typedef ^ ^ ReKi FullCirculationStart - - - "Time when the circulation is full" s +typedef ^ ^ IntKi CirculationMethod - - - "Method to determine the circulation" - +typedef ^ ^ ReKi PrescribedCirculation : - - "Prescribed circulation on all lifting lines" "m/s" +typedef ^ ^ IntKi CircSolvMaxIter - - - "Maximum number of iterations for circulation solving" - +typedef ^ ^ ReKi CircSolvConvCrit - - - "Convergence criterion for circulation solving" - +typedef ^ ^ ReKi CircSolvRelaxation - - - "Relaxation factor for circulation solving" - +typedef ^ ^ IntKi CircSolvPolar - - - "(0=Use AD polars, 1=2PiAlpha, 2=sin(2pialpha)" - +typedef ^ ^ IntKi DiffusionMethod - - - "Diffusion method (None, CoreSpreading, PSE)" - +typedef ^ ^ ReKi CoreSpreadEddyVisc - - - "Eddy viscosity used in the core spreading method" +typedef ^ ^ IntKi RegDeterMethod - - - "Regularization determinatino method (manual, automatic)" - +typedef ^ ^ IntKi RegFunction - - - "Type of regularizaion function (LambOseen, Vatistas, see FVW_BiotSavart)" - +typedef ^ ^ IntKi WakeRegMethod - - - "Method for regularization (constant, stretching, age, etc.)" - +typedef ^ ^ ReKi WakeRegParam - - - "Initial value of the regularization parameter" +typedef ^ ^ ReKi WingRegParam - - - "Regularization parameter of the wing" +typedef ^ ^ IntKi ShearModel - - - "Option for shear modelling" +typedef ^ ^ Logical TwrShadowOnWake - - - "Include tower shadow effects on wake" +typedef ^ ^ IntKi VelocityMethod - - - "Velocity calculation method" +typedef ^ ^ ReKi TreeBranchFactor - - - "Factor used to determine if a point is far enough" +typedef ^ ^ IntKi PartPerSegment - - - "Number of particles per segment, e.g. for tree method" +typedef ^ ^ DbKi DTaero - - - "Time interval for calls calculations" s +typedef ^ ^ DbKi DTfvw - - - "Time interval for calculating wake induced velocities" s +typedef ^ ^ ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +# Parametesr output options +typedef ^ ^ IntKi WrVTK - - - "Outputs VTK at each calcoutput call, even if main fst doesnt do it" - +typedef ^ ^ IntKi VTKBlades - - - "Outputs VTk for each blade 0=no blade, 1=Bld 1" - +typedef ^ ^ DbKi DTvtk - - - "DT between vtk writes" s +typedef ^ ^ IntKi VTKCoord - - - "Switch for VTK outputs coordinate system" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ CHARACTER(1024) VTK_OutFileRoot - - - "Rootdirectory for writing VTK files" - +typedef ^ ^ CHARACTER(1024) VTK_OutFileBase - - - "Basename for writing VTK files" - + +# ....... MiscVars ............ +# FVW_MiscVarType +typedef FVW/FVW MiscVarType Logical FirstCall - - - "True if this is the first call to update state (used in CalcOutput)" - +# Variables at wing extent +typedef ^ ^ ReKi LE ::: - - "Leading edge points" - +typedef ^ ^ ReKi TE ::: - - "Trailing edge points" - +typedef ^ ^ ReKi r_LL :::: - - "Position of the Lifting line panels" - +typedef ^ ^ ReKi s_LL :: - - "Spanwise coordinate of LL elements" m +typedef ^ ^ ReKi chord_LL :: - - "chord on LL nodes " m +# Variables at control point - Dimensions nSpan +typedef ^ ^ ReKi s_CP_LL :: - - "Spanwise coordinate of LL CP" m +typedef ^ ^ ReKi chord_CP_LL :: - - "chord on LL cp " m +typedef ^ ^ ReKi CP_LL ::: - - "Coordinates of LL CP" - +typedef ^ ^ ReKi Tang ::: - - "Unit Tangential vector on LL CP" - +typedef ^ ^ ReKi Norm ::: - - "Unit Normal vector on LL CP " - +typedef ^ ^ ReKi Orth ::: - - "Unit Orthogonal vector on LL CP" - +typedef ^ ^ ReKi dl ::: - - "Vector of elementary length along the LL" - +typedef ^ ^ ReKi Area :: - - "Area of each LL panel" - +typedef ^ ^ ReKi diag_LL :: - - "Diagonal length of each LL panel" - +typedef ^ ^ Reki Gamma_LL :: - - "Circulation on the wing lifting line (COPY of Constraint State)" - +typedef ^ ^ ReKi Vind_LL ::: - - "Induced velocity on lifting line control points" m/s +typedef ^ ^ ReKi Vtot_LL ::: - - "Total velocity on lifting line control points" m/s +typedef ^ ^ ReKi Vstr_LL ::: - - "Structural velocity on LL CP" m/s +typedef ^ ^ ReKi Vwnd_LL ::: - - "Wind on lifting line control points" m/s +typedef ^ ^ ReKi Vwnd_NW :::: - - "Wind on near wake panels" m/s +typedef ^ ^ ReKi Vwnd_FW :::: - - "Wind on far wake panels" m/s +typedef ^ ^ ReKi Vind_NW :::: - - "Induced velocity on near wake panels" m/s +typedef ^ ^ ReKi Vind_FW :::: - - "Induced velocity on far wake panels" m/s +typedef ^ ^ IntKi nNW - - - "Number of active near wake panels" - +typedef ^ ^ IntKi nFW - - - "Number of active far wake panels" - +typedef ^ ^ IntKi iStep - - - "Current step number used for update state" - +typedef ^ ^ IntKi VTKstep - - - "Current vtk output step number" - +typedef ^ ^ DbKi VTKlastTime - - - "Time the last VTK file set was written out" s +typedef ^ ^ ReKi r_wind :: - - "List of points where wind is requested for next time step" - +typedef ^ ^ ReKi PitchAndTwist :: - - "Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)]" rad +typedef ^ ^ Logical ComputeWakeInduced - - - "Compute induced velocities on this timestep" - +typedef ^ ^ DbKi OldWakeTime - - - "Time the wake induction velocities were last calculated" s +typedef ^ ^ ReKi tSpent - - - "Time spent in expensive Biot-Savart computation" s +typedef ^ ^ ReKi dxdt_NW :::: - - "State time derivatie, stored for subcylcing" - +typedef ^ ^ ReKi dxdt_FW :::: - - "State time derivatie, stored for subcylcing" - +# Convenient storage +typedef ^ ^ Reki alpha_LL :: - - "Angle of attack at lifting line CP, only computed with CircPolarData method" - +typedef ^ ^ Reki Vreln_LL :: - - "Norm of Vrel on the lifting line" - +# Segment storage (buffer) +typedef ^ ^ IntKi SegConnct :: - - "Connectivity of segments" - +typedef ^ ^ ReKi SegPoints :: - - "Points delimiting the segments" - +typedef ^ ^ ReKi SegGamma : - - "Segment circulations" - +typedef ^ ^ ReKi SegEpsilon : - - "Segment regularization parameter" - +# Wake rollup storage (buffer) +typedef ^ ^ ReKi CPs :: - - "Control points used for wake rollup computation" - +typedef ^ ^ ReKi Uind :: - - "Induced velocities obtained at control points" - +# for calculating outputs at blade nodes +typedef ^ ^ ReKi BN_AxInd :: - - "Axial induction [size: (NumBlNds,numBlades)]" - +typedef ^ ^ ReKi BN_TanInd :: - - "Tangential induction [size: (NumBlNds,numBlades)]" - +typedef ^ ^ ReKi BN_Vrel :: - - "Relative velocity [size: (NumBlNds,numBlades)]" m/s +typedef ^ ^ ReKi BN_alpha :: - - "Angle of attack [size: (NumBlNds,numBlades)]" rad +typedef ^ ^ ReKi BN_phi :: - - "angle between the plane of rotation and the direction of the local wind [size: (NumBlNds,numBlades)]" rad +typedef ^ ^ ReKi BN_Re :: - - "Reynolds number [size: (NumBlNds,numBlades)]" - +typedef ^ ^ ReKi BN_URelWind_s ::: - - "Relative wind velocity in section coordinates [size: (3,NumBlNds,numBlades)]" m/s +typedef ^ ^ ReKi BN_Cl_Static :: - - "Coefficient lift, excluding unsteady aero effects" - +typedef ^ ^ ReKi BN_Cd_Static :: - - "Coefficient drag. excluding unsteady aero effects" - +typedef ^ ^ ReKi BN_Cm_Static :: - - "Coefficient moment, excluding unsteady aero effects" - +typedef ^ ^ ReKi BN_Cl :: - - "Coefficient lift, including unsteady aero effects" - +typedef ^ ^ ReKi BN_Cd :: - - "Coefficient drag, including unsteady aero effects" - +typedef ^ ^ ReKi BN_Cm :: - - "Coefficient moment, including unsteady aero effects" - +typedef ^ ^ ReKi BN_Cx :: - - "normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade" - +typedef ^ ^ ReKi BN_Cy :: - - "tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade" - + +# TODO UA - Should be part of AeroDyn +typedef ^ ^ UA_MiscVarType m_UA - - - "misc vars for UnsteadyAero" - +typedef ^ ^ UA_OutputType y_UA - - - "outputs from UnsteadyAero" - +typedef ^ ^ UA_ParameterType p_UA - - - "parameters for UnsteadyAero" - +typedef ^ ^ LOGICAL UA_Flag - - - "logical flag indicating whether to use UnsteadyAero" - +typedef ^ ^ ReKi Vwnd_ND ::: - - "InflowOnBlade (at nodes) values modified by tower influence. ONLY for UA" m/s + +# ........ Input ............ +# FVW_InputType +typedef FVW/FVW InputType MeshType WingsMesh : - - "Input Mesh defining position and orientation of wings" +typedef ^ ^ ReKi V_wind :: - - "Wind at requested points (r_wind)" - +typedef ^ ^ ReKi HubOrientation {3}{3} - - "Orientation of hub coordinate system (for output only)" - +typedef ^ ^ ReKi HubPosition {3} - - "Origin of hub (for output only)" - + +# ........ Output ............ +# FVW_OutputType +typedef FVW/FVW OutputType ReKi Vind ::: - - "TODO mesh - Induced velocity vector. " - +typedef ^ ^ ReKi Cl_KJ :: - - "Lift coefficient from circulation (Kutta-Joukowski)" - + +#.......... ContinuousStateType ...... +# FVW_ContinuousStateType +typedef FVW/FVW ContinuousStateType ReKi Gamma_NW ::: - - "Circulation of the near wake panels" - +typedef ^ ^ ReKi Gamma_FW ::: - - "Circulation of the far wake panels" - +typedef ^ ^ ReKi r_NW :::: - - "Position of the near wake panels" - +typedef ^ ^ ReKi r_FW :::: - - "Position of the far wake panels" - +# TODO UA +typedef ^ ^ UA_ContinuousStateType UA - - - "states for UnsteadyAero" - + + +#.......... DiscreteStateType ...... +# FVW_DiscreteStateType +typedef FVW/FVW DiscreteStateType ReKi NULL - - - "Empty to satisfy framework" - +# TODO UA +typedef ^ ^ UA_DiscreteStateType UA - - - "states for UnsteadyAero" - + +#.......... ConstraintStateType ...... +# FVW_ConstraintStateType +typedef FVW/FVW ConstraintStateType Reki residual - - "Residual" - +typedef ^ ^ Reki Gamma_LL :: - - "Circulation on the wing lifting line" - + +# ....... OtherStateType ............ +# FVW_OtherStateType +typedef FVW/FVW OtherStateType IntKi NULL - - - "Number of active near wake panels" - +# TODO UA +typedef ^ ^ UA_OtherStateType UA - - - "other states for UnsteadyAero" - +typedef ^ ^ Logical UA_Flag {:}{:} - - "logical flag indicating whether to use UnsteadyAero" - + + +#.......... InitInputType ...... +# FVW_InitInputType +typedef FVW/FVW InitInputType CHARACTER(1024) FVWFileName - - - "Main FVW input file name" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ MeshType WingsMesh : - - "Input Mesh defining position and orientation of wings (nSpan+1) " - +typedef ^ ^ IntKi AFindx :: - - "Index to the airfoils from AD15 [idx1=BladeNode, idx2=Blade number]" - +typedef ^ ^ ReKi Chord :: - - "Chord of each blade element from input file [idx1=BladeNode, idx2=Blade number]" - +typedef ^ ^ ReKi RElm : - - "radius of center of each element" - +typedef ^ ^ ReKi zHub : - - "Distance to hub for each blade" m +typedef ^ ^ ReKi zLocal :: - - "Distance to blade node, measured along the blade" m +typedef ^ ^ ReKi zTip : - - "Distance to blade tip, measured along the blade" m +typedef ^ ^ ReKi rLocal :: - - "Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT" m +typedef ^ ^ IntKi NumBlades - - - "Number of blades" - +typedef ^ ^ IntKi NumBladeNodes - - - "Number of nodes on each blade" - +typedef ^ ^ DbKi DTaero - - - "Time interval for calls (from AD15)" s +typedef ^ ^ ReKi KinVisc - - - "Kinematic air viscosity" m^2/s +# TODO UA - Should be part of AeroDyn +typedef ^ ^ IntKi UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - +typedef ^ ^ LOGICAL UA_Flag - - - "logical flag indicating whether to use UnsteadyAero" - +typedef ^ ^ LOGICAL Flookup - - - "Use table lookup for f' and f'' " - +typedef ^ ^ ReKi a_s - - - "speed of sound" m/s + +#.......... InputFileType ...... +# FVW_InputFile +typedef FVW/FVW FVW_InputFile IntKi CirculationMethod - - - "Method to determine the circulation" - +typedef ^ ^ CHARACTER(1024) CirculationFile - - - "Prescribed circulation file" - +typedef ^ ^ IntKi CircSolvMaxIter - - - "Maximum number of iterations for circulation solving" - +typedef ^ ^ ReKi CircSolvConvCrit - - - "Convergence criterion for circulation solving" - +typedef ^ ^ ReKi CircSolvRelaxation - - - "Relaxation factor for circulation solving" - + +typedef ^ ^ IntKi IntMethod - - - "Integration Method (1=RK4, 2=AB4, 3=ABM4, 5=Euler1, 7=Corrector/Predictor)" - +typedef ^ ^ LOGICAL FreeWake - - - "Disable roll up, wake convects with wind only (flag)" - +typedef ^ ^ ReKi FreeWakeStart - - - "Time when wake starts convecting (rolling up)" s +typedef ^ ^ ReKi FullCirculationStart - - - "Time when the circulation is full" s +typedef ^ ^ DbKi DTfvw - - - "Time interval for calculating wake induced velocities" s +typedef ^ ^ IntKi CircSolvPolar - - - "(0=Use AD polars, 1=2PiAlpha, 2=sin(2pialpha)" - +typedef ^ ^ IntKi nNWPanels - - - "Number of nw panels" - +typedef ^ ^ IntKi nFWPanels - - - "Number of fw panels" - +typedef ^ ^ IntKi nFWPanelsFree - - - "Number of fw panels that are free" - +typedef ^ ^ Logical FWShedVorticity - - - "Include shed vorticity in the far wake" - +typedef ^ ^ IntKi DiffusionMethod - - - "Diffusion method (None, CoreSpreading, PSE)" - +typedef ^ ^ ReKi CoreSpreadEddyVisc - - - "Eddy viscosity used in the core spreading method" +typedef ^ ^ IntKi RegDeterMethod - - - "Regularization determinatino method (manual, automatic)" - +typedef ^ ^ IntKi RegFunction - - - "Type of regularizaion function (LambOseen, Vatistas, see FVW_BiotSavart)" - +typedef ^ ^ IntKi WakeRegMethod - - - "Method for regularization (constant, stretching, age, etc.)" - +typedef ^ ^ ReKi WakeRegParam - - - "Factor used in the regularization " +typedef ^ ^ ReKi WingRegParam - - - "Factor used in the regularization " +typedef ^ ^ IntKi ShearModel - - - "Option for shear modelling" +typedef ^ ^ Logical TwrShadowOnWake - - - "Include tower shadow effects on wake" +typedef ^ ^ IntKi VelocityMethod - - - "Velocity calculation method" +typedef ^ ^ ReKi TreeBranchFactor - - - "Factor used to determine if a point is far enough" +typedef ^ ^ IntKi PartPerSegment - - - "Number of particles per segment, e.g. for tree method" +typedef ^ ^ IntKi WrVTK - - - "Outputs VTK at each calcoutput call, even if main fst doesnt do it" - +typedef ^ ^ IntKi VTKBlades - - - "Outputs VTk for each blade 0=no blade, 1=Bld 1" - +typedef ^ ^ DbKi DTvtk - - - "Requested timestep between VTK outputs (calculated from the VTK_fps read in)" s +typedef ^ ^ IntKi VTKCoord - - - "Switch for VTK outputs coordinate system" - + +#.......... InitOutputType ...... +# FVW_InitOutputType +typedef FVW/FVW InitOutputType IntKi Null - - - "Empty parameter to satisfy framework" - + + + diff --git a/OpenFAST/modules/aerodyn/src/FVW_Subs.f90 b/OpenFAST/modules/aerodyn/src/FVW_Subs.f90 new file mode 100644 index 000000000..cdff22612 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_Subs.f90 @@ -0,0 +1,1088 @@ +module FVW_SUBS + + use NWTC_LIBRARY + use FVW_TYPES + use FVW_VortexTools + use FVW_BiotSavart + + implicit none + + ! --- Module parameters + ! Circulation solving methods + integer(IntKi), parameter :: idCircPolarData = 1 + integer(IntKi), parameter :: idCircNoFlowThrough = 2 + integer(IntKi), parameter :: idCircPrescribed = 3 + integer(IntKi), parameter, dimension(2) :: idCircVALID = (/idCircPolarData, idCircPrescribed /) + ! Integration method + integer(IntKi), parameter :: idRK4 = 1 + integer(IntKi), parameter :: idAB4 = 2 + integer(IntKi), parameter :: idABM4 = 3 + integer(IntKi), parameter :: idPredictor= 4 + integer(IntKi), parameter :: idEuler1 = 5 + integer(IntKi), parameter, dimension(1) :: idIntMethodVALID = (/idEuler1 /) + ! Diffusion method + integer(IntKi), parameter :: idDiffusionNone = 0 + integer(IntKi), parameter :: idDiffusionCoreSpread = 1 + integer(IntKi), parameter :: idDiffusionPSE = 2 + integer(IntKi), parameter, dimension(1) :: idDiffusionVALID = (/idDiffusionNone /) + ! Regularization Method + integer(IntKi), parameter :: idRegConstant = 1 + integer(IntKi), parameter :: idRegStretching = 2 + integer(IntKi), parameter :: idRegAge = 3 + integer(IntKi), parameter, dimension(2) :: idRegMethodVALID = (/idRegConstant,idRegAge/) + ! Regularization determination method + integer(IntKi), parameter :: idRegDeterManual = 0 + integer(IntKi), parameter :: idRegDeterAuto = 1 + integer(IntKi), parameter, dimension(2) :: idRegDeterVALID = (/idRegDeterManual, idRegDeterAuto /) + ! Shear model + integer(IntKi), parameter :: idShearNone = 0 + integer(IntKi), parameter :: idShearMirror = 1 + integer(IntKi), parameter, dimension(2) :: idShearVALID = (/idShearNone, idShearMirror /) + ! Velocity calculation method + integer(IntKi), parameter :: idVelocityBasic = 1 + integer(IntKi), parameter :: idVelocityTree = 2 + integer(IntKi), parameter :: idVelocityPart = 3 + integer(IntKi), parameter, dimension(3) :: idVelocityVALID = (/idVelocityBasic, idVelocityTree, idVelocityPart /) + + real(ReKi), parameter :: CoreSpreadAlpha = 1.25643 + + ! Implementation + integer(IntKi), parameter :: iNWStart=2 !< Index in r%NW where the near wake start (if >1 then the Wing panels are included in r_NW) + integer(IntKi), parameter :: FWnSpan=1 !< Number of spanwise far wake panels ! TODO make it an input later + logical , parameter :: DEV_VERSION=.False. +contains + +!========================================================================== +!> Helper function for 1d interpolation (interp1d) +function interpolation_array( xvals, yvals, xi, nOut, nIn ) + integer nOut, nIn, arindx, ilo + real(ReKi), dimension( nOut ) :: interpolation_array, xi + real(ReKi), dimension( nIn ) :: xvals, yvals, tmp2, tmp3 + real(ReKi) :: tmp1 + ilo = 1 + DO arindx = 1, nOut + IF ( xi( arindx ) .LT. xvals( 1 )) THEN + interpolation_array( arindx ) = yvals( 1 ) + ( xi( arindx ) - xvals( 1 )) / & + & ( xvals( 2 ) - xvals( 1 )) * ( yvals( 2 ) - yvals( 1 )) + ELSE IF ( xi( arindx ) .GT. xvals( nIn )) THEN + interpolation_array( arindx ) = yvals( nIn - 1 ) + ( xi( arindx ) - & + & xvals( nIn - 1 )) / ( xvals( nIn ) - xvals( nIn - 1 )) * & + & ( yvals( nIn ) - yvals( nIn - 1 )) + ELSE + tmp1 = real( xi( arindx ), ReKi) + tmp2 = real( xvals , ReKi) + tmp3 = real( yvals , ReKi) + interpolation_array( arindx ) = InterpBinReal( tmp1, tmp2, tmp3, ilo, nIn ) + END IF + END DO +END FUNCTION interpolation_array +!========================================================================== + +! ===================================================================================== +!> Output blade circulation +subroutine Output_Gamma(CP, Gamma_LL, iWing, iStep, iLabel, iIter) + real( ReKi ), dimension( :, : ), intent(in ) :: CP !< Control Points + real( ReKi ), dimension( : ), intent(in ) :: Gamma_LL !< Circulation on the lifting line + integer( IntKi ), intent(in ) :: iWing !< Wing index + integer( IntKi ), intent(in ) :: iStep !< Call ID + integer( IntKi ), intent(in ) :: iLabel !< Call ID + integer( IntKi ), intent(in ) :: iIter !< Call ID + character(len=255) :: filename + integer :: i + integer :: iUnit + real(ReKi) :: norm + call GetNewUnit(iUnit) + ! TODO output folder + CALL MKDIR('Gamma') + write(filename,'(A,I0,A,I0,A,I0,A,I0,A)')'Gamma/Gamma_step',int(iStep),'_lab',iLabel,'_it',iIter,'_Wing',int(iWing),'.txt' + OPEN(unit = iUnit, file = trim(filename), status="unknown", action="write") + write(iUnit,'(A)') 'norm_[m],x_[m],y_[m],z_[m], Gamma_[m^2/s]' + do i=1,size(Gamma_LL) + norm=sqrt(CP(1,i)**2+CP(2,i)**2+CP(3,i)**2) + write(iUnit,'(E14.7,A,E14.7,A,E14.7,A,E14.7,A,E14.7)') norm,',', CP(1,i),',',CP(2,i),',',CP(3,i),',', Gamma_LL(i) + enddo + close(iUnit) +endsubroutine Output_Gamma +! ===================================================================================== +!> Read a delimited file containing a circulation and interpolate it on the requested Control Points +!! The input file is a delimited file with one line of header. +!! Each following line consists of two columns: r/R_[-] and Gamma_[m^2/s] +subroutine ReadAndInterpGamma(CirculationFileName, s_CP_LL, L, Gamma_CP_LL, ErrStat, ErrMsg) + character(len=*), intent(in ) :: CirculationFileName !< Input file to read + real(ReKi), dimension(:), intent(in ) :: s_CP_LL !< Spanwise location of the lifting CP [m] + real(ReKi), intent(in ) :: L !< Full span of lifting line + real(ReKi), dimension(:), intent(out ) :: Gamma_CP_LL !< Interpolated circulation of the LL CP + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local + integer(IntKi) :: nLines + integer(IntKi) :: i + integer(IntKi) :: iStat + integer(IntKi) :: iUnit + character(len=1054) :: line + real(ReKi), dimension(:), allocatable :: sPrescr, GammaPrescr !< Radius + ErrStat = ErrID_None + ErrMsg = '' + ! --- + call GetNewUnit(iUnit) + open(unit = iUnit, file = CirculationFileName) + nLines=line_count(iUnit)-1 + ! Read Header + read(iUnit,*, iostat=istat) line + ! Read table: s/L [-], GammaPresc [m^2/s] + allocate(sPrescr(1:nLines), GammaPrescr(1:nLines)) + do i=1,nLines + read(iUnit,*, iostat=istat) sPrescr(i), GammaPrescr(i) + sPrescr(i) = sPrescr(i) * L + GammaPrescr(i) = GammaPrescr(i) + enddo + close(iUnit) + if (istat/=0) then + ErrStat=ErrID_Fatal + ErrMsg='Error occured while reading Circulation file: '//trim(CirculationFileName) + return + endif + ! NOTE: TODO TODO TODO THIS ROUTINE PERFORMS NASTY EXTRAPOLATION, SHOULD BE PLATEAUED + Gamma_CP_LL = interpolation_array( sPrescr, GammaPrescr, s_CP_LL, size(s_CP_LL), nLines ) +contains + + !> Counts number of lines in a file + integer function line_count(iunit) + integer(IntKi), intent(in) :: iunit + character(len=1054) :: line + ! safety for infinite loop.. + integer(IntKi), parameter :: nline_max=100000000 ! 100 M + integer(IntKi) :: i + line_count=0 + do i=1,nline_max + line='' + read(iunit,'(A)',END=100)line + line_count=line_count+1 + enddo + if (line_count==nline_max) then + print*,'Error: maximum number of line exceeded' + endif + 100 if(len(trim(line))>0) then + line_count=line_count+1 + endif + rewind(iunit) + end function + +endsubroutine ReadAndInterpGamma +! ===================================================================================== + +! -------------------------------------------------------------------------------- +! --- Mapping functions +! -------------------------------------------------------------------------------- + +!> Make sure the First panel of the NW match the last panel of the Trailing edge +!! - Same position of points +!! - Same circulation +subroutine Map_LL_NW(p, m, z, x, ShedScale, ErrStat, ErrMsg ) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraints states + type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states + real(ReKi), intent(in) :: ShedScale !< Time scaling of shed vorticity + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(ReKi) :: Gamma_Prev, Gamma_new + ! Local + integer(IntKi) :: iSpan , iW + ErrStat = ErrID_None + ErrMsg = "" + + ! First panel of NW is the last lifting line panel + do iW = 1,p%nWings + do iSpan = 1,p%nSpan+1 + x%r_NW(1:3, iSpan, iNWStart-1, iW) = m%r_LL(1:3, iSpan, 1, iW) ! iAge=1 + x%r_NW(1:3, iSpan, iNWStart , iW) = m%r_LL(1:3, iSpan, 2, iW) ! iAge=2 + enddo + enddo + ! First panel of NW is the last lifting line panel + do iW = 1,p%nWings + do iSpan = 1,p%nSpan + x%Gamma_NW(iSpan, iNWStart-1, iW) = z%Gamma_LL(iSpan,iW) ! iAge=1 + enddo + enddo + ! Circulations are the same on both side of the TE + if (p%nNWMax>iNWStart-1) then + do iW = 1,p%nWings + do iSpan = 1,p%nSpan + x%Gamma_NW(iSpan, iNWStart , iW) = z%Gamma_LL(iSpan,iW) ! iAge=2 + enddo + enddo + endif + ! When subcycling, we make sure the new circulation progressively ramps up from the old one + ! NOTE: subcycling needs improvement. + ! Frequencies are introduced, even for prescribed circulation, when wake roll up is included + ! If the wake is not free, the convection velocity is constant and there is no issue. + ! As a test case, the elliptical wing with constant circulation can be used, with roll up + ! The error seems to be bigger near the tip/root for this case. + if(.false.) then + if ((ShedScale<1.0_ReKi) .and. (m%nNW>=3)) then + print*,'Scaling' + do iW = 1,p%nWings + do iSpan = 1,p%nSpan + Gamma_Prev = x%Gamma_NW(iSpan, iNWStart+1, iW) ! Previous circulation + Gamma_New = x%Gamma_NW(iSpan, iNWStart , iW) + x%Gamma_NW(iSpan, iNWStart , iW) = Gamma_New*ShedScale + (1.0_ReKi-ShedScale) * Gamma_Prev + enddo + enddo + endif + endif +end subroutine Map_LL_NW + +!> Map the last NW panel with the first FW panel +subroutine Map_NW_FW(p, m, z, x, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraints states + type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: iW, iRoot + real(ReKi), dimension(p%nWings) :: FWGamma + integer(IntKi), parameter :: iAgeFW=1 !< we update the first FW panel + ErrStat = ErrID_None + ErrMsg = "" + + ! First Panel of Farwake has coordinates of last panel of near wake always + if (p%nFWMax>0) then + FWGamma(:)=0.0_ReKi + if (m%nNW==p%nNWMax) then + ! First circulation of Farwake is taken as the max circulation of last NW column + do iW=1,p%nWings + !FWGamma = sum(x%Gamma_NW(:,p%nNWMax,iW))/p%nSpan + FWGamma(iW) = maxval(x%Gamma_NW(:,p%nNWMax,iW)) + x%Gamma_FW(1:FWnSpan,iAgeFW,iW) = FWGamma(iW) + enddo + endif + + do iW=1,p%nWings + ! Find first point (in half span) where circulation is more than 0.1% of MaxGamma, call it the root + iRoot=1 + ! NOTE: this below won't work for a wing + ! Need to go from maxgamma location, and integrate spanwise position on both side to find location of tip and root vortex + !do while ((iRoot<int(p%nSpan/2)) .and. (x%Gamma_NW(iRoot, p%nNWMax,iW)< 0.001*FWGamma(iW) )) + ! iRoot=iRoot+1 + !enddo + + x%r_FW(1:3,1 ,iAgeFW,iW) = x%r_NW(1:3,iRoot ,p%nNWMax+1,iW) ! Point 1 (root) + x%r_FW(1:3,FWnSpan+1,iAgeFW,iW) = x%r_NW(1:3,p%nSpan+1 ,p%nNWMax+1,iW) ! Point FWnSpan (tip) + if ((FWnSpan==2)) then + ! in between point + x%r_FW(1:3,2,iAgeFW,iW) = x%r_NW(1:3,int(p%nSpan+1)/4 ,p%nNWMax+1,iW) ! Point (mid) + else if ((FWnSpan>2)) then + ErrMsg='Error: FWnSpan>2 not implemented.' + ErrStat=ErrID_Fatal + return + endif + enddo + endif + if (.false.) print*,z%Gamma_LL(1,1) ! Just to avoid unused var warning +endsubroutine Map_NW_FW + +!> Propagate the positions and circulation one index forward (loop from end to start) +subroutine PropagateWake(p, m, z, x, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(FVW_ConstraintStateType), intent(in ) :: z !< Constraints states + type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: iSpan, iAge, iW + ErrStat = ErrID_None + ErrMsg = "" + + ! -- Propagate far wake + do iW=1,p%nWings + do iAge=p%nFWMax+1,2,-1 ! + do iSpan=1,FWnSpan+1 + x%r_FW(1:3,iSpan,iAge,iW) = x%r_FW(1:3,iSpan,iAge-1,iW) + enddo + enddo + x%r_FW(1:3,1:FWnSpan+1,1,iW) = -999.9_ReKi ! Nullified + enddo + if (p%nFWMax>0) then + do iW=1,p%nWings + do iAge=p%nFWMax,2,-1 + do iSpan=1,FWnSpan + x%Gamma_FW(iSpan,iAge,iW) = x%Gamma_FW(iSpan,iAge-1,iW) + enddo + enddo + x%Gamma_FW(1,1:FWnSpan-1,iW) = -999.9_ReKi ! Nullified + enddo + endif + ! --- Propagate near wake + do iW=1,p%nWings + do iAge=p%nNWMax+1,iNWStart+1,-1 + do iSpan=1,p%nSpan+1 + x%r_NW(1:3,iSpan,iAge,iW) = x%r_NW(1:3,iSpan,iAge-1,iW) + enddo + enddo + x%r_NW(1:3,:,1:iNWStart,iW) = -999.9_ReKi ! Nullified + enddo + if (p%nNWMax>1) then + do iW=1,p%nWings + do iAge=p%nNWMax,iNWStart+1,-1 + do iSpan=1,p%nSpan + x%Gamma_NW(iSpan,iAge,iW) = x%Gamma_NW(iSpan,iAge-1,iW) + enddo + enddo + x%Gamma_NW(:,1:iNWStart,iW) = -999.9_ReKi ! Nullified + enddo + endif + + ! Temporary hack for sub-cycling since straight after wkae computation, the wake size will increase + ! So we do a "fake" propagation here + do iW=1,p%nWings + do iAge=p%nFWMax+1,2,-1 ! + do iSpan=1,FWnSpan+1 + m%dxdt_FW(1:3,iSpan,iAge,iW) = m%dxdt_FW(1:3,iSpan,iAge-1,iW) + enddo + enddo + !m%dxdt_FW(1:3,1:FWnSpan+1,1,iW) = -999999_ReKi ! Important not nullified. The best would be to map the last NW convection velocity for this first row. + enddo + do iW=1,p%nWings + do iAge=p%nNWMax+1,iNWStart+1,-1 + do iSpan=1,p%nSpan+1 + m%dxdt_NW(1:3,iSpan,iAge,iW) = m%dxdt_NW(1:3,iSpan,iAge-1,iW) + enddo + enddo + m%dxdt_NW(1:3,:,1:iNWStart,iW) = 0.0_ReKi ! Nullified, wing do no convect, handled by LL,NW mapping + enddo + + if (.false.) print*,m%nNW,z%Gamma_LL(1,1) ! Just to avoid unused var warning +end subroutine PropagateWake + + +subroutine print_x_NW_FW(p, m, x, label) + type(FVW_ParameterType), intent(in) :: p !< Parameters + type(FVW_MiscVarType), intent(in) :: m !< Initial misc/optimization variables + type(FVW_ContinuousStateType), intent(in) :: x !< Continuous states + character(len=*),intent(in) :: label + integer(IntKi) :: iAge + character(len=1):: flag + print*,'------------------------------------------------------------------' + print'(A,I0,A,I0)',' NW .....................iNWStart:',iNWStart,' nNW:',m%nNW + do iAge=1,p%nNWMax+1 + flag='X' + if ((iAge)<= m%nNW+1) flag='.' + print'(A,A,I0,A)',flag,'iAge ',iAge,' Root Tip' + print*,trim(label)//'x', x%r_NW(1, 1, iAge,1), x%r_NW(1, p%nSpan+1, iAge,1) + print*,trim(label)//'y', x%r_NW(2, 1, iAge,1), x%r_NW(2, p%nSpan+1, iAge,1) + print*,trim(label)//'z', x%r_NW(3, 1, iAge,1), x%r_NW(3, p%nSpan+1, iAge,1) + enddo + print'(A,I0)','FW <<<<<<<<<<<<<<<<<<<< nFW:',m%nFW + do iAge=1,p%nFWMax+1 + flag='X' + if ((iAge)<= m%nFW+1) flag='.' + print'(A,A,I0,A)',flag,'iAge ',iAge,' Root Tip' + print*,trim(label)//'x', x%r_FW(1, 1, iAge,1), x%r_FW(1, FWnSpan+1, iAge,1) + print*,trim(label)//'y', x%r_FW(2, 1, iAge,1), x%r_FW(2, FWnSpan+1, iAge,1) + print*,trim(label)//'z', x%r_FW(3, 1, iAge,1), x%r_FW(3, FWnSpan+1, iAge,1) + enddo + !print'(A,I0,A,I0)','dxdt NW .....................iNWStart:',iNWStart,' nNW:',m%nNW + !do iAge=1,p%nNWMax+1 + ! flag='X' + ! if ((iAge)<= m%nNW+1) flag='.' + ! print'(A,A,I0,A)',flag,'iAge ',iAge,' Root Tip' + ! print*,trim(label)//'x', m%dxdt_NW(1, 1, iAge,1), m%dxdt_NW(1, p%nSpan+1, iAge,1) + ! print*,trim(label)//'y', m%dxdt_NW(2, 1, iAge,1), m%dxdt_NW(2, p%nSpan+1, iAge,1) + ! print*,trim(label)//'z', m%dxdt_NW(3, 1, iAge,1), m%dxdt_NW(3, p%nSpan+1, iAge,1) + !enddo + !print'(A,I0)','dxdt FW <<<<<<<<<<<<<<<<<<<< nFW:',m%nFW + !do iAge=1,p%nFWMax+1 + ! flag='X' + ! if ((iAge)<= m%nFW+1) flag='.' + ! print'(A,A,I0,A)',flag,'iAge ',iAge,' Root Tip' + ! print*,trim(label)//'x', m%dxdt_FW(1, 1, iAge,1), m%dxdt_FW(1, FWnSpan+1, iAge,1) + ! print*,trim(label)//'y', m%dxdt_FW(2, 1, iAge,1), m%dxdt_FW(2, FWnSpan+1, iAge,1) + ! print*,trim(label)//'z', m%dxdt_FW(3, 1, iAge,1), m%dxdt_FW(3, FWnSpan+1, iAge,1) + !enddo +endsubroutine + + +! -------------------------------------------------------------------------------- +! --- PACKING/UNPACKING FUNCTIONS +! -------------------------------------------------------------------------------- +!> Establish the list of points where we will need the free stream +!! The r_wind array is allocated at initialization to the largest size possible. This is to +!! ensure that we do not violate requirements in the framework later for changing the size +!! of input and output arrays. +subroutine SetRequestedWindPoints(r_wind, x, p, m) + real(ReKi), dimension(:,:), allocatable, intent(inout) :: r_wind !< Position where wind is requested + type(FVW_ContinuousStateType), intent(inout) :: x !< States + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + integer(IntKi) :: iP_start,iP_end ! Current index of point, start and end of range + + ! Using array reshaping to ensure a given near or far wake point is always at the same location in the array. + ! NOTE: Maximum number of points are passed, whether they "exist" or not. + ! NOTE: InflowWind ignores points at (0,0,0) + !if (DEV_VERSION) then + ! ! Removing points that don't exist + ! !call print_x_NW_FW(p,m,x,'wind befr') + ! if (m%nNW<=p%nNWMax) then + ! x%r_NW(1:3, 1:p%nSpan+1, m%nNW+2:p%nNWMax+1, 1:p%nWings) = 0.0_ReKi + ! endif + ! if ( ((p%nNWMax<=1) .and. (m%nFW==0)) .or. ((m%nFW>0) .and. (m%nFW<=p%nFWMax))) then + ! x%r_FW(1:3, 1:FWnSpan+1, m%nFW+2:p%nFWMax+1, 1:p%nWings) = 0.0_ReKi + ! else + ! x%r_FW(1:3, 1:FWnSpan+1, m%nFW+1:p%nFWMax+1, 1:p%nWings) = 0.0_ReKi + ! endif + ! !call print_x_NW_FW(p,m,x,'wind after') + !endif + + ! --- LL CP + iP_start=1 + iP_end=p%nWings*p%nSpan + r_wind(1:3,iP_start:iP_end) = reshape( m%CP_LL(1:3,1:p%nSpan,1:p%nWings), (/ 3, p%nSpan*p%nWings /)) + ! --- NW points + iP_start=iP_end+1 + iP_end=iP_start-1+(p%nSpan+1)*(p%nNWMax+1)*p%nWings + r_wind(1:3,iP_start:iP_end) = reshape( x%r_NW(1:3,1:p%nSpan+1,1:p%nNWMax+1,1:p%nWings), (/ 3, (p%nSpan+1)*(p%nNWMax+1)*p%nWings /)) + ! --- FW points + if (p%nFWMax>0) then + iP_start=iP_end+1 + iP_end=iP_start-1+(FWnSpan+1)*(p%nFWMax+1)*p%nWings + r_wind(1:3,iP_start:iP_end) = reshape( x%r_FW(1:3,1:FWnSpan+1,1:p%nFWMax+1,1:p%nWings), (/ 3, (FWnSpan+1)*(p%nFWMax+1)*p%nWings /)) + endif + + !if (DEV_VERSION) then + ! ! Additional checks + ! if (any(r_wind(3,:)<=-99999_ReKi)) then + ! call print_x_NW_FW(p,m,x,'wind after') + ! print*,'Error in wind' + ! STOP + ! endif + ! ! Removing points that don't exist + ! if (m%nNW<=p%nNWMax) then + ! x%r_NW(1:3, 1:p%nSpan+1, m%nNW+2:p%nNWMax+1, 1:p%nWings) = -999999.0_ReKi + ! endif + ! if ( ((p%nNWMax<=1) .and. (m%nFW==0)) .or. ((m%nFW>0) .and. (m%nFW<=p%nFWMax))) then + ! x%r_FW(1:3, 1:FWnSpan+1, m%nFW+2:p%nFWMax+1, 1:p%nWings) =-999999.0_ReKi + ! else + ! x%r_FW(1:3, 1:FWnSpan+1, m%nFW+1:p%nFWMax+1, 1:p%nWings) =-999999.0_ReKi + ! endif + !endif + +end subroutine SetRequestedWindPoints + + +!> Set the requested wind into the correponding misc variables +subroutine DistributeRequestedWind(V_wind, p, m) + real(ReKi), dimension(:,:), intent(in ) :: V_wind !< Position where wind is requested + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi) :: iP_start,iP_end ! Current index of point, start and end of range + + ! Using array reshaping to ensure a given near or far wake point is always at the same location in the array. + ! NOTE: Maximum number of points are passed, whether they "exist" or not. + ! --- LL CP + iP_start=1 + iP_end=p%nWings*p%nSpan + m%Vwnd_LL(1:3,1:p%nSpan,1:p%nWings) = reshape( V_wind(1:3,iP_start:iP_end), (/ 3, p%nSpan, p%nWings /)) + ! --- NW points + iP_start=iP_end+1 + iP_end=iP_start-1+(p%nSpan+1)*(p%nNWMax+1)*p%nWings + m%Vwnd_NW(1:3,1:p%nSpan+1,1:p%nNWMax+1,1:p%nWings) = reshape( V_wind(1:3,iP_start:iP_end), (/ 3, p%nSpan+1, p%nNWMax+1, p%nWings/)) + ! --- FW points + if (p%nFWMax>0) then + iP_start=iP_end+1 + iP_end=iP_start-1+(FWnSpan+1)*(p%nFWMax+1)*p%nWings + m%Vwnd_FW(1:3,1:FWnSpan+1,1:p%nFWMax+1,1:p%nWings) = reshape( V_wind(1:3,iP_start:iP_end), (/ 3, FWnSpan+1, p%nFWMax+1, p%nWings /)) + endif + +end subroutine DistributeRequestedWind + + +!> Count how many segments are needed to represent the Near wake and far wakes, starting at a given depth +subroutine CountSegments(p, nNW, nFW, iDepthStart, nSeg, nSegP, nSegNW) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + integer(IntKi), intent(in ) :: nNW !< Number of NW panels + integer(IntKi), intent(in ) :: nFW !< Number of FW panels + integer(IntKi), intent(in ) :: iDepthStart !< Index where we start packing for NW panels + integer(IntKi), intent( out) :: nSeg !< Total number of segments after packing + integer(IntKi), intent( out) :: nSegP !< Total number of segments points after packing + integer(IntKi), intent( out) :: nSegNW !< Total number of segments points for the near wake only + logical :: LastNWShed + ! If the FW contains Shed vorticity, we include the last shed vorticity from the NW, otherwise, we don't! + ! It's important not to include it, otherwise a strong vortex will be present there with no compensating vorticity from the FW + LastNWShed = (p%FWShedVorticity ) .or. ((.not.p%FWShedVorticity) .and. (nNW<p%nNWMax)) + ! --- Counting total number of segments + nSegP=0; nSeg=0; nSegNW=0 + ! NW segments + if ((nNW-iDepthStart)>=0) then + nSegP = p%nWings * ( (p%nSpan+1)*(nNW-iDepthStart+2) ) + nSegNW = p%nWings * (2*(p%nSpan+1)*(nNW-iDepthStart+2)-(p%nSpan+1)-(nNW-iDepthStart+1+1)) + if (.not.LastNWShed) then + nSegNW = nSegNW - p%nWings * (p%nSpan) ! Removing last set of shed segments + endif + endif + nSeg=nSegNW + ! FW segments + if (nFW>0) then + nSegP = nSegP + p%nWings * ( (FWnSpan+1)*(nFW+1) ) + if (p%FWShedVorticity) then + nSeg = nSeg + p%nWings * (2*(FWnSpan+1)*(nFW+1)-(FWnSpan+1)-(nFW+1)) + else + nSeg = nSeg + p%nWings * ( (FWnSpan+1)*(nFW) ) ! No Shed vorticity + endif + endif +end subroutine CountSegments + +!> Count how many control points are convecting (needed to compute the wake convection) +pure integer(IntKi) function CountCPs(p, nNW, nFWEff) result(nCPs) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + integer(IntKi), intent(in ) :: nNW !< Number of NW panels + integer(IntKi), intent(in ) :: nFWEff !< Number of effective (ie. convecting) FW panels + nCPs = p%nWings * ( (p%nSpan+1)*(nNW+1) ) + if (nFWEff>0) nCPs = nCPs + p%nWings * ((FWnSpan+1)*(nFWEff+1) ) +end function CountCPs + + +subroutine PackPanelsToSegments(p, m, x, iDepthStart, bMirror, SegConnct, SegPoints, SegGamma, nSeg, nSegP) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + type(FVW_ContinuousStateType), intent(in ) :: x !< States + integer(IntKi), intent(in ) :: iDepthStart !< Index where we start packing for NW panels + logical, intent(in ) :: bMirror !< Mirror the vorticity wrt the ground + integer(IntKi),dimension(:,:), intent(inout) :: SegConnct !< Segment connectivity + real(ReKi), dimension(:,:), intent(inout) :: SegPoints !< Segment Points + real(ReKi), dimension(:) , intent(inout) :: SegGamma !< Segment Circulation + integer(IntKi), intent(out) :: nSeg !< Total number of segments after packing + integer(IntKi), intent(out) :: nSegP !< Total number of segments points after packing + ! Local + integer(IntKi) :: iHeadC, iHeadP, nC, nCNW, nP, iW, iHeadC_bkp, i, iMirror + logical :: LastNWShed + + ! If the FW contains Shed vorticity, we include the last shed vorticity form the NW, orhtwerise, we don't! + ! It's important not to include it, otherwise a strong vortex will be present there with no compensating vorticity from the FW + LastNWShed = (p%FWShedVorticity ) .or. ((.not.p%FWShedVorticity) .and. (m%nNW<p%nNWMax)) + + ! Counting total number of segments + ! Returns nC, nP, nCNW, number of segments (without accounting for mirroring) + call CountSegments(p, m%nNW, m%nFW, iDepthStart, nC, nP, nCNW) + + if (nP>0) then + ! Nullifying for safety + SegConnct=-1 + SegPoints=-1 + SegGamma =-1 + ! + iHeadP=1 + iHeadC=1 + if (nCNW>0) then + do iW=1,p%nWings + CALL LatticeToSegments(x%r_NW(1:3,:,1:m%nNW+1,iW), x%Gamma_NW(:,1:m%nNW,iW), iDepthStart, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC, .True., LastNWShed ) + enddo + endif + if (m%nFW>0) then + iHeadC_bkp = iHeadC + do iW=1,p%nWings + CALL LatticeToSegments(x%r_FW(1:3,:,1:m%nFW+1,iW), x%Gamma_FW(:,1:m%nFW,iW), 1, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC , p%FWShedVorticity, p%FWShedVorticity) + enddo + SegConnct(3,iHeadC_bkp:) = SegConnct(3,iHeadC_bkp:) + m%nNW ! Increasing iDepth (or age) to account for NW + endif + if (DEV_VERSION) then + ! Safety checks + if ((iHeadP-1)/=nP) then + print*,'PackPanelsToSegments: Number of points wrongly estimated',nP, iHeadP-1 + STOP ! Keep me. The check will be removed once the code is well established + endif + if ((iHeadC-1)/=nC) then + print*,'PackPanelsToSegments: Number of segments wrongly estimated',nC, iHeadC-1 + STOP ! Keep me. The check will be removed once the code is well established + endif + if (any(SegPoints(3,:)<-99._ReKi)) then + call print_x_NW_FW(p,m,x,'pack') + print*,'PackPanelsToSegments: some segments are NAN' + STOP ! Keep me. The check will be removed once the code is well established + endif + endif + nSeg = iHeadC-1 + nSegP = iHeadP-1 + + if (bMirror) then + ! Mirroring the segments directly + ! NOTE: an alternative is to handle this in the Biot-Savart law directly... + do i=1,nSeg + iMirror = i + nSeg + SegConnct(1:2, iMirror) = SegConnct(1:2, i) + nSegP ! Increased point indices + SegConnct(3:4, iMirror) = SegConnct(3:4, i) ! Span and age is copied + SegGamma(iMirror) = -SegGamma(i) ! Vorticity needs mirroring + enddo + do i=1,nSegP + iMirror = i + nSegP + SegPoints(1:2, iMirror) = SegPoints(1:2, i) ! Same x and y + SegPoints(3 , iMirror) = - SegPoints(3 , i) ! Mirror with respect to z=0 + enddo + ! We now have double the amount of segments and points + nSeg = nSeg*2 + nSegP = nSegP*2 + endif + else + nSeg = 0 + nSegP = 0 + endif +end subroutine PackPanelsToSegments + +!> Set up regularization parameter based on diffusion method and regularization method +!! NOTE: this should preferably be done at the "panel"/vortex sheet level +subroutine FVW_InitRegularization(p, m, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(inout) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + real(ReKi) :: ds_min, ds_max, ds_mean !< min,max and mean of spanwise sections + real(ReKi) :: c_min, c_max, c_mean !< min,max and mean of chord + real(ReKi) :: d_min, d_max, d_mean !< min,max and mean of panel diagonal + real(ReKi) :: RegParam + real(ReKi) :: Span !< "Blade span" + integer :: iW + ErrStat = ErrID_None + ErrMsg = "" + ! --- Compute min max and mean spanwise section lengths + iW =1 + ds_min = minval(m%s_ll(2:p%nSpan+1,iW)-m%s_ll(1:p%nSpan,iW)) + ds_max = maxval(m%s_ll(2:p%nSpan+1,iW)-m%s_ll(1:p%nSpan,iW)) + ds_mean = sum(m%s_ll(2:p%nSpan+1,iW)-m%s_ll(1:p%nSpan,iW))/(p%nSpan+1) + c_min = minval(m%chord_LL(:,iW)) + c_max = maxval(m%chord_LL(:,iW)) + c_mean = sum (m%chord_LL(:,iW))/(p%nSpan+1) + d_min = minval(m%diag_LL(:,iW)) + d_max = maxval(m%diag_LL(:,iW)) + d_mean = sum (m%diag_LL(:,iW))/(p%nSpan+1) + Span = m%s_ll(p%nSpan+1,iW)-m%s_ll(1,iW) + RegParam = ds_mean*2 + if (DEV_VERSION) then + write(*,'(A)')'-----------------------------------------------------------------------------------------' + write(*,'(A)')'Regularization Info' + write(*,'(A,1F8.4,A)') 'Span : ',Span + write(*,'(A,3F8.4,A)') 'Chord : ',c_min,c_mean,c_max,' (min, mean, max)' + write(*,'(A,3F8.4,A)') 'Spanwise discretization: ',ds_min,ds_mean,ds_max,' (min, mean, max)' + write(*,'(A,3F8.4,A)') 'Diagonal discretization: ',d_min,d_mean,d_max,' (min, mean, max)' + write(*,'(A,1F8.4)') 'RegParam (Recommended) : ',RegParam + write(*,'(A,1F8.4)') 'RegParam (Input ) : ',p%WakeRegParam + endif + if (p%RegDeterMethod==idRegDeterAuto) then + ! TODO this is beta + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + print*,'!!! NOTE: using optmized wake regularization parameters is still a beta feature!' + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + p%WakeRegMethod = idRegConstant + p%RegFunction = idRegVatistas + p%WakeRegParam = RegParam + p%WingRegParam = RegParam + p%CoreSpreadEddyVisc = 100 + write(*,'(A)' ) 'The following regularization parameters will be used:' + write(*,'(A,I0)' ) 'WakeRegMethod : ', p%WakeRegMethod + write(*,'(A,I0)' ) 'RegFunction : ', p%RegFunction + write(*,'(A,1F8.4)') 'WakeRegParam : ', p%WakeRegParam + write(*,'(A,1F8.4)') 'WingRegParam : ', p%WingRegParam + write(*,'(A,1F8.4)') 'CoreSpreadEddyVisc: ', p%CoreSpreadEddyVisc + endif + ! KEEP ME: potentially perform pre-computation here + !if (p%WakeRegMethod==idRegConstant) then + !else if (p%WakeRegMethod==idRegStretching) then + !else if (p%WakeRegMethod==idRegAge) then + !else + ! ErrStat = ErrID_Fatal + ! ErrMsg ='Regularization method not implemented' + !endif +end subroutine FVW_InitRegularization + + +!> Set up regularization parameter based on diffusion method and regularization method +!! NOTE: this should preferably be done at the "panel"/vortex sheet level +subroutine WakeRegularization(p, x, m, SegConnct, SegPoints, SegGamma, SegEpsilon, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< States + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + integer(IntKi),dimension(:,:) , intent(in ) :: SegConnct !< Segment connectivity + real(ReKi), dimension(:,:) , intent(in ) :: SegPoints !< Segment Points + real(ReKi), dimension(:) , intent(in ) :: SegGamma !< Segment Circulation + real(ReKi), dimension(:) , intent( out) :: SegEpsilon !< Segment regularization parameter + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: iSeg + real(ReKi) :: time + ErrStat = ErrID_None + ErrMsg = "" + + ! + if (p%WakeRegMethod==idRegConstant) then + SegEpsilon=p%WakeRegParam + + else if (p%WakeRegMethod==idRegStretching) then + ! TODO + ErrStat = ErrID_Fatal + ErrMsg ='Regularization method not implemented' + if (.false.) print*,m%nNW,x%r_NW(1,1,1,1),SegPoints(1,1),SegGamma(1) ! Needed in the future, Just to avoid unused var warning + + else if (p%WakeRegMethod==idRegAge) then + do iSeg=1,size(SegEpsilon,1) ! loop on segments + time = (SegConnct(3, iSeg)-1) * p%DTfvw ! column 3 contains "iDepth", or "iAge", from 1 to nSteps + SegEpsilon(iSeg) = sqrt( 4._ReKi * CoreSpreadAlpha * p%CoreSpreadEddyVisc * p%KinVisc* time + p%WakeRegParam**2 ) + enddo + + else + ErrStat = ErrID_Fatal + ErrMsg ='Regularization method not implemented' + endif + +end subroutine WakeRegularization + + +!> Compute induced velocities from all vortex elements onto all the vortex elements +!! In : x%r_NW, x%r_FW, x%Gamma_NW, x%Gamma_FW +!! Out: m%Vind_NW, m%Vind_FW +subroutine WakeInducedVelocities(p, x, m, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< States + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: iW, nSeg, nSegP, nCPs, iHeadP + integer(IntKi) :: nFWEff ! Number of farwake panels that are free at current tmie step + logical :: bMirror ! True if we mirror the vorticity wrt ground + ! TODO new options + integer(IntKi) :: RegFunctionPart + integer(IntKi) :: nPart + real(ReKi) :: DistanceDirect ! Distance under which direct evaluation of the Biot-Savart should be done for tree + type(T_Tree) :: Tree + real(ReKi), dimension(:,:), allocatable :: PartPoints !< Particle points + real(ReKi), dimension(:,:), allocatable :: PartAlpha !< Particle circulation + real(ReKi), dimension(:) , allocatable :: PartEpsilon !< Regularization parameter + ErrStat= ErrID_None + ErrMsg ='' + + nFWEff = min(m%nFW, p%nFWFree) + bMirror = p%ShearModel==idShearMirror ! Whether or not we mirror the vorticity wrt ground + + m%Vind_NW = -9999._ReKi !< Safety + m%Vind_FW = -9999._ReKi !< Safety + + ! --- Packing all vortex elements into a list of segments + ! NOTE: modifies m%Seg* + call PackPanelsToSegments(p, m, x, 1, bMirror, m%SegConnct, m%SegPoints, m%SegGamma, nSeg, nSegP) + + ! --- Setting up regularization SegEpsilon + call WakeRegularization(p, x, m, m%SegConnct, m%SegPoints, m%SegGamma, m%SegEpsilon(1:nSeg), ErrStat, ErrMsg) + + ! --- Computing induced velocity + call PackConvectingPoints() + if (DEV_VERSION) then + print'(A,I0,A,I0,A,I0)','Convection - nSeg:',nSeg,' - nSegP:',nSegP, ' - nCPs:',nCPs + endif + + ! --- Converting to particles + if ((p%VelocityMethod==idVelocityTree) .or. (p%VelocityMethod==idVelocityPart)) then + iHeadP=1 + nPart = p%PartPerSegment * nSeg + allocate(PartPoints(3,nPart), PartAlpha(3,nPart), PartEpsilon(nPart)) + PartAlpha(:,:) = -99999.99_ReKi + PartPoints(:,:) = -99999.99_ReKi + PartEpsilon(:) = -99999.99_ReKi + call SegmentsToPart(m%SegPoints, m%SegConnct, m%SegGamma, m%SegEpsilon, 1, nSeg, p%PartPerSegment, PartPoints, PartAlpha, PartEpsilon, iHeadP) + if (p%RegFunction/=idRegNone) then + RegFunctionPart = idRegExp ! TODO need to find a good equivalence and potentially adapt Epsilon in SegmentsToPart + endif + if (any(PartEpsilon(:)<-9999.99_ReKi)) then + print*,'Error in Segment to part conversion' + STOP + endif + endif + + ! --- Getting induced velocity + m%Uind=0.0_ReKi ! very important due to side effects of ui_* methods + if (p%VelocityMethod==idVelocityBasic) then + call ui_seg( 1, nCPs, m%CPs, 1, nSeg, nSeg, nSegP, m%SegPoints, m%SegConnct, m%SegGamma, p%RegFunction, m%SegEpsilon, m%Uind) + + elseif (p%VelocityMethod==idVelocityTree) then + + DistanceDirect = 2*sum(PartEpsilon)/size(PartEpsilon) ! 2*mean(eps), below that distance eps has a strong effect + call grow_tree(Tree, PartPoints, PartAlpha, RegFunctionPart, PartEpsilon, 0) + !call print_tree(Tree) + call ui_tree(Tree, m%CPs, 0, 1, nCPs, p%TreeBranchFactor, DistanceDirect, m%Uind, ErrStat, ErrMsg) + call cut_tree(Tree) + deallocate(PartPoints, PartAlpha, PartEpsilon) + + elseif (p%VelocityMethod==idVelocityPart) then + call ui_part_nograd(m%CPs ,PartPoints, PartAlpha, RegFunctionPart, PartEpsilon, m%Uind, nCPs, nPart) + deallocate(PartPoints, PartAlpha, PartEpsilon) + endif + call UnPackInducedVelocity() + +contains + !> Pack all the points that convect + subroutine PackConvectingPoints() + ! Counting total number of control points that convects + nCPs = CountCPs(p, m%nNW, nFWEff) + m%CPs=-999.9_ReKi + ! Packing + iHeadP=1 + do iW=1,p%nWings + CALL LatticeToPoints(x%r_NW(1:3,:,1:m%nNW+1,iW), 1, m%CPs, iHeadP) + enddo + if (nFWEff>0) then + do iW=1,p%nWings + CALL LatticeToPoints(x%r_FW(1:3,:,1:nFWEff+1,iW), 1, m%CPs, iHeadP) + enddo + endif + if (DEV_VERSION) then + ! Additional checks + if (any(m%CPs(1,1:nCPs)<=-99)) then + call print_x_NW_FW(p,m,x,'pack') + ErrMsg='PackConvectingPoints: Problem in Control points'; ErrStat=ErrID_Fatal; return + endif + if ((iHeadP-1)/=nCPs) then + print*,'PackConvectingPoints: Number of points wrongly estimated',nCPs, iHeadP-1 + STOP ! Keep me. The check will be removed once the code is well established + ErrMsg='PackConvectingPoints: Number of points wrongly estimated '; ErrStat=ErrID_Fatal; return + endif + endif + end subroutine + !> Distribute the induced velocity to the proper location + subroutine UnPackInducedVelocity() + iHeadP=1 + do iW=1,p%nWings + CALL VecToLattice(m%Uind, 1, m%Vind_NW(:,:,1:m%nNW+1,iW), iHeadP) + enddo + if (nFWEff>0) then + do iW=1,p%nWings + CALL VecToLattice(m%Uind, 1, m%Vind_FW(1:3,1:FWnSpan+1,1:nFWEff+1,iW), iHeadP) + enddo + if (DEV_VERSION) then + if (any(m%Vind_FW(1:3,1:FWnSpan+1,1:nFWEff+1,:)<-99)) then + ErrMsg='UnPackInducedVelocity: Problem in FW induced velocity on FW points'; ErrStat=ErrID_Fatal; return + endif + endif + endif + if (DEV_VERSION) then + if ((iHeadP-1)/=nCPs) then + print*,'UnPackInducedVelocity: Number of points wrongly estimated',nCPs, iHeadP-1 + STOP ! Keep me. The check will be removed once the code is well established + ErrMsg='UnPackInducedVelocity: Number of points wrongly estimated'; ErrStat=ErrID_Fatal; return + endif + endif + end subroutine + +end subroutine + +!> Compute induced velocities from all vortex elements onto the lifting line control points +!! In : x%r_NW, x%r_FW, x%Gamma_NW, x%Gamma_FW +!! Out: m%Vind_LL +subroutine LiftingLineInducedVelocities(p, x, iDepthStart, m, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< States + integer(IntKi), intent(in ) :: iDepthStart !< Index where we start packing for NW panels + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + ! Local variables + integer(IntKi) :: iW, nSeg, nSegP, nCPs, iHeadP + real(ReKi), dimension(:,:), allocatable :: CPs !< ControlPoints + real(ReKi), dimension(:,:), allocatable :: Uind !< Induced velocity + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + logical :: bMirror + ErrStat = ErrID_None + ErrMsg = "" + m%Vind_LL = -9999._ReKi !< Safety + bMirror = p%ShearModel==idShearMirror ! Whether or not we mirror the vorticity wrt ground + + ! --- Packing all vortex elements into a list of segments + call PackPanelsToSegments(p, m, x, iDepthStart, bMirror, m%SegConnct, m%SegPoints, m%SegGamma, nSeg, nSegP) + + ! --- Computing induced velocity + if (nSegP==0) then + nCPs=0 + m%Vind_LL = 0.0_ReKi + if (DEV_VERSION) then + print'(A,I0,A,I0,A,I0,A)','Induction - nSeg:',nSeg,' - nSegP:',nSegP, ' - nCPs:',nCPs, ' -> No induction' + endif + else + ! --- Setting up regularization + call WakeRegularization(p, x, m, m%SegConnct(:,1:nSeg), m%SegPoints(:,1:nSegP), m%SegGamma(1:nSeg), m%SegEpsilon(1:nSeg), ErrStat, ErrMsg) + + nCPs=p%nWings * p%nSpan + allocate(CPs (1:3,1:nCPs)) ! NOTE: here we do allocate CPs and Uind insteadof using Misc + allocate(Uind(1:3,1:nCPs)) ! The size is reasonably small, and m%Uind then stay filled with "rollup velocities" (for export) + Uind=0.0_ReKi !< important due to side effects of ui_seg + ! --- + call PackLiftingLinePoints() + if (DEV_VERSION) then + print'(A,I0,A,I0,A,I0)','Induction - nSeg:',nSeg,' - nSegP:',nSegP, ' - nCPs:',nCPs + endif + call ui_seg( 1, nCPs, CPs, 1, nSeg, nSeg, nSegP, m%SegPoints, m%SegConnct, m%SegGamma, p%RegFunction, m%SegEpsilon, Uind) + call UnPackLiftingLineVelocities() + + deallocate(Uind) + deallocate(CPs) + endif +contains + !> Pack all the control points + subroutine PackLiftingLinePoints() + iHeadP=1 + do iW=1,p%nWings + CALL LatticeToPoints(m%CP_LL(1:3,:,iW:iW), 1, CPs, iHeadP) + enddo + if (DEV_VERSION) then + if ((iHeadP-1)/=size(CPs,2)) then + print*,'PackLLPoints: Number of points wrongly estimated',size(CPs,2), iHeadP-1 + STOP ! Keep me. The check will be removed once the code is well established + endif + endif + nCPs=iHeadP-1 + end subroutine + + !> Distribute the induced velocity to the proper location + subroutine UnPackLiftingLineVelocities() + iHeadP=1 + do iW=1,p%nWings + CALL VecToLattice(Uind, 1, m%Vind_LL(1:3,:,iW:iW), iHeadP) + enddo + if (DEV_VERSION) then + if ((iHeadP-1)/=size(Uind,2)) then + print*,'UnPackLiftingLineVelocities: Number of points wrongly estimated',size(Uind,2), iHeadP-1 + STOP ! Keep me. The check will be removed once the code is well established + endif + endif + end subroutine +end subroutine + +!> Fake ground effect handling to prevents vortices to enter the ground +!! For now a crude bounding is done, engineering models may follow +!! True account of the ground effect (using mirroring or panels) should be done elsewhere +!! This assumes that the ground is at z=0, in harmony with inflow wind +subroutine FakeGroundEffect(p, x, m, ErrStat, ErrMsg) + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(inout) :: x !< States + type(FVW_MiscVarType), intent(in ) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: iAge, iWing, iSpan + integer(IntKi) :: nBelow + real(ReKi), parameter:: GROUND = 1.e-4_ReKi + real(ReKi), parameter:: ABOVE_GROUND = 0.1_ReKi + ErrStat = ErrID_None + ErrMsg = "" + + nBelow=0 + do iWing = 1,p%nWings + do iAge = 1,m%nNW+1 + do iSpan = 1,p%nSpan+1 + if (x%r_NW(3, iSpan, iAge, iWing) < GROUND) then + x%r_NW(3, iSpan, iAge, iWing) = ABOVE_GROUND ! could use m%dxdt + nBelow=nBelow+1 + endif + enddo + enddo + enddo + if (m%nFW>0) then + do iWing = 1,p%nWings + do iAge = 1,m%nFW+1 + do iSpan = 1,FWnSpan + if (x%r_FW(3, iSpan, iAge, iWing) < GROUND) then + x%r_FW(3, iSpan, iAge, iWing) = ABOVE_GROUND ! could use m%dxdt + nBelow=nBelow+1 + endif + enddo + enddo + enddo + endif + if (nBelow>0) then + print*,'[WARN] Check the simulation, some vortices were found below the ground: ',nBelow + endif +end subroutine FakeGroundEffect + +!> Compute typical aerodynamic outputs based on: +!! - the lifting line velocities in global coordinates +!! - some transformation matrices +!! - M_ag : from global to airfoil (this is well defined, also called "n-t" system in AeroDyn) +!! - M_sg : from global to section (this is ill-defined), this coordinate is used to define the "axial" and "tangential" inductions +subroutine FVW_AeroOuts( M_sg, M_ag, PitchAndTwist, Vstr_g, Vind_g, Vwnd_g, KinVisc, Chord, & + AxInd, TanInd, Vrel_norm, phi, alpha, Re, Urel_s, ErrStat, ErrMsg ) + real(ReKi), intent(in ) :: M_sg(3,3) ! m%WithoutSweepPitchTwist global coord to "section" coord + real(R8Ki), intent(in ) :: M_ag(3,3) ! u%BladeMotion(k)%Orientation(1:3,1:3,j) global coord to airfoil coord + real(ReKi), intent(in ) :: PitchAndTwist ! Pitch and twist of section + real(ReKi), intent(in ) :: Vstr_g(3) ! Structural velocity global coord + real(ReKi), intent(in ) :: Vind_g(3) ! Induced wind velocity global coord + real(ReKi), intent(in ) :: Vwnd_g(3) ! Disturbed inflow global coord + real(ReKi), intent(in ) :: KinVisc ! Viscosity + real(ReKi), intent(in ) :: Chord ! chord length + real(ReKi), intent( out) :: AxInd ! axial induction + real(ReKi), intent( out) :: TanInd ! Tangential induction + real(ReKi), intent( out) :: Vrel_norm ! Relative velocity norm + real(Reki), intent( out) :: phi ! Flow angle + real(Reki), intent( out) :: alpha ! angle of attack + real(ReKi), intent( out) :: Re ! Reynolds number + real(ReKi), intent( out) :: Urel_s(3) ! Relative wind of the airfoil (Vwnd - Vstr) section coord + integer(IntKi), intent( out) :: ErrStat + character(ErrMsgLen), intent( out) :: ErrMsg + + ! Local vars + real(ReKi) :: Vstr_s(3) ! Struct Velocity, section coord + real(ReKi) :: Vind_s(3) ! Induced Velocity, section coord + real(ReKi) :: Vwnd_s(3) ! Disturbed wind velocity, section coord + real(ReKi) :: Vtot_g(3) ! Vector of total relative velocity section coord + real(ReKi) :: Vtot_a(3) ! Vector of total relative velocity global coord + real(ReKi) :: Vtot_s(3) ! Vector of total relative velocity global coord + ErrStat = ErrID_None + ErrMsg = "" + !real(DbKi), dimension(3,3) :: M_sa !< Transformation matrix from airfoil to section coord + !real(DbKi), dimension(3,3) :: M_sg2 !< Transformation matrix from global to section coord + ! --- Transformation from airfoil to section (KEEP ME) + !M_sa(1,1:3) = (/ cos(PitchAndTwist*1._DbKi), sin(PitchAndTwist*1._DbKi), 0.0_DbKi /) + !M_sa(2,1:3) = (/ -sin(PitchAndTwist*1._DbKi), cos(PitchAndTwist*1._DbKi), 0.0_DbKi /) + !M_sa(3,1:3) = (/ 0.0_DbKi, 0.0_DbKi, 1.0_DbKi /) + !M_sg= matmul(M_sa, M_ag ) + + ! --- Airfoil coordinates: used to define alpha, and Vrel, also called "n-t" system + Vtot_g = Vwnd_g - Vstr_g + Vind_g + Vtot_a = matmul(M_ag, Vtot_g) + alpha = atan2( Vtot_a(1), Vtot_a(2) ) + Vrel_norm = sqrt(Vtot_a(1)**2 + Vtot_a(2)**2) ! NOTE: z component shoudn't be used + Re = Chord * Vrel_norm / KinVisc / 1.0E6 + + ! Section coordinates: used to define axial induction andflow angle + Vstr_s = matmul(M_sg, Vstr_g) + Vind_s = matmul(M_sg, Vind_g) + Vwnd_s = matmul(M_sg, Vwnd_g) + Urel_s = Vwnd_s - Vstr_s ! relative wind + Vtot_s = Vwnd_s - Vstr_s + Vind_s + AxInd = -Vind_s(1)/Urel_s(1) + TanInd = Vind_s(2)/Urel_s(2) + phi = atan2( Vtot_s(1), Vtot_s(2) ) ! flow angle + + if(.false.) print*,PitchAndTwist ! just to avoid unused var for now +end subroutine FVW_AeroOuts + +!> Generic function to compute alpha, Vrel and Re based on global data +subroutine AlphaVrel_Generic(M_ag, Vstr_g, Vind_g, Vwnd_g, KinVisc, Chord, Vrel_norm, alpha, Re) + real(R8Ki), intent(in ) :: M_ag(3,3) ! u%BladeMotion(k)%Orientation(1:3,1:3,j) global coord to airfoil coord + real(ReKi), intent(in ) :: Vstr_g(3) ! Structural velocity global coord + real(ReKi), intent(in ) :: Vind_g(3) ! Induced wind velocity global coord + real(ReKi), intent(in ) :: Vwnd_g(3) ! Disturbed inflow global coord + real(ReKi), intent(in ) :: KinVisc ! Viscosity + real(ReKi), intent(in ) :: Chord ! chord length + real(ReKi), intent( out) :: Vrel_norm ! Relative velocity norm + real(Reki), intent( out) :: alpha ! angle of attack + real(ReKi), intent( out) :: Re ! Reynolds number + ! Local vars + real(ReKi) :: Vtot_g(3) ! Vector of total relative velocity section coord + real(ReKi) :: Vtot_a(3) ! Vector of total relative velocity global coord + ! --- Airfoil coordinates: used to define alpha, and Vrel, also called "n-t" system + Vtot_g = Vwnd_g - Vstr_g + Vind_g + Vtot_a = matmul(M_ag, Vtot_g) + alpha = atan2( Vtot_a(1), Vtot_a(2) ) + Vrel_norm = sqrt(Vtot_a(1)**2 + Vtot_a(2)**2) ! NOTE: z component shoudn't be used + Re = Chord * Vrel_norm / KinVisc / 1.0E6 +end subroutine AlphaVrel_Generic + + +end module FVW_Subs diff --git a/OpenFAST/modules/aerodyn/src/FVW_Tests.f90 b/OpenFAST/modules/aerodyn/src/FVW_Tests.f90 new file mode 100644 index 000000000..03dc1c19c --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_Tests.f90 @@ -0,0 +1,754 @@ +module FVW_Tests + + use NWTC_Library + + use FVW_Types + use FVW_Subs + use FVW_VortexTools + use FVW_Wings + use FVW_IO + use FVW_BiotSavart + use FVW_VTK, only : FVW_VTK_Misc + + implicit none + + public :: FVW_RunTests + private + + interface test_equal; module procedure & + test_equal_i1, & + test_equal_i0 + end interface + interface test_almost_equal; module procedure & + test_almost_equal_0, & + test_almost_equal_1, & + test_almost_equal_2 + end interface +contains + ! -------------------------------------------------------------------------------- + ! --- Helper functions (should be part of NWTC library) + ! -------------------------------------------------------------------------------- + subroutine test_success(testname,info,bPrint_in) + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + end subroutine + + subroutine test_fail(testname,info,bPrint_in,bStop_in) + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + logical, intent(in), optional :: bStop_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + if(present(bStop_in)) then + if(bStop_in) then + STOP + endif + else + STOP + endif + end subroutine + + subroutine test_equal_i0(testname,Var,iTry,iRef) + ! Arguments + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: Var + integer, intent(in) :: iTry !< + integer, intent(in) :: iRef !< + ! Variables + character(len=255) :: InfoAbs + if(iRef/=iTry) then + write(InfoAbs,'(A,I0,A,I0)') trim(Var),iRef,'/',iTry + call test_fail(testname,InfoAbs) + STOP + else + write(InfoAbs,'(A,A,I0)') trim(Var),' ok ',iRef + call test_success(testname,InfoAbs) + endif + end subroutine + + subroutine test_equal_i1(testname,Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) + ! Arguments + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: Var + integer, dimension(:), intent(in) :: VecTry !< + integer, dimension(:), intent(in) :: VecRef !< + logical, intent(in) :: bTest + logical, intent(in) :: bPrintOnly + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + ! + cpt=0 + do i=1,size(VecRef) + if(VecRef(i)/=VecTry(i)) then + cpt=cpt+1 + endif + enddo + if(cpt>0) then + write(InfoAbs,'(A,I0)') trim(Var)//' Elements different: ',cpt + if(present(bPassed)) then + bPassed=.false. + endif + else + write(InfoAbs,'(A)') trim(Var)//' reproduced to identity' + if(present(bPassed)) then + bPassed=.true. + endif + endif + if(bPrintOnly) then + print'(A)',trim(InfoAbs) + endif + if(bTest) then + if(cpt>0) then + call test_fail(testname,InfoAbs) + STOP + else + call test_success(testname,InfoAbs) + endif + endif + end subroutine + + subroutine test_almost_equal_0(testname,Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: Var + real(ReKi), intent(in) :: Ref !< + real(ReKi), intent(in) :: Try !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + real(ReKi) :: delta + integer :: cpt + ! + cpt=0 + delta=abs(Ref-Try) + if(delta>MINNORM) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta,' - Failed:',cpt + call test_fail(testname,InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta + call test_success(testname,InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=delta>MINNORM + endif + end subroutine + subroutine test_almost_equal_1(testname,Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: Var + real(ReKi), dimension(:), intent(in) :: VecRef !< + real(ReKi), dimension(:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + real(ReKi) :: delta + real(ReKi) :: delta_cum + ! + cpt=0 + delta_cum=0.0_ReKi + do i=1,size(VecRef,1) + delta=abs(VecRef(i)-VecTry(i)) + delta_cum=delta_cum+delta + if(delta>MINNORM) then + cpt=cpt+1 + endif + enddo + delta_cum=delta_cum/size(VecRef) + + if(cpt>0) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum,' - Failed:',cpt + call test_fail(testname,InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum + call test_success(testname,InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=(cpt==0) + endif + end subroutine + subroutine test_almost_equal_2(testname,Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: testname + character(len=*), intent(in) :: Var + real(ReKi), dimension(:,:), intent(in) :: VecRef !< + real(ReKi), dimension(:,:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + real(ReKi), dimension(:),allocatable :: VecRef2 !< + real(ReKi), dimension(:),allocatable :: VecTry2 !< + integer :: p, i,j,n1,n2,nCPs + ! + n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 + allocate ( VecRef2 (n1*n2) ) ; allocate ( VecTry2 (n1*n2) ) + p=0 + do j=1,n2; do i=1,n1 + p=p+1 + VecRef2(p)=VecRef(i,j) + VecTry2(p)=VecTry(i,j) + enddo; enddo; + call test_almost_equal(testname,Var,VecRef2,VecTry2,MINNORM,bStop,bPrint,bPassed) + end subroutine + + ! --------------------------------------------------------------------------------} + ! --- Specific FVW tests + ! --------------------------------------------------------------------------------{ + !> + subroutine Test_BiotSavart_Sgmt(testname, ErrStat, ErrMsg) + character(len=*), intent(in) :: testname + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(ReKi), dimension(3) :: P1,P2,P3,CP + real(ReKi), dimension(3) :: U1 + real(ReKi) :: SegGamma1 !< Circulation [m^2/s] + real(ReKi) :: RegParam1 !< + integer(IntKi) :: i1,i2 + integer(IntKi) :: RegFunction + integer(IntKi), parameter :: nSegTot = 2 + integer(IntKi), parameter :: nSegPTot = 3 + integer(IntKi), parameter :: nCPsTot = 1 + real(ReKi), dimension(3,nCPsTot) :: CPs !< Control points + real(ReKi), dimension(3,nSegPTot) :: SegPoints !< Segment points + integer(IntKi), dimension(2,nSegTot) :: SegConnct !< Connectivity, indices of segments points iSeg1, iSeg2 + real(ReKi), dimension(nSegTot) :: SegGamma !< Segment circulation + real(ReKi), dimension(nSegTot) :: RegParam !< Regularization parameter + real(ReKi), dimension(3,nCPsTot) :: Uind_out !< Induced velocity vector - Side effects!!! + real(ReKi), dimension(3,4) :: CPs_test !< + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! --- Test that the two functions return the same values + P1=(/0. ,0.,-1./) + P2=(/0. ,0., 1./) + CPs_test(:,1) = (/ 0.0, 0., 0.0 /) ! Middle + CPs_test(:,2) = P1 ! Extremity + CPs_test(:,3) = (/ 0.05, 0., -0.5 /) ! Close + CPs_test(:,4) = (/ 10., 0., 0.0 /) ! Far + do i2 = 1, size(CPs_test,2) + ! Segment param + CP=CPs_test(:,i2) + SegGamma1=1 + RegParam1=0.5 + ! One segment param + SegConnct(:,1)=(/1,2/) + SegPoints(:,1) = P1 + SegPoints(:,2) = P2 + SegGamma(:) = SegGamma1 + RegParam(:) = RegParam1 + CPs (:,1) = CP + do i1=1,5 + RegFunction = idRegVALID(i1) + ! Method 1 + Uind_out =0.0_ReKi + call ui_seg(1, 1, CPs, & + 1, 1, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, & + RegFunction, RegParam, Uind_out) + ! Method 2 + call ui_seg_11(CP-P1, CP-P2, SegGamma1, RegFunction, RegParam1, U1) + ! Test + !print*,'Reg function', RegFunction, 'CP',CP + !print*,'Uind_out',Uind_out + !print*,'U1 ',U1 + call test_almost_equal(testname,'Uind method1/2', U1, Uind_out(:,1), 1e-4_ReKi, .true.,.true.) + !call test_almost_equal('Uind method1/2', U1, Uind_out(:,1), 1e-4, .false.,.true.) + enddo + enddo + + ! --- Test that the two segments or one segment returns the same value + P1=(/0. ,0.,-1./) + P2=(/0. ,0., 1./) + P3=(/0. ,0., 0./) + CPs_test(:,1) = (/ 0.0, 0., 0.0 /) ! Middle + CPs_test(:,2) = P1 ! Extremity + CPs_test(:,3) = (/ 0.05, 0., -0.5 /) ! Close + CPs_test(:,4) = (/ 100., 0., -0.5 /) ! Far + do i2 = 1,size(CPs_test,2) + ! Segment param + CP=CPs_test(:,i2) + SegGamma1=1 + RegParam1=0.5 + ! One segment param + SegConnct(:,1)=(/1,2/) + SegConnct(:,2)=(/2,3/) + SegPoints(:,1) = P1 + SegPoints(:,2) = P3 + SegPoints(:,3) = P2 + SegGamma(:) = SegGamma1 + RegParam(:) = RegParam1 + CPs (:,1) = CP + do i1=1,4 ! NOTE stopping at 4 since Offset is not linear + RegFunction = idRegVALID(i1) + ! Method 1 + Uind_out =0.0_ReKi + call ui_seg(1, 1, CPs, & + 1, 2, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, & + RegFunction, RegParam, Uind_out) + ! Method 2 + call ui_seg_11(CP-P1, CP-P2, SegGamma1, RegFunction, RegParam1, U1) + !print*,'Reg function', RegFunction, 'CP',CP + !print*,'Uind_out',Uind_out + !print*,'U1 ',U1 + call test_almost_equal(testname,'Uind 1seg/2seg', U1, Uind_out(:,1), 1e-4_ReKi, .true.,.true.) + enddo + enddo + end subroutine + + !> + subroutine Test_BiotSavart_Part(testname, ErrStat, ErrMsg) + character(len=*), intent(in) :: testname + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(ReKi), dimension(3) :: P1,CP + real(ReKi), dimension(3) :: U1 + real(ReKi), dimension(3) :: PartAlpha1 !< Particle intensity alpha=om.dV [m^3/s] + real(ReKi) :: RegParam1 !< + integer(IntKi) :: i1,i2 + integer(IntKi) :: RegFunction + integer(IntKi), parameter :: nPart = 1 + integer(IntKi), parameter :: nCPs = 1 + real(ReKi), dimension(3,nCPs) :: CPs !< Control points + real(ReKi), dimension(3,nPart):: PartPoints !< Particle points + real(ReKi), dimension(3,nPart):: PartAlpha !< Particle circulation + real(ReKi), dimension(nPart) :: RegParam !< Regularization parameter + real(ReKi), dimension(3,nCPs) :: Uind_out !< Induced velocity vector - Side effects!!! + real(ReKi), dimension(3,4) :: CPs_test !< + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! --- Test that the two functions return the same values + P1=(/0.0, 0.0, -1.0 /) + CPs_test(:,1) = (/ 0.0, 0., 0.0 /) ! Middle + CPs_test(:,2) = P1 ! Extremity + CPs_test(:,3) = (/ 0.01, 0.01, -0.9 /) ! Close + CPs_test(:,4) = (/ 10., 0., 0.0 /) ! Far + do i1=1,3 + do i2 = 1, size(CPs_test,2) + ! Segment param + CP = CPs_test(:,i2) + PartAlpha1(1:2) = 0 + PartAlpha1(3 ) = 2 + RegParam1 = 0.5 + ! One segment param + PartPoints(:,1) = P1 + PartAlpha(:,1) = PartAlpha1 + RegParam(:) = RegParam1 + CPs (:,1) = CP + RegFunction = idRegPartVALID(i1) + ! Method 1 + Uind_out =0.0_ReKi + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunction, RegParam, Uind_out, nCPs, nPart) + ! Method 2 + call ui_part_nograd_11(CP-P1, PartAlpha1, RegFunction, RegParam1, U1) + ! Test + !print*,'Reg function', RegFunction, 'CP',CP + !print*,'Uind_out',Uind_out + !print*,'U1 ',U1 + call test_almost_equal(testname,'Uind part method1/2', U1, Uind_out(:,1), 1e-4_ReKi, .true.,.true.) + enddo + enddo + end subroutine Test_BiotSavart_Part + + !> This test compares calls using the tree algorithm and the direct N^2 evaluation + subroutine Test_BiotSavart_PartTree(testname, ErrStat, ErrMsg) + character(len=*), intent(in) :: testname + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + type(T_Tree) :: Tree + real(ReKi), dimension(3) :: U_ref + integer(IntKi) :: i1,i2,i3,k, iCP + integer(IntKi) :: RegFunction + integer(IntKi) :: nPart = 1 + integer(IntKi) :: nCPs = 1 + real(ReKi), dimension(:,:), allocatable :: CPs !< Control points + real(ReKi), dimension(:,:), allocatable :: PartPoints !< Particle points + real(ReKi), dimension(:,:), allocatable :: PartAlpha !< Particle circulation + real(ReKi), dimension(:) , allocatable :: RegParam !< Regularization parameter + real(ReKi), dimension(:,:), allocatable :: Uind1 !< Induced velocity vector - Side effects!!! + real(ReKi), dimension(:,:), allocatable :: Uind2 !< Induced velocity vector - Side effects!!! + real(ReKi) :: BranchFactor, BranchSmall + real(ReKi), dimension(3,5) :: CPs_test !< + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + BranchFactor = 2.0_ReKi !< Should be above1 + BranchSmall = 0.0_ReKi + RegFunction = 1 + + ! --- Test with 0 particle + nPart=0; nCPs= 1 + call alloc(nPart,nCPs) + CPs(:,1) = (/0.0,0.0,0.0/) + Uind1 =0.0_ReKi + Uind2 =0.0_ReKi + U_ref =0.0_ReKi + call grow_tree(Tree, PartPoints, PartAlpha, RegFunction, RegParam, 0) + !call print_tree(Tree) + call ui_tree(Tree, CPs, 0, 1, nCPs, BranchFactor, BranchSmall, Uind2, ErrStat, ErrMsg) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunction, RegParam, Uind1, nCPs, nPart) + ! Test + call test_almost_equal(testname,'Uind tree 0 part', U_ref, Uind2(:,1), 1e-4_ReKi, .true.,.true.) + call cut_tree(Tree) + call dealloc() + + + ! --- Test with 1 particle + nPart=1; nCPs= 1 + call alloc(nPart,nCPs) + CPs(:,1) = (/0.0,0.0,0.0/) + PartPoints(1:3,1) = (/1.0,0.0,0.0/) + U_ref =0.0_ReKi + call grow_tree(Tree, PartPoints, PartAlpha, RegFunction, RegParam, 0) + !call print_tree(Tree) + call ui_tree(Tree, CPs, 0, 1, nCPs, BranchFactor, BranchSmall, Uind2, ErrStat, ErrMsg) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunction, RegParam, Uind1, nCPs, nPart) + ! Test + call test_almost_equal(testname,'Uind tree 1 part', Uind1, Uind2, 1e-4_ReKi, .true.,.true.) + call cut_tree(Tree) + !call print_tree(Tree) + call dealloc() + + ! --- Test with 81 particles on different CPs, inside and outside the distribution of particles + nPart=3*3**3; nCPs= 1 + call alloc(nPart,nCPs) + k=0 + do i1 = -1,1,1 + do i2 = -1,1,1 + do i3 = -1,1,1 + ! NOTE: here we purposely duplicate a point, since since is a challenging case + k=k+1; PartPoints(1:3,k) = (/ i1, i2, i3 /) + k=k+1; PartPoints(1:3,k) = (/ i1, i2, i3 /) + k=k+1; PartPoints(1:3,k) = (/ i1*1.2, i2*1.3, i3*1.1 /) + enddo + enddo + enddo + CPs_test(:,1) = (/ 0.0, 0., 0.0 /) ! Middle + CPs_test(:,2) = (/ 1.0, 1.0, 1.0 /) ! Close to a cell center + CPs_test(:,3) = PartPoints(:,5) ! On a particle point + CPs_test(:,4) = (/ 2.0, 2.0, 2.0 /) ! Starts to be far from most points + CPs_test(:,5) = (/ 10., 10., 10.0 /) ! Far from all + + call grow_tree(Tree, PartPoints, PartAlpha, RegFunction, RegParam, 0) + !call print_tree(Tree) + do iCP=1,4 + CPs(:,1) = CPs_test(:,icp) + Uind2=0.0_ReKi; Uind1=0.0_ReKi + call ui_tree(Tree, CPs, 0, 1, nCPs, BranchFactor, BranchSmall, Uind2, ErrStat, ErrMsg) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunction, RegParam, Uind1, nCPs, nPart) + !print*,'Uind',Uind1, Uind2 + ! Test + call test_almost_equal(testname,'Uind tree 81 part', Uind1, Uind2, 1e-2_ReKi, .true.,.true.) + enddo + call cut_tree(Tree) + ! --- Test that tree ui cannot be called after tree has been cut + call ui_tree(Tree, CPs, 0, 1, nCPs, BranchFactor, BranchSmall, Uind2, ErrStat, ErrMsg) + call test_equal(testname,'Err. stat tree cut',ErrStat,ErrID_Fatal) + call dealloc() + + contains + subroutine alloc(nPart, nCPs) + integer(IntKi) :: nPart, nCPs + allocate(PartPoints(3,nPart), PartAlpha(3,nPart), RegParam(nPart)) + allocate(CPs(3,nCPs), Uind1(3,nCPs), Uind2(3,nCPs)) + RegParam(:)=0.01 + PartAlpha(1,:) = 0.0 + PartAlpha(2,:) = 0.0 + PartAlpha(3,:) = 1.0 + Uind1 =0.0_ReKi + Uind2 =0.0_ReKi + end subroutine + subroutine dealloc() + deallocate(PartPoints, PartAlpha, RegParam) + deallocate(CPs, Uind1, Uind2) + end subroutine + end subroutine Test_BiotSavart_PartTree + + !> Compares the velocity field obtained from a segment and its convert to particle version + subroutine Test_SegmentsToPart(testname, ErrStat, ErrMsg) + character(len=*), intent(in) :: testname + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(ReKi), dimension(:,:), allocatable :: PartPoints !< Particle points + real(ReKi), dimension(:,:), allocatable :: PartAlpha !< Particle circulation + real(ReKi), dimension(:) , allocatable :: PartEpsilon !< Regularization parameter + integer(IntKi), parameter :: nSegTot = 2 + integer(IntKi), parameter :: nSegPTot = 3 + integer(IntKi), parameter :: nCPsTot = 10 + real(ReKi), dimension(3,nSegPTot) :: SegPoints !< Segment points + integer(IntKi), dimension(2,nSegTot) :: SegConnct !< Connectivity, indices of segments points iSeg1, iSeg2 + real(ReKi), dimension(nSegTot) :: SegGamma !< Segment circulation + real(ReKi), dimension(nSegTot) :: SegEpsilon !< Regularization parameter + real(ReKi), dimension(3,nCPsTot) :: CPs !< Control points + real(ReKi), dimension(3,nCPsTot) :: Uind1 !< Induced velocity vector - Side effects!!! + real(ReKi), dimension(3,nCPsTot) :: Uind2 !< Induced velocity vector - Side effects!!! + real(ReKi) :: RegParam1 !< + integer(IntKi) :: nPartPerSeg, nPart, iHeadP + integer(IntKi) :: RegFunctionPart, RegFunctionSeg + ErrStat = ErrID_None + ErrMsg = "" + RegParam1=1.0 + ! Creating two aligned segments + SegConnct(:,1)=(/1,2/) + SegConnct(:,2)=(/2,3/) + SegPoints(:,1) = (/0. ,0.,-1./) + SegPoints(:,2) = (/0. ,0., 0./) + SegPoints(:,3) = (/0. ,0., 1./) + SegGamma(:) =4 + SegEpsilon = RegParam1 + ! Points where velocity will be evaluated + CPs(:,1) = SegPoints(:,1) + CPs(:,2) = SegPoints(:,2) + CPs(:,3) = SegPoints(:,3) + CPs(:,4) = (/ 0.2, 0.2, 0.0/) + CPs(:,6) = (/ 0.5, 0.5, 0. /) + CPs(:,8) = (/ 1.0, 1.0, 0./) + CPs(:,9) = (/ 10.0, 10.0, 0./) + CPs(:,5) = (/ 0.2, 0.2, 0.5/) + CPs(:,7) = (/ 0.5, 0.5, 0.5/) + CPs(:,10) = (/ 1.0, 1.0, 1./) + + ! --- Test 1 - 10 particles, no regularization + RegFunctionSeg = idRegNone + RegFunctionPart = idRegNone + nPartPerSeg = 10 + + nPart = nPartPerSeg * nSegTot + call alloc(nPart) + iHeadP=1 + call SegmentsToPart(SegPoints, SegConnct, SegGamma, SegEpsilon, 1, nSegTot, nPartPerSeg, PartPoints, PartAlpha, PartEpsilon, iHeadP) + + Uind1 =0.0_ReKi; Uind2 =0.0_ReKi; + call ui_seg(1, nCPsTot, CPs, 1, nSegTot, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, RegFunctionSeg, SegEpsilon, Uind1) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunctionPart, PartEpsilon, Uind2, nCPsTot, nPart) + call test_almost_equal(testname,'Uind 10 part/sgmt no reg', Uind1, Uind2, 1e-3_ReKi, .true.,.true.) + call dealloc() + + ! --- Test 1 - 2 particles, no regularization + RegFunctionSeg = idRegNone + RegFunctionPart = idRegNone + nPartPerSeg = 2 + + nPart = nPartPerSeg * nSegTot + call alloc(nPart) + iHeadP=1 + call SegmentsToPart(SegPoints, SegConnct, SegGamma, SegEpsilon, 1, nSegTot, nPartPerSeg, PartPoints, PartAlpha, PartEpsilon, iHeadP) + + Uind1 =0.0_ReKi; Uind2 =0.0_ReKi; + call ui_seg(1, nCPsTot, CPs, 1, nSegTot, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, RegFunctionSeg, SegEpsilon, Uind1) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunctionPart, PartEpsilon, Uind2, nCPsTot, nPart) + call test_almost_equal(testname,'Uind 2 part/sgmt noreg', Uind1, Uind2, 3e-1_ReKi, .true.,.true.) + call dealloc() + + + ! --- Test 3 - 10 particles, regularization + ! NOTE: more work needed to match the regularization functions and parameters optimally + RegFunctionSeg = idRegLambOseen + RegFunctionPart = idRegExp + nPartPerSeg = 10 + + nPart = nPartPerSeg * nSegTot + call alloc(nPart) + iHeadP=1 + call SegmentsToPart(SegPoints, SegConnct, SegGamma, SegEpsilon, 1, nSegTot, nPartPerSeg, PartPoints, PartAlpha, PartEpsilon, iHeadP) + + Uind1 =0.0_ReKi; Uind2 =0.0_ReKi; + call ui_seg(1, nCPsTot, CPs, 1, nSegTot, nSegTot, nSegPTot, SegPoints, SegConnct, SegGamma, RegFunctionSeg, SegEpsilon, Uind1) + call ui_part_nograd(CPs,PartPoints, PartAlpha, RegFunctionPart, PartEpsilon, Uind2, nCPsTot, nPart) + !print'(A,10F7.3)','Uind1',Uind1(1,:) + !print'(A,10F7.3)','Uind2',Uind2(1,:) + !print'(A,10F7.3)','Uind1',Uind1(2,:) + !print'(A,10F7.3)','Uind2',Uind2(2,:) + !print'(A,10F7.3)','Uind1',Uind1(3,:) + !print'(A,10F7.3)','Uind2',Uind2(3,:) + call test_almost_equal(testname,'Uind 10 part/sgmt w.reg', Uind1, Uind2, 5e-2_ReKi, .true.,.true.) + call dealloc() + + contains + subroutine alloc(n) + integer(IntKi) :: n + allocate(PartPoints(3,n), PartAlpha(3,n), PartEpsilon(n)) + PartAlpha(:,:) = -99999.99_ReKi + PartPoints(:,:) = -99999.99_ReKi + PartEpsilon(:) = -99999.99_ReKi + end subroutine + subroutine dealloc() + deallocate(PartPoints, PartAlpha, PartEpsilon) + end subroutine + end subroutine Test_SegmentsToPart + + !> + subroutine Test_LatticeToSegment(mvtk,iStat) + type(FVW_VTK_Misc),intent(inout) :: mvtk !< miscvars for VTK output + integer(IntKi), intent( out) :: iStat !< Status for test + ! Local + integer(IntKi),dimension(:,:), allocatable :: SegConnct !< Segment connectivity + real(ReKi), dimension(:,:), allocatable :: SegPoints !< Segment Points + real(ReKi), dimension(:) , allocatable :: SegGamma !< Segment Circulation + real(ReKi), dimension(:), allocatable :: SegEpsilon !< + ! + real(ReKi), dimension(:,:,:), allocatable :: LatticePoints1 !< Lattice Points + real(ReKi), dimension(:,:,:), allocatable :: LatticePoints2 !< Lattice Points + real(ReKi), dimension(:,:), allocatable :: LatticeGamma1 !< Lattice Circulation + real(ReKi), dimension(:,:), allocatable :: LatticeGamma2 !< Lattice Circulation + real(ReKi), dimension(:,:), allocatable :: CPs !< ControlPoints + real(ReKi), dimension(:,:), allocatable :: Uind !< Induced velocity + integer(IntKi) :: iHeadC + integer(IntKi) :: iHeadP + integer(IntKi) :: i,j + integer(IntKi) :: nP + integer(IntKi) :: nC + integer(IntKi) :: nP1, nP2 + integer(IntKi) :: nC1, nC2 + integer(IntKi) :: nDepth, nSpan + integer(IntKi) :: SmoothModel + logical :: bladeFrame !< Output in blade frame instead of global coordinate frame + iStat=0 + bladeFrame=.FALSE. + + ! --- Creating two lattice + allocate(LatticePoints1(3,2,2)) + allocate(LatticePoints2(3,3,4)) + allocate(LatticeGamma1(1,1)) ; + allocate(LatticeGamma2(2,3)) ; + LatticeGamma1=1 + ! Test shed vorticity + LatticeGamma2(:,1)=1 + LatticeGamma2(:,2)=2 + LatticeGamma2(:,3)=3 + ! Test trailed vorticity +! LatticeGamma2(1,:)=1 +! LatticeGamma2(2,:)=2 + CALL MeshMe(LatticePoints1,(/0.,0.,0./)) + CALL MeshMe(LatticePoints2,(/0.,0.,1./)) + + CALL WrVTK_Lattice('Points1.vtk',mvtk,LatticePoints1, LatticeGamma1, bladeframe=bladeframe) + CALL WrVTK_Lattice('Points2.vtk',mvtk,LatticePoints2, LatticeGamma2, bladeframe=bladeframe) + + ! --- Convert lattice 1 to segments + nSpan = size(LatticePoints1,2) + nDepth = size(LatticePoints1,3) + nP1 = nSpan*nDepth + nC1 = 2*(nSpan*nDepth)-nSpan-nDepth + allocate(SegConnct(1:2,1:nC1)); SegConnct=-1 + allocate(SegPoints(1:3,1:nP1)); SegPoints=-1 + allocate(SegGamma (1:nC1) ); SegGamma=-999 + allocate(SegEpsilon(1:nC1) ); SegEpsilon=0.0_ReKi + + iHeadP=1 + iHeadC=1 + CALL LatticeToSegments(LatticePoints1, LatticeGamma1, 1, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC, .true., .true. ) + CALL printall() + CALL WrVTK_Segments('Points1_seg.vtk', mvtk, SegPoints, SegConnct, SegGamma, SegEpsilon, bladeFrame) + + allocate(Uind(1:3,1) ); Uind=0.0_ReKi + allocate(CPs (1:3,1) ); + CPs(1:3,1)=(/1.5,1.5,0./) + SegEpsilon=100.0_ReKi + SmoothModel=0 ! No smooth + CALL ui_seg(1, 1, CPs, & + 1, nC1, nC1, nP1, SegPoints, SegConnct, SegGamma, & + SmoothModel, SegEpsilon, Uind) + !print*,'Uind',Uind + + ! --- Convert lattice 2 to segments + nSpan = size(LatticePoints2,2) + nDepth = size(LatticePoints2,3) + nP2 = nSpan*nDepth + nC2 = 2*(nSpan*nDepth)-nSpan-nDepth + deallocate(SegConnct) + deallocate(SegPoints) + deallocate(SegGamma) + allocate(SegConnct(1:2,1:nC2)); SegConnct=-1 + allocate(SegPoints(1:3,1:nP2)); SegPoints=-1 + allocate(SegGamma (1:nC2) ); SegGamma=-9999 + iHeadP=1 + iHeadC=1 + CALL LatticeToSegments(LatticePoints2, LatticeGamma2, 1, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC , .true., .true.) + CALL printall() + CALL WrVTK_Segments('Points2_seg.vtk', mvtk, SegPoints, SegConnct, SegGamma, SegEpsilon, bladeFrame) + + ! --- Concatenate both + nP = nP1 + nP2 + nC = nC1 + nC2 + iHeadP=1 + iHeadC=1 + deallocate(SegConnct) + deallocate(SegPoints) + deallocate(SegGamma) + allocate(SegConnct(1:2,1:nC)); SegConnct=-1 + allocate(SegPoints(1:3,1:nP)); SegPoints=-1 + allocate(SegGamma (1:nC) ); SegGamma=-9999 + CALL LatticeToSegments(LatticePoints1, LatticeGamma1, 1, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC, .true. , .true.) + CALL LatticeToSegments(LatticePoints2, LatticeGamma2, 1, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC, .true. , .true.) + CALL printall() + CALL WrVTK_Segments('PointsBoth_seg.vtk', mvtk, SegPoints, SegConnct, SegGamma, SegEpsilon, bladeFrame) + + + contains + subroutine printall() + print*,'Points' + do i=1,size(SegPoints,2) + print*,'i',i,'Coords:', SegPoints(1:3,i) + enddo + print*,'Connectivity' + do i=1,size(SegConnct,2) + print*,'i',i,'Conn:', SegConnct(1:2,i),'Gam:', SegGamma(i) + enddo + print*,'-----------------------------' + endsubroutine + + subroutine MeshMe(M,offset) + real(ReKi), dimension(:,:,:), intent(inout) :: M + real(ReKi), dimension(3) , intent(in ):: offset + do j=1,size(M,3) + do i=1,size(M,2) + M(1,i,j)=i + offset(1) + M(2,i,j)=j + offset(2) + M(3,i,j)=0 + offset(3) + enddo + enddo + endsubroutine + endsubroutine Test_LatticeToSegment + + !> Main test function + subroutine FVW_RunTests(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(len=255) :: testname + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + testname='FVW' + call Test_BiotSavart_Sgmt(testname, ErrStat2, ErrMsg2) + call Test_BiotSavart_Part(testname, ErrStat2, ErrMsg2) + call Test_BiotSavart_PartTree(testname, ErrStat2, ErrMsg2) + call Test_SegmentsToPart(testname, ErrStat2, ErrMsg2) + end subroutine FVW_RunTests + +end module FVW_Tests diff --git a/OpenFAST/modules/aerodyn/src/FVW_Types.f90 b/OpenFAST/modules/aerodyn/src/FVW_Types.f90 new file mode 100644 index 000000000..530c8a2dd --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_Types.f90 @@ -0,0 +1,8329 @@ +!STARTOFREGISTRYGENERATEDFILE 'FVW_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 +!********************************************************************************************************************************* +! FVW_Types +!................................................................................................................................. +! This file is part of FVW. +! +! 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 FVW. 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 FVW_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE UnsteadyAero_Types +USE NWTC_Library +IMPLICIT NONE +! ========= FVW_ParameterType ======= + TYPE, PUBLIC :: FVW_ParameterType + INTEGER(IntKi) :: nWings !< Number of Wings [-] + INTEGER(IntKi) :: nSpan !< TODO, should be defined per wing. Number of spanwise element [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: AFindx !< Index to the airfoils from AD15 [idx1= BladeNode, idx2=Blade number] [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Chord !< Chord of each blade element from input file [idx1=BladeNode, idx2=Blade number] [-] + INTEGER(IntKi) :: nNWMax !< Maximum number of nw panels, per wing [-] + INTEGER(IntKi) :: nFWMax !< Maximum number of fw panels, per wing [-] + INTEGER(IntKi) :: nFWFree !< Number of fw panels that are free, per wing [-] + LOGICAL :: FWShedVorticity !< Include shed vorticity in the far wake [-] + INTEGER(IntKi) :: IntMethod !< Integration Method (1=RK4, 2=AB4, 3=ABM4, 5=Euler1) [-] + REAL(ReKi) :: FreeWakeStart !< Time when wake starts convecting (rolling up) [s] + REAL(ReKi) :: FullCirculationStart !< Time when the circulation is full [s] + INTEGER(IntKi) :: CirculationMethod !< Method to determine the circulation [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PrescribedCirculation !< Prescribed circulation on all lifting lines [m/s] + INTEGER(IntKi) :: CircSolvMaxIter !< Maximum number of iterations for circulation solving [-] + REAL(ReKi) :: CircSolvConvCrit !< Convergence criterion for circulation solving [-] + REAL(ReKi) :: CircSolvRelaxation !< Relaxation factor for circulation solving [-] + INTEGER(IntKi) :: CircSolvPolar !< (0=Use AD polars, 1=2PiAlpha, 2=sin(2pialpha) [-] + INTEGER(IntKi) :: DiffusionMethod !< Diffusion method (None, CoreSpreading, PSE) [-] + REAL(ReKi) :: CoreSpreadEddyVisc !< Eddy viscosity used in the core spreading method [-] + INTEGER(IntKi) :: RegDeterMethod !< Regularization determinatino method (manual, automatic) [-] + INTEGER(IntKi) :: RegFunction !< Type of regularizaion function (LambOseen, Vatistas, see FVW_BiotSavart) [-] + INTEGER(IntKi) :: WakeRegMethod !< Method for regularization (constant, stretching, age, etc.) [-] + REAL(ReKi) :: WakeRegParam !< Initial value of the regularization parameter [-] + REAL(ReKi) :: WingRegParam !< Regularization parameter of the wing [-] + INTEGER(IntKi) :: ShearModel !< Option for shear modelling [-] + LOGICAL :: TwrShadowOnWake !< Include tower shadow effects on wake [-] + INTEGER(IntKi) :: VelocityMethod !< Velocity calculation method [-] + REAL(ReKi) :: TreeBranchFactor !< Factor used to determine if a point is far enough [-] + INTEGER(IntKi) :: PartPerSegment !< Number of particles per segment, e.g. for tree method [-] + REAL(DbKi) :: DTaero !< Time interval for calls calculations [s] + REAL(DbKi) :: DTfvw !< Time interval for calculating wake induced velocities [s] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + INTEGER(IntKi) :: WrVTK !< Outputs VTK at each calcoutput call, even if main fst doesnt do it [-] + INTEGER(IntKi) :: VTKBlades !< Outputs VTk for each blade 0=no blade, 1=Bld 1 [-] + REAL(DbKi) :: DTvtk !< DT between vtk writes [s] + INTEGER(IntKi) :: VTKCoord !< Switch for VTK outputs coordinate system [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + CHARACTER(1024) :: VTK_OutFileRoot !< Rootdirectory for writing VTK files [-] + CHARACTER(1024) :: VTK_OutFileBase !< Basename for writing VTK files [-] + END TYPE FVW_ParameterType +! ======================= +! ========= FVW_MiscVarType ======= + TYPE, PUBLIC :: FVW_MiscVarType + LOGICAL :: FirstCall !< True if this is the first call to update state (used in CalcOutput) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: LE !< Leading edge points [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: TE !< Trailing edge points [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: r_LL !< Position of the Lifting line panels [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: s_LL !< Spanwise coordinate of LL elements [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chord_LL !< chord on LL nodes [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: s_CP_LL !< Spanwise coordinate of LL CP [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: chord_CP_LL !< chord on LL cp [m] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CP_LL !< Coordinates of LL CP [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Tang !< Unit Tangential vector on LL CP [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Norm !< Unit Normal vector on LL CP [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Orth !< Unit Orthogonal vector on LL CP [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: dl !< Vector of elementary length along the LL [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Area !< Area of each LL panel [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: diag_LL !< Diagonal length of each LL panel [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Gamma_LL !< Circulation on the wing lifting line (COPY of Constraint State) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vind_LL !< Induced velocity on lifting line control points [m/s] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vtot_LL !< Total velocity on lifting line control points [m/s] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vstr_LL !< Structural velocity on LL CP [m/s] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vwnd_LL !< Wind on lifting line control points [m/s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vwnd_NW !< Wind on near wake panels [m/s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vwnd_FW !< Wind on far wake panels [m/s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vind_NW !< Induced velocity on near wake panels [m/s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vind_FW !< Induced velocity on far wake panels [m/s] + INTEGER(IntKi) :: nNW !< Number of active near wake panels [-] + INTEGER(IntKi) :: nFW !< Number of active far wake panels [-] + INTEGER(IntKi) :: iStep !< Current step number used for update state [-] + INTEGER(IntKi) :: VTKstep !< Current vtk output step number [-] + REAL(DbKi) :: VTKlastTime !< Time the last VTK file set was written out [s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: r_wind !< List of points where wind is requested for next time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PitchAndTwist !< Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)] [rad] + LOGICAL :: ComputeWakeInduced !< Compute induced velocities on this timestep [-] + REAL(DbKi) :: OldWakeTime !< Time the wake induction velocities were last calculated [s] + REAL(ReKi) :: tSpent !< Time spent in expensive Biot-Savart computation [s] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: dxdt_NW !< State time derivatie, stored for subcylcing [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: dxdt_FW !< State time derivatie, stored for subcylcing [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: alpha_LL !< Angle of attack at lifting line CP, only computed with CircPolarData method [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vreln_LL !< Norm of Vrel on the lifting line [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: SegConnct !< Connectivity of segments [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SegPoints !< Points delimiting the segments [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SegGamma !< Segment circulations [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SegEpsilon !< Segment regularization parameter [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CPs !< Control points used for wake rollup computation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Uind !< Induced velocities obtained at control points [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_AxInd !< Axial induction [size: (NumBlNds,numBlades)] [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_TanInd !< Tangential induction [size: (NumBlNds,numBlades)] [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Vrel !< Relative velocity [size: (NumBlNds,numBlades)] [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_alpha !< Angle of attack [size: (NumBlNds,numBlades)] [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_phi !< angle between the plane of rotation and the direction of the local wind [size: (NumBlNds,numBlades)] [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Re !< Reynolds number [size: (NumBlNds,numBlades)] [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: BN_URelWind_s !< Relative wind velocity in section coordinates [size: (3,NumBlNds,numBlades)] [m/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cl_Static !< Coefficient lift, excluding unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cd_Static !< Coefficient drag. excluding unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cm_Static !< Coefficient moment, excluding unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cl !< Coefficient lift, including unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cd !< Coefficient drag, including unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cm !< Coefficient moment, including unsteady aero effects [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cx !< normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BN_Cy !< tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade [-] + TYPE(UA_MiscVarType) :: m_UA !< misc vars for UnsteadyAero [-] + TYPE(UA_OutputType) :: y_UA !< outputs from UnsteadyAero [-] + TYPE(UA_ParameterType) :: p_UA !< parameters for UnsteadyAero [-] + LOGICAL :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vwnd_ND !< InflowOnBlade (at nodes) values modified by tower influence. ONLY for UA [m/s] + END TYPE FVW_MiscVarType +! ======================= +! ========= FVW_InputType ======= + TYPE, PUBLIC :: FVW_InputType + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: WingsMesh !< Input Mesh defining position and orientation of wings [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: V_wind !< Wind at requested points (r_wind) [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: HubOrientation !< Orientation of hub coordinate system (for output only) [-] + REAL(ReKi) , DIMENSION(1:3) :: HubPosition !< Origin of hub (for output only) [-] + END TYPE FVW_InputType +! ======================= +! ========= FVW_OutputType ======= + TYPE, PUBLIC :: FVW_OutputType + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vind !< TODO mesh - Induced velocity vector. [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cl_KJ !< Lift coefficient from circulation (Kutta-Joukowski) [-] + END TYPE FVW_OutputType +! ======================= +! ========= FVW_ContinuousStateType ======= + TYPE, PUBLIC :: FVW_ContinuousStateType + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Gamma_NW !< Circulation of the near wake panels [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Gamma_FW !< Circulation of the far wake panels [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: r_NW !< Position of the near wake panels [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: r_FW !< Position of the far wake panels [-] + TYPE(UA_ContinuousStateType) :: UA !< states for UnsteadyAero [-] + END TYPE FVW_ContinuousStateType +! ======================= +! ========= FVW_DiscreteStateType ======= + TYPE, PUBLIC :: FVW_DiscreteStateType + REAL(ReKi) :: NULL !< Empty to satisfy framework [-] + TYPE(UA_DiscreteStateType) :: UA !< states for UnsteadyAero [-] + END TYPE FVW_DiscreteStateType +! ======================= +! ========= FVW_ConstraintStateType ======= + TYPE, PUBLIC :: FVW_ConstraintStateType + REAL(ReKi) :: residual + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Gamma_LL !< Circulation on the wing lifting line [-] + END TYPE FVW_ConstraintStateType +! ======================= +! ========= FVW_OtherStateType ======= + TYPE, PUBLIC :: FVW_OtherStateType + INTEGER(IntKi) :: NULL !< Number of active near wake panels [-] + TYPE(UA_OtherStateType) :: UA !< other states for UnsteadyAero [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + END TYPE FVW_OtherStateType +! ======================= +! ========= FVW_InitInputType ======= + TYPE, PUBLIC :: FVW_InitInputType + CHARACTER(1024) :: FVWFileName !< Main FVW input file name [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: WingsMesh !< Input Mesh defining position and orientation of wings (nSpan+1) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: AFindx !< Index to the airfoils from AD15 [idx1=BladeNode, idx2=Blade number] [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Chord !< Chord of each blade element from input file [idx1=BladeNode, idx2=Blade number] [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RElm !< radius of center of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zHub !< Distance to hub for each blade [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: zLocal !< Distance to blade node, measured along the blade [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zTip !< Distance to blade tip, measured along the blade [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rLocal !< Radial distance to blade node from the center of rotation, measured in the rotor plane, needed for DBEMT [m] + INTEGER(IntKi) :: NumBlades !< Number of blades [-] + INTEGER(IntKi) :: NumBladeNodes !< Number of nodes on each blade [-] + REAL(DbKi) :: DTaero !< Time interval for calls (from AD15) [s] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] + INTEGER(IntKi) :: UAMod !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] + LOGICAL :: UA_Flag !< logical flag indicating whether to use UnsteadyAero [-] + LOGICAL :: Flookup !< Use table lookup for f' and f'' [-] + REAL(ReKi) :: a_s !< speed of sound [m/s] + END TYPE FVW_InitInputType +! ======================= +! ========= FVW_InputFile ======= + TYPE, PUBLIC :: FVW_InputFile + INTEGER(IntKi) :: CirculationMethod !< Method to determine the circulation [-] + CHARACTER(1024) :: CirculationFile !< Prescribed circulation file [-] + INTEGER(IntKi) :: CircSolvMaxIter !< Maximum number of iterations for circulation solving [-] + REAL(ReKi) :: CircSolvConvCrit !< Convergence criterion for circulation solving [-] + REAL(ReKi) :: CircSolvRelaxation !< Relaxation factor for circulation solving [-] + INTEGER(IntKi) :: IntMethod !< Integration Method (1=RK4, 2=AB4, 3=ABM4, 5=Euler1, 7=Corrector/Predictor) [-] + LOGICAL :: FreeWake !< Disable roll up, wake convects with wind only (flag) [-] + REAL(ReKi) :: FreeWakeStart !< Time when wake starts convecting (rolling up) [s] + REAL(ReKi) :: FullCirculationStart !< Time when the circulation is full [s] + REAL(DbKi) :: DTfvw !< Time interval for calculating wake induced velocities [s] + INTEGER(IntKi) :: CircSolvPolar !< (0=Use AD polars, 1=2PiAlpha, 2=sin(2pialpha) [-] + INTEGER(IntKi) :: nNWPanels !< Number of nw panels [-] + INTEGER(IntKi) :: nFWPanels !< Number of fw panels [-] + INTEGER(IntKi) :: nFWPanelsFree !< Number of fw panels that are free [-] + LOGICAL :: FWShedVorticity !< Include shed vorticity in the far wake [-] + INTEGER(IntKi) :: DiffusionMethod !< Diffusion method (None, CoreSpreading, PSE) [-] + REAL(ReKi) :: CoreSpreadEddyVisc !< Eddy viscosity used in the core spreading method [-] + INTEGER(IntKi) :: RegDeterMethod !< Regularization determinatino method (manual, automatic) [-] + INTEGER(IntKi) :: RegFunction !< Type of regularizaion function (LambOseen, Vatistas, see FVW_BiotSavart) [-] + INTEGER(IntKi) :: WakeRegMethod !< Method for regularization (constant, stretching, age, etc.) [-] + REAL(ReKi) :: WakeRegParam !< Factor used in the regularization [-] + REAL(ReKi) :: WingRegParam !< Factor used in the regularization [-] + INTEGER(IntKi) :: ShearModel !< Option for shear modelling [-] + LOGICAL :: TwrShadowOnWake !< Include tower shadow effects on wake [-] + INTEGER(IntKi) :: VelocityMethod !< Velocity calculation method [-] + REAL(ReKi) :: TreeBranchFactor !< Factor used to determine if a point is far enough [-] + INTEGER(IntKi) :: PartPerSegment !< Number of particles per segment, e.g. for tree method [-] + INTEGER(IntKi) :: WrVTK !< Outputs VTK at each calcoutput call, even if main fst doesnt do it [-] + INTEGER(IntKi) :: VTKBlades !< Outputs VTk for each blade 0=no blade, 1=Bld 1 [-] + REAL(DbKi) :: DTvtk !< Requested timestep between VTK outputs (calculated from the VTK_fps read in) [s] + INTEGER(IntKi) :: VTKCoord !< Switch for VTK outputs coordinate system [-] + END TYPE FVW_InputFile +! ======================= +! ========= FVW_InitOutputType ======= + TYPE, PUBLIC :: FVW_InitOutputType + INTEGER(IntKi) :: Null !< Empty parameter to satisfy framework [-] + END TYPE FVW_InitOutputType +! ======================= +CONTAINS + SUBROUTINE FVW_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_ParameterType), INTENT(IN) :: SrcParamData + TYPE(FVW_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 = 'FVW_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%nWings = SrcParamData%nWings + DstParamData%nSpan = SrcParamData%nSpan +IF (ALLOCATED(SrcParamData%AFindx)) THEN + i1_l = LBOUND(SrcParamData%AFindx,1) + i1_u = UBOUND(SrcParamData%AFindx,1) + i2_l = LBOUND(SrcParamData%AFindx,2) + i2_u = UBOUND(SrcParamData%AFindx,2) + IF (.NOT. ALLOCATED(DstParamData%AFindx)) THEN + ALLOCATE(DstParamData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AFindx = SrcParamData%AFindx +ENDIF +IF (ALLOCATED(SrcParamData%Chord)) THEN + i1_l = LBOUND(SrcParamData%Chord,1) + i1_u = UBOUND(SrcParamData%Chord,1) + i2_l = LBOUND(SrcParamData%Chord,2) + i2_u = UBOUND(SrcParamData%Chord,2) + IF (.NOT. ALLOCATED(DstParamData%Chord)) THEN + ALLOCATE(DstParamData%Chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Chord = SrcParamData%Chord +ENDIF + DstParamData%nNWMax = SrcParamData%nNWMax + DstParamData%nFWMax = SrcParamData%nFWMax + DstParamData%nFWFree = SrcParamData%nFWFree + DstParamData%FWShedVorticity = SrcParamData%FWShedVorticity + DstParamData%IntMethod = SrcParamData%IntMethod + DstParamData%FreeWakeStart = SrcParamData%FreeWakeStart + DstParamData%FullCirculationStart = SrcParamData%FullCirculationStart + DstParamData%CirculationMethod = SrcParamData%CirculationMethod +IF (ALLOCATED(SrcParamData%PrescribedCirculation)) THEN + i1_l = LBOUND(SrcParamData%PrescribedCirculation,1) + i1_u = UBOUND(SrcParamData%PrescribedCirculation,1) + IF (.NOT. ALLOCATED(DstParamData%PrescribedCirculation)) THEN + ALLOCATE(DstParamData%PrescribedCirculation(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PrescribedCirculation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PrescribedCirculation = SrcParamData%PrescribedCirculation +ENDIF + DstParamData%CircSolvMaxIter = SrcParamData%CircSolvMaxIter + DstParamData%CircSolvConvCrit = SrcParamData%CircSolvConvCrit + DstParamData%CircSolvRelaxation = SrcParamData%CircSolvRelaxation + DstParamData%CircSolvPolar = SrcParamData%CircSolvPolar + DstParamData%DiffusionMethod = SrcParamData%DiffusionMethod + DstParamData%CoreSpreadEddyVisc = SrcParamData%CoreSpreadEddyVisc + DstParamData%RegDeterMethod = SrcParamData%RegDeterMethod + DstParamData%RegFunction = SrcParamData%RegFunction + DstParamData%WakeRegMethod = SrcParamData%WakeRegMethod + DstParamData%WakeRegParam = SrcParamData%WakeRegParam + DstParamData%WingRegParam = SrcParamData%WingRegParam + DstParamData%ShearModel = SrcParamData%ShearModel + DstParamData%TwrShadowOnWake = SrcParamData%TwrShadowOnWake + DstParamData%VelocityMethod = SrcParamData%VelocityMethod + DstParamData%TreeBranchFactor = SrcParamData%TreeBranchFactor + DstParamData%PartPerSegment = SrcParamData%PartPerSegment + DstParamData%DTaero = SrcParamData%DTaero + DstParamData%DTfvw = SrcParamData%DTfvw + DstParamData%KinVisc = SrcParamData%KinVisc + DstParamData%WrVTK = SrcParamData%WrVTK + DstParamData%VTKBlades = SrcParamData%VTKBlades + DstParamData%DTvtk = SrcParamData%DTvtk + DstParamData%VTKCoord = SrcParamData%VTKCoord + DstParamData%RootName = SrcParamData%RootName + DstParamData%VTK_OutFileRoot = SrcParamData%VTK_OutFileRoot + DstParamData%VTK_OutFileBase = SrcParamData%VTK_OutFileBase + END SUBROUTINE FVW_CopyParam + + SUBROUTINE FVW_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(FVW_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%AFindx)) THEN + DEALLOCATE(ParamData%AFindx) +ENDIF +IF (ALLOCATED(ParamData%Chord)) THEN + DEALLOCATE(ParamData%Chord) +ENDIF +IF (ALLOCATED(ParamData%PrescribedCirculation)) THEN + DEALLOCATE(ParamData%PrescribedCirculation) +ENDIF + END SUBROUTINE FVW_DestroyParam + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! nWings + Int_BufSz = Int_BufSz + 1 ! nSpan + Int_BufSz = Int_BufSz + 1 ! AFindx allocated yes/no + IF ( ALLOCATED(InData%AFindx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFindx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AFindx) ! AFindx + END IF + Int_BufSz = Int_BufSz + 1 ! Chord allocated yes/no + IF ( ALLOCATED(InData%Chord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Chord) ! Chord + END IF + Int_BufSz = Int_BufSz + 1 ! nNWMax + Int_BufSz = Int_BufSz + 1 ! nFWMax + Int_BufSz = Int_BufSz + 1 ! nFWFree + Int_BufSz = Int_BufSz + 1 ! FWShedVorticity + Int_BufSz = Int_BufSz + 1 ! IntMethod + Re_BufSz = Re_BufSz + 1 ! FreeWakeStart + Re_BufSz = Re_BufSz + 1 ! FullCirculationStart + Int_BufSz = Int_BufSz + 1 ! CirculationMethod + Int_BufSz = Int_BufSz + 1 ! PrescribedCirculation allocated yes/no + IF ( ALLOCATED(InData%PrescribedCirculation) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PrescribedCirculation upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PrescribedCirculation) ! PrescribedCirculation + END IF + Int_BufSz = Int_BufSz + 1 ! CircSolvMaxIter + Re_BufSz = Re_BufSz + 1 ! CircSolvConvCrit + Re_BufSz = Re_BufSz + 1 ! CircSolvRelaxation + Int_BufSz = Int_BufSz + 1 ! CircSolvPolar + Int_BufSz = Int_BufSz + 1 ! DiffusionMethod + Re_BufSz = Re_BufSz + 1 ! CoreSpreadEddyVisc + Int_BufSz = Int_BufSz + 1 ! RegDeterMethod + Int_BufSz = Int_BufSz + 1 ! RegFunction + Int_BufSz = Int_BufSz + 1 ! WakeRegMethod + Re_BufSz = Re_BufSz + 1 ! WakeRegParam + Re_BufSz = Re_BufSz + 1 ! WingRegParam + Int_BufSz = Int_BufSz + 1 ! ShearModel + Int_BufSz = Int_BufSz + 1 ! TwrShadowOnWake + Int_BufSz = Int_BufSz + 1 ! VelocityMethod + Re_BufSz = Re_BufSz + 1 ! TreeBranchFactor + Int_BufSz = Int_BufSz + 1 ! PartPerSegment + Db_BufSz = Db_BufSz + 1 ! DTaero + Db_BufSz = Db_BufSz + 1 ! DTfvw + Re_BufSz = Re_BufSz + 1 ! KinVisc + Int_BufSz = Int_BufSz + 1 ! WrVTK + Int_BufSz = Int_BufSz + 1 ! VTKBlades + Db_BufSz = Db_BufSz + 1 ! DTvtk + Int_BufSz = Int_BufSz + 1 ! VTKCoord + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1*LEN(InData%VTK_OutFileRoot) ! VTK_OutFileRoot + Int_BufSz = Int_BufSz + 1*LEN(InData%VTK_OutFileBase) ! VTK_OutFileBase + 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%nWings + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nSpan + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AFindx) ) 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%AFindx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFindx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFindx,2), UBOUND(InData%AFindx,2) + DO i1 = LBOUND(InData%AFindx,1), UBOUND(InData%AFindx,1) + IntKiBuf(Int_Xferred) = InData%AFindx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Chord) ) 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%Chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Chord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Chord,2), UBOUND(InData%Chord,2) + DO i1 = LBOUND(InData%Chord,1), UBOUND(InData%Chord,1) + ReKiBuf(Re_Xferred) = InData%Chord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%nNWMax + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nFWMax + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nFWFree + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FWShedVorticity, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FreeWakeStart + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FullCirculationStart + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CirculationMethod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PrescribedCirculation) ) 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%PrescribedCirculation,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PrescribedCirculation,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PrescribedCirculation,1), UBOUND(InData%PrescribedCirculation,1) + ReKiBuf(Re_Xferred) = InData%PrescribedCirculation(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%CircSolvMaxIter + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CircSolvConvCrit + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CircSolvRelaxation + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CircSolvPolar + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DiffusionMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CoreSpreadEddyVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RegDeterMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RegFunction + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WakeRegMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WakeRegParam + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WingRegParam + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ShearModel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrShadowOnWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VelocityMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TreeBranchFactor + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PartPerSegment + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTaero + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTfvw + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WrVTK + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKBlades + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTvtk + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKCoord + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%VTK_OutFileRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%VTK_OutFileRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%VTK_OutFileBase) + IntKiBuf(Int_Xferred) = ICHAR(InData%VTK_OutFileBase(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE FVW_PackParam + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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%nWings = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nSpan = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFindx 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%AFindx)) DEALLOCATE(OutData%AFindx) + ALLOCATE(OutData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFindx,2), UBOUND(OutData%AFindx,2) + DO i1 = LBOUND(OutData%AFindx,1), UBOUND(OutData%AFindx,1) + OutData%AFindx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Chord 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%Chord)) DEALLOCATE(OutData%Chord) + ALLOCATE(OutData%Chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Chord,2), UBOUND(OutData%Chord,2) + DO i1 = LBOUND(OutData%Chord,1), UBOUND(OutData%Chord,1) + OutData%Chord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%nNWMax = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nFWMax = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nFWFree = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FWShedVorticity = TRANSFER(IntKiBuf(Int_Xferred), OutData%FWShedVorticity) + Int_Xferred = Int_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FreeWakeStart = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FullCirculationStart = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CirculationMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PrescribedCirculation 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%PrescribedCirculation)) DEALLOCATE(OutData%PrescribedCirculation) + ALLOCATE(OutData%PrescribedCirculation(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PrescribedCirculation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PrescribedCirculation,1), UBOUND(OutData%PrescribedCirculation,1) + OutData%PrescribedCirculation(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%CircSolvMaxIter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CircSolvConvCrit = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CircSolvRelaxation = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CircSolvPolar = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DiffusionMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CoreSpreadEddyVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RegDeterMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RegFunction = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WakeRegMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WakeRegParam = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WingRegParam = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShearModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrShadowOnWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrShadowOnWake) + Int_Xferred = Int_Xferred + 1 + OutData%VelocityMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TreeBranchFactor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PartPerSegment = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DTaero = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DTfvw = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WrVTK = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DTvtk = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%VTKCoord = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%VTK_OutFileRoot) + OutData%VTK_OutFileRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%VTK_OutFileBase) + OutData%VTK_OutFileBase(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE FVW_UnPackParam + + SUBROUTINE FVW_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(FVW_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%FirstCall = SrcMiscData%FirstCall +IF (ALLOCATED(SrcMiscData%LE)) THEN + i1_l = LBOUND(SrcMiscData%LE,1) + i1_u = UBOUND(SrcMiscData%LE,1) + i2_l = LBOUND(SrcMiscData%LE,2) + i2_u = UBOUND(SrcMiscData%LE,2) + i3_l = LBOUND(SrcMiscData%LE,3) + i3_u = UBOUND(SrcMiscData%LE,3) + IF (.NOT. ALLOCATED(DstMiscData%LE)) THEN + ALLOCATE(DstMiscData%LE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LE = SrcMiscData%LE +ENDIF +IF (ALLOCATED(SrcMiscData%TE)) THEN + i1_l = LBOUND(SrcMiscData%TE,1) + i1_u = UBOUND(SrcMiscData%TE,1) + i2_l = LBOUND(SrcMiscData%TE,2) + i2_u = UBOUND(SrcMiscData%TE,2) + i3_l = LBOUND(SrcMiscData%TE,3) + i3_u = UBOUND(SrcMiscData%TE,3) + IF (.NOT. ALLOCATED(DstMiscData%TE)) THEN + ALLOCATE(DstMiscData%TE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%TE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%TE = SrcMiscData%TE +ENDIF +IF (ALLOCATED(SrcMiscData%r_LL)) THEN + i1_l = LBOUND(SrcMiscData%r_LL,1) + i1_u = UBOUND(SrcMiscData%r_LL,1) + i2_l = LBOUND(SrcMiscData%r_LL,2) + i2_u = UBOUND(SrcMiscData%r_LL,2) + i3_l = LBOUND(SrcMiscData%r_LL,3) + i3_u = UBOUND(SrcMiscData%r_LL,3) + i4_l = LBOUND(SrcMiscData%r_LL,4) + i4_u = UBOUND(SrcMiscData%r_LL,4) + IF (.NOT. ALLOCATED(DstMiscData%r_LL)) THEN + ALLOCATE(DstMiscData%r_LL(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 DstMiscData%r_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%r_LL = SrcMiscData%r_LL +ENDIF +IF (ALLOCATED(SrcMiscData%s_LL)) THEN + i1_l = LBOUND(SrcMiscData%s_LL,1) + i1_u = UBOUND(SrcMiscData%s_LL,1) + i2_l = LBOUND(SrcMiscData%s_LL,2) + i2_u = UBOUND(SrcMiscData%s_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%s_LL)) THEN + ALLOCATE(DstMiscData%s_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%s_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%s_LL = SrcMiscData%s_LL +ENDIF +IF (ALLOCATED(SrcMiscData%chord_LL)) THEN + i1_l = LBOUND(SrcMiscData%chord_LL,1) + i1_u = UBOUND(SrcMiscData%chord_LL,1) + i2_l = LBOUND(SrcMiscData%chord_LL,2) + i2_u = UBOUND(SrcMiscData%chord_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%chord_LL)) THEN + ALLOCATE(DstMiscData%chord_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%chord_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%chord_LL = SrcMiscData%chord_LL +ENDIF +IF (ALLOCATED(SrcMiscData%s_CP_LL)) THEN + i1_l = LBOUND(SrcMiscData%s_CP_LL,1) + i1_u = UBOUND(SrcMiscData%s_CP_LL,1) + i2_l = LBOUND(SrcMiscData%s_CP_LL,2) + i2_u = UBOUND(SrcMiscData%s_CP_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%s_CP_LL)) THEN + ALLOCATE(DstMiscData%s_CP_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%s_CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%s_CP_LL = SrcMiscData%s_CP_LL +ENDIF +IF (ALLOCATED(SrcMiscData%chord_CP_LL)) THEN + i1_l = LBOUND(SrcMiscData%chord_CP_LL,1) + i1_u = UBOUND(SrcMiscData%chord_CP_LL,1) + i2_l = LBOUND(SrcMiscData%chord_CP_LL,2) + i2_u = UBOUND(SrcMiscData%chord_CP_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%chord_CP_LL)) THEN + ALLOCATE(DstMiscData%chord_CP_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%chord_CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%chord_CP_LL = SrcMiscData%chord_CP_LL +ENDIF +IF (ALLOCATED(SrcMiscData%CP_LL)) THEN + i1_l = LBOUND(SrcMiscData%CP_LL,1) + i1_u = UBOUND(SrcMiscData%CP_LL,1) + i2_l = LBOUND(SrcMiscData%CP_LL,2) + i2_u = UBOUND(SrcMiscData%CP_LL,2) + i3_l = LBOUND(SrcMiscData%CP_LL,3) + i3_u = UBOUND(SrcMiscData%CP_LL,3) + IF (.NOT. ALLOCATED(DstMiscData%CP_LL)) THEN + ALLOCATE(DstMiscData%CP_LL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CP_LL = SrcMiscData%CP_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Tang)) THEN + i1_l = LBOUND(SrcMiscData%Tang,1) + i1_u = UBOUND(SrcMiscData%Tang,1) + i2_l = LBOUND(SrcMiscData%Tang,2) + i2_u = UBOUND(SrcMiscData%Tang,2) + i3_l = LBOUND(SrcMiscData%Tang,3) + i3_u = UBOUND(SrcMiscData%Tang,3) + IF (.NOT. ALLOCATED(DstMiscData%Tang)) THEN + ALLOCATE(DstMiscData%Tang(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Tang.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Tang = SrcMiscData%Tang +ENDIF +IF (ALLOCATED(SrcMiscData%Norm)) THEN + i1_l = LBOUND(SrcMiscData%Norm,1) + i1_u = UBOUND(SrcMiscData%Norm,1) + i2_l = LBOUND(SrcMiscData%Norm,2) + i2_u = UBOUND(SrcMiscData%Norm,2) + i3_l = LBOUND(SrcMiscData%Norm,3) + i3_u = UBOUND(SrcMiscData%Norm,3) + IF (.NOT. ALLOCATED(DstMiscData%Norm)) THEN + ALLOCATE(DstMiscData%Norm(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Norm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Norm = SrcMiscData%Norm +ENDIF +IF (ALLOCATED(SrcMiscData%Orth)) THEN + i1_l = LBOUND(SrcMiscData%Orth,1) + i1_u = UBOUND(SrcMiscData%Orth,1) + i2_l = LBOUND(SrcMiscData%Orth,2) + i2_u = UBOUND(SrcMiscData%Orth,2) + i3_l = LBOUND(SrcMiscData%Orth,3) + i3_u = UBOUND(SrcMiscData%Orth,3) + IF (.NOT. ALLOCATED(DstMiscData%Orth)) THEN + ALLOCATE(DstMiscData%Orth(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Orth.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Orth = SrcMiscData%Orth +ENDIF +IF (ALLOCATED(SrcMiscData%dl)) THEN + i1_l = LBOUND(SrcMiscData%dl,1) + i1_u = UBOUND(SrcMiscData%dl,1) + i2_l = LBOUND(SrcMiscData%dl,2) + i2_u = UBOUND(SrcMiscData%dl,2) + i3_l = LBOUND(SrcMiscData%dl,3) + i3_u = UBOUND(SrcMiscData%dl,3) + IF (.NOT. ALLOCATED(DstMiscData%dl)) THEN + ALLOCATE(DstMiscData%dl(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%dl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%dl = SrcMiscData%dl +ENDIF +IF (ALLOCATED(SrcMiscData%Area)) THEN + i1_l = LBOUND(SrcMiscData%Area,1) + i1_u = UBOUND(SrcMiscData%Area,1) + i2_l = LBOUND(SrcMiscData%Area,2) + i2_u = UBOUND(SrcMiscData%Area,2) + IF (.NOT. ALLOCATED(DstMiscData%Area)) THEN + ALLOCATE(DstMiscData%Area(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Area.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Area = SrcMiscData%Area +ENDIF +IF (ALLOCATED(SrcMiscData%diag_LL)) THEN + i1_l = LBOUND(SrcMiscData%diag_LL,1) + i1_u = UBOUND(SrcMiscData%diag_LL,1) + i2_l = LBOUND(SrcMiscData%diag_LL,2) + i2_u = UBOUND(SrcMiscData%diag_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%diag_LL)) THEN + ALLOCATE(DstMiscData%diag_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%diag_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%diag_LL = SrcMiscData%diag_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Gamma_LL)) THEN + i1_l = LBOUND(SrcMiscData%Gamma_LL,1) + i1_u = UBOUND(SrcMiscData%Gamma_LL,1) + i2_l = LBOUND(SrcMiscData%Gamma_LL,2) + i2_u = UBOUND(SrcMiscData%Gamma_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%Gamma_LL)) THEN + ALLOCATE(DstMiscData%Gamma_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Gamma_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Gamma_LL = SrcMiscData%Gamma_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vind_LL)) THEN + i1_l = LBOUND(SrcMiscData%Vind_LL,1) + i1_u = UBOUND(SrcMiscData%Vind_LL,1) + i2_l = LBOUND(SrcMiscData%Vind_LL,2) + i2_u = UBOUND(SrcMiscData%Vind_LL,2) + i3_l = LBOUND(SrcMiscData%Vind_LL,3) + i3_u = UBOUND(SrcMiscData%Vind_LL,3) + IF (.NOT. ALLOCATED(DstMiscData%Vind_LL)) THEN + ALLOCATE(DstMiscData%Vind_LL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vind_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vind_LL = SrcMiscData%Vind_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vtot_LL)) THEN + i1_l = LBOUND(SrcMiscData%Vtot_LL,1) + i1_u = UBOUND(SrcMiscData%Vtot_LL,1) + i2_l = LBOUND(SrcMiscData%Vtot_LL,2) + i2_u = UBOUND(SrcMiscData%Vtot_LL,2) + i3_l = LBOUND(SrcMiscData%Vtot_LL,3) + i3_u = UBOUND(SrcMiscData%Vtot_LL,3) + IF (.NOT. ALLOCATED(DstMiscData%Vtot_LL)) THEN + ALLOCATE(DstMiscData%Vtot_LL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vtot_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vtot_LL = SrcMiscData%Vtot_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vstr_LL)) THEN + i1_l = LBOUND(SrcMiscData%Vstr_LL,1) + i1_u = UBOUND(SrcMiscData%Vstr_LL,1) + i2_l = LBOUND(SrcMiscData%Vstr_LL,2) + i2_u = UBOUND(SrcMiscData%Vstr_LL,2) + i3_l = LBOUND(SrcMiscData%Vstr_LL,3) + i3_u = UBOUND(SrcMiscData%Vstr_LL,3) + IF (.NOT. ALLOCATED(DstMiscData%Vstr_LL)) THEN + ALLOCATE(DstMiscData%Vstr_LL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vstr_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vstr_LL = SrcMiscData%Vstr_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vwnd_LL)) THEN + i1_l = LBOUND(SrcMiscData%Vwnd_LL,1) + i1_u = UBOUND(SrcMiscData%Vwnd_LL,1) + i2_l = LBOUND(SrcMiscData%Vwnd_LL,2) + i2_u = UBOUND(SrcMiscData%Vwnd_LL,2) + i3_l = LBOUND(SrcMiscData%Vwnd_LL,3) + i3_u = UBOUND(SrcMiscData%Vwnd_LL,3) + IF (.NOT. ALLOCATED(DstMiscData%Vwnd_LL)) THEN + ALLOCATE(DstMiscData%Vwnd_LL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vwnd_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vwnd_LL = SrcMiscData%Vwnd_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vwnd_NW)) THEN + i1_l = LBOUND(SrcMiscData%Vwnd_NW,1) + i1_u = UBOUND(SrcMiscData%Vwnd_NW,1) + i2_l = LBOUND(SrcMiscData%Vwnd_NW,2) + i2_u = UBOUND(SrcMiscData%Vwnd_NW,2) + i3_l = LBOUND(SrcMiscData%Vwnd_NW,3) + i3_u = UBOUND(SrcMiscData%Vwnd_NW,3) + i4_l = LBOUND(SrcMiscData%Vwnd_NW,4) + i4_u = UBOUND(SrcMiscData%Vwnd_NW,4) + IF (.NOT. ALLOCATED(DstMiscData%Vwnd_NW)) THEN + ALLOCATE(DstMiscData%Vwnd_NW(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 DstMiscData%Vwnd_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vwnd_NW = SrcMiscData%Vwnd_NW +ENDIF +IF (ALLOCATED(SrcMiscData%Vwnd_FW)) THEN + i1_l = LBOUND(SrcMiscData%Vwnd_FW,1) + i1_u = UBOUND(SrcMiscData%Vwnd_FW,1) + i2_l = LBOUND(SrcMiscData%Vwnd_FW,2) + i2_u = UBOUND(SrcMiscData%Vwnd_FW,2) + i3_l = LBOUND(SrcMiscData%Vwnd_FW,3) + i3_u = UBOUND(SrcMiscData%Vwnd_FW,3) + i4_l = LBOUND(SrcMiscData%Vwnd_FW,4) + i4_u = UBOUND(SrcMiscData%Vwnd_FW,4) + IF (.NOT. ALLOCATED(DstMiscData%Vwnd_FW)) THEN + ALLOCATE(DstMiscData%Vwnd_FW(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 DstMiscData%Vwnd_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vwnd_FW = SrcMiscData%Vwnd_FW +ENDIF +IF (ALLOCATED(SrcMiscData%Vind_NW)) THEN + i1_l = LBOUND(SrcMiscData%Vind_NW,1) + i1_u = UBOUND(SrcMiscData%Vind_NW,1) + i2_l = LBOUND(SrcMiscData%Vind_NW,2) + i2_u = UBOUND(SrcMiscData%Vind_NW,2) + i3_l = LBOUND(SrcMiscData%Vind_NW,3) + i3_u = UBOUND(SrcMiscData%Vind_NW,3) + i4_l = LBOUND(SrcMiscData%Vind_NW,4) + i4_u = UBOUND(SrcMiscData%Vind_NW,4) + IF (.NOT. ALLOCATED(DstMiscData%Vind_NW)) THEN + ALLOCATE(DstMiscData%Vind_NW(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 DstMiscData%Vind_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vind_NW = SrcMiscData%Vind_NW +ENDIF +IF (ALLOCATED(SrcMiscData%Vind_FW)) THEN + i1_l = LBOUND(SrcMiscData%Vind_FW,1) + i1_u = UBOUND(SrcMiscData%Vind_FW,1) + i2_l = LBOUND(SrcMiscData%Vind_FW,2) + i2_u = UBOUND(SrcMiscData%Vind_FW,2) + i3_l = LBOUND(SrcMiscData%Vind_FW,3) + i3_u = UBOUND(SrcMiscData%Vind_FW,3) + i4_l = LBOUND(SrcMiscData%Vind_FW,4) + i4_u = UBOUND(SrcMiscData%Vind_FW,4) + IF (.NOT. ALLOCATED(DstMiscData%Vind_FW)) THEN + ALLOCATE(DstMiscData%Vind_FW(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 DstMiscData%Vind_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vind_FW = SrcMiscData%Vind_FW +ENDIF + DstMiscData%nNW = SrcMiscData%nNW + DstMiscData%nFW = SrcMiscData%nFW + DstMiscData%iStep = SrcMiscData%iStep + DstMiscData%VTKstep = SrcMiscData%VTKstep + DstMiscData%VTKlastTime = SrcMiscData%VTKlastTime +IF (ALLOCATED(SrcMiscData%r_wind)) THEN + i1_l = LBOUND(SrcMiscData%r_wind,1) + i1_u = UBOUND(SrcMiscData%r_wind,1) + i2_l = LBOUND(SrcMiscData%r_wind,2) + i2_u = UBOUND(SrcMiscData%r_wind,2) + IF (.NOT. ALLOCATED(DstMiscData%r_wind)) THEN + ALLOCATE(DstMiscData%r_wind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%r_wind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%r_wind = SrcMiscData%r_wind +ENDIF +IF (ALLOCATED(SrcMiscData%PitchAndTwist)) THEN + i1_l = LBOUND(SrcMiscData%PitchAndTwist,1) + i1_u = UBOUND(SrcMiscData%PitchAndTwist,1) + i2_l = LBOUND(SrcMiscData%PitchAndTwist,2) + i2_u = UBOUND(SrcMiscData%PitchAndTwist,2) + IF (.NOT. ALLOCATED(DstMiscData%PitchAndTwist)) THEN + ALLOCATE(DstMiscData%PitchAndTwist(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%PitchAndTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%PitchAndTwist = SrcMiscData%PitchAndTwist +ENDIF + DstMiscData%ComputeWakeInduced = SrcMiscData%ComputeWakeInduced + DstMiscData%OldWakeTime = SrcMiscData%OldWakeTime + DstMiscData%tSpent = SrcMiscData%tSpent +IF (ALLOCATED(SrcMiscData%dxdt_NW)) THEN + i1_l = LBOUND(SrcMiscData%dxdt_NW,1) + i1_u = UBOUND(SrcMiscData%dxdt_NW,1) + i2_l = LBOUND(SrcMiscData%dxdt_NW,2) + i2_u = UBOUND(SrcMiscData%dxdt_NW,2) + i3_l = LBOUND(SrcMiscData%dxdt_NW,3) + i3_u = UBOUND(SrcMiscData%dxdt_NW,3) + i4_l = LBOUND(SrcMiscData%dxdt_NW,4) + i4_u = UBOUND(SrcMiscData%dxdt_NW,4) + IF (.NOT. ALLOCATED(DstMiscData%dxdt_NW)) THEN + ALLOCATE(DstMiscData%dxdt_NW(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 DstMiscData%dxdt_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%dxdt_NW = SrcMiscData%dxdt_NW +ENDIF +IF (ALLOCATED(SrcMiscData%dxdt_FW)) THEN + i1_l = LBOUND(SrcMiscData%dxdt_FW,1) + i1_u = UBOUND(SrcMiscData%dxdt_FW,1) + i2_l = LBOUND(SrcMiscData%dxdt_FW,2) + i2_u = UBOUND(SrcMiscData%dxdt_FW,2) + i3_l = LBOUND(SrcMiscData%dxdt_FW,3) + i3_u = UBOUND(SrcMiscData%dxdt_FW,3) + i4_l = LBOUND(SrcMiscData%dxdt_FW,4) + i4_u = UBOUND(SrcMiscData%dxdt_FW,4) + IF (.NOT. ALLOCATED(DstMiscData%dxdt_FW)) THEN + ALLOCATE(DstMiscData%dxdt_FW(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 DstMiscData%dxdt_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%dxdt_FW = SrcMiscData%dxdt_FW +ENDIF +IF (ALLOCATED(SrcMiscData%alpha_LL)) THEN + i1_l = LBOUND(SrcMiscData%alpha_LL,1) + i1_u = UBOUND(SrcMiscData%alpha_LL,1) + i2_l = LBOUND(SrcMiscData%alpha_LL,2) + i2_u = UBOUND(SrcMiscData%alpha_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%alpha_LL)) THEN + ALLOCATE(DstMiscData%alpha_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%alpha_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%alpha_LL = SrcMiscData%alpha_LL +ENDIF +IF (ALLOCATED(SrcMiscData%Vreln_LL)) THEN + i1_l = LBOUND(SrcMiscData%Vreln_LL,1) + i1_u = UBOUND(SrcMiscData%Vreln_LL,1) + i2_l = LBOUND(SrcMiscData%Vreln_LL,2) + i2_u = UBOUND(SrcMiscData%Vreln_LL,2) + IF (.NOT. ALLOCATED(DstMiscData%Vreln_LL)) THEN + ALLOCATE(DstMiscData%Vreln_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vreln_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vreln_LL = SrcMiscData%Vreln_LL +ENDIF +IF (ALLOCATED(SrcMiscData%SegConnct)) THEN + i1_l = LBOUND(SrcMiscData%SegConnct,1) + i1_u = UBOUND(SrcMiscData%SegConnct,1) + i2_l = LBOUND(SrcMiscData%SegConnct,2) + i2_u = UBOUND(SrcMiscData%SegConnct,2) + IF (.NOT. ALLOCATED(DstMiscData%SegConnct)) THEN + ALLOCATE(DstMiscData%SegConnct(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SegConnct.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SegConnct = SrcMiscData%SegConnct +ENDIF +IF (ALLOCATED(SrcMiscData%SegPoints)) THEN + i1_l = LBOUND(SrcMiscData%SegPoints,1) + i1_u = UBOUND(SrcMiscData%SegPoints,1) + i2_l = LBOUND(SrcMiscData%SegPoints,2) + i2_u = UBOUND(SrcMiscData%SegPoints,2) + IF (.NOT. ALLOCATED(DstMiscData%SegPoints)) THEN + ALLOCATE(DstMiscData%SegPoints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SegPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SegPoints = SrcMiscData%SegPoints +ENDIF +IF (ALLOCATED(SrcMiscData%SegGamma)) THEN + i1_l = LBOUND(SrcMiscData%SegGamma,1) + i1_u = UBOUND(SrcMiscData%SegGamma,1) + IF (.NOT. ALLOCATED(DstMiscData%SegGamma)) THEN + ALLOCATE(DstMiscData%SegGamma(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SegGamma.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SegGamma = SrcMiscData%SegGamma +ENDIF +IF (ALLOCATED(SrcMiscData%SegEpsilon)) THEN + i1_l = LBOUND(SrcMiscData%SegEpsilon,1) + i1_u = UBOUND(SrcMiscData%SegEpsilon,1) + IF (.NOT. ALLOCATED(DstMiscData%SegEpsilon)) THEN + ALLOCATE(DstMiscData%SegEpsilon(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SegEpsilon.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SegEpsilon = SrcMiscData%SegEpsilon +ENDIF +IF (ALLOCATED(SrcMiscData%CPs)) THEN + i1_l = LBOUND(SrcMiscData%CPs,1) + i1_u = UBOUND(SrcMiscData%CPs,1) + i2_l = LBOUND(SrcMiscData%CPs,2) + i2_u = UBOUND(SrcMiscData%CPs,2) + IF (.NOT. ALLOCATED(DstMiscData%CPs)) THEN + ALLOCATE(DstMiscData%CPs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CPs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CPs = SrcMiscData%CPs +ENDIF +IF (ALLOCATED(SrcMiscData%Uind)) THEN + i1_l = LBOUND(SrcMiscData%Uind,1) + i1_u = UBOUND(SrcMiscData%Uind,1) + i2_l = LBOUND(SrcMiscData%Uind,2) + i2_u = UBOUND(SrcMiscData%Uind,2) + IF (.NOT. ALLOCATED(DstMiscData%Uind)) THEN + ALLOCATE(DstMiscData%Uind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Uind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Uind = SrcMiscData%Uind +ENDIF +IF (ALLOCATED(SrcMiscData%BN_AxInd)) THEN + i1_l = LBOUND(SrcMiscData%BN_AxInd,1) + i1_u = UBOUND(SrcMiscData%BN_AxInd,1) + i2_l = LBOUND(SrcMiscData%BN_AxInd,2) + i2_u = UBOUND(SrcMiscData%BN_AxInd,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_AxInd)) THEN + ALLOCATE(DstMiscData%BN_AxInd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_AxInd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_AxInd = SrcMiscData%BN_AxInd +ENDIF +IF (ALLOCATED(SrcMiscData%BN_TanInd)) THEN + i1_l = LBOUND(SrcMiscData%BN_TanInd,1) + i1_u = UBOUND(SrcMiscData%BN_TanInd,1) + i2_l = LBOUND(SrcMiscData%BN_TanInd,2) + i2_u = UBOUND(SrcMiscData%BN_TanInd,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_TanInd)) THEN + ALLOCATE(DstMiscData%BN_TanInd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_TanInd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_TanInd = SrcMiscData%BN_TanInd +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Vrel)) THEN + i1_l = LBOUND(SrcMiscData%BN_Vrel,1) + i1_u = UBOUND(SrcMiscData%BN_Vrel,1) + i2_l = LBOUND(SrcMiscData%BN_Vrel,2) + i2_u = UBOUND(SrcMiscData%BN_Vrel,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Vrel)) THEN + ALLOCATE(DstMiscData%BN_Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Vrel = SrcMiscData%BN_Vrel +ENDIF +IF (ALLOCATED(SrcMiscData%BN_alpha)) THEN + i1_l = LBOUND(SrcMiscData%BN_alpha,1) + i1_u = UBOUND(SrcMiscData%BN_alpha,1) + i2_l = LBOUND(SrcMiscData%BN_alpha,2) + i2_u = UBOUND(SrcMiscData%BN_alpha,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_alpha)) THEN + ALLOCATE(DstMiscData%BN_alpha(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_alpha = SrcMiscData%BN_alpha +ENDIF +IF (ALLOCATED(SrcMiscData%BN_phi)) THEN + i1_l = LBOUND(SrcMiscData%BN_phi,1) + i1_u = UBOUND(SrcMiscData%BN_phi,1) + i2_l = LBOUND(SrcMiscData%BN_phi,2) + i2_u = UBOUND(SrcMiscData%BN_phi,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_phi)) THEN + ALLOCATE(DstMiscData%BN_phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_phi = SrcMiscData%BN_phi +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Re)) THEN + i1_l = LBOUND(SrcMiscData%BN_Re,1) + i1_u = UBOUND(SrcMiscData%BN_Re,1) + i2_l = LBOUND(SrcMiscData%BN_Re,2) + i2_u = UBOUND(SrcMiscData%BN_Re,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Re)) THEN + ALLOCATE(DstMiscData%BN_Re(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Re.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Re = SrcMiscData%BN_Re +ENDIF +IF (ALLOCATED(SrcMiscData%BN_URelWind_s)) THEN + i1_l = LBOUND(SrcMiscData%BN_URelWind_s,1) + i1_u = UBOUND(SrcMiscData%BN_URelWind_s,1) + i2_l = LBOUND(SrcMiscData%BN_URelWind_s,2) + i2_u = UBOUND(SrcMiscData%BN_URelWind_s,2) + i3_l = LBOUND(SrcMiscData%BN_URelWind_s,3) + i3_u = UBOUND(SrcMiscData%BN_URelWind_s,3) + IF (.NOT. ALLOCATED(DstMiscData%BN_URelWind_s)) THEN + ALLOCATE(DstMiscData%BN_URelWind_s(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_URelWind_s.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_URelWind_s = SrcMiscData%BN_URelWind_s +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cl_Static)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cl_Static,1) + i1_u = UBOUND(SrcMiscData%BN_Cl_Static,1) + i2_l = LBOUND(SrcMiscData%BN_Cl_Static,2) + i2_u = UBOUND(SrcMiscData%BN_Cl_Static,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cl_Static)) THEN + ALLOCATE(DstMiscData%BN_Cl_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cl_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cl_Static = SrcMiscData%BN_Cl_Static +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cd_Static)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cd_Static,1) + i1_u = UBOUND(SrcMiscData%BN_Cd_Static,1) + i2_l = LBOUND(SrcMiscData%BN_Cd_Static,2) + i2_u = UBOUND(SrcMiscData%BN_Cd_Static,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cd_Static)) THEN + ALLOCATE(DstMiscData%BN_Cd_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cd_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cd_Static = SrcMiscData%BN_Cd_Static +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cm_Static)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cm_Static,1) + i1_u = UBOUND(SrcMiscData%BN_Cm_Static,1) + i2_l = LBOUND(SrcMiscData%BN_Cm_Static,2) + i2_u = UBOUND(SrcMiscData%BN_Cm_Static,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cm_Static)) THEN + ALLOCATE(DstMiscData%BN_Cm_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cm_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cm_Static = SrcMiscData%BN_Cm_Static +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cl)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cl,1) + i1_u = UBOUND(SrcMiscData%BN_Cl,1) + i2_l = LBOUND(SrcMiscData%BN_Cl,2) + i2_u = UBOUND(SrcMiscData%BN_Cl,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cl)) THEN + ALLOCATE(DstMiscData%BN_Cl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cl = SrcMiscData%BN_Cl +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cd)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cd,1) + i1_u = UBOUND(SrcMiscData%BN_Cd,1) + i2_l = LBOUND(SrcMiscData%BN_Cd,2) + i2_u = UBOUND(SrcMiscData%BN_Cd,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cd)) THEN + ALLOCATE(DstMiscData%BN_Cd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cd = SrcMiscData%BN_Cd +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cm)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cm,1) + i1_u = UBOUND(SrcMiscData%BN_Cm,1) + i2_l = LBOUND(SrcMiscData%BN_Cm,2) + i2_u = UBOUND(SrcMiscData%BN_Cm,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cm)) THEN + ALLOCATE(DstMiscData%BN_Cm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cm = SrcMiscData%BN_Cm +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cx)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cx,1) + i1_u = UBOUND(SrcMiscData%BN_Cx,1) + i2_l = LBOUND(SrcMiscData%BN_Cx,2) + i2_u = UBOUND(SrcMiscData%BN_Cx,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cx)) THEN + ALLOCATE(DstMiscData%BN_Cx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cx = SrcMiscData%BN_Cx +ENDIF +IF (ALLOCATED(SrcMiscData%BN_Cy)) THEN + i1_l = LBOUND(SrcMiscData%BN_Cy,1) + i1_u = UBOUND(SrcMiscData%BN_Cy,1) + i2_l = LBOUND(SrcMiscData%BN_Cy,2) + i2_u = UBOUND(SrcMiscData%BN_Cy,2) + IF (.NOT. ALLOCATED(DstMiscData%BN_Cy)) THEN + ALLOCATE(DstMiscData%BN_Cy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BN_Cy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BN_Cy = SrcMiscData%BN_Cy +ENDIF + CALL UA_CopyMisc( SrcMiscData%m_UA, DstMiscData%m_UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL UA_CopyOutput( SrcMiscData%y_UA, DstMiscData%y_UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL UA_CopyParam( SrcMiscData%p_UA, DstMiscData%p_UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%UA_Flag = SrcMiscData%UA_Flag +IF (ALLOCATED(SrcMiscData%Vwnd_ND)) THEN + i1_l = LBOUND(SrcMiscData%Vwnd_ND,1) + i1_u = UBOUND(SrcMiscData%Vwnd_ND,1) + i2_l = LBOUND(SrcMiscData%Vwnd_ND,2) + i2_u = UBOUND(SrcMiscData%Vwnd_ND,2) + i3_l = LBOUND(SrcMiscData%Vwnd_ND,3) + i3_u = UBOUND(SrcMiscData%Vwnd_ND,3) + IF (.NOT. ALLOCATED(DstMiscData%Vwnd_ND)) THEN + ALLOCATE(DstMiscData%Vwnd_ND(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Vwnd_ND.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Vwnd_ND = SrcMiscData%Vwnd_ND +ENDIF + END SUBROUTINE FVW_CopyMisc + + SUBROUTINE FVW_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(FVW_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%LE)) THEN + DEALLOCATE(MiscData%LE) +ENDIF +IF (ALLOCATED(MiscData%TE)) THEN + DEALLOCATE(MiscData%TE) +ENDIF +IF (ALLOCATED(MiscData%r_LL)) THEN + DEALLOCATE(MiscData%r_LL) +ENDIF +IF (ALLOCATED(MiscData%s_LL)) THEN + DEALLOCATE(MiscData%s_LL) +ENDIF +IF (ALLOCATED(MiscData%chord_LL)) THEN + DEALLOCATE(MiscData%chord_LL) +ENDIF +IF (ALLOCATED(MiscData%s_CP_LL)) THEN + DEALLOCATE(MiscData%s_CP_LL) +ENDIF +IF (ALLOCATED(MiscData%chord_CP_LL)) THEN + DEALLOCATE(MiscData%chord_CP_LL) +ENDIF +IF (ALLOCATED(MiscData%CP_LL)) THEN + DEALLOCATE(MiscData%CP_LL) +ENDIF +IF (ALLOCATED(MiscData%Tang)) THEN + DEALLOCATE(MiscData%Tang) +ENDIF +IF (ALLOCATED(MiscData%Norm)) THEN + DEALLOCATE(MiscData%Norm) +ENDIF +IF (ALLOCATED(MiscData%Orth)) THEN + DEALLOCATE(MiscData%Orth) +ENDIF +IF (ALLOCATED(MiscData%dl)) THEN + DEALLOCATE(MiscData%dl) +ENDIF +IF (ALLOCATED(MiscData%Area)) THEN + DEALLOCATE(MiscData%Area) +ENDIF +IF (ALLOCATED(MiscData%diag_LL)) THEN + DEALLOCATE(MiscData%diag_LL) +ENDIF +IF (ALLOCATED(MiscData%Gamma_LL)) THEN + DEALLOCATE(MiscData%Gamma_LL) +ENDIF +IF (ALLOCATED(MiscData%Vind_LL)) THEN + DEALLOCATE(MiscData%Vind_LL) +ENDIF +IF (ALLOCATED(MiscData%Vtot_LL)) THEN + DEALLOCATE(MiscData%Vtot_LL) +ENDIF +IF (ALLOCATED(MiscData%Vstr_LL)) THEN + DEALLOCATE(MiscData%Vstr_LL) +ENDIF +IF (ALLOCATED(MiscData%Vwnd_LL)) THEN + DEALLOCATE(MiscData%Vwnd_LL) +ENDIF +IF (ALLOCATED(MiscData%Vwnd_NW)) THEN + DEALLOCATE(MiscData%Vwnd_NW) +ENDIF +IF (ALLOCATED(MiscData%Vwnd_FW)) THEN + DEALLOCATE(MiscData%Vwnd_FW) +ENDIF +IF (ALLOCATED(MiscData%Vind_NW)) THEN + DEALLOCATE(MiscData%Vind_NW) +ENDIF +IF (ALLOCATED(MiscData%Vind_FW)) THEN + DEALLOCATE(MiscData%Vind_FW) +ENDIF +IF (ALLOCATED(MiscData%r_wind)) THEN + DEALLOCATE(MiscData%r_wind) +ENDIF +IF (ALLOCATED(MiscData%PitchAndTwist)) THEN + DEALLOCATE(MiscData%PitchAndTwist) +ENDIF +IF (ALLOCATED(MiscData%dxdt_NW)) THEN + DEALLOCATE(MiscData%dxdt_NW) +ENDIF +IF (ALLOCATED(MiscData%dxdt_FW)) THEN + DEALLOCATE(MiscData%dxdt_FW) +ENDIF +IF (ALLOCATED(MiscData%alpha_LL)) THEN + DEALLOCATE(MiscData%alpha_LL) +ENDIF +IF (ALLOCATED(MiscData%Vreln_LL)) THEN + DEALLOCATE(MiscData%Vreln_LL) +ENDIF +IF (ALLOCATED(MiscData%SegConnct)) THEN + DEALLOCATE(MiscData%SegConnct) +ENDIF +IF (ALLOCATED(MiscData%SegPoints)) THEN + DEALLOCATE(MiscData%SegPoints) +ENDIF +IF (ALLOCATED(MiscData%SegGamma)) THEN + DEALLOCATE(MiscData%SegGamma) +ENDIF +IF (ALLOCATED(MiscData%SegEpsilon)) THEN + DEALLOCATE(MiscData%SegEpsilon) +ENDIF +IF (ALLOCATED(MiscData%CPs)) THEN + DEALLOCATE(MiscData%CPs) +ENDIF +IF (ALLOCATED(MiscData%Uind)) THEN + DEALLOCATE(MiscData%Uind) +ENDIF +IF (ALLOCATED(MiscData%BN_AxInd)) THEN + DEALLOCATE(MiscData%BN_AxInd) +ENDIF +IF (ALLOCATED(MiscData%BN_TanInd)) THEN + DEALLOCATE(MiscData%BN_TanInd) +ENDIF +IF (ALLOCATED(MiscData%BN_Vrel)) THEN + DEALLOCATE(MiscData%BN_Vrel) +ENDIF +IF (ALLOCATED(MiscData%BN_alpha)) THEN + DEALLOCATE(MiscData%BN_alpha) +ENDIF +IF (ALLOCATED(MiscData%BN_phi)) THEN + DEALLOCATE(MiscData%BN_phi) +ENDIF +IF (ALLOCATED(MiscData%BN_Re)) THEN + DEALLOCATE(MiscData%BN_Re) +ENDIF +IF (ALLOCATED(MiscData%BN_URelWind_s)) THEN + DEALLOCATE(MiscData%BN_URelWind_s) +ENDIF +IF (ALLOCATED(MiscData%BN_Cl_Static)) THEN + DEALLOCATE(MiscData%BN_Cl_Static) +ENDIF +IF (ALLOCATED(MiscData%BN_Cd_Static)) THEN + DEALLOCATE(MiscData%BN_Cd_Static) +ENDIF +IF (ALLOCATED(MiscData%BN_Cm_Static)) THEN + DEALLOCATE(MiscData%BN_Cm_Static) +ENDIF +IF (ALLOCATED(MiscData%BN_Cl)) THEN + DEALLOCATE(MiscData%BN_Cl) +ENDIF +IF (ALLOCATED(MiscData%BN_Cd)) THEN + DEALLOCATE(MiscData%BN_Cd) +ENDIF +IF (ALLOCATED(MiscData%BN_Cm)) THEN + DEALLOCATE(MiscData%BN_Cm) +ENDIF +IF (ALLOCATED(MiscData%BN_Cx)) THEN + DEALLOCATE(MiscData%BN_Cx) +ENDIF +IF (ALLOCATED(MiscData%BN_Cy)) THEN + DEALLOCATE(MiscData%BN_Cy) +ENDIF + CALL UA_DestroyMisc( MiscData%m_UA, ErrStat, ErrMsg ) + CALL UA_DestroyOutput( MiscData%y_UA, ErrStat, ErrMsg ) + CALL UA_DestroyParam( MiscData%p_UA, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%Vwnd_ND)) THEN + DEALLOCATE(MiscData%Vwnd_ND) +ENDIF + END SUBROUTINE FVW_DestroyMisc + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! FirstCall + Int_BufSz = Int_BufSz + 1 ! LE allocated yes/no + IF ( ALLOCATED(InData%LE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! LE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LE) ! LE + END IF + Int_BufSz = Int_BufSz + 1 ! TE allocated yes/no + IF ( ALLOCATED(InData%TE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! TE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TE) ! TE + END IF + Int_BufSz = Int_BufSz + 1 ! r_LL allocated yes/no + IF ( ALLOCATED(InData%r_LL) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! r_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r_LL) ! r_LL + END IF + Int_BufSz = Int_BufSz + 1 ! s_LL allocated yes/no + IF ( ALLOCATED(InData%s_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! s_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%s_LL) ! s_LL + END IF + Int_BufSz = Int_BufSz + 1 ! chord_LL allocated yes/no + IF ( ALLOCATED(InData%chord_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chord_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chord_LL) ! chord_LL + END IF + Int_BufSz = Int_BufSz + 1 ! s_CP_LL allocated yes/no + IF ( ALLOCATED(InData%s_CP_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! s_CP_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%s_CP_LL) ! s_CP_LL + END IF + Int_BufSz = Int_BufSz + 1 ! chord_CP_LL allocated yes/no + IF ( ALLOCATED(InData%chord_CP_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! chord_CP_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%chord_CP_LL) ! chord_CP_LL + END IF + Int_BufSz = Int_BufSz + 1 ! CP_LL allocated yes/no + IF ( ALLOCATED(InData%CP_LL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CP_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CP_LL) ! CP_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Tang allocated yes/no + IF ( ALLOCATED(InData%Tang) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Tang upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Tang) ! Tang + END IF + Int_BufSz = Int_BufSz + 1 ! Norm allocated yes/no + IF ( ALLOCATED(InData%Norm) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Norm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Norm) ! Norm + END IF + Int_BufSz = Int_BufSz + 1 ! Orth allocated yes/no + IF ( ALLOCATED(InData%Orth) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Orth upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Orth) ! Orth + END IF + Int_BufSz = Int_BufSz + 1 ! dl allocated yes/no + IF ( ALLOCATED(InData%dl) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! dl upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dl) ! dl + END IF + Int_BufSz = Int_BufSz + 1 ! Area allocated yes/no + IF ( ALLOCATED(InData%Area) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Area upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Area) ! Area + END IF + Int_BufSz = Int_BufSz + 1 ! diag_LL allocated yes/no + IF ( ALLOCATED(InData%diag_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! diag_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%diag_LL) ! diag_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Gamma_LL allocated yes/no + IF ( ALLOCATED(InData%Gamma_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Gamma_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Gamma_LL) ! Gamma_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vind_LL allocated yes/no + IF ( ALLOCATED(InData%Vind_LL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vind_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vind_LL) ! Vind_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vtot_LL allocated yes/no + IF ( ALLOCATED(InData%Vtot_LL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vtot_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vtot_LL) ! Vtot_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vstr_LL allocated yes/no + IF ( ALLOCATED(InData%Vstr_LL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vstr_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vstr_LL) ! Vstr_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vwnd_LL allocated yes/no + IF ( ALLOCATED(InData%Vwnd_LL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vwnd_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vwnd_LL) ! Vwnd_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vwnd_NW allocated yes/no + IF ( ALLOCATED(InData%Vwnd_NW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Vwnd_NW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vwnd_NW) ! Vwnd_NW + END IF + Int_BufSz = Int_BufSz + 1 ! Vwnd_FW allocated yes/no + IF ( ALLOCATED(InData%Vwnd_FW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Vwnd_FW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vwnd_FW) ! Vwnd_FW + END IF + Int_BufSz = Int_BufSz + 1 ! Vind_NW allocated yes/no + IF ( ALLOCATED(InData%Vind_NW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Vind_NW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vind_NW) ! Vind_NW + END IF + Int_BufSz = Int_BufSz + 1 ! Vind_FW allocated yes/no + IF ( ALLOCATED(InData%Vind_FW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Vind_FW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vind_FW) ! Vind_FW + END IF + Int_BufSz = Int_BufSz + 1 ! nNW + Int_BufSz = Int_BufSz + 1 ! nFW + Int_BufSz = Int_BufSz + 1 ! iStep + Int_BufSz = Int_BufSz + 1 ! VTKstep + Db_BufSz = Db_BufSz + 1 ! VTKlastTime + Int_BufSz = Int_BufSz + 1 ! r_wind allocated yes/no + IF ( ALLOCATED(InData%r_wind) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! r_wind upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r_wind) ! r_wind + END IF + Int_BufSz = Int_BufSz + 1 ! PitchAndTwist allocated yes/no + IF ( ALLOCATED(InData%PitchAndTwist) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PitchAndTwist upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PitchAndTwist) ! PitchAndTwist + END IF + Int_BufSz = Int_BufSz + 1 ! ComputeWakeInduced + Db_BufSz = Db_BufSz + 1 ! OldWakeTime + Re_BufSz = Re_BufSz + 1 ! tSpent + Int_BufSz = Int_BufSz + 1 ! dxdt_NW allocated yes/no + IF ( ALLOCATED(InData%dxdt_NW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! dxdt_NW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dxdt_NW) ! dxdt_NW + END IF + Int_BufSz = Int_BufSz + 1 ! dxdt_FW allocated yes/no + IF ( ALLOCATED(InData%dxdt_FW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! dxdt_FW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dxdt_FW) ! dxdt_FW + END IF + Int_BufSz = Int_BufSz + 1 ! alpha_LL allocated yes/no + IF ( ALLOCATED(InData%alpha_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! alpha_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha_LL) ! alpha_LL + END IF + Int_BufSz = Int_BufSz + 1 ! Vreln_LL allocated yes/no + IF ( ALLOCATED(InData%Vreln_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vreln_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vreln_LL) ! Vreln_LL + END IF + Int_BufSz = Int_BufSz + 1 ! SegConnct allocated yes/no + IF ( ALLOCATED(InData%SegConnct) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SegConnct upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SegConnct) ! SegConnct + END IF + Int_BufSz = Int_BufSz + 1 ! SegPoints allocated yes/no + IF ( ALLOCATED(InData%SegPoints) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SegPoints upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SegPoints) ! SegPoints + END IF + Int_BufSz = Int_BufSz + 1 ! SegGamma allocated yes/no + IF ( ALLOCATED(InData%SegGamma) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SegGamma upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SegGamma) ! SegGamma + END IF + Int_BufSz = Int_BufSz + 1 ! SegEpsilon allocated yes/no + IF ( ALLOCATED(InData%SegEpsilon) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SegEpsilon upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SegEpsilon) ! SegEpsilon + END IF + Int_BufSz = Int_BufSz + 1 ! CPs allocated yes/no + IF ( ALLOCATED(InData%CPs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CPs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CPs) ! CPs + END IF + Int_BufSz = Int_BufSz + 1 ! Uind allocated yes/no + IF ( ALLOCATED(InData%Uind) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Uind upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Uind) ! Uind + END IF + Int_BufSz = Int_BufSz + 1 ! BN_AxInd allocated yes/no + IF ( ALLOCATED(InData%BN_AxInd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_AxInd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_AxInd) ! BN_AxInd + END IF + Int_BufSz = Int_BufSz + 1 ! BN_TanInd allocated yes/no + IF ( ALLOCATED(InData%BN_TanInd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_TanInd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_TanInd) ! BN_TanInd + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Vrel allocated yes/no + IF ( ALLOCATED(InData%BN_Vrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Vrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Vrel) ! BN_Vrel + END IF + Int_BufSz = Int_BufSz + 1 ! BN_alpha allocated yes/no + IF ( ALLOCATED(InData%BN_alpha) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_alpha upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_alpha) ! BN_alpha + END IF + Int_BufSz = Int_BufSz + 1 ! BN_phi allocated yes/no + IF ( ALLOCATED(InData%BN_phi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_phi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_phi) ! BN_phi + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Re allocated yes/no + IF ( ALLOCATED(InData%BN_Re) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Re upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Re) ! BN_Re + END IF + Int_BufSz = Int_BufSz + 1 ! BN_URelWind_s allocated yes/no + IF ( ALLOCATED(InData%BN_URelWind_s) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! BN_URelWind_s upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_URelWind_s) ! BN_URelWind_s + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cl_Static allocated yes/no + IF ( ALLOCATED(InData%BN_Cl_Static) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cl_Static upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cl_Static) ! BN_Cl_Static + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cd_Static allocated yes/no + IF ( ALLOCATED(InData%BN_Cd_Static) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cd_Static upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cd_Static) ! BN_Cd_Static + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cm_Static allocated yes/no + IF ( ALLOCATED(InData%BN_Cm_Static) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cm_Static upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cm_Static) ! BN_Cm_Static + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cl allocated yes/no + IF ( ALLOCATED(InData%BN_Cl) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cl upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cl) ! BN_Cl + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cd allocated yes/no + IF ( ALLOCATED(InData%BN_Cd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cd) ! BN_Cd + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cm allocated yes/no + IF ( ALLOCATED(InData%BN_Cm) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cm) ! BN_Cm + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cx allocated yes/no + IF ( ALLOCATED(InData%BN_Cx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cx) ! BN_Cx + END IF + Int_BufSz = Int_BufSz + 1 ! BN_Cy allocated yes/no + IF ( ALLOCATED(InData%BN_Cy) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BN_Cy upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BN_Cy) ! BN_Cy + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! m_UA: size of buffers for each call to pack subtype + CALL UA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m_UA, ErrStat2, ErrMsg2, .TRUE. ) ! m_UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m_UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m_UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m_UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y_UA: size of buffers for each call to pack subtype + CALL UA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_UA, ErrStat2, ErrMsg2, .TRUE. ) ! y_UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! p_UA: size of buffers for each call to pack subtype + CALL UA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p_UA, ErrStat2, ErrMsg2, .TRUE. ) ! p_UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p_UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p_UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p_UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! UA_Flag + Int_BufSz = Int_BufSz + 1 ! Vwnd_ND allocated yes/no + IF ( ALLOCATED(InData%Vwnd_ND) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vwnd_ND upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vwnd_ND) ! Vwnd_ND + 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) = TRANSFER(InData%FirstCall, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LE) ) 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%LE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%LE,3), UBOUND(InData%LE,3) + DO i2 = LBOUND(InData%LE,2), UBOUND(InData%LE,2) + DO i1 = LBOUND(InData%LE,1), UBOUND(InData%LE,1) + ReKiBuf(Re_Xferred) = InData%LE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TE) ) 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%TE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%TE,3), UBOUND(InData%TE,3) + DO i2 = LBOUND(InData%TE,2), UBOUND(InData%TE,2) + DO i1 = LBOUND(InData%TE,1), UBOUND(InData%TE,1) + ReKiBuf(Re_Xferred) = InData%TE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%r_LL) ) 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%r_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_LL,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_LL,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_LL,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%r_LL,4), UBOUND(InData%r_LL,4) + DO i3 = LBOUND(InData%r_LL,3), UBOUND(InData%r_LL,3) + DO i2 = LBOUND(InData%r_LL,2), UBOUND(InData%r_LL,2) + DO i1 = LBOUND(InData%r_LL,1), UBOUND(InData%r_LL,1) + ReKiBuf(Re_Xferred) = InData%r_LL(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%s_LL) ) 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%s_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%s_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%s_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%s_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%s_LL,2), UBOUND(InData%s_LL,2) + DO i1 = LBOUND(InData%s_LL,1), UBOUND(InData%s_LL,1) + ReKiBuf(Re_Xferred) = InData%s_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%chord_LL) ) 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%chord_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chord_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chord_LL,2), UBOUND(InData%chord_LL,2) + DO i1 = LBOUND(InData%chord_LL,1), UBOUND(InData%chord_LL,1) + ReKiBuf(Re_Xferred) = InData%chord_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%s_CP_LL) ) 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%s_CP_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%s_CP_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%s_CP_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%s_CP_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%s_CP_LL,2), UBOUND(InData%s_CP_LL,2) + DO i1 = LBOUND(InData%s_CP_LL,1), UBOUND(InData%s_CP_LL,1) + ReKiBuf(Re_Xferred) = InData%s_CP_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%chord_CP_LL) ) 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%chord_CP_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord_CP_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%chord_CP_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%chord_CP_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%chord_CP_LL,2), UBOUND(InData%chord_CP_LL,2) + DO i1 = LBOUND(InData%chord_CP_LL,1), UBOUND(InData%chord_CP_LL,1) + ReKiBuf(Re_Xferred) = InData%chord_CP_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CP_LL) ) 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%CP_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CP_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CP_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CP_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CP_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CP_LL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CP_LL,3), UBOUND(InData%CP_LL,3) + DO i2 = LBOUND(InData%CP_LL,2), UBOUND(InData%CP_LL,2) + DO i1 = LBOUND(InData%CP_LL,1), UBOUND(InData%CP_LL,1) + ReKiBuf(Re_Xferred) = InData%CP_LL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Tang) ) 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%Tang,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tang,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Tang,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tang,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Tang,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tang,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Tang,3), UBOUND(InData%Tang,3) + DO i2 = LBOUND(InData%Tang,2), UBOUND(InData%Tang,2) + DO i1 = LBOUND(InData%Tang,1), UBOUND(InData%Tang,1) + ReKiBuf(Re_Xferred) = InData%Tang(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Norm) ) 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%Norm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Norm,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Norm,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Norm,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Norm,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Norm,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Norm,3), UBOUND(InData%Norm,3) + DO i2 = LBOUND(InData%Norm,2), UBOUND(InData%Norm,2) + DO i1 = LBOUND(InData%Norm,1), UBOUND(InData%Norm,1) + ReKiBuf(Re_Xferred) = InData%Norm(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Orth) ) 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%Orth,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Orth,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Orth,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Orth,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Orth,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Orth,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Orth,3), UBOUND(InData%Orth,3) + DO i2 = LBOUND(InData%Orth,2), UBOUND(InData%Orth,2) + DO i1 = LBOUND(InData%Orth,1), UBOUND(InData%Orth,1) + ReKiBuf(Re_Xferred) = InData%Orth(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dl) ) 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%dl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dl,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dl,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dl,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dl,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dl,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%dl,3), UBOUND(InData%dl,3) + DO i2 = LBOUND(InData%dl,2), UBOUND(InData%dl,2) + DO i1 = LBOUND(InData%dl,1), UBOUND(InData%dl,1) + ReKiBuf(Re_Xferred) = InData%dl(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Area) ) 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%Area,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Area,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Area,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Area,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Area,2), UBOUND(InData%Area,2) + DO i1 = LBOUND(InData%Area,1), UBOUND(InData%Area,1) + ReKiBuf(Re_Xferred) = InData%Area(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%diag_LL) ) 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%diag_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%diag_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%diag_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%diag_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%diag_LL,2), UBOUND(InData%diag_LL,2) + DO i1 = LBOUND(InData%diag_LL,1), UBOUND(InData%diag_LL,1) + ReKiBuf(Re_Xferred) = InData%diag_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Gamma_LL) ) 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%Gamma_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Gamma_LL,2), UBOUND(InData%Gamma_LL,2) + DO i1 = LBOUND(InData%Gamma_LL,1), UBOUND(InData%Gamma_LL,1) + ReKiBuf(Re_Xferred) = InData%Gamma_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vind_LL) ) 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%Vind_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_LL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vind_LL,3), UBOUND(InData%Vind_LL,3) + DO i2 = LBOUND(InData%Vind_LL,2), UBOUND(InData%Vind_LL,2) + DO i1 = LBOUND(InData%Vind_LL,1), UBOUND(InData%Vind_LL,1) + ReKiBuf(Re_Xferred) = InData%Vind_LL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vtot_LL) ) 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%Vtot_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vtot_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vtot_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vtot_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vtot_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vtot_LL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vtot_LL,3), UBOUND(InData%Vtot_LL,3) + DO i2 = LBOUND(InData%Vtot_LL,2), UBOUND(InData%Vtot_LL,2) + DO i1 = LBOUND(InData%Vtot_LL,1), UBOUND(InData%Vtot_LL,1) + ReKiBuf(Re_Xferred) = InData%Vtot_LL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vstr_LL) ) 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%Vstr_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vstr_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vstr_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vstr_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vstr_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vstr_LL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vstr_LL,3), UBOUND(InData%Vstr_LL,3) + DO i2 = LBOUND(InData%Vstr_LL,2), UBOUND(InData%Vstr_LL,2) + DO i1 = LBOUND(InData%Vstr_LL,1), UBOUND(InData%Vstr_LL,1) + ReKiBuf(Re_Xferred) = InData%Vstr_LL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vwnd_LL) ) 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%Vwnd_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_LL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_LL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_LL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vwnd_LL,3), UBOUND(InData%Vwnd_LL,3) + DO i2 = LBOUND(InData%Vwnd_LL,2), UBOUND(InData%Vwnd_LL,2) + DO i1 = LBOUND(InData%Vwnd_LL,1), UBOUND(InData%Vwnd_LL,1) + ReKiBuf(Re_Xferred) = InData%Vwnd_LL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vwnd_NW) ) 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%Vwnd_NW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_NW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_NW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_NW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_NW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_NW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_NW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_NW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Vwnd_NW,4), UBOUND(InData%Vwnd_NW,4) + DO i3 = LBOUND(InData%Vwnd_NW,3), UBOUND(InData%Vwnd_NW,3) + DO i2 = LBOUND(InData%Vwnd_NW,2), UBOUND(InData%Vwnd_NW,2) + DO i1 = LBOUND(InData%Vwnd_NW,1), UBOUND(InData%Vwnd_NW,1) + ReKiBuf(Re_Xferred) = InData%Vwnd_NW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vwnd_FW) ) 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%Vwnd_FW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_FW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_FW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_FW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_FW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_FW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_FW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_FW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Vwnd_FW,4), UBOUND(InData%Vwnd_FW,4) + DO i3 = LBOUND(InData%Vwnd_FW,3), UBOUND(InData%Vwnd_FW,3) + DO i2 = LBOUND(InData%Vwnd_FW,2), UBOUND(InData%Vwnd_FW,2) + DO i1 = LBOUND(InData%Vwnd_FW,1), UBOUND(InData%Vwnd_FW,1) + ReKiBuf(Re_Xferred) = InData%Vwnd_FW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vind_NW) ) 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%Vind_NW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_NW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_NW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_NW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_NW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_NW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_NW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_NW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Vind_NW,4), UBOUND(InData%Vind_NW,4) + DO i3 = LBOUND(InData%Vind_NW,3), UBOUND(InData%Vind_NW,3) + DO i2 = LBOUND(InData%Vind_NW,2), UBOUND(InData%Vind_NW,2) + DO i1 = LBOUND(InData%Vind_NW,1), UBOUND(InData%Vind_NW,1) + ReKiBuf(Re_Xferred) = InData%Vind_NW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vind_FW) ) 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%Vind_FW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_FW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_FW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_FW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_FW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_FW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_FW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_FW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Vind_FW,4), UBOUND(InData%Vind_FW,4) + DO i3 = LBOUND(InData%Vind_FW,3), UBOUND(InData%Vind_FW,3) + DO i2 = LBOUND(InData%Vind_FW,2), UBOUND(InData%Vind_FW,2) + DO i1 = LBOUND(InData%Vind_FW,1), UBOUND(InData%Vind_FW,1) + ReKiBuf(Re_Xferred) = InData%Vind_FW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%nNW + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nFW + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%iStep + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKstep + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%VTKlastTime + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%r_wind) ) 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%r_wind,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_wind,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_wind,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_wind,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%r_wind,2), UBOUND(InData%r_wind,2) + DO i1 = LBOUND(InData%r_wind,1), UBOUND(InData%r_wind,1) + ReKiBuf(Re_Xferred) = InData%r_wind(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PitchAndTwist) ) 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%PitchAndTwist,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitchAndTwist,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PitchAndTwist,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitchAndTwist,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PitchAndTwist,2), UBOUND(InData%PitchAndTwist,2) + DO i1 = LBOUND(InData%PitchAndTwist,1), UBOUND(InData%PitchAndTwist,1) + ReKiBuf(Re_Xferred) = InData%PitchAndTwist(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%ComputeWakeInduced, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%OldWakeTime + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tSpent + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%dxdt_NW) ) 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%dxdt_NW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_NW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_NW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_NW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_NW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_NW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_NW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_NW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%dxdt_NW,4), UBOUND(InData%dxdt_NW,4) + DO i3 = LBOUND(InData%dxdt_NW,3), UBOUND(InData%dxdt_NW,3) + DO i2 = LBOUND(InData%dxdt_NW,2), UBOUND(InData%dxdt_NW,2) + DO i1 = LBOUND(InData%dxdt_NW,1), UBOUND(InData%dxdt_NW,1) + ReKiBuf(Re_Xferred) = InData%dxdt_NW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dxdt_FW) ) 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%dxdt_FW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_FW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_FW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_FW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_FW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_FW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dxdt_FW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dxdt_FW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%dxdt_FW,4), UBOUND(InData%dxdt_FW,4) + DO i3 = LBOUND(InData%dxdt_FW,3), UBOUND(InData%dxdt_FW,3) + DO i2 = LBOUND(InData%dxdt_FW,2), UBOUND(InData%dxdt_FW,2) + DO i1 = LBOUND(InData%dxdt_FW,1), UBOUND(InData%dxdt_FW,1) + ReKiBuf(Re_Xferred) = InData%dxdt_FW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alpha_LL) ) 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%alpha_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%alpha_LL,2), UBOUND(InData%alpha_LL,2) + DO i1 = LBOUND(InData%alpha_LL,1), UBOUND(InData%alpha_LL,1) + ReKiBuf(Re_Xferred) = InData%alpha_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Vreln_LL) ) 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%Vreln_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vreln_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vreln_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vreln_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vreln_LL,2), UBOUND(InData%Vreln_LL,2) + DO i1 = LBOUND(InData%Vreln_LL,1), UBOUND(InData%Vreln_LL,1) + ReKiBuf(Re_Xferred) = InData%Vreln_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SegConnct) ) 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%SegConnct,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegConnct,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SegConnct,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegConnct,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SegConnct,2), UBOUND(InData%SegConnct,2) + DO i1 = LBOUND(InData%SegConnct,1), UBOUND(InData%SegConnct,1) + IntKiBuf(Int_Xferred) = InData%SegConnct(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SegPoints) ) 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%SegPoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegPoints,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SegPoints,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegPoints,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SegPoints,2), UBOUND(InData%SegPoints,2) + DO i1 = LBOUND(InData%SegPoints,1), UBOUND(InData%SegPoints,1) + ReKiBuf(Re_Xferred) = InData%SegPoints(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SegGamma) ) 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%SegGamma,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegGamma,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SegGamma,1), UBOUND(InData%SegGamma,1) + ReKiBuf(Re_Xferred) = InData%SegGamma(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SegEpsilon) ) 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%SegEpsilon,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SegEpsilon,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SegEpsilon,1), UBOUND(InData%SegEpsilon,1) + ReKiBuf(Re_Xferred) = InData%SegEpsilon(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CPs) ) 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%CPs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CPs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CPs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CPs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CPs,2), UBOUND(InData%CPs,2) + DO i1 = LBOUND(InData%CPs,1), UBOUND(InData%CPs,1) + ReKiBuf(Re_Xferred) = InData%CPs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Uind) ) 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%Uind,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Uind,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Uind,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Uind,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Uind,2), UBOUND(InData%Uind,2) + DO i1 = LBOUND(InData%Uind,1), UBOUND(InData%Uind,1) + ReKiBuf(Re_Xferred) = InData%Uind(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_AxInd) ) 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%BN_AxInd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_AxInd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_AxInd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_AxInd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_AxInd,2), UBOUND(InData%BN_AxInd,2) + DO i1 = LBOUND(InData%BN_AxInd,1), UBOUND(InData%BN_AxInd,1) + ReKiBuf(Re_Xferred) = InData%BN_AxInd(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_TanInd) ) 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%BN_TanInd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_TanInd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_TanInd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_TanInd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_TanInd,2), UBOUND(InData%BN_TanInd,2) + DO i1 = LBOUND(InData%BN_TanInd,1), UBOUND(InData%BN_TanInd,1) + ReKiBuf(Re_Xferred) = InData%BN_TanInd(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Vrel) ) 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%BN_Vrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Vrel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Vrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Vrel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Vrel,2), UBOUND(InData%BN_Vrel,2) + DO i1 = LBOUND(InData%BN_Vrel,1), UBOUND(InData%BN_Vrel,1) + ReKiBuf(Re_Xferred) = InData%BN_Vrel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_alpha) ) 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%BN_alpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_alpha,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_alpha,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_alpha,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_alpha,2), UBOUND(InData%BN_alpha,2) + DO i1 = LBOUND(InData%BN_alpha,1), UBOUND(InData%BN_alpha,1) + ReKiBuf(Re_Xferred) = InData%BN_alpha(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_phi) ) 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%BN_phi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_phi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_phi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_phi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_phi,2), UBOUND(InData%BN_phi,2) + DO i1 = LBOUND(InData%BN_phi,1), UBOUND(InData%BN_phi,1) + ReKiBuf(Re_Xferred) = InData%BN_phi(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Re) ) 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%BN_Re,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Re,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Re,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Re,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Re,2), UBOUND(InData%BN_Re,2) + DO i1 = LBOUND(InData%BN_Re,1), UBOUND(InData%BN_Re,1) + ReKiBuf(Re_Xferred) = InData%BN_Re(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_URelWind_s) ) 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%BN_URelWind_s,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_URelWind_s,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_URelWind_s,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_URelWind_s,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_URelWind_s,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_URelWind_s,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%BN_URelWind_s,3), UBOUND(InData%BN_URelWind_s,3) + DO i2 = LBOUND(InData%BN_URelWind_s,2), UBOUND(InData%BN_URelWind_s,2) + DO i1 = LBOUND(InData%BN_URelWind_s,1), UBOUND(InData%BN_URelWind_s,1) + ReKiBuf(Re_Xferred) = InData%BN_URelWind_s(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cl_Static) ) 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%BN_Cl_Static,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cl_Static,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cl_Static,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cl_Static,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cl_Static,2), UBOUND(InData%BN_Cl_Static,2) + DO i1 = LBOUND(InData%BN_Cl_Static,1), UBOUND(InData%BN_Cl_Static,1) + ReKiBuf(Re_Xferred) = InData%BN_Cl_Static(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cd_Static) ) 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%BN_Cd_Static,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cd_Static,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cd_Static,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cd_Static,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cd_Static,2), UBOUND(InData%BN_Cd_Static,2) + DO i1 = LBOUND(InData%BN_Cd_Static,1), UBOUND(InData%BN_Cd_Static,1) + ReKiBuf(Re_Xferred) = InData%BN_Cd_Static(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cm_Static) ) 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%BN_Cm_Static,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cm_Static,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cm_Static,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cm_Static,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cm_Static,2), UBOUND(InData%BN_Cm_Static,2) + DO i1 = LBOUND(InData%BN_Cm_Static,1), UBOUND(InData%BN_Cm_Static,1) + ReKiBuf(Re_Xferred) = InData%BN_Cm_Static(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cl) ) 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%BN_Cl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cl,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cl,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cl,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cl,2), UBOUND(InData%BN_Cl,2) + DO i1 = LBOUND(InData%BN_Cl,1), UBOUND(InData%BN_Cl,1) + ReKiBuf(Re_Xferred) = InData%BN_Cl(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cd) ) 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%BN_Cd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cd,2), UBOUND(InData%BN_Cd,2) + DO i1 = LBOUND(InData%BN_Cd,1), UBOUND(InData%BN_Cd,1) + ReKiBuf(Re_Xferred) = InData%BN_Cd(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cm) ) 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%BN_Cm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cm,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cm,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cm,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cm,2), UBOUND(InData%BN_Cm,2) + DO i1 = LBOUND(InData%BN_Cm,1), UBOUND(InData%BN_Cm,1) + ReKiBuf(Re_Xferred) = InData%BN_Cm(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cx) ) 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%BN_Cx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cx,2), UBOUND(InData%BN_Cx,2) + DO i1 = LBOUND(InData%BN_Cx,1), UBOUND(InData%BN_Cx,1) + ReKiBuf(Re_Xferred) = InData%BN_Cx(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BN_Cy) ) 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%BN_Cy,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cy,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BN_Cy,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BN_Cy,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BN_Cy,2), UBOUND(InData%BN_Cy,2) + DO i1 = LBOUND(InData%BN_Cy,1), UBOUND(InData%BN_Cy,1) + ReKiBuf(Re_Xferred) = InData%BN_Cy(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + CALL UA_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m_UA, ErrStat2, ErrMsg2, OnlySize ) ! m_UA + 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 UA_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_UA, ErrStat2, ErrMsg2, OnlySize ) ! y_UA + 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 UA_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p_UA, ErrStat2, ErrMsg2, OnlySize ) ! p_UA + 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) = TRANSFER(InData%UA_Flag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Vwnd_ND) ) 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%Vwnd_ND,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_ND,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_ND,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_ND,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vwnd_ND,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vwnd_ND,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vwnd_ND,3), UBOUND(InData%Vwnd_ND,3) + DO i2 = LBOUND(InData%Vwnd_ND,2), UBOUND(InData%Vwnd_ND,2) + DO i1 = LBOUND(InData%Vwnd_ND,1), UBOUND(InData%Vwnd_ND,1) + ReKiBuf(Re_Xferred) = InData%Vwnd_ND(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FVW_PackMisc + + SUBROUTINE FVW_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(FVW_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_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%FirstCall = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstCall) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LE 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%LE)) DEALLOCATE(OutData%LE) + ALLOCATE(OutData%LE(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%LE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%LE,3), UBOUND(OutData%LE,3) + DO i2 = LBOUND(OutData%LE,2), UBOUND(OutData%LE,2) + DO i1 = LBOUND(OutData%LE,1), UBOUND(OutData%LE,1) + OutData%LE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TE 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%TE)) DEALLOCATE(OutData%TE) + ALLOCATE(OutData%TE(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%TE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%TE,3), UBOUND(OutData%TE,3) + DO i2 = LBOUND(OutData%TE,2), UBOUND(OutData%TE,2) + DO i1 = LBOUND(OutData%TE,1), UBOUND(OutData%TE,1) + OutData%TE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r_LL 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%r_LL)) DEALLOCATE(OutData%r_LL) + ALLOCATE(OutData%r_LL(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%r_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%r_LL,4), UBOUND(OutData%r_LL,4) + DO i3 = LBOUND(OutData%r_LL,3), UBOUND(OutData%r_LL,3) + DO i2 = LBOUND(OutData%r_LL,2), UBOUND(OutData%r_LL,2) + DO i1 = LBOUND(OutData%r_LL,1), UBOUND(OutData%r_LL,1) + OutData%r_LL(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! s_LL 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%s_LL)) DEALLOCATE(OutData%s_LL) + ALLOCATE(OutData%s_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%s_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%s_LL,2), UBOUND(OutData%s_LL,2) + DO i1 = LBOUND(OutData%s_LL,1), UBOUND(OutData%s_LL,1) + OutData%s_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chord_LL 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%chord_LL)) DEALLOCATE(OutData%chord_LL) + ALLOCATE(OutData%chord_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chord_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chord_LL,2), UBOUND(OutData%chord_LL,2) + DO i1 = LBOUND(OutData%chord_LL,1), UBOUND(OutData%chord_LL,1) + OutData%chord_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! s_CP_LL 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%s_CP_LL)) DEALLOCATE(OutData%s_CP_LL) + ALLOCATE(OutData%s_CP_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%s_CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%s_CP_LL,2), UBOUND(OutData%s_CP_LL,2) + DO i1 = LBOUND(OutData%s_CP_LL,1), UBOUND(OutData%s_CP_LL,1) + OutData%s_CP_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! chord_CP_LL 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%chord_CP_LL)) DEALLOCATE(OutData%chord_CP_LL) + ALLOCATE(OutData%chord_CP_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%chord_CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%chord_CP_LL,2), UBOUND(OutData%chord_CP_LL,2) + DO i1 = LBOUND(OutData%chord_CP_LL,1), UBOUND(OutData%chord_CP_LL,1) + OutData%chord_CP_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CP_LL 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%CP_LL)) DEALLOCATE(OutData%CP_LL) + ALLOCATE(OutData%CP_LL(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%CP_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CP_LL,3), UBOUND(OutData%CP_LL,3) + DO i2 = LBOUND(OutData%CP_LL,2), UBOUND(OutData%CP_LL,2) + DO i1 = LBOUND(OutData%CP_LL,1), UBOUND(OutData%CP_LL,1) + OutData%CP_LL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Tang 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%Tang)) DEALLOCATE(OutData%Tang) + ALLOCATE(OutData%Tang(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%Tang.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Tang,3), UBOUND(OutData%Tang,3) + DO i2 = LBOUND(OutData%Tang,2), UBOUND(OutData%Tang,2) + DO i1 = LBOUND(OutData%Tang,1), UBOUND(OutData%Tang,1) + OutData%Tang(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Norm 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%Norm)) DEALLOCATE(OutData%Norm) + ALLOCATE(OutData%Norm(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%Norm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Norm,3), UBOUND(OutData%Norm,3) + DO i2 = LBOUND(OutData%Norm,2), UBOUND(OutData%Norm,2) + DO i1 = LBOUND(OutData%Norm,1), UBOUND(OutData%Norm,1) + OutData%Norm(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Orth 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%Orth)) DEALLOCATE(OutData%Orth) + ALLOCATE(OutData%Orth(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%Orth.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Orth,3), UBOUND(OutData%Orth,3) + DO i2 = LBOUND(OutData%Orth,2), UBOUND(OutData%Orth,2) + DO i1 = LBOUND(OutData%Orth,1), UBOUND(OutData%Orth,1) + OutData%Orth(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dl 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%dl)) DEALLOCATE(OutData%dl) + ALLOCATE(OutData%dl(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%dl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%dl,3), UBOUND(OutData%dl,3) + DO i2 = LBOUND(OutData%dl,2), UBOUND(OutData%dl,2) + DO i1 = LBOUND(OutData%dl,1), UBOUND(OutData%dl,1) + OutData%dl(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Area 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%Area)) DEALLOCATE(OutData%Area) + ALLOCATE(OutData%Area(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Area.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Area,2), UBOUND(OutData%Area,2) + DO i1 = LBOUND(OutData%Area,1), UBOUND(OutData%Area,1) + OutData%Area(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! diag_LL 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%diag_LL)) DEALLOCATE(OutData%diag_LL) + ALLOCATE(OutData%diag_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%diag_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%diag_LL,2), UBOUND(OutData%diag_LL,2) + DO i1 = LBOUND(OutData%diag_LL,1), UBOUND(OutData%diag_LL,1) + OutData%diag_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gamma_LL 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%Gamma_LL)) DEALLOCATE(OutData%Gamma_LL) + ALLOCATE(OutData%Gamma_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Gamma_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Gamma_LL,2), UBOUND(OutData%Gamma_LL,2) + DO i1 = LBOUND(OutData%Gamma_LL,1), UBOUND(OutData%Gamma_LL,1) + OutData%Gamma_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vind_LL 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%Vind_LL)) DEALLOCATE(OutData%Vind_LL) + ALLOCATE(OutData%Vind_LL(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%Vind_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vind_LL,3), UBOUND(OutData%Vind_LL,3) + DO i2 = LBOUND(OutData%Vind_LL,2), UBOUND(OutData%Vind_LL,2) + DO i1 = LBOUND(OutData%Vind_LL,1), UBOUND(OutData%Vind_LL,1) + OutData%Vind_LL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vtot_LL 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%Vtot_LL)) DEALLOCATE(OutData%Vtot_LL) + ALLOCATE(OutData%Vtot_LL(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%Vtot_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vtot_LL,3), UBOUND(OutData%Vtot_LL,3) + DO i2 = LBOUND(OutData%Vtot_LL,2), UBOUND(OutData%Vtot_LL,2) + DO i1 = LBOUND(OutData%Vtot_LL,1), UBOUND(OutData%Vtot_LL,1) + OutData%Vtot_LL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vstr_LL 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%Vstr_LL)) DEALLOCATE(OutData%Vstr_LL) + ALLOCATE(OutData%Vstr_LL(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%Vstr_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vstr_LL,3), UBOUND(OutData%Vstr_LL,3) + DO i2 = LBOUND(OutData%Vstr_LL,2), UBOUND(OutData%Vstr_LL,2) + DO i1 = LBOUND(OutData%Vstr_LL,1), UBOUND(OutData%Vstr_LL,1) + OutData%Vstr_LL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vwnd_LL 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%Vwnd_LL)) DEALLOCATE(OutData%Vwnd_LL) + ALLOCATE(OutData%Vwnd_LL(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%Vwnd_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vwnd_LL,3), UBOUND(OutData%Vwnd_LL,3) + DO i2 = LBOUND(OutData%Vwnd_LL,2), UBOUND(OutData%Vwnd_LL,2) + DO i1 = LBOUND(OutData%Vwnd_LL,1), UBOUND(OutData%Vwnd_LL,1) + OutData%Vwnd_LL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vwnd_NW 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%Vwnd_NW)) DEALLOCATE(OutData%Vwnd_NW) + ALLOCATE(OutData%Vwnd_NW(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%Vwnd_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Vwnd_NW,4), UBOUND(OutData%Vwnd_NW,4) + DO i3 = LBOUND(OutData%Vwnd_NW,3), UBOUND(OutData%Vwnd_NW,3) + DO i2 = LBOUND(OutData%Vwnd_NW,2), UBOUND(OutData%Vwnd_NW,2) + DO i1 = LBOUND(OutData%Vwnd_NW,1), UBOUND(OutData%Vwnd_NW,1) + OutData%Vwnd_NW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vwnd_FW 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%Vwnd_FW)) DEALLOCATE(OutData%Vwnd_FW) + ALLOCATE(OutData%Vwnd_FW(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%Vwnd_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Vwnd_FW,4), UBOUND(OutData%Vwnd_FW,4) + DO i3 = LBOUND(OutData%Vwnd_FW,3), UBOUND(OutData%Vwnd_FW,3) + DO i2 = LBOUND(OutData%Vwnd_FW,2), UBOUND(OutData%Vwnd_FW,2) + DO i1 = LBOUND(OutData%Vwnd_FW,1), UBOUND(OutData%Vwnd_FW,1) + OutData%Vwnd_FW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vind_NW 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%Vind_NW)) DEALLOCATE(OutData%Vind_NW) + ALLOCATE(OutData%Vind_NW(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%Vind_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Vind_NW,4), UBOUND(OutData%Vind_NW,4) + DO i3 = LBOUND(OutData%Vind_NW,3), UBOUND(OutData%Vind_NW,3) + DO i2 = LBOUND(OutData%Vind_NW,2), UBOUND(OutData%Vind_NW,2) + DO i1 = LBOUND(OutData%Vind_NW,1), UBOUND(OutData%Vind_NW,1) + OutData%Vind_NW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vind_FW 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%Vind_FW)) DEALLOCATE(OutData%Vind_FW) + ALLOCATE(OutData%Vind_FW(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%Vind_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Vind_FW,4), UBOUND(OutData%Vind_FW,4) + DO i3 = LBOUND(OutData%Vind_FW,3), UBOUND(OutData%Vind_FW,3) + DO i2 = LBOUND(OutData%Vind_FW,2), UBOUND(OutData%Vind_FW,2) + DO i1 = LBOUND(OutData%Vind_FW,1), UBOUND(OutData%Vind_FW,1) + OutData%Vind_FW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + OutData%nNW = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nFW = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%iStep = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKstep = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKlastTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r_wind 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%r_wind)) DEALLOCATE(OutData%r_wind) + ALLOCATE(OutData%r_wind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%r_wind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%r_wind,2), UBOUND(OutData%r_wind,2) + DO i1 = LBOUND(OutData%r_wind,1), UBOUND(OutData%r_wind,1) + OutData%r_wind(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PitchAndTwist 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%PitchAndTwist)) DEALLOCATE(OutData%PitchAndTwist) + ALLOCATE(OutData%PitchAndTwist(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PitchAndTwist.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PitchAndTwist,2), UBOUND(OutData%PitchAndTwist,2) + DO i1 = LBOUND(OutData%PitchAndTwist,1), UBOUND(OutData%PitchAndTwist,1) + OutData%PitchAndTwist(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%ComputeWakeInduced = TRANSFER(IntKiBuf(Int_Xferred), OutData%ComputeWakeInduced) + Int_Xferred = Int_Xferred + 1 + OutData%OldWakeTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%tSpent = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dxdt_NW 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%dxdt_NW)) DEALLOCATE(OutData%dxdt_NW) + ALLOCATE(OutData%dxdt_NW(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%dxdt_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%dxdt_NW,4), UBOUND(OutData%dxdt_NW,4) + DO i3 = LBOUND(OutData%dxdt_NW,3), UBOUND(OutData%dxdt_NW,3) + DO i2 = LBOUND(OutData%dxdt_NW,2), UBOUND(OutData%dxdt_NW,2) + DO i1 = LBOUND(OutData%dxdt_NW,1), UBOUND(OutData%dxdt_NW,1) + OutData%dxdt_NW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dxdt_FW 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%dxdt_FW)) DEALLOCATE(OutData%dxdt_FW) + ALLOCATE(OutData%dxdt_FW(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%dxdt_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%dxdt_FW,4), UBOUND(OutData%dxdt_FW,4) + DO i3 = LBOUND(OutData%dxdt_FW,3), UBOUND(OutData%dxdt_FW,3) + DO i2 = LBOUND(OutData%dxdt_FW,2), UBOUND(OutData%dxdt_FW,2) + DO i1 = LBOUND(OutData%dxdt_FW,1), UBOUND(OutData%dxdt_FW,1) + OutData%dxdt_FW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_LL 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%alpha_LL)) DEALLOCATE(OutData%alpha_LL) + ALLOCATE(OutData%alpha_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%alpha_LL,2), UBOUND(OutData%alpha_LL,2) + DO i1 = LBOUND(OutData%alpha_LL,1), UBOUND(OutData%alpha_LL,1) + OutData%alpha_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vreln_LL 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%Vreln_LL)) DEALLOCATE(OutData%Vreln_LL) + ALLOCATE(OutData%Vreln_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vreln_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vreln_LL,2), UBOUND(OutData%Vreln_LL,2) + DO i1 = LBOUND(OutData%Vreln_LL,1), UBOUND(OutData%Vreln_LL,1) + OutData%Vreln_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SegConnct 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%SegConnct)) DEALLOCATE(OutData%SegConnct) + ALLOCATE(OutData%SegConnct(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SegConnct.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SegConnct,2), UBOUND(OutData%SegConnct,2) + DO i1 = LBOUND(OutData%SegConnct,1), UBOUND(OutData%SegConnct,1) + OutData%SegConnct(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SegPoints 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%SegPoints)) DEALLOCATE(OutData%SegPoints) + ALLOCATE(OutData%SegPoints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SegPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SegPoints,2), UBOUND(OutData%SegPoints,2) + DO i1 = LBOUND(OutData%SegPoints,1), UBOUND(OutData%SegPoints,1) + OutData%SegPoints(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SegGamma 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%SegGamma)) DEALLOCATE(OutData%SegGamma) + ALLOCATE(OutData%SegGamma(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SegGamma.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SegGamma,1), UBOUND(OutData%SegGamma,1) + OutData%SegGamma(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SegEpsilon 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%SegEpsilon)) DEALLOCATE(OutData%SegEpsilon) + ALLOCATE(OutData%SegEpsilon(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SegEpsilon.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SegEpsilon,1), UBOUND(OutData%SegEpsilon,1) + OutData%SegEpsilon(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CPs 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%CPs)) DEALLOCATE(OutData%CPs) + ALLOCATE(OutData%CPs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CPs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CPs,2), UBOUND(OutData%CPs,2) + DO i1 = LBOUND(OutData%CPs,1), UBOUND(OutData%CPs,1) + OutData%CPs(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Uind 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%Uind)) DEALLOCATE(OutData%Uind) + ALLOCATE(OutData%Uind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Uind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Uind,2), UBOUND(OutData%Uind,2) + DO i1 = LBOUND(OutData%Uind,1), UBOUND(OutData%Uind,1) + OutData%Uind(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_AxInd 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%BN_AxInd)) DEALLOCATE(OutData%BN_AxInd) + ALLOCATE(OutData%BN_AxInd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_AxInd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_AxInd,2), UBOUND(OutData%BN_AxInd,2) + DO i1 = LBOUND(OutData%BN_AxInd,1), UBOUND(OutData%BN_AxInd,1) + OutData%BN_AxInd(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_TanInd 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%BN_TanInd)) DEALLOCATE(OutData%BN_TanInd) + ALLOCATE(OutData%BN_TanInd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_TanInd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_TanInd,2), UBOUND(OutData%BN_TanInd,2) + DO i1 = LBOUND(OutData%BN_TanInd,1), UBOUND(OutData%BN_TanInd,1) + OutData%BN_TanInd(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Vrel 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%BN_Vrel)) DEALLOCATE(OutData%BN_Vrel) + ALLOCATE(OutData%BN_Vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Vrel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Vrel,2), UBOUND(OutData%BN_Vrel,2) + DO i1 = LBOUND(OutData%BN_Vrel,1), UBOUND(OutData%BN_Vrel,1) + OutData%BN_Vrel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_alpha 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%BN_alpha)) DEALLOCATE(OutData%BN_alpha) + ALLOCATE(OutData%BN_alpha(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_alpha,2), UBOUND(OutData%BN_alpha,2) + DO i1 = LBOUND(OutData%BN_alpha,1), UBOUND(OutData%BN_alpha,1) + OutData%BN_alpha(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_phi 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%BN_phi)) DEALLOCATE(OutData%BN_phi) + ALLOCATE(OutData%BN_phi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_phi,2), UBOUND(OutData%BN_phi,2) + DO i1 = LBOUND(OutData%BN_phi,1), UBOUND(OutData%BN_phi,1) + OutData%BN_phi(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Re 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%BN_Re)) DEALLOCATE(OutData%BN_Re) + ALLOCATE(OutData%BN_Re(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Re.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Re,2), UBOUND(OutData%BN_Re,2) + DO i1 = LBOUND(OutData%BN_Re,1), UBOUND(OutData%BN_Re,1) + OutData%BN_Re(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_URelWind_s 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%BN_URelWind_s)) DEALLOCATE(OutData%BN_URelWind_s) + ALLOCATE(OutData%BN_URelWind_s(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%BN_URelWind_s.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%BN_URelWind_s,3), UBOUND(OutData%BN_URelWind_s,3) + DO i2 = LBOUND(OutData%BN_URelWind_s,2), UBOUND(OutData%BN_URelWind_s,2) + DO i1 = LBOUND(OutData%BN_URelWind_s,1), UBOUND(OutData%BN_URelWind_s,1) + OutData%BN_URelWind_s(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cl_Static 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%BN_Cl_Static)) DEALLOCATE(OutData%BN_Cl_Static) + ALLOCATE(OutData%BN_Cl_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cl_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cl_Static,2), UBOUND(OutData%BN_Cl_Static,2) + DO i1 = LBOUND(OutData%BN_Cl_Static,1), UBOUND(OutData%BN_Cl_Static,1) + OutData%BN_Cl_Static(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cd_Static 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%BN_Cd_Static)) DEALLOCATE(OutData%BN_Cd_Static) + ALLOCATE(OutData%BN_Cd_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cd_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cd_Static,2), UBOUND(OutData%BN_Cd_Static,2) + DO i1 = LBOUND(OutData%BN_Cd_Static,1), UBOUND(OutData%BN_Cd_Static,1) + OutData%BN_Cd_Static(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cm_Static 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%BN_Cm_Static)) DEALLOCATE(OutData%BN_Cm_Static) + ALLOCATE(OutData%BN_Cm_Static(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cm_Static.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cm_Static,2), UBOUND(OutData%BN_Cm_Static,2) + DO i1 = LBOUND(OutData%BN_Cm_Static,1), UBOUND(OutData%BN_Cm_Static,1) + OutData%BN_Cm_Static(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cl 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%BN_Cl)) DEALLOCATE(OutData%BN_Cl) + ALLOCATE(OutData%BN_Cl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cl,2), UBOUND(OutData%BN_Cl,2) + DO i1 = LBOUND(OutData%BN_Cl,1), UBOUND(OutData%BN_Cl,1) + OutData%BN_Cl(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cd 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%BN_Cd)) DEALLOCATE(OutData%BN_Cd) + ALLOCATE(OutData%BN_Cd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cd,2), UBOUND(OutData%BN_Cd,2) + DO i1 = LBOUND(OutData%BN_Cd,1), UBOUND(OutData%BN_Cd,1) + OutData%BN_Cd(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cm 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%BN_Cm)) DEALLOCATE(OutData%BN_Cm) + ALLOCATE(OutData%BN_Cm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cm,2), UBOUND(OutData%BN_Cm,2) + DO i1 = LBOUND(OutData%BN_Cm,1), UBOUND(OutData%BN_Cm,1) + OutData%BN_Cm(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cx 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%BN_Cx)) DEALLOCATE(OutData%BN_Cx) + ALLOCATE(OutData%BN_Cx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cx,2), UBOUND(OutData%BN_Cx,2) + DO i1 = LBOUND(OutData%BN_Cx,1), UBOUND(OutData%BN_Cx,1) + OutData%BN_Cx(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BN_Cy 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%BN_Cy)) DEALLOCATE(OutData%BN_Cy) + ALLOCATE(OutData%BN_Cy(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BN_Cy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BN_Cy,2), UBOUND(OutData%BN_Cy,2) + DO i1 = LBOUND(OutData%BN_Cy,1), UBOUND(OutData%BN_Cy,1) + OutData%BN_Cy(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 UA_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m_UA, ErrStat2, ErrMsg2 ) ! m_UA + 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 UA_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_UA, ErrStat2, ErrMsg2 ) ! y_UA + 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 UA_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p_UA, ErrStat2, ErrMsg2 ) ! p_UA + 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%UA_Flag = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vwnd_ND 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%Vwnd_ND)) DEALLOCATE(OutData%Vwnd_ND) + ALLOCATE(OutData%Vwnd_ND(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%Vwnd_ND.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vwnd_ND,3), UBOUND(OutData%Vwnd_ND,3) + DO i2 = LBOUND(OutData%Vwnd_ND,2), UBOUND(OutData%Vwnd_ND,2) + DO i1 = LBOUND(OutData%Vwnd_ND,1), UBOUND(OutData%Vwnd_ND,1) + OutData%Vwnd_ND(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FVW_UnPackMisc + + SUBROUTINE FVW_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_InputType), INTENT(INOUT) :: SrcInputData + TYPE(FVW_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 = 'FVW_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%WingsMesh)) THEN + i1_l = LBOUND(SrcInputData%WingsMesh,1) + i1_u = UBOUND(SrcInputData%WingsMesh,1) + IF (.NOT. ALLOCATED(DstInputData%WingsMesh)) THEN + ALLOCATE(DstInputData%WingsMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%WingsMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%WingsMesh,1), UBOUND(SrcInputData%WingsMesh,1) + CALL MeshCopy( SrcInputData%WingsMesh(i1), DstInputData%WingsMesh(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInputData%V_wind)) THEN + i1_l = LBOUND(SrcInputData%V_wind,1) + i1_u = UBOUND(SrcInputData%V_wind,1) + i2_l = LBOUND(SrcInputData%V_wind,2) + i2_u = UBOUND(SrcInputData%V_wind,2) + IF (.NOT. ALLOCATED(DstInputData%V_wind)) THEN + ALLOCATE(DstInputData%V_wind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%V_wind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%V_wind = SrcInputData%V_wind +ENDIF + DstInputData%HubOrientation = SrcInputData%HubOrientation + DstInputData%HubPosition = SrcInputData%HubPosition + END SUBROUTINE FVW_CopyInput + + SUBROUTINE FVW_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(FVW_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%WingsMesh)) THEN +DO i1 = LBOUND(InputData%WingsMesh,1), UBOUND(InputData%WingsMesh,1) + CALL MeshDestroy( InputData%WingsMesh(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%WingsMesh) +ENDIF +IF (ALLOCATED(InputData%V_wind)) THEN + DEALLOCATE(InputData%V_wind) +ENDIF + END SUBROUTINE FVW_DestroyInput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! WingsMesh allocated yes/no + IF ( ALLOCATED(InData%WingsMesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WingsMesh upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%WingsMesh,1), UBOUND(InData%WingsMesh,1) + Int_BufSz = Int_BufSz + 3 ! WingsMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! WingsMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WingsMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WingsMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WingsMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! V_wind allocated yes/no + IF ( ALLOCATED(InData%V_wind) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! V_wind upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%V_wind) ! V_wind + END IF + Re_BufSz = Re_BufSz + SIZE(InData%HubOrientation) ! HubOrientation + Re_BufSz = Re_BufSz + SIZE(InData%HubPosition) ! HubPosition + 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%WingsMesh) ) 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%WingsMesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WingsMesh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WingsMesh,1), UBOUND(InData%WingsMesh,1) + CALL MeshPack( InData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! WingsMesh + 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%V_wind) ) 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_wind,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V_wind,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%V_wind,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V_wind,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%V_wind,2), UBOUND(InData%V_wind,2) + DO i1 = LBOUND(InData%V_wind,1), UBOUND(InData%V_wind,1) + ReKiBuf(Re_Xferred) = InData%V_wind(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i2 = LBOUND(InData%HubOrientation,2), UBOUND(InData%HubOrientation,2) + DO i1 = LBOUND(InData%HubOrientation,1), UBOUND(InData%HubOrientation,1) + ReKiBuf(Re_Xferred) = InData%HubOrientation(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%HubPosition,1), UBOUND(InData%HubPosition,1) + ReKiBuf(Re_Xferred) = InData%HubPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FVW_PackInput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! WingsMesh 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%WingsMesh)) DEALLOCATE(OutData%WingsMesh) + ALLOCATE(OutData%WingsMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WingsMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WingsMesh,1), UBOUND(OutData%WingsMesh,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 MeshUnpack( OutData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! WingsMesh + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! V_wind 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%V_wind)) DEALLOCATE(OutData%V_wind) + ALLOCATE(OutData%V_wind(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%V_wind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%V_wind,2), UBOUND(OutData%V_wind,2) + DO i1 = LBOUND(OutData%V_wind,1), UBOUND(OutData%V_wind,1) + OutData%V_wind(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%HubOrientation,1) + i1_u = UBOUND(OutData%HubOrientation,1) + i2_l = LBOUND(OutData%HubOrientation,2) + i2_u = UBOUND(OutData%HubOrientation,2) + DO i2 = LBOUND(OutData%HubOrientation,2), UBOUND(OutData%HubOrientation,2) + DO i1 = LBOUND(OutData%HubOrientation,1), UBOUND(OutData%HubOrientation,1) + OutData%HubOrientation(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%HubPosition,1) + i1_u = UBOUND(OutData%HubPosition,1) + DO i1 = LBOUND(OutData%HubPosition,1), UBOUND(OutData%HubPosition,1) + OutData%HubPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FVW_UnPackInput + + SUBROUTINE FVW_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_OutputType), INTENT(IN) :: SrcOutputData + TYPE(FVW_OutputType), INTENT(INOUT) :: DstOutputData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%Vind)) THEN + i1_l = LBOUND(SrcOutputData%Vind,1) + i1_u = UBOUND(SrcOutputData%Vind,1) + i2_l = LBOUND(SrcOutputData%Vind,2) + i2_u = UBOUND(SrcOutputData%Vind,2) + i3_l = LBOUND(SrcOutputData%Vind,3) + i3_u = UBOUND(SrcOutputData%Vind,3) + IF (.NOT. ALLOCATED(DstOutputData%Vind)) THEN + ALLOCATE(DstOutputData%Vind(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Vind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Vind = SrcOutputData%Vind +ENDIF +IF (ALLOCATED(SrcOutputData%Cl_KJ)) THEN + i1_l = LBOUND(SrcOutputData%Cl_KJ,1) + i1_u = UBOUND(SrcOutputData%Cl_KJ,1) + i2_l = LBOUND(SrcOutputData%Cl_KJ,2) + i2_u = UBOUND(SrcOutputData%Cl_KJ,2) + IF (.NOT. ALLOCATED(DstOutputData%Cl_KJ)) THEN + ALLOCATE(DstOutputData%Cl_KJ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Cl_KJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Cl_KJ = SrcOutputData%Cl_KJ +ENDIF + END SUBROUTINE FVW_CopyOutput + + SUBROUTINE FVW_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(FVW_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%Vind)) THEN + DEALLOCATE(OutputData%Vind) +ENDIF +IF (ALLOCATED(OutputData%Cl_KJ)) THEN + DEALLOCATE(OutputData%Cl_KJ) +ENDIF + END SUBROUTINE FVW_DestroyOutput + + SUBROUTINE FVW_PackOutput( 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(FVW_OutputType), 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 = 'FVW_PackOutput' + ! 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 ! Vind allocated yes/no + IF ( ALLOCATED(InData%Vind) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Vind upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vind) ! Vind + END IF + Int_BufSz = Int_BufSz + 1 ! Cl_KJ allocated yes/no + IF ( ALLOCATED(InData%Cl_KJ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cl_KJ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cl_KJ) ! Cl_KJ + 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%Vind) ) 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%Vind,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Vind,3), UBOUND(InData%Vind,3) + DO i2 = LBOUND(InData%Vind,2), UBOUND(InData%Vind,2) + DO i1 = LBOUND(InData%Vind,1), UBOUND(InData%Vind,1) + ReKiBuf(Re_Xferred) = InData%Vind(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cl_KJ) ) 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%Cl_KJ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cl_KJ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cl_KJ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cl_KJ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cl_KJ,2), UBOUND(InData%Cl_KJ,2) + DO i1 = LBOUND(InData%Cl_KJ,1), UBOUND(InData%Cl_KJ,1) + ReKiBuf(Re_Xferred) = InData%Cl_KJ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_PackOutput + + SUBROUTINE FVW_UnPackOutput( 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(FVW_OutputType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_UnPackOutput' + ! 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 ! Vind 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%Vind)) DEALLOCATE(OutData%Vind) + ALLOCATE(OutData%Vind(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%Vind.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Vind,3), UBOUND(OutData%Vind,3) + DO i2 = LBOUND(OutData%Vind,2), UBOUND(OutData%Vind,2) + DO i1 = LBOUND(OutData%Vind,1), UBOUND(OutData%Vind,1) + OutData%Vind(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cl_KJ 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%Cl_KJ)) DEALLOCATE(OutData%Cl_KJ) + ALLOCATE(OutData%Cl_KJ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cl_KJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cl_KJ,2), UBOUND(OutData%Cl_KJ,2) + DO i1 = LBOUND(OutData%Cl_KJ,1), UBOUND(OutData%Cl_KJ,1) + OutData%Cl_KJ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_UnPackOutput + + SUBROUTINE FVW_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(FVW_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) :: 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 = 'FVW_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%Gamma_NW)) THEN + i1_l = LBOUND(SrcContStateData%Gamma_NW,1) + i1_u = UBOUND(SrcContStateData%Gamma_NW,1) + i2_l = LBOUND(SrcContStateData%Gamma_NW,2) + i2_u = UBOUND(SrcContStateData%Gamma_NW,2) + i3_l = LBOUND(SrcContStateData%Gamma_NW,3) + i3_u = UBOUND(SrcContStateData%Gamma_NW,3) + IF (.NOT. ALLOCATED(DstContStateData%Gamma_NW)) THEN + ALLOCATE(DstContStateData%Gamma_NW(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%Gamma_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%Gamma_NW = SrcContStateData%Gamma_NW +ENDIF +IF (ALLOCATED(SrcContStateData%Gamma_FW)) THEN + i1_l = LBOUND(SrcContStateData%Gamma_FW,1) + i1_u = UBOUND(SrcContStateData%Gamma_FW,1) + i2_l = LBOUND(SrcContStateData%Gamma_FW,2) + i2_u = UBOUND(SrcContStateData%Gamma_FW,2) + i3_l = LBOUND(SrcContStateData%Gamma_FW,3) + i3_u = UBOUND(SrcContStateData%Gamma_FW,3) + IF (.NOT. ALLOCATED(DstContStateData%Gamma_FW)) THEN + ALLOCATE(DstContStateData%Gamma_FW(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%Gamma_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%Gamma_FW = SrcContStateData%Gamma_FW +ENDIF +IF (ALLOCATED(SrcContStateData%r_NW)) THEN + i1_l = LBOUND(SrcContStateData%r_NW,1) + i1_u = UBOUND(SrcContStateData%r_NW,1) + i2_l = LBOUND(SrcContStateData%r_NW,2) + i2_u = UBOUND(SrcContStateData%r_NW,2) + i3_l = LBOUND(SrcContStateData%r_NW,3) + i3_u = UBOUND(SrcContStateData%r_NW,3) + i4_l = LBOUND(SrcContStateData%r_NW,4) + i4_u = UBOUND(SrcContStateData%r_NW,4) + IF (.NOT. ALLOCATED(DstContStateData%r_NW)) THEN + ALLOCATE(DstContStateData%r_NW(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 DstContStateData%r_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%r_NW = SrcContStateData%r_NW +ENDIF +IF (ALLOCATED(SrcContStateData%r_FW)) THEN + i1_l = LBOUND(SrcContStateData%r_FW,1) + i1_u = UBOUND(SrcContStateData%r_FW,1) + i2_l = LBOUND(SrcContStateData%r_FW,2) + i2_u = UBOUND(SrcContStateData%r_FW,2) + i3_l = LBOUND(SrcContStateData%r_FW,3) + i3_u = UBOUND(SrcContStateData%r_FW,3) + i4_l = LBOUND(SrcContStateData%r_FW,4) + i4_u = UBOUND(SrcContStateData%r_FW,4) + IF (.NOT. ALLOCATED(DstContStateData%r_FW)) THEN + ALLOCATE(DstContStateData%r_FW(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 DstContStateData%r_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%r_FW = SrcContStateData%r_FW +ENDIF + CALL UA_CopyContState( SrcContStateData%UA, DstContStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FVW_CopyContState + + SUBROUTINE FVW_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(FVW_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%Gamma_NW)) THEN + DEALLOCATE(ContStateData%Gamma_NW) +ENDIF +IF (ALLOCATED(ContStateData%Gamma_FW)) THEN + DEALLOCATE(ContStateData%Gamma_FW) +ENDIF +IF (ALLOCATED(ContStateData%r_NW)) THEN + DEALLOCATE(ContStateData%r_NW) +ENDIF +IF (ALLOCATED(ContStateData%r_FW)) THEN + DEALLOCATE(ContStateData%r_FW) +ENDIF + CALL UA_DestroyContState( ContStateData%UA, ErrStat, ErrMsg ) + END SUBROUTINE FVW_DestroyContState + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 + Int_BufSz = Int_BufSz + 1 ! Gamma_NW allocated yes/no + IF ( ALLOCATED(InData%Gamma_NW) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Gamma_NW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Gamma_NW) ! Gamma_NW + END IF + Int_BufSz = Int_BufSz + 1 ! Gamma_FW allocated yes/no + IF ( ALLOCATED(InData%Gamma_FW) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Gamma_FW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Gamma_FW) ! Gamma_FW + END IF + Int_BufSz = Int_BufSz + 1 ! r_NW allocated yes/no + IF ( ALLOCATED(InData%r_NW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! r_NW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r_NW) ! r_NW + END IF + Int_BufSz = Int_BufSz + 1 ! r_FW allocated yes/no + IF ( ALLOCATED(InData%r_FW) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! r_FW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r_FW) ! r_FW + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + 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 + + IF ( .NOT. ALLOCATED(InData%Gamma_NW) ) 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%Gamma_NW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_NW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_NW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_NW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_NW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_NW,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Gamma_NW,3), UBOUND(InData%Gamma_NW,3) + DO i2 = LBOUND(InData%Gamma_NW,2), UBOUND(InData%Gamma_NW,2) + DO i1 = LBOUND(InData%Gamma_NW,1), UBOUND(InData%Gamma_NW,1) + ReKiBuf(Re_Xferred) = InData%Gamma_NW(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Gamma_FW) ) 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%Gamma_FW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_FW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_FW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_FW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_FW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_FW,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Gamma_FW,3), UBOUND(InData%Gamma_FW,3) + DO i2 = LBOUND(InData%Gamma_FW,2), UBOUND(InData%Gamma_FW,2) + DO i1 = LBOUND(InData%Gamma_FW,1), UBOUND(InData%Gamma_FW,1) + ReKiBuf(Re_Xferred) = InData%Gamma_FW(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%r_NW) ) 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%r_NW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_NW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_NW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_NW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_NW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_NW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_NW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_NW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%r_NW,4), UBOUND(InData%r_NW,4) + DO i3 = LBOUND(InData%r_NW,3), UBOUND(InData%r_NW,3) + DO i2 = LBOUND(InData%r_NW,2), UBOUND(InData%r_NW,2) + DO i1 = LBOUND(InData%r_NW,1), UBOUND(InData%r_NW,1) + ReKiBuf(Re_Xferred) = InData%r_NW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%r_FW) ) 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%r_FW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_FW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_FW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_FW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_FW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_FW,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r_FW,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_FW,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%r_FW,4), UBOUND(InData%r_FW,4) + DO i3 = LBOUND(InData%r_FW,3), UBOUND(InData%r_FW,3) + DO i2 = LBOUND(InData%r_FW,2), UBOUND(InData%r_FW,2) + DO i1 = LBOUND(InData%r_FW,1), UBOUND(InData%r_FW,1) + ReKiBuf(Re_Xferred) = InData%r_FW(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + CALL UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 FVW_PackContState + + SUBROUTINE FVW_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(FVW_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) :: 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 = 'FVW_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gamma_NW 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%Gamma_NW)) DEALLOCATE(OutData%Gamma_NW) + ALLOCATE(OutData%Gamma_NW(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%Gamma_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Gamma_NW,3), UBOUND(OutData%Gamma_NW,3) + DO i2 = LBOUND(OutData%Gamma_NW,2), UBOUND(OutData%Gamma_NW,2) + DO i1 = LBOUND(OutData%Gamma_NW,1), UBOUND(OutData%Gamma_NW,1) + OutData%Gamma_NW(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gamma_FW 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%Gamma_FW)) DEALLOCATE(OutData%Gamma_FW) + ALLOCATE(OutData%Gamma_FW(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%Gamma_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Gamma_FW,3), UBOUND(OutData%Gamma_FW,3) + DO i2 = LBOUND(OutData%Gamma_FW,2), UBOUND(OutData%Gamma_FW,2) + DO i1 = LBOUND(OutData%Gamma_FW,1), UBOUND(OutData%Gamma_FW,1) + OutData%Gamma_FW(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r_NW 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%r_NW)) DEALLOCATE(OutData%r_NW) + ALLOCATE(OutData%r_NW(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%r_NW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%r_NW,4), UBOUND(OutData%r_NW,4) + DO i3 = LBOUND(OutData%r_NW,3), UBOUND(OutData%r_NW,3) + DO i2 = LBOUND(OutData%r_NW,2), UBOUND(OutData%r_NW,2) + DO i1 = LBOUND(OutData%r_NW,1), UBOUND(OutData%r_NW,1) + OutData%r_NW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r_FW 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%r_FW)) DEALLOCATE(OutData%r_FW) + ALLOCATE(OutData%r_FW(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%r_FW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%r_FW,4), UBOUND(OutData%r_FW,4) + DO i3 = LBOUND(OutData%r_FW,3), UBOUND(OutData%r_FW,3) + DO i2 = LBOUND(OutData%r_FW,2), UBOUND(OutData%r_FW,2) + DO i1 = LBOUND(OutData%r_FW,1), UBOUND(OutData%r_FW,1) + OutData%r_FW(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + 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 UA_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 FVW_UnPackContState + + SUBROUTINE FVW_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(FVW_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 = 'FVW_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%NULL = SrcDiscStateData%NULL + CALL UA_CopyDiscState( SrcDiscStateData%UA, DstDiscStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FVW_CopyDiscState + + SUBROUTINE FVW_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(FVW_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyDiscState( DiscStateData%UA, ErrStat, ErrMsg ) + END SUBROUTINE FVW_DestroyDiscState + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! NULL + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + 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 + + ReKiBuf(Re_Xferred) = InData%NULL + Re_Xferred = Re_Xferred + 1 + CALL UA_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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 FVW_PackDiscState + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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%NULL = 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 UA_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 FVW_UnPackDiscState + + SUBROUTINE FVW_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(FVW_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) :: 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 = 'FVW_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%residual = SrcConstrStateData%residual +IF (ALLOCATED(SrcConstrStateData%Gamma_LL)) THEN + i1_l = LBOUND(SrcConstrStateData%Gamma_LL,1) + i1_u = UBOUND(SrcConstrStateData%Gamma_LL,1) + i2_l = LBOUND(SrcConstrStateData%Gamma_LL,2) + i2_u = UBOUND(SrcConstrStateData%Gamma_LL,2) + IF (.NOT. ALLOCATED(DstConstrStateData%Gamma_LL)) THEN + ALLOCATE(DstConstrStateData%Gamma_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%Gamma_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstConstrStateData%Gamma_LL = SrcConstrStateData%Gamma_LL +ENDIF + END SUBROUTINE FVW_CopyConstrState + + SUBROUTINE FVW_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(FVW_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ConstrStateData%Gamma_LL)) THEN + DEALLOCATE(ConstrStateData%Gamma_LL) +ENDIF + END SUBROUTINE FVW_DestroyConstrState + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 ! residual + Int_BufSz = Int_BufSz + 1 ! Gamma_LL allocated yes/no + IF ( ALLOCATED(InData%Gamma_LL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Gamma_LL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Gamma_LL) ! Gamma_LL + 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%residual + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Gamma_LL) ) 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%Gamma_LL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_LL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gamma_LL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma_LL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Gamma_LL,2), UBOUND(InData%Gamma_LL,2) + DO i1 = LBOUND(InData%Gamma_LL,1), UBOUND(InData%Gamma_LL,1) + ReKiBuf(Re_Xferred) = InData%Gamma_LL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_PackConstrState + + SUBROUTINE FVW_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(FVW_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) :: 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 = 'FVW_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%residual = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gamma_LL 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%Gamma_LL)) DEALLOCATE(OutData%Gamma_LL) + ALLOCATE(OutData%Gamma_LL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Gamma_LL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Gamma_LL,2), UBOUND(OutData%Gamma_LL,2) + DO i1 = LBOUND(OutData%Gamma_LL,1), UBOUND(OutData%Gamma_LL,1) + OutData%Gamma_LL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_UnPackConstrState + + SUBROUTINE FVW_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(FVW_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) :: 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 = 'FVW_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%NULL = SrcOtherStateData%NULL + CALL UA_CopyOtherState( SrcOtherStateData%UA, DstOtherStateData%UA, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOtherStateData%UA_Flag)) THEN + i1_l = LBOUND(SrcOtherStateData%UA_Flag,1) + i1_u = UBOUND(SrcOtherStateData%UA_Flag,1) + i2_l = LBOUND(SrcOtherStateData%UA_Flag,2) + i2_u = UBOUND(SrcOtherStateData%UA_Flag,2) + IF (.NOT. ALLOCATED(DstOtherStateData%UA_Flag)) THEN + ALLOCATE(DstOtherStateData%UA_Flag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%UA_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%UA_Flag = SrcOtherStateData%UA_Flag +ENDIF + END SUBROUTINE FVW_CopyOtherState + + SUBROUTINE FVW_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(FVW_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL UA_DestroyOtherState( OtherStateData%UA, ErrStat, ErrMsg ) +IF (ALLOCATED(OtherStateData%UA_Flag)) THEN + DEALLOCATE(OtherStateData%UA_Flag) +ENDIF + END SUBROUTINE FVW_DestroyOtherState + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 + Int_BufSz = Int_BufSz + 1 ! NULL + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! UA: size of buffers for each call to pack subtype + CALL UA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, .TRUE. ) ! UA + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! UA + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! UA + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! UA + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! UA_Flag allocated yes/no + IF ( ALLOCATED(InData%UA_Flag) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! UA_Flag upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%UA_Flag) ! UA_Flag + 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%NULL + Int_Xferred = Int_Xferred + 1 + CALL UA_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%UA, ErrStat2, ErrMsg2, OnlySize ) ! UA + 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%UA_Flag) ) 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%UA_Flag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UA_Flag,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UA_Flag,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UA_Flag,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%UA_Flag,2), UBOUND(InData%UA_Flag,2) + DO i1 = LBOUND(InData%UA_Flag,1), UBOUND(InData%UA_Flag,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%UA_Flag(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_PackOtherState + + SUBROUTINE FVW_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(FVW_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) :: 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 = 'FVW_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%NULL = 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 UA_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%UA, ErrStat2, ErrMsg2 ) ! UA + 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 ! UA_Flag 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%UA_Flag)) DEALLOCATE(OutData%UA_Flag) + ALLOCATE(OutData%UA_Flag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UA_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%UA_Flag,2), UBOUND(OutData%UA_Flag,2) + DO i1 = LBOUND(OutData%UA_Flag,1), UBOUND(OutData%UA_Flag,1) + OutData%UA_Flag(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FVW_UnPackOtherState + + SUBROUTINE FVW_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_InitInputType), INTENT(INOUT) :: SrcInitInputData + TYPE(FVW_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 = 'FVW_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%FVWFileName = SrcInitInputData%FVWFileName + DstInitInputData%RootName = SrcInitInputData%RootName +IF (ALLOCATED(SrcInitInputData%WingsMesh)) THEN + i1_l = LBOUND(SrcInitInputData%WingsMesh,1) + i1_u = UBOUND(SrcInitInputData%WingsMesh,1) + IF (.NOT. ALLOCATED(DstInitInputData%WingsMesh)) THEN + ALLOCATE(DstInitInputData%WingsMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WingsMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%WingsMesh,1), UBOUND(SrcInitInputData%WingsMesh,1) + CALL MeshCopy( SrcInitInputData%WingsMesh(i1), DstInitInputData%WingsMesh(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInitInputData%AFindx)) THEN + i1_l = LBOUND(SrcInitInputData%AFindx,1) + i1_u = UBOUND(SrcInitInputData%AFindx,1) + i2_l = LBOUND(SrcInitInputData%AFindx,2) + i2_u = UBOUND(SrcInitInputData%AFindx,2) + IF (.NOT. ALLOCATED(DstInitInputData%AFindx)) THEN + ALLOCATE(DstInitInputData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%AFindx = SrcInitInputData%AFindx +ENDIF +IF (ALLOCATED(SrcInitInputData%Chord)) THEN + i1_l = LBOUND(SrcInitInputData%Chord,1) + i1_u = UBOUND(SrcInitInputData%Chord,1) + i2_l = LBOUND(SrcInitInputData%Chord,2) + i2_u = UBOUND(SrcInitInputData%Chord,2) + IF (.NOT. ALLOCATED(DstInitInputData%Chord)) THEN + ALLOCATE(DstInitInputData%Chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%Chord = SrcInitInputData%Chord +ENDIF +IF (ALLOCATED(SrcInitInputData%RElm)) THEN + i1_l = LBOUND(SrcInitInputData%RElm,1) + i1_u = UBOUND(SrcInitInputData%RElm,1) + IF (.NOT. ALLOCATED(DstInitInputData%RElm)) THEN + ALLOCATE(DstInitInputData%RElm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%RElm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%RElm = SrcInitInputData%RElm +ENDIF +IF (ALLOCATED(SrcInitInputData%zHub)) THEN + i1_l = LBOUND(SrcInitInputData%zHub,1) + i1_u = UBOUND(SrcInitInputData%zHub,1) + IF (.NOT. ALLOCATED(DstInitInputData%zHub)) THEN + ALLOCATE(DstInitInputData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zHub = SrcInitInputData%zHub +ENDIF +IF (ALLOCATED(SrcInitInputData%zLocal)) THEN + i1_l = LBOUND(SrcInitInputData%zLocal,1) + i1_u = UBOUND(SrcInitInputData%zLocal,1) + i2_l = LBOUND(SrcInitInputData%zLocal,2) + i2_u = UBOUND(SrcInitInputData%zLocal,2) + IF (.NOT. ALLOCATED(DstInitInputData%zLocal)) THEN + ALLOCATE(DstInitInputData%zLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zLocal = SrcInitInputData%zLocal +ENDIF +IF (ALLOCATED(SrcInitInputData%zTip)) THEN + i1_l = LBOUND(SrcInitInputData%zTip,1) + i1_u = UBOUND(SrcInitInputData%zTip,1) + IF (.NOT. ALLOCATED(DstInitInputData%zTip)) THEN + ALLOCATE(DstInitInputData%zTip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%zTip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%zTip = SrcInitInputData%zTip +ENDIF +IF (ALLOCATED(SrcInitInputData%rLocal)) THEN + i1_l = LBOUND(SrcInitInputData%rLocal,1) + i1_u = UBOUND(SrcInitInputData%rLocal,1) + i2_l = LBOUND(SrcInitInputData%rLocal,2) + i2_u = UBOUND(SrcInitInputData%rLocal,2) + IF (.NOT. ALLOCATED(DstInitInputData%rLocal)) THEN + ALLOCATE(DstInitInputData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%rLocal = SrcInitInputData%rLocal +ENDIF + DstInitInputData%NumBlades = SrcInitInputData%NumBlades + DstInitInputData%NumBladeNodes = SrcInitInputData%NumBladeNodes + DstInitInputData%DTaero = SrcInitInputData%DTaero + DstInitInputData%KinVisc = SrcInitInputData%KinVisc + DstInitInputData%UAMod = SrcInitInputData%UAMod + DstInitInputData%UA_Flag = SrcInitInputData%UA_Flag + DstInitInputData%Flookup = SrcInitInputData%Flookup + DstInitInputData%a_s = SrcInitInputData%a_s + END SUBROUTINE FVW_CopyInitInput + + SUBROUTINE FVW_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(FVW_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WingsMesh)) THEN +DO i1 = LBOUND(InitInputData%WingsMesh,1), UBOUND(InitInputData%WingsMesh,1) + CALL MeshDestroy( InitInputData%WingsMesh(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%WingsMesh) +ENDIF +IF (ALLOCATED(InitInputData%AFindx)) THEN + DEALLOCATE(InitInputData%AFindx) +ENDIF +IF (ALLOCATED(InitInputData%Chord)) THEN + DEALLOCATE(InitInputData%Chord) +ENDIF +IF (ALLOCATED(InitInputData%RElm)) THEN + DEALLOCATE(InitInputData%RElm) +ENDIF +IF (ALLOCATED(InitInputData%zHub)) THEN + DEALLOCATE(InitInputData%zHub) +ENDIF +IF (ALLOCATED(InitInputData%zLocal)) THEN + DEALLOCATE(InitInputData%zLocal) +ENDIF +IF (ALLOCATED(InitInputData%zTip)) THEN + DEALLOCATE(InitInputData%zTip) +ENDIF +IF (ALLOCATED(InitInputData%rLocal)) THEN + DEALLOCATE(InitInputData%rLocal) +ENDIF + END SUBROUTINE FVW_DestroyInitInput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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%FVWFileName) ! FVWFileName + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! WingsMesh allocated yes/no + IF ( ALLOCATED(InData%WingsMesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WingsMesh upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%WingsMesh,1), UBOUND(InData%WingsMesh,1) + Int_BufSz = Int_BufSz + 3 ! WingsMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! WingsMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WingsMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WingsMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WingsMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! AFindx allocated yes/no + IF ( ALLOCATED(InData%AFindx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFindx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AFindx) ! AFindx + END IF + Int_BufSz = Int_BufSz + 1 ! Chord allocated yes/no + IF ( ALLOCATED(InData%Chord) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Chord) ! Chord + END IF + Int_BufSz = Int_BufSz + 1 ! RElm allocated yes/no + IF ( ALLOCATED(InData%RElm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RElm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RElm) ! RElm + END IF + Int_BufSz = Int_BufSz + 1 ! zHub allocated yes/no + IF ( ALLOCATED(InData%zHub) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zHub upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zHub) ! zHub + END IF + Int_BufSz = Int_BufSz + 1 ! zLocal allocated yes/no + IF ( ALLOCATED(InData%zLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! zLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zLocal) ! zLocal + END IF + Int_BufSz = Int_BufSz + 1 ! zTip allocated yes/no + IF ( ALLOCATED(InData%zTip) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zTip upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zTip) ! zTip + END IF + Int_BufSz = Int_BufSz + 1 ! rLocal allocated yes/no + IF ( ALLOCATED(InData%rLocal) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rLocal upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rLocal) ! rLocal + END IF + Int_BufSz = Int_BufSz + 1 ! NumBlades + Int_BufSz = Int_BufSz + 1 ! NumBladeNodes + Db_BufSz = Db_BufSz + 1 ! DTaero + Re_BufSz = Re_BufSz + 1 ! KinVisc + Int_BufSz = Int_BufSz + 1 ! UAMod + Int_BufSz = Int_BufSz + 1 ! UA_Flag + Int_BufSz = Int_BufSz + 1 ! Flookup + Re_BufSz = Re_BufSz + 1 ! a_s + 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%FVWFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%FVWFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%WingsMesh) ) 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%WingsMesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WingsMesh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WingsMesh,1), UBOUND(InData%WingsMesh,1) + CALL MeshPack( InData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! WingsMesh + 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%AFindx) ) 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%AFindx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFindx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFindx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFindx,2), UBOUND(InData%AFindx,2) + DO i1 = LBOUND(InData%AFindx,1), UBOUND(InData%AFindx,1) + IntKiBuf(Int_Xferred) = InData%AFindx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Chord) ) 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%Chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Chord,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Chord,2), UBOUND(InData%Chord,2) + DO i1 = LBOUND(InData%Chord,1), UBOUND(InData%Chord,1) + ReKiBuf(Re_Xferred) = InData%Chord(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RElm) ) 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%RElm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RElm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RElm,1), UBOUND(InData%RElm,1) + ReKiBuf(Re_Xferred) = InData%RElm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zHub) ) 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%zHub,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zHub,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zHub,1), UBOUND(InData%zHub,1) + ReKiBuf(Re_Xferred) = InData%zHub(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zLocal) ) 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%zLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%zLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%zLocal,2), UBOUND(InData%zLocal,2) + DO i1 = LBOUND(InData%zLocal,1), UBOUND(InData%zLocal,1) + ReKiBuf(Re_Xferred) = InData%zLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%zTip) ) 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%zTip,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zTip,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zTip,1), UBOUND(InData%zTip,1) + ReKiBuf(Re_Xferred) = InData%zTip(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rLocal) ) 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%rLocal,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rLocal,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rLocal,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rLocal,2), UBOUND(InData%rLocal,2) + DO i1 = LBOUND(InData%rLocal,1), UBOUND(InData%rLocal,1) + ReKiBuf(Re_Xferred) = InData%rLocal(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBladeNodes + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTaero + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UAMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UA_Flag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Flookup, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%a_s + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FVW_PackInitInput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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%FVWFileName) + OutData%FVWFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WingsMesh 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%WingsMesh)) DEALLOCATE(OutData%WingsMesh) + ALLOCATE(OutData%WingsMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WingsMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WingsMesh,1), UBOUND(OutData%WingsMesh,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 MeshUnpack( OutData%WingsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! WingsMesh + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFindx 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%AFindx)) DEALLOCATE(OutData%AFindx) + ALLOCATE(OutData%AFindx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFindx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFindx,2), UBOUND(OutData%AFindx,2) + DO i1 = LBOUND(OutData%AFindx,1), UBOUND(OutData%AFindx,1) + OutData%AFindx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Chord 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%Chord)) DEALLOCATE(OutData%Chord) + ALLOCATE(OutData%Chord(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Chord,2), UBOUND(OutData%Chord,2) + DO i1 = LBOUND(OutData%Chord,1), UBOUND(OutData%Chord,1) + OutData%Chord(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RElm 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%RElm)) DEALLOCATE(OutData%RElm) + ALLOCATE(OutData%RElm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RElm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RElm,1), UBOUND(OutData%RElm,1) + OutData%RElm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zHub 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%zHub)) DEALLOCATE(OutData%zHub) + ALLOCATE(OutData%zHub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zHub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%zHub,1), UBOUND(OutData%zHub,1) + OutData%zHub(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zLocal 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%zLocal)) DEALLOCATE(OutData%zLocal) + ALLOCATE(OutData%zLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%zLocal,2), UBOUND(OutData%zLocal,2) + DO i1 = LBOUND(OutData%zLocal,1), UBOUND(OutData%zLocal,1) + OutData%zLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zTip 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%zTip)) DEALLOCATE(OutData%zTip) + ALLOCATE(OutData%zTip(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zTip.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%zTip,1), UBOUND(OutData%zTip,1) + OutData%zTip(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rLocal 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%rLocal)) DEALLOCATE(OutData%rLocal) + ALLOCATE(OutData%rLocal(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rLocal.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rLocal,2), UBOUND(OutData%rLocal,2) + DO i1 = LBOUND(OutData%rLocal,1), UBOUND(OutData%rLocal,1) + OutData%rLocal(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%NumBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumBladeNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DTaero = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UAMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UA_Flag = TRANSFER(IntKiBuf(Int_Xferred), OutData%UA_Flag) + Int_Xferred = Int_Xferred + 1 + OutData%Flookup = TRANSFER(IntKiBuf(Int_Xferred), OutData%Flookup) + Int_Xferred = Int_Xferred + 1 + OutData%a_s = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FVW_UnPackInitInput + + SUBROUTINE FVW_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(FVW_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'FVW_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%CirculationMethod = SrcInputFileData%CirculationMethod + DstInputFileData%CirculationFile = SrcInputFileData%CirculationFile + DstInputFileData%CircSolvMaxIter = SrcInputFileData%CircSolvMaxIter + DstInputFileData%CircSolvConvCrit = SrcInputFileData%CircSolvConvCrit + DstInputFileData%CircSolvRelaxation = SrcInputFileData%CircSolvRelaxation + DstInputFileData%IntMethod = SrcInputFileData%IntMethod + DstInputFileData%FreeWake = SrcInputFileData%FreeWake + DstInputFileData%FreeWakeStart = SrcInputFileData%FreeWakeStart + DstInputFileData%FullCirculationStart = SrcInputFileData%FullCirculationStart + DstInputFileData%DTfvw = SrcInputFileData%DTfvw + DstInputFileData%CircSolvPolar = SrcInputFileData%CircSolvPolar + DstInputFileData%nNWPanels = SrcInputFileData%nNWPanels + DstInputFileData%nFWPanels = SrcInputFileData%nFWPanels + DstInputFileData%nFWPanelsFree = SrcInputFileData%nFWPanelsFree + DstInputFileData%FWShedVorticity = SrcInputFileData%FWShedVorticity + DstInputFileData%DiffusionMethod = SrcInputFileData%DiffusionMethod + DstInputFileData%CoreSpreadEddyVisc = SrcInputFileData%CoreSpreadEddyVisc + DstInputFileData%RegDeterMethod = SrcInputFileData%RegDeterMethod + DstInputFileData%RegFunction = SrcInputFileData%RegFunction + DstInputFileData%WakeRegMethod = SrcInputFileData%WakeRegMethod + DstInputFileData%WakeRegParam = SrcInputFileData%WakeRegParam + DstInputFileData%WingRegParam = SrcInputFileData%WingRegParam + DstInputFileData%ShearModel = SrcInputFileData%ShearModel + DstInputFileData%TwrShadowOnWake = SrcInputFileData%TwrShadowOnWake + DstInputFileData%VelocityMethod = SrcInputFileData%VelocityMethod + DstInputFileData%TreeBranchFactor = SrcInputFileData%TreeBranchFactor + DstInputFileData%PartPerSegment = SrcInputFileData%PartPerSegment + DstInputFileData%WrVTK = SrcInputFileData%WrVTK + DstInputFileData%VTKBlades = SrcInputFileData%VTKBlades + DstInputFileData%DTvtk = SrcInputFileData%DTvtk + DstInputFileData%VTKCoord = SrcInputFileData%VTKCoord + END SUBROUTINE FVW_CopyInputFile + + SUBROUTINE FVW_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(FVW_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FVW_DestroyInputFile + + SUBROUTINE FVW_PackInputFile( 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(FVW_InputFile), 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 = 'FVW_PackInputFile' + ! 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 ! CirculationMethod + Int_BufSz = Int_BufSz + 1*LEN(InData%CirculationFile) ! CirculationFile + Int_BufSz = Int_BufSz + 1 ! CircSolvMaxIter + Re_BufSz = Re_BufSz + 1 ! CircSolvConvCrit + Re_BufSz = Re_BufSz + 1 ! CircSolvRelaxation + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! FreeWake + Re_BufSz = Re_BufSz + 1 ! FreeWakeStart + Re_BufSz = Re_BufSz + 1 ! FullCirculationStart + Db_BufSz = Db_BufSz + 1 ! DTfvw + Int_BufSz = Int_BufSz + 1 ! CircSolvPolar + Int_BufSz = Int_BufSz + 1 ! nNWPanels + Int_BufSz = Int_BufSz + 1 ! nFWPanels + Int_BufSz = Int_BufSz + 1 ! nFWPanelsFree + Int_BufSz = Int_BufSz + 1 ! FWShedVorticity + Int_BufSz = Int_BufSz + 1 ! DiffusionMethod + Re_BufSz = Re_BufSz + 1 ! CoreSpreadEddyVisc + Int_BufSz = Int_BufSz + 1 ! RegDeterMethod + Int_BufSz = Int_BufSz + 1 ! RegFunction + Int_BufSz = Int_BufSz + 1 ! WakeRegMethod + Re_BufSz = Re_BufSz + 1 ! WakeRegParam + Re_BufSz = Re_BufSz + 1 ! WingRegParam + Int_BufSz = Int_BufSz + 1 ! ShearModel + Int_BufSz = Int_BufSz + 1 ! TwrShadowOnWake + Int_BufSz = Int_BufSz + 1 ! VelocityMethod + Re_BufSz = Re_BufSz + 1 ! TreeBranchFactor + Int_BufSz = Int_BufSz + 1 ! PartPerSegment + Int_BufSz = Int_BufSz + 1 ! WrVTK + Int_BufSz = Int_BufSz + 1 ! VTKBlades + Db_BufSz = Db_BufSz + 1 ! DTvtk + Int_BufSz = Int_BufSz + 1 ! VTKCoord + 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%CirculationMethod + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%CirculationFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%CirculationFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%CircSolvMaxIter + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CircSolvConvCrit + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CircSolvRelaxation + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FreeWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FreeWakeStart + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FullCirculationStart + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTfvw + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CircSolvPolar + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNWPanels + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nFWPanels + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nFWPanelsFree + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FWShedVorticity, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DiffusionMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CoreSpreadEddyVisc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RegDeterMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RegFunction + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WakeRegMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WakeRegParam + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WingRegParam + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ShearModel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrShadowOnWake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VelocityMethod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TreeBranchFactor + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PartPerSegment + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WrVTK + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKBlades + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTvtk + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKCoord + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FVW_PackInputFile + + SUBROUTINE FVW_UnPackInputFile( 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(FVW_InputFile), 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 = 'FVW_UnPackInputFile' + ! 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%CirculationMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%CirculationFile) + OutData%CirculationFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CircSolvMaxIter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CircSolvConvCrit = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CircSolvRelaxation = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FreeWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%FreeWake) + Int_Xferred = Int_Xferred + 1 + OutData%FreeWakeStart = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FullCirculationStart = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DTfvw = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%CircSolvPolar = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNWPanels = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nFWPanels = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nFWPanelsFree = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FWShedVorticity = TRANSFER(IntKiBuf(Int_Xferred), OutData%FWShedVorticity) + Int_Xferred = Int_Xferred + 1 + OutData%DiffusionMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CoreSpreadEddyVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RegDeterMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RegFunction = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WakeRegMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WakeRegParam = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WingRegParam = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShearModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrShadowOnWake = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrShadowOnWake) + Int_Xferred = Int_Xferred + 1 + OutData%VelocityMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TreeBranchFactor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PartPerSegment = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WrVTK = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DTvtk = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%VTKCoord = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FVW_UnPackInputFile + + SUBROUTINE FVW_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FVW_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(FVW_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 = 'FVW_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%Null = SrcInitOutputData%Null + END SUBROUTINE FVW_CopyInitOutput + + SUBROUTINE FVW_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(FVW_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FVW_DestroyInitOutput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 + Int_BufSz = Int_BufSz + 1 ! Null + 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%Null + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FVW_PackInitOutput + + SUBROUTINE FVW_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(FVW_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 = 'FVW_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 + OutData%Null = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FVW_UnPackInitOutput + + + SUBROUTINE FVW_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(FVW_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(FVW_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL FVW_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL FVW_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL FVW_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE FVW_Input_ExtrapInterp + + + SUBROUTINE FVW_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(FVW_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(FVW_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(FVW_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%WingsMesh) .AND. ALLOCATED(u1%WingsMesh)) THEN + DO i1 = LBOUND(u_out%WingsMesh,1),UBOUND(u_out%WingsMesh,1) + CALL MeshExtrapInterp1(u1%WingsMesh(i1), u2%WingsMesh(i1), tin, u_out%WingsMesh(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%V_wind) .AND. ALLOCATED(u1%V_wind)) THEN + DO i2 = LBOUND(u_out%V_wind,2),UBOUND(u_out%V_wind,2) + DO i1 = LBOUND(u_out%V_wind,1),UBOUND(u_out%V_wind,1) + b = -(u1%V_wind(i1,i2) - u2%V_wind(i1,i2)) + u_out%V_wind(i1,i2) = u1%V_wind(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + DO i2 = LBOUND(u_out%HubOrientation,2),UBOUND(u_out%HubOrientation,2) + DO i1 = LBOUND(u_out%HubOrientation,1),UBOUND(u_out%HubOrientation,1) + b = -(u1%HubOrientation(i1,i2) - u2%HubOrientation(i1,i2)) + u_out%HubOrientation(i1,i2) = u1%HubOrientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%HubPosition,1),UBOUND(u_out%HubPosition,1) + b = -(u1%HubPosition(i1) - u2%HubPosition(i1)) + u_out%HubPosition(i1) = u1%HubPosition(i1) + b * ScaleFactor + END DO + END SUBROUTINE FVW_Input_ExtrapInterp1 + + + SUBROUTINE FVW_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(FVW_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(FVW_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(FVW_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(FVW_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%WingsMesh) .AND. ALLOCATED(u1%WingsMesh)) THEN + DO i1 = LBOUND(u_out%WingsMesh,1),UBOUND(u_out%WingsMesh,1) + CALL MeshExtrapInterp2(u1%WingsMesh(i1), u2%WingsMesh(i1), u3%WingsMesh(i1), tin, u_out%WingsMesh(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated +IF (ALLOCATED(u_out%V_wind) .AND. ALLOCATED(u1%V_wind)) THEN + DO i2 = LBOUND(u_out%V_wind,2),UBOUND(u_out%V_wind,2) + DO i1 = LBOUND(u_out%V_wind,1),UBOUND(u_out%V_wind,1) + b = (t(3)**2*(u1%V_wind(i1,i2) - u2%V_wind(i1,i2)) + t(2)**2*(-u1%V_wind(i1,i2) + u3%V_wind(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%V_wind(i1,i2) + t(3)*u2%V_wind(i1,i2) - t(2)*u3%V_wind(i1,i2) ) * scaleFactor + u_out%V_wind(i1,i2) = u1%V_wind(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + DO i2 = LBOUND(u_out%HubOrientation,2),UBOUND(u_out%HubOrientation,2) + DO i1 = LBOUND(u_out%HubOrientation,1),UBOUND(u_out%HubOrientation,1) + b = (t(3)**2*(u1%HubOrientation(i1,i2) - u2%HubOrientation(i1,i2)) + t(2)**2*(-u1%HubOrientation(i1,i2) + u3%HubOrientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%HubOrientation(i1,i2) + t(3)*u2%HubOrientation(i1,i2) - t(2)*u3%HubOrientation(i1,i2) ) * scaleFactor + u_out%HubOrientation(i1,i2) = u1%HubOrientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%HubPosition,1),UBOUND(u_out%HubPosition,1) + b = (t(3)**2*(u1%HubPosition(i1) - u2%HubPosition(i1)) + t(2)**2*(-u1%HubPosition(i1) + u3%HubPosition(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%HubPosition(i1) + t(3)*u2%HubPosition(i1) - t(2)*u3%HubPosition(i1) ) * scaleFactor + u_out%HubPosition(i1) = u1%HubPosition(i1) + b + c * t_out + END DO + END SUBROUTINE FVW_Input_ExtrapInterp2 + + + SUBROUTINE FVW_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(FVW_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(FVW_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL FVW_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL FVW_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL FVW_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE FVW_Output_ExtrapInterp + + + SUBROUTINE FVW_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(FVW_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(FVW_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(FVW_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%Vind) .AND. ALLOCATED(y1%Vind)) THEN + DO i3 = LBOUND(y_out%Vind,3),UBOUND(y_out%Vind,3) + DO i2 = LBOUND(y_out%Vind,2),UBOUND(y_out%Vind,2) + DO i1 = LBOUND(y_out%Vind,1),UBOUND(y_out%Vind,1) + b = -(y1%Vind(i1,i2,i3) - y2%Vind(i1,i2,i3)) + y_out%Vind(i1,i2,i3) = y1%Vind(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cl_KJ) .AND. ALLOCATED(y1%Cl_KJ)) THEN + DO i2 = LBOUND(y_out%Cl_KJ,2),UBOUND(y_out%Cl_KJ,2) + DO i1 = LBOUND(y_out%Cl_KJ,1),UBOUND(y_out%Cl_KJ,1) + b = -(y1%Cl_KJ(i1,i2) - y2%Cl_KJ(i1,i2)) + y_out%Cl_KJ(i1,i2) = y1%Cl_KJ(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + END SUBROUTINE FVW_Output_ExtrapInterp1 + + + SUBROUTINE FVW_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(FVW_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(FVW_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(FVW_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(FVW_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FVW_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%Vind) .AND. ALLOCATED(y1%Vind)) THEN + DO i3 = LBOUND(y_out%Vind,3),UBOUND(y_out%Vind,3) + DO i2 = LBOUND(y_out%Vind,2),UBOUND(y_out%Vind,2) + DO i1 = LBOUND(y_out%Vind,1),UBOUND(y_out%Vind,1) + b = (t(3)**2*(y1%Vind(i1,i2,i3) - y2%Vind(i1,i2,i3)) + t(2)**2*(-y1%Vind(i1,i2,i3) + y3%Vind(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%Vind(i1,i2,i3) + t(3)*y2%Vind(i1,i2,i3) - t(2)*y3%Vind(i1,i2,i3) ) * scaleFactor + y_out%Vind(i1,i2,i3) = y1%Vind(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Cl_KJ) .AND. ALLOCATED(y1%Cl_KJ)) THEN + DO i2 = LBOUND(y_out%Cl_KJ,2),UBOUND(y_out%Cl_KJ,2) + DO i1 = LBOUND(y_out%Cl_KJ,1),UBOUND(y_out%Cl_KJ,1) + b = (t(3)**2*(y1%Cl_KJ(i1,i2) - y2%Cl_KJ(i1,i2)) + t(2)**2*(-y1%Cl_KJ(i1,i2) + y3%Cl_KJ(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%Cl_KJ(i1,i2) + t(3)*y2%Cl_KJ(i1,i2) - t(2)*y3%Cl_KJ(i1,i2) ) * scaleFactor + y_out%Cl_KJ(i1,i2) = y1%Cl_KJ(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + END SUBROUTINE FVW_Output_ExtrapInterp2 + +END MODULE FVW_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/FVW_VTK.f90 b/OpenFAST/modules/aerodyn/src/FVW_VTK.f90 new file mode 100644 index 000000000..8770d43b8 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_VTK.f90 @@ -0,0 +1,565 @@ +module FVW_VTK + !use PrecisionMod, only: ReKi + use NWTC_Library, only: ReKi, GetNewUnit + implicit none +! character(8), parameter :: RFMT='F14.5' + !character(8), parameter :: RFMT='E24.15E3' + character(8), parameter :: RFMT='E17.8E3' + character(8), parameter :: IFMT='I7' + + TYPE, PUBLIC :: FVW_VTK_Misc + integer :: vtk_unit + logical :: bFileOpen=.false. + + integer :: nData=0; + integer :: nPoints=0; + + logical :: bBinary = .false. + character(len=255) :: buffer + + ! Reference Frame + real(ReKi),dimension(3,3) :: T_g2b + real(ReKi),dimension(3) :: PO_g + END TYPE FVW_VTK_Misc + + character(1), parameter :: NL = char(10) ! New Line character + + interface vtk_dataset_structured_grid; module procedure & + vtk_dataset_structured_grid_flat, & + vtk_dataset_structured_grid_grid + end interface + + interface vtk_point_data_vector; module procedure & + vtk_point_data_vector_flat, & + vtk_point_data_vector_grid2D,& + vtk_point_data_vector_grid + end interface + interface vtk_point_data_scalar; module procedure & + vtk_point_data_scalar_flat, & + vtk_point_data_scalar_grid2D, & + vtk_point_data_scalar_grid + end interface + interface vtk_cell_data_scalar; module procedure & + vtk_cell_data_scalar_1d,& + vtk_cell_data_scalar_2d + end interface + + public + +contains + + subroutine vtk_misc_init(mvtk) + type(FVW_VTK_Misc),intent(inout) :: mvtk + mvtk%vtk_unit = -1 !< VTK output unit [-] + mvtk%bFileOpen = .false. !< binary file is open [-] + mvtk%bBinary = .false. !< write binary files [-] + mvtk%nData = 0 !< number of data lines [-] + mvtk%nPoints = 0 !< number of points [-] + end subroutine + + !> + subroutine set_vtk_binary_format(bBin,mvtk) + logical, intent(in)::bBin + type(FVW_VTK_Misc),intent(inout) :: mvtk + mvtk%bBinary=bBin + end subroutine + + + !> Save a coordinate transform + ! ALL VTK Will be exported in this coordinate system! + subroutine set_vtk_coordinate_transform(T_g2b_in,PO_g_in,mvtk) + real(ReKi),dimension(3,3), intent(in) :: T_g2b_in + real(ReKi),dimension(3) , intent(in) :: PO_g_in + type(FVW_VTK_Misc),intent(inout) :: mvtk + mvtk%T_g2b=T_g2b_in + mvtk%PO_g=PO_g_in + end subroutine + + logical function vtk_new_ascii_file(filename,label,mvtk) + !use MainIO, only: get_free_unit ,check_io + !use MainIOData, only: bSTOP_ALLOWED + !use FileSystem, only: file_exists + !use Logging, only: log_warning,log_error,log_info + ! + character(len=*),intent(in) :: filename + character(len=*),intent(in) :: label + type(FVW_VTK_Misc),intent(inout) :: mvtk + ! + integer :: iostatvar + logical :: b + + if (.not. mvtk%bFileOpen) then + CALL GetNewUnit( mvtk%vtk_unit ) + if (mvtk%bBinary) then + ! Fortran 2003 stream, otherwise intel fortran ! + !form='UNFORMATTED',access='SEQUENTIAL',action='WRITE',convert='BIG_ENDIAN',recordtype='STREAM',buffered='YES', + !print*,'Not available for this compiler' !COMPAQ-COMPILER + !STOP !COMPAQ-COMPILER + open(unit = mvtk%vtk_unit,file= trim(adjustl(filename)),form='UNFORMATTED',access = 'stream',& !OTHER-COMPILER + action = 'WRITE',convert= 'BIG_ENDIAN',iostat=iostatvar,status='replace') !OTHER-COMPILER + else + open(mvtk%vtk_unit,file=trim(adjustl(filename)),iostat=iostatvar,action="write",status='replace') + endif + if (iostatvar == 0) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'# vtk DataFile Version 3.0'//NL + write(mvtk%vtk_unit)trim(label)//NL + write(mvtk%vtk_unit)'BINARY'//NL + else + write(mvtk%vtk_unit,'(a)') '# vtk DataFile Version 2.0' + write(mvtk%vtk_unit,'(a)') label + write(mvtk%vtk_unit,'(a)') 'ASCII' + write(mvtk%vtk_unit,'(a)') ' ' + endif + + mvtk%bFileOpen=.true. + mvtk%nData=-1; + endif + else + b=.false. + !call log_error('VTK: Cannot open two vtk files at the same time, call vtk_close first') + endif + if (iostatvar ==0) then + vtk_new_ascii_file=.true. + else + vtk_new_ascii_file=.false. + endif + end function + + subroutine vtk_close_file(mvtk) + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + close(mvtk%vtk_unit) + mvtk%bFileOpen=.false. + endif + endsubroutine + + + ! ------------------------------------------------------------------------- + ! --- POLYDATA STUFF + ! ------------------------------------------------------------------------- + subroutine vtk_dataset_polydata(Points,mvtk,bladeFrame) + real(ReKi), dimension(:,:),intent(in) :: Points !< 3 x n + type(FVW_VTK_Misc),intent(inout) :: mvtk + logical, intent(in) :: bladeFrame + integer :: i + if ( mvtk%bFileOpen ) then + mvtk%nPoints=size(Points,2) + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'DATASET POLYDATA'//NL + write(mvtk%buffer,'(A,I0,A)') 'POINTS ', mvtk%nPoints ,' double' + write(mvtk%vtk_unit)trim(mvtk%buffer)//NL + if (bladeFrame) then + do i=1,mvtk%nPoints + write(mvtk%vtk_unit)matmul(mvtk%T_g2b,Points(1:3,i)-mvtk%PO_g) + enddo + else + do i=1,mvtk%nPoints + write(mvtk%vtk_unit)Points(1:3,i) + enddo + endif + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A)') 'DATASET POLYDATA' + write(mvtk%vtk_unit,'(A,I0,A)') 'POINTS ', mvtk%nPoints ,' double' + if (bladeFrame) then + do i=1,mvtk%nPoints + write(mvtk%vtk_unit,'(3'//RFMT//')') matmul(mvtk%T_g2b,Points(1:3,i)-mvtk%PO_g) + enddo + else + do i=1,mvtk%nPoints + write(mvtk%vtk_unit,'(3'//RFMT//')') Points(1:3,i) + enddo + endif + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + + subroutine vtk_lines(L,mvtk) + integer, dimension(:,:),intent(in) :: L !< 2 x n + type(FVW_VTK_Misc),intent(inout) :: mvtk + + integer :: i + + if ( mvtk%bFileOpen ) then + mvtk%nData=size(L,2) + if (mvtk%bBinary) then + write(mvtk%buffer,'(A,I0,A,I0)')'LINES ',mvtk%nData,' ',3*mvtk%nData + write(mvtk%vtk_unit)trim(mvtk%buffer)//NL + do i=1,mvtk%nData + write(mvtk%vtk_unit)2,L(1:2,i) + enddo + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,I0,A,I0)')'LINES ',mvtk%nData,' ',3*mvtk%nData + do i=1,mvtk%nData + write(mvtk%vtk_unit,'(3'//IFMT//')') 2, L(1:2,i) + enddo + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + subroutine vtk_quad(Q,mvtk) + integer, dimension(:,:),intent(in) :: Q !< 4 x n + type(FVW_VTK_Misc),intent(inout) :: mvtk + integer :: i + if ( mvtk%bFileOpen ) then + mvtk%nData=size(Q,2) + if (mvtk%bBinary) then + write(mvtk%buffer,'(A,I0,A,I0)')'POLYGONS ',mvtk%nData,' ',5*mvtk%nData + write(mvtk%vtk_unit)trim(mvtk%buffer)//NL + do i=1,mvtk%nData + write(mvtk%vtk_unit)4,Q(1:4,i) + enddo + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,I0,A,I0)') 'POLYGONS ', mvtk%nData,' ',5*mvtk%nData + do i=1,mvtk%nData + write(mvtk%vtk_unit,'(5'//IFMT//')') 4, Q(1:4,i) + enddo + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + ! ------------------------------------------------------------------------- + ! --- RECTILINEAR + ! ------------------------------------------------------------------------- + subroutine vtk_dataset_rectilinear(v1,v2,v3,mvtk) + real(ReKi), dimension(:),intent(in) :: v1,v2,v3 !< n + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + mvtk%nPoints=size(v1)*size(v2)*size(v3) + if (mvtk%bBinary) then + write(mvtk%vtk_unit) 'DATASET RECTILINEAR_GRID'//NL + write(mvtk%buffer,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', size(v1),' ',size(v2),' ',size(v3) + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%buffer,'(A,I0,A)') 'X_COORDINATES ', size(v1), ' double' + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%vtk_unit)v1 + write(mvtk%vtk_unit)NL + write(mvtk%buffer,'(A,I0,A)') 'Y_COORDINATES ', size(v2), ' double' + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%vtk_unit)v2 + write(mvtk%vtk_unit)NL + write(mvtk%buffer,'(A,I0,A)') 'Z_COORDINATES ', size(v3), ' double' + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%vtk_unit)v3 + !write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A)') 'DATASET RECTILINEAR_GRID' + write(mvtk%vtk_unit,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', size(v1),' ',size(v2),' ',size(v3) + write(mvtk%vtk_unit,'(A,I0,A)') 'X_COORDINATES ', size(v1), ' double' + write(mvtk%vtk_unit,'('//RFMT//')') v1 + write(mvtk%vtk_unit,'(A,I0,A)') 'Y_COORDINATES ', size(v2), ' double' + write(mvtk%vtk_unit,'('//RFMT//')') v2 + write(mvtk%vtk_unit,'(A,I0,A)') 'Z_COORDINATES ', size(v3), ' double' + write(mvtk%vtk_unit,'('//RFMT//')') v3 + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + ! ------------------------------------------------------------------------- + ! --- STRUCTURED GRID (Points dumped without for loop since memory is in proper order) + ! ------------------------------------------------------------------------- + !> Subroutine using flat data as input (not in natural order) + subroutine vtk_dataset_structured_grid_flat(D,n1,n2,n3,mvtk) + integer , intent(in) :: n1,n2,n3 + real(ReKi), dimension(:,:),intent(in)::D + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + mvtk%nPoints=n1*n2*n3 + if (mvtk%bBinary) then + write(mvtk%vtk_unit) 'DATASET STRUCTURED_GRID'//NL + write(mvtk%buffer,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', n1,' ',n2,' ',n3 + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%buffer,'(A,I0,A)') 'POINTS ', mvtk%nPoints, ' double' + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A)') 'DATASET STRUCTURED_GRID' + write(mvtk%vtk_unit,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', n1,' ',n2,' ',n3 + write(mvtk%vtk_unit,'(A,I0,A)') 'POINTS ', mvtk%nPoints, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + !> Using Grid data 4d as input + subroutine vtk_dataset_structured_grid_grid(D,n1,n2,n3,mvtk) + integer , intent(in) :: n1,n2,n3 + real(ReKi), dimension(:,:,:,:),intent(in)::D + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + mvtk%nPoints=n1*n2*n3 + if (mvtk%bBinary) then + write(mvtk%vtk_unit) 'DATASET STRUCTURED_GRID'//NL + write(mvtk%buffer,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', n1,' ',n2,' ',n3 + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%buffer,'(A,I0,A)') 'POINTS ', mvtk%nPoints, ' double' + write(mvtk%vtk_unit) trim(mvtk%buffer)//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A)') 'DATASET STRUCTURED_GRID' + write(mvtk%vtk_unit,'(A,I0,A,I0,A,I0)') 'DIMENSIONS ', n1,' ',n2,' ',n3 + write(mvtk%vtk_unit,'(A,I0,A)') 'POINTS ', mvtk%nPoints, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + write(mvtk%vtk_unit,*) ' ' + endif + endif + end subroutine + + + + ! ------------------------------------------------------------------------- + ! --- POINT DATA + ! ------------------------------------------------------------------------- + subroutine vtk_point_data_init(mvtk) + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if(mvtk%bBinary) then + write(mvtk%buffer,'(A,I0)')'POINT_DATA ',mvtk%nPoints + write(mvtk%vtk_unit)trim(mvtk%buffer)//NL + else + write(mvtk%vtk_unit,'(A,I0)') 'POINT_DATA ', mvtk%nPoints + endif + endif + end subroutine + + subroutine vtk_point_data_scalar_flat(D,sname,mvtk) + real(ReKi), dimension(:),intent(in)::D + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'SCALARS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)'LOOKUP_TABLE default'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'SCALARS ', sname, ' double' + write(mvtk%vtk_unit,'(A)') 'LOOKUP_TABLE default' + write(mvtk%vtk_unit,'(1'//RFMT//')')D + endif + endif + end subroutine + + subroutine vtk_point_data_scalar_grid(D,sname,mvtk) + real(ReKi), dimension(:,:,:,:),intent(in)::D + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'SCALARS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)'LOOKUP_TABLE default'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'SCALARS ', sname, ' double' + write(mvtk%vtk_unit,'(A)') 'LOOKUP_TABLE default' + write(mvtk%vtk_unit,'(1'//RFMT//')')D + endif + endif + end subroutine + + subroutine vtk_point_data_scalar_grid2D(D,sname,mvtk) + real(ReKi), dimension(:,:,:),intent(in)::D + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'SCALARS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)'LOOKUP_TABLE default'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'SCALARS ', sname, ' double' + write(mvtk%vtk_unit,'(A)') 'LOOKUP_TABLE default' + write(mvtk%vtk_unit,'(1'//RFMT//')')D + endif + endif + end subroutine + + !> + subroutine vtk_point_data_vector_flat(D,sname,mvtk) + real(ReKi), dimension(:,:),intent(in) :: D !< 3 x n + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'VECTORS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'VECTORS ', sname, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + endif + endif + end subroutine + !> + subroutine vtk_point_data_vector_grid(D,sname,mvtk) + real(ReKi), dimension(:,:,:,:),intent(in) :: D !< 3 x n + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'VECTORS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'VECTORS ', sname, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + endif + endif + end subroutine + !> + subroutine vtk_point_data_vector_grid2D(D,sname,mvtk) + real(ReKi), dimension(:,:,:),intent(in) :: D !< + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'VECTORS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'VECTORS ', sname, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + endif + endif + end subroutine + + + ! ------------------------------------------------------------------------- + ! --- CELL DATA + ! ------------------------------------------------------------------------- + subroutine vtk_cell_data_init(mvtk) + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%buffer,'(A,I0)')'CELL_DATA ',mvtk%nData + write(mvtk%vtk_unit)trim(mvtk%buffer)//NL + else + write(mvtk%vtk_unit,'(A,I0)') 'CELL_DATA ', mvtk%nData + endif + endif + end subroutine + + subroutine vtk_cell_data_scalar_1d(D,sname,mvtk) + real(ReKi), dimension(:),intent(in)::D + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'SCALARS '//trim(sname)//' double 1'//NL + write(mvtk%vtk_unit)'LOOKUP_TABLE default'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,fmt='(A,A,A)') 'SCALARS ', sname, ' double' + write(mvtk%vtk_unit,'(A)') 'LOOKUP_TABLE default' + write(mvtk%vtk_unit,'(1'//RFMT//')')D + endif + endif + end subroutine + + subroutine vtk_cell_data_scalar_2d(D,sname,mvtk) + real(ReKi), dimension(:,:),intent(in)::D + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'SCALARS '//trim(sname)//' double 1'//NL + write(mvtk%vtk_unit)'LOOKUP_TABLE default'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,fmt='(A,A,A)') 'SCALARS ', sname, ' double' + write(mvtk%vtk_unit,'(A)') 'LOOKUP_TABLE default' + write(mvtk%vtk_unit,'(1'//RFMT//')')D + endif + endif + end subroutine + + + subroutine vtk_cell_data_vector(D,sname,mvtk) + real(ReKi), dimension(:,:),intent(in) :: D !< 3 x n + character(len=*),intent(in) ::sname + type(FVW_VTK_Misc),intent(inout) :: mvtk + if ( mvtk%bFileOpen ) then + if (mvtk%bBinary) then + write(mvtk%vtk_unit)'VECTORS '//trim(sname)//' double'//NL + write(mvtk%vtk_unit)D + write(mvtk%vtk_unit)NL + else + write(mvtk%vtk_unit,'(A,A,A)') 'VECTORS ', sname, ' double' + write(mvtk%vtk_unit,'(3'//RFMT//')')D + endif + endif + end subroutine + + ! --------------------------------------------------------------------------------} + ! --- VTK Tools + ! --------------------------------------------------------------------------------{ + !> Exports a Plane From a mesh + subroutine export_plane_grid3d(fname,v1,v2,v3,Values,mvtk) + character(len=*),intent(in) :: fname + real(ReKi),dimension(:), intent(in) :: v1,v2,v3 + real(ReKi),dimension(:,:,:,:), intent(in) :: Values + type(FVW_VTK_Misc),intent(inout) :: mvtk + ! Variables + integer :: nD + + ! Writting + if ( vtk_new_ascii_file(trim(fname),'grid',mvtk)) then + nD=size(Values,1) + call vtk_dataset_rectilinear(v1,v2,v3,mvtk) + ! Output as a structured grid, No need to reorder + call vtk_point_data_init(mvtk) + ! Could be a function of nDim, be careful + if(nD==3) then + call vtk_point_data_vector(Values(1:3,:,:,:),'Velocity',mvtk) ! Label... + endif + + call vtk_close_file(mvtk) + endif ! file opening + end subroutine + + !> Exports a Plane From a mesh + subroutine export_plane_grid2d(fname,v1,v2,v3,Values,mvtk) + character(len=*),intent(in) :: fname + real(ReKi),dimension(:), intent(in) :: v1,v2,v3 + real(ReKi),dimension(:,:,:), intent(in) :: Values + type(FVW_VTK_Misc),intent(inout) :: mvtk + ! Variables + integer :: nD + + ! Writting + if ( vtk_new_ascii_file(trim(fname),'plane',mvtk) ) then + nD=size(Values,1) + call vtk_dataset_rectilinear(v1,v2,v3,mvtk) + ! Output as a structured grid, No need to reorder + call vtk_point_data_init(mvtk) + ! Could be a function of nDim, be careful + if(nD==3) then + call vtk_point_data_vector(Values(1:3,:,:),'Velocity',mvtk) ! Label... + endif + + call vtk_close_file(mvtk) + endif ! file opening + end subroutine +end module FVW_VTK diff --git a/OpenFAST/modules/aerodyn/src/FVW_VortexTools.f90 b/OpenFAST/modules/aerodyn/src/FVW_VortexTools.f90 new file mode 100644 index 000000000..dc9778362 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_VortexTools.f90 @@ -0,0 +1,892 @@ +module FVW_VortexTools + ! Contains Typical Tools for vortex methods + + ! Should be *independent* of the Framework and any derived type + + ! Only low level functions ! + + use NWTC_LIBRARY + + implicit none + + ! Tree parameters + integer, parameter :: IK1 = selected_int_kind(1) ! to store particle branch number (from 1 to 8) + integer,parameter :: M0 = 1, M1_1=2, M1_2=3, M1_3=4, M2_11=5, M2_21=6, M2_22=7, M2_31=8, M2_32=9, M2_33=10 ! For moment coefficients + integer,parameter :: M0_000 = 1 + integer,parameter :: M1_100 = 2 + integer,parameter :: M1_010 = 3 + integer,parameter :: M1_001 = 4 + + !> + type T_Part + real(ReKi), dimension(:,:), pointer :: P =>null() + real(ReKi), dimension(:,:), pointer :: Alpha =>null() + real(ReKi), dimension(:), pointer :: RegParam =>null() + integer(IntKi) :: RegFunction =-1 + integer(IntKi) :: n =-1 + end type T_Part + + !> The node type is recursive and is used to make a chained-list of nodes for the tree + type T_Node + real(ReKi) :: radius !< Typical dimension of a cell (max of x,y,z extent) + real(ReKi),dimension(3) :: center + real(ReKi),dimension(3,10) :: Moments + integer,dimension(:),pointer :: iPart=>null() !< indexes of particles stored in this node + integer,dimension(:),pointer :: leaves=>null() ! NOTE: leaves are introduced to save memory + type(T_Node),dimension(:), pointer :: branches =>null() + integer :: nPart = -1 ! Number of particles in branches and leaves of this node + end type T_Node + + !> The type tree contains some basic data, a chained-list of nodes, and a pointer to the Particle data that were used + type T_Tree + type(T_Part) :: Part !< Storage for all particles + integer :: iStep =-1 !< Time step at which the tree was built + logical :: bGrown =.false. !< Is the tree build + type(T_Node) :: Root !< Contains the chained-list of nodes + end type T_Tree + + interface cut_tree + module procedure cut_tree_parallel ; ! to switch between parallel and rec easily + end interface + +contains + + subroutine VecToLattice(PointVectors, iDepthStart, LatticeVectors, iHeadP) + real(Reki), dimension(:,:), intent(in ) :: PointVectors !< nVal x n + integer(IntKi), intent(in ) :: iDepthStart !< Start index for depth dimension + real(ReKi), dimension(:,:,:), intent(inout) :: LatticeVectors !< nVal x nSpan x nDepth + integer(IntKi), intent(inout) :: iHeadP !< Index indicating where to start in PointVectors + integer(IntKi) :: iSpan, iDepth + do iDepth = iDepthStart, size(LatticeVectors,3) + do iSpan = 1, size(LatticeVectors,2) + LatticeVectors(:, iSpan, iDepth) = PointVectors(:, iHeadP) + iHeadP=iHeadP+1 + enddo + enddo + end subroutine + + subroutine LatticeToPoints(LatticePoints, iDepthStart, Points, iHeadP) + real(Reki), dimension(:,:,:), intent(in ) :: LatticePoints !< Points 3 x nSpan x nDepth + integer(IntKi), intent(in ) :: iDepthStart !< Start index for depth dimension + real(ReKi), dimension(:,:), intent(inout) :: Points !< + integer(IntKi), intent(inout) :: iHeadP !< Index indicating where to start in Points + ! Local + integer(IntKi) :: iSpan, iDepth + ! Points are flattened as follows: (Loop order is important) + ! + ! 3---6 + ! | | + ! 2---5 + ! | | + ! 1---4 + ! + do iDepth = iDepthStart, size(LatticePoints,3) + do iSpan = 1, size(LatticePoints,2) + Points(1:3,iHeadP) = LatticePoints(1:3, iSpan, iDepth) + iHeadP=iHeadP+1 + enddo + enddo + + endsubroutine LatticeToPoints + + subroutine LatticeToSegments(LatticePoints, LatticeGamma, iDepthStart, SegPoints, SegConnct, SegGamma, iHeadP, iHeadC, bShedVorticity, bShedLastVorticity ) + real(Reki), dimension(:,:,:), intent(in ) :: LatticePoints !< Points 3 x nSpan x nDepth + real(Reki), dimension(:,:), intent(in ) :: LatticeGamma !< GammaPanl nSpan x nDepth + integer(IntKi), intent(in ) :: iDepthStart !< Start index for depth dimension + real(ReKi), dimension(:,:), intent(inout) :: SegPoints !< + integer(IntKi), dimension(:,:), intent(inout) :: SegConnct !< + real(ReKi), dimension(:), intent(inout) :: SegGamma !< + integer(IntKi), intent(inout) :: iHeadP !< Index indicating where to start in SegPoints + integer(IntKi), intent(inout) :: iHeadC !< Index indicating where to start in SegConnct + logical , intent(in ) :: bShedVorticity !< Shed vorticity is included if true + logical , intent(in ) :: bShedLastVorticity !< Shed the last vorticity segment if true + ! Local + integer(IntKi) :: nSpan, nDepth + integer(IntKi) :: iSpan, iDepth + integer(IntKi) :: iHeadP0, iseg1, iseg2, iseg3 ,iseg4 !< Index indicating where to start in SegPoints + real(ReKi) :: Gamma12 + real(ReKi) :: Gamma41 + + nSpan = size(LatticePoints,2) + nDepth= size(LatticePoints,3) + + + iHeadP0=iHeadP ! Storing + ! --- Flattening LatticePoints into SegPoints array, and increment iHeadP + ! We will need all the points, we flatten the point array + call LatticeToPoints(LatticePoints, iDepthStart, SegPoints, iHeadP) + + ! --- Creating segments + ! Naming convention for point indices and segments of a panel: + ! 2---3 + ! | | + ! 1---4 + ! We go "Panel per panel" , for a given Panel, we create + ! - Segment 1-2 + ! - Segment 1-4 + ! - Segment 4-3 if the last Depth panel + ! - Segment 2-3 if the last Span panel + ! Circulation is defined positive as follows (clockwise): + ! 2->-3 + ! ^ v + ! 1-<-4 + do iDepth = iDepthStart, nDepth-1 + do iSpan = 1, nSpan-1 + iseg1 = iHeadP0 + (iSpan-1) +(iDepth-1-iDepthStart+1)*nSpan ! Point 1 + iseg2 = iHeadP0 + (iSpan ) +(iDepth-1-iDepthStart+1)*nSpan ! Point 2 + iseg3 = iHeadP0 + (iSpan ) +(iDepth -iDepthStart+1)*nSpan ! Point 3 + iseg4 = iHeadP0 + (iSpan-1) +(iDepth -iDepthStart+1)*nSpan ! Point 4 + if (iDepth==iDepthStart) then + Gamma12 = LatticeGamma(iSpan,iDepth) + else + Gamma12 = LatticeGamma(iSpan,iDepth)-LatticeGamma(iSpan,iDepth-1) + endif + if (iSpan==1) then + Gamma41 = LatticeGamma(iSpan,iDepth) + else + Gamma41 = LatticeGamma(iSpan,iDepth)-LatticeGamma(iSpan-1,iDepth) + endif + ! Segment 1-2 + if (bShedVorticity) then + SegConnct(1,iHeadC) = iseg1 + SegConnct(2,iHeadC) = iseg2 + SegConnct(3,iHeadC) = iDepth + SegConnct(4,iHeadC) = iSpan + SegGamma (iHeadC ) = Gamma12 + iHeadC=iHeadC+1 + endif + ! Segment 1-4 + SegConnct(1,iHeadC) = iseg1 + SegConnct(2,iHeadC) = iseg4 + SegConnct(3,iHeadC) = iDepth + SegConnct(4,iHeadC) = iSpan + SegGamma (iHeadC ) = -Gamma41 + iHeadC=iHeadC+1 + ! Segment 4-3 + if (iDepth==nDepth-1) then + if ((bShedVorticity) .and. (bShedLastVorticity)) then + SegConnct(1,iHeadC) = iseg4 + SegConnct(2,iHeadC) = iseg3 + SegConnct(3,iHeadC) = iDepth + SegConnct(4,iHeadC) = iSpan + SegGamma (iHeadC ) = - LatticeGamma(iSpan,iDepth) + iHeadC=iHeadC+1 + endif + endif + ! Segment 2-3 + if (iSpan==nSpan-1) then + SegConnct(1,iHeadC) = iseg2 + SegConnct(2,iHeadC) = iseg3 + SegConnct(3,iHeadC) = iDepth + SegConnct(4,iHeadC) = iSpan + SegGamma (iHeadC ) = LatticeGamma(iSpan,iDepth) + iHeadC=iHeadC+1 + endif + enddo + enddo + end subroutine LatticeToSegments + + !> Convert segments between index iSegStart and iSegEnd to particles. + subroutine SegmentsToPart(SegPoints, SegConnct, SegGamma, SegEpsilon, iSegStart, iSegEnd, nPartPerSeg, PartPoints, PartAlpha, PartEpsilon, iHeadPart) + real(ReKi), dimension(:,:), intent(in ) :: SegPoints !< + integer(IntKi), dimension(:,:), intent(in ) :: SegConnct !< + real(ReKi), dimension(:), intent(in ) :: SegGamma !< + real(ReKi), dimension(:), intent(in ) :: SegEpsilon !< + integer, intent(in ) :: iSegStart !< Index where to start in Seg* vectors + integer, intent(in ) :: iSegEnd !< + integer, intent(in ) :: nPartPerSeg !< Segments will be dividied into nPartPerSeg particles + real(ReKi), dimension(:,:), intent(inout) :: PartPoints !< Particle points (3 x nPart) + real(ReKi), dimension(:,:), intent(inout) :: PartAlpha !< Particle intensities (3 x nPart) + real(ReKi), dimension(:), intent(inout) :: PartEpsilon !< Particle regularization parameter (nPart) + integer, optional, intent(inout) :: iHeadPart !< Index where to start in Part* vectors + real(ReKi), dimension(3) :: P1, P2, DP !< Segment extremities + real(ReKi), dimension(3) :: SegDir !< direction vector + real(ReKi), dimension(3) :: PartInt + real(ReKi) :: PartLen !< Initial "length" of the blob + real(ReKi) :: PartEps !< Regularization of the blob + real(ReKi) :: SegLen + integer(IntKi) :: iPart !< index in particle vectors + integer(IntKi) :: iSeg, iSubPart + if (present(iHeadPart)) then + iPart = iHeadPart + else + iPart = 1 + endif + ! loop on selected segments + do iSeg=iSegStart,iSegEnd + P1 = SegPoints(1:3,SegConnct(1,iSeg)) ! Segment extremities + P2 = SegPoints(1:3,SegConnct(2,iSeg)) + DP = P2-P1 + SegLen = sqrt(DP(1)**2 + DP(2)**2 + DP(3)**2) + SegDir = DP/SegLen ! Unit vector along segment direction + PartInt = DP*SegGamma(iSeg)/nPartPerSeg ! alpha = Gamma.L/n = omega.dV [m^3/s] + PartEps = SegEpsilon(iSeg) ! TODO this might need tuning depending on RegFunction and n_new + PartLen = SegLen/nPartPerSeg + do iSubPart=0,nPartPerSeg-1 + PartPoints(1:3, iPart) = P1(1:3) + (0.5_ReKi+iSubPart)*PartLen*SegDir(1:3) ! ds/2:ds:L + PartAlpha (1:3, iPart) = PartInt(1:3) + PartEpsilon( iPart) = PartEps + iPart = iPart +1 + enddo + enddo + if (present(iHeadPart)) then + iHeadPart=iPart + endif + end subroutine SegmentsToPart + + subroutine print_mean_4d(M, Label) + real(ReKi), dimension(:,:,:,:), intent(in) :: M + character(len=*), intent(in) :: Label + integer(IntKi) :: i, j, k + real(ReKi), dimension(3) :: U + ! + U(1:3)=0 + if ((size(M,4)*size(M,3)*size(M,2) )>0) then + do i=1,size(M,4); do j=1,size(M,3); do k=1,size(M,2); + U(1:3)= U(1:3)+ M(1:3, k, j, i) + enddo; enddo; enddo; + U(1:3)=U(1:3)/ (size(M,4)*size(M,3)*size(M,2)) + endif + print'(A25,3F12.4)',trim(Label),U + end subroutine + + subroutine print_mean_3d(M, Label) + real(ReKi), dimension(:,:,:), intent(in) :: M + character(len=*), intent(in) :: Label + integer(IntKi) :: i, j + real(ReKi), dimension(3) :: U + ! + U(1:3)=0 + if ((size(M,3)*size(M,2))>0) then + do i=1,size(M,3); do j=1,size(M,2) + U(1:3)= U(1:3)+ M(1:3, j, i) + enddo; enddo; + U(1:3)=U(1:3)/ (size(M,3)*size(M,2)) + endif + print'(A24,3F12.4)',trim(Label),U + end subroutine + + !> Perform interpolation from control points to nodes assuming CP are between nodes + subroutine interpextrap_cp2node(xin, yin, xnew, ynew) + real(ReKi), intent(in ) :: xin(:) + real(ReKi), intent(in ) :: yin(:) + real(ReKi), intent(in ) :: xnew(:) + real(ReKi), intent( out) :: ynew(:) + integer(IntKi) :: n + n=size(xin) + call InterpArray(xin, yin, xnew(2:n), ynew(2:n)) + ! Boundaries + if (n>1) then ! If more than 2 panels, use extrapolation + ynew(1) = lin_extrap(xnew(1) , xin(1), yin(1), xin(2) , yin(2)) + ynew(n+1) = lin_extrap(xnew(n+1), xin(n), yin(n), xin(n-1), yin(n-1)) + else ! If one panel, duplicate the unique point on both side + ynew(1) = yin(1) + ynew(n+1) = yin(n) !n=1 + endif + contains + !> Perform linear extrapolation to get value of y(x0), using y(x1) and y(x2) + real(ReKi) function lin_extrap(x0, x1, y1, x2, y2) result(y0) + real(ReKi), intent(in) :: x0, x1, y1, x2, y2 + real(ReKi) :: a + a = (x0-x1)/(x0-x2) + y0 = 1._ReKi/(1._ReKi-a) * (y1-a*y2) + end function lin_extrap + end subroutine interpextrap_cp2node + + ! --------------------------------------------------------------------------------} + ! --- Tree -Grow + ! --------------------------------------------------------------------------------{ + subroutine grow_tree(Tree, PartP, PartAlpha, PartRegFunction, PartRegParam, iStep) + type(T_Tree), intent(inout), target :: Tree !< + real(ReKi), dimension(:,:), intent(in ), target :: PartP !< + real(ReKi), dimension(:,:), intent(in ), target :: PartAlpha !< + integer(IntKi), intent(in ) :: PartRegFunction !< + real(ReKi), dimension(:), intent(in ), target :: PartRegParam !< + integer(IntKi), intent(in ) :: iStep !< + type(T_Node), pointer :: node !< Alias + type(T_Part), pointer :: Part !< Alias + real(ReKi) :: max_x,max_y,max_z !< for domain dimension + real(ReKi) :: min_x,min_y,min_z !< for domain dimension + integer(IntKi) :: i + + ! Cutting tree if it already has content + if (associated(Tree%root%branches).or.associated(Tree%root%leaves)) then + call cut_tree_parallel(Tree) + endif + ! Linking tree particles to given part, no copy! + nullify(Tree%Part%P) + nullify(Tree%Part%Alpha) + nullify(Tree%Part%RegParam) + Tree%Part%P => PartP + Tree%Part%Alpha => PartAlpha + Tree%Part%RegParam => PartRegParam + Tree%Part%RegFunction = PartRegFunction + Tree%Part%n = size(PartP,2) + + ! --- Handle special case for root node + node => Tree%Root + Part => Tree%Part + if (Part%n==0) then + ! Do nothing + node%radius = -9999.99_ReKi + node%center = -9999.99_ReKi + node%Moments= -9999.99_ReKi + else if (Tree%Part%n==1) then + node%radius=0 + node%center(1:3)=Part%P(1:3,1) + node%Moments=0.0_ReKi + nullify(node%iPart) + nullify(node%branches) + allocate(node%leaves(1:1)) + node%leaves(1) = Part%n !< index + node%nPart = 1 + else + ! Domain dimensions + max_x=maxval(Part%P(1,1:Part%n)); max_y=maxval(Part%P(2,1:Part%n)); max_z=maxval(Part%P(3,1:Part%n)) + min_x=minval(Part%P(1,1:Part%n)); min_y=minval(Part%P(2,1:Part%n)); min_z=minval(Part%P(3,1:Part%n)) + + ! Init of trunc + ! Radius taken slightly bigger than domain extent. This radius will be divided by 2 successively + node%radius = max(abs(max_x-min_x),abs(max_y-min_y),abs(max_z-min_z))*1.001_ReKi + if(node%radius>1e6) then + print*,'[Error] Domain extent too large, particle points must be invalid'; + print*, min_x, max_x, min_y, max_y, min_z, max_z + STOP + endif + node%center = (/ (max_x+min_x)/2._ReKi, (max_y+min_y)/2._ReKi, (max_z+min_z)/2._ReKi /) + node%Moments=0.0_ReKi + if(associated(node%iPart)) then ; print*,'[Error] Node part allocated'; STOP; endif + allocate(node%iPart(1:Part%n)) + do i=1,Part%n + node%iPart(i) = i + end do + if(associated(node%branches)) then; print*,'node branches allocated'; STOP; endif + if(associated(node%leaves)) then; print*,'node leaves allocated'; STOP; endif + node%branches=>null() + node%leaves=>null() + node%nPart=Part%n + ! --- Calling grow function on subbrances + call grow_tree_parallel(Tree%root, Tree%Part) +! call grow_tree_rec(Tree%root, Tree%Part) + endif + Tree%iStep = iStep + Tree%bGrown = .true. + end subroutine grow_tree + + !> Recursive function to grow/setup a tree. + !! Note, needed preliminary calc are done by grow_tree before + recursive subroutine grow_tree_rec(node, Part) + type(T_Node), target :: node !< + type(T_Part), intent(in) :: Part !< + integer :: i + ! Sub Step: + ! - compute moments and center for the current node + ! - allocate branches and leaves + call grow_tree_substep(node, Part) + ! Call grow_tree on branches + if(associated(node%branches)) then + do i = 1,size(node%branches) + call grow_tree_rec(node%branches(i), Part) + end do + endif + end subroutine grow_tree_rec + + !> Perform a substep of tree growth, growing sub branches from a given node/cell + !! Parent has already setup node%iPart, indices of the particle in this cell + !! Steps are: + !! - Compute node center (barycenter of vorticity) + !! - Compute node moments + !! - Distribute particles in each 8 octants. Branches are not created for empty octant + !! - Allocate branches and leaves and distribute particles to them + subroutine grow_tree_substep(node, Part) + type(T_Node), intent(inout) :: node !< Current node we are growing from + type(T_Part), intent(in) :: Part !< All particles info + integer(IK1) :: iPartOctant !< Index corresponding to which octant the particle falls into + integer :: nLeaves, nBranches + integer :: iLeaf, iOctant, iBranch + integer :: i1,i2,i3,i4,i5,i6,i7,i8 + integer :: i,j,k + real(ReKi) :: wTot, wLoc ! Total and local vorticity strength + real(ReKi) :: halfSize ! TODO remove me + real(ReKi),dimension(3) :: locCenter, DeltaP,PartPos,PartAlpha + real(ReKi),dimension(3) :: nodeGeomCenter !< Geometric center from division of the domain in powers of 2 + real(ReKi),dimension(3) :: nodeBaryCenter !< Vorticity weighted center + integer(IK1),dimension(:),allocatable :: PartOctant !< Stores the octant (1-8) where each particle belongs + integer,dimension(8) :: npart_per_octant !< Number of particle per octant + integer,dimension(8) :: octant2branches !< Mapping between 8 octants, to index of non empty branch + integer,dimension(8) :: octant2leaves !< Idem for singleton/leaves + real(ReKi) :: max_x,max_y,max_z !< for domain dimension + real(ReKi) :: min_x,min_y,min_z !< for domain dimension + nodeGeomCenter = node%center ! NOTE: we rely on the fact that our parent has set this to the Geometric value + nodeBaryCenter = 0.0_ReKi + wTot = 0.0_ReKi + ! --- Barycenter of vorticity of the node + do i = 1,node%nPart + PartPos = Part%P(:,node%iPart(i)) + PartAlpha = Part%Alpha(:,node%iPart(i)) + wLoc = (PartAlpha(1)**2 + PartAlpha(2)**2 + PartAlpha(3)**2)**0.5_ReKi ! Vorticity norm + nodeBaryCenter = nodeBaryCenter + wLoc*PartPos ! Sum coordinates weighted by vorticity + wTot = wTot + wLoc ! Total vorticity + end do + ! There is no vorticity, we make it a empty node and we exit + if(EqualRealNos(abs(wTot),0.0_ReKi)) then + node%nPart=0 + if (associated(node%iPart)) deallocate(node%iPart) + return ! NOTE: we exit + endif + nodeBaryCenter = nodeBaryCenter/wTot ! barycenter of vorticity + node%center = nodeBaryCenter ! updating + + ! --- Calculation of moments about nodeBaryCenter + do i = 1,node%nPart + PartPos = Part%P (:,node%iPart(i)) + PartAlpha = Part%Alpha(:,node%iPart(i)) + DeltaP = PartPos-nodeBaryCenter + ! Order 0 + node%Moments(1:3,M0_000) = node%Moments(1:3,M0_000) + PartAlpha + ! 1st order + node%Moments(1:3,M1_100) = node%Moments(1:3,M1_100) + PartAlpha*DeltaP(1) ! 100 + node%Moments(1:3,M1_010) = node%Moments(1:3,M1_010) + PartAlpha*DeltaP(2) ! 010 + node%Moments(1:3,M1_001) = node%Moments(1:3,M1_001) + PartAlpha*DeltaP(3) ! 001 + ! 2nd order + do j=1,3 + do k=1,j + node%Moments(1:3,3+j+k+j/3) = node%Moments(1:3,3+j+k+j/3) + PartAlpha*DeltaP(j)*DeltaP(k) + end do + end do + end do + + ! --- Distributing particles to the 8 octants (based on the geometric center!) + allocate (PartOctant(1:node%nPart)) + npart_per_octant(1:8)=0 + do i = 1,node%nPart + PartPos = Part%P(:,node%iPart(i)) + ! index corresponding to which octant the particle falls into + iPartOctant = int(1,IK1) + if (PartPos(1) > nodeGeomCenter(1)) iPartOctant = iPartOctant + int(1,IK1) + if (PartPos(2) > nodeGeomCenter(2)) iPartOctant = iPartOctant + int(2,IK1) + if (PartPos(3) > nodeGeomCenter(3)) iPartOctant = iPartOctant + int(4,IK1) + npart_per_octant(iPartOctant) = npart_per_octant(iPartOctant) + 1 ! Counter of particles per octant + PartOctant(i)=iPartOctant ! Store in which octant particle i is + end do + + ! --- Leaves and branches + ! A node contains a combination of child nodes and leaves (single particles) + ! TODO: introduce a "minimum cell size", (e.g. cell radius is less than the Distance for direct evaluation, then all should be leaves) + nLeaves = 0 + nBranches = 0 + octant2branches = 0 + octant2leaves = 0 + do iOctant = 1,8 + if(npart_per_octant(iOctant)==1) then + nLeaves = nLeaves+1 + octant2leaves(iOctant) = nLeaves + else if(npart_per_octant(iOctant)>1) then + if (npart_per_octant(iOctant)==node%nPart) then + ! All particle falls into the same octant, if they all have the same location, we would divide forever. + ! Quick fix below + max_x=maxval(Part%P(1,node%iPart(:))); max_y=maxval(Part%P(2,node%iPart(:))); max_z=maxval(Part%P(3,node%iPart(:))) + min_x=minval(Part%P(1,node%iPart(:))); min_y=minval(Part%P(2,node%iPart(:))); min_z=minval(Part%P(3,node%iPart(:))) + if (max(abs(max_x-min_x),abs(max_y-min_y),abs(max_z-min_z))< 1.0e-5) then + nLeaves=node%nPart + allocate (node%leaves(1:nLeaves)) + do i = 1,node%nPart + node%leaves(i)=node%iPart(i) + enddo + ! Cleanup and exit! + if (associated(node%iPart)) deallocate(node%iPart) ! Freeing memory + if (allocated(PartOctant)) deallocate(PartOctant) + return + endif + endif + nBranches = nBranches+1 + octant2branches(iOctant) = nBranches + endif + enddo + if (associated(node%branches)) then + print*,'Tree build: error, branches associated' + STOP + endif + if (associated(node%leaves)) then + print*,'Tree build: error, leaves associated' + STOP + end if + + if(nBranches>0) allocate (node%branches(1:nBranches)) + if(nLeaves>0) allocate (node%leaves(1:nLeaves)) + + ! --- Initializing the branches nodes and leaves + halfSize = node%radius/2._ReKi + do iOctant = 1,8 ! there is max 8 octant + iBranch = octant2branches(iOctant) + if (iBranch>0) then ! this node has branches + allocate(node%branches(iBranch)%iPart(1:npart_per_octant(iOctant))) + node%branches(iBranch)%nPart=npart_per_octant(iOctant) + ! NOTE: this is geometric center not barycenter + locCenter = nodeGeomCenter + 0.5*halfSize*(/ (-1)**(iOctant), (-1)**floor(0.5*real(iOctant-1)+1), (-1)**floor(0.25*real(iOctant-1)+1) /) + ! Init of branches + node%branches(iBranch)%radius = halfSize ! + node%branches(iBranch)%center = locCenter ! NOTE: this is the geometric center + node%branches(iBranch)%Moments = 0.0_ReKi ! + node%branches(iBranch)%branches=>null() + node%branches(iBranch)%leaves=>null() + endif + ! other cases are leaves or dead branches + end do + + ! Store indices of the particles the sub-branch contains + i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; i7=0; i8=0; + do i = 1,node%nPart + iBranch = octant2branches(PartOctant(i)) + if(iBranch>0) then + select case(iBranch) + case(1);i1=i1+1; node%branches(1)%iPart(i1) = node%iPart(i) + case(2);i2=i2+1; node%branches(2)%iPart(i2) = node%iPart(i) + case(3);i3=i3+1; node%branches(3)%iPart(i3) = node%iPart(i) + case(4);i4=i4+1; node%branches(4)%iPart(i4) = node%iPart(i) + case(5);i5=i5+1; node%branches(5)%iPart(i5) = node%iPart(i) + case(6);i6=i6+1; node%branches(6)%iPart(i6) = node%iPart(i) + case(7);i7=i7+1; node%branches(7)%iPart(i7) = node%iPart(i) + case(8);i8=i8+1; node%branches(8)%iPart(i8) = node%iPart(i) + end select + else + iLeaf = octant2leaves(PartOctant(i)) + if(iLeaf>0) then + node%leaves(iLeaf)=node%iPart(i) + else + print*,'This particle do not belong to anybody!!',i + STOP + endif + endif + end do + if (associated(node%iPart)) deallocate(node%iPart) ! Freeing memory + if (allocated(PartOctant)) deallocate(PartOctant) + end subroutine grow_tree_substep + + !> Grow a tree in "parallel", since recursive calls cannot be parallized easily, we unroll the different layer calls + !! Note, needed preliminary calc are done by grow_tree before! + subroutine grow_tree_parallel(Root, Part) + type(T_Node), intent(inout) :: Root + type(T_Part), intent(in) :: Part + integer :: i, nBranches + integer :: i1 + integer :: i2 + + ! --- Unrolled version of grow_tree for the first node + ! Sub Step: + ! - compute moments and center for the current node + ! - allocate branches and leaves + call grow_tree_substep(Root, Part) + + if(.not. associated(Root%branches)) then + nBranches=0 + else + nBranches=size(Root%branches) + if (nBranches==0) then + print*,'No branches' ! This should not happen + STOP + else + ! Call "grow_tree" on branches + + !$OMP PARALLEL default(shared) + + ! --- Unrolled version of grow_tree for the second levels + !$OMP do private(i) schedule(runtime) + do i = 1,nBranches ! maximum 8 branches + if(Root%branches(i)%nPart>1) then ! I dont think this test is needed + call grow_tree_substep(Root%branches(i), Part) + endif + end do + !$OMP end do + !$OMP barrier ! we need to be sure that all the branches were built + ! --- Unrolled version of grow_tree for third node levels + !$OMP do private(i,i1,i2) schedule(runtime) + do i = 1,nBranches*8 ! maximum 64 sub branches + i1=(i-1)/8+1; + i2=mod(i-1,8)+1; + if(associated(Root%branches(i1)%branches)) then + if (i2<=size(Root%branches(i1)%branches)) then + call grow_tree_rec(Root%branches(i1)%branches(i2), Part) + endif + endif + enddo + !$OMP end do + !Note: We could add more levels + !$OMP END PARALLEL + endif + endif + end subroutine grow_tree_parallel + + + + ! -------------------------------------------------------------------------------- + ! --- Cut tree + ! -------------------------------------------------------------------------------- + !> Cut a tree and all its subbranches in a recursive manner + recursive subroutine cut_tree_rec(node) + integer :: i + type(T_Node),intent(inout) :: node + call cut_substep(node) + if (associated(node%branches)) then + do i=1,size(node%branches) + call cut_tree_rec(node%branches(i)) + end do + deallocate(node%branches) + node%branches=> null() + end if + end subroutine cut_tree_rec + + !> Perform a substep of tree cutting (used by recursive and parallel calls) + subroutine cut_substep(node) + type(T_Node), intent(inout) :: node + if (associated(node%leaves)) then + deallocate(node%leaves) + end if + if (associated(node%iPart)) then + print*,'The tree particles were not properly cleaned' + STOP + deallocate(node%iPart) + end if + end subroutine cut_substep + + !> Cut a tree and all its sub-branches, unrolled to use parallelization for the first 3 levels + subroutine cut_tree_parallel(Tree) + type(T_Tree), intent(inout) :: Tree + integer :: i,i1,i2,nBranches + ! --- Unlinking particles + nullify(Tree%Part%P) + nullify(Tree%Part%Alpha) + nullify(Tree%Part%RegParam) + ! --- Unrolled version of cut_tree for the first node + call cut_substep(Tree%root) + if(associated(Tree%Root%branches)) then + nBranches=size(Tree%Root%branches) + !$OMP PARALLEL default(shared) + + ! --- Unrolled version for the second levels + !$OMP do private(i) schedule(runtime) + do i = 1,nBranches ! maximum 8 branches + call cut_substep(Tree%Root%branches(i)) + end do + !$OMP end do + !$OMP barrier ! we need to be sure that all the branches were cut + + ! --- Unrolled version for third node levels + !$OMP do private(i,i1,i2) schedule(runtime) + do i = 1,nBranches*8 ! maximum 64 sub branches + i1=(i-1)/8+1; + i2=mod(i-1,8)+1; + if(associated(Tree%Root%branches(i1)%branches)) then + if (i2<=size(Tree%Root%branches(i1)%branches)) then + call cut_tree_rec(Tree%Root%branches(i1)%branches(i2)) + endif + endif + enddo + !$OMP end do + !$OMP END PARALLEL + + ! --- Cleanup second level + do i = 1,nBranches ! maximum 8 branches + if (associated(Tree%root%branches(i)%branches)) then + deallocate(Tree%root%branches(i)%branches) + nullify(Tree%root%branches(i)%branches) + endif + end do + + ! --- Cleanup First level + deallocate(Tree%root%branches) + nullify(Tree%root%branches) + endif + if (associated(Tree%root%branches)) then + print*,'Tree cut: branches are still allocated' + STOP + endif + Tree%iStep=-1 + Tree%root%nPart=-1 + Tree%bGrown=.false. + end subroutine cut_tree_parallel + + subroutine print_tree(Tree) + type(T_Tree) :: Tree + character(len=1024) :: preffix + preffix='root' + print '(A, L1)', trim(preffix)//':partP_assoc = ',associated(Tree%Part%P) + print '(A, L1)', trim(preffix)//':bGrown = ',Tree%bGrown + print '(A, I0)', trim(preffix)//':iStep = ',Tree%iStep + call print_tree_rec(Tree%Root, preffix) + contains + recursive subroutine print_tree_rec(node, preffix) + type(T_Node), target :: node !< + character(len=*), intent(in) :: preffix + integer :: i + ! Test if there are enough particles on the node to build new branchess + ! The case of only one particle should be handled upstream by allocating one leaf to the parent node + print'(A)' ,trim(preffix)//':nPart = '//Num2LStr(node%nPart) + print'(A,3F12.3)',trim(preffix)//':center =',node%center + print'(A,1F12.3)',trim(preffix)//':radius =',node%radius + if(associated(node%leaves)) then + do i = 1,size(node%leaves) + print'(A)',trim(preffix)//':leaf'//trim(Num2LStr(i))//'='//trim(Num2LStr(node%leaves(i))) + end do + endif + if(associated(node%branches)) then + do i = 1,size(node%branches) + call print_tree_rec(node%branches(i), trim(preffix)//':branch'//trim(Num2LStr(i))) + end do + endif + end subroutine print_tree_rec + end subroutine print_tree + + ! -------------------------------------------------------------------------------- + ! --- Velocity computation + ! -------------------------------------------------------------------------------- + subroutine ui_tree(Tree, CPs, ioff, icp_beg, icp_end, BranchFactor, DistanceDirect, Uind, ErrStat, ErrMsg) + use FVW_BiotSavart, only: fourpi_inv, ui_part_nograd_11 + type(T_Tree), target, intent(inout) :: Tree !< + integer, intent(in ) :: ioff !< + integer, intent(in ) :: icp_beg !< + integer, intent(in ) :: icp_end !< + real(ReKi), intent(in ) :: BranchFactor !< + real(ReKi), intent(in ) :: DistanceDirect !< Distance under which direct evaluation should be done no matter what the tree cell size is + real(ReKi), dimension(:,:), intent(in ) :: CPs !< Control Points (3 x nCPs) + real(ReKi), dimension(:,:), intent(inout) :: Uind !< Induced velocity at CPs, with side effects (3 x nCPs) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(ReKi), dimension(3) :: Uind_tmp !< + real(ReKi), dimension(3) :: CP !< Current CP + integer :: icp, nDirect, nQuad + type(T_Part), pointer :: Part ! Alias + Part => Tree%Part + if(.not. associated(Part%P)) then + ErrMsg='Ui Part Tree called but tree particles not associated'; ErrStat=ErrID_Fatal; return + endif + !$OMP PARALLEL DEFAULT(SHARED) + !$OMP DO PRIVATE(icp,CP,Uind_tmp,nDirect,nQuad) schedule(runtime) + do icp=icp_beg,icp_end + CP = CPs(1:3,icp) + Uind_tmp(1:3) = 0.0_ReKi + nDirect =0 + nQuad =0 + call ui_tree_11(Tree%root, CP, Uind_tmp, nDirect, nQuad) !< SIDE EFFECTS + !print*,'Number of direct calls, and quad calls',nDirect, nQuad + Uind(1:3,ioff+icp-icp_beg+1) = Uind(1:3,ioff+icp-icp_beg+1) + Uind_tmp(1:3) + enddo + !$OMP END DO + !$OMP END PARALLEL + contains + !> Velocity at one control point from the entire tree + recursive subroutine ui_tree_11(node, CP, Uind, nDirect, nQuad) + real(ReKi),dimension(3),intent(inout) :: CP, Uind !< Velocity at control point, with side effect + integer, intent(inout) :: nDirect,nQuad + type(T_Node), intent(inout) :: node + real(ReKi) :: distDirect, coeff + real(ReKi),dimension(3) :: DeltaP, phi, Uloc + real(ReKi) :: x,y,z,mx,my,mz,r + integer :: i,j,ieqj + integer :: iPart + if (node%nPart<=0) then + ! We skip the dead leaf + elseif (.not.associated(node%branches)) then + ! Loop on leaves + if(associated(node%leaves)) then + do i =1,size(node%leaves) + iPart=node%leaves(i) + DeltaP = CP(1:3) - Part%P(1:3,iPart) + call ui_part_nograd_11(DeltaP, Part%Alpha(1:3,iPart), Part%RegFunction, Part%RegParam(iPart), Uloc) + nDirect=nDirect+1 + Uind(1:3) = Uind(1:3) + Uloc + enddo + endif + else + distDirect = max(BranchFactor*node%radius, DistanceDirect) ! Under this distance-> Direct eval., Above it -> quadrupole calculation + DeltaP = - node%center + CP(1:3) ! Vector between the control point and the center of the branch + r = sqrt( DeltaP(1)**2 + DeltaP(2)**2 + DeltaP(3)**2) + ! Test if the control point is too close from the branch node so that a direct evaluation is needed + if (r<distDirect) then + ! We are too close, perform direct evaluation using children (leaves and branches) + if(associated(node%leaves)) then + do i =1,size(node%leaves) + iPart=node%leaves(i) + DeltaP = CP(1:3) - Part%P(1:3,iPart) + call ui_part_nograd_11(DeltaP, Part%Alpha(1:3,iPart), Part%RegFunction, Part%RegParam(iPart), Uloc) + nDirect=nDirect+1 + Uind(1:3) = Uind(1:3) + Uloc + enddo + endif + if(associated(node%branches)) then + ! TODO: consider implementing a recursive method for that: direct call on all children + do i =1,size(node%branches) + call ui_tree_11(node%branches(i), CP, Uind, nDirect, nQuad) + end do + endif + + else + ! We are far enough, use branch node quadrupole + x=DeltaP(1) + y=DeltaP(2) + z=DeltaP(3) + phi = node%Moments(1:3,M0)/r**3*fourpi_inv + + ! Speed, order 0 + Uloc(1) = phi(2)*z - phi(3)*y + Uloc(2) = phi(3)*x - phi(1)*z + Uloc(3) = phi(1)*y - phi(2)*x + Uind = Uind+Uloc + + ! Speed, order 1 + Uloc=0.0_ReKi + coeff = 3.0_ReKi*x*fourpi_inv/r**5 + Uloc(1) = Uloc(1)- coeff*(node%Moments(3,M1_1)*y-node%Moments(2,M1_1)*z) + Uloc(2) = Uloc(2)- coeff*(node%Moments(1,M1_1)*z-node%Moments(3,M1_1)*x) + Uloc(3) = Uloc(3)- coeff*(node%Moments(2,M1_1)*x-node%Moments(1,M1_1)*y) + + coeff = 3.0_ReKi*y*fourpi_inv/r**5 + Uloc(1) = Uloc(1) - coeff*(node%Moments(3,M1_2)*y-node%Moments(2,M1_2)*z) + Uloc(2) = Uloc(2) - coeff*(node%Moments(1,M1_2)*z-node%Moments(3,M1_2)*x) + Uloc(3) = Uloc(3) - coeff*(node%Moments(2,M1_2)*x-node%Moments(1,M1_2)*y) + + coeff = 3.0_ReKi*z*fourpi_inv/r**5 + Uloc(1) = Uloc(1) - coeff*(node%Moments(3,M1_3)*y-node%Moments(2,M1_3)*z) + Uloc(2) = Uloc(2) - coeff*(node%Moments(1,M1_3)*z-node%Moments(3,M1_3)*x) + Uloc(3) = Uloc(3) - coeff*(node%Moments(2,M1_3)*x-node%Moments(1,M1_3)*y) + + coeff = fourpi_inv/r**3 + Uloc(1) = Uloc(1) + coeff*node%Moments(3,M1_2) - coeff*node%Moments(2,M1_3) + Uloc(2) = Uloc(2) + coeff*node%Moments(1,M1_3) - coeff*node%Moments(3,M1_1) + Uloc(3) = Uloc(3) + coeff*node%Moments(2,M1_1) - coeff*node%Moments(1,M1_2) + Uind=Uind+Uloc + Uloc =0.0_ReKi + do i =1,3 + coeff = 1.5_ReKi*fourpi_inv/r**5 + Uloc(1) = Uloc(1) + coeff * (y*node%Moments(3,5+2*(i/2)+3*(i/3)) - z*node%Moments(2,5+2*(i/2)+3*(i/3))) + Uloc(2) = Uloc(2) + coeff * (z*node%Moments(1,5+2*(i/2)+3*(i/3)) - x*node%Moments(3,5+2*(i/2)+3*(i/3))) + Uloc(3) = Uloc(3) + coeff * (x*node%Moments(2,5+2*(i/2)+3*(i/3)) - y*node%Moments(1,5+2*(i/2)+3*(i/3))) + do j=1,i + if (i==j) then + ieqj = 1 + else + ieqj = 2 + end if + coeff = -7.5_ReKi*DeltaP(i)*DeltaP(j)*fourpi_inv/r**7 + Uloc(1) = Uloc(1) + ieqj * coeff * ( y*node%Moments(3,3+i+j+i/3) - z*node%Moments(2,3+i+j+i/3)) + Uloc(2) = Uloc(2) + ieqj * coeff * ( z*node%Moments(1,3+i+j+i/3) - x*node%Moments(3,3+i+j+i/3)) + Uloc(3) = Uloc(3) + ieqj * coeff * ( x*node%Moments(2,3+i+j+i/3) - y*node%Moments(1,3+i+j+i/3)) + end do + end do + coeff = 3.0_ReKi*fourpi_inv/r**5 + Uloc(1) = Uloc(1) + coeff * ( y*node%Moments(3,M2_22) - z*node%Moments(2,M2_33) ) + Uloc(2) = Uloc(2) + coeff * ( z*node%Moments(1,M2_33) - x*node%Moments(3,M2_11) ) + Uloc(3) = Uloc(3) + coeff * ( x*node%Moments(2,M2_11) - y*node%Moments(1,M2_22) ) + + coeff = 3.0_ReKi*fourpi_inv/r**5 + Uloc(1) = Uloc(1) + coeff * (z*node%Moments(3,M2_32) + x*node%Moments(3,M2_21) - x*node%Moments(2,M2_31) - y*node%Moments(2,M2_32)) + Uloc(2) = Uloc(2) + coeff * (x*node%Moments(1,M2_31) + y*node%Moments(1,M2_32) - y*node%Moments(3,M2_21) - z*node%Moments(3,M2_31)) + Uloc(3) = Uloc(3) + coeff * (y*node%Moments(2,M2_21) + z*node%Moments(2,M2_31) - z*node%Moments(1,M2_32) - x*node%Moments(1,M2_21)) + Uind(1:3) = Uind(1:3) + Uloc + nQuad=nQuad+1 + end if ! Far enough + end if ! had more than 1 particles + end subroutine ui_tree_11 + end subroutine ui_tree + +end module FVW_VortexTools diff --git a/OpenFAST/modules/aerodyn/src/FVW_Wings.f90 b/OpenFAST/modules/aerodyn/src/FVW_Wings.f90 new file mode 100644 index 000000000..bad06fbce --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/FVW_Wings.f90 @@ -0,0 +1,508 @@ +module FVW_Wings + + use NWTC_Library + use FVW_Types + use FVW_Subs + use AirFoilInfo, only : AFI_ComputeAirfoilCoefs + + implicit none + +contains + + !> Meshing function. Create a 1D mesh of size `n`, based on a `method` and an input vector `x` + subroutine Meshing(method, x, n, y) + ! Arguments declarations + character(len=*), intent(in) :: method !< String defining the method used + integer(IntKi), intent(in) :: n !< size of vector y + real(ReKi), dimension(:),intent(in) :: x !< input vector of nodes or (/ min, max/) + real(ReKi), dimension(:), intent(out) :: y !< output vector with meshing values + ! Variable declarations + real(ReKi), dimension(:),allocatable :: dx !< + integer::jr + y = 0.0_ReKi + select case (method) ! + case ('middle') ! + allocate(dx(1:n)) + dx=diff(x) ! dx is the width of each panel + y(1:n)=x(1:n)+dx(1:n)/2._ReKi + deallocate(dx) + + case ('fullcosineapprox') ! + ! x is assumed to be of size n+1 + if (n==1) then + y(1)=(x(1)+x(2))/2._ReKi ! middle + return + else + allocate(dx(1:n)) + dx=diff(x) ! dx is the width of each panel + y(1) = x(1)+(dx(1) /(dx(1) +dx(2)))*dx(1) + y(n) = x(n)+(dx(n-1)/(dx(n-1)+dx(n)))*dx(n) + do jr=2,n-1 + y(jr)=x(jr)+0.25_ReKi*(dx(jr-1)/(dx(jr-1)+dx(jr)) + dx(jr)/(dx(jr)+dx(jr+1))+1 )*dx(jr) + end do + deallocate(dx) + endif + end select + + contains + !> Compute: x(2:n)-x(1:n-1) + function diff(d) + real(ReKi),dimension(:),intent(in) ::d + real(ReKi),dimension(size(d)-1) ::diff + integer::i + do i=1,size(d)-1 + diff(i)=d(i+1)-d(i) + enddo + end function + end subroutine Meshing + + + !---------------------------------------------------------------------------------------------------------------------------------- + !> Based on an input mesh, sets the following: + !! - s_LL : Dimensionless spanwise coordinate of LL + !! - s_CP_LL : Dimensionless spanwise coordinate of LL CP + !! - chord_LL : chord on LL + !! - chord_LL_CP: chord on LL cp + subroutine Wings_Panelling_Init(Meshes, p, m, ErrStat, ErrMsg ) + type(MeshType), dimension(:), intent(in ) :: Meshes !< Wings mesh + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local + !integer(IntKi) :: ErrStat2 ! temporary error status of the operation + !character(ErrMsgLen) :: ErrMsg2 ! temporary error message + integer(IntKi) :: iW, iSpan + real(ReKi), dimension(3) :: DP + real(ReKi), dimension(:),allocatable :: s_in !< Dimensionless spanwise coordinate of input + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Meshing + do iW = 1,p%nWings + if (allocated(s_in)) deallocate(s_in) + allocate(s_in(1:Meshes(iW)%nNodes)) + ! --- Computing spanwise coordinate of input mesh normalized from 0 to 1 +!Note: this info also exists in InitInp%zLocal + s_in(:) = -999 + s_in(1) = 0 + do iSpan = 2, Meshes(iW)%nNodes + DP = Meshes(iW)%Position(1:3, iSpan) - Meshes(iW)%Position(1:3, iSpan-1) + s_in(iSpan) = s_in(iSpan-1) + TwoNorm(DP) + enddo + + ! --- Setting up Lifting line variables based on input and a "meshing" method (TODO) + if (Meshes(iW)%nNodes /= p%nSpan+1) then + ! TODO Possibly interpolate based on FVW meshing + ! NOTE: p%chord is copied from the InitInput + ErrMsg ='TODO different discretization InputMesh / vortex code'; ErrStat=ErrID_Fatal; return + endif + do iSpan = 1, p%nSpan+1 + m%s_LL (iSpan, iW) = s_in(iSpan) + m%chord_LL(iSpan, iW) = p%chord(iSpan,iW) + enddo + ! --- Control points spanwise location + ! NOTE: we use the cos approximation of VanGarrel. For equispacing, it returns mid point + ! otherwise, points are slightly closer to panels that are shorter + !call Meshing('middle' , m%s_LL(:,iW), p%nSpan, m%s_CP_LL(:,iW)) + call Meshing('fullcosineapprox' , m%s_LL(:,iW), p%nSpan, m%s_CP_LL(:,iW)) + call InterpArray(m%s_LL(:,iW), m%chord_LL(:,iW), m%s_CP_LL(:,iW), m%chord_CP_LL(:,iW)) + enddo + end subroutine Wings_Panelling_Init + !---------------------------------------------------------------------------------------------------------------------------------- + !> Based on an input mesh, sets the following: + !! - LE : Leading edge points (3 x nSpan+1 x nWings) + !! - TE : Trailing edge points (3 x nSpan+1 x nWings) + !! - CP_LL : Coordinates of LL CP" (3 x nSpan x nWings) + !! - Tang : Unit Tangential vector on LL CP" - + !! - Norm : Unit Normal vector on LL CP " - + !! - Orth : Unit Orthogonal vector on LL CP" - + !! - Vstr_LL : Structural velocity on LL CP" m/s + subroutine Wings_Panelling(Meshes, p, m, ErrStat, ErrMsg ) + type(MeshType), dimension(:), intent(in ) :: Meshes !< Wings mesh + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local + !integer(IntKi) :: ErrStat2 ! temporary error status of the operation + !character(ErrMsgLen) :: ErrMsg2 ! temporary error message + integer(IntKi) ::iSpan , iW + real(ReKi), dimension(3) :: P_ref ! Reference point of Input Mesh (e.g. AeroDynamic Center?) + real(ReKi), dimension(3) :: DP_LE ! Distance between reference point and Leading edge + real(ReKi), dimension(3) :: DP_TE ! Distance between reference point and trailing edge + real(ReKi), dimension(3) :: P1,P2,P3,P4,P5,P7,P8,P6,P9,P10 + real(ReKi), dimension(3) :: DP1, DP2, DP3 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! --- Position of leading edge (LE) and trailing edge (TE) + ! NOTE, this assumes one to one between InputMesh and FVW Mesh + do iW = 1,p%nWings + do iSpan = 1,p%nSpan+1 + P_ref = Meshes(iW)%Position(1:3, iSpan )+Meshes(iW)%TranslationDisp(1:3, iSpan) + DP_LE(1:3) = 0.0 + DP_LE(1) = -m%chord_LL(iSpan,iW)/4. + DP_TE(1:3) = 0.0 + DP_TE(1) = +3.*m%chord_LL(iSpan,iW)/4. + m%LE(1:3, iSpan, iW) = P_ref + DP_LE(1)*Meshes(iW)%Orientation(2,1:3,iSpan) + m%TE(1:3, iSpan, iW) = P_ref + DP_TE(1)*Meshes(iW)%Orientation(2,1:3,iSpan) + enddo + enddo + ! --- Generic code below to compute normal/tangential vectors of a lifting line panel + ! Notations follow vanGarrel [ECN-C--03-079, Development of a wind turbine aerodynamics simulation module,2003] + ! + ! P4 -P10---P7------ P3 + ! | + ! P8 P6 + ! | + ! P1 -P9----P5------ P2 + ! + do iW = 1,p%nWings + do iSpan = 1,p%nSpan + P1 = m%LE(:,iSpan , iw) + P4 = m%LE(:,iSpan+1, iw) + P3 = m%TE(:,iSpan+1, iw) + P2 = m%TE(:,iSpan , iw) + P8 = (P1+P4)/2 + P6 = (P2+P3)/2 + P5 = (P1+P2)/2 + P7 = (P4+P3)/2 + P9 = 0.75_ReKi*P1+0.25_ReKi*P2 + P10 = 0.75_ReKi*P4+0.25_ReKi*P3 + DP1 = P6-P8 + DP2 = P10-P9 + DP3 = P7-P5 + + ! NOTE: The denominator below has seg-faulted with Intel Fortran in Release mode, possibly due to nuances in copmiler optimizations. + ! This code was previously after the m%Norm calculations, but moving it up "fixes" the bug. + m%Tang(1:3,iSpan,iW) = (DP1)/TwoNorm(DP1) ! tangential unit vector, along chord + + m%Norm(1:3,iSpan,iW) = cross_product(DP1,DP2) + m%Norm(1:3,iSpan,iW) = m%Norm(1:3,iSpan,iW)/TwoNorm(m%Norm(1:3,iSpan,iW)) + ! m%Tscoord(1:3,iSpan) = (DP3)/norm2(DP3) ! tangential unit vector, along span, follows ref line + m%dl (1:3,iSpan,iW) = DP2 + m%Orth(1:3,iSpan,iW) = cross_product(m%Norm(1:3,iSpan,iW),m%Tang(1:3,iSpan,iW)) ! orthogonal vector to N and T + m%Area(iSpan, iW) = TwoNorm(cross_product(DP1,DP3)) + DP3 = P1-P3 + m%diag_LL(iSpan, iW) = TwoNorm(DP3) + end do + enddo +!FIXME: does it make sense to use the position mesh for this info? + ! --- Lifting Line/ Bound Circulation panel + ! For now: goes from 1/4 chord to TE + ! More panelling options may be considered in the future + do iW = 1,p%nWings + do iSpan = 1,p%nSpan+1 + m%r_LL(1:3,iSpan,1,iW)= m%TE(1:3,iSpan,iW)*0.25_ReKi+m%LE(1:3,iSpan,iW)*0.75_ReKi ! 1/4 chord + m%r_LL(1:3,iSpan,2,iW)= m%TE(1:3,iSpan,iW) ! TE + enddo + enddo + + ! --- Position of control points CP_LL + ! For now: placed exactly on the LL panel + ! NOTE: separated from other loops just in case a special discretization is used + do iW = 1,p%nWings + call InterpArray(m%s_LL(:,iW), m%r_LL(1,:,1,iW), m%s_CP_LL(:,iW), m%CP_LL(1,:,iW)) + call InterpArray(m%s_LL(:,iW), m%r_LL(2,:,1,iW), m%s_CP_LL(:,iW), m%CP_LL(2,:,iW)) + call InterpArray(m%s_LL(:,iW), m%r_LL(3,:,1,iW), m%s_CP_LL(:,iW), m%CP_LL(3,:,iW)) + enddo + + ! --- Structural velocity on LL + ! TODO: difference meshes in/LL + do iW = 1,p%nWings + call InterpArray(m%s_LL(:,iW), Meshes(iW)%TranslationVel(1,:) ,m%s_CP_LL(:,iW), m%Vstr_LL(1,:,iW)) + call InterpArray(m%s_LL(:,iW), Meshes(iW)%TranslationVel(2,:) ,m%s_CP_LL(:,iW), m%Vstr_LL(2,:,iW)) + call InterpArray(m%s_LL(:,iW), Meshes(iW)%TranslationVel(3,:) ,m%s_CP_LL(:,iW), m%Vstr_LL(3,:,iW)) + enddo + end subroutine Wings_Panelling + + !---------------------------------------------------------------------------------------------------------------------------------- + !> + subroutine Wings_ComputeCirculation(t, Gamma_LL, Gamma_LL_prev, u, p, x, m, AFInfo, ErrStat, ErrMsg, iLabel) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + real(ReKi), dimension(:,:), intent(inout) :: Gamma_LL !< Circulation on all the lifting lines + real(ReKi), dimension(:,:), intent(in ) :: Gamma_LL_prev !< Previous/Guessed circulation + type(FVW_InputType), intent(in ) :: u !< Parameters + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi), intent(in) :: iLabel + ! Local + integer(IntKi) :: iW + real(DbKi) :: s, RealAxis + real(ReKi) :: GammaScale + ErrStat = ErrID_None + ErrMsg = "" + + if (t<p%FullCirculationStart) then + ! The circulation is ramped up progressively, starting from 0 + if (t<=0.0_DbKi) then + GammaScale=0.0_ReKi + else + s=t/p%FullCirculationStart + ! If we have at least 10 points we use a smooth Heavyside, otherwise we use a simple linear scaling + if (p%FullCirculationStart/p%DTfvw >= 9) then + ! Smooth approximations of the Heavyside function + ! Example 1: 1/2 (1+2/pi arctan(k x) ) x \in ]-infty,+infty [ + ! Example 2: 1/(1+exp(k x) ) x \in ]-infty,+infty [ + ! Example 3: sin(pi/2*s)**2 s \in [0,1] + RealAxis = (1-2*s)/(s*(s-1._DbKi)-1.0e-02_DbKi) ! Scaling from 0-1 to real axis + GammaScale = 1._ReKi- 1._ReKi/(1._ReKi+exp(real(RealAxis,ReKi))) + else + GammaScale = s ! Using a linear scaling + endif + endif + else + GammaScale=1.0_ReKi + endif + + if (p%CirculationMethod==idCircPrescribed) then + do iW = 1, p%nWings !Loop over lifting lines + Gamma_LL(1:p%nSpan,iW) = p%PrescribedCirculation(1:p%nSpan) + enddo + + else if (p%CirculationMethod==idCircPolarData) then + ! --- Solve for circulation using polar data + CALL Wings_ComputeCirculationPolarData(Gamma_LL, Gamma_LL_prev, p, x, m, AFInfo, GammaScale, ErrStat, ErrMsg, iLabel) + + else if (p%CirculationMethod==idCircNoFlowThrough) then + ! --- Solve for circulation using the no-flow through condition + ErrMsg='Circulation method nor implemented'; ErrStat=ErrID_Fatal; return ! should never happen + else + ErrMsg='Circulation method nor implemented'; ErrStat=ErrID_Fatal; return ! should never happen + endif + + ! Scale circulation (for initial transient) + Gamma_LL = Gamma_LL * GammaScale + + + endsubroutine Wings_ComputeCirculation + + !---------------------------------------------------------------------------------------------------------------------------------- + !> + subroutine Wings_ComputeCirculationPolarData(Gamma_LL, Gamma_LL_prev, p, x, m, AFInfo, GammaScale, ErrStat, ErrMsg, iLabel) + real(ReKi), dimension(:,:), intent(inout) :: Gamma_LL !< Circulation on all the lifting lines + real(ReKi), dimension(:,:), intent(in ) :: Gamma_LL_prev !< Previous/Guessed circulation + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_ContinuousStateType), intent(in ) :: x !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + real(ReKi), intent(in ) :: GammaScale !< Scaling factor used at init + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi), intent(in) :: iLabel + ! Local + real(ReKi), dimension(:,:), allocatable :: DGamma !< + real(ReKi), dimension(:,:), allocatable :: GammaLastIter !< + logical :: bConverged !< + integer(IntKi) :: iIter !< iteration step number + real(ReKi) :: MeanGamma + real(ReKi), dimension(:,:,:), allocatable :: Vcst !< Part of the velocity that is constant + real(ReKi), dimension(:,:,:), allocatable :: Vvar !< Part of the velocity that is varies due to the solve + integer(IntKi) :: iW, iSpan, iDepth, iWCP, nCPs + real(ReKi), dimension(3) :: P1, P2, P3, P4 + real(ReKi) :: Gamm + ! Error handling + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + !print*,'Parameters for circulation solv: ',p%CircSolvConvCrit ,p%CircSolvRelaxation ,p%CircSolvMaxIter + + allocate(DGamma (1:p%nSpan,1:p%nWings)) + allocate(GammaLastIter(1:p%nSpan,1:p%nWings)) + + ! --- Last iteration circulation + if (m%FirstCall) then + ! We find a guess by looking simply at the Wind and Elasticity velocity + m%Vtot_ll = m%Vwnd_LL - m%Vstr_ll + call CirculationFromPolarData(GammaLastIter, p, m, AFInfo,ErrStat2,ErrMsg2); if(Failed()) return; + else + ! NOTE: we need to inverse the scaling to speed up the convergence + if (.not. EqualRealNos(GammaScale, 0.0_ReKi)) then + GammaLastIter(1:p%nSpan,1:p%nWings) = Gamma_LL_prev(1:p%nSpan,1:p%nWings) / GammaScale + else + GammaLastIter(1:p%nSpan,1:p%nWings) = Gamma_LL_prev(1:p%nSpan,1:p%nWings) + endif + endif + + if (any(x%r_NW(1,:,1:m%nNW+1,:)<-999)) then + ErrMsg='Wings_ComputeCirculationPolarData: Problem in input NW points'; ErrStat=ErrID_Fatal; return + endif + + + ! --- Setting up Vcst: part of the velocity that is constant withing the iteration loop + ! Vrel_ll_cst = U_u0 - U_body + call AllocAry(Vvar, 3, p%nSpan, p%nWings, 'Vvar', ErrStat2, ErrMsg2); if(Failed()) return; + call AllocAry(Vcst, 3, p%nSpan, p%nWings, 'Vcst', ErrStat2, ErrMsg2); if(Failed()) return; + + ! Set m%Vind_LL Induced velocity from Known wake only (after iNWStart+1) + call LiftingLineInducedVelocities(p, x, iNWStart+1, m, ErrStat2, ErrMsg2); if(Failed()) return; + + Vcst = m%Vind_LL + m%Vwnd_LL - m%Vstr_ll + + if (any(m%Vind_LL(1:3,:,:)<-99)) then + ErrMsg='Wings_ComputeCirculationPolarData: Problem in induced velocity on LL points'; ErrStat=ErrID_Fatal; return + endif + if (any(m%Vwnd_LL(1:3,:,:)<-99)) then + ErrMsg='Wings_ComputeCirculationPolarData: Problem in wind velocity on LL points'; ErrStat=ErrID_Fatal; return + endif + + ! --- Convergence loop until near wake gives induction coherent with circulation + bConverged=.false. + iIter=0 + do while (.not.(bConverged) .and. iIter<p%CircSolvMaxIter) + !print*,'------- ITERATION',iIter + ! --- The induced velocity from the profiles is different at each iteration: + Vvar=0 + nCPs=p%nSpan + do iW=1,p%nWings + do iSpan=1,p%nSpan + do iDepth=1,iNWStart ! Two first panels + P1=x%r_NW(1:3,iSpan ,iDepth ,iW) + P2=x%r_NW(1:3,iSpan+1,iDepth ,iW) + P3=x%r_NW(1:3,iSpan+1,iDepth+1,iW) + P4=x%r_NW(1:3,iSpan ,iDepth+1,iW) + Gamm=GammaLastIter(iSpan, iW) + do iWCP=1,p%nWings + call ui_quad_n1(m%CP_LL(1:3,1:p%nSpan,iWCP), nCPs, P1, P2, P3, P4, Gamm, p%RegFunction, p%WingRegParam, Vvar(1:3,1:p%nSpan,iWCP)) + enddo + enddo + enddo + enddo + ! Total velocity on the lifting line + m%Vtot_ll = Vcst + Vvar + ! --- Computing circulation based on Vtot_LL + call CirculationFromPolarData(Gamma_LL, p, m, AFInfo,ErrStat2,ErrMsg2); if(Failed()) return; + + ! --------------------------------------------- + ! Differences between iterations and relaxation + DGamma=Gamma_LL-GammaLastIter + GammaLastIter=GammaLastIter+p%CircSolvRelaxation*DGamma + + iIter=iIter+1 + MeanGamma = sum(abs(GammaLastIter))/(p%nWings*p%nSpan) + bConverged = maxval(abs(DGamma))/(MeanGamma)<p%CircSolvConvCrit + + end do ! convergence loop + if (iIter==p%CircSolvMaxIter) then + if (DEV_VERSION) then + print'(A,I0,A,I0,A)','Circulation solve, call ',iLabel,', done after ........................ nIter: ', iIter, ' <<< Max reached' + endif + Gamma_LL=GammaLastIter ! returning relaxed value if not converged + else + if (DEV_VERSION) then + print'(A,I0,A,I0)','Circulation solve, call ',iLabel,', done after ........................ nIter: ', iIter + endif + ! We return Gamma_LL + endif + ! KEEP ME: --- ADP: removed m%iStep in favor of m%VTKstep + !iW=1 + !call Output_Gamma(m%CP_ll(1:3,:,iW), Gamma_LL(:,iW), iW, m%iStep, iLabel, iIter) + !call print_mean_3d( m%Vwnd_LL(:,:,:), 'Mean wind vel. LL (cst)') + !call print_mean_3d( m%Vstr_LL(:,:,:), 'Mean struct vel. LL (cst)') + !call print_mean_3d( m%Vind_LL(:,:,:), 'Mean induced vel. LL (cst)') + !call print_mean_3d( Vvar(:,:,:) , 'Mean induced vel. LL (var)') + !call print_mean_3d( Vvar+m%Vind_LL(:,:,:), 'Mean induced vel. LL (tot)') + !call print_mean_3d( m%Vtot_LL(:,:,:), 'Mean relativevel. LL (tot)') + !print*,'m%Vind_LL',m%Vind_LL(1,:,:) + !print*,'m%Vwnd_LL',m%Vwnd_LL(1,:,:) + !print*,'m%Vcst_LL',Vcst(1,:,:) + !print*,'Gamm: ',Gamma_LL(1, 1), Gamma_LL(p%nSpan,1) + m%Vind_LL=-9999._ReKi !< Safety (the induction above was not the true one) + m%Vtot_LL=-9999._ReKi !< Safety + call CleanUp() + contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Wings_ComputeCirculationPolarData') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + if(allocated(DGamma )) deallocate(DGamma ) + if(allocated(GammaLastIter)) deallocate(GammaLastIter) + if(allocated(Vcst)) deallocate(Vcst) + if(allocated(Vvar)) deallocate(Vvar) + end subroutine + end subroutine Wings_ComputeCirculationPolarData + + + !> Compute circulation based on polar data + !! Uses m%Vtot_ll to compute Gamma_ll + subroutine CirculationFromPolarData(Gamma_LL, p, m, AFInfo, ErrStat, ErrMsg) + real(ReKi), dimension(:,:), intent(inout) :: Gamma_LL !< Circulation on all the lifting lines + type(FVW_ParameterType), intent(in ) :: p !< Parameters + type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local + integer(IntKi) :: iW, iCP !< Index on wings and spanwise control points + real(ReKi), dimension(3) :: N, Tc !< Normal and Tangent vector + real(ReKi), dimension(3) :: Vrel, Vrel_orth, Vjouk, Vjouk_orth + real(ReKi) :: Vrel_orth_norm, Vjouk_orth_norm, Vrel_norm + real(ReKi) :: alpha, Re, Cl, Cd, Cm + type(AFI_OutputType) :: AFI_interp + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + do iW=1,p%nWings + do icp=1,p%nSpan + ! Aliases to shorten notations + N = m%Norm(1:3, icp, iW) + Tc = m%Tang(1:3, icp, iW) + Vrel = m%Vtot_LL(1:3,icp,iW) + ! "Orth": cross sectional plane of the lifting line + Vrel_orth(1:3) = dot_product(Vrel,N)*N + dot_product(Vrel,Tc)*Tc + Vrel_orth_norm = TwoNorm(Vrel_orth(1:3)) + Vjouk(1:3) = cross_product(Vrel,m%dl(1:3,icp,iW)) + Vjouk_orth(1:3) = dot_product(Vjouk,N)*N + dot_product(Vjouk,Tc)*Tc + Vjouk_orth_norm = TwoNorm(Vjouk_orth) + Vrel_norm = TwoNorm(Vrel) + + alpha = atan2(dot_product(Vrel,N) , dot_product(Vrel,Tc) ) ! [rad] + Re = p%Chord(icp,iW) * Vrel_norm / p%KinVisc / 1.0E6 + + !if (p%CircSolvPolar==idPolarAeroDyn) then + ! compute steady Airfoil Coefs ! NOTE: UserProp set to 0.0_ReKi (no idea what it does). Also, note this assumes airfoils at nodes. +!TODO: AFindx is on the nodes, not control points. + call AFI_ComputeAirfoilCoefs( alpha, Re, 0.0_ReKi, AFInfo(p%AFindx(icp,iW)), AFI_interp, ErrStat2, ErrMsg2 ); if(Failed()) return; + Cl = AFI_interp%Cl + Cd = AFI_interp%Cd + Cm = AFI_interp%Cm + ! Simple method: + ! Gamma_LL=(0.5 * Cl * Vrel_orth_norm*chord) + ! VanGarrel's method: + Gamma_LL(icp,iW) =(0.5_ReKi * Cl * Vrel_orth_norm**2*m%Area(icp,iW)/(Vjouk_orth_norm)) + ! Convenient storage + m%alpha_LL(icp, iW) = alpha ! [rad] + m%Vreln_LL(icp, iW) = Vrel_norm + enddo + enddo + contains + logical function Failed() + character(25) :: NodeText + if (ErrStat2 /= ErrID_None) then + NodeText = '(node '//trim(num2lstr(icp))//', blade '//trim(num2lstr(iW))//')' + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CirculationFromPolarData'//trim(NodeText)) + end if + Failed = ErrStat >= AbortErrLev + end function Failed + end subroutine CirculationFromPolarData + +end module FVW_Wings diff --git a/OpenFAST/modules/aerodyn/src/UA_Dvr_Subs.f90 b/OpenFAST/modules/aerodyn/src/UA_Dvr_Subs.f90 new file mode 100644 index 000000000..cb56cb264 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/UA_Dvr_Subs.f90 @@ -0,0 +1,621 @@ +module UA_Dvr_Subs + + use NWTC_Library + use AirfoilInfo + use AirfoilInfo_Types + use UnsteadyAero_Types + use UnsteadyAero + + implicit none + + + type UA_Dvr_InitInput + logical :: Echo + real(ReKi) :: SpdSound + character(1024) :: OutRootName + real(ReKi) :: InflowVel + integer :: UAMod + logical :: Flookup + logical :: UseCm + character(1024) :: AirFoil1 + real(ReKi) :: Chord + integer :: SimMod + real(ReKi) :: NCycles + real(ReKi) :: Frequency + real(ReKi) :: Re + integer :: StepsPerCycle + real(ReKi) :: Amplitude + real(ReKi) :: Mean + integer :: Phase + character(1024) :: InputsFile + end type UA_Dvr_InitInput + + contains + + subroutine ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) + + character(1024), intent( in ) :: inputFile + type(UA_Dvr_InitInput), intent( out ) :: InitInp + integer, intent( out ) :: ErrStat ! returns a non-zero value when an error occurs + character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + integer :: UnIn ! Unit number for the input file + integer :: UnEchoLocal ! The local unit number for this module's echo file + character(1024) :: EchoFile ! Name of HydroDyn echo file + character(1024) :: FileName ! Name of HydroDyn input file + + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'ReadDriverInputFile' + + ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input + UnEchoLocal = -1 + ErrStat = ErrID_None + ErrMsg = '' + FileName = trim(inputFile) + + call GetNewUnit( UnIn ) + call OpenFInpFile( UnIn, FileName, errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + call WrScr( ' Opening UnsteadyAero Driver input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + call ReadCom( UnIn, FileName, ' UnsteadyAero Driver input file header line 1', errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 2', errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! Echo Input Files. + + call ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + if ( InitInp%Echo ) then + + EchoFile = TRIM(FileName)//'.ech' + call GetNewUnit( UnEchoLocal ) + call OpenEcho ( UnEchoLocal, EchoFile, errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + rewind(UnIn) + + call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 1', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 2', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. + + call ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + end if + + !------------------------------------------------------------------------------------------------- + ! Environmental conditions section + !------------------------------------------------------------------------------------------------- + + ! Header + + call ReadCom( UnIn, FileName, 'Environmental conditions header', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! SpdSound - Speed of Sound. + + call ReadVar ( UnIn, FileName, InitInp%SpdSound, 'SpdSound', 'SpdSound', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + !------------------------------------------------------------------------------------------------- + ! UNSTEADYAERO section + !------------------------------------------------------------------------------------------------- + + ! Header + + call ReadCom( UnIn, FileName, 'UNSTEADYAERO header', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! OutRootName + call ReadVar ( UnIn, FileName, InitInp%OutRootName, 'OutRootName', & + 'UnsteadyAero output root filename', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! InflowVel + + call ReadVar ( UnIn, FileName, InitInp%InflowVel, 'InflowVel', & + 'Inflow velocity', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Re + + call ReadVar ( UnIn, FileName, InitInp%Re, 'Re', & + 'Reynolds number in millions', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! UAMod + call ReadVar ( UnIn, FileName, InitInp%UAMod, 'UAMod', & + 'Unsteady Aero Model Switch', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Flookup + call ReadVar ( UnIn, FileName, InitInp%Flookup, 'Flookup', & + "Lookup used to determine f'", errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + + + !------------------------------------------------------------------------------------------------- + ! AIRFOIL PROPERTIES section + !------------------------------------------------------------------------------------------------- + + ! Header + + call ReadCom( UnIn, FileName, 'AIRFOIL PROPERTIES header', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + + ! AirFoil1 + + call ReadVar ( UnIn, FileName, InitInp%AirFoil1, 'AirFoil1', & + 'Filename for the airfoil table and properties', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Chord + + call ReadVar ( UnIn, FileName, InitInp%Chord, 'Chord', & + 'Chord length', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Using Cm column + call ReadVar ( UnIn, FileName, InitInp%UseCm, 'UseCm', & + "Using Cm Airfoil table data", errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + !------------------------------------------------------------------------------------------------- + ! SIMULATION CONTROL section + !------------------------------------------------------------------------------------------------- + + ! Header + + call ReadCom( UnIn, FileName, 'SIMULATION CONTROL header', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + ! SimMod + call ReadVar ( UnIn, FileName, InitInp%SimMod, 'SimMod', & + 'Simulation model', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! NCycles + call ReadVar ( UnIn, FileName, InitInp%NCycles, 'NCycles', & + 'Number of cycles for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! StepsPerCycle + call ReadVar ( UnIn, FileName, InitInp%StepsPerCycle, 'StepsPerCycle', & + 'Number of timesteps per cycle', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Frequency + call ReadVar ( UnIn, FileName, InitInp%Frequency, 'Frequency', & + 'Frequency of angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Amplitude + call ReadVar ( UnIn, FileName, InitInp%Amplitude, 'Amplitude', & + 'Amplitude for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Mean + call ReadVar ( UnIn, FileName, InitInp%Mean, 'Mean', & + 'Mean for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! Phase + call ReadVar ( UnIn, FileName, InitInp%Phase, 'Phase', & + 'Initial phase for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + ! InputsFile + call ReadVar ( UnIn, FileName, InitInp%InputsFile, 'InputsFile', & + 'Filename for Time series data in an ASCII input file', errStat2, errMsg2, UnEchoLocal ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + call Cleanup() + + + contains + !==================================================================================================== + subroutine Cleanup() + ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + ! any existing echo information + !---------------------------------------------------------------------------------------------------- + ! logical, intent( in ) :: EchoFlag ! local version of echo flag + ! integer, intent( in ) :: UnEcho ! echo unit number + + ! Close this module's echo file + if ( InitInp%Echo ) then + close(UnEchoLocal) + end if + + close( UnIn ) + + end subroutine Cleanup + + + end subroutine ReadDriverInputFile + + subroutine ReadTimeSeriesData( inputsFile, nSimSteps, timeArr, AOAarr, Uarr, OmegaArr, ErrStat, ErrMsg ) + character(1024), intent( in ) :: inputsFile + integer, intent( out ) :: nSimSteps + real(DbKi),allocatable, intent( out ) :: timeArr(:) + real(ReKi),allocatable, intent( out ) :: AOAarr(:) + real(ReKi),allocatable, intent( out ) :: Uarr(:) !RRD + real(ReKi),allocatable, intent( out ) :: OmegaArr(:) + integer, intent( out ) :: ErrStat ! returns a non-zero value when an error occurs + character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + real(SiKi) :: dt + real(DbKi) :: tmpArr(4) + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'ReadTimeSeriesData' + character(1024) :: FileName + integer :: UnIn + integer :: i + integer, PARAMETER ::hdrlines=8 ! RRD + + ErrStat = ErrID_None + ErrMsg = '' + nSimSteps = 0 ! allocate here in case errors occur + + FileName = trim(inputsFile) + + call GetNewUnit( UnIn ) + call OpenFInpFile( UnIn, FileName, errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + + call WrScr( ' Opening UnsteadyAero time-series input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! Determine how many lines of data are in the file: + !------------------------------------------------------------------------------------------------- + do i=1,hdrlines !RRD + call ReadCom( UnIn, FileName, ' UnsteadyAero time-series input file header line 1', errStat2, errMsg2 ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + enddo + + do + call ReadAry( UnIn, FileName, tmpArr, 4, 'Data', 'Time-series data', errStat2, errMsg2 ) + ! The assumption is that the only parsing error occurs at the end of the file and therefore we stop reading data + if (errStat2 > ErrID_None) then + exit + else + nSimSteps = nSimSteps + 1 + end if + end do + + !------------------------------------------------------------------------------------------------- + ! Allocate arrays to be read + !------------------------------------------------------------------------------------------------- + allocate ( timeArr( nSimSteps ), STAT=ErrStat2 ) + if ( ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate timeArr.', ErrStat, ErrMsg, RoutineName) + call Cleanup() + return + end if + + allocate ( AOAarr( nSimSteps ), STAT=ErrStat2 ) + if ( ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate AOAarr.', ErrStat, ErrMsg, RoutineName) + call Cleanup() + return + end if + + allocate ( Uarr( nSimSteps ), OmegaArr( nSimSteps ), STAT=ErrStat2 ) + if ( ErrStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate Uarr and OmegaArr.', ErrStat, ErrMsg, RoutineName) + call Cleanup() + return + end if + + + !------------------------------------------------------------------------------------------------- + ! Read arrays from file + !------------------------------------------------------------------------------------------------- + rewind(UnIn) + do i=1,hdrlines !RRD + call ReadCom( UnIn, FileName, ' UnsteadyAero time-series input file header line 1', errStat2, errMsg2 ) + enddo + do i = 1,nSimSteps + call ReadAry( UnIn, FileName, tmpArr, 4, 'Data', 'Time-series data', errStat2, errMsg2 ) + timeArr(i) = tmpArr(1) + AOAarr(i) = real(tmpArr(2),ReKi) + Uarr(i) = real(tmpArr(3),ReKi) + OmegaArr(i) = real(tmpArr(4),ReKi) + end do + + if (nSimSteps > 1) then + dt = timeArr(2) - timeArr(1) + + do i = 2,nSimSteps-1 + if (.not. EqualRealNos(dt, REAL(timeArr(i+1)-timeArr(i), SiKi) ) ) then + call SetErrStat( ErrID_Fatal, 'Times in InputsFile must be contain the same delta t.', ErrStat, ErrMsg, RoutineName) + exit !exit the do loop + end if + end do + end if + + call Cleanup() + + contains + !==================================================================================================== + subroutine Cleanup() + ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + ! any existing echo information + !---------------------------------------------------------------------------------------------------- + ! logical, intent( in ) :: EchoFlag ! local version of echo flag + ! integer, intent( in ) :: UnEcho ! echo unit number + + ! Close this module's echo file + + + close( UnIn ) + + end subroutine Cleanup + end subroutine ReadTimeSeriesData +!-------------------------------------------------------------------------------------------------------------- + subroutine Init_AFI(p, NumAFfiles, afNames, UseCm, AFI_Params, ErrStat, ErrMsg) + + type(UA_ParameterType),intent(in) :: p + integer, intent(in ) :: NumAFfiles + CHARACTER(1024), intent(in ) :: afNames(NumAFfiles) + logical, intent(in ) :: UseCm + type(AFI_ParameterType), intent( out) :: AFI_Params(NumAFfiles) + integer(IntKi), intent( out) :: ErrStat ! Error status. + character(*), intent( out) :: ErrMsg ! Error message. + + + type(AFI_InitInputType) :: AFI_InitInputs + integer :: UnEc + integer :: i + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'Init_AFI' + + ! Initialize the Airfoil Info module + ! Setup Airfoil info + + UnEc = 0 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Set this to 1 to use the UA coefs + !AFI_InitInputs%UA_Model = 1 + ! This is the number of columns of coefs in the AOA table: Cl, Cd, Cm, for example, but doesn't include Alpha + !AFI_InitInputs%NumCoefs = 3 + ! + AFI_InitInputs%InCol_Alfa = 1 + AFI_InitInputs%InCol_Cl = 2 + AFI_InitInputs%InCol_Cd = 3 + if (UseCm) then + AFI_InitInputs%InCol_Cm = 4 + else + AFI_InitInputs%InCol_Cm = 0 + end if + + AFI_InitInputs%InCol_Cpmin = 0 + AFI_InitInputs%AFTabMod = AFITable_1 ! 1D-interpolation (on AoA only) + + + do i=1,NumAFfiles + AFI_InitInputs%FileName = afNames(i) !InitInp%AF_File(i) + + ! Call AFI_Init to read in and process the airfoil files. + ! This includes creating the spline coefficients to be used for interpolation. + + call AFI_Init ( AFI_InitInputs, AFI_Params(i), errStat2, errMsg2, UnEc ) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + end do + + + + do i=1,NumAFfiles + + call UA_ValidateAFI(p%UAMod, AFI_Params(i), afNames(i), ErrStat2, ErrMsg2) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + + call UA_TurnOff_param(p, AFI_Params(i), ErrStat2, ErrMsg2) + call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) + end do + + call Cleanup() + + + contains + + !==================================================================================================== + subroutine Cleanup() + ! The routine cleans up data arrays framework structures + ! + !---------------------------------------------------------------------------------------------------- + + + + !Clean up initialization inputs + call AFI_DestroyInitInput(AFI_InitInputs, errStat2, errMsg2) + + + + end subroutine Cleanup + end subroutine Init_AFI + + + + + + + + + + + + + + +end module UA_Dvr_Subs + \ No newline at end of file diff --git a/OpenFAST/modules/aerodyn/src/UnsteadyAero.f90 b/OpenFAST/modules/aerodyn/src/UnsteadyAero.f90 new file mode 100644 index 000000000..d24a730da --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/UnsteadyAero.f90 @@ -0,0 +1,2610 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! This file is part of AeroDyn. +! +! 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 UnsteadyAero + + ! This module uses equations defined in the document "The Unsteady Aerodynamics Module for FAST 8" by Rick Damiani and Greg Hayman, 28-Feb-2017 + + use NWTC_Library + use UnsteadyAero_Types + use AirfoilInfo + + implicit none + +private + + + public :: UA_Init + public :: UA_UpdateDiscOtherState + public :: UA_UpdateStates + public :: UA_CalcOutput + public :: UA_CalcContStateDeriv + + public :: UA_ReInit + public :: UA_ValidateAFI + public :: UA_TurnOff_param + public :: UA_TurnOff_input + public :: UA_InitStates_AllNodes + + integer(intki), parameter :: UA_Baseline = 1 ! UAMod = 1 [Baseline model (Original)] + integer(intki), parameter :: UA_Gonzalez = 2 ! UAMod = 2 [Gonzalez's variant (changes in Cn,Cc,Cm)] + integer(intki), parameter :: UA_MinnemaPierce = 3 ! UAMod = 3 [Minnema/Pierce variant (changes in Cc and Cm)] + integer(intki), parameter, public :: UA_HGM = 4 ! UAMod = 4 [continuous variant of HGM (Hansen) model] + + real(ReKi), parameter :: Gonzalez_factor = 0.2_ReKi ! this factor, proposed by Gonzalez (for "all" models) is used to modify Cc to account for negative values seen at f=0 (see Eqn 1.40) + + contains + +! ************************************************** +FUNCTION SAT( X, VAL, SLOPE ) + ! AOA saturation function 02/15/98 + ! ************************************************** + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi) :: SAT +REAL(ReKi),INTENT(IN) :: SLOPE +REAL(ReKi),INTENT(IN) :: VAL +REAL(ReKi),INTENT(IN) :: X + + +IF ( ABS(X) <= VAL ) THEN + SAT = X +ELSEIF ( X > VAL) THEN + SAT = SLOPE * X + VAL * ( 1. - SLOPE ) +ELSE + SAT = SLOPE * X - VAL * ( 1. - SLOPE ) +ENDIF + + +RETURN +END FUNCTION SAT + + + +!============================================================================== +!> Compute the deficiency function: +!! \f$ Y_n = Y_{n-1} \exp \left(-\frac{\Delta t}{T}\right)+\left(x_n - x_{n-1}\right)\exp\left(-\frac{\Delta t}{2T}\right)\f$ +real(ReKi) function Get_ExpEqn( dt, T, Y_minus1, x, x_minus1 ) +! Called by : ComputeKelvinChain +! Calls to : NONE +!.............................................................................. + + real(ReKi), intent(in ) :: dt !< numerator of the exponent, \f$\Delta t \f$ + real(ReKi), intent(in ) :: T !< denominator of the exponent (time constant), \f$T\f$ + real(ReKi), intent(in ) :: Y_minus1 !< previous value of the computed decay function, \f$ Y_{n-1} \f$ + real(ReKi), intent(in ) :: x !< current value of x, \f$x_n\f$ + real(ReKi), intent(in ) :: x_minus1 !< previous value of x, \f$x_{n-1}\f$ + + real(ReKi) :: tmp + + tmp = -dt/T ! tmp should always be negative... should we check this, or are there some physics that make this check unnecessary? + + Get_ExpEqn = Y_minus1*exp(tmp) + (x - x_minus1)*exp(0.5_ReKi*tmp) + +end function Get_ExpEqn +!============================================================================== + + +!============================================================================== +! TE Flow Separation Equations ! +!============================================================================== + +!============================================================================== +subroutine Get_f_from_Lookup( UAMod, Re, UserProp, alpha_in, alpha0, C_nalpha_circ, AFInfo, ErrStat, ErrMsg, f, cn_fs) +! Compute either fprime or fprimeprime using an analytical equation (and eventually a table lookup) +! Called by : ComputeKelvinChain +! Calls to : NONE +!.............................................................................. + integer, intent(in ) :: UAMod + real(ReKi), intent(in ) :: Re ! Reynolds number + real(ReKi), intent(in ) :: UserProp ! User property for interpolating AFI + real(ReKi), intent(in ) :: alpha_in ! angle of attack (radians) + real(ReKi), intent(in ) :: alpha0 + real(ReKi), intent(in ) :: C_nalpha_circ + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(ReKi),optional, intent( out) :: f + real(ReKi),optional, intent( out) :: cn_fs + + real(ReKi) :: f_st + + real(ReKi) :: Cn, tmpRoot, denom + type(AFI_OutputType) :: AFI_Interp + + + real(ReKi) :: alpha ! angle of attack (radians) + real(ReKi) :: alpha_minus_alpha0 + + ErrStat = ErrID_None + ErrMsg = '' + ! NOTE: This subroutine call cannot live in Blade Element because BE module calls UnsteadyAero module. + + + ! this routine is solving Eqn 1.32 for f: + ! cn = C_nalpha_circ * (alpha-alpha0) * ((1+sqrt(f))/2)**2 + + + !bjj: if cn = 0 or c_nalpha_circ = 0 or alpha=alpha0, f has infinitely many solutions to this equation + + ! ensure that these angles are in appropriate ranges + alpha = alpha_in + + call MPi2Pi(alpha) + + alpha_minus_alpha0 = alpha - alpha0 + call MPi2Pi(alpha_minus_alpha0) + + call AFI_ComputeAirfoilCoefs( alpha, Re, UserProp, AFInfo, AFI_interp, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev ) return + + Cn = AFI_interp%Cl*cos(alpha) + (AFI_interp%Cd-AFI_interp%Cd0)*sin(alpha) + + + if (EqualRealNos( real(c_nalpha_circ,SiKi), 0.0_SiKi )) then + tmpRoot = 0.0_ReKi + else if (EqualRealNos( real(alpha,SiKi), real(alpha0,SiKi) )) then + tmpRoot = 0.0_ReKi + else + + + if (EqualRealNos( real(cn,SiKi), 0.0_SiKi )) then + tmpRoot = 0.0_ReKi + else + + denom = (C_nalpha_circ*alpha_minus_alpha0) + + ! bjj: if tmpRoot=cn/(C_nalpha_circ*(alpha-alpha0)) is negative, this whole equation is bogus.... + tmpRoot = Cn/denom + + if (tmpRoot < 0.0_ReKi) then + tmpRoot = 0.0_ReKi + end if + + end if + + end if + + if (UAMod == UA_Gonzalez) then + f_st = ((3.0_ReKi * sqrt(tmpRoot)-1.0_ReKi)/ 2.0_ReKi )**2 + else + f_st = ( 2.0_ReKi * sqrt( tmpRoot ) - 1.0_ReKi )**2 + end if + + + if ( f_st > 1.0 ) then + f_st = 1.0_ReKi + end if + + if (present(f)) then + f = f_st + end if + + if (present(cn_fs)) then + if (equalRealNos(f_st,1.0_ReKi)) then + cn_fs = 0.0_ReKi + else + cn_fs = (Cn - C_nalpha_circ * alpha_minus_alpha0 * f_st) / (1.0_ReKi-f_st); ! modification by Envision Energy + end if + end if + +end subroutine Get_f_from_Lookup +!============================================================================== + +!============================================================================== +real(ReKi) function Get_f_c_from_Lookup( UAMod, Re, UserProp, alpha_in, alpha0_in, c_nalpha_circ, eta_e, AFInfo, ErrStat, ErrMsg) +! Compute either fprime or fprimeprime using an analytical equation (and eventually a table lookup) +! Called by : ComputeKelvinChain +! Calls to : NONE +!.............................................................................. + integer, intent(in ) :: UAMod + real(ReKi), intent(in ) :: Re ! Reynolds number + real(ReKi), intent(in ) :: UserProp ! User property for 2D AFI interpolation + real(ReKi), intent(in ) :: alpha_in ! angle of attack (radians) + real(ReKi), intent(in ) :: alpha0_in + real(ReKi), intent(in ) :: c_nalpha_circ + real(ReKi), intent(in ) :: eta_e + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + real(ReKi), parameter :: fc_limit = (1.0_ReKi + Gonzalez_factor)**2 ! normally, fc is limited by 1, but we're limiting (sqrt(fc)-Gonzalez_factor) to 1, so fc is limited to 1.44 instead (when Gonzalez_factor is 0.2) + real(ReKi) :: Cc, denom + type(AFI_OutputType) :: AFI_Interp + + real(ReKi) :: alpha ! angle of attack (radians) + real(ReKi) :: alpha0 + + ErrStat = ErrID_None + ErrMsg = '' + ! NOTE: This subroutine call cannot live in Blade Element because BE module calls UnsteadyAero module. + + ! ensure that these angles are in appropriate ranges + alpha = alpha_in + alpha0 = alpha0_in + + call MPi2Pi(alpha) + call MPi2Pi(alpha0) + + ! in cases where denom is zero, Get_f_c_from_Lookup = min(fc_limit, inf) + if (EqualRealNos(real(alpha,SiKi), 0.0_SiKi)) then + + Get_f_c_from_Lookup = fc_limit + + elseif (EqualRealNos(real(alpha,SiKi), real(alpha0,SiKi))) then + + Get_f_c_from_Lookup = fc_limit + + else if (EqualRealNos( real(c_nalpha_circ,SiKi), 0.0_SiKi )) then + + Get_f_c_from_Lookup = fc_limit + + else + + call AFI_ComputeAirfoilCoefs( alpha, Re, UserProp, AFInfo, AFI_interp, ErrStat, ErrMsg) + if (ErrStat >= AbortErrLev) return + + Cc = AFI_interp%Cl*sin(alpha) - (AFI_interp%Cd-AFI_interp%Cd0)*cos(alpha) + + + if (UAMod == UA_Gonzalez) then + denom = eta_e*c_nalpha_circ*( alpha-alpha0 )*(alpha) !NOTE: Added back (alpha) because idling cases with alpha 90-degrees show problems with tan(alpha), the code should match steady state if the formulation in the calculation of Cc is in agreement with this formulation + else + denom = eta_e*c_nalpha_circ*( alpha-alpha0 )*tan(alpha) + endif + Get_f_c_from_Lookup = min(fc_limit, ( Cc / denom + Gonzalez_factor ) **2 ) + end if + ! Apply an offset of Gonzalez_factor = 0.2 to fix cases where f_c should be negative, but we are using **2 so can only return positive values + ! Note: because we include this offset, it must be accounted for in the final value of Cc, eqn 1.40. This will be applied + ! For both UA_Mod = 1,2, and 3 when using Flookup = T + + +end function Get_f_c_from_Lookup + +!============================================================================== +real(ReKi) function Get_f( alpha, alpha0, alpha1, alpha2, S1, S2, S3, S4 ) +! Compute fprime, implements Eqn 1.33 +! Called by : ComputeKelvinChain +!.............................................................................. + + real(ReKi), intent(in ) :: alpha ! angle of attack (radians) + real(ReKi), intent(in ) :: alpha0 ! zero lift angle of attack (radians) + real(ReKi), intent(in ) :: alpha1 ! angle of attack at f = 0.7, approximately the stall angle; for alpha >= alpha0 (radians) + real(ReKi), intent(in ) :: alpha2 ! angle of attack at f = 0.7, approximately the stall angle; for alpha < alpha0 (radians) + real(ReKi), intent(in ) :: S1 ! constant in the f-curve best-fit, alpha >= alpha0 + real(ReKi), intent(in ) :: S2 ! constant in the f-curve best-fit, alpha >= alpha0 + real(ReKi), intent(in ) :: S3 ! constant in the f-curve best-fit, alpha < alpha0 + real(ReKi), intent(in ) :: S4 ! constant in the f-curve best-fit, alpha < alpha0 + + + ! Implements Equation 1.33 + if (alpha > alpha1) then + Get_f = 0.04_ReKi + 0.66_ReKi*exp((alpha1-alpha)/S2) + else if (alpha < alpha2) then + Get_f = 0.04_ReKi + 0.66_ReKi*exp((alpha-alpha2)/S4) + else if (alpha>= alpha0) then !alpha0<=alpha<=alpha1 + Get_f = 1.0_ReKi - 0.3_ReKi*exp((alpha-alpha1)/S1) + else ! alpha2<= alpha < alpha0 + Get_f = 1.0_ReKi - 0.3_ReKi*exp((alpha2-alpha)/S3) + end if + +end function Get_f +!============================================================================== +subroutine ComputeKelvinChain( i, j, u, p, xd, OtherState, misc, AFInfo, KC, BL_p, ErrStat, ErrMsg ) +! +! Called by : DRIVER +! Calls to : Get_Beta_M_Sqrd, Get_Beta_M, AFI_ComputeUACoefs, Get_ds, Get_Pitchrate, Get_k_, Get_Kupper, Get_ExpEqn +! Get_Cn_nc, Get_alpha_e, Get_Cm_q_circ, Get_Cm_q_nc, Get_f, Get_Cn_FS, Get_C_V, Get_Cn_v +!............................................................................... + + + integer(IntKi), intent(in ) :: i,j ! Blade node indices + type(UA_InputType), intent(in ) :: u ! Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_DiscreteStateType), intent(in ) :: xd ! Input: Discrete states at t; + type(UA_OtherStateType), intent(in ) :: OtherState ! Other states at t + type(UA_MiscVarType), intent(inout) :: misc ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + + + type(AFI_UA_BL_Type), intent( out) :: BL_p + + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + type(UA_KelvinChainType), intent( out) :: KC + + real(ReKi) :: M ! Mach number (-) + real(ReKi) :: beta_M ! Prandtl-Glauert compressibility correction factor, sqrt(1-M**2) + real(ReKi) :: beta_M_Sqrd ! square of the Prandtl-Glauert compressibility correction factor, (1-M**2) + + real(ReKi) :: Cn_temp + real(ReKi) :: Cn_fs_temp + + type(AFI_OutputType) :: AFI_interp ! Cl, Cd, Cm, Cpmin + + real(ReKi) :: T_I ! + real(ReKi) :: Kalpha ! + real(ReKi) :: Kalpha_f_minus1 ! + real(ReKi) :: Kq_f_minus1 ! + real(ReKi) :: alpha_minus1 ! + real(ReKi) :: alpha_filt_minus1 ! + real(ReKi) :: q_minus1 ! + real(ReKi) :: q_f_minus1 + real(ReKi) :: Cn_pot_minus1 ! + real(ReKi) :: K3prime_q ! + real(ReKi) :: k_mq ! + real(ReKi) :: Kprimeprime_q ! + real(ReKi) :: dynamicFilterCutoffHz ! find frequency based on reduced frequency of k = BL_p%filtCutOff + real(ReKi) :: LowPassConst + + +#ifdef TEST_THEORY + real(ReKi) :: Cn_prime_diff +#endif + + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'ComputeKelvinChain' + + ErrStat = ErrID_None + ErrMsg = "" + + KC%fprimeprime_m = 0 + + M = u%U / p%a_s + call UA_CheckMachNumber(M, misc%FirstWarn_M, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + beta_M_Sqrd = 1.0_ReKi - M**2 + beta_M = sqrt(beta_M_Sqrd) + + ! Lookup values using Airfoil Info module + call AFI_ComputeUACoefs( AFInfo, u%Re, u%UserProp, BL_p, ErrMsg2, ErrStat2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + KC%C_nalpha_circ = BL_p%C_nalpha / beta_M + + ! Override eta_e if we are using Flookup + if ( p%Flookup ) then + BL_p%eta_e = 1.0 + end if + + ! Kelvin chain + KC%ds = 2.0_ReKi*u%U*p%dt/p%c(i,j) ! Eqn 1.5b + + if (OtherState%FirstPass(i,j)) then + alpha_minus1 = u%alpha + alpha_filt_minus1 = u%alpha + else + alpha_minus1 = xd%alpha_minus1(i,j) + alpha_filt_minus1 = xd%alpha_filt_minus1(i,j) + end if + + ! Low Pass filtering of alpha, q, and Kq in order to deal with numerical issues that arise for very small values of dt + ! See equations 1.7 and 1.8 of the manual + ! This filter is a Simple Infinite Impulse Response Filter + ! See https://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter + + dynamicFilterCutoffHz = max( 1.0_ReKi, u%U ) * BL_p%filtCutOff / PI / p%C(i,j) + LowPassConst = exp(-2.0_ReKi*PI*p%dt*dynamicFilterCutoffHz) ! from Eqn 1.8 [7] + + KC%alpha_filt_cur = LowPassConst*alpha_filt_minus1 + (1.0_ReKi-LowPassConst)*u%alpha ! from eq 1.8 [1: typo in documentation, though] + + + KC%dalpha0 = KC%alpha_filt_cur - BL_p%alpha0 + + ! Compute Kalpha using Eqn 1.7 + + Kalpha = ( KC%alpha_filt_cur - alpha_filt_minus1 ) / p%dt ! Eqn 1.7, using filtered values of alpha + + if (OtherState%FirstPass(i,j)) then + Kalpha_f_minus1 = 0.0_ReKi + else + Kalpha_f_minus1 = xd%Kalpha_f_minus1(i,j) + end if + + KC%q_cur = Kalpha * p%c(i,j) / u%U ! Kalpha here uses the low-pass filtered alphas (Eqn 1.8 [2]) + + + if (OtherState%FirstPass(i,j)) then + q_minus1 = KC%q_cur + q_f_minus1 = KC%q_cur + else + q_minus1 = xd%q_minus1(i,j) + q_f_minus1 = xd%q_f_minus1(i,j) + end if + + KC%q_f_cur = LowPassConst*q_f_minus1 + (1.0_ReKi-LowPassConst)*KC%q_cur ! (Eqn 1.8 [3]) + + +#ifdef TEST_THEORY + ! Change found in ADv14 + KC%q_f_cur = SAT( KC%q_f_cur, 0.03_ReKi, 0.1_ReKi ) +#endif + + KC%Kalpha_f = KC%q_f_cur * u%U / p%c(i,j) ! Kalpha_f is using the low-pass filtered q (Eqn. 1.8 [4]) + + + ! Compute Kq using Eqn 1.8 with time-shifted q s +#ifdef TEST_THEORY + KC%Kq = ( KC%q_f_cur - q_f_minus1 ) / p%dt !bjj: jmj questions if this should be the way it's implemented +#else + + KC%Kq = ( KC%q_cur - q_minus1 ) / p%dt ! Eqn. 1.8 [5] +#endif + + if (OtherState%FirstPass(i,j)) then + Kq_f_minus1 = 0.0_ReKi + else + Kq_f_minus1 = xd%Kq_f_minus1(i,j) + end if + + KC%Kq_f = LowPassConst*Kq_f_minus1 + (1.0_ReKi-LowPassConst)*KC%Kq !Eqn. 1.8 [6] + + + !bjj: todo: should we check the denominator to make sure it doesn't go to 0? + + KC%k_alpha = 1.0_ReKi / ( (1.0_ReKi - M) + (BL_p%C_nalpha/2.0_ReKi) * M**2 * beta_M * (BL_p%A1*BL_p%b1 + BL_p%A2*BL_p%b2) ) ! Eqn 1.11a + KC%k_q = 1.0_ReKi / ( (1.0_ReKi - M) + BL_p%C_nalpha * M**2 * beta_M * (BL_p%A1*BL_p%b1 + BL_p%A2*BL_p%b2) ) ! Eqn 1.11b + T_I = p%c(i,j) / p%a_s ! Eqn 1.11c + + KC%T_alpha = T_I * KC%k_alpha * 0.75 ! Eqn 1.10a + KC%T_q = T_I * KC%k_q * 0.75 ! Eqn 1.10b + + KC%T_f = BL_p%T_f0 / OtherState%sigma1(i,j) ! Eqn 1.37 + KC%T_fc = BL_p%T_f0 / OtherState%sigma1c(i,j) ! NOTE: Added equations for time constants of fc (for Cc) and fm (for Cm) with UAMod=2 + KC%T_fm = BL_p%T_f0 / OtherState%sigma1m(i,j) + + KC%Kprime_alpha = Get_ExpEqn( real(p%dt,ReKi), KC%T_alpha, xd%Kprime_alpha_minus1(i,j), KC%Kalpha_f, Kalpha_f_minus1 ) ! Eqn 1.18b + KC%Cn_alpha_nc = 4.0_ReKi*KC%T_alpha * ( KC%Kalpha_f - KC%Kprime_alpha ) / M ! Eqn 1.18a + + KC%Kprime_q = Get_ExpEqn( real(p%dt,ReKi), KC%T_q , xd%Kprime_q_minus1(i,j) , KC%Kq_f , Kq_f_minus1 ) ! Eqn 1.19b + KC%Cn_q_nc = -1.0_ReKi*KC%T_q * ( KC%Kq_f - KC%Kprime_q ) / M ! Eqn 1.19a + + KC%Cn_alpha_q_nc = KC%Cn_alpha_nc + KC%Cn_q_nc ! Eqn 1.17 + +if (p%ShedEffect) then + KC%X1 = Get_ExpEqn( KC%ds*beta_M_Sqrd*BL_p%b1, 1.0_ReKi, xd%X1_minus1(i,j), BL_p%A1*(KC%alpha_filt_cur - alpha_filt_minus1), 0.0_ReKi ) ! Eqn 1.15a + KC%X2 = Get_ExpEqn( KC%ds*beta_M_Sqrd*BL_p%b2, 1.0_ReKi, xd%X2_minus1(i,j), BL_p%A2*(KC%alpha_filt_cur - alpha_filt_minus1), 0.0_ReKi ) ! Eqn 1.15b +else + KC%X1 = 0.0_ReKi ! u%alpha (and alpha_filt_cur) contains shed vorticity effect already + KC%X2 = 0.0_ReKi ! so that alpha_e = u%alpha-alpha0 directly +endif + + KC%alpha_e = (KC%alpha_filt_cur - BL_p%alpha0) - KC%X1 - KC%X2 ! Eqn 1.14 + + KC%Cn_alpha_q_circ = KC%C_nalpha_circ * KC%alpha_e ! Eqn 1.13 + + if ( p%UAMod == UA_Gonzalez ) then + ! Compute X3 and X4 using Eqn 1.16a and then add Cn_q_circ (Eqn 1.16) to the previously computed Cn_alpha_q_circ +if (p%ShedEffect) then + KC%X3 = Get_ExpEqn( KC%ds*beta_M_Sqrd*BL_p%b1, 1.0_ReKi, xd%X3_minus1(i,j), BL_p%A1*(KC%q_f_cur - q_f_minus1), 0.0_ReKi ) ! Eqn 1.16a [1] + KC%X4 = Get_ExpEqn( KC%ds*beta_M_Sqrd*BL_p%b2, 1.0_ReKi, xd%X4_minus1(i,j), BL_p%A2*(KC%q_f_cur - q_f_minus1), 0.0_ReKi ) ! Eqn 1.16a [2] +else + KC%X3 = 0.0_ReKi ! Similar to X1 and X2, we assumed that this effect is already included + KC%X4 = 0.0_ReKi +endif + + KC%Cn_q_circ = KC%C_nalpha_circ*KC%q_f_cur/2.0 - KC%X3 - KC%X4 ! Eqn 1.16 + + else ! these aren't used (they are possibly output to UA_OUT file, though) + KC%X3 = 0.0_ReKi + KC%X4 = 0.0_ReKi + KC%Cn_q_circ = 0.0_ReKi + end if + + K3prime_q = Get_ExpEqn( BL_p%b5*beta_M_Sqrd*KC%ds, 1.0_ReKi, xd%K3prime_q_minus1(i,j), BL_p%A5*(KC%q_f_cur - q_f_minus1), 0.0_ReKi ) ! Eqn 1.26 + KC%Cm_q_circ = -BL_p%C_nalpha*(KC%q_f_cur - K3prime_q)*p%c(i,j)/(16.0_ReKi*beta_M*u%U) ! Eqn 1.25 + + KC%Cn_pot = KC%Cn_alpha_q_circ + KC%Cn_alpha_q_nc ! Eqn 1.20 [2a] + + k_mq = 7.0_ReKi / (15.0_ReKi*(1.0_ReKi-M) + 1.5_ReKi * BL_p%C_nalpha * BL_p%A5 * BL_p%b5 * beta_M * M**2) ! Eqn 1.29 [2] ! CHECK THAT DENOM ISN'T ZERO! + Kprimeprime_q = Get_ExpEqn( real(p%dt,ReKi), k_mq**2*T_I , xd%Kprimeprime_q_minus1(i,j) , KC%Kq_f , Kq_f_minus1 ) ! Eqn 1.29 [3] + + ! Compute Cm_q_nc + if ( p%UAMod == UA_MinnemaPierce ) then + KC%Cm_q_nc = -1.0_ReKi * KC%Cn_q_nc / 4.0_ReKi - (KC%k_alpha**2) * T_I * (KC%Kq_f - Kprimeprime_q) / (3.0_ReKi*M) ! Eqn 1.31 + else + KC%Cm_q_nc = -7.0_ReKi * (k_mq**2) * T_I * (KC%Kq_f - Kprimeprime_q) / (12.0_ReKi*M) ! Eqn 1.29 [1] + end if + + if ( p%UAMod == UA_Gonzalez ) then + KC%Cc_pot = KC%C_nalpha_circ * KC%alpha_e * u%alpha !Added this equation with (u%alpha) instead of tan(alpha_e+alpha0). First, tangent gives problems in idling conditions at angles of attack of 90 degrees. Second, the angle there is a physical concept according to the original BL model, and u%alpha could be more suitable + else + !!! THIS IS A PROBLEM IF KC%alpha_e+BL_p%alpha0 ARE NEAR +/-PI/2 + KC%Cc_pot = KC%Cn_alpha_q_circ * tan(KC%alpha_e+BL_p%alpha0) ! Eqn 1.21 with cn_pot_circ=KC%Cn_alpha_q_circ as from Eqn 1.20 [3] + endif + + if (OtherState%FirstPass(i,j)) then + Cn_pot_minus1 = KC%Cn_pot + else + Cn_pot_minus1 = xd%Cn_pot_minus1(i,j) + end if + + KC%Dp = Get_ExpEqn( KC%ds, BL_p%T_p, xd%Dp_minus1(i,j), KC%Cn_pot, Cn_pot_minus1 ) ! Eqn 1.35b + KC%Cn_prime = KC%Cn_Pot - KC%Dp ! Eqn 1.35a + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! This code is taken from ADv14 but doesn't reflect the original intent of the UA theory document +#ifdef TEST_THEORY + if (OtherState%FirstPass(i,j)) then + Cn_prime_diff = 0.0_ReKi + else + Cn_prime_diff = KC%Cn_prime - xd%Cn_prime_minus1(i,j) + end if + +IF ( p%UAMod /= UA_Gonzalez ) THEN + IF ( KC%alpha_filt_cur * Cn_prime_diff < 0. ) THEN + + KC%T_f = BL_p%T_f0*1.5 + ELSE + + KC%T_f = BL_p%T_f0 + ENDIF +ENDIF +#endif +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + KC%alpha_f = KC%Cn_prime / KC%C_nalpha_circ + BL_p%alpha0 ! Eqn 1.34 + + if (p%flookup) then + call Get_f_from_Lookup( p%UAMod, u%Re, u%UserProp, KC%alpha_f, BL_p%alpha0, KC%C_nalpha_circ, AFInfo, ErrStat2, ErrMsg2, f=KC%fprime) ! Solve Eqn 1.32a for f (=KC%fprime) when alpha is replaced with alpha_f (see issue when KC%C_nalpha_circ is 0) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + else + KC%fprime = Get_f( KC%alpha_f, BL_p%alpha0, BL_p%alpha1, BL_p%alpha2, BL_p%S1, BL_p%S2, BL_p%S3, BL_p%S4) ! Eqn 1.33 + end if + + if (OtherState%FirstPass(i,j)) then + KC%Df = 0.0_ReKi + else + KC%Df = Get_ExpEqn( KC%ds, KC%T_f, xd%Df_minus1(i,j), KC%fprime, xd%fprime_minus1(i,j) ) ! Eqn 1.36b + end if + + KC%fprimeprime = KC%fprime - KC%Df ! Eqn 1.36a + + if (p%Flookup) then + ! Compute fprime using Eqn 1.32 and Eqn 1.33 + KC%fprime_c = Get_f_c_from_Lookup( p%UAMod, u%Re, u%UserProp, KC%alpha_f, BL_p%alpha0, KC%C_nalpha_circ, BL_p%eta_e, AFInfo, ErrStat2, ErrMsg2) ! Solve Eqn 1.32b for f when alpha is replaced with alpha_f + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + if ( p%UAMod == UA_Gonzalez ) then !Added this part of the code to obtain fm + call AFI_ComputeAirfoilCoefs( KC%alpha_f, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + Cn_temp = AFI_interp%Cl*cos(KC%alpha_f) + (AFI_interp%Cd - AFI_interp%Cd0)*sin(KC%alpha_f) + if (abs(Cn_temp) < 0.01_ReKi ) then + KC%fprime_m = 0.0_ReKi + else + KC%fprime_m = (AFI_interp%Cm - AFI_interp%Cm0) / Cn_temp + end if + else + KC%fprime_m = 0.0_ReKi + endif + + + if (OtherState%FirstPass(i,j)) then + KC%Df_c = 0.0_ReKi + KC%Df_m = 0.0_ReKi + else + KC%Df_c = Get_ExpEqn( KC%ds, KC%T_fc, xd%Df_c_minus1(i,j), KC%fprime_c, xd%fprime_c_minus1(i,j) ) + KC%Df_m = Get_ExpEqn( KC%ds, KC%T_fm, xd%Df_m_minus1(i,j), KC%fprime_m, xd%fprime_m_minus1(i,j) ) ! used in UAMod=UA_Gonzalez only + end if + + ! Compute Df using Eqn 1.36b + + ! Compute fprimeprime using Eqn 1.36a + KC%fprimeprime_c = KC%fprime_c - KC%Df_c + + IF ( p%UAMod == UA_Gonzalez ) THEN + KC%fprimeprime_m = KC%fprime_m - KC%Df_m + END IF + else + KC%fprime_c = KC%fprime + KC%Df_c = KC%Df + KC%fprimeprime_c = KC%fprimeprime + + ! variables used for UAMod=UA_Gonzalez + KC%fprime_m = 0.0_ReKi + KC%Df_m = 0.0_ReKi + KC%fprimeprime_m = KC%fprimeprime + end if + + + if ( p%UAMod == UA_Gonzalez ) then + KC%Cn_FS = KC%Cn_alpha_q_nc + KC%Cn_q_circ + KC%Cn_alpha_q_circ * ( (1.0_ReKi + 2.0_ReKi*sqrt(KC%fprimeprime) ) / 3.0_ReKi )**2 ! Eqn 1.39 + else + ! change proposed by Pariya: + ! KC%Cn_FS = KC%Cn_alpha_q_nc + KC%Cn_alpha_q_circ * ( (1.0_ReKi + sqrt(KC%fprimeprime) ) / 2.0_ReKi )**2 ! Eqn 1.38 + call Get_f_from_Lookup( p%UAMod, u%Re, u%UserProp, KC%alpha_e+BL_p%alpha0, BL_p%alpha0, KC%C_nalpha_circ, AFInfo, ErrStat2, ErrMsg2, cn_fs=Cn_fs_temp) + KC%Cn_FS = KC%Cn_alpha_q_nc + KC%C_nalpha_circ * KC%alpha_e*KC%fprimeprime + Cn_fs_temp*(1-KC%fprimeprime) + end if + + if ( p%UAMod == UA_MinnemaPierce ) then + if (OtherState%FirstPass(i,j)) then + KC%Dalphaf = 0.0_ReKi + else + KC%Dalphaf = Get_ExpEqn( KC%ds, 0.1_ReKi*KC%T_f, xd%Dalphaf_minus1(i,j), KC%alpha_f, xd%alphaf_minus1(i,j) ) ! Eqn 1.43 + end if + else + KC%Dalphaf = 0.0_ReKi + end if + + if ( p%UAMod == UA_Gonzalez ) then + KC%C_V = KC%Cn_alpha_q_circ * ( 1.0_ReKi - ((1.0_ReKi + 2.0_ReKi*sqrt(KC%fprimeprime) )/3.0_ReKi)**2 ) ! Eqn. 1.50 + else + KC%C_V = KC%Cn_alpha_q_circ * ( 1.0_ReKi - ( 0.5_ReKi + 0.5_ReKi*sqrt(KC%fprimeprime) )**2 ) ! Eqn. 1.49 + end if + + KC%T_V = BL_p%T_V0 / OtherState%sigma3(i,j) ! Eqn 1.48 + + if (OtherState%FirstPass(i,j)) then + KC%Cn_v = 0.0_ReKi + else + if (xd%tau_V(i,j) > BL_p%T_VL .AND. KC%Kalpha_f * KC%dalpha0 > 0 ) then ! .AND. (.not. LESF) + ! We no longer require that T_V will always equal T_V0/2 when this condition is satisfied as was the case in AD v13 GJH 7/20/2017 + ! If we fall into this condition, we need to require we stay here until the current vortex is shed (i.e., tauV is reset to zero) + if ( p%UAMod == UA_Gonzalez ) then !Added this equation from the formulation used in UAMod=UA_Gonzalez + KC%Cn_v = xd%Cn_v_minus1(i,j)*exp(-2.0_ReKi*KC%ds/KC%T_V) + else + KC%Cn_v = xd%Cn_v_minus1(i,j)*exp(-KC%ds/KC%T_V) ! Eqn 1.52 + end if + else + KC%Cn_v = Get_ExpEqn( KC%ds, KC%T_V, xd%Cn_v_minus1(i,j), KC%C_V, xd%C_V_minus1(i,j) ) ! Eqn 1.47 + end if + + if ( KC%Cn_v < 0.0_ReKi ) then + KC%Cn_v = 0.0_ReKi + end if + end if + +end subroutine ComputeKelvinChain + + +!============================================================================== + +!============================================================================== +! Framework Routines ! +!============================================================================== + + +!============================================================================== +subroutine UA_SetParameters( dt, InitInp, p, ErrStat, ErrMsg ) +! +! Called by : UA_Init +! Calls to : NONE +!.............................................................................. + + real(DbKi), intent(in ) :: dt ! time step length (s) + type(UA_InitInputType), intent(inout) :: InitInp ! input data for initialization routine, needs to be inout because there is a copy of some data in InitInp in BEMT_SetParameters() + type(UA_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 + + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'UA_SetParameters' + + + + ! Initialize variables for this routine + ErrStat = ErrID_None + ErrMsg = "" + p%dt = dt + + allocate(p%c(InitInp%nNodesPerBlade,InitInp%numBlades), stat = ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, 'Error allocating p%c.', ErrStat, ErrMsg, RoutineName ) + ! Set errmessage and return + return + end if + + p%c = InitInp%c ! this can't be 0 + p%numBlades = InitInp%numBlades + p%nNodesPerBlade = InitInp%nNodesPerBlade + p%UAMod = InitInp%UAMod + p%a_s = InitInp%a_s ! this can't be 0 + p%Flookup = InitInp%Flookup + + if (p%UAMod==UA_HGM) then + p%lin_nx = p%numBlades*p%nNodesPerBlade*4 + else + p%lin_nx = 0 + end if + +end subroutine UA_SetParameters +!============================================================================== + +!============================================================================== +subroutine UA_InitStates_Misc( p, x, xd, OtherState, m, ErrStat, ErrMsg ) +! Called by : UA_Init +! Calls to : NONE +!.............................................................................. + + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_ContinuousStateType), intent(inout) :: x ! Initial continuous states + type(UA_DiscreteStateType), intent(inout) :: xd ! Initial discrete states + type(UA_OtherStateType), intent(inout) :: OtherState ! Initial other states + type(UA_MiscVarType), intent(inout) :: m ! Initial misc/optimization variables + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'UA_InitStates' + + ErrMsg = "" + ErrStat = ErrID_None + + + ! allocate all the state arrays + if (p%UAMod == UA_HGM) then + + allocate( x%element( p%nNodesPerBlade, p%numBlades ), stat=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat(ErrID_Fatal,"Cannot allocate x%x.",ErrStat,ErrMsg,RoutineName) + + allocate( OtherState%n(p%nNodesPerBlade, p%numBlades), stat=ErrStat2) + if (ErrStat2 /= 0 ) call SetErrStat( ErrID_Fatal, " Error allocating OtherState%n.", ErrStat, ErrMsg, RoutineName) + + + else + call AllocAry( xd%alpha_minus1, p%nNodesPerBlade,p%numBlades, 'xd%alpha_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%alpha_filt_minus1, p%nNodesPerBlade,p%numBlades, 'xd%alpha_filt_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%q_minus1, p%nNodesPerBlade,p%numBlades, 'xd%q_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%q_f_minus1, p%nNodesPerBlade,p%numBlades, 'xd%q_f_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Kq_f_minus1, p%nNodesPerBlade,p%numBlades, 'xd%Kq_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Kalpha_f_minus1, p%nNodesPerBlade,p%numBlades, 'xd%Kalpha_f_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%X1_minus1, p%nNodesPerBlade,p%numBlades, 'xd%X1_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%X2_minus1, p%nNodesPerBlade,p%numBlades, 'xd%X2_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%X3_minus1, p%nNodesPerBlade,p%numBlades, 'xd%X3_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%X4_minus1, p%nNodesPerBlade,p%numBlades, 'xd%X4_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Kprime_alpha_minus1, p%nNodesPerBlade,p%numBlades, 'xd%Kprime_alpha_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Kprime_q_minus1, p%nNodesPerBlade,p%numBlades, 'xd%Kprime_q_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Kprimeprime_q_minus1,p%nNodesPerBlade,p%numBlades, 'xd%Kprimeprime_q_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%K3prime_q_minus1, p%nNodesPerBlade,p%numBlades, 'xd%K3prime_q_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( xd%Dp_minus1, p%nNodesPerBlade,p%numBlades, 'xd%Dp_minus1', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call AllocAry(xd%Cn_prime_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Cn_prime_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Cn_pot_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Cn_pot_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprimeprime_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%fprimeprime_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprimeprime_c_minus1,p%nNodesPerBlade,p%numBlades,'xd%fprimeprime_c_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprimeprime_m_minus1,p%nNodesPerBlade,p%numBlades,'xd%fprimeprime_m_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Df_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Df_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Df_c_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Df_c_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Df_m_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Df_m_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Dalphaf_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Dalphaf_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%alphaf_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%alphaf_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprime_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%fprime_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprime_c_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%fprime_c_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%fprime_m_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%fprime_m_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%tau_V ,p%nNodesPerBlade,p%numBlades,'xd%tau_V',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%tau_V_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%tau_V_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%Cn_v_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%Cn_v_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(xd%C_V_minus1 ,p%nNodesPerBlade,p%numBlades,'xd%C_V_minus1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call AllocAry(OtherState%sigma1 ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma1',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(OtherState%sigma1c ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma1c',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(OtherState%sigma1m ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma1m',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(OtherState%sigma3 ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma3',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + +# ifdef UA_OUTS + call AllocAry(m%TESF ,p%nNodesPerBlade,p%numBlades,'m%TESF',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(m%LESF ,p%nNodesPerBlade,p%numBlades,'m%LESF',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(m%VRTX ,p%nNodesPerBlade,p%numBlades,'m%VRTX',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(m%T_Sh ,p%nNodesPerBlade,p%numBlades,'m%T_Sh',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) +# endif + end if + + call AllocAry(OtherState%FirstPass,p%nNodesPerBlade,p%numBlades,'OtherState%FirstPass',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + + call UA_ReInit( p, x, xd, OtherState, m,ErrStat2,ErrMsg2 ) ! initializes values of states and misc vars + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + +end subroutine UA_InitStates_Misc +!============================================================================== +subroutine UA_ReInit( p, x, xd, OtherState, m, ErrStat, ErrMsg ) + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_ContinuousStateType), intent(inout) :: x ! Initial continuous states + type(UA_DiscreteStateType), intent(inout) :: xd ! Initial discrete states + type(UA_OtherStateType), intent(inout) :: OtherState ! Initial other states + type(UA_MiscVarType), intent(inout) :: m ! Initial misc/optimization variables + + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'UA_ReInit' + integer :: i + integer :: j + + ErrStat = ErrID_None + ErrMsg = "" + + m%FirstWarn_M = .true. + m%FirstWarn_UA = .true. + + OtherState%FirstPass = .true. + + if ( p%UAMod == UA_HGM ) then + + OtherState%n = -1 ! we haven't updated OtherState%xdot, yet + + do j=1,size(x%element,2) + do i=1,size(x%element,1) + x%element(i,j)%x = 0.0_ReKi + end do + end do + + do i = 1, size(OtherState%xdot) + call UA_CopyContState( x, OtherState%xdot(i), MESH_UPDATECOPY, ErrStat2, ErrMsg2) ! there are no meshes, so the control code is irrelevant + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end do + + else + OtherState%sigma1 = 1.0_ReKi + OtherState%sigma1c = 1.0_ReKi + OtherState%sigma1m = 1.0_ReKi + OtherState%sigma3 = 1.0_ReKi + +# ifdef UA_OUTS + m%TESF = .FALSE. + m%LESF = .FALSE. + m%VRTX = .FALSE. + m%T_sh = 0.0_ReKi +# endif + + xd%Cn_prime_minus1 = 0.0_ReKi + xd%alpha_minus1 = 0.0_ReKi + xd%alpha_filt_minus1 = 0.0_ReKi + xd%q_minus1 = 0.0_ReKi + xd%q_f_minus1 = 0.0_ReKi + xd%Kq_f_minus1 = 0.0_ReKi + xd%Kalpha_f_minus1 = 0.0_ReKi + xd%X1_minus1 = 0.0_ReKi + xd%X2_minus1 = 0.0_ReKi + xd%X3_minus1 = 0.0_ReKi + xd%X4_minus1 = 0.0_ReKi + xd%Kprime_alpha_minus1 = 0.0_ReKi + xd%Kprime_q_minus1 = 0.0_ReKi + xd%Dp_minus1 = 0.0_ReKi + xd%Cn_pot_minus1 = 0.0_ReKi + xd%K3prime_q_minus1 = 0.0_ReKi + xd%Kprimeprime_q_minus1 = 0.0_ReKi + xd%fprimeprime_minus1 = 0.0_ReKi + xd%fprimeprime_c_minus1 = 0.0_ReKi + xd%fprimeprime_m_minus1 = 0.0_ReKi + xd%Df_minus1 = 0.0_ReKi + xd%Df_c_minus1 = 0.0_ReKi + xd%Df_m_minus1 = 0.0_ReKi + xd%Dalphaf_minus1 = 0.0_ReKi + xd%alphaf_minus1 = 0.0_ReKi + xd%fprime_minus1 = 0.0_ReKi + xd%fprime_c_minus1 = 0.0_ReKi + xd%fprime_m_minus1 = 0.0_ReKi + xd%tau_V = 0.0_ReKi + xd%tau_V_minus1 = 0.0_ReKi + xd%Cn_v_minus1 = 0.0_ReKi + xd%C_V_minus1 = 0.0_ReKi ! This probably should not be set to 0.0, but should be set + end if + +end subroutine UA_ReInit +!============================================================================== +subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & + InitOut,ErrStat, ErrMsg ) +! 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. +! The initial states and initial guess for the input are defined. +! Called by : DRIVER +! Calls to : NWTC_Init, UA_SetParameters, UA_InitStates +!.............................................................................. + + type(UA_InitInputType), intent(inout) :: InitInp ! Input data for initialization routine, needs to be inout because there is a copy of some data in InitInp in BEMT_SetParameters() + type(UA_InputType), intent(in ) :: u ! An initial guess for the input; input mesh must be defined + type(UA_ParameterType), intent( out) :: p ! Parameters + type(UA_ContinuousStateType), intent( out) :: x ! Initial continuous states + type(UA_DiscreteStateType), intent( out) :: xd ! Initial discrete states + type(UA_OtherStateType), intent( out) :: OtherState ! Initial other states + type(UA_OutputType), intent( out) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + type(UA_MiscVarType), intent( out) :: m ! Initial misc/optimization variables + real(DbKi), intent(in ) :: interval ! Coupling interval in seconds: the rate that + ! (1) BEMT_UpdateStates() is called in loose coupling & + ! (2) BEMT_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + type(UA_InitOutputType), intent( out) :: InitOut ! Output for initialization routine + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'UA_Init' + +#ifdef UA_OUTS + integer(IntKi) :: i,j, iNode, iOffset + character(64) :: chanPrefix +#endif + + ! Initialize variables for this routine + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + call NWTC_Init( EchoLibVer=.FALSE. ) + + call UA_ValidateInput(InitInp, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate and set parameter data structure using initialization data + call UA_SetParameters( interval, InitInp, p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! initialize the discrete states, other states, and misc variables + call UA_InitStates_Misc( p, x, xd, OtherState, m, ErrStat2, ErrMsg2 ) ! initialize the continuous states + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + +#ifdef UA_OUTS + + ! Allocate and set the InitOut data + if (p%UAMod == UA_HGM) then + p%NumOuts = 17 + else + p%NumOuts = 42 + end if + + allocate(InitOut%WriteOutputHdr(p%NumOuts*p%numBlades*p%nNodesPerBlade),STAT=ErrStat2) + if (ErrStat2 /= 0) call SetErrStat(ErrID_Fatal,'Error allocating WriteOutputHdr.',ErrStat,ErrMsg,RoutineName) + allocate(InitOut%WriteOutputUnt(p%NumOuts*p%numBlades*p%nNodesPerBlade),STAT=ErrStat2) + if (ErrStat2 /= 0) call SetErrStat(ErrID_Fatal,'Error allocating WriteOutputUnt.',ErrStat,ErrMsg,RoutineName) + allocate(y%WriteOutput(p%NumOuts*p%numBlades*p%nNodesPerBlade),STAT=ErrStat2) + if (ErrStat2 /= 0) call SetErrStat(ErrID_Fatal,'Error allocating y%WriteOutput.',ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + iNode = 0 + do j = 1,p%numBlades + do i = 1,p%nNodesPerBlade + + iOffset = (i-1)*p%NumOuts + (j-1)*p%nNodesPerBlade*p%NumOuts + + chanPrefix = "B"//trim(num2lstr(j))//"N"//trim(num2lstr(i)) + + InitOut%WriteOutputHdr(iOffset+ 2) = trim(chanPrefix)//'VREL' + InitOut%WriteOutputHdr(iOffset+ 3) = trim(chanPrefix)//'Cn' + InitOut%WriteOutputHdr(iOffset+ 4) = trim(chanPrefix)//'Cc' + InitOut%WriteOutputHdr(iOffset+ 5) = trim(chanPrefix)//'Cl' + InitOut%WriteOutputHdr(iOffset+ 6) = trim(chanPrefix)//'Cd' + InitOut%WriteOutputHdr(iOffset+ 7) = trim(chanPrefix)//'Cm' + + InitOut%WriteOutputUnt(iOffset+ 2) ='(m/s)' + InitOut%WriteOutputUnt(iOffset+ 3) ='(-)' + InitOut%WriteOutputUnt(iOffset+ 4) ='(-)' + InitOut%WriteOutputUnt(iOffset+ 5) ='(-)' + InitOut%WriteOutputUnt(iOffset+ 6) ='(-)' + InitOut%WriteOutputUnt(iOffset+ 7) ='(-)' + + if (p%UAmod == UA_HGM) then + InitOut%WriteOutputHdr(iOffset+ 1) = trim(chanPrefix)//'ALPHA' + + InitOut%WriteOutputHdr(iOffset+ 8) = trim(chanPrefix)//'omega' + InitOut%WriteOutputHdr(iOffset+ 9) = trim(chanPrefix)//'alphaE' + InitOut%WriteOutputHdr(iOffset+10) = trim(chanPrefix)//'Tu' + InitOut%WriteOutputHdr(iOffset+11) = trim(chanPrefix)//'alpha_34' + InitOut%WriteOutputHdr(iOffset+12) = trim(chanPrefix)//'cl_fs' + InitOut%WriteOutputHdr(iOffset+13) = trim(chanPrefix)//'fs_aE' + + InitOut%WriteOutputHdr(iOffset+14) = trim(chanPrefix)//'x1' + InitOut%WriteOutputHdr(iOffset+15) = trim(chanPrefix)//'x2' + InitOut%WriteOutputHdr(iOffset+16) = trim(chanPrefix)//'x3' + InitOut%WriteOutputHdr(iOffset+17) = trim(chanPrefix)//'x4' + + + InitOut%WriteOutputUnt(iOffset+ 1) ='(deg)' + + InitOut%WriteOutputUnt(iOffset+ 8) = '(deg/sec)' + InitOut%WriteOutputUnt(iOffset+ 9) = '(deg)' + InitOut%WriteOutputUnt(iOffset+10) = '(s)' + InitOut%WriteOutputUnt(iOffset+11) = '(deg)' + InitOut%WriteOutputUnt(iOffset+12) = '(-)' + InitOut%WriteOutputUnt(iOffset+13) = '(-)' + + InitOut%WriteOutputUnt(iOffset+14) = '(rad)' + InitOut%WriteOutputUnt(iOffset+15) = '(rad)' + InitOut%WriteOutputUnt(iOffset+16) = '(-)' + InitOut%WriteOutputUnt(iOffset+17) = '(-)' + + else + InitOut%WriteOutputHdr(iOffset+ 1) = trim(chanPrefix)//'ALPHA_filt' + + InitOut%WriteOutputHdr(iOffset+ 8) = trim(chanPrefix)//'Cn_aq_circ' + InitOut%WriteOutputHdr(iOffset+ 9) = trim(chanPrefix)//'Cn_aq_nc' + InitOut%WriteOutputHdr(iOffset+10) = trim(chanPrefix)//'Cn_pot' + InitOut%WriteOutputHdr(iOffset+11) = trim(chanPrefix)//'Dp' + InitOut%WriteOutputHdr(iOffset+12) = trim(chanPrefix)//'Cn_prime' + InitOut%WriteOutputHdr(iOffset+13) = trim(chanPrefix)//'fprime' + InitOut%WriteOutputHdr(iOffset+14) = trim(chanPrefix)//'Df' + InitOut%WriteOutputHdr(iOffset+15) = trim(chanPrefix)//'Cn_v' + InitOut%WriteOutputHdr(iOffset+16) = trim(chanPrefix)//'Tau_V' + InitOut%WriteOutputHdr(iOffset+17) = trim(chanPrefix)//'LESF' + InitOut%WriteOutputHdr(iOffset+18) = trim(chanPrefix)//'TESF' + InitOut%WriteOutputHdr(iOffset+19) = trim(chanPrefix)//'VRTX' + InitOut%WriteOutputHdr(iOffset+20) = trim(chanPrefix)//'C_v' + InitOut%WriteOutputHdr(iOffset+21) = trim(chanPrefix)//'Cm_a_nc' + InitOut%WriteOutputHdr(iOffset+22) = trim(chanPrefix)//'Cm_q_nc' + InitOut%WriteOutputHdr(iOffset+23) = trim(chanPrefix)//'Cm_v' + InitOut%WriteOutputHdr(iOffset+24) = trim(chanPrefix)//'alpha_p_f' + InitOut%WriteOutputHdr(iOffset+25) = trim(chanPrefix)//'Dalphaf' + InitOut%WriteOutputHdr(iOffset+26) = trim(chanPrefix)//'PMC' + InitOut%WriteOutputHdr(iOffset+27) = trim(chanPrefix)//'T_f' + InitOut%WriteOutputHdr(iOffset+28) = trim(chanPrefix)//'T_V' + InitOut%WriteOutputHdr(iOffset+29) = trim(chanPrefix)//'dS' + InitOut%WriteOutputHdr(iOffset+30) = trim(chanPrefix)//'T_alpha' + InitOut%WriteOutputHdr(iOffset+31) = trim(chanPrefix)//'T_q' + InitOut%WriteOutputHdr(iOffset+32) = trim(chanPrefix)//'k_alpha' + InitOut%WriteOutputHdr(iOffset+33) = trim(chanPrefix)//'k_q' + InitOut%WriteOutputHdr(iOffset+34) = trim(chanPrefix)//'alpha_e' + InitOut%WriteOutputHdr(iOffset+35) = trim(chanPrefix)//'X1' + InitOut%WriteOutputHdr(iOffset+36) = trim(chanPrefix)//'X2' + InitOut%WriteOutputHdr(iOffset+37) = trim(chanPrefix)//'cn_q_nc' + InitOut%WriteOutputHdr(iOffset+38) = trim(chanPrefix)//'alpha_f' + InitOut%WriteOutputHdr(iOffset+39) = trim(chanPrefix)//'fprimeprime' + InitOut%WriteOutputHdr(iOffset+40) = trim(chanPrefix)//'sigma1' + InitOut%WriteOutputHdr(iOffset+41) = trim(chanPrefix)//'sigma3' + InitOut%WriteOutputHdr(iOffset+42) = trim(chanPrefix)//'T_sh' + + + InitOut%WriteOutputUnt(iOffset+1) ='(deg)' + + InitOut%WriteOutputUnt(iOffset+8) ='(-)' + InitOut%WriteOutputUnt(iOffset+9) ='(-)' + InitOut%WriteOutputUnt(iOffset+10) ='(-)' + InitOut%WriteOutputUnt(iOffset+11) ='(-)' + InitOut%WriteOutputUnt(iOffset+12) ='(-)' + InitOut%WriteOutputUnt(iOffset+13) ='(-)' + InitOut%WriteOutputUnt(iOffset+14) ='(-)' + InitOut%WriteOutputUnt(iOffset+15) ='(-)' + InitOut%WriteOutputUnt(iOffset+16) ='(-)' + InitOut%WriteOutputUnt(iOffset+17) ='(-)' + InitOut%WriteOutputUnt(iOffset+18) ='(-)' + InitOut%WriteOutputUnt(iOffset+19) ='(-)' + InitOut%WriteOutputUnt(iOffset+20) ='(-)' + InitOut%WriteOutputUnt(iOffset+21) ='(-)' + InitOut%WriteOutputUnt(iOffset+22) ='(-)' + InitOut%WriteOutputUnt(iOffset+23) ='(-)' + InitOut%WriteOutputUnt(iOffset+24) ='(rad)' + InitOut%WriteOutputUnt(iOffset+25) ='(-)' + InitOut%WriteOutputUnt(iOffset+26) ='(-)' + InitOut%WriteOutputUnt(iOffset+27) ='(-)' + InitOut%WriteOutputUnt(iOffset+28) ='(-)' + InitOut%WriteOutputUnt(iOffset+29) ='(-)' + InitOut%WriteOutputUnt(iOffset+30) ='(-)' + InitOut%WriteOutputUnt(iOffset+31) ='(-)' + InitOut%WriteOutputUnt(iOffset+32) ='(-)' + InitOut%WriteOutputUnt(iOffset+33) ='(-)' + InitOut%WriteOutputUnt(iOffset+34) ='(rad)' + InitOut%WriteOutputUnt(iOffset+35) ='(-)' + InitOut%WriteOutputUnt(iOffset+36) ='(-)' + InitOut%WriteOutputUnt(iOffset+37) ='(-)' + InitOut%WriteOutputUnt(iOffset+38) ='(rad)' + InitOut%WriteOutputUnt(iOffset+39) ='(-)' + InitOut%WriteOutputUnt(iOffset+40) ='(-)' + InitOut%WriteOutputUnt(iOffset+41) ='(-)' + InitOut%WriteOutputUnt(iOffset+42) ='(-)' + end if + + end do + end do +#else + p%NumOuts = 0 + + !..................................... + ! add the following two lines only to avoid compiler warnings about uninitialized variables when not building the UA driver: + y%cm = 0.0_ReKi + InitOut%Version = ProgDesc( 'Unsteady Aero', '', '' ) + !..................................... + +#endif + +end subroutine UA_Init +!============================================================================== +subroutine UA_ValidateInput(InitInp, ErrStat, ErrMsg) + type(UA_InitInputType), intent(inout) :: InitInp ! Input data for initialization routine, needs to be inout because there is a copy of some data in InitInp in BEMT_SetParameters() + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'UA_ValidateInput' + + ErrStat = ErrID_None + ErrMsg = "" + + !>>> remove after this feature gets tested better: + if (InitInp%UAMod == UA_HGM ) then + call SetErrStat( ErrID_Fatal, "UAMod cannot be 4 (continuous HGM model) in this version of OpenFAST.", ErrStat, ErrMsg, RoutineName ) + end if + !<<< + + if (InitInp%UAMod < UA_Gonzalez .or. InitInp%UAMod > UA_HGM ) call SetErrStat( ErrID_Fatal, & + "In this version, UAMod must be 2 (Gonzalez's variant), 3 (Minnema/Pierce variant), or 4 (continuous HGM model).", ErrStat, ErrMsg, RoutineName ) ! NOTE: for later- 1 (baseline/original) + + if (.not. InitInp%FLookUp ) call SetErrStat( ErrID_Fatal, 'FLookUp must be TRUE for this version.', ErrStat, ErrMsg, RoutineName ) + + if (InitInp%a_s <= 0.0) call SetErrStat ( ErrID_Fatal, 'The speed of sound (SpdSound) must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + +end subroutine UA_ValidateInput +!============================================================================== +subroutine UA_ValidateAFI(UAMod, AFInfo, afName, ErrStat, ErrMsg) + integer(IntKi), intent(in ) :: UAMod ! which UA model we are using + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + character(*), intent(in ) :: afName ! The airfoil file name + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer(IntKi) :: j + character(*), parameter :: RoutineName = 'UA_ValidateAFI' + + ErrStat = ErrID_None + ErrMsg = "" + + if (.not. allocated(AFInfo%Table)) then + call SetErrStat(ErrID_Fatal, 'Airfoil table not allocated in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + else + + do j=1, AFInfo%NumTabs + if ( .not. AFInfo%Table(j)%InclUAdata ) then + call SetErrStat(ErrID_Fatal, 'Airfoil file "'//trim(afName)//'", table #'//trim(num2lstr(j))// & + ' does not contain parameters for UA data.', ErrStat, ErrMsg, RoutineName ) + else + ! parameters used only for UAMod/=UA_HGM) + if (UAMod /= UA_HGM) then + if ( EqualRealNos(AFInfo%Table(j)%UA_BL%St_sh, 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal, 'UA St_sh parameter must not be 0 in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + if ( AFInfo%Table(j)%UA_BL%alpha1 > pi .or. AFInfo%Table(j)%UA_BL%alpha1 < -pi ) then + call SetErrStat(ErrID_Fatal, 'UA alpha1 parameter must be between -180 and 180 degrees in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + if ( AFInfo%Table(j)%UA_BL%alpha2 > pi .or. AFInfo%Table(j)%UA_BL%alpha2 < -pi ) then + call SetErrStat(ErrID_Fatal, 'UA alpha2 parameter must be between -180 and 180 degrees in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + if ( AFInfo%Table(j)%UA_BL%filtCutOff < 0 ) then + call SetErrStat(ErrID_Fatal, 'UA filtCutOff parameter must be greater than 0 in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + end if + + ! variables used in all UA models: + if ( AFInfo%Table(j)%UA_BL%alpha0 > pi .or. AFInfo%Table(j)%UA_BL%alpha0 < -pi ) then + call SetErrStat(ErrID_Fatal, 'UA alpha0 parameter must be between -180 and 180 degrees in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + if ( AFInfo%Table(j)%UA_BL%T_f0 < 0 ) then + call SetErrStat(ErrID_Fatal, 'UA T_f0 parameter must be greater than 0 in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + if ( AFInfo%Table(j)%UA_BL%T_p < 0 ) then + call SetErrStat(ErrID_Fatal, 'UA T_p parameter must be greater than 0 in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + end if + + +!bjj: check that these SHOULD be used for UA_HGM (EB wasn't sure this was necessary) + if ( AFInfo%Table(j)%UA_BL%UACutout < 0.0_ReKi ) then + call SetErrStat(ErrID_Fatal, 'UA UACutout parameter must not be negative in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + end if + + + + end do + + if (ErrStat >= AbortErrLev) return + + if (UAMod /= UA_HGM) then + ! check interpolated values: + + do j=2, AFInfo%NumTabs + if ( sign( 1.0_ReKi, AFInfo%Table(j)%UA_BL%St_sh) /= & + sign( 1.0_ReKi, AFInfo%Table(1)%UA_BL%St_sh) ) then + call SetErrStat(ErrID_Fatal, 'UA St_sh parameter (interpolated value) must not be 0 in "'//trim(afName)//'".', ErrStat, ErrMsg, RoutineName ) + exit + end if + end do + end if + + end if + + +end subroutine UA_ValidateAFI +!============================================================================== +!> This routine checks if the UA parameters indicate that UA should not be used. (i.e., if C_nalpha = 0) +!! This should be called at initialization. +subroutine UA_TurnOff_param(p, AFInfo, ErrStat, ErrMsg) + type(UA_ParameterType), intent(in ) :: p ! The UA parameter data + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer(IntKi) :: j + + ErrStat = ErrID_None + ErrMsg = "" + + if (p%UAMod == UA_HGM) then + ! unsteady aerodynamics will be turned off + do j=1, AFInfo%NumTabs + if ( EqualRealNos(AFInfo%Table(j)%UA_BL%C_lalpha, 0.0_ReKi) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'C_lalpha is 0.' + return + end if + end do + + ! now check about interpolated values: + do j=2, AFInfo%NumTabs + if ( sign( 1.0_ReKi, AFInfo%Table(j)%UA_BL%C_lalpha) /= & + sign( 1.0_ReKi, AFInfo%Table(1)%UA_BL%C_lalpha) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'C_lalpha (interpolated value) could be 0.' + return + end if + end do + + else + ! unsteady aerodynamics will be turned off + do j=1, AFInfo%NumTabs + if ( EqualRealNos(AFInfo%Table(j)%UA_BL%C_nalpha, 0.0_ReKi) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'C_nalpha is 0.' + return + end if + end do + + ! now check about interpolated values: + do j=2, AFInfo%NumTabs + if ( sign( 1.0_ReKi, AFInfo%Table(j)%UA_BL%C_nalpha) /= & + sign( 1.0_ReKi, AFInfo%Table(1)%UA_BL%C_nalpha) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'C_nalpha (interpolated value) could be 0.' + return + end if + end do + + end if + + +end subroutine UA_TurnOff_param +!============================================================================== +!> This routine checks if the inputs to UA indicate that UA should not be used. +!! This should be called before updating UA states (and maybe other places). +subroutine UA_TurnOff_input(p, AFInfo, u, ErrStat, ErrMsg) + type(UA_ParameterType), intent(in ) :: p ! UA parameters + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + type(UA_InputType), intent(in ) :: u ! UA input + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi) :: AoA ! The angle of attack + TYPE(AFI_UA_BL_Type) :: UA_BL ! The tables of Leishman-Beddoes unsteady-aero data for given Re and control setting [-] + + + ErrStat = ErrID_None + ErrMsg = "" + + ! check for zero relative velocity + if (EqualRealNos(u%U, 0.0_ReKi) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'zero relative velocity.' + return + end if + + + ! check for high angle of attack (value larger than cutout specified in tables) + call AFI_ComputeUACoefs( AFInfo, u%Re, u%UserProp, UA_BL, ErrMsg, ErrStat ) + if (ErrStat >= AbortErrLev) return + + ! put alpha in [-pi,pi] before checking its value + AoA = u%alpha + call Mpi2pi(AoA) + + if ( abs(AoA) >= UA_BL%UACutout ) then ! Is the angle of attack larger than the UA cut-out for this airfoil? + ErrStat = ErrID_Fatal + ErrMsg = 'high angle of attack ('//trim(num2lstr(AoA*R2D))//' deg).' + return + end if + +end subroutine UA_TurnOff_input +!============================================================================== +subroutine UA_UpdateDiscOtherState( i, j, u, p, xd, OtherState, AFInfo, m, ErrStat, ErrMsg ) +! Routine for updating discrete states and other states (note it breaks the framework) +!.............................................................................. + + integer , intent(in ) :: i ! node index within a blade + integer , intent(in ) :: j ! blade index + type(UA_InputType), intent(in ) :: u ! Inputs at Time + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_DiscreteStateType), intent(inout) :: xd ! Input: Discrete states at Time; + ! Output: Discrete states at Time + Interval + type(UA_OtherStateType), intent(inout) :: OtherState ! Other states + type(UA_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local Variables + + LOGICAL :: LESF ! logical flag indicating if leading edge separation is possible [-] + LOGICAL :: VRTX ! logical flag indicating if a vortex is being processed [-] + LOGICAL :: TESF ! logical flag indicating if trailing edge separation is possible [-] + + real(ReKi) :: Kafactor + real(ReKi) :: T_sh + + type(AFI_UA_BL_Type) :: BL_p ! airfoil UA parameters retrieved in Kelvin Chain + type(UA_KelvinChainType) :: KC ! values computed in Kelvin Chain + + + character(ErrMsgLen) :: errMsg2 + integer(IntKi) :: errStat2 + character(*), parameter :: RoutineName = 'UA_UpdateDiscOtherState' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + +!bjj: use sigma1 and sigma3 states values from t + + call ComputeKelvinChain(i, j, u, p, xd, OtherState, m, AFInfo, KC, BL_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat>= AbortErrLev) return + + + T_sh = 2.0_ReKi*(1.0_ReKi-KC%fprimeprime) / BL_p%St_sh ! Eq 1.54 + + !--------------------------------------------------------- + ! Update the OtherStates + !--------------------------------------------------------- + + LESF = (KC%Cn_prime > BL_p%Cn1) .or. ( KC%Cn_prime < BL_p%Cn2 ) ! LE separation can occur when this is .true.; assumption is that Cn2 < 0.0 and Cn1 > 0 + if (p%UAMod == UA_Gonzalez) then !Added specific logic for UAMod=UA_Gonzalez + TESF = ABS( KC%Cn_prime ) > ABS( xd%Cn_prime_minus1(i,j) ) + else + TESF = KC%fprimeprime < xd%fprimeprime_minus1(i,j) ! Separation point is moving towards the Leading Edge when .true.; otherwise separation point is moving toward trailing edge + end if + + + VRTX = (xd%tau_V(i,j) <= BL_p%T_VL) .and. (xd%tau_V(i,j) > 0.0_ReKi) ! Is the vortex over the chord? + + + !--------------------------------------------------------- + ! Update the OtherStates + !--------------------------------------------------------- + +!bjj: update sigma1 to value at t + dt + + ! Set sigma1 to the default value. T_f = T_f0 / sigma1 + OtherState%sigma1( i,j) = 1.0_ReKi + OtherState%sigma1c(i,j) = 1.0_ReKi + OtherState%sigma1m(i,j) = 1.0_ReKi + + Kafactor = KC%Kalpha_f*KC%dalpha0 ! indicates if the airfoil is moving towards alpha0 [ Kafactor < 0.0 ] or away [ Kafactor > 0.0] + +if (p%UAMod == UA_Gonzalez) then !Added modifiers for Tfn, Tfc and Tfm depending on the aerodynamic state, this set of values can be optimized for different airfoils or wind conditions + if ( TESF .AND. .NOT.LESF .AND. .NOT.VRTX ) then + if ( KC%fprimeprime>0.7 ) then + OtherState%sigma1( i,j)=1.0!0.2 + OtherState%sigma1c(i,j)=1.0!0.2 + OtherState%sigma1m(i,j)=1.0!0.1 + else !if ((KC%fprimeprime<=0.7).AND.(TESF).AND.(.NOT.LESF).AND. NOT.VRTX ) then + OtherState%sigma1( i,j)=1.0!0.5 + OtherState%sigma1c(i,j)=1.0!0.8 + OtherState%sigma1m(i,j)=1.0!0.3 + endif + elseif ((xd%tau_V(i,j) < BL_p%T_VL).AND.(xd%tau_V(i,j)>0.001).AND.(TESF)) then + OtherState%sigma1( i,j)=2.0!4.0 + OtherState%sigma1c(i,j)=1.0!1.0 + OtherState%sigma1m(i,j)=1.0!0.2 + elseif ( LESF ) then + if (TESF) then + OtherState%sigma1( i,j)=2.0!4.0 + OtherState%sigma1c(i,j)=1.0!1.0 + OtherState%sigma1m(i,j)=1.0!0.3 + else !if ((LESF).AND.(.NOT.TESF)) then + OtherState%sigma1( i,j)=1.0!0.2 + OtherState%sigma1c(i,j)=1.0!0.2 + OtherState%sigma1m(i,j)=1.0!0.2 + endif + elseif ( .NOT.TESF ) then + if (KC%fprimeprime<=0.7) then + OtherState%sigma1( i,j)=0.5!0.5 + OtherState%sigma1c(i,j)=1.0!0.5 + OtherState%sigma1m(i,j)=1.0!2.0 + else !if ((KC%fprimeprime>0.7).AND.(.NOT.TESF)) then + OtherState%sigma1( i,j)=0.5!4.0 + OtherState%sigma1c(i,j)=1.0!0.4 + OtherState%sigma1m(i,j)=1.0!2.0 + endif + else + OtherState%sigma1( i,j)=1.0_ReKi + OtherState%sigma1c(i,j)=1.0_ReKi + OtherState%sigma1m(i,j)=1.0_ReKi + endif +else + if ( TESF ) then ! Flow is continuing or starting to separate + if (Kafactor < 0.0_ReKi) then + ! We are moving towards alpha0 + OtherState%sigma1(i,j) = 2.0_ReKi ! This must be the first check + else if (.not. LESF ) then + OtherState%sigma1(i,j) = 1.0_ReKi ! Leading edge separation has not occurred and we are moving away from alpha0 + else if (xd%fprimeprime_minus1(i,j) <= 0.7_ReKi) then ! For this else, LESF = True and we are moving away from alpha0 + OtherState%sigma1(i,j) = 2.0_ReKi + else + OtherState%sigma1(i,j) = 1.75_ReKi + end if + else ! Reattaching flow + + if (.not. LESF ) then + OtherState%sigma1(i,j) = 0.5_ReKi + end if + + if ( VRTX ) then ! Still shedding a vortex, i.e., the current vortex is still over the chord? + OtherState%sigma1(i,j) = 0.25_ReKi + end if + + if (Kafactor > 0.0_ReKi) then + OtherState%sigma1(i,j) = 0.75_ReKi + end if + + end if + +end if + + + +!bjj: update sigma3 to value at t + dt + + ! This is the default value for sigma3 which effects T_V = T_V0 / sigma3 + OtherState%sigma3(i,j) = 1.0_ReKi + +if (p%UAMod /= UA_Gonzalez) then !this is not applied for UAMod=UZ_Gonzalez, Tv has always the same value + ! Identify where the vortex is located relative to the chord + + ! 1) Is the vortex past the trailing edge, but less than 2 chords? + if ( (xd%tau_V(i,j) <= 2.0_ReKi*BL_p%T_VL) .and. (xd%tau_V(i,j) >= BL_p%T_VL) ) then + ! We want to diminish the effects of this vortex on Cn by setting a high value of sigma3 + OtherState%sigma3(i,j) = 3.0_ReKi + if (.not. TESF) then + ! If we are reattaching the flow, then we when to diminish the current vortex's effects on Cn further + + OtherState%sigma3(i,j) = 4.0_ReKi + + end if + + ! 2) Is the vortex over the chord + else if ( VRTX ) then + if (Kafactor < 0.0_ReKi) then + ! If we are moving towards alpha0, then we want to reduce the contribution of the vortex to Cn + OtherState%sigma3(i,j) = 2.0_ReKi + else + OtherState%sigma3(i,j) = 1.0_ReKi + end if + + ! 3) Is the vortex ((past 2 chords or at the leading edge), and is the airfoil moving away from the stall region (towards alpha0). + ! NOTE: We could also end up here if tau_V = 0.0 + else if (Kafactor < 0 ) then + ! In this case, we want to diminish the effects of this vortex on Cn by setting a high value of sigma3 + OtherState%sigma3(i,j) = 4.0_ReKi + end if + + + + ! Finally, we will override all the previous values of sigma1 if we are reattaching flow and the rate of change of the of the angle of attack is slowing down + ! In this case we want to enhance the contribute of the vortex and set sigma3 = 1.0 + if ((.not. TESF) .and. (KC%Kq_f*KC%dalpha0 < 0.0_ReKi)) then + OtherState%sigma3(i,j) = 1.0_ReKi + end if +endif + + +#ifdef TEST_UA_SIGMA + OtherState%sigma3(i,j) = 1.0_ReKi + OtherState%sigma1(i,j) = 1.0_ReKi +#endif + + !--------------------------------------------------------- + ! Update the Discrete States, xd + !--------------------------------------------------------- + + + xd%alpha_minus1(i,j) = u%alpha + xd%alpha_filt_minus1(i,j) = KC%alpha_filt_cur + xd%Kalpha_f_minus1(i,j) = KC%Kalpha_f + xd%Kq_f_minus1(i,j) = KC%Kq_f + xd%q_f_minus1(i,j) = KC%q_f_cur + xd%q_minus1(i,j) = KC%q_cur + xd%X1_minus1(i,j) = KC%X1 + xd%X2_minus1(i,j) = KC%X2 + xd%X3_minus1(i,j) = KC%X3 + xd%X4_minus1(i,j) = KC%X4 + xd%Kprime_alpha_minus1(i,j) = KC%Kprime_alpha + xd%Kprime_q_minus1(i,j) = KC%Kprime_q + xd%Dp_minus1(i,j) = KC%Dp + xd%Cn_pot_minus1(i,j) = KC%Cn_pot + xd%Cn_prime_minus1(i,j) = KC%Cn_prime + xd%fprimeprime_minus1(i,j) = KC%fprimeprime + xd%Df_minus1(i,j) = KC%Df + if (p%Flookup) then + xd%Df_c_minus1(i,j) = KC%Df_c + xd%Df_m_minus1(i,j) = KC%Df_m + xd%fprimeprime_c_minus1(i,j) = KC%fprimeprime_c + xd%fprimeprime_m_minus1(i,j) = KC%fprimeprime_m + xd%fprime_c_minus1(i,j) = KC%fprime_c + xd%fprime_m_minus1(i,j) = KC%fprime_m + end if + + xd%Dalphaf_minus1(i,j) = KC%Dalphaf + xd%fprime_minus1(i,j) = KC%fprime + xd%alphaf_minus1(i,j) = KC%alpha_f + xd%Cn_v_minus1(i,j) = KC%Cn_v + xd%C_V_minus1(i,j) = KC%C_V + + ! If we are currently tracking a vortex, or we are in the stall region, increment tau_V + if (p%UAMod == UA_Gonzalez) then !Added specific logic for UAMod=UA_Gonzalez + if ( (.NOT.LESF .AND. .NOT.VRTX) .OR. & + (.NOT.TESF .AND. xd%tau_V(i,j)<0.0001_ReKi) .OR.& + (.NOT.TESF .AND. xd%tau_V(i,j) + KC%ds > 2.*BL_p%T_VL) ) then + xd%tau_V(i,j)=0.0 + else + xd%tau_V(i,j) = xd%tau_V(i,j) + KC%ds + if (( xd%tau_V(i,j) >= (BL_p%T_VL + T_sh) ) .and. TESF) then !.and. (TESF) RRD added + xd%tau_V(i,j) = xd%tau_V(i,j)-(BL_p%T_VL + T_sh) + ! LESF=.FALSE. !also added this + end if + endif + + else + if ( xd%tau_V(i,j) > 0.0 .or. LESF ) then + xd%tau_V(i,j) = xd%tau_V(i,j) + KC%ds ! Eqn 1.51 + end if + + ! If we a have been tracking a vortex and 1) it is now past the chord [T_VL] and 2) we have gone beyond the next shedding period [T_sh], and + ! 3) we are continuing the flow serparation, we will shed the existing vortex so that we can create a new one at the leading edge + if (( xd%tau_V(i,j) >= (BL_p%T_VL + T_sh) ) .and. TESF) then !.and. (TESF) RRD added + xd%tau_V(i,j) = 0.0_ReKi + end if + end if + +#ifdef UA_OUTS + m%TESF(i,j) = TESF + m%LESF(i,j) = LESF + m%VRTX(i,j) = VRTX + m%T_sh(i,j) = T_sh +#endif + + +end subroutine UA_UpdateDiscOtherState +!============================================================================== + +!============================================================================== +subroutine UA_UpdateStates( i, j, t, n, u, uTimes, p, x, xd, OtherState, AFInfo, m, ErrStat, ErrMsg ) +! Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +! Continuous, constraint, discrete, and other states are updated to values at t + Interval. +!.............................................................................. + + integer(IntKi), intent(in ) :: i ! node index within a blade + integer(IntKi), intent(in ) :: j ! blade index + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current simulation time step n = 0,1,... + type(UA_InputType), intent(in ) :: u(:) ! Input at current timestep, t and t+dt + real(DbKi), intent(in ) :: utimes(:) !< Times associated with u(:), in seconds + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_ContinuousStateType), intent(inout) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + Interval + type(UA_DiscreteStateType), intent(inout) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + type(UA_OtherStateType), intent(inout) :: OtherState ! Input: Other states at t; + ! Output: Other states at t + Interval + type(UA_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + + character(ErrMsgLen) :: errMsg2 + integer(IntKi) :: errStat2 + character(*), parameter :: RoutineName = 'UA_UpdateStates' + type(UA_InputType) :: u_interp ! Input at current timestep, t and t+dt + + ! Initialize variables + + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + !BJJ: this seems to be the root cause of all sorts of numerical problems.... + + + if (p%UAMod == UA_HGM) then + + ! initialize states to steady-state values: + if (OtherState%FirstPass(i,j)) then + CALL UA_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + call HGM_Steady( i, j, u_interp, p, x%element(i,j), AFInfo, ErrStat2, ErrMsg2 ) + end if + + + call UA_ABM4( i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + x%element(i,j)%x(4) = max( min( x%element(i,j)%x(4), 1.0_R8Ki ), 0.0_R8Ki ) + + ! these are angles that should not get too large, so I am fixing them here (should turn off UA if this exceeds reasonable numbers) + if (abs(x%element(i,j)%x(1)) > pi .or. abs(x%element(i,j)%x(2)) > pi) then + if (m%FirstWarn_UA) then + call SetErrStat(ErrID_Severe, "Divergent states in UA HGM model", ErrStat, ErrMsg, RoutineName ) + m%FirstWarn_UA = .false. + end if + + call Mpi2pi(x%element(i,j)%x(1)) + call Mpi2pi(x%element(i,j)%x(2)) + end if + + else + if (n<=0) return ! previous logic (before adding UA_HGM required n > 0 before UA_UpdateStates was called) + + CALL UA_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Update discrete states: +# ifdef DEBUG_v14 + call UA_UpdateDiscOtherState2( i, j, u_interp, p, xd, OtherState, AFInfo, m, ErrStat2, ErrMsg2 ) +# else + call UA_UpdateDiscOtherState( i, j, u_interp, p, xd, OtherState, AFInfo, m, ErrStat2, ErrMsg2 ) +# endif + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + end if + + OtherState%FirstPass(i,j) = .false. + +end subroutine UA_UpdateStates +!============================================================================== +!!---------------------------------------------------------------------------------------------------------------------------------- +!> routine to initialize the states based on inputs at t=0 +subroutine UA_InitStates_AllNodes( u, p, x, OtherState, UA_is_on, AFInfo, AFIndx ) + type(UA_InputType), intent(in ) :: u !< Inputs at t + type(UA_ParameterType), intent(in ) :: p !< Parameters + type(UA_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; + type(UA_OtherStateType), intent(inout) :: OtherState !< Other/logical states at t on input; at t+dt on output + type(AFI_ParameterType), intent(in ) :: AFInfo(:) !< The airfoil parameter data + logical, intent(in) :: UA_is_on(:,:) + INTEGER(IntKi), intent(in) :: AFIndx(:,:) + + INTEGER(IntKi) :: i !< blade node counter + INTEGER(IntKi) :: j !< blade counter + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + !............................................................................................................................... + ! compute UA states at t=0 (with known inputs) + !............................................................................................................................... + if (p%UAMod == UA_HGM) then + + do j = 1,size(UA_is_on,2) ! blades + do i = 1,size(UA_is_on,1) ! nodes + + ! We only update the UnsteadyAero states if we have unsteady aero turned on for this node + if ( UA_is_on(i,j) .and. OtherState%FirstPass(i,j) ) then + + ! initialize states to steady-state values: + call HGM_Steady( i, j, u, p, x%element(i,j), AFInfo(AFIndx(i,j)), ErrStat2, ErrMsg2 ) + !call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + OtherState%FirstPass(i,j) = .false. + end if + + end do + end do + + end if + +end subroutine UA_InitStates_AllNodes +!============================================================================== +SUBROUTINE HGM_Steady( i, j, u, p, x, AFInfo, ErrStat, ErrMsg ) +! Routine to initialize the continuous states of the HGM model +!.................................................................................................................................. + + INTEGER(IntKi), INTENT(IN ) :: i !< blade node counter + INTEGER(IntKi), INTENT(IN ) :: j !< blade counter + TYPE(UA_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(UA_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(UA_ElementContinuousStateType), INTENT(INOUT) :: x ! Continuous states at t + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + + type(AFI_UA_BL_Type) :: BL_p ! potentially interpolated UA parameters + type(AFI_OutputType) :: AFI_Interp + character(ErrMsgLen) :: errMsg2 + integer(IntKi) :: errStat2 + character(*), parameter :: RoutineName = 'HGM_Steady' + + real(ReKi) :: Tu + real(ReKi) :: alphaE + real(ReKi) :: alphaF + real(ReKi) :: alpha_34 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Lookup values using Airfoil Info module + call AFI_ComputeUACoefs( AFInfo, u%Re, u%UserProp, BL_p, ErrMsg2, ErrStat2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + call Get_HGM_constants(i, j, p, u, x, BL_p, Tu, alpha_34, alphaE) ! compute Tu, alpha_34, and alphaE + + + ! States + !x1: Downwash memory term 1 (rad) + !x2: Downwash memory term 2 (rad) + !x3: Clp', Lift coefficient with a time lag to the attached lift coeff + !x4: f'' , Final separation point function + + + ! Steady states + x%x(1) = BL_p%A1 * alpha_34 + x%x(2) = BL_p%A2 * alpha_34 + + alphaE = alpha_34 ! Eq. 12 (after substitute of x1 and x2 initializations) + x%x(3) = BL_p%c_lalpha * (alphaE-BL_p%alpha0) + + ! calculate x%x(4) = fs_aF = f_st(alphaF): + alphaF = x%x(3)/BL_p%c_lalpha + BL_p%alpha0 ! p. 13 + + call AFI_ComputeAirfoilCoefs( alphaF, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat, ErrMsg) + x%x(4) = AFI_interp%f_st + +end subroutine HGM_Steady +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine UA_CalcContStateDeriv( i, j, t, u, p, x, OtherState, AFInfo, m, dxdt, ErrStat, ErrMsg ) +! Tight coupling routine for computing derivatives of continuous states +!.................................................................................................................................. + + INTEGER(IntKi), INTENT(IN ) :: i !< blade node counter + INTEGER(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(UA_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(UA_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(UA_ElementContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(UA_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + type(UA_MiscVarType), intent(inout) :: m ! Misc/optimization variables + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + TYPE(UA_ElementContinuousStateType), INTENT( OUT) :: dxdt ! Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + + type(AFI_UA_BL_Type) :: BL_p ! potentially interpolated UA parameters + type(AFI_OutputType) :: AFI_Interp + character(ErrMsgLen) :: errMsg2 + integer(IntKi) :: errStat2 + character(*), parameter :: RoutineName = 'UA_CalcContStateDeriv' + + real(ReKi) :: Tu + real(ReKi) :: alphaE + real(ReKi) :: alphaF + real(ReKi) :: Clp + real(R8Ki) :: x4 + real(ReKi) :: alpha_34 + real(ReKi), parameter :: U_dot = 0.0_ReKi ! at some point we may add this term + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Lookup values using Airfoil Info module + call AFI_ComputeUACoefs( AFInfo, u%Re, u%UserProp, BL_p, ErrMsg2, ErrStat2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + call Get_HGM_constants(i, j, p, u, x, BL_p, Tu, alpha_34, alphaE) ! compute Tu, alpha_34, and alphaE + + Clp = BL_p%c_lalpha * (alphaE - BL_p%alpha0) + pi * Tu * u%omega ! Eq. 13 + + ! calculate fs_aF (stored in AFI_interp%f_st): + + !note: BL_p%c_lalpha cannot be zero. UA is turned off at initialization if this occurs. + alphaF = x%x(3)/BL_p%c_lalpha + BL_p%alpha0 ! p. 13 + call AFI_ComputeAirfoilCoefs( alphaF, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + ! States + !x1: Downwash memory term 1 (rad) + !x2: Downwash memory term 2 (rad) + !x3: Clp', Lift coefficient with a time lag to the attached lift coeff + !x4: f'' , Final separation point function + + ! Constraining x4 between 0 and 1 increases numerical stability (should be done elsewhere, but we'll double check here in case there were perturbations on the state value) + x4 = max( min( x%x(4), 1.0_R8Ki ), 0.0_R8Ki ) + + dxdt%x(1) = -1.0_R8Ki / Tu * (BL_p%b1 + p%c(i,j) * U_dot/(2*u%u**2)) * x%x(1) + BL_p%b1 * BL_p%A1 / Tu * alpha_34 + dxdt%x(2) = -1.0_R8Ki / Tu * (BL_p%b2 + p%c(i,j) * U_dot/(2*u%u**2)) * x%x(2) + BL_p%b2 * BL_p%A2 / Tu * alpha_34 + dxdt%x(3) = -1.0_R8Ki / BL_p%T_p * x%x(3) + 1.0_ReKi / BL_p%T_p * Clp + dxdt%x(4) = -1.0_R8Ki / BL_p%T_f0 * x4 + 1.0_ReKi / BL_p%T_f0 * AFI_interp%f_st + +END SUBROUTINE UA_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Get_HGM_constants(i, j, p, u, x, BL_p, Tu, alpha_34, alphaE) + INTEGER(IntKi), INTENT(IN ) :: i !< blade node counter + INTEGER(IntKi), INTENT(IN ) :: j !< blade counter + TYPE(UA_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(UA_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(UA_ElementContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(AFI_UA_BL_Type), INTENT(IN ) :: BL_p ! potentially interpolated UA parameters + + REAL(ReKi), INTENT( OUT) :: alpha_34 + REAL(ReKi), INTENT( OUT) :: Tu + REAL(ReKi), INTENT( OUT) :: alphaE + + ! Local variables + real(ReKi) :: vx_34 + + + ! Variables derived from inputs + !u%u = U_ac = TwoNorm(u%v_ac) ! page 4 definitions + + Tu = p%c(i,j) / (2.0_ReKi* u%u) ! Eq. 23 + Tu = min(Tu, 50.0_ReKi) ! ensure the time constant doesn't exceed 50 s. + Tu = max(Tu, 0.001_ReKi) ! ensure the time constant doesn't get too small, either. + + vx_34 = u%v_ac(1) - u%omega * 0.5_ReKi*p%c(i,j) ! Eq. 1 + alpha_34 = atan2(vx_34, u%v_ac(2) ) ! page 5 definitions + + ! Variables derived from states + alphaE = alpha_34*(1.0_ReKi - BL_p%A1 - BL_p%A2) + x%x(1) + x%x(2) ! Eq. 12 + call MPi2Pi(alphaE) + +END SUBROUTINE Get_HGM_constants +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." Sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE UA_RK4( i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(UA_InputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(UA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(UA_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(UA_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(AFI_ParameterType), INTENT(IN ) :: AFInfo ! The airfoil parameter data + TYPE(UA_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 + + ! local variables + + TYPE(UA_ElementContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(UA_ElementContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(UA_ElementContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(UA_ElementContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(UA_ElementContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(UA_InputType) :: u_interp ! interpolated value of inputs + + REAL(DbKi) :: TPlusHalfDt + REAL(DbKi) :: TPlusDt + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'UA_RK4' + + + !NOTE: the error handling here assumes that we do not have any allocatable data in the inputs (u_interp) to be concerned with. + ! Also, We assume that if there is going to be an error in UA_CalcContStateDeriv, it will happen only on the first call + ! to the routine. + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! interpolate u to find u_interp = u(t) + CALL UA_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + x_tmp = x%element(i,j) + + ! find xdot at t + CALL UA_CalcContStateDeriv( i, j, t, u_interp, p, x_tmp, OtherState, AFInfo, m, k1, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + k1%x = p%dt * k1%x + + x_tmp%x = x%element(i,j)%x + 0.5 * k1%x + + ! interpolate u to find u_interp = u(t + dt/2) + TPlusHalfDt = t + 0.5_DbKi*p%dt + CALL UA_Input_ExtrapInterp(u, utimes, u_interp, TPlusHalfDt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt/2 + CALL UA_CalcContStateDeriv( i, j, TPlusHalfDt, u_interp, p, x_tmp, OtherState, AFInfo, m, k2, ErrStat2, ErrMsg2 ) + + k2%x = p%dt * k2%x + + x_tmp%x = x%element(i,j)%x + 0.5 * k2%x + + ! find xdot at t + dt/2 (note x_tmp has changed) + CALL UA_CalcContStateDeriv( i, j, TPlusHalfDt, u_interp, p, x_tmp, OtherState, AFInfo, m, k3, ErrStat2, ErrMsg2 ) + + k3%x = p%dt * k3%x + + x_tmp%x = x%element(i,j)%x + k3%x + + ! interpolate u to find u_interp = u(t + dt) + TPlusDt = t + p%dt + CALL UA_Input_ExtrapInterp(u, utimes, u_interp, TPlusDt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt + CALL UA_CalcContStateDeriv( i, j, TPlusDt, u_interp, p, x_tmp, OtherState, AFInfo, m, k4, ErrStat2, ErrMsg2 ) + + k4%x = p%dt * k4%x + + x%element(i,j)%x = x%element(i,j)%x + ( k1%x + 2. * k2%x + 2. * k3%x + k4%x ) / 6. + +END SUBROUTINE UA_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE UA_AB4( i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(UA_InputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(UA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(UA_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(UA_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(AFI_ParameterType), INTENT(IN ) :: AFInfo ! The airfoil parameter data + TYPE(UA_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 + + + ! local variables + TYPE(UA_InputType) :: u_interp + TYPE(UA_ElementContinuousStateType) :: x_tmp + TYPE(UA_ElementContinuousStateType) :: xdot + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'UA_AB4' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + if (OtherState%n(i,j) < n) then + + OtherState%n(i,j) = n + + OtherState%xdot(4)%element(i,j) = OtherState%xdot(3)%element(i,j) + OtherState%xdot(3)%element(i,j) = OtherState%xdot(2)%element(i,j) + OtherState%xdot(2)%element(i,j) = OtherState%xdot(1)%element(i,j) + + elseif (OtherState%n(i,j) > n) then + + CALL SetErrStat(ErrID_Fatal,'Backing up in time is not supported with a multistep method.',ErrStat,ErrMsg,RoutineName) + RETURN + + endif + + + ! need xdot at t, get inputs at t + CALL UA_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + x_tmp = x%element(i,j) + + CALL UA_CalcContStateDeriv( i, j, t, u_interp, p, x_tmp, OtherState, AFInfo, m, xdot, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! make sure OtherState%xdot( 1 ) is most up to date: + OtherState%xdot( 1 )%element(i,j) = xdot + + if (n <= 2) then + + CALL UA_RK4(i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + else + x%element(i,j)%x = x%element(i,j)%x + p%DT/24. * ( 55.*OtherState%xdot(1)%element(i,j)%x - 59.*OtherState%xdot(2)%element(i,j)%x & + + 37.*OtherState%xdot(3)%element(i,j)%x - 9.*OtherState%xdot(4)%element(i,j)%x ) + + + endif + + +END SUBROUTINE UA_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: \n +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: \n +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE UA_ABM4( i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + integer(IntKi), INTENT(IN ) :: i !< blade node counter + integer(IntKi), INTENT(IN ) :: j !< blade counter + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(UA_InputType), INTENT(IN ) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(UA_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(UA_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(UA_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(AFI_ParameterType), INTENT(IN ) :: AFInfo ! The airfoil parameter data + TYPE(UA_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 + + ! local variables + + TYPE(UA_InputType) :: u_interp ! Inputs at t + TYPE(UA_ElementContinuousStateType) :: x_in ! Continuous states at t + TYPE(UA_ElementContinuousStateType) :: xdot_pred ! Derivative of continuous states at t + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'UA_ABM4' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! save copy of x(t): + x_in = x%element(i,j) + + ! predict: (note that we are overwritting x%element(i,j) here): + CALL UA_AB4( i, j, t, n, u, utimes, p, x, OtherState, AFInfo, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + if (n > 2_IntKi) then + + ! correct: + + CALL UA_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL UA_CalcContStateDeriv( i, j, t + p%dt, u_interp, p, x%element(i,j), OtherState, AFInfo, m, xdot_pred, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + + x%element(i,j)%x = x_in%x + p%DT/24. * ( 9. * xdot_pred%x + 19. * OtherState%xdot(1)%element(i,j)%x & + - 5. * OtherState%xdot(2)%element(i,j)%x & + + 1. * OtherState%xdot(3)%element(i,j)%x ) + + endif + +END SUBROUTINE UA_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +!---------------------------------------------------------------------------------------------------------------------------------- + + + +!============================================================================== +subroutine UA_CalcOutput( i, j, u, p, x, xd, OtherState, AFInfo, y, misc, ErrStat, ErrMsg ) +! Routine for computing outputs, used in both loose and tight coupling. +!.............................................................................. + + integer(IntKi), intent(in ) :: i ! node index within a blade + integer(IntKi), intent(in ) :: j ! blade index + type(UA_InputType), intent(in ) :: u ! Inputs at Time + type(UA_ParameterType), intent(in ) :: p ! Parameters + type(UA_ContinuousStateType), intent(in ) :: x ! Continuous states at Time + type(UA_DiscreteStateType), intent(in ) :: xd ! Discrete states at Time + type(UA_OtherStateType), intent(in ) :: OtherState ! Other states at Time + type(AFI_ParameterType), intent(in ) :: AFInfo ! The airfoil parameter data + type(UA_OutputType), intent(inout) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + type(UA_MiscVarType), intent(inout) :: misc ! Misc/optimization variables + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + integer(IntKi) :: errStat2 ! Error status of the operation (secondary error) + character(ErrMsgLen) :: errMsg2 ! Error message if ErrStat2 /= ErrID_None + character(*), parameter :: RoutineName = 'UA_CalcOutput' + + type(AFI_UA_BL_Type) :: BL_p ! airfoil values computed in Kelvin Chain + type(UA_KelvinChainType) :: KC ! values computed in Kelvin Chain + + real(ReKi) :: Cm_FS + real(ReKi) :: Cc_FS + real(ReKi) :: Cm_alpha_nc + real(ReKi) :: M, f, k2_hat + real(ReKi) :: Cm_v, alpha_prime_f + real(ReKi) :: x_cp_hat ! center-of-pressure distance from LE in chord fraction + real(ReKi) :: Cm_common ! + + ! for UA_HGM + real(ReKi) :: alphaE + real(ReKi) :: Tu + real(ReKi) :: alpha_34 + real(ReKi) :: fs_aE + real(ReKi) :: cl_fs + real(ReKi) :: x4 + real(ReKi) :: delta_c_df_primeprime + real(ReKi), parameter :: delta_c_mf_primeprime = 0.0_ReKi + TYPE(UA_ElementContinuousStateType) :: x_in ! Continuous states at t + + + type(AFI_OutputType) :: AFI_interp + +#ifdef UA_OUTS + integer :: iOffset +#endif + + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + Cm_alpha_nc = 0.0_ReKi + + AFI_interp%Cm = 0.0_ReKi ! value will be output if not computed below + alpha_prime_f = 0.0_ReKi ! value will be output if not computed below + + if ( (OtherState%FirstPass(i, j) .and. p%UAMod /= UA_HGM) .or. EqualRealNos(u%U, 0.0_ReKi) ) then ! note: if u%U is = 0 in UpdateStates, BEMT shuts off UA; however, it could still be called with u%U=TwoNorm(u%v_ac)=0 here + + call AFI_ComputeAirfoilCoefs( u%alpha, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + y%Cl = AFI_interp%Cl + y%Cd = AFI_interp%Cd + y%Cm = AFI_interp%Cm + + + y%Cn = y%Cl*cos(u%alpha) + (y%Cd-AFI_interp%Cd0)*sin(u%alpha) + y%Cc = y%Cl*sin(u%alpha) - (y%Cd-AFI_interp%Cd0)*cos(u%alpha) + + Cm_v = 0.0_ReKi + KC%Cn_alpha_q_circ = 0.0_ReKi + KC%Cn_alpha_q_nc = 0.0_ReKi + KC%Cn_pot = 0.0_ReKi + KC%Dp = 0.0_ReKi + KC%Cn_prime = 0.0_ReKi + KC%fprime = 0.0_ReKi + KC%Df = 0.0_ReKi + KC%Cn_V = 0.0_ReKi + KC%C_V = 0.0_ReKi + KC%Cm_q_circ = 0.0_ReKi + KC%Cm_q_nc = 0.0_ReKi + KC%Dalphaf = 0.0_ReKi + KC%T_f = 0.0_ReKi + KC%T_V = 0.0_ReKi + KC%alpha_filt_cur = 0.0_ReKi + KC%ds = 2.0_ReKi*u%U*p%dt/p%c(i, j) + + alphaE = 0.0 + Tu = 0.0 + alpha_34 = 0.0 + cl_fs = 0.0 + fs_aE = 0.0 + + elseif (p%UAMod == UA_HGM) then + x_in = x%element(i,j) + + if (OtherState%FirstPass(i,j)) then + call HGM_Steady( i, j, u, p, x_in, AFInfo, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + call AFI_ComputeUACoefs( AFInfo, u%Re, u%UserProp, BL_p, ErrMsg2, ErrStat2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + call Get_HGM_constants(i, j, p, u, x_in, BL_p, Tu, alpha_34, alphaE) ! compute Tu, alpha_34, and alphaE + + call AFI_ComputeAirfoilCoefs( alphaE, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! calculate fs_aE and cl_fs: + cl_fs = AFI_interp%cl_fs + fs_aE = AFI_interp%f_st + + ! Constraining x4 between 0 and 1 increases numerical stability (should be done elsewhere, but we'll double check here in case there were perturbations on the state value) + x4 = max( min( x_in%x(4), 1.0_R8Ki ), 0.0_R8Ki ) + + delta_c_df_primeprime = 0.5_ReKi * (sqrt(fs_aE) - sqrt(x4)) - 0.25_ReKi * (fs_aE - x4) + +! bjj: do we need to check that u%alpha is between -pi and + pi? + y%Cl = x4 * (alphaE - BL_p%alpha0) * BL_p%c_lalpha + (1.0_ReKi - x4) * cl_fs + pi * Tu * u%omega ! Eq. 78 + y%Cd = AFI_interp%Cd + (u%alpha - alphaE) * y%Cl + (AFI_interp%Cd - BL_p%Cd0) * delta_c_df_primeprime ! Eq. 79 + + if (AFInfo%ColCm == 0) then ! we don't have a cm column, so make everything 0 + y%Cm = 0.0_ReKi + else + y%Cm = AFI_interp%Cm + y%Cl * delta_c_mf_primeprime - piBy2 * Tu * u%omega ! Eq. 80 + end if + + y%Cn = y%Cl*cos(u%alpha) + y%Cd*sin(u%alpha) + y%Cc = y%Cl*sin(u%alpha) - y%Cd*cos(u%alpha) + + else + + M = u%U / p%a_s + + call UA_CheckMachNumber(M, misc%FirstWarn_M, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + call ComputeKelvinChain( i, j, u, p, xd, OtherState, misc, AFInfo, KC, BL_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + !............................. + ! Cn + !............................. + ! Eqn 1.53 or 1.53b depending on UAMod + if (xd%tau_v(i, j) > 0.0) then + y%Cn= KC%Cn_FS + KC%Cn_v ! Eqn 1.53 + else + y%Cn= KC%Cn_FS + end if + + !............................. + ! Cc + !............................. + + + if ( p%flookup ) then + !if ( p%UAMod == UA_Gonzalez ) then + Cc_FS = BL_p%eta_e*KC%Cc_pot *(sqrt(KC%fprimeprime_c) - Gonzalez_factor) ! Eqn 1.40 + else + Cc_FS = BL_p%eta_e*KC%Cc_pot * sqrt(KC%fprimeprime_c) ! Eqn 1.40 without Gonzalez's modification for negative Cc + end if + + + if ( p%UAMod == UA_MinnemaPierce ) then +#ifdef TEST_THEORY + y%Cc = Cc_FS + KC%Cn_v*tan(KC%alpha_e)*(1-xd%tau_v(i, j)/(BL_p%T_VL)) ! Eqn 1.55 with Eqn. 1.40 +#else + y%Cc = Cc_FS + KC%Cn_v* KC%alpha_e *(1.0_ReKi-xd%tau_v(i, j)/(BL_p%T_VL)) ! Eqn 1.55 with approximation of tan(KC%alpha_e)=KC%alpha_e and Eqn. 1.40 substitution +#endif + + elseif ( p%UAMod == UA_Gonzalez ) then + y%Cc = Cc_FS ! Eqn. 1.55b + else + ! TODO: This is UAMod = 1 and we still need to verify these equations!!! GJH Dec 20 2015 + if ( KC%Cn_prime <= BL_p%Cn1 ) then + !y%Cc = BL_p%eta_e*KC%Cc_pot*(sqrt(KC%fprimeprime_c) - f_c_offset) !*sin(KC%alpha_e + BL_p%alpha0) + y%Cc = Cc_FS * sin(KC%alpha_e + BL_p%alpha0) ! Eqn 1.56a [1] + else + if ( p%flookup ) then + ! if (p%UAMod == UA_Baseline) then + ! call Get_f_from_Lookup( p%UAMod, u%Re, u%UserProp, KC%alpha_filt_cur, BL_p%alpha0, KC%C_nalpha_circ, AFInfo, ErrStat2, ErrMsg2, f=f) + ! else + ! TODO: Need to understand the effect of the offset on this f in the following equations and fprimeprime_c. + !bjj: fprimeprime_c is computed with the Gonzalez offset in the Kelvin Chain, so it's not just f that could be a problem. + f = Get_f_c_from_Lookup( p%UAMod, u%Re, u%UserProp, KC%alpha_filt_cur, BL_p%alpha0, KC%C_nalpha_circ, BL_p%eta_e, AFInfo, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! endif + + else + f = Get_f( KC%alpha_filt_cur, BL_p%alpha0, BL_p%alpha1, BL_p%alpha2, BL_p%S1, BL_p%S2, BL_p%S3, BL_p%S4 ) + end if + + k2_hat = 2.0_ReKi*(KC%Cn_prime - BL_p%Cn1) + KC%fprimeprime_c - f ! Eqn 1.56b + ! TODO: why did we comment out the sin() term below? GJH 2/28/2017 + y%Cc = BL_p%k1_hat + KC%Cc_pot*sqrt(KC%fprimeprime_c)*KC%fprimeprime_c**k2_hat *sin(KC%alpha_e + BL_p%alpha0) ! Eqn 1.56a [2] + + end if + + end if + + !............................. + ! convert cc and cn to cl and cd + !............................. + + y%Cl = y%Cn*cos(u%alpha) + y%Cc*sin(u%alpha) ! Eqn 1.2a + y%Cd = y%Cn*sin(u%alpha) - y%Cc*cos(u%alpha) + BL_p%Cd0 ! Eqn 1.2b + + ! Make Cn and CC consistent with the added contribution of Cd0 in Cd: + y%Cn = y%Cl*cos(u%alpha) + y%Cd*sin(u%alpha) !Added the contribution of Cd0 in Cn and Cc + y%Cc = y%Cl*sin(u%alpha) - y%Cd*cos(u%alpha) + + !............................. + ! convert cm + !............................. + + alpha_prime_f = 0.0_ReKi ! initialize for output purposes + + ! Check for Cm column in AFInfo data + if (AFInfo%ColCm == 0) then ! we don't have a cm column, so make everything 0 + + y%Cm = 0.0_ReKi + Cm_v = 0.0_ReKi + + else + + if ( p%UAMod == UA_Gonzalez ) then !bjj: what is this doing? + + if (abs(KC%alpha_f - BL_p%alpha0) < .01) then + if (KC%alpha_f < BL_p%alpha0) then + KC%alpha_f = KC%alpha_f - .01 + else + KC%alpha_f = KC%alpha_f + .01 + end if + end if ! Removed part of the code related to fprimeprime_m, which has been added in other part of the code + + end if + + !........... + ! compute Cm_FS + !........... + + Cm_alpha_nc = - KC%Cn_alpha_nc / 4.0_ReKi ! Eqn 1.27 + Cm_common = KC%Cm_q_circ + Cm_alpha_nc + KC%Cm_q_nc ! second parts of Eqn 1.41, Eqn 1.44, and Eqn 1.45 + + if ( p%UAMod == UA_Baseline ) then + + x_cp_hat = BL_p%k0 + BL_p%k1*(1.0_ReKi-KC%fprimeprime) + BL_p%k2*sin(pi*KC%fprimeprime**BL_p%k3) ! Eqn 1.42 + Cm_FS = BL_p%Cm0 - KC%Cn_alpha_q_circ*(x_cp_hat - 0.25_ReKi) + Cm_common ! Eqn 1.41 + + elseif ( p%UAMod == UA_MinnemaPierce ) then + + ! Look up Cm using alpha_prime_f + alpha_prime_f = KC%alpha_f - KC%Dalphaf ! Eqn 1.43a + + call AFI_ComputeAirfoilCoefs( alpha_prime_f, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + Cm_FS = AFI_interp%Cm + Cm_common ! Eqn 1.44 + else ! UAMod == UA_Gonzalez + Cm_FS = BL_p%Cm0 + KC%Cn_FS*KC%fprimeprime_m + Cm_common ! Eqn 1.45 + + end if + + Cm_v = -BL_p%x_cp_bar*( 1.0_ReKi - cos( pi*xd%tau_v(i, j)/BL_p%T_VL ) )*KC%Cn_v ! Eqn 1.57 + if (p%UAMod == UA_Gonzalez .and. xd%tau_v(i, j) <= 0.0 ) then !Added specific logic for UAMod=UA_Gonzalez + y%Cm = Cm_FS + else + y%Cm = Cm_FS + Cm_v ! Eqn 1.58, Eqn 1.59, and Eqn 1.60 + end if + + end if + end if + +#ifdef UA_OUTS + iOffset = (i-1)*p%NumOuts + (j-1)*p%nNodesPerBlade*p%NumOuts + if (allocated(y%WriteOutput)) then !bjj: because BEMT uses local variables for UA output, y%WriteOutput is not necessarially allocated. Need to figure out a better solution. + + y%WriteOutput(iOffset+ 2) = u%U + y%WriteOutput(iOffset+ 3) = y%Cn + y%WriteOutput(iOffset+ 4) = y%Cc + y%WriteOutput(iOffset+ 5) = y%Cl + y%WriteOutput(iOffset+ 6) = y%Cd + y%WriteOutput(iOffset+ 7) = y%Cm + + if (p%UAMod == UA_HGM) then + + y%WriteOutput(iOffset+ 1) = u%alpha*R2D + + y%WriteOutput(iOffset+ 8) = u%omega*R2D + y%WriteOutput(iOffset+ 9) = alphaE*R2D + y%WriteOutput(iOffset+10) = Tu + y%WriteOutput(iOffset+11) = alpha_34*R2D + y%WriteOutput(iOffset+12) = cl_fs + y%WriteOutput(iOffset+13) = fs_aE + + y%WriteOutput(iOffset+14) = x%element(i,j)%x(1) + y%WriteOutput(iOffset+15) = x%element(i,j)%x(2) + y%WriteOutput(iOffset+16) = x%element(i,j)%x(3) + y%WriteOutput(iOffset+17) = x%element(i,j)%x(4) + + else + y%WriteOutput(iOffset+ 1) = KC%alpha_filt_cur*R2D + + y%WriteOutput(iOffset+ 8) = KC%Cn_alpha_q_circ ! CNCP in ADv14 + y%WriteOutput(iOffset+ 9) = KC%Cn_alpha_q_nc ! CNIQ in ADv14 + y%WriteOutput(iOffset+10) = KC%Cn_pot + y%WriteOutput(iOffset+11) = KC%Dp + y%WriteOutput(iOffset+12) = KC%Cn_prime + y%WriteOutput(iOffset+13) = KC%fprime + y%WriteOutput(iOffset+14) = KC%Df + y%WriteOutput(iOffset+15) = KC%Cn_V + y%WriteOutput(iOffset+16) = xd%tau_v(i, j) + + if ( misc%LESF(i, j) ) then ! BEDSEP in v14 !bjj: note that this output is calculated in UpdateDiscState, so it may be out of sync here. + y%WriteOutput(iOffset+17) = 1.0_ReKi + else + y%WriteOutput(iOffset+17) = 0.0_ReKi + end if + + if ( misc%TESF(i, j) ) then !SHIFT in v14 !bjj: note that this output is calculated in UpdateDiscState, so it may be out of sync here. + y%WriteOutput(iOffset+18) = 1.0_ReKi + else + y%WriteOutput(iOffset+18) = 0.0_ReKi + end if + if ( misc%VRTX(i, j) ) then ! VOR in v14 !bjj: note that this output is calculated in UpdateDiscState, so it may be out of sync here. + y%WriteOutput(iOffset+19) = 1.0_ReKi + else + y%WriteOutput(iOffset+19) = 0.0_ReKi + end if + y%WriteOutput(iOffset+20) = KC%C_V + y%WriteOutput(iOffset+21) = Cm_alpha_nc + y%WriteOutput(iOffset+22) = KC%Cm_q_nc + y%WriteOutput(iOffset+23) = Cm_v + y%WriteOutput(iOffset+24) = alpha_prime_f + y%WriteOutput(iOffset+25) = KC%Dalphaf + y%WriteOutput(iOffset+26) = AFI_interp%Cm + y%WriteOutput(iOffset+27) = KC%T_f + y%WriteOutput(iOffset+28) = KC%T_V + y%WriteOutput(iOffset+29) = KC%ds ! Eqn 1.51 (tau_v) + y%WriteOutput(iOffset+30) = KC%T_alpha + y%WriteOutput(iOffset+31) = KC%T_q + y%WriteOutput(iOffset+32) = KC%k_alpha + y%WriteOutput(iOffset+33) = KC%k_q + y%WriteOutput(iOffset+34) = KC%alpha_e + y%WriteOutput(iOffset+35) = KC%X1 + y%WriteOutput(iOffset+36) = KC%X2 + y%WriteOutput(iOffset+37) = KC%cn_q_nc + y%WriteOutput(iOffset+38) = KC%alpha_f + y%WriteOutput(iOffset+39) = KC%fprimeprime + y%WriteOutput(iOffset+40) = OtherState%sigma1(i, j) + y%WriteOutput(iOffset+41) = OtherState%sigma3(i, j) + y%WriteOutput(iOffset+42) = misc%T_sh(i, j) + end if + end if +#endif + +end subroutine UA_CalcOutput +!============================================================================== +!> This subroutine checks that the Mach number is valid. If M > 0.3, the theory +!! is invalid. If M > 1, numerical issues result in the code. +subroutine UA_CheckMachNumber(M, FirstWarn_M, ErrStat, ErrMsg ) + + real(ReKi), intent(in ) :: M !< Mach number (-) + logical, intent(inout) :: FirstWarn_M !< is this the first warning about Mach number? + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + if (abs(M) > 0.3_ReKi) then + if (abs(M) >= 1.0_ReKi) then + ErrStat = ErrID_Fatal + ErrMsg = 'Mach number exceeds 1.0. Equations cannot be evaluated.' + else + if ( FirstWarn_M ) then + ErrStat = ErrID_Warn + ErrMsg = 'Mach number exceeds 0.3. Theory is invalid. This warning will not be repeated though the condition may persist.' + FirstWarn_M = .false. + else + ErrStat = ErrID_None + ErrMsg = "" + end if + end if + else + ErrStat = ErrID_None + ErrMsg = "" + end if + + +end subroutine UA_CheckMachNumber + + + + + +end module UnsteadyAero diff --git a/OpenFAST/modules/aerodyn/src/UnsteadyAero_Driver.f90 b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Driver.f90 new file mode 100644 index 000000000..e544a7850 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Driver.f90 @@ -0,0 +1,350 @@ +!********************************************************************************************************************************** +! UnsteadyAero_DriverCode: This code tests a stand-alone version of the UnsteadyAero module +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! This file is part of UnsteadyAero. +! +! 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. +! +!********************************************************************************************************************************** + + + + + +program UnsteadyAero_Driver + + use NWTC_Library + use AirfoilInfo + use AirfoilInfo_Types + use UnsteadyAero_Types + use UnsteadyAero + use UA_Dvr_Subs + USE VersionInfo + + implicit none + + + + + + ! Variables + integer(IntKi), parameter :: NumInp = 2 ! Number of inputs sent to UA_UpdateStates (must be at least 2) + + real(DbKi) :: dt, t, uTimes(NumInp) + integer :: i, j, k, n, iu + type(UA_InitInputType) :: InitInData ! Input data for initialization + type(UA_InitOutputType) :: InitOutData ! Output data from initialization + type(UA_ContinuousStateType) :: x ! Continuous states + type(UA_DiscreteStateType) :: xd ! Discrete states + type(UA_OtherStateType) :: OtherState ! Other/optimization states + type(UA_MiscVarType) :: m ! Misc/optimization variables + type(UA_ParameterType) :: p ! Parameters + type(UA_InputType) :: u(NumInp) ! System inputs + type(UA_OutputType) :: y ! System outputs + integer(IntKi) :: ErrStat ! Status of error message + character(ErrMsgLen) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer, parameter :: NumAFfiles = 1 + character(1024) :: afNames(NumAFfiles) + type(AFI_ParameterType) :: AFI_Params(NumAFfiles) + integer, allocatable :: AFIndx(:,:) + character(1024) :: outFileName + integer :: unOutFile + character(200) :: TimeFrmt, Frmt + CHARACTER(1024) :: dvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. + TYPE(UA_Dvr_InitInput) :: dvrInitInp ! Initialization data for the driver program + real(DbKi) :: simTime + integer :: nSimSteps + character(*), parameter :: RoutineName = 'UnsteadyAero_Driver' + real(DbKi), allocatable :: timeArr(:) + real(ReKi), allocatable :: AOAarr(:) + real(ReKi), allocatable :: Uarr(:) + real(ReKi), allocatable :: OmegaArr(:) + + CHARACTER(200) :: git_commit + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'UnsteadyAero Driver', '', '' ) ! The version number of this program. + ! Initialize the NWTC library + call NWTC_Init() + + ! Initialize error handling variables + ErrMsg = '' + ErrStat = ErrID_None + + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + + ! Parse the driver file if one was provided, if not, then set driver parameters using hardcoded values + if ( command_argument_count() > 1 ) then + call print_help() + call checkError() + end if + + + ! Establish initialization inputs which are fixed for the stand-alone driver, but would be + ! variable for a coupled simulation + InitInData%nNodesPerBlade = 1 + InitInData%numBlades = 1 + + ! Set up initialization data + allocate(AFIndx(InitInData%nNodesPerBlade,InitInData%numBlades), STAT = ErrStat) + if ( ErrStat /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate InitInData%AFIndx.', ErrStat, ErrMsg, RoutineName) + call checkError() + end if + + allocate(InitInData%c(InitInData%nNodesPerBlade,InitInData%numBlades), STAT = ErrStat) + if ( ErrStat /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate InitInData%c.', ErrStat, ErrMsg, RoutineName) + call checkError() + end if + + + ! Parse the driver input file and run the simulation based on that file + + if ( command_argument_count() == 1 ) then + + call get_command_argument(1, dvrFilename) + call ReadDriverInputFile( dvrFilename, dvrInitInp, errStat, errMsg ) + call checkError() + InitInData%a_s = dvrInitInp%SpdSound + InitInData%c(1,1) = dvrInitInp%Chord + InitInData%UAMod = dvrInitInp%UAMod + InitInData%Flookup = dvrInitInp%Flookup + + else + + dvrInitInp%OutRootName = './TestingUA_Driver' + InitInData%UAMod = 1 + InitInData%Flookup = .FALSE. + InitInData%a_s = 340.29 ! m/s + InitInData%c(1,1) = 1.0 + + dvrInitInp%InflowVel = 30.0 ! m/s + dvrInitInp%Re = 75 ! million + dvrInitInp%AirFoil1 = './OSU075_FAST.txt' + dvrInitInp%SimMod = 1 + dvrInitInp%NCycles = 3.0 + dvrInitInp%Frequency = 1.2 ! Hz + dvrInitInp%StepsPerCycle= 180 + dvrInitInp%Amplitude = 10.0 ! deg + dvrInitInp%Mean = 2.0 ! deg + dvrInitInp%Phase = 0 ! steps of a cycle + dvrInitInp%InputsFile = '' + + end if + + if ( dvrInitInp%SimMod == 1 ) then + ! Using the frequency and NCycles, determine how long the simulation needs to run + simTime = dvrInitInp%NCycles/dvrInitInp%Frequency + nSimSteps = dvrInitInp%StepsPerCycle*dvrInitInp%NCycles ! we could add 1 here to make this a complete cycle + dt = simTime / nSimSteps + + else + ! Read time-series data file with a 1 line header and then each row contains time-step data with 4, white-space-separated columns + ! time, Angle-of-attack, Vrel, omega + call ReadTimeSeriesData( dvrInitInp%InputsFile, nSimSteps, timeArr, AOAarr, Uarr, OmegaArr, errStat, errMsg ) + call checkError() + dt = (timeArr(nSimSteps) - timeArr(1)) / (nSimSteps-1) + nSimSteps = nSimSteps-NumInp + 1 + + end if + + ! Initialize UnsteadyAero + call UA_Init( InitInData, u(1), p, x, xd, OtherState, y, m, dt, InitOutData, errStat, errMsg ) + call checkError() + + ! Initialize the Airfoil Info Params + afNames(1) = dvrInitInp%AirFoil1 ! All nodes/blades are using the same 2D airfoil + AFIndx(1,1) = 1 + call Init_AFI( p, NumAFfiles, afNames, dvrInitInp%UseCm, AFI_Params, errStat, errMsg ) + call checkError() + + if (p%NumOuts > 0) then + ! Initialize the output file + ! Open the file for output + outFileName = trim(dvrInitInp%OutRootName)//'.out' + call GetNewUnit( unOutFile ) + + call OpenFOutFile ( unOutFile, outFileName, errStat, errMsg ) + call checkError() + + ! Write the output file header + p%OutSFmt = 'A19' + p%OutFmt = 'ES19.5e2' + p%Delim ='' + + Frmt = '('//trim(Int2LStr(p%NumOuts*p%numBlades*p%nNodesPerBlade))//'(:,A,'//trim( p%OutSFmt )//'))' + + write (unOutFile,'(/,A/)', IOSTAT=ErrStat) 'These predictions were generated by UnSteadyAero on '//CurDate()//' at '//CurTime()//'.' + write (unOutFile,'(/,A/)', IOSTAT=ErrStat) 'Driver file name: '//trim(dvrFilename) + + ! Write the names of the output parameters: + write(unOutFile, '(A15)', ADVANCE='no') trim( 'Time' ) + write(unOutFile, Frmt, ADVANCE='no') ( p%Delim, trim( InitOutData%WriteOutputHdr(I) ), i=1,p%NumOuts*p%numBlades*p%nNodesPerBlade ) + write (unOutFile,'()', IOSTAT=ErrStat) ! write the line return + + ! Write the units of the output parameters: + write(unOutFile, '(A15)', ADVANCE='no') trim( '(sec)' ) + write(unOutFile, Frmt, ADVANCE='no') ( p%Delim, trim( InitOutData%WriteOutputUnt(I) ), i=1,p%NumOuts*p%numBlades*p%nNodesPerBlade ) + write (unOutFile,'()', IOSTAT=ErrStat) ! write the line return + + TimeFrmt = '(F15.4)' + Frmt = '('//trim(Int2LStr(p%NumOuts*p%numBlades*p%nNodesPerBlade))//'(:,A,'//trim( p%OutFmt )//'))' + end if + + + ! set inputs: + DO iu = 1, NumInp + call setUAinputs(-iu+2, u(iu), uTimes(iu), dt, dvrInitInp, timeArr, AOAarr, Uarr, OmegaArr) + END DO + + ! Set inputs which do not vary with node or time + + ! time marching loop + do n = 1, nSimSteps + + i = 1 ! nodes per blade + j = 1 ! number of blades + + ! set inputs: + DO iu = NumInp-1, 1, -1 + u( iu+1) = u( iu) + uTimes(iu+1) = uTimes(iu) + END DO + + ! first value of uTimes/u contain inputs at t+dt + call setUAinputs(n+1, u(1), uTimes(1), dt, dvrInitInp, timeArr, AOAarr, Uarr, OmegaArr) + + t = uTimes(2) + + ! Use existing states to compute the outputs + call UA_CalcOutput(i, j, u(2), p, x, xd, OtherState, AFI_Params(AFIndx(i,j)), y, m, errStat, errMsg ) + call checkError() + + ! Generate file outputs + if (p%NumOuts > 0) then + write (unOutFile,TimeFrmt,ADVANCE='no') t + write (unOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WriteOutput(k) , k=1,p%NumOuts*p%numBlades*p%nNodesPerBlade ) + write (unOutFile,'()', IOSTAT=ErrStat) ! write the line return + end if + + ! Prepare states for next time step + call UA_UpdateStates(i, j, t, n, u, uTimes, p, x, xd, OtherState, AFI_Params(AFIndx(i,j)), m, errStat, errMsg ) + call checkError() + + + end do + + ! write (unOutFile,'(/,A/)', IOSTAT=ErrStat) 'This output file was closed on '//CurDate()//' at '//CurTime()//'.' + + !------------------------------------------------------------------------------------------------- + ! Close our output file + !------------------------------------------------------------------------------------------------- + + + call Cleanup() + call NormStop() + + contains + + !==================================================================================================== + subroutine Cleanup() + ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + ! any existing echo information + !---------------------------------------------------------------------------------------------------- + + if (p%NumOuts > 0) close( unOutFile, IOSTAT = ErrStat ) + + + end subroutine Cleanup + + !---------------------------------------------------------------------------------------------------- + subroutine checkError() + + if (ErrStat >= AbortErrLev) then + + call Cleanup() + call ProgAbort(ErrMsg) + + elseif ( ErrStat /= ErrID_None ) then + + call WrScr( trim(ErrMsg) ) + + end if + + end subroutine checkError + !---------------------------------------------------------------------------------------------------- + subroutine setUAinputs(n,u,t,dt,dvrInitInp,timeArr,AOAarr,Uarr,OmegaArr) + + integer, intent(in) :: n + type(UA_InputType), intent(inout) :: u ! System inputs + real(DbKi), intent( out) :: t + real(DbKi), intent(in) :: dt + TYPE(UA_Dvr_InitInput), intent(in) :: dvrInitInp ! Initialization data for the driver program + real(DbKi), intent(in) :: timeArr(:) + real(ReKi), intent(in) :: AOAarr(:) + real(ReKi), intent(in) :: Uarr(:) + real(ReKi), intent(in) :: OmegaArr(:) + integer :: indx + real(ReKi) :: phase + + u%UserProp = 0 + u%Re = dvrInitInp%Re + + if ( dvrInitInp%SimMod == 1 ) then + t = (n-1)*dt + phase = (n+dvrInitInp%Phase-1)*2*pi/dvrInitInp%StepsPerCycle + u%alpha = (dvrInitInp%Amplitude * sin(phase) + dvrInitInp%Mean)*D2R ! This needs to be in radians + ! u%omega = dvrInitInp%Amplitude * cos(phase) * dvrInitInp%Frequency * pi**2 / 90.0 ! This needs to be in radians derivative: d_alpha /d_t + u%omega = dvrInitInp%Amplitude * cos(phase) * 2*pi/dvrInitInp%StepsPerCycle / dt * D2R ! This needs to be in radians derivative: d_alpha /d_t + + u%U = dvrInitInp%InflowVel ! m/s + else + indx = min(n,size(timeArr)) + + ! Load timestep data from the time-series inputs which were previous read from input file + t = timeArr(indx) + u%alpha = AOAarr(indx)*pi/180.0 ! This needs to be in radians + u%omega = OmegaArr(indx) + u%U = Uarr(indx) + if (n> size(timeArr)) then + t = t + dt*(n - size(timeArr) ) ! update for NumInp>1; + end if + end if + u%v_ac(1) = sin(u%alpha)*u%U + u%v_ac(2) = cos(u%alpha)*u%U + + end subroutine setUAinputs + !---------------------------------------------------------------------------------------------------- + + subroutine print_help() + print '(a)', 'usage: ' + print '(a)', '' + print '(a)', 'UnsteadyAero_Driver.exe [driverfilename]' + print '(a)', '' + print '(a)', 'Where the optional argument, driverfilename, is the name of the UnsteadyAero driver input file.' + print '(a)', '' + + end subroutine print_help + +end program UnsteadyAero_Driver + diff --git a/OpenFAST/modules/aerodyn/src/UnsteadyAero_Registry.txt b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Registry.txt new file mode 100644 index 000000000..617a09cf5 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Registry.txt @@ -0,0 +1,198 @@ +################################################################################################################################### +# Registry for UnsteadyAero in the FAST Modularization Framework +# This Registry file is used to create MODULE UnsteadyAero which contains all of the user-defined types needed in UnsteadyAero. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt +usefrom AirfoilInfo_Registry.txt +# +# +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef UnsteadyAero/UA InitInputType DbKi dt - - - "time step" s +typedef ^ ^ CHARACTER(1024) OutRootName - - - "Supplied by Driver: The name of the root file (without extension) including the full path" - +typedef ^ ^ ReKi c {:}{:} - - "Chord length at node" m +typedef ^ ^ INTEGER numBlades - - - "Number nodes of all blades" - +typedef ^ ^ INTEGER nNodesPerBlade - - - "Number nodes per blades" - +typedef ^ ^ INTEGER UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - +typedef ^ ^ ReKi a_s - - - "speed of sound" m/s +typedef ^ ^ LOGICAL Flookup - - - "Use table lookup for f' and f'' " - +typedef ^ ^ INTEGER NumOuts - - - "The number of outputs for this module as requested in the input file" - + +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType ProgDesc Version - - - "Version structure" - +typedef ^ InitOutputType CHARACTER(19) WriteOutputHdr {:} - - "The is the list of all UA-related output channel header strings (includes all sub-module channels)" - +typedef ^ ^ CHARACTER(19) WriteOutputUnt {:} - - "The is the list of all UA-related output channel unit strings (includes all sub-module channels)" - + + +# Variables local to the Kelvin Chain: +typedef ^ UA_KelvinChainType ReKi Cn_prime - - - "" - +#typedef ^ UA_KelvinChainType ReKi Cn_prime_diff - - - "" - +typedef ^ UA_KelvinChainType ReKi C_nalpha_circ - - - "slope of the circulatory normal force coefficient vs alpha curve" - +typedef ^ UA_KelvinChainType ReKi Kalpha_f - - - "filtered backwards finite difference of alpha (xd%Kalpha_f_minus1)" - +typedef ^ UA_KelvinChainType ReKi Kq_f - - - "filtered backwards finite difference of q" - +typedef ^ UA_KelvinChainType ReKi alpha_filt_cur - - - "filtered angle of attack" - +typedef ^ UA_KelvinChainType ReKi alpha_e - - - "effective angle of attack at 3/4 chord TODO: verify 3/4 and not 1/4" - +typedef ^ UA_KelvinChainType ReKi dalpha0 - - - "" - +typedef ^ UA_KelvinChainType ReKi alpha_f - - - "" - +typedef ^ UA_KelvinChainType ReKi Kq - - - "" - +typedef ^ UA_KelvinChainType ReKi q_cur - - - "" - +typedef ^ UA_KelvinChainType ReKi q_f_cur - - - "" - +typedef ^ UA_KelvinChainType ReKi X1 - - - "" - +typedef ^ UA_KelvinChainType ReKi X2 - - - "" - +typedef ^ UA_KelvinChainType ReKi X3 - - - "" - +typedef ^ UA_KelvinChainType ReKi X4 - - - "" - +typedef ^ UA_KelvinChainType ReKi Kprime_alpha - - - "" - +typedef ^ UA_KelvinChainType ReKi Kprime_q - - - "" - +typedef ^ UA_KelvinChainType ReKi Dp - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_pot - - - "" - +typedef ^ UA_KelvinChainType ReKi Cc_pot - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_alpha_q_circ - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_alpha_q_nc - - - "non-circulatory component of normal force coefficient response to step change in alpha and q" - +typedef ^ UA_KelvinChainType ReKi Cm_q_circ - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_alpha_nc - - - "non-circulatory component of the normal force coefficient response to step change in alpha" - +typedef ^ UA_KelvinChainType ReKi Cn_q_circ - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_q_nc - - - "" - +typedef ^ UA_KelvinChainType ReKi Cm_q_nc - - - "non-circulatory component of the moment coefficient response to step change in q" - +typedef ^ UA_KelvinChainType ReKi fprimeprime - - - "" - +typedef ^ UA_KelvinChainType ReKi Df - - - "" - +typedef ^ UA_KelvinChainType ReKi Df_c - - - "" - +typedef ^ UA_KelvinChainType ReKi Df_m - - - "" - +typedef ^ UA_KelvinChainType ReKi Dalphaf - - - "" - +typedef ^ UA_KelvinChainType ReKi fprime - - - "" - +typedef ^ UA_KelvinChainType ReKi fprime_c - - - "" - +typedef ^ UA_KelvinChainType ReKi fprimeprime_c - - - "" - +typedef ^ UA_KelvinChainType ReKi fprime_m - - - "" - +typedef ^ UA_KelvinChainType ReKi fprimeprime_m - - - "" - +typedef ^ UA_KelvinChainType ReKi Cn_v - - - "normal force coefficient due to the presence of LE vortex" - +typedef ^ UA_KelvinChainType ReKi C_V - - - "contribution to the normal force coefficient due to accumulated vorticity in the LE vortex" - +typedef ^ UA_KelvinChainType ReKi Cn_FS - - - "" - +typedef ^ UA_KelvinChainType ReKi T_f - - - "" - +typedef ^ UA_KelvinChainType ReKi T_fc - - - "" - +typedef ^ UA_KelvinChainType ReKi T_fm - - - "" - +typedef ^ UA_KelvinChainType ReKi T_V - - - "backwards finite difference of the non-dimensionalized distance parameter" - +typedef ^ UA_KelvinChainType ReKi k_alpha - - - "" - +typedef ^ UA_KelvinChainType ReKi k_q - - - "" - +typedef ^ UA_KelvinChainType ReKi T_alpha - - - "" - +typedef ^ UA_KelvinChainType ReKi T_q - - - "" - +typedef ^ UA_KelvinChainType ReKi ds - - - "non-dimensionalized distance parameter" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ UA_ElementContinuousStateType R8Ki x 4 - - "continuous states when UA_Mod=4 (x1 and x2:Downwash memory terms; x3:Clp', Lift coefficient with a time lag to the attached lift coeff; x4: f'' , Final separation point function)" "{rad, rad, - -}" +typedef ^ ContinuousStateType UA_ElementContinuousStateType element {:}{:} - - "continuous states when UA_Mod=4 for each blade/node" "-" + +# Define discrete (non-differentiable) states here: +# +typedef ^ DiscreteStateType ReKi alpha_minus1 {:}{:} - - "angle of attack, previous time step" rad +typedef ^ DiscreteStateType ReKi alpha_filt_minus1 {:}{:} - - "filtered angle of attack, previous time step" rad +typedef ^ DiscreteStateType ReKi q_minus1 {:}{:} - - "non-dimensional pitching rate, previous time step" - +typedef ^ DiscreteStateType ReKi Kalpha_f_minus1 {:}{:} - - "filtered pitching rate, previous time step" - +typedef ^ DiscreteStateType ReKi Kq_f_minus1 {:}{:} - - "filtered pitching acceleration, previous time step" - +typedef ^ DiscreteStateType ReKi q_f_minus1 {:}{:} - - "filtered non-dimensional pitching rate, previous time step" - +typedef ^ DiscreteStateType ReKi X1_minus1 {:}{:} - - "deficiency function used in the development of Cn_alpha_q_circ, previous time step" rad +typedef ^ DiscreteStateType ReKi X2_minus1 {:}{:} - - "deficiency function used in the development of Cn_alpha_q_circ, previous time step" rad +typedef ^ DiscreteStateType ReKi X3_minus1 {:}{:} - - "deficiency function used in the development of Cn_q_circ, previous time step" rad +typedef ^ DiscreteStateType ReKi X4_minus1 {:}{:} - - "deficiency function used in the development of Cn_q_circ, previous time step" rad +typedef ^ DiscreteStateType ReKi Kprime_alpha_minus1 {:}{:} - - "deficiency function used in the development of Cn_alpha_nc, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Kprime_q_minus1 {:}{:} - - "deficiency function used in the development of Cn_q_nc, previous time step" rad/s^2 +typedef ^ DiscreteStateType ReKi Kprimeprime_q_minus1 {:}{:} - - "deficiency function used in the development of Cm_q_nc, previous time step" rad/s^2 +typedef ^ DiscreteStateType ReKi K3prime_q_minus1 {:}{:} - - "deficiency function used in the development of Cm_q_circ, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Dp_minus1 {:}{:} - - "deficiency function used in the development of Cm_q_circ, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Cn_pot_minus1 {:}{:} - - "deficiency function used in the development of Cn_prime" - +typedef ^ DiscreteStateType ReKi fprimeprime_minus1 {:}{:} - - "lagged version of fprime, accounting for unsteady boundary layer response, previous time step" - +typedef ^ DiscreteStateType ReKi fprimeprime_c_minus1 {:}{:} - - "lagged version of fprime_c, accounting for unsteady boundary layer response, previous time step" - +typedef ^ DiscreteStateType ReKi fprimeprime_m_minus1 {:}{:} - - "lagged version of fprime_m, accounting for unsteady boundary layer response, previous time step" - +typedef ^ DiscreteStateType ReKi Df_minus1 {:}{:} - - "deficiency function used in the development of fprime, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Df_c_minus1 {:}{:} - - "deficiency function used in the development of fprime, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Df_m_minus1 {:}{:} - - "deficiency function used in the development of fprime, previous time step" rad/s +typedef ^ DiscreteStateType ReKi Dalphaf_minus1 {:}{:} - - "deficiency function used in the development of fprime, previous time step" rad/s +typedef ^ DiscreteStateType ReKi alphaf_minus1 {:}{:} - - "deficiency function used in the development of fprime, previous time step" rad/s +typedef ^ DiscreteStateType ReKi fprime_minus1 {:}{:} - - "separation point Cn distance from leading edge, expressed in cord fraction, previous time step" - +typedef ^ DiscreteStateType ReKi fprime_c_minus1 {:}{:} - - "separation point Ct distance from leading edge, expressed in cord fraction, previous time step" - +typedef ^ DiscreteStateType ReKi fprime_m_minus1 {:}{:} - - "Distance application of Cn with respect to Cm, previous time step" - +typedef ^ DiscreteStateType ReKi tau_V {:}{:} - - "time variable, tracking the travel of the LE vortex over the airfoil suction surface" - +typedef ^ DiscreteStateType ReKi tau_V_minus1 {:}{:} - - "time variable, tracking the travel of the LE vortex over the airfoil suction surface" - +typedef ^ DiscreteStateType ReKi Cn_v_minus1 {:}{:} - - "normal force coefficient due to the presence of LE vortex, previous time step" - +typedef ^ DiscreteStateType ReKi C_V_minus1 {:}{:} - - "contribution to the normal force coefficient due to accumulated vorticity in the LE vortex, previous time step" - +typedef ^ DiscreteStateType ReKi Cn_prime_minus1 {:}{:} - - "difference between Cn_prime and Cn_prime_minus1, previous time step" rad +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType ReKi DummyConstraintState - - - "" - +# +# +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType LOGICAL FirstPass {:}{:} - - "logical flag indicating if this is the first time step" - +typedef ^ OtherStateType ReKi sigma1 {:}{:} - - "multiplier for T_fn" - +typedef ^ OtherStateType ReKi sigma1c {:}{:} - - "multiplier for T_fc" - +typedef ^ OtherStateType ReKi sigma1m {:}{:} - - "multiplier for T_fm" - +typedef ^ OtherStateType ReKi sigma3 {:}{:} - - "multiplier for T_V" - +typedef ^ OtherStateType IntKi n {:}{:} - - "counter for continuous state integration" - +typedef ^ OtherStateType UA_ContinuousStateType xdot 4 - - "counter for continuous state integration" - + +# ..... 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 Logical FirstWarn_M - - - "flag so Mach number warning doesn't get repeated forever" - +typedef ^ MiscVarType Logical FirstWarn_UA - - - "flag so UA state warning doesn't get repeated forever" - +# these COULD be OtherStates or just scalar local variables (they are calcaulted/used in UpdateDiscState and written to WriteOutput in CalcOutput) +typedef ^ MiscVarType LOGICAL TESF {:}{:} - - "logical flag indicating if trailing edge separation is possible" - +typedef ^ MiscVarType LOGICAL LESF {:}{:} - - "logical flag indicating if leading edge separation is possible" - +typedef ^ MiscVarType LOGICAL VRTX {:}{:} - - "logical flag indicating if a vortex is being processed" - +typedef ^ MiscVarType ReKi T_Sh {:}{:} - - "shedding frequency" - +typedef ^ MiscVarType LOGICAL BEDSEP {:}{:} - - "logical flag indicating if this is undergoing separated flow (for compison with AD14)" - + + +# ..... Parameters ................................................................................................................ +# Define parameters here: +typedef ^ ParameterType DbKi dt - - - "time step" s +typedef ^ ^ ReKi c {:}{:} - - "Chord length at node" m +typedef ^ ^ INTEGER numBlades - - - "Number nodes of all blades" - +typedef ^ ^ INTEGER nNodesPerBlade - - - "Number nodes per blades" - +typedef ^ ^ INTEGER UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - +typedef ^ ^ LOGICAL Flookup - - - "Use table lookup for f' and f'' " - +typedef ^ ^ ReKi a_s - - - "speed of sound" m/s +typedef ^ ^ INTEGER NumOuts - - - "Number of outputs" - +typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Unsteady.out 2=GlueCode.out 3=both files]" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "Output format for numerical results" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "Output format for header strings" - +typedef ^ ^ CHARACTER(1) Delim - - - "Delimiter string for outputs, defaults to tab-delimiters" - +typedef ^ ^ INTEGER UnOutFile - - - "File unit for the UnsteadyAero outputs" - +typedef ^ ^ Logical ShedEffect - .True. - "Include the effect of shed vorticity. If False, the input alpha is assumed to already contain this effect (e.g. vortex methods)" - +typedef ^ ParameterType IntKi lin_nx - 0 - "Number of continuous states for linearization" - + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType ReKi U - - - "air velocity magnitude relative to the airfoil" m/s +typedef ^ ^ ReKi alpha - - 2pi "angle of attack" rad +typedef ^ ^ ReKi Re - - - "Reynold's number" - +typedef ^ ^ ReKi UserProp - 0.0 - "UserProp value for interpolating airfoil tables" - +typedef ^ ^ ReKi v_ac 2 - - "Relative fluid velocity at the aerodynamic center (UAMod=4)" m/s +typedef ^ ^ ReKi omega - - - "pitching/twisting rate of the airfoil section (UAMod=4)" rad/s + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType ReKi Cn - - - "2D, normal to chord, force coefficient" - +typedef ^ OutputType ReKi Cc - - - "2D, tangent to chord, force coefficient" +typedef ^ OutputType ReKi Cm - - - "2D pitching moment coefficient about the 1/4 chord, positive when nose is up" +typedef ^ OutputType ReKi Cl - - - "2D lift coefficient" - +typedef ^ OutputType ReKi Cd - - - "2D drag coefficient" - +typedef ^ ^ ReKi WriteOutput {:} - - "outputs to be written to a file" - + diff --git a/OpenFAST/modules/aerodyn/src/UnsteadyAero_Types.f90 b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Types.f90 new file mode 100644 index 000000000..cd19e10c4 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/UnsteadyAero_Types.f90 @@ -0,0 +1,6050 @@ +!STARTOFREGISTRYGENERATEDFILE 'UnsteadyAero_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 +!********************************************************************************************************************************* +! UnsteadyAero_Types +!................................................................................................................................. +! This file is part of UnsteadyAero. +! +! 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 UnsteadyAero. 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 UnsteadyAero_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE AirfoilInfo_Types +USE NWTC_Library +IMPLICIT NONE +! ========= UA_InitInputType ======= + TYPE, PUBLIC :: UA_InitInputType + REAL(DbKi) :: dt !< time step [s] + CHARACTER(1024) :: OutRootName !< Supplied by Driver: The name of the root file (without extension) including the full path [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: c !< Chord length at node [m] + INTEGER(IntKi) :: numBlades !< Number nodes of all blades [-] + INTEGER(IntKi) :: nNodesPerBlade !< Number nodes per blades [-] + INTEGER(IntKi) :: UAMod !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] + REAL(ReKi) :: a_s !< speed of sound [m/s] + LOGICAL :: Flookup !< Use table lookup for f' and f'' [-] + INTEGER(IntKi) :: NumOuts !< The number of outputs for this module as requested in the input file [-] + END TYPE UA_InitInputType +! ======================= +! ========= UA_InitOutputType ======= + TYPE, PUBLIC :: UA_InitOutputType + TYPE(ProgDesc) :: Version !< Version structure [-] + CHARACTER(19) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all UA-related output channel header strings (includes all sub-module channels) [-] + CHARACTER(19) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< The is the list of all UA-related output channel unit strings (includes all sub-module channels) [-] + END TYPE UA_InitOutputType +! ======================= +! ========= UA_KelvinChainType ======= + TYPE, PUBLIC :: UA_KelvinChainType + REAL(ReKi) :: Cn_prime !< [-] + REAL(ReKi) :: C_nalpha_circ !< slope of the circulatory normal force coefficient vs alpha curve [-] + REAL(ReKi) :: Kalpha_f !< filtered backwards finite difference of alpha (xd%Kalpha_f_minus1) [-] + REAL(ReKi) :: Kq_f !< filtered backwards finite difference of q [-] + REAL(ReKi) :: alpha_filt_cur !< filtered angle of attack [-] + REAL(ReKi) :: alpha_e !< effective angle of attack at 3/4 chord TODO: verify 3/4 and not 1/4 [-] + REAL(ReKi) :: dalpha0 !< [-] + REAL(ReKi) :: alpha_f !< [-] + REAL(ReKi) :: Kq !< [-] + REAL(ReKi) :: q_cur !< [-] + REAL(ReKi) :: q_f_cur !< [-] + REAL(ReKi) :: X1 !< [-] + REAL(ReKi) :: X2 !< [-] + REAL(ReKi) :: X3 !< [-] + REAL(ReKi) :: X4 !< [-] + REAL(ReKi) :: Kprime_alpha !< [-] + REAL(ReKi) :: Kprime_q !< [-] + REAL(ReKi) :: Dp !< [-] + REAL(ReKi) :: Cn_pot !< [-] + REAL(ReKi) :: Cc_pot !< [-] + REAL(ReKi) :: Cn_alpha_q_circ !< [-] + REAL(ReKi) :: Cn_alpha_q_nc !< non-circulatory component of normal force coefficient response to step change in alpha and q [-] + REAL(ReKi) :: Cm_q_circ !< [-] + REAL(ReKi) :: Cn_alpha_nc !< non-circulatory component of the normal force coefficient response to step change in alpha [-] + REAL(ReKi) :: Cn_q_circ !< [-] + REAL(ReKi) :: Cn_q_nc !< [-] + REAL(ReKi) :: Cm_q_nc !< non-circulatory component of the moment coefficient response to step change in q [-] + REAL(ReKi) :: fprimeprime !< [-] + REAL(ReKi) :: Df !< [-] + REAL(ReKi) :: Df_c !< [-] + REAL(ReKi) :: Df_m !< [-] + REAL(ReKi) :: Dalphaf !< [-] + REAL(ReKi) :: fprime !< [-] + REAL(ReKi) :: fprime_c !< [-] + REAL(ReKi) :: fprimeprime_c !< [-] + REAL(ReKi) :: fprime_m !< [-] + REAL(ReKi) :: fprimeprime_m !< [-] + REAL(ReKi) :: Cn_v !< normal force coefficient due to the presence of LE vortex [-] + REAL(ReKi) :: C_V !< contribution to the normal force coefficient due to accumulated vorticity in the LE vortex [-] + REAL(ReKi) :: Cn_FS !< [-] + REAL(ReKi) :: T_f !< [-] + REAL(ReKi) :: T_fc !< [-] + REAL(ReKi) :: T_fm !< [-] + REAL(ReKi) :: T_V !< backwards finite difference of the non-dimensionalized distance parameter [-] + REAL(ReKi) :: k_alpha !< [-] + REAL(ReKi) :: k_q !< [-] + REAL(ReKi) :: T_alpha !< [-] + REAL(ReKi) :: T_q !< [-] + REAL(ReKi) :: ds !< non-dimensionalized distance parameter [-] + END TYPE UA_KelvinChainType +! ======================= +! ========= UA_ElementContinuousStateType ======= + TYPE, PUBLIC :: UA_ElementContinuousStateType + REAL(R8Ki) , DIMENSION(1:4) :: x !< continuous states when UA_Mod=4 (x1 and x2:Downwash memory terms; x3:Clp', Lift coefficient with a time lag to the attached lift coeff; x4: f'' , Final separation point function) [{rad, rad, - -}] + END TYPE UA_ElementContinuousStateType +! ======================= +! ========= UA_ContinuousStateType ======= + TYPE, PUBLIC :: UA_ContinuousStateType + TYPE(UA_ElementContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: element !< continuous states when UA_Mod=4 for each blade/node [-] + END TYPE UA_ContinuousStateType +! ======================= +! ========= UA_DiscreteStateType ======= + TYPE, PUBLIC :: UA_DiscreteStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: alpha_minus1 !< angle of attack, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: alpha_filt_minus1 !< filtered angle of attack, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: q_minus1 !< non-dimensional pitching rate, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Kalpha_f_minus1 !< filtered pitching rate, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Kq_f_minus1 !< filtered pitching acceleration, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: q_f_minus1 !< filtered non-dimensional pitching rate, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: X1_minus1 !< deficiency function used in the development of Cn_alpha_q_circ, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: X2_minus1 !< deficiency function used in the development of Cn_alpha_q_circ, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: X3_minus1 !< deficiency function used in the development of Cn_q_circ, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: X4_minus1 !< deficiency function used in the development of Cn_q_circ, previous time step [rad] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Kprime_alpha_minus1 !< deficiency function used in the development of Cn_alpha_nc, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Kprime_q_minus1 !< deficiency function used in the development of Cn_q_nc, previous time step [rad/s^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Kprimeprime_q_minus1 !< deficiency function used in the development of Cm_q_nc, previous time step [rad/s^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K3prime_q_minus1 !< deficiency function used in the development of Cm_q_circ, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dp_minus1 !< deficiency function used in the development of Cm_q_circ, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cn_pot_minus1 !< deficiency function used in the development of Cn_prime [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprimeprime_minus1 !< lagged version of fprime, accounting for unsteady boundary layer response, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprimeprime_c_minus1 !< lagged version of fprime_c, accounting for unsteady boundary layer response, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprimeprime_m_minus1 !< lagged version of fprime_m, accounting for unsteady boundary layer response, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Df_minus1 !< deficiency function used in the development of fprime, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Df_c_minus1 !< deficiency function used in the development of fprime, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Df_m_minus1 !< deficiency function used in the development of fprime, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dalphaf_minus1 !< deficiency function used in the development of fprime, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: alphaf_minus1 !< deficiency function used in the development of fprime, previous time step [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprime_minus1 !< separation point Cn distance from leading edge, expressed in cord fraction, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprime_c_minus1 !< separation point Ct distance from leading edge, expressed in cord fraction, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: fprime_m_minus1 !< Distance application of Cn with respect to Cm, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tau_V !< time variable, tracking the travel of the LE vortex over the airfoil suction surface [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tau_V_minus1 !< time variable, tracking the travel of the LE vortex over the airfoil suction surface [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cn_v_minus1 !< normal force coefficient due to the presence of LE vortex, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C_V_minus1 !< contribution to the normal force coefficient due to accumulated vorticity in the LE vortex, previous time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cn_prime_minus1 !< difference between Cn_prime and Cn_prime_minus1, previous time step [rad] + END TYPE UA_DiscreteStateType +! ======================= +! ========= UA_ConstraintStateType ======= + TYPE, PUBLIC :: UA_ConstraintStateType + REAL(ReKi) :: DummyConstraintState !< [-] + END TYPE UA_ConstraintStateType +! ======================= +! ========= UA_OtherStateType ======= + TYPE, PUBLIC :: UA_OtherStateType + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: FirstPass !< logical flag indicating if this is the first time step [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: sigma1 !< multiplier for T_fn [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: sigma1c !< multiplier for T_fc [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: sigma1m !< multiplier for T_fm [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: sigma3 !< multiplier for T_V [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: n !< counter for continuous state integration [-] + TYPE(UA_ContinuousStateType) , DIMENSION(1:4) :: xdot !< counter for continuous state integration [-] + END TYPE UA_OtherStateType +! ======================= +! ========= UA_MiscVarType ======= + TYPE, PUBLIC :: UA_MiscVarType + LOGICAL :: FirstWarn_M !< flag so Mach number warning doesn't get repeated forever [-] + LOGICAL :: FirstWarn_UA !< flag so UA state warning doesn't get repeated forever [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: TESF !< logical flag indicating if trailing edge separation is possible [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: LESF !< logical flag indicating if leading edge separation is possible [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: VRTX !< logical flag indicating if a vortex is being processed [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_Sh !< shedding frequency [-] + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: BEDSEP !< logical flag indicating if this is undergoing separated flow (for compison with AD14) [-] + END TYPE UA_MiscVarType +! ======================= +! ========= UA_ParameterType ======= + TYPE, PUBLIC :: UA_ParameterType + REAL(DbKi) :: dt !< time step [s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: c !< Chord length at node [m] + INTEGER(IntKi) :: numBlades !< Number nodes of all blades [-] + INTEGER(IntKi) :: nNodesPerBlade !< Number nodes per blades [-] + INTEGER(IntKi) :: UAMod !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] + LOGICAL :: Flookup !< Use table lookup for f' and f'' [-] + REAL(ReKi) :: a_s !< speed of sound [m/s] + INTEGER(IntKi) :: NumOuts !< Number of outputs [-] + INTEGER(IntKi) :: OutSwtch !< Output requested channels to: [1=Unsteady.out 2=GlueCode.out 3=both files] [-] + CHARACTER(20) :: OutFmt !< Output format for numerical results [-] + CHARACTER(20) :: OutSFmt !< Output format for header strings [-] + CHARACTER(1) :: Delim !< Delimiter string for outputs, defaults to tab-delimiters [-] + INTEGER(IntKi) :: UnOutFile !< File unit for the UnsteadyAero outputs [-] + LOGICAL :: ShedEffect = .True. !< Include the effect of shed vorticity. If False, the input alpha is assumed to already contain this effect (e.g. vortex methods) [-] + INTEGER(IntKi) :: lin_nx = 0 !< Number of continuous states for linearization [-] + END TYPE UA_ParameterType +! ======================= +! ========= UA_InputType ======= + TYPE, PUBLIC :: UA_InputType + REAL(ReKi) :: U !< air velocity magnitude relative to the airfoil [m/s] + REAL(ReKi) :: alpha !< angle of attack [rad] + REAL(ReKi) :: Re !< Reynold's number [-] + REAL(ReKi) :: UserProp = 0.0 !< UserProp value for interpolating airfoil tables [-] + REAL(ReKi) , DIMENSION(1:2) :: v_ac !< Relative fluid velocity at the aerodynamic center (UAMod=4) [m/s] + REAL(ReKi) :: omega !< pitching/twisting rate of the airfoil section (UAMod=4) [rad/s] + END TYPE UA_InputType +! ======================= +! ========= UA_OutputType ======= + TYPE, PUBLIC :: UA_OutputType + REAL(ReKi) :: Cn !< 2D, normal to chord, force coefficient [-] + REAL(ReKi) :: Cc !< 2D, tangent to chord, force coefficient [-] + REAL(ReKi) :: Cm !< 2D pitching moment coefficient about the 1/4 chord, positive when nose is up [-] + REAL(ReKi) :: Cl !< 2D lift coefficient [-] + REAL(ReKi) :: Cd !< 2D drag coefficient [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< outputs to be written to a file [-] + END TYPE UA_OutputType +! ======================= +CONTAINS + SUBROUTINE UA_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(UA_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 = 'UA_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%dt = SrcInitInputData%dt + DstInitInputData%OutRootName = SrcInitInputData%OutRootName +IF (ALLOCATED(SrcInitInputData%c)) THEN + i1_l = LBOUND(SrcInitInputData%c,1) + i1_u = UBOUND(SrcInitInputData%c,1) + i2_l = LBOUND(SrcInitInputData%c,2) + i2_u = UBOUND(SrcInitInputData%c,2) + IF (.NOT. ALLOCATED(DstInitInputData%c)) THEN + ALLOCATE(DstInitInputData%c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%c = SrcInitInputData%c +ENDIF + DstInitInputData%numBlades = SrcInitInputData%numBlades + DstInitInputData%nNodesPerBlade = SrcInitInputData%nNodesPerBlade + DstInitInputData%UAMod = SrcInitInputData%UAMod + DstInitInputData%a_s = SrcInitInputData%a_s + DstInitInputData%Flookup = SrcInitInputData%Flookup + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + END SUBROUTINE UA_CopyInitInput + + SUBROUTINE UA_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(UA_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%c)) THEN + DEALLOCATE(InitInputData%c) +ENDIF + END SUBROUTINE UA_DestroyInitInput + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Db_BufSz = Db_BufSz + 1 ! dt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutRootName) ! OutRootName + Int_BufSz = Int_BufSz + 1 ! c allocated yes/no + IF ( ALLOCATED(InData%c) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! c upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%c) ! c + END IF + Int_BufSz = Int_BufSz + 1 ! numBlades + Int_BufSz = Int_BufSz + 1 ! nNodesPerBlade + Int_BufSz = Int_BufSz + 1 ! UAMod + Re_BufSz = Re_BufSz + 1 ! a_s + Int_BufSz = Int_BufSz + 1 ! Flookup + Int_BufSz = Int_BufSz + 1 ! NumOuts + 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 + + DbKiBuf(Db_Xferred) = InData%dt + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(InData%OutRootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutRootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%c) ) 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%c,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%c,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%c,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%c,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%c,2), UBOUND(InData%c,2) + DO i1 = LBOUND(InData%c,1), UBOUND(InData%c,1) + ReKiBuf(Re_Xferred) = InData%c(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodesPerBlade + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UAMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%a_s + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Flookup, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE UA_PackInitInput + + SUBROUTINE UA_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(UA_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 = 'UA_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%dt = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(OutData%OutRootName) + OutData%OutRootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! c 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%c)) DEALLOCATE(OutData%c) + ALLOCATE(OutData%c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%c,2), UBOUND(OutData%c,2) + DO i1 = LBOUND(OutData%c,1), UBOUND(OutData%c,1) + OutData%c(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%numBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNodesPerBlade = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UAMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%a_s = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Flookup = TRANSFER(IntKiBuf(Int_Xferred), OutData%Flookup) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE UA_UnPackInitInput + + SUBROUTINE UA_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(UA_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 = 'UA_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Version, DstInitOutputData%Version, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE UA_CopyInitOutput + + SUBROUTINE UA_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(UA_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Version, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE UA_DestroyInitOutput + + SUBROUTINE UA_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(UA_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 = 'UA_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 ! Version: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Version, ErrStat2, ErrMsg2, .TRUE. ) ! Version + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Version + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Version + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Version + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%Version, ErrStat2, ErrMsg2, OnlySize ) ! Version + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE UA_PackInitOutput + + SUBROUTINE UA_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(UA_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 = 'UA_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%Version, ErrStat2, ErrMsg2 ) ! Version + 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 ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE UA_UnPackInitOutput + + SUBROUTINE UA_CopyKelvinChainType( SrcKelvinChainTypeData, DstKelvinChainTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_KelvinChainType), INTENT(IN) :: SrcKelvinChainTypeData + TYPE(UA_KelvinChainType), INTENT(INOUT) :: DstKelvinChainTypeData + 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 = 'UA_CopyKelvinChainType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstKelvinChainTypeData%Cn_prime = SrcKelvinChainTypeData%Cn_prime + DstKelvinChainTypeData%C_nalpha_circ = SrcKelvinChainTypeData%C_nalpha_circ + DstKelvinChainTypeData%Kalpha_f = SrcKelvinChainTypeData%Kalpha_f + DstKelvinChainTypeData%Kq_f = SrcKelvinChainTypeData%Kq_f + DstKelvinChainTypeData%alpha_filt_cur = SrcKelvinChainTypeData%alpha_filt_cur + DstKelvinChainTypeData%alpha_e = SrcKelvinChainTypeData%alpha_e + DstKelvinChainTypeData%dalpha0 = SrcKelvinChainTypeData%dalpha0 + DstKelvinChainTypeData%alpha_f = SrcKelvinChainTypeData%alpha_f + DstKelvinChainTypeData%Kq = SrcKelvinChainTypeData%Kq + DstKelvinChainTypeData%q_cur = SrcKelvinChainTypeData%q_cur + DstKelvinChainTypeData%q_f_cur = SrcKelvinChainTypeData%q_f_cur + DstKelvinChainTypeData%X1 = SrcKelvinChainTypeData%X1 + DstKelvinChainTypeData%X2 = SrcKelvinChainTypeData%X2 + DstKelvinChainTypeData%X3 = SrcKelvinChainTypeData%X3 + DstKelvinChainTypeData%X4 = SrcKelvinChainTypeData%X4 + DstKelvinChainTypeData%Kprime_alpha = SrcKelvinChainTypeData%Kprime_alpha + DstKelvinChainTypeData%Kprime_q = SrcKelvinChainTypeData%Kprime_q + DstKelvinChainTypeData%Dp = SrcKelvinChainTypeData%Dp + DstKelvinChainTypeData%Cn_pot = SrcKelvinChainTypeData%Cn_pot + DstKelvinChainTypeData%Cc_pot = SrcKelvinChainTypeData%Cc_pot + DstKelvinChainTypeData%Cn_alpha_q_circ = SrcKelvinChainTypeData%Cn_alpha_q_circ + DstKelvinChainTypeData%Cn_alpha_q_nc = SrcKelvinChainTypeData%Cn_alpha_q_nc + DstKelvinChainTypeData%Cm_q_circ = SrcKelvinChainTypeData%Cm_q_circ + DstKelvinChainTypeData%Cn_alpha_nc = SrcKelvinChainTypeData%Cn_alpha_nc + DstKelvinChainTypeData%Cn_q_circ = SrcKelvinChainTypeData%Cn_q_circ + DstKelvinChainTypeData%Cn_q_nc = SrcKelvinChainTypeData%Cn_q_nc + DstKelvinChainTypeData%Cm_q_nc = SrcKelvinChainTypeData%Cm_q_nc + DstKelvinChainTypeData%fprimeprime = SrcKelvinChainTypeData%fprimeprime + DstKelvinChainTypeData%Df = SrcKelvinChainTypeData%Df + DstKelvinChainTypeData%Df_c = SrcKelvinChainTypeData%Df_c + DstKelvinChainTypeData%Df_m = SrcKelvinChainTypeData%Df_m + DstKelvinChainTypeData%Dalphaf = SrcKelvinChainTypeData%Dalphaf + DstKelvinChainTypeData%fprime = SrcKelvinChainTypeData%fprime + DstKelvinChainTypeData%fprime_c = SrcKelvinChainTypeData%fprime_c + DstKelvinChainTypeData%fprimeprime_c = SrcKelvinChainTypeData%fprimeprime_c + DstKelvinChainTypeData%fprime_m = SrcKelvinChainTypeData%fprime_m + DstKelvinChainTypeData%fprimeprime_m = SrcKelvinChainTypeData%fprimeprime_m + DstKelvinChainTypeData%Cn_v = SrcKelvinChainTypeData%Cn_v + DstKelvinChainTypeData%C_V = SrcKelvinChainTypeData%C_V + DstKelvinChainTypeData%Cn_FS = SrcKelvinChainTypeData%Cn_FS + DstKelvinChainTypeData%T_f = SrcKelvinChainTypeData%T_f + DstKelvinChainTypeData%T_fc = SrcKelvinChainTypeData%T_fc + DstKelvinChainTypeData%T_fm = SrcKelvinChainTypeData%T_fm + DstKelvinChainTypeData%T_V = SrcKelvinChainTypeData%T_V + DstKelvinChainTypeData%k_alpha = SrcKelvinChainTypeData%k_alpha + DstKelvinChainTypeData%k_q = SrcKelvinChainTypeData%k_q + DstKelvinChainTypeData%T_alpha = SrcKelvinChainTypeData%T_alpha + DstKelvinChainTypeData%T_q = SrcKelvinChainTypeData%T_q + DstKelvinChainTypeData%ds = SrcKelvinChainTypeData%ds + END SUBROUTINE UA_CopyKelvinChainType + + SUBROUTINE UA_DestroyKelvinChainType( KelvinChainTypeData, ErrStat, ErrMsg ) + TYPE(UA_KelvinChainType), INTENT(INOUT) :: KelvinChainTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyKelvinChainType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE UA_DestroyKelvinChainType + + SUBROUTINE UA_PackKelvinChainType( 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(UA_KelvinChainType), 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 = 'UA_PackKelvinChainType' + ! 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 ! Cn_prime + Re_BufSz = Re_BufSz + 1 ! C_nalpha_circ + Re_BufSz = Re_BufSz + 1 ! Kalpha_f + Re_BufSz = Re_BufSz + 1 ! Kq_f + Re_BufSz = Re_BufSz + 1 ! alpha_filt_cur + Re_BufSz = Re_BufSz + 1 ! alpha_e + Re_BufSz = Re_BufSz + 1 ! dalpha0 + Re_BufSz = Re_BufSz + 1 ! alpha_f + Re_BufSz = Re_BufSz + 1 ! Kq + Re_BufSz = Re_BufSz + 1 ! q_cur + Re_BufSz = Re_BufSz + 1 ! q_f_cur + Re_BufSz = Re_BufSz + 1 ! X1 + Re_BufSz = Re_BufSz + 1 ! X2 + Re_BufSz = Re_BufSz + 1 ! X3 + Re_BufSz = Re_BufSz + 1 ! X4 + Re_BufSz = Re_BufSz + 1 ! Kprime_alpha + Re_BufSz = Re_BufSz + 1 ! Kprime_q + Re_BufSz = Re_BufSz + 1 ! Dp + Re_BufSz = Re_BufSz + 1 ! Cn_pot + Re_BufSz = Re_BufSz + 1 ! Cc_pot + Re_BufSz = Re_BufSz + 1 ! Cn_alpha_q_circ + Re_BufSz = Re_BufSz + 1 ! Cn_alpha_q_nc + Re_BufSz = Re_BufSz + 1 ! Cm_q_circ + Re_BufSz = Re_BufSz + 1 ! Cn_alpha_nc + Re_BufSz = Re_BufSz + 1 ! Cn_q_circ + Re_BufSz = Re_BufSz + 1 ! Cn_q_nc + Re_BufSz = Re_BufSz + 1 ! Cm_q_nc + Re_BufSz = Re_BufSz + 1 ! fprimeprime + Re_BufSz = Re_BufSz + 1 ! Df + Re_BufSz = Re_BufSz + 1 ! Df_c + Re_BufSz = Re_BufSz + 1 ! Df_m + Re_BufSz = Re_BufSz + 1 ! Dalphaf + Re_BufSz = Re_BufSz + 1 ! fprime + Re_BufSz = Re_BufSz + 1 ! fprime_c + Re_BufSz = Re_BufSz + 1 ! fprimeprime_c + Re_BufSz = Re_BufSz + 1 ! fprime_m + Re_BufSz = Re_BufSz + 1 ! fprimeprime_m + Re_BufSz = Re_BufSz + 1 ! Cn_v + Re_BufSz = Re_BufSz + 1 ! C_V + Re_BufSz = Re_BufSz + 1 ! Cn_FS + Re_BufSz = Re_BufSz + 1 ! T_f + Re_BufSz = Re_BufSz + 1 ! T_fc + Re_BufSz = Re_BufSz + 1 ! T_fm + Re_BufSz = Re_BufSz + 1 ! T_V + Re_BufSz = Re_BufSz + 1 ! k_alpha + Re_BufSz = Re_BufSz + 1 ! k_q + Re_BufSz = Re_BufSz + 1 ! T_alpha + Re_BufSz = Re_BufSz + 1 ! T_q + Re_BufSz = Re_BufSz + 1 ! ds + 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%Cn_prime + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_nalpha_circ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kalpha_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kq_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha_filt_cur + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha_e + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dalpha0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%q_cur + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%q_f_cur + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X3 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X4 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kprime_alpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kprime_q + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Dp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_pot + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cc_pot + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_alpha_q_circ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_alpha_q_nc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm_q_circ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_alpha_nc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_q_circ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_q_nc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm_q_nc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprimeprime + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Df + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Df_c + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Df_m + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Dalphaf + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprime + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprime_c + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprimeprime_c + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprime_m + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%fprimeprime_m + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_v + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_V + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cn_FS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_fc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_fm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_V + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k_alpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%k_q + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_alpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T_q + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ds + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_PackKelvinChainType + + SUBROUTINE UA_UnPackKelvinChainType( 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(UA_KelvinChainType), 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 = 'UA_UnPackKelvinChainType' + ! 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%Cn_prime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_nalpha_circ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kalpha_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kq_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha_filt_cur = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha_e = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dalpha0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%q_cur = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%q_f_cur = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%X1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%X2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%X3 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%X4 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kprime_alpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kprime_q = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Dp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_pot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cc_pot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_alpha_q_circ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_alpha_q_nc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm_q_circ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_alpha_nc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_q_circ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_q_nc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm_q_nc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprimeprime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Df = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Df_c = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Df_m = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Dalphaf = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprime_c = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprimeprime_c = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprime_m = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%fprimeprime_m = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_v = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_V = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cn_FS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_fc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_fm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_V = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k_alpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%k_q = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_alpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T_q = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ds = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_UnPackKelvinChainType + + SUBROUTINE UA_CopyElementContinuousStateType( SrcElementContinuousStateTypeData, DstElementContinuousStateTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_ElementContinuousStateType), INTENT(IN) :: SrcElementContinuousStateTypeData + TYPE(UA_ElementContinuousStateType), INTENT(INOUT) :: DstElementContinuousStateTypeData + 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 = 'UA_CopyElementContinuousStateType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElementContinuousStateTypeData%x = SrcElementContinuousStateTypeData%x + END SUBROUTINE UA_CopyElementContinuousStateType + + SUBROUTINE UA_DestroyElementContinuousStateType( ElementContinuousStateTypeData, ErrStat, ErrMsg ) + TYPE(UA_ElementContinuousStateType), INTENT(INOUT) :: ElementContinuousStateTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyElementContinuousStateType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE UA_DestroyElementContinuousStateType + + SUBROUTINE UA_PackElementContinuousStateType( 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(UA_ElementContinuousStateType), 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 = 'UA_PackElementContinuousStateType' + ! 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 + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + 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%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE UA_PackElementContinuousStateType + + SUBROUTINE UA_UnPackElementContinuousStateType( 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(UA_ElementContinuousStateType), 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 = 'UA_UnPackElementContinuousStateType' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE UA_UnPackElementContinuousStateType + + SUBROUTINE UA_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(UA_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 = 'UA_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%element)) THEN + i1_l = LBOUND(SrcContStateData%element,1) + i1_u = UBOUND(SrcContStateData%element,1) + i2_l = LBOUND(SrcContStateData%element,2) + i2_u = UBOUND(SrcContStateData%element,2) + IF (.NOT. ALLOCATED(DstContStateData%element)) THEN + ALLOCATE(DstContStateData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcContStateData%element,2), UBOUND(SrcContStateData%element,2) + DO i1 = LBOUND(SrcContStateData%element,1), UBOUND(SrcContStateData%element,1) + CALL UA_Copyelementcontinuousstatetype( SrcContStateData%element(i1,i2), DstContStateData%element(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF + END SUBROUTINE UA_CopyContState + + SUBROUTINE UA_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(UA_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%element)) THEN +DO i2 = LBOUND(ContStateData%element,2), UBOUND(ContStateData%element,2) +DO i1 = LBOUND(ContStateData%element,1), UBOUND(ContStateData%element,1) + CALL UA_Destroyelementcontinuousstatetype( ContStateData%element(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(ContStateData%element) +ENDIF + END SUBROUTINE UA_DestroyContState + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Int_BufSz = Int_BufSz + 1 ! element allocated yes/no + IF ( ALLOCATED(InData%element) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! element upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + Int_BufSz = Int_BufSz + 3 ! element: size of buffers for each call to pack subtype + CALL UA_Packelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! element + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! element + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! element + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! element + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + 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%element) ) 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%element,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%element,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%element,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%element,2), UBOUND(InData%element,2) + DO i1 = LBOUND(InData%element,1), UBOUND(InData%element,1) + CALL UA_Packelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, InData%element(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! element + 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 DO + END IF + END SUBROUTINE UA_PackContState + + SUBROUTINE UA_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(UA_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 = 'UA_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! element 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%element)) DEALLOCATE(OutData%element) + ALLOCATE(OutData%element(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%element.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%element,2), UBOUND(OutData%element,2) + DO i1 = LBOUND(OutData%element,1), UBOUND(OutData%element,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 UA_Unpackelementcontinuousstatetype( Re_Buf, Db_Buf, Int_Buf, OutData%element(i1,i2), ErrStat2, ErrMsg2 ) ! element + 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 DO + END DO + END IF + END SUBROUTINE UA_UnPackContState + + SUBROUTINE UA_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(UA_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) :: 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 = 'UA_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcDiscStateData%alpha_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%alpha_minus1,1) + i1_u = UBOUND(SrcDiscStateData%alpha_minus1,1) + i2_l = LBOUND(SrcDiscStateData%alpha_minus1,2) + i2_u = UBOUND(SrcDiscStateData%alpha_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%alpha_minus1)) THEN + ALLOCATE(DstDiscStateData%alpha_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%alpha_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%alpha_minus1 = SrcDiscStateData%alpha_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%alpha_filt_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%alpha_filt_minus1,1) + i1_u = UBOUND(SrcDiscStateData%alpha_filt_minus1,1) + i2_l = LBOUND(SrcDiscStateData%alpha_filt_minus1,2) + i2_u = UBOUND(SrcDiscStateData%alpha_filt_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%alpha_filt_minus1)) THEN + ALLOCATE(DstDiscStateData%alpha_filt_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%alpha_filt_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%alpha_filt_minus1 = SrcDiscStateData%alpha_filt_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%q_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%q_minus1,1) + i1_u = UBOUND(SrcDiscStateData%q_minus1,1) + i2_l = LBOUND(SrcDiscStateData%q_minus1,2) + i2_u = UBOUND(SrcDiscStateData%q_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%q_minus1)) THEN + ALLOCATE(DstDiscStateData%q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%q_minus1 = SrcDiscStateData%q_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Kalpha_f_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Kalpha_f_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Kalpha_f_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Kalpha_f_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Kalpha_f_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Kalpha_f_minus1)) THEN + ALLOCATE(DstDiscStateData%Kalpha_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Kalpha_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Kalpha_f_minus1 = SrcDiscStateData%Kalpha_f_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Kq_f_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Kq_f_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Kq_f_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Kq_f_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Kq_f_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Kq_f_minus1)) THEN + ALLOCATE(DstDiscStateData%Kq_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Kq_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Kq_f_minus1 = SrcDiscStateData%Kq_f_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%q_f_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%q_f_minus1,1) + i1_u = UBOUND(SrcDiscStateData%q_f_minus1,1) + i2_l = LBOUND(SrcDiscStateData%q_f_minus1,2) + i2_u = UBOUND(SrcDiscStateData%q_f_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%q_f_minus1)) THEN + ALLOCATE(DstDiscStateData%q_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%q_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%q_f_minus1 = SrcDiscStateData%q_f_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%X1_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%X1_minus1,1) + i1_u = UBOUND(SrcDiscStateData%X1_minus1,1) + i2_l = LBOUND(SrcDiscStateData%X1_minus1,2) + i2_u = UBOUND(SrcDiscStateData%X1_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%X1_minus1)) THEN + ALLOCATE(DstDiscStateData%X1_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%X1_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%X1_minus1 = SrcDiscStateData%X1_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%X2_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%X2_minus1,1) + i1_u = UBOUND(SrcDiscStateData%X2_minus1,1) + i2_l = LBOUND(SrcDiscStateData%X2_minus1,2) + i2_u = UBOUND(SrcDiscStateData%X2_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%X2_minus1)) THEN + ALLOCATE(DstDiscStateData%X2_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%X2_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%X2_minus1 = SrcDiscStateData%X2_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%X3_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%X3_minus1,1) + i1_u = UBOUND(SrcDiscStateData%X3_minus1,1) + i2_l = LBOUND(SrcDiscStateData%X3_minus1,2) + i2_u = UBOUND(SrcDiscStateData%X3_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%X3_minus1)) THEN + ALLOCATE(DstDiscStateData%X3_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%X3_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%X3_minus1 = SrcDiscStateData%X3_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%X4_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%X4_minus1,1) + i1_u = UBOUND(SrcDiscStateData%X4_minus1,1) + i2_l = LBOUND(SrcDiscStateData%X4_minus1,2) + i2_u = UBOUND(SrcDiscStateData%X4_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%X4_minus1)) THEN + ALLOCATE(DstDiscStateData%X4_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%X4_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%X4_minus1 = SrcDiscStateData%X4_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Kprime_alpha_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Kprime_alpha_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Kprime_alpha_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Kprime_alpha_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Kprime_alpha_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Kprime_alpha_minus1)) THEN + ALLOCATE(DstDiscStateData%Kprime_alpha_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Kprime_alpha_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Kprime_alpha_minus1 = SrcDiscStateData%Kprime_alpha_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Kprime_q_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Kprime_q_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Kprime_q_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Kprime_q_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Kprime_q_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Kprime_q_minus1)) THEN + ALLOCATE(DstDiscStateData%Kprime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Kprime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Kprime_q_minus1 = SrcDiscStateData%Kprime_q_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Kprimeprime_q_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Kprimeprime_q_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Kprimeprime_q_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Kprimeprime_q_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Kprimeprime_q_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Kprimeprime_q_minus1)) THEN + ALLOCATE(DstDiscStateData%Kprimeprime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Kprimeprime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Kprimeprime_q_minus1 = SrcDiscStateData%Kprimeprime_q_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%K3prime_q_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%K3prime_q_minus1,1) + i1_u = UBOUND(SrcDiscStateData%K3prime_q_minus1,1) + i2_l = LBOUND(SrcDiscStateData%K3prime_q_minus1,2) + i2_u = UBOUND(SrcDiscStateData%K3prime_q_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%K3prime_q_minus1)) THEN + ALLOCATE(DstDiscStateData%K3prime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%K3prime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%K3prime_q_minus1 = SrcDiscStateData%K3prime_q_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Dp_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Dp_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Dp_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Dp_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Dp_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Dp_minus1)) THEN + ALLOCATE(DstDiscStateData%Dp_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Dp_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Dp_minus1 = SrcDiscStateData%Dp_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Cn_pot_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Cn_pot_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Cn_pot_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Cn_pot_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Cn_pot_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Cn_pot_minus1)) THEN + ALLOCATE(DstDiscStateData%Cn_pot_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Cn_pot_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Cn_pot_minus1 = SrcDiscStateData%Cn_pot_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprimeprime_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprimeprime_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprimeprime_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprimeprime_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprimeprime_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprimeprime_minus1)) THEN + ALLOCATE(DstDiscStateData%fprimeprime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprimeprime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprimeprime_minus1 = SrcDiscStateData%fprimeprime_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprimeprime_c_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprimeprime_c_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprimeprime_c_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprimeprime_c_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprimeprime_c_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprimeprime_c_minus1)) THEN + ALLOCATE(DstDiscStateData%fprimeprime_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprimeprime_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprimeprime_c_minus1 = SrcDiscStateData%fprimeprime_c_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprimeprime_m_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprimeprime_m_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprimeprime_m_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprimeprime_m_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprimeprime_m_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprimeprime_m_minus1)) THEN + ALLOCATE(DstDiscStateData%fprimeprime_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprimeprime_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprimeprime_m_minus1 = SrcDiscStateData%fprimeprime_m_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Df_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Df_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Df_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Df_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Df_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Df_minus1)) THEN + ALLOCATE(DstDiscStateData%Df_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Df_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Df_minus1 = SrcDiscStateData%Df_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Df_c_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Df_c_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Df_c_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Df_c_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Df_c_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Df_c_minus1)) THEN + ALLOCATE(DstDiscStateData%Df_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Df_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Df_c_minus1 = SrcDiscStateData%Df_c_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Df_m_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Df_m_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Df_m_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Df_m_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Df_m_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Df_m_minus1)) THEN + ALLOCATE(DstDiscStateData%Df_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Df_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Df_m_minus1 = SrcDiscStateData%Df_m_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Dalphaf_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Dalphaf_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Dalphaf_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Dalphaf_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Dalphaf_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Dalphaf_minus1)) THEN + ALLOCATE(DstDiscStateData%Dalphaf_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Dalphaf_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Dalphaf_minus1 = SrcDiscStateData%Dalphaf_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%alphaf_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%alphaf_minus1,1) + i1_u = UBOUND(SrcDiscStateData%alphaf_minus1,1) + i2_l = LBOUND(SrcDiscStateData%alphaf_minus1,2) + i2_u = UBOUND(SrcDiscStateData%alphaf_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%alphaf_minus1)) THEN + ALLOCATE(DstDiscStateData%alphaf_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%alphaf_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%alphaf_minus1 = SrcDiscStateData%alphaf_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprime_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprime_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprime_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprime_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprime_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprime_minus1)) THEN + ALLOCATE(DstDiscStateData%fprime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprime_minus1 = SrcDiscStateData%fprime_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprime_c_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprime_c_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprime_c_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprime_c_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprime_c_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprime_c_minus1)) THEN + ALLOCATE(DstDiscStateData%fprime_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprime_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprime_c_minus1 = SrcDiscStateData%fprime_c_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%fprime_m_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%fprime_m_minus1,1) + i1_u = UBOUND(SrcDiscStateData%fprime_m_minus1,1) + i2_l = LBOUND(SrcDiscStateData%fprime_m_minus1,2) + i2_u = UBOUND(SrcDiscStateData%fprime_m_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%fprime_m_minus1)) THEN + ALLOCATE(DstDiscStateData%fprime_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%fprime_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%fprime_m_minus1 = SrcDiscStateData%fprime_m_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%tau_V)) THEN + i1_l = LBOUND(SrcDiscStateData%tau_V,1) + i1_u = UBOUND(SrcDiscStateData%tau_V,1) + i2_l = LBOUND(SrcDiscStateData%tau_V,2) + i2_u = UBOUND(SrcDiscStateData%tau_V,2) + IF (.NOT. ALLOCATED(DstDiscStateData%tau_V)) THEN + ALLOCATE(DstDiscStateData%tau_V(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%tau_V.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%tau_V = SrcDiscStateData%tau_V +ENDIF +IF (ALLOCATED(SrcDiscStateData%tau_V_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%tau_V_minus1,1) + i1_u = UBOUND(SrcDiscStateData%tau_V_minus1,1) + i2_l = LBOUND(SrcDiscStateData%tau_V_minus1,2) + i2_u = UBOUND(SrcDiscStateData%tau_V_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%tau_V_minus1)) THEN + ALLOCATE(DstDiscStateData%tau_V_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%tau_V_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%tau_V_minus1 = SrcDiscStateData%tau_V_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Cn_v_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Cn_v_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Cn_v_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Cn_v_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Cn_v_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Cn_v_minus1)) THEN + ALLOCATE(DstDiscStateData%Cn_v_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Cn_v_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Cn_v_minus1 = SrcDiscStateData%Cn_v_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%C_V_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%C_V_minus1,1) + i1_u = UBOUND(SrcDiscStateData%C_V_minus1,1) + i2_l = LBOUND(SrcDiscStateData%C_V_minus1,2) + i2_u = UBOUND(SrcDiscStateData%C_V_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%C_V_minus1)) THEN + ALLOCATE(DstDiscStateData%C_V_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%C_V_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%C_V_minus1 = SrcDiscStateData%C_V_minus1 +ENDIF +IF (ALLOCATED(SrcDiscStateData%Cn_prime_minus1)) THEN + i1_l = LBOUND(SrcDiscStateData%Cn_prime_minus1,1) + i1_u = UBOUND(SrcDiscStateData%Cn_prime_minus1,1) + i2_l = LBOUND(SrcDiscStateData%Cn_prime_minus1,2) + i2_u = UBOUND(SrcDiscStateData%Cn_prime_minus1,2) + IF (.NOT. ALLOCATED(DstDiscStateData%Cn_prime_minus1)) THEN + ALLOCATE(DstDiscStateData%Cn_prime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%Cn_prime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%Cn_prime_minus1 = SrcDiscStateData%Cn_prime_minus1 +ENDIF + END SUBROUTINE UA_CopyDiscState + + SUBROUTINE UA_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(UA_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(DiscStateData%alpha_minus1)) THEN + DEALLOCATE(DiscStateData%alpha_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%alpha_filt_minus1)) THEN + DEALLOCATE(DiscStateData%alpha_filt_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%q_minus1)) THEN + DEALLOCATE(DiscStateData%q_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Kalpha_f_minus1)) THEN + DEALLOCATE(DiscStateData%Kalpha_f_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Kq_f_minus1)) THEN + DEALLOCATE(DiscStateData%Kq_f_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%q_f_minus1)) THEN + DEALLOCATE(DiscStateData%q_f_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%X1_minus1)) THEN + DEALLOCATE(DiscStateData%X1_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%X2_minus1)) THEN + DEALLOCATE(DiscStateData%X2_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%X3_minus1)) THEN + DEALLOCATE(DiscStateData%X3_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%X4_minus1)) THEN + DEALLOCATE(DiscStateData%X4_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Kprime_alpha_minus1)) THEN + DEALLOCATE(DiscStateData%Kprime_alpha_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Kprime_q_minus1)) THEN + DEALLOCATE(DiscStateData%Kprime_q_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Kprimeprime_q_minus1)) THEN + DEALLOCATE(DiscStateData%Kprimeprime_q_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%K3prime_q_minus1)) THEN + DEALLOCATE(DiscStateData%K3prime_q_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Dp_minus1)) THEN + DEALLOCATE(DiscStateData%Dp_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Cn_pot_minus1)) THEN + DEALLOCATE(DiscStateData%Cn_pot_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprimeprime_minus1)) THEN + DEALLOCATE(DiscStateData%fprimeprime_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprimeprime_c_minus1)) THEN + DEALLOCATE(DiscStateData%fprimeprime_c_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprimeprime_m_minus1)) THEN + DEALLOCATE(DiscStateData%fprimeprime_m_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Df_minus1)) THEN + DEALLOCATE(DiscStateData%Df_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Df_c_minus1)) THEN + DEALLOCATE(DiscStateData%Df_c_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Df_m_minus1)) THEN + DEALLOCATE(DiscStateData%Df_m_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Dalphaf_minus1)) THEN + DEALLOCATE(DiscStateData%Dalphaf_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%alphaf_minus1)) THEN + DEALLOCATE(DiscStateData%alphaf_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprime_minus1)) THEN + DEALLOCATE(DiscStateData%fprime_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprime_c_minus1)) THEN + DEALLOCATE(DiscStateData%fprime_c_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%fprime_m_minus1)) THEN + DEALLOCATE(DiscStateData%fprime_m_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%tau_V)) THEN + DEALLOCATE(DiscStateData%tau_V) +ENDIF +IF (ALLOCATED(DiscStateData%tau_V_minus1)) THEN + DEALLOCATE(DiscStateData%tau_V_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Cn_v_minus1)) THEN + DEALLOCATE(DiscStateData%Cn_v_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%C_V_minus1)) THEN + DEALLOCATE(DiscStateData%C_V_minus1) +ENDIF +IF (ALLOCATED(DiscStateData%Cn_prime_minus1)) THEN + DEALLOCATE(DiscStateData%Cn_prime_minus1) +ENDIF + END SUBROUTINE UA_DestroyDiscState + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Int_BufSz = Int_BufSz + 1 ! alpha_minus1 allocated yes/no + IF ( ALLOCATED(InData%alpha_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! alpha_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha_minus1) ! alpha_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! alpha_filt_minus1 allocated yes/no + IF ( ALLOCATED(InData%alpha_filt_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! alpha_filt_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha_filt_minus1) ! alpha_filt_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! q_minus1 allocated yes/no + IF ( ALLOCATED(InData%q_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! q_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%q_minus1) ! q_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Kalpha_f_minus1 allocated yes/no + IF ( ALLOCATED(InData%Kalpha_f_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Kalpha_f_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Kalpha_f_minus1) ! Kalpha_f_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Kq_f_minus1 allocated yes/no + IF ( ALLOCATED(InData%Kq_f_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Kq_f_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Kq_f_minus1) ! Kq_f_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! q_f_minus1 allocated yes/no + IF ( ALLOCATED(InData%q_f_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! q_f_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%q_f_minus1) ! q_f_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! X1_minus1 allocated yes/no + IF ( ALLOCATED(InData%X1_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! X1_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X1_minus1) ! X1_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! X2_minus1 allocated yes/no + IF ( ALLOCATED(InData%X2_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! X2_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X2_minus1) ! X2_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! X3_minus1 allocated yes/no + IF ( ALLOCATED(InData%X3_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! X3_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X3_minus1) ! X3_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! X4_minus1 allocated yes/no + IF ( ALLOCATED(InData%X4_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! X4_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%X4_minus1) ! X4_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Kprime_alpha_minus1 allocated yes/no + IF ( ALLOCATED(InData%Kprime_alpha_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Kprime_alpha_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Kprime_alpha_minus1) ! Kprime_alpha_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Kprime_q_minus1 allocated yes/no + IF ( ALLOCATED(InData%Kprime_q_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Kprime_q_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Kprime_q_minus1) ! Kprime_q_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Kprimeprime_q_minus1 allocated yes/no + IF ( ALLOCATED(InData%Kprimeprime_q_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Kprimeprime_q_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Kprimeprime_q_minus1) ! Kprimeprime_q_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! K3prime_q_minus1 allocated yes/no + IF ( ALLOCATED(InData%K3prime_q_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K3prime_q_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K3prime_q_minus1) ! K3prime_q_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Dp_minus1 allocated yes/no + IF ( ALLOCATED(InData%Dp_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Dp_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Dp_minus1) ! Dp_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Cn_pot_minus1 allocated yes/no + IF ( ALLOCATED(InData%Cn_pot_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cn_pot_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cn_pot_minus1) ! Cn_pot_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprimeprime_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprimeprime_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprimeprime_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprimeprime_minus1) ! fprimeprime_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprimeprime_c_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprimeprime_c_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprimeprime_c_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprimeprime_c_minus1) ! fprimeprime_c_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprimeprime_m_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprimeprime_m_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprimeprime_m_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprimeprime_m_minus1) ! fprimeprime_m_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Df_minus1 allocated yes/no + IF ( ALLOCATED(InData%Df_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Df_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Df_minus1) ! Df_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Df_c_minus1 allocated yes/no + IF ( ALLOCATED(InData%Df_c_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Df_c_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Df_c_minus1) ! Df_c_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Df_m_minus1 allocated yes/no + IF ( ALLOCATED(InData%Df_m_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Df_m_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Df_m_minus1) ! Df_m_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Dalphaf_minus1 allocated yes/no + IF ( ALLOCATED(InData%Dalphaf_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Dalphaf_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Dalphaf_minus1) ! Dalphaf_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! alphaf_minus1 allocated yes/no + IF ( ALLOCATED(InData%alphaf_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! alphaf_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alphaf_minus1) ! alphaf_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprime_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprime_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprime_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprime_minus1) ! fprime_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprime_c_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprime_c_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprime_c_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprime_c_minus1) ! fprime_c_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! fprime_m_minus1 allocated yes/no + IF ( ALLOCATED(InData%fprime_m_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fprime_m_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fprime_m_minus1) ! fprime_m_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! tau_V allocated yes/no + IF ( ALLOCATED(InData%tau_V) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tau_V upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%tau_V) ! tau_V + END IF + Int_BufSz = Int_BufSz + 1 ! tau_V_minus1 allocated yes/no + IF ( ALLOCATED(InData%tau_V_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tau_V_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%tau_V_minus1) ! tau_V_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Cn_v_minus1 allocated yes/no + IF ( ALLOCATED(InData%Cn_v_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cn_v_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cn_v_minus1) ! Cn_v_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! C_V_minus1 allocated yes/no + IF ( ALLOCATED(InData%C_V_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C_V_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C_V_minus1) ! C_V_minus1 + END IF + Int_BufSz = Int_BufSz + 1 ! Cn_prime_minus1 allocated yes/no + IF ( ALLOCATED(InData%Cn_prime_minus1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Cn_prime_minus1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cn_prime_minus1) ! Cn_prime_minus1 + 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%alpha_minus1) ) 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%alpha_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%alpha_minus1,2), UBOUND(InData%alpha_minus1,2) + DO i1 = LBOUND(InData%alpha_minus1,1), UBOUND(InData%alpha_minus1,1) + ReKiBuf(Re_Xferred) = InData%alpha_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alpha_filt_minus1) ) 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%alpha_filt_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_filt_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_filt_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_filt_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%alpha_filt_minus1,2), UBOUND(InData%alpha_filt_minus1,2) + DO i1 = LBOUND(InData%alpha_filt_minus1,1), UBOUND(InData%alpha_filt_minus1,1) + ReKiBuf(Re_Xferred) = InData%alpha_filt_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%q_minus1) ) 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%q_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%q_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%q_minus1,2), UBOUND(InData%q_minus1,2) + DO i1 = LBOUND(InData%q_minus1,1), UBOUND(InData%q_minus1,1) + ReKiBuf(Re_Xferred) = InData%q_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Kalpha_f_minus1) ) 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%Kalpha_f_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kalpha_f_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Kalpha_f_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kalpha_f_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Kalpha_f_minus1,2), UBOUND(InData%Kalpha_f_minus1,2) + DO i1 = LBOUND(InData%Kalpha_f_minus1,1), UBOUND(InData%Kalpha_f_minus1,1) + ReKiBuf(Re_Xferred) = InData%Kalpha_f_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Kq_f_minus1) ) 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%Kq_f_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kq_f_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Kq_f_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kq_f_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Kq_f_minus1,2), UBOUND(InData%Kq_f_minus1,2) + DO i1 = LBOUND(InData%Kq_f_minus1,1), UBOUND(InData%Kq_f_minus1,1) + ReKiBuf(Re_Xferred) = InData%Kq_f_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%q_f_minus1) ) 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%q_f_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q_f_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%q_f_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q_f_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%q_f_minus1,2), UBOUND(InData%q_f_minus1,2) + DO i1 = LBOUND(InData%q_f_minus1,1), UBOUND(InData%q_f_minus1,1) + ReKiBuf(Re_Xferred) = InData%q_f_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X1_minus1) ) 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%X1_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X1_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%X1_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X1_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%X1_minus1,2), UBOUND(InData%X1_minus1,2) + DO i1 = LBOUND(InData%X1_minus1,1), UBOUND(InData%X1_minus1,1) + ReKiBuf(Re_Xferred) = InData%X1_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X2_minus1) ) 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%X2_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X2_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%X2_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X2_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%X2_minus1,2), UBOUND(InData%X2_minus1,2) + DO i1 = LBOUND(InData%X2_minus1,1), UBOUND(InData%X2_minus1,1) + ReKiBuf(Re_Xferred) = InData%X2_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X3_minus1) ) 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%X3_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X3_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%X3_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X3_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%X3_minus1,2), UBOUND(InData%X3_minus1,2) + DO i1 = LBOUND(InData%X3_minus1,1), UBOUND(InData%X3_minus1,1) + ReKiBuf(Re_Xferred) = InData%X3_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%X4_minus1) ) 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%X4_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X4_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%X4_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%X4_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%X4_minus1,2), UBOUND(InData%X4_minus1,2) + DO i1 = LBOUND(InData%X4_minus1,1), UBOUND(InData%X4_minus1,1) + ReKiBuf(Re_Xferred) = InData%X4_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Kprime_alpha_minus1) ) 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%Kprime_alpha_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprime_alpha_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Kprime_alpha_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprime_alpha_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Kprime_alpha_minus1,2), UBOUND(InData%Kprime_alpha_minus1,2) + DO i1 = LBOUND(InData%Kprime_alpha_minus1,1), UBOUND(InData%Kprime_alpha_minus1,1) + ReKiBuf(Re_Xferred) = InData%Kprime_alpha_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Kprime_q_minus1) ) 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%Kprime_q_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprime_q_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Kprime_q_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprime_q_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Kprime_q_minus1,2), UBOUND(InData%Kprime_q_minus1,2) + DO i1 = LBOUND(InData%Kprime_q_minus1,1), UBOUND(InData%Kprime_q_minus1,1) + ReKiBuf(Re_Xferred) = InData%Kprime_q_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Kprimeprime_q_minus1) ) 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%Kprimeprime_q_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprimeprime_q_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Kprimeprime_q_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Kprimeprime_q_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Kprimeprime_q_minus1,2), UBOUND(InData%Kprimeprime_q_minus1,2) + DO i1 = LBOUND(InData%Kprimeprime_q_minus1,1), UBOUND(InData%Kprimeprime_q_minus1,1) + ReKiBuf(Re_Xferred) = InData%Kprimeprime_q_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%K3prime_q_minus1) ) 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%K3prime_q_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K3prime_q_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K3prime_q_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K3prime_q_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%K3prime_q_minus1,2), UBOUND(InData%K3prime_q_minus1,2) + DO i1 = LBOUND(InData%K3prime_q_minus1,1), UBOUND(InData%K3prime_q_minus1,1) + ReKiBuf(Re_Xferred) = InData%K3prime_q_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Dp_minus1) ) 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%Dp_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dp_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Dp_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dp_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Dp_minus1,2), UBOUND(InData%Dp_minus1,2) + DO i1 = LBOUND(InData%Dp_minus1,1), UBOUND(InData%Dp_minus1,1) + ReKiBuf(Re_Xferred) = InData%Dp_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cn_pot_minus1) ) 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%Cn_pot_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_pot_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cn_pot_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_pot_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cn_pot_minus1,2), UBOUND(InData%Cn_pot_minus1,2) + DO i1 = LBOUND(InData%Cn_pot_minus1,1), UBOUND(InData%Cn_pot_minus1,1) + ReKiBuf(Re_Xferred) = InData%Cn_pot_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprimeprime_minus1) ) 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%fprimeprime_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprimeprime_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprimeprime_minus1,2), UBOUND(InData%fprimeprime_minus1,2) + DO i1 = LBOUND(InData%fprimeprime_minus1,1), UBOUND(InData%fprimeprime_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprimeprime_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprimeprime_c_minus1) ) 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%fprimeprime_c_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_c_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprimeprime_c_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_c_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprimeprime_c_minus1,2), UBOUND(InData%fprimeprime_c_minus1,2) + DO i1 = LBOUND(InData%fprimeprime_c_minus1,1), UBOUND(InData%fprimeprime_c_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprimeprime_c_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprimeprime_m_minus1) ) 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%fprimeprime_m_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_m_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprimeprime_m_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprimeprime_m_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprimeprime_m_minus1,2), UBOUND(InData%fprimeprime_m_minus1,2) + DO i1 = LBOUND(InData%fprimeprime_m_minus1,1), UBOUND(InData%fprimeprime_m_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprimeprime_m_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Df_minus1) ) 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%Df_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Df_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Df_minus1,2), UBOUND(InData%Df_minus1,2) + DO i1 = LBOUND(InData%Df_minus1,1), UBOUND(InData%Df_minus1,1) + ReKiBuf(Re_Xferred) = InData%Df_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Df_c_minus1) ) 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%Df_c_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_c_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Df_c_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_c_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Df_c_minus1,2), UBOUND(InData%Df_c_minus1,2) + DO i1 = LBOUND(InData%Df_c_minus1,1), UBOUND(InData%Df_c_minus1,1) + ReKiBuf(Re_Xferred) = InData%Df_c_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Df_m_minus1) ) 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%Df_m_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_m_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Df_m_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Df_m_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Df_m_minus1,2), UBOUND(InData%Df_m_minus1,2) + DO i1 = LBOUND(InData%Df_m_minus1,1), UBOUND(InData%Df_m_minus1,1) + ReKiBuf(Re_Xferred) = InData%Df_m_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Dalphaf_minus1) ) 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%Dalphaf_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dalphaf_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Dalphaf_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dalphaf_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Dalphaf_minus1,2), UBOUND(InData%Dalphaf_minus1,2) + DO i1 = LBOUND(InData%Dalphaf_minus1,1), UBOUND(InData%Dalphaf_minus1,1) + ReKiBuf(Re_Xferred) = InData%Dalphaf_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alphaf_minus1) ) 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%alphaf_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alphaf_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alphaf_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alphaf_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%alphaf_minus1,2), UBOUND(InData%alphaf_minus1,2) + DO i1 = LBOUND(InData%alphaf_minus1,1), UBOUND(InData%alphaf_minus1,1) + ReKiBuf(Re_Xferred) = InData%alphaf_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprime_minus1) ) 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%fprime_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprime_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprime_minus1,2), UBOUND(InData%fprime_minus1,2) + DO i1 = LBOUND(InData%fprime_minus1,1), UBOUND(InData%fprime_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprime_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprime_c_minus1) ) 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%fprime_c_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_c_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprime_c_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_c_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprime_c_minus1,2), UBOUND(InData%fprime_c_minus1,2) + DO i1 = LBOUND(InData%fprime_c_minus1,1), UBOUND(InData%fprime_c_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprime_c_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fprime_m_minus1) ) 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%fprime_m_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_m_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fprime_m_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fprime_m_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fprime_m_minus1,2), UBOUND(InData%fprime_m_minus1,2) + DO i1 = LBOUND(InData%fprime_m_minus1,1), UBOUND(InData%fprime_m_minus1,1) + ReKiBuf(Re_Xferred) = InData%fprime_m_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tau_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%tau_V,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tau_V,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tau_V,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tau_V,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tau_V,2), UBOUND(InData%tau_V,2) + DO i1 = LBOUND(InData%tau_V,1), UBOUND(InData%tau_V,1) + ReKiBuf(Re_Xferred) = InData%tau_V(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tau_V_minus1) ) 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%tau_V_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tau_V_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tau_V_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tau_V_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tau_V_minus1,2), UBOUND(InData%tau_V_minus1,2) + DO i1 = LBOUND(InData%tau_V_minus1,1), UBOUND(InData%tau_V_minus1,1) + ReKiBuf(Re_Xferred) = InData%tau_V_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cn_v_minus1) ) 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%Cn_v_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_v_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cn_v_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_v_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cn_v_minus1,2), UBOUND(InData%Cn_v_minus1,2) + DO i1 = LBOUND(InData%Cn_v_minus1,1), UBOUND(InData%Cn_v_minus1,1) + ReKiBuf(Re_Xferred) = InData%Cn_v_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C_V_minus1) ) 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%C_V_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C_V_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C_V_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C_V_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C_V_minus1,2), UBOUND(InData%C_V_minus1,2) + DO i1 = LBOUND(InData%C_V_minus1,1), UBOUND(InData%C_V_minus1,1) + ReKiBuf(Re_Xferred) = InData%C_V_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cn_prime_minus1) ) 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%Cn_prime_minus1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_prime_minus1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cn_prime_minus1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cn_prime_minus1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Cn_prime_minus1,2), UBOUND(InData%Cn_prime_minus1,2) + DO i1 = LBOUND(InData%Cn_prime_minus1,1), UBOUND(InData%Cn_prime_minus1,1) + ReKiBuf(Re_Xferred) = InData%Cn_prime_minus1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE UA_PackDiscState + + SUBROUTINE UA_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(UA_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) :: 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 = 'UA_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_minus1 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%alpha_minus1)) DEALLOCATE(OutData%alpha_minus1) + ALLOCATE(OutData%alpha_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%alpha_minus1,2), UBOUND(OutData%alpha_minus1,2) + DO i1 = LBOUND(OutData%alpha_minus1,1), UBOUND(OutData%alpha_minus1,1) + OutData%alpha_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_filt_minus1 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%alpha_filt_minus1)) DEALLOCATE(OutData%alpha_filt_minus1) + ALLOCATE(OutData%alpha_filt_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_filt_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%alpha_filt_minus1,2), UBOUND(OutData%alpha_filt_minus1,2) + DO i1 = LBOUND(OutData%alpha_filt_minus1,1), UBOUND(OutData%alpha_filt_minus1,1) + OutData%alpha_filt_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! q_minus1 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%q_minus1)) DEALLOCATE(OutData%q_minus1) + ALLOCATE(OutData%q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%q_minus1,2), UBOUND(OutData%q_minus1,2) + DO i1 = LBOUND(OutData%q_minus1,1), UBOUND(OutData%q_minus1,1) + OutData%q_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Kalpha_f_minus1 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%Kalpha_f_minus1)) DEALLOCATE(OutData%Kalpha_f_minus1) + ALLOCATE(OutData%Kalpha_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Kalpha_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Kalpha_f_minus1,2), UBOUND(OutData%Kalpha_f_minus1,2) + DO i1 = LBOUND(OutData%Kalpha_f_minus1,1), UBOUND(OutData%Kalpha_f_minus1,1) + OutData%Kalpha_f_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Kq_f_minus1 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%Kq_f_minus1)) DEALLOCATE(OutData%Kq_f_minus1) + ALLOCATE(OutData%Kq_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Kq_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Kq_f_minus1,2), UBOUND(OutData%Kq_f_minus1,2) + DO i1 = LBOUND(OutData%Kq_f_minus1,1), UBOUND(OutData%Kq_f_minus1,1) + OutData%Kq_f_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! q_f_minus1 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%q_f_minus1)) DEALLOCATE(OutData%q_f_minus1) + ALLOCATE(OutData%q_f_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%q_f_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%q_f_minus1,2), UBOUND(OutData%q_f_minus1,2) + DO i1 = LBOUND(OutData%q_f_minus1,1), UBOUND(OutData%q_f_minus1,1) + OutData%q_f_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X1_minus1 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%X1_minus1)) DEALLOCATE(OutData%X1_minus1) + ALLOCATE(OutData%X1_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X1_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%X1_minus1,2), UBOUND(OutData%X1_minus1,2) + DO i1 = LBOUND(OutData%X1_minus1,1), UBOUND(OutData%X1_minus1,1) + OutData%X1_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X2_minus1 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%X2_minus1)) DEALLOCATE(OutData%X2_minus1) + ALLOCATE(OutData%X2_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X2_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%X2_minus1,2), UBOUND(OutData%X2_minus1,2) + DO i1 = LBOUND(OutData%X2_minus1,1), UBOUND(OutData%X2_minus1,1) + OutData%X2_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X3_minus1 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%X3_minus1)) DEALLOCATE(OutData%X3_minus1) + ALLOCATE(OutData%X3_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X3_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%X3_minus1,2), UBOUND(OutData%X3_minus1,2) + DO i1 = LBOUND(OutData%X3_minus1,1), UBOUND(OutData%X3_minus1,1) + OutData%X3_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! X4_minus1 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%X4_minus1)) DEALLOCATE(OutData%X4_minus1) + ALLOCATE(OutData%X4_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%X4_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%X4_minus1,2), UBOUND(OutData%X4_minus1,2) + DO i1 = LBOUND(OutData%X4_minus1,1), UBOUND(OutData%X4_minus1,1) + OutData%X4_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Kprime_alpha_minus1 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%Kprime_alpha_minus1)) DEALLOCATE(OutData%Kprime_alpha_minus1) + ALLOCATE(OutData%Kprime_alpha_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Kprime_alpha_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Kprime_alpha_minus1,2), UBOUND(OutData%Kprime_alpha_minus1,2) + DO i1 = LBOUND(OutData%Kprime_alpha_minus1,1), UBOUND(OutData%Kprime_alpha_minus1,1) + OutData%Kprime_alpha_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Kprime_q_minus1 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%Kprime_q_minus1)) DEALLOCATE(OutData%Kprime_q_minus1) + ALLOCATE(OutData%Kprime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Kprime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Kprime_q_minus1,2), UBOUND(OutData%Kprime_q_minus1,2) + DO i1 = LBOUND(OutData%Kprime_q_minus1,1), UBOUND(OutData%Kprime_q_minus1,1) + OutData%Kprime_q_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Kprimeprime_q_minus1 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%Kprimeprime_q_minus1)) DEALLOCATE(OutData%Kprimeprime_q_minus1) + ALLOCATE(OutData%Kprimeprime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Kprimeprime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Kprimeprime_q_minus1,2), UBOUND(OutData%Kprimeprime_q_minus1,2) + DO i1 = LBOUND(OutData%Kprimeprime_q_minus1,1), UBOUND(OutData%Kprimeprime_q_minus1,1) + OutData%Kprimeprime_q_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K3prime_q_minus1 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%K3prime_q_minus1)) DEALLOCATE(OutData%K3prime_q_minus1) + ALLOCATE(OutData%K3prime_q_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K3prime_q_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%K3prime_q_minus1,2), UBOUND(OutData%K3prime_q_minus1,2) + DO i1 = LBOUND(OutData%K3prime_q_minus1,1), UBOUND(OutData%K3prime_q_minus1,1) + OutData%K3prime_q_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Dp_minus1 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%Dp_minus1)) DEALLOCATE(OutData%Dp_minus1) + ALLOCATE(OutData%Dp_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Dp_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Dp_minus1,2), UBOUND(OutData%Dp_minus1,2) + DO i1 = LBOUND(OutData%Dp_minus1,1), UBOUND(OutData%Dp_minus1,1) + OutData%Dp_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cn_pot_minus1 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%Cn_pot_minus1)) DEALLOCATE(OutData%Cn_pot_minus1) + ALLOCATE(OutData%Cn_pot_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cn_pot_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cn_pot_minus1,2), UBOUND(OutData%Cn_pot_minus1,2) + DO i1 = LBOUND(OutData%Cn_pot_minus1,1), UBOUND(OutData%Cn_pot_minus1,1) + OutData%Cn_pot_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprimeprime_minus1 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%fprimeprime_minus1)) DEALLOCATE(OutData%fprimeprime_minus1) + ALLOCATE(OutData%fprimeprime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprimeprime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprimeprime_minus1,2), UBOUND(OutData%fprimeprime_minus1,2) + DO i1 = LBOUND(OutData%fprimeprime_minus1,1), UBOUND(OutData%fprimeprime_minus1,1) + OutData%fprimeprime_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprimeprime_c_minus1 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%fprimeprime_c_minus1)) DEALLOCATE(OutData%fprimeprime_c_minus1) + ALLOCATE(OutData%fprimeprime_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprimeprime_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprimeprime_c_minus1,2), UBOUND(OutData%fprimeprime_c_minus1,2) + DO i1 = LBOUND(OutData%fprimeprime_c_minus1,1), UBOUND(OutData%fprimeprime_c_minus1,1) + OutData%fprimeprime_c_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprimeprime_m_minus1 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%fprimeprime_m_minus1)) DEALLOCATE(OutData%fprimeprime_m_minus1) + ALLOCATE(OutData%fprimeprime_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprimeprime_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprimeprime_m_minus1,2), UBOUND(OutData%fprimeprime_m_minus1,2) + DO i1 = LBOUND(OutData%fprimeprime_m_minus1,1), UBOUND(OutData%fprimeprime_m_minus1,1) + OutData%fprimeprime_m_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Df_minus1 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%Df_minus1)) DEALLOCATE(OutData%Df_minus1) + ALLOCATE(OutData%Df_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Df_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Df_minus1,2), UBOUND(OutData%Df_minus1,2) + DO i1 = LBOUND(OutData%Df_minus1,1), UBOUND(OutData%Df_minus1,1) + OutData%Df_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Df_c_minus1 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%Df_c_minus1)) DEALLOCATE(OutData%Df_c_minus1) + ALLOCATE(OutData%Df_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Df_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Df_c_minus1,2), UBOUND(OutData%Df_c_minus1,2) + DO i1 = LBOUND(OutData%Df_c_minus1,1), UBOUND(OutData%Df_c_minus1,1) + OutData%Df_c_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Df_m_minus1 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%Df_m_minus1)) DEALLOCATE(OutData%Df_m_minus1) + ALLOCATE(OutData%Df_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Df_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Df_m_minus1,2), UBOUND(OutData%Df_m_minus1,2) + DO i1 = LBOUND(OutData%Df_m_minus1,1), UBOUND(OutData%Df_m_minus1,1) + OutData%Df_m_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Dalphaf_minus1 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%Dalphaf_minus1)) DEALLOCATE(OutData%Dalphaf_minus1) + ALLOCATE(OutData%Dalphaf_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Dalphaf_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Dalphaf_minus1,2), UBOUND(OutData%Dalphaf_minus1,2) + DO i1 = LBOUND(OutData%Dalphaf_minus1,1), UBOUND(OutData%Dalphaf_minus1,1) + OutData%Dalphaf_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alphaf_minus1 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%alphaf_minus1)) DEALLOCATE(OutData%alphaf_minus1) + ALLOCATE(OutData%alphaf_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alphaf_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%alphaf_minus1,2), UBOUND(OutData%alphaf_minus1,2) + DO i1 = LBOUND(OutData%alphaf_minus1,1), UBOUND(OutData%alphaf_minus1,1) + OutData%alphaf_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprime_minus1 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%fprime_minus1)) DEALLOCATE(OutData%fprime_minus1) + ALLOCATE(OutData%fprime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprime_minus1,2), UBOUND(OutData%fprime_minus1,2) + DO i1 = LBOUND(OutData%fprime_minus1,1), UBOUND(OutData%fprime_minus1,1) + OutData%fprime_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprime_c_minus1 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%fprime_c_minus1)) DEALLOCATE(OutData%fprime_c_minus1) + ALLOCATE(OutData%fprime_c_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprime_c_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprime_c_minus1,2), UBOUND(OutData%fprime_c_minus1,2) + DO i1 = LBOUND(OutData%fprime_c_minus1,1), UBOUND(OutData%fprime_c_minus1,1) + OutData%fprime_c_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fprime_m_minus1 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%fprime_m_minus1)) DEALLOCATE(OutData%fprime_m_minus1) + ALLOCATE(OutData%fprime_m_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fprime_m_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fprime_m_minus1,2), UBOUND(OutData%fprime_m_minus1,2) + DO i1 = LBOUND(OutData%fprime_m_minus1,1), UBOUND(OutData%fprime_m_minus1,1) + OutData%fprime_m_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tau_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 + IF (ALLOCATED(OutData%tau_V)) DEALLOCATE(OutData%tau_V) + ALLOCATE(OutData%tau_V(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tau_V.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tau_V,2), UBOUND(OutData%tau_V,2) + DO i1 = LBOUND(OutData%tau_V,1), UBOUND(OutData%tau_V,1) + OutData%tau_V(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tau_V_minus1 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%tau_V_minus1)) DEALLOCATE(OutData%tau_V_minus1) + ALLOCATE(OutData%tau_V_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tau_V_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tau_V_minus1,2), UBOUND(OutData%tau_V_minus1,2) + DO i1 = LBOUND(OutData%tau_V_minus1,1), UBOUND(OutData%tau_V_minus1,1) + OutData%tau_V_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cn_v_minus1 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%Cn_v_minus1)) DEALLOCATE(OutData%Cn_v_minus1) + ALLOCATE(OutData%Cn_v_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cn_v_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cn_v_minus1,2), UBOUND(OutData%Cn_v_minus1,2) + DO i1 = LBOUND(OutData%Cn_v_minus1,1), UBOUND(OutData%Cn_v_minus1,1) + OutData%Cn_v_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C_V_minus1 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%C_V_minus1)) DEALLOCATE(OutData%C_V_minus1) + ALLOCATE(OutData%C_V_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C_V_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C_V_minus1,2), UBOUND(OutData%C_V_minus1,2) + DO i1 = LBOUND(OutData%C_V_minus1,1), UBOUND(OutData%C_V_minus1,1) + OutData%C_V_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cn_prime_minus1 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%Cn_prime_minus1)) DEALLOCATE(OutData%Cn_prime_minus1) + ALLOCATE(OutData%Cn_prime_minus1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cn_prime_minus1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Cn_prime_minus1,2), UBOUND(OutData%Cn_prime_minus1,2) + DO i1 = LBOUND(OutData%Cn_prime_minus1,1), UBOUND(OutData%Cn_prime_minus1,1) + OutData%Cn_prime_minus1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE UA_UnPackDiscState + + SUBROUTINE UA_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(UA_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 = 'UA_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstraintState = SrcConstrStateData%DummyConstraintState + END SUBROUTINE UA_CopyConstrState + + SUBROUTINE UA_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(UA_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE UA_DestroyConstrState + + SUBROUTINE UA_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(UA_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 = 'UA_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 ! DummyConstraintState + 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%DummyConstraintState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_PackConstrState + + SUBROUTINE UA_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(UA_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 = 'UA_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%DummyConstraintState = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_UnPackConstrState + + SUBROUTINE UA_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(UA_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) :: 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 = 'UA_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%FirstPass)) THEN + i1_l = LBOUND(SrcOtherStateData%FirstPass,1) + i1_u = UBOUND(SrcOtherStateData%FirstPass,1) + i2_l = LBOUND(SrcOtherStateData%FirstPass,2) + i2_u = UBOUND(SrcOtherStateData%FirstPass,2) + IF (.NOT. ALLOCATED(DstOtherStateData%FirstPass)) THEN + ALLOCATE(DstOtherStateData%FirstPass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%FirstPass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%FirstPass = SrcOtherStateData%FirstPass +ENDIF +IF (ALLOCATED(SrcOtherStateData%sigma1)) THEN + i1_l = LBOUND(SrcOtherStateData%sigma1,1) + i1_u = UBOUND(SrcOtherStateData%sigma1,1) + i2_l = LBOUND(SrcOtherStateData%sigma1,2) + i2_u = UBOUND(SrcOtherStateData%sigma1,2) + IF (.NOT. ALLOCATED(DstOtherStateData%sigma1)) THEN + ALLOCATE(DstOtherStateData%sigma1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%sigma1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%sigma1 = SrcOtherStateData%sigma1 +ENDIF +IF (ALLOCATED(SrcOtherStateData%sigma1c)) THEN + i1_l = LBOUND(SrcOtherStateData%sigma1c,1) + i1_u = UBOUND(SrcOtherStateData%sigma1c,1) + i2_l = LBOUND(SrcOtherStateData%sigma1c,2) + i2_u = UBOUND(SrcOtherStateData%sigma1c,2) + IF (.NOT. ALLOCATED(DstOtherStateData%sigma1c)) THEN + ALLOCATE(DstOtherStateData%sigma1c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%sigma1c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%sigma1c = SrcOtherStateData%sigma1c +ENDIF +IF (ALLOCATED(SrcOtherStateData%sigma1m)) THEN + i1_l = LBOUND(SrcOtherStateData%sigma1m,1) + i1_u = UBOUND(SrcOtherStateData%sigma1m,1) + i2_l = LBOUND(SrcOtherStateData%sigma1m,2) + i2_u = UBOUND(SrcOtherStateData%sigma1m,2) + IF (.NOT. ALLOCATED(DstOtherStateData%sigma1m)) THEN + ALLOCATE(DstOtherStateData%sigma1m(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%sigma1m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%sigma1m = SrcOtherStateData%sigma1m +ENDIF +IF (ALLOCATED(SrcOtherStateData%sigma3)) THEN + i1_l = LBOUND(SrcOtherStateData%sigma3,1) + i1_u = UBOUND(SrcOtherStateData%sigma3,1) + i2_l = LBOUND(SrcOtherStateData%sigma3,2) + i2_u = UBOUND(SrcOtherStateData%sigma3,2) + IF (.NOT. ALLOCATED(DstOtherStateData%sigma3)) THEN + ALLOCATE(DstOtherStateData%sigma3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%sigma3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%sigma3 = SrcOtherStateData%sigma3 +ENDIF +IF (ALLOCATED(SrcOtherStateData%n)) THEN + i1_l = LBOUND(SrcOtherStateData%n,1) + i1_u = UBOUND(SrcOtherStateData%n,1) + i2_l = LBOUND(SrcOtherStateData%n,2) + i2_u = UBOUND(SrcOtherStateData%n,2) + IF (.NOT. ALLOCATED(DstOtherStateData%n)) THEN + ALLOCATE(DstOtherStateData%n(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%n.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%n = SrcOtherStateData%n +ENDIF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL UA_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + END SUBROUTINE UA_CopyOtherState + + SUBROUTINE UA_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(UA_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%FirstPass)) THEN + DEALLOCATE(OtherStateData%FirstPass) +ENDIF +IF (ALLOCATED(OtherStateData%sigma1)) THEN + DEALLOCATE(OtherStateData%sigma1) +ENDIF +IF (ALLOCATED(OtherStateData%sigma1c)) THEN + DEALLOCATE(OtherStateData%sigma1c) +ENDIF +IF (ALLOCATED(OtherStateData%sigma1m)) THEN + DEALLOCATE(OtherStateData%sigma1m) +ENDIF +IF (ALLOCATED(OtherStateData%sigma3)) THEN + DEALLOCATE(OtherStateData%sigma3) +ENDIF +IF (ALLOCATED(OtherStateData%n)) THEN + DEALLOCATE(OtherStateData%n) +ENDIF +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL UA_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + END SUBROUTINE UA_DestroyOtherState + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Int_BufSz = Int_BufSz + 1 ! FirstPass allocated yes/no + IF ( ALLOCATED(InData%FirstPass) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FirstPass upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FirstPass) ! FirstPass + END IF + Int_BufSz = Int_BufSz + 1 ! sigma1 allocated yes/no + IF ( ALLOCATED(InData%sigma1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! sigma1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%sigma1) ! sigma1 + END IF + Int_BufSz = Int_BufSz + 1 ! sigma1c allocated yes/no + IF ( ALLOCATED(InData%sigma1c) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! sigma1c upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%sigma1c) ! sigma1c + END IF + Int_BufSz = Int_BufSz + 1 ! sigma1m allocated yes/no + IF ( ALLOCATED(InData%sigma1m) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! sigma1m upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%sigma1m) ! sigma1m + END IF + Int_BufSz = Int_BufSz + 1 ! sigma3 allocated yes/no + IF ( ALLOCATED(InData%sigma3) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! sigma3 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%sigma3) ! sigma3 + END IF + Int_BufSz = Int_BufSz + 1 ! n allocated yes/no + IF ( ALLOCATED(InData%n) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! n upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%n) ! n + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%FirstPass) ) 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%FirstPass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FirstPass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FirstPass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FirstPass,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FirstPass,2), UBOUND(InData%FirstPass,2) + DO i1 = LBOUND(InData%FirstPass,1), UBOUND(InData%FirstPass,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstPass(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%sigma1) ) 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%sigma1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%sigma1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%sigma1,2), UBOUND(InData%sigma1,2) + DO i1 = LBOUND(InData%sigma1,1), UBOUND(InData%sigma1,1) + ReKiBuf(Re_Xferred) = InData%sigma1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%sigma1c) ) 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%sigma1c,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1c,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%sigma1c,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1c,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%sigma1c,2), UBOUND(InData%sigma1c,2) + DO i1 = LBOUND(InData%sigma1c,1), UBOUND(InData%sigma1c,1) + ReKiBuf(Re_Xferred) = InData%sigma1c(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%sigma1m) ) 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%sigma1m,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1m,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%sigma1m,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma1m,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%sigma1m,2), UBOUND(InData%sigma1m,2) + DO i1 = LBOUND(InData%sigma1m,1), UBOUND(InData%sigma1m,1) + ReKiBuf(Re_Xferred) = InData%sigma1m(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%sigma3) ) 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%sigma3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%sigma3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sigma3,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%sigma3,2), UBOUND(InData%sigma3,2) + DO i1 = LBOUND(InData%sigma3,1), UBOUND(InData%sigma3,1) + ReKiBuf(Re_Xferred) = InData%sigma3(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%n) ) 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%n,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%n,2), UBOUND(InData%n,2) + DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) + IntKiBuf(Int_Xferred) = InData%n(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL UA_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 SUBROUTINE UA_PackOtherState + + SUBROUTINE UA_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(UA_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) :: 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 = 'UA_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FirstPass 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%FirstPass)) DEALLOCATE(OutData%FirstPass) + ALLOCATE(OutData%FirstPass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FirstPass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FirstPass,2), UBOUND(OutData%FirstPass,2) + DO i1 = LBOUND(OutData%FirstPass,1), UBOUND(OutData%FirstPass,1) + OutData%FirstPass(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstPass(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! sigma1 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%sigma1)) DEALLOCATE(OutData%sigma1) + ALLOCATE(OutData%sigma1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%sigma1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%sigma1,2), UBOUND(OutData%sigma1,2) + DO i1 = LBOUND(OutData%sigma1,1), UBOUND(OutData%sigma1,1) + OutData%sigma1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! sigma1c 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%sigma1c)) DEALLOCATE(OutData%sigma1c) + ALLOCATE(OutData%sigma1c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%sigma1c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%sigma1c,2), UBOUND(OutData%sigma1c,2) + DO i1 = LBOUND(OutData%sigma1c,1), UBOUND(OutData%sigma1c,1) + OutData%sigma1c(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! sigma1m 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%sigma1m)) DEALLOCATE(OutData%sigma1m) + ALLOCATE(OutData%sigma1m(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%sigma1m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%sigma1m,2), UBOUND(OutData%sigma1m,2) + DO i1 = LBOUND(OutData%sigma1m,1), UBOUND(OutData%sigma1m,1) + OutData%sigma1m(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! sigma3 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%sigma3)) DEALLOCATE(OutData%sigma3) + ALLOCATE(OutData%sigma3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%sigma3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%sigma3,2), UBOUND(OutData%sigma3,2) + DO i1 = LBOUND(OutData%sigma3,1), UBOUND(OutData%sigma3,1) + OutData%sigma3(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! n 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%n)) DEALLOCATE(OutData%n) + ALLOCATE(OutData%n(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%n.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%n,2), UBOUND(OutData%n,2) + DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) + OutData%n(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%xdot,1) + i1_u = UBOUND(OutData%xdot,1) + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 UA_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END SUBROUTINE UA_UnPackOtherState + + SUBROUTINE UA_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(UA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'UA_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%FirstWarn_M = SrcMiscData%FirstWarn_M + DstMiscData%FirstWarn_UA = SrcMiscData%FirstWarn_UA +IF (ALLOCATED(SrcMiscData%TESF)) THEN + i1_l = LBOUND(SrcMiscData%TESF,1) + i1_u = UBOUND(SrcMiscData%TESF,1) + i2_l = LBOUND(SrcMiscData%TESF,2) + i2_u = UBOUND(SrcMiscData%TESF,2) + IF (.NOT. ALLOCATED(DstMiscData%TESF)) THEN + ALLOCATE(DstMiscData%TESF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%TESF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%TESF = SrcMiscData%TESF +ENDIF +IF (ALLOCATED(SrcMiscData%LESF)) THEN + i1_l = LBOUND(SrcMiscData%LESF,1) + i1_u = UBOUND(SrcMiscData%LESF,1) + i2_l = LBOUND(SrcMiscData%LESF,2) + i2_u = UBOUND(SrcMiscData%LESF,2) + IF (.NOT. ALLOCATED(DstMiscData%LESF)) THEN + ALLOCATE(DstMiscData%LESF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LESF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LESF = SrcMiscData%LESF +ENDIF +IF (ALLOCATED(SrcMiscData%VRTX)) THEN + i1_l = LBOUND(SrcMiscData%VRTX,1) + i1_u = UBOUND(SrcMiscData%VRTX,1) + i2_l = LBOUND(SrcMiscData%VRTX,2) + i2_u = UBOUND(SrcMiscData%VRTX,2) + IF (.NOT. ALLOCATED(DstMiscData%VRTX)) THEN + ALLOCATE(DstMiscData%VRTX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%VRTX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%VRTX = SrcMiscData%VRTX +ENDIF +IF (ALLOCATED(SrcMiscData%T_Sh)) THEN + i1_l = LBOUND(SrcMiscData%T_Sh,1) + i1_u = UBOUND(SrcMiscData%T_Sh,1) + i2_l = LBOUND(SrcMiscData%T_Sh,2) + i2_u = UBOUND(SrcMiscData%T_Sh,2) + IF (.NOT. ALLOCATED(DstMiscData%T_Sh)) THEN + ALLOCATE(DstMiscData%T_Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%T_Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%T_Sh = SrcMiscData%T_Sh +ENDIF +IF (ALLOCATED(SrcMiscData%BEDSEP)) THEN + i1_l = LBOUND(SrcMiscData%BEDSEP,1) + i1_u = UBOUND(SrcMiscData%BEDSEP,1) + i2_l = LBOUND(SrcMiscData%BEDSEP,2) + i2_u = UBOUND(SrcMiscData%BEDSEP,2) + IF (.NOT. ALLOCATED(DstMiscData%BEDSEP)) THEN + ALLOCATE(DstMiscData%BEDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BEDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BEDSEP = SrcMiscData%BEDSEP +ENDIF + END SUBROUTINE UA_CopyMisc + + SUBROUTINE UA_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(UA_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%TESF)) THEN + DEALLOCATE(MiscData%TESF) +ENDIF +IF (ALLOCATED(MiscData%LESF)) THEN + DEALLOCATE(MiscData%LESF) +ENDIF +IF (ALLOCATED(MiscData%VRTX)) THEN + DEALLOCATE(MiscData%VRTX) +ENDIF +IF (ALLOCATED(MiscData%T_Sh)) THEN + DEALLOCATE(MiscData%T_Sh) +ENDIF +IF (ALLOCATED(MiscData%BEDSEP)) THEN + DEALLOCATE(MiscData%BEDSEP) +ENDIF + END SUBROUTINE UA_DestroyMisc + + SUBROUTINE UA_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(UA_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 = 'UA_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 ! FirstWarn_M + Int_BufSz = Int_BufSz + 1 ! FirstWarn_UA + Int_BufSz = Int_BufSz + 1 ! TESF allocated yes/no + IF ( ALLOCATED(InData%TESF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TESF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%TESF) ! TESF + END IF + Int_BufSz = Int_BufSz + 1 ! LESF allocated yes/no + IF ( ALLOCATED(InData%LESF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LESF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LESF) ! LESF + END IF + Int_BufSz = Int_BufSz + 1 ! VRTX allocated yes/no + IF ( ALLOCATED(InData%VRTX) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! VRTX upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%VRTX) ! VRTX + END IF + Int_BufSz = Int_BufSz + 1 ! T_Sh allocated yes/no + IF ( ALLOCATED(InData%T_Sh) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! T_Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%T_Sh) ! T_Sh + END IF + Int_BufSz = Int_BufSz + 1 ! BEDSEP allocated yes/no + IF ( ALLOCATED(InData%BEDSEP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BEDSEP upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BEDSEP) ! BEDSEP + 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) = TRANSFER(InData%FirstWarn_M, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstWarn_UA, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TESF) ) 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%TESF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TESF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TESF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TESF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TESF,2), UBOUND(InData%TESF,2) + DO i1 = LBOUND(InData%TESF,1), UBOUND(InData%TESF,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%TESF(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LESF) ) 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%LESF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LESF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LESF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LESF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LESF,2), UBOUND(InData%LESF,2) + DO i1 = LBOUND(InData%LESF,1), UBOUND(InData%LESF,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%LESF(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VRTX) ) 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%VRTX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VRTX,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VRTX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VRTX,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%VRTX,2), UBOUND(InData%VRTX,2) + DO i1 = LBOUND(InData%VRTX,1), UBOUND(InData%VRTX,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%VRTX(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%T_Sh) ) 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%T_Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_Sh,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_Sh,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_Sh,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%T_Sh,2), UBOUND(InData%T_Sh,2) + DO i1 = LBOUND(InData%T_Sh,1), UBOUND(InData%T_Sh,1) + ReKiBuf(Re_Xferred) = InData%T_Sh(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BEDSEP) ) 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%BEDSEP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BEDSEP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BEDSEP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BEDSEP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BEDSEP,2), UBOUND(InData%BEDSEP,2) + DO i1 = LBOUND(InData%BEDSEP,1), UBOUND(InData%BEDSEP,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%BEDSEP(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE UA_PackMisc + + SUBROUTINE UA_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(UA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'UA_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%FirstWarn_M = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_M) + Int_Xferred = Int_Xferred + 1 + OutData%FirstWarn_UA = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn_UA) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TESF 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%TESF)) DEALLOCATE(OutData%TESF) + ALLOCATE(OutData%TESF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TESF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TESF,2), UBOUND(OutData%TESF,2) + DO i1 = LBOUND(OutData%TESF,1), UBOUND(OutData%TESF,1) + OutData%TESF(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%TESF(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LESF 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%LESF)) DEALLOCATE(OutData%LESF) + ALLOCATE(OutData%LESF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LESF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LESF,2), UBOUND(OutData%LESF,2) + DO i1 = LBOUND(OutData%LESF,1), UBOUND(OutData%LESF,1) + OutData%LESF(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%LESF(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VRTX 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%VRTX)) DEALLOCATE(OutData%VRTX) + ALLOCATE(OutData%VRTX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VRTX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%VRTX,2), UBOUND(OutData%VRTX,2) + DO i1 = LBOUND(OutData%VRTX,1), UBOUND(OutData%VRTX,1) + OutData%VRTX(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%VRTX(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_Sh 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%T_Sh)) DEALLOCATE(OutData%T_Sh) + ALLOCATE(OutData%T_Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%T_Sh,2), UBOUND(OutData%T_Sh,2) + DO i1 = LBOUND(OutData%T_Sh,1), UBOUND(OutData%T_Sh,1) + OutData%T_Sh(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BEDSEP 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%BEDSEP)) DEALLOCATE(OutData%BEDSEP) + ALLOCATE(OutData%BEDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BEDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BEDSEP,2), UBOUND(OutData%BEDSEP,2) + DO i1 = LBOUND(OutData%BEDSEP,1), UBOUND(OutData%BEDSEP,1) + OutData%BEDSEP(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%BEDSEP(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE UA_UnPackMisc + + SUBROUTINE UA_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_ParameterType), INTENT(IN) :: SrcParamData + TYPE(UA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'UA_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%dt = SrcParamData%dt +IF (ALLOCATED(SrcParamData%c)) THEN + i1_l = LBOUND(SrcParamData%c,1) + i1_u = UBOUND(SrcParamData%c,1) + i2_l = LBOUND(SrcParamData%c,2) + i2_u = UBOUND(SrcParamData%c,2) + IF (.NOT. ALLOCATED(DstParamData%c)) THEN + ALLOCATE(DstParamData%c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%c = SrcParamData%c +ENDIF + DstParamData%numBlades = SrcParamData%numBlades + DstParamData%nNodesPerBlade = SrcParamData%nNodesPerBlade + DstParamData%UAMod = SrcParamData%UAMod + DstParamData%Flookup = SrcParamData%Flookup + DstParamData%a_s = SrcParamData%a_s + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%OutSwtch = SrcParamData%OutSwtch + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + DstParamData%UnOutFile = SrcParamData%UnOutFile + DstParamData%ShedEffect = SrcParamData%ShedEffect + DstParamData%lin_nx = SrcParamData%lin_nx + END SUBROUTINE UA_CopyParam + + SUBROUTINE UA_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(UA_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%c)) THEN + DEALLOCATE(ParamData%c) +ENDIF + END SUBROUTINE UA_DestroyParam + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Db_BufSz = Db_BufSz + 1 ! dt + Int_BufSz = Int_BufSz + 1 ! c allocated yes/no + IF ( ALLOCATED(InData%c) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! c upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%c) ! c + END IF + Int_BufSz = Int_BufSz + 1 ! numBlades + Int_BufSz = Int_BufSz + 1 ! nNodesPerBlade + Int_BufSz = Int_BufSz + 1 ! UAMod + Int_BufSz = Int_BufSz + 1 ! Flookup + Re_BufSz = Re_BufSz + 1 ! a_s + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UnOutFile + Int_BufSz = Int_BufSz + 1 ! ShedEffect + Int_BufSz = Int_BufSz + 1 ! lin_nx + 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 + + DbKiBuf(Db_Xferred) = InData%dt + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%c) ) 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%c,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%c,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%c,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%c,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%c,2), UBOUND(InData%c,2) + DO i1 = LBOUND(InData%c,1), UBOUND(InData%c,1) + ReKiBuf(Re_Xferred) = InData%c(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numBlades + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodesPerBlade + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UAMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Flookup, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%a_s + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ShedEffect, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%lin_nx + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE UA_PackParam + + SUBROUTINE UA_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(UA_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 = 'UA_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%dt = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! c 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%c)) DEALLOCATE(OutData%c) + ALLOCATE(OutData%c(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%c.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%c,2), UBOUND(OutData%c,2) + DO i1 = LBOUND(OutData%c,1), UBOUND(OutData%c,1) + OutData%c(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%numBlades = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNodesPerBlade = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UAMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Flookup = TRANSFER(IntKiBuf(Int_Xferred), OutData%Flookup) + Int_Xferred = Int_Xferred + 1 + OutData%a_s = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ShedEffect = TRANSFER(IntKiBuf(Int_Xferred), OutData%ShedEffect) + Int_Xferred = Int_Xferred + 1 + OutData%lin_nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE UA_UnPackParam + + SUBROUTINE UA_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_InputType), INTENT(IN) :: SrcInputData + TYPE(UA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'UA_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%U = SrcInputData%U + DstInputData%alpha = SrcInputData%alpha + DstInputData%Re = SrcInputData%Re + DstInputData%UserProp = SrcInputData%UserProp + DstInputData%v_ac = SrcInputData%v_ac + DstInputData%omega = SrcInputData%omega + END SUBROUTINE UA_CopyInput + + SUBROUTINE UA_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(UA_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE UA_DestroyInput + + SUBROUTINE UA_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(UA_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 = 'UA_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 + Re_BufSz = Re_BufSz + 1 ! U + Re_BufSz = Re_BufSz + 1 ! alpha + Re_BufSz = Re_BufSz + 1 ! Re + Re_BufSz = Re_BufSz + 1 ! UserProp + Re_BufSz = Re_BufSz + SIZE(InData%v_ac) ! v_ac + Re_BufSz = Re_BufSz + 1 ! omega + 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%U + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Re + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UserProp + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%v_ac,1), UBOUND(InData%v_ac,1) + ReKiBuf(Re_Xferred) = InData%v_ac(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%omega + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_PackInput + + SUBROUTINE UA_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(UA_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'UA_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 + OutData%U = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Re = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UserProp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%v_ac,1) + i1_u = UBOUND(OutData%v_ac,1) + DO i1 = LBOUND(OutData%v_ac,1), UBOUND(OutData%v_ac,1) + OutData%v_ac(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%omega = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE UA_UnPackInput + + SUBROUTINE UA_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UA_OutputType), INTENT(IN) :: SrcOutputData + TYPE(UA_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'UA_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%Cn = SrcOutputData%Cn + DstOutputData%Cc = SrcOutputData%Cc + DstOutputData%Cm = SrcOutputData%Cm + DstOutputData%Cl = SrcOutputData%Cl + DstOutputData%Cd = SrcOutputData%Cd +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE UA_CopyOutput + + SUBROUTINE UA_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(UA_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'UA_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE UA_DestroyOutput + + SUBROUTINE UA_PackOutput( 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(UA_OutputType), 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 = 'UA_PackOutput' + ! 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 ! Cn + Re_BufSz = Re_BufSz + 1 ! Cc + Re_BufSz = Re_BufSz + 1 ! Cm + Re_BufSz = Re_BufSz + 1 ! Cl + Re_BufSz = Re_BufSz + 1 ! Cd + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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%Cn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE UA_PackOutput + + SUBROUTINE UA_UnPackOutput( 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(UA_OutputType), 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 = 'UA_UnPackOutput' + ! 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%Cn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE UA_UnPackOutput + + + SUBROUTINE UA_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(UA_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(UA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL UA_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL UA_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL UA_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE UA_Input_ExtrapInterp + + + SUBROUTINE UA_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(UA_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(UA_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(UA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%U - u2%U) + u_out%U = u1%U + b * ScaleFactor + CALL Angles_ExtrapInterp( u1%alpha, u2%alpha, tin, u_out%alpha, tin_out ) + b = -(u1%Re - u2%Re) + u_out%Re = u1%Re + b * ScaleFactor + b = -(u1%UserProp - u2%UserProp) + u_out%UserProp = u1%UserProp + b * ScaleFactor + DO i1 = LBOUND(u_out%v_ac,1),UBOUND(u_out%v_ac,1) + b = -(u1%v_ac(i1) - u2%v_ac(i1)) + u_out%v_ac(i1) = u1%v_ac(i1) + b * ScaleFactor + END DO + b = -(u1%omega - u2%omega) + u_out%omega = u1%omega + b * ScaleFactor + END SUBROUTINE UA_Input_ExtrapInterp1 + + + SUBROUTINE UA_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(UA_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(UA_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(UA_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(UA_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%U - u2%U) + t(2)**2*(-u1%U + u3%U))* scaleFactor + c = ( (t(2)-t(3))*u1%U + t(3)*u2%U - t(2)*u3%U ) * scaleFactor + u_out%U = u1%U + b + c * t_out + CALL Angles_ExtrapInterp( u1%alpha, u2%alpha, u3%alpha, tin, u_out%alpha, tin_out ) + b = (t(3)**2*(u1%Re - u2%Re) + t(2)**2*(-u1%Re + u3%Re))* scaleFactor + c = ( (t(2)-t(3))*u1%Re + t(3)*u2%Re - t(2)*u3%Re ) * scaleFactor + u_out%Re = u1%Re + b + c * t_out + b = (t(3)**2*(u1%UserProp - u2%UserProp) + t(2)**2*(-u1%UserProp + u3%UserProp))* scaleFactor + c = ( (t(2)-t(3))*u1%UserProp + t(3)*u2%UserProp - t(2)*u3%UserProp ) * scaleFactor + u_out%UserProp = u1%UserProp + b + c * t_out + DO i1 = LBOUND(u_out%v_ac,1),UBOUND(u_out%v_ac,1) + b = (t(3)**2*(u1%v_ac(i1) - u2%v_ac(i1)) + t(2)**2*(-u1%v_ac(i1) + u3%v_ac(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%v_ac(i1) + t(3)*u2%v_ac(i1) - t(2)*u3%v_ac(i1) ) * scaleFactor + u_out%v_ac(i1) = u1%v_ac(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%omega - u2%omega) + t(2)**2*(-u1%omega + u3%omega))* scaleFactor + c = ( (t(2)-t(3))*u1%omega + t(3)*u2%omega - t(2)*u3%omega ) * scaleFactor + u_out%omega = u1%omega + b + c * t_out + END SUBROUTINE UA_Input_ExtrapInterp2 + + + SUBROUTINE UA_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(UA_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(UA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL UA_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL UA_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL UA_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE UA_Output_ExtrapInterp + + + SUBROUTINE UA_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(UA_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(UA_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(UA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(y1%Cn - y2%Cn) + y_out%Cn = y1%Cn + b * ScaleFactor + b = -(y1%Cc - y2%Cc) + y_out%Cc = y1%Cc + b * ScaleFactor + b = -(y1%Cm - y2%Cm) + y_out%Cm = y1%Cm + b * ScaleFactor + b = -(y1%Cl - y2%Cl) + y_out%Cl = y1%Cl + b * ScaleFactor + b = -(y1%Cd - y2%Cd) + y_out%Cd = y1%Cd + b * ScaleFactor +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE UA_Output_ExtrapInterp1 + + + SUBROUTINE UA_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(UA_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(UA_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(UA_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(UA_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'UA_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(y1%Cn - y2%Cn) + t(2)**2*(-y1%Cn + y3%Cn))* scaleFactor + c = ( (t(2)-t(3))*y1%Cn + t(3)*y2%Cn - t(2)*y3%Cn ) * scaleFactor + y_out%Cn = y1%Cn + b + c * t_out + b = (t(3)**2*(y1%Cc - y2%Cc) + t(2)**2*(-y1%Cc + y3%Cc))* scaleFactor + c = ( (t(2)-t(3))*y1%Cc + t(3)*y2%Cc - t(2)*y3%Cc ) * scaleFactor + y_out%Cc = y1%Cc + b + c * t_out + b = (t(3)**2*(y1%Cm - y2%Cm) + t(2)**2*(-y1%Cm + y3%Cm))* scaleFactor + c = ( (t(2)-t(3))*y1%Cm + t(3)*y2%Cm - t(2)*y3%Cm ) * scaleFactor + y_out%Cm = y1%Cm + b + c * t_out + b = (t(3)**2*(y1%Cl - y2%Cl) + t(2)**2*(-y1%Cl + y3%Cl))* scaleFactor + c = ( (t(2)-t(3))*y1%Cl + t(3)*y2%Cl - t(2)*y3%Cl ) * scaleFactor + y_out%Cl = y1%Cl + b + c * t_out + b = (t(3)**2*(y1%Cd - y2%Cd) + t(2)**2*(-y1%Cd + y3%Cd))* scaleFactor + c = ( (t(2)-t(3))*y1%Cd + t(3)*y2%Cd - t(2)*y3%Cd ) * scaleFactor + y_out%Cd = y1%Cd + b + c * t_out +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE UA_Output_ExtrapInterp2 + +END MODULE UnsteadyAero_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn/src/mod_root1dim.f90 b/OpenFAST/modules/aerodyn/src/mod_root1dim.f90 new file mode 100644 index 000000000..8d68f6e57 --- /dev/null +++ b/OpenFAST/modules/aerodyn/src/mod_root1dim.f90 @@ -0,0 +1,235 @@ +! A module for performing one-dimensional root finding via +! +! brent's method (see sub_brent) +! +! Grey Gordon, 2013 +! This code may be reproduced and modified provided it is not sold and the author's +! name and this notice remain intact. +! +! modified by Bonnie Jonkman, Envision Energy, 2016 +! +module mod_root1dim + use NWTC_Library + use AirFoilInfo_Types + use BEMTUnCoupled, only: BEMTU_InductionWithResidual + use BEMT_Types + + implicit none + + integer, parameter, private :: SolveKi = ReKi + real(SolveKi), parameter, private :: xtoler_def = 1d-6, printmod_def = -1 + + +contains + +! Tests whether the two functions values bracket a root -- i.e., have different signs +function bracketsRoot(fa,fb) result(tf) + logical :: tf + real(SolveKi) :: fa,fb + tf = sign(1.0_SolveKi,fb)/=sign(1.0_SolveKi,fa) +end function bracketsRoot + + +! Written using the FORTRAN program zero in "Algorithms for Minimization +! without Derivatives" by Brent. +! +! Description: +! Returns a zero x of the function f in the given interval [a,b], to within a tolerance 6macheps|x| + 2t, +! where macheps is the relative machine precision and t is a positive tolerance. The procedure assumes that +! f(a) and f(b) have different signs. +subroutine sub_brent(bemt_parameters, bemt_inputs, iBladeNode, jBlade, x,a_in,b_in, AFInfo, IsValidSolution, ErrStat, ErrMsg, fa_in,fb_in,xtoler_in,printmod_in) + + implicit none + type(BEMT_ParameterType), intent(in) :: bemt_parameters + type(BEMT_InputType), intent(in) :: bemt_inputs !< Inputs at t + integer(IntKi), intent(in) :: iBladeNode !< index for blade node + integer(IntKi), intent(in) :: jBlade !< index for blade + logical, intent(out):: IsValidSolution + integer(IntKi), intent(out):: errStat ! Error status of the operation + character(ErrMsgLen), intent(out):: errMsg ! Error message if ErrStat /= ErrID_None + + real(ReKi), intent(out) :: x !< solution + real(ReKi), intent(in) :: a_in !< lower bound of solution region + real(ReKi), intent(in) :: b_in !< upper bound of solution region + + TYPE (AFI_ParameterType), INTENT(IN ) :: AFInfo !< The derived type for holding the constant parameters for this airfoil. + real(ReKi), intent(in), optional :: fa_in !< starting value for f(a), if not present, will be evaluated + real(ReKi), intent(in), optional :: fb_in !< starting value for f(b), if not present, will be evaluated + real(ReKi), intent(in), optional :: xtoler_in !< + integer, intent(in), optional :: printmod_in !< print switch; otherwise uses default printmod_deff + + ! local + real(SolveKi), parameter :: machep = epsilon(0.0_SolveKi) + real(SolveKi) :: c,fa,fb,fc,toler,xtoler,e,d,m,p,q,tol,r,s + real(ReKi) :: a,b + integer :: maxiter,printmod,iter + character(len=6) :: step + + integer :: ErrStat_a + character(ErrMsgLen) :: ErrMsg_a + logical :: ValidPhi_a + ! Set of get parameters + toler = bemt_parameters%aTol + maxiter = bemt_parameters%maxIndIterations + + xtoler = xtoler_def; if (present(xtoler_in)) xtoler = xtoler_in + printmod = printmod_def; if (present(printmod_in)) printmod = printmod_in + + ErrStat = ErrID_None + ErrMsg = "" + + ! Set the user chosen tolerance t to xtoler + if (xtoler<0.0_SolveKi) then + CALL WrScr('WARNING: xtoler must be positive. Resetting xtoler.') + xtoler = 0.0_SolveKi + end if + + ! Get initial bracket + a=a_in + b=b_in + if (present(fa_in)) then + fa = fa_in + ErrStat_a = ErrID_None + ErrMsg_a = "" + else + fa = BEMTU_InductionWithResidual(bemt_parameters, bemt_inputs, iBladeNode, jBlade, a, AFInfo, ValidPhi_a, errStat_a, errMsg_a) + end if + if (present(fb_in)) then + fb = fb_in + else + fb = BEMTU_InductionWithResidual(bemt_parameters, bemt_inputs, iBladeNode, jBlade, b, AFInfo, IsValidSolution, errStat, errMsg) + end if + + ! Test whether root is bracketed + if (.not. bracketsRoot(fa,fb)) then + if (abs(fa)<abs(fb)) then + call WrScr( 'brent: WARNING: root is not bracketed, returning best endpoint a = '//trim(Num2Lstr(a))//' fa = '//trim(Num2Lstr(fa)) ) + x = a + IsValidSolution = ValidPhi_a + errStat = ErrStat_a + errMsg = ErrMsg_a + else + call WrScr( 'brent: WARNING: root is not bracketed, returning best endpoint b = '//trim(Num2Lstr(b))//' fb = '//trim(Num2Lstr(fb)) ) + x = b + end if + return + end if + + step = 'init' + + ! At any point in time, b is the best guess of the root, a is the previous value of b, + ! and the root is bracketed by b and c. + do iter = 1,maxiter + + if (iter==1 .or. (fb>0.0_SolveKi .and. fc>0.0_SolveKi) .or. (fb<=0.0_SolveKi .and. fc<=0.0_SolveKi)) then + c = a + fc = fa + e = b - a + d = e + end if + + ! If c is strictly better than b, swap b and c so b is the best guess. + if (abs(fc)<abs(fb)) then + a = b + b = c + c = a + fa = fb + fb = fc + fc = fa + end if + + ! Set the tolerance. Note: brent is very careful with these things, so don't deviate from this. + tol = 2.0_SolveKi*machep*abs(b) + xtoler + + ! Determine what half the length of the bracket [b,c] is + m = 0.5_SolveKi*(c-b) + + ! If taking a bisection step would move the guess of the root less than tol, then return b the best guess. + if ((abs(m)<=tol) .or. (fb==0.0_SolveKi)) then + x = b + return + end if + + ! Display info + if (printmod>0 .and. mod(iter,printmod)==0) write(*,"(A,i5,A,e13.5,A,e13.5,A,A)") & + 'brent: iter ',iter,' b',b,' fb',fb,' ',step + + ! If still here, then check whether need to do bisection or can do interpolation + if ((abs(e)>=tol) .and. (abs(fa)>abs(fb))) then + s = fb/fa + if (a/=c) then + ! Inverse quadratic interpolation + q = fa/fc + r = fb/fc + p = s*(2.0_SolveKi*m*q*(q-r) - (b-a)*(r-1.0_SolveKi)) + q = (q-1.0_SolveKi)*(r-1.0_SolveKi)*(s-1.0_SolveKi) + + step = 'quad' + else + ! Linear interpolation + p = 2.0_SolveKi*m*s + q = 1.0_SolveKi-s + + step = 'linear' + end if + + ! Ensure p is positive + if (p<=0.0_SolveKi) then + p = -p + else + q = -q + end if + + s = e + e = d + if ((2.0_SolveKi*p>=3.0_SolveKi*m*q-abs(tol*q)) .or. & + (p>=abs(0.5_SolveKi*s*q))) then + ! Interpolation step failed to produce good step, bisect instead + e = m + d = m ! m is half the distance between b and c + step = 'bisect' + else + ! Do interpolation step (either quadratic or linear) + d = p/q + end if + else + + ! Do bisection step + e = m + d = m + + end if + + ! Get new points. + !! Replace a (the old b) with b. + a = b + fa = fb + + !!! Increment b by d if that is greater than the tolerance. O/w, increment by tol. + if (abs(d)<=tol) then + ! m is .5*(c-b) with the bracket either [b,c] or [c,b]. + if (m > 0.0_SolveKi) then + ! If m>0d0, then bracket is [b,c] so move towards c by tol + b = b + tol + else + ! If m<=0d0, then bracket is [c,b] so move towards c by tol + b = b - tol + end if + else + b = b + d + end if + + !!! Evaluate at the new point + fb = BEMTU_InductionWithResidual(bemt_parameters, bemt_inputs, iBladeNode, jBlade, b, AFInfo, IsValidSolution, errStat, errMsg) + + ! Check my custom tolerance + if (abs(fb)<toler) then + x = b + return + end if + + end do + +end subroutine sub_brent + +end module mod_root1dim diff --git a/OpenFAST/modules/aerodyn/tests/test_FVW_testsuite.F90 b/OpenFAST/modules/aerodyn/tests/test_FVW_testsuite.F90 new file mode 100644 index 000000000..57a72ea24 --- /dev/null +++ b/OpenFAST/modules/aerodyn/tests/test_FVW_testsuite.F90 @@ -0,0 +1,48 @@ +@test +subroutine test_AD_FVW() + ! test branches + ! - known valid checks for various FVW routines (contained in own module) + ! - known invalid rotation matrix: halve the angle of the diagonal elements + + use pFUnit_mod + use NWTC_Num + use FVW_Tests + + implicit none + + integer(IntKi) :: ErrStat + character(ErrMsgLen) :: ErrMsg + character(1024) :: testname + + ! initialize NWTC_Num constants + call SetConstants() + +!This is a single routine that contains the test cases below. + ! -------------------------------------------------------------------------- + testname = "Set of FVW tests" + call FVW_RunTests( ErrStat, ErrMsg ) + @assertEqual(0, ErrStat, testname) + + +! test routines from FVW_RunTests to be run individually -- except these are all private +! ! -------------------------------------------------------------------------- +! testname = "known valid Biot-Savart segment" +! call Test_BiotSavart_Sgmt(testname, ErrStat, ErrMsg) +! @assertEqual(0, ErrStat, testname) +! +! ! -------------------------------------------------------------------------- +! testname = "known valid Biot-Savart part" +! call Test_BiotSavart_Part(testname, ErrStat, ErrMsg) +! @assertEqual(0, ErrStat, testname) +! +! ! -------------------------------------------------------------------------- +! testname = "known valid Biot-Savart to part-tree" +! call Test_BiotSavart_PartTree(testname, ErrStat, ErrMsg) +! @assertEqual(0, ErrStat, testname) +! +! ! -------------------------------------------------------------------------- +! testname = "known valid segment split to parts" +! call Test_SegmentsToPart(testname, ErrStat, ErrMsg) +! @assertEqual(0, ErrStat, testname) + +end subroutine test_AD_FVW diff --git a/OpenFAST/modules/aerodyn14/CMakeLists.txt b/OpenFAST/modules/aerodyn14/CMakeLists.txt new file mode 100644 index 000000000..be1846cc9 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/Registry-AD14.txt ${CMAKE_CURRENT_LIST_DIR}/src/AeroDyn14_Types.f90) + generate_f90_types(src/Registry-DWM.txt ${CMAKE_CURRENT_LIST_DIR}/src/DWM_Types.f90) +endif() + +set(AD14_LIBS_SOURCES + src/AeroDyn14.f90 + src/AeroSubs.f90 + src/DWM.f90 + src/DWM_Wake_Sub_ver2.f90 + src/GenSubs.f90 + src/AeroDyn14_Types.f90 + src/DWM_Types.f90 +) + +add_library(aerodyn14lib ${AD14_LIBS_SOURCES}) +target_link_libraries(aerodyn14lib ifwlib nwtclibs) + +install(TARGETS aerodyn14lib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + +set(DWM_SOURCES + src/DWM_driver_wind_farm_mod.f90 + src/DWM_driver_wind_farm_sub.f90 + src/DWM_driver_wind_farm.f90 +) + +add_executable(dwm_driver_wind_farm ${DWM_SOURCES}) +target_link_libraries(dwm_driver_wind_farm aerodyn14lib) + +install(TARGETS dwm_driver_wind_farm + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/aerodyn14/README.md b/OpenFAST/modules/aerodyn14/README.md new file mode 100644 index 000000000..eb6b85684 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/README.md @@ -0,0 +1,14 @@ +# AeroDyn 14 Module +The legacy version of this module and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/AeroDyn14/). + +**DEPRECATED** +AeroDyn 14 will be replaced with DBEMT and FAST.Farm as discussed in +[issue #93](https://github.com/OpenFAST/openfast/issues/93). + +## Overview +AeroDyn 14 is an aerodynamics software library (module) for use by designers of +horizontal-axis wind turbines. It is written to be interfaced with a dynamics +analysis software package for aero-elastic analysis of wind turbine models. +This version of AeroDyn works only with the modularization framework used in +OpenFAST. diff --git a/OpenFAST/modules/aerodyn14/src/AD14AeroConf_Types.f90 b/OpenFAST/modules/aerodyn14/src/AD14AeroConf_Types.f90 new file mode 100644 index 000000000..91c5a3736 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/AD14AeroConf_Types.f90 @@ -0,0 +1,2921 @@ +!STARTOFREGISTRYGENERATEDFILE 'AD14AeroConf_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 +!********************************************************************************************************************************* +! AD14AeroConf_Types +!................................................................................................................................. +! This file is part of AD14AeroConf. +! +! 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 AD14AeroConf. 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 AD14AeroConf_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Marker ======= + TYPE, PUBLIC :: Marker + REAL(ReKi) , DIMENSION(1:3) :: Position + REAL(ReKi) , DIMENSION(1:3,1:3) :: Orientation + REAL(ReKi) , DIMENSION(1:3) :: TranslationVel + REAL(ReKi) , DIMENSION(1:3) :: RotationVel + END TYPE Marker +! ======================= +! ========= AD14AeroConf_MiscVarType ======= + TYPE, PUBLIC :: AD14AeroConf_MiscVarType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AL + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CD + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CL + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CM + REAL(ReKi) :: PMC + REAL(ReKi) :: MulTabLoc + END TYPE AD14AeroConf_MiscVarType +! ======================= +! ========= AD14AeroConf_ParameterType ======= + TYPE, PUBLIC :: AD14AeroConf_ParameterType + INTEGER(IntKi) :: MaxTable = 20 + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NTables + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NLift + INTEGER(IntKi) :: NumCL + INTEGER(IntKi) :: NumFoil + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NFoil + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MulTabMet + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: FoilNm + END TYPE AD14AeroConf_ParameterType +! ======================= +! ========= AD14AeroConf_InputType ======= + TYPE, PUBLIC :: AD14AeroConf_InputType + TYPE(Marker) , DIMENSION(:), ALLOCATABLE :: Blade + TYPE(Marker) :: Hub + TYPE(Marker) :: RotorFurl + TYPE(Marker) :: Nacelle + TYPE(Marker) :: TailFin + TYPE(Marker) :: Tower + TYPE(Marker) :: SubStructure + TYPE(Marker) :: Foundation + REAL(ReKi) :: BladeLength + END TYPE AD14AeroConf_InputType +! ======================= +! ========= AD14AeroConf_OutputType ======= + TYPE, PUBLIC :: AD14AeroConf_OutputType + REAL(ReKi) :: Dummy + END TYPE AD14AeroConf_OutputType +! ======================= +CONTAINS + SUBROUTINE AD14AeroConf_CopyMarker( SrcMarkerData, DstMarkerData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Marker), INTENT(IN) :: SrcMarkerData + TYPE(Marker), INTENT(INOUT) :: DstMarkerData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_CopyMarker' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMarkerData%Position = SrcMarkerData%Position + DstMarkerData%Orientation = SrcMarkerData%Orientation + DstMarkerData%TranslationVel = SrcMarkerData%TranslationVel + DstMarkerData%RotationVel = SrcMarkerData%RotationVel + END SUBROUTINE AD14AeroConf_CopyMarker + + SUBROUTINE AD14AeroConf_DestroyMarker( MarkerData, ErrStat, ErrMsg ) + TYPE(Marker), INTENT(INOUT) :: MarkerData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_DestroyMarker' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14AeroConf_DestroyMarker + + SUBROUTINE AD14AeroConf_PackMarker( 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(Marker), 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 = 'AD14AeroConf_PackMarker' + ! 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%Position) ! Position + Re_BufSz = Re_BufSz + SIZE(InData%Orientation) ! Orientation + Re_BufSz = Re_BufSz + SIZE(InData%TranslationVel) ! TranslationVel + Re_BufSz = Re_BufSz + SIZE(InData%RotationVel) ! RotationVel + 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:Re_Xferred+(SIZE(InData%Position))-1 ) = PACK(InData%Position,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Position) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Orientation))-1 ) = PACK(InData%Orientation,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Orientation) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TranslationVel))-1 ) = PACK(InData%TranslationVel,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%TranslationVel) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RotationVel))-1 ) = PACK(InData%RotationVel,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%RotationVel) + END SUBROUTINE AD14AeroConf_PackMarker + + SUBROUTINE AD14AeroConf_UnPackMarker( 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(Marker), 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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_UnPackMarker' + ! 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%Position,1) + i1_u = UBOUND(OutData%Position,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%Position = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Position))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Position) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%Orientation,1) + i1_u = UBOUND(OutData%Orientation,1) + i2_l = LBOUND(OutData%Orientation,2) + i2_u = UBOUND(OutData%Orientation,2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + OutData%Orientation = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Orientation))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Orientation) + DEALLOCATE(mask2) + i1_l = LBOUND(OutData%TranslationVel,1) + i1_u = UBOUND(OutData%TranslationVel,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%TranslationVel = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TranslationVel))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%TranslationVel) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%RotationVel,1) + i1_u = UBOUND(OutData%RotationVel,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%RotationVel = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RotationVel))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%RotationVel) + DEALLOCATE(mask1) + END SUBROUTINE AD14AeroConf_UnPackMarker + + SUBROUTINE AD14AeroConf_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(AD14AeroConf_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%AL)) THEN + i1_l = LBOUND(SrcMiscData%AL,1) + i1_u = UBOUND(SrcMiscData%AL,1) + i2_l = LBOUND(SrcMiscData%AL,2) + i2_u = UBOUND(SrcMiscData%AL,2) + IF (.NOT. ALLOCATED(DstMiscData%AL)) THEN + ALLOCATE(DstMiscData%AL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AL = SrcMiscData%AL +ENDIF +IF (ALLOCATED(SrcMiscData%CD)) THEN + i1_l = LBOUND(SrcMiscData%CD,1) + i1_u = UBOUND(SrcMiscData%CD,1) + i2_l = LBOUND(SrcMiscData%CD,2) + i2_u = UBOUND(SrcMiscData%CD,2) + i3_l = LBOUND(SrcMiscData%CD,3) + i3_u = UBOUND(SrcMiscData%CD,3) + IF (.NOT. ALLOCATED(DstMiscData%CD)) THEN + ALLOCATE(DstMiscData%CD(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CD = SrcMiscData%CD +ENDIF +IF (ALLOCATED(SrcMiscData%CL)) THEN + i1_l = LBOUND(SrcMiscData%CL,1) + i1_u = UBOUND(SrcMiscData%CL,1) + i2_l = LBOUND(SrcMiscData%CL,2) + i2_u = UBOUND(SrcMiscData%CL,2) + i3_l = LBOUND(SrcMiscData%CL,3) + i3_u = UBOUND(SrcMiscData%CL,3) + IF (.NOT. ALLOCATED(DstMiscData%CL)) THEN + ALLOCATE(DstMiscData%CL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CL = SrcMiscData%CL +ENDIF +IF (ALLOCATED(SrcMiscData%CM)) THEN + i1_l = LBOUND(SrcMiscData%CM,1) + i1_u = UBOUND(SrcMiscData%CM,1) + i2_l = LBOUND(SrcMiscData%CM,2) + i2_u = UBOUND(SrcMiscData%CM,2) + i3_l = LBOUND(SrcMiscData%CM,3) + i3_u = UBOUND(SrcMiscData%CM,3) + IF (.NOT. ALLOCATED(DstMiscData%CM)) THEN + ALLOCATE(DstMiscData%CM(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%CM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%CM = SrcMiscData%CM +ENDIF + DstMiscData%PMC = SrcMiscData%PMC + DstMiscData%MulTabLoc = SrcMiscData%MulTabLoc + END SUBROUTINE AD14AeroConf_CopyMisc + + SUBROUTINE AD14AeroConf_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%AL)) THEN + DEALLOCATE(MiscData%AL) +ENDIF +IF (ALLOCATED(MiscData%CD)) THEN + DEALLOCATE(MiscData%CD) +ENDIF +IF (ALLOCATED(MiscData%CL)) THEN + DEALLOCATE(MiscData%CL) +ENDIF +IF (ALLOCATED(MiscData%CM)) THEN + DEALLOCATE(MiscData%CM) +ENDIF + END SUBROUTINE AD14AeroConf_DestroyMisc + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 = 'AD14AeroConf_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 ! AL allocated yes/no + IF ( ALLOCATED(InData%AL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AL) ! AL + END IF + Int_BufSz = Int_BufSz + 1 ! CD allocated yes/no + IF ( ALLOCATED(InData%CD) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CD) ! CD + END IF + Int_BufSz = Int_BufSz + 1 ! CL allocated yes/no + IF ( ALLOCATED(InData%CL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CL) ! CL + END IF + Int_BufSz = Int_BufSz + 1 ! CM allocated yes/no + IF ( ALLOCATED(InData%CM) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CM) ! CM + END IF + Re_BufSz = Re_BufSz + 1 ! PMC + Re_BufSz = Re_BufSz + 1 ! MulTabLoc + 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%AL) ) 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%AL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AL,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AL))-1 ) = PACK(InData%AL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AL) + END IF + IF ( .NOT. ALLOCATED(InData%CD) ) 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%CD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CD,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CD)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CD))-1 ) = PACK(InData%CD,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CD) + END IF + IF ( .NOT. ALLOCATED(InData%CL) ) 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%CL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CL))-1 ) = PACK(InData%CL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CL) + END IF + IF ( .NOT. ALLOCATED(InData%CM) ) 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%CM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CM))-1 ) = PACK(InData%CM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CM) + END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%PMC + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MulTabLoc + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_PackMisc + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_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 ! AL 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%AL)) DEALLOCATE(OutData%AL) + ALLOCATE(OutData%AL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%AL)>0) OutData%AL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AL))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AL) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CD 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%CD)) DEALLOCATE(OutData%CD) + ALLOCATE(OutData%CD(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%CD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%CD)>0) OutData%CD = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CD))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CD) + DEALLOCATE(mask3) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CL 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%CL)) DEALLOCATE(OutData%CL) + ALLOCATE(OutData%CL(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%CL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%CL)>0) OutData%CL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CL))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CL) + DEALLOCATE(mask3) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CM 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%CM)) DEALLOCATE(OutData%CM) + ALLOCATE(OutData%CM(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%CM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%CM)>0) OutData%CM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CM))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CM) + DEALLOCATE(mask3) + END IF + OutData%PMC = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%MulTabLoc = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_UnPackMisc + + SUBROUTINE AD14AeroConf_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_ParameterType), INTENT(IN) :: SrcParamData + TYPE(AD14AeroConf_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%MaxTable = SrcParamData%MaxTable +IF (ALLOCATED(SrcParamData%NTables)) THEN + i1_l = LBOUND(SrcParamData%NTables,1) + i1_u = UBOUND(SrcParamData%NTables,1) + IF (.NOT. ALLOCATED(DstParamData%NTables)) THEN + ALLOCATE(DstParamData%NTables(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NTables.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NTables = SrcParamData%NTables +ENDIF +IF (ALLOCATED(SrcParamData%NLift)) THEN + i1_l = LBOUND(SrcParamData%NLift,1) + i1_u = UBOUND(SrcParamData%NLift,1) + IF (.NOT. ALLOCATED(DstParamData%NLift)) THEN + ALLOCATE(DstParamData%NLift(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NLift.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NLift = SrcParamData%NLift +ENDIF + DstParamData%NumCL = SrcParamData%NumCL + DstParamData%NumFoil = SrcParamData%NumFoil +IF (ALLOCATED(SrcParamData%NFoil)) THEN + i1_l = LBOUND(SrcParamData%NFoil,1) + i1_u = UBOUND(SrcParamData%NFoil,1) + IF (.NOT. ALLOCATED(DstParamData%NFoil)) THEN + ALLOCATE(DstParamData%NFoil(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NFoil.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NFoil = SrcParamData%NFoil +ENDIF +IF (ALLOCATED(SrcParamData%MulTabMet)) THEN + i1_l = LBOUND(SrcParamData%MulTabMet,1) + i1_u = UBOUND(SrcParamData%MulTabMet,1) + i2_l = LBOUND(SrcParamData%MulTabMet,2) + i2_u = UBOUND(SrcParamData%MulTabMet,2) + IF (.NOT. ALLOCATED(DstParamData%MulTabMet)) THEN + ALLOCATE(DstParamData%MulTabMet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MulTabMet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MulTabMet = SrcParamData%MulTabMet +ENDIF +IF (ALLOCATED(SrcParamData%FoilNm)) THEN + i1_l = LBOUND(SrcParamData%FoilNm,1) + i1_u = UBOUND(SrcParamData%FoilNm,1) + IF (.NOT. ALLOCATED(DstParamData%FoilNm)) THEN + ALLOCATE(DstParamData%FoilNm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FoilNm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FoilNm = SrcParamData%FoilNm +ENDIF + END SUBROUTINE AD14AeroConf_CopyParam + + SUBROUTINE AD14AeroConf_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%NTables)) THEN + DEALLOCATE(ParamData%NTables) +ENDIF +IF (ALLOCATED(ParamData%NLift)) THEN + DEALLOCATE(ParamData%NLift) +ENDIF +IF (ALLOCATED(ParamData%NFoil)) THEN + DEALLOCATE(ParamData%NFoil) +ENDIF +IF (ALLOCATED(ParamData%MulTabMet)) THEN + DEALLOCATE(ParamData%MulTabMet) +ENDIF +IF (ALLOCATED(ParamData%FoilNm)) THEN + DEALLOCATE(ParamData%FoilNm) +ENDIF + END SUBROUTINE AD14AeroConf_DestroyParam + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 = 'AD14AeroConf_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 ! MaxTable + Int_BufSz = Int_BufSz + 1 ! NTables allocated yes/no + IF ( ALLOCATED(InData%NTables) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NTables upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NTables) ! NTables + END IF + Int_BufSz = Int_BufSz + 1 ! NLift allocated yes/no + IF ( ALLOCATED(InData%NLift) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NLift upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NLift) ! NLift + END IF + Int_BufSz = Int_BufSz + 1 ! NumCL + Int_BufSz = Int_BufSz + 1 ! NumFoil + Int_BufSz = Int_BufSz + 1 ! NFoil allocated yes/no + IF ( ALLOCATED(InData%NFoil) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NFoil upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NFoil) ! NFoil + END IF + Int_BufSz = Int_BufSz + 1 ! MulTabMet allocated yes/no + IF ( ALLOCATED(InData%MulTabMet) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MulTabMet upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MulTabMet) ! MulTabMet + END IF + Int_BufSz = Int_BufSz + 1 ! FoilNm allocated yes/no + IF ( ALLOCATED(InData%FoilNm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FoilNm upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FoilNm)*LEN(InData%FoilNm) ! FoilNm + 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:Int_Xferred+(1)-1 ) = InData%MaxTable + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NTables) ) 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%NTables,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NTables,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NTables)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NTables))-1 ) = PACK(InData%NTables,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NTables) + END IF + IF ( .NOT. ALLOCATED(InData%NLift) ) 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%NLift,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NLift,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NLift)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NLift))-1 ) = PACK(InData%NLift,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NLift) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumCL + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumFoil + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NFoil) ) 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%NFoil,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NFoil,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NFoil)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NFoil))-1 ) = PACK(InData%NFoil,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NFoil) + END IF + IF ( .NOT. ALLOCATED(InData%MulTabMet) ) 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%MulTabMet,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabMet,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MulTabMet,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabMet,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MulTabMet)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MulTabMet))-1 ) = PACK(InData%MulTabMet,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MulTabMet) + END IF + IF ( .NOT. ALLOCATED(InData%FoilNm) ) 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%FoilNm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FoilNm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FoilNm,1), UBOUND(InData%FoilNm,1) + DO I = 1, LEN(InData%FoilNm) + IntKiBuf(Int_Xferred) = ICHAR(InData%FoilNm(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + END SUBROUTINE AD14AeroConf_PackParam + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + 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 = 'AD14AeroConf_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%MaxTable = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NTables 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%NTables)) DEALLOCATE(OutData%NTables) + ALLOCATE(OutData%NTables(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NTables.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NTables)>0) OutData%NTables = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NTables))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NTables) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NLift 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%NLift)) DEALLOCATE(OutData%NLift) + ALLOCATE(OutData%NLift(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NLift.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NLift)>0) OutData%NLift = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NLift))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NLift) + DEALLOCATE(mask1) + END IF + OutData%NumCL = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NumFoil = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NFoil 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%NFoil)) DEALLOCATE(OutData%NFoil) + ALLOCATE(OutData%NFoil(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NFoil.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NFoil)>0) OutData%NFoil = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NFoil))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NFoil) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MulTabMet 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%MulTabMet)) DEALLOCATE(OutData%MulTabMet) + ALLOCATE(OutData%MulTabMet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MulTabMet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MulTabMet)>0) OutData%MulTabMet = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MulTabMet))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MulTabMet) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FoilNm 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%FoilNm)) DEALLOCATE(OutData%FoilNm) + ALLOCATE(OutData%FoilNm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FoilNm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%FoilNm,1), UBOUND(OutData%FoilNm,1) + DO I = 1, LEN(OutData%FoilNm) + OutData%FoilNm(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + END SUBROUTINE AD14AeroConf_UnPackParam + + SUBROUTINE AD14AeroConf_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_InputType), INTENT(IN) :: SrcInputData + TYPE(AD14AeroConf_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%Blade)) THEN + i1_l = LBOUND(SrcInputData%Blade,1) + i1_u = UBOUND(SrcInputData%Blade,1) + IF (.NOT. ALLOCATED(DstInputData%Blade)) THEN + ALLOCATE(DstInputData%Blade(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Blade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%Blade,1), UBOUND(SrcInputData%Blade,1) + CALL AD14AeroConf_Copymarker( SrcInputData%Blade(i1), DstInputData%Blade(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL AD14AeroConf_Copymarker( SrcInputData%Hub, DstInputData%Hub, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%RotorFurl, DstInputData%RotorFurl, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%Nacelle, DstInputData%Nacelle, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%TailFin, DstInputData%TailFin, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%Tower, DstInputData%Tower, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%SubStructure, DstInputData%SubStructure, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14AeroConf_Copymarker( SrcInputData%Foundation, DstInputData%Foundation, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInputData%BladeLength = SrcInputData%BladeLength + END SUBROUTINE AD14AeroConf_CopyInput + + SUBROUTINE AD14AeroConf_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%Blade)) THEN +DO i1 = LBOUND(InputData%Blade,1), UBOUND(InputData%Blade,1) + CALL AD14AeroConf_Destroymarker( InputData%Blade(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%Blade) +ENDIF + CALL AD14AeroConf_Destroymarker( InputData%Hub, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%RotorFurl, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%Nacelle, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%TailFin, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%Tower, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%SubStructure, ErrStat, ErrMsg ) + CALL AD14AeroConf_Destroymarker( InputData%Foundation, ErrStat, ErrMsg ) + END SUBROUTINE AD14AeroConf_DestroyInput + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 = 'AD14AeroConf_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 ! Blade allocated yes/no + IF ( ALLOCATED(InData%Blade) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Blade upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Blade,1), UBOUND(InData%Blade,1) + Int_BufSz = Int_BufSz + 3 ! Blade: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Blade(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Blade + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Blade + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Blade + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Blade + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! Hub: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Hub, ErrStat2, ErrMsg2, .TRUE. ) ! Hub + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Hub + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Hub + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Hub + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! RotorFurl: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%RotorFurl, ErrStat2, ErrMsg2, .TRUE. ) ! RotorFurl + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RotorFurl + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RotorFurl + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RotorFurl + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Nacelle: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Nacelle, ErrStat2, ErrMsg2, .TRUE. ) ! Nacelle + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Nacelle + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Nacelle + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Nacelle + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TailFin: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%TailFin, ErrStat2, ErrMsg2, .TRUE. ) ! TailFin + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TailFin + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TailFin + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TailFin + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Tower: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Tower, ErrStat2, ErrMsg2, .TRUE. ) ! Tower + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Tower + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Tower + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Tower + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SubStructure: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%SubStructure, ErrStat2, ErrMsg2, .TRUE. ) ! SubStructure + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SubStructure + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SubStructure + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SubStructure + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Foundation: size of buffers for each call to pack subtype + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Foundation, ErrStat2, ErrMsg2, .TRUE. ) ! Foundation + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Foundation + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Foundation + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Foundation + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! BladeLength + 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%Blade) ) 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%Blade,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Blade,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Blade,1), UBOUND(InData%Blade,1) + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Blade(i1), ErrStat2, ErrMsg2, OnlySize ) ! Blade + 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 + CALL AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Hub, ErrStat2, ErrMsg2, OnlySize ) ! Hub + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%RotorFurl, ErrStat2, ErrMsg2, OnlySize ) ! RotorFurl + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Nacelle, ErrStat2, ErrMsg2, OnlySize ) ! Nacelle + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%TailFin, ErrStat2, ErrMsg2, OnlySize ) ! TailFin + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Tower, ErrStat2, ErrMsg2, OnlySize ) ! Tower + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%SubStructure, ErrStat2, ErrMsg2, OnlySize ) ! SubStructure + 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 AD14AeroConf_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Foundation, ErrStat2, ErrMsg2, OnlySize ) ! Foundation + 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 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_PackInput + + SUBROUTINE AD14AeroConf_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(AD14AeroConf_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_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 ! Blade 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%Blade)) DEALLOCATE(OutData%Blade) + ALLOCATE(OutData%Blade(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Blade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Blade,1), UBOUND(OutData%Blade,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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Blade(i1), ErrStat2, ErrMsg2 ) ! Blade + 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 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Hub, ErrStat2, ErrMsg2 ) ! Hub + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%RotorFurl, ErrStat2, ErrMsg2 ) ! RotorFurl + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Nacelle, ErrStat2, ErrMsg2 ) ! Nacelle + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%TailFin, ErrStat2, ErrMsg2 ) ! TailFin + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Tower, ErrStat2, ErrMsg2 ) ! Tower + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%SubStructure, ErrStat2, ErrMsg2 ) ! SubStructure + 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 AD14AeroConf_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Foundation, ErrStat2, ErrMsg2 ) ! Foundation + 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%BladeLength = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_UnPackInput + + SUBROUTINE AD14AeroConf_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: SrcOutputData + TYPE(AD14AeroConf_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'AD14AeroConf_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%Dummy = SrcOutputData%Dummy + END SUBROUTINE AD14AeroConf_CopyOutput + + SUBROUTINE AD14AeroConf_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(AD14AeroConf_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14AeroConf_DestroyOutput + + SUBROUTINE AD14AeroConf_PackOutput( 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(AD14AeroConf_OutputType), 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 = 'AD14AeroConf_PackOutput' + ! 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:Re_Xferred+(1)-1 ) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_PackOutput + + SUBROUTINE AD14AeroConf_UnPackOutput( 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(AD14AeroConf_OutputType), 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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_UnPackOutput' + ! 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 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14AeroConf_UnPackOutput + + + SUBROUTINE AD14AeroConf_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(AD14AeroConf_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL AD14AeroConf_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD14AeroConf_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD14AeroConf_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD14AeroConf_Input_ExtrapInterp + + + SUBROUTINE AD14AeroConf_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(AD14AeroConf_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Input_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: b2 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: c2 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF +IF (ALLOCATED(u_out%Blade) .AND. ALLOCATED(u1%Blade)) THEN + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%Position,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%Position,1))) + b1 = -(u1%Blade(i01)%Position - u2%Blade(i01)%Position)/t(2) + u_out%Blade(i01)%Position = u1%Blade(i01)%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b2(SIZE(u_out%Blade(i01)%Orientation,1),SIZE(u_out%Blade(i01)%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Blade(i01)%Orientation,1),SIZE(u_out%Blade(i01)%Orientation,2) )) + b2 = -(u1%Blade(i01)%Orientation - u2%Blade(i01)%Orientation)/t(2) + u_out%Blade(i01)%Orientation = u1%Blade(i01)%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%TranslationVel,1))) + b1 = -(u1%Blade(i01)%TranslationVel - u2%Blade(i01)%TranslationVel)/t(2) + u_out%Blade(i01)%TranslationVel = u1%Blade(i01)%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%RotationVel,1))) + b1 = -(u1%Blade(i01)%RotationVel - u2%Blade(i01)%RotationVel)/t(2) + u_out%Blade(i01)%RotationVel = u1%Blade(i01)%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO +END IF ! check if allocated + ALLOCATE(b1(SIZE(u_out%Hub%Position,1))) + ALLOCATE(c1(SIZE(u_out%Hub%Position,1))) + b1 = -(u1%Hub%Position - u2%Hub%Position)/t(2) + u_out%Hub%Position = u1%Hub%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Hub%Orientation,1),SIZE(u_out%Hub%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Hub%Orientation,1),SIZE(u_out%Hub%Orientation,2) )) + b2 = -(u1%Hub%Orientation - u2%Hub%Orientation)/t(2) + u_out%Hub%Orientation = u1%Hub%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Hub%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Hub%TranslationVel,1))) + b1 = -(u1%Hub%TranslationVel - u2%Hub%TranslationVel)/t(2) + u_out%Hub%TranslationVel = u1%Hub%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Hub%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Hub%RotationVel,1))) + b1 = -(u1%Hub%RotationVel - u2%Hub%RotationVel)/t(2) + u_out%Hub%RotationVel = u1%Hub%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%RotorFurl%Position,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%Position,1))) + b1 = -(u1%RotorFurl%Position - u2%RotorFurl%Position)/t(2) + u_out%RotorFurl%Position = u1%RotorFurl%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%RotorFurl%Orientation,1),SIZE(u_out%RotorFurl%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%RotorFurl%Orientation,1),SIZE(u_out%RotorFurl%Orientation,2) )) + b2 = -(u1%RotorFurl%Orientation - u2%RotorFurl%Orientation)/t(2) + u_out%RotorFurl%Orientation = u1%RotorFurl%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%RotorFurl%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%TranslationVel,1))) + b1 = -(u1%RotorFurl%TranslationVel - u2%RotorFurl%TranslationVel)/t(2) + u_out%RotorFurl%TranslationVel = u1%RotorFurl%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%RotorFurl%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%RotationVel,1))) + b1 = -(u1%RotorFurl%RotationVel - u2%RotorFurl%RotationVel)/t(2) + u_out%RotorFurl%RotationVel = u1%RotorFurl%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Nacelle%Position,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%Position,1))) + b1 = -(u1%Nacelle%Position - u2%Nacelle%Position)/t(2) + u_out%Nacelle%Position = u1%Nacelle%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Nacelle%Orientation,1),SIZE(u_out%Nacelle%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Nacelle%Orientation,1),SIZE(u_out%Nacelle%Orientation,2) )) + b2 = -(u1%Nacelle%Orientation - u2%Nacelle%Orientation)/t(2) + u_out%Nacelle%Orientation = u1%Nacelle%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Nacelle%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%TranslationVel,1))) + b1 = -(u1%Nacelle%TranslationVel - u2%Nacelle%TranslationVel)/t(2) + u_out%Nacelle%TranslationVel = u1%Nacelle%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Nacelle%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%RotationVel,1))) + b1 = -(u1%Nacelle%RotationVel - u2%Nacelle%RotationVel)/t(2) + u_out%Nacelle%RotationVel = u1%Nacelle%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%TailFin%Position,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%Position,1))) + b1 = -(u1%TailFin%Position - u2%TailFin%Position)/t(2) + u_out%TailFin%Position = u1%TailFin%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%TailFin%Orientation,1),SIZE(u_out%TailFin%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%TailFin%Orientation,1),SIZE(u_out%TailFin%Orientation,2) )) + b2 = -(u1%TailFin%Orientation - u2%TailFin%Orientation)/t(2) + u_out%TailFin%Orientation = u1%TailFin%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%TailFin%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%TranslationVel,1))) + b1 = -(u1%TailFin%TranslationVel - u2%TailFin%TranslationVel)/t(2) + u_out%TailFin%TranslationVel = u1%TailFin%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%TailFin%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%RotationVel,1))) + b1 = -(u1%TailFin%RotationVel - u2%TailFin%RotationVel)/t(2) + u_out%TailFin%RotationVel = u1%TailFin%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Tower%Position,1))) + ALLOCATE(c1(SIZE(u_out%Tower%Position,1))) + b1 = -(u1%Tower%Position - u2%Tower%Position)/t(2) + u_out%Tower%Position = u1%Tower%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Tower%Orientation,1),SIZE(u_out%Tower%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Tower%Orientation,1),SIZE(u_out%Tower%Orientation,2) )) + b2 = -(u1%Tower%Orientation - u2%Tower%Orientation)/t(2) + u_out%Tower%Orientation = u1%Tower%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Tower%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Tower%TranslationVel,1))) + b1 = -(u1%Tower%TranslationVel - u2%Tower%TranslationVel)/t(2) + u_out%Tower%TranslationVel = u1%Tower%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Tower%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Tower%RotationVel,1))) + b1 = -(u1%Tower%RotationVel - u2%Tower%RotationVel)/t(2) + u_out%Tower%RotationVel = u1%Tower%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%SubStructure%Position,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%Position,1))) + b1 = -(u1%SubStructure%Position - u2%SubStructure%Position)/t(2) + u_out%SubStructure%Position = u1%SubStructure%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%SubStructure%Orientation,1),SIZE(u_out%SubStructure%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%SubStructure%Orientation,1),SIZE(u_out%SubStructure%Orientation,2) )) + b2 = -(u1%SubStructure%Orientation - u2%SubStructure%Orientation)/t(2) + u_out%SubStructure%Orientation = u1%SubStructure%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%SubStructure%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%TranslationVel,1))) + b1 = -(u1%SubStructure%TranslationVel - u2%SubStructure%TranslationVel)/t(2) + u_out%SubStructure%TranslationVel = u1%SubStructure%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%SubStructure%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%RotationVel,1))) + b1 = -(u1%SubStructure%RotationVel - u2%SubStructure%RotationVel)/t(2) + u_out%SubStructure%RotationVel = u1%SubStructure%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Foundation%Position,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%Position,1))) + b1 = -(u1%Foundation%Position - u2%Foundation%Position)/t(2) + u_out%Foundation%Position = u1%Foundation%Position + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Foundation%Orientation,1),SIZE(u_out%Foundation%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Foundation%Orientation,1),SIZE(u_out%Foundation%Orientation,2) )) + b2 = -(u1%Foundation%Orientation - u2%Foundation%Orientation)/t(2) + u_out%Foundation%Orientation = u1%Foundation%Orientation + b2 * t_out + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Foundation%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%TranslationVel,1))) + b1 = -(u1%Foundation%TranslationVel - u2%Foundation%TranslationVel)/t(2) + u_out%Foundation%TranslationVel = u1%Foundation%TranslationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Foundation%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%RotationVel,1))) + b1 = -(u1%Foundation%RotationVel - u2%Foundation%RotationVel)/t(2) + u_out%Foundation%RotationVel = u1%Foundation%RotationVel + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) + b0 = -(u1%BladeLength - u2%BladeLength)/t(2) + u_out%BladeLength = u1%BladeLength + b0 * t_out + END SUBROUTINE AD14AeroConf_Input_ExtrapInterp1 + + + SUBROUTINE AD14AeroConf_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(AD14AeroConf_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(AD14AeroConf_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: b2 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: c2 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF +IF (ALLOCATED(u_out%Blade) .AND. ALLOCATED(u1%Blade)) THEN + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%Position,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%Position,1))) + b1 = (t(3)**2*(u1%Blade(i01)%Position - u2%Blade(i01)%Position) + t(2)**2*(-u1%Blade(i01)%Position + u3%Blade(i01)%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Blade(i01)%Position + t(3)*u2%Blade(i01)%Position - t(2)*u3%Blade(i01)%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Blade(i01)%Position = u1%Blade(i01)%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b2(SIZE(u_out%Blade(i01)%Orientation,1),SIZE(u_out%Blade(i01)%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Blade(i01)%Orientation,1),SIZE(u_out%Blade(i01)%Orientation,2) )) + b2 = (t(3)**2*(u1%Blade(i01)%Orientation - u2%Blade(i01)%Orientation) + t(2)**2*(-u1%Blade(i01)%Orientation + u3%Blade(i01)%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%Blade(i01)%Orientation + t(3)*u2%Blade(i01)%Orientation - t(2)*u3%Blade(i01)%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Blade(i01)%Orientation = u1%Blade(i01)%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%TranslationVel,1))) + b1 = (t(3)**2*(u1%Blade(i01)%TranslationVel - u2%Blade(i01)%TranslationVel) + t(2)**2*(-u1%Blade(i01)%TranslationVel + u3%Blade(i01)%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Blade(i01)%TranslationVel + t(3)*u2%Blade(i01)%TranslationVel - t(2)*u3%Blade(i01)%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Blade(i01)%TranslationVel = u1%Blade(i01)%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO + DO i01 = LBOUND(u_out%Blade,1),UBOUND(u_out%Blade,1) + ALLOCATE(b1(SIZE(u_out%Blade(i01)%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Blade(i01)%RotationVel,1))) + b1 = (t(3)**2*(u1%Blade(i01)%RotationVel - u2%Blade(i01)%RotationVel) + t(2)**2*(-u1%Blade(i01)%RotationVel + u3%Blade(i01)%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Blade(i01)%RotationVel + t(3)*u2%Blade(i01)%RotationVel - t(2)*u3%Blade(i01)%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Blade(i01)%RotationVel = u1%Blade(i01)%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ENDDO +END IF ! check if allocated + ALLOCATE(b1(SIZE(u_out%Hub%Position,1))) + ALLOCATE(c1(SIZE(u_out%Hub%Position,1))) + b1 = (t(3)**2*(u1%Hub%Position - u2%Hub%Position) + t(2)**2*(-u1%Hub%Position + u3%Hub%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Hub%Position + t(3)*u2%Hub%Position - t(2)*u3%Hub%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Hub%Position = u1%Hub%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Hub%Orientation,1),SIZE(u_out%Hub%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Hub%Orientation,1),SIZE(u_out%Hub%Orientation,2) )) + b2 = (t(3)**2*(u1%Hub%Orientation - u2%Hub%Orientation) + t(2)**2*(-u1%Hub%Orientation + u3%Hub%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%Hub%Orientation + t(3)*u2%Hub%Orientation - t(2)*u3%Hub%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Hub%Orientation = u1%Hub%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Hub%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Hub%TranslationVel,1))) + b1 = (t(3)**2*(u1%Hub%TranslationVel - u2%Hub%TranslationVel) + t(2)**2*(-u1%Hub%TranslationVel + u3%Hub%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Hub%TranslationVel + t(3)*u2%Hub%TranslationVel - t(2)*u3%Hub%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Hub%TranslationVel = u1%Hub%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Hub%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Hub%RotationVel,1))) + b1 = (t(3)**2*(u1%Hub%RotationVel - u2%Hub%RotationVel) + t(2)**2*(-u1%Hub%RotationVel + u3%Hub%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Hub%RotationVel + t(3)*u2%Hub%RotationVel - t(2)*u3%Hub%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Hub%RotationVel = u1%Hub%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%RotorFurl%Position,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%Position,1))) + b1 = (t(3)**2*(u1%RotorFurl%Position - u2%RotorFurl%Position) + t(2)**2*(-u1%RotorFurl%Position + u3%RotorFurl%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%RotorFurl%Position + t(3)*u2%RotorFurl%Position - t(2)*u3%RotorFurl%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%RotorFurl%Position = u1%RotorFurl%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%RotorFurl%Orientation,1),SIZE(u_out%RotorFurl%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%RotorFurl%Orientation,1),SIZE(u_out%RotorFurl%Orientation,2) )) + b2 = (t(3)**2*(u1%RotorFurl%Orientation - u2%RotorFurl%Orientation) + t(2)**2*(-u1%RotorFurl%Orientation + u3%RotorFurl%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%RotorFurl%Orientation + t(3)*u2%RotorFurl%Orientation - t(2)*u3%RotorFurl%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%RotorFurl%Orientation = u1%RotorFurl%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%RotorFurl%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%TranslationVel,1))) + b1 = (t(3)**2*(u1%RotorFurl%TranslationVel - u2%RotorFurl%TranslationVel) + t(2)**2*(-u1%RotorFurl%TranslationVel + u3%RotorFurl%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%RotorFurl%TranslationVel + t(3)*u2%RotorFurl%TranslationVel - t(2)*u3%RotorFurl%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%RotorFurl%TranslationVel = u1%RotorFurl%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%RotorFurl%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%RotorFurl%RotationVel,1))) + b1 = (t(3)**2*(u1%RotorFurl%RotationVel - u2%RotorFurl%RotationVel) + t(2)**2*(-u1%RotorFurl%RotationVel + u3%RotorFurl%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%RotorFurl%RotationVel + t(3)*u2%RotorFurl%RotationVel - t(2)*u3%RotorFurl%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%RotorFurl%RotationVel = u1%RotorFurl%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Nacelle%Position,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%Position,1))) + b1 = (t(3)**2*(u1%Nacelle%Position - u2%Nacelle%Position) + t(2)**2*(-u1%Nacelle%Position + u3%Nacelle%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Nacelle%Position + t(3)*u2%Nacelle%Position - t(2)*u3%Nacelle%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Nacelle%Position = u1%Nacelle%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Nacelle%Orientation,1),SIZE(u_out%Nacelle%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Nacelle%Orientation,1),SIZE(u_out%Nacelle%Orientation,2) )) + b2 = (t(3)**2*(u1%Nacelle%Orientation - u2%Nacelle%Orientation) + t(2)**2*(-u1%Nacelle%Orientation + u3%Nacelle%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%Nacelle%Orientation + t(3)*u2%Nacelle%Orientation - t(2)*u3%Nacelle%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Nacelle%Orientation = u1%Nacelle%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Nacelle%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%TranslationVel,1))) + b1 = (t(3)**2*(u1%Nacelle%TranslationVel - u2%Nacelle%TranslationVel) + t(2)**2*(-u1%Nacelle%TranslationVel + u3%Nacelle%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Nacelle%TranslationVel + t(3)*u2%Nacelle%TranslationVel - t(2)*u3%Nacelle%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Nacelle%TranslationVel = u1%Nacelle%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Nacelle%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Nacelle%RotationVel,1))) + b1 = (t(3)**2*(u1%Nacelle%RotationVel - u2%Nacelle%RotationVel) + t(2)**2*(-u1%Nacelle%RotationVel + u3%Nacelle%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Nacelle%RotationVel + t(3)*u2%Nacelle%RotationVel - t(2)*u3%Nacelle%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Nacelle%RotationVel = u1%Nacelle%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%TailFin%Position,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%Position,1))) + b1 = (t(3)**2*(u1%TailFin%Position - u2%TailFin%Position) + t(2)**2*(-u1%TailFin%Position + u3%TailFin%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%TailFin%Position + t(3)*u2%TailFin%Position - t(2)*u3%TailFin%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%TailFin%Position = u1%TailFin%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%TailFin%Orientation,1),SIZE(u_out%TailFin%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%TailFin%Orientation,1),SIZE(u_out%TailFin%Orientation,2) )) + b2 = (t(3)**2*(u1%TailFin%Orientation - u2%TailFin%Orientation) + t(2)**2*(-u1%TailFin%Orientation + u3%TailFin%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%TailFin%Orientation + t(3)*u2%TailFin%Orientation - t(2)*u3%TailFin%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%TailFin%Orientation = u1%TailFin%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%TailFin%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%TranslationVel,1))) + b1 = (t(3)**2*(u1%TailFin%TranslationVel - u2%TailFin%TranslationVel) + t(2)**2*(-u1%TailFin%TranslationVel + u3%TailFin%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%TailFin%TranslationVel + t(3)*u2%TailFin%TranslationVel - t(2)*u3%TailFin%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%TailFin%TranslationVel = u1%TailFin%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%TailFin%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%TailFin%RotationVel,1))) + b1 = (t(3)**2*(u1%TailFin%RotationVel - u2%TailFin%RotationVel) + t(2)**2*(-u1%TailFin%RotationVel + u3%TailFin%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%TailFin%RotationVel + t(3)*u2%TailFin%RotationVel - t(2)*u3%TailFin%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%TailFin%RotationVel = u1%TailFin%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Tower%Position,1))) + ALLOCATE(c1(SIZE(u_out%Tower%Position,1))) + b1 = (t(3)**2*(u1%Tower%Position - u2%Tower%Position) + t(2)**2*(-u1%Tower%Position + u3%Tower%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Tower%Position + t(3)*u2%Tower%Position - t(2)*u3%Tower%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Tower%Position = u1%Tower%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Tower%Orientation,1),SIZE(u_out%Tower%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Tower%Orientation,1),SIZE(u_out%Tower%Orientation,2) )) + b2 = (t(3)**2*(u1%Tower%Orientation - u2%Tower%Orientation) + t(2)**2*(-u1%Tower%Orientation + u3%Tower%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%Tower%Orientation + t(3)*u2%Tower%Orientation - t(2)*u3%Tower%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Tower%Orientation = u1%Tower%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Tower%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Tower%TranslationVel,1))) + b1 = (t(3)**2*(u1%Tower%TranslationVel - u2%Tower%TranslationVel) + t(2)**2*(-u1%Tower%TranslationVel + u3%Tower%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Tower%TranslationVel + t(3)*u2%Tower%TranslationVel - t(2)*u3%Tower%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Tower%TranslationVel = u1%Tower%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Tower%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Tower%RotationVel,1))) + b1 = (t(3)**2*(u1%Tower%RotationVel - u2%Tower%RotationVel) + t(2)**2*(-u1%Tower%RotationVel + u3%Tower%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Tower%RotationVel + t(3)*u2%Tower%RotationVel - t(2)*u3%Tower%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Tower%RotationVel = u1%Tower%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%SubStructure%Position,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%Position,1))) + b1 = (t(3)**2*(u1%SubStructure%Position - u2%SubStructure%Position) + t(2)**2*(-u1%SubStructure%Position + u3%SubStructure%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%SubStructure%Position + t(3)*u2%SubStructure%Position - t(2)*u3%SubStructure%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%SubStructure%Position = u1%SubStructure%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%SubStructure%Orientation,1),SIZE(u_out%SubStructure%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%SubStructure%Orientation,1),SIZE(u_out%SubStructure%Orientation,2) )) + b2 = (t(3)**2*(u1%SubStructure%Orientation - u2%SubStructure%Orientation) + t(2)**2*(-u1%SubStructure%Orientation + u3%SubStructure%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%SubStructure%Orientation + t(3)*u2%SubStructure%Orientation - t(2)*u3%SubStructure%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%SubStructure%Orientation = u1%SubStructure%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%SubStructure%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%TranslationVel,1))) + b1 = (t(3)**2*(u1%SubStructure%TranslationVel - u2%SubStructure%TranslationVel) + t(2)**2*(-u1%SubStructure%TranslationVel + u3%SubStructure%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%SubStructure%TranslationVel + t(3)*u2%SubStructure%TranslationVel - t(2)*u3%SubStructure%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%SubStructure%TranslationVel = u1%SubStructure%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%SubStructure%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%SubStructure%RotationVel,1))) + b1 = (t(3)**2*(u1%SubStructure%RotationVel - u2%SubStructure%RotationVel) + t(2)**2*(-u1%SubStructure%RotationVel + u3%SubStructure%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%SubStructure%RotationVel + t(3)*u2%SubStructure%RotationVel - t(2)*u3%SubStructure%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%SubStructure%RotationVel = u1%SubStructure%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Foundation%Position,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%Position,1))) + b1 = (t(3)**2*(u1%Foundation%Position - u2%Foundation%Position) + t(2)**2*(-u1%Foundation%Position + u3%Foundation%Position))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Foundation%Position + t(3)*u2%Foundation%Position - t(2)*u3%Foundation%Position ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Foundation%Position = u1%Foundation%Position + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b2(SIZE(u_out%Foundation%Orientation,1),SIZE(u_out%Foundation%Orientation,2) )) + ALLOCATE(c2(SIZE(u_out%Foundation%Orientation,1),SIZE(u_out%Foundation%Orientation,2) )) + b2 = (t(3)**2*(u1%Foundation%Orientation - u2%Foundation%Orientation) + t(2)**2*(-u1%Foundation%Orientation + u3%Foundation%Orientation))/(t(2)*t(3)*(t(2) - t(3))) + c2 = ( (t(2)-t(3))*u1%Foundation%Orientation + t(3)*u2%Foundation%Orientation - t(2)*u3%Foundation%Orientation ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Foundation%Orientation = u1%Foundation%Orientation + b2 * t_out + c2 * t_out**2 + DEALLOCATE(b2) + DEALLOCATE(c2) + ALLOCATE(b1(SIZE(u_out%Foundation%TranslationVel,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%TranslationVel,1))) + b1 = (t(3)**2*(u1%Foundation%TranslationVel - u2%Foundation%TranslationVel) + t(2)**2*(-u1%Foundation%TranslationVel + u3%Foundation%TranslationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Foundation%TranslationVel + t(3)*u2%Foundation%TranslationVel - t(2)*u3%Foundation%TranslationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Foundation%TranslationVel = u1%Foundation%TranslationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + ALLOCATE(b1(SIZE(u_out%Foundation%RotationVel,1))) + ALLOCATE(c1(SIZE(u_out%Foundation%RotationVel,1))) + b1 = (t(3)**2*(u1%Foundation%RotationVel - u2%Foundation%RotationVel) + t(2)**2*(-u1%Foundation%RotationVel + u3%Foundation%RotationVel))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%Foundation%RotationVel + t(3)*u2%Foundation%RotationVel - t(2)*u3%Foundation%RotationVel ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%Foundation%RotationVel = u1%Foundation%RotationVel + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) + b0 = (t(3)**2*(u1%BladeLength - u2%BladeLength) + t(2)**2*(-u1%BladeLength + u3%BladeLength))/(t(2)*t(3)*(t(2) - t(3))) + c0 = ( (t(2)-t(3))*u1%BladeLength + t(3)*u2%BladeLength - t(2)*u3%BladeLength ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%BladeLength = u1%BladeLength + b0 * t_out + c0 * t_out**2 + END SUBROUTINE AD14AeroConf_Input_ExtrapInterp2 + + + SUBROUTINE AD14AeroConf_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(AD14AeroConf_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL AD14AeroConf_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD14AeroConf_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD14AeroConf_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD14AeroConf_Output_ExtrapInterp + + + SUBROUTINE AD14AeroConf_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(AD14AeroConf_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Output_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = -(y1%Dummy - y2%Dummy)/t(2) + y_out%Dummy = y1%Dummy + b0 * t_out + END SUBROUTINE AD14AeroConf_Output_ExtrapInterp1 + + + SUBROUTINE AD14AeroConf_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(AD14AeroConf_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(AD14AeroConf_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14AeroConf_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = (t(3)**2*(y1%Dummy - y2%Dummy) + t(2)**2*(-y1%Dummy + y3%Dummy))/(t(2)*t(3)*(t(2) - t(3))) + c0 = ( (t(2)-t(3))*y1%Dummy + t(3)*y2%Dummy - t(2)*y3%Dummy ) / (t(2)*t(3)*(t(2) - t(3))) + y_out%Dummy = y1%Dummy + b0 * t_out + c0 * t_out**2 + END SUBROUTINE AD14AeroConf_Output_ExtrapInterp2 + +END MODULE AD14AeroConf_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn14/src/AD_RegistryEntries.xlsx b/OpenFAST/modules/aerodyn14/src/AD_RegistryEntries.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c7648aec13454e7da44721d2b023d12b3e562009 GIT binary patch literal 35792 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 Z5hzH5epxaA0PNSt`pe4Y!v4DZ{{Y;?>(BrI literal 0 HcmV?d00001 diff --git a/OpenFAST/modules/aerodyn14/src/AeroDyn14.f90 b/OpenFAST/modules/aerodyn14/src/AeroDyn14.f90 new file mode 100644 index 000000000..b608cef64 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/AeroDyn14.f90 @@ -0,0 +1,1238 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! This file is part of AeroDyn. +! +! 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 for the old aerodynamic routines. This module is for loose coupling only, without linearization, because it does not +!! fully conform to the FAST framework. This module will eventually be replaced by AeroDyn (i.e., AeroDyn v15 [aerodyn.f90]) +MODULE AeroDyn14 + + USE AeroDyn14_Types + USE AeroSubs + USE NWTC_Library + + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: AD14_Ver = ProgDesc( 'AeroDyn14', '', '' ) + + ! ..... Public Subroutines ............ + + PUBLIC :: AD14_Init ! Initialization routine + PUBLIC :: AD14_End ! Ending routine (includes clean up) + + PUBLIC :: AD14_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: AD14_CalcOutput ! Routine for computing outputs + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AD14_Init( InitInp, u, p, x, xd, z, O, y, m, Interval, InitOut, ErrStat, ErrMess ) +!.................................................................................................................................. + USE AeroGenSubs, ONLY: ElemOpen + USE DWM + IMPLICIT NONE + + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInp ! Input data for initialization routine + TYPE(AD14_InputType), INTENT( OUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(AD14_ParameterType), INTENT( OUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT( OUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT( OUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT( OUT) :: z ! Initial guess of the constraint states + TYPE(AD14_OtherStateType), INTENT( OUT) :: O ! Initial other states + TYPE(AD14_OutputType), INTENT( OUT) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + TYPE(AD14_MiscVarType), INTENT( OUT) :: m ! Misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval ! Coupling interval in seconds: the rate that + ! (1) AD14_UpdateStates() is called in loose coupling & + ! (2) AD14_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + TYPE(AD14_InitOutputType), INTENT( OUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + + ! Internal variables + REAL(ReKi) :: CosPrecone + REAL(ReKi) :: DTip, ElemRad, Dhub, Rhub ! variables for calculating hub- and tip-loss constants + REAL(ReKi) :: HubRadius +! REAL(ReKi) :: MeanWind + REAL(ReKi) :: TipRadius + REAL(ReKi) :: TmpVar + REAL(ReKi) :: TmpPos(3) + REAL(ReKi) :: TwrNodeHt ! The height of the current tower node. + + INTEGER :: IB, IE + INTEGER :: IELM + +! CHARACTER(1024) :: Title + + INTEGER :: Elem ! Index for mesh element. + INTEGER :: InterpIndx ! Index telling the interpolation routine where to start in the array. + INTEGER :: Node ! Index used to pull points out of the array of values at given node location. + INTEGER :: ErrStatLcL ! Error status returned by called routines. + + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Init' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMess = "" + InterpIndx = 1 + + + CALL NWTC_Init( ) + + + ! Display the module information + + CALL DispNVD( AD14_Ver ) + + InitOut%Ver = AD14_Ver + m%FirstWarn = .TRUE. + !------------------------------------------------------------------------------------------------- + ! Set up AD variables + !------------------------------------------------------------------------------------------------- + + p%LinearizeFlag = .FALSE. ! InitInp%LinearizeFlag + p%Blade%BladeLength = InitInp%TurbineComponents%BladeLength + p%DtAero = Interval ! set the default DT here; may be overwritten later, when we read the input file in AD14_GetInput() + p%UseDWM = InitInp%UseDWM + + ! Define parameters here: + + p%WrOptFile = InitInp%WrSumFile + + p%NumBl = SIZE( InitInp%TurbineComponents%Blade ) + IF ( p%NumBl < 1 ) THEN + CALL SetErrStat( ErrID_Fatal,'AeroDyn cannot run without blades in the model.',ErrStat,ErrMess,RoutineName) + RETURN + END IF +!bjj: what's the difference between p%NumBl, p%Blade%NB, and InitInp%NumBl? +!MLB: Heck if I know! + + ! Define initial system states here: + !------------------------------------------------------------------------------------------------- + ! Read the AeroDyn14 input file and open the output file if requested + ! bjj: these should perhaps be combined + !------------------------------------------------------------------------------------------------- + CALL AD14_GetInput(InitInp, P, x, xd, z, m, y, ErrStatLcl, ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev ) RETURN + + + ! allocate variables for aerodyn forces + p%LinearizeFlag = .FALSE. + + Interval = p%DtAero + + + IF ( .NOT. ALLOCATED( m%StoredForces )) THEN + CALL AllocAry(m%StoredForces, 3,p%Element%NELM,p%NumBl,'m%StoredForces',ErrStatLcl,ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + END IF + IF ( .NOT. ALLOCATED( m%StoredMoments )) THEN + CALL AllocAry(m%StoredMoments, 3,p%Element%NELM,p%NumBl,'m%StoredForces',ErrStatLcl,ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + END IF + + IF (.NOT. ALLOCATED(m%Element%W2) ) THEN + CALL AllocAry(m%Element%W2, p%Element%NELM, p%NumBl,'m%Element%W2',ErrStatLcl,ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + END IF + + IF (.NOT. ALLOCATED(m%Element%Alpha) ) THEN + CALL AllocAry(m%Element%Alpha, p%Element%NELM, p%NumBl,'m%Element%Alpha',ErrStatLcl,ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + END IF + + IF (.NOT. ALLOCATED(m%Element%PitNow) ) THEN + CALL AllocAry(m%Element%PitNow, p%Element%NELM, p%NumBl,'m%Element%PitNow',ErrStatLcl,ErrMessLcl ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + END IF + IF (ErrStat >= AbortErrLev ) RETURN + + + P%UnWndOut = -1 + P%UnElem = -1 + IF ( p%ElemPrn ) THEN + CALL ElemOpen ( TRIM( InitInp%OutRootName )//'.AD.out', P, m, ErrStat, ErrMess, AD14_Ver ) + CALL SetErrStat( ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev ) RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Calculate the rotor and hub radaii from the input values + !------------------------------------------------------------------------------------------------- + HubRadius = DOT_PRODUCT( InitInp%TurbineComponents%Blade(1)%Position(:) & + - InitInp%TurbineComponents%Hub%Position(:), & + InitInp%TurbineComponents%Blade(1)%Orientation(3,:) ) + + DO IB = 2,p%NumBl + TmpVar = DOT_PRODUCT( InitInp%TurbineComponents%Blade(IB)%Position(:) & + - InitInp%TurbineComponents%Hub%Position(:), & + InitInp%TurbineComponents%Blade(IB)%Orientation(3,:) ) + IF ( ABS( TmpVar - HubRadius ) > 0.001 ) THEN ! within 1 mm + CALL ProgWarn( ' AeroDyn\AD14_Init() calculated HubRadius is not the same for all '// & + 'blades. Using value from blade 1.' ) + EXIT + END IF + END DO !IB + + TipRadius = InitInp%TurbineComponents%BladeLength + HubRadius + + CosPrecone = ASIN( DOT_PRODUCT( InitInp%TurbineComponents%Blade(1)%Orientation(3,:), & + InitInp%TurbineComponents%Hub%Orientation(1,:) ) ) ! precone angle -- do COS later + + DO IB = 2,p%NumBl + TmpVar = ASIN( DOT_PRODUCT( InitInp%TurbineComponents%Blade(IB)%Orientation(3,:), & + InitInp%TurbineComponents%Hub%Orientation(1,:) ) ) + IF ( ABS( TmpVar - CosPrecone ) > 0.009 ) THEN ! within ~ 1/2 degree + CALL ProgWarn( ' AeroDyn\AD14_Init() calculated precone angle is not the same for all'// & + ' blades. Using value from blade 1.' ) + EXIT + END IF + END DO !IBld + + CosPrecone = COS( CosPrecone ) + + p%Blade%R = TipRadius * CosPrecone + RHub = HubRadius * CosPrecone + p%HubRad = RHub + + ! Check that the AeroDyn input DR and RElm match (use the HubRadius and TipRadius to verify) + ! before using them to calculate the tip- and hub-loss constants + CALL CheckRComp( P, x, xd, z, m, y, ErrStat, ErrMess, & + InitInp%ADFileName, HubRadius, TipRadius ) + + IF ( ErrStat /= ErrID_None ) RETURN + + !------------------------------------------------------------------------------------------------- + ! Calculate tip-loss constants + !------------------------------------------------------------------------------------------------- + DO IElm = 1,p%Element%NElm ! Loop through all blade elements + + ElemRad = p%Element%RELM(IElm)*CosPrecone + + IF( ElemRad == 0.0 ) THEN !BJJ: should this be 0.001 (or another small number) instead of exactly 0.0? + CALL SetErrStat( ErrID_Fatal,'Error calculating tip loss constant for element '//TRIM(Int2LStr(IElm))//& + '. Division by zero.',ErrStat,ErrMess,RoutineName) + + RETURN + ELSE + DTip = p%Blade%R - ElemRad + p%Element%TLCNST(IElm) = 0.5 * p%NumBl * DTip / ElemRad + ENDIF + + ENDDO ! IElm - all blade elements + + + !------------------------------------------------------------------------------------------------- + ! Calculate hub-loss constants + !------------------------------------------------------------------------------------------------- + IF ( RHub > 0.001 ) THEN + + DO Ielm = 1,p%Element%NELM ! Loop through all blade elements + + ElemRad = p%Element%RELM(Ielm)*CosPrecone ! Use only the precone angle of blade 1 (assumed very similar to other blades) + + DHub = ElemRad - RHub + p%Element%HLCNST(Ielm) = 0.5 * p%NumBl * DHub / RHub + + ENDDO ! IELM - all blade elements + + ELSE + + p%Element%HLCNST(:) = 0.0 + + ENDIF + + + + !------------------------------------------------------------------------------------------------- + ! Interpolate the tower diameter at ElastoDyn's tower nodes if we will be computing tower aerodynamics. + !------------------------------------------------------------------------------------------------- + + IF ( p%TwrProps%CalcTwrAero ) THEN + + !------------------------------------------------------------------------------------------------- + ! IMPORTANT NOTES: + ! o Supposedly, the glue code will not try to do anything with the tower-aero mesh if is is + ! not created, so the creation is inside the test for CalcTwrAero. + ! o The tower properties from AeroDyn's tower file are for heights from the origin (ground or + ! MSL) to the hub height--not the top of the tower. + ! o For now, we are allowing only one set of Cd for the entire tower. + ! o InterpIndx is initialize to 1 at compile time. + !------------------------------------------------------------------------------------------------- + + + ! Create the mesh for the tower aerodynamics. + + CALL MeshCreate ( BlankMesh = u%Twr_InputMarkers & + , IOS = COMPONENT_INPUT & + , NNodes = InitInp%NumTwrNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , ErrStat = ErrStatLcl & + , ErrMess = ErrMessLcl ) + + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Set the positions of the nodes. MeshCreate() allocated the Position array. + + DO Node = 1,u%Twr_InputMarkers%Nnodes + CALL MeshPositionNode ( Mesh = u%Twr_InputMarkers & + ,INode = Node & + ,Pos = InitInp%TwrNodeLocs(:,Node) & + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + END DO + + + ! Construct the tower with Line-2 elements. + + DO Elem=1,u%Twr_InputMarkers%Nnodes-1 + + CALL MeshConstructElement ( Mesh = u%Twr_InputMarkers & + , Xelement = ELEMENT_LINE2 & + , P1 = Elem & + , P2 = Elem+1 & + , ErrStat = ErrStatLcl & + , ErrMess = ErrMessLcl ) + + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ENDDO + + + ! Commit the mesh to the funny farm. + + CALL MeshCommit ( u%Twr_InputMarkers, ErrStatLcl, ErrMessLcl ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Copy the input mesh to create the output mesh. Does + + CALL MeshCopy ( SrcMesh = u%Twr_InputMarkers & + , DestMesh = y%Twr_OutputLoads & + , CtrlCode = MESH_SIBLING & + , Force = .TRUE. & + , ErrStat = ErrStatLcl & + , ErrMess = ErrMessLcl ) + + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Check to ensure that the user did not specify more than one set of Cd(Re) tables. Temporary restriction. + + IF ( p%TwrProps%NTwrCD /= 1 ) THEN + CALL SetErrStat(ErrID_Fatal,'You must have one and only one set of drag coefficients for the AeroDyn tower file.',ErrStat,ErrMess,RoutineName ) + RETURN + END IF + + + ! Build the TwrNodeWidth array. + + p%TwrProps%NumTwrNodes = InitInp%NumTwrNodes + + IF (.NOT. ALLOCATED( p%TwrProps%TwrNodeWidth ) ) THEN + CALL AllocAry( p%TwrProps%TwrNodeWidth, p%TwrProps%NumTwrNodes, "array for tower widths at ED node locations", ErrStatLcl, ErrMessLcl ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + DO Node=1,p%TwrProps%NumTwrNodes + + TwrNodeHt = InitInp%TwrNodeLocs(3,Node)/p%Rotor%HH + + p%TwrProps%TwrNodeWidth(Node) = InterpStp( TwrNodeHt, p%TwrProps%TwrHtFr, p%TwrProps%TwrWid, InterpIndx, p%TwrProps%NTwrHT ) + + END DO ! Node + + ELSE + u%Twr_InputMarkers%Nnodes = 0 + y%Twr_OutputLoads%Nnodes = 0 + END IF ! ( p%TwrProps%CalcTwrAero ) + + + !------------------------------------------------------------------------------------------------- + ! Write the summary (opt) file, then close it + !------------------------------------------------------------------------------------------------- + + IF (p%WrOptFile) THEN + + CALL ADOut(InitInp, P, m, AD14_Ver, TRIM(InitInp%OutRootName)//'.AD.sum', ErrStatLcl, ErrMessLcl ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Initialize the inputs from the wind inflow module + !------------------------------------------------------------------------------------------------- + CALL AllocAry( u%InflowVelocity, 3, p%Element%NElm*p%NumBl + u%Twr_InputMarkers%Nnodes, 'u%InflowVelocity', ErrStatLcl, ErrMessLcl ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + u%InflowVelocity = 0.0_ReKi + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Calling the DWM + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + IF ( p%UseDWM ) THEN + ! InitInp%DWM%IfW%InputFileName is already set in FAST + + ! bjj: all this stuff should be put in DWM_Init.....> + p%DWM%RR = p%Blade%R + p%DWM%BNum = p%NumBl + !p%DWM%ElementNum = m%ElOut%NumElOut !bjj: NumElOut is the number of elements to be printed in an output file. I really think you want the number of blade elements. I guess we should check that NumElOut is the same as p%Element%NElm + p%DWM%ElementNum = p%Element%NElm ! yj: 1/18/2016 + p%DWM%air_density = p%Wind%Rho + + IF (.NOT. ALLOCATED(m%DWM%Nforce )) ALLOCATE ( m%DWM%Nforce( p%Element%NElm,p%NumBl),STAT=ErrStatLcl);CALL SetErrStat(ErrStatLcl, 'Error allocating DWM Nforce array', ErrStat,ErrMess,RoutineName ) + IF (.NOT. ALLOCATED(m%DWM%blade_dr )) ALLOCATE ( m%DWM%blade_dr( p%Element%NElm), STAT=ErrStatLcl);CALL SetErrStat(ErrStatLcl, 'Error allocating DWM blade_dr array', ErrStat,ErrMess,RoutineName ) + IF (.NOT. ALLOCATED(p%DWM%ElementRad)) ALLOCATE ( p%DWM%ElementRad(p%Element%NElm), STAT=ErrStatLcl);CALL SetErrStat(ErrStatLcl, 'Error allocating DWM ElementRad array', ErrStat,ErrMess,RoutineName ) + if (errStat >= AbortErrLev) return + + m%DWM%blade_dr = p%Blade%DR(:) + p%DWM%ElementRad = p%Element%RELM(:) + + CALL DWM_Init( InitInp%DWM, m%DWM_Inputs, p%DWM, x%DWM, xd%DWM, z%DWM, O%DWM, m%DWM_Outputs, m%DWM, Interval, InitOut%DWM, ErrStatLcl, ErrMessLcl) + + + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + END IF !UseDWM + + !------------------------------------------------------------------------------------------------- + ! Turn off dynamic inflow for wind less than 8 m/s (per DJL: 8 m/s is really just an empirical guess) + ! DJL: Comment out this code when using new proposed GDW check in ELEMFRC + ! BJJ: FIX THIS!!!! + !------------------------------------------------------------------------------------------------- + + ! BJJ: can't put this here b/c we need InitInp%MWS from InflowWind + !IF (p%DynInfl) THEN + ! + ! IF ( InitInp%MWS < 8.0 ) THEN + ! p%DynInfl = .FALSE. + ! CALL SetErrStat(ErrID_Info,'Estimated average inflow wind speed is less than 8 m/s. Dynamic Inflow will be turned off.',ErrStat,ErrMess,RoutineName ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + ! END IF + ! + !ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Set initial guesses for inputs: + !------------------------------------------------------------------------------------------------- + + !.......... + ! u%TurbineComponents + !.......... + + CALL AD14_CopyAeroConfig( InitInp%TurbineComponents, u%TurbineComponents, MESH_NEWCOPY, ErrStatLcl, ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + !.......... + ! u%InputMarkers (blade meshes): + !.......... + + ALLOCATE( u%InputMarkers(p%NumBl), STAT=ErrStatLcl ) + IF (ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Could not allocate u%InputMarkers (meshes)', ErrStat,ErrMess,RoutineName ) + RETURN + END IF + + + DO IB = 1, p%NumBl + CALL MeshCreate( BlankMesh = u%InputMarkers(IB) & + ,IOS = COMPONENT_INPUT & + ,NNodes = p%Element%NELM & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,TranslationAcc = .TRUE. & !bjj: added for MHK turbines + ,RotationVel = .TRUE. & + ,nScalars = 2 & ! scalar 1 is W, scalar 2 is Alpha + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! create the elements + DO IE = 1, p%Element%NELM-1 ! construct the blades into Line2 elements + CALL MeshConstructElement ( Mesh = u%InputMarkers(IB) & + ,Xelement = ELEMENT_LINE2 & + ,P1 = IE & + ,P2 = IE+1 & + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ENDDO + + ! position/orient the nodes + DO IE = 1, p%Element%NELM + TmpPos(1) = 0. + TmpPos(2) = 0. + TmpPos(3) = p%Element%Relm(IE) - HubRadius + CALL MeshPositionNode ( Mesh = u%InputMarkers(IB) & + ,INode = IE & + ,Pos= TmpPos & ! this info comes from FAST (not yet) + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! RELATIVE ORIENTATION OF BLADE ELEMENTS + u%InputMarkers(IB)%Orientation(1,1,IE) = COS( P%Element%TWIST(IE) ) + u%InputMarkers(IB)%Orientation(2,1,IE) = SIN( P%Element%TWIST(IE) ) + u%InputMarkers(IB)%Orientation(3,1,IE) = SIN( P%Element%TWIST(IE) ) + u%InputMarkers(IB)%Orientation(1,2,IE) = -1. * u%InputMarkers(IB)%Orientation(2,1,IE) + u%InputMarkers(IB)%Orientation(2,2,IE) = u%InputMarkers(IB)%Orientation(1,1,IE) + u%InputMarkers(IB)%Orientation(3,2,IE) = 0.0 + u%InputMarkers(IB)%Orientation(1,3,IE) = 0.0 + u%InputMarkers(IB)%Orientation(2,3,IE) = 0.0 + u%InputMarkers(IB)%Orientation(3,3,IE) = 1.0 + ENDDO + + CALL MeshCommit ( Mesh = u%InputMarkers(IB) & + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ENDDO + + + !.......... + ! u%Twr_InputMarkers (tower meshes): + !.......... + + !bjj: done above in section for IF Tower Loads is on + + + !.......... + ! u%MulTabLoc: + !.......... + + IF (.NOT. ALLOCATED(u%MulTabLoc)) THEN + ALLOCATE( u%MulTabLoc(p%Element%NELM, p%NumBl), STAT = ErrStatLcl ) + IF (ErrStatLcl /= 0) THEN + CALL SetErrStat ( ErrID_Fatal, 'Could not allocate u%MulTabLoc', ErrStat,ErrMess,RoutineName ) + RETURN + END IF + END IF + + u%MulTabLoc(:,:) = 0.0 + + + !------------------------------------------------------------------------------------------------- + ! Allocate space for outputs and set up output meshes: + !------------------------------------------------------------------------------------------------- + + !.......... + ! y%OutputLoads (blade meshes): + !.......... + + + ALLOCATE( y%OutputLoads(p%NumBl), STAT = ErrStatLcl ) + IF (ErrStatLcl /= 0) THEN + CALL SetErrStat ( ErrID_Fatal, 'Could not allocate y%OutputLoads (meshes)', ErrStat,ErrMess,RoutineName ) + RETURN + END IF + + DO IB = 1, p%NumBl + + CALL MeshCopy ( SrcMesh = u%InputMarkers(IB) & + ,DestMesh = y%OutputLoads(IB) & + ,CtrlCode = MESH_SIBLING & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStatLcl & + ,ErrMess = ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + ENDDO + + + !.......... + ! y%Twr_OutputLoads (tower meshes): + !.......... + + !bjj: done above in section for IF Tower Loads is on + + + !------------------------------------------------------------------------------------------------- + ! Initialize AeroDyn variables not initialized elsewhere (except in module initialization) + ! and return + !------------------------------------------------------------------------------------------------- + m%InducedVel%SumInfl = 0.0_ReKi + m%Rotor%AvgInfl = 0.0_ReKi + m%OldTime = 0.0_DbKi + m%SuperSonic = .FALSE. + m%NoLoadsCalculated = .TRUE. + + p%TwoPiNB = TwoPi / REAL( p%NumBl, ReKi ) + + + DO ie = 1, maxInfl + p%DynInflow%xMinv(ie) = PIBY2 / hfunc(MRvector(ie), NJvector(ie)) !bjj: this is really just a Fortran parameter, too. + END DO !ie + + + InitOut%AirDens = p%Wind%Rho + + + RETURN + +END SUBROUTINE AD14_Init +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AD14_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! This routine is called at the end of the simulation. +!.................................................................................................................................. + USE DWM_Types + USE DWM + + TYPE(AD14_InputType), INTENT(INOUT) :: u ! System inputs + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states + TYPE(AD14_OtherStateType), INTENT(INOUT) :: OtherState ! Other states + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! System outputs + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMess = "" + + + ! Place any last minute operations or calculations here: + + IF (p%UseDWM ) THEN + !----- Call the DWM ------- + + CALL DWM_End( m%DWM_Inputs, p%DWM, x%DWM, xd%DWM, z%DWM, OtherState%DWM, m%DWM_Outputs, m%DWM, ErrStat, ErrMess ) + END IF ! UseDWM + + !-------------------------- + + + ! Close files here: + + ! AD14_IOParams + IF (P%UnEc > 0) CLOSE(P%UnEc) ! not currently used + + IF (P%UnWndOut > 0) CLOSE(P%UnWndOut) + IF (P%UnElem > 0) CLOSE(P%UnElem) + + ! Destroy the input data: + + CALL AD14_DestroyInput( u, ErrStat, ErrMess ) + + + ! Destroy the parameter data: + + CALL AD14_DestroyParam( p, ErrStat, ErrMess ) + + + ! Destroy the state data: + + CALL AD14_DestroyContState( x, ErrStat, ErrMess ) + CALL AD14_DestroyDiscState( xd, ErrStat, ErrMess ) + CALL AD14_DestroyConstrState( z, ErrStat, ErrMess ) + CALL AD14_DestroyOtherState( OtherState, ErrStat, ErrMess ) + + CALL AD14_DestroyMisc( m, ErrStat, ErrMess ) + + ! Destroy the output data: + + CALL AD14_DestroyOutput( y, ErrStat, ErrMess ) + + +END SUBROUTINE AD14_End +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AD14_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMess ) +! Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states +! Constraint states are solved for input Time; Continuous and discrete states are updated for Time + Interval +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n ! Current simulation time step n = 0,1,... + TYPE(AD14_InputType), INTENT(INOUT) :: u(:) ! Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) ! Times associated with u(:), in seconds + TYPE(AD14_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + Interval + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Input: Constraint states at t; + ! Output: Constraint states at t + Interval + TYPE(AD14_OtherStateType), INTENT(INOUT) :: OtherState ! Input: Other states at t; + ! Output: Other states at t + Interval + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + ! Local variables + + TYPE(AD14_ContinuousStateType) :: dxdt ! Continuous state derivatives at Time + TYPE(AD14_ConstraintStateType) :: z_Residual ! Residual of the constraint state equations (Z) + +! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) +! CHARACTER(ErrMsgLen) :: ErrMess2 ! Error message if ErrStat2 /= ErrID_None + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMess = "" + + + ! AeroDyn v14 DOES actually have states, but they are updated in CalcOutput because no one ever took the time to + ! identify which variables are states. + +END SUBROUTINE AD14_UpdateStates + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE AD14_CalcOutput( Time, u, p, x, xd, z, O, y, m, ErrStat, ErrMess ) +! Routine for computing outputs, used in both loose and tight coupling. +!.................................................................................................................................. + + USE AeroGenSubs, ONLY: ElemOut + USE DWM_Types + USE DWM + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(AD14_InputType), INTENT(INOUT) :: u ! Inputs at Time + TYPE(AD14_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at Time + TYPE(AD14_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at Time + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states at Time + TYPE(AD14_OtherStateType), INTENT(IN ) :: O ! Other states at Time + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + + ! Local variables + REAL(DbKi), PARAMETER :: OnePlusEpsilon = 1 + EPSILON(Time) + + REAL(ReKi) :: VelNormalToRotor2 + REAL(ReKi) :: VTWind + REAL(ReKi) :: VNWind + REAL(ReKi) :: VNElement + REAL(ReKi) :: VTElement + REAL(ReKi) :: VN_ind + REAL(ReKi) :: VT_ind + REAL(ReKi) :: VN + REAL(ReKi) :: VT + REAL(ReKi) :: VTTotal + REAL(ReKi) :: DFN + REAL(ReKi) :: DFT + REAL(ReKi) :: PMA + REAL(ReKi) :: SPitch ! sine of PitNow + REAL(ReKi) :: CPitch ! cosine of PitNow + REAL(ReKi) :: Phi ! Local value of Phi + + REAL(ReKi) :: AvgVelNacelleRotorFurlYaw + REAL(ReKi) :: AvgVelTowerBaseNacelleYaw + REAL(ReKi) :: AvgVelTowerBaseYaw + REAL(ReKi) :: AzimuthAngle + REAL(ReKi) :: rNacelleHub (2) + REAL(ReKi) :: rLocal + REAL(ReKi) :: rRotorFurlHub (2) + REAL(ReKi) :: rTowerBaseHub (2) + + REAL(ReKi) :: tmpVector (3) + REAL(ReKi) :: norm_Vector (3) ! Unit vector normal to chord + REAL(ReKi) :: tang_Vector (3) ! Unit vector tangent to chord + REAL(ReKi) :: VelocityVec (3) + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + INTEGER :: IBlade + INTEGER :: IElement + INTEGER :: Node ! Node index. + + INTEGER :: I + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_AeroSubs' !KS Not sure why I added this + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMess = "" + + + !------------------------------------------------------------------------------------------------- + ! Determine if loads should be recalculated or just returned + !------------------------------------------------------------------------------------------------- + ! NOTE: Time is scaled by OnePlusEps to ensure that loads are calculated at every + ! time step when DTAero = DT, even in the presence of numerical precision errors. + + IF ( m%NoLoadsCalculated .OR. ( Time*OnePlusEpsilon - m%OldTime ) >= p%DTAERO ) THEN + ! It's time to update the aero forces + + ! First we reset the DTAERO parameters for next time + m%DT = Time - m%OldTime !bjj: DT = 0 on first step, + !but the subroutines that use DT check for NoLoadsCalculated (or time > 0) + m%OldTime = Time + + ELSE IF ( .NOT. p%LinearizeFlag ) THEN + + ! Return the previously-calculated loads + +! CurrentOutputs = ADCurrentLoads + + DO IBlade=1,p%NumBl + DO IElement=1,p%Element%Nelm + y%OutputLoads(IBlade)%Force(:,IElement) = m%StoredForces(:,IElement,IBlade) + y%OutputLoads(IBlade)%Moment(:,IElement) = m%StoredMoments(:,IElement,IBlade) + ENDDO + ENDDO + + IF ( m%FirstWarn ) THEN + CALL SetErrStat ( ErrID_Warn, 'AeroDyn was designed for an explicit-loose coupling scheme. '//& + 'Using last calculated values from AeroDyn on all subsequent calls until time is advanced. '//& + 'Warning will not be displayed again.', ErrStat,ErrMess,'AD14_CalcOutput' ) + m%FirstWarn = .FALSE. + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END IF + + RETURN + + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Calculate the forces and moments for the blade: SUBROUTINE AeroFrcIntrface( FirstLoop, JElemt, DFN, DFT, PMA ) + !------------------------------------------------------------------------------------------------- + + ! calculate rotor speed + ! note: Subtracting the RotorFurl rotational velocity for REVS is needed to get the + ! same answers as before v13.00.00. RotorFurl shouldn't be needed. + + m%Rotor%REVS = ABS( DOT_PRODUCT( u%TurbineComponents%Hub%RotationVel(:) - u%TurbineComponents%RotorFurl%RotationVel(:), & + u%TurbineComponents%Hub%Orientation(1,:) ) ) + + + ! calculate yaw angle + ! note: YawAng should use the Hub instead of the RotorFurl, but it is calculated this way to + ! get the same answers as previous version. + m%Rotor%YawAng = ATAN2( -1.*u%TurbineComponents%RotorFurl%Orientation(1,2), u%TurbineComponents%RotorFurl%Orientation(1,1) ) + m%Rotor%SYaw = SIN( m%Rotor%YawAng ) + m%Rotor%CYaw = COS( m%Rotor%YawAng ) + + ! tilt angle + ! note: tilt angle should use the Hub instead of RotorFurl, but it needs hub to get the same + ! answers as the version before v13.00.00 + + m%Rotor%Tilt = ATAN2( u%TurbineComponents%RotorFurl%Orientation(1,3), & + SQRT( u%TurbineComponents%RotorFurl%Orientation(1,1)**2 + & + u%TurbineComponents%RotorFurl%Orientation(1,2)**2 ) ) + + m%Rotor%CTilt = COS( m%Rotor%Tilt ) + m%Rotor%STilt = SIN( m%Rotor%Tilt ) + + + ! HubVDue2Yaw - yaw velocity due solely to yaw + + AvgVelNacelleRotorFurlYaw = u%TurbineComponents%RotorFurl%RotationVel(3) - u%TurbineComponents%Nacelle%RotationVel(3) + AvgVelTowerBaseNacelleYaw = u%TurbineComponents%Nacelle%RotationVel(3) - u%TurbineComponents%Tower%RotationVel(3) + AvgVelTowerBaseYaw = u%TurbineComponents%Tower%RotationVel(3) + + rRotorFurlHub(1:2) = u%TurbineComponents%Hub%Position(1:2) - u%TurbineComponents%RotorFurl%Position(1:2) + rNacelleHub(1:2) = u%TurbineComponents%Hub%Position(1:2) - u%TurbineComponents%Nacelle%Position(1:2) + rTowerBaseHub(1:2) = u%TurbineComponents%Hub%Position(1:2) - u%TurbineComponents%Tower%Position(1:2) + + m%Rotor%YawVel = ( AvgVelNacelleRotorFurlYaw * rRotorFurlHub(2) + AvgVelTowerBaseNacelleYaw * rNacelleHub(2) & + + AvgVelTowerBaseYaw * rTowerBaseHub(2) ) * m%Rotor%SYaw & + - ( AvgVelNacelleRotorFurlYaw * rRotorFurlHub(1) + AvgVelTowerBaseNacelleYaw * rNacelleHub(1) & + + AvgVelTowerBaseYaw * rTowerBaseHub(1) ) * m%Rotor%CYaw + + + !................................................................................................. + ! start of NewTime routine + !................................................................................................. + + m%Rotor%AvgInfl = m%InducedVel%SumInfl * 2.0 / (p%Blade%R*p%Blade%R*p%NumBl) ! Average inflow from the previous time step + m%InducedVel%SumInfl = 0.0 ! reset to sum for the current time step + + CALL DiskVel(Time, P, m, u%AvgInfVel, ErrStatLcl, ErrMessLcl) ! Get a sort of "Average velocity" - sets a bunch of stored variables... + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput/DiskVel' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( P%DStall ) CALL BedUpdate( m ) + + ! Enter the dynamic inflow routines here + + IF ( p%Wake ) THEN + CALL Inflow(Time, P, m, ErrStatLcl, ErrMessLcl) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput/Inflow' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END IF + + !bjj: perhaps we should send NoLoadsCalculated to initialize dynamic inflow [subroutine Infinit()] + !bjj: instead of the check that time > 0...? + + !................................................................................................. + ! end of NewTime routine + !................................................................................................. + + ! Set blade element pitches + DO IBlade = 1,p%NumBl + DO IElement = 1,p%Element%NElm + ! calculate element pitch + m%Element%PitNow(IElement,IBlade) = -1.*ATAN2( -1.*DOT_PRODUCT( u%TurbineComponents%Blade(IBlade)%Orientation(1,:), & + u%InputMarkers(IBlade)%Orientation(2,:,IElement) ) , & + DOT_PRODUCT( u%TurbineComponents%Blade(IBlade)%Orientation(1,:), & + u%InputMarkers(IBlade)%Orientation(1,:,IElement) ) ) + ENDDO + ENDDO + + + Node = 0 + ! --- Loop on blades + DO IBlade = 1,p%NumBl + + ! calculate the azimuth angle ( we add pi because AeroDyn defines 0 as pointing downward) + ! note: the equation below should use TurbineComponents%Blade markers, but this is used to get the + ! same answers as the previous version (before v13.00.00) + + AzimuthAngle = ATAN2( -1.*DOT_PRODUCT( u%TurbineComponents%Hub%Orientation(3,:), & + u%TurbineComponents%RotorFurl%Orientation(2,:) ), & + DOT_PRODUCT( u%TurbineComponents%Hub%Orientation(3,:), & + u%TurbineComponents%RotorFurl%Orientation(3,:) ) ) + pi + (IBlade - 1)*p%TwoPiNB + ! --- Loop on elements + DO IElement = 1,p%Element%NElm + + SPitch = SIN( m%Element%PitNow(IElement,IBlade) ) + CPitch = COS( m%Element%PitNow(IElement,IBlade) ) + + ! calculate distance between hub and element + tmpVector = u%InputMarkers(IBlade)%Position(:,IElement) - u%TurbineComponents%Hub%Position(:) + rLocal = SQRT( DOT_PRODUCT( tmpVector, u%TurbineComponents%Hub%Orientation(2,:) )**2 & + + DOT_PRODUCT( tmpVector, u%TurbineComponents%Hub%Orientation(3,:) )**2 ) + + ! determine if MulTabLoc should be set. + + IF (.not. p%Reynolds) m%AirFoil%MulTabLoc = u%MulTabLoc(IElement,IBlade) + + !------------------------------------------------------------------------------------------- + ! Get wind velocity components; calculate velocity normal to the rotor squared + ! Save variables for printing in a file later; + !------------------------------------------------------------------------------------------- + Node = Node + 1 + VelocityVec(:) = AD_WindVelocityWithDisturbance( Time, u, p, x, xd, z, m, y, ErrStatLcl, ErrMessLcl, & + u%InputMarkers(IBlade)%Position(:,IElement), & + u%InflowVelocity(:,Node) ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + !------------------------------------------------------------------------------------------- + ! DWM wind input update phase 1 + !------------------------------------------------------------------------------------------- + IF (p%UseDWM) THEN + !bjj: FIX THIS!!!! + !bjj: where do p%DWM%RTPD%SimulationOrder_index and p%DWM%RTPD%upwindturbine_number get set? + + IF ( p%DWM%RTPD%SimulationOrder_index > 1) THEN + IF( p%DWM%RTPD%upwindturbine_number /= 0 ) THEN + + m%DWM%position_y = u%InputMarkers(IBlade)%Position(2,IElement) + + m%DWM%position_z = u%InputMarkers(IBlade)%Position(3,IElement) + + m%DWM%velocity_wake_mean = 1 + + DO I = 1,p%DWM%RTPD%upwindturbine_number + m%DWM%DWM_tb%Aerodyn_turbine_num = I + + CALL DWM_phase1( Time, m%DWM_Inputs, p%DWM, x%DWM, xd%DWM, z%DWM, & + O%DWM, m%DWM_Outputs, m%DWM, ErrStatLcl, ErrMessLcl ) + + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput/DWM_phase1' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + m%DWM%velocity_wake_mean = (1-((1-m%DWM%velocity_wake_mean)**2 + (1-m%DWM%shifted_velocity_aerodyn)**2)**0.5) + END DO + + m%DWM%velocity_wake_mean = m%DWM%velocity_wake_mean * p%DWM%Wind_file_Mean_u + + VelocityVec(1) = (VelocityVec(1) - p%DWM%Wind_file_Mean_u)*(m%DWM_Inputs%Upwind_result%upwind_small_TI(1)/p%DWM%TI_amb) & + + m%DWM%velocity_wake_mean + + END IF + END IF + + !------------------------DWM PHASE 2----------------------------------------------- + IF (Time > 50.00 ) THEN + m%DWM%U_velocity = VelocityVec(1) + m%DWM%V_velocity = VelocityVec(2) + m%DWM%NacYaw = m%Rotor%YawAng + m%DWM%DWM_tb%Blade_index = IBlade + m%DWM%DWM_tb%Element_index = IElement + + CALL DWM_phase2( Time, m%DWM_Inputs, p%DWM, x%DWM, xd%DWM, z%DWM, O%DWM, m%DWM_Outputs, m%DWM, ErrStatLcl, ErrMessLcl ) + + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput/DWM_phase1' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + !CALL CalVelScale(VelocityVec(1),VelocityVec(2),m%DWM_Outputs,z%DWM) + + !CALL turbine_average_velocity( VelocityVec(1), IBlade, IElement, m%DWM_Outputs,x%DWM,z%DWM) + END IF + END IF ! UseDWM + + !----------------------------------------------------------------------------------------------------------------------- + + ! NOTE: VelocityVec is freestream with disturbances from Tower Shadow and Wakes (DWM) + VelNormalToRotor2 = ( VelocityVec(3) * m%Rotor%STilt + (VelocityVec(1) * m%Rotor%CYaw & + - VelocityVec(2) * m%Rotor%SYaw) * m%Rotor%CTilt )**2 + + !------------------------------------------------------------------------------------------- + ! Normal and tangential velocities from wind and relative blade motion + !------------------------------------------------------------------------------------------- + tang_Vector = - SPitch*u%InputMarkers(IBlade)%Orientation(1,:,IElement) & + & + CPitch*u%InputMarkers(IBlade)%Orientation(2,:,IElement) + norm_Vector = CPitch*u%InputMarkers(IBlade)%Orientation(1,:,IElement) & + & + SPitch*u%InputMarkers(IBlade)%Orientation(2,:,IElement) + + VTTotal = DOT_PRODUCT( tang_Vector, VelocityVec - u%InputMarkers(IBlade)%TranslationVel(:,IElement) ) + VTElement = - DOT_PRODUCT( tang_Vector, u%InputMarkers(IBlade)%TranslationVel(:,IElement) ) + VNElement = - DOT_PRODUCT( norm_Vector, u%InputMarkers(IBlade)%TranslationVel(:,IElement ) ) + + VTWind = DOT_PRODUCT( tang_Vector, VelocityVec) + VNWind = DOT_PRODUCT( norm_Vector, VelocityVec) + + !------------------------------------------------------------------------------------------- + ! Get blade element forces and induced velocity + !------------------------------------------------------------------------------------------- + ! --------------------------------------------------------------------------------} + ! --- Setting Element% values: W2, Alpha, A, AP + ! --------------------------------------------------------------------------------{ + ! --- BEM + CALL ELEM_INDUCTIONS( p, m, ErrStatLcl, ErrMessLcl, & + AzimuthAngle, rLocal, IElement, IBlade, VelNormalToRotor2, VTTotal, VNWind, & + VNElement, m%NoLoadsCalculated) + ! Normal and tangential induced velocities + VN_ind = - VNWind * m%Element%A (IElement, IBLADE) + VT_ind = VTTotal * m%Element%AP(IElement, IBLADE) + + ! Cumulative (integrated) induction over the blades + m%InducedVel%SumInfl = m%InducedVel%SumInfl - VN_IND * RLOCAL * p%Blade%DR(IElement) + + ! --- Total flow velocity at the blade element + VN = VN_IND + VNWind + VNElement ! Normal velocity : Indution + Wind + Rel. blade vel + VT = VT_IND + VTTotal ! Tangential velocity : Indution + (Wind + Rel. blade vel) + + PHI = ATAN2( VN, VT) ! Flow angle [rad] + m%Element%ALPHA(IElement,IBlade) = PHI - m%Element%PitNow(IElement,IBlade) ! Angle of attack [rad] + CALL MPI2PI ( m%Element%ALPHA(IElement,IBlade) ) + m%Element%W2(IElement,IBlade) = VN * VN + VT * VT ! Relative velocity norm + + CALL ELEMFRC2( p, m, ErrStatLcl, ErrMessLcl, IElement, IBlade, & + DFN, DFT, PMA, m%NoLoadsCalculated, phi ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + !------------------------------------------------------------------------------------------- + ! Set up dynamic inflow parameters + !------------------------------------------------------------------------------------------- + IF ( p%DynInfl .OR. m%DynInit ) THEN + CALL GetRM (P, m, ErrStatLcl, ErrMessLcl, & + rLocal, DFN, DFT, AzimuthAngle, IElement, IBlade) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ENDIF + + IF (p%UseDWM) THEN + m%DWM%Nforce(IElement,IBlade) = DFN ! 12.4.2014 add by yh + END IF ! UseDWM + + m%StoredForces(1,IElement,IBlade) = ( DFN*CPitch + DFT*SPitch ) / p%Blade%DR(IElement) + m%StoredForces(2,IElement,IBlade) = ( DFN*SPitch - DFT*CPitch ) / p%Blade%DR(IElement) + m%StoredForces(3,IElement,IBlade) = 0.0 + + m%StoredMoments(1,IElement,IBlade) = 0.0 + m%StoredMoments(2,IElement,IBlade) = 0.0 + m%StoredMoments(3,IElement,IBlade) = PMA / p%Blade%DR(IElement) + +! DO IBlade=1,p%NumBl +! DO IElement=1,p%Element%Nelm +! y%OutputLoads(IBlade)%Force(:,IElement) = m%StoredForces(:,IElement,IBlade) +! y%OutputLoads(IBlade)%Moment(:,IElement) = m%StoredMoments(:,IElement,IBlade) +! ENDDO +!! ENDDO + + ! save velocities for output, if requested + + IF ( m%ElOut%WndElPrList(IElement) > 0 ) THEN + m%ElOut%SaveVX( m%ElOut%WndElPrList(IElement), IBlade ) = VelocityVec(1) + m%ElOut%SaveVY( m%ElOut%WndElPrList(IElement), IBlade ) = VelocityVec(2) + m%ElOut%SaveVZ( m%ElOut%WndElPrList(IElement), IBlade ) = VelocityVec(3) + ENDIF + + + END DO !IElement + + IF ( IBlade == 1 .AND. p%ElemPrn ) THEN + m%ElOut%VXSAV = VelocityVec(1) + m%ElOut%VYSAV = VelocityVec(2) + m%ElOut%VZSAV = VelocityVec(3) + ENDIF + + + END DO !IBlade + + m%NoLoadsCalculated = .FALSE. + + DO IBlade=1,p%NumBl + DO IElement=1,p%Element%Nelm + y%OutputLoads(IBlade)%Force(:,IElement) = m%StoredForces(:,IElement,IBlade) + y%OutputLoads(IBlade)%Moment(:,IElement) = m%StoredMoments(:,IElement,IBlade) + ENDDO + ENDDO + + + !------------------------DWM PHASE 3----------------------------------------------- + IF (p%UseDWM) THEN + + IF (Time > 50.00 ) THEN !BJJ: why is 50 hard-coded here and above??? + + !m%DWM%Nforce(:,:) = m%DWM%DFN_DWM(:,:) + CALL DWM_phase3( Time, m%DWM_Inputs, p%DWM, x%DWM, xd%DWM, z%DWM, O%DWM, m%DWM_Outputs, m%DWM, ErrStatLcl, ErrMessLcl ) + + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'AD14_CalcOutput/DWM_phase3' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + !CALL filter_average_induction_factor( AD14_ParameterType, DWM_ConstraintStateType, m%DWM_Outputs ) + END IF + END IF !UseDWM + + !----------------------------------------------------------------------------------- + + + + + + + ! Loop through all the tower nodes to calculate the aerodynamic loads on the tower if aerodynamics were requested. + + IF ( p%TwrProps%CalcTwrAero ) THEN + + DO Node=1,u%Twr_InputMarkers%Nnodes + + + ! Calculate the aerodynamic load on this tower node: TwrAeroLoads ( p, Node, NodeDCMGbl, NodeVelGbl, NodeWindVelGbl, NodeFrcGbl ) + + CALL TwrAeroLoads ( p, Node, u%Twr_InputMarkers%Orientation(:,:,Node), u%Twr_InputMarkers%TranslationVel(:,Node) & + , u%InflowVelocity(:,Node+p%NumBl*p%Element%NElm), y%Twr_OutputLoads%Force(:,Node) ) + + END DO ! Node + + END IF ! ( p%TwrProps%CalcTwrAero ) + + !................................................................................................ + + + CALL ElemOut(time, P, m ) + + CALL CleanUp ( ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE CleanUp ( ) + + + ! This subroutine cleans up the parent routine before exiting. + + + ! ! Deallocate the IfW_Inputs%Position array if it had been allocated. + ! + !CALL IfW_DestroyInput( IfW_Inputs, ErrStatLcl, ErrMessLcl ) + + + RETURN + + END SUBROUTINE CleanUp + + +END SUBROUTINE AD14_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE AeroDyn14 +!********************************************************************************************************************************** + diff --git a/OpenFAST/modules/aerodyn14/src/AeroDyn14_Types.f90 b/OpenFAST/modules/aerodyn14/src/AeroDyn14_Types.f90 new file mode 100644 index 000000000..138de427c --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/AeroDyn14_Types.f90 @@ -0,0 +1,16900 @@ +!STARTOFREGISTRYGENERATEDFILE 'AeroDyn14_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 +!********************************************************************************************************************************* +! AeroDyn14_Types +!................................................................................................................................. +! This file is part of AeroDyn14. +! +! 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 AeroDyn14. 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 AeroDyn14_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE IfW_UniformWind_Types +USE IfW_FFWind_Base_Types +USE IfW_TSFFWind_Types +USE IfW_BladedFFWind_Types +USE IfW_HAWCWind_Types +USE IfW_UserWind_Types +USE IfW_4Dext_Types +USE Lidar_Types +USE InflowWind_Types +USE DWM_Types +USE NWTC_Library +IMPLICIT NONE +! ========= Marker ======= + TYPE, PUBLIC :: Marker + REAL(ReKi) , DIMENSION(1:3) :: Position + REAL(ReKi) , DIMENSION(1:3,1:3) :: Orientation + REAL(ReKi) , DIMENSION(1:3) :: TranslationVel + REAL(ReKi) , DIMENSION(1:3) :: RotationVel + END TYPE Marker +! ======================= +! ========= AeroConfig ======= + TYPE, PUBLIC :: AeroConfig + TYPE(Marker) , DIMENSION(:), ALLOCATABLE :: Blade + TYPE(Marker) :: Hub + TYPE(Marker) :: RotorFurl + TYPE(Marker) :: Nacelle + TYPE(Marker) :: TailFin + TYPE(Marker) :: Tower + TYPE(Marker) :: SubStructure + TYPE(Marker) :: Foundation + REAL(ReKi) :: BladeLength + END TYPE AeroConfig +! ======================= +! ========= AirFoil ======= + TYPE, PUBLIC :: AirFoil + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AL + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CD + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CL + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CM + REAL(ReKi) :: PMC + REAL(ReKi) :: MulTabLoc + END TYPE AirFoil +! ======================= +! ========= AirFoilParms ======= + TYPE, PUBLIC :: AirFoilParms + INTEGER(IntKi) :: MaxTable = 20 + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NTables + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NLift + INTEGER(IntKi) :: NumCL + INTEGER(IntKi) :: NumFoil + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NFoil + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MulTabMet + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: FoilNm + END TYPE AirFoilParms +! ======================= +! ========= Beddoes ======= + TYPE, PUBLIC :: Beddoes + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ADOT + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ADOT1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AFE + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AFE1 + REAL(ReKi) :: AN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ANE + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ANE1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AOD + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AOL + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: BEDSEP + LOGICAL , DIMENSION(:,:), ALLOCATABLE :: OLDSEP + REAL(ReKi) :: CC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CDO + REAL(ReKi) :: CMI + REAL(ReKi) :: CMQ + REAL(ReKi) :: CN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNA + REAL(ReKi) :: CNCP + REAL(ReKi) :: CNIQ + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNP + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNP1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNPD + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNPD1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNPOT + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNPOT1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNS + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNSL + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CNV + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CVN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CVN1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DF + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DFAFE + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DFAFE1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DFC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DPP + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DQ + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DQP + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DQP1 + REAL(ReKi) :: DS + REAL(ReKi) :: FK + REAL(ReKi) :: FP + REAL(ReKi) :: FPC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FSP + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FSP1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FSPC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FSPC1 + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: FTB + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: FTBC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDCNV + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDDF + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDDFC + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDDN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDDPP + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDDQ + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDTAU + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDXN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLDYN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: QX + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: QX1 + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TAU + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: XN + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: YN + LOGICAL :: SHIFT + LOGICAL :: VOR + END TYPE Beddoes +! ======================= +! ========= BeddoesParms ======= + TYPE, PUBLIC :: BeddoesParms + REAL(ReKi) :: AS !< Speed of sound for mach num calc [-] + REAL(ReKi) :: TF !< Time constant applied to loc of separation pt [-] + REAL(ReKi) :: TP !< Time constant for pressure lag [-] + REAL(ReKi) :: TV !< Time constant for strength and shed of vortex [-] + REAL(ReKi) :: TVL !< Nondim time of transit of vort moving across airfoil surf [-] + END TYPE BeddoesParms +! ======================= +! ========= BladeParms ======= + TYPE, PUBLIC :: BladeParms + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: C !< Chord of each blade element from input file [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DR !< Span-wise width of elem (len of elem ctred at RELM(i) [-] + REAL(ReKi) :: R !< Rotor radius [-] + REAL(ReKi) :: BladeLength !< Blade Length [-] + END TYPE BladeParms +! ======================= +! ========= DynInflow ======= + TYPE, PUBLIC :: DynInflow + REAL(ReKi) , DIMENSION(1:6,1:4) :: dAlph_dt + REAL(ReKi) , DIMENSION(3:6,1:4) :: dBeta_dt + REAL(ReKi) :: DTO + REAL(ReKi) , DIMENSION(1:6) :: old_Alph + REAL(ReKi) , DIMENSION(3:6) :: old_Beta + REAL(ReKi) :: old_LmdM + REAL(ReKi) :: oldKai + REAL(ReKi) , DIMENSION(1:6) :: PhiLqC + REAL(ReKi) , DIMENSION(3:6) :: PhiLqS + REAL(ReKi) :: Pzero + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: RMC_SAVE + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: RMS_SAVE + REAL(ReKi) :: TipSpeed + REAL(ReKi) :: totalInf + REAL(ReKi) :: Vparam + REAL(ReKi) :: Vtotal + REAL(ReKi) , DIMENSION(1:6) :: xAlpha + REAL(ReKi) , DIMENSION(3:6) :: xBeta + REAL(ReKi) :: xKai + REAL(ReKi) :: XLAMBDA_M + REAL(ReKi) , DIMENSION(1:6,1:6) :: xLcos + REAL(ReKi) , DIMENSION(3:6,3:6) :: xLsin + INTEGER(IntKi) , DIMENSION(1:6,1:6) :: MminR + INTEGER(IntKi) , DIMENSION(1:6,1:6) :: MminusR + INTEGER(IntKi) , DIMENSION(1:6,1:6) :: MplusR + REAL(ReKi) , DIMENSION(1:6,1:6) :: GAMMA + END TYPE DynInflow +! ======================= +! ========= DynInflowParms ======= + TYPE, PUBLIC :: DynInflowParms + INTEGER(IntKi) :: MAXINFLO = 2 + REAL(ReKi) , DIMENSION(1:6) :: xMinv + END TYPE DynInflowParms +! ======================= +! ========= Element ======= + TYPE, PUBLIC :: Element + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< - [Axial induction factor] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AP !< - [Tangential induction factor] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ALPHA !< - [Angle of attack] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: W2 !< - [Relative velocity norm ] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLD_A_NS + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: OLD_AP_NS + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PITNOW !< - [Current pitch angle - Based on blade orientation (to verify)] + END TYPE Element +! ======================= +! ========= ElementParms ======= + TYPE, PUBLIC :: ElementParms + INTEGER(IntKi) :: NELM !< - [Number of elements (constant)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TWIST !< - [Airfoil twist angle (constant)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RELM !< - [Radius of element (constant)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HLCNST !< - [Hub loss constant B/2*(r-rh)/rh (constant)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TLCNST !< - [Tip loss constant B/2*(R-r)/R (constant) ] + END TYPE ElementParms +! ======================= +! ========= ElOutParms ======= + TYPE, PUBLIC :: ElOutParms + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AAA + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AAP + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ALF + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CDD + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CLL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMM + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CNN + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CTT + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DFNSAV + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DFTSAV + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DynPres + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PMM + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PITSAV + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ReyNum + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Gamma !< - [Circulation along the span, 1/2 c Vrel Cl] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SaveVX + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SaveVY + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SaveVZ + REAL(ReKi) :: VXSAV + REAL(ReKi) :: VYSAV + REAL(ReKi) :: VZSAV + INTEGER(IntKi) :: NumWndElOut !< Number of Blade Elements [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: WndElPrList + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: WndElPrNum + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ElPrList + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ElPrNum + INTEGER(IntKi) :: NumElOut !< Number of Blade Elements [-] + END TYPE ElOutParms +! ======================= +! ========= InducedVel ======= + TYPE, PUBLIC :: InducedVel + REAL(ReKi) :: SumInFl = 0 + END TYPE InducedVel +! ======================= +! ========= InducedVelParms ======= + TYPE, PUBLIC :: InducedVelParms + REAL(ReKi) :: AToler !< Convergence tolerance for induction factor [-] + REAL(ReKi) :: EqAIDmult !< Multiplier for drag term in axial-induction equation. [-] + LOGICAL :: EquilDA !< False unless DB or DA appended to EQUIL [-] + LOGICAL :: EquilDT !< False unless DB or DT appended to EQUIL [-] + LOGICAL :: TLoss !< Tip-loss model (EQUIL only) [PRANDtl, GTECH, or NONE] [-] + LOGICAL :: GTech !< Tip-loss model (EQUIL only) [PRANDtl, GTECH, or NONE] [-] + LOGICAL :: HLoss !< Hub-loss model (EQUIL only) [PRANDtl or NONE] [-] + END TYPE InducedVelParms +! ======================= +! ========= Rotor ======= + TYPE, PUBLIC :: Rotor + REAL(ReKi) :: AVGINFL !< average induced velocity at the previous time [-] + REAL(ReKi) :: CTILT + REAL(ReKi) :: CYaw + REAL(ReKi) :: REVS + REAL(ReKi) :: STILT + REAL(ReKi) :: SYaw + REAL(ReKi) :: TILT + REAL(ReKi) :: YawAng + REAL(ReKi) :: YawVEL + END TYPE Rotor +! ======================= +! ========= RotorParms ======= + TYPE, PUBLIC :: RotorParms + REAL(ReKi) :: HH + END TYPE RotorParms +! ======================= +! ========= TwrPropsParms ======= + TYPE, PUBLIC :: TwrPropsParms + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrHtFr + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrWid + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TwrCD + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrRe + REAL(ReKi) , DIMENSION(1:3) :: VTwr + REAL(ReKi) :: Tower_Wake_Constant + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NTwrCDCol !< The tower CD column that represents a particular twr ht [-] + INTEGER(IntKi) :: NTwrHT !< The number of tower height rows in the table [-] + INTEGER(IntKi) :: NTwrRe !< The number of tower Re entry rows in the table [-] + INTEGER(IntKi) :: NTwrCD !< The number of tower CD columns in the table [-] + LOGICAL :: TwrPotent !< Tower influence model [-] + LOGICAL :: TwrShadow !< Tower shadow model [-] + REAL(ReKi) :: ShadHWid !< Tower-shadow half width [m] + REAL(ReKi) :: TShadC1 !< Tower-shadow constant [-] + REAL(ReKi) :: TShadC2 !< Tower-shadow constant [-] + REAL(ReKi) :: TwrShad !< Tower-shadow velocity deficit [-] + LOGICAL :: PJM_Version !< Only true if new tower influence model, by PJM [-] + CHARACTER(1024) :: TwrFile !< Tower data file name [-] + REAL(ReKi) :: T_Shad_Refpt !< Tower-shadow reference point [m] + LOGICAL :: CalcTwrAero !< Flag to tell AeroDyn to calculate drag on the tower [m] + INTEGER(IntKi) :: NumTwrNodes !< Number of ElastoDyn tower nodes. Tower drag will be computed at those points. [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrNodeWidth !< The width (diameter) of the tower at the ElastoDyn node locations. [-] + END TYPE TwrPropsParms +! ======================= +! ========= Wind ======= + TYPE, PUBLIC :: Wind + REAL(ReKi) :: ANGFLW + REAL(ReKi) :: CDEL + REAL(ReKi) :: VROTORX + REAL(ReKi) :: VROTORY + REAL(ReKi) :: VROTORZ + REAL(ReKi) :: SDEL + END TYPE Wind +! ======================= +! ========= WindParms ======= + TYPE, PUBLIC :: WindParms + REAL(ReKi) :: Rho !< Air density [kg/m^3] + REAL(ReKi) :: KinVisc !< Kinematic air viscosity [(m^2/sec)] + END TYPE WindParms +! ======================= +! ========= PositionType ======= + TYPE, PUBLIC :: PositionType + REAL(ReKi) , DIMENSION(1:3) :: Pos !< X,Y,Z coordinate of a point [-] + END TYPE PositionType +! ======================= +! ========= OrientationType ======= + TYPE, PUBLIC :: OrientationType + REAL(ReKi) , DIMENSION(1:3,1:3) :: Orient !< Direction Cosine Matrix [-] + END TYPE OrientationType +! ======================= +! ========= AD14_InitInputType ======= + TYPE, PUBLIC :: AD14_InitInputType + CHARACTER(1024) :: Title !< Title [-] + CHARACTER(1024) :: OutRootName + CHARACTER(1024) :: ADFileName !< AeroDyn file name [-] + LOGICAL :: WrSumFile !< T/F: Write an AeroDyn summary [-] + INTEGER(IntKi) :: NumBl !< Number of Blades [-] + REAL(ReKi) :: BladeLength !< Blade Length [-] + LOGICAL :: LinearizeFlag + LOGICAL :: UseDWM = .FALSE. !< flag to determine if DWM module should be used [-] + TYPE(AeroConfig) :: TurbineComponents + INTEGER(IntKi) :: NumTwrNodes !< Number of ElastoDyn tower nodes. Tower drag will be computed at those points. [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TwrNodeLocs !< Location of ElastoDyn tower nodes with respect to the inertial origin. [-] + REAL(ReKi) :: HubHt !< hub height wrt inertial origin [m] + TYPE(DWM_InitInputType) :: DWM + END TYPE AD14_InitInputType +! ======================= +! ========= AD14_InitOutputType ======= + TYPE, PUBLIC :: AD14_InitOutputType + TYPE(ProgDesc) :: Ver !< version information [-] + TYPE(DWM_InitOutputType) :: DWM + REAL(ReKi) :: AirDens !< Air density [kg/m^3] + END TYPE AD14_InitOutputType +! ======================= +! ========= AD14_ContinuousStateType ======= + TYPE, PUBLIC :: AD14_ContinuousStateType + TYPE(DWM_ContinuousStateType) :: DWM + END TYPE AD14_ContinuousStateType +! ======================= +! ========= AD14_DiscreteStateType ======= + TYPE, PUBLIC :: AD14_DiscreteStateType + TYPE(DWM_DiscreteStateType) :: DWM + END TYPE AD14_DiscreteStateType +! ======================= +! ========= AD14_ConstraintStateType ======= + TYPE, PUBLIC :: AD14_ConstraintStateType + TYPE(DWM_ConstraintStateType) :: DWM + END TYPE AD14_ConstraintStateType +! ======================= +! ========= AD14_OtherStateType ======= + TYPE, PUBLIC :: AD14_OtherStateType + TYPE(DWM_OtherStateType) :: DWM !< variables for DWM module [-] + END TYPE AD14_OtherStateType +! ======================= +! ========= AD14_MiscVarType ======= + TYPE, PUBLIC :: AD14_MiscVarType + TYPE(DWM_MiscVarType) :: DWM !< variables for DWM module [-] + TYPE(DWM_InputType) :: DWM_Inputs + TYPE(DWM_OutputType) :: DWM_Outputs + REAL(DbKi) :: DT !< actual Time step [seconds] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ElPrNum + REAL(DbKi) :: OldTime + REAL(ReKi) :: HubLoss = 1 + REAL(ReKi) :: Loss = 1 + REAL(ReKi) :: TipLoss = 1 + REAL(ReKi) :: TLpt7 + LOGICAL :: FirstPassGTL = .TRUE. + LOGICAL :: SuperSonic = .FALSE. + LOGICAL :: AFLAGVinderr = .FALSE. + LOGICAL :: AFLAGTwrInflu = .FALSE. + LOGICAL :: OnePassDynDbg = .TRUE. + LOGICAL :: NoLoadsCalculated = .TRUE. + INTEGER(IntKi) :: NERRORS = 0 + TYPE(AirFoil) :: AirFoil + TYPE(Beddoes) :: Beddoes + TYPE(DynInflow) :: DynInflow + TYPE(Element) :: Element + TYPE(Rotor) :: Rotor + TYPE(Wind) :: Wind + TYPE(InducedVel) :: InducedVel + TYPE(ElOutParms) :: ElOut + LOGICAL :: Skew + LOGICAL :: DynInit !< FALSE=EQUIL, TRUE=DYNIN [-] + LOGICAL :: FirstWarn !< If it's the first warning about AeroDyn not recalculating loads [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: StoredForces + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: StoredMoments + END TYPE AD14_MiscVarType +! ======================= +! ========= AD14_ParameterType ======= + TYPE, PUBLIC :: AD14_ParameterType + CHARACTER(1024) :: Title !< Title [-] + LOGICAL :: SIUnit + LOGICAL :: Echo = .FALSE. + LOGICAL :: MultiTab + LOGICAL :: LinearizeFlag + LOGICAL :: OutputPlottingInfo = .FALSE. + LOGICAL :: UseDWM = .FALSE. !< flag to determine if DWM module should be used [-] + REAL(ReKi) :: TwoPiNB !< 2*pi/num of blades [-] + INTEGER(IntKi) :: NumBl !< Number of Blades [-] + INTEGER(IntKi) :: NBlInpSt !< Number of Blade Input Stations [-] + LOGICAL :: ElemPrn + LOGICAL :: DStall !< FALSE=Steady, TRUE=BEDDOES [-] + LOGICAL :: PMoment !< FALSE=NO_CM, TRUE=USE_CM [-] + LOGICAL :: Reynolds + LOGICAL :: DynInfl !< FALSE=EQUIL, TRUE=DYNIN [-] + LOGICAL :: Wake !< False unless WAKE or SWIRL [-] + LOGICAL :: Swirl !< False unless WAKE or SWIRL [-] + REAL(DbKi) :: DtAero !< Time interval for aerodynamic calculations [-] + REAL(ReKi) :: HubRad !< Hub radius [m] + INTEGER(IntKi) :: UnEc = -1 + INTEGER(IntKi) :: UnElem = -1 + INTEGER(IntKi) :: UnWndOut = -1 + INTEGER(IntKi) :: MAXICOUNT = 1000 + LOGICAL :: WrOptFile = .TRUE. !< T/F: Write an AeroDyn summary [-] + INTEGER(IntKi) :: DEFAULT_Wind = -1 + TYPE(AirFoilParms) :: AirFoil + TYPE(BladeParms) :: Blade + TYPE(BeddoesParms) :: Beddoes + TYPE(DynInflowParms) :: DynInflow + TYPE(ElementParms) :: Element + TYPE(TwrPropsParms) :: TwrProps + TYPE(InducedVelParms) :: InducedVel + TYPE(WindParms) :: Wind + TYPE(RotorParms) :: Rotor + TYPE(DWM_ParameterType) :: DWM + END TYPE AD14_ParameterType +! ======================= +! ========= AD14_InputType ======= + TYPE, PUBLIC :: AD14_InputType + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: InputMarkers !< Input Forces and positions for the blades (mesh) for each blade [-] + TYPE(MeshType) :: Twr_InputMarkers !< Input Forces and positions for the tower (mesh) [-] + TYPE(AeroConfig) :: TurbineComponents !< Current locations of components [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MulTabLoc + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: InflowVelocity !< U,V,W wind inflow speeds at all locations on the Inputmarker and Twr_InputMarker meshes [m/s] + REAL(ReKi) , DIMENSION(1:3) :: AvgInfVel !< an average disk velocity (depends on wind type and should be removed) [m/s] + END TYPE AD14_InputType +! ======================= +! ========= AD14_OutputType ======= + TYPE, PUBLIC :: AD14_OutputType + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: OutputLoads !< Output Loads (mesh) for each blade [-] + TYPE(MeshType) :: Twr_OutputLoads !< Tower Output Loads (mesh) [-] + END TYPE AD14_OutputType +! ======================= +CONTAINS + SUBROUTINE AD14_CopyMarker( SrcMarkerData, DstMarkerData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Marker), INTENT(IN) :: SrcMarkerData + TYPE(Marker), INTENT(INOUT) :: DstMarkerData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_CopyMarker' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMarkerData%Position = SrcMarkerData%Position + DstMarkerData%Orientation = SrcMarkerData%Orientation + DstMarkerData%TranslationVel = SrcMarkerData%TranslationVel + DstMarkerData%RotationVel = SrcMarkerData%RotationVel + END SUBROUTINE AD14_CopyMarker + + SUBROUTINE AD14_DestroyMarker( MarkerData, ErrStat, ErrMsg ) + TYPE(Marker), INTENT(INOUT) :: MarkerData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyMarker' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyMarker + + SUBROUTINE AD14_PackMarker( 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(Marker), 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 = 'AD14_PackMarker' + ! 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%Position) ! Position + Re_BufSz = Re_BufSz + SIZE(InData%Orientation) ! Orientation + Re_BufSz = Re_BufSz + SIZE(InData%TranslationVel) ! TranslationVel + Re_BufSz = Re_BufSz + SIZE(InData%RotationVel) ! RotationVel + 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%Position,1), UBOUND(InData%Position,1) + ReKiBuf(Re_Xferred) = InData%Position(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%Orientation,2), UBOUND(InData%Orientation,2) + DO i1 = LBOUND(InData%Orientation,1), UBOUND(InData%Orientation,1) + ReKiBuf(Re_Xferred) = InData%Orientation(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%TranslationVel,1), UBOUND(InData%TranslationVel,1) + ReKiBuf(Re_Xferred) = InData%TranslationVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%RotationVel,1), UBOUND(InData%RotationVel,1) + ReKiBuf(Re_Xferred) = InData%RotationVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_PackMarker + + SUBROUTINE AD14_UnPackMarker( 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(Marker), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_UnPackMarker' + ! 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%Position,1) + i1_u = UBOUND(OutData%Position,1) + DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) + OutData%Position(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%Orientation,1) + i1_u = UBOUND(OutData%Orientation,1) + i2_l = LBOUND(OutData%Orientation,2) + i2_u = UBOUND(OutData%Orientation,2) + DO i2 = LBOUND(OutData%Orientation,2), UBOUND(OutData%Orientation,2) + DO i1 = LBOUND(OutData%Orientation,1), UBOUND(OutData%Orientation,1) + OutData%Orientation(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%TranslationVel,1) + i1_u = UBOUND(OutData%TranslationVel,1) + DO i1 = LBOUND(OutData%TranslationVel,1), UBOUND(OutData%TranslationVel,1) + OutData%TranslationVel(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%RotationVel,1) + i1_u = UBOUND(OutData%RotationVel,1) + DO i1 = LBOUND(OutData%RotationVel,1), UBOUND(OutData%RotationVel,1) + OutData%RotationVel(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_UnPackMarker + + SUBROUTINE AD14_CopyAeroConfig( SrcAeroConfigData, DstAeroConfigData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AeroConfig), INTENT(IN) :: SrcAeroConfigData + TYPE(AeroConfig), INTENT(INOUT) :: DstAeroConfigData + 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 = 'AD14_CopyAeroConfig' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcAeroConfigData%Blade)) THEN + i1_l = LBOUND(SrcAeroConfigData%Blade,1) + i1_u = UBOUND(SrcAeroConfigData%Blade,1) + IF (.NOT. ALLOCATED(DstAeroConfigData%Blade)) THEN + ALLOCATE(DstAeroConfigData%Blade(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroConfigData%Blade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcAeroConfigData%Blade,1), UBOUND(SrcAeroConfigData%Blade,1) + CALL AD14_Copymarker( SrcAeroConfigData%Blade(i1), DstAeroConfigData%Blade(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL AD14_Copymarker( SrcAeroConfigData%Hub, DstAeroConfigData%Hub, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%RotorFurl, DstAeroConfigData%RotorFurl, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%Nacelle, DstAeroConfigData%Nacelle, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%TailFin, DstAeroConfigData%TailFin, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%Tower, DstAeroConfigData%Tower, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%SubStructure, DstAeroConfigData%SubStructure, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copymarker( SrcAeroConfigData%Foundation, DstAeroConfigData%Foundation, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstAeroConfigData%BladeLength = SrcAeroConfigData%BladeLength + END SUBROUTINE AD14_CopyAeroConfig + + SUBROUTINE AD14_DestroyAeroConfig( AeroConfigData, ErrStat, ErrMsg ) + TYPE(AeroConfig), INTENT(INOUT) :: AeroConfigData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyAeroConfig' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(AeroConfigData%Blade)) THEN +DO i1 = LBOUND(AeroConfigData%Blade,1), UBOUND(AeroConfigData%Blade,1) + CALL AD14_Destroymarker( AeroConfigData%Blade(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(AeroConfigData%Blade) +ENDIF + CALL AD14_Destroymarker( AeroConfigData%Hub, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%RotorFurl, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%Nacelle, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%TailFin, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%Tower, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%SubStructure, ErrStat, ErrMsg ) + CALL AD14_Destroymarker( AeroConfigData%Foundation, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyAeroConfig + + SUBROUTINE AD14_PackAeroConfig( 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(AeroConfig), 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 = 'AD14_PackAeroConfig' + ! 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 ! Blade allocated yes/no + IF ( ALLOCATED(InData%Blade) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Blade upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Blade,1), UBOUND(InData%Blade,1) + Int_BufSz = Int_BufSz + 3 ! Blade: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Blade(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Blade + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Blade + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Blade + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Blade + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! Hub: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Hub, ErrStat2, ErrMsg2, .TRUE. ) ! Hub + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Hub + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Hub + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Hub + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! RotorFurl: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%RotorFurl, ErrStat2, ErrMsg2, .TRUE. ) ! RotorFurl + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RotorFurl + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RotorFurl + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RotorFurl + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Nacelle: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Nacelle, ErrStat2, ErrMsg2, .TRUE. ) ! Nacelle + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Nacelle + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Nacelle + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Nacelle + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TailFin: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%TailFin, ErrStat2, ErrMsg2, .TRUE. ) ! TailFin + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TailFin + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TailFin + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TailFin + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Tower: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Tower, ErrStat2, ErrMsg2, .TRUE. ) ! Tower + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Tower + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Tower + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Tower + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SubStructure: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%SubStructure, ErrStat2, ErrMsg2, .TRUE. ) ! SubStructure + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SubStructure + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SubStructure + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SubStructure + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Foundation: size of buffers for each call to pack subtype + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Foundation, ErrStat2, ErrMsg2, .TRUE. ) ! Foundation + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Foundation + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Foundation + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Foundation + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! BladeLength + 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%Blade) ) 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%Blade,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Blade,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Blade,1), UBOUND(InData%Blade,1) + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Blade(i1), ErrStat2, ErrMsg2, OnlySize ) ! Blade + 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 + CALL AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Hub, ErrStat2, ErrMsg2, OnlySize ) ! Hub + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%RotorFurl, ErrStat2, ErrMsg2, OnlySize ) ! RotorFurl + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Nacelle, ErrStat2, ErrMsg2, OnlySize ) ! Nacelle + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%TailFin, ErrStat2, ErrMsg2, OnlySize ) ! TailFin + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Tower, ErrStat2, ErrMsg2, OnlySize ) ! Tower + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%SubStructure, ErrStat2, ErrMsg2, OnlySize ) ! SubStructure + 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 AD14_Packmarker( Re_Buf, Db_Buf, Int_Buf, InData%Foundation, ErrStat2, ErrMsg2, OnlySize ) ! Foundation + 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 + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackAeroConfig + + SUBROUTINE AD14_UnPackAeroConfig( 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(AeroConfig), 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 = 'AD14_UnPackAeroConfig' + ! 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 ! Blade 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%Blade)) DEALLOCATE(OutData%Blade) + ALLOCATE(OutData%Blade(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Blade.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Blade,1), UBOUND(OutData%Blade,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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Blade(i1), ErrStat2, ErrMsg2 ) ! Blade + 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 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Hub, ErrStat2, ErrMsg2 ) ! Hub + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%RotorFurl, ErrStat2, ErrMsg2 ) ! RotorFurl + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Nacelle, ErrStat2, ErrMsg2 ) ! Nacelle + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%TailFin, ErrStat2, ErrMsg2 ) ! TailFin + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Tower, ErrStat2, ErrMsg2 ) ! Tower + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%SubStructure, ErrStat2, ErrMsg2 ) ! SubStructure + 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 AD14_Unpackmarker( Re_Buf, Db_Buf, Int_Buf, OutData%Foundation, ErrStat2, ErrMsg2 ) ! Foundation + 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%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackAeroConfig + + SUBROUTINE AD14_CopyAirFoil( SrcAirFoilData, DstAirFoilData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AirFoil), INTENT(IN) :: SrcAirFoilData + TYPE(AirFoil), INTENT(INOUT) :: DstAirFoilData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_CopyAirFoil' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcAirFoilData%AL)) THEN + i1_l = LBOUND(SrcAirFoilData%AL,1) + i1_u = UBOUND(SrcAirFoilData%AL,1) + i2_l = LBOUND(SrcAirFoilData%AL,2) + i2_u = UBOUND(SrcAirFoilData%AL,2) + IF (.NOT. ALLOCATED(DstAirFoilData%AL)) THEN + ALLOCATE(DstAirFoilData%AL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilData%AL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilData%AL = SrcAirFoilData%AL +ENDIF +IF (ALLOCATED(SrcAirFoilData%CD)) THEN + i1_l = LBOUND(SrcAirFoilData%CD,1) + i1_u = UBOUND(SrcAirFoilData%CD,1) + i2_l = LBOUND(SrcAirFoilData%CD,2) + i2_u = UBOUND(SrcAirFoilData%CD,2) + i3_l = LBOUND(SrcAirFoilData%CD,3) + i3_u = UBOUND(SrcAirFoilData%CD,3) + IF (.NOT. ALLOCATED(DstAirFoilData%CD)) THEN + ALLOCATE(DstAirFoilData%CD(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilData%CD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilData%CD = SrcAirFoilData%CD +ENDIF +IF (ALLOCATED(SrcAirFoilData%CL)) THEN + i1_l = LBOUND(SrcAirFoilData%CL,1) + i1_u = UBOUND(SrcAirFoilData%CL,1) + i2_l = LBOUND(SrcAirFoilData%CL,2) + i2_u = UBOUND(SrcAirFoilData%CL,2) + i3_l = LBOUND(SrcAirFoilData%CL,3) + i3_u = UBOUND(SrcAirFoilData%CL,3) + IF (.NOT. ALLOCATED(DstAirFoilData%CL)) THEN + ALLOCATE(DstAirFoilData%CL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilData%CL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilData%CL = SrcAirFoilData%CL +ENDIF +IF (ALLOCATED(SrcAirFoilData%CM)) THEN + i1_l = LBOUND(SrcAirFoilData%CM,1) + i1_u = UBOUND(SrcAirFoilData%CM,1) + i2_l = LBOUND(SrcAirFoilData%CM,2) + i2_u = UBOUND(SrcAirFoilData%CM,2) + i3_l = LBOUND(SrcAirFoilData%CM,3) + i3_u = UBOUND(SrcAirFoilData%CM,3) + IF (.NOT. ALLOCATED(DstAirFoilData%CM)) THEN + ALLOCATE(DstAirFoilData%CM(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilData%CM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilData%CM = SrcAirFoilData%CM +ENDIF + DstAirFoilData%PMC = SrcAirFoilData%PMC + DstAirFoilData%MulTabLoc = SrcAirFoilData%MulTabLoc + END SUBROUTINE AD14_CopyAirFoil + + SUBROUTINE AD14_DestroyAirFoil( AirFoilData, ErrStat, ErrMsg ) + TYPE(AirFoil), INTENT(INOUT) :: AirFoilData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyAirFoil' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(AirFoilData%AL)) THEN + DEALLOCATE(AirFoilData%AL) +ENDIF +IF (ALLOCATED(AirFoilData%CD)) THEN + DEALLOCATE(AirFoilData%CD) +ENDIF +IF (ALLOCATED(AirFoilData%CL)) THEN + DEALLOCATE(AirFoilData%CL) +ENDIF +IF (ALLOCATED(AirFoilData%CM)) THEN + DEALLOCATE(AirFoilData%CM) +ENDIF + END SUBROUTINE AD14_DestroyAirFoil + + SUBROUTINE AD14_PackAirFoil( 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(AirFoil), 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 = 'AD14_PackAirFoil' + ! 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 ! AL allocated yes/no + IF ( ALLOCATED(InData%AL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AL) ! AL + END IF + Int_BufSz = Int_BufSz + 1 ! CD allocated yes/no + IF ( ALLOCATED(InData%CD) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CD) ! CD + END IF + Int_BufSz = Int_BufSz + 1 ! CL allocated yes/no + IF ( ALLOCATED(InData%CL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CL) ! CL + END IF + Int_BufSz = Int_BufSz + 1 ! CM allocated yes/no + IF ( ALLOCATED(InData%CM) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CM) ! CM + END IF + Re_BufSz = Re_BufSz + 1 ! PMC + Re_BufSz = Re_BufSz + 1 ! MulTabLoc + 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%AL) ) 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%AL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AL,2), UBOUND(InData%AL,2) + DO i1 = LBOUND(InData%AL,1), UBOUND(InData%AL,1) + ReKiBuf(Re_Xferred) = InData%AL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CD) ) 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%CD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CD,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CD,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CD,3), UBOUND(InData%CD,3) + DO i2 = LBOUND(InData%CD,2), UBOUND(InData%CD,2) + DO i1 = LBOUND(InData%CD,1), UBOUND(InData%CD,1) + ReKiBuf(Re_Xferred) = InData%CD(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CL) ) 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%CL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CL,3), UBOUND(InData%CL,3) + DO i2 = LBOUND(InData%CL,2), UBOUND(InData%CL,2) + DO i1 = LBOUND(InData%CL,1), UBOUND(InData%CL,1) + ReKiBuf(Re_Xferred) = InData%CL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CM) ) 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%CM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CM,3), UBOUND(InData%CM,3) + DO i2 = LBOUND(InData%CM,2), UBOUND(InData%CM,2) + DO i1 = LBOUND(InData%CM,1), UBOUND(InData%CM,1) + ReKiBuf(Re_Xferred) = InData%CM(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%PMC + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MulTabLoc + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackAirFoil + + SUBROUTINE AD14_UnPackAirFoil( 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(AirFoil), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_UnPackAirFoil' + ! 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 ! AL 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%AL)) DEALLOCATE(OutData%AL) + ALLOCATE(OutData%AL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AL,2), UBOUND(OutData%AL,2) + DO i1 = LBOUND(OutData%AL,1), UBOUND(OutData%AL,1) + OutData%AL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CD 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%CD)) DEALLOCATE(OutData%CD) + ALLOCATE(OutData%CD(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%CD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CD,3), UBOUND(OutData%CD,3) + DO i2 = LBOUND(OutData%CD,2), UBOUND(OutData%CD,2) + DO i1 = LBOUND(OutData%CD,1), UBOUND(OutData%CD,1) + OutData%CD(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CL 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%CL)) DEALLOCATE(OutData%CL) + ALLOCATE(OutData%CL(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%CL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CL,3), UBOUND(OutData%CL,3) + DO i2 = LBOUND(OutData%CL,2), UBOUND(OutData%CL,2) + DO i1 = LBOUND(OutData%CL,1), UBOUND(OutData%CL,1) + OutData%CL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CM 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%CM)) DEALLOCATE(OutData%CM) + ALLOCATE(OutData%CM(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%CM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CM,3), UBOUND(OutData%CM,3) + DO i2 = LBOUND(OutData%CM,2), UBOUND(OutData%CM,2) + DO i1 = LBOUND(OutData%CM,1), UBOUND(OutData%CM,1) + OutData%CM(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%PMC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MulTabLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackAirFoil + + SUBROUTINE AD14_CopyAirFoilParms( SrcAirFoilParmsData, DstAirFoilParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AirFoilParms), INTENT(IN) :: SrcAirFoilParmsData + TYPE(AirFoilParms), INTENT(INOUT) :: DstAirFoilParmsData + 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 = 'AD14_CopyAirFoilParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstAirFoilParmsData%MaxTable = SrcAirFoilParmsData%MaxTable +IF (ALLOCATED(SrcAirFoilParmsData%NTables)) THEN + i1_l = LBOUND(SrcAirFoilParmsData%NTables,1) + i1_u = UBOUND(SrcAirFoilParmsData%NTables,1) + IF (.NOT. ALLOCATED(DstAirFoilParmsData%NTables)) THEN + ALLOCATE(DstAirFoilParmsData%NTables(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilParmsData%NTables.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilParmsData%NTables = SrcAirFoilParmsData%NTables +ENDIF +IF (ALLOCATED(SrcAirFoilParmsData%NLift)) THEN + i1_l = LBOUND(SrcAirFoilParmsData%NLift,1) + i1_u = UBOUND(SrcAirFoilParmsData%NLift,1) + IF (.NOT. ALLOCATED(DstAirFoilParmsData%NLift)) THEN + ALLOCATE(DstAirFoilParmsData%NLift(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilParmsData%NLift.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilParmsData%NLift = SrcAirFoilParmsData%NLift +ENDIF + DstAirFoilParmsData%NumCL = SrcAirFoilParmsData%NumCL + DstAirFoilParmsData%NumFoil = SrcAirFoilParmsData%NumFoil +IF (ALLOCATED(SrcAirFoilParmsData%NFoil)) THEN + i1_l = LBOUND(SrcAirFoilParmsData%NFoil,1) + i1_u = UBOUND(SrcAirFoilParmsData%NFoil,1) + IF (.NOT. ALLOCATED(DstAirFoilParmsData%NFoil)) THEN + ALLOCATE(DstAirFoilParmsData%NFoil(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilParmsData%NFoil.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilParmsData%NFoil = SrcAirFoilParmsData%NFoil +ENDIF +IF (ALLOCATED(SrcAirFoilParmsData%MulTabMet)) THEN + i1_l = LBOUND(SrcAirFoilParmsData%MulTabMet,1) + i1_u = UBOUND(SrcAirFoilParmsData%MulTabMet,1) + i2_l = LBOUND(SrcAirFoilParmsData%MulTabMet,2) + i2_u = UBOUND(SrcAirFoilParmsData%MulTabMet,2) + IF (.NOT. ALLOCATED(DstAirFoilParmsData%MulTabMet)) THEN + ALLOCATE(DstAirFoilParmsData%MulTabMet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilParmsData%MulTabMet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilParmsData%MulTabMet = SrcAirFoilParmsData%MulTabMet +ENDIF +IF (ALLOCATED(SrcAirFoilParmsData%FoilNm)) THEN + i1_l = LBOUND(SrcAirFoilParmsData%FoilNm,1) + i1_u = UBOUND(SrcAirFoilParmsData%FoilNm,1) + IF (.NOT. ALLOCATED(DstAirFoilParmsData%FoilNm)) THEN + ALLOCATE(DstAirFoilParmsData%FoilNm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAirFoilParmsData%FoilNm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAirFoilParmsData%FoilNm = SrcAirFoilParmsData%FoilNm +ENDIF + END SUBROUTINE AD14_CopyAirFoilParms + + SUBROUTINE AD14_DestroyAirFoilParms( AirFoilParmsData, ErrStat, ErrMsg ) + TYPE(AirFoilParms), INTENT(INOUT) :: AirFoilParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyAirFoilParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(AirFoilParmsData%NTables)) THEN + DEALLOCATE(AirFoilParmsData%NTables) +ENDIF +IF (ALLOCATED(AirFoilParmsData%NLift)) THEN + DEALLOCATE(AirFoilParmsData%NLift) +ENDIF +IF (ALLOCATED(AirFoilParmsData%NFoil)) THEN + DEALLOCATE(AirFoilParmsData%NFoil) +ENDIF +IF (ALLOCATED(AirFoilParmsData%MulTabMet)) THEN + DEALLOCATE(AirFoilParmsData%MulTabMet) +ENDIF +IF (ALLOCATED(AirFoilParmsData%FoilNm)) THEN + DEALLOCATE(AirFoilParmsData%FoilNm) +ENDIF + END SUBROUTINE AD14_DestroyAirFoilParms + + SUBROUTINE AD14_PackAirFoilParms( 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(AirFoilParms), 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 = 'AD14_PackAirFoilParms' + ! 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 ! MaxTable + Int_BufSz = Int_BufSz + 1 ! NTables allocated yes/no + IF ( ALLOCATED(InData%NTables) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NTables upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NTables) ! NTables + END IF + Int_BufSz = Int_BufSz + 1 ! NLift allocated yes/no + IF ( ALLOCATED(InData%NLift) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NLift upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NLift) ! NLift + END IF + Int_BufSz = Int_BufSz + 1 ! NumCL + Int_BufSz = Int_BufSz + 1 ! NumFoil + Int_BufSz = Int_BufSz + 1 ! NFoil allocated yes/no + IF ( ALLOCATED(InData%NFoil) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NFoil upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NFoil) ! NFoil + END IF + Int_BufSz = Int_BufSz + 1 ! MulTabMet allocated yes/no + IF ( ALLOCATED(InData%MulTabMet) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MulTabMet upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MulTabMet) ! MulTabMet + END IF + Int_BufSz = Int_BufSz + 1 ! FoilNm allocated yes/no + IF ( ALLOCATED(InData%FoilNm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FoilNm upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FoilNm)*LEN(InData%FoilNm) ! FoilNm + 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%MaxTable + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NTables) ) 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%NTables,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NTables,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NTables,1), UBOUND(InData%NTables,1) + IntKiBuf(Int_Xferred) = InData%NTables(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NLift) ) 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%NLift,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NLift,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NLift,1), UBOUND(InData%NLift,1) + IntKiBuf(Int_Xferred) = InData%NLift(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumCL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumFoil + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NFoil) ) 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%NFoil,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NFoil,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NFoil,1), UBOUND(InData%NFoil,1) + IntKiBuf(Int_Xferred) = InData%NFoil(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MulTabMet) ) 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%MulTabMet,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabMet,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MulTabMet,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabMet,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MulTabMet,2), UBOUND(InData%MulTabMet,2) + DO i1 = LBOUND(InData%MulTabMet,1), UBOUND(InData%MulTabMet,1) + ReKiBuf(Re_Xferred) = InData%MulTabMet(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FoilNm) ) 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%FoilNm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FoilNm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FoilNm,1), UBOUND(InData%FoilNm,1) + DO I = 1, LEN(InData%FoilNm) + IntKiBuf(Int_Xferred) = ICHAR(InData%FoilNm(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE AD14_PackAirFoilParms + + SUBROUTINE AD14_UnPackAirFoilParms( 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(AirFoilParms), 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 = 'AD14_UnPackAirFoilParms' + ! 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%MaxTable = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NTables 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%NTables)) DEALLOCATE(OutData%NTables) + ALLOCATE(OutData%NTables(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NTables.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NTables,1), UBOUND(OutData%NTables,1) + OutData%NTables(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NLift 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%NLift)) DEALLOCATE(OutData%NLift) + ALLOCATE(OutData%NLift(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NLift.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NLift,1), UBOUND(OutData%NLift,1) + OutData%NLift(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NumCL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumFoil = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NFoil 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%NFoil)) DEALLOCATE(OutData%NFoil) + ALLOCATE(OutData%NFoil(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NFoil.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NFoil,1), UBOUND(OutData%NFoil,1) + OutData%NFoil(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MulTabMet 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%MulTabMet)) DEALLOCATE(OutData%MulTabMet) + ALLOCATE(OutData%MulTabMet(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MulTabMet.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MulTabMet,2), UBOUND(OutData%MulTabMet,2) + DO i1 = LBOUND(OutData%MulTabMet,1), UBOUND(OutData%MulTabMet,1) + OutData%MulTabMet(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FoilNm 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%FoilNm)) DEALLOCATE(OutData%FoilNm) + ALLOCATE(OutData%FoilNm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FoilNm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FoilNm,1), UBOUND(OutData%FoilNm,1) + DO I = 1, LEN(OutData%FoilNm) + OutData%FoilNm(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE AD14_UnPackAirFoilParms + + SUBROUTINE AD14_CopyBeddoes( SrcBeddoesData, DstBeddoesData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Beddoes), INTENT(IN) :: SrcBeddoesData + TYPE(Beddoes), INTENT(INOUT) :: DstBeddoesData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_CopyBeddoes' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcBeddoesData%ADOT)) THEN + i1_l = LBOUND(SrcBeddoesData%ADOT,1) + i1_u = UBOUND(SrcBeddoesData%ADOT,1) + i2_l = LBOUND(SrcBeddoesData%ADOT,2) + i2_u = UBOUND(SrcBeddoesData%ADOT,2) + IF (.NOT. ALLOCATED(DstBeddoesData%ADOT)) THEN + ALLOCATE(DstBeddoesData%ADOT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%ADOT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%ADOT = SrcBeddoesData%ADOT +ENDIF +IF (ALLOCATED(SrcBeddoesData%ADOT1)) THEN + i1_l = LBOUND(SrcBeddoesData%ADOT1,1) + i1_u = UBOUND(SrcBeddoesData%ADOT1,1) + i2_l = LBOUND(SrcBeddoesData%ADOT1,2) + i2_u = UBOUND(SrcBeddoesData%ADOT1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%ADOT1)) THEN + ALLOCATE(DstBeddoesData%ADOT1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%ADOT1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%ADOT1 = SrcBeddoesData%ADOT1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%AFE)) THEN + i1_l = LBOUND(SrcBeddoesData%AFE,1) + i1_u = UBOUND(SrcBeddoesData%AFE,1) + i2_l = LBOUND(SrcBeddoesData%AFE,2) + i2_u = UBOUND(SrcBeddoesData%AFE,2) + IF (.NOT. ALLOCATED(DstBeddoesData%AFE)) THEN + ALLOCATE(DstBeddoesData%AFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%AFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%AFE = SrcBeddoesData%AFE +ENDIF +IF (ALLOCATED(SrcBeddoesData%AFE1)) THEN + i1_l = LBOUND(SrcBeddoesData%AFE1,1) + i1_u = UBOUND(SrcBeddoesData%AFE1,1) + i2_l = LBOUND(SrcBeddoesData%AFE1,2) + i2_u = UBOUND(SrcBeddoesData%AFE1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%AFE1)) THEN + ALLOCATE(DstBeddoesData%AFE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%AFE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%AFE1 = SrcBeddoesData%AFE1 +ENDIF + DstBeddoesData%AN = SrcBeddoesData%AN +IF (ALLOCATED(SrcBeddoesData%ANE)) THEN + i1_l = LBOUND(SrcBeddoesData%ANE,1) + i1_u = UBOUND(SrcBeddoesData%ANE,1) + i2_l = LBOUND(SrcBeddoesData%ANE,2) + i2_u = UBOUND(SrcBeddoesData%ANE,2) + IF (.NOT. ALLOCATED(DstBeddoesData%ANE)) THEN + ALLOCATE(DstBeddoesData%ANE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%ANE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%ANE = SrcBeddoesData%ANE +ENDIF +IF (ALLOCATED(SrcBeddoesData%ANE1)) THEN + i1_l = LBOUND(SrcBeddoesData%ANE1,1) + i1_u = UBOUND(SrcBeddoesData%ANE1,1) + i2_l = LBOUND(SrcBeddoesData%ANE1,2) + i2_u = UBOUND(SrcBeddoesData%ANE1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%ANE1)) THEN + ALLOCATE(DstBeddoesData%ANE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%ANE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%ANE1 = SrcBeddoesData%ANE1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%AOD)) THEN + i1_l = LBOUND(SrcBeddoesData%AOD,1) + i1_u = UBOUND(SrcBeddoesData%AOD,1) + i2_l = LBOUND(SrcBeddoesData%AOD,2) + i2_u = UBOUND(SrcBeddoesData%AOD,2) + IF (.NOT. ALLOCATED(DstBeddoesData%AOD)) THEN + ALLOCATE(DstBeddoesData%AOD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%AOD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%AOD = SrcBeddoesData%AOD +ENDIF +IF (ALLOCATED(SrcBeddoesData%AOL)) THEN + i1_l = LBOUND(SrcBeddoesData%AOL,1) + i1_u = UBOUND(SrcBeddoesData%AOL,1) + i2_l = LBOUND(SrcBeddoesData%AOL,2) + i2_u = UBOUND(SrcBeddoesData%AOL,2) + IF (.NOT. ALLOCATED(DstBeddoesData%AOL)) THEN + ALLOCATE(DstBeddoesData%AOL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%AOL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%AOL = SrcBeddoesData%AOL +ENDIF +IF (ALLOCATED(SrcBeddoesData%BEDSEP)) THEN + i1_l = LBOUND(SrcBeddoesData%BEDSEP,1) + i1_u = UBOUND(SrcBeddoesData%BEDSEP,1) + i2_l = LBOUND(SrcBeddoesData%BEDSEP,2) + i2_u = UBOUND(SrcBeddoesData%BEDSEP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%BEDSEP)) THEN + ALLOCATE(DstBeddoesData%BEDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%BEDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%BEDSEP = SrcBeddoesData%BEDSEP +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDSEP)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDSEP,1) + i1_u = UBOUND(SrcBeddoesData%OLDSEP,1) + i2_l = LBOUND(SrcBeddoesData%OLDSEP,2) + i2_u = UBOUND(SrcBeddoesData%OLDSEP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDSEP)) THEN + ALLOCATE(DstBeddoesData%OLDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDSEP = SrcBeddoesData%OLDSEP +ENDIF + DstBeddoesData%CC = SrcBeddoesData%CC +IF (ALLOCATED(SrcBeddoesData%CDO)) THEN + i1_l = LBOUND(SrcBeddoesData%CDO,1) + i1_u = UBOUND(SrcBeddoesData%CDO,1) + i2_l = LBOUND(SrcBeddoesData%CDO,2) + i2_u = UBOUND(SrcBeddoesData%CDO,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CDO)) THEN + ALLOCATE(DstBeddoesData%CDO(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CDO.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CDO = SrcBeddoesData%CDO +ENDIF + DstBeddoesData%CMI = SrcBeddoesData%CMI + DstBeddoesData%CMQ = SrcBeddoesData%CMQ + DstBeddoesData%CN = SrcBeddoesData%CN +IF (ALLOCATED(SrcBeddoesData%CNA)) THEN + i1_l = LBOUND(SrcBeddoesData%CNA,1) + i1_u = UBOUND(SrcBeddoesData%CNA,1) + i2_l = LBOUND(SrcBeddoesData%CNA,2) + i2_u = UBOUND(SrcBeddoesData%CNA,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNA)) THEN + ALLOCATE(DstBeddoesData%CNA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNA = SrcBeddoesData%CNA +ENDIF + DstBeddoesData%CNCP = SrcBeddoesData%CNCP + DstBeddoesData%CNIQ = SrcBeddoesData%CNIQ +IF (ALLOCATED(SrcBeddoesData%CNP)) THEN + i1_l = LBOUND(SrcBeddoesData%CNP,1) + i1_u = UBOUND(SrcBeddoesData%CNP,1) + i2_l = LBOUND(SrcBeddoesData%CNP,2) + i2_u = UBOUND(SrcBeddoesData%CNP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNP)) THEN + ALLOCATE(DstBeddoesData%CNP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNP = SrcBeddoesData%CNP +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNP1)) THEN + i1_l = LBOUND(SrcBeddoesData%CNP1,1) + i1_u = UBOUND(SrcBeddoesData%CNP1,1) + i2_l = LBOUND(SrcBeddoesData%CNP1,2) + i2_u = UBOUND(SrcBeddoesData%CNP1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNP1)) THEN + ALLOCATE(DstBeddoesData%CNP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNP1 = SrcBeddoesData%CNP1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNPD)) THEN + i1_l = LBOUND(SrcBeddoesData%CNPD,1) + i1_u = UBOUND(SrcBeddoesData%CNPD,1) + i2_l = LBOUND(SrcBeddoesData%CNPD,2) + i2_u = UBOUND(SrcBeddoesData%CNPD,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNPD)) THEN + ALLOCATE(DstBeddoesData%CNPD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNPD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNPD = SrcBeddoesData%CNPD +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNPD1)) THEN + i1_l = LBOUND(SrcBeddoesData%CNPD1,1) + i1_u = UBOUND(SrcBeddoesData%CNPD1,1) + i2_l = LBOUND(SrcBeddoesData%CNPD1,2) + i2_u = UBOUND(SrcBeddoesData%CNPD1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNPD1)) THEN + ALLOCATE(DstBeddoesData%CNPD1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNPD1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNPD1 = SrcBeddoesData%CNPD1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNPOT)) THEN + i1_l = LBOUND(SrcBeddoesData%CNPOT,1) + i1_u = UBOUND(SrcBeddoesData%CNPOT,1) + i2_l = LBOUND(SrcBeddoesData%CNPOT,2) + i2_u = UBOUND(SrcBeddoesData%CNPOT,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNPOT)) THEN + ALLOCATE(DstBeddoesData%CNPOT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNPOT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNPOT = SrcBeddoesData%CNPOT +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNPOT1)) THEN + i1_l = LBOUND(SrcBeddoesData%CNPOT1,1) + i1_u = UBOUND(SrcBeddoesData%CNPOT1,1) + i2_l = LBOUND(SrcBeddoesData%CNPOT1,2) + i2_u = UBOUND(SrcBeddoesData%CNPOT1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNPOT1)) THEN + ALLOCATE(DstBeddoesData%CNPOT1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNPOT1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNPOT1 = SrcBeddoesData%CNPOT1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNS)) THEN + i1_l = LBOUND(SrcBeddoesData%CNS,1) + i1_u = UBOUND(SrcBeddoesData%CNS,1) + i2_l = LBOUND(SrcBeddoesData%CNS,2) + i2_u = UBOUND(SrcBeddoesData%CNS,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNS)) THEN + ALLOCATE(DstBeddoesData%CNS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNS = SrcBeddoesData%CNS +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNSL)) THEN + i1_l = LBOUND(SrcBeddoesData%CNSL,1) + i1_u = UBOUND(SrcBeddoesData%CNSL,1) + i2_l = LBOUND(SrcBeddoesData%CNSL,2) + i2_u = UBOUND(SrcBeddoesData%CNSL,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNSL)) THEN + ALLOCATE(DstBeddoesData%CNSL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNSL = SrcBeddoesData%CNSL +ENDIF +IF (ALLOCATED(SrcBeddoesData%CNV)) THEN + i1_l = LBOUND(SrcBeddoesData%CNV,1) + i1_u = UBOUND(SrcBeddoesData%CNV,1) + i2_l = LBOUND(SrcBeddoesData%CNV,2) + i2_u = UBOUND(SrcBeddoesData%CNV,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CNV)) THEN + ALLOCATE(DstBeddoesData%CNV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CNV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CNV = SrcBeddoesData%CNV +ENDIF +IF (ALLOCATED(SrcBeddoesData%CVN)) THEN + i1_l = LBOUND(SrcBeddoesData%CVN,1) + i1_u = UBOUND(SrcBeddoesData%CVN,1) + i2_l = LBOUND(SrcBeddoesData%CVN,2) + i2_u = UBOUND(SrcBeddoesData%CVN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CVN)) THEN + ALLOCATE(DstBeddoesData%CVN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CVN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CVN = SrcBeddoesData%CVN +ENDIF +IF (ALLOCATED(SrcBeddoesData%CVN1)) THEN + i1_l = LBOUND(SrcBeddoesData%CVN1,1) + i1_u = UBOUND(SrcBeddoesData%CVN1,1) + i2_l = LBOUND(SrcBeddoesData%CVN1,2) + i2_u = UBOUND(SrcBeddoesData%CVN1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%CVN1)) THEN + ALLOCATE(DstBeddoesData%CVN1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%CVN1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%CVN1 = SrcBeddoesData%CVN1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%DF)) THEN + i1_l = LBOUND(SrcBeddoesData%DF,1) + i1_u = UBOUND(SrcBeddoesData%DF,1) + i2_l = LBOUND(SrcBeddoesData%DF,2) + i2_u = UBOUND(SrcBeddoesData%DF,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DF)) THEN + ALLOCATE(DstBeddoesData%DF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DF = SrcBeddoesData%DF +ENDIF +IF (ALLOCATED(SrcBeddoesData%DFAFE)) THEN + i1_l = LBOUND(SrcBeddoesData%DFAFE,1) + i1_u = UBOUND(SrcBeddoesData%DFAFE,1) + i2_l = LBOUND(SrcBeddoesData%DFAFE,2) + i2_u = UBOUND(SrcBeddoesData%DFAFE,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DFAFE)) THEN + ALLOCATE(DstBeddoesData%DFAFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DFAFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DFAFE = SrcBeddoesData%DFAFE +ENDIF +IF (ALLOCATED(SrcBeddoesData%DFAFE1)) THEN + i1_l = LBOUND(SrcBeddoesData%DFAFE1,1) + i1_u = UBOUND(SrcBeddoesData%DFAFE1,1) + i2_l = LBOUND(SrcBeddoesData%DFAFE1,2) + i2_u = UBOUND(SrcBeddoesData%DFAFE1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DFAFE1)) THEN + ALLOCATE(DstBeddoesData%DFAFE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DFAFE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DFAFE1 = SrcBeddoesData%DFAFE1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%DFC)) THEN + i1_l = LBOUND(SrcBeddoesData%DFC,1) + i1_u = UBOUND(SrcBeddoesData%DFC,1) + i2_l = LBOUND(SrcBeddoesData%DFC,2) + i2_u = UBOUND(SrcBeddoesData%DFC,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DFC)) THEN + ALLOCATE(DstBeddoesData%DFC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DFC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DFC = SrcBeddoesData%DFC +ENDIF +IF (ALLOCATED(SrcBeddoesData%DN)) THEN + i1_l = LBOUND(SrcBeddoesData%DN,1) + i1_u = UBOUND(SrcBeddoesData%DN,1) + i2_l = LBOUND(SrcBeddoesData%DN,2) + i2_u = UBOUND(SrcBeddoesData%DN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DN)) THEN + ALLOCATE(DstBeddoesData%DN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DN = SrcBeddoesData%DN +ENDIF +IF (ALLOCATED(SrcBeddoesData%DPP)) THEN + i1_l = LBOUND(SrcBeddoesData%DPP,1) + i1_u = UBOUND(SrcBeddoesData%DPP,1) + i2_l = LBOUND(SrcBeddoesData%DPP,2) + i2_u = UBOUND(SrcBeddoesData%DPP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DPP)) THEN + ALLOCATE(DstBeddoesData%DPP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DPP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DPP = SrcBeddoesData%DPP +ENDIF +IF (ALLOCATED(SrcBeddoesData%DQ)) THEN + i1_l = LBOUND(SrcBeddoesData%DQ,1) + i1_u = UBOUND(SrcBeddoesData%DQ,1) + i2_l = LBOUND(SrcBeddoesData%DQ,2) + i2_u = UBOUND(SrcBeddoesData%DQ,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DQ)) THEN + ALLOCATE(DstBeddoesData%DQ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DQ = SrcBeddoesData%DQ +ENDIF +IF (ALLOCATED(SrcBeddoesData%DQP)) THEN + i1_l = LBOUND(SrcBeddoesData%DQP,1) + i1_u = UBOUND(SrcBeddoesData%DQP,1) + i2_l = LBOUND(SrcBeddoesData%DQP,2) + i2_u = UBOUND(SrcBeddoesData%DQP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DQP)) THEN + ALLOCATE(DstBeddoesData%DQP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DQP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DQP = SrcBeddoesData%DQP +ENDIF +IF (ALLOCATED(SrcBeddoesData%DQP1)) THEN + i1_l = LBOUND(SrcBeddoesData%DQP1,1) + i1_u = UBOUND(SrcBeddoesData%DQP1,1) + i2_l = LBOUND(SrcBeddoesData%DQP1,2) + i2_u = UBOUND(SrcBeddoesData%DQP1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%DQP1)) THEN + ALLOCATE(DstBeddoesData%DQP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%DQP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%DQP1 = SrcBeddoesData%DQP1 +ENDIF + DstBeddoesData%DS = SrcBeddoesData%DS + DstBeddoesData%FK = SrcBeddoesData%FK + DstBeddoesData%FP = SrcBeddoesData%FP + DstBeddoesData%FPC = SrcBeddoesData%FPC +IF (ALLOCATED(SrcBeddoesData%FSP)) THEN + i1_l = LBOUND(SrcBeddoesData%FSP,1) + i1_u = UBOUND(SrcBeddoesData%FSP,1) + i2_l = LBOUND(SrcBeddoesData%FSP,2) + i2_u = UBOUND(SrcBeddoesData%FSP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%FSP)) THEN + ALLOCATE(DstBeddoesData%FSP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FSP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FSP = SrcBeddoesData%FSP +ENDIF +IF (ALLOCATED(SrcBeddoesData%FSP1)) THEN + i1_l = LBOUND(SrcBeddoesData%FSP1,1) + i1_u = UBOUND(SrcBeddoesData%FSP1,1) + i2_l = LBOUND(SrcBeddoesData%FSP1,2) + i2_u = UBOUND(SrcBeddoesData%FSP1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%FSP1)) THEN + ALLOCATE(DstBeddoesData%FSP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FSP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FSP1 = SrcBeddoesData%FSP1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%FSPC)) THEN + i1_l = LBOUND(SrcBeddoesData%FSPC,1) + i1_u = UBOUND(SrcBeddoesData%FSPC,1) + i2_l = LBOUND(SrcBeddoesData%FSPC,2) + i2_u = UBOUND(SrcBeddoesData%FSPC,2) + IF (.NOT. ALLOCATED(DstBeddoesData%FSPC)) THEN + ALLOCATE(DstBeddoesData%FSPC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FSPC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FSPC = SrcBeddoesData%FSPC +ENDIF +IF (ALLOCATED(SrcBeddoesData%FSPC1)) THEN + i1_l = LBOUND(SrcBeddoesData%FSPC1,1) + i1_u = UBOUND(SrcBeddoesData%FSPC1,1) + i2_l = LBOUND(SrcBeddoesData%FSPC1,2) + i2_u = UBOUND(SrcBeddoesData%FSPC1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%FSPC1)) THEN + ALLOCATE(DstBeddoesData%FSPC1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FSPC1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FSPC1 = SrcBeddoesData%FSPC1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%FTB)) THEN + i1_l = LBOUND(SrcBeddoesData%FTB,1) + i1_u = UBOUND(SrcBeddoesData%FTB,1) + i2_l = LBOUND(SrcBeddoesData%FTB,2) + i2_u = UBOUND(SrcBeddoesData%FTB,2) + i3_l = LBOUND(SrcBeddoesData%FTB,3) + i3_u = UBOUND(SrcBeddoesData%FTB,3) + IF (.NOT. ALLOCATED(DstBeddoesData%FTB)) THEN + ALLOCATE(DstBeddoesData%FTB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FTB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FTB = SrcBeddoesData%FTB +ENDIF +IF (ALLOCATED(SrcBeddoesData%FTBC)) THEN + i1_l = LBOUND(SrcBeddoesData%FTBC,1) + i1_u = UBOUND(SrcBeddoesData%FTBC,1) + i2_l = LBOUND(SrcBeddoesData%FTBC,2) + i2_u = UBOUND(SrcBeddoesData%FTBC,2) + i3_l = LBOUND(SrcBeddoesData%FTBC,3) + i3_u = UBOUND(SrcBeddoesData%FTBC,3) + IF (.NOT. ALLOCATED(DstBeddoesData%FTBC)) THEN + ALLOCATE(DstBeddoesData%FTBC(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%FTBC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%FTBC = SrcBeddoesData%FTBC +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDCNV)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDCNV,1) + i1_u = UBOUND(SrcBeddoesData%OLDCNV,1) + i2_l = LBOUND(SrcBeddoesData%OLDCNV,2) + i2_u = UBOUND(SrcBeddoesData%OLDCNV,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDCNV)) THEN + ALLOCATE(DstBeddoesData%OLDCNV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDCNV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDCNV = SrcBeddoesData%OLDCNV +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDDF)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDDF,1) + i1_u = UBOUND(SrcBeddoesData%OLDDF,1) + i2_l = LBOUND(SrcBeddoesData%OLDDF,2) + i2_u = UBOUND(SrcBeddoesData%OLDDF,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDDF)) THEN + ALLOCATE(DstBeddoesData%OLDDF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDDF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDDF = SrcBeddoesData%OLDDF +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDDFC)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDDFC,1) + i1_u = UBOUND(SrcBeddoesData%OLDDFC,1) + i2_l = LBOUND(SrcBeddoesData%OLDDFC,2) + i2_u = UBOUND(SrcBeddoesData%OLDDFC,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDDFC)) THEN + ALLOCATE(DstBeddoesData%OLDDFC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDDFC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDDFC = SrcBeddoesData%OLDDFC +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDDN)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDDN,1) + i1_u = UBOUND(SrcBeddoesData%OLDDN,1) + i2_l = LBOUND(SrcBeddoesData%OLDDN,2) + i2_u = UBOUND(SrcBeddoesData%OLDDN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDDN)) THEN + ALLOCATE(DstBeddoesData%OLDDN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDDN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDDN = SrcBeddoesData%OLDDN +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDDPP)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDDPP,1) + i1_u = UBOUND(SrcBeddoesData%OLDDPP,1) + i2_l = LBOUND(SrcBeddoesData%OLDDPP,2) + i2_u = UBOUND(SrcBeddoesData%OLDDPP,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDDPP)) THEN + ALLOCATE(DstBeddoesData%OLDDPP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDDPP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDDPP = SrcBeddoesData%OLDDPP +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDDQ)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDDQ,1) + i1_u = UBOUND(SrcBeddoesData%OLDDQ,1) + i2_l = LBOUND(SrcBeddoesData%OLDDQ,2) + i2_u = UBOUND(SrcBeddoesData%OLDDQ,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDDQ)) THEN + ALLOCATE(DstBeddoesData%OLDDQ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDDQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDDQ = SrcBeddoesData%OLDDQ +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDTAU)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDTAU,1) + i1_u = UBOUND(SrcBeddoesData%OLDTAU,1) + i2_l = LBOUND(SrcBeddoesData%OLDTAU,2) + i2_u = UBOUND(SrcBeddoesData%OLDTAU,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDTAU)) THEN + ALLOCATE(DstBeddoesData%OLDTAU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDTAU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDTAU = SrcBeddoesData%OLDTAU +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDXN)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDXN,1) + i1_u = UBOUND(SrcBeddoesData%OLDXN,1) + i2_l = LBOUND(SrcBeddoesData%OLDXN,2) + i2_u = UBOUND(SrcBeddoesData%OLDXN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDXN)) THEN + ALLOCATE(DstBeddoesData%OLDXN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDXN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDXN = SrcBeddoesData%OLDXN +ENDIF +IF (ALLOCATED(SrcBeddoesData%OLDYN)) THEN + i1_l = LBOUND(SrcBeddoesData%OLDYN,1) + i1_u = UBOUND(SrcBeddoesData%OLDYN,1) + i2_l = LBOUND(SrcBeddoesData%OLDYN,2) + i2_u = UBOUND(SrcBeddoesData%OLDYN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%OLDYN)) THEN + ALLOCATE(DstBeddoesData%OLDYN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%OLDYN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%OLDYN = SrcBeddoesData%OLDYN +ENDIF +IF (ALLOCATED(SrcBeddoesData%QX)) THEN + i1_l = LBOUND(SrcBeddoesData%QX,1) + i1_u = UBOUND(SrcBeddoesData%QX,1) + i2_l = LBOUND(SrcBeddoesData%QX,2) + i2_u = UBOUND(SrcBeddoesData%QX,2) + IF (.NOT. ALLOCATED(DstBeddoesData%QX)) THEN + ALLOCATE(DstBeddoesData%QX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%QX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%QX = SrcBeddoesData%QX +ENDIF +IF (ALLOCATED(SrcBeddoesData%QX1)) THEN + i1_l = LBOUND(SrcBeddoesData%QX1,1) + i1_u = UBOUND(SrcBeddoesData%QX1,1) + i2_l = LBOUND(SrcBeddoesData%QX1,2) + i2_u = UBOUND(SrcBeddoesData%QX1,2) + IF (.NOT. ALLOCATED(DstBeddoesData%QX1)) THEN + ALLOCATE(DstBeddoesData%QX1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%QX1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%QX1 = SrcBeddoesData%QX1 +ENDIF +IF (ALLOCATED(SrcBeddoesData%TAU)) THEN + i1_l = LBOUND(SrcBeddoesData%TAU,1) + i1_u = UBOUND(SrcBeddoesData%TAU,1) + i2_l = LBOUND(SrcBeddoesData%TAU,2) + i2_u = UBOUND(SrcBeddoesData%TAU,2) + IF (.NOT. ALLOCATED(DstBeddoesData%TAU)) THEN + ALLOCATE(DstBeddoesData%TAU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%TAU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%TAU = SrcBeddoesData%TAU +ENDIF +IF (ALLOCATED(SrcBeddoesData%XN)) THEN + i1_l = LBOUND(SrcBeddoesData%XN,1) + i1_u = UBOUND(SrcBeddoesData%XN,1) + i2_l = LBOUND(SrcBeddoesData%XN,2) + i2_u = UBOUND(SrcBeddoesData%XN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%XN)) THEN + ALLOCATE(DstBeddoesData%XN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%XN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%XN = SrcBeddoesData%XN +ENDIF +IF (ALLOCATED(SrcBeddoesData%YN)) THEN + i1_l = LBOUND(SrcBeddoesData%YN,1) + i1_u = UBOUND(SrcBeddoesData%YN,1) + i2_l = LBOUND(SrcBeddoesData%YN,2) + i2_u = UBOUND(SrcBeddoesData%YN,2) + IF (.NOT. ALLOCATED(DstBeddoesData%YN)) THEN + ALLOCATE(DstBeddoesData%YN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeddoesData%YN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeddoesData%YN = SrcBeddoesData%YN +ENDIF + DstBeddoesData%SHIFT = SrcBeddoesData%SHIFT + DstBeddoesData%VOR = SrcBeddoesData%VOR + END SUBROUTINE AD14_CopyBeddoes + + SUBROUTINE AD14_DestroyBeddoes( BeddoesData, ErrStat, ErrMsg ) + TYPE(Beddoes), INTENT(INOUT) :: BeddoesData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyBeddoes' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BeddoesData%ADOT)) THEN + DEALLOCATE(BeddoesData%ADOT) +ENDIF +IF (ALLOCATED(BeddoesData%ADOT1)) THEN + DEALLOCATE(BeddoesData%ADOT1) +ENDIF +IF (ALLOCATED(BeddoesData%AFE)) THEN + DEALLOCATE(BeddoesData%AFE) +ENDIF +IF (ALLOCATED(BeddoesData%AFE1)) THEN + DEALLOCATE(BeddoesData%AFE1) +ENDIF +IF (ALLOCATED(BeddoesData%ANE)) THEN + DEALLOCATE(BeddoesData%ANE) +ENDIF +IF (ALLOCATED(BeddoesData%ANE1)) THEN + DEALLOCATE(BeddoesData%ANE1) +ENDIF +IF (ALLOCATED(BeddoesData%AOD)) THEN + DEALLOCATE(BeddoesData%AOD) +ENDIF +IF (ALLOCATED(BeddoesData%AOL)) THEN + DEALLOCATE(BeddoesData%AOL) +ENDIF +IF (ALLOCATED(BeddoesData%BEDSEP)) THEN + DEALLOCATE(BeddoesData%BEDSEP) +ENDIF +IF (ALLOCATED(BeddoesData%OLDSEP)) THEN + DEALLOCATE(BeddoesData%OLDSEP) +ENDIF +IF (ALLOCATED(BeddoesData%CDO)) THEN + DEALLOCATE(BeddoesData%CDO) +ENDIF +IF (ALLOCATED(BeddoesData%CNA)) THEN + DEALLOCATE(BeddoesData%CNA) +ENDIF +IF (ALLOCATED(BeddoesData%CNP)) THEN + DEALLOCATE(BeddoesData%CNP) +ENDIF +IF (ALLOCATED(BeddoesData%CNP1)) THEN + DEALLOCATE(BeddoesData%CNP1) +ENDIF +IF (ALLOCATED(BeddoesData%CNPD)) THEN + DEALLOCATE(BeddoesData%CNPD) +ENDIF +IF (ALLOCATED(BeddoesData%CNPD1)) THEN + DEALLOCATE(BeddoesData%CNPD1) +ENDIF +IF (ALLOCATED(BeddoesData%CNPOT)) THEN + DEALLOCATE(BeddoesData%CNPOT) +ENDIF +IF (ALLOCATED(BeddoesData%CNPOT1)) THEN + DEALLOCATE(BeddoesData%CNPOT1) +ENDIF +IF (ALLOCATED(BeddoesData%CNS)) THEN + DEALLOCATE(BeddoesData%CNS) +ENDIF +IF (ALLOCATED(BeddoesData%CNSL)) THEN + DEALLOCATE(BeddoesData%CNSL) +ENDIF +IF (ALLOCATED(BeddoesData%CNV)) THEN + DEALLOCATE(BeddoesData%CNV) +ENDIF +IF (ALLOCATED(BeddoesData%CVN)) THEN + DEALLOCATE(BeddoesData%CVN) +ENDIF +IF (ALLOCATED(BeddoesData%CVN1)) THEN + DEALLOCATE(BeddoesData%CVN1) +ENDIF +IF (ALLOCATED(BeddoesData%DF)) THEN + DEALLOCATE(BeddoesData%DF) +ENDIF +IF (ALLOCATED(BeddoesData%DFAFE)) THEN + DEALLOCATE(BeddoesData%DFAFE) +ENDIF +IF (ALLOCATED(BeddoesData%DFAFE1)) THEN + DEALLOCATE(BeddoesData%DFAFE1) +ENDIF +IF (ALLOCATED(BeddoesData%DFC)) THEN + DEALLOCATE(BeddoesData%DFC) +ENDIF +IF (ALLOCATED(BeddoesData%DN)) THEN + DEALLOCATE(BeddoesData%DN) +ENDIF +IF (ALLOCATED(BeddoesData%DPP)) THEN + DEALLOCATE(BeddoesData%DPP) +ENDIF +IF (ALLOCATED(BeddoesData%DQ)) THEN + DEALLOCATE(BeddoesData%DQ) +ENDIF +IF (ALLOCATED(BeddoesData%DQP)) THEN + DEALLOCATE(BeddoesData%DQP) +ENDIF +IF (ALLOCATED(BeddoesData%DQP1)) THEN + DEALLOCATE(BeddoesData%DQP1) +ENDIF +IF (ALLOCATED(BeddoesData%FSP)) THEN + DEALLOCATE(BeddoesData%FSP) +ENDIF +IF (ALLOCATED(BeddoesData%FSP1)) THEN + DEALLOCATE(BeddoesData%FSP1) +ENDIF +IF (ALLOCATED(BeddoesData%FSPC)) THEN + DEALLOCATE(BeddoesData%FSPC) +ENDIF +IF (ALLOCATED(BeddoesData%FSPC1)) THEN + DEALLOCATE(BeddoesData%FSPC1) +ENDIF +IF (ALLOCATED(BeddoesData%FTB)) THEN + DEALLOCATE(BeddoesData%FTB) +ENDIF +IF (ALLOCATED(BeddoesData%FTBC)) THEN + DEALLOCATE(BeddoesData%FTBC) +ENDIF +IF (ALLOCATED(BeddoesData%OLDCNV)) THEN + DEALLOCATE(BeddoesData%OLDCNV) +ENDIF +IF (ALLOCATED(BeddoesData%OLDDF)) THEN + DEALLOCATE(BeddoesData%OLDDF) +ENDIF +IF (ALLOCATED(BeddoesData%OLDDFC)) THEN + DEALLOCATE(BeddoesData%OLDDFC) +ENDIF +IF (ALLOCATED(BeddoesData%OLDDN)) THEN + DEALLOCATE(BeddoesData%OLDDN) +ENDIF +IF (ALLOCATED(BeddoesData%OLDDPP)) THEN + DEALLOCATE(BeddoesData%OLDDPP) +ENDIF +IF (ALLOCATED(BeddoesData%OLDDQ)) THEN + DEALLOCATE(BeddoesData%OLDDQ) +ENDIF +IF (ALLOCATED(BeddoesData%OLDTAU)) THEN + DEALLOCATE(BeddoesData%OLDTAU) +ENDIF +IF (ALLOCATED(BeddoesData%OLDXN)) THEN + DEALLOCATE(BeddoesData%OLDXN) +ENDIF +IF (ALLOCATED(BeddoesData%OLDYN)) THEN + DEALLOCATE(BeddoesData%OLDYN) +ENDIF +IF (ALLOCATED(BeddoesData%QX)) THEN + DEALLOCATE(BeddoesData%QX) +ENDIF +IF (ALLOCATED(BeddoesData%QX1)) THEN + DEALLOCATE(BeddoesData%QX1) +ENDIF +IF (ALLOCATED(BeddoesData%TAU)) THEN + DEALLOCATE(BeddoesData%TAU) +ENDIF +IF (ALLOCATED(BeddoesData%XN)) THEN + DEALLOCATE(BeddoesData%XN) +ENDIF +IF (ALLOCATED(BeddoesData%YN)) THEN + DEALLOCATE(BeddoesData%YN) +ENDIF + END SUBROUTINE AD14_DestroyBeddoes + + SUBROUTINE AD14_PackBeddoes( 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(Beddoes), 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 = 'AD14_PackBeddoes' + ! 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 ! ADOT allocated yes/no + IF ( ALLOCATED(InData%ADOT) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ADOT upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ADOT) ! ADOT + END IF + Int_BufSz = Int_BufSz + 1 ! ADOT1 allocated yes/no + IF ( ALLOCATED(InData%ADOT1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ADOT1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ADOT1) ! ADOT1 + END IF + Int_BufSz = Int_BufSz + 1 ! AFE allocated yes/no + IF ( ALLOCATED(InData%AFE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AFE) ! AFE + END IF + Int_BufSz = Int_BufSz + 1 ! AFE1 allocated yes/no + IF ( ALLOCATED(InData%AFE1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AFE1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AFE1) ! AFE1 + END IF + Re_BufSz = Re_BufSz + 1 ! AN + Int_BufSz = Int_BufSz + 1 ! ANE allocated yes/no + IF ( ALLOCATED(InData%ANE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ANE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ANE) ! ANE + END IF + Int_BufSz = Int_BufSz + 1 ! ANE1 allocated yes/no + IF ( ALLOCATED(InData%ANE1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ANE1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ANE1) ! ANE1 + END IF + Int_BufSz = Int_BufSz + 1 ! AOD allocated yes/no + IF ( ALLOCATED(InData%AOD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AOD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AOD) ! AOD + END IF + Int_BufSz = Int_BufSz + 1 ! AOL allocated yes/no + IF ( ALLOCATED(InData%AOL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AOL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AOL) ! AOL + END IF + Int_BufSz = Int_BufSz + 1 ! BEDSEP allocated yes/no + IF ( ALLOCATED(InData%BEDSEP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BEDSEP upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BEDSEP) ! BEDSEP + END IF + Int_BufSz = Int_BufSz + 1 ! OLDSEP allocated yes/no + IF ( ALLOCATED(InData%OLDSEP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDSEP upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OLDSEP) ! OLDSEP + END IF + Re_BufSz = Re_BufSz + 1 ! CC + Int_BufSz = Int_BufSz + 1 ! CDO allocated yes/no + IF ( ALLOCATED(InData%CDO) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CDO upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CDO) ! CDO + END IF + Re_BufSz = Re_BufSz + 1 ! CMI + Re_BufSz = Re_BufSz + 1 ! CMQ + Re_BufSz = Re_BufSz + 1 ! CN + Int_BufSz = Int_BufSz + 1 ! CNA allocated yes/no + IF ( ALLOCATED(InData%CNA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNA) ! CNA + END IF + Re_BufSz = Re_BufSz + 1 ! CNCP + Re_BufSz = Re_BufSz + 1 ! CNIQ + Int_BufSz = Int_BufSz + 1 ! CNP allocated yes/no + IF ( ALLOCATED(InData%CNP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNP) ! CNP + END IF + Int_BufSz = Int_BufSz + 1 ! CNP1 allocated yes/no + IF ( ALLOCATED(InData%CNP1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNP1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNP1) ! CNP1 + END IF + Int_BufSz = Int_BufSz + 1 ! CNPD allocated yes/no + IF ( ALLOCATED(InData%CNPD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNPD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNPD) ! CNPD + END IF + Int_BufSz = Int_BufSz + 1 ! CNPD1 allocated yes/no + IF ( ALLOCATED(InData%CNPD1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNPD1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNPD1) ! CNPD1 + END IF + Int_BufSz = Int_BufSz + 1 ! CNPOT allocated yes/no + IF ( ALLOCATED(InData%CNPOT) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNPOT upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNPOT) ! CNPOT + END IF + Int_BufSz = Int_BufSz + 1 ! CNPOT1 allocated yes/no + IF ( ALLOCATED(InData%CNPOT1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNPOT1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNPOT1) ! CNPOT1 + END IF + Int_BufSz = Int_BufSz + 1 ! CNS allocated yes/no + IF ( ALLOCATED(InData%CNS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNS) ! CNS + END IF + Int_BufSz = Int_BufSz + 1 ! CNSL allocated yes/no + IF ( ALLOCATED(InData%CNSL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNSL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNSL) ! CNSL + END IF + Int_BufSz = Int_BufSz + 1 ! CNV allocated yes/no + IF ( ALLOCATED(InData%CNV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CNV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNV) ! CNV + END IF + Int_BufSz = Int_BufSz + 1 ! CVN allocated yes/no + IF ( ALLOCATED(InData%CVN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CVN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CVN) ! CVN + END IF + Int_BufSz = Int_BufSz + 1 ! CVN1 allocated yes/no + IF ( ALLOCATED(InData%CVN1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CVN1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CVN1) ! CVN1 + END IF + Int_BufSz = Int_BufSz + 1 ! DF allocated yes/no + IF ( ALLOCATED(InData%DF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DF) ! DF + END IF + Int_BufSz = Int_BufSz + 1 ! DFAFE allocated yes/no + IF ( ALLOCATED(InData%DFAFE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DFAFE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DFAFE) ! DFAFE + END IF + Int_BufSz = Int_BufSz + 1 ! DFAFE1 allocated yes/no + IF ( ALLOCATED(InData%DFAFE1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DFAFE1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DFAFE1) ! DFAFE1 + END IF + Int_BufSz = Int_BufSz + 1 ! DFC allocated yes/no + IF ( ALLOCATED(InData%DFC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DFC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DFC) ! DFC + END IF + Int_BufSz = Int_BufSz + 1 ! DN allocated yes/no + IF ( ALLOCATED(InData%DN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DN) ! DN + END IF + Int_BufSz = Int_BufSz + 1 ! DPP allocated yes/no + IF ( ALLOCATED(InData%DPP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DPP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DPP) ! DPP + END IF + Int_BufSz = Int_BufSz + 1 ! DQ allocated yes/no + IF ( ALLOCATED(InData%DQ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DQ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DQ) ! DQ + END IF + Int_BufSz = Int_BufSz + 1 ! DQP allocated yes/no + IF ( ALLOCATED(InData%DQP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DQP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DQP) ! DQP + END IF + Int_BufSz = Int_BufSz + 1 ! DQP1 allocated yes/no + IF ( ALLOCATED(InData%DQP1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DQP1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DQP1) ! DQP1 + END IF + Re_BufSz = Re_BufSz + 1 ! DS + Re_BufSz = Re_BufSz + 1 ! FK + Re_BufSz = Re_BufSz + 1 ! FP + Re_BufSz = Re_BufSz + 1 ! FPC + Int_BufSz = Int_BufSz + 1 ! FSP allocated yes/no + IF ( ALLOCATED(InData%FSP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FSP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSP) ! FSP + END IF + Int_BufSz = Int_BufSz + 1 ! FSP1 allocated yes/no + IF ( ALLOCATED(InData%FSP1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FSP1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSP1) ! FSP1 + END IF + Int_BufSz = Int_BufSz + 1 ! FSPC allocated yes/no + IF ( ALLOCATED(InData%FSPC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FSPC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSPC) ! FSPC + END IF + Int_BufSz = Int_BufSz + 1 ! FSPC1 allocated yes/no + IF ( ALLOCATED(InData%FSPC1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FSPC1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSPC1) ! FSPC1 + END IF + Int_BufSz = Int_BufSz + 1 ! FTB allocated yes/no + IF ( ALLOCATED(InData%FTB) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FTB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FTB) ! FTB + END IF + Int_BufSz = Int_BufSz + 1 ! FTBC allocated yes/no + IF ( ALLOCATED(InData%FTBC) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FTBC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FTBC) ! FTBC + END IF + Int_BufSz = Int_BufSz + 1 ! OLDCNV allocated yes/no + IF ( ALLOCATED(InData%OLDCNV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDCNV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDCNV) ! OLDCNV + END IF + Int_BufSz = Int_BufSz + 1 ! OLDDF allocated yes/no + IF ( ALLOCATED(InData%OLDDF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDDF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDDF) ! OLDDF + END IF + Int_BufSz = Int_BufSz + 1 ! OLDDFC allocated yes/no + IF ( ALLOCATED(InData%OLDDFC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDDFC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDDFC) ! OLDDFC + END IF + Int_BufSz = Int_BufSz + 1 ! OLDDN allocated yes/no + IF ( ALLOCATED(InData%OLDDN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDDN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDDN) ! OLDDN + END IF + Int_BufSz = Int_BufSz + 1 ! OLDDPP allocated yes/no + IF ( ALLOCATED(InData%OLDDPP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDDPP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDDPP) ! OLDDPP + END IF + Int_BufSz = Int_BufSz + 1 ! OLDDQ allocated yes/no + IF ( ALLOCATED(InData%OLDDQ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDDQ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDDQ) ! OLDDQ + END IF + Int_BufSz = Int_BufSz + 1 ! OLDTAU allocated yes/no + IF ( ALLOCATED(InData%OLDTAU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDTAU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDTAU) ! OLDTAU + END IF + Int_BufSz = Int_BufSz + 1 ! OLDXN allocated yes/no + IF ( ALLOCATED(InData%OLDXN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDXN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDXN) ! OLDXN + END IF + Int_BufSz = Int_BufSz + 1 ! OLDYN allocated yes/no + IF ( ALLOCATED(InData%OLDYN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLDYN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLDYN) ! OLDYN + END IF + Int_BufSz = Int_BufSz + 1 ! QX allocated yes/no + IF ( ALLOCATED(InData%QX) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! QX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%QX) ! QX + END IF + Int_BufSz = Int_BufSz + 1 ! QX1 allocated yes/no + IF ( ALLOCATED(InData%QX1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! QX1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%QX1) ! QX1 + END IF + Int_BufSz = Int_BufSz + 1 ! TAU allocated yes/no + IF ( ALLOCATED(InData%TAU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TAU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TAU) ! TAU + END IF + Int_BufSz = Int_BufSz + 1 ! XN allocated yes/no + IF ( ALLOCATED(InData%XN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! XN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%XN) ! XN + END IF + Int_BufSz = Int_BufSz + 1 ! YN allocated yes/no + IF ( ALLOCATED(InData%YN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! YN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%YN) ! YN + END IF + Int_BufSz = Int_BufSz + 1 ! SHIFT + Int_BufSz = Int_BufSz + 1 ! VOR + 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%ADOT) ) 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%ADOT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADOT,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ADOT,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADOT,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ADOT,2), UBOUND(InData%ADOT,2) + DO i1 = LBOUND(InData%ADOT,1), UBOUND(InData%ADOT,1) + ReKiBuf(Re_Xferred) = InData%ADOT(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ADOT1) ) 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%ADOT1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADOT1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ADOT1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADOT1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ADOT1,2), UBOUND(InData%ADOT1,2) + DO i1 = LBOUND(InData%ADOT1,1), UBOUND(InData%ADOT1,1) + ReKiBuf(Re_Xferred) = InData%ADOT1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFE) ) 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%AFE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFE,2), UBOUND(InData%AFE,2) + DO i1 = LBOUND(InData%AFE,1), UBOUND(InData%AFE,1) + ReKiBuf(Re_Xferred) = InData%AFE(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AFE1) ) 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%AFE1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFE1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AFE1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AFE1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AFE1,2), UBOUND(InData%AFE1,2) + DO i1 = LBOUND(InData%AFE1,1), UBOUND(InData%AFE1,1) + ReKiBuf(Re_Xferred) = InData%AFE1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AN + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ANE) ) 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%ANE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ANE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ANE,2), UBOUND(InData%ANE,2) + DO i1 = LBOUND(InData%ANE,1), UBOUND(InData%ANE,1) + ReKiBuf(Re_Xferred) = InData%ANE(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ANE1) ) 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%ANE1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANE1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ANE1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANE1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ANE1,2), UBOUND(InData%ANE1,2) + DO i1 = LBOUND(InData%ANE1,1), UBOUND(InData%ANE1,1) + ReKiBuf(Re_Xferred) = InData%ANE1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AOD) ) 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%AOD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AOD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AOD,2), UBOUND(InData%AOD,2) + DO i1 = LBOUND(InData%AOD,1), UBOUND(InData%AOD,1) + ReKiBuf(Re_Xferred) = InData%AOD(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AOL) ) 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%AOL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AOL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AOL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AOL,2), UBOUND(InData%AOL,2) + DO i1 = LBOUND(InData%AOL,1), UBOUND(InData%AOL,1) + ReKiBuf(Re_Xferred) = InData%AOL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BEDSEP) ) 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%BEDSEP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BEDSEP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BEDSEP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BEDSEP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BEDSEP,2), UBOUND(InData%BEDSEP,2) + DO i1 = LBOUND(InData%BEDSEP,1), UBOUND(InData%BEDSEP,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%BEDSEP(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDSEP) ) 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%OLDSEP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDSEP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDSEP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDSEP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDSEP,2), UBOUND(InData%OLDSEP,2) + DO i1 = LBOUND(InData%OLDSEP,1), UBOUND(InData%OLDSEP,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%OLDSEP(i1,i2), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%CC + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CDO) ) 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%CDO,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CDO,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CDO,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CDO,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CDO,2), UBOUND(InData%CDO,2) + DO i1 = LBOUND(InData%CDO,1), UBOUND(InData%CDO,1) + ReKiBuf(Re_Xferred) = InData%CDO(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%CMI + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CMQ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CN + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CNA) ) 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%CNA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNA,2), UBOUND(InData%CNA,2) + DO i1 = LBOUND(InData%CNA,1), UBOUND(InData%CNA,1) + ReKiBuf(Re_Xferred) = InData%CNA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%CNCP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CNIQ + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CNP) ) 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%CNP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNP,2), UBOUND(InData%CNP,2) + DO i1 = LBOUND(InData%CNP,1), UBOUND(InData%CNP,1) + ReKiBuf(Re_Xferred) = InData%CNP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNP1) ) 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%CNP1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNP1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNP1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNP1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNP1,2), UBOUND(InData%CNP1,2) + DO i1 = LBOUND(InData%CNP1,1), UBOUND(InData%CNP1,1) + ReKiBuf(Re_Xferred) = InData%CNP1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNPD) ) 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%CNPD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNPD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNPD,2), UBOUND(InData%CNPD,2) + DO i1 = LBOUND(InData%CNPD,1), UBOUND(InData%CNPD,1) + ReKiBuf(Re_Xferred) = InData%CNPD(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNPD1) ) 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%CNPD1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPD1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNPD1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPD1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNPD1,2), UBOUND(InData%CNPD1,2) + DO i1 = LBOUND(InData%CNPD1,1), UBOUND(InData%CNPD1,1) + ReKiBuf(Re_Xferred) = InData%CNPD1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNPOT) ) 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%CNPOT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPOT,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNPOT,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPOT,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNPOT,2), UBOUND(InData%CNPOT,2) + DO i1 = LBOUND(InData%CNPOT,1), UBOUND(InData%CNPOT,1) + ReKiBuf(Re_Xferred) = InData%CNPOT(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNPOT1) ) 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%CNPOT1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPOT1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNPOT1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNPOT1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNPOT1,2), UBOUND(InData%CNPOT1,2) + DO i1 = LBOUND(InData%CNPOT1,1), UBOUND(InData%CNPOT1,1) + ReKiBuf(Re_Xferred) = InData%CNPOT1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNS) ) 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%CNS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNS,2), UBOUND(InData%CNS,2) + DO i1 = LBOUND(InData%CNS,1), UBOUND(InData%CNS,1) + ReKiBuf(Re_Xferred) = InData%CNS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNSL) ) 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%CNSL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNSL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNSL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNSL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNSL,2), UBOUND(InData%CNSL,2) + DO i1 = LBOUND(InData%CNSL,1), UBOUND(InData%CNSL,1) + ReKiBuf(Re_Xferred) = InData%CNSL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNV) ) 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%CNV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CNV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNV,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CNV,2), UBOUND(InData%CNV,2) + DO i1 = LBOUND(InData%CNV,1), UBOUND(InData%CNV,1) + ReKiBuf(Re_Xferred) = InData%CNV(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CVN) ) 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%CVN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CVN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CVN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CVN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CVN,2), UBOUND(InData%CVN,2) + DO i1 = LBOUND(InData%CVN,1), UBOUND(InData%CVN,1) + ReKiBuf(Re_Xferred) = InData%CVN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CVN1) ) 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%CVN1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CVN1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CVN1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CVN1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CVN1,2), UBOUND(InData%CVN1,2) + DO i1 = LBOUND(InData%CVN1,1), UBOUND(InData%CVN1,1) + ReKiBuf(Re_Xferred) = InData%CVN1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DF) ) 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%DF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DF,2), UBOUND(InData%DF,2) + DO i1 = LBOUND(InData%DF,1), UBOUND(InData%DF,1) + ReKiBuf(Re_Xferred) = InData%DF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DFAFE) ) 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%DFAFE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFAFE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DFAFE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFAFE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DFAFE,2), UBOUND(InData%DFAFE,2) + DO i1 = LBOUND(InData%DFAFE,1), UBOUND(InData%DFAFE,1) + ReKiBuf(Re_Xferred) = InData%DFAFE(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DFAFE1) ) 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%DFAFE1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFAFE1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DFAFE1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFAFE1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DFAFE1,2), UBOUND(InData%DFAFE1,2) + DO i1 = LBOUND(InData%DFAFE1,1), UBOUND(InData%DFAFE1,1) + ReKiBuf(Re_Xferred) = InData%DFAFE1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DFC) ) 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%DFC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DFC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFC,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DFC,2), UBOUND(InData%DFC,2) + DO i1 = LBOUND(InData%DFC,1), UBOUND(InData%DFC,1) + ReKiBuf(Re_Xferred) = InData%DFC(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DN) ) 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%DN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DN,2), UBOUND(InData%DN,2) + DO i1 = LBOUND(InData%DN,1), UBOUND(InData%DN,1) + ReKiBuf(Re_Xferred) = InData%DN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DPP) ) 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%DPP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DPP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DPP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DPP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DPP,2), UBOUND(InData%DPP,2) + DO i1 = LBOUND(InData%DPP,1), UBOUND(InData%DPP,1) + ReKiBuf(Re_Xferred) = InData%DPP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DQ) ) 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%DQ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DQ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DQ,2), UBOUND(InData%DQ,2) + DO i1 = LBOUND(InData%DQ,1), UBOUND(InData%DQ,1) + ReKiBuf(Re_Xferred) = InData%DQ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DQP) ) 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%DQP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DQP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DQP,2), UBOUND(InData%DQP,2) + DO i1 = LBOUND(InData%DQP,1), UBOUND(InData%DQP,1) + ReKiBuf(Re_Xferred) = InData%DQP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DQP1) ) 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%DQP1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQP1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DQP1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DQP1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DQP1,2), UBOUND(InData%DQP1,2) + DO i1 = LBOUND(InData%DQP1,1), UBOUND(InData%DQP1,1) + ReKiBuf(Re_Xferred) = InData%DQP1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%DS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FK + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FPC + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FSP) ) 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%FSP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FSP,2), UBOUND(InData%FSP,2) + DO i1 = LBOUND(InData%FSP,1), UBOUND(InData%FSP,1) + ReKiBuf(Re_Xferred) = InData%FSP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FSP1) ) 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%FSP1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSP1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSP1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSP1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FSP1,2), UBOUND(InData%FSP1,2) + DO i1 = LBOUND(InData%FSP1,1), UBOUND(InData%FSP1,1) + ReKiBuf(Re_Xferred) = InData%FSP1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FSPC) ) 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%FSPC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSPC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSPC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSPC,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FSPC,2), UBOUND(InData%FSPC,2) + DO i1 = LBOUND(InData%FSPC,1), UBOUND(InData%FSPC,1) + ReKiBuf(Re_Xferred) = InData%FSPC(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FSPC1) ) 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%FSPC1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSPC1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSPC1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSPC1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FSPC1,2), UBOUND(InData%FSPC1,2) + DO i1 = LBOUND(InData%FSPC1,1), UBOUND(InData%FSPC1,1) + ReKiBuf(Re_Xferred) = InData%FSPC1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FTB) ) 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%FTB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FTB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTB,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FTB,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTB,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FTB,3), UBOUND(InData%FTB,3) + DO i2 = LBOUND(InData%FTB,2), UBOUND(InData%FTB,2) + DO i1 = LBOUND(InData%FTB,1), UBOUND(InData%FTB,1) + ReKiBuf(Re_Xferred) = InData%FTB(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FTBC) ) 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%FTBC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTBC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FTBC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTBC,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FTBC,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTBC,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FTBC,3), UBOUND(InData%FTBC,3) + DO i2 = LBOUND(InData%FTBC,2), UBOUND(InData%FTBC,2) + DO i1 = LBOUND(InData%FTBC,1), UBOUND(InData%FTBC,1) + ReKiBuf(Re_Xferred) = InData%FTBC(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDCNV) ) 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%OLDCNV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDCNV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDCNV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDCNV,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDCNV,2), UBOUND(InData%OLDCNV,2) + DO i1 = LBOUND(InData%OLDCNV,1), UBOUND(InData%OLDCNV,1) + ReKiBuf(Re_Xferred) = InData%OLDCNV(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDDF) ) 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%OLDDF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDDF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDDF,2), UBOUND(InData%OLDDF,2) + DO i1 = LBOUND(InData%OLDDF,1), UBOUND(InData%OLDDF,1) + ReKiBuf(Re_Xferred) = InData%OLDDF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDDFC) ) 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%OLDDFC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDFC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDDFC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDFC,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDDFC,2), UBOUND(InData%OLDDFC,2) + DO i1 = LBOUND(InData%OLDDFC,1), UBOUND(InData%OLDDFC,1) + ReKiBuf(Re_Xferred) = InData%OLDDFC(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDDN) ) 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%OLDDN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDDN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDDN,2), UBOUND(InData%OLDDN,2) + DO i1 = LBOUND(InData%OLDDN,1), UBOUND(InData%OLDDN,1) + ReKiBuf(Re_Xferred) = InData%OLDDN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDDPP) ) 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%OLDDPP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDPP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDDPP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDPP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDDPP,2), UBOUND(InData%OLDDPP,2) + DO i1 = LBOUND(InData%OLDDPP,1), UBOUND(InData%OLDDPP,1) + ReKiBuf(Re_Xferred) = InData%OLDDPP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDDQ) ) 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%OLDDQ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDQ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDDQ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDDQ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDDQ,2), UBOUND(InData%OLDDQ,2) + DO i1 = LBOUND(InData%OLDDQ,1), UBOUND(InData%OLDDQ,1) + ReKiBuf(Re_Xferred) = InData%OLDDQ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDTAU) ) 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%OLDTAU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDTAU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDTAU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDTAU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDTAU,2), UBOUND(InData%OLDTAU,2) + DO i1 = LBOUND(InData%OLDTAU,1), UBOUND(InData%OLDTAU,1) + ReKiBuf(Re_Xferred) = InData%OLDTAU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDXN) ) 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%OLDXN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDXN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDXN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDXN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDXN,2), UBOUND(InData%OLDXN,2) + DO i1 = LBOUND(InData%OLDXN,1), UBOUND(InData%OLDXN,1) + ReKiBuf(Re_Xferred) = InData%OLDXN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLDYN) ) 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%OLDYN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDYN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLDYN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLDYN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLDYN,2), UBOUND(InData%OLDYN,2) + DO i1 = LBOUND(InData%OLDYN,1), UBOUND(InData%OLDYN,1) + ReKiBuf(Re_Xferred) = InData%OLDYN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QX) ) 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%QX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QX,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QX,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%QX,2), UBOUND(InData%QX,2) + DO i1 = LBOUND(InData%QX,1), UBOUND(InData%QX,1) + ReKiBuf(Re_Xferred) = InData%QX(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QX1) ) 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%QX1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QX1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QX1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QX1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%QX1,2), UBOUND(InData%QX1,2) + DO i1 = LBOUND(InData%QX1,1), UBOUND(InData%QX1,1) + ReKiBuf(Re_Xferred) = InData%QX1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TAU) ) 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%TAU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TAU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TAU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TAU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TAU,2), UBOUND(InData%TAU,2) + DO i1 = LBOUND(InData%TAU,1), UBOUND(InData%TAU,1) + ReKiBuf(Re_Xferred) = InData%TAU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%XN) ) 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%XN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%XN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%XN,2), UBOUND(InData%XN,2) + DO i1 = LBOUND(InData%XN,1), UBOUND(InData%XN,1) + ReKiBuf(Re_Xferred) = InData%XN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%YN) ) 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%YN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%YN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%YN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%YN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%YN,2), UBOUND(InData%YN,2) + DO i1 = LBOUND(InData%YN,1), UBOUND(InData%YN,1) + ReKiBuf(Re_Xferred) = InData%YN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%SHIFT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%VOR, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_PackBeddoes + + SUBROUTINE AD14_UnPackBeddoes( 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(Beddoes), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_UnPackBeddoes' + ! 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 ! ADOT 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%ADOT)) DEALLOCATE(OutData%ADOT) + ALLOCATE(OutData%ADOT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ADOT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ADOT,2), UBOUND(OutData%ADOT,2) + DO i1 = LBOUND(OutData%ADOT,1), UBOUND(OutData%ADOT,1) + OutData%ADOT(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ADOT1 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%ADOT1)) DEALLOCATE(OutData%ADOT1) + ALLOCATE(OutData%ADOT1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ADOT1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ADOT1,2), UBOUND(OutData%ADOT1,2) + DO i1 = LBOUND(OutData%ADOT1,1), UBOUND(OutData%ADOT1,1) + OutData%ADOT1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFE 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%AFE)) DEALLOCATE(OutData%AFE) + ALLOCATE(OutData%AFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFE,2), UBOUND(OutData%AFE,2) + DO i1 = LBOUND(OutData%AFE,1), UBOUND(OutData%AFE,1) + OutData%AFE(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AFE1 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%AFE1)) DEALLOCATE(OutData%AFE1) + ALLOCATE(OutData%AFE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AFE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AFE1,2), UBOUND(OutData%AFE1,2) + DO i1 = LBOUND(OutData%AFE1,1), UBOUND(OutData%AFE1,1) + OutData%AFE1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%AN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ANE 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%ANE)) DEALLOCATE(OutData%ANE) + ALLOCATE(OutData%ANE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ANE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ANE,2), UBOUND(OutData%ANE,2) + DO i1 = LBOUND(OutData%ANE,1), UBOUND(OutData%ANE,1) + OutData%ANE(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ANE1 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%ANE1)) DEALLOCATE(OutData%ANE1) + ALLOCATE(OutData%ANE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ANE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ANE1,2), UBOUND(OutData%ANE1,2) + DO i1 = LBOUND(OutData%ANE1,1), UBOUND(OutData%ANE1,1) + OutData%ANE1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AOD 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%AOD)) DEALLOCATE(OutData%AOD) + ALLOCATE(OutData%AOD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AOD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AOD,2), UBOUND(OutData%AOD,2) + DO i1 = LBOUND(OutData%AOD,1), UBOUND(OutData%AOD,1) + OutData%AOD(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AOL 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%AOL)) DEALLOCATE(OutData%AOL) + ALLOCATE(OutData%AOL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AOL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AOL,2), UBOUND(OutData%AOL,2) + DO i1 = LBOUND(OutData%AOL,1), UBOUND(OutData%AOL,1) + OutData%AOL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BEDSEP 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%BEDSEP)) DEALLOCATE(OutData%BEDSEP) + ALLOCATE(OutData%BEDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BEDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BEDSEP,2), UBOUND(OutData%BEDSEP,2) + DO i1 = LBOUND(OutData%BEDSEP,1), UBOUND(OutData%BEDSEP,1) + OutData%BEDSEP(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%BEDSEP(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDSEP 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%OLDSEP)) DEALLOCATE(OutData%OLDSEP) + ALLOCATE(OutData%OLDSEP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDSEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDSEP,2), UBOUND(OutData%OLDSEP,2) + DO i1 = LBOUND(OutData%OLDSEP,1), UBOUND(OutData%OLDSEP,1) + OutData%OLDSEP(i1,i2) = TRANSFER(IntKiBuf(Int_Xferred), OutData%OLDSEP(i1,i2)) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%CC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CDO 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%CDO)) DEALLOCATE(OutData%CDO) + ALLOCATE(OutData%CDO(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CDO.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CDO,2), UBOUND(OutData%CDO,2) + DO i1 = LBOUND(OutData%CDO,1), UBOUND(OutData%CDO,1) + OutData%CDO(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%CMI = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CMQ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNA 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%CNA)) DEALLOCATE(OutData%CNA) + ALLOCATE(OutData%CNA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNA,2), UBOUND(OutData%CNA,2) + DO i1 = LBOUND(OutData%CNA,1), UBOUND(OutData%CNA,1) + OutData%CNA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%CNCP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CNIQ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNP 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%CNP)) DEALLOCATE(OutData%CNP) + ALLOCATE(OutData%CNP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNP,2), UBOUND(OutData%CNP,2) + DO i1 = LBOUND(OutData%CNP,1), UBOUND(OutData%CNP,1) + OutData%CNP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNP1 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%CNP1)) DEALLOCATE(OutData%CNP1) + ALLOCATE(OutData%CNP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNP1,2), UBOUND(OutData%CNP1,2) + DO i1 = LBOUND(OutData%CNP1,1), UBOUND(OutData%CNP1,1) + OutData%CNP1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNPD 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%CNPD)) DEALLOCATE(OutData%CNPD) + ALLOCATE(OutData%CNPD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNPD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNPD,2), UBOUND(OutData%CNPD,2) + DO i1 = LBOUND(OutData%CNPD,1), UBOUND(OutData%CNPD,1) + OutData%CNPD(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNPD1 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%CNPD1)) DEALLOCATE(OutData%CNPD1) + ALLOCATE(OutData%CNPD1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNPD1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNPD1,2), UBOUND(OutData%CNPD1,2) + DO i1 = LBOUND(OutData%CNPD1,1), UBOUND(OutData%CNPD1,1) + OutData%CNPD1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNPOT 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%CNPOT)) DEALLOCATE(OutData%CNPOT) + ALLOCATE(OutData%CNPOT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNPOT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNPOT,2), UBOUND(OutData%CNPOT,2) + DO i1 = LBOUND(OutData%CNPOT,1), UBOUND(OutData%CNPOT,1) + OutData%CNPOT(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNPOT1 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%CNPOT1)) DEALLOCATE(OutData%CNPOT1) + ALLOCATE(OutData%CNPOT1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNPOT1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNPOT1,2), UBOUND(OutData%CNPOT1,2) + DO i1 = LBOUND(OutData%CNPOT1,1), UBOUND(OutData%CNPOT1,1) + OutData%CNPOT1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNS 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%CNS)) DEALLOCATE(OutData%CNS) + ALLOCATE(OutData%CNS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNS,2), UBOUND(OutData%CNS,2) + DO i1 = LBOUND(OutData%CNS,1), UBOUND(OutData%CNS,1) + OutData%CNS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNSL 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%CNSL)) DEALLOCATE(OutData%CNSL) + ALLOCATE(OutData%CNSL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNSL,2), UBOUND(OutData%CNSL,2) + DO i1 = LBOUND(OutData%CNSL,1), UBOUND(OutData%CNSL,1) + OutData%CNSL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNV 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%CNV)) DEALLOCATE(OutData%CNV) + ALLOCATE(OutData%CNV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CNV,2), UBOUND(OutData%CNV,2) + DO i1 = LBOUND(OutData%CNV,1), UBOUND(OutData%CNV,1) + OutData%CNV(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CVN 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%CVN)) DEALLOCATE(OutData%CVN) + ALLOCATE(OutData%CVN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CVN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CVN,2), UBOUND(OutData%CVN,2) + DO i1 = LBOUND(OutData%CVN,1), UBOUND(OutData%CVN,1) + OutData%CVN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CVN1 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%CVN1)) DEALLOCATE(OutData%CVN1) + ALLOCATE(OutData%CVN1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CVN1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CVN1,2), UBOUND(OutData%CVN1,2) + DO i1 = LBOUND(OutData%CVN1,1), UBOUND(OutData%CVN1,1) + OutData%CVN1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DF 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%DF)) DEALLOCATE(OutData%DF) + ALLOCATE(OutData%DF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DF,2), UBOUND(OutData%DF,2) + DO i1 = LBOUND(OutData%DF,1), UBOUND(OutData%DF,1) + OutData%DF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DFAFE 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%DFAFE)) DEALLOCATE(OutData%DFAFE) + ALLOCATE(OutData%DFAFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DFAFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DFAFE,2), UBOUND(OutData%DFAFE,2) + DO i1 = LBOUND(OutData%DFAFE,1), UBOUND(OutData%DFAFE,1) + OutData%DFAFE(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DFAFE1 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%DFAFE1)) DEALLOCATE(OutData%DFAFE1) + ALLOCATE(OutData%DFAFE1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DFAFE1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DFAFE1,2), UBOUND(OutData%DFAFE1,2) + DO i1 = LBOUND(OutData%DFAFE1,1), UBOUND(OutData%DFAFE1,1) + OutData%DFAFE1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DFC 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%DFC)) DEALLOCATE(OutData%DFC) + ALLOCATE(OutData%DFC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DFC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DFC,2), UBOUND(OutData%DFC,2) + DO i1 = LBOUND(OutData%DFC,1), UBOUND(OutData%DFC,1) + OutData%DFC(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DN 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%DN)) DEALLOCATE(OutData%DN) + ALLOCATE(OutData%DN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DN,2), UBOUND(OutData%DN,2) + DO i1 = LBOUND(OutData%DN,1), UBOUND(OutData%DN,1) + OutData%DN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DPP 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%DPP)) DEALLOCATE(OutData%DPP) + ALLOCATE(OutData%DPP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DPP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DPP,2), UBOUND(OutData%DPP,2) + DO i1 = LBOUND(OutData%DPP,1), UBOUND(OutData%DPP,1) + OutData%DPP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DQ 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%DQ)) DEALLOCATE(OutData%DQ) + ALLOCATE(OutData%DQ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DQ,2), UBOUND(OutData%DQ,2) + DO i1 = LBOUND(OutData%DQ,1), UBOUND(OutData%DQ,1) + OutData%DQ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DQP 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%DQP)) DEALLOCATE(OutData%DQP) + ALLOCATE(OutData%DQP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DQP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DQP,2), UBOUND(OutData%DQP,2) + DO i1 = LBOUND(OutData%DQP,1), UBOUND(OutData%DQP,1) + OutData%DQP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DQP1 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%DQP1)) DEALLOCATE(OutData%DQP1) + ALLOCATE(OutData%DQP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DQP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DQP1,2), UBOUND(OutData%DQP1,2) + DO i1 = LBOUND(OutData%DQP1,1), UBOUND(OutData%DQP1,1) + OutData%DQP1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%DS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FK = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FPC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSP 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%FSP)) DEALLOCATE(OutData%FSP) + ALLOCATE(OutData%FSP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FSP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FSP,2), UBOUND(OutData%FSP,2) + DO i1 = LBOUND(OutData%FSP,1), UBOUND(OutData%FSP,1) + OutData%FSP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSP1 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%FSP1)) DEALLOCATE(OutData%FSP1) + ALLOCATE(OutData%FSP1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FSP1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FSP1,2), UBOUND(OutData%FSP1,2) + DO i1 = LBOUND(OutData%FSP1,1), UBOUND(OutData%FSP1,1) + OutData%FSP1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSPC 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%FSPC)) DEALLOCATE(OutData%FSPC) + ALLOCATE(OutData%FSPC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FSPC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FSPC,2), UBOUND(OutData%FSPC,2) + DO i1 = LBOUND(OutData%FSPC,1), UBOUND(OutData%FSPC,1) + OutData%FSPC(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSPC1 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%FSPC1)) DEALLOCATE(OutData%FSPC1) + ALLOCATE(OutData%FSPC1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FSPC1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FSPC1,2), UBOUND(OutData%FSPC1,2) + DO i1 = LBOUND(OutData%FSPC1,1), UBOUND(OutData%FSPC1,1) + OutData%FSPC1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FTB 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%FTB)) DEALLOCATE(OutData%FTB) + ALLOCATE(OutData%FTB(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%FTB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FTB,3), UBOUND(OutData%FTB,3) + DO i2 = LBOUND(OutData%FTB,2), UBOUND(OutData%FTB,2) + DO i1 = LBOUND(OutData%FTB,1), UBOUND(OutData%FTB,1) + OutData%FTB(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FTBC 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%FTBC)) DEALLOCATE(OutData%FTBC) + ALLOCATE(OutData%FTBC(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%FTBC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FTBC,3), UBOUND(OutData%FTBC,3) + DO i2 = LBOUND(OutData%FTBC,2), UBOUND(OutData%FTBC,2) + DO i1 = LBOUND(OutData%FTBC,1), UBOUND(OutData%FTBC,1) + OutData%FTBC(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDCNV 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%OLDCNV)) DEALLOCATE(OutData%OLDCNV) + ALLOCATE(OutData%OLDCNV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDCNV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDCNV,2), UBOUND(OutData%OLDCNV,2) + DO i1 = LBOUND(OutData%OLDCNV,1), UBOUND(OutData%OLDCNV,1) + OutData%OLDCNV(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDDF 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%OLDDF)) DEALLOCATE(OutData%OLDDF) + ALLOCATE(OutData%OLDDF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDDF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDDF,2), UBOUND(OutData%OLDDF,2) + DO i1 = LBOUND(OutData%OLDDF,1), UBOUND(OutData%OLDDF,1) + OutData%OLDDF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDDFC 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%OLDDFC)) DEALLOCATE(OutData%OLDDFC) + ALLOCATE(OutData%OLDDFC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDDFC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDDFC,2), UBOUND(OutData%OLDDFC,2) + DO i1 = LBOUND(OutData%OLDDFC,1), UBOUND(OutData%OLDDFC,1) + OutData%OLDDFC(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDDN 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%OLDDN)) DEALLOCATE(OutData%OLDDN) + ALLOCATE(OutData%OLDDN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDDN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDDN,2), UBOUND(OutData%OLDDN,2) + DO i1 = LBOUND(OutData%OLDDN,1), UBOUND(OutData%OLDDN,1) + OutData%OLDDN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDDPP 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%OLDDPP)) DEALLOCATE(OutData%OLDDPP) + ALLOCATE(OutData%OLDDPP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDDPP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDDPP,2), UBOUND(OutData%OLDDPP,2) + DO i1 = LBOUND(OutData%OLDDPP,1), UBOUND(OutData%OLDDPP,1) + OutData%OLDDPP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDDQ 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%OLDDQ)) DEALLOCATE(OutData%OLDDQ) + ALLOCATE(OutData%OLDDQ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDDQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDDQ,2), UBOUND(OutData%OLDDQ,2) + DO i1 = LBOUND(OutData%OLDDQ,1), UBOUND(OutData%OLDDQ,1) + OutData%OLDDQ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDTAU 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%OLDTAU)) DEALLOCATE(OutData%OLDTAU) + ALLOCATE(OutData%OLDTAU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDTAU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDTAU,2), UBOUND(OutData%OLDTAU,2) + DO i1 = LBOUND(OutData%OLDTAU,1), UBOUND(OutData%OLDTAU,1) + OutData%OLDTAU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDXN 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%OLDXN)) DEALLOCATE(OutData%OLDXN) + ALLOCATE(OutData%OLDXN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDXN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDXN,2), UBOUND(OutData%OLDXN,2) + DO i1 = LBOUND(OutData%OLDXN,1), UBOUND(OutData%OLDXN,1) + OutData%OLDXN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLDYN 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%OLDYN)) DEALLOCATE(OutData%OLDYN) + ALLOCATE(OutData%OLDYN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLDYN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLDYN,2), UBOUND(OutData%OLDYN,2) + DO i1 = LBOUND(OutData%OLDYN,1), UBOUND(OutData%OLDYN,1) + OutData%OLDYN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QX 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%QX)) DEALLOCATE(OutData%QX) + ALLOCATE(OutData%QX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%QX,2), UBOUND(OutData%QX,2) + DO i1 = LBOUND(OutData%QX,1), UBOUND(OutData%QX,1) + OutData%QX(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QX1 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%QX1)) DEALLOCATE(OutData%QX1) + ALLOCATE(OutData%QX1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QX1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%QX1,2), UBOUND(OutData%QX1,2) + DO i1 = LBOUND(OutData%QX1,1), UBOUND(OutData%QX1,1) + OutData%QX1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TAU 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%TAU)) DEALLOCATE(OutData%TAU) + ALLOCATE(OutData%TAU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TAU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TAU,2), UBOUND(OutData%TAU,2) + DO i1 = LBOUND(OutData%TAU,1), UBOUND(OutData%TAU,1) + OutData%TAU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! XN 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%XN)) DEALLOCATE(OutData%XN) + ALLOCATE(OutData%XN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%XN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%XN,2), UBOUND(OutData%XN,2) + DO i1 = LBOUND(OutData%XN,1), UBOUND(OutData%XN,1) + OutData%XN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! YN 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%YN)) DEALLOCATE(OutData%YN) + ALLOCATE(OutData%YN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%YN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%YN,2), UBOUND(OutData%YN,2) + DO i1 = LBOUND(OutData%YN,1), UBOUND(OutData%YN,1) + OutData%YN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%SHIFT = TRANSFER(IntKiBuf(Int_Xferred), OutData%SHIFT) + Int_Xferred = Int_Xferred + 1 + OutData%VOR = TRANSFER(IntKiBuf(Int_Xferred), OutData%VOR) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_UnPackBeddoes + + SUBROUTINE AD14_CopyBeddoesParms( SrcBeddoesParmsData, DstBeddoesParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BeddoesParms), INTENT(IN) :: SrcBeddoesParmsData + TYPE(BeddoesParms), INTENT(INOUT) :: DstBeddoesParmsData + 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 = 'AD14_CopyBeddoesParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBeddoesParmsData%AS = SrcBeddoesParmsData%AS + DstBeddoesParmsData%TF = SrcBeddoesParmsData%TF + DstBeddoesParmsData%TP = SrcBeddoesParmsData%TP + DstBeddoesParmsData%TV = SrcBeddoesParmsData%TV + DstBeddoesParmsData%TVL = SrcBeddoesParmsData%TVL + END SUBROUTINE AD14_CopyBeddoesParms + + SUBROUTINE AD14_DestroyBeddoesParms( BeddoesParmsData, ErrStat, ErrMsg ) + TYPE(BeddoesParms), INTENT(INOUT) :: BeddoesParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyBeddoesParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyBeddoesParms + + SUBROUTINE AD14_PackBeddoesParms( 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(BeddoesParms), 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 = 'AD14_PackBeddoesParms' + ! 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 ! AS + Re_BufSz = Re_BufSz + 1 ! TF + Re_BufSz = Re_BufSz + 1 ! TP + Re_BufSz = Re_BufSz + 1 ! TV + Re_BufSz = Re_BufSz + 1 ! TVL + 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%AS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TF + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TVL + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackBeddoesParms + + SUBROUTINE AD14_UnPackBeddoesParms( 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(BeddoesParms), 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 = 'AD14_UnPackBeddoesParms' + ! 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%AS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TF = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TVL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackBeddoesParms + + SUBROUTINE AD14_CopyBladeParms( SrcBladeParmsData, DstBladeParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladeParms), INTENT(IN) :: SrcBladeParmsData + TYPE(BladeParms), INTENT(INOUT) :: DstBladeParmsData + 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 = 'AD14_CopyBladeParms' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcBladeParmsData%C)) THEN + i1_l = LBOUND(SrcBladeParmsData%C,1) + i1_u = UBOUND(SrcBladeParmsData%C,1) + IF (.NOT. ALLOCATED(DstBladeParmsData%C)) THEN + ALLOCATE(DstBladeParmsData%C(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeParmsData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeParmsData%C = SrcBladeParmsData%C +ENDIF +IF (ALLOCATED(SrcBladeParmsData%DR)) THEN + i1_l = LBOUND(SrcBladeParmsData%DR,1) + i1_u = UBOUND(SrcBladeParmsData%DR,1) + IF (.NOT. ALLOCATED(DstBladeParmsData%DR)) THEN + ALLOCATE(DstBladeParmsData%DR(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeParmsData%DR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeParmsData%DR = SrcBladeParmsData%DR +ENDIF + DstBladeParmsData%R = SrcBladeParmsData%R + DstBladeParmsData%BladeLength = SrcBladeParmsData%BladeLength + END SUBROUTINE AD14_CopyBladeParms + + SUBROUTINE AD14_DestroyBladeParms( BladeParmsData, ErrStat, ErrMsg ) + TYPE(BladeParms), INTENT(INOUT) :: BladeParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyBladeParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladeParmsData%C)) THEN + DEALLOCATE(BladeParmsData%C) +ENDIF +IF (ALLOCATED(BladeParmsData%DR)) THEN + DEALLOCATE(BladeParmsData%DR) +ENDIF + END SUBROUTINE AD14_DestroyBladeParms + + SUBROUTINE AD14_PackBladeParms( 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(BladeParms), 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 = 'AD14_PackBladeParms' + ! 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 ! C allocated yes/no + IF ( ALLOCATED(InData%C) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! C upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C) ! C + END IF + Int_BufSz = Int_BufSz + 1 ! DR allocated yes/no + IF ( ALLOCATED(InData%DR) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DR) ! DR + END IF + Re_BufSz = Re_BufSz + 1 ! R + Re_BufSz = Re_BufSz + 1 ! BladeLength + 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%C) ) 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%C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%C,1), UBOUND(InData%C,1) + ReKiBuf(Re_Xferred) = InData%C(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DR) ) 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%DR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DR,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DR,1), UBOUND(InData%DR,1) + ReKiBuf(Re_Xferred) = InData%DR(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%R + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackBladeParms + + SUBROUTINE AD14_UnPackBladeParms( 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(BladeParms), 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 = 'AD14_UnPackBladeParms' + ! 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 ! C 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%C)) DEALLOCATE(OutData%C) + ALLOCATE(OutData%C(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%C,1), UBOUND(OutData%C,1) + OutData%C(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DR 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%DR)) DEALLOCATE(OutData%DR) + ALLOCATE(OutData%DR(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DR,1), UBOUND(OutData%DR,1) + OutData%DR(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%R = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackBladeParms + + SUBROUTINE AD14_CopyDynInflow( SrcDynInflowData, DstDynInflowData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DynInflow), INTENT(IN) :: SrcDynInflowData + TYPE(DynInflow), INTENT(INOUT) :: DstDynInflowData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_CopyDynInflow' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDynInflowData%dAlph_dt = SrcDynInflowData%dAlph_dt + DstDynInflowData%dBeta_dt = SrcDynInflowData%dBeta_dt + DstDynInflowData%DTO = SrcDynInflowData%DTO + DstDynInflowData%old_Alph = SrcDynInflowData%old_Alph + DstDynInflowData%old_Beta = SrcDynInflowData%old_Beta + DstDynInflowData%old_LmdM = SrcDynInflowData%old_LmdM + DstDynInflowData%oldKai = SrcDynInflowData%oldKai + DstDynInflowData%PhiLqC = SrcDynInflowData%PhiLqC + DstDynInflowData%PhiLqS = SrcDynInflowData%PhiLqS + DstDynInflowData%Pzero = SrcDynInflowData%Pzero +IF (ALLOCATED(SrcDynInflowData%RMC_SAVE)) THEN + i1_l = LBOUND(SrcDynInflowData%RMC_SAVE,1) + i1_u = UBOUND(SrcDynInflowData%RMC_SAVE,1) + i2_l = LBOUND(SrcDynInflowData%RMC_SAVE,2) + i2_u = UBOUND(SrcDynInflowData%RMC_SAVE,2) + i3_l = LBOUND(SrcDynInflowData%RMC_SAVE,3) + i3_u = UBOUND(SrcDynInflowData%RMC_SAVE,3) + IF (.NOT. ALLOCATED(DstDynInflowData%RMC_SAVE)) THEN + ALLOCATE(DstDynInflowData%RMC_SAVE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDynInflowData%RMC_SAVE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDynInflowData%RMC_SAVE = SrcDynInflowData%RMC_SAVE +ENDIF +IF (ALLOCATED(SrcDynInflowData%RMS_SAVE)) THEN + i1_l = LBOUND(SrcDynInflowData%RMS_SAVE,1) + i1_u = UBOUND(SrcDynInflowData%RMS_SAVE,1) + i2_l = LBOUND(SrcDynInflowData%RMS_SAVE,2) + i2_u = UBOUND(SrcDynInflowData%RMS_SAVE,2) + i3_l = LBOUND(SrcDynInflowData%RMS_SAVE,3) + i3_u = UBOUND(SrcDynInflowData%RMS_SAVE,3) + IF (.NOT. ALLOCATED(DstDynInflowData%RMS_SAVE)) THEN + ALLOCATE(DstDynInflowData%RMS_SAVE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDynInflowData%RMS_SAVE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDynInflowData%RMS_SAVE = SrcDynInflowData%RMS_SAVE +ENDIF + DstDynInflowData%TipSpeed = SrcDynInflowData%TipSpeed + DstDynInflowData%totalInf = SrcDynInflowData%totalInf + DstDynInflowData%Vparam = SrcDynInflowData%Vparam + DstDynInflowData%Vtotal = SrcDynInflowData%Vtotal + DstDynInflowData%xAlpha = SrcDynInflowData%xAlpha + DstDynInflowData%xBeta = SrcDynInflowData%xBeta + DstDynInflowData%xKai = SrcDynInflowData%xKai + DstDynInflowData%XLAMBDA_M = SrcDynInflowData%XLAMBDA_M + DstDynInflowData%xLcos = SrcDynInflowData%xLcos + DstDynInflowData%xLsin = SrcDynInflowData%xLsin + DstDynInflowData%MminR = SrcDynInflowData%MminR + DstDynInflowData%MminusR = SrcDynInflowData%MminusR + DstDynInflowData%MplusR = SrcDynInflowData%MplusR + DstDynInflowData%GAMMA = SrcDynInflowData%GAMMA + END SUBROUTINE AD14_CopyDynInflow + + SUBROUTINE AD14_DestroyDynInflow( DynInflowData, ErrStat, ErrMsg ) + TYPE(DynInflow), INTENT(INOUT) :: DynInflowData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyDynInflow' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(DynInflowData%RMC_SAVE)) THEN + DEALLOCATE(DynInflowData%RMC_SAVE) +ENDIF +IF (ALLOCATED(DynInflowData%RMS_SAVE)) THEN + DEALLOCATE(DynInflowData%RMS_SAVE) +ENDIF + END SUBROUTINE AD14_DestroyDynInflow + + SUBROUTINE AD14_PackDynInflow( 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(DynInflow), 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 = 'AD14_PackDynInflow' + ! 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%dAlph_dt) ! dAlph_dt + Re_BufSz = Re_BufSz + SIZE(InData%dBeta_dt) ! dBeta_dt + Re_BufSz = Re_BufSz + 1 ! DTO + Re_BufSz = Re_BufSz + SIZE(InData%old_Alph) ! old_Alph + Re_BufSz = Re_BufSz + SIZE(InData%old_Beta) ! old_Beta + Re_BufSz = Re_BufSz + 1 ! old_LmdM + Re_BufSz = Re_BufSz + 1 ! oldKai + Re_BufSz = Re_BufSz + SIZE(InData%PhiLqC) ! PhiLqC + Re_BufSz = Re_BufSz + SIZE(InData%PhiLqS) ! PhiLqS + Re_BufSz = Re_BufSz + 1 ! Pzero + Int_BufSz = Int_BufSz + 1 ! RMC_SAVE allocated yes/no + IF ( ALLOCATED(InData%RMC_SAVE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! RMC_SAVE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RMC_SAVE) ! RMC_SAVE + END IF + Int_BufSz = Int_BufSz + 1 ! RMS_SAVE allocated yes/no + IF ( ALLOCATED(InData%RMS_SAVE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! RMS_SAVE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RMS_SAVE) ! RMS_SAVE + END IF + Re_BufSz = Re_BufSz + 1 ! TipSpeed + Re_BufSz = Re_BufSz + 1 ! totalInf + Re_BufSz = Re_BufSz + 1 ! Vparam + Re_BufSz = Re_BufSz + 1 ! Vtotal + Re_BufSz = Re_BufSz + SIZE(InData%xAlpha) ! xAlpha + Re_BufSz = Re_BufSz + SIZE(InData%xBeta) ! xBeta + Re_BufSz = Re_BufSz + 1 ! xKai + Re_BufSz = Re_BufSz + 1 ! XLAMBDA_M + Re_BufSz = Re_BufSz + SIZE(InData%xLcos) ! xLcos + Re_BufSz = Re_BufSz + SIZE(InData%xLsin) ! xLsin + Int_BufSz = Int_BufSz + SIZE(InData%MminR) ! MminR + Int_BufSz = Int_BufSz + SIZE(InData%MminusR) ! MminusR + Int_BufSz = Int_BufSz + SIZE(InData%MplusR) ! MplusR + Re_BufSz = Re_BufSz + SIZE(InData%GAMMA) ! GAMMA + 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 i2 = LBOUND(InData%dAlph_dt,2), UBOUND(InData%dAlph_dt,2) + DO i1 = LBOUND(InData%dAlph_dt,1), UBOUND(InData%dAlph_dt,1) + ReKiBuf(Re_Xferred) = InData%dAlph_dt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%dBeta_dt,2), UBOUND(InData%dBeta_dt,2) + DO i1 = LBOUND(InData%dBeta_dt,1), UBOUND(InData%dBeta_dt,1) + ReKiBuf(Re_Xferred) = InData%dBeta_dt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + ReKiBuf(Re_Xferred) = InData%DTO + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%old_Alph,1), UBOUND(InData%old_Alph,1) + ReKiBuf(Re_Xferred) = InData%old_Alph(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%old_Beta,1), UBOUND(InData%old_Beta,1) + ReKiBuf(Re_Xferred) = InData%old_Beta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%old_LmdM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%oldKai + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%PhiLqC,1), UBOUND(InData%PhiLqC,1) + ReKiBuf(Re_Xferred) = InData%PhiLqC(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%PhiLqS,1), UBOUND(InData%PhiLqS,1) + ReKiBuf(Re_Xferred) = InData%PhiLqS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%Pzero + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%RMC_SAVE) ) 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%RMC_SAVE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMC_SAVE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMC_SAVE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMC_SAVE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMC_SAVE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMC_SAVE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%RMC_SAVE,3), UBOUND(InData%RMC_SAVE,3) + DO i2 = LBOUND(InData%RMC_SAVE,2), UBOUND(InData%RMC_SAVE,2) + DO i1 = LBOUND(InData%RMC_SAVE,1), UBOUND(InData%RMC_SAVE,1) + ReKiBuf(Re_Xferred) = InData%RMC_SAVE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RMS_SAVE) ) 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%RMS_SAVE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMS_SAVE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMS_SAVE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMS_SAVE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMS_SAVE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMS_SAVE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%RMS_SAVE,3), UBOUND(InData%RMS_SAVE,3) + DO i2 = LBOUND(InData%RMS_SAVE,2), UBOUND(InData%RMS_SAVE,2) + DO i1 = LBOUND(InData%RMS_SAVE,1), UBOUND(InData%RMS_SAVE,1) + ReKiBuf(Re_Xferred) = InData%RMS_SAVE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TipSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%totalInf + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Vparam + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Vtotal + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%xAlpha,1), UBOUND(InData%xAlpha,1) + ReKiBuf(Re_Xferred) = InData%xAlpha(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%xBeta,1), UBOUND(InData%xBeta,1) + ReKiBuf(Re_Xferred) = InData%xBeta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%xKai + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%XLAMBDA_M + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%xLcos,2), UBOUND(InData%xLcos,2) + DO i1 = LBOUND(InData%xLcos,1), UBOUND(InData%xLcos,1) + ReKiBuf(Re_Xferred) = InData%xLcos(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%xLsin,2), UBOUND(InData%xLsin,2) + DO i1 = LBOUND(InData%xLsin,1), UBOUND(InData%xLsin,1) + ReKiBuf(Re_Xferred) = InData%xLsin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%MminR,2), UBOUND(InData%MminR,2) + DO i1 = LBOUND(InData%MminR,1), UBOUND(InData%MminR,1) + IntKiBuf(Int_Xferred) = InData%MminR(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%MminusR,2), UBOUND(InData%MminusR,2) + DO i1 = LBOUND(InData%MminusR,1), UBOUND(InData%MminusR,1) + IntKiBuf(Int_Xferred) = InData%MminusR(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%MplusR,2), UBOUND(InData%MplusR,2) + DO i1 = LBOUND(InData%MplusR,1), UBOUND(InData%MplusR,1) + IntKiBuf(Int_Xferred) = InData%MplusR(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%GAMMA,2), UBOUND(InData%GAMMA,2) + DO i1 = LBOUND(InData%GAMMA,1), UBOUND(InData%GAMMA,1) + ReKiBuf(Re_Xferred) = InData%GAMMA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE AD14_PackDynInflow + + SUBROUTINE AD14_UnPackDynInflow( 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(DynInflow), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_UnPackDynInflow' + ! 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%dAlph_dt,1) + i1_u = UBOUND(OutData%dAlph_dt,1) + i2_l = LBOUND(OutData%dAlph_dt,2) + i2_u = UBOUND(OutData%dAlph_dt,2) + DO i2 = LBOUND(OutData%dAlph_dt,2), UBOUND(OutData%dAlph_dt,2) + DO i1 = LBOUND(OutData%dAlph_dt,1), UBOUND(OutData%dAlph_dt,1) + OutData%dAlph_dt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%dBeta_dt,1) + i1_u = UBOUND(OutData%dBeta_dt,1) + i2_l = LBOUND(OutData%dBeta_dt,2) + i2_u = UBOUND(OutData%dBeta_dt,2) + DO i2 = LBOUND(OutData%dBeta_dt,2), UBOUND(OutData%dBeta_dt,2) + DO i1 = LBOUND(OutData%dBeta_dt,1), UBOUND(OutData%dBeta_dt,1) + OutData%dBeta_dt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%DTO = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%old_Alph,1) + i1_u = UBOUND(OutData%old_Alph,1) + DO i1 = LBOUND(OutData%old_Alph,1), UBOUND(OutData%old_Alph,1) + OutData%old_Alph(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%old_Beta,1) + i1_u = UBOUND(OutData%old_Beta,1) + DO i1 = LBOUND(OutData%old_Beta,1), UBOUND(OutData%old_Beta,1) + OutData%old_Beta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%old_LmdM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%oldKai = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%PhiLqC,1) + i1_u = UBOUND(OutData%PhiLqC,1) + DO i1 = LBOUND(OutData%PhiLqC,1), UBOUND(OutData%PhiLqC,1) + OutData%PhiLqC(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%PhiLqS,1) + i1_u = UBOUND(OutData%PhiLqS,1) + DO i1 = LBOUND(OutData%PhiLqS,1), UBOUND(OutData%PhiLqS,1) + OutData%PhiLqS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%Pzero = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RMC_SAVE 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%RMC_SAVE)) DEALLOCATE(OutData%RMC_SAVE) + ALLOCATE(OutData%RMC_SAVE(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%RMC_SAVE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%RMC_SAVE,3), UBOUND(OutData%RMC_SAVE,3) + DO i2 = LBOUND(OutData%RMC_SAVE,2), UBOUND(OutData%RMC_SAVE,2) + DO i1 = LBOUND(OutData%RMC_SAVE,1), UBOUND(OutData%RMC_SAVE,1) + OutData%RMC_SAVE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RMS_SAVE 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%RMS_SAVE)) DEALLOCATE(OutData%RMS_SAVE) + ALLOCATE(OutData%RMS_SAVE(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%RMS_SAVE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%RMS_SAVE,3), UBOUND(OutData%RMS_SAVE,3) + DO i2 = LBOUND(OutData%RMS_SAVE,2), UBOUND(OutData%RMS_SAVE,2) + DO i1 = LBOUND(OutData%RMS_SAVE,1), UBOUND(OutData%RMS_SAVE,1) + OutData%RMS_SAVE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%TipSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%totalInf = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Vparam = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Vtotal = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%xAlpha,1) + i1_u = UBOUND(OutData%xAlpha,1) + DO i1 = LBOUND(OutData%xAlpha,1), UBOUND(OutData%xAlpha,1) + OutData%xAlpha(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%xBeta,1) + i1_u = UBOUND(OutData%xBeta,1) + DO i1 = LBOUND(OutData%xBeta,1), UBOUND(OutData%xBeta,1) + OutData%xBeta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%xKai = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%XLAMBDA_M = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%xLcos,1) + i1_u = UBOUND(OutData%xLcos,1) + i2_l = LBOUND(OutData%xLcos,2) + i2_u = UBOUND(OutData%xLcos,2) + DO i2 = LBOUND(OutData%xLcos,2), UBOUND(OutData%xLcos,2) + DO i1 = LBOUND(OutData%xLcos,1), UBOUND(OutData%xLcos,1) + OutData%xLcos(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%xLsin,1) + i1_u = UBOUND(OutData%xLsin,1) + i2_l = LBOUND(OutData%xLsin,2) + i2_u = UBOUND(OutData%xLsin,2) + DO i2 = LBOUND(OutData%xLsin,2), UBOUND(OutData%xLsin,2) + DO i1 = LBOUND(OutData%xLsin,1), UBOUND(OutData%xLsin,1) + OutData%xLsin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%MminR,1) + i1_u = UBOUND(OutData%MminR,1) + i2_l = LBOUND(OutData%MminR,2) + i2_u = UBOUND(OutData%MminR,2) + DO i2 = LBOUND(OutData%MminR,2), UBOUND(OutData%MminR,2) + DO i1 = LBOUND(OutData%MminR,1), UBOUND(OutData%MminR,1) + OutData%MminR(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%MminusR,1) + i1_u = UBOUND(OutData%MminusR,1) + i2_l = LBOUND(OutData%MminusR,2) + i2_u = UBOUND(OutData%MminusR,2) + DO i2 = LBOUND(OutData%MminusR,2), UBOUND(OutData%MminusR,2) + DO i1 = LBOUND(OutData%MminusR,1), UBOUND(OutData%MminusR,1) + OutData%MminusR(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%MplusR,1) + i1_u = UBOUND(OutData%MplusR,1) + i2_l = LBOUND(OutData%MplusR,2) + i2_u = UBOUND(OutData%MplusR,2) + DO i2 = LBOUND(OutData%MplusR,2), UBOUND(OutData%MplusR,2) + DO i1 = LBOUND(OutData%MplusR,1), UBOUND(OutData%MplusR,1) + OutData%MplusR(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%GAMMA,1) + i1_u = UBOUND(OutData%GAMMA,1) + i2_l = LBOUND(OutData%GAMMA,2) + i2_u = UBOUND(OutData%GAMMA,2) + DO i2 = LBOUND(OutData%GAMMA,2), UBOUND(OutData%GAMMA,2) + DO i1 = LBOUND(OutData%GAMMA,1), UBOUND(OutData%GAMMA,1) + OutData%GAMMA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE AD14_UnPackDynInflow + + SUBROUTINE AD14_CopyDynInflowParms( SrcDynInflowParmsData, DstDynInflowParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DynInflowParms), INTENT(IN) :: SrcDynInflowParmsData + TYPE(DynInflowParms), INTENT(INOUT) :: DstDynInflowParmsData + 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 = 'AD14_CopyDynInflowParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDynInflowParmsData%MAXINFLO = SrcDynInflowParmsData%MAXINFLO + DstDynInflowParmsData%xMinv = SrcDynInflowParmsData%xMinv + END SUBROUTINE AD14_CopyDynInflowParms + + SUBROUTINE AD14_DestroyDynInflowParms( DynInflowParmsData, ErrStat, ErrMsg ) + TYPE(DynInflowParms), INTENT(INOUT) :: DynInflowParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyDynInflowParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyDynInflowParms + + SUBROUTINE AD14_PackDynInflowParms( 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(DynInflowParms), 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 = 'AD14_PackDynInflowParms' + ! 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 ! MAXINFLO + Re_BufSz = Re_BufSz + SIZE(InData%xMinv) ! xMinv + 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%MAXINFLO + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%xMinv,1), UBOUND(InData%xMinv,1) + ReKiBuf(Re_Xferred) = InData%xMinv(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_PackDynInflowParms + + SUBROUTINE AD14_UnPackDynInflowParms( 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(DynInflowParms), 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 = 'AD14_UnPackDynInflowParms' + ! 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%MAXINFLO = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%xMinv,1) + i1_u = UBOUND(OutData%xMinv,1) + DO i1 = LBOUND(OutData%xMinv,1), UBOUND(OutData%xMinv,1) + OutData%xMinv(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_UnPackDynInflowParms + + SUBROUTINE AD14_CopyElement( SrcElementData, DstElementData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Element), INTENT(IN) :: SrcElementData + TYPE(Element), INTENT(INOUT) :: DstElementData + 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 = 'AD14_CopyElement' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcElementData%A)) THEN + i1_l = LBOUND(SrcElementData%A,1) + i1_u = UBOUND(SrcElementData%A,1) + i2_l = LBOUND(SrcElementData%A,2) + i2_u = UBOUND(SrcElementData%A,2) + IF (.NOT. ALLOCATED(DstElementData%A)) THEN + ALLOCATE(DstElementData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%A = SrcElementData%A +ENDIF +IF (ALLOCATED(SrcElementData%AP)) THEN + i1_l = LBOUND(SrcElementData%AP,1) + i1_u = UBOUND(SrcElementData%AP,1) + i2_l = LBOUND(SrcElementData%AP,2) + i2_u = UBOUND(SrcElementData%AP,2) + IF (.NOT. ALLOCATED(DstElementData%AP)) THEN + ALLOCATE(DstElementData%AP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%AP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%AP = SrcElementData%AP +ENDIF +IF (ALLOCATED(SrcElementData%ALPHA)) THEN + i1_l = LBOUND(SrcElementData%ALPHA,1) + i1_u = UBOUND(SrcElementData%ALPHA,1) + i2_l = LBOUND(SrcElementData%ALPHA,2) + i2_u = UBOUND(SrcElementData%ALPHA,2) + IF (.NOT. ALLOCATED(DstElementData%ALPHA)) THEN + ALLOCATE(DstElementData%ALPHA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%ALPHA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%ALPHA = SrcElementData%ALPHA +ENDIF +IF (ALLOCATED(SrcElementData%W2)) THEN + i1_l = LBOUND(SrcElementData%W2,1) + i1_u = UBOUND(SrcElementData%W2,1) + i2_l = LBOUND(SrcElementData%W2,2) + i2_u = UBOUND(SrcElementData%W2,2) + IF (.NOT. ALLOCATED(DstElementData%W2)) THEN + ALLOCATE(DstElementData%W2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%W2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%W2 = SrcElementData%W2 +ENDIF +IF (ALLOCATED(SrcElementData%OLD_A_NS)) THEN + i1_l = LBOUND(SrcElementData%OLD_A_NS,1) + i1_u = UBOUND(SrcElementData%OLD_A_NS,1) + i2_l = LBOUND(SrcElementData%OLD_A_NS,2) + i2_u = UBOUND(SrcElementData%OLD_A_NS,2) + IF (.NOT. ALLOCATED(DstElementData%OLD_A_NS)) THEN + ALLOCATE(DstElementData%OLD_A_NS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%OLD_A_NS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%OLD_A_NS = SrcElementData%OLD_A_NS +ENDIF +IF (ALLOCATED(SrcElementData%OLD_AP_NS)) THEN + i1_l = LBOUND(SrcElementData%OLD_AP_NS,1) + i1_u = UBOUND(SrcElementData%OLD_AP_NS,1) + i2_l = LBOUND(SrcElementData%OLD_AP_NS,2) + i2_u = UBOUND(SrcElementData%OLD_AP_NS,2) + IF (.NOT. ALLOCATED(DstElementData%OLD_AP_NS)) THEN + ALLOCATE(DstElementData%OLD_AP_NS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%OLD_AP_NS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%OLD_AP_NS = SrcElementData%OLD_AP_NS +ENDIF +IF (ALLOCATED(SrcElementData%PITNOW)) THEN + i1_l = LBOUND(SrcElementData%PITNOW,1) + i1_u = UBOUND(SrcElementData%PITNOW,1) + i2_l = LBOUND(SrcElementData%PITNOW,2) + i2_u = UBOUND(SrcElementData%PITNOW,2) + IF (.NOT. ALLOCATED(DstElementData%PITNOW)) THEN + ALLOCATE(DstElementData%PITNOW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementData%PITNOW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementData%PITNOW = SrcElementData%PITNOW +ENDIF + END SUBROUTINE AD14_CopyElement + + SUBROUTINE AD14_DestroyElement( ElementData, ErrStat, ErrMsg ) + TYPE(Element), INTENT(INOUT) :: ElementData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyElement' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ElementData%A)) THEN + DEALLOCATE(ElementData%A) +ENDIF +IF (ALLOCATED(ElementData%AP)) THEN + DEALLOCATE(ElementData%AP) +ENDIF +IF (ALLOCATED(ElementData%ALPHA)) THEN + DEALLOCATE(ElementData%ALPHA) +ENDIF +IF (ALLOCATED(ElementData%W2)) THEN + DEALLOCATE(ElementData%W2) +ENDIF +IF (ALLOCATED(ElementData%OLD_A_NS)) THEN + DEALLOCATE(ElementData%OLD_A_NS) +ENDIF +IF (ALLOCATED(ElementData%OLD_AP_NS)) THEN + DEALLOCATE(ElementData%OLD_AP_NS) +ENDIF +IF (ALLOCATED(ElementData%PITNOW)) THEN + DEALLOCATE(ElementData%PITNOW) +ENDIF + END SUBROUTINE AD14_DestroyElement + + SUBROUTINE AD14_PackElement( 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(Element), 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 = 'AD14_PackElement' + ! 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 ! A allocated yes/no + IF ( ALLOCATED(InData%A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! A upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%A) ! A + END IF + Int_BufSz = Int_BufSz + 1 ! AP allocated yes/no + IF ( ALLOCATED(InData%AP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AP) ! AP + END IF + Int_BufSz = Int_BufSz + 1 ! ALPHA allocated yes/no + IF ( ALLOCATED(InData%ALPHA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ALPHA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ALPHA) ! ALPHA + END IF + Int_BufSz = Int_BufSz + 1 ! W2 allocated yes/no + IF ( ALLOCATED(InData%W2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! W2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%W2) ! W2 + END IF + Int_BufSz = Int_BufSz + 1 ! OLD_A_NS allocated yes/no + IF ( ALLOCATED(InData%OLD_A_NS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLD_A_NS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLD_A_NS) ! OLD_A_NS + END IF + Int_BufSz = Int_BufSz + 1 ! OLD_AP_NS allocated yes/no + IF ( ALLOCATED(InData%OLD_AP_NS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OLD_AP_NS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OLD_AP_NS) ! OLD_AP_NS + END IF + Int_BufSz = Int_BufSz + 1 ! PITNOW allocated yes/no + IF ( ALLOCATED(InData%PITNOW) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PITNOW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PITNOW) ! PITNOW + 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%A) ) 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%A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%A,2), UBOUND(InData%A,2) + DO i1 = LBOUND(InData%A,1), UBOUND(InData%A,1) + ReKiBuf(Re_Xferred) = InData%A(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AP) ) 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%AP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AP,2), UBOUND(InData%AP,2) + DO i1 = LBOUND(InData%AP,1), UBOUND(InData%AP,1) + ReKiBuf(Re_Xferred) = InData%AP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ALPHA) ) 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%ALPHA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ALPHA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ALPHA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ALPHA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ALPHA,2), UBOUND(InData%ALPHA,2) + DO i1 = LBOUND(InData%ALPHA,1), UBOUND(InData%ALPHA,1) + ReKiBuf(Re_Xferred) = InData%ALPHA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%W2) ) 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%W2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%W2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%W2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%W2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%W2,2), UBOUND(InData%W2,2) + DO i1 = LBOUND(InData%W2,1), UBOUND(InData%W2,1) + ReKiBuf(Re_Xferred) = InData%W2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLD_A_NS) ) 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%OLD_A_NS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLD_A_NS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLD_A_NS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLD_A_NS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLD_A_NS,2), UBOUND(InData%OLD_A_NS,2) + DO i1 = LBOUND(InData%OLD_A_NS,1), UBOUND(InData%OLD_A_NS,1) + ReKiBuf(Re_Xferred) = InData%OLD_A_NS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OLD_AP_NS) ) 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%OLD_AP_NS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLD_AP_NS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OLD_AP_NS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OLD_AP_NS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OLD_AP_NS,2), UBOUND(InData%OLD_AP_NS,2) + DO i1 = LBOUND(InData%OLD_AP_NS,1), UBOUND(InData%OLD_AP_NS,1) + ReKiBuf(Re_Xferred) = InData%OLD_AP_NS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PITNOW) ) 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%PITNOW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PITNOW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PITNOW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PITNOW,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PITNOW,2), UBOUND(InData%PITNOW,2) + DO i1 = LBOUND(InData%PITNOW,1), UBOUND(InData%PITNOW,1) + ReKiBuf(Re_Xferred) = InData%PITNOW(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD14_PackElement + + SUBROUTINE AD14_UnPackElement( 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(Element), 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 = 'AD14_UnPackElement' + ! 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 ! A 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%A)) DEALLOCATE(OutData%A) + ALLOCATE(OutData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%A,2), UBOUND(OutData%A,2) + DO i1 = LBOUND(OutData%A,1), UBOUND(OutData%A,1) + OutData%A(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AP 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%AP)) DEALLOCATE(OutData%AP) + ALLOCATE(OutData%AP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AP,2), UBOUND(OutData%AP,2) + DO i1 = LBOUND(OutData%AP,1), UBOUND(OutData%AP,1) + OutData%AP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ALPHA 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%ALPHA)) DEALLOCATE(OutData%ALPHA) + ALLOCATE(OutData%ALPHA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ALPHA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ALPHA,2), UBOUND(OutData%ALPHA,2) + DO i1 = LBOUND(OutData%ALPHA,1), UBOUND(OutData%ALPHA,1) + OutData%ALPHA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! W2 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%W2)) DEALLOCATE(OutData%W2) + ALLOCATE(OutData%W2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%W2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%W2,2), UBOUND(OutData%W2,2) + DO i1 = LBOUND(OutData%W2,1), UBOUND(OutData%W2,1) + OutData%W2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLD_A_NS 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%OLD_A_NS)) DEALLOCATE(OutData%OLD_A_NS) + ALLOCATE(OutData%OLD_A_NS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLD_A_NS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLD_A_NS,2), UBOUND(OutData%OLD_A_NS,2) + DO i1 = LBOUND(OutData%OLD_A_NS,1), UBOUND(OutData%OLD_A_NS,1) + OutData%OLD_A_NS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OLD_AP_NS 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%OLD_AP_NS)) DEALLOCATE(OutData%OLD_AP_NS) + ALLOCATE(OutData%OLD_AP_NS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OLD_AP_NS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OLD_AP_NS,2), UBOUND(OutData%OLD_AP_NS,2) + DO i1 = LBOUND(OutData%OLD_AP_NS,1), UBOUND(OutData%OLD_AP_NS,1) + OutData%OLD_AP_NS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PITNOW 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%PITNOW)) DEALLOCATE(OutData%PITNOW) + ALLOCATE(OutData%PITNOW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PITNOW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PITNOW,2), UBOUND(OutData%PITNOW,2) + DO i1 = LBOUND(OutData%PITNOW,1), UBOUND(OutData%PITNOW,1) + OutData%PITNOW(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE AD14_UnPackElement + + SUBROUTINE AD14_CopyElementParms( SrcElementParmsData, DstElementParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElementParms), INTENT(IN) :: SrcElementParmsData + TYPE(ElementParms), INTENT(INOUT) :: DstElementParmsData + 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 = 'AD14_CopyElementParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElementParmsData%NELM = SrcElementParmsData%NELM +IF (ALLOCATED(SrcElementParmsData%TWIST)) THEN + i1_l = LBOUND(SrcElementParmsData%TWIST,1) + i1_u = UBOUND(SrcElementParmsData%TWIST,1) + IF (.NOT. ALLOCATED(DstElementParmsData%TWIST)) THEN + ALLOCATE(DstElementParmsData%TWIST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementParmsData%TWIST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementParmsData%TWIST = SrcElementParmsData%TWIST +ENDIF +IF (ALLOCATED(SrcElementParmsData%RELM)) THEN + i1_l = LBOUND(SrcElementParmsData%RELM,1) + i1_u = UBOUND(SrcElementParmsData%RELM,1) + IF (.NOT. ALLOCATED(DstElementParmsData%RELM)) THEN + ALLOCATE(DstElementParmsData%RELM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementParmsData%RELM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementParmsData%RELM = SrcElementParmsData%RELM +ENDIF +IF (ALLOCATED(SrcElementParmsData%HLCNST)) THEN + i1_l = LBOUND(SrcElementParmsData%HLCNST,1) + i1_u = UBOUND(SrcElementParmsData%HLCNST,1) + IF (.NOT. ALLOCATED(DstElementParmsData%HLCNST)) THEN + ALLOCATE(DstElementParmsData%HLCNST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementParmsData%HLCNST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementParmsData%HLCNST = SrcElementParmsData%HLCNST +ENDIF +IF (ALLOCATED(SrcElementParmsData%TLCNST)) THEN + i1_l = LBOUND(SrcElementParmsData%TLCNST,1) + i1_u = UBOUND(SrcElementParmsData%TLCNST,1) + IF (.NOT. ALLOCATED(DstElementParmsData%TLCNST)) THEN + ALLOCATE(DstElementParmsData%TLCNST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElementParmsData%TLCNST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElementParmsData%TLCNST = SrcElementParmsData%TLCNST +ENDIF + END SUBROUTINE AD14_CopyElementParms + + SUBROUTINE AD14_DestroyElementParms( ElementParmsData, ErrStat, ErrMsg ) + TYPE(ElementParms), INTENT(INOUT) :: ElementParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyElementParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ElementParmsData%TWIST)) THEN + DEALLOCATE(ElementParmsData%TWIST) +ENDIF +IF (ALLOCATED(ElementParmsData%RELM)) THEN + DEALLOCATE(ElementParmsData%RELM) +ENDIF +IF (ALLOCATED(ElementParmsData%HLCNST)) THEN + DEALLOCATE(ElementParmsData%HLCNST) +ENDIF +IF (ALLOCATED(ElementParmsData%TLCNST)) THEN + DEALLOCATE(ElementParmsData%TLCNST) +ENDIF + END SUBROUTINE AD14_DestroyElementParms + + SUBROUTINE AD14_PackElementParms( 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(ElementParms), 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 = 'AD14_PackElementParms' + ! 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 ! NELM + Int_BufSz = Int_BufSz + 1 ! TWIST allocated yes/no + IF ( ALLOCATED(InData%TWIST) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TWIST upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TWIST) ! TWIST + END IF + Int_BufSz = Int_BufSz + 1 ! RELM allocated yes/no + IF ( ALLOCATED(InData%RELM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RELM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RELM) ! RELM + END IF + Int_BufSz = Int_BufSz + 1 ! HLCNST allocated yes/no + IF ( ALLOCATED(InData%HLCNST) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! HLCNST upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HLCNST) ! HLCNST + END IF + Int_BufSz = Int_BufSz + 1 ! TLCNST allocated yes/no + IF ( ALLOCATED(InData%TLCNST) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TLCNST upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TLCNST) ! TLCNST + 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%NELM + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TWIST) ) 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%TWIST,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TWIST,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TWIST,1), UBOUND(InData%TWIST,1) + ReKiBuf(Re_Xferred) = InData%TWIST(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RELM) ) 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%RELM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RELM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RELM,1), UBOUND(InData%RELM,1) + ReKiBuf(Re_Xferred) = InData%RELM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%HLCNST) ) 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%HLCNST,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HLCNST,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%HLCNST,1), UBOUND(InData%HLCNST,1) + ReKiBuf(Re_Xferred) = InData%HLCNST(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TLCNST) ) 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%TLCNST,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TLCNST,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TLCNST,1), UBOUND(InData%TLCNST,1) + ReKiBuf(Re_Xferred) = InData%TLCNST(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD14_PackElementParms + + SUBROUTINE AD14_UnPackElementParms( 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(ElementParms), 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 = 'AD14_UnPackElementParms' + ! 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%NELM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TWIST 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%TWIST)) DEALLOCATE(OutData%TWIST) + ALLOCATE(OutData%TWIST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TWIST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TWIST,1), UBOUND(OutData%TWIST,1) + OutData%TWIST(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RELM 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%RELM)) DEALLOCATE(OutData%RELM) + ALLOCATE(OutData%RELM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RELM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RELM,1), UBOUND(OutData%RELM,1) + OutData%RELM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HLCNST 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%HLCNST)) DEALLOCATE(OutData%HLCNST) + ALLOCATE(OutData%HLCNST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HLCNST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%HLCNST,1), UBOUND(OutData%HLCNST,1) + OutData%HLCNST(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TLCNST 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%TLCNST)) DEALLOCATE(OutData%TLCNST) + ALLOCATE(OutData%TLCNST(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TLCNST.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TLCNST,1), UBOUND(OutData%TLCNST,1) + OutData%TLCNST(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD14_UnPackElementParms + + SUBROUTINE AD14_CopyElOutParms( SrcElOutParmsData, DstElOutParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElOutParms), INTENT(IN) :: SrcElOutParmsData + TYPE(ElOutParms), INTENT(INOUT) :: DstElOutParmsData + 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 = 'AD14_CopyElOutParms' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcElOutParmsData%AAA)) THEN + i1_l = LBOUND(SrcElOutParmsData%AAA,1) + i1_u = UBOUND(SrcElOutParmsData%AAA,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%AAA)) THEN + ALLOCATE(DstElOutParmsData%AAA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%AAA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%AAA = SrcElOutParmsData%AAA +ENDIF +IF (ALLOCATED(SrcElOutParmsData%AAP)) THEN + i1_l = LBOUND(SrcElOutParmsData%AAP,1) + i1_u = UBOUND(SrcElOutParmsData%AAP,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%AAP)) THEN + ALLOCATE(DstElOutParmsData%AAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%AAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%AAP = SrcElOutParmsData%AAP +ENDIF +IF (ALLOCATED(SrcElOutParmsData%ALF)) THEN + i1_l = LBOUND(SrcElOutParmsData%ALF,1) + i1_u = UBOUND(SrcElOutParmsData%ALF,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%ALF)) THEN + ALLOCATE(DstElOutParmsData%ALF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%ALF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%ALF = SrcElOutParmsData%ALF +ENDIF +IF (ALLOCATED(SrcElOutParmsData%CDD)) THEN + i1_l = LBOUND(SrcElOutParmsData%CDD,1) + i1_u = UBOUND(SrcElOutParmsData%CDD,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%CDD)) THEN + ALLOCATE(DstElOutParmsData%CDD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%CDD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%CDD = SrcElOutParmsData%CDD +ENDIF +IF (ALLOCATED(SrcElOutParmsData%CLL)) THEN + i1_l = LBOUND(SrcElOutParmsData%CLL,1) + i1_u = UBOUND(SrcElOutParmsData%CLL,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%CLL)) THEN + ALLOCATE(DstElOutParmsData%CLL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%CLL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%CLL = SrcElOutParmsData%CLL +ENDIF +IF (ALLOCATED(SrcElOutParmsData%CMM)) THEN + i1_l = LBOUND(SrcElOutParmsData%CMM,1) + i1_u = UBOUND(SrcElOutParmsData%CMM,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%CMM)) THEN + ALLOCATE(DstElOutParmsData%CMM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%CMM = SrcElOutParmsData%CMM +ENDIF +IF (ALLOCATED(SrcElOutParmsData%CNN)) THEN + i1_l = LBOUND(SrcElOutParmsData%CNN,1) + i1_u = UBOUND(SrcElOutParmsData%CNN,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%CNN)) THEN + ALLOCATE(DstElOutParmsData%CNN(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%CNN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%CNN = SrcElOutParmsData%CNN +ENDIF +IF (ALLOCATED(SrcElOutParmsData%CTT)) THEN + i1_l = LBOUND(SrcElOutParmsData%CTT,1) + i1_u = UBOUND(SrcElOutParmsData%CTT,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%CTT)) THEN + ALLOCATE(DstElOutParmsData%CTT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%CTT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%CTT = SrcElOutParmsData%CTT +ENDIF +IF (ALLOCATED(SrcElOutParmsData%DFNSAV)) THEN + i1_l = LBOUND(SrcElOutParmsData%DFNSAV,1) + i1_u = UBOUND(SrcElOutParmsData%DFNSAV,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%DFNSAV)) THEN + ALLOCATE(DstElOutParmsData%DFNSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%DFNSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%DFNSAV = SrcElOutParmsData%DFNSAV +ENDIF +IF (ALLOCATED(SrcElOutParmsData%DFTSAV)) THEN + i1_l = LBOUND(SrcElOutParmsData%DFTSAV,1) + i1_u = UBOUND(SrcElOutParmsData%DFTSAV,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%DFTSAV)) THEN + ALLOCATE(DstElOutParmsData%DFTSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%DFTSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%DFTSAV = SrcElOutParmsData%DFTSAV +ENDIF +IF (ALLOCATED(SrcElOutParmsData%DynPres)) THEN + i1_l = LBOUND(SrcElOutParmsData%DynPres,1) + i1_u = UBOUND(SrcElOutParmsData%DynPres,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%DynPres)) THEN + ALLOCATE(DstElOutParmsData%DynPres(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%DynPres.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%DynPres = SrcElOutParmsData%DynPres +ENDIF +IF (ALLOCATED(SrcElOutParmsData%PMM)) THEN + i1_l = LBOUND(SrcElOutParmsData%PMM,1) + i1_u = UBOUND(SrcElOutParmsData%PMM,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%PMM)) THEN + ALLOCATE(DstElOutParmsData%PMM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%PMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%PMM = SrcElOutParmsData%PMM +ENDIF +IF (ALLOCATED(SrcElOutParmsData%PITSAV)) THEN + i1_l = LBOUND(SrcElOutParmsData%PITSAV,1) + i1_u = UBOUND(SrcElOutParmsData%PITSAV,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%PITSAV)) THEN + ALLOCATE(DstElOutParmsData%PITSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%PITSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%PITSAV = SrcElOutParmsData%PITSAV +ENDIF +IF (ALLOCATED(SrcElOutParmsData%ReyNum)) THEN + i1_l = LBOUND(SrcElOutParmsData%ReyNum,1) + i1_u = UBOUND(SrcElOutParmsData%ReyNum,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%ReyNum)) THEN + ALLOCATE(DstElOutParmsData%ReyNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%ReyNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%ReyNum = SrcElOutParmsData%ReyNum +ENDIF +IF (ALLOCATED(SrcElOutParmsData%Gamma)) THEN + i1_l = LBOUND(SrcElOutParmsData%Gamma,1) + i1_u = UBOUND(SrcElOutParmsData%Gamma,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%Gamma)) THEN + ALLOCATE(DstElOutParmsData%Gamma(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%Gamma.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%Gamma = SrcElOutParmsData%Gamma +ENDIF +IF (ALLOCATED(SrcElOutParmsData%SaveVX)) THEN + i1_l = LBOUND(SrcElOutParmsData%SaveVX,1) + i1_u = UBOUND(SrcElOutParmsData%SaveVX,1) + i2_l = LBOUND(SrcElOutParmsData%SaveVX,2) + i2_u = UBOUND(SrcElOutParmsData%SaveVX,2) + IF (.NOT. ALLOCATED(DstElOutParmsData%SaveVX)) THEN + ALLOCATE(DstElOutParmsData%SaveVX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%SaveVX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%SaveVX = SrcElOutParmsData%SaveVX +ENDIF +IF (ALLOCATED(SrcElOutParmsData%SaveVY)) THEN + i1_l = LBOUND(SrcElOutParmsData%SaveVY,1) + i1_u = UBOUND(SrcElOutParmsData%SaveVY,1) + i2_l = LBOUND(SrcElOutParmsData%SaveVY,2) + i2_u = UBOUND(SrcElOutParmsData%SaveVY,2) + IF (.NOT. ALLOCATED(DstElOutParmsData%SaveVY)) THEN + ALLOCATE(DstElOutParmsData%SaveVY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%SaveVY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%SaveVY = SrcElOutParmsData%SaveVY +ENDIF +IF (ALLOCATED(SrcElOutParmsData%SaveVZ)) THEN + i1_l = LBOUND(SrcElOutParmsData%SaveVZ,1) + i1_u = UBOUND(SrcElOutParmsData%SaveVZ,1) + i2_l = LBOUND(SrcElOutParmsData%SaveVZ,2) + i2_u = UBOUND(SrcElOutParmsData%SaveVZ,2) + IF (.NOT. ALLOCATED(DstElOutParmsData%SaveVZ)) THEN + ALLOCATE(DstElOutParmsData%SaveVZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%SaveVZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%SaveVZ = SrcElOutParmsData%SaveVZ +ENDIF + DstElOutParmsData%VXSAV = SrcElOutParmsData%VXSAV + DstElOutParmsData%VYSAV = SrcElOutParmsData%VYSAV + DstElOutParmsData%VZSAV = SrcElOutParmsData%VZSAV + DstElOutParmsData%NumWndElOut = SrcElOutParmsData%NumWndElOut +IF (ALLOCATED(SrcElOutParmsData%WndElPrList)) THEN + i1_l = LBOUND(SrcElOutParmsData%WndElPrList,1) + i1_u = UBOUND(SrcElOutParmsData%WndElPrList,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%WndElPrList)) THEN + ALLOCATE(DstElOutParmsData%WndElPrList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%WndElPrList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%WndElPrList = SrcElOutParmsData%WndElPrList +ENDIF +IF (ALLOCATED(SrcElOutParmsData%WndElPrNum)) THEN + i1_l = LBOUND(SrcElOutParmsData%WndElPrNum,1) + i1_u = UBOUND(SrcElOutParmsData%WndElPrNum,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%WndElPrNum)) THEN + ALLOCATE(DstElOutParmsData%WndElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%WndElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%WndElPrNum = SrcElOutParmsData%WndElPrNum +ENDIF +IF (ALLOCATED(SrcElOutParmsData%ElPrList)) THEN + i1_l = LBOUND(SrcElOutParmsData%ElPrList,1) + i1_u = UBOUND(SrcElOutParmsData%ElPrList,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%ElPrList)) THEN + ALLOCATE(DstElOutParmsData%ElPrList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%ElPrList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%ElPrList = SrcElOutParmsData%ElPrList +ENDIF +IF (ALLOCATED(SrcElOutParmsData%ElPrNum)) THEN + i1_l = LBOUND(SrcElOutParmsData%ElPrNum,1) + i1_u = UBOUND(SrcElOutParmsData%ElPrNum,1) + IF (.NOT. ALLOCATED(DstElOutParmsData%ElPrNum)) THEN + ALLOCATE(DstElOutParmsData%ElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElOutParmsData%ElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElOutParmsData%ElPrNum = SrcElOutParmsData%ElPrNum +ENDIF + DstElOutParmsData%NumElOut = SrcElOutParmsData%NumElOut + END SUBROUTINE AD14_CopyElOutParms + + SUBROUTINE AD14_DestroyElOutParms( ElOutParmsData, ErrStat, ErrMsg ) + TYPE(ElOutParms), INTENT(INOUT) :: ElOutParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyElOutParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ElOutParmsData%AAA)) THEN + DEALLOCATE(ElOutParmsData%AAA) +ENDIF +IF (ALLOCATED(ElOutParmsData%AAP)) THEN + DEALLOCATE(ElOutParmsData%AAP) +ENDIF +IF (ALLOCATED(ElOutParmsData%ALF)) THEN + DEALLOCATE(ElOutParmsData%ALF) +ENDIF +IF (ALLOCATED(ElOutParmsData%CDD)) THEN + DEALLOCATE(ElOutParmsData%CDD) +ENDIF +IF (ALLOCATED(ElOutParmsData%CLL)) THEN + DEALLOCATE(ElOutParmsData%CLL) +ENDIF +IF (ALLOCATED(ElOutParmsData%CMM)) THEN + DEALLOCATE(ElOutParmsData%CMM) +ENDIF +IF (ALLOCATED(ElOutParmsData%CNN)) THEN + DEALLOCATE(ElOutParmsData%CNN) +ENDIF +IF (ALLOCATED(ElOutParmsData%CTT)) THEN + DEALLOCATE(ElOutParmsData%CTT) +ENDIF +IF (ALLOCATED(ElOutParmsData%DFNSAV)) THEN + DEALLOCATE(ElOutParmsData%DFNSAV) +ENDIF +IF (ALLOCATED(ElOutParmsData%DFTSAV)) THEN + DEALLOCATE(ElOutParmsData%DFTSAV) +ENDIF +IF (ALLOCATED(ElOutParmsData%DynPres)) THEN + DEALLOCATE(ElOutParmsData%DynPres) +ENDIF +IF (ALLOCATED(ElOutParmsData%PMM)) THEN + DEALLOCATE(ElOutParmsData%PMM) +ENDIF +IF (ALLOCATED(ElOutParmsData%PITSAV)) THEN + DEALLOCATE(ElOutParmsData%PITSAV) +ENDIF +IF (ALLOCATED(ElOutParmsData%ReyNum)) THEN + DEALLOCATE(ElOutParmsData%ReyNum) +ENDIF +IF (ALLOCATED(ElOutParmsData%Gamma)) THEN + DEALLOCATE(ElOutParmsData%Gamma) +ENDIF +IF (ALLOCATED(ElOutParmsData%SaveVX)) THEN + DEALLOCATE(ElOutParmsData%SaveVX) +ENDIF +IF (ALLOCATED(ElOutParmsData%SaveVY)) THEN + DEALLOCATE(ElOutParmsData%SaveVY) +ENDIF +IF (ALLOCATED(ElOutParmsData%SaveVZ)) THEN + DEALLOCATE(ElOutParmsData%SaveVZ) +ENDIF +IF (ALLOCATED(ElOutParmsData%WndElPrList)) THEN + DEALLOCATE(ElOutParmsData%WndElPrList) +ENDIF +IF (ALLOCATED(ElOutParmsData%WndElPrNum)) THEN + DEALLOCATE(ElOutParmsData%WndElPrNum) +ENDIF +IF (ALLOCATED(ElOutParmsData%ElPrList)) THEN + DEALLOCATE(ElOutParmsData%ElPrList) +ENDIF +IF (ALLOCATED(ElOutParmsData%ElPrNum)) THEN + DEALLOCATE(ElOutParmsData%ElPrNum) +ENDIF + END SUBROUTINE AD14_DestroyElOutParms + + SUBROUTINE AD14_PackElOutParms( 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(ElOutParms), 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 = 'AD14_PackElOutParms' + ! 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 ! AAA allocated yes/no + IF ( ALLOCATED(InData%AAA) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AAA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AAA) ! AAA + END IF + Int_BufSz = Int_BufSz + 1 ! AAP allocated yes/no + IF ( ALLOCATED(InData%AAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AAP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AAP) ! AAP + END IF + Int_BufSz = Int_BufSz + 1 ! ALF allocated yes/no + IF ( ALLOCATED(InData%ALF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ALF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ALF) ! ALF + END IF + Int_BufSz = Int_BufSz + 1 ! CDD allocated yes/no + IF ( ALLOCATED(InData%CDD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CDD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CDD) ! CDD + END IF + Int_BufSz = Int_BufSz + 1 ! CLL allocated yes/no + IF ( ALLOCATED(InData%CLL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CLL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CLL) ! CLL + END IF + Int_BufSz = Int_BufSz + 1 ! CMM allocated yes/no + IF ( ALLOCATED(InData%CMM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CMM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMM) ! CMM + END IF + Int_BufSz = Int_BufSz + 1 ! CNN allocated yes/no + IF ( ALLOCATED(InData%CNN) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CNN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CNN) ! CNN + END IF + Int_BufSz = Int_BufSz + 1 ! CTT allocated yes/no + IF ( ALLOCATED(InData%CTT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CTT upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CTT) ! CTT + END IF + Int_BufSz = Int_BufSz + 1 ! DFNSAV allocated yes/no + IF ( ALLOCATED(InData%DFNSAV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DFNSAV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DFNSAV) ! DFNSAV + END IF + Int_BufSz = Int_BufSz + 1 ! DFTSAV allocated yes/no + IF ( ALLOCATED(InData%DFTSAV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DFTSAV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DFTSAV) ! DFTSAV + END IF + Int_BufSz = Int_BufSz + 1 ! DynPres allocated yes/no + IF ( ALLOCATED(InData%DynPres) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DynPres upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DynPres) ! DynPres + END IF + Int_BufSz = Int_BufSz + 1 ! PMM allocated yes/no + IF ( ALLOCATED(InData%PMM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PMM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMM) ! PMM + END IF + Int_BufSz = Int_BufSz + 1 ! PITSAV allocated yes/no + IF ( ALLOCATED(InData%PITSAV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PITSAV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PITSAV) ! PITSAV + END IF + Int_BufSz = Int_BufSz + 1 ! ReyNum allocated yes/no + IF ( ALLOCATED(InData%ReyNum) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ReyNum upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ReyNum) ! ReyNum + END IF + Int_BufSz = Int_BufSz + 1 ! Gamma allocated yes/no + IF ( ALLOCATED(InData%Gamma) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Gamma upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Gamma) ! Gamma + END IF + Int_BufSz = Int_BufSz + 1 ! SaveVX allocated yes/no + IF ( ALLOCATED(InData%SaveVX) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SaveVX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SaveVX) ! SaveVX + END IF + Int_BufSz = Int_BufSz + 1 ! SaveVY allocated yes/no + IF ( ALLOCATED(InData%SaveVY) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SaveVY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SaveVY) ! SaveVY + END IF + Int_BufSz = Int_BufSz + 1 ! SaveVZ allocated yes/no + IF ( ALLOCATED(InData%SaveVZ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SaveVZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SaveVZ) ! SaveVZ + END IF + Re_BufSz = Re_BufSz + 1 ! VXSAV + Re_BufSz = Re_BufSz + 1 ! VYSAV + Re_BufSz = Re_BufSz + 1 ! VZSAV + Int_BufSz = Int_BufSz + 1 ! NumWndElOut + Int_BufSz = Int_BufSz + 1 ! WndElPrList allocated yes/no + IF ( ALLOCATED(InData%WndElPrList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WndElPrList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WndElPrList) ! WndElPrList + END IF + Int_BufSz = Int_BufSz + 1 ! WndElPrNum allocated yes/no + IF ( ALLOCATED(InData%WndElPrNum) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WndElPrNum upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WndElPrNum) ! WndElPrNum + END IF + Int_BufSz = Int_BufSz + 1 ! ElPrList allocated yes/no + IF ( ALLOCATED(InData%ElPrList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElPrList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElPrList) ! ElPrList + END IF + Int_BufSz = Int_BufSz + 1 ! ElPrNum allocated yes/no + IF ( ALLOCATED(InData%ElPrNum) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElPrNum upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElPrNum) ! ElPrNum + END IF + Int_BufSz = Int_BufSz + 1 ! NumElOut + 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%AAA) ) 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%AAA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AAA,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AAA,1), UBOUND(InData%AAA,1) + ReKiBuf(Re_Xferred) = InData%AAA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AAP) ) 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%AAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AAP,1), UBOUND(InData%AAP,1) + ReKiBuf(Re_Xferred) = InData%AAP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ALF) ) 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%ALF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ALF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ALF,1), UBOUND(InData%ALF,1) + ReKiBuf(Re_Xferred) = InData%ALF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CDD) ) 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%CDD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CDD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CDD,1), UBOUND(InData%CDD,1) + ReKiBuf(Re_Xferred) = InData%CDD(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CLL) ) 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%CLL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CLL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CLL,1), UBOUND(InData%CLL,1) + ReKiBuf(Re_Xferred) = InData%CLL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CMM) ) 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%CMM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CMM,1), UBOUND(InData%CMM,1) + ReKiBuf(Re_Xferred) = InData%CMM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CNN) ) 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%CNN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CNN,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CNN,1), UBOUND(InData%CNN,1) + ReKiBuf(Re_Xferred) = InData%CNN(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CTT) ) 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%CTT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CTT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CTT,1), UBOUND(InData%CTT,1) + ReKiBuf(Re_Xferred) = InData%CTT(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DFNSAV) ) 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%DFNSAV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFNSAV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DFNSAV,1), UBOUND(InData%DFNSAV,1) + ReKiBuf(Re_Xferred) = InData%DFNSAV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DFTSAV) ) 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%DFTSAV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DFTSAV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DFTSAV,1), UBOUND(InData%DFTSAV,1) + ReKiBuf(Re_Xferred) = InData%DFTSAV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DynPres) ) 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%DynPres,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DynPres,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DynPres,1), UBOUND(InData%DynPres,1) + ReKiBuf(Re_Xferred) = InData%DynPres(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMM) ) 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%PMM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PMM,1), UBOUND(InData%PMM,1) + ReKiBuf(Re_Xferred) = InData%PMM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PITSAV) ) 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%PITSAV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PITSAV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PITSAV,1), UBOUND(InData%PITSAV,1) + ReKiBuf(Re_Xferred) = InData%PITSAV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ReyNum) ) 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%ReyNum,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ReyNum,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ReyNum,1), UBOUND(InData%ReyNum,1) + ReKiBuf(Re_Xferred) = InData%ReyNum(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Gamma) ) 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%Gamma,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gamma,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Gamma,1), UBOUND(InData%Gamma,1) + ReKiBuf(Re_Xferred) = InData%Gamma(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SaveVX) ) 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%SaveVX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVX,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SaveVX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVX,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SaveVX,2), UBOUND(InData%SaveVX,2) + DO i1 = LBOUND(InData%SaveVX,1), UBOUND(InData%SaveVX,1) + ReKiBuf(Re_Xferred) = InData%SaveVX(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SaveVY) ) 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%SaveVY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SaveVY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVY,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SaveVY,2), UBOUND(InData%SaveVY,2) + DO i1 = LBOUND(InData%SaveVY,1), UBOUND(InData%SaveVY,1) + ReKiBuf(Re_Xferred) = InData%SaveVY(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SaveVZ) ) 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%SaveVZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVZ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SaveVZ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SaveVZ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SaveVZ,2), UBOUND(InData%SaveVZ,2) + DO i1 = LBOUND(InData%SaveVZ,1), UBOUND(InData%SaveVZ,1) + ReKiBuf(Re_Xferred) = InData%SaveVZ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%VXSAV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VYSAV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VZSAV + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumWndElOut + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WndElPrList) ) 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%WndElPrList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WndElPrList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WndElPrList,1), UBOUND(InData%WndElPrList,1) + IntKiBuf(Int_Xferred) = InData%WndElPrList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WndElPrNum) ) 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%WndElPrNum,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WndElPrNum,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WndElPrNum,1), UBOUND(InData%WndElPrNum,1) + IntKiBuf(Int_Xferred) = InData%WndElPrNum(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElPrList) ) 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%ElPrList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElPrList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElPrList,1), UBOUND(InData%ElPrList,1) + IntKiBuf(Int_Xferred) = InData%ElPrList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElPrNum) ) 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%ElPrNum,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElPrNum,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElPrNum,1), UBOUND(InData%ElPrNum,1) + IntKiBuf(Int_Xferred) = InData%ElPrNum(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumElOut + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_PackElOutParms + + SUBROUTINE AD14_UnPackElOutParms( 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(ElOutParms), 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 = 'AD14_UnPackElOutParms' + ! 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 ! AAA 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%AAA)) DEALLOCATE(OutData%AAA) + ALLOCATE(OutData%AAA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AAA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AAA,1), UBOUND(OutData%AAA,1) + OutData%AAA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AAP 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%AAP)) DEALLOCATE(OutData%AAP) + ALLOCATE(OutData%AAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AAP,1), UBOUND(OutData%AAP,1) + OutData%AAP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ALF 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%ALF)) DEALLOCATE(OutData%ALF) + ALLOCATE(OutData%ALF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ALF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ALF,1), UBOUND(OutData%ALF,1) + OutData%ALF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CDD 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%CDD)) DEALLOCATE(OutData%CDD) + ALLOCATE(OutData%CDD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CDD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CDD,1), UBOUND(OutData%CDD,1) + OutData%CDD(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CLL 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%CLL)) DEALLOCATE(OutData%CLL) + ALLOCATE(OutData%CLL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CLL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CLL,1), UBOUND(OutData%CLL,1) + OutData%CLL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM 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%CMM)) DEALLOCATE(OutData%CMM) + ALLOCATE(OutData%CMM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CMM,1), UBOUND(OutData%CMM,1) + OutData%CMM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CNN 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%CNN)) DEALLOCATE(OutData%CNN) + ALLOCATE(OutData%CNN(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CNN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CNN,1), UBOUND(OutData%CNN,1) + OutData%CNN(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CTT 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%CTT)) DEALLOCATE(OutData%CTT) + ALLOCATE(OutData%CTT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CTT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CTT,1), UBOUND(OutData%CTT,1) + OutData%CTT(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DFNSAV 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%DFNSAV)) DEALLOCATE(OutData%DFNSAV) + ALLOCATE(OutData%DFNSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DFNSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DFNSAV,1), UBOUND(OutData%DFNSAV,1) + OutData%DFNSAV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DFTSAV 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%DFTSAV)) DEALLOCATE(OutData%DFTSAV) + ALLOCATE(OutData%DFTSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DFTSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DFTSAV,1), UBOUND(OutData%DFTSAV,1) + OutData%DFTSAV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DynPres 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%DynPres)) DEALLOCATE(OutData%DynPres) + ALLOCATE(OutData%DynPres(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DynPres.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DynPres,1), UBOUND(OutData%DynPres,1) + OutData%DynPres(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMM 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%PMM)) DEALLOCATE(OutData%PMM) + ALLOCATE(OutData%PMM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PMM,1), UBOUND(OutData%PMM,1) + OutData%PMM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PITSAV 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%PITSAV)) DEALLOCATE(OutData%PITSAV) + ALLOCATE(OutData%PITSAV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PITSAV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PITSAV,1), UBOUND(OutData%PITSAV,1) + OutData%PITSAV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ReyNum 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%ReyNum)) DEALLOCATE(OutData%ReyNum) + ALLOCATE(OutData%ReyNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ReyNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ReyNum,1), UBOUND(OutData%ReyNum,1) + OutData%ReyNum(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gamma 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%Gamma)) DEALLOCATE(OutData%Gamma) + ALLOCATE(OutData%Gamma(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Gamma.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Gamma,1), UBOUND(OutData%Gamma,1) + OutData%Gamma(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SaveVX 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%SaveVX)) DEALLOCATE(OutData%SaveVX) + ALLOCATE(OutData%SaveVX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SaveVX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SaveVX,2), UBOUND(OutData%SaveVX,2) + DO i1 = LBOUND(OutData%SaveVX,1), UBOUND(OutData%SaveVX,1) + OutData%SaveVX(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SaveVY 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%SaveVY)) DEALLOCATE(OutData%SaveVY) + ALLOCATE(OutData%SaveVY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SaveVY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SaveVY,2), UBOUND(OutData%SaveVY,2) + DO i1 = LBOUND(OutData%SaveVY,1), UBOUND(OutData%SaveVY,1) + OutData%SaveVY(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SaveVZ 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%SaveVZ)) DEALLOCATE(OutData%SaveVZ) + ALLOCATE(OutData%SaveVZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SaveVZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SaveVZ,2), UBOUND(OutData%SaveVZ,2) + DO i1 = LBOUND(OutData%SaveVZ,1), UBOUND(OutData%SaveVZ,1) + OutData%SaveVZ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%VXSAV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VYSAV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VZSAV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumWndElOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WndElPrList 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%WndElPrList)) DEALLOCATE(OutData%WndElPrList) + ALLOCATE(OutData%WndElPrList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WndElPrList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WndElPrList,1), UBOUND(OutData%WndElPrList,1) + OutData%WndElPrList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WndElPrNum 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%WndElPrNum)) DEALLOCATE(OutData%WndElPrNum) + ALLOCATE(OutData%WndElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WndElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WndElPrNum,1), UBOUND(OutData%WndElPrNum,1) + OutData%WndElPrNum(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElPrList 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%ElPrList)) DEALLOCATE(OutData%ElPrList) + ALLOCATE(OutData%ElPrList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElPrList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElPrList,1), UBOUND(OutData%ElPrList,1) + OutData%ElPrList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElPrNum 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%ElPrNum)) DEALLOCATE(OutData%ElPrNum) + ALLOCATE(OutData%ElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElPrNum,1), UBOUND(OutData%ElPrNum,1) + OutData%ElPrNum(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NumElOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_UnPackElOutParms + + SUBROUTINE AD14_CopyInducedVel( SrcInducedVelData, DstInducedVelData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InducedVel), INTENT(IN) :: SrcInducedVelData + TYPE(InducedVel), INTENT(INOUT) :: DstInducedVelData + 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 = 'AD14_CopyInducedVel' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInducedVelData%SumInFl = SrcInducedVelData%SumInFl + END SUBROUTINE AD14_CopyInducedVel + + SUBROUTINE AD14_DestroyInducedVel( InducedVelData, ErrStat, ErrMsg ) + TYPE(InducedVel), INTENT(INOUT) :: InducedVelData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyInducedVel' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyInducedVel + + SUBROUTINE AD14_PackInducedVel( 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(InducedVel), 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 = 'AD14_PackInducedVel' + ! 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 ! SumInFl + 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%SumInFl + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackInducedVel + + SUBROUTINE AD14_UnPackInducedVel( 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(InducedVel), 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 = 'AD14_UnPackInducedVel' + ! 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%SumInFl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackInducedVel + + SUBROUTINE AD14_CopyInducedVelParms( SrcInducedVelParmsData, DstInducedVelParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InducedVelParms), INTENT(IN) :: SrcInducedVelParmsData + TYPE(InducedVelParms), INTENT(INOUT) :: DstInducedVelParmsData + 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 = 'AD14_CopyInducedVelParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInducedVelParmsData%AToler = SrcInducedVelParmsData%AToler + DstInducedVelParmsData%EqAIDmult = SrcInducedVelParmsData%EqAIDmult + DstInducedVelParmsData%EquilDA = SrcInducedVelParmsData%EquilDA + DstInducedVelParmsData%EquilDT = SrcInducedVelParmsData%EquilDT + DstInducedVelParmsData%TLoss = SrcInducedVelParmsData%TLoss + DstInducedVelParmsData%GTech = SrcInducedVelParmsData%GTech + DstInducedVelParmsData%HLoss = SrcInducedVelParmsData%HLoss + END SUBROUTINE AD14_CopyInducedVelParms + + SUBROUTINE AD14_DestroyInducedVelParms( InducedVelParmsData, ErrStat, ErrMsg ) + TYPE(InducedVelParms), INTENT(INOUT) :: InducedVelParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyInducedVelParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyInducedVelParms + + SUBROUTINE AD14_PackInducedVelParms( 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(InducedVelParms), 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 = 'AD14_PackInducedVelParms' + ! 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 ! AToler + Re_BufSz = Re_BufSz + 1 ! EqAIDmult + Int_BufSz = Int_BufSz + 1 ! EquilDA + Int_BufSz = Int_BufSz + 1 ! EquilDT + Int_BufSz = Int_BufSz + 1 ! TLoss + Int_BufSz = Int_BufSz + 1 ! GTech + Int_BufSz = Int_BufSz + 1 ! HLoss + 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%AToler + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%EqAIDmult + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%EquilDA, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%EquilDT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GTech, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%HLoss, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_PackInducedVelParms + + SUBROUTINE AD14_UnPackInducedVelParms( 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(InducedVelParms), 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 = 'AD14_UnPackInducedVelParms' + ! 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%AToler = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%EqAIDmult = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%EquilDA = TRANSFER(IntKiBuf(Int_Xferred), OutData%EquilDA) + Int_Xferred = Int_Xferred + 1 + OutData%EquilDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%EquilDT) + Int_Xferred = Int_Xferred + 1 + OutData%TLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%TLoss) + Int_Xferred = Int_Xferred + 1 + OutData%GTech = TRANSFER(IntKiBuf(Int_Xferred), OutData%GTech) + Int_Xferred = Int_Xferred + 1 + OutData%HLoss = TRANSFER(IntKiBuf(Int_Xferred), OutData%HLoss) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE AD14_UnPackInducedVelParms + + SUBROUTINE AD14_CopyRotor( SrcRotorData, DstRotorData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Rotor), INTENT(IN) :: SrcRotorData + TYPE(Rotor), INTENT(INOUT) :: DstRotorData + 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 = 'AD14_CopyRotor' +! + ErrStat = ErrID_None + ErrMsg = "" + DstRotorData%AVGINFL = SrcRotorData%AVGINFL + DstRotorData%CTILT = SrcRotorData%CTILT + DstRotorData%CYaw = SrcRotorData%CYaw + DstRotorData%REVS = SrcRotorData%REVS + DstRotorData%STILT = SrcRotorData%STILT + DstRotorData%SYaw = SrcRotorData%SYaw + DstRotorData%TILT = SrcRotorData%TILT + DstRotorData%YawAng = SrcRotorData%YawAng + DstRotorData%YawVEL = SrcRotorData%YawVEL + END SUBROUTINE AD14_CopyRotor + + SUBROUTINE AD14_DestroyRotor( RotorData, ErrStat, ErrMsg ) + TYPE(Rotor), INTENT(INOUT) :: RotorData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyRotor' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyRotor + + SUBROUTINE AD14_PackRotor( 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(Rotor), 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 = 'AD14_PackRotor' + ! 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 ! AVGINFL + Re_BufSz = Re_BufSz + 1 ! CTILT + Re_BufSz = Re_BufSz + 1 ! CYaw + Re_BufSz = Re_BufSz + 1 ! REVS + Re_BufSz = Re_BufSz + 1 ! STILT + Re_BufSz = Re_BufSz + 1 ! SYaw + Re_BufSz = Re_BufSz + 1 ! TILT + Re_BufSz = Re_BufSz + 1 ! YawAng + Re_BufSz = Re_BufSz + 1 ! YawVEL + 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%AVGINFL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CTILT + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CYaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%REVS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%STILT + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SYaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TILT + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawAng + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawVEL + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackRotor + + SUBROUTINE AD14_UnPackRotor( 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(Rotor), 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 = 'AD14_UnPackRotor' + ! 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%AVGINFL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CTILT = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CYaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%REVS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%STILT = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SYaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TILT = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawAng = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawVEL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackRotor + + SUBROUTINE AD14_CopyRotorParms( SrcRotorParmsData, DstRotorParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(RotorParms), INTENT(IN) :: SrcRotorParmsData + TYPE(RotorParms), INTENT(INOUT) :: DstRotorParmsData + 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 = 'AD14_CopyRotorParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstRotorParmsData%HH = SrcRotorParmsData%HH + END SUBROUTINE AD14_CopyRotorParms + + SUBROUTINE AD14_DestroyRotorParms( RotorParmsData, ErrStat, ErrMsg ) + TYPE(RotorParms), INTENT(INOUT) :: RotorParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyRotorParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyRotorParms + + SUBROUTINE AD14_PackRotorParms( 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(RotorParms), 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 = 'AD14_PackRotorParms' + ! 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 ! HH + 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%HH + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackRotorParms + + SUBROUTINE AD14_UnPackRotorParms( 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(RotorParms), 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 = 'AD14_UnPackRotorParms' + ! 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%HH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackRotorParms + + SUBROUTINE AD14_CopyTwrPropsParms( SrcTwrPropsParmsData, DstTwrPropsParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TwrPropsParms), INTENT(IN) :: SrcTwrPropsParmsData + TYPE(TwrPropsParms), INTENT(INOUT) :: DstTwrPropsParmsData + 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 = 'AD14_CopyTwrPropsParms' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcTwrPropsParmsData%TwrHtFr)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%TwrHtFr,1) + i1_u = UBOUND(SrcTwrPropsParmsData%TwrHtFr,1) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%TwrHtFr)) THEN + ALLOCATE(DstTwrPropsParmsData%TwrHtFr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%TwrHtFr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%TwrHtFr = SrcTwrPropsParmsData%TwrHtFr +ENDIF +IF (ALLOCATED(SrcTwrPropsParmsData%TwrWid)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%TwrWid,1) + i1_u = UBOUND(SrcTwrPropsParmsData%TwrWid,1) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%TwrWid)) THEN + ALLOCATE(DstTwrPropsParmsData%TwrWid(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%TwrWid.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%TwrWid = SrcTwrPropsParmsData%TwrWid +ENDIF +IF (ALLOCATED(SrcTwrPropsParmsData%TwrCD)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%TwrCD,1) + i1_u = UBOUND(SrcTwrPropsParmsData%TwrCD,1) + i2_l = LBOUND(SrcTwrPropsParmsData%TwrCD,2) + i2_u = UBOUND(SrcTwrPropsParmsData%TwrCD,2) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%TwrCD)) THEN + ALLOCATE(DstTwrPropsParmsData%TwrCD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%TwrCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%TwrCD = SrcTwrPropsParmsData%TwrCD +ENDIF +IF (ALLOCATED(SrcTwrPropsParmsData%TwrRe)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%TwrRe,1) + i1_u = UBOUND(SrcTwrPropsParmsData%TwrRe,1) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%TwrRe)) THEN + ALLOCATE(DstTwrPropsParmsData%TwrRe(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%TwrRe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%TwrRe = SrcTwrPropsParmsData%TwrRe +ENDIF + DstTwrPropsParmsData%VTwr = SrcTwrPropsParmsData%VTwr + DstTwrPropsParmsData%Tower_Wake_Constant = SrcTwrPropsParmsData%Tower_Wake_Constant +IF (ALLOCATED(SrcTwrPropsParmsData%NTwrCDCol)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%NTwrCDCol,1) + i1_u = UBOUND(SrcTwrPropsParmsData%NTwrCDCol,1) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%NTwrCDCol)) THEN + ALLOCATE(DstTwrPropsParmsData%NTwrCDCol(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%NTwrCDCol.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%NTwrCDCol = SrcTwrPropsParmsData%NTwrCDCol +ENDIF + DstTwrPropsParmsData%NTwrHT = SrcTwrPropsParmsData%NTwrHT + DstTwrPropsParmsData%NTwrRe = SrcTwrPropsParmsData%NTwrRe + DstTwrPropsParmsData%NTwrCD = SrcTwrPropsParmsData%NTwrCD + DstTwrPropsParmsData%TwrPotent = SrcTwrPropsParmsData%TwrPotent + DstTwrPropsParmsData%TwrShadow = SrcTwrPropsParmsData%TwrShadow + DstTwrPropsParmsData%ShadHWid = SrcTwrPropsParmsData%ShadHWid + DstTwrPropsParmsData%TShadC1 = SrcTwrPropsParmsData%TShadC1 + DstTwrPropsParmsData%TShadC2 = SrcTwrPropsParmsData%TShadC2 + DstTwrPropsParmsData%TwrShad = SrcTwrPropsParmsData%TwrShad + DstTwrPropsParmsData%PJM_Version = SrcTwrPropsParmsData%PJM_Version + DstTwrPropsParmsData%TwrFile = SrcTwrPropsParmsData%TwrFile + DstTwrPropsParmsData%T_Shad_Refpt = SrcTwrPropsParmsData%T_Shad_Refpt + DstTwrPropsParmsData%CalcTwrAero = SrcTwrPropsParmsData%CalcTwrAero + DstTwrPropsParmsData%NumTwrNodes = SrcTwrPropsParmsData%NumTwrNodes +IF (ALLOCATED(SrcTwrPropsParmsData%TwrNodeWidth)) THEN + i1_l = LBOUND(SrcTwrPropsParmsData%TwrNodeWidth,1) + i1_u = UBOUND(SrcTwrPropsParmsData%TwrNodeWidth,1) + IF (.NOT. ALLOCATED(DstTwrPropsParmsData%TwrNodeWidth)) THEN + ALLOCATE(DstTwrPropsParmsData%TwrNodeWidth(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTwrPropsParmsData%TwrNodeWidth.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTwrPropsParmsData%TwrNodeWidth = SrcTwrPropsParmsData%TwrNodeWidth +ENDIF + END SUBROUTINE AD14_CopyTwrPropsParms + + SUBROUTINE AD14_DestroyTwrPropsParms( TwrPropsParmsData, ErrStat, ErrMsg ) + TYPE(TwrPropsParms), INTENT(INOUT) :: TwrPropsParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyTwrPropsParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(TwrPropsParmsData%TwrHtFr)) THEN + DEALLOCATE(TwrPropsParmsData%TwrHtFr) +ENDIF +IF (ALLOCATED(TwrPropsParmsData%TwrWid)) THEN + DEALLOCATE(TwrPropsParmsData%TwrWid) +ENDIF +IF (ALLOCATED(TwrPropsParmsData%TwrCD)) THEN + DEALLOCATE(TwrPropsParmsData%TwrCD) +ENDIF +IF (ALLOCATED(TwrPropsParmsData%TwrRe)) THEN + DEALLOCATE(TwrPropsParmsData%TwrRe) +ENDIF +IF (ALLOCATED(TwrPropsParmsData%NTwrCDCol)) THEN + DEALLOCATE(TwrPropsParmsData%NTwrCDCol) +ENDIF +IF (ALLOCATED(TwrPropsParmsData%TwrNodeWidth)) THEN + DEALLOCATE(TwrPropsParmsData%TwrNodeWidth) +ENDIF + END SUBROUTINE AD14_DestroyTwrPropsParms + + SUBROUTINE AD14_PackTwrPropsParms( 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(TwrPropsParms), 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 = 'AD14_PackTwrPropsParms' + ! 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 ! TwrHtFr allocated yes/no + IF ( ALLOCATED(InData%TwrHtFr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrHtFr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrHtFr) ! TwrHtFr + END IF + Int_BufSz = Int_BufSz + 1 ! TwrWid allocated yes/no + IF ( ALLOCATED(InData%TwrWid) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrWid upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrWid) ! TwrWid + END IF + Int_BufSz = Int_BufSz + 1 ! TwrCD allocated yes/no + IF ( ALLOCATED(InData%TwrCD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TwrCD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrCD) ! TwrCD + END IF + Int_BufSz = Int_BufSz + 1 ! TwrRe allocated yes/no + IF ( ALLOCATED(InData%TwrRe) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrRe upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrRe) ! TwrRe + END IF + Re_BufSz = Re_BufSz + SIZE(InData%VTwr) ! VTwr + Re_BufSz = Re_BufSz + 1 ! Tower_Wake_Constant + Int_BufSz = Int_BufSz + 1 ! NTwrCDCol allocated yes/no + IF ( ALLOCATED(InData%NTwrCDCol) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NTwrCDCol upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NTwrCDCol) ! NTwrCDCol + END IF + Int_BufSz = Int_BufSz + 1 ! NTwrHT + Int_BufSz = Int_BufSz + 1 ! NTwrRe + Int_BufSz = Int_BufSz + 1 ! NTwrCD + Int_BufSz = Int_BufSz + 1 ! TwrPotent + Int_BufSz = Int_BufSz + 1 ! TwrShadow + Re_BufSz = Re_BufSz + 1 ! ShadHWid + Re_BufSz = Re_BufSz + 1 ! TShadC1 + Re_BufSz = Re_BufSz + 1 ! TShadC2 + Re_BufSz = Re_BufSz + 1 ! TwrShad + Int_BufSz = Int_BufSz + 1 ! PJM_Version + Int_BufSz = Int_BufSz + 1*LEN(InData%TwrFile) ! TwrFile + Re_BufSz = Re_BufSz + 1 ! T_Shad_Refpt + Int_BufSz = Int_BufSz + 1 ! CalcTwrAero + Int_BufSz = Int_BufSz + 1 ! NumTwrNodes + Int_BufSz = Int_BufSz + 1 ! TwrNodeWidth allocated yes/no + IF ( ALLOCATED(InData%TwrNodeWidth) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrNodeWidth upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrNodeWidth) ! TwrNodeWidth + 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%TwrHtFr) ) 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%TwrHtFr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrHtFr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrHtFr,1), UBOUND(InData%TwrHtFr,1) + ReKiBuf(Re_Xferred) = InData%TwrHtFr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrWid) ) 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%TwrWid,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrWid,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrWid,1), UBOUND(InData%TwrWid,1) + ReKiBuf(Re_Xferred) = InData%TwrWid(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrCD) ) 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%TwrCD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrCD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrCD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrCD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TwrCD,2), UBOUND(InData%TwrCD,2) + DO i1 = LBOUND(InData%TwrCD,1), UBOUND(InData%TwrCD,1) + ReKiBuf(Re_Xferred) = InData%TwrCD(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrRe) ) 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%TwrRe,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrRe,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrRe,1), UBOUND(InData%TwrRe,1) + ReKiBuf(Re_Xferred) = InData%TwrRe(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%VTwr,1), UBOUND(InData%VTwr,1) + ReKiBuf(Re_Xferred) = InData%VTwr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%Tower_Wake_Constant + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NTwrCDCol) ) 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%NTwrCDCol,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NTwrCDCol,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NTwrCDCol,1), UBOUND(InData%NTwrCDCol,1) + IntKiBuf(Int_Xferred) = InData%NTwrCDCol(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NTwrHT + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NTwrRe + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NTwrCD + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrPotent, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwrShadow, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShadHWid + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TShadC1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TShadC2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwrShad + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PJM_Version, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%TwrFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%TwrFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%T_Shad_Refpt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcTwrAero, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumTwrNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TwrNodeWidth) ) 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%TwrNodeWidth,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrNodeWidth,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrNodeWidth,1), UBOUND(InData%TwrNodeWidth,1) + ReKiBuf(Re_Xferred) = InData%TwrNodeWidth(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD14_PackTwrPropsParms + + SUBROUTINE AD14_UnPackTwrPropsParms( 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(TwrPropsParms), 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 = 'AD14_UnPackTwrPropsParms' + ! 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 ! TwrHtFr 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%TwrHtFr)) DEALLOCATE(OutData%TwrHtFr) + ALLOCATE(OutData%TwrHtFr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrHtFr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrHtFr,1), UBOUND(OutData%TwrHtFr,1) + OutData%TwrHtFr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrWid 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%TwrWid)) DEALLOCATE(OutData%TwrWid) + ALLOCATE(OutData%TwrWid(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrWid.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrWid,1), UBOUND(OutData%TwrWid,1) + OutData%TwrWid(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrCD 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%TwrCD)) DEALLOCATE(OutData%TwrCD) + ALLOCATE(OutData%TwrCD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TwrCD,2), UBOUND(OutData%TwrCD,2) + DO i1 = LBOUND(OutData%TwrCD,1), UBOUND(OutData%TwrCD,1) + OutData%TwrCD(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrRe 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%TwrRe)) DEALLOCATE(OutData%TwrRe) + ALLOCATE(OutData%TwrRe(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrRe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrRe,1), UBOUND(OutData%TwrRe,1) + OutData%TwrRe(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%VTwr,1) + i1_u = UBOUND(OutData%VTwr,1) + DO i1 = LBOUND(OutData%VTwr,1), UBOUND(OutData%VTwr,1) + OutData%VTwr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%Tower_Wake_Constant = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NTwrCDCol 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%NTwrCDCol)) DEALLOCATE(OutData%NTwrCDCol) + ALLOCATE(OutData%NTwrCDCol(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NTwrCDCol.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NTwrCDCol,1), UBOUND(OutData%NTwrCDCol,1) + OutData%NTwrCDCol(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NTwrHT = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NTwrRe = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NTwrCD = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrPotent = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrPotent) + Int_Xferred = Int_Xferred + 1 + OutData%TwrShadow = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwrShadow) + Int_Xferred = Int_Xferred + 1 + OutData%ShadHWid = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TShadC1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TShadC2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TwrShad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PJM_Version = TRANSFER(IntKiBuf(Int_Xferred), OutData%PJM_Version) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%TwrFile) + OutData%TwrFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%T_Shad_Refpt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CalcTwrAero = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcTwrAero) + Int_Xferred = Int_Xferred + 1 + OutData%NumTwrNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrNodeWidth 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%TwrNodeWidth)) DEALLOCATE(OutData%TwrNodeWidth) + ALLOCATE(OutData%TwrNodeWidth(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrNodeWidth.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrNodeWidth,1), UBOUND(OutData%TwrNodeWidth,1) + OutData%TwrNodeWidth(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE AD14_UnPackTwrPropsParms + + SUBROUTINE AD14_CopyWind( SrcWindData, DstWindData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Wind), INTENT(IN) :: SrcWindData + TYPE(Wind), INTENT(INOUT) :: DstWindData + 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 = 'AD14_CopyWind' +! + ErrStat = ErrID_None + ErrMsg = "" + DstWindData%ANGFLW = SrcWindData%ANGFLW + DstWindData%CDEL = SrcWindData%CDEL + DstWindData%VROTORX = SrcWindData%VROTORX + DstWindData%VROTORY = SrcWindData%VROTORY + DstWindData%VROTORZ = SrcWindData%VROTORZ + DstWindData%SDEL = SrcWindData%SDEL + END SUBROUTINE AD14_CopyWind + + SUBROUTINE AD14_DestroyWind( WindData, ErrStat, ErrMsg ) + TYPE(Wind), INTENT(INOUT) :: WindData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyWind' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyWind + + SUBROUTINE AD14_PackWind( 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(Wind), 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 = 'AD14_PackWind' + ! 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 ! ANGFLW + Re_BufSz = Re_BufSz + 1 ! CDEL + Re_BufSz = Re_BufSz + 1 ! VROTORX + Re_BufSz = Re_BufSz + 1 ! VROTORY + Re_BufSz = Re_BufSz + 1 ! VROTORZ + Re_BufSz = Re_BufSz + 1 ! SDEL + 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%ANGFLW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CDEL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VROTORX + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VROTORY + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VROTORZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SDEL + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackWind + + SUBROUTINE AD14_UnPackWind( 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(Wind), 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 = 'AD14_UnPackWind' + ! 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%ANGFLW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CDEL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VROTORX = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VROTORY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VROTORZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SDEL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackWind + + SUBROUTINE AD14_CopyWindParms( SrcWindParmsData, DstWindParmsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WindParms), INTENT(IN) :: SrcWindParmsData + TYPE(WindParms), INTENT(INOUT) :: DstWindParmsData + 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 = 'AD14_CopyWindParms' +! + ErrStat = ErrID_None + ErrMsg = "" + DstWindParmsData%Rho = SrcWindParmsData%Rho + DstWindParmsData%KinVisc = SrcWindParmsData%KinVisc + END SUBROUTINE AD14_CopyWindParms + + SUBROUTINE AD14_DestroyWindParms( WindParmsData, ErrStat, ErrMsg ) + TYPE(WindParms), INTENT(INOUT) :: WindParmsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyWindParms' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyWindParms + + SUBROUTINE AD14_PackWindParms( 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(WindParms), 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 = 'AD14_PackWindParms' + ! 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 ! Rho + Re_BufSz = Re_BufSz + 1 ! KinVisc + 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%Rho + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%KinVisc + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackWindParms + + SUBROUTINE AD14_UnPackWindParms( 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(WindParms), 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 = 'AD14_UnPackWindParms' + ! 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%Rho = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%KinVisc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackWindParms + + SUBROUTINE AD14_CopyPositionType( SrcPositionTypeData, DstPositionTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(PositionType), INTENT(IN) :: SrcPositionTypeData + TYPE(PositionType), INTENT(INOUT) :: DstPositionTypeData + 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 = 'AD14_CopyPositionType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstPositionTypeData%Pos = SrcPositionTypeData%Pos + END SUBROUTINE AD14_CopyPositionType + + SUBROUTINE AD14_DestroyPositionType( PositionTypeData, ErrStat, ErrMsg ) + TYPE(PositionType), INTENT(INOUT) :: PositionTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyPositionType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyPositionType + + SUBROUTINE AD14_PackPositionType( 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(PositionType), 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 = 'AD14_PackPositionType' + ! 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%Pos) ! Pos + 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%Pos,1), UBOUND(InData%Pos,1) + ReKiBuf(Re_Xferred) = InData%Pos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_PackPositionType + + SUBROUTINE AD14_UnPackPositionType( 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(PositionType), 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 = 'AD14_UnPackPositionType' + ! 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%Pos,1) + i1_u = UBOUND(OutData%Pos,1) + DO i1 = LBOUND(OutData%Pos,1), UBOUND(OutData%Pos,1) + OutData%Pos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_UnPackPositionType + + SUBROUTINE AD14_CopyOrientationType( SrcOrientationTypeData, DstOrientationTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OrientationType), INTENT(IN) :: SrcOrientationTypeData + TYPE(OrientationType), INTENT(INOUT) :: DstOrientationTypeData + 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 = 'AD14_CopyOrientationType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOrientationTypeData%Orient = SrcOrientationTypeData%Orient + END SUBROUTINE AD14_CopyOrientationType + + SUBROUTINE AD14_DestroyOrientationType( OrientationTypeData, ErrStat, ErrMsg ) + TYPE(OrientationType), INTENT(INOUT) :: OrientationTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyOrientationType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE AD14_DestroyOrientationType + + SUBROUTINE AD14_PackOrientationType( 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(OrientationType), 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 = 'AD14_PackOrientationType' + ! 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%Orient) ! Orient + 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 i2 = LBOUND(InData%Orient,2), UBOUND(InData%Orient,2) + DO i1 = LBOUND(InData%Orient,1), UBOUND(InData%Orient,1) + ReKiBuf(Re_Xferred) = InData%Orient(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE AD14_PackOrientationType + + SUBROUTINE AD14_UnPackOrientationType( 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(OrientationType), 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 = 'AD14_UnPackOrientationType' + ! 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%Orient,1) + i1_u = UBOUND(OutData%Orient,1) + i2_l = LBOUND(OutData%Orient,2) + i2_u = UBOUND(OutData%Orient,2) + DO i2 = LBOUND(OutData%Orient,2), UBOUND(OutData%Orient,2) + DO i1 = LBOUND(OutData%Orient,1), UBOUND(OutData%Orient,1) + OutData%Orient(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE AD14_UnPackOrientationType + + SUBROUTINE AD14_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(AD14_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 = 'AD14_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%Title = SrcInitInputData%Title + DstInitInputData%OutRootName = SrcInitInputData%OutRootName + DstInitInputData%ADFileName = SrcInitInputData%ADFileName + DstInitInputData%WrSumFile = SrcInitInputData%WrSumFile + DstInitInputData%NumBl = SrcInitInputData%NumBl + DstInitInputData%BladeLength = SrcInitInputData%BladeLength + DstInitInputData%LinearizeFlag = SrcInitInputData%LinearizeFlag + DstInitInputData%UseDWM = SrcInitInputData%UseDWM + CALL AD14_Copyaeroconfig( SrcInitInputData%TurbineComponents, DstInitInputData%TurbineComponents, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%NumTwrNodes = SrcInitInputData%NumTwrNodes +IF (ALLOCATED(SrcInitInputData%TwrNodeLocs)) THEN + i1_l = LBOUND(SrcInitInputData%TwrNodeLocs,1) + i1_u = UBOUND(SrcInitInputData%TwrNodeLocs,1) + i2_l = LBOUND(SrcInitInputData%TwrNodeLocs,2) + i2_u = UBOUND(SrcInitInputData%TwrNodeLocs,2) + IF (.NOT. ALLOCATED(DstInitInputData%TwrNodeLocs)) THEN + ALLOCATE(DstInitInputData%TwrNodeLocs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%TwrNodeLocs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%TwrNodeLocs = SrcInitInputData%TwrNodeLocs +ENDIF + DstInitInputData%HubHt = SrcInitInputData%HubHt + CALL DWM_CopyInitInput( SrcInitInputData%DWM, DstInitInputData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyInitInput + + SUBROUTINE AD14_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL AD14_Destroyaeroconfig( InitInputData%TurbineComponents, ErrStat, ErrMsg ) +IF (ALLOCATED(InitInputData%TwrNodeLocs)) THEN + DEALLOCATE(InitInputData%TwrNodeLocs) +ENDIF + CALL DWM_DestroyInitInput( InitInputData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyInitInput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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%Title) ! Title + Int_BufSz = Int_BufSz + 1*LEN(InData%OutRootName) ! OutRootName + Int_BufSz = Int_BufSz + 1*LEN(InData%ADFileName) ! ADFileName + Int_BufSz = Int_BufSz + 1 ! WrSumFile + Int_BufSz = Int_BufSz + 1 ! NumBl + Re_BufSz = Re_BufSz + 1 ! BladeLength + Int_BufSz = Int_BufSz + 1 ! LinearizeFlag + Int_BufSz = Int_BufSz + 1 ! UseDWM + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! TurbineComponents: size of buffers for each call to pack subtype + CALL AD14_Packaeroconfig( Re_Buf, Db_Buf, Int_Buf, InData%TurbineComponents, ErrStat2, ErrMsg2, .TRUE. ) ! TurbineComponents + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TurbineComponents + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TurbineComponents + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TurbineComponents + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! NumTwrNodes + Int_BufSz = Int_BufSz + 1 ! TwrNodeLocs allocated yes/no + IF ( ALLOCATED(InData%TwrNodeLocs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TwrNodeLocs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrNodeLocs) ! TwrNodeLocs + END IF + Re_BufSz = Re_BufSz + 1 ! HubHt + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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%Title) + IntKiBuf(Int_Xferred) = ICHAR(InData%Title(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutRootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutRootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%ADFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%ADFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%WrSumFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LinearizeFlag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseDWM, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL AD14_Packaeroconfig( Re_Buf, Db_Buf, Int_Buf, InData%TurbineComponents, ErrStat2, ErrMsg2, OnlySize ) ! TurbineComponents + 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%NumTwrNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TwrNodeLocs) ) 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%TwrNodeLocs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrNodeLocs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrNodeLocs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrNodeLocs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TwrNodeLocs,2), UBOUND(InData%TwrNodeLocs,2) + DO i1 = LBOUND(InData%TwrNodeLocs,1), UBOUND(InData%TwrNodeLocs,1) + ReKiBuf(Re_Xferred) = InData%TwrNodeLocs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%HubHt + Re_Xferred = Re_Xferred + 1 + CALL DWM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackInitInput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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%Title) + OutData%Title(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutRootName) + OutData%OutRootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%ADFileName) + OutData%ADFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WrSumFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%WrSumFile) + Int_Xferred = Int_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LinearizeFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%LinearizeFlag) + Int_Xferred = Int_Xferred + 1 + OutData%UseDWM = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseDWM) + 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 AD14_Unpackaeroconfig( Re_Buf, Db_Buf, Int_Buf, OutData%TurbineComponents, ErrStat2, ErrMsg2 ) ! TurbineComponents + 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%NumTwrNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrNodeLocs 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%TwrNodeLocs)) DEALLOCATE(OutData%TwrNodeLocs) + ALLOCATE(OutData%TwrNodeLocs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrNodeLocs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TwrNodeLocs,2), UBOUND(OutData%TwrNodeLocs,2) + DO i1 = LBOUND(OutData%TwrNodeLocs,1), UBOUND(OutData%TwrNodeLocs,1) + OutData%TwrNodeLocs(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%HubHt = 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 DWM_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackInitInput + + SUBROUTINE AD14_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(AD14_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 = 'AD14_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 DWM_CopyInitOutput( SrcInitOutputData%DWM, DstInitOutputData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%AirDens = SrcInitOutputData%AirDens + END SUBROUTINE AD14_CopyInitOutput + + SUBROUTINE AD14_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(AD14_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + CALL DWM_DestroyInitOutput( InitOutputData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyInitOutput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! AirDens + 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 DWM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_PackInitOutput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 DWM_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE AD14_UnPackInitOutput + + SUBROUTINE AD14_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(AD14_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 = 'AD14_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_CopyContState( SrcContStateData%DWM, DstContStateData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyContState + + SUBROUTINE AD14_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_DestroyContState( ContStateData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyContState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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 DWM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackContState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + 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 DWM_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackContState + + SUBROUTINE AD14_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(AD14_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 = 'AD14_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_CopyDiscState( SrcDiscStateData%DWM, DstDiscStateData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyDiscState + + SUBROUTINE AD14_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_DestroyDiscState( DiscStateData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyDiscState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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 DWM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackDiscState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + 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 DWM_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackDiscState + + SUBROUTINE AD14_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(AD14_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 = 'AD14_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_CopyConstrState( SrcConstrStateData%DWM, DstConstrStateData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyConstrState + + SUBROUTINE AD14_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_DestroyConstrState( ConstrStateData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyConstrState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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 DWM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackConstrState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + 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 DWM_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackConstrState + + SUBROUTINE AD14_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(AD14_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 = 'AD14_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_CopyOtherState( SrcOtherStateData%DWM, DstOtherStateData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyOtherState + + SUBROUTINE AD14_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(AD14_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_DestroyOtherState( OtherStateData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyOtherState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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 DWM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackOtherState + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + 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 DWM_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackOtherState + + SUBROUTINE AD14_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(AD14_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_CopyMisc( SrcMiscData%DWM, DstMiscData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_CopyInput( SrcMiscData%DWM_Inputs, DstMiscData%DWM_Inputs, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_CopyOutput( SrcMiscData%DWM_Outputs, DstMiscData%DWM_Outputs, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%DT = SrcMiscData%DT +IF (ALLOCATED(SrcMiscData%ElPrNum)) THEN + i1_l = LBOUND(SrcMiscData%ElPrNum,1) + i1_u = UBOUND(SrcMiscData%ElPrNum,1) + IF (.NOT. ALLOCATED(DstMiscData%ElPrNum)) THEN + ALLOCATE(DstMiscData%ElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ElPrNum = SrcMiscData%ElPrNum +ENDIF + DstMiscData%OldTime = SrcMiscData%OldTime + DstMiscData%HubLoss = SrcMiscData%HubLoss + DstMiscData%Loss = SrcMiscData%Loss + DstMiscData%TipLoss = SrcMiscData%TipLoss + DstMiscData%TLpt7 = SrcMiscData%TLpt7 + DstMiscData%FirstPassGTL = SrcMiscData%FirstPassGTL + DstMiscData%SuperSonic = SrcMiscData%SuperSonic + DstMiscData%AFLAGVinderr = SrcMiscData%AFLAGVinderr + DstMiscData%AFLAGTwrInflu = SrcMiscData%AFLAGTwrInflu + DstMiscData%OnePassDynDbg = SrcMiscData%OnePassDynDbg + DstMiscData%NoLoadsCalculated = SrcMiscData%NoLoadsCalculated + DstMiscData%NERRORS = SrcMiscData%NERRORS + CALL AD14_Copyairfoil( SrcMiscData%AirFoil, DstMiscData%AirFoil, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copybeddoes( SrcMiscData%Beddoes, DstMiscData%Beddoes, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copydyninflow( SrcMiscData%DynInflow, DstMiscData%DynInflow, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyelement( SrcMiscData%Element, DstMiscData%Element, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyrotor( SrcMiscData%Rotor, DstMiscData%Rotor, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copywind( SrcMiscData%Wind, DstMiscData%Wind, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyinducedvel( SrcMiscData%InducedVel, DstMiscData%InducedVel, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyeloutparms( SrcMiscData%ElOut, DstMiscData%ElOut, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%Skew = SrcMiscData%Skew + DstMiscData%DynInit = SrcMiscData%DynInit + DstMiscData%FirstWarn = SrcMiscData%FirstWarn +IF (ALLOCATED(SrcMiscData%StoredForces)) THEN + i1_l = LBOUND(SrcMiscData%StoredForces,1) + i1_u = UBOUND(SrcMiscData%StoredForces,1) + i2_l = LBOUND(SrcMiscData%StoredForces,2) + i2_u = UBOUND(SrcMiscData%StoredForces,2) + i3_l = LBOUND(SrcMiscData%StoredForces,3) + i3_u = UBOUND(SrcMiscData%StoredForces,3) + IF (.NOT. ALLOCATED(DstMiscData%StoredForces)) THEN + ALLOCATE(DstMiscData%StoredForces(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%StoredForces.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%StoredForces = SrcMiscData%StoredForces +ENDIF +IF (ALLOCATED(SrcMiscData%StoredMoments)) THEN + i1_l = LBOUND(SrcMiscData%StoredMoments,1) + i1_u = UBOUND(SrcMiscData%StoredMoments,1) + i2_l = LBOUND(SrcMiscData%StoredMoments,2) + i2_u = UBOUND(SrcMiscData%StoredMoments,2) + i3_l = LBOUND(SrcMiscData%StoredMoments,3) + i3_u = UBOUND(SrcMiscData%StoredMoments,3) + IF (.NOT. ALLOCATED(DstMiscData%StoredMoments)) THEN + ALLOCATE(DstMiscData%StoredMoments(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%StoredMoments.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%StoredMoments = SrcMiscData%StoredMoments +ENDIF + END SUBROUTINE AD14_CopyMisc + + SUBROUTINE AD14_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(AD14_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_DestroyMisc( MiscData%DWM, ErrStat, ErrMsg ) + CALL DWM_DestroyInput( MiscData%DWM_Inputs, ErrStat, ErrMsg ) + CALL DWM_DestroyOutput( MiscData%DWM_Outputs, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%ElPrNum)) THEN + DEALLOCATE(MiscData%ElPrNum) +ENDIF + CALL AD14_Destroyairfoil( MiscData%AirFoil, ErrStat, ErrMsg ) + CALL AD14_Destroybeddoes( MiscData%Beddoes, ErrStat, ErrMsg ) + CALL AD14_Destroydyninflow( MiscData%DynInflow, ErrStat, ErrMsg ) + CALL AD14_Destroyelement( MiscData%Element, ErrStat, ErrMsg ) + CALL AD14_Destroyrotor( MiscData%Rotor, ErrStat, ErrMsg ) + CALL AD14_Destroywind( MiscData%Wind, ErrStat, ErrMsg ) + CALL AD14_Destroyinducedvel( MiscData%InducedVel, ErrStat, ErrMsg ) + CALL AD14_Destroyeloutparms( MiscData%ElOut, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%StoredForces)) THEN + DEALLOCATE(MiscData%StoredForces) +ENDIF +IF (ALLOCATED(MiscData%StoredMoments)) THEN + DEALLOCATE(MiscData%StoredMoments) +ENDIF + END SUBROUTINE AD14_DestroyMisc + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DWM_Inputs: size of buffers for each call to pack subtype + CALL DWM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%DWM_Inputs, ErrStat2, ErrMsg2, .TRUE. ) ! DWM_Inputs + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM_Inputs + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM_Inputs + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM_Inputs + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DWM_Outputs: size of buffers for each call to pack subtype + CALL DWM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%DWM_Outputs, ErrStat2, ErrMsg2, .TRUE. ) ! DWM_Outputs + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM_Outputs + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM_Outputs + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM_Outputs + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! ElPrNum allocated yes/no + IF ( ALLOCATED(InData%ElPrNum) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElPrNum upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElPrNum) ! ElPrNum + END IF + Db_BufSz = Db_BufSz + 1 ! OldTime + Re_BufSz = Re_BufSz + 1 ! HubLoss + Re_BufSz = Re_BufSz + 1 ! Loss + Re_BufSz = Re_BufSz + 1 ! TipLoss + Re_BufSz = Re_BufSz + 1 ! TLpt7 + Int_BufSz = Int_BufSz + 1 ! FirstPassGTL + Int_BufSz = Int_BufSz + 1 ! SuperSonic + Int_BufSz = Int_BufSz + 1 ! AFLAGVinderr + Int_BufSz = Int_BufSz + 1 ! AFLAGTwrInflu + Int_BufSz = Int_BufSz + 1 ! OnePassDynDbg + Int_BufSz = Int_BufSz + 1 ! NoLoadsCalculated + Int_BufSz = Int_BufSz + 1 ! NERRORS + Int_BufSz = Int_BufSz + 3 ! AirFoil: size of buffers for each call to pack subtype + CALL AD14_Packairfoil( Re_Buf, Db_Buf, Int_Buf, InData%AirFoil, ErrStat2, ErrMsg2, .TRUE. ) ! AirFoil + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AirFoil + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AirFoil + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AirFoil + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Beddoes: size of buffers for each call to pack subtype + CALL AD14_Packbeddoes( Re_Buf, Db_Buf, Int_Buf, InData%Beddoes, ErrStat2, ErrMsg2, .TRUE. ) ! Beddoes + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Beddoes + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Beddoes + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Beddoes + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DynInflow: size of buffers for each call to pack subtype + CALL AD14_Packdyninflow( Re_Buf, Db_Buf, Int_Buf, InData%DynInflow, ErrStat2, ErrMsg2, .TRUE. ) ! DynInflow + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DynInflow + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DynInflow + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DynInflow + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Element: size of buffers for each call to pack subtype + CALL AD14_Packelement( Re_Buf, Db_Buf, Int_Buf, InData%Element, ErrStat2, ErrMsg2, .TRUE. ) ! Element + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Element + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Element + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Element + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Rotor: size of buffers for each call to pack subtype + CALL AD14_Packrotor( Re_Buf, Db_Buf, Int_Buf, InData%Rotor, ErrStat2, ErrMsg2, .TRUE. ) ! Rotor + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Rotor + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Rotor + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Rotor + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Wind: size of buffers for each call to pack subtype + CALL AD14_Packwind( Re_Buf, Db_Buf, Int_Buf, InData%Wind, ErrStat2, ErrMsg2, .TRUE. ) ! Wind + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Wind + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Wind + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Wind + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InducedVel: size of buffers for each call to pack subtype + CALL AD14_Packinducedvel( Re_Buf, Db_Buf, Int_Buf, InData%InducedVel, ErrStat2, ErrMsg2, .TRUE. ) ! InducedVel + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InducedVel + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InducedVel + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InducedVel + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ElOut: size of buffers for each call to pack subtype + CALL AD14_Packeloutparms( Re_Buf, Db_Buf, Int_Buf, InData%ElOut, ErrStat2, ErrMsg2, .TRUE. ) ! ElOut + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ElOut + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ElOut + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ElOut + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Skew + Int_BufSz = Int_BufSz + 1 ! DynInit + Int_BufSz = Int_BufSz + 1 ! FirstWarn + Int_BufSz = Int_BufSz + 1 ! StoredForces allocated yes/no + IF ( ALLOCATED(InData%StoredForces) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! StoredForces upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StoredForces) ! StoredForces + END IF + Int_BufSz = Int_BufSz + 1 ! StoredMoments allocated yes/no + IF ( ALLOCATED(InData%StoredMoments) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! StoredMoments upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StoredMoments) ! StoredMoments + 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 DWM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 DWM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%DWM_Inputs, ErrStat2, ErrMsg2, OnlySize ) ! DWM_Inputs + 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 DWM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%DWM_Outputs, ErrStat2, ErrMsg2, OnlySize ) ! DWM_Outputs + 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%DT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ElPrNum) ) 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%ElPrNum,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElPrNum,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElPrNum,1), UBOUND(InData%ElPrNum,1) + IntKiBuf(Int_Xferred) = InData%ElPrNum(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%OldTime + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubLoss + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Loss + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TipLoss + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TLpt7 + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstPassGTL, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SuperSonic, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%AFLAGVinderr, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%AFLAGTwrInflu, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OnePassDynDbg, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%NoLoadsCalculated, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NERRORS + Int_Xferred = Int_Xferred + 1 + CALL AD14_Packairfoil( Re_Buf, Db_Buf, Int_Buf, InData%AirFoil, ErrStat2, ErrMsg2, OnlySize ) ! AirFoil + 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 AD14_Packbeddoes( Re_Buf, Db_Buf, Int_Buf, InData%Beddoes, ErrStat2, ErrMsg2, OnlySize ) ! Beddoes + 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 AD14_Packdyninflow( Re_Buf, Db_Buf, Int_Buf, InData%DynInflow, ErrStat2, ErrMsg2, OnlySize ) ! DynInflow + 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 AD14_Packelement( Re_Buf, Db_Buf, Int_Buf, InData%Element, ErrStat2, ErrMsg2, OnlySize ) ! Element + 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 AD14_Packrotor( Re_Buf, Db_Buf, Int_Buf, InData%Rotor, ErrStat2, ErrMsg2, OnlySize ) ! Rotor + 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 AD14_Packwind( Re_Buf, Db_Buf, Int_Buf, InData%Wind, ErrStat2, ErrMsg2, OnlySize ) ! Wind + 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 AD14_Packinducedvel( Re_Buf, Db_Buf, Int_Buf, InData%InducedVel, ErrStat2, ErrMsg2, OnlySize ) ! InducedVel + 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 AD14_Packeloutparms( Re_Buf, Db_Buf, Int_Buf, InData%ElOut, ErrStat2, ErrMsg2, OnlySize ) ! ElOut + 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) = TRANSFER(InData%Skew, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DynInit, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FirstWarn, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%StoredForces) ) 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%StoredForces,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredForces,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StoredForces,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredForces,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StoredForces,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredForces,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%StoredForces,3), UBOUND(InData%StoredForces,3) + DO i2 = LBOUND(InData%StoredForces,2), UBOUND(InData%StoredForces,2) + DO i1 = LBOUND(InData%StoredForces,1), UBOUND(InData%StoredForces,1) + ReKiBuf(Re_Xferred) = InData%StoredForces(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StoredMoments) ) 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%StoredMoments,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredMoments,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StoredMoments,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredMoments,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StoredMoments,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StoredMoments,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%StoredMoments,3), UBOUND(InData%StoredMoments,3) + DO i2 = LBOUND(InData%StoredMoments,2), UBOUND(InData%StoredMoments,2) + DO i1 = LBOUND(InData%StoredMoments,1), UBOUND(InData%StoredMoments,1) + ReKiBuf(Re_Xferred) = InData%StoredMoments(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AD14_PackMisc + + SUBROUTINE AD14_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(AD14_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_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 + 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 DWM_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 DWM_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%DWM_Inputs, ErrStat2, ErrMsg2 ) ! DWM_Inputs + 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 DWM_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%DWM_Outputs, ErrStat2, ErrMsg2 ) ! DWM_Outputs + 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElPrNum 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%ElPrNum)) DEALLOCATE(OutData%ElPrNum) + ALLOCATE(OutData%ElPrNum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElPrNum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElPrNum,1), UBOUND(OutData%ElPrNum,1) + OutData%ElPrNum(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%OldTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HubLoss = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Loss = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TipLoss = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TLpt7 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FirstPassGTL = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstPassGTL) + Int_Xferred = Int_Xferred + 1 + OutData%SuperSonic = TRANSFER(IntKiBuf(Int_Xferred), OutData%SuperSonic) + Int_Xferred = Int_Xferred + 1 + OutData%AFLAGVinderr = TRANSFER(IntKiBuf(Int_Xferred), OutData%AFLAGVinderr) + Int_Xferred = Int_Xferred + 1 + OutData%AFLAGTwrInflu = TRANSFER(IntKiBuf(Int_Xferred), OutData%AFLAGTwrInflu) + Int_Xferred = Int_Xferred + 1 + OutData%OnePassDynDbg = TRANSFER(IntKiBuf(Int_Xferred), OutData%OnePassDynDbg) + Int_Xferred = Int_Xferred + 1 + OutData%NoLoadsCalculated = TRANSFER(IntKiBuf(Int_Xferred), OutData%NoLoadsCalculated) + Int_Xferred = Int_Xferred + 1 + OutData%NERRORS = 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 AD14_Unpackairfoil( Re_Buf, Db_Buf, Int_Buf, OutData%AirFoil, ErrStat2, ErrMsg2 ) ! AirFoil + 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 AD14_Unpackbeddoes( Re_Buf, Db_Buf, Int_Buf, OutData%Beddoes, ErrStat2, ErrMsg2 ) ! Beddoes + 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 AD14_Unpackdyninflow( Re_Buf, Db_Buf, Int_Buf, OutData%DynInflow, ErrStat2, ErrMsg2 ) ! DynInflow + 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 AD14_Unpackelement( Re_Buf, Db_Buf, Int_Buf, OutData%Element, ErrStat2, ErrMsg2 ) ! Element + 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 AD14_Unpackrotor( Re_Buf, Db_Buf, Int_Buf, OutData%Rotor, ErrStat2, ErrMsg2 ) ! Rotor + 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 AD14_Unpackwind( Re_Buf, Db_Buf, Int_Buf, OutData%Wind, ErrStat2, ErrMsg2 ) ! Wind + 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 AD14_Unpackinducedvel( Re_Buf, Db_Buf, Int_Buf, OutData%InducedVel, ErrStat2, ErrMsg2 ) ! InducedVel + 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 AD14_Unpackeloutparms( Re_Buf, Db_Buf, Int_Buf, OutData%ElOut, ErrStat2, ErrMsg2 ) ! ElOut + 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%Skew = TRANSFER(IntKiBuf(Int_Xferred), OutData%Skew) + Int_Xferred = Int_Xferred + 1 + OutData%DynInit = TRANSFER(IntKiBuf(Int_Xferred), OutData%DynInit) + Int_Xferred = Int_Xferred + 1 + OutData%FirstWarn = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StoredForces 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%StoredForces)) DEALLOCATE(OutData%StoredForces) + ALLOCATE(OutData%StoredForces(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%StoredForces.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%StoredForces,3), UBOUND(OutData%StoredForces,3) + DO i2 = LBOUND(OutData%StoredForces,2), UBOUND(OutData%StoredForces,2) + DO i1 = LBOUND(OutData%StoredForces,1), UBOUND(OutData%StoredForces,1) + OutData%StoredForces(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StoredMoments 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%StoredMoments)) DEALLOCATE(OutData%StoredMoments) + ALLOCATE(OutData%StoredMoments(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%StoredMoments.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%StoredMoments,3), UBOUND(OutData%StoredMoments,3) + DO i2 = LBOUND(OutData%StoredMoments,2), UBOUND(OutData%StoredMoments,2) + DO i1 = LBOUND(OutData%StoredMoments,1), UBOUND(OutData%StoredMoments,1) + OutData%StoredMoments(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE AD14_UnPackMisc + + SUBROUTINE AD14_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_ParameterType), INTENT(IN) :: SrcParamData + TYPE(AD14_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 = 'AD14_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%Title = SrcParamData%Title + DstParamData%SIUnit = SrcParamData%SIUnit + DstParamData%Echo = SrcParamData%Echo + DstParamData%MultiTab = SrcParamData%MultiTab + DstParamData%LinearizeFlag = SrcParamData%LinearizeFlag + DstParamData%OutputPlottingInfo = SrcParamData%OutputPlottingInfo + DstParamData%UseDWM = SrcParamData%UseDWM + DstParamData%TwoPiNB = SrcParamData%TwoPiNB + DstParamData%NumBl = SrcParamData%NumBl + DstParamData%NBlInpSt = SrcParamData%NBlInpSt + DstParamData%ElemPrn = SrcParamData%ElemPrn + DstParamData%DStall = SrcParamData%DStall + DstParamData%PMoment = SrcParamData%PMoment + DstParamData%Reynolds = SrcParamData%Reynolds + DstParamData%DynInfl = SrcParamData%DynInfl + DstParamData%Wake = SrcParamData%Wake + DstParamData%Swirl = SrcParamData%Swirl + DstParamData%DtAero = SrcParamData%DtAero + DstParamData%HubRad = SrcParamData%HubRad + DstParamData%UnEc = SrcParamData%UnEc + DstParamData%UnElem = SrcParamData%UnElem + DstParamData%UnWndOut = SrcParamData%UnWndOut + DstParamData%MAXICOUNT = SrcParamData%MAXICOUNT + DstParamData%WrOptFile = SrcParamData%WrOptFile + DstParamData%DEFAULT_Wind = SrcParamData%DEFAULT_Wind + CALL AD14_Copyairfoilparms( SrcParamData%AirFoil, DstParamData%AirFoil, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copybladeparms( SrcParamData%Blade, DstParamData%Blade, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copybeddoesparms( SrcParamData%Beddoes, DstParamData%Beddoes, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copydyninflowparms( SrcParamData%DynInflow, DstParamData%DynInflow, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyelementparms( SrcParamData%Element, DstParamData%Element, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copytwrpropsparms( SrcParamData%TwrProps, DstParamData%TwrProps, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyinducedvelparms( SrcParamData%InducedVel, DstParamData%InducedVel, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copywindparms( SrcParamData%Wind, DstParamData%Wind, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyrotorparms( SrcParamData%Rotor, DstParamData%Rotor, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_CopyParam( SrcParamData%DWM, DstParamData%DWM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyParam + + SUBROUTINE AD14_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(AD14_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL AD14_Destroyairfoilparms( ParamData%AirFoil, ErrStat, ErrMsg ) + CALL AD14_Destroybladeparms( ParamData%Blade, ErrStat, ErrMsg ) + CALL AD14_Destroybeddoesparms( ParamData%Beddoes, ErrStat, ErrMsg ) + CALL AD14_Destroydyninflowparms( ParamData%DynInflow, ErrStat, ErrMsg ) + CALL AD14_Destroyelementparms( ParamData%Element, ErrStat, ErrMsg ) + CALL AD14_Destroytwrpropsparms( ParamData%TwrProps, ErrStat, ErrMsg ) + CALL AD14_Destroyinducedvelparms( ParamData%InducedVel, ErrStat, ErrMsg ) + CALL AD14_Destroywindparms( ParamData%Wind, ErrStat, ErrMsg ) + CALL AD14_Destroyrotorparms( ParamData%Rotor, ErrStat, ErrMsg ) + CALL DWM_DestroyParam( ParamData%DWM, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyParam + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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*LEN(InData%Title) ! Title + Int_BufSz = Int_BufSz + 1 ! SIUnit + Int_BufSz = Int_BufSz + 1 ! Echo + Int_BufSz = Int_BufSz + 1 ! MultiTab + Int_BufSz = Int_BufSz + 1 ! LinearizeFlag + Int_BufSz = Int_BufSz + 1 ! OutputPlottingInfo + Int_BufSz = Int_BufSz + 1 ! UseDWM + Re_BufSz = Re_BufSz + 1 ! TwoPiNB + Int_BufSz = Int_BufSz + 1 ! NumBl + Int_BufSz = Int_BufSz + 1 ! NBlInpSt + Int_BufSz = Int_BufSz + 1 ! ElemPrn + Int_BufSz = Int_BufSz + 1 ! DStall + Int_BufSz = Int_BufSz + 1 ! PMoment + Int_BufSz = Int_BufSz + 1 ! Reynolds + Int_BufSz = Int_BufSz + 1 ! DynInfl + Int_BufSz = Int_BufSz + 1 ! Wake + Int_BufSz = Int_BufSz + 1 ! Swirl + Db_BufSz = Db_BufSz + 1 ! DtAero + Re_BufSz = Re_BufSz + 1 ! HubRad + Int_BufSz = Int_BufSz + 1 ! UnEc + Int_BufSz = Int_BufSz + 1 ! UnElem + Int_BufSz = Int_BufSz + 1 ! UnWndOut + Int_BufSz = Int_BufSz + 1 ! MAXICOUNT + Int_BufSz = Int_BufSz + 1 ! WrOptFile + Int_BufSz = Int_BufSz + 1 ! DEFAULT_Wind + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! AirFoil: size of buffers for each call to pack subtype + CALL AD14_Packairfoilparms( Re_Buf, Db_Buf, Int_Buf, InData%AirFoil, ErrStat2, ErrMsg2, .TRUE. ) ! AirFoil + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AirFoil + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AirFoil + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AirFoil + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Blade: size of buffers for each call to pack subtype + CALL AD14_Packbladeparms( Re_Buf, Db_Buf, Int_Buf, InData%Blade, ErrStat2, ErrMsg2, .TRUE. ) ! Blade + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Blade + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Blade + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Blade + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Beddoes: size of buffers for each call to pack subtype + CALL AD14_Packbeddoesparms( Re_Buf, Db_Buf, Int_Buf, InData%Beddoes, ErrStat2, ErrMsg2, .TRUE. ) ! Beddoes + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Beddoes + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Beddoes + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Beddoes + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DynInflow: size of buffers for each call to pack subtype + CALL AD14_Packdyninflowparms( Re_Buf, Db_Buf, Int_Buf, InData%DynInflow, ErrStat2, ErrMsg2, .TRUE. ) ! DynInflow + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DynInflow + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DynInflow + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DynInflow + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Element: size of buffers for each call to pack subtype + CALL AD14_Packelementparms( Re_Buf, Db_Buf, Int_Buf, InData%Element, ErrStat2, ErrMsg2, .TRUE. ) ! Element + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Element + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Element + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Element + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TwrProps: size of buffers for each call to pack subtype + CALL AD14_Packtwrpropsparms( Re_Buf, Db_Buf, Int_Buf, InData%TwrProps, ErrStat2, ErrMsg2, .TRUE. ) ! TwrProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TwrProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TwrProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TwrProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InducedVel: size of buffers for each call to pack subtype + CALL AD14_Packinducedvelparms( Re_Buf, Db_Buf, Int_Buf, InData%InducedVel, ErrStat2, ErrMsg2, .TRUE. ) ! InducedVel + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InducedVel + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InducedVel + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InducedVel + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Wind: size of buffers for each call to pack subtype + CALL AD14_Packwindparms( Re_Buf, Db_Buf, Int_Buf, InData%Wind, ErrStat2, ErrMsg2, .TRUE. ) ! Wind + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Wind + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Wind + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Wind + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Rotor: size of buffers for each call to pack subtype + CALL AD14_Packrotorparms( Re_Buf, Db_Buf, Int_Buf, InData%Rotor, ErrStat2, ErrMsg2, .TRUE. ) ! Rotor + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Rotor + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Rotor + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Rotor + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DWM: size of buffers for each call to pack subtype + CALL DWM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, .TRUE. ) ! DWM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM + 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%Title) + IntKiBuf(Int_Xferred) = ICHAR(InData%Title(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%SIUnit, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%MultiTab, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LinearizeFlag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutputPlottingInfo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseDWM, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwoPiNB + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBlInpSt + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ElemPrn, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DStall, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PMoment, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Reynolds, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DynInfl, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Wake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Swirl, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DtAero + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubRad + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnEc + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnElem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnWndOut + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MAXICOUNT + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WrOptFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DEFAULT_Wind + Int_Xferred = Int_Xferred + 1 + CALL AD14_Packairfoilparms( Re_Buf, Db_Buf, Int_Buf, InData%AirFoil, ErrStat2, ErrMsg2, OnlySize ) ! AirFoil + 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 AD14_Packbladeparms( Re_Buf, Db_Buf, Int_Buf, InData%Blade, ErrStat2, ErrMsg2, OnlySize ) ! Blade + 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 AD14_Packbeddoesparms( Re_Buf, Db_Buf, Int_Buf, InData%Beddoes, ErrStat2, ErrMsg2, OnlySize ) ! Beddoes + 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 AD14_Packdyninflowparms( Re_Buf, Db_Buf, Int_Buf, InData%DynInflow, ErrStat2, ErrMsg2, OnlySize ) ! DynInflow + 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 AD14_Packelementparms( Re_Buf, Db_Buf, Int_Buf, InData%Element, ErrStat2, ErrMsg2, OnlySize ) ! Element + 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 AD14_Packtwrpropsparms( Re_Buf, Db_Buf, Int_Buf, InData%TwrProps, ErrStat2, ErrMsg2, OnlySize ) ! TwrProps + 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 AD14_Packinducedvelparms( Re_Buf, Db_Buf, Int_Buf, InData%InducedVel, ErrStat2, ErrMsg2, OnlySize ) ! InducedVel + 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 AD14_Packwindparms( Re_Buf, Db_Buf, Int_Buf, InData%Wind, ErrStat2, ErrMsg2, OnlySize ) ! Wind + 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 AD14_Packrotorparms( Re_Buf, Db_Buf, Int_Buf, InData%Rotor, ErrStat2, ErrMsg2, OnlySize ) ! Rotor + 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 DWM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%DWM, ErrStat2, ErrMsg2, OnlySize ) ! DWM + 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 AD14_PackParam + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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%Title) + OutData%Title(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%SIUnit = TRANSFER(IntKiBuf(Int_Xferred), OutData%SIUnit) + Int_Xferred = Int_Xferred + 1 + OutData%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 + OutData%MultiTab = TRANSFER(IntKiBuf(Int_Xferred), OutData%MultiTab) + Int_Xferred = Int_Xferred + 1 + OutData%LinearizeFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%LinearizeFlag) + Int_Xferred = Int_Xferred + 1 + OutData%OutputPlottingInfo = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutputPlottingInfo) + Int_Xferred = Int_Xferred + 1 + OutData%UseDWM = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseDWM) + Int_Xferred = Int_Xferred + 1 + OutData%TwoPiNB = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBlInpSt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ElemPrn = TRANSFER(IntKiBuf(Int_Xferred), OutData%ElemPrn) + Int_Xferred = Int_Xferred + 1 + OutData%DStall = TRANSFER(IntKiBuf(Int_Xferred), OutData%DStall) + Int_Xferred = Int_Xferred + 1 + OutData%PMoment = TRANSFER(IntKiBuf(Int_Xferred), OutData%PMoment) + Int_Xferred = Int_Xferred + 1 + OutData%Reynolds = TRANSFER(IntKiBuf(Int_Xferred), OutData%Reynolds) + Int_Xferred = Int_Xferred + 1 + OutData%DynInfl = TRANSFER(IntKiBuf(Int_Xferred), OutData%DynInfl) + Int_Xferred = Int_Xferred + 1 + OutData%Wake = TRANSFER(IntKiBuf(Int_Xferred), OutData%Wake) + Int_Xferred = Int_Xferred + 1 + OutData%Swirl = TRANSFER(IntKiBuf(Int_Xferred), OutData%Swirl) + Int_Xferred = Int_Xferred + 1 + OutData%DtAero = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HubRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UnEc = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnElem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnWndOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MAXICOUNT = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WrOptFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%WrOptFile) + Int_Xferred = Int_Xferred + 1 + OutData%DEFAULT_Wind = 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 AD14_Unpackairfoilparms( Re_Buf, Db_Buf, Int_Buf, OutData%AirFoil, ErrStat2, ErrMsg2 ) ! AirFoil + 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 AD14_Unpackbladeparms( Re_Buf, Db_Buf, Int_Buf, OutData%Blade, ErrStat2, ErrMsg2 ) ! Blade + 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 AD14_Unpackbeddoesparms( Re_Buf, Db_Buf, Int_Buf, OutData%Beddoes, ErrStat2, ErrMsg2 ) ! Beddoes + 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 AD14_Unpackdyninflowparms( Re_Buf, Db_Buf, Int_Buf, OutData%DynInflow, ErrStat2, ErrMsg2 ) ! DynInflow + 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 AD14_Unpackelementparms( Re_Buf, Db_Buf, Int_Buf, OutData%Element, ErrStat2, ErrMsg2 ) ! Element + 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 AD14_Unpacktwrpropsparms( Re_Buf, Db_Buf, Int_Buf, OutData%TwrProps, ErrStat2, ErrMsg2 ) ! TwrProps + 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 AD14_Unpackinducedvelparms( Re_Buf, Db_Buf, Int_Buf, OutData%InducedVel, ErrStat2, ErrMsg2 ) ! InducedVel + 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 AD14_Unpackwindparms( Re_Buf, Db_Buf, Int_Buf, OutData%Wind, ErrStat2, ErrMsg2 ) ! Wind + 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 AD14_Unpackrotorparms( Re_Buf, Db_Buf, Int_Buf, OutData%Rotor, ErrStat2, ErrMsg2 ) ! Rotor + 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 DWM_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%DWM, ErrStat2, ErrMsg2 ) ! DWM + 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 AD14_UnPackParam + + SUBROUTINE AD14_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_InputType), INTENT(INOUT) :: SrcInputData + TYPE(AD14_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 = 'AD14_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%InputMarkers)) THEN + i1_l = LBOUND(SrcInputData%InputMarkers,1) + i1_u = UBOUND(SrcInputData%InputMarkers,1) + IF (.NOT. ALLOCATED(DstInputData%InputMarkers)) THEN + ALLOCATE(DstInputData%InputMarkers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%InputMarkers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%InputMarkers,1), UBOUND(SrcInputData%InputMarkers,1) + CALL MeshCopy( SrcInputData%InputMarkers(i1), DstInputData%InputMarkers(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcInputData%Twr_InputMarkers, DstInputData%Twr_InputMarkers, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_Copyaeroconfig( SrcInputData%TurbineComponents, DstInputData%TurbineComponents, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%MulTabLoc)) THEN + i1_l = LBOUND(SrcInputData%MulTabLoc,1) + i1_u = UBOUND(SrcInputData%MulTabLoc,1) + i2_l = LBOUND(SrcInputData%MulTabLoc,2) + i2_u = UBOUND(SrcInputData%MulTabLoc,2) + IF (.NOT. ALLOCATED(DstInputData%MulTabLoc)) THEN + ALLOCATE(DstInputData%MulTabLoc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%MulTabLoc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%MulTabLoc = SrcInputData%MulTabLoc +ENDIF +IF (ALLOCATED(SrcInputData%InflowVelocity)) THEN + i1_l = LBOUND(SrcInputData%InflowVelocity,1) + i1_u = UBOUND(SrcInputData%InflowVelocity,1) + i2_l = LBOUND(SrcInputData%InflowVelocity,2) + i2_u = UBOUND(SrcInputData%InflowVelocity,2) + IF (.NOT. ALLOCATED(DstInputData%InflowVelocity)) THEN + ALLOCATE(DstInputData%InflowVelocity(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%InflowVelocity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%InflowVelocity = SrcInputData%InflowVelocity +ENDIF + DstInputData%AvgInfVel = SrcInputData%AvgInfVel + END SUBROUTINE AD14_CopyInput + + SUBROUTINE AD14_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(AD14_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%InputMarkers)) THEN +DO i1 = LBOUND(InputData%InputMarkers,1), UBOUND(InputData%InputMarkers,1) + CALL MeshDestroy( InputData%InputMarkers(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%InputMarkers) +ENDIF + CALL MeshDestroy( InputData%Twr_InputMarkers, ErrStat, ErrMsg ) + CALL AD14_Destroyaeroconfig( InputData%TurbineComponents, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%MulTabLoc)) THEN + DEALLOCATE(InputData%MulTabLoc) +ENDIF +IF (ALLOCATED(InputData%InflowVelocity)) THEN + DEALLOCATE(InputData%InflowVelocity) +ENDIF + END SUBROUTINE AD14_DestroyInput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 ! InputMarkers allocated yes/no + IF ( ALLOCATED(InData%InputMarkers) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputMarkers upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%InputMarkers,1), UBOUND(InData%InputMarkers,1) + Int_BufSz = Int_BufSz + 3 ! InputMarkers: size of buffers for each call to pack subtype + CALL MeshPack( InData%InputMarkers(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! InputMarkers + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InputMarkers + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InputMarkers + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InputMarkers + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! Twr_InputMarkers: size of buffers for each call to pack subtype + CALL MeshPack( InData%Twr_InputMarkers, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Twr_InputMarkers + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Twr_InputMarkers + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Twr_InputMarkers + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Twr_InputMarkers + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TurbineComponents: size of buffers for each call to pack subtype + CALL AD14_Packaeroconfig( Re_Buf, Db_Buf, Int_Buf, InData%TurbineComponents, ErrStat2, ErrMsg2, .TRUE. ) ! TurbineComponents + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TurbineComponents + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TurbineComponents + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TurbineComponents + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! MulTabLoc allocated yes/no + IF ( ALLOCATED(InData%MulTabLoc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MulTabLoc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MulTabLoc) ! MulTabLoc + END IF + Int_BufSz = Int_BufSz + 1 ! InflowVelocity allocated yes/no + IF ( ALLOCATED(InData%InflowVelocity) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InflowVelocity upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InflowVelocity) ! InflowVelocity + END IF + Re_BufSz = Re_BufSz + SIZE(InData%AvgInfVel) ! AvgInfVel + 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%InputMarkers) ) 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%InputMarkers,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputMarkers,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputMarkers,1), UBOUND(InData%InputMarkers,1) + CALL MeshPack( InData%InputMarkers(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! InputMarkers + 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 + CALL MeshPack( InData%Twr_InputMarkers, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Twr_InputMarkers + 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 AD14_Packaeroconfig( Re_Buf, Db_Buf, Int_Buf, InData%TurbineComponents, ErrStat2, ErrMsg2, OnlySize ) ! TurbineComponents + 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%MulTabLoc) ) 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%MulTabLoc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabLoc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MulTabLoc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MulTabLoc,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MulTabLoc,2), UBOUND(InData%MulTabLoc,2) + DO i1 = LBOUND(InData%MulTabLoc,1), UBOUND(InData%MulTabLoc,1) + ReKiBuf(Re_Xferred) = InData%MulTabLoc(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InflowVelocity) ) 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%InflowVelocity,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowVelocity,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InflowVelocity,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InflowVelocity,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InflowVelocity,2), UBOUND(InData%InflowVelocity,2) + DO i1 = LBOUND(InData%InflowVelocity,1), UBOUND(InData%InflowVelocity,1) + ReKiBuf(Re_Xferred) = InData%InflowVelocity(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%AvgInfVel,1), UBOUND(InData%AvgInfVel,1) + ReKiBuf(Re_Xferred) = InData%AvgInfVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_PackInput + + SUBROUTINE AD14_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(AD14_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 = 'AD14_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 ! InputMarkers 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%InputMarkers)) DEALLOCATE(OutData%InputMarkers) + ALLOCATE(OutData%InputMarkers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputMarkers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputMarkers,1), UBOUND(OutData%InputMarkers,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 MeshUnpack( OutData%InputMarkers(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! InputMarkers + 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 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 MeshUnpack( OutData%Twr_InputMarkers, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Twr_InputMarkers + 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 AD14_Unpackaeroconfig( Re_Buf, Db_Buf, Int_Buf, OutData%TurbineComponents, ErrStat2, ErrMsg2 ) ! TurbineComponents + 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 ! MulTabLoc 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%MulTabLoc)) DEALLOCATE(OutData%MulTabLoc) + ALLOCATE(OutData%MulTabLoc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MulTabLoc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MulTabLoc,2), UBOUND(OutData%MulTabLoc,2) + DO i1 = LBOUND(OutData%MulTabLoc,1), UBOUND(OutData%MulTabLoc,1) + OutData%MulTabLoc(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InflowVelocity 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%InflowVelocity)) DEALLOCATE(OutData%InflowVelocity) + ALLOCATE(OutData%InflowVelocity(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InflowVelocity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InflowVelocity,2), UBOUND(OutData%InflowVelocity,2) + DO i1 = LBOUND(OutData%InflowVelocity,1), UBOUND(OutData%InflowVelocity,1) + OutData%InflowVelocity(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%AvgInfVel,1) + i1_u = UBOUND(OutData%AvgInfVel,1) + DO i1 = LBOUND(OutData%AvgInfVel,1), UBOUND(OutData%AvgInfVel,1) + OutData%AvgInfVel(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE AD14_UnPackInput + + SUBROUTINE AD14_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AD14_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(AD14_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'AD14_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%OutputLoads)) THEN + i1_l = LBOUND(SrcOutputData%OutputLoads,1) + i1_u = UBOUND(SrcOutputData%OutputLoads,1) + IF (.NOT. ALLOCATED(DstOutputData%OutputLoads)) THEN + ALLOCATE(DstOutputData%OutputLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%OutputLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOutputData%OutputLoads,1), UBOUND(SrcOutputData%OutputLoads,1) + CALL MeshCopy( SrcOutputData%OutputLoads(i1), DstOutputData%OutputLoads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcOutputData%Twr_OutputLoads, DstOutputData%Twr_OutputLoads, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE AD14_CopyOutput + + SUBROUTINE AD14_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(AD14_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%OutputLoads)) THEN +DO i1 = LBOUND(OutputData%OutputLoads,1), UBOUND(OutputData%OutputLoads,1) + CALL MeshDestroy( OutputData%OutputLoads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OutputData%OutputLoads) +ENDIF + CALL MeshDestroy( OutputData%Twr_OutputLoads, ErrStat, ErrMsg ) + END SUBROUTINE AD14_DestroyOutput + + SUBROUTINE AD14_PackOutput( 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(AD14_OutputType), 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 = 'AD14_PackOutput' + ! 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 ! OutputLoads allocated yes/no + IF ( ALLOCATED(InData%OutputLoads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutputLoads upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%OutputLoads,1), UBOUND(InData%OutputLoads,1) + Int_BufSz = Int_BufSz + 3 ! OutputLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%OutputLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! OutputLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutputLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutputLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutputLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! Twr_OutputLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%Twr_OutputLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Twr_OutputLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Twr_OutputLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Twr_OutputLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Twr_OutputLoads + 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 + + IF ( .NOT. ALLOCATED(InData%OutputLoads) ) 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%OutputLoads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutputLoads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutputLoads,1), UBOUND(InData%OutputLoads,1) + CALL MeshPack( InData%OutputLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! OutputLoads + 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 + CALL MeshPack( InData%Twr_OutputLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Twr_OutputLoads + 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 AD14_PackOutput + + SUBROUTINE AD14_UnPackOutput( 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(AD14_OutputType), 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 = 'AD14_UnPackOutput' + ! 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 ! OutputLoads 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%OutputLoads)) DEALLOCATE(OutData%OutputLoads) + ALLOCATE(OutData%OutputLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutputLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutputLoads,1), UBOUND(OutData%OutputLoads,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 MeshUnpack( OutData%OutputLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! OutputLoads + 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 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 MeshUnpack( OutData%Twr_OutputLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Twr_OutputLoads + 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 AD14_UnPackOutput + + + SUBROUTINE AD14_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD14_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(AD14_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL AD14_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD14_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD14_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD14_Input_ExtrapInterp + + + SUBROUTINE AD14_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(AD14_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(AD14_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(AD14_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i11 ! dim1 level 1 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i12 ! dim2 level 1 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%InputMarkers) .AND. ALLOCATED(u1%InputMarkers)) THEN + DO i1 = LBOUND(u_out%InputMarkers,1),UBOUND(u_out%InputMarkers,1) + CALL MeshExtrapInterp1(u1%InputMarkers(i1), u2%InputMarkers(i1), tin, u_out%InputMarkers(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp1(u1%Twr_InputMarkers, u2%Twr_InputMarkers, tin, u_out%Twr_InputMarkers, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%TurbineComponents%Blade) .AND. ALLOCATED(u1%TurbineComponents%Blade)) THEN + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%Position,1),UBOUND(u_out%TurbineComponents%Blade(i11)%Position,1) + b = -(u1%TurbineComponents%Blade(i11)%Position(i1) - u2%TurbineComponents%Blade(i11)%Position(i1)) + u_out%TurbineComponents%Blade(i11)%Position(i1) = u1%TurbineComponents%Blade(i11)%Position(i1) + b * ScaleFactor + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i2 = LBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,2),UBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,1),UBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,1) + b = -(u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) - u2%TurbineComponents%Blade(i11)%Orientation(i1,i2)) + u_out%TurbineComponents%Blade(i11)%Orientation(i1,i2) = u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%TranslationVel,1),UBOUND(u_out%TurbineComponents%Blade(i11)%TranslationVel,1) + b = -(u1%TurbineComponents%Blade(i11)%TranslationVel(i1) - u2%TurbineComponents%Blade(i11)%TranslationVel(i1)) + u_out%TurbineComponents%Blade(i11)%TranslationVel(i1) = u1%TurbineComponents%Blade(i11)%TranslationVel(i1) + b * ScaleFactor + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%RotationVel,1),UBOUND(u_out%TurbineComponents%Blade(i11)%RotationVel,1) + b = -(u1%TurbineComponents%Blade(i11)%RotationVel(i1) - u2%TurbineComponents%Blade(i11)%RotationVel(i1)) + u_out%TurbineComponents%Blade(i11)%RotationVel(i1) = u1%TurbineComponents%Blade(i11)%RotationVel(i1) + b * ScaleFactor + END DO + ENDDO +END IF ! check if allocated + DO i1 = LBOUND(u_out%TurbineComponents%Hub%Position,1),UBOUND(u_out%TurbineComponents%Hub%Position,1) + b = -(u1%TurbineComponents%Hub%Position(i1) - u2%TurbineComponents%Hub%Position(i1)) + u_out%TurbineComponents%Hub%Position(i1) = u1%TurbineComponents%Hub%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Hub%Orientation,2),UBOUND(u_out%TurbineComponents%Hub%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Hub%Orientation,1),UBOUND(u_out%TurbineComponents%Hub%Orientation,1) + b = -(u1%TurbineComponents%Hub%Orientation(i1,i2) - u2%TurbineComponents%Hub%Orientation(i1,i2)) + u_out%TurbineComponents%Hub%Orientation(i1,i2) = u1%TurbineComponents%Hub%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Hub%TranslationVel,1),UBOUND(u_out%TurbineComponents%Hub%TranslationVel,1) + b = -(u1%TurbineComponents%Hub%TranslationVel(i1) - u2%TurbineComponents%Hub%TranslationVel(i1)) + u_out%TurbineComponents%Hub%TranslationVel(i1) = u1%TurbineComponents%Hub%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Hub%RotationVel,1),UBOUND(u_out%TurbineComponents%Hub%RotationVel,1) + b = -(u1%TurbineComponents%Hub%RotationVel(i1) - u2%TurbineComponents%Hub%RotationVel(i1)) + u_out%TurbineComponents%Hub%RotationVel(i1) = u1%TurbineComponents%Hub%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%Position,1),UBOUND(u_out%TurbineComponents%RotorFurl%Position,1) + b = -(u1%TurbineComponents%RotorFurl%Position(i1) - u2%TurbineComponents%RotorFurl%Position(i1)) + u_out%TurbineComponents%RotorFurl%Position(i1) = u1%TurbineComponents%RotorFurl%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%RotorFurl%Orientation,2),UBOUND(u_out%TurbineComponents%RotorFurl%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%Orientation,1),UBOUND(u_out%TurbineComponents%RotorFurl%Orientation,1) + b = -(u1%TurbineComponents%RotorFurl%Orientation(i1,i2) - u2%TurbineComponents%RotorFurl%Orientation(i1,i2)) + u_out%TurbineComponents%RotorFurl%Orientation(i1,i2) = u1%TurbineComponents%RotorFurl%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%TranslationVel,1),UBOUND(u_out%TurbineComponents%RotorFurl%TranslationVel,1) + b = -(u1%TurbineComponents%RotorFurl%TranslationVel(i1) - u2%TurbineComponents%RotorFurl%TranslationVel(i1)) + u_out%TurbineComponents%RotorFurl%TranslationVel(i1) = u1%TurbineComponents%RotorFurl%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%RotationVel,1),UBOUND(u_out%TurbineComponents%RotorFurl%RotationVel,1) + b = -(u1%TurbineComponents%RotorFurl%RotationVel(i1) - u2%TurbineComponents%RotorFurl%RotationVel(i1)) + u_out%TurbineComponents%RotorFurl%RotationVel(i1) = u1%TurbineComponents%RotorFurl%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%Position,1),UBOUND(u_out%TurbineComponents%Nacelle%Position,1) + b = -(u1%TurbineComponents%Nacelle%Position(i1) - u2%TurbineComponents%Nacelle%Position(i1)) + u_out%TurbineComponents%Nacelle%Position(i1) = u1%TurbineComponents%Nacelle%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Nacelle%Orientation,2),UBOUND(u_out%TurbineComponents%Nacelle%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%Orientation,1),UBOUND(u_out%TurbineComponents%Nacelle%Orientation,1) + b = -(u1%TurbineComponents%Nacelle%Orientation(i1,i2) - u2%TurbineComponents%Nacelle%Orientation(i1,i2)) + u_out%TurbineComponents%Nacelle%Orientation(i1,i2) = u1%TurbineComponents%Nacelle%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%TranslationVel,1),UBOUND(u_out%TurbineComponents%Nacelle%TranslationVel,1) + b = -(u1%TurbineComponents%Nacelle%TranslationVel(i1) - u2%TurbineComponents%Nacelle%TranslationVel(i1)) + u_out%TurbineComponents%Nacelle%TranslationVel(i1) = u1%TurbineComponents%Nacelle%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%RotationVel,1),UBOUND(u_out%TurbineComponents%Nacelle%RotationVel,1) + b = -(u1%TurbineComponents%Nacelle%RotationVel(i1) - u2%TurbineComponents%Nacelle%RotationVel(i1)) + u_out%TurbineComponents%Nacelle%RotationVel(i1) = u1%TurbineComponents%Nacelle%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%Position,1),UBOUND(u_out%TurbineComponents%TailFin%Position,1) + b = -(u1%TurbineComponents%TailFin%Position(i1) - u2%TurbineComponents%TailFin%Position(i1)) + u_out%TurbineComponents%TailFin%Position(i1) = u1%TurbineComponents%TailFin%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%TailFin%Orientation,2),UBOUND(u_out%TurbineComponents%TailFin%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%Orientation,1),UBOUND(u_out%TurbineComponents%TailFin%Orientation,1) + b = -(u1%TurbineComponents%TailFin%Orientation(i1,i2) - u2%TurbineComponents%TailFin%Orientation(i1,i2)) + u_out%TurbineComponents%TailFin%Orientation(i1,i2) = u1%TurbineComponents%TailFin%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%TranslationVel,1),UBOUND(u_out%TurbineComponents%TailFin%TranslationVel,1) + b = -(u1%TurbineComponents%TailFin%TranslationVel(i1) - u2%TurbineComponents%TailFin%TranslationVel(i1)) + u_out%TurbineComponents%TailFin%TranslationVel(i1) = u1%TurbineComponents%TailFin%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%RotationVel,1),UBOUND(u_out%TurbineComponents%TailFin%RotationVel,1) + b = -(u1%TurbineComponents%TailFin%RotationVel(i1) - u2%TurbineComponents%TailFin%RotationVel(i1)) + u_out%TurbineComponents%TailFin%RotationVel(i1) = u1%TurbineComponents%TailFin%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%Position,1),UBOUND(u_out%TurbineComponents%Tower%Position,1) + b = -(u1%TurbineComponents%Tower%Position(i1) - u2%TurbineComponents%Tower%Position(i1)) + u_out%TurbineComponents%Tower%Position(i1) = u1%TurbineComponents%Tower%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Tower%Orientation,2),UBOUND(u_out%TurbineComponents%Tower%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Tower%Orientation,1),UBOUND(u_out%TurbineComponents%Tower%Orientation,1) + b = -(u1%TurbineComponents%Tower%Orientation(i1,i2) - u2%TurbineComponents%Tower%Orientation(i1,i2)) + u_out%TurbineComponents%Tower%Orientation(i1,i2) = u1%TurbineComponents%Tower%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%TranslationVel,1),UBOUND(u_out%TurbineComponents%Tower%TranslationVel,1) + b = -(u1%TurbineComponents%Tower%TranslationVel(i1) - u2%TurbineComponents%Tower%TranslationVel(i1)) + u_out%TurbineComponents%Tower%TranslationVel(i1) = u1%TurbineComponents%Tower%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%RotationVel,1),UBOUND(u_out%TurbineComponents%Tower%RotationVel,1) + b = -(u1%TurbineComponents%Tower%RotationVel(i1) - u2%TurbineComponents%Tower%RotationVel(i1)) + u_out%TurbineComponents%Tower%RotationVel(i1) = u1%TurbineComponents%Tower%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%Position,1),UBOUND(u_out%TurbineComponents%SubStructure%Position,1) + b = -(u1%TurbineComponents%SubStructure%Position(i1) - u2%TurbineComponents%SubStructure%Position(i1)) + u_out%TurbineComponents%SubStructure%Position(i1) = u1%TurbineComponents%SubStructure%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%SubStructure%Orientation,2),UBOUND(u_out%TurbineComponents%SubStructure%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%Orientation,1),UBOUND(u_out%TurbineComponents%SubStructure%Orientation,1) + b = -(u1%TurbineComponents%SubStructure%Orientation(i1,i2) - u2%TurbineComponents%SubStructure%Orientation(i1,i2)) + u_out%TurbineComponents%SubStructure%Orientation(i1,i2) = u1%TurbineComponents%SubStructure%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%TranslationVel,1),UBOUND(u_out%TurbineComponents%SubStructure%TranslationVel,1) + b = -(u1%TurbineComponents%SubStructure%TranslationVel(i1) - u2%TurbineComponents%SubStructure%TranslationVel(i1)) + u_out%TurbineComponents%SubStructure%TranslationVel(i1) = u1%TurbineComponents%SubStructure%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%RotationVel,1),UBOUND(u_out%TurbineComponents%SubStructure%RotationVel,1) + b = -(u1%TurbineComponents%SubStructure%RotationVel(i1) - u2%TurbineComponents%SubStructure%RotationVel(i1)) + u_out%TurbineComponents%SubStructure%RotationVel(i1) = u1%TurbineComponents%SubStructure%RotationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%Position,1),UBOUND(u_out%TurbineComponents%Foundation%Position,1) + b = -(u1%TurbineComponents%Foundation%Position(i1) - u2%TurbineComponents%Foundation%Position(i1)) + u_out%TurbineComponents%Foundation%Position(i1) = u1%TurbineComponents%Foundation%Position(i1) + b * ScaleFactor + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Foundation%Orientation,2),UBOUND(u_out%TurbineComponents%Foundation%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%Orientation,1),UBOUND(u_out%TurbineComponents%Foundation%Orientation,1) + b = -(u1%TurbineComponents%Foundation%Orientation(i1,i2) - u2%TurbineComponents%Foundation%Orientation(i1,i2)) + u_out%TurbineComponents%Foundation%Orientation(i1,i2) = u1%TurbineComponents%Foundation%Orientation(i1,i2) + b * ScaleFactor + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%TranslationVel,1),UBOUND(u_out%TurbineComponents%Foundation%TranslationVel,1) + b = -(u1%TurbineComponents%Foundation%TranslationVel(i1) - u2%TurbineComponents%Foundation%TranslationVel(i1)) + u_out%TurbineComponents%Foundation%TranslationVel(i1) = u1%TurbineComponents%Foundation%TranslationVel(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%RotationVel,1),UBOUND(u_out%TurbineComponents%Foundation%RotationVel,1) + b = -(u1%TurbineComponents%Foundation%RotationVel(i1) - u2%TurbineComponents%Foundation%RotationVel(i1)) + u_out%TurbineComponents%Foundation%RotationVel(i1) = u1%TurbineComponents%Foundation%RotationVel(i1) + b * ScaleFactor + END DO + b = -(u1%TurbineComponents%BladeLength - u2%TurbineComponents%BladeLength) + u_out%TurbineComponents%BladeLength = u1%TurbineComponents%BladeLength + b * ScaleFactor +IF (ALLOCATED(u_out%MulTabLoc) .AND. ALLOCATED(u1%MulTabLoc)) THEN + DO i2 = LBOUND(u_out%MulTabLoc,2),UBOUND(u_out%MulTabLoc,2) + DO i1 = LBOUND(u_out%MulTabLoc,1),UBOUND(u_out%MulTabLoc,1) + b = -(u1%MulTabLoc(i1,i2) - u2%MulTabLoc(i1,i2)) + u_out%MulTabLoc(i1,i2) = u1%MulTabLoc(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowVelocity) .AND. ALLOCATED(u1%InflowVelocity)) THEN + DO i2 = LBOUND(u_out%InflowVelocity,2),UBOUND(u_out%InflowVelocity,2) + DO i1 = LBOUND(u_out%InflowVelocity,1),UBOUND(u_out%InflowVelocity,1) + b = -(u1%InflowVelocity(i1,i2) - u2%InflowVelocity(i1,i2)) + u_out%InflowVelocity(i1,i2) = u1%InflowVelocity(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + DO i1 = LBOUND(u_out%AvgInfVel,1),UBOUND(u_out%AvgInfVel,1) + b = -(u1%AvgInfVel(i1) - u2%AvgInfVel(i1)) + u_out%AvgInfVel(i1) = u1%AvgInfVel(i1) + b * ScaleFactor + END DO + END SUBROUTINE AD14_Input_ExtrapInterp1 + + + SUBROUTINE AD14_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(AD14_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(AD14_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(AD14_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(AD14_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i11 ! dim1 level 1 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i12 ! dim2 level 1 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%InputMarkers) .AND. ALLOCATED(u1%InputMarkers)) THEN + DO i1 = LBOUND(u_out%InputMarkers,1),UBOUND(u_out%InputMarkers,1) + CALL MeshExtrapInterp2(u1%InputMarkers(i1), u2%InputMarkers(i1), u3%InputMarkers(i1), tin, u_out%InputMarkers(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp2(u1%Twr_InputMarkers, u2%Twr_InputMarkers, u3%Twr_InputMarkers, tin, u_out%Twr_InputMarkers, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%TurbineComponents%Blade) .AND. ALLOCATED(u1%TurbineComponents%Blade)) THEN + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%Position,1),UBOUND(u_out%TurbineComponents%Blade(i11)%Position,1) + b = (t(3)**2*(u1%TurbineComponents%Blade(i11)%Position(i1) - u2%TurbineComponents%Blade(i11)%Position(i1)) + t(2)**2*(-u1%TurbineComponents%Blade(i11)%Position(i1) + u3%TurbineComponents%Blade(i11)%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Blade(i11)%Position(i1) + t(3)*u2%TurbineComponents%Blade(i11)%Position(i1) - t(2)*u3%TurbineComponents%Blade(i11)%Position(i1) ) * scaleFactor + u_out%TurbineComponents%Blade(i11)%Position(i1) = u1%TurbineComponents%Blade(i11)%Position(i1) + b + c * t_out + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i2 = LBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,2),UBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,1),UBOUND(u_out%TurbineComponents%Blade(i11)%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) - u2%TurbineComponents%Blade(i11)%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) + u3%TurbineComponents%Blade(i11)%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) + t(3)*u2%TurbineComponents%Blade(i11)%Orientation(i1,i2) - t(2)*u3%TurbineComponents%Blade(i11)%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%Blade(i11)%Orientation(i1,i2) = u1%TurbineComponents%Blade(i11)%Orientation(i1,i2) + b + c * t_out + END DO + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%TranslationVel,1),UBOUND(u_out%TurbineComponents%Blade(i11)%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Blade(i11)%TranslationVel(i1) - u2%TurbineComponents%Blade(i11)%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Blade(i11)%TranslationVel(i1) + u3%TurbineComponents%Blade(i11)%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Blade(i11)%TranslationVel(i1) + t(3)*u2%TurbineComponents%Blade(i11)%TranslationVel(i1) - t(2)*u3%TurbineComponents%Blade(i11)%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Blade(i11)%TranslationVel(i1) = u1%TurbineComponents%Blade(i11)%TranslationVel(i1) + b + c * t_out + END DO + ENDDO + DO i11 = LBOUND(u_out%TurbineComponents%Blade,1),UBOUND(u_out%TurbineComponents%Blade,1) + DO i1 = LBOUND(u_out%TurbineComponents%Blade(i11)%RotationVel,1),UBOUND(u_out%TurbineComponents%Blade(i11)%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Blade(i11)%RotationVel(i1) - u2%TurbineComponents%Blade(i11)%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Blade(i11)%RotationVel(i1) + u3%TurbineComponents%Blade(i11)%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Blade(i11)%RotationVel(i1) + t(3)*u2%TurbineComponents%Blade(i11)%RotationVel(i1) - t(2)*u3%TurbineComponents%Blade(i11)%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Blade(i11)%RotationVel(i1) = u1%TurbineComponents%Blade(i11)%RotationVel(i1) + b + c * t_out + END DO + ENDDO +END IF ! check if allocated + DO i1 = LBOUND(u_out%TurbineComponents%Hub%Position,1),UBOUND(u_out%TurbineComponents%Hub%Position,1) + b = (t(3)**2*(u1%TurbineComponents%Hub%Position(i1) - u2%TurbineComponents%Hub%Position(i1)) + t(2)**2*(-u1%TurbineComponents%Hub%Position(i1) + u3%TurbineComponents%Hub%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Hub%Position(i1) + t(3)*u2%TurbineComponents%Hub%Position(i1) - t(2)*u3%TurbineComponents%Hub%Position(i1) ) * scaleFactor + u_out%TurbineComponents%Hub%Position(i1) = u1%TurbineComponents%Hub%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Hub%Orientation,2),UBOUND(u_out%TurbineComponents%Hub%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Hub%Orientation,1),UBOUND(u_out%TurbineComponents%Hub%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%Hub%Orientation(i1,i2) - u2%TurbineComponents%Hub%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%Hub%Orientation(i1,i2) + u3%TurbineComponents%Hub%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Hub%Orientation(i1,i2) + t(3)*u2%TurbineComponents%Hub%Orientation(i1,i2) - t(2)*u3%TurbineComponents%Hub%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%Hub%Orientation(i1,i2) = u1%TurbineComponents%Hub%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Hub%TranslationVel,1),UBOUND(u_out%TurbineComponents%Hub%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Hub%TranslationVel(i1) - u2%TurbineComponents%Hub%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Hub%TranslationVel(i1) + u3%TurbineComponents%Hub%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Hub%TranslationVel(i1) + t(3)*u2%TurbineComponents%Hub%TranslationVel(i1) - t(2)*u3%TurbineComponents%Hub%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Hub%TranslationVel(i1) = u1%TurbineComponents%Hub%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Hub%RotationVel,1),UBOUND(u_out%TurbineComponents%Hub%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Hub%RotationVel(i1) - u2%TurbineComponents%Hub%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Hub%RotationVel(i1) + u3%TurbineComponents%Hub%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Hub%RotationVel(i1) + t(3)*u2%TurbineComponents%Hub%RotationVel(i1) - t(2)*u3%TurbineComponents%Hub%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Hub%RotationVel(i1) = u1%TurbineComponents%Hub%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%Position,1),UBOUND(u_out%TurbineComponents%RotorFurl%Position,1) + b = (t(3)**2*(u1%TurbineComponents%RotorFurl%Position(i1) - u2%TurbineComponents%RotorFurl%Position(i1)) + t(2)**2*(-u1%TurbineComponents%RotorFurl%Position(i1) + u3%TurbineComponents%RotorFurl%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%RotorFurl%Position(i1) + t(3)*u2%TurbineComponents%RotorFurl%Position(i1) - t(2)*u3%TurbineComponents%RotorFurl%Position(i1) ) * scaleFactor + u_out%TurbineComponents%RotorFurl%Position(i1) = u1%TurbineComponents%RotorFurl%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%RotorFurl%Orientation,2),UBOUND(u_out%TurbineComponents%RotorFurl%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%Orientation,1),UBOUND(u_out%TurbineComponents%RotorFurl%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%RotorFurl%Orientation(i1,i2) - u2%TurbineComponents%RotorFurl%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%RotorFurl%Orientation(i1,i2) + u3%TurbineComponents%RotorFurl%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%RotorFurl%Orientation(i1,i2) + t(3)*u2%TurbineComponents%RotorFurl%Orientation(i1,i2) - t(2)*u3%TurbineComponents%RotorFurl%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%RotorFurl%Orientation(i1,i2) = u1%TurbineComponents%RotorFurl%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%TranslationVel,1),UBOUND(u_out%TurbineComponents%RotorFurl%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%RotorFurl%TranslationVel(i1) - u2%TurbineComponents%RotorFurl%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%RotorFurl%TranslationVel(i1) + u3%TurbineComponents%RotorFurl%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%RotorFurl%TranslationVel(i1) + t(3)*u2%TurbineComponents%RotorFurl%TranslationVel(i1) - t(2)*u3%TurbineComponents%RotorFurl%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%RotorFurl%TranslationVel(i1) = u1%TurbineComponents%RotorFurl%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%RotorFurl%RotationVel,1),UBOUND(u_out%TurbineComponents%RotorFurl%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%RotorFurl%RotationVel(i1) - u2%TurbineComponents%RotorFurl%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%RotorFurl%RotationVel(i1) + u3%TurbineComponents%RotorFurl%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%RotorFurl%RotationVel(i1) + t(3)*u2%TurbineComponents%RotorFurl%RotationVel(i1) - t(2)*u3%TurbineComponents%RotorFurl%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%RotorFurl%RotationVel(i1) = u1%TurbineComponents%RotorFurl%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%Position,1),UBOUND(u_out%TurbineComponents%Nacelle%Position,1) + b = (t(3)**2*(u1%TurbineComponents%Nacelle%Position(i1) - u2%TurbineComponents%Nacelle%Position(i1)) + t(2)**2*(-u1%TurbineComponents%Nacelle%Position(i1) + u3%TurbineComponents%Nacelle%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Nacelle%Position(i1) + t(3)*u2%TurbineComponents%Nacelle%Position(i1) - t(2)*u3%TurbineComponents%Nacelle%Position(i1) ) * scaleFactor + u_out%TurbineComponents%Nacelle%Position(i1) = u1%TurbineComponents%Nacelle%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Nacelle%Orientation,2),UBOUND(u_out%TurbineComponents%Nacelle%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%Orientation,1),UBOUND(u_out%TurbineComponents%Nacelle%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%Nacelle%Orientation(i1,i2) - u2%TurbineComponents%Nacelle%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%Nacelle%Orientation(i1,i2) + u3%TurbineComponents%Nacelle%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Nacelle%Orientation(i1,i2) + t(3)*u2%TurbineComponents%Nacelle%Orientation(i1,i2) - t(2)*u3%TurbineComponents%Nacelle%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%Nacelle%Orientation(i1,i2) = u1%TurbineComponents%Nacelle%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%TranslationVel,1),UBOUND(u_out%TurbineComponents%Nacelle%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Nacelle%TranslationVel(i1) - u2%TurbineComponents%Nacelle%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Nacelle%TranslationVel(i1) + u3%TurbineComponents%Nacelle%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Nacelle%TranslationVel(i1) + t(3)*u2%TurbineComponents%Nacelle%TranslationVel(i1) - t(2)*u3%TurbineComponents%Nacelle%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Nacelle%TranslationVel(i1) = u1%TurbineComponents%Nacelle%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Nacelle%RotationVel,1),UBOUND(u_out%TurbineComponents%Nacelle%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Nacelle%RotationVel(i1) - u2%TurbineComponents%Nacelle%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Nacelle%RotationVel(i1) + u3%TurbineComponents%Nacelle%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Nacelle%RotationVel(i1) + t(3)*u2%TurbineComponents%Nacelle%RotationVel(i1) - t(2)*u3%TurbineComponents%Nacelle%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Nacelle%RotationVel(i1) = u1%TurbineComponents%Nacelle%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%Position,1),UBOUND(u_out%TurbineComponents%TailFin%Position,1) + b = (t(3)**2*(u1%TurbineComponents%TailFin%Position(i1) - u2%TurbineComponents%TailFin%Position(i1)) + t(2)**2*(-u1%TurbineComponents%TailFin%Position(i1) + u3%TurbineComponents%TailFin%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%TailFin%Position(i1) + t(3)*u2%TurbineComponents%TailFin%Position(i1) - t(2)*u3%TurbineComponents%TailFin%Position(i1) ) * scaleFactor + u_out%TurbineComponents%TailFin%Position(i1) = u1%TurbineComponents%TailFin%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%TailFin%Orientation,2),UBOUND(u_out%TurbineComponents%TailFin%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%Orientation,1),UBOUND(u_out%TurbineComponents%TailFin%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%TailFin%Orientation(i1,i2) - u2%TurbineComponents%TailFin%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%TailFin%Orientation(i1,i2) + u3%TurbineComponents%TailFin%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%TailFin%Orientation(i1,i2) + t(3)*u2%TurbineComponents%TailFin%Orientation(i1,i2) - t(2)*u3%TurbineComponents%TailFin%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%TailFin%Orientation(i1,i2) = u1%TurbineComponents%TailFin%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%TranslationVel,1),UBOUND(u_out%TurbineComponents%TailFin%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%TailFin%TranslationVel(i1) - u2%TurbineComponents%TailFin%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%TailFin%TranslationVel(i1) + u3%TurbineComponents%TailFin%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%TailFin%TranslationVel(i1) + t(3)*u2%TurbineComponents%TailFin%TranslationVel(i1) - t(2)*u3%TurbineComponents%TailFin%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%TailFin%TranslationVel(i1) = u1%TurbineComponents%TailFin%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%TailFin%RotationVel,1),UBOUND(u_out%TurbineComponents%TailFin%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%TailFin%RotationVel(i1) - u2%TurbineComponents%TailFin%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%TailFin%RotationVel(i1) + u3%TurbineComponents%TailFin%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%TailFin%RotationVel(i1) + t(3)*u2%TurbineComponents%TailFin%RotationVel(i1) - t(2)*u3%TurbineComponents%TailFin%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%TailFin%RotationVel(i1) = u1%TurbineComponents%TailFin%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%Position,1),UBOUND(u_out%TurbineComponents%Tower%Position,1) + b = (t(3)**2*(u1%TurbineComponents%Tower%Position(i1) - u2%TurbineComponents%Tower%Position(i1)) + t(2)**2*(-u1%TurbineComponents%Tower%Position(i1) + u3%TurbineComponents%Tower%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Tower%Position(i1) + t(3)*u2%TurbineComponents%Tower%Position(i1) - t(2)*u3%TurbineComponents%Tower%Position(i1) ) * scaleFactor + u_out%TurbineComponents%Tower%Position(i1) = u1%TurbineComponents%Tower%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Tower%Orientation,2),UBOUND(u_out%TurbineComponents%Tower%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Tower%Orientation,1),UBOUND(u_out%TurbineComponents%Tower%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%Tower%Orientation(i1,i2) - u2%TurbineComponents%Tower%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%Tower%Orientation(i1,i2) + u3%TurbineComponents%Tower%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Tower%Orientation(i1,i2) + t(3)*u2%TurbineComponents%Tower%Orientation(i1,i2) - t(2)*u3%TurbineComponents%Tower%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%Tower%Orientation(i1,i2) = u1%TurbineComponents%Tower%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%TranslationVel,1),UBOUND(u_out%TurbineComponents%Tower%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Tower%TranslationVel(i1) - u2%TurbineComponents%Tower%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Tower%TranslationVel(i1) + u3%TurbineComponents%Tower%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Tower%TranslationVel(i1) + t(3)*u2%TurbineComponents%Tower%TranslationVel(i1) - t(2)*u3%TurbineComponents%Tower%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Tower%TranslationVel(i1) = u1%TurbineComponents%Tower%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Tower%RotationVel,1),UBOUND(u_out%TurbineComponents%Tower%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Tower%RotationVel(i1) - u2%TurbineComponents%Tower%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Tower%RotationVel(i1) + u3%TurbineComponents%Tower%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Tower%RotationVel(i1) + t(3)*u2%TurbineComponents%Tower%RotationVel(i1) - t(2)*u3%TurbineComponents%Tower%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Tower%RotationVel(i1) = u1%TurbineComponents%Tower%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%Position,1),UBOUND(u_out%TurbineComponents%SubStructure%Position,1) + b = (t(3)**2*(u1%TurbineComponents%SubStructure%Position(i1) - u2%TurbineComponents%SubStructure%Position(i1)) + t(2)**2*(-u1%TurbineComponents%SubStructure%Position(i1) + u3%TurbineComponents%SubStructure%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%SubStructure%Position(i1) + t(3)*u2%TurbineComponents%SubStructure%Position(i1) - t(2)*u3%TurbineComponents%SubStructure%Position(i1) ) * scaleFactor + u_out%TurbineComponents%SubStructure%Position(i1) = u1%TurbineComponents%SubStructure%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%SubStructure%Orientation,2),UBOUND(u_out%TurbineComponents%SubStructure%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%Orientation,1),UBOUND(u_out%TurbineComponents%SubStructure%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%SubStructure%Orientation(i1,i2) - u2%TurbineComponents%SubStructure%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%SubStructure%Orientation(i1,i2) + u3%TurbineComponents%SubStructure%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%SubStructure%Orientation(i1,i2) + t(3)*u2%TurbineComponents%SubStructure%Orientation(i1,i2) - t(2)*u3%TurbineComponents%SubStructure%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%SubStructure%Orientation(i1,i2) = u1%TurbineComponents%SubStructure%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%TranslationVel,1),UBOUND(u_out%TurbineComponents%SubStructure%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%SubStructure%TranslationVel(i1) - u2%TurbineComponents%SubStructure%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%SubStructure%TranslationVel(i1) + u3%TurbineComponents%SubStructure%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%SubStructure%TranslationVel(i1) + t(3)*u2%TurbineComponents%SubStructure%TranslationVel(i1) - t(2)*u3%TurbineComponents%SubStructure%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%SubStructure%TranslationVel(i1) = u1%TurbineComponents%SubStructure%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%SubStructure%RotationVel,1),UBOUND(u_out%TurbineComponents%SubStructure%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%SubStructure%RotationVel(i1) - u2%TurbineComponents%SubStructure%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%SubStructure%RotationVel(i1) + u3%TurbineComponents%SubStructure%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%SubStructure%RotationVel(i1) + t(3)*u2%TurbineComponents%SubStructure%RotationVel(i1) - t(2)*u3%TurbineComponents%SubStructure%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%SubStructure%RotationVel(i1) = u1%TurbineComponents%SubStructure%RotationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%Position,1),UBOUND(u_out%TurbineComponents%Foundation%Position,1) + b = (t(3)**2*(u1%TurbineComponents%Foundation%Position(i1) - u2%TurbineComponents%Foundation%Position(i1)) + t(2)**2*(-u1%TurbineComponents%Foundation%Position(i1) + u3%TurbineComponents%Foundation%Position(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Foundation%Position(i1) + t(3)*u2%TurbineComponents%Foundation%Position(i1) - t(2)*u3%TurbineComponents%Foundation%Position(i1) ) * scaleFactor + u_out%TurbineComponents%Foundation%Position(i1) = u1%TurbineComponents%Foundation%Position(i1) + b + c * t_out + END DO + DO i2 = LBOUND(u_out%TurbineComponents%Foundation%Orientation,2),UBOUND(u_out%TurbineComponents%Foundation%Orientation,2) + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%Orientation,1),UBOUND(u_out%TurbineComponents%Foundation%Orientation,1) + b = (t(3)**2*(u1%TurbineComponents%Foundation%Orientation(i1,i2) - u2%TurbineComponents%Foundation%Orientation(i1,i2)) + t(2)**2*(-u1%TurbineComponents%Foundation%Orientation(i1,i2) + u3%TurbineComponents%Foundation%Orientation(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Foundation%Orientation(i1,i2) + t(3)*u2%TurbineComponents%Foundation%Orientation(i1,i2) - t(2)*u3%TurbineComponents%Foundation%Orientation(i1,i2) ) * scaleFactor + u_out%TurbineComponents%Foundation%Orientation(i1,i2) = u1%TurbineComponents%Foundation%Orientation(i1,i2) + b + c * t_out + END DO + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%TranslationVel,1),UBOUND(u_out%TurbineComponents%Foundation%TranslationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Foundation%TranslationVel(i1) - u2%TurbineComponents%Foundation%TranslationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Foundation%TranslationVel(i1) + u3%TurbineComponents%Foundation%TranslationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Foundation%TranslationVel(i1) + t(3)*u2%TurbineComponents%Foundation%TranslationVel(i1) - t(2)*u3%TurbineComponents%Foundation%TranslationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Foundation%TranslationVel(i1) = u1%TurbineComponents%Foundation%TranslationVel(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%TurbineComponents%Foundation%RotationVel,1),UBOUND(u_out%TurbineComponents%Foundation%RotationVel,1) + b = (t(3)**2*(u1%TurbineComponents%Foundation%RotationVel(i1) - u2%TurbineComponents%Foundation%RotationVel(i1)) + t(2)**2*(-u1%TurbineComponents%Foundation%RotationVel(i1) + u3%TurbineComponents%Foundation%RotationVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%Foundation%RotationVel(i1) + t(3)*u2%TurbineComponents%Foundation%RotationVel(i1) - t(2)*u3%TurbineComponents%Foundation%RotationVel(i1) ) * scaleFactor + u_out%TurbineComponents%Foundation%RotationVel(i1) = u1%TurbineComponents%Foundation%RotationVel(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%TurbineComponents%BladeLength - u2%TurbineComponents%BladeLength) + t(2)**2*(-u1%TurbineComponents%BladeLength + u3%TurbineComponents%BladeLength))* scaleFactor + c = ( (t(2)-t(3))*u1%TurbineComponents%BladeLength + t(3)*u2%TurbineComponents%BladeLength - t(2)*u3%TurbineComponents%BladeLength ) * scaleFactor + u_out%TurbineComponents%BladeLength = u1%TurbineComponents%BladeLength + b + c * t_out +IF (ALLOCATED(u_out%MulTabLoc) .AND. ALLOCATED(u1%MulTabLoc)) THEN + DO i2 = LBOUND(u_out%MulTabLoc,2),UBOUND(u_out%MulTabLoc,2) + DO i1 = LBOUND(u_out%MulTabLoc,1),UBOUND(u_out%MulTabLoc,1) + b = (t(3)**2*(u1%MulTabLoc(i1,i2) - u2%MulTabLoc(i1,i2)) + t(2)**2*(-u1%MulTabLoc(i1,i2) + u3%MulTabLoc(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%MulTabLoc(i1,i2) + t(3)*u2%MulTabLoc(i1,i2) - t(2)*u3%MulTabLoc(i1,i2) ) * scaleFactor + u_out%MulTabLoc(i1,i2) = u1%MulTabLoc(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%InflowVelocity) .AND. ALLOCATED(u1%InflowVelocity)) THEN + DO i2 = LBOUND(u_out%InflowVelocity,2),UBOUND(u_out%InflowVelocity,2) + DO i1 = LBOUND(u_out%InflowVelocity,1),UBOUND(u_out%InflowVelocity,1) + b = (t(3)**2*(u1%InflowVelocity(i1,i2) - u2%InflowVelocity(i1,i2)) + t(2)**2*(-u1%InflowVelocity(i1,i2) + u3%InflowVelocity(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%InflowVelocity(i1,i2) + t(3)*u2%InflowVelocity(i1,i2) - t(2)*u3%InflowVelocity(i1,i2) ) * scaleFactor + u_out%InflowVelocity(i1,i2) = u1%InflowVelocity(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + DO i1 = LBOUND(u_out%AvgInfVel,1),UBOUND(u_out%AvgInfVel,1) + b = (t(3)**2*(u1%AvgInfVel(i1) - u2%AvgInfVel(i1)) + t(2)**2*(-u1%AvgInfVel(i1) + u3%AvgInfVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%AvgInfVel(i1) + t(3)*u2%AvgInfVel(i1) - t(2)*u3%AvgInfVel(i1) ) * scaleFactor + u_out%AvgInfVel(i1) = u1%AvgInfVel(i1) + b + c * t_out + END DO + END SUBROUTINE AD14_Input_ExtrapInterp2 + + + SUBROUTINE AD14_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(AD14_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(AD14_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL AD14_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL AD14_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL AD14_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE AD14_Output_ExtrapInterp + + + SUBROUTINE AD14_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(AD14_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(AD14_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(AD14_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%OutputLoads) .AND. ALLOCATED(y1%OutputLoads)) THEN + DO i1 = LBOUND(y_out%OutputLoads,1),UBOUND(y_out%OutputLoads,1) + CALL MeshExtrapInterp1(y1%OutputLoads(i1), y2%OutputLoads(i1), tin, y_out%OutputLoads(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp1(y1%Twr_OutputLoads, y2%Twr_OutputLoads, tin, y_out%Twr_OutputLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE AD14_Output_ExtrapInterp1 + + + SUBROUTINE AD14_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(AD14_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(AD14_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(AD14_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(AD14_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'AD14_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%OutputLoads) .AND. ALLOCATED(y1%OutputLoads)) THEN + DO i1 = LBOUND(y_out%OutputLoads,1),UBOUND(y_out%OutputLoads,1) + CALL MeshExtrapInterp2(y1%OutputLoads(i1), y2%OutputLoads(i1), y3%OutputLoads(i1), tin, y_out%OutputLoads(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp2(y1%Twr_OutputLoads, y2%Twr_OutputLoads, y3%Twr_OutputLoads, tin, y_out%Twr_OutputLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE AD14_Output_ExtrapInterp2 + +END MODULE AeroDyn14_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn14/src/AeroSubs.f90 b/OpenFAST/modules/aerodyn14/src/AeroSubs.f90 new file mode 100644 index 000000000..3ca457193 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/AeroSubs.f90 @@ -0,0 +1,5531 @@ +!********************************************************************************************************************************** +MODULE AeroSubs + + USE NWTC_Library + USE AeroDyn14_Types + + USE AeroGenSubs, ONLY : MaxInfl + + + IMPLICIT NONE + + + INTEGER(IntKi) , PARAMETER, DIMENSION(1:6) :: MRvector = (/ 0, 0, 1, 1, 2, 3 /) !bjj why aren't these parameters? Now they are. + INTEGER(IntKi) , PARAMETER, DIMENSION(1:6) :: NJVector = (/ 1, 3, 2, 4, 3, 4 /) + + +CONTAINS +! ************************************************ +! AeroDyn Subroutines for YawDyn, ADAMS, +! SymDyn and FAST. +! ************************************************ +! UNIVERSITY OF UTAH, MECHANICAL ENGINEERING DEPARTMENT + + +! Updated version that uses FAST Interface types +!==================================================================================================== +SUBROUTINE AD14_GetInput(InitInp, P, x, xd, z, m, y, ErrStat, ErrMess ) +!==================================================================================================== + USE AeroGenSubs, ONLY: AllocArrays + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInp + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Initial misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + ! Local Variables: + + INTEGER :: ElIndex + INTEGER :: IELM + INTEGER :: IndPrint + INTEGER :: K + INTEGER :: UnIn + INTEGER :: ErrStatLcl + + LOGICAL :: PremEOF_indicator + CHARACTER(1024) :: LINE + CHARACTER(1024) :: FilePath ! The path name of the AeroDyn input file (so files listed in it can be defined relative to the main input file location) + CHARACTER(ErrMsgLen) :: ErrMessLcl + character(*), parameter :: RoutineName = 'AD14_GetInput' + + !bjj: error handling here needs to be fixed! (we overwrite any non-AbortErrLev errors) + + ErrStat = ErrID_None + ErrMess = '' + + ! Function definition + + call GetNewUnit(UnIn, ErrStatLcl, ErrMessLcl) + + !------------------------------------------------------------------------------------------------- + ! Open the AeroDyn input file + !------------------------------------------------------------------------------------------------- + CALL OpenFInpFile(UnIn, TRIM(InitInp%ADFileName), ErrStatLcl, ErrMessLcl) + CALL SetErrStat(ErrStatLcl, ErrMessLcl,ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + CALL GetPath( InitInp%ADFileName, FilePath ) + + !------------------------------------------------------------------------------------------------- + ! If the echo file is open, write the header... + !------------------------------------------------------------------------------------------------- + IF ( p%Echo ) THEN + WRITE( p%UnEc, '(// A /)' ) 'AeroDyn input data from file "'//TRIM( InitInp%ADFileName )//'":' + END IF + + !------------------------------------------------------------------------------------------------- + ! Read the AeroDyn input file + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, InitInp%ADFileName, 'Header', ErrStatLcl, ErrMessLcl ) + CALL SetErrStat(ErrStatLcl, ErrMessLcl,ErrStat, ErrMess,RoutineName) + + ! Read in the title line + CALL ReadStr( UnIn, InitInp%ADFileName, InitInp%Title, VarName='Title', VarDescr='File title', ErrStat=ErrStatLcl, ErrMsg=ErrMessLcl) + CALL SetErrStat(ErrStatLcl, ErrMessLcl,ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr( ' Heading of the AeroDyn input file: '//NewLine//' '//TRIM(InitInp%Title) ) + END IF + p%TITLE = InitInp%TITLE + + p%SIunit = .TRUE. + + ! Read in the stall model + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='DStall', VarDescr='Stall model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + CALL Conv2UC(LINE(1:7)) + + SELECT CASE ( TRIM(Line) ) + CASE ('STEADY') + P%DStall = .FALSE. + CASE ('BEDDOES') ! added -- maybe the input format changed? jm + P%DStall = .TRUE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "STEADY" or "BEDDOES" stall model option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + + + ! Read in the CM option + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='PMoment', VarDescr='Pitching moment option', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + CALL Conv2UC(LINE(1:6)) + + SELECT CASE ( TRIM(Line) ) + CASE ('USE_CM') + P%PMoment = .TRUE. + CASE ('NO_CM') + P%PMoment = .FALSE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "USE_CM" or "NO_CM" pitching moment option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + + + ! Read in the inflow model option + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='DynInfl', VarDescr='Inflow model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + CALL Conv2UC(LINE(1:7)) + + SELECT CASE ( Line(1:5) ) + CASE ('EQUIL') + P%DynInfl = .FALSE. + m%DynInit = .FALSE. + + IF (Line(6:7) == 'DA') THEN + P%Inducedvel%EqAIDmult = 1.0 + P%Inducedvel%EquilDA = .TRUE. + P%Inducedvel%EquilDT = .FALSE. + ELSEIF (LINE(6:7) == 'DB') THEN + P%Inducedvel%EqAIDmult = 1.0 + P%Inducedvel%EquilDA = .TRUE. + P%Inducedvel%EquilDT = .TRUE. + ELSEIF (LINE(6:7) == 'DT') THEN + P%Inducedvel%EqAIDmult = 0.0 + P%Inducedvel%EquilDA = .FALSE. + P%Inducedvel%EquilDT = .TRUE. + ELSE + P%Inducedvel%EqAIDmult = 0.0 + P%Inducedvel%EquilDA = .FALSE. + P%Inducedvel%EquilDT = .FALSE. + ENDIF + + CASE ('DYNIN') + P%DynInfl = .TRUE. + m%DynInit = .TRUE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "EQUIL" or "DYNIN" inflow model option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + + + ! Read in the wake model + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='Wake', VarDescr='Wake model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + CALL Conv2UC(LINE(1:5)) + + SELECT CASE ( TRIM(Line) ) + CASE ('NONE') + P%Wake = .FALSE. + P%Swirl = .FALSE. + + CALL ProgWarn( ' All wake calculations are turned off! This option is recommended only '// & + 'in high winds or for debugging.' ) + CASE ('WAKE') + P%Wake = .TRUE. + P%Swirl = .FALSE. + CASE ('SWIRL') + P%Wake = .TRUE. + P%Swirl = .TRUE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "NONE", "WAKE", or "SWIRL" wake model option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + + ! Read in the tolerance for the wake model + CALL ReadVar( UnIn, InitInp%ADFileName, P%Inducedvel%AToler, VarName='AToler', VarDescr='Induction factor tolerance', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Read in the tip-loss model for EQUIL inflow + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='TLoss', VarDescr='Tip-loss model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + IF ( P%DynInfl ) THEN ! Initialize these variables, though they shouldn't be used + P%Inducedvel%TLoss = .FALSE. + P%Inducedvel%GTech = .FALSE. + ELSE + CALL Conv2UC(LINE(1:5)) + + SELECT CASE ( LINE(1:5) ) + CASE ('NONE ') + P%Inducedvel%TLoss = .FALSE. + P%Inducedvel%GTech = .FALSE. + CASE ('PRAND') + P%Inducedvel%TLoss = .TRUE. + P%Inducedvel%GTech = .FALSE. + CASE ('GTECH') + P%Inducedvel%TLoss = .TRUE. + P%Inducedvel%GTech = .TRUE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "NONE", "PRAND", or "GTECH" tip-loss model option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + END IF + + + ! Read in the hub-loss model for EQUIL inflow + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='HLoss', VarDescr='Hub-loss model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( P%DynInfl ) THEN ! Initialize these variables, though they shouldn't be used + P%Inducedvel%HLoss = .FALSE. + ELSE + CALL Conv2UC( LINE(1:5) ) + + SELECT CASE ( LINE(1:5) ) + CASE ('NONE') + P%Inducedvel%HLoss = .FALSE. + CASE ('PRAND') + P%Inducedvel%HLoss = .TRUE. + CASE DEFAULT + CALL ProgWarn( ' Error: Expecting "NONE" or "PRAND" hub-loss model option.') + ErrStat = ErrID_Fatal + CLOSE(UnIn) + RETURN + END SELECT + END IF + + p%Rotor%HH = InitInp%HubHt + +!bjj: this is a hack job to allow both the new tower influence and the old tower wake models to be used +! CALL ReadStr( UnIn, InitInp%ADFileName, LINE, VarName='NewTowerModel?', VarDescr='Check for tower influence model', ErrStat=ErrStat ) + CALL ReadVar( UnIn, InitInp%ADFileName, LINE, VarName='NewTowerModel?', VarDescr='Check for tower influence model', ErrStat=ErrStat, ErrMsg=ErrMess ) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Check if this is the "special string" to indicate the new tower influence model + CALL Conv2UC( Line ) + IF ( INDEX(Line, "NEWTOWER" ) > 0 ) THEN + + !---------------------------------------------------------------------------------------------- + ! New tower influence model, as implemented by PJM + !---------------------------------------------------------------------------------------------- + P%TwrProps%PJM_Version = .TRUE. + + ! Read in the tower potential flow switch + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%TwrPotent, VarName='TwrPotent', VarDescr='Tower influence model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Read in the tower shadow switch + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%TwrShadow, VarName='TwrShadow', VarDescr='Tower shadow model', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Read in the tower drag file name + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%TwrFile, VarName='TwrFile', VarDescr='Tower data file name', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + IF ( PathIsRelative( P%TwrProps%TwrFile ) ) P%TwrProps%TwrFile = TRIM(FilePath)//TRIM(P%TwrProps%TwrFile) + + ! Read in the flag to tell AeroDyn to compute tower aerodynamics. + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%CalcTwrAero, VarName='CalcTwrAero', VarDescr='Flag to calculate tower aerodynamics', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ELSE + !---------------------------------------------------------------------------------------------- + ! Old tower influence model, read TwrShad from Line for now + !---------------------------------------------------------------------------------------------- + P%TwrProps%PJM_Version = .FALSE. + + P%TwrProps%TwrPotent = .FALSE. ! We don't want to read the tower file! + P%TwrProps%TwrShadow = .FALSE. ! We don't want to read the tower file! + P%TwrProps%CalcTwrAero = .FALSE. ! We don't want to read the tower file! + + ! Read in the tower shadow deficit + IF ( INDEX( 'FTft', Line(:1) ) > 0 ) THEN + CALL ProgWarn( ' Invalid numeric input. "'//TRIM( Line )//'" found when trying to read TwrShad.' ) + close(unin) + ErrStat = ErrID_Fatal + RETURN + ELSE + READ (Line,*,IOSTAT=ErrStat) P%TwrProps%TwrShad + CALL CheckIOS ( ErrStat, InitInp%ADFileName, 'TwrShad', NumType, ErrStat, ErrMess ) +!bjj: is this aborting? + IF ( p%Echo ) THEN + WRITE (p%UnEc,"( 2X, ES11.4e2, 2X, A, T30, ' - ', A )") P%TwrProps%TwrShad, "TwrShad", 'Tower shadow deficit' + END IF + + END IF +!---------------- + + IF ( P%TwrProps%TwrShad >= 1.0 ) THEN + CALL ProgWarn( ' Tower shadow deficit cannot be >= 1. Setting default deficit = 0.3' ) + P%TwrProps%TwrShad = 0.3 + END IF + + + ! Read in the tower shadow width + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%ShadHWid, VarName='ShadHWid', VarDescr='Tower shadow half width', ErrStat=ErrStat, ErrMsg=ErrMess) + IF ( ErrStat /= ErrID_None ) RETURN + + IF ( P%TwrProps%ShadHWid <= 0.0 ) THEN + CALL ProgWarn( ' Tower shadow width cannot be <= zero. Setting default half width = 1.0' ) + P%TwrProps%ShadHWid = 1.0 + END IF + + + ! Read in the tower shadow reference point (distance from yaw axis to hub) + CALL ReadVar( UnIn, InitInp%ADFileName, P%TwrProps%T_Shad_Refpt, VarName='T_Shad_Refpt', VarDescr='Tower shadow reference point', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Constants used in tower shadow calculations + P%TwrProps%TShadC1 = P%TwrProps%ShadHWid / SQRT ( ABS( P%TwrProps%T_Shad_Refpt ) ) + P%TwrProps%TShadC2 = P%TwrProps%TwrShad * SQRT ( ABS( P%TwrProps%T_Shad_Refpt ) ) + + END IF + + ! Read in the air density + CALL ReadVar( UnIn, InitInp%ADFileName, P%Wind%Rho, VarName='Rho', VarDescr='Air density', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + !bjj do we need to check the the air density is non-negative? + + IF ( P%Wind%Rho == 0.0 .AND. P%DynInfl ) THEN ! Turn off the GDW if RHO = 0. It will crash + CALL ProgWarn( 'Air density is zero. Dynamic Inflow will be turned off to avoid program crash.' ) + P%DynInfl = .FALSE. + ENDIF + + ! Read in the kinematic viscosity + CALL ReadVar( UnIn, InitInp%ADFileName, P%Wind%KinVisc, 'KinVisc', 'Kinematic viscosity', ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + ! Aero calculation time interval + CALL ReadVar( UnIn, InitInp%ADFileName, Line, 'DtAero', 'Aero calculation time step', ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in P%DtAero + READ( Line, *, IOSTAT=ErrStatLcl) P%DtAero + IF ( ErrStatLcl /= 0 ) THEN + CALL CheckIOS ( ErrStatLcl, InitInp%ADFileName, "DT", NumType, ErrStat, ErrMess ) + RETURN + ELSE + ErrStat = ErrID_None + END IF + END IF + + + ! Read the number of airfoil files + CALL ReadVar( UnIn, InitInp%ADFileName, P%AirFoil%NumFoil, 'NumFoil', 'Number of airfoil files', ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + IF ( P%AirFoil%NumFoil < 1 ) THEN + CALL ProgWarn( ' Error: Number of airfoil files must be a positive integer.') + ErrStat = ErrID_Fatal + close(unin) + RETURN + END IF + + !.............................................................................................. + ! Allocate space for the airfoil data file name(s), then read them + !.............................................................................................. + IF (.NOT. ALLOCATED(P%AirFoil%FoilNm)) THEN + ALLOCATE ( P%AirFoil%FoilNm( P%AirFoil%NumFoil ) , STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL ProgWarn(' Error allocating space for the FoilNm array.') + close(unin) + RETURN + END IF + END IF + + CALL ReadAryLines( UnIn, InitInp%ADFileName, P%AirFoil%FoilNm, P%AirFoil%NumFoil, AryName='FoilNm', AryDescr='Airfoil file names', ErrStat=ErrStat, ErrMsg=ErrMess ) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + DO K=1,P%AirFoil%NumFoil + IF ( PathIsRelative( P%AirFoil%FoilNm(K) ) ) P%AirFoil%FoilNm(K) = TRIM(FilePath)//TRIM( P%AirFoil%FoilNm(K) ) + END DO + + + ! Read in the number of blade elements + CALL ReadVar( UnIn, InitInp%ADFileName, P%Element%NElm, VarName='NElm', VarDescr='Number of blade elements', ErrStat=ErrStat, ErrMsg=ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + + !.............................................................................................. + ! Allocate space for blade element data and read the arrays + ! Read blade element data, check some inputs, convert twist to radians + !.............................................................................................. + CALL AllocArrays (InitInp, P, x, xd, z, m, y, 'Element') + + m%ElOut%NumElOut = 0 ! Initialize the element print array index + m%ElOut%NumWndElOut = 0 + + CALL ReadCom( UnIn, InitInp%ADFileName, 'Element table headers', ErrStat, ErrMess) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(UnIn) + RETURN + END IF + + DO IElm = 1, p%Element%NElm + + READ(UnIn,'(A)',IOSTAT=ErrStat) Line !read into a line to see if print/no print is enabled + + IF (ErrStat == 0) THEN + READ(Line,*,IOSTAT=ErrStat) P%Element%RElm(IElm), P%Element%Twist(IElm), P%Blade%DR(IElm), P%Blade%C(IElm), P%AirFoil%NFoil(IElm) + END IF + + IF ( ErrStat == 0 ) THEN + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! Check if AeroDyn will print out the element and/or wind data + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + CALL Conv2UC(LINE) + + m%ElOut%ElPrList(IElm) = 0 ! INITIALIZE + IndPrint = INDEX(LINE,"PRINT") + IF (IndPrint > 0) THEN + IF (LINE(IndPrint-2:IndPrint+4) /= "NOPRINT") THEN + m%ElOut%NumElOut = m%ElOut%NumElOut + 1 + m%ElOut%ElPrList(IElm) = m%ElOut%NumElOut + END IF + ENDIF + + + m%ElOut%WndElPrList(IElm) = 0 ! INITIALIZE + IndPrint = INDEX(LINE,"WIND") + IF (IndPrint > 0) THEN + IF (LINE(IndPrint-2:IndPrint-1) /= "NO") THEN + m%ElOut%NumWndElOut = m%ElOut%NumWndElOut + 1 + m%ElOut%WndElPrList(IElm) = m%ElOut%NumWndElOut + END IF + ENDIF + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! Echo data to the file NWTC_Library echo file, if requested + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + IF ( p%Echo ) THEN ! NWTC_Library echo file + WRITE (p%UnEc,'(4(2X,ES11.4e2),2X,I11,1(2X,L11))') P%Element%RElm(IElm), P%Element%Twist(IElm), P%Blade%DR(IElm), P%Blade%C(IElm), P%AirFoil%NFoil(IElm), & + m%ElOut%ElPrList(IElm) /= 0 !, m%ElOut%WndElPrList(IElm) == 0 + END IF + + ELSE IF ( ErrStat < 0 ) THEN + + CALL ProgWarn( ' Premature end of file while reading line '//TRIM(Int2Lstr(IElm))// & + ' of the AeroDyn element table in file "'//TRIM(InitInp%ADFileName)//'."' ) + close(unin) + ErrStat = ErrID_Fatal + ErrMess = 'Error reading from line '//TRIM(Int2Lstr(IElm))//' of the AeroDyn element table.' + RETURN + ELSE + close(unin) + ErrStat = ErrID_Fatal + ErrMess = 'Error reading from line '//TRIM(Int2Lstr(IElm))// & + ' of the AeroDyn element table in file "'//TRIM(InitInp%ADFileName)//'."' + RETURN + END IF + + + ! Check for valid data: + + IF( P%Blade%C(IElm) <= 0.0 ) THEN + CALL ProgWarn(' Error reading from line '//TRIM(Int2Lstr(IElm))//' of the AeroDyn element table.'// & + ' Chord length must be larger than 0.' ) + ErrStat = ErrID_Fatal + close(unin) + RETURN + ENDIF + + IF (p%AirFoil%NFoil(IElm) < 1 .OR. p%AirFoil%NFoil(IElm) > p%AirFoil%NumFoil) THEN + CALL ProgWarn(' Error reading from line '//TRIM(Int2Lstr(IElm))//' of the AeroDyn element table.'// & + ' Airfoil file ID must be a number between 1 and '//TRIM(Int2Lstr(p%AirFoil%NumFoil))//'.' ) + ErrStat = ErrID_Fatal + close(unin) + RETURN + END IF + + ! Convert Twist to radians: + + P%Element%Twist(IElm) = P%Element%Twist(IElm)*D2R + + ENDDO ! IELM + + + !.............................................................................................. + ! Read multiple airfoil table option + !.............................................................................................. + + PremEOF_indicator = .FALSE. + READ(UnIn,*,IOSTAT=ErrStatLcl) Line !read MultiTab -- it may not exist + IF (ErrStatLcl > 0 ) THEN + CALL WrScr1 ( ' Invalid character input for file "'//TRIM( InitInp%ADFileName )//'".' ) + CALL ProgWarn ( ' The error occurred while trying to read "MultiTab".' ) + ErrStat=ErrID_Fatal + close(unin) + RETURN + ELSE IF (ErrStatLcl == 0) THEN + IF ( p%Echo ) THEN + WRITE (p%UnEc, "( 15X, A, T30, ' - ', A, /, 2X, A )" ) & + 'MultiTab', 'Multiple airfoil table option', '"'//TRIM( Line )//'"' + END IF + ELSE + p%MultiTab = .FALSE. + p%Reynolds = .FALSE. + PremEOF_indicator = .TRUE. + ! CALL PremEOF ( TRIM( Fil ), Variable, TrapThisError ) + END IF + + !------------------------------------------------------------------------------------------------- + ! Close AeroDyn input file + !------------------------------------------------------------------------------------------------- + CLOSE(UnIn) + + !------------------------------------------------------------------------------------------------- + ! Read airfoil data and check for MultiTab values using LINE, which was read above + !------------------------------------------------------------------------------------------------- + CALL READFL(InitInp, P, x, xd, z, m, y, ErrStatLcl, ErrMessLcl) + CALL SetErrStat(ErrStatLcl, ErrMessLcl, ErrStat, ErrMess,'AD_GetInput') + IF ( ErrStat >= AbortErrLev ) THEN + close(unin) + RETURN + END IF + + m%AirFoil%MulTabLoc = 0.0 ! Initialize this value + + + ! Read in the type of airfoil data table in each file + IF ( PremEOF_indicator ) THEN ! If we hit the end of the file without MultiTab, use only 1 airfoil table + IF ( ANY( p%AirFoil%NTables(1:p%AirFoil%NumFoil) > 1 ) ) THEN + CALL ProgWarn( ' Error reading multiple airfoil table option. Only one table for each file will be used.' ) + END IF + p%MultiTab = .FALSE. + p%Reynolds = .FALSE. + ELSE ! not PremEOF_indicator + + IF ( ANY( p%AirFoil%NTables(1:p%AirFoil%NumFoil) > 1 ) ) THEN + CALL Conv2UC(LINE(1:6)) + + SELECT CASE ( TRIM(Line) ) + CASE ( 'USER' ) + p%MultiTab = .TRUE. + p%Reynolds = .FALSE. + + DO K = 1, p%AirFoil%NumFoil + IF ( p%AirFoil%NTables(K) > 1 ) THEN + IF ( ( m%AirFoil%MulTabLoc < p%AirFoil%MulTabMet(K,1) ) .OR. & + ( m%AirFoil%MulTabLoc > p%AirFoil%MulTabMet(K,p%AirFoil%NTables(K) ) ))THEN + CALL ProgWarn( 'Error interpolating between airfoil tables. '// & + ' Initial interpolation value = '//TRIM(Num2LStr(m%AirFoil%MulTabLoc))// & + ' is outside table range of '//TRIM(Num2LStr(p%AirFoil%MulTabMet(K,1)))// & + ' to '//TRIM(Num2LStr(p%AirFoil%MulTabMet(K,p%AirFoil%NTables(K))))// & + ' in airfoil file #'//TRIM(Int2LStr(K))//'.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF ! NTables(K) > 1 + ENDDO ! K + + CASE ( 'RENUM' ) + p%MultiTab = .TRUE. + p%Reynolds = .TRUE. + CASE ( 'SINGLE' ) + p%MultiTab = .FALSE. + p%Reynolds = .FALSE. + CASE DEFAULT + CALL WrScr( ' Error: control model option must be "USER", "RENUM" or "SINGLE".' ) + END SELECT + ELSE + p%MultiTab = .FALSE. + p%Reynolds = .FALSE. + END IF + + ENDIF + + !------------------------------------------------------------------------------------------------- + ! Read tower drag input file, if necessary + !------------------------------------------------------------------------------------------------- + IF (p%TwrProps%TwrPotent .OR. p%TwrProps%TwrShadow .OR. p%TwrProps%CalcTwrAero) THEN ! Read in the tower drag file + CALL READTwr(UnIn, InitInp, P, x, xd, z, m, y, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Initialize variables for printing + !------------------------------------------------------------------------------------------------- + IF ( m%ElOut%NumElOut > 0 .OR. m%ElOut%NumWndElOut > 0 ) THEN + p%ElemPrn = .TRUE. + CALL AllocArrays (InitInp, P, x, xd, z, m, y, 'ElPrint') + + ElIndex = 0 ! Re-Initialize the element print array index for wind + DO IElm = 1, p%Element%NElm + IF (m%ElOut%WndElPrList(IElm) > 0) THEN + ElIndex = ElIndex + 1 + m%ElOut%WndElPrNum(ElIndex) = IElm + END IF + END DO ! IELM + + ElIndex = 0 ! Re-Initialize the element print array index + DO IElm = 1, p%Element%NElm + IF (m%ElOut%ElPrList(IElm) > 0) THEN + ElIndex = ElIndex + 1 + m%ElOut%ElPrNum(ElIndex) = IElm + END IF + END DO ! IELM + ELSE + p%ElemPrn = .FALSE. + END IF + + !------------------------------------------------------------------------------------------------- + ! Initialize Beddoes dynamic stall data + !------------------------------------------------------------------------------------------------- + IF ( p%DStall ) CALL BEDDAT( P, x, xd, z, m, y, ErrStat, ErrMess ) + + + RETURN + +contains + SUBROUTINE CleanUp() + + CLOSE(UnIn) + + END SUBROUTINE CleanUp + +END SUBROUTINE AD14_GetInput +!==================================================================================================== + SUBROUTINE ADOut(InitInp, P, m, AD14_Ver, FileName, ErrStat, ErrMess ) + ! used to output data to a summary file + ! ***************************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_InitInputType), INTENT(IN ) :: InitInp + TYPE(AD14_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(IN ) :: m ! Misc/optimization variables + TYPE(ProgDesc), INTENT(IN ) :: AD14_ver + INTEGER, INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + CHARACTER(*), INTENT(IN ) :: FileName + + + + ! Local Variables: + + INTEGER :: IElm + INTEGER :: IFoil + INTEGER :: UnOut + INTEGER :: I,K + INTEGER(IntKi) :: ErrStatLcl + + CHARACTER( 2) :: Dst_Unit + CHARACTER(150) :: Frmt + CHARACTER( 4) :: Mass_Unit + CHARACTER( 35) :: MESAGE + CHARACTER( 3) :: Vel_Unit + + CHARACTER(1),PARAMETER :: Delim = ' ' ! bjj: made this a parameter because I don't think tabs work very well in a summary file + CHARACTER(ErrMsgLen) :: ErrMessLcl + + + ErrStat = ErrID_None + ErrMess = "" + + ! Function definition + + CALL GetNewUnit( UnOut, ErrStat, ErrMess ) + CALL OpenFOutFile( UnOut, FileName, ErrStatLcl, ErrMessLcl) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,'ADOut' ) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE(UnOut) + RETURN + END IF + + + WRITE (UnOut,"(/A)") 'This file was generated by '//TRIM(GetNVD(AD14_Ver))//& + ' on '//CurDate()//' at '//CurTime()//'.' + + +IF (p%SIUNIT) THEN + Dst_Unit = 'm' + Mass_Unit = 'kg' + Vel_Unit = 'mps' +ELSE + Dst_Unit = 'ft' + Mass_Unit = 'slug' + Vel_Unit = 'fps' +ENDIF + + ! Reiterate the input file +WRITE(UnOut,'(/A)') 'Inputs read in from the AeroDyn input file:' +WRITE(UnOut,'(A/)') TRIM(p%TITLE) + +! Ec_Ch11Frmt is a parameter defined for echo output in the NWTC Subroutine Library +MESAGE = 'Units for input and output' +IF ( p%SIUNIT ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'SI','SysUnits',MESAGE +ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'ENGLISH','SysUnits',MESAGE +ENDIF + +MESAGE = 'Dynamic stall model' +IF ( p%DSTALL ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'BEDDOES',"StallMod", MESAGE//' [Beddoes]' +ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'STEADY',"StallMod", MESAGE//' [NO Dynamic stall]' +ENDIF + +MESAGE = 'Aerodynamic pitching moment model' +IF ( p%PMOMENT ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'USE_CM','UseCm',MESAGE//' [Pitching Moments calculated]' +ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'NO_CM','UseCm',MESAGE//' [NO Pitching Moments calculated]' +ENDIF + +MESAGE = 'Inflow model' +IF ( p%DYNINFL ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'DYNIN','InfModel',MESAGE//' [Dynamic Inflow]' +ELSE + IF ( p%InducedVel%EquilDA .AND. p%InducedVel%EquilDT ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'EQUILDB','InfModel',MESAGE//' [Equilibrium w/ axial and tangential drag]' + ELSEIF ( p%InducedVel%EquilDA ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'EQUILDA','InfModel',MESAGE//' [Equilibrium w/ axial drag]' + ELSEIF ( p%InducedVel%EquilDT ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'EQUILDT','InfModel',MESAGE//' [Equilibrium w/ tangential drag]' + ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'EQUIL','InfModel',MESAGE//' [Equilibrium]' + ENDIF +ENDIF + + +MESAGE = 'Induction factor model' +IF ( p%WAKE ) THEN + IF (p%SWIRL) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'SWIRL','IndModel',MESAGE//' [Normal and Radial flow induction factors calculated]' + ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'WAKE','IndModel',MESAGE//' [Normal flow induction factors calculated]' + ENDIF + WRITE(UnOut,Ec_ReFrmt) p%InducedVel%ATOLER,'AToler','Convergence tolerance for induction factor' +ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'NONE','IndModel',MESAGE//' [NO induction factors calculated]' + WRITE(UnOut,Ec_Ch11Frmt) '[Not Used]','AToler','Convergence tolerance for induction factor' +ENDIF + +MESAGE = 'Tip-loss model' +IF (.NOT. p%DYNINFL) THEN + IF ( p%InducedVel%TLOSS ) THEN + IF (p%InducedVel%GTECH) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'GTECH','TLModel',MESAGE//' [Georgia Tech correction to Prandtl model]' + ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'PRAND','TLModel',MESAGE//' [Prandtl model]' + ENDIF + ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'NONE','TLModel',MESAGE//' [NO tip-loss calculated]' + ENDIF +ELSE + WRITE(UnOut,Ec_Ch11Frmt) '[Not Used]','TLModel',MESAGE +ENDIF + +MESAGE = 'Hub-loss model' +IF (.NOT. p%DYNINFL) THEN + IF ( p%InducedVel%HLOSS ) THEN + WRITE(UnOut,Ec_Ch11Frmt) 'PRAND','HLModel',MESAGE//' [Prandtl model]' + ELSE + WRITE(UnOut,Ec_Ch11Frmt) 'NONE','HLModel',MESAGE//' [NO hub-loss calculated]' + ENDIF +ELSE + WRITE(UnOut,Ec_Ch11Frmt) '[Not Used]','HLModel',MESAGE +ENDIF + + +WRITE(UnOut,Ec_ReFrmt) p%Rotor%HH,'HH','Wind reference (hub) height, '//TRIM(Dst_Unit) + +IF ( p%TwrProps%PJM_Version ) THEN + WRITE(UnOut,Ec_LgFrmt) p%TwrProps%TwrPotent,'TwrPotent','Calculate tower potential flow [T or F]' + WRITE(UnOut,Ec_LgFrmt) p%TwrProps%TwrShadow,'TwrShadow','Calculate tower shadow [T or F]' + IF ( p%TwrProps%TwrPotent .OR. p%TwrProps%TwrShadow ) THEN + WRITE(UnOut,Ec_StrFrmt) 'TwrFile','Tower drag file name',TRIM(P%TwrProps%TwrFile) + ELSE + WRITE(UnOut,Ec_Ch11Frmt) '[none]','TwrFile','No tower drag properties file' + ENDIF +ELSE + WRITE(UnOut,Ec_ReFrmt) p%TwrProps%TwrShad,'TwrShad','Tower shadow centerline velocity deficit' + WRITE(UnOut,Ec_ReFrmt) p%TwrProps%ShadHWid,'ShadHWid','Tower shadow half width, '//TRIM(Dst_Unit) + WRITE(UnOut,Ec_ReFrmt) p%TwrProps%T_Shad_Refpt,'T_Shad_Refpt','Tower shadow reference point, '//TRIM(Dst_Unit) +END IF + + +WRITE(UnOut,Ec_ReFrmt) p%Wind%RHO,'AirDens','Air density, '//TRIM(Mass_Unit)//'/'//TRIM(Dst_Unit)//'^3' +WRITE(UnOut,Ec_ReFrmt) p%Wind%KinVisc,'KinVisc','Kinematic air viscosity, '//TRIM(Dst_Unit)//'^2/sec' +WRITE(UnOut,Ec_ReFrmt) p%DTAERO,'DTAERO','Time interval for aerodynamic calculations, sec' +WRITE(UnOut,Ec_IntFrmt) p%AirFoil%NUMFOIL,'NumFoil','Number of airfoil files used. Files listed below:' + +DO IFoil = 1, p%AirFoil%NUMFOIL + WRITE(UnOut,'(A)') '"'//TRIM(p%AirFoil%FOILNM(IFoil))//'"' +END DO ! IFoil + +WRITE(UnOut,Ec_IntFrmt) p%Element%NELM,'BldNodes','Number of blade elements per blade' + + !------------------------------------------------------------------------------------------------- + ! write out element information + !------------------------------------------------------------------------------------------------- + Frmt = '(3X,A10,8("'//Delim//'",A10))' + + WRITE(UnOut,'( )') + + ! column names + + WRITE(UnOut,Frmt) ' Element ', & + ' RELM ', & + ' Twist ', & + ' DR ', & + ' Chord ', & + ' NFoil ', & + ' Print? ', & + ' Tip-loss ', & + ' Hub-loss ' + + ! column units + + WRITE(UnOut,Frmt) ' (-) ', & + ' (m) ', & + ' (deg) ', & + ' (m) ', & + ' (m) ', & + ' (-) ', & + ' (Yes/No) ', & + ' constant ', & + ' constant ' + + WRITE(UnOut,Frmt) '----------', & + '----------', & + '----------', & + '----------', & + '----------', & + '----------', & + '----------', & + '----------', & + '----------' + + ! column data + Frmt = '(3X, I10, 4("'//Delim//'",F10.5),"'//Delim//'",I10,"'//Delim//'",A10, 2("'//Delim//'",F10.5) )' + + DO IElm = 1, p%Element%NELM + + IF (m%ElOut%ElPrList(IElm) /= 0) THEN + MESAGE = 'Yes' + ELSE + MESAGE = 'No' + ENDIF + + WRITE(UnOut, Frmt) IElm, p%Element%RELM(IElm), p%Element%TWIST(IElm)*R2D, p%Blade%DR(IElm), p%Blade%C(IElm), & + p%AirFoil%NFOIL(IElm), TRIM(Mesage), p%Element%TLCNST(IElm), p%Element%HLCNST(IElm) + END DO + + +IF ( p%MultiTab ) THEN + WRITE(UnOut,'(A)') 'MULTI Multiple airfoil tables used' +ELSE + WRITE(UnOut,'( )') +ENDIF + + WRITE(UnOut,"(/' Rotor radius = ',F7.3,' m')") p%Blade%R + WRITE(UnOut,"( ' Hub radius = ',F7.3,' m')") p%HubRad + WRITE(UnOut,"( ' Number of blades = ',I3 )") p%NumBl + +IF ( p%DSTALL ) THEN + Frmt = '(3X,A, 21(:F8.4,3X) )' + DO K = 1, P%AirFoil%NTables(1) + WRITE(UnOut,'(/A/)') ' BEDDOES DYNAMIC STALL PARAMETERS:' + WRITE(UnOut, Frmt) 'CN SLOPE ', ( m%Beddoes%CNA(I,K), I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut, Frmt) 'STALL CN (UPPER) ', ( m%Beddoes%CNS(I,K), I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut, Frmt) 'STALL CN (LOWER) ', ( m%Beddoes%CNSL(I,K), I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut, Frmt) 'ZERO LIFT AOA ', ( m%Beddoes%AOL(I,K)*R2D, I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut, Frmt) 'MIN DRAG AOA ', ( m%Beddoes%AOD(I,K)*R2D, I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut, Frmt) 'MIN DRAG COEFF ', ( m%Beddoes%CDO(I,K), I = 1, P%AirFoil%NUMFOIL ) + WRITE(UnOut,'(/)') + ENDDO !K + + WRITE(UnOut,*) ' VORTEX TRANSIT TIME FROM LE TO TE ', P%Beddoes%TVL + WRITE(UnOut,*) ' PRESSURE TIME CONSTANT ', P%Beddoes%TP + WRITE(UnOut,*) ' VORTEX TIME CONSTANT ', P%Beddoes%TV + WRITE(UnOut,*) ' F-PARAMETER TIME CONSTANT ', P%Beddoes%TF +END IF + +IF ( p%ELEMPRN ) WRITE(UnOut,'(/A/)')'Blade element aerodynamic time series data written to file.' + +CLOSE (UnOut ) + +RETURN +END SUBROUTINE ADOut + + ! **************************************************** + SUBROUTINE READFL(InitInp, P, x, xd, z, m, y, ErrStat, ErrMess ) + ! Reads a data file containing airfoil angle of attack, + ! CL and CD, and dynamic stall parameters + ! **************************************************** +!==================================================================================================== + USE AeroGenSubs, ONLY: AllocArrays + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInp + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + ! Local Variables: + +REAL(ReKi), ALLOCATABLE :: CDNegPI(:) +REAL(ReKi), ALLOCATABLE :: CDPosPI(:) +REAL(ReKi), ALLOCATABLE :: CLNegPI(:) +REAL(ReKi), ALLOCATABLE :: CLPosPI(:) +REAL(ReKi), ALLOCATABLE :: CMNegPI(:) +REAL(ReKi), ALLOCATABLE :: CMPosPI(:) + +INTEGER :: IPHI +INTEGER :: I +INTEGER :: K +INTEGER :: Sttus +INTEGER :: NFOILID +INTEGER :: NumLines +INTEGER :: NUNIT +INTEGER :: IOS + +LOGICAL :: ALPosPI +LOGICAL :: ALNegPI + +CHARACTER( 40) :: TITLE (2) +CHARACTER(1024) :: LINE + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + + + ErrStat = ErrID_None + ErrMess = "" + + CALL GetNewUnit(NUNIT, ErrStat, ErrMess) + p%AirFoil%NumCL = 0 + + ! The first loop checks existence and file length to set NumCL +DO NFOILID = 1, p%AirFoil%NUMFOIL + + ! Open the file for reading # of lines + CALL OpenFInpFile (NUNIT, TRIM(p%AirFoil%FOILNM(NFOILID)), ErrStatLcL, ErrMessLcl) + CALL SetErrStat( ErrStatLcL, ErrMessLcl, ErrStat, ErrMess, 'READFL') + IF (ErrStat >= AbortErrLev) THEN + CLOSE(NUNIT) + RETURN + END IF + + ! Determine the maximum number of aerodata points in all files + + NumLines = 0 + IOS = 0 + DO WHILE (IOS == 0) + READ ( NUNIT, '()', IOSTAT=IOS ) + NumLines = NumLines + 1 + END DO + + p%AirFoil%NumCL = MAX(NumLines - 14, p%AirFoil%NumCL) + + CLOSE (NUNIT) + +END DO ! NFOILID + + ! Allocate the arrays + +CALL AllocArrays (InitInp, P, x, xd, z, m, y, 'Aerodata') + !CALL SetErrStat( ErrStatLcL, ErrMessLcl, ErrStat, ErrMess, 'READFL') + !IF (ErrStat >= AbortErrLev) RETURN + + ! The second loop reads the files +DO NFOILID = 1, p%AirFoil%NUMFOIL + + ! Open the file for reading inputs + CALL OpenFInpFile (NUNIT, TRIM(Adjustl(p%AirFoil%FOILNM(NFOILID))), ErrStatLcL, ErrMessLcl ) + CALL SetErrStat( ErrStatLcL, ErrMessLcl, ErrStat, ErrMess, 'READFL') + IF (ErrStat >= AbortErrLev) THEN + CLOSE(NUNIT) + RETURN + END IF + + ! Set up the file to read the aerodata + READ(NUNIT,'( A )',IOSTAT=IOS) TITLE(1) + READ(NUNIT,'( A )',IOSTAT=IOS) TITLE(2) + + ! Read in airfoil table dimension parameters: + ! NTables = number of airfoil data tables + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , '# of tables', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + END IF + + + READ(LINE,*,ERR=205) p%AirFoil%NTables( NFOILID ) + + ! Allocate local arrays with NTables dimension + + Sttus = 0 + IF (.NOT. ALLOCATED(CLPosPI)) THEN + ALLOCATE ( CLPosPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CLPosPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + + IF (.NOT. ALLOCATED(CDPosPI)) THEN + ALLOCATE ( CDPosPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CDPosPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + IF (.NOT. ALLOCATED(CMPosPI)) THEN + ALLOCATE ( CMPosPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CMPosPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + IF (.NOT. ALLOCATED(CLNegPI)) THEN + ALLOCATE ( CLNegPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CLNegPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + IF (.NOT. ALLOCATED(CDNegPI)) THEN + ALLOCATE ( CDNegPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CDNegPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + IF (.NOT. ALLOCATED(CMNegPI)) THEN + ALLOCATE ( CMNegPI(P%AirFoil%NTables(NFOILID)) , STAT=Sttus ) + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error allocating memory for CMNegPI array.', ErrStat, ErrMess, 'READFL' ) + close(NUNIT) + RETURN + END IF + END IF + + + ! Read in airfoil data table identification array + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) then + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'multi-table metric', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + READ(LINE,*,ERR=205) (p%AirFoil%MulTabMet ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + ! Read in four lines that are no longer used + ! These are retained for future USE and backwards compatibility only + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) then + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , '5th line', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) then + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , '6th line', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) then + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , '7th line', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) then + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , '8th line', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + + ! Read Beddoes stall parameters + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'Angle of zero lift (AOL)', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%AOL( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'CNA', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%CNA ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'CNS', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%CNS ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'CNSL', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%CNSL ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'AOD', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%AOD ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + READ(NUNIT,'( A )',IOSTAT=IOS) LINE + IF ( IOS < 0 ) THEN + CALL PremEOF ( Trim(p%AirFoil%FOILNM(NFOILID)) , 'CDO', .TRUE., ErrMessLcl ) + close(NUNIT) + CALL SetErrStat( ErrID_Fatal, ErrMessLcl, ErrStat, ErrMess, 'READFL') + RETURN + END IF + IF (p%DSTALL) READ(LINE,*,ERR=205) (m%Beddoes%CDO ( NFOILID, K ), K = 1, p%AirFoil%NTables(NFOILID)) + + ! Convert angles to radians + IF (p%DSTALL) THEN + m%Beddoes%AOD ( NFOILID, : ) = m%Beddoes%AOD( NFOILID, : )*D2R + m%Beddoes%AOL ( NFOILID, : ) = m%Beddoes%AOL( NFOILID, : )*D2R + ENDIF + + + ! Read airfoil data tables to end of file + + p%AirFoil%NLIFT(NFOILID) = 0 + ALPosPI = .FALSE. + ALNegPI = .FALSE. + + DO I = 1, p%AirFoil%NumCL + + IF ( p%PMOMENT ) THEN + + READ( NUNIT,*,END=150 ) m%AirFoil%AL(NFOILID,I), & + (m%AirFoil%CL(NFOILID,I,IPHI), m%AirFoil%CD(NFOILID,I,IPHI), & + m%AirFoil%CM(NFOILID,I,IPHI), IPHI = 1, p%AirFoil%NTables(NFOILID)) + + ELSE + + READ( NUNIT,*,END=150 ) m%AirFoil%AL(NFOILID,I), & + (m%AirFoil%CL(NFOILID,I,IPHI), m%AirFoil%CD(NFOILID,I,IPHI), & + IPHI = 1, p%AirFoil%NTables(NFOILID)) + + m%AirFoil%CM(NFOILID,I,:) = 0. + + ENDIF + + ! Check to see if values look reasonable + + DO IPHI = 1, p%AirFoil%NTables(NFOILID) + IF ( ABS( m%AirFoil%AL( NFOILID, I ) ) > 185.) THEN + CALL SetErrStat( ErrID_Fatal, 'Probable error in airfoil data table number '//TRIM(Int2LStr(NFOILID))// & + ' Angle of attack exceeds 185 degrees.', ErrStat, ErrMess, 'READFL') + CLOSE(NUNIT) + RETURN + + ELSEIF (ABS( m%AirFoil%CL( NFOILID, I, IPHI ) ) > 3. ) THEN + CALL SetErrStat( ErrID_Fatal, 'Probable error in airfoil data table number '//TRIM(Int2LStr(NFOILID))// & + ' Coefficient of Lift exceeds 3.0.', ErrStat, ErrMess, 'READFL') + CLOSE(NUNIT) + RETURN + ELSEIF (ABS( m%AirFoil%CD( NFOILID, I, IPHI ) ) > 3. ) THEN + CALL SetErrStat( ErrID_Fatal, 'Probable error in airfoil data table number '//TRIM(Int2LStr(NFOILID))// & + ' Coefficient of Drag exceeds 3.0.', ErrStat, ErrMess, 'READFL') + CLOSE(NUNIT) + RETURN + ELSEIF (ABS( m%AirFoil%CM( NFOILID, I, IPHI ) ) > 3. ) THEN + CALL SetErrStat( ErrID_Fatal, 'Probable error in airfoil data table number '//TRIM(Int2LStr(NFOILID))// & + ' Coefficient of Moment exceeds 3.0.', ErrStat, ErrMess, 'READFL') + CLOSE(NUNIT) + RETURN + + + ENDIF + ENDDO ! IPHI + + ! Store the values at 180 deg. and -180 deg. for check + IF ( m%AirFoil%AL (NFOILID, I ) == 180. ) THEN + ALPosPI = .TRUE. + Do IPHI = 1, p%AirFoil%NTables(NFOILID) + CLPosPI(IPHI) = m%AirFoil%CL(NFOILID,I,IPHI) + CDPosPI(IPHI) = m%AirFoil%CD(NFOILID,I,IPHI) + CMPosPI(IPHI) = m%AirFoil%CM(NFOILID,I,IPHI) + END Do ! IPHI + + ELSEIF ( m%AirFoil%AL (NFOILID, I ) == -180. ) THEN + ALNegPI = .TRUE. + Do IPHI = 1, p%AirFoil%NTables(NFOILID) + CLNegPI(IPHI) = m%AirFoil%CL(NFOILID,I,IPHI) + CDNegPI(IPHI) = m%AirFoil%CD(NFOILID,I,IPHI) + CMNegPI(IPHI) = m%AirFoil%CM(NFOILID,I,IPHI) + END Do ! IPHI + ENDIF + + m%AirFoil%AL ( NFOILID, I ) = m%AirFoil%AL(NFOILID,I) * D2R + p%AirFoil%NLIFT ( NFOILID ) = p%AirFoil%NLIFT(NFOILID) + 1 + + ENDDO ! I + + 150 CLOSE( NUNIT ) + + ! Check to see if values at 180 deg. equal those at -180 deg. + IF (ALPosPI .AND. ALNegPI) THEN + Do IPHI = 1, p%AirFoil%NTables(NFOILID) + IF (CLPosPI(IPHI) /= CLNegPI(IPHI) .OR. & + CDPosPI(IPHI) /= CDNegPI(IPHI) .OR. & + CMPosPI(IPHI) /= CMNegPI(IPHI)) THEN + CALL SetErrStat( ErrID_Fatal, ' The airfoil data at +180 deg is different from -180 deg in file :'//Trim(P%AirFoil%FOILNM(NFOILID)), ErrStat, ErrMess, 'READFL') + return + ENDIF + END Do ! IPHI + ENDIF + + ! Deallocate arrays to make them available for the next file + + IF ( ALLOCATED(CLPosPI) ) DEALLOCATE ( CLPosPI ) + IF ( ALLOCATED(CDPosPI) ) DEALLOCATE ( CDPosPI ) + IF ( ALLOCATED(CMPosPI) ) DEALLOCATE ( CMPosPI ) + IF ( ALLOCATED(CLNegPI) ) DEALLOCATE ( CLNegPI ) + IF ( ALLOCATED(CDNegPI) ) DEALLOCATE ( CDNegPI ) + IF ( ALLOCATED(CMNegPI) ) DEALLOCATE ( CMNegPI ) + + +END DO !NUMFOIL +RETURN + +205 CALL SetErrStat( ErrID_Fatal, ' Error reading line: "'//TRIM(Line)//'" in file : "'//TRIM(P%AirFoil%FOILNM(NFOILID))//'"', ErrStat, ErrMess, 'READFL') + CLOSE(NUNIT) + RETURN + +RETURN +END SUBROUTINE READFL + + ! **************************************************** + SUBROUTINE READTwr(UnIn, InitInp, P, x, xd, z, m, y, ErrStat, ErrMess ) +! This subroutine reads the tower properties input file, allocating TwrProps variables to do so. +! The tower data file contains radius and Re vs CD data as well as the tower wake constant. + ! **************************************************** +!==================================================================================================== + IMPLICIT NONE + ! Passed Variables: + INTEGER, INTENT(IN) :: UnIn + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInp + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Local Variables: + + INTEGER :: I ! loop counter for rows in the data tables + INTEGER :: J ! loop counter for columns in the data tables + + CHARACTER(99) :: Fmt ! format for printing to an echo file + CHARACTER(1024) :: FilName ! file name + + !------------------------------------------------------------------------------------------------- + ! Open the file for reading + !------------------------------------------------------------------------------------------------- + FilName = p%TwrProps%TwrFile + CALL OpenFInpFile (UnIn, TRIM(FilName), ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + + !------------------------------------------------------------------------------------------------- + ! Read the heading, section 1 + !------------------------------------------------------------------------------------------------- + + ! Read in 2 header/comment lines + CALL ReadCom( UnIn, FilName, 'Title line 1', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL ReadCom( UnIn, FilName, 'Title line 2', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + + ! Read in number of tower height entries, NTwrHt + CALL ReadVar( UnIn, FilName, p%TwrProps%NTwrHt, 'NTwrHt', 'Number of tower stations', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + IF (p%TwrProps%NTwrHt < 1) THEN + CALL ProgWarn( 'Number of tower height entries, NTwrHt, must be greater than zero.' ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Read in number of tower Reynolds number entries, NTwrRe + CALL ReadVar( UnIn, FilName, p%TwrProps%NTwrRe, 'NTwrRe', 'Number of tower Reynolds number rows', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + IF (p%TwrProps%NTwrRe < 1) THEN + CALL ProgWarn( 'Number of tower Reynolds number entries, NTwrRe, must be greater than zero.' ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + + ! Read in number of tower CD entries, NTwrCD + CALL ReadVar( UnIn, FilName, p%TwrProps%NTwrCD, 'NTwrCD', 'Number of tower CD columns', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + IF (p%TwrProps%NTwrCD < 1) THEN + CALL ProgWarn( 'Number of tower CD entries, NTwrCD, must be greater than zero.' ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + + ! Read in constant for tower wake model = 0 full potential flow = 0.1 model of Bak et al. + CALL ReadVar( UnIn, FilName, p%TwrProps%Tower_Wake_Constant, 'Tower_Wake_Constant', 'Constant for tower wake model', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! bjj: should there be a sanity check here, too? + + !------------------------------------------------------------------------------------------------- + ! Allocate TwrProps arrays with NTwrHt, NTwrRe, and NTwrCD dimensions; these arrays are + ! read in the next 2 sections of this file. + !------------------------------------------------------------------------------------------------- + + IF ( .NOT. ALLOCATED( p%TwrProps%TwrHtFr ) ) THEN + ALLOCATE ( p%TwrProps%TwrHtFr(p%TwrProps%NTwrHt) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgWarn( ' Error allocating memory for TwrHtFr array.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + IF ( .NOT. ALLOCATED( p%TwrProps%TwrWid ) ) THEN + ALLOCATE ( p%TwrProps%TwrWid(p%TwrProps%NTwrHt) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgWarn( ' Error allocating memory for TwrWid array.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + IF ( .NOT. ALLOCATED( p%TwrProps%NTwrCDCol ) ) THEN + ALLOCATE ( p%TwrProps%NTwrCDCol(p%TwrProps%NTwrHt) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgWarn( ' Error allocating memory for NTwrCDCol array.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + IF ( .NOT. ALLOCATED( p%TwrProps%TwrRe ) ) THEN + ALLOCATE ( p%TwrProps%TwrRe(p%TwrProps%NTwrRe) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgWarn( ' Error allocating memory for TwrRe array.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + IF ( .NOT. ALLOCATED( p%TwrProps%TwrCD ) ) THEN + ALLOCATE ( p%TwrProps%TwrCD(p%TwrProps%NTwrRe, p%TwrProps%NTwrCD) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgWarn( ' Error allocating memory for TwrCD array.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + !------------------------------------------------------------------------------------------------- + ! Read section 2, DISTRIBUTED TOWER PROPERTIES; + ! section contains 2 heading lines in addition to NTwrHt rows of data with 3 columns + !------------------------------------------------------------------------------------------------- + ! Read in 2 header/comment lines + CALL ReadCom( UnIn, FilName, 'Distributed Tower Properties header 1', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL ReadCom( UnIn, FilName, 'Distributed Tower Properties header 2', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + + ! Read tower height data table + + DO I = 1, p%TwrProps%NTwrHt ! 1 line per fraction of height + + + READ( UnIn,*,IOSTAT=ErrStat ) p%TwrProps%TwrHtFr(I), p%TwrProps%TwrWid(I), p%TwrProps%NTwrCDCol(I) + + IF ( ErrStat == 0 ) THEN + IF ( p%Echo ) THEN + WRITE (p%UnEc,'(2X,ES11.4e2, 2X,ES11.4e2, 2X,I11)') p%TwrProps%TwrHtFr(I), p%TwrProps%TwrWid(I), p%TwrProps%NTwrCDCol(I) + END IF + ELSE IF ( ErrStat < 0 ) THEN + CALL ProgWarn( ' Premature end of file while reading line '//TRIM(Int2Lstr(I))// & + ' of the distributed tower properties in file "'//TRIM(FilName)//'."' ) + RETURN + ELSE + CALL ProgWarn( ' Error reading line '//TRIM(Int2Lstr(I))// & + ' of the distributed tower properties in file "'//TRIM(FilName)//'."' ) + RETURN + END IF + + + !.............................................................................................. + ! Check to see if values look reasonable + !.............................................................................................. + + ! Make sure tower height fractions are between 0 and 1 + IF ( p%TwrProps%TwrHtFr( I ) < 0.0 .OR. p%TwrProps%TwrHtFr( I ) > 1.0 ) THEN + CALL ProgWarn( ' Error on line '//TRIM(Int2Lstr(I))//' of the distributed tower properties in file "' & + //TRIM(FilName)//'." Tower height fractions must be between 0.0 and 1.0.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Make sure the tower height increases for each entry + IF (I > 1) THEN + IF (p%TwrProps%TwrHtFr(I) <= p%TwrProps%TwrHtFr(I-1)) THEN + CALL ProgWarn( ' Error on line '//TRIM(Int2Lstr(I))//' of the distributed tower properties in file "' & + //TRIM(FilName)//'." Tower height fraction entries must be in order of increasing height.' ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + ENDIF + + ! Make sure tower width is positive + IF ( p%TwrProps%TwrWid( I ) <= 0.0 ) THEN + CALL ProgWarn( ' Error on line '//TRIM(Int2Lstr(I))//' of the distributed tower properties in file "' & + //TRIM(FilName)//'." Tower width must be positive.' ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Make sure the tower CD column is within range + IF ( p%TwrProps%NTwrCDCol(I) < 1 .OR. p%TwrProps%NTwrCDCol(I) > P%TwrProps%NTwrCD ) THEN + CALL ProgWarn( ' Error on line '//TRIM(Int2Lstr(I))//' of the distributed tower properties in file "' & + //TRIM(FilName)//'." Tower height CD column must be between 1 and '//TRIM(Int2Lstr(P%TwrProps%NTwrCD))//'.' ) + ErrStat = ErrID_Fatal + RETURN + END IF + + END DO ! I + + !------------------------------------------------------------------------------------------------- + ! Read section 3, Re vs CD PROPERTIES; + ! this section has 2 header lines plus NTwrRe rows of data with NTwrCD+1 columns + !------------------------------------------------------------------------------------------------- + + ! Read in 2 header/comment lines + CALL ReadCom( UnIn, FilName, 'Re vs CD Properties header 1', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL ReadCom( UnIn, FilName, 'Re vs CD Properties header 2', ErrStat, ErrMess ) + IF ( ErrStat /= ErrID_None ) RETURN + + Fmt = '('//TRIM(Int2Lstr(p%TwrProps%NTwrCD+1))//'(2X,ES11.4e2))' + + DO I = 1, p%TwrProps%NTwrRe + + READ( UnIn,*,IOSTAT=ErrStat ) p%TwrProps%TwrRe(I), (p%TwrProps%TwrCD(I,J), J = 1, p%TwrProps%NTwrCD) + + IF ( ErrStat == 0 ) THEN + IF ( p%Echo ) THEN + WRITE (p%UnEc,Fmt) p%TwrProps%TwrRe(I), (p%TwrProps%TwrCD(I,J), J = 1, p%TwrProps%NTwrCD) + END IF + ELSE IF ( ErrStat < 0 ) THEN + CALL ProgWarn( ' Premature end of file while reading line '//TRIM(Int2Lstr(I))// & + ' of the tower Re vs CD properties in file "'//TRIM(FilName)//'."' ) + RETURN + ELSE + CALL ProgWarn( ' Error reading line '//TRIM(Int2Lstr(I))// & + ' of the tower Re vs CD properties in file "'//TRIM(FilName)//'."' ) + RETURN + END IF + + END DO ! I + + !------------------------------------------------------------------------------------------------- + ! close the file and return + !------------------------------------------------------------------------------------------------- + + CLOSE( UnIn ) + + RETURN + +END SUBROUTINE READTwr + +!==================================================================================================== +!> Calculates the axial and tangential induction factor for each annular segment +! and time step (i.e. sets m%Element%A and m%Element%AP) + SUBROUTINE ELEM_INDUCTIONS( p, m, ErrStat, ErrMess, & + PSI, RLOCAL, J, IBlade, VNROTOR2, VT, VNW, & + VNB, Initial) + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + REAL(ReKi),INTENT(IN) :: PSI + REAL(ReKi),INTENT(IN) :: RLOCAL + REAL(ReKi), INTENT(IN ) :: VNB ! Normal (relative) velocity of the element + REAL(ReKi),INTENT(IN) :: VNROTOR2 + REAL(ReKi),INTENT(IN) :: VNW + REAL(ReKi), INTENT(IN ) :: VT + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + LOGICAL, INTENT(IN) :: Initial + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + ErrStat = ErrID_None + ErrMess = "" + + !-mlb Check for being at the center of rotation. + ! If we are at the center of rotation, the induction equations + ! are undefined, so let's just USE zeros. + +! initialize AxInd and TanInd variables + m%Element%A (J,IBLADE) = 0.0 + m%Element%AP(J,IBLADE) = 0.0 + +IF ( RLOCAL < 0.01 ) THEN + ! Already set to 0 +ELSEIF( P%DYNINFL .AND. P%Blade%R * m%Rotor%REVS < 2.0 ) THEN !ACH 3/10/03 This block deals with dyn. inflow problems at low tip speed + ! Already set to 0 + m%DYNINIT = .TRUE. !Re-initialize if we begin using dynamic inflow again +ELSE + + ! Turn wake off when using dynamic inflow and tip speed goes low. Wake will remain off. + ! Get induction factor = A using static airfoil coefficients + IF ( P%WAKE .AND. .NOT. Initial) THEN + + IF ( P%DYNINFL ) THEN + ! USE dynamic inflow model to find A + CALL VINDINF( P, m, ErrStatLcl, ErrMessLcl, & + J, IBlade, RLOCAL, VNW, VNB, VT, PSI ) !possibly changes A, and AP + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEM_INDUCTIONS' ) + IF (ErrStat >= AbortErrLev) RETURN + ELSE + ! USE momentum balance to find A + CALL VIND( P, m, ErrStatLcl, ErrMessLcl, & + J, IBlade, RLOCAL, VNROTOR2, VNW, VNB, VT ) !changes A, and AP + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEM_INDUCTIONS' ) + IF (ErrStat >= AbortErrLev) RETURN + ! Apply skewed-wake correction, if applicable + IF( m%SKEW ) CALL VNMOD( P, m, ErrStatLcl, ErrMessLcl,& + J, IBlade, RLOCAL, PSI ) !changes A + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEM_INDUCTIONS' ) + IF (ErrStat >= AbortErrLev) RETURN + ENDIF + ENDIF +ENDIF + +END SUBROUTINE ELEM_INDUCTIONS + +SUBROUTINE ELEMFRC2( p, m, ErrStat, ErrMess, J, IBlade, & + DFN, DFT, PMA, Initial, phi ) + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + REAL(ReKi), INTENT( OUT) :: DFN + REAL(ReKi), INTENT( OUT) :: DFT + REAL(ReKi), INTENT( OUT) :: PMA + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + LOGICAL, INTENT(IN) :: Initial + + ! Local Variables: + + REAL(ReKi) :: CDA + REAL(ReKi) :: CLA + REAL(ReKi) :: CMA + REAL(ReKi) :: CPHI + REAL(ReKi), intent(in) :: PHI + REAL(ReKi) :: QA + REAL(ReKi) :: ReNum + REAL(ReKi) :: SPHI + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + ErrStat = ErrID_None + ErrMess = "" + + ! Get the Reynold's number for the element + ! Returns Reynold's number x 10^6 !bjj: Reynold's number x 10^-6 ? +ReNum = GetReynolds( SQRT(m%Element%W2(J,IBlade)), P%Blade%C(J), P%Wind%KinVisc ) +IF (P%Reynolds) m%AirFoil%MulTabLoc = ReNum + + ! Get lift coefficient from dynamic stall routine if desired + ! note that the induced velocity was calculated + ! using the static CL, not the dynamic CL + +IF ( P%DSTALL ) THEN + ! USE Beddoes dynamic stall model + IF (Initial) THEN ! USE static data on first pass + CALL BEDINIT ( P, m, ErrStatLcl, ErrMessLcl, & + J, IBlade, m%Element%ALPHA(J,IBlade)) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEMFRC' ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CLCD( P, m, ErrStatLcl, ErrMessLcl, & + m%Element%ALPHA(J,IBlade), CLA, CDA, CMA, P%AirFoil%NFOIL(J) ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEMFRC' ) + IF (ErrStat >= AbortErrLev) RETURN + ELSE + CALL BeddoesModel( P, m, ErrStatLcl, ErrMessLcl, & + m%Element%W2(J,IBlade), J, IBlade, m%Element%ALPHA(J,IBlade), CLA, CDA, CMA) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEMFRC' ) + IF (ErrStat >= AbortErrLev) RETURN + ENDIF +ELSE + ! Don't USE dynamic stall model + CALL CLCD( P, m, ErrStatLcl, ErrMessLcl, & + m%Element%ALPHA(J,IBlade), CLA, CDA, CMA, P%AirFoil%NFOIL(J) ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'ELEMFRC' ) + IF (ErrStat >= AbortErrLev) RETURN +ENDIF + +QA = 0.5 * P%Wind%RHO * m%Element%W2(J,IBlade) * P%Blade%DR(J) * P%Blade%C(J) +CPHI = COS( PHI ) +SPHI = SIN( PHI ) +DFN = ( CLA * CPHI + CDA * SPHI ) * QA +DFT = ( CLA * SPHI - CDA * CPHI ) * QA + +IF ( P%PMOMENT ) THEN + PMA = CMA * QA * P%Blade%C(J) +ELSE + PMA = 0. + CMA = 0. +ENDIF + + + ! Save values at appropriate station + +IF ( IBLADE == 1 ) THEN + IF ( m%ElOut%ElPrList(J) > 0 ) THEN + m%ElOut%AAA ( m%ElOut%ElPrList(J) ) = m%Element%A (J,IBLADE) + m%ElOut%AAP ( m%ElOut%ElPrList(J) ) = m%Element%AP(J,IBLADE) + m%ElOut%ALF ( m%ElOut%ElPrList(J) ) = m%Element%ALPHA(J,IBlade) * R2D + m%ElOut%CDD ( m%ElOut%ElPrList(J) ) = CDA + m%ElOut%CLL ( m%ElOut%ElPrList(J) ) = CLA + m%ElOut%CMM ( m%ElOut%ElPrList(J) ) = CMA + m%ElOut%CNN ( m%ElOut%ElPrList(J) ) = CLA * COS(m%Element%ALPHA(J,IBlade)) + CDA * SIN(m%Element%ALPHA(J,IBlade)) + m%ElOut%CTT ( m%ElOut%ElPrList(J) ) =-CDA * COS(m%Element%ALPHA(J,IBlade)) + CLA * SIN(m%Element%ALPHA(J,IBlade)) + m%ElOut%DFNSAV ( m%ElOut%ElPrList(J) ) = DFN + m%ElOut%DFTSAV ( m%ElOut%ElPrList(J) ) = DFT + m%ElOut%DynPres( m%ElOut%ElPrList(J) ) = 0.5 * P%Wind%RHO * m%Element%W2(J,IBlade) + m%ElOut%PITSAV ( m%ElOut%ElPrList(J) ) = m%Element%PitNow(J,IBlade) * R2D + m%ElOut%PMM ( m%ElOut%ElPrList(J) ) = PMA + m%ElOut%ReyNum ( m%ElOut%ElPrList(J) ) = ReNum + m%ElOut%Gamma ( m%ElOut%ElPrList(J) ) = 0.5 * P%Blade%C(J) * sqrt(m%Element%W2(J,IBlade)) * CLA ! 1/2 c Urel Cl [m^2/s] + ENDIF + +ENDIF + +RETURN +END SUBROUTINE ELEMFRC2 + +!====================================================== + SUBROUTINE VIND( p, m, ErrStat, ErrMess, & + J, IBlade, RLOCAL, VNROTOR2, VNW, VNB, VT ) + ! Calculates the axial and tangential induction factor for each annular segment + ! and time step (i.e. sets m%Element%A and m%Element%AP) + ! *************************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + + REAL(ReKi), INTENT(IN ) :: RLOCAL + REAL(ReKi), INTENT(IN ) :: VNB + REAL(ReKi), INTENT(IN ) :: VNROTOR2 + REAL(ReKi), INTENT(IN ) :: VNW + REAL(ReKi), INTENT(IN ) :: VT ! tangential velocity from relative blade motion and wind, no induction + + INTEGER, INTENT(IN ) :: J + INTEGER, INTENT(IN ) :: IBlade + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + + ! Local Variables: + + REAL(ReKi) :: A2 + REAL(ReKi) :: A2P + REAL(ReKi) :: AI + REAL(ReKi) :: ALPHA + REAL(ReKi) :: ASTEP + REAL(ReKi) :: ATOLER2 + REAL(ReKi) :: ATOLERBY10 + REAL(ReKi) :: CDA + REAL(ReKi) :: CLA + REAL(ReKi) :: CMA + REAL(ReKi) :: DAI + REAL(ReKi) :: DAI1 + REAL(ReKi) :: DELAI + REAL(ReKi) :: PHI + REAL(ReKi) :: SOLFACT + REAL(ReKi) :: VNA + REAL(ReKi) :: VT2_Inv + REAL(ReKi) :: VTA + + INTEGER :: ICOUNT + INTEGER :: MAXICOUNT + INTEGER :: Sttus + INTEGER(IntKi) :: ErrStatLcl + character(ErrMsgLen) :: ErrMessLcl + + ErrStat = ErrID_None + ErrMess = "" + + ! Allocate and initialize the local array on the first pass +IF ( .NOT. ALLOCATED (m%Element%OLD_A_NS) ) THEN + ALLOCATE ( m%Element%OLD_A_NS ( P%Element%NELM, P%NumBl) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLD_A_NS array.' ) + m%Element%OLD_A_NS(:,:) = 0.0 +ENDIF + + ! Allocate and initialize the local array on the first pass +IF ( .NOT. ALLOCATED (m%Element%OLD_AP_NS) ) THEN + ALLOCATE ( m%Element%OLD_AP_NS ( P%Element%NELM, P%NumBl) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLD_AP_NS array.' ) + m%Element%OLD_AP_NS(:,:) = 0.0 +ENDIF + + ! Set maximum iterations +MAXICOUNT = P%MAXICOUNT + + ! CH-- Alternate convergence criteria +ATOLER2 = 2.0 * P%InducedVel%ATOLER +ATOLERBY10 = 0.1 * P%InducedVel%ATOLER + + ! Bypass calculations for low wind speed, assume no induced velocity. + +IF ( VNROTOR2 < 0.1 ) THEN + m%Element%A(J,IBLADE) = 0.0 + RETURN +ENDIF + + ! SOLFACT is solidity factor divided by 2*VNROTOR2 + ! VT2_Inv is 1./VT**2 to save computation time + +IF ( RLOCAL == 0.0 ) THEN ! Avoid div/0 in FAST2 + SOLFACT = 1.0/VNROTOR2 +ELSE + SOLFACT = P%NumBl * P%Blade%C(J) / ( TWOPI * RLOCAL * VNROTOR2) +ENDIF +VT2_Inv = 1. / ( VT * VT ) + + !-mlb Let's USE the old value of the A from before it was corrected for skew. +AI = m%Element%OLD_A_NS( J, IBLADE ) +DAI1 = 0.05 +A2P = m%Element%OLD_AP_NS( J, IBLADE ) +ASTEP = 0.5 +ICOUNT = 0 + + ! Check for extremely high VN and bypass calculations if necessary + +IF ( ABS( VNB ) > 100. ) THEN + m%Element%A( J, IBLADE ) = 0.0 + CALL VINDERR( m, ErrStat, ErrMess, & + VNW, VNB, 'VNB', J, IBLADE ) + RETURN +ELSEIF ( ABS( VT ) > 400. ) THEN + m%Element%A( J, IBLADE ) = 0.0 + CALL VINDERR( m, ErrStat, ErrMess, & + VNW, VT, 'VT', J, IBLADE ) + RETURN +ENDIF + +A2 = AI + +CALL AXIND ( P, m, ErrStat, ErrMess, & + VNW, VNB, VNA, VTA, VT, VT2_Inv, VNROTOR2, A2, A2P, & + J, IBlade, SOLFACT, ALPHA, PHI, CLA, CDA, CMA, RLOCAL ) + IF (ErrStat >= AbortErrLev) RETURN + +DAI = A2 - AI + +DELAI = ASTEP * DAI + + !CH-- Modification of mlb's proposed change + ! Must pass two criteria. If we have crossed zero many times + ! then the first criterion will be easier to meet than the second + ! because ASTEP will be small (but the second is relaxed to ATOLER2) + +DO WHILE ( ABS( DELAI ) > ATOLERBY10 .AND. ABS(DAI) > ATOLER2 ) + + ICOUNT = ICOUNT + 1 + + A2 = AI + + CALL AXIND ( P, m, ErrStatLcl, ErrMessLcl, & + VNW, VNB, VNA, VTA, VT, VT2_Inv, VNROTOR2, A2, A2P, & + J, IBlade, SOLFACT, ALPHA, PHI, CLA, CDA, CMA, RLOCAL ) + CALL SetErrStat(ErrStatLcl,ErrMessLcl,ErrStat,ErrMess,'VIND' ) + IF (ErrStat >= AbortErrLev) RETURN + + DAI = A2 - AI + + DELAI = ASTEP * DAI + + ! Test for convergence, program warning after 1000 iterations + + IF ( ICOUNT > MAXICOUNT ) THEN + CALL ProgWarn( 'Induction factor calculation did not converge after'//TRIM(Int2LStr(MAXICOUNT))// & + ' iterations. AeroDyn will continue using induction factors from previous successful time step.' ) + A2 = m%Element%OLD_A_NS (J,IBLADE) + A2P = m%Element%OLD_AP_NS(J,IBLADE) + !CALL SetErrStat(ErrID_Warn,ErrMessLcl,ErrStat,ErrMess,'VIND' ) + + EXIT + ENDIF + + ! Reduce step size after a zero crossing + !CH-- Put floor under ASTEP to keep it reasonable after many zero crossings + + IF( NINT( SIGN(1.0_ReKi, DAI) ) /= NINT( SIGN(1.0_ReKi, DAI1) ) ) ASTEP = MAX( 1.0E-4_ReKi, 0.5_ReKi*ASTEP ) + + AI = AI + DELAI + DAI1 = DELAI + +END DO + + ! Passed test, we're done +m%Element%A (J,IBLADE) = A2 +m%Element%AP(J,IBLADE) = A2P +m%Element%OLD_A_NS (J,IBLADE) = A2 +m%Element%OLD_AP_NS (J,IBLADE) = A2P + +RETURN +END SUBROUTINE VIND + + + ! *************************************************** + SUBROUTINE VINDERR( m, ErrStat, ErrMess, & + VNW, VX, VID, J, IBLADE ) +! SUBROUTINE VINDERR( VNW, VX, VID, J, IBLADE ) + ! used to write warning messages to the screen + ! when VN or VT is high. + ! *************************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + REAL(ReKi),INTENT(IN) :: VNW + REAL(ReKi),INTENT(IN) :: VX + + INTEGER ,INTENT(IN) :: IBLADE + INTEGER ,INTENT(IN) :: J + + CHARACTER( *),INTENT(IN) :: VID + + + ErrStat = ErrID_None + ErrMess = "" + + ! Don't write messages if we've already done it 5 times + +IF ( m%AFLAGVinderr ) RETURN + +m%NERRORS = m%NERRORS + 1 + + CALL ProgWarn( ' High '//TRIM(VID)//' velocity encountered during induction factor calculation.' ) + CALL WrScr( ' Blade number '//TRIM(Int2LStr(IBLADE))//', Element number '//TRIM(Int2LStr(J )) ) + CALL WrScr( ' VNW = ' //TRIM(Num2LStr(VNW))//', '//TRIM(VID)//' = '//TRIM(Num2LStr(VX)) ) + +IF ( m%NERRORS >= 5 ) THEN + m%AFLAGVinderr = .TRUE. + CALL ProgWarn( ' Induced velocity warning written 5 times. '//& + ' The message will not be repeated, though the condition may persist.' ) +ENDIF + + +RETURN +END SUBROUTINE VINDERR + + ! ****************************************************** + SUBROUTINE AXIND (P, m, ErrStat, ErrMess, & + VNW, VNB, VNA, VTA, VT, VT2_Inv, VNROTOR2, A2, & + A2P, J, IBlade, SOLFACT, ALPHA, PHI, CLA, CDA, CMA, RLOCAL ) +! SUBROUTINE AXIND ( VNW, VNB, VNA, VTA, VT, VT2_Inv, VNROTOR2, A2, & +! A2P, J, SOLFACT, ALPHA, PHI, CLA, CDA, CMA, RLOCAL ) + ! calculates a new axial induction factor from + ! given values of velocities and geometry. This routine + ! is called by vind as part of the iteration process + ! ****************************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + REAL(ReKi),INTENT(INOUT) :: A2 + REAL(ReKi),INTENT(INOUT) :: A2P + REAL(ReKi),INTENT(OUT) :: ALPHA + REAL(ReKi),INTENT(OUT) :: CDA + REAL(ReKi),INTENT(OUT) :: CLA + REAL(ReKi),INTENT(OUT) :: CMA + REAL(ReKi),INTENT(OUT) :: PHI + REAL(ReKi),INTENT(IN) :: RLOCAL + REAL(ReKi),INTENT(IN) :: SOLFACT + REAL(ReKi),INTENT(OUT) :: VNA + REAL(ReKi),INTENT(IN) :: VNB + REAL(ReKi),INTENT(IN) :: VNROTOR2 + REAL(ReKi),INTENT(IN) :: VNW + REAL(ReKi),INTENT(IN) :: VT + REAL(ReKi),INTENT(IN) :: VT2_Inv + REAL(ReKi),INTENT(OUT) :: VTA + + INTEGER ,INTENT(IN) :: J + INTEGER ,INTENT(IN) :: IBlade + + ! Local Variables: + + REAL(ReKi) :: CH + REAL(ReKi) :: CPhi ! COS( PHI ) + REAL(ReKi) :: SPHI + REAL(ReKi) :: SWRLARG + REAL(ReKi) :: W2 + + + ErrStat = ErrID_None + ErrMess = "" + + +VNA = VNW * ( 1. - A2 ) + VNB +VTA = VT * ( 1. + A2P ) + + ! Get airfoil CL and CD +PHI = ATAN2( VNA, VTA ) +ALPHA = PHI - m%Element%PitNow(J,IBlade) + +CALL MPI2PI ( ALPHA ) + +CALL CLCD ( P, m, ErrStat, ErrMess, & + ALPHA, CLA, CDA, CMA, P%AirFoil%NFoil(J) ) + IF (ErrStat >= AbortErrLev) RETURN + +W2 = VNA * VNA + VTA * VTA +SPHI = VNA/SQRT( W2 ) +CPhi = COS( Phi ) + + ! Calculate new value of A. Optionally include normal force due to drag. + +CH = W2*SOLFACT*( CLA*CPhi + P%InducedVel%EqAIDmult*CDA*SPhi ) + + + ! Get the tip loss values for the element (if they change) +IF (p%InducedVel%TLOSS) CALL GetTipLoss ( P, m, ErrStat, ErrMess, & + J, SPHI, m%TIPLOSS, RLOCAL) + + ! Get the hub loss values for the element (if they change) +IF (p%InducedVel%HLOSS) CALL GetPrandtlLoss ( P%Element%HLCNST(J), SPHI, m%HUBLOSS) + + ! Get the total loss for the element +m%LOSS = m%TIPLOSS * m%HUBLOSS + + ! Check for diverging CH and correct if necessary + +IF ( ABS( CH ) > 2. ) CH = SIGN( 2.0_ReKi, CH ) + +IF ( CH < 0.96*m%LOSS ) THEN + A2 = 0.5*( 1 - SQRT( 1.0 - CH/m%LOSS ) ) +ELSE + A2 = 0.1432 + SQRT( -0.55106 + .6427*CH/m%LOSS) +ENDIF + + ! Calculate induced swirl (a') if desired. + ! From C. Ross Harmon's paper on PROPX. + +IF ( p%SWIRL ) THEN + IF ( p%InducedVel%EquilDT ) THEN ! USE PROP-PC style tangential induction equation with the addition of the drag term. + ! Because of the singularity that occurs when phi approaches zero, + ! let's test for small phi and set a' equal to a small, negative number. + IF ( ( ABS( SPhi ) > 0.01 ) .AND. ( ABS( CPhi ) > 0.01 ) ) THEN + A2P = SOLFACT*( CLA*SPhi - CDA*CPhi )*( 1.0 + A2P )*VNROTOR2/( 4.0*m%LOSS*SPhi*CPhi ) + ELSEIF ( ABS( SPhi ) > 0.01 ) THEN ! Tangential velocity near zero, phi near 90 degrees. + A2P = SOLFACT*( CLA*SPhi - CDA*SIGN( 0.01_ReKi, CPhi ) )*( 1.0 + A2P )*VNROTOR2/( 4.0*m%LOSS*SPhi*SIGN( 0.01_ReKi, CPhi ) ) + ELSE ! Normal velocity near zero, phi near 0 degrees. + A2P = SOLFACT*( CLA*SIGN( 0.01_ReKi, SPhi ) - CDA*CPhi )*( 1.0 + A2P )*VNROTOR2/( 4.0*m%LOSS*SIGN( 0.01_ReKi, SPhi )*CPhi ) + ENDIF + ELSE + SWRLARG = 1.0 + 4.0*m%LOSS*A2*VNW*VNA*VT2_Inv + IF ( SWRLARG < 0.0 ) THEN + A2P = 0.0 + ELSE + A2P = 0.5*( -1.0 + SQRT( SWRLARG ) ) + ENDIF + ENDIF +ELSE + A2P = 0.0 +ENDIF + + +RETURN +END SUBROUTINE AXIND + + + ! *************************************************** + FUNCTION GetReynolds( WindSpd, ChordLen, KinVisc ) + ! computes the Reynolds number for the element, divided by 1.0E6 + ! *************************************************** + +IMPLICIT NONE + + ! Passed Variables: + +REAL(ReKi),INTENT(IN) :: WindSpd +REAL(ReKi),INTENT(IN) :: ChordLen +REAL(ReKi),INTENT(IN) :: KinVisc + + ! function definition +REAL(ReKi) :: GetReynolds + +GetReynolds = 1.0E-6 * WindSpd * ChordLen / KinVisc + + +RETURN +END FUNCTION GetReynolds + + ! *************************************************** + SUBROUTINE GetTipLoss( P, m, ErrStat, ErrMess, & + J, SPHI, TIPLOSS, RLOCAL ) +! SUBROUTINE GetTipLoss( J, SPHI, TIPLOSS, RLOCAL ) + ! computes the tip loss constant for element J + ! TIPLOSS is returned to AXIND + ! Uses the Prandtl tip loss model with a correction + ! from Georgia Tech (2002 ASME Wind Energy Symposium) + ! *************************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + REAL(ReKi), INTENT(IN) :: SPHI + REAL(ReKi), INTENT(IN) :: RLOCAL + REAL(ReKi), INTENT(OUT) :: TIPLOSS + + INTEGER , INTENT(IN) :: J + + + ! Local Variables: + + REAL(ReKi) :: Dist2pt7 = 0.7 ! current element distance to r/R = 0.7 + REAL(ReKi) :: OLDDist7 ! previous element distance to r/R = 0.7 + REAL(ReKi) :: percentR + + INTEGER :: Jpt7 = 0 ! The element closest to r/R = 0.7 + + + ErrStat = ErrID_None + ErrMess = "" + + ! Calculate PRANDTL tip loss model +CALL GetPrandtlLoss( P%Element%TLCNST(J), SPHI, TIPLOSS ) + + + ! Apply Georgia Tech correction to Prandtl model if activated +IF (p%InducedVel%GTECH) THEN + percentR = RLOCAL/P%Blade%R + + ! Search for the element closest to r/R = 0.7 + IF (m%FirstPassGTL) THEN + ! If the current element is closer than the previous, update values + IF ( ABS(percentR - 0.7) < Dist2pt7 ) THEN + OLDDist7 = Dist2pt7 + Dist2pt7 = ABS(percentR - 0.7) + Jpt7 = J + m%TLpt7 = TIPLOSS + ENDIF + IF (J == P%Element%NELM) THEN ! We're done after one pass through the blades + m%FirstPassGTL = .FALSE. + ELSE + RETURN ! Don't do the correction until we calculate the correct TLpt7 + ENDIF + ENDIF + + IF ( J == Jpt7 ) m%TLpt7 = TIPLOSS ! Update the value of TLpt7 at the proper element + + ! Do the actual Georgia Tech correction to the Prandtl model + IF (percentR >= 0.7) THEN + TIPLOSS = (TIPLOSS**0.85 + 0.5 ) / 2.0 + ELSE + TIPLOSS = 1.0 - percentR*(1.0 - m%TLpt7)/0.7 + ENDIF +ENDIF + + + +RETURN +END SUBROUTINE GetTipLoss + + + ! *************************************************** + + SUBROUTINE GetPrandtlLoss( LCnst, SPHI, PrLOSS ) + ! computes the hub loss constant for element J + ! HUBLOSS is returned to AXIND + ! Uses the Prandtl loss model + ! *************************************************** + IMPLICIT NONE + ! Passed Variables: + + REAL(ReKi),INTENT(IN) :: LCnst + REAL(ReKi),INTENT(OUT) :: PrLOSS + REAL(ReKi),INTENT(IN) :: SPHI + + ! Local Variables: + + REAL(ReKi) :: F + + ! Calculate PRANDTL loss model + ! Check values of SPHI to save runtime. + IF ( ABS( SPHI ) < 1.E-4 ) THEN + PrLOSS = 1.0 + ELSE + ! USE ABS function to account for unusual PHI. + F = ABS( LCnst / SPHI ) + ! Check values of F to avoid underflow of EXP function. + IF ( F < 7. ) THEN + PrLOSS = ACOS( EXP( -F ) ) / PIBY2 + ELSE + PrLOSS = 1.0 + ENDIF + ENDIF + + +RETURN +END SUBROUTINE GetPrandtlLoss + +!==================================================================================================== +SUBROUTINE GetTwrInfluence ( P, m, ErrStat, ErrMess, & + VX, VY, InputPosition) +!SUBROUTINE GetTwrInfluence (VX, VY, InputPosition) +! Computes tower shadow or dam influence on the blade +! Note that this routine assumes there are NO tower deflections. +! +! Use the Riso tower dam model of Bak, Madsen and Johansen +! This model is based on potential flow and is applicable in front of and behind the tower, +! although in the wake we use the method of Powles +! PJM, NREL +! +! bjj, jmj: this function should return the influence parameters, which will be based on some mean +! wind direction (or possibly the direction at the tower) for a given height, instead of using the +! local velocity/direction so that all points on a horizontal slice of air can use the same +! deficit at each given time. Will need the tower position, too. +!==================================================================================================== + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + + REAL(ReKi), INTENT(INOUT) :: VX ! on input, U-velocity without tower effect; on output, U-velocity including tower effect + REAL(ReKi), INTENT(INOUT) :: VY ! on input, V-velocity without tower effect; on output, V-velocity including tower effect + REAL(ReKi), INTENT(IN) :: InputPosition(3) !velocities in global coordinates with tower effect + + ! Local Variables: + + REAL(ReKi) :: ANGLE ! Angle determining whether blade is upwind or downwind of tower + REAL(ReKi) :: CenterDist ! Distance from blade element to wake centerline + REAL(ReKi) :: phi ! Angle between x-axis and horizontal wind direction based upon instantaneous velocities VY and VX (at the blade element) + REAL(ReKi) :: CosPhi ! COS(phi) + REAL(ReKi) :: SinPhi ! SIN(phi) + REAL(ReKi) :: Distance ! Normalized horizontal distance from tower to blade element + REAL(ReKi) :: SHADOW ! Value of the tower shadow deficit at the blade element + REAL(ReKi) :: THETA ! Angle between x-axis and line from tower to blade element + REAL(ReKi) :: TwrCD_Station ! Drag coefficient of the tower + REAL(ReKi) :: TwrRad ! Radius of the tower at the height of interest + REAL(ReKi) :: WIDTH ! Half width of the wake after accounting for wake expansion proportional to square root of Distance + + REAL(ReKi) :: V_total ! total freestream wind speed + REAL(ReKi) :: VX_wind ! tower influenced wind speeds in wind coordinates + REAL(ReKi) :: VY_wind ! tower influenced wind speeds in wind coordinates + REAL(ReKi) :: WindXInf ! Influence of the tower on X wind velocity in wind reference frame + REAL(ReKi) :: WindYInf ! Influence of the tower on Y wind velocity in wind reference frame + REAL(ReKi) :: Xtemp ! Temporary variable used in tower dam calculations + REAL(ReKi) :: Xtemp2 ! Temporary variable used in tower dam calculations + REAL(ReKi) :: Xwind ! X Location of element in a wind-based coordinate system + REAL(ReKi) :: Yg ! Variable used to smooth dam effect above the tower + REAL(ReKi) :: Ytemp2 ! Temporary variable used in tower dam calculations + REAL(ReKi) :: Ywind ! Y Location of element in a wind-based coordinate system + + REAL(ReKi) :: ZGrnd ! distance between position and undeflected hub + + + ErrStat = ErrID_None + ErrMess = "" + + !------------------------------------------------------------------------------------------------- + ! This subroutine is only valid for TwrPotent and TwrShadow features + !------------------------------------------------------------------------------------------------- + IF (.NOT. p%TwrProps%TwrPotent .AND. .NOT. p%TwrProps%TwrShadow) RETURN + + !------------------------------------------------------------------------------------------------- + ! Initialize some variables + !------------------------------------------------------------------------------------------------- + ZGrnd = InputPosition(3) - p%Rotor%HH ! distance between position and hub !BJJ: this should really be the tower height (position), not HH + V_total = SQRT( VX**2 + VY**2 ) ! total wind speed + + !------------------------------------------------------------------------------------------------- + ! Tower influence calculations aren't necessary for zero velocity + !------------------------------------------------------------------------------------------------- + IF ( V_total <= 0.0 ) RETURN + + !------------------------------------------------------------------------------------------------- + ! For the current element location, get the appropriate tower properties and calculate the + ! element distance from from the tower. + ! BJJ: If we're above the tower top, is the radius zero? + !------------------------------------------------------------------------------------------------- + + CALL GetTwrSectProp (P, m, ErrStat, ErrMess, & + InputPosition(:), V_total, TwrRad, TwrCD_Station) ! Get the tower properties for the current element location + + Distance = SQRT ( InputPosition(1)**2 + InputPosition(2)**2 ) / TwrRad ! normalized distance to tower center + + ! Check for tower strike + IF ( Distance < 1.0 ) THEN ! potentially inside the tower !bjj: only if we're not ABOVE the tower, though.... + + IF (ZGrnd < 0.0) THEN !bjj added this condition.... check that it's correct +!bjj: what does this exactly mean? "temporarily disabled?" + IF( .NOT. m%AFLAGTwrInflu) THEN + CALL ProgWarn( ' Tower model temporarily disabled due to possible tower strike.'// & + ' This message will not be repeated though the condition may persist.' ) + !write a blank line (so FAST doesn't write over it) + CALL WrScr( ' ' ) + m%AFLAGTwrInflu = .TRUE. + ENDIF + + RETURN + + END IF + + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Store the wind direction for later + !------------------------------------------------------------------------------------------------- + + phi = ATAN2( VY, VX ) ! angle between x-axis and instantaneous horizontal wind direction + CosPhi = COS( phi ) + SinPhi = SIN( phi ) + + + !------------------------------------------------------------------------------------------------- + ! Calculate the influence due to potential flow around tower based on velocity at element + !------------------------------------------------------------------------------------------------- + + IF ( P%TwrProps%TwrPotent ) THEN + + ! When above the tower, smooth the transition to the free-stream + IF ( ZGrnd > 0 ) THEN + Yg = SQRT( InputPosition(2)**2 + ZGrnd**2 ) + ELSE + Yg = InputPosition(2) + ENDIF + + ! Get the element location in the wind reference frame + Xwind = InputPosition(1) * CosPhi + Yg * SinPhi + Ywind = Yg * CosPhi - InputPosition(1) * SinPhi + + ! Normalize the location coordinates + Xwind = Xwind / TwrRad + Ywind = Ywind / TwrRad + + + Xtemp = Xwind + P%TwrProps%Tower_Wake_Constant !PJM fixed this error 3/30/06 + Xtemp2 = Xtemp * Xtemp + Ytemp2 = Ywind * Ywind + + + ! Calculate the tower influence + WindXInf = 1.0 - (Xtemp2 - Ytemp2)/( (Xtemp2 + Ytemp2)**2 ) & + + TwrCD_Station/TwoPi * Xtemp/(Xtemp2 + Ytemp2) + WindYInf = -2.0 * (Xtemp * Ywind)/( (Xtemp2 + Ytemp2)**2 ) & !PJM fixed sign error 3/30/06 added minus sign from Bak + + TwrCD_Station/TwoPi * Ywind/(Xtemp2 + Ytemp2) + ELSE + WindXInf = 1.0 + WindYInf = 0.0 + ENDIF + + !------------------------------------------------------------------------------------------------- + ! Calculate the influence of tower shadow if user specifies and we are downwind of the tower + !------------------------------------------------------------------------------------------------- + + IF ( P%TwrProps%TwrShadow ) THEN + + theta = ATAN2( InputPosition(2), InputPosition(1) ) ! angle between x-axis and line from tower to blade element + angle = ABS( theta - phi ) + + CALL mPi2Pi( angle ) ! angle difference between -pi and pi + angle = ABS(angle) !BJJ: SHOULDN'T THIS BE ABS(angle)? I'm adding it here.... + + IF ( angle <= PiBy2 ) THEN ! We are downwind of the tower in shadow territory + + width = SQRT ( Distance ) + + ! Calculate how far we are from the free-stream centerline + CenterDist = Distance * SIN ( angle ) ! bjj: non-negative because angle is non-negative (now) + + ! If above hub height apply shadow in arc above hub to maintain a continuous deficit function. Somewhat of a nacelle deficit. + IF ( ZGrnd > 0.0 ) THEN + CenterDist = SQRT( CenterDist**2 + ZGrnd**2 ) + END IF + + ! See if we are in the wake. If not, then no velocity deficit + + IF ( CenterDist < width ) THEN ! We are in the wake + + shadow = ( COS( PiBy2 * CenterDist / width ) )**2 * TwrCD_Station / width + WindXInf = 1.0 - shadow ! Overwrites the potential flow solution in the x direction only (BJJ: longitudinal? not x?) + + WindXInf = MAX( WindXInf, REAL(0.0, ReKi) ) ! Assume tower does not reverse flow direction + + END IF + + END IF ! angle <= PiBy2 + + END IF !TwrShadow + + + !------------------------------------------------------------------------------------------------- + ! Apply the tower influence to the input wind speeds + !------------------------------------------------------------------------------------------------- + + VX_wind = WindXInf*V_total + VY_wind = WindYInf*V_total + + ! Need to transpose these back to the global reference frame + VX = VX_wind * CosPhi - VY_wind * SinPhi + VY = VY_wind * CosPhi + VX_wind * SinPhi + + RETURN + +END SUBROUTINE GetTwrInfluence + +!==================================================================================================== +SUBROUTINE GetTwrSectProp ( P, m, ErrStat, ErrMess, & + InputPosition, VelHor, TwrElRad, TwrElCD ) +!SUBROUTINE GetTwrSectProp (InputPosition, VelHor, TwrElRad, TwrElCD) +! Returns the tower radius and CD for the vertical location +! of the element currently being evaluated for tower influence. +!==================================================================================================== + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + + ! Passed Variables: + REAL(ReKi), INTENT(IN) :: InputPosition(3) ! Location where tower properties are desired + REAL(ReKi), INTENT(IN) :: VelHor ! The horizontal wind speed, used to get Reynolds number, if necessary + REAL(ReKi), INTENT(OUT) :: TwrElRad ! Radius of the tower element + REAL(ReKi), INTENT(OUT) :: TwrElCD ! Drag coefficient of the tower element + + + ! Local Variables: + REAL(ReKi) :: P1 ! Interpolation weighting factor + REAL(ReKi) :: P2 ! Interpolation weighting factor + REAL(ReKi) :: TwrElCD1 ! Dummy variable for 2-D interpolation + REAL(ReKi) :: TwrElCD2 ! Dummy variable for 2-D interpolation + REAL(ReKi) :: TwrElHt ! Non-dimensional height of the tower element + REAL(ReKi) :: TwrElRe ! Reynold's # of the tower element + + INTEGER :: N1 ! Index position in table for interpolation + INTEGER :: N2 ! Index position in table for interpolation + INTEGER :: N1P1 ! Index position + 1 in table for interpolation + INTEGER :: N2P1 ! Index position + 1 in table for interpolation + + + ErrStat = ErrID_None + ErrMess = "" + + !------------------------------------------------------------------------------------------------- + ! Get the tower radius, TwrElRad, by interpolating into the TwrWid(:) array + !------------------------------------------------------------------------------------------------- + + TwrElHt = InputPosition(3) / P%Rotor%HH !!!!BJJ!!!! HH???? !MLB: It's the hub height. It really should be the tower height. + TwrElRad = 0.5*InterpBin( TwrElHt, p%TwrProps%TwrHtFr, p%TwrProps%TwrWid, N2, p%TwrProps%NTwrHt ) + + !------------------------------------------------------------------------------------------------- + ! Get the section CD, TwrElCD, by interpolating into the TwrCD(:,:) array + !------------------------------------------------------------------------------------------------- + + IF ( p%TwrProps%NTwrRe == 1 ) THEN ! There is only one Re row + + IF ( p%TwrProps%NTwrCD == 1 ) THEN ! There is only one CD column + TwrElCD = p%TwrProps%TwrCD(1,1) + ELSE IF ( p%TwrProps%NTwrHt == 1 ) THEN ! There is more than one column of CD, but only one used + TwrElCD = p%TwrProps%TwrCD(1,p%TwrProps%NTwrCDCol(1)) + ELSE ! Interpolate; this will be the same Indx as before... + TwrElCD = InterpStp( TwrElHt, p%TwrProps%TwrHtFr, p%TwrProps%TwrCD(1,:), N2, p%TwrProps%NTwrHt ) + END IF + + ELSE ! There are multiple Re rows + + TwrElRe = GetReynolds( VelHor, 2.0_ReKi*TwrElRad, P%Wind%KinVisc ) + + IF ( p%TwrProps%NTwrCD == 1 ) THEN ! There is only one CD column + TwrElCD = InterpBin( TwrElRe, p%TwrProps%TwrRe, p%TwrProps%TwrCD(:,1), N1, p%TwrProps%NTwrRe ) + ELSE IF ( p%TwrProps%NTwrHt == 1 ) THEN ! Interpolate over Re only + TwrElCD = InterpBin( TwrElRe, p%TwrProps%TwrRe, p%TwrProps%TwrCD(:,p%TwrProps%NTwrCDCol(1)), N1, p%TwrProps%NTwrRe ) + ELSE ! A 2-D interpolation is needed + CALL LocateBin( TwrElRe, p%TwrProps%TwrRe, N1, p%TwrProps%NTwrRe ) + + ! Let's use nearest-neighbor extrapolation with bi-linear interpolation: + + N1 = MIN( MAX( N1, 1 ), p%TwrProps%NTwrRe-1 ) + N1P1 = N1+1 + + P1 = MIN( MAX( (TwrElRe - p%TwrProps%TwrRe(N1)) / (p%TwrProps%TwrRe(N1P1) - p%TwrProps%TwrRe(N1)) , REAL(0.0, ReKi) ), REAL(1.0, ReKi) ) + + N2P1 = N2 + 1 + P2 = MIN( MAX( (TwrElHt - p%TwrProps%TwrHtFr(N2)) / (p%TwrProps%TwrHtFr(N2P1) - p%TwrProps%TwrHtFr(N2)), REAL(0.0, ReKi) ), REAL(1.0, ReKi) ) + + + TwrElCD1 = p%TwrProps%TwrCD(N1,N2 ) + P1 * ( p%TwrProps%TwrCD(N1P1,N2 ) - p%TwrProps%TwrCD(N1,N2 ) ) + TwrElCD2 = p%TwrProps%TwrCD(N1,N2P1) + P1 * ( p%TwrProps%TwrCD(N1P1,N2P1) - p%TwrProps%TwrCD(N1,N2P1) ) + + + TwrElCD = TwrElCD1 + P2 * ( TwrElCD2 - TwrElCD1 ) + END IF + + END IF + + +RETURN +END SUBROUTINE GetTwrSectProp + + +!==================================================================================================== +FUNCTION AD_WindVelocityWithDisturbance( Time, u, p, x, xd, z, m, y, ErrStat, ErrMsg, & + InputPosition, InputVelocity ) +! InputPosition, TShadC1, TShadC2, PJM_Version ) +!FUNCTION AD_WindVelocityWithDisturbance( InputPosition, TShadC1, TShadC2, PJM_Version, LeStat ) +! This function computes the (dimensional) wind velocity components at the location InputPosition +! in the inertial frame of reference, including any tower shadow defecit. +! ** Formerly SUBROUTINE VEL and later SUBROUTINE VWrel2G( VNRotor2, At_Hub ) ** +!---------------------------------------------------------------------------------------------------- + + + IMPLICIT NONE + + ! Passed Variables: + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(AD14_InputType), INTENT(IN ) :: u ! Inputs at Time + TYPE(AD14_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at Time + TYPE(AD14_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at Time + TYPE(AD14_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at Time + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi),INTENT(IN) :: InputPosition(3) ! + REAL(ReKi),INTENT(IN) :: InputVelocity(3) ! undisturbed velocity + + ! REAL(ReKi),INTENT(IN) :: TShadC1 +! REAL(ReKi),INTENT(IN) :: TShadC2 +! LOGICAL,INTENT(IN) :: PJM_Version + + ! function definition + + REAL(ReKi) :: AD_WindVelocityWithDisturbance(3) + + ! Local variables + + REAL(ReKi) :: angle ! absolute difference between theta and phi + REAL(ReKi) :: dist ! distance from blade element to wake centerline + REAL(ReKi) :: phi ! angle between x-axis and instantaneous horizontal wind direction + REAL(ReKi) :: RADIUS ! horizontal distance from tower to blade element ** BJJ NOTE: in actuality, it's the distance from the undeflected tower centerline, not the actual tower + REAL(ReKi) :: ROOTR ! SQRT(radius) + REAL(ReKi) :: SHADOW + REAL(ReKi) :: TEMP + REAL(ReKi) :: theta ! Angle between x-axis and line from tower to blade element + REAL(ReKi) :: width ! half width of the wake after accounting for wake expansion proportional to square root of RADIUS + +! INTEGER :: Sttus + +! INTEGER :: TmpErrStat +! CHARACTER(ErrMsgLen) :: TmpErrMsg + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get the undisturbed velocity + + AD_WindVelocityWithDisturbance(:) = InputVelocity + + ! Add the tower influence to the undisturbed velocity. + + IF ( p%TwrProps%PJM_Version ) THEN + + CALL GetTwrInfluence ( P, m, ErrStat, ErrMsg, & + AD_WindVelocityWithDisturbance(1), AD_WindVelocityWithDisturbance(2), InputPosition(:) ) + + ELSE !Old tower version + + ! Apply tower shadow if the blade element is in the wake + + IF ( p%TwrProps%TShadC2 > 0.0 ) THEN ! Perform calculations only if the wake strength is positive + + ! Bypass tower shadow for zero horizontal wind, check U-component first to save time. + + IF ( AD_WindVelocityWithDisturbance(1) /= 0.0 .OR. AD_WindVelocityWithDisturbance(2) /= 0.0 ) THEN + + phi = ATAN2( AD_WindVelocityWithDisturbance(2), AD_WindVelocityWithDisturbance(1) ) ! angle between x-axis and instantaneous horizontal wind direction + theta = ATAN2( InputPosition(2), InputPosition(1) ) ! angle between x-axis and line from tower to blade element + angle = ABS( theta - phi ) + + CALL MPi2Pi( angle ) + angle = ABS( angle ) + + IF ( angle <= PiBy2 ) THEN ! Skip cases where we are upwind of the tower -- bjj: DOES THIS ACTUALLY WORK? WHAT ABOUT + + radius = SQRT( InputPosition(1)**2 + InputPosition(2)**2 ) ! bjj: shouldn't this be relative to the hub position? + + RootR = SQRT( radius ) + width = p%TwrProps%TShadC1 * RootR ! half width of the wake after accounting for wake expansion proportional to square root of RADIUS + + IF ( width > 0 ) THEN ! Skip cases with zero width or radius so we don't divide by zero + + dist = radius * SIN( angle ) ! distance from blade element to wake centerline + IF ( InputPosition(3) > p%Rotor%HH ) THEN ! Apply shadow in arc above hub to maintain a continuous deficit function. Somewhat of a nacelle deficit. + dist = SQRT( dist**2 + (InputPosition(3)-p%Rotor%HH)**2 ) !bjj: I think this should use hub position, not HH + END IF + + IF ( width > dist ) THEN ! There is velocity deficit in the wake only. + temp = COS ( PiBy2 * dist/width ) + shadow = p%TwrProps%TShadC2/RootR * temp * temp + + ! Adjust only the horizontal components; vertical wind is not changed + + AD_WindVelocityWithDisturbance(1:2) = AD_WindVelocityWithDisturbance(1:2) * ( 1. - shadow ) + + END IF ! width > dist + END IF ! width > 0 + + END IF ! angle <= PiBy2 + + END IF !AD_WindVelocityWithDisturbance(1) /= 0.0 .OR. AD_WindVelocityWithDisturbance(2) /= 0.0 + END IF ! TShadC2 > 0.0 + + END IF + +RETURN + +END FUNCTION AD_WindVelocityWithDisturbance + +!==================================================================================================== +SUBROUTINE DiskVel ( Time, P, m, AvgInfVel, ErrStat, ErrMess ) +! SUBROUTINE DiskVel + ! calculates the mean velocities relative to the rotor disk + ! calls routine to get wind velocity at a specified location + ! + ! Updated on 08/12/97 xyz-direction changed + ! Combined VELD and GETSKEW 04/24/01 + ! Updated 12/1/09 to use new inflow module; WindInf_ADhack_diskVel MUST be replaced! + ! ******************************************** + IMPLICIT NONE + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: Time + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + REAL(ReKi), INTENT(IN) :: AvgInfVel(3) !some sort of averaged wind speed (currently depends on wind file type) + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + + REAL(ReKi) :: Vinplane + REAL(ReKi) :: VXY + + ErrStat = ErrID_None + ErrMess = "" + +!Position = (/0.0_ReKi, 0.0_ReKi, P%Rotor%HH /) +!AvgInfVel(:) = WindInf_ADhack_diskVel( REAL(Time, ReKi), Position, ErrStat ) + + +VXY = AvgInfVel(1) * m%Rotor%CYaw - AvgInfVel(2) * m%Rotor%SYaw + + ! Mean velocities in rotor disk coord. Includes yaw rate. + ! X = Normal to plane, parallel to axis of rotation DOWNWIND + ! Y = Inplane, horizontal to left (looking downwind) + ! Z = Inplane, vertical up + +m%Wind%VROTORX = VXY * m%Rotor%CTILT + AvgInfVel(3) * m%Rotor%STILT + +m%Wind%VROTORY = AvgInfVel(1) * m%Rotor%SYaw + AvgInfVel(2) * m%Rotor%CYaw + m%Rotor%YAWVEL + +m%Wind%VROTORZ = -1.* VXY * m%Rotor%STILT + AvgInfVel(3) * m%Rotor%CTILT + + ! Skewed wake correction not needed for GDW +IF (.NOT. P%DYNINFL) THEN + ! Set SKEW flag and assign values to related parameters + ! used in the skewed wake correction. + + ! Vinplane is the resultant in-plane velocity + Vinplane = SQRT( m%Wind%VROTORY * m%Wind%VROTORY + m%Wind%VROTORZ * m%Wind%VROTORZ ) + + ! SKEW is TRUE if there is a cross flow, FALSE otherwise. + IF ( Vinplane >= 1.0E-3 ) THEN + m%SKEW = .TRUE. + m%Wind%SDEL = m%Wind%VROTORY/Vinplane + m%Wind%CDEL = -m%Wind%VROTORZ/Vinplane + m%Wind%ANGFLW = ATAN2( ABS( m%Wind%VROTORX - m%Rotor%AVGINFL ), Vinplane ) + ELSE + m%SKEW = .FALSE. + ENDIF + +ENDIF + + + +RETURN +END SUBROUTINE DiskVel +!======================================================================= +SUBROUTINE TwrAeroLoads ( p, Node, NodeDCMGbl, NodeVelGbl, NodeWindVelGbl, NodeFrcGbl ) + + + ! This routine calcualtes the aeroynamic loads of all tower nodes above the mean sea level. + ! It doesn't worry about whether or not a node is below water. The aero loads will be far less than the hydro loads. + + IMPLICIT NONE + + + ! Arguments: + + REAL(R8Ki), INTENT(IN ) :: NodeDCMGbl (3,3) ! The direction-cosine matrix used to transform from the global system to the node system. + REAL(ReKi), INTENT(OUT) :: NodeFrcGbl (3) ! The forces per unit length at the current tower element. + REAL(ReKi), INTENT(IN ) :: NodeVelGbl (3) ! The 3 components of the translational velocity at the node in the global system. + REAL(ReKi), INTENT(IN ) :: NodeWindVelGbl(3) ! The 3 components of the wind at the node in the global system. + + INTEGER, INTENT(IN ) :: Node ! Tower node index. + + TYPE(AD14_ParameterType), INTENT(IN) :: p ! The AeroDyn parameters. + + + ! Local variables. + + REAL(ReKi) :: NodeFrcLcl (3) ! The forces per unit length on the tower node in the local system. +! REAL(ReKi) :: NodeLocTwr (3) ! The location of the node in the tower coordinate system. This is used to get the tower section properties. + REAL(ReKi) :: NodeVelRelGbl (3) ! The relative wind velocity in the global reference frame.. + REAL(ReKi) :: NodeVelRelLcl (3) ! The relative wind velocity in the local reference frame.. + REAL(ReKi) :: RelNmlWndSpd ! The relative wind speed normal to the tower axis. sqrt(u^2+v^2) +! REAL(ReKi) :: TwrFrcLcl (3) ! The drag coefficient corresponding to the computed Reynolds Number. + REAL(ReKi) :: TwrNodeCd ! The drag coefficient corresponding to the computed Reynolds Number. + REAL(ReKi) :: TwrNodeRe ! The Reynolds Number computed using the wind speed normal to the tower axis. +! REAL(ReKi) :: WndDirLcl ! The wind direction relative to the local node coordinate system using only the u and v components. + + INTEGER(IntKi) :: IndLo ! The index pointing to the lower of the two points bounding an interpolated value. + + + + ! Calculate the relative local wind velocity. + + NodeVelRelGbl(:) = NodeWindVelGbl(:) - NodeVelGbl(:) + + + ! Transform the relative velocity into the node coordinate system. + + NodeVelRelLcl(:) = MATMUL( NodeDCMGbl, NodeVelRelGbl ) + + + ! Compute the relative normal wind speed and its square. + + RelNmlWndSpd = SQRT( DOT_PRODUCT( NodeVelRelLcl(1:2), NodeVelRelLcl(1:2) ) ) + + + ! Compute the Reynolds Number. Because interpolation is expensive, we will compute the magnitude of the drag and resolve it into components. + + TwrNodeRe = GetReynolds( RelNmlWndSpd, p%TwrProps%TwrNodeWidth(Node), p%Wind%KinVisc ) + + + ! Get the local value of the drag coefficient. + + IndLo = 1 + +!MLB: Why have two different calls? Can't the second accommodate the first? Is the first method more efficient than the second method if there is only one Cd column? +!MLB: This logic was stolen from AeroSubs.f90\GetTwrSectProp(). + + IF ( p%TwrProps%NTwrCD == 1 ) THEN ! There is only one CD column + TwrNodeCd = InterpBin( TwrNodeRe, p%TwrProps%TwrRe, p%TwrProps%TwrCD(:,1), IndLo, p%TwrProps%NTwrRe ) + ELSE IF ( p%TwrProps%NTwrHt == 1 ) THEN ! Interpolate over Re only + TwrNodeCd = InterpBin( TwrNodeRe, p%TwrProps%TwrRe, p%TwrProps%TwrCD(:,p%TwrProps%NTwrCDCol(1)), IndLo, p%TwrProps%NTwrRe ) !MLB Why have two different calls? Can't the second accommodate the first? + END IF + + + ! Compute the forces on the tower in the local system. + + NodeFrcLcl(1) = 0.5*TwrNodeCd*p%Wind%Rho*p%TwrProps%TwrNodeWidth(Node)*RelNmlWndSpd*NodeVelRelLcl(1) + NodeFrcLcl(2) = 0.5*TwrNodeCd*p%Wind%Rho*p%TwrProps%TwrNodeWidth(Node)*RelNmlWndSpd*NodeVelRelLcl(2) + NodeFrcLcl(3) = 0.0 + + + ! Convert the force to global coordinates. + + NodeFrcGbl = MATMUL( TRANSPOSE( NodeDCMGbl ), NodeFrcLcl ) + + +! Temporarily set the returned force to zero until we figure why the forces are not being applied correctly. +!NodeFrcGbl(:) = 0.0 + + + RETURN + +END SUBROUTINE TwrAeroLoads +!======================================================================= + + + ! **************************************** + SUBROUTINE VNMOD( P, m, ErrStat, ErrMess, & + J, IBlade, RLOCAL, PSI ) +! SUBROUTINE VNMOD( J, IBlade, RLOCAL, PSI ) + ! applies the skewed wake correction + ! to the axial induction factor A. + ! **************************************** +!USE Blade +!USE Element +!USE Wind + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + + REAL(ReKi),INTENT(IN) :: PSI + REAL(ReKi),INTENT(IN) :: RLOCAL + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + + ! Local Variables: + + REAL(ReKi) :: BB + REAL(ReKi) :: SANG + + + ErrStat = ErrID_None + ErrMess = "" + +SANG = SIN( m%Wind%ANGFLW ) +BB = 0.7363 * SQRT( ( 1. - SANG )/(1. + SANG) ) + +m%Element%A(J,IBLADE) = m%Element%A(J,IBLADE) * ( 1. + 2. * RLOCAL/P%Blade%R * BB * & + ( m%Wind%SDEL * SIN( PSI ) + m%Wind%CDEL * COS( PSI ) ) ) + + + +RETURN +END SUBROUTINE VNMOD + + + ! ********************************************************** + SUBROUTINE BEDINIT( P, m, ErrStat, ErrMess, & + J, IBlade, ALPHA ) +! SUBROUTINE BEDINIT( J, IBlade, ALPHA ) + ! calculates initial values of Beddoes 'f' arrays + ! ********************************************************** +!USE Airfoil +!USE Beddoes + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + REAL(ReKi),INTENT(INOUT) :: ALPHA + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + + + ! Local Variables: + + REAL(ReKi) :: AOL1 + REAL(ReKi) :: CNA1 + REAL(ReKi) :: FSPA + REAL(ReKi) :: FSPB + REAL(ReKi) :: FSPCA + REAL(ReKi) :: FSPCB + REAL(ReKi) :: P0 + REAL(ReKi) :: P1 + REAL(ReKi) :: P2 + REAL(ReKi) :: SRFP + REAL(ReKi) :: TEMP + + INTEGER :: I + INTEGER :: I1 + INTEGER :: I1P1 + INTEGER :: I2 + INTEGER :: I2P1 + INTEGER :: N + INTEGER :: NP1 + + ErrStat = ErrID_None + ErrMess = "" + +m%Beddoes%ANE(J,IBLADE) = ALPHA +m%Beddoes%AFE(J,IBLADE) = ALPHA + +I = P%AirFoil%NFOIL(J) + +IF ( P%AirFoil%NTables(I) > 1 ) THEN + m%AirFoil%MulTabLoc = MIN( MAX( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1) ), P%AirFoil%MulTabMet(I,P%AirFoil%NTables(I)) ) + CALL LocateBin( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1:P%AirFoil%NTables(I)), N, P%AirFoil%NTables(I) ) + + IF (N == 0 ) THEN + CNA1 = m%Beddoes%CNA(I,1) + AOL1 = m%Beddoes%AOL(I,1) + ELSE IF( N == P%AirFoil%NTables(I) ) THEN + CNA1 = m%Beddoes%CNA(I,N) + AOL1 = m%Beddoes%AOL(I,N) + ELSE + NP1 = N+1 + P0 = (m%AirFoil%MulTabLoc-P%AirFoil%MulTabMet(I,N))/(P%AirFoil%MulTabMet(I,NP1)-P%AirFoil%MulTabMet(I,N)) + CNA1 = m%Beddoes%CNA(I,N) + P0 * ( m%Beddoes%CNA(I,NP1) - m%Beddoes%CNA(I,N) ) + AOL1 = m%Beddoes%AOL(I,N) + P0 * ( m%Beddoes%AOL(I,NP1) - m%Beddoes%AOL(I,N) ) + END IF +ELSE + CNA1 = m%Beddoes%CNA(I,1) + AOL1 = m%Beddoes%AOL(I,1) +ENDIF + +m%Beddoes%CNPOT(J,IBLADE) = CNA1 * (ALPHA - AOL1) +m%Beddoes%CNP(J,IBLADE) = m%Beddoes%CNPOT(J,IBLADE) + + +ALPHA = MIN( MAX( ALPHA, m%AirFoil%AL(I,1) ), m%AirFoil%AL(I,P%AirFoil%NLIFT(I)) ) +CALL LocateBin( ALPHA, m%AirFoil%AL(I,1:P%AirFoil%NLIFT(I)), I1, P%AirFoil%NLIFT(I) ) + +IF ( I1 == 0 ) THEN + I1 = 1 + I1P1 = 2 + P1 = 0.0 +ELSEIF ( I1 == P%AirFoil%NLIFT(I) ) THEN + I1P1 = I1 + I1 = I1 - 1 + P1 = 1.0 +ELSE + I1P1 = I1 + 1 + !bjj: check for division by zero? + P1 = ( m%AirFoil%AL(I,I1) - ALPHA ) / ( m%AirFoil%AL(I,I1) - m%AirFoil%AL(I,I1P1) ) +ENDIF + + +IF ( P%AirFoil%NTables(I) > 1 ) THEN + + ! Locate the multiple airfoil table position in the table + + + m%AirFoil%MulTabLoc = MIN( MAX( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1) ), P%AirFoil%MulTabMet(I,P%AirFoil%NTables(I)) ) + CALL LocateBin( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1:P%AirFoil%NTables(I)), I2, P%AirFoil%NTables(I) ) + + IF ( I2 == 0 ) THEN + I2P1 = 2 + I2 = 1 + P2 = 0.0 + ELSE IF( I2 == P%AirFoil%NTables(I) ) THEN + I2P1 = I2 + I2 = I2 - 1 + P2 = 1.0 + ELSE + I2P1 = I2 + 1 + P2 = (m%AirFoil%MulTabLoc-P%AirFoil%MulTabMet(I,I2))/(P%AirFoil%MulTabMet(I,I2P1)-P%AirFoil%MulTabMet(I,I2)) + ENDIF + + ! Interpolate the F-table values + + FSPB = m%Beddoes%FTB( I,I1,I2P1) - (m%Beddoes%FTB( I,I1,I2P1) - m%Beddoes%FTB( I,I1P1,I2P1))*P1 + FSPCB = m%Beddoes%FTBC(I,I1,I2P1) - (m%Beddoes%FTBC(I,I1,I2P1) - m%Beddoes%FTBC(I,I1P1,I2P1))*P1 + FSPA = m%Beddoes%FTB( I,I1,I2 ) - (m%Beddoes%FTB( I,I1,I2 ) - m%Beddoes%FTB( I,I1P1,I2 ))*P1 + FSPCA = m%Beddoes%FTBC(I,I1,I2 ) - (m%Beddoes%FTBC(I,I1,I2 ) - m%Beddoes%FTBC(I,I1P1,I2 ))*P1 + + m%Beddoes%FSP( J,IBLADE) = FSPA + P2 * ( FSPB - FSPA ) + m%Beddoes%FSPC(J,IBLADE) = FSPCA + P2 * ( FSPCB - FSPCA ) + +ELSE + + m%Beddoes%FSP( J,IBLADE) = m%Beddoes%FTB( I,I1,1) - ( m%Beddoes%FTB( I,I1,1) - m%Beddoes%FTB( I,I1P1,1) )*P1 + m%Beddoes%FSPC(J,IBLADE) = m%Beddoes%FTBC(I,I1,1) - ( m%Beddoes%FTBC(I,I1,1) - m%Beddoes%FTBC(I,I1P1,1) )*P1 + +ENDIF + +IF ( ABS( m%Beddoes%AFE(J,IBLADE) - AOL1 ) < 1.E-10 ) THEN + + m%Beddoes%FSP(J,IBLADE) = 1.0 + m%Beddoes%FSPC(J,IBLADE) = 1.0 + +ELSE + + TEMP = 2.*SQRT(ABS(m%Beddoes%FSP(J,IBLADE)/(m%Beddoes%AFE(J,IBLADE)-AOL1)))-1. + m%Beddoes%FSP(J,IBLADE) = TEMP * TEMP * SIGN ( 1.0_ReKi, TEMP ) + IF ( m%Beddoes%FSP(J,IBLADE) > 1.0 ) m%Beddoes%FSP(J,IBLADE) = 1.0 + IF ( m%Beddoes%FSP(J,IBLADE) < -1.0 ) m%Beddoes%FSP(J,IBLADE) = -1.0 + + IF ( ABS( m%Beddoes%AFE(J,IBLADE) ) < 1.E-10 ) THEN + m%Beddoes%FSPC(J,IBLADE) = 1.0 + ELSE + TEMP = m%Beddoes%FSPC(J,IBLADE)/((m%Beddoes%AFE(J,IBLADE)-AOL1)*m%Beddoes%AFE(J,IBLADE)) + m%Beddoes%FSPC(J,IBLADE) = TEMP * TEMP * SIGN ( 1.0_ReKi, TEMP ) + IF ( m%Beddoes%FSPC(J,IBLADE) > 1.0 ) m%Beddoes%FSPC(J,IBLADE) = 1.0 + IF ( m%Beddoes%FSPC(J,IBLADE) < -1.0 ) m%Beddoes%FSPC(J,IBLADE) = -1.0 + ENDIF + +ENDIF + +SRFP = SQRT( ABS( m%Beddoes%FSP(J,IBLADE) ) ) * SIGN( 1.0_ReKi, m%Beddoes%FSP(J,IBLADE) ) + 1. +m%Beddoes%FK = 0.25 * SRFP * SRFP +m%Beddoes%CVN(J,IBLADE) = m%Beddoes%CNPOT(J,IBLADE) * ( 1. - m%Beddoes%FK ) + +RETURN +END SUBROUTINE BEDINIT + + + ! ***************************************************** + SUBROUTINE BedUpdate( m ) + ! Update old Beddoes parameters at new time step + ! ***************************************************** +!USE Beddoes + IMPLICIT NONE + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + +m%Beddoes%ANE1 = m%Beddoes%ANE +m%Beddoes%ADOT1 = m%Beddoes%ADOT +m%Beddoes%OLDXN = m%Beddoes%XN +m%Beddoes%OLDYN = m%Beddoes%YN +m%Beddoes%CNPOT1 = m%Beddoes%CNPOT +m%Beddoes%OLDDPP = m%Beddoes%DPP +m%Beddoes%FSP1 = m%Beddoes%FSP +m%Beddoes%FSPC1 = m%Beddoes%FSPC +m%Beddoes%OLDTAU = m%Beddoes%TAU +m%Beddoes%OLDDF = m%Beddoes%DF +m%Beddoes%OLDDFC = m%Beddoes%DFC +m%Beddoes%OLDDN = m%Beddoes%DN +m%Beddoes%OLDCNV = m%Beddoes%CNV +m%Beddoes%CVN1 = m%Beddoes%CVN +m%Beddoes%CNP1 = m%Beddoes%CNP +m%Beddoes%CNPD1 = m%Beddoes%CNPD +m%Beddoes%OLDSEP = m%Beddoes%BEDSEP +m%Beddoes%QX1 = m%Beddoes%QX +m%Beddoes%OLDDQ = m%Beddoes%DQ +m%Beddoes%AFE1 = m%Beddoes%AFE +m%Beddoes%DQP1 = m%Beddoes%DQP +m%Beddoes%DFAFE1 = m%Beddoes%DFAFE + + +RETURN +END SUBROUTINE BedUpdate + + + ! ***************************************************** + SUBROUTINE BEDDAT ( P, x, xd, z, m, y, ErrStat, ErrMess ) + ! USED TO INPUT PARAMETERS FOR THE + ! Beddoes DYNAMIC STALL MODEL + ! ***************************************************** +!USE Airfoil +!USE Beddoes +!USE Switch + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Local Variables: + + REAL(ReKi) :: ETA + REAL(ReKi) :: CA + REAL(ReKi) :: SA + + INTEGER :: I + INTEGER :: J + INTEGER :: K + + + ErrStat = ErrID_None + ErrMess = "" + + ! Empirical constants for the Beddoes model + + ! TVL = Non-dimensional time of transit for the + ! vortex moving across the airfoil surface + ! TP = Time constant for pressure lag + ! TV = Time constant for strength of shed vortex + ! TF = Time constant applied to location of + ! the separation point + ! AS = Speed of sound for Mach number calculation + +P%Beddoes%TVL = 11.0 +P%Beddoes%TP = 1.7 +P%Beddoes%TV = 6.0 +P%Beddoes%TF = 3.0 +ETA = .99 !bjj: this doesn't seem to be used for anything.... + +IF ( P%SIUNIT ) THEN + ! SI UNITS--m/sec + P%Beddoes%AS = 335. +ELSE + ! ENGLISH UNITS--ft/sec + P%Beddoes%AS = 1100. +ENDIF + + ! Generate table of F values from airfoil data table + +DO J =1,P%AirFoil%NUMFOIL + DO K =1,P%AirFoil%NTables(J) + DO I = 1, P%AirFoil%NLIFT(J) + + CA = COS( m%AirFoil%AL(J,I) ) + SA = SIN( m%AirFoil%AL(J,I) ) + m%Beddoes%CN = m%AirFoil%CL(J,I,K) * CA + ( m%AirFoil%CD(J,I,K) - m%Beddoes%CDO(J,K) ) * SA + m%Beddoes%CC = m%AirFoil%CL(J,I,K) * SA - ( m%AirFoil%CD(J,I,K) - m%Beddoes%CDO(J,K) ) * CA + + IF ( ABS( m%Beddoes%CNA(J,K) ) .GT. 1.E-6 ) THEN + m%Beddoes%FTB(J,I,K) = m%Beddoes%CN / m%Beddoes%CNA(J,K) + m%Beddoes%FTBC(J,I,K) = m%Beddoes%CC / m%Beddoes%CNA(J,K) + ELSE + m%Beddoes%FTB(J,I,K) = 1.0 + m%Beddoes%FTBC(J,I,K) = 1.0 + ENDIF + + END DO !I + END DO !K +END DO !J + +m%Beddoes%VOR = .FALSE. +m%Beddoes%SHIFT = .FALSE. + +m%Beddoes%BEDSEP = .FALSE. +m%Beddoes%ANE1 = 0. +m%Beddoes%OLDCNV = 0. +m%Beddoes%CVN1 = 0. +m%Beddoes%CNPOT1 = 0. +m%Beddoes%CNP1 = 0. +m%Beddoes%CNPD1 = 0. +m%Beddoes%OLDDF = 0. +m%Beddoes%OLDDFC = 0. +m%Beddoes%OLDDPP = 0. +m%Beddoes%FSP1 = 0. +m%Beddoes%FSPC1 = 0. +m%Beddoes%TAU = 0. +m%Beddoes%OLDTAU = 0. +m%Beddoes%OLDXN = 0. +m%Beddoes%OLDYN = 0. + +RETURN +END SUBROUTINE BEDDAT + + + ! ****************************************************** + SUBROUTINE BeddoesModel( P, m, ErrStat, ErrMess, & + W2, J, IBlade, ALPHA, CLA, CDA ,CMA ) + ! uses the Beddoes dynamic stall model + ! the routine is entered with an angle of attack + ! and returns CL, CD, and CM. + ! This routine is used regardless of whether the element + ! is actually in dynamic stall state. + ! + ! VARIABLES: + ! W2 = Relative velocity squared over blade element + ! J = Index which identifies the blade element + ! ALPHA = Angle of attack in radians + ! CLA = Lift coeff. which is calculated by the routine + ! CDA = Drag coeff. which is calculated by the routine + ! CMA = Moment coeff. which is calculated by the routine + ! ****************************************************** + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + REAL(ReKi),INTENT(IN) :: ALPHA + REAL(ReKi),INTENT(OUT) :: CDA + REAL(ReKi),INTENT(OUT) :: CLA + REAL(ReKi),INTENT(OUT) :: CMA + REAL(ReKi),INTENT(IN) :: W2 + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + + ! Local Variables: + + REAL(ReKi) :: AE + REAL(ReKi) :: AOD1 + REAL(ReKi) :: AOL1 + REAL(ReKi) :: CA + REAL(ReKi) :: CDO1 + REAL(ReKi) :: CNA1 + REAL(ReKi) :: CNS1 + REAL(ReKi) :: CNSL1 + REAL(ReKi) :: P1 + REAL(ReKi) :: SA + REAL(ReKi) :: VREL + + INTEGER :: I + INTEGER :: N + INTEGER :: NP1 + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + ErrStat = ErrID_None + ErrMess = "" + + ! Check to see if element has multiple airfoil tables, then interpolate values + ! of constants based on the current location. + +I = P%AirFoil%NFOIL(J) + +IF (P%AirFoil%NTables(I) > 1)THEN + + m%AirFoil%MulTabLoc = MIN( MAX( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1) ), P%AirFoil%MulTabMet(I,P%AirFoil%NTables(I)) ) + CALL LocateBin( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1:P%AirFoil%NTables(I)), N, P%AirFoil%NTables(I) ) + + IF ( N == 0 ) THEN + CNA1 = m%Beddoes%CNA( I,1) + AOL1 = m%Beddoes%AOL( I,1) + CNS1 = m%Beddoes%CNS( I,1) + CNSL1 = m%Beddoes%CNSL(I,1) + AOD1 = m%Beddoes%AOD( I,1) + CDO1 = m%Beddoes%CDO( I,1) + ELSE IF ( N == P%AirFoil%NTables(I) ) THEN + CNA1 = m%Beddoes%CNA( I,N) + AOL1 = m%Beddoes%AOL( I,N) + CNS1 = m%Beddoes%CNS( I,N) + CNSL1 = m%Beddoes%CNSL(I,N) + AOD1 = m%Beddoes%AOD( I,N) + CDO1 = m%Beddoes%CDO( I,N) + ELSE + NP1 = N+1 + !bjj: check for division by zero? + P1 = (m%AirFoil%MulTabLoc-P%AirFoil%MulTabMet(I,N))/(P%AirFoil%MulTabMet(I,NP1)-P%AirFoil%MulTabMet(I,N)) + + CNA1 = m%Beddoes%CNA(I,N) + P1 * ( m%Beddoes%CNA(I,NP1) - m%Beddoes%CNA(I,N) ) + AOL1 = m%Beddoes%AOL(I,N) + P1 * ( m%Beddoes%AOL(I,NP1) - m%Beddoes%AOL(I,N) ) + CNS1 = m%Beddoes%CNS(I,N) + P1 * ( m%Beddoes%CNS(I,NP1) - m%Beddoes%CNS(I,N) ) + CNSL1 = m%Beddoes%CNSL(I,N)+ P1 * ( m%Beddoes%CNSL(I,NP1)- m%Beddoes%CNSL(I,N)) + AOD1 = m%Beddoes%AOD(I,N) + P1 * ( m%Beddoes%AOD(I,NP1) - m%Beddoes%AOD(I,N) ) + CDO1 = m%Beddoes%CDO(I,N) + P1 * ( m%Beddoes%CDO(I,NP1) - m%Beddoes%CDO(I,N) ) + END IF + +ELSE + CNA1 = m%Beddoes%CNA(I,1) + AOL1 = m%Beddoes%AOL(I,1) + CNS1 = m%Beddoes%CNS(I,1) + CNSL1 = m%Beddoes%CNSL(I,1) + AOD1 = m%Beddoes%AOD(I,1) + CDO1 = m%Beddoes%CDO(I,1) +ENDIF + + ! Jump back if lift-curve slope is zero + +IF ( EqualRealNos(CNA1, 0.0_ReKi) ) THEN + CLA = 0.0 + CDA = CDO1 + CMA = 0.0 + RETURN +ENDIF + +m%Beddoes%AN = ALPHA +VREL = SQRT( W2 ) + +CALL ATTACH( P, m, ErrStatLcl, ErrMessLcl, VREL, J, IBlade, CNA1, AOL1, AE ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'BeddoesModel' ) + IF (ErrStat >= AbortErrLev) RETURN + + +CALL SEPAR( P, m, ErrStatLcl, ErrMessLcl, P%AirFoil%NLIFT(I), J, IBlade, I, CNA1, AOL1, CNS1, CNSL1 ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'BeddoesModel' ) + IF (ErrStat >= AbortErrLev) RETURN + +CALL VORTEX( P, m, ErrStatLcl, ErrMessLcl, J, IBlade, AE ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'BeddoesModel' ) + IF (ErrStat >= AbortErrLev) RETURN + +CA = COS( m%Beddoes%AN ) +SA = SIN( m%Beddoes%AN ) +CLA = m%Beddoes%CN * CA + m%Beddoes%CC * SA +CDA = m%Beddoes%CN * SA - m%Beddoes%CC * CA + CDO1 +CMA = m%AirFoil%PMC + +RETURN +END SUBROUTINE BeddoesModel + + + ! ****************************************************** + SUBROUTINE ATTACH( P, m, ErrStat, ErrMess, & + VREL, J, IBlade, CNA1, AOL1, AE ) + ! PART OF THE Beddoes DYNAMIC STALL MODEL. + ! ****************************************************** + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + REAL(ReKi), INTENT( OUT) :: AE + REAL(ReKi), INTENT(IN) :: AOL1 + REAL(ReKi), INTENT(IN) :: CNA1 + REAL(ReKi), INTENT(IN) :: VREL + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + + ! Local Variables: + + REAL(ReKi) :: B2 + REAL(ReKi) :: BS + REAL(ReKi) :: CNI + REAL(ReKi) :: CNQ + REAL(ReKi) :: CO + REAL(ReKi) :: DA + REAL(ReKi) :: PRP + REAL(ReKi) :: X0 + REAL(ReKi) :: XKA + REAL(ReKi) :: XM + + + ErrStat = ErrID_None + ErrMess = "" + +IF ( ABS( m%Beddoes%AN ) <= PIBY2 ) THEN + m%Beddoes%ANE(J,IBLADE) = m%Beddoes%AN +ELSEIF ( m%Beddoes%AN > PiBy2 ) THEN + m%Beddoes%ANE(J,IBLADE) = PI - m%Beddoes%AN +ELSE + m%Beddoes%ANE(J,IBLADE) = - PI - m%Beddoes%AN +ENDIF + + +XM = VREL / p%Beddoes%AS + + ! Check to see that the element is not supersonic +IF ( .NOT. m%SuperSonic .AND. XM >= 1.0 ) THEN + XM = 0.7 + m%SuperSonic = .TRUE. + ErrMess = 'ATTACH: Blade #'//TRIM(Int2LStr(IBLADE))//' element #'//TRIM(Int2LStr(J))//' is supersonic! '//& + ' Other elements are likely supersonic as well. Supersonic mach nos. will be set to '//& + TRIM(Num2LStr(XM))//' to attempt continuation.' + ErrStat = ErrID_Warn +ELSEIF (m%SuperSonic .AND. XM < 1.0) THEN + m%SuperSonic = .FALSE. + ErrMess = 'ATTACH: Supersonic condition has subsided with Blade #'// TRIM(Int2LStr(IBLADE))// & + ' element #'//TRIM(Int2LStr(J))//'.' + ErrStat = ErrID_Info +ENDIF +IF (ErrStat >= AbortErrLev) RETURN + +B2 = 1.0 - XM * XM +m%Beddoes%DS = 2. * m%DT * VREL/p%Blade%C(J) +BS = B2 * m%Beddoes%DS +XKA = .75/( ( 1. - XM ) + PI * B2 * XM * XM * 0.413 ) +X0 = m%DT * p%Beddoes%AS / p%Blade%C(J) / XKA +CO = XKA * p%Blade%C(J) / p%Beddoes%AS / XM + +DA = m%Beddoes%ANE(J,IBLADE) - m%Beddoes%ANE1(J,IBLADE) +m%Beddoes%ADOT(J,IBLADE) = DA / m%DT + +PRP = m%Beddoes%ADOT(J,IBLADE) * p%Blade%C(J) / VREL +PRP = SAT( PRP, 0.03_ReKi, 0.1_ReKi ) +m%Beddoes%ADOT(J,IBLADE) = PRP * VREL / p%Blade%C(J) + +m%Beddoes%DN(J,IBLADE) = m%Beddoes%OLDDN(J,IBLADE) * EXP(-X0) + & + (m%Beddoes%ADOT(J,IBLADE) - m%Beddoes%ADOT1(J,IBLADE)) * EXP(-.5*X0) +CNI = 4._ReKi * CO * ( m%Beddoes%ADOT(J,IBLADE) - m%Beddoes%DN(J,IBLADE) ) +m%Beddoes%CMI = -.25_ReKi * CNI + +m%Beddoes%QX(J,IBLADE) = (m%Beddoes%ADOT(J,IBLADE) - m%Beddoes%ADOT1(J,IBLADE)) * P%Blade%C(J)/VREL/m%DT +m%Beddoes%DQ(J,IBLADE) = m%Beddoes%OLDDQ(J,IBLADE)*EXP(-X0) + & + ( m%Beddoes%QX(J,IBLADE) - m%Beddoes%QX1(J,IBLADE) ) * EXP(-.5*X0) +CNQ = -CO * (m%Beddoes%QX(J,IBLADE) - m%Beddoes%DQ(J,IBLADE)) +m%Beddoes%DQP(J,IBLADE) = m%Beddoes%DQP1(J,IBLADE) * EXP(-X0/XKA) + (m%Beddoes%QX(J,IBLADE) & + - m%Beddoes%QX1(J,IBLADE)) * EXP(-.5*X0/XKA) + +m%Beddoes%CMQ = -.25 * CNQ - (XKA*CO/3.) * (m%Beddoes%QX(J,IBLADE) - m%Beddoes%DQP(J,IBLADE)) + +m%Beddoes%CNIQ = MIN( ABS( CNI+CNQ ), 1.0_ReKi ) * SIGN( 1.0_ReKi, CNI+CNQ ) + +m%Beddoes%XN(J,IBLADE) = m%Beddoes%OLDXN(J,IBLADE)*EXP(-.14*BS) + .3*DA*EXP(-.07*BS) +m%Beddoes%YN(J,IBLADE) = m%Beddoes%OLDYN(J,IBLADE)*EXP(-.53*BS) + .7*DA*EXP(-.265*BS) + +AE = m%Beddoes%ANE(J,IBLADE) - m%Beddoes%YN(J,IBLADE) - m%Beddoes%XN(J,IBLADE) +m%Beddoes%CNCP = CNA1 * ( AE - AOL1 ) +m%Beddoes%CNPOT(J,IBLADE) = m%Beddoes%CNCP + m%Beddoes%CNIQ +m%Beddoes%CC = m%Beddoes%CNPOT(J,IBLADE) * AE + + +RETURN +END SUBROUTINE ATTACH + + + ! ****************************************************** + SUBROUTINE SEPAR( P, m, ErrStat, ErrMess, & + NFT, J, IBlade, IFOIL, CNA1, AOL1, CNS1, CNSL1 ) +! SUBROUTINE SEPAR( NFT, J, IBlade, IFOIL, CNA1, AOL1, CNS1, CNSL1 ) + ! PART OF THE Beddoes DYNAMIC STALL MODEL + ! ****************************************************** + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + REAL(ReKi),INTENT(IN) :: AOL1 + REAL(ReKi),INTENT(IN) :: CNA1 + REAL(ReKi),INTENT(IN) :: CNS1 + REAL(ReKi),INTENT(IN) :: CNSL1 + + INTEGER ,INTENT(IN) :: IFOIL + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + INTEGER ,INTENT(IN) :: NFT + + ! Local Variables: + + REAL(ReKi) :: AFEP + REAL(ReKi) :: AFF + REAL(ReKi) :: CMPA + REAL(ReKi) :: CMPB + REAL(ReKi) :: FSPA + REAL(ReKi) :: FSPB + REAL(ReKi) :: FSPCA + REAL(ReKi) :: FSPCB + REAL(ReKi) :: P1 + REAL(ReKi) :: P2 + REAL(ReKi) :: SRFP + REAL(ReKi) :: SRFPC + REAL(ReKi) :: TEMP + REAL(ReKi) :: TFE + + INTEGER :: I1 + INTEGER :: I1P1 + INTEGER :: I2 + INTEGER :: I2P1 + + ErrStat = ErrID_None + ErrMess = "" + + +TFE = p%Beddoes%TF +m%Beddoes%DPP(J,IBLADE) = m%Beddoes%OLDDPP(J,IBLADE) * EXP(-m%Beddoes%DS/P%Beddoes%TP) & + + ( m%Beddoes%CNPOT(J,IBLADE) - m%Beddoes%CNPOT1(J,IBLADE) ) * EXP(-.5*m%Beddoes%DS/P%Beddoes%TP) +m%Beddoes%CNP(J,IBLADE) = m%Beddoes%CNPOT(J,IBLADE) - m%Beddoes%DPP(J,IBLADE) +m%Beddoes%CNPD(J,IBLADE) = m%Beddoes%CNP(J,IBLADE) - m%Beddoes%CNP1(J,IBLADE) + + ! USE CNPD to determine if AOA is increasing or decreasing. + ! Vortex lift decays more rapidly for decreasing AOA. + +IF ( m%Beddoes%ANE(J,IBLADE) * m%Beddoes%CNPD(J,IBLADE) < 0. ) THEN + m%Beddoes%SHIFT = .TRUE. +ELSE + m%Beddoes%SHIFT = .FALSE. +ENDIF + +AFF = m%Beddoes%CNP(J,IBLADE)/CNA1 + AOL1 + +IF ( ABS( m%Beddoes%AN ) <= PIBY2 ) THEN + m%Beddoes%AFE(J,IBLADE) = AFF +ELSEIF ( m%Beddoes%AN > PIBY2 ) THEN + m%Beddoes%AFE(J,IBLADE) = PI - AFF +ELSE + m%Beddoes%AFE(J,IBLADE) = -PI - AFF +ENDIF + +CALL MPI2PI ( m%Beddoes%AFE(J,IBLADE) ) + +IF ( ( m%Beddoes%AFE(J,IBLADE) < m%AirFoil%AL(IFOIL,1) ) .OR. & + ( m%Beddoes%AFE(J,IBLADE) > m%AirFoil%AL(IFOIL,p%AirFoil%NLIFT(IFOIL) ) ) ) THEN + ErrMess = 'SEPAR: Angle of attack = '//TRIM(Num2LStr( m%Beddoes%AFE(J,IBLADE)*R2D ))//' is outside table.' + ErrStat = ErrID_Fatal + RETURN +ENDIF + +m%Beddoes%AFE(J,IBLADE) = MIN( MAX( m%Beddoes%AFE(J,IBLADE), m%AirFoil%AL(IFOIL,1) ), m%AirFoil%AL(IFOIL,NFT) ) +CALL LocateBin( m%Beddoes%AFE(J,IBLADE), m%AirFoil%AL(IFOIL,1:NFT), I1, NFT ) + +IF (I1 == 0) THEN + I1 = 1 +ELSE IF ( I1 == NFT ) THEN + I1 = I1 - 1 +END IF + +I1P1 = I1 + 1 + + !bjj: check for division by zero? +P1 = ( m%AirFoil%AL(IFOIL,I1) - m%Beddoes%AFE(J,IBLADE) ) / ( m%AirFoil%AL(IFOIL,I1) - m%AirFoil%AL(IFOIL,I1P1) ) + +IF ( p%AirFoil%NTables(IFOIL) > 1 ) THEN + + ! Locate the multiple airfoil position in the table + + m%AirFoil%MulTabLoc = MIN( MAX( m%AirFoil%MulTabLoc, p%AirFoil%MulTabMet(IFOIL,1) ), p%AirFoil%MulTabMet(IFOIL,p%AirFoil%NTables(IFOIL)) ) + CALL LocateBin( m%AirFoil%MulTabLoc, p%AirFoil%MulTabMet(IFOIL,1:p%AirFoil%NTables(IFOIL)),I2,p%AirFoil%NTables(IFOIL) ) + + IF ( I2 == 0 ) THEN + I2 = 1 + I2P1 = 2 + P2 = 0.0 + ELSE IF ( I2 == p%AirFoil%NTables(IFOIL) ) THEN + I2P1 = I2 + I2 = I2 - 1 + + P2 = 1.0 + ELSE + I2P1 = I2 + 1 + + P2=(m%AirFoil%MulTabLoc-p%AirFoil%MulTabMet(IFOIL,I2))/(p%AirFoil%MulTabMet(IFOIL,I2P1)-p%AirFoil%MulTabMet(IFOIL,I2)) + END IF + + ! Interpolate the F-table values + + + FSPB = m%Beddoes%FTB( IFOIL,I1,I2P1) - (m%Beddoes%FTB( IFOIL,I1,I2P1) - m%Beddoes%FTB( IFOIL,I1P1,I2P1) ) * P1 + FSPCB = m%Beddoes%FTBC(IFOIL,I1,I2P1) - (m%Beddoes%FTBC(IFOIL,I1,I2P1) - m%Beddoes%FTBC(IFOIL,I1P1,I2P1) ) * P1 + FSPA = m%Beddoes%FTB( IFOIL,I1,I2 ) - (m%Beddoes%FTB( IFOIL,I1,I2 ) - m%Beddoes%FTB( IFOIL,I1P1,I2 ) ) * P1 + FSPCA = m%Beddoes%FTBC(IFOIL,I1,I2 ) - (m%Beddoes%FTBC(IFOIL,I1,I2 ) - m%Beddoes%FTBC(IFOIL,I1P1,I2 ) ) * P1 + + m%Beddoes%FSP(J,IBLADE) = FSPA + P2 * (FSPB-FSPA) + + m%Beddoes%FSPC(J,IBLADE)= FSPCA + P2 * (FSPCB-FSPCA) + +ELSE + + m%Beddoes%FSP(J,IBLADE) = m%Beddoes%FTB(IFOIL,I1,1) - (m%Beddoes%FTB(IFOIL,I1,1) - m%Beddoes%FTB(IFOIL,I1P1,1) ) * P1 + + m%Beddoes%FSPC(J,IBLADE)= m%Beddoes%FTBC(IFOIL,I1,1) - (m%Beddoes%FTBC(IFOIL,I1,1) - m%Beddoes%FTBC(IFOIL,I1P1,1) ) * P1 + +ENDIF + +IF ( ABS( m%Beddoes%AFE(J,IBLADE) - AOL1 ) < 1.E-10 ) THEN + m%Beddoes%FSP(J,IBLADE) = 1.0 + m%Beddoes%FSPC(J,IBLADE) = 1.0 +ELSE + TEMP = 2.*SQRT(ABS(m%Beddoes%FSP(J,IBLADE)/(m%Beddoes%AFE(J,IBLADE)-AOL1)))-1. + m%Beddoes%FSP(J,IBLADE) = TEMP * TEMP * SIGN ( 1.0_ReKi, TEMP ) + IF ( m%Beddoes%FSP(J,IBLADE) > 1.0 ) m%Beddoes%FSP(J,IBLADE) = 1.0 + IF ( m%Beddoes%FSP(J,IBLADE) < -1.0 ) m%Beddoes%FSP(J,IBLADE) = -1.0 + + IF ( ABS( m%Beddoes%AFE(J,IBLADE) ) < 1.E-10 ) THEN + m%Beddoes%FSPC(J,IBLADE) = 1.0 + ELSE + TEMP = m%Beddoes%FSPC(J,IBLADE)/((m%Beddoes%AFE(J,IBLADE)-AOL1)*m%Beddoes%AFE(J,IBLADE)) + m%Beddoes%FSPC(J,IBLADE) = TEMP * TEMP * SIGN ( 1.0_ReKi, TEMP ) + IF ( m%Beddoes%FSPC(J,IBLADE) > 1.0 ) m%Beddoes%FSPC(J,IBLADE) = 1.0 + IF ( m%Beddoes%FSPC(J,IBLADE) < -1.0 ) m%Beddoes%FSPC(J,IBLADE) = -1.0 + ENDIF + +ENDIF + +IF ( m%Beddoes%CNP(J,IBLADE) > CNS1 ) m%Beddoes%BEDSEP(J,IBLADE) = .TRUE. +IF ( m%Beddoes%CNP(J,IBLADE) < CNSL1 ) m%Beddoes%BEDSEP(J,IBLADE) = .TRUE. + +IF ( m%Beddoes%BEDSEP(J,IBLADE) ) m%Beddoes%TAU(J,IBLADE) = m%Beddoes%OLDTAU(J,IBLADE) + m%Beddoes%DS/P%Beddoes%TVL + +IF (m%Beddoes%SHIFT) TFE = 1.5*TFE + +m%Beddoes%DF(J,IBLADE) = m%Beddoes%OLDDF(J,IBLADE) * EXP(-m%Beddoes%DS/TFE) & + + (m%Beddoes%FSP(J,IBLADE) - m%Beddoes%FSP1(J,IBLADE)) * EXP(-.5*m%Beddoes%DS/TFE) +m%Beddoes%DFC(J,IBLADE)= m%Beddoes%OLDDFC(J,IBLADE) * EXP(-m%Beddoes%DS/TFE) & + + (m%Beddoes%FSPC(J,IBLADE) - m%Beddoes%FSPC1(J,IBLADE)) * EXP(-.5*m%Beddoes%DS/TFE) + +m%Beddoes%FP = m%Beddoes%FSP(J,IBLADE) - m%Beddoes%DF(J,IBLADE) +m%Beddoes%FPC = m%Beddoes%FSPC(J,IBLADE) - m%Beddoes%DFC(J,IBLADE) +SRFP = SQRT( ABS(m%Beddoes%FP) ) * SIGN( 1.0_ReKi, m%Beddoes%FP ) + 1. +SRFPC= SQRT( ABS(m%Beddoes%FPC) ) * SIGN( 1.0_ReKi,m%Beddoes%FPC ) + +m%Beddoes%FK = 0.25 * SRFP * SRFP +m%Beddoes%CN = m%Beddoes%CNCP * m%Beddoes%FK + m%Beddoes%CNIQ + +m%Beddoes%CC = m%Beddoes%CC * SRFPC + +m%Beddoes%DFAFE(J,IBLADE) = m%Beddoes%DFAFE1(J,IBLADE) * EXP(-m%Beddoes%DS/(.1*TFE)) & + + (m%Beddoes%AFE(J,IBLADE) - m%Beddoes%AFE1(J,IBLADE)) * EXP(-.5*m%Beddoes%DS/(.1*TFE)) + +AFEP=m%Beddoes%AFE(J,IBLADE) - m%Beddoes%DFAFE(J,IBLADE) + + +AFEP = MIN( MAX( AFEP, m%AirFoil%AL(IFOIL,1) ), m%AirFoil%AL(IFOIL,NFT) ) +CALL LocateBin( AFEP, m%AirFoil%AL(IFOIL,1:NFT), I1, NFT ) + +IF (I1 == 0) THEN + I1 = 1 + I1P1 = 2 + P1 = 0.0 +ELSEIF ( I1 == NFT ) THEN + I1P1 = I1 + I1 = I1 - 1 + P1 = 1.0 +ELSE + I1P1 = I1 + 1 + P1 = (m%AirFoil%AL(IFOIL,I1) - AFEP)/(m%AirFoil%AL(IFOIL,I1) - m%AirFoil%AL(IFOIL,I1P1)) +END IF + + +IF (p%AirFoil%NTables(IFOIL) > 1) THEN + + ! Interpolate the F-table values + + CMPB = m%AirFoil%CM(IFOIL,I1,I2P1) - (m%AirFoil%CM(IFOIL,I1,I2P1) - m%AirFoil%CM(IFOIL,I1P1,I2P1) ) * P1 + + CMPA = m%AirFoil%CM(IFOIL,I1,I2) - (m%AirFoil%CM(IFOIL,I1,I2) - m%AirFoil%CM(IFOIL,I1P1,I2) ) * P1 + + m%AirFoil%PMC = CMPA + P2*(CMPB-CMPA) + +ELSE + + m%AirFoil%PMC = m%AirFoil%CM(IFOIL,I1,1) - ( (m%AirFoil%CM(IFOIL,I1,1) - m%AirFoil%CM(IFOIL,I1P1,1) ) * P1 ) + +ENDIF + + + +RETURN +END SUBROUTINE SEPAR + + + ! ****************************************************** + SUBROUTINE VORTEX( P, m, ErrStat, ErrMess, & + J, IBlade, AE ) + ! PART OF THE Beddoes DYNAMIC STALL MODEL + ! ****************************************************** + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + REAL(ReKi),INTENT(IN) :: AE + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + + ! Local Variables: + REAL(ReKi) :: CMV + REAL(ReKi) :: TSH + REAL(ReKi) :: TVE + + ErrStat = ErrID_None + ErrMess = "" + +TVE = P%Beddoes%TV +m%Beddoes%CVN(J,IBLADE) = m%Beddoes%CNCP * ( 1. - m%Beddoes%FK ) + +IF ( m%Beddoes%TAU(J,IBLADE) < 1. ) THEN + m%Beddoes%VOR = .TRUE. + IF (m%Beddoes%SHIFT) m%Beddoes%VOR = .FALSE. +ELSE + m%Beddoes%VOR = .FALSE. +ENDIF + +IF (m%Beddoes%VOR) THEN + m%Beddoes%CNV(J,IBLADE) = m%Beddoes%OLDCNV(J,IBLADE) * EXP(-m%Beddoes%DS/TVE) & + + (m%Beddoes%CVN(J,IBLADE) - m%Beddoes%CVN1(J,IBLADE)) * EXP(-.5*m%Beddoes%DS/TVE) +ELSE + m%Beddoes%CNV(J,IBLADE) = m%Beddoes%OLDCNV(J,IBLADE) * EXP(-m%Beddoes%DS/(TVE*.5)) +ENDIF + +m%Beddoes%CN = m%Beddoes%CN + m%Beddoes%CNV(J,IBLADE) +m%Beddoes%CC = m%Beddoes%CC + m%Beddoes%CNV(J,IBLADE) * AE * (1.- m%Beddoes%TAU(J,IBLADE)) +CMV = -0.2 * (1. - COS(PI*m%Beddoes%TAU(J,IBLADE)) ) * m%Beddoes%CNV(J,IBLADE) +m%AirFoil%PMC = m%AirFoil%PMC + CMV + m%Beddoes%CMI + m%Beddoes%CMQ + +TSH = 2.*(1.- m%Beddoes%FP)/.19 + +IF ( m%Beddoes%TAU(J,IBLADE) .GT. 1. + TSH/p%Beddoes%TVL .AND. .NOT. m%Beddoes%SHIFT) THEN + m%Beddoes%TAU(J,IBLADE) = 0. + m%Beddoes%BEDSEP(J,IBLADE) = .FALSE. +ENDIF + +IF ( m%Beddoes%TAU(J,IBLADE) .GT. 1. ) THEN + IF ( m%Beddoes%ANE(J,IBLADE) .LT. 0. ) THEN + + IF (m%Beddoes%CNPD(J,IBLADE) .LE. 0. .AND. m%Beddoes%CNPD1(J,IBLADE) .GE. 0.) THEN + m%Beddoes%BEDSEP(J,IBLADE) = .FALSE. + m%Beddoes%TAU(J,IBLADE) = 0. + ENDIF + + IF (m%Beddoes%ANE1(J,IBLADE) .GT. 0.) THEN + m%Beddoes%BEDSEP(J,IBLADE) = .FALSE. + m%Beddoes%TAU(J,IBLADE) = 0. + ENDIF + + ELSE + + IF (m%Beddoes%CNPD(J,IBLADE) .GE. 0. .AND. m%Beddoes%CNPD1(J,IBLADE) .LE. 0.) THEN + m%Beddoes%BEDSEP(J,IBLADE) = .FALSE. + m%Beddoes%TAU(J,IBLADE) = 0. + ENDIF + + IF (m%Beddoes%ANE1(J,IBLADE) .LT. 0.) THEN + m%Beddoes%BEDSEP(J,IBLADE) = .FALSE. + m%Beddoes%TAU(J,IBLADE) = 0. + ENDIF + + ENDIF +ENDIF + + + +RETURN +END SUBROUTINE VORTEX + + + ! ****************************************************** + SUBROUTINE CLCD( P, m, ErrStat, ErrMess, & + ALPHA, CLA, CDA, CMA, I ) +! SUBROUTINE CLCD( ALPHA, CLA, CDA, CMA, I, ErrStat ) + ! returns values of lift and drag coeffs. + ! This subroutine interpolates airfoil coefficients + ! from a table of airfoil data. The table must consist + ! of ALPHA, CL and CD over the entire range of angles + ! that will be encountered. + ! + ! VARIABLES: + ! CLA = Returned value of lift coefficient + ! CDA = Returned value of drag coeff + ! CMA = Returned value of pitching moment coeff + ! ALPHA = Angle of attack (radians) + ! AL = Array containing the angle of attack + ! CL = Array containing the lift coeffs. at AL(I) + ! CD = Array containing the drag coeffs. at AL(I) + ! CM = Array containing the moment coeffs. at AL(I) + ! I = Airfoil ID for this element, equal to NFoil(J), where J is the index identifying the blade element + ! MulTabLoc= Multiple airfoil table location for this element + ! MulTabMet= Array containing the multiple airfoil table metric + ! ****************************************************** +!USE Airfoil + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + REAL(ReKi),INTENT(INOUT) :: ALPHA + REAL(ReKi),INTENT(OUT) :: CDA + REAL(ReKi),INTENT(OUT) :: CLA + REAL(ReKi),INTENT(OUT) :: CMA + + INTEGER ,INTENT(IN) :: I ! NFOIL(J) + + ! Local Variables: + + REAL(ReKi) :: CDA1 + REAL(ReKi) :: CDA2 + REAL(ReKi) :: CLA1 + REAL(ReKi) :: CLA2 + REAL(ReKi) :: CMA1 + REAL(ReKi) :: CMA2 + REAL(ReKi) :: P1 + REAL(ReKi) :: P2 + + INTEGER :: N1 + INTEGER :: N1P1 + INTEGER :: N2 + INTEGER :: N2P1 + INTEGER :: NTAB + +ErrStat = ErrID_None +ErrMess = "" + +IF (.NOT. ALLOCATED(P%AirFoil%NFoil) ) THEN + CDA = 0. + CLA = 0. + CMA = 0. + ErrStat = ErrID_Fatal + RETURN +ELSE + ErrStat = ErrID_None +END IF + +NTAB = P%AirFoil%NLIFT(I) + +IF ( ( ALPHA < m%AirFoil%AL(I,1) ) .OR. ( ALPHA > m%AirFoil%AL(I,NTAB) ) ) THEN +!bjj: This error message isn't necessarially accurate: + CDA = 0. + CLA = 0. + CMA = 0. + ErrMess = ' Angle of attack = '//TRIM(Num2LStr(ALPHA*R2D))// & + ' deg is outside data table range. '// & !Blade #'//TRIM(Int2LStr(IBLADE))//& + ' Airfoil '//TRIM(Int2LStr(I))//'.' +! ' element '//TRIM(Int2LStr(J))//'.' ) + + ErrStat = ErrID_Fatal + RETURN +ENDIF + +ALPHA = MIN( MAX( ALPHA, m%AirFoil%AL(I,1) ), m%AirFoil%AL(I,NTAB) ) +CALL LocateBin (ALPHA, m%AirFoil%AL(I,1:NTAB), N1, NTAB ) + +IF (N1 == 0) THEN + N1 = 1 + N1P1 = 2 + P1 = 0.0 +ELSEIF(N1 == NTAB) THEN + N1P1 = N1 + N1 = N1 - 1 + P1 = 1.0 +ELSE + N1P1 = N1 + 1 + P1 = ( ALPHA - m%AirFoil%AL(I, N1) )/( m%AirFoil%AL(I, N1P1) - m%AirFoil%AL(I, N1) ) +END IF + + ! If the element has multiple airfoil tables, do a 2-D linear interpolation + ! for Cl and CD + +IF (P%AirFoil%NTables(I) > 1) THEN + + m%AirFoil%MulTabLoc = MIN( MAX( m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1) ), P%AirFoil%MulTabMet(I,P%AirFoil%NTables(I)) ) + CALL LocateBin (m%AirFoil%MulTabLoc, P%AirFoil%MulTabMet(I,1:P%AirFoil%NTables(I)),N2,P%AirFoil%NTables(I)) + + IF (N2 == 0) THEN + N2 = 1 + N2P1 = 2 + P2 = 0.0 + ELSE IF ( N2 == P%AirFoil%NTables(I) ) THEN + N2P1 = N2 + N2 = N2 - 1 + P2 = 1.0 + ELSE + N2P1 = N2 + 1 + P2 = (m%AirFoil%MulTabLoc - P%AirFoil%MulTabMet(I,N2))/(P%AirFoil%MulTabMet(I,N2P1)-P%AirFoil%MulTabMet(I,N2)) + END IF + + CLA1 = m%AirFoil%CL(I,N1,N2) + P1 * ( m%AirFoil%CL(I,N1P1,N2) - m%AirFoil%CL(I,N1,N2) ) + CDA1 = m%AirFoil%CD(I,N1,N2) + P1 * ( m%AirFoil%CD(I,N1P1,N2) - m%AirFoil%CD(I,N1,N2) ) + CMA1 = m%AirFoil%CM(I,N1,N2) + P1 * ( m%AirFoil%CM(I,N1P1,N2) - m%AirFoil%CM(I,N1,N2) ) + + CLA2 = m%AirFoil%CL(I,N1,N2P1) + P1 * ( m%AirFoil%CL(I,N1P1,N2P1) - m%AirFoil%CL(I,N1,N2P1) ) + CDA2 = m%AirFoil%CD(I,N1,N2P1) + P1 * ( m%AirFoil%CD(I,N1P1,N2P1) - m%AirFoil%CD(I,N1,N2P1) ) + CMA2 = m%AirFoil%CM(I,N1,N2P1) + P1 * ( m%AirFoil%CM(I,N1P1,N2P1) - m%AirFoil%CM(I,N1,N2P1) ) + + CLA = CLA1 + P2 * ( CLA2 - CLA1 ) + CDA = CDA1 + P2 * ( CDA2 - CDA1 ) + CMA = CMA1 + P2 * ( CMA2 - CMA1 ) + +ELSE + + CLA = m%AirFoil%CL(I,N1,1) + P1 * ( m%AirFoil%CL(I,N1P1,1) - m%AirFoil%CL(I,N1,1) ) + CDA = m%AirFoil%CD(I,N1,1) + P1 * ( m%AirFoil%CD(I,N1P1,1) - m%AirFoil%CD(I,N1,1) ) + CMA = m%AirFoil%CM(I,N1,1) + P1 * ( m%AirFoil%CM(I,N1P1,1) - m%AirFoil%CM(I,N1,1) ) + +ENDIF + + +RETURN +END SUBROUTINE CLCD + + ! ************************************************** + FUNCTION SAT( X, VAL, SLOPE ) + ! AOA saturation function 02/15/98 + ! ************************************************** + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi) :: SAT +REAL(ReKi),INTENT(IN) :: SLOPE +REAL(ReKi),INTENT(IN) :: VAL +REAL(ReKi),INTENT(IN) :: X + + +IF ( ABS(X) <= VAL ) THEN + SAT = X +ELSEIF ( X > VAL) THEN + SAT = SLOPE * X + VAL * ( 1. - SLOPE ) +ELSE + SAT = SLOPE * X - VAL * ( 1. - SLOPE ) +ENDIF + + +RETURN +END FUNCTION SAT + + + ! **************** Dynamic Inflow Subroutines *************** + ! + ! Generalized Dynamic Wake (GDW) Model replaced the Pitt & + ! Peters model. + ! A. Suzuki, 06/23/00 + + ! Subroutine VG2ROTOR was added again to v11.31 + ! A. Suzuki, 01/24/00 + + ! + ! Modified for FFWIND. Subroutine VG2ROTOR was added. + ! A. Suzuki, 11/05/99. + + ! This model is based on Pitt & Peters model. + ! AB predictor-corrector is used for integration. + ! A. Suzuki, 07/22/98. + ! + ! ************************************************************* + + ! ************************************** + + SUBROUTINE Inflow( Time, P, m, ErrStat, ErrMess ) + + ! Gateway to the dynamic inflow routines. + ! Called by NEWTIME after a time step. + ! ************************************** + + IMPLICIT NONE + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: Time + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + ErrStat = ErrID_None + ErrMess = "" + + IF ( P%DYNINFL ) THEN + +! INITIALIZE DYNAMIC INFLOW PARAMETERS + IF ( m%DYNINIT .AND. ( TIME > 0.0D0 ) ) THEN + CALL INFINIT( P, m, ErrStatLcl, ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'Inflow' ) + IF (ErrStat >= AbortErrLev) RETURN + !WRITE(*,*) 'Activating dynamic inflow calculation' + m%DynInflow%old_Alph = 0.0 + m%DynInflow%old_Beta = 0.0 + m%DYNINIT = .FALSE. + m%SKEW = .FALSE. + ENDIF + + ! Update the dynamic inflow parameters + CALL INFUPDT(P, m, ErrStatLcl, ErrMessLcl) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'Inflow' ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL GetPhiLq(P, m, ErrStatLcl, ErrMessLcl) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'Inflow' ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Calculate the dynamic inflow paremeters for the new time step + IF( TIME > 1.0D0 ) THEN + CALL INFDIST(P, m, ErrStatLcl, ErrMessLcl) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'Inflow' ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + ENDIF ! DYNINFL + +RETURN +END SUBROUTINE Inflow + + + ! ************************************** + + SUBROUTINE GetRM ( P, m, ErrStat, ErrMess, & + rLocal, DFN, DFT, psi, J, IBlade) + + ! Returns RM(MODE), the [mode]-th moment of the blade normal force. + ! Here, the force is in [N/m], while the moment arm is + ! non-dimensional (RLOCAL/R). Also see FUNCTION XPHI. + ! Called as each element is processed by AeroDyn. + ! ************************************** + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + + REAL(ReKi),INTENT(IN) :: DFN + REAL(ReKi),INTENT(IN) :: DFT + REAL(ReKi),INTENT(IN) :: psi + REAL(ReKi),INTENT(IN) :: rLocal + + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: IBlade + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Local Variables: + REAL(ReKi) :: fElem + ! psiBar is Suzuki's, WindPsi is Shawler's + !REAL(ReKi) :: psiBar + REAL(ReKi) :: Rzero + REAL(ReKi) :: WindPsi + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + + INTEGER :: mode + + ErrStat = ErrID_None + ErrMess = "" + + +IF ( P%SWIRL ) THEN + fElem = SQRT( DFN * DFN + DFT * DFT ) +ELSE + fElem = DFN +ENDIF +fElem = fElem / P%Blade%R + +Rzero = rLocal / P%Blade%R +! Suzukis inflow azimuth measure +!psiBar = - psi - piBy2 +! Shawler: wind based inflow azimuth measure +CALL WindAzimuthZero (psi,m%Wind%VrotorY,m%Wind%VrotorZ,WindPsi) + +! Save values rotor loads for USE in Newtime (to accumulate rotor loads) +DO mode = 1, P%DynInflow%MAXINFLO + m%DynInflow%RMC_SAVE(IBLADE, J, mode) = fElem * XPHI( Rzero, mode, ErrStatLcl, ErrMessLcl ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'GetRM' ) + IF (ErrStat >= AbortErrLev) RETURN +END DO ! mode + +!+++++++++++++++++++++++++++++++++++++++++++++++++++++ +!Suzuki's method +!DO mode = MaxInflo+1, maxInfl +! m%DynInflow%RMC_SAVE(IBLADE, J, mode) = fElem * XPHI( Rzero, mode ) * COS( REAL(MRvector(mode), ReKi) * psiBar ) +! m%DynInflow%RMS_SAVE(IBLADE, J, mode) = fElem * XPHI( Rzero, mode ) * SIN( REAL(MRvector(mode), ReKi) * psiBar ) +!END DO ! mode +! Shawler's method +DO mode = p%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%RMC_SAVE(IBLADE, J, mode) = fElem * XPHI( Rzero, mode, ErrStatLcl, ErrMessLcl ) * COS( REAL(MRvector(mode), ReKi) * WindPsi ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'GetRM' ) + IF (ErrStat >= AbortErrLev) RETURN + + m%DynInflow%RMS_SAVE(IBLADE, J, mode) = fElem * XPHI( Rzero, mode, ErrStatLcl, ErrMessLcl ) * SIN( REAL(MRvector(mode), ReKi) * WindPsi ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'GetRM' ) + IF (ErrStat >= AbortErrLev) RETURN + +END DO ! mode +!++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +RETURN +END SUBROUTINE GetRM + + + ! ************************************** + + SUBROUTINE GetPhiLq( P, m, ErrStat, ErrMess ) + + ! Accumulate the rotor forces for dynamic inflow calculations + ! PhiLqC is Lq times PHI (shape function) in COS equation. + ! PhiLqS is Lq times PHI (shape function) in SIN equation. + ! RM?_SAVE, which were calculated for each element, + ! are summed here after a time step. + ! ************************************** + +!USE Blade +!USE DynInflow +!USE Element + + IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + + INTEGER :: iblad + INTEGER :: ielem + INTEGER :: mode + + ErrStat = ErrID_None + ErrMess = "" + +m%DynInflow%PhiLqC = 0. +m%DynInflow%PhiLqS = 0. + +DO mode = 1, maxInfl + DO iblad = 1, P%NumBl + DO ielem = 1, P%Element%NELM + m%DynInflow%PhiLqC(mode) = m%DynInflow%PhiLqC(mode) + m%DynInflow%RMC_SAVE(iblad, ielem, mode) + IF (mode >= p%DynInflow%MaxInflo+1) & + m%DynInflow%PhiLqS(mode) = m%DynInflow%PhiLqS(mode) + m%DynInflow%RMS_SAVE(iblad, ielem, mode) + END DO !ielem + END DO !iblad +END DO !mode + +RETURN +END SUBROUTINE GetPhiLq + + + ! ************************************************************* + SUBROUTINE infinit( P, m, ErrStat, ErrMess ) + ! Initializes the variables in the dynamic inflow equation. + ! Called only once to initialize the GDW parameters. + ! ************************************************************* + IMPLICIT NONE + + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Local Variables: + + REAL(ReKi) :: tauCos ( maxInfl ) + REAL(ReKi) :: tauSin ( P%DynInflow%MaxInflo+1 : maxInfl ) + REAL(ReKi) :: v1 + REAL(ReKi) :: v2 + REAL(ReKi) :: v3 + REAL(ReKi) :: Vplane2 + + INTEGER :: i + INTEGER :: iElem + INTEGER :: irow + INTEGER :: jBlade + INTEGER :: jcol + INTEGER :: k + INTEGER :: mode + + ErrStat = ErrID_None + ErrMess = "" + + ! Initialize the MRvector & NJVector. + ! MRvector is the azimuthal mode of the inflow distribution. + ! NJvector is the radial mode of the inflow distribution. + +!P%DynInflow%MRVector(:) = (/ 0, 0, 1, 1, 2, 3 /) !bjj why aren't these parameters? Now they are. +!P%DynInflow%NJVector(:) = (/ 1, 3, 2, 4, 3, 4 /) + + ! For your reference, + ! Marray(irow,jcol) = MRvector(jcol) + ! Rarray(irow,jcol) = MRvector(irow) + ! Narray(irow,jcol) = NJvector(jcol) + ! Jarray(irow,jcol) = NJvector(irow) + + ! Initialize the time derivatives. +m%DynInflow%dAlph_dt(:,:) = 0. +m%DynInflow%dBeta_dt(:,:) = 0. + +! ! Set up the constants. +! ! xMinv is [M]^-1. Because [M]^-1 is just a diagonal matrix, +! ! it is stored as a column vector. +!bjj: this is a parameter that we'll set at initialization +!DO irow = 1, maxInfl +! p%DynInflow%xMinv(irow) = PIBY2 / hfunc(MRvector(irow), NJvector(irow)) !bjj: this is really just a parameter, too. +!END DO !irow + + ! Set up the GAMMA matrix which is used to calculate [L] matrix. + ! FUNCTION FGAMMA is called. +DO irow = 1, maxInfl + DO jcol = 1, maxInfl + m%DynInflow%gamma( irow, jcol ) & + = fgamma( MRvector( irow ), NJvector( irow ), & + MRvector( jcol ), NJvector( jcol ) ) !bjj: this is really just a parameter, too. + END DO !jcol +END DO !irow + + ! calculate and store the M-R matrices, which are used in Subroutine LMATRIX. +DO irow = 1, maxInfl + DO jcol = 1, maxInfl + m%DynInflow%MminR (irow,jcol) = MIN( MRvector(jcol) , MRvector(irow) ) + m%DynInflow%MplusR (irow,jcol) = MRvector(jcol) + MRvector(irow) + m%DynInflow%MminusR(irow,jcol) = ABS( MRvector(jcol) - MRvector(irow) ) + END DO !jcol +END DO !irow + + ! Calculate the tip speed of the rotor. This isn't constant in ADAMS. + ! Thus, it will be updated at every time step in ADAMS. +m%DynInflow%TipSpeed = MAX(P%Blade%r * m%Rotor%revs, 1.0e-6_ReKi) + + ! Calculate the disk loading normalization factor. + ! This is not exactly pressure but let's call it P0. + ! The actual unit is [N/m] or [Pa*m]. + ! Pzero = PI * AirDensity * (Rotational Speed)^2 * (Radius)^3 + ! Pzero = pi * rho * revs**2 * P%Blade%r**3 + ! Pzero = pi * rho * revs * revs * P%Blade%r * P%Blade%r * P%Blade%r +m%DynInflow%Pzero = pi * p%Wind%rho * m%DynInflow%TipSpeed * m%DynInflow%TipSpeed * P%Blade%r + ! Non-dimensional time +m%DynInflow%DTO = m%DT * m%Rotor%REVS !bjj: this isn't used in this subroutine? + + ! Calculate the initial values of inflow distribution parameters + + ! Calculate the non-dimensional wind velocity components. + +v1 = m%Wind%VrotorZ / m%DynInflow%TipSpeed !inplane, upward +v2 = m%Wind%VrotorY / m%DynInflow%TipSpeed !inplane, right looking downwind +v3 = - m%Wind%VrotorX / m%DynInflow%TipSpeed !out-of-plane, normal to the rotor + + ! Calculate the initial value of lambda_m by taking the average + ! of the induction factors(A). The A's are calculated by + ! momentum balance during the first rotation of the trim solution. +m%DynInflow%xLambda_M = 0. +DO jBlade=1,P%NumBl + DO iElem =1,P%Element%nelm + m%DynInflow%xLambda_M = m%DynInflow%xLambda_M + m%Element%a(iElem,jBlade) + END DO !iElem +END DO !jBlade +m%DynInflow%xLambda_M = m%DynInflow%xLambda_M / ( P%NumBl * P%Element%nelm ) + + ! A's are normalized by the normal wind speed, while Lambda's are + ! mormalized by the tip speed. Make the conversion. + ! xLambda_M = xLambda_M * (-VrotorX/TipSpeed) +m%DynInflow%xLambda_M = m%DynInflow%xLambda_M * v3 + + ! totalInf is the non-dimensional total wind speed normal to the rotor. +m%DynInflow%totalInf = - v3 + m%DynInflow%xLambda_M + ! Vplane2 is the square of in-plane component of the non-dimensional + ! wind velocity. +Vplane2 = v1 * v1 + v2 * v2 + ! VTOTAL is the total wind speed at the rotor. +m%DynInflow%Vtotal = SQRT( m%DynInflow%totalInf * m%DynInflow%totalInf + Vplane2 ) + ! VPARAM is the velocity parameter. +m%DynInflow%Vparam =( Vplane2 + ( m%DynInflow%totalInf + m%DynInflow%old_LmdM ) * m%DynInflow%totalInf ) / m%DynInflow%Vtotal + + ! Calculate the disk skew angle function using the effective disk angle + ! of attack. + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Shawler - USE the single wake skew angle, squared variable means its always positive + ! and because blade azimuth position is measured using windpsi the wake skew + ! is defined in the right direction relative to the oncoming wind, + ! ie directly downwind. + !Suzuki: +!xKaiC = TAN( .5 * ATAN( -v2 / totalInf ) ) +!xKaiS = TAN( .5 * ATAN( v1 / totalInf ) ) + !xkai = TAN( .5 * SIGN( ATAN( SQRT( vplane2 ) / totalInf ), v2 ) ) + !Shawler: +m%DynInflow%xkai = TAN( .5 * ATAN( SQRT( Vplane2 ) / m%DynInflow%totalInf ) ) + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ! To calculate the initial values of xAlpha & xBeta, get [L] matrices + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Suzuki: +!CALL LMATRIX ( m,p,xKaiC, 1 ) +!CALL LMATRIX ( m,p,xKaiS, 2 ) + ! Shawler: +CALL LMATRIX ( m,p, 1, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infinit:'//TRIM(ErrMess) + RETURN + END IF +CALL LMATRIX ( m,p, 2, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infinit:'//TRIM(ErrMess) + RETURN + END IF + +! CALL LMATRIX ( xkai ) + ! Here we need [L_cos] & [L_sin], not [L_***}^-1. + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ! Get TAU's (pressure coefficient). Refer to Subroutine INFDIST. +DO mode = 1, P%DynInflow%MaxInflo + tauCos(mode) = - m%DynInflow%PhiLqC(mode) / m%DynInflow%Pzero * .5 +END DO !mode + +DO mode = P%DynInflow%MaxInflo+1, maxInfl + tauCos(mode) = - m%DynInflow%PhiLqC(mode) / m%DynInflow%Pzero + tauSin(mode) = - m%DynInflow%PhiLqS(mode) / m%DynInflow%Pzero +END DO !mode + + ! Get the steady values of alpha(1) + ! If m=0 and n=1, USE VTOTAL. +m%DynInflow%xAlpha(1) = 0. +DO k = 1, maxInfl + m%DynInflow%xAlpha(1) = m%DynInflow%xAlpha(1) + m%DynInflow%xLcos(1,k) * tauCos(k) +END DO !k +m%DynInflow%xAlpha(1) = .5 * m%DynInflow%xAlpha(1) / m%DynInflow%Vtotal + + ! If m=0 but NOT n=1, USE VPARAM. +DO i = 2, P%DynInflow%MaxInflo + m%DynInflow%xAlpha(i) = 0. + DO k = 1, maxInfl + m%DynInflow%xAlpha(i) = m%DynInflow%xAlpha(i) + m%DynInflow%xLcos(i,k) * tauCos(k) + END DO !k + m%DynInflow%xAlpha(i) = .5 * m%DynInflow%xAlpha(i) / m%DynInflow%Vparam +END DO !i + + ! Get the steady values of alpha's & beta's +DO i = P%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%xAlpha(i) = 0. + ! akihiro +! DO k = 1, maxInfl + DO k = P%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%xAlpha(i) = m%DynInflow%xAlpha(i) + m%DynInflow%xLcos(i,k) * tauCos(k) + END DO !k + m%DynInflow%xAlpha(i) = .5 * m%DynInflow%xAlpha(i) / m%DynInflow%Vparam + + m%DynInflow%xBeta (i) = 0. + DO k = P%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%xBeta (i) = m%DynInflow%xBeta (i) + m%DynInflow%xLsin(i,k) * tauSin(k) + END DO !k + m%DynInflow%xBeta (i) = .5 * m%DynInflow%xBeta (i) / m%DynInflow%Vparam +END DO !i + + ! Invert [L_cos] & [L_sin] matrices in case the XKAI is constant + ! and the same [L]'s are used later. +CALL MATINV ( m%DynInflow%xLcos, m%DynInflow%xLsin, maxInfl, P%DynInflow%MaxInflo, 1, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infinit:'//TRIM(ErrMess) + RETURN + END IF +CALL MATINV ( m%DynInflow%xLcos, m%DynInflow%xLsin, maxInfl, P%DynInflow%MaxInflo, 2, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infinit:'//TRIM(ErrMess) + RETURN + END IF + +RETURN +END SUBROUTINE infinit + + + ! ********************************************************************** + SUBROUTINE infupdt( P, m, ErrStat, ErrMess ) + ! INFUPDT updates the OLD variables of inflow distribution parameters. + ! The program must call this subroutine before calling + ! the subroutine INFDIST. + ! ********************************************************************** + +!USE DynInflow + + IMPLICIT NONE + + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + INTEGER :: i + + + ErrStat = ErrID_None + ErrMess = "" + +!+++++++++++++++++++++++++++ +!Suzuki: +!oldKaiC = xKaiC +!oldKaiS = xKaiS +!Shawler: +m%DynInflow%oldKai = m%DynInflow%xKai +!+++++++++++++++++++++++++++ + +m%DynInflow%old_LmdM = m%DynInflow%xLambda_M + +DO i = 1, maxInfl + m%DynInflow%old_Alph(i) = m%DynInflow%xAlpha (i) + m%DynInflow%dAlph_dt(i,4) = m%DynInflow%dAlph_dt(i,3) + m%DynInflow%dAlph_dt(i,3) = m%DynInflow%dAlph_dt(i,2) + m%DynInflow%dAlph_dt(i,2) = m%DynInflow%dAlph_dt(i,1) +END DO !i + +DO i = P%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%old_Beta(i) = m%DynInflow%xBeta (i) + m%DynInflow%dBeta_dt(i,4) = m%DynInflow%dBeta_dt(i,3) + m%DynInflow%dBeta_dt(i,3) = m%DynInflow%dBeta_dt(i,2) + m%DynInflow%dBeta_dt(i,2) = m%DynInflow%dBeta_dt(i,1) +END DO !i + +RETURN +END SUBROUTINE infupdt + + + ! ********************************************************************** + SUBROUTINE DynDebug (Time, P, x, xd, z, m, y, ErrStat, ErrMess, RHScos, RHSsin) + ! Write out debugging information + ! ********************************************************************** + + IMPLICIT NONE + REAL(DbKi), INTENT(IN) :: Time + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed Variables: + + REAL(ReKi) :: RHScos ( maxInfl ) + REAL(ReKi) :: RHSsin ( P%DynInflow%MaxInflo+1:maxInfl ) + + + ! Local Variables: + + INTEGER :: i + INTEGER :: NumOut + INTEGER, PARAMETER :: UnDyn = 80 + + CHARACTER(50) :: Frmt + + ErrStat = ErrID_None + ErrMess = "" + +!SAVE ! Save *all* local variables. Is this necessary, or is OnePass enough. + +NumOut = maxInfl+(maxInfl-P%DynInflow%MaxInflo) + 1 + +IF (m%OnePassDynDbg) THEN + + CALL OpenFOutFile (UnDyn, 'DynDebug.plt', ErrStat, ErrMess) + IF (ErrStat>=AbortErrLev) RETURN + + Frmt = '( A4, (: A1, A, I1.1 ) )' + + WRITE(Frmt(7:9), '(I3)') NumOut + WRITE(UnDyn, Frmt) 'Time', & + ( TAB, 'dAlph_dt', i, & + i = 1, maxInfl ), & + ( TAB, 'dBeta_dt', i, & + i = P%DynInflow%MaxInflo+1, maxInfl ), & + TAB, 'TotalInf' + + m%OnePassDynDbg = .FALSE. + +ENDIF + +Frmt = '( F10.3, ( : A1, ES12.5 ) )' + +IF (TIME > 0.0D0) THEN + + WRITE(Frmt(10:12), '(I3)') NumOut + WRITE(UnDyn,Frmt) TIME, & + ( TAB, m%DynInflow%dAlph_dt(i,1), & + i = 1, maxInfl ), & + ( TAB, m%DynInflow%dBeta_dt(i,1), & + i = P%DynInflow%MaxInflo+1, maxInfl ), & + TAB, m%DynInflow%totalInf + +ENDIF + +RETURN +END SUBROUTINE DynDebug + + + ! ********************************************************************** + SUBROUTINE infdist( P, m, ErrStat, ErrMess ) + ! INFDIST calculates the inflow (induced flow) distribution + ! parameters using Generalized Dynamic Wake Theory. + ! ********************************************************************** + IMPLICIT NONE + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Local Variables: + + REAL(ReKi) :: RHScos ( maxInfl ) ! The cosine terms go from 1 to 6. The sine terms go from 3 to 6. + REAL(ReKi) :: RHSsin ( P%DynInflow%MaxInflo+1:maxInfl ) ! The right hand side of the governing equation. + REAL(ReKi) :: tauCos ( maxInfl ) ! Forcing Functions + REAL(ReKi) :: tauSin ( P%DynInflow%MaxInflo+1:maxInfl ) + REAL(ReKi) :: v1 + REAL(ReKi) :: v2 + REAL(ReKi) :: v3 + REAL(ReKi) :: Vplane2 + + INTEGER :: i + INTEGER :: k + INTEGER :: mode + + ErrStat = ErrID_None + ErrMess = "" +m%DynInflow%TipSpeed = MAX(P%Blade%r * m%Rotor%revs, 1.0e-6_ReKi) !bjj: why is this here AND in InfInit()? + +m%DynInflow%Pzero = pi * p%Wind%rho * m%DynInflow%TipSpeed * m%DynInflow%TipSpeed * P%Blade%r + + ! Non-dimensional time +m%DynInflow%DTO = m%DT * m%Rotor%REVS + + ! Calculate the wind velocity components in rotor-fixed + ! coordinates(1-2-3), which are normalized by the tipspeed. +v1 = m%Wind%VrotorZ / m%DynInflow%TipSpeed !inplane, upward +v2 = m%Wind%VrotorY / m%DynInflow%TipSpeed !inplane, right looking downwind +v3 = - m%Wind%VrotorX / m%DynInflow%TipSpeed !out-of-plane (normal to the rotor) + ! Vplane2 is the square of in-plane component of the non-dimensional + ! wind velocity. +Vplane2 = v1 * v1 + v2 * v2 + + ! Note: Direction of non-dimensional velocity (All normal to the rotor plane). + ! totalInf: positive downwind. This is the total inflow to the rotor. + ! v3: positive upwind (thus, in normal condition, v3 < 0 ) + ! xLambda_M: positive downwind (opposite to A(i,j) ) + ! old_LmdM: positive downwind (opposite to A(i,j) ) +m%DynInflow%totalInf = - v3 + m%DynInflow%old_LmdM +! if ( m%DynInflow%totalInf .le. 0. ) then +! call usrmes( .true. , & +! 'In SUBROUTINE INFDIST. totalInf =< 0.', & +! 27, 'WARN' ) +! endif + + ! VTOTAL is the speed of the total inflow to the rotor. +m%DynInflow%Vtotal = SQRT( m%DynInflow%totalInf * m%DynInflow%totalInf + Vplane2 ) +IF (m%DynInflow%vtotal <= 1.0e-6) m%DynInflow%vtotal=1.0e-6 + + ! VPARAM is the inflow velocity parameter. +m%DynInflow%Vparam = ( Vplane2 + ( m%DynInflow%totalInf + m%DynInflow%old_LmdM ) * m%DynInflow%totalInf ) / m%DynInflow%Vtotal + ! Calculate the disk skew angle function + ! using the effective disk angle of attack. +IF (m%DynInflow% totalInf == 0. ) THEN +! WRITE(*,*) v3, m%DynInflow%old_LmdM + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! Suzuki: +! xKaiC = 0. +! xKaiS = 0. +! Shawler: + m%DynInflow%xKai = 0 + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +ELSE + ! Note the definition of Yaw Angle is around -Z axis. + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! Suzuki: +! xKaiC = TAN( .5 * ATAN( -v2 / totalInf ) ) +! xKaiS = TAN( .5 * ATAN( v1 / totalInf ) ) +!! xKaiC = TAN( .5 * SIGN( ATAN( SQRT( vplane2 ) / totalInf ), v2 ) ) +! Shawler: + m%DynInflow%xkai = TAN( .5 * ATAN( SQRT( vplane2 ) / m%DynInflow%totalInf ) ) + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +ENDIF + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! Suzuki: + ! Update [L_cos] and [L_sin] matrices only if 'xkai' has changed. + ! Then invert [L_cos] & [L_sin] matrices. +!IF ( xKaiC /= oldKaiC ) THEN +! CALL LMATRIX ( xKaiC, 1 ) +! CALL MATINV ( xLcos, xLsin, maxInfl, MaxInflo, 1 ) +!ENDIF + +!IF ( xKaiS /= oldKaiS ) THEN +! CALL LMATRIX ( m%DynInflow%xKaiS, 2 ) +! CALL MATINV ( m%DynInflow%xLcos, m%DynInflow%xLsin, maxInfl, P%DynInflow%MaxInflo, 2 ) +!ENDIF +! Shawler: +!IF ( xKai /= oldKai ) THEN + CALL LMATRIX ( m,p, 1, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infdist:'//TRIM(ErrMess) + RETURN + END IF + CALL LMATRIX ( m,p, 2, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infdist:'//TRIM(ErrMess) + RETURN + END IF + CALL MATINV ( m%DynInflow%xLcos, m%DynInflow%xLsin, maxInfl, P%DynInflow%MaxInflo, 1, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infdist:'//TRIM(ErrMess) + RETURN + END IF + CALL MATINV ( m%DynInflow%xLcos, m%DynInflow%xLsin, maxInfl, P%DynInflow%MaxInflo, 2, ErrStat, ErrMess ) + IF (ErrStat /= ErrID_None) THEN + ErrMess='infdist:'//TRIM(ErrMess) + RETURN + END IF +!ENDIF + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ! [L_***] is now [L_***]^-1. + + ! Calculate the forcing functions (lift or normal forces). + ! In the generalized dynamic wake model, the normal forces on the blades + ! are positve upwind (just like a helicopter rotor). On the other hand, + ! they are positve downwind in YawDyn, which is normal in wind turbine rotor. + ! Put a minus sign for each forcing function. + + ! The modes for r=0. +DO mode = 1, P%DynInflow%MaxInflo + tauCos(mode) = - m%DynInflow%PhiLqC(mode) / m%DynInflow%Pzero * .5 +END DO !mode + + ! The modes for r>0. +DO mode = P%DynInflow%MaxInflo+1, maxInfl + tauCos(mode) = - m%DynInflow%PhiLqC(mode) / m%DynInflow%Pzero + tauSin(mode) = - m%DynInflow%PhiLqS(mode) / m%DynInflow%Pzero +END DO !mode + + ! Solve for the time derivatives of xAlpha's, {d(alpha)_dt}. + ! Calculate the right hand side of the governing equation. + ! {rhs} = 0.5*{tau} - [V][L]^-1*{alpha} + + ! First, calculate {rhs} = V[L]^-1*{alpha} + ! USE "VTOTAL" for the first row of r=0. Cosine Matrix only. +RHScos(1) = 0. +DO k = 1, maxInfl + RHScos(1) = RHScos(1) + m%DynInflow%xLcos(1,k) * m%DynInflow%old_Alph(k) +END DO !k +RHScos(1) = .5 * tauCos(1) - m%DynInflow%vtotal * RHScos(1) + + ! USE "VPARAM" for the second row or higher of r=0. +DO i = 2, P%DynInflow%MaxInflo + RHScos(i) = 0. + DO k = 1, maxInfl + RHScos(i) = RHScos(i) + m%DynInflow%xLcos(i,k) * m%DynInflow%old_Alph(k) + END DO !k + RHScos(i) = .5 * tauCos(i) - m%DynInflow%Vparam * RHScos(i) +END DO !i + + ! Rows with r=1 or greater. Both cosine and sine matrices. +DO i = P%DynInflow%MaxInflo+1, maxInfl + RHScos(i) = 0. + RHSsin(i) = 0. + ! First, calculate {rhs} = V[L]^-1*{alpha} + RHScos(i) = sum(m%DynInflow%xLcos(i,1:maxInfl) * m%DynInflow%old_Alph(1:maxInfl)) + RHSsin(i) = sum(m%DynInflow%xLsin(i,P%DynInflow%MaxInflo+1:maxInfl) * m%DynInflow%old_Beta(P%DynInflow%MaxInflo+1:maxInfl)) + ! Second, calculate {rhs} = 0.5*{tau} - [V]{rhs} + ! = 0.5*{tau} - [V][L]^-1*{alpha} + ! USE "VPARAM" for m>0 + RHScos(i) = .5 * tauCos(i) - m%DynInflow%Vparam * RHScos(i) + RHSsin(i) = .5 * tauSin(i) - m%DynInflow%Vparam * RHSsin(i) +END DO !i + +DO i = 1, P%DynInflow%MaxInflo + m%DynInflow%dAlph_dt(i,1) = p%DynInflow%xMinv(i) * RHScos(i) +END DO !i +DO i = P%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%dAlph_dt(i,1) = p%DynInflow%xMinv(i) * RHScos(i) + m%DynInflow%dBeta_dt(i,1) = p%DynInflow%xMinv(i) * RHSsin(i) +END DO !i + + ! Integration using Adams-Bashford predictor corrector method. + ! Note: The time step is nondimensional. t0=Omega*t + ! Thus, in YawDyn, DT0=DT*REVS=(DELPSI/REVS)*REVS=DELPSI + ! USE DT*REVS for compatibility with AeroDyn (DT0 not constant). + ! DT is in module 'Lift' + ! Determines xAlpha and xBeta +CALL ABPRECOR ( m%DynInflow%xAlpha, m%DynInflow%old_Alph, m%DynInflow%dAlph_dt, m%DynInflow%DTO, maxInfl, 1 ) +CALL ABPRECOR ( m%DynInflow%xBeta, m%DynInflow%old_Beta, m%DynInflow%dBeta_dt, m%DynInflow%DTO, maxInfl, P%DynInflow%MaxInflo+1 ) + + ! Calculate the new lambda_m. +!bjj: why are there 2 do loops? can't they be combined???? (assuming MaxInflo < maxInfl) or is one of these supposed to be sin? +m%DynInflow%xLambda_M= 0. +DO k = 1, P%DynInflow%MaxInflo-1 + m%DynInflow%xLambda_M = m%DynInflow%xLambda_M + m%DynInflow%xLcos(1,k) * m%DynInflow%xAlpha(k) +END DO !k +DO k = P%DynInflow%MaxInflo, maxInfl + m%DynInflow%xLambda_M = m%DynInflow%xLambda_M + m%DynInflow%xLcos(1,k) * m%DynInflow%xAlpha(k) +END DO !k +! xLambda_M = 2. / sqrt(3.) * xLambda_M +m%DynInflow%xLambda_M = 1.1547005 * m%DynInflow%xLambda_M + +! Added additional output for GDW debugging - comment out for distribution +!CALL DynDebug (Time, P, x, xd, z, m, y, ErrStat, ErrMess, RHScos, RHSsin) + +RETURN +END SUBROUTINE infdist + + ! ************************************************************* + SUBROUTINE VINDINF( P, m, ErrStat, ErrMess, & + iradius, iblade, rlocal, vnw, VNB, VT, psi ) + ! Calculates the axial and tangential induction factor for each annular segment + ! and time step (i.e. sets m%Element%A and m%Element%AP) + ! Uses the calculated inflow parameters + ! Called by ElemFrc for each element at a new time step. + ! ************************************************************* + + IMPLICIT NONE + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + + ! Passed Variables: + REAL(ReKi),INTENT(IN) :: psi + REAL(ReKi),INTENT(IN) :: rlocal + REAL(ReKi),INTENT(IN) :: VNB + REAL(ReKi),INTENT(IN) :: vnw + REAL(ReKi),INTENT(IN ) :: VT ! Tangential velocity from relative blade motion and wind, no induction + + INTEGER, INTENT(IN) :: iradius + INTEGER, INTENT(IN) :: iblade + + ! Local Variables: + + REAL(ReKi) :: A2P + !Suzuki uses psiBar, Shawler - WindPsi + !REAL(ReKi) :: psibar + REAL(ReKi) :: Rzero + REAL(ReKi) :: SWRLARG + REAL(ReKi) :: Windpsi + + INTEGER :: mode + + INTEGER :: ErrStatLcL ! Error status returned by called routines. + CHARACTER(ErrMsgLen) :: ErrMessLcl ! Error message returned by called routines. + + +ErrStat = ErrID_None +ErrMess = "" + + ! Rzero is the non-dimensional radius. +Rzero = rlocal / P%Blade%r + + ! PSIBAR is the azimuth angle measured counterclockwise from + ! the horizontal to the left looking downwind. The directions + ! of PSI and PSIBAR are opposite and there is 90 deg difference. + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!Suzuki: +! psiBar = - psi - piBy2 +! Shawler: +CALL WindAzimuthZero (psi,m%Wind%VrotorY,m%Wind%VrotorZ,WindPsi) + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ! Calculate the induction factor using the inflow parameters. + ! Here it's normalized by the tipspeed. + +m%Element%A(iRadius,iBlade) = 0. + +DO mode = 1, p%DynInflow%MaxInflo + m%Element%A(iRadius,iBlade) = m%Element%A(iRadius,iBlade) & + + xphi(Rzero,mode,ErrStatLcl, ErrMessLcl) * m%DynInflow%xAlpha(mode) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'VINDINF' ) + IF (ErrStat >= AbortErrLev) RETURN + +! & + phis(Rzero, MRvector(mode), NJvector(mode) )* xAlpha(mode) +END DO !mode + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!Suzuki: +!DO mode = MaxInflo+1, maxInfl +! A(iRadius,iBlade) = A(iRadius,iBlade) + xphi(Rzero,mode) * & +!! & + phis(Rzero, MRvector(mode), NJvector(mode) ) * +! ( xAlpha(mode) * COS( REAL(MRvector(MODE), ReKi) * psibar ) & +! + xBeta (mode) * SIN( REAL(MRvector(MODE), ReKi) * psibar ) ) +!END DO !mode +! Shawler: +DO mode = p%DynInflow%MaxInflo+1, maxInfl + m%Element%A(iRadius,iBlade) = m%Element%A(iRadius,iBlade) + xphi(Rzero,mode,ErrStatLcl, ErrMessLcl) * & + ( m%DynInflow%xAlpha(mode) * COS( REAL(MRvector(MODE), ReKi) * Windpsi ) & + + m%DynInflow%xBeta (mode) * SIN( REAL(MRvector(MODE), ReKi) * Windpsi ) ) + CALL SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat,ErrMess,'VINDINF' ) + IF (ErrStat >= AbortErrLev) RETURN + +END DO !mode + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ! A is positive upwind, while alpha's & beta's are positve downwind. + ! Also, they are normalized by different factors. +m%Element%A(iRadius,iBlade) = - m%Element%A(iRadius,iBlade) * m%DynInflow%TipSpeed / VNW + + ! Calculate induced swirl (a') if desired. + +m%Element%AP(iRadius,iBlade) = 0.0_ReKi ! Default value + +IF ( P%SWIRL ) THEN + ! akihiro 10/26/99 + SWRLARG = 1.0 + 4.0 * m%Element%A(iradius,iblade) * VNW * & + ( (1.0 - m%Element%A(iradius,iblade)) * VNW + VNB ) / VT / VT + IF ( SWRLARG > 0.0 ) THEN + A2P = 0.5 * ( -1.0 + SQRT( SWRLARG ) ) +! bjj: this value was not properly set before. We could also just replace the local A2P variable with AP() instead. + m%Element%AP(iRadius,iBlade) = A2P + ENDIF + +ENDIF + +RETURN +END SUBROUTINE VINDINF + + ! *********************************************************************** + SUBROUTINE ABPRECOR( F, OLDF, DFDT, DT, N, N0 ) + ! Integrates Function F by Adams-Bashford Predictor and Adams-Moulton + ! Corrector using four previous values of dF/dt. + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: +INTEGER ,INTENT(IN) :: N +INTEGER ,INTENT(IN) :: N0 + +REAL(ReKi),INTENT(IN) :: DT +REAL(ReKi),INTENT(IN) :: DFDT ( N0:N, 4 ) +REAL(ReKi),INTENT(OUT) :: F ( N0:N ) +REAL(ReKi),INTENT(IN) :: OLDF ( N0:N ) + + ! Local Variables: + +REAL(ReKi) :: DFDT0 + +INTEGER :: I + + + +DO I = N0, N + ! Adams-Bashford Predictor + F(I) = OLDF(I) + ( 55. * DFDT(I,1) - 59. * DFDT(I,2) & + + 37. * DFDT(I,3) - 9. * DFDT(I,4) ) * DT / 24. + + ! New time derivative for corrector + DFDT0 = ( F(I) - OLDF(I) ) / DT + + ! Adams-Moulton Corrector + F(I) = OLDF(I) + ( 9. * DFDT0 + 19. * DFDT(I,1) & + - 5. * DFDT(I,2) + DFDT(I,3) ) * DT / 24. + +END DO !I + + + +RETURN +END SUBROUTINE ABPRECOR + + ! *********************************************************************** + SUBROUTINE LMATRIX ( m, p, matrixMode,ErrStat, ErrMess) + ! LMATRIX calculates the [L_***] matrix using Gamma matrix and xkai=X. + ! matrixMode = 1 : Calculate [L_cos] matrix + ! matrixMode = 2 : Calculate [L_sin] matrix + ! *********************************************************************** + +IMPLICIT NONE + ! Passed Variables: + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables +TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters +INTEGER ,INTENT(IN) :: matrixMode + +INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation +CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + +REAL(ReKi) :: X + + + ! Local Variables: + +REAL(ReKi) :: XM + +INTEGER :: IROW +INTEGER :: JCOL + + ErrStat = ErrID_None + ErrMess = "" + + +X = m%DynInflow%xKai + + ! Check the value of X +IF ( ( X < -1.) .OR. ( X > 1.) ) THEN +! IF ( ( X < 0.) .OR. ( X > 1.) ) THEN + ErrStat = ErrID_Fatal + ErrMess = 'LMATRIX: Value of X = '//TRIM(Num2LStr(X))//' must be between -1 and 1.' + RETURN +ENDIF + +SELECT CASE ( matrixMode ) + + ! Calculate the rows for r=0 of [L_cos] matrix, + ! which needs a separate formula. + CASE (1) + DO JCOL = 1, maxInfl + XM = X ** MRvector(JCOL) + DO IROW = 1, p%DynInflow%MaxInflo + m%DynInflow%xLcos( IROW, JCOL ) = m%DynInflow%gamma( IROW, JCOL ) * XM + END DO !IROW + END DO !JCOL + + ! Calculate the [L_cos] matrix, + ! the rows for r=1 and higher. + DO IROW = p%DynInflow%MaxInflo+1, maxInfl + DO JCOL = 1, maxInfl + m%DynInflow%xLcos( IROW, JCOL ) = m%DynInflow%GAMMA( IROW, JCOL ) & + *( X ** m%DynInflow%MminusR( IROW, JCOL ) & + + X ** m%DynInflow%MplusR ( IROW, JCOL ) & + * (-1.) ** m%DynInflow%MminR ( IROW, JCOL ) ) + END DO !JCOL + END DO !IROW + + ! Calculate [L_sin] matrix. + CASE (2) + DO IROW = p%DynInflow%MaxInflo+1, maxInfl + DO JCOL = p%DynInflow%MaxInflo+1, maxInfl + m%DynInflow%xLsin( IROW, JCOL ) = m%DynInflow%GAMMA( IROW, JCOL ) & + *( X ** m%DynInflow%MminusR( IROW, JCOL ) & + - X ** m%DynInflow%MplusR ( IROW, JCOL ) & + * (-1.) ** m%DynInflow%MminR ( IROW, JCOL ) ) + END DO !JCOL + END DO !IROW + + CASE DEFAULT + CALL ProgAbort( 'Value of matrixMode = '//TRIM(Int2LStr(matrixMode))//' must be 1 or 2.') +END SELECT + +RETURN +END SUBROUTINE LMATRIX + + ! *********************************************************************** + SUBROUTINE MATINV( A0, A1, N, N0, invMode,ErrStat,ErrMsg ) + ! Inverts the [L_cos] and [L_sin] matrices. + ! Subroutine GAUSSJ (modified) from "Numerical Recipe" is needed. + ! invMode = 1 : Invert [L_cos] matrix + ! invMode = 2 : Invert [L_sin] matrix + !********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: +INTEGER ,INTENT(IN) :: invMode +INTEGER ,INTENT(IN) :: N +INTEGER ,INTENT(IN) :: N0 + +REAL(ReKi),INTENT(INOUT) :: A0 ( N , N ) +REAL(ReKi),INTENT(INOUT) :: A1 ( N0+1:N , N0+1:N ) + +INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation +CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local Variables: + +REAL(ReKi) :: DUMMY( N-N0, N-N0 ) + +INTEGER :: I +INTEGER :: J + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Invert [L_cos] in all cases + ! [L_cos] matrix can be inverted without a dummy. + ! Invert the [A0]=[L_cos] matrix by Gauss-Jordan Method +SELECT CASE ( invMode ) + + CASE (1) + CALL GAUSSJ(A0,N,ErrStat,ErrMsg) + IF (ErrStat /= ErrID_None) THEN + ErrMsg = 'MATINV:'//TRIM(ErrMsg) + RETURN + END IF + + ! [L_sin] matrix needs a dummy array, because the index goes + ! from MaxInflo(=N0) to maxInfl(=N), + ! which is incompatible with SUBROUTINE GAUSSJ. + !BJJ: IS THIS REALLY NECESSARY? Aren't the indicies an abstraction?? if you pass an array (1:3) and use it as (0:2) in another subroutine, it's really okay??? + CASE (2) + DO I=1,N-N0 + DO J=1,N-N0 + DUMMY(I,J) = A1(I+N0,J+N0) + END DO !J + END DO !I + + ! Invert the [A1]=[L_sin] matrix by Gauss-Jordan Method. + CALL GAUSSJ(DUMMY,N-N0,ErrStat,ErrMsg) + IF (ErrStat /= ErrID_None) THEN + ErrMsg = 'MATINV:'//TRIM(ErrMsg) + RETURN + END IF + + ! Put the dummy back into [A1]=[L_sin]. + DO I=1,N-N0 + DO J=1,N-N0 + A1(I+N0,J+N0) = DUMMY(I,J) + END DO !J + END DO !I + + CASE DEFAULT + CALL ProgAbort( 'Value of invMode = '//TRIM(Int2LStr(invMode))//' must be 1 or 2.') + IF (ErrStat >= AbortErrLev) RETURN + + +END SELECT + + + +RETURN +END SUBROUTINE MATINV + + ! *********************************************************************** + SUBROUTINE gaussj(a,n, ErrStat, ErrMsg) + ! Invert a matrix by Gauss-Jordan Method. The original source code + ! from "Numerical Recipe" was slightly modified. + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: +INTEGER , INTENT(IN) :: n +REAL(ReKi), INTENT(INOUT) :: a(n,n) + +INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation +CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local Variables: + +INTEGER , PARAMETER :: NMAX = 6 + +REAL(ReKi) :: big +REAL(ReKi) :: dum +REAL(ReKi) :: pivinv + +INTEGER :: i +INTEGER :: icol +INTEGER :: indxc(NMAX) +INTEGER :: indxr(NMAX) +INTEGER :: ipiv(NMAX) +INTEGER :: irow +INTEGER :: j +INTEGER :: k +INTEGER :: l +INTEGER :: ll + + +ErrStat=ErrID_None +ErrMsg="" + +DO j=1,n + ipiv(j)=0 +END DO !j +DO i=1,n + big=0. + DO j=1,n + IF (ipiv(j) /= 1) THEN + DO k=1,n + IF (ipiv(k) == 0) THEN + IF (ABS(a(j,k)) >= big) THEN + big=ABS(a(j,k)) + irow=j + icol=k + ENDIF + + ELSE IF (ipiv(k) > 1) THEN + ErrStat = ErrID_Fatal + ErrMsg = "gaussj: Singular matrix encountered." + RETURN + ENDIF + END DO !k + ENDIF + END DO !j + ipiv(icol)=ipiv(icol)+1 + IF (irow /= icol) THEN + DO l=1,n + dum=a(irow,l) + a(irow,l)=a(icol,l) + a(icol,l)=dum + END DO !l + ENDIF + indxr(i)=irow + indxc(i)=icol + IF (a(icol,icol) == 0.) THEN + ErrStat = ErrID_Fatal + ErrMsg = "gaussj: Singular matrix encountered." + RETURN + ENDIF + pivinv=1./a(icol,icol) + a(icol,icol)=1. + DO l=1,n + a(icol,l)=a(icol,l)*pivinv + END DO !l + DO ll=1,n + if (ll /= icol) THEN + dum=a(ll,icol) + a(ll,icol)=0. + DO l=1,n + a(ll,l)=a(ll,l)-a(icol,l)*dum + END DO !l + ENDIF + END DO !ll +END DO !i +DO l=n,1,-1 + IF (indxr(l) /= indxc(l)) THEN + + DO k=1,n + dum=a(k,indxr(l)) + a(k,indxr(l))=a(k,indxc(l)) + a(k,indxc(l))=dum + END DO !k + ENDIF +END DO !l + + + +RETURN +END SUBROUTINE gaussj + +! *********************************************************************** + FUNCTION FGAMMA( R, J, M, N ) +! Calculate the GAMMA matrix. It is NOT the statistical function. +! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi) :: FGAMMA +INTEGER ,INTENT(IN) :: J +INTEGER ,INTENT(IN) :: M +INTEGER ,INTENT(IN) :: N +INTEGER ,INTENT(IN) :: R + + +IF ( MOD(R+M,2) == 0 ) THEN + FGAMMA = (-1)**((N+J-2*R)*.5) * 2. & + * SQRT( REAL( (2*N+1) * (2*J+1), ReKi ) ) & + / SQRT( HFUNC(M,N) * HFUNC(R,J) ) & + / REAL( (J+N) * (J+N+2) * ((J-N)*(J-N)-1), ReKi ) + +ELSE IF ( ABS(J-N) == 1 ) THEN !bjj: why don't we use the pi() variable? or PibyTwo + FGAMMA = 3.14159265 * SIGN(1., REAL(R-M, ReKi) ) * .5 & + / SQRT( HFUNC(M,N) * HFUNC(R,J) ) & + / SQRT( REAL( (2*N+1) * (2*J+1) , ReKi) ) + +ELSE + FGAMMA = 0. + +ENDIF + + + +RETURN +END FUNCTION FGAMMA + + ! *********************************************************************** + FUNCTION HFUNC( M, N ) + ! Calculates the value of function H(m,n). + ! Warning: This subroutine is not optimized for large m or n. + ! Although H(m,n) is a well behaving function, it may + ! cause math overflow, if m or n is large. + !bjj: we only call with with the MRvector and NJvector (parameter) values. This could + ! possibly increase performance if implemented differently.... + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi) :: HFUNC + +INTEGER ,INTENT(IN) :: M +INTEGER ,INTENT(IN) :: N + + + ! Local Variables: + +INTEGER :: NMM ! n minus M +INTEGER :: NPM ! N plus M + + + +IF ( N <= M ) THEN + CALL ProgAbort( 'Value of N = '//TRIM(Int2LStr(N))//' must be geater than M = '//TRIM(Int2LStr(M))//'.' ) +ENDIF + +NPM = N + M +NMM = N - M + +HFUNC = ( REAL( IDUBFACT(NPM-1), ReKi ) / REAL( IDUBFACT(NPM), ReKi ) ) & + * ( REAL( IDUBFACT(NMM-1), ReKi ) / REAL( IDUBFACT(NMM), ReKi ) ) + + + +RETURN +END FUNCTION HFUNC + + ! *********************************************************************** + INTEGER FUNCTION IDUBFACT( I ) + ! Calculates the double factorial of an integer I + ! IDUBFACT( I ) = I!! = I*(I-2)*(I-4)*...*4*2 for I = even + ! or = I*(I-2)*(I-4)*...*3*1 for I = odd + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: +INTEGER ,INTENT(IN) :: I + + ! Local Variables: + +INTEGER :: K + + + +IF ( I >= 1 ) THEN + IDUBFACT = 1 + + DO K = I, 1, -2 + IDUBFACT = IDUBFACT * K + END DO !K + +ELSE IF ( I == 0 .OR. I == -1 ) THEN + IDUBFACT = 1 +ELSE IF ( I == -3 ) THEN ! use definition of n!! for odd negative numbers + IDUBFACT = -1 +ELSE + CALL ProgAbort( 'Double factorial is NOT defined for '//TRIM(Int2LStr(I))//' in FUNCTION IDUBFACT.') +ENDIF + + + +RETURN +END FUNCTION IDUBFACT + + ! *********************************************************************** + FUNCTION xphi( Rzero, mode,ErrStat, ErrMsg ) + ! Set up the PHI coefficients. They are the results from Mathematica. + ! phi(1) = sqrt( 3.) ! m=0, n=1 + ! phi(2) = 2*sqrt(7) (1.5 - 3.75 Rzero**2 ) / 3.! m=0, n=3 + ! phi(3) = sqrt( 15./ 2.) *Rzero ! m=1, n=2 + ! phi(4) = 4*(15/4 * Rzero - 105/16 *Rzero**3 )/sqrt(5)! m=1, n=4 + ! phi(5) = sqrt( 105./ 2.) / 2. *Rzero**2 ! m=2, n=3 + ! phi(6) = sqrt( 35.) *3. / 4. *Rzero**3 ! m=3, n=4 + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: +REAL(ReKi),INTENT(IN) :: Rzero +REAL(ReKi) :: xphi + +INTEGER ,INTENT(IN) :: mode +INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation +CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + +IF ( Rzero < 0. ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Value of Rzero = '//TRIM(Num2LStr(Rzero))//' must be larger than 0 in xphi().' + RETURN +ELSE IF ( Rzero > 1. ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Value of Rzero = '//TRIM(Num2LStr(Rzero))//' must be smaller than 1 in xphi().' + RETURN +ELSE + ErrStat = ErrID_None + ErrMsg = '' +ENDIF + +SELECT CASE ( mode ) + CASE (1) + xphi = 1.732051 + CASE (2) + xphi = 2.645751 - 6.6143783 * Rzero * Rzero + CASE (3) + xphi = 2.738613 * Rzero + CASE (4) + xphi = ( 6.708204 - 11.73936 * Rzero * Rzero ) * Rzero + CASE (5) + xphi = 3.622844 * Rzero * Rzero + CASE (6) + xphi = 4.437060 * Rzero * Rzero * Rzero + CASE DEFAULT + CALL ProgAbort('Integer MODE = '//TRIM(Int2LStr(MODE))//' must be 1 through 6.' ) +END SELECT + + + +RETURN +END FUNCTION xphi + + !*********************************************************************** + ! akihiro 06/25/00 + ! This subroutine is not currently used, may be used in the future. + ! + FUNCTION phis( Rzero, r, j ) + ! Calculates the PHI coefficients. This function is not used unless + ! the # of inflow states is increased greater than 10 (Mode 7 and higher) + ! *********************************************************************** + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi) :: phis +REAL(ReKi),INTENT(IN) :: Rzero + +INTEGER ,INTENT(IN) :: j +INTEGER ,INTENT(IN) :: r + + ! Local Variables: + +INTEGER :: q + + +IF ( Rzero < 0. ) THEN + CALL ProgAbort('Value of Rzero = '//TRIM(Num2LStr(Rzero))//' must be larger than 0 in phis().' ) +ELSE IF ( Rzero > 1. ) THEN + CALL ProgAbort('Value of Rzero = '//TRIM(Num2LStr(Rzero))//' must be smaller than 1 in phis().' ) +ENDIF + +phis = 0. + +DO q = r, j-1, 2 + phis = phis & + + Rzero ** q * (-1.) **((q-r)/2) * REAL( idubfact(j+q), ReKi ) & + / REAL( idubfact(q-r) * idubfact(q+r) * idubfact(j-q-1), ReKi ) +END DO !q + +phis = phis * SQRT( REAL( 2*j+1, ReKi ) * hfunc(r,j) ) + + +RETURN +END FUNCTION phis + + +!*********************************************************** +SUBROUTINE WindAzimuthZero (psi,VrotorY,VrotorZ,WindPsi) +! Subroutine added by JRS to define the zero azimuth datum in +! a wind based co-ordinate system, for USE in the dynamic inflow +! routines. +! Calculates the rotational measurement in radians +! of the resultant of two vectors, VrotorZ and VrotorY. +! VrotorZ is positive vertically upwards and negative vertically +! downwards, VrotorY is positive to the left and negative +! to the right, both when looking towards the rotor from upwind. +! Zero degrees azimuth is defined when veritically down +! and rises with a clockwise rotation. + + +IMPLICIT NONE + + + ! Passed Variables: +REAL(ReKi),INTENT(IN) :: psi,VrotorY,VrotorZ +REAL(ReKi),INTENT(OUT) :: WindPsi + +WindPsi = psi - ATAN2(VrotorY,-VrotorZ) + +RETURN +END SUBROUTINE WindAzimuthZero + + ! ************* END OF FILE *************** + +! ******************************************************************** +!==================================================================================================== +SUBROUTINE CheckRComp( P, x, xd, z, m, y, ErrStat, ErrMess, & + ADFile, HubRadius, TipRadius ) +! This routine checks to see if RElm(:) and DR(:) are compatible within a millimeter; +!---------------------------------------------------------------------------------------------------- + IMPLICIT NONE + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + INTEGER, INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMess + + ! Passed variables + + CHARACTER(*), INTENT(IN) :: ADFile ! Name of the AeroDyn input file, used for printing error message + REAL(ReKi), INTENT(IN) :: HubRadius ! Hub radius, used to verify that RElm and DR are input correctly + REAL(ReKi), INTENT(IN) :: TipRadius ! Tip radius, used to verify that RElm and DR are input correctly + + + ! Local variables. + + REAL(ReKi) :: DRNodesNew(P%Element%NElm) ! Length of variable-spaced blade elements--calculated from input RElm(:). + REAL(ReKi) :: DRSum ! Sum of DRs--should be close to TipRadius + REAL(ReKi), PARAMETER :: EPS = EPSILON(HubRadius) ! A small value used to compare two numbers + + INTEGER :: I ! Generic index. + + CHARACTER(33) :: DRChange ! A string showing how to change DR to get campatibility + + + + ! Initialize ErrStat to 0 (no error): + + ErrStat = ErrID_None + ErrMess = "" + + + ! Calculate DRNodesNew(:) based on input RElm(:) and compare to input DR(:): + +! AssumedHubRadius = P%Element%RElm(1) - 0.5*P%Blade%DR(1) + DRNodesNew(1) = 2.0*( P%Element%RElm(1) - HubRadius ) + DRSum = DRNodesNew(1) + HubRadius + + IF ( DRNodesNew(1) <= EPS ) THEN ! Check to see if RElm(1) > HubRad; if not, ProgAbort program + ErrMess = 'CheckRComp: RElm(1) must be larger than the hub radius (HubRadius = RElm(1) - 0.5*DR(1)). ' + ErrStat = ErrID_Fatal + RETURN + ELSEIF ( ABS( DRNodesNew(1) - P%Blade%DR(1) ) > 0.001 ) THEN ! Check to see if the calculated DRNodes(1) is close to the inputted DRNodes(1); if not, set flag--this will cause the program to ProgAbort later. + !ErrMess = ' this error message will be written at the end of the routine ' + ErrStat = ErrID_Fatal + ENDIF + + DO I = 2,P%Element%NElm ! Loop through all but the innermost blade element + + DRNodesNew(I) = 2.0*( P%Element%RElm(I) - P%Element%RElm(I-1) ) - DRNodesNew(I-1) + DRSum = DRSum + DRNodesNew(I) + + + IF ( DRNodesNew(I) <= EPS ) THEN ! Check to see if it is possible to have compatible DR(:) with the input RElm(:); if not, abort program + ErrMess = 'CheckRComp: RElm('//TRIM( Int2LStr(I) )//') produces ill-conditioned DR(:)' + ErrStat = ErrID_Fatal + RETURN + ELSEIF ( ABS( DRNodesNew(I) - P%Blade%DR(I) ) > 0.001 ) THEN ! Check to see if the calculated DRNodes(I) is close to the inputted DRNodes(I); if not, set flag--this will cause the program to Abort later. + !ErrMess = ' this error message will be written at the end of the routine ' + ErrStat = ErrID_Fatal + ENDIF + + END DO ! I - all but the innermost blade element + + + ! Abort program if necessary + + IF ( ErrStat /= ErrID_None ) THEN + + ! Write error message since the input DR(:) are not close to the calculated DRNodesNew(:) + + ErrMess = ' Input values for DR(:) are not compatible with input RElm(:).' + CALL WrScr1(TRIM(ErrMess)) + CALL WrScr( ' To make them compatible, please modify DR in the AeroDyn input file, '// TRIM( ADFile ) //', as follows:' ) + CALL WrScr1(' DR (Old) --> DR (New) ') + + DO I = 1,P%Element%NElm + WRITE( DRChange, "(' ', F13.4, ' --> ', F13.4, ' ')" ) P%Blade%DR(I), DRNodesNew(I) + CALL WrScr( DRChange ) + ENDDO !I + + ErrMess = 'CheckRComp: '//TRIM(ErrMess) + RETURN + + ELSEIF ( ABS( DRSum - TipRadius ) > 0.001 ) THEN + + ! Abort program since SUM( DRNodes(:) ) /= ( TipRadius - HubRadius) + + ErrMess = 'CheckRComp: TipRadius must be equal to HubRadius + SUM( P%Blade%DR(:) ).' + ErrStat = ErrID_Fatal + + RETURN + + ENDIF + + + RETURN +END SUBROUTINE CheckRComp + + +END MODULE AeroSubs diff --git a/OpenFAST/modules/aerodyn14/src/DWM.f90 b/OpenFAST/modules/aerodyn14/src/DWM.f90 new file mode 100644 index 000000000..2889057e3 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM.f90 @@ -0,0 +1,341 @@ +MODULE DWM + USE DWM_Types + USE NWTC_Library + USE DWM_Wake_Sub + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: DWM_Ver = ProgDesc( 'DWM', '', '' ) + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: DWM_Init ! Initialization routine + PUBLIC :: DWM_End ! Ending routine (includes clean up) + + PUBLIC :: DWM_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + + PUBLIC :: DWM_phase1 + + PUBLIC :: DWM_phase2 + + PUBLIC :: DWM_phase3 + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMess ) +! +! 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. +! The initial states and initial guess for the input are defined. +!.................................................................................................................................. + USE InflowWind + + !bjj: for a true FAST module, u,p,x,xs,z,OtherState, and y should be INTENT(OUT) instead of INTENT(INOUT) + + TYPE(DWM_InitInputType), INTENT(INOUT) :: InitInp ! Input data for initialization routine + TYPE(DWM_InputType), INTENT(INOUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(DWM_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(DWM_OtherStateType), INTENT(INOUT) :: OtherState ! Initial other states + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval ! Coupling interval in seconds: the rate that + ! (1) Mod1_UpdateStates() is called in loose coupling & + ! (2) Mod1_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + TYPE(DWM_InitOutputType), INTENT( OUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + ! Display the module information + CALL WrScr('') + CALL DispNVD(DWM_Ver) + + ! read the wind file for DWM + + CALL WrScr(" Reading the wind file for DWM simulation." ) + + ! InitInp%IfW%InputFileName is already set in FAST + InitInp%IfW%UseInputFile = .TRUE. + InitInp%IfW%NumWindPoints = 1 + InitInp%IfW%lidar%SensorType = SensorType_None + InitInp%IfW%Use4Dext = .false. + + CALL InflowWind_Init( InitInp%IfW, u%IfW, p%IfW, x%IfW, xd%IfW, z%IfW, OtherState%IfW, y%IfW, m%IfW, & + Interval, InitOut%IfW, ErrStat, ErrMess ) + + ! Read the parameter data from the text input file + + CALL read_parameter_file( p ) + + ! Read the turbine position index + + CALL read_turbine_position( m, p, u ) + + ! Read the result from upwind turbines + + CALL read_upwind_result_file( m, p, u ) + +END SUBROUTINE DWM_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! This routine is called at the end of the simulation. +!.................................................................................................................................. + USE InflowWind + + TYPE(DWM_InputType), INTENT(INOUT) :: u ! System inputs + TYPE(DWM_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states + TYPE(DWM_OtherStateType), INTENT(INOUT) :: OtherState ! Other/optimization states + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! System outputs + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMess = "" + + + ! Place any last minute operations or calculations here: + CALL DWM_phase4( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) + + CALL write_result_file( m, p, y, u ) + + CALL InflowWind_End( u%IfW, p%IfW, x%IfW, xd%IfW, z%IfW, OtherState%IfW, y%IfW, m%IfW, ErrStat, ErrMess ) + + ! Close files here: + + + + ! Destroy the input data: + + CALL DWM_DestroyInput( u, ErrStat, ErrMess ) + + + ! Destroy the parameter data: + + CALL DWM_DestroyParam( p, ErrStat, ErrMess ) + + + ! Destroy the state data: + + CALL DWM_DestroyContState( x, ErrStat, ErrMess ) + CALL DWM_DestroyDiscState( xd, ErrStat, ErrMess ) + CALL DWM_DestroyConstrState( z, ErrStat, ErrMess ) + CALL DWM_DestroyOtherState( OtherState, ErrStat, ErrMess ) + + + ! Destroy the output data: + + CALL DWM_DestroyOutput( y, ErrStat, ErrMess ) + + + +END SUBROUTINE DWM_End + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_UpdateStates( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMess ) +! Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states +! Constraint states are solved for input Time; Continuous and discrete states are updated for Time + Interval +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(DWM_InputType), INTENT(IN ) :: u ! Inputs at Time + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! Input: Continuous states at Time; + ! Output: Continuous states at Time + Interval + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at Time; + ! Output: Discrete states at Time + Interval + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! Input: Constraint states at Time; + ! Output: Constraint states at Time + Interval + TYPE(DWM_OtherStateType), INTENT(INOUT) :: OtherState ! Input: Other states at Time; + ! Output: Other states at Time + Interval + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + ErrStat = ErrID_None + ErrMess = "" + +END SUBROUTINE DWM_UpdateStates + +!--------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_phase1( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! DWM_phase1 subroutine +! it is called at every time step for each blade and element, +! used to superimpose the wake velocity from upwind turbine onto the downwind turbine in the AeroDyn_CalcOutput, +! then to perform loads and power analysis. +!................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(DWM_InputType), INTENT(IN ) :: u ! Inputs at Time + TYPE(DWM_ParameterType) ,INTENT(IN ) :: p ! Parameters + TYPE(DWM_ContinuousStateType) ,INTENT(IN ) :: x ! Continuous states at Time + TYPE(DWM_DiscreteStateType) ,INTENT(IN ) :: xd ! Discrete states at Time + TYPE(DWM_ConstraintStateType) ,INTENT(IN ) :: z ! Constraint states at Time + TYPE(DWM_OtherStateType), INTENT(IN ) :: OtherState ! Other states at Time + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + ErrStat = ErrID_None + ErrMess = "" + + m%shifted_velocity_aerodyn = shifted_velocity( Time, p, m, m%position_y, m%position_z, & + u%upwind_result%upwind_meanU (m%DWM_tb%Aerodyn_turbine_num ),& + u%upwind_result%upwind_U (m%DWM_tb%Aerodyn_turbine_num,: ),& + u%upwind_result%upwind_wakecenter (m%DWM_tb%Aerodyn_turbine_num,:,:,:),& + p%RTPD %upwind_turbine_projected_distance(m%DWM_tb%Aerodyn_turbine_num ),& + p%RTPD %upwind_align_angle (m%DWM_tb%Aerodyn_turbine_num ) ) + +END SUBROUTINE DWM_phase1 + +!--------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_phase2( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! DWM phase2 subroutine +! it is called at every time step for each blade and element, +! used to calculate the average wind speed on blade for different nodal positions. +!................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(DWM_InputType) ,INTENT(IN ) :: u ! Inputs at Time + TYPE(DWM_ParameterType) ,INTENT(IN ) :: p ! Parameters + TYPE(DWM_ContinuousStateType) ,INTENT(IN ) :: x ! Continuous states at Time + TYPE(DWM_DiscreteStateType) ,INTENT(IN ) :: xd ! Discrete states at Time + TYPE(DWM_ConstraintStateType) ,INTENT(IN ) :: z ! Constraint states at Time + TYPE(DWM_OtherStateType), INTENT(IN ) :: OtherState ! Other states at Time + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + ErrStat = ErrID_None + ErrMess = "" + + CALL turbine_average_velocity( p, m, m%U_velocity, m%DWM_tb%Blade_index, m%DWM_tb%Element_index, y%Mean_FFWS_array ) + + +END SUBROUTINE DWM_phase2 + +!--------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_phase3( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! DWM phase2 subroutine +! it is called at every time step (after finishing looping over the blade elements) , +! to calculate the cumulative time averaged induction factor. +!................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(DWM_InputType) ,INTENT(IN ) :: u ! Inputs at Time + TYPE(DWM_ParameterType) ,INTENT(IN ) :: p ! Parameters + TYPE(DWM_ContinuousStateType) ,INTENT(IN ) :: x ! Continuous states at Time + TYPE(DWM_DiscreteStateType) ,INTENT(IN ) :: xd ! Discrete states at Time + TYPE(DWM_ConstraintStateType) ,INTENT(IN ) :: z ! Constraint states at Time + TYPE(DWM_OtherStateType), INTENT(IN ) :: OtherState ! Other states at Time + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + ErrStat = ErrID_None + ErrMess = "" + CALL filter_average_induction_factor( m, p, y, m%Nforce, p%ElementNum, m%blade_dr ) + + m%FAST_Time = Time + + +END SUBROUTINE DWM_phase3 + +!--------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE DWM_phase4( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMess ) +! DWM phase2 subroutine +! contains the main subroutines that calculate the wake deficit and meandered wake center location. (no time integration) +!................................................................................................................................. + + TYPE(DWM_InputType), INTENT(INOUT) :: u ! Inputs at Time + TYPE(DWM_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states at Time + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states at Time + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states at Time + TYPE(DWM_OtherStateType), INTENT(INOUT) :: OtherState ! Other/optimization states + TYPE(DWM_OutputType), INTENT(INOUT) :: y ! Outputs computed at Time (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + + ErrStat = ErrID_None + ErrMess = "" + + !CALL calculate_SD_averagePower( OtherState,y ) + + CALL calculate_mean_u( m, p, u, p%ElementNum, p%ElementRad(:), y%Mean_FFWS, y%TI, m%FAST_Time) + + + CALL get_initial_condition ( m, p, u, y, y%induction_factor, p%ElementRad(:), p%ElementNum, y%r_initial, y%U_initial ) + + CALL calculate_wake ( m, p, y, y%r_initial, y%U_initial, p%ElementNum, y%wake_u, m%WMC%wake_width ) + + !--test-- + !ALLOCATE ( y%wake_u(1750,250) ) + !y%wake_u(:,:) = 0.75 + !m%DWDD%n_x_vector = 1750 + !m%DWDD%n_r_vector = 250 + !ALLOCATE ( m%DWDD%Turb_Stress_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + !m%DWDD%Turb_Stress_DWM = 0.1 + !m%DWDD%ppR = 50 + !------- + + CALL Get_wake_center ( OtherState, m, p, y, u, x, xd, z, m%WMC%wake_width, y%wake_position ) + + + IF (p%RTPD%downwindturbine_number >0 ) THEN + DO I = 1,p%RTPD%downwindturbine_number + CALL smooth_out_wake(m, p, y%wake_u,y%wake_position,u%Upwind_result%smoothed_velocity_array(I,:),p%RTPD%downwind_turbine_projected_distance(I),& + p%RTPD%downwind_align_angle(I),u%Upwind_result%vel_matrix(I,:,:)) + u%Upwind_result%TI_downstream (I) = TI_downstream_total (m, p, y, p%RTPD%downwind_turbine_projected_distance(I),& + p%RTPD%downwind_align_angle(I),u%Upwind_result%vel_matrix(I,:,:)) + u%Upwind_result%small_scale_TI_downstream (I) = smallscale_TI (m, p, y, p%RTPD%downwind_turbine_projected_distance(I),& + p%RTPD%downwind_align_angle(I),u%Upwind_result%vel_matrix(I,:,:)) + + END DO + END IF + + +END SUBROUTINE DWM_phase4 + +END MODULE DWM + + + + + \ No newline at end of file diff --git a/OpenFAST/modules/aerodyn14/src/DWM_Types.f90 b/OpenFAST/modules/aerodyn14/src/DWM_Types.f90 new file mode 100644 index 000000000..414686d85 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM_Types.f90 @@ -0,0 +1,9855 @@ +!STARTOFREGISTRYGENERATEDFILE 'DWM_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 +!********************************************************************************************************************************* +! DWM_Types +!................................................................................................................................. +! This file is part of DWM. +! +! 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 DWM. 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 DWM_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE IfW_UniformWind_Types +USE IfW_FFWind_Base_Types +USE IfW_TSFFWind_Types +USE IfW_BladedFFWind_Types +USE IfW_HAWCWind_Types +USE IfW_UserWind_Types +USE IfW_4Dext_Types +USE Lidar_Types +USE InflowWind_Types +USE NWTC_Library +IMPLICIT NONE +! ========= CVSD ======= + TYPE, PUBLIC :: CVSD + INTEGER(IntKi) :: counter = 0 !< [-] + REAL(ReKi) :: Denominator = 0.0 !< [-] + REAL(ReKi) :: Numerator = 0.0 !< [-] + END TYPE CVSD +! ======================= +! ========= turbine_average_velocity_data ======= + TYPE, PUBLIC :: turbine_average_velocity_data + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: average_velocity_array_temp !< the average velocity of the whole blade sections in a specific time step [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: average_velocity_array !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: swept_area !< [m2] + INTEGER(IntKi) :: time_step_velocity = -1 !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: time_step_velocity_array !< [-] + INTEGER(IntKi) :: time_step_pass_velocity = -1 !< [-] + INTEGER(IntKi) :: time_step_force = -1 !< [-] + END TYPE turbine_average_velocity_data +! ======================= +! ========= DWM_Wake_Deficit_Data ======= + TYPE, PUBLIC :: DWM_Wake_Deficit_Data + INTEGER(IntKi) :: np_x !< point per axial distance [-] + REAL(ReKi) :: X_length !< normalized length in axial direction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Turb_Stress_DWM !< [-] + INTEGER(IntKi) :: n_x_vector !< [-] + INTEGER(IntKi) :: n_r_vector !< [-] + REAL(ReKi) :: ppR !< Point_per_R_resoulution [-] + END TYPE DWM_Wake_Deficit_Data +! ======================= +! ========= MeanderData ======= + TYPE, PUBLIC :: MeanderData + INTEGER(IntKi) :: scale_factor !< [-] + INTEGER(IntKi) :: moving_time !< [-] + END TYPE MeanderData +! ======================= +! ========= read_turbine_position_data ======= + TYPE, PUBLIC :: read_turbine_position_data + INTEGER(IntKi) :: SimulationOrder_index !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Turbine_sort_order !< [-] + INTEGER(IntKi) :: WT_index !< wind turbine index in the wind farm [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: TurbineInfluenceData !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: upwind_turbine_index !< the upwind turbines that affecting this turbine [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: downwind_turbine_index !< [-] + INTEGER(IntKi) :: upwindturbine_number !< the number of upwind turbines affecting the downwind turbine [-] + INTEGER(IntKi) :: downwindturbine_number !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: turbine_windorigin_length !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_turbine_projected_distance !< the projected distance between two turbines [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: downwind_turbine_projected_distance !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: turbine_angle !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_align_angle !< the angle beween the line connecting the upwind turbine and this turbine and the wind direction vector [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: downwind_align_angle !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_turbine_Xcoor !< the coordinate of the upwind turbine which affects this investigated turbine [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_turbine_Ycoor !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: wind_farm_Xcoor !< the coordinates of all the turbines in the wind farm [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: wind_farm_Ycoor !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: downwind_turbine_Xcoor !< the coordinate of the downwind turbine which is affected by this investigated turbine [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: downwind_turbine_Ycoor !< [-] + END TYPE read_turbine_position_data +! ======================= +! ========= WeiMethod ======= + TYPE, PUBLIC :: WeiMethod + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: sweptarea !< [-] + REAL(ReKi) :: weighting_denominator !< [-] + END TYPE WeiMethod +! ======================= +! ========= TIDownstream ======= + TYPE, PUBLIC :: TIDownstream + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI_downstream_matrix !< [-] + INTEGER(IntKi) :: i !< [-] + INTEGER(IntKi) :: j !< [-] + INTEGER(IntKi) :: k !< [-] + INTEGER(IntKi) :: cross_plane_position_ds !< the cross plane position which to be investigated in term of the flying time [-] + INTEGER(IntKi) :: cross_plane_position_TI !< the cross plane position which to be investigated in term of the n_x_vector [-] + INTEGER(IntKi) :: distance_index !< the index of the distance in the TI axisymmetric array [-] + INTEGER(IntKi) :: counter1 !< [-] + INTEGER(IntKi) :: counter2 !< [-] + INTEGER(IntKi) :: initial_timestep !< [-] + REAL(ReKi) :: y_axis_turbine !< [-] + REAL(ReKi) :: z_axis_turbine !< [-] + REAL(ReKi) :: distance !< the distance between one point to the meandered wake center [-] + REAL(ReKi) :: TI_downstream_node !< the TI at a specfic point in the inbestigated cross plane [-] + REAL(ReKi) :: TI_node_temp !< [-] + REAL(ReKi) :: TI_node !< [-] + REAL(ReKi) :: TI_accumulation !< [-] + REAL(ReKi) :: TI_apprant_accumulation !< [-] + REAL(ReKi) :: TI_average !< THE AVERAGE TI OF THE CROSS PLANE [-] + REAL(ReKi) :: TI_apprant !< The TI due to the meadering [-] + REAL(ReKi) :: HubHt !< [-] + REAL(ReKi) :: wake_center_y !< [-] + REAL(ReKi) :: wake_center_z !< [-] + REAL(ReKi) :: Rscale !< [-] + REAL(ReKi) :: y !< [-] + REAL(ReKi) :: z !< [-] + REAL(ReKi) :: zero_spacing !< [-] + REAL(ReKi) :: temp1 !< [-] + REAL(ReKi) :: temp2 !< [-] + REAL(ReKi) :: temp3 !< [-] + END TYPE TIDownstream +! ======================= +! ========= TurbKaimal ======= + TYPE, PUBLIC :: TurbKaimal + INTEGER(IntKi) :: fs !< sample frequency [-] + INTEGER(IntKi) :: temp_n !< [-] + INTEGER(IntKi) :: i !< [-] + REAL(ReKi) :: low_f !< lower bound of frequency range [-] + REAL(ReKi) :: high_f !< upper bound of frequency range [-] + REAL(ReKi) :: lk_facor !< turbulence length-scale [-] + REAL(ReKi) :: STD !< standard deviation of the turbulence [-] + END TYPE TurbKaimal +! ======================= +! ========= Shinozuka ======= + TYPE, PUBLIC :: Shinozuka + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: f_syn !< frequency series [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: t_syn !< time series [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: phi !< random phase angle [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: p_k !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: a_k !< [-] + INTEGER(IntKi) :: num_points !< total number of points [-] + INTEGER(IntKi) :: ILo !< [-] + INTEGER(IntKi) :: i !< [-] + INTEGER(IntKi) :: j !< [-] + REAL(ReKi) :: dt !< time step [-] + REAL(ReKi) :: t_min !< [-] + REAL(ReKi) :: t_max !< [-] + REAL(ReKi) :: df !< frequency step [-] + END TYPE Shinozuka +! ======================= +! ========= smooth_out_wake_data ======= + TYPE, PUBLIC :: smooth_out_wake_data + INTEGER(IntKi) :: length_velocity_array !< the length of velocity_array [-] + END TYPE smooth_out_wake_data +! ======================= +! ========= SWSV ======= + TYPE, PUBLIC :: SWSV + INTEGER(IntKi) :: p1 !< [-] + INTEGER(IntKi) :: p2 !< [-] + REAL(ReKi) :: distance !< the distance from the point to the meandered wake center [-] + REAL(ReKi) :: y0 !< wake center position on y axis [-] + REAL(ReKi) :: z0 !< wake center position on z axis [-] + REAL(ReKi) :: unit !< single unit length R/ppR [-] + END TYPE SWSV +! ======================= +! ========= read_upwind_result ======= + TYPE, PUBLIC :: read_upwind_result + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: upwind_U !< [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: upwind_wakecenter !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_meanU !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_TI !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: upwind_small_TI !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: upwind_smoothWake !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: velocity_aerodyn !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TI_downstream !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: small_scale_TI_downstream !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: smoothed_velocity_array !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: vel_matrix !< The smoothed out wake velocity matrix for n downwind turbine [-] + END TYPE read_upwind_result +! ======================= +! ========= wake_meandered_center ======= + TYPE, PUBLIC :: wake_meandered_center + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: wake_width !< wake width [-] + END TYPE wake_meandered_center +! ======================= +! ========= DWM_turbine_blade ======= + TYPE, PUBLIC :: DWM_turbine_blade + INTEGER(IntKi) :: Aerodyn_turbine_num !< [-] + INTEGER(IntKi) :: Blade_index !< the index of Aerodyn Blade [-] + INTEGER(IntKi) :: Element_index !< the index of Aerodyn Element [-] + END TYPE DWM_turbine_blade +! ======================= +! ========= DWM_ParameterType ======= + TYPE, PUBLIC :: DWM_ParameterType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: velocityU !< the wake velocity profile @ the downstream turbine plane [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: smoothed_wake !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WakePosition !< meandered wake center [-] + INTEGER(IntKi) :: WakePosition_1 !< size of the WakePosition [-] + INTEGER(IntKi) :: WakePosition_2 !< size of the WakePosition [-] + INTEGER(IntKi) :: smooth_flag !< Whether or not use the smoothed out upstream wake profile (1-yes, 0-no) [-] + INTEGER(IntKi) :: p_p_r !< [-] + INTEGER(IntKi) :: NumWT !< Number of wind turbines [-] + INTEGER(IntKi) :: Tinfluencer !< [-] + REAL(ReKi) :: RotorR !< Rotor radius [-] + REAL(ReKi) :: r_domain !< [-] + REAL(ReKi) :: x_domain !< [-] + REAL(ReKi) :: Uambient !< The ambient wind velocity [-] + REAL(ReKi) :: TI_amb !< Ambient turbulence intensity [%] + REAL(ReKi) :: TI_wake !< [-] + REAL(ReKi) :: hub_height !< [-] + REAL(ReKi) :: length_velocityU !< [-] + REAL(ReKi) :: WFLowerBd !< The lower bound height of the wind file [-] + REAL(ReKi) :: Wind_file_Mean_u !< The mean velocity of the first turbine [-] + REAL(ReKi) :: Winddir !< [-] + REAL(ReKi) :: air_density !< air density [-] + REAL(ReKi) :: RR !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ElementRad !< the element node radius [-] + INTEGER(IntKi) :: Bnum !< the number of blade [-] + INTEGER(IntKi) :: ElementNum !< the number of element [-] + TYPE(read_turbine_position_data) :: RTPD + TYPE(InflowWind_ParameterType) :: IfW + END TYPE DWM_ParameterType +! ======================= +! ========= DWM_OtherStateType ======= + TYPE, PUBLIC :: DWM_OtherStateType + TYPE(InflowWind_OtherStateType) :: IfW + END TYPE DWM_OtherStateType +! ======================= +! ========= DWM_MiscVarType ======= + TYPE, PUBLIC :: DWM_MiscVarType + TYPE(InflowWind_MiscVarType) :: IfW + REAL(ReKi) :: position_y !< the y position of the blade node [-] + REAL(ReKi) :: position_z !< the z position of the blade node [-] + REAL(ReKi) :: velocity_wake_mean !< [-] + REAL(ReKi) :: shifted_velocity_Aerodyn !< [-] + REAL(ReKi) :: U_velocity !< the u component velocity of blade [-] + REAL(ReKi) :: V_velocity !< the v component velocity of blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nforce !< the normal force [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: blade_dr !< blade dr [-] + REAL(ReKi) :: NacYaw !< [-] + REAL(ReKi) :: TI_original !< [-] + TYPE(turbine_average_velocity_data) :: TAVD + TYPE(CVSD) :: CalVelScale_data + TYPE(MeanderData) :: meandering_data + TYPE(WeiMethod) :: weighting_method + TYPE(TIDownstream) :: TI_downstream_data + TYPE(TurbKaimal) :: Turbulence_KS + TYPE(Shinozuka) :: shinozuka_data + TYPE(smooth_out_wake_data) :: SmoothOut + TYPE(SWSV) :: smooth_wake_shifted_velocity_data + TYPE(DWM_Wake_Deficit_Data) :: DWDD + REAL(ReKi) :: ct_tilde !< the tilde Ct [-] + REAL(ReKi) :: FAST_Time !< FAST simulation time [-] + INTEGER(IntKi) :: SDtimestep = 0 !< [-] + TYPE(DWM_turbine_blade) :: DWM_tb + TYPE(wake_meandered_center) :: WMC + END TYPE DWM_MiscVarType +! ======================= +! ========= DWM_InputType ======= + TYPE, PUBLIC :: DWM_InputType + TYPE(read_upwind_result) :: Upwind_result + TYPE(InflowWind_InputType) :: IfW + END TYPE DWM_InputType +! ======================= +! ========= DWM_OutputType ======= + TYPE, PUBLIC :: DWM_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: turbine_thrust_force !< [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: induction_factor !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: r_initial !< scaled rotor radius [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_initial !< scaled velocity at the rotor [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Mean_FFWS_array !< Mean velocity of each section on the blade [-] + REAL(ReKi) :: Mean_FFWS !< Mean (total) wind speed at the hub height [m/s] + REAL(ReKi) :: TI !< the turbulence intensity of the turbine [-] + REAL(ReKi) :: TI_downstream !< the TI of a downstream turbine before normalization [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: wake_u !< wake velocity [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: wake_position !< wake center position [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: smoothed_velocity_array !< smoothed out upstream axisymetric wake profile [-] + REAL(ReKi) :: AtmUscale !< atmospheric velocity scale before introducing TI [-] + REAL(ReKi) :: du_dz_ABL !< atmosperic shear gradient [-] + REAL(ReKi) :: total_SDgenpwr = 0.0 !< [-] + REAL(ReKi) :: mean_SDgenpwr !< [-] + REAL(ReKi) :: avg_ct !< average Ct over the rotor [-] + TYPE(InflowWind_OutputType) :: IfW + END TYPE DWM_OutputType +! ======================= +! ========= DWM_ContinuousStateType ======= + TYPE, PUBLIC :: DWM_ContinuousStateType + REAL(ReKi) :: dummy !< [-] + TYPE(InflowWind_ContinuousStateType) :: IfW + END TYPE DWM_ContinuousStateType +! ======================= +! ========= DWM_DiscreteStateType ======= + TYPE, PUBLIC :: DWM_DiscreteStateType + REAL(ReKi) :: dummy !< [-] + TYPE(InflowWind_DiscreteStateType) :: IfW + END TYPE DWM_DiscreteStateType +! ======================= +! ========= DWM_ConstraintStateType ======= + TYPE, PUBLIC :: DWM_ConstraintStateType + REAL(ReKi) :: dummy !< [-] + TYPE(InflowWind_ConstraintStateType) :: IfW + END TYPE DWM_ConstraintStateType +! ======================= +! ========= DWM_InitInputType ======= + TYPE, PUBLIC :: DWM_InitInputType + REAL(ReKi) :: dummy !< [-] + TYPE(InflowWind_InitInputType) :: IfW + END TYPE DWM_InitInputType +! ======================= +! ========= DWM_InitOutputType ======= + TYPE, PUBLIC :: DWM_InitOutputType + REAL(ReKi) :: dummy !< [-] + TYPE(InflowWind_InitOutputType) :: IfW + END TYPE DWM_InitOutputType +! ======================= +CONTAINS + SUBROUTINE DWM_CopyCVSD( SrcCVSDData, DstCVSDData, CtrlCode, ErrStat, ErrMsg ) + TYPE(CVSD), INTENT(IN) :: SrcCVSDData + TYPE(CVSD), INTENT(INOUT) :: DstCVSDData + 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 = 'DWM_CopyCVSD' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCVSDData%counter = SrcCVSDData%counter + DstCVSDData%Denominator = SrcCVSDData%Denominator + DstCVSDData%Numerator = SrcCVSDData%Numerator + END SUBROUTINE DWM_CopyCVSD + + SUBROUTINE DWM_DestroyCVSD( CVSDData, ErrStat, ErrMsg ) + TYPE(CVSD), INTENT(INOUT) :: CVSDData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyCVSD' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_DestroyCVSD + + SUBROUTINE DWM_PackCVSD( 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(CVSD), 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 = 'DWM_PackCVSD' + ! 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 ! counter + Re_BufSz = Re_BufSz + 1 ! Denominator + Re_BufSz = Re_BufSz + 1 ! Numerator + 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%counter + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Denominator + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Numerator + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackCVSD + + SUBROUTINE DWM_UnPackCVSD( 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(CVSD), 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 = 'DWM_UnPackCVSD' + ! 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%counter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Denominator = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Numerator = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackCVSD + + SUBROUTINE DWM_Copyturbine_average_velocity_data( Srcturbine_average_velocity_dataData, Dstturbine_average_velocity_dataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(turbine_average_velocity_data), INTENT(IN) :: Srcturbine_average_velocity_dataData + TYPE(turbine_average_velocity_data), INTENT(INOUT) :: Dstturbine_average_velocity_dataData + 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 = 'DWM_Copyturbine_average_velocity_data' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Srcturbine_average_velocity_dataData%average_velocity_array_temp)) THEN + i1_l = LBOUND(Srcturbine_average_velocity_dataData%average_velocity_array_temp,1) + i1_u = UBOUND(Srcturbine_average_velocity_dataData%average_velocity_array_temp,1) + IF (.NOT. ALLOCATED(Dstturbine_average_velocity_dataData%average_velocity_array_temp)) THEN + ALLOCATE(Dstturbine_average_velocity_dataData%average_velocity_array_temp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstturbine_average_velocity_dataData%average_velocity_array_temp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstturbine_average_velocity_dataData%average_velocity_array_temp = Srcturbine_average_velocity_dataData%average_velocity_array_temp +ENDIF +IF (ALLOCATED(Srcturbine_average_velocity_dataData%average_velocity_array)) THEN + i1_l = LBOUND(Srcturbine_average_velocity_dataData%average_velocity_array,1) + i1_u = UBOUND(Srcturbine_average_velocity_dataData%average_velocity_array,1) + IF (.NOT. ALLOCATED(Dstturbine_average_velocity_dataData%average_velocity_array)) THEN + ALLOCATE(Dstturbine_average_velocity_dataData%average_velocity_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstturbine_average_velocity_dataData%average_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstturbine_average_velocity_dataData%average_velocity_array = Srcturbine_average_velocity_dataData%average_velocity_array +ENDIF +IF (ALLOCATED(Srcturbine_average_velocity_dataData%swept_area)) THEN + i1_l = LBOUND(Srcturbine_average_velocity_dataData%swept_area,1) + i1_u = UBOUND(Srcturbine_average_velocity_dataData%swept_area,1) + IF (.NOT. ALLOCATED(Dstturbine_average_velocity_dataData%swept_area)) THEN + ALLOCATE(Dstturbine_average_velocity_dataData%swept_area(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstturbine_average_velocity_dataData%swept_area.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstturbine_average_velocity_dataData%swept_area = Srcturbine_average_velocity_dataData%swept_area +ENDIF + Dstturbine_average_velocity_dataData%time_step_velocity = Srcturbine_average_velocity_dataData%time_step_velocity +IF (ALLOCATED(Srcturbine_average_velocity_dataData%time_step_velocity_array)) THEN + i1_l = LBOUND(Srcturbine_average_velocity_dataData%time_step_velocity_array,1) + i1_u = UBOUND(Srcturbine_average_velocity_dataData%time_step_velocity_array,1) + IF (.NOT. ALLOCATED(Dstturbine_average_velocity_dataData%time_step_velocity_array)) THEN + ALLOCATE(Dstturbine_average_velocity_dataData%time_step_velocity_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstturbine_average_velocity_dataData%time_step_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstturbine_average_velocity_dataData%time_step_velocity_array = Srcturbine_average_velocity_dataData%time_step_velocity_array +ENDIF + Dstturbine_average_velocity_dataData%time_step_pass_velocity = Srcturbine_average_velocity_dataData%time_step_pass_velocity + Dstturbine_average_velocity_dataData%time_step_force = Srcturbine_average_velocity_dataData%time_step_force + END SUBROUTINE DWM_Copyturbine_average_velocity_data + + SUBROUTINE DWM_Destroyturbine_average_velocity_data( turbine_average_velocity_dataData, ErrStat, ErrMsg ) + TYPE(turbine_average_velocity_data), INTENT(INOUT) :: turbine_average_velocity_dataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroyturbine_average_velocity_data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(turbine_average_velocity_dataData%average_velocity_array_temp)) THEN + DEALLOCATE(turbine_average_velocity_dataData%average_velocity_array_temp) +ENDIF +IF (ALLOCATED(turbine_average_velocity_dataData%average_velocity_array)) THEN + DEALLOCATE(turbine_average_velocity_dataData%average_velocity_array) +ENDIF +IF (ALLOCATED(turbine_average_velocity_dataData%swept_area)) THEN + DEALLOCATE(turbine_average_velocity_dataData%swept_area) +ENDIF +IF (ALLOCATED(turbine_average_velocity_dataData%time_step_velocity_array)) THEN + DEALLOCATE(turbine_average_velocity_dataData%time_step_velocity_array) +ENDIF + END SUBROUTINE DWM_Destroyturbine_average_velocity_data + + SUBROUTINE DWM_Packturbine_average_velocity_data( 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(turbine_average_velocity_data), 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 = 'DWM_Packturbine_average_velocity_data' + ! 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 ! average_velocity_array_temp allocated yes/no + IF ( ALLOCATED(InData%average_velocity_array_temp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! average_velocity_array_temp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%average_velocity_array_temp) ! average_velocity_array_temp + END IF + Int_BufSz = Int_BufSz + 1 ! average_velocity_array allocated yes/no + IF ( ALLOCATED(InData%average_velocity_array) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! average_velocity_array upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%average_velocity_array) ! average_velocity_array + END IF + Int_BufSz = Int_BufSz + 1 ! swept_area allocated yes/no + IF ( ALLOCATED(InData%swept_area) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! swept_area upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%swept_area) ! swept_area + END IF + Int_BufSz = Int_BufSz + 1 ! time_step_velocity + Int_BufSz = Int_BufSz + 1 ! time_step_velocity_array allocated yes/no + IF ( ALLOCATED(InData%time_step_velocity_array) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! time_step_velocity_array upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%time_step_velocity_array) ! time_step_velocity_array + END IF + Int_BufSz = Int_BufSz + 1 ! time_step_pass_velocity + Int_BufSz = Int_BufSz + 1 ! time_step_force + 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%average_velocity_array_temp) ) 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%average_velocity_array_temp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%average_velocity_array_temp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%average_velocity_array_temp,1), UBOUND(InData%average_velocity_array_temp,1) + ReKiBuf(Re_Xferred) = InData%average_velocity_array_temp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%average_velocity_array) ) 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%average_velocity_array,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%average_velocity_array,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%average_velocity_array,1), UBOUND(InData%average_velocity_array,1) + ReKiBuf(Re_Xferred) = InData%average_velocity_array(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%swept_area) ) 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%swept_area,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%swept_area,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%swept_area,1), UBOUND(InData%swept_area,1) + ReKiBuf(Re_Xferred) = InData%swept_area(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%time_step_velocity + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%time_step_velocity_array) ) 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_step_velocity_array,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%time_step_velocity_array,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%time_step_velocity_array,1), UBOUND(InData%time_step_velocity_array,1) + IntKiBuf(Int_Xferred) = InData%time_step_velocity_array(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%time_step_pass_velocity + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%time_step_force + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_Packturbine_average_velocity_data + + SUBROUTINE DWM_UnPackturbine_average_velocity_data( 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(turbine_average_velocity_data), 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 = 'DWM_UnPackturbine_average_velocity_data' + ! 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 ! average_velocity_array_temp 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%average_velocity_array_temp)) DEALLOCATE(OutData%average_velocity_array_temp) + ALLOCATE(OutData%average_velocity_array_temp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%average_velocity_array_temp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%average_velocity_array_temp,1), UBOUND(OutData%average_velocity_array_temp,1) + OutData%average_velocity_array_temp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! average_velocity_array 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%average_velocity_array)) DEALLOCATE(OutData%average_velocity_array) + ALLOCATE(OutData%average_velocity_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%average_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%average_velocity_array,1), UBOUND(OutData%average_velocity_array,1) + OutData%average_velocity_array(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! swept_area 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%swept_area)) DEALLOCATE(OutData%swept_area) + ALLOCATE(OutData%swept_area(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%swept_area.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%swept_area,1), UBOUND(OutData%swept_area,1) + OutData%swept_area(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%time_step_velocity = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! time_step_velocity_array 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_step_velocity_array)) DEALLOCATE(OutData%time_step_velocity_array) + ALLOCATE(OutData%time_step_velocity_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%time_step_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%time_step_velocity_array,1), UBOUND(OutData%time_step_velocity_array,1) + OutData%time_step_velocity_array(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%time_step_pass_velocity = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%time_step_force = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_UnPackturbine_average_velocity_data + + SUBROUTINE DWM_CopyWake_Deficit_Data( SrcWake_Deficit_DataData, DstWake_Deficit_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_Wake_Deficit_Data), INTENT(IN) :: SrcWake_Deficit_DataData + TYPE(DWM_Wake_Deficit_Data), INTENT(INOUT) :: DstWake_Deficit_DataData + 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 = 'DWM_CopyWake_Deficit_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DstWake_Deficit_DataData%np_x = SrcWake_Deficit_DataData%np_x + DstWake_Deficit_DataData%X_length = SrcWake_Deficit_DataData%X_length +IF (ALLOCATED(SrcWake_Deficit_DataData%Turb_Stress_DWM)) THEN + i1_l = LBOUND(SrcWake_Deficit_DataData%Turb_Stress_DWM,1) + i1_u = UBOUND(SrcWake_Deficit_DataData%Turb_Stress_DWM,1) + i2_l = LBOUND(SrcWake_Deficit_DataData%Turb_Stress_DWM,2) + i2_u = UBOUND(SrcWake_Deficit_DataData%Turb_Stress_DWM,2) + IF (.NOT. ALLOCATED(DstWake_Deficit_DataData%Turb_Stress_DWM)) THEN + ALLOCATE(DstWake_Deficit_DataData%Turb_Stress_DWM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstWake_Deficit_DataData%Turb_Stress_DWM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstWake_Deficit_DataData%Turb_Stress_DWM = SrcWake_Deficit_DataData%Turb_Stress_DWM +ENDIF + DstWake_Deficit_DataData%n_x_vector = SrcWake_Deficit_DataData%n_x_vector + DstWake_Deficit_DataData%n_r_vector = SrcWake_Deficit_DataData%n_r_vector + DstWake_Deficit_DataData%ppR = SrcWake_Deficit_DataData%ppR + END SUBROUTINE DWM_CopyWake_Deficit_Data + + SUBROUTINE DWM_DestroyWake_Deficit_Data( Wake_Deficit_DataData, ErrStat, ErrMsg ) + TYPE(DWM_Wake_Deficit_Data), INTENT(INOUT) :: Wake_Deficit_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyWake_Deficit_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Wake_Deficit_DataData%Turb_Stress_DWM)) THEN + DEALLOCATE(Wake_Deficit_DataData%Turb_Stress_DWM) +ENDIF + END SUBROUTINE DWM_DestroyWake_Deficit_Data + + SUBROUTINE DWM_PackWake_Deficit_Data( 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(DWM_Wake_Deficit_Data), 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 = 'DWM_PackWake_Deficit_Data' + ! 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 ! np_x + Re_BufSz = Re_BufSz + 1 ! X_length + Int_BufSz = Int_BufSz + 1 ! Turb_Stress_DWM allocated yes/no + IF ( ALLOCATED(InData%Turb_Stress_DWM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Turb_Stress_DWM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Turb_Stress_DWM) ! Turb_Stress_DWM + END IF + Int_BufSz = Int_BufSz + 1 ! n_x_vector + Int_BufSz = Int_BufSz + 1 ! n_r_vector + Re_BufSz = Re_BufSz + 1 ! ppR + 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%np_x + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X_length + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Turb_Stress_DWM) ) 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%Turb_Stress_DWM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Turb_Stress_DWM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Turb_Stress_DWM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Turb_Stress_DWM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Turb_Stress_DWM,2), UBOUND(InData%Turb_Stress_DWM,2) + DO i1 = LBOUND(InData%Turb_Stress_DWM,1), UBOUND(InData%Turb_Stress_DWM,1) + ReKiBuf(Re_Xferred) = InData%Turb_Stress_DWM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%n_x_vector + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_r_vector + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ppR + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackWake_Deficit_Data + + SUBROUTINE DWM_UnPackWake_Deficit_Data( 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(DWM_Wake_Deficit_Data), 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 = 'DWM_UnPackWake_Deficit_Data' + ! 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%np_x = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%X_length = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Turb_Stress_DWM 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%Turb_Stress_DWM)) DEALLOCATE(OutData%Turb_Stress_DWM) + ALLOCATE(OutData%Turb_Stress_DWM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Turb_Stress_DWM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Turb_Stress_DWM,2), UBOUND(OutData%Turb_Stress_DWM,2) + DO i1 = LBOUND(OutData%Turb_Stress_DWM,1), UBOUND(OutData%Turb_Stress_DWM,1) + OutData%Turb_Stress_DWM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%n_x_vector = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_r_vector = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ppR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackWake_Deficit_Data + + SUBROUTINE DWM_CopyMeanderData( SrcMeanderDataData, DstMeanderDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeanderData), INTENT(IN) :: SrcMeanderDataData + TYPE(MeanderData), INTENT(INOUT) :: DstMeanderDataData + 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 = 'DWM_CopyMeanderData' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMeanderDataData%scale_factor = SrcMeanderDataData%scale_factor + DstMeanderDataData%moving_time = SrcMeanderDataData%moving_time + END SUBROUTINE DWM_CopyMeanderData + + SUBROUTINE DWM_DestroyMeanderData( MeanderDataData, ErrStat, ErrMsg ) + TYPE(MeanderData), INTENT(INOUT) :: MeanderDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyMeanderData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_DestroyMeanderData + + SUBROUTINE DWM_PackMeanderData( 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(MeanderData), 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 = 'DWM_PackMeanderData' + ! 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 ! scale_factor + Int_BufSz = Int_BufSz + 1 ! moving_time + 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%scale_factor + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%moving_time + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_PackMeanderData + + SUBROUTINE DWM_UnPackMeanderData( 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(MeanderData), 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 = 'DWM_UnPackMeanderData' + ! 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%scale_factor = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%moving_time = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_UnPackMeanderData + + SUBROUTINE DWM_Copyread_turbine_position_data( Srcread_turbine_position_dataData, Dstread_turbine_position_dataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(read_turbine_position_data), INTENT(IN) :: Srcread_turbine_position_dataData + TYPE(read_turbine_position_data), INTENT(INOUT) :: Dstread_turbine_position_dataData + 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 = 'DWM_Copyread_turbine_position_data' +! + ErrStat = ErrID_None + ErrMsg = "" + Dstread_turbine_position_dataData%SimulationOrder_index = Srcread_turbine_position_dataData%SimulationOrder_index +IF (ALLOCATED(Srcread_turbine_position_dataData%Turbine_sort_order)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%Turbine_sort_order,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%Turbine_sort_order,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%Turbine_sort_order)) THEN + ALLOCATE(Dstread_turbine_position_dataData%Turbine_sort_order(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%Turbine_sort_order.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%Turbine_sort_order = Srcread_turbine_position_dataData%Turbine_sort_order +ENDIF + Dstread_turbine_position_dataData%WT_index = Srcread_turbine_position_dataData%WT_index +IF (ALLOCATED(Srcread_turbine_position_dataData%TurbineInfluenceData)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%TurbineInfluenceData,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%TurbineInfluenceData,1) + i2_l = LBOUND(Srcread_turbine_position_dataData%TurbineInfluenceData,2) + i2_u = UBOUND(Srcread_turbine_position_dataData%TurbineInfluenceData,2) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%TurbineInfluenceData)) THEN + ALLOCATE(Dstread_turbine_position_dataData%TurbineInfluenceData(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%TurbineInfluenceData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%TurbineInfluenceData = Srcread_turbine_position_dataData%TurbineInfluenceData +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%upwind_turbine_index)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%upwind_turbine_index,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%upwind_turbine_index,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%upwind_turbine_index)) THEN + ALLOCATE(Dstread_turbine_position_dataData%upwind_turbine_index(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%upwind_turbine_index.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%upwind_turbine_index = Srcread_turbine_position_dataData%upwind_turbine_index +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%downwind_turbine_index)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%downwind_turbine_index,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%downwind_turbine_index,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%downwind_turbine_index)) THEN + ALLOCATE(Dstread_turbine_position_dataData%downwind_turbine_index(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%downwind_turbine_index.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%downwind_turbine_index = Srcread_turbine_position_dataData%downwind_turbine_index +ENDIF + Dstread_turbine_position_dataData%upwindturbine_number = Srcread_turbine_position_dataData%upwindturbine_number + Dstread_turbine_position_dataData%downwindturbine_number = Srcread_turbine_position_dataData%downwindturbine_number +IF (ALLOCATED(Srcread_turbine_position_dataData%turbine_windorigin_length)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%turbine_windorigin_length,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%turbine_windorigin_length,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%turbine_windorigin_length)) THEN + ALLOCATE(Dstread_turbine_position_dataData%turbine_windorigin_length(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%turbine_windorigin_length.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%turbine_windorigin_length = Srcread_turbine_position_dataData%turbine_windorigin_length +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%upwind_turbine_projected_distance)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%upwind_turbine_projected_distance,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%upwind_turbine_projected_distance,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%upwind_turbine_projected_distance)) THEN + ALLOCATE(Dstread_turbine_position_dataData%upwind_turbine_projected_distance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%upwind_turbine_projected_distance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%upwind_turbine_projected_distance = Srcread_turbine_position_dataData%upwind_turbine_projected_distance +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%downwind_turbine_projected_distance)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%downwind_turbine_projected_distance,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%downwind_turbine_projected_distance,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%downwind_turbine_projected_distance)) THEN + ALLOCATE(Dstread_turbine_position_dataData%downwind_turbine_projected_distance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%downwind_turbine_projected_distance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%downwind_turbine_projected_distance = Srcread_turbine_position_dataData%downwind_turbine_projected_distance +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%turbine_angle)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%turbine_angle,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%turbine_angle,1) + i2_l = LBOUND(Srcread_turbine_position_dataData%turbine_angle,2) + i2_u = UBOUND(Srcread_turbine_position_dataData%turbine_angle,2) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%turbine_angle)) THEN + ALLOCATE(Dstread_turbine_position_dataData%turbine_angle(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%turbine_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%turbine_angle = Srcread_turbine_position_dataData%turbine_angle +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%upwind_align_angle)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%upwind_align_angle,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%upwind_align_angle,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%upwind_align_angle)) THEN + ALLOCATE(Dstread_turbine_position_dataData%upwind_align_angle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%upwind_align_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%upwind_align_angle = Srcread_turbine_position_dataData%upwind_align_angle +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%downwind_align_angle)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%downwind_align_angle,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%downwind_align_angle,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%downwind_align_angle)) THEN + ALLOCATE(Dstread_turbine_position_dataData%downwind_align_angle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%downwind_align_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%downwind_align_angle = Srcread_turbine_position_dataData%downwind_align_angle +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%upwind_turbine_Xcoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%upwind_turbine_Xcoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%upwind_turbine_Xcoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%upwind_turbine_Xcoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%upwind_turbine_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%upwind_turbine_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%upwind_turbine_Xcoor = Srcread_turbine_position_dataData%upwind_turbine_Xcoor +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%upwind_turbine_Ycoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%upwind_turbine_Ycoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%upwind_turbine_Ycoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%upwind_turbine_Ycoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%upwind_turbine_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%upwind_turbine_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%upwind_turbine_Ycoor = Srcread_turbine_position_dataData%upwind_turbine_Ycoor +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%wind_farm_Xcoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%wind_farm_Xcoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%wind_farm_Xcoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%wind_farm_Xcoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%wind_farm_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%wind_farm_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%wind_farm_Xcoor = Srcread_turbine_position_dataData%wind_farm_Xcoor +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%wind_farm_Ycoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%wind_farm_Ycoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%wind_farm_Ycoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%wind_farm_Ycoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%wind_farm_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%wind_farm_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%wind_farm_Ycoor = Srcread_turbine_position_dataData%wind_farm_Ycoor +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%downwind_turbine_Xcoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%downwind_turbine_Xcoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%downwind_turbine_Xcoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%downwind_turbine_Xcoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%downwind_turbine_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%downwind_turbine_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%downwind_turbine_Xcoor = Srcread_turbine_position_dataData%downwind_turbine_Xcoor +ENDIF +IF (ALLOCATED(Srcread_turbine_position_dataData%downwind_turbine_Ycoor)) THEN + i1_l = LBOUND(Srcread_turbine_position_dataData%downwind_turbine_Ycoor,1) + i1_u = UBOUND(Srcread_turbine_position_dataData%downwind_turbine_Ycoor,1) + IF (.NOT. ALLOCATED(Dstread_turbine_position_dataData%downwind_turbine_Ycoor)) THEN + ALLOCATE(Dstread_turbine_position_dataData%downwind_turbine_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_turbine_position_dataData%downwind_turbine_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_turbine_position_dataData%downwind_turbine_Ycoor = Srcread_turbine_position_dataData%downwind_turbine_Ycoor +ENDIF + END SUBROUTINE DWM_Copyread_turbine_position_data + + SUBROUTINE DWM_Destroyread_turbine_position_data( read_turbine_position_dataData, ErrStat, ErrMsg ) + TYPE(read_turbine_position_data), INTENT(INOUT) :: read_turbine_position_dataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroyread_turbine_position_data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(read_turbine_position_dataData%Turbine_sort_order)) THEN + DEALLOCATE(read_turbine_position_dataData%Turbine_sort_order) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%TurbineInfluenceData)) THEN + DEALLOCATE(read_turbine_position_dataData%TurbineInfluenceData) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%upwind_turbine_index)) THEN + DEALLOCATE(read_turbine_position_dataData%upwind_turbine_index) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%downwind_turbine_index)) THEN + DEALLOCATE(read_turbine_position_dataData%downwind_turbine_index) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%turbine_windorigin_length)) THEN + DEALLOCATE(read_turbine_position_dataData%turbine_windorigin_length) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%upwind_turbine_projected_distance)) THEN + DEALLOCATE(read_turbine_position_dataData%upwind_turbine_projected_distance) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%downwind_turbine_projected_distance)) THEN + DEALLOCATE(read_turbine_position_dataData%downwind_turbine_projected_distance) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%turbine_angle)) THEN + DEALLOCATE(read_turbine_position_dataData%turbine_angle) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%upwind_align_angle)) THEN + DEALLOCATE(read_turbine_position_dataData%upwind_align_angle) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%downwind_align_angle)) THEN + DEALLOCATE(read_turbine_position_dataData%downwind_align_angle) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%upwind_turbine_Xcoor)) THEN + DEALLOCATE(read_turbine_position_dataData%upwind_turbine_Xcoor) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%upwind_turbine_Ycoor)) THEN + DEALLOCATE(read_turbine_position_dataData%upwind_turbine_Ycoor) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%wind_farm_Xcoor)) THEN + DEALLOCATE(read_turbine_position_dataData%wind_farm_Xcoor) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%wind_farm_Ycoor)) THEN + DEALLOCATE(read_turbine_position_dataData%wind_farm_Ycoor) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%downwind_turbine_Xcoor)) THEN + DEALLOCATE(read_turbine_position_dataData%downwind_turbine_Xcoor) +ENDIF +IF (ALLOCATED(read_turbine_position_dataData%downwind_turbine_Ycoor)) THEN + DEALLOCATE(read_turbine_position_dataData%downwind_turbine_Ycoor) +ENDIF + END SUBROUTINE DWM_Destroyread_turbine_position_data + + SUBROUTINE DWM_Packread_turbine_position_data( 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(read_turbine_position_data), 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 = 'DWM_Packread_turbine_position_data' + ! 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 ! SimulationOrder_index + Int_BufSz = Int_BufSz + 1 ! Turbine_sort_order allocated yes/no + IF ( ALLOCATED(InData%Turbine_sort_order) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Turbine_sort_order upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Turbine_sort_order) ! Turbine_sort_order + END IF + Int_BufSz = Int_BufSz + 1 ! WT_index + Int_BufSz = Int_BufSz + 1 ! TurbineInfluenceData allocated yes/no + IF ( ALLOCATED(InData%TurbineInfluenceData) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TurbineInfluenceData upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%TurbineInfluenceData) ! TurbineInfluenceData + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_turbine_index allocated yes/no + IF ( ALLOCATED(InData%upwind_turbine_index) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_turbine_index upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%upwind_turbine_index) ! upwind_turbine_index + END IF + Int_BufSz = Int_BufSz + 1 ! downwind_turbine_index allocated yes/no + IF ( ALLOCATED(InData%downwind_turbine_index) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! downwind_turbine_index upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%downwind_turbine_index) ! downwind_turbine_index + END IF + Int_BufSz = Int_BufSz + 1 ! upwindturbine_number + Int_BufSz = Int_BufSz + 1 ! downwindturbine_number + Int_BufSz = Int_BufSz + 1 ! turbine_windorigin_length allocated yes/no + IF ( ALLOCATED(InData%turbine_windorigin_length) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! turbine_windorigin_length upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%turbine_windorigin_length) ! turbine_windorigin_length + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_turbine_projected_distance allocated yes/no + IF ( ALLOCATED(InData%upwind_turbine_projected_distance) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_turbine_projected_distance upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_turbine_projected_distance) ! upwind_turbine_projected_distance + END IF + Int_BufSz = Int_BufSz + 1 ! downwind_turbine_projected_distance allocated yes/no + IF ( ALLOCATED(InData%downwind_turbine_projected_distance) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! downwind_turbine_projected_distance upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%downwind_turbine_projected_distance) ! downwind_turbine_projected_distance + END IF + Int_BufSz = Int_BufSz + 1 ! turbine_angle allocated yes/no + IF ( ALLOCATED(InData%turbine_angle) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! turbine_angle upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%turbine_angle) ! turbine_angle + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_align_angle allocated yes/no + IF ( ALLOCATED(InData%upwind_align_angle) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_align_angle upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_align_angle) ! upwind_align_angle + END IF + Int_BufSz = Int_BufSz + 1 ! downwind_align_angle allocated yes/no + IF ( ALLOCATED(InData%downwind_align_angle) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! downwind_align_angle upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%downwind_align_angle) ! downwind_align_angle + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_turbine_Xcoor allocated yes/no + IF ( ALLOCATED(InData%upwind_turbine_Xcoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_turbine_Xcoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_turbine_Xcoor) ! upwind_turbine_Xcoor + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_turbine_Ycoor allocated yes/no + IF ( ALLOCATED(InData%upwind_turbine_Ycoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_turbine_Ycoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_turbine_Ycoor) ! upwind_turbine_Ycoor + END IF + Int_BufSz = Int_BufSz + 1 ! wind_farm_Xcoor allocated yes/no + IF ( ALLOCATED(InData%wind_farm_Xcoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! wind_farm_Xcoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%wind_farm_Xcoor) ! wind_farm_Xcoor + END IF + Int_BufSz = Int_BufSz + 1 ! wind_farm_Ycoor allocated yes/no + IF ( ALLOCATED(InData%wind_farm_Ycoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! wind_farm_Ycoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%wind_farm_Ycoor) ! wind_farm_Ycoor + END IF + Int_BufSz = Int_BufSz + 1 ! downwind_turbine_Xcoor allocated yes/no + IF ( ALLOCATED(InData%downwind_turbine_Xcoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! downwind_turbine_Xcoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%downwind_turbine_Xcoor) ! downwind_turbine_Xcoor + END IF + Int_BufSz = Int_BufSz + 1 ! downwind_turbine_Ycoor allocated yes/no + IF ( ALLOCATED(InData%downwind_turbine_Ycoor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! downwind_turbine_Ycoor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%downwind_turbine_Ycoor) ! downwind_turbine_Ycoor + 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%SimulationOrder_index + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Turbine_sort_order) ) 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%Turbine_sort_order,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Turbine_sort_order,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Turbine_sort_order,1), UBOUND(InData%Turbine_sort_order,1) + IntKiBuf(Int_Xferred) = InData%Turbine_sort_order(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%WT_index + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TurbineInfluenceData) ) 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%TurbineInfluenceData,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TurbineInfluenceData,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TurbineInfluenceData,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TurbineInfluenceData,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TurbineInfluenceData,2), UBOUND(InData%TurbineInfluenceData,2) + DO i1 = LBOUND(InData%TurbineInfluenceData,1), UBOUND(InData%TurbineInfluenceData,1) + IntKiBuf(Int_Xferred) = InData%TurbineInfluenceData(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_turbine_index) ) 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%upwind_turbine_index,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_turbine_index,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_turbine_index,1), UBOUND(InData%upwind_turbine_index,1) + IntKiBuf(Int_Xferred) = InData%upwind_turbine_index(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%downwind_turbine_index) ) 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%downwind_turbine_index,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%downwind_turbine_index,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%downwind_turbine_index,1), UBOUND(InData%downwind_turbine_index,1) + IntKiBuf(Int_Xferred) = InData%downwind_turbine_index(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%upwindturbine_number + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%downwindturbine_number + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%turbine_windorigin_length) ) 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%turbine_windorigin_length,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%turbine_windorigin_length,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%turbine_windorigin_length,1), UBOUND(InData%turbine_windorigin_length,1) + ReKiBuf(Re_Xferred) = InData%turbine_windorigin_length(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_turbine_projected_distance) ) 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%upwind_turbine_projected_distance,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_turbine_projected_distance,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_turbine_projected_distance,1), UBOUND(InData%upwind_turbine_projected_distance,1) + ReKiBuf(Re_Xferred) = InData%upwind_turbine_projected_distance(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%downwind_turbine_projected_distance) ) 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%downwind_turbine_projected_distance,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%downwind_turbine_projected_distance,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%downwind_turbine_projected_distance,1), UBOUND(InData%downwind_turbine_projected_distance,1) + ReKiBuf(Re_Xferred) = InData%downwind_turbine_projected_distance(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%turbine_angle) ) 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%turbine_angle,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%turbine_angle,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%turbine_angle,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%turbine_angle,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%turbine_angle,2), UBOUND(InData%turbine_angle,2) + DO i1 = LBOUND(InData%turbine_angle,1), UBOUND(InData%turbine_angle,1) + ReKiBuf(Re_Xferred) = InData%turbine_angle(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_align_angle) ) 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%upwind_align_angle,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_align_angle,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_align_angle,1), UBOUND(InData%upwind_align_angle,1) + ReKiBuf(Re_Xferred) = InData%upwind_align_angle(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%downwind_align_angle) ) 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%downwind_align_angle,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%downwind_align_angle,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%downwind_align_angle,1), UBOUND(InData%downwind_align_angle,1) + ReKiBuf(Re_Xferred) = InData%downwind_align_angle(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_turbine_Xcoor) ) 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%upwind_turbine_Xcoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_turbine_Xcoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_turbine_Xcoor,1), UBOUND(InData%upwind_turbine_Xcoor,1) + ReKiBuf(Re_Xferred) = InData%upwind_turbine_Xcoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_turbine_Ycoor) ) 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%upwind_turbine_Ycoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_turbine_Ycoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_turbine_Ycoor,1), UBOUND(InData%upwind_turbine_Ycoor,1) + ReKiBuf(Re_Xferred) = InData%upwind_turbine_Ycoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%wind_farm_Xcoor) ) 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%wind_farm_Xcoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wind_farm_Xcoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%wind_farm_Xcoor,1), UBOUND(InData%wind_farm_Xcoor,1) + ReKiBuf(Re_Xferred) = InData%wind_farm_Xcoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%wind_farm_Ycoor) ) 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%wind_farm_Ycoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wind_farm_Ycoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%wind_farm_Ycoor,1), UBOUND(InData%wind_farm_Ycoor,1) + ReKiBuf(Re_Xferred) = InData%wind_farm_Ycoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%downwind_turbine_Xcoor) ) 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%downwind_turbine_Xcoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%downwind_turbine_Xcoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%downwind_turbine_Xcoor,1), UBOUND(InData%downwind_turbine_Xcoor,1) + ReKiBuf(Re_Xferred) = InData%downwind_turbine_Xcoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%downwind_turbine_Ycoor) ) 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%downwind_turbine_Ycoor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%downwind_turbine_Ycoor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%downwind_turbine_Ycoor,1), UBOUND(InData%downwind_turbine_Ycoor,1) + ReKiBuf(Re_Xferred) = InData%downwind_turbine_Ycoor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE DWM_Packread_turbine_position_data + + SUBROUTINE DWM_UnPackread_turbine_position_data( 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(read_turbine_position_data), 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 = 'DWM_UnPackread_turbine_position_data' + ! 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%SimulationOrder_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Turbine_sort_order 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%Turbine_sort_order)) DEALLOCATE(OutData%Turbine_sort_order) + ALLOCATE(OutData%Turbine_sort_order(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Turbine_sort_order.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Turbine_sort_order,1), UBOUND(OutData%Turbine_sort_order,1) + OutData%Turbine_sort_order(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%WT_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TurbineInfluenceData 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%TurbineInfluenceData)) DEALLOCATE(OutData%TurbineInfluenceData) + ALLOCATE(OutData%TurbineInfluenceData(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TurbineInfluenceData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TurbineInfluenceData,2), UBOUND(OutData%TurbineInfluenceData,2) + DO i1 = LBOUND(OutData%TurbineInfluenceData,1), UBOUND(OutData%TurbineInfluenceData,1) + OutData%TurbineInfluenceData(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_turbine_index 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%upwind_turbine_index)) DEALLOCATE(OutData%upwind_turbine_index) + ALLOCATE(OutData%upwind_turbine_index(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_turbine_index.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_turbine_index,1), UBOUND(OutData%upwind_turbine_index,1) + OutData%upwind_turbine_index(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! downwind_turbine_index 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%downwind_turbine_index)) DEALLOCATE(OutData%downwind_turbine_index) + ALLOCATE(OutData%downwind_turbine_index(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%downwind_turbine_index.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%downwind_turbine_index,1), UBOUND(OutData%downwind_turbine_index,1) + OutData%downwind_turbine_index(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%upwindturbine_number = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%downwindturbine_number = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! turbine_windorigin_length 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%turbine_windorigin_length)) DEALLOCATE(OutData%turbine_windorigin_length) + ALLOCATE(OutData%turbine_windorigin_length(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%turbine_windorigin_length.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%turbine_windorigin_length,1), UBOUND(OutData%turbine_windorigin_length,1) + OutData%turbine_windorigin_length(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_turbine_projected_distance 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%upwind_turbine_projected_distance)) DEALLOCATE(OutData%upwind_turbine_projected_distance) + ALLOCATE(OutData%upwind_turbine_projected_distance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_turbine_projected_distance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_turbine_projected_distance,1), UBOUND(OutData%upwind_turbine_projected_distance,1) + OutData%upwind_turbine_projected_distance(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! downwind_turbine_projected_distance 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%downwind_turbine_projected_distance)) DEALLOCATE(OutData%downwind_turbine_projected_distance) + ALLOCATE(OutData%downwind_turbine_projected_distance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%downwind_turbine_projected_distance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%downwind_turbine_projected_distance,1), UBOUND(OutData%downwind_turbine_projected_distance,1) + OutData%downwind_turbine_projected_distance(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! turbine_angle 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%turbine_angle)) DEALLOCATE(OutData%turbine_angle) + ALLOCATE(OutData%turbine_angle(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%turbine_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%turbine_angle,2), UBOUND(OutData%turbine_angle,2) + DO i1 = LBOUND(OutData%turbine_angle,1), UBOUND(OutData%turbine_angle,1) + OutData%turbine_angle(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_align_angle 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%upwind_align_angle)) DEALLOCATE(OutData%upwind_align_angle) + ALLOCATE(OutData%upwind_align_angle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_align_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_align_angle,1), UBOUND(OutData%upwind_align_angle,1) + OutData%upwind_align_angle(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! downwind_align_angle 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%downwind_align_angle)) DEALLOCATE(OutData%downwind_align_angle) + ALLOCATE(OutData%downwind_align_angle(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%downwind_align_angle.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%downwind_align_angle,1), UBOUND(OutData%downwind_align_angle,1) + OutData%downwind_align_angle(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_turbine_Xcoor 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%upwind_turbine_Xcoor)) DEALLOCATE(OutData%upwind_turbine_Xcoor) + ALLOCATE(OutData%upwind_turbine_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_turbine_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_turbine_Xcoor,1), UBOUND(OutData%upwind_turbine_Xcoor,1) + OutData%upwind_turbine_Xcoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_turbine_Ycoor 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%upwind_turbine_Ycoor)) DEALLOCATE(OutData%upwind_turbine_Ycoor) + ALLOCATE(OutData%upwind_turbine_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_turbine_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_turbine_Ycoor,1), UBOUND(OutData%upwind_turbine_Ycoor,1) + OutData%upwind_turbine_Ycoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! wind_farm_Xcoor 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%wind_farm_Xcoor)) DEALLOCATE(OutData%wind_farm_Xcoor) + ALLOCATE(OutData%wind_farm_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%wind_farm_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%wind_farm_Xcoor,1), UBOUND(OutData%wind_farm_Xcoor,1) + OutData%wind_farm_Xcoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! wind_farm_Ycoor 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%wind_farm_Ycoor)) DEALLOCATE(OutData%wind_farm_Ycoor) + ALLOCATE(OutData%wind_farm_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%wind_farm_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%wind_farm_Ycoor,1), UBOUND(OutData%wind_farm_Ycoor,1) + OutData%wind_farm_Ycoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! downwind_turbine_Xcoor 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%downwind_turbine_Xcoor)) DEALLOCATE(OutData%downwind_turbine_Xcoor) + ALLOCATE(OutData%downwind_turbine_Xcoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%downwind_turbine_Xcoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%downwind_turbine_Xcoor,1), UBOUND(OutData%downwind_turbine_Xcoor,1) + OutData%downwind_turbine_Xcoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! downwind_turbine_Ycoor 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%downwind_turbine_Ycoor)) DEALLOCATE(OutData%downwind_turbine_Ycoor) + ALLOCATE(OutData%downwind_turbine_Ycoor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%downwind_turbine_Ycoor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%downwind_turbine_Ycoor,1), UBOUND(OutData%downwind_turbine_Ycoor,1) + OutData%downwind_turbine_Ycoor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE DWM_UnPackread_turbine_position_data + + SUBROUTINE DWM_CopyWeiMethod( SrcWeiMethodData, DstWeiMethodData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WeiMethod), INTENT(IN) :: SrcWeiMethodData + TYPE(WeiMethod), INTENT(INOUT) :: DstWeiMethodData + 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 = 'DWM_CopyWeiMethod' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcWeiMethodData%sweptarea)) THEN + i1_l = LBOUND(SrcWeiMethodData%sweptarea,1) + i1_u = UBOUND(SrcWeiMethodData%sweptarea,1) + IF (.NOT. ALLOCATED(DstWeiMethodData%sweptarea)) THEN + ALLOCATE(DstWeiMethodData%sweptarea(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstWeiMethodData%sweptarea.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstWeiMethodData%sweptarea = SrcWeiMethodData%sweptarea +ENDIF + DstWeiMethodData%weighting_denominator = SrcWeiMethodData%weighting_denominator + END SUBROUTINE DWM_CopyWeiMethod + + SUBROUTINE DWM_DestroyWeiMethod( WeiMethodData, ErrStat, ErrMsg ) + TYPE(WeiMethod), INTENT(INOUT) :: WeiMethodData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyWeiMethod' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(WeiMethodData%sweptarea)) THEN + DEALLOCATE(WeiMethodData%sweptarea) +ENDIF + END SUBROUTINE DWM_DestroyWeiMethod + + SUBROUTINE DWM_PackWeiMethod( 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(WeiMethod), 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 = 'DWM_PackWeiMethod' + ! 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 ! sweptarea allocated yes/no + IF ( ALLOCATED(InData%sweptarea) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! sweptarea upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%sweptarea) ! sweptarea + END IF + Re_BufSz = Re_BufSz + 1 ! weighting_denominator + 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%sweptarea) ) 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%sweptarea,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%sweptarea,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%sweptarea,1), UBOUND(InData%sweptarea,1) + ReKiBuf(Re_Xferred) = InData%sweptarea(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%weighting_denominator + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackWeiMethod + + SUBROUTINE DWM_UnPackWeiMethod( 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(WeiMethod), 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 = 'DWM_UnPackWeiMethod' + ! 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 ! sweptarea 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%sweptarea)) DEALLOCATE(OutData%sweptarea) + ALLOCATE(OutData%sweptarea(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%sweptarea.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%sweptarea,1), UBOUND(OutData%sweptarea,1) + OutData%sweptarea(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%weighting_denominator = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackWeiMethod + + SUBROUTINE DWM_CopyTIDownstream( SrcTIDownstreamData, DstTIDownstreamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TIDownstream), INTENT(IN) :: SrcTIDownstreamData + TYPE(TIDownstream), INTENT(INOUT) :: DstTIDownstreamData + 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 = 'DWM_CopyTIDownstream' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcTIDownstreamData%TI_downstream_matrix)) THEN + i1_l = LBOUND(SrcTIDownstreamData%TI_downstream_matrix,1) + i1_u = UBOUND(SrcTIDownstreamData%TI_downstream_matrix,1) + i2_l = LBOUND(SrcTIDownstreamData%TI_downstream_matrix,2) + i2_u = UBOUND(SrcTIDownstreamData%TI_downstream_matrix,2) + IF (.NOT. ALLOCATED(DstTIDownstreamData%TI_downstream_matrix)) THEN + ALLOCATE(DstTIDownstreamData%TI_downstream_matrix(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstTIDownstreamData%TI_downstream_matrix.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstTIDownstreamData%TI_downstream_matrix = SrcTIDownstreamData%TI_downstream_matrix +ENDIF + DstTIDownstreamData%i = SrcTIDownstreamData%i + DstTIDownstreamData%j = SrcTIDownstreamData%j + DstTIDownstreamData%k = SrcTIDownstreamData%k + DstTIDownstreamData%cross_plane_position_ds = SrcTIDownstreamData%cross_plane_position_ds + DstTIDownstreamData%cross_plane_position_TI = SrcTIDownstreamData%cross_plane_position_TI + DstTIDownstreamData%distance_index = SrcTIDownstreamData%distance_index + DstTIDownstreamData%counter1 = SrcTIDownstreamData%counter1 + DstTIDownstreamData%counter2 = SrcTIDownstreamData%counter2 + DstTIDownstreamData%initial_timestep = SrcTIDownstreamData%initial_timestep + DstTIDownstreamData%y_axis_turbine = SrcTIDownstreamData%y_axis_turbine + DstTIDownstreamData%z_axis_turbine = SrcTIDownstreamData%z_axis_turbine + DstTIDownstreamData%distance = SrcTIDownstreamData%distance + DstTIDownstreamData%TI_downstream_node = SrcTIDownstreamData%TI_downstream_node + DstTIDownstreamData%TI_node_temp = SrcTIDownstreamData%TI_node_temp + DstTIDownstreamData%TI_node = SrcTIDownstreamData%TI_node + DstTIDownstreamData%TI_accumulation = SrcTIDownstreamData%TI_accumulation + DstTIDownstreamData%TI_apprant_accumulation = SrcTIDownstreamData%TI_apprant_accumulation + DstTIDownstreamData%TI_average = SrcTIDownstreamData%TI_average + DstTIDownstreamData%TI_apprant = SrcTIDownstreamData%TI_apprant + DstTIDownstreamData%HubHt = SrcTIDownstreamData%HubHt + DstTIDownstreamData%wake_center_y = SrcTIDownstreamData%wake_center_y + DstTIDownstreamData%wake_center_z = SrcTIDownstreamData%wake_center_z + DstTIDownstreamData%Rscale = SrcTIDownstreamData%Rscale + DstTIDownstreamData%y = SrcTIDownstreamData%y + DstTIDownstreamData%z = SrcTIDownstreamData%z + DstTIDownstreamData%zero_spacing = SrcTIDownstreamData%zero_spacing + DstTIDownstreamData%temp1 = SrcTIDownstreamData%temp1 + DstTIDownstreamData%temp2 = SrcTIDownstreamData%temp2 + DstTIDownstreamData%temp3 = SrcTIDownstreamData%temp3 + END SUBROUTINE DWM_CopyTIDownstream + + SUBROUTINE DWM_DestroyTIDownstream( TIDownstreamData, ErrStat, ErrMsg ) + TYPE(TIDownstream), INTENT(INOUT) :: TIDownstreamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyTIDownstream' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(TIDownstreamData%TI_downstream_matrix)) THEN + DEALLOCATE(TIDownstreamData%TI_downstream_matrix) +ENDIF + END SUBROUTINE DWM_DestroyTIDownstream + + SUBROUTINE DWM_PackTIDownstream( 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(TIDownstream), 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 = 'DWM_PackTIDownstream' + ! 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 ! TI_downstream_matrix allocated yes/no + IF ( ALLOCATED(InData%TI_downstream_matrix) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI_downstream_matrix upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI_downstream_matrix) ! TI_downstream_matrix + END IF + Int_BufSz = Int_BufSz + 1 ! i + Int_BufSz = Int_BufSz + 1 ! j + Int_BufSz = Int_BufSz + 1 ! k + Int_BufSz = Int_BufSz + 1 ! cross_plane_position_ds + Int_BufSz = Int_BufSz + 1 ! cross_plane_position_TI + Int_BufSz = Int_BufSz + 1 ! distance_index + Int_BufSz = Int_BufSz + 1 ! counter1 + Int_BufSz = Int_BufSz + 1 ! counter2 + Int_BufSz = Int_BufSz + 1 ! initial_timestep + Re_BufSz = Re_BufSz + 1 ! y_axis_turbine + Re_BufSz = Re_BufSz + 1 ! z_axis_turbine + Re_BufSz = Re_BufSz + 1 ! distance + Re_BufSz = Re_BufSz + 1 ! TI_downstream_node + Re_BufSz = Re_BufSz + 1 ! TI_node_temp + Re_BufSz = Re_BufSz + 1 ! TI_node + Re_BufSz = Re_BufSz + 1 ! TI_accumulation + Re_BufSz = Re_BufSz + 1 ! TI_apprant_accumulation + Re_BufSz = Re_BufSz + 1 ! TI_average + Re_BufSz = Re_BufSz + 1 ! TI_apprant + Re_BufSz = Re_BufSz + 1 ! HubHt + Re_BufSz = Re_BufSz + 1 ! wake_center_y + Re_BufSz = Re_BufSz + 1 ! wake_center_z + Re_BufSz = Re_BufSz + 1 ! Rscale + Re_BufSz = Re_BufSz + 1 ! y + Re_BufSz = Re_BufSz + 1 ! z + Re_BufSz = Re_BufSz + 1 ! zero_spacing + Re_BufSz = Re_BufSz + 1 ! temp1 + Re_BufSz = Re_BufSz + 1 ! temp2 + Re_BufSz = Re_BufSz + 1 ! temp3 + 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%TI_downstream_matrix) ) 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%TI_downstream_matrix,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_downstream_matrix,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI_downstream_matrix,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_downstream_matrix,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TI_downstream_matrix,2), UBOUND(InData%TI_downstream_matrix,2) + DO i1 = LBOUND(InData%TI_downstream_matrix,1), UBOUND(InData%TI_downstream_matrix,1) + ReKiBuf(Re_Xferred) = InData%TI_downstream_matrix(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%i + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%j + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%k + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%cross_plane_position_ds + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%cross_plane_position_TI + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%distance_index + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%counter1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%counter2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%initial_timestep + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%y_axis_turbine + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%z_axis_turbine + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%distance + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_downstream_node + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_node_temp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_node + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_accumulation + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_apprant_accumulation + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_average + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_apprant + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%wake_center_y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%wake_center_z + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rscale + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%z + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%zero_spacing + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%temp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%temp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%temp3 + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackTIDownstream + + SUBROUTINE DWM_UnPackTIDownstream( 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(TIDownstream), 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 = 'DWM_UnPackTIDownstream' + ! 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 ! TI_downstream_matrix 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%TI_downstream_matrix)) DEALLOCATE(OutData%TI_downstream_matrix) + ALLOCATE(OutData%TI_downstream_matrix(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI_downstream_matrix.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TI_downstream_matrix,2), UBOUND(OutData%TI_downstream_matrix,2) + DO i1 = LBOUND(OutData%TI_downstream_matrix,1), UBOUND(OutData%TI_downstream_matrix,1) + OutData%TI_downstream_matrix(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%i = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%j = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%k = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%cross_plane_position_ds = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%cross_plane_position_TI = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%distance_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%counter1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%counter2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%initial_timestep = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%y_axis_turbine = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%z_axis_turbine = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%distance = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_downstream_node = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_node_temp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_node = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_accumulation = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_apprant_accumulation = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_average = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_apprant = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%wake_center_y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%wake_center_z = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rscale = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%z = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%zero_spacing = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%temp1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%temp2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%temp3 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackTIDownstream + + SUBROUTINE DWM_CopyTurbKaimal( SrcTurbKaimalData, DstTurbKaimalData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TurbKaimal), INTENT(IN) :: SrcTurbKaimalData + TYPE(TurbKaimal), INTENT(INOUT) :: DstTurbKaimalData + 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 = 'DWM_CopyTurbKaimal' +! + ErrStat = ErrID_None + ErrMsg = "" + DstTurbKaimalData%fs = SrcTurbKaimalData%fs + DstTurbKaimalData%temp_n = SrcTurbKaimalData%temp_n + DstTurbKaimalData%i = SrcTurbKaimalData%i + DstTurbKaimalData%low_f = SrcTurbKaimalData%low_f + DstTurbKaimalData%high_f = SrcTurbKaimalData%high_f + DstTurbKaimalData%lk_facor = SrcTurbKaimalData%lk_facor + DstTurbKaimalData%STD = SrcTurbKaimalData%STD + END SUBROUTINE DWM_CopyTurbKaimal + + SUBROUTINE DWM_DestroyTurbKaimal( TurbKaimalData, ErrStat, ErrMsg ) + TYPE(TurbKaimal), INTENT(INOUT) :: TurbKaimalData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyTurbKaimal' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_DestroyTurbKaimal + + SUBROUTINE DWM_PackTurbKaimal( 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(TurbKaimal), 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 = 'DWM_PackTurbKaimal' + ! 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 ! fs + Int_BufSz = Int_BufSz + 1 ! temp_n + Int_BufSz = Int_BufSz + 1 ! i + Re_BufSz = Re_BufSz + 1 ! low_f + Re_BufSz = Re_BufSz + 1 ! high_f + Re_BufSz = Re_BufSz + 1 ! lk_facor + Re_BufSz = Re_BufSz + 1 ! STD + 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%fs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%temp_n + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%i + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%low_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%high_f + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%lk_facor + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%STD + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackTurbKaimal + + SUBROUTINE DWM_UnPackTurbKaimal( 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(TurbKaimal), 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 = 'DWM_UnPackTurbKaimal' + ! 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%fs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%temp_n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%i = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%low_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%high_f = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%lk_facor = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%STD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackTurbKaimal + + SUBROUTINE DWM_CopyShinozuka( SrcShinozukaData, DstShinozukaData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Shinozuka), INTENT(IN) :: SrcShinozukaData + TYPE(Shinozuka), INTENT(INOUT) :: DstShinozukaData + 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 = 'DWM_CopyShinozuka' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcShinozukaData%f_syn)) THEN + i1_l = LBOUND(SrcShinozukaData%f_syn,1) + i1_u = UBOUND(SrcShinozukaData%f_syn,1) + IF (.NOT. ALLOCATED(DstShinozukaData%f_syn)) THEN + ALLOCATE(DstShinozukaData%f_syn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstShinozukaData%f_syn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstShinozukaData%f_syn = SrcShinozukaData%f_syn +ENDIF +IF (ALLOCATED(SrcShinozukaData%t_syn)) THEN + i1_l = LBOUND(SrcShinozukaData%t_syn,1) + i1_u = UBOUND(SrcShinozukaData%t_syn,1) + IF (.NOT. ALLOCATED(DstShinozukaData%t_syn)) THEN + ALLOCATE(DstShinozukaData%t_syn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstShinozukaData%t_syn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstShinozukaData%t_syn = SrcShinozukaData%t_syn +ENDIF +IF (ALLOCATED(SrcShinozukaData%phi)) THEN + i1_l = LBOUND(SrcShinozukaData%phi,1) + i1_u = UBOUND(SrcShinozukaData%phi,1) + IF (.NOT. ALLOCATED(DstShinozukaData%phi)) THEN + ALLOCATE(DstShinozukaData%phi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstShinozukaData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstShinozukaData%phi = SrcShinozukaData%phi +ENDIF +IF (ALLOCATED(SrcShinozukaData%p_k)) THEN + i1_l = LBOUND(SrcShinozukaData%p_k,1) + i1_u = UBOUND(SrcShinozukaData%p_k,1) + IF (.NOT. ALLOCATED(DstShinozukaData%p_k)) THEN + ALLOCATE(DstShinozukaData%p_k(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstShinozukaData%p_k.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstShinozukaData%p_k = SrcShinozukaData%p_k +ENDIF +IF (ALLOCATED(SrcShinozukaData%a_k)) THEN + i1_l = LBOUND(SrcShinozukaData%a_k,1) + i1_u = UBOUND(SrcShinozukaData%a_k,1) + IF (.NOT. ALLOCATED(DstShinozukaData%a_k)) THEN + ALLOCATE(DstShinozukaData%a_k(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstShinozukaData%a_k.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstShinozukaData%a_k = SrcShinozukaData%a_k +ENDIF + DstShinozukaData%num_points = SrcShinozukaData%num_points + DstShinozukaData%ILo = SrcShinozukaData%ILo + DstShinozukaData%i = SrcShinozukaData%i + DstShinozukaData%j = SrcShinozukaData%j + DstShinozukaData%dt = SrcShinozukaData%dt + DstShinozukaData%t_min = SrcShinozukaData%t_min + DstShinozukaData%t_max = SrcShinozukaData%t_max + DstShinozukaData%df = SrcShinozukaData%df + END SUBROUTINE DWM_CopyShinozuka + + SUBROUTINE DWM_DestroyShinozuka( ShinozukaData, ErrStat, ErrMsg ) + TYPE(Shinozuka), INTENT(INOUT) :: ShinozukaData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyShinozuka' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ShinozukaData%f_syn)) THEN + DEALLOCATE(ShinozukaData%f_syn) +ENDIF +IF (ALLOCATED(ShinozukaData%t_syn)) THEN + DEALLOCATE(ShinozukaData%t_syn) +ENDIF +IF (ALLOCATED(ShinozukaData%phi)) THEN + DEALLOCATE(ShinozukaData%phi) +ENDIF +IF (ALLOCATED(ShinozukaData%p_k)) THEN + DEALLOCATE(ShinozukaData%p_k) +ENDIF +IF (ALLOCATED(ShinozukaData%a_k)) THEN + DEALLOCATE(ShinozukaData%a_k) +ENDIF + END SUBROUTINE DWM_DestroyShinozuka + + SUBROUTINE DWM_PackShinozuka( 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(Shinozuka), 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 = 'DWM_PackShinozuka' + ! 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 ! f_syn allocated yes/no + IF ( ALLOCATED(InData%f_syn) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! f_syn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%f_syn) ! f_syn + END IF + Int_BufSz = Int_BufSz + 1 ! t_syn allocated yes/no + IF ( ALLOCATED(InData%t_syn) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! t_syn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%t_syn) ! t_syn + END IF + Int_BufSz = Int_BufSz + 1 ! phi allocated yes/no + IF ( ALLOCATED(InData%phi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! phi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%phi) ! phi + END IF + Int_BufSz = Int_BufSz + 1 ! p_k allocated yes/no + IF ( ALLOCATED(InData%p_k) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! p_k upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%p_k) ! p_k + END IF + Int_BufSz = Int_BufSz + 1 ! a_k allocated yes/no + IF ( ALLOCATED(InData%a_k) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! a_k upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%a_k) ! a_k + END IF + Int_BufSz = Int_BufSz + 1 ! num_points + Int_BufSz = Int_BufSz + 1 ! ILo + Int_BufSz = Int_BufSz + 1 ! i + Int_BufSz = Int_BufSz + 1 ! j + Re_BufSz = Re_BufSz + 1 ! dt + Re_BufSz = Re_BufSz + 1 ! t_min + Re_BufSz = Re_BufSz + 1 ! t_max + Re_BufSz = Re_BufSz + 1 ! df + 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%f_syn) ) 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%f_syn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%f_syn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%f_syn,1), UBOUND(InData%f_syn,1) + ReKiBuf(Re_Xferred) = InData%f_syn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%t_syn) ) 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%t_syn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t_syn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%t_syn,1), UBOUND(InData%t_syn,1) + ReKiBuf(Re_Xferred) = InData%t_syn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%phi) ) 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%phi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%phi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%phi,1), UBOUND(InData%phi,1) + ReKiBuf(Re_Xferred) = InData%phi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%p_k) ) 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%p_k,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%p_k,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%p_k,1), UBOUND(InData%p_k,1) + ReKiBuf(Re_Xferred) = InData%p_k(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%a_k) ) 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%a_k,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%a_k,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%a_k,1), UBOUND(InData%a_k,1) + ReKiBuf(Re_Xferred) = InData%a_k(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%num_points + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ILo + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%i + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%j + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t_min + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t_max + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%df + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackShinozuka + + SUBROUTINE DWM_UnPackShinozuka( 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(Shinozuka), 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 = 'DWM_UnPackShinozuka' + ! 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 ! f_syn 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%f_syn)) DEALLOCATE(OutData%f_syn) + ALLOCATE(OutData%f_syn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%f_syn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%f_syn,1), UBOUND(OutData%f_syn,1) + OutData%f_syn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! t_syn 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%t_syn)) DEALLOCATE(OutData%t_syn) + ALLOCATE(OutData%t_syn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%t_syn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%t_syn,1), UBOUND(OutData%t_syn,1) + OutData%t_syn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! phi 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%phi)) DEALLOCATE(OutData%phi) + ALLOCATE(OutData%phi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%phi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%phi,1), UBOUND(OutData%phi,1) + OutData%phi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! p_k 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%p_k)) DEALLOCATE(OutData%p_k) + ALLOCATE(OutData%p_k(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%p_k.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%p_k,1), UBOUND(OutData%p_k,1) + OutData%p_k(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! a_k 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%a_k)) DEALLOCATE(OutData%a_k) + ALLOCATE(OutData%a_k(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%a_k.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%a_k,1), UBOUND(OutData%a_k,1) + OutData%a_k(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%num_points = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ILo = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%i = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%j = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t_min = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t_max = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%df = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackShinozuka + + SUBROUTINE DWM_Copysmooth_out_wake_data( Srcsmooth_out_wake_dataData, Dstsmooth_out_wake_dataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(smooth_out_wake_data), INTENT(IN) :: Srcsmooth_out_wake_dataData + TYPE(smooth_out_wake_data), INTENT(INOUT) :: Dstsmooth_out_wake_dataData + 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 = 'DWM_Copysmooth_out_wake_data' +! + ErrStat = ErrID_None + ErrMsg = "" + Dstsmooth_out_wake_dataData%length_velocity_array = Srcsmooth_out_wake_dataData%length_velocity_array + END SUBROUTINE DWM_Copysmooth_out_wake_data + + SUBROUTINE DWM_Destroysmooth_out_wake_data( smooth_out_wake_dataData, ErrStat, ErrMsg ) + TYPE(smooth_out_wake_data), INTENT(INOUT) :: smooth_out_wake_dataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroysmooth_out_wake_data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_Destroysmooth_out_wake_data + + SUBROUTINE DWM_Packsmooth_out_wake_data( 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(smooth_out_wake_data), 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 = 'DWM_Packsmooth_out_wake_data' + ! 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 ! length_velocity_array + 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%length_velocity_array + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_Packsmooth_out_wake_data + + SUBROUTINE DWM_UnPacksmooth_out_wake_data( 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(smooth_out_wake_data), 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 = 'DWM_UnPacksmooth_out_wake_data' + ! 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%length_velocity_array = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_UnPacksmooth_out_wake_data + + SUBROUTINE DWM_CopySWSV( SrcSWSVData, DstSWSVData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SWSV), INTENT(IN) :: SrcSWSVData + TYPE(SWSV), INTENT(INOUT) :: DstSWSVData + 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 = 'DWM_CopySWSV' +! + ErrStat = ErrID_None + ErrMsg = "" + DstSWSVData%p1 = SrcSWSVData%p1 + DstSWSVData%p2 = SrcSWSVData%p2 + DstSWSVData%distance = SrcSWSVData%distance + DstSWSVData%y0 = SrcSWSVData%y0 + DstSWSVData%z0 = SrcSWSVData%z0 + DstSWSVData%unit = SrcSWSVData%unit + END SUBROUTINE DWM_CopySWSV + + SUBROUTINE DWM_DestroySWSV( SWSVData, ErrStat, ErrMsg ) + TYPE(SWSV), INTENT(INOUT) :: SWSVData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroySWSV' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_DestroySWSV + + SUBROUTINE DWM_PackSWSV( 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(SWSV), 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 = 'DWM_PackSWSV' + ! 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 ! p1 + Int_BufSz = Int_BufSz + 1 ! p2 + Re_BufSz = Re_BufSz + 1 ! distance + Re_BufSz = Re_BufSz + 1 ! y0 + Re_BufSz = Re_BufSz + 1 ! z0 + Re_BufSz = Re_BufSz + 1 ! unit + 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%p1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%p2 + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%distance + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%y0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%z0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%unit + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_PackSWSV + + SUBROUTINE DWM_UnPackSWSV( 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(SWSV), 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 = 'DWM_UnPackSWSV' + ! 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%p1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%p2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%distance = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%y0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%z0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%unit = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE DWM_UnPackSWSV + + SUBROUTINE DWM_Copyread_upwind_result( Srcread_upwind_resultData, Dstread_upwind_resultData, CtrlCode, ErrStat, ErrMsg ) + TYPE(read_upwind_result), INTENT(IN) :: Srcread_upwind_resultData + TYPE(read_upwind_result), INTENT(INOUT) :: Dstread_upwind_resultData + 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 = 'DWM_Copyread_upwind_result' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Srcread_upwind_resultData%upwind_U)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_U,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_U,1) + i2_l = LBOUND(Srcread_upwind_resultData%upwind_U,2) + i2_u = UBOUND(Srcread_upwind_resultData%upwind_U,2) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_U)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_U(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%upwind_U.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_U = Srcread_upwind_resultData%upwind_U +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%upwind_wakecenter)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_wakecenter,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_wakecenter,1) + i2_l = LBOUND(Srcread_upwind_resultData%upwind_wakecenter,2) + i2_u = UBOUND(Srcread_upwind_resultData%upwind_wakecenter,2) + i3_l = LBOUND(Srcread_upwind_resultData%upwind_wakecenter,3) + i3_u = UBOUND(Srcread_upwind_resultData%upwind_wakecenter,3) + i4_l = LBOUND(Srcread_upwind_resultData%upwind_wakecenter,4) + i4_u = UBOUND(Srcread_upwind_resultData%upwind_wakecenter,4) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_wakecenter)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_wakecenter(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 Dstread_upwind_resultData%upwind_wakecenter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_wakecenter = Srcread_upwind_resultData%upwind_wakecenter +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%upwind_meanU)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_meanU,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_meanU,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_meanU)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_meanU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%upwind_meanU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_meanU = Srcread_upwind_resultData%upwind_meanU +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%upwind_TI)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_TI,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_TI,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_TI)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_TI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%upwind_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_TI = Srcread_upwind_resultData%upwind_TI +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%upwind_small_TI)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_small_TI,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_small_TI,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_small_TI)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_small_TI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%upwind_small_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_small_TI = Srcread_upwind_resultData%upwind_small_TI +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%upwind_smoothWake)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%upwind_smoothWake,1) + i1_u = UBOUND(Srcread_upwind_resultData%upwind_smoothWake,1) + i2_l = LBOUND(Srcread_upwind_resultData%upwind_smoothWake,2) + i2_u = UBOUND(Srcread_upwind_resultData%upwind_smoothWake,2) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%upwind_smoothWake)) THEN + ALLOCATE(Dstread_upwind_resultData%upwind_smoothWake(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%upwind_smoothWake.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%upwind_smoothWake = Srcread_upwind_resultData%upwind_smoothWake +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%velocity_aerodyn)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%velocity_aerodyn,1) + i1_u = UBOUND(Srcread_upwind_resultData%velocity_aerodyn,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%velocity_aerodyn)) THEN + ALLOCATE(Dstread_upwind_resultData%velocity_aerodyn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%velocity_aerodyn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%velocity_aerodyn = Srcread_upwind_resultData%velocity_aerodyn +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%TI_downstream)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%TI_downstream,1) + i1_u = UBOUND(Srcread_upwind_resultData%TI_downstream,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%TI_downstream)) THEN + ALLOCATE(Dstread_upwind_resultData%TI_downstream(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%TI_downstream.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%TI_downstream = Srcread_upwind_resultData%TI_downstream +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%small_scale_TI_downstream)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%small_scale_TI_downstream,1) + i1_u = UBOUND(Srcread_upwind_resultData%small_scale_TI_downstream,1) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%small_scale_TI_downstream)) THEN + ALLOCATE(Dstread_upwind_resultData%small_scale_TI_downstream(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%small_scale_TI_downstream.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%small_scale_TI_downstream = Srcread_upwind_resultData%small_scale_TI_downstream +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%smoothed_velocity_array)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%smoothed_velocity_array,1) + i1_u = UBOUND(Srcread_upwind_resultData%smoothed_velocity_array,1) + i2_l = LBOUND(Srcread_upwind_resultData%smoothed_velocity_array,2) + i2_u = UBOUND(Srcread_upwind_resultData%smoothed_velocity_array,2) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%smoothed_velocity_array)) THEN + ALLOCATE(Dstread_upwind_resultData%smoothed_velocity_array(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%smoothed_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%smoothed_velocity_array = Srcread_upwind_resultData%smoothed_velocity_array +ENDIF +IF (ALLOCATED(Srcread_upwind_resultData%vel_matrix)) THEN + i1_l = LBOUND(Srcread_upwind_resultData%vel_matrix,1) + i1_u = UBOUND(Srcread_upwind_resultData%vel_matrix,1) + i2_l = LBOUND(Srcread_upwind_resultData%vel_matrix,2) + i2_u = UBOUND(Srcread_upwind_resultData%vel_matrix,2) + i3_l = LBOUND(Srcread_upwind_resultData%vel_matrix,3) + i3_u = UBOUND(Srcread_upwind_resultData%vel_matrix,3) + IF (.NOT. ALLOCATED(Dstread_upwind_resultData%vel_matrix)) THEN + ALLOCATE(Dstread_upwind_resultData%vel_matrix(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstread_upwind_resultData%vel_matrix.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstread_upwind_resultData%vel_matrix = Srcread_upwind_resultData%vel_matrix +ENDIF + END SUBROUTINE DWM_Copyread_upwind_result + + SUBROUTINE DWM_Destroyread_upwind_result( read_upwind_resultData, ErrStat, ErrMsg ) + TYPE(read_upwind_result), INTENT(INOUT) :: read_upwind_resultData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroyread_upwind_result' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(read_upwind_resultData%upwind_U)) THEN + DEALLOCATE(read_upwind_resultData%upwind_U) +ENDIF +IF (ALLOCATED(read_upwind_resultData%upwind_wakecenter)) THEN + DEALLOCATE(read_upwind_resultData%upwind_wakecenter) +ENDIF +IF (ALLOCATED(read_upwind_resultData%upwind_meanU)) THEN + DEALLOCATE(read_upwind_resultData%upwind_meanU) +ENDIF +IF (ALLOCATED(read_upwind_resultData%upwind_TI)) THEN + DEALLOCATE(read_upwind_resultData%upwind_TI) +ENDIF +IF (ALLOCATED(read_upwind_resultData%upwind_small_TI)) THEN + DEALLOCATE(read_upwind_resultData%upwind_small_TI) +ENDIF +IF (ALLOCATED(read_upwind_resultData%upwind_smoothWake)) THEN + DEALLOCATE(read_upwind_resultData%upwind_smoothWake) +ENDIF +IF (ALLOCATED(read_upwind_resultData%velocity_aerodyn)) THEN + DEALLOCATE(read_upwind_resultData%velocity_aerodyn) +ENDIF +IF (ALLOCATED(read_upwind_resultData%TI_downstream)) THEN + DEALLOCATE(read_upwind_resultData%TI_downstream) +ENDIF +IF (ALLOCATED(read_upwind_resultData%small_scale_TI_downstream)) THEN + DEALLOCATE(read_upwind_resultData%small_scale_TI_downstream) +ENDIF +IF (ALLOCATED(read_upwind_resultData%smoothed_velocity_array)) THEN + DEALLOCATE(read_upwind_resultData%smoothed_velocity_array) +ENDIF +IF (ALLOCATED(read_upwind_resultData%vel_matrix)) THEN + DEALLOCATE(read_upwind_resultData%vel_matrix) +ENDIF + END SUBROUTINE DWM_Destroyread_upwind_result + + SUBROUTINE DWM_Packread_upwind_result( 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(read_upwind_result), 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 = 'DWM_Packread_upwind_result' + ! 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 ! upwind_U allocated yes/no + IF ( ALLOCATED(InData%upwind_U) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! upwind_U upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_U) ! upwind_U + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_wakecenter allocated yes/no + IF ( ALLOCATED(InData%upwind_wakecenter) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! upwind_wakecenter upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_wakecenter) ! upwind_wakecenter + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_meanU allocated yes/no + IF ( ALLOCATED(InData%upwind_meanU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_meanU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_meanU) ! upwind_meanU + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_TI allocated yes/no + IF ( ALLOCATED(InData%upwind_TI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_TI) ! upwind_TI + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_small_TI allocated yes/no + IF ( ALLOCATED(InData%upwind_small_TI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! upwind_small_TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_small_TI) ! upwind_small_TI + END IF + Int_BufSz = Int_BufSz + 1 ! upwind_smoothWake allocated yes/no + IF ( ALLOCATED(InData%upwind_smoothWake) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! upwind_smoothWake upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%upwind_smoothWake) ! upwind_smoothWake + END IF + Int_BufSz = Int_BufSz + 1 ! velocity_aerodyn allocated yes/no + IF ( ALLOCATED(InData%velocity_aerodyn) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! velocity_aerodyn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%velocity_aerodyn) ! velocity_aerodyn + END IF + Int_BufSz = Int_BufSz + 1 ! TI_downstream allocated yes/no + IF ( ALLOCATED(InData%TI_downstream) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TI_downstream upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI_downstream) ! TI_downstream + END IF + Int_BufSz = Int_BufSz + 1 ! small_scale_TI_downstream allocated yes/no + IF ( ALLOCATED(InData%small_scale_TI_downstream) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! small_scale_TI_downstream upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%small_scale_TI_downstream) ! small_scale_TI_downstream + END IF + Int_BufSz = Int_BufSz + 1 ! smoothed_velocity_array allocated yes/no + IF ( ALLOCATED(InData%smoothed_velocity_array) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! smoothed_velocity_array upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%smoothed_velocity_array) ! smoothed_velocity_array + END IF + Int_BufSz = Int_BufSz + 1 ! vel_matrix allocated yes/no + IF ( ALLOCATED(InData%vel_matrix) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! vel_matrix upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%vel_matrix) ! vel_matrix + 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%upwind_U) ) 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%upwind_U,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_U,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%upwind_U,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_U,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%upwind_U,2), UBOUND(InData%upwind_U,2) + DO i1 = LBOUND(InData%upwind_U,1), UBOUND(InData%upwind_U,1) + ReKiBuf(Re_Xferred) = InData%upwind_U(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_wakecenter) ) 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%upwind_wakecenter,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_wakecenter,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%upwind_wakecenter,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_wakecenter,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%upwind_wakecenter,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_wakecenter,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%upwind_wakecenter,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_wakecenter,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%upwind_wakecenter,4), UBOUND(InData%upwind_wakecenter,4) + DO i3 = LBOUND(InData%upwind_wakecenter,3), UBOUND(InData%upwind_wakecenter,3) + DO i2 = LBOUND(InData%upwind_wakecenter,2), UBOUND(InData%upwind_wakecenter,2) + DO i1 = LBOUND(InData%upwind_wakecenter,1), UBOUND(InData%upwind_wakecenter,1) + ReKiBuf(Re_Xferred) = InData%upwind_wakecenter(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_meanU) ) 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%upwind_meanU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_meanU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_meanU,1), UBOUND(InData%upwind_meanU,1) + ReKiBuf(Re_Xferred) = InData%upwind_meanU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_TI) ) 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%upwind_TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_TI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_TI,1), UBOUND(InData%upwind_TI,1) + ReKiBuf(Re_Xferred) = InData%upwind_TI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_small_TI) ) 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%upwind_small_TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_small_TI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%upwind_small_TI,1), UBOUND(InData%upwind_small_TI,1) + ReKiBuf(Re_Xferred) = InData%upwind_small_TI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%upwind_smoothWake) ) 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%upwind_smoothWake,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_smoothWake,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%upwind_smoothWake,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%upwind_smoothWake,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%upwind_smoothWake,2), UBOUND(InData%upwind_smoothWake,2) + DO i1 = LBOUND(InData%upwind_smoothWake,1), UBOUND(InData%upwind_smoothWake,1) + ReKiBuf(Re_Xferred) = InData%upwind_smoothWake(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%velocity_aerodyn) ) 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%velocity_aerodyn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%velocity_aerodyn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%velocity_aerodyn,1), UBOUND(InData%velocity_aerodyn,1) + ReKiBuf(Re_Xferred) = InData%velocity_aerodyn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TI_downstream) ) 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%TI_downstream,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI_downstream,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TI_downstream,1), UBOUND(InData%TI_downstream,1) + ReKiBuf(Re_Xferred) = InData%TI_downstream(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%small_scale_TI_downstream) ) 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%small_scale_TI_downstream,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%small_scale_TI_downstream,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%small_scale_TI_downstream,1), UBOUND(InData%small_scale_TI_downstream,1) + ReKiBuf(Re_Xferred) = InData%small_scale_TI_downstream(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%smoothed_velocity_array) ) 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%smoothed_velocity_array,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%smoothed_velocity_array,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%smoothed_velocity_array,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%smoothed_velocity_array,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%smoothed_velocity_array,2), UBOUND(InData%smoothed_velocity_array,2) + DO i1 = LBOUND(InData%smoothed_velocity_array,1), UBOUND(InData%smoothed_velocity_array,1) + ReKiBuf(Re_Xferred) = InData%smoothed_velocity_array(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%vel_matrix) ) 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_matrix,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vel_matrix,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vel_matrix,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vel_matrix,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vel_matrix,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vel_matrix,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%vel_matrix,3), UBOUND(InData%vel_matrix,3) + DO i2 = LBOUND(InData%vel_matrix,2), UBOUND(InData%vel_matrix,2) + DO i1 = LBOUND(InData%vel_matrix,1), UBOUND(InData%vel_matrix,1) + ReKiBuf(Re_Xferred) = InData%vel_matrix(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE DWM_Packread_upwind_result + + SUBROUTINE DWM_UnPackread_upwind_result( 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(read_upwind_result), 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 = 'DWM_UnPackread_upwind_result' + ! 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 ! upwind_U 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%upwind_U)) DEALLOCATE(OutData%upwind_U) + ALLOCATE(OutData%upwind_U(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_U.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%upwind_U,2), UBOUND(OutData%upwind_U,2) + DO i1 = LBOUND(OutData%upwind_U,1), UBOUND(OutData%upwind_U,1) + OutData%upwind_U(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_wakecenter 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%upwind_wakecenter)) DEALLOCATE(OutData%upwind_wakecenter) + ALLOCATE(OutData%upwind_wakecenter(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%upwind_wakecenter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%upwind_wakecenter,4), UBOUND(OutData%upwind_wakecenter,4) + DO i3 = LBOUND(OutData%upwind_wakecenter,3), UBOUND(OutData%upwind_wakecenter,3) + DO i2 = LBOUND(OutData%upwind_wakecenter,2), UBOUND(OutData%upwind_wakecenter,2) + DO i1 = LBOUND(OutData%upwind_wakecenter,1), UBOUND(OutData%upwind_wakecenter,1) + OutData%upwind_wakecenter(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_meanU 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%upwind_meanU)) DEALLOCATE(OutData%upwind_meanU) + ALLOCATE(OutData%upwind_meanU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_meanU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_meanU,1), UBOUND(OutData%upwind_meanU,1) + OutData%upwind_meanU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_TI 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%upwind_TI)) DEALLOCATE(OutData%upwind_TI) + ALLOCATE(OutData%upwind_TI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_TI,1), UBOUND(OutData%upwind_TI,1) + OutData%upwind_TI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_small_TI 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%upwind_small_TI)) DEALLOCATE(OutData%upwind_small_TI) + ALLOCATE(OutData%upwind_small_TI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_small_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%upwind_small_TI,1), UBOUND(OutData%upwind_small_TI,1) + OutData%upwind_small_TI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! upwind_smoothWake 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%upwind_smoothWake)) DEALLOCATE(OutData%upwind_smoothWake) + ALLOCATE(OutData%upwind_smoothWake(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%upwind_smoothWake.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%upwind_smoothWake,2), UBOUND(OutData%upwind_smoothWake,2) + DO i1 = LBOUND(OutData%upwind_smoothWake,1), UBOUND(OutData%upwind_smoothWake,1) + OutData%upwind_smoothWake(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! velocity_aerodyn 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%velocity_aerodyn)) DEALLOCATE(OutData%velocity_aerodyn) + ALLOCATE(OutData%velocity_aerodyn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%velocity_aerodyn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%velocity_aerodyn,1), UBOUND(OutData%velocity_aerodyn,1) + OutData%velocity_aerodyn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI_downstream 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%TI_downstream)) DEALLOCATE(OutData%TI_downstream) + ALLOCATE(OutData%TI_downstream(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI_downstream.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TI_downstream,1), UBOUND(OutData%TI_downstream,1) + OutData%TI_downstream(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! small_scale_TI_downstream 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%small_scale_TI_downstream)) DEALLOCATE(OutData%small_scale_TI_downstream) + ALLOCATE(OutData%small_scale_TI_downstream(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%small_scale_TI_downstream.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%small_scale_TI_downstream,1), UBOUND(OutData%small_scale_TI_downstream,1) + OutData%small_scale_TI_downstream(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! smoothed_velocity_array 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%smoothed_velocity_array)) DEALLOCATE(OutData%smoothed_velocity_array) + ALLOCATE(OutData%smoothed_velocity_array(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%smoothed_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%smoothed_velocity_array,2), UBOUND(OutData%smoothed_velocity_array,2) + DO i1 = LBOUND(OutData%smoothed_velocity_array,1), UBOUND(OutData%smoothed_velocity_array,1) + OutData%smoothed_velocity_array(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! vel_matrix 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%vel_matrix)) DEALLOCATE(OutData%vel_matrix) + ALLOCATE(OutData%vel_matrix(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%vel_matrix.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%vel_matrix,3), UBOUND(OutData%vel_matrix,3) + DO i2 = LBOUND(OutData%vel_matrix,2), UBOUND(OutData%vel_matrix,2) + DO i1 = LBOUND(OutData%vel_matrix,1), UBOUND(OutData%vel_matrix,1) + OutData%vel_matrix(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE DWM_UnPackread_upwind_result + + SUBROUTINE DWM_Copywake_meandered_center( Srcwake_meandered_centerData, Dstwake_meandered_centerData, CtrlCode, ErrStat, ErrMsg ) + TYPE(wake_meandered_center), INTENT(IN) :: Srcwake_meandered_centerData + TYPE(wake_meandered_center), INTENT(INOUT) :: Dstwake_meandered_centerData + 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 = 'DWM_Copywake_meandered_center' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Srcwake_meandered_centerData%wake_width)) THEN + i1_l = LBOUND(Srcwake_meandered_centerData%wake_width,1) + i1_u = UBOUND(Srcwake_meandered_centerData%wake_width,1) + IF (.NOT. ALLOCATED(Dstwake_meandered_centerData%wake_width)) THEN + ALLOCATE(Dstwake_meandered_centerData%wake_width(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Dstwake_meandered_centerData%wake_width.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + Dstwake_meandered_centerData%wake_width = Srcwake_meandered_centerData%wake_width +ENDIF + END SUBROUTINE DWM_Copywake_meandered_center + + SUBROUTINE DWM_Destroywake_meandered_center( wake_meandered_centerData, ErrStat, ErrMsg ) + TYPE(wake_meandered_center), INTENT(INOUT) :: wake_meandered_centerData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroywake_meandered_center' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(wake_meandered_centerData%wake_width)) THEN + DEALLOCATE(wake_meandered_centerData%wake_width) +ENDIF + END SUBROUTINE DWM_Destroywake_meandered_center + + SUBROUTINE DWM_Packwake_meandered_center( 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(wake_meandered_center), 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 = 'DWM_Packwake_meandered_center' + ! 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 ! wake_width allocated yes/no + IF ( ALLOCATED(InData%wake_width) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! wake_width upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%wake_width) ! wake_width + 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%wake_width) ) 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%wake_width,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_width,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%wake_width,1), UBOUND(InData%wake_width,1) + IntKiBuf(Int_Xferred) = InData%wake_width(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE DWM_Packwake_meandered_center + + SUBROUTINE DWM_UnPackwake_meandered_center( 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(wake_meandered_center), 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 = 'DWM_UnPackwake_meandered_center' + ! 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 ! wake_width 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%wake_width)) DEALLOCATE(OutData%wake_width) + ALLOCATE(OutData%wake_width(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%wake_width.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%wake_width,1), UBOUND(OutData%wake_width,1) + OutData%wake_width(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE DWM_UnPackwake_meandered_center + + SUBROUTINE DWM_Copyturbine_blade( Srcturbine_bladeData, Dstturbine_bladeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_turbine_blade), INTENT(IN) :: Srcturbine_bladeData + TYPE(DWM_turbine_blade), INTENT(INOUT) :: Dstturbine_bladeData + 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 = 'DWM_Copyturbine_blade' +! + ErrStat = ErrID_None + ErrMsg = "" + Dstturbine_bladeData%Aerodyn_turbine_num = Srcturbine_bladeData%Aerodyn_turbine_num + Dstturbine_bladeData%Blade_index = Srcturbine_bladeData%Blade_index + Dstturbine_bladeData%Element_index = Srcturbine_bladeData%Element_index + END SUBROUTINE DWM_Copyturbine_blade + + SUBROUTINE DWM_Destroyturbine_blade( turbine_bladeData, ErrStat, ErrMsg ) + TYPE(DWM_turbine_blade), INTENT(INOUT) :: turbine_bladeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Destroyturbine_blade' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE DWM_Destroyturbine_blade + + SUBROUTINE DWM_Packturbine_blade( 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(DWM_turbine_blade), 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 = 'DWM_Packturbine_blade' + ! 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 ! Aerodyn_turbine_num + Int_BufSz = Int_BufSz + 1 ! Blade_index + Int_BufSz = Int_BufSz + 1 ! Element_index + 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%Aerodyn_turbine_num + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Blade_index + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Element_index + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_Packturbine_blade + + SUBROUTINE DWM_UnPackturbine_blade( 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(DWM_turbine_blade), 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 = 'DWM_UnPackturbine_blade' + ! 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%Aerodyn_turbine_num = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Blade_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Element_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE DWM_UnPackturbine_blade + + SUBROUTINE DWM_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_ParameterType), INTENT(IN) :: SrcParamData + TYPE(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcParamData%velocityU)) THEN + i1_l = LBOUND(SrcParamData%velocityU,1) + i1_u = UBOUND(SrcParamData%velocityU,1) + IF (.NOT. ALLOCATED(DstParamData%velocityU)) THEN + ALLOCATE(DstParamData%velocityU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%velocityU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%velocityU = SrcParamData%velocityU +ENDIF +IF (ALLOCATED(SrcParamData%smoothed_wake)) THEN + i1_l = LBOUND(SrcParamData%smoothed_wake,1) + i1_u = UBOUND(SrcParamData%smoothed_wake,1) + IF (.NOT. ALLOCATED(DstParamData%smoothed_wake)) THEN + ALLOCATE(DstParamData%smoothed_wake(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%smoothed_wake.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%smoothed_wake = SrcParamData%smoothed_wake +ENDIF +IF (ALLOCATED(SrcParamData%WakePosition)) THEN + i1_l = LBOUND(SrcParamData%WakePosition,1) + i1_u = UBOUND(SrcParamData%WakePosition,1) + i2_l = LBOUND(SrcParamData%WakePosition,2) + i2_u = UBOUND(SrcParamData%WakePosition,2) + i3_l = LBOUND(SrcParamData%WakePosition,3) + i3_u = UBOUND(SrcParamData%WakePosition,3) + IF (.NOT. ALLOCATED(DstParamData%WakePosition)) THEN + ALLOCATE(DstParamData%WakePosition(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%WakePosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WakePosition = SrcParamData%WakePosition +ENDIF + DstParamData%WakePosition_1 = SrcParamData%WakePosition_1 + DstParamData%WakePosition_2 = SrcParamData%WakePosition_2 + DstParamData%smooth_flag = SrcParamData%smooth_flag + DstParamData%p_p_r = SrcParamData%p_p_r + DstParamData%NumWT = SrcParamData%NumWT + DstParamData%Tinfluencer = SrcParamData%Tinfluencer + DstParamData%RotorR = SrcParamData%RotorR + DstParamData%r_domain = SrcParamData%r_domain + DstParamData%x_domain = SrcParamData%x_domain + DstParamData%Uambient = SrcParamData%Uambient + DstParamData%TI_amb = SrcParamData%TI_amb + DstParamData%TI_wake = SrcParamData%TI_wake + DstParamData%hub_height = SrcParamData%hub_height + DstParamData%length_velocityU = SrcParamData%length_velocityU + DstParamData%WFLowerBd = SrcParamData%WFLowerBd + DstParamData%Wind_file_Mean_u = SrcParamData%Wind_file_Mean_u + DstParamData%Winddir = SrcParamData%Winddir + DstParamData%air_density = SrcParamData%air_density + DstParamData%RR = SrcParamData%RR +IF (ALLOCATED(SrcParamData%ElementRad)) THEN + i1_l = LBOUND(SrcParamData%ElementRad,1) + i1_u = UBOUND(SrcParamData%ElementRad,1) + IF (.NOT. ALLOCATED(DstParamData%ElementRad)) THEN + ALLOCATE(DstParamData%ElementRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElementRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ElementRad = SrcParamData%ElementRad +ENDIF + DstParamData%Bnum = SrcParamData%Bnum + DstParamData%ElementNum = SrcParamData%ElementNum + CALL DWM_Copyread_turbine_position_data( SrcParamData%RTPD, DstParamData%RTPD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyParam( SrcParamData%IfW, DstParamData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyParam + + SUBROUTINE DWM_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(DWM_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%velocityU)) THEN + DEALLOCATE(ParamData%velocityU) +ENDIF +IF (ALLOCATED(ParamData%smoothed_wake)) THEN + DEALLOCATE(ParamData%smoothed_wake) +ENDIF +IF (ALLOCATED(ParamData%WakePosition)) THEN + DEALLOCATE(ParamData%WakePosition) +ENDIF +IF (ALLOCATED(ParamData%ElementRad)) THEN + DEALLOCATE(ParamData%ElementRad) +ENDIF + CALL DWM_Destroyread_turbine_position_data( ParamData%RTPD, ErrStat, ErrMsg ) + CALL InflowWind_DestroyParam( ParamData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyParam + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 ! velocityU allocated yes/no + IF ( ALLOCATED(InData%velocityU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! velocityU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%velocityU) ! velocityU + END IF + Int_BufSz = Int_BufSz + 1 ! smoothed_wake allocated yes/no + IF ( ALLOCATED(InData%smoothed_wake) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! smoothed_wake upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%smoothed_wake) ! smoothed_wake + END IF + Int_BufSz = Int_BufSz + 1 ! WakePosition allocated yes/no + IF ( ALLOCATED(InData%WakePosition) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WakePosition upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WakePosition) ! WakePosition + END IF + Int_BufSz = Int_BufSz + 1 ! WakePosition_1 + Int_BufSz = Int_BufSz + 1 ! WakePosition_2 + Int_BufSz = Int_BufSz + 1 ! smooth_flag + Int_BufSz = Int_BufSz + 1 ! p_p_r + Int_BufSz = Int_BufSz + 1 ! NumWT + Int_BufSz = Int_BufSz + 1 ! Tinfluencer + Re_BufSz = Re_BufSz + 1 ! RotorR + Re_BufSz = Re_BufSz + 1 ! r_domain + Re_BufSz = Re_BufSz + 1 ! x_domain + Re_BufSz = Re_BufSz + 1 ! Uambient + Re_BufSz = Re_BufSz + 1 ! TI_amb + Re_BufSz = Re_BufSz + 1 ! TI_wake + Re_BufSz = Re_BufSz + 1 ! hub_height + Re_BufSz = Re_BufSz + 1 ! length_velocityU + Re_BufSz = Re_BufSz + 1 ! WFLowerBd + Re_BufSz = Re_BufSz + 1 ! Wind_file_Mean_u + Re_BufSz = Re_BufSz + 1 ! Winddir + Re_BufSz = Re_BufSz + 1 ! air_density + Re_BufSz = Re_BufSz + 1 ! RR + Int_BufSz = Int_BufSz + 1 ! ElementRad allocated yes/no + IF ( ALLOCATED(InData%ElementRad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElementRad upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ElementRad) ! ElementRad + END IF + Int_BufSz = Int_BufSz + 1 ! Bnum + Int_BufSz = Int_BufSz + 1 ! ElementNum + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! RTPD: size of buffers for each call to pack subtype + CALL DWM_Packread_turbine_position_data( Re_Buf, Db_Buf, Int_Buf, InData%RTPD, ErrStat2, ErrMsg2, .TRUE. ) ! RTPD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RTPD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RTPD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RTPD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + IF ( .NOT. ALLOCATED(InData%velocityU) ) 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%velocityU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%velocityU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%velocityU,1), UBOUND(InData%velocityU,1) + ReKiBuf(Re_Xferred) = InData%velocityU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%smoothed_wake) ) 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%smoothed_wake,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%smoothed_wake,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%smoothed_wake,1), UBOUND(InData%smoothed_wake,1) + ReKiBuf(Re_Xferred) = InData%smoothed_wake(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WakePosition) ) 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%WakePosition,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WakePosition,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WakePosition,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WakePosition,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WakePosition,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WakePosition,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WakePosition,3), UBOUND(InData%WakePosition,3) + DO i2 = LBOUND(InData%WakePosition,2), UBOUND(InData%WakePosition,2) + DO i1 = LBOUND(InData%WakePosition,1), UBOUND(InData%WakePosition,1) + ReKiBuf(Re_Xferred) = InData%WakePosition(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%WakePosition_1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WakePosition_2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%smooth_flag + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%p_p_r + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumWT + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Tinfluencer + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotorR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%r_domain + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%x_domain + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Uambient + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_amb + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_wake + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%hub_height + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%length_velocityU + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WFLowerBd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Wind_file_Mean_u + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Winddir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%air_density + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RR + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ElementRad) ) 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%ElementRad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElementRad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElementRad,1), UBOUND(InData%ElementRad,1) + ReKiBuf(Re_Xferred) = InData%ElementRad(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Bnum + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ElementNum + Int_Xferred = Int_Xferred + 1 + CALL DWM_Packread_turbine_position_data( Re_Buf, Db_Buf, Int_Buf, InData%RTPD, ErrStat2, ErrMsg2, OnlySize ) ! RTPD + 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_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackParam + + SUBROUTINE DWM_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(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_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 ! velocityU 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%velocityU)) DEALLOCATE(OutData%velocityU) + ALLOCATE(OutData%velocityU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%velocityU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%velocityU,1), UBOUND(OutData%velocityU,1) + OutData%velocityU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! smoothed_wake 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%smoothed_wake)) DEALLOCATE(OutData%smoothed_wake) + ALLOCATE(OutData%smoothed_wake(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%smoothed_wake.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%smoothed_wake,1), UBOUND(OutData%smoothed_wake,1) + OutData%smoothed_wake(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WakePosition 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%WakePosition)) DEALLOCATE(OutData%WakePosition) + ALLOCATE(OutData%WakePosition(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%WakePosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WakePosition,3), UBOUND(OutData%WakePosition,3) + DO i2 = LBOUND(OutData%WakePosition,2), UBOUND(OutData%WakePosition,2) + DO i1 = LBOUND(OutData%WakePosition,1), UBOUND(OutData%WakePosition,1) + OutData%WakePosition(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%WakePosition_1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WakePosition_2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%smooth_flag = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%p_p_r = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumWT = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Tinfluencer = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RotorR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%r_domain = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%x_domain = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Uambient = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_amb = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_wake = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%hub_height = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%length_velocityU = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WFLowerBd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Wind_file_Mean_u = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Winddir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%air_density = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElementRad 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%ElementRad)) DEALLOCATE(OutData%ElementRad) + ALLOCATE(OutData%ElementRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElementRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElementRad,1), UBOUND(OutData%ElementRad,1) + OutData%ElementRad(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Bnum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ElementNum = 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 DWM_Unpackread_turbine_position_data( Re_Buf, Db_Buf, Int_Buf, OutData%RTPD, ErrStat2, ErrMsg2 ) ! RTPD + 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 InflowWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackParam + + SUBROUTINE DWM_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(DWM_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 = 'DWM_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_CopyOtherState( SrcOtherStateData%IfW, DstOtherStateData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyOtherState + + SUBROUTINE DWM_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(DWM_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyOtherState( OtherStateData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyOtherState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackOtherState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + 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_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackOtherState + + SUBROUTINE DWM_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_CopyMisc( SrcMiscData%IfW, DstMiscData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%position_y = SrcMiscData%position_y + DstMiscData%position_z = SrcMiscData%position_z + DstMiscData%velocity_wake_mean = SrcMiscData%velocity_wake_mean + DstMiscData%shifted_velocity_Aerodyn = SrcMiscData%shifted_velocity_Aerodyn + DstMiscData%U_velocity = SrcMiscData%U_velocity + DstMiscData%V_velocity = SrcMiscData%V_velocity +IF (ALLOCATED(SrcMiscData%Nforce)) THEN + i1_l = LBOUND(SrcMiscData%Nforce,1) + i1_u = UBOUND(SrcMiscData%Nforce,1) + i2_l = LBOUND(SrcMiscData%Nforce,2) + i2_u = UBOUND(SrcMiscData%Nforce,2) + IF (.NOT. ALLOCATED(DstMiscData%Nforce)) THEN + ALLOCATE(DstMiscData%Nforce(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Nforce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Nforce = SrcMiscData%Nforce +ENDIF +IF (ALLOCATED(SrcMiscData%blade_dr)) THEN + i1_l = LBOUND(SrcMiscData%blade_dr,1) + i1_u = UBOUND(SrcMiscData%blade_dr,1) + IF (.NOT. ALLOCATED(DstMiscData%blade_dr)) THEN + ALLOCATE(DstMiscData%blade_dr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%blade_dr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%blade_dr = SrcMiscData%blade_dr +ENDIF + DstMiscData%NacYaw = SrcMiscData%NacYaw + DstMiscData%TI_original = SrcMiscData%TI_original + CALL DWM_Copyturbine_average_velocity_data( SrcMiscData%TAVD, DstMiscData%TAVD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copycvsd( SrcMiscData%CalVelScale_data, DstMiscData%CalVelScale_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copymeanderdata( SrcMiscData%meandering_data, DstMiscData%meandering_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copyweimethod( SrcMiscData%weighting_method, DstMiscData%weighting_method, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copytidownstream( SrcMiscData%TI_downstream_data, DstMiscData%TI_downstream_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copyturbkaimal( SrcMiscData%Turbulence_KS, DstMiscData%Turbulence_KS, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copyshinozuka( SrcMiscData%shinozuka_data, DstMiscData%shinozuka_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copysmooth_out_wake_data( SrcMiscData%SmoothOut, DstMiscData%SmoothOut, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copyswsv( SrcMiscData%smooth_wake_shifted_velocity_data, DstMiscData%smooth_wake_shifted_velocity_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copywake_deficit_data( SrcMiscData%DWDD, DstMiscData%DWDD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%ct_tilde = SrcMiscData%ct_tilde + DstMiscData%FAST_Time = SrcMiscData%FAST_Time + DstMiscData%SDtimestep = SrcMiscData%SDtimestep + CALL DWM_Copyturbine_blade( SrcMiscData%DWM_tb, DstMiscData%DWM_tb, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL DWM_Copywake_meandered_center( SrcMiscData%WMC, DstMiscData%WMC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyMisc + + SUBROUTINE DWM_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(DWM_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyMisc( MiscData%IfW, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%Nforce)) THEN + DEALLOCATE(MiscData%Nforce) +ENDIF +IF (ALLOCATED(MiscData%blade_dr)) THEN + DEALLOCATE(MiscData%blade_dr) +ENDIF + CALL DWM_Destroyturbine_average_velocity_data( MiscData%TAVD, ErrStat, ErrMsg ) + CALL DWM_Destroycvsd( MiscData%CalVelScale_data, ErrStat, ErrMsg ) + CALL DWM_Destroymeanderdata( MiscData%meandering_data, ErrStat, ErrMsg ) + CALL DWM_Destroyweimethod( MiscData%weighting_method, ErrStat, ErrMsg ) + CALL DWM_Destroytidownstream( MiscData%TI_downstream_data, ErrStat, ErrMsg ) + CALL DWM_Destroyturbkaimal( MiscData%Turbulence_KS, ErrStat, ErrMsg ) + CALL DWM_Destroyshinozuka( MiscData%shinozuka_data, ErrStat, ErrMsg ) + CALL DWM_Destroysmooth_out_wake_data( MiscData%SmoothOut, ErrStat, ErrMsg ) + CALL DWM_Destroyswsv( MiscData%smooth_wake_shifted_velocity_data, ErrStat, ErrMsg ) + CALL DWM_Destroywake_deficit_data( MiscData%DWDD, ErrStat, ErrMsg ) + CALL DWM_Destroyturbine_blade( MiscData%DWM_tb, ErrStat, ErrMsg ) + CALL DWM_Destroywake_meandered_center( MiscData%WMC, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyMisc + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! position_y + Re_BufSz = Re_BufSz + 1 ! position_z + Re_BufSz = Re_BufSz + 1 ! velocity_wake_mean + Re_BufSz = Re_BufSz + 1 ! shifted_velocity_Aerodyn + Re_BufSz = Re_BufSz + 1 ! U_velocity + Re_BufSz = Re_BufSz + 1 ! V_velocity + Int_BufSz = Int_BufSz + 1 ! Nforce allocated yes/no + IF ( ALLOCATED(InData%Nforce) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nforce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Nforce) ! Nforce + END IF + Int_BufSz = Int_BufSz + 1 ! blade_dr allocated yes/no + IF ( ALLOCATED(InData%blade_dr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! blade_dr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%blade_dr) ! blade_dr + END IF + Re_BufSz = Re_BufSz + 1 ! NacYaw + Re_BufSz = Re_BufSz + 1 ! TI_original + Int_BufSz = Int_BufSz + 3 ! TAVD: size of buffers for each call to pack subtype + CALL DWM_Packturbine_average_velocity_data( Re_Buf, Db_Buf, Int_Buf, InData%TAVD, ErrStat2, ErrMsg2, .TRUE. ) ! TAVD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TAVD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TAVD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TAVD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! CalVelScale_data: size of buffers for each call to pack subtype + CALL DWM_Packcvsd( Re_Buf, Db_Buf, Int_Buf, InData%CalVelScale_data, ErrStat2, ErrMsg2, .TRUE. ) ! CalVelScale_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! CalVelScale_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! CalVelScale_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! CalVelScale_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! meandering_data: size of buffers for each call to pack subtype + CALL DWM_Packmeanderdata( Re_Buf, Db_Buf, Int_Buf, InData%meandering_data, ErrStat2, ErrMsg2, .TRUE. ) ! meandering_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! meandering_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! meandering_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! meandering_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! weighting_method: size of buffers for each call to pack subtype + CALL DWM_Packweimethod( Re_Buf, Db_Buf, Int_Buf, InData%weighting_method, ErrStat2, ErrMsg2, .TRUE. ) ! weighting_method + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! weighting_method + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! weighting_method + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! weighting_method + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TI_downstream_data: size of buffers for each call to pack subtype + CALL DWM_Packtidownstream( Re_Buf, Db_Buf, Int_Buf, InData%TI_downstream_data, ErrStat2, ErrMsg2, .TRUE. ) ! TI_downstream_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TI_downstream_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TI_downstream_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TI_downstream_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Turbulence_KS: size of buffers for each call to pack subtype + CALL DWM_Packturbkaimal( Re_Buf, Db_Buf, Int_Buf, InData%Turbulence_KS, ErrStat2, ErrMsg2, .TRUE. ) ! Turbulence_KS + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Turbulence_KS + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Turbulence_KS + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Turbulence_KS + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! shinozuka_data: size of buffers for each call to pack subtype + CALL DWM_Packshinozuka( Re_Buf, Db_Buf, Int_Buf, InData%shinozuka_data, ErrStat2, ErrMsg2, .TRUE. ) ! shinozuka_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! shinozuka_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! shinozuka_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! shinozuka_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SmoothOut: size of buffers for each call to pack subtype + CALL DWM_Packsmooth_out_wake_data( Re_Buf, Db_Buf, Int_Buf, InData%SmoothOut, ErrStat2, ErrMsg2, .TRUE. ) ! SmoothOut + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SmoothOut + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SmoothOut + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SmoothOut + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! smooth_wake_shifted_velocity_data: size of buffers for each call to pack subtype + CALL DWM_Packswsv( Re_Buf, Db_Buf, Int_Buf, InData%smooth_wake_shifted_velocity_data, ErrStat2, ErrMsg2, .TRUE. ) ! smooth_wake_shifted_velocity_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! smooth_wake_shifted_velocity_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! smooth_wake_shifted_velocity_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! smooth_wake_shifted_velocity_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DWDD: size of buffers for each call to pack subtype + CALL DWM_Packwake_deficit_data( Re_Buf, Db_Buf, Int_Buf, InData%DWDD, ErrStat2, ErrMsg2, .TRUE. ) ! DWDD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWDD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWDD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWDD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! ct_tilde + Re_BufSz = Re_BufSz + 1 ! FAST_Time + Int_BufSz = Int_BufSz + 1 ! SDtimestep + Int_BufSz = Int_BufSz + 3 ! DWM_tb: size of buffers for each call to pack subtype + CALL DWM_Packturbine_blade( Re_Buf, Db_Buf, Int_Buf, InData%DWM_tb, ErrStat2, ErrMsg2, .TRUE. ) ! DWM_tb + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DWM_tb + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DWM_tb + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DWM_tb + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WMC: size of buffers for each call to pack subtype + CALL DWM_Packwake_meandered_center( Re_Buf, Db_Buf, Int_Buf, InData%WMC, ErrStat2, ErrMsg2, .TRUE. ) ! WMC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WMC + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WMC + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WMC + 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 InflowWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 + ReKiBuf(Re_Xferred) = InData%position_y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%position_z + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%velocity_wake_mean + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%shifted_velocity_Aerodyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%U_velocity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%V_velocity + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nforce) ) 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%Nforce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nforce,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nforce,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nforce,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Nforce,2), UBOUND(InData%Nforce,2) + DO i1 = LBOUND(InData%Nforce,1), UBOUND(InData%Nforce,1) + ReKiBuf(Re_Xferred) = InData%Nforce(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%blade_dr) ) 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%blade_dr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%blade_dr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%blade_dr,1), UBOUND(InData%blade_dr,1) + ReKiBuf(Re_Xferred) = InData%blade_dr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%NacYaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_original + Re_Xferred = Re_Xferred + 1 + CALL DWM_Packturbine_average_velocity_data( Re_Buf, Db_Buf, Int_Buf, InData%TAVD, ErrStat2, ErrMsg2, OnlySize ) ! TAVD + 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 DWM_Packcvsd( Re_Buf, Db_Buf, Int_Buf, InData%CalVelScale_data, ErrStat2, ErrMsg2, OnlySize ) ! CalVelScale_data + 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 DWM_Packmeanderdata( Re_Buf, Db_Buf, Int_Buf, InData%meandering_data, ErrStat2, ErrMsg2, OnlySize ) ! meandering_data + 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 DWM_Packweimethod( Re_Buf, Db_Buf, Int_Buf, InData%weighting_method, ErrStat2, ErrMsg2, OnlySize ) ! weighting_method + 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 DWM_Packtidownstream( Re_Buf, Db_Buf, Int_Buf, InData%TI_downstream_data, ErrStat2, ErrMsg2, OnlySize ) ! TI_downstream_data + 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 DWM_Packturbkaimal( Re_Buf, Db_Buf, Int_Buf, InData%Turbulence_KS, ErrStat2, ErrMsg2, OnlySize ) ! Turbulence_KS + 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 DWM_Packshinozuka( Re_Buf, Db_Buf, Int_Buf, InData%shinozuka_data, ErrStat2, ErrMsg2, OnlySize ) ! shinozuka_data + 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 DWM_Packsmooth_out_wake_data( Re_Buf, Db_Buf, Int_Buf, InData%SmoothOut, ErrStat2, ErrMsg2, OnlySize ) ! SmoothOut + 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 DWM_Packswsv( Re_Buf, Db_Buf, Int_Buf, InData%smooth_wake_shifted_velocity_data, ErrStat2, ErrMsg2, OnlySize ) ! smooth_wake_shifted_velocity_data + 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 DWM_Packwake_deficit_data( Re_Buf, Db_Buf, Int_Buf, InData%DWDD, ErrStat2, ErrMsg2, OnlySize ) ! DWDD + 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 + ReKiBuf(Re_Xferred) = InData%ct_tilde + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FAST_Time + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SDtimestep + Int_Xferred = Int_Xferred + 1 + CALL DWM_Packturbine_blade( Re_Buf, Db_Buf, Int_Buf, InData%DWM_tb, ErrStat2, ErrMsg2, OnlySize ) ! DWM_tb + 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 DWM_Packwake_meandered_center( Re_Buf, Db_Buf, Int_Buf, InData%WMC, ErrStat2, ErrMsg2, OnlySize ) ! WMC + 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 DWM_PackMisc + + SUBROUTINE DWM_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(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_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 + 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_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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%position_y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%position_z = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%velocity_wake_mean = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%shifted_velocity_Aerodyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%U_velocity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%V_velocity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nforce 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%Nforce)) DEALLOCATE(OutData%Nforce) + ALLOCATE(OutData%Nforce(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nforce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Nforce,2), UBOUND(OutData%Nforce,2) + DO i1 = LBOUND(OutData%Nforce,1), UBOUND(OutData%Nforce,1) + OutData%Nforce(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! blade_dr 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%blade_dr)) DEALLOCATE(OutData%blade_dr) + ALLOCATE(OutData%blade_dr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%blade_dr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%blade_dr,1), UBOUND(OutData%blade_dr,1) + OutData%blade_dr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NacYaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_original = 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 DWM_Unpackturbine_average_velocity_data( Re_Buf, Db_Buf, Int_Buf, OutData%TAVD, ErrStat2, ErrMsg2 ) ! TAVD + 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 DWM_Unpackcvsd( Re_Buf, Db_Buf, Int_Buf, OutData%CalVelScale_data, ErrStat2, ErrMsg2 ) ! CalVelScale_data + 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 DWM_Unpackmeanderdata( Re_Buf, Db_Buf, Int_Buf, OutData%meandering_data, ErrStat2, ErrMsg2 ) ! meandering_data + 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 DWM_Unpackweimethod( Re_Buf, Db_Buf, Int_Buf, OutData%weighting_method, ErrStat2, ErrMsg2 ) ! weighting_method + 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 DWM_Unpacktidownstream( Re_Buf, Db_Buf, Int_Buf, OutData%TI_downstream_data, ErrStat2, ErrMsg2 ) ! TI_downstream_data + 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 DWM_Unpackturbkaimal( Re_Buf, Db_Buf, Int_Buf, OutData%Turbulence_KS, ErrStat2, ErrMsg2 ) ! Turbulence_KS + 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 DWM_Unpackshinozuka( Re_Buf, Db_Buf, Int_Buf, OutData%shinozuka_data, ErrStat2, ErrMsg2 ) ! shinozuka_data + 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 DWM_Unpacksmooth_out_wake_data( Re_Buf, Db_Buf, Int_Buf, OutData%SmoothOut, ErrStat2, ErrMsg2 ) ! SmoothOut + 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 DWM_Unpackswsv( Re_Buf, Db_Buf, Int_Buf, OutData%smooth_wake_shifted_velocity_data, ErrStat2, ErrMsg2 ) ! smooth_wake_shifted_velocity_data + 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 DWM_Unpackwake_deficit_data( Re_Buf, Db_Buf, Int_Buf, OutData%DWDD, ErrStat2, ErrMsg2 ) ! DWDD + 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%ct_tilde = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FAST_Time = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SDtimestep = 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 DWM_Unpackturbine_blade( Re_Buf, Db_Buf, Int_Buf, OutData%DWM_tb, ErrStat2, ErrMsg2 ) ! DWM_tb + 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 DWM_Unpackwake_meandered_center( Re_Buf, Db_Buf, Int_Buf, OutData%WMC, ErrStat2, ErrMsg2 ) ! WMC + 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 DWM_UnPackMisc + + SUBROUTINE DWM_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_InputType), INTENT(IN) :: SrcInputData + TYPE(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_Copyread_upwind_result( SrcInputData%Upwind_result, DstInputData%Upwind_result, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyInput( SrcInputData%IfW, DstInputData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyInput + + SUBROUTINE DWM_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(DWM_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL DWM_Destroyread_upwind_result( InputData%Upwind_result, ErrStat, ErrMsg ) + CALL InflowWind_DestroyInput( InputData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyInput + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Upwind_result: size of buffers for each call to pack subtype + CALL DWM_Packread_upwind_result( Re_Buf, Db_Buf, Int_Buf, InData%Upwind_result, ErrStat2, ErrMsg2, .TRUE. ) ! Upwind_result + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Upwind_result + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Upwind_result + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Upwind_result + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 DWM_Packread_upwind_result( Re_Buf, Db_Buf, Int_Buf, InData%Upwind_result, ErrStat2, ErrMsg2, OnlySize ) ! Upwind_result + 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%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackInput + + SUBROUTINE DWM_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(DWM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_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 + 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 DWM_Unpackread_upwind_result( Re_Buf, Db_Buf, Int_Buf, OutData%Upwind_result, ErrStat2, ErrMsg2 ) ! Upwind_result + 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 InflowWind_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackInput + + SUBROUTINE DWM_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_OutputType), INTENT(IN) :: SrcOutputData + TYPE(DWM_OutputType), INTENT(INOUT) :: DstOutputData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%turbine_thrust_force)) THEN + i1_l = LBOUND(SrcOutputData%turbine_thrust_force,1) + i1_u = UBOUND(SrcOutputData%turbine_thrust_force,1) + IF (.NOT. ALLOCATED(DstOutputData%turbine_thrust_force)) THEN + ALLOCATE(DstOutputData%turbine_thrust_force(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%turbine_thrust_force.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%turbine_thrust_force = SrcOutputData%turbine_thrust_force +ENDIF +IF (ALLOCATED(SrcOutputData%induction_factor)) THEN + i1_l = LBOUND(SrcOutputData%induction_factor,1) + i1_u = UBOUND(SrcOutputData%induction_factor,1) + IF (.NOT. ALLOCATED(DstOutputData%induction_factor)) THEN + ALLOCATE(DstOutputData%induction_factor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%induction_factor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%induction_factor = SrcOutputData%induction_factor +ENDIF +IF (ALLOCATED(SrcOutputData%r_initial)) THEN + i1_l = LBOUND(SrcOutputData%r_initial,1) + i1_u = UBOUND(SrcOutputData%r_initial,1) + IF (.NOT. ALLOCATED(DstOutputData%r_initial)) THEN + ALLOCATE(DstOutputData%r_initial(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%r_initial.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%r_initial = SrcOutputData%r_initial +ENDIF +IF (ALLOCATED(SrcOutputData%U_initial)) THEN + i1_l = LBOUND(SrcOutputData%U_initial,1) + i1_u = UBOUND(SrcOutputData%U_initial,1) + IF (.NOT. ALLOCATED(DstOutputData%U_initial)) THEN + ALLOCATE(DstOutputData%U_initial(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%U_initial.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%U_initial = SrcOutputData%U_initial +ENDIF +IF (ALLOCATED(SrcOutputData%Mean_FFWS_array)) THEN + i1_l = LBOUND(SrcOutputData%Mean_FFWS_array,1) + i1_u = UBOUND(SrcOutputData%Mean_FFWS_array,1) + IF (.NOT. ALLOCATED(DstOutputData%Mean_FFWS_array)) THEN + ALLOCATE(DstOutputData%Mean_FFWS_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Mean_FFWS_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%Mean_FFWS_array = SrcOutputData%Mean_FFWS_array +ENDIF + DstOutputData%Mean_FFWS = SrcOutputData%Mean_FFWS + DstOutputData%TI = SrcOutputData%TI + DstOutputData%TI_downstream = SrcOutputData%TI_downstream +IF (ALLOCATED(SrcOutputData%wake_u)) THEN + i1_l = LBOUND(SrcOutputData%wake_u,1) + i1_u = UBOUND(SrcOutputData%wake_u,1) + i2_l = LBOUND(SrcOutputData%wake_u,2) + i2_u = UBOUND(SrcOutputData%wake_u,2) + IF (.NOT. ALLOCATED(DstOutputData%wake_u)) THEN + ALLOCATE(DstOutputData%wake_u(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%wake_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%wake_u = SrcOutputData%wake_u +ENDIF +IF (ALLOCATED(SrcOutputData%wake_position)) THEN + i1_l = LBOUND(SrcOutputData%wake_position,1) + i1_u = UBOUND(SrcOutputData%wake_position,1) + i2_l = LBOUND(SrcOutputData%wake_position,2) + i2_u = UBOUND(SrcOutputData%wake_position,2) + i3_l = LBOUND(SrcOutputData%wake_position,3) + i3_u = UBOUND(SrcOutputData%wake_position,3) + IF (.NOT. ALLOCATED(DstOutputData%wake_position)) THEN + ALLOCATE(DstOutputData%wake_position(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%wake_position.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%wake_position = SrcOutputData%wake_position +ENDIF +IF (ALLOCATED(SrcOutputData%smoothed_velocity_array)) THEN + i1_l = LBOUND(SrcOutputData%smoothed_velocity_array,1) + i1_u = UBOUND(SrcOutputData%smoothed_velocity_array,1) + i2_l = LBOUND(SrcOutputData%smoothed_velocity_array,2) + i2_u = UBOUND(SrcOutputData%smoothed_velocity_array,2) + IF (.NOT. ALLOCATED(DstOutputData%smoothed_velocity_array)) THEN + ALLOCATE(DstOutputData%smoothed_velocity_array(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%smoothed_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%smoothed_velocity_array = SrcOutputData%smoothed_velocity_array +ENDIF + DstOutputData%AtmUscale = SrcOutputData%AtmUscale + DstOutputData%du_dz_ABL = SrcOutputData%du_dz_ABL + DstOutputData%total_SDgenpwr = SrcOutputData%total_SDgenpwr + DstOutputData%mean_SDgenpwr = SrcOutputData%mean_SDgenpwr + DstOutputData%avg_ct = SrcOutputData%avg_ct + CALL InflowWind_CopyOutput( SrcOutputData%IfW, DstOutputData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyOutput + + SUBROUTINE DWM_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(DWM_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%turbine_thrust_force)) THEN + DEALLOCATE(OutputData%turbine_thrust_force) +ENDIF +IF (ALLOCATED(OutputData%induction_factor)) THEN + DEALLOCATE(OutputData%induction_factor) +ENDIF +IF (ALLOCATED(OutputData%r_initial)) THEN + DEALLOCATE(OutputData%r_initial) +ENDIF +IF (ALLOCATED(OutputData%U_initial)) THEN + DEALLOCATE(OutputData%U_initial) +ENDIF +IF (ALLOCATED(OutputData%Mean_FFWS_array)) THEN + DEALLOCATE(OutputData%Mean_FFWS_array) +ENDIF +IF (ALLOCATED(OutputData%wake_u)) THEN + DEALLOCATE(OutputData%wake_u) +ENDIF +IF (ALLOCATED(OutputData%wake_position)) THEN + DEALLOCATE(OutputData%wake_position) +ENDIF +IF (ALLOCATED(OutputData%smoothed_velocity_array)) THEN + DEALLOCATE(OutputData%smoothed_velocity_array) +ENDIF + CALL InflowWind_DestroyOutput( OutputData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyOutput + + SUBROUTINE DWM_PackOutput( 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(DWM_OutputType), 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 = 'DWM_PackOutput' + ! 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 ! turbine_thrust_force allocated yes/no + IF ( ALLOCATED(InData%turbine_thrust_force) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! turbine_thrust_force upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%turbine_thrust_force) ! turbine_thrust_force + END IF + Int_BufSz = Int_BufSz + 1 ! induction_factor allocated yes/no + IF ( ALLOCATED(InData%induction_factor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! induction_factor upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%induction_factor) ! induction_factor + END IF + Int_BufSz = Int_BufSz + 1 ! r_initial allocated yes/no + IF ( ALLOCATED(InData%r_initial) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! r_initial upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r_initial) ! r_initial + END IF + Int_BufSz = Int_BufSz + 1 ! U_initial allocated yes/no + IF ( ALLOCATED(InData%U_initial) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_initial upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_initial) ! U_initial + END IF + Int_BufSz = Int_BufSz + 1 ! Mean_FFWS_array allocated yes/no + IF ( ALLOCATED(InData%Mean_FFWS_array) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Mean_FFWS_array upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Mean_FFWS_array) ! Mean_FFWS_array + END IF + Re_BufSz = Re_BufSz + 1 ! Mean_FFWS + Re_BufSz = Re_BufSz + 1 ! TI + Re_BufSz = Re_BufSz + 1 ! TI_downstream + Int_BufSz = Int_BufSz + 1 ! wake_u allocated yes/no + IF ( ALLOCATED(InData%wake_u) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! wake_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%wake_u) ! wake_u + END IF + Int_BufSz = Int_BufSz + 1 ! wake_position allocated yes/no + IF ( ALLOCATED(InData%wake_position) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! wake_position upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%wake_position) ! wake_position + END IF + Int_BufSz = Int_BufSz + 1 ! smoothed_velocity_array allocated yes/no + IF ( ALLOCATED(InData%smoothed_velocity_array) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! smoothed_velocity_array upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%smoothed_velocity_array) ! smoothed_velocity_array + END IF + Re_BufSz = Re_BufSz + 1 ! AtmUscale + Re_BufSz = Re_BufSz + 1 ! du_dz_ABL + Re_BufSz = Re_BufSz + 1 ! total_SDgenpwr + Re_BufSz = Re_BufSz + 1 ! mean_SDgenpwr + Re_BufSz = Re_BufSz + 1 ! avg_ct + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + IF ( .NOT. ALLOCATED(InData%turbine_thrust_force) ) 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%turbine_thrust_force,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%turbine_thrust_force,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%turbine_thrust_force,1), UBOUND(InData%turbine_thrust_force,1) + ReKiBuf(Re_Xferred) = InData%turbine_thrust_force(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%induction_factor) ) 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%induction_factor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%induction_factor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%induction_factor,1), UBOUND(InData%induction_factor,1) + ReKiBuf(Re_Xferred) = InData%induction_factor(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%r_initial) ) 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%r_initial,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r_initial,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%r_initial,1), UBOUND(InData%r_initial,1) + ReKiBuf(Re_Xferred) = InData%r_initial(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%U_initial) ) 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%U_initial,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_initial,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%U_initial,1), UBOUND(InData%U_initial,1) + ReKiBuf(Re_Xferred) = InData%U_initial(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Mean_FFWS_array) ) 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%Mean_FFWS_array,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mean_FFWS_array,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Mean_FFWS_array,1), UBOUND(InData%Mean_FFWS_array,1) + ReKiBuf(Re_Xferred) = InData%Mean_FFWS_array(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Mean_FFWS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TI_downstream + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%wake_u) ) 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%wake_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_u,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%wake_u,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_u,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%wake_u,2), UBOUND(InData%wake_u,2) + DO i1 = LBOUND(InData%wake_u,1), UBOUND(InData%wake_u,1) + ReKiBuf(Re_Xferred) = InData%wake_u(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%wake_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%wake_position,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_position,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%wake_position,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_position,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%wake_position,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wake_position,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%wake_position,3), UBOUND(InData%wake_position,3) + DO i2 = LBOUND(InData%wake_position,2), UBOUND(InData%wake_position,2) + DO i1 = LBOUND(InData%wake_position,1), UBOUND(InData%wake_position,1) + ReKiBuf(Re_Xferred) = InData%wake_position(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%smoothed_velocity_array) ) 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%smoothed_velocity_array,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%smoothed_velocity_array,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%smoothed_velocity_array,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%smoothed_velocity_array,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%smoothed_velocity_array,2), UBOUND(InData%smoothed_velocity_array,2) + DO i1 = LBOUND(InData%smoothed_velocity_array,1), UBOUND(InData%smoothed_velocity_array,1) + ReKiBuf(Re_Xferred) = InData%smoothed_velocity_array(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AtmUscale + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%du_dz_ABL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%total_SDgenpwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%mean_SDgenpwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%avg_ct + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackOutput + + SUBROUTINE DWM_UnPackOutput( 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(DWM_OutputType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_UnPackOutput' + ! 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 ! turbine_thrust_force 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%turbine_thrust_force)) DEALLOCATE(OutData%turbine_thrust_force) + ALLOCATE(OutData%turbine_thrust_force(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%turbine_thrust_force.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%turbine_thrust_force,1), UBOUND(OutData%turbine_thrust_force,1) + OutData%turbine_thrust_force(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! induction_factor 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%induction_factor)) DEALLOCATE(OutData%induction_factor) + ALLOCATE(OutData%induction_factor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%induction_factor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%induction_factor,1), UBOUND(OutData%induction_factor,1) + OutData%induction_factor(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r_initial 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%r_initial)) DEALLOCATE(OutData%r_initial) + ALLOCATE(OutData%r_initial(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%r_initial.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%r_initial,1), UBOUND(OutData%r_initial,1) + OutData%r_initial(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_initial 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%U_initial)) DEALLOCATE(OutData%U_initial) + ALLOCATE(OutData%U_initial(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_initial.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%U_initial,1), UBOUND(OutData%U_initial,1) + OutData%U_initial(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Mean_FFWS_array 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%Mean_FFWS_array)) DEALLOCATE(OutData%Mean_FFWS_array) + ALLOCATE(OutData%Mean_FFWS_array(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Mean_FFWS_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Mean_FFWS_array,1), UBOUND(OutData%Mean_FFWS_array,1) + OutData%Mean_FFWS_array(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Mean_FFWS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TI_downstream = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! wake_u 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%wake_u)) DEALLOCATE(OutData%wake_u) + ALLOCATE(OutData%wake_u(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%wake_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%wake_u,2), UBOUND(OutData%wake_u,2) + DO i1 = LBOUND(OutData%wake_u,1), UBOUND(OutData%wake_u,1) + OutData%wake_u(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! wake_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 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%wake_position)) DEALLOCATE(OutData%wake_position) + ALLOCATE(OutData%wake_position(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%wake_position.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%wake_position,3), UBOUND(OutData%wake_position,3) + DO i2 = LBOUND(OutData%wake_position,2), UBOUND(OutData%wake_position,2) + DO i1 = LBOUND(OutData%wake_position,1), UBOUND(OutData%wake_position,1) + OutData%wake_position(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! smoothed_velocity_array 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%smoothed_velocity_array)) DEALLOCATE(OutData%smoothed_velocity_array) + ALLOCATE(OutData%smoothed_velocity_array(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%smoothed_velocity_array.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%smoothed_velocity_array,2), UBOUND(OutData%smoothed_velocity_array,2) + DO i1 = LBOUND(OutData%smoothed_velocity_array,1), UBOUND(OutData%smoothed_velocity_array,1) + OutData%smoothed_velocity_array(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%AtmUscale = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%du_dz_ABL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%total_SDgenpwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%mean_SDgenpwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%avg_ct = 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_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackOutput + + SUBROUTINE DWM_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(DWM_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 = 'DWM_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%dummy = SrcContStateData%dummy + CALL InflowWind_CopyContState( SrcContStateData%IfW, DstContStateData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyContState + + SUBROUTINE DWM_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyContState( ContStateData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyContState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + ReKiBuf(Re_Xferred) = InData%dummy + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackContState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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%dummy = 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_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackContState + + SUBROUTINE DWM_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(DWM_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 = 'DWM_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%dummy = SrcDiscStateData%dummy + CALL InflowWind_CopyDiscState( SrcDiscStateData%IfW, DstDiscStateData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyDiscState + + SUBROUTINE DWM_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyDiscState( DiscStateData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyDiscState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + ReKiBuf(Re_Xferred) = InData%dummy + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackDiscState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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%dummy = 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_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackDiscState + + SUBROUTINE DWM_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(DWM_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 = 'DWM_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%dummy = SrcConstrStateData%dummy + CALL InflowWind_CopyConstrState( SrcConstrStateData%IfW, DstConstrStateData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyConstrState + + SUBROUTINE DWM_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyConstrState( ConstrStateData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyConstrState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + ReKiBuf(Re_Xferred) = InData%dummy + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackConstrState + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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%dummy = 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_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackConstrState + + SUBROUTINE DWM_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(DWM_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 = 'DWM_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%dummy = SrcInitInputData%dummy + CALL InflowWind_CopyInitInput( SrcInitInputData%IfW, DstInitInputData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyInitInput + + SUBROUTINE DWM_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(DWM_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyInitInput( InitInputData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyInitInput + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + Re_BufSz = Re_BufSz + 1 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + ReKiBuf(Re_Xferred) = InData%dummy + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackInitInput + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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%dummy = 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_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackInitInput + + SUBROUTINE DWM_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(DWM_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(DWM_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 = 'DWM_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%dummy = SrcInitOutputData%dummy + CALL InflowWind_CopyInitOutput( SrcInitOutputData%IfW, DstInitOutputData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE DWM_CopyInitOutput + + SUBROUTINE DWM_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(DWM_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL InflowWind_DestroyInitOutput( InitOutputData%IfW, ErrStat, ErrMsg ) + END SUBROUTINE DWM_DestroyInitOutput + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + Re_BufSz = Re_BufSz + 1 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + 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 + + ReKiBuf(Re_Xferred) = InData%dummy + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 DWM_PackInitOutput + + SUBROUTINE DWM_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(DWM_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 = 'DWM_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 + OutData%dummy = 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_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 DWM_UnPackInitOutput + + + SUBROUTINE DWM_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(DWM_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(DWM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL DWM_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL DWM_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL DWM_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE DWM_Input_ExtrapInterp + + + SUBROUTINE DWM_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(DWM_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(DWM_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(DWM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%Upwind_result%upwind_U) .AND. ALLOCATED(u1%Upwind_result%upwind_U)) THEN + DO i2 = LBOUND(u_out%Upwind_result%upwind_U,2),UBOUND(u_out%Upwind_result%upwind_U,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_U,1),UBOUND(u_out%Upwind_result%upwind_U,1) + b = -(u1%Upwind_result%upwind_U(i1,i2) - u2%Upwind_result%upwind_U(i1,i2)) + u_out%Upwind_result%upwind_U(i1,i2) = u1%Upwind_result%upwind_U(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_wakecenter) .AND. ALLOCATED(u1%Upwind_result%upwind_wakecenter)) THEN + DO i4 = LBOUND(u_out%Upwind_result%upwind_wakecenter,4),UBOUND(u_out%Upwind_result%upwind_wakecenter,4) + DO i3 = LBOUND(u_out%Upwind_result%upwind_wakecenter,3),UBOUND(u_out%Upwind_result%upwind_wakecenter,3) + DO i2 = LBOUND(u_out%Upwind_result%upwind_wakecenter,2),UBOUND(u_out%Upwind_result%upwind_wakecenter,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_wakecenter,1),UBOUND(u_out%Upwind_result%upwind_wakecenter,1) + b = -(u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) - u2%Upwind_result%upwind_wakecenter(i1,i2,i3,i4)) + u_out%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) = u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) + b * ScaleFactor + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_meanU) .AND. ALLOCATED(u1%Upwind_result%upwind_meanU)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_meanU,1),UBOUND(u_out%Upwind_result%upwind_meanU,1) + b = -(u1%Upwind_result%upwind_meanU(i1) - u2%Upwind_result%upwind_meanU(i1)) + u_out%Upwind_result%upwind_meanU(i1) = u1%Upwind_result%upwind_meanU(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_TI) .AND. ALLOCATED(u1%Upwind_result%upwind_TI)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_TI,1),UBOUND(u_out%Upwind_result%upwind_TI,1) + b = -(u1%Upwind_result%upwind_TI(i1) - u2%Upwind_result%upwind_TI(i1)) + u_out%Upwind_result%upwind_TI(i1) = u1%Upwind_result%upwind_TI(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_small_TI) .AND. ALLOCATED(u1%Upwind_result%upwind_small_TI)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_small_TI,1),UBOUND(u_out%Upwind_result%upwind_small_TI,1) + b = -(u1%Upwind_result%upwind_small_TI(i1) - u2%Upwind_result%upwind_small_TI(i1)) + u_out%Upwind_result%upwind_small_TI(i1) = u1%Upwind_result%upwind_small_TI(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_smoothWake) .AND. ALLOCATED(u1%Upwind_result%upwind_smoothWake)) THEN + DO i2 = LBOUND(u_out%Upwind_result%upwind_smoothWake,2),UBOUND(u_out%Upwind_result%upwind_smoothWake,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_smoothWake,1),UBOUND(u_out%Upwind_result%upwind_smoothWake,1) + b = -(u1%Upwind_result%upwind_smoothWake(i1,i2) - u2%Upwind_result%upwind_smoothWake(i1,i2)) + u_out%Upwind_result%upwind_smoothWake(i1,i2) = u1%Upwind_result%upwind_smoothWake(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%velocity_aerodyn) .AND. ALLOCATED(u1%Upwind_result%velocity_aerodyn)) THEN + DO i1 = LBOUND(u_out%Upwind_result%velocity_aerodyn,1),UBOUND(u_out%Upwind_result%velocity_aerodyn,1) + b = -(u1%Upwind_result%velocity_aerodyn(i1) - u2%Upwind_result%velocity_aerodyn(i1)) + u_out%Upwind_result%velocity_aerodyn(i1) = u1%Upwind_result%velocity_aerodyn(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%TI_downstream) .AND. ALLOCATED(u1%Upwind_result%TI_downstream)) THEN + DO i1 = LBOUND(u_out%Upwind_result%TI_downstream,1),UBOUND(u_out%Upwind_result%TI_downstream,1) + b = -(u1%Upwind_result%TI_downstream(i1) - u2%Upwind_result%TI_downstream(i1)) + u_out%Upwind_result%TI_downstream(i1) = u1%Upwind_result%TI_downstream(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%small_scale_TI_downstream) .AND. ALLOCATED(u1%Upwind_result%small_scale_TI_downstream)) THEN + DO i1 = LBOUND(u_out%Upwind_result%small_scale_TI_downstream,1),UBOUND(u_out%Upwind_result%small_scale_TI_downstream,1) + b = -(u1%Upwind_result%small_scale_TI_downstream(i1) - u2%Upwind_result%small_scale_TI_downstream(i1)) + u_out%Upwind_result%small_scale_TI_downstream(i1) = u1%Upwind_result%small_scale_TI_downstream(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%smoothed_velocity_array) .AND. ALLOCATED(u1%Upwind_result%smoothed_velocity_array)) THEN + DO i2 = LBOUND(u_out%Upwind_result%smoothed_velocity_array,2),UBOUND(u_out%Upwind_result%smoothed_velocity_array,2) + DO i1 = LBOUND(u_out%Upwind_result%smoothed_velocity_array,1),UBOUND(u_out%Upwind_result%smoothed_velocity_array,1) + b = -(u1%Upwind_result%smoothed_velocity_array(i1,i2) - u2%Upwind_result%smoothed_velocity_array(i1,i2)) + u_out%Upwind_result%smoothed_velocity_array(i1,i2) = u1%Upwind_result%smoothed_velocity_array(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%vel_matrix) .AND. ALLOCATED(u1%Upwind_result%vel_matrix)) THEN + DO i3 = LBOUND(u_out%Upwind_result%vel_matrix,3),UBOUND(u_out%Upwind_result%vel_matrix,3) + DO i2 = LBOUND(u_out%Upwind_result%vel_matrix,2),UBOUND(u_out%Upwind_result%vel_matrix,2) + DO i1 = LBOUND(u_out%Upwind_result%vel_matrix,1),UBOUND(u_out%Upwind_result%vel_matrix,1) + b = -(u1%Upwind_result%vel_matrix(i1,i2,i3) - u2%Upwind_result%vel_matrix(i1,i2,i3)) + u_out%Upwind_result%vel_matrix(i1,i2,i3) = u1%Upwind_result%vel_matrix(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated + CALL InflowWind_Input_ExtrapInterp1( u1%IfW, u2%IfW, tin, u_out%IfW, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE DWM_Input_ExtrapInterp1 + + + SUBROUTINE DWM_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(DWM_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(DWM_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(DWM_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(DWM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i04 ! dim4 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + INTEGER :: i4 ! dim4 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%Upwind_result%upwind_U) .AND. ALLOCATED(u1%Upwind_result%upwind_U)) THEN + DO i2 = LBOUND(u_out%Upwind_result%upwind_U,2),UBOUND(u_out%Upwind_result%upwind_U,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_U,1),UBOUND(u_out%Upwind_result%upwind_U,1) + b = (t(3)**2*(u1%Upwind_result%upwind_U(i1,i2) - u2%Upwind_result%upwind_U(i1,i2)) + t(2)**2*(-u1%Upwind_result%upwind_U(i1,i2) + u3%Upwind_result%upwind_U(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_U(i1,i2) + t(3)*u2%Upwind_result%upwind_U(i1,i2) - t(2)*u3%Upwind_result%upwind_U(i1,i2) ) * scaleFactor + u_out%Upwind_result%upwind_U(i1,i2) = u1%Upwind_result%upwind_U(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_wakecenter) .AND. ALLOCATED(u1%Upwind_result%upwind_wakecenter)) THEN + DO i4 = LBOUND(u_out%Upwind_result%upwind_wakecenter,4),UBOUND(u_out%Upwind_result%upwind_wakecenter,4) + DO i3 = LBOUND(u_out%Upwind_result%upwind_wakecenter,3),UBOUND(u_out%Upwind_result%upwind_wakecenter,3) + DO i2 = LBOUND(u_out%Upwind_result%upwind_wakecenter,2),UBOUND(u_out%Upwind_result%upwind_wakecenter,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_wakecenter,1),UBOUND(u_out%Upwind_result%upwind_wakecenter,1) + b = (t(3)**2*(u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) - u2%Upwind_result%upwind_wakecenter(i1,i2,i3,i4)) + t(2)**2*(-u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) + u3%Upwind_result%upwind_wakecenter(i1,i2,i3,i4)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) + t(3)*u2%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) - t(2)*u3%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) ) * scaleFactor + u_out%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) = u1%Upwind_result%upwind_wakecenter(i1,i2,i3,i4) + b + c * t_out + END DO + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_meanU) .AND. ALLOCATED(u1%Upwind_result%upwind_meanU)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_meanU,1),UBOUND(u_out%Upwind_result%upwind_meanU,1) + b = (t(3)**2*(u1%Upwind_result%upwind_meanU(i1) - u2%Upwind_result%upwind_meanU(i1)) + t(2)**2*(-u1%Upwind_result%upwind_meanU(i1) + u3%Upwind_result%upwind_meanU(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_meanU(i1) + t(3)*u2%Upwind_result%upwind_meanU(i1) - t(2)*u3%Upwind_result%upwind_meanU(i1) ) * scaleFactor + u_out%Upwind_result%upwind_meanU(i1) = u1%Upwind_result%upwind_meanU(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_TI) .AND. ALLOCATED(u1%Upwind_result%upwind_TI)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_TI,1),UBOUND(u_out%Upwind_result%upwind_TI,1) + b = (t(3)**2*(u1%Upwind_result%upwind_TI(i1) - u2%Upwind_result%upwind_TI(i1)) + t(2)**2*(-u1%Upwind_result%upwind_TI(i1) + u3%Upwind_result%upwind_TI(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_TI(i1) + t(3)*u2%Upwind_result%upwind_TI(i1) - t(2)*u3%Upwind_result%upwind_TI(i1) ) * scaleFactor + u_out%Upwind_result%upwind_TI(i1) = u1%Upwind_result%upwind_TI(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_small_TI) .AND. ALLOCATED(u1%Upwind_result%upwind_small_TI)) THEN + DO i1 = LBOUND(u_out%Upwind_result%upwind_small_TI,1),UBOUND(u_out%Upwind_result%upwind_small_TI,1) + b = (t(3)**2*(u1%Upwind_result%upwind_small_TI(i1) - u2%Upwind_result%upwind_small_TI(i1)) + t(2)**2*(-u1%Upwind_result%upwind_small_TI(i1) + u3%Upwind_result%upwind_small_TI(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_small_TI(i1) + t(3)*u2%Upwind_result%upwind_small_TI(i1) - t(2)*u3%Upwind_result%upwind_small_TI(i1) ) * scaleFactor + u_out%Upwind_result%upwind_small_TI(i1) = u1%Upwind_result%upwind_small_TI(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%upwind_smoothWake) .AND. ALLOCATED(u1%Upwind_result%upwind_smoothWake)) THEN + DO i2 = LBOUND(u_out%Upwind_result%upwind_smoothWake,2),UBOUND(u_out%Upwind_result%upwind_smoothWake,2) + DO i1 = LBOUND(u_out%Upwind_result%upwind_smoothWake,1),UBOUND(u_out%Upwind_result%upwind_smoothWake,1) + b = (t(3)**2*(u1%Upwind_result%upwind_smoothWake(i1,i2) - u2%Upwind_result%upwind_smoothWake(i1,i2)) + t(2)**2*(-u1%Upwind_result%upwind_smoothWake(i1,i2) + u3%Upwind_result%upwind_smoothWake(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%upwind_smoothWake(i1,i2) + t(3)*u2%Upwind_result%upwind_smoothWake(i1,i2) - t(2)*u3%Upwind_result%upwind_smoothWake(i1,i2) ) * scaleFactor + u_out%Upwind_result%upwind_smoothWake(i1,i2) = u1%Upwind_result%upwind_smoothWake(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%velocity_aerodyn) .AND. ALLOCATED(u1%Upwind_result%velocity_aerodyn)) THEN + DO i1 = LBOUND(u_out%Upwind_result%velocity_aerodyn,1),UBOUND(u_out%Upwind_result%velocity_aerodyn,1) + b = (t(3)**2*(u1%Upwind_result%velocity_aerodyn(i1) - u2%Upwind_result%velocity_aerodyn(i1)) + t(2)**2*(-u1%Upwind_result%velocity_aerodyn(i1) + u3%Upwind_result%velocity_aerodyn(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%velocity_aerodyn(i1) + t(3)*u2%Upwind_result%velocity_aerodyn(i1) - t(2)*u3%Upwind_result%velocity_aerodyn(i1) ) * scaleFactor + u_out%Upwind_result%velocity_aerodyn(i1) = u1%Upwind_result%velocity_aerodyn(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%TI_downstream) .AND. ALLOCATED(u1%Upwind_result%TI_downstream)) THEN + DO i1 = LBOUND(u_out%Upwind_result%TI_downstream,1),UBOUND(u_out%Upwind_result%TI_downstream,1) + b = (t(3)**2*(u1%Upwind_result%TI_downstream(i1) - u2%Upwind_result%TI_downstream(i1)) + t(2)**2*(-u1%Upwind_result%TI_downstream(i1) + u3%Upwind_result%TI_downstream(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%TI_downstream(i1) + t(3)*u2%Upwind_result%TI_downstream(i1) - t(2)*u3%Upwind_result%TI_downstream(i1) ) * scaleFactor + u_out%Upwind_result%TI_downstream(i1) = u1%Upwind_result%TI_downstream(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%small_scale_TI_downstream) .AND. ALLOCATED(u1%Upwind_result%small_scale_TI_downstream)) THEN + DO i1 = LBOUND(u_out%Upwind_result%small_scale_TI_downstream,1),UBOUND(u_out%Upwind_result%small_scale_TI_downstream,1) + b = (t(3)**2*(u1%Upwind_result%small_scale_TI_downstream(i1) - u2%Upwind_result%small_scale_TI_downstream(i1)) + t(2)**2*(-u1%Upwind_result%small_scale_TI_downstream(i1) + u3%Upwind_result%small_scale_TI_downstream(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%small_scale_TI_downstream(i1) + t(3)*u2%Upwind_result%small_scale_TI_downstream(i1) - t(2)*u3%Upwind_result%small_scale_TI_downstream(i1) ) * scaleFactor + u_out%Upwind_result%small_scale_TI_downstream(i1) = u1%Upwind_result%small_scale_TI_downstream(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%smoothed_velocity_array) .AND. ALLOCATED(u1%Upwind_result%smoothed_velocity_array)) THEN + DO i2 = LBOUND(u_out%Upwind_result%smoothed_velocity_array,2),UBOUND(u_out%Upwind_result%smoothed_velocity_array,2) + DO i1 = LBOUND(u_out%Upwind_result%smoothed_velocity_array,1),UBOUND(u_out%Upwind_result%smoothed_velocity_array,1) + b = (t(3)**2*(u1%Upwind_result%smoothed_velocity_array(i1,i2) - u2%Upwind_result%smoothed_velocity_array(i1,i2)) + t(2)**2*(-u1%Upwind_result%smoothed_velocity_array(i1,i2) + u3%Upwind_result%smoothed_velocity_array(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%smoothed_velocity_array(i1,i2) + t(3)*u2%Upwind_result%smoothed_velocity_array(i1,i2) - t(2)*u3%Upwind_result%smoothed_velocity_array(i1,i2) ) * scaleFactor + u_out%Upwind_result%smoothed_velocity_array(i1,i2) = u1%Upwind_result%smoothed_velocity_array(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%Upwind_result%vel_matrix) .AND. ALLOCATED(u1%Upwind_result%vel_matrix)) THEN + DO i3 = LBOUND(u_out%Upwind_result%vel_matrix,3),UBOUND(u_out%Upwind_result%vel_matrix,3) + DO i2 = LBOUND(u_out%Upwind_result%vel_matrix,2),UBOUND(u_out%Upwind_result%vel_matrix,2) + DO i1 = LBOUND(u_out%Upwind_result%vel_matrix,1),UBOUND(u_out%Upwind_result%vel_matrix,1) + b = (t(3)**2*(u1%Upwind_result%vel_matrix(i1,i2,i3) - u2%Upwind_result%vel_matrix(i1,i2,i3)) + t(2)**2*(-u1%Upwind_result%vel_matrix(i1,i2,i3) + u3%Upwind_result%vel_matrix(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*u1%Upwind_result%vel_matrix(i1,i2,i3) + t(3)*u2%Upwind_result%vel_matrix(i1,i2,i3) - t(2)*u3%Upwind_result%vel_matrix(i1,i2,i3) ) * scaleFactor + u_out%Upwind_result%vel_matrix(i1,i2,i3) = u1%Upwind_result%vel_matrix(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated + CALL InflowWind_Input_ExtrapInterp2( u1%IfW, u2%IfW, u3%IfW, tin, u_out%IfW, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE DWM_Input_ExtrapInterp2 + + + SUBROUTINE DWM_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(DWM_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(DWM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL DWM_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL DWM_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL DWM_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE DWM_Output_ExtrapInterp + + + SUBROUTINE DWM_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(DWM_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(DWM_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(DWM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%turbine_thrust_force) .AND. ALLOCATED(y1%turbine_thrust_force)) THEN + DO i1 = LBOUND(y_out%turbine_thrust_force,1),UBOUND(y_out%turbine_thrust_force,1) + b = -(y1%turbine_thrust_force(i1) - y2%turbine_thrust_force(i1)) + y_out%turbine_thrust_force(i1) = y1%turbine_thrust_force(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%induction_factor) .AND. ALLOCATED(y1%induction_factor)) THEN + DO i1 = LBOUND(y_out%induction_factor,1),UBOUND(y_out%induction_factor,1) + b = -(y1%induction_factor(i1) - y2%induction_factor(i1)) + y_out%induction_factor(i1) = y1%induction_factor(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%r_initial) .AND. ALLOCATED(y1%r_initial)) THEN + DO i1 = LBOUND(y_out%r_initial,1),UBOUND(y_out%r_initial,1) + b = -(y1%r_initial(i1) - y2%r_initial(i1)) + y_out%r_initial(i1) = y1%r_initial(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%U_initial) .AND. ALLOCATED(y1%U_initial)) THEN + DO i1 = LBOUND(y_out%U_initial,1),UBOUND(y_out%U_initial,1) + b = -(y1%U_initial(i1) - y2%U_initial(i1)) + y_out%U_initial(i1) = y1%U_initial(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Mean_FFWS_array) .AND. ALLOCATED(y1%Mean_FFWS_array)) THEN + DO i1 = LBOUND(y_out%Mean_FFWS_array,1),UBOUND(y_out%Mean_FFWS_array,1) + b = -(y1%Mean_FFWS_array(i1) - y2%Mean_FFWS_array(i1)) + y_out%Mean_FFWS_array(i1) = y1%Mean_FFWS_array(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + b = -(y1%Mean_FFWS - y2%Mean_FFWS) + y_out%Mean_FFWS = y1%Mean_FFWS + b * ScaleFactor + b = -(y1%TI - y2%TI) + y_out%TI = y1%TI + b * ScaleFactor + b = -(y1%TI_downstream - y2%TI_downstream) + y_out%TI_downstream = y1%TI_downstream + b * ScaleFactor +IF (ALLOCATED(y_out%wake_u) .AND. ALLOCATED(y1%wake_u)) THEN + DO i2 = LBOUND(y_out%wake_u,2),UBOUND(y_out%wake_u,2) + DO i1 = LBOUND(y_out%wake_u,1),UBOUND(y_out%wake_u,1) + b = -(y1%wake_u(i1,i2) - y2%wake_u(i1,i2)) + y_out%wake_u(i1,i2) = y1%wake_u(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%wake_position) .AND. ALLOCATED(y1%wake_position)) THEN + DO i3 = LBOUND(y_out%wake_position,3),UBOUND(y_out%wake_position,3) + DO i2 = LBOUND(y_out%wake_position,2),UBOUND(y_out%wake_position,2) + DO i1 = LBOUND(y_out%wake_position,1),UBOUND(y_out%wake_position,1) + b = -(y1%wake_position(i1,i2,i3) - y2%wake_position(i1,i2,i3)) + y_out%wake_position(i1,i2,i3) = y1%wake_position(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%smoothed_velocity_array) .AND. ALLOCATED(y1%smoothed_velocity_array)) THEN + DO i2 = LBOUND(y_out%smoothed_velocity_array,2),UBOUND(y_out%smoothed_velocity_array,2) + DO i1 = LBOUND(y_out%smoothed_velocity_array,1),UBOUND(y_out%smoothed_velocity_array,1) + b = -(y1%smoothed_velocity_array(i1,i2) - y2%smoothed_velocity_array(i1,i2)) + y_out%smoothed_velocity_array(i1,i2) = y1%smoothed_velocity_array(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + b = -(y1%AtmUscale - y2%AtmUscale) + y_out%AtmUscale = y1%AtmUscale + b * ScaleFactor + b = -(y1%du_dz_ABL - y2%du_dz_ABL) + y_out%du_dz_ABL = y1%du_dz_ABL + b * ScaleFactor + b = -(y1%total_SDgenpwr - y2%total_SDgenpwr) + y_out%total_SDgenpwr = y1%total_SDgenpwr + b * ScaleFactor + b = -(y1%mean_SDgenpwr - y2%mean_SDgenpwr) + y_out%mean_SDgenpwr = y1%mean_SDgenpwr + b * ScaleFactor + b = -(y1%avg_ct - y2%avg_ct) + y_out%avg_ct = y1%avg_ct + b * ScaleFactor + CALL InflowWind_Output_ExtrapInterp1( y1%IfW, y2%IfW, tin, y_out%IfW, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE DWM_Output_ExtrapInterp1 + + + SUBROUTINE DWM_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(DWM_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(DWM_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(DWM_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(DWM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'DWM_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%turbine_thrust_force) .AND. ALLOCATED(y1%turbine_thrust_force)) THEN + DO i1 = LBOUND(y_out%turbine_thrust_force,1),UBOUND(y_out%turbine_thrust_force,1) + b = (t(3)**2*(y1%turbine_thrust_force(i1) - y2%turbine_thrust_force(i1)) + t(2)**2*(-y1%turbine_thrust_force(i1) + y3%turbine_thrust_force(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%turbine_thrust_force(i1) + t(3)*y2%turbine_thrust_force(i1) - t(2)*y3%turbine_thrust_force(i1) ) * scaleFactor + y_out%turbine_thrust_force(i1) = y1%turbine_thrust_force(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%induction_factor) .AND. ALLOCATED(y1%induction_factor)) THEN + DO i1 = LBOUND(y_out%induction_factor,1),UBOUND(y_out%induction_factor,1) + b = (t(3)**2*(y1%induction_factor(i1) - y2%induction_factor(i1)) + t(2)**2*(-y1%induction_factor(i1) + y3%induction_factor(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%induction_factor(i1) + t(3)*y2%induction_factor(i1) - t(2)*y3%induction_factor(i1) ) * scaleFactor + y_out%induction_factor(i1) = y1%induction_factor(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%r_initial) .AND. ALLOCATED(y1%r_initial)) THEN + DO i1 = LBOUND(y_out%r_initial,1),UBOUND(y_out%r_initial,1) + b = (t(3)**2*(y1%r_initial(i1) - y2%r_initial(i1)) + t(2)**2*(-y1%r_initial(i1) + y3%r_initial(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%r_initial(i1) + t(3)*y2%r_initial(i1) - t(2)*y3%r_initial(i1) ) * scaleFactor + y_out%r_initial(i1) = y1%r_initial(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%U_initial) .AND. ALLOCATED(y1%U_initial)) THEN + DO i1 = LBOUND(y_out%U_initial,1),UBOUND(y_out%U_initial,1) + b = (t(3)**2*(y1%U_initial(i1) - y2%U_initial(i1)) + t(2)**2*(-y1%U_initial(i1) + y3%U_initial(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%U_initial(i1) + t(3)*y2%U_initial(i1) - t(2)*y3%U_initial(i1) ) * scaleFactor + y_out%U_initial(i1) = y1%U_initial(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%Mean_FFWS_array) .AND. ALLOCATED(y1%Mean_FFWS_array)) THEN + DO i1 = LBOUND(y_out%Mean_FFWS_array,1),UBOUND(y_out%Mean_FFWS_array,1) + b = (t(3)**2*(y1%Mean_FFWS_array(i1) - y2%Mean_FFWS_array(i1)) + t(2)**2*(-y1%Mean_FFWS_array(i1) + y3%Mean_FFWS_array(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%Mean_FFWS_array(i1) + t(3)*y2%Mean_FFWS_array(i1) - t(2)*y3%Mean_FFWS_array(i1) ) * scaleFactor + y_out%Mean_FFWS_array(i1) = y1%Mean_FFWS_array(i1) + b + c * t_out + END DO +END IF ! check if allocated + b = (t(3)**2*(y1%Mean_FFWS - y2%Mean_FFWS) + t(2)**2*(-y1%Mean_FFWS + y3%Mean_FFWS))* scaleFactor + c = ( (t(2)-t(3))*y1%Mean_FFWS + t(3)*y2%Mean_FFWS - t(2)*y3%Mean_FFWS ) * scaleFactor + y_out%Mean_FFWS = y1%Mean_FFWS + b + c * t_out + b = (t(3)**2*(y1%TI - y2%TI) + t(2)**2*(-y1%TI + y3%TI))* scaleFactor + c = ( (t(2)-t(3))*y1%TI + t(3)*y2%TI - t(2)*y3%TI ) * scaleFactor + y_out%TI = y1%TI + b + c * t_out + b = (t(3)**2*(y1%TI_downstream - y2%TI_downstream) + t(2)**2*(-y1%TI_downstream + y3%TI_downstream))* scaleFactor + c = ( (t(2)-t(3))*y1%TI_downstream + t(3)*y2%TI_downstream - t(2)*y3%TI_downstream ) * scaleFactor + y_out%TI_downstream = y1%TI_downstream + b + c * t_out +IF (ALLOCATED(y_out%wake_u) .AND. ALLOCATED(y1%wake_u)) THEN + DO i2 = LBOUND(y_out%wake_u,2),UBOUND(y_out%wake_u,2) + DO i1 = LBOUND(y_out%wake_u,1),UBOUND(y_out%wake_u,1) + b = (t(3)**2*(y1%wake_u(i1,i2) - y2%wake_u(i1,i2)) + t(2)**2*(-y1%wake_u(i1,i2) + y3%wake_u(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%wake_u(i1,i2) + t(3)*y2%wake_u(i1,i2) - t(2)*y3%wake_u(i1,i2) ) * scaleFactor + y_out%wake_u(i1,i2) = y1%wake_u(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%wake_position) .AND. ALLOCATED(y1%wake_position)) THEN + DO i3 = LBOUND(y_out%wake_position,3),UBOUND(y_out%wake_position,3) + DO i2 = LBOUND(y_out%wake_position,2),UBOUND(y_out%wake_position,2) + DO i1 = LBOUND(y_out%wake_position,1),UBOUND(y_out%wake_position,1) + b = (t(3)**2*(y1%wake_position(i1,i2,i3) - y2%wake_position(i1,i2,i3)) + t(2)**2*(-y1%wake_position(i1,i2,i3) + y3%wake_position(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*y1%wake_position(i1,i2,i3) + t(3)*y2%wake_position(i1,i2,i3) - t(2)*y3%wake_position(i1,i2,i3) ) * scaleFactor + y_out%wake_position(i1,i2,i3) = y1%wake_position(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%smoothed_velocity_array) .AND. ALLOCATED(y1%smoothed_velocity_array)) THEN + DO i2 = LBOUND(y_out%smoothed_velocity_array,2),UBOUND(y_out%smoothed_velocity_array,2) + DO i1 = LBOUND(y_out%smoothed_velocity_array,1),UBOUND(y_out%smoothed_velocity_array,1) + b = (t(3)**2*(y1%smoothed_velocity_array(i1,i2) - y2%smoothed_velocity_array(i1,i2)) + t(2)**2*(-y1%smoothed_velocity_array(i1,i2) + y3%smoothed_velocity_array(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%smoothed_velocity_array(i1,i2) + t(3)*y2%smoothed_velocity_array(i1,i2) - t(2)*y3%smoothed_velocity_array(i1,i2) ) * scaleFactor + y_out%smoothed_velocity_array(i1,i2) = y1%smoothed_velocity_array(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + b = (t(3)**2*(y1%AtmUscale - y2%AtmUscale) + t(2)**2*(-y1%AtmUscale + y3%AtmUscale))* scaleFactor + c = ( (t(2)-t(3))*y1%AtmUscale + t(3)*y2%AtmUscale - t(2)*y3%AtmUscale ) * scaleFactor + y_out%AtmUscale = y1%AtmUscale + b + c * t_out + b = (t(3)**2*(y1%du_dz_ABL - y2%du_dz_ABL) + t(2)**2*(-y1%du_dz_ABL + y3%du_dz_ABL))* scaleFactor + c = ( (t(2)-t(3))*y1%du_dz_ABL + t(3)*y2%du_dz_ABL - t(2)*y3%du_dz_ABL ) * scaleFactor + y_out%du_dz_ABL = y1%du_dz_ABL + b + c * t_out + b = (t(3)**2*(y1%total_SDgenpwr - y2%total_SDgenpwr) + t(2)**2*(-y1%total_SDgenpwr + y3%total_SDgenpwr))* scaleFactor + c = ( (t(2)-t(3))*y1%total_SDgenpwr + t(3)*y2%total_SDgenpwr - t(2)*y3%total_SDgenpwr ) * scaleFactor + y_out%total_SDgenpwr = y1%total_SDgenpwr + b + c * t_out + b = (t(3)**2*(y1%mean_SDgenpwr - y2%mean_SDgenpwr) + t(2)**2*(-y1%mean_SDgenpwr + y3%mean_SDgenpwr))* scaleFactor + c = ( (t(2)-t(3))*y1%mean_SDgenpwr + t(3)*y2%mean_SDgenpwr - t(2)*y3%mean_SDgenpwr ) * scaleFactor + y_out%mean_SDgenpwr = y1%mean_SDgenpwr + b + c * t_out + b = (t(3)**2*(y1%avg_ct - y2%avg_ct) + t(2)**2*(-y1%avg_ct + y3%avg_ct))* scaleFactor + c = ( (t(2)-t(3))*y1%avg_ct + t(3)*y2%avg_ct - t(2)*y3%avg_ct ) * scaleFactor + y_out%avg_ct = y1%avg_ct + b + c * t_out + CALL InflowWind_Output_ExtrapInterp2( y1%IfW, y2%IfW, y3%IfW, tin, y_out%IfW, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE DWM_Output_ExtrapInterp2 + +END MODULE DWM_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/aerodyn14/src/DWM_Wake_Sub_ver2.f90 b/OpenFAST/modules/aerodyn14/src/DWM_Wake_Sub_ver2.f90 new file mode 100644 index 000000000..b6eaefee0 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM_Wake_Sub_ver2.f90 @@ -0,0 +1,2851 @@ +MODULE DWM_Wake_Sub + + USE DWM_Types + USE NWTC_Library + !USE InflowWind + + IMPLICIT NONE + + ! ..... Public Subroutines ............ + + PUBLIC :: turbine_average_velocity + PUBLIC :: pass_velocity + PUBLIC :: filter_average_induction_factor + PUBLIC :: calculate_mean_u + PUBLIC :: calculate_element_area + PUBLIC :: calculate_induction_factor + PUBLIC :: get_initial_condition + PUBLIC :: calculate_wake + PUBLIC :: create_F1_filter + PUBLIC :: create_F2_filter + PUBLIC :: Gauss + PUBLIC :: shear_correction + PUBLIC :: filter_velocity + PUBLIC :: Get_wake_center + PUBLIC :: smooth_out_wake + PUBLIC :: smooth_wake_shifted_velocity + PUBLIC :: shifted_velocity + PUBLIC :: TI_downstream_total + PUBLIC :: smallscale_TI + PUBLIC :: read_parameter_file + PUBLIC :: read_turbine_position + PUBLIC :: read_upwind_result_file + PUBLIC :: write_result_file +! PUBLIC :: rename_FAST_output + PUBLIC :: min_of_array + PUBLIC :: max_of_array + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!SUBROUTINE CalVelScale(u,v,y,z) +!.................................................................................................................................. +! This routine is to calculat the atmospheric length scale before introducing the TI term (which will be used later) +!.................................................................................................................................. + ! IMPLICIT NONE + + ! TYPE(DWM_OutputType), INTENT(INOUT) :: y + !TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z + + !! Internal variables + !REAL(ReKi) :: u ! atmospheric U velocity + !REAL(ReKi) :: v ! atmospheric V velocity + + !z%CalVelScale_data%counter = z%CalVelScale_data%counter + 1 + + !z%CalVelScale_data%Denominator = (z%CalVelScale_data%Denominator * (z%CalVelScale_data%counter-1) + u*v)/z%CalVelScale_data%counter + !z%CalVelScale_data%Numerator = (z%CalVelScale_data%Numerator * (z%CalVelScale_data%counter-1) + u*v)/z%CalVelScale_data%counter + + !y%AtmUscale = z%CalVelScale_data%Numerator / z%CalVelScale_data%Denominator + +!END SUBROUTINE CalVelScale + + +!!---------------------------------------------------------------------------------------------------------------------------------- +!SUBROUTINE turbine_average_velocity( single_velocity, blade_num, element, y,X,z) +!.................................................................................................................................. +! This routine is called at every time step of the Aerodyn simuilation. +! To calculate the average of the wind speed of a specific blade ring, the outpout is the average_velocity_array +!.................................................................................................................................. + ! IMPLICIT NONE + + ! TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z + !TYPE(DWM_OutputType), INTENT(INOUT) :: y + + ! ! Internal variables + !REAL(ReKi) :: single_velocity + !REAL(ReKi),ALLOCATABLE :: y%Mean_FFWS_array(:) + !INTEGER(IntKi) :: element + !INTEGER(IntKi) :: blade_num + !INTEGER(IntKi) :: I + + !z%turbine_average_velocity_data%time_step_velocity = z%turbine_average_velocity_data%time_step_velocity + 1 + + !IF (z%turbine_average_velocity_data%time_step_velocity == 0) THEN + ! ALLOCATE (y%Mean_FFWS_array (X%ElOut%NumElOut)) + ! ALLOCATE (z%turbine_average_velocity_data%time_step_velocity_array(X%ElOut%NumElOut)) + !y%Mean_FFWS_array = 0 + !z%turbine_average_velocity_data%time_step_velocity_array = 0 + !y%Mean_FFWS_array(element) = single_velocity + !z%turbine_average_velocity_data%time_step_velocity_array(element) = 1 + + !ELSE IF (z%turbine_average_velocity_data%time_step_velocity > 0) THEN + ! DO I = 1,X%ElOut%NumElOut + ! IF ( element == I ) THEN + ! z%turbine_average_velocity_data%time_step_velocity_array(element) = z%turbine_average_velocity_data%time_step_velocity_array(element) + 1 + ! y%Mean_FFWS_array(element) = ( y%Mean_FFWS_array(element)*( (z%turbine_average_velocity_data%time_step_velocity_array(element)-1) )& + ! +single_velocity)/z%turbine_average_velocity_data%time_step_velocity_array(element) + ! IF ( I == X%ElOut%NumElOut .AND. blade_num = X%Blade%NB ) THEN + ! CALL pass_velocity(y%Mean_FFWS_array,Q,X) + ! z%turbine_average_velocity_data%time_step_velocity = -1 + ! IF ( ALLOCATED( y%Mean_FFWS_array )) DEALLOCATE ( y%Mean_FFWS_array ) + ! IF ( ALLOCATED( z%turbine_average_velocity_data%time_step_velocity_array )) DEALLOCATE ( z%turbine_average_velocity_data%time_step_velocity_array ) + !END IF + !END IF + !END DO + !END IF + +!END SUBROUTINE turbine_average_velocity + +!---------------------------------------------------------------------------------- +SUBROUTINE turbine_average_velocity( p, m, single_velocity, blade_num, element, average_velocity_array_local ) +!.................................................................................. +! This routine is called at every time step of the Aerodyn simuilation. +! To calculate the average of the wind speed of a specific blade ring +! the outpout is the average_velocity_array +!.................................................................................. + !USE TAVD, ONLY: m%TAVD%time_step_velocity_array, m%TAVD%time_step_velocity + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p + + REAL(ReKi), INTENT(IN) :: single_velocity + REAL(ReKi),ALLOCATABLE, INTENT(INOUT) :: average_velocity_array_local(:) + INTEGER, intent(in) :: element + INTEGER, intent(in) :: blade_num + INTEGER :: i + !INTEGER :: m%TAVD%time_step_velocity = -1 + !INTEGER,ALLOCATABLE,SAVE :: m%TAVD%time_step_velocity_array(:) ! counter of each section of the blade + + m%TAVD%time_step_velocity = m%TAVD%time_step_velocity +1 + + IF ( m%TAVD%time_step_velocity==0) THEN + ALLOCATE ( average_velocity_array_local(p%ElementNum) ) + ALLOCATE ( m%TAVD%time_step_velocity_array(p%ElementNum) ) + average_velocity_array_local(:) = 0 + m%TAVD%time_step_velocity_array(:) = 0 + average_velocity_array_local(element) = single_velocity + m%TAVD%time_step_velocity_array(element) = 1 + + ELSE IF (m%TAVD%time_step_velocity > 0) THEN + DO i=1,p%ElementNum + IF ( element == i) THEN + m%TAVD%time_step_velocity_array(element) = m%TAVD%time_step_velocity_array(element)+1 + average_velocity_array_local(element) = (average_velocity_array_local(element)*( (m%TAVD%time_step_velocity_array(element)-1) ) + single_velocity) & + / (m%TAVD%time_step_velocity_array(element)) + IF ( element == p%ElementNum ) THEN + IF ( blade_num == p%Bnum) THEN + CALL pass_velocity(p, m, average_velocity_array_local) + m%TAVD%time_step_velocity = -1 + IF (ALLOCATED( average_velocity_array_local )) DEALLOCATE ( average_velocity_array_local ) + IF (ALLOCATED( m%TAVD%time_step_velocity_array )) DEALLOCATE ( m%TAVD%time_step_velocity_array ) + END IF + END IF + END IF + END DO + END IF + + +END SUBROUTINE turbine_average_velocity + +!!---------------------------------------------------------------------------------------------------------------------------------- +!SUBROUTINE pass_velocity(array_velocity,z,X) +!.................................................................................................................................. +!.................................................................................................................................. + ! IMPLICIT NONE + !TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z + + ! ! Internal variables + !REAL(ReKi),ALLOCATEBLE :: array_velocity(:) + + + !z%turbine_average_velocity_data%time_step_pass_velocity = z%turbine_average_velocity_data%time_step_pass_velocity+1 + + !IF( z%turbine_average_velocity_data%time_step_pass_velocity==0 ) THEN + ! ALLOCATE (z%turbine_average_velocity_data%average_velocity_array_temp(X%ElOut%NumElOut)) + ! z%turbine_average_velocity_data%average_velocity_array_temp(:) = array_velocity(:) + !ELSE IF( z%turbine_average_velocity_data%time_step_pass_velocity>0 ) THEN + ! z%turbine_average_velocity_data%average_velocity_array_temp(:) = array_velocity(:) + !END IF + +!END SUBROUTINE pass_velocity + +!---------------------------------------------------------------------------------- +SUBROUTINE pass_velocity(p, m, array_velocity) +!.................................................................................. +! +! +! +!.................................................................................. + !USE TAVD, ONLY: m%TAVD%average_velocity_array_temp, m%TAVD%time_step_pass_velocity + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + + + REAL(ReKi) :: array_velocity(p%ElementNum) + !INTEGER,SAVE :: m%TAVD%time_step_pass_velocity = -1 + + m%TAVD%time_step_pass_velocity = m%TAVD%time_step_pass_velocity+1 + + IF (m%TAVD%time_step_pass_velocity==0) THEN + ALLOCATE (m%TAVD%average_velocity_array_temp(p%ElementNum)) + m%TAVD%average_velocity_array_temp(:) = array_velocity(:) + ELSE IF(m%TAVD%time_step_pass_velocity>0) THEN + m%TAVD%average_velocity_array_temp(:) = array_velocity(:) + END IF + +END SUBROUTINE pass_velocity +!!---------------------------------------------------------------------------------------------------------------------------------- +!SUBROUTINE filter_average_induction_factor( X, z, y ) +!.................................................................................................................................. +! This routine is called at every time step of the Aerodyn simuilation. +! The output of the subroutine is induction factor at this time step +! and the average induction factor through all the time steps which have been simulated +!.................................................................................................................................. + ! IMPLICIT NONE + ! TYPE(DWM_OutputType), INTENT(INOUT) :: y + ! TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z + + ! ! Internal variables + !REAL(ReKi) :: thrust_coefficient ( X%Element%NELM ) + !REAL(ReKi) :: average_induction_factor ( X%Element%NELM ) + !REAL(ReKi) :: induction_factor_local_temp ( X%Element%NELM ) + + + !z%turbine_average_velocity_data%time_step_force = z%turbine_average_velocity_data%time_step_force +1 + + + !IF ( z%turbine_average_velocity_data%time_step_force==0) THEN + ! ALLOCATE (y%induction_factor ( X%Element%NELM )) + ! ALLOCATE (z%turbine_average_velocity_data%average_velocity_array ( X%Element%NELM )) + !ALLOCATE (y%turbine_thrust_force (X%Element%NELM )) + !ALLOCATE (z%turbine_average_velocity_data%swept_area (X%Element%NELM )) + !y%turbine_thrust_force (:) = X%Blade%NB * X%Element%DFNSAV(:) + !CALL calculate_element_area ( X%Blade%R, X%Element%NElm, X%Element%RELM(:), z%turbine_average_velocity_data%swept_area ) + !CALL calculate_induction_factor ( y%turbine_thrust_force , z%turbine_average_velocity_data%swept_area , X%Element%NELM, & + ! z%turbine_average_velocity_data%average_velocity_array_temp, induction_factor_local_temp ) + !y%induction_factor = induction_factor_local_temp + !z%turbine_average_velocity_data%average_velocity_array = z%turbine_average_velocity_data%average_velocity_array_temp + !ELSE IF ( z%turbine_average_velocity_data%time_step_force>0) THEN + ! y%turbine_thrust_force (:) = X%Blade%NB * X%Element%DFNSAV(:) + ! CALL calculate_induction_factor ( y%turbine_thrust_force , z%turbine_average_velocity_data%swept_area , X%Element%NELM, & + ! z%turbine_average_velocity_data%average_velocity_array_temp, induction_factor_local_temp ) + !y%induction_factor = ( y%induction_factor(:) * z%turbine_average_velocity_data%time_step_force + induction_factor_local_temp(:) ) & + ! / ( z%turbine_average_velocity_data%time_step_force+1 ) + !z%turbine_average_velocity_data%average_velocity_array = ( z%turbine_average_velocity_data%average_velocity_array(:) * & + ! z%turbine_average_velocity_data%time_step_force + z%turbine_average_velocity_data%average_velocity_array_temp(:) ) & + ! / ( z%turbine_average_velocity_data%time_step_force+1 ) + !END IF + +!END SUBROUTINE filter_average_induction_factor + +!---------------------------------------------------------------------------------- +SUBROUTINE filter_average_induction_factor( m, p, y, thrust_force, num_of_element, dr_blade) +!.................................................................................. +! This routine is called at every time step of the Aerodyn simuilation. +! The output of the subroutine is induction factor at this time step +! and the average induction factor through all the time steps which have been simulated +!.................................................................................. + !USE TAVD, ONLY: m%TAVD%time_step_force, m%TAVD%swept_area, m%TAVD%average_velocity_array, m%TAVD%average_velocity_array_temp + !USE DWN_OutputType, ONLY: m%induction_factor, m%turbine_thrust_force + !USE Blade, ONLY: R + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + + INTEGER, INTENT(IN) :: num_of_element ! The number of the nodes in the blade + REAL(ReKi), INTENT(IN) :: thrust_force ( num_of_element,p%BNum ) ! Thrust force at each node + !INTEGER, SAVE :: m%TAVD%time_step_force = -1 ! The time step (save attribute) of the FAST simulation + REAL(ReKi) :: thrust_coefficient ( num_of_element ) + REAL(ReKi) :: average_induction_factor ( num_of_element ) + REAL(ReKi) :: induction_factor_local_temp ( num_of_element ) + INTEGER :: I,J + REAL(ReKi), INTENT(IN) :: dr_blade ( num_of_element ) + + + m%TAVD%time_step_force = m%TAVD%time_step_force +1 + + + IF ( m%TAVD%time_step_force==0) THEN + ALLOCATE (y%induction_factor ( num_of_element )) + ALLOCATE (m%TAVD%average_velocity_array ( num_of_element )) + ALLOCATE (y%turbine_thrust_force (num_of_element )) + ALLOCATE (m%TAVD%swept_area (num_of_element )) + + y%turbine_thrust_force = 0 + DO I = 1,num_of_element + DO J = 1,p%BNum + y%turbine_thrust_force (I) = y%turbine_thrust_force (I) + thrust_force(I,J) + END DO + END DO + + DO I = 1,num_of_element + y%turbine_thrust_force (I) = y%turbine_thrust_force(I) !* dr_blade(I) ! integrate dFn through blade + END DO + + CALL calculate_element_area ( p%RotorR, p%ElementNum, p%ElementRad(:), m%TAVD%swept_area ) + CALL calculate_induction_factor ( p, y%turbine_thrust_force , m%TAVD%swept_area , num_of_element, m%TAVD%average_velocity_array_temp, induction_factor_local_temp ) + y%induction_factor = induction_factor_local_temp + m%TAVD%average_velocity_array = m%TAVD%average_velocity_array_temp + + ELSE IF ( m%TAVD%time_step_force>0) THEN + + y%turbine_thrust_force = 0 + DO J = 1,p%BNum + DO I = 1,num_of_element + y%turbine_thrust_force (I) = y%turbine_thrust_force (I) + thrust_force(I,J) + END DO + END DO + + DO I = 1,num_of_element + y%turbine_thrust_force (I) = y%turbine_thrust_force(I) !* dr_blade(I) ! integrate dFn through blade + END DO + + CALL calculate_induction_factor ( p, y%turbine_thrust_force , m%TAVD%swept_area , num_of_element, m%TAVD%average_velocity_array_temp, induction_factor_local_temp ) + y%induction_factor = ( y%induction_factor(:) * m%TAVD%time_step_force + induction_factor_local_temp(:) ) / ( m%TAVD%time_step_force+1 ) + m%TAVD%average_velocity_array = ( m%TAVD%average_velocity_array(:) * m%TAVD%time_step_force + m%TAVD%average_velocity_array_temp(:) ) / ( m%TAVD%time_step_force+1 ) + END IF + + !print*, y%induction_factor(40), induction_factor_local_temp(40) + +END SUBROUTINE filter_average_induction_factor + +!---------------------------------------------------------------------------------- +SUBROUTINE calculate_mean_u( m, p, u, num_element,r_t,turbine_mean_velocity,TI_normalization, FAST_Time ) +!.................................................................................. +! This routine is called to calculate the mean velocity and the TI of the turbine +! Using weighting method according to the blade ring area +!.................................................................................. + !USE TAVD, ONLY : m%TAVD%average_velocity_array + !USE read_turbine_position_data , ONLY : m%RTPD%SimulationOrder_index,m%RTPD%upwindturbine_number + !USE weighting_method , ONLY : m%weighting_method%sweptarea,m%weighting_method%weighting_denominator + !USE read_upwind_result_file_data , ONLY : m%Upwind_result%upwind_TI + !USE Blade , ONLY : R + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_InputType), INTENT(INOUT) :: u + + INTEGER :: num_element + INTEGER :: i + REAL(ReKi) :: r_t ( num_element ) ! The distance from the node to the hub + REAL(ReKi) :: turbine_mean_velocity ! turbine mean velocity + REAL(ReKi) :: node_radius ( num_element ) + REAL(ReKi) :: element_length ( num_element ) + REAL(ReKi) :: TI_normalization + REAL(ReKi) :: FAST_Time + + ! check if the meandering simulation time is valid + IF (p%WakePosition_1 < FAST_Time/ ( (20*p%RotorR/p%p_p_r)/(0.32*p%Uambient) ) + 1 ) THEN + ! bjj: this at least is standard fortran, but calling ProgAbort is not allowed in a module in the FAST framework. Please trap your errors and return an error code. + CALL ProgAbort('WARNING: Meandering_simulation_time is not valid, please refer to the DWM manual') + END IF + + ALLOCATE (m%weighting_method%sweptarea(num_element)) + + m%weighting_method%weighting_denominator = 0 + turbine_mean_velocity = 0 + + element_length (num_element) = 2.0*( p%RotorR - r_t(num_element) ) + DO i=num_element-1,1,(-1) + element_length(i)= 2.0*( r_t(i+1)-r_t(i) ) - element_length (i+1) + END DO + + node_radius ( num_element ) = p%RotorR - element_length (num_element) + DO i=num_element-1,1,(-1) + node_radius (i) = node_radius (i+1) - element_length (i) + END DO + + DO i=1, num_element-1,1 + m%weighting_method%sweptarea (i) = Pi * (node_radius (i+1) **2 - node_radius (i) **2) + END DO + m%weighting_method%sweptarea (num_element) = Pi * (p%RotorR**2-node_radius (num_element)**2) ! ring area + + DO i=1,num_element + m%weighting_method%weighting_denominator = m%weighting_method%weighting_denominator + m%weighting_method%sweptarea (i) ! denominator + END DO + + ! calculate the mean velocity of the turbine using weighting method + DO i=1,num_element + turbine_mean_velocity = turbine_mean_velocity + m%weighting_method%sweptarea (i) / m%weighting_method%weighting_denominator * m%TAVD%average_velocity_array(i) + END DO + + IF (p%RTPD%SimulationOrder_index == 1 .OR. p%RTPD%SimulationOrder_index == 0) THEN + TI_normalization = p%TI_amb + ELSE + IF(p%RTPD%upwindturbine_number /= 0) THEN ! superimpose the TI from upstream wakes + TI_normalization = 0 + DO I = 1,p%RTPD%upwindturbine_number + TI_normalization = (TI_normalization**2 + u%Upwind_result%upwind_TI(I)**2)**0.5 + END DO + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + TI_normalization = u%Upwind_result%upwind_TI(1) ! only take the TI effect from the closest upstream turbine + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + TI_normalization = TI_normalization/(turbine_mean_velocity/p%Uambient) + ELSE + TI_normalization = p%TI_amb + END IF + END IF + +END SUBROUTINE calculate_mean_u + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE calculate_element_area (blade_radius, num_element, r_t, sweptarea) +!.................................................................................................................................. +! This routine is called when the Aerodyn simuilation finishes. +! This routine is called to calculate the swept area of each blade section. +! The output of the subroutine is swept_area (:), which is the swept area of of each blade element. +!.................................................................................................................................. + IMPLICIT NONE + + ! Internal variables + INTEGER(IntKi) :: num_element + INTEGER(IntKi) :: I + REAL(ReKi) :: blade_radius + REAL(ReKi) :: r_t ( num_element ) ! The distance from the node to the hub + REAL(ReKi) :: node_radius ( num_element ) + REAL(ReKi) :: element_length ( num_element ) + REAL(ReKi) :: sweptarea(num_element) + + element_length (num_element) = 2.0*( blade_radius - r_t(num_element) ) + DO I=num_element-1,1,(-1) + element_length(I)= 2.0*( r_t(I+1)-r_t(I) ) - element_length (I+1) + END DO + + node_radius ( num_element ) = blade_radius - element_length (num_element) + DO I=num_element-1,1,(-1) + node_radius (I) = node_radius (I+1) - element_length (I) + END DO + + DO I=1, num_element-1,1 + sweptarea (I) = Pi * (node_radius (I+1) **2 - node_radius (I) **2) + END DO + sweptarea (num_element) = Pi * (blade_radius**2-node_radius (num_element)**2) + +END SUBROUTINE calculate_element_area + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE calculate_induction_factor ( p, normal_force , element_swept_area , num_element, FFWS_array, induction_factor_local ) +!.................................................................................................................................. +! This routine is called to calculate thrust coefficient then the induction factor using local thrust force. +! The output of the subroutine is induction_factor (:), which is the induction factor of each blade node. +!.................................................................................................................................. + + TYPE(DWM_ParameterType), INTENT(IN ) :: p + + + ! Internal variables + INTEGER(IntKi) :: num_element + INTEGER(IntKi) :: I + REAL(ReKi) :: normal_force ( num_element ) + REAL(ReKi) :: element_swept_area ( num_element ) + REAL(ReKi) :: thrust_coefficient ( num_element ) + REAL(ReKi) :: induction_factor_local ( num_element ) + REAL(ReKi) :: FFWS_array( num_element) + REAL(ReKi) :: Ct_1 + REAL(ReKi) :: a_t + REAL(ReKi) :: Ct_critical + + + !Calculate thrust coefficient + DO I=1,num_element + thrust_coefficient (I) = normal_force(I)/(0.5* p%air_density * element_swept_area(I)* FFWS_array(I)**2) + END DO + + + ! Then calculate the induction factor by solving 4a(1-a)= Ct + ! Applying the Glauert empirical Ct modification (10.7.2013) + + Ct_1 = 1.816 + a_t = 1 - 0.5*SQRT(Ct_1) + Ct_critical = 4*a_t*(1-a_t) + + DO I=1,num_element + IF (thrust_coefficient(I)<=Ct_critical) THEN + induction_factor_local (I) = (-4 + (16-16*thrust_coefficient(I))**(0.5))/(2*(-4)) + ELSE + induction_factor_local (I) = 1 - (thrust_coefficient(I)-Ct_1) / (-4*(SQRT(Ct_1)-1)) + END IF + END DO + +END SUBROUTINE calculate_induction_factor + +!---------------------------------------------------------------------------------- +SUBROUTINE get_initial_condition( m, p, u, y, induc_array, r_t, element_num, r_w, U_w ) +!.................................................................................. +! This routine is called at the end of the subroutine calculate_initial_condition. +! This routine is called to calculate the initial condition of the DWM model. +! The output of the subroutine is r_wake (:) and U_wake (:). +! Which are the the scaled rotor radius and the scaled velocity at the rotor. +!.................................................................................. + !USE read_turbine_position_data, ONLY: m%RTPD%SimulationOrder_index,m%RTPD%upwindturbine_number + !USE DWM_ParameterType, ONLY: p%smoothed_wake,p%smooth_flag,p%Uambient + !USE DWM_OutputType, ONLY: m%Mean_FFWS + !USE read_upwind_result_file_data, ONLY: m%Upwind_result%upwind_smoothWake + !USE BLADE, ONLY: R + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_InputType), INTENT(INOUT) :: u + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + + INTEGER :: element_num + INTEGER :: i,J + REAL(ReKi) :: induc_array(element_num) + REAL(ReKi) :: r_t(element_num) + REAL(ReKi) :: dA (element_num-1) + REAL(ReKi) :: a_cellC (element_num-1) + REAL(ReKi) :: mean_a + REAL(ReKi) :: f_w + REAL(ReKi) :: fU !fU factor (realised induction for wake depth) {0-1} + REAL(ReKi) :: fR !fR factor (realised expansion for wake width) {0-1} + REAL(ReKi), ALLOCATABLE :: r_w(:) + REAL(ReKi), ALLOCATABLE :: U_w(:) + + + ALLOCATE (r_w(element_num)) + ALLOCATE (U_w(element_num)) + fU = 1.10 !1.10 is not working when induction factor is reaching 0.5: (1-a*(fu+1))<1 !!!! 0.92 + fR = 0.98 + + + !------------------------------------------------------------------------------------------------- + ! apply the smoothed wake profile as the input wind profile for downstream turbine + !------------------------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------------------------- + ! calculate the boundary condition + !------------------------------------------------------------------------------------------------- + !===Initial Condition=== + DO i=1,element_num-1 + dA (i) =( (r_t(i+1)/p%RotorR)**2 - (r_t(i)/p%RotorR)**2 )*Pi + END DO + !== simple approximation of cell center value + DO i=1,element_num-1 + a_cellC (i) = ( induc_array(i+1) +induc_array(i) ) /2 + END DO + + !== Boundary Condition r_w + mean_a = 0.0 + DO i=1,element_num-1 + mean_a = ( a_cellC (i) * dA (i) ) /Pi + mean_a + END DO + + !== Uniform expansion + f_w = ( (1-mean_a) / (1- ((1+fR) * mean_a)) )**0.5 + r_w = r_t /p%RotorR * f_w + + !== Boundary velocity + !U_w = 1 - (induc_array * (1+fU)) + + ! superimpose the smoothed wake from upwind turbines + IF (p%RTPD%SimulationOrder_index == 1 .OR. p%RTPD%SimulationOrder_index == 0) THEN + U_w = 1 - (induc_array * (1+fU)) + ELSEIF(p%RTPD%SimulationOrder_index > 1) THEN + IF (p%RTPD%upwindturbine_number == 0) THEN + U_w = 1 - (induc_array * (1+fU)) + ELSEIF (p%RTPD%upwindturbine_number > 0) THEN + !!ALLOCATE (p%smoothed_wake(element_num)) + !!p%smoothed_wake = 1 + !!DO I = 1,p%RTPD%upwindturbine_number + !!DO J = 1,element_num + !!p%smoothed_wake(J) = 1- ( (1-p%smoothed_wake(J))**2 + (1-u%Upwind_result%upwind_smoothWake(I,J))**2 )**0.5 + !!END DO + !!END DO + + DO I = 1,element_num + !U_w(I) = (p%Uambient/y%Mean_FFWS) * u%Upwind_result%upwind_smoothWake(1,I)*(1 - (induc_array(I) * (1+fU))) + U_w(I) = (y%Mean_FFWS/p%Uambient) *(1 - (induc_array(I) * (1+fU))) + END DO + END IF + END IF + + DO i=1,element_num,1 ! modification for low wind speed, high thrust situation + IF (U_w(i) < 0.0) THEN + U_w(i) = 0.01 + END IF + END DO + + ! calculate the average induction factor of the rotor plane + !avg_induction_factor = 0 + + !DO i=1,element_num + !avg_induction_factor = avg_induction_factor + m%weighting_method%sweptarea (i) / m%weighting_method%weighting_denominator * induc_array(i) + !END DO + + !m%skew_angle = 0.60*avg_induction_factor*NacYaw *(-1) ! minus sign means different direction + + + !--- calculate the average thrust coefficient and the ct_tilde --- + + y%avg_ct = 0 + + !-------test-------- + !u%NacYaw = 0.00 + !------------------- + + DO i=1,element_num + y%avg_ct = y%avg_ct + m%weighting_method%sweptarea (i) / m%weighting_method%weighting_denominator * ( 4*induc_array(i)*(1-induc_array(i)) ) + END DO + + !m%ct_tilde = 0.5*COS(m%NacYaw)**2*SIN(m%NacYaw)*y%avg_ct + m%ct_tilde = y%avg_ct + +END SUBROUTINE get_initial_condition + +!------------------------------------------------------------------------- +SUBROUTINE calculate_wake(m, p, y, r_w, U_w, element_num, U, b) +!.................................................................................. +! This routine is the main routine to calculate the wake +! This routine is called after receiving the scaled rotor radius and the scaled velocity at the rotor +! The output of this routine is the wake velocity which is "U" +! and the wake width which is the "b" +!.................................................................................. + !USE DWM_Wake_Deficit_Data + !USE DWM_ParameterType, ONLY: p%p_p_r, p%r_domain, p%Uambient, p%x_domain, p%hub_height, p%TI_amb + + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + INTEGER :: element_num + REAL(ReKi) :: r_w (element_num) ! scaled rotor radius r_w + REAL(ReKi) :: U_w (element_num) ! scaled velocity U_w + REAL(ReKi),ALLOCATABLE :: U(:,:) + INTEGER,ALLOCATABLE :: b(:) + + ! local variables + REAL(ReKi) :: mtemp + REAL(ReKi) :: ntemp + REAL(ReKi) :: xtemp + REAL(ReKi) :: ytemp + + REAL(ReKi), DIMENSION(2) :: filter1 + REAL(ReKi), DIMENSION(2) :: filter2 + REAL(ReKi), ALLOCATABLE :: F1_vector (:) + REAL(ReKi), ALLOCATABLE :: F2_vector (:) + !REAL(ReKi) :: m%DWDD%ppR ! Point_per_R_resoulution + REAL(ReKi) :: Domain_R ! Domain_size_in_radial_direction + REAL(ReKi) :: Domain_X ! Domain_size_in_flow_direction + !REAL(ReKi) :: TI_original ! Turbulence_intensity normalized back to ambient wind speed + REAL(ReKi) :: k1 ! Amb turb. coeff. + REAL(ReKi) :: k2 ! Shear layer coeff. + + !INTEGER :: m%DWDD%n_x_vector + !INTEGER :: m%DWDD%n_r_vector + + !%%%%% Rolf modification + INTEGER :: length_F1_vector + REAL(ReKi) :: L_ABL_vector(3) + REAL(ReKi) :: UW_UU_vector(3) + REAL(ReKi) :: L_DEF_vector(3) + REAL(ReKi) :: UU_DEF_UU_ABL_vector(3) + REAL(ReKi) :: UW_DEF_UU_DEF_vector(3) + REAL(ReKi) :: x_ary(3) + REAL(ReKi) :: L_ABL + REAL(ReKi) :: UW_UU + REAL(ReKi) :: L_DEF + REAL(ReKi) :: UU_DEF_UU_ABL + REAL(ReKi) :: UW_DEF_UU_DEF + REAL(ReKi) :: Rotor_fixed_R + REAL(ReKi) :: l_star_ABL + REAL(ReKi) :: l_star_DEF + REAL(ReKi) :: UU_DEF_UU_ABL_fac + REAL(ReKi) :: u_star_ABL + REAL(ReKi) :: u_star_DEF + REAL(ReKi) :: Shear_add_du_dz + REAL(ReKi),ALLOCATABLE :: visc_wake(:,:) + REAL(ReKi),ALLOCATABLE :: visc_wake1(:,:) + REAL(ReKi),ALLOCATABLE :: visc_wake2(:,:) + REAL(ReKi) :: visc_norm_factor + REAL(ReKi),ALLOCATABLE :: alfa_1(:) + REAL(ReKi),ALLOCATABLE :: alfa_2(:) + REAL(ReKi),ALLOCATABLE :: du_dr_tot(:,:) + INTEGER,ALLOCATABLE :: shear_flag(:) + REAL(ReKi),ALLOCATABLE :: One_div_du_dr_DWM(:,:) + REAL(ReKi),ALLOCATABLE :: visc_fac(:) + + REAL(ReKi) :: R_WTG ! normalized radius + REAL(ReKi) :: U0 ! normalized wind speed + REAL(ReKi) :: D_WTG ! normalized diameter + REAL(ReKi) :: R_length ! normalized length in radial direction + !REAL(ReKi) :: m%DWDD%X_length ! normalized length in axial direction + INTEGER :: np_r ! point per radial distance + !INTEGER :: m%DWDD%np_x ! point per axial distance + REAL(ReKi) :: delrad ! delta r + REAL(ReKi) :: delaxi ! delta x + + REAL(ReKi), ALLOCATABLE :: x_vector(:) + REAL(ReKi), ALLOCATABLE :: r_vector(:) + + REAL(ReKi), ALLOCATABLE :: V(:,:) + REAL(ReKi), ALLOCATABLE :: visc(:,:) + REAL(ReKi), ALLOCATABLE :: visc_DWM(:,:) + REAL(ReKi), ALLOCATABLE :: du_dr_DWM(:,:) + REAL(ReKi), ALLOCATABLE :: du_dr_total(:,:) + !REAL(ReKi), ALLOCATABLE :: m%DWDD%Turb_Stress_DWM(:,:) + !REAL(ReKi), ALLOCATABLE :: TI_DWM(:,:) + !REAL(ReKi), ALLOCATABLE :: U_face(:,:) + !REAL(ReKi), ALLOCATABLE :: VOL_x_jhigh(:,:) + !REAL(ReKi), ALLOCATABLE :: VOL_x_jlow (:,:) + !REAL(ReKi), ALLOCATABLE :: VOL_r_ihigh(:,:) + !REAL(ReKi), ALLOCATABLE :: VOL_r_ilow (:,:) + REAL(ReKi), ALLOCATABLE :: r_vec_DWM (:) + REAL(ReKi), ALLOCATABLE :: dA_DWM (:) + + INTEGER :: n_r_vec_DWM + INTEGER :: b_loop + INTEGER :: b_counter + REAL(ReKi) :: dr_DWM + REAL(ReKi) :: Def_DWM + REAL(ReKi) :: Def_DWM_mixL + REAL(ReKi) :: A_total + REAL(ReKi) :: k_wiener + + INTEGER, ALLOCATABLE :: counter(:) + INTEGER :: i + INTEGER :: j + INTEGER :: k + INTEGER :: ILo + INTEGER :: NumEqu + INTEGER :: n_xi + INTEGER :: n_U_tmp_2 + + REAL(ReKi), ALLOCATABLE :: bin_filter(:) + REAL(ReKi), ALLOCATABLE :: xi(:) + REAL(ReKi), ALLOCATABLE :: U_tmp_1(:) + REAL(ReKi), ALLOCATABLE :: U_tmp_2(:) + REAL(ReKi), ALLOCATABLE :: U_tmp(:) + REAL(ReKi), ALLOCATABLE :: mat(:,:) + REAL(ReKi), ALLOCATABLE :: RHS(:) + REAL(ReKi), ALLOCATABLE :: Soln(:) + REAL(ReKi), ALLOCATABLE :: AugMat(:,:) + + REAL(ReKi) :: LHS1 + REAL(ReKi) :: LHS2 + REAL(ReKi) :: LHS3 + REAL(ReKi) :: LHS11 + REAL(ReKi) :: LHS12 + REAL(ReKi) :: LHS13 + REAL(ReKi) :: LHS21 + REAL(ReKi) :: LHS22 + REAL(ReKi) :: LHS23 + REAL(ReKi) :: LHS31 + REAL(ReKi) :: LHS41 + REAL(ReKi) :: LHS32 + REAL(ReKi) :: LHS33 + REAL(ReKi) :: LHS43 + + REAL(ReKi),ALLOCATABLE :: main_diagonal(:) + REAL(ReKi),ALLOCATABLE :: sub_diagonal(:) + REAL(ReKi),ALLOCATABLE :: sup_diagonal(:) + + m%DWDD%ppR = p%p_p_r + Domain_R = p%r_domain !10.0 domain size in R [R] + Domain_X = p%x_domain !42.0 domain size in X [R] + filter1 = (/0.0, 4.0 /) + filter2 = (/0.035, 0.35/) + k1 = 0.0919 + k2 = 0.0178 + R_WTG = 1.0 + U0 = 1.0 + D_WTG = 2.0 + R_length = Domain_R + m%DWDD%X_length = Domain_X + + m%TI_original = y%TI*(y%Mean_FFWS/p%Uambient) ! calculate the TI if under ambient wind speed + + np_r = m%DWDD%ppR ! per R ie. R resolution is 50 + m%DWDD%np_x = m%DWDD%ppR ! per D ie. X resolution is 50 + delrad = R_WTG/np_r ! dr + delaxi = D_WTG/m%DWDD%np_x ! dx + m%DWDD%n_x_vector = floor((m%DWDD%X_length)/D_WTG*m%DWDD%np_x) ! number of point in equally spaced array x_vector + m%DWDD%n_r_vector = floor((R_length)/R_WTG*np_r) ! number of point in equally spaced array r_vector + + ! create coordinate vectors + ALLOCATE (x_vector(m%DWDD%n_x_vector)) + ALLOCATE (r_vector(m%DWDD%n_r_vector)) + ! similar to linspace function + x_vector = ( (m%DWDD%X_length-delaxi)/(m%DWDD%n_x_vector-1 ) )*[(i,i=1,m%DWDD%n_x_vector)]+(0-( (m%DWDD%X_length-delaxi)/(m%DWDD%n_x_vector-1) )) + r_vector = ( (R_length-delrad)/(m%DWDD%n_r_vector-1 ) )*[(i,i=1,m%DWDD%n_r_vector)]+(0-( (R_length-delrad)/(m%DWDD%n_r_vector-1) )) + + ! Create the F1 filter + + CALL create_F1_filter (F1_vector, filter1, length_F1_vector,m%DWDD%np_x,m%DWDD%X_length) + !OPEN (unit=25,file="DWM\results\F1_filter.txt") + !WRITE (25,'(f13.6)'), F1_vector(:) + !CLOSE(25) + + CALL create_F2_filter (F2_vector, filter2, m%DWDD%np_x, length_F1_vector) + + + !CALL create_filter_vector ( filter1, F1_vector ) + + !CALL create_filter_vector ( filter2, F2_vector ) + + !OPEN (unit=25,file="DWM\results\F2_filter.txt") + !WRITE (25,'(f13.6)'), F2_vector(:) + !CLOSE(25) + + ! Initiate the U, V, visc, TI_add, Turb_stress matrices + ALLOCATE (V (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (U (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) !axial velocity matrix + ALLOCATE (visc (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (visc_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (du_dr_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (du_dr_total (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (m%DWDD%Turb_Stress_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + !ALLOCATE (TI_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + !ALLOCATE (U_face (m%DWDD%n_x_vector,m%DWDD%n_r_vector-1)) + !ALLOCATE (VOL_x_jhigh (m%DWDD%n_x_vector,m%DWDD%n_r_vector-1)) + !ALLOCATE (VOL_x_jlow (m%DWDD%n_x_vector,m%DWDD%n_r_vector-1)) + !ALLOCATE (VOL_r_ihigh (m%DWDD%n_x_vector,m%DWDD%n_r_vector-1)) + !ALLOCATE (VOL_r_ilow (m%DWDD%n_x_vector,m%DWDD%n_r_vector-1)) + ALLOCATE (visc_wake (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (visc_wake1 (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (visc_wake2 (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (alfa_1 (m%DWDD%n_r_vector )) + ALLOCATE (alfa_2 (m%DWDD%n_r_vector )) + ALLOCATE (du_dr_tot (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (shear_flag (m%DWDD%n_r_vector )) + ALLOCATE (One_div_du_dr_DWM (m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + ALLOCATE (visc_fac (m%DWDD%n_r_vector )) + + ALLOCATE (main_diagonal (m%DWDD%n_r_vector )) + ALLOCATE (sub_diagonal (m%DWDD%n_r_vector )) + ALLOCATE (sup_diagonal (m%DWDD%n_r_vector )) + + V = 0 + U = 0 + visc = 0 + du_dr_DWM = 0 + m%DWDD%Turb_Stress_DWM = 0 + !TI_DWM = 0 + !U_face = 0 + !VOL_x_jhigh = 0 + !VOL_x_jlow = 0 + !VOL_r_ihigh = 0 + !VOL_r_ilow = 0 + + !%%%% BOUNDARY CONDITIONS + ! ROTOR PLANE + ALLOCATE (bin_filter(m%DWDD%n_r_vector)) + DO i=1,m%DWDD%n_r_vector + IF (MAXVAL(r_w)>r_vector(i)) THEN + bin_filter(i) = 1 + ELSE + bin_filter(i) = 0 + END IF + END DO + + + n_xi=floor(sum(bin_filter)) + ALLOCATE (xi(n_xi)) + xi=r_vector(1:n_xi)*bin_filter(1:n_xi) + + ALLOCATE (U_tmp_1(n_xi)) + ILo = 1 + DO i=1,n_xi + U_tmp_1(i) = InterpBin( xi(i), r_w, U_w, ILo, size(r_w)) + END DO + + n_U_tmp_2 = size(r_vector)-n_xi + ALLOCATE (U_tmp_2(n_U_tmp_2)) + U_tmp_2 = U0 + + ALLOCATE (U_tmp(n_xi +n_U_tmp_2)) ! =m%DWDD%n_r_vector + U_tmp = (/U_tmp_1, U_tmp_2/) + U (1,:) = U_tmp(1:m%DWDD%n_r_vector) + + ! Centerline + V (1,:) = 0 + + + + !%%%% SOLVING FLOW FIELD + ALLOCATE (b(m%DWDD%n_x_vector)) + ALLOCATE (counter(m%DWDD%n_x_vector)) + counter=1 + ALLOCATE (AugMat (m%DWDD%n_r_vector,m%DWDD%n_r_vector+1) ) + ALLOCATE (Soln (m%DWDD%n_r_vector) ) + + ALLOCATE (mat(m%DWDD%n_r_vector,m%DWDD%n_r_vector)) + ALLOCATE (RHS(m%DWDD%n_r_vector)) + + n_r_vec_DWM = floor(m%DWDD%ppR*Domain_R) + ALLOCATE ( r_vec_DWM (n_r_vec_DWM) ) + ALLOCATE ( dA_DWM (n_r_vec_DWM-1) ) + + !%%%%%%%%%%%%%%% Atmospheric stability effects %%%%%%%%%%%%%%%%%% + L_ABL_vector = (/26.5352, 34.026, 40.7458/) + UW_UU_vector = (/-0.27359, -0.27887, -0.27935/) + L_DEF_vector = (/11.065, 12.9746, 14.4395/) + UU_DEF_UU_ABL_vector = (/0.63044, 0.57982, 0.5287/) + UW_DEF_UU_DEF_vector = (/-0.27341, -0.25684, -0.24217/) + + !%%%%% interpolation wrt to the hub height + x_ary = (/40,100,160/) + L_ABL = InterpBin( p%hub_height, x_ary, L_ABL_vector, ILo, size(x_ary) ) !int_Lww(k3) i.e (Integral length scale (in vertical directions), from ww(k3)) + UW_UU = InterpBin( p%hub_height, x_ary, UW_UU_vector, ILo, size(x_ary) ) ! ratio of UW and UU stresses for whole spectra + L_DEF = InterpBin( p%hub_height, x_ary, L_DEF_vector, ILo, size(x_ary) ) ! Integral length scale (in vertical directions), Meandering length scale subtracted, from ww(k3) + UU_DEF_UU_ABL = InterpBin( p%hub_height, x_ary, UU_DEF_UU_ABL_vector, ILo, size(x_ary) ) ! Part of normal stress in the deficit module + UW_DEF_UU_DEF = InterpBin( p%hub_height, x_ary, UW_DEF_UU_DEF_vector, ILo, size(x_ary) ) ! ratio of UW and UU stresses for spectra in deficit scales + + !%%%%% normalized by the fixed rotor R + Rotor_fixed_R = 40 !ATMOSTAB ANALYSIS IS CARRIED OUT OVER R = 40m, which should be used to normalize the length scales + l_star_ABL = L_ABL / Rotor_fixed_R; + l_star_DEF = L_DEF / Rotor_fixed_R; + + !%%%%% Normalize UU_160m to neutral condition + UU_DEF_UU_ABL_fac = InterpBin( p%hub_height, x_ary, (/0.63044_ReKi, 0.57982_ReKi, 0.5287_ReKi/), ILo, size(x_ary) ) + UU_DEF_UU_ABL = UU_DEF_UU_ABL / UU_DEF_UU_ABL_fac + + !%%%%% CALCULATE u* according to: + ! 1. u* ~= (mean(u'w')^2 )^0.25 + ! 2. {mean(u'w') = mean(u'u')*Cuw_uu} + ! 3. {u' ~= TI (in normalized form)} + ! => u* ~= ((TI^2 * Cuw_uu )^2)^0.25 + u_star_ABL = ( ( (p%TI_amb/100)**2 * ABS(UW_UU) )**2 )**0.25 + u_star_DEF = ( ( (m%TI_original/100)**2 * UU_DEF_UU_ABL * abs(UW_DEF_UU_DEF) )**2 )**0.25; + + Shear_add_du_dz = u_star_ABL / l_star_ABL + + !k_wiener = du_dz_ABL + delrad**2 + + DO j=2, m%DWDD%n_x_vector, 1 ! start from the plane next to the rotor plane + + !==== Calculating wake width "b" where 95% of the deficit is captured + dr_DWM = 1.0/m%DWDD%ppR + + DO i=1,n_r_vec_DWM ! build r_vec_DWM + r_vec_DWM (i) = dr_DWM/2 + (i-1)*dr_DWM + END DO + + DO i=1,n_r_vec_DWM-1 ! build dA_DWM + dA_DWM (i) = Pi * ( r_vec_DWM (i+1)**2 - r_vec_DWM (i)**2 ) + END DO + + Def_DWM = 0 ! Calculate Def_DWM + DO i=1, n_r_vec_DWM-1 + Def_DWM = (1-U (j-1,i+1)) * dA_DWM (i) + Def_DWM + END DO + + Def_DWM_mixL = 0 ! Calculate the wake width "b" + DO i = 2,NINT( m%DWDD%ppR ) + Def_DWM_mixL = ( 1- U(j-1,i) ) * dA_DWM(i) + Def_DWM_mixL + END DO + DO b_counter = NINT(m%DWDD%ppR)+1, n_r_vec_DWM-1 + Def_DWM_mixL = ( 1- U(j-1,b_counter) ) * dA_DWM(b_counter) + Def_DWM_mixL + IF ( Def_DWM_mixL > Def_DWM * 0.99 ) THEN + EXIT + ELSE IF (b_counter == n_r_vec_DWM-1) THEN + EXIT + END IF + END DO + b(j-1) = b_counter + + ! %%%%% Calculate eddy viscosity + ! Include blend between original Prandtl model and Ainslie to avoid issues when wake turbulence goes to 0. + ! The largest eddy viscosity at each point is applied. + + ! Calculate mean flow gradient - du/dr is created with CDS (apart from 1st and last point) + du_dr_DWM(j-1,1) = (U(j-1,2) - U(j-1,1))/delrad + du_dr_DWM(j-1,2:NINT(R_length*np_r)-1) = ( U(j-1,3:NINT(R_length*np_r-1)+1) - U(j-1,1:NINT(R_length*np_r-1)-1))/(2*delrad) + du_dr_DWM(j-1, NINT(R_length*np_r) ) = ( U(j-1, NINT(R_length*np_r ) ) - U(j-1, NINT(R_length*np_r-1) ))/delrad + + ! %%% Blend of mixL and Ainslie eddy visc + DO I = 1,m%DWDD%n_r_vector + visc_wake1(j-1,I) = F2_vector(j-1)* k2 *( r_vector(b(j-1))/R_WTG )**2 * ABS(du_dr_DWM(j-1,I)); + visc_wake2(j-1,I) = F2_vector(j-1)* k2 *( r_vector(b(j-1))/R_WTG ) * ( 1 - min_of_array( U(j-1,:),SIZE(U(j-1,:)) ) ); + visc_wake (j-1,I) = max( visc_wake1(j-1,I),visc_wake2(j-1,I) ); + END DO + + ! %%% Atmospheric eddy visc as u*l*, yields total eddy viscosity + visc_norm_factor = 6.3918 + DO I = 1,m%DWDD%n_r_vector + visc(j-1,I) = F1_vector(j-1) * k1 * visc_norm_factor * u_star_DEF * l_star_DEF + visc_wake(j-1,I); + END DO + + ! %%%%% Include contribution from atmospheric boundary layer on DWM + ! % 1. Calculate the azimuthally averaged local gradient (du/dr tot) acting of the eddy viscosity as a combination of du/dr in the DWM model and du/dz from ABL + ! % 2. The du/dr contribution is constant in azimuthal direction. The du/dz part is assumed linear, which gives a sinus curve in a du/dr system + + !% Calculate total mean flow gradient - adds shear contribution via + !% sin function. This gets the stresses right, but sign is wrong in + !% regions where du/dr_DWM - sign of du/dz_ABL is negative + + DO I = 1,m%DWDD%n_r_vector + !alfa_1(I) = ASIN(ABS(du_dr_DWM(j-1,I)) / Shear_add_du_dz) + !alfa_2(I) = Pi - alfa_1(I) + + ! % condition for added shear gradient (if du/dr_DWM >= du/dz_ABL there are no contribution) + IF ( ABS(du_dr_DWM(j-1,I)) < Shear_add_du_dz ) THEN + shear_flag(I) = 1 + alfa_1(I) = ASIN(ABS(du_dr_DWM(j-1,I)) / Shear_add_du_dz) + alfa_2(I) = Pi - alfa_1(I) + ELSE + shear_flag(I) = 0 + alfa_1(I) = 0 + alfa_2(I) = 0 + END IF + + + du_dr_tot(j-1,I) = ( ABS(du_dr_DWM(j-1,I))*2*Pi + shear_flag(I)*2*& + ( Shear_add_du_dz*2*COS(alfa_1(I))-ABS(du_dr_DWM(j-1,I))*(alfa_2(I) - alfa_1(I))) )/(2*Pi) + END DO + + ! %%% Use "wiener filter" for numerical stability: 1/f(x) ~= f(x) / (f(x)^2 + k) + k_wiener = 2*Shear_add_du_dz * delrad**2; + DO I = 1,m%DWDD%n_r_vector + One_div_du_dr_DWM(j-1,I) = du_dr_DWM(j-1,I) / (du_dr_DWM(j-1,I)**2 + k_wiener) + visc_fac(I) = max(1.0_ReKi, (du_dr_tot(j-1,I) * ABS(One_div_du_dr_DWM(j-1,I)))) + visc(j-1,I) = visc(j-1,I) * visc_fac(I) + END DO + + + + + + + + + + !!!DO i = 1,m%DWDD%n_r_vector + !!! IF ( ABS(du_dr_DWM(j-1,i)) >= du_dz_ABL ) THEN + !! ! A_total = 2*Pi*du_dr_DWM(j-1,i) + !!! ELSE + !!! ytemp = du_dr_DWM(j-1,i) + !!! xtemp = 2 * shear_correction( du_dr_DWM(j-1,i),du_dz_ABL ) + !!! A_total = 2*Pi*du_dr_DWM(j-1,i) + 2 * shear_correction( du_dr_DWM(j-1,i),du_dz_ABL ) + !!!END IF + !!!du_dr_total(j-1,i) = A_total / (2*Pi) + !!!END DO + + !!!visc_DWM(j-1,:) = F1_vector(j-1)*k1*(TI_original/100) + F2_vector(j-1)* k2 *( r_vector(b(j-1))/R_WTG )**2 * ABS( du_dr_DWM(j-1,:) ) + !!!visc(j-1,:) = visc_DWM(j-1,:) + + + !DO i = 1,m%DWDD%n_r_vector + !mtemp = du_dr_total(j-1,i) + !ntemp = du_dr_DWM(j-1,i) + !IF (ABS( du_dr_DWM(j-1,i) < 0.0001 ) ) THEN + ! visc(j-1,i) = visc_DWM(j-1,i) * du_dr_total(j-1,i) * ABS( du_dr_DWM(j-1,i)/(du_dr_DWM(j-1,i)**2 + k_wiener) ) + !ELSE + ! visc(j-1,i) = visc_DWM(j-1,i) * du_dr_total(j-1,i) / ABS( du_dr_DWM(j-1,i) ) + !END IF + !visc(j-1,i) = visc_DWM(j-1,i) * du_dr_total(j-1,i) * ABS( 1/du_dr_DWM(j-1,i)) + !END DO + + mat=0 + ! ====SHORT INSTRUCIONS TO SOLVE RUTINE: + ! The terms LHS and RHS (left/right hand side) refers to the terms of + ! the coefficient matrix developed to solve the then shear layer + ! approximation of NS. The numbers indicate the position in the equation, + ! ex LHS21 is the 2nd part of the 1st term on the left side in eq.2.8, + ! see document "Numerical implementation of DWM deficit module" for details. + + ! Input BC for wake center + + LHS2 = U(j-1,1)/delaxi + (2*visc(j-1,1)/(delrad**2)) + LHS3 = -(2*visc(j-1,1) /(delrad**2)) + RHS(1) = (U(j-1,1)**2 / delaxi) + mat(1,1) = LHS2 + mat(2,1) = LHS3 + + ! Calculation of U for the wake body + DO i=2,(m%DWDD%n_r_vector-1),1 ! starts from the point next to the hub center + LHS11 = -V(j-1,i) / (2*delrad) + LHS21 = visc(j-1,i) / (2*r_vector(i)*delrad) + LHS31 = -visc(j-1,i) / (delrad**2) + LHS41 = (visc(j-1,i+1) - visc(j-1,i-1)) / (2*delrad)**2; ! new term due to d(nu_t)/dr dependence + LHS12 = U(j-1,i) / (delaxi) + LHS22 = 2*visc(j-1,i) / (delrad**2) + LHS13 = V(j-1,i) / (2*delrad) + LHS23 = -visc(j-1,i) / (2*r_vector(i)*delrad) + LHS33 = -visc(j-1,i) / (delrad**2) + LHS43 = -(visc(j-1,i+1) - visc(j-1,i-1)) / (2*delrad)**2; ! new term due to d(nu_t)/dr dependence + LHS1 = LHS11 + LHS21 + LHS31 + LHS41 + LHS2 = LHS12 + LHS22 + LHS3 = LHS13 + LHS23 + LHS33 + LHS43 + RHS(i) = (U(j-1,i)**2 / delaxi) + ! Build the matrix for X =A/B + mat(i-1,i) = LHS1 + mat(i ,i) = LHS2 + mat(i+1,i) = LHS3 + END DO + + ! Input BC for wake edge + LHS1 = 0 + LHS2 = 1/delaxi + RHS(NINT(R_length*np_r)) = (U(j-1,NINT(R_length*np_r))/ delaxi) + mat(NINT(R_length*np_r)-1, NINT(R_length*np_r) ) = LHS1 + mat(NINT(R_length*np_r) , NINT(R_length*np_r) ) = LHS2 + + ! Solve for the U + ! Use Gauss-Jordan elimination + AugMat (1:m%DWDD%n_r_vector, 1:m%DWDD%n_r_vector) = TRANSPOSE(mat) + AugMat (: , m%DWDD%n_r_vector+1) = RHS + NumEqu = m%DWDD%n_r_vector + !CALL Gauss(AugMat, NumEqu, Soln) + !U(j,:)=Soln + + ! === USE Thomas Algorithm to solve the matrix ==== 6.30.2014 + main_diagonal (1) = AugMat(1,1) + sub_diagonal (1) = 0 ! means it is the diagonal below the main diagonal + sup_diagonal (1) = AugMat(1,2) ! means it is the diagonal above the main diagonal + + DO I = 2,m%DWDD%n_r_vector-1 + main_diagonal (I) = AugMat(I,I) + sub_diagonal (I) = AugMat(I,I-1) + sup_diagonal (I) = AugMat(I,I+1) + END DO + + main_diagonal (m%DWDD%n_r_vector) = AugMat(m%DWDD%n_r_vector, m%DWDD%n_r_vector) + sub_diagonal (m%DWDD%n_r_vector) = AugMat(m%DWDD%n_r_vector, m%DWDD%n_r_vector-1) + sup_diagonal (m%DWDD%n_r_vector) = 0 + + CALL Thomas_diagonal (sub_diagonal, main_diagonal, sup_diagonal, RHS, Soln, NumEqu) + U(j,:)=Soln + + ! === Solve for V + DO i = 1,NINT(R_length)*np_r-1,1 + V(j,i+1) = (r_vector(i) / r_vector(i+1)) * V(j,i) -(delrad/(2*delaxi))*( (U(j,i+1) - U(j-1,i+1)) + & + (r_vector(i) / r_vector(i+1)) * ((U(j,i) - U(j-1,i))) ) + END DO + + ! POST PROCESSING SIGNAL: Turbulent stress + DO i=1,m%DWDD%n_r_vector,1 + !m%DWDD%Turb_Stress_DWM(j-1,i) = visc_DWM(j-1,i) * du_dr_total(j-1,i) + m%DWDD%Turb_Stress_DWM(j-1,i) = visc(j-1,i) * du_dr_DWM(j-1,i) + END DO + + ! Control calculatoins of mass flux over cells + + !!DO i=1,m%DWDD%n_r_vector-1,1 + !! VOL_x_jhigh(j-1,i) = (Pi/3) *((U(j,i) *(r_vector(i+1)**3 - (3 *r_vector(i)**2 *r_vector(i+1)) + 2 *r_vector(i)**3)) +& + !! (U(j,i+1) *(r_vector(i)**3 - (3*r_vector(i+1)**2 *r_vector(i)) + 2 *r_vector(i+1)**3)))/ delrad + !! VOL_x_jlow(j-1,i) = (Pi/3) *((U(j-1,i) *(r_vector(i+1)**3 - (3*r_vector(i)**2 *r_vector(i+1)) + 2 *r_vector(i)**3)) +& + !! (U(j-1,i+1) *(r_vector(i)**3 - (3*r_vector(i+1)**2 *r_vector(i)) + 2 *r_vector(i+1)**3)))/ delrad + !! VOL_r_ilow(j-1,i) = Pi * r_vector(i) * (V(j-1,i)+V(j,i)) * delaxi + + !! V(j,i+1) = ((VOL_x_jlow(j-1,i) - VOL_x_jhigh(j-1,i) + VOL_r_ilow(j-1,i)) / (Pi*(r_vector(i+1)) *delaxi)) - V(j-1,i+1) !! changed to version 2 2012/4/11 + !! VOL_r_ihigh(j-1,i) = Pi * r_vector(i+1) * (V(j-1,i+1)+V(j,i+1)) * delaxi + !! specificly U_face for mass flow and momentum calculations + !! U_face(j-1,i) = VOL_x_jlow(j-1,i) / (Pi*((r_vector(i+1)**2)-(r_vector(i))**2)) + !!END DO + + END DO + + b(m%DWDD%n_x_vector) = b(m%DWDD%n_x_vector-1) + + IF (ALLOCATED( V )) DEALLOCATE ( V ) + IF (ALLOCATED( visc )) DEALLOCATE ( visc ) + IF (ALLOCATED( du_dr_DWM )) DEALLOCATE ( du_dr_DWM ) + !IF (ALLOCATED( m%DWDD%Turb_Stress_DWM )) DEALLOCATE ( m%DWDD%Turb_Stress_DWM ) + !IF (ALLOCATED( TI_DWM )) DEALLOCATE ( TI_DWM ) + !IF (ALLOCATED( U_face )) DEALLOCATE ( U_face ) + !IF (ALLOCATED( VOL_x_jhigh )) DEALLOCATE ( VOL_x_jhigh ) + !IF (ALLOCATED( VOL_x_jlow )) DEALLOCATE ( VOL_x_jlow ) + !IF (ALLOCATED( VOL_r_ihigh )) DEALLOCATE ( VOL_r_ihigh ) + !IF (ALLOCATED( VOL_r_ilow )) DEALLOCATE ( VOL_r_ilow ) + IF (ALLOCATED( r_vec_DWM )) DEALLOCATE ( r_vec_DWM ) + IF (ALLOCATED( dA_DWM )) DEALLOCATE ( dA_DWM ) + IF (ALLOCATED( bin_filter )) DEALLOCATE ( bin_filter ) + IF (ALLOCATED( xi )) DEALLOCATE ( xi ) + IF (ALLOCATED( U_tmp_1 )) DEALLOCATE ( U_tmp_1 ) + IF (ALLOCATED( U_tmp_2 )) DEALLOCATE ( U_tmp_2 ) + IF (ALLOCATED( U_tmp )) DEALLOCATE ( U_tmp ) + IF (ALLOCATED( mat )) DEALLOCATE ( mat ) + IF (ALLOCATED( U_tmp )) DEALLOCATE ( U_tmp ) + IF (ALLOCATED( RHS )) DEALLOCATE ( RHS ) + IF (ALLOCATED( Soln )) DEALLOCATE ( Soln ) + IF (ALLOCATED( AugMat )) DEALLOCATE ( AugMat ) + + !OPEN(unit = 10, status='replace',file='sizeof_Uvelocity_2nd.bin',form='unformatted') ! create sizeof_Uvelocity_2nd.bin, or overwrite an existing on + !WRITE(10) m%DWDD%ppR,Domain_R ! write the length of the velocity vector + !CLOSE(10) + + !OPEN(unit = 10, status='replace',file='DWM\results\Uvelocity.bin',form='unformatted') + !WRITE(10) U(floor(spacing_turbine * m%DWDD%ppR)+1,:) ! write the wind data of the plane where the downstream turbine locates + !CLOSE(10) + + !OPEN (unit=25,file="DWM\results\wake_width.txt") + !WRITE (25,'(I5)'), b(:) + !close(25) + + +END SUBROUTINE calculate_wake + +!--------------------------------------------------------------------------------------------- +SUBROUTINE Thomas_diagonal (lowerDia, mainDia, upperDia, RightHS, SolnVec, NumEq) +!............................................................................................. +! This function returns the F1 filter function +!............................................................................................. + + INTEGER :: NumEq + + REAL(ReKi) :: lowerDia(NumEq) + REAL(ReKi) :: mainDia(NumEq) + REAL(ReKi) :: upperDia(NumEq) + REAL(ReKi) :: RightHS(NumEq) + REAL(ReKi) :: SolnVec(NumEq) + + REAL(ReKi) :: cp_vec(NumEq) + REAL(ReKi) :: dp_vec(NumEq) + REAL(ReKi) :: temp + INTEGER :: I + + ! initialize c-prime and d-prime + cp_vec(1) = upperDia(1) / mainDia(1) + dp_vec(1) = RightHS(1) / mainDia(1) + + ! solve for vectors c-prime and d-prime + DO I = 2,NumEq + temp = mainDia(i) - cp_vec(i-1)*lowerDia(i) + cp_vec(i) = upperDia(i)/temp + dp_vec(i) = (RightHS(i)-dp_vec(i-1)*lowerDia(i))/temp + END DO + + ! initialized SolnVec + SolnVec(NumEq) = dp_vec(NumEq) + + ! solve for x from the vectors c-prime and d-prime + DO I = NumEq-1, 1,-1 + SolnVec(i) = dp_vec(i) - cp_vec(i)*SolnVec(i+1) + END DO + +END SUBROUTINE Thomas_diagonal + +!--------------------------------------------------------------------------------------------- +SUBROUTINE create_F1_filter (F1_vector, filter1, length_F1_vector,np_x,X_length) +!............................................................................................. +! This function returns the F1 filter function +!............................................................................................. + REAL(ReKi),ALLOCATABLE :: F1_vector(:) + REAL(ReKi) :: filter1(2) + INTEGER :: length_F1_vector + INTEGER :: np_x + REAL(ReKi) :: X_length + + INTEGER :: length_F1_vector_1 + INTEGER :: length_F1_vector_2 + REAL(ReKi),ALLOCATABLE :: F1_vector_1(:) + REAL(ReKi),ALLOCATABLE :: F1_vector_2(:) + INTEGER :: I + + length_F1_vector_1 = floor(filter1(2)*np_x/2) + length_F1_vector_2 = floor(X_length*np_x/2) + length_F1_vector = length_F1_vector_1 + length_F1_vector_2 + ALLOCATE (F1_vector_1(length_F1_vector_1)) + ALLOCATE (F1_vector_2(length_F1_vector_2)) + ALLOCATE (F1_vector (length_F1_vector )) + + F1_vector_1 = ( (1-filter1(1)) /(length_F1_vector_1-1 ) )*[(i,i=1,length_F1_vector_1)]+(0-( (1-filter1(1) )/(length_F1_vector_1-1 ) )) + !r_vector = ( (R_length-delrad)/(n_r_vector-1 ) )*[(i,i=1,n_r_vector)]+(0-( (R_length-delrad)/(n_r_vector-1) )) + F1_vector_2 = 1 + + F1_vector = (/F1_vector_1,F1_vector_2/) + +END SUBROUTINE create_F1_filter + +!--------------------------------------------------------------------------------------------- +SUBROUTINE create_F2_filter (F2_vector, filter2, np_x, length_F1_vector) +!............................................................................................. +! This function returns the F2 filter function +!............................................................................................. + REAL(ReKi),ALLOCATABLE :: F2_vector(:) + REAL(ReKi) :: filter2(2) + INTEGER :: np_x + INTEGER :: length_F1_vector + + REAL(ReKi),ALLOCATABLE :: F2_vector_x(:) + REAL(ReKi),ALLOCATABLE :: F2_vector_1(:) + REAL(ReKi),ALLOCATABLE :: F2_vector_2(:) + INTEGER :: length_F2_vector_x + INTEGER :: length_F2_vector_1 + INTEGER :: length_F2_vector_2 + INTEGER :: length_F2_vector + INTEGER :: I + + length_F2_vector_x = floor(( REAL(length_F1_vector,ReKi) * (1/REAL(np_x,ReKi)) - (2+1/REAL(np_x,ReKi)) ) / (1/REAL(np_x,ReKi)) + 1) + length_F2_vector_1 = 2*np_x + length_F2_vector_2 = length_F2_vector_x + length_F2_vector = length_F2_vector_1 + length_F2_vector_2 + + ALLOCATE ( F2_vector_x(length_F2_vector_x) ) + ALLOCATE ( F2_vector_1(length_F2_vector_1) ) + ALLOCATE ( F2_vector_2(length_F2_vector_2) ) + ALLOCATE ( F2_vector (length_F2_vector ) ) + + F2_vector_x = ( (length_F1_vector * (1/REAL(np_x,ReKi)) - (2+1/REAL(np_x,ReKi))) /(length_F2_vector_x-1 ) )*[(i,i=1,length_F2_vector_x)]+(2+1/REAL(np_x,ReKi)-( (length_F1_vector * (1/REAL(np_x,ReKi)) - (2+1/REAL(np_x,ReKi))) /(length_F2_vector_x-1 ) )) + F2_vector_1 = filter2(1) + + DO I = 1,length_F2_vector_2 + F2_vector_2(I) = 1-(1-filter2(1))*EXP(-filter2(2)*(F2_vector_x(I)-2)) + END DO + + F2_vector = (/F2_vector_1,F2_vector_2/) + +END SUBROUTINE create_F2_filter + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Gauss( AugMatIn, NumEq, SolnVec ) +!.................................................................................................................................. +! This routine uses the Gauss-Jordan elimination method for the solution of +! a given set of simultaneous linear equations. +! NOTE: this routine works if no pivot points are zero and you don't want +! the eschelon or reduced eschelon form of the augmented matrix. The form of +! the original augmented matrix IS preserved in this call. +!.................................................................................................................................. + IMPLICIT NONE + + + ! Passed variables: + + INTEGER(4), INTENT(IN ) :: NumEq ! Number of equations in augmented matrix. + + REAL(ReKi), INTENT(IN ) :: AugMatIn (NumEq,( NumEq + 1 )) ! Augmented matrix passed into this subroutine. + REAL(ReKi), INTENT(OUT) :: SolnVec (NumEq) ! Solution vector. + + + ! Local variables: + + REAL(ReKi) :: AugMat (NumEq,( NumEq + 1 )) ! A copy of the augmented matrix. + + INTEGER(4) :: I ! Steps through columns + INTEGER(4) :: J ! Steps through rows + INTEGER(4) :: L ! Steps through rows + INTEGER(4) :: NAug ! Column dimension of augmented matrix + + + + ! Transfer the data from AugMatIn to AugMat: + + AugMat = AugMatIn + + + ! Find the column dimension of the augmented matrix: + + NAug = NumEq + 1 + + + ! Perform Gauss-Jordan elimination and store the solution vector + ! in the last column of the augmented matrix: + + DO L = 1,NumEq ! Loop through all rows + DO I = ( L + 1 ), NAug ! Loop through all columns above current row number + AugMat(L,I) = AugMat(L,I) / AugMat(L,L) + DO J = 1,NumEq ! Loop through all rows except L + IF ( J /= L ) AugMat(J,I) = AugMat(J,I) - ( AugMat(J,L)*AugMat(L,I) ) + ENDDO ! J - All rows except L + ENDDO ! I - All columns above current row number + ENDDO ! L - All rows + + + ! Transfer the solution vector from AugMat() to SolnVec(): + + SolnVec = AugMat(:,NAug) + + + + RETURN + +END SUBROUTINE Gauss + +!---------------------------------------------------------------------------------------------------------------------------------- +FUNCTION shear_correction (du_dr_dwm,du_dz) +!.................................................................................................................................. +! This function returns the shear correction factor A1 and A2 +!.................................................................................................................................. + IMPLICIT NONE + + REAL(ReKi) :: shear_correction + REAL(ReKi) :: du_dr_dwm + REAL(ReKi) :: du_dz ! du_dz_abl + + ! Internal variables + REAL(ReKi) :: alpha_1 + REAL(ReKi) :: alpha_2 + REAL(ReKi) :: temp_integration + REAL(ReKi) :: correction_factor + REAL(ReKi),ALLOCATABLE :: alpha_array(:) + REAL(ReKi) :: delta_alpha + INTEGER(IntKi) :: I + INTEGER(IntKi) :: temp_n + + alpha_1 = ASIN(du_dr_dwm/du_dz) + alpha_2 = Pi/2 - alpha_1 + temp_integration = 0 + + temp_n = 100 + ALLOCATE ( alpha_array (temp_n) ) + + alpha_array = ((alpha_2-alpha_1)/(temp_n-1))*[(i,i=1,temp_n)]+(alpha_1-((alpha_2-alpha_1)/(temp_n-1))) + delta_alpha = (alpha_2-alpha_1)/(temp_n-1) + + DO I = 1,temp_n + temp_integration = du_dz * SIN(alpha_array(I)) * delta_alpha + temp_integration + END DO + + shear_correction = temp_integration - (alpha_2 - alpha_1) * du_dr_dwm + + IF (ALLOCATED( alpha_array )) DEALLOCATE ( alpha_array ) + +END FUNCTION shear_correction + +!------------------------------------------------------------------------------- +FUNCTION filter_velocity (OS,m,p,u,x,xd,z,y,timestep,y_0,z_0,wake_radius) +!............................................................................... +! This function is called to calculate the filtered wake velocity +! The filter is a low pass filter +! The output is the filtered wake velocity at a certain wake center +!............................................................................... + !USE DWM_Wake_Deficit_Data, ONLY: m%DWDD%ppR + !USE filter_velocity_data + USE InflowWind + + TYPE(DWM_OtherStateType), INTENT(IN ) :: OS + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p + TYPE(DWM_OutputType), INTENT(INOUT) :: y + TYPE(DWM_InputType), INTENT(INOUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + + + REAL(DbKi) :: timestep ! upper limit = usable time + grid width / mean wind speed %%% will change wrt wind speed + ! = second / 0.05 timestep >= 1 + REAL(ReKi) :: y_0 ! wake center point + REAL(ReKi) :: z_0 + INTEGER :: wake_radius ! b(:) in cal_mixl + REAL(ReKi) :: filter_velocity (3) ! only v,w components + + INTEGER :: number_counter ! counter : how many points are in the circle + INTEGER :: radius_length ! wake radius (meters) + INTEGER :: y_axis + INTEGER :: z_axis + REAL(ReKi) :: temp_filter_velocity (3) ! interpolation function, has u,v,w three components + REAL(ReKi) :: temp_wind_velocity (3) + + INTEGER( IntKi ) :: ErrStat ! Error status of the operation + CHARACTER :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + !Print*, y_0 + + temp_filter_velocity = 0.0 + number_counter = 0 + !radius_length = NINT( wake_radius/m%DWDD%ppR*p%RotorR ) ! R(m): turbine radius + radius_length = NINT(2*p%RotorR ) + + IF (.NOT. ALLOCATED(u%IfW%PositionXYZ) ) THEN + CALL AllocAry( u%IfW%PositionXYZ, 3, 1, "Position array to send to IfW_CalcOutput", ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + DO y_axis = NINT(y_0-radius_length),NINT(y_0+radius_length),1 + !IF (y_axis > p%WFLowerBd) THEN ! add 9/25/2014 + DO z_axis = NINT(z_0-radius_length),NINT(z_0+radius_length),1 + IF ( z_axis > p%WFLowerBd ) THEN !(make sure the circle does not exceed wind field) + IF ( ((y_axis-y_0)**2+(z_axis-z_0)**2)**0.5 <= radius_length ) THEN + + + + u%IfW%PositionXYZ(1,1) = 0.0 + u%IfW%PositionXYZ(2,1) = REAL(y_axis,ReKi) + u%IfW%PositionXYZ(3,1) = REAL(z_axis,ReKi) + CALL InflowWind_CalcOutput( timestep, u%IfW, p%IfW, x%IfW, xd%IfW, z%IfW, OS%IfW, y%IfW, m%IfW, ErrStat, ErrMsg ) + temp_wind_velocity (:) = y%IfW%VelocityUVW(:,1) + + !temp_filter_velocity(:) = temp_filter_velocity(:) + AD_WindVelocityWithDisturbance( REAL(timestep,ReKi), A_u, A_p, A_x, A_xd, A_z, A_O, A_y, ErrStat, ErrMsg,& + !(/0.0,REAL(y_axis,ReKi),REAL(z_axis,ReKi)/) ) + temp_filter_velocity(:) = temp_filter_velocity(:) + temp_wind_velocity(:) + + !+ AD_GetUndisturbedWind ( (REAL(timestep,ReKi)), (/0.0,& + !REAL(y_axis,ReKi),REAL(z_axis,ReKi)/), ErrStat) + + ! AD_GetUndisturbedWind ( (REAL(timestep,ReKi)/20.0)-315.0, (/0.0,& + !REAL(y_axis,ReKi),REAL(z_axis,ReKi)/), ErrStat) + number_counter = number_counter + 1 + END IF + END IF + END DO + !END IF + END DO + + filter_velocity (1) = temp_filter_velocity(1) / number_counter + + filter_velocity (2) = temp_filter_velocity(2) / number_counter ! Filtered V velocity in the certain radius circle + + filter_velocity (3) = temp_filter_velocity(3) / number_counter ! Filtered W velocity in the certain radius circle + +END FUNCTION filter_velocity + +!--------------------------------------------------------------------------------- +SUBROUTINE Get_wake_center ( OS, m, p, y, u, x, xd, z, wakewidth, wake_center ) +!................................................................................ +! This routine is called to calculate the wake center of a specific release time +! and flying time wind plane. +! The wake center is passed to the filter to calculate the averaged wind velocity for +! the downstream turbine. +!................................................................................. + !USE DWM_Wake_Deficit_Data, ONLY : m%DWDD%n_x_vector,m%DWDD%ppR + !USE MeanderData + !USE DWM_ParameterType, ONLY : p%WakePosition_1, p%WakePosition_2, p%hub_height, p%TurbRefHt, p%Uambient + !USE BLADE, ONLY : R + !USE AeroDyn_Types + USE InflowWind + + TYPE(DWM_OtherStateType), INTENT(IN ) :: OS + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_OutputType), INTENT(INOUT) :: y + TYPE(DWM_InputType), INTENT(INOUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(DWM_ContinuousStateType), INTENT(INOUT) :: x ! continuous states + TYPE(DWM_DiscreteStateType), INTENT(INOUT) :: xd ! discrete states + TYPE(DWM_ConstraintStateType), INTENT(INOUT) :: z ! constraint states + + REAL(ReKi), ALLOCATABLE, INTENT(INOUT) :: wake_center (:,:,:) !bjj: this is actually y%wake_position + INTEGER, ALLOCATABLE, INTENT(INOUT) :: wakewidth(:) + + ! local variables + + REAL(ReKi) :: Modified_U + INTEGER :: release_time + INTEGER :: flying_time + INTEGER :: simulation_time_length + REAL(DbKi) :: DWM_time_step + REAL(ReKi) :: temp_center_wake (3) + REAL(ReKi) :: temp_velocity (3) + REAL(ReKi) :: U_Scale_Factor + REAL(ReKi) :: U_factor + REAL(ReKi) :: x_step + + INTEGER( IntKi ) :: ErrStat ! Error status of the operation + CHARACTER :: ErrMsg ! Error message if ErrStat /= ErrID_None + + real(ReKi) :: test_1, test_2 + + !------------------------------------------------------------- + !!m%DWDD%n_x_vector = 1700 + !!ALLOCATE (wakewidth(m%DWDD%n_x_vector)) + !!wakewidth = 50 + !!m%DWDD%ppR = 50 + !--------------------------------------------------------------- + + U_factor = 1.00 + + Modified_U = y%Mean_FFWS * U_factor + + + !------------------------------ TEST --------------------------- + !m%DWDD%ppR = 50 + !allocate (wakewidth(1750)) + !wakewidth(:) = 60 + !--------------------------------------------------------------- + + + DWM_time_step = (2*p%RotorR/m%DWDD%ppR)/Modified_U ! resolution (126m/50) / wind speed (8m/s) => make sure there is always a wake width at every time step + ! D/(DWM_time_step*Mean_FFWS)= 50 which is the X resolution + + U_Scale_Factor = Modified_U / (p%Uambient*U_factor) ! modify the wake displacement error caused by the change of Mean_FFWS + + U_Scale_Factor = 1 ! 7.15.2015 + + simulation_time_length = p%WakePosition_1 !80 in reality, 80*scale_factor*DWM_time_step + ! from 1 to 800 (scale_factor : 800/80=10) to 16D (16*50) + m%meandering_data%moving_time = p%WakePosition_2 !50 from 0 to 49 0: wind turbine plane + ! ppR/scale_factor = 5 presents 1D + + + release_time = simulation_time_length + flying_time = m%meandering_data%moving_time + m%meandering_data%scale_factor = 10 ! to decrease the calculation time + ALLOCATE (wake_center (release_time,flying_time+1,3) ) + ! ex. @8D: (1~release_time,8*[ppR/scale_factor]+1,:) + + DO release_time = 1,simulation_time_length,1 ! wake center position at turbine plane + wake_center (release_time,1,1) = 0 + wake_center (release_time,1,2) = 0 + wake_center (release_time,1,3) = REAL(p%hub_height,ReKi) + END DO + + x_step = Modified_U * (DWM_time_step*m%meandering_data%scale_factor) + + IF (.NOT. ALLOCATED(u%IfW%PositionXYZ) ) THEN + CALL AllocAry( u%IfW%PositionXYZ, 3, 1, "Position array to send to IfW_CalcOutput", ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + ! get the initial wake center position of each cross scetion (from the velocity at the turbine plane * dt) + DO release_time=1,simulation_time_length,1 + wake_center (release_time,2,1) = Modified_U * (DWM_time_step*m%meandering_data%scale_factor) +0 + + + !temp_center_wake (:) = AD_WindVelocityWithDisturbance( (REAL(((release_time-1)+1)*DWM_time_step*m%meandering_data%scale_factor,ReKi)), & + !A_u, A_p, A_x, A_xd, A_z, A_O, A_y, ErrStat, ErrMsg, (/0.0,REAL(0,ReKi),REAL(p%TurbRefHt,ReKi)/) ) + !AD_GetUndisturbedWind ( (REAL(((release_time-1)+1)*DWM_time_step*m%meandering_data%scale_factor,ReKi)), (/0.0,& + !REAL(0,ReKi),REAL(p%TurbRefHt,ReKi)/), ErrStat) ! get the velocity at the turbine plane + + u%IfW%PositionXYZ(1,1) = (0.0_ReKi) + u%IfW%PositionXYZ(2,1) = (0.0_ReKi) + u%IfW%PositionXYZ(3,1) = (p%hub_height) + + + CALL InflowWind_CalcOutput( ( ((release_time-1)+1)*DWM_time_step*m%meandering_data%scale_factor), u%IfW, p%IfW, & + x%IfW, xd%IfW, z%IfW, OS%IfW, y%IfW, m%IfW, ErrStat, ErrMsg ) + + temp_center_wake (:) = y%IfW%VelocityUVW(:,1) + !temp_center_wake (3) = y%IfW%Velocity(3,1) + + wake_center (release_time,2,2) = temp_center_wake (2) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,1,2)+ & + local_skew_angle(m%NacYaw, m%ct_tilde, wake_center (release_time,2,1), NINT(m%DWDD%ppR), m%DWDD%ppR) * x_step !+ & + !rotation_lateral_offset( wake_center (release_time,2,1) ) + + wake_center (release_time,2,3) = temp_center_wake (3) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,1,3) + END DO + + + DO flying_time = 2,m%meandering_data%moving_time,1 + DO release_time = 1,simulation_time_length,1 + wake_center (release_time,flying_time+1,1) = wake_center (release_time,flying_time+1-1,1) + Modified_U * (DWM_time_step*m%meandering_data%scale_factor) + + temp_velocity(:) = filter_velocity (OS,m,p,u,x,xd,z,y,((release_time-1)+1)*DWM_time_step*m%meandering_data%scale_factor, wake_center (release_time,flying_time+1-1,2), & + wake_center (release_time,flying_time+1-1,3), wakewidth((flying_time-1)*m%meandering_data%scale_factor) ) + + !!!--------- temp data------ + test_1 = temp_velocity (2) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,flying_time,2)+ & + local_skew_angle(m%NacYaw, m%ct_tilde, wake_center (release_time,flying_time,1), wakewidth((flying_time-1)*m%meandering_data%scale_factor), m%DWDD%ppR) * x_step + test_2 = temp_velocity (3) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,flying_time,3) + !!!------------------------- + + wake_center (release_time,flying_time+1,2) = temp_velocity (2) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,flying_time,2)+ & + local_skew_angle(m%NacYaw, m%ct_tilde, wake_center (release_time,flying_time,1), wakewidth((flying_time-1)*m%meandering_data%scale_factor), m%DWDD%ppR) * x_step !+ & + !rotation_lateral_offset( wake_center (release_time,flying_time+1,1) ) - & + !rotation_lateral_offset( wake_center (release_time,flying_time, 1) ) + + wake_center (release_time,flying_time+1,3) = temp_velocity (3) * (DWM_time_step*m%meandering_data%scale_factor) * U_Scale_Factor + wake_center (release_time,flying_time,3) + + + END DO + END DO + + + +END SUBROUTINE Get_wake_center + +!------------------------------------------------------------------------------------------------ +FUNCTION shifted_velocity( ZTime, p, m, y, z, upwind_mean_u, Uwake, WakeCenter,spacing,angle) +!............................................................................ +! This routine is called to get the DWM wake velocity at a certain point in the downstream turbine plane +! Consideirng the meandered wake center +! Uwake(:) is the axial velocity of the wake at the downstream turbine plane +! WakeCenter(:,:,:) is the wake center (y,z) at the downstream turbine plane +!............................................................................ + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !USE SimCont, ONLY: ZTime + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + !USE DWM_Wake_Deficit_Data, ONLY: m%DWDD%ppR + !USE DWM_ParameterType, ONLY: p%Wind_file_Mean_u,p%hub_height,p%TurbRefHt + + TYPE(DWM_MiscVarType), INTENT(IN ) :: m + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + + REAL(DbKi), INTENT(IN ) :: ZTime + REAL(ReKi), intent(in) :: y,z ! point location on the y,z axis + REAL(ReKi), intent(in) :: Uwake(:) ! axial velocity of the wake at the downstream turbine plane + REAL(ReKi), intent(in) :: upwind_mean_u ! the mean velocity of the turbine UPstream + REAL(ReKi), intent(in) :: WakeCenter(:,:,:) ! wake_center + REAL(ReKi), intent(in) :: spacing ! the distance from the downstream turbine to the upstream turbine + REAL(ReKi), intent(in) :: angle ! the angle between the investigated turbine and the line connecting the upwind turbine and wind origin + + REAL(ReKi) :: shifted_velocity ! the output + ! the velocity at a certain point + + REAL(ReKi) :: distance ! the distance from the point to the meandered wake center + REAL(ReKi) :: y0 ! wake center position on y axis + REAL(ReKi) :: z0 ! wake center position on z axis + REAL(ReKi) :: unit ! single unit length R/ppR + REAL(ReKi) :: scale_factor + INTEGER :: p1 + INTEGER :: p2 + INTEGER :: time_position ! to define which plane's wake center is used + REAL(ReKi) :: Yshifted + REAL(ReKi) :: Zshifted + + + !ALLOCATE (Uwake(NINT( m%DWDD%ppR*Rdomain ))) ! the axis symmetrical velocity + !ALLOCATE (WakeCenter( size_of_WakeCenter1,size_of_WakeCenter2,3 )) + + scale_factor = 10 + + time_position = floor(ZTime/( (2*p%RotorR/p%p_p_r/upwind_mean_u/1.00)*scale_factor ))+1 ! ZTime/(DWM_time_step*scale_factor) + + + + y0 = WakeCenter(time_position,FLOOR(spacing*p%p_p_r/scale_factor)+1,2) !+ 2*P%RotorR*spacing*TAN(m%skew_angle) + z0 = WakeCenter(time_position,FLOOR(spacing*p%p_p_r/scale_factor)+1,3) !! - REAL(p%TurbRefHt-p%hub_height) + + Yshifted = y + 2*p%RotorR*spacing*TAN(angle*Pi/180) + Zshifted = z + + distance = ( (Yshifted-y0)**2 + (Zshifted-z0)**2 )**(0.5) + unit=p%RotorR / p%p_p_r + + p1=FLOOR(distance/unit) + p2=p1+1 + IF (p1>0) THEN + shifted_velocity = Uwake(p1)+( Uwake(p2)-Uwake(p1) )*( (distance/unit)-p1 ) ! Weighting method + ELSE + shifted_velocity = Uwake(p2) + END IF + +END FUNCTION shifted_velocity + +!---------------------------------------------------------------------------------- +SUBROUTINE smooth_out_wake(m, p, Uvelocity,Uwake_center,wake_array,spacing,angle,velocity_matrix) +!.................................................................................. +! This routine is called to fillter out the smoothed out upstream wake profile +! The output is the wake_array +! Which is the axisymmetrical wake velocity profile +!.................................................................................. + !USE DWM_Wake_Deficit_Data, ONLY: m%DWDD%n_x_vector, m%DWDD%n_r_vector, m%DWDD%ppR + !USE DWM_ParameterType, ONLY: p%hub_height, p%WakePosition_1 + !USE smooth_out_wake_data, ONLY: m%SmoothOut%length_velocity_array + + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + + REAL(ReKi),ALLOCATABLE :: Uvelocity(:,:) + REAL(ReKi),ALLOCATABLE :: Uwake_center(:,:,:) + REAL(ReKi) :: wake_array(:) + REAL(ReKi) :: spacing ! the spacing between two turbines + REAL(ReKi) :: angle ! the angle between the downwind turbine and the line conneting the upwind(investigated) turbine and the wind origin + REAL(ReKi) :: velocity_matrix(:,:) ! the velocity matrix that store the velocity of the downstream turbine plane + + INTEGER,ALLOCATABLE :: counter_array(:) + REAL(ReKi),ALLOCATABLE :: velocity_array(:) + !INTEGER :: m%SmoothOut%length_velocity_array ! the length of velocity_array + INTEGER :: low + INTEGER :: high + INTEGER :: i,j,k,n + INTEGER :: counter + REAL(ReKi) :: y ! y coordinate + REAL(ReKi) :: z ! z coordinate + + !m%SmoothOut%length_velocity_array = NINT(1.2*R) + + !ALLOCATE ( Uvelocity(m%DWDD%n_x_vector,m%DWDD%n_r_vector) ) + !ALLOCATE ( Uwake_center(release_time,flying_time+1,3) ) + IF (ALLOCATED( velocity_array )) DEALLOCATE ( velocity_array ) + IF (ALLOCATED( counter_array )) DEALLOCATE ( counter_array ) + ALLOCATE ( velocity_array (m%SmoothOut%length_velocity_array) ) + !ALLOCATE ( velocity_matrix (2*m%SmoothOut%length_velocity_array,2*m%SmoothOut%length_velocity_array) ) ! twice the size of the velocity array + ALLOCATE ( counter_array (m%SmoothOut%length_velocity_array) ) + !ALLOCATE ( wake_array (p%ElementNum) ) + + velocity_array=0 + velocity_matrix = 0 + counter=0 + counter_array=0 + + !------------------------------------------------------------------------------------------------- + ! get the time averaged velocity matrix + !------------------------------------------------------------------------------------------------- + DO i=1,p%WakePosition_1,1 + DO j=1,2*m%SmoothOut%length_velocity_array,1 ! y axis + DO k=1,2*m%SmoothOut%length_velocity_array,1 ! z axis + y = (0-m%SmoothOut%length_velocity_array) + (j-1) ! y coordinate + z = (p%hub_height-m%SmoothOut%length_velocity_array) + (k-1) ! z coordinate + velocity_matrix(j,k) = velocity_matrix(j,k) + smooth_wake_shifted_velocity( m, p, y, z, Uvelocity(floor(spacing * m%DWDD%ppR)+1,:), Uwake_center(:,:,:),spacing,i,angle) + !velocity_matrix(j,k) = velocity_matrix(j,k) + smooth_wake_shifted_velocity( y, z, Uvelocity(floor(4.4 * m%DWDD%ppR)+1,:), Uwake_center(:,:,:),4.4,i) + END DO + END DO + counter = counter+1 + END DO + + velocity_matrix = velocity_matrix / counter + + !------------------------------------------------------------------------------------------------- + ! get the time averaged axisymmetrical velocity array + !------------------------------------------------------------------------------------------------- + DO i=1,m%SmoothOut%length_velocity_array,1 ! velocity array + DO j=1,2*m%SmoothOut%length_velocity_array,1 ! velocity_matrix (j,:) + DO k=1,2*m%SmoothOut%length_velocity_array,1 ! velocity_matrix (:,k) + y = (0-m%SmoothOut%length_velocity_array) + (j-1) ! y coordinate + z = (p%hub_height-m%SmoothOut%length_velocity_array) + (k-1) ! z coordinate + IF ( ((y-0)**2+(z-p%hub_height)**2)**0.5>(i-1) .and. ((y-0)**2+(z-p%hub_height)**2)**0.5<=i) THEN + velocity_array(i) = velocity_array(i)+velocity_matrix(j,k) + counter_array(i) = counter_array(i)+1 + END IF + END DO + END DO + END DO + + DO i=1,m%SmoothOut%length_velocity_array,1 + velocity_array(i) = velocity_array(i) / counter_array(i) + END DO + + !------------------------------------------------------------------------------------------------- + ! get the wake array at the RELM node point + !------------------------------------------------------------------------------------------------- + + DO i=1,p%ElementNum,1 + low = FLOOR(p%ElementRad(i)) + high = low+1 + wake_array(i) = velocity_array(low) + ( velocity_array(high)-velocity_array(low) )*(p%ElementRad(i)-low) ! Weighting method + END DO + +END SUBROUTINE smooth_out_wake + +!------------------------------------------------------------------------------------------------ +FUNCTION smooth_wake_shifted_velocity( m, p, y_coor, z_coor, Uwake, WakeCenter,spacing,time_position,angle) +!............................................................................ +! This routine is called to get the DWM wake velocity at a certain point in the downstream turbine plane +! Consideirng the meandered wake center +! Uwake(:) is the axial velocity of the wake at the downstream turbine plane +! WakeCenter(:,:,:) is the wake center +! Used to calculate the smoothed out wake profile +! (y,z) at the downstream turbine plane +!............................................................................ + + !USE DWM_ParameterType, ONLY: p%p_p_r, p%hub_height, p%TurbRefHt + !USE MeanderData, ONLY: m%meandering_data%scale_factor + + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + + REAL(ReKi) :: y_coor,z_coor ! point location on the y,z axis + REAL(ReKi) :: Uwake(:) ! axial velocity of the wake at the downstream turbine plane + REAL(ReKi) :: WakeCenter(:,:,:) ! wake_center + REAL(ReKi) :: spacing ! the distance from the downstream turbine to the upstream turbine + INTEGER :: time_position ! to define which plane's wake center is used + REAL(ReKi) :: angle ! the angle between the downwind turbine and the line conneting the upwind(investigated) turbine and the wind origin + + REAL(ReKi) :: smooth_wake_shifted_velocity ! the output + ! the velocity at a certain point + REAL(ReKi) :: Yshifted + REAL(ReKi) :: Zshifted + + INTEGER :: p1 + INTEGER :: p2 + REAL(ReKi) :: distance ! the distance from the point to the meandered wake center + REAL(ReKi) :: y0 ! wake center position on y axis + REAL(ReKi) :: z0 ! wake center position on z axis + REAL(ReKi) :: unit ! single unit length R/ppR + + y0 = WakeCenter(time_position,FLOOR(spacing*p%p_p_r/m%meandering_data%scale_factor)+1,2) !+ 2*P%RotorR*spacing*TAN(m%skew_angle) + z0 = WakeCenter(time_position,FLOOR(spacing*p%p_p_r/m%meandering_data%scale_factor)+1,3) !!- REAL(p%TurbRefHt-p%hub_height) + + Yshifted = y_coor + 2*p%RotorR*spacing*TAN(angle*Pi/180) + Zshifted = z_coor + + distance = ( (Yshifted-y0)**2 + (Zshifted-z0)**2 )**(0.5) + unit=p%RotorR/p%p_p_r + + p1=FLOOR(distance/unit) + p2=p1+1 + IF (p1>0) THEN + smooth_wake_shifted_velocity = Uwake(p1)+( Uwake(p2)-Uwake(p1) )*( (distance/unit)-p1 ) ! Weighting method + ELSE + smooth_wake_shifted_velocity = Uwake(p2) + END IF + + +END FUNCTION smooth_wake_shifted_velocity +!---------------------------------------------------------------------------------- +FUNCTION TI_downstream_total (m, p, y, spacing,angle,velocity_matrix) ! name should be calculate_TI_downstream +!.................................................................................. +! This subroutine is called to calculate the TI of the wake deficit +! The method is by the paper of Rolf-Erik +! The output is TI_downstream_matrix which is the TI for each computating node in the DWM domain +!.................................................................................. + !USE DWM_Wake_Deficit_Data, ONLY: m%DWDD%Turb_Stress_DWM, m%DWDD%n_x_vector, m%DWDD%n_r_vector, m%DWDD%ppR + !USE DWM_OutputType, ONLY: m%wake_position,m%wake_u + !USE MeanderData, ONLY: m%meandering_data%moving_time, m%meandering_data%scale_factor + !USE DWM_ParameterType, ONLY: p%TI_amb, p%hub_height,p%TurbRefHt,p%Uambient,p%WakePosition_1 + !USE smooth_out_wake_data, ONLY: m%SmoothOut%length_velocity_array + !USE BLADE, ONLY: R + + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + REAL(ReKi) :: TI_downstream_total ! TI of a downstream turbine + REAL(ReKi) :: spacing ! the spacing between the downwind turbine and this upwind turbine + REAL(ReKi) :: angle ! the angle between the downwind turbine and the line connecting this upwind turbine and the wind direction + REAL(ReKi) :: velocity_matrix(:,:) ! the velocity matrix at the certain downswind turbine + + ! local variables + REAL(ReKi), ALLOCATABLE :: TI_downstream_matrix(:,:) + INTEGER :: i,j,k + INTEGER :: cross_plane_position_ds ! the cross plane position which to be investigated in term of the flying time + INTEGER :: cross_plane_position_TI ! the cross plane position which to be investigated in term of the m%DWDD%n_x_vector + INTEGER :: distance_index ! the index of the distance in the TI axisymmetric array + INTEGER :: counter1 + INTEGER :: counter2 + INTEGER :: initial_timestep + REAL(ReKi) :: y_axis_turbine + REAL(ReKi) :: z_axis_turbine + REAL(ReKi) :: distance ! the distance between one point to the meandered wake center + REAL(ReKi) :: TI_downstream_node ! the TI at a specfic point in the inbestigated cross plane + REAL(ReKi) :: TI_node_temp + REAL(ReKi) :: TI_node + REAL(ReKi) :: TI_accumulation + REAL(ReKi) :: TI_apprant_accumulation + REAl(ReKi) :: TI_average ! THE AVERAGE TI OF THE CROSS PLANE + REAL(ReKi) :: TI_apprant ! The TI due to the meadering + REAL(ReKi) :: HubHt + REAL(ReKi) :: wake_center_y + REAL(ReKi) :: wake_center_z + REAL(ReKi) :: Rscale + REAL(ReKi) :: y_coor + REAL(ReKi) :: z_coor + REAL(ReKi) :: zero_spacing + REAL(ReKi) :: temp1,temp2,temp3 + REAL(ReKi) :: c_uw + + !------------------------------------------------------------------------------------------------- + ! calculate the TI at each node at the downstream turbine plane from the wake deficit calculation + !------------------------------------------------------------------------------------------------- + IF (ALLOCATED( TI_downstream_matrix )) DEALLOCATE ( TI_downstream_matrix ) + ALLOCATE (TI_downstream_matrix(m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + c_uw = (0.7550 - m%TI_original/100 *1.75) / 2 + + DO i=1,m%DWDD%n_x_vector + DO j=1,m%DWDD%n_r_vector + TI_downstream_matrix(i,j) = abs( ( 1/c_uw *m%DWDD%Turb_Stress_DWM(i,j) ) )**0.5 + END DO + END DO + + !------------------------------------------------------------------------------------------------- + ! calculate the TI of the downstream turbine grid considering the meandering effect + !------------------------------------------------------------------------------------------------- + cross_plane_position_TI = ANINT( m%DWDD%ppR*spacing+1 ) + !cross_plane_position_TI = ANINT( m%DWDD%ppR*4.4+1 ) + cross_plane_position_ds = ANINT( (m%DWDD%ppR/m%meandering_data%scale_factor)*spacing+1 ) ! the moving time index of the cross plane in the wake_position(:,:,:) + !cross_plane_position_ds = ANINT( (m%DWDD%ppR/m%meandering_data%scale_factor)*4.4+1 ) + + Rscale = 2 !1.3 + HubHt = p%hub_height + counter1 = 0 + counter2 = 0 + TI_accumulation = 0 + TI_apprant_accumulation = 0 + + DO i=1,p%WakePosition_1,1 + DO j=NINT(HubHt-Rscale*p%RotorR),NINT(HubHt+Rscale*p%RotorR),1 ! Z direction + DO k=1,NINT(2*Rscale*p%RotorR)+1,1 ! Y direction + y_axis_turbine = k-(p%RotorR+1) + 2*p%RotorR*spacing*TAN(angle*Pi/180) ! shift effect + z_axis_turbine = j + + wake_center_y=y%wake_position(i,cross_plane_position_ds,2) !+ 2*P%RotorR*spacing*TAN(m%skew_angle) + wake_center_z=y%wake_position(i,cross_plane_position_ds,3) !!- REAL(p%TurbRefHt-p%hub_height,ReKi) + + distance = ( (y_axis_turbine-wake_center_y)**2 + (z_axis_turbine-wake_center_z)**2)**0.5 + + distance_index = FLOOR(distance/(p%RotorR/m%DWDD%ppR)) + 1 + + TI_node_temp = TI_downstream_matrix( cross_plane_position_TI,distance_index ) + + IF ( TI_node_temp > (y%TI/100*(y%Mean_FFWS/p%Uambient)) ) THEN + TI_node = TI_node_temp + ELSE + TI_node = y%TI/100*(y%Mean_FFWS/p%Uambient) + END IF + + TI_accumulation = TI_accumulation + TI_node + counter1 = counter1+1 + + END DO + END DO + END DO + + TI_average = TI_accumulation / REAL(counter1,ReKi) + + !------------------------------------------------------------------------------------------------- + ! calculate the apprant TI due to the meadering + !------------------------------------------------------------------------------------------------- + zero_spacing = 0 + initial_timestep = 1 + !ALLOCATE (velocity_matrix(2*m%SmoothOut%length_velocity_array,2*m%SmoothOut%length_velocity_array)) + + DO i=1,2*m%SmoothOut%length_velocity_array,1 ! velocity_matrix (i,:) + DO j=1,2*m%SmoothOut%length_velocity_array,1 ! velocity_matrix (i,:) + y_coor = (0-m%SmoothOut%length_velocity_array) + (i-1) ! y coordinate + z_coor = (p%hub_height-m%SmoothOut%length_velocity_array) + (j-1) ! z coordinate + TI_apprant_accumulation = TI_apprant_accumulation + & + !(smooth_wake_shifted_velocity(y,z,m%wake_u(floor(spacing_turbine * m%DWDD%ppR)+1,:), m%wake_position(:,:,:),spacing_turbine,k) - & + !velocity_matrix(i,j))**2 + (velocity_matrix(i,j) - & + smooth_wake_shifted_velocity(m, p, y_coor, z_coor, y%wake_u(floor(spacing * m%DWDD%ppR)+1,:), y%wake_position(:,:,:),zero_spacing,initial_timestep,angle))**2 + !smooth_wake_shifted_velocity(y,z,m%wake_u(floor(4.4 * m%DWDD%ppR)+1,:), m%wake_position(:,:,:),zero_spacing,initial_timestep))**2 + counter2=counter2+1 + END DO + END DO + + TI_apprant = ((TI_apprant_accumulation / REAL(counter2,ReKi))**0.5) + + + !------------------------------------------------------------------------------------------------- + ! calculate the total TI + !------------------------------------------------------------------------------------------------- + !TI_downstream_total = (TI_average**2 + TI_apprant**2)**0.5*100 + + TI_downstream_total = TI_average * 100 + + !OPEN(unit = 10, status='replace',file='DWM\results\Downstream_TI_b4normalization.bin',form='unformatted') + !WRITE(10) TI_total + !CLOSE(10) + + !open (unit=25,file="D:\5MW_simulation\after_release\results\TI.txt") + !write (25,'(f13.7)'), TI_total + + !print*, TI_downstream_matrix(300,120) + +END FUNCTION TI_downstream_total + +!---------------------------------------------------------------------------------- +FUNCTION smallscale_TI (m, p, y, spacing,angle,velocity_matrix) +!.................................................................................. +! This subroutine is called to calculate the smalle scale TI of the wake deficit +! +! +!.................................................................................. + !USE DWM_Wake_Deficit_Data, ONLY: m%DWDD%Turb_Stress_DWM, m%DWDD%n_x_vector, m%DWDD%n_r_vector, m%DWDD%ppR + !USE DWM_OutputType, ONLY: m%wake_position,m%wake_u + !USE MeanderData, ONLY: m%meandering_data%moving_time, m%meandering_data%scale_factor + !USE DWM_ParameterType, ONLY: p%TI_amb, p%hub_height,p%TurbRefHt,p%Uambient,p%WakePosition_1 + !USE smooth_out_wake_data, ONLY: m%SmoothOut%length_velocity_array + !USE BLADE, ONLY: R + + TYPE(DWM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + REAL(ReKi) :: spacing ! the spacing between the downwind turbine and this upwind turbine + REAL(ReKi) :: angle ! the angle between the downwind turbine and the line connecting this upwind turbine and the wind direction + REAL(ReKi) :: velocity_matrix(:,:) ! the velocity matrix at the certain downswind turbine + REAL(ReKi) :: smallscale_TI + + ! local variables + REAL(ReKi), ALLOCATABLE :: TI_downstream_matrix(:,:) + INTEGER :: i,j,k + INTEGER :: cross_plane_position_ds ! the cross plane position which to be investigated in term of the flying time + INTEGER :: cross_plane_position_TI ! the cross plane position which to be investigated in term of the m%DWDD%n_x_vector + INTEGER :: distance_index ! the index of the distance in the TI axisymmetric array + INTEGER :: counter1 + INTEGER :: counter2 + INTEGER :: initial_timestep + REAL(ReKi) :: y_axis_turbine + REAL(ReKi) :: z_axis_turbine + REAL(ReKi) :: distance ! the distance between one point to the meandered wake center + REAL(ReKi) :: TI_downstream_node ! the TI at a specfic point in the inbestigated cross plane + REAL(ReKi) :: TI_node_temp + REAL(ReKi) :: TI_node + REAL(ReKi) :: TI_accumulation + REAL(ReKi) :: TI_apprant_accumulation + REAl(ReKi) :: TI_average ! THE AVERAGE TI OF THE CROSS PLANE + REAL(ReKi) :: TI_apprant ! The TI due to the meadering + REAL(ReKi) :: HubHt + REAL(ReKi) :: wake_center_y + REAL(ReKi) :: wake_center_z + REAL(ReKi) :: Rscale + REAL(ReKi) :: y_coor + REAL(ReKi) :: z_coor + REAL(ReKi) :: zero_spacing + REAL(ReKi) :: temp1,temp2,temp3 + + !------------------------------------------------------------------------------------------------- + ! calculate the TI at each node at the downstream turbine plane from the wake deficit calculation + !------------------------------------------------------------------------------------------------- + IF (ALLOCATED( TI_downstream_matrix )) DEALLOCATE ( TI_downstream_matrix ) + ALLOCATE (TI_downstream_matrix(m%DWDD%n_x_vector,m%DWDD%n_r_vector)) + + DO i=1,m%DWDD%n_x_vector + DO j=1,m%DWDD%n_r_vector + TI_downstream_matrix(i,j) = abs( ( 10/3*m%DWDD%Turb_Stress_DWM(i,j) ) )**0.5 + END DO + END DO + + !------------------------------------------------------------------------------------------------- + ! calculate the TI of the downstream turbine grid considering the meandering effect + !------------------------------------------------------------------------------------------------- + cross_plane_position_TI = ANINT( m%DWDD%ppR*spacing+1 ) + !cross_plane_position_TI = ANINT( m%DWDD%ppR*4.4+1 ) + cross_plane_position_ds = ANINT( (m%DWDD%ppR/m%meandering_data%scale_factor)*spacing+1 ) ! the moving time index of the cross plane in the wake_position(:,:,:) + !cross_plane_position_ds = ANINT( (m%DWDD%ppR/m%meandering_data%scale_factor)*4.4+1 ) + + Rscale = 2 !1.3 + HubHt = p%hub_height + counter1 = 0 + counter2 = 0 + TI_accumulation = 0 + TI_apprant_accumulation = 0 + + DO i=1,p%WakePosition_1,1 + DO j=NINT(HubHt-Rscale*p%RotorR),NINT(HubHt+Rscale*p%RotorR),1 ! Z direction + DO k=1,NINT(2*Rscale*p%RotorR)+1,1 ! Y direction + y_axis_turbine = k-(p%RotorR+1) + 2*p%RotorR*spacing*TAN(angle*Pi/180) ! shift effect + z_axis_turbine = j + + wake_center_y=y%wake_position(i,cross_plane_position_ds,2) !+ 2*P%RotorR*spacing*TAN(m%skew_angle) + wake_center_z=y%wake_position(i,cross_plane_position_ds,3) !!- REAL(p%TurbRefHt-p%hub_height) + + distance = ( (y_axis_turbine-wake_center_y)**2 + (z_axis_turbine-wake_center_z)**2)**0.5 + + distance_index = FLOOR(distance/(p%RotorR/m%DWDD%ppR)) + 1 + + TI_node_temp = TI_downstream_matrix( cross_plane_position_TI,distance_index ) + + IF ( TI_node_temp > (y%TI/100*(y%Mean_FFWS/p%Uambient)) ) THEN + TI_node = TI_node_temp + ELSE + TI_node = y%TI/100*(y%Mean_FFWS/p%Uambient) + END IF + + TI_accumulation = TI_accumulation + TI_node + counter1 = counter1+1 + + END DO + END DO + END DO + + TI_average = TI_accumulation / REAL(counter1, ReKi) + + smallscale_TI = TI_average * 100 + +END FUNCTION smallscale_TI + +!------------------------------------------------------------------------------------------------ +SUBROUTINE read_parameter_file( p ) +!............................................................................ +! This routine is called to read the parameter file from the DWM simulation of upstream turbine +! read wake velocity @ the downstream turbine from the upstream wake +! read the meandered wake center +! read the mean velocity of the upstream turbine +!............................................................................ + TYPE(DWM_ParameterType), INTENT(INOUT) :: p + INTEGER :: OPENNUM + INTEGER ErrStat + + CALL GetNewUnit(OPENNUM) + + OPEN(unit = OPENNUM, status='old',file='DWM-driver'//trim(PathSep)//'DWM_parameter.bin',form='unformatted',IOSTAT=ErrStat) ! open an existing file + IF (ErrStat /= 0) CALL ProgAbort('Error opening existing file, "'//'DWM-driver'//trim(PathSep)//'DWM_parameter.bin"' ) + + READ(OPENNUM) p%hub_height, p%RotorR, p%NumWT, p%Uambient, & + p%TI_amb, p%r_domain, p%x_domain, p%p_p_r, & + p%WakePosition_1, p%WakePosition_2, p%WFLowerBd, & + p%Winddir + CLOSE(OPENNUM) ! close the file + + p%Tinfluencer = 1 + + + +END SUBROUTINE read_parameter_file + +!---------------------------------------------------------------------------------- +SUBROUTINE read_turbine_position( m, p, u ) +!.................................................................................. +! This routine is called at the first of the FAST. +! To decide the position of the turbine in a row +! if it is the first turbine or not +!.................................................................................. + + TYPE(DWM_ParameterType), INTENT(INOUT) :: p + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_InputType), INTENT(INOUT) :: u + + + INTEGER(IntKi) :: N_ARGU + CHARACTER(20) :: SimulationOrder_index_char + !USE read_turbine_position_data + !USE DWM_ParameterType, ONLY: p%NumWT,p%Tinfluencer + + + + INTEGER :: I,J + INTEGER :: MyUn + + N_ARGU = COMMAND_ARGUMENT_COUNT() + IF (N_ARGU < 2) THEN + CALL ProgAbort('Incorrect number of command arguments in DWM. Arg_1=InputFileName, Arg_2=SimulationOrder_Index, Arg_n="DWM"') + END IF + + + CALL GET_COMMAND_ARGUMENT(2, SimulationOrder_index_char) + !print*,SimulationOrder_index_char + READ(SimulationOrder_index_char,*) p%RTPD%SimulationOrder_index + !print*,p%RTPD%SimulationOrder_index + !CALL WrScr(' simulation order index = '//TRIM(Num2LStr(p%RTPD%SimulationOrder_index) ) + + CALL GetNewUnit(MyUn) + + IF ( p%RTPD%SimulationOrder_index /= 0 ) THEN ! exclude the base turbine + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! obtain the wind turbine index + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + ALLOCATE (p%RTPD%Turbine_sort_order(p%NumWT)) + OPEN(unit = MyUn, status='old',file='DWM-results'//trim(PathSep)//'wind_farm_turbine_sort.bin',form='unformatted') ! open an existing file + READ(MyUn) p%RTPD%Turbine_sort_order + CLOSE(MyUn) ! close the file + + + p%RTPD%WT_index = p%RTPD%Turbine_sort_order(p%RTPD%SimulationOrder_index) + + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + !''''''''''''''''''''''''''''''''''''UPWIND DIRECTION'''''''''''''''''''''''''''''''''''''' + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! obtain the index of upwind turbines that affecting this turbine, and the distance/angle + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + IF (p%RTPD%SimulationOrder_index > 0) THEN + ALLOCATE (p%RTPD%TurbineInfluenceData(p%NumWT,p%Tinfluencer ) ) + + OPEN(unit = MyUn, status='old',file='DWM-results'//trim(PathSep)//'turbine_interaction.bin',form='unformatted') + READ(MyUn) p%RTPD%TurbineInfluenceData + CLOSE(MyUn) + + ! obtain the upwind turbine index + ALLOCATE (p%RTPD%upwind_turbine_index(p%Tinfluencer)) + DO I = 1,p%Tinfluencer + p%RTPD%upwind_turbine_index(I) = p%RTPD%TurbineInfluenceData(p%RTPD%WT_index,I) + END DO + + ! calculate the number of upwind turbines affecting the downwind turbine + p%RTPD%upwindturbine_number = 0 + DO I = 1,p%Tinfluencer + IF (p%RTPD%upwind_turbine_index(I) /=0) THEN + p%RTPD%upwindturbine_number = p%RTPD%upwindturbine_number + 1 + END IF + END DO + + ! obtain the upwind turbine coordinates + ALLOCATE (p%RTPD%wind_farm_Xcoor (p%NumWT)) + ALLOCATE (p%RTPD%wind_farm_Ycoor (p%NumWT)) + + OPEN(unit = MyUn, status='old',file='DWM-driver'//trim(PathSep)//'wind_farm_coordinate.bin',form='unformatted') + READ(MyUn) p%RTPD%wind_farm_Xcoor,p%RTPD%wind_farm_Ycoor + CLOSE(MyUn) + + + IF (p%RTPD%upwindturbine_number /= 0) THEN + ALLOCATE(p%RTPD%upwind_turbine_Xcoor(p%RTPD%upwindturbine_number)) + ALLOCATE(p%RTPD%upwind_turbine_Ycoor(p%RTPD%upwindturbine_number)) + DO I = 1,p%RTPD%upwindturbine_number + p%RTPD%upwind_turbine_Xcoor(I) = p%RTPD%wind_farm_Xcoor(p%RTPD%upwind_turbine_index(I)) + p%RTPD%upwind_turbine_Ycoor(I) = p%RTPD%wind_farm_Ycoor(p%RTPD%upwind_turbine_index(I)) + END DO + END IF + + ! obtain the distance beween the upwind turbine and this turbine + ALLOCATE (p%RTPD%turbine_windorigin_length (p%NumWT )) + + OPEN(unit = MyUn, status='old',file='DWM-results'//trim(PathSep)//'turbine_distance.bin',form='unformatted') + READ(MyUn) p%RTPD%turbine_windorigin_length + CLOSE(MyUn) + + + IF (p%RTPD%upwindturbine_number /= 0) THEN + ALLOCATE (p%RTPD%upwind_turbine_projected_distance(p%RTPD%upwindturbine_number)) + DO I = 1,p%RTPD%upwindturbine_number + p%RTPD%upwind_turbine_projected_distance(I) = p%RTPD%turbine_windorigin_length(p%RTPD%WT_index) - p%RTPD%turbine_windorigin_length(p%RTPD%upwind_turbine_index(I)) + END DO + END IF + + + ! obtain the angle beween the line connecting the upwind turbine and this turbine and the wind direction vector + ALLOCATE (p%RTPD%turbine_angle(p%NumWT,p%NumWT)) + + OPEN(unit = MyUn, status='old',file='DWM-results'//trim(PathSep)//'turbine_angles.bin',form='unformatted') + READ(MyUn) p%RTPD%turbine_angle + CLOSE(MyUn) + + IF (p%RTPD%upwindturbine_number /= 0) THEN + ALLOCATE (p%RTPD%upwind_align_angle(p%RTPD%upwindturbine_number)) + DO I = 1,p%RTPD%upwindturbine_number + p%RTPD%upwind_align_angle(I) = p%RTPD%turbine_angle(p%RTPD%upwind_turbine_index(I),p%RTPD%WT_index) + END DO + END IF + + END IF + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + !''''''''''''''''''''''''''''''''''DOWNWIND DIRECTION'''''''''''''''''''''''''''''''''''''' + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! obtain the index of downwind turbines that being affected by this turbine, and the distance/angle + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + IF (p%RTPD%SimulationOrder_index/=p%NumWT) THEN ! WHEN index = 0, there will not such files (which are generated by the 0 turbine) + + ! obtain the downwind turbine index and calculate the downwind turbine numbers + p%RTPD%downwindturbine_number = 0 + ALLOCATE (p%RTPD%downwind_turbine_index(p%NumWT-1)) + DO I = 1,p%Tinfluencer + DO J = 1,p%NumWT + IF (p%RTPD%TurbineInfluenceData(J,I) == p%RTPD%WT_index) THEN + p%RTPD%downwindturbine_number = p%RTPD%downwindturbine_number + 1 + p%RTPD%downwind_turbine_index(p%RTPD%downwindturbine_number) = J + END IF + END DO + END DO + + ! obtain the downwind turbine coordinates + IF (p%RTPD%downwindturbine_number /= 0) THEN + ALLOCATE(p%RTPD%downwind_turbine_Xcoor(p%RTPD%downwindturbine_number)) + ALLOCATE(p%RTPD%downwind_turbine_Ycoor(p%RTPD%downwindturbine_number)) + DO I = 1,p%RTPD%downwindturbine_number + p%RTPD%downwind_turbine_Xcoor(I) = p%RTPD%wind_farm_Xcoor(p%RTPD%downwind_turbine_index(I)) + p%RTPD%downwind_turbine_Ycoor(I) = p%RTPD%wind_farm_Ycoor(p%RTPD%downwind_turbine_index(I)) + END DO + END IF + + ! obtain the distance beween the upwind turbine and this turbine + IF (p%RTPD%downwindturbine_number/=0) THEN + ALLOCATE (p%RTPD%downwind_turbine_projected_distance(p%RTPD%downwindturbine_number)) + DO I = 1,p%RTPD%downwindturbine_number + p%RTPD%downwind_turbine_projected_distance(I) = p%RTPD%turbine_windorigin_length(p%RTPD%downwind_turbine_index(I)) - p%RTPD%turbine_windorigin_length(p%RTPD%WT_index) + END DO + END IF + + ! obtain the angle beween the line connecting the downwind turbine and this turbine and the wind direction vector + IF (p%RTPD%downwindturbine_number/=0) THEN + ALLOCATE (p%RTPD%downwind_align_angle(p%RTPD%downwindturbine_number)) + DO I = 1,p%RTPD%downwindturbine_number + p%RTPD%downwind_align_angle(I) = p%RTPD%turbine_angle(p%RTPD%WT_index,p%RTPD%downwind_turbine_index(I)) + END DO + END IF + + END IF + END IF + + ! check if the Meandering_Moving_time is valid + DO I = 1,p%RTPD%downwindturbine_number + IF (p%WakePosition_2 < p%RTPD%downwind_turbine_projected_distance(I) * p%p_p_r/10 + 1) THEN + ! bjj: ProgAbort at least is standard fortran (as opposed to "CALL EXIT"), but calling ProgAbort is not allowed in a module in the FAST framework. Please trap your errors and return an error code. + CALL ProgAbort('WARNING: Meandering_Moving_time should be larger than the maximum turbine spacing') + END IF + END DO + +END SUBROUTINE read_turbine_position + +!------------------------------------------------------------------------------------------------ +SUBROUTINE read_upwind_result_file( m, p, u ) +!............................................................................ +! This routine is called to read the results from the DWM simulation of upwind turbines +! and to generate the output variables +!............................................................................ + TYPE(DWM_ParameterType), INTENT(INOUT) :: p + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_InputType), INTENT(INOUT) :: u + + !USE read_turbine_position_data, ONLY:m%RTPD%upwindturbine_number,m%RTPD%upwind_turbine_index,m%RTPD%WT_index,m%RTPD%downwindturbine_number,m%RTPD%SimulationOrder_index,m%RTPD%Turbine_sort_order + !USE DWM_ParameterType, ONLY:p%p_p_r,p%r_domain,p%WakePosition_1,p%WakePosition_2,p%Wind_file_Mean_u + !USE read_upwind_result + !USE smooth_out_wake_data, ONLY:m%SmoothOut%length_velocity_array + + CHARACTER(LEN=3) :: invetigated_turbine_index_character + CHARACTER(LEN=3) :: upwind_turbine_index_character + CHARACTER(LEN=80) :: filename_u_bin,filename_wakecenter_bin,filename_meanU_bin,filename_TI_bin,filename_smoothWake_bin,filename_smallTI_bin + CHARACTER(LEN=80) :: filename_meanU_txt + CHARACTER(LEN=2) :: Uprefix_bin = 'U_' + CHARACTER(LEN=3) :: WCprefix_bin = 'WC_' + CHARACTER(LEN=7) :: MeanUprefix_bin = 'Mean_U_' + CHARACTER(LEN=3) :: Tiprefix_bin = 'TI_' + CHARACTER(LEN=8) :: smallTIprefix_bin = 'SmallTI_' + CHARACTER(LEN=11) :: SmoothWprefix_bin = 'Smoothwake_' + CHARACTER(LEN=22) :: Prefix = 'DWM-results'//trim(PathSep) + CHARACTER(LEN=4) :: connectionprefix = '_to_' + CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' + INTEGER :: I + INTEGER :: MyUn + CHARACTER(LEN=3) :: turbine_sort_order_char + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! read the wind file mean velocity at the turbine plane from the very first turbine + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + IF (p%RTPD%SimulationOrder_index > 1) THEN + IF (p%RTPD%Turbine_sort_order(1) <= 9) THEN + write(turbine_sort_order_char,'(i1)') p%RTPD%Turbine_sort_order(1) + ELSEIF (p%RTPD%Turbine_sort_order(1) <= 99) THEN + write(turbine_sort_order_char,'(i2)') p%RTPD%Turbine_sort_order(1) + ELSE + write(turbine_sort_order_char,'(i3)') p%RTPD%Turbine_sort_order(1) + END IF + + filename_meanU_txt = trim(Prefix)//trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(turbine_sort_order_char)//".txt" + CALL GetNewUnit(MyUn) + OPEN(unit = MyUn, status='old',file=filename_meanU_txt,form='formatted') + READ(MyUn,'(f13.7)') p%Wind_file_Mean_u + CLOSE(MyUn) + END IF + + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! read the upwind results if have any + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + IF (p%RTPD%upwindturbine_number > 0) THEN + ALLOCATE (u%Upwind_result%upwind_U (p%RTPD%upwindturbine_number,floor(p%p_p_r*p%r_domain))) ! declare the input + ALLOCATE (u%Upwind_result%upwind_wakecenter (p%RTPD%upwindturbine_number,p%WakePosition_1,p%WakePosition_2,3)) + ALLOCATE (u%Upwind_result%upwind_meanU (p%RTPD%upwindturbine_number)) + ALLOCATE (u%Upwind_result%upwind_TI (p%RTPD%upwindturbine_number)) + ALLOCATE (u%Upwind_result%upwind_small_TI (p%RTPD%upwindturbine_number)) + ALLOCATE (u%Upwind_result%upwind_smoothWake (p%RTPD%upwindturbine_number,p%ElementNum)) + ALLOCATE (u%Upwind_result%velocity_aerodyn (p%RTPD%upwindturbine_number)) ! the temp velocity used by the aerodyn + + ! transfer the turbine index from integer to character + IF (p%RTPD%WT_index <= 9) THEN + write(invetigated_turbine_index_character,'(i1)') p%RTPD%WT_index + ELSEIF (p%RTPD%WT_index <= 99) THEN + write(invetigated_turbine_index_character,'(i2)') p%RTPD%WT_index + ELSE + write(invetigated_turbine_index_character,'(i3)') p%RTPD%WT_index + END IF + + DO I = 1,p%RTPD%upwindturbine_number + + IF (p%RTPD%upwind_turbine_index(I) <= 9) THEN + write(upwind_turbine_index_character,'(i1)') p%RTPD%upwind_turbine_index(I) + ELSEIF (p%RTPD%upwind_turbine_index(I) <= 99) THEN + write(upwind_turbine_index_character,'(i2)') p%RTPD%upwind_turbine_index(I) + ELSE + write(upwind_turbine_index_character,'(i3)') p%RTPD%upwind_turbine_index(I) + END IF + + ! obtain the coresponded profile name + + filename_u_bin = trim(Prefix)//trim(Uprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)& + //trim(connectionprefix)//trim(invetigated_turbine_index_character)//".bin" ! the file name needs to be read + + filename_TI_bin = trim(Prefix)//trim(TIprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)& + //trim(connectionprefix)//trim(invetigated_turbine_index_character)//".bin" + + filename_smallTI_bin = trim(Prefix)//trim(smallTIprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)& + //trim(connectionprefix)//trim(invetigated_turbine_index_character)//".bin" + + filename_smoothWake_bin = trim(Prefix)//trim(SmoothWprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)& + //trim(connectionprefix)//trim(invetigated_turbine_index_character)//".bin" + + filename_wakecenter_bin = trim(Prefix)//trim(WCprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)//".bin" + + filename_meanU_bin = trim(Prefix)//trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(upwind_turbine_index_character)//".bin" + + ! open the file and read + OPEN(unit = MyUn, status='old',file=filename_u_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_U(I,:) + CLOSE(MyUn) + + OPEN(unit = MyUn, status='old',file=filename_TI_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_TI(I) + CLOSE(MyUn) + + OPEN(unit = MyUn, status='old',file=filename_smallTI_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_small_TI(I) + CLOSE(MyUn) + + OPEN(unit = MyUn, status='old',file=filename_smoothWake_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_smoothWake(I,:) + CLOSE(MyUn) + + OPEN(unit = MyUn, status='old',file=filename_wakecenter_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_wakecenter(I,:,:,:) + CLOSE(MyUn) + + OPEN(unit = MyUn, status='old',file=filename_meanU_bin,form='unformatted') + READ(MyUn) u%Upwind_result%upwind_meanU(I) + CLOSE(MyUn) + + END DO + END IF + + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! declare the downwind output variables + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + IF (p%RTPD%SimulationOrder_index > 0) THEN ! not for the base 0 turbine + IF (p%RTPD%downwindturbine_number /= 0 ) THEN ! not for the turbines that don't have a downwind turbine + m%SmoothOut%length_velocity_array = NINT(1.2*p%RotorR) + ALLOCATE ( u%Upwind_result%TI_downstream (p%RTPD%downwindturbine_number ) ) + ALLOCATE ( u%Upwind_result%small_scale_TI_downstream (p%RTPD%downwindturbine_number ) ) + ALLOCATE ( u%Upwind_result%smoothed_velocity_array (p%RTPD%downwindturbine_number,p%ElementNum ) ) + ALLOCATE ( u%Upwind_result%vel_matrix (p%RTPD%downwindturbine_number,2*m%SmoothOut%length_velocity_array,2*m%SmoothOut%length_velocity_array) ) + END IF + END IF + +END SUBROUTINE read_upwind_result_file + +!------------------------------------------------------------------------------------------------ +SUBROUTINE write_result_file(m,p,y,u) +!............................................................................ +! This routine is called to write the results from the DWM simulation of this turbine +!............................................................................ + + TYPE(DWM_ParameterType), INTENT(INOUT) :: p + TYPE(DWM_MiscVarType), INTENT(INOUT) :: m + TYPE(DWM_OutputType), INTENT(INOUT) :: y + TYPE(DWM_InputType), INTENT(INOUT) :: u + + CHARACTER(LEN=3) :: invetigated_turbine_index_character + CHARACTER(LEN=3) :: downwind_turbine_index_character + CHARACTER(LEN=80) :: filename_u_bin,filename_wakecenter_bin,filename_meanU_bin,filename_TI_bin,filename_smallTI_bin,filename_smoothWake_bin,filename_wakewidth_bin,filename_wake_bin + CHARACTER(LEN=80) :: filename_TI_txt,filename_meanU_txt,filename_induction_txt,filename_wake_txt,filename_wakecenter_txt,filename_SDpower_txt,filename_Ct_txt + CHARACTER(LEN=2) :: Uprefix_bin = 'U_' + CHARACTER(LEN=3) :: WCprefix_bin = 'WC_' + CHARACTER(LEN=7) :: MeanUprefix_bin = 'Mean_U_' + CHARACTER(LEN=3) :: Tiprefix_bin = 'TI_' + CHARACTER(LEN=8) :: smallTIprefix_bin = 'SmallTI_' + CHARACTER(LEN=11) :: SmoothWprefix_bin = 'Smoothwake_' + CHARACTER(LEN=10) :: InductionPrefix = 'Induction_' + CHARACTER(LEN=6) :: Wakeprefix = 'WakeU_' + CHARACTER(LEN=11) :: WWprefix_bin = 'Wake_width_' + CHARACTER(LEN=22) :: Prefix = 'DWM-results'//trim(PathSep) + CHARACTER(LEN=4) :: connectionprefix = '_to_' + CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' + CHARACTER(LEN=8) :: Powerprefix = 'SDpower_' + CHARACTER(LEN=7) :: MeanCtPrefix = 'MeanCt_' + INTEGER :: I,RESULT + + INTEGER :: write_unit + + CHARACTER(LEN=80) :: filename_TI_to_txt + CHARACTER(LEN=80) :: filename_SmallTI_to_txt + +!bjj: use GetNewUnit() and parameters instead of "25" and "10". "10" is especially bad, because some other file is bound to be using it! + + IF ( p%RTPD%SimulationOrder_index > 0 ) THEN ! exclude the first turbine + + IF (p%RTPD%WT_index <= 9) THEN + write(invetigated_turbine_index_character,'(i1)') p%RTPD%WT_index + ELSEIF (p%RTPD%WT_index <= 99) THEN + write(invetigated_turbine_index_character,'(i2)') p%RTPD%WT_index + ELSE + write(invetigated_turbine_index_character,'(i3)') p%RTPD%WT_index + END IF + + ! Write the TI of this turbine + filename_TI_txt = trim(Prefix)//trim(Tiprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_TI_txt) + WRITE (write_unit,'(f13.7)') y%TI + CLOSE (write_unit) + + ! Write the mean velocity of this turbine + filename_meanU_bin = trim(Prefix)//trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".bin" + filename_meanU_txt = trim(Prefix)//trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_meanU_txt) + WRITE (write_unit,'(f13.7)') y%Mean_FFWS + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_meanU_bin,form='unformatted') + WRITE (write_unit) y%Mean_FFWS + CLOSE (write_unit) + + ! Write the induction factor of this turbine + filename_induction_txt = trim(Prefix)//trim(InductionPrefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_induction_txt) + WRITE (write_unit,'(f13.7)') y%induction_factor(:) + CLOSE (write_unit) + + ! Write the mean Ct of this turbine + filename_Ct_txt = trim(Prefix)//trim(MeanCtPrefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_Ct_txt) + WRITE (write_unit,'(f13.7)') y%avg_ct + CLOSE (write_unit) + + ! Write the averaged SD power of this turbine + filename_SDpower_txt = trim(Prefix)//trim(Powerprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_SDpower_txt,POSITION = 'APPEND') + WRITE (write_unit,'(f13.7)') y%mean_SDgenpwr + CLOSE (write_unit) + + + ! Write the wake deficit profile of this turbine + filename_wake_txt = trim(Prefix)//trim(Wakeprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + filename_wake_bin = trim(Prefix)//trim(Wakeprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".bin" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_wake_txt) + WRITE (write_unit,'(f10.7)') y%wake_u(:,:) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_wake_bin,form='unformatted') + WRITE (write_unit) y%wake_u(:,:) + CLOSE (write_unit) + + ! Write the meandered wake center result of this turbine + filename_wakecenter_bin = trim(Prefix)//trim(WCprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".bin" + filename_wakecenter_txt = trim(Prefix)//trim(WCprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".txt" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_wakecenter_txt) + WRITE (write_unit,'(f13.7)') y%wake_position(:,:,:) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_wakecenter_bin,form='unformatted') + WRITE (write_unit) y%wake_position(:,:,:) + CLOSE (write_unit) + + ! Write the downstream turbine customized output files + IF (p%RTPD%downwindturbine_number /= 0) THEN + + DO I = 1,p%RTPD%downwindturbine_number + IF (p%RTPD%downwind_turbine_index(I) <= 9) THEN + write(downwind_turbine_index_character,'(i1)') p%RTPD%downwind_turbine_index(I) + ELSEIF (p%RTPD%downwind_turbine_index(I) <= 99) THEN + write(downwind_turbine_index_character,'(i2)') p%RTPD%downwind_turbine_index(I) + ELSE + write(downwind_turbine_index_character,'(i3)') p%RTPD%downwind_turbine_index(I) + END IF + + filename_u_bin = trim(Prefix)//trim(Uprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + filename_TI_bin = trim(Prefix)//trim(TIprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + filename_smallTI_bin = trim(Prefix)//trim(smallTIprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + filename_smoothWake_bin = trim(Prefix)//trim(SmoothWprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + + + filename_TI_to_txt = trim(Prefix)//trim(TIprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".txt" + filename_SmallTI_to_txt = trim(Prefix)//trim(smallTIprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".txt" + + ! Write the wake velocity at the certain downstream turbine plane + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_u_bin,form='unformatted') + WRITE (write_unit) y%wake_u(floor(p%RTPD%downwind_turbine_projected_distance(I) * p%p_p_r)+1,:) + CLOSE (write_unit) + + ! Write the TI at the certain downstream turbine plane + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_TI_bin,form='unformatted') + WRITE (write_unit) u%Upwind_result%TI_downstream (I) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_smallTI_bin,form='unformatted') + WRITE (write_unit) u%Upwind_result%small_scale_TI_downstream (I) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_TI_to_txt) + WRITE (write_unit,'(f14.7)') u%Upwind_result%TI_downstream (I) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit,file=filename_smallTI_to_txt) + WRITE (write_unit,'(f14.7)') u%Upwind_result%small_scale_TI_downstream (I) + CLOSE (write_unit) + + ! Write the smoothed wake profile at the certain downstream turbine plane + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_smoothWake_bin,form='unformatted') + WRITE (write_unit) u%Upwind_result%smoothed_velocity_array(I,:) ! write the wind data of the plane where the downstream turbine locates, + CLOSE (write_unit) + END DO + END IF + END IF + + ! Write the meandered wake center and the wake width result from the 0 base wind turbine + IF (p%RTPD%SimulationOrder_index == 0) THEN + + filename_wakecenter_bin = trim(Prefix)//trim(WCprefix_bin)//trim(Turbineprefix)//"0"//".bin" + filename_wakewidth_bin = trim(Prefix)//trim(WWprefix_bin)//trim(Turbineprefix)//"0"//".bin" + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_wakecenter_bin,form='unformatted') + WRITE (write_unit) y%wake_position(:,:,:) + CLOSE (write_unit) + + CALL GetNewUnit (write_unit) + OPEN (unit = write_unit, status='replace',file=filename_wakewidth_bin,form='unformatted') + WRITE (write_unit) m%WMC%wake_width(:) + CLOSE (write_unit) + + END IF + +END SUBROUTINE write_result_file + +!!---------------------------------------------------------------------------------- +!!BJJ: THIS routine uses non-standard Fortran. IFPORT and DFLIB are incompatible with gfortran. Since this routine isn't used, I'm commenting it out. +!SUBROUTINE rename_FAST_output(m, u, p) +!!............................................................................ +!! This routine is called to rename the fast output +!!............................................................................ +! USE IFPORT +! USE DFLIB +! +! TYPE(DWM_InputType), INTENT(INOUT) :: u ! Inputs at Time +! TYPE(DWM_MiscVarType), INTENT(INOUT) :: m +! TYPE(DWM_ParameterType), INTENT(INOUT) :: p +! +! CHARACTER(LEN=80) :: filename_FastOutput,filename_FastElm +! CHARACTER(LEN=11) :: Fastprefix = 'FastOutput_' ! Fast output file +! CHARACTER(LEN=8) :: FastElmprefix = 'FastElm_' ! Fast Elm output file +! INTEGER :: RESULT +! CHARACTER(LEN=22) :: Prefix = 'DWM-results'//trim(PathSep) +! CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' +! CHARACTER(LEN=3) :: invetigated_turbine_index_character +! +! IF ( p%RTPD%SimulationOrder_index > 0 ) THEN ! exclude the first turbine +! +! IF (p%RTPD%WT_index <= 9) THEN +! write(invetigated_turbine_index_character,'(i1)') p%RTPD%WT_index +! ELSEIF (p%RTPD%WT_index <= 99) THEN +! write(invetigated_turbine_index_character,'(i2)') p%RTPD%WT_index +! ELSE +! write(invetigated_turbine_index_character,'(i3)') p%RTPD%WT_index +! END IF +! +! ! Rename the FAST output wrt the turbine index +! filename_FastOutput = trim(Prefix)//trim(Fastprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".out" +! filename_FastElm = trim(Prefix)//trim(FastElmprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".AD.out" +! +! !RESULT =rename('V80_2MW.out',filename_FastOutput) +! !RESULT =rename('V80_2MW.elm',filename_FastElm ) +! +! RESULT =rename('FAST_V80.out',filename_FastOutput) +! RESULT =rename('FAST_V80.elm',filename_FastElm ) +! END IF +! +!END SUBROUTINE rename_FAST_output + +!------------------------------------------------------------------------------------------------ +FUNCTION min_of_array(ary, ary_length) +!............................................................................ +! This routine is called to return the minmum value in an array +!............................................................................ + + INTEGER :: ary_length + REAL(ReKi) :: ary(ary_length) + REAL(ReKi) :: min_of_array + INTEGER :: I + + + min_of_array = ary(1) + + DO I = 2,ary_length + IF (ary(I) < min_of_array) THEN + min_of_array = ary(I) + END IF + END DO + +END FUNCTION min_of_array + +!------------------------------------------------------------------------------------------------ +FUNCTION max_of_array(ary, ary_length) +!............................................................................ +! This routine is called to return the maximum value in an array +!............................................................................ + + INTEGER :: ary_length + REAL :: ary(ary_length) + REAL :: max_of_array + INTEGER :: I + + max_of_array = ary(1) + + DO I = 2,ary_length + IF (ary(I) > max_of_array) THEN + max_of_array = ary(I) + END IF + END DO + +END FUNCTION max_of_array + +!------------------------------------------------------------------------------------------------ +FUNCTION rotation_lateral_offset(x_spacing) +!............................................................................ +! This routine is called to return the wake lateral offset due to the turbine rotation +! (assume the rotor spins clockwise) --> always shift to right (negative) +!............................................................................ + + REAL :: x_spacing + REAL :: rotation_lateral_offset + + ! parameters + REAL :: ad = -4.5 + REAL :: bd = -0.01 + + rotation_lateral_offset = ad + bd*x_spacing + +END FUNCTION rotation_lateral_offset + +!------------------------------------------------------------------------------------------------ +FUNCTION local_skew_angle(yaw_angle, tilde_ct, x_spacing, wake_width, ppr) +!............................................................................ +! This routine is called to return the local skew angle at a certain downstream location +!............................................................................ + + REAL(ReKi) :: yaw_angle + REAL(ReKi) :: tilde_ct + REAL(ReKi) :: x_spacing + INTEGER :: wake_width + REAL(ReKi) :: ppr + REAL(ReKi) :: local_skew_angle + + IF ( ABS(yaw_angle) > 0.000001 ) THEN + local_skew_angle = (ppr/wake_width)**2 *COS(yaw_angle)**2 *SIN(yaw_angle) *tilde_ct/2 + local_skew_angle = -local_skew_angle ! the direction (positive or negative) is opposite to the turbine yaw angle + ELSE + local_skew_angle = 0.0 + END IF + + local_skew_angle = TAN(local_skew_angle) + +END FUNCTION local_skew_angle + +!------------------------------------------------------------------------------------------------ +SUBROUTINE calculate_SD_averagePower( m,y ) +!------------------------------------------------------------------------------------------------ +! This routine is used to calculate the average time step power from SD subroutine +!------------------------------------------------------------------------------------------------ + + TYPE(DWM_MiscVarType), INTENT(IN ) :: m + TYPE(DWM_OutputType), INTENT(INOUT) :: y + + + y%mean_SDgenpwr = y%total_SDgenpwr / m%SDtimestep + +END SUBROUTINE calculate_SD_averagePower + +END MODULE DWM_Wake_Sub + + + + diff --git a/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm.f90 b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm.f90 new file mode 100644 index 000000000..f59052165 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm.f90 @@ -0,0 +1,51 @@ +PROGRAM DWM_driver_wind_farm + + USE DWM_driver_wind_farm_sub + USE read_wind_farm_parameter_data, ONLY: NumWT, DWM_exe_name + USE DWM_init_data, ONLY:InputFile +#ifdef __INTEL_COMPILER + USE IFPORT +#endif + + IMPLICIT NONE + + INTEGER :: simulation_index + INTEGER :: RESULT + REAL :: T1,T2 + + ! pre-processing + CALL Driver_Init + CALL read_wind_farm_parameter(InputFile) + CALL Check_DWM_parameter + CALL write_parameter_to_file + + ! sort the turbines + CALL wind_farm_geometry + + !run the DWM for the very first base turbine to generate the turbine interaction information + simulation_index = 0 + + ! FAST 8 + RESULT = system("echo "//TRIM(DWM_exe_name)//" "// TRIM(InputFile)//".fst" // " " //TRIM(Int2LStr(simulation_index)) //" "// "DWM") + RESULT = system(TRIM(DWM_exe_name)//" "// TRIM(InputFile)//".fst" // " " //TRIM(Int2LStr(simulation_index)) //" "// "DWM") + + ! calculate the wake sector angle and the turbine interaction information + CALL cal_wake_sector_angle + + ! Run the simulation for all the turbines in the wind farm + DO simulation_index = 1,NumWT + !RESULT = system("DWM_Wind_Farm.exe "// TRIM(Int2LStr(simulation_index)) //" V80_2MW.fst") ! 2MW NEW + + !general DWM FAST input + !RESULT = system(TRIM(DWM_exe_name)//".exe "// TRIM(Int2LStr(simulation_index)) //" "//TRIM(InputFile)//".fst") + + ! FAST 8 + RESULT = system(TRIM(DWM_exe_name)//" "// TRIM(InputFile)//".fst" // " " //TRIM(Int2LStr(simulation_index)) //" "// "DWM") + + result = 0 !SetExitQQ (QWIN$EXITNOPERSIST) + CALL rename_FAST_output(simulation_index) + END DO + + CALL delete_temp_files + +END PROGRAM DWM_driver_wind_farm \ No newline at end of file diff --git a/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_mod.f90 b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_mod.f90 new file mode 100644 index 000000000..75ec54a47 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_mod.f90 @@ -0,0 +1,42 @@ +MODULE read_wind_farm_parameter_data + IMPLICIT NONE + REAL :: HubHt + REAL :: RotorR + INTEGER :: NumWT ! The total number of wind turbines + REAL :: Uambient + REAL :: TI + INTEGER :: ppR + REAL :: Domain_R + REAL :: Domain_X + INTEGER :: Mstl ! Meandering_simulation_time_length + INTEGER :: Mmt ! Meandering_Moving_time + INTEGER :: smooth_flag ! smoothed out upstream wake profile flag + REAL :: WFLowerBd ! The lower bound height of the wind file (m) + REAL :: Winddir ! The ambient wind direction + INTEGER :: Tinfluencer ! The max number of upstream turbines that affects a downstream turbine (-) + CHARACTER(1024):: DWM_exe_name + + REAL(8), ALLOCATABLE :: Xcoordinate (:) ! wind turbine x location + REAL(8), ALLOCATABLE :: Ycoordinate (:) ! wind turbine y location + +END MODULE read_wind_farm_parameter_data + +!------------------------------------------------------------ +MODULE wind_farm_geometry_data + IMPLICIT NONE + INTEGER,ALLOCATABLE :: turbine_sort(:) ! the array that stores the order of the turbines from upstream to downstream + INTEGER,ALLOCATABLE :: TurbineInfluenceData(:,:) + REAL,ALLOCATABLE :: wake_sector_angle_array(:) + REAL(8) :: xwind + REAL(8) :: ywind + INTEGER :: scale_factor + REAL :: Pi + REAL,ALLOCATABLE :: length(:) ! projected length on the wind direction vector + +END MODULE wind_farm_geometry_data + +!------------------------------------------------------------ +MODULE DWM_init_data + CHARACTER(1024) :: OutFileRoot + CHARACTER(1024) :: InputFile +END MODULE DWM_init_data diff --git a/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_sub.f90 b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_sub.f90 new file mode 100644 index 000000000..dae5c1a2d --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/DWM_driver_wind_farm_sub.f90 @@ -0,0 +1,879 @@ +MODULE DWM_driver_wind_farm_sub + USE NWTC_Library + IMPLICIT NONE + +!PUBLIC SUBROUTINES + PUBLIC :: read_wind_farm_parameter + PUBLIC :: write_parameter_to_file + PUBLIC :: wind_farm_geometry + PUBLIC :: projected_length + PUBLIC :: AngleBetweenVectors + PUBLIC :: turbine_position_LorR + PUBLIC :: Driver_init + PUBLIC :: delete_temp_files + PUBLIC :: Check_DWM_parameter + + +CONTAINS +!------------------------------------------------------------------- +SUBROUTINE read_wind_farm_parameter(PriFile) +!................................................................... +! This subroutine is to read the wind farm parameter files +! Including the number of rows of the wind farm, the number of turbine in each row +! and the turbine spacing +!................................................................... + USE read_wind_farm_parameter_data + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: PriFile + INTEGER :: UnIn = 0 + INTEGER :: UnEc = -1 + INTEGER :: I + CHARACTER(1024) :: DWM_Title,comment + INTEGER :: ErrStat = 0 + CHARACTER(ErrMsgLen) :: ErrMsg + INTEGER(4) :: IOS + + CALL OpenFInpFile ( UnIn, PriFile, ErrStat, ErrMsg ) + + READ (UnIn,'(//,A,/)',IOSTAT=IOS) DWM_Title ! read the words (title) + CALL CheckIOS( IOS, PriFile, 'file title', StrType ) + + READ (UnIn,'(A)',IOSTAT=IOS) Comment ! read the words (comment) + CALL CheckIOS( IOS, PriFile, 'simulation control parameters comment', StrType ) + + ! Read in the hub height + CALL ReadVar ( UnIn, PriFile, HubHt, 'HubHt', 'The hub height (m)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the rotor radius + CALL ReadVar ( UnIn, PriFile, RotorR, 'RotorR', 'The Rotor radius (m)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the total number of wind turbines + CALL ReadVar ( UnIn, PriFile, NumWT, 'NumWT', 'The total number of wind turbines (-)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the ambient wind velocity + CALL ReadVar ( UnIn, PriFile, Uambient, 'Uambient', 'The ambient wind velocity (m/s)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the ambient TI + CALL ReadVar ( UnIn, PriFile, TI, 'TI', 'TI for first turbine (%)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the radial domain size + CALL ReadVar ( UnIn, PriFile, ppR, 'ppR', 'Point per R resolution (-)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the point per R resolution + CALL ReadVar ( UnIn, PriFile, Domain_R, 'Domain_R', 'Radial domain size (R)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the point per R resolution + CALL ReadVar ( UnIn, PriFile, Domain_X, 'Domain_X', 'Longitudinal domain size (R)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the simulation time length of the meandering wake model + CALL ReadVar ( UnIn, PriFile, Mstl, 'Meandering_simulation_time_length', 'The length of the simulation time in the meandering wake model (-)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the moving time length of the meandering wake model + CALL ReadVar ( UnIn, PriFile, Mmt, 'Meandering_Moving_time', 'The length of the moving time in the meandering wake model (-)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the lower bound height of the wind file + CALL ReadVar ( UnIn, PriFile, WFLowerBd, 'WFLowerBd', 'The lower bound height of the wind file (m)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the ambient wind direction + CALL ReadVar ( UnIn, PriFile, Winddir, 'Winddir', 'The ambient wind direction (degree)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= 0 ) RETURN + + ! Read in the DWM_FAST.exe file rootname + CALL ReadVar ( UnIn, PriFile, DWM_exe_name, 'DWM_exe_name', 'The file rootname of the DWM-FAST program', ErrStat, ErrMsg, UnEc ) + + ALLOCATE (Xcoordinate(NumWT)) + ALLOCATE (Ycoordinate(NumWT)) + + CALL ReadCom( UnIn, PriFile, 'Coordinate table headers', ErrStat, ErrMsg) + IF ( ErrStat /= 0 ) RETURN + + DO i = 1, NumWT + IF (ErrStat == 0) THEN + READ(UnIn,*,IOSTAT=ErrStat) Xcoordinate(i), Ycoordinate(i) + END IF + END DO + + Tinfluencer = 1 + !Tinfluencer = 10 + +END SUBROUTINE read_wind_farm_parameter + +!------------------------------------------------------------------- +SUBROUTINE Check_DWM_parameter() +!................................................................... +! This subroutine is to check if the input parameters are valid +!................................................................... + USE read_wind_farm_parameter_data + + IF (HubHt < 0.0) THEN + PRINT*, 'WARNING: HubHt should be positive' + CALL EXIT + END IF + + IF (RotorR < 0.0) THEN + PRINT*, 'WARNING: RotorR should be positive' + CALL EXIT + END IF + IF (RotorR > HubHt) THEN + PRINT*, 'WARNING: RotorR should be smaller than HubHt' + CALL EXIT + END IF + + IF (NumWT < 1.0) THEN + PRINT*, 'WARNING: NumWT should be positive' + CALL EXIT + END IF + + IF (Uambient < 0.0) THEN + PRINT*, 'WARNING: Uambient should be positive' + CALL EXIT + END IF + + IF (TI < 0.0) THEN + PRINT*, 'WARNING: TI should be positive' + CALL EXIT + END IF + + IF (ppR < 1.0) THEN + PRINT*, 'WARNING: ppR should be positive' + CALL EXIT + END IF + + IF (Domain_R < 0.0) THEN + PRINT*, 'WARNING: Domain_R should be positive' + CALL EXIT + END IF + + IF (Domain_X < 0.0) THEN + PRINT*, 'WARNING: Domain_X should be positive' + CALL EXIT + END IF + +END SUBROUTINE Check_DWM_parameter + +!------------------------------------------------------------------- +SUBROUTINE write_parameter_to_file() +!................................................................... +! This subroutine is to write the turbine spacing from the input file +! to a bin file, which enables the DWM to read the turbine spacing at every +! instances of running +!................................................................... + + USE read_wind_farm_parameter_data + IMPLICIT NONE + integer :: Un + + !CALL GetNewUnit(Un) + Un = 10 + + OPEN(unit = Un, status='replace',file='DWM_parameter.bin',form='unformatted') + WRITE(Un) HubHt,RotorR,NumWT,Uambient,TI,Domain_R,Domain_X,ppR,Mstl,Mmt,WFLowerBd,Winddir,Tinfluencer + CLOSE(Un) + + OPEN(unit = Un, status='replace',file='wind_farm_coordinate.bin',form='unformatted') + WRITE(Un) Xcoordinate,Ycoordinate + CLOSE(Un) + +END SUBROUTINE write_parameter_to_file + +!------------------------------------------------------------------- +SUBROUTINE wind_farm_geometry() +!................................................................... +! This subroutine is to calculate the wind direction and sort the wind +! turbines as the order from upstream to downstream +! output the angles between turbines +!................................................................... + USE read_wind_farm_parameter_data, ONLY: Xcoordinate, Ycoordinate, NumWT, Winddir, Tinfluencer,Mmt,ppR, Domain_X + USE wind_farm_geometry_data, ONLY: turbine_sort, xwind, ywind,length + + INTEGER :: I,J,K + INTEGER :: temp, Un + REAL :: origin_turbine_x + REAL :: origin_turbine_y + REAL :: downwind_turbine_x + REAL :: downwind_turbine_y + REAL :: max_xturbine + REAL :: max_yturbine + REAL :: Circle_Radius + REAL :: Pi + REAL :: vector1x + REAL :: vector1y + REAL :: vector2x + REAL :: vector2y + REAL :: Max_spacing + REAL :: spacing_temp + + INTEGER,ALLOCATABLE :: position_sign(:,:) + + REAL,ALLOCATABLE :: length_sort(:) + REAL,ALLOCATABLE :: turbine_angle(:,:) + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! determine the SIZE of the wind farm + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + max_xturbine = 0 + max_yturbine = 0 + + + DO I = 1,NumWT + IF ( ABS(Xcoordinate(I)) > max_xturbine ) THEN + max_xturbine = ABS(Xcoordinate(I)) + END IF + + IF ( ABS(Ycoordinate(I)) > max_yturbine ) THEN + max_yturbine = ABS(Ycoordinate(I)) + END IF + END DO + + Circle_Radius = 2*SQRT(max_xturbine*max_xturbine + max_yturbine*max_yturbine) + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! determine the inflow wind origin + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + Pi = ACOS( -1.0 ) + xwind = SIN(Winddir*Pi/180) * circle_radius + ywind = COS(Winddir*Pi/180) * circle_radius + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! sort the wind turbines as the order from upstream to downstream + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ALLOCATE ( turbine_sort(NumWT) ) + ALLOCATE ( length(NumWT) ) + ALLOCATE ( length_sort(NumWT) ) + + DO I = 1,NumWT + length(I) = projected_length(xwind,ywind,Xcoordinate(I),Ycoordinate(I)) + END DO + + length_sort = length + + DO I=1,NumWT + turbine_sort(I) = I + END DO + + + DO I = 1,NumWt-1 + DO J = 1,NumWt-1 + IF ( length_sort(J) > length_sort(J+1) ) THEN + temp = turbine_sort(J) + turbine_sort(J) = turbine_sort(J+1) + turbine_sort(J+1) = temp + + temp = length_sort(J) + length_sort(J) = length_sort(J+1) + length_sort(J+1) = temp + END IF + END DO + END DO + + !CALL GetNewUnit(Un) + Un = 10 + OPEN(unit = Un, status='replace',file='wind_farm_turbine_sort.bin',form='unformatted') + WRITE(Un) turbine_sort(:) + CLOSE(Un) + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! calculate the angles between the line connecting two turbines and the wind direction + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ALLOCATE (turbine_angle(NumWT,NumWT)) + ALLOCATE (position_sign(NumWT,NumWT)) + turbine_angle = 0.0 + position_sign = 0 + + DO I = 1,NumWT + DO J = 1,NumWT + origin_turbine_x = Xcoordinate(I) + origin_turbine_y = Ycoordinate(I) + downwind_turbine_x = Xcoordinate(J) + downwind_turbine_y = Ycoordinate(J) + + vector1x = 0 - xwind ! the wind direction + vector1y = 0 - ywind + vector2x = downwind_turbine_x - origin_turbine_x ! the vector between two turbines + vector2y = downwind_turbine_y - origin_turbine_y + + IF (I /= J) THEN + turbine_angle(I,J) = AngleBetweenVectors(vector1x,vector1y,vector2x,vector2y) + position_sign(I,J) = turbine_position_LorR(xwind,ywind,origin_turbine_x,origin_turbine_y,downwind_turbine_x,downwind_turbine_y) + turbine_angle(I,J) = turbine_angle(I,J)*position_sign(I,J) ! to specify the downstream turbine is on left side (+) or right side (-) + END IF + END DO + END DO + + !CALL GetNewUnit(Un) + Un = 10 + OPEN(unit = Un, status='replace',file='turbine_angles.bin',form='unformatted') + WRITE(Un) turbine_angle(:,:) + CLOSE(Un) + + OPEN(unit = Un, status='replace',file='turbine_distance.bin',form='unformatted') + WRITE(Un) length(:) + CLOSE(Un) + + ! check if the Domain_X is larger than the maximum spacing + Max_spacing = 0.0 + DO I = 1,NumWT + IF (I+Tinfluencer < NumWT+1) THEN + spacing_temp = length(I+Tinfluencer) - length(I) + IF (spacing_temp > Max_spacing) THEN + Max_spacing = spacing_temp + END IF + END IF + END DO + + + ! LOGIC WRONG ! 2.14.2014 + !IF ( Domain_X/2 < Max_spacing ) THEN + ! PRINT*, 'WARNING: Domain_x should be larger than the maximum turbine spacing' + ! CALL EXIT + !END IF + + ! test + + OPEN (unit=25,file="turbine_spacing.txt") + WRITE (25,*) length(:) + CLOSE(25) + +END SUBROUTINE wind_farm_geometry + +!------------------------------------------------------------------- +SUBROUTINE cal_wake_sector_angle() +!................................................................... +! This subroutine is to calculate the wake sector angle +! with respect to the change of the downstream distance +!................................................................... + USE wind_farm_geometry_data, ONLY: wake_sector_angle_array,scale_factor,Pi,TurbineInfluenceData,length,xwind,ywind,turbine_sort + USE read_wind_farm_parameter_data, ONLY: NumWT, Winddir, Tinfluencer,Mmt,ppR,Xcoordinate, Ycoordinate,Mstl,Domain_X + + REAL,ALLOCATABLE :: distance_array(:) + INTEGER :: I,J + + REAL :: DownStart + REAL :: DownEnd + REAL :: delta + INTEGER :: node + + INTEGER, ALLOCATABLE :: wake_width(:) + REAL, ALLOCATABLE :: wake_center_position(:,:,:) + + INTEGER :: Turbine0_index + INTEGER :: Turbine1_index + INTEGER :: Counter + REAL :: Turbine_Spacing + REAL :: vector1x + REAL :: vector1y + REAL :: vector2x + REAL :: vector2y + REAL :: Angle + REAL :: Spacing_rounding + REAL :: Sector_angle_boundary + + INTEGER :: T7_wake + INTEGER :: T8_wake + + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! read the wake file and wake width + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ALLOCATE (wake_width (NINT(ppR * Domain_X/2 ))) + !ALLOCATE (wake_width (ppR * 36/2 )) + ALLOCATE (wake_center_position(Mstl ,Mmt+1,3 )) + scale_factor = 10 + Pi = ACOS( -1.0 ) + + ! read the wake file and wake width + OPEN(unit = 10, status='old',file='Wake_width_Turbine_0.bin',form='unformatted') ! open an existing file + READ(10) wake_width(:) + CLOSE(10) + + OPEN(unit = 10, status='old',file='WC_Turbine_0.bin',form='unformatted') ! open an existing file + READ(10) wake_center_position(:,:,:) + CLOSE(10) + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! calculate the wake sector angle array + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + DownStart = 1 + DownEnd = 12 ! from 1D to 34D + delta = 0.1 + node = (DownEnd-Downstart)/delta + 1 + + ALLOCATE (distance_array(node)) + ALLOCATE (wake_sector_angle_array(node)) + distance_array = ((DownEnd-DownStart)/(node-1))*[(I,I=1,node)]+(DownStart-((DownEnd-DownStart)/(node-1))) + + DO I = 1,node + wake_sector_angle_array(I) = Sector_angle(wake_width,wake_center_position,distance_array(I)) + END DO + + OPEN(unit = 10, status='replace',file='wake_sector_angle.bin',form='unformatted') + WRITE(10) wake_sector_angle_array(:) + CLOSE(10) + + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! for a specfic downstream turbine, determine the wakes from which upstream turbines will make an effect + !''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + !WindSectorAngle = 7 + ALLOCATE ( TurbineInfluenceData (NumWT,Tinfluencer ) ) + + TurbineInfluenceData = 0 + + DO I = 1,NumWt + Turbine0_index = turbine_sort(NumWt-I+1) ! Start from the most downwind turbine + Counter = 0 + DO J = 1,NumWt-1 + IF (Counter <Tinfluencer) THEN + IF (NumWt-I+1-J>0) THEN + Turbine1_index = turbine_sort(NumWt-I+1-J) + + Turbine_Spacing = length(Turbine0_index) - length(Turbine1_index) ! Absolute spacing + + Spacing_rounding = NINT(Turbine_Spacing*10.0)/10.0 ! the rounding spacing x.x to calculate the sector angle + IF (Spacing_rounding>(Mmt/(ppR/scale_factor))) THEN + Spacing_rounding = Mmt/(ppR/scale_factor) + END IF + IF (Spacing_rounding<0.1) THEN + Spacing_rounding = 0.1 + END IF + + vector1x = 0 - xwind ! the wind direction + vector1y = 0 - ywind + vector2x = Xcoordinate(Turbine0_index) - Xcoordinate(Turbine1_index) ! the vector between two turbines + vector2y = Ycoordinate(Turbine0_index) - Ycoordinate(Turbine1_index) + + !IF (Turbine_Spacing >= 3) THEN + Angle = AngleBetweenVectors(vector1x,vector1y,vector2x,vector2y) + Sector_angle_boundary = Sector_angle(wake_width,wake_center_position,Spacing_rounding) + IF ( Angle < Sector_angle_boundary ) THEN + Counter = Counter + 1 + TurbineInfluenceData(Turbine0_index,Counter) = Turbine1_index + END IF + !END IF + END IF + + END IF + END DO + END DO + + OPEN(unit = 10, status='replace',file='turbine_interaction.bin',form='unformatted') + WRITE(10) TurbineInfluenceData(:,:) + CLOSE(10) + +END SUBROUTINE cal_wake_sector_angle + +!------------------------------------------------------------------- +FUNCTION projected_length(ax,ay,bx,by) +!................................................................... +! This function is to calculate the downstream distance from the specific +! turbine to the origin of the inflow wind +! The distance is used to sort the turbines from ipstream to downstream +!................................................................... + + REAL(8) :: ax ! the x coordinate of the point a (reference point) + REAL(8) :: ay ! the y coordinate of the point a + REAL(8) :: bx ! the x coordinate of the point b + REAL(8) :: by ! the y coordinate of the point b + REAL :: projected_length + + REAL :: side_a ! triangle side a length + REAL :: side_b ! triangle side b length + REAL :: side_c ! triangle side c length + REAL :: semi ! triangle semiperimeter + REAL :: area ! triangle area + REAL :: height ! triangle height + + + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! calculate the area of the triangle whose corners are the (0,0), turbine location and the wind origin using Heron's method + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + side_a = SQRT( (bx-ax)*(bx-ax) + (by-ay)*(by-ay) ) + side_b = SQRT( bx*bx + by*by ) + side_c = SQRT( ax*ax + ay*ay ) + semi = (side_a + side_b + side_c)/2 + + area = SQRT(ABS( semi * ( semi - side_a ) * ( semi - side_b ) * ( semi - side_c ) )) + + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! calculate the projected length of the turbine on the wind direction vector + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + height = 2 * area / side_c + + projected_length = SQRT( side_a*side_a - height*height ) + + +END FUNCTION projected_length + +!------------------------------------------------------------------- +FUNCTION AngleBetweenVectors(x1,y1,x2,y2) +!................................................................... +! This function is to calculate the angle between two vectors +! x1,y1,x2,y2 are the vector coordinates +!................................................................... + + REAL :: x1 + REAL :: y1 + REAL :: x2 + REAL :: y2 + REAL :: Pi = ACOS( -1.0 ) + REAL :: AngleBetweenVectors + REAL :: CosAlpha + REAL :: Rad + + Pi = ACOS( -1.0 ) + + CosAlpha = (x1*x2 + y1*y2) / ( SQRT(x1*x1+y1*y1) * SQRT(x2*x2+y2*y2) ) + + !Rad = ACOS(CosAlpha-0.00001) ! ACOS(1) = NaN??!!!! + + IF (CosAlpha>1.0) THEN + CosAlpha = 1.0 + END IF + + IF (CosAlpha<-1.0) THEN + CosAlpha = -1.0 + END IF + + Rad = ACOS(CosAlpha) + + AngleBetweenVectors = Rad * 180/Pi + +END FUNCTION AngleBetweenVectors +!------------------------------------------------------------------- +FUNCTION Sector_angle(wake_width,wake_center,downstream_distance) +!................................................................... +! This function is to calculate the maximum sector angle at a certain downstream +! distance behind a wind turbine +!................................................................... + USE read_wind_farm_parameter_data, ONLY: ppR,Mstl,Mmt,RotorR + USE wind_farm_geometry_data, ONLY: Pi,scale_factor + + REAL :: Sector_angle + INTEGER :: wake_width(:) + REAL :: wake_center(:,:,:) + REAL :: downstream_distance + + INTEGER :: I,J,K + REAL :: max_temp + INTEGER :: index_I + REAL :: Wakewidth + REAL :: angle_temp + REAL :: y1_temp,y2_temp,y_temp,x_temp + + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + ! Calculate the max arctan(y/x) as the 1/2 sector angle + !'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + max_temp = 0 + + ! Calculate the index of the corresponding downstream distance + IF (MOD(downstream_distance,(1.0/(ppR/scale_factor))) == 0) THEN + J = FLOOR(downstream_distance/(1.0/(ppR/scale_factor)))+1 ! resolution = 1/(ppR/scale_factor) D + ELSE + J = FLOOR(downstream_distance/(1.0/(ppR/scale_factor)))+2 + END IF + + IF (J> Mmt+1) THEN + J = Mmt+1 + END IF + + DO I = 1,Mstl + !DO J = downstream_distance*ppR/scale_factor+1,Mmt+1 + Wakewidth = wake_width( (J-1)*scale_factor ) + + y1_temp = ABS(wake_center(I,J,2)) + y2_temp = Wakewidth/ppR*RotorR + y_temp = y1_temp + y2_temp + x_temp = wake_center(I,J,1) + + angle_temp = ATAN( y_temp / x_temp ) + + IF (angle_temp > max_temp) THEN + max_temp = angle_temp + index_I = I + END IF + !END DO + END DO + + Sector_angle = max_temp * 180/Pi + +END FUNCTION Sector_angle + +!------------------------------------------------------------------- +FUNCTION turbine_position_LorR(xwind,ywind,x0,y0,x1,y1) +!................................................................... +! This function is to see if the downwind turbine is on the left side or right side of the line +! connecting the wind origin and the upwind turbine +!................................................................... + REAL(8) :: xwind ! wind origin + REAL(8) :: ywind + REAL :: x0 ! investigated origin turbine + REAL :: y0 + REAL :: x1 ! turbine other than the investigated turbine + REAL :: y1 + INTEGER :: turbine_position_LorR + + REAL :: flag + + flag = -xwind*(y1-y0) + ywind*(x1-x0) + + IF (flag >= 0) THEN + turbine_position_LorR = 1 ! the downwind turbine is on the left side + ELSE + turbine_position_LorR = -1 ! the downwind turbine is on the right side + END IF + +END FUNCTION turbine_position_LorR + +!------------------------------------------------------------------- +SUBROUTINE rename_files(turbine_index) +!................................................................... +! This subroutine is to called to rename the output files of the DWM +! according to the turbine index +!................................................................... + + INTEGER :: turbine_index + CHARACTER(LEN=30) :: filename_u,filename_wakecenter,filename_meanU,filename_TI,filename_A,filename_FastOutput,filename_FastElm + CHARACTER(LEN=30) :: filename_u_bin,filename_wakecenter_bin,filename_meanU_bin + CHARACTER(LEN=3) :: turbine_index_character + CHARACTER(LEN=2) :: Uprefix_txt = 'U_' ! wake_velocity + CHARACTER(LEN=3) :: WCprefix_txt = 'WC_' ! wake center + CHARACTER(LEN=7) :: MeanUprefix_txt = 'Mean_U_' ! average velocity + CHARACTER(LEN=3) :: TIprefix_txt = 'TI_' ! TI of each turbine downstream + CHARACTER(LEN=6) :: Inducprefix_txt = 'Induc_' ! Induction factor of each turbine + CHARACTER(LEN=11) :: Fastprefix_out = 'FastOutput_' ! Fast output file + CHARACTER(LEN=8) :: FastElmprefix_elm = 'FastElm_' ! Fast Elm output file + !CHARACTER(LEN=11) :: Smoothprefix_bin = 'Smoothwake_' ! Smoothed out wake for downwind turbines + CHARACTER(LEN=2) :: Uprefix_bin = 'U_' + CHARACTER(LEN=3) :: WCprefix_bin = 'WC_' + CHARACTER(LEN=7) :: MeanUprefix_bin = 'Mean_U_' + + + CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' + + IF (turbine_index <= 9) THEN + write(turbine_index_character,'(i1)') turbine_index + ELSEIF (turbine_index <= 99) THEN + write(turbine_index_character,'(i2)') turbine_index + ELSE + write(turbine_index_character,'(i3)') turbine_index + END IF + + filename_u = trim(Uprefix_txt)//trim(Turbineprefix)//trim(turbine_index_character)//".txt" + filename_wakecenter = trim(WCprefix_txt)//trim(Turbineprefix)//trim(turbine_index_character)//".txt" + filename_meanU = trim(MeanUprefix_txt)//trim(Turbineprefix)//trim(turbine_index_character)//".txt" + filename_TI = trim(TIprefix_txt)//trim(Turbineprefix)//trim(turbine_index_character)//".txt" + filename_A = trim(Inducprefix_txt)//trim(Turbineprefix)//trim(turbine_index_character)//".txt" + + filename_FastOutput = trim(Fastprefix_out)//trim(Turbineprefix)//trim(turbine_index_character)//".out" + filename_FastElm = trim(FastElmprefix_elm)//trim(Turbineprefix)//trim(turbine_index_character)//".elm" + + !filename_u_bin = trim(Uprefix_bin)//trim(Turbineprefix)//trim(turbine_index_character)//".bin" + !filename_wakecenter_bin = trim(WCprefix_bin)//trim(Turbineprefix)//trim(turbine_index_character)//".bin" + !filename_meanU_bin = trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(turbine_index_character)//".bin" + + +END SUBROUTINE rename_files + +!------------------------------------------------------------------- +SUBROUTINE delete_temp_files() +!................................................................... +! This routine is called to delete the temporary DWM binary files +!................................................................... + USE read_wind_farm_parameter_data, ONLY : NumWT + USE wind_farm_geometry_data, ONLY : TurbineInfluenceData + + + CHARACTER(LEN=3) :: invetigated_turbine_index_character + CHARACTER(LEN=3) :: downwind_turbine_index_character + CHARACTER(LEN=80) :: filename_u_bin,filename_wakecenter_bin,filename_meanU_bin,filename_TI_bin,filename_smoothWake_bin,filename_wakewidth_bin + CHARACTER(LEN=80) :: filename_TI_txt,filename_meanU_txt,filename_induction_txt,filename_wake_txt,filename_wakecenter_txt + CHARACTER(LEN=2) :: Uprefix_bin = 'U_' + CHARACTER(LEN=3) :: WCprefix_bin = 'WC_' + CHARACTER(LEN=7) :: MeanUprefix_bin = 'Mean_U_' + CHARACTER(LEN=3) :: Tiprefix_bin = 'TI_' + CHARACTER(LEN=11) :: SmoothWprefix_bin = 'Smoothwake_' + CHARACTER(LEN=10) :: InductionPrefix = 'Induction_' + CHARACTER(LEN=6) :: Wakeprefix = 'WakeU_' + CHARACTER(LEN=11) :: WWprefix_bin = 'Wake_width_' + CHARACTER(LEN=22) :: Prefix = 'DWM-results/' + CHARACTER(LEN=4) :: connectionprefix = '_to_' + CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' + INTEGER :: I,J,K + INTEGER :: downwindturbine_number + INTEGER,ALLOCATABLE :: downwind_turbine_index(:) + + + DO I = 1,NumWT + !bjj: you could call Num2LStr(I) instead of using this if statement: + IF (I <= 9) THEN + write(invetigated_turbine_index_character,'(i1)') I + ELSEIF (I <= 99) THEN + write(invetigated_turbine_index_character,'(i2)') I + ELSE + write(invetigated_turbine_index_character,'(i3)') I + END IF + + filename_meanU_bin = trim(Prefix)//trim(MeanUprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".bin" + OPEN (29, file=filename_meanU_bin) + CLOSE (29, status='delete') + + filename_wakecenter_bin = trim(Prefix)//trim(WCprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".bin" + OPEN (29, file=filename_wakecenter_bin) + CLOSE (29, status='delete') + END DO + + + + DO K = 1,NumWT + IF (K <= 9) THEN + write(invetigated_turbine_index_character,'(i1)') K + ELSEIF (K <= 99) THEN + write(invetigated_turbine_index_character,'(i2)') K + ELSE + write(invetigated_turbine_index_character,'(i3)') K + END IF + + + downwindturbine_number = 0 + IF (.NOT. ALLOCATED(downwind_turbine_index) ) THEN + ALLOCATE (downwind_turbine_index(NumWT-1)) + END IF + + DO I = 1,1 !Tinfluencer + DO J = 1,NumWT + IF (TurbineInfluenceData(J,I) == K) THEN + downwindturbine_number = downwindturbine_number + 1 + downwind_turbine_index(downwindturbine_number) = J + END IF + END DO + END DO + + IF (downwindturbine_number /= 0 ) THEN + DO I = 1,downwindturbine_number + IF (downwind_turbine_index(I) <= 9) THEN + write(downwind_turbine_index_character,'(i1)') downwind_turbine_index(I) + ELSEIF (downwind_turbine_index(I) <= 99) THEN + write(downwind_turbine_index_character,'(i2)') downwind_turbine_index(I) + ELSE + write(downwind_turbine_index_character,'(i3)') downwind_turbine_index(I) + END IF + + filename_u_bin = trim(Prefix)//trim(Uprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + filename_TI_bin = trim(Prefix)//trim(TIprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + filename_smoothWake_bin = trim(Prefix)//trim(SmoothWprefix_bin)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)& + //trim(connectionprefix)//trim(downwind_turbine_index_character)//".bin" + + OPEN (29, file=filename_u_bin) + CLOSE (29, status='delete') + + OPEN (29, file=filename_TI_bin) + CLOSE (29, status='delete') + + OPEN (29, file=filename_smoothWake_bin) + CLOSE (29, status='delete') + END DO + END IF + END DO + + + OPEN (29, file='turbine_angles.bin') + CLOSE (29, status='delete') + + OPEN (29, file='turbine_distance.bin') + CLOSE (29, status='delete') + + OPEN (29, file='turbine_interaction.bin') + CLOSE (29, status='delete') + + OPEN (29, file='wake_sector_angle.bin') + CLOSE (29, status='delete') + + OPEN (29, file='Wake_width_Turbine_0.bin') + CLOSE (29, status='delete') + + OPEN (29, file='WC_Turbine_0.bin') + CLOSE (29, status='delete') + + OPEN (29, file='wind_farm_turbine_sort.bin') + CLOSE (29, status='delete') + + +END SUBROUTINE delete_temp_files + +!------------------------------------------------------------------- +SUBROUTINE Driver_init() +!................................................................... +! This routine called to initiate the Driver program +!................................................................... + USE DWM_init_data, ONLY:OutFileRoot, InputFile + + INTEGER :: Stat + CHARACTER(1024) :: DirName + + CALL CheckArgs( InputFile, Stat ) + + CALL GetRoot( InputFile, OutFileRoot ) + + CALL Get_CWD ( DirName, Stat ) + +END SUBROUTINE Driver_init + +!---------------------------------------------------------------------------------- +SUBROUTINE rename_FAST_output(SimulationOrder_index) +!............................................................................ +! This routine is called to rename the fast output +!............................................................................ +#ifdef __INTEL_COMPILER + USE IFPORT +#endif + USE wind_farm_geometry_data, ONLY: turbine_sort + USE DWM_init_data, ONLY: OutFileRoot + + CHARACTER(LEN=80) :: filename_FastOutput,filename_FastElm + CHARACTER(LEN=11) :: Fastprefix = 'FastOutput_' ! Fast output file + CHARACTER(LEN=8) :: FastElmprefix = 'FastElm_' ! Fast Elm output file + INTEGER :: RESULT + CHARACTER(LEN=22) :: Prefix = 'DWM-results/' + CHARACTER(LEN=8) :: Turbineprefix = 'Turbine_' + CHARACTER(LEN=3) :: invetigated_turbine_index_character + INTEGER :: WT_index + INTEGER :: SimulationOrder_index + + IF ( SimulationOrder_index > 0 ) THEN ! exclude the first turbine + + WT_index = turbine_sort(SimulationOrder_index) + + IF (WT_index <= 9) THEN + write(invetigated_turbine_index_character,'(i1)') WT_index + ELSEIF (WT_index <= 99) THEN + write(invetigated_turbine_index_character,'(i2)') WT_index + ELSE + write(invetigated_turbine_index_character,'(i3)') WT_index + END IF + + ! Rename the FAST output wrt the turbine index + filename_FastOutput = trim(Prefix)//trim(Fastprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".out" + filename_FastElm = trim(Prefix)//trim(FastElmprefix)//trim(Turbineprefix)//trim(invetigated_turbine_index_character)//".AD.out" + + RESULT =rename( TRIM(OutFileRoot)//'.out', filename_FastOutput) !bjj: what if I'm using .outb in FAST instead of .out? + RESULT =rename( TRIM(OutFileRoot)//'.AD.out',filename_FastElm ) !bjj: *.elm has been renamed *.AD.out in FAST v8. Also, .AD.out files are not always generated. + END IF + +END SUBROUTINE rename_FAST_output + +END MODULE DWM_driver_wind_farm_sub \ No newline at end of file diff --git a/OpenFAST/modules/aerodyn14/src/GenSubs.f90 b/OpenFAST/modules/aerodyn14/src/GenSubs.f90 new file mode 100644 index 000000000..e02fd5cbc --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/GenSubs.f90 @@ -0,0 +1,669 @@ +!********************************************************************************************************************************** + MODULE AeroGenSubs + + + USE NWTC_LIBRARY + USE AeroDyn14_Types + +IMPLICIT NONE + +! SUBROUTINE AllocArrays( Arg ) +! SUBROUTINE ElemOpen( ElemFile ) +! SUBROUTINE ElemOut( ) + + INTEGER(IntKi) , PARAMETER :: MAXINFL = 6 + + + CONTAINS + ! **************************************************** + SUBROUTINE AllocArrays ( InitInp, P, xc, xd, z, m, y, Arg ) + ! Allocates space to the phenomenal number of arrays + ! we use in this program + ! **************************************************** + ! Passed Variables: + TYPE(AD14_InitInputType), INTENT(INOUT) :: InitInp + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_ContinuousStateType), INTENT(INOUT) :: xc ! Initial continuous states + TYPE(AD14_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states + TYPE(AD14_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states + TYPE(AD14_MiscVarType), INTENT(INOUT) :: m ! Initial misc/optimization variables + TYPE(AD14_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; + CHARACTER(*), INTENT(IN ) :: Arg + + ! Local Variables: + + INTEGER(4) :: Sttus + + INTEGER :: NElm, NB, MaxTable, NumCl, NumFoil, NumElOut, NumWndElOut + + +!bjj: I really don't understand why these aren't 3 separate subroutines... + + +NB = P%NumBl +Nelm = P%Element%Nelm +NumFoil = P%AirFoil%NumFoil +NumCl = P%AirFoil%NumCl +MaxTable = P%AirFoil%MaxTable +NumElOut = m%ElOut%NumElOut +NumWndElOut = m%ElOut%NumWndElOut + + +Sttus = 0.0 + +IF (Arg(1:7) == 'Element') THEN + + IF (.NOT. ALLOCATED(m%ElOut%ElPrList)) ALLOCATE ( m%ElOut%ElPrList(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ElPrList array.' ) + m%ElOut%ElPrList ( : ) = 0 + + IF (.NOT. ALLOCATED(m%ElOut%WndElPrList)) ALLOCATE ( m%ElOut%WndElPrList(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for WndElPrList array.' ) + m%ElOut%WndElPrList ( : ) = 0 + + IF (.NOT. ALLOCATED(m%Element%A)) ALLOCATE ( m%Element%A(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for A array.' ) + m%Element%A ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Element%AP)) ALLOCATE ( m%Element%AP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AP array.' ) + +! Beddoes arrays + IF (P%Dstall) THEN + + IF (.NOT. ALLOCATED(m%Beddoes%ADOT)) ALLOCATE ( m%Beddoes%ADOT(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ADOT array.' ) + m%Beddoes%ADOT ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%ADOT1)) ALLOCATE ( m%Beddoes%ADOT1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ADOT1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%AFE)) ALLOCATE ( m%Beddoes%AFE(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AFE array.' ) + m%Beddoes%AFE(:,:) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%AFE1)) ALLOCATE ( m%Beddoes%AFE1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AFE1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%ANE)) ALLOCATE ( m%Beddoes%ANE(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ANE array.' ) + m%Beddoes%ANE ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%ANE1)) ALLOCATE ( m%Beddoes%ANE1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ANE1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%AOD)) ALLOCATE ( m%Beddoes%AOD(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AOD array.' ) + m%Beddoes%AOD = 0.0_ReKi + + IF (.NOT. ALLOCATED(m%Beddoes%AOL)) ALLOCATE ( m%Beddoes%AOL(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AOL array.' ) + m%Beddoes%AOL = 0.0_ReKi + + + IF (.NOT. ALLOCATED(m%Beddoes%CDO)) ALLOCATE ( m%Beddoes%CDO(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CDO array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNA)) ALLOCATE ( m%Beddoes%CNA(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNA array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNP)) ALLOCATE ( m%Beddoes%CNP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNP array.' ) + m%Beddoes%CNP ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%CNP1)) ALLOCATE ( m%Beddoes%CNP1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNP1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNPD)) ALLOCATE ( m%Beddoes%CNPD(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNPD array.' ) + m%Beddoes%CNPD ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%CNPD1)) ALLOCATE ( m%Beddoes%CNPD1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNPD1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNPOT)) ALLOCATE ( m%Beddoes%CNPOT(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNPOT array.' ) + m%Beddoes%CNPOT ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%CNPOT1)) ALLOCATE ( m%Beddoes%CNPOT1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNPOT1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNS)) ALLOCATE ( m%Beddoes%CNS(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNS array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNSL)) ALLOCATE ( m%Beddoes%CNSL(NELM,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNSL array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%CNV)) ALLOCATE ( m%Beddoes%CNV(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNV array.' ) + m%Beddoes%CNV ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%CVN)) ALLOCATE ( m%Beddoes%CVN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CVN array.' ) + m%Beddoes%CVN ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%CVN1)) ALLOCATE ( m%Beddoes%CVN1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CVN1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%DF)) ALLOCATE ( m%Beddoes%DF(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DF array.' ) + m%Beddoes%DF( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DFAFE)) ALLOCATE ( m%Beddoes%DFAFE(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DFAFE array.' ) + m%Beddoes%DFAFE ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DFAFE1)) ALLOCATE ( m%Beddoes%DFAFE1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DFAFE1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%DFC)) ALLOCATE ( m%Beddoes%DFC(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DFC array.' ) + m%Beddoes%DFC ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DN)) ALLOCATE ( m%Beddoes%DN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DN array.' ) + m%Beddoes%DN ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DPP)) ALLOCATE ( m%Beddoes%DPP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DP array.' ) + m%Beddoes%DPP ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DQ)) ALLOCATE ( m%Beddoes%DQ(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DQ array.' ) + m%Beddoes%DQ ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DQP)) ALLOCATE ( m%Beddoes%DQP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DQP array.' ) + m%Beddoes%DQP ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%DQP1)) ALLOCATE ( m%Beddoes%DQP1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DQP1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%FSP)) ALLOCATE ( m%Beddoes%FSP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FSP array.' ) + m%Beddoes%FSP ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%FSP1)) ALLOCATE ( m%Beddoes%FSP1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FSP1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%FSPC)) ALLOCATE ( m%Beddoes%FSPC(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FSPC array.' ) + m%Beddoes%FSPC ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%FSPC1)) ALLOCATE ( m%Beddoes%FSPC1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FSPC1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDCNV)) ALLOCATE ( m%Beddoes%OLDCNV(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDCNV array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDDF)) ALLOCATE ( m%Beddoes%OLDDF(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDDF array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDDFC)) ALLOCATE ( m%Beddoes%OLDDFC(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDDFC array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDDN)) ALLOCATE ( m%Beddoes%OLDDN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDDN array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDDPP)) ALLOCATE ( m%Beddoes%OLDDPP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDDP array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDDQ)) ALLOCATE ( m%Beddoes%OLDDQ(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDDQ array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDTAU)) ALLOCATE ( m%Beddoes%OLDTAU(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDTAU array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDXN)) ALLOCATE ( m%Beddoes%OLDXN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDXN array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%OLDYN)) ALLOCATE ( m%Beddoes%OLDYN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDYN array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%QX)) ALLOCATE ( m%Beddoes%QX(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for QX array.' ) + m%Beddoes%QX ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%QX1)) ALLOCATE ( m%Beddoes%QX1(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for QX1 array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%TAU)) ALLOCATE ( m%Beddoes%TAU(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for TAU array.' ) + m%Beddoes%TAU(:,:) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%XN)) ALLOCATE ( m%Beddoes%XN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for XN array.' ) + m%Beddoes%XN ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%YN)) ALLOCATE ( m%Beddoes%YN(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for YN array.' ) + m%Beddoes%YN ( :, : ) = 0.0 + + IF (.NOT. ALLOCATED(m%Beddoes%OLDSEP)) ALLOCATE ( m%Beddoes%OLDSEP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for OLDSEP array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%BEDSEP)) ALLOCATE ( m%Beddoes%BEDSEP(NELM,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for BEDSEP array.' ) + m%Beddoes%BEDSEP(:,:) = .FALSE. + + ENDIF ! Beddoes arrays + + IF (.NOT. ALLOCATED(P%Blade%C)) ALLOCATE ( P%Blade%C(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for C array.' ) + + IF (.NOT. ALLOCATED(P%Blade%DR)) ALLOCATE ( P%Blade%DR(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DR array.' ) + + IF (.NOT. ALLOCATED(P%Element%RELM)) ALLOCATE ( P%Element%RELM(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for RELM array.' ) + + IF (.NOT. ALLOCATED(P%Element%TWIST)) ALLOCATE ( P%Element%TWIST(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for TWIST array.' ) + + IF (.NOT. ALLOCATED(P%Element%TLCNST)) ALLOCATE ( P%Element%TLCNST(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for TLCNST array.' ) + P%Element%TLCNST = 99.0 + + IF (.NOT. ALLOCATED(P%Element%HLCNST)) ALLOCATE ( P%Element%HLCNST(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for HLCNST array.' ) + P%Element%HLCNST = 99.0 + + IF (.NOT. ALLOCATED(P%AirFoil%NFOIL)) ALLOCATE ( P%AirFoil%NFOIL(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for NFOIL array.' ) + + IF (.NOT. ALLOCATED(P%AirFoil%NLIFT)) ALLOCATE ( P%AirFoil%NLIFT(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for NLIFT array.' ) + + IF (.NOT. ALLOCATED(P%AirFoil%NTables)) ALLOCATE ( P%AirFoil%NTables(NELM) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for NTables array.' ) + + IF (P%Dyninfl .OR. m%Dyninit) THEN + IF (.NOT. ALLOCATED(m%DynInflow%RMC_SAVE)) ALLOCATE ( m%DynInflow%RMC_SAVE ( NB, NELM, MAXINFL ) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for RMC_SAVE array.' ) + m%DynInflow%RMC_SAVE = 0.0 + + IF (.NOT. ALLOCATED(m%DynInflow%RMS_SAVE)) ALLOCATE ( m%DynInflow%RMS_SAVE ( NB, NELM, MAXINFL ) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for RMS_SAVE array.' ) + m%DynInflow%RMS_SAVE = 0.0 + ENDIF + +ELSEIF (Arg(1:7) == 'ElPrint') THEN + + IF ( m%ElOut%NumElOut > 0 ) THEN + IF (.NOT. ALLOCATED(m%ElOut%AAA)) ALLOCATE ( m%ElOut%AAA(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AAA array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%AAP)) ALLOCATE ( m%ElOut%AAP(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AAP array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%ALF)) ALLOCATE ( m%ElOut%ALF(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ALF array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%CDD)) ALLOCATE ( m%ElOut%CDD(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CDD array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%CLL)) ALLOCATE ( m%ElOut%CLL(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CLL array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%CMM)) ALLOCATE ( m%ElOut%CMM(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CMM array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%CNN)) ALLOCATE ( m%ElOut%CNN(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CNN array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%CTT)) ALLOCATE ( m%ElOut%CTT(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CTT array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%DFNSAV)) ALLOCATE ( m%ElOut%DFNSAV(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DFNSAV array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%DFTSAV)) ALLOCATE ( m%ElOut%DFTSAV(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DFTSAV array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%DynPres)) ALLOCATE ( m%ElOut%DynPres(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for DynPres array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%PMM)) ALLOCATE ( m%ElOut%PMM(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for PMM array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%PITSAV)) ALLOCATE ( m%ElOut%PITSAV(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for PITSAV array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%ReyNum)) ALLOCATE ( m%ElOut%ReyNum(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ReyNum array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%Gamma)) ALLOCATE ( m%ElOut%Gamma(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for Gamma array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%ElPrNum)) ALLOCATE ( m%ElOut%ElPrNum(NumElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for ElPrNum array.' ) + m%ElOut%ElPrNum ( : ) = 0 + + END IF + + IF ( NumWndElOut > 0 ) THEN + + IF (.NOT. ALLOCATED(m%ElOut%WndElPrNum)) ALLOCATE ( m%ElOut%WndElPrNum(NumWndElOut) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for WndElPrNum array.' ) + m%ElOut%WndElPrNum ( : ) = 0 + + IF (.NOT. ALLOCATED(m%ElOut%SaveVX)) ALLOCATE ( m%ElOut%SaveVX(NumWndElOut,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for SaveVX array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%SaveVY)) ALLOCATE ( m%ElOut%SaveVY(NumWndElOut,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for SaveVY array.' ) + + IF (.NOT. ALLOCATED(m%ElOut%SaveVZ)) ALLOCATE ( m%ElOut%SaveVZ(NumWndElOut,NB) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for SaveVZ array.' ) + + END IF + +ELSEIF (Arg(1:8) == 'Aerodata') THEN + + IF (.NOT. ALLOCATED(m%AirFoil%AL)) ALLOCATE ( m%AirFoil%AL(NumFoil,NumCL) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for AL array.' ) + + IF (.NOT. ALLOCATED(m%AirFoil%CD)) ALLOCATE ( m%AirFoil%CD(NumFoil,NumCL,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CD array.' ) + + IF (.NOT. ALLOCATED(m%AirFoil%CL)) ALLOCATE ( m%AirFoil%CL(NumFoil,NumCL,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CL array.' ) + + IF (.NOT. ALLOCATED(m%AirFoil%CM)) ALLOCATE ( m%AirFoil%CM(NumFoil,NumCL,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for CM array.' ) + + IF (.NOT. ALLOCATED(p%AirFoil%MulTabMet)) ALLOCATE ( p%AirFoil%MulTabMet(NumFoil,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for MulTabMet array.' ) + + IF (P%DSTALL) THEN + + IF (.NOT. ALLOCATED(m%Beddoes%FTB)) ALLOCATE ( m%Beddoes%FTB(NumFoil,NumCL,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FTB array.' ) + + IF (.NOT. ALLOCATED(m%Beddoes%FTBC)) ALLOCATE ( m%Beddoes%FTBC(NumFoil,NumCL,MAXTABLE) , STAT=Sttus ) + IF ( Sttus /= 0 ) CALL ProgAbort ( ' Error allocating memory for FTBC array.' ) + + ENDIF ! Beddoes arrays + +!jm we did not recognize the argument consider that an error +ELSE + + CALL ProgAbort( 'Unknown switch argument to AllocArrays' ) + +ENDIF + + + +RETURN +END SUBROUTINE AllocArrays + + ! ***************************************************** + SUBROUTINE ElemOpen (ElemFile, P, m, ErrStat, ErrMsg, AD14_Ver ) + ! This subroutine opens the element output file and writes + ! column headings separated by tab characters + ! ElemFile = file name + ! ***************************************************** + + ! Passed Variables: + CHARACTER(*), INTENT(IN) :: ElemFile + TYPE(AD14_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(AD14_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 + TYPE(ProgDesc) , INTENT(IN) :: AD14_Ver + + ! Local Variables: + +INTEGER(4) :: JE + +INTEGER(4) :: JB ! Counter for number of blades + +CHARACTER( 2) :: Dst_Unit +CHARACTER( 2) :: Frc_Unit +CHARACTER(140) :: Frmt +CHARACTER( 3) :: Prs_Unit + + +ErrStat = ErrID_None +ErrMsg = "" + + + +IF (m%ElOut%NumWndElOut > 0) THEN + CALL GetNewUnit(P%UnWndOut) + CALL OpenFOutFile (P%UnWndOut, TRIM(ElemFile)//'.wind', ErrStat, ErrMsg) + IF (ErrStat /= ErrID_None) RETURN + WRITE (P%UnWndOut,"( 'This file was generated by ' , A , ' on ' , A , ' at ' , A , '.' )") & + TRIM(GETNVD(AD14_Ver)), CurDate(), CurTime() +ENDIF + + + ! Open the Element Print file if requested +IF (p%ELEMPRN) THEN + CALL GetNewUnit(P%UnElem) + CALL OpenFOutFile (p%UnElem, TRIM(ElemFile), ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + WRITE (p%UnElem,"(/, 'This file was generated by ' , A , ' on ' , A , ' at ' , A , '.' )") & + TRIM(GETNVD(AD14_Ver)), CurDate(), CurTime() + WRITE (p%UnElem,'(/,/,/)') ! write some blank lines so the output file so the headers are on the same line as FAST's +ELSE + RETURN +ENDIF + + ! Set the units labels +IF (p%SIUNIT) THEN + Dst_Unit = 'm' + Frc_Unit = 'N' + Prs_Unit = 'Pa' +ELSE + Dst_Unit = 'ft' + Frc_Unit = 'lb' + Prs_Unit = 'psf' +ENDIF + + +Frmt = '( A4, 3(A1,A2,I2.2), (: A1, A, I2.2 ) )' + +IF ( p%PMOMENT ) THEN + WRITE(Frmt(22:24), '(I3)') 15*m%ElOut%NumElOut + WRITE(p%UnElem, Frmt) 'Time', & + TAB, 'VX', p%Element%NELM, & + TAB, 'VY', p%Element%NELM, & + TAB, 'VZ', p%Element%NELM, & + ( TAB, 'Alpha', m%ElOut%ElPrNum(JE), & + TAB, 'DynPres', m%ElOut%ElPrNum(JE), & + TAB, 'CLift', m%ElOut%ElPrNum(JE), & + TAB, 'CDrag', m%ElOut%ElPrNum(JE), & + TAB, 'CNorm', m%ElOut%ElPrNum(JE), & + TAB, 'CTang', m%ElOut%ElPrNum(JE), & + TAB, 'CMomt', m%ElOut%ElPrNum(JE), & + TAB, 'Pitch', m%ElOut%ElPrNum(JE), & + TAB, 'AxInd', m%ElOut%ElPrNum(JE), & + TAB, 'TanInd', m%ElOut%ElPrNum(JE), & + TAB, 'ForcN', m%ElOut%ElPrNum(JE), & + TAB, 'ForcT', m%ElOut%ElPrNum(JE), & + TAB, 'Pmomt', m%ElOut%ElPrNum(JE), & + TAB, 'ReNum', m%ElOut%ElPrNum(JE), & + TAB, 'Gamma', m%ElOut%ElPrNum(JE), & + JE = 1, m%ElOut%NumElOut ) + + Frmt = '( A5, 3(A1,A8), (: A1, A ) )' + WRITE(Frmt(17:19), '(I3)') 15*m%ElOut%NumElOut + WRITE(p%UnElem, Frmt) '(sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + ( TAB, '(deg)', & + TAB, '('//TRIM(Prs_Unit)//')', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(deg)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '('//TRIM(Frc_Unit)//')', & + TAB, '('//TRIM(Frc_Unit)//')', & + TAB, '('//TRIM(Frc_Unit)//'-'//TRIM(Dst_Unit)//')', & + TAB, '(x10^6)', & + TAB, '(m^2/sec)', & + JE = 1, m%ElOut%NumElOut ) + +ELSE + WRITE(Frmt(22:24), '(I3)') 13*m%ElOut%NumElOut + WRITE(p%UnElem, Frmt) 'Time', & + TAB, 'VX', p%Element%NELM, & + TAB, 'VY', p%Element%NELM, & + TAB, 'VZ', p%Element%NELM, & + ( TAB, 'Alpha', m%ElOut%ElPrNum(JE), & + TAB, 'DynPres', m%ElOut%ElPrNum(JE), & + TAB, 'CLift', m%ElOut%ElPrNum(JE), & + TAB, 'CDrag', m%ElOut%ElPrNum(JE), & + TAB, 'CNorm', m%ElOut%ElPrNum(JE), & + TAB, 'CTang', m%ElOut%ElPrNum(JE), & + TAB, 'Pitch', m%ElOut%ElPrNum(JE), & + TAB, 'AxInd', m%ElOut%ElPrNum(JE), & + TAB, 'TanInd', m%ElOut%ElPrNum(JE), & + TAB, 'ForcN', m%ElOut%ElPrNum(JE), & + TAB, 'ForcT', m%ElOut%ElPrNum(JE), & + TAB, 'ReNum', m%ElOut%ElPrNum(JE), & + TAB, 'Gamma', m%ElOut%ElPrNum(JE), & + JE = 1, m%ElOut%NumElOut ) + + Frmt = '( A5, 3(A1,A8), (: A1, A ) )' + WRITE(Frmt(17:19), '(I3)') 13*m%ElOut%NumElOut + WRITE(p%UnElem, Frmt) '(sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + ( TAB, '(deg)', & + TAB, '('//TRIM(Prs_Unit)//')', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '(deg)', & + TAB, '(-)', & + TAB, '(-)', & + TAB, '('//TRIM(Frc_Unit)//')', & + TAB, '('//TRIM(Frc_Unit)//')', & + TAB, '(x10^6)', & + TAB, '(m^2/sec)', & + JE = 1, m%ElOut%NumElOut ) +ENDIF + +IF ( m%ElOut%NumWndElOut > 0 ) THEN + Frmt = '( A4, XXX(A1,A2,I2.2,"-B",I1.1) )' + WRITE(Frmt(7:9), '(I3)') 3*m%ElOut%NumWndElOut*p%NumBl + + WRITE(p%UnWndOut, Frmt) 'Time', & + ( ( TAB, 'VX', m%ElOut%WndElPrNum(JE), JB, & + TAB, 'VY', m%ElOut%WndElPrNum(JE), JB, & + TAB, 'VZ', m%ElOut%WndElPrNum(JE), JB, & + JE = 1, m%ElOut%NumWndElOut ) , & + JB = 1, p%NumBl ) + + Frmt = '( A5, XXX(A1,A8) )' + WRITE(Frmt(7:9), '(I3)') 3*m%ElOut%NumWndElOut*p%NumBl + + WRITE(p%UnWndOut, Frmt) '(sec)', & + ( TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + TAB, '('//TRIM(Dst_Unit)//'/sec)', & + JE = 1, m%ElOut%NumWndElOut*p%NumBl ) +ENDIF + +RETURN +END SUBROUTINE ElemOpen + + + ! ***************************************************** + SUBROUTINE ElemOut( time, P, m ) + ! This subroutine writes the element output values + ! for the desired elements + ! ***************************************************** + + + REAL(DbKi), INTENT(IN) :: time + TYPE(AD14_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(AD14_MiscVarType), INTENT(IN) :: m ! misc/optimization variables + + + ! Local Variables: + + INTEGER(IntKi) :: JE + INTEGER(IntKi) :: JB ! Counter for number of blades + CHARACTER(30) :: Frmt + + + ! Write the element data if requested +IF (p%ELEMPRN) THEN + + Frmt = '( F10.3, ( : A1, ES12.5 ) )' + + IF ( P%PMOMENT ) THEN + WRITE(Frmt(10:12), '(I3)') 15*m%ElOut%NumElOut + 3 + WRITE(p%UnElem,Frmt) TIME, & + TAB, m%ElOut%VXSAV, & + TAB, m%ElOut%VYSAV, & + TAB, m%ElOut%VZSAV, & + ( TAB, m%ElOut%ALF (JE), & + TAB, m%ElOut%DynPres(JE), & + TAB, m%ElOut%CLL (JE), & + TAB, m%ElOut%CDD (JE), & + TAB, m%ElOut%CNN (JE), & + TAB, m%ElOut%CTT (JE), & + TAB, m%ElOut%CMM (JE), & + TAB, m%ElOut%PITSAV (JE), & + TAB, m%ElOut%AAA (JE), & + TAB, m%ElOut%AAP (JE), & + TAB, m%ElOut%DFNSAV (JE), & + TAB, m%ElOut%DFTSAV (JE), & + TAB, m%ElOut%PMM (JE), & + TAB, m%ElOut%ReyNum (JE), & + TAB, m%ElOut%Gamma (JE), & + JE= 1, m%ElOut%NumElOut ) + + + ELSE + WRITE(Frmt(10:12), '(I3)') 13*m%ElOut%NumElOut + 3 + WRITE(p%UnElem,Frmt) TIME, & + TAB, m%ElOut%VXSAV, & + TAB, m%ElOut%VYSAV, & + TAB, m%ElOut%VZSAV, & + ( TAB, m%ElOut%ALF (JE), & + TAB, m%ElOut%DynPres(JE), & + TAB, m%ElOut%CLL (JE), & + TAB, m%ElOut%CDD (JE), & + TAB, m%ElOut%CNN (JE), & + TAB, m%ElOut%CTT (JE), & + TAB, m%ElOut%PITSAV (JE), & + TAB, m%ElOut%AAA (JE), & + TAB, m%ElOut%AAP (JE), & + TAB, m%ElOut%DFNSAV (JE), & + TAB, m%ElOut%DFTSAV (JE), & + TAB, m%ElOut%ReyNum (JE), & + TAB, m%ElOut%Gamma (JE), & + JE= 1, m%ElOut%NumElOut ) + ENDIF ! PMOMENT + +IF (m%ElOut%NumWndElOut > 0) THEN + + WRITE(Frmt(10:12), '(I3)') 3*m%ElOut%NumWndElOut*p%NumBl + WRITE(p%UnWndOut,Frmt) TIME, & + ( ( TAB, m%ElOut%SaveVX( JE, JB ), & + TAB, m%ElOut%SaveVY( JE, JB ), & + TAB, m%ElOut%SaveVZ( JE, JB ), & + JE = 1,m%ElOut%NumWndElOut ), JB = 1,p%NumBl ) +ENDIF + +ENDIF ! ELEMPRN + + + +RETURN +END SUBROUTINE ElemOut +!======================================================================= + +END MODULE AeroGenSubs diff --git a/OpenFAST/modules/aerodyn14/src/Registry-AD14.txt b/OpenFAST/modules/aerodyn14/src/Registry-AD14.txt new file mode 100644 index 000000000..59eceb2c7 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/Registry-AD14.txt @@ -0,0 +1,412 @@ +################################################################################################################################### +# Registry for AeroDyn14 in the FAST Modularization Framework +# This Registry file is used to create MODULE AeroDyn_Types which contains all of the user-defined types needed in AeroDyn14. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +################################################################################################################################### +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +include Registry_NWTC_Library.txt +usefrom Registry-DWM.txt + +# AeroDyn Subtypes +typedef AeroDyn14/AD14 Marker Reki Position 3 0.0 - - +typedef ^ Marker ^ Orientation {3}{3} 0.0 - - +typedef ^ Marker ^ TranslationVel 3 0.0 - - +typedef ^ Marker ^ RotationVel 3 0.0 - - + +#ADOptions +#typedef AeroDyn14/AD14 ADOptions CHARACTER(1024) ADFile +#typedef ^ ADOptions CHARACTER(1024) RootName +#typedef ^ ADOptions CHARACTER(1024) SumFile +#typedef ^ ADOptions LOGICAL WrSumFile + +#AeroConfig +typedef AeroDyn14/AD14 AeroConfig Marker Blade {:} - - - +typedef ^ AeroConfig ^ Hub - - - - +typedef ^ AeroConfig ^ RotorFurl - - - - +typedef ^ AeroConfig ^ Nacelle - - - - +typedef ^ AeroConfig ^ TailFin - - - - +typedef ^ AeroConfig ^ Tower - - - - +typedef ^ AeroConfig ^ SubStructure - - - - +typedef ^ AeroConfig ^ Foundation - - - - +typedef ^ AeroConfig ReKi BladeLength - - - - + + +#Airfoil +typedef AeroDyn14/AD14 AirFoil ReKi AL {:}{:} - - - +typedef ^ AirFoil ReKi CD {:}{:}{:} - - - +typedef ^ AirFoil ReKi CL {:}{:}{:} - - - +typedef ^ AirFoil ReKi CM {:}{:}{:} - - - +typedef ^ AirFoil ReKi PMC - - - - +typedef ^ AirFoil ReKi MulTabLoc - +typedef ^ AirFoilParms IntKi MaxTable - 20 - +typedef ^ AirFoilParms IntKi NTables {:} - - - +typedef ^ AirFoilParms IntKi NLift {:} - - - +typedef ^ AirFoilParms IntKi NumCL - - - - +typedef ^ AirFoilParms IntKi NumFoil - - - +typedef ^ AirFoilParms IntKi NFoil {:} - - - +typedef ^ AirFoilParms ReKi MulTabMet {:}{:} - - - +typedef ^ AirFoilParms CHARACTER(1024) FoilNm {:} "Number of airfoil data sets" + +#Beddoes +typedef ^ Beddoes ReKi ADOT {:}{:} - - - +typedef ^ Beddoes ReKi ADOT1 {:}{:} - - - +typedef ^ Beddoes ReKi AFE {:}{:} - - - +typedef ^ Beddoes ReKi AFE1 {:}{:} - - - +typedef ^ Beddoes ReKi AN - - - - +typedef ^ Beddoes ReKi ANE {:}{:} - - - +typedef ^ Beddoes ReKi ANE1 {:}{:} - - - +typedef ^ Beddoes ReKi AOD {:}{:} - - - +typedef ^ Beddoes ReKi AOL {:}{:} - - - +typedef ^ Beddoes LOGICAL BEDSEP {:}{:} - - - +typedef ^ Beddoes LOGICAL OLDSEP {:}{:} - - - +typedef ^ Beddoes ReKi CC - - - - +typedef ^ Beddoes ReKi CDO {:}{:} - - - +typedef ^ Beddoes ReKi CMI - - - - +typedef ^ Beddoes ReKi CMQ - - - - +typedef ^ Beddoes ReKi CN - - - - +typedef ^ Beddoes ReKi CNA {:}{:} - - - +typedef ^ Beddoes ReKi CNCP - - - - +typedef ^ Beddoes ReKi CNIQ - - - - +typedef ^ Beddoes ReKi CNP {:}{:} - - - +typedef ^ Beddoes ReKi CNP1 {:}{:} - - - +typedef ^ Beddoes ReKi CNPD {:}{:} - - - +typedef ^ Beddoes ReKi CNPD1 {:}{:} - - - +typedef ^ Beddoes ReKi CNPOT {:}{:} - - - +typedef ^ Beddoes ReKi CNPOT1 {:}{:} - - - +typedef ^ Beddoes ReKi CNS {:}{:} - - - +typedef ^ Beddoes ReKi CNSL {:}{:} - - - +typedef ^ Beddoes ReKi CNV {:}{:} - - - +typedef ^ Beddoes ReKi CVN {:}{:} - - - +typedef ^ Beddoes ReKi CVN1 {:}{:} - - - +typedef ^ Beddoes ReKi DF {:}{:} - - - +typedef ^ Beddoes ReKi DFAFE {:}{:} - - - +typedef ^ Beddoes ReKi DFAFE1 {:}{:} - - - +typedef ^ Beddoes ReKi DFC {:}{:} - - - +typedef ^ Beddoes ReKi DN {:}{:} - - - +typedef ^ Beddoes ReKi DPP {:}{:} - - - +typedef ^ Beddoes ReKi DQ {:}{:} - - - +typedef ^ Beddoes ReKi DQP {:}{:} - - - +typedef ^ Beddoes ReKi DQP1 {:}{:} - - - +typedef ^ Beddoes ReKi DS - - - - +typedef ^ Beddoes ReKi FK - - - - +typedef ^ Beddoes ReKi FP - - - - +typedef ^ Beddoes ReKi FPC - - - - +typedef ^ Beddoes ReKi FSP {:}{:} - - - +typedef ^ Beddoes ReKi FSP1 {:}{:} - - - +typedef ^ Beddoes ReKi FSPC {:}{:} - - - +typedef ^ Beddoes ReKi FSPC1 {:}{:} - - - +typedef ^ Beddoes ReKi FTB {:}{:}{:} - - - +typedef ^ Beddoes ReKi FTBC {:}{:}{:} - - - +typedef ^ Beddoes ReKi OLDCNV {:}{:} - - - +typedef ^ Beddoes ReKi OLDDF {:}{:} - - - +typedef ^ Beddoes ReKi OLDDFC {:}{:} - - - +typedef ^ Beddoes ReKi OLDDN {:}{:} - - - +typedef ^ Beddoes ReKi OLDDPP {:}{:} - - - +typedef ^ Beddoes ReKi OLDDQ {:}{:} - - - +typedef ^ Beddoes ReKi OLDTAU {:}{:} - - - +typedef ^ Beddoes ReKi OLDXN {:}{:} - - - +typedef ^ Beddoes ReKi OLDYN {:}{:} - - - +typedef ^ Beddoes ReKi QX {:}{:} - - - +typedef ^ Beddoes ReKi QX1 {:}{:} - - - +typedef ^ Beddoes ReKi TAU {:}{:} - - - +typedef ^ Beddoes ReKi XN {:}{:} - - - +typedef ^ Beddoes ReKi YN {:}{:} - - - +typedef ^ BeddoesParms ReKi AS - - - "Speed of sound for mach num calc" - +typedef ^ BeddoesParms ReKi TF - - - "Time constant applied to loc of separation pt" - +typedef ^ BeddoesParms ReKi TP - - - "Time constant for pressure lag" - +typedef ^ BeddoesParms ReKi TV - - - "Time constant for strength and shed of vortex" - +typedef ^ BeddoesParms ReKi TVL - - - "Nondim time of transit of vort moving across airfoil surf" - +typedef ^ Beddoes LOGICAL SHIFT - - - - +typedef ^ Beddoes LOGICAL VOR - - - - + +#Blade +typedef ^ BladeParms ReKi C {:} - - "Chord of each blade element from input file" +typedef ^ BladeParms ReKi DR {:} - - "Span-wise width of elem (len of elem ctred at RELM(i)" +typedef ^ BladeParms ReKi R - - - "Rotor radius" +typedef ^ BladeParms ReKi BladeLength - - - "Blade Length" +#typedef ^ BladeParms INTEGER NB - - - "Number odem blades" + +#DynInflow +dimspec maxinfl constant=6 +dimspec maxinfl0 constant=2 +dimspec maxinfl1 constant=3:6 +typedef AeroDyn14/AD14 DynInflow ReKi dAlph_dt {maxinfl}{4} - - +typedef ^ DynInflow ReKi dBeta_dt {maxinfl1}{4} - - +typedef ^ DynInflow ReKi DTO - - - +typedef ^ DynInflow ReKi old_Alph {maxinfl} - - +typedef ^ DynInflow ReKi old_Beta {maxinfl1} - - +typedef ^ DynInflow ReKi old_LmdM - - - +typedef ^ DynInflow ReKi oldKai - - - +typedef ^ DynInflow ReKi PhiLqC {maxinfl} - - +typedef ^ DynInflow ReKi PhiLqS {maxinfl1} - - +typedef ^ DynInflow ReKi Pzero - - - +typedef ^ DynInflow ReKi RMC_SAVE {:}{:}{:} - - - +typedef ^ DynInflow ReKi RMS_SAVE {:}{:}{:} - - - +typedef ^ DynInflow ReKi TipSpeed - - - +typedef ^ DynInflow ReKi totalInf - - - +typedef ^ DynInflow ReKi Vparam - - - +typedef ^ DynInflow ReKi Vtotal - - - +typedef ^ DynInflow ReKi xAlpha {maxinfl} - - +typedef ^ DynInflow ReKi xBeta {maxinfl1} - - +typedef ^ DynInflow ReKi xKai - - - +typedef ^ DynInflow ReKi XLAMBDA_M - - - +typedef ^ DynInflow ReKi xLcos {maxinfl}{maxinfl} - - +typedef ^ DynInflow ReKi xLsin {maxinfl1}{maxinfl1} - - +typedef ^ DynInflow IntKi MminR {maxinfl}{maxinfl} - - +typedef ^ DynInflow IntKi MminusR {maxinfl}{maxinfl} - - +typedef ^ DynInflow IntKi MplusR {maxinfl}{maxinfl} - - +typedef ^ DynInflow ReKi GAMMA {maxinfl}{maxinfl} - - +#typedef ^ DynInflowParms IntKi MAXINFL - 6 - #should be possible to spec with maxinfl +typedef ^ DynInflowParms IntKi MAXINFLO - 2 - #should be possible to spec with maxinfl0 +#typedef ^ DynInflowParms IntKi MRvector {maxinfl} - - +#typedef ^ DynInflowParms IntKi NJvector {maxinfl} - - +typedef ^ DynInflowParms ReKi xMinv {maxinfl} - - + +#Element +typedef ^ Element ReKi A {:}{:} - - - "Axial induction factor" - +typedef ^ Element ReKi AP {:}{:} - - - "Tangential induction factor" - +typedef ^ Element ReKi ALPHA {:}{:} - - - "Angle of attack" rad +typedef ^ Element ReKi W2 {:}{:} - - - "Relative velocity norm " m/s +typedef ^ Element ReKi OLD_A_NS {:}{:} - - - #allocated in VIND +typedef ^ Element ReKi OLD_AP_NS {:}{:} - - - #allocated in VIND +typedef ^ Element ReKi PITNOW :: - - - "Current pitch angle - Based on blade orientation (to verify)" rad +typedef ^ ElementParms IntKi NELM - - - - "Number of elements (constant)" - +typedef ^ ElementParms ReKi TWIST {:} - - - "Airfoil twist angle (constant)" - rad +typedef ^ ElementParms ReKi RELM {:} - - - "Radius of element (constant)" m +typedef ^ ElementParms ReKi HLCNST {:} - - - "Hub loss constant B/2*(r-rh)/rh (constant)" - +typedef ^ ElementParms ReKi TLCNST {:} - - - "Tip loss constant B/2*(R-r)/R (constant) " - + +#ElOutParams +typedef ^ ElOutParms ReKi AAA {:} - - - +typedef ^ ElOutParms ReKi AAP {:} - - - +typedef ^ ElOutParms ReKi ALF {:} - - - +typedef ^ ElOutParms ReKi CDD {:} - - - +typedef ^ ElOutParms ReKi CLL {:} - - - +typedef ^ ElOutParms ReKi CMM {:} - - - +typedef ^ ElOutParms ReKi CNN {:} - - - +typedef ^ ElOutParms ReKi CTT {:} - - - +typedef ^ ElOutParms ReKi DFNSAV {:} - - - +typedef ^ ElOutParms ReKi DFTSAV {:} - - - +typedef ^ ElOutParms ReKi DynPres {:} - - - +typedef ^ ElOutParms ReKi PMM {:} - - - +typedef ^ ElOutParms ReKi PITSAV {:} - - - +typedef ^ ElOutParms ReKi ReyNum {:} - - - +typedef ^ ElOutParms ReKi Gamma {:} - - - "Circulation along the span, 1/2 c Vrel Cl" m^2/s +typedef ^ ElOutParms ReKi SaveVX {:}{:} - - - +typedef ^ ElOutParms ReKi SaveVY {:}{:} - - - +typedef ^ ElOutParms ReKi SaveVZ {:}{:} - - - +typedef ^ ElOutParms ReKi VXSAV - - - - +typedef ^ ElOutParms ReKi VYSAV - - - - +typedef ^ ElOutParms ReKi VZSAV - - - - +typedef ^ ElOutParms IntKi NumWndElOut - - - "Number of Blade Elements" +typedef ^ ElOutParms IntKi WndElPrList {:} - - - +typedef ^ ElOutParms IntKi WndElPrNum {:} - - - +typedef ^ ElOutParms IntKi ElPrList {:} - - - +typedef ^ ElOutParms IntKi ElPrNum {:} - - - +typedef ^ ElOutParms IntKi NumElOut - - - "Number of Blade Elements" + +#InducedVel +typedef ^ InducedVel ReKi SumInFl - 0 - +typedef ^ InducedVelParms ReKi AToler - - - "Convergence tolerance for induction factor" - +typedef ^ InducedVelParms ReKi EqAIDmult - - - "Multiplier for drag term in axial-induction equation." +typedef ^ InducedVelParms LOGICAL EquilDA - - - "False unless DB or DA appended to EQUIL" +typedef ^ InducedVelParms LOGICAL EquilDT - - - "False unless DB or DT appended to EQUIL" +typedef ^ InducedVelParms LOGICAL TLoss - - - "Tip-loss model (EQUIL only) [PRANDtl, GTECH, or NONE]" +typedef ^ InducedVelParms LOGICAL GTech - - - "Tip-loss model (EQUIL only) [PRANDtl, GTECH, or NONE]" +typedef ^ InducedVelParms LOGICAL HLoss - - - "Hub-loss model (EQUIL only) [PRANDtl or NONE]" + + +#Rotor +typedef ^ Rotor ReKi AVGINFL - - - "average induced velocity at the previous time" +typedef ^ Rotor ReKi CTILT - - - +typedef ^ Rotor ReKi CYaw - - - +typedef ^ Rotor ReKi REVS - - - +typedef ^ Rotor ReKi STILT - - - +typedef ^ Rotor ReKi SYaw - - - +typedef ^ Rotor ReKi TILT - - - +typedef ^ Rotor ReKi YawAng - - - +typedef ^ Rotor ReKi YawVEL - - - +typedef ^ RotorParms ReKi HH - - - + +#TwrProps +typedef ^ TwrPropsParms ReKi TwrHtFr {:} - - +typedef ^ TwrPropsParms ReKi TwrWid {:} - - +typedef ^ TwrPropsParms ReKi TwrCD {:}{:} - - +typedef ^ TwrPropsParms ReKi TwrRe {:} - - +typedef ^ TwrPropsParms ReKi VTwr 3 - - +typedef ^ TwrPropsParms ReKi Tower_Wake_Constant - - - +typedef ^ TwrPropsParms IntKi NTwrCDCol {:} - - "The tower CD column that represents a particular twr ht" +typedef ^ TwrPropsParms IntKi NTwrHT - - - "The number of tower height rows in the table" +typedef ^ TwrPropsParms IntKi NTwrRe - - - "The number of tower Re entry rows in the table" +typedef ^ TwrPropsParms IntKi NTwrCD - - - "The number of tower CD columns in the table" +typedef ^ TwrPropsParms LOGICAL TwrPotent - - - "Tower influence model" +typedef ^ TwrPropsParms LOGICAL TwrShadow - - - "Tower shadow model" +typedef ^ TwrPropsParms ReKi ShadHWid - - - "Tower-shadow half width" m +typedef ^ TwrPropsParms ReKi TShadC1 - - - "Tower-shadow constant" +typedef ^ TwrPropsParms ReKi TShadC2 - - - "Tower-shadow constant" +typedef ^ TwrPropsParms ReKi TwrShad - - - "Tower-shadow velocity deficit" +typedef ^ TwrPropsParms LOGICAL PJM_Version - - - "Only true if new tower influence model, by PJM" +typedef ^ TwrPropsParms CHARACTER(1024) TwrFile - - - "Tower data file name" +typedef ^ TwrPropsParms ReKi T_Shad_Refpt - - - "Tower-shadow reference point" m +typedef ^ TwrPropsParms LOGICAL CalcTwrAero - - - "Flag to tell AeroDyn to calculate drag on the tower" m +typedef ^ TwrPropsParms INTEGER NumTwrNodes - - - "Number of ElastoDyn tower nodes. Tower drag will be computed at those points." +typedef ^ TwrPropsParms ReKi TwrNodeWidth {:} - - "The width (diameter) of the tower at the ElastoDyn node locations." - + +#Wind +typedef ^ Wind ReKi ANGFLW - - - +typedef ^ Wind ReKi CDEL - - - +typedef ^ Wind ReKi VROTORX - - - +typedef ^ Wind ReKi VROTORY - - - +typedef ^ Wind ReKi VROTORZ - - - +typedef ^ Wind ReKi SDEL - - - +typedef ^ WindParms ReKi Rho - - - "Air density" kg/m^3 +typedef ^ WindParms ReKi KinVisc - - - "Kinematic air viscosity" (m^2/sec) + +################## Registry for AeroDyn ############### + +typedef AeroDyn14/AD14 PositionType ReKi Pos 3 - - "X,Y,Z coordinate of a point" +typedef AeroDyn14/AD14 OrientationType ReKi Orient {3}{3} - - "Direction Cosine Matrix" + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +#typedef AeroDyn14/AD14 InitInputType ADOptions ADOptions - - - +typedef AeroDyn14/AD14 InitInputType CHARACTER(1024) Title - - - "Title" +typedef ^ InitInputType CHARACTER(1024) OutRootName - - - +typedef ^ InitInputType CHARACTER(1024) ADFileName - - - "AeroDyn file name" +typedef ^ InitInputType LOGICAL WrSumFile - - - "T/F: Write an AeroDyn summary" +typedef ^ InitInputType INTEGER NumBl - - - "Number of Blades" +#typedef ^ InitInputType INTEGER NBlInpSt - - - "Number of Blade Input Stations" +typedef ^ InitInputType ReKi BladeLength - - - "Blade Length" +#typedef ^ InitInputType PositionType InitBladePos {:}{:} - - "Positions of the blades elements, initially, from FAST" +#typedef ^ InitInputType PositionType HubPos - - - "Positions of the blades, initially, from FAST" +#typedef ^ InitInputType OrientationType InitBladeOrient {:}{:} - - "Positions of the blades, initially, from FAST" +typedef ^ InitInputType LOGICAL LinearizeFlag +typedef ^ InitInputType LOGICAL UseDWM - .FALSE. - "flag to determine if DWM module should be used" - +typedef ^ InitInputType AeroConfig TurbineComponents - - - - +typedef ^ InitInputType INTEGER NumTwrNodes - - - "Number of ElastoDyn tower nodes. Tower drag will be computed at those points." +typedef ^ InitInputType ReKi TwrNodeLocs {:}{:} - - "Location of ElastoDyn tower nodes with respect to the inertial origin." - +typedef ^ InitInputType ReKi HubHt - - - "hub height wrt inertial origin" m +typedef ^ InitInputType DWM_InitInputType DWM - - - - + +# Define outputs from the initialization routine here: +typedef AeroDyn14/AD14 InitOutputType ProgDesc Ver - - - "version information" +typedef ^ InitOutputType DWM_InitOutputType DWM - - - - +typedef ^ InitOutputType ReKi AirDens - - - "Air density" kg/m^3 + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType DWM_ContinuousStateType DWM - - - - + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType DWM_DiscreteStateType DWM - - - - + +# Define constraint states here: +typedef ^ ConstraintStateType DWM_ConstraintStateType DWM - - - - + + +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType DWM_OtherStateType DWM - - - "variables for DWM module" + + +# ..... 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 DWM_MiscVarType DWM - - - "variables for DWM module" +typedef ^ MiscVarType DWM_InputType DWM_Inputs - - - - +typedef ^ MiscVarType DWM_OutputType DWM_Outputs - - - - + +# +# JM: At this point, I don't know which of these are actually discrete, continuous, or constraint, so they're all misc variables for now +# +typedef ^ MiscVarType DbKi DT - - - "actual Time step" seconds +typedef ^ MiscVarType IntKi ElPrNum {:} - - - +typedef ^ MiscVarType DbKi OldTime - - - +typedef ^ MiscVarType ReKi HubLoss - 1 - # was saved in AXIND +typedef ^ MiscVarType ReKi Loss - 1 - # was saved in AXIND +typedef ^ MiscVarType ReKi TipLoss - 1 - # was saved in AXIND +typedef ^ MiscVarType ReKi TLpt7 - - - # was saved in GetTipLoss +typedef ^ MiscVarType LOGICAL FirstPassGTL - .TRUE. - # was saved latch in GetTipLoss +typedef ^ MiscVarType LOGICAL SuperSonic - .FALSE. - # was saved latch in Attach() +typedef ^ MiscVarType LOGICAL AFLAGVinderr - .FALSE. - # was saved latch in GetTwrInfluence +typedef ^ MiscVarType LOGICAL AFLAGTwrInflu - .FALSE. - # was saved latch in GetTwrInfluence +typedef ^ MiscVarType LOGICAL OnePassDynDbg - .TRUE. - # +typedef ^ MiscVarType LOGICAL NoLoadsCalculated - .TRUE. - - +typedef ^ MiscVarType IntKi NERRORS - 0 - # was saved variable in vinderr +typedef ^ MiscVarType AirFoil AirFoil +typedef ^ MiscVarType Beddoes Beddoes +typedef ^ MiscVarType DynInflow DynInflow +typedef ^ MiscVarType Element Element +typedef ^ MiscVarType Rotor Rotor +typedef ^ MiscVarType Wind Wind +typedef ^ MiscVarType InducedVel InducedVel +typedef ^ MiscVarType ElOutParms ElOut +typedef ^ MiscVarType LOGICAL Skew - - - +typedef ^ MiscVarType LOGICAL DynInit - - - "FALSE=EQUIL, TRUE=DYNIN" +typedef ^ MiscVarType LOGICAL FirstWarn - - - "If it's the first warning about AeroDyn not recalculating loads" +#### Stores previously calculated loads: +typedef ^ MiscVarType Reki StoredForces {:}{:}{:} #indices: force, ielm, iblade +typedef ^ MiscVarType Reki StoredMoments {:}{:}{:} #indices: force, ielm, iblade + +# ..... 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 ADOptions ADOptions +typedef ^ ParameterType CHARACTER(1024) Title - - - "Title" +typedef ^ ParameterType LOGICAL SIUnit - +typedef ^ ParameterType LOGICAL Echo - .FALSE. - +typedef ^ ParameterType LOGICAL MultiTab - +typedef ^ ParameterType LOGICAL LinearizeFlag +typedef ^ ParameterType LOGICAL OutputPlottingInfo - .FALSE. +typedef ^ ParameterType LOGICAL UseDWM - .FALSE. - "flag to determine if DWM module should be used" - +typedef ^ ParameterType ReKi TwoPiNB - - - "2*pi/num of blades" - +typedef ^ ParameterType INTEGER NumBl - - - "Number of Blades" +typedef ^ ParameterType INTEGER NBlInpSt - - - "Number of Blade Input Stations" +typedef ^ ParameterType LOGICAL ElemPrn - - - +typedef ^ ParameterType LOGICAL DStall - - - "FALSE=Steady, TRUE=BEDDOES" +typedef ^ ParameterType LOGICAL PMoment - - - "FALSE=NO_CM, TRUE=USE_CM" +typedef ^ ParameterType LOGICAL Reynolds - +typedef ^ ParameterType LOGICAL DynInfl - - - "FALSE=EQUIL, TRUE=DYNIN" +typedef ^ ParameterType LOGICAL Wake - - - "False unless WAKE or SWIRL" +typedef ^ ParameterType LOGICAL Swirl - - - "False unless WAKE or SWIRL" +typedef ^ ParameterType DbKi DtAero - - - "Time interval for aerodynamic calculations" +typedef ^ ParameterType ReKi HubRad - - - "Hub radius" m +#typedef ^ ParameterType ReKi RotorRad - - - "Rotor radius" m +typedef ^ ParameterType INTEGER UnEc - -1 #patch this in for now; lost in NWTC_Library +typedef ^ ParameterType INTEGER UnElem - -1 +typedef ^ ParameterType INTEGER UnWndOut - -1 # note, these are not minus signs +typedef ^ ParameterType INTEGER MAXICOUNT - 1000 - # used in VIND +typedef ^ ParameterType LOGICAL WrOptFile - .TRUE. - "T/F: Write an AeroDyn summary" +typedef ^ ParameterType IntKi DEFAULT_Wind - -1 - +typedef ^ ParameterType AirFoilParms AirFoil +typedef ^ ParameterType BladeParms Blade +typedef ^ ParameterType BeddoesParms Beddoes +typedef ^ ParameterType DynInflowParms DynInflow +typedef ^ ParameterType ElementParms Element +typedef ^ ParameterType TwrPropsParms TwrProps +typedef ^ ParameterType InducedVelParms InducedVel +typedef ^ ParameterType WindParms Wind +typedef ^ ParameterType RotorParms Rotor +typedef ^ ParameterType DWM_ParameterType DWM - - - - + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +#typedef ^ InputType MeshType MeshedInput - - - "Meshed input data" - +# Define inputs that are not on this mesh here: +typedef ^ InputType MeshType InputMarkers {:} - - "Input Forces and positions for the blades (mesh) for each blade" - +typedef ^ InputType MeshType Twr_InputMarkers - - - "Input Forces and positions for the tower (mesh)" - +typedef ^ InputType AeroConfig TurbineComponents - - - "Current locations of components" +typedef ^ InputType ReKi MulTabLoc {:}{:} +typedef ^ InputType ReKi InflowVelocity {:}{:} - - "U,V,W wind inflow speeds at all locations on the Inputmarker and Twr_InputMarker meshes" "m/s" +typedef ^ InputType ReKi AvgInfVel {3} - - "an average disk velocity (depends on wind type and should be removed)" "m/s" + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +#typedef ^ OutputType MeshType MeshedOutput - - - "Meshed output data" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType MeshType OutputLoads {:} - - "Output Loads (mesh) for each blade" - +typedef ^ OutputType MeshType Twr_OutputLoads - - - "Tower Output Loads (mesh)" - diff --git a/OpenFAST/modules/aerodyn14/src/Registry-AD14AeroConf.txt b/OpenFAST/modules/aerodyn14/src/Registry-AD14AeroConf.txt new file mode 100644 index 000000000..920e646bc --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/Registry-AD14AeroConf.txt @@ -0,0 +1,56 @@ +################################################################################################################################### +# Registry for AD14AeroConf in the FAST Modularization Framework +# This Registry file is used to create MODULE AD14AeroConf_Types which contains all of the user-defined types needed in AD14AeroConf. +# This module is used within the FVW_Types and AeroDyn_Types modules. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +################################################################################################################################### +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +include Registry_NWTC_Library.txt + + +## This bit is redundant with AD14 registry. Could not figure out how to have both this and the AD14 registry use a third common chunk +# AeroDyn Subtypes +typedef AD14AeroConf/AD14AeroConf Marker Reki Position 3 0.0 - - +typedef ^ Marker ^ Orientation {3}{3} 0.0 - - +typedef ^ Marker ^ TranslationVel 3 0.0 - - +typedef ^ Marker ^ RotationVel 3 0.0 - - + + +# Airfoil +typedef AD14AeroConf/AD14AeroConf MiscVarType ReKi AL :: - - - +typedef ^ MiscVarType ReKi CD ::: - - - +typedef ^ MiscVarType ReKi CL ::: - - - +typedef ^ MiscVarType ReKi CM ::: - - - +typedef ^ MiscVarType ReKi PMC - - - - +typedef ^ MiscVarType ReKi MulTabLoc - - - - + +# Parameters: this used to be called AirFoilParms +typedef ^ ParameterType IntKi MaxTable - 20 - - +typedef ^ ParameterType IntKi NTables : - - - +typedef ^ ParameterType IntKi NLift : - - - +typedef ^ ParameterType IntKi NumCL - - - - +typedef ^ ParameterType IntKi NumFoil - - - - +typedef ^ ParameterType IntKi NFoil : - - - +typedef ^ ParameterType ReKi MulTabMet :: - - - +typedef ^ ParameterType CHARACTER(1024) FoilNm : "Number of airfoil data sets" - - + + +# Aero input-type --> this used to be called AeroConfig +typedef AD14AeroConf/AD14AeroConf InputType Marker Blade : - - - +typedef ^ InputType ^ Hub - - - - +typedef ^ InputType ^ RotorFurl - - - - +typedef ^ InputType ^ Nacelle - - - - +typedef ^ InputType ^ TailFin - - - - +typedef ^ InputType ^ Tower - - - - +typedef ^ InputType ^ SubStructure - - - - +typedef ^ InputType ^ Foundation - - - - +typedef ^ InputType ReKi BladeLength - - - - + +# Dummy outputtype so that the registry is happy +typedef AD14AeroConf/AD14AeroConf OutputType ReKi Dummy - - - - + diff --git a/OpenFAST/modules/aerodyn14/src/Registry-DWM.txt b/OpenFAST/modules/aerodyn14/src/Registry-DWM.txt new file mode 100644 index 000000000..9b4221129 --- /dev/null +++ b/OpenFAST/modules/aerodyn14/src/Registry-DWM.txt @@ -0,0 +1,274 @@ +################################################################################################################################## +# Registry for DWM +# Entries are of the form +# keyword <modulename/modname> <TypeBeingDefined> <FieldType> <FieldName> <Dims> <InitialValue> <Ctrl> "<DESCRIP>" "<UNITS>" +################################################################################################################################## +include Registry_NWTC_Library.txt +usefrom InflowWind.txt + +# CalVelScale_data +typedef DWM/DWM CVSD IntKi counter - 0 - "" - +typedef ^ ^ Reki Denominator - 0.0 - "" - +typedef ^ ^ ^ Numerator - 0.0 - "" - + +# turbine_average_velocity_data +typedef DWM/DWM turbine_average_velocity_data Reki average_velocity_array_temp : - - "the average velocity of the whole blade sections in a specific time step" - +typedef ^ ^ ^ average_velocity_array : - - "" - +typedef ^ ^ ^ swept_area : - - "" m2 +typedef ^ ^ IntKi time_step_velocity - -1 - "" - +typedef ^ ^ ^ time_step_velocity_array : - - "" - +typedef ^ ^ ^ time_step_pass_velocity - -1 - "" - +typedef ^ ^ ^ time_step_force - -1 - "" - + +# DWM_Wake_Deficit_Data +typedef ^ DWM_Wake_Deficit_Data IntKi np_x - - - "point per axial distance" - +typedef ^ ^ Reki X_length - - - "normalized length in axial direction" - +typedef ^ ^ Reki Turb_Stress_DWM :: - - "" - +typedef ^ ^ IntKi n_x_vector - - - "" - +typedef ^ ^ IntKi n_r_vector - - - "" - +typedef ^ ^ Reki ppR - - - "Point_per_R_resoulution" - + +# meandering_data +typedef DWM/DWM MeanderData IntKi scale_factor - - - "" - +#typedef ^ ^ ^ release_time - - - "" - +#typedef ^ ^ ^ flying_time - - - "" - +#typedef ^ ^ ^ simulation_time_length - - - "" - +typedef ^ ^ ^ moving_time - - - "" - +#typedef ^ ^ Reki DWM_time_step - - - "" - +#typedef ^ ^ ^ temp_center_wake 3 - - "" - +#typedef ^ ^ ^ temp_velocity 3 - - "" - +#typedef ^ ^ ^ U_Scale_Factor - - - "" - +#typedef ^ ^ ^ U_factor - - - "" - + + +# RTPD +typedef DWM/DWM read_turbine_position_data IntKi SimulationOrder_index - - - "" - +typedef ^ ^ ^ Turbine_sort_order : - - "" - +typedef ^ ^ ^ WT_index - - - "wind turbine index in the wind farm" - +typedef ^ ^ ^ TurbineInfluenceData :: - - "" - +typedef ^ ^ ^ upwind_turbine_index : - - "the upwind turbines that affecting this turbine" - +typedef ^ ^ ^ downwind_turbine_index : - - "" - +typedef ^ ^ ^ upwindturbine_number - - - "the number of upwind turbines affecting the downwind turbine" - +typedef ^ ^ ^ downwindturbine_number - - - "" - +typedef ^ ^ Reki turbine_windorigin_length : - - "" - +typedef ^ ^ ^ upwind_turbine_projected_distance : - - "the projected distance between two turbines" - +typedef ^ ^ ^ downwind_turbine_projected_distance : - - "" - +typedef ^ ^ ^ turbine_angle :: - - "" - +typedef ^ ^ ^ upwind_align_angle : - - "the angle beween the line connecting the upwind turbine and this turbine and the wind direction vector" - +typedef ^ ^ ^ downwind_align_angle : - - "" - +typedef ^ ^ ^ upwind_turbine_Xcoor : - - "the coordinate of the upwind turbine which affects this investigated turbine" - +typedef ^ ^ ^ upwind_turbine_Ycoor : - - "" - +typedef ^ ^ ^ wind_farm_Xcoor : - - "the coordinates of all the turbines in the wind farm" - +typedef ^ ^ ^ wind_farm_Ycoor : - - "" - +typedef ^ ^ ^ downwind_turbine_Xcoor : - - "the coordinate of the downwind turbine which is affected by this investigated turbine" - +typedef ^ ^ ^ downwind_turbine_Ycoor : - - "" - + + +# weighting_method +typedef DWM/DWM WeiMethod Reki sweptarea : - - "" - +typedef ^ ^ ^ weighting_denominator - - - "" - + +# TI_downstream_data +typedef DWM/DWM TIDownstream Reki TI_downstream_matrix :: - - "" - +typedef ^ ^ IntKi i - - - "" - +typedef ^ ^ ^ j - - - "" - +typedef ^ ^ ^ k - - - "" - +typedef ^ ^ ^ cross_plane_position_ds - - - "the cross plane position which to be investigated in term of the flying time" - +typedef ^ ^ ^ cross_plane_position_TI - - - "the cross plane position which to be investigated in term of the n_x_vector" - +typedef ^ ^ ^ distance_index - - - "the index of the distance in the TI axisymmetric array" - +typedef ^ ^ ^ counter1 - - - "" - +typedef ^ ^ ^ counter2 - - - "" - +typedef ^ ^ ^ initial_timestep - - - "" - +typedef ^ ^ Reki y_axis_turbine - - - "" - +typedef ^ ^ ^ z_axis_turbine - - - "" - +typedef ^ ^ ^ distance - - - "the distance between one point to the meandered wake center" - +typedef ^ ^ ^ TI_downstream_node - - - "the TI at a specfic point in the inbestigated cross plane" - +typedef ^ ^ ^ TI_node_temp - - - "" - +typedef ^ ^ ^ TI_node - - - "" - +typedef ^ ^ ^ TI_accumulation - - - "" - +typedef ^ ^ ^ TI_apprant_accumulation - - - "" - +typedef ^ ^ ^ TI_average - - - "THE AVERAGE TI OF THE CROSS PLANE" - +typedef ^ ^ ^ TI_apprant - - - "The TI due to the meadering" - +typedef ^ ^ ^ HubHt - - - "" - +typedef ^ ^ ^ wake_center_y - - - "" - +typedef ^ ^ ^ wake_center_z - - - "" - +typedef ^ ^ ^ Rscale - - - "" - +typedef ^ ^ ^ y - - - "" - +typedef ^ ^ ^ z - - - "" - +typedef ^ ^ ^ zero_spacing - - - "" - +typedef ^ ^ ^ temp1 - - - "" - +typedef ^ ^ ^ temp2 - - - "" - +typedef ^ ^ ^ temp3 - - - "" - + +# Turbulence_KS +typedef DWM/DWM TurbKaimal IntKi fs - - - "sample frequency" - +typedef ^ ^ ^ temp_n - - - "" - +typedef ^ ^ ^ i - - - "" - +typedef ^ ^ Reki low_f - - - "lower bound of frequency range" - +typedef ^ ^ ^ high_f - - - "upper bound of frequency range" - +typedef ^ ^ ^ lk_facor - - - "turbulence length-scale" - +typedef ^ ^ ^ STD - - - "standard deviation of the turbulence" - + +# shinozuka_data +typedef DWM/DWM Shinozuka Reki f_syn : - - "frequency series" - +typedef ^ ^ ^ t_syn : - - "time series" - +typedef ^ ^ ^ phi : - - "random phase angle" - +typedef ^ ^ ^ p_k : - - "" - +typedef ^ ^ ^ a_k : - - "" - +typedef ^ ^ IntKi num_points - - - "total number of points" - +typedef ^ ^ ^ ILo - - - "" - +typedef ^ ^ ^ i - - - "" - +typedef ^ ^ ^ j - - - "" - +typedef ^ ^ Reki dt - - - "time step" - +typedef ^ ^ ^ t_min - - - "" - +typedef ^ ^ ^ t_max - - - "" - +typedef ^ ^ ^ df - - - "frequency step" - + +# smooth_out_wake_data +typedef ^ smooth_out_wake_data IntKi length_velocity_array - - - "the length of velocity_array" - + +# smooth_wake_shifted_velocity_data +typedef DWM/DWM SWSV IntKi p1 - - - "" - +typedef ^ ^ ^ p2 - - - "" - +typedef ^ ^ Reki distance - - - "the distance from the point to the meandered wake center" - +typedef ^ ^ ^ y0 - - - "wake center position on y axis" - +typedef ^ ^ ^ z0 - - - "wake center position on z axis" - +typedef ^ ^ ^ unit - - - "single unit length R/ppR" - + +# Upwind_result +typedef DWM/DWM read_upwind_result Reki upwind_U :: - - "" - +typedef ^ ^ ^ upwind_wakecenter :::: - - "" - +typedef ^ ^ ^ upwind_meanU : - - "" - +typedef ^ ^ ^ upwind_TI : - - "" - +typedef ^ ^ ^ upwind_small_TI : - - "" - +typedef ^ ^ ^ upwind_smoothWake :: - - "" - +typedef ^ ^ ^ velocity_aerodyn : - - "" - +typedef ^ ^ ^ TI_downstream : - - "" - +typedef ^ ^ ^ small_scale_TI_downstream : - - "" - +typedef ^ ^ ^ smoothed_velocity_array :: - - "" - +typedef ^ ^ ^ vel_matrix ::: - - "The smoothed out wake velocity matrix for n downwind turbine" - + +# wake_meandered_center +typedef DWM/DWM wake_meandered_center IntKi wake_width : - - "wake width" - + +# DWM_turbine_blade +typedef DWM/DWM DWM_turbine_blade IntKi Aerodyn_turbine_num - - - "" - +typedef ^ ^ ^ Blade_index - - - " the index of Aerodyn Blade" - +typedef ^ ^ ^ Element_index - - - " the index of Aerodyn Element" - + + +################## Registry for DWM ############### +# ..... PARAMETERS ......................... +# DWM_Parameters +typedef DWM/DWM ParameterType Reki velocityU : - - "the wake velocity profile @ the downstream turbine plane" - +typedef ^ ^ ^ smoothed_wake : - - "" - +typedef ^ ^ ^ WakePosition ::: - - "meandered wake center" - +typedef ^ ^ IntKi WakePosition_1 - - - "size of the WakePosition" - +typedef ^ ^ ^ WakePosition_2 - - - "size of the WakePosition" - +typedef ^ ^ ^ smooth_flag - - - "Whether or not use the smoothed out upstream wake profile (1-yes, 0-no)" - +typedef ^ ^ ^ p_p_r - - - "" - +typedef ^ ^ ^ NumWT - - - "Number of wind turbines" - +typedef ^ ^ ^ Tinfluencer - - - "" - +typedef ^ ^ Reki RotorR - - - "Rotor radius" - +typedef ^ ^ ^ r_domain - - - "" - +typedef ^ ^ ^ x_domain - - - "" - +typedef ^ ^ ^ Uambient - - - "The ambient wind velocity" - +typedef ^ ^ ^ TI_amb - - - "Ambient turbulence intensity" % +typedef ^ ^ ^ TI_wake - - - "" - +typedef ^ ^ ^ hub_height - - - "" - +typedef ^ ^ ^ length_velocityU - - - "" - +typedef ^ ^ ^ WFLowerBd - - - "The lower bound height of the wind file" - +typedef ^ ^ ^ Wind_file_Mean_u - - - "The mean velocity of the first turbine" - +typedef ^ ^ ^ Winddir - - - "" - +typedef ^ ^ ^ air_density - - - "air density" - +typedef ^ ^ ^ RR - - - "" - +typedef ^ ^ ^ ElementRad : - - " the element node radius" - +typedef ^ ^ IntKi Bnum - - - " the number of blade" - +typedef ^ ^ ^ ElementNum - - - " the number of element" - +typedef ^ ^ read_turbine_position_data RTPD +typedef ^ ParameterType InflowWind_ParameterType IfW - - - - + +# ....... OtherStateType ............ +# DWM_OtherStateType +typedef ^ OtherStateType InflowWind_OtherStateType IfW - - - - + +# ....... OtherStateType ............ +# DWM_MiscVarType +typedef ^ MiscVarType InflowWind_MiscVarType IfW - - - - +typedef DWM/DWM ^ Reki position_y - - - "the y position of the blade node" - +typedef ^ ^ ^ position_z - - - "the z position of the blade node" - +typedef ^ ^ ^ velocity_wake_mean - - - "" - +typedef ^ ^ ^ shifted_velocity_Aerodyn - - - "" - +typedef ^ ^ ^ U_velocity - - - " the u component velocity of blade" - +typedef ^ ^ ^ V_velocity - - - " the v component velocity of blade" - +typedef ^ ^ ^ Nforce :: - - " the normal force" - +typedef ^ ^ ^ blade_dr : - - " blade dr" - +typedef ^ ^ ^ NacYaw - - - "" - +typedef ^ ^ ^ TI_original - - - "" - +typedef ^ ^ turbine_average_velocity_data TAVD +typedef ^ ^ CVSD CalVelScale_data +typedef ^ ^ MeanderData meandering_data +typedef ^ ^ WeiMethod weighting_method +typedef ^ ^ TIDownstream TI_downstream_data +typedef ^ ^ TurbKaimal Turbulence_KS +typedef ^ ^ Shinozuka shinozuka_data +typedef ^ ^ smooth_out_wake_data SmoothOut +typedef ^ ^ SWSV smooth_wake_shifted_velocity_data +typedef ^ ^ DWM_Wake_Deficit_Data DWDD +typedef ^ ^ Reki ct_tilde - - - "the tilde Ct" - +typedef ^ ^ ^ FAST_Time - - - "FAST simulation time" - +typedef ^ ^ IntKi SDtimestep - 0 - "" - +typedef ^ ^ DWM_turbine_blade DWM_tb +typedef ^ ^ wake_meandered_center WMC + +# ........ Input ............ +# DWM_InputType +typedef DWM/DWM InputType read_upwind_result Upwind_result +typedef ^ InputType InflowWind_InputType IfW - - - - + +# ........ Output ............ +# DWM_OutputType + +typedef DWM/DWM OutputType Reki turbine_thrust_force : - - "" N +typedef ^ ^ ^ induction_factor : - - "" - +typedef ^ ^ ^ r_initial : - - "scaled rotor radius" - +typedef ^ ^ ^ U_initial : - - "scaled velocity at the rotor" - +typedef ^ ^ ^ Mean_FFWS_array : - - "Mean velocity of each section on the blade" - +typedef ^ ^ ^ Mean_FFWS - - - "Mean (total) wind speed at the hub height" m/s +typedef ^ ^ ^ TI - - - "the turbulence intensity of the turbine" - +typedef ^ ^ ^ TI_downstream - - - "the TI of a downstream turbine before normalization" - +typedef ^ ^ ^ wake_u :: - - "wake velocity" - +typedef ^ ^ ^ wake_position ::: - - "wake center position" m +typedef ^ ^ ^ smoothed_velocity_array :: - - "smoothed out upstream axisymetric wake profile" - +typedef ^ ^ ^ AtmUscale - - - "atmospheric velocity scale before introducing TI" - +typedef ^ ^ ^ du_dz_ABL - - - "atmosperic shear gradient" - +typedef ^ ^ ^ total_SDgenpwr - 0.0 - "" - +typedef ^ ^ ^ mean_SDgenpwr - - - "" - +typedef ^ ^ ^ avg_ct - - - "average Ct over the rotor" - +typedef ^ OutputType InflowWind_OutputType IfW - - - - + +#.......... ContinuousStateType ...... +# DWM_ContinuousStateType +typedef DWM/DWM ContinuousStateType Reki dummy - - - "" - +typedef ^ ContinuousStateType InflowWind_ContinuousStateType IfW - - - - + +#.......... DiscreteStateType ...... +# DWM_DiscreteStateType +typedef DWM/DWM DiscreteStateType Reki dummy - - - "" - +typedef ^ DiscreteStateType InflowWind_DiscreteStateType IfW - - - - + +#.......... ConstraintStateType ...... +# DWM_ConstraintStateType +typedef DWM/DWM ConstraintStateType Reki dummy - - - "" - +typedef ^ ConstraintStateType InflowWind_ConstraintStateType IfW - - - - + + +#.......... InitInputType ...... +# DWM_InitInputType +typedef DWM/DWM InitInputType Reki dummy - - - "" - +typedef ^ InitInputType InflowWind_InitInputType IfW - - - - + +#.......... InitOutputType ...... +# DWM_InitOutputType +typedef DWM/DWM InitOutputType Reki dummy - - - "" - +typedef ^ InitOutputType InflowWind_InitOutputType IfW - - - - \ No newline at end of file diff --git a/OpenFAST/modules/beamdyn/CMakeLists.txt b/OpenFAST/modules/beamdyn/CMakeLists.txt new file mode 100644 index 000000000..dae656b08 --- /dev/null +++ b/OpenFAST/modules/beamdyn/CMakeLists.txt @@ -0,0 +1,48 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/Registry_BeamDyn.txt ${CMAKE_CURRENT_LIST_DIR}/src/BeamDyn_Types.f90) +endif() + +set(BD_SOURCES + src/BeamDyn.f90 + src/BeamDyn_IO.f90 + src/BeamDyn_BldNdOuts_IO.f90 + src/BeamDyn_Subs.f90 + src/BeamDyn_Types.f90 + ) + +add_library(beamdynlib ${BD_SOURCES}) +target_link_libraries(beamdynlib nwtclibs) + +install(TARGETS beamdynlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + +set(BD_DRIVER_SOURCES + src/Driver_Beam.f90 + src/Driver_Beam_Subs.f90) + +add_executable(beamdyn_driver ${BD_DRIVER_SOURCES}) +target_link_libraries(beamdyn_driver beamdynlib nwtclibs versioninfolib ${CMAKE_DL_LIBS}) + +install(TARGETS beamdyn_driver + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/beamdyn/README.md b/OpenFAST/modules/beamdyn/README.md new file mode 100644 index 000000000..9e1675f38 --- /dev/null +++ b/OpenFAST/modules/beamdyn/README.md @@ -0,0 +1,56 @@ +# BeamDyn Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/BeamDyn/). + +## Overview +BeamDyn is a time-domain structural-dynamics module for slender structures. +The module has been coupled into the FAST aero-hydro-servo-elastic wind turbine +multi-physics engineering tool where it used to model blade structural +dynamics. BeamDyn is designed to analyze beams that are made of composite +materials, initially curved and twisted, and subject to large displacement and +rotation deformations. BeamDyn can also be used for static analysis of beams. + +BeamDyn is based on the geometrically exact beam theory (GEBT) and is +implemented using Legendre spectral finite elements (LSFEs). GEBT supports full +geometric nonlinearity and large deflection, with bending, torsion, shear, and +extensional degree-of-freedom (DOFs); anisotropic composite material couplings +(using full 6x6 mass and stiffness matrices, including bend-twist coupling); +and a reference axis that permits blades that are not straight (supporting +built-in curve, sweep, and sectional offsets). + +BeamDyn was originally developed by Qi Wang, Mike Sprague, and Jason Jonkman +under an NREL Laboratory Directed Research and Development (LDRD) +Project: High-fidelity computational modeling of wind-turbine structural +dynamics (2011-2013; PI: M.A. Sprague). +Further development was funded by the DOE Wind Energy Technology Office. NREL +gratefully acknowledges the development contributions from the following organizations: +* [Envision Energy USA, Ltd](http://www.envision-energy.com) + +## Manual +BeamDyn documentation is available on the OpenFAST +[ReadTheDocs](https://openfast.readthedocs.io/en/master/source/user/beamdyn/index.html) site. + +## Relevant Publications + +* Wang, Q., M.A. Sprague, J. Jonkman, N. Johnson, and B. Jonkman, 2017, BeamDyn: An efficient high-fidelity wind turbine blade solver in the FAST modular framework. +*Wind Energy*, [DOI:10.1002/we.2101](http://onlinelibrary.wiley.com/doi/10.1002/we.2101/full). + +* Wang, Q., M. Sprague, J. Jonkman, and B. Jonkman, Partitioned nonlinear structural analysis of wind turbines using BeamDyn. +Proceedings of *34th Wind Energy Symposium, AIAA Science and Technology Forum and Exposition 2016*, San Diego, California, 4--8 January 2016. + +* Guntur, S., J. Jonkman, S. Schreck, B. Jonkman, Q. Wang, M. Sprague, M. Hind, and R. Sievers, +FAST v8 Verification and Validation Using Experiments from Aeroelastically Tailored Megawatt-Scale Wind Turbine Blades. +Proceedings of *34th Wind Energy Symposium, AIAA Science and Technology Forum and Exposition 2016*, San Diego, California, 4--8 January 2016. Also published as [NREL/CP-5000-65389](http://www.nrel.gov/docs/fy16osti/65389.pdf). + +* C. Pavese, T. Kim, Q. Wang, J. Jonkman, M.A. Sprague, +HAWC2 and BeamDyn: Comparison Between Beam Structural Models for Aero-Servo-Elastic Frameworks, Proceedings of the *European Wind Energy Association Annual Conference and Exhibition 2015* (EWEA 2015), 17-20 November 2015, Paris, France pp. 1193-1201. Also published as [NREL/CP-5000-65115](http://www.nrel.gov/docs/fy16osti/65115.pdf). + +* Wang, Q., N. Johnson, M.A. Sprague, J. Jonkman, BeamDyn: +A high-fidelity wind turbine blade solver in the FAST modular framework. +Proceedings of the *AIAA Science and Technology Forum and Exposition, +33rd ASME Wind Energy Symposium*, Kissimmee, FL, 5--9 January 2015. Also published as [NREL/CP-5000-63165](http://www.nrel.gov/docs/fy15osti/63165.pdf). + +* Wang, Q., M.A. Sprague, and J.M. Jonkman, Nonlinear +Legendre spectral finite elements for wind turbine blade dynamics. +Proceedings of the *AIAA Science and Technology Forum and +Exposition, 32nd ASME Wind Energy Symposium*, National Harbor, MD, January 13--17, 2014. Also published as [NREL/CP-2C00-60759](http://www.nrel.gov/docs/fy14osti/60759.pdf). diff --git a/OpenFAST/modules/beamdyn/src/BeamDyn.f90 b/OpenFAST/modules/beamdyn/src/BeamDyn.f90 new file mode 100644 index 000000000..a2ccb45f1 --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/BeamDyn.f90 @@ -0,0 +1,6807 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2018 Envision Energy USA, LTD +! +! 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 BeamDyn + + USE BeamDyn_BldNdOuts_IO + USE BeamDyn_IO + USE BeamDyn_Subs + !USE NWTC_LAPACK inherited from BeamDyn_Subs and BeamDyn_IO + + IMPLICIT NONE + +#ifndef UNIT_TEST + PRIVATE + + ! ..... Public Subroutines.................................................................... + + PUBLIC :: BD_Init ! Initialization routine + PUBLIC :: BD_End ! Ending routine (includes clean up) + PUBLIC :: BD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + PUBLIC :: BD_CalcOutput ! Routine for computing outputs + PUBLIC :: BD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: BD_UpdateDiscState ! Tight coupling routine for updating discrete states +#endif + + PUBLIC :: BD_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 :: BD_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 :: BD_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 :: BD_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 :: BD_GetOP !< Routine to pack the operating point values (for linearization) into arrays + + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE BD_Init( InitInp, u, p, x, xd, z, OtherState, y, MiscVar, Interval, InitOut, ErrStat, ErrMsg ) + + TYPE(BD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(BD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(BD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(BD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(BD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(BD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(BD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(BD_MiscVarType), INTENT( OUT) :: MiscVar !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Mod1_UpdateStates() is called in loose coupling & + !! (2) Mod1_UpdateDiscState() is called in tight coupling. ! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(BD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + TYPE(BD_InputFile) :: InputFileData ! Data stored in the module's input file + REAL(BDKi) :: temp_CRV(3) + REAL(BDKi),ALLOCATABLE :: GLL_nodes(:) + REAL(BDKi) :: TmpDCM(3,3) + REAL(BDKi) :: denom + LOGICAL :: QuasiStaticInitialized !< True if quasi-static solution was found + + + INTEGER(IntKi) :: nelem + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(*), parameter :: RoutineName = 'BD_Init' + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + ! Display the module information + + CALL DispNVD( BeamDyn_Ver ) + + CALL BD_ReadInput(InitInp%InputFile,InputFileData,InitInp%RootName,Interval,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + CALL BD_ValidateInputData( InitInp, InputFileData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! this routine sets *some* of the parameters (basically the "easy" ones) + call SetParameters(InitInp, InputFileData, p, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! Temporary GLL point intrinsic coordinates array + CALL BD_GenerateGLL(p%nodes_per_elem,GLL_nodes,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! In the following, trapezoidalpointweight should be generalized to multi-element; likewise for gausspointweight + + IF(p%quadrature .EQ. GAUSS_QUADRATURE) THEN + + CALL BD_GaussPointWeight(p%nqp,p%QPtN,p%QPtWeight,ErrStat2,ErrMsg2) !calculates p%QPtN and p%QPtWeight + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ELSEIF(p%quadrature .EQ. TRAP_QUADRATURE) THEN + + CALL BD_TrapezoidalPointWeight(p, InputFileData%InpBl%station_eta, InputFileData%InpBl%station_total) ! computes p%QPtN and p%QPtWeight + + ENDIF + + ! compute physical distances to set positions of p%uuN0 (FE GLL_Nodes) (depends on p%SP_Coef): + call InitializeNodalLocations(InputFileData%member_total,InputFileData%kp_member,InputFileData%kp_coordinate,p,GLL_nodes,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! compute p%Shp, p%ShpDer, and p%Jacobian: + CALL BD_InitShpDerJaco( GLL_Nodes, p ) + + ! set mass and stiffness matrices: p%Stif0_QP and p%Mass0_QP + call InitializeMassStiffnessMatrices(InputFileData, p, ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! Set the initial displacements: p%uu0, p%rrN0, p%E10 + CALL BD_QuadraturePointDataAt0(p) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + +!FIXME: shift mass stiffness matrices here from the keypoint line to the calculated curvature line in p%uu0 +! CALL BD_KMshift2Ref(p) + + + call Initialize_FEweights(p,GLL_nodes,ErrStat2,ErrMsg2) ! set p%FEweight; needs p%uuN0 and p%uu0 + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! compute blade mass, CG, and IN for summary file: + CALL BD_ComputeBladeMassNew( p, ErrStat2, ErrMsg2 ) !computes p%blade_mass,p%blade_CG,p%blade_IN + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Actuator + p%UsePitchAct = InputFileData%UsePitchAct + + if (p%UsePitchAct) then + + p%pitchK = InputFileData%pitchK + p%pitchC = InputFileData%pitchC + p%pitchJ = InputFileData%pitchJ + + ! calculate (I-hA)^-1 + + p%torqM(1,1) = p%pitchJ + p%pitchC*p%dt + p%torqM(2,1) = -p%pitchK * p%dt + p%torqM(1,2) = p%pitchJ * p%dt + p%torqM(2,2) = p%pitchJ + denom = p%pitchJ + p%pitchC*p%dt + p%pitchK*p%dt**2 + if (EqualRealNos(denom,0.0_BDKi)) then + call SetErrStat(ErrID_Fatal,"Cannot invert matrix for pitch actuator: J+c*dt+k*dt^2 is zero.",ErrStat,ErrMsg,RoutineName) + else + p%torqM(:,:) = p%torqM / denom + end if + + ! Calculate the pitch angle + TmpDCM(:,:) = MATMUL(u%RootMotion%Orientation(:,:,1),TRANSPOSE(u%HubMotion%Orientation(:,:,1))) + temp_CRV(:) = EulerExtract(TmpDCM) + xd%thetaP = -temp_CRV(3) + xd%thetaPD = 0.0_BDKi + end if + + + ! Define and initialize system inputs (set up and initialize input meshes) here: + call Init_u(InitInp, p, u, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! allocate and initialize continuous states (need to do this after initializing inputs): + call Init_ContinuousStates(p, u, x, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! allocate and initialize other states: + call Init_OtherStates(p, OtherState, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! initialize outputs (need to do this after initializing inputs and parameters (p%nnu0)) + call Init_y(p, u, y, ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! allocate and initialize misc vars (do this after initializing input and output meshes): + call Init_MiscVars(p, u, y, MiscVar, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + + ! Now that we have the initial conditions, we can run a quasi-steady-state solve + ! We want to do this before calculating the output mesh or setting QP data. + IF(p%analysis_type == BD_DYN_SSS_ANALYSIS) THEN + ! Solve for the displacements with the acceleration and rotational velocity terms included + ! This will set m%qp%aaa, OtherState%Acc, x%q, and x%dqdt + ! (note that we won't ramp loads as there are no loads provided yet.) + ! if this is not successful, it restores the values of x and sets OtherState%Acc=0 + CALL BD_QuasiStatic(u,p,x,OtherState,MiscVar,ErrStat2,ErrMsg2, RampLoad=.false.) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + QuasiStaticInitialized = ErrStat2 == ErrID_None ! We have now run the quasi-static initialization once, so don't run again. + ELSE + QuasiStaticInitialized = .FALSE. + ENDIF + + + + !................................. + ! initialization of output mesh values (used for initial guess to AeroDyn) + if (p%BldMotionNodeLoc==BD_MESH_QP) then + DO nelem=1,p%elem_total + CALL BD_DisplacementQP( nelem, p, x, MiscVar ) + CALL BD_RotationalInterpQP( nelem, p, x, MiscVar ) + end do + + call BD_QPDataVelocity( p, x, MiscVar ) ! set MiscVar%qp%vvv + call BD_QPDataAcceleration( p, OtherState, MiscVar ) ! set MiscVar%qp%aaa + + end if + + CALL Set_BldMotion_NoAcc(p, x, MiscVar, y) + + IF(QuasiStaticInitialized) THEN + ! Set the BldMotion mesh acceleration but only if quasistatic succeeded + call Set_BldMotion_InitAcc(p,u,OtherState,MiscVar,y) + ELSE + y%BldMotion%TranslationAcc = 0.0_BDKi + y%BldMotion%RotationAcc = 0.0_BDKi + ENDIF + + !................................. + + ! set initialization outputs + call SetInitOut(p, InitOut, errStat2, errMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !............................................... + + ! Print the summary file if requested: + if (InputFileData%SumPrint) then + call BD_PrintSum( p, x, MiscVar, InitInp, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + !............................................... + + z%DummyConstrState = 0.0_BDKi + + ! copy data for BeamDyn driver: + call move_alloc ( InputFileData%kp_coordinate, InitOut%kp_coordinate) + InitOut%kp_total = InputFileData%kp_total + + !............................................................................................ + ! Initialize Jacobian: + !............................................................................................ + if (InitInp%Linearize) then + call Init_Jacobian( p, u, y, MiscVar, InitOut, ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + + call Cleanup() + + return +CONTAINS + SUBROUTINE Cleanup() + if (allocated(GLL_nodes )) deallocate(GLL_nodes ) + CALL BD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2) + END SUBROUTINE Cleanup +END SUBROUTINE BD_Init + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the mass (p%Mass0_QP) and stiffness (p%Stif0_QP) matrices at the quadrature nodes. +subroutine InitializeMassStiffnessMatrices(InputFileData,p,ErrStat, ErrMsg) + type(BD_InputFile), intent(in ) :: InputFileData !< data from the input file + type(BD_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 + + INTEGER(IntKi) :: i ! do-loop counter + INTEGER(IntKi) :: j ! do-loop counter + INTEGER(IntKi) :: idx_qp !< index of current quadrature point in loop + INTEGER(IntKi) :: nelem !< index to the element counter + INTEGER(IntKi) :: k ! do-loop counter + INTEGER(IntKi) :: temp_id + REAL(BDKi) :: temp66(6,6) + REAL(BDKi),ALLOCATABLE :: temp_ratio(:,:) ! array that contains the relative location of each quadrature point along the (curve of the) blade, in [0,1] + + REAL(BDKi),PARAMETER :: EPS = 1.0D-10 + + INTEGER(IntKi) :: idx1 + INTEGER(IntKi) :: idx2 + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'InitializeMassStiffnessMatrices' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! compute member length ratio w.r.t blade length + CALL BD_MemberEta( InputFileData%member_total, p%QPtWeight, p%Jacobian, p%member_eta, p%blade_length ) + + CALL AllocAry(p%Stif0_QP,6,6,p%nqp*p%elem_total,'Stif0_QP',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%Mass0_QP,6,6,p%nqp*p%elem_total,'Mass0_QP',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + IF(p%quadrature .EQ. GAUSS_QUADRATURE) THEN + + ! Compute sectional propertities ( 6 by 6 stiffness and mass matrices) + ! at Gauss points + + !.... Compute the relative location of each quadrature node along the length of the curved blade .... + CALL AllocAry(temp_ratio,p%nqp,p%elem_total,'temp_ratio',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + temp_ratio(:,:) = 0.0_BDKi + DO idx_qp=1,p%nqp + temp_ratio(idx_qp,1) = ((p%QPtN(idx_qp) + 1.0_BDKi)/2.0_BDKi)*p%member_eta(1) ! get QPtN ratio in [0,1] and multiply by member (element)'s relative length along the beam [0,1] + ENDDO + DO i=2,p%elem_total + ! add lengths of all previous members (elements) + DO j=1,i-1 + temp_ratio(:,i) = temp_ratio(:,i) + p%member_eta(j) ! compute the relative distance along the blade at the start of the member (element) + ENDDO + + ! then add ratio of length of quadrature point along this member (element) + DO idx_qp=1,p%nqp + temp_ratio(idx_qp,i) = temp_ratio(idx_qp,i) + ((p%QPtN(idx_qp) + 1.0_BDKi)/2.0_BDKi)*p%member_eta(i) + ENDDO + ENDDO + + !.... now compute mass and stiffness matrices based on this + DO i=1,p%elem_total + DO idx_qp=1,p%nqp + temp_id = (i-1)*p%nqp+idx_qp + + DO k=1,InputFileData%InpBl%station_total + + IF(temp_ratio(idx_qp,i) - InputFileData%InpBl%station_eta(k) <= EPS) THEN + + IF(ABS(temp_ratio(idx_qp,i) - InputFileData%InpBl%station_eta(k)) <= EPS) THEN + p%Stif0_QP(1:6,1:6,temp_id) = InputFileData%InpBl%stiff0(1:6,1:6,k) + p%Mass0_QP(1:6,1:6,temp_id) = InputFileData%InpBl%mass0(1:6,1:6,k) + ELSE + temp66(1:6,1:6) = (InputFileData%InpBl%stiff0(1:6,1:6,k)-InputFileData%InpBl%stiff0(1:6,1:6,k-1)) / & + (InputFileData%InpBl%station_eta(k) - InputFileData%InpBl%station_eta(k-1)) + p%Stif0_QP(1:6,1:6,temp_id) = temp66(1:6,1:6) * temp_ratio(idx_qp,i) + & + InputFileData%InpBl%stiff0(1:6,1:6,k-1) - & + temp66(1:6,1:6) * InputFileData%InpBl%station_eta(k-1) + + temp66(1:6,1:6) = (InputFileData%InpBl%mass0(1:6,1:6,k)-InputFileData%InpBl%mass0(1:6,1:6,k-1)) / & + (InputFileData%InpBl%station_eta(k) - InputFileData%InpBl%station_eta(k-1)) + p%Mass0_QP(1:6,1:6,temp_id) = temp66(1:6,1:6) * temp_ratio(idx_qp,i) + & + InputFileData%InpBl%mass0(1:6,1:6,k-1) - & + temp66(1:6,1:6) * InputFileData%InpBl%station_eta(k-1) + ENDIF + EXIT + ENDIF + ENDDO ! k=InputFileData%InpBl%station_total + + ENDDO ! idx_qp=quadrature point + ENDDO ! i=element + + DEALLOCATE(temp_ratio) + + ELSEIF(p%quadrature .EQ. TRAP_QUADRATURE) THEN +!bjj: this assumes trap quadrature has only one member. + + p%Stif0_QP(1:6,1:6,1) = InputFileData%InpBl%stiff0(1:6,1:6,1) + p%Mass0_QP(1:6,1:6,1) = InputFileData%InpBl%mass0( 1:6,1:6,1) + DO idx_qp = 2,p%nqp + + idx2 = (idx_qp-2)/p%refine + 1 ! bjj: integer math here; p%nqp = (station_total-1)*p%refine + 1 + idx1 = idx2 + 1 + + ! this is interpolating the mass and stiffness matrices ONLY if p%refine is not 1 + p%Stif0_QP(1:6,1:6,idx_qp) = InputFileData%InpBl%stiff0(1:6,1:6,idx2) + & + ((InputFileData%InpBl%stiff0(1:6,1:6,idx1) - & + InputFileData%InpBl%stiff0(1:6,1:6,idx2))/p%refine) * & + (MOD(idx_qp-2,p%refine) + 1) + + p%Mass0_QP(1:6,1:6,idx_qp) = InputFileData%InpBl%mass0(1:6,1:6,idx2) + & + ((InputFileData%InpBl%mass0(1:6,1:6,idx1) - & + InputFileData%InpBl%mass0(1:6,1:6,idx2))/p%refine) * & + (MOD(idx_qp-2,p%refine) + 1) + ENDDO + ENDIF + + +!FIXME: if we must shift the K and M matrices, this will need to be recaulculated (or calculated elsewhere) + ! Initialize some mass and inertia properies at the quadrature points + DO nelem=1,p%elem_total + DO idx_qp=1,p%nqp + p%qp%mmm(idx_qp,nelem) = p%Mass0_QP(1,1,(nelem-1)*p%nqp+idx_qp) ! mass + p%qp%mEta(1,idx_qp,nelem) = -p%Mass0_QP(3,5,(nelem-1)*p%nqp+idx_qp) ! -mass*X_cm term from equation 3.9 (after applying transform to BD coords, (3,5) in original) + p%qp%mEta(2,idx_qp,nelem) = p%Mass0_QP(3,4,(nelem-1)*p%nqp+idx_qp) ! maxx*Y_cm term from equation 3.9 (after applying transform to BD coords, (3,4) in original) + p%qp%mEta(3,idx_qp,nelem) = 0.0_BDKi + ENDDO + ENDDO + + + call Cleanup() + + return + +CONTAINS + + SUBROUTINE Cleanup() + if (allocated(temp_ratio)) deallocate(temp_ratio) + END SUBROUTINE Cleanup + +end subroutine InitializeMassStiffnessMatrices +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the positions and rotations stored in p%uuN0 (output GLL nodes) and p%QuadPt (input quadrature nodes). p%QPtN must be already set. +subroutine InitializeNodalLocations(member_total,kp_member,kp_coordinate,p,GLL_nodes,ErrStat, ErrMsg) + + INTEGER(IntKi),INTENT(IN ):: member_total + INTEGER(IntKi),INTENT(IN ):: kp_member(:) !< Number of key points of each member, InputFileData%kp_member from BD input file + REAL(BDKi), INTENT(IN ):: kp_coordinate(:,:) !< Keypoints coordinates, from BD input file InputFileData%kp_coordinate(member key points,1:4); + type(BD_ParameterType), intent(inout) :: p !< Parameters + REAL(BDKi), INTENT(IN ) :: GLL_nodes(:) !< GLL_nodes(p%nodes_per_elem): location of the (p%nodes_per_elem) p%GLL points + !type(BD_InitOutputType), intent(inout) :: InitOut !< initialization output type (for setting z_coordinate variable) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(BDKi),PARAMETER :: EPS = 1.0D-10 + + ! ---------------------------------------- + ! local variables + INTEGER(IntKi) :: elem ! do-loop counter + INTEGER(IntKi) :: i ! do-loop counter + INTEGER(IntKi) :: j ! do-loop counter + INTEGER(IntKi) :: k ! do-loop counter + INTEGER(IntKi) :: kp ! do-loop counter + integer(IntKi) :: nkp ! number keypoints for an element + integer(IntKi) :: qfit ! polynomial order used for first fit + REAL(BDKi),allocatable :: least_sq_mat(:,:) + REAL(BDKi),allocatable :: least_sq_rhs(:,:) ! RHS for X,Y,Z,Twist + integer(IntKi),allocatable :: least_sq_indx(:) + REAL(BDKi),allocatable :: least_sq_gll(:) + REAL(BDKi) :: twist + REAL(BDKi) :: tangent(3) + + REAL(BDKi),allocatable :: least_sq_shp(:,:) + REAL(BDKi),allocatable :: least_sq_shpder(:,:) + + REAL(BDKi),allocatable :: kp_param(:) + + INTEGER(IntKi) :: first_kp + INTEGER(IntKi) :: last_kp + REAL(BDKi) :: temp_POS(3) + REAL(BDKi) :: temp_CRV(3) + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'InitializeNodalLocations' + + ErrStat = ErrID_None + ErrMsg = "" + + !MIKE + + !------------------------------------------------- + ! p%uuN0 contains the initial (physical) positions and orientations of the (FE) GLL nodes + !------------------------------------------------- + p%uuN0(:,:,:) = 0.0_BDKi + + first_kp = 1 !first key point on member (element) + DO elem=1,p%elem_total + + last_kp = first_kp + kp_member(elem) - 1 !last key point of member (element) + + nkp = kp_member(elem) ! number of keypoints in this element + + if (p%nodes_per_elem .le. nkp) then + qfit = p%nodes_per_elem ! if LSFE points-per-element is less than number of keypoints fit to final poly + else + qfit = nkp ! if points-per-element more that number of keypoints, fit to LSFE with order (nkp-1) + endif + + call AllocAry(least_sq_gll, qfit, "least-squares GLL nodes",ErrStat2, ErrMsg2) + + call BD_GenerateGLL(qfit,least_sq_gll,ErrStat2,ErrMsg2) + + CALL AllocAry(least_sq_Shp,qfit,nkp,'least-squares fit shp',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(least_sq_ShpDer,qfit,nkp,'ShpDer',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL AllocAry(kp_param,nkp,'parameterization of keypoints',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! parameterize the keypoint data to [-1,1] based on z-coordinate + kp = first_kp + do j = 1, nkp + kp_param(j) = 2._BDki*(kp_coordinate(kp,3)-kp_coordinate(first_kp,3))/(kp_coordinate(last_kp,3)-kp_coordinate(first_kp,3)) - 1._BDKi + kp = kp + 1 + enddo + + ! Create shape functions evaluated at the kp positions + call BD_diffmtc(qfit,least_sq_gll,kp_param,nkp,least_sq_Shp,least_sq_ShpDer) + + CALL AllocAry(least_sq_mat,qfit,qfit,'matrix for least-squares fit',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(least_sq_indx,qfit,'indx solving least-squares fit',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(least_sq_rhs,qfit,4,'indx solving least-squares fit',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! build the least-squares-fit matrix and RHS vectors + least_sq_mat = 0._BDKi + do i = 1, qfit + do j = 1, qfit + do k = 1, nkp + least_sq_mat(i,j) = least_sq_mat(i,j) + least_sq_shp(i,k)*least_sq_shp(j,k) + enddo + enddo + enddo + + least_sq_rhs = 0._BDKi + do j = 1, 4 + do i = 1, qfit + kp = first_kp + do k = 1, nkp + least_sq_rhs(i,j) = least_sq_rhs(i,j) + least_sq_shp(i,k)*kp_coordinate(kp,j) + kp = kp+1 + enddo + enddo + enddo + + ! modify linear system so that fitted function captures keypoint endpoints + do i = 1, qfit + least_sq_mat(1,i) = 0._BDKi + least_sq_mat(qfit,i) = 0._BDKi + enddo + least_sq_mat(1,1) = 1._BDKi + least_sq_mat(qfit,qfit) = 1._BDKi + + do j = 1,4 + least_sq_rhs(1,j) = kp_coordinate(first_kp,j) + least_sq_rhs(qfit,j) = kp_coordinate(last_kp,j) + enddo + + ! factor matrix system + + CALL LAPACK_getrf( qfit, qfit, least_sq_mat, least_sq_indx, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! solve the linear system + CALL LAPACK_getrs( 'N', qfit, least_sq_mat, least_sq_indx, least_sq_rhs, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! we now have qfit LSFE coefficent that are a least squares fit to the keypoint data for XYZT + ! next, we calculate the coefficent of the p%nodes_per_elem LSFE for this element + + ! need to re-evalate qfit-node shape functions at the p%nodes_per_elem GLL points + deallocate(least_sq_shp) + deallocate(least_sq_shpder) + CALL AllocAry(least_sq_Shp,qfit,p%nodes_per_elem,'least-squares fit shp',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(least_sq_ShpDer,qfit,p%nodes_per_elem,'ShpDer',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! BD_diffmtc( nodes_per_elem,GLL_nodes,QPtN,nqp,Shp,ShpDer ) + call BD_diffmtc(qfit,least_sq_gll,gll_nodes,p%nodes_per_elem,least_sq_Shp,least_sq_ShpDer) + + do i = 1, p%nodes_per_elem + + ! start with XYZ + twist = 0._BDKi + tangent = 0._BDKi + do k = 1, qfit + do j = 1, 3 + p%uuN0(j,i,elem) = p%uuN0(j,i,elem) + least_sq_rhs(k,j)*least_sq_shp(k,i) + tangent(j) = tangent(j) + least_sq_rhs(k,j)*least_sq_shpder(k,i) + enddo + twist = twist + least_sq_rhs(k,4)*least_sq_shp(k,i) + enddo + + tangent = tangent / TwoNorm(tangent) + + CALL BD_ComputeIniNodalCrv(tangent, twist, temp_CRV, ErrStat, ErrMsg) + p%uuN0(4:6,i,elem) = temp_CRV + + enddo + + ! set for next element: + first_kp = last_kp + + deallocate(least_sq_gll) + deallocate(least_sq_Shp) + deallocate(least_sq_ShpDer) + deallocate(kp_param) + deallocate(least_sq_mat) + deallocate(least_sq_indx) + deallocate(least_sq_rhs) + + ENDDO + + return + +end subroutine InitializeNodalLocations +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the contributions of the integral of shape functions outboard of an FE node. These weighting values are +!! used as part of the integration scheme for the output of the internal forces from the Fc and Fd terms. This is simply a numerical +!! integration of those shape functions. +!! Note from ADP: I don't like this method, but haven't found a better method yet. I think a better approach may be to use the +!! inverse H' matrix and inverse shape functions, but I have not tried deriving that yet. +subroutine Initialize_FEweights(p,GLL_nodes,ErrStat,ErrMsg) + type(BD_ParameterType), intent(inout) :: p !< Parameters + real(BDKi), intent(in ) :: GLL_nodes(:) + 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 ! do-loop counter + integer(IntKi) :: nelem ! do-loop counter over number of elements + integer(IntKi) :: IntPtIdx !< index of current quadrature point in loop + real(BDKi) :: SumShp + + real(BDKi), allocatable :: Shp(:,:) !< High resolution of Shp functions + real(BDKi), allocatable :: ShpDer(:,:) !< High resolution of ShpDer functions + integer(IntKi) :: IntPoints !< number of points in the high res + REAL(BDKi), allocatable :: EtaVals(:) !< Integeration points along Z, scaled [-1 1] + REAL(BDKi), allocatable :: DistVals(:) !< Integeration points along Z, actual distance + REAL(BDKi) :: ElemLength + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Initialize_FEweights' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Set number of points for the integrations. Number chosen based on convergence tests + IntPoints=100001 + + + CALL AllocAry(EtaVals,IntPoints,'Distance along blade for high res Shp functions',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(DistVals,IntPoints,'Distance along blade for high res Shp functions',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(Shp,p%nodes_per_elem,IntPoints,'Shp',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(ShpDer,p%nodes_per_elem,IntPoints,'ShpDer',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup + return + endif + + + p%FEweight= 0.0_BDKi + + ! Loop over the elements in case we change the number of FE points between elements in the future + do nelem=1,p%elem_total + + ! Find the length of this element (straight line approximation) + ElemLength = TwoNorm(p%uuN0(1:3,p%nodes_per_elem,nelem) - p%uuN0(1:3,1,nelem)) + + ! Setup the corresponding EtaVals for all the integration points + do IntPtIdx=1,IntPoints + EtaVals(IntPtIdx) = REAL(IntPtIdx-1,BDKi)/REAL(IntPoints-1,BDKi) + enddo + + ! Calculate corresponding distances for the integration region + DistVals = EtaVals*ElemLength + + ! Scale the EtaVals to [-1 1] range for the diffmtc routine + EtaVals = 2.0_BDKi*EtaVals - 1.0_BDKi + + ! Get the high resolution Shp functions. We won't use the ShpDer results at all + call BD_diffmtc(p%nodes_per_elem,GLL_nodes,EtaVals,IntPoints,Shp,ShpDer) + + ! Integrate region outboard shape function contributions to this FE node! + do i=1,p%nodes_per_elem + SumShp=0.0_BDKi + do IntPtIdx=IntPoints,1,-1 ! Step inwards and integrate + if ( DistVals(IntPtIdx) > TwoNorm(p%uuN0(1:3,i,nelem)-p%uuN0(1:3,1,nelem))) THEN + p%FEweight(i,nelem) = p%FEweight(i,nelem) + Shp(i,IntPtIdx) + endif + SumShp=SumShp+Shp(i,IntPtIdx) + enddo + p%FEweight(i,nelem) = p%FEweight(i,nelem) / SumShp + enddo + enddo + + + call Cleanup + + contains + subroutine Cleanup() + if (allocated(EtaVals)) deallocate(EtaVals) + if (allocated(DistVals)) deallocate(DistVals) + if (allocated(EtaVals)) deallocate(Shp) + if (allocated(EtaVals)) deallocate(ShpDer) + end subroutine Cleanup +end subroutine Initialize_FEweights +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_InitShpDerJaco( GLL_Nodes, p ) + + ! Bauchau chapter 17.1 gives an intro to displacement fields, the shape functions and the jacobian + ! see Bauchau equation 17.12 + ! also https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant + + REAL(BDKi), INTENT(IN ) :: GLL_nodes(:) !< p%GLL point locations + TYPE(BD_ParameterType), INTENT(INOUT) :: p !< Parameters + + REAL(BDKi) :: Gup0(3) + INTEGER(IntKi) :: i, j + INTEGER(IntKi) :: nelem, idx_qp + + CHARACTER(*), PARAMETER :: RoutineName = 'BD_InitShpDerJaco' + + + CALL BD_diffmtc(p%nodes_per_elem,GLL_nodes,p%QPtN,p%nqp,p%Shp,p%ShpDer) + + DO nelem = 1,p%elem_total + DO idx_qp = 1, p%nqp + Gup0(:) = 0.0_BDKi + DO i=1,p%nodes_per_elem + Gup0(:) = Gup0(:) + p%ShpDer(i,idx_qp)*p%uuN0(1:3,i,nelem) + ENDDO + p%Jacobian(idx_qp,nelem) = TwoNorm(Gup0) + ENDDO + ENDDO + + + ! save some variables so we don't recalculate them so often: + DO nelem=1,p%elem_total + DO idx_qp=1,p%nqp + DO j=1,p%nodes_per_elem + DO i=1,p%nodes_per_elem + p%QPtw_Shp_Shp_Jac( idx_qp,i,j,nelem) = p%Shp( i,idx_qp)*p%Shp( j,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem) + p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) = p%ShpDer(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp)/p%Jacobian(idx_qp,nelem) + END DO + END DO + END DO + END DO + + + DO idx_qp=1,p%nqp + DO j=1,p%nodes_per_elem + DO i=1,p%nodes_per_elem + p%QPtw_Shp_ShpDer(idx_qp,i,j) = p%Shp(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp) + END DO + END DO + END DO + + DO nelem=1,p%elem_total + DO i=1,p%nodes_per_elem + DO idx_qp=1,p%nqp + p%QPtw_Shp_Jac(idx_qp,i,nelem) = p%Shp( i,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem) + END DO + END DO + END DO + + DO i=1,p%nodes_per_elem + DO idx_qp=1,p%nqp + p%QPtw_ShpDer(idx_qp,i) = p%ShpDer(i,idx_qp)*p%QPtWeight(idx_qp) + END DO + END DO + +END SUBROUTINE BD_InitShpDerJaco + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine initializes data in the InitOut type, which is returned to the glue code. +subroutine SetInitOut(p, InitOut, ErrStat, ErrMsg) + + type(BD_InitOutputType), intent(inout) :: InitOut !< output data (we've already set InitOut%z_coordinate) + type(BD_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 + integer(intKi) :: i ! loop counter + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'SetInitOut' + + + + ! Initialize variables for this routine + + errStat = ErrID_None + errMsg = "" + + ! p%BldNd_BlOutNd contains the list of nodes we are outputting. At each node there are BldNd_NumOuts output channels. + + call AllocAry( InitOut%WriteOutputHdr, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputHdr', errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call AllocAry( InitOut%WriteOutputUnt, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputUnt', errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + do i=1,p%NumOuts + InitOut%WriteOutputHdr(i) = p%OutParam(i)%Name + InitOut%WriteOutputUnt(i) = p%OutParam(i)%Units + end do + + InitOut%Ver = BeamDyn_Ver + + + ! Set the info in WriteOutputHdr and WriteOutputUnt for BldNd sections. + CALL BldNdOuts_InitOut( InitOut, p, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +end subroutine SetInitOut +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine allocates and initializes most (not all) of the parameters used in BeamDyn. +subroutine SetParameters(InitInp, InputFileData, p, ErrStat, ErrMsg) + type(BD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(BD_InputFile), intent(inout) :: InputFileData !< data from the input file [we may need to shift the keypoint to match a MK matrix eta for trap multi-element] + type(BD_ParameterType), intent(inout) :: p !< Parameters ! intent(out) only because it changes p%NdIndx + 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, j ! generic counter index + INTEGER(IntKi) :: indx ! counter into index array (p%NdIndx) + INTEGER(IntKi) :: nUniqueQP ! number of unique quadrature points (not double-counting nodes at element boundaries) + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'SetParameters' + + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Global position vector + p%GlbPos = InitInp%GlbPos + + + ! Global rotation tensor. What comes from the driver may not be a properly formed + ! DCM (may have roundoff), so recalculate it from the extracted WM parameters. + p%GlbRot = TRANSPOSE(InitInp%GlbRot) ! matrix that now transfers from local to global (FAST's DCMs convert from global to local) + CALL BD_CrvExtractCrv(p%GlbRot,p%Glb_crv, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + CALL BD_CrvMatrixR(p%Glb_crv,p%GlbRot) ! ensure that the rotation matrix is a DCM in double precision (this should be the same as TRANSPOSE(InitInp%GlbRot)) + + ! Gravity vector + p%gravity = MATMUL(InitInp%gravity,p%GlbRot) + + + !.................... + ! data copied/derived from input file + !.................... + + ! Set solve type + IF (.NOT. InitInp%DynamicSolve) THEN + p%analysis_type = BD_STATIC_ANALYSIS + ELSE + ! QuasiStatic only valid with dynamic solves + IF ( InputFileData%QuasiStaticInit ) THEN + p%analysis_type = BD_DYN_SSS_ANALYSIS + ELSE + p%analysis_type = BD_DYNAMIC_ANALYSIS + ENDIF + ENDIF + + + p%RotStates = InputFileData%RotStates ! Rotate states in linearization? + p%RelStates = InputFileData%RelStates ! Define states relative to root motion in linearization? + + p%rhoinf = InputFileData%rhoinf ! Numerical damping coefficient: [0,1]. No numerical damping if rhoinf = 1; maximum numerical damping if rhoinf = 0. + p%dt = InputFileData%DTBeam ! Time step size + CALL BD_TiSchmComputeCoefficients(p) ! Compute generalized-alpha time integrator coefficients requires p%rhoinf,p%dt; sets p%coef + + p%tngt_stf_fd = InputFileData%tngt_stf_fd ! flag used to compute tangent stiffness matrix using finite differencing + p%tngt_stf_comp = InputFileData%tngt_stf_comp ! flag used to compare finite differenced and analytical tangent stiffness matrix + p%tngt_stf_pert = InputFileData%tngt_stf_pert ! perturbation size used to compute finite differenced tangent stiffness matrix + p%tngt_stf_difftol = InputFileData%tngt_stf_difftol ! tolerance for informing user of significant differences in analytical and fd tangent stiffness + + p%ld_retries = InputFileData%load_retries ! Maximum number of iterations in Newton-Raphson algorithm + p%niter = InputFileData%NRMax ! Maximum number of iterations in Newton-Raphson algorithm + p%tol = InputFileData%stop_tol ! Tolerance used in stopping criterion + p%elem_total = InputFileData%member_total ! Total number of elements + p%nodes_per_elem = InputFileData%order_elem + 1 ! Number of GLL nodes per element + p%n_fact = InputFileData%n_fact ! Factorization frequency + p%quadrature = InputFileData%quadrature ! Quadrature method: 1 Gauss 2 Trapezoidal + + p%BldMotionNodeLoc = BD_MESH_FE + + IF(p%quadrature .EQ. GAUSS_QUADRATURE) THEN + ! Number of Gauss points + p%nqp = p%nodes_per_elem !- 1 + p%qp_indx_offset = 1 ! we skip the first node on the input mesh (AD needs values at the end points, but BD doesn't use them) + ELSEIF(p%quadrature .EQ. TRAP_QUADRATURE) THEN ! at least one quadrature point associated with each blade station + p%refine = InputFileData%refine + p%nqp = (InputFileData%InpBl%station_total - 1)*p%refine + 1 + p%qp_indx_offset = 0 + p%BldMotionNodeLoc = BD_MESH_QP ! we want to output y%BldMotion at the blade input property stations, and this will be a short-cut + ENDIF + + + p%dof_node = 6 ! Degree-of-freedom (DoF) per node + p%node_total = p%elem_total*(p%nodes_per_elem-1) + 1 ! Total number of (finite element) nodes + p%dof_total = p%node_total*p%dof_node ! Total number of (finite element) dofs + + p%dof_elem = p%dof_node * p%nodes_per_elem + p%rot_elem = (p%dof_node/2) * p%nodes_per_elem + + + + !................................ + ! allocate some parameter arrays + !................................ + CALL AllocAry(p%member_eta, p%elem_total,'member length ratio array', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%segment_eta,InputFileData%kp_total-1,'segment length ratio array',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%node_elem_idx,p%elem_total,2,'start and end node numbers of elements in p%node_total sized arrays',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL AllocAry(p%Shp, p%nodes_per_elem,p%nqp, 'p%Shp', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%ShpDer, p%nodes_per_elem,p%nqp, 'p%ShpDer', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%Jacobian,p%nqp, p%elem_total,'p%Jacobian',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(p%QPtw_Shp_Shp_Jac ,p%nqp,p%nodes_per_elem,p%nodes_per_elem,p%elem_total,'p%QPtw_Shp_Shp_Jac', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%QPtw_Shp_ShpDer ,p%nqp,p%nodes_per_elem,p%nodes_per_elem, 'p%QPtw_Shp_ShpDer', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%QPtw_ShpDer_ShpDer_Jac,p%nqp,p%nodes_per_elem,p%nodes_per_elem,p%elem_total,'p%QPtw_ShpDer_ShpDer_Jac',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%QPtw_Shp_Jac ,p%nqp ,p%nodes_per_elem,p%elem_total,'p%QPtw_Shp_Jac', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%QPtw_ShpDer ,p%nqp ,p%nodes_per_elem, 'p%QPtw_ShpDer', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL AllocAry(p%uuN0, p%dof_node,p%nodes_per_elem, p%elem_total,'uuN0 (initial position) array',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%rrN0, (p%dof_node/2),p%nodes_per_elem, p%elem_total,'p%rrN0',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%uu0, p%dof_node, p%nqp, p%elem_total,'p%uu0', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%E10, (p%dof_node/2),p%nqp, p%elem_total,'p%E10', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(p%FEweight,p%nodes_per_elem,p%elem_total,'p%FEweight array',ErrStat2,ErrMsg2) ; CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Quadrature point and weight arrays in natural frame + CALL AllocAry(p%QPtN, p%nqp,'p%QPtN', ErrStat2,ErrMsg2) ; CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%QPtWeight,p%nqp,'p%QPtWeight array',ErrStat2,ErrMsg2) ; CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Quadrature mass and inertia terms + CALL AllocAry(p%qp%mmm, p%nqp,p%elem_total, 'p%qp%mmm mass at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%qp%mEta, p%dof_node/2,p%nqp,p%elem_total, 'p%qp%mEta at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + if (ErrStat >= AbortErrLev) return + + + + !............................................... + ! Set start and end node index for each elements + !............................................... + + ! Store the node number for first and last FE node in element + ! p%node_total = p%elem_total*(p%nodes_per_elem-1) + 1 is the number of GLL nodes total for the beam + ! --> This assumes that the first node of element 2 is the same as the last node of element 1. + ! Some subroutines are looking at a single element, in which case the values stored in p%nodes_elem_idx + ! are used to indicate which node to start with. + DO i=1,p%elem_total + p%node_elem_idx(i,1) = (i-1)*(p%nodes_per_elem-1) + 1 ! First node in element + p%node_elem_idx(i,2) = i *(p%nodes_per_elem-1) + 1 ! Last node in element + ENDDO + + + SELECT CASE(p%BldMotionNodeLoc) + CASE (BD_MESH_FE) + CALL AllocAry(p%NdIndx,p%node_total,'p%NdIndx',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%NdIndxInverse,p%elem_total*p%nodes_per_elem,'p%NdIndxInverse',ErrStat2,ErrMsg2) ! same size as y%BldMotion%NNodes + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%OutNd2NdElem,2,p%node_total,'p%OutNd2NdElem',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + p%NdIndx(1) = 1 + p%OutNd2NdElem(:,1) = 1 ! note this is an array + indx = 2 + DO i=1,p%elem_total + p%NdIndxInverse((i-1)*p%nodes_per_elem + 1) = indx-1 ! Index into BldMotion mesh (to number the nodes for output without using collocated nodes) + + DO j=2,p%nodes_per_elem ! GLL nodes overlap at element end points; we will skip the first node of each element (after the first one) + p%NdIndx(indx) = (i-1)*p%nodes_per_elem + j ! Index into BldMotion mesh (to number the nodes for output without using collocated nodes) + p%NdIndxInverse(p%NdIndx(indx)) = indx ! Index from BldMotion mesh (to number of unique nodes) + p%OutNd2NdElem(1,indx) = j ! Node number. To go from an output node number to a node/elem pair + p%OutNd2NdElem(2,indx) = i ! Element number. To go from an output node number to a node/elem pair + indx = indx + 1 + END DO + ENDDO + + CASE (BD_MESH_QP) + + IF (p%quadrature .EQ. GAUSS_QUADRATURE) THEN + nUniqueQP = p%nqp*p%elem_total + 2*p%qp_indx_offset + + CALL AllocAry(p%NdIndxInverse, nUniqueQP,'p%NdIndxInverse',ErrStat2,ErrMsg2) ! same size as y%BldMotion%NNodes, a sibling of u%DistrLoad + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%NdIndx, nUniqueQP,'p%NdIndx',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%OutNd2NdElem,2,nUniqueQP,'p%OutNd2NdElem',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + DO i=1,nUniqueQP ! gauss quadrature doesn't have overlapping nodes + p%NdIndx(i) = i + p%NdIndxInverse(i) = i + END DO + + indx = 2 + DO i=1,p%elem_total + DO j=1,p%nqp ! gauss quadrature doesn't have overlapping nodes, but it does contain two end points + p%OutNd2NdElem(1,indx) = j ! Node number. To go from an output node number to a node/elem pair + p%OutNd2NdElem(2,indx) = i ! Element number. To go from an output node number to a node/elem pair + indx = indx + 1; + END DO + ENDDO + p%OutNd2NdElem(1,1) = 0 ! node: this end point isn't really a quadrature node - need to check how this is used!!!! + p%OutNd2NdElem(2,1) = 1 ! element: this end point isn't really a quadrature node - need to check how this is used!!!! + p%OutNd2NdElem(1,nUniqueQP) = 0 ! node: this end point isn't really a quadrature node - need to check how this is used!!!! + p%OutNd2NdElem(2,nUniqueQP) = p%elem_total ! element: this end point isn't really a quadrature node - need to check how this is used!!!! + + ELSEIF(p%quadrature .EQ. TRAP_QUADRATURE) THEN ! at least one quadrature point associated with each blade station + nUniqueQP = (p%nqp-1)*p%elem_total + 1 + + CALL AllocAry(p%NdIndxInverse, nUniqueQP,'p%NdIndxInverse',ErrStat2,ErrMsg2) ! same size as y%BldMotion%NNodes, a sibling of u%DistrLoad + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%NdIndx, nUniqueQP,'p%NdIndx',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%OutNd2NdElem,2,nUniqueQP,'p%OutNd2NdElem',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + p%NdIndx(1) = 1 + p%OutNd2NdElem(:,1) = 1 ! note this is an array + indx = 2 + DO i=1,p%elem_total + DO j=2,p%nqp ! trap quadrature contains overlapping nodes at element end points; we will skip the first node of each element (after the first one) + p%NdIndx(indx) = (i-1)*p%nqp + j ! Index into BldMotion mesh (to number the nodes for output without using collocated nodes) + p%NdIndxInverse(p%NdIndx(indx)) = indx ! Index from BldMotion mesh + p%OutNd2NdElem(1,indx) = j ! Node number. To go from an output node number to a node/elem pair + p%OutNd2NdElem(2,indx) = i ! Element number. To go from an output node number to a node/elem pair + indx = indx + 1; + END DO + ENDDO + + ENDIF + + END SELECT + + !............................................... + ! Physical damping flag and 6 damping coefficients + !............................................... + p%damp_flag = InputFileData%InpBl%damp_flag + p%beta = InputFileData%InpBl%beta + + !............................................... + ! set parameters for pitch actuator: + !............................................... + + + !............................................... + ! set parameters for File I/O data: + !............................................... + p%OutFmt = InputFileData%OutFmt + + p%numOuts = InputFileData%NumOuts + p%NNodeOuts = InputFileData%NNodeOuts + p%OutNd = InputFileData%OutNd + + p%OutInputs = .false. ! will get set to true in SetOutParam if we request the inputs as output values + + call SetOutParam(InputFileData%OutList, p, ErrStat2, ErrMsg2 ) ! requires: p%NumOuts, p%NNodeOuts, p%UsePitchAct; sets: p%OutParam. + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + + call BldNdOuts_SetParameters(InitInp, InputFileData, p, ErrStat2, ErrMsg2 ) ! requires p%BldNd_NumOuts, y%BldMotion + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + +end subroutine SetParameters +!----------------------------------------------------------------------------------------------------------------------------------- +!> this routine initializes the outputs, y, that are used in the BeamDyn interface for coupling in the FAST framework. +subroutine Init_y( p, u, y, ErrStat, ErrMsg) + + type(BD_ParameterType), intent(inout) :: p !< Parameters -- intent(out) only because it changes p%NdIndx + type(BD_InputType), intent(inout) :: u !< Inputs + type(BD_OutputType), intent(inout) :: y !< Outputs + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + real(R8Ki) :: DCM(3,3) ! must be same type as mesh orientation fields + real(ReKi) :: Pos(3) ! must be same type as mesh position fields + + + integer(intKi) :: temp_id + integer(intKi) :: i,j ! loop counters + integer(intKi) :: NNodes ! number of nodes in mesh + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_y' + + + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................. + ! y%ReactionForce (for coupling with ElastoDyn) + !................................. + + CALL MeshCopy( SrcMesh = u%RootMotion & + , DestMesh = y%ReactionForce & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) RETURN + + + !................................. + ! y%BldMotion (for coupling with AeroDyn) + !................................. + + SELECT CASE (p%BldMotionNodeLoc) + CASE (BD_MESH_FE) ! This is how the NREL-version of BeamDyn works (output nodes at the finite element nodes) + + NNodes = p%nodes_per_elem*p%elem_total ! this is the same as the number of FE nodes, with overlapping nodes at the element end points + CALL MeshCreate( BlankMesh = y%BldMotion & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = NNodes & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) RETURN + + ! position nodes + DO i=1,p%elem_total + DO j=1,p%nodes_per_elem + + temp_id = (j-1)*p%dof_node + + Pos = p%GlbPos + MATMUL(p%GlbRot,p%uuN0(1:3,j,i)) + + ! possible type conversions here: + DCM = BDrot_to_FASTdcm(p%uuN0(4:6,j,i),p) + + ! set the reference position and orientation for each node. + temp_id = (i-1)*p%nodes_per_elem+j + CALL MeshPositionNode ( Mesh = y%BldMotion & + ,INode = temp_id & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ENDDO + ENDDO + + ! create elements + + DO i=1,p%elem_total + DO j=1,p%nodes_per_elem - 1 + temp_id = (i-1)*p%nodes_per_elem + j ! first node of element + + CALL MeshConstructElement( Mesh = y%BldMotion & + ,Xelement = ELEMENT_LINE2 & + ,P1 = temp_id & + ,P2 = temp_id+1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + ENDDO + + CALL MeshCommit ( Mesh = y%BldMotion & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) RETURN + + CASE (BD_MESH_QP) ! create the mesh at the quadrature points, which are the same as the blade input property stations for trapezoidal quadrature + + CALL MeshCopy( SrcMesh = u%DistrLoad & + , DestMesh = y%BldMotion & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) RETURN + + + CASE DEFAULT + + CALL SetErrStat(ErrID_Fatal, "Invalid p%BldMotionNodeLoc.", ErrStat, ErrMsg, RoutineName ) + + END SELECT + y%BldMotion%RefNode = 1 + + + + !................................. + ! y%WriteOutput (for writing columns to output file) + !................................. + ! p%BldNd_BlOutNd contains the list of nodes we are outputting. + + call AllocAry( y%WriteOutput, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutput', errStat2, errMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +end subroutine Init_y +!----------------------------------------------------------------------------------------------------------------------------------- +!> this routine initializes the inputs, u, that are used in the BeamDyn interface for coupling in the FAST framework. +subroutine Init_u( InitInp, p, u, ErrStat, ErrMsg ) + + type(BD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(BD_ParameterType), intent(in ) :: p !< Parameters + type(BD_InputType), intent(inout) :: u !< Inputs + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + real(R8Ki) :: DCM(3,3) ! must be same type as mesh orientation fields + real(ReKi) :: Pos(3) ! must be same type as mesh position fields + + integer(intKi) :: temp_id + integer(intKi) :: i,j ! loop counters + integer(intKi) :: NNodes ! number of nodes in mesh + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_u' + + ErrStat = ErrID_None + ErrMsg = "" + + !................................. + ! u%HubMotion (from ElastoDyn for pitch actuator) + !................................. + + CALL MeshCreate( BlankMesh = u%HubMotion & + ,IOS = COMPONENT_INPUT & + ,NNodes = 1 & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) return + + ! possible type conversions here: + DCM = InitInp%HubRot + Pos = InitInp%HubPos + CALL MeshPositionNode ( Mesh = u%HubMotion & + , INode = 1 & + , Pos = Pos & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 & + , Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshConstructElement ( Mesh = u%HubMotion & + , Xelement = ELEMENT_POINT & + , P1 = 1 & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshCommit(u%HubMotion, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! initial guesses + u%HubMotion%TranslationDisp(1:3,1) = 0.0_ReKi + u%HubMotion%Orientation(1:3,1:3,1) = InitInp%HubRot + + !................................. + ! u%RootMotion (for coupling with ElastoDyn) + !................................. + + CALL MeshCreate( BlankMesh = u%RootMotion & + ,IOS = COMPONENT_INPUT & + ,NNodes = 1 & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , RotationAcc = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) return + + + DCM = TRANSPOSE(p%GlbRot) + Pos = p%GlbPos + CALL MeshPositionNode ( Mesh = u%RootMotion & + , INode = 1 & + , Pos = Pos & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 & + , Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshConstructElement ( Mesh = u%RootMotion & + , Xelement = ELEMENT_POINT & + , P1 = 1 & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL MeshCommit ( Mesh = u%RootMotion & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! initial guesses + u%RootMotion%TranslationDisp(1:3,1) = InitInp%RootDisp(1:3) + u%RootMotion%Orientation(1:3,1:3,1) = InitInp%RootOri(1:3,1:3) + u%RootMotion%TranslationVel(1:3,1) = InitInp%RootVel(1:3) + u%RootMotion%RotationVel(1:3,1) = InitInp%RootVel(4:6) + u%RootMotion%TranslationAcc(:,:) = 0.0_ReKi + u%RootMotion%RotationAcc(:,:) = 0.0_ReKi + + !................................. + ! u%PointLoad (currently not used in FAST; from BD driver only) + !................................. + + CALL MeshCreate( BlankMesh = u%PointLoad & + ,IOS = COMPONENT_INPUT & + ,NNodes = p%node_total & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) return + + DO i=1,p%elem_total + DO j=1,p%nodes_per_elem + POS = p%GlbPos(1:3) + MATMUL(p%GlbRot,p%uuN0(1:3,j,i)) + + ! Note: Here we can use this subroutine to get the DCM. This is under the assumption + ! that there is no rotational displacement yet, so x%q is zero + DCM = BDrot_to_FASTdcm(p%uuN0(4:6,j,i),p) + + temp_id = (i-1)*(p%nodes_per_elem-1)+j + CALL MeshPositionNode ( Mesh = u%PointLoad & + ,INode = temp_id & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + , Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + ENDDO + + DO i=1,p%node_total + CALL MeshConstructElement( Mesh = u%PointLoad & + ,Xelement = ELEMENT_POINT & + ,P1 = i & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ENDDO + + CALL MeshCommit ( Mesh = u%PointLoad & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! initial guesses + u%PointLoad%Force = 0.0_ReKi + u%PointLoad%Moment = 0.0_ReKi + + !................................. + ! u%DistrLoad (for coupling with AeroDyn) + !................................. + + NNodes = p%nqp*p%elem_total + 2*p%qp_indx_offset + + CALL MeshCreate( BlankMesh = u%DistrLoad & + ,IOS = COMPONENT_INPUT & + ,NNodes = NNodes & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat>=AbortErrLev) return + + + + DO i=1,p%elem_total + DO j=1,p%nqp !NOTE: if we add multi-element to trap, we will need to change this. + temp_id = (i-1)*p%nqp + j + p%qp_indx_offset ! Index to a node within element i + Pos(1:3) = p%GlbPos(1:3) + MATMUL(p%GlbRot,p%uu0(1:3,j,i)) + + ! Note: Here we can use this subroutine to get the DCM. This is under the assumption + ! that there is no rotational displacement yet, so m%qp%uuu is zero + DCM = BDrot_to_FASTdcm(p%uu0(4:6,j,i),p) + + CALL MeshPositionNode ( Mesh = u%DistrLoad & + ,INode = temp_id & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + ENDDO + + ! For Gauss quadrature, an additional node is added to the end. + IF (p%quadrature .EQ. GAUSS_QUADRATURE) THEN + ! First node + Pos(1:3) = p%GlbPos(1:3) + MATMUL(p%GlbRot,p%uuN0(1:3,1,1)) + DCM = BDrot_to_FASTdcm(p%uuN0(4:6,1,1),p) + CALL MeshPositionNode ( Mesh = u%DistrLoad & + ,INode = 1 & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Last node + Pos(1:3) = p%GlbPos(1:3) + MATMUL(p%GlbRot,p%uuN0(1:3,p%nodes_per_elem,p%elem_total)) + DCM = BDrot_to_FASTdcm(p%uuN0(4:6,p%nodes_per_elem,p%elem_total),p) + CALL MeshPositionNode ( Mesh = u%DistrLoad & + ,INode = NNodes & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + + + DO i=1,NNodes-1 + CALL MeshConstructElement( Mesh = u%DistrLoad & + ,Xelement = ELEMENT_LINE2 & + ,P1 = i & + ,P2 = i+1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + + + CALL MeshCommit ( Mesh = u%DistrLoad & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u%DistrLoad'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! initial guesses + u%DistrLoad%Force = 0.0_ReKi + u%DistrLoad%Moment = 0.0_ReKi + + +end subroutine Init_u +!----------------------------------------------------------------------------------------------------------------------------------- +!> this subroutine initializes the misc variables. +subroutine Init_MiscVars( p, u, y, m, ErrStat, ErrMsg ) + type(BD_ParameterType), intent(in ) :: p !< Parameters + type(BD_InputType), intent(inout) :: u !< Inputs ! intent(out) because I'm copying it + type(BD_OutputType), intent(inout) :: y !< Outputs ! intent(out) because I'm copying it + type(BD_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 + + + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_MiscVars' + + ErrStat = ErrID_None + ErrMsg = "" + + m%Un_Sum = -1 + + +! NOTE: +! p%nodes_per_elem = nodes per element, read in +! p%elem_total = number elements, read in +! p%dof_node = 6 +! p%node_total = p%elem_total * (p%nodes_per_elem-1) + 1 +! p%dof_total = p%dof_node * p%node_total +! p%dof_elem = p%dof_node * p%nodes_per_elem +! p%rot_elem = p%dof_node/2 * p%nodes_per_elem + + + + ! allocate arrays at initialization so we don't waste so much time on memory allocation/deallocation on each step + + ! Arrays for use with LAPACK matrix solve routines (A*X = B solve for X) + ! - m%LP_StifK_LU - matrix A in solve + ! - m%LP_RHS_LU - array B in call, solution array X returned + CALL AllocAry(m%LP_RHS_LU, p%dof_total-6, 'LP_RHS_LU', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_RHS, p%dof_total, 'LP_RHS', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_StifK_LU, p%dof_total-6,p%dof_total-6, 'LP_StifK_LU', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_StifK, p%dof_total,p%dof_total, 'LP_StifK', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_MassM, p%dof_total,p%dof_total, 'LP_MassM', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_MassM_LU, p%dof_total-6,p%dof_total-6, 'LP_MassM_LU', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%LP_indx, p%dof_total, 'LP_indx', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! LAPACK routine outputs converted to dimensionality used in BD. Note the index ordering here is due to reshape functions before calls to LAPACK routines + ! - m%Solution holds the redimensioned m%LP_RHS_LU (returned X array) + CALL AllocAry(m%Solution, p%dof_node, p%node_total, 'Solution', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%RHS, p%dof_node,p%node_total, 'RHS', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%StifK, p%dof_node,p%node_total,p%dof_node,p%node_total, 'StifK', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%MassM, p%dof_node,p%node_total,p%dof_node,p%node_total, 'MassM', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%DampG, p%dof_node,p%node_total,p%dof_node,p%node_total, 'DampG', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Arrays used in the finite differencing routines. These arrays are analogoous to the above declared analytical arrays and follow the same dimensionality + IF ( p%tngt_stf_fd .or. p%tngt_stf_comp ) THEN + CALL AllocAry(m%RHS_m, p%dof_node,p%node_total, 'RHS_m', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%RHS_p, p%dof_node,p%node_total, 'RHS_p', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%StifK_fd, p%dof_node,p%node_total,p%dof_node,p%node_total, 'StifK_fd', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%MassM_fd, p%dof_node,p%node_total,p%dof_node,p%node_total, 'MassM_fd', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%DampG_fd, p%dof_node,p%node_total,p%dof_node,p%node_total, 'DampG_fd', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + + CALL AllocAry(m%BldInternalForceFE, p%dof_node,p%node_total, 'Calculated Internal Force at FE', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%BldInternalForceQP, p%dof_node,y%BldMotion%NNodes, 'Calculated Internal Force at QP', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%FirstNodeReactionLclForceMoment, p%dof_node, 'Root node reaction force/moment', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + m%FirstNodeReactionLclForceMoment = 0.0_BDKi ! This is set to zero so that first timestep values make sense from driver with static solve. + + CALL AllocAry(m%Nrrr, (p%dof_node/2),p%nodes_per_elem,p%elem_total,'Nrrr: rotation parameters relative to root', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(m%elf, p%dof_node,p%nodes_per_elem, 'elf', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(m%EFint, p%dof_node,p%nodes_per_elem,p%elem_total, 'Elastic Force internal', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Note the index ordering here. This comes from the reshaping to other arrays used with LAPACK solvers + CALL AllocAry(m%elk, p%dof_node,p%nodes_per_elem,p%dof_node,p%nodes_per_elem, 'elk', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%elg, p%dof_node,p%nodes_per_elem,p%dof_node,p%nodes_per_elem, 'elg', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%elm, p%dof_node,p%nodes_per_elem,p%dof_node,p%nodes_per_elem, 'elm', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Point loads applied to FE nodes from driver code. + CALL AllocAry(m%PointLoadLcl, p%dof_node,p%node_total, 'PointLoadLcl', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Distributed load from mesh, on the quadrature points. The ramping copy is for the quasi-static solve + CALL AllocAry(m%DistrLoad_QP, p%dof_node,p%nqp,p%elem_total, 'DistrLoad_QP',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Array for storing the position information for the quadrature points. + CALL AllocAry(m%qp%uuu, p%dof_node ,p%nqp,p%elem_total, 'm%qp%uuu displacement at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%uup, p%dof_node/2,p%nqp,p%elem_total, 'm%qp%uup displacement prime at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%vvv, p%dof_node ,p%nqp,p%elem_total, 'm%qp%vvv velocity at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%vvp, p%dof_node ,p%nqp,p%elem_total, 'm%qp%vvp velocity prime at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%aaa, p%dof_node ,p%nqp,p%elem_total, 'm%qp%aaa acceleration at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! Need to initialize this to zero especially for static cases + m%qp%aaa = 0.0_BDKi + + ! E1, kappa -- used in force calculations + CALL AllocAry(m%qp%E1, p%dof_node/2,p%nqp,p%elem_total, 'm%qp%E1 at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%kappa, p%dof_node/2,p%nqp,p%elem_total, 'm%qp%kappa at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%RR0, 3,3, p%nqp,p%elem_total, 'm%qp%RR0 at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Stif, 6,6, p%nqp,p%elem_total, 'm%qp%Stif at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Calculations for mass matrix + CALL AllocAry(m%qp%RR0mEta, p%dof_node/2,p%nqp,p%elem_total, 'm%qp%RRo times p%qp%mEta at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%rho, 3,3, p%nqp,p%elem_total, 'm%qp%rho at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%betaC, 6,6, p%nqp,p%elem_total, 'm%qp%betaC at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Force calculation terms + CALL AllocAry(m%qp%Fb, p%dof_node,p%nqp,p%elem_total, 'm%qp%Fb at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Fc, p%dof_node,p%nqp,p%elem_total, 'm%qp%Fc at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Fd, p%dof_node,p%nqp,p%elem_total, 'm%qp%Fd at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Fg, p%dof_node,p%nqp,p%elem_total, 'm%qp%Fg at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Fi, p%dof_node,p%nqp,p%elem_total, 'm%qp%Fi at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Ftemp, p%dof_node,p%nqp,p%elem_total, 'm%qp%Ftemp at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Inertial force terms + CALL AllocAry(m%qp%Gi, 6,6, p%nqp,p%elem_total, 'm%qp%Gi gyroscopic at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Ki, 6,6, p%nqp,p%elem_total, 'm%qp%Ki stiffness at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Mi, 6,6, p%nqp,p%elem_total, 'm%qp%Mi mass at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Elastic force terms: \f$ \underline{\underline{\mathcal{O}}} \f$, etc. from equation (19-21) of NREL CP-2C00-60759. + CALL AllocAry(m%qp%Oe, 6,6, p%nqp,p%elem_total, 'm%qp%Oe term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Pe, 6,6, p%nqp,p%elem_total, 'm%qp%Pe term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Qe, 6,6, p%nqp,p%elem_total, 'm%qp%Qe term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Dissipative terms + CALL AllocAry(m%qp%Gd, 6,6, p%nqp,p%elem_total, 'm%qp%Gd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Od, 6,6, p%nqp,p%elem_total, 'm%qp%Od term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Pd, 6,6, p%nqp,p%elem_total, 'm%qp%Pd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Qd, 6,6, p%nqp,p%elem_total, 'm%qp%Qd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Sd, 6,6, p%nqp,p%elem_total, 'm%qp%Sd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Xd, 6,6, p%nqp,p%elem_total, 'm%qp%Xd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(m%qp%Yd, 6,6, p%nqp,p%elem_total, 'm%qp%Yd term at quadrature point',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize variables that could be output before they are set. + m%qp%Fi = 0.0_BDKi ! This could be output before it gets set. + + ! create copy of u%DistrLoad at y%BldMotion locations (for WriteOutput only) + if (p%OutInputs .and. p%BldMotionNodeLoc /= BD_MESH_QP ) then + + ! y%BldMotion and u%DistrLoad are not siblings, so we need to create + ! mapping to output u%DistrLoad values at y%BldMotion nodes + ! (not making these new meshes siblings of old ones because FAST needs to + ! do this same trick and we can't have more than one sibling of a mesh) + + CALL MeshCopy ( SrcMesh = y%BldMotion & + , DestMesh = m%u_DistrLoad_at_y & + , CtrlCode = MESH_COUSIN & ! Like a sibling, except using new memory for position/refOrientation and elements + , IOS = COMPONENT_INPUT & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshCopy ( SrcMesh = u%DistrLoad & + , DestMesh = m%y_BldMotion_at_u & + , CtrlCode = MESH_COUSIN & + , IOS = COMPONENT_OUTPUT & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshMapCreate( u%DistrLoad, m%u_DistrLoad_at_y, m%Map_u_DistrLoad_to_y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MeshMapCreate( y%BldMotion, m%y_BldMotion_at_u, m%Map_y_BldMotion_to_u, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + m%u_DistrLoad_at_y%remapFlag = .false. + m%y_BldMotion_at_u%remapFlag = .false. + end if + + ! create copy of inputs, which will be converted to internal BeamDyn coordinate system + ! (put in miscVars so we don't have to create new meshes each call) + CALL BD_CopyInput(u, m%u, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL BD_CopyInput(u, m%u2, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + +end subroutine Init_MiscVars +!----------------------------------------------------------------------------------------------------------------------------------- +!> this subroutine initializes the other states. +subroutine Init_OtherStates( p, OtherState, ErrStat, ErrMsg ) + type(BD_ParameterType), intent(in ) :: p !< Parameters + type(BD_OtherStateType), intent(inout) :: OtherState !< Other states + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_OtherStates' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Allocate other states: Acceleration and algorithm accelerations for generalized-alpha time integator + CALL AllocAry(OtherState%acc, p%dof_node, p%node_total, 'OtherState%acc',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(OtherState%xcc, p%dof_node, p%node_total, 'OtherState%xcc',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat>=AbortErrLev) return + + OtherState%InitAcc = .false. ! accelerations have not been initialized, yet + + OtherState%acc(:,:) = 0.0_BDKi + OtherState%xcc(:,:) = 0.0_BDKi + + + ! This is used to make sure we only run the quasi-static initialization for the states at T=0 when p%analysis_type == BD_DYN_SSS_ANALYSIS (otherwise don't rerun it). + !OtherState%RunQuasiStaticInit = p%analysis_type == BD_DYN_SSS_ANALYSIS + ! BJJ: not sure this should be used in CalcOutput when we are calculating Jacobians (this will alter the operating point of the continuous state) + OtherState%RunQuasiStaticInit = .FALSE. + +end subroutine Init_OtherStates +!----------------------------------------------------------------------------------------------------------------------------------- +!> this subroutine initializes the continuous states. +subroutine Init_ContinuousStates( p, u, x, ErrStat, ErrMsg ) + type(BD_ParameterType), intent(inout) :: p !< Parameters !sets the copy-of-state values + type(BD_InputType), intent(inout) :: u !< Inputs !intent(out) because of mesh copy, otherwise not changed + type(BD_ContinuousStateType), intent(inout) :: x !< Continuous states + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + TYPE(BD_InputType) :: u_tmp ! A copy of the initial input (guess), converted to BeamDyn internal coordinates + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_ContinuousStates' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate continuous states + CALL AllocAry(x%q, p%dof_node, p%node_total,'x%q', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(x%dqdt, p%dof_node, p%node_total,'x%dqdt', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + x%q(:,:) = 0.0_BDKi + x%dqdt(:,:) = 0.0_BDKi + + + ! create copy of inputs, u, to convert to BeamDyn-internal system inputs, u_tmp, which is used to initialize states: + CALL BD_CopyInput(u, u_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! convert to BeamDyn-internal system inputs, u_tmp: + CALL BD_InputGlobalLocal(p,u_tmp) + + + ! initialize states, given parameters and initial inputs (in BD coordinates) + CALL BD_CalcIC_Position(u_tmp,p,x, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL BD_CalcIC_Velocity(u_tmp,p,x) + CALL Cleanup() + +CONTAINS + SUBROUTINE Cleanup() + CALL BD_DestroyInput( u_tmp, ErrStat2, ErrMsg2) + END SUBROUTINE cleanup +END SUBROUTINE Init_ContinuousStates + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE BD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + TYPE(BD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(BD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(BD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(BD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(BD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(BD_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Place any last minute operations or calculations here: + + ! Close files here: + if (m%Un_Sum > 0) CLOSE(m%Un_Sum) + + + ! Destroy the input data: + + CALL BD_DestroyInput( u, ErrStat, ErrMsg ) + + ! Destroy the parameter data: + + CALL BD_DestroyParam( p, ErrStat, ErrMsg ) + + ! Destroy the state data: + + CALL BD_DestroyContState( x, ErrStat, ErrMsg ) + CALL BD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL BD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL BD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + ! Destroy misc data + CALL BD_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL BD_DestroyOutput( y, ErrStat, ErrMsg ) + +END SUBROUTINE BD_End + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> 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 BD_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current simulation time step n = 0,1,... + TYPE(BD_InputType), INTENT(INOUT) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< Times associated with u(:), in seconds + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + dt + TYPE(BD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(BD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Initial guess of constraint states at t + dt; + !! Output: Constraint states at t + dt + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + dt + TYPE(BD_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 + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + IF(p%analysis_type /= BD_STATIC_ANALYSIS) THEN ! dynamic analysis + CALL BD_GA2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSE !IF(p%analysis_type == BD_STATIC_ANALYSIS) THEN + CALL BD_Static( t, u, utimes, p, x, OtherState, m, ErrStat, ErrMsg ) + ENDIF + +END SUBROUTINE BD_UpdateStates + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE BD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, NeedWriteOutput ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at t + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(BD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(BD_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 + LOGICAL, OPTIONAL, INTENT(IN ) :: NeedWriteOutput !< Flag to determine if WriteOutput values need to be calculated in this call + + TYPE(BD_ContinuousStateType) :: x_tmp + TYPE(BD_OtherStateType) :: OtherState_tmp + INTEGER(IntKi) :: i ! generic loop counter + INTEGER(IntKi) :: nelem ! loop over elements + REAL(ReKi) :: AllOuts(0:MaxOutPts) + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcOutput' + LOGICAL :: CalcWriteOutput + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + AllOuts = 0.0_ReKi + + if (present(NeedWriteOutput)) then + CalcWriteOutput = NeedWriteOutput + else + CalcWriteOutput = .true. ! by default, calculate WriteOutput unless told that we do not need it + end if + + ! Since x is passed in, but we need to update it, we must work with a copy. + CALL BD_CopyContState(x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! we may change the inputs (u) by applying the pitch actuator, so we will use m%u in this routine + CALL BD_CopyInput(u, m%u, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Actuator + IF( p%UsePitchAct ) THEN + CALL PitchActuator_SetBC(p, m%u, xd, AllOuts) + ENDIF + ! END Actuator + + + CALL BD_CopyInput(m%u, m%u2, MESH_UPDATECOPY, ErrStat2, ErrMsg2) ! this is a copy of the inputs after the pitch actuator has been applied, but before converting to BD coordinates. will use this for computing WriteOutput values. + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + + ! We are trying to use quasistatic solve with loads, but do not know the input loads during initialization (no mesh yet). + ! So, we need to rerun the solve routine to set the states at T=0 for the outputs to make sense. + ! bjj: do we need to do a hack to get the jacobian set properly? + IF ( OtherState%RunQuasiStaticInit ) THEN + + ! Since OtherState is passed in, but we need to update it, we must work with a copy. + CALL BD_CopyOtherState(OtherState, OtherState_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Solve for the displacements with the acceleration and rotational velocity terms included + ! This will set m%qp%aaa, OtherState%Acc, x_tmp%q, and x_tmp%dqdt + ! if this is not successful, it restores the values of x_tmp and sets OtherState_tmp%Acc=0 + CALL BD_QuasiStatic(u,p,x_tmp,OtherState_tmp,m,ErrStat2,ErrMsg2, RampLoad=.true.) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Destroy the copy of OtherState. + CALL BD_DestroyOtherState(OtherState_tmp, ErrStat2, ErrMsg2 ) + + ENDIF + + + + ! convert to BD coordinates and apply boundary conditions + CALL BD_InputGlobalLocal(p,m%u) + + ! Copy over the DistrLoads + CALL BD_DistrLoadCopy( p, m%u, m ) + + ! Incorporate boundary conditions (note that we are doing this because the first node isn't really a state. should fix x so we don't need a temp copy here.) + x_tmp%q( 1:3,1) = m%u%RootMotion%TranslationDisp(:,1) + CALL ExtractRelativeRotation(m%u%RootMotion%Orientation(:,:,1),p, x_tmp%q( 4:6,1), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + x_tmp%dqdt(1:3,1) = m%u%RootMotion%TranslationVel(:,1) + x_tmp%dqdt(4:6,1) = m%u%Rootmotion%RotationVel(:,1) + + ! Calculate Quadrature point values needed for BldForce results + CALL BD_QuadraturePointData( p,x_tmp,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + + IF(p%analysis_type /= BD_STATIC_ANALYSIS) THEN ! dynamic analysis + + ! These values have not been set yet for the QP + CALL BD_QPData_mEta_rho( p,m ) ! Calculate the \f$ m \eta \f$ and \f$ \rho \f$ terms + CALL BD_QPDataVelocity( p, x_tmp, m ) ! x%dqdt --> m%qp%vvv, m%qp%vvp + + ! calculate accelerations and reaction loads (in m%RHS): + CALL BD_CalcForceAcc(m%u, p, m, ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE + ! Calculate the elastic forces for the static case. + DO nelem=1,p%elem_total + CALL BD_StaticElementMatrix( nelem, p%gravity, p, m ) + ENDDO + + ENDIF + + ! Calculate internal forces and moments + CALL BD_InternalForceMoment( x, p, m ) + + ! Transfer the FirstNodeReaction forces to the output ReactionForce + y%ReactionForce%Force(:,1) = MATMUL(p%GlbRot,m%FirstNodeReactionLclForceMoment(1:3)) + y%ReactionForce%Moment(:,1) = MATMUL(p%GlbRot,m%FirstNodeReactionLclForceMoment(4:6)) + + + ! set y%BldMotion fields: + CALL Set_BldMotion_Mesh( p, m%u2, x, m, y) + + !------------------------------------------------------- + ! compute RootMxr and RootMyr for ServoDyn and + ! get values to output to file: + !------------------------------------------------------- + call Calc_WriteOutput( p, AllOuts, y, m, ErrStat2, ErrMsg2, CalcWriteOutput ) !uses m%u2 + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + y%RootMxr = AllOuts( RootMxr ) + y%RootMyr = AllOuts( RootMyr ) + + if (CalcWriteOutput) then + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) array with the proper sign: + !............................................................................................................................... + + do i = 1,p%NumOuts ! Loop through all selected output channels + y%WriteOutput(i) = p%OutParam(i)%SignM * AllOuts( p%OutParam(i)%Indx ) + end do ! i - All selected output channels + + + IF( p%BldNd_NumOuts > 0 ) THEN + ! Put the values from the nodal outputs into the writeoutput array + y%WriteOutput(p%NumOuts+1:) = 0.0_ReKi + + ! Now we need to populate the blade node outputs here + call Calc_WriteBldNdOutput( p, m, y, ErrStat2, ErrMsg2 ) ! Call after normal writeoutput. Will just postpend data on here. + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDIF + end if + + + call cleanup() + return + +CONTAINS + SUBROUTINE Cleanup() + CALL BD_DestroyContState(x_tmp, ErrStat2, ErrMsg2 ) + END SUBROUTINE cleanup +END SUBROUTINE BD_CalcOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +SUBROUTINE BD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at t () + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: dxdt !< Continuous state derivatives at t [intent in so we don't need to allocate/deallocate constantly] + 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 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcContStateDeriv' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! we may change the inputs (u) by applying the pitch actuator, so we will use m%u in this routine + CALL BD_CopyInput(u, m%u, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + ! Actuator + !!!IF( p%UsePitchAct ) THEN + !!! CALL PitchActuator_SetBC(p, m%u, xd, AllOuts) + !!!ENDIF + ! END Actuator + + ! convert to BD coordinates and apply boundary conditions + CALL BD_InputGlobalLocal(p,m%u) + + ! Copy over the DistrLoads + CALL BD_DistrLoadCopy( p, m%u, m ) + + ! Incorporate boundary conditions (note that we are doing this because the first node isn't really a state. should fix x so we don't need a temp copy here.) + ! Note that I am using dxdt as a temporary copy of x here. + CALL BD_CopyContState(x, dxdt, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + dxdt%q( 1:3,1) = m%u%RootMotion%TranslationDisp(:,1) + CALL ExtractRelativeRotation(m%u%RootMotion%Orientation(:,:,1),p, dxdt%q( 4:6,1), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + !dxdt%q( 4:6,1) = ExtractRelativeRotation(m%u%RootMotion%Orientation(:,:,1),p) + dxdt%dqdt(1:3,1) = m%u%RootMotion%TranslationVel(:,1) + dxdt%dqdt(4:6,1) = m%u%Rootmotion%RotationVel(:,1) + + ! Calculate Quadrature point values needed for BldForce results + CALL BD_QuadraturePointData( p, dxdt,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + + ! These values have not been set yet for the QP + CALL BD_QPData_mEta_rho( p,m ) ! Calculate the \f$ m \eta \f$ and \f$ \rho \f$ terms + CALL BD_QPDataVelocity( p, dxdt, m ) ! x%dqdt --> m%qp%vvv, m%qp%vvp + + ! calculate accelerations and reaction loads (in m%RHS): + CALL BD_CalcForceAcc(m%u, p, m, ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + ! now set the derivatives of the continuous states. + ! I am a little concerned that W-M parameter derivatives are in the wrong units, but I think this is the same issue that is in the GA2 solve (the opposite direction) + dxdt%q = dxdt%dqdt + dxdt%dqdt = m%RHS + + ! constraint state (which is not necessary, but I'll just add it here anyway) + dxdt%dqdt(1:3,1) = u%RootMotion%TranslationAcc(:,1) + dxdt%dqdt(4:6,1) = u%RootMotion%RotationAcc( :,1) + +END SUBROUTINE BD_CalcContStateDeriv + +!----------------------------------------------------------------------------------------------------------------------------------- +!> Routine for updating discrete states +SUBROUTINE BD_UpdateDiscState( t, n, u, 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*dt + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(BD_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 + + ! local variables + REAL(BDKi) :: temp_R(3,3) + REAL(BDKi) :: Hub_theta_Root(3) + REAL(BDKi) :: u_theta_pitch + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Update discrete states here: + +! Actuator + IF( p%UsePitchAct ) THEN + !bjj: note that we've cheated a bit here because we have inputs at t+dt + temp_R = MATMUL(u%RootMotion%Orientation(:,:,1),TRANSPOSE(u%HubMotion%Orientation(:,:,1))) + Hub_theta_Root = EulerExtract(temp_R) + u_theta_pitch = -Hub_theta_Root(3) + + xd%thetaP = p%torqM(1,1)*xd%thetaP + p%torqM(1,2)*xd%thetaPD + p%torqM(1,2)*(p%pitchK*p%dt/p%pitchJ)*(-Hub_theta_Root(3)) + xd%thetaPD = p%torqM(2,1)*xd%thetaP + p%torqM(2,2)*xd%thetaPD + p%torqM(2,2)*(p%pitchK*p%dt/p%pitchJ)*(-Hub_theta_Root(3)) + + + ENDIF +! END Actuator + +END SUBROUTINE BD_UpdateDiscState + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes initial Gauss point values: uu0, E10 +! Note similarities to BD_QuadraturePointData +SUBROUTINE BD_QuadraturePointDataAt0( p ) + + TYPE(BD_ParameterType), INTENT(INOUT) :: p !< Parameters + + REAL(BDKi) :: rot0_temp(3) + REAL(BDKi) :: rotu_temp(3) + REAL(BDKi) :: rot_temp(3) + REAL(BDKi) :: R0_temp(3,3) + + INTEGER(IntKi) :: nelem ! number of current element + INTEGER(IntKi) :: idx_qp ! index of current quadrature point + INTEGER(IntKi) :: idx_node ! index of current GLL node + + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuadraturePointDataAt0' + + + ! Initialize to zero for the summation + p%uu0(:,:,:) = 0.0_BDKi + p%rrN0(:,:,:) = 0.0_BDKi + p%E10(:,:,:) = 0.0_BDKi + + + ! calculate rrN0 (Initial relative rotation array) + DO nelem = 1,p%elem_total + p%rrN0(1:3,1,nelem) = (/ 0.0_BDKi, 0.0_BDKi, 0.0_BDKi /) ! first node has no rotation relative to itself. + DO idx_node=2,p%nodes_per_elem + ! Find resulting rotation parameters R(Nr) = Ri^T(Nu(1)) R(Nu(:)) + ! where R(Nu(1))^T is the transpose rotation parameters for the root node + CALL BD_CrvCompose(p%rrN0(1:3,idx_node,nelem),p%uuN0(4:6,1,nelem),p%uuN0(4:6,idx_node,nelem),FLAG_R1TR2) ! rrN0 = node composed with root + ENDDO + ENDDO + + + DO nelem = 1,p%elem_total + DO idx_qp = 1,p%nqp + !> ### Calculate the the initial displacement fields in an element + !! Initial displacement field \n + !! \f$ \underline{u_0}\left( \xi \right) = + !! \sum_{k=1}^{p+1} h^k\left( \xi \right) \underline{\hat{u}_0}^k + !! \f$ \n + !! and curvature \n + !! \f$ \underline{c_0}\left( \xi \right) = + !! \sum_{k=1}^{p+1} h^k\left( \xi \right) \underline{\hat{c}_0}^k + !! \f$ + + ! Note that p%uu0 was set to zero prior to this routine call, so the following is the summation. + + DO idx_node=1,p%nodes_per_elem + p%uu0(1:3,idx_qp,nelem) = p%uu0(1:3,idx_qp,nelem) + p%Shp(idx_node,idx_qp)*p%uuN0(1:3,idx_node,nelem) + p%uu0(4:6,idx_qp,nelem) = p%uu0(4:6,idx_qp,nelem) + p%Shp(idx_node,idx_qp)*p%rrN0(1:3,idx_node,nelem) + ENDDO + + + !> Add the blade root rotation parameters. That is, + !! compose the rotation parameters calculated with the shape functions with the rotation parameters + !! for the blade root. + rot0_temp(:) = p%uuN0(4:6,1,nelem) ! Rotation at root + rotu_temp(:) = p%uu0( 4:6,idx_qp,nelem) ! Rotation at current GLL point without root rotation + + CALL BD_CrvCompose(rot_temp,rot0_temp,rotu_temp,FLAG_R1R2) ! rot_temp = rot0_temp composed with rotu_temp + p%uu0(4:6,idx_qp,nelem) = rot_temp(:) ! Rotation parameters at current GLL point with the root orientation + + + !> Set the initial value of \f$ x_0^\prime \f$, the derivative with respect to \f$ \hat{x} \f$-direction + !! (tangent to curve through this GLL point). This is simply the + CALL BD_CrvMatrixR(p%uu0(4:6,idx_qp,nelem),R0_temp) ! returns R0_temp (the transpose of the DCM orientation matrix) + p%E10(:,idx_qp,nelem) = R0_temp(:,3) ! unit vector tangent to curve through this GLL point (derivative with respect to z in IEC coords). + ENDDO + ENDDO + + +END SUBROUTINE BD_QuadraturePointDataAt0 + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine interpolates quadrature point values in the inertial frame of the following values: +!! 4) RR0, and 5) kappa. +!! This routine contains steps 2 and 3 of the interpolation algorithm; step 1 is found in the subroutine bd_nodalrelrot(), +!! which is called prior to this routine (that routine is called for all quadrature points, whereas this one is called within +!! a loop over quadrature points). +SUBROUTINE BD_QuadraturePointData( p, x, m ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: nelem !< index to the current element + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuadraturePointData' + + DO nelem=1,p%elem_total + CALL BD_DisplacementQP( nelem, p, x, m ) + CALL BD_RotationalInterpQP( nelem, p, x, m ) + CALL BD_StifAtDeformedQP( nelem, p, m ) + ENDDO + +END SUBROUTINE BD_QuadraturePointData + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine interpolates quadrature point values in the inertial frame of the following values: +!! 1) uuu, 2) uup, 3) E1 +!! +!! The equations used here can be found in the NREL publication CP-2C00-60759 +!! "Nonlinear Legendre Spectral Finite Elements for Wind Turbine Blade Dynamics" +!! http://www.nrel.gov/docs/fy14osti/60759.pdf +!! +!! NOTE: on coordinate frames of p%E10 nd m%qp%E1 +!! At first glance it appears that p%E10 and m%qp%E1 are in different coordinate frames (initial reference, and inertial with rotation). +!! However, note that the m%qp%uup is rotating and compensates for the fact that p%E10 is in the initial reference frame. If there is +!! change in x%q due to inertial or other loading (such that x%q is purely due to rotation), the m%qp%E1 values are merely the rotated +!! p%E10 values. +SUBROUTINE BD_DisplacementQP( nelem, p, x, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: idx_qp !< index to the current quadrature point + INTEGER(IntKi) :: elem_start !< Node point of first node in current element + INTEGER(IntKi) :: idx_node + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DisplacementQP' + + + DO idx_qp=1,p%nqp + ! Node point before start of this element + elem_start = p%node_elem_idx( nelem,1 ) + + + !> ### Calculate the the displacement fields in an element + !! Using equations (27) and (28) \n + !! \f$ \underline{u}\left( \xi \right) = + !! \sum_{i=1}^{p+1} h^i\left( \xi \right) \underline{\hat{u}}^i + !! \f$ \n + !! and \n + !! \f$ \underline{u}^\prime \left( \xi \right) = + !! \sum_{k=1}^{p+1} h^{k\prime} \left( \xi \right) \underline{\hat{u}}^i + !! \f$ + !! + !! | Variable | Value | + !! | :---------: | :------------------------------------------------------------------------- | + !! | \f$ \xi \f$ | Element natural coordinate \f$ \in [-1,1] \f$ | + !! | \f$ k \f$ | Node number of a \f$ p^\text{th} \f$ order Langrangian-interpolant | + !! | \f$ h^i \left( \xi \right ) \f$ | Component of the shape function matrix, \f$ \underline{\underline{N}} \f$ | + !! | \f$ h^{k\prime} \left( \xi \right ) \f$ | \f$ \frac{\mathrm{d}}{\mathrm{d}x_1} h^i \left( \xi \right) \f$ | + !! | \f$ \underline{\hat{u}}^i \f$ | \f$ k^\text{th} \f$ nodal value | + + ! Initialize values for summation + m%qp%uuu(:,idx_qp,nelem) = 0.0_BDKi ! displacement field \f$ \underline{u} \left( \xi \right) \f$ + m%qp%uup(:,idx_qp,nelem) = 0.0_BDKi ! displacement field \f$ \underline{u}^\prime \left( \xi \right) \f$ + + DO idx_node=1,p%nodes_per_elem + m%qp%uuu(1:3,idx_qp,nelem) = m%qp%uuu(1:3,idx_qp,nelem) + p%Shp(idx_node,idx_qp) *x%q(1:3,elem_start - 1 + idx_node) + m%qp%uup(1:3,idx_qp,nelem) = m%qp%uup(1:3,idx_qp,nelem) + p%ShpDer(idx_node,idx_qp)/p%Jacobian(idx_qp,nelem)*x%q(1:3,elem_start - 1 + idx_node) + ENDDO + + !> Calculate \f$ \underline{E}_1 = x_0^\prime + u^\prime \f$ (equation 23). Note E_1 is along the z direction. + m%qp%E1(1:3,idx_qp,nelem) = p%E10(1:3,idx_qp,nelem) + m%qp%uup(1:3,idx_qp,nelem) + + ENDDO +END SUBROUTINE BD_DisplacementQP + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine interpolates quadrature point values in the inertial frame of the following values: +!! 4) RR0, and 5) kappa. +!! This routine contains steps 2 and 3 of the interpolation algorithm; step 1 is found in the subroutine bd_nodalrelrot(), +!! which is called prior to this routine (that routine is called for all quadrature points, whereas this one is called within +!! a loop over quadrature points). +SUBROUTINE BD_RotationalInterpQP( nelem, p, x, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: idx_qp !< index to the current quadrature point + INTEGER(IntKi) :: elem_start !< Node point of first node in current element + INTEGER(IntKi) :: idx_node !< index to current GLL point in element + REAL(BDKi) :: rrr(3) !< relative rotation field \f$ \underline{r}(\xi) \f$ + REAL(BDKi) :: rrp(3) !< relative prime rotation field \f$ \underline{r}^\prime(\xi) \f$ + REAL(BDKi) :: cc(3) + REAL(BDKi) :: temp33(3,3) + REAL(BDKi) :: DCM_root(3,3) !< DCM for first node + CHARACTER(*), PARAMETER :: RoutineName = 'BD_RotationalInterpQP' + + + !> ## Calculate the interpolated rotational displacements + !! To calculate this, the algorithm given in http://www.nrel.gov/docs/fy14osti/60759.pdf + !! is used. + !! This overcomes issues related to + !! -# the non-linear nature of the rotation parameters + !! -# rescaling to eliminate singularity at \f$ \pm 2 \pi \f$ + !! -# rotation fields lacking objectivity + !! + !! The steps involved in the interpolation algorithm are: + !! -# Find rotation parameters relative to root, \f$\underline{\hat{r}}^i\f$ + !! In principle this step could be done here, but for practical reasons is done outside this routine. + !! -# Interploate the relative rotation field using shape functions as \n + !! \f$ \underline{r}(\xi) = \sum_{k=1}^{p+1} h^i(\xi) \underline{\hat{r}}^i\f$\n + !! and \n + !! \f$ \underline{r}^\prime(\xi) = \sum_{k=1}^{p+1} h^i(\xi) h^{k\prime}(\xi) \underline{\hat{r}}^i\f$.\n + !! Then find the curvature field, + !! \f$ \underline{k}(\xi) + !! = \underline{\underline{R}}\left(\underline{\hat{c}}^1\right) + !! \underline{\underline{H}}(\underline{r})\underline{r}^\prime \f$, \n where + !! \f$\underline{\underline{H}}\f$ is the tangent tensor that relates the curvator vector \f$\underline{k}\f$ + !! and rotation vector \f$\underline{p}\f$ as + !! \f$ \underline{k}=\underline{\underline{H}}\underline{p}^\prime \f$ (equation (31)_ + !! + !! -# Restore rigid body motion removed in Step 1 with + !! \f$ \underline{c}\left(\xi\right) = \underline{\hat{c}}^1 \oplus \underline{r}\left(\xi\right) \f$ + + + ! Index to GLL node for start of current element + elem_start = p%node_elem_idx(nelem,1) + + + !> ** Step 1: ** Find rotation parameters relative to root \f$\underline{\hat{r}}^i\f$ + !! Compute the nodal relative rotations, \f$\underline{\hat{r}}^k\f$ by removing the reference rotation (root rotation), \f$\underline{\hat{c}}^1\f$ + !! from the finite rotation at each node. Calculate by \n + !! \f$ \underline{\hat{r}}^k = \left(\underline{\hat{c}}^{1-}\right) \oplus \hat{c}^k \f$. \n + !! The minus sign on \f$ \underline{\hat{c}}^{1} \f$ denotes the relative rotation is calculated by removing the reference rotation from each node. + !! This composition in this equation is the equivalent of \n + !! \f$ \underline{\underline{R}}\left(\underline{\hat{r}}^k\right) + !! = \underline{\underline{R}}^T\left(\underline{\hat{c}}^1\right) \underline{\underline{R}}\left(\underline{\underline{c}}^k\right) \f$. + + !> Find the transpose of the DCM orientation matrix of the root as + !! \f$ \underline{\underline{R}}\left(\underline{\hat{c}}^1\right)\f$ + CALL BD_CrvMatrixR(x%q(4:6,elem_start),DCM_root) ! returns DCM_root (the transpose of the DCM orientation matrix at the root (first node of the element)) + + + ! Calculate the rotation parameters relative to the root for each node + DO idx_node=1,p%nodes_per_elem + ! Find resulting rotation parameters R(Nr) = Ri^T(x%q(1)) R(x%q(:)) + ! where R(x%q(1))^T is the transpose rotation parameters for the root node + CALL BD_CrvCompose(m%Nrrr(1:3,idx_node,nelem),x%q(4:6,elem_start),x%q(4:6,elem_start-1+idx_node),FLAG_R1TR2) ! m%Nrrr(1:3,idx_node,nelem) = x%q(4:6,elem_start)^- composed with x%q(4:6,elem_start-1+idx_node) + ENDDO + + + + ! QP rotational interpolation + DO idx_qp=1,p%nqp + + + !> ### Calculate \f$ \underline{r}(\xi) \f$ and \f$\underline{r}^\prime (\xi)\f$ + !! + !! **Step 2:** + !! Using equations (29) and (30) \n + !! \f$ \underline{r}\left( \xi \right) = + !! \sum_{k=1}^{p+1} h^i\left( \xi \right) \underline{\hat{r}}^i + !! \f$ \n + !! and \n + !! \f$ \underline{r}^\prime \left( \xi \right) = + !! \sum_{k=1}^{p+1} h^{k\prime} \left( \xi \right) \underline{\hat{r}}^i + !! \f$ + !! + !! | Variable | Value | + !! | :---------: | :------------------------------------------------------------------------- | + !! | \f$ \xi \f$ | Element natural coordinate \f$ \in [-1,1] \f$ | + !! | \f$ k \f$ | Node number of a \f$ p^\text{th} \f$ order Langrangian-interpolant | + !! | \f$ h^i \left( \xi \right ) \f$ | Component of the shape function matrix, \f$ \underline{\underline{N}} \f$ | + !! | \f$ h^{k\prime} \left( \xi \right ) \f$ | \f$ \frac{\mathrm{d}}{\mathrm{d}x_1} h^i \left( \xi \right) \f$ | + !! | \f$ \underline{\hat{r}}^i \f$ | \f$ k^\text{th} \f$ nodal value | + + + ! Initialize values for summations + rrr = 0.0_BDKi ! intermediate rotation field for calculation + rrp = 0.0_BDKi + + ! Note: `m%Nrrr` is \f$ \underline{\hat{r}}^i \f$ + DO idx_node=1,p%nodes_per_elem + rrr(1:3) = rrr(1:3) + p%Shp(idx_node,idx_qp) *m%Nrrr(1:3,idx_node,nelem) + rrp(1:3) = rrp(1:3) + p%ShpDer(idx_node,idx_qp)/p%Jacobian(idx_qp,nelem)*m%Nrrr(1:3,idx_node,nelem) + ENDDO + + !> **Step 3:** Restore the rigid body rotation at node \f$ \xi \f$ with \n + !! \f$ \underline{c}(\xi) = \underline{\hat{c}}^1 \oplus \underline{r}(\xi) \f$ \n + !! which is equivalent to \n + !! \f$ \underline{\underline{R}}\left(c^i\right) + !! = \underline{\underline{R}}\left(\underline{\hat{c}}^1\right) + !! \underline{\underline{R}}\left(\underline{\underline{r}}^i\right) \f$ + CALL BD_CrvCompose(m%qp%uuu(4:6,idx_qp,nelem),x%q(4:6,elem_start),rrr,FLAG_R1R2) ! m%qp%uuu(4:6,idx_qp,nelem) = x%q(4:6,elem_start) composed with rrr + + + !> ###Find the curvature field + !! \f$ \underline{k}(\xi) + !! = \underline{\underline{R}}\left(\underline{\hat{c}}^1\right) + !! \underline{\underline{H}}(\underline{r})\underline{r}^\prime \f$ + !! + !! **Step 2:** + + !> Calculate the tangent tensor, \f$\underline{\underline{H}}(\underline{r})\f$ times \f$\underline{r}^\prime\f$ + !! This term gives us the axial(R'R^T). See Bauchau book 17.119 + CALL BD_CrvMatrixH(rrr,temp33) ! retrieve the tangent tensor given rrr + cc = MATMUL(temp33,rrp) ! \underline{k} in eq (5) http://www.nrel.gov/docs/fy14osti/60759.pdf + + !> Assemble \f$\underline{kappa}\f$ by adding in the root rotation. + !! This is \f$\underline{\kappa} = \underline{k} + \underline{\underline{R}}\underline{k}_i \f$ + m%qp%kappa(:,idx_qp,nelem) = MATMUL(DCM_root,cc) + + !> ###Find the rotation tensor \f$ \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \f$ + !! + !! Note: \f$ \underline{\underline{R}}\underline{\underline{R}}_0 \f$ is used to go from the material basis into the inertial basis + !! and the transpose for the other direction. + + CALL BD_CrvCompose(cc,m%qp%uuu(4:6,idx_qp,nelem),p%uu0(4:6,idx_qp,nelem),FLAG_R1R2) ! cc = m%qp%uuu(4:6,idx_qp,nelem) composed with p%uu0(4:6,idx_qp,nelem) + CALL BD_CrvMatrixR(cc,m%qp%RR0(:,:,idx_qp,nelem)) ! returns RR0 (the transpose of the DCM orientation matrix) + + ENDDO + +END SUBROUTINE BD_RotationalInterpQP + +!----------------------------------------------------------------------------------------------------------------------------------- +!> Transform the \f$\underline{\underline{C}}\f$ stiffness matrix to the local quadrature point deformed orientation. +!! Returns new value for m%qp%Stif +SUBROUTINE BD_StifAtDeformedQP( nelem, p, m ) + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: idx_qp !< index counter for quadrature point + INTEGER(IntKi) :: temp_id2 !< Index to last node of previous element + INTEGER(IntKi) :: i,j !< generic counters + REAL(BDKi) :: tempR6(6,6) + REAL(BDKi) :: tempBeta6(6,6) + + + ! see Bauchau 2011 Flexible Multibody Dynamics p 692-693, section 17.7.2 + + ! extract the mass and stiffness matrices for the current element + temp_id2 = (nelem-1)*p%nqp + + DO idx_qp=1,p%nqp + !> RR0 is the rotation tensor at quadrature point \f$ \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \f$ (3x3) + + ! Setup the temporary matrix for modifying the stiffness matrix. RR0 is changing with time. + tempR6 = 0.0_BDKi + tempBeta6 = 0.0_BDKi + tempR6(1:3,1:3) = m%qp%RR0(:,:,idx_qp,nelem) ! upper left -- translation + tempR6(4:6,4:6) = m%qp%RR0(:,:,idx_qp,nelem) ! lower right -- rotation + !NOTE: Bauchau has the lower right corner multiplied by H + + ! Move damping ratio from material frame to the calculation reference frame + ! This is the following: + ! tempBEta6=matmul(tempR6,matmul(diag(p%beta),transpose(tempR6))) + do j=1,6 + do i=1,6 + ! diagonal of p%beta * TRANSPOSE(tempR6) + tempBeta6(i,j) = p%beta(i)*tempR6(j,i) + enddo + enddo + tempBeta6 = matmul(tempR6,tempBeta6) + + + !> Modify the Mass matrix so it is in the calculation reference frame + !! \f$ \begin{bmatrix} + !! \left(\underline{\underline{R}} \underline{\underline{R}}_0\right) & 0 \\ + !! 0 & \left(\underline{\underline{R}} \underline{\underline{R}}_0\right) + !! \end{bmatrix} + !! \underline{\underline{C}} + !! \begin{bmatrix} + !! \left(\underline{\underline{R}} \underline{\underline{R}}_0\right)^T & 0 \\ + !! 0 & \left(\underline{\underline{R}} \underline{\underline{R}}_0\right)^T + !! \end{bmatrix} \f$ + m%qp%Stif(:,:,idx_qp,nelem) = MATMUL(tempR6,MATMUL(p%Stif0_QP(1:6,1:6,temp_id2+idx_qp),TRANSPOSE(tempR6))) + + ! Now apply the damping + m%qp%betaC(:,:,idx_qp,nelem) = matmul(tempBeta6,m%qp%Stif(:,:,idx_qp,nelem)) + ENDDO + +END SUBROUTINE BD_StifAtDeformedQP + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> Calculate the \f$ m \underline{\eta} \f$ and \f$ \rho \f$ terms for use in calculations involving mass +!! Returns values for `m%qp%RR0mEta` and `m%qp%rho` +! +! Input: Mass0_QP RR0 +! Output: m%qp%RR0mEta m%qp%rho +! +! mEta is a 3 element array +! rho is a 3x3 matrix +SUBROUTINE BD_QPData_mEta_rho( p, m ) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: nelem !< index to current element number + INTEGER(IntKi) :: idx_qp !< index to the current quadrature point + + DO nelem=1,p%elem_total + DO idx_qp=1,p%nqp + !> Calculate the new center of mass times mass at the deflected location + !! as \f$ \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) m \underline{\eta} \f$ + m%qp%RR0mEta(:,idx_qp,nelem) = MATMUL(m%qp%RR0(:,:,idx_qp,nelem),p%qp%mEta(:,idx_qp,nelem)) + + !> Calculate \f$ \rho = \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) + !! \underline{\underline{M}}_{2,2} + !! \left(\underline{\underline{R}}\underline{\underline{R}}_0\right)^T \f$ where + !! \f$ \underline{\underline{M}}_{2,2} \f$ is the inertial terms of the undeflected mass matrix at this quadrature point + m%qp%rho(:,:,idx_qp,nelem) = p%Mass0_QP(4:6,4:6,(nelem-1)*p%nqp+idx_qp) + m%qp%rho(:,:,idx_qp,nelem) = MATMUL(m%qp%RR0(:,:,idx_qp,nelem),MATMUL(m%qp%rho(:,:,idx_qp,nelem),TRANSPOSE(m%qp%RR0(:,:,idx_qp,nelem)))) + ENDDO + ENDDO + +END SUBROUTINE BD_QPData_mEta_rho + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the elastic forces Fc and Fd +!! It also calcuates the linearized matrices Oe, Pe, and Qe for N-R algorithm. +!! +!! The equations used here can be found in the NREL publication CP-2C00-60759 +!! (http://www.nrel.gov/docs/fy14osti/60759.pdf) +SUBROUTINE BD_ElasticForce(nelem,p,m,fact) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables. + LOGICAL, INTENT(IN ) :: fact !< Boolean to calculate the Jacobian + + REAL(BDKi) :: cet !< for storing the \f$ I_{yy} + I_{zz} \f$ inertia term + REAL(BDKi) :: k1s + REAL(BDKi) :: Wrk33(3,3) + REAL(BDKi) :: tildeE(3,3) + REAL(BDKi) :: C21(3,3) + REAL(BDKi) :: epsi(3,3) + REAL(BDKi) :: mu(3,3) + + INTEGER(IntKi) :: idx_qp !< Index to quadrature point currently being calculated + + + if (.not. fact) then + + do idx_qp=1,p%nqp + call Calc_Fc_Fd() + end do + + else + + do idx_qp=1,p%nqp + + call Calc_Fc_Fd() + + + !> ###Calculate the \f$ \underline{\underline{\mathcal{O}}} \f$ from equation (19) + !! + !! \f$ \underline{\underline{\mathcal{O}}} = + !! \begin{bmatrix} + !! \underline{\underline{0}} & \underline{\underline{C}}_{11} \tilde{E}_1 - \tilde{F} \\ + !! \underline{\underline{0}} & \underline{\underline{C}}_{21} \tilde{E}_1 - \tilde{M} + !! \end{bmatrix} + !! = \begin{bmatrix} + !! \underline{\underline{0}} & \psi_E - \tilde{F} \\ + !! \underline{\underline{0}} & \mu - \tilde{M} + !! \end{bmatrix} + !! \f$ + Wrk33(:,:) = OuterProduct(m%qp%RR0(1:3,3,idx_qp,nelem), m%qp%RR0(1:3,3,idx_qp,nelem)) ! z-direction in IEC coords + C21(:,:) = m%qp%Stif(4:6,1:3,idx_qp,nelem) + cet*k1s*Wrk33(:,:) + + tildeE = SkewSymMat(m%qp%E1(:,idx_qp,nelem)) + epsi(:,:) = MATMUL(m%qp%Stif(1:3,1:3,idx_qp,nelem),tildeE) ! Stif is RR0 * p%Stif0_QP * RR0^T + mu(:,:) = MATMUL(C21,tildeE) + + m%qp%Oe(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Oe(1:3,4:6,idx_qp,nelem) = epsi(1:3,1:3) - SkewSymMat(m%qp%Fc(1:3,idx_qp,nelem)) + m%qp%Oe(4:6,4:6,idx_qp,nelem) = mu(1:3,1:3) - SkewSymMat(m%qp%Fc(4:6,idx_qp,nelem)) + + + !> ###Calculated \f$ \underline{\underline{\mathcal{P}}} \f$ from equation (20) + !! + !! \f$ \underline{\underline{\mathcal{P}}} = + !! \begin{bmatrix} + !! \underline{\underline{0}} & \underline{\underline{0}} \\ + !! \left(\underline{\underline{\bar{C}}}_{11} \tilde{E}_1 \right)^T + \tilde{F} + !! \left(\underline{\underline{\bar{C}}}_{11} \tilde{E}_1 \right)^T + !! \end{bmatrix} + !! = \begin{bmatrix} + !! \underline{\underline{0}} & \underline{\underline{0}} \\ + !! \psi_E^T + \tilde{F} & \mu^T + !! \end{bmatrix} \f$ + m%qp%Pe(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Pe(4:6,1:3,idx_qp,nelem) = TRANSPOSE(epsi) + SkewSymMat(m%qp%Fc(1:3,idx_qp,nelem)) + m%qp%Pe(4:6,4:6,idx_qp,nelem) = TRANSPOSE(mu) + + !> ###Calculated \f$ \underline{\underline{\mathcal{Q}}} \f$ from equation (21) + !! + !! \f{eqnarray*}{ + !! \underline{\underline{\mathcal{Q}}} + !! & =& \underline{\underline{\Upsilon}} \underline{\underline{\mathcal{O}}} + !! = \begin{bmatrix} 0 & 0 \\ + !! \tilde{E}_1^T & 0 \end{bmatrix} + !! \underline{\underline{\mathcal{O}}} \\ + !! \begin{bmatrix} 0 & 0 \\ + !! 0 & \underline{\underline{\mathcal{Q}}}_{22} \end{bmatrix} + !! & =& \tilde{E}_1^T \underline{\underline{\mathcal{O}}}_{12} + !! = - \tilde{E}_1 \underline{\underline{\mathcal{O}}}_{12} + !! \f}\n + !! Note: \f$ \tilde{E}_1^T = - \tilde{E}_1 \f$ + m%qp%Qe(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Qe(4:6,4:6,idx_qp,nelem) = -MATMUL(tildeE,m%qp%Oe(1:3,4:6,idx_qp,nelem)) + end do + + ENDIF + +contains + subroutine Calc_Fc_Fd() + REAL(BDKi) :: e1s + REAL(BDKi) :: eee(6) !< intermediate array for calculation Strain and curvature terms of Fc + REAL(BDKi) :: fff(6) !< intermediate array for calculation of the elastic force, Fc + !REAL(BDKi) :: Wrk(3) + + + !> ### Calculate the 1D strain, \f$ \underline{\epsilon} \f$, equation (5) + !! \f$ \underline{\epsilon} = \underline{x}^\prime_0 + \underline{u}^\prime - + !! \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \bar{\imath}_1 + !! = \underline{E}_1 - + !! \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \bar{\imath}_1 \f$ + !! where \f$ \bar{\imath}_1 \f$ is the unit vector along the \f$ x_1 \f$ direction in the inertial frame + !! (z in the IEC). The last term simplifies to the first column of \f$ \underline{\underline{R}}\underline{\underline{R}}_0 \f$ + !! + !! Note: \f$ \underline{\underline{R}}\underline{\underline{R}}_0 \f$ is used to go from the material basis into the inertial basis + !! and the transpose for the other direction. + eee(1:3) = m%qp%E1(1:3,idx_qp,nelem) - m%qp%RR0(1:3,3,idx_qp,nelem) ! Using RR0 z direction in IEC coords + + + !> ### Set the 1D sectional curvature, \f$ \underline{\kappa} \f$, equation (5) + !! \f$ \underline{\kappa} = \underline{k} + \underline{\underline{R}}\underline{k}_i \f$ + !! where \f$ \underline{k} = \text{axial}\left(\underline{\underline{R}}^\prime\underline{\underline{R}}^T \right) \f$ + !! and \f$ \underline{k}_i \f$ is the corresponding initial curvature vector (root reference). + !! Note that \f$ \underline{k} \f$ can be calculated with rotation parameters as + !! \f$ \underline{k} = \underline{\underline{H}}(\underline{p}) \underline{p}' \f$ + !! + !! \f$ \text{axial}\left( \underline{\underline{A}} \right) \f$ is defined as \n + !! \f$ \text{axial}\left( \underline{\underline{A}} \right) + !! = \left\{ \begin{array}{c} a_1 \\ + !! a_2 \\ + !! a_3 \end{array}\right\} + !! = \left\{ \begin{array}{c} A_{32} - A_{23} \\ + !! A_{13} - A_{31} \\ + !! A_{21} - A_{12} \end{array}\right\} + !! \f$ + !! In other words, \f$ \tilde{k} = \left(\underline{\underline{R}}^\prime\underline{\underline{R}}^T \right) \f$. + !! Note: \f$ \underline{\kappa} \f$ was already calculated in the BD_DisplacementQP routine + eee(4:6) = m%qp%kappa(1:3,idx_qp,nelem) + + + !FIXME: note that the k_i terms may not be documented correctly here. + !> ### Calculate the elastic force, \f$ \underline{\mathcal{F}}^C \f$ + !! Using equations (15), (23), (24), and (5) we write the elastic force as\n + !! \f$ + !! \underline{\mathcal{F}}^C + !! = \left\{ \begin{array}{c} \underline{F} \\ + !! \underline{M} \end{array} \right\} + !! = \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) + !! \underline{\underline{C}} + !! \left(\underline{\underline{R}}\underline{\underline{R}}_0\right)^T + !! \left\{ \begin{array}{c} \underline{\epsilon} \\ + !! \underline{\kappa} \end{array} \right\} + !! \f$ + !! + !! Note then that the extension twist term is added to this so that we get + !! \f$ \underline{\mathcal{F}}^C = \underline{F}^c_{a} + \underline{F}^c_{et} \f$ + !! + !! where \f$ \underline{F}^c_{et} \f$ is the extension twist coupling term. + + !> ###Calculate the first term. + !! \f$ \underline{F}^c_a + !! = \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) + !! \underline{\underline{C}} + !! \left(\underline{\underline{R}}\underline{\underline{R}}_0\right)^T + !! \left\{ \begin{array}{c} + !! \underline{\epsilon} \\ + !! \underline{k} + !! \end{array} \right\} \f$ + !! + fff(1:6) = MATMUL(m%qp%Stif(:,:,idx_qp,nelem),eee) + + + !> ###Calculate the extension twist coupling. + !! This is calculated in the material basis, not in the rotated reference frame \f$ \underline{F}^c_a \f$ was calculated in. + !! First find \f$ \epsilon_1 \f$ and \f$ \kappa_1 \f$ in the material basis\n + !! \f$ \epsilon_{m} = \left( \underline{\underline{R}}\underline{\underline{R}}_0 \right) ^T \epsilon \f$ \n + !! and \n + !! \f$ \kappa_{m} = \left( \underline{\underline{R}}\underline{\underline{R}}_0 \right) ^T \underline{k}\f$ \n + + ! Strain into the material basis (eq (39) of Dymore manual) + !Wrk(:) = MATMUL(TRANSPOSE(m%qp%RR0(:,:,idx_qp,nelem)),eee(1:3)) + !e1s = Wrk(3) !epsilon_{1} in material basis (for major axis of blade, which is z in the IEC formulation) + e1s = dot_product( m%qp%RR0(:,3,idx_qp,nelem), eee(1:3) ) + + !Wrk(:) = MATMUL(TRANSPOSE(m%qp%RR0(:,:,idx_qp,nelem)),eee(4:6)) + !k1s = Wrk(3) !kappa_{1} in material basis (for major axis of blade, which is z in the IEC formulation) + k1s = dot_product( m%qp%RR0(:,3,idx_qp,nelem), eee(4:6) ) + + + !> Add extension twist coupling terms to the \f$ \underline{F}^c_{a} \f$\n + !! \f$ \underline{F}^c = + !! \underline{F}^c_{a} + \underline{F}^c_{et} \f$\n + !! The extension twist term is calculated in the material basis, which can be simplified and rewritten as follows (_the details of this are fuzzy to me_):\n + !! \f$ \underline{F}^c_{et} = + !! \begin{bmatrix} + !! \frac{1}{2} C_{et} \kappa^2_{m}(1) \left(\underline{\underline{R}}\underline{\underline{R}}_0\right)_{:,1} \\ + !! C_{et} \kappa_{m}(1) \epsilon_{m}(1) \left(\underline{\underline{R}}\underline{\underline{R}}_0\right)_{:,1} + !! \end{bmatrix} + !! \f$ + !! + !! Where \f$ C_{et} = C_{5,5} + C_{6,6} \f$ is the inertial term along major axis, \f$x\f$, in the material coordinate system + !! Note that with coverting to the FAST / IEC coordinate system, we now are using the Ixx and Iyy terms which are located at + !! \f$ C_{et} = C_{4,4} + C_{5,5} \f$ + ! Refer Section 1.4 in "Dymore User's Manual - Formulation and finite element implementation of beam elements". + cet= p%Stif0_QP(4,4,(nelem-1)*p%nqp+idx_qp) + p%Stif0_QP(5,5,(nelem-1)*p%nqp+idx_qp) ! Dymore theory (22) + m%qp%Fc(1:3,idx_qp,nelem) = fff(1:3) + 0.5_BDKi*cet*k1s*k1s*m%qp%RR0(1:3,3,idx_qp,nelem) ! Dymore theory (25a). Note z-axis is the length of blade. + m%qp%Fc(4:6,idx_qp,nelem) = fff(4:6) + cet*e1s*k1s*m%qp%RR0(1:3,3,idx_qp,nelem) ! Dymore theory (25b). Note z-axis is the length of blade. + + !> ###Calculate \f$ \underline{\mathcal{F}}^d \f$, equation (16) + !! \f$ \underline{F}^d = + !! \underline{\underline{\Upsilon}} \underline{\mathcal{F}}^c + !! = \begin{bmatrix} \underline{\underline{0}} & \underline{\underline{0}} \\ + !! \tilde{E}_1^T & \underline{\underline{0}} \end{bmatrix} + !! \underline{\mathcal{F}}^c + !! = \begin{bmatrix} \underline{0} \\ + !! \left(\underline{\mathcal{F}}^c \times \underline{E}_1 \right)^T + !! \end{bmatrix} \f$ + m%qp%Fd(1:3,idx_qp,nelem) = 0.0_BDKi + ! ADP uu0 ref: If E1 is referenced against a different curve than Stif0_QP, there will be strange coupling terms here. + m%qp%Fd(4:6,idx_qp,nelem) = cross_product(m%qp%Fc(1:3,idx_qp,nelem), m%qp%E1(:,idx_qp,nelem)) + + end subroutine Calc_Fc_Fd +END SUBROUTINE BD_ElasticForce + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the mass quantities at the quadrature point +!! 1) velocity (vvv); 2) derivative of velocity wrt axis (vvp); 3) acceleration (aaa) +!! +!! These values are used in the calculations for inertial and dissipative forces. +! +! Input: x%dqdt p%Shp p%ShpDer +! Output: m%qp%vvv m%qp%vvp +! +SUBROUTINE BD_QPDataVelocity( p, x, m ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + INTEGER(IntKi) :: nelem !< index to current element + INTEGER(IntKi) :: idx_qp !< index to quadrature point + INTEGER(IntKi) :: idx_node !< index to the GLL node + INTEGER(IntKi) :: elem_start !< Starting quadrature point of current element + + DO nelem=1,p%elem_total + + elem_start = p%node_elem_idx(nelem,1) + + DO idx_qp=1,p%nqp + + !> Calculate the values for the + + ! Initialize to zero for summation + m%qp%vvv(:,idx_qp,nelem) = 0.0_BDKi + m%qp%vvp(:,idx_qp,nelem) = 0.0_BDKi + + ! Calculate the velocity term, velocity prime (derivative of velocity with respect to X-axis), and acceleration terms + DO idx_node=1,p%nodes_per_elem + m%qp%vvv(:,idx_qp,nelem) = m%qp%vvv(:,idx_qp,nelem) + p%Shp(idx_node,idx_qp) * x%dqdt(:,elem_start-1+idx_node) + m%qp%vvp(:,idx_qp,nelem) = m%qp%vvp(:,idx_qp,nelem) + p%ShpDer(idx_node,idx_qp)/p%Jacobian(idx_qp,nelem) * x%dqdt(:,elem_start-1+idx_node) + ENDDO + + ENDDO + + ENDDO + +END SUBROUTINE BD_QPDataVelocity + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the acceleration at the quadrature point +!! 1) acceleration (aaa) at time t+dt +!! +!! These values are used in the calculations for inertial and dissipative forces. +! +! Input: OtherState%acc p%Shp p%ShpDer +! Output: m%qp%aaa +! +!NOTE: This routine used to be part of BD_QPDataVelocity +SUBROUTINE BD_QPDataAcceleration( p, OtherState, m ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t on input; at t+dt on outputs + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + INTEGER(IntKi) :: nelem !< index of current element + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + INTEGER(IntKi) :: idx_node + INTEGER(IntKi) :: elem_start + + + + ! Initialize to zero for summation + m%qp%aaa = 0.0_BDKi + + ! Calculate the acceleration term at t+dt (OtherState%acc is at t+dt) + + DO nelem=1,p%elem_total + + elem_start = p%node_elem_idx(nelem,1) + + DO idx_qp=1,p%nqp + DO idx_node=1,p%nodes_per_elem + m%qp%aaa(:,idx_qp,nelem) = m%qp%aaa(:,idx_qp,nelem) + p%Shp(idx_node,idx_qp) * OtherState%acc(:,elem_start-1+idx_node) + END DO + END DO + + END DO + + +END SUBROUTINE BD_QPDataAcceleration + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the inertial force `m%qp%Fi` +!! It also calcuates the linearized matrices `m%qp%Mi`, `m%qp%Gi`, and `m%qp%Ki` for N-R algorithm +SUBROUTINE BD_InertialForce( nelem, p, m, fact ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< index of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables. + LOGICAL, INTENT(IN ) :: fact + + REAL(BDKi) :: beta(3) + REAL(BDKi) :: gama(3) + REAL(BDKi) :: nu(3) + REAL(BDKi) :: epsi(3,3) + REAL(BDKi) :: mu(3,3) + + REAL(BDKi) :: SSmat_vvv(3,3) + REAL(BDKi) :: SSmat_RR0mEta(3,3) + + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + + ! Note, in the following there are cases where SkewSymMat(A)*SkewSymMat(B)*C has been reduced to + ! cross_product(A, cross_product(B, C)). This is correct because SkewSymMat(B)*C = cross_product(B, C) + ! but SkewSymMat(A)*SkewSymMat(B) does not give a vector so the cross products cannot be switched. + ! Note that in the matrix multiplication (A*B)*C = A*(B*C) + + ! Note that F_i is calculated in the inertial frame, not the rotating frame. + ! Note that RR0*mEta is the rotation at the current node times the (m*cm_x,m*cm_y,0) of the blade section at qp. + ! So, the omega terms are therefore correction terms? + do idx_qp=1,p%nqp + beta = cross_product(m%qp%vvv(4:6,idx_qp,nelem), m%qp%RR0mEta(:,idx_qp,nelem)) !MATMUL(SkewSymMat(ome),mEta) + gama = MATMUL(m%qp%rho(:,:,idx_qp,nelem),m%qp%vvv(4:6,idx_qp,nelem)) + nu = MATMUL(m%qp%rho(:,:,idx_qp,nelem),m%qp%aaa(4:6,idx_qp,nelem)) + + !Compute Fi (Equation 22 in Wang_2014, Equation 17.110 in Bauchau's book) + m%qp%Fi(1:3,idx_qp,nelem) = p%qp%mmm(idx_qp,nelem)*m%qp%aaa(1:3,idx_qp,nelem) & + + cross_product(m%qp%aaa(4:6,idx_qp,nelem), m%qp%RR0mEta(:,idx_qp,nelem)) & + + cross_product(m%qp%vvv(4:6,idx_qp,nelem), beta) ! MATMUL(SkewSymMat(aaa(4:6)),mEta)+MATMUL(SkewSymMat(ome),beta) + m%qp%Fi(4:6,idx_qp,nelem) = cross_product(m%qp%RR0mEta(:,idx_qp,nelem), m%qp%aaa(1:3,idx_qp,nelem)) + nu + cross_product(m%qp%vvv(4:6,idx_qp,nelem), gama) ! MATMUL(SkewSymMat(mEta),aaa(1:3)) + nu + MATMUL(SkewSymMat(ome),gama) + end do + + IF(fact) THEN + CALL BD_InertialMassMatrix( nelem, p, m ) ! compute Mi + do idx_qp=1,p%nqp + + !Gyroscopic Matrix (Equation 17 in Wang_2014) + m%qp%Gi(:,1:3,idx_qp,nelem) = 0.0_BDKi + SSmat_vvv = SkewSymMat(m%qp%vvv(4:6,idx_qp,nelem)) + SSmat_RR0mEta = SkewSymMat(m%qp%RR0mEta(:,idx_qp,nelem)) + + epsi = MATMUL(SSmat_vvv,m%qp%rho(:,:,idx_qp,nelem)) + mu = -MATMUL(SSmat_vvv,SSmat_RR0mEta) + nu = MATMUL(m%qp%rho(:,:,idx_qp,nelem),m%qp%aaa(4:6,idx_qp,nelem)) + beta = cross_product(m%qp%vvv(4:6,idx_qp,nelem), m%qp%RR0mEta(:,idx_qp,nelem)) !MATMUL(SkewSymMat(ome),mEta) + gama = MATMUL(m%qp%rho(:,:,idx_qp,nelem),m%qp%vvv(4:6,idx_qp,nelem)) + m%qp%Gi(1:3,4:6,idx_qp,nelem) = -SkewSymMat(beta) + mu + m%qp%Gi(4:6,4:6,idx_qp,nelem) = epsi - SkewSymMat(gama) + + !Stiffness Matrix (Equation 18 in Wang_2014) + m%qp%Ki( : ,1:3,idx_qp,nelem) = 0.0_BDKi + m%qp%Ki(1:3,4:6,idx_qp,nelem) = -MATMUL(SkewSymMat(m%qp%aaa(4:6,idx_qp,nelem)),SSmat_RR0mEta) & + + MATMUL(SSmat_vvv,mu) + m%qp%Ki(4:6,4:6,idx_qp,nelem) = MATMUL(SkewSymMat(m%qp%aaa(1:3,idx_qp,nelem)),SSmat_RR0mEta) & + + MATMUL(m%qp%rho(:,:,idx_qp,nelem),SkewSymMat(m%qp%aaa(4:6,idx_qp,nelem))) & + - SkewSymMat(nu) & + + MATMUL(epsi,SSmat_vvv) & + - MATMUL(SSmat_vvv,SkewSymMat(gama)) + end do + ENDIF + +END SUBROUTINE BD_InertialForce + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the dissipative forces and added it to Fc and Fd +!! It also calcuates the linearized matrices Sd, Od, Pd and Qd +!! betaC, Gd, Xd, Yd for N-R algorithm +SUBROUTINE BD_DissipativeForce( nelem, p, m,fact ) + INTEGER(IntKi), INTENT(IN ) :: nelem !< index of current element in loop + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + LOGICAL, INTENT(IN ) :: fact + + REAL(BDKi) :: SS_ome(3,3) + REAL(BDKi) :: ffd(6) + REAL(BDKi) :: D11(3,3) + REAL(BDKi) :: D12(3,3) + REAL(BDKi) :: D21(3,3) + REAL(BDKi) :: D22(3,3) + REAL(BDKi) :: b11(3,3) + REAL(BDKi) :: b12(3,3) + REAL(BDKi) :: alpha(3,3) + + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + + + IF (.NOT. fact) then ! skip all but Fc and Fd terms + + DO idx_qp=1,p%nqp + call Calc_FC_FD_ffd() ! this modifies m%qp%Fc and m%qp%Fd + END DO + + ! bjj: we don't use these values when fact is FALSE, so let's save time and ignore them here, too. + ! m%qp%Sd(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Pd(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Od(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Qd(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Gd(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Xd(:,:,:,nelem) = 0.0_BDKi + ! m%qp%Yd(:,:,:,nelem) = 0.0_BDKi + + ELSE +!FIXME: sometime we can condense this with vector arithmetic and removing some variables that aren't needed. + + DO idx_qp=1,p%nqp + + CALL Calc_FC_FD_ffd() ! this sets local variable ffd and modifies m%qp%Fc and m%qp%Fd + + D11 = m%qp%betaC(1:3,1:3,idx_qp,nelem) + D12 = m%qp%betaC(1:3,4:6,idx_qp,nelem) + D21 = m%qp%betaC(4:6,1:3,idx_qp,nelem) + D22 = m%qp%betaC(4:6,4:6,idx_qp,nelem) + + b11(1:3,1:3) = -MATMUL(SkewSymMat(m%qp%E1(:,idx_qp,nelem)),D11) + b12(1:3,1:3) = -MATMUL(SkewSymMat(m%qp%E1(:,idx_qp,nelem)),D12) + + SS_ome = SkewSymMat( m%qp%vvv(4:6,idx_qp,nelem) ) + + ! Compute stiffness matrix Sd + m%qp%Sd(1:3,1:3,idx_qp,nelem) = -MATMUL(D11,SS_ome) + m%qp%Sd(1:3,4:6,idx_qp,nelem) = -MATMUL(D12,SS_ome) + m%qp%Sd(4:6,1:3,idx_qp,nelem) = -MATMUL(D21,SS_ome) + m%qp%Sd(4:6,4:6,idx_qp,nelem) = -MATMUL(D22,SS_ome) + + ! Compute stiffness matrix Pd + m%qp%Pd(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Pd(4:6,1:3,idx_qp,nelem) = SkewSymMat(ffd(1:3)) - MATMUL(b11,SS_ome) + m%qp%Pd(4:6,4:6,idx_qp,nelem) = -MATMUL(b12,SS_ome) + + ! Compute stiffness matrix Od + m%qp%Od(:,1:3,idx_qp,nelem) = 0.0_BDKi + alpha = SkewSymMat(m%qp%vvp(1:3,idx_qp,nelem)) - MATMUL(SS_ome,SkewSymMat(m%qp%E1(:,idx_qp,nelem))) + m%qp%Od(1:3,4:6,idx_qp,nelem) = MATMUL(D11,alpha) - SkewSymMat(ffd(1:3)) + m%qp%Od(4:6,4:6,idx_qp,nelem) = MATMUL(D21,alpha) - SkewSymMat(ffd(4:6)) + + ! Compute stiffness matrix Qd + m%qp%Qd(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Qd(4:6,4:6,idx_qp,nelem) = -MATMUL(SkewSymMat(m%qp%E1(:,idx_qp,nelem)),m%qp%Od(1:3,4:6,idx_qp,nelem)) + ! Compute gyroscopic matrix Gd + m%qp%Gd(:,1:3,idx_qp,nelem) = 0.0_BDKi + m%qp%Gd(1:3,4:6,idx_qp,nelem) = TRANSPOSE(b11) + m%qp%Gd(4:6,4:6,idx_qp,nelem) = TRANSPOSE(b12) + + ! Compute gyroscopic matrix Xd + m%qp%Xd(:,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Xd(4:6,4:6,idx_qp,nelem) = -MATMUL(SkewSymMat(m%qp%E1(:,idx_qp,nelem)),m%qp%Gd(1:3,4:6,idx_qp,nelem)) + + ! Compute gyroscopic matrix Yd + m%qp%Yd(1:3,:,idx_qp,nelem) = 0.0_BDKi + m%qp%Yd(4:6,1:3,idx_qp,nelem) = b11 + m%qp%Yd(4:6,4:6,idx_qp,nelem) = b12 + END DO + ENDIF + +CONTAINS + SUBROUTINE Calc_FC_FD_ffd() + REAL(BDKi) :: eed(6) + + ! Compute strain rates + eed = m%qp%vvp(1:6,idx_qp,nelem) + eed(1:3) = eed(1:3) + cross_product(m%qp%E1(:,idx_qp,nelem),m%qp%vvv(4:6,idx_qp,nelem)) + + ! Compute dissipative force + ffd(1:6) = MATMUL(m%qp%betaC(:,:,idx_qp,nelem),eed) + + m%qp%Fc(1:6,idx_qp,nelem) = m%qp%Fc(1:6,idx_qp,nelem) + ffd + m%qp%Fd(4:6,idx_qp,nelem) = m%qp%Fd(4:6,idx_qp,nelem) + cross_product(ffd(1:3),m%qp%E1(:,idx_qp,nelem)) + + END SUBROUTINE Calc_FC_FD_ffd +END SUBROUTINE BD_DissipativeForce + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the gravity forces `m%qp%Fg` +SUBROUTINE BD_GravityForce( nelem,p,m,grav ) + INTEGER(IntKi), INTENT(IN ) :: nelem !< index of current element in loop + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables. + REAL(BDKi), INTENT(IN ) :: grav(:) !< Gravity, which is scaled in the case of Static analysis + + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + + do idx_qp=1,p%nqp + + m%qp%Fg(1:3,idx_qp,nelem) = p%qp%mmm(idx_qp,nelem) * grav(1:3) + m%qp%Fg(4:6,idx_qp,nelem) = cross_product(m%qp%RR0mEta(:,idx_qp,nelem),grav) + + end do + +END SUBROUTINE BD_GravityForce + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine assembles total stiffness matrix. +SUBROUTINE BD_AssembleStiffK(nelem,p,ElemK,GlobalK) + INTEGER(IntKi), INTENT(IN ) :: nelem !< Number of elements + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(BDKi), INTENT(IN ) :: ElemK(:,:,:,:) !< Element matrix + REAL(BDKi), INTENT(INOUT) :: GlobalK(:,:,:,:) !< Global stiffness matrix + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: idx_dof2 + INTEGER(IntKi) :: temp_id + + temp_id = p%node_elem_idx(nelem,1)-1 ! Node just before the start of this element + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + GlobalK( :,i+temp_id,idx_dof2,j+temp_id ) = GlobalK( :,i+temp_id,idx_dof2,j+temp_id ) + ElemK( :,i,idx_dof2,j ) + ENDDO + ENDDO + ENDDO + +END SUBROUTINE BD_AssembleStiffK + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine assembles global force vector. +SUBROUTINE BD_AssembleRHS(nelem,p,ElemRHS,GlobalRHS) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< Number of elements + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(BDKi), INTENT(IN ) :: ElemRHS(:,:) !< Total element force (Fc, Fd, Fb) (size = p%dofnode x p%nodes_per_elem) + REAL(BDKi), INTENT(INOUT) :: GlobalRHS(:,:) !< Global force vector (size = p%dofnode x p%nodes_per_elem) + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: temp_id + +! GlobalRHS --> p%dof_total = p%node_total * p%dof_node = [p%elem_total*(p%nodes_per_elem-1) + 1] * p%dof_node +! ElemRHS --> p%dof_elem = = p%nodes_per_elem * p%dof_node +! +! Will need to redimension GlobalRHS to p%dof_node,p%node_total + + temp_id = p%node_elem_idx(nelem,1)-1 ! Node just before the start of this element + DO i=1,p%nodes_per_elem + GlobalRHS(:,i+temp_id) = GlobalRHS(:,i+temp_id)+ElemRHS(:,i) + ENDDO + +END SUBROUTINE BD_AssembleRHS + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine total element forces and mass matrices +!FIXME: note similarities with BD_ElementMatrixGA2 +SUBROUTINE BD_ElementMatrixAcc( nelem, p, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ElementMatrixAcc' + + + CALL BD_ElasticForce( nelem, p, m, .FALSE. ) ! Calculate Fc, Fd only + IF(p%damp_flag .NE. 0) THEN + CALL BD_DissipativeForce( nelem, p, m, .FALSE. ) ! Calculate dissipative terms on Fc, Fd + ENDIF + CALL BD_GravityForce( nelem, p, m, p%gravity ) ! Calculate Fg + CALL BD_GyroForce( nelem, p, m ) ! Calculate Fb (velocity terms from InertialForce with aaa=0) + + CALL BD_InertialMassMatrix( nelem, p, m ) ! Calculate Mi + + CALL Integrate_ElementMass(nelem, p, m) ! use m%qp%Mi to compute m%elm + + m%qp%Ftemp(:,:,nelem) = m%qp%Fd(:,:,nelem) + m%qp%Fb(:,:,nelem) - m%qp%Fg(:,:,nelem) - m%DistrLoad_QP(:,:,nelem) + CALL Integrate_ElementForce(nelem, p, m) ! use m%qp%Fc and m%qp%Ftemp to compute m%elf + + RETURN +END SUBROUTINE BD_ElementMatrixAcc + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the mass matrix. +!! Returns value for `m%qp%Mi` +! used in BD_ElementMatrixAcc and BD_InertialForce +SUBROUTINE BD_InertialMassMatrix( nelem, p, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< index of current element in loop + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + + do idx_qp=1,p%nqp + + m%qp%Mi(:,:,idx_qp,nelem) = 0.0_BDKi + + ! Set diagonal values for mass + DO i=1,3 + m%qp%Mi(i,i,idx_qp,nelem) = p%qp%mmm(idx_qp,nelem) + ENDDO + + ! set mass-inertia coupling terms + m%qp%Mi(1:3,4:6,idx_qp,nelem) = -SkewSymMat(m%qp%RR0mEta(:,idx_qp,nelem)) + m%qp%Mi(4:6,1:3,idx_qp,nelem) = SkewSymMat(m%qp%RR0mEta(:,idx_qp,nelem)) + + ! Set inertia terms + m%qp%Mi(4:6,4:6,idx_qp,nelem) = m%qp%rho(:,:,idx_qp,nelem) + + end do + + +END SUBROUTINE BD_InertialMassMatrix + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes gyroscopic forces +!! Returns new value for `m%qp%Fb` Note that the equations here are the inertial equations with the acceleration terms set to zero. +! called by BD_ElementMatrixAcc and BD_ElementMatrixForce +SUBROUTINE BD_GyroForce( nelem, p, m ) + INTEGER(IntKi), INTENT(IN ) :: nelem !< index of current element in loop + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + + REAL(BDKi) :: beta(3) + REAL(BDKi) :: gama(3) + INTEGER(IntKi) :: idx_qp !< index of current quadrature point + + m%qp%Fb(:,:,nelem) = 0.0_BDKi + + do idx_qp=1,p%nqp + + beta = cross_product(m%qp%vvv(4:6,idx_qp,nelem), m%qp%RR0mEta(:,idx_qp,nelem)) !MATMUL(SkewSymMat(ome),mEta) + gama = MATMUL(m%qp%rho(:,:,idx_qp,nelem),m%qp%vvv(4:6,idx_qp,nelem)) + + !Compute Fb (Equation 22 in Wang_2014 with aaa = 0) + m%qp%Fb(1:3,idx_qp,nelem) = cross_product(m%qp%vvv(4:6,idx_qp,nelem), beta) + m%qp%Fb(4:6,idx_qp,nelem) = cross_product(m%qp%vvv(4:6,idx_qp,nelem), gama) + + end do + +END SUBROUTINE BD_GyroForce + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the member length ratio w.r.t. length of a beam. +!! It also computes the total length. +!! Member: FE element +SUBROUTINE BD_MemberEta(member_total, QPtW, Jac, member_eta, total_length) + + INTEGER(IntKi),INTENT(IN ):: member_total !< number of total members that make up the beam, InputFileData%member_total from BD input file + REAL(BDKi), INTENT(IN ):: QPtW(:) !< quadrature point weights + REAL(BDKi), INTENT(IN ):: Jac(:,:) !< Jacobian value at each quadrature point + REAL(BDKi), INTENT( OUT):: member_eta(:) !< ratio of member length to beam length - computed based on FE quadrature + REAL(BDKi), INTENT( OUT):: total_length !< total length of the beam - computed based on FE quadrature + + REAL(BDKi) :: member_length(member_total) ! member length using FE quadrature + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + + total_length = 0.0_BDKi ! initialize to zero + member_length = 0.0_BDKi ! initialize to zero + member_eta = 0.0_BDKi ! initialize to zero + + ! total beam length + DO i=1,member_total ! mas: why not call these elements? + DO j=1,size(Jac,1) ! loop over number of quadrature points + member_length(i) = member_length(i) + QPtW(j)*Jac(j,i) + ENDDO + total_length = total_length + member_length(i) + ENDDO + + ! ratio of member's length to the total beam length + member_eta = member_length/total_length + +END SUBROUTINE BD_MemberEta +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_Static(t,u,utimes,p,x,OtherState,m,ErrStat,ErrMsg) + + REAL(DbKi), INTENT(IN ):: t !< Current simulation time in seconds + REAL(DbKi), INTENT(IN ):: utimes(:) !< times of input + TYPE(BD_ParameterType), INTENT(IN ):: p !< Parameters + TYPE(BD_OtherStateType), INTENT(INOUT):: OtherState !< Other states at t + TYPE(BD_MiscVarType), INTENT(INOUT):: m !< misc/optimization variables + TYPE(BD_ContinuousStateType), INTENT(INOUT):: x !< Continuous states at t on input at t + dt on output + TYPE(BD_InputType), INTENT(INOUT):: u(:) !< Inputs at t + INTEGER(IntKi), INTENT( OUT):: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT):: ErrMsg !< Error message if ErrStat /= ErrID_None + + TYPE(BD_InputType) :: u_interp ! temporary copy of inputs, transferred to BD local system + REAL(BDKi) :: ScaleFactor ! Factor for scaling applied loads at each step + INTEGER(IntKi) :: j ! Generic counters + INTEGER(IntKi) :: piter + REAL(BDKi) :: gravity_temp(3) + REAL(BDKi) :: load_works + REAL(BDKi) :: load_works_not + REAL(BDKi) :: load_test + TYPE(BD_ContinuousStateType) :: x_works + LOGICAL :: solved + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + INTEGER(IntKi) :: ErrStat3 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg3 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Static' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Create a copy, so we can reset when things don't converge. + CALL BD_CopyContState(x, x_works, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Get u_interp at t (call to extrapinterp in case driver sets u(:) or utimes(:) differently, though in the static case, the inputs shouldn't be changing) + call BD_CopyInput(u(1),u_interp,MESH_NEWCOPY,ErrStat2,ErrMsg2) ! allocate space if necessary + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + call BD_Input_extrapinterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) ! make sure u_interp holds values at t + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + + ! Transform quantities from global frame to local (blade in BD coords) frame + CALL BD_InputGlobalLocal(p,u_interp) + + + ! Incorporate boundary conditions + CALL BD_BoundaryGA2(x,p,u_interp,OtherState, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! new logic + ! (1) try first with full load (load_reduce = 1) + ! (2) if that does not work, keep reducing until finding converged solution or reach + ! maximum number of iterations; if found save as x_works + ! (3) keep bisecting the load looking using lsat successful iteration (x_works) + + solved = .false. + load_works = 0.0_BDKi + load_test = 1.0_BDKi + load_works_not = 1.0_BDKi + + ! x_works = x ! save initial guess (done above) + + DO j=1,p%ld_retries + + CALL BD_DistrLoadCopy( p, u_interp, m, load_test ) ! move the input loads from u_interp into misc vars + gravity_temp(:) = p%gravity(:)*load_test + + CALL BD_StaticSolution(x, gravity_temp, p, m, piter, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) ! concerned about error reporting + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! note that if BD_StaticSolution converges, then piter will .le. p%niter + + ! bjj: note that this is not necessarially sufficient: if an error occurred in the loop inside BD_StaticSolution + ! and it exited early, this condition would also hold. Care must be taken inside BD_StaticSolution so that doesn't + ! happen if this convergence condition is used. + + if (piter .le. p%niter) then + + ! save this successfully converged value + !x_works = x + CALL BD_CopyContState(x, x_works, MESH_UPDATECOPY, ErrStat3, ErrMsg3) + + + if ( EqualRealNos(load_test,1.0_BDKi) ) then + solved = .true. + EXIT + else + load_works = load_test + ! if we found a convergent load, try full load next + load_test = 1.0_BDKi + endif + + else + + ! last try did not converge -- save that load value as load_works_not + load_works_not = load_test + + ! Take average of the works and works_not values for next test + load_test = 0.5_BDKi * (load_works + load_works_not) + + ! reset best guess + !x = x_works + CALL BD_CopyContState(x_works, x, MESH_UPDATECOPY, ErrStat3, ErrMsg3) + + + endif + + ! test halfway point between load_works and full load + + ENDDO + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + + IF( .not. solved) then + call SetErrStat( ErrID_Fatal, "Solution does not converge after the maximum number of load steps.", & + ErrStat,ErrMsg, RoutineName) + CALL WrScr( NewLine//"Maxium number of load steps reached. Exit BeamDyn") + ENDIF + + call cleanup() + return + +CONTAINS + SUBROUTINE Cleanup() + CALL BD_DestroyInput(u_interp, ErrStat2, ErrMsg2 ) + CALL BD_DestroyContState(x_works, ErrStat2, ErrMsg2 ) + END SUBROUTINE Cleanup +END SUBROUTINE BD_Static + +!----------------------------------------------------------------------------------------------------------------------------------- + +SUBROUTINE BD_StaticSolution( x, gravity, p, m, piter, ErrStat, ErrMsg ) + + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + REAL(BDKi), INTENT(IN ) :: gravity(:) !< not the same as p%gravity (used for ramp of loads and gravity) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi), INTENT( OUT) :: piter + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(BDKi) :: Eref + REAL(BDKi) :: Enorm + + INTEGER(IntKi) :: j + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_StaticSolution' + + ErrStat = ErrID_None + ErrMsg = "" + + Eref = 0.0_BDKi + DO piter=1,p%niter + + ! compute the finite differenced stiffness matrix + IF ( p%tngt_stf_fd .or. p%tngt_stf_comp ) CALL BD_FD_Stat( x, gravity, p, m ) + + CALL BD_QuadraturePointData( p,x,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + CALL BD_GenerateStaticElement(gravity, p, m) ! Calculate RHS and analytical tangent stiffness matrix + + ! compare the finite differenced stiffness matrix against the analytical tangent stiffness matrix is flag is set + IF ( p%tngt_stf_comp ) CALL BD_CompTngtStiff( RESHAPE(m%StifK ,(/p%dof_total,p%dof_total/)), & + RESHAPE(m%StifK_fd,(/p%dof_total,p%dof_total/)), p%tngt_stf_difftol, & + ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) return + + + ! Point loads are on the GLL points. + DO j=1,p%node_total + m%RHS(1:6,j) = m%RHS(1:6,j) + m%PointLoadLcl(1:6,j) + ENDDO + + ! Reshape for the use with the LAPACK solver + m%LP_RHS = RESHAPE(m%RHS, (/p%dof_total/)) + m%LP_RHS_LU = m%LP_RHS(7:p%dof_total) + + ! Set tangnet stiffness matrix based on flag for finite differencing + IF ( p%tngt_stf_fd ) THEN + m%LP_StifK = RESHAPE(m%StifK_fd, (/p%dof_total,p%dof_total/)); + ELSE + m%LP_StifK = RESHAPE( m%StifK, (/p%dof_total,p%dof_total/)); + ENDIF + m%LP_StifK_LU = m%LP_StifK(7:p%dof_total,7:p%dof_total) + + ! Solve for X in A*X=B to get the displacement of blade under static load. + CALL LAPACK_getrf( p%dof_total-p%dof_node, p%dof_total-p%dof_node, m%LP_StifK_LU, m%LP_indx, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! if there is a problem with the factorization, we should not continue with this iteration + if (ErrStat >= AbortErrLev) RETURN + + CALL LAPACK_getrs( 'N',p%dof_total-p%dof_node, m%LP_StifK_LU, m%LP_indx, m%LP_RHS_LU, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! if there is a problem with the solve, we should not continue with this iteration + if (ErrStat >= AbortErrLev) RETURN + + ! Reshape to BeamDyn arrays + m%Solution(:,1) = 0.0_BDKi ! first node is not set below + m%Solution(:,2:p%node_total) = RESHAPE( m%LP_RHS_LU, (/ p%dof_node, (p%node_total - 1) /) ) + + CALL BD_StaticUpdateConfiguration(p,m,x) + + ! Set the first node reaction force / moment + m%FirstNodeReactionLclForceMoment(1:6) = m%RHS(1:6,1) + + Enorm = abs(DOT_PRODUCT(m%LP_RHS_LU, m%LP_RHS(7:p%dof_total))) ! compute the energy of the current system (note - not a norm!) + + ! Check if solution has converged. + IF(piter .EQ. 1) THEN + Eref = Enorm + IF(Eref .LE. p%tol) RETURN + ELSE + IF(Enorm/Eref .LE. p%tol) RETURN + ENDIF + + ENDDO + +END SUBROUTINE BD_StaticSolution + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the finite differenced tangent stiffness matrix +SUBROUTINE BD_FD_Stat( x, gravity, p, m ) + + ! Function arguments + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + REAL(BDKi), INTENT(IN ) :: gravity(:) !< not the same as p%gravity (used for ramp of loads and gravity) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + ! local variables + INTEGER(IntKi) :: i + INTEGER(IntKi) :: idx_dof + CHARACTER(*), PARAMETER :: RoutineName = 'BD_FD_Stat' + + ! zero out the local matrices. + m%RHS_m = 0.0_BDKi + m%RHS_p = 0.0_BDKi + m%StifK_fd = 0.0_BDKi + + ! perform a central finite difference to obtain + DO i=1,p%nodes_per_elem + DO idx_dof=1,p%dof_node + + ! Perturb in the negative direction + x%q(idx_dof,i) = x%q(idx_dof,i) - p%tngt_stf_pert + + ! Evaluate governing equations for current solution vector + CALL BD_QuadraturePointData(p,x,m) + CALL BD_GenerateStaticElement(gravity,p,m) + + ! Account for externally applied point loads + m%RHS_m(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! Perturb in the positive direction + x%q(idx_dof,i) = x%q(idx_dof,i) + 2*p%tngt_stf_pert + + ! Evaluate governing equations for current solution vector + CALL BD_QuadraturePointData(p,x,m) + CALL BD_GenerateStaticElement(gravity,p,m) + + ! Account for externally applied point loads + m%RHS_p(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! The negative sign is because we are finite differencing + ! f_ext - f_int instead of just f_int + m%StifK_fd(:,:,idx_dof,i) = -(m%RHS_p - m%RHS_m)/(2*p%tngt_stf_pert) + + ! Reset the solution vector entry to unperturbed state + x%q(idx_dof,i) = x%q(idx_dof,i) - p%tngt_stf_pert + + ENDDO + ENDDO + +END SUBROUTINE BD_FD_Stat + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine updates the static configuration +!! given incremental value calculated by the +!! Newton-Raphson algorithm +SUBROUTINE BD_StaticUpdateConfiguration(p,m,x) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(IN ) :: m !< misc/optimization variables + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + + REAL(BDKi) :: rotf_temp(3) + REAL(BDKi) :: roti_temp(3) + REAL(BDKi) :: rot_temp(3) + INTEGER(IntKi) :: i + CHARACTER(*), PARAMETER :: RoutineName = 'BD_StaticUpdateConfiguration' + + ! Root node is known, so do not calculate it. + DO i=2, p%node_total + + ! Calculate new position + x%q(1:3,i) = x%q(1:3,i) + m%Solution(1:3,i) + + ! Calculate the new rotation. Combine the original rotation parameters, x%q(4:6,:), + ! with the rotation displacement parameters, m%Solution(4:6,i). Note that the result must + ! be composed from the two sets of rotation parameters + rotf_temp(:) = x%q(4:6,i) + roti_temp(:) = m%Solution(4:6,i) + CALL BD_CrvCompose(rot_temp,roti_temp,rotf_temp,FLAG_R1R2) ! R(rot_temp) = R(roti_temp) R(rotf_temp) + x%q(4:6,i) = rot_temp(:) + + ENDDO + +END SUBROUTINE BD_StaticUpdateConfiguration + + +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_GenerateStaticElement( gravity, p, m ) + + REAL(BDKi), INTENT(IN ):: gravity(:) + TYPE(BD_ParameterType),INTENT(IN ):: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT):: m !< misc/optimization variables + + INTEGER(IntKi) :: nelem + CHARACTER(*), PARAMETER :: RoutineName = 'BD_GenerateStaticElement' + + + ! must initialize these because BD_AssembleStiffK and BD_AssembleRHS are INOUT + m%RHS = 0.0_BDKi + m%StifK = 0.0_BDKi + + ! These values have not been set yet for the QP + CALL BD_QPData_mEta_rho( p,m ) ! Calculate the \f$ m \eta \f$ and \f$ \rho \f$ terms + + DO nelem=1,p%elem_total + + CALL BD_StaticElementMatrix( nelem, gravity, p, m ) + CALL BD_AssembleStiffK(nelem,p,m%elk,m%StifK) + CALL BD_AssembleRHS(nelem,p,m%elf,m%RHS) + + ENDDO + + RETURN +END SUBROUTINE BD_GenerateStaticElement + + +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_StaticElementMatrix( nelem, gravity, p, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< current element number + REAL(BDKi), INTENT(IN ) :: gravity(:) !< gravity vector + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: idx_dof1, idx_dof2 + INTEGER(IntKi) :: idx_qp + CHARACTER(*), PARAMETER :: RoutineName = 'BD_StaticElementMatrix' + + + CALL BD_ElasticForce( nelem,p,m,.true. ) ! Calculate Fc, Fd [and Oe, Pe, and Qe for N-R algorithm] + CALL BD_GravityForce( nelem,p,m,gravity ) ! Calculate Fg + + + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + m%elk(idx_dof1,i,idx_dof2,j) = 0.0_BDKi + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Qe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac( :,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Qe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Pe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,i,j) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Pe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,i,j) + END DO + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Oe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,j,i) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Oe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,j,i) + END DO + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Stif(idx_dof1,idx_dof2,:,nelem), p%QPtw_ShpDer_ShpDer_Jac(:,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Stif(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) + END DO + ENDDO + ENDDO + ENDDO + ENDDO + + m%qp%Ftemp(:,:,nelem) = m%qp%Fd(:,:,nelem) - m%qp%Fg(:,:,nelem) - m%DistrLoad_QP(:,:,nelem) + call Integrate_ElementForce(nelem, p, m) ! use m%qp%Fc and m%qp%Ftemp to compute m%elf + + RETURN + +END SUBROUTINE BD_StaticElementMatrix + + +!> This routine computes m%elf from the parameters (shape functions, derivatives) as well as m%qp%Fc and m%qp%Ftemp +SUBROUTINE Integrate_ElementForce(nelem, p, m) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + INTEGER(IntKi) :: idx_qp + INTEGER(IntKi) :: i + INTEGER(IntKi) :: idx_dof1 + CHARACTER(*), PARAMETER :: RoutineName = 'Integrate_ElementForce' + + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + m%elf(idx_dof1,i) = 0.0_BDKi + + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Fc (idx_dof1,:,nelem), p%QPtw_ShpDer( :,i)) + m%elf(idx_dof1,i) = m%elf(idx_dof1,i) - m%qp%Fc (idx_dof1,idx_qp,nelem)*p%QPtw_ShpDer(idx_qp,i) + END DO + + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Ftemp(idx_dof1,:,nelem), p%QPtw_Shp_Jac(:,i,nelem) ) + m%elf(idx_dof1,i) = m%elf(idx_dof1,i) - m%qp%Ftemp(idx_dof1,idx_qp,nelem)*p%QPtw_Shp_Jac(idx_qp,i,nelem) + END DO + + ENDDO + ENDDO + +END SUBROUTINE Integrate_ElementForce +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes m%elm from the parameters (shape functions, derivatives) as well as m%qp%Mi +SUBROUTINE Integrate_ElementMass(nelem, p, m) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< number of current element + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + + INTEGER(IntKi) :: idx_qp + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: idx_dof1, idx_dof2 + CHARACTER(*), PARAMETER :: RoutineName = 'Integrate_ElementMass' + + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + m%elm(idx_dof1,i,idx_dof2,j) = 0.0_BDKi + + DO idx_qp = 1,p%nqp + m%elm(idx_dof1,i,idx_dof2,j) = m%elm(idx_dof1,i,idx_dof2,j) + m%qp%Mi(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + + END DO + END DO + + END DO + END DO + + +END SUBROUTINE Integrate_ElementMass + + +!----------------------------------------------------------------------------------------------------------------------------------- +! The next set of routines are for finding the quasi-static solution where a set of accelerations and rotational velocities are +! known. This can be used to set the initial blade distortion at T=0 to avoid some of the startup transients. +! NOTE: This is not an energy conserving calculation!!!! +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_QuasiStatic(u,p,x,OtherState,m,ErrStat,ErrMsg, RampLoad) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at t (in FAST global coords) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL, INTENT(IN ) :: RampLoad !< Whether or not to ramp load + + TYPE(BD_InputType) :: u_temp ! a temporary variable that holds inputs in BD local system + TYPE(BD_ContinuousStateType) :: x_temp ! a temporary variable that holds initial state (in case the quasi-static solution doesn't work) + LOGICAL :: isConverged ! If solution converged + REAL(BDKi) :: ScaleFactor ! Factor for scaling applied loads at each step + INTEGER(IntKi) :: piter ! Iteration count of the QuasiStaticSolution + INTEGER(IntKi) :: j ! Generic counters + INTEGER(IntKi) :: LoadSteps ! Current load step + INTEGER(IntKi) :: MaxLoadSteps ! Maximum number of loadsteps we can take + LOGICAL :: ConvergeWarn ! Warning issued if more than Newton_Raphson_Iteration_Limit NR iterations required for convergence + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuasiStatic' + + ErrStat = ErrID_None + ErrMsg = "" + ConvergeWarn = .FALSE. + + + ! allocate space for input type (mainly for meshes) + CALL BD_CopyInput(u,u_temp,MESH_NEWCOPY,ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + + CALL BD_CopyContState(x,x_temp,MESH_NEWCOPY,ErrStat2,ErrMsg2) ! copy in case we can't find a solution here. + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! Transform quantities from global frame to local (blade in BD coords) frame + CALL BD_InputGlobalLocal(p,u_temp) + + ! Incorporate boundary conditions + CALL BD_BoundaryGA2(x,p,u_temp,OtherState, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + + ! Set centripetal acceleration terms (note that this is done on the local coordinates + CALL BD_CalcCentripAcc( p, x, OtherState) + + + + ! Load ramping. + ! In order to get the solution to converge, it might be necessary to ramp up the load (both distributed and point). Gravity + ! should not be ramped up if we can avoid it (currently done in the BD_Static solve) as I have not encountered a case where + ! that was an issue yet. + ! + ! NOTE: if we have issues with convergence at initialization due to the load being too large, we may need to ramp gravity. + + LoadSteps = 1_IntKi + IF ( .NOT. RampLoad ) THEN + MaxLoadSteps = 1_IntKi ! If we are not allowing ramping of loads, we will set this to one loadstep. + ELSE + MaxLoadSteps = 10_IntKi ! If we are not allowing ramping of loads, we will set this to one loadstep. + ENDIF + + DO + ! Gradually increase load. First we attempt with one loadstep, then ramp up number of loadsteps until it works + DO j=1,LoadSteps ! NOTE: LoadSteps will increase by powers of 2 + + ScaleFactor = REAL(j,BDKi) / REAL(LoadSteps,BDKi) + CALL BD_DistrLoadCopy( p, u, m, ScaleFactor ) + + ! If the initial rotation rate is large, we may encounter a situation where the initial curvature cannot be calculated. + ! To get around this, we could use a stepping algorithm to increase the rotation rate while attempting to solve. This + ! should in theory give the desired information. See the static solve case for ideas on how to ramp up the load. + CALL BD_QuasiStaticSolution(x, OtherState, u_temp, p, m, isConverged, piter, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! If it couldn't converge on a given loadstep, we must increase the loadstep (again) + IF ( .NOT. isConverged ) THEN + EXIT +! ELSEIF ( piter > Newton_Raphson_Iteration_Limit .AND. (.NOT. ConvergeWarn) ) THEN ! Warn only once. +! CALL SetErrStat( ErrID_Warn,' More than '//trim(num2lstr(Newton_Raphson_Iteration_Limit))//' Newton Raphson iterations required for convergence. Solution suspect.', ErrStat, ErrMsg, RoutineName ) +! ConvergeWarn = .TRUE. + ENDIF + + ENDDO + + ! After exiting the load stepping loop, we either found a solution, or we need to add a loadstep? + IF ( isConverged ) THEN + EXIT ! Solution converged on full DistrLoad_QP, so exit this while loop + ELSE + + ! Reset things, and try again. Increment count for total loadsteps + CALL BD_CopyContState(x_temp,x,MESH_NEWCOPY,ErrStat2,ErrMsg2) ! these are the states we started with + call SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + OtherState%Acc = 0.0_BDKi + + ! Reset the inertial forces (this is for output purposes if we have to start without the quasistatic solve) + m%qp%Fi = 0.0_BDKi ! This could be output before it gets set. + + + ! Now proceed only if we are allowed to and have not exceeded the + IF ( LoadSteps .EQ. 2**MaxLoadSteps ) THEN + !NOTE: if we did not converge to a solution, then we will return now that we have reset the states. + CALL SetErrStat(ErrID_Warn,'BeamDyn could not find a quasi-static solution to initialize with. Proceeding with no initial solve.', ErrStat, ErrMsg, RoutineName) + EXIT ! we will set the error below + ELSE + ! Try adding a loadstep + LoadSteps = LoadSteps*2_IntKi + ENDIF + ENDIF + + ENDDO + + + call cleanup() + return + +CONTAINS + SUBROUTINE Cleanup() + CALL BD_DestroyInput(u_temp, ErrStat2, ErrMsg2 ) + CALL BD_DestroyContState(x_temp, ErrStat2, ErrMsg2 ) + END SUBROUTINE Cleanup +END SUBROUTINE BD_QuasiStatic + + +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_QuasiStaticSolution( x, OtherState, u, p, m, isConverged, piter, ErrStat, ErrMsg ) + + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + TYPE(BD_InputType), INTENT(IN ) :: u !< inputs (in BD local coords) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + LOGICAL, INTENT( OUT) :: isConverged !< tells if this converged + INTEGER(IntKi), INTENT( OUT) :: piter ! iteration counter + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(BDKi) :: Eref + REAL(BDKi) :: Enorm + INTEGER(IntKi) :: j + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuasiStaticSolution' + + ErrStat = ErrID_None + ErrMsg = "" + + Eref = 0.0_BDKi + isConverged = .false. + + DO piter=1,p%niter + ! Calculate Quadrature point values needed + CALL BD_QuadraturePointData( p,x,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + CALL BD_GenerateQuasiStaticElement(x, OtherState, p, m) + + ! Add in point loads. This is used in the driver code for QuasiStatic solves. These are zero + ! during initialization, but have values during the call in UpdateStates. + ! Point loads are on the GLL points. + DO j=1,p%node_total + m%RHS(1:3,j) = m%RHS(1:3,j) + m%PointLoadLcl(1:3,j) + m%RHS(4:6,j) = m%RHS(4:6,j) + m%PointLoadLcl(4:6,j) + ENDDO + + ! Reshape for the use with the LAPACK solver + m%LP_RHS = RESHAPE(m%RHS, (/p%dof_total/)) + m%LP_RHS_LU = m%LP_RHS(7:p%dof_total) + m%LP_StifK = RESHAPE(m%StifK, (/p%dof_total,p%dof_total/)) + m%LP_StifK_LU = m%LP_StifK(7:p%dof_total,7:p%dof_total) + + + ! Solve for X in A*X=B to get the displacement of blade under static load. + CALL LAPACK_getrf( p%dof_total-p%dof_node, p%dof_total-p%dof_node, m%LP_StifK_LU, m%LP_indx, ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL LAPACK_getrs( 'N',p%dof_total-p%dof_node, m%LP_StifK_LU, m%LP_indx, m%LP_RHS_LU, ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Reshape to BeamDyn arrays + m%Solution(:,1) = 0.0_BDKi ! first node is not set below + m%Solution(:,2:p%node_total) = RESHAPE( m%LP_RHS_LU, (/ p%dof_node, (p%node_total - 1) /) ) + + + CALL BD_QuasiStaticUpdateConfiguration(u,p,m,x,OtherState) + +!FIXME: we may need to update the tolerance criteria a bit. + ! Check if solution has converged. + IF(piter .EQ. 1) THEN + Eref = SQRT(abs(DOT_PRODUCT(m%LP_RHS_LU, m%LP_RHS(7:p%dof_total))))*p%tol + IF(Eref .LE. p%tol) THEN + isConverged = .true. + RETURN + END IF + + ELSE + Enorm = SQRT(abs(DOT_PRODUCT(m%LP_RHS_LU, m%LP_RHS(7:p%dof_total)))) + IF(Enorm .LE. Eref) THEN + isConverged = .true. + RETURN + END IF + ENDIF + + ENDDO + + ! if we didn't converge, we will take care of the error in the calling subroutine (looking at with piter) + RETURN + +END SUBROUTINE BD_QuasiStaticSolution + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine updates the static configuration +!! given incremental value calculated by the +!! Newton-Raphson algorithm +SUBROUTINE BD_QuasiStaticUpdateConfiguration(u,p,m,x,OtherState) + TYPE(BD_InputType), INTENT(IN ) :: u !< inputs in local BD coordinates + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(IN ) :: m !< misc/optimization variables + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + + REAL(BDKi) :: rotf_temp(3) + REAL(BDKi) :: roti_temp(3) + REAL(BDKi) :: rot_temp(3) + INTEGER(IntKi) :: i + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuasiStaticUpdateConfiguration' + + + ! Skip first node as it is not really a state + DO i=2, p%node_total + + ! Calculate new position + x%q(1:3,i) = x%q(1:3,i) + m%Solution(1:3,i) + + ! Calculate the new rotation. Combine the original rotation parameters, x%q(4:6,:), + ! with the rotation displacement parameters, m%Solution(4:6,i). Note that the result must + ! be composed from the two sets of rotation parameters + rotf_temp(:) = x%q(4:6,i) + roti_temp(:) = m%Solution(4:6,i) + CALL BD_CrvCompose(rot_temp,roti_temp,rotf_temp,FLAG_R1R2) ! R(rot_temp) = R(roti_temp) R(rotf_temp) + x%q(4:6,i) = rot_temp(:) + + ENDDO + + + ! Using the new position info above, update the velocity and acceleration + + ! Reinitialize the velocity using the new x%q and root velocity + CALL BD_CalcIC_Velocity( u, p ,x ) + + ! Set centripetal acceleration terms using x%q and x%dqdt + CALL BD_CalcCentripAcc( p, x, OtherState) + + + +END SUBROUTINE BD_QuasiStaticUpdateConfiguration + + +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_GenerateQuasiStaticElement( x, OtherState, p, m ) + + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t on input; at t+dt on outputs + TYPE(BD_ParameterType), INTENT(IN ):: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT):: m !< misc/optimization variables + + INTEGER(IntKi) :: nelem + CHARACTER(*), PARAMETER :: RoutineName = 'BD_GenerateQuasiStaticElement' + + + ! must initialize these because BD_AssembleStiffK and BD_AssembleRHS are INOUT + m%RHS = 0.0_BDKi + m%StifK = 0.0_BDKi + + ! These values have not been set yet for the QP + CALL BD_QPData_mEta_rho( p,m ) ! Calculate the \f$ m \eta \f$ and \f$ \rho \f$ terms + CALL BD_QPDataVelocity( p, x, m ) ! x%dqdt --> m%qp%vvv, m%qp%vvp + + CALL BD_QPDataAcceleration( p, OtherState, m ) ! Naaa --> aaa (OtherState%Acc --> m%qp%aaa) + + DO nelem=1,p%elem_total + + CALL BD_QuasiStaticElementMatrix( nelem, p, m ) + CALL BD_AssembleStiffK(nelem,p,m%elk,m%StifK) + CALL BD_AssembleRHS(nelem,p,m%elf,m%RHS) + + ENDDO + + RETURN +END SUBROUTINE BD_GenerateQuasiStaticElement + + +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_QuasiStaticElementMatrix( nelem, p, m ) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< current element number + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: idx_dof1, idx_dof2 + INTEGER(IntKi) :: idx_qp + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuasiStaticElementMatrix' + + + CALL BD_ElasticForce( nelem,p,m,.true. ) ! Calculate Fc, Fd [and Oe, Pe, and Qe for N-R algorithm] + CALL BD_GravityForce( nelem,p,m,p%gravity ) ! Calculate Fg + + ! NOTE: we only use Ki (not Gi or Mi as we are not calculating \delta{a} or \delta{v}) + CALL BD_InertialForce( nelem,p,m,.true. ) ! Calculate Fi [and Mi, Gi, Ki] + + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + m%elk(idx_dof1,i,idx_dof2,j) = 0.0_BDKi + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Qe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac( :,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + (m%qp%Qe( idx_dof1,idx_dof2,idx_qp,nelem) + m%qp%Ki(idx_dof1,idx_dof2,idx_qp,nelem))*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Pe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,i,j) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Pe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,i,j) + END DO + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Oe( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,j,i) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Oe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,j,i) + END DO + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Stif(idx_dof1,idx_dof2,:,nelem), p%QPtw_ShpDer_ShpDer_Jac(:,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Stif(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) + END DO + ENDDO + ENDDO + ENDDO + ENDDO + + ! NOTE: m%DistrLoad_QP is ramped in the QuasiStatic call. + m%qp%Ftemp(:,:,nelem) = m%qp%Fd(:,:,nelem) + m%qp%Fi(:,:,nelem) - m%qp%Fg(:,:,nelem) - m%DistrLoad_QP(:,:,nelem) + call Integrate_ElementForce(nelem, p, m) ! use m%qp%Fc and m%qp%Ftemp to compute m%elf + + + RETURN + +END SUBROUTINE BD_QuasiStaticElementMatrix +!----------------------------------------------------------------------------------------------------------------------------------- +! The above section of code can be used for calculating the quasi-static initial condition. It is not energy conserving, so cannot +! be used during a simulation!!! +!----------------------------------------------------------------------------------------------------------------------------------- + + + + + + + +!----------------------------------------------------------------------------------------------------------------------------------- +! This subroutine calculates the internal nodal forces at each finite-element +! nodes along beam axis for the static case. This is more involved than in the dynamic case because m%EFint is not calculated beforehand. +! Nodal forces = K u +!FIXME: NOTE: if we go to multiple elements for trap quadrature, we will need to double check this routine. +SUBROUTINE BD_InternalForceMoment( x, p, m ) + + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + INTEGER(IntKi) :: nelem ! number of current element + INTEGER(IntKi) :: idx_node_in_elem + INTEGER(IntKi) :: idx_node + INTEGER(IntKi) :: idx_qp + REAL(BDKi) :: Tmp6(6) + REAL(BDKi) :: Tmp3(3) + REAL(BDKi) :: PrevNodePos(3) + INTEGER(IntKi) :: i !< generic counter + INTEGER(IntKi) :: LastNode !< Last node in element to consider in integration in FE points + INTEGER(IntKi) :: StartNode !< First node to consider in integration for QP points + CHARACTER(*), PARAMETER:: RoutineName = 'BD_InternalForceMoment' + + + ! Initialize all values to zero. + m%BldInternalForceFE(:,:) = 0.0_BDKi + m%BldInternalForceQP(:,:) = 0.0_BDKi + + ! Integrate quadrature points to get the FE nodes elastic force per length. + m%EFint(:,:,:) = 0.0_BDKi + + DO nelem=1,p%elem_total + DO i=1,p%nodes_per_elem + ! Integrate shape functions across the quadrature points to get FE nodes. + DO idx_qp=1,p%nqp + ! Force contributions from current node + m%EFint(1:3,i,nelem) = m%EFint(1:3,i,nelem) & + + m%qp%Fc(1:3,idx_qp,nelem)*p%QPtw_ShpDer(idx_qp,i) + + ! Moment contributions from current node + m%EFint(4:6,i,nelem) = m%EFint(4:6,i,nelem) & + + m%qp%Fc(4:6,idx_qp,nelem)*p%QPtw_ShpDer( idx_qp,i) & + + m%qp%Fd(4:6,idx_qp,nelem)*p%QPtw_Shp_Jac(idx_qp,i,nelem) ! Fd only contains moments + ENDDO + ENDDO + ENDDO + + + + ! Now Integerate from the tip inwards to get the internal forces at the FE nodes + + ! Calculate the internal forces and moments at the FE nodes. + ! NOTE: the elastic force contributions are already calculated and stored, so we merely need to perform the summation. + ! NOTE: we are only counting unique points, not overlapping FE points (those are identical as the first node is not a state) + ! The p%node_elem_idx stores the first and last nodes of elements in the aggregated nodes (ignoring overlapping nodes) + + ! Working from tip to root + LastNode = p%nodes_per_elem-1 ! Already counted tip, so set the last node for iteration loop + + DO nelem = p%elem_total,1,-1 + + m%BldInternalForceFE(1:3,nelem*LastNode+1) = p%FEweight(p%nodes_per_elem,nelem) * m%EFint(1:3,p%nodes_per_elem,nelem) + m%BldInternalForceFE(4:6,nelem*LastNode+1) = m%EFint(4:6,p%nodes_per_elem,nelem) + + ! Keep track of previous node for adding force contributions to moments + PrevNodePos = p%uuN0(1:3,p%nodes_per_elem,nelem) + x%q(1:3,nelem*LastNode+1) + + DO idx_node_in_elem=LastNode,1,-1 + + ! Index to node in FE array + idx_node = p%node_elem_idx(nelem,1)-1 + idx_node_in_elem ! p%node_elem_idx(nelem,1) is the first node in the element + + ! Force term + ! NOTE: the idx_node+1 includes all force contributions up to the previous node tip inwards + m%BldInternalForceFE(1:3,idx_node) = p%FEweight(idx_node_in_elem,nelem) * m%EFint(1:3,idx_node_in_elem,nelem) & + + m%BldInternalForceFE(1:3,idx_node+1) & + + (1.0_BDKi - p%FEweight(idx_node_in_elem+1,nelem)) * m%EFint(1:3,idx_node_in_elem+1,nelem) ! Remaining integral of prior nodes shape functions + + ! Moment term including forces from next node out projected to this node + ! NOTE: this appears like double counting, but the issue is that the Fd and Fc terms are both included in EFint. + ! These terms partially cancel each other. Fd includes part of the force term as well. + Tmp3 = PrevNodePos - (p%uuN0(1:3,idx_node_in_elem,nelem) + x%q(1:3,idx_node)) + m%BldInternalForceFE(4:6,idx_node) = m%EFint(4:6,idx_node_in_elem,nelem) & + + m%BldInternalForceFE(4:6,idx_node+1) & + + cross_product( Tmp3, m%BldInternalForceFE(1:3,idx_node+1) ) & + + cross_product( Tmp3, (1.0_BDKi - p%FEweight(idx_node_in_elem+1,nelem)) * m%EFint(1:3,idx_node_in_elem+1,nelem)) ! remaining integral of prior node shape function + + ! Keep track of node position next node in. + PrevNodePos = p%uuN0(1:3,idx_node_in_elem,nelem) + x%q(1:3,idx_node) + + ENDDO + + ENDDO + + + ! The mathematics above ends up setting element boundaries to exactly zero. + DO nelem = p%elem_total,2,-1 + ! if we are at the element boundary, we keep the average value from the tip of the next element in and + ! the negative of the first node of this element. + ! + ! NOTE: the above calculations result in something close to zero otherwise because it is counting both + ! the tip of inner element and first node of outer element, which will almost cancel. + idx_node = p%node_elem_idx(nelem-1,2) ! Last node of next element inboard + m%BldInternalForceFE(1:3,idx_node) = ( m%EFint(1:3,p%nodes_per_elem,nelem-1) - m%EFint(1:3,1,nelem) ) / 2.0_BDKi + ENDDO + + ! Now deal with the root node + ! Add root reaction: For the dynamic solves, this includes the mass*acceleration terms for the first node + ! For the static solve, this is in the first node for static case and does not need + ! contributions from the outboard sections due to how the solve is performed. + m%BldInternalForceFE(1:6,1) = m%FirstNodeReactionLclForceMoment(:) + + ! Point force at the tip is not counted at the last point. However, its contribution to the moment, and the tip moment are counted already. + m%BldInternalForceFE(1:3,p%node_total) = m%BldInternalForceFE(1:3,p%node_total) + (1.0_BDKi - p%FEweight(p%nodes_per_elem,p%elem_total))*m%PointLoadLcl(1:3,p%node_total) + + + + ! Rotate coords to global reference frame + DO i=1,SIZE(m%BldInternalForceFE,DIM=2) + m%BldInternalForceFE(1:3,i) = MATMUL(p%GlbRot,m%BldInternalForceFE(1:3,i)) + m%BldInternalForceFE(4:6,i) = MATMUL(p%GlbRot,m%BldInternalForceFE(4:6,i)) + ENDDO + + + + ! Internal reaction force at QP (if trap quadrature is used) + ! NOTE: the elastic force contributions are already calculated and stored at the quadrature point, but prior to the use + ! of the shape functions. Therefore, some additional mathematics are required. + + SELECT CASE (p%BldMotionNodeLoc) + CASE (BD_MESH_QP) + + ! Using the FE node information above which includes the root reactions, we can reconstruct exactly what the QP data + ! is using the shape functions. The reason for doing this is that the original QP information stored in m%qp%Fc is not + ! the elastic force directly, but rather must be integrated with ShpDer before yielding the FE point information. To + ! retrieve the QP data, we take the FE node result with the root reaction, and perform an integration using the pseudo- + ! inverse of the ShpDer function to retrieve the QP reaction info. Since the starting info includes the coordinate + ! transforms, we do not need to transform again. + ! Note: the FE node information above already has the rotation to the global reference frame, so we do not do that again here. + + + DO idx_node=1,size(p%NdIndx) + + ! Get the element and qp information + nelem = p%OutNd2NdElem(2,idx_node) + idx_qp = p%OutNd2NdElem(1,idx_node) + + ! Integrate over the FE point information + Tmp6 = 0.0_BDKi + StartNode=p%node_elem_idx(nelem,1) + DO i=1,p%nodes_per_elem + Tmp6 = Tmp6 + m%BldInternalForceFE(:,StartNode+i-1)* p%Shp(i,idx_qp) + ENDDO + + m%BldInternalForceQP(:,idx_node) = Tmp6 + + ENDDO + + END SELECT + + RETURN +END SUBROUTINE BD_InternalForceMoment + + + + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine performs time marching from t_i to t_f +SUBROUTINE BD_GA2(t,n,u,utimes,p,x,xd,z,OtherState,m,ErrStat,ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(BD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states at t + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + TYPE(BD_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 + + ! local variables + TYPE(BD_InputType) :: u_interp ! interpolated value of inputs + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_GA2' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL BD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! on first call, initialize accelerations at t=0 and put mass and stiffness matrices in the summary file: + IF ( ( n .EQ. 0 .OR. .NOT. OtherState%InitAcc ) ) THEN + + ! Set the inputs at t + call BD_Input_extrapinterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! We cannot set the load during initialization (because there is no input mesh yet), so initialize with the load inputs. + IF ( OtherState%RunQuasiStaticInit ) THEN + + ! We don't want to run quasistatic again regardless of outcome, so set the flag now + OtherState%RunQuasiStaticInit = .FALSE. + + ! Solve for the displacements with the acceleration and rotational velocity terms included + ! This will set m%qp%aaa, OtherState%Acc, x%q, and x%dqdt. + ! If this is not successful, it restores the values of x and sets OtherState%Acc=0 + CALL BD_QuasiStatic(u_interp,p,x,OtherState,m,ErrStat2,ErrMsg2, RampLoad=.true.) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ENDIF + + + !................ + ! Initialize the accelerations with the input root accelerations: + !................ + + ! Transform quantities from global frame to local (blade) frame + CALL BD_InputGlobalLocal(p,u_interp) + + ! Copy over the DistrLoads + CALL BD_DistrLoadCopy( p, u_interp, m ) + + ! Incorporate boundary conditions + CALL BD_BoundaryGA2(x,p,u_interp,OtherState, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! initialize the accelerations in OtherState%Acc + CALL BD_InitAcc( u_interp, p, x, m, OtherState%Acc, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! initialize GA2 algorithm acceleration variable, OtherState%Xcc (acts as a filtering value on OtherState%acc) + OtherState%Xcc(:,:) = OtherState%Acc(:,:) + + ! accelerations have been initialized + OtherState%InitAcc = .true. + + + ! If we are writing to a summary file + IF (m%Un_Sum > 0) THEN + + ! compute mass and stiffness matrices + ! Calculate Quadrature point values needed + CALL BD_QuadraturePointData( p,x,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE.) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL BD_WriteMassStiff( p, m, ErrStat2,ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL BD_WriteMassStiffInFirstNodeFrame( p, x, m, ErrStat2,ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CLOSE(m%Un_Sum) + m%Un_Sum = -1 + END IF + + END IF + + + call BD_Input_extrapinterp( u, utimes, u_interp, t+p%dt, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL BD_UpdateDiscState( t, n, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! Actuator + IF( p%UsePitchAct ) THEN + CALL PitchActuator_SetBC(p, u_interp, xd) + ENDIF + + ! Transform quantities from global frame to local (blade in BD coords) frame + CALL BD_InputGlobalLocal(p,u_interp) + + ! Copy over the DistrLoads + CALL BD_DistrLoadCopy( p, u_interp, m ) + + + ! GA2: prediction + CALL BD_TiSchmPredictorStep( x, OtherState, p ) ! updates x and OtherState accelerations (from values at t to predictions at t+dt) + + ! Incorporate boundary conditions (overwrite first node of continuous states and Acc array at t+dt) + CALL BD_BoundaryGA2(x,p,u_interp,OtherState, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + ! find x, acc, and xcc at t+dt + CALL BD_DynamicSolutionGA2( x, OtherState, p, m, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call cleanup() + return + +CONTAINS + SUBROUTINE cleanup() + CALL BD_DestroyInput(u_interp, ErrStat2, ErrMsg2) + END SUBROUTINE cleanup +END SUBROUTINE BD_GA2 + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the predicted values (initial guess) +!! of u,v,acc, and xcc in generalized-alpha algorithm +SUBROUTINE BD_TiSchmPredictorStep( x, OtherState, p ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + + REAL(BDKi) ::tr(6) + REAL(BDKi) ::rot_temp(3) + INTEGER ::i ! generic counter + CHARACTER(*), PARAMETER :: RoutineName = 'BD_TiSchmPredictorStep' + DO i=2,p%node_total + + tr = p%dt * x%dqdt(:,i) + p%coef(1) * OtherState%acc(:,i) + p%coef(2) * OtherState%xcc(:,i) ! displacements at t+dt + x%dqdt(:,i) = x%dqdt(:,i) + p%coef(3) * OtherState%acc(:,i) + p%coef(4) * OtherState%xcc(:,i) ! velocities at t+dt + OtherState%xcc(:,i) = p%coef(5) * OtherState%acc(:,i) + p%coef(6) * OtherState%xcc(:,i) ! xcc accelerations at t+dt: ((1-alpha_m)*xcc_(t+dt) = (1-alpha_f)*Acc_(t+dt) + alpha_f*Acc_t - alpha_m*xcc_t + OtherState%acc(:,i) = 0.0_BDKi ! acc accelerations at t+dt + + x%q(1:3,i) = x%q(1:3,i) + tr(1:3) ! position at t+dt + + ! tr does not contain w-m parameters, yet we are treating them as such + CALL BD_CrvCompose(rot_temp, tr(4:6), x%q(4:6,i), FLAG_R1R2) ! rot_temp = tr(4:6) composed with x%q(4:6,i) [rotations at t], is the output + x%q(4:6,i) = rot_temp ! rotations at t+dt + + ENDDO + +END SUBROUTINE BD_TiSchmPredictorStep + + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the Timoshenko coefficients, p%coef, used in generalized-alpha +!! time integrator. It requires that p%rhoinf and p%dt have been set +SUBROUTINE BD_TiSchmComputeCoefficients(p) + + TYPE(BD_ParameterType), INTENT(inout) :: p + + REAL(DbKi) :: tr0 + REAL(DbKi) :: tr1 + REAL(DbKi) :: tr2 + REAL(DbKi) :: alfam ! \alpha_M + REAL(DbKi) :: alfaf ! \alpha_F + REAL(DbKi) :: gama + REAL(DbKi) :: beta + REAL(DbKi) :: oalfaM ! 1 - \alpha_M + REAL(DbKi) :: deltat2 ! {\delta t}^2 = dt^2 + + ! Bauchau equations 17.39 + tr0 = p%rhoinf + 1.0_BDKi + alfam = (2.0_BDKi * p%rhoinf - 1.0_BDKi) / tr0 + alfaf = p%rhoinf / tr0 + + ! Bauchau equations 17.40 + gama = 0.5_BDKi - alfam + alfaf + beta = 0.25 * (1.0_BDKi - alfam + alfaf)**2 + + ! The coefficents are then found using equations 17.41a - 17.41c + deltat2 = p%dt**2 + oalfaM = 1.0_BDKi - alfam + tr0 = alfaf / oalfaM + tr1 = alfam / oalfaM + tr2 = (1.0_BDKi - alfaf) / oalfaM + + p%coef(1) = beta * tr0 * deltat2 + p%coef(2) = (0.5_BDKi - beta/oalfaM) * deltat2 + p%coef(3) = gama * tr0 * p%dt + p%coef(4) = (1.0_BDKi - gama / oalfaM) * p%dt + p%coef(5) = tr0 + p%coef(6) = -tr1 + p%coef(7) = gama * tr2 * p%dt + p%coef(8) = beta * tr2 * deltat2 + p%coef(9) = tr2 + +END SUBROUTINE BD_TiSchmComputeCoefficients + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine applies the prescribed boundary conditions (from the input RootMotion mesh) +!! into states and otherstates at the root finite element node +SUBROUTINE BD_BoundaryGA2(x,p,u,OtherState, ErrStat, ErrMsg) + + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t (in local BD coords) + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Inputs at t + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Continuous states at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_BoundaryGA2' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Root displacements + x%q(1:3,1) = u%RootMotion%TranslationDisp(1:3,1) + + ! Root rotations + CALL ExtractRelativeRotation(u%RootMotion%Orientation(:,:,1),p, x%q(4:6,1), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Root velocities/angular velocities and accelerations/angular accelerations + x%dqdt(1:3,1) = u%RootMotion%TranslationVel(1:3,1) + x%dqdt(4:6,1) = u%Rootmotion%RotationVel(1:3,1) + OtherState%acc(1:3,1) = u%RootMotion%TranslationAcc(1:3,1) + OtherState%acc(4:6,1) = u%RootMotion%RotationAcc(1:3,1) + +END SUBROUTINE BD_BoundaryGA2 + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine perform time-marching in one interval +!! Given states (u,v) and accelerations (acc,xcc) at the initial of a time step (t_i), +!! it returns the values of states and accelerations at the end of a time step (t_f) +!FIXME: note similarities to BD_StaticSolution. May be able to combine +SUBROUTINE BD_DynamicSolutionGA2( x, OtherState, p, m, ErrStat, ErrMsg) + + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states: input are the predicted values at t+dt; output are calculated values at t + dt + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: input are the predicted accelerations at t+dt; output are calculated values at t + dt + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_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 + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DynamicSolutionGA2' + + REAL(DbKi) :: Eref + REAL(DbKi) :: Enorm + INTEGER(IntKi) :: piter + INTEGER(IntKi) :: j + LOGICAL :: fact + + ErrStat = ErrID_None + ErrMsg = "" + + Eref = 0.0_BDKi + DO piter=1,p%niter + + fact = MOD(piter-1,p%n_fact) .EQ. 0 ! when true, we factor the jacobian matrix + + IF ( (p%tngt_stf_fd .OR. p%tngt_stf_comp) .AND. fact ) CALL BD_FD_GA2( x, OtherState, p, m ) + + ! Apply accelerations using F=ma ? Is that what this routine does? + ! Calculate Quadrature point values needed + CALL BD_QuadraturePointData( p,x,m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 using current guess at continuous states (displacements and velocities) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m,fact) + + ! Apply additional forces / loads at GLL points (driver code only -- aero is from DistrLoad) + DO j=1,p%node_total + m%RHS(1:6,j) = m%RHS(1:6,j) + m%PointLoadLcl(1:6,j) + ENDDO + + IF(fact) THEN + m%StifK = m%MassM + p%coef(7) * m%DampG + p%coef(8) * m%StifK + IF ( p%tngt_stf_fd .OR. p%tngt_stf_comp ) m%StifK_fd = m%MassM_fd + p%coef(7) * m%DampG_fd + p%coef(8) * m%StifK_fd + + ! compare the finite differenced stiffness matrix against the analytical tangent stiffness matrix is flag is set + IF ( p%tngt_stf_comp ) CALL BD_CompTngtStiff( RESHAPE(m%StifK ,(/p%dof_total,p%dof_total/)), & + RESHAPE(m%StifK_fd,(/p%dof_total,p%dof_total/)), p%tngt_stf_difftol, & + ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) return + + ! Reshape 4d array into 2d for the use with the LAPACK solver + IF ( p%tngt_stf_fd ) THEN + m%LP_StifK = RESHAPE(m%StifK_fd, (/p%dof_total,p%dof_total/)); + ELSE + m%LP_StifK = RESHAPE( m%StifK, (/p%dof_total,p%dof_total/)); + ENDIF + ! extract the unconstrained stifness matrix + m%LP_StifK_LU = m%LP_StifK(7:p%dof_total,7:p%dof_total) + + ! note m%LP_indx is allocated larger than necessary (to allow us to use it in multiple places) + CALL LAPACK_getrf( p%dof_total-6, p%dof_total-6, m%LP_StifK_LU, m%LP_indx, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + ENDIF + + ! Reshape 2d array into 1d for the use with the LAPACK solver + m%LP_RHS = RESHAPE(m%RHS(:,:), (/p%dof_total/)) + m%LP_RHS_LU = m%LP_RHS(7:p%dof_total) + + ! Solve for X in A*X=B to get the accelerations of blade + CALL LAPACK_getrs( 'N',p%dof_total-6, m%LP_StifK_LU, m%LP_indx, m%LP_RHS_LU, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + m%Solution(:,1) = 0.0_BDKi ! first node is not set below. By definition, there is no displacement of the first node. + m%Solution(:,2:p%node_total) = RESHAPE( m%LP_RHS_LU, (/ p%dof_node, (p%node_total - 1) /) ) + + CALL BD_UpdateDynamicGA2(p,m,x,OtherState) + + ! Compute energy of the current system (note - not a norm!) + m%LP_RHS = RESHAPE(x%q(:,:), (/p%dof_total/)) + Enorm = abs(DOT_PRODUCT(m%LP_RHS_LU, m%LP_RHS(7:p%dof_total))) + + ! Check if solution has converged. + IF(piter .EQ. 1) THEN + Eref = Enorm + IF(Eref .LE. p%tol) RETURN + ELSE + IF(Enorm/Eref .LE. p%tol) RETURN + ENDIF + + ENDDO + + CALL setErrStat( ErrID_Fatal, "Solution does not converge after the maximum number of iterations", ErrStat, ErrMsg, RoutineName) + RETURN + +END SUBROUTINE BD_DynamicSolutionGA2 + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the finite differenced tangent stiffness matrix +SUBROUTINE BD_FD_GA2( x, OtherState, p, m ) + + ! Function arguments + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + ! Local variables + INTEGER(IntKi) :: i + INTEGER(IntKi) :: idx_dof + CHARACTER(*), PARAMETER :: RoutineName = 'BD_FD_GA2' + + ! zero out the local matrices. Not sure where these should be initailzed + m%RHS_m = 0.0_BDKi + m%RHS_p = 0.0_BDKi + m%StifK_fd = 0.0_BDKi + m%DampG_fd = 0.0_BDKi + m%MassM_fd = 0.0_BDKi + + ! Perform finite differencing for velocity dofs + DO i=1,p%nodes_per_elem + DO idx_dof=1,p%dof_node + + ! Perturb in the negative direction + x%q(idx_dof,i) = x%q(idx_dof,i) - p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_m(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! Perturb in the positive direction + x%q(idx_dof,i) = x%q(idx_dof,i) + 2*p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_p(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! The negative sign is because we are finite differencing + ! f_ext - f_int instead of f_int + m%StifK_fd(:,:,idx_dof,i) = -(m%RHS_p - m%RHS_m)/(2*p%tngt_stf_pert) + + ! Reset the solution vector entry to unperturbed state + x%q(idx_dof,i) = x%q(idx_dof,i) - p%tngt_stf_pert + + ENDDO + ENDDO + + ! zero out the local matrices. + m%RHS_m = 0.0_BDKi + m%RHS_p = 0.0_BDKi + + ! Perform finite differencing for velocity dofs + DO i=1,p%nodes_per_elem + DO idx_dof=1,p%dof_node + + ! Perturb in the negative direction + x%dqdt(idx_dof,i) = x%dqdt(idx_dof,i) - p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_m(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! Perturb in the positive direction + x%dqdt(idx_dof,i) = x%dqdt(idx_dof,i) + 2*p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_p(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! The negative sign is because we are finite differencing + ! f_ext - f_int instead of f_int + m%DampG_fd(:,:,idx_dof,i) = -(m%RHS_p - m%RHS_m)/(2*p%tngt_stf_pert) + + ! Reset the solution vector entry to unperturbed state + x%dqdt(idx_dof,i) = x%dqdt(idx_dof,i) - p%tngt_stf_pert + + ENDDO + ENDDO + + ! zero out the local matrices. + m%RHS_m = 0.0_BDKi + m%RHS_p = 0.0_BDKi + + ! Perform finite differencing for acceleration dofss + DO i=1,p%nodes_per_elem + DO idx_dof=1,p%dof_node + + ! Perturb in the negative direction + OtherState%acc(idx_dof,i) = OtherState%acc(idx_dof,i) - p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_m(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! Perturb in the positive direction + OtherState%acc(idx_dof,i) = OtherState%acc(idx_dof,i) + 2*p%tngt_stf_pert + + ! Calculate weak for for current solution vector + CALL BD_QuadraturePointData( p,x,m ) + CALL BD_GenerateDynamicElementGA2( x, OtherState, p, m, .TRUE. ) + + ! Account for externally applied point loads + m%RHS_p(1:6,:) = m%RHS(1:6,:) + m%PointLoadLcl(1:6,:) + + ! The negative sign is because we are finite differencing + ! f_ext - f_int instead of f_int + m%MassM_fd(:,:,idx_dof,i) = -(m%RHS_p - m%RHS_m)/(2*p%tngt_stf_pert) + + ! Reset the solution vector entry to unperturbed state + OtherState%acc(idx_dof,i) = OtherState%acc(idx_dof,i) - p%tngt_stf_pert + + ENDDO + ENDDO + +END SUBROUTINE BD_FD_GA2 + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine updates the 1) displacements/rotations(uf) +!! 2) linear/angular velocities(vf); 3) linear/angular accelerations(af); and +!! 4) algorithmic accelerations(xf) given the increments obtained through +!! N-R algorithm +SUBROUTINE BD_UpdateDynamicGA2( p, m, x, OtherState ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(IN ) :: m !< misc/optimization variables + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + + REAL(BDKi) :: roti_temp(3) + REAL(BDKi) :: rot_temp(3) + INTEGER(IntKi) :: i + CHARACTER(*), PARAMETER :: RoutineName = 'BD_UpdateDynamicGA2' + + ! m%Solution contains (\delta q dot dot) + ! The first node has no displacements by definition. + DO i=2, p%node_total + x%q(1:3,i) = x%q(1:3,i) + p%coef(8) * m%Solution(1:3,i) + + roti_temp = p%coef(8) * m%Solution(4:6,i) ! m%Solution(4:6,i) seems to contain accelerations (i.e., delta \omega dot), so I don't think this can be a w-m parameter + CALL BD_CrvCompose(rot_temp,roti_temp,x%q(4:6,i),FLAG_R1R2) ! rot_temp = roti_temp composed with x%q(4:6,i) + x%q(4:6,i) = rot_temp(1:3) + + + x%dqdt(:,i) = x%dqdt(:,i) + p%coef(7) * m%Solution(:,i) + OtherState%acc(:,i) = OtherState%acc(:,i) + m%Solution(:,i) ! update acceleration (dqdtdt: q dot dot) to next guess for values at t+dt + OtherState%xcc(:,i) = OtherState%xcc(:,i) + p%coef(9) * m%Solution(:,i) ! update algorithm acceleration to next guess for values at t+dt: (1-alpha_m)*xcc_(n+1) = (1-alpha_f)*dqdtdt_(n+1) + alpha_f*dqdtdt_n - alpha_m*xcc_n + ENDDO + +END SUBROUTINE BD_UpdateDynamicGA2 + + +!----------------------------------------------------------------------------------------------------------------------------------- +! this routine computes m%LP_MassM, m%LP_RHS, m%LP_StifK +!FIXME: this routine is really similar to the begining section of BD_GenerateDynamicElementAcc. Only real difference is that it calculates the m%Stif and m%LP_DampG as well. +SUBROUTINE BD_GenerateDynamicElementGA2( x, OtherState, p, m, fact ) + + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t on input at t + dt on output + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t on input; at t+dt on outputs + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + LOGICAL, INTENT(IN ) :: fact + + INTEGER(IntKi) :: nelem + CHARACTER(*), PARAMETER :: RoutineName = 'BD_GenerateDynamicElementGA2' + + + ! must initialize these because BD_AssembleStiffK and BD_AssembleRHS are INOUT + m%RHS = 0.0_BDKi + + IF(fact) THEN + m%StifK = 0.0_BDKi + m%MassM = 0.0_BDKi + m%DampG = 0.0_BDKi + END IF + + + + ! These values have not been set yet for the QP. + ! We can leave these inside this subroutine rather than move them up. + CALL BD_QPData_mEta_rho( p,m ) ! Calculate the \f$ m \eta \f$ and \f$ \rho \f$ terms + CALL BD_QPDataVelocity( p, x, m ) ! x%dqdt --> m%qp%vvv, m%qp%vvp + + CALL BD_QPDataAcceleration( p, OtherState, m ) ! Naaa --> aaa (OtherState%Acc --> m%qp%aaa) + + DO nelem=1,p%elem_total + + ! compute m%elk,m%elf,m%elm,m%elg: + CALL BD_ElementMatrixGA2(fact, nelem, p, m ) + + IF(fact) THEN + CALL BD_AssembleStiffK(nelem,p,m%elk,m%StifK) + CALL BD_AssembleStiffK(nelem,p,m%elm,m%MassM) + CALL BD_AssembleStiffK(nelem,p,m%elg,m%DampG) + ENDIF + CALL BD_AssembleRHS(nelem,p,m%elf,m%RHS) + + ENDDO + RETURN +END SUBROUTINE BD_GenerateDynamicElementGA2 + + +!----------------------------------------------------------------------------------------------------------------------------------- +!FIXME: lots of pieces of BD_ElementMatrixAcc show up in here +SUBROUTINE BD_ElementMatrixGA2( fact, nelem, p, m ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + + LOGICAL, INTENT(IN ) :: fact !< are we factoring? + INTEGER(IntKi), INTENT(IN ) :: nelem !< Number of current element + + INTEGER(IntKi) :: idx_qp + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: idx_dof1 + INTEGER(IntKi) :: idx_dof2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ElementMatrixGA2' + + +!FIXME: adp: I don't see the gyroscopic term in here. That is stored in m%qp%Fb +!VA: The gyroscopic term is included in the m%qp%Gi. I think the m%qp%Fb term is used to calculate the accelerations + + + CALL BD_ElasticForce( nelem,p,m,fact ) ! Calculate Fc, Fd [and if(fact): Oe, Pe, and Qe for N-R algorithm] using m%qp%E1, m%qp%RR0, m%qp%kappa, m%qp%Stif + CALL BD_InertialForce( nelem,p,m,fact ) ! Calculate Fi [and Mi,Gi,Ki IF(fact)] + + IF(p%damp_flag .NE. 0) THEN + CALL BD_DissipativeForce( nelem,p,m,fact ) ! Calculate dissipative terms on Fc, Fd [and Sd, Od, Pd and Qd, betaC, Gd, Xd, Yd for N-R algorithm] + ENDIF + + CALL BD_GravityForce( nelem, p, m, p%gravity ) + + + + ! Equations 10, 11, 12 in Wang_2014 + + IF (fact) THEN + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + m%elk(idx_dof1,i,idx_dof2,j) = 0.0_BDKi + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Qe( idx_dof1,idx_dof2,:,nelem) + m%qp%Ki(idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac( :,i,j,nelem) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + (m%qp%Qe(idx_dof1,idx_dof2,idx_qp,nelem) + m%qp%Ki(idx_dof1,idx_dof2,idx_qp,nelem))*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Pe( idx_dof1,idx_dof2,:,nelem) , p%QPtw_Shp_ShpDer( :,i,j) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Pe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,i,j) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Oe( idx_dof1,idx_dof2,:,nelem) , p%QPtw_Shp_ShpDer( :,j,i) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Oe( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,j,i) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Stif(idx_dof1,idx_dof2,:,nelem) , p%QPtw_ShpDer_ShpDer_Jac(:,i,j,nelem) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Stif(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) + END DO + + ENDDO + ENDDO + ENDDO + END DO + + CALL Integrate_ElementMass(nelem, p, m) ! use m%qp%Mi to compute m%elm + + + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + m%elg(idx_dof1,i,idx_dof2,j) = 0.0_BDKi + DO idx_qp = 1,p%nqp ! dot_product( m%qp%Gi(idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac(:,i,j,nelem)) + m%elg(idx_dof1,i,idx_dof2,j) = m%elg(idx_dof1,i,idx_dof2,j) + m%qp%Gi(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + + ENDDO + ENDDO + ENDDO + END DO + + ! Dissipative terms + IF (p%damp_flag .NE. 0) THEN + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Qd(idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac( :,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Qd(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Pd(idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,i,j) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Pd(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,i,j) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Od(idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,j,i) ) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Od(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,j,i) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Sd(idx_dof1,idx_dof2,:,nelem), p%QPtw_ShpDer_ShpDer_Jac(:,i,j,nelem)) + m%elk(idx_dof1,i,idx_dof2,j) = m%elk(idx_dof1,i,idx_dof2,j) + m%qp%Sd(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) + END DO + + ENDDO + ENDDO + ENDDO + END DO + + DO j=1,p%nodes_per_elem + DO idx_dof2=1,p%dof_node + DO i=1,p%nodes_per_elem + DO idx_dof1=1,p%dof_node + + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Xd( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_Shp_Jac( :,i,j,nelem)) + m%elg(idx_dof1,i,idx_dof2,j) = m%elg(idx_dof1,i,idx_dof2,j) + m%qp%Xd( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Yd( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,i,j) ) + m%elg(idx_dof1,i,idx_dof2,j) = m%elg(idx_dof1,i,idx_dof2,j) + m%qp%Yd( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,i,j) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%Gd( idx_dof1,idx_dof2,:,nelem), p%QPtw_Shp_ShpDer( :,j,i) ) + m%elg(idx_dof1,i,idx_dof2,j) = m%elg(idx_dof1,i,idx_dof2,j) + m%qp%Gd( idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_Shp_ShpDer(idx_qp,j,i) + END DO + DO idx_qp = 1,p%nqp ! dot_product(m%qp%betaC(idx_dof1,idx_dof2,:,nelem), p%QPtw_ShpDer_ShpDer_Jac(:,i,j,nelem)) + m%elg(idx_dof1,i,idx_dof2,j) = m%elg(idx_dof1,i,idx_dof2,j) + m%qp%betaC(idx_dof1,idx_dof2,idx_qp,nelem)*p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) + END DO + + ENDDO + ENDDO + ENDDO + END DO + ENDIF ! add the dissipative terms + + ENDIF + + ! Equations 13 and 14 in Wang_2014. F^ext is combined with F^D (F^D = F^D-F^ext) + ! F^ext is combined with F^D (F^D = F^D-F^ext), i.e. RHS of Equation 9 in Wang_2014 + m%qp%Ftemp(:,:,nelem) = m%qp%Fd(:,:,nelem) + m%qp%Fi(:,:,nelem) - m%qp%Fg(:,:,nelem) - m%DistrLoad_QP(:,:,nelem) + call Integrate_ElementForce(nelem, p, m) ! use m%qp%Fc and m%qp%Ftemp to compute m%elf + + RETURN + +END SUBROUTINE BD_ElementMatrixGA2 + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine compares the tangent stiffness matrix against the finite differenced tangent stiffness matrix +SUBROUTINE BD_CompTngtStiff( K_anlyt, K_fd, errtol, ErrStat, ErrMsg ) + + ! Function arguments + REAL(BDKi), INTENT(IN) :: K_anlyt(:,:) !< analytical tangent stiffness matrix + REAL(BDKi), INTENT(IN) :: K_fd(:,:) !< finite differenced tangent stiffness matrix + REAL(BDKi), INTENT(IN) :: errtol !< allowable difference tolerance for comparison + !! any relative difference greater than this will stop the ongoing + !! simulation + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(BDKi) :: ignore_fac=1e-3 !< values smaller than this times maximum value in corresponding + !! row will be ignored during the comparison of matrices + !! In doing so we hope to avoid comparison of entries that are + !! less significant in terms of inverting the matrix + REAL(BDKi), allocatable :: K_diff(:,:) !< array containing the relative differences between + ! finite differenced and analytical tangent stiffness matrices + INTEGER(IntKi) :: max_diff_loc(2) + INTEGER(IntKi) :: idof + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CompTngtStiff' + + ErrStat = ErrID_None + ErrMsg = "" + + ! allocate local array and initialize to all zeros + CALL AllocAry(K_diff,size(K_fd,1),size(K_fd,2),'StifK Diff',ErrStat,ErrMsg); + K_diff = 0.0_BDKi + + ! Compute the relative difference. abs allows user to set a difference tolerance without worrying about the sign + K_diff = abs( (K_anlyt-K_fd) / K_fd ) + + ! ignore differences for entries that are smaller than ignore_fac*max(element in row) + DO idof=1,size(K_fd,1) + WHERE( K_fd(idof,:) < ignore_fac*maxval(K_fd(idof,:)) ) K_diff(idof,:) = 0.0 + END DO + max_diff_loc = maxloc( K_diff ) + + CALL WrScr( NewLine // NewLine // 'Maximum difference between analytical and fd tangent stiffness occurred for entry (' // & + TRIM(Num2LStr(max_diff_loc(1))) //','// TRIM(Num2LStr(max_diff_loc(2))) // ') ' // NewLine // & + 'Max relative difference is ' // TRIM(Num2LStr(maxval(K_diff))) // NewLine ) + + ! check that the flags set are consistent before moving further + IF ( maxval(K_diff) > errtol ) THEN + CALL SetErrStat(ErrID_Fatal, 'maximum relative difference between analytical and fd tangent stiffness exceeded used defined tolerance.', ErrStat, ErrMsg, RoutineName ) + return + END IF + +END SUBROUTINE BD_CompTngtStiff + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine tranforms the following quantities in Input data structure from global frame to local (blade) frame: +!! 1 Displacements +!! 2 Linear/Angular velocities +!! 3 Linear/Angular accelerations +!! 4 Point forces/moments +!! 5 Distributed forces/moments +!! It also transforms the DCM to rotation tensor in the input data structure +SUBROUTINE BD_InputGlobalLocal(p, u) + TYPE(BD_ParameterType), INTENT(IN ):: p + TYPE(BD_InputType), INTENT(INOUT):: u + INTEGER(IntKi) :: i !< Generic counter + CHARACTER(*), PARAMETER :: RoutineName = 'BD_InputGlobalLocal' + + ! Transform Root Motion from Global to Local (Blade) frame + u%RootMotion%TranslationDisp(:,1) = MATMUL(u%RootMotion%TranslationDisp(:,1),p%GlbRot) + u%RootMotion%TranslationVel(:,1) = MATMUL(u%RootMotion%TranslationVel( :,1),p%GlbRot) + u%RootMotion%RotationVel(:,1) = MATMUL(u%RootMotion%RotationVel( :,1),p%GlbRot) + u%RootMotion%TranslationAcc(:,1) = MATMUL(u%RootMotion%TranslationAcc( :,1),p%GlbRot) + u%RootMotion%RotationAcc(:,1) = MATMUL(u%RootMotion%RotationAcc( :,1),p%GlbRot) + + ! Transform DCM to Rotation Tensor (RT) + u%RootMotion%Orientation(:,:,1) = TRANSPOSE(u%RootMotion%Orientation(:,:,1)) ! matrix that now transfers from local to global (FAST's DCMs convert from global to local) + + ! Transform Applied Forces from Global to Local (Blade) frame + DO i=1,p%node_total + u%PointLoad%Force(1:3,i) = MATMUL(u%PointLoad%Force(:,i),p%GlbRot) + u%PointLoad%Moment(1:3,i) = MATMUL(u%PointLoad%Moment(:,i),p%GlbRot) + ENDDO + + ! transform distributed forces and moments + DO i=1,u%DistrLoad%Nnodes + u%DistrLoad%Force(1:3,i) = MATMUL(u%DistrLoad%Force(:,i),p%GlbRot) + u%DistrLoad%Moment(1:3,i) = MATMUL(u%DistrLoad%Moment(:,i),p%GlbRot) + ENDDO + +END SUBROUTINE BD_InputGlobalLocal + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine is just to clean up the code a bit. This is called between the BD_InputGlobalLocal and BD_BoundaryGA2 routines. +!! It could probably live in the BD_InputGlobablLocal except for the call just before the BD_CalcIC call (though it might not matter there). +! NOTE: This routine could be entirely removed if the u%DistrLoad arrays are used directly, but that would require some messy indexing. +SUBROUTINE BD_DistrLoadCopy( p, u, m, RampScaling ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at t (in BD coordinates) + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + REAL(BDKi), OPTIONAL :: RampScaling + + INTEGER(IntKi) :: temp_id + INTEGER(IntKi) :: idx_qp + INTEGER(IntKi) :: nelem + INTEGER(IntKi) :: i + REAL(BDKi) :: ScalingFactor + + ! To simplify ramping with the static and quasi-static calculations, we add a ramping scale factor + IF (PRESENT(RampScaling)) THEN + ScalingFactor = RampScaling + ELSE + ScalingFactor = 1.0_BDki + ENDIF + + ! Set the intermediate DistrLoad_QP array. + DO nelem=1,p%elem_total + temp_id = (nelem-1)*p%nqp + p%qp_indx_offset + DO idx_qp=1,p%nqp + m%DistrLoad_QP(1:3,idx_qp,nelem) = u%DistrLoad%Force(1:3,temp_id+idx_qp) * ScalingFactor + m%DistrLoad_QP(4:6,idx_qp,nelem) = u%DistrLoad%Moment(1:3,temp_id+idx_qp) * ScalingFactor + ENDDO + ENDDO + + ! Transform Applied Forces from Global to Local (Blade) frame + DO i=1,p%node_total + m%PointLoadLcl(1:3,i) = u%PointLoad%Force(:,i) * ScalingFactor ! Type conversion!! + m%PointLoadLcl(4:6,i) = u%PointLoad%Moment(:,i) * ScalingFactor ! Type conversion!! + ENDDO + +END SUBROUTINE BD_DistrLoadCopy + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the initial states +!! Rigid body assumption is used in initialization of the states. +!! The initial displacements/rotations and linear velocities are +!! set to the root value; the angular velocities over the beam +!! are computed based on rigid body rotation: \omega = v_{root} \times r_{pos} +SUBROUTINE BD_CalcIC_Position( u, p, x, ErrStat, ErrMsg) + + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t (in BD coordinates) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t + 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) :: j + INTEGER(IntKi) :: k + INTEGER(IntKi) :: temp_id + REAL(BDKi) :: temp_p0(3) + REAL(BDKi) :: temp_rv(3) + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcIC_Position' + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Since RootMotion%Orientation is the transpose of the absolute orientation in the global frame, + ! we need to find the relative change in orientation from the reference. + CALL ExtractRelativeRotation(u%RootMotion%Orientation(:,:,1),p,temp_rv, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + + !Initialize displacements and rotations + k = 1 !when i=1, k=1 + DO i=1,p%elem_total + temp_id = p%node_elem_idx(i,1)-1 ! Node just before the start of this element + DO j=k,p%nodes_per_elem + ! reference at current root orientation. + temp_p0 = MATMUL(u%rootmotion%orientation(:,:,1),p%uuN0(1:3,j,i)) ! Global frame + temp_p0 = MATMUL(temp_p0, p%GlbRot ) ! Into the local frame + ! Add the root displacement (in local frame) to the reference at current root orientation in local frame, + ! and subtract the reference to get the displacement. This is equivalent to TranslationDisp in the local frame. + x%q(1:3,temp_id+j) = u%RootMotion%TranslationDisp(1:3,1) + temp_p0 - p%uuN0(1:3,j,i) + ENDDO + k = 2 ! start j loop at k=2 for remaining elements (i>1) + ENDDO + + k = 1 !when i=1, k=1 + DO i=1,p%elem_total + temp_id = p%node_elem_idx(i,1)-1 ! Node just before the start of this element + DO j=k,p%nodes_per_elem + x%q(4:6,temp_id+j) = temp_rv ! each node is assumed to have the same initial relative rotation as the root + ENDDO + k = 2 ! start j loop at k=2 for remaining elements (i>1) + ENDDO + +END SUBROUTINE BD_CalcIC_Position + + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the initial states +!! Rigid body assumption is used in initialization of the states. +!! The initial displacements/rotations and linear velocities are +!! set to the root value; the angular velocities over the beam +!! are computed based on rigid body rotation: \omega = v_{root} \times r_{pos} +SUBROUTINE BD_CalcIC_Velocity( u, p, x) + + TYPE(BD_InputType), INTENT(IN ):: u !< Inputs at t (in BD coordinates) + TYPE(BD_ParameterType), INTENT(IN ):: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(INOUT):: x !< Continuous states at t + + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: k + INTEGER(IntKi) :: temp_id + REAL(BDKi) :: temp3(3) + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcIC_Velocity' + + + !Initialize velocities and angular velocities + x%dqdt(:,:) = 0.0_BDKi + + ! these values don't change in the loop: + k=1 !when i=1, k=1 + DO i=1,p%elem_total + temp_id = p%node_elem_idx(i,1)-1 ! Node just before the start of this element + DO j=k,p%nodes_per_elem + + ! Find distance vector from root + temp3 = (p%uuN0(1:3,j,i) + x%q(1:3,temp_id+j)) - (p%uuN0(1:3,1,1) + x%q(1:3,1)) + ! Calculate translational velocity of tip relative to root, and add it to the root translational velocity + x%dqdt(1:3,temp_id+j) = u%RootMotion%TranslationVel(:,1) + cross_product(u%RootMotion%RotationVel(:,1),temp3) + + ! Rotational velocity is the same as the root rotational velocity + x%dqdt(4:6,temp_id+j) = u%RootMotion%RotationVel(1:3,1) + ENDDO + k = 2 ! start j loop at k=2 for remaining elements (i>1) + ENDDO + +END SUBROUTINE BD_CalcIC_Velocity + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the initial OtherStates values for the acceleration +!! The rigid body assumption is used in initialization of the centripetal accelerations, which is then iterated to find the initial +!! quasi-steady state solution for the beam shape. This is all in an effort to reduce the initial transients in the system. +!! The initial displacements/rotations and linear and rotational velocities are already set. The centripetal acceleration terms +!! are calculated based on the rotational velocity and distance from the rotation center in a stationary reference frame. +!! +!! Once the centripetal acceleration terms are found, the a quasi-steady state solution for the distorted beam shape can be found +!! for a constant rotation velocity. This can then be used to initialize BeamDyn with a better known condition that will not exhibit +!! initial transients from finding the initial shape. +!! +!! The centripetal acceleration due to rotation is\n +!! \f$ \underline{a}_\textrm{centrip} = +!! \underline{\omega} \times \left( \underline{\omega} \times \left(\underline{r}_i - \underline{r_0} \right) \right) \f$\n +!! where \f$\underline{\omega}\f$ is the rotational velocity of the node, \f$\underline{r}_0\f$ is the point we are rotating about +!! (axis of rotation), and \f$\underline{r}^_i\f$ is the location of the current node. +SUBROUTINE BD_CalcCentripAcc( p, x, OtherState) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input; at t+dt on outputs + + + INTEGER(IntKi) :: i,j,k !< generic counter + INTEGER(IntKi) :: temp_id + REAL(BDKi) :: R_0(3) !< center point of rotation (anywhere along axis of rotation) + REAL(BDKi) :: R(3) !< vector from R_0 to current node + REAL(BDKi) :: temp3(3) !< temporary vector + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcCentripAcc' + + + !> Find the center of rotation (any point along the axis of rotation will work I think) using the root node motion + !! Using the root node equation used to find the translational velocity of a node, + !! _x%dqdt(1:3,1) = cross_product(u%RootMotion%RotationVel(:,1),tempR)_ + !! we solve for temp33, the center point of rotation (note that any hub translation motion is included, so we end up + !! calculating everything in a global stationary reference frame, but that should be fine). So in the stationary frame, we have: + !! _tempRV = cross_product(u%RootMotion%RotationVel(:,1),tempR)_ + !! where _tempRV = x%dqdt - u%RootMotion%TranslationVelocity_ + !! This of course cannot be solved as is, but we will force the condition that the three vectors temp3V, temp3, and + !! u%RootMotion%RotationVel are orthogonal (dot products of each pair are zero) to get a unique solution. + !! + !! A solution for \f$\underline{B}\f$ from \f$\underline{A} \times \underline{B} = \underline{C}\f$ is\n + !! \f$ \underline{B} = \frac{\underline{C} \times \underline{A}}{\underline{A} \cdot \underline{A}} + t\underline{A} \f$\n + !! where \f$t\f$ is a scalar. Setting \f$t=0\f$ is equivalent to enforcing all three vectors to be orthogonal to each + !! other, which means their dot products are zero:\n + !! \f$\underline{A}\cdot\underline{B} = \underline{A}\cdot\underline{C} = \underline{B}\cdot\underline{C} = 0\f$. + !! + !! Solving for the vector R, we now can write _tempR = cross_product(x%dqdt,RotationVel) / (dot_product(RotationVel,RotationVel)) _ + + ! Find where the rotation center is relative to the first node. + ! NODE: If there is no rotational velocity, then we can set R=0, and all centripetal accelerations will be zero. + IF ( EqualRealNos( TwoNorm(x%dqdt(4:6,1)), 0.0_BDKi )) THEN + R_0 = 0.0_BDKi + ELSE + temp3 = cross_product( x%dqdt(1:3,1), x%dqdt(4:6,1) ) / dot_product( x%dqdt(4:6,1), x%dqdt(4:6,1) ) + R_0 = x%q(1:3,1) + p%uuN0(1:3,1,1) - temp3 ! NOTE: we assume whole blade rotates rigidly about this point + ENDIF + + !> Now we can find the centripetal acceleration: + !! \f$ \underline{a}_\textrm{centrip} = + !! \underline{\omega} \times \left( \underline{\omega} \times \left(\underline{r}_i - \underline{r_0} \right) \right) \f$ + ! NOTE: we calculate for the root node also as the center of rotation may not be the root node, so there will be a small + ! centripetal acceleration value at the root node. + ! NOTE: we assume the whole blade is rigidly rotating about the same center point. +!FIXME: is the centripetal root node acceleration properly handled elsewhere in BD?????? + + ! these values don't change in the loop: + k=1 !when i=1, k=1 + DO i=1,p%elem_total + temp_id = p%node_elem_idx(i,1)-1 ! Node just before the start of this element + DO j=k,p%nodes_per_elem + + R = x%q(1:3,temp_id+j) + p%uuN0(1:3,j,i) - R_0 ! vector R to current node from rotation center + temp3 = cross_product( x%dqdt(4:6,temp_id+j), R ) ! Cross product in parenthesis + OtherState%Acc(1:3,temp_id+j) = cross_product( x%dqdt(4:6,temp_id+j), temp3 ) + + ENDDO + k = 2 ! start j loop at k=2 for remaining elements (i>1) (first-last node overlap) + ENDDO + +END SUBROUTINE BD_CalcCentripAcc + + +!----------------------------------------------------------------------------------------------------------------------------------- +!! Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE BD_InitAcc( u, p, x, m, qdotdot, ErrStat, ErrMsg ) + + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t (in BD coordinates) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + REAL(BDKi), INTENT( OUT) :: qdotdot(:,:) !< accelerations + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_InitAcc' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Calculate Quadrature point values needed + CALL BD_QuadraturePointData( p, x, m ) ! Calculate QP values uuu, uup, RR0, kappa, E1 + + ! set misc vars, particularly m%RHS + CALL BD_CalcForceAcc( u, p, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! set accelerations with inputs from the root and BD_CalcForceAcc solution + qdotdot(1:3,1 ) = u%RootMotion%TranslationAcc(:,1) + qdotdot(4:6,1 ) = u%RootMotion%RotationAcc(:,1) + qdotdot( :,2:) = m%RHS(:,2:) + + return + +END SUBROUTINE BD_InitAcc + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calls other subroutines to apply the force, build the beam element +!! stiffness and mass matrices, and build nodal force vector. The output of this subroutine +!! is the second time derivative of state "q". This is simply a solve of \f$ F=ma \f$. +!! +!! The full set of equations can be written as: +!! +!! \f{eqnarray*}{ +!! M \cdot A &=& F \\ +!! \begin{bmatrix} m_{11} & m_{12} & m_{13} & \dots & m_{1N} \\ +!! m_{21} & m_{22} & m_{23} & \dots & m_{2N} \\ +!! m_{31} & m_{32} & m_{33} & \dots & m_{3N} \\ +!! \vdots & \vdots & \vdots & \ddots & \vdots \\ +!! m_{N1} & m_{N2} & m_{N3} & \dots & m_{NN} \end{bmatrix} \cdot +!! \begin{bmatrix} a_{1} \\ +!! a_{2} \\ +!! a_{3} \\ +!! \vdots \\ +!! a_{N} \end{bmatrix} +!! & = & +!! \begin{bmatrix} f_{1} - F_\text{root} \\ +!! f_{2} \\ +!! f_{3} \\ +!! \vdots \\ +!! f_{N} \end{bmatrix} +!! \f}\n +!! Since the acceleration at the first node, \f$ a_{1} \f$, is known, we can rearrange as: +!! \f{eqnarray*}{ +!! \begin{bmatrix} 0 & m_{12} & m_{13} & \dots & m_{1N} \\ +!! 0 & m_{22} & m_{23} & \dots & m_{2N} \\ +!! 0 & m_{32} & m_{33} & \dots & m_{3N} \\ +!! \vdots & \vdots & \vdots & \ddots & \vdots \\ +!! 0 & m_{N2} & m_{N3} & \dots & m_{NN} \end{bmatrix} \cdot +!! \begin{bmatrix} a_{1} \\ +!! a_{2} \\ +!! a_{3} \\ +!! \vdots \\ +!! a_{N} \end{bmatrix} +!! & = & +!! \begin{bmatrix} f_{1} - m_{11} a_{1} - F_\text{root} \\ +!! f_{2} - m_{21} a_{1} \\ +!! f_{3} - m_{31} a_{1} \\ +!! \vdots \\ +!! f_{N} - m_{N1} a_{1} \end{bmatrix} +!! \f}\n +!! This could be rearranged to solve for \f$ F_\text{root} \f$ simultaneously with the +!! accelerations. However, root force is orders of magnitude larger than the accelerations +!! which creates numerical issues in the solve. Further, nodes 2 onwards can be solved +!! separately which gets around the numerical issues. Therefore, solving for the acclerations +!! for node 2 onwards first we can simplify the equations to: +!! \f{eqnarray*}{ +!! \begin{bmatrix} m_{22} & m_{23} & \dots & m_{2N} \\ +!! m_{32} & m_{33} & \dots & m_{3N} \\ +!! \vdots & \vdots & \ddots & \vdots \\ +!! m_{N2} & m_{N3} & \dots & m_{NN} \end{bmatrix} \cdot +!! \begin{bmatrix} a_{2} \\ +!! a_{3} \\ +!! \vdots \\ +!! a_{N} \end{bmatrix} +!! & = & +!! \begin{bmatrix} f_{2} - m_{21} a_{1} \\ +!! f_{3} - m_{31} a_{1} \\ +!! \vdots \\ +!! f_{N} - m_{N1} a_{1} \end{bmatrix} +!! \f}\n +!! NOTE: each of the terms in \f$ f_{i} \f$ and \f$ a_{i} \f$ are vectors of 6 elements and each +!! of the elements in the mass matrix, \f$ m_{ij} \f$, are 6x6 matrices corresponding to the +!! degrees of freedom. +!! +!! The root reaction force is therefore calculated afterwards as +!! \f$ F_\textrm{root} = f_1 - \sum_{i} m_{1,i} a_{i} \f$. +SUBROUTINE BD_CalcForceAcc( u, p, m, ErrStat, ErrMsg ) + + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_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 + + INTEGER(IntKi) :: j + REAL(BDKi) :: RootAcc(6) + REAL(BDKi) :: NodeMassAcc(6) + INTEGER(IntKi) :: nelem ! number of elements + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CalcForceAcc' + + ErrStat = ErrID_None + ErrMsg = "" + + ! must initialize these because BD_AssembleStiffK and BD_AssembleRHS are INOUT + m%RHS = 0.0_BDKi + m%MassM = 0.0_BDKi + + ! Store the root accelerations as they will be used multiple times + RootAcc(1:3) = u%RootMotion%TranslationAcc(1:3,1) + RootAcc(4:6) = u%RootMotion%RotationAcc(1:3,1) + + + ! Calculate the global mass matrix and force vector for the beam + DO nelem=1,p%elem_total + CALL BD_ElementMatrixAcc( nelem, p, m ) ! Calculate m%elm and m%elf + CALL BD_AssembleStiffK(nelem,p,m%elm, m%MassM) ! Assemble full mass matrix + CALL BD_AssembleRHS(nelem,p,m%elf, m%RHS) ! Assemble right hand side force terms + ENDDO + + + ! Add point forces at GLL points to RHS of equation. + DO j=1,p%node_total + m%RHS(1:3,j) = m%RHS(1:3,j) + m%PointLoadLcl(1:3,j) + m%RHS(4:6,j) = m%RHS(4:6,j) + m%PointLoadLcl(4:6,j) + ENDDO + + + ! Now set the root reaction force. + ! Note: m%RHS currently holds the force terms for the RHS of the equation. + !> The root reaction force is first node force minus mass time acceleration terms: + !! \f$ F_\textrm{root} = F_1 - \sum_{i} m_{1,i} a_{i} \f$. + m%FirstNodeReactionLclForceMoment(1:6) = m%RHS(1:6,1) + + ! Setup the RHS of the m*a=F equation. Skip the first node as that is handled separately. + DO j=2,p%node_total + m%RHS(:,j) = m%RHS(:,j) - MATMUL( RESHAPE(m%MassM(:,j,:,1),(/6,6/)), RootAcc) + ENDDO + + + ! Solve for the accelerations! + ! Reshape for the use with the LAPACK solver. Only solving for nodes 2:p%node_total (node 1 accelerations are known) + m%LP_RHS_LU = RESHAPE(m%RHS(:,2:p%node_total), (/p%dof_total-6/)) + m%LP_MassM = RESHAPE(m%MassM, (/p%dof_total,p%dof_total/)) ! Flatten out the dof dimensions of the matrix. + m%LP_MassM_LU = m%LP_MassM(7:p%dof_total,7:p%dof_total) + + ! Solve linear equations A * X = B for acceleration (F=ma) for nodes 2:p%node_total + CALL LAPACK_getrf( p%dof_total-6, p%dof_total-6, m%LP_MassM_LU, m%LP_indx, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL LAPACK_getrs( 'N',p%dof_total-6, m%LP_MassM_LU, m%LP_indx, m%LP_RHS_LU,ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) return + + ! Reshape for copy over to output overall accelerations of system + m%RHS(:,2:p%node_total) = RESHAPE( m%LP_RHS_LU, (/ p%dof_node, p%node_total-1 /) ) + m%RHS(:,1) = RootAcc ! This is known at the start. + + + + !> Now that we have all the accelerations, complete the summation \f$ \sum_{i} m_{1,i} a_{i} \f$ + ! First node: + NodeMassAcc = MATMUL( RESHAPE(m%MassM(:,1,:,1),(/6,6/)),m%RHS(:,1) ) + m%FirstNodeReactionLclForceMoment(1:6) = m%FirstNodeReactionLclForceMoment(1:6) - NodeMassAcc(1:6) + + ! remaining nodes + DO j=2,p%Node_total + NodeMassAcc = MATMUL( RESHAPE(m%MassM(:,j,:,1),(/6,6/)),m%RHS(:,j) ) + m%FirstNodeReactionLclForceMoment(1:6) = m%FirstNodeReactionLclForceMoment(1:6) - NodeMassAcc(1:6) + ENDDO + + + RETURN + +END SUBROUTINE BD_CalcForceAcc + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes Global mass matrix and force vector for the beam. +SUBROUTINE BD_ComputeBladeMassNew( p, ErrStat, ErrMsg ) + + TYPE(BD_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 + + REAL(BDKi), ALLOCATABLE:: NQPpos(:,:) + REAL(BDKi) :: elem_mass + REAL(BDKi) :: elem_CG(3) + REAL(BDKi) :: elem_IN(3,3) + REAL(BDKi), ALLOCATABLE:: EMass0_GL(:,:,:) + INTEGER(IntKi) :: dof_elem ! Degree of freedom per node + INTEGER(IntKi) :: nelem ! number of elements + INTEGER(IntKi) :: j ! Index counter + INTEGER(IntKi) :: temp_id ! Index counter + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ComputeBladeMassNew' + + ErrStat = ErrID_None + ErrMsg = "" + p%blade_mass = 0.0_BDKi + + dof_elem = p%dof_node * p%nodes_per_elem + + CALL AllocAry(NQPpos,3,p%nqp,'NQPpos',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(EMass0_GL,6,6,p%nqp,'EMass0_GL',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + NQPpos(:,:) = 0.0_BDKi + EMass0_GL(:,:,:) = 0.0_BDKi + elem_mass= 0.0_BDKi + elem_CG(:)= 0.0_BDKi + elem_IN(:,:)= 0.0_BDKi + + DO nelem=1,p%elem_total + + temp_id = (nelem-1)*p%nqp + DO j=1,p%nqp + EMass0_GL(1:6,1:6,j) = p%Mass0_QP(1:6,1:6,temp_id+j) + NQPpos(1:3,j) = p%uu0(1:3,j,nelem) + ENDDO + + CALL BD_ComputeElementMass(nelem,p,NQPpos,EMass0_GL,elem_mass,elem_CG,elem_IN) + + p%blade_mass = p%blade_mass + elem_mass + p%blade_CG(:) = p%blade_CG(:) + elem_CG(:) + p%blade_IN(:,:) = p%blade_IN(:,:) + elem_IN(:,:) + + ENDDO + + if (.not. EqualRealNos( p%blade_mass, 0.0_BDKi )) then + p%blade_CG(:) = p%blade_CG(:) / p%blade_mass + else + p%blade_CG = 0.0_BDKi + end if + + CALL Cleanup() + RETURN + +CONTAINS + SUBROUTINE Cleanup() + if (allocated(NQPpos )) deallocate(NQPpos ) + if (allocated(EMass0_GL )) deallocate(EMass0_GL ) + END SUBROUTINE Cleanup +END SUBROUTINE BD_ComputeBladeMassNew + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine total element forces and mass matrices +!FIXME: this routine is only used in the BD_ComputeBladeMassNew subroutine. Might make sense to combine with that, but low gains since only used in Init +SUBROUTINE BD_ComputeElementMass(nelem,p,NQPpos,EMass0_GL,elem_mass,elem_CG,elem_IN) + + INTEGER(IntKi), INTENT(IN ) :: nelem !< current element number + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(BDKi), INTENT(IN ) :: NQPpos(:,:) + REAL(BDKi), INTENT(IN ) :: EMass0_GL(:,:,:) !< Nodal material properties for each element + REAL(BDKi), INTENT( OUT) :: elem_mass !< Total element force (Fd, Fc, Fb) + REAL(BDKi), INTENT( OUT) :: elem_CG(:) + REAL(BDKi), INTENT( OUT) :: elem_IN(:,:) + + REAL(BDKi) :: mmm + INTEGER(IntKi) :: idx_qp + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ComputeElementMass' + + elem_mass = 0.0_BDKi + elem_CG(:) = 0.0_BDKi + elem_IN(:,:) = 0.0_BDKi + + + DO idx_qp=1,p%nqp + + mmm = EMass0_GL(1,1,idx_qp) + + elem_mass = elem_mass + p%QPtWeight(idx_qp) * p%Jacobian(idx_qp,nelem) * mmm + elem_CG(1:3) = elem_CG(1:3) + p%QPtWeight(idx_qp) * p%Jacobian(idx_qp,nelem) * mmm * NQPpos(1:3,idx_qp) + elem_IN(1:3,1:3) = elem_IN(1:3,1:3) - p%QPtWeight(idx_qp) * p%Jacobian(idx_qp,nelem) * mmm * & + MATMUL(SkewSymMat(NQPpos(1:3,idx_qp)),SkewSymMat(NQPpos(1:3,idx_qp))) + + ENDDO + + + RETURN + +END SUBROUTINE BD_ComputeElementMass + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine alters the RootMotion inputs based on the pitch-actuator parameters and discrete states +SUBROUTINE PitchActuator_SetBC(p, u, xd, AllOuts) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< The module parameters + TYPE(BD_InputType), INTENT(INOUT) :: u !< inputs + TYPE(BD_DiscreteStateType),INTENT(IN ) :: xd !< The module discrete states + REAL(ReKi), OPTIONAL,INTENT(INOUT) :: AllOuts(0:) !< all output array for writing to file + ! local variables + REAL(BDKi) :: temp_R(3,3) + REAL(BDKi) :: temp_cc(3) + REAL(BDKi) :: u_theta_pitch + REAL(BDKi) :: thetaP + REAL(BDKi) :: omegaP + REAL(BDKi) :: alphaP + + + temp_R = MATMUL(u%RootMotion%Orientation(:,:,1),TRANSPOSE(u%HubMotion%Orientation(:,:,1))) + temp_cc = EulerExtract(temp_R) != Hub_theta_Root + u_theta_pitch = -temp_cc(3) + + thetaP = xd%thetaP + omegaP = xd%thetaPD + alphaP = -(p%pitchK/p%pitchJ) * xd%thetaP - (p%pitchC/p%pitchJ) * xd%thetaPD + (p%pitchK/p%pitchJ) * u_theta_pitch + + ! Calculate new root motions for use as BeamDyn boundary conditions: + !note: we alter the orientation last because we need the input (before actuator) root orientation for the rotational velocity and accelerations + u%RootMotion%RotationVel(:,1) = u%RootMotion%RotationVel(:,1) - omegaP * u%RootMotion%Orientation(3,:,1) + u%RootMotion%RotationAcc(:,1) = u%RootMotion%RotationAcc(:,1) - alphaP * u%RootMotion%Orientation(3,:,1) + + temp_cc(3) = -thetaP + temp_R = EulerConstruct(temp_cc) + u%RootMotion%Orientation(:,:,1) = MATMUL(temp_R,u%HubMotion%Orientation(:,:,1)) + + if (present(AllOuts)) then + AllOuts(PAngInp) = u_theta_pitch + AllOuts(PAngAct) = thetaP + AllOuts(PRatAct) = omegaP + AllOuts(PAccAct) = alphaP + end if + +END SUBROUTINE PitchActuator_SetBC + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in BD_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 BD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdu, dXdu, dXddu, dZdu, StateRel_x, StateRel_xdot) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_OutputType), INTENT(INOUT) :: 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(BD_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 the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: StateRel_x(:,:) !< Matrix by which the displacement states are optionally converted relative to root + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: StateRel_xdot(:,:) !< Matrix by which the velocity states are optionally converted relative to root + + + ! local variables + TYPE(BD_OutputType) :: y_p + TYPE(BD_OutputType) :: y_m + TYPE(BD_ContinuousStateType) :: x_p + TYPE(BD_ContinuousStateType) :: x_m + TYPE(BD_InputType) :: u_perturb + REAL(R8Ki) :: delta_p, delta_m ! delta change in input (plus, minus) + INTEGER(IntKi) :: i + REAL(R8Ki) :: RotateStates(3,3) + REAL(R8Ki), ALLOCATABLE :: RelState_x(:,:) + REAL(R8Ki), ALLOCATABLE :: RelState_xdot(:,:) + + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'BD_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + ! get OP values here: + call BD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! make a copy of the inputs to perturb + call BD_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + if (p%RelStates) then + if (.not. allocated(RelState_x)) then + call AllocAry(RelState_x, p%Jac_nx * 2, size(p%Jac_u_indx,1), 'RelState_x', ErrStat2, ErrMsg2) ! 18=6 motion fields on mesh x 3 directions for each field + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + if (.not. allocated(RelState_xdot)) then + call AllocAry(RelState_xdot, size(RelState_x,1), size(RelState_x,2), 'RelState_xdot', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + call Compute_RelState_Matrix(p, u, x, RelState_x, RelState_xdot) + + if ( present(StateRel_x) ) then + if (.not. allocated(StateRel_x)) then + call AllocAry(StateRel_x, size(RelState_x,1), size(RelState_x,2), 'StateRel_x', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + StateRel_x = RelState_x + end if + if ( present(StateRel_xdot) ) then + if (.not. allocated(StateRel_xdot)) then + call AllocAry(StateRel_xdot, size(RelState_xdot,1), size(RelState_xdot,2), 'StateRel_xdot', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + StateRel_xdot = RelState_xdot + end if + else + if ( present(StateRel_x) ) then + if (allocated(StateRel_x)) deallocate(StateRel_x) + end if + if ( present(StateRel_xdot) ) then + if (allocated(StateRel_xdot)) deallocate(StateRel_xdot) + end if + end if + + + IF ( PRESENT( dYdu ) ) THEN + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate dYdu + if (.not. allocated(dYdu) ) then + call AllocAry(dYdu,p%Jac_ny, size(p%Jac_u_indx,1),'dYdu', ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call BD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call BD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta_p u + call BD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, 1, u_perturb, delta_p ) + + ! compute y at u_op + delta_p u + call BD_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! get u_op - delta_m u + call BD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, -1, u_perturb, delta_m ) + + ! compute y at u_op - delta_m u + call BD_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta_p, dYdu(:,i) ) + + end do + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call BD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call BD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + if (p%RelStates) then + call BD_JacobianPContState_noRotate( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx=m%lin_C ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + dYdu = dYdu + matmul(m%lin_C, RelState_x) + end if + + END IF + + IF ( PRESENT( dXdu ) ) THEN + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate dXdu if necessary + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, p%Jac_nx * 2, size(p%Jac_u_indx,1), 'dXdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta u + call BD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call Perturb_u( p, i, 1, u_perturb, delta_p ) + + ! compute x at u_op + delta u + call BD_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get u_op - delta u + call BD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call Perturb_u( p, i, -1, u_perturb, delta_m ) + + ! compute x at u_op - delta u + call BD_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! get central difference: + call Compute_dX( p, x_p, x_m, delta_p, dXdu(:,i) ) + + end do + + call BD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call BD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + if (p%RelStates) then + call BD_JacobianPContState_noRotate( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dXdx=m%lin_A ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + dXdu = dXdu + matmul(m%lin_A, RelState_x) - RelState_xdot + end if + + if (p%RotStates) then + RotateStates = matmul( u%RootMotion%Orientation(:,:,1), transpose( u%RootMotion%RefOrientation(:,:,1) ) ) + do i=1,size(dXdu,1),3 + dXdu(i:i+2, :) = matmul( RotateStates, dXdu(i:i+2, :) ) + end do + end if + + END IF ! dXdu + + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF + + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + call cleanup() +contains + subroutine cleanup() + call BD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call BD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call BD_DestroyInput( u_perturb, ErrStat2, ErrMsg2 ) + + if (allocated(RelState_x)) deallocate(RelState_x) + if (allocated(RelState_xdot)) deallocate(RelState_xdot) + end subroutine cleanup + +END SUBROUTINE BD_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 BD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx, dXddx, dZdx, StateRotation ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_OutputType), INTENT(INOUT) :: 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(BD_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] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: StateRotation(:,:) !< Matrix by which the states are optionally rotated + + + ! local variables + TYPE(BD_OutputType) :: y_p + TYPE(BD_OutputType) :: y_m + TYPE(BD_ContinuousStateType) :: x_p + TYPE(BD_ContinuousStateType) :: x_m + TYPE(BD_ContinuousStateType) :: x_perturb + INTEGER(IntKi) :: i + REAL(R8Ki) :: RotateStates(3,3) + REAL(R8Ki) :: RotateStatesTranspose(3,3) + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_JacobianPContState' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( dYdx ) .AND. PRESENT( dXdx )) THEN + call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2, dYdx, dXdx) +! call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, LIN_X_CALLED_FIRST, ErrStat2, ErrMsg2, dYdx, dXdx) + ELSEIF ( PRESENT( dYdx ) ) THEN + call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2, dYdx=dYdx ) +! call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, LIN_X_CALLED_FIRST, ErrStat2, ErrMsg2, dYdx=dYdx ) + ELSEIF ( PRESENT( dXdx ) ) THEN + call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2, dXdx=dXdx) +! call BD_JacobianPContState_noRotate(t, u, p, x, xd, z, OtherState, y, m, LIN_X_CALLED_FIRST, ErrStat2, ErrMsg2, dXdx=dXdx) + END IF + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (p%RotStates) then + RotateStates = matmul( u%RootMotion%Orientation(:,:,1), transpose( u%RootMotion%RefOrientation(:,:,1) ) ) + RotateStatesTranspose = transpose( RotateStates ) + + if ( present(StateRotation) ) then + if (.not. allocated(StateRotation)) then + call AllocAry(StateRotation, 3, 3, 'StateRotation', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + StateRotation = RotateStates + end if + else + if ( present(StateRotation) ) then + if (allocated(StateRotation)) deallocate(StateRotation) + end if + end if + + IF ( PRESENT( dYdx ) ) THEN + + if (p%RotStates) then + do i=1,size(dYdx,2),3 + dYdx(:, i:i+2) = matmul( dYdx(:, i:i+2), RotateStatesTranspose ) + end do + end if + + END IF + + IF ( PRESENT( dXdx ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the continuous states (x) here: + + if (p%RotStates) then + do i=1,size(dXdx,1),3 + dXdx(i:i+2,:) = matmul( RotateStates, dXdx(i:i+2,:) ) + end do + do i=1,size(dXdx,2),3 + dXdx(:, i:i+2) = matmul( dXdx(:, i:i+2), RotateStatesTranspose ) + end do + end if + + END IF + + IF ( PRESENT( dXddx ) ) THEN + if (allocated(dXddx)) deallocate(dXddx) + END IF + + IF ( PRESENT( dZdx ) ) THEN + if (allocated(dZdx)) deallocate(dZdx) + END IF + + call cleanup() + +contains + subroutine cleanup() + call BD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call BD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call BD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call BD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call BD_DestroyContState(x_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE BD_JacobianPContState +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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, and dX/dx are returned. +!SUBROUTINE BD_JacobianPContState_noRotate( t, u, p, x, xd, z, OtherState, y, m, calledFrom, ErrStat, ErrMsg, dYdx, dXdx ) +SUBROUTINE BD_JacobianPContState_noRotate( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_OutputType), INTENT(INOUT) :: 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(BD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + !INTEGER(IntKi), INTENT(IN ) :: calledFrom !< flag to help determine logic for when these matrices need to be recalculated + 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] + + + ! local variables + TYPE(BD_OutputType) :: y_p + TYPE(BD_OutputType) :: y_m + TYPE(BD_ContinuousStateType) :: x_p + TYPE(BD_ContinuousStateType) :: x_m + TYPE(BD_ContinuousStateType) :: x_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, k + INTEGER(IntKi) :: index + INTEGER(IntKi) :: dof + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_JacobianPContState_noRotate' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + ! make a copy of the continuous states to perturb + call BD_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + IF ( PRESENT( dYdx ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + + ! allocate dYdx if necessary + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%Jac_ny, p%Jac_nx*2, 'dYdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call BD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call BD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + index = 1 + do k=1,2 + do i=2,p%node_total + do dof=1,p%dof_node + + ! get x_op + delta x + call BD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call perturb_x(p, k, i, dof, 1, x_perturb, delta ) + + ! compute y at x_op + delta x + call BD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get x_op - delta x + call BD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call perturb_x(p, k, i, dof, -1, x_perturb, delta ) + + ! compute y at x_op - delta x + call BD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta, dYdx(:,index) ) + + index = index+1 + end do + end do + end do + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call BD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call BD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + 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 dXdu if necessary + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, p%Jac_nx * 2, p%Jac_nx * 2, 'dXdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + index = 1 ! counter into dXdx + do k=1,2 ! 1=positions (x_perturb%q); 2=velocities (x_perturb%dqdt) + do i=2,p%node_total + do dof=1,p%dof_node + + ! get x_op + delta x + call BD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call perturb_x(p, k, i, dof, 1, x_perturb, delta ) + + ! compute x at x_op + delta x + call BD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get x_op - delta x + call BD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call perturb_x(p, k, i, dof, -1, x_perturb, delta ) + + ! compute x at x_op - delta x + call BD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + ! get central difference: + call Compute_dX( p, x_p, x_m, delta, dXdx(:,index) ) + + index = index+1 + end do + end do + end do + + call BD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call BD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + END IF + + + call cleanup() + +contains + subroutine cleanup() + call BD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call BD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call BD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call BD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call BD_DestroyContState(x_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE BD_JacobianPContState_noRotate +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 BD_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(BD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_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(BD_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 BD_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 BD_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(BD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_OutputType), INTENT(INOUT) :: 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(BD_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] + + ! local variables + character(*), parameter :: RoutineName = 'BD_JacobianPConstrState' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + IF ( PRESENT( dYdz ) ) THEN + + END IF + + IF ( PRESENT( dXdz ) ) THEN + if (allocated(dXdz)) deallocate(dXdz) + END IF + + IF ( PRESENT( dXddz ) ) THEN + if (allocated(dXddz)) deallocate(dXddz) + END IF + + IF ( PRESENT(dZdz) ) THEN + END IF + + +END SUBROUTINE BD_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE BD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, y_op, x_op, dx_op, xd_op, z_op, NeedLogMap ) + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(BD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(BD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(BD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(BD_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(BD_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 + LOGICAL, OPTIONAL, INTENT(IN ) :: NeedLogMap !< whether a y_op values should contain log maps instead of full orientation matrices + + INTEGER(IntKi) :: index, i, dof + INTEGER(IntKi) :: nu + INTEGER(IntKi) :: ny + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_GetOP' + LOGICAL :: FieldMask(FIELDMASK_SIZE) + LOGICAL :: ReturnLogMap + TYPE(BD_ContinuousStateType) :: dx ! derivative of continuous states at operating point + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( u_op ) ) THEN + + nu = size(p%Jac_u_indx,1) + u%RootMotion%NNodes * 6 ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM (thus 6 more per node) + + if (.not. allocated(u_op)) then + call AllocAry(u_op, nu, 'u_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + index = 1 + FieldMask = .false. + FieldMask(MASKID_TranslationDisp) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TranslationVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TranslationAcc) = .true. + FieldMask(MASKID_RotationAcc) = .true. + call PackMotionMesh(u%RootMotion, u_op, index, FieldMask=FieldMask) + + call PackLoadMesh(u%PointLoad, u_op, index) + call PackLoadMesh(u%DistrLoad, u_op, index) + + END IF + + + IF ( PRESENT( y_op ) ) THEN + if (present(NeedLogMap)) then + ReturnLogMap = NeedLogMap + else + ReturnLogMap = .false. + end if + + if (.not. allocated(y_op)) then + ny = p%Jac_ny + y%BldMotion%NNodes * 6 ! Jac_ny has 3 orientation angles, but the OP needs the full 9 elements of the DCM (thus 6 more per node) + + call AllocAry(y_op, ny, 'y_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + index = 1 + call PackLoadMesh(y%ReactionForce, y_op, index) + + FieldMask = .false. + FieldMask(MASKID_TranslationDisp) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TranslationVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TranslationAcc) = .true. + FieldMask(MASKID_RotationAcc) = .true. + call PackMotionMesh(y%BldMotion, y_op, index, FieldMask=FieldMask, UseLogMaps=ReturnLogMap) + + index = index - 1 + do i=1,p%NumOuts + p%BldNd_TotNumOuts + y_op(i+index) = y%WriteOutput(i) + end do + + + END IF + + IF ( PRESENT( x_op ) ) THEN + + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%Jac_nx * 2,'x_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + index = 1 + do i=2,p%node_total + do dof=1,p%dof_node + x_op(index) = x%q( dof, i ) + index = index+1 + end do + end do + + do i=2,p%node_total + do dof=1,p%dof_node + x_op(index) = x%dqdt( dof, i ) + index = index+1 + end do + end do + + END IF + + IF ( PRESENT( dx_op ) ) THEN + + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%Jac_nx * 2,'dx_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + call BD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call BD_DestroyContState( dx, ErrStat2, ErrMsg2) + return + end if + + index = 1 + do i=2,p%node_total + do dof=1,p%dof_node + dx_op(index) = dx%q( dof, i ) + index = index+1 + end do + end do + + do i=2,p%node_total + do dof=1,p%dof_node + dx_op(index) = dx%dqdt( dof, i ) + index = index+1 + end do + end do + + call BD_DestroyContState( dx, ErrStat2, ErrMsg2) + + END IF + + IF ( PRESENT( xd_op ) ) THEN + + END IF + + IF ( PRESENT( z_op ) ) THEN + ! this is a little weird, but seems to be how BD has implemented the first node in the continuous state array. + + if (.not. allocated(z_op)) then + call AllocAry(z_op, p%dof_node * 2,'z_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + index = 1 + do dof=1,p%dof_node + z_op(index) = x%q( dof, 1 ) + index = index+1 + end do + + do dof=1,p%dof_node + z_op(index) = x%dqdt( dof, 1 ) + index = index+1 + end do + + END IF + +END SUBROUTINE BD_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +SUBROUTINE BD_WriteMassStiff( p, m, ErrStat, ErrMsg ) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables ! intent(out) so that we can update the accelerations here... + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= + + CHARACTER(*), PARAMETER :: RoutineName = 'BD_WriteMassStiff' + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + IF (m%Un_Sum <= 0) THEN + CAll SetErrStat( ErrID_Severe, ' Output file unit already closed. Cannot write mass and stiffness matrices.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Write out the mass and stiffness in the calculation frame + WRITE(m%Un_Sum,'()') + CALL WrMatrix(RESHAPE(m%StifK, (/p%dof_total, p%dof_total/)), m%Un_Sum, p%OutFmt, 'Full stiffness matrix (BD calculation coordinate frame)') + WRITE(m%Un_Sum,'()') + CALL WrMatrix(RESHAPE(m%MassM, (/p%dof_total, p%dof_total/)), m%Un_Sum, p%OutFmt, 'Full mass matrix (BD calculation coordinate frame)') + + RETURN + +END SUBROUTINE BD_WriteMassStiff +!---------------------------------------------------------------------------------------------------------------------------------- + + +SUBROUTINE BD_WriteMassStiffInFirstNodeFrame( p, x, m, ErrStat, ErrMsg ) + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables ! intent(out) so that we can update the accelerations here... + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= + + REAL(BDKi), ALLOCATABLE :: TmpStifK(:,:) ! temporary array for holding the stiffness matrix for coordinate transform before writing to file + REAL(BDKi), ALLOCATABLE :: TmpMassM(:,:) ! temporary array for holding the Mass matrix for coordinate transform before writing to file + REAL(BDKi) :: TmpRR0Local(3,3) + REAL(BDKi) :: tempR6(6,6) + INTEGER :: i + INTEGER :: j + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_WriteMassStiffInFirstNodeFrame' + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + IF (m%Un_Sum <= 0) THEN + CAll SetErrStat( ErrID_Severe, ' Output file unit already closed. Cannot write mass and stiffness matrices.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Rotate the total mass and stiffness matrices into the first node coordinate frame + CALL AllocAry(TmpStifK, p%dof_total,p%dof_total, 'TmpStifK', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(TmpMassM, p%dof_total,p%dof_total, 'TmpMassM', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Find transpose of DCM for first node + CALL BD_CrvMatrixR(x%q(4:6,1),TmpRR0Local) ! Transpose of DCM for first node of blade + + ! Create the 6x6 needed for conversion. See the calculations of m%qp%StifK for why + tempR6=0.0_BDKi + tempR6(1:3,1:3) = TmpRR0Local + tempR6(4:6,4:6) = TmpRR0Local + + do i=1,p%Node_Total + do j=1,p%Node_Total + TmpStifK( (j-1)*p%dof_node+1:j*p%dof_node, (i-1)*p%dof_node+1:i*p%dof_node ) = MATMUL( transpose(tempR6), MATMUL( m%StifK(:,j,:,i), tempR6 )) + TmpMassM( (j-1)*p%dof_node+1:j*p%dof_node, (i-1)*p%dof_node+1:i*p%dof_node ) = MATMUL( transpose(tempR6), MATMUL( m%MassM(:,j,:,i), tempR6 )) + enddo + enddo + + ! Write out the mass and stiffness in the first node frame + WRITE(m%Un_Sum,'()') + CALL WrMatrix(RESHAPE(TmpStifK, (/p%dof_total, p%dof_total/)), m%Un_Sum, p%OutFmt, 'Full stiffness matrix (IEC blade first node coordinate frame)') + WRITE(m%Un_Sum,'()') + CALL WrMatrix(RESHAPE(TmpMassM, (/p%dof_total, p%dof_total/)), m%Un_Sum, p%OutFmt, 'Full mass matrix (IEC blade first node coordinate frame)') + + + + CALL Cleanup() + RETURN + + + CONTAINS + SUBROUTINE Cleanup() + IF (ALLOCATED( TmpStifK )) DEALLOCATE( TmpStifK ) + IF (ALLOCATED( TmpMassM )) DEALLOCATE( TmpMassM ) + END SUBROUTINE cleanup +END SUBROUTINE BD_WriteMassStiffInFirstNodeFrame +!---------------------------------------------------------------------------------------------------------------------------------- + + +!----------------------------------------------------------------------------------------------------------------------------------- +END MODULE BeamDyn diff --git a/OpenFAST/modules/beamdyn/src/BeamDyn_BldNdOuts_IO.f90 b/OpenFAST/modules/beamdyn/src/BeamDyn_BldNdOuts_IO.f90 new file mode 100644 index 000000000..9cc98cb5d --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/BeamDyn_BldNdOuts_IO.f90 @@ -0,0 +1,1494 @@ +! This module is an add on to BeamDyn to allow output of data at each blade node. +! +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +MODULE BeamDyn_BldNdOuts_IO + + USE NWTC_Library + USE NWTC_LAPACK + USE BeamDyn_Subs + USE BeamDyn_Types + + IMPLICIT NONE + + PRIVATE + + + ! Outstanding issues + ! 1. Currently nothing is added to the summary file. If we add some output there, some changes either in the BeamDyn + ! code (as distributed) will be needed, or changes here (reopen file and append). + + + PUBLIC :: BldNdOuts_InitOut + PUBLIC :: Calc_WriteBldNdOutput + PUBLIC :: BldNdOuts_SetParameters + + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen-6 ! We are making these of the form B1Z###quantity, but note that the glue code adds the "B1" (turbine component) part + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 12-Dec-2017 20:48:14. + + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + + + ! Sectional Loads: + + INTEGER(IntKi), PARAMETER :: BldNd_FxL = 1 + INTEGER(IntKi), PARAMETER :: BldNd_FyL = 2 + INTEGER(IntKi), PARAMETER :: BldNd_FzL = 3 + INTEGER(IntKi), PARAMETER :: BldNd_MxL = 4 + INTEGER(IntKi), PARAMETER :: BldNd_MyL = 5 + INTEGER(IntKi), PARAMETER :: BldNd_MzL = 6 + INTEGER(IntKi), PARAMETER :: BldNd_Fxr = 7 + INTEGER(IntKi), PARAMETER :: BldNd_Fyr = 8 + INTEGER(IntKi), PARAMETER :: BldNd_Fzr = 9 + INTEGER(IntKi), PARAMETER :: BldNd_Mxr = 10 + INTEGER(IntKi), PARAMETER :: BldNd_Myr = 11 + INTEGER(IntKi), PARAMETER :: BldNd_Mzr = 12 + + + ! Sectional Motions: + + INTEGER(IntKi), PARAMETER :: BldNd_TDxr = 13 + INTEGER(IntKi), PARAMETER :: BldNd_TDyr = 14 + INTEGER(IntKi), PARAMETER :: BldNd_TDzr = 15 + INTEGER(IntKi), PARAMETER :: BldNd_RDxr = 16 + INTEGER(IntKi), PARAMETER :: BldNd_RDyr = 17 + INTEGER(IntKi), PARAMETER :: BldNd_RDzr = 18 + INTEGER(IntKi), PARAMETER :: BldNd_AbsXg = 19 + INTEGER(IntKi), PARAMETER :: BldNd_AbsYg = 20 + INTEGER(IntKi), PARAMETER :: BldNd_AbsZg = 21 + INTEGER(IntKi), PARAMETER :: BldNd_AbsXr = 22 + INTEGER(IntKi), PARAMETER :: BldNd_AbsYr = 23 + INTEGER(IntKi), PARAMETER :: BldNd_AbsZr = 24 + INTEGER(IntKi), PARAMETER :: BldNd_TVxg = 25 + INTEGER(IntKi), PARAMETER :: BldNd_TVyg = 26 + INTEGER(IntKi), PARAMETER :: BldNd_TVzg = 27 + INTEGER(IntKi), PARAMETER :: BldNd_TVxl = 28 + INTEGER(IntKi), PARAMETER :: BldNd_TVyl = 29 + INTEGER(IntKi), PARAMETER :: BldNd_TVzl = 30 + INTEGER(IntKi), PARAMETER :: BldNd_TVxr = 31 + INTEGER(IntKi), PARAMETER :: BldNd_TVyr = 32 + INTEGER(IntKi), PARAMETER :: BldNd_TVzr = 33 + INTEGER(IntKi), PARAMETER :: BldNd_RVxg = 34 + INTEGER(IntKi), PARAMETER :: BldNd_RVyg = 35 + INTEGER(IntKi), PARAMETER :: BldNd_RVzg = 36 + INTEGER(IntKi), PARAMETER :: BldNd_RVxl = 37 + INTEGER(IntKi), PARAMETER :: BldNd_RVyl = 38 + INTEGER(IntKi), PARAMETER :: BldNd_RVzl = 39 + INTEGER(IntKi), PARAMETER :: BldNd_RVxr = 40 + INTEGER(IntKi), PARAMETER :: BldNd_RVyr = 41 + INTEGER(IntKi), PARAMETER :: BldNd_RVzr = 42 + INTEGER(IntKi), PARAMETER :: BldNd_TAxl = 43 + INTEGER(IntKi), PARAMETER :: BldNd_TAyl = 44 + INTEGER(IntKi), PARAMETER :: BldNd_TAzl = 45 + INTEGER(IntKi), PARAMETER :: BldNd_TAxr = 46 + INTEGER(IntKi), PARAMETER :: BldNd_TAyr = 47 + INTEGER(IntKi), PARAMETER :: BldNd_TAzr = 48 + INTEGER(IntKi), PARAMETER :: BldNd_RAxl = 49 + INTEGER(IntKi), PARAMETER :: BldNd_RAyl = 50 + INTEGER(IntKi), PARAMETER :: BldNd_RAzl = 51 + INTEGER(IntKi), PARAMETER :: BldNd_RAxr = 52 + INTEGER(IntKi), PARAMETER :: BldNd_RAyr = 53 + INTEGER(IntKi), PARAMETER :: BldNd_RAzr = 54 + + ! Applied Loads: + + INTEGER(IntKi), PARAMETER :: BldNd_PFxL = 55 + INTEGER(IntKi), PARAMETER :: BldNd_PFyL = 56 + INTEGER(IntKi), PARAMETER :: BldNd_PFzL = 57 + INTEGER(IntKi), PARAMETER :: BldNd_PMxL = 58 + INTEGER(IntKi), PARAMETER :: BldNd_PMyL = 59 + INTEGER(IntKi), PARAMETER :: BldNd_PMzL = 60 + INTEGER(IntKi), PARAMETER :: BldNd_DFxL = 61 + INTEGER(IntKi), PARAMETER :: BldNd_DFyL = 62 + INTEGER(IntKi), PARAMETER :: BldNd_DFzL = 63 + INTEGER(IntKi), PARAMETER :: BldNd_DMxL = 64 + INTEGER(IntKi), PARAMETER :: BldNd_DMyL = 65 + INTEGER(IntKi), PARAMETER :: BldNd_DMzL = 66 + INTEGER(IntKi), PARAMETER :: BldNd_DFxR = 67 + INTEGER(IntKi), PARAMETER :: BldNd_DFyR = 68 + INTEGER(IntKi), PARAMETER :: BldNd_DFzR = 69 + INTEGER(IntKi), PARAMETER :: BldNd_DMxR = 70 + INTEGER(IntKi), PARAMETER :: BldNd_DMyR = 71 + INTEGER(IntKi), PARAMETER :: BldNd_DMzR = 72 + + + ! Sectional Partial Loads (debugging): + + INTEGER(IntKi), PARAMETER :: BldNd_FFbxl = 73 + INTEGER(IntKi), PARAMETER :: BldNd_FFbyl = 74 + INTEGER(IntKi), PARAMETER :: BldNd_FFbzl = 75 + INTEGER(IntKi), PARAMETER :: BldNd_FFbxr = 76 + INTEGER(IntKi), PARAMETER :: BldNd_FFbyr = 77 + INTEGER(IntKi), PARAMETER :: BldNd_FFbzr = 78 + INTEGER(IntKi), PARAMETER :: BldNd_MFbxl = 79 + INTEGER(IntKi), PARAMETER :: BldNd_MFbyl = 80 + INTEGER(IntKi), PARAMETER :: BldNd_MFbzl = 81 + INTEGER(IntKi), PARAMETER :: BldNd_MFbxr = 82 + INTEGER(IntKi), PARAMETER :: BldNd_MFbyr = 83 + INTEGER(IntKi), PARAMETER :: BldNd_MFbzr = 84 + INTEGER(IntKi), PARAMETER :: BldNd_FFcxl = 85 + INTEGER(IntKi), PARAMETER :: BldNd_FFcyl = 86 + INTEGER(IntKi), PARAMETER :: BldNd_FFczl = 87 + INTEGER(IntKi), PARAMETER :: BldNd_FFcxr = 88 + INTEGER(IntKi), PARAMETER :: BldNd_FFcyr = 89 + INTEGER(IntKi), PARAMETER :: BldNd_FFczr = 90 + INTEGER(IntKi), PARAMETER :: BldNd_MFcxl = 91 + INTEGER(IntKi), PARAMETER :: BldNd_MFcyl = 92 + INTEGER(IntKi), PARAMETER :: BldNd_MFczl = 93 + INTEGER(IntKi), PARAMETER :: BldNd_MFcxr = 94 + INTEGER(IntKi), PARAMETER :: BldNd_MFcyr = 95 + INTEGER(IntKi), PARAMETER :: BldNd_MFczr = 96 + INTEGER(IntKi), PARAMETER :: BldNd_FFdxl = 97 + INTEGER(IntKi), PARAMETER :: BldNd_FFdyl = 98 + INTEGER(IntKi), PARAMETER :: BldNd_FFdzl = 99 + INTEGER(IntKi), PARAMETER :: BldNd_FFdxr = 100 + INTEGER(IntKi), PARAMETER :: BldNd_FFdyr = 101 + INTEGER(IntKi), PARAMETER :: BldNd_FFdzr = 102 + INTEGER(IntKi), PARAMETER :: BldNd_MFdxl = 103 + INTEGER(IntKi), PARAMETER :: BldNd_MFdyl = 104 + INTEGER(IntKi), PARAMETER :: BldNd_MFdzl = 105 + INTEGER(IntKi), PARAMETER :: BldNd_MFdxr = 106 + INTEGER(IntKi), PARAMETER :: BldNd_MFdyr = 107 + INTEGER(IntKi), PARAMETER :: BldNd_MFdzr = 108 + INTEGER(IntKi), PARAMETER :: BldNd_FFgxl = 109 + INTEGER(IntKi), PARAMETER :: BldNd_FFgyl = 110 + INTEGER(IntKi), PARAMETER :: BldNd_FFgzl = 111 + INTEGER(IntKi), PARAMETER :: BldNd_FFgxr = 112 + INTEGER(IntKi), PARAMETER :: BldNd_FFgyr = 113 + INTEGER(IntKi), PARAMETER :: BldNd_FFgzr = 114 + INTEGER(IntKi), PARAMETER :: BldNd_MFgxl = 115 + INTEGER(IntKi), PARAMETER :: BldNd_MFgyl = 116 + INTEGER(IntKi), PARAMETER :: BldNd_MFgzl = 117 + INTEGER(IntKi), PARAMETER :: BldNd_MFgxr = 118 + INTEGER(IntKi), PARAMETER :: BldNd_MFgyr = 119 + INTEGER(IntKi), PARAMETER :: BldNd_MFgzr = 120 + INTEGER(IntKi), PARAMETER :: BldNd_FFixl = 121 + INTEGER(IntKi), PARAMETER :: BldNd_FFiyl = 122 + INTEGER(IntKi), PARAMETER :: BldNd_FFizl = 123 + INTEGER(IntKi), PARAMETER :: BldNd_FFixr = 124 + INTEGER(IntKi), PARAMETER :: BldNd_FFiyr = 125 + INTEGER(IntKi), PARAMETER :: BldNd_FFizr = 126 + INTEGER(IntKi), PARAMETER :: BldNd_MFixl = 127 + INTEGER(IntKi), PARAMETER :: BldNd_MFiyl = 128 + INTEGER(IntKi), PARAMETER :: BldNd_MFizl = 129 + INTEGER(IntKi), PARAMETER :: BldNd_MFixr = 130 + INTEGER(IntKi), PARAMETER :: BldNd_MFiyr = 131 + INTEGER(IntKi), PARAMETER :: BldNd_MFizr = 132 + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER, PUBLIC :: BldNd_MaxOutPts = 132 + +!End of code generated by Matlab script +! =================================================================================================== + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is blade:node:channel (channel iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteBldNdOutput routine as well. +SUBROUTINE BldNdOuts_InitOut( InitOut, p, ErrStat, ErrMsg ) + + + TYPE(BD_InitOutputType), INTENT(INOUT) :: InitOut ! output data + TYPE(BD_ParameterType), INTENT(IN ) :: p ! The module parameters + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + INTEGER(IntKi) :: ErrStat2 ! Error status code + INTEGER(IntKi) :: INDX ! Index count within WriteOutput + INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(1) :: ChanPrefix ! Name prefix (B#_ -- note that the B# part is added in FAST, not here) + CHARACTER(4), ALLOCATABLE :: DistStr(:) ! Array of prefix (Z######y) + CHARACTER(3) :: TmpChar ! Temporary char array to hold the node digits (3 places only!!!!) + CHARACTER(*), PARAMETER :: RoutineName = ('BldNdOuts_InitOut') + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + + IF ( p%BldNd_NumOuts == 0 ) THEN + return + ENDIF + + ! create the channel names using the z-coordinate of the beam in mm + ALLOCATE( DistStr(size(p%BldNd_BlOutNd)), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + call SetErrStat(ErrID_Fatal, 'Error allocating DistStr array.', ErrStat, ErrMsg, RoutineName) + return + END IF + + ! Warn if we will run into issues with more than 999 nodes. + IF (p%node_total > 999 ) CALL SetErrStat(ErrID_Severe,'More than 999 blade nodes in use. Output channel headers will not '// & + 'correctly reflect blade stations beyond 999. Modifications to the variable ChanLen in FAST are required.',ErrStat,ErrMsg,RoutineName) + + DO IdxNode=1,size(p%BldNd_BlOutNd) + ! Create the name prefix: + WRITE (TmpChar,'(I3.3)') IdxNode + DistStr(IdxNode) = 'N' // TmpChar + END DO + + + ! Populate the header an unit lines for all blades and nodes + ! First set a counter so we know where in the output array we are in + ! NOTE: we populate invalid names as well (some names are not valid outputs for certain configurations). That means we will have zeros in those values. + INDX = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal BeamDyn output. The WriteOutput array is sized to p%NumOuts + num(BldNdOuts) + + +! ChanPrefix = '_' !newer names have underscore character to deliniate between sections + ChanPrefix = '' + ! Loop through all the outputs we requested here: + DO IdxChan=1,p%BldNd_NumOuts + + DO IdxNode=1,size(p%BldNd_BlOutNd) + + ! Now write to the header + InitOut%WriteOutputHdr(INDX) = TRIM(ChanPrefix) // TRIM(DistStr(IdxNode)) // p%BldNd_OutParam(IdxChan)%Name + InitOut%WriteOutputUnt(INDX) = p%BldNd_OutParam(IdxChan)%Units + + ! Increment the index to the Header arrays + INDX = INDX + 1 + + ENDDO + + ENDDO + + IF (ALLOCATED(DistStr)) DEALLOCATE(DistStr) + + +END SUBROUTINE BldNdOuts_InitOut + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is blade:node:channel (channel iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteBldNdOutput routine as well. +SUBROUTINE Calc_WriteBldNdOutput( p, m, y, ErrStat, ErrMsg ) + TYPE(BD_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(BD_MiscVarType), INTENT(INOUT) :: m ! misc variables + TYPE(BD_OutputType), INTENT(INOUT) :: y ! outputs + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + INTEGER(IntKi) :: IdxOutList ! Index within WriteOutput + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteBldNdOutput' + + + ! temporary variables for calculation + INTEGER(IntKi) :: idx_node_in_elem ! node on current element + INTEGER(IntKi) :: nelem ! current element + INTEGER(IntKi) :: idx_node ! Counter to the blade node we are on + INTEGER(IntKi) :: compIndx ! index for array component (x,y,z) + REAL(BDKi) :: Tmp33a(3,3) ! Temporary 3x4 for orientation calcs + REAL(BDKi) :: Tmp33b(3,3) ! Temporary 3x4 for orientation calcs + + REAL(BDKi) :: WM_ParamRD(3) ! Wiener Milenkovic parameters for current node, in Global coordinates + REAL(BDKi) :: temp_vec(3) ! temporary vector for orientation info. + REAL(BDKi) :: temp_vec2(3) ! temporary vector for orientation info. + REAL(BDKi) :: temp_vec3(3) ! temporary vector for orientation info. + REAL(BDKi) :: d_ref(3) ! root displacement + REAL(BDKi) :: d(3) ! displacement + + ! WM param finding + REAL(BDKi) :: RootRelOrient(3,3) + + ! Error handling + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + IF ( p%BldNd_NumOuts == 0 ) THEN + return + ENDIF + + + ! Set the root rotation DCM relative to the reference. + ! NOTE: the orientations used in this routine are DCM's. These are directly from the mesh. + call LAPACK_DGEMM('T', 'N', 1.0_BDKi, m%u2%RootMotion%Orientation(:,:,1), m%u2%RootMotion%RefOrientation(:,:,1), 0.0_BDKi, RootRelOrient, ErrStat2, ErrMsg2 ) + + + ! Loop over the channel sets + DO IdxChan=1,p%BldNd_NumOuts + + + ! Case to assign output to this channel and populate based on Indx value (this indicates what the channel is) + ! Logic and mathematics used here come from Calc_WriteOutput + + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + + CASE (0) ! This is an invalid channel so we'll just skip it + CYCLE + + !---------------------------------------- + ! Sectional translational locations and deflections (relative to the undeflected position) expressed in g + CASE (BldNd_AbsXg,BldNd_AbsYg,BldNd_AbsZg) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_AbsXg) + compIndx = 1 + CASE (BldNd_AbsYg) + compIndx = 2 + CASE (BldNd_AbsZg) + compIndx = 3 + END SELECT + + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + d = y%BldMotion%TranslationDisp(:, idx_node) + d_ref = y%BldMotion%Position( :, idx_node) + ! For actual global location + temp_vec = d + d_ref + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + !---------------------------------------- + ! Sectional translational locations and deflections (relative to the undeflected position) expressed in r + CASE (BldNd_TDxr,BldNd_TDyr,BldNd_TDzr,BldNd_AbsXr,BldNd_AbsYr,BldNd_AbsZr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + d = y%BldMotion%TranslationDisp(:, idx_node) - m%u2%RootMotion%TranslationDisp(:,1) + d_ref = y%BldMotion%Position( :, idx_node) - m%u2%RootMotion%Position( :,1) + ! For relative change in location + temp_vec2 = d + d_ref - matmul( RootRelOrient, d_ref ) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) + ! For actual location relative to root + temp_vec2 = d + d_ref + temp_vec3 = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_TDxr) + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_TDyr) + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_TDzr) + y%WriteOutput( IdxOutList ) = temp_vec(3) + CASE (BldNd_AbsXr) + y%WriteOutput( IdxOutList ) = temp_vec3(1) + CASE (BldNd_AbsYr) + y%WriteOutput( IdxOutList ) = temp_vec3(2) + CASE (BldNd_AbsZr) + y%WriteOutput( IdxOutList ) = temp_vec3(3) + END SELECT + ENDDO + + + + !---------------------------------------- + ! Rotational displacements as W-M parameters + CASE ( BldNd_RDxr, BldNd_RDyr, BldNd_RDzr ) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_RDxr) + compIndx = 1 + CASE (BldNd_RDyr) + compIndx = 2 + CASE (BldNd_RDzr) + compIndx = 3 + END SELECT + + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + + !------------------------- +!FIXME: we are not trapping errors here. Do we need to? + ! Sectional angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) expressed in r + call LAPACK_DGEMM('N', 'T', 1.0_BDKi, y%BldMotion%RefOrientation(:,:,idx_node), RootRelOrient, 0.0_BDKi, Tmp33b, ErrStat2, ErrMsg2 ) + call LAPACK_DGEMM('T', 'N', 1.0_BDKi, y%BldMotion%Orientation( :,:,idx_node), Tmp33b, 0.0_BDKi, Tmp33a, ErrStat2, ErrMsg2 ) + call BD_CrvExtractCrv(Tmp33a,temp_vec2, ErrStat2, ErrMsg2) ! temp_vec2 = the Wiener-Milenkovic parameters of the node's angular/rotational defelctions + WM_ParamRD = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) ! Rotate the parameters to the correct coordinate system for output + + y%WriteOutput( IdxOutList ) = WM_ParamRD(compIndx) + END DO + + + !---------------------------------------- + ! Translational Velocities, global frame + CASE (BldNd_TVxg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%TranslationVel(1,idx_node) + ENDDO + CASE (BldNd_TVyg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%TranslationVel(2,idx_node) + ENDDO + CASE (BldNd_TVzg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%TranslationVel(3,idx_node) + ENDDO + !---------------------------------------- + ! Rotational Velocities, global frame + CASE (BldNd_RVxg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%RotationVel(1,idx_node) * R2D + ENDDO + CASE (BldNd_RVyg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%RotationVel(2,idx_node) * R2D + ENDDO + CASE (BldNd_RVzg) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + y%WriteOutput( IdxOutList ) = y%BldMotion%RotationVel(3,idx_node) * R2D + ENDDO + + + !---------------------------------------- + ! Translational Velocities, local frame + CASE (BldNd_TVxl,BldNd_TVyl,BldNd_TVzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_TVxl) + compIndx = 1 + CASE (BldNd_TVyl) + compIndx = 2 + CASE (BldNd_TVzl) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node),y%BldMotion%TranslationVel(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + !---------------------------------------- + ! Rotational Velocities, local frame + CASE (BldNd_RVxl,BldNd_RVyl,BldNd_RVzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_RVxl) + compIndx = 1 + CASE (BldNd_RVyl) + compIndx = 2 + CASE (BldNd_RVzl) + compIndx = 3 + END SELECT + + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node),y%BldMotion%RotationVel(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx)*R2D + ENDDO + + + !---------------------------------------- + ! Translational Velocities, root frame + CASE (BldNd_TVxr,BldNd_TVyr,BldNd_TVzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_TVxr) + compIndx = 1 + CASE (BldNd_TVyr) + compIndx = 2 + CASE (BldNd_TVzr) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%BldMotion%TranslationVel(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + !---------------------------------------- + ! Rotational Velocities, root frame + CASE (BldNd_RVxr,BldNd_RVyr,BldNd_RVzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_RVxr) + compIndx = 1 + CASE (BldNd_RVyr) + compIndx = 2 + CASE (BldNd_RVzr) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%BldMotion%RotationVel(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx)*R2D + ENDDO + + + !---------------------------------------- + ! Translational Accelerations, local frame + CASE (BldNd_TAxl, BldNd_TAyl, BldNd_TAzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_TAxl) + compIndx = 1 + CASE (BldNd_TAyl) + compIndx = 2 + CASE (BldNd_TAzl) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node),y%BldMotion%TranslationAcc(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + !---------------------------------------- + ! Rotational Accelerations, local frame + CASE (BldNd_RAxl, BldNd_RAyl, BldNd_RAzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_RAxl) + compIndx = 1 + CASE (BldNd_RAyl) + compIndx = 2 + CASE (BldNd_RAzl) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node),y%BldMotion%RotationAcc(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx)*R2D + ENDDO + + + !---------------------------------------- + ! Translational Accelerations, root frame + CASE (BldNd_TAxr, BldNd_TAyr, BldNd_TAzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_TAxr) + compIndx = 1 + CASE (BldNd_TAyr) + compIndx = 2 + CASE (BldNd_TAzr) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%BldMotion%TranslationAcc(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + !---------------------------------------- + ! Rotational Accelerations, root frame + CASE (BldNd_RAxr, BldNd_RAyr, BldNd_RAzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_RAxr) + compIndx = 1 + CASE (BldNd_RAyr) + compIndx = 2 + CASE (BldNd_RAzr) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%BldMotion%RotationAcc(:,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx)*R2D + ENDDO + + !---------------------------------------- + ! Applied point forces, local coordinate system. Not used when coupled to FAST. + CASE (BldNd_PFxl,BldNd_PFyl,BldNd_PFzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_PFxl) + compIndx = 1 + CASE (BldNd_PFyl) + compIndx = 2 + CASE (BldNd_PFzl) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_FE) THEN + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%u2%PointLoad%Force( :,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else ! we need to do a mesh mapping first +!FIXME: this is not implemented yet. + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + y%WriteOutput( IdxOutList ) = 0.0_ReKi + ENDDO + end if + + !---------------------------------------- + ! Applied point moments, local coordinate system. Not used when coupled to FAST. + CASE (BldNd_PMxl, BldNd_PMyl, BldNd_PMzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_PMxl) + compIndx = 1 + CASE (BldNd_PMyl) + compIndx = 2 + CASE (BldNd_PMzl) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + y%WriteOutput( IdxOutList ) = 0.0_ReKi + ENDDO + if (p%BldMotionNodeLoc == BD_MESH_FE) THEN + DO idx_node=1,y%BldMotion%NNodes + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%u2%PointLoad%Moment( :,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else ! we need to do a mesh mapping first +!FIXME: this is not implemented yet. + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + y%WriteOutput( IdxOutList ) = 0.0_ReKi + ENDDO + end if + + !---------------------------------------- + ! Applied distributed forces (from AD15 when coupled to FAST), local frame + CASE (BldNd_DFxl,BldNd_DFyl,BldNd_DFzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_DFxl) + compIndx = 1 + CASE (BldNd_DFyl) + compIndx = 2 + CASE (BldNd_DFzl) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) THEN ! If we are on the quadrature points, the input and output meshes are siblings + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%u2%DistrLoad%Force( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u_DistrLoad_at_y%Force( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + !---------------------------------------- + ! Applied distributed moments (from AD15 when coupled to FAST), local frame + CASE (BldNd_DMxl,BldNd_DMyl,BldNd_DMzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_DMxl) + compIndx = 1 + CASE (BldNd_DMyl) + compIndx = 2 + CASE (BldNd_DMzl) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) THEN ! If we are on the quadrature points, the input and output meshes are siblings + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%u2%DistrLoad%Moment( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u_DistrLoad_at_y%Moment( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + + !---------------------------------------- + ! Applied distributed forces (from AD15 when coupled to FAST), root frame + CASE (BldNd_DFxr,BldNd_DFyr,BldNd_DFzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_DFxr) + compIndx = 1 + CASE (BldNd_DFyr) + compIndx = 2 + CASE (BldNd_DFzr) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) THEN ! If we are on the quadrature points, the input and output meshes are siblings + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u2%DistrLoad%Force( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u_DistrLoad_at_y%Force( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + !---------------------------------------- + ! Applied distributed moments (from AD15 when coupled to FAST), root frame + CASE (BldNd_DMxr,BldNd_DMyr,BldNd_DMzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_DMxr) + compIndx = 1 + CASE (BldNd_DMyr) + compIndx = 2 + CASE (BldNd_DMzr) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) THEN ! If we are on the quadrature points, the input and output meshes are siblings + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u2%DistrLoad%Moment( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%u_DistrLoad_at_y%Moment( :,idx_node)) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + + + !---------------------------------------- + ! Internal Forces, local + CASE (BldNd_Fxl,BldNd_Fyl,BldNd_Fzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_Fxl) + compIndx = 1 + CASE (BldNd_Fyl) + compIndx = 2 + CASE (BldNd_Fzl) + compIndx = 3 + END SELECT + + if (p%BldMotionNodeLoc == BD_MESH_QP) then + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%BldInternalForceQP(1:3,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%BldInternalForceFE(1:3,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + + !---------------------------------------- + ! Internal Moments, local + CASE (BldNd_Mxl,BldNd_Myl,BldNd_Mzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_Mxl) + compIndx = 1 + CASE (BldNd_Myl) + compIndx = 2 + CASE (BldNd_Mzl) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) then + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%BldInternalForceQP(4:6,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), m%BldInternalForceFE(4:6,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + + !---------------------------------------- + ! Internal Forces, root frame + CASE (BldNd_Fxr,BldNd_Fyr,BldNd_Fzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_Fxr) + compIndx = 1 + CASE (BldNd_Fyr) + compIndx = 2 + CASE (BldNd_Fzr) + compIndx = 3 + END SELECT + if (p%BldMotionNodeLoc == BD_MESH_QP) then + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%BldInternalForceQP(1:3,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%BldInternalForceFE(1:3,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + + !---------------------------------------- + ! Internal Moments, root frame + CASE (BldNd_Mxr,BldNd_Myr,BldNd_Mzr) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_Mxr) + compIndx = 1 + CASE (BldNd_Myr) + compIndx = 2 + CASE (BldNd_Mzr) + compIndx = 3 + END SELECT + + if (p%BldMotionNodeLoc == BD_MESH_QP) then + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%BldInternalForceQP(4:6,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + else + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%BldInternalForceFE(4:6,p%NdIndxInverse(idx_node))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + end if + +!>>> The remaining loads outputs are for debugging, and are not valid with BD_MESH_FE. We cannot get here in that case. + !---------------------------------------- + ! Internal forces from CalcOutput, local frame + CASE (BldNd_FFbxl,BldNd_FFbyl,BldNd_FFbzl) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) + CASE (BldNd_FFbxl) + compIndx = 1 + CASE (BldNd_FFbyl) + compIndx = 2 + CASE (BldNd_FFbzl) + compIndx = 3 + END SELECT + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fb(1:3,idx_node_in_elem,nelem))) + y%WriteOutput( IdxOutList ) = temp_vec(compIndx) + ENDDO + CASE (BldNd_MFbxl,BldNd_MFbyl,BldNd_MFbzl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fb(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFbxl) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFbyl) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFbzl) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFcxl,BldNd_FFcyl,BldNd_FFczl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fc(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFcxl) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFcyl) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFczl) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFcxl,BldNd_MFcyl,BldNd_MFczl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fc(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFcxl) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFcyl) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFczl) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFdxl,BldNd_FFdyl,BldNd_FFdzl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fd(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFdxl) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFdyl) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFdzl) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFdxl,BldNd_MFdyl,BldNd_MFdzl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fd(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFdxl) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFdyl) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFdzl) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFgxl,BldNd_FFgyl,BldNd_FFgzl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fg(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFgxl) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFgyl) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFgzl) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFgxl,BldNd_MFgyl,BldNd_MFgzl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fg(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFgxl) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFgyl) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFgzl) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + + + !---------------------------------------- + ! Internal forces from CalcOutput, local frame + CASE (BldNd_FFbxr,BldNd_FFbyr,BldNd_FFbzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fb(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFbxr) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFbyr) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFbzr) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFbxr,BldNd_MFbyr,BldNd_MFbzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fb(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFbxr) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFbyr) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFbzr) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFcxr,BldNd_FFcyr,BldNd_FFczr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fc(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFcxr) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFcyr) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFczr) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFcxr,BldNd_MFcyr,BldNd_MFczr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fc(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFcxr) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFcyr) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFczr) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFdxr,BldNd_FFdyr,BldNd_FFdzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fd(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFdxr) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFdyr) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFdzr) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFdxr,BldNd_MFdyr,BldNd_MFdzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fd(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFdxr) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFdyr) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFdzr) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + CASE (BldNd_FFgxr,BldNd_FFgyr,BldNd_FFgzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fg(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFgxr) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFgyr) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFgzr) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFgxr,BldNd_MFgyr,BldNd_MFgzr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), m%qp%Fg(4:6,idx_node_in_elem,nelem)) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFgxr) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFgyr) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFgzr) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + + !---------------------------------------- + ! Inertial force from UpdateStates (Includes a few other terms), local frame + CASE (BldNd_FFixl,BldNd_FFiyl,BldNd_FFizl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fi(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFixl) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFiyl) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFizl) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFixl,BldNd_MFiyl,BldNd_MFizl) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,idx_node), MATMUL(p%GlbRot,m%qp%Fi(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFixl) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFiyl) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFizl) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + !---------------------------------------- + ! Inertial force from UpdateStates (Includes a few other terms), root frame + CASE (BldNd_FFixr,BldNd_FFiyr,BldNd_FFizr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fi(1:3,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_FFixr) ! Gyroscopic force Fc x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_FFiyr) ! Gyroscopic force Fc y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_FFizr) ! Gyroscopic force Fc z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + CASE (BldNd_MFixr,BldNd_MFiyr,BldNd_MFizr) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes ! Index to current output + nelem = p%OutNd2NdElem(2,idx_node) + idx_node_in_elem = p%OutNd2NdElem(1,idx_node) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1), MATMUL(p%GlbRot,m%qp%Fi(4:6,idx_node_in_elem,nelem))) + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (BldNd_MFixr) ! Gyroscopic moment Fc about x, root frame + y%WriteOutput( IdxOutList ) = temp_vec(1) + CASE (BldNd_MFiyr) ! Gyroscopic moment Fc about y, root frame + y%WriteOutput( IdxOutList ) = temp_vec(2) + CASE (BldNd_MFizr) ! Gyroscopic moment Fc about z, root frame + y%WriteOutput( IdxOutList ) = temp_vec(3) + END SELECT + ENDDO + + + + CASE DEFAULT + CALL SetErrStat( ErrID_Severe, "Coding error. Output channel not properly set.",ErrStat,ErrMsg,RoutineName ) + DO idx_node=1,y%BldMotion%NNodes ! Note p%node_total is total number of nodes including all elements + IdxOutList = p%NumOuts + idx_node + (IdxChan-1)*y%BldMotion%NNodes + y%WriteOutput( IdxOutList ) = 0.0_ReKi + ENDDO + + END SELECT + + ENDDO ! Loop over the output channel list + + +END SUBROUTINE Calc_WriteBldNdOutput + +!.................................................................................................................................. +SUBROUTINE BldNdOuts_SetParameters(InitInp, InputFileData, p, ErrStat, ErrMsg) + type(BD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(BD_InputFile), intent(in ) :: InputFileData !< data from the input file + type(BD_ParameterType), intent(inout) :: p !< Parameters ! intent(out) only because it changes p%NdIndx + 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) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = ('BldNdOuts_SetParameters') + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + + + ! Set the parameter to store number of requested Blade Node output sets + p%BldNd_NumOuts = InputFileData%BldNd_NumOuts + + IF ( p%BldNd_NumOuts == 0 ) THEN + + p%BldNd_TotNumOuts = 0 ! default to no nodal outputs + + ELSE + + ! Check if the blade node array to output is valid: p%BldNd_BlOutNd + ! TODO: this value is not read in by the input file reading yet, so setting to all blade nodes + ! -- check if list handed in is of nodes that exist (not sure this is ever checked) + ! -- Make sure the nodes actually exist on the y%BldMotion mesh + ! -- Sort the order of the list handed in + ! -- copy values over + + + ! Temporary workaround here: + ALLOCATE ( p%BldNd_BlOutNd( size(p%NdIndxInverse) ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the BeamDyn BldNd_BlOutNd array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + DO I=1,size(p%BldNd_BlOutNd) + p%BldNd_BlOutNd(i) = i + ENDDO + + ! Set the total number of outputs ( requested channel groups * number requested nodes ) + p%BldNd_TotNumOuts = p%BldNd_NumOuts * SIZE(p%BldNd_BlOutNd) + + call BldNdOuts_SetOutParam(InputFileData%BldNd_OutList, p, ErrStat2, ErrMsg2 ) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + END IF + + +END SUBROUTINE BldNdOuts_SetParameters +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 12-Dec-2017 20:48:14. +SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: BldNd_OutList(:) !< The list out user-requested outputs + TYPE(BD_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 + + ! Local variables + + 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 :: InvalidOutput(1:BldNd_MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "BldNdOuts_SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(177) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ABSXG ","ABSXR ","ABSYG ","ABSYR ","ABSZG ", & + "ABSZR ","AXB ","AXL ","AYB ","AYL ","AZB ","AZL ", & + "DFXL ","DFXR ","DFYL ","DFYR ","DFZL ","DFZR ","DMXL ", & + "DMXR ","DMYL ","DMYR ","DMZL ","DMZR ","FFBXL ","FFBXR ","FFBYL ", & + "FFBYR ","FFBZL ","FFBZR ","FFCXL ","FFCXR ","FFCYL ","FFCYR ","FFCZL ", & + "FFCZR ","FFDXL ","FFDXR ","FFDYL ","FFDYR ","FFDZL ","FFDZR ","FFGXL ", & + "FFGXR ","FFGYL ","FFGYR ","FFGZL ","FFGZR ","FFIXL ","FFIXR ","FFIYL ", & + "FFIYR ","FFIZL ","FFIZR ","FXB ","FXL ","FXR ","FYB ","FYL ", & + "FYR ","FZB ","FZL ","FZR ","MFBXL ","MFBXR ","MFBYL ","MFBYR ", & + "MFBZL ","MFBZR ","MFCXL ","MFCXR ","MFCYL ","MFCYR ","MFCZL ","MFCZR ", & + "MFDXL ","MFDXR ","MFDYL ","MFDYR ","MFDZL ","MFDZR ","MFGXL ","MFGXR ", & + "MFGYL ","MFGYR ","MFGZL ","MFGZR ","MFIXL ","MFIXR ","MFIYL ","MFIYR ", & + "MFIZL ","MFIZR ","MXB ","MXL ","MXR ","MYB ","MYL ","MYR ", & + "MZB ","MZL ","MZR ","PFXL ","PFYL ","PFZL ","PMXL ","PMYL ", & + "PMZL ","PXB ","PXG ","PYB ","PYG ","PZB ","PZG ","QXB ", & + "QXL ","QYB ","QYL ","QZB ","QZL ","RAXL ","RAXR ","RAYL ", & + "RAYR ","RAZL ","RAZR ","RDXR ","RDYR ", & + "RDZR ","RVXG ","RVXL ","RVXR ","RVYG ","RVYL ","RVYR ","RVZG ", & + "RVZL ","RVZR ","TAXL ","TAXR ","TAYL ", & + "TAYR ","TAZL ","TAZR ","TDXR ","TDYR ","TDZR ", & + "TVXG ","TVXL ","TVXR ","TVYG ","TVYL ","TVYR ","TVZG ","TVZL ", & + "TVZR ","UXB ","UYB ","UZB ","VXB ","VXG ", & + "VXL ","VYB ","VYG ","VYL ","VZB ","VZG ","VZL ","WXB ", & + "WXG ","WXL ","WYB ","WYG ","WYL ","WZB ","WZG ","WZL "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(177) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + BldNd_AbsXg , BldNd_AbsXr , BldNd_AbsYg , BldNd_AbsYr , BldNd_AbsZg , & + BldNd_AbsZr , BldNd_TAxr , BldNd_TAxl , BldNd_TAyr , BldNd_TAyl , BldNd_TAzr , BldNd_TAzl , & + BldNd_DFxL , BldNd_DFxR , BldNd_DFyL , BldNd_DFyR , BldNd_DFzL , BldNd_DFzR , BldNd_DMxL , & + BldNd_DMxR , BldNd_DMyL , BldNd_DMyR , BldNd_DMzL , BldNd_DMzR , BldNd_FFbxl , BldNd_FFbxr , BldNd_FFbyl , & + BldNd_FFbyr , BldNd_FFbzl , BldNd_FFbzr , BldNd_FFcxl , BldNd_FFcxr , BldNd_FFcyl , BldNd_FFcyr , BldNd_FFczl , & + BldNd_FFczr , BldNd_FFdxl , BldNd_FFdxr , BldNd_FFdyl , BldNd_FFdyr , BldNd_FFdzl , BldNd_FFdzr , BldNd_FFgxl , & + BldNd_FFgxr , BldNd_FFgyl , BldNd_FFgyr , BldNd_FFgzl , BldNd_FFgzr , BldNd_FFixl , BldNd_FFixr , BldNd_FFiyl , & + BldNd_FFiyr , BldNd_FFizl , BldNd_FFizr , BldNd_Fxr , BldNd_FxL , BldNd_Fxr , BldNd_Fyr , BldNd_FyL , & + BldNd_Fyr , BldNd_Fzr , BldNd_FzL , BldNd_Fzr , BldNd_MFbxl , BldNd_MFbxr , BldNd_MFbyl , BldNd_MFbyr , & + BldNd_MFbzl , BldNd_MFbzr , BldNd_MFcxl , BldNd_MFcxr , BldNd_MFcyl , BldNd_MFcyr , BldNd_MFczl , BldNd_MFczr , & + BldNd_MFdxl , BldNd_MFdxr , BldNd_MFdyl , BldNd_MFdyr , BldNd_MFdzl , BldNd_MFdzr , BldNd_MFgxl , BldNd_MFgxr , & + BldNd_MFgyl , BldNd_MFgyr , BldNd_MFgzl , BldNd_MFgzr , BldNd_MFixl , BldNd_MFixr , BldNd_MFiyl , BldNd_MFiyr , & + BldNd_MFizl , BldNd_MFizr , BldNd_Mxr , BldNd_MxL , BldNd_Mxr , BldNd_Myr , BldNd_MyL , BldNd_Myr , & + BldNd_Mzr , BldNd_MzL , BldNd_Mzr , BldNd_PFxL , BldNd_PFyL , BldNd_PFzL , BldNd_PMxL , BldNd_PMyL , & + BldNd_PMzL , BldNd_AbsXr , BldNd_AbsXg , BldNd_AbsYr , BldNd_AbsYg , BldNd_AbsZr , BldNd_AbsZg , BldNd_RAxr , & + BldNd_RAxl , BldNd_RAyr , BldNd_RAyl , BldNd_RAzr , BldNd_RAzl , BldNd_RAxl , BldNd_RAxr , BldNd_RAyl , & + BldNd_RAyr , BldNd_RAzl , BldNd_RAzr , BldNd_RDxr , BldNd_RDyr , & + BldNd_RDzr , BldNd_RVxg , BldNd_RVxl , BldNd_RVxr , BldNd_RVyg , BldNd_RVyl , BldNd_RVyr , BldNd_RVzg , & + BldNd_RVzl , BldNd_RVzr , BldNd_TAxl , BldNd_TAxr , BldNd_TAyl , & + BldNd_TAyr , BldNd_TAzl , BldNd_TAzr , BldNd_TDxr , BldNd_TDyr , BldNd_TDzr , & + BldNd_TVxg , BldNd_TVxl , BldNd_TVxr , BldNd_TVyg , BldNd_TVyl , BldNd_TVyr , BldNd_TVzg , BldNd_TVzl , & + BldNd_TVzr , BldNd_TDxr , BldNd_TDyr , BldNd_TDzr , BldNd_TVxr , BldNd_TVxg , & + BldNd_TVxl , BldNd_TVyr , BldNd_TVyg , BldNd_TVyl , BldNd_TVzr , BldNd_TVzg , BldNd_TVzl , BldNd_RVxr , & + BldNd_RVxg , BldNd_RVxl , BldNd_RVyr , BldNd_RVyg , BldNd_RVyl , BldNd_RVzr , BldNd_RVzg , BldNd_RVzl /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(177) = (/ & ! This lists the units corresponding to the allowed parameters + "(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ",& + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(deg/s^2)", & + "(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)", & + "(deg/s^2)","(deg/s^2)","(deg/s^2)","(-) ","(-) ", & + "(-) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(deg/s) ", & + "(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + + ! these outputs are not valid for FE (Gauss) + IF (p%BldMotionNodeLoc==BD_MESH_FE) then + InvalidOutput( BldNd_FFbxl ) = .true. + InvalidOutput( BldNd_FFbyl ) = .true. + InvalidOutput( BldNd_FFbzl ) = .true. + InvalidOutput( BldNd_MFbxl ) = .true. + InvalidOutput( BldNd_MFbyl ) = .true. + InvalidOutput( BldNd_MFbzl ) = .true. + InvalidOutput( BldNd_FFcxl ) = .true. + InvalidOutput( BldNd_FFcyl ) = .true. + InvalidOutput( BldNd_FFczl ) = .true. + InvalidOutput( BldNd_MFcxl ) = .true. + InvalidOutput( BldNd_MFcyl ) = .true. + InvalidOutput( BldNd_MFczl ) = .true. + InvalidOutput( BldNd_FFdxl ) = .true. + InvalidOutput( BldNd_FFdyl ) = .true. + InvalidOutput( BldNd_FFdzl ) = .true. + InvalidOutput( BldNd_MFdxl ) = .true. + InvalidOutput( BldNd_MFdyl ) = .true. + InvalidOutput( BldNd_MFdzl ) = .true. + InvalidOutput( BldNd_FFgxl ) = .true. + InvalidOutput( BldNd_FFgyl ) = .true. + InvalidOutput( BldNd_FFgzl ) = .true. + InvalidOutput( BldNd_MFgxl ) = .true. + InvalidOutput( BldNd_MFgyl ) = .true. + InvalidOutput( BldNd_MFgzl ) = .true. + InvalidOutput( BldNd_FFbxr ) = .true. + InvalidOutput( BldNd_FFbyr ) = .true. + InvalidOutput( BldNd_FFbzr ) = .true. + InvalidOutput( BldNd_MFbxr ) = .true. + InvalidOutput( BldNd_MFbyr ) = .true. + InvalidOutput( BldNd_MFbzr ) = .true. + InvalidOutput( BldNd_FFcxr ) = .true. + InvalidOutput( BldNd_FFcyr ) = .true. + InvalidOutput( BldNd_FFczr ) = .true. + InvalidOutput( BldNd_MFcxr ) = .true. + InvalidOutput( BldNd_MFcyr ) = .true. + InvalidOutput( BldNd_MFczr ) = .true. + InvalidOutput( BldNd_FFdxr ) = .true. + InvalidOutput( BldNd_FFdyr ) = .true. + InvalidOutput( BldNd_FFdzr ) = .true. + InvalidOutput( BldNd_MFdxr ) = .true. + InvalidOutput( BldNd_MFdyr ) = .true. + InvalidOutput( BldNd_MFdzr ) = .true. + InvalidOutput( BldNd_FFgxr ) = .true. + InvalidOutput( BldNd_FFgyr ) = .true. + InvalidOutput( BldNd_FFgzr ) = .true. + InvalidOutput( BldNd_MFgxr ) = .true. + InvalidOutput( BldNd_MFgyr ) = .true. + InvalidOutput( BldNd_MFgzr ) = .true. + InvalidOutput( BldNd_FFixl ) = .true. + InvalidOutput( BldNd_FFiyl ) = .true. + InvalidOutput( BldNd_FFizl ) = .true. + InvalidOutput( BldNd_MFixl ) = .true. + InvalidOutput( BldNd_MFiyl ) = .true. + InvalidOutput( BldNd_MFizl ) = .true. + InvalidOutput( BldNd_FFixr ) = .true. + InvalidOutput( BldNd_FFiyr ) = .true. + InvalidOutput( BldNd_FFizr ) = .true. + InvalidOutput( BldNd_MFixr ) = .true. + InvalidOutput( BldNd_MFiyr ) = .true. + InvalidOutput( BldNd_MFizr ) = .true. + END IF + IF (.NOT. (p%OutInputs .and. p%BldMotionNodeLoc/=BD_MESH_FE)) then + ! Distributed output channels not allowed yet as the mapping of the m%u_DistrLoad_at_y only exists for MESH_QP with p%OutInputs set to true + InvalidOutput( BldNd_DFxL ) = .true. + InvalidOutput( BldNd_DFyL ) = .true. + InvalidOutput( BldNd_DFzL ) = .true. + InvalidOutput( BldNd_DMxL ) = .true. + InvalidOutput( BldNd_DMyL ) = .true. + InvalidOutput( BldNd_DMzL ) = .true. + InvalidOutput( BldNd_DFxr ) = .true. + InvalidOutput( BldNd_DFyr ) = .true. + InvalidOutput( BldNd_DFzr ) = .true. + InvalidOutput( BldNd_DMxr ) = .true. + InvalidOutput( BldNd_DMyr ) = .true. + InvalidOutput( BldNd_DMzr ) = .true. + END IF + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%BldNd_OutParam(1:p%BldNd_NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the BeamDyn BldNd_OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%BldNd_NumOuts + + p%BldNd_OutParam(I)%Name = "_"//BldNd_OutList(I) + OutListTmp = BldNd_OutList(I) + p%BldNd_OutParam(I)%SignM = 1 ! this won't be used + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + IF ( Indx > 0 ) THEN ! we found the channel name + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 + ELSE + p%BldNd_OutParam(I)%Indx = ParamIndxAry(Indx) + p%BldNd_OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%BldNd_OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE BldNdOuts_SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +END MODULE BeamDyn_BldNdOuts_IO diff --git a/OpenFAST/modules/beamdyn/src/BeamDyn_IO.f90 b/OpenFAST/modules/beamdyn/src/BeamDyn_IO.f90 new file mode 100644 index 000000000..92af5a918 --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/BeamDyn_IO.f90 @@ -0,0 +1,2708 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2018 Envision Energy USA, LTD +! +! 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. +!********************************************************************************************************************************** +!> This module contains the input/output parameters and routines for the BeamDyn module. +MODULE BeamDyn_IO + + USE BeamDyn_BldNdOuts_IO + USE BeamDyn_Types + USE BeamDyn_Subs + USE NWTC_Library + !USE NWTC_LAPACK + + IMPLICIT NONE + + TYPE(ProgDesc), PARAMETER:: BeamDyn_Ver = ProgDesc('BeamDyn', '','') + + + + + ! Mass tolerance for checking the mass matrices: + REAL(SiKi), PARAMETER :: Mass0Tol = 1E-3 ! Tolerance for checking mass values + + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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-Sep-2015 10:23:41. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Reaction Loads: + + INTEGER(IntKi), PARAMETER :: RootFxr = 1 + INTEGER(IntKi), PARAMETER :: RootFyr = 2 + INTEGER(IntKi), PARAMETER :: RootFzr = 3 + INTEGER(IntKi), PARAMETER :: RootMxr = 4 + INTEGER(IntKi), PARAMETER :: RootMyr = 5 + INTEGER(IntKi), PARAMETER :: RootMzr = 6 + + + ! Tip Motions: + + INTEGER(IntKi), PARAMETER :: TipTDxr = 7 + INTEGER(IntKi), PARAMETER :: TipTDyr = 8 + INTEGER(IntKi), PARAMETER :: TipTDzr = 9 + INTEGER(IntKi), PARAMETER :: TipRDxr = 10 + INTEGER(IntKi), PARAMETER :: TipRDyr = 11 + INTEGER(IntKi), PARAMETER :: TipRDzr = 12 + INTEGER(IntKi), PARAMETER :: TipTVXg = 13 + INTEGER(IntKi), PARAMETER :: TipTVYg = 14 + INTEGER(IntKi), PARAMETER :: TipTVZg = 15 + INTEGER(IntKi), PARAMETER :: TipRVXg = 16 + INTEGER(IntKi), PARAMETER :: TipRVYg = 17 + INTEGER(IntKi), PARAMETER :: TipRVZg = 18 + INTEGER(IntKi), PARAMETER :: TipTAXl = 19 + INTEGER(IntKi), PARAMETER :: TipTAYl = 20 + INTEGER(IntKi), PARAMETER :: TipTAZl = 21 + INTEGER(IntKi), PARAMETER :: TipRAXl = 22 + INTEGER(IntKi), PARAMETER :: TipRAYl = 23 + INTEGER(IntKi), PARAMETER :: TipRAZl = 24 + + + ! Sectional Loads: + + INTEGER(IntKi), PARAMETER :: N1Fxl = 25 + INTEGER(IntKi), PARAMETER :: N1Fyl = 26 + INTEGER(IntKi), PARAMETER :: N1Fzl = 27 + INTEGER(IntKi), PARAMETER :: N2Fxl = 28 + INTEGER(IntKi), PARAMETER :: N2Fyl = 29 + INTEGER(IntKi), PARAMETER :: N2Fzl = 30 + INTEGER(IntKi), PARAMETER :: N3Fxl = 31 + INTEGER(IntKi), PARAMETER :: N3Fyl = 32 + INTEGER(IntKi), PARAMETER :: N3Fzl = 33 + INTEGER(IntKi), PARAMETER :: N4Fxl = 34 + INTEGER(IntKi), PARAMETER :: N4Fyl = 35 + INTEGER(IntKi), PARAMETER :: N4Fzl = 36 + INTEGER(IntKi), PARAMETER :: N5Fxl = 37 + INTEGER(IntKi), PARAMETER :: N5Fyl = 38 + INTEGER(IntKi), PARAMETER :: N5Fzl = 39 + INTEGER(IntKi), PARAMETER :: N6Fxl = 40 + INTEGER(IntKi), PARAMETER :: N6Fyl = 41 + INTEGER(IntKi), PARAMETER :: N6Fzl = 42 + INTEGER(IntKi), PARAMETER :: N7Fxl = 43 + INTEGER(IntKi), PARAMETER :: N7Fyl = 44 + INTEGER(IntKi), PARAMETER :: N7Fzl = 45 + INTEGER(IntKi), PARAMETER :: N8Fxl = 46 + INTEGER(IntKi), PARAMETER :: N8Fyl = 47 + INTEGER(IntKi), PARAMETER :: N8Fzl = 48 + INTEGER(IntKi), PARAMETER :: N9Fxl = 49 + INTEGER(IntKi), PARAMETER :: N9Fyl = 50 + INTEGER(IntKi), PARAMETER :: N9Fzl = 51 + INTEGER(IntKi), PARAMETER :: N1Mxl = 52 + INTEGER(IntKi), PARAMETER :: N1Myl = 53 + INTEGER(IntKi), PARAMETER :: N1Mzl = 54 + INTEGER(IntKi), PARAMETER :: N2Mxl = 55 + INTEGER(IntKi), PARAMETER :: N2Myl = 56 + INTEGER(IntKi), PARAMETER :: N2Mzl = 57 + INTEGER(IntKi), PARAMETER :: N3Mxl = 58 + INTEGER(IntKi), PARAMETER :: N3Myl = 59 + INTEGER(IntKi), PARAMETER :: N3Mzl = 60 + INTEGER(IntKi), PARAMETER :: N4Mxl = 61 + INTEGER(IntKi), PARAMETER :: N4Myl = 62 + INTEGER(IntKi), PARAMETER :: N4Mzl = 63 + INTEGER(IntKi), PARAMETER :: N5Mxl = 64 + INTEGER(IntKi), PARAMETER :: N5Myl = 65 + INTEGER(IntKi), PARAMETER :: N5Mzl = 66 + INTEGER(IntKi), PARAMETER :: N6Mxl = 67 + INTEGER(IntKi), PARAMETER :: N6Myl = 68 + INTEGER(IntKi), PARAMETER :: N6Mzl = 69 + INTEGER(IntKi), PARAMETER :: N7Mxl = 70 + INTEGER(IntKi), PARAMETER :: N7Myl = 71 + INTEGER(IntKi), PARAMETER :: N7Mzl = 72 + INTEGER(IntKi), PARAMETER :: N8Mxl = 73 + INTEGER(IntKi), PARAMETER :: N8Myl = 74 + INTEGER(IntKi), PARAMETER :: N8Mzl = 75 + INTEGER(IntKi), PARAMETER :: N9Mxl = 76 + INTEGER(IntKi), PARAMETER :: N9Myl = 77 + INTEGER(IntKi), PARAMETER :: N9Mzl = 78 + + + ! Sectional Motions: + + INTEGER(IntKi), PARAMETER :: N1TDxr = 79 + INTEGER(IntKi), PARAMETER :: N1TDyr = 80 + INTEGER(IntKi), PARAMETER :: N1TDzr = 81 + INTEGER(IntKi), PARAMETER :: N2TDxr = 82 + INTEGER(IntKi), PARAMETER :: N2TDyr = 83 + INTEGER(IntKi), PARAMETER :: N2TDzr = 84 + INTEGER(IntKi), PARAMETER :: N3TDxr = 85 + INTEGER(IntKi), PARAMETER :: N3TDyr = 86 + INTEGER(IntKi), PARAMETER :: N3TDzr = 87 + INTEGER(IntKi), PARAMETER :: N4TDxr = 88 + INTEGER(IntKi), PARAMETER :: N4TDyr = 89 + INTEGER(IntKi), PARAMETER :: N4TDzr = 90 + INTEGER(IntKi), PARAMETER :: N5TDxr = 91 + INTEGER(IntKi), PARAMETER :: N5TDyr = 92 + INTEGER(IntKi), PARAMETER :: N5TDzr = 93 + INTEGER(IntKi), PARAMETER :: N6TDxr = 94 + INTEGER(IntKi), PARAMETER :: N6TDyr = 95 + INTEGER(IntKi), PARAMETER :: N6TDzr = 96 + INTEGER(IntKi), PARAMETER :: N7TDxr = 97 + INTEGER(IntKi), PARAMETER :: N7TDyr = 98 + INTEGER(IntKi), PARAMETER :: N7TDzr = 99 + INTEGER(IntKi), PARAMETER :: N8TDxr = 100 + INTEGER(IntKi), PARAMETER :: N8TDyr = 101 + INTEGER(IntKi), PARAMETER :: N8TDzr = 102 + INTEGER(IntKi), PARAMETER :: N9TDxr = 103 + INTEGER(IntKi), PARAMETER :: N9TDyr = 104 + INTEGER(IntKi), PARAMETER :: N9TDzr = 105 + INTEGER(IntKi), PARAMETER :: N1RDxr = 106 + INTEGER(IntKi), PARAMETER :: N1RDyr = 107 + INTEGER(IntKi), PARAMETER :: N1RDzr = 108 + INTEGER(IntKi), PARAMETER :: N2RDxr = 109 + INTEGER(IntKi), PARAMETER :: N2RDyr = 110 + INTEGER(IntKi), PARAMETER :: N2RDzr = 111 + INTEGER(IntKi), PARAMETER :: N3RDxr = 112 + INTEGER(IntKi), PARAMETER :: N3RDyr = 113 + INTEGER(IntKi), PARAMETER :: N3RDzr = 114 + INTEGER(IntKi), PARAMETER :: N4RDxr = 115 + INTEGER(IntKi), PARAMETER :: N4RDyr = 116 + INTEGER(IntKi), PARAMETER :: N4RDzr = 117 + INTEGER(IntKi), PARAMETER :: N5RDxr = 118 + INTEGER(IntKi), PARAMETER :: N5RDyr = 119 + INTEGER(IntKi), PARAMETER :: N5RDzr = 120 + INTEGER(IntKi), PARAMETER :: N6RDxr = 121 + INTEGER(IntKi), PARAMETER :: N6RDyr = 122 + INTEGER(IntKi), PARAMETER :: N6RDzr = 123 + INTEGER(IntKi), PARAMETER :: N7RDxr = 124 + INTEGER(IntKi), PARAMETER :: N7RDyr = 125 + INTEGER(IntKi), PARAMETER :: N7RDzr = 126 + INTEGER(IntKi), PARAMETER :: N8RDxr = 127 + INTEGER(IntKi), PARAMETER :: N8RDyr = 128 + INTEGER(IntKi), PARAMETER :: N8RDzr = 129 + INTEGER(IntKi), PARAMETER :: N9RDxr = 130 + INTEGER(IntKi), PARAMETER :: N9RDyr = 131 + INTEGER(IntKi), PARAMETER :: N9RDzr = 132 + INTEGER(IntKi), PARAMETER :: N1TVXg = 133 + INTEGER(IntKi), PARAMETER :: N1TVYg = 134 + INTEGER(IntKi), PARAMETER :: N1TVZg = 135 + INTEGER(IntKi), PARAMETER :: N2TVXg = 136 + INTEGER(IntKi), PARAMETER :: N2TVYg = 137 + INTEGER(IntKi), PARAMETER :: N2TVZg = 138 + INTEGER(IntKi), PARAMETER :: N3TVXg = 139 + INTEGER(IntKi), PARAMETER :: N3TVYg = 140 + INTEGER(IntKi), PARAMETER :: N3TVZg = 141 + INTEGER(IntKi), PARAMETER :: N4TVXg = 142 + INTEGER(IntKi), PARAMETER :: N4TVYg = 143 + INTEGER(IntKi), PARAMETER :: N4TVZg = 144 + INTEGER(IntKi), PARAMETER :: N5TVXg = 145 + INTEGER(IntKi), PARAMETER :: N5TVYg = 146 + INTEGER(IntKi), PARAMETER :: N5TVZg = 147 + INTEGER(IntKi), PARAMETER :: N6TVXg = 148 + INTEGER(IntKi), PARAMETER :: N6TVYg = 149 + INTEGER(IntKi), PARAMETER :: N6TVZg = 150 + INTEGER(IntKi), PARAMETER :: N7TVXg = 151 + INTEGER(IntKi), PARAMETER :: N7TVYg = 152 + INTEGER(IntKi), PARAMETER :: N7TVZg = 153 + INTEGER(IntKi), PARAMETER :: N8TVXg = 154 + INTEGER(IntKi), PARAMETER :: N8TVYg = 155 + INTEGER(IntKi), PARAMETER :: N8TVZg = 156 + INTEGER(IntKi), PARAMETER :: N9TVXg = 157 + INTEGER(IntKi), PARAMETER :: N9TVYg = 158 + INTEGER(IntKi), PARAMETER :: N9TVZg = 159 + INTEGER(IntKi), PARAMETER :: N1RVXg = 160 + INTEGER(IntKi), PARAMETER :: N1RVYg = 161 + INTEGER(IntKi), PARAMETER :: N1RVZg = 162 + INTEGER(IntKi), PARAMETER :: N2RVXg = 163 + INTEGER(IntKi), PARAMETER :: N2RVYg = 164 + INTEGER(IntKi), PARAMETER :: N2RVZg = 165 + INTEGER(IntKi), PARAMETER :: N3RVXg = 166 + INTEGER(IntKi), PARAMETER :: N3RVYg = 167 + INTEGER(IntKi), PARAMETER :: N3RVZg = 168 + INTEGER(IntKi), PARAMETER :: N4RVXg = 169 + INTEGER(IntKi), PARAMETER :: N4RVYg = 170 + INTEGER(IntKi), PARAMETER :: N4RVZg = 171 + INTEGER(IntKi), PARAMETER :: N5RVXg = 172 + INTEGER(IntKi), PARAMETER :: N5RVYg = 173 + INTEGER(IntKi), PARAMETER :: N5RVZg = 174 + INTEGER(IntKi), PARAMETER :: N6RVXg = 175 + INTEGER(IntKi), PARAMETER :: N6RVYg = 176 + INTEGER(IntKi), PARAMETER :: N6RVZg = 177 + INTEGER(IntKi), PARAMETER :: N7RVXg = 178 + INTEGER(IntKi), PARAMETER :: N7RVYg = 179 + INTEGER(IntKi), PARAMETER :: N7RVZg = 180 + INTEGER(IntKi), PARAMETER :: N8RVXg = 181 + INTEGER(IntKi), PARAMETER :: N8RVYg = 182 + INTEGER(IntKi), PARAMETER :: N8RVZg = 183 + INTEGER(IntKi), PARAMETER :: N9RVXg = 184 + INTEGER(IntKi), PARAMETER :: N9RVYg = 185 + INTEGER(IntKi), PARAMETER :: N9RVZg = 186 + INTEGER(IntKi), PARAMETER :: N1TAXl = 187 + INTEGER(IntKi), PARAMETER :: N1TAYl = 188 + INTEGER(IntKi), PARAMETER :: N1TAZl = 189 + INTEGER(IntKi), PARAMETER :: N2TAXl = 190 + INTEGER(IntKi), PARAMETER :: N2TAYl = 191 + INTEGER(IntKi), PARAMETER :: N2TAZl = 192 + INTEGER(IntKi), PARAMETER :: N3TAXl = 193 + INTEGER(IntKi), PARAMETER :: N3TAYl = 194 + INTEGER(IntKi), PARAMETER :: N3TAZl = 195 + INTEGER(IntKi), PARAMETER :: N4TAXl = 196 + INTEGER(IntKi), PARAMETER :: N4TAYl = 197 + INTEGER(IntKi), PARAMETER :: N4TAZl = 198 + INTEGER(IntKi), PARAMETER :: N5TAXl = 199 + INTEGER(IntKi), PARAMETER :: N5TAYl = 200 + INTEGER(IntKi), PARAMETER :: N5TAZl = 201 + INTEGER(IntKi), PARAMETER :: N6TAXl = 202 + INTEGER(IntKi), PARAMETER :: N6TAYl = 203 + INTEGER(IntKi), PARAMETER :: N6TAZl = 204 + INTEGER(IntKi), PARAMETER :: N7TAXl = 205 + INTEGER(IntKi), PARAMETER :: N7TAYl = 206 + INTEGER(IntKi), PARAMETER :: N7TAZl = 207 + INTEGER(IntKi), PARAMETER :: N8TAXl = 208 + INTEGER(IntKi), PARAMETER :: N8TAYl = 209 + INTEGER(IntKi), PARAMETER :: N8TAZl = 210 + INTEGER(IntKi), PARAMETER :: N9TAXl = 211 + INTEGER(IntKi), PARAMETER :: N9TAYl = 212 + INTEGER(IntKi), PARAMETER :: N9TAZl = 213 + INTEGER(IntKi), PARAMETER :: N1RAXl = 214 + INTEGER(IntKi), PARAMETER :: N1RAYl = 215 + INTEGER(IntKi), PARAMETER :: N1RAZl = 216 + INTEGER(IntKi), PARAMETER :: N2RAXl = 217 + INTEGER(IntKi), PARAMETER :: N2RAYl = 218 + INTEGER(IntKi), PARAMETER :: N2RAZl = 219 + INTEGER(IntKi), PARAMETER :: N3RAXl = 220 + INTEGER(IntKi), PARAMETER :: N3RAYl = 221 + INTEGER(IntKi), PARAMETER :: N3RAZl = 222 + INTEGER(IntKi), PARAMETER :: N4RAXl = 223 + INTEGER(IntKi), PARAMETER :: N4RAYl = 224 + INTEGER(IntKi), PARAMETER :: N4RAZl = 225 + INTEGER(IntKi), PARAMETER :: N5RAXl = 226 + INTEGER(IntKi), PARAMETER :: N5RAYl = 227 + INTEGER(IntKi), PARAMETER :: N5RAZl = 228 + INTEGER(IntKi), PARAMETER :: N6RAXl = 229 + INTEGER(IntKi), PARAMETER :: N6RAYl = 230 + INTEGER(IntKi), PARAMETER :: N6RAZl = 231 + INTEGER(IntKi), PARAMETER :: N7RAXl = 232 + INTEGER(IntKi), PARAMETER :: N7RAYl = 233 + INTEGER(IntKi), PARAMETER :: N7RAZl = 234 + INTEGER(IntKi), PARAMETER :: N8RAXl = 235 + INTEGER(IntKi), PARAMETER :: N8RAYl = 236 + INTEGER(IntKi), PARAMETER :: N8RAZl = 237 + INTEGER(IntKi), PARAMETER :: N9RAXl = 238 + INTEGER(IntKi), PARAMETER :: N9RAYl = 239 + INTEGER(IntKi), PARAMETER :: N9RAZl = 240 + + + ! Applied Loads: + + INTEGER(IntKi), PARAMETER :: N1PFxl = 241 + INTEGER(IntKi), PARAMETER :: N1PFyl = 242 + INTEGER(IntKi), PARAMETER :: N1PFzl = 243 + INTEGER(IntKi), PARAMETER :: N2PFxl = 244 + INTEGER(IntKi), PARAMETER :: N2PFyl = 245 + INTEGER(IntKi), PARAMETER :: N2PFzl = 246 + INTEGER(IntKi), PARAMETER :: N3PFxl = 247 + INTEGER(IntKi), PARAMETER :: N3PFyl = 248 + INTEGER(IntKi), PARAMETER :: N3PFzl = 249 + INTEGER(IntKi), PARAMETER :: N4PFxl = 250 + INTEGER(IntKi), PARAMETER :: N4PFyl = 251 + INTEGER(IntKi), PARAMETER :: N4PFzl = 252 + INTEGER(IntKi), PARAMETER :: N5PFxl = 253 + INTEGER(IntKi), PARAMETER :: N5PFyl = 254 + INTEGER(IntKi), PARAMETER :: N5PFzl = 255 + INTEGER(IntKi), PARAMETER :: N6PFxl = 256 + INTEGER(IntKi), PARAMETER :: N6PFyl = 257 + INTEGER(IntKi), PARAMETER :: N6PFzl = 258 + INTEGER(IntKi), PARAMETER :: N7PFxl = 259 + INTEGER(IntKi), PARAMETER :: N7PFyl = 260 + INTEGER(IntKi), PARAMETER :: N7PFzl = 261 + INTEGER(IntKi), PARAMETER :: N8PFxl = 262 + INTEGER(IntKi), PARAMETER :: N8PFyl = 263 + INTEGER(IntKi), PARAMETER :: N8PFzl = 264 + INTEGER(IntKi), PARAMETER :: N9PFxl = 265 + INTEGER(IntKi), PARAMETER :: N9PFyl = 266 + INTEGER(IntKi), PARAMETER :: N9PFzl = 267 + INTEGER(IntKi), PARAMETER :: N1PMxl = 268 + INTEGER(IntKi), PARAMETER :: N1PMyl = 269 + INTEGER(IntKi), PARAMETER :: N1PMzl = 270 + INTEGER(IntKi), PARAMETER :: N2PMxl = 271 + INTEGER(IntKi), PARAMETER :: N2PMyl = 272 + INTEGER(IntKi), PARAMETER :: N2PMzl = 273 + INTEGER(IntKi), PARAMETER :: N3PMxl = 274 + INTEGER(IntKi), PARAMETER :: N3PMyl = 275 + INTEGER(IntKi), PARAMETER :: N3PMzl = 276 + INTEGER(IntKi), PARAMETER :: N4PMxl = 277 + INTEGER(IntKi), PARAMETER :: N4PMyl = 278 + INTEGER(IntKi), PARAMETER :: N4PMzl = 279 + INTEGER(IntKi), PARAMETER :: N5PMxl = 280 + INTEGER(IntKi), PARAMETER :: N5PMyl = 281 + INTEGER(IntKi), PARAMETER :: N5PMzl = 282 + INTEGER(IntKi), PARAMETER :: N6PMxl = 283 + INTEGER(IntKi), PARAMETER :: N6PMyl = 284 + INTEGER(IntKi), PARAMETER :: N6PMzl = 285 + INTEGER(IntKi), PARAMETER :: N7PMxl = 286 + INTEGER(IntKi), PARAMETER :: N7PMyl = 287 + INTEGER(IntKi), PARAMETER :: N7PMzl = 288 + INTEGER(IntKi), PARAMETER :: N8PMxl = 289 + INTEGER(IntKi), PARAMETER :: N8PMyl = 290 + INTEGER(IntKi), PARAMETER :: N8PMzl = 291 + INTEGER(IntKi), PARAMETER :: N9PMxl = 292 + INTEGER(IntKi), PARAMETER :: N9PMyl = 293 + INTEGER(IntKi), PARAMETER :: N9PMzl = 294 + INTEGER(IntKi), PARAMETER :: N1DFxl = 295 + INTEGER(IntKi), PARAMETER :: N1DFyl = 296 + INTEGER(IntKi), PARAMETER :: N1DFzl = 297 + INTEGER(IntKi), PARAMETER :: N2DFxl = 298 + INTEGER(IntKi), PARAMETER :: N2DFyl = 299 + INTEGER(IntKi), PARAMETER :: N2DFzl = 300 + INTEGER(IntKi), PARAMETER :: N3DFxl = 301 + INTEGER(IntKi), PARAMETER :: N3DFyl = 302 + INTEGER(IntKi), PARAMETER :: N3DFzl = 303 + INTEGER(IntKi), PARAMETER :: N4DFxl = 304 + INTEGER(IntKi), PARAMETER :: N4DFyl = 305 + INTEGER(IntKi), PARAMETER :: N4DFzl = 306 + INTEGER(IntKi), PARAMETER :: N5DFxl = 307 + INTEGER(IntKi), PARAMETER :: N5DFyl = 308 + INTEGER(IntKi), PARAMETER :: N5DFzl = 309 + INTEGER(IntKi), PARAMETER :: N6DFxl = 310 + INTEGER(IntKi), PARAMETER :: N6DFyl = 311 + INTEGER(IntKi), PARAMETER :: N6DFzl = 312 + INTEGER(IntKi), PARAMETER :: N7DFxl = 313 + INTEGER(IntKi), PARAMETER :: N7DFyl = 314 + INTEGER(IntKi), PARAMETER :: N7DFzl = 315 + INTEGER(IntKi), PARAMETER :: N8DFxl = 316 + INTEGER(IntKi), PARAMETER :: N8DFyl = 317 + INTEGER(IntKi), PARAMETER :: N8DFzl = 318 + INTEGER(IntKi), PARAMETER :: N9DFxl = 319 + INTEGER(IntKi), PARAMETER :: N9DFyl = 320 + INTEGER(IntKi), PARAMETER :: N9DFzl = 321 + INTEGER(IntKi), PARAMETER :: N1DMxl = 322 + INTEGER(IntKi), PARAMETER :: N1DMyl = 323 + INTEGER(IntKi), PARAMETER :: N1DMzl = 324 + INTEGER(IntKi), PARAMETER :: N2DMxl = 325 + INTEGER(IntKi), PARAMETER :: N2DMyl = 326 + INTEGER(IntKi), PARAMETER :: N2DMzl = 327 + INTEGER(IntKi), PARAMETER :: N3DMxl = 328 + INTEGER(IntKi), PARAMETER :: N3DMyl = 329 + INTEGER(IntKi), PARAMETER :: N3DMzl = 330 + INTEGER(IntKi), PARAMETER :: N4DMxl = 331 + INTEGER(IntKi), PARAMETER :: N4DMyl = 332 + INTEGER(IntKi), PARAMETER :: N4DMzl = 333 + INTEGER(IntKi), PARAMETER :: N5DMxl = 334 + INTEGER(IntKi), PARAMETER :: N5DMyl = 335 + INTEGER(IntKi), PARAMETER :: N5DMzl = 336 + INTEGER(IntKi), PARAMETER :: N6DMxl = 337 + INTEGER(IntKi), PARAMETER :: N6DMyl = 338 + INTEGER(IntKi), PARAMETER :: N6DMzl = 339 + INTEGER(IntKi), PARAMETER :: N7DMxl = 340 + INTEGER(IntKi), PARAMETER :: N7DMyl = 341 + INTEGER(IntKi), PARAMETER :: N7DMzl = 342 + INTEGER(IntKi), PARAMETER :: N8DMxl = 343 + INTEGER(IntKi), PARAMETER :: N8DMyl = 344 + INTEGER(IntKi), PARAMETER :: N8DMzl = 345 + INTEGER(IntKi), PARAMETER :: N9DMxl = 346 + INTEGER(IntKi), PARAMETER :: N9DMyl = 347 + INTEGER(IntKi), PARAMETER :: N9DMzl = 348 + + + ! Pitch Actuator: + + INTEGER(IntKi), PARAMETER :: PAngInp = 349 + INTEGER(IntKi), PARAMETER :: PAngAct = 350 + INTEGER(IntKi), PARAMETER :: PRatAct = 351 + INTEGER(IntKi), PARAMETER :: PAccAct = 352 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 352 + +!End of code generated by Matlab script +! =================================================================================================== + + INTEGER, PARAMETER :: NFl(9, 3) = RESHAPE( (/ & ! Sectional force resultants expressed in l + N1Fxl,N2Fxl,N3Fxl,N4Fxl,N5Fxl,N6Fxl,N7Fxl,N8Fxl,N9Fxl, & + N1Fyl,N2Fyl,N3Fyl,N4Fyl,N5Fyl,N6Fyl,N7Fyl,N8Fyl,N9Fyl, & + N1Fzl,N2Fzl,N3Fzl,N4Fzl,N5Fzl,N6Fzl,N7Fzl,N8Fzl,N9Fzl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NMl(9, 3) = RESHAPE( (/ & ! Sectional moment resultants expressed in l + N1Mxl,N2Mxl,N3Mxl,N4Mxl,N5Mxl,N6Mxl,N7Mxl,N8Mxl,N9Mxl, & + N1Myl,N2Myl,N3Myl,N4Myl,N5Myl,N6Myl,N7Myl,N8Myl,N9Myl, & + N1Mzl,N2Mzl,N3Mzl,N4Mzl,N5Mzl,N6Mzl,N7Mzl,N8Mzl,N9Mzl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NTDr(9, 3) = RESHAPE( (/ & ! Sectional translational deflections expressed in r + N1TDxr,N2TDxr,N3TDxr,N4TDxr,N5TDxr,N6TDxr,N7TDxr,N8TDxr,N9TDxr, & + N1TDyr,N2TDyr,N3TDyr,N4TDyr,N5TDyr,N6TDyr,N7TDyr,N8TDyr,N9TDyr, & + N1TDzr,N2TDzr,N3TDzr,N4TDzr,N5TDzr,N6TDzr,N7TDzr,N8TDzr,N9TDzr & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NRDr(9, 3) = RESHAPE( (/ & ! Sectional angular/rotational deflections expressed in r + N1RDxr,N2RDxr,N3RDxr,N4RDxr,N5RDxr,N6RDxr,N7RDxr,N8RDxr,N9RDxr, & + N1RDyr,N2RDyr,N3RDyr,N4RDyr,N5RDyr,N6RDyr,N7RDyr,N8RDyr,N9RDyr, & + N1RDzr,N2RDzr,N3RDzr,N4RDzr,N5RDzr,N6RDzr,N7RDzr,N8RDzr,N9RDzr & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NTVg(9, 3) = RESHAPE( (/ & ! Sectional translational velocities expressed in g + N1TVXg,N2TVXg,N3TVXg,N4TVXg,N5TVXg,N6TVXg,N7TVXg,N8TVXg,N9TVXg, & + N1TVYg,N2TVYg,N3TVYg,N4TVYg,N5TVYg,N6TVYg,N7TVYg,N8TVYg,N9TVYg, & + N1TVZg,N2TVZg,N3TVZg,N4TVZg,N5TVZg,N6TVZg,N7TVZg,N8TVZg,N9TVZg & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NRVg(9, 3) = RESHAPE( (/ & ! Sectional angular/rotational velocities expressed in g + N1RVXg,N2RVXg,N3RVXg,N4RVXg,N5RVXg,N6RVXg,N7RVXg,N8RVXg,N9RVXg, & + N1RVYg,N2RVYg,N3RVYg,N4RVYg,N5RVYg,N6RVYg,N7RVYg,N8RVYg,N9RVYg, & + N1RVZg,N2RVZg,N3RVZg,N4RVZg,N5RVZg,N6RVZg,N7RVZg,N8RVZg,N9RVZg & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NTAl(9, 3) = RESHAPE( (/ & ! Sectional translational accelerations expressed in l + N1TAXl,N2TAXl,N3TAXl,N4TAXl,N5TAXl,N6TAXl,N7TAXl,N8TAXl,N9TAXl, & + N1TAYl,N2TAYl,N3TAYl,N4TAYl,N5TAYl,N6TAYl,N7TAYl,N8TAYl,N9TAYl, & + N1TAZl,N2TAZl,N3TAZl,N4TAZl,N5TAZl,N6TAZl,N7TAZl,N8TAZl,N9TAZl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NRAl(9, 3) = RESHAPE( (/ & ! Sectional angular/rotational accelerations expressed in l + N1RAXl,N2RAXl,N3RAXl,N4RAXl,N5RAXl,N6RAXl,N7RAXl,N8RAXl,N9RAXl, & + N1RAYl,N2RAYl,N3RAYl,N4RAYl,N5RAYl,N6RAYl,N7RAYl,N8RAYl,N9RAYl, & + N1RAZl,N2RAZl,N3RAZl,N4RAZl,N5RAZl,N6RAZl,N7RAZl,N8RAZl,N9RAZl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NPFl(9, 3) = RESHAPE( (/ & ! Applied point forces expressed in l + N1PFxl,N2PFxl,N3PFxl,N4PFxl,N5PFxl,N6PFxl,N7PFxl,N8PFxl,N9PFxl, & + N1PFyl,N2PFyl,N3PFyl,N4PFyl,N5PFyl,N6PFyl,N7PFyl,N8PFyl,N9PFyl, & + N1PFzl,N2PFzl,N3PFzl,N4PFzl,N5PFzl,N6PFzl,N7PFzl,N8PFzl,N9PFzl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NPMl(9, 3) = RESHAPE( (/ & ! Applied point moments expressed in l + N1PMxl,N2PMxl,N3PMxl,N4PMxl,N5PMxl,N6PMxl,N7PMxl,N8PMxl,N9PMxl, & + N1PMyl,N2PMyl,N3PMyl,N4PMyl,N5PMyl,N6PMyl,N7PMyl,N8PMyl,N9PMyl, & + N1PMzl,N2PMzl,N3PMzl,N4PMzl,N5PMzl,N6PMzl,N7PMzl,N8PMzl,N9PMzl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NDFl(9, 3) = RESHAPE( (/ & ! Applied distributed forces expressed in l + N1DFxl,N2DFxl,N3DFxl,N4DFxl,N5DFxl,N6DFxl,N7DFxl,N8DFxl,N9DFxl, & + N1DFyl,N2DFyl,N3DFyl,N4DFyl,N5DFyl,N6DFyl,N7DFyl,N8DFyl,N9DFyl, & + N1DFzl,N2DFzl,N3DFzl,N4DFzl,N5DFzl,N6DFzl,N7DFzl,N8DFzl,N9DFzl & + /), (/9, 3/) ) + INTEGER, PARAMETER :: NDMl(9, 3) = RESHAPE( (/ & ! Applied distributed moments expressed in l + N1DMxl,N2DMxl,N3DMxl,N4DMxl,N5DMxl,N6DMxl,N7DMxl,N8DMxl,N9DMxl, & + N1DMyl,N2DMyl,N3DMyl,N4DMyl,N5DMyl,N6DMyl,N7DMyl,N8DMyl,N9DMyl, & + N1DMzl,N2DMzl,N3DMzl,N4DMzl,N5DMzl,N6DMzl,N7DMzl,N8DMzl,N9DMzl & + /), (/9, 3/) ) + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_ReadInput(InputFileName,InputFileData,OutFileRoot, Default_DT,ErrStat,ErrMsg) + + ! Passed Variables: + CHARACTER(*), INTENT(IN ) :: InputFileName !< Name of the input file + CHARACTER(*), INTENT(IN ) :: OutFileRoot !< Name of the input file + REAL(DbKi), INTENT(IN ) :: Default_DT !< The default DT (from glue code) + TYPE(BD_InputFile), INTENT( OUT) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message, if an error occurred + + + ! Local variables: + INTEGER(IntKi) :: UnEcho + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'BD_ReadInput' + + + ErrStat = ErrID_None + ErrMsg = '' + UnEcho = -1 + + InputFileData%DTBeam = Default_DT + CALL BD_ReadPrimaryFile(InputFileName,InputFileData,OutFileRoot,UnEcho,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF(ErrStat >= AbortErrLev) THEN + IF (UnEcho > 0) CLOSE (UnEcho) + RETURN + END IF + + CALL BD_ReadBladeFile(InputFileData%BldFile,InputFileData%InpBl,UnEcho,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF(ErrStat >= AbortErrLev) THEN + IF (UnEcho > 0) CLOSE (UnEcho) + RETURN + END IF + +END SUBROUTINE BD_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary BeamDyn input file and places the values it reads +!! in the InputFileData structure. +!! It opens an echo file if requested and returns the (still-open) echo file to the +!! calling routine. +SUBROUTINE BD_ReadPrimaryFile(InputFile,InputFileData,OutFileRoot,UnEc,ErrStat,ErrMsg) + + ! Passed variables + INTEGER(IntKi), INTENT( OUT) :: UnEc + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT(IN ) :: InputFile + CHARACTER(*), INTENT(IN ) :: OutFileRoot + CHARACTER(*), INTENT( OUT) :: ErrMsg + + TYPE(BD_InputFile), INTENT(INOUT) :: InputFileData + + ! Local variables: + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + INTEGER(IntKi) :: IOS ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(ErrMsgLen) :: ErrMsg_NoBldNdOuts ! Temporary Error message + character(*), parameter :: RoutineName = 'BD_ReadPrimaryFile' + + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(200) :: Line ! Temporary storage of a line from the input + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: temp_int + REAL(BDKi) :: tmpReAry(4) + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + Echo = .FALSE. + UnEc = -1 + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + CALL AllocAry( InputFileData%OutList, MaxOutPts, "Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Allocate array for holding the list of node outputs + CALL AllocAry( InputFileData%BldNd_OutList, BldNd_MaxOutPts, "BldNd_Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL GetNewUnit(UnIn,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL OpenFInpFile(UnIn,InputFile,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + + + + I = 1 !set the number of times we've read the file + DO + !-------------------------- HEADER --------------------------------------------- + CALL ReadCom(UnIn,InputFile,'File Header: Module Version (line 1)',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadStr(UnIn,InputFile,FTitle,'FTitle','File Header: File Description (line 2)',ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + !---------------------- SIMULATION CONTROL -------------------------------------- + CALL ReadCom(UnIn,InputFile,'Section Header: Simulation Control',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,InputFile,Echo,'Echo','Echo switch',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, BeamDyn_Ver ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(BeamDyn_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".', ErrStat, ErrMsg, RoutineName ) + call cleanup() + RETURN + END IF + + END DO + + CALL ReadVar(UnIn,InputFile,InputFileData%QuasiStaticInit,"QuasiStaticInit", "QuasiStaticInit",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,InputFile,InputFileData%rhoinf,"rhoinf", "Coefficient for GA2",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,InputFile,InputFileData%quadrature,"quadrature", "Quadrature type",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "refine", "Refinement parameter for trapezoidal quadrature {or default} ", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%refine = 1 + ELSE ! If it's not "default", read this variable + READ( Line, *, IOSTAT=IOS) InputFileData%refine + CALL CheckIOS ( IOS, InputFile, 'refine', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "n_fact", "Factorization frequency {or default}", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%n_fact = 5 + ELSE ! If it's not "default", read this variable + READ( Line, *, IOSTAT=IOS) InputFileData%n_fact + CALL CheckIOS ( IOS, InputFile, 'n_fact', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "DTBeam", "Time interval for BeamDyn calculations {or default} (s)", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DTBeam + READ( Line, *, IOSTAT=IOS) InputFileData%DTBeam + CALL CheckIOS ( IOS, InputFile, 'DTBeam', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "load_retries", "Tolerance for stopping criterion", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%load_retries = 20 + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%load_retries + CALL CheckIOS ( IOS, InputFile, 'load_retries', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "NRMax", "Max number of interations in Newton-Raphson algorithm", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%NRMax = 10 + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%NRMax + CALL CheckIOS ( IOS, InputFile, 'NRMax', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar( UnIn, InputFile, Line, "stop_tol", "Tolerance for stopping criterion", ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%stop_tol = 1.0D-05 + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%stop_tol + CALL CheckIOS ( IOS, InputFile, 'stop_tol', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar(UnIn, InputFile, Line, 'tngt_stf_fd','finite difference for tangent stiffness flag', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%tngt_stf_fd = .FALSE. + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%tngt_stf_fd + CALL CheckIOS ( IOS, InputFile, 'tngt_stf_fd', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + if (InputFileData%tngt_stf_fd) CALL WrScr( 'Using finite difference to compute tangent stiffness matrix'//NewLine ) + ! ! RelStates - Define states relative to root motion during linearization? (flag) [used only when linearizing] + !CALL ReadVar(UnIn,InputFile,InputFileData%RelStates,"RelStates", "Define states relative to root motion during linearization? (flag) [used only when linearizing]",ErrStat2,ErrMsg2,UnEc) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + InputFileData%RelStates = .false. ! this doesn't seem to be needed anymore (and I think there is a problem with using it in MBC3) + + Line = "" + CALL ReadVar(UnIn, InputFile, Line, 'tngt_stf_comp','compare tangent stiffness using finite difference flag', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%tngt_stf_comp = .FALSE. + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%tngt_stf_comp + CALL CheckIOS ( IOS, InputFile, 'tngt_stf_comp', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + if (InputFileData%tngt_stf_comp) CALL WrScr( 'WARNING: tngt_stf_comp set to true. Output will be verbose'//NewLine ) + + Line = "" + CALL ReadVar(UnIn, InputFile, Line, 'tngt_stf_pert','perturbation size for finite differenced tangent stiffness', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%tngt_stf_pert = 1.0D-06 + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%tngt_stf_pert + CALL CheckIOS ( IOS, InputFile, 'tngt_stf_pert', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + Line = "" + CALL ReadVar(UnIn, InputFile, Line, 'tngt_stf_difftol','tolerance for difference between analytical and fd tangent stiffness', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) .EQ. 1) THEN + InputFileData%tngt_stf_difftol = 1.0D-01 + ELSE ! If it's not "default", read this variable; + READ( Line, *, IOSTAT=IOS) InputFileData%tngt_stf_difftol + CALL CheckIOS ( IOS, InputFile, 'tngt_stf_difftol', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ! RotStates - Orient states in the rotating frame during linearization? (flag) [used only when linearizing] + CALL ReadVar(UnIn,InputFile,InputFileData%RotStates,"RotStates", "Orient states in the rotating frame during linearization? (flag) [used only when linearizing]",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! return on error at end of section + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + !---------------------- GEOMETRY PARAMETER -------------------------------------- + CALL ReadCom(UnIn,InputFile,'Section Header: Geometry Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,InputFile,InputFileData%member_total,"member_total", "Total number of member",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,InputFile,InputFileData%kp_total,"kp_total", "Total number of key point",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! check these values before allocating the arrays below + if (InputFileData%member_total<1 .or. InputFileData%kp_total<1) then + CALL SetErrStat( ErrID_Fatal, "member_total and kp_total must be positive numbers", ErrStat, ErrMsg, RoutineName ) + call cleanup() + return + end if + + CALL AllocAry(InputFileData%kp_member,InputFileData%member_total,'Number of key point in each member',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(InputFileData%kp_coordinate,InputFileData%kp_total,4,'Key point coordinates input array',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + InputFileData%kp_member = 0 + temp_int = 0 + DO i=1,InputFileData%member_total + ! bjj: we cannot read j, InputFileData%kp_member(j) because j could be outside the valid range: + READ(UnIn,*,IOSTAT=IOS) j,temp_int + CALL CheckIOS ( IOS, InputFile, 'Member number; Number of key points in this member', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + if (j>0 .and. j<= InputFileData%member_total) then + InputFileData%kp_member(j) = temp_int + end if + + !bjj: what happens if the user enters a member number multiple times? or if not each member is accounted for? + ! I'm going to force them to be entered 1-InputFileData%kp_member to avoid this issue for now. + if (j /= i) then + call SetErrStat(ErrID_Warn, "Member numbers must be entered in monotonicly increasing order, starting with 1.",ErrStat,ErrMsg,RoutineName) + end if + + ENDDO + + + CALL ReadCom(UnIn,InputFile,'key point x,y,z locations and initial twist angles',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadCom(UnIn,InputFile,'key point and initial twist units',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !InputFileData%kp_coordinate = 0.0_BDKi + DO i=1,InputFileData%kp_total + CALL ReadAry( UnIn, InputFile, TmpReAry, 4, 'kp_coordinate', 'Key point coordinates and initial twist', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + InputFileData%kp_coordinate(i,1) = TmpReAry(1) ! x + InputFileData%kp_coordinate(i,2) = TmpReAry(2) ! y + InputFileData%kp_coordinate(i,3) = TmpReAry(3) ! z + InputFileData%kp_coordinate(i,4) = -TmpReAry(4) ! initial twist + ENDDO + + + !---------------------- MESH PARAMETER ----------------------------------------- + CALL ReadCom(UnIn,InputFile,'Section Header: Mesh Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,InputFile,InputFileData%order_elem,"order_elem","Order of basis function",& + ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !---------------------- BEAM SECTIONAL PARAMETER ---------------------------------------- + CALL ReadCom(UnIn,InputFile,'Section Header: Beam Material Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar ( UnIn, InputFile, InputFileData%BldFile, 'BldFile', 'Name of the file containing properties for beam', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( PathIsRelative( InputFileData%BldFile ) ) InputFileData%BldFile = TRIM(PriPath)//TRIM(InputFileData%BldFile) + + + !---------------------- PITCH ACTUATOR PARAMETER ---------------------------------------- + CALL ReadCom(UnIn,InputFile,'Section Header: Pitch Actuator Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar ( UnIn, InputFile, InputFileData%UsePitchAct, 'UsePitchAct', 'Whether a pitch actuator should be used (flag)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar ( UnIn, InputFile, InputFileData%PitchJ, 'PitchJ', 'Pitch actuator inertia (kg-m^2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar ( UnIn, InputFile, InputFileData%PitchK, 'PitchK', 'Pitch actuator stiffness (kg-m^2/s^2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar ( UnIn, InputFile, InputFileData%PitchC, 'PitchC', 'Pitch actuator damping (kg-m^2/s)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !----------- OUTPUTS ----------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Outputs', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! SumPrint - Print summary data to <RootName>.BD.sum (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.BD.sum (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + call ReadVar( UnIn, InputFile, InputFileData%OutFmt, "OutFmt", "Format used for text tabular output (except time). Resulting field should be 10 characters. (-)",ErrStat2, ErrMsg2, UnEc) + call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) + + ! NNodeOuts - Number of node outputs [0 - 9] (-): + CALL ReadVar( UnIn, InputFile, InputFileData%NNodeOuts, "NNodeOuts", "Number of node outputs [0 - 9] (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( InputFileData%NNodeOuts > SIZE(InputFileData%OutNd) ) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: number of output nodes exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%OutNd))) //'.', ErrStat, ErrMsg, RoutineName ) + InputFileData%NNodeOuts = SIZE(InputFileData%OutNd) + END IF + + ! OutNd - Nodes whose values will be output (-): + CALL ReadAry( UnIn, InputFile, InputFileData%OutNd, InputFileData%NNodeOuts, "OutNd", "Nodes whose values will be output (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Return on error at end of section + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !----------- OUTLIST ----------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !---------------------- END OF FILE ----------------------------------------- + + + + !----------- OUTLIST ----------------------------------------------------------- + ! In case there is something ill-formed in the additional nodal outputs section, we will simply ignore it. + ErrMsg_NoBldNdOuts='Nodal outputs section of BeamDyn input file not found or improperly formatted.' + InputFileData%BldNd_NumOuts = 0 ! Just in case we don't get an error but have no nodal outputs. + + + !----------- OUTLIST for BldNd ----------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList for Blade node channels', ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + ! Number of blade nodes to output: will modify this at some point for arrays + ! TODO: Parse this string into an array of nodes to output at (one idea is to set an array of boolean to T/F for which nodes to output). At present, we ignore it entirely. + CALL ReadVar( UnIn, InputFile, InputFileData%BldNd_BlOutNd_Str, 'BldNd_BlOutNd_Str', 'Which nodes to output node data on.'//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + + ! Section header for outlist + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_NumOuts = 0 + CALL SetErrStat( ErrID_Warn, ErrMsg_NoBldNdOuts, ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + + ! OutList - List of user-requested output channels at each node(-): + CALL ReadOutputList ( UnIn, InputFile, InputFileData%BldNd_OutList, InputFileData%BldNd_NumOuts, 'BldNd_OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + !---------------------- END OF FILE ----------------------------------------- + + + call cleanup() + return + +contains + subroutine cleanup() + if (UnIn > 0) close(UnIn) + ! don't close the echo file here + end subroutine cleanup +END SUBROUTINE BD_ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_ReadBladeFile(BldFile,BladeInputFileData,UnEc,ErrStat,ErrMsg) + + ! Passed variables: + TYPE(BladeInputData), INTENT( OUT):: BladeInputFileData + CHARACTER(*), INTENT(IN ):: BldFile + INTEGER(IntKi), INTENT(IN ):: UnEc + INTEGER(IntKi), INTENT( OUT):: ErrStat !< Error status + CHARACTER(*), INTENT( OUT):: ErrMsg !< Error message + + ! Local variables: + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + character(*), parameter :: RoutineName = 'BD_ReadBladeFile' + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + + REAL(BDKi) :: temp66(6,6) + + ErrStat = ErrID_None + ErrMsg = "" + + CALL GetNewUnit(UnIn,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL OpenFInpFile (UnIn,BldFile,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + return + end if + + ! -------------- HEADER ------------------------------------------------------- + ! Skip the header. + CALL ReadCom(UnIn,BldFile,'unused beam file header line 1',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadCom(UnIn,BldFile,'unused beam file header line 2',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! -------------- BLADE PARAMETER----------------------------------------------- + CALL ReadCom(UnIn,BldFile,'beam parameters',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,BldFile,BladeInputFileData%station_total,'station_total','Number of blade input stations',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(BladeInputFileData%stiff0,6,6,BladeInputFileData%station_total,'Cross-sectional 6 by 6 stiffness matrix',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(BladeInputFileData%mass0,6,6,BladeInputFileData%station_total,'Cross-sectional 6 by 6 mass matrix',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(BladeInputFileData%station_eta,BladeInputFileData%station_total,'Station eta array',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !after allocating these arrays, we'll make sure it was successful: + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + +!FIXME: any reason not to use a logical for this? + CALL ReadVar(UnIn,BldFile,BladeInputFileData%damp_flag,'damp_flag','Damping flag',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! -------------- DAMPING PARAMETER----------------------------------------------- + CALL ReadCom(UnIn,BldFile,'damping parameters',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadCom(UnIn,BldFile,'mu1 to mu6',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadCom(UnIn,BldFile,'units',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadAry(UnIn,BldFile,BladeInputFileData%beta,6,'damping coefficient','damping coefficient',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + +! -------------- DISTRIBUTED PROPERTIES-------------------------------------------- + CALL ReadCom(UnIn,BldFile,'Distributed properties',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO i=1,BladeInputFileData%station_total + + CALL ReadVar(UnIn,BldFile,BladeInputFileData%station_eta(i),'station_eta','Station '//trim(num2lstr(i))//' Eta',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j=1,6 + CALL ReadAry(UnIn,BldFile,temp66(j,:),6,'siffness_matrix','Blade C/S stiffness matrix',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + BladeInputFileData%stiff0(:,:,i) = temp66 + + DO j=1,6 + CALL ReadAry(UnIn,BldFile,temp66(j,:),6,'mass_matrix','Blade C/S mass matrix',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + BladeInputFileData%mass0(:,:,i) = temp66 + + ENDDO + + call cleanup() + return + +contains + !..................... + subroutine cleanup() + close(UnIn) + return + end subroutine cleanup +END SUBROUTINE BD_ReadBladeFile +!---------------------------------------------------------------------------------------------------------------------------------- +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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-Sep-2015 10:23:41. +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + TYPE(BD_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 + + ! Local variables + + 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(352) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "N1DFXL ","N1DFYL ","N1DFZL ","N1DMXL ","N1DMYL ","N1DMZL ","N1FXL ", & + "N1FYL ","N1FZL ","N1MXL ","N1MYL ","N1MZL ","N1PFXL ","N1PFYL ", & + "N1PFZL ","N1PMXL ","N1PMYL ","N1PMZL ","N1RAXL ","N1RAYL ","N1RAZL ", & + "N1RDXR ","N1RDYR ","N1RDZR ","N1RVXG ","N1RVYG ","N1RVZG ","N1TAXL ", & + "N1TAYL ","N1TAZL ","N1TDXR ","N1TDYR ","N1TDZR ","N1TVXG ","N1TVYG ", & + "N1TVZG ","N2DFXL ","N2DFYL ","N2DFZL ","N2DMXL ","N2DMYL ","N2DMZL ", & + "N2FXL ","N2FYL ","N2FZL ","N2MXL ","N2MYL ","N2MZL ","N2PFXL ", & + "N2PFYL ","N2PFZL ","N2PMXL ","N2PMYL ","N2PMZL ","N2RAXL ","N2RAYL ", & + "N2RAZL ","N2RDXR ","N2RDYR ","N2RDZR ","N2RVXG ","N2RVYG ","N2RVZG ", & + "N2TAXL ","N2TAYL ","N2TAZL ","N2TDXR ","N2TDYR ","N2TDZR ","N2TVXG ", & + "N2TVYG ","N2TVZG ","N3DFXL ","N3DFYL ","N3DFZL ","N3DMXL ","N3DMYL ", & + "N3DMZL ","N3FXL ","N3FYL ","N3FZL ","N3MXL ","N3MYL ","N3MZL ", & + "N3PFXL ","N3PFYL ","N3PFZL ","N3PMXL ","N3PMYL ","N3PMZL ","N3RAXL ", & + "N3RAYL ","N3RAZL ","N3RDXR ","N3RDYR ","N3RDZR ","N3RVXG ","N3RVYG ", & + "N3RVZG ","N3TAXL ","N3TAYL ","N3TAZL ","N3TDXR ","N3TDYR ","N3TDZR ", & + "N3TVXG ","N3TVYG ","N3TVZG ","N4DFXL ","N4DFYL ","N4DFZL ","N4DMXL ", & + "N4DMYL ","N4DMZL ","N4FXL ","N4FYL ","N4FZL ","N4MXL ","N4MYL ", & + "N4MZL ","N4PFXL ","N4PFYL ","N4PFZL ","N4PMXL ","N4PMYL ","N4PMZL ", & + "N4RAXL ","N4RAYL ","N4RAZL ","N4RDXR ","N4RDYR ","N4RDZR ","N4RVXG ", & + "N4RVYG ","N4RVZG ","N4TAXL ","N4TAYL ","N4TAZL ","N4TDXR ","N4TDYR ", & + "N4TDZR ","N4TVXG ","N4TVYG ","N4TVZG ","N5DFXL ","N5DFYL ","N5DFZL ", & + "N5DMXL ","N5DMYL ","N5DMZL ","N5FXL ","N5FYL ","N5FZL ","N5MXL ", & + "N5MYL ","N5MZL ","N5PFXL ","N5PFYL ","N5PFZL ","N5PMXL ","N5PMYL ", & + "N5PMZL ","N5RAXL ","N5RAYL ","N5RAZL ","N5RDXR ","N5RDYR ","N5RDZR ", & + "N5RVXG ","N5RVYG ","N5RVZG ","N5TAXL ","N5TAYL ","N5TAZL ","N5TDXR ", & + "N5TDYR ","N5TDZR ","N5TVXG ","N5TVYG ","N5TVZG ","N6DFXL ","N6DFYL ", & + "N6DFZL ","N6DMXL ","N6DMYL ","N6DMZL ","N6FXL ","N6FYL ","N6FZL ", & + "N6MXL ","N6MYL ","N6MZL ","N6PFXL ","N6PFYL ","N6PFZL ","N6PMXL ", & + "N6PMYL ","N6PMZL ","N6RAXL ","N6RAYL ","N6RAZL ","N6RDXR ","N6RDYR ", & + "N6RDZR ","N6RVXG ","N6RVYG ","N6RVZG ","N6TAXL ","N6TAYL ","N6TAZL ", & + "N6TDXR ","N6TDYR ","N6TDZR ","N6TVXG ","N6TVYG ","N6TVZG ","N7DFXL ", & + "N7DFYL ","N7DFZL ","N7DMXL ","N7DMYL ","N7DMZL ","N7FXL ","N7FYL ", & + "N7FZL ","N7MXL ","N7MYL ","N7MZL ","N7PFXL ","N7PFYL ","N7PFZL ", & + "N7PMXL ","N7PMYL ","N7PMZL ","N7RAXL ","N7RAYL ","N7RAZL ","N7RDXR ", & + "N7RDYR ","N7RDZR ","N7RVXG ","N7RVYG ","N7RVZG ","N7TAXL ","N7TAYL ", & + "N7TAZL ","N7TDXR ","N7TDYR ","N7TDZR ","N7TVXG ","N7TVYG ","N7TVZG ", & + "N8DFXL ","N8DFYL ","N8DFZL ","N8DMXL ","N8DMYL ","N8DMZL ","N8FXL ", & + "N8FYL ","N8FZL ","N8MXL ","N8MYL ","N8MZL ","N8PFXL ","N8PFYL ", & + "N8PFZL ","N8PMXL ","N8PMYL ","N8PMZL ","N8RAXL ","N8RAYL ","N8RAZL ", & + "N8RDXR ","N8RDYR ","N8RDZR ","N8RVXG ","N8RVYG ","N8RVZG ","N8TAXL ", & + "N8TAYL ","N8TAZL ","N8TDXR ","N8TDYR ","N8TDZR ","N8TVXG ","N8TVYG ", & + "N8TVZG ","N9DFXL ","N9DFYL ","N9DFZL ","N9DMXL ","N9DMYL ","N9DMZL ", & + "N9FXL ","N9FYL ","N9FZL ","N9MXL ","N9MYL ","N9MZL ","N9PFXL ", & + "N9PFYL ","N9PFZL ","N9PMXL ","N9PMYL ","N9PMZL ","N9RAXL ","N9RAYL ", & + "N9RAZL ","N9RDXR ","N9RDYR ","N9RDZR ","N9RVXG ","N9RVYG ","N9RVZG ", & + "N9TAXL ","N9TAYL ","N9TAZL ","N9TDXR ","N9TDYR ","N9TDZR ","N9TVXG ", & + "N9TVYG ","N9TVZG ","PACCACT ","PANGACT ","PANGINP ","PRATACT ","ROOTFXR ", & + "ROOTFYR ","ROOTFZR ","ROOTMXR ","ROOTMYR ","ROOTMZR ","TIPRAXL ","TIPRAYL ", & + "TIPRAZL ","TIPRDXR ","TIPRDYR ","TIPRDZR ","TIPRVXG ","TIPRVYG ","TIPRVZG ", & + "TIPTAXL ","TIPTAYL ","TIPTAZL ","TIPTDXR ","TIPTDYR ","TIPTDZR ","TIPTVXG ", & + "TIPTVYG ","TIPTVZG "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(352) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + N1DFxl , N1DFyl , N1DFzl , N1DMxl , N1DMyl , N1DMzl , N1Fxl , & + N1Fyl , N1Fzl , N1Mxl , N1Myl , N1Mzl , N1PFxl , N1PFyl , & + N1PFzl , N1PMxl , N1PMyl , N1PMzl , N1RAXl , N1RAYl , N1RAZl , & + N1RDxr , N1RDyr , N1RDzr , N1RVXg , N1RVYg , N1RVZg , N1TAXl , & + N1TAYl , N1TAZl , N1TDxr , N1TDyr , N1TDzr , N1TVXg , N1TVYg , & + N1TVZg , N2DFxl , N2DFyl , N2DFzl , N2DMxl , N2DMyl , N2DMzl , & + N2Fxl , N2Fyl , N2Fzl , N2Mxl , N2Myl , N2Mzl , N2PFxl , & + N2PFyl , N2PFzl , N2PMxl , N2PMyl , N2PMzl , N2RAXl , N2RAYl , & + N2RAZl , N2RDxr , N2RDyr , N2RDzr , N2RVXg , N2RVYg , N2RVZg , & + N2TAXl , N2TAYl , N2TAZl , N2TDxr , N2TDyr , N2TDzr , N2TVXg , & + N2TVYg , N2TVZg , N3DFxl , N3DFyl , N3DFzl , N3DMxl , N3DMyl , & + N3DMzl , N3Fxl , N3Fyl , N3Fzl , N3Mxl , N3Myl , N3Mzl , & + N3PFxl , N3PFyl , N3PFzl , N3PMxl , N3PMyl , N3PMzl , N3RAXl , & + N3RAYl , N3RAZl , N3RDxr , N3RDyr , N3RDzr , N3RVXg , N3RVYg , & + N3RVZg , N3TAXl , N3TAYl , N3TAZl , N3TDxr , N3TDyr , N3TDzr , & + N3TVXg , N3TVYg , N3TVZg , N4DFxl , N4DFyl , N4DFzl , N4DMxl , & + N4DMyl , N4DMzl , N4Fxl , N4Fyl , N4Fzl , N4Mxl , N4Myl , & + N4Mzl , N4PFxl , N4PFyl , N4PFzl , N4PMxl , N4PMyl , N4PMzl , & + N4RAXl , N4RAYl , N4RAZl , N4RDxr , N4RDyr , N4RDzr , N4RVXg , & + N4RVYg , N4RVZg , N4TAXl , N4TAYl , N4TAZl , N4TDxr , N4TDyr , & + N4TDzr , N4TVXg , N4TVYg , N4TVZg , N5DFxl , N5DFyl , N5DFzl , & + N5DMxl , N5DMyl , N5DMzl , N5Fxl , N5Fyl , N5Fzl , N5Mxl , & + N5Myl , N5Mzl , N5PFxl , N5PFyl , N5PFzl , N5PMxl , N5PMyl , & + N5PMzl , N5RAXl , N5RAYl , N5RAZl , N5RDxr , N5RDyr , N5RDzr , & + N5RVXg , N5RVYg , N5RVZg , N5TAXl , N5TAYl , N5TAZl , N5TDxr , & + N5TDyr , N5TDzr , N5TVXg , N5TVYg , N5TVZg , N6DFxl , N6DFyl , & + N6DFzl , N6DMxl , N6DMyl , N6DMzl , N6Fxl , N6Fyl , N6Fzl , & + N6Mxl , N6Myl , N6Mzl , N6PFxl , N6PFyl , N6PFzl , N6PMxl , & + N6PMyl , N6PMzl , N6RAXl , N6RAYl , N6RAZl , N6RDxr , N6RDyr , & + N6RDzr , N6RVXg , N6RVYg , N6RVZg , N6TAXl , N6TAYl , N6TAZl , & + N6TDxr , N6TDyr , N6TDzr , N6TVXg , N6TVYg , N6TVZg , N7DFxl , & + N7DFyl , N7DFzl , N7DMxl , N7DMyl , N7DMzl , N7Fxl , N7Fyl , & + N7Fzl , N7Mxl , N7Myl , N7Mzl , N7PFxl , N7PFyl , N7PFzl , & + N7PMxl , N7PMyl , N7PMzl , N7RAXl , N7RAYl , N7RAZl , N7RDxr , & + N7RDyr , N7RDzr , N7RVXg , N7RVYg , N7RVZg , N7TAXl , N7TAYl , & + N7TAZl , N7TDxr , N7TDyr , N7TDzr , N7TVXg , N7TVYg , N7TVZg , & + N8DFxl , N8DFyl , N8DFzl , N8DMxl , N8DMyl , N8DMzl , N8Fxl , & + N8Fyl , N8Fzl , N8Mxl , N8Myl , N8Mzl , N8PFxl , N8PFyl , & + N8PFzl , N8PMxl , N8PMyl , N8PMzl , N8RAXl , N8RAYl , N8RAZl , & + N8RDxr , N8RDyr , N8RDzr , N8RVXg , N8RVYg , N8RVZg , N8TAXl , & + N8TAYl , N8TAZl , N8TDxr , N8TDyr , N8TDzr , N8TVXg , N8TVYg , & + N8TVZg , N9DFxl , N9DFyl , N9DFzl , N9DMxl , N9DMyl , N9DMzl , & + N9Fxl , N9Fyl , N9Fzl , N9Mxl , N9Myl , N9Mzl , N9PFxl , & + N9PFyl , N9PFzl , N9PMxl , N9PMyl , N9PMzl , N9RAXl , N9RAYl , & + N9RAZl , N9RDxr , N9RDyr , N9RDzr , N9RVXg , N9RVYg , N9RVZg , & + N9TAXl , N9TAYl , N9TAZl , N9TDxr , N9TDyr , N9TDzr , N9TVXg , & + N9TVYg , N9TVZg , PAccAct , PAngAct , PAngInp , PRatAct , RootFxr , & + RootFyr , RootFzr , RootMxr , RootMyr , RootMzr , TipRAXl , TipRAYl , & + TipRAZl , TipRDxr , TipRDyr , TipRDzr , TipRVXg , TipRVYg , TipRVZg , & + TipTAXl , TipTAYl , TipTAZl , TipTDxr , TipTDyr , TipTDzr , TipTVXg , & + TipTVYg , TipTVZg /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(352) = (/ & ! This lists the units corresponding to the allowed parameters + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ", & + "(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ", & + "(m/s) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ", & + "(deg/s^2) ","(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ", & + "(m/s) ","(m/s) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ", & + "(deg/s^2) ","(deg/s^2) ","(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ", & + "(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(m/s) ","(m/s) ","(m/s) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(-) ","(-) ","(-) ","(deg/s) ", & + "(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(m/s) ","(m/s) ","(m/s) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(-) ","(-) ","(-) ", & + "(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(-) ","(-) ", & + "(-) ","(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(-) ", & + "(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ", & + "(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ", & + "(m/s) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ", & + "(deg/s^2) ","(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ", & + "(m/s) ","(m/s) ","(deg/s^2) ","(deg) ","(deg) ","(deg/s) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(deg/s^2) ","(deg/s^2) ", & + "(deg/s^2) ","(-) ","(-) ","(-) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m/s) ", & + "(m/s) ","(m/s) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + DO I = p%NNodeOuts+1,9 ! Invalid nodes + + InvalidOutput( NFl( i,:) ) = .true. + InvalidOutput( NMl( i,:) ) = .true. + InvalidOutput( NTDr(i,:) ) = .true. + InvalidOutput( NRDr(i,:) ) = .true. + InvalidOutput( NTVg(i,:) ) = .true. + InvalidOutput( NRVg(i,:) ) = .true. + InvalidOutput( NTAl(i,:) ) = .true. + InvalidOutput( NRAl(i,:) ) = .true. + InvalidOutput( NPFl(i,:) ) = .true. + InvalidOutput( NPMl(i,:) ) = .true. + InvalidOutput( NDFl(i,:) ) = .true. + InvalidOutput( NDMl(i,:) ) = .true. + + END DO + + IF (.not. p%UsePitchAct) THEN + InvalidOutput( PAngInp ) = .true. + InvalidOutput( PAngAct ) = .true. + InvalidOutput( PRatAct ) = .true. + InvalidOutput( PAccAct ) = .true. + END IF + + if (p%BldMotionNodeLoc /= BD_MESH_FE) then + DO I = 1,9 + InvalidOutput( NPFl(i,:) ) = .true. + InvalidOutput( NPMl(i,:) ) = .true. + END DO + end if + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the BeamDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + + if ( p%OutParam(I)%Indx >= N1DFxl .and. p%OutParam(I)%Indx <= N9DMzl ) p%OutInputs = .true. + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = Time ! pick any valid channel (I just picked "Time" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the BeamDyn input files. +SUBROUTINE BD_ValidateInputData( InitInp, InputFileData, ErrStat, ErrMsg ) + + ! Passed variables: + + TYPE(BD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(BD_InputFile), INTENT(IN ) :: InputFileData !< All the data in the BeamDyn input file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + + ! local variables + INTEGER(IntKi) :: i,j ! loop counters + INTEGER(IntKi) :: nNodes ! number of nodes that will be on the BldMotion mesh + REAL(SiKi) :: r1, r2 ! use single-precision real numbers for validity check + + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ValidateInputData' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! QuasiStaticInit only valid with DynamicSolve. Warn and ignore + IF(InputFileData%QuasiStaticInit .AND. (.NOT. InitInp%DynamicSolve)) & + CALL SetErrStat ( ErrID_Warn, 'QuasiStaticInit option only valid with dynamic solve. Ignoring.', ErrStat, ErrMsg, RoutineName ) + + IF(InputFileData%rhoinf .LT. 0.0_BDKi .OR. InputFileData%rhoinf .GT. 1.0_BDKi) & + CALL SetErrStat ( ErrID_Fatal, 'Numerical damping parameter \rho_{inf} must be in the range of [0.0,1.0]', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%quadrature .NE. GAUSS_QUADRATURE .AND. InputFileData%quadrature .NE. TRAP_QUADRATURE) & + CALL SetErrStat ( ErrID_Fatal, 'Quadrature type must be 1 (Gauss) or 2 (Trapezoidal)', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%refine .LT. 1 ) & + CALL SetErrStat ( ErrID_Fatal, 'Refinement parameter must be greater than or equal to 1', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%n_fact .LT. 1 ) & + CALL SetErrStat ( ErrID_Fatal, 'Factorization parameter must be greater than or equal to 1', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%member_total .LT. 1 ) & + CALL SetErrStat ( ErrID_Fatal, 'member_total must be greater than 0', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%member_total .NE. 1 .AND. InputFileData%quadrature .EQ. TRAP_QUADRATURE) & + CALL SetErrStat ( ErrID_Fatal, 'Trapzoidal quadrature only allows one member (element)', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%kp_total .LT. 3 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'kp_total must be greater than or equal to 3', ErrStat, ErrMsg, RoutineName ) + ELSE ! added this in the "else" in case InputFileData%kp_coordinate isn't allocated with at least 1 point + IF ( .not. EqualRealNos( InputFileData%kp_coordinate(1,3), 0.0_BDKi ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'kp_zr on first key point must be 0.', ErrStat, ErrMsg, RoutineName ) + END IF + !bjj: added checks on kp_xr(1) and kp_yr(1) because BeamDyn's equations currently assume that the blade root and the first FE node + ! are at the same point (i.e., u%BladeRoot is located at the first finite-element node) + IF ( .not. EqualRealNos( InputFileData%kp_coordinate(1,2), 0.0_BDKi ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'kp_yr on first key point must be 0.', ErrStat, ErrMsg, RoutineName ) + END IF + IF ( .not. EqualRealNos( InputFileData%kp_coordinate(1,1), 0.0_BDKi ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'kp_xr on first key point must be 0.', ErrStat, ErrMsg, RoutineName ) + END IF + END IF + + DO i=1,InputFileData%member_total + IF(InputFileData%kp_member(i) .LT. 3) THEN + CALL SetErrStat(ErrID_Fatal,'There must be at least three key points in member number '//TRIM(Num2LStr(i))//'.', ErrStat, ErrMsg,RoutineName) + EXIT + ENDIF + ENDDO + IF(SUM(InputFileData%kp_member) .NE. InputFileData%kp_total+InputFileData%member_total-1 ) & + CALL SetErrStat ( ErrID_Fatal, 'Geometric definition error: kp_total and key points in each member are inconsistent', ErrStat, ErrMsg,RoutineName) + + IF(InputFileData%order_elem .LT. 1 ) & + CALL SetErrStat ( ErrID_Fatal, 'order_elem must be greater than 0', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%order_elem .LT. 2 .AND. InputFileData%quadrature .EQ. GAUSS_QUADRATURE) & + CALL SetErrStat ( ErrID_Fatal, 'order_elem must be greater than 1 for Gauss quadrature', ErrStat, ErrMsg, RoutineName ) + + IF(InputFileData%InpBl%station_total .LT. 2 ) & + CALL SetErrStat ( ErrID_Fatal, 'Number of material stations along blade axis much be greater than 2', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%InpBl%station_eta(1) .NE. 0.0_BDKi ) & + CALL SetErrStat ( ErrID_Fatal, 'The first station_eta must be equal to 0.0 (root)', ErrStat, ErrMsg, RoutineName ) + IF(InputFileData%InpBl%station_eta(InputFileData%InpBl%station_total) .NE. 1.0_BDKi ) & + CALL SetErrStat ( ErrID_Fatal, 'The last station_eta must be equal to 1.0 (tip)', ErrStat, ErrMsg, RoutineName ) + + IF (InputFileData%NRMax < 2) CALL SetErrStat ( ErrID_Fatal, 'Maximum number of iterations in Newton-Raphson (NRMax) must be greater than 1.', ErrStat, ErrMsg, RoutineName ) + IF (InputFileData%stop_tol < EPSILON(InputFileData%stop_tol) ) & + CALL SetErrStat ( ErrID_Fatal, 'Tolerance for stopping (stop_tol) must be larger than machine precision ('//trim(num2lstr(EPSILON(InputFileData%stop_tol)))//').', ErrStat, ErrMsg, RoutineName ) + + if (InputFileData%UsePitchAct) then + if ( EqualRealNos(InputFileData%pitchJ, 0.0_BDKi) ) call SetErrStat(ErrID_Fatal,'Pitch actuator inertia must not be 0.',ErrStat,ErrMsg,RoutineName) + end if + + !bjj: should check that there aren't any overlapping trapezoidal quadrature points (is this done in the input file section??) + + ! Check that the values for the damping are similar. + ! According to Qi, the damping values mu1 .. mu6 should be of the same order of magnitude. If they aren't, BeamDyn will likely fail badly. + ! Will assume for moment that they must be within a factor of 5 of the first value given. +!FIXME: Check a valid range sometime. + IF ( (maxval(abs(InputFileData%InpBl%beta)) / minval(abs(InputFileData%InpBl%beta)) > 10.0_R8Ki) .AND. InputFileData%InpBl%damp_flag == 1 ) THEN + call SetErrStat( ErrID_Warn,'Damping values in blade file are not of similar order of magnitude. BeamDyn may not converge!', ErrStat, ErrMsg, RoutineName ) + ENDIF + + + DO j=1,InputFileData%InpBl%station_total + DO i=2,3 + IF ( .not. EqualRealNos( InputFileData%InpBl%mass0(i,i,j), InputFileData%InpBl%mass0(1,1,j) ) ) then + call SetErrStat( ErrID_Fatal, 'Input station '//trim(num2lstr(j))//' mass densities are not the same (i.e., first 3 diagonal elements in mass matrix must be equal).', ErrStat, ErrMsg, RoutineName ) + exit + END IF + END DO + + !............ + ! NOTE: InputFileData%InpBl%mass0 is in IEC coordinates (it was previously in beam coordinates); error message refers to IEC coordinates in input file + r1 = InputFileData%InpBl%mass0(6,6,j) + r2 = InputFileData%InpBl%mass0(4,4,j) + InputFileData%InpBl%mass0(5,5,j) + IF ( abs(r1 - r2) > Mass0Tol ) then + call SetErrStat( ErrID_Fatal, 'Input station '//trim(num2lstr(j))//' i_plr must equal i_Edg + i_Flp (i.e., sum of 4th and 5th diagonal elements in mass matrix must equal the 6th diagonal element).', ErrStat, ErrMsg, RoutineName ) + END IF + !............ + END DO + + + ! ............................. + ! check outputs: + ! ............................. + + if ( ( InputFileData%NNodeOuts < 0_IntKi ) .OR. ( InputFileData%NNodeOuts > 9_IntKi ) ) then + call SetErrStat( ErrID_Fatal, 'NNodeOuts must be between 0 and 9 (inclusive).', ErrStat, ErrMsg, RoutineName ) + else + + ! Check to see if all OutNd(:) analysis points are existing analysis points: +!bjj: FIXME!!!! THIS ISN'T NECESSARIALLY THE NUMBER OF NODES ON THIS MESH +! IF (p%BldMotionNodeLoc == BD_MESH_QP) THEN + if(InputFileData%quadrature .EQ. TRAP_QUADRATURE) then + nNodes = (InputFileData%InpBl%station_total - 1)*InputFileData%refine + 1 ! number of nodes on y%BldMotion mesh + else + nNodes = (InputFileData%order_elem + 1)*InputFileData%member_total ! = p%nodes_per_elem*p%elem_total (number of nodes on y%BldMotion mesh) + end if +! ELSE +! nNodes = (InputFileData%order_elem + 1)*InputFileData%member_total + 1 +! END IF + + do j=1,InputFileData%NNodeOuts + if ( InputFileData%OutNd(j) < 1_IntKi .OR. InputFileData%OutNd(j) > nNodes ) then + call SetErrStat( ErrID_Fatal, ' All OutNd values must be between 1 and '//& + trim( Num2LStr( nNodes ) )//' (inclusive).', ErrStat, ErrMsg, RoutineName ) + exit ! stop checking this loop + end if + end do + + end if + + !.................. + ! check for linearization + !.................. + if (InitInp%Linearize) then + if (.NOT. InitInp%DynamicSolve) THEN + call SetErrStat( ErrID_Fatal, 'Static analysis cannot be used for BeamDyn linearization. Set DynamicSolve to TRUE.', ErrStat, ErrMsg, RoutineName ) + end if + + if (InputFileData%UsePitchAct) then + call SetErrStat( ErrID_Fatal, 'Pitch actuator model cannot currently be used for linearization in BeamDyn. Set UsePitchAct=False.', ErrStat, ErrMsg, RoutineName ) + end if + end if + +END SUBROUTINE BD_ValidateInputData +!---------------------------------------------------------------------------------------------------------------------------------- +!> this routine fills the AllOuts array, which is used to send data to the glue code to be written to an output file. +SUBROUTINE Calc_WriteOutput( p, AllOuts, y, m, ErrStat, ErrMsg, CalcWriteOutput ) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< The module parameters + REAL(ReKi), INTENT(INOUT) :: AllOuts(0:) !< array of values to potentially write to file + TYPE(BD_OutputType), INTENT(IN ) :: y !< outputs + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables (for computing mesh transfers) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message, if an error occurred + LOGICAL , INTENT(IN ) :: CalcWriteOutput !< flag that determines if we need to compute AllOuts (or just the reaction loads that get returned to ServoDyn) + + ! local variables + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteOutput' + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + INTEGER(IntKi) :: j,beta,j_BldMotion + REAL(BDKi) :: temp_vec(3) + REAL(BDKi) :: temp_vec2(3) + REAL(BDKi) :: temp33(3,3) + REAL(BDKi) :: temp33_2(3,3) + + REAL(BDKi) :: d_ref(3) + REAL(BDKi) :: d(3) + REAL(BDKi) :: RootRelOrient(3,3) + + + + ! start routine: + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------- + ! Reaction forces + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%ReactionForce%Force(:,1)) + AllOuts( RootFxr ) = temp_vec(1) + AllOuts( RootFyr ) = temp_vec(2) + AllOuts( RootFzr ) = temp_vec(3) + + !------------------------- + ! Reaction moments (these are being computed for ServoDyn output, as well as for WriteOutput) + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),y%ReactionForce%Moment(:,1)) + AllOuts( RootMxr ) = temp_vec(1) + AllOuts( RootMyr ) = temp_vec(2) + AllOuts( RootMzr ) = temp_vec(3) + + !------------------------- + ! we don't need to calculate the rest of these values if we don't ask for WriteOutput channels + ! (but we did need RootMxr and RootMyr) + if ( p%NumOuts <= 0 .or. .not. CalcWriteOutput) RETURN + !------------------------- + + + ! compute the root relative orientation, RootRelOrient, which is used in several calculations below + ! RootRelOrient = matmul( transpose(m%u2%RootMotion%Orientation(:,:,1)), m%u2%RootMotion%RefOrientation(:,:,1)) + call LAPACK_DGEMM('T', 'N', 1.0_BDKi, m%u2%RootMotion%Orientation(:,:,1), m%u2%RootMotion%RefOrientation(:,:,1), 0.0_BDKi, RootRelOrient, ErrStat2, ErrMsg2 ) + + !------------------------------------ + ! Tip translational deflection (relative to the undeflected position) expressed in r + d = y%BldMotion%TranslationDisp(:, y%BldMotion%NNodes) - m%u2%RootMotion%TranslationDisp(:,1) + d_ref = y%BldMotion%Position( :, y%BldMotion%NNodes) - m%u2%RootMotion%Position( :,1) + temp_vec2 = d + d_ref - matmul( RootRelOrient, d_ref ) ! tip displacement + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) + + AllOuts( TipTDxr ) = temp_vec(1) + AllOuts( TipTDyr ) = temp_vec(2) + AllOuts( TipTDzr ) = temp_vec(3) + + !------------------------- + ! Tip angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) expressed in r + call LAPACK_DGEMM('N', 'T', 1.0_BDKi, y%BldMotion%RefOrientation(:,:,y%BldMotion%NNodes), RootRelOrient, 0.0_BDKi, temp33_2, ErrStat2, ErrMsg2 ) + call LAPACK_DGEMM('T', 'N', 1.0_BDKi, y%BldMotion%Orientation( :,:,y%BldMotion%NNodes), temp33_2, 0.0_BDKi, temp33, ErrStat2, ErrMsg2 ) + call BD_CrvExtractCrv(temp33,temp_vec2, ErrStat2, ErrMsg2) ! temp_vec2 = the Wiener-Milenkovic parameters of the tip angular/rotational defelctions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) ! translate these parameters to the correct system for output + + AllOuts( TipRDxr ) = temp_vec(1) + AllOuts( TipRDyr ) = temp_vec(2) + AllOuts( TipRDzr ) = temp_vec(3) + + !------------------------- + ! Tip translational velocities (absolute) expressed in g, given in m/s + AllOuts( TipTVXg ) = y%BldMotion%TranslationVel(1,y%BldMotion%NNodes) + AllOuts( TipTVYg ) = y%BldMotion%TranslationVel(2,y%BldMotion%NNodes) + AllOuts( TipTVZg ) = y%BldMotion%TranslationVel(3,y%BldMotion%NNodes) + + !------------------------- + ! Tip angular/rotational velocities (absolute) expressed in g, given in deg/s + AllOuts( TipRVXg ) = y%BldMotion%RotationVel(1,y%BldMotion%NNodes)*R2D + AllOuts( TipRVYg ) = y%BldMotion%RotationVel(2,y%BldMotion%NNodes)*R2D + AllOuts( TipRVZg ) = y%BldMotion%RotationVel(3,y%BldMotion%NNodes)*R2D + + !------------------------- + ! Tip translational accelerations (absolute) expressed in l, given in m/s^2 + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,y%BldMotion%NNodes), y%BldMotion%TranslationAcc(:,y%BldMotion%NNodes)) ! translate accelerations to local system for output + AllOuts( TipTAXl ) = temp_vec(1) + AllOuts( TipTAYl ) = temp_vec(2) + AllOuts( TipTAZl ) = temp_vec(3) + + !------------------------- + ! Tip angular/rotational accelerations (absolute) expressed in l, given in deg/s^2 + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,y%BldMotion%NNodes), y%BldMotion%RotationAcc(:,y%BldMotion%NNodes)) ! translate accelerations to local system for output + AllOuts( TipRAXl ) = temp_vec(1)*R2D + AllOuts( TipRAYl ) = temp_vec(2)*R2D + AllOuts( TipRAZl ) = temp_vec(3)*R2D + + + !------------------------------------ + ! Calculate Motion of blade nodes + !------------------------------------ + + ! outputs on the nodes + DO beta=1,p%NNodeOuts + + j=p%OutNd(beta) + j_BldMotion = p%NdIndx(j) + + !------------------------------------ + ! Sectional force resultants at Node 1 expressed in l, given in N + SELECT CASE (p%BldMotionNodeLoc) + CASE (BD_MESH_FE) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%BldInternalForceFE(1:3,j)) + CASE (BD_MESH_QP) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%BldInternalForceQP(1:3,j)) + END SELECT + AllOuts( NFl( beta,1 ) ) = temp_vec(1) + AllOuts( NFl( beta,2 ) ) = temp_vec(2) + AllOuts( NFl( beta,3 ) ) = temp_vec(3) + + !------------------------------------ + ! Sectional moment resultants at Node 1 expressed in l, given in N-m + SELECT CASE (p%BldMotionNodeLoc) + CASE (BD_MESH_FE) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%BldInternalForceFE(4:6,j)) + CASE (BD_MESH_QP) + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%BldInternalForceQP(4:6,j)) + END SELECT + AllOuts( NMl( beta,1 ) ) = temp_vec(1) + AllOuts( NMl( beta,2 ) ) = temp_vec(2) + AllOuts( NMl( beta,3 ) ) = temp_vec(3) + + + !------------------------------------ + ! Sectional translational deflection (relative to the undeflected position) expressed in r + d = y%BldMotion%TranslationDisp(:, j_BldMotion) - m%u2%RootMotion%TranslationDisp(:,1) + d_ref = y%BldMotion%Position( :, j_BldMotion) - m%u2%RootMotion%Position( :,1) + temp_vec2 = d + d_ref - MATMUL( RootRelOrient, d_ref ) ! tip displacement + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) + + AllOuts( NTDr( beta,1 ) ) = temp_vec(1) + AllOuts( NTDr( beta,2 ) ) = temp_vec(2) + AllOuts( NTDr( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Sectional angular/rotational deflection Wiener-Milenkovic parameter (relative to the undeflected orientation) expressed in r + call LAPACK_DGEMM('N', 'T', 1.0_BDKi, y%BldMotion%RefOrientation(:,:,j_BldMotion), RootRelOrient, 0.0_BDKi, temp33_2, ErrStat2, ErrMsg2 ) + call LAPACK_DGEMM('T', 'N', 1.0_BDKi, y%BldMotion%Orientation( :,:,j_BldMotion), temp33_2, 0.0_BDKi, temp33, ErrStat2, ErrMsg2 ) + call BD_CrvExtractCrv(temp33,temp_vec2, ErrStat2, ErrMsg2) ! temp_vec2 = the Wiener-Milenkovic parameters of the node's angular/rotational defelctions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + temp_vec = MATMUL(m%u2%RootMotion%Orientation(:,:,1),temp_vec2) ! translate these parameters to the correct system for output + + AllOuts( NRDr( beta,1 ) ) = temp_vec(1) + AllOuts( NRDr( beta,2 ) ) = temp_vec(2) + AllOuts( NRDr( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Sectional translational velocities (absolute) expressed in g, given in m/s + AllOuts( NTVg( beta,1 ) ) = y%BldMotion%TranslationVel(1,j_BldMotion) + AllOuts( NTVg( beta,2 ) ) = y%BldMotion%TranslationVel(2,j_BldMotion) + AllOuts( NTVg( beta,3 ) ) = y%BldMotion%TranslationVel(3,j_BldMotion) + + !------------------------- + ! Sectional angular/rotational velocities (absolute) expressed in g, given in deg/s + AllOuts( NRVg( beta,1 ) ) = y%BldMotion%RotationVel(1,j_BldMotion)*R2D + AllOuts( NRVg( beta,2 ) ) = y%BldMotion%RotationVel(2,j_BldMotion)*R2D + AllOuts( NRVg( beta,3 ) ) = y%BldMotion%RotationVel(3,j_BldMotion)*R2D + + + !------------------------- + ! Sectional Tip translational accelerations (absolute) expressed in l, given in m/s^2 + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), y%BldMotion%TranslationAcc(:,j_BldMotion)) + AllOuts( NTAl( beta,1 ) ) = temp_vec(1) + AllOuts( NTAl( beta,2 ) ) = temp_vec(2) + AllOuts( NTAl( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Sectional angular/rotational accelerations (absolute) expressed in l, given in deg/s^2 + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), y%BldMotion%RotationAcc(:,j_BldMotion)) + AllOuts( NRAl( beta,1 ) ) = temp_vec(1)*R2D + AllOuts( NRAl( beta,2 ) ) = temp_vec(2)*R2D + AllOuts( NRAl( beta,3 ) ) = temp_vec(3)*R2D + + + if (p%BldMotionNodeLoc == BD_MESH_FE) THEN !> FIXME: If we are on the finite element points, the input and output meshes are siblings, otherwise we need to multiply by a different orientation (if we're okay + !! with the nodes meaning something different) or we need to map the u2%PointLoad like we do for the m%u2%DistrLoad%Force loads. + !------------------------- + ! Applied point forces at Node 1 expressed in l, given in N + temp_vec = MATMUL(y%BldMotion%Orientation(1:3,1:3,j_BldMotion),m%u2%PointLoad%Force(:,j)) + AllOuts( NPFl( beta,1 ) ) = temp_vec(1) + AllOuts( NPFl( beta,2 ) ) = temp_vec(2) + AllOuts( NPFl( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Applied point moments at Node 1 expressed in l, given in N-m + temp_vec = MATMUL(y%BldMotion%Orientation(1:3,1:3,j_BldMotion),m%u2%PointLoad%Moment(:,j)) + AllOuts( NPMl( beta,1 ) ) = temp_vec(1) + AllOuts( NPMl( beta,2 ) ) = temp_vec(2) + AllOuts( NPMl( beta,3 ) ) = temp_vec(3) + end if + + + end do ! nodes + + ! to avoid unnecessary mesh mapping calculations, calculate these outputs only when we've requested them + if (p%OutInputs) then + + if (p%BldMotionNodeLoc == BD_MESH_QP) THEN ! If we are on the quadrature points, the input and output meshes are siblings + + do beta=1,p%NNodeOuts + + j=p%OutNd(beta) + j_BldMotion = p%NdIndx(j) + + !------------------------- + ! Applied distributed forces at Node 1 expressed in l, in N/m + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%u2%DistrLoad%Force( :,j_BldMotion)) + AllOuts( NDFl( beta,1 ) ) = temp_vec(1) + AllOuts( NDFl( beta,2 ) ) = temp_vec(2) + AllOuts( NDFl( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Applied distributed moments at Node 1 expressed in l, in N-m/m + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%u2%DistrLoad%Moment(:,j_BldMotion)) + AllOuts( NDMl( beta,1 ) ) = temp_vec(1) + AllOuts( NDMl( beta,2 ) ) = temp_vec(2) + AllOuts( NDMl( beta,3 ) ) = temp_vec(3) + + end do ! nodes + + + else + + + ! transfer the output motions to the input nodes for load transfer + CALL Transfer_Line2_to_Line2( y%BldMotion, m%y_BldMotion_at_u, m%Map_y_BldMotion_to_u, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! transfer the input loads to the output nodes for writing output + CALL Transfer_Line2_to_Line2( m%u2%DistrLoad, m%u_DistrLoad_at_y, m%Map_u_DistrLoad_to_y, ErrStat2, ErrMsg2, m%y_BldMotion_at_u, y%BldMotion) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + do beta=1,p%NNodeOuts + + j=p%OutNd(beta) + j_BldMotion = p%NdIndx(j) + + !------------------------- + ! Applied distributed forces at Node 1 expressed in l, in N/m + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%u_DistrLoad_at_y%Force( :,j_BldMotion)) + AllOuts( NDFl( beta,1 ) ) = temp_vec(1) + AllOuts( NDFl( beta,2 ) ) = temp_vec(2) + AllOuts( NDFl( beta,3 ) ) = temp_vec(3) + + !------------------------- + ! Applied distributed moments at Node 1 expressed in l, in N-m/m + temp_vec = MATMUL(y%BldMotion%Orientation(:,:,j_BldMotion), m%u_DistrLoad_at_y%Moment(:,j_BldMotion)) + AllOuts( NDMl( beta,1 ) ) = temp_vec(1) + AllOuts( NDMl( beta,2 ) ) = temp_vec(2) + AllOuts( NDMl( beta,3 ) ) = temp_vec(3) + + end do ! nodes + + end if + + + end if + + + + +END SUBROUTINE Calc_WriteOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine generates the summary file, which contains a regurgitation of the input data and interpolated flexible body data. +SUBROUTINE BD_PrintSum( p, x, m, InitInp, ErrStat, ErrMsg ) + + ! passed variables + TYPE(BD_ParameterType), INTENT(IN) :: p !< Parameters of the structural dynamics module + type(BD_ContinuousStateType), intent(in) :: x !< Continuous states + TYPE(BD_MiscVarType), INTENT(INout) :: m !< misc/optimization variables + TYPE(BD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< error message + + + ! Local variables. + + INTEGER(IntKi) :: I ! Index for the nodes + INTEGER(IntKi) :: j, k ! Generic index + INTEGER(IntKi) :: UnSu ! I/O unit number for the summary output file + + CHARACTER(*), PARAMETER :: FmtDat = '(A,T35,1(:,F13.3))' ! Format for outputting mass and modal data. + CHARACTER(*), PARAMETER :: FmtDatT = '(A,T35,1(:,F13.8))' ! Format for outputting time steps. + + CHARACTER(30) :: OutPFmt ! Format to print list of selected output channels to summary file + + ! Open the summary file and give it a heading. + + CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) + CALL OpenFOutFile ( UnSu, TRIM( InitInp%RootName )//'.sum', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Heading: + WRITE (UnSu,'(/,A)') 'This summary information was generated by '//TRIM( GetNVD(BeamDyn_Ver) )// & + ' on '//CurDate()//' at '//CurTime()//'.' + + WRITE (UnSu,'(A,F13.3)') 'Blade mass (kg) ', p%blade_mass + WRITE (UnSu,'(A,F13.3)' ) 'Blade length (m) ', p%blade_length + + WRITE (UnSu,'(A)') 'Blade center of mass (IEC coords): ' + WRITE (UnSu,'(3ES18.5)' ) p%blade_CG(:) + + WRITE (UnSu,'(A)') 'Blade mass moment of inertia: ' + DO i=1,3 + WRITE (UnSu,'(3ES18.5)' ) p%blade_IN(i,:) + ENDDO + + WRITE (UnSu,'(A)') 'Global position vector (IEC coords):' + WRITE (UnSu,'(3ES18.5)' ) p%GlbPos(:) + + WRITE (UnSu,'(A)') 'Global rotation tensor (IEC coords):' + DO i=1,3 + WRITE (UnSu,'(3ES18.5)' ) p%GlbRot(i,:) + ENDDO + + WRITE (UnSu,'(A)') 'Initial blade orientation tensor (relative to global rotation tensor):' + DO i=1,3 + WRITE (UnSu,'(3ES18.5)' ) InitInp%RootOri(i,:) + ENDDO + + WRITE (UnSu,'(A)') 'Global rotation WM parameters (IEC coords):' + WRITE (UnSu,'(3ES18.5)' ) p%Glb_crv(:) + + WRITE (UnSu,'(A)') 'Gravity vector (m/s^2) (IEC coords):' + WRITE (UnSu,'(3ES18.5)' ) p%gravity(:) + +!FIXME:analysis_type + IF(p%analysis_type .EQ. BD_STATIC_ANALYSIS) THEN + WRITE (UnSu,'(A,T59,A15)') 'Analysis type:','STATIC' + ELSEIF(p%analysis_type .EQ. BD_DYNAMIC_ANALYSIS) THEN + WRITE (UnSu,'(A,T59,A15)') 'Analysis type:','DYNAMIC' + ELSEIF(p%analysis_type .EQ. BD_DYN_SSS_ANALYSIS) THEN + WRITE (UnSu,'(A,T37,A)') 'Analysis type:','DYNAMIC with quasi-steady-state start' + ENDIF + + WRITE (UnSu,'(A,T59,1ES15.5)') 'Numerical damping parameter:',p%rhoinf + + WRITE (UnSu,'(A,T59,1ES15.5)') 'Time increment:',p%dt + + WRITE (UnSu,'(A,T59,I15)' ) 'Maximum number of iterations in Newton-Raphson solution:', p%niter + WRITE (UnSu,'(A,T59,1ES15.5)' ) 'Convergence parameter:', p%tol + WRITE (UnSu,'(A,T59,I15)' ) 'Factorization frequency in Newton-Raphson solution:', p%n_fact + + IF(p%quadrature .EQ. GAUSS_QUADRATURE) THEN + WRITE (UnSu,'(A,T59,A15)') 'Quadrature method: ', 'Gaussian' + ELSEIF(p%quadrature .EQ. TRAP_QUADRATURE) THEN + WRITE (UnSu,'(A,T59,A15)') 'Quadrature method: ', 'Trapezoidal' + WRITE (UnSu,'(A,T59,I15)' ) 'FE mesh refinement factor:', p%refine + ENDIF + + WRITE (UnSu,'(A,T59,I15)' ) 'Number of elements: ', p%elem_total + + WRITE (UnSu,'(A,T59,I15)' ) 'Number of nodes: ', p%node_total + + WRITE (UnSu,'(/,A)') 'Initial position vectors (IEC coordinate system)' + k=1 + DO i=1,p%elem_total + WRITE (UnSu,'(2x,A,I4)') 'Element number: ',i + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') 'Node', 'Global node',' X ',' Y ',' Z ' + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') '----', '-----------','-----------------','-----------------','-----------------' + DO j = 1, p%nodes_per_elem + WRITE(UnSu,'(I6,1x,I9,2x,3ES18.5)') j,k,p%uuN0(1:3,j,i) + k=k+1 + ENDDO + k = k-1 + ENDDO + WRITE (UnSu,'(/,A)') 'Initial Weiner-Milenkovic rotation vectors (IEC coordinate system)' + k=1 + DO i=1,p%elem_total + WRITE (UnSu,'(2x,A,I4)') 'Element number: ',i + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') 'Node', 'Global node',' WM_x ',' WM_y ',' WM_z ' + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') '----', '-----------','-----------------','-----------------','-----------------' + DO j = 1, p%nodes_per_elem + WRITE(UnSu,'(I6,1x,I9,2x,3ES18.5)') j,k,p%uuN0(4:6,j,i) + k=k+1 + ENDDO + k = k-1 + ENDDO + + WRITE (UnSu,'(/,A)') 'Quadrature point position vectors' + k=1 + DO i=1,p%elem_total + WRITE (UnSu,'(2x,A,I4)') 'Element number: ',i + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') ' QP ', ' Global QP ',' X ',' Y ',' Z ' + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') '----', '-----------','-----------------','-----------------','-----------------' + DO j = 1, p%nqp + WRITE(UnSu,'(I6,1x,I9,2x,3ES18.5)') j,k,p%uu0(1:3,j,i) + k=k+1 + ENDDO + k = k-1 + ENDDO + WRITE (UnSu,'(/,A)') 'Quadrature point rotation vectors' + k=1 + DO i=1,p%elem_total + WRITE (UnSu,'(2x,A,I4)') 'Element number: ',i + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') ' QP ', ' Global QP ',' WM_x ',' WM_y ',' WM_z ' + WRITE (UnSu, '(2x,A,1x,A,1x,3(1x,A))') '----', '-----------','-----------------','-----------------','-----------------' + DO j = 1, p%nqp + WRITE(UnSu,'(I6,1x,I9,2x,3ES18.5)') j,k,p%uu0(4:6,j,i) + k=k+1 + ENDDO + k = k-1 + ENDDO + + WRITE (UnSu,'(/,A)') 'Sectional stiffness and mass matrices at quadrature points (in IEC coordinates)' + DO i=1,size(p%Stif0_QP,3) + WRITE (UnSu,'(/,A,I4)') 'Quadrature point number: ',i + DO j=1,6 + WRITE(UnSu,'(6ES15.5)') p%Stif0_QP(j,1:6,i) + ENDDO + WRITE(UnSu,'(A)') + DO j=1,6 + WRITE(UnSu,'(6ES15.5)') p%Mass0_QP(j,1:6,i) + ENDDO + ENDDO + + WRITE (UnSu,'(/,A)') 'Initial displacement' + DO i=1,p%node_total + WRITE(UnSu,'(I4,3ES18.5)') i,x%q(1:3,i) + ENDDO + + WRITE (UnSu,'(/,A)') 'Initial rotation' + DO i=1,p%node_total + WRITE(UnSu,'(I4,3ES18.5)') i,x%q(4:6,i) + ENDDO + + WRITE (UnSu,'(/,A)') 'Initial velocity' + DO i=1,p%node_total + WRITE(UnSu,'(I4,3ES18.5)') i,x%dqdt(1:3,i) + ENDDO + + WRITE (UnSu,'(/,A)') 'Initial angular velocity' + DO i=1,p%node_total + WRITE(UnSu,'(I4,3ES18.5)') i,x%dqdt(4:6,i) + ENDDO + + + select case (p%BldMotionNodeLoc) + case (BD_MESH_FE) + WRITE (UnSu, '(/,A)') 'Output nodes located at finite element nodes.' + case (BD_MESH_QP) + WRITE (UnSu, '(/,A)') 'Output nodes located at quadrature points.' + case (BD_MESH_STATIONS) + WRITE (UnSu, '(/,A)') 'Output nodes located at blade propery input station locations.' + !bjj: need to write where these nodes are located... + end select + + + + ! output channels: + OutPFmt = '( I4, 3X,A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + WRITE (UnSu,'(//,A,/)') 'Requested Outputs:' + WRITE (UnSu,"( ' Col Parameter Units', /, ' --- -------------- ----------')") + DO I = 0,p%NumOuts + WRITE (UnSu,OutPFmt) I, p%OutParam(I)%Name, p%OutParam(I)%Units + END DO + + + WRITE (UnSu,'(15x,A)') + WRITE (UnSu,'(15x,A)') + WRITE (UnSu,'(15x,A)') 'Requested Output Channels at each blade station:' + WRITE (UnSu,'(15x,A)') 'Col Parameter Units' + WRITE (UnSu,'(15x,A)') '---- --------- -----' + DO I = 1,p%BldNd_NumOuts + WRITE (UnSu,OutPFmt) I, p%BldNd_OutParam(I)%Name, p%BldNd_OutParam(I)%Units + END DO + + + if ( p%analysis_type /= BD_STATIC_ANALYSIS ) then !dynamic analysis + ! we'll add mass and stiffness matrices in the first call to UpdateStates + m%Un_Sum = UnSu + else + CLOSE(UnSu) + end if + + +RETURN +END SUBROUTINE BD_PrintSum +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing subroutine ! +SUBROUTINE Init_Jacobian( p, u, y, m, InitOut, ErrStat, ErrMsg) + + TYPE(BD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(BD_InputType) , INTENT(IN ) :: u !< inputs + TYPE(BD_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(BD_MiscVarType) , INTENT(INOUT) :: m !< misc var data + TYPE(BD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian' + + ! local variables: + INTEGER(IntKi) :: i, j, index, nu, i_meshField + REAL(R8Ki) :: perturb, perturb_b + REAL(R8Ki) :: MaxThrust, MaxTorque + CHARACTER(1), PARAMETER :: UVW(3) = (/'U','V','W'/) + + + + ErrStat = ErrID_None + ErrMsg = "" + + call Init_Jacobian_y( p, y, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call Init_Jacobian_x_z( p, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! determine how many inputs there are in the Jacobians + nu = u%RootMotion%NNodes * 18 & ! 3 Translation Displacements + 3 orientations + 6 velocities (rotation+translation) + 6 accelerations at each node + + u%PointLoad%NNodes * 6 & ! 3 forces + 3 moments at each node + + u%DistrLoad%NNodes * 6 ! 3 forces + 3 moments at each node + + ! all other inputs (e.g., hub motion) ignored + + !............................ + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! (see beamdyn::perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index (x-y-z component) of the field + ! column 3 is the node + !............................ + + call allocAry( p%Jac_u_indx, nu, 3, 'p%Jac_u_indx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !............... + ! BD input mappings stored in p%Jac_u_indx: + !............... + index = 1 + !Module/Mesh/Field: u%RootMotion%TranslationDisp = 1; + !Module/Mesh/Field: u%RootMotion%Orientation = 2; + !Module/Mesh/Field: u%RootMotion%TranslationVel = 3; + !Module/Mesh/Field: u%RootMotion%RotationVel = 4; + !Module/Mesh/Field: u%RootMotion%TranslationAcc = 5; + !Module/Mesh/Field: u%RootMotion%RotationAcc = 6; + do i_meshField = 1,6 + do i=1,u%RootMotion%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + !Module/Mesh/Field: u%PointLoad%Force = 7; + !Module/Mesh/Field: u%PointLoad%Moment = 8; + do i_meshField = 7,8 + do i=1,u%PointLoad%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + !Module/Mesh/Field: u%DistrLoad%Force = 9; + !Module/Mesh/Field: u%DistrLoad%Moment = 10; + do i_meshField = 9,10 + do i=1,u%DistrLoad%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + p%Jac_u_indx(index,2) = j !component index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do !i_meshField + + + + !...................................... + ! default perturbations, p%du: + !...................................... + call allocAry( p%du, 10, 'p%du', ErrStat2, ErrMsg2) ! 10 = number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + perturb = 0.2_R8Ki*D2R_D + perturb_b = 0.2_R8Ki*D2R_D * p%blade_length + + MaxThrust = 170.0_R8Ki*p%blade_length**2 + MaxTorque = 14.0_R8Ki*p%blade_length**3 + + p%du( 1) = perturb_b ! u%RootMotion%TranslationDisp = 1; + p%du( 2) = perturb ! u%RootMotion%Orientation = 2; + p%du( 3) = perturb_b ! u%RootMotion%TranslationVel = 3; + p%du( 4) = perturb ! u%RootMotion%RotationVel = 4; + p%du( 5) = perturb_b ! u%RootMotion%TranslationAcc = 5; + p%du( 6) = perturb ! u%RootMotion%RotationAcc = 6; + + p%du( 7) = MaxThrust / (100.0_R8Ki * 3.0_R8Ki * u%PointLoad%NNodes ) ! u%PointLoad%Force = 7; + p%du( 8) = MaxTorque / (100.0_R8Ki * 3.0_R8Ki * u%PointLoad%NNodes ) ! u%PointLoad%Moment = 8; + + p%du( 9) = MaxThrust / (100.0_R8Ki * 3.0_R8Ki * u%DistrLoad%NNodes ) ! u%DistrLoad%Force = 9; + p%du(10) = MaxTorque / (100.0_R8Ki * 3.0_R8Ki * u%DistrLoad%NNodes ) ! u%DistrLoad%Moment =10; + + !..................... + ! get names of linearized inputs + !..................... + call AllocAry(InitOut%LinNames_u, nu, 'LinNames_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%RotFrame_u, nu, 'RotFrame_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%IsLoad_u, nu, 'IsLoad_u', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%RotFrame_u = .false. ! every input is on a mesh, which stores values in the global (not rotating) frame + + index = 1 + call PackMotionMesh_Names(u%RootMotion, 'RootMotion', InitOut%LinNames_u, index) ! all 6 motion fields + InitOut%IsLoad_u(1:index-1) = .false. ! the RootMotion inputs are not loads + InitOut%IsLoad_u(index:) = .true. ! the remaining inputs are loads + call PackLoadMesh_Names( u%PointLoad, 'PointLoad', InitOut%LinNames_u, index) + call PackLoadMesh_Names( u%DistrLoad, 'DistrLoad', InitOut%LinNames_u, index) + + +END SUBROUTINE Init_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized outputs. +SUBROUTINE Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) + + TYPE(BD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(BD_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(BD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + + 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 + INTEGER(IntKi) :: j + INTEGER(IntKi) :: index_next + LOGICAL :: AllOut(MaxOutPts) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian_y' + + CHARACTER(ChanLen) :: ChannelName + LOGICAL :: isRotating + + ErrStat = ErrID_None + ErrMsg = "" + + + ! determine how many outputs there are in the Jacobians + p%Jac_ny = y%ReactionForce%NNodes * 6 & ! 3 forces + 3 moments at each node + + y%BldMotion%NNodes * 18 & ! 6 displacements (translation, rotation) + 6 velocities + 6 accelerations at each node + + p%NumOuts + p%BldNd_TotNumOuts ! WriteOutput values + + + ! get the names of the linearized outputs: + call AllocAry(InitOut%LinNames_y, p%Jac_ny,'LinNames_y',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitOut%RotFrame_y, p%Jac_ny,'RotFrame_y',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + + InitOut%RotFrame_y = .false. ! need to set all the values in the global system to .false + + index_next = 1 + call PackLoadMesh_Names( y%ReactionForce, 'Reaction force', InitOut%LinNames_y, index_next) + call PackMotionMesh_Names(y%BldMotion, 'Blade motion', InitOut%LinNames_y, index_next) + + do i=1,p%NumOuts + p%BldNd_TotNumOuts + InitOut%LinNames_y(i+index_next-1) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) + end do + + AllOut = .true. ! all output values except those specifically in the global system are in the rotating system + AllOut(TipTVXg) = .false. + AllOut(TipTVYg) = .false. + AllOut(TipTVZg) = .false. + AllOut(TipRVXg) = .false. + AllOut(TipRVYg) = .false. + AllOut(TipRVZg) = .false. + + do j=1,9 + do i=1,3 !x,y,z + AllOut(NTVg(j,i)) = .false. + AllOut(NRVg(j,i)) = .false. + end do + end do + + do i=1,p%NumOuts + if (p%OutParam(i)%Indx == 0 ) then + InitOut%RotFrame_y(i+index_next-1) = .false. + else + InitOut%RotFrame_y(i+index_next-1) = AllOut( p%OutParam(i)%Indx ) + end if + end do + + + ! set outputs for all nodes out: + index_next = index_next + p%NumOuts + DO i=1,p%BldNd_NumOuts + ChannelName = p%BldNd_OutParam(i)%Name + call Conv2UC(ChannelName) + if ( ChannelName( LEN_TRIM(ChannelName):LEN_TRIM(ChannelName) ) == 'G') then ! channel is in global coordinate system + isRotating = .false. + else + isRotating = .true. + end if + InitOut%RotFrame_y(index_next : index_next+size(p%BldNd_BlOutNd)-1 ) = isRotating + index_next = index_next + size(p%BldNd_BlOutNd) + ENDDO + + +END SUBROUTINE Init_Jacobian_y +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized continuous states. +SUBROUTINE Init_Jacobian_x_z( p, InitOut, ErrStat, ErrMsg) + + TYPE(BD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(BD_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Jacobian_x' + CHARACTER(200) :: Describe + + ! local variables: + INTEGER(IntKi) :: i + INTEGER(IntKi) :: indx + + ErrStat = ErrID_None + ErrMsg = "" + + p%Jac_nx = p%dof_node * (p%node_total-1) ! the first node is actually a constraint state + + ! allocate space for the row/column names and for perturbation sizes + !call allocAry(p%dx, p%dof_node*(p%node_total-1), 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%LinNames_x, p%Jac_nx*2, 'LinNames_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%RotFrame_x, p%Jac_nx*2, 'RotFrame_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%DerivOrder_x, p%Jac_nx*2, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + !CALL AllocAry(InitOut%LinNames_z, p%dof_node*2, 'LinNames_z', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + !CALL AllocAry(InitOut%RotFrame_z, p%dof_node*2, 'RotFrame_z', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + + !...................................... + ! default perturbations, p%dx: + !...................................... + p%dx(1:3) = 0.2_BDKi*D2R_D * p%blade_length ! deflection states in m and m/s + p%dx(4:6) = 0.2_BDKi*D2R_D ! deflection states in rad and rad/s + + InitOut%RotFrame_x = p%RotStates + InitOut%DerivOrder_x = 2 + + !...................................... + ! set linearization output names: + !...................................... + indx = 1 + DO i=2, p%node_total + Describe = 'finite element node '//trim(num2lstr(i))//' (number of elements = '//trim(num2lstr(p%elem_total))//'; element order = '//trim(num2lstr(p%nodes_per_elem-1))//')' + InitOut%LinNames_x(indx) = trim(Describe)//' translational displacement in X, m' + indx = indx + 1 + InitOut%LinNames_x(indx) = trim(Describe)//' translational displacement in Y, m' + indx = indx + 1 + InitOut%LinNames_x(indx) = trim(Describe)//' translational displacement in Z, m' + indx = indx + 1 + InitOut%LinNames_x(indx) = trim(Describe)//' rotational displacement in X, rad' + indx = indx + 1 + InitOut%LinNames_x(indx) = trim(Describe)//' rotational displacement in Y, rad' + indx = indx + 1 + InitOut%LinNames_x(indx) = trim(Describe)//' rotational displacement in Z, rad' + indx = indx + 1 + END DO + + do i=1,p%Jac_nx + InitOut%LinNames_x(i+p%Jac_nx) = 'First time derivative of '//trim(InitOut%LinNames_x(i))//'/s' + InitOut%RotFrame_x(i+p%Jac_nx) = InitOut%RotFrame_x(i) + end do + + + !InitOut%RotFrame_z = .true. + !InitOut%LinNames_z(1) = 'Node 1 translational displacement in X, m' + !InitOut%LinNames_z(2) = 'Node 1 translational displacement in Y, m' + !InitOut%LinNames_z(3) = 'Node 1 translational displacement in Z, m' + !InitOut%LinNames_z(4) = 'Node 1 rotational displacement in X, -' + !InitOut%LinNames_z(5) = 'Node 1 rotational displacement in Y, -' + !InitOut%LinNames_z(6) = 'Node 1 rotational displacement in Z, -' + ! + !do i=1,6 + ! InitOut%LinNames_x(i+6) = 'First time derivative of '//trim(InitOut%LinNames_z(i))//'/s' + !end do + + +END SUBROUTINE Init_Jacobian_x_z +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE Perturb_u( p, n, perturb_sign, u, du ) + + TYPE(BD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(BD_InputType) , INTENT(INOUT) :: u !< perturbed BD inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + + + ! local variables + INTEGER :: fieldIndx + INTEGER :: node + + fieldIndx = p%Jac_u_indx(n,2) + node = p%Jac_u_indx(n,3) + + du = p%du( p%Jac_u_indx(n,1) ) + + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( p%Jac_u_indx(n,1) ) + + CASE ( 1) !Module/Mesh/Field: u%RootMotion%TranslationDisp = 1; + u%RootMotion%TranslationDisp( fieldIndx,node) = u%RootMotion%TranslationDisp( fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%RootMotion%Orientation = 2; + CALL PerturbOrientationMatrix( u%RootMotion%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%RootMotion%TranslationVel = 3; + u%RootMotion%TranslationVel( fieldIndx,node) = u%RootMotion%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%RootMotion%RotationVel = 4; + u%RootMotion%RotationVel(fieldIndx,node) = u%RootMotion%RotationVel(fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%RootMotion%TranslationAcc = 5; + u%RootMotion%TranslationAcc( fieldIndx,node) = u%RootMotion%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%RootMotion%RotationAcc = 6; + u%RootMotion%RotationAcc(fieldIndx,node) = u%RootMotion%RotationAcc(fieldIndx,node) + du * perturb_sign + + CASE ( 7) !Module/Mesh/Field: u%PointLoad%Force = 7; + u%PointLoad%Force(fieldIndx,node) = u%PointLoad%Force(fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%PointLoad%Moment = 8; + u%PointLoad%Moment(fieldIndx,node) = u%PointLoad%Moment(fieldIndx,node) + du * perturb_sign + + CASE ( 9) !Module/Mesh/Field: u%DistrLoad%Force = 9; + u%DistrLoad%Force( fieldIndx,node) = u%DistrLoad%Force( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%DistrLoad%Moment = 10; + u%DistrLoad%Moment(fieldIndx,node) = u%DistrLoad%Moment(fieldIndx,node) + du * perturb_sign + + END SELECT + +END SUBROUTINE Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) + + TYPE(BD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(BD_OutputType) , INTENT(IN ) :: y_p !< BD outputs at \f$ u + \Delta_p u \f$ or \f$ z + \Delta_p z \f$ (p=plus) + TYPE(BD_OutputType) , INTENT(IN ) :: y_m !< BD outputs at \f$ u - \Delta_m u \f$ or \f$ z - \Delta_m z \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial z_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + INTEGER(IntKi) :: i ! loop over outputs + INTEGER(IntKi) :: indx_first ! index indicating next value of dY to be filled + + indx_first = 1 + call PackLoadMesh_dY( y_p%ReactionForce, y_m%ReactionForce, dY, indx_first) + call PackMotionMesh_dY(y_p%BldMotion, y_m%BldMotion, dY, indx_first) ! all 6 motion fields + + do i=1,p%NumOuts + p%BldNd_TotNumOuts + dY(i+indx_first-1) = y_p%WriteOutput(i) - y_m%WriteOutput(i) + end do + + + dY = dY / (2.0_R8Ki*delta) + +END SUBROUTINE Compute_dY +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the x array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE Perturb_x( p, fieldIndx, node, dof, perturb_sign, x, dx ) + + TYPE(BD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: fieldIndx !< field in the state type: 1=displacements; 2=velocities + INTEGER( IntKi ) , INTENT(IN ) :: node !< node number + INTEGER( IntKi ) , INTENT(IN ) :: dof !< dof for this perturbation + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(BD_ContinuousStateType) , INTENT(INOUT) :: x !< perturbed BD states + REAL( R8Ki ) , INTENT( OUT) :: dx !< amount that specific state was perturbed + + + ! local variables + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + REAL(R8Ki) :: orientation(3,3) + REAL(R8Ki) :: rotation(3,3) + + dx = p%dx(dof) + + if (fieldIndx==1) then + if (dof < 4) then ! translational displacement + x%q( dof, node ) = x%q( dof, node ) + dx * perturb_sign + else ! w-m parameters + call BD_CrvMatrixR( x%q( 4:6, node ), rotation ) ! returns the rotation matrix (transpose of DCM) that was stored in the state as a w-m parameter + orientation = transpose(rotation) + + CALL PerturbOrientationMatrix( orientation, dx * perturb_sign, dof-3 ) + + rotation = transpose(orientation) + call BD_CrvExtractCrv( rotation, x%q( 4:6, node ), ErrStat2, ErrMsg2 ) ! return the w-m parameters of the new orientation + end if + else + x%dqdt( dof, node ) = x%dqdt( dof, node ) + dx * perturb_sign + end if + + +END SUBROUTINE Perturb_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE Compute_dX(p, x_p, x_m, delta, dX) + + TYPE(BD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(BD_ContinuousStateType) , INTENT(IN ) :: x_p !< BD continuous states at \f$ u + \Delta_p u \f$ or \f$ x + \Delta_p x \f$ (p=plus) + TYPE(BD_ContinuousStateType) , INTENT(IN ) :: x_m !< BD continuous states at \f$ u - \Delta_m u \f$ or \f$ x - \Delta_m x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dX(:) !< column of dXdu or dXdx: \f$ \frac{\partial X}{\partial u_i} = \frac{x_p - x_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial X}{\partial x_i} = \frac{x_p - x_m}{2 \, \Delta x}\f$ + + ! local variables: + INTEGER(IntKi) :: i ! loop over nodes + INTEGER(IntKi) :: dof ! loop over dofs + INTEGER(IntKi) :: index ! index indicating next value of dX to be filled + + index = 1 + do i=2,p%node_total + do dof=1,p%dof_node + dX(index) = x_p%q( dof, i ) - x_m%q( dof, i ) + index = index+1 + end do + end do + + do i=2,p%node_total + do dof=1,p%dof_node + dX(index) = x_p%dqdt( dof, i ) - x_m%dqdt( dof, i ) + index = index+1 + end do + end do + + dX = dX / ( 2.0_R8Ki*delta) + +END SUBROUTINE Compute_dX +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE Compute_RelState_Matrix(p, u, x, RelState_x, RelState_xdot) + + TYPE(BD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(BD_InputType) , INTENT(IN ) :: u !< BD inputs + TYPE(BD_ContinuousStateType) , INTENT(IN ) :: x !< BD continuous states + REAL(R8Ki) , INTENT(INOUT) :: RelState_x(:,:) !< + REAL(R8Ki) , INTENT(INOUT) :: RelState_xdot(:,:) !< + + ! local variables: + INTEGER(IntKi) :: i ! loop counter + INTEGER(IntKi) :: j ! loop counter + INTEGER(IntKi) :: dof ! loop over dofs + INTEGER(IntKi) :: q_index ! index into the state arrays + INTEGER(IntKi) :: dqdt_index ! index into the state arrays + INTEGER(IntKi) :: node ! node in the state arrays + + REAL(R8Ki) :: dp ! temporary dot product + REAL(R8Ki) :: cp(3) ! temporary cross product + REAL(R8Ki) :: RotVel(3) ! temporary velocity + REAL(R8Ki) :: RotAcc(3) ! temporary acceleration + REAL(R8Ki) :: DisplacedPosition(3) + REAL(R8Ki) :: fx_p(3,3) + + RelState_x = 0.0_ReKi + RelState_xdot = 0.0_ReKi + + !----------------------------------- + do i=1,p%elem_total + do j=2,p%nodes_per_elem + + node = (i-1)*(p%nodes_per_elem-1) + j ! index to state array (rows of conversion matrices) + q_index = (node - 2)*p%dof_node + 1 ! index into displacement portion of x (skipping node 1) + dqdt_index = p%Jac_nx + q_index + + DisplacedPosition = u%RootMotion%Position(:,1) + u%RootMotion%TranslationDisp(:,1) & + - p%GlbPos - MATMUL(p%GlbRot, p%uuN0(1:3,j,i) + x%q(1:3,node) ) + + RotVel = real(u%RootMotion%RotationVel(:,1),R8Ki) + RotAcc = real(u%RootMotion%RotationAcc(:,1),R8Ki) + + fx_p = SkewSymMat(DisplacedPosition) + + do dof=0,5 + RelState_x( q_index+dof, 1+dof ) = 1.0_R8Ki ! root displacements to node displacements + end do + do dof=0,5 + RelState_x( dqdt_index+dof, 7+dof ) = 1.0_R8Ki ! root velocities to node velocities + end do + + + RelState_x( q_index:q_index+2, 4: 6 ) = fx_p ! root rotational displacement to node translational displacement + RelState_x( dqdt_index:dqdt_index+2, 10:12 ) = fx_p ! root rotational velocity to node translational velocity + + ! root rotational displacement to node translational velocity: + RelState_x( dqdt_index:dqdt_index+2, 4:6 ) = OuterProduct( DisplacedPosition, RotVel ) + dp = dot_product( DisplacedPosition, RotVel ) + do dof=0,2 + RelState_x( dqdt_index+dof, 4+dof ) = RelState_x( dqdt_index+dof, 4+dof ) - dp ! root rotational displacement to node translational velocity + end do + !---------- + + + !............................................. + ! The first p%Jac_nx rows of RelState_xdot are the same as the last p%Jac_nx rows of RelState_x, so I'm not going to recalculate these rows, we'll set them after the loops: + !do dof=0,5 + ! RelState_xdot( q_index+dof, 7+dof ) = 1.0_ReKi ! root velocities to node velocities + !end do + !RelState_xdot( q_index:q_index+2, 4:6 ) = RelState_x( dqdt_index:dqdt_index+2, 4:6 ) ! root rotational displacement to node translational velocity + !RelState_xdot( q_index:q_index+2, 10:12 ) = fx_p ! root rotational velocity to node translational velocity + + do dof=0,5 + RelState_xdot( dqdt_index+dof, 13+dof ) = 1.0_R8Ki ! root accelerations to node accelerations + end do + + + ! root translational velocity to node translational acceleration: + cp = cross_product(u%RootMotion%RotationVel(:,1), DisplacedPosition) + RelState_xdot( dqdt_index:dqdt_index+2, 7:9 ) = OuterProduct( DisplacedPosition, RotAcc ) & + + OuterProduct( cp, RotVel ) - dp*SkewSymMat(RotVel) + dp = dot_product( DisplacedPosition, RotAcc ) + do dof=0,2 + RelState_xdot( dqdt_index+dof, 7+dof ) = RelState_xdot( dqdt_index+dof, 7+dof ) - dp + end do + !----------- + + RelState_xdot( dqdt_index:dqdt_index+2, 10:12 ) = RelState_x( dqdt_index:dqdt_index+2, 4:6 ) + SkewSymMat(cp) ! root rotational velocity to node translational acceleration + RelState_xdot( dqdt_index:dqdt_index+2, 16:18 ) = fx_p ! root rotational acceleration to node translational acceleration + + end do + end do + RelState_xdot(1:p%Jac_nx,:) = RelState_x(p%Jac_nx+1:,:) + +END SUBROUTINE Compute_RelState_Matrix +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE BeamDyn_IO diff --git a/OpenFAST/modules/beamdyn/src/BeamDyn_Subs.f90 b/OpenFAST/modules/beamdyn/src/BeamDyn_Subs.f90 new file mode 100644 index 000000000..4a47bbd5b --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/BeamDyn_Subs.f90 @@ -0,0 +1,1134 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! 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 BeamDyn_Subs + + USE BeamDyn_Types + USE NWTC_LAPACK + + IMPLICIT NONE + + INTEGER, PARAMETER :: BDKi = R8Ki + INTEGER, PARAMETER :: FLAG_R1R2 = 0 !< BD_CrvCompose flag = 0: R(rr) = R (pp) R (qq) + INTEGER, PARAMETER :: FLAG_R1TR2 = 1 !< BD_CrvCompose flag = 1: R(rr) = R(T) (pp) R (qq) + INTEGER, PARAMETER :: FLAG_R1R2T = 2 !< BD_CrvCompose flag = 2: R(rr) = R (pp) R(T) (qq) + INTEGER, PARAMETER :: FLAG_R1TR2T = 3 !< BD_CrvCompose flag = 3: R(rr) = R(T) (pp) R(T) (qq) + + INTEGER, PARAMETER :: GAUSS_QUADRATURE = 1 !< p%quadrature method: gaussian quadrature + INTEGER, PARAMETER :: TRAP_QUADRATURE = 2 !< p%quadrature method: trapeziodal quadrature + +CONTAINS + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine determines the (N+1) Gauss-Lobatto-Legendre points x and weights w +!! +!! For details, see +!! \@book{Deville-etal:2002, +!! author = {M. O. Deville and P. F. Fischer and E. H. Mund}, +!! title = {High-Order Methods for Incompressible Fluid Flow}, +!! publisher = {Cambridge University Press}, +!! address = {Cambridge}, +!! year = 2002 +!!} +SUBROUTINE BD_GenerateGLL(N1, GLL_nodes, ErrStat, ErrMsg) + + ! input variables + + INTEGER(IntKi), INTENT(IN ) :: N1 !< 1 + the order of spectral element, or equivalently p%nodes_per_elem + REAL(BDKi), ALLOCATABLE, INTENT( OUT) :: GLL_nodes(:) !< location of GLL nodes + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(BDKi) , PARAMETER :: tol = 10.0_BDKi*EPSILON(tol) / 2.0_BDKi ! tolerance for newton-raphson solve (ignores 1 significant digit) + INTEGER(IntKi) , PARAMETER :: maxit = 1000 ! maximum allowable iterations in newton-raphson solve + + REAL(BDKi) :: x_it ! current NR-iteration value + REAL(BDKi) :: x_old ! last NR-iteration value + REAL(BDKi) :: dleg(N1) ! legendre polynomial + INTEGER(IntKi) :: N ! Order of spectral element + INTEGER(IntKi) :: i ! do-loop counter + INTEGER(IntKi) :: j ! do-loop counter + INTEGER(IntKi) :: k ! do-loop counter + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'BD_GenerateGLL' + + + ErrStat = ErrID_None + ErrMsg = "" + + N = N1 - 1 + + + CALL AllocAry(GLL_nodes,N1,'GLL points array',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + + !bjj: these are getting overwritten later.... + ! enter known endpoints [-1.0, 1.0] + GLL_nodes(1) = -1.0_BDKi + GLL_nodes(N1) = 1.0_BDKi + + DO i = 1, N1 + + x_it = -COS(pi_D * REAL(i-1,BDKi) / N) ! initial guess - chebyshev points + DO j = 1, maxit + x_old = x_it + dleg(1) = 1.0_BDKi + dleg(2) = x_it + DO k = 2,N + dleg(k+1) = ( REAL(2*k - 1,BDKi) * dleg(k) * x_it & + - REAL( k - 1,BDKi) * dleg(k-1) ) / REAL(k,BDKi) + ENDDO + x_it = x_it - ( x_it * dleg(N1) - dleg(N) ) / & + (REAL(N1,BDKi) * dleg(N1) ) + IF (ABS(x_it - x_old) .lt. tol) EXIT + ENDDO + + GLL_nodes(i) = x_it + !GLL_weights(i) = 2.0_BDKi / (REAL(N * N1, BDKi) * dleg(N1)**2 ) + + ENDDO + +END SUBROUTINE BD_GenerateGLL +!----------------------------------------------------------------------------------------------------------------------------------- + +!> This subroutine computes the rotation tensor (RT=\f$ \phi \f$ ) +!! given Wiener-Milenkovic rotation parameters, \f$ \vec{c} \f$, +!! where \f$ \vec{c}=4\tan\left(\frac{\phi}{4}\right)\bar{n} \f$. +SUBROUTINE BD_CrvMatrixR(cc,Rr) +!FIXME: would this routine benefit from matrix mathematics? The basic formulation is matrix based. + + REAL(BDKi), INTENT(IN ):: cc(3) !< \f$ \vec{c}\f$ + REAL(BDKi), INTENT( OUT):: Rr(3,3) !< returned rotation tensor (transpose of DCM matrix) + + REAL(BDKi) :: c0 !< \f$ c_0 = ( 1 - c_1 c_1 - c_2 c_2 - c_3 c_3 ) / 2 \f$ (different from AIAA paper) + REAL(BDKi) :: c1 + REAL(BDKi) :: c2 + REAL(BDKi) :: c3 + REAL(BDKi) :: tr0 !< \f$ 2 / ( 1 - c_0 )^2 \f$ (which is different from AIAA paper) + + + !> Compare this routine with equation (14) from AIAA paper, "Geometric Nonlinear Analysis of Composite Beams Using + !! Wiener-Milenkovic Parameters", Wang, et. al.\n + !! \f$ + !! \underline{\underline{R}} (\vec{c}) = t_{r0} + !! \begin{bmatrix} + !! c_0^2 + c_1^2 - c_2^2 - c_3^2 & 2(c_1 c_2 + c_0 c_3) & 2(c_1 c_3 - c_0 c_2) \\ + !! 2(c_1 c_2 - c_0 c_3) & c_0^2 - c_1^2 + c_2^2 - c_3^2 & 2(c_2 c_3 + c_0 c_1) \\ + !! 2(c_1 c_3 + c_0 c_2) & 2(c_2 c_3 - c_0 c_1) & c_0^2 - c_1^2 - c_2^2 + c_3^2 \\ + !! \end{bmatrix} + !! \f$ + !! + !! Where \f$ c_0 = 2 - c_1 c_1 / 8 - c_2 c_2 / 8 - c_3 c_3 /8 \f$ and \f$ t_{r0} = 1/(4-c_0)^2 \f$ + !! + !! _Note:_ The above equation is the transpose of what we have here. This subroutine returns the transpose of the DCM, + !! not the DCM. + !! + !! Also, note that the formulation in this routine looks different, but can be shown as algebraically identical. + + c1 = cc(1)/4.0_BDKi + c2 = cc(2)/4.0_BDKi + c3 = cc(3)/4.0_BDKi + ! \f$ c_0 \f$ is equivalent to \f$ 0.5 - (||\vec{c}||)^2 / 32 \f$ + c0 = 0.5_BDKi * (1.0_BDKi-c1*c1-c2*c2-c3*c3) ! 1/4 the value of the the AIAA paper (after plugging in c1, c2, c3 conversions) + + + tr0 = 1.0_BDKi - c0 ! This is 1/4 the value of the AIAA paper, after converting c0. + tr0 = 2.0_BDKi/(tr0*tr0) ! this is 32x the equivalent term from the AIAA paper. This is well behaved and won't go to zero. + + ! The following terms can be shown to match the transpose of the DCM given in the AIAA paper. + Rr(1,1) = tr0*(c1*c1 + c0*c0) - 1.0_BDKi + Rr(2,1) = tr0*(c1*c2 + c0*c3) + Rr(3,1) = tr0*(c1*c3 - c0*c2) + + Rr(1,2) = tr0*(c1*c2 - c0*c3) + Rr(2,2) = tr0*(c2*c2 + c0*c0) - 1.0_BDKi + Rr(3,2) = tr0*(c2*c3 + c0*c1) + + Rr(1,3) = tr0*(c1*c3 + c0*c2) + Rr(2,3) = tr0*(c2*c3 - c0*c1) + Rr(3,3) = tr0*(c3*c3 + c0*c0) - 1.0_BDKi + +END SUBROUTINE BD_CrvMatrixR +!----------------------------------------------------------------------------------------------------------------------------------- + +!> This subroutine calculutates the tangent vector, \f$ \underline{\underline{H}} \f$ defined in equation (35) of Wang, et. al., +!! "BeamDyn: A hig-fidelity wind turbine blade solver in the FAST modular framework", Wind Energy, 2016. +!! +!! Note that the formulation here is slightly different than in the WE paper, but is algebraically equivalent. +SUBROUTINE BD_CrvMatrixH(cc,Hh) +!FIXME: would this routine benefit from matrix mathematics? The basic formulation is matrix based. + + REAL(BDKi),INTENT(IN) ::cc(3) + REAL(BDKi),INTENT(OUT)::Hh(3,3) + + REAL(BDKi):: cf1,cf2,cf3,cq,ocq,aa,cb0,cb1,cb2,cb3 + + ! Note that the factor of 4 here is a rescaling that simplifies the equation implementation slightly. + cf1 = cc(1)/4.0_BDKi + cf2 = cc(2)/4.0_BDKi + cf3 = cc(3)/4.0_BDKi + cq = cf1 * cf1 + cf2 * cf2 + cf3 * cf3 ! equivalent to \f$ (\vec{c} \dotproduct \vec{c}) / 16 \f$ + ocq = 1.0_BDKi + cq + aa = 2.0_BDKi * ocq * ocq + cb0 = 2.0_BDKi * (1.0_BDKi - cq) / aa + cb1 = cc(1)/aa + cb2 = cc(2)/aa + cb3 = cc(3)/aa + + !> The equation given in the WE paper is given as \n + !! \f$ + !! \underline{\underline{H}(\vec{c})} = 2/(4-c_0)^2 \left[ c_0 + \tilde{c} + \frac{1}{4} \underline{\vec{c}\vec{c}^T} \right] + !! \f$ + !! where \f$ c_0 = 2 - \frac{1}{8} \underline{\vec{c}}^T \underline{\vec{c}} \f$ + !! + !! This gives the matrix + !! + !! \f$ + !! \underline{\underline{R} (\vec{c}) } = \frac{2}{(4-c_0)^2} + !! \begin{bmatrix} + !! c_1 c_1 + c_0 & c_1 c_2 - c_3 & c_1 c_3 + c_2 \\ + !! c_2 c_1 + c_3 & c_2 c_2 + c_0 & c_2 c_3 - c_1 \\ + !! c_3 c_1 - c_2 & c_3 c_2 + c_1 & c_3 c_3 + c_0 \\ + !! \end{bmatrix} + !! = 2/(4-c_0)^2 \left[ c_0 + \tilde{c} + \vec{c} \vec{c}^T / 4 \right] + !! \f$\n + !! where \f$ c_0 = 2 - \frac{1}{8} \vec{c}^T \vec{c} \f$ + + + Hh(1,1) = cb1 * cf1 + cb0 + Hh(2,1) = cb2 * cf1 + cb3 + Hh(3,1) = cb3 * cf1 - cb2 + + Hh(1,2) = cb1 * cf2 - cb3 + Hh(2,2) = cb2 * cf2 + cb0 + Hh(3,2) = cb3 * cf2 + cb1 + + Hh(1,3) = cb1 * cf3 + cb2 + Hh(2,3) = cb2 * cf3 - cb1 + Hh(3,3) = cb3 * cf3 + cb0 + + +END SUBROUTINE BD_CrvMatrixH +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine composes two Wiener-Milenkovic parameters pp and qq to find the resulting parameter rr +!! This method is detailed in the paper: Bauchau, O.A., 2008, "Interpolation of finite rotations in flexible +!! multi-body dynamics simulations", IMechE, Equation (9). +!! see http://www.dymoresolutions.com/publications/BauchauEppleHeo08.pdf \n +!! FLAG_R1R2: flag = 0: R(rr) = R (pp) R (qq) \n +!! FLAG_R1TR2: flag = 1: R(rr) = R(T) (pp) R (qq) \n +!! FLAG_R1R2T: flag = 2: R(rr) = R (pp) R(T) (qq) \n +!! FLAG_R1TR2T: flag = 3: R(rr) = R(T) (pp) R(T) (qq) +!! +SUBROUTINE BD_CrvCompose( rr, pp, qq, flag) +!FIXME: would this routine benefit from matrix mathematics? The basic formulation is matrix based. + + REAL(BDKi), INTENT( OUT):: rr(3) !< Composed rotation + REAL(BDKi), INTENT(IN ):: pp(3) !< Input rotation 1 + REAL(BDKi), INTENT(IN ):: qq(3) !< Input rotation 2 + INTEGER ,INTENT(IN ):: flag !< Option flag + + REAL(BDKi) :: pp0 + REAL(BDKi) :: p(3) + REAL(BDKi) :: qq0 + REAL(BDKi) :: q(3) + REAL(BDKi) :: tr1 + REAL(BDKi) :: Delta1 + REAL(BDKi) :: Delta2 + REAL(BDKi) :: dd1 + REAL(BDKi) :: dd2 + + + ! Set the local values pp and qq allowing for the transpose + + IF(flag==FLAG_R1TR2 .OR. flag==FLAG_R1TR2T) THEN ! "transpose" (negative) of first rotation parameter + p = -pp + ELSE + p = pp + ENDIF + + IF(flag==FLAG_R1R2T .OR. flag==FLAG_R1TR2T) THEN ! "transpose" (negative) of second rotation parameter + q = -qq + ELSE + q = qq + ENDIF + + !> ## Composing the resulting Wiener-Milenkovic parameter + !! + !! From the paper by Bauchau, the resulting parameter \f$ \underline{r} \f$ (denoted as rr in the code) + !! can be composed from \f$ \underline{p} \f$ and \f$ \underline{q} \f$ (pp and qq, respectively, in the code) as: + !! + !! \f$ \underline{r} = 4 \frac{ q_0 \underline{p} + p_0 \underline{q} + \tilde{p} \underline{q} } + !! { \Delta_1 + \Delta_2 } \f$ + !! + !! where + !! + !! \f$ p_0 = 2 - \frac{1}{8} \underline{p}^T \underline{p} + !! = 2 - \frac{1}{8} \left( p_1 p_1 + p_2 p_2 + p_3 p_3 \right) \f$ \n + !! \f$ q_0 = 2 - \frac{1}{8} \underline{q}^T \underline{q} + !! = 2 - \frac{1}{8} \left( q_1 q_1 + q_2 q_2 + q_3 q_3 \right) \f$ \n + !! \f$ \Delta_1 = \left( 4 - p_0 \right) \left( 4 - q_0 \right) \f$ \n + !! \f$ \Delta_2 = p_0 q_0 - \underline{p}^T \underline{q} + !! = p_0 q_0 - \left( p_1 q_1 + p_2 q_2 + p_3 q_3 \right) \f$ \n + !! + !! + + + ! Calculate pp0 and qq0. See Bauchau for the mathematics here (equations 8 to 9 and interviening text) + + pp0 = 2.0_BDKi - dot_product(p,p) / 8.0_BDKi ! p_0 + qq0 = 2.0_BDKi - dot_product(q,q) / 8.0_BDKi ! q_0 + + Delta1 = (4.0_BDKi - pp0) * (4.0_BDKi - qq0) ! Delta_1 in Bauchau + Delta2 = pp0 * qq0 - dot_product(p,q) ! Delta_2 in Bauchau + dd1 = Delta1 + Delta2 ! Denomimator term for \Delta_2 >= 0 + dd2 = Delta1 - Delta2 ! Denomimator term for \Delta_2 < 0 + + ! Rescaling to remove singularities at +/- 2 \pi + ! Note: changed this to test on \Delta_2 (instead of dd1 > dd2) for better consistency with documentation. + IF ( Delta2 >= 0.0_BDKi ) THEN + tr1 = 4.0_BDKi / dd1 + ELSE + tr1 = -4.0_BDKi / dd2 + ENDIF + + rr = tr1 * (qq0*p + pp0*q + cross_product(p,q)) + + +END SUBROUTINE BD_CrvCompose + + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes the CRV parameters given the rotation matrix +!> The algorithm for this subroutine can be found in Markley, 'Unit Quaternion from Rotation Matrix' +!> https://doi.org/10.2514/1.31730 +SUBROUTINE BD_CrvExtractCrv(R, cc, ErrStat, ErrMsg) + + REAL(BDKi), INTENT(IN ) :: R(3,3) !< Rotation Matrix + REAL(BDKi), INTENT( OUT) :: cc(3) !< Crv paramters + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(BDKi) :: pivot(4) ! Trace of the rotation matrix and diagonal elements + REAL(BDKi) :: sm(0:3) + REAL(BDKi) :: em + REAL(BDKi) :: Rr(3,3) + INTEGER :: i ! case indicator + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(*), parameter :: RoutineName = 'BD_CrvExtractCrv' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! use the local rotation matrix variable to avoid side effects + Rr = R + + !> Starting with equation (14) from AIAA paper, "Geometric Nonlinear Analysis of Composite Beams Using + !! Wiener-Milenkovic Parameters", Wang, et. al. \n + !! \f$ + !! \underline{\underline{R}} (\vec{c}) = t_{r0} + !! \begin{bmatrix} + !! c_0^2 + c_1^2 - c_2^2 - c_3^2 & 2(c_1 c_2 + c_0 c_3) & 2(c_1 c_3 - c_0 c_2) \\ + !! 2(c_1 c_2 - c_0 c_3) & c_0^2 - c_1^2 + c_2^2 - c_3^2 & 2(c_2 c_3 + c_0 c_1) \\ + !! 2(c_1 c_3 + c_0 c_2) & 2(c_2 c_3 - c_0 c_1) & c_0^2 - c_1^2 - c_2^2 + c_3^2 \\ + !! \end{bmatrix} + !! \f$ + !! + !! where \f$ c_0 = 2 - c_1 c_1 / 8 - c_2 c_2 / 8 - c_3 c_3 /8 \f$ and \f$ t_{r0} = 1/(4-c_0)^2 \f$ + !! + !! _Note:_ The above equation does not match what is in the March 2016 BD manual (it is the transpose). + !! It does, however, match equation 5.17 in the March 2016 "BeamDyn User's Guide and Theory Manual" + + ! mjs--determine whether R is a valid rotation matrix and correct it if not + call BD_CheckRotMat(Rr, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! mjs--find max value of T := Tr(Rr) and diagonal elements of Rr + ! This tells us which denominator is largest (and less likely to produce numerical noise) + pivot = (/ Rr(1,1) + Rr(2,2) + Rr(3,3), Rr(1,1), Rr(2,2), Rr(3,3) /) + i = maxloc(pivot, 1) - 1 ! our sm array starts at 0, so we need to subtract 1 here to get the correct index + + !> - Condition 1: \f$ \underline{\underline{R(3,3)}} > T \f$ + !! This implies that \f$ c_3^2 > c_0^2 \f$ + select case (i) + case (3) + !! We need the condition that c_3 is not zero for this set of equations. + sm(0) = Rr(2,1) - Rr(1,2) ! 4 c_0 c_3 t_{r0} + sm(1) = Rr(1,3) + Rr(3,1) ! 4 c_1 c_3 t_{r0} + sm(2) = Rr(2,3) + Rr(3,2) ! 4 c_2 c_3 t_{r0} + sm(3) = 1.0_BDKi - Rr(1,1) - Rr(2,2) + Rr(3,3) ! 4 c_3 c_3 t_{r0} + + !> - Condition 2: \f$ \underline{\underline{R(2,2)}} > T \f$ + !! This implies that \f$ c_2^2 > c_0^2 \f$ + case (2) + !! We need the condition that c_2 is not zero for this set of equations. + sm(0) = Rr(1,3) - Rr(3,1) ! 4 c_0 c_2 t_{r0} + sm(1) = Rr(1,2) + Rr(2,1) ! 4 c_1 c_2 t_{r0} + sm(2) = 1.0_BDKi - Rr(1,1) + Rr(2,2) - Rr(3,3) ! 4 c_2 c_2 t_{r0} + sm(3) = Rr(2,3) + Rr(3,2) ! 4 c_3 c_2 t_{r0} + + !> - Condition 3: \f$ \underline{\underline{R(1,1)}} > T \f$ + !! This implies that \f$ c_1^2 > c_0^2 \f$ + case (1) + !! We need the condition that c_1 is not zero for this set of equations. + sm(0) = Rr(3,2) - Rr(2,3) ! 4 c_0 c_1 t_{r0} + sm(1) = 1.0_BDKi + Rr(1,1) - Rr(2,2) - Rr(3,3) ! 4 c_1 c_1 t_{r0} + sm(2) = Rr(1,2) + Rr(2,1) ! 4 c_2 c_1 t_{r0} + sm(3) = Rr(1,3) + Rr(3,1) ! 4 c_3 c_1 t_{r0} + + !> - Condition 4: all diagonal terms are less than the trace + case (0) + !! We need the condition that c_0 is not zero for this set of equations. + sm(0) = 1.0_BDKi + Rr(1,1) + Rr(2,2) + Rr(3,3) ! 4 c_0 c_0 t_{r0} + sm(1) = Rr(3,2) - Rr(2,3) ! 4 c_1 c_0 t_{r0} + sm(2) = Rr(1,3) - Rr(3,1) ! 4 c_2 c_0 t_{r0} + sm(3) = Rr(2,1) - Rr(1,2) ! 4 c_3 c_0 t_{r0} + end select + + em = sm(0) + SIGN( 2.0_BDKi*SQRT(sm(i)), sm(0) ) + em = 4.0_BDKi/em ! 1 / ( 4 t_{r0} c_{i} ), assuming 0 <= c_0 < 4 and c_{i} > 0 + cc = em*sm(1:3) + +END SUBROUTINE BD_CrvExtractCrv + + +SUBROUTINE BD_CheckRotMat(R, ErrStat, ErrMsg) + !> This subroutine checks for rotation matrix validity. + !> Returns: + !> ErrStat = 0 if valid + !> ErrStat = 4 (fatal error) if invalid + + REAL(BDKi), INTENT(IN ) :: R(3,3) !< Rotation Matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(BDKi) :: Rr(3,3) !< Local Rotation Matrix variable + INTEGER(IntKi) :: lwork = 27 !mjs--from LAPACK: dgesvd doc page, lwork >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) + REAL(BDKi), ALLOCATABLE :: work(:) ! where M x N is dimension of R, and lwork is the dimension of work + REAL(BDKi) :: S(3), U(3,3), VT(3,3) !mjs--these three are the SVD matrices (S is actually a vector) + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + LOGICAL :: ortho !mjs--logical value indicating whether R is orthogonal + INTEGER :: i + character(*), parameter :: RoutineName = 'BD_CheckRotMat' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! use the local rotation matrix variable to avoid side effects + Rr = R + + ! mjs--Start by determining if R is a valid rotation matrix using the properties: + ! 1) the eigenvalues of an orthogonal matrix have complex modulus == 1, where + ! the leading eigenvalue is +1 and the other two are a complex conjugate pair + ! 2) a valid rotation matrix must have determinant == +1 i.e., the singular values == 1 + + allocate(work(lwork)) + call LAPACK_gesvd('A', 'A', 3, 3, Rr, S, U, VT, work, lwork, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + deallocate(work) + + ! mjs--If \f$ \underline{\underline{R}} \f$ is not a valid roatation tensor, + ! and the correction is desired, + ! compute \f$ \underline{\underline{R_{out}} \f$, the nearest orthogonal tensor + ! to \f$ \underline{\underline{R}} \f$. + ! This is done via computing SVD for \f$ \underline{\underline{R}} = USV^T \f$ + ! and setting \f$ \underline{\underline{R_{out}} = UV^T \f$ + ! otherwise, assign \f$ \underline{\underline{R_{out}}} = \underline{\underline{R}} \f$ + + do i = 1, 3 + ortho = equalrealnos(S(i), 1.0_BDKi) + if (.not. ortho) then + CALL SetErrStat(ErrID_Fatal, "Passed invalid rotation matrix", ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + end do + + ! mjs--after consulting with Mike Sprague, it was decided that instead of fixing the rotation matrix and + ! notifying the user, the simulation should be stopped if an invalid rotation matrix is passed + ! To change this and implement the fix, use the following lines + ! ErrStat2 = ErrID_Info + ! ErrMsg2 = 'Passed invalid rotation matrix--fixing via SVD' + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! if (ErrStat >= AbortErrLev) return + ! R = matmul(U, VT) + +END SUBROUTINE BD_CheckRotMat + + +!------------------------------------------------------------------------------ +!> This subroutine generates n-point gauss-legendre quadrature points and weights +!! +!! Subroutine is based on well-known formulas for generating Legendre polynomials, the +!! roots of which are the Gauss-Legendre quadrature points. Also used are well-known +!! expressions for the quadrature weights associated with the GL quadrature points. +!! The basic idea of the logic is to use the roots of the Chebyshev polynomial as +!! an initial guess for the roots of the Legendre polynomial, and to then use Newton +!! iteration to find the "exact" roots. +SUBROUTINE BD_GaussPointWeight(n, x, w, ErrStat, ErrMsg) + + INTEGER(IntKi),INTENT(IN ):: n !< Number of Gauss point (p%nqp) + REAL(BDKi), INTENT( OUT):: x(n) !< Gauss point location (p%QPtN) + REAL(BDKi), INTENT( OUT):: w(n) !< Gauss point weight (p%QPtWeight) + INTEGER(IntKi),INTENT( OUT):: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT):: ErrMsg !< Error message if ErrStat /= + + ! local variables + + REAL(BDKi), PARAMETER:: eps = 1000.0_BDKi*EPSILON(eps) / 2.0_BDKi ! tolerance for newton-raphson solve (ignores 3 significant digits) + + + INTEGER(IntKi) :: n_half + + REAL(BDKi) :: n_real ! real version of loop index + INTEGER(IntKi) :: i ! loop index + INTEGER(IntKi) :: j ! loop index + REAL(BDKi) :: j_real ! real version of loop index + + INTEGER(IntKi) :: newton ! newton-iteration index + INTEGER(IntKi), parameter :: newton_max = 10 ! maximum number of newton iterations; should not need many! + + REAL(BDKi) :: p1 ! legendre polynomial j-2 + REAL(BDKi) :: p2 ! legendre polynomial j-1 + REAL(BDKi) :: p3 ! legendre polynomial j + + REAL(BDKi) :: dp3 ! derivative of legendre polynomial j + + if (n .lt. 2) then + ErrStat = ErrID_Fatal + ErrMsg = 'BD_GaussPointWeight: invalid value of n.' + else + ErrStat = ErrID_None + ErrMsg = '' + endif + + n_real = REAL(n,BDKi) + + n_half = (n+1) / 2 ! integer for "half" the points: e.g., n=5 => n_half=3, n=4 => n_half = 2 + + ! loop through each of the "half" n points + do i = 1, n_half + + ! Intial guess for ith root; based on ith root of Chebyshev polynomial + x(i) = - cos( REAL( 2*i - 1, BDKi) * pi_D / (2.0_BDKi * n_real) ) + + ! initialize newton iteration counter + newton = 0 + + p3 = 1. ! some intial big number; logic will always take at least one newton iteration + do while (abs(p3) .gt. eps .and. newton .le. newton_max) + + newton = newton + 1 ! keep track of number of newton iterations + + ! build the legendre polynomial and its derivative evaluated at current root guess + p1 = 1.0_BDKi ! zeroth order legendre polynomial + p2 = x(i) ! first-order legendre polynomial + + do j = 2, n + + j_real = REAL(j, BDKi) + + ! recurrence relation for legendre polynomial + p3 = ( REAL(2*j - 1, BDKi) * x(i) * p2 - REAL(j - 1, BDKi) * p1 ) / j_real + + ! derivative of legendre polynomial; needed for newton iteration + dp3 = j_real * ( - x(i) * p3 + p2 ) / ( 1.0_BDKi - x(i)*x(i) ) + + ! save values for next iteration + p1 = p2 + p2 = p3 + + enddo + + ! newton iteration: xnew = xold - P_n(xold) / P_n'(xold) + x(i) = x(i) - p3 / dp3 + + enddo + + if (abs(x(i)) .lt. eps) x(i) = 0.0_BDKi + + ! fill in the other "side" of the array + x(n-i+1) = - x(i) + + ! calculate weight for this Gauss point location + w(i) = 2.0_BDKi / ( ( 1.0_BDKi - x(i)*x(i) ) * dp3 * dp3 ) + w(n-i+1) = w(i) + + enddo + +END SUBROUTINE BD_GaussPointWeight +!----------------------------------------------------------------------------------------------------------------------------------- +! This subroutine computes trapezoidal quadrature points and weights, p%QPtN and p%QPtWeight +SUBROUTINE BD_TrapezoidalPointWeight(p, station_eta, station_total) + + TYPE(BD_ParameterType),INTENT(INOUT):: p !< BeamDyn parameters + Integer(IntKi),INTENT(IN ) :: station_total + REAL(BDKi),INTENT(IN ) :: station_eta(:) + + ! local variables + REAL(BDKi) :: denom ! denominator for quadrature weight computations + + INTEGER(IntKi) :: indx, temp_id0, temp_id1 ! temporary index into QPtN array + INTEGER(IntKi), parameter :: id0 = 1 + INTEGER(IntKi) :: id1, j + +!bjj: this assumes there is only one member + + + ! compute the trapezoidal quadrature points, p%QPtN, and scale to range [-1,1]: + ! If there is refinement, this will add new points between the specified ones. If p%refine == 1, can skip this. + p%QPtN(1) = station_eta(1) + DO j = 2,p%nqp + indx = 1+(j-2_IntKi)/p%refine ! note use of integer math here --> (J-2)/p%refine may not be integer. + p%QPtN(j) = station_eta(indx) + & + ((station_eta(indx+1) - station_eta(indx))/p%refine) * (MOD(j-2,p%refine) + 1) + ENDDO + p%QPtN = 2.0_BDKi*p%QPtN - 1.0_BDKi ! rescale range from [0, 1] to [-1,1] + + ! compute the trapezoidal quadrature weights, p%QPtWeight: + id1 = station_total + temp_id0 = (id0 - 1)*p%refine + 1 ! Starting index in QPtN --> always going to be 1 + temp_id1 = (id1 - 1)*p%refine + 1 ! ending index in QPtN --> will be size(p%QPtN) + denom = p%QPtN(temp_id1) - p%QPtN(temp_id0) ! This is the range of QPtN --> for single member, is always == 2 + + p%QPtWeight(1) = (p%QPtN(temp_id0+1) - p%QPtN(temp_id0 ))/denom + DO j=2,p%nqp-1 + p%QPtWeight(j) = (p%QPtN(temp_id0+j) - p%QPtN(temp_id0+j-2))/denom + ENDDO + p%QPtWeight(p%nqp) = (p%QPtN(temp_id1 ) - p%QPtN(temp_id1-1 ))/denom + +END SUBROUTINE BD_TrapezoidalPointWeight + +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates y%BldMotion%TranslationDisp, y%BldMotion%Orientation, y%BldMotion%TranslationVel, and +!! y%BldMotion%RotationVel, which depend only on states (and indirectly, u%RootMotion), and parameters. +SUBROUTINE Set_BldMotion_NoAcc(p, x, m, y) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(IN ) :: m !< misc/optimization variables + TYPE(BD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: temp_id + INTEGER(IntKi) :: temp_id2 + REAL(BDKi) :: cc(3) + REAL(BDKi) :: cc0(3) + REAL(BDKi) :: temp_R(3,3) + CHARACTER(*), PARAMETER :: RoutineName = 'Set_BldMotion_NoAcc' + + ! The first node on the mesh is just the root location, but since the orientation of the root node may not + ! RootMotion orientation (due to blade twist), we will calculated it as though it was a regular node + + ! now fill in the other nodes + SELECT CASE (p%BldMotionNodeLoc) + + CASE (BD_MESH_FE) + + DO i=1,p%elem_total + DO j=1,p%nodes_per_elem + temp_id = (i-1)*(p%nodes_per_elem-1)+j ! The last node of the first element is used as the first node in the second element. + temp_id2= (i-1)*p%nodes_per_elem+j ! Index to a node within element i + + + ! Calculate the translational displacement of each GLL node in the FAST coordinate system, + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationDisp(1:3,temp_id2) = MATMUL(p%GlbRot,x%q(1:3,temp_id)) + +!bjj: note differences here compared to BDrot_to_FASTdcm +!adp: in BDrot_to_FASTdcm we are assuming that x%q(4:6,:) is zero because there is no rotatinoal displacement yet + ! Find the rotation parameter in global coordinates (initial orientation + rotation parameters) + ! referenced against the DCM of the blade root at T=0. + CALL BD_CrvCompose( cc, x%q(4:6,temp_id), p%uuN0(4:6,j,i), FLAG_R1R2 ) + CALL BD_CrvCompose( cc0, p%Glb_crv, cc, FLAG_R1R2 ) + + ! Create the DCM from the rotation parameters + CALL BD_CrvMatrixR(cc0,temp_R) ! returns temp_R (the transpose of the DCM orientation matrix) + + ! Store the DCM for the j'th node of the i'th element (in FAST coordinate system) + y%BldMotion%Orientation(1:3,1:3,temp_id2) = TRANSPOSE(temp_R) + + ! Calculate the translation velocity and store in FAST coordinate system + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationVel(1:3,temp_id2) = MATMUL(p%GlbRot,x%dqdt(1:3,temp_id)) + + ! Calculate the rotational velocity and store in FAST coordinate system + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%RotationVel(1:3,temp_id2) = MATMUL(p%GlbRot,x%dqdt(4:6,temp_id)) + + ENDDO + ENDDO + + CASE (BD_MESH_QP) + + DO i=1,p%elem_total + DO j=1,p%nqp + temp_id2 = (i-1)*p%nqp + j + p%qp_indx_offset ! Index to a node within element i + + ! Calculate the translational displacement of each quadrature node in the FAST coordinate system, + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationDisp(1:3,temp_id2) = MATMUL(p%GlbRot,m%qp%uuu(1:3,j,i) ) + + +!bjj: note differences here compared to BDrot_to_FASTdcm +!adp: in BDrot_to_FASTdcm we are assuming that x%q(4:6,:) is zero because there is no rotatinoal displacement yet + ! Find the rotation parameter in global coordinates (initial orientation + rotation parameters) + ! referenced against the DCM of the blade root at T=0. + CALL BD_CrvCompose( cc, m%qp%uuu(4:6,j,i), p%uu0(4:6,j,i), FLAG_R1R2 ) + CALL BD_CrvCompose( cc0, p%Glb_crv, cc, FLAG_R1R2 ) + + CALL BD_CrvMatrixR(cc0,temp_R) ! returns temp_R (the transpose of the DCM orientation matrix) + ! Store the DCM for the j'th node of the i'th element (in FAST coordinate system) + y%BldMotion%Orientation(1:3,1:3,temp_id2) = TRANSPOSE(temp_R) + + ! Calculate the translation velocity and store in FAST coordinate system + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationVel(1:3,temp_id2) = MATMUL(p%GlbRot,m%qp%vvv(1:3,j,i)) + + ! Calculate the rotational velocity and store in FAST coordinate system + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%RotationVel(1:3,temp_id2) = MATMUL(p%GlbRot,m%qp%vvv(4:6,j,i)) + + ENDDO + ENDDO + + + + CASE (BD_MESH_STATIONS) + END SELECT + + +END SUBROUTINE Set_BldMotion_NoAcc +!----------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates values for the y%BldMotion mesh. +SUBROUTINE Set_BldMotion_Mesh(p, u, x, m, y) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t - in the FAST coordinate system (NOT BD) + TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables ! intent(out) so that we can update the accelerations here... + TYPE(BD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: j_start !starting node on this element + INTEGER(IntKi) :: idx_node + INTEGER(IntKi) :: temp_id + INTEGER(IntKi) :: temp_id2 + CHARACTER(*), PARAMETER :: RoutineName = 'Set_BldMotion_Mesh' + + + ! set positions and velocities (not accelerations) + call Set_BldMotion_NoAcc(p, x, m, y) + + ! Only need this bit for dynamic cases + IF ( p%analysis_type /= BD_STATIC_ANALYSIS ) THEN + + ! now set the accelerations: + + ! The first node on the mesh is just the root location: + y%BldMotion%TranslationAcc(:,1) = u%RootMotion%TranslationAcc(:,1) + y%BldMotion%RotationAcc(:,1) = u%RootMotion%RotationAcc(:,1) + + SELECT CASE (p%BldMotionNodeLoc) + + CASE (BD_MESH_FE) ! This is how the NREL-version of BeamDyn works (output nodes at the finite element nodes) + + j_start = 2 ! we'll skip the first node on the first element; otherwise we will start at the first node on the other elements + DO i=1,p%elem_total + DO j=j_start,p%nodes_per_elem + temp_id = (i-1)*(p%nodes_per_elem-1)+j + temp_id2= (i-1)*p%nodes_per_elem+j + + y%BldMotion%TranslationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, m%RHS(1:3,temp_id) ) + + y%BldMotion%RotationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, m%RHS(4:6,temp_id) ) + ENDDO + j_start = 1 + ENDDO + + CASE (BD_MESH_QP) + + + m%qp%aaa(1:3,1,1) = u%RootMotion%TranslationAcc(:,1) + m%qp%aaa(4:6,1,1) = u%RootMotion%RotationAcc(:,1) + + ! Calculate the and acceleration term at t+dt (OtherState%acc is at t+dt) + j_start = 2 ! we'll skip the first node on the first element; otherwise we will start at the first node on the other elements + DO i=1,p%elem_total + DO j=j_start,p%nqp + + ! Initialize to zero for summation, then recalculate accelerations at quadrature nodes based on accelerations at FE nodes + m%qp%aaa(:,j,i) = 0.0_BDKi + DO idx_node=j_start,p%nodes_per_elem + m%qp%aaa(:,j,i) = m%qp%aaa(:,j,i) + p%Shp(idx_node,j) * m%RHS(:,p%node_elem_idx(i,1)-1+idx_node) + ENDDO + + temp_id2 = (i-1)*p%nqp + j + p%qp_indx_offset ! Index to a node within element i + + ! Calculate the translational acceleration of each quadrature node in the FAST coordinate system, + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationAcc(1:3,temp_id2) = MATMUL(p%GlbRot,m%qp%aaa(1:3,j,i) ) + + y%BldMotion%RotationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, m%qp%aaa(4:6,j,i) ) + ENDDO + j_start = 1 + ENDDO + + CASE (BD_MESH_STATIONS) + END SELECT + + END IF + +END SUBROUTINE Set_BldMotion_Mesh +!> This routine calculates values for the y%BldMotion mesh. +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Set_BldMotion_InitAcc(p, u, OtherState, m, y) + + TYPE(BD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BD_InputType), INTENT(IN ) :: u !< Inputs at t - in the FAST coordinate system (NOT BD) + TYPE(BD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables ! intent(out) so that we can update the accelerations here... + TYPE(BD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + INTEGER(IntKi) :: i + INTEGER(IntKi) :: j + INTEGER(IntKi) :: j_start !starting node on this element + INTEGER(IntKi) :: temp_id + INTEGER(IntKi) :: temp_id2 + CHARACTER(*), PARAMETER :: RoutineName = 'Set_BldMotion_InitAcc' + + + ! The first node on the mesh is just the root location: + y%BldMotion%TranslationAcc(:,1) = u%RootMotion%TranslationAcc(:,1) + y%BldMotion%RotationAcc(:,1) = u%RootMotion%RotationAcc(:,1) + + SELECT CASE (p%BldMotionNodeLoc) + + CASE (BD_MESH_FE) ! This is how the NREL-version of BeamDyn works (output nodes at the finite element nodes) + + j_start = 2 ! we'll skip the first node on the first element; otherwise we will start at the first node on the other elements + DO i=1,p%elem_total + DO j=j_start,p%nodes_per_elem + temp_id = (i-1)*(p%nodes_per_elem-1)+j + temp_id2= (i-1)*p%nodes_per_elem+j + + y%BldMotion%TranslationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, OtherState%Acc(1:3,temp_id) ) + + y%BldMotion%RotationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, OtherState%Acc(4:6,temp_id) ) + ENDDO + j_start = 1 + ENDDO + + CASE (BD_MESH_QP) + + ! Calculate the and acceleration term at t+dt (OtherState%acc is at t+dt) + j_start = 2 ! we'll skip the first node on the first element; otherwise we will start at the first node on the other elements + DO i=1,p%elem_total + DO j=j_start,p%nqp + + temp_id2 = (i-1)*p%nqp + j + p%qp_indx_offset ! Index to a node within element i + + ! Calculate the translational acceleration of each quadrature node in the FAST coordinate system, + ! referenced against the DCM of the blade root at T=0. + y%BldMotion%TranslationAcc(1:3,temp_id2) = MATMUL(p%GlbRot,m%qp%aaa(1:3,j,i) ) + + y%BldMotion%RotationAcc(1:3,temp_id2) = MATMUL(p%GlbRot, m%qp%aaa(4:6,j,i) ) + ENDDO + j_start = 1 + ENDDO + + CASE (BD_MESH_STATIONS) + END SELECT + + +END SUBROUTINE Set_BldMotion_InitAcc +!----------------------------------------------------------------------------------------------------------------------------------- +!> calculate Lagrangian interpolant tensor at ns points where basis +!! functions are assumed to be associated with (np+1) GLL points on [-1,1] +SUBROUTINE BD_diffmtc( nodes_per_elem,GLL_nodes,QPtN,nqp,Shp,ShpDer ) + + ! See Bauchau equations 17.1 - 17.5 + + INTEGER(IntKi), INTENT(IN ) :: nodes_per_elem !< Nodes per elemenent + REAL(BDKi), INTENT(IN ) :: GLL_nodes(:) !< GLL_nodes(p%nodes_per_elem): location of the (p%nodes_per_elem) p%GLL points + REAL(BDKi), INTENT(IN ) :: QPtN(:) !< Locations of quadrature points ([-1 1]) + INTEGER(IntKi), INTENT(IN ) :: nqp !< number of quadrature points to consider. Should be size of 2nd index of Shp & ShpDer + REAL(BDKi), INTENT(INOUT) :: Shp(:,:) !< p%Shp (or another Shp array for when we add outputs at arbitrary locations) + REAL(BDKi), INTENT(INOUT) :: ShpDer(:,:) !< p%ShpDer (or another Shp array for when we add outputs at arbitrary locations) + + REAL(BDKi) :: dnum + REAL(BDKi) :: den + REAL(BDKi), PARAMETER:: eps = SQRT(EPSILON(eps)) !1.0D-08 + INTEGER(IntKi) :: l + INTEGER(IntKi) :: j + INTEGER(IntKi) :: i + INTEGER(IntKi) :: k + + ! See Bauchau equations 17.1 - 17.5 + + Shp(:,:) = 0.0_BDKi + ShpDer(:,:) = 0.0_BDKi + + + do j = 1,nqp + do l = 1,nodes_per_elem + + if ((abs(QPtN(j)-1.).LE.eps).AND.(l.EQ.nodes_per_elem)) then !adp: FIXME: do we want to compare to eps, or EqualRealNos??? + ShpDer(l,j) = REAL((nodes_per_elem)*(nodes_per_elem-1), BDKi)/4.0_BDKi + elseif ((abs(QPtN(j)+1.).LE.eps).AND.(l.EQ.1)) then + ShpDer(l,j) = -REAL((nodes_per_elem)*(nodes_per_elem-1), BDKi)/4.0_BDKi + elseif (abs(QPtN(j)-GLL_nodes(l)).LE.eps) then + ShpDer(l,j) = 0.0_BDKi + else + ShpDer(l,j) = 0.0_BDKi + den = 1.0_BDKi + do i = 1,nodes_per_elem + if (i.NE.l) then + den = den*(GLL_nodes(l)-GLL_nodes(i)) + endif + dnum = 1.0_BDKi + do k = 1,nodes_per_elem + if ((k.NE.l).AND.(k.NE.i).AND.(i.NE.l)) then + dnum = dnum*(QPtN(j)-GLL_nodes(k)) + elseif (i.EQ.l) then + dnum = 0.0_BDKi + endif + enddo + ShpDer(l,j) = ShpDer(l,j) + dnum + enddo + ShpDer(l,j) = ShpDer(l,j)/den + endif + enddo + enddo + + do j = 1,nqp + do l = 1,nodes_per_elem + + if(abs(QPtN(j)-GLL_nodes(l)).LE.eps) then + Shp(l,j) = 1.0_BDKi + else + dnum = 1.0_BDKi + den = 1.0_BDKi + do k = 1,nodes_per_elem + if (k.NE.l) then + den = den *(GLL_nodes(l) - GLL_nodes(k)) + dnum = dnum*(QPtN(j) - GLL_nodes(k)) + endif + enddo + Shp(l,j) = dnum/den + endif + enddo + enddo + + + END SUBROUTINE BD_diffmtc +!----------------------------------------------------------------------------------------------------------------------------------- +!> this routine interpolates teh POS and CRV based on the nodal values +SUBROUTINE BD_Interp_Pos_CRV(p, eta, POS, CRV, ErrStat, ErrMsg) + + type(BD_ParameterType), intent(in ) :: p ! BD Parameters + real(BDki), intent(in ) :: eta ! location to interpolate to; 0 <= eta <= 1 + real(BDki), intent( out) :: POS(3) ! output XYZ + real(BDki), intent( out) :: CRV(3) ! output rotation parameters + + 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 ! do loop + integer(IntKi) :: j ! do loop + integer(IntKi) :: found ! marker for finding element that eta lies in + integer(IntKi) :: element ! element where eta lies + real(BDki) :: eta_left ! left eta value for an element + real(BDki) :: eta_right ! right eta_value for an element + real(BDki) :: eta_local(1) ! eta_local in [-1,1] for finite element space + + real(BDki),allocatable :: gll(:) ! local gll points; ez enough to generate here + real(BDki),allocatable :: shp(:,:) ! local shape function + real(BDki),allocatable :: shpder(:,:) ! local shape function deriv + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(*), parameter :: RoutineName = 'BD_Interp_Pos_CRV' + + ErrStat = ErrID_None + ErrMsg = "" + + ! find element in which eta resides + eta_right = 0._BDKi + found = 0 + eta_left = 0._BDki + do i = 1, p%elem_total + eta_right = eta_right + p%member_eta(i) + if (eta .le. eta_right .and. found .eq. 0) then + element = i + found = 1 + endif + if (found .eq. 0) then + eta_left = eta_right + endif + enddo + + ! need to evaluate shp and shpder at eta_local in [-1,1] for the found element + eta_local(1) = 2._BDKi * (eta - eta_left)/p%member_eta(element) - 1._BDKi + + call AllocAry(gll, p%nodes_per_elem, "local GLL nodes",ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(shp, p%nodes_per_elem, 1,"local shape function",ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(shpder, p%nodes_per_elem, 1,"local shape deriv function",ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (ErrStat < AbortErrLev) then + call BD_GenerateGLL(p%nodes_per_elem,gll,ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call bd_diffmtc(p%nodes_per_elem, gll, eta_local, 1, shp, shpder) ! evaluate shp and shpder at single point + + pos = 0._BDki + crv = 0._BDki + do i = 1, p%nodes_per_elem + do j = 1, 3 + pos(j) = pos(j) + p%uuN0(j, i,element) *shp(i,1) + CRV(j) = CRV(j) + p%uuN0(j+3,i,element)*shp(i,1) + enddo + enddo + + end if + + if (allocated(gll)) deallocate(gll) + if (allocated(shp)) deallocate(shp) + if (allocated(shpder)) deallocate(shpder) + +END SUBROUTINE BD_Interp_Pos_CRV +!----------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine computes initial CRV parameters +!! given geometry information +SUBROUTINE BD_ComputeIniNodalCrv(e1, phi, cc, ErrStat, ErrMsg) + + REAL(BDKi), INTENT(IN ) :: e1(:) !< Tangent unit vector + REAL(BDKi), INTENT(IN ) :: phi !< Initial twist angle, in degrees + REAL(BDKi), INTENT( OUT) :: cc(:) !< Initial Crv Parameter + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(BDKi) :: e2(3) !< Unit normal vector + REAL(BDKi) :: Rr(3,3) !< Initial rotation matrix + REAL(BDKi) :: PhiRad !< Phi in radians + REAL(BDKi) :: Delta + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'BD_ComputeIniNodalCrv' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + PhiRad = phi*D2R_D ! convert to radians + + ! Note that e1 corresponds with the Z-axis direction in our formulation. For Beam theory, this would be the x-axis. + Rr(:,3) = e1(:) + + e2(3) = -(e1(1)*COS(PhiRad) + e1(2)*SIN(PhiRad))/e1(3) + Delta = SQRT(1.0_BDKi + e2(3)*e2(3)) + e2(1) = COS(PhiRad) + e2(2) = SIN(PhiRad) + e2 = e2 / Delta + Rr(:,1) = e2 + Rr(:,2) = Cross_Product(e1,e2) + + CALL BD_CrvExtractCrv(Rr, cc, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + +END SUBROUTINE BD_ComputeIniNodalCrv +!----------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ExtractRelativeRotation(R, p, rr, ErrStat, ErrMsg) + real(R8Ki), INTENT(in ) :: R(3,3) !< input rotation matrix (transpose of DCM; in BD coords) + type(BD_ParameterType), INTENT(in ) :: p !< Parameters + real(BDKi), INTENT( OUT) :: rr(3) !< W-M parameters of relative rotation + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + real(BDKi) :: R_WM(3) ! W-M parameters of R + real(BDKi) :: R_BD(3,3) ! input rotation matrix in BDKi precision + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'ExtractRelativeRotation' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + +! Calculate p(rr) = p(Glb_crv)^- (+) p(R) where (+) is the curve compose +! which is the same as operation as +! R(rr) = R(Glb_crv)^T R + + ! note that the u%RootMotion mesh does not contain the initial twist, but p%Glb_crv does not have this twist, either. + ! The relative rotation will be the same in this case. + + R_BD = R ! possible type conversion (only if BDKi /= R8Ki) + + CALL BD_CrvExtractCrv(R_BD,R_WM, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + CALL BD_CrvCompose(rr,p%Glb_crv,R_WM,FLAG_R1TR2) ! rr = p%Glb_crv^- composed with R_WM + + ! NOTE: the above calculation is not the inverse of what is in Set_BldMotion_NoAcc. The reason is that this + ! routine is only looking at RootMotion. The Set_BldMotion_NoAcc routine is looking at the blade motion + ! which at the root differs by the WM values in p%uuN0(4:6,1,1) from the RootMotion mesh. + +END SUBROUTINE ExtractRelativeRotation +!----------------------------------------------------------------------------------------------------------------------------------- +FUNCTION BDrot_to_FASTdcm(rr,p) RESULT(dcm) + real(BDKi), intent(in) :: rr(3) !< W-M parameters of relative rotation + type(BD_ParameterType), intent(in) :: p !< Parameters + real(BDKi) :: dcm(3,3) !< input rotation matrix (transpose of DCM; in BD coords) + + + REAL(BDKi) :: temp_CRV2(3) ! temp curvature parameters + real(BDKi) :: R(3,3) ! rotation matrix + +! note differences in setting up meshes with Set_BldMotion_NoAcc +!adp: in the case of the meshes in Set_BldMotion_NoAcc, x%q(4:6,:) and m%qp%uuu(4:6,:,:) are not zero. When this routine is called, they +! are zero, and the expression in Set_BldMotion_NoAcc simplifies to this expression. + + ! rotate relative W-M rotations to global system? + CALL BD_CrvCompose(temp_CRV2,p%Glb_crv,rr,FLAG_R1R2) !temp_CRV2 = p%Glb_crv composed with rr + + ! create rotation matrix from W-M parameters: + CALL BD_CrvMatrixR(temp_CRV2,R) ! returns R (rotation matrix, the transpose of the DCM orientation matrix) + + ! get DCM from rotation matrix: + dcm = TRANSPOSE(R) + + +END FUNCTION BDrot_to_FASTdcm +!----------------------------------------------------------------------------------------------------------------------------------- +END MODULE BeamDyn_Subs diff --git a/OpenFAST/modules/beamdyn/src/BeamDyn_Types.f90 b/OpenFAST/modules/beamdyn/src/BeamDyn_Types.f90 new file mode 100644 index 000000000..196dfafaa --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/BeamDyn_Types.f90 @@ -0,0 +1,13004 @@ +!STARTOFREGISTRYGENERATEDFILE 'BeamDyn_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 +!********************************************************************************************************************************* +! BeamDyn_Types +!................................................................................................................................. +! This file is part of BeamDyn. +! +! 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 BeamDyn. 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 BeamDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_STATIC_ANALYSIS = 1 ! Constant for static analysis. InputType%Dynamic = FALSE. [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_DYNAMIC_ANALYSIS = 2 ! Constant for dynamic analysis. InputType%Dynamic = TRUE .AND. BD_InputFile%QuasiStaticSolve = FALSE [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_DYN_SSS_ANALYSIS = 3 ! Constant for dynamic analysis with Steady State Startup solve. InputType%Dynamic = TRUE .AND. BD_InputFile%QuasiStaticSolve = TRUE [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_MESH_FE = 1 ! Constant for creating y%BldMotion at the FE (GLL) nodes [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_MESH_QP = 2 ! Constant for creating y%BldMotion at the quadrature nodes [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BD_MESH_STATIONS = 3 ! Constant for creating y%BldMotion at the blade property input stations [-] +! ========= BD_InitInputType ======= + TYPE, PUBLIC :: BD_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(1:3) :: gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) , DIMENSION(1:3) :: GlbPos !< Initial Position Vector of the local blade coordinate system [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: GlbRot !< Initial direction cosine matrix of the local blade coordinate system -- in BD coords [-] + REAL(R8Ki) , DIMENSION(1:3) :: RootDisp !< Initial root displacement [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: RootOri !< Initial root orientation [-] + REAL(ReKi) , DIMENSION(1:6) :: RootVel !< Initial root velocities and angular veolcities [-] + REAL(ReKi) , DIMENSION(1:3) :: HubPos !< Initial Hub position vector [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: HubRot !< Initial Hub direction cosine matrix [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + LOGICAL :: DynamicSolve = .TRUE. !< Use dynamic solve option. Set to False for static solving (handled by glue code or driver code). [-] + END TYPE BD_InitInputType +! ======================= +! ========= BD_InitOutputType ======= + TYPE, PUBLIC :: BD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: kp_coordinate !< Key point coordinates array [-] + INTEGER(IntKi) :: kp_total !< Total number of key points [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + END TYPE BD_InitOutputType +! ======================= +! ========= BladeInputData ======= + TYPE, PUBLIC :: BladeInputData + INTEGER(IntKi) :: station_total !< Number of blade input stations [-] + INTEGER(IntKi) :: format_index !< Number of blade input stations [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: station_eta !< Station location in eta [0,1] [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: stiff0 !< C/S stiffness matrix arrays [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: mass0 !< C/S mass matrix arrays [-] + REAL(R8Ki) , DIMENSION(1:6) :: beta !< Damping Coefficient [-] + INTEGER(IntKi) :: damp_flag !< Damping Flag: 0-No Damping, 1-Damped [-] + END TYPE BladeInputData +! ======================= +! ========= BD_InputFile ======= + TYPE, PUBLIC :: BD_InputFile + INTEGER(IntKi) :: member_total !< Total number of members [-] + INTEGER(IntKi) :: kp_total !< Total number of key point [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: kp_member !< Number of key points in each member [-] + INTEGER(IntKi) :: order_elem !< Order of interpolation (basis) function [-] + INTEGER(IntKi) :: load_retries !< Maximum Number of factored load retries [-] + INTEGER(IntKi) :: NRMax !< Max number of iterations in Newton Raphson algorithm [-] + INTEGER(IntKi) :: quadrature !< Quadrature: 1: Gauss; 2: Trapezoidal [-] + INTEGER(IntKi) :: n_fact !< Factorization frequency [-] + INTEGER(IntKi) :: refine !< FE mesh refinement factor for trapezoidal quadrature [-] + REAL(DbKi) :: rhoinf !< Numerical damping parameter for generalized-alpha integrator [-] + REAL(DbKi) :: DTBeam !< Time interval for BeamDyn calculations {or default} (s) [-] + TYPE(BladeInputData) :: InpBl !< Input data for individual blades [see BladeInputData Type] + CHARACTER(1024) :: BldFile !< Name of blade input file [-] + LOGICAL :: UsePitchAct !< Whether to use a pitch actuator inside BeamDyn [(flag)] + LOGICAL :: QuasiStaticInit !< Use quasistatic pre-conditioning with centripetal accelerations in initialization (flag) [dynamic solve and enFAST only] [-] + REAL(R8Ki) :: stop_tol !< Tolerance for stopping criterion [-] + REAL(R8Ki) :: tngt_stf_pert !< Perturbation size for computing finite differenced tangent stiffness [-] + REAL(R8Ki) :: tngt_stf_difftol !< When comparing tangent stiffness matrix, stop simulation if error greater than this [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: kp_coordinate !< Key point coordinates array [-] + REAL(R8Ki) :: pitchJ !< Pitch actuator inertia [(kg-m^2)] + REAL(R8Ki) :: pitchK !< Pitch actuator stiffness [(kg-m^2/s^2)] + REAL(R8Ki) :: pitchC !< Pitch actuator damping [-] + LOGICAL :: Echo !< Echo [-] + LOGICAL :: RotStates = .TRUE. !< Orient states in rotating frame during linearization? (flag) [-] + LOGICAL :: RelStates = .FALSE. !< Define states relative to root motion during linearization? (flag) [-] + LOGICAL :: tngt_stf_fd !< Flag to compute tangent stifness matrix via finite difference [-] + LOGICAL :: tngt_stf_comp !< Flag to compare finite differenced and analytical tangent stifness [-] + INTEGER(IntKi) :: NNodeOuts !< Number of node outputs [0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: OutNd !< Nodes whose values will be output [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + LOGICAL :: SumPrint !< Print summary data to file? (.sum) [-] + CHARACTER(20) :: OutFmt !< Format specifier [-] + INTEGER(IntKi) :: BldNd_NumOuts !< Number of requested output channels per blade node (BD_BldNdOuts) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: BldNd_OutList !< List of user-requested output channels (BD_BldNdOuts) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: BldNd_BlOutNd !< The blade nodes to actually output (BD_BldNdOuts) [-] + CHARACTER(1024) :: BldNd_BlOutNd_Str !< String to parse for the blade nodes to actually output (BD_BldNdOuts) [-] + END TYPE BD_InputFile +! ======================= +! ========= BD_ContinuousStateType ======= + TYPE, PUBLIC :: BD_ContinuousStateType + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: q !< q - displacement (1:3), and rotation displacement parameters (4:6) [m,-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: dqdt !< dqdt - velocity [m/s] + END TYPE BD_ContinuousStateType +! ======================= +! ========= BD_DiscreteStateType ======= + TYPE, PUBLIC :: BD_DiscreteStateType + REAL(ReKi) :: thetaP !< Pitch angle state [-] + REAL(ReKi) :: thetaPD !< Pitch rate state [-] + END TYPE BD_DiscreteStateType +! ======================= +! ========= BD_ConstraintStateType ======= + TYPE, PUBLIC :: BD_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< A variable, Replace if you have constraint states [-] + END TYPE BD_ConstraintStateType +! ======================= +! ========= BD_OtherStateType ======= + TYPE, PUBLIC :: BD_OtherStateType + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: acc !< Acceleration (dqdtdt) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: xcc !< Algorithm acceleration in GA2: (1-alpha_m)*xcc_(n+1) = (1-alpha_f)*Acc_(n+1) + alpha_f*Acc_n - alpha_m*xcc_n [-] + LOGICAL :: InitAcc !< flag to determine if accerlerations have been initialized in updateStates [-] + LOGICAL :: RunQuasiStaticInit !< flag to determine if quasi-static solution initialization should be run again (with load inputs) [-] + END TYPE BD_OtherStateType +! ======================= +! ========= qpParam ======= + TYPE, PUBLIC :: qpParam + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: mmm !< Mass at current QP [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: mEta !< Center of mass location times mass: (m*X_cm, m*Y_cm, m*Z_cm) where X_cm = 0 [-] + END TYPE qpParam +! ======================= +! ========= BD_ParameterType ======= + TYPE, PUBLIC :: BD_ParameterType + REAL(DbKi) :: dt !< module dt [s] + REAL(DbKi) , DIMENSION(1:9) :: coef !< GA2 Coefficient [-] + REAL(DbKi) :: rhoinf !< Numerical Damping Coefficient for GA2 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uuN0 !< Initial Postion Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Stif0_QP !< Sectional Stiffness Properties at quadrature points (6x6xqp) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Mass0_QP !< Sectional Mass Properties at quadrature points (6x6xqp) [-] + REAL(R8Ki) , DIMENSION(1:3) :: gravity !< Gravitational acceleration [m/s^2] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: segment_eta !< Array stored length ratio of each segment w.r.t. member it lies in [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: member_eta !< Array stored length ratio of each member w.r.t. entire blade [-] + REAL(R8Ki) :: blade_length !< Blade Length [-] + REAL(R8Ki) :: blade_mass !< Blade mass [-] + REAL(R8Ki) , DIMENSION(1:3) :: blade_CG !< Blade center of gravity [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: blade_IN !< Blade Length [-] + REAL(R8Ki) , DIMENSION(1:6) :: beta !< Damping Coefficient [-] + REAL(R8Ki) :: tol !< Tolerance used in stopping criterion [-] + REAL(R8Ki) , DIMENSION(1:3) :: GlbPos !< Initial Position Vector between origins of Global and blade frames (BD coordinates) [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: GlbRot !< Initial Rotation Tensor between Global and Blade frames (BD coordinates; transfers local to global) [-] + REAL(R8Ki) , DIMENSION(1:3) :: Glb_crv !< CRV parameters of GlbRot [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QPtN !< Quadrature (QuadPt) point locations in natural frame [-1, 1] [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QPtWeight !< Weights at each quadrature point (QuadPt) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: Shp !< Shape function matrix (index 1 = FE nodes; index 2=quadrature points) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: ShpDer !< Derivative of shape function matrix (index 1 = FE nodes; index 2=quadrature points) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: Jacobian !< Jacobian value at each quadrature point [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uu0 !< Initial Disp/Rot value at quadrature point (at T=0) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: rrN0 !< Initial relative rotation array, relative to root (at T=0) (index 1=rot DOF; index 2=FE nodes; index 3=element) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: E10 !< Initial E10 at quadrature point [-] + INTEGER(IntKi) :: nodes_per_elem !< Finite element (GLL) nodes per element [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: node_elem_idx !< Index to first and last nodes of element in p%node_total sized arrays [-] + INTEGER(IntKi) :: refine !< FE mesh refinement factor for trapezoidal quadrature [-] + INTEGER(IntKi) :: dof_node !< dof per node [-] + INTEGER(IntKi) :: dof_elem !< dof per element [-] + INTEGER(IntKi) :: rot_elem !< rotational dof per element [-] + INTEGER(IntKi) :: elem_total !< Total number of elements [-] + INTEGER(IntKi) :: node_total !< Total number of finite element (GLL) nodes [-] + INTEGER(IntKi) :: dof_total !< Total number of dofs [-] + INTEGER(IntKi) :: nqp !< Number of quadrature points (per element) [-] + INTEGER(IntKi) :: analysis_type !< analysis_type flag [-] + INTEGER(IntKi) :: damp_flag !< damping flag [-] + INTEGER(IntKi) :: ld_retries !< Maximum Number of factored load retries [-] + INTEGER(IntKi) :: niter !< Maximum number of iterations in Newton-Raphson algorithm [-] + INTEGER(IntKi) :: quadrature !< Quadrature method: 1 Gauss 2 Trapezoidal [-] + INTEGER(IntKi) :: n_fact !< Factorization frequency [-] + LOGICAL :: OutInputs !< Determines if we've asked to output the inputs (do we need mesh transfer?) [-] + INTEGER(IntKi) :: NumOuts !< 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) :: NNodeOuts !< Number of nodes to output data to a file[0 - 9] [-] + INTEGER(IntKi) , DIMENSION(1:9) :: OutNd !< Nodes whose values will be output [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NdIndx !< Index into BldMotion mesh (to number the nodes for output without using collocated nodes) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NdIndxInverse !< Index from BldMotion mesh to unique nodes (to number the nodes for output without using collocated nodes) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: OutNd2NdElem !< To go from an output node number to a node/elem pair [-] + CHARACTER(20) :: OutFmt !< Format specifier [-] + LOGICAL :: UsePitchAct !< Whether to use a pitch actuator inside BeamDyn [(flag)] + REAL(ReKi) :: pitchJ !< Pitch actuator inertia [(kg-m^2)] + REAL(ReKi) :: pitchK !< Pitch actuator stiffness [(kg-m^2/s^2)] + REAL(ReKi) :: pitchC !< Pitch actuator damping [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: torqM !< Pitch actuator matrix: (I-hA)^-1 [-] + TYPE(qpParam) :: qp !< Quadrature point info that does not change during simulation [-] + INTEGER(IntKi) :: qp_indx_offset !< Offset for computing index of the quadrature arrays (gauss skips the first [end-point] node) [-] + INTEGER(IntKi) :: BldMotionNodeLoc !< switch to determine where the nodes on the blade motion mesh should be located 1=FE (GLL) nodes; 2=quadrature nodes; 3=blade input stations [-] + LOGICAL :: tngt_stf_fd !< Flag to compute tangent stifness matrix via finite difference [-] + LOGICAL :: tngt_stf_comp !< Flag to compare finite differenced and analytical tangent stifness [-] + REAL(R8Ki) :: tngt_stf_pert !< Perturbation size for computing finite differenced tangent stiffness [-] + REAL(R8Ki) :: tngt_stf_difftol !< When comparing tangent stiffness matrix, stop simulation if error greater than this [-] + INTEGER(IntKi) :: BldNd_NumOuts !< [BD_BldNdOuts] Number of requested output channels per blade node [-] + INTEGER(IntKi) :: BldNd_TotNumOuts !< [BD_BldNdOuts] Total number of requested output channels of blade node information (equal to BldNd_NumOuts * BldNd_BlOutNd) [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: BldNd_OutParam !< [BD_BldNdOuts] Names and units (and other characteristics) of all requested output parameters [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: BldNd_BlOutNd !< [BD_BldNdOuts] The blade nodes to actually output [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: QPtw_Shp_Shp_Jac !< optimization variable: QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) = p%Shp(i,idx_qp)*p%Shp(j,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: QPtw_Shp_ShpDer !< optimization variable: QPtw_Shp_ShpDer(idx_qp,i,j) = p%Shp(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp) [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: QPtw_ShpDer_ShpDer_Jac !< optimization variable: QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) = p%ShpDer(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp)/p%Jacobian(idx_qp,nelem) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: QPtw_Shp_Jac !< optimization variable: QPtw_Shp_Jac(idx_qp,i,nelem) = p%Shp(i,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: QPtw_ShpDer !< optimization variable: QPtw_ShpDer(idx_qp,i) = p%ShpDer(i,idx_qp)*p%QPtWeight(idx_qp) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: FEweight !< weighting factors for integrating local sectional loads [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-] + REAL(R8Ki) , DIMENSION(1:6) :: dx !< vector that determines size of perturbation for x (continuous states) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-] + INTEGER(IntKi) :: Jac_nx !< half the number of continuous states in jacobian matrix [-] + LOGICAL :: RotStates !< Orient states in rotating frame during linearization? (flag) [-] + LOGICAL :: RelStates !< Define states relative to root motion during linearization? (flag) [-] + END TYPE BD_ParameterType +! ======================= +! ========= BD_InputType ======= + TYPE, PUBLIC :: BD_InputType + TYPE(MeshType) :: RootMotion !< contains motion [-] + TYPE(MeshType) :: PointLoad !< Applied point forces along beam axis [-] + TYPE(MeshType) :: DistrLoad !< Applied distributed forces along beam axis [-] + TYPE(MeshType) :: HubMotion !< motion (orientation) at the hub [-] + END TYPE BD_InputType +! ======================= +! ========= BD_OutputType ======= + TYPE, PUBLIC :: BD_OutputType + TYPE(MeshType) :: ReactionForce !< contains force and moments [-] + TYPE(MeshType) :: BldMotion !< Motion (disp,rot,vel, acc) along beam axis [-] + REAL(ReKi) :: RootMxr !< x-component of the root reaction moment expressed in r (used for ServoDyn Bladed DLL Interface) [Nm] + REAL(ReKi) :: RootMyr !< y-component of the root reaction moment expressed in r (used for ServoDyn Bladed DLL Interface) [Nm] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE BD_OutputType +! ======================= +! ========= EqMotionQP ======= + TYPE, PUBLIC :: EqMotionQP + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uuu !< Displacement and rotation field [u c] at current QP [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uup !< Derivative of uuu with respect to X at current QP [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: vvv !< Translational velocity and rotational parameter velocity (at current QP) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: vvp !< Derivative of vvv with respect to X [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: aaa !< Translational acceleration and rotational parameter acceration (at current QP) [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: RR0 !< Rotation tensor at current QP \f$ \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \f$ [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: kappa !< Curvature vector \f$ \underline{k} \f$ at current QP (note this is not \kappa, but a term in \kappa) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: E1 !< \vec{e_1} = x_0^\prime + u^\prime (3) at current QP [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Stif !< C/S stiffness matrix resolved in inertial frame at current QP. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fb !< Gyroscopic forces at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fc !< Elastic force \f$ \underline{F}^c \f$ at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fd !< Elastic force \f$ \underline{F}^d \f$ at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity forces at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fi !< Inertial forces at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Ftemp !< Sum of some of the forces at current QP. 6 [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: RR0mEta !< RR0 times Center of mass location times mass: (m*X_cm, m*Y_cm, m*Z_cm) where X_cm = 0 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: rho !< Tensor of inertia resolved in inertia frame at quadrature point. 3x3 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: betaC !< No idea. Used in dissipative force. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Gi !< Gyroscopic matrix for inertial force. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ki !< Stiffness matrix for inertial force. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Mi !< Mass matrix for inertial force. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Oe !< \f$ \underline{\underline{\mathcal{O}}} \f$ from equation (19) of NREL CP-2C00-60759. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Pe !< \f$ \underline{\underline{\mathcal{P}}} \f$ from equation (20) of NREL CP-2C00-60759. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Qe !< \f$ \underline{\underline{\mathcal{Q}}} \f$ from equation (21) of NREL CP-2C00-60759. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Gd !< Dissipative term for gyroscopic term. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Od !< Dissipative term on O. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Pd !< Dissipative term on P. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Qd !< Dissipative term on Q. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Sd !< Dissipative term on S. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Xd !< Dissipative term on X. 6x6 [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Yd !< Dissipative term on Y. 6x6 [-] + END TYPE EqMotionQP +! ======================= +! ========= BD_MiscVarType ======= + TYPE, PUBLIC :: BD_MiscVarType + TYPE(MeshType) :: u_DistrLoad_at_y !< input loads at output node locations [-] + TYPE(MeshType) :: y_BldMotion_at_u !< output motions at input node locations (displacements necessary for mapping loads) [-] + TYPE(MeshMapType) :: Map_u_DistrLoad_to_y !< mapping of input loads to output node locations [-] + TYPE(MeshMapType) :: Map_y_BldMotion_to_u !< mapping of output motions to input node locations (for load transfer) [-] + INTEGER(IntKi) :: Un_Sum !< unit number of summary file [-] + TYPE(EqMotionQP) :: qp !< Quadrature point calculation info [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: lin_A !< A (dXdx) matrix used in linearization (before RotState is applied) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: lin_C !< C (dYdx) matrix used in linearization (before RotState is applied) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Nrrr !< Rotation parameters relative to root node, from Nuuu (at GLL points) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: elf !< [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: EFint !< Elastic forces internal to blade. For output calculations only. [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: elk !< [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: elg !< [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: elm !< [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: DistrLoad_QP !< Copy of the distributed load, in the BD reference frame [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: PointLoadLcl !< Copy of the point loads, in the BD reference frame [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: StifK !< Stiffness Matrix [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: MassM !< Mass Matrix [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: DampG !< Damping Matrix [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: StifK_fd !< Finite differenced Stiffness Matrix [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: MassM_fd !< Finite differenced Mass Matrix [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: DampG_fd !< Finite differenced Damping Matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: RHS !< Right-hand-side vector [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: RHS_p !< Positive fd perturbation of RHS [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: RHS_m !< Negative fd perturbation of RHS [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: BldInternalForceFE !< Force/Moment array for internal force calculations at FE [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: BldInternalForceQP !< Force/Moment array for internal force calculations at QP [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FirstNodeReactionLclForceMoment !< Force/Moment array for first node reaction. Needed in InternalForce calculations. [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: Solution !< Result from LAPACK solve (X from A*X = B solve) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: LP_StifK !< Stiffness Matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: LP_MassM !< Mass Matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: LP_MassM_LU !< Mass Matrix for LU [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: LP_RHS !< Right-hand-side vector [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: LP_StifK_LU !< Stiffness Matrix for LU [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: LP_RHS_LU !< Right-hand-side vector for LU [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: LP_indx !< Index vector for LU [-] + TYPE(BD_InputType) :: u !< Inputs converted to the internal BD coordinate system [-] + TYPE(BD_InputType) :: u2 !< Inputs in the FAST coordinate system, possibly modified by pitch actuator [-] + END TYPE BD_MiscVarType +! ======================= +CONTAINS + SUBROUTINE BD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(BD_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 = 'BD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%gravity = SrcInitInputData%gravity + DstInitInputData%GlbPos = SrcInitInputData%GlbPos + DstInitInputData%GlbRot = SrcInitInputData%GlbRot + DstInitInputData%RootDisp = SrcInitInputData%RootDisp + DstInitInputData%RootOri = SrcInitInputData%RootOri + DstInitInputData%RootVel = SrcInitInputData%RootVel + DstInitInputData%HubPos = SrcInitInputData%HubPos + DstInitInputData%HubRot = SrcInitInputData%HubRot + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%DynamicSolve = SrcInitInputData%DynamicSolve + END SUBROUTINE BD_CopyInitInput + + SUBROUTINE BD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(BD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE BD_DestroyInitInput + + SUBROUTINE BD_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(BD_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 = 'BD_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + SIZE(InData%gravity) ! gravity + Re_BufSz = Re_BufSz + SIZE(InData%GlbPos) ! GlbPos + Db_BufSz = Db_BufSz + SIZE(InData%GlbRot) ! GlbRot + Db_BufSz = Db_BufSz + SIZE(InData%RootDisp) ! RootDisp + Db_BufSz = Db_BufSz + SIZE(InData%RootOri) ! RootOri + Re_BufSz = Re_BufSz + SIZE(InData%RootVel) ! RootVel + Re_BufSz = Re_BufSz + SIZE(InData%HubPos) ! HubPos + Db_BufSz = Db_BufSz + SIZE(InData%HubRot) ! HubRot + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1 ! DynamicSolve + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%gravity,1), UBOUND(InData%gravity,1) + ReKiBuf(Re_Xferred) = InData%gravity(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%GlbPos,1), UBOUND(InData%GlbPos,1) + ReKiBuf(Re_Xferred) = InData%GlbPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%GlbRot,2), UBOUND(InData%GlbRot,2) + DO i1 = LBOUND(InData%GlbRot,1), UBOUND(InData%GlbRot,1) + DbKiBuf(Db_Xferred) = InData%GlbRot(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%RootDisp,1), UBOUND(InData%RootDisp,1) + DbKiBuf(Db_Xferred) = InData%RootDisp(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i2 = LBOUND(InData%RootOri,2), UBOUND(InData%RootOri,2) + DO i1 = LBOUND(InData%RootOri,1), UBOUND(InData%RootOri,1) + DbKiBuf(Db_Xferred) = InData%RootOri(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%RootVel,1), UBOUND(InData%RootVel,1) + ReKiBuf(Re_Xferred) = InData%RootVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%HubPos,1), UBOUND(InData%HubPos,1) + ReKiBuf(Re_Xferred) = InData%HubPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%HubRot,2), UBOUND(InData%HubRot,2) + DO i1 = LBOUND(InData%HubRot,1), UBOUND(InData%HubRot,1) + DbKiBuf(Db_Xferred) = InData%HubRot(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DynamicSolve, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_PackInitInput + + SUBROUTINE BD_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(BD_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 = 'BD_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%gravity,1) + i1_u = UBOUND(OutData%gravity,1) + DO i1 = LBOUND(OutData%gravity,1), UBOUND(OutData%gravity,1) + OutData%gravity(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%GlbPos,1) + i1_u = UBOUND(OutData%GlbPos,1) + DO i1 = LBOUND(OutData%GlbPos,1), UBOUND(OutData%GlbPos,1) + OutData%GlbPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%GlbRot,1) + i1_u = UBOUND(OutData%GlbRot,1) + i2_l = LBOUND(OutData%GlbRot,2) + i2_u = UBOUND(OutData%GlbRot,2) + DO i2 = LBOUND(OutData%GlbRot,2), UBOUND(OutData%GlbRot,2) + DO i1 = LBOUND(OutData%GlbRot,1), UBOUND(OutData%GlbRot,1) + OutData%GlbRot(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%RootDisp,1) + i1_u = UBOUND(OutData%RootDisp,1) + DO i1 = LBOUND(OutData%RootDisp,1), UBOUND(OutData%RootDisp,1) + OutData%RootDisp(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%RootOri,1) + i1_u = UBOUND(OutData%RootOri,1) + i2_l = LBOUND(OutData%RootOri,2) + i2_u = UBOUND(OutData%RootOri,2) + DO i2 = LBOUND(OutData%RootOri,2), UBOUND(OutData%RootOri,2) + DO i1 = LBOUND(OutData%RootOri,1), UBOUND(OutData%RootOri,1) + OutData%RootOri(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%RootVel,1) + i1_u = UBOUND(OutData%RootVel,1) + DO i1 = LBOUND(OutData%RootVel,1), UBOUND(OutData%RootVel,1) + OutData%RootVel(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%HubPos,1) + i1_u = UBOUND(OutData%HubPos,1) + DO i1 = LBOUND(OutData%HubPos,1), UBOUND(OutData%HubPos,1) + OutData%HubPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%HubRot,1) + i1_u = UBOUND(OutData%HubRot,1) + i2_l = LBOUND(OutData%HubRot,2) + i2_u = UBOUND(OutData%HubRot,2) + DO i2 = LBOUND(OutData%HubRot,2), UBOUND(OutData%HubRot,2) + DO i1 = LBOUND(OutData%HubRot,1), UBOUND(OutData%HubRot,1) + OutData%HubRot(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%DynamicSolve = TRANSFER(IntKiBuf(Int_Xferred), OutData%DynamicSolve) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_UnPackInitInput + + SUBROUTINE BD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(BD_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) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%kp_coordinate)) THEN + i1_l = LBOUND(SrcInitOutputData%kp_coordinate,1) + i1_u = UBOUND(SrcInitOutputData%kp_coordinate,1) + i2_l = LBOUND(SrcInitOutputData%kp_coordinate,2) + i2_u = UBOUND(SrcInitOutputData%kp_coordinate,2) + IF (.NOT. ALLOCATED(DstInitOutputData%kp_coordinate)) THEN + ALLOCATE(DstInitOutputData%kp_coordinate(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%kp_coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%kp_coordinate = SrcInitOutputData%kp_coordinate +ENDIF + DstInitOutputData%kp_total = SrcInitOutputData%kp_total +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x +ENDIF + END SUBROUTINE BD_CopyInitOutput + + SUBROUTINE BD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(BD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%kp_coordinate)) THEN + DEALLOCATE(InitOutputData%kp_coordinate) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF + END SUBROUTINE BD_DestroyInitOutput + + SUBROUTINE BD_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(BD_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 = 'BD_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + 1 ! kp_coordinate allocated yes/no + IF ( ALLOCATED(InData%kp_coordinate) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! kp_coordinate upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%kp_coordinate) ! kp_coordinate + END IF + Int_BufSz = Int_BufSz + 1 ! kp_total + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 + IF ( .NOT. ALLOCATED(InData%kp_coordinate) ) 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%kp_coordinate,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kp_coordinate,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%kp_coordinate,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kp_coordinate,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%kp_coordinate,2), UBOUND(InData%kp_coordinate,2) + DO i1 = LBOUND(InData%kp_coordinate,1), UBOUND(InData%kp_coordinate,1) + DbKiBuf(Db_Xferred) = InData%kp_coordinate(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%kp_total + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) 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%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) 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%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) 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%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE BD_PackInitOutput + + SUBROUTINE BD_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(BD_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) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! kp_coordinate 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%kp_coordinate)) DEALLOCATE(OutData%kp_coordinate) + ALLOCATE(OutData%kp_coordinate(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%kp_coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%kp_coordinate,2), UBOUND(OutData%kp_coordinate,2) + DO i1 = LBOUND(OutData%kp_coordinate,1), UBOUND(OutData%kp_coordinate,1) + OutData%kp_coordinate(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + OutData%kp_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x 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%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x 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%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x 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%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE BD_UnPackInitOutput + + SUBROUTINE BD_CopyBladeInputData( SrcBladeInputDataData, DstBladeInputDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladeInputData), INTENT(IN) :: SrcBladeInputDataData + TYPE(BladeInputData), INTENT(INOUT) :: DstBladeInputDataData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CopyBladeInputData' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladeInputDataData%station_total = SrcBladeInputDataData%station_total + DstBladeInputDataData%format_index = SrcBladeInputDataData%format_index +IF (ALLOCATED(SrcBladeInputDataData%station_eta)) THEN + i1_l = LBOUND(SrcBladeInputDataData%station_eta,1) + i1_u = UBOUND(SrcBladeInputDataData%station_eta,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%station_eta)) THEN + ALLOCATE(DstBladeInputDataData%station_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%station_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%station_eta = SrcBladeInputDataData%station_eta +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%stiff0)) THEN + i1_l = LBOUND(SrcBladeInputDataData%stiff0,1) + i1_u = UBOUND(SrcBladeInputDataData%stiff0,1) + i2_l = LBOUND(SrcBladeInputDataData%stiff0,2) + i2_u = UBOUND(SrcBladeInputDataData%stiff0,2) + i3_l = LBOUND(SrcBladeInputDataData%stiff0,3) + i3_u = UBOUND(SrcBladeInputDataData%stiff0,3) + IF (.NOT. ALLOCATED(DstBladeInputDataData%stiff0)) THEN + ALLOCATE(DstBladeInputDataData%stiff0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%stiff0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%stiff0 = SrcBladeInputDataData%stiff0 +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%mass0)) THEN + i1_l = LBOUND(SrcBladeInputDataData%mass0,1) + i1_u = UBOUND(SrcBladeInputDataData%mass0,1) + i2_l = LBOUND(SrcBladeInputDataData%mass0,2) + i2_u = UBOUND(SrcBladeInputDataData%mass0,2) + i3_l = LBOUND(SrcBladeInputDataData%mass0,3) + i3_u = UBOUND(SrcBladeInputDataData%mass0,3) + IF (.NOT. ALLOCATED(DstBladeInputDataData%mass0)) THEN + ALLOCATE(DstBladeInputDataData%mass0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%mass0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%mass0 = SrcBladeInputDataData%mass0 +ENDIF + DstBladeInputDataData%beta = SrcBladeInputDataData%beta + DstBladeInputDataData%damp_flag = SrcBladeInputDataData%damp_flag + END SUBROUTINE BD_CopyBladeInputData + + SUBROUTINE BD_DestroyBladeInputData( BladeInputDataData, ErrStat, ErrMsg ) + TYPE(BladeInputData), INTENT(INOUT) :: BladeInputDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyBladeInputData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladeInputDataData%station_eta)) THEN + DEALLOCATE(BladeInputDataData%station_eta) +ENDIF +IF (ALLOCATED(BladeInputDataData%stiff0)) THEN + DEALLOCATE(BladeInputDataData%stiff0) +ENDIF +IF (ALLOCATED(BladeInputDataData%mass0)) THEN + DEALLOCATE(BladeInputDataData%mass0) +ENDIF + END SUBROUTINE BD_DestroyBladeInputData + + SUBROUTINE BD_PackBladeInputData( 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(BladeInputData), 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 = 'BD_PackBladeInputData' + ! 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 ! station_total + Int_BufSz = Int_BufSz + 1 ! format_index + Int_BufSz = Int_BufSz + 1 ! station_eta allocated yes/no + IF ( ALLOCATED(InData%station_eta) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! station_eta upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%station_eta) ! station_eta + END IF + Int_BufSz = Int_BufSz + 1 ! stiff0 allocated yes/no + IF ( ALLOCATED(InData%stiff0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! stiff0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%stiff0) ! stiff0 + END IF + Int_BufSz = Int_BufSz + 1 ! mass0 allocated yes/no + IF ( ALLOCATED(InData%mass0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! mass0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%mass0) ! mass0 + END IF + Db_BufSz = Db_BufSz + SIZE(InData%beta) ! beta + Int_BufSz = Int_BufSz + 1 ! damp_flag + 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%station_total + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%format_index + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%station_eta) ) 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%station_eta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%station_eta,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%station_eta,1), UBOUND(InData%station_eta,1) + DbKiBuf(Db_Xferred) = InData%station_eta(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%stiff0) ) 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%stiff0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%stiff0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%stiff0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%stiff0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%stiff0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%stiff0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%stiff0,3), UBOUND(InData%stiff0,3) + DO i2 = LBOUND(InData%stiff0,2), UBOUND(InData%stiff0,2) + DO i1 = LBOUND(InData%stiff0,1), UBOUND(InData%stiff0,1) + DbKiBuf(Db_Xferred) = InData%stiff0(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%mass0) ) 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%mass0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mass0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mass0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mass0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mass0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mass0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%mass0,3), UBOUND(InData%mass0,3) + DO i2 = LBOUND(InData%mass0,2), UBOUND(InData%mass0,2) + DO i1 = LBOUND(InData%mass0,1), UBOUND(InData%mass0,1) + DbKiBuf(Db_Xferred) = InData%mass0(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%beta,1), UBOUND(InData%beta,1) + DbKiBuf(Db_Xferred) = InData%beta(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%damp_flag + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_PackBladeInputData + + SUBROUTINE BD_UnPackBladeInputData( 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(BladeInputData), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_UnPackBladeInputData' + ! 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%station_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%format_index = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! station_eta 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%station_eta)) DEALLOCATE(OutData%station_eta) + ALLOCATE(OutData%station_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%station_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%station_eta,1), UBOUND(OutData%station_eta,1) + OutData%station_eta(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! stiff0 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%stiff0)) DEALLOCATE(OutData%stiff0) + ALLOCATE(OutData%stiff0(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%stiff0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%stiff0,3), UBOUND(OutData%stiff0,3) + DO i2 = LBOUND(OutData%stiff0,2), UBOUND(OutData%stiff0,2) + DO i1 = LBOUND(OutData%stiff0,1), UBOUND(OutData%stiff0,1) + OutData%stiff0(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! mass0 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%mass0)) DEALLOCATE(OutData%mass0) + ALLOCATE(OutData%mass0(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%mass0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%mass0,3), UBOUND(OutData%mass0,3) + DO i2 = LBOUND(OutData%mass0,2), UBOUND(OutData%mass0,2) + DO i1 = LBOUND(OutData%mass0,1), UBOUND(OutData%mass0,1) + OutData%mass0(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%beta,1) + i1_u = UBOUND(OutData%beta,1) + DO i1 = LBOUND(OutData%beta,1), UBOUND(OutData%beta,1) + OutData%beta(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + OutData%damp_flag = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_UnPackBladeInputData + + SUBROUTINE BD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(BD_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'BD_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%member_total = SrcInputFileData%member_total + DstInputFileData%kp_total = SrcInputFileData%kp_total +IF (ALLOCATED(SrcInputFileData%kp_member)) THEN + i1_l = LBOUND(SrcInputFileData%kp_member,1) + i1_u = UBOUND(SrcInputFileData%kp_member,1) + IF (.NOT. ALLOCATED(DstInputFileData%kp_member)) THEN + ALLOCATE(DstInputFileData%kp_member(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%kp_member.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%kp_member = SrcInputFileData%kp_member +ENDIF + DstInputFileData%order_elem = SrcInputFileData%order_elem + DstInputFileData%load_retries = SrcInputFileData%load_retries + DstInputFileData%NRMax = SrcInputFileData%NRMax + DstInputFileData%quadrature = SrcInputFileData%quadrature + DstInputFileData%n_fact = SrcInputFileData%n_fact + DstInputFileData%refine = SrcInputFileData%refine + DstInputFileData%rhoinf = SrcInputFileData%rhoinf + DstInputFileData%DTBeam = SrcInputFileData%DTBeam + CALL BD_Copybladeinputdata( SrcInputFileData%InpBl, DstInputFileData%InpBl, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInputFileData%BldFile = SrcInputFileData%BldFile + DstInputFileData%UsePitchAct = SrcInputFileData%UsePitchAct + DstInputFileData%QuasiStaticInit = SrcInputFileData%QuasiStaticInit + DstInputFileData%stop_tol = SrcInputFileData%stop_tol + DstInputFileData%tngt_stf_pert = SrcInputFileData%tngt_stf_pert + DstInputFileData%tngt_stf_difftol = SrcInputFileData%tngt_stf_difftol +IF (ALLOCATED(SrcInputFileData%kp_coordinate)) THEN + i1_l = LBOUND(SrcInputFileData%kp_coordinate,1) + i1_u = UBOUND(SrcInputFileData%kp_coordinate,1) + i2_l = LBOUND(SrcInputFileData%kp_coordinate,2) + i2_u = UBOUND(SrcInputFileData%kp_coordinate,2) + IF (.NOT. ALLOCATED(DstInputFileData%kp_coordinate)) THEN + ALLOCATE(DstInputFileData%kp_coordinate(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%kp_coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%kp_coordinate = SrcInputFileData%kp_coordinate +ENDIF + DstInputFileData%pitchJ = SrcInputFileData%pitchJ + DstInputFileData%pitchK = SrcInputFileData%pitchK + DstInputFileData%pitchC = SrcInputFileData%pitchC + DstInputFileData%Echo = SrcInputFileData%Echo + DstInputFileData%RotStates = SrcInputFileData%RotStates + DstInputFileData%RelStates = SrcInputFileData%RelStates + DstInputFileData%tngt_stf_fd = SrcInputFileData%tngt_stf_fd + DstInputFileData%tngt_stf_comp = SrcInputFileData%tngt_stf_comp + DstInputFileData%NNodeOuts = SrcInputFileData%NNodeOuts + DstInputFileData%OutNd = SrcInputFileData%OutNd + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%OutFmt = SrcInputFileData%OutFmt + DstInputFileData%BldNd_NumOuts = SrcInputFileData%BldNd_NumOuts +IF (ALLOCATED(SrcInputFileData%BldNd_OutList)) THEN + i1_l = LBOUND(SrcInputFileData%BldNd_OutList,1) + i1_u = UBOUND(SrcInputFileData%BldNd_OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%BldNd_OutList)) THEN + ALLOCATE(DstInputFileData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BldNd_OutList = SrcInputFileData%BldNd_OutList +ENDIF +IF (ALLOCATED(SrcInputFileData%BldNd_BlOutNd)) THEN + i1_l = LBOUND(SrcInputFileData%BldNd_BlOutNd,1) + i1_u = UBOUND(SrcInputFileData%BldNd_BlOutNd,1) + IF (.NOT. ALLOCATED(DstInputFileData%BldNd_BlOutNd)) THEN + ALLOCATE(DstInputFileData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BldNd_BlOutNd = SrcInputFileData%BldNd_BlOutNd +ENDIF + DstInputFileData%BldNd_BlOutNd_Str = SrcInputFileData%BldNd_BlOutNd_Str + END SUBROUTINE BD_CopyInputFile + + SUBROUTINE BD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(BD_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%kp_member)) THEN + DEALLOCATE(InputFileData%kp_member) +ENDIF + CALL BD_Destroybladeinputdata( InputFileData%InpBl, ErrStat, ErrMsg ) +IF (ALLOCATED(InputFileData%kp_coordinate)) THEN + DEALLOCATE(InputFileData%kp_coordinate) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF +IF (ALLOCATED(InputFileData%BldNd_OutList)) THEN + DEALLOCATE(InputFileData%BldNd_OutList) +ENDIF +IF (ALLOCATED(InputFileData%BldNd_BlOutNd)) THEN + DEALLOCATE(InputFileData%BldNd_BlOutNd) +ENDIF + END SUBROUTINE BD_DestroyInputFile + + SUBROUTINE BD_PackInputFile( 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(BD_InputFile), 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 = 'BD_PackInputFile' + ! 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 ! member_total + Int_BufSz = Int_BufSz + 1 ! kp_total + Int_BufSz = Int_BufSz + 1 ! kp_member allocated yes/no + IF ( ALLOCATED(InData%kp_member) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! kp_member upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%kp_member) ! kp_member + END IF + Int_BufSz = Int_BufSz + 1 ! order_elem + Int_BufSz = Int_BufSz + 1 ! load_retries + Int_BufSz = Int_BufSz + 1 ! NRMax + Int_BufSz = Int_BufSz + 1 ! quadrature + Int_BufSz = Int_BufSz + 1 ! n_fact + Int_BufSz = Int_BufSz + 1 ! refine + Db_BufSz = Db_BufSz + 1 ! rhoinf + Db_BufSz = Db_BufSz + 1 ! DTBeam + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! InpBl: size of buffers for each call to pack subtype + CALL BD_Packbladeinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBl, ErrStat2, ErrMsg2, .TRUE. ) ! InpBl + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InpBl + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InpBl + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InpBl + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%BldFile) ! BldFile + Int_BufSz = Int_BufSz + 1 ! UsePitchAct + Int_BufSz = Int_BufSz + 1 ! QuasiStaticInit + Db_BufSz = Db_BufSz + 1 ! stop_tol + Db_BufSz = Db_BufSz + 1 ! tngt_stf_pert + Db_BufSz = Db_BufSz + 1 ! tngt_stf_difftol + Int_BufSz = Int_BufSz + 1 ! kp_coordinate allocated yes/no + IF ( ALLOCATED(InData%kp_coordinate) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! kp_coordinate upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%kp_coordinate) ! kp_coordinate + END IF + Db_BufSz = Db_BufSz + 1 ! pitchJ + Db_BufSz = Db_BufSz + 1 ! pitchK + Db_BufSz = Db_BufSz + 1 ! pitchC + Int_BufSz = Int_BufSz + 1 ! Echo + Int_BufSz = Int_BufSz + 1 ! RotStates + Int_BufSz = Int_BufSz + 1 ! RelStates + Int_BufSz = Int_BufSz + 1 ! tngt_stf_fd + Int_BufSz = Int_BufSz + 1 ! tngt_stf_comp + Int_BufSz = Int_BufSz + 1 ! NNodeOuts + Int_BufSz = Int_BufSz + SIZE(InData%OutNd) ! OutNd + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + END IF + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutList allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_OutList)*LEN(InData%BldNd_OutList) ! BldNd_OutList + END IF + Int_BufSz = Int_BufSz + 1 ! BldNd_BlOutNd allocated yes/no + IF ( ALLOCATED(InData%BldNd_BlOutNd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_BlOutNd upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_BlOutNd) ! BldNd_BlOutNd + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%BldNd_BlOutNd_Str) ! BldNd_BlOutNd_Str + 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%member_total + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%kp_total + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%kp_member) ) 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%kp_member,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kp_member,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%kp_member,1), UBOUND(InData%kp_member,1) + IntKiBuf(Int_Xferred) = InData%kp_member(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%order_elem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%load_retries + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NRMax + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%quadrature + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_fact + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%refine + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%rhoinf + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DTBeam + Db_Xferred = Db_Xferred + 1 + CALL BD_Packbladeinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBl, ErrStat2, ErrMsg2, OnlySize ) ! InpBl + 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%BldFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%UsePitchAct, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%QuasiStaticInit, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%stop_tol + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%tngt_stf_pert + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%tngt_stf_difftol + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%kp_coordinate) ) 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%kp_coordinate,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kp_coordinate,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%kp_coordinate,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kp_coordinate,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%kp_coordinate,2), UBOUND(InData%kp_coordinate,2) + DO i1 = LBOUND(InData%kp_coordinate,1), UBOUND(InData%kp_coordinate,1) + DbKiBuf(Db_Xferred) = InData%kp_coordinate(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + DbKiBuf(Db_Xferred) = InData%pitchJ + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%pitchK + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%pitchC + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotStates, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RelStates, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%tngt_stf_fd, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%tngt_stf_comp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodeOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%OutNd,1), UBOUND(InData%OutNd,1) + IntKiBuf(Int_Xferred) = InData%OutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_OutList) ) 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%BldNd_OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutList,1), UBOUND(InData%BldNd_OutList,1) + DO I = 1, LEN(InData%BldNd_OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldNd_BlOutNd) ) 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%BldNd_BlOutNd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_BlOutNd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_BlOutNd,1), UBOUND(InData%BldNd_BlOutNd,1) + IntKiBuf(Int_Xferred) = InData%BldNd_BlOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DO I = 1, LEN(InData%BldNd_BlOutNd_Str) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_BlOutNd_Str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE BD_PackInputFile + + SUBROUTINE BD_UnPackInputFile( 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(BD_InputFile), 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 = 'BD_UnPackInputFile' + ! 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%member_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%kp_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! kp_member 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%kp_member)) DEALLOCATE(OutData%kp_member) + ALLOCATE(OutData%kp_member(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%kp_member.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%kp_member,1), UBOUND(OutData%kp_member,1) + OutData%kp_member(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%order_elem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%load_retries = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NRMax = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%quadrature = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_fact = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%refine = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%rhoinf = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DTBeam = DbKiBuf(Db_Xferred) + Db_Xferred = Db_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 BD_Unpackbladeinputdata( Re_Buf, Db_Buf, Int_Buf, OutData%InpBl, ErrStat2, ErrMsg2 ) ! InpBl + 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%BldFile) + OutData%BldFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UsePitchAct = TRANSFER(IntKiBuf(Int_Xferred), OutData%UsePitchAct) + Int_Xferred = Int_Xferred + 1 + OutData%QuasiStaticInit = TRANSFER(IntKiBuf(Int_Xferred), OutData%QuasiStaticInit) + Int_Xferred = Int_Xferred + 1 + OutData%stop_tol = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%tngt_stf_pert = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%tngt_stf_difftol = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! kp_coordinate 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%kp_coordinate)) DEALLOCATE(OutData%kp_coordinate) + ALLOCATE(OutData%kp_coordinate(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%kp_coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%kp_coordinate,2), UBOUND(OutData%kp_coordinate,2) + DO i1 = LBOUND(OutData%kp_coordinate,1), UBOUND(OutData%kp_coordinate,1) + OutData%kp_coordinate(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + OutData%pitchJ = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%pitchK = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%pitchC = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 + OutData%RotStates = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotStates) + Int_Xferred = Int_Xferred + 1 + OutData%RelStates = TRANSFER(IntKiBuf(Int_Xferred), OutData%RelStates) + Int_Xferred = Int_Xferred + 1 + OutData%tngt_stf_fd = TRANSFER(IntKiBuf(Int_Xferred), OutData%tngt_stf_fd) + Int_Xferred = Int_Xferred + 1 + OutData%tngt_stf_comp = TRANSFER(IntKiBuf(Int_Xferred), OutData%tngt_stf_comp) + Int_Xferred = Int_Xferred + 1 + OutData%NNodeOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%OutNd,1) + i1_u = UBOUND(OutData%OutNd,1) + DO i1 = LBOUND(OutData%OutNd,1), UBOUND(OutData%OutNd,1) + OutData%OutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutList 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%BldNd_OutList)) DEALLOCATE(OutData%BldNd_OutList) + ALLOCATE(OutData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutList,1), UBOUND(OutData%BldNd_OutList,1) + DO I = 1, LEN(OutData%BldNd_OutList) + OutData%BldNd_OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_BlOutNd 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%BldNd_BlOutNd)) DEALLOCATE(OutData%BldNd_BlOutNd) + ALLOCATE(OutData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_BlOutNd,1), UBOUND(OutData%BldNd_BlOutNd,1) + OutData%BldNd_BlOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DO I = 1, LEN(OutData%BldNd_BlOutNd_Str) + OutData%BldNd_BlOutNd_Str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE BD_UnPackInputFile + + SUBROUTINE BD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(BD_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 = 'BD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%q)) THEN + i1_l = LBOUND(SrcContStateData%q,1) + i1_u = UBOUND(SrcContStateData%q,1) + i2_l = LBOUND(SrcContStateData%q,2) + i2_u = UBOUND(SrcContStateData%q,2) + IF (.NOT. ALLOCATED(DstContStateData%q)) THEN + ALLOCATE(DstContStateData%q(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%q.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%q = SrcContStateData%q +ENDIF +IF (ALLOCATED(SrcContStateData%dqdt)) THEN + i1_l = LBOUND(SrcContStateData%dqdt,1) + i1_u = UBOUND(SrcContStateData%dqdt,1) + i2_l = LBOUND(SrcContStateData%dqdt,2) + i2_u = UBOUND(SrcContStateData%dqdt,2) + IF (.NOT. ALLOCATED(DstContStateData%dqdt)) THEN + ALLOCATE(DstContStateData%dqdt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%dqdt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%dqdt = SrcContStateData%dqdt +ENDIF + END SUBROUTINE BD_CopyContState + + SUBROUTINE BD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(BD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%q)) THEN + DEALLOCATE(ContStateData%q) +ENDIF +IF (ALLOCATED(ContStateData%dqdt)) THEN + DEALLOCATE(ContStateData%dqdt) +ENDIF + END SUBROUTINE BD_DestroyContState + + SUBROUTINE BD_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(BD_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 = 'BD_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 + Int_BufSz = Int_BufSz + 1 ! q allocated yes/no + IF ( ALLOCATED(InData%q) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! q upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%q) ! q + END IF + Int_BufSz = Int_BufSz + 1 ! dqdt allocated yes/no + IF ( ALLOCATED(InData%dqdt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! dqdt upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%dqdt) ! dqdt + 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%q) ) 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%q,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%q,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%q,2), UBOUND(InData%q,2) + DO i1 = LBOUND(InData%q,1), UBOUND(InData%q,1) + DbKiBuf(Db_Xferred) = InData%q(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dqdt) ) 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%dqdt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dqdt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dqdt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dqdt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%dqdt,2), UBOUND(InData%dqdt,2) + DO i1 = LBOUND(InData%dqdt,1), UBOUND(InData%dqdt,1) + DbKiBuf(Db_Xferred) = InData%dqdt(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BD_PackContState + + SUBROUTINE BD_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(BD_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 = 'BD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! q 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%q)) DEALLOCATE(OutData%q) + ALLOCATE(OutData%q(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%q.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%q,2), UBOUND(OutData%q,2) + DO i1 = LBOUND(OutData%q,1), UBOUND(OutData%q,1) + OutData%q(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dqdt 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%dqdt)) DEALLOCATE(OutData%dqdt) + ALLOCATE(OutData%dqdt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dqdt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%dqdt,2), UBOUND(OutData%dqdt,2) + DO i1 = LBOUND(OutData%dqdt,1), UBOUND(OutData%dqdt,1) + OutData%dqdt(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE BD_UnPackContState + + SUBROUTINE BD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(BD_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 = 'BD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%thetaP = SrcDiscStateData%thetaP + DstDiscStateData%thetaPD = SrcDiscStateData%thetaPD + END SUBROUTINE BD_CopyDiscState + + SUBROUTINE BD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(BD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE BD_DestroyDiscState + + SUBROUTINE BD_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(BD_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 = 'BD_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 ! thetaP + Re_BufSz = Re_BufSz + 1 ! thetaPD + 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%thetaP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%thetaPD + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BD_PackDiscState + + SUBROUTINE BD_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(BD_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 = 'BD_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%thetaP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%thetaPD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE BD_UnPackDiscState + + SUBROUTINE BD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(BD_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 = 'BD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE BD_CopyConstrState + + SUBROUTINE BD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(BD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE BD_DestroyConstrState + + SUBROUTINE BD_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(BD_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 = 'BD_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 BD_PackConstrState + + SUBROUTINE BD_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(BD_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 = 'BD_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 BD_UnPackConstrState + + SUBROUTINE BD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(BD_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) :: 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 = 'BD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%acc)) THEN + i1_l = LBOUND(SrcOtherStateData%acc,1) + i1_u = UBOUND(SrcOtherStateData%acc,1) + i2_l = LBOUND(SrcOtherStateData%acc,2) + i2_u = UBOUND(SrcOtherStateData%acc,2) + IF (.NOT. ALLOCATED(DstOtherStateData%acc)) THEN + ALLOCATE(DstOtherStateData%acc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%acc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%acc = SrcOtherStateData%acc +ENDIF +IF (ALLOCATED(SrcOtherStateData%xcc)) THEN + i1_l = LBOUND(SrcOtherStateData%xcc,1) + i1_u = UBOUND(SrcOtherStateData%xcc,1) + i2_l = LBOUND(SrcOtherStateData%xcc,2) + i2_u = UBOUND(SrcOtherStateData%xcc,2) + IF (.NOT. ALLOCATED(DstOtherStateData%xcc)) THEN + ALLOCATE(DstOtherStateData%xcc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%xcc = SrcOtherStateData%xcc +ENDIF + DstOtherStateData%InitAcc = SrcOtherStateData%InitAcc + DstOtherStateData%RunQuasiStaticInit = SrcOtherStateData%RunQuasiStaticInit + END SUBROUTINE BD_CopyOtherState + + SUBROUTINE BD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(BD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%acc)) THEN + DEALLOCATE(OtherStateData%acc) +ENDIF +IF (ALLOCATED(OtherStateData%xcc)) THEN + DEALLOCATE(OtherStateData%xcc) +ENDIF + END SUBROUTINE BD_DestroyOtherState + + SUBROUTINE BD_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(BD_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 = 'BD_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 + Int_BufSz = Int_BufSz + 1 ! acc allocated yes/no + IF ( ALLOCATED(InData%acc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! acc upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%acc) ! acc + END IF + Int_BufSz = Int_BufSz + 1 ! xcc allocated yes/no + IF ( ALLOCATED(InData%xcc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! xcc upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%xcc) ! xcc + END IF + Int_BufSz = Int_BufSz + 1 ! InitAcc + Int_BufSz = Int_BufSz + 1 ! RunQuasiStaticInit + 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%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 + + DO i2 = LBOUND(InData%acc,2), UBOUND(InData%acc,2) + DO i1 = LBOUND(InData%acc,1), UBOUND(InData%acc,1) + DbKiBuf(Db_Xferred) = InData%acc(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%xcc) ) 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%xcc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xcc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xcc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xcc,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%xcc,2), UBOUND(InData%xcc,2) + DO i1 = LBOUND(InData%xcc,1), UBOUND(InData%xcc,1) + DbKiBuf(Db_Xferred) = InData%xcc(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%InitAcc, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RunQuasiStaticInit, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_PackOtherState + + SUBROUTINE BD_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(BD_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) :: 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 = 'BD_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 + 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 + IF (ALLOCATED(OutData%acc)) DEALLOCATE(OutData%acc) + ALLOCATE(OutData%acc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%acc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%acc,2), UBOUND(OutData%acc,2) + DO i1 = LBOUND(OutData%acc,1), UBOUND(OutData%acc,1) + OutData%acc(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xcc 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%xcc)) DEALLOCATE(OutData%xcc) + ALLOCATE(OutData%xcc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%xcc,2), UBOUND(OutData%xcc,2) + DO i1 = LBOUND(OutData%xcc,1), UBOUND(OutData%xcc,1) + OutData%xcc(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + OutData%InitAcc = TRANSFER(IntKiBuf(Int_Xferred), OutData%InitAcc) + Int_Xferred = Int_Xferred + 1 + OutData%RunQuasiStaticInit = TRANSFER(IntKiBuf(Int_Xferred), OutData%RunQuasiStaticInit) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_UnPackOtherState + + SUBROUTINE BD_CopyqpParam( SrcqpParamData, DstqpParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(qpParam), INTENT(IN) :: SrcqpParamData + TYPE(qpParam), INTENT(INOUT) :: DstqpParamData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CopyqpParam' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcqpParamData%mmm)) THEN + i1_l = LBOUND(SrcqpParamData%mmm,1) + i1_u = UBOUND(SrcqpParamData%mmm,1) + i2_l = LBOUND(SrcqpParamData%mmm,2) + i2_u = UBOUND(SrcqpParamData%mmm,2) + IF (.NOT. ALLOCATED(DstqpParamData%mmm)) THEN + ALLOCATE(DstqpParamData%mmm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstqpParamData%mmm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstqpParamData%mmm = SrcqpParamData%mmm +ENDIF +IF (ALLOCATED(SrcqpParamData%mEta)) THEN + i1_l = LBOUND(SrcqpParamData%mEta,1) + i1_u = UBOUND(SrcqpParamData%mEta,1) + i2_l = LBOUND(SrcqpParamData%mEta,2) + i2_u = UBOUND(SrcqpParamData%mEta,2) + i3_l = LBOUND(SrcqpParamData%mEta,3) + i3_u = UBOUND(SrcqpParamData%mEta,3) + IF (.NOT. ALLOCATED(DstqpParamData%mEta)) THEN + ALLOCATE(DstqpParamData%mEta(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstqpParamData%mEta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstqpParamData%mEta = SrcqpParamData%mEta +ENDIF + END SUBROUTINE BD_CopyqpParam + + SUBROUTINE BD_DestroyqpParam( qpParamData, ErrStat, ErrMsg ) + TYPE(qpParam), INTENT(INOUT) :: qpParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyqpParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(qpParamData%mmm)) THEN + DEALLOCATE(qpParamData%mmm) +ENDIF +IF (ALLOCATED(qpParamData%mEta)) THEN + DEALLOCATE(qpParamData%mEta) +ENDIF + END SUBROUTINE BD_DestroyqpParam + + SUBROUTINE BD_PackqpParam( 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(qpParam), 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 = 'BD_PackqpParam' + ! 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 ! mmm allocated yes/no + IF ( ALLOCATED(InData%mmm) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! mmm upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%mmm) ! mmm + END IF + Int_BufSz = Int_BufSz + 1 ! mEta allocated yes/no + IF ( ALLOCATED(InData%mEta) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! mEta upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%mEta) ! mEta + 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%mmm) ) 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%mmm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mmm,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mmm,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mmm,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%mmm,2), UBOUND(InData%mmm,2) + DO i1 = LBOUND(InData%mmm,1), UBOUND(InData%mmm,1) + DbKiBuf(Db_Xferred) = InData%mmm(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%mEta) ) 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%mEta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mEta,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mEta,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mEta,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mEta,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mEta,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%mEta,3), UBOUND(InData%mEta,3) + DO i2 = LBOUND(InData%mEta,2), UBOUND(InData%mEta,2) + DO i1 = LBOUND(InData%mEta,1), UBOUND(InData%mEta,1) + DbKiBuf(Db_Xferred) = InData%mEta(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE BD_PackqpParam + + SUBROUTINE BD_UnPackqpParam( 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(qpParam), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_UnPackqpParam' + ! 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 ! mmm 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%mmm)) DEALLOCATE(OutData%mmm) + ALLOCATE(OutData%mmm(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%mmm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%mmm,2), UBOUND(OutData%mmm,2) + DO i1 = LBOUND(OutData%mmm,1), UBOUND(OutData%mmm,1) + OutData%mmm(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! mEta 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%mEta)) DEALLOCATE(OutData%mEta) + ALLOCATE(OutData%mEta(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%mEta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%mEta,3), UBOUND(OutData%mEta,3) + DO i2 = LBOUND(OutData%mEta,2), UBOUND(OutData%mEta,2) + DO i1 = LBOUND(OutData%mEta,1), UBOUND(OutData%mEta,1) + OutData%mEta(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE BD_UnPackqpParam + + SUBROUTINE BD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(BD_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 = 'BD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%dt = SrcParamData%dt + DstParamData%coef = SrcParamData%coef + DstParamData%rhoinf = SrcParamData%rhoinf +IF (ALLOCATED(SrcParamData%uuN0)) THEN + i1_l = LBOUND(SrcParamData%uuN0,1) + i1_u = UBOUND(SrcParamData%uuN0,1) + i2_l = LBOUND(SrcParamData%uuN0,2) + i2_u = UBOUND(SrcParamData%uuN0,2) + i3_l = LBOUND(SrcParamData%uuN0,3) + i3_u = UBOUND(SrcParamData%uuN0,3) + IF (.NOT. ALLOCATED(DstParamData%uuN0)) THEN + ALLOCATE(DstParamData%uuN0(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%uuN0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%uuN0 = SrcParamData%uuN0 +ENDIF +IF (ALLOCATED(SrcParamData%Stif0_QP)) THEN + i1_l = LBOUND(SrcParamData%Stif0_QP,1) + i1_u = UBOUND(SrcParamData%Stif0_QP,1) + i2_l = LBOUND(SrcParamData%Stif0_QP,2) + i2_u = UBOUND(SrcParamData%Stif0_QP,2) + i3_l = LBOUND(SrcParamData%Stif0_QP,3) + i3_u = UBOUND(SrcParamData%Stif0_QP,3) + IF (.NOT. ALLOCATED(DstParamData%Stif0_QP)) THEN + ALLOCATE(DstParamData%Stif0_QP(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%Stif0_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Stif0_QP = SrcParamData%Stif0_QP +ENDIF +IF (ALLOCATED(SrcParamData%Mass0_QP)) THEN + i1_l = LBOUND(SrcParamData%Mass0_QP,1) + i1_u = UBOUND(SrcParamData%Mass0_QP,1) + i2_l = LBOUND(SrcParamData%Mass0_QP,2) + i2_u = UBOUND(SrcParamData%Mass0_QP,2) + i3_l = LBOUND(SrcParamData%Mass0_QP,3) + i3_u = UBOUND(SrcParamData%Mass0_QP,3) + IF (.NOT. ALLOCATED(DstParamData%Mass0_QP)) THEN + ALLOCATE(DstParamData%Mass0_QP(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%Mass0_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Mass0_QP = SrcParamData%Mass0_QP +ENDIF + DstParamData%gravity = SrcParamData%gravity +IF (ALLOCATED(SrcParamData%segment_eta)) THEN + i1_l = LBOUND(SrcParamData%segment_eta,1) + i1_u = UBOUND(SrcParamData%segment_eta,1) + IF (.NOT. ALLOCATED(DstParamData%segment_eta)) THEN + ALLOCATE(DstParamData%segment_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%segment_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%segment_eta = SrcParamData%segment_eta +ENDIF +IF (ALLOCATED(SrcParamData%member_eta)) THEN + i1_l = LBOUND(SrcParamData%member_eta,1) + i1_u = UBOUND(SrcParamData%member_eta,1) + IF (.NOT. ALLOCATED(DstParamData%member_eta)) THEN + ALLOCATE(DstParamData%member_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%member_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%member_eta = SrcParamData%member_eta +ENDIF + DstParamData%blade_length = SrcParamData%blade_length + DstParamData%blade_mass = SrcParamData%blade_mass + DstParamData%blade_CG = SrcParamData%blade_CG + DstParamData%blade_IN = SrcParamData%blade_IN + DstParamData%beta = SrcParamData%beta + DstParamData%tol = SrcParamData%tol + DstParamData%GlbPos = SrcParamData%GlbPos + DstParamData%GlbRot = SrcParamData%GlbRot + DstParamData%Glb_crv = SrcParamData%Glb_crv +IF (ALLOCATED(SrcParamData%QPtN)) THEN + i1_l = LBOUND(SrcParamData%QPtN,1) + i1_u = UBOUND(SrcParamData%QPtN,1) + IF (.NOT. ALLOCATED(DstParamData%QPtN)) THEN + ALLOCATE(DstParamData%QPtN(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%QPtN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtN = SrcParamData%QPtN +ENDIF +IF (ALLOCATED(SrcParamData%QPtWeight)) THEN + i1_l = LBOUND(SrcParamData%QPtWeight,1) + i1_u = UBOUND(SrcParamData%QPtWeight,1) + IF (.NOT. ALLOCATED(DstParamData%QPtWeight)) THEN + ALLOCATE(DstParamData%QPtWeight(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%QPtWeight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtWeight = SrcParamData%QPtWeight +ENDIF +IF (ALLOCATED(SrcParamData%Shp)) THEN + i1_l = LBOUND(SrcParamData%Shp,1) + i1_u = UBOUND(SrcParamData%Shp,1) + i2_l = LBOUND(SrcParamData%Shp,2) + i2_u = UBOUND(SrcParamData%Shp,2) + IF (.NOT. ALLOCATED(DstParamData%Shp)) THEN + ALLOCATE(DstParamData%Shp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Shp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Shp = SrcParamData%Shp +ENDIF +IF (ALLOCATED(SrcParamData%ShpDer)) THEN + i1_l = LBOUND(SrcParamData%ShpDer,1) + i1_u = UBOUND(SrcParamData%ShpDer,1) + i2_l = LBOUND(SrcParamData%ShpDer,2) + i2_u = UBOUND(SrcParamData%ShpDer,2) + IF (.NOT. ALLOCATED(DstParamData%ShpDer)) THEN + ALLOCATE(DstParamData%ShpDer(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ShpDer = SrcParamData%ShpDer +ENDIF +IF (ALLOCATED(SrcParamData%Jacobian)) THEN + i1_l = LBOUND(SrcParamData%Jacobian,1) + i1_u = UBOUND(SrcParamData%Jacobian,1) + i2_l = LBOUND(SrcParamData%Jacobian,2) + i2_u = UBOUND(SrcParamData%Jacobian,2) + IF (.NOT. ALLOCATED(DstParamData%Jacobian)) THEN + ALLOCATE(DstParamData%Jacobian(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jacobian.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jacobian = SrcParamData%Jacobian +ENDIF +IF (ALLOCATED(SrcParamData%uu0)) THEN + i1_l = LBOUND(SrcParamData%uu0,1) + i1_u = UBOUND(SrcParamData%uu0,1) + i2_l = LBOUND(SrcParamData%uu0,2) + i2_u = UBOUND(SrcParamData%uu0,2) + i3_l = LBOUND(SrcParamData%uu0,3) + i3_u = UBOUND(SrcParamData%uu0,3) + IF (.NOT. ALLOCATED(DstParamData%uu0)) THEN + ALLOCATE(DstParamData%uu0(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%uu0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%uu0 = SrcParamData%uu0 +ENDIF +IF (ALLOCATED(SrcParamData%rrN0)) THEN + i1_l = LBOUND(SrcParamData%rrN0,1) + i1_u = UBOUND(SrcParamData%rrN0,1) + i2_l = LBOUND(SrcParamData%rrN0,2) + i2_u = UBOUND(SrcParamData%rrN0,2) + i3_l = LBOUND(SrcParamData%rrN0,3) + i3_u = UBOUND(SrcParamData%rrN0,3) + IF (.NOT. ALLOCATED(DstParamData%rrN0)) THEN + ALLOCATE(DstParamData%rrN0(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%rrN0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rrN0 = SrcParamData%rrN0 +ENDIF +IF (ALLOCATED(SrcParamData%E10)) THEN + i1_l = LBOUND(SrcParamData%E10,1) + i1_u = UBOUND(SrcParamData%E10,1) + i2_l = LBOUND(SrcParamData%E10,2) + i2_u = UBOUND(SrcParamData%E10,2) + i3_l = LBOUND(SrcParamData%E10,3) + i3_u = UBOUND(SrcParamData%E10,3) + IF (.NOT. ALLOCATED(DstParamData%E10)) THEN + ALLOCATE(DstParamData%E10(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%E10.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%E10 = SrcParamData%E10 +ENDIF + DstParamData%nodes_per_elem = SrcParamData%nodes_per_elem +IF (ALLOCATED(SrcParamData%node_elem_idx)) THEN + i1_l = LBOUND(SrcParamData%node_elem_idx,1) + i1_u = UBOUND(SrcParamData%node_elem_idx,1) + i2_l = LBOUND(SrcParamData%node_elem_idx,2) + i2_u = UBOUND(SrcParamData%node_elem_idx,2) + IF (.NOT. ALLOCATED(DstParamData%node_elem_idx)) THEN + ALLOCATE(DstParamData%node_elem_idx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%node_elem_idx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%node_elem_idx = SrcParamData%node_elem_idx +ENDIF + DstParamData%refine = SrcParamData%refine + DstParamData%dof_node = SrcParamData%dof_node + DstParamData%dof_elem = SrcParamData%dof_elem + DstParamData%rot_elem = SrcParamData%rot_elem + DstParamData%elem_total = SrcParamData%elem_total + DstParamData%node_total = SrcParamData%node_total + DstParamData%dof_total = SrcParamData%dof_total + DstParamData%nqp = SrcParamData%nqp + DstParamData%analysis_type = SrcParamData%analysis_type + DstParamData%damp_flag = SrcParamData%damp_flag + DstParamData%ld_retries = SrcParamData%ld_retries + DstParamData%niter = SrcParamData%niter + DstParamData%quadrature = SrcParamData%quadrature + DstParamData%n_fact = SrcParamData%n_fact + DstParamData%OutInputs = SrcParamData%OutInputs + DstParamData%NumOuts = SrcParamData%NumOuts +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NNodeOuts = SrcParamData%NNodeOuts + DstParamData%OutNd = SrcParamData%OutNd +IF (ALLOCATED(SrcParamData%NdIndx)) THEN + i1_l = LBOUND(SrcParamData%NdIndx,1) + i1_u = UBOUND(SrcParamData%NdIndx,1) + IF (.NOT. ALLOCATED(DstParamData%NdIndx)) THEN + ALLOCATE(DstParamData%NdIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NdIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NdIndx = SrcParamData%NdIndx +ENDIF +IF (ALLOCATED(SrcParamData%NdIndxInverse)) THEN + i1_l = LBOUND(SrcParamData%NdIndxInverse,1) + i1_u = UBOUND(SrcParamData%NdIndxInverse,1) + IF (.NOT. ALLOCATED(DstParamData%NdIndxInverse)) THEN + ALLOCATE(DstParamData%NdIndxInverse(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NdIndxInverse.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NdIndxInverse = SrcParamData%NdIndxInverse +ENDIF +IF (ALLOCATED(SrcParamData%OutNd2NdElem)) THEN + i1_l = LBOUND(SrcParamData%OutNd2NdElem,1) + i1_u = UBOUND(SrcParamData%OutNd2NdElem,1) + i2_l = LBOUND(SrcParamData%OutNd2NdElem,2) + i2_u = UBOUND(SrcParamData%OutNd2NdElem,2) + IF (.NOT. ALLOCATED(DstParamData%OutNd2NdElem)) THEN + ALLOCATE(DstParamData%OutNd2NdElem(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutNd2NdElem.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%OutNd2NdElem = SrcParamData%OutNd2NdElem +ENDIF + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%UsePitchAct = SrcParamData%UsePitchAct + DstParamData%pitchJ = SrcParamData%pitchJ + DstParamData%pitchK = SrcParamData%pitchK + DstParamData%pitchC = SrcParamData%pitchC + DstParamData%torqM = SrcParamData%torqM + CALL BD_Copyqpparam( SrcParamData%qp, DstParamData%qp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%qp_indx_offset = SrcParamData%qp_indx_offset + DstParamData%BldMotionNodeLoc = SrcParamData%BldMotionNodeLoc + DstParamData%tngt_stf_fd = SrcParamData%tngt_stf_fd + DstParamData%tngt_stf_comp = SrcParamData%tngt_stf_comp + DstParamData%tngt_stf_pert = SrcParamData%tngt_stf_pert + DstParamData%tngt_stf_difftol = SrcParamData%tngt_stf_difftol + DstParamData%BldNd_NumOuts = SrcParamData%BldNd_NumOuts + DstParamData%BldNd_TotNumOuts = SrcParamData%BldNd_TotNumOuts +IF (ALLOCATED(SrcParamData%BldNd_OutParam)) THEN + i1_l = LBOUND(SrcParamData%BldNd_OutParam,1) + i1_u = UBOUND(SrcParamData%BldNd_OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%BldNd_OutParam)) THEN + ALLOCATE(DstParamData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%BldNd_OutParam,1), UBOUND(SrcParamData%BldNd_OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%BldNd_OutParam(i1), DstParamData%BldNd_OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%BldNd_BlOutNd)) THEN + i1_l = LBOUND(SrcParamData%BldNd_BlOutNd,1) + i1_u = UBOUND(SrcParamData%BldNd_BlOutNd,1) + IF (.NOT. ALLOCATED(DstParamData%BldNd_BlOutNd)) THEN + ALLOCATE(DstParamData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldNd_BlOutNd = SrcParamData%BldNd_BlOutNd +ENDIF +IF (ALLOCATED(SrcParamData%QPtw_Shp_Shp_Jac)) THEN + i1_l = LBOUND(SrcParamData%QPtw_Shp_Shp_Jac,1) + i1_u = UBOUND(SrcParamData%QPtw_Shp_Shp_Jac,1) + i2_l = LBOUND(SrcParamData%QPtw_Shp_Shp_Jac,2) + i2_u = UBOUND(SrcParamData%QPtw_Shp_Shp_Jac,2) + i3_l = LBOUND(SrcParamData%QPtw_Shp_Shp_Jac,3) + i3_u = UBOUND(SrcParamData%QPtw_Shp_Shp_Jac,3) + i4_l = LBOUND(SrcParamData%QPtw_Shp_Shp_Jac,4) + i4_u = UBOUND(SrcParamData%QPtw_Shp_Shp_Jac,4) + IF (.NOT. ALLOCATED(DstParamData%QPtw_Shp_Shp_Jac)) THEN + ALLOCATE(DstParamData%QPtw_Shp_Shp_Jac(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%QPtw_Shp_Shp_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtw_Shp_Shp_Jac = SrcParamData%QPtw_Shp_Shp_Jac +ENDIF +IF (ALLOCATED(SrcParamData%QPtw_Shp_ShpDer)) THEN + i1_l = LBOUND(SrcParamData%QPtw_Shp_ShpDer,1) + i1_u = UBOUND(SrcParamData%QPtw_Shp_ShpDer,1) + i2_l = LBOUND(SrcParamData%QPtw_Shp_ShpDer,2) + i2_u = UBOUND(SrcParamData%QPtw_Shp_ShpDer,2) + i3_l = LBOUND(SrcParamData%QPtw_Shp_ShpDer,3) + i3_u = UBOUND(SrcParamData%QPtw_Shp_ShpDer,3) + IF (.NOT. ALLOCATED(DstParamData%QPtw_Shp_ShpDer)) THEN + ALLOCATE(DstParamData%QPtw_Shp_ShpDer(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%QPtw_Shp_ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtw_Shp_ShpDer = SrcParamData%QPtw_Shp_ShpDer +ENDIF +IF (ALLOCATED(SrcParamData%QPtw_ShpDer_ShpDer_Jac)) THEN + i1_l = LBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,1) + i1_u = UBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,1) + i2_l = LBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,2) + i2_u = UBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,2) + i3_l = LBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,3) + i3_u = UBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,3) + i4_l = LBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,4) + i4_u = UBOUND(SrcParamData%QPtw_ShpDer_ShpDer_Jac,4) + IF (.NOT. ALLOCATED(DstParamData%QPtw_ShpDer_ShpDer_Jac)) THEN + ALLOCATE(DstParamData%QPtw_ShpDer_ShpDer_Jac(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%QPtw_ShpDer_ShpDer_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtw_ShpDer_ShpDer_Jac = SrcParamData%QPtw_ShpDer_ShpDer_Jac +ENDIF +IF (ALLOCATED(SrcParamData%QPtw_Shp_Jac)) THEN + i1_l = LBOUND(SrcParamData%QPtw_Shp_Jac,1) + i1_u = UBOUND(SrcParamData%QPtw_Shp_Jac,1) + i2_l = LBOUND(SrcParamData%QPtw_Shp_Jac,2) + i2_u = UBOUND(SrcParamData%QPtw_Shp_Jac,2) + i3_l = LBOUND(SrcParamData%QPtw_Shp_Jac,3) + i3_u = UBOUND(SrcParamData%QPtw_Shp_Jac,3) + IF (.NOT. ALLOCATED(DstParamData%QPtw_Shp_Jac)) THEN + ALLOCATE(DstParamData%QPtw_Shp_Jac(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%QPtw_Shp_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtw_Shp_Jac = SrcParamData%QPtw_Shp_Jac +ENDIF +IF (ALLOCATED(SrcParamData%QPtw_ShpDer)) THEN + i1_l = LBOUND(SrcParamData%QPtw_ShpDer,1) + i1_u = UBOUND(SrcParamData%QPtw_ShpDer,1) + i2_l = LBOUND(SrcParamData%QPtw_ShpDer,2) + i2_u = UBOUND(SrcParamData%QPtw_ShpDer,2) + IF (.NOT. ALLOCATED(DstParamData%QPtw_ShpDer)) THEN + ALLOCATE(DstParamData%QPtw_ShpDer(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%QPtw_ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%QPtw_ShpDer = SrcParamData%QPtw_ShpDer +ENDIF +IF (ALLOCATED(SrcParamData%FEweight)) THEN + i1_l = LBOUND(SrcParamData%FEweight,1) + i1_u = UBOUND(SrcParamData%FEweight,1) + i2_l = LBOUND(SrcParamData%FEweight,2) + i2_u = UBOUND(SrcParamData%FEweight,2) + IF (.NOT. ALLOCATED(DstParamData%FEweight)) THEN + ALLOCATE(DstParamData%FEweight(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FEweight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FEweight = SrcParamData%FEweight +ENDIF +IF (ALLOCATED(SrcParamData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcParamData%Jac_u_indx,1) + i1_u = UBOUND(SrcParamData%Jac_u_indx,1) + i2_l = LBOUND(SrcParamData%Jac_u_indx,2) + i2_u = UBOUND(SrcParamData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstParamData%Jac_u_indx)) THEN + ALLOCATE(DstParamData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jac_u_indx = SrcParamData%Jac_u_indx +ENDIF +IF (ALLOCATED(SrcParamData%du)) THEN + i1_l = LBOUND(SrcParamData%du,1) + i1_u = UBOUND(SrcParamData%du,1) + IF (.NOT. ALLOCATED(DstParamData%du)) THEN + ALLOCATE(DstParamData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%du = SrcParamData%du +ENDIF + DstParamData%dx = SrcParamData%dx + DstParamData%Jac_ny = SrcParamData%Jac_ny + DstParamData%Jac_nx = SrcParamData%Jac_nx + DstParamData%RotStates = SrcParamData%RotStates + DstParamData%RelStates = SrcParamData%RelStates + END SUBROUTINE BD_CopyParam + + SUBROUTINE BD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(BD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%uuN0)) THEN + DEALLOCATE(ParamData%uuN0) +ENDIF +IF (ALLOCATED(ParamData%Stif0_QP)) THEN + DEALLOCATE(ParamData%Stif0_QP) +ENDIF +IF (ALLOCATED(ParamData%Mass0_QP)) THEN + DEALLOCATE(ParamData%Mass0_QP) +ENDIF +IF (ALLOCATED(ParamData%segment_eta)) THEN + DEALLOCATE(ParamData%segment_eta) +ENDIF +IF (ALLOCATED(ParamData%member_eta)) THEN + DEALLOCATE(ParamData%member_eta) +ENDIF +IF (ALLOCATED(ParamData%QPtN)) THEN + DEALLOCATE(ParamData%QPtN) +ENDIF +IF (ALLOCATED(ParamData%QPtWeight)) THEN + DEALLOCATE(ParamData%QPtWeight) +ENDIF +IF (ALLOCATED(ParamData%Shp)) THEN + DEALLOCATE(ParamData%Shp) +ENDIF +IF (ALLOCATED(ParamData%ShpDer)) THEN + DEALLOCATE(ParamData%ShpDer) +ENDIF +IF (ALLOCATED(ParamData%Jacobian)) THEN + DEALLOCATE(ParamData%Jacobian) +ENDIF +IF (ALLOCATED(ParamData%uu0)) THEN + DEALLOCATE(ParamData%uu0) +ENDIF +IF (ALLOCATED(ParamData%rrN0)) THEN + DEALLOCATE(ParamData%rrN0) +ENDIF +IF (ALLOCATED(ParamData%E10)) THEN + DEALLOCATE(ParamData%E10) +ENDIF +IF (ALLOCATED(ParamData%node_elem_idx)) THEN + DEALLOCATE(ParamData%node_elem_idx) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%NdIndx)) THEN + DEALLOCATE(ParamData%NdIndx) +ENDIF +IF (ALLOCATED(ParamData%NdIndxInverse)) THEN + DEALLOCATE(ParamData%NdIndxInverse) +ENDIF +IF (ALLOCATED(ParamData%OutNd2NdElem)) THEN + DEALLOCATE(ParamData%OutNd2NdElem) +ENDIF + CALL BD_Destroyqpparam( ParamData%qp, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%BldNd_OutParam)) THEN +DO i1 = LBOUND(ParamData%BldNd_OutParam,1), UBOUND(ParamData%BldNd_OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%BldNd_OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%BldNd_OutParam) +ENDIF +IF (ALLOCATED(ParamData%BldNd_BlOutNd)) THEN + DEALLOCATE(ParamData%BldNd_BlOutNd) +ENDIF +IF (ALLOCATED(ParamData%QPtw_Shp_Shp_Jac)) THEN + DEALLOCATE(ParamData%QPtw_Shp_Shp_Jac) +ENDIF +IF (ALLOCATED(ParamData%QPtw_Shp_ShpDer)) THEN + DEALLOCATE(ParamData%QPtw_Shp_ShpDer) +ENDIF +IF (ALLOCATED(ParamData%QPtw_ShpDer_ShpDer_Jac)) THEN + DEALLOCATE(ParamData%QPtw_ShpDer_ShpDer_Jac) +ENDIF +IF (ALLOCATED(ParamData%QPtw_Shp_Jac)) THEN + DEALLOCATE(ParamData%QPtw_Shp_Jac) +ENDIF +IF (ALLOCATED(ParamData%QPtw_ShpDer)) THEN + DEALLOCATE(ParamData%QPtw_ShpDer) +ENDIF +IF (ALLOCATED(ParamData%FEweight)) THEN + DEALLOCATE(ParamData%FEweight) +ENDIF +IF (ALLOCATED(ParamData%Jac_u_indx)) THEN + DEALLOCATE(ParamData%Jac_u_indx) +ENDIF +IF (ALLOCATED(ParamData%du)) THEN + DEALLOCATE(ParamData%du) +ENDIF + END SUBROUTINE BD_DestroyParam + + SUBROUTINE BD_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(BD_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 = 'BD_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 + Db_BufSz = Db_BufSz + 1 ! dt + Db_BufSz = Db_BufSz + SIZE(InData%coef) ! coef + Db_BufSz = Db_BufSz + 1 ! rhoinf + Int_BufSz = Int_BufSz + 1 ! uuN0 allocated yes/no + IF ( ALLOCATED(InData%uuN0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! uuN0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%uuN0) ! uuN0 + END IF + Int_BufSz = Int_BufSz + 1 ! Stif0_QP allocated yes/no + IF ( ALLOCATED(InData%Stif0_QP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Stif0_QP upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Stif0_QP) ! Stif0_QP + END IF + Int_BufSz = Int_BufSz + 1 ! Mass0_QP allocated yes/no + IF ( ALLOCATED(InData%Mass0_QP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Mass0_QP upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Mass0_QP) ! Mass0_QP + END IF + Db_BufSz = Db_BufSz + SIZE(InData%gravity) ! gravity + Int_BufSz = Int_BufSz + 1 ! segment_eta allocated yes/no + IF ( ALLOCATED(InData%segment_eta) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! segment_eta upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%segment_eta) ! segment_eta + END IF + Int_BufSz = Int_BufSz + 1 ! member_eta allocated yes/no + IF ( ALLOCATED(InData%member_eta) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! member_eta upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%member_eta) ! member_eta + END IF + Db_BufSz = Db_BufSz + 1 ! blade_length + Db_BufSz = Db_BufSz + 1 ! blade_mass + Db_BufSz = Db_BufSz + SIZE(InData%blade_CG) ! blade_CG + Db_BufSz = Db_BufSz + SIZE(InData%blade_IN) ! blade_IN + Db_BufSz = Db_BufSz + SIZE(InData%beta) ! beta + Db_BufSz = Db_BufSz + 1 ! tol + Db_BufSz = Db_BufSz + SIZE(InData%GlbPos) ! GlbPos + Db_BufSz = Db_BufSz + SIZE(InData%GlbRot) ! GlbRot + Db_BufSz = Db_BufSz + SIZE(InData%Glb_crv) ! Glb_crv + Int_BufSz = Int_BufSz + 1 ! QPtN allocated yes/no + IF ( ALLOCATED(InData%QPtN) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! QPtN upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtN) ! QPtN + END IF + Int_BufSz = Int_BufSz + 1 ! QPtWeight allocated yes/no + IF ( ALLOCATED(InData%QPtWeight) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! QPtWeight upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtWeight) ! QPtWeight + END IF + Int_BufSz = Int_BufSz + 1 ! Shp allocated yes/no + IF ( ALLOCATED(InData%Shp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Shp upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Shp) ! Shp + END IF + Int_BufSz = Int_BufSz + 1 ! ShpDer allocated yes/no + IF ( ALLOCATED(InData%ShpDer) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ShpDer upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%ShpDer) ! ShpDer + END IF + Int_BufSz = Int_BufSz + 1 ! Jacobian allocated yes/no + IF ( ALLOCATED(InData%Jacobian) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jacobian upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Jacobian) ! Jacobian + END IF + Int_BufSz = Int_BufSz + 1 ! uu0 allocated yes/no + IF ( ALLOCATED(InData%uu0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! uu0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%uu0) ! uu0 + END IF + Int_BufSz = Int_BufSz + 1 ! rrN0 allocated yes/no + IF ( ALLOCATED(InData%rrN0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rrN0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rrN0) ! rrN0 + END IF + Int_BufSz = Int_BufSz + 1 ! E10 allocated yes/no + IF ( ALLOCATED(InData%E10) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! E10 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%E10) ! E10 + END IF + Int_BufSz = Int_BufSz + 1 ! nodes_per_elem + Int_BufSz = Int_BufSz + 1 ! node_elem_idx allocated yes/no + IF ( ALLOCATED(InData%node_elem_idx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! node_elem_idx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%node_elem_idx) ! node_elem_idx + END IF + Int_BufSz = Int_BufSz + 1 ! refine + Int_BufSz = Int_BufSz + 1 ! dof_node + Int_BufSz = Int_BufSz + 1 ! dof_elem + Int_BufSz = Int_BufSz + 1 ! rot_elem + Int_BufSz = Int_BufSz + 1 ! elem_total + Int_BufSz = Int_BufSz + 1 ! node_total + Int_BufSz = Int_BufSz + 1 ! dof_total + Int_BufSz = Int_BufSz + 1 ! nqp + Int_BufSz = Int_BufSz + 1 ! analysis_type + Int_BufSz = Int_BufSz + 1 ! damp_flag + Int_BufSz = Int_BufSz + 1 ! ld_retries + Int_BufSz = Int_BufSz + 1 ! niter + Int_BufSz = Int_BufSz + 1 ! quadrature + Int_BufSz = Int_BufSz + 1 ! n_fact + Int_BufSz = Int_BufSz + 1 ! OutInputs + Int_BufSz = Int_BufSz + 1 ! NumOuts + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NNodeOuts + Int_BufSz = Int_BufSz + SIZE(InData%OutNd) ! OutNd + Int_BufSz = Int_BufSz + 1 ! NdIndx allocated yes/no + IF ( ALLOCATED(InData%NdIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NdIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NdIndx) ! NdIndx + END IF + Int_BufSz = Int_BufSz + 1 ! NdIndxInverse allocated yes/no + IF ( ALLOCATED(InData%NdIndxInverse) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NdIndxInverse upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NdIndxInverse) ! NdIndxInverse + END IF + Int_BufSz = Int_BufSz + 1 ! OutNd2NdElem allocated yes/no + IF ( ALLOCATED(InData%OutNd2NdElem) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OutNd2NdElem upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutNd2NdElem) ! OutNd2NdElem + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1 ! UsePitchAct + Re_BufSz = Re_BufSz + 1 ! pitchJ + Re_BufSz = Re_BufSz + 1 ! pitchK + Re_BufSz = Re_BufSz + 1 ! pitchC + Re_BufSz = Re_BufSz + SIZE(InData%torqM) ! torqM + Int_BufSz = Int_BufSz + 3 ! qp: size of buffers for each call to pack subtype + CALL BD_Packqpparam( Re_Buf, Db_Buf, Int_Buf, InData%qp, ErrStat2, ErrMsg2, .TRUE. ) ! qp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! qp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! qp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! qp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! qp_indx_offset + Int_BufSz = Int_BufSz + 1 ! BldMotionNodeLoc + Int_BufSz = Int_BufSz + 1 ! tngt_stf_fd + Int_BufSz = Int_BufSz + 1 ! tngt_stf_comp + Db_BufSz = Db_BufSz + 1 ! tngt_stf_pert + Db_BufSz = Db_BufSz + 1 ! tngt_stf_difftol + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_TotNumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutParam allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutParam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutParam upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + Int_BufSz = Int_BufSz + 3 ! BldNd_OutParam: size of buffers for each call to pack subtype + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BldNd_OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BldNd_OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BldNd_OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BldNd_OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BldNd_BlOutNd allocated yes/no + IF ( ALLOCATED(InData%BldNd_BlOutNd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_BlOutNd upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_BlOutNd) ! BldNd_BlOutNd + END IF + Int_BufSz = Int_BufSz + 1 ! QPtw_Shp_Shp_Jac allocated yes/no + IF ( ALLOCATED(InData%QPtw_Shp_Shp_Jac) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! QPtw_Shp_Shp_Jac upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtw_Shp_Shp_Jac) ! QPtw_Shp_Shp_Jac + END IF + Int_BufSz = Int_BufSz + 1 ! QPtw_Shp_ShpDer allocated yes/no + IF ( ALLOCATED(InData%QPtw_Shp_ShpDer) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! QPtw_Shp_ShpDer upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtw_Shp_ShpDer) ! QPtw_Shp_ShpDer + END IF + Int_BufSz = Int_BufSz + 1 ! QPtw_ShpDer_ShpDer_Jac allocated yes/no + IF ( ALLOCATED(InData%QPtw_ShpDer_ShpDer_Jac) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! QPtw_ShpDer_ShpDer_Jac upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtw_ShpDer_ShpDer_Jac) ! QPtw_ShpDer_ShpDer_Jac + END IF + Int_BufSz = Int_BufSz + 1 ! QPtw_Shp_Jac allocated yes/no + IF ( ALLOCATED(InData%QPtw_Shp_Jac) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! QPtw_Shp_Jac upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtw_Shp_Jac) ! QPtw_Shp_Jac + END IF + Int_BufSz = Int_BufSz + 1 ! QPtw_ShpDer allocated yes/no + IF ( ALLOCATED(InData%QPtw_ShpDer) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! QPtw_ShpDer upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QPtw_ShpDer) ! QPtw_ShpDer + END IF + Int_BufSz = Int_BufSz + 1 ! FEweight allocated yes/no + IF ( ALLOCATED(InData%FEweight) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FEweight upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%FEweight) ! FEweight + END IF + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 1 ! du allocated yes/no + IF ( ALLOCATED(InData%du) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! du upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%du) ! du + END IF + Db_BufSz = Db_BufSz + SIZE(InData%dx) ! dx + Int_BufSz = Int_BufSz + 1 ! Jac_ny + Int_BufSz = Int_BufSz + 1 ! Jac_nx + Int_BufSz = Int_BufSz + 1 ! RotStates + Int_BufSz = Int_BufSz + 1 ! RelStates + 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 + + DbKiBuf(Db_Xferred) = InData%dt + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%coef,1), UBOUND(InData%coef,1) + DbKiBuf(Db_Xferred) = InData%coef(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%rhoinf + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%uuN0) ) 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%uuN0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuN0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uuN0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuN0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uuN0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuN0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%uuN0,3), UBOUND(InData%uuN0,3) + DO i2 = LBOUND(InData%uuN0,2), UBOUND(InData%uuN0,2) + DO i1 = LBOUND(InData%uuN0,1), UBOUND(InData%uuN0,1) + DbKiBuf(Db_Xferred) = InData%uuN0(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Stif0_QP) ) 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%Stif0_QP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif0_QP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stif0_QP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif0_QP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stif0_QP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif0_QP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Stif0_QP,3), UBOUND(InData%Stif0_QP,3) + DO i2 = LBOUND(InData%Stif0_QP,2), UBOUND(InData%Stif0_QP,2) + DO i1 = LBOUND(InData%Stif0_QP,1), UBOUND(InData%Stif0_QP,1) + DbKiBuf(Db_Xferred) = InData%Stif0_QP(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Mass0_QP) ) 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%Mass0_QP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass0_QP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mass0_QP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass0_QP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mass0_QP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass0_QP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Mass0_QP,3), UBOUND(InData%Mass0_QP,3) + DO i2 = LBOUND(InData%Mass0_QP,2), UBOUND(InData%Mass0_QP,2) + DO i1 = LBOUND(InData%Mass0_QP,1), UBOUND(InData%Mass0_QP,1) + DbKiBuf(Db_Xferred) = InData%Mass0_QP(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%gravity,1), UBOUND(InData%gravity,1) + DbKiBuf(Db_Xferred) = InData%gravity(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%segment_eta) ) 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%segment_eta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%segment_eta,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%segment_eta,1), UBOUND(InData%segment_eta,1) + DbKiBuf(Db_Xferred) = InData%segment_eta(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%member_eta) ) 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%member_eta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%member_eta,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%member_eta,1), UBOUND(InData%member_eta,1) + DbKiBuf(Db_Xferred) = InData%member_eta(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%blade_length + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%blade_mass + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%blade_CG,1), UBOUND(InData%blade_CG,1) + DbKiBuf(Db_Xferred) = InData%blade_CG(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i2 = LBOUND(InData%blade_IN,2), UBOUND(InData%blade_IN,2) + DO i1 = LBOUND(InData%blade_IN,1), UBOUND(InData%blade_IN,1) + DbKiBuf(Db_Xferred) = InData%blade_IN(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%beta,1), UBOUND(InData%beta,1) + DbKiBuf(Db_Xferred) = InData%beta(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%tol + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%GlbPos,1), UBOUND(InData%GlbPos,1) + DbKiBuf(Db_Xferred) = InData%GlbPos(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i2 = LBOUND(InData%GlbRot,2), UBOUND(InData%GlbRot,2) + DO i1 = LBOUND(InData%GlbRot,1), UBOUND(InData%GlbRot,1) + DbKiBuf(Db_Xferred) = InData%GlbRot(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%Glb_crv,1), UBOUND(InData%Glb_crv,1) + DbKiBuf(Db_Xferred) = InData%Glb_crv(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%QPtN) ) 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%QPtN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtN,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%QPtN,1), UBOUND(InData%QPtN,1) + DbKiBuf(Db_Xferred) = InData%QPtN(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtWeight) ) 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%QPtWeight,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtWeight,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%QPtWeight,1), UBOUND(InData%QPtWeight,1) + DbKiBuf(Db_Xferred) = InData%QPtWeight(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Shp) ) 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%Shp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Shp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Shp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Shp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Shp,2), UBOUND(InData%Shp,2) + DO i1 = LBOUND(InData%Shp,1), UBOUND(InData%Shp,1) + DbKiBuf(Db_Xferred) = InData%Shp(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ShpDer) ) 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%ShpDer,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShpDer,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ShpDer,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShpDer,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ShpDer,2), UBOUND(InData%ShpDer,2) + DO i1 = LBOUND(InData%ShpDer,1), UBOUND(InData%ShpDer,1) + DbKiBuf(Db_Xferred) = InData%ShpDer(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Jacobian) ) 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%Jacobian,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jacobian,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jacobian,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jacobian,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jacobian,2), UBOUND(InData%Jacobian,2) + DO i1 = LBOUND(InData%Jacobian,1), UBOUND(InData%Jacobian,1) + DbKiBuf(Db_Xferred) = InData%Jacobian(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%uu0) ) 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%uu0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uu0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uu0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uu0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uu0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uu0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%uu0,3), UBOUND(InData%uu0,3) + DO i2 = LBOUND(InData%uu0,2), UBOUND(InData%uu0,2) + DO i1 = LBOUND(InData%uu0,1), UBOUND(InData%uu0,1) + DbKiBuf(Db_Xferred) = InData%uu0(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rrN0) ) 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%rrN0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rrN0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rrN0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rrN0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rrN0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rrN0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rrN0,3), UBOUND(InData%rrN0,3) + DO i2 = LBOUND(InData%rrN0,2), UBOUND(InData%rrN0,2) + DO i1 = LBOUND(InData%rrN0,1), UBOUND(InData%rrN0,1) + DbKiBuf(Db_Xferred) = InData%rrN0(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%E10) ) 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%E10,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E10,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%E10,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E10,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%E10,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E10,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%E10,3), UBOUND(InData%E10,3) + DO i2 = LBOUND(InData%E10,2), UBOUND(InData%E10,2) + DO i1 = LBOUND(InData%E10,1), UBOUND(InData%E10,1) + DbKiBuf(Db_Xferred) = InData%E10(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%nodes_per_elem + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%node_elem_idx) ) 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%node_elem_idx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%node_elem_idx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%node_elem_idx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%node_elem_idx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%node_elem_idx,2), UBOUND(InData%node_elem_idx,2) + DO i1 = LBOUND(InData%node_elem_idx,1), UBOUND(InData%node_elem_idx,1) + IntKiBuf(Int_Xferred) = InData%node_elem_idx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%refine + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%dof_node + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%dof_elem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%rot_elem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%elem_total + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%node_total + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%dof_total + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nqp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%analysis_type + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%damp_flag + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ld_retries + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%niter + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%quadrature + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_fact + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutInputs, IntKiBuf(1)) + 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 + + 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 + IntKiBuf(Int_Xferred) = InData%NNodeOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%OutNd,1), UBOUND(InData%OutNd,1) + IntKiBuf(Int_Xferred) = InData%OutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%NdIndx) ) 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%NdIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NdIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NdIndx,1), UBOUND(InData%NdIndx,1) + IntKiBuf(Int_Xferred) = InData%NdIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NdIndxInverse) ) 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%NdIndxInverse,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NdIndxInverse,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NdIndxInverse,1), UBOUND(InData%NdIndxInverse,1) + IntKiBuf(Int_Xferred) = InData%NdIndxInverse(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OutNd2NdElem) ) 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%OutNd2NdElem,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutNd2NdElem,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutNd2NdElem,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutNd2NdElem,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OutNd2NdElem,2), UBOUND(InData%OutNd2NdElem,2) + DO i1 = LBOUND(InData%OutNd2NdElem,1), UBOUND(InData%OutNd2NdElem,1) + IntKiBuf(Int_Xferred) = InData%OutNd2NdElem(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%UsePitchAct, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%pitchJ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%pitchK + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%pitchC + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%torqM,2), UBOUND(InData%torqM,2) + DO i1 = LBOUND(InData%torqM,1), UBOUND(InData%torqM,1) + ReKiBuf(Re_Xferred) = InData%torqM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + CALL BD_Packqpparam( Re_Buf, Db_Buf, Int_Buf, InData%qp, ErrStat2, ErrMsg2, OnlySize ) ! qp + 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%qp_indx_offset + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldMotionNodeLoc + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%tngt_stf_fd, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%tngt_stf_comp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%tngt_stf_pert + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%tngt_stf_difftol + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_TotNumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_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%BldNd_OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! BldNd_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%BldNd_BlOutNd) ) 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%BldNd_BlOutNd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_BlOutNd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_BlOutNd,1), UBOUND(InData%BldNd_BlOutNd,1) + IntKiBuf(Int_Xferred) = InData%BldNd_BlOutNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtw_Shp_Shp_Jac) ) 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%QPtw_Shp_Shp_Jac,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Shp_Jac,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_Shp_Jac,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Shp_Jac,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_Shp_Jac,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Shp_Jac,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_Shp_Jac,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Shp_Jac,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%QPtw_Shp_Shp_Jac,4), UBOUND(InData%QPtw_Shp_Shp_Jac,4) + DO i3 = LBOUND(InData%QPtw_Shp_Shp_Jac,3), UBOUND(InData%QPtw_Shp_Shp_Jac,3) + DO i2 = LBOUND(InData%QPtw_Shp_Shp_Jac,2), UBOUND(InData%QPtw_Shp_Shp_Jac,2) + DO i1 = LBOUND(InData%QPtw_Shp_Shp_Jac,1), UBOUND(InData%QPtw_Shp_Shp_Jac,1) + DbKiBuf(Db_Xferred) = InData%QPtw_Shp_Shp_Jac(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtw_Shp_ShpDer) ) 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%QPtw_Shp_ShpDer,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_ShpDer,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_ShpDer,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_ShpDer,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_ShpDer,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_ShpDer,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%QPtw_Shp_ShpDer,3), UBOUND(InData%QPtw_Shp_ShpDer,3) + DO i2 = LBOUND(InData%QPtw_Shp_ShpDer,2), UBOUND(InData%QPtw_Shp_ShpDer,2) + DO i1 = LBOUND(InData%QPtw_Shp_ShpDer,1), UBOUND(InData%QPtw_Shp_ShpDer,1) + DbKiBuf(Db_Xferred) = InData%QPtw_Shp_ShpDer(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtw_ShpDer_ShpDer_Jac) ) 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%QPtw_ShpDer_ShpDer_Jac,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,4), UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,4) + DO i3 = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,3), UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,3) + DO i2 = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,2), UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,2) + DO i1 = LBOUND(InData%QPtw_ShpDer_ShpDer_Jac,1), UBOUND(InData%QPtw_ShpDer_ShpDer_Jac,1) + DbKiBuf(Db_Xferred) = InData%QPtw_ShpDer_ShpDer_Jac(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtw_Shp_Jac) ) 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%QPtw_Shp_Jac,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Jac,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_Jac,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Jac,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_Shp_Jac,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_Shp_Jac,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%QPtw_Shp_Jac,3), UBOUND(InData%QPtw_Shp_Jac,3) + DO i2 = LBOUND(InData%QPtw_Shp_Jac,2), UBOUND(InData%QPtw_Shp_Jac,2) + DO i1 = LBOUND(InData%QPtw_Shp_Jac,1), UBOUND(InData%QPtw_Shp_Jac,1) + DbKiBuf(Db_Xferred) = InData%QPtw_Shp_Jac(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QPtw_ShpDer) ) 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%QPtw_ShpDer,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%QPtw_ShpDer,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QPtw_ShpDer,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%QPtw_ShpDer,2), UBOUND(InData%QPtw_ShpDer,2) + DO i1 = LBOUND(InData%QPtw_ShpDer,1), UBOUND(InData%QPtw_ShpDer,1) + DbKiBuf(Db_Xferred) = InData%QPtw_ShpDer(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FEweight) ) 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%FEweight,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FEweight,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FEweight,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FEweight,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FEweight,2), UBOUND(InData%FEweight,2) + DO i1 = LBOUND(InData%FEweight,1), UBOUND(InData%FEweight,1) + DbKiBuf(Db_Xferred) = InData%FEweight(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%du) ) 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%du,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%du,1), UBOUND(InData%du,1) + DbKiBuf(Db_Xferred) = InData%du(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%dx,1), UBOUND(InData%dx,1) + DbKiBuf(Db_Xferred) = InData%dx(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Jac_nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotStates, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RelStates, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_PackParam + + SUBROUTINE BD_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(BD_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 = 'BD_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%dt = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%coef,1) + i1_u = UBOUND(OutData%coef,1) + DO i1 = LBOUND(OutData%coef,1), UBOUND(OutData%coef,1) + OutData%coef(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + OutData%rhoinf = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! uuN0 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%uuN0)) DEALLOCATE(OutData%uuN0) + ALLOCATE(OutData%uuN0(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%uuN0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%uuN0,3), UBOUND(OutData%uuN0,3) + DO i2 = LBOUND(OutData%uuN0,2), UBOUND(OutData%uuN0,2) + DO i1 = LBOUND(OutData%uuN0,1), UBOUND(OutData%uuN0,1) + OutData%uuN0(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Stif0_QP 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%Stif0_QP)) DEALLOCATE(OutData%Stif0_QP) + ALLOCATE(OutData%Stif0_QP(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%Stif0_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Stif0_QP,3), UBOUND(OutData%Stif0_QP,3) + DO i2 = LBOUND(OutData%Stif0_QP,2), UBOUND(OutData%Stif0_QP,2) + DO i1 = LBOUND(OutData%Stif0_QP,1), UBOUND(OutData%Stif0_QP,1) + OutData%Stif0_QP(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Mass0_QP 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%Mass0_QP)) DEALLOCATE(OutData%Mass0_QP) + ALLOCATE(OutData%Mass0_QP(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%Mass0_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Mass0_QP,3), UBOUND(OutData%Mass0_QP,3) + DO i2 = LBOUND(OutData%Mass0_QP,2), UBOUND(OutData%Mass0_QP,2) + DO i1 = LBOUND(OutData%Mass0_QP,1), UBOUND(OutData%Mass0_QP,1) + OutData%Mass0_QP(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%gravity,1) + i1_u = UBOUND(OutData%gravity,1) + DO i1 = LBOUND(OutData%gravity,1), UBOUND(OutData%gravity,1) + OutData%gravity(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! segment_eta 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%segment_eta)) DEALLOCATE(OutData%segment_eta) + ALLOCATE(OutData%segment_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%segment_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%segment_eta,1), UBOUND(OutData%segment_eta,1) + OutData%segment_eta(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! member_eta 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%member_eta)) DEALLOCATE(OutData%member_eta) + ALLOCATE(OutData%member_eta(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%member_eta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%member_eta,1), UBOUND(OutData%member_eta,1) + OutData%member_eta(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%blade_length = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%blade_mass = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%blade_CG,1) + i1_u = UBOUND(OutData%blade_CG,1) + DO i1 = LBOUND(OutData%blade_CG,1), UBOUND(OutData%blade_CG,1) + OutData%blade_CG(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%blade_IN,1) + i1_u = UBOUND(OutData%blade_IN,1) + i2_l = LBOUND(OutData%blade_IN,2) + i2_u = UBOUND(OutData%blade_IN,2) + DO i2 = LBOUND(OutData%blade_IN,2), UBOUND(OutData%blade_IN,2) + DO i1 = LBOUND(OutData%blade_IN,1), UBOUND(OutData%blade_IN,1) + OutData%blade_IN(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%beta,1) + i1_u = UBOUND(OutData%beta,1) + DO i1 = LBOUND(OutData%beta,1), UBOUND(OutData%beta,1) + OutData%beta(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + OutData%tol = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%GlbPos,1) + i1_u = UBOUND(OutData%GlbPos,1) + DO i1 = LBOUND(OutData%GlbPos,1), UBOUND(OutData%GlbPos,1) + OutData%GlbPos(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%GlbRot,1) + i1_u = UBOUND(OutData%GlbRot,1) + i2_l = LBOUND(OutData%GlbRot,2) + i2_u = UBOUND(OutData%GlbRot,2) + DO i2 = LBOUND(OutData%GlbRot,2), UBOUND(OutData%GlbRot,2) + DO i1 = LBOUND(OutData%GlbRot,1), UBOUND(OutData%GlbRot,1) + OutData%GlbRot(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%Glb_crv,1) + i1_u = UBOUND(OutData%Glb_crv,1) + DO i1 = LBOUND(OutData%Glb_crv,1), UBOUND(OutData%Glb_crv,1) + OutData%Glb_crv(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtN 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%QPtN)) DEALLOCATE(OutData%QPtN) + ALLOCATE(OutData%QPtN(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QPtN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%QPtN,1), UBOUND(OutData%QPtN,1) + OutData%QPtN(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtWeight 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%QPtWeight)) DEALLOCATE(OutData%QPtWeight) + ALLOCATE(OutData%QPtWeight(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QPtWeight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%QPtWeight,1), UBOUND(OutData%QPtWeight,1) + OutData%QPtWeight(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Shp 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%Shp)) DEALLOCATE(OutData%Shp) + ALLOCATE(OutData%Shp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Shp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Shp,2), UBOUND(OutData%Shp,2) + DO i1 = LBOUND(OutData%Shp,1), UBOUND(OutData%Shp,1) + OutData%Shp(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShpDer 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%ShpDer)) DEALLOCATE(OutData%ShpDer) + ALLOCATE(OutData%ShpDer(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ShpDer,2), UBOUND(OutData%ShpDer,2) + DO i1 = LBOUND(OutData%ShpDer,1), UBOUND(OutData%ShpDer,1) + OutData%ShpDer(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jacobian 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%Jacobian)) DEALLOCATE(OutData%Jacobian) + ALLOCATE(OutData%Jacobian(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jacobian.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jacobian,2), UBOUND(OutData%Jacobian,2) + DO i1 = LBOUND(OutData%Jacobian,1), UBOUND(OutData%Jacobian,1) + OutData%Jacobian(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! uu0 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%uu0)) DEALLOCATE(OutData%uu0) + ALLOCATE(OutData%uu0(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%uu0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%uu0,3), UBOUND(OutData%uu0,3) + DO i2 = LBOUND(OutData%uu0,2), UBOUND(OutData%uu0,2) + DO i1 = LBOUND(OutData%uu0,1), UBOUND(OutData%uu0,1) + OutData%uu0(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rrN0 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%rrN0)) DEALLOCATE(OutData%rrN0) + ALLOCATE(OutData%rrN0(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%rrN0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rrN0,3), UBOUND(OutData%rrN0,3) + DO i2 = LBOUND(OutData%rrN0,2), UBOUND(OutData%rrN0,2) + DO i1 = LBOUND(OutData%rrN0,1), UBOUND(OutData%rrN0,1) + OutData%rrN0(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! E10 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%E10)) DEALLOCATE(OutData%E10) + ALLOCATE(OutData%E10(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%E10.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%E10,3), UBOUND(OutData%E10,3) + DO i2 = LBOUND(OutData%E10,2), UBOUND(OutData%E10,2) + DO i1 = LBOUND(OutData%E10,1), UBOUND(OutData%E10,1) + OutData%E10(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%nodes_per_elem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! node_elem_idx 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%node_elem_idx)) DEALLOCATE(OutData%node_elem_idx) + ALLOCATE(OutData%node_elem_idx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%node_elem_idx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%node_elem_idx,2), UBOUND(OutData%node_elem_idx,2) + DO i1 = LBOUND(OutData%node_elem_idx,1), UBOUND(OutData%node_elem_idx,1) + OutData%node_elem_idx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%refine = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dof_node = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dof_elem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%rot_elem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%elem_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%node_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dof_total = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nqp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%analysis_type = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%damp_flag = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ld_retries = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%niter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%quadrature = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_fact = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutInputs = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutInputs) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NNodeOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%OutNd,1) + i1_u = UBOUND(OutData%OutNd,1) + DO i1 = LBOUND(OutData%OutNd,1), UBOUND(OutData%OutNd,1) + OutData%OutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NdIndx 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%NdIndx)) DEALLOCATE(OutData%NdIndx) + ALLOCATE(OutData%NdIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NdIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NdIndx,1), UBOUND(OutData%NdIndx,1) + OutData%NdIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NdIndxInverse 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%NdIndxInverse)) DEALLOCATE(OutData%NdIndxInverse) + ALLOCATE(OutData%NdIndxInverse(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NdIndxInverse.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NdIndxInverse,1), UBOUND(OutData%NdIndxInverse,1) + OutData%NdIndxInverse(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutNd2NdElem 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%OutNd2NdElem)) DEALLOCATE(OutData%OutNd2NdElem) + ALLOCATE(OutData%OutNd2NdElem(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutNd2NdElem.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OutNd2NdElem,2), UBOUND(OutData%OutNd2NdElem,2) + DO i1 = LBOUND(OutData%OutNd2NdElem,1), UBOUND(OutData%OutNd2NdElem,1) + OutData%OutNd2NdElem(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UsePitchAct = TRANSFER(IntKiBuf(Int_Xferred), OutData%UsePitchAct) + Int_Xferred = Int_Xferred + 1 + OutData%pitchJ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%pitchK = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%pitchC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%torqM,1) + i1_u = UBOUND(OutData%torqM,1) + i2_l = LBOUND(OutData%torqM,2) + i2_u = UBOUND(OutData%torqM,2) + DO i2 = LBOUND(OutData%torqM,2), UBOUND(OutData%torqM,2) + DO i1 = LBOUND(OutData%torqM,1), UBOUND(OutData%torqM,1) + OutData%torqM(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 BD_Unpackqpparam( Re_Buf, Db_Buf, Int_Buf, OutData%qp, ErrStat2, ErrMsg2 ) ! qp + 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%qp_indx_offset = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldMotionNodeLoc = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%tngt_stf_fd = TRANSFER(IntKiBuf(Int_Xferred), OutData%tngt_stf_fd) + Int_Xferred = Int_Xferred + 1 + OutData%tngt_stf_comp = TRANSFER(IntKiBuf(Int_Xferred), OutData%tngt_stf_comp) + Int_Xferred = Int_Xferred + 1 + OutData%tngt_stf_pert = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%tngt_stf_difftol = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_TotNumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutParam 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%BldNd_OutParam)) DEALLOCATE(OutData%BldNd_OutParam) + ALLOCATE(OutData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutParam,1), UBOUND(OutData%BldNd_OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%BldNd_OutParam(i1), ErrStat2, ErrMsg2 ) ! BldNd_OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_BlOutNd 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%BldNd_BlOutNd)) DEALLOCATE(OutData%BldNd_BlOutNd) + ALLOCATE(OutData%BldNd_BlOutNd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_BlOutNd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_BlOutNd,1), UBOUND(OutData%BldNd_BlOutNd,1) + OutData%BldNd_BlOutNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtw_Shp_Shp_Jac 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%QPtw_Shp_Shp_Jac)) DEALLOCATE(OutData%QPtw_Shp_Shp_Jac) + ALLOCATE(OutData%QPtw_Shp_Shp_Jac(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%QPtw_Shp_Shp_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%QPtw_Shp_Shp_Jac,4), UBOUND(OutData%QPtw_Shp_Shp_Jac,4) + DO i3 = LBOUND(OutData%QPtw_Shp_Shp_Jac,3), UBOUND(OutData%QPtw_Shp_Shp_Jac,3) + DO i2 = LBOUND(OutData%QPtw_Shp_Shp_Jac,2), UBOUND(OutData%QPtw_Shp_Shp_Jac,2) + DO i1 = LBOUND(OutData%QPtw_Shp_Shp_Jac,1), UBOUND(OutData%QPtw_Shp_Shp_Jac,1) + OutData%QPtw_Shp_Shp_Jac(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtw_Shp_ShpDer 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%QPtw_Shp_ShpDer)) DEALLOCATE(OutData%QPtw_Shp_ShpDer) + ALLOCATE(OutData%QPtw_Shp_ShpDer(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%QPtw_Shp_ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%QPtw_Shp_ShpDer,3), UBOUND(OutData%QPtw_Shp_ShpDer,3) + DO i2 = LBOUND(OutData%QPtw_Shp_ShpDer,2), UBOUND(OutData%QPtw_Shp_ShpDer,2) + DO i1 = LBOUND(OutData%QPtw_Shp_ShpDer,1), UBOUND(OutData%QPtw_Shp_ShpDer,1) + OutData%QPtw_Shp_ShpDer(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtw_ShpDer_ShpDer_Jac 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%QPtw_ShpDer_ShpDer_Jac)) DEALLOCATE(OutData%QPtw_ShpDer_ShpDer_Jac) + ALLOCATE(OutData%QPtw_ShpDer_ShpDer_Jac(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%QPtw_ShpDer_ShpDer_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,4), UBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,4) + DO i3 = LBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,3), UBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,3) + DO i2 = LBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,2), UBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,2) + DO i1 = LBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,1), UBOUND(OutData%QPtw_ShpDer_ShpDer_Jac,1) + OutData%QPtw_ShpDer_ShpDer_Jac(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtw_Shp_Jac 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%QPtw_Shp_Jac)) DEALLOCATE(OutData%QPtw_Shp_Jac) + ALLOCATE(OutData%QPtw_Shp_Jac(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%QPtw_Shp_Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%QPtw_Shp_Jac,3), UBOUND(OutData%QPtw_Shp_Jac,3) + DO i2 = LBOUND(OutData%QPtw_Shp_Jac,2), UBOUND(OutData%QPtw_Shp_Jac,2) + DO i1 = LBOUND(OutData%QPtw_Shp_Jac,1), UBOUND(OutData%QPtw_Shp_Jac,1) + OutData%QPtw_Shp_Jac(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QPtw_ShpDer 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%QPtw_ShpDer)) DEALLOCATE(OutData%QPtw_ShpDer) + ALLOCATE(OutData%QPtw_ShpDer(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QPtw_ShpDer.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%QPtw_ShpDer,2), UBOUND(OutData%QPtw_ShpDer,2) + DO i1 = LBOUND(OutData%QPtw_ShpDer,1), UBOUND(OutData%QPtw_ShpDer,1) + OutData%QPtw_ShpDer(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FEweight 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%FEweight)) DEALLOCATE(OutData%FEweight) + ALLOCATE(OutData%FEweight(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FEweight.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FEweight,2), UBOUND(OutData%FEweight,2) + DO i1 = LBOUND(OutData%FEweight,1), UBOUND(OutData%FEweight,1) + OutData%FEweight(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du 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%du)) DEALLOCATE(OutData%du) + ALLOCATE(OutData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%du,1), UBOUND(OutData%du,1) + OutData%du(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%dx,1) + i1_u = UBOUND(OutData%dx,1) + DO i1 = LBOUND(OutData%dx,1), UBOUND(OutData%dx,1) + OutData%dx(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Jac_nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RotStates = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotStates) + Int_Xferred = Int_Xferred + 1 + OutData%RelStates = TRANSFER(IntKiBuf(Int_Xferred), OutData%RelStates) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE BD_UnPackParam + + SUBROUTINE BD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(BD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%RootMotion, DstInputData%RootMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%PointLoad, DstInputData%PointLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%DistrLoad, DstInputData%DistrLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%HubMotion, DstInputData%HubMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE BD_CopyInput + + SUBROUTINE BD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(BD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%RootMotion, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%PointLoad, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%DistrLoad, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%HubMotion, ErrStat, ErrMsg ) + END SUBROUTINE BD_DestroyInput + + SUBROUTINE BD_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(BD_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 = 'BD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! RootMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%RootMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! RootMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RootMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RootMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RootMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! PointLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%PointLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PointLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PointLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PointLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PointLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! DistrLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%DistrLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistrLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DistrLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DistrLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DistrLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HubMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubMotion + 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 MeshPack( InData%RootMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! RootMotion + 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 MeshPack( InData%PointLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PointLoad + 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 MeshPack( InData%DistrLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistrLoad + 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 MeshPack( InData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubMotion + 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 BD_PackInput + + SUBROUTINE BD_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(BD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_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 + 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 MeshUnpack( OutData%RootMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! RootMotion + 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 MeshUnpack( OutData%PointLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PointLoad + 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 MeshUnpack( OutData%DistrLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistrLoad + 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 MeshUnpack( OutData%HubMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubMotion + 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 BD_UnPackInput + + SUBROUTINE BD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(BD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'BD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%ReactionForce, DstOutputData%ReactionForce, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%BldMotion, DstOutputData%BldMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstOutputData%RootMxr = SrcOutputData%RootMxr + DstOutputData%RootMyr = SrcOutputData%RootMyr +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE BD_CopyOutput + + SUBROUTINE BD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(BD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%ReactionForce, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%BldMotion, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE BD_DestroyOutput + + SUBROUTINE BD_PackOutput( 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(BD_OutputType), 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 = 'BD_PackOutput' + ! 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 ! ReactionForce: size of buffers for each call to pack subtype + CALL MeshPack( InData%ReactionForce, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ReactionForce + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ReactionForce + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ReactionForce + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ReactionForce + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! BldMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%BldMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BldMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BldMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BldMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BldMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! RootMxr + Re_BufSz = Re_BufSz + 1 ! RootMyr + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%ReactionForce, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ReactionForce + 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 MeshPack( InData%BldMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BldMotion + 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 + ReKiBuf(Re_Xferred) = InData%RootMxr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RootMyr + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE BD_PackOutput + + SUBROUTINE BD_UnPackOutput( 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(BD_OutputType), 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 = 'BD_UnPackOutput' + ! 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 MeshUnpack( OutData%ReactionForce, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ReactionForce + 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 MeshUnpack( OutData%BldMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BldMotion + 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%RootMxr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RootMyr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE BD_UnPackOutput + + SUBROUTINE BD_CopyEqMotionQP( SrcEqMotionQPData, DstEqMotionQPData, CtrlCode, ErrStat, ErrMsg ) + TYPE(EqMotionQP), INTENT(IN) :: SrcEqMotionQPData + TYPE(EqMotionQP), INTENT(INOUT) :: DstEqMotionQPData + 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 = 'BD_CopyEqMotionQP' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcEqMotionQPData%uuu)) THEN + i1_l = LBOUND(SrcEqMotionQPData%uuu,1) + i1_u = UBOUND(SrcEqMotionQPData%uuu,1) + i2_l = LBOUND(SrcEqMotionQPData%uuu,2) + i2_u = UBOUND(SrcEqMotionQPData%uuu,2) + i3_l = LBOUND(SrcEqMotionQPData%uuu,3) + i3_u = UBOUND(SrcEqMotionQPData%uuu,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%uuu)) THEN + ALLOCATE(DstEqMotionQPData%uuu(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%uuu.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%uuu = SrcEqMotionQPData%uuu +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%uup)) THEN + i1_l = LBOUND(SrcEqMotionQPData%uup,1) + i1_u = UBOUND(SrcEqMotionQPData%uup,1) + i2_l = LBOUND(SrcEqMotionQPData%uup,2) + i2_u = UBOUND(SrcEqMotionQPData%uup,2) + i3_l = LBOUND(SrcEqMotionQPData%uup,3) + i3_u = UBOUND(SrcEqMotionQPData%uup,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%uup)) THEN + ALLOCATE(DstEqMotionQPData%uup(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%uup.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%uup = SrcEqMotionQPData%uup +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%vvv)) THEN + i1_l = LBOUND(SrcEqMotionQPData%vvv,1) + i1_u = UBOUND(SrcEqMotionQPData%vvv,1) + i2_l = LBOUND(SrcEqMotionQPData%vvv,2) + i2_u = UBOUND(SrcEqMotionQPData%vvv,2) + i3_l = LBOUND(SrcEqMotionQPData%vvv,3) + i3_u = UBOUND(SrcEqMotionQPData%vvv,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%vvv)) THEN + ALLOCATE(DstEqMotionQPData%vvv(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%vvv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%vvv = SrcEqMotionQPData%vvv +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%vvp)) THEN + i1_l = LBOUND(SrcEqMotionQPData%vvp,1) + i1_u = UBOUND(SrcEqMotionQPData%vvp,1) + i2_l = LBOUND(SrcEqMotionQPData%vvp,2) + i2_u = UBOUND(SrcEqMotionQPData%vvp,2) + i3_l = LBOUND(SrcEqMotionQPData%vvp,3) + i3_u = UBOUND(SrcEqMotionQPData%vvp,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%vvp)) THEN + ALLOCATE(DstEqMotionQPData%vvp(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%vvp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%vvp = SrcEqMotionQPData%vvp +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%aaa)) THEN + i1_l = LBOUND(SrcEqMotionQPData%aaa,1) + i1_u = UBOUND(SrcEqMotionQPData%aaa,1) + i2_l = LBOUND(SrcEqMotionQPData%aaa,2) + i2_u = UBOUND(SrcEqMotionQPData%aaa,2) + i3_l = LBOUND(SrcEqMotionQPData%aaa,3) + i3_u = UBOUND(SrcEqMotionQPData%aaa,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%aaa)) THEN + ALLOCATE(DstEqMotionQPData%aaa(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%aaa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%aaa = SrcEqMotionQPData%aaa +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%RR0)) THEN + i1_l = LBOUND(SrcEqMotionQPData%RR0,1) + i1_u = UBOUND(SrcEqMotionQPData%RR0,1) + i2_l = LBOUND(SrcEqMotionQPData%RR0,2) + i2_u = UBOUND(SrcEqMotionQPData%RR0,2) + i3_l = LBOUND(SrcEqMotionQPData%RR0,3) + i3_u = UBOUND(SrcEqMotionQPData%RR0,3) + i4_l = LBOUND(SrcEqMotionQPData%RR0,4) + i4_u = UBOUND(SrcEqMotionQPData%RR0,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%RR0)) THEN + ALLOCATE(DstEqMotionQPData%RR0(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 DstEqMotionQPData%RR0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%RR0 = SrcEqMotionQPData%RR0 +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%kappa)) THEN + i1_l = LBOUND(SrcEqMotionQPData%kappa,1) + i1_u = UBOUND(SrcEqMotionQPData%kappa,1) + i2_l = LBOUND(SrcEqMotionQPData%kappa,2) + i2_u = UBOUND(SrcEqMotionQPData%kappa,2) + i3_l = LBOUND(SrcEqMotionQPData%kappa,3) + i3_u = UBOUND(SrcEqMotionQPData%kappa,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%kappa)) THEN + ALLOCATE(DstEqMotionQPData%kappa(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%kappa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%kappa = SrcEqMotionQPData%kappa +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%E1)) THEN + i1_l = LBOUND(SrcEqMotionQPData%E1,1) + i1_u = UBOUND(SrcEqMotionQPData%E1,1) + i2_l = LBOUND(SrcEqMotionQPData%E1,2) + i2_u = UBOUND(SrcEqMotionQPData%E1,2) + i3_l = LBOUND(SrcEqMotionQPData%E1,3) + i3_u = UBOUND(SrcEqMotionQPData%E1,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%E1)) THEN + ALLOCATE(DstEqMotionQPData%E1(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%E1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%E1 = SrcEqMotionQPData%E1 +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Stif)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Stif,1) + i1_u = UBOUND(SrcEqMotionQPData%Stif,1) + i2_l = LBOUND(SrcEqMotionQPData%Stif,2) + i2_u = UBOUND(SrcEqMotionQPData%Stif,2) + i3_l = LBOUND(SrcEqMotionQPData%Stif,3) + i3_u = UBOUND(SrcEqMotionQPData%Stif,3) + i4_l = LBOUND(SrcEqMotionQPData%Stif,4) + i4_u = UBOUND(SrcEqMotionQPData%Stif,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Stif)) THEN + ALLOCATE(DstEqMotionQPData%Stif(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 DstEqMotionQPData%Stif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Stif = SrcEqMotionQPData%Stif +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Fb)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Fb,1) + i1_u = UBOUND(SrcEqMotionQPData%Fb,1) + i2_l = LBOUND(SrcEqMotionQPData%Fb,2) + i2_u = UBOUND(SrcEqMotionQPData%Fb,2) + i3_l = LBOUND(SrcEqMotionQPData%Fb,3) + i3_u = UBOUND(SrcEqMotionQPData%Fb,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Fb)) THEN + ALLOCATE(DstEqMotionQPData%Fb(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Fb = SrcEqMotionQPData%Fb +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Fc)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Fc,1) + i1_u = UBOUND(SrcEqMotionQPData%Fc,1) + i2_l = LBOUND(SrcEqMotionQPData%Fc,2) + i2_u = UBOUND(SrcEqMotionQPData%Fc,2) + i3_l = LBOUND(SrcEqMotionQPData%Fc,3) + i3_u = UBOUND(SrcEqMotionQPData%Fc,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Fc)) THEN + ALLOCATE(DstEqMotionQPData%Fc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Fc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Fc = SrcEqMotionQPData%Fc +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Fd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Fd,1) + i1_u = UBOUND(SrcEqMotionQPData%Fd,1) + i2_l = LBOUND(SrcEqMotionQPData%Fd,2) + i2_u = UBOUND(SrcEqMotionQPData%Fd,2) + i3_l = LBOUND(SrcEqMotionQPData%Fd,3) + i3_u = UBOUND(SrcEqMotionQPData%Fd,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Fd)) THEN + ALLOCATE(DstEqMotionQPData%Fd(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Fd = SrcEqMotionQPData%Fd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Fg)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Fg,1) + i1_u = UBOUND(SrcEqMotionQPData%Fg,1) + i2_l = LBOUND(SrcEqMotionQPData%Fg,2) + i2_u = UBOUND(SrcEqMotionQPData%Fg,2) + i3_l = LBOUND(SrcEqMotionQPData%Fg,3) + i3_u = UBOUND(SrcEqMotionQPData%Fg,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Fg)) THEN + ALLOCATE(DstEqMotionQPData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Fg = SrcEqMotionQPData%Fg +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Fi)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Fi,1) + i1_u = UBOUND(SrcEqMotionQPData%Fi,1) + i2_l = LBOUND(SrcEqMotionQPData%Fi,2) + i2_u = UBOUND(SrcEqMotionQPData%Fi,2) + i3_l = LBOUND(SrcEqMotionQPData%Fi,3) + i3_u = UBOUND(SrcEqMotionQPData%Fi,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Fi)) THEN + ALLOCATE(DstEqMotionQPData%Fi(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Fi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Fi = SrcEqMotionQPData%Fi +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Ftemp)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Ftemp,1) + i1_u = UBOUND(SrcEqMotionQPData%Ftemp,1) + i2_l = LBOUND(SrcEqMotionQPData%Ftemp,2) + i2_u = UBOUND(SrcEqMotionQPData%Ftemp,2) + i3_l = LBOUND(SrcEqMotionQPData%Ftemp,3) + i3_u = UBOUND(SrcEqMotionQPData%Ftemp,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Ftemp)) THEN + ALLOCATE(DstEqMotionQPData%Ftemp(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%Ftemp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Ftemp = SrcEqMotionQPData%Ftemp +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%RR0mEta)) THEN + i1_l = LBOUND(SrcEqMotionQPData%RR0mEta,1) + i1_u = UBOUND(SrcEqMotionQPData%RR0mEta,1) + i2_l = LBOUND(SrcEqMotionQPData%RR0mEta,2) + i2_u = UBOUND(SrcEqMotionQPData%RR0mEta,2) + i3_l = LBOUND(SrcEqMotionQPData%RR0mEta,3) + i3_u = UBOUND(SrcEqMotionQPData%RR0mEta,3) + IF (.NOT. ALLOCATED(DstEqMotionQPData%RR0mEta)) THEN + ALLOCATE(DstEqMotionQPData%RR0mEta(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstEqMotionQPData%RR0mEta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%RR0mEta = SrcEqMotionQPData%RR0mEta +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%rho)) THEN + i1_l = LBOUND(SrcEqMotionQPData%rho,1) + i1_u = UBOUND(SrcEqMotionQPData%rho,1) + i2_l = LBOUND(SrcEqMotionQPData%rho,2) + i2_u = UBOUND(SrcEqMotionQPData%rho,2) + i3_l = LBOUND(SrcEqMotionQPData%rho,3) + i3_u = UBOUND(SrcEqMotionQPData%rho,3) + i4_l = LBOUND(SrcEqMotionQPData%rho,4) + i4_u = UBOUND(SrcEqMotionQPData%rho,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%rho)) THEN + ALLOCATE(DstEqMotionQPData%rho(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 DstEqMotionQPData%rho.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%rho = SrcEqMotionQPData%rho +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%betaC)) THEN + i1_l = LBOUND(SrcEqMotionQPData%betaC,1) + i1_u = UBOUND(SrcEqMotionQPData%betaC,1) + i2_l = LBOUND(SrcEqMotionQPData%betaC,2) + i2_u = UBOUND(SrcEqMotionQPData%betaC,2) + i3_l = LBOUND(SrcEqMotionQPData%betaC,3) + i3_u = UBOUND(SrcEqMotionQPData%betaC,3) + i4_l = LBOUND(SrcEqMotionQPData%betaC,4) + i4_u = UBOUND(SrcEqMotionQPData%betaC,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%betaC)) THEN + ALLOCATE(DstEqMotionQPData%betaC(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 DstEqMotionQPData%betaC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%betaC = SrcEqMotionQPData%betaC +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Gi)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Gi,1) + i1_u = UBOUND(SrcEqMotionQPData%Gi,1) + i2_l = LBOUND(SrcEqMotionQPData%Gi,2) + i2_u = UBOUND(SrcEqMotionQPData%Gi,2) + i3_l = LBOUND(SrcEqMotionQPData%Gi,3) + i3_u = UBOUND(SrcEqMotionQPData%Gi,3) + i4_l = LBOUND(SrcEqMotionQPData%Gi,4) + i4_u = UBOUND(SrcEqMotionQPData%Gi,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Gi)) THEN + ALLOCATE(DstEqMotionQPData%Gi(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 DstEqMotionQPData%Gi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Gi = SrcEqMotionQPData%Gi +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Ki)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Ki,1) + i1_u = UBOUND(SrcEqMotionQPData%Ki,1) + i2_l = LBOUND(SrcEqMotionQPData%Ki,2) + i2_u = UBOUND(SrcEqMotionQPData%Ki,2) + i3_l = LBOUND(SrcEqMotionQPData%Ki,3) + i3_u = UBOUND(SrcEqMotionQPData%Ki,3) + i4_l = LBOUND(SrcEqMotionQPData%Ki,4) + i4_u = UBOUND(SrcEqMotionQPData%Ki,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Ki)) THEN + ALLOCATE(DstEqMotionQPData%Ki(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 DstEqMotionQPData%Ki.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Ki = SrcEqMotionQPData%Ki +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Mi)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Mi,1) + i1_u = UBOUND(SrcEqMotionQPData%Mi,1) + i2_l = LBOUND(SrcEqMotionQPData%Mi,2) + i2_u = UBOUND(SrcEqMotionQPData%Mi,2) + i3_l = LBOUND(SrcEqMotionQPData%Mi,3) + i3_u = UBOUND(SrcEqMotionQPData%Mi,3) + i4_l = LBOUND(SrcEqMotionQPData%Mi,4) + i4_u = UBOUND(SrcEqMotionQPData%Mi,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Mi)) THEN + ALLOCATE(DstEqMotionQPData%Mi(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 DstEqMotionQPData%Mi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Mi = SrcEqMotionQPData%Mi +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Oe)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Oe,1) + i1_u = UBOUND(SrcEqMotionQPData%Oe,1) + i2_l = LBOUND(SrcEqMotionQPData%Oe,2) + i2_u = UBOUND(SrcEqMotionQPData%Oe,2) + i3_l = LBOUND(SrcEqMotionQPData%Oe,3) + i3_u = UBOUND(SrcEqMotionQPData%Oe,3) + i4_l = LBOUND(SrcEqMotionQPData%Oe,4) + i4_u = UBOUND(SrcEqMotionQPData%Oe,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Oe)) THEN + ALLOCATE(DstEqMotionQPData%Oe(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 DstEqMotionQPData%Oe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Oe = SrcEqMotionQPData%Oe +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Pe)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Pe,1) + i1_u = UBOUND(SrcEqMotionQPData%Pe,1) + i2_l = LBOUND(SrcEqMotionQPData%Pe,2) + i2_u = UBOUND(SrcEqMotionQPData%Pe,2) + i3_l = LBOUND(SrcEqMotionQPData%Pe,3) + i3_u = UBOUND(SrcEqMotionQPData%Pe,3) + i4_l = LBOUND(SrcEqMotionQPData%Pe,4) + i4_u = UBOUND(SrcEqMotionQPData%Pe,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Pe)) THEN + ALLOCATE(DstEqMotionQPData%Pe(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 DstEqMotionQPData%Pe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Pe = SrcEqMotionQPData%Pe +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Qe)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Qe,1) + i1_u = UBOUND(SrcEqMotionQPData%Qe,1) + i2_l = LBOUND(SrcEqMotionQPData%Qe,2) + i2_u = UBOUND(SrcEqMotionQPData%Qe,2) + i3_l = LBOUND(SrcEqMotionQPData%Qe,3) + i3_u = UBOUND(SrcEqMotionQPData%Qe,3) + i4_l = LBOUND(SrcEqMotionQPData%Qe,4) + i4_u = UBOUND(SrcEqMotionQPData%Qe,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Qe)) THEN + ALLOCATE(DstEqMotionQPData%Qe(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 DstEqMotionQPData%Qe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Qe = SrcEqMotionQPData%Qe +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Gd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Gd,1) + i1_u = UBOUND(SrcEqMotionQPData%Gd,1) + i2_l = LBOUND(SrcEqMotionQPData%Gd,2) + i2_u = UBOUND(SrcEqMotionQPData%Gd,2) + i3_l = LBOUND(SrcEqMotionQPData%Gd,3) + i3_u = UBOUND(SrcEqMotionQPData%Gd,3) + i4_l = LBOUND(SrcEqMotionQPData%Gd,4) + i4_u = UBOUND(SrcEqMotionQPData%Gd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Gd)) THEN + ALLOCATE(DstEqMotionQPData%Gd(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 DstEqMotionQPData%Gd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Gd = SrcEqMotionQPData%Gd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Od)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Od,1) + i1_u = UBOUND(SrcEqMotionQPData%Od,1) + i2_l = LBOUND(SrcEqMotionQPData%Od,2) + i2_u = UBOUND(SrcEqMotionQPData%Od,2) + i3_l = LBOUND(SrcEqMotionQPData%Od,3) + i3_u = UBOUND(SrcEqMotionQPData%Od,3) + i4_l = LBOUND(SrcEqMotionQPData%Od,4) + i4_u = UBOUND(SrcEqMotionQPData%Od,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Od)) THEN + ALLOCATE(DstEqMotionQPData%Od(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 DstEqMotionQPData%Od.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Od = SrcEqMotionQPData%Od +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Pd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Pd,1) + i1_u = UBOUND(SrcEqMotionQPData%Pd,1) + i2_l = LBOUND(SrcEqMotionQPData%Pd,2) + i2_u = UBOUND(SrcEqMotionQPData%Pd,2) + i3_l = LBOUND(SrcEqMotionQPData%Pd,3) + i3_u = UBOUND(SrcEqMotionQPData%Pd,3) + i4_l = LBOUND(SrcEqMotionQPData%Pd,4) + i4_u = UBOUND(SrcEqMotionQPData%Pd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Pd)) THEN + ALLOCATE(DstEqMotionQPData%Pd(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 DstEqMotionQPData%Pd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Pd = SrcEqMotionQPData%Pd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Qd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Qd,1) + i1_u = UBOUND(SrcEqMotionQPData%Qd,1) + i2_l = LBOUND(SrcEqMotionQPData%Qd,2) + i2_u = UBOUND(SrcEqMotionQPData%Qd,2) + i3_l = LBOUND(SrcEqMotionQPData%Qd,3) + i3_u = UBOUND(SrcEqMotionQPData%Qd,3) + i4_l = LBOUND(SrcEqMotionQPData%Qd,4) + i4_u = UBOUND(SrcEqMotionQPData%Qd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Qd)) THEN + ALLOCATE(DstEqMotionQPData%Qd(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 DstEqMotionQPData%Qd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Qd = SrcEqMotionQPData%Qd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Sd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Sd,1) + i1_u = UBOUND(SrcEqMotionQPData%Sd,1) + i2_l = LBOUND(SrcEqMotionQPData%Sd,2) + i2_u = UBOUND(SrcEqMotionQPData%Sd,2) + i3_l = LBOUND(SrcEqMotionQPData%Sd,3) + i3_u = UBOUND(SrcEqMotionQPData%Sd,3) + i4_l = LBOUND(SrcEqMotionQPData%Sd,4) + i4_u = UBOUND(SrcEqMotionQPData%Sd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Sd)) THEN + ALLOCATE(DstEqMotionQPData%Sd(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 DstEqMotionQPData%Sd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Sd = SrcEqMotionQPData%Sd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Xd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Xd,1) + i1_u = UBOUND(SrcEqMotionQPData%Xd,1) + i2_l = LBOUND(SrcEqMotionQPData%Xd,2) + i2_u = UBOUND(SrcEqMotionQPData%Xd,2) + i3_l = LBOUND(SrcEqMotionQPData%Xd,3) + i3_u = UBOUND(SrcEqMotionQPData%Xd,3) + i4_l = LBOUND(SrcEqMotionQPData%Xd,4) + i4_u = UBOUND(SrcEqMotionQPData%Xd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Xd)) THEN + ALLOCATE(DstEqMotionQPData%Xd(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 DstEqMotionQPData%Xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Xd = SrcEqMotionQPData%Xd +ENDIF +IF (ALLOCATED(SrcEqMotionQPData%Yd)) THEN + i1_l = LBOUND(SrcEqMotionQPData%Yd,1) + i1_u = UBOUND(SrcEqMotionQPData%Yd,1) + i2_l = LBOUND(SrcEqMotionQPData%Yd,2) + i2_u = UBOUND(SrcEqMotionQPData%Yd,2) + i3_l = LBOUND(SrcEqMotionQPData%Yd,3) + i3_u = UBOUND(SrcEqMotionQPData%Yd,3) + i4_l = LBOUND(SrcEqMotionQPData%Yd,4) + i4_u = UBOUND(SrcEqMotionQPData%Yd,4) + IF (.NOT. ALLOCATED(DstEqMotionQPData%Yd)) THEN + ALLOCATE(DstEqMotionQPData%Yd(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 DstEqMotionQPData%Yd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstEqMotionQPData%Yd = SrcEqMotionQPData%Yd +ENDIF + END SUBROUTINE BD_CopyEqMotionQP + + SUBROUTINE BD_DestroyEqMotionQP( EqMotionQPData, ErrStat, ErrMsg ) + TYPE(EqMotionQP), INTENT(INOUT) :: EqMotionQPData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyEqMotionQP' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(EqMotionQPData%uuu)) THEN + DEALLOCATE(EqMotionQPData%uuu) +ENDIF +IF (ALLOCATED(EqMotionQPData%uup)) THEN + DEALLOCATE(EqMotionQPData%uup) +ENDIF +IF (ALLOCATED(EqMotionQPData%vvv)) THEN + DEALLOCATE(EqMotionQPData%vvv) +ENDIF +IF (ALLOCATED(EqMotionQPData%vvp)) THEN + DEALLOCATE(EqMotionQPData%vvp) +ENDIF +IF (ALLOCATED(EqMotionQPData%aaa)) THEN + DEALLOCATE(EqMotionQPData%aaa) +ENDIF +IF (ALLOCATED(EqMotionQPData%RR0)) THEN + DEALLOCATE(EqMotionQPData%RR0) +ENDIF +IF (ALLOCATED(EqMotionQPData%kappa)) THEN + DEALLOCATE(EqMotionQPData%kappa) +ENDIF +IF (ALLOCATED(EqMotionQPData%E1)) THEN + DEALLOCATE(EqMotionQPData%E1) +ENDIF +IF (ALLOCATED(EqMotionQPData%Stif)) THEN + DEALLOCATE(EqMotionQPData%Stif) +ENDIF +IF (ALLOCATED(EqMotionQPData%Fb)) THEN + DEALLOCATE(EqMotionQPData%Fb) +ENDIF +IF (ALLOCATED(EqMotionQPData%Fc)) THEN + DEALLOCATE(EqMotionQPData%Fc) +ENDIF +IF (ALLOCATED(EqMotionQPData%Fd)) THEN + DEALLOCATE(EqMotionQPData%Fd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Fg)) THEN + DEALLOCATE(EqMotionQPData%Fg) +ENDIF +IF (ALLOCATED(EqMotionQPData%Fi)) THEN + DEALLOCATE(EqMotionQPData%Fi) +ENDIF +IF (ALLOCATED(EqMotionQPData%Ftemp)) THEN + DEALLOCATE(EqMotionQPData%Ftemp) +ENDIF +IF (ALLOCATED(EqMotionQPData%RR0mEta)) THEN + DEALLOCATE(EqMotionQPData%RR0mEta) +ENDIF +IF (ALLOCATED(EqMotionQPData%rho)) THEN + DEALLOCATE(EqMotionQPData%rho) +ENDIF +IF (ALLOCATED(EqMotionQPData%betaC)) THEN + DEALLOCATE(EqMotionQPData%betaC) +ENDIF +IF (ALLOCATED(EqMotionQPData%Gi)) THEN + DEALLOCATE(EqMotionQPData%Gi) +ENDIF +IF (ALLOCATED(EqMotionQPData%Ki)) THEN + DEALLOCATE(EqMotionQPData%Ki) +ENDIF +IF (ALLOCATED(EqMotionQPData%Mi)) THEN + DEALLOCATE(EqMotionQPData%Mi) +ENDIF +IF (ALLOCATED(EqMotionQPData%Oe)) THEN + DEALLOCATE(EqMotionQPData%Oe) +ENDIF +IF (ALLOCATED(EqMotionQPData%Pe)) THEN + DEALLOCATE(EqMotionQPData%Pe) +ENDIF +IF (ALLOCATED(EqMotionQPData%Qe)) THEN + DEALLOCATE(EqMotionQPData%Qe) +ENDIF +IF (ALLOCATED(EqMotionQPData%Gd)) THEN + DEALLOCATE(EqMotionQPData%Gd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Od)) THEN + DEALLOCATE(EqMotionQPData%Od) +ENDIF +IF (ALLOCATED(EqMotionQPData%Pd)) THEN + DEALLOCATE(EqMotionQPData%Pd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Qd)) THEN + DEALLOCATE(EqMotionQPData%Qd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Sd)) THEN + DEALLOCATE(EqMotionQPData%Sd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Xd)) THEN + DEALLOCATE(EqMotionQPData%Xd) +ENDIF +IF (ALLOCATED(EqMotionQPData%Yd)) THEN + DEALLOCATE(EqMotionQPData%Yd) +ENDIF + END SUBROUTINE BD_DestroyEqMotionQP + + SUBROUTINE BD_PackEqMotionQP( 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(EqMotionQP), 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 = 'BD_PackEqMotionQP' + ! 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 ! uuu allocated yes/no + IF ( ALLOCATED(InData%uuu) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! uuu upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%uuu) ! uuu + END IF + Int_BufSz = Int_BufSz + 1 ! uup allocated yes/no + IF ( ALLOCATED(InData%uup) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! uup upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%uup) ! uup + END IF + Int_BufSz = Int_BufSz + 1 ! vvv allocated yes/no + IF ( ALLOCATED(InData%vvv) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! vvv upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%vvv) ! vvv + END IF + Int_BufSz = Int_BufSz + 1 ! vvp allocated yes/no + IF ( ALLOCATED(InData%vvp) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! vvp upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%vvp) ! vvp + END IF + Int_BufSz = Int_BufSz + 1 ! aaa allocated yes/no + IF ( ALLOCATED(InData%aaa) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! aaa upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%aaa) ! aaa + END IF + Int_BufSz = Int_BufSz + 1 ! RR0 allocated yes/no + IF ( ALLOCATED(InData%RR0) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! RR0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%RR0) ! RR0 + END IF + Int_BufSz = Int_BufSz + 1 ! kappa allocated yes/no + IF ( ALLOCATED(InData%kappa) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! kappa upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%kappa) ! kappa + END IF + Int_BufSz = Int_BufSz + 1 ! E1 allocated yes/no + IF ( ALLOCATED(InData%E1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! E1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%E1) ! E1 + END IF + Int_BufSz = Int_BufSz + 1 ! Stif allocated yes/no + IF ( ALLOCATED(InData%Stif) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Stif upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Stif) ! Stif + END IF + Int_BufSz = Int_BufSz + 1 ! Fb allocated yes/no + IF ( ALLOCATED(InData%Fb) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fb upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fb) ! Fb + END IF + Int_BufSz = Int_BufSz + 1 ! Fc allocated yes/no + IF ( ALLOCATED(InData%Fc) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fc upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fc) ! Fc + END IF + Int_BufSz = Int_BufSz + 1 ! Fd allocated yes/no + IF ( ALLOCATED(InData%Fd) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fd) ! Fd + END IF + Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no + IF ( ALLOCATED(InData%Fg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fg) ! Fg + END IF + Int_BufSz = Int_BufSz + 1 ! Fi allocated yes/no + IF ( ALLOCATED(InData%Fi) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fi upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fi) ! Fi + END IF + Int_BufSz = Int_BufSz + 1 ! Ftemp allocated yes/no + IF ( ALLOCATED(InData%Ftemp) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Ftemp upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Ftemp) ! Ftemp + END IF + Int_BufSz = Int_BufSz + 1 ! RR0mEta allocated yes/no + IF ( ALLOCATED(InData%RR0mEta) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! RR0mEta upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%RR0mEta) ! RR0mEta + END IF + Int_BufSz = Int_BufSz + 1 ! rho allocated yes/no + IF ( ALLOCATED(InData%rho) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! rho upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rho) ! rho + END IF + Int_BufSz = Int_BufSz + 1 ! betaC allocated yes/no + IF ( ALLOCATED(InData%betaC) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! betaC upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%betaC) ! betaC + END IF + Int_BufSz = Int_BufSz + 1 ! Gi allocated yes/no + IF ( ALLOCATED(InData%Gi) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Gi upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Gi) ! Gi + END IF + Int_BufSz = Int_BufSz + 1 ! Ki allocated yes/no + IF ( ALLOCATED(InData%Ki) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Ki upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Ki) ! Ki + END IF + Int_BufSz = Int_BufSz + 1 ! Mi allocated yes/no + IF ( ALLOCATED(InData%Mi) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Mi upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Mi) ! Mi + END IF + Int_BufSz = Int_BufSz + 1 ! Oe allocated yes/no + IF ( ALLOCATED(InData%Oe) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Oe upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Oe) ! Oe + END IF + Int_BufSz = Int_BufSz + 1 ! Pe allocated yes/no + IF ( ALLOCATED(InData%Pe) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Pe upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Pe) ! Pe + END IF + Int_BufSz = Int_BufSz + 1 ! Qe allocated yes/no + IF ( ALLOCATED(InData%Qe) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Qe upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Qe) ! Qe + END IF + Int_BufSz = Int_BufSz + 1 ! Gd allocated yes/no + IF ( ALLOCATED(InData%Gd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Gd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Gd) ! Gd + END IF + Int_BufSz = Int_BufSz + 1 ! Od allocated yes/no + IF ( ALLOCATED(InData%Od) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Od upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Od) ! Od + END IF + Int_BufSz = Int_BufSz + 1 ! Pd allocated yes/no + IF ( ALLOCATED(InData%Pd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Pd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Pd) ! Pd + END IF + Int_BufSz = Int_BufSz + 1 ! Qd allocated yes/no + IF ( ALLOCATED(InData%Qd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Qd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Qd) ! Qd + END IF + Int_BufSz = Int_BufSz + 1 ! Sd allocated yes/no + IF ( ALLOCATED(InData%Sd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Sd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Sd) ! Sd + END IF + Int_BufSz = Int_BufSz + 1 ! Xd allocated yes/no + IF ( ALLOCATED(InData%Xd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Xd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Xd) ! Xd + END IF + Int_BufSz = Int_BufSz + 1 ! Yd allocated yes/no + IF ( ALLOCATED(InData%Yd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Yd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Yd) ! Yd + 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%uuu) ) 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%uuu,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuu,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uuu,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuu,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uuu,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uuu,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%uuu,3), UBOUND(InData%uuu,3) + DO i2 = LBOUND(InData%uuu,2), UBOUND(InData%uuu,2) + DO i1 = LBOUND(InData%uuu,1), UBOUND(InData%uuu,1) + DbKiBuf(Db_Xferred) = InData%uuu(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%uup) ) 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%uup,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uup,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uup,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uup,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%uup,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%uup,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%uup,3), UBOUND(InData%uup,3) + DO i2 = LBOUND(InData%uup,2), UBOUND(InData%uup,2) + DO i1 = LBOUND(InData%uup,1), UBOUND(InData%uup,1) + DbKiBuf(Db_Xferred) = InData%uup(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%vvv) ) 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%vvv,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvv,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vvv,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvv,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vvv,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvv,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%vvv,3), UBOUND(InData%vvv,3) + DO i2 = LBOUND(InData%vvv,2), UBOUND(InData%vvv,2) + DO i1 = LBOUND(InData%vvv,1), UBOUND(InData%vvv,1) + DbKiBuf(Db_Xferred) = InData%vvv(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%vvp) ) 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%vvp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vvp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvp,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%vvp,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vvp,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%vvp,3), UBOUND(InData%vvp,3) + DO i2 = LBOUND(InData%vvp,2), UBOUND(InData%vvp,2) + DO i1 = LBOUND(InData%vvp,1), UBOUND(InData%vvp,1) + DbKiBuf(Db_Xferred) = InData%vvp(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%aaa) ) 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%aaa,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%aaa,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%aaa,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%aaa,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%aaa,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%aaa,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%aaa,3), UBOUND(InData%aaa,3) + DO i2 = LBOUND(InData%aaa,2), UBOUND(InData%aaa,2) + DO i1 = LBOUND(InData%aaa,1), UBOUND(InData%aaa,1) + DbKiBuf(Db_Xferred) = InData%aaa(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RR0) ) 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%RR0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RR0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RR0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RR0,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%RR0,4), UBOUND(InData%RR0,4) + DO i3 = LBOUND(InData%RR0,3), UBOUND(InData%RR0,3) + DO i2 = LBOUND(InData%RR0,2), UBOUND(InData%RR0,2) + DO i1 = LBOUND(InData%RR0,1), UBOUND(InData%RR0,1) + DbKiBuf(Db_Xferred) = InData%RR0(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%kappa) ) 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%kappa,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kappa,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%kappa,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kappa,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%kappa,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%kappa,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%kappa,3), UBOUND(InData%kappa,3) + DO i2 = LBOUND(InData%kappa,2), UBOUND(InData%kappa,2) + DO i1 = LBOUND(InData%kappa,1), UBOUND(InData%kappa,1) + DbKiBuf(Db_Xferred) = InData%kappa(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%E1) ) 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%E1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%E1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%E1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%E1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%E1,3), UBOUND(InData%E1,3) + DO i2 = LBOUND(InData%E1,2), UBOUND(InData%E1,2) + DO i1 = LBOUND(InData%E1,1), UBOUND(InData%E1,1) + DbKiBuf(Db_Xferred) = InData%E1(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Stif) ) 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%Stif,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stif,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stif,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stif,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stif,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Stif,4), UBOUND(InData%Stif,4) + DO i3 = LBOUND(InData%Stif,3), UBOUND(InData%Stif,3) + DO i2 = LBOUND(InData%Stif,2), UBOUND(InData%Stif,2) + DO i1 = LBOUND(InData%Stif,1), UBOUND(InData%Stif,1) + DbKiBuf(Db_Xferred) = InData%Stif(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fb) ) 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%Fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fb,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fb,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fb,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fb,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fb,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fb,3), UBOUND(InData%Fb,3) + DO i2 = LBOUND(InData%Fb,2), UBOUND(InData%Fb,2) + DO i1 = LBOUND(InData%Fb,1), UBOUND(InData%Fb,1) + DbKiBuf(Db_Xferred) = InData%Fb(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fc) ) 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%Fc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fc,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fc,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fc,3), UBOUND(InData%Fc,3) + DO i2 = LBOUND(InData%Fc,2), UBOUND(InData%Fc,2) + DO i1 = LBOUND(InData%Fc,1), UBOUND(InData%Fc,1) + DbKiBuf(Db_Xferred) = InData%Fc(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fd) ) 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%Fd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fd,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fd,3), UBOUND(InData%Fd,3) + DO i2 = LBOUND(InData%Fd,2), UBOUND(InData%Fd,2) + DO i1 = LBOUND(InData%Fd,1), UBOUND(InData%Fd,1) + DbKiBuf(Db_Xferred) = InData%Fd(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fg) ) 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%Fg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fg,3), UBOUND(InData%Fg,3) + DO i2 = LBOUND(InData%Fg,2), UBOUND(InData%Fg,2) + DO i1 = LBOUND(InData%Fg,1), UBOUND(InData%Fg,1) + DbKiBuf(Db_Xferred) = InData%Fg(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fi) ) 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%Fi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fi,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fi,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fi,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fi,3), UBOUND(InData%Fi,3) + DO i2 = LBOUND(InData%Fi,2), UBOUND(InData%Fi,2) + DO i1 = LBOUND(InData%Fi,1), UBOUND(InData%Fi,1) + DbKiBuf(Db_Xferred) = InData%Fi(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Ftemp) ) 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%Ftemp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ftemp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ftemp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ftemp,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ftemp,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ftemp,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Ftemp,3), UBOUND(InData%Ftemp,3) + DO i2 = LBOUND(InData%Ftemp,2), UBOUND(InData%Ftemp,2) + DO i1 = LBOUND(InData%Ftemp,1), UBOUND(InData%Ftemp,1) + DbKiBuf(Db_Xferred) = InData%Ftemp(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RR0mEta) ) 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%RR0mEta,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0mEta,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RR0mEta,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0mEta,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RR0mEta,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RR0mEta,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%RR0mEta,3), UBOUND(InData%RR0mEta,3) + DO i2 = LBOUND(InData%RR0mEta,2), UBOUND(InData%RR0mEta,2) + DO i1 = LBOUND(InData%RR0mEta,1), UBOUND(InData%RR0mEta,1) + DbKiBuf(Db_Xferred) = InData%RR0mEta(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rho) ) 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%rho,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rho,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rho,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rho,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rho,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rho,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rho,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rho,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%rho,4), UBOUND(InData%rho,4) + DO i3 = LBOUND(InData%rho,3), UBOUND(InData%rho,3) + DO i2 = LBOUND(InData%rho,2), UBOUND(InData%rho,2) + DO i1 = LBOUND(InData%rho,1), UBOUND(InData%rho,1) + DbKiBuf(Db_Xferred) = InData%rho(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%betaC) ) 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%betaC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%betaC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%betaC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%betaC,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%betaC,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%betaC,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%betaC,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%betaC,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%betaC,4), UBOUND(InData%betaC,4) + DO i3 = LBOUND(InData%betaC,3), UBOUND(InData%betaC,3) + DO i2 = LBOUND(InData%betaC,2), UBOUND(InData%betaC,2) + DO i1 = LBOUND(InData%betaC,1), UBOUND(InData%betaC,1) + DbKiBuf(Db_Xferred) = InData%betaC(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Gi) ) 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%Gi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gi,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gi,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gi,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gi,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gi,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Gi,4), UBOUND(InData%Gi,4) + DO i3 = LBOUND(InData%Gi,3), UBOUND(InData%Gi,3) + DO i2 = LBOUND(InData%Gi,2), UBOUND(InData%Gi,2) + DO i1 = LBOUND(InData%Gi,1), UBOUND(InData%Gi,1) + DbKiBuf(Db_Xferred) = InData%Gi(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Ki) ) 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%Ki,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ki,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ki,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ki,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ki,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ki,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ki,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ki,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Ki,4), UBOUND(InData%Ki,4) + DO i3 = LBOUND(InData%Ki,3), UBOUND(InData%Ki,3) + DO i2 = LBOUND(InData%Ki,2), UBOUND(InData%Ki,2) + DO i1 = LBOUND(InData%Ki,1), UBOUND(InData%Ki,1) + DbKiBuf(Db_Xferred) = InData%Ki(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Mi) ) 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%Mi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mi,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mi,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mi,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mi,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mi,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Mi,4), UBOUND(InData%Mi,4) + DO i3 = LBOUND(InData%Mi,3), UBOUND(InData%Mi,3) + DO i2 = LBOUND(InData%Mi,2), UBOUND(InData%Mi,2) + DO i1 = LBOUND(InData%Mi,1), UBOUND(InData%Mi,1) + DbKiBuf(Db_Xferred) = InData%Mi(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Oe) ) 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%Oe,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Oe,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Oe,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Oe,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Oe,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Oe,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Oe,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Oe,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Oe,4), UBOUND(InData%Oe,4) + DO i3 = LBOUND(InData%Oe,3), UBOUND(InData%Oe,3) + DO i2 = LBOUND(InData%Oe,2), UBOUND(InData%Oe,2) + DO i1 = LBOUND(InData%Oe,1), UBOUND(InData%Oe,1) + DbKiBuf(Db_Xferred) = InData%Oe(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pe) ) 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%Pe,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pe,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pe,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pe,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pe,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pe,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pe,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pe,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Pe,4), UBOUND(InData%Pe,4) + DO i3 = LBOUND(InData%Pe,3), UBOUND(InData%Pe,3) + DO i2 = LBOUND(InData%Pe,2), UBOUND(InData%Pe,2) + DO i1 = LBOUND(InData%Pe,1), UBOUND(InData%Pe,1) + DbKiBuf(Db_Xferred) = InData%Pe(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Qe) ) 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%Qe,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qe,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qe,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qe,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qe,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qe,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qe,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qe,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Qe,4), UBOUND(InData%Qe,4) + DO i3 = LBOUND(InData%Qe,3), UBOUND(InData%Qe,3) + DO i2 = LBOUND(InData%Qe,2), UBOUND(InData%Qe,2) + DO i1 = LBOUND(InData%Qe,1), UBOUND(InData%Qe,1) + DbKiBuf(Db_Xferred) = InData%Qe(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Gd) ) 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%Gd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Gd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Gd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Gd,4), UBOUND(InData%Gd,4) + DO i3 = LBOUND(InData%Gd,3), UBOUND(InData%Gd,3) + DO i2 = LBOUND(InData%Gd,2), UBOUND(InData%Gd,2) + DO i1 = LBOUND(InData%Gd,1), UBOUND(InData%Gd,1) + DbKiBuf(Db_Xferred) = InData%Gd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Od) ) 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%Od,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Od,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Od,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Od,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Od,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Od,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Od,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Od,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Od,4), UBOUND(InData%Od,4) + DO i3 = LBOUND(InData%Od,3), UBOUND(InData%Od,3) + DO i2 = LBOUND(InData%Od,2), UBOUND(InData%Od,2) + DO i1 = LBOUND(InData%Od,1), UBOUND(InData%Od,1) + DbKiBuf(Db_Xferred) = InData%Od(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Pd) ) 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%Pd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Pd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Pd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Pd,4), UBOUND(InData%Pd,4) + DO i3 = LBOUND(InData%Pd,3), UBOUND(InData%Pd,3) + DO i2 = LBOUND(InData%Pd,2), UBOUND(InData%Pd,2) + DO i1 = LBOUND(InData%Pd,1), UBOUND(InData%Pd,1) + DbKiBuf(Db_Xferred) = InData%Pd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Qd) ) 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%Qd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Qd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Qd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Qd,4), UBOUND(InData%Qd,4) + DO i3 = LBOUND(InData%Qd,3), UBOUND(InData%Qd,3) + DO i2 = LBOUND(InData%Qd,2), UBOUND(InData%Qd,2) + DO i1 = LBOUND(InData%Qd,1), UBOUND(InData%Qd,1) + DbKiBuf(Db_Xferred) = InData%Qd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Sd) ) 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%Sd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Sd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Sd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Sd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Sd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Sd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Sd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Sd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Sd,4), UBOUND(InData%Sd,4) + DO i3 = LBOUND(InData%Sd,3), UBOUND(InData%Sd,3) + DO i2 = LBOUND(InData%Sd,2), UBOUND(InData%Sd,2) + DO i1 = LBOUND(InData%Sd,1), UBOUND(InData%Sd,1) + DbKiBuf(Db_Xferred) = InData%Sd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Xd) ) 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%Xd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Xd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Xd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Xd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Xd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Xd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Xd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Xd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Xd,4), UBOUND(InData%Xd,4) + DO i3 = LBOUND(InData%Xd,3), UBOUND(InData%Xd,3) + DO i2 = LBOUND(InData%Xd,2), UBOUND(InData%Xd,2) + DO i1 = LBOUND(InData%Xd,1), UBOUND(InData%Xd,1) + DbKiBuf(Db_Xferred) = InData%Xd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Yd) ) 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%Yd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Yd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Yd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Yd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Yd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Yd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Yd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Yd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Yd,4), UBOUND(InData%Yd,4) + DO i3 = LBOUND(InData%Yd,3), UBOUND(InData%Yd,3) + DO i2 = LBOUND(InData%Yd,2), UBOUND(InData%Yd,2) + DO i1 = LBOUND(InData%Yd,1), UBOUND(InData%Yd,1) + DbKiBuf(Db_Xferred) = InData%Yd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + END SUBROUTINE BD_PackEqMotionQP + + SUBROUTINE BD_UnPackEqMotionQP( 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(EqMotionQP), 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 = 'BD_UnPackEqMotionQP' + ! 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 ! uuu 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%uuu)) DEALLOCATE(OutData%uuu) + ALLOCATE(OutData%uuu(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%uuu.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%uuu,3), UBOUND(OutData%uuu,3) + DO i2 = LBOUND(OutData%uuu,2), UBOUND(OutData%uuu,2) + DO i1 = LBOUND(OutData%uuu,1), UBOUND(OutData%uuu,1) + OutData%uuu(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! uup 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%uup)) DEALLOCATE(OutData%uup) + ALLOCATE(OutData%uup(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%uup.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%uup,3), UBOUND(OutData%uup,3) + DO i2 = LBOUND(OutData%uup,2), UBOUND(OutData%uup,2) + DO i1 = LBOUND(OutData%uup,1), UBOUND(OutData%uup,1) + OutData%uup(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! vvv 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%vvv)) DEALLOCATE(OutData%vvv) + ALLOCATE(OutData%vvv(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%vvv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%vvv,3), UBOUND(OutData%vvv,3) + DO i2 = LBOUND(OutData%vvv,2), UBOUND(OutData%vvv,2) + DO i1 = LBOUND(OutData%vvv,1), UBOUND(OutData%vvv,1) + OutData%vvv(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! vvp 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%vvp)) DEALLOCATE(OutData%vvp) + ALLOCATE(OutData%vvp(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%vvp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%vvp,3), UBOUND(OutData%vvp,3) + DO i2 = LBOUND(OutData%vvp,2), UBOUND(OutData%vvp,2) + DO i1 = LBOUND(OutData%vvp,1), UBOUND(OutData%vvp,1) + OutData%vvp(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! aaa 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%aaa)) DEALLOCATE(OutData%aaa) + ALLOCATE(OutData%aaa(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%aaa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%aaa,3), UBOUND(OutData%aaa,3) + DO i2 = LBOUND(OutData%aaa,2), UBOUND(OutData%aaa,2) + DO i1 = LBOUND(OutData%aaa,1), UBOUND(OutData%aaa,1) + OutData%aaa(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RR0 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%RR0)) DEALLOCATE(OutData%RR0) + ALLOCATE(OutData%RR0(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%RR0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%RR0,4), UBOUND(OutData%RR0,4) + DO i3 = LBOUND(OutData%RR0,3), UBOUND(OutData%RR0,3) + DO i2 = LBOUND(OutData%RR0,2), UBOUND(OutData%RR0,2) + DO i1 = LBOUND(OutData%RR0,1), UBOUND(OutData%RR0,1) + OutData%RR0(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! kappa 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%kappa)) DEALLOCATE(OutData%kappa) + ALLOCATE(OutData%kappa(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%kappa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%kappa,3), UBOUND(OutData%kappa,3) + DO i2 = LBOUND(OutData%kappa,2), UBOUND(OutData%kappa,2) + DO i1 = LBOUND(OutData%kappa,1), UBOUND(OutData%kappa,1) + OutData%kappa(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! E1 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%E1)) DEALLOCATE(OutData%E1) + ALLOCATE(OutData%E1(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%E1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%E1,3), UBOUND(OutData%E1,3) + DO i2 = LBOUND(OutData%E1,2), UBOUND(OutData%E1,2) + DO i1 = LBOUND(OutData%E1,1), UBOUND(OutData%E1,1) + OutData%E1(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Stif 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%Stif)) DEALLOCATE(OutData%Stif) + ALLOCATE(OutData%Stif(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%Stif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Stif,4), UBOUND(OutData%Stif,4) + DO i3 = LBOUND(OutData%Stif,3), UBOUND(OutData%Stif,3) + DO i2 = LBOUND(OutData%Stif,2), UBOUND(OutData%Stif,2) + DO i1 = LBOUND(OutData%Stif,1), UBOUND(OutData%Stif,1) + OutData%Stif(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fb 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%Fb)) DEALLOCATE(OutData%Fb) + ALLOCATE(OutData%Fb(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%Fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fb,3), UBOUND(OutData%Fb,3) + DO i2 = LBOUND(OutData%Fb,2), UBOUND(OutData%Fb,2) + DO i1 = LBOUND(OutData%Fb,1), UBOUND(OutData%Fb,1) + OutData%Fb(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fc 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%Fc)) DEALLOCATE(OutData%Fc) + ALLOCATE(OutData%Fc(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%Fc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fc,3), UBOUND(OutData%Fc,3) + DO i2 = LBOUND(OutData%Fc,2), UBOUND(OutData%Fc,2) + DO i1 = LBOUND(OutData%Fc,1), UBOUND(OutData%Fc,1) + OutData%Fc(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fd 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%Fd)) DEALLOCATE(OutData%Fd) + ALLOCATE(OutData%Fd(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%Fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fd,3), UBOUND(OutData%Fd,3) + DO i2 = LBOUND(OutData%Fd,2), UBOUND(OutData%Fd,2) + DO i1 = LBOUND(OutData%Fd,1), UBOUND(OutData%Fd,1) + OutData%Fd(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg 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%Fg)) DEALLOCATE(OutData%Fg) + ALLOCATE(OutData%Fg(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%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fg,3), UBOUND(OutData%Fg,3) + DO i2 = LBOUND(OutData%Fg,2), UBOUND(OutData%Fg,2) + DO i1 = LBOUND(OutData%Fg,1), UBOUND(OutData%Fg,1) + OutData%Fg(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fi 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%Fi)) DEALLOCATE(OutData%Fi) + ALLOCATE(OutData%Fi(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%Fi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fi,3), UBOUND(OutData%Fi,3) + DO i2 = LBOUND(OutData%Fi,2), UBOUND(OutData%Fi,2) + DO i1 = LBOUND(OutData%Fi,1), UBOUND(OutData%Fi,1) + OutData%Fi(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ftemp 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%Ftemp)) DEALLOCATE(OutData%Ftemp) + ALLOCATE(OutData%Ftemp(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%Ftemp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Ftemp,3), UBOUND(OutData%Ftemp,3) + DO i2 = LBOUND(OutData%Ftemp,2), UBOUND(OutData%Ftemp,2) + DO i1 = LBOUND(OutData%Ftemp,1), UBOUND(OutData%Ftemp,1) + OutData%Ftemp(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RR0mEta 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%RR0mEta)) DEALLOCATE(OutData%RR0mEta) + ALLOCATE(OutData%RR0mEta(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%RR0mEta.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%RR0mEta,3), UBOUND(OutData%RR0mEta,3) + DO i2 = LBOUND(OutData%RR0mEta,2), UBOUND(OutData%RR0mEta,2) + DO i1 = LBOUND(OutData%RR0mEta,1), UBOUND(OutData%RR0mEta,1) + OutData%RR0mEta(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rho 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%rho)) DEALLOCATE(OutData%rho) + ALLOCATE(OutData%rho(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%rho.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%rho,4), UBOUND(OutData%rho,4) + DO i3 = LBOUND(OutData%rho,3), UBOUND(OutData%rho,3) + DO i2 = LBOUND(OutData%rho,2), UBOUND(OutData%rho,2) + DO i1 = LBOUND(OutData%rho,1), UBOUND(OutData%rho,1) + OutData%rho(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! betaC 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%betaC)) DEALLOCATE(OutData%betaC) + ALLOCATE(OutData%betaC(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%betaC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%betaC,4), UBOUND(OutData%betaC,4) + DO i3 = LBOUND(OutData%betaC,3), UBOUND(OutData%betaC,3) + DO i2 = LBOUND(OutData%betaC,2), UBOUND(OutData%betaC,2) + DO i1 = LBOUND(OutData%betaC,1), UBOUND(OutData%betaC,1) + OutData%betaC(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gi 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%Gi)) DEALLOCATE(OutData%Gi) + ALLOCATE(OutData%Gi(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%Gi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Gi,4), UBOUND(OutData%Gi,4) + DO i3 = LBOUND(OutData%Gi,3), UBOUND(OutData%Gi,3) + DO i2 = LBOUND(OutData%Gi,2), UBOUND(OutData%Gi,2) + DO i1 = LBOUND(OutData%Gi,1), UBOUND(OutData%Gi,1) + OutData%Gi(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ki 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%Ki)) DEALLOCATE(OutData%Ki) + ALLOCATE(OutData%Ki(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%Ki.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Ki,4), UBOUND(OutData%Ki,4) + DO i3 = LBOUND(OutData%Ki,3), UBOUND(OutData%Ki,3) + DO i2 = LBOUND(OutData%Ki,2), UBOUND(OutData%Ki,2) + DO i1 = LBOUND(OutData%Ki,1), UBOUND(OutData%Ki,1) + OutData%Ki(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Mi 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%Mi)) DEALLOCATE(OutData%Mi) + ALLOCATE(OutData%Mi(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%Mi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Mi,4), UBOUND(OutData%Mi,4) + DO i3 = LBOUND(OutData%Mi,3), UBOUND(OutData%Mi,3) + DO i2 = LBOUND(OutData%Mi,2), UBOUND(OutData%Mi,2) + DO i1 = LBOUND(OutData%Mi,1), UBOUND(OutData%Mi,1) + OutData%Mi(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Oe 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%Oe)) DEALLOCATE(OutData%Oe) + ALLOCATE(OutData%Oe(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%Oe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Oe,4), UBOUND(OutData%Oe,4) + DO i3 = LBOUND(OutData%Oe,3), UBOUND(OutData%Oe,3) + DO i2 = LBOUND(OutData%Oe,2), UBOUND(OutData%Oe,2) + DO i1 = LBOUND(OutData%Oe,1), UBOUND(OutData%Oe,1) + OutData%Oe(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pe 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%Pe)) DEALLOCATE(OutData%Pe) + ALLOCATE(OutData%Pe(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%Pe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Pe,4), UBOUND(OutData%Pe,4) + DO i3 = LBOUND(OutData%Pe,3), UBOUND(OutData%Pe,3) + DO i2 = LBOUND(OutData%Pe,2), UBOUND(OutData%Pe,2) + DO i1 = LBOUND(OutData%Pe,1), UBOUND(OutData%Pe,1) + OutData%Pe(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Qe 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%Qe)) DEALLOCATE(OutData%Qe) + ALLOCATE(OutData%Qe(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%Qe.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Qe,4), UBOUND(OutData%Qe,4) + DO i3 = LBOUND(OutData%Qe,3), UBOUND(OutData%Qe,3) + DO i2 = LBOUND(OutData%Qe,2), UBOUND(OutData%Qe,2) + DO i1 = LBOUND(OutData%Qe,1), UBOUND(OutData%Qe,1) + OutData%Qe(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Gd 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%Gd)) DEALLOCATE(OutData%Gd) + ALLOCATE(OutData%Gd(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%Gd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Gd,4), UBOUND(OutData%Gd,4) + DO i3 = LBOUND(OutData%Gd,3), UBOUND(OutData%Gd,3) + DO i2 = LBOUND(OutData%Gd,2), UBOUND(OutData%Gd,2) + DO i1 = LBOUND(OutData%Gd,1), UBOUND(OutData%Gd,1) + OutData%Gd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Od 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%Od)) DEALLOCATE(OutData%Od) + ALLOCATE(OutData%Od(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%Od.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Od,4), UBOUND(OutData%Od,4) + DO i3 = LBOUND(OutData%Od,3), UBOUND(OutData%Od,3) + DO i2 = LBOUND(OutData%Od,2), UBOUND(OutData%Od,2) + DO i1 = LBOUND(OutData%Od,1), UBOUND(OutData%Od,1) + OutData%Od(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Pd 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%Pd)) DEALLOCATE(OutData%Pd) + ALLOCATE(OutData%Pd(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%Pd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Pd,4), UBOUND(OutData%Pd,4) + DO i3 = LBOUND(OutData%Pd,3), UBOUND(OutData%Pd,3) + DO i2 = LBOUND(OutData%Pd,2), UBOUND(OutData%Pd,2) + DO i1 = LBOUND(OutData%Pd,1), UBOUND(OutData%Pd,1) + OutData%Pd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Qd 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%Qd)) DEALLOCATE(OutData%Qd) + ALLOCATE(OutData%Qd(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%Qd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Qd,4), UBOUND(OutData%Qd,4) + DO i3 = LBOUND(OutData%Qd,3), UBOUND(OutData%Qd,3) + DO i2 = LBOUND(OutData%Qd,2), UBOUND(OutData%Qd,2) + DO i1 = LBOUND(OutData%Qd,1), UBOUND(OutData%Qd,1) + OutData%Qd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Sd 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%Sd)) DEALLOCATE(OutData%Sd) + ALLOCATE(OutData%Sd(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%Sd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Sd,4), UBOUND(OutData%Sd,4) + DO i3 = LBOUND(OutData%Sd,3), UBOUND(OutData%Sd,3) + DO i2 = LBOUND(OutData%Sd,2), UBOUND(OutData%Sd,2) + DO i1 = LBOUND(OutData%Sd,1), UBOUND(OutData%Sd,1) + OutData%Sd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Xd 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%Xd)) DEALLOCATE(OutData%Xd) + ALLOCATE(OutData%Xd(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%Xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Xd,4), UBOUND(OutData%Xd,4) + DO i3 = LBOUND(OutData%Xd,3), UBOUND(OutData%Xd,3) + DO i2 = LBOUND(OutData%Xd,2), UBOUND(OutData%Xd,2) + DO i1 = LBOUND(OutData%Xd,1), UBOUND(OutData%Xd,1) + OutData%Xd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Yd 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%Yd)) DEALLOCATE(OutData%Yd) + ALLOCATE(OutData%Yd(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%Yd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Yd,4), UBOUND(OutData%Yd,4) + DO i3 = LBOUND(OutData%Yd,3), UBOUND(OutData%Yd,3) + DO i2 = LBOUND(OutData%Yd,2), UBOUND(OutData%Yd,2) + DO i1 = LBOUND(OutData%Yd,1), UBOUND(OutData%Yd,1) + OutData%Yd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + END SUBROUTINE BD_UnPackEqMotionQP + + SUBROUTINE BD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BD_MiscVarType), INTENT(INOUT) :: SrcMiscData + TYPE(BD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcMiscData%u_DistrLoad_at_y, DstMiscData%u_DistrLoad_at_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcMiscData%y_BldMotion_at_u, DstMiscData%y_BldMotion_at_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Map_u_DistrLoad_to_y, DstMiscData%Map_u_DistrLoad_to_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Map_y_BldMotion_to_u, DstMiscData%Map_y_BldMotion_to_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%Un_Sum = SrcMiscData%Un_Sum + CALL BD_Copyeqmotionqp( SrcMiscData%qp, DstMiscData%qp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMiscData%lin_A)) THEN + i1_l = LBOUND(SrcMiscData%lin_A,1) + i1_u = UBOUND(SrcMiscData%lin_A,1) + i2_l = LBOUND(SrcMiscData%lin_A,2) + i2_u = UBOUND(SrcMiscData%lin_A,2) + IF (.NOT. ALLOCATED(DstMiscData%lin_A)) THEN + ALLOCATE(DstMiscData%lin_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%lin_A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%lin_A = SrcMiscData%lin_A +ENDIF +IF (ALLOCATED(SrcMiscData%lin_C)) THEN + i1_l = LBOUND(SrcMiscData%lin_C,1) + i1_u = UBOUND(SrcMiscData%lin_C,1) + i2_l = LBOUND(SrcMiscData%lin_C,2) + i2_u = UBOUND(SrcMiscData%lin_C,2) + IF (.NOT. ALLOCATED(DstMiscData%lin_C)) THEN + ALLOCATE(DstMiscData%lin_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%lin_C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%lin_C = SrcMiscData%lin_C +ENDIF +IF (ALLOCATED(SrcMiscData%Nrrr)) THEN + i1_l = LBOUND(SrcMiscData%Nrrr,1) + i1_u = UBOUND(SrcMiscData%Nrrr,1) + i2_l = LBOUND(SrcMiscData%Nrrr,2) + i2_u = UBOUND(SrcMiscData%Nrrr,2) + i3_l = LBOUND(SrcMiscData%Nrrr,3) + i3_u = UBOUND(SrcMiscData%Nrrr,3) + IF (.NOT. ALLOCATED(DstMiscData%Nrrr)) THEN + ALLOCATE(DstMiscData%Nrrr(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Nrrr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Nrrr = SrcMiscData%Nrrr +ENDIF +IF (ALLOCATED(SrcMiscData%elf)) THEN + i1_l = LBOUND(SrcMiscData%elf,1) + i1_u = UBOUND(SrcMiscData%elf,1) + i2_l = LBOUND(SrcMiscData%elf,2) + i2_u = UBOUND(SrcMiscData%elf,2) + IF (.NOT. ALLOCATED(DstMiscData%elf)) THEN + ALLOCATE(DstMiscData%elf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%elf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%elf = SrcMiscData%elf +ENDIF +IF (ALLOCATED(SrcMiscData%EFint)) THEN + i1_l = LBOUND(SrcMiscData%EFint,1) + i1_u = UBOUND(SrcMiscData%EFint,1) + i2_l = LBOUND(SrcMiscData%EFint,2) + i2_u = UBOUND(SrcMiscData%EFint,2) + i3_l = LBOUND(SrcMiscData%EFint,3) + i3_u = UBOUND(SrcMiscData%EFint,3) + IF (.NOT. ALLOCATED(DstMiscData%EFint)) THEN + ALLOCATE(DstMiscData%EFint(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%EFint.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%EFint = SrcMiscData%EFint +ENDIF +IF (ALLOCATED(SrcMiscData%elk)) THEN + i1_l = LBOUND(SrcMiscData%elk,1) + i1_u = UBOUND(SrcMiscData%elk,1) + i2_l = LBOUND(SrcMiscData%elk,2) + i2_u = UBOUND(SrcMiscData%elk,2) + i3_l = LBOUND(SrcMiscData%elk,3) + i3_u = UBOUND(SrcMiscData%elk,3) + i4_l = LBOUND(SrcMiscData%elk,4) + i4_u = UBOUND(SrcMiscData%elk,4) + IF (.NOT. ALLOCATED(DstMiscData%elk)) THEN + ALLOCATE(DstMiscData%elk(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 DstMiscData%elk.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%elk = SrcMiscData%elk +ENDIF +IF (ALLOCATED(SrcMiscData%elg)) THEN + i1_l = LBOUND(SrcMiscData%elg,1) + i1_u = UBOUND(SrcMiscData%elg,1) + i2_l = LBOUND(SrcMiscData%elg,2) + i2_u = UBOUND(SrcMiscData%elg,2) + i3_l = LBOUND(SrcMiscData%elg,3) + i3_u = UBOUND(SrcMiscData%elg,3) + i4_l = LBOUND(SrcMiscData%elg,4) + i4_u = UBOUND(SrcMiscData%elg,4) + IF (.NOT. ALLOCATED(DstMiscData%elg)) THEN + ALLOCATE(DstMiscData%elg(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 DstMiscData%elg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%elg = SrcMiscData%elg +ENDIF +IF (ALLOCATED(SrcMiscData%elm)) THEN + i1_l = LBOUND(SrcMiscData%elm,1) + i1_u = UBOUND(SrcMiscData%elm,1) + i2_l = LBOUND(SrcMiscData%elm,2) + i2_u = UBOUND(SrcMiscData%elm,2) + i3_l = LBOUND(SrcMiscData%elm,3) + i3_u = UBOUND(SrcMiscData%elm,3) + i4_l = LBOUND(SrcMiscData%elm,4) + i4_u = UBOUND(SrcMiscData%elm,4) + IF (.NOT. ALLOCATED(DstMiscData%elm)) THEN + ALLOCATE(DstMiscData%elm(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 DstMiscData%elm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%elm = SrcMiscData%elm +ENDIF +IF (ALLOCATED(SrcMiscData%DistrLoad_QP)) THEN + i1_l = LBOUND(SrcMiscData%DistrLoad_QP,1) + i1_u = UBOUND(SrcMiscData%DistrLoad_QP,1) + i2_l = LBOUND(SrcMiscData%DistrLoad_QP,2) + i2_u = UBOUND(SrcMiscData%DistrLoad_QP,2) + i3_l = LBOUND(SrcMiscData%DistrLoad_QP,3) + i3_u = UBOUND(SrcMiscData%DistrLoad_QP,3) + IF (.NOT. ALLOCATED(DstMiscData%DistrLoad_QP)) THEN + ALLOCATE(DstMiscData%DistrLoad_QP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%DistrLoad_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DistrLoad_QP = SrcMiscData%DistrLoad_QP +ENDIF +IF (ALLOCATED(SrcMiscData%PointLoadLcl)) THEN + i1_l = LBOUND(SrcMiscData%PointLoadLcl,1) + i1_u = UBOUND(SrcMiscData%PointLoadLcl,1) + i2_l = LBOUND(SrcMiscData%PointLoadLcl,2) + i2_u = UBOUND(SrcMiscData%PointLoadLcl,2) + IF (.NOT. ALLOCATED(DstMiscData%PointLoadLcl)) THEN + ALLOCATE(DstMiscData%PointLoadLcl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%PointLoadLcl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%PointLoadLcl = SrcMiscData%PointLoadLcl +ENDIF +IF (ALLOCATED(SrcMiscData%StifK)) THEN + i1_l = LBOUND(SrcMiscData%StifK,1) + i1_u = UBOUND(SrcMiscData%StifK,1) + i2_l = LBOUND(SrcMiscData%StifK,2) + i2_u = UBOUND(SrcMiscData%StifK,2) + i3_l = LBOUND(SrcMiscData%StifK,3) + i3_u = UBOUND(SrcMiscData%StifK,3) + i4_l = LBOUND(SrcMiscData%StifK,4) + i4_u = UBOUND(SrcMiscData%StifK,4) + IF (.NOT. ALLOCATED(DstMiscData%StifK)) THEN + ALLOCATE(DstMiscData%StifK(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 DstMiscData%StifK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%StifK = SrcMiscData%StifK +ENDIF +IF (ALLOCATED(SrcMiscData%MassM)) THEN + i1_l = LBOUND(SrcMiscData%MassM,1) + i1_u = UBOUND(SrcMiscData%MassM,1) + i2_l = LBOUND(SrcMiscData%MassM,2) + i2_u = UBOUND(SrcMiscData%MassM,2) + i3_l = LBOUND(SrcMiscData%MassM,3) + i3_u = UBOUND(SrcMiscData%MassM,3) + i4_l = LBOUND(SrcMiscData%MassM,4) + i4_u = UBOUND(SrcMiscData%MassM,4) + IF (.NOT. ALLOCATED(DstMiscData%MassM)) THEN + ALLOCATE(DstMiscData%MassM(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 DstMiscData%MassM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%MassM = SrcMiscData%MassM +ENDIF +IF (ALLOCATED(SrcMiscData%DampG)) THEN + i1_l = LBOUND(SrcMiscData%DampG,1) + i1_u = UBOUND(SrcMiscData%DampG,1) + i2_l = LBOUND(SrcMiscData%DampG,2) + i2_u = UBOUND(SrcMiscData%DampG,2) + i3_l = LBOUND(SrcMiscData%DampG,3) + i3_u = UBOUND(SrcMiscData%DampG,3) + i4_l = LBOUND(SrcMiscData%DampG,4) + i4_u = UBOUND(SrcMiscData%DampG,4) + IF (.NOT. ALLOCATED(DstMiscData%DampG)) THEN + ALLOCATE(DstMiscData%DampG(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 DstMiscData%DampG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DampG = SrcMiscData%DampG +ENDIF +IF (ALLOCATED(SrcMiscData%StifK_fd)) THEN + i1_l = LBOUND(SrcMiscData%StifK_fd,1) + i1_u = UBOUND(SrcMiscData%StifK_fd,1) + i2_l = LBOUND(SrcMiscData%StifK_fd,2) + i2_u = UBOUND(SrcMiscData%StifK_fd,2) + i3_l = LBOUND(SrcMiscData%StifK_fd,3) + i3_u = UBOUND(SrcMiscData%StifK_fd,3) + i4_l = LBOUND(SrcMiscData%StifK_fd,4) + i4_u = UBOUND(SrcMiscData%StifK_fd,4) + IF (.NOT. ALLOCATED(DstMiscData%StifK_fd)) THEN + ALLOCATE(DstMiscData%StifK_fd(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 DstMiscData%StifK_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%StifK_fd = SrcMiscData%StifK_fd +ENDIF +IF (ALLOCATED(SrcMiscData%MassM_fd)) THEN + i1_l = LBOUND(SrcMiscData%MassM_fd,1) + i1_u = UBOUND(SrcMiscData%MassM_fd,1) + i2_l = LBOUND(SrcMiscData%MassM_fd,2) + i2_u = UBOUND(SrcMiscData%MassM_fd,2) + i3_l = LBOUND(SrcMiscData%MassM_fd,3) + i3_u = UBOUND(SrcMiscData%MassM_fd,3) + i4_l = LBOUND(SrcMiscData%MassM_fd,4) + i4_u = UBOUND(SrcMiscData%MassM_fd,4) + IF (.NOT. ALLOCATED(DstMiscData%MassM_fd)) THEN + ALLOCATE(DstMiscData%MassM_fd(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 DstMiscData%MassM_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%MassM_fd = SrcMiscData%MassM_fd +ENDIF +IF (ALLOCATED(SrcMiscData%DampG_fd)) THEN + i1_l = LBOUND(SrcMiscData%DampG_fd,1) + i1_u = UBOUND(SrcMiscData%DampG_fd,1) + i2_l = LBOUND(SrcMiscData%DampG_fd,2) + i2_u = UBOUND(SrcMiscData%DampG_fd,2) + i3_l = LBOUND(SrcMiscData%DampG_fd,3) + i3_u = UBOUND(SrcMiscData%DampG_fd,3) + i4_l = LBOUND(SrcMiscData%DampG_fd,4) + i4_u = UBOUND(SrcMiscData%DampG_fd,4) + IF (.NOT. ALLOCATED(DstMiscData%DampG_fd)) THEN + ALLOCATE(DstMiscData%DampG_fd(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 DstMiscData%DampG_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DampG_fd = SrcMiscData%DampG_fd +ENDIF +IF (ALLOCATED(SrcMiscData%RHS)) THEN + i1_l = LBOUND(SrcMiscData%RHS,1) + i1_u = UBOUND(SrcMiscData%RHS,1) + i2_l = LBOUND(SrcMiscData%RHS,2) + i2_u = UBOUND(SrcMiscData%RHS,2) + IF (.NOT. ALLOCATED(DstMiscData%RHS)) THEN + ALLOCATE(DstMiscData%RHS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%RHS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%RHS = SrcMiscData%RHS +ENDIF +IF (ALLOCATED(SrcMiscData%RHS_p)) THEN + i1_l = LBOUND(SrcMiscData%RHS_p,1) + i1_u = UBOUND(SrcMiscData%RHS_p,1) + i2_l = LBOUND(SrcMiscData%RHS_p,2) + i2_u = UBOUND(SrcMiscData%RHS_p,2) + IF (.NOT. ALLOCATED(DstMiscData%RHS_p)) THEN + ALLOCATE(DstMiscData%RHS_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%RHS_p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%RHS_p = SrcMiscData%RHS_p +ENDIF +IF (ALLOCATED(SrcMiscData%RHS_m)) THEN + i1_l = LBOUND(SrcMiscData%RHS_m,1) + i1_u = UBOUND(SrcMiscData%RHS_m,1) + i2_l = LBOUND(SrcMiscData%RHS_m,2) + i2_u = UBOUND(SrcMiscData%RHS_m,2) + IF (.NOT. ALLOCATED(DstMiscData%RHS_m)) THEN + ALLOCATE(DstMiscData%RHS_m(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%RHS_m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%RHS_m = SrcMiscData%RHS_m +ENDIF +IF (ALLOCATED(SrcMiscData%BldInternalForceFE)) THEN + i1_l = LBOUND(SrcMiscData%BldInternalForceFE,1) + i1_u = UBOUND(SrcMiscData%BldInternalForceFE,1) + i2_l = LBOUND(SrcMiscData%BldInternalForceFE,2) + i2_u = UBOUND(SrcMiscData%BldInternalForceFE,2) + IF (.NOT. ALLOCATED(DstMiscData%BldInternalForceFE)) THEN + ALLOCATE(DstMiscData%BldInternalForceFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BldInternalForceFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BldInternalForceFE = SrcMiscData%BldInternalForceFE +ENDIF +IF (ALLOCATED(SrcMiscData%BldInternalForceQP)) THEN + i1_l = LBOUND(SrcMiscData%BldInternalForceQP,1) + i1_u = UBOUND(SrcMiscData%BldInternalForceQP,1) + i2_l = LBOUND(SrcMiscData%BldInternalForceQP,2) + i2_u = UBOUND(SrcMiscData%BldInternalForceQP,2) + IF (.NOT. ALLOCATED(DstMiscData%BldInternalForceQP)) THEN + ALLOCATE(DstMiscData%BldInternalForceQP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%BldInternalForceQP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%BldInternalForceQP = SrcMiscData%BldInternalForceQP +ENDIF +IF (ALLOCATED(SrcMiscData%FirstNodeReactionLclForceMoment)) THEN + i1_l = LBOUND(SrcMiscData%FirstNodeReactionLclForceMoment,1) + i1_u = UBOUND(SrcMiscData%FirstNodeReactionLclForceMoment,1) + IF (.NOT. ALLOCATED(DstMiscData%FirstNodeReactionLclForceMoment)) THEN + ALLOCATE(DstMiscData%FirstNodeReactionLclForceMoment(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FirstNodeReactionLclForceMoment.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FirstNodeReactionLclForceMoment = SrcMiscData%FirstNodeReactionLclForceMoment +ENDIF +IF (ALLOCATED(SrcMiscData%Solution)) THEN + i1_l = LBOUND(SrcMiscData%Solution,1) + i1_u = UBOUND(SrcMiscData%Solution,1) + i2_l = LBOUND(SrcMiscData%Solution,2) + i2_u = UBOUND(SrcMiscData%Solution,2) + IF (.NOT. ALLOCATED(DstMiscData%Solution)) THEN + ALLOCATE(DstMiscData%Solution(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Solution.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Solution = SrcMiscData%Solution +ENDIF +IF (ALLOCATED(SrcMiscData%LP_StifK)) THEN + i1_l = LBOUND(SrcMiscData%LP_StifK,1) + i1_u = UBOUND(SrcMiscData%LP_StifK,1) + i2_l = LBOUND(SrcMiscData%LP_StifK,2) + i2_u = UBOUND(SrcMiscData%LP_StifK,2) + IF (.NOT. ALLOCATED(DstMiscData%LP_StifK)) THEN + ALLOCATE(DstMiscData%LP_StifK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_StifK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_StifK = SrcMiscData%LP_StifK +ENDIF +IF (ALLOCATED(SrcMiscData%LP_MassM)) THEN + i1_l = LBOUND(SrcMiscData%LP_MassM,1) + i1_u = UBOUND(SrcMiscData%LP_MassM,1) + i2_l = LBOUND(SrcMiscData%LP_MassM,2) + i2_u = UBOUND(SrcMiscData%LP_MassM,2) + IF (.NOT. ALLOCATED(DstMiscData%LP_MassM)) THEN + ALLOCATE(DstMiscData%LP_MassM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_MassM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_MassM = SrcMiscData%LP_MassM +ENDIF +IF (ALLOCATED(SrcMiscData%LP_MassM_LU)) THEN + i1_l = LBOUND(SrcMiscData%LP_MassM_LU,1) + i1_u = UBOUND(SrcMiscData%LP_MassM_LU,1) + i2_l = LBOUND(SrcMiscData%LP_MassM_LU,2) + i2_u = UBOUND(SrcMiscData%LP_MassM_LU,2) + IF (.NOT. ALLOCATED(DstMiscData%LP_MassM_LU)) THEN + ALLOCATE(DstMiscData%LP_MassM_LU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_MassM_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_MassM_LU = SrcMiscData%LP_MassM_LU +ENDIF +IF (ALLOCATED(SrcMiscData%LP_RHS)) THEN + i1_l = LBOUND(SrcMiscData%LP_RHS,1) + i1_u = UBOUND(SrcMiscData%LP_RHS,1) + IF (.NOT. ALLOCATED(DstMiscData%LP_RHS)) THEN + ALLOCATE(DstMiscData%LP_RHS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_RHS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_RHS = SrcMiscData%LP_RHS +ENDIF +IF (ALLOCATED(SrcMiscData%LP_StifK_LU)) THEN + i1_l = LBOUND(SrcMiscData%LP_StifK_LU,1) + i1_u = UBOUND(SrcMiscData%LP_StifK_LU,1) + i2_l = LBOUND(SrcMiscData%LP_StifK_LU,2) + i2_u = UBOUND(SrcMiscData%LP_StifK_LU,2) + IF (.NOT. ALLOCATED(DstMiscData%LP_StifK_LU)) THEN + ALLOCATE(DstMiscData%LP_StifK_LU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_StifK_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_StifK_LU = SrcMiscData%LP_StifK_LU +ENDIF +IF (ALLOCATED(SrcMiscData%LP_RHS_LU)) THEN + i1_l = LBOUND(SrcMiscData%LP_RHS_LU,1) + i1_u = UBOUND(SrcMiscData%LP_RHS_LU,1) + IF (.NOT. ALLOCATED(DstMiscData%LP_RHS_LU)) THEN + ALLOCATE(DstMiscData%LP_RHS_LU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_RHS_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_RHS_LU = SrcMiscData%LP_RHS_LU +ENDIF +IF (ALLOCATED(SrcMiscData%LP_indx)) THEN + i1_l = LBOUND(SrcMiscData%LP_indx,1) + i1_u = UBOUND(SrcMiscData%LP_indx,1) + IF (.NOT. ALLOCATED(DstMiscData%LP_indx)) THEN + ALLOCATE(DstMiscData%LP_indx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LP_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LP_indx = SrcMiscData%LP_indx +ENDIF + CALL BD_CopyInput( SrcMiscData%u, DstMiscData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL BD_CopyInput( SrcMiscData%u2, DstMiscData%u2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE BD_CopyMisc + + SUBROUTINE BD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(BD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'BD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( MiscData%u_DistrLoad_at_y, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%y_BldMotion_at_u, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Map_u_DistrLoad_to_y, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Map_y_BldMotion_to_u, ErrStat, ErrMsg ) + CALL BD_Destroyeqmotionqp( MiscData%qp, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%lin_A)) THEN + DEALLOCATE(MiscData%lin_A) +ENDIF +IF (ALLOCATED(MiscData%lin_C)) THEN + DEALLOCATE(MiscData%lin_C) +ENDIF +IF (ALLOCATED(MiscData%Nrrr)) THEN + DEALLOCATE(MiscData%Nrrr) +ENDIF +IF (ALLOCATED(MiscData%elf)) THEN + DEALLOCATE(MiscData%elf) +ENDIF +IF (ALLOCATED(MiscData%EFint)) THEN + DEALLOCATE(MiscData%EFint) +ENDIF +IF (ALLOCATED(MiscData%elk)) THEN + DEALLOCATE(MiscData%elk) +ENDIF +IF (ALLOCATED(MiscData%elg)) THEN + DEALLOCATE(MiscData%elg) +ENDIF +IF (ALLOCATED(MiscData%elm)) THEN + DEALLOCATE(MiscData%elm) +ENDIF +IF (ALLOCATED(MiscData%DistrLoad_QP)) THEN + DEALLOCATE(MiscData%DistrLoad_QP) +ENDIF +IF (ALLOCATED(MiscData%PointLoadLcl)) THEN + DEALLOCATE(MiscData%PointLoadLcl) +ENDIF +IF (ALLOCATED(MiscData%StifK)) THEN + DEALLOCATE(MiscData%StifK) +ENDIF +IF (ALLOCATED(MiscData%MassM)) THEN + DEALLOCATE(MiscData%MassM) +ENDIF +IF (ALLOCATED(MiscData%DampG)) THEN + DEALLOCATE(MiscData%DampG) +ENDIF +IF (ALLOCATED(MiscData%StifK_fd)) THEN + DEALLOCATE(MiscData%StifK_fd) +ENDIF +IF (ALLOCATED(MiscData%MassM_fd)) THEN + DEALLOCATE(MiscData%MassM_fd) +ENDIF +IF (ALLOCATED(MiscData%DampG_fd)) THEN + DEALLOCATE(MiscData%DampG_fd) +ENDIF +IF (ALLOCATED(MiscData%RHS)) THEN + DEALLOCATE(MiscData%RHS) +ENDIF +IF (ALLOCATED(MiscData%RHS_p)) THEN + DEALLOCATE(MiscData%RHS_p) +ENDIF +IF (ALLOCATED(MiscData%RHS_m)) THEN + DEALLOCATE(MiscData%RHS_m) +ENDIF +IF (ALLOCATED(MiscData%BldInternalForceFE)) THEN + DEALLOCATE(MiscData%BldInternalForceFE) +ENDIF +IF (ALLOCATED(MiscData%BldInternalForceQP)) THEN + DEALLOCATE(MiscData%BldInternalForceQP) +ENDIF +IF (ALLOCATED(MiscData%FirstNodeReactionLclForceMoment)) THEN + DEALLOCATE(MiscData%FirstNodeReactionLclForceMoment) +ENDIF +IF (ALLOCATED(MiscData%Solution)) THEN + DEALLOCATE(MiscData%Solution) +ENDIF +IF (ALLOCATED(MiscData%LP_StifK)) THEN + DEALLOCATE(MiscData%LP_StifK) +ENDIF +IF (ALLOCATED(MiscData%LP_MassM)) THEN + DEALLOCATE(MiscData%LP_MassM) +ENDIF +IF (ALLOCATED(MiscData%LP_MassM_LU)) THEN + DEALLOCATE(MiscData%LP_MassM_LU) +ENDIF +IF (ALLOCATED(MiscData%LP_RHS)) THEN + DEALLOCATE(MiscData%LP_RHS) +ENDIF +IF (ALLOCATED(MiscData%LP_StifK_LU)) THEN + DEALLOCATE(MiscData%LP_StifK_LU) +ENDIF +IF (ALLOCATED(MiscData%LP_RHS_LU)) THEN + DEALLOCATE(MiscData%LP_RHS_LU) +ENDIF +IF (ALLOCATED(MiscData%LP_indx)) THEN + DEALLOCATE(MiscData%LP_indx) +ENDIF + CALL BD_DestroyInput( MiscData%u, ErrStat, ErrMsg ) + CALL BD_DestroyInput( MiscData%u2, ErrStat, ErrMsg ) + END SUBROUTINE BD_DestroyMisc + + SUBROUTINE BD_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(BD_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 = 'BD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! u_DistrLoad_at_y: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_DistrLoad_at_y, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_DistrLoad_at_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_DistrLoad_at_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_DistrLoad_at_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_DistrLoad_at_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y_BldMotion_at_u: size of buffers for each call to pack subtype + CALL MeshPack( InData%y_BldMotion_at_u, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! y_BldMotion_at_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_BldMotion_at_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_BldMotion_at_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_BldMotion_at_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Map_u_DistrLoad_to_y: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Map_u_DistrLoad_to_y, ErrStat2, ErrMsg2, .TRUE. ) ! Map_u_DistrLoad_to_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Map_u_DistrLoad_to_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Map_u_DistrLoad_to_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Map_u_DistrLoad_to_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Map_y_BldMotion_to_u: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Map_y_BldMotion_to_u, ErrStat2, ErrMsg2, .TRUE. ) ! Map_y_BldMotion_to_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Map_y_BldMotion_to_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Map_y_BldMotion_to_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Map_y_BldMotion_to_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Un_Sum + Int_BufSz = Int_BufSz + 3 ! qp: size of buffers for each call to pack subtype + CALL BD_Packeqmotionqp( Re_Buf, Db_Buf, Int_Buf, InData%qp, ErrStat2, ErrMsg2, .TRUE. ) ! qp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! qp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! qp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! qp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! lin_A allocated yes/no + IF ( ALLOCATED(InData%lin_A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! lin_A upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%lin_A) ! lin_A + END IF + Int_BufSz = Int_BufSz + 1 ! lin_C allocated yes/no + IF ( ALLOCATED(InData%lin_C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! lin_C upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%lin_C) ! lin_C + END IF + Int_BufSz = Int_BufSz + 1 ! Nrrr allocated yes/no + IF ( ALLOCATED(InData%Nrrr) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Nrrr upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Nrrr) ! Nrrr + END IF + Int_BufSz = Int_BufSz + 1 ! elf allocated yes/no + IF ( ALLOCATED(InData%elf) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! elf upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%elf) ! elf + END IF + Int_BufSz = Int_BufSz + 1 ! EFint allocated yes/no + IF ( ALLOCATED(InData%EFint) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! EFint upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%EFint) ! EFint + END IF + Int_BufSz = Int_BufSz + 1 ! elk allocated yes/no + IF ( ALLOCATED(InData%elk) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! elk upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%elk) ! elk + END IF + Int_BufSz = Int_BufSz + 1 ! elg allocated yes/no + IF ( ALLOCATED(InData%elg) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! elg upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%elg) ! elg + END IF + Int_BufSz = Int_BufSz + 1 ! elm allocated yes/no + IF ( ALLOCATED(InData%elm) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! elm upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%elm) ! elm + END IF + Int_BufSz = Int_BufSz + 1 ! DistrLoad_QP allocated yes/no + IF ( ALLOCATED(InData%DistrLoad_QP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! DistrLoad_QP upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DistrLoad_QP) ! DistrLoad_QP + END IF + Int_BufSz = Int_BufSz + 1 ! PointLoadLcl allocated yes/no + IF ( ALLOCATED(InData%PointLoadLcl) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PointLoadLcl upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PointLoadLcl) ! PointLoadLcl + END IF + Int_BufSz = Int_BufSz + 1 ! StifK allocated yes/no + IF ( ALLOCATED(InData%StifK) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! StifK upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%StifK) ! StifK + END IF + Int_BufSz = Int_BufSz + 1 ! MassM allocated yes/no + IF ( ALLOCATED(InData%MassM) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! MassM upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%MassM) ! MassM + END IF + Int_BufSz = Int_BufSz + 1 ! DampG allocated yes/no + IF ( ALLOCATED(InData%DampG) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! DampG upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DampG) ! DampG + END IF + Int_BufSz = Int_BufSz + 1 ! StifK_fd allocated yes/no + IF ( ALLOCATED(InData%StifK_fd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! StifK_fd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%StifK_fd) ! StifK_fd + END IF + Int_BufSz = Int_BufSz + 1 ! MassM_fd allocated yes/no + IF ( ALLOCATED(InData%MassM_fd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! MassM_fd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%MassM_fd) ! MassM_fd + END IF + Int_BufSz = Int_BufSz + 1 ! DampG_fd allocated yes/no + IF ( ALLOCATED(InData%DampG_fd) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! DampG_fd upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DampG_fd) ! DampG_fd + END IF + Int_BufSz = Int_BufSz + 1 ! RHS allocated yes/no + IF ( ALLOCATED(InData%RHS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RHS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%RHS) ! RHS + END IF + Int_BufSz = Int_BufSz + 1 ! RHS_p allocated yes/no + IF ( ALLOCATED(InData%RHS_p) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RHS_p upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%RHS_p) ! RHS_p + END IF + Int_BufSz = Int_BufSz + 1 ! RHS_m allocated yes/no + IF ( ALLOCATED(InData%RHS_m) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RHS_m upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%RHS_m) ! RHS_m + END IF + Int_BufSz = Int_BufSz + 1 ! BldInternalForceFE allocated yes/no + IF ( ALLOCATED(InData%BldInternalForceFE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldInternalForceFE upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%BldInternalForceFE) ! BldInternalForceFE + END IF + Int_BufSz = Int_BufSz + 1 ! BldInternalForceQP allocated yes/no + IF ( ALLOCATED(InData%BldInternalForceQP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldInternalForceQP upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%BldInternalForceQP) ! BldInternalForceQP + END IF + Int_BufSz = Int_BufSz + 1 ! FirstNodeReactionLclForceMoment allocated yes/no + IF ( ALLOCATED(InData%FirstNodeReactionLclForceMoment) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FirstNodeReactionLclForceMoment upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%FirstNodeReactionLclForceMoment) ! FirstNodeReactionLclForceMoment + END IF + Int_BufSz = Int_BufSz + 1 ! Solution allocated yes/no + IF ( ALLOCATED(InData%Solution) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Solution upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Solution) ! Solution + END IF + Int_BufSz = Int_BufSz + 1 ! LP_StifK allocated yes/no + IF ( ALLOCATED(InData%LP_StifK) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LP_StifK upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_StifK) ! LP_StifK + END IF + Int_BufSz = Int_BufSz + 1 ! LP_MassM allocated yes/no + IF ( ALLOCATED(InData%LP_MassM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LP_MassM upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_MassM) ! LP_MassM + END IF + Int_BufSz = Int_BufSz + 1 ! LP_MassM_LU allocated yes/no + IF ( ALLOCATED(InData%LP_MassM_LU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LP_MassM_LU upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_MassM_LU) ! LP_MassM_LU + END IF + Int_BufSz = Int_BufSz + 1 ! LP_RHS allocated yes/no + IF ( ALLOCATED(InData%LP_RHS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LP_RHS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_RHS) ! LP_RHS + END IF + Int_BufSz = Int_BufSz + 1 ! LP_StifK_LU allocated yes/no + IF ( ALLOCATED(InData%LP_StifK_LU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LP_StifK_LU upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_StifK_LU) ! LP_StifK_LU + END IF + Int_BufSz = Int_BufSz + 1 ! LP_RHS_LU allocated yes/no + IF ( ALLOCATED(InData%LP_RHS_LU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LP_RHS_LU upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LP_RHS_LU) ! LP_RHS_LU + END IF + Int_BufSz = Int_BufSz + 1 ! LP_indx allocated yes/no + IF ( ALLOCATED(InData%LP_indx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LP_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LP_indx) ! LP_indx + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u2: size of buffers for each call to pack subtype + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u2, ErrStat2, ErrMsg2, .TRUE. ) ! u2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u2 + 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 MeshPack( InData%u_DistrLoad_at_y, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_DistrLoad_at_y + 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 MeshPack( InData%y_BldMotion_at_u, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! y_BldMotion_at_u + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Map_u_DistrLoad_to_y, ErrStat2, ErrMsg2, OnlySize ) ! Map_u_DistrLoad_to_y + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Map_y_BldMotion_to_u, ErrStat2, ErrMsg2, OnlySize ) ! Map_y_BldMotion_to_u + 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%Un_Sum + Int_Xferred = Int_Xferred + 1 + CALL BD_Packeqmotionqp( Re_Buf, Db_Buf, Int_Buf, InData%qp, ErrStat2, ErrMsg2, OnlySize ) ! qp + 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%lin_A) ) 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%lin_A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lin_A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%lin_A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lin_A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%lin_A,2), UBOUND(InData%lin_A,2) + DO i1 = LBOUND(InData%lin_A,1), UBOUND(InData%lin_A,1) + DbKiBuf(Db_Xferred) = InData%lin_A(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%lin_C) ) 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%lin_C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lin_C,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%lin_C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lin_C,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%lin_C,2), UBOUND(InData%lin_C,2) + DO i1 = LBOUND(InData%lin_C,1), UBOUND(InData%lin_C,1) + DbKiBuf(Db_Xferred) = InData%lin_C(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Nrrr) ) 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%Nrrr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nrrr,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nrrr,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nrrr,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nrrr,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nrrr,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Nrrr,3), UBOUND(InData%Nrrr,3) + DO i2 = LBOUND(InData%Nrrr,2), UBOUND(InData%Nrrr,2) + DO i1 = LBOUND(InData%Nrrr,1), UBOUND(InData%Nrrr,1) + DbKiBuf(Db_Xferred) = InData%Nrrr(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elf) ) 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%elf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elf,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elf,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elf,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%elf,2), UBOUND(InData%elf,2) + DO i1 = LBOUND(InData%elf,1), UBOUND(InData%elf,1) + DbKiBuf(Db_Xferred) = InData%elf(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EFint) ) 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%EFint,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EFint,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EFint,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EFint,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EFint,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EFint,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%EFint,3), UBOUND(InData%EFint,3) + DO i2 = LBOUND(InData%EFint,2), UBOUND(InData%EFint,2) + DO i1 = LBOUND(InData%EFint,1), UBOUND(InData%EFint,1) + DbKiBuf(Db_Xferred) = InData%EFint(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elk) ) 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%elk,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elk,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elk,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elk,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elk,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elk,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elk,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elk,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%elk,4), UBOUND(InData%elk,4) + DO i3 = LBOUND(InData%elk,3), UBOUND(InData%elk,3) + DO i2 = LBOUND(InData%elk,2), UBOUND(InData%elk,2) + DO i1 = LBOUND(InData%elk,1), UBOUND(InData%elk,1) + DbKiBuf(Db_Xferred) = InData%elk(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elg) ) 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%elg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elg,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elg,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elg,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%elg,4), UBOUND(InData%elg,4) + DO i3 = LBOUND(InData%elg,3), UBOUND(InData%elg,3) + DO i2 = LBOUND(InData%elg,2), UBOUND(InData%elg,2) + DO i1 = LBOUND(InData%elg,1), UBOUND(InData%elg,1) + DbKiBuf(Db_Xferred) = InData%elg(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elm) ) 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%elm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elm,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elm,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elm,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elm,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elm,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elm,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elm,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%elm,4), UBOUND(InData%elm,4) + DO i3 = LBOUND(InData%elm,3), UBOUND(InData%elm,3) + DO i2 = LBOUND(InData%elm,2), UBOUND(InData%elm,2) + DO i1 = LBOUND(InData%elm,1), UBOUND(InData%elm,1) + DbKiBuf(Db_Xferred) = InData%elm(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DistrLoad_QP) ) 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%DistrLoad_QP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DistrLoad_QP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DistrLoad_QP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DistrLoad_QP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DistrLoad_QP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DistrLoad_QP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%DistrLoad_QP,3), UBOUND(InData%DistrLoad_QP,3) + DO i2 = LBOUND(InData%DistrLoad_QP,2), UBOUND(InData%DistrLoad_QP,2) + DO i1 = LBOUND(InData%DistrLoad_QP,1), UBOUND(InData%DistrLoad_QP,1) + DbKiBuf(Db_Xferred) = InData%DistrLoad_QP(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PointLoadLcl) ) 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%PointLoadLcl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PointLoadLcl,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PointLoadLcl,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PointLoadLcl,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PointLoadLcl,2), UBOUND(InData%PointLoadLcl,2) + DO i1 = LBOUND(InData%PointLoadLcl,1), UBOUND(InData%PointLoadLcl,1) + DbKiBuf(Db_Xferred) = InData%PointLoadLcl(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StifK) ) 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%StifK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%StifK,4), UBOUND(InData%StifK,4) + DO i3 = LBOUND(InData%StifK,3), UBOUND(InData%StifK,3) + DO i2 = LBOUND(InData%StifK,2), UBOUND(InData%StifK,2) + DO i1 = LBOUND(InData%StifK,1), UBOUND(InData%StifK,1) + DbKiBuf(Db_Xferred) = InData%StifK(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MassM) ) 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%MassM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%MassM,4), UBOUND(InData%MassM,4) + DO i3 = LBOUND(InData%MassM,3), UBOUND(InData%MassM,3) + DO i2 = LBOUND(InData%MassM,2), UBOUND(InData%MassM,2) + DO i1 = LBOUND(InData%MassM,1), UBOUND(InData%MassM,1) + DbKiBuf(Db_Xferred) = InData%MassM(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DampG) ) 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%DampG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%DampG,4), UBOUND(InData%DampG,4) + DO i3 = LBOUND(InData%DampG,3), UBOUND(InData%DampG,3) + DO i2 = LBOUND(InData%DampG,2), UBOUND(InData%DampG,2) + DO i1 = LBOUND(InData%DampG,1), UBOUND(InData%DampG,1) + DbKiBuf(Db_Xferred) = InData%DampG(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StifK_fd) ) 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%StifK_fd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK_fd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK_fd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK_fd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK_fd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK_fd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StifK_fd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StifK_fd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%StifK_fd,4), UBOUND(InData%StifK_fd,4) + DO i3 = LBOUND(InData%StifK_fd,3), UBOUND(InData%StifK_fd,3) + DO i2 = LBOUND(InData%StifK_fd,2), UBOUND(InData%StifK_fd,2) + DO i1 = LBOUND(InData%StifK_fd,1), UBOUND(InData%StifK_fd,1) + DbKiBuf(Db_Xferred) = InData%StifK_fd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MassM_fd) ) 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%MassM_fd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM_fd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM_fd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM_fd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM_fd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM_fd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassM_fd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassM_fd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%MassM_fd,4), UBOUND(InData%MassM_fd,4) + DO i3 = LBOUND(InData%MassM_fd,3), UBOUND(InData%MassM_fd,3) + DO i2 = LBOUND(InData%MassM_fd,2), UBOUND(InData%MassM_fd,2) + DO i1 = LBOUND(InData%MassM_fd,1), UBOUND(InData%MassM_fd,1) + DbKiBuf(Db_Xferred) = InData%MassM_fd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DampG_fd) ) 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%DampG_fd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG_fd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG_fd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG_fd,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG_fd,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG_fd,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DampG_fd,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampG_fd,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%DampG_fd,4), UBOUND(InData%DampG_fd,4) + DO i3 = LBOUND(InData%DampG_fd,3), UBOUND(InData%DampG_fd,3) + DO i2 = LBOUND(InData%DampG_fd,2), UBOUND(InData%DampG_fd,2) + DO i1 = LBOUND(InData%DampG_fd,1), UBOUND(InData%DampG_fd,1) + DbKiBuf(Db_Xferred) = InData%DampG_fd(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RHS) ) 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%RHS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RHS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RHS,2), UBOUND(InData%RHS,2) + DO i1 = LBOUND(InData%RHS,1), UBOUND(InData%RHS,1) + DbKiBuf(Db_Xferred) = InData%RHS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RHS_p) ) 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%RHS_p,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS_p,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RHS_p,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS_p,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RHS_p,2), UBOUND(InData%RHS_p,2) + DO i1 = LBOUND(InData%RHS_p,1), UBOUND(InData%RHS_p,1) + DbKiBuf(Db_Xferred) = InData%RHS_p(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RHS_m) ) 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%RHS_m,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS_m,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RHS_m,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RHS_m,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RHS_m,2), UBOUND(InData%RHS_m,2) + DO i1 = LBOUND(InData%RHS_m,1), UBOUND(InData%RHS_m,1) + DbKiBuf(Db_Xferred) = InData%RHS_m(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldInternalForceFE) ) 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%BldInternalForceFE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldInternalForceFE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldInternalForceFE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldInternalForceFE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldInternalForceFE,2), UBOUND(InData%BldInternalForceFE,2) + DO i1 = LBOUND(InData%BldInternalForceFE,1), UBOUND(InData%BldInternalForceFE,1) + DbKiBuf(Db_Xferred) = InData%BldInternalForceFE(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldInternalForceQP) ) 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%BldInternalForceQP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldInternalForceQP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldInternalForceQP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldInternalForceQP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldInternalForceQP,2), UBOUND(InData%BldInternalForceQP,2) + DO i1 = LBOUND(InData%BldInternalForceQP,1), UBOUND(InData%BldInternalForceQP,1) + DbKiBuf(Db_Xferred) = InData%BldInternalForceQP(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FirstNodeReactionLclForceMoment) ) 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%FirstNodeReactionLclForceMoment,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FirstNodeReactionLclForceMoment,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FirstNodeReactionLclForceMoment,1), UBOUND(InData%FirstNodeReactionLclForceMoment,1) + DbKiBuf(Db_Xferred) = InData%FirstNodeReactionLclForceMoment(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Solution) ) 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%Solution,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Solution,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Solution,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Solution,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Solution,2), UBOUND(InData%Solution,2) + DO i1 = LBOUND(InData%Solution,1), UBOUND(InData%Solution,1) + DbKiBuf(Db_Xferred) = InData%Solution(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_StifK) ) 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%LP_StifK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_StifK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LP_StifK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_StifK,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LP_StifK,2), UBOUND(InData%LP_StifK,2) + DO i1 = LBOUND(InData%LP_StifK,1), UBOUND(InData%LP_StifK,1) + DbKiBuf(Db_Xferred) = InData%LP_StifK(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_MassM) ) 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%LP_MassM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_MassM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LP_MassM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_MassM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LP_MassM,2), UBOUND(InData%LP_MassM,2) + DO i1 = LBOUND(InData%LP_MassM,1), UBOUND(InData%LP_MassM,1) + DbKiBuf(Db_Xferred) = InData%LP_MassM(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_MassM_LU) ) 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%LP_MassM_LU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_MassM_LU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LP_MassM_LU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_MassM_LU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LP_MassM_LU,2), UBOUND(InData%LP_MassM_LU,2) + DO i1 = LBOUND(InData%LP_MassM_LU,1), UBOUND(InData%LP_MassM_LU,1) + DbKiBuf(Db_Xferred) = InData%LP_MassM_LU(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_RHS) ) 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%LP_RHS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_RHS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LP_RHS,1), UBOUND(InData%LP_RHS,1) + DbKiBuf(Db_Xferred) = InData%LP_RHS(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_StifK_LU) ) 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%LP_StifK_LU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_StifK_LU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LP_StifK_LU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_StifK_LU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LP_StifK_LU,2), UBOUND(InData%LP_StifK_LU,2) + DO i1 = LBOUND(InData%LP_StifK_LU,1), UBOUND(InData%LP_StifK_LU,1) + DbKiBuf(Db_Xferred) = InData%LP_StifK_LU(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_RHS_LU) ) 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%LP_RHS_LU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_RHS_LU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LP_RHS_LU,1), UBOUND(InData%LP_RHS_LU,1) + DbKiBuf(Db_Xferred) = InData%LP_RHS_LU(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LP_indx) ) 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%LP_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LP_indx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LP_indx,1), UBOUND(InData%LP_indx,1) + IntKiBuf(Int_Xferred) = InData%LP_indx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u2, ErrStat2, ErrMsg2, OnlySize ) ! u2 + 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 BD_PackMisc + + SUBROUTINE BD_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(BD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'BD_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 + 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 MeshUnpack( OutData%u_DistrLoad_at_y, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_DistrLoad_at_y + 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 MeshUnpack( OutData%y_BldMotion_at_u, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! y_BldMotion_at_u + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Map_u_DistrLoad_to_y, ErrStat2, ErrMsg2 ) ! Map_u_DistrLoad_to_y + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Map_y_BldMotion_to_u, ErrStat2, ErrMsg2 ) ! Map_y_BldMotion_to_u + 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%Un_Sum = 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 BD_Unpackeqmotionqp( Re_Buf, Db_Buf, Int_Buf, OutData%qp, ErrStat2, ErrMsg2 ) ! qp + 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 ! lin_A 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%lin_A)) DEALLOCATE(OutData%lin_A) + ALLOCATE(OutData%lin_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lin_A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%lin_A,2), UBOUND(OutData%lin_A,2) + DO i1 = LBOUND(OutData%lin_A,1), UBOUND(OutData%lin_A,1) + OutData%lin_A(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lin_C 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%lin_C)) DEALLOCATE(OutData%lin_C) + ALLOCATE(OutData%lin_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lin_C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%lin_C,2), UBOUND(OutData%lin_C,2) + DO i1 = LBOUND(OutData%lin_C,1), UBOUND(OutData%lin_C,1) + OutData%lin_C(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nrrr 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%Nrrr)) DEALLOCATE(OutData%Nrrr) + ALLOCATE(OutData%Nrrr(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%Nrrr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Nrrr,3), UBOUND(OutData%Nrrr,3) + DO i2 = LBOUND(OutData%Nrrr,2), UBOUND(OutData%Nrrr,2) + DO i1 = LBOUND(OutData%Nrrr,1), UBOUND(OutData%Nrrr,1) + OutData%Nrrr(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elf 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%elf)) DEALLOCATE(OutData%elf) + ALLOCATE(OutData%elf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%elf,2), UBOUND(OutData%elf,2) + DO i1 = LBOUND(OutData%elf,1), UBOUND(OutData%elf,1) + OutData%elf(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EFint 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%EFint)) DEALLOCATE(OutData%EFint) + ALLOCATE(OutData%EFint(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%EFint.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%EFint,3), UBOUND(OutData%EFint,3) + DO i2 = LBOUND(OutData%EFint,2), UBOUND(OutData%EFint,2) + DO i1 = LBOUND(OutData%EFint,1), UBOUND(OutData%EFint,1) + OutData%EFint(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elk 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%elk)) DEALLOCATE(OutData%elk) + ALLOCATE(OutData%elk(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%elk.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%elk,4), UBOUND(OutData%elk,4) + DO i3 = LBOUND(OutData%elk,3), UBOUND(OutData%elk,3) + DO i2 = LBOUND(OutData%elk,2), UBOUND(OutData%elk,2) + DO i1 = LBOUND(OutData%elk,1), UBOUND(OutData%elk,1) + OutData%elk(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elg 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%elg)) DEALLOCATE(OutData%elg) + ALLOCATE(OutData%elg(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%elg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%elg,4), UBOUND(OutData%elg,4) + DO i3 = LBOUND(OutData%elg,3), UBOUND(OutData%elg,3) + DO i2 = LBOUND(OutData%elg,2), UBOUND(OutData%elg,2) + DO i1 = LBOUND(OutData%elg,1), UBOUND(OutData%elg,1) + OutData%elg(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elm 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%elm)) DEALLOCATE(OutData%elm) + ALLOCATE(OutData%elm(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%elm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%elm,4), UBOUND(OutData%elm,4) + DO i3 = LBOUND(OutData%elm,3), UBOUND(OutData%elm,3) + DO i2 = LBOUND(OutData%elm,2), UBOUND(OutData%elm,2) + DO i1 = LBOUND(OutData%elm,1), UBOUND(OutData%elm,1) + OutData%elm(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DistrLoad_QP 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%DistrLoad_QP)) DEALLOCATE(OutData%DistrLoad_QP) + ALLOCATE(OutData%DistrLoad_QP(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%DistrLoad_QP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%DistrLoad_QP,3), UBOUND(OutData%DistrLoad_QP,3) + DO i2 = LBOUND(OutData%DistrLoad_QP,2), UBOUND(OutData%DistrLoad_QP,2) + DO i1 = LBOUND(OutData%DistrLoad_QP,1), UBOUND(OutData%DistrLoad_QP,1) + OutData%DistrLoad_QP(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PointLoadLcl 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%PointLoadLcl)) DEALLOCATE(OutData%PointLoadLcl) + ALLOCATE(OutData%PointLoadLcl(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PointLoadLcl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PointLoadLcl,2), UBOUND(OutData%PointLoadLcl,2) + DO i1 = LBOUND(OutData%PointLoadLcl,1), UBOUND(OutData%PointLoadLcl,1) + OutData%PointLoadLcl(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StifK 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%StifK)) DEALLOCATE(OutData%StifK) + ALLOCATE(OutData%StifK(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%StifK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%StifK,4), UBOUND(OutData%StifK,4) + DO i3 = LBOUND(OutData%StifK,3), UBOUND(OutData%StifK,3) + DO i2 = LBOUND(OutData%StifK,2), UBOUND(OutData%StifK,2) + DO i1 = LBOUND(OutData%StifK,1), UBOUND(OutData%StifK,1) + OutData%StifK(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MassM 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%MassM)) DEALLOCATE(OutData%MassM) + ALLOCATE(OutData%MassM(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%MassM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%MassM,4), UBOUND(OutData%MassM,4) + DO i3 = LBOUND(OutData%MassM,3), UBOUND(OutData%MassM,3) + DO i2 = LBOUND(OutData%MassM,2), UBOUND(OutData%MassM,2) + DO i1 = LBOUND(OutData%MassM,1), UBOUND(OutData%MassM,1) + OutData%MassM(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DampG 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%DampG)) DEALLOCATE(OutData%DampG) + ALLOCATE(OutData%DampG(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%DampG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%DampG,4), UBOUND(OutData%DampG,4) + DO i3 = LBOUND(OutData%DampG,3), UBOUND(OutData%DampG,3) + DO i2 = LBOUND(OutData%DampG,2), UBOUND(OutData%DampG,2) + DO i1 = LBOUND(OutData%DampG,1), UBOUND(OutData%DampG,1) + OutData%DampG(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StifK_fd 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%StifK_fd)) DEALLOCATE(OutData%StifK_fd) + ALLOCATE(OutData%StifK_fd(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%StifK_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%StifK_fd,4), UBOUND(OutData%StifK_fd,4) + DO i3 = LBOUND(OutData%StifK_fd,3), UBOUND(OutData%StifK_fd,3) + DO i2 = LBOUND(OutData%StifK_fd,2), UBOUND(OutData%StifK_fd,2) + DO i1 = LBOUND(OutData%StifK_fd,1), UBOUND(OutData%StifK_fd,1) + OutData%StifK_fd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MassM_fd 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%MassM_fd)) DEALLOCATE(OutData%MassM_fd) + ALLOCATE(OutData%MassM_fd(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%MassM_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%MassM_fd,4), UBOUND(OutData%MassM_fd,4) + DO i3 = LBOUND(OutData%MassM_fd,3), UBOUND(OutData%MassM_fd,3) + DO i2 = LBOUND(OutData%MassM_fd,2), UBOUND(OutData%MassM_fd,2) + DO i1 = LBOUND(OutData%MassM_fd,1), UBOUND(OutData%MassM_fd,1) + OutData%MassM_fd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DampG_fd 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%DampG_fd)) DEALLOCATE(OutData%DampG_fd) + ALLOCATE(OutData%DampG_fd(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%DampG_fd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%DampG_fd,4), UBOUND(OutData%DampG_fd,4) + DO i3 = LBOUND(OutData%DampG_fd,3), UBOUND(OutData%DampG_fd,3) + DO i2 = LBOUND(OutData%DampG_fd,2), UBOUND(OutData%DampG_fd,2) + DO i1 = LBOUND(OutData%DampG_fd,1), UBOUND(OutData%DampG_fd,1) + OutData%DampG_fd(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RHS 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%RHS)) DEALLOCATE(OutData%RHS) + ALLOCATE(OutData%RHS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RHS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RHS,2), UBOUND(OutData%RHS,2) + DO i1 = LBOUND(OutData%RHS,1), UBOUND(OutData%RHS,1) + OutData%RHS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RHS_p 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%RHS_p)) DEALLOCATE(OutData%RHS_p) + ALLOCATE(OutData%RHS_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RHS_p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RHS_p,2), UBOUND(OutData%RHS_p,2) + DO i1 = LBOUND(OutData%RHS_p,1), UBOUND(OutData%RHS_p,1) + OutData%RHS_p(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RHS_m 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%RHS_m)) DEALLOCATE(OutData%RHS_m) + ALLOCATE(OutData%RHS_m(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RHS_m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RHS_m,2), UBOUND(OutData%RHS_m,2) + DO i1 = LBOUND(OutData%RHS_m,1), UBOUND(OutData%RHS_m,1) + OutData%RHS_m(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldInternalForceFE 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%BldInternalForceFE)) DEALLOCATE(OutData%BldInternalForceFE) + ALLOCATE(OutData%BldInternalForceFE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldInternalForceFE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldInternalForceFE,2), UBOUND(OutData%BldInternalForceFE,2) + DO i1 = LBOUND(OutData%BldInternalForceFE,1), UBOUND(OutData%BldInternalForceFE,1) + OutData%BldInternalForceFE(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldInternalForceQP 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%BldInternalForceQP)) DEALLOCATE(OutData%BldInternalForceQP) + ALLOCATE(OutData%BldInternalForceQP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldInternalForceQP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldInternalForceQP,2), UBOUND(OutData%BldInternalForceQP,2) + DO i1 = LBOUND(OutData%BldInternalForceQP,1), UBOUND(OutData%BldInternalForceQP,1) + OutData%BldInternalForceQP(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FirstNodeReactionLclForceMoment 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%FirstNodeReactionLclForceMoment)) DEALLOCATE(OutData%FirstNodeReactionLclForceMoment) + ALLOCATE(OutData%FirstNodeReactionLclForceMoment(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FirstNodeReactionLclForceMoment.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FirstNodeReactionLclForceMoment,1), UBOUND(OutData%FirstNodeReactionLclForceMoment,1) + OutData%FirstNodeReactionLclForceMoment(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Solution 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%Solution)) DEALLOCATE(OutData%Solution) + ALLOCATE(OutData%Solution(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Solution.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Solution,2), UBOUND(OutData%Solution,2) + DO i1 = LBOUND(OutData%Solution,1), UBOUND(OutData%Solution,1) + OutData%Solution(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_StifK 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%LP_StifK)) DEALLOCATE(OutData%LP_StifK) + ALLOCATE(OutData%LP_StifK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_StifK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LP_StifK,2), UBOUND(OutData%LP_StifK,2) + DO i1 = LBOUND(OutData%LP_StifK,1), UBOUND(OutData%LP_StifK,1) + OutData%LP_StifK(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_MassM 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%LP_MassM)) DEALLOCATE(OutData%LP_MassM) + ALLOCATE(OutData%LP_MassM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_MassM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LP_MassM,2), UBOUND(OutData%LP_MassM,2) + DO i1 = LBOUND(OutData%LP_MassM,1), UBOUND(OutData%LP_MassM,1) + OutData%LP_MassM(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_MassM_LU 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%LP_MassM_LU)) DEALLOCATE(OutData%LP_MassM_LU) + ALLOCATE(OutData%LP_MassM_LU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_MassM_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LP_MassM_LU,2), UBOUND(OutData%LP_MassM_LU,2) + DO i1 = LBOUND(OutData%LP_MassM_LU,1), UBOUND(OutData%LP_MassM_LU,1) + OutData%LP_MassM_LU(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_RHS 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%LP_RHS)) DEALLOCATE(OutData%LP_RHS) + ALLOCATE(OutData%LP_RHS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_RHS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LP_RHS,1), UBOUND(OutData%LP_RHS,1) + OutData%LP_RHS(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_StifK_LU 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%LP_StifK_LU)) DEALLOCATE(OutData%LP_StifK_LU) + ALLOCATE(OutData%LP_StifK_LU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_StifK_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LP_StifK_LU,2), UBOUND(OutData%LP_StifK_LU,2) + DO i1 = LBOUND(OutData%LP_StifK_LU,1), UBOUND(OutData%LP_StifK_LU,1) + OutData%LP_StifK_LU(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_RHS_LU 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%LP_RHS_LU)) DEALLOCATE(OutData%LP_RHS_LU) + ALLOCATE(OutData%LP_RHS_LU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_RHS_LU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LP_RHS_LU,1), UBOUND(OutData%LP_RHS_LU,1) + OutData%LP_RHS_LU(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LP_indx 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%LP_indx)) DEALLOCATE(OutData%LP_indx) + ALLOCATE(OutData%LP_indx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LP_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LP_indx,1), UBOUND(OutData%LP_indx,1) + OutData%LP_indx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + 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 BD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 BD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u2, ErrStat2, ErrMsg2 ) ! u2 + 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 BD_UnPackMisc + + + SUBROUTINE BD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(BD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(BD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL BD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL BD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL BD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE BD_Input_ExtrapInterp + + + SUBROUTINE BD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(BD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(BD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(BD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%RootMotion, u2%RootMotion, tin, u_out%RootMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%PointLoad, u2%PointLoad, tin, u_out%PointLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%DistrLoad, u2%DistrLoad, tin, u_out%DistrLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%HubMotion, u2%HubMotion, tin, u_out%HubMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE BD_Input_ExtrapInterp1 + + + SUBROUTINE BD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(BD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(BD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(BD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(BD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%RootMotion, u2%RootMotion, u3%RootMotion, tin, u_out%RootMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%PointLoad, u2%PointLoad, u3%PointLoad, tin, u_out%PointLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%DistrLoad, u2%DistrLoad, u3%DistrLoad, tin, u_out%DistrLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%HubMotion, u2%HubMotion, u3%HubMotion, tin, u_out%HubMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE BD_Input_ExtrapInterp2 + + + SUBROUTINE BD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(BD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(BD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL BD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL BD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL BD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE BD_Output_ExtrapInterp + + + SUBROUTINE BD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(BD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(BD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(BD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%ReactionForce, y2%ReactionForce, tin, y_out%ReactionForce, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%BldMotion, y2%BldMotion, tin, y_out%BldMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + b = -(y1%RootMxr - y2%RootMxr) + y_out%RootMxr = y1%RootMxr + b * ScaleFactor + b = -(y1%RootMyr - y2%RootMyr) + y_out%RootMyr = y1%RootMyr + b * ScaleFactor +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE BD_Output_ExtrapInterp1 + + + SUBROUTINE BD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(BD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(BD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(BD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(BD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'BD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%ReactionForce, y2%ReactionForce, y3%ReactionForce, tin, y_out%ReactionForce, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%BldMotion, y2%BldMotion, y3%BldMotion, tin, y_out%BldMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + b = (t(3)**2*(y1%RootMxr - y2%RootMxr) + t(2)**2*(-y1%RootMxr + y3%RootMxr))* scaleFactor + c = ( (t(2)-t(3))*y1%RootMxr + t(3)*y2%RootMxr - t(2)*y3%RootMxr ) * scaleFactor + y_out%RootMxr = y1%RootMxr + b + c * t_out + b = (t(3)**2*(y1%RootMyr - y2%RootMyr) + t(2)**2*(-y1%RootMyr + y3%RootMyr))* scaleFactor + c = ( (t(2)-t(3))*y1%RootMyr + t(3)*y2%RootMyr - t(2)*y3%RootMyr ) * scaleFactor + y_out%RootMyr = y1%RootMyr + b + c * t_out +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE BD_Output_ExtrapInterp2 + +END MODULE BeamDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/beamdyn/src/Driver_Beam.f90 b/OpenFAST/modules/beamdyn/src/Driver_Beam.f90 new file mode 100644 index 000000000..8c11cb9a5 --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/Driver_Beam.f90 @@ -0,0 +1,267 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! 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. +! +!********************************************************************************************************************************** +PROGRAM BeamDyn_Driver_Program + + USE BeamDyn_driver_subs ! all other modules inherited through this one + USE VersionInfo + + IMPLICIT NONE + + ! global glue-code-specific variables + + INTEGER(IntKi) :: ErrStat ! Error status of the operation + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(DbKi) :: dt_global ! fixed/constant global time step + REAL(DbKi) :: t_global ! global-loop time marker + INTEGER(IntKi) :: n_t_final ! total number of time steps + INTEGER(IntKi) :: n_t_global ! global-loop time counter + INTEGER(IntKi), parameter :: BD_interp_order = 1 ! order of interpolation/extrapolation + + ! Module1 Derived-types variables; see Registry_Module1.txt for details + + TYPE(BD_InitInputType) :: BD_InitInput + TYPE(BD_ParameterType) :: BD_Parameter + TYPE(BD_ContinuousStateType) :: BD_ContinuousState + TYPE(BD_InitOutputType) :: BD_InitOutput + TYPE(BD_DiscreteStateType) :: BD_DiscreteState + TYPE(BD_ConstraintStateType) :: BD_ConstraintState + TYPE(BD_OtherStateType) :: BD_OtherState + TYPE(BD_MiscVarType) :: BD_MiscVar + TYPE(BD_InputType) ,ALLOCATABLE :: BD_Input(:) + REAL(DbKi), ALLOCATABLE :: BD_InputTimes(:) + TYPE(BD_OutputType) :: BD_Output + INTEGER(IntKi) :: DvrOut + + TYPE(BD_DriverInternalType) :: DvrData + + ! local variables + + CHARACTER(256) :: DvrInputFile + CHARACTER(256) :: RootName + INTEGER(IntKi) :: j ! counter for various loops + INTEGER(IntKi) :: i ! counter for various loops + INTEGER(IntKi) :: max_ld_step=8 ! maximum load steps for static runs. + REAL(DbKi) :: TiLstPrn ! The simulation time of the last print (to file) [(s)] + REAL(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds [(s)] + REAL(ReKi) :: UsrTime1 ! User CPU time for simulation initialization [(s)] + REAL(ReKi) :: UsrTime2 ! User CPU time for simulation (without intialization) [(s)] + INTEGER(IntKi) , DIMENSION(1:8) :: StrtTime ! Start time of simulation (including intialization) [-] + INTEGER(IntKi) , DIMENSION(1:8) :: SimStrtTime ! Start time of simulation (after initialization) [-] + CHARACTER(200) :: git_commit ! String containing the current git commit hash + + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'BeamDyn Driver', '', '' ) ! The version number of this program. + + + ! ------------------------------------------------------------------------- + ! Initialization of library (especially for screen output) + ! ------------------------------------------------------------------------- + + CALL DATE_AND_TIME ( Values=StrtTime ) ! Let's time the whole simulation + CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + UsrTime1 = MAX( 0.0_ReKi, UsrTime1 ) ! CPU_TIME: If a meaningful time cannot be returned, a processor-dependent negative value is returned + + + CALL NWTC_Init() + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + ! ------------------------------------------------------------------------- + ! Initialization of glue-code time-step variables + ! ------------------------------------------------------------------------- + + CALL GET_COMMAND_ARGUMENT(1,DvrInputFile) + CALL GetRoot(DvrInputFile,RootName) + CALL BD_ReadDvrFile(DvrInputFile,dt_global,BD_InitInput,DvrData,ErrStat,ErrMsg) + CALL CheckError() + + ! initialize the BD_InitInput values not in the driver input file + BD_InitInput%RootName = TRIM(BD_Initinput%InputFile) + BD_InitInput%RootDisp = matmul(transpose(BD_InitInput%RootOri),BD_InitInput%GlbPos) - BD_InitInput%GlbPos + BD_InitInput%RootVel(1:3) = matmul(BD_InitInput%RootOri, Cross_Product( BD_InitInput%RootVel(4:6), BD_InitInput%GlbPos )) ! set translational velocities based on rotation and GlbPos. + BD_InitInput%DynamicSolve = DvrData%DynamicSolve ! QuasiStatic options handled within the BD code. + + t_global = DvrData%t_initial + n_t_final = ((DvrData%t_final - DvrData%t_initial) / dt_global ) + + !Module1: allocate Input and Output arrays; used for interpolation and extrapolation + ALLOCATE(BD_Input(BD_interp_order + 1)) + ALLOCATE(BD_InputTimes(BD_interp_order + 1)) + + CALL BD_Init(BD_InitInput & + , BD_Input(1) & + , BD_Parameter & + , BD_ContinuousState & + , BD_DiscreteState & + , BD_ConstraintState & + , BD_OtherState & + , BD_Output & + , BD_MiscVar & + , dt_global & + , BD_InitOutput & + , ErrStat & + , ErrMsg ) + CALL CheckError() + + ! If the Quasi-Static solve is in use, rerun the initialization with loads at t=0 + ! (HACK: set in the driver only because computing Jacobians with this option [as in FAST glue code] is problematic) + BD_OtherState%RunQuasiStaticInit = BD_Parameter%analysis_type == BD_DYN_SSS_ANALYSIS + + + ! Set the Initial root orientation + BD_Input(1)%RootMotion%Orientation(1:3,1:3,1) = DvrData%RootRelInit + + call Init_RotationCenterMesh(DvrData, BD_InitInput, BD_Input(1)%RootMotion, ErrStat, ErrMsg) + CALL CheckError() + + call CreateMultiPointMeshes(DvrData,BD_InitInput,BD_InitOutput,BD_Parameter, BD_Output, BD_Input(1), ErrStat, ErrMsg) + call Transfer_MultipointLoads(DvrData, BD_Output, BD_Input(1), ErrStat, ErrMsg) + + CALL Dvr_InitializeOutputFile(DvrOut,BD_InitOutput,RootName,ErrStat,ErrMsg) + CALL CheckError() + + + ! initialize BD_Input and BD_InputTimes + BD_InputTimes(1) = DvrData%t_initial + CALL BD_InputSolve( BD_InputTimes(1), BD_Input(1), DvrData, ErrStat, ErrMsg) + + DO j = 2,BD_interp_order+1 + ! create new meshes + CALL BD_CopyInput (BD_Input(1) , BD_Input(j) , MESH_NEWCOPY, ErrStat, ErrMsg) + CALL CheckError() + + ! solve for inputs at previous time steps + BD_InputTimes(j) = DvrData%t_initial - (j - 1) * dt_global + CALL BD_InputSolve( BD_InputTimes(j), BD_Input(j), DvrData, ErrStat, ErrMsg) + CALL CheckError() + END DO + + + + !......................... + ! calculate outputs at t=0 + !......................... + CALL SimStatus_FirstTime( TiLstPrn, PrevClockTime, SimStrtTime, UsrTime2, t_global, DvrData%t_final ) + + CALL BD_CalcOutput( t_global, BD_Input(1), BD_Parameter, BD_ContinuousState, BD_DiscreteState, & + BD_ConstraintState, BD_OtherState, BD_Output, BD_MiscVar, ErrStat, ErrMsg) + CALL CheckError() + + CALL Dvr_WriteOutputLine(t_global,DvrOut,BD_Parameter%OutFmt,BD_Output) + + !......................... + ! time marching + !......................... + + DO n_t_global = 0, n_t_final + + ! Shift "window" of BD_Input + DO j = BD_interp_order, 1, -1 + CALL BD_CopyInput (BD_Input(j), BD_Input(j+1), MESH_UPDATECOPY, Errstat, ErrMsg) + CALL CheckError() + BD_InputTimes(j+1) = BD_InputTimes(j) + END DO + + BD_InputTimes(1) = t_global + dt_global + CALL BD_InputSolve( BD_InputTimes(1), BD_Input(1), DvrData, ErrStat, ErrMsg) + CALL CheckError() + + + IF(BD_Parameter%analysis_type .EQ. BD_STATIC_ANALYSIS .AND. n_t_global > max_ld_step) EXIT + + ! update states from n_t_global to n_t_global + 1 + CALL BD_UpdateStates( t_global, n_t_global, BD_Input, BD_InputTimes, BD_Parameter, & + BD_ContinuousState, & + BD_DiscreteState, BD_ConstraintState, & + BD_OtherState, BD_MiscVar, ErrStat, ErrMsg ) + CALL CheckError() + + + ! advance time + t_global = (n_t_global+1) * dt_global + DvrData%t_initial + + ! calculate outputs at n_t_global + 1 + CALL BD_CalcOutput( t_global, BD_Input(1), BD_Parameter, BD_ContinuousState, BD_DiscreteState, & + BD_ConstraintState, BD_OtherState, BD_Output, BD_MiscVar, ErrStat, ErrMsg) + CALL CheckError() + + CALL Dvr_WriteOutputLine(t_global,DvrOut,BD_Parameter%OutFmt,BD_Output) + + if ( MOD( n_t_global + 1, 100 ) == 0 ) call SimStatus( TiLstPrn, PrevClockTime, t_global, DvrData%t_final ) + ENDDO + + CALL RunTimes( StrtTime, UsrTime1, SimStrtTime, UsrTime2, t_global ) + + + CALL Dvr_End() + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE Dvr_End() + + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'Dvr_End' + + IF(DvrOut >0) CLOSE(DvrOut) + + IF ( ALLOCATED(BD_Input) ) THEN + CALL BD_End( BD_Input(1), BD_Parameter, BD_ContinuousState, BD_DiscreteState, & + BD_ConstraintState, BD_OtherState, BD_Output, BD_MiscVar, ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + DO i=2,BD_interp_order + 1 + CALL BD_DestroyInput( BD_Input(i), ErrStat2, ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + ENDDO + + DEALLOCATE(BD_Input) + END IF + + IF(ALLOCATED(BD_InputTimes )) DEALLOCATE(BD_InputTimes ) + if(allocated(DvrData%MultiPointLoad)) deallocate(DvrData%MultiPointLoad) + + + + if (ErrStat >= AbortErrLev) then + CALL ProgAbort( 'BeamDyn Driver encountered simulation error level: '& + //TRIM(GetErrStr(ErrStat)), TrapErrors=.FALSE., TimeWait=3._ReKi ) ! wait 3 seconds (in case they double-clicked and got an error) + else + call NormStop() + end if + END SUBROUTINE Dvr_End +!---------------------------------------------------------------------------------------------------------------------------------- + subroutine CheckError() + + if (ErrStat /= ErrID_None) then + call WrScr(TRIM(ErrMsg)) + + if (ErrStat >= AbortErrLev) then + call Dvr_End() + end if + end if + + end subroutine CheckError + +END PROGRAM BeamDyn_Driver_Program diff --git a/OpenFAST/modules/beamdyn/src/Driver_Beam_Subs.f90 b/OpenFAST/modules/beamdyn/src/Driver_Beam_Subs.f90 new file mode 100644 index 000000000..ca4ea3df4 --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/Driver_Beam_Subs.f90 @@ -0,0 +1,781 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! 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 BeamDyn_driver_subs + + USE BeamDyn + USE BeamDyn_Subs + + IMPLICIT NONE + + ! Variables for multi-point loads + TYPE , PUBLIC :: BD_DriverInternalType + REAL(ReKi) , DIMENSION(1:6) :: DistrLoad !< Constant distributed load along beam axis, 3 forces and 3 moments [-] + REAL(ReKi) , DIMENSION(1:6) :: TipLoad !< Constant point load applied at tip, 3 forces and 3 moments [-] + INTEGER(IntKi) :: NumPointLoads !< Number of constant point loads applied along beam axis, 3 forces and 3 moments, from the driver input file [-] + REAL(BDKi) , DIMENSION(:,:), ALLOCATABLE :: MultiPointLoad !< Constant point loads applied along beam axis, size (NumPointLoads,7); (dimension 2: index 1=Relative position along blade span; indices 2-7 = Fx, Fy, Fz, Mx, My, Mz) [-] + + TYPE(MeshType) :: mplMotion ! Mesh for blade motion at multipoint loads locations + TYPE(MeshType) :: mplLoads ! Mesh for multipoint loads + TYPE(MeshMapType) :: Map_BldMotion_to_mplMotion + TYPE(MeshMapType) :: Map_mplLoads_to_PointLoad + TYPE(MeshType) :: y_BldMotion_at_u_point ! Intermediate mesh to transfer motion from output mesh to input mesh + TYPE(MeshMapType) :: Map_y_BldMotion_to_u_point + + TYPE(MeshType) :: RotationCenter + TYPE(MeshMapType) :: Map_RotationCenter_to_RootMotion + + LOGICAL :: DynamicSolve + LOGICAL :: GlbRotBladeT0 ! Initial blade root orientation is also the GlbRot reference frame + REAL(DbKi) :: RootRelInit(3,3) ! Initial root orientation relative to GlbRot + REAL(DbKi) :: t_initial + REAL(DbKi) :: t_final + REAL(R8Ki) :: w ! magnitude of rotational velocity vector + + END TYPE + + + + contains + +!------------------------------------------------------------------------------------ +!> This routine reads in the primary BeamDyn input file and places the values it reads +!! in the InputFileData structure. +!! It opens an echo file if requested and returns the (still-open) echo file to the +!! calling routine. +!! It also returns the names of the BldFile, FurlFile, and TrwFile for further +!! reading of inputs. +!------------------------------------------------------------------------------------ + SUBROUTINE BD_ReadDvrFile(DvrInputFile,dt,InitInputData,DvrData,& + ErrStat,ErrMsg) + + ! Passed variables + CHARACTER(*), INTENT(IN ) :: DvrInputFile + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + TYPE(BD_InitInputType), INTENT( OUT) :: InitInputData + TYPE(BD_DriverInternalType), INTENT( OUT) :: DvrData + REAL(DbKi), INTENT( OUT) :: dt + + ! Local variables: + REAL(BDKi) :: TmpReAry(7) + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(*), parameter :: RoutineName = 'BD_ReadDvrFile' + character(1024) :: line + INTEGER(IntKi) :: UnEc + + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(1024) :: PriPath ! Path name of the primary file + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: IOS +!------------------------------------------------------------------------------------ + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + UnEc = -1 + + CALL GetNewUnit(UnIn,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL OpenFInpFile(UnIn,DvrInputFile,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + + CALL GetPath( DvrInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + !-------------------------- HEADER --------------------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'File Header: Module Version (line 1)',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadStr(UnIn,DvrInputFile,FTitle,'FTitle','File Header: File Description (line 2)',ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + !---------------------- SIMULATION CONTROL -------------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Simulation Control',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,DvrData%DynamicSolve,'DynamicSolve','Use Dynamic solve (false for static solve).',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,DvrData%t_initial,'t_initial','Starting time of simulation',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,DvrData%t_final,"t_final", "Ending time of simulation",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,dt,"dt", "Time increment size",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !---------------------- GRAVITY PARAMETER -------------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Gravity Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + InitInputData%gravity(:) = 0.0_ReKi + CALL ReadVar(UnIn,DvrInputFile,InitInputData%gravity(1),"InitInputData%gravity(1)", "gravity vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%gravity(2),"InitInputData%gravity(2)", "gravity vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%gravity(3),"InitInputData%gravity(3)", "gravity vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + !---------------------- FRAME PARAMETER -------------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Frame Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + InitInputData%GlbPos(:) = 0.0_ReKi + InitInputData%GlbRot(:,:) = 0.0_R8Ki + InitInputData%RootOri(:,:) = 0.0_R8Ki + CALL ReadVar(UnIn,DvrInputFile,InitInputData%GlbPos(1),"InitInputData%GlbPos(1)", "position vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%GlbPos(2),"InitInputData%GlbPos(2)", "position vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%GlbPos(3),"InitInputData%GlbPos(3)", "position vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadCom(UnIn,DvrInputFile,'Comments on DCM',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadCom(UnIn,DvrInputFile,'Comments on DCM',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + DO i=1,3 + CALL ReadAry(UnIn,DvrInputFile,InitInputData%RootOri(i,:),3,"InitInputData%RootOri",& + "Initial root orientation",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ENDDO + + CALL ReadVar(UnIn,DvrInputFile,DvrData%GlbRotBladeT0,"DvrData%GlbRotBladeT0","Is the blade initial orientation also the GlbRot calculation frame",ErrStat2,ErrMSg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! Use the initial blade root orientation as the GlbRot reference orientation for all calculations? + if ( DvrData%GlbRotBladeT0 ) then + + ! Set the GlbRot matrix + InitInputData%GlbRot = InitInputData%RootOri + CALL eye( DvrData%RootRelInit, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + else + + ! Initialize the GlbRot matrix as the identity. Relative rotation for root to GlbRot + DvrData%RootRelInit = InitInputData%RootOri + CALL eye( InitInputData%GlbRot, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + end if + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + !---------------------- INITIAL VELOCITY PARAMETER -------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Initial Velocity Parameter',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,InitInputData%RootVel(4),"InitInputData%IniRootVel(1)", "angular velocity vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%RootVel(5),"InitInputData%IniRootVel(2)", "angular velocity vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,InitInputData%RootVel(6),"InitInputData%IniRootVel(3)", "angular velocity vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + InitInputData%RootVel(1:3) = cross_product(InitInputData%RootVel(4:6),InitInputData%GlbPos(:)) + + !---------------------- APPLIED FORCE -------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Applied Force',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(1),"InitInputData%DistrLoad(1)", "Distributed load vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(2),"InitInputData%DistrLoad(2)", "Distributed load vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(3),"InitInputData%DistrLoad(3)", "Distributed load vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(4),"InitInputData%DistrLoad(4)", "Distributed load vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(5),"InitInputData%DistrLoad(5)", "Distributed load vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%DistrLoad(6),"InitInputData%DistrLoad(6)", "Distributed load vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(1),"InitInputData%TipLoad(1)", "Tip load vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(2),"InitInputData%TipLoad(2)", "Tip load vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(3),"InitInputData%TipLoad(3)", "Tip load vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(4),"InitInputData%TipLoad(4)", "Tip load vector X",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(5),"InitInputData%TipLoad(5)", "Tip load vector Y",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadVar(UnIn,DvrInputFile,DvrData%TipLoad(6),"InitInputData%TipLoad(6)", "Tip load vector Z",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + !---------------------- MULTI-POINT LOAD INPUTS ---------------------------------------- + !First read into temporary "line" variable so we can check if this is numeric or not (for backward compatibility) + CALL ReadVar(UnIn,DvrInputFile,line,"DvrData%NumPointLoads", "Number of Point Loads (primary input file section header)",ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + READ( Line, *, IOSTAT=IOS) DvrData%NumPointLoads + if (IOS == 0) then !this is numeric, so we can go ahead with the multi-point loads + + CALL ReadCom(UnIn,DvrInputFile,'Multiple Point Loads Table',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ReadCom(UnIn,DvrInputFile,'Multiple Point Loads Table Units',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(DvrData%MultiPointLoad,max(1,DvrData%NumPointLoads),7,'Point loads input array',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + DvrData%MultiPointLoad = 0.0_ReKi ! this must have at least one node, and it will be initialized to 0 + + DO i = 1,DvrData%NumPointLoads + CALL ReadAry( UnIn, DvrInputFile, TmpReAry, 7, 'PointLoad', 'Nodal point loads - Node No., DOF No., ', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + DvrData%MultiPointLoad(i,1) = TmpReAry(1) + DvrData%MultiPointLoad(i,2) = TmpReAry(2) + DvrData%MultiPointLoad(i,3) = TmpReAry(3) + DvrData%MultiPointLoad(i,4) = TmpReAry(4) + DvrData%MultiPointLoad(i,5) = TmpReAry(5) + DvrData%MultiPointLoad(i,6) = TmpReAry(6) + DvrData%MultiPointLoad(i,7) = TmpReAry(7) + ENDDO + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + DvrData%NumPointLoads = max(1,DvrData%NumPointLoads) + + !---------------------- BEAM SECTIONAL PARAMETER ---------------------------------------- + CALL ReadCom(UnIn,DvrInputFile,'Section Header: Primary input file',ErrStat2,ErrMsg2,UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + else + DvrData%NumPointLoads = 1 + CALL AllocAry(DvrData%MultiPointLoad,DvrData%NumPointLoads,7,'Point loads input array',ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + DvrData%MultiPointLoad = 0.0_ReKi + end if ! we read the header already + + !---------------------- BEAM SECTIONAL PARAMETER ---------------------------------------- + CALL ReadVar ( UnIn, DvrInputFile, InitInputData%InputFile, 'InputFile', 'Name of the primary input file', ErrStat2,ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( PathIsRelative( InitInputData%InputFile ) ) InitInputData%InputFile = TRIM(PriPath)//TRIM(InitInputData%InputFile) + + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + call cleanup() + return + +contains + subroutine cleanup() + close(UnIn) + return + end subroutine cleanup +END SUBROUTINE BD_ReadDvrFile + +SUBROUTINE Dvr_InitializeOutputFile(OutUnit,IntOutput,RootName,ErrStat,ErrMsg) + + + INTEGER(IntKi), INTENT( OUT):: OutUnit + TYPE(BD_InitOutputType), INTENT(IN ):: IntOutput ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT):: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT):: ErrMsg ! Error message if ErrStat /= ErrID_None + CHARACTER(*), INTENT(IN ):: RootName + + integer(IntKi) :: i + integer(IntKi) :: numOuts + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + character(*), parameter :: RoutineName = 'Dvr_InitializeOutputFile' + + ErrStat = ErrID_none + ErrMsg = "" + + CALL GetNewUnit(OutUnit,ErrStat2,ErrMsg2) + CALL OpenFOutFile ( OutUnit, trim(RootName)//'.out', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + write (OutUnit,'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using '//trim(GetNVD(IntOutput%Ver)) + write (OutUnit,'()' ) !print a blank line + + numOuts = size(IntOutput%WriteOutputHdr) + !...................................................... + ! Write the names of the output parameters on one line: + !...................................................... + + write (OutUnit,'()') + write (OutUnit,'()') + write (OutUnit,'()') + + call WrFileNR ( OutUnit, 'Time' ) + + do i=1,NumOuts + call WrFileNR ( OutUnit, tab//IntOutput%WriteOutputHdr(i) ) + end do ! i + + write (OutUnit,'()') + + !...................................................... + ! Write the units of the output parameters on one line: + !...................................................... + + call WrFileNR ( OutUnit, '(s)' ) + + do i=1,NumOuts + call WrFileNR ( Outunit, tab//trim(IntOutput%WriteOutputUnt(i)) ) + end do ! i + + write (OutUnit,'()') + + +END SUBROUTINE Dvr_InitializeOutputFile + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Dvr_WriteOutputLine(t,OutUnit, OutFmt, Output) + + + real(DbKi) , intent(in ) :: t ! simulation time (s) + INTEGER(IntKi) , intent(in ) :: OutUnit ! Status of error message + CHARACTER(*) , intent(in ) :: OutFmt +! real(ReKi) , intent(in ) :: output(:) ! Rootname for the output file + TYPE(BD_OutputType), INTENT(IN ) :: Output + + ! Local variables. + + integer(IntKi) :: errStat ! Status of error message (we're going to ignore errors in writing to the file) + character(ErrMsgLen) :: errMsg ! Error message if ErrStat /= ErrID_None + character(200) :: frmt ! A string to hold a format specifier + character(15) :: tmpStr ! temporary string to print the time output as text + + frmt = '"'//tab//'"'//trim(OutFmt) ! format for array elements from individual modules + + ! time + write( tmpStr, '(F15.6)' ) t + call WrFileNR( OutUnit, tmpStr ) + call WrNumAryFileNR ( OutUnit, Output%WriteOutput, frmt, errStat, errMsg ) + + ! write a new line (advance to the next line) + write (OutUnit,'()') + +end subroutine Dvr_WriteOutputLine + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine CreateMultiPointMeshes(DvrData,BD_InitInput,BD_InitOutput,BD_Parameter,y, u, ErrStat,ErrMsg) + + TYPE(BD_DriverInternalType), INTENT(INOUT) :: DvrData + TYPE(BD_InitInputType) , INTENT(IN ) :: BD_InitInput + TYPE(BD_InitOutputType) , INTENT(IN ) :: BD_InitOutput + TYPE(BD_ParameterType) , INTENT(IN ) :: BD_Parameter + TYPE(BD_OutputType), INTENT(IN ) :: y + TYPE(BD_InputType), INTENT(INOUT) :: u ! sets pointLoad with values from BD driver input file + 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) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'CreateMultiPointMeshes' + + REAL(BDKi) :: temp_POS(3) + REAL(BDKi) :: temp_CRV(3) + REAL(BDKi) :: temp_CRV2(3) + REAL(R8Ki) :: DCM(3,3) ! must be same type as mesh orientation fields + REAL(ReKi) :: Pos(3) ! must be same type as mesh position fields + REAL(BDKi) :: TmpDCM(3,3) + + + ErrStat = ErrID_None + ErrMsg = "" + + ! DvrData%NumPointLoads is at least 1 + + !....................... + ! Mesh for multi-point loading on blades + !....................... + CALL MeshCreate( BlankMesh = DvrData%mplMotion & + ,IOS = COMPONENT_INPUT & + ,NNodes = DvrData%NumPointLoads & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) return + + ! these nodes are placed along the key point line (as are the GLL nodes) + DO i = 1,DvrData%NumPointLoads + + !FIXME Mike Sprague; given DvrData%MultiPointLoad(i,1), find temp_POS and temp_CRV; we should have p%uuN0 + ! Find_IniNode(kp_coordinate, p, member_first_kp, member_last_kp, eta, POS, CRV, ErrStat, ErrMsg) + !call Find_IniNode(BD_InitOutput%kp_coordinate, BD_Parameter, 1, BD_InitOutput%kp_total, DvrData%MultiPointLoad(i,1), temp_POS, temp_CRV, ErrStat2, ErrMsg2) + call BD_Interp_Pos_CRV(BD_Parameter, DvrData%MultiPointLoad(i,1), temp_POS, temp_CRV, ErrStat, ErrMsg) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + Pos = BD_Parameter%GlbPos + MATMUL(BD_Parameter%GlbRot,temp_POS) + + temp_CRV2 = MATMUL(BD_Parameter%GlbRot,temp_CRV) + CALL BD_CrvCompose(temp_CRV,BD_Parameter%Glb_crv,temp_CRV2,FLAG_R1R2) !temp_CRV = p%Glb_crv composed with temp_CRV2 + + CALL BD_CrvMatrixR(temp_CRV,TmpDCM) ! returns TmpDCM (the transpose of the DCM orientation matrix) + + ! possible type conversions here: + DCM = TRANSPOSE(TmpDCM) + + ! set the reference position and orientation for each node. + CALL MeshPositionNode ( Mesh = DvrData%mplMotion & + ,INode = i & + ,Pos = Pos & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Orient = DCM ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ENDDO + + DO i = 1,DvrData%NumPointLoads + CALL MeshConstructElement( Mesh = DvrData%mplMotion & + ,Xelement = ELEMENT_POINT & + ,P1 = i & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ENDDO + + CALL MeshCommit ( Mesh = DvrData%mplMotion & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !....................... + ! sibling mesh for motions, which are needed to transfer loads + !....................... + + CALL MeshCopy ( SrcMesh = DvrData%mplMotion & + , DestMesh = DvrData%mplLoads & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_INPUT & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !....................... + ! "sibling" mesh for BD motions, which are needed to transfer loads + ! BD's input and output meshes may not be at the same location, so we need another copy + !....................... + + CALL MeshCopy ( SrcMesh = u%PointLoad & + , DestMesh = DvrData%y_BldMotion_at_u_point & + , CtrlCode = MESH_COUSIN & ! Like a sibling, except using new memory for position/refOrientation and elements + , IOS = COMPONENT_OUTPUT & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) return + + !....................... + ! initialize the mapping between the BD output motions and driver mpl motion mesh: + !....................... + + CALL MeshMapCreate( y%BldMotion, DvrData%mplMotion, DvrData%Map_BldMotion_to_mplMotion, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !....................... + ! initialize the mapping between the driver mpl loads and BD input point loads mesh: + !....................... + CALL MeshMapCreate( DvrData%mplLoads, u%PointLoad, DvrData%Map_mplLoads_to_PointLoad, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !....................... + ! initialize the mapping between the BD output motions and BD motions at the nodes on the y%BldMotion mesh: + !....................... + + CALL MeshMapCreate( y%BldMotion, DvrData%y_BldMotion_at_u_point, DvrData%Map_y_BldMotion_to_u_point, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + DvrData%mplMotion%remapFlag = .false. + DvrData%mplLoads%remapFlag = .false. + DvrData%y_BldMotion_at_u_point%remapFlag = .false. + +end subroutine CreateMultiPointMeshes +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Transfer_MultipointLoads(DvrData, y, u, ErrStat, ErrMsg) + + TYPE(BD_DriverInternalType), INTENT(INOUT) :: DvrData + TYPE(BD_OutputType), INTENT(IN ) :: y + TYPE(BD_InputType), INTENT(INOUT) :: u ! sets pointLoad with values from BD driver input file + 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) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Transfer_MultipointLoads' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! the mpl loads are constant over the course of the simulation, but they could be set up to vary + DO i = 1,DvrData%NumPointLoads + DvrData%mplLoads%Force(1:3,i) = DvrData%MultiPointLoad(i,2:4) + DvrData%mplLoads%Moment(1:3,i) = DvrData%MultiPointLoad(i,5:7) + ENDDO + + ! get the motions from BD to the two meshes needed in this loads transfer: + CALL Transfer_Line2_to_Point( y%BldMotion, DvrData%y_BldMotion_at_u_point, DvrData%Map_y_BldMotion_to_u_point, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL Transfer_Line2_to_Point( y%BldMotion, DvrData%mplMotion, DvrData%Map_BldMotion_to_mplMotion, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! we'll do this each time step in case we want to make this time-series input at some point + ! transfer the mpl loads to BD's input point mesh at the GLL nodes: + CALL Transfer_Point_to_Point( DvrData%mplLoads, u%PointLoad, DvrData%Map_mplLoads_to_PointLoad, ErrStat2, ErrMsg2, DvrData%mplMotion, DvrData%y_BldMotion_at_u_point) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +end subroutine Transfer_MultipointLoads + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_RotationCenterMesh(DvrData, InitInputData, RootMotionMesh, ErrStat, ErrMsg) + TYPE(BD_InitInputType), INTENT(IN ) :: InitInputData + TYPE(BD_DriverInternalType), INTENT(INOUT) :: DvrData + TYPE(MeshType), INTENT(INOUT) :: RootMotionMesh + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'Init_RotationCenterMesh' + + real(r8Ki) :: orientation(3,3) + real(ReKi) :: position(3) + real(R8Ki) :: z_hat(3) ! unit-magnitude rotational velocity vector + real(R8Ki) :: Z_unit(3) ! unit vector in the Z direction + real(R8Ki) :: vec(3) ! temporary vector + + ErrStat = ErrID_None + ErrMsg = '' + + + position = 0.0_ReKi ! center of rotation + + DvrData%w = TwoNorm( InitInputData%RootVel(4:6) ) + + if (EqualRealNos(DvrData%w,0.0_R8Ki)) then + DvrData%w = 0.0_R8Ki + ! the beam is not rotating, so pick an orientation + call eye(orientation, ErrStat2, ErrMsg2) + else + z_hat = InitInputData%RootVel(4:6) / DvrData%w + + if ( EqualRealNos( z_hat(3), 1.0_R8Ki ) ) then + call eye(orientation, ErrStat2, ErrMsg2) + elseif ( EqualRealNos( z_hat(3), -1.0_R8Ki ) ) then + orientation = 0.0_ReKi + orientation(1,1) = -1.0_R8Ki + orientation(2,2) = 1.0_R8Ki + orientation(3,3) = -1.0_R8Ki + else + + Z_unit = (/0.0_R8Ki, 0.0_R8Ki, 1.0_R8Ki/) + + vec = Z_unit - z_hat*z_hat(3) ! vec = matmul( eye(3) - outerproduct(z_hat,z_hat), (/ 0,0,1/) ) + vec = vec / TwoNorm(vec) ! we've already checked that this is not zero + orientation(1,:) = vec + + vec = cross_product(z_hat,Z_unit) + vec = vec / TwoNorm(vec) + orientation(2,:) = vec + + orientation(3,:) = z_hat + + end if + + end if + + !....................... + ! Mesh for center of rotation + !....................... + CALL MeshCreate( BlankMesh = DvrData%RotationCenter & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) return + + ! set the reference position and orientation. + CALL MeshPositionNode ( DvrData%RotationCenter, 1, position, ErrStat2, ErrMsg2, orientation ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshConstructElement( DvrData%RotationCenter, ELEMENT_POINT, ErrStat2, ErrMsg2, 1 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MeshCommit (DvrData%RotationCenter, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) return + + + ! note that the following fields do not change during the simulation; orientation will change in BD_InputSolve. + DvrData%RotationCenter%TranslationDisp = 0.0_ReKi + DvrData%RotationCenter%TranslationVel = 0.0_ReKi + DvrData%RotationCenter%RotationVel(:,1) = InitInputData%RootVel(4:6) + DvrData%RotationCenter%TranslationAcc = 0.0_ReKi + DvrData%RotationCenter%RotationAcc = 0.0_ReKi + + + !....................... + ! initialize the mapping between the BD center of rotation and BD root motion input mesh: + !....................... + + CALL MeshMapCreate( DvrData%RotationCenter, RootMotionMesh, DvrData%Map_RotationCenter_to_RootMotion, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DvrData%RotationCenter%remapFlag = .false. + RootMotionMesh%remapFlag = .false. + +END SUBROUTINE Init_RotationCenterMesh + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE BD_InputSolve( t, u, DvrData, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t + TYPE(BD_InputType), INTENT(INOUT) :: u + TYPE(BD_DriverInternalType), INTENT(INOUT) :: DvrData + 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 ! do-loop counter + REAL(R8Ki) :: Orientation(3,3) + REAL(R8Ki) :: wt ! time from start start of simulation multiplied by magnitude of rotational velocity + REAL(R8Ki) :: swt, cwt ! sine and cosine of w*t + + integer(intKi) :: ErrStat2 ! temporary Error status + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message + character(*), parameter :: RoutineName = 'BD_InputSolve' + + ErrStat = ErrID_None + ErrMsg = '' + + !............................. + ! Set up u%RootMotion: + !............................. + + ! Compute the orientation at the center of rotation + wt = DvrData%w * (t - DvrData%t_initial) + swt = sin( wt ) + cwt = cos( wt ) + Orientation(1,1) = cwt + Orientation(2,1) =-swt + Orientation(3,1) = 0.0_R8Ki + + Orientation(1,2) = swt + Orientation(2,2) = cwt + Orientation(3,2) = 0.0_R8Ki + + Orientation(1,3) = 0.0_R8Ki + Orientation(2,3) = 0.0_R8Ki + Orientation(3,3) = 1.0_R8Ki + + DvrData%RotationCenter%Orientation(:,:,1) = matmul(Orientation, matmul(DvrData%RotationCenter%RefOrientation(:,:,1),DvrData%RootRelInit)) + + CALL Transfer_Point_to_Point( DvrData%RotationCenter, u%RootMotion, DvrData%Map_RotationCenter_to_RootMotion, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !............................. + ! set up the point load input: + ! @VA: if we want to apply these at different positions, we should call Transfer_MultipointLoads(); + ! putting the calculation here so we can have changing loads at some point... + !............................. + CALL Transfer_Point_to_Point( DvrData%mplLoads, u%PointLoad, DvrData%Map_mplLoads_to_PointLoad, ErrStat2, ErrMsg2, DvrData%mplMotion, DvrData%y_BldMotion_at_u_point) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + u%PointLoad%Force(1:3,u%PointLoad%NNodes) = u%PointLoad%Force(1:3,u%PointLoad%NNodes) + DvrData%TipLoad(1:3) + u%PointLoad%Moment(1:3,u%PointLoad%NNodes) = u%PointLoad%Moment(1:3,u%PointLoad%NNodes) + DvrData%TipLoad(4:6) + + !............................. + ! LINE2 mesh: DistrLoad + !............................. + DO i=1,u%DistrLoad%NNodes + u%DistrLoad%Force(:,i) = DvrData%DistrLoad(1:3) + u%DistrLoad%Moment(:,i)= DvrData%DistrLoad(4:6) + ENDDO + +END SUBROUTINE BD_InputSolve + + +end module BeamDyn_driver_subs diff --git a/OpenFAST/modules/beamdyn/src/Registry_BeamDyn.txt b/OpenFAST/modules/beamdyn/src/Registry_BeamDyn.txt new file mode 100644 index 000000000..768160a51 --- /dev/null +++ b/OpenFAST/modules/beamdyn/src/Registry_BeamDyn.txt @@ -0,0 +1,376 @@ +################################################################################################################################## +# Registry for BeamDyn, creates MODULE BeamDyn_Types +# Module BeamDyn_Types contains all of the user-defined types needed in BeamDyn. It also contains copy, destroy, pack, and +# unpack routines associated with each defined data types. +################################################################################################################################## +# Entries are of the form +# keyword <modulename/modname> <TypeBeingDefined> <FieldType> <FieldName> <Dims> <InitialValue> <Ctrl> "<DESCRIP>" "<UNITS>" +################################################################################################################################## +include Registry_NWTC_Library.txt + +# BeamDyn Constants +param BeamDyn/BD - IntKi BD_STATIC_ANALYSIS - 1 - "Constant for static analysis. InputType%Dynamic = FALSE." - +param ^ - IntKi BD_DYNAMIC_ANALYSIS - 2 - "Constant for dynamic analysis. InputType%Dynamic = TRUE .AND. BD_InputFile%QuasiStaticSolve = FALSE" - +param ^ - IntKi BD_DYN_SSS_ANALYSIS - 3 - "Constant for dynamic analysis with Steady State Startup solve. InputType%Dynamic = TRUE .AND. BD_InputFile%QuasiStaticSolve = TRUE" - + +param ^ - IntKi BD_MESH_FE - 1 - "Constant for creating y%BldMotion at the FE (GLL) nodes" - +param ^ - IntKi BD_MESH_QP - 2 - "Constant for creating y%BldMotion at the quadrature nodes" - +param ^ - IntKi BD_MESH_STATIONS - 3 - "Constant for creating y%BldMotion at the blade property input stations" - + + +# ..... Initialization data +# ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef ^ InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ InitInputType ReKi gravity {3} - - "Gravitational acceleration" m/s^2 +typedef ^ InitInputType ReKi GlbPos {3} - - "Initial Position Vector of the local blade coordinate system" +typedef ^ InitInputType R8Ki GlbRot {3}{3} - - "Initial direction cosine matrix of the local blade coordinate system -- in BD coords" +typedef ^ InitInputType R8Ki RootDisp {3} - - "Initial root displacement" +typedef ^ InitInputType R8Ki RootOri {3}{3} - - "Initial root orientation" +typedef ^ InitInputType ReKi RootVel {6} - - "Initial root velocities and angular veolcities" +typedef ^ InitInputType ReKi HubPos {3} - - "Initial Hub position vector" +typedef ^ InitInputType R8Ki HubRot {3}{3} - - "Initial Hub direction cosine matrix" +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ InitInputType Logical DynamicSolve - .TRUE. - "Use dynamic solve option. Set to False for static solving (handled by glue code or driver code)." - + + +# Define outputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType R8Ki kp_coordinate {:}{:} - - "Key point coordinates array" - +typedef ^ InitOutputType IntKi kp_total - - - "Total number of key points" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_z {:} - - "Names of the constraint states used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states 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" - +#typedef ^ InitOutputType LOGICAL RotFrame_z {:} - - "Flag that tells FAST/MBC3 if the constraint states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - + +# ..... Blade Input file data........................................................................ +typedef ^ BladeInputData IntKi station_total - - - "Number of blade input stations" +typedef ^ BladeInputData IntKi format_index - - - "Number of blade input stations" +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ BladeInputData R8Ki station_eta {:} - - "Station location in eta [0,1]" +typedef ^ BladeInputData ^ stiff0 {:}{:}{:} - - "C/S stiffness matrix arrays" +typedef ^ BladeInputData ^ mass0 {:}{:}{:} - - "C/S mass matrix arrays" +typedef ^ BladeInputData ^ beta {6} - - "Damping Coefficient" - +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +typedef ^ BladeInputData IntKi damp_flag - - - "Damping Flag: 0-No Damping, 1-Damped" + + +# ..... Input file data.............................................................................. +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary Input file data...................................................................... +typedef ^ BD_InputFile IntKi member_total - - - "Total number of members" - +typedef ^ BD_InputFile IntKi kp_total - - - "Total number of key point" - +typedef ^ BD_InputFile IntKi kp_member {:} - - "Number of key points in each member" - +typedef ^ BD_InputFile IntKi order_elem - - - "Order of interpolation (basis) function" - +typedef ^ BD_InputFile IntKi load_retries - - - "Maximum Number of factored load retries" - +typedef ^ BD_InputFile IntKi NRMax - - - "Max number of iterations in Newton Raphson algorithm" - +typedef ^ BD_InputFile IntKi quadrature - - - "Quadrature: 1: Gauss; 2: Trapezoidal" - +typedef ^ BD_InputFile IntKi n_fact - - - "Factorization frequency" - +typedef ^ BD_InputFile IntKi refine - - - "FE mesh refinement factor for trapezoidal quadrature" - +typedef ^ BD_InputFile DbKi rhoinf - - - "Numerical damping parameter for generalized-alpha integrator" - +typedef ^ BD_InputFile DbKi DTBeam - - - "Time interval for BeamDyn calculations {or default} (s)" - +typedef ^ BD_InputFile BladeInputData InpBl - - - "Input data for individual blades" "see BladeInputData Type" +typedef ^ BD_InputFile CHARACTER(1024) BldFile - - - "Name of blade input file" +typedef ^ BD_InputFile Logical UsePitchAct - - - "Whether to use a pitch actuator inside BeamDyn" (flag) +typedef ^ BD_InputFile Logical QuasiStaticInit - - - "Use quasistatic pre-conditioning with centripetal accelerations in initialization (flag) [dynamic solve and enFAST only]" - +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ BD_InputFile R8Ki stop_tol - - - "Tolerance for stopping criterion" - +typedef ^ BD_InputFile ^ tngt_stf_pert - - - "Perturbation size for computing finite differenced tangent stiffness" - +typedef ^ BD_InputFile ^ tngt_stf_difftol - - - "When comparing tangent stiffness matrix, stop simulation if error greater than this" - +typedef ^ BD_InputFile ^ kp_coordinate {:}{:} - - "Key point coordinates array" - +typedef ^ BD_InputFile ^ pitchJ - - - "Pitch actuator inertia" (kg-m^2) +typedef ^ BD_InputFile ^ pitchK - - - "Pitch actuator stiffness" (kg-m^2/s^2) +typedef ^ BD_InputFile ^ pitchC - - - "Pitch actuator damping" - (kg-m^2/s) +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +typedef ^ BD_InputFile Logical Echo - - - "Echo" - +typedef ^ BD_InputFile Logical RotStates - .TRUE. - "Orient states in rotating frame during linearization? (flag)" - +typedef ^ BD_InputFile Logical RelStates - .FALSE. - "Define states relative to root motion during linearization? (flag)" - +typedef ^ BD_InputFile Logical tngt_stf_fd - - - "Flag to compute tangent stifness matrix via finite difference" - +typedef ^ BD_InputFile Logical tngt_stf_comp - - - "Flag to compare finite differenced and analytical tangent stifness" - +typedef ^ BD_InputFile IntKi NNodeOuts - - - "Number of node outputs [0 - 9]" - +typedef ^ BD_InputFile IntKi OutNd {9} - - "Nodes whose values will be output" - +typedef ^ BD_InputFile IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ BD_InputFile CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - +typedef ^ BD_InputFile LOGICAL SumPrint - - - "Print summary data to file? (.sum)" - +typedef ^ BD_InputFile CHARACTER(20) OutFmt - - - "Format specifier" - + +# ..... BldNdOuts ............................................................................................ +typedef ^ BD_InputFile IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (BD_BldNdOuts)" - +typedef ^ BD_InputFile CHARACTER(ChanLen) BldNd_OutList {:} - - "List of user-requested output channels (BD_BldNdOuts)" - +typedef ^ BD_InputFile IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (BD_BldNdOuts)" - +typedef ^ BD_InputFile CHARACTER(1024) BldNd_BlOutNd_Str - - - "String to parse for the blade nodes to actually output (BD_BldNdOuts)" - + + +# ..... States +# .................................................................................................................... +# Define continuous (differentiable) states here: +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ ContinuousStateType R8Ki q {:}{:} - - "q - displacement (1:3), and rotation displacement parameters (4:6)" m,- #BDKi +typedef ^ ContinuousStateType ^ dqdt {:}{:} - - "dqdt - velocity" m/s #BDKi +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +# Define discrete (nondifferentiable) states here: +#typedef ^ BD_DiscreteStateType ReKi rot {3} - - "For filter" - +typedef ^ BD_DiscreteStateType ReKi thetaP - - - "Pitch angle state" - +typedef ^ BD_DiscreteStateType ReKi thetaPD - - - "Pitch rate state" - + +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "A variable, Replace if you have constraint states" - + +# Define any data that are not considered actual states here: +# e.g. data used only for efficiency purposes (indices for searching in an array, copies of previous calculations of output +# at a given time, etc.) +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ OtherStateType R8Ki acc {:}{:} - - "Acceleration (dqdtdt)" +typedef ^ OtherStateType ^ xcc {:}{:} - - "Algorithm acceleration in GA2: (1-alpha_m)*xcc_(n+1) = (1-alpha_f)*Acc_(n+1) + alpha_f*Acc_n - alpha_m*xcc_n" +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +typedef ^ OtherStateType Logical InitAcc - - - "flag to determine if accerlerations have been initialized in updateStates" +typedef ^ OtherStateType Logical RunQuasiStaticInit - - - "flag to determine if quasi-static solution initialization should be run again (with load inputs)" - + + +# Quadrature point info that does not change throughout the simulation +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ qpParam R8Ki mmm :: - - "Mass at current QP" - +typedef ^ ^ ^ mEta ::: - - "Center of mass location times mass: (m*X_cm, m*Y_cm, m*Z_cm) where X_cm = 0" - +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + + + +# ..... 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 DbKi dt - - - "module dt" s +typedef ^ ParameterType DbKi coef {9} - - "GA2 Coefficient" - +typedef ^ ParameterType DbKi rhoinf - - - "Numerical Damping Coefficient for GA2" +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ ParameterType R8Ki uuN0 {:}{:}{:} - - "Initial Postion Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element)" - +typedef ^ ParameterType ^ Stif0_QP {:}{:}{:} - - "Sectional Stiffness Properties at quadrature points (6x6xqp)" - +typedef ^ ParameterType ^ Mass0_QP {:}{:}{:} - - "Sectional Mass Properties at quadrature points (6x6xqp)" - +typedef ^ ParameterType ^ gravity {3} - - "Gravitational acceleration" m/s^2 +typedef ^ ParameterType ^ segment_eta {:} - - "Array stored length ratio of each segment w.r.t. member it lies in" - +typedef ^ ParameterType ^ member_eta {:} - - "Array stored length ratio of each member w.r.t. entire blade" - +typedef ^ ParameterType ^ blade_length - - - "Blade Length" - +typedef ^ ParameterType ^ blade_mass - - - "Blade mass" - +typedef ^ ParameterType ^ blade_CG {3} - - "Blade center of gravity" - +typedef ^ ParameterType ^ blade_IN {3}{3} - - "Blade Length" - +typedef ^ ParameterType ^ beta {6} - - "Damping Coefficient" - +typedef ^ ParameterType ^ tol - - - "Tolerance used in stopping criterion" - +typedef ^ ParameterType ^ GlbPos {3} - - "Initial Position Vector between origins of Global and blade frames (BD coordinates)" - +typedef ^ ParameterType ^ GlbRot {3}{3} - - "Initial Rotation Tensor between Global and Blade frames (BD coordinates; transfers local to global)" - +typedef ^ ParameterType ^ Glb_crv {3} - - "CRV parameters of GlbRot" - +typedef ^ ParameterType ^ QPtN {:} - - "Quadrature (QuadPt) point locations in natural frame [-1, 1]" - +typedef ^ ParameterType ^ QPtWeight {:} - - "Weights at each quadrature point (QuadPt)" - +typedef ^ ParameterType ^ Shp {:}{:} - - "Shape function matrix (index 1 = FE nodes; index 2=quadrature points)" - +typedef ^ ParameterType ^ ShpDer {:}{:} - - "Derivative of shape function matrix (index 1 = FE nodes; index 2=quadrature points)" - +typedef ^ ParameterType ^ Jacobian {:}{:} - - "Jacobian value at each quadrature point" - +typedef ^ ParameterType ^ uu0 {:}{:}{:} - - "Initial Disp/Rot value at quadrature point (at T=0)" - +typedef ^ ParameterType ^ rrN0 {:}{:}{:} - - "Initial relative rotation array, relative to root (at T=0) (index 1=rot DOF; index 2=FE nodes; index 3=element)" - +typedef ^ ParameterType ^ E10 {:}{:}{:} - - "Initial E10 at quadrature point" - +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +typedef ^ ParameterType IntKi nodes_per_elem - - - "Finite element (GLL) nodes per element" - +typedef ^ ParameterType IntKi node_elem_idx {:}{:} - - "Index to first and last nodes of element in p%node_total sized arrays" - +typedef ^ ParameterType IntKi refine - - - "FE mesh refinement factor for trapezoidal quadrature" - +typedef ^ ParameterType IntKi dof_node - - - "dof per node" - +typedef ^ ParameterType IntKi dof_elem - - - "dof per element" - +typedef ^ ParameterType IntKi rot_elem - - - "rotational dof per element" - +typedef ^ ParameterType IntKi elem_total - - - "Total number of elements" - +typedef ^ ParameterType IntKi node_total - - - "Total number of finite element (GLL) nodes" - +typedef ^ ParameterType IntKi dof_total - - - "Total number of dofs" - +typedef ^ ParameterType IntKi nqp - - - "Number of quadrature points (per element)" - +typedef ^ ParameterType IntKi analysis_type - - - "analysis_type flag" - +typedef ^ ParameterType IntKi damp_flag - - - "damping flag" - +typedef ^ ParameterType IntKi ld_retries - - - "Maximum Number of factored load retries" - +typedef ^ ParameterType IntKi niter - - - "Maximum number of iterations in Newton-Raphson algorithm" - +typedef ^ ParameterType IntKi quadrature - - - "Quadrature method: 1 Gauss 2 Trapezoidal" - +typedef ^ ParameterType IntKi n_fact - - - "Factorization frequency" - +typedef ^ ParameterType Logical OutInputs - - - "Determines if we've asked to output the inputs (do we need mesh transfer?)" - +typedef ^ ParameterType IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType IntKi NNodeOuts - - - "Number of nodes to output data to a file[0 - 9]" - +typedef ^ ParameterType IntKi OutNd {9} - - "Nodes whose values will be output" - +typedef ^ ParameterType IntKi NdIndx {:} - - "Index into BldMotion mesh (to number the nodes for output without using collocated nodes)" - +typedef ^ ParameterType IntKi NdIndxInverse {:} - - "Index from BldMotion mesh to unique nodes (to number the nodes for output without using collocated nodes)" - +typedef ^ ParameterType IntKi OutNd2NdElem {:}{:} - - "To go from an output node number to a node/elem pair" - +typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format specifier" - +typedef ^ ParameterType Logical UsePitchAct - - - "Whether to use a pitch actuator inside BeamDyn" (flag) +typedef ^ ParameterType ReKi pitchJ - - - "Pitch actuator inertia" (kg-m^2) +typedef ^ ParameterType ReKi pitchK - - - "Pitch actuator stiffness" (kg-m^2/s^2) +typedef ^ ParameterType ReKi pitchC - - - "Pitch actuator damping" - (kg-m^2/s) +typedef ^ ParameterType ReKi torqM {2}{2} - - "Pitch actuator matrix: (I-hA)^-1" - +typedef ^ ParameterType qpParam qp - - - "Quadrature point info that does not change during simulation" - +typedef ^ ParameterType IntKi qp_indx_offset - - - "Offset for computing index of the quadrature arrays (gauss skips the first [end-point] node)" - +typedef ^ ParameterType IntKi BldMotionNodeLoc - - - "switch to determine where the nodes on the blade motion mesh should be located 1=FE (GLL) nodes; 2=quadrature nodes; 3=blade input stations" +typedef ^ ParameterType Logical tngt_stf_fd - - - "Flag to compute tangent stifness matrix via finite difference" - +typedef ^ ParameterType Logical tngt_stf_comp - - - "Flag to compare finite differenced and analytical tangent stifness" - +typedef ^ ParameterType R8Ki tngt_stf_pert - - - "Perturbation size for computing finite differenced tangent stiffness" - +typedef ^ ParameterType R8Ki tngt_stf_difftol - - - "When comparing tangent stiffness matrix, stop simulation if error greater than this" - +# .... BD_BlNdOuts ........................................................................................................ +typedef ^ ParameterType IntKi BldNd_NumOuts - - - "[BD_BldNdOuts] Number of requested output channels per blade node" - +typedef ^ ParameterType IntKi BldNd_TotNumOuts - - - "[BD_BldNdOuts] Total number of requested output channels of blade node information (equal to BldNd_NumOuts * BldNd_BlOutNd)" - +typedef ^ ParameterType OutParmType BldNd_OutParam {:} - - "[BD_BldNdOuts] Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType IntKi BldNd_BlOutNd {:} - - "[BD_BldNdOuts] The blade nodes to actually output" - +# .... arrays for optimization ........................................................................................................ +typedef ^ ParameterType R8Ki QPtw_Shp_Shp_Jac {:}{:}{:}{:} - - "optimization variable: QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) = p%Shp(i,idx_qp)*p%Shp(j,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem)" - +typedef ^ ParameterType ^ QPtw_Shp_ShpDer {:}{:}{:} - - "optimization variable: QPtw_Shp_ShpDer(idx_qp,i,j) = p%Shp(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp)" - +typedef ^ ParameterType ^ QPtw_ShpDer_ShpDer_Jac {:}{:}{:}{:} - - "optimization variable: QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) = p%ShpDer(i,idx_qp)*p%ShpDer(j,idx_qp)*p%QPtWeight(idx_qp)/p%Jacobian(idx_qp,nelem)" - +typedef ^ ParameterType ^ QPtw_Shp_Jac {:}{:}{:} - - "optimization variable: QPtw_Shp_Jac(idx_qp,i,nelem) = p%Shp(i,idx_qp)*p%QPtWeight(idx_qp)*p%Jacobian(idx_qp,nelem)" - +typedef ^ ParameterType ^ QPtw_ShpDer {:}{:} - - "optimization variable: QPtw_ShpDer(idx_qp,i) = p%ShpDer(i,idx_qp)*p%QPtWeight(idx_qp)" - +typedef ^ ParameterType ^ FEweight {:}{:} - - "weighting factors for integrating local sectional loads" - + +typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ParameterType R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" +typedef ^ ParameterType R8Ki dx {6} - - "vector that determines size of perturbation for x (continuous states)" +typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - +typedef ^ ParameterType Integer Jac_nx - - - "half the number of continuous states in jacobian matrix" - +typedef ^ ParameterType logical RotStates - - - "Orient states in rotating frame during linearization? (flag)" - +typedef ^ ParameterType Logical RelStates - - - "Define states relative to root motion during linearization? (flag)" - + + +# ..... Inputs +# .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef ^ InputType MeshType RootMotion - - - "contains motion" - +typedef ^ InputType MeshType PointLoad - - - "Applied point forces along beam axis" - +typedef ^ InputType MeshType DistrLoad - - - "Applied distributed forces along beam axis" - +typedef ^ InputType MeshType HubMotion - - - "motion (orientation) at the hub" - + +# ..... Outputs +# ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType ReactionForce - - - "contains force and moments" - +typedef ^ OutputType MeshType BldMotion - - - "Motion (disp,rot,vel, acc) along beam axis" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi RootMxr - - - "x-component of the root reaction moment expressed in r (used for ServoDyn Bladed DLL Interface)" "Nm" +typedef ^ OutputType ReKi RootMyr - - - "y-component of the root reaction moment expressed in r (used for ServoDyn Bladed DLL Interface)" "Nm" +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" + + + +# ..... EQMotion_QP variables .................................. +# Variables for equation of motion calculation at current quadrature point. This will be a subtype of MiscVars. +# These variables are dimensioned with p%nqp,p%elem_total as the last two dimensions +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ EqMotionQP R8Ki uuu ::: - - "Displacement and rotation field [u c] at current QP" - +typedef ^ EqMotionQP ^ uup ::: - - "Derivative of uuu with respect to X at current QP" - +typedef ^ EqMotionQP ^ vvv ::: - - "Translational velocity and rotational parameter velocity (at current QP)" - +typedef ^ EqMotionQP ^ vvp ::: - - "Derivative of vvv with respect to X" - +typedef ^ EqMotionQP ^ aaa ::: - - "Translational acceleration and rotational parameter acceration (at current QP)" - + +#This may not be needed at all. Would be useful only if we decide to use something other than the quadrature points for the output mesh. In that case, don't put it in m%qp%q +#typedef ^ EqMotionQP ^ q ::: - - "Displacement and rotation for all quadrature points -- Calculated from x%q after solve. size 6 x p%nqp x p%elem_total" - + +typedef ^ EqMotionQP ^ RR0 :::: - - "Rotation tensor at current QP \f$ \left(\underline{\underline{R}}\underline{\underline{R}}_0\right) \f$" - +typedef ^ EqMotionQP ^ kappa ::: - - "Curvature vector \f$ \underline{k} \f$ at current QP (note this is not \kappa, but a term in \kappa)" - +typedef ^ EqMotionQP ^ E1 ::: - - "\vec{e_1} = x_0^\prime + u^\prime (3) at current QP" - +typedef ^ EqMotionQP ^ Stif :::: - - "C/S stiffness matrix resolved in inertial frame at current QP. 6x6" - + +typedef ^ EqMotionQP ^ Fb ::: - - "Gyroscopic forces at current QP. 6" - +typedef ^ EqMotionQP ^ Fc ::: - - "Elastic force \f$ \underline{F}^c \f$ at current QP. 6" - +typedef ^ EqMotionQP ^ Fd ::: - - "Elastic force \f$ \underline{F}^d \f$ at current QP. 6" - +typedef ^ EqMotionQP ^ Fg ::: - - "Gravity forces at current QP. 6" - +typedef ^ EqMotionQP ^ Fi ::: - - "Inertial forces at current QP. 6" - +typedef ^ EqMotionQP ^ Ftemp ::: - - "Sum of some of the forces at current QP. 6" - + +typedef ^ EqMotionQP ^ RR0mEta ::: - - "RR0 times Center of mass location times mass: (m*X_cm, m*Y_cm, m*Z_cm) where X_cm = 0" - +typedef ^ EqMotionQP ^ rho :::: - - "Tensor of inertia resolved in inertia frame at quadrature point. 3x3" - +typedef ^ EqMotionQP ^ betaC :::: - - "No idea. Used in dissipative force. 6x6" - + +# Inertial force terms +typedef ^ EqMotionQP ^ Gi :::: - - "Gyroscopic matrix for inertial force. 6x6" - +typedef ^ EqMotionQP ^ Ki :::: - - "Stiffness matrix for inertial force. 6x6" - +typedef ^ EqMotionQP ^ Mi :::: - - "Mass matrix for inertial force. 6x6" - + +# Elastic force terms +typedef ^ EqMotionQP ^ Oe :::: - - "\f$ \underline{\underline{\mathcal{O}}} \f$ from equation (19) of NREL CP-2C00-60759. 6x6" - +typedef ^ EqMotionQP ^ Pe :::: - - "\f$ \underline{\underline{\mathcal{P}}} \f$ from equation (20) of NREL CP-2C00-60759. 6x6" - +typedef ^ EqMotionQP ^ Qe :::: - - "\f$ \underline{\underline{\mathcal{Q}}} \f$ from equation (21) of NREL CP-2C00-60759. 6x6" - + +# Disspipative terms +typedef ^ EqMotionQP ^ Gd :::: - - "Dissipative term for gyroscopic term. 6x6" - +typedef ^ EqMotionQP ^ Od :::: - - "Dissipative term on O. 6x6" - +typedef ^ EqMotionQP ^ Pd :::: - - "Dissipative term on P. 6x6" - +typedef ^ EqMotionQP ^ Qd :::: - - "Dissipative term on Q. 6x6" - +typedef ^ EqMotionQP ^ Sd :::: - - "Dissipative term on S. 6x6" - +typedef ^ EqMotionQP ^ Xd :::: - - "Dissipative term on X. 6x6" - +typedef ^ EqMotionQP ^ Yd :::: - - "Dissipative term on Y. 6x6" - +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + + +# ..... 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 MeshType u_DistrLoad_at_y - - - "input loads at output node locations" - +typedef ^ MiscVarType MeshType y_BldMotion_at_u - - - "output motions at input node locations (displacements necessary for mapping loads)" - +typedef ^ MiscVarType MeshMapType Map_u_DistrLoad_to_y - - - "mapping of input loads to output node locations" - +typedef ^ MiscVarType MeshMapType Map_y_BldMotion_to_u - - - "mapping of output motions to input node locations (for load transfer)" - +typedef ^ MiscVarType IntKi Un_Sum - - - "unit number of summary file" - +typedef ^ MiscVarType EqMotionQP qp - - - "Quadrature point calculation info" - +typedef ^ MiscVarType R8Ki lin_A {:}{:} - - "A (dXdx) matrix used in linearization (before RotState is applied)" - +typedef ^ MiscVarType R8Ki lin_C {:}{:} - - "C (dYdx) matrix used in linearization (before RotState is applied)" - + +# +# these are temporary variables placed in a type so we don't allocate and deallocate each time step +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +#the following are BDKi = R8Ki +typedef ^ MiscVarType R8Ki Nrrr ::: - - "Rotation parameters relative to root node, from Nuuu (at GLL points)" - +typedef ^ MiscVarType ^ elf {:}{:} - - "" - +typedef ^ MiscVarType ^ EFint {:}{:}{:} - - "Elastic forces internal to blade. For output calculations only." - +typedef ^ MiscVarType ^ elk {:}{:}{:}{:} - - "" - +typedef ^ MiscVarType ^ elg {:}{:}{:}{:} - - "" - +typedef ^ MiscVarType ^ elm {:}{:}{:}{:} - - "" - +typedef ^ MiscVarType ^ DistrLoad_QP {:}{:}{:} - - "Copy of the distributed load, in the BD reference frame" - +typedef ^ MiscVarType ^ PointLoadLcl {:}{:} - - "Copy of the point loads, in the BD reference frame" - +typedef ^ MiscVarType ^ StifK {:}{:}{:}{:} - - "Stiffness Matrix" - +typedef ^ MiscVarType ^ MassM {:}{:}{:}{:} - - "Mass Matrix" - +typedef ^ MiscVarType ^ DampG {:}{:}{:}{:} - - "Damping Matrix" - +typedef ^ MiscVarType ^ StifK_fd {:}{:}{:}{:} - - "Finite differenced Stiffness Matrix" - +typedef ^ MiscVarType ^ MassM_fd {:}{:}{:}{:} - - "Finite differenced Mass Matrix" - +typedef ^ MiscVarType ^ DampG_fd {:}{:}{:}{:} - - "Finite differenced Damping Matrix" - +typedef ^ MiscVarType ^ RHS {:}{:} - - "Right-hand-side vector" - +typedef ^ MiscVarType ^ RHS_p {:}{:} - - "Positive fd perturbation of RHS" - +typedef ^ MiscVarType ^ RHS_m {:}{:} - - "Negative fd perturbation of RHS" - +typedef ^ MiscVarType ^ BldInternalForceFE {:}{:} - - "Force/Moment array for internal force calculations at FE" - +typedef ^ MiscVarType ^ BldInternalForceQP {:}{:} - - "Force/Moment array for internal force calculations at QP" - +typedef ^ MiscVarType ^ FirstNodeReactionLclForceMoment {:} - - "Force/Moment array for first node reaction. Needed in InternalForce calculations." - +typedef ^ MiscVarType ^ Solution {:}{:} - - "Result from LAPACK solve (X from A*X = B solve)" - +# arrays for lapack routines +typedef ^ MiscVarType ^ LP_StifK {:}{:} - - "Stiffness Matrix" - +typedef ^ MiscVarType ^ LP_MassM {:}{:} - - "Mass Matrix" - +typedef ^ MiscVarType ^ LP_MassM_LU {:}{:} - - "Mass Matrix for LU" - +typedef ^ MiscVarType ^ LP_RHS {:} - - "Right-hand-side vector" - +typedef ^ MiscVarType ^ LP_StifK_LU {:}{:} - - "Stiffness Matrix for LU" - +typedef ^ MiscVarType ^ LP_RHS_LU {:} - - "Right-hand-side vector for LU" - +#end of BDKi-type variables +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +typedef ^ MiscVarType IntKi LP_indx {:} - - "Index vector for LU" - +typedef ^ MiscVarType BD_InputType u - - - "Inputs converted to the internal BD coordinate system" - +typedef ^ MiscVarType BD_InputType u2 - - - "Inputs in the FAST coordinate system, possibly modified by pitch actuator" - + diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_CheckRotMat.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_CheckRotMat.F90 new file mode 100644 index 000000000..c1750fd29 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_CheckRotMat.F90 @@ -0,0 +1,44 @@ +@test +subroutine test_BD_CheckRotMat() + ! test branches + ! - known valid rotation matrix: pi about x-axis + ! - known invalid rotation matrix: halve the angle of the diagonal elements + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi) :: n(3) + real(BDKi) :: angle + real(BDKi) :: testR(3,3) + integer(IntKi) :: ErrStat + character(ErrMsgLen) :: ErrMsg + character(1024) :: testname + + ! initialize NWTC_Num constants + call SetConstants() + + ! set the rotation axis and angle for all tests + n = (/ 1, 0, 0 /) ! x axis + angle = Pi + + + ! -------------------------------------------------------------------------- + testname = "known valid rotation matrix: pi about x-axis:" + testR = calcRotationMatrix(angle, n) + call BD_CheckRotMat(testR, ErrStat, ErrMsg) + @assertEqual(0, ErrStat, testname) + + + ! -------------------------------------------------------------------------- + testname = "known invalid rotation matrix: halve the angle of the diagonal elements:" + ! this should produce a fatal error (ErrStat = 4) + testR(:,2) = (/ testR(1,2), cos(real(Pi/2, BDKi)), testR(3,2) /) + testR(:,3) = (/ testR(1,2), testR(2,2), cos(real(Pi/2, BDKi)) /) + call BD_CheckRotMat(testR, ErrStat, ErrMsg) + @assertEqual(4, ErrStat, testname) + +end subroutine test_BD_CheckRotMat diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_ComputeIniNodalCrv.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_ComputeIniNodalCrv.F90 new file mode 100644 index 000000000..17f476db3 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_ComputeIniNodalCrv.F90 @@ -0,0 +1,83 @@ +@test +subroutine test_BD_ComputeIniNodalCrv() + ! test branches + ! - simple rotation with known parameters: Pi on xaxis + ! - 0 rotation + ! - small rotation with baseline WM parameters calculated + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi), dimension(3,3) :: r + real(BDKi), dimension(3) :: test_wmparams, baseline_wmparams + real(BDKi) :: angle, param, n(3) + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "Tangent aligned with z-axis and 0 degree twist:" + n = (/ real(0.0, BDKi), real(0.0, BDKi), real(1.0, BDKi) /) ! tangent axis + angle = 0 + + ! Baseline Wiener-Milenkovic parameters + baseline_wmparams = (/ 0.0, 0.0, 0.0 /) + + call BD_ComputeIniNodalCrv(n, angle, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + + ! -------------------------------------------------------------------------- + testname = "Tangent at 45 degree w.r.t. y-axis and 0 degree twist:" + n = (/ 1.0_BDKi/sqrt(2.0_BDKi), 0.0_BDKi, 1.0_BDKi/sqrt(2.0_BDKi) /) ! tangent axis + angle = 0.0_BDKi + + ! Baseline Wiener-Milenkovic parameters + param = 4*tan((Pi_D/4)/4) + baseline_wmparams = (/ real(0.0, BDKi), param, real(0.0, BDKi) /) + + call BD_ComputeIniNodalCrv(n, angle, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + + ! -------------------------------------------------------------------------- + testname = "Tangent at -45 degree w.r.t. x-axis and 0 degree twist:" + n = (/ 0.0_BDKi, 1.0_BDKi/sqrt(2.0_BDKi), 1.0_BDKi/sqrt(2.0_BDKi) /) ! tangent axis + angle = 0.0_BDKi + + ! Baseline Wiener-Milenkovic parameters + param = 4*tan((-Pi_D/4)/4) + baseline_wmparams = (/ param, real(0.0, BDKi), real(0.0, BDKi) /) + + call BD_ComputeIniNodalCrv(n, angle, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + + ! -------------------------------------------------------------------------- + testname = "Tangent along z-axis with 45 degree twist:" + n = (/ real(0.0, BDKi), real(0.0, BDKi), 1.0_BDKi /) ! tangent axis + angle = 45.0_BDKi + + ! Baseline Wiener-Milenkovic parameters + param = 4*tan((Pi_D/4)/4) + baseline_wmparams = (/ real(0.0, BDKi), real(0.0, BDKi), param /) + + call BD_ComputeIniNodalCrv(n, angle, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + +end subroutine test_BD_ComputeIniNodalCrv diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_CrvCompose.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_CrvCompose.F90 new file mode 100644 index 000000000..a376a6af8 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_CrvCompose.F90 @@ -0,0 +1,137 @@ +@test +subroutine test_BD_CrvCompose() + ! test branches + ! - both rotation angles 0, no transpose of input rotations (flag = 0) + ! - delta2 > 0, no transpose of input rotations (flag = 0) + ! - delta2 < 0, no transpose of input rotations (flag = 0) + ! - flag = 1 + ! - flag = 2 + ! - flag = 3 + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + ! input rotation axis and angle + real(BDKi), dimension(3) :: n1, n2 + real(BDKi) :: angle1, angle2 + + ! result rotations + real(BDKi), dimension(3,3) :: testrotation, baselinerotation, r1, r2 + real(BDKi), dimension(3) :: composedparams + + ! other test settings + integer :: flag + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! set the rotation axes for all tests + n1 = (/ 1, 0, 0 /) ! x axis + n2 = (/ 0, 0, 1 /) ! z axis + + + ! -------------------------------------------------------------------------- + testname = "both rotation angles 0, no transpose of input rotations (flag = 0):" + angle1 = 0 ! 0 degrees + angle2 = 0 ! 0 degrees + flag = 0 + + ! both rotations should return an identity matrix + r1 = calcRotationMatrix(angle1, n1) + r2 = calcRotationMatrix(angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "delta2 > 0, no transpose of input rotations (flag = 0):" + angle1 = PiBy2_D ! 90 degrees + angle2 = PiBy2_D ! 90 degrees + flag = 0 + + r1 = calcRotationMatrix(angle1, n1) + r2 = calcRotationMatrix(angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "delta2 < 0, no transpose of input rotations (flag = 0):" + angle1 = PiBy2_D ! 90 degrees + angle2 = 1.5*Pi ! 270 degrees + flag = 0 + + r1 = calcRotationMatrix(angle1, n1) + r2 = calcRotationMatrix(angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "delta2 > 0, transpose of first rotation (flag = 1):" + angle1 = PiBy2_D ! 90 degrees + angle2 = PiBy2_D ! 90 degrees + flag = 1 + + r1 = calcRotationMatrix(-angle1, n1) + r2 = calcRotationMatrix(angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "delta2 > 0, transpose of second rotation (flag = 2):" + angle1 = PiBy2_D ! 90 degrees + angle2 = PiBy2_D ! 90 degrees + flag = 2 + + r1 = calcRotationMatrix(angle1, n1) + r2 = calcRotationMatrix(-angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "delta2 > 0, transpose of both rotations (flag = 3):" + angle1 = PiBy2_D ! 90 degrees + angle2 = PiBy2_D ! 90 degrees + flag = 3 + + r1 = calcRotationMatrix(-angle1, n1) + r2 = calcRotationMatrix(-angle2, n2) + baselinerotation = matmul(r1,r2) + + call BD_CrvCompose(composedparams, 4*tan(angle1/4)*n1, 4*tan(angle2/4)*n2, flag) + call BD_CrvMatrixR(composedparams, testrotation) + + @assertEqual(baselinerotation, testrotation, tolerance, testname) + +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_CrvExtractCrv.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_CrvExtractCrv.F90 new file mode 100644 index 000000000..bd8143f18 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_CrvExtractCrv.F90 @@ -0,0 +1,73 @@ +@test +subroutine test_BD_CrvExtractCrv() + ! test branches + ! - simple rotation with known parameters: Pi on xaxis + ! - 0 rotation + ! - small rotation with baseline WM parameters calculated + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi), dimension(3,3) :: r + real(BDKi), dimension(3) :: test_wmparams, baseline_wmparams + real(BDKi) :: angle, n(3) + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! set the rotation axis for all tests + n = (/ 1, 0, 0 /) ! x axis + + + ! -------------------------------------------------------------------------- + testname = "simple rotation with known parameters: Pi on xaxis:" + angle = Pi_D + + ! Wiener-Milenkovic parameters are <4.0, 0.0, 0.0> + baseline_wmparams = (/ 4.0, 0.0, 0.0 /) + + r = RonXAxis(angle) + call BD_CrvExtractCrv(r, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "0 rotation:" + angle = 0 + + ! Wiener-Milenkovic parameters are <0.0, 0.0, 0.0> + baseline_wmparams = (/ 0.0, 0.0, 0.0 /) + + r = RonXAxis(angle) + call BD_CrvExtractCrv(r, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "small rotation with baseline WM parameters calculated:" + angle = 0.1*Pi_D + + ! Wiener-Milenkovic parameters are calculated; note tangent is asymptotic at +/- pi/2 + baseline_wmparams = 4*tan(angle/4)*n + + r = RonXAxis(angle) + call BD_CrvExtractCrv(r, test_wmparams, ErrStat, ErrMsg) + + @assertEqual(0.0_BDKi, ErrStat, tolerance, testname) + @assertEqual(baseline_wmparams, test_wmparams, tolerance, testname) + +end subroutine test_BD_CrvExtractCrv diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixH.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixH.F90 new file mode 100644 index 000000000..5f7ff9e9b --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixH.F90 @@ -0,0 +1,90 @@ +@test +subroutine test_BD_CrvMatrixH() + ! test branches + ! - simple rotation with known parameters: Pi on xaxis + ! - 0 rotation + ! - small rotation with baseline WM parameters calculated + + ! TODO + ! invalid wm parameters (if thats a thing) + ! does the implemented WM formulation have any boundaries? + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi), dimension(3,3) :: testH, baselineH + real(BDKi), dimension(3) :: wmparams + real(BDKi) :: angle, n(3) + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! set the rotation axis for all tests + n = (/ 1, 0, 0 /) ! x axis + + + ! -------------------------------------------------------------------------- + testname = "simple rotation with known parameters: Pi on xaxis:" + angle = Pi_D + + ! Wiener-Milenkovic parameters are <4.0, 0.0, 0.0> + wmparams = (/ 4.0, 0.0, 0.0 /) + + baselineH = H(wmparams) + + call BD_CrvMatrixH(wmparams, testH) + + @assertEqual(baselineH, testH, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "0 rotation:" + angle = 0 + + ! Wiener-Milenkovic parameters are <0.0, 0.0, 0.0> + wmparams = (/ 0.0, 0.0, 0.0 /) + + baselineH = H(wmparams) + + call BD_CrvMatrixH(wmparams, testH) + + @assertEqual(baselineH, testH, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "small rotation with baseline WM parameters calculated:" + angle = 0.1*Pi_D + + ! Wiener-Milenkovic parameters are calculated; note tangent is asymptotic at +/- pi/2 + wmparams = 4*tan(angle/4)*n + + baselineH = H(wmparams) + + call BD_CrvMatrixH(wmparams, testH) + + @assertEqual(baselineH, testH, tolerance, testname) + + contains + function H(c) + real(BDKi) :: c0, c(3) + real(BDKi) :: H(3,3) + + c0 = 2.0 - dot_product(c,c) / 8.0 + + H(1,:) = (/ c0 + c(1)*c(1)/4, c(1)*c(2)/4 - c(3), c(1)*c(3)/4 + c(2) /) + H(2,:) = (/ c(1)*c(2)/4 + c(3), c0 + c(2)*c(2)/4, c(2)*c(3)/4 - c(1) /) + H(3,:) = (/ c(1)*c(3)/4 - c(2), c(2)*c(3)/4 + c(1), c0 + c(3)*c(3)/4 /) + H = 2*H/(4-c0)**2 + + end function +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixR.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixR.F90 new file mode 100644 index 000000000..b2cf77912 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_CrvMatrixR.F90 @@ -0,0 +1,74 @@ +@test +subroutine test_BD_CrvMatrixR() + ! test branches + ! - simple rotation with known parameters: Pi on xaxis + ! - 0 rotation + ! - small rotation with baseline WM parameters calculated + + ! TODO + ! invalid wm parameters (if thats a thing) + ! does the implemented WM formulation have any boundaries? + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi), dimension(3,3) :: testR, baselineR + real(BDKi), dimension(3) :: wmparams + real(BDKi) :: angle, n(3) + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! set the rotation axis for all tests + n = (/ 1, 0, 0 /) ! x axis + + + ! -------------------------------------------------------------------------- + testname = "simple rotation with known parameters: Pi on xaxis:" + angle = Pi_D + + baselineR = RonXAxis(angle) + + ! Wiener-Milenkovic parameters are <4.0, 0.0, 0.0> + wmparams = (/ 4.0, 0.0, 0.0 /) + call BD_CrvMatrixR(wmparams, testR) + + @assertEqual(baselineR, testR, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "0 rotation:" + angle = 0 + + baselineR = RonXAxis(angle) + + ! Wiener-Milenkovic parameters are <0.0, 0.0, 0.0> + wmparams = (/ 0.0, 0.0, 0.0 /) + call BD_CrvMatrixR(wmparams, testR) + + @assertEqual(baselineR, testR, tolerance, testname) + + + ! -------------------------------------------------------------------------- + testname = "small rotation with baseline WM parameters calculated:" + angle = 0.1*Pi_D + + baselineR = RonXAxis(angle) + + ! Wiener-Milenkovic parameters are calculated; note tangent is asymptotic at +/- pi/2 + wmparams = 4*tan(angle/4)*n + call BD_CrvMatrixR(wmparams, testR) + + @assertEqual(baselineR, testR, tolerance, testname) + +end subroutine test_BD_CrvMatrixR diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_DistrLoadCopy.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_DistrLoadCopy.F90 new file mode 100644 index 000000000..bfa603751 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_DistrLoadCopy.F90 @@ -0,0 +1,46 @@ +@test +subroutine test_BD_DistrLoadCopy() + ! branches to test + ! - the 2D array is correctly stored in the 3D array + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer :: i, j + type(BD_ParameterType) :: parametertype + type(BD_InputType) :: inputtype + type(BD_MiscVarType) :: miscvartype + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + + ! -------------------------------------------------------------------------- + testname = "static simple beam under gravity:" + + ! build the parametertype, inputtype, and miscvartype + parametertype = simpleParameterType(1,16,16,0,1) + miscvartype = simpleMiscVarType(parametertype%nqp, parametertype%elem_total) + inputtype = simpleInputType(parametertype%nqp, parametertype%elem_total) + + call BD_DistrLoadCopy(parametertype, inputtype, miscvartype) + + do j = 1, parametertype%elem_total + do i = 1, parametertype%nqp + @assertEqual((/ 9*(j-1)+3*(i-1)+1, 9*(j-1)+3*(i-1)+2, 9*(j-1)+3*(i-1)+3 /), miscvartype%DistrLoad_QP(1:3,i,j)) + @assertEqual((/ -9*(j-1)-3*(i-1)-1, -9*(j-1)-3*(i-1)-2, -9*(j-1)-3*(i-1)-3 /), miscvartype%DistrLoad_QP(4:6,i,j)) + end do + end do + + call BD_DestroyParam(parametertype, ErrStat, ErrMsg) +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_GaussPointWeight.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_GaussPointWeight.F90 new file mode 100644 index 000000000..9464377b2 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_GaussPointWeight.F90 @@ -0,0 +1,123 @@ +@test +subroutine test_BD_GaussPointWeight() + ! test branches + ! - p = 1, invalid value + ! - p = 2, boundaries only + ! - p = 5, odd number + ! - p = 6, even number + ! - p = 97, large, prime number + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + integer :: p + real(BDKi), allocatable :: locations(:), weights(:) + real(BDKi), allocatable :: baselinelocations(:), baselineweights(:) + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-10 + + + ! the baseline solutions for this unit test can be calculated using the Gauss-Lobatto quadrature + ! the Python Numpy package provides this functionality with numpy.polynomial.legendre.leggauss. + ! the first array returned are locations and the second are the weights + ! >>> from numpy import polynomial + ! >>> polynomial.legendre.leggauss(2) + ! (array([-0.57735027, 0.57735027]), array([ 1., 1.])) + ! >>> polynomial.legendre.leggauss(5) + ! (array([-0.90617985, -0.53846931, 0. , 0.53846931, 0.90617985]), array([ 0.23692689, 0.47862867, 0.56888889, 0.47862867, 0.23692689])) + + + ! -------------------------------------------------------------------------- + testname = "p = 1, invalid value:" + p = 1 + call AllocAry(baselinelocations, p, "GLL baseline", ErrStat, ErrMsg) + call AllocAry(baselineweights, p, "GLL baseline", ErrStat, ErrMsg) + baselinelocations = (/ -0.57735026919, 0.57735026919 /) + baselineweights = (/ 1.0, 1.0/) + + call AllocAry(locations, p, "GLL nodes", ErrStat, ErrMsg) + call AllocAry(weights, p, "GLL weights", ErrStat, ErrMsg) + call BD_GaussPointWeight(p, locations, weights, ErrStat, ErrMsg) + + @assertEqual(4, ErrStat, testname) + + deallocate(baselinelocations) + deallocate(baselineweights) + deallocate(locations) + deallocate(weights) + + + ! -------------------------------------------------------------------------- + testname = "p = 2, boundaries only:" + p = 2 + call AllocAry(baselinelocations, p, "GLL baseline", ErrStat, ErrMsg) + call AllocAry(baselineweights, p, "GLL baseline", ErrStat, ErrMsg) + baselinelocations = (/ -0.57735026919, 0.57735026919 /) + baselineweights = (/ 1.0, 1.0/) + + call AllocAry(locations, p, "GLL nodes", ErrStat, ErrMsg) + call AllocAry(weights, p, "GLL weights", ErrStat, ErrMsg) + call BD_GaussPointWeight(p, locations, weights, ErrStat, ErrMsg) + + @assertEqual(baselinelocations, locations, tolerance, testname) + @assertEqual(baselineweights, weights, tolerance, testname) + + deallocate(baselinelocations) + deallocate(baselineweights) + deallocate(locations) + deallocate(weights) + + + ! -------------------------------------------------------------------------- + testname = "p = 5, odd number:" + p = 5 + call AllocAry(baselinelocations, p, "GLL baseline", ErrStat, ErrMsg) + call AllocAry(baselineweights, p, "GLL baseline", ErrStat, ErrMsg) + baselinelocations = (/ -0.906179845939, -0.538469310106, 0.0, 0.538469310106, 0.906179845939 /) + baselineweights = (/ 0.236926885056, 0.478628670499, 0.568888888889, 0.478628670499, 0.236926885056 /) + + call AllocAry(locations, p, "GLL nodes", ErrStat, ErrMsg) + call AllocAry(weights, p, "GLL weights", ErrStat, ErrMsg) + call BD_GaussPointWeight(p, locations, weights, ErrStat, ErrMsg) + + @assertEqual(baselinelocations, locations, tolerance, testname) + @assertEqual(baselineweights, weights, tolerance, testname) + + deallocate(baselinelocations) + deallocate(baselineweights) + deallocate(locations) + deallocate(weights) + + + ! -------------------------------------------------------------------------- + testname = "p = 6, even number:" + p = 6 + call AllocAry(baselinelocations, p, "GLL baseline", ErrStat, ErrMsg) + call AllocAry(baselineweights, p, "GLL baseline", ErrStat, ErrMsg) + baselinelocations = (/ -0.932469514203, -0.661209386466, -0.238619186083, 0.238619186083, 0.661209386466, 0.932469514203 /) + baselineweights = (/ 0.171324492379, 0.360761573048, 0.467913934573, 0.467913934573, 0.360761573048, 0.171324492379 /) + + call AllocAry(locations, p, "GLL nodes", ErrStat, ErrMsg) + call AllocAry(weights, p, "GLL weights", ErrStat, ErrMsg) + call BD_GaussPointWeight(p, locations, weights, ErrStat, ErrMsg) + + @assertEqual(baselinelocations, locations, tolerance, testname) + @assertEqual(baselineweights, weights, tolerance, testname) + + deallocate(baselinelocations) + deallocate(baselineweights) + deallocate(locations) + deallocate(weights) + +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_GenerateGLL.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_GenerateGLL.F90 new file mode 100644 index 000000000..d71e75895 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_GenerateGLL.F90 @@ -0,0 +1,117 @@ +@test +subroutine test_BD_GenerateGLL() + ! test branches + ! - p = 2, boundaries only + ! - p = 5, odd number + ! - p = 6, even number + ! - p = 97, large, prime number + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + integer :: p + real(BDKi), allocatable :: gll_nodes(:), baseline(:) + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + + ! the baseline solutions for this unit test can be calculated using the Gauss-Lobatto quadrature + ! this website provides the nodes and weights: + ! http://keisan.casio.com/exec/system/1280801905 + + + ! -------------------------------------------------------------------------- + testname = "p = 2, boundaries only:" + p = 2 + allocate(baseline(p)) + baseline = (/ -1.0, 1.0 /) + + call AllocAry(gll_nodes, p, "GLL points array", ErrStat, ErrMsg) + call BD_GenerateGLL(p, gll_nodes, ErrStat, ErrMsg) + + @assertEqual(baseline, gll_nodes, tolerance, testname) + + deallocate(baseline) + deallocate(gll_nodes) + + ! -------------------------------------------------------------------------- + testname = "p = 5, odd number:" + p = 5 + allocate(baseline(p)) + baseline = (/ -1.0, -0.6546536707079771437983, 0.0, 0.654653670707977143798, 1.0 /) + + call AllocAry(gll_nodes, p, "GLL points array", ErrStat, ErrMsg) + call BD_GenerateGLL(p, gll_nodes, ErrStat, ErrMsg) + + @assertEqual(baseline, gll_nodes, tolerance, testname) + + deallocate(baseline) + deallocate(gll_nodes) + + + ! -------------------------------------------------------------------------- + testname = "p = 6, even number:" + p = 6 + allocate(baseline(p)) + baseline = (/ -1.0, -0.765055323929464692851, -0.2852315164806450963142, 0.2852315164806450963142, 0.765055323929464692851, 1.0 /) + + call AllocAry(gll_nodes, p, "GLL points array", ErrStat, ErrMsg) + call BD_GenerateGLL(p, gll_nodes, ErrStat, ErrMsg) + + @assertEqual(baseline, gll_nodes, tolerance, testname) + + deallocate(baseline) + deallocate(gll_nodes) + + + ! -------------------------------------------------------------------------- + testname = "p = 97, large, prime number:" + p = 97 + allocate(baseline(p)) + baseline = (/ & + -1.0, -0.9992117675187679372925, -0.997358420211575308381, -0.994447829238317218534, & + -0.9904833045655763827779, -0.9854690874505481580336, -0.9794105031099910659294, -0.972313976393383949863, & + -0.964187029755659609253, -0.955038276712134050045, -0.944877413224633009627, -0.933715207638498109806, & + -0.921563489367936527388, -0.9084351364079280548151, -0.8943440617122115723236, -0.8793051984632038831786,& + -0.8633344842547974738284, -0.8464488442074511804343, -0.8286661730348553921423, -0.810005316081936147328, & + -0.7904860493547251817926, -0.7701290585635136140501, -0.748955917201652598455, -0.7269890636833281333, & + -0.704251777564599720681, -0.6807681548729427782946, -0.6565630825714660926978, -0.631662212184884059709, & + -0.6060919326152061877601, -0.579879342175961313997, -0.553052219874599625586, -0.5256389959735105979894,& + -0.4976687218608582506373, -0.4691710392631656985371, -0.440176148832277959663, -0.4107147781399945491769,& + -0.3808181491142908001982, -0.350517944951638397684, -0.3198462765404906463777, -0.2888356484315159109028,& + -0.257518924390642905356, -0.2259292925714235538959, -0.1941002303436225183436, -0.1620654688153067619161,& + -0.1298589570860333006308, -0.09751482626901823919031, -0.0650673533204149925476, -0.032550924714033997197, & + 0.0, 0.032550924714033997197, 0.0650673533204149925476, 0.0975148262690182391903,& + 0.1298589570860333006308, 0.1620654688153067619161, 0.194100230343622518344, 0.225929292571423553896, & + 0.257518924390642905356, 0.2888356484315159109028, 0.3198462765404906463777, 0.3505179449516383976839,& + 0.3808181491142908001982, 0.410714778139994549177, 0.4401761488322779596629, 0.4691710392631656985371,& + 0.4976687218608582506373, 0.5256389959735105979894, 0.5530522198745996255862, 0.579879342175961313997, & + 0.6060919326152061877601, 0.6316622121848840597089, 0.6565630825714660926978, 0.6807681548729427782946,& + 0.7042517775645997206813, 0.7269890636833281332999, 0.7489559172016525984547, 0.7701290585635136140501,& + 0.7904860493547251817926, 0.8100053160819361473279, 0.8286661730348553921423, 0.8464488442074511804343,& + 0.8633344842547974738284, 0.8793051984632038831786, 0.8943440617122115723236, 0.9084351364079280548151,& + 0.9215634893679365273879, 0.933715207638498109806, 0.9448774132246330096275, 0.955038276712134050045, & + 0.9641870297556596092534, 0.9723139763933839498625, 0.9794105031099910659294, 0.9854690874505481580336,& + 0.9904833045655763827779, 0.9944478292383172185338, 0.9973584202115753083808, 0.9992117675187679372925,& + 1.0 /) + + call AllocAry(gll_nodes, p, "GLL points array", ErrStat, ErrMsg) + call BD_GenerateGLL(p, gll_nodes, ErrStat, ErrMsg) + + @assertEqual(baseline, gll_nodes, tolerance, testname) + + deallocate(baseline) + deallocate(gll_nodes) + +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_GravityForce.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_GravityForce.F90 new file mode 100644 index 000000000..6b7b4bc4d --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_GravityForce.F90 @@ -0,0 +1,46 @@ +@test +subroutine test_BD_GravityForce() + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer :: i, j + real(BDKi) :: gravity(3) + type(BD_ParameterType) :: parametertype + type(BD_MiscVarType) :: miscvartype + real(BDKi) :: baseline(6) + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + + ! -------------------------------------------------------------------------- + testname = "static simple beam under gravity:" + baseline(1:3) = getGravityInZ() + baseline(4:6) = (/ 0.0, 0.0, 0.0 /) + + ! allocate and build the custom types + parametertype = simpleParameterType(1,16,16,0,1) + miscvartype = simpleMiscVarType(parametertype%nqp, parametertype%elem_total) + + gravity = getGravityInZ() + + ! call the subroutine to test + call BD_GravityForce(1, parametertype, miscvartype, gravity) + + ! test the values + @assertEqual(baseline, miscvartype%qp%Fg(:,1,1), tolerance, testname) + + call BD_DestroyParam(parametertype, ErrStat, ErrMsg) + +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_InitShpDerJaco.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_InitShpDerJaco.F90 new file mode 100644 index 000000000..13e39f733 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_InitShpDerJaco.F90 @@ -0,0 +1,173 @@ +module test_BD_InitShpDerJaco + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer(IntKi) :: i, j, idx_qp, nelem + type(BD_ParameterType) :: p + real(BDKi), allocatable :: gll_nodes(:), inp_QPtWeight(:) + real(BDKi), allocatable :: baseline_QPtWeight(:), baseline_QPtN(:) + real(BDKi), allocatable :: baseline_Shp(:,:), baseline_ShpDer(:,:), baseline_jacobian(:,:), baseline_QPtw_ShpDer(:,:) + real(BDKi), allocatable :: baseline_QPtw_Shp_ShpDer(:,:,:), baseline_QPtw_Shp_Jac(:,:,:) + real(BDKi), allocatable :: baseline_QPtw_Shp_Shp_Jac(:,:,:,:), baseline_QPtw_ShpDer_ShpDer_Jac(:,:,:,:) + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + +contains + + @test + subroutine test_BD_InitShpDerJaco_5node() + ! branches to test + ! - 5 node, 1 element; undeformed + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-13 + + ! -------------------------------------------------------------------------- + testname = "5 node, 1 element, curved:" + + ! Let's use Gauss_Legendre Quadrature, which should be exact for intended polynomial test case + p = simpleparametertype(1,5,5,0,1) + + ! Allocate memory for baseline results + call AllocAry(baseline_Shp , p%nodes_per_elem, p%nqp, 'Reference Shp' , ErrStat, ErrMsg) + call AllocAry(baseline_ShpDer , p%nodes_per_elem, p%nqp, 'Reference ShpDer' , ErrStat, ErrMsg) + call AllocAry(baseline_Jacobian , p%nqp, p%elem_total, 'Reference Jacobian', ErrStat, ErrMsg) + call AllocAry(baseline_QPtN , p%nqp, 'Reference QPtN' , ErrStat, ErrMsg) + call AllocAry(baseline_QPtWeight, p%nqp, 'Reference QPtWeight', ErrStat, ErrMsg) + + ! Allocate memory for other relevant variables belonging to module p + call AllocAry(baseline_QPtw_Shp_Shp_Jac , p%nqp, p%nodes_per_elem, p%nodes_per_elem, p%elem_total, 'reference QPtw_Shp_Shp_Jac' , ErrStat, ErrMsg) + call AllocAry(baseline_QPtw_ShpDer_ShpDer_Jac, p%nqp, p%nodes_per_elem, p%nodes_per_elem, p%elem_total, 'reference baseline_QPtw_ShpDer_ShpDer_Jac', ErrStat, ErrMsg) + call AllocAry(baseline_QPtw_Shp_ShpDer , p%nqp, p%nodes_per_elem, p%nodes_per_elem , 'reference QPtw_Shp_ShpDer' , ErrStat, ErrMsg) + call AllocAry(baseline_QPtw_Shp_Jac , p%nqp, p%nodes_per_elem, p%elem_total , 'reference QPtw_Shp_Jac' , ErrStat, ErrMsg) + call AllocAry(baseline_QPtw_ShpDer , p%nqp, p%nodes_per_elem , 'reference QPtw_ShpDer' , ErrStat, ErrMsg) + + ! assign baseline results + ! baseline quadrature points and weights; this is 5-point Gauss-Legendre quadrature + + baseline_QPtN(1:p%nqp) = (/ -0.9061798459386640, -0.5384693101056831, 0. , 0.5384693101056831, 0.9061798459386640 /) + baseline_QPtWeight(1:p%nqp) = (/ 0.2369268850561891, 0.4786286704993665, 0.5688888888888889, 0.4786286704993665, 0.2369268850561891 /) + + ! assign baseline jacobian based; these values were calculated in separte mathematica script + baseline_jacobian(1:p%nqp,1) = (/ 0.6715870058501458, 1.509599209717604, 2.861380785564901, 4.097191592895223, 4.880926263217582 /) + + ! assign baseline shape functions based on example as described above + baseline_Shp(1,1:p%nqp) = (/ 0.5933706960199465, -0.10048256880508302, 0., 0.030144110771879763, -0.029205077492916114 /) + baseline_Shp(2,1:p%nqp) = (/ 0.516435198649618, 0.9313661019373962, 0., -0.09069490469997694, 0.08322282221996001 /) + baseline_Shp(3,1:p%nqp) = (/ -0.16382363939660807, 0.22966726079578503, 1., 0.22966726079578503, -0.16382363939660807 /) + baseline_Shp(4,1:p%nqp) = (/ 0.08322282221996001, -0.09069490469997694, 0., 0.9313661019373962, 0.516435198649618 /) + baseline_Shp(5,1:p%nqp) = (/ -0.029205077492916114, 0.030144110771879763, 0., -0.10048256880508302, 0.5933706960199465 /) + + ! assign baseline shape function derivatives based on example as described above + baseline_ShpDer(1,1:p%nqp) = (/ -3.705336453591454, -0.5287152679802739, 0.375, -0.24351802112960028, 0.14423640936799356 /) + baseline_ShpDer(2,1:p%nqp) = (/ 4.33282116876393, -1.0976579678283382, -1.3365845776954537, 0.7497385700132875, -0.42067623042767965 /) + baseline_ShpDer(3,1:p%nqp) = (/ -0.9039245362321631, 2.1325937846922898, 0., -2.1325937846922898, 0.9039245362321631 /) + baseline_ShpDer(4,1:p%nqp) = (/ 0.42067623042767965, -0.7497385700132875, 1.3365845776954537, 1.0976579678283382, -4.33282116876393 /) + baseline_ShpDer(5,1:p%nqp) = (/ -0.14423640936799356, 0.24351802112960028, -0.375, 0.5287152679802739, 3.705336453591454 /) + + ! uuN0 is of dimension (3 dof, nodes_per_elem, elem_total) + p%uuN0(1:3,1,1) = (/ 0.0, 0.0, 0.0 /) + p%uuN0(1:3,2,1) = (/ 0.16237631096713473, 0.17578464768961147, 0.1481911137890286 /) + p%uuN0(1:3,3,1) = (/ 0.25, 1., 1.1875 /) + p%uuN0(1:3,4,1) = (/ -0.30523345382427747, 2.4670724951675314, 2.953849702537502 /) + p%uuN0(1:3,5,1) = (/ -1., 3.5, 4. /) + + ! Using BD_GaussPointWeight; hoping it's tested! + call BD_GaussPointWeight(p%nqp, p%QPtN, p%QPtWeight, ErrStat, ErrMsg) + + @assertEqual(baseline_QPtN, p%QPtN , tolerance, testname) + @assertEqual(baseline_QPtWeight, p%QPtWeight, tolerance, testname) + + ! Allocate memory for GLL node positions in 1D parametric space + call AllocAry(gll_nodes, p%nodes_per_elem, "GLL points array", ErrStat, ErrMsg) + gll_nodes = (/ -1., -0.6546536707079771, 0., 0.6546536707079771, 1. /) + + ! call the test subroutine + call BD_InitShpDerJaco(gll_nodes, p) + + ! check the baseline shape functions and their derivatives + do idx_qp = 1, p%nqp + do j = 1, p%nodes_per_elem + @assertEqual(baseline_Shp(j,idx_qp) , p%Shp(j,idx_qp) , tolerance, testname) + @assertEqual(baseline_ShpDer(j,idx_qp), p%ShpDer(j,idx_qp), tolerance, testname) + end do + end do + + ! check the baseline jacobian + do nelem = 1, p%elem_total + do idx_qp = 1, p%nqp + @assertEqual(baseline_jacobian(idx_qp,nelem), p%jacobian(idx_qp,nelem), tolerance, testname) + end do + end do + + ! Test and assemble variables N*N^T*wt*Jacobian and dN*dN^T*wt/Jacobian + do nelem = 1, p%elem_total + do idx_qp = 1, p%nqp + do j = 1, p%nodes_per_elem + do i = 1, p%nodes_per_elem + ! Check the variable N*N^T*Jacobian + baseline_QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem) = baseline_Shp(i,idx_qp)*baseline_Shp(j,idx_qp)*baseline_QPtWeight(idx_qp)*baseline_jacobian(idx_qp,nelem) + @assertEqual(baseline_QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem), p%QPtw_Shp_Shp_Jac(idx_qp,i,j,nelem), tolerance, testname) + + ! Check the variable dN*dN^T*Jacobian + baseline_QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem) = baseline_ShpDer(i,idx_qp)*baseline_ShpDer(j,idx_qp)*baseline_QPtWeight(idx_qp)/baseline_jacobian(idx_qp,nelem) + @assertEqual(baseline_QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem), p%QPtw_ShpDer_ShpDer_Jac(idx_qp,i,j,nelem), tolerance, testname) + end do + end do + end do + end do + + ! Test and assemble variable N*dN^T*wt*Jacobian + do idx_qp = 1, p%nqp + do j = 1, p%nodes_per_elem + do i = 1, p%nodes_per_elem + baseline_QPtw_Shp_ShpDer(idx_qp,i,j) = baseline_Shp(i,idx_qp)*baseline_ShpDer(j,idx_qp)*baseline_QPtWeight(idx_qp) + @assertEqual(baseline_QPtw_Shp_ShpDer(idx_qp,i,j), p%QPtw_Shp_ShpDer(idx_qp,i,j), tolerance, testname) + end do + end do + end do + + ! Test and assemble variable N*wt*Jacobian + do nelem = 1, p%elem_total + do i = 1, p%nodes_per_elem + do idx_qp = 1, p%nqp + baseline_QPtw_Shp_Jac(idx_qp,i,nelem) = baseline_Shp(i,idx_qp)*baseline_QPtWeight(idx_qp)*baseline_Jacobian(idx_qp,nelem) + @assertEqual(baseline_QPtw_Shp_Jac(idx_qp,i,nelem), p%QPtw_Shp_Jac(idx_qp,i,nelem), tolerance, testname) + end do + end do + end do + + ! Test and assemble variable dN*wt. + do i = 1, p%nodes_per_elem + do idx_qp = 1, p%nqp + baseline_QPtw_ShpDer(idx_qp,i) = baseline_ShpDer(i,idx_qp)*baseline_QPtWeight(idx_qp) + @assertEqual(baseline_QPtw_ShpDer(idx_qp,i), p%QPtw_ShpDer(idx_qp,i), tolerance, testname) + end do + end do + + ! dealocate baseline variables + if (allocated(gll_nodes)) deallocate(gll_nodes) + deallocate(baseline_Shp) + deallocate(baseline_ShpDer) + deallocate(baseline_Jacobian) + deallocate(baseline_QPtN) + deallocate(baseline_QPtWeight) + deallocate(baseline_QPtw_Shp_Shp_Jac) + deallocate(baseline_QPtw_ShpDer_ShpDer_Jac) + deallocate(baseline_QPtw_Shp_ShpDer) + deallocate(baseline_QPtw_Shp_Jac) + deallocate(baseline_QPtw_ShpDer) + + call BD_DestroyParam(p, ErrStat, ErrMsg) + + end subroutine +end module diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_InputGlobalLocal.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_InputGlobalLocal.F90 new file mode 100644 index 000000000..255f75f8c --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_InputGlobalLocal.F90 @@ -0,0 +1,102 @@ +@test +subroutine test_BD_InputGlobalLocal() + ! branches to test + ! - a simple rotation does the rotation + + ! Check the following quanities are actually rotated + !! 1 Displacements -> u%RootMotion%TranslationDisp(:,1) + !! 2 Linear/Angular velocities -> u%RootMotion%TranslationVel(:,1), u%RootMotion%RotationVel(:,1) + !! 3 Linear/Angular accelerations -> u%RootMotion%TranslationAcc(:,1), u%RootMotion%RotationAcc(:,1) + !! 4 Point forces/moments -> u%PointLoad%Force(1:3,i), u%PointLoad%Moment(1:3,i) + !! 5 Distributed forces/moments -> u%DistrLoad%Force(1:3,i), u%DistrLoad%Moment(1:3,i) + + ! Verify the DCM is transposed + !! u%RootMotion%Orientation(:,:,1) + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer :: i, totalnodes + type(BD_ParameterType) :: parametertype + type(BD_InputType) :: inputtype + real(BDKi), dimension(3) :: vectorInit, vectorAfterRotation, rotationaxis + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! initialize NWTC_Num constants + call SetConstants() + + + ! -------------------------------------------------------------------------- + testname = "test_BD_InputGlobalLocal:" + + tolerance = 1e-14 + totalnodes = 2 + vectorInit = (/ 0.0, 0.0, 1.0 /) + vectorAfterRotation = (/ 0.0, 0.0, -1.0 /) + rotationaxis = (/ 1.0, 0.0, 0.0 /) + + ! build the parameter type + parametertype%node_total = totalnodes + parametertype%GlbRot = calcRotationMatrix(real(Pi, BDKi), rotationaxis) + + ! build the inputs + call AllocAry(inputtype%RootMotion%TranslationDisp, 3, 1, 'TranslationDisp', ErrStat, ErrMsg) + call AllocAry(inputtype%RootMotion%TranslationVel, 3, 1, 'TranslationVel', ErrStat, ErrMsg) + call AllocAry(inputtype%RootMotion%RotationVel, 3, 1, 'RotationVel', ErrStat, ErrMsg) + call AllocAry(inputtype%RootMotion%TranslationAcc, 3, 1, 'TranslationAcc', ErrStat, ErrMsg) + call AllocAry(inputtype%RootMotion%RotationAcc, 3, 1, 'RotationAcc', ErrStat, ErrMsg) + inputtype%RootMotion%TranslationDisp(:,1) = vectorInit + inputtype%RootMotion%TranslationVel(:,1) = vectorInit + inputtype%RootMotion%RotationVel(:,1) = vectorInit + inputtype%RootMotion%TranslationAcc(:,1) = vectorInit + inputtype%RootMotion%RotationAcc(:,1) = vectorInit + + call AllocAry(inputtype%PointLoad%Force, 3, totalnodes, 'PointLoad%Force', ErrStat, ErrMsg) + call AllocAry(inputtype%PointLoad%Moment, 3, totalnodes, 'PointLoad%Moment', ErrStat, ErrMsg) + do i = 1, parametertype%node_total + inputtype%PointLoad%Force(1:3,i) = vectorInit + inputtype%PointLoad%Moment(1:3,i) = vectorInit + end do + + inputtype%DistrLoad%Nnodes = totalnodes + call AllocAry(inputtype%DistrLoad%Force, 3, totalnodes, 'DistrLoad%Force', ErrStat, ErrMsg) + call AllocAry(inputtype%DistrLoad%Moment, 3, totalnodes, 'DistrLoad%Moment', ErrStat, ErrMsg) + do i = 1, inputtype%DistrLoad%Nnodes + inputtype%DistrLoad%Force(1:3,i) = vectorInit + inputtype%DistrLoad%Moment(1:3,i) = vectorInit + end do + + call AllocAry(inputtype%RootMotion%Orientation, 3, 3, totalnodes, 'RootMotion%Orientation', ErrStat, ErrMsg) + inputtype%RootMotion%Orientation(:,:,1) = parametertype%GlbRot + + ! call the subroutine to test + call BD_InputGlobalLocal(parametertype, inputtype) + + ! test the values + @assertEqual(vectorAfterRotation, real(inputtype%RootMotion%TranslationDisp(:,1), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%RootMotion%TranslationVel(:,1), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%RootMotion%RotationVel(:,1), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%RootMotion%TranslationAcc(:,1), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%RootMotion%RotationAcc(:,1), BDKi), tolerance, testname) + + do i = 1, parametertype%node_total + @assertEqual(vectorAfterRotation, real(inputtype%PointLoad%Force(1:3,i), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%PointLoad%Moment(1:3,i), BDKi), tolerance, testname) + end do + + inputtype%DistrLoad%Nnodes = totalnodes + do i = 1, inputtype%DistrLoad%Nnodes + @assertEqual(vectorAfterRotation, real(inputtype%DistrLoad%Force(1:3,i), BDKi), tolerance, testname) + @assertEqual(vectorAfterRotation, real(inputtype%DistrLoad%Moment(1:3,i), BDKi), tolerance, testname) + end do + + @assertEqual(transpose(parametertype%GlbRot), inputtype%RootMotion%Orientation(:,:,1), tolerance, testname) + +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_MemberEta.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_MemberEta.F90 new file mode 100644 index 000000000..08df56dbf --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_MemberEta.F90 @@ -0,0 +1,87 @@ +module test_BD_MemberEta + + ! tests routine that calculates the length of the beam's reference line + ! also finds element boundaries in eta coordinates + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer(IntKi) :: nqp + integer(IntKi) :: member_total + real(BDKi) :: total_length + real(BDKi), allocatable :: baseline_jac(:,:) + real(BDKi), allocatable :: baseline_QPtW(:) + real(BDKi), allocatable :: baseline_member_eta(:) + real(BDKi), allocatable :: test_member_eta(:) + real(BDKi) :: baseline_total_length + real(BDKi) :: test_total_length + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + +contains + + @test + subroutine test_BD_MemberEta_5node() + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "test_bd_member_eta_5node" + + ! this test problem is for a beam reference axis defined by 5 points + ! x = 0., 0.16237631096713473, 0.25, -0.30523345382427747, -1. + ! y = 0., 0.17578464768961147, 1., 2.4670724951675314, 3.5 + ! z = 0., 0.1481911137890286, 1.1875, 2.953849702537502, 4. + ! where the underlying forth-order polynomial is + ! fx[u_] = u - 2 u^3; + ! fy[u_] = u/2 + 3 u^2; + ! fz[u_] = 5 u^2 - u^4; + ! + ! exact (to mp) length is 5.627175237247959 + ! The Jacobian values below are calculate based on a 5-node Legendre Spectral Element + ! While we give baseline Jacobian here, we check "test_BD_InitShpDerJaco.F90" elsewhere + + nqp = 5 ! number of quadrature points + member_total = 1 ! 1 element + + call AllocAry(baseline_jac , nqp, member_total, 'Reference Jacobian', ErrStat, ErrMsg) + call AllocAry(baseline_QPtW, nqp, 'Reference QPtWeight', ErrStat, ErrMsg) + call AllocAry(baseline_member_eta, member_total, 'Reference member_eta', ErrStat, ErrMsg) + call AllocAry(test_member_eta, member_total, 'test member_eta', ErrStat, ErrMsg) + + ! 5-point Guass-Legendre quadrature; see https://pomax.github.io/bezierinfo/legendre-gauss.html + baseline_QPtW(1:nqp) = (/ 0.2369268850561891, 0.4786286704993665, 0.5688888888888889, 0.4786286704993665, 0.2369268850561891 /) + + ! assign baseline jacobian based; these values were calculated in separate mathematica script + baseline_jac(1:nqp,1) = (/ 0.6715870058501458, 1.509599209717604, 2.861380785564901, 4.097191592895223, 4.880926263217582 /) + + ! total length of beam calculated in mathematica; note that for this curved beam, GL quadrature is APPROXIMATE, but + ! converged rapidly; TR quadrature is not nearly as good; commented-out values are useful for understanding quadrature performance + ! for curved beams. + !baseline_total_length = 5.627175237247959 ! this is actual length based on mathematica + !baseline_total_length = 5.634413547964786 ! this is approximation with 9-point Trapezoidal quadrature; 0.13% error + !baseline_total_length = 5.627202424388781 ! this is approximation with 7-point gauss quadrature; 0.0005% error + baseline_total_length = 5.626918236484061 ! this is approximation with 5-point gauss quadrature; 0.005% error (tested here) + baseline_member_eta(1) = 1. ! just one element; so member_length / total_length = 1 + + call BD_MemberEta(member_total, baseline_QPtW, baseline_jac, test_member_eta, test_total_length) + + @assertEqual(baseline_total_length, test_total_length, tolerance, testname) + @assertEqual(baseline_member_eta, test_member_eta, tolerance, testname) + + deallocate(baseline_Jac) + deallocate(baseline_QPtW) + deallocate(baseline_member_eta) + deallocate(test_member_eta) + + end subroutine +end module diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_QPData_mEta_rho.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_QPData_mEta_rho.F90 new file mode 100644 index 000000000..5cea83100 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_QPData_mEta_rho.F90 @@ -0,0 +1,50 @@ +@test +subroutine test_BD_QPData_mEta_rho() + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer :: i, j + type(BD_MiscVarType) :: miscvartype + type(BD_ParameterType) :: parametertype + real(BDKi) :: baselineRho(3,3), baselineRR0mEta(3) + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + + ! -------------------------------------------------------------------------- + testname = "static simple beam under gravity:" + + baselineRho(1,:) = (/ 1.0, 0.0, 0.0 /) + baselineRho(2,:) = (/ 0.0, 1.0, 0.0 /) + baselineRho(3,:) = (/ 0.0, 0.0, 2.0 /) + + baselineRR0mEta = (/ 0.0, 0.0, 0.0 /) + + ! allocate and build the custom input types + parametertype = simpleParameterType(1,16,16,0,1) + miscvartype = simpleMiscVarType(parametertype%nqp, parametertype%elem_total) + + ! allocate the results + call BD_QPData_mEta_rho(parametertype, miscvartype) + + do j=1, parametertype%elem_total + do i=1, parametertype%nqp + @assertEqual(baselineRho, miscvartype%qp%rho(:,:,i,j), tolerance, testname) + @assertEqual(baselineRR0mEta, miscvartype%qp%RR0mEta(:,i,j), tolerance, testname) + end do + end do + call BD_DestroyParam(parametertype, ErrStat, ErrMsg) +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_TrapezoidalPointWeight.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_TrapezoidalPointWeight.F90 new file mode 100644 index 000000000..0ca075ad1 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_TrapezoidalPointWeight.F90 @@ -0,0 +1,113 @@ +module test_BD_TrapezoidalPointWeight + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + type(BD_ParameterType) :: p + + integer(IntKi) :: nqp + integer(IntKi) :: refine + integer(IntKi) :: station_total + real(BDKi), allocatable :: station_eta(:) + real(BDKi), allocatable :: baseline_QPtN(:) + real(BDKi), allocatable :: baseline_QPtW(:) + + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + +contains + + @test + subroutine test_BD_TrapezoidalPointWeight_2station() + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "test_BD_TrapezoidalPointWeight_2station_8refine" + + station_total = 2 + + call AllocAry(station_eta, station_total, "station_eta", ErrStat, ErrMsg) + + ! simple case where we have enpoints only; typical with constant cross sections + station_eta(1:station_total) = (/0., 1./) + + refine = 8 + + nqp = (station_total - 1)*refine + 1 + + p=simpleParameterType(1,1,nqp,0,refine) + + call AllocAry(baseline_QPtN, nqp, "baseline_QPtN", ErrStat, ErrMsg) + call AllocAry(baseline_QPtW, nqp, "baseline_QPtW", ErrStat, ErrMsg) + + baseline_QPtN(1:nqp) = (/ -1., -0.75, -0.5, -0.25, 0., 0.25, 0.5, 0.75, 1. /) + baseline_QPtW(1:nqp) = (/ 0.125, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.125 /) + + call BD_TrapezoidalPointWeight(p, station_eta, station_total) + + @assertEqual(baseline_QPtN, p%QPtN, tolerance, testname) + @assertEqual(baseline_QPtW, p%QPtWeight, tolerance, testname) + + deallocate(station_eta) + deallocate(baseline_QPtN) + deallocate(baseline_QPtW) + + call BD_DestroyParam(p, ErrStat, ErrMsg) + + end subroutine + + @test + subroutine test_BD_TrapezoidalPointWeight_3station() + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "test_BD_TrapezoidalPointWeight_3station_2refine" + + ! provide three stations, unequally distributed + ! refine by factor of two + + station_total = 3 + + call AllocAry(station_eta, station_total, "station_eta", ErrStat, ErrMsg) + + station_eta(1:station_total) = (/0., 0.25, 1./) + + refine = 2 + + nqp = (station_total - 1)*refine + 1 + + p=simpleParameterType(1,1,nqp,0,refine) + + call AllocAry(baseline_QPtN, nqp, "baseline_QPtN", ErrStat, ErrMsg) + call AllocAry(baseline_QPtW, nqp, "baseline_QPtW", ErrStat, ErrMsg) + + baseline_QPtN(1:nqp) = (/ -1., -0.75, -0.5, 0.25, 1. /) + baseline_QPtW(1:nqp) = (/ 0.125, 0.25, 0.125+0.5*0.75, 0.75, 0.5*0.75/) + + call BD_TrapezoidalPointWeight(p, station_eta, station_total) + + @assertEqual(baseline_QPtN, p%QPtN, tolerance, testname) + @assertEqual(baseline_QPtW, p%QPtWeight, tolerance, testname) + + deallocate(station_eta) + deallocate(baseline_QPtN) + deallocate(baseline_QPtW) + + call BD_DestroyParam(p, ErrStat, ErrMsg) + + end subroutine +end module diff --git a/OpenFAST/modules/beamdyn/tests/test_BD_diffmtc.F90 b/OpenFAST/modules/beamdyn/tests/test_BD_diffmtc.F90 new file mode 100644 index 000000000..6d3319d92 --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_BD_diffmtc.F90 @@ -0,0 +1,163 @@ +module test_BD_diffmtc + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + integer :: n, i + type(BD_ParameterType) :: parametertype + real(BDKi), allocatable :: test_shape(:,:), test_shapederivative(:,:) + real(BDKi), allocatable :: baseline_shape(:,:), baseline_shapederivative(:,:) + real(BDKi), allocatable :: gll_nodes(:) + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + + ! mathematica code for calculating shape function values and derivative values + !ClearAll[p, \[Xi]j, xj, h, j, \[Xi], x, sol]; + !(* find p+1 GLL points *) + !p = 4; + !test[x_] = (1 - x^2) D[LegendreP[p, x], x]; + !\[Xi]j = Array[f, p + 1]; (* initialize list *) + !For[j = 0, j <= p, j++, + !sol = x /. FindRoot[test[x], {x, -Cos[(Pi (j))/p]}]; + ! \[Xi]j[[j + 1]] = sol + !] + !h[\[Xi]_, xj_] = -(((1. - \[Xi]^2) D[ LegendreP[p, \[Xi]], \[Xi]])/( + !p (p + 1) LegendreP[p, xj] (\[Xi] - xj))); + !hd[\[Xi]_, xj_] = D[h[\[Xi], xj], \[Xi]] + !Plot[h[x, \[Xi]j[[1]]], {x, -1, 1}, PlotRange -> All] + !h[0.5, \[Xi]j[[2]]] + +contains + + @test + subroutine test_BD_diffmtc_2node() + ! branches to test + ! - 2 node, 1 element + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "2-node element: evaluate shape/shapederivative at nodes" + + ! the shape functions should be: + ! h1(-1) = 1, h1(+1) = 0 + ! h2(-1) = 0, h2(+1) = 1 + ! + ! this is satisfied by these linear equations + ! h1(s) = 0.5*(1-s) + ! h2(s) = 0.5*(1+s) + ! therefore, + ! h1` = -0.5 + ! h2` = 0.5 + ! + ! the expected result of BD_diffmtc is + ! Shp - the shape function evaluated at the GLL nodes + ! ShpDer - the shape function derivative evaluated at the GLL nodes + ! + ! shp(1,:) = 1.0, 0.0 + ! shp(2,:) = 0.0, 1.0 + ! shpder(1,:) = -0.5, -0.5 + ! shpder(2,:) = 0.5, 0.5 + + parametertype = simpleParameterType(1,2,2,0,1) + n = parametertype%nodes_per_elem + + call AllocAry(test_shape, parametertype%nodes_per_elem, parametertype%nqp, "test_shape", ErrStat, ErrMsg) + call AllocAry(test_shapederivative, parametertype%nodes_per_elem, parametertype%nqp, "test_shapederivative", ErrStat, ErrMsg) + + call AllocAry(parametertype%QPtN, parametertype%nodes_per_elem, 'QPtN', ErrStat, ErrMsg) + parametertype%QPtN = (/ -1.0, 1.0 /) + + call AllocAry(gll_nodes, n, "GLL points array", ErrStat, ErrMsg) + gll_nodes = (/ -1.0, 1.0 /) + + call BD_diffmtc(parametertype%nodes_per_elem, gll_nodes, parametertype%QPtN, parametertype%nqp, test_shape, test_shapederivative) + + call AllocAry(baseline_shape, parametertype%nodes_per_elem,parametertype%nqp, "baseline_shape", ErrStat, ErrMsg) + call AllocAry(baseline_shapederivative, parametertype%nodes_per_elem,parametertype%nqp, "baseline_shapederivative", ErrStat, ErrMsg) + baseline_shape(1,:) = (/ 1.0, 0.0 /) + baseline_shape(2,:) = (/ 0.0, 1.0 /) + baseline_shapederivative(1,:) = (/ -0.5, -0.5 /) + baseline_shapederivative(2,:) = (/ 0.5, 0.5 /) + + @assertEqual(baseline_shape, test_shape, tolerance, testname) + @assertEqual(baseline_shapederivative, test_shapederivative, tolerance, testname) + + deallocate(test_shape) + deallocate(test_shapederivative) + deallocate(gll_nodes) + deallocate(baseline_shape) + deallocate(baseline_shapederivative) + + call BD_DestroyParam(parametertype, ErrStat, ErrMsg) + + end subroutine + + @test + subroutine test_BD_diffmtc_5node() + ! branches to test + ! - 5 node, 1 element + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + ! -------------------------------------------------------------------------- + testname = "5-node element: evaluate shape/shapederivative at nodes and at three non-node locations" + + parametertype = simpleParameterType(1,5,8,0,1) + !parametertype%nodes_per_elem = 5 + !parametertype%nqp = 8 ! testing the GLL nodes and three non-nodal locations (-0.8, 0.1, 0.4) + n = parametertype%nodes_per_elem + + call AllocAry(test_shape, parametertype%nodes_per_elem, parametertype%nqp, "test_shape", ErrStat, ErrMsg) + call AllocAry(test_shapederivative, parametertype%nodes_per_elem, parametertype%nqp, "test_shapederivative", ErrStat, ErrMsg) + + call AllocAry(parametertype%QPtN, parametertype%nodes_per_elem, 'QPtN', ErrStat, ErrMsg) + ! in following, first five points are the 4th-order GLL locations; last three points are randomly chosen off-node points + parametertype%QPtN = (/ -1.0, -0.6546536707079771, 0.0, 0.6546536707079771, 1.0, -0.8, 0.1, 0.4 /) + + call AllocAry(gll_nodes, n, "GLL points array", ErrStat, ErrMsg) + gll_nodes = (/ -1.0, -0.6546536707079771, 0.0, 0.6546536707079771, 1.0 /) + + call BD_diffmtc(parametertype%nodes_per_elem, gll_nodes, parametertype%QPtN, parametertype%nqp, test_shape, test_shapederivative) + + call AllocAry(baseline_shape, parametertype%nodes_per_elem, parametertype%nqp, "baseline_shape", ErrStat, ErrMsg) + call AllocAry(baseline_shapederivative, parametertype%nodes_per_elem, parametertype%nqp, "baseline_shapederivative", ErrStat, ErrMsg) + + ! baseline_shape and baseline_shapederivative were calculated in Mathematica for fourth order Legendre spectral FE + + baseline_shape(1,:) = (/ 1., 0., 0., 0., 0., 0.266400000000000, 0.0329625, 0.0564/) + baseline_shape(2,:) = (/ 0., 1., 0., 0., 0., 0.855336358376291, -0.1121093731918499, -0.1746924181056723/) + baseline_shape(3,:) = (/ 0., 0., 1., 0., 0., -0.1776000000000001, 0.9669, 0.5263999999999998/) + baseline_shape(4,:) = (/ 0., 0., 0., 1., 0., 0.0854636416237095, 0.1525343731918499, 0.7234924181056726/) + baseline_shape(5,:) = (/ 0., 0., 0., 0., 1., -0.0296000000000000, -0.0402875, -0.1316/) + baseline_shapederivative(1,:) = (/-5., -1.240990253030983,0.375,-0.2590097469690172,0.5,-2.497, 0.27725, -0.1210000000000001/) + baseline_shapederivative(2,:) = (/ 6.756502488724241,0.,-1.336584577695454,0.7637626158259736,-1.410164177942427,2.144324478146486,-0.896320373697923, 0.4156426862650312/) + baseline_shapederivative(3,:) = (/-2.666666666666667, 1.74574312188794,0.,-1.74574312188794,2.666666666666667,0.5546666666666656,-0.6573333333333338, -2.069333333333333/) + baseline_shapederivative(4,:) = (/ 1.410164177942427,-0.7637626158259736, 1.336584577695454,0.,-6.756502488724241,-0.31499114481315,1.696653707031257, 1.805690647068303/) + baseline_shapederivative(5,:) = (/-0.5, 0.2590097469690172,-0.375,1.240990253030983,5.,0.1129999999999999,-0.42025, -0.03099999999999978/) + + @assertEqual(baseline_shape, test_shape, tolerance, testname) + @assertEqual(baseline_shapederivative, test_shapederivative, tolerance, testname) + + deallocate(test_shape) + deallocate(test_shapederivative) + deallocate(gll_nodes) + deallocate(baseline_shape) + deallocate(baseline_shapederivative) + + call BD_DestroyParam(parametertype, ErrStat, ErrMsg) + + end subroutine +end module diff --git a/OpenFAST/modules/beamdyn/tests/test_ExtractRelativeRotation.F90 b/OpenFAST/modules/beamdyn/tests/test_ExtractRelativeRotation.F90 new file mode 100644 index 000000000..25c1c01dc --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_ExtractRelativeRotation.F90 @@ -0,0 +1,34 @@ +@test +subroutine test_ExtractRelativeRotation() + ! this is actually an integration test not a unit test... + + use pFUnit_mod + use BeamDyn_Subs + use NWTC_Num + use test_tools + + implicit none + + real(BDKi), dimension(3) :: rr + character(1024) :: testname + real(BDKi) :: tolerance + integer(IntKi) :: ErrStat + character :: ErrMsg + + type(BD_ParameterType) :: parametertype + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-14 + + + ! -------------------------------------------------------------------------- + testname = "static simple beam under gravity:" + + parametertype = simpleParameterType(1,16,16,0,0) + + call ExtractRelativeRotation(identity(), parametertype, rr, ErrStat, ErrMsg) + + @assertEqual((/ 0.0, 0.0, 0.0 /), rr, tolerance, testname) +end subroutine diff --git a/OpenFAST/modules/beamdyn/tests/test_InitializeNodalLocations.F90 b/OpenFAST/modules/beamdyn/tests/test_InitializeNodalLocations.F90 new file mode 100644 index 000000000..9c488583c --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_InitializeNodalLocations.F90 @@ -0,0 +1,134 @@ +module test_InitializeNodalLocations + + use pFUnit_mod + use BeamDyn + use NWTC_Num + use test_tools + + implicit none + + type(BD_ParameterType) :: p + + integer(IntKi) :: i ! do loop + + integer(IntKi) :: member_total + integer(IntKi), allocatable :: kp_member(:) + real(BDKi), allocatable :: kp_coordinate(:,:) + + real(BDKi), allocatable :: baseline_uuN0(:,:,:) + real(BDKi), allocatable :: baseline_tangent(:,:,:) + real(BDKi), allocatable :: baseline_twist(:,:) + real(BDKi), allocatable :: gll(:) + + real(BDKi) :: cc(3) + + integer(IntKi) :: np ! number of points defining reference line + + integer(IntKi) :: ErrStat + character :: ErrMsg + character(1024) :: testname + real(BDKi) :: tolerance + +contains + + @test + subroutine test_InitializeNodalLocations_np5_p6() + + ! test problem where reference line is defined by 1 member, 5 keypoints, + ! and we fit a 6th order LSFE + + ! initialize NWTC_Num constants + call SetConstants() + + tolerance = 1e-13 + + ! -------------------------------------------------------------------------- + testname = "test_InitializeNodalLocations_1m_kp5_p6" + + member_total = 1 + + np = 5 ! five points defining the reference line + p=simpleParameterType(1,7,3,0,1) !simpleParameterType(elem_total, nodes_per_elem, nqp, qp_indx_offset, refine) + + p%dof_node = 6 + + call AllocAry(kp_member, member_total, "kp_member",ErrStat, ErrMsg) + call AllocAry(gll,p%nodes_per_elem, "gll",ErrStat, ErrMsg) + call AllocAry(baseline_uuN0, p%dof_node, p%nodes_per_elem, p%elem_total, "baseline_uuN0",ErrStat, ErrMsg) + + call AllocAry(baseline_tangent, 3, p%nodes_per_elem, p%elem_total, "baseline_tangent", ErrStat, ErrMsg) + call AllocAry(baseline_twist, p%nodes_per_elem, p%elem_total, "baseline_twist", ErrStat, ErrMsg) + + ! remove the following once the routine moves to least squares + + CALL AllocAry(p%segment_eta,np-1,'segment length ratio array',ErrStat,ErrMsg) + + kp_member(1) = np ! one member defined by 5 points + + call AllocAry(kp_coordinate, kp_member(1), 4, "kp_coordinate",ErrStat, ErrMsg) + + kp_coordinate(1,:) = (/ 0.,0.,0.,0. /) + kp_coordinate(2,:) = (/ 0.2421875,0.3125,1.25,5.625 /) + kp_coordinate(3,:) = (/ 0.375,1.,2.5,22.5/) + kp_coordinate(4,:) = (/ 0.1171875,2.0625,3.75, 50.625 /) + kp_coordinate(5,:) = (/ -1.,3.5,5., 90. /) + + gll(:) = (/ -1., -0.8302238962785669, -0.46884879347071423, 0., 0.46884879347071423, 0.8302238962785669, 1. /) + + baseline_uuN0 = 0. + + ! following calculated in mathematica + baseline_uuN0(1:3,1,1) = (/ 0.,0.,0. /) + baseline_uuN0(1:3,2,1) = (/ 0.0847841995263206,0.06406196997648083,0.4244402593035813 /) + baseline_uuN0(1:3,3,1) = (/ 0.2556265283202704,0.3443790047804582,1.327878016323214 /) + baseline_uuN0(1:3,4,1) = (/ 0.375,1.,2.5 /) + baseline_uuN0(1:3,5,1) = (/ 0.152564565773068,1.985349781927959,3.672121983676785 /) + baseline_uuN0(1:3,6,1) = (/ -0.4874656517463806,2.969845606951464,4.575559740696413 /) + baseline_uuN0(1:3,7,1) = (/ -1.,3.5,5. /) + + baseline_tangent(1:3,1,1) = (/ 0.1951800145897074,0.0975900072948519,0.975900072948533 /) + baseline_tangent(1:3,2,1) = (/ 0.1914764728687931,0.1942130285347349,0.962090463462295 /) + baseline_tangent(1:3,3,1) = (/ 0.1549438849532919,0.3815415434641369,0.911272979477931 /) + baseline_tangent(1:3,4,1) = (/ 0., 0.5734623443633284,0.81923192051904 /) + baseline_tangent(1:3,5,1) = (/ -0.2957782328585355,0.6690666276575518,0.6818101529913093 /) + baseline_tangent(1:3,6,1) = (/ -0.5494018213496115,0.6414840856724742,0.535402471535834 /) + baseline_tangent(1:3,7,1) = (/ -0.6492344540642337,0.6028605644882184,0.4637388957601716 /) + + baseline_twist(1,1) = 0. + baseline_twist(2,1) = 0.6485383213836768 + baseline_twist(3,1) = 6.347736094444107 + baseline_twist(4,1) = 22.50000000000001 + baseline_twist(5,1) = 48.54412750680838 + baseline_twist(6,1) = 75.36868898645466 + baseline_twist(7,1) = 90. + + ! here we're using the BD_ComputeIniNodalCrv to construct the rotation parameters; this is what is used in + ! BeamDyn; I do not want to rely on this routine and would rather calculate externally + do i = 1, 7 + CALL BD_ComputeIniNodalCrv(baseline_tangent(1:3,i,1), baseline_twist(i,1), cc, ErrStat, ErrMsg) + baseline_uuN0(4:6,i,1) = cc + enddo + + ! remove after reworking fit; dropping spline in favor of lease squares; p%SP_Coef is required in original spline fit implementation + !call ComputeSplineCoeffs(member_total, np, kp_member, kp_coordinate, p%SP_Coef, ErrStat, ErrMsg) + + call InitializeNodalLocations(member_total, kp_member, kp_coordinate, p, GLL, ErrStat,ErrMsg) + + !do i = 1, 7 + ! write(*,*) i, baseline_uuN0(4,i,1), baseline_uuN0(5,i,1), baseline_uuN0(6,i,1), p%uuN0(4,i,1), p%uuN0(5,i,1), p%uuN0(6,i,1) + !enddo + + @assertEqual(baseline_uuN0, p%uuN0, tolerance, testname) + + deallocate(kp_member) + deallocate(kp_coordinate) + deallocate(gll) + deallocate(baseline_uuN0) + deallocate(baseline_tangent) + deallocate(baseline_twist) + + call BD_DestroyParam(p, ErrStat, ErrMsg) + + end subroutine + +end module diff --git a/OpenFAST/modules/beamdyn/tests/test_tools.F90 b/OpenFAST/modules/beamdyn/tests/test_tools.F90 new file mode 100644 index 000000000..909a7c10b --- /dev/null +++ b/OpenFAST/modules/beamdyn/tests/test_tools.F90 @@ -0,0 +1,238 @@ +module test_tools + +use BeamDyn_Types + +implicit none + +contains + + subroutine calcWMParameters(params, angle, n) + use BeamDyn_Subs + implicit none + + real(BDKi), intent( out), dimension(3) :: params + real(BDKi), intent(in ) :: angle + real(BDKi), intent(in ), dimension(3) :: n + + params = 4.0 * tan(angle/4.0) * n + end subroutine + + function calcRotationMatrix(angle, axis) + use BeamDyn_Subs + implicit none + + real(BDKi), dimension(3,3) :: calcRotationMatrix + real(BDKi), intent(in) :: angle + real(BDKi), intent(in), dimension(3) :: axis + real(BDKi), dimension(3,3) :: r + + r(1,:) = (/ cos(angle) + (1-cos(angle))*axis(1)**2, axis(1)*axis(2)*(1-cos(angle)) - axis(3)*sin(angle), axis(1)*axis(3)*(1-cos(angle)) + axis(2)*sin(angle) /) + r(2,:) = (/ axis(2)*axis(1)*(1-cos(angle)) + axis(3)*sin(angle), cos(angle) + (1-cos(angle))*axis(2)**2, axis(2)*axis(3)*(1-cos(angle)) - axis(1)*sin(angle) /) + r(3,:) = (/ axis(3)*axis(1)*(1-cos(angle)) - axis(2)*sin(angle), axis(3)*axis(2)*(1-cos(angle)) + axis(1)*sin(angle), cos(angle) + (1-cos(angle))*axis(3)**2 /) + + calcRotationMatrix = r + + end function + + function identity() + use BeamDyn_Subs + implicit none + + real(BDKi) :: identity(3,3) + + identity(1,:) = (/ 1.0, 0.0, 0.0 /) + identity(2,:) = (/ 0.0, 1.0, 0.0 /) + identity(3,:) = (/ 0.0, 0.0, 1.0 /) + end function + + function RonXAxis(angle) + use BeamDyn_Subs + implicit none + + real(BDKi) :: angle, r(3,3), RonXAxis(3,3) + + r(1,:) = (/ 1.0_BDKi, 0.0_BDKi, 0.0_BDKi /) + r(2,:) = (/ 0.0_BDKi, cos(angle), -sin(angle) /) + r(3,:) = (/ 0.0_BDKi, sin(angle), cos(angle) /) + RonXAxis = r + end function + + function getMassMatrix() + use BeamDyn_Subs + implicit none + + real(BDKi), dimension(6,6) :: getMassMatrix + getMassMatrix(1,:) = (/ 1.E0, 0.0, 0.0, 0.0, 0.0, -0.5 /) + getMassMatrix(2,:) = (/ 0.0, 1.E0, 0.0, 0.0, 0.0, 0.5 /) + getMassMatrix(3,:) = (/ 0.0, 0.0, 1.E0, 0.5, -0.5, 0.0 /) + getMassMatrix(4,:) = (/ 0.0, 0.0, 0.5, 1.E0, 0.0, 0.0 /) + getMassMatrix(5,:) = (/ 0.0, 0.0, -0.5, 0.0, 1.E0, 0.0 /) + getMassMatrix(6,:) = (/ -0.5, 0.5, 0.0, 0.0, 0.0, 2.E0 /) + end function + + function getStiffnessMatrix() + use BeamDyn_Subs + implicit none + + real(BDKi), dimension(6,6) :: getStiffnessMatrix + getStiffnessMatrix(1,:) = (/ 1.E4, 0.0, 0.0, 0.0, 0.0, 0.0 /) + getStiffnessMatrix(2,:) = (/ 0.0, 1.E4, 0.0, 0.0, 0.0, 0.0 /) + getStiffnessMatrix(3,:) = (/ 0.0, 0.0, 1.E4, 0.0, 0.0, 0.0 /) + getStiffnessMatrix(4,:) = (/ 0.0, 0.0, 0.0, 1.E2, 0.0, 0.0 /) + getStiffnessMatrix(5,:) = (/ 0.0, 0.0, 0.0, 0.0, 1.E2, 0.0 /) + getStiffnessMatrix(6,:) = (/ 0.0, 0.0, 0.0, 0.0, 0.0, 200.E0 /) + end function + + function getGravityInZ() + use BeamDyn_Subs + implicit none + + real(BDKi), dimension(3) :: getGravityInZ + getGravityInZ = (/ 0.0, 0.0, -9.806 /) + end function + + type(BD_ParameterType) function simpleParameterType(elem_total, nodes_per_elem, nqp, qp_indx_offset, refine) RESULT(p) + + integer, intent(in ) :: elem_total + integer, intent(in ) :: nodes_per_elem + integer, intent(in ) :: nqp + integer, intent(in ) :: qp_indx_offset + integer, intent(in ) :: refine + + integer :: i, j + integer :: ErrStat + character(1024) :: ErrMsg + + p%elem_total = elem_total + p%nodes_per_elem = nodes_per_elem + p%nqp = nqp + p%qp_indx_offset = qp_indx_offset + p%refine = refine + + p%dof_node = 6 + + ! fixed size arrays + p%Glb_crv = (/ 0.0, 0.0, 0.0 /) + p%GlbRot = identity() + + ! allocate arrays + call AllocAry(p%qp%mmm, p%nqp, p%elem_total, 'qp_mmm', ErrStat, ErrMsg) + call AllocAry(p%qp%mEta, 3, p%nqp, p%elem_total, 'qp_RR0mEta', ErrStat, ErrMsg) + call AllocAry(p%Mass0_QP, 6, 6, p%nqp*p%elem_total, 'Mass0_QP', ErrStat, ErrMsg) + call AllocAry(p%QPtw_Shp_Shp_Jac, p%nqp, p%nodes_per_elem, p%nodes_per_elem, p%elem_total, 'QPtw_Shp_Shp_Jac', ErrStat, ErrMsg) + call AllocAry(p%QPtw_ShpDer_ShpDer_Jac, p%nqp, p%nodes_per_elem, p%nodes_per_elem, p%elem_total, 'QPtw_ShpDer_ShpDer_Jac', ErrStat, ErrMsg) + call AllocAry(p%QPtw_Shp_ShpDer, p%nqp, p%nodes_per_elem, p%nodes_per_elem, 'QPtw_Shp_ShpDer', ErrStat, ErrMsg) + call AllocAry(p%QPtw_Shp_Jac, p%nqp, p%nodes_per_elem, p%elem_total, 'QPtw_Shp_Jac', ErrStat, ErrMsg) + call AllocAry(p%Shp, p%nodes_per_elem, p%nqp, 'Shp', ErrStat, ErrMsg) + call AllocAry(p%ShpDer, p%nodes_per_elem, p%nqp, 'ShpDer', ErrStat, ErrMsg) + call AllocAry(p%QPtN, p%nqp, 'QPtN', ErrStat, ErrMsg) + call AllocAry(p%QPtWeight, p%nqp, 'QPtWeight', ErrStat, ErrMsg) + call AllocAry(p%QPtw_ShpDer, p%nqp, p%nodes_per_elem, 'QPtw_ShpDer', ErrStat, ErrMsg) + call AllocAry(p%Jacobian, p%nqp, p%elem_total, 'Jacobian', ErrStat, ErrMsg) + call AllocAry(p%uuN0, p%dof_node, p%nodes_per_elem, p%elem_total,'uuN0', ErrStat, ErrMsg) + + ! construct arrays + p%qp%mmm = 1.0 + + do j=1, p%elem_total + do i=1, p%nqp + p%qp%mEta(:,i,j) = (/ 0.0, 0.0, 0.0 /) + p%Mass0_QP(:,:,(i-1)*p%elem_total+j) = getMassMatrix() + end do + end do + + end function + + type(BD_MiscVarType) function simpleMiscVarType(nqp, nelem) RESULT(m) + + integer, intent(in) :: nqp, nelem + integer :: i, j + integer :: ErrStat + character(1024) :: ErrMsg + + ! scalars + + ! fixed size arrays + + ! allocate arrays + call AllocAry(m%qp%Fg, 6, nqp, nelem, 'qp_Fg', ErrStat, ErrMsg) + call AllocAry(m%qp%RR0, 3, 3, nqp, nelem, 'qp_RR0', ErrStat, ErrMsg) + call AllocAry(m%qp%RR0mEta, 3, nqp, nelem, 'qp_RR0mEta', ErrStat, ErrMsg) + call AllocAry(m%DistrLoad_QP, 6, nqp, nelem, 'DistrLoad_QP', ErrStat, ErrMsg) + call AllocAry(m%qp%rho, 3, 3, nqp, nelem, 'qp_rho', ErrStat, ErrMsg) + + ! construct arrays + do j=1, nelem + do i=1, nqp + m%qp%RR0(:,:,i,j) = identity() + m%qp%RR0mEta(:,i,j) = (/ 0.0, 0.0, 0.0 /) + end do + end do + + end function + + type(BD_InputType) function simpleInputType(nqp, nelem) RESULT(i) + + integer, intent(in) :: nqp, nelem + integer :: j + integer :: ErrStat + character(1024) :: ErrMsg + + ! scalars + + ! fixed size arrays + + ! allocate arrays + call AllocAry(i%DistrLoad%Force, 3, nqp*nelem, 'DistrLoadForce', ErrStat, ErrMsg) + call AllocAry(i%DistrLoad%Moment, 3, nqp*nelem, 'DistrLoadMoment', ErrStat, ErrMsg) + + ! construct arrays + do j = 1, nqp*nelem + i%DistrLoad%Force(:,j) = (/ 3*(j-1)+1, 3*(j-1)+2, 3*(j-1)+3 /) + i%DistrLoad%Moment(:,j) = (/ -3*(j-1)-1, -3*(j-1)-2, -3*(j-1)-3 /) + end do + + end function + + type(BD_InputFile) function simpleInputFile() RESULT(i) + + integer :: j + integer :: ErrStat + character(1024) :: ErrMsg + + ! scalars + i%QuasiStaticInit = .false. ! - - - "QuasiStaticInit" - + i%member_total = 1 ! - - - "Total number of members" - + i%kp_total = 3 ! - - - "Total number of key point" - + i%order_elem = 15 ! - - - "Order of interpolation (basis) function" - + i%NRMax = 10 ! - - - "Max number of iterations in Newton Ralphson algorithm" - + i%quadrature = 1 ! - - - "Quadrature: 1: Gauss; 2: Trapezoidal" - + i%n_fact = 5 ! - - - "Factorization frequency" - + i%refine = 1 ! - - - "FE mesh refinement factor for trapezoidal quadrature" - + i%rhoinf = 0.0 ! - - - "Numerical damping parameter for generalized-alpha integrator" - + i%DTBeam = 2E-03 ! - - - "Time interval for BeamDyn calculations {or default} (s)" - + i%UsePitchAct = .FALSE. ! - - - "Whether to use a pitch actuator inside BeamDyn" (flag) + i%pitchJ = 0.0 ! - - - "Pitch actuator inertia" (kg-m^2) + i%pitchK = 0.0 ! - - - "Pitch actuator stiffness" (kg-m^2/s^2) + i%pitchC = 0.0 ! - - - "Pitch actuator damping" - (kg-m^2/s) + i%Echo = .TRUE. ! - - - "Echo" + i%NNodeOuts = 1 ! - - - "Number of node outputs [0 - 9]" - + i%OutNd = 1 ! {9} - - "Nodes whose values will be output" - + i%SumPrint = .TRUE. ! - - - "Print summary data to file? (.sum)" - + i%OutFmt = "ES16.8E2" ! - - - "Format specifier" - + + ! fixed size arrays + i%kp_member = (/ 3 /) !{:} - - "Number of key points in each member" - + i%OutList = (/ "TipTDxr, TipTDyr, TipTDzr", "TipRDxr, TipRDyr, TipRDzr" /) ! {:} - - "List of user-requested output channels" - + + ! allocate arrays + call AllocAry(i%kp_coordinate, 3, 4, 'kp_coordinate', ErrStat, ErrMsg) + + ! construct arrays + i%kp_coordinate(1,:) = (/ 0.000000, 0.000000, 0.0000, 0.00000 /) ! {:}{:} - - "Key point coordinates array" - + i%kp_coordinate(2,:) = (/ 0.000000, 0.000000, 5.0000, 0.00000 /) + i%kp_coordinate(3,:) = (/ 0.000000, 0.000000, 10.0000, 0.00000 /) + + end function + +end module diff --git a/OpenFAST/modules/elastodyn/CMakeLists.txt b/OpenFAST/modules/elastodyn/CMakeLists.txt new file mode 100644 index 000000000..5610748e9 --- /dev/null +++ b/OpenFAST/modules/elastodyn/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/ElastoDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/ElastoDyn_Types.f90) +endif() + +set(ED_SOURCES + src/ElastoDyn.f90 + src/ElastoDyn_IO.f90 + src/ElastoDyn_AllBldNdOuts_IO.f90 + src/ED_UserSubs.f90 + src/ElastoDyn_Types.f90 + ) + +add_library(elastodynlib ${ED_SOURCES}) +target_link_libraries(elastodynlib servodynlib nwtclibs) + +install(TARGETS elastodynlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/elastodyn/README.md b/OpenFAST/modules/elastodyn/README.md new file mode 100644 index 000000000..a52f91e43 --- /dev/null +++ b/OpenFAST/modules/elastodyn/README.md @@ -0,0 +1,4 @@ +# ElastoDyn Module + +## Overview +ElastoDyn is the structural dynamics module in the OpenFAST framework. diff --git a/OpenFAST/modules/elastodyn/src/ED_UserSubs.f90 b/OpenFAST/modules/elastodyn/src/ED_UserSubs.f90 new file mode 100644 index 000000000..5184e8159 --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ED_UserSubs.f90 @@ -0,0 +1,156 @@ + ! NOTE: This source file contains dummy placeholders for the + ! user-specified routines available in ElastoDyn. These routines + ! are as follows: + ! Routine Description + ! ------------ --------------------------------------------------- + ! UserRFrl() User-specified rotor-furl spring/damper model. + ! UserTeet() User-specified rotor-teeter spring/damper model. + ! UserTFrl() User-specified tail-furl spring/damper model. + ! In order to interface ElastoDyn with your own user-specified routines, + ! you can develop your own logic within these dummy placeholders and + ! recompile; We recommend that you do not use these files, as they do not + ! conform to the FAST Modularization framework. + +module ED_UserSubs +contains + +!======================================================================= +SUBROUTINE UserRFrl ( RFrlDef, RFrlRate, ZTime, DirRoot, RFrlMom ) + + + ! This is a dummy routine for holding the place of a user-specified + ! rotor-furl spring/damper. Modify this code to create your own device. + + ! NOTE: If you (the user) wants to switch on-or-off the rotor-furl DOF at + ! runtime from this user-defined routine, then do the following: + ! (1) USE MODULE DOFs(). + ! (2) Type in "DOF_Flag(DOF_RFrl) = VALUE" where VALUE = .TRUE. or + ! .FALSE. depending on whether you want to turn-on or turn-off + ! the DOF, respectively. Turning off the DOF forces the + ! current RATE to remain fixed. If the rate is currently zero, + ! the current POSITION will remain fixed as well. + ! This technique is useful, for example, if the rotor-furl hinge has + ! an electromagnetic latch that will unlock and relock the hinge under + ! certain specified conditions. + ! Note that this technique WILL NOT work for user-defined routines + ! written for ADAMS datasets extracted using the FAST-to-ADAMS + ! preprocessor. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(R8Ki), INTENT(IN ) :: RFrlDef ! Rotor-furl angular deflection, rad. +REAL(ReKi), INTENT(OUT) :: RFrlMom ! Rotor-furl restoring moment, N-m. +REAL(R8Ki), INTENT(IN ) :: RFrlRate ! Rotor-furl angular rate, rad/s +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(*), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +RFrlMom = 0.0 + + + +RETURN +END SUBROUTINE UserRFrl +!======================================================================= +SUBROUTINE UserTeet ( TeetDef, TeetRate, ZTime, DirRoot, TeetMom ) + + + ! This is a dummy routine for holding the place of a user-specified + ! teeter spring/damper. Modify this code to create your own device. + + ! NOTE: If you (the user) wants to switch on-or-off the teeter DOF at + ! runtime from this user-defined routine, then do the following: + ! (1) USE MODULE DOFs(). + ! (2) Type in "DOF_Flag(DOF_Teet) = VALUE" where VALUE = .TRUE. or + ! .FALSE. depending on whether you want to turn-on or turn-off + ! the DOF, respectively. Turning off the DOF forces the + ! current RATE to remain fixed. If the rate is currently zero, + ! the current POSITION will remain fixed as well. + ! This technique is useful, for example, if the teeter hinge has + ! an electromagnetic latch that will unlock and relock the hinge under + ! certain specified conditions. + ! Note that this technique WILL NOT work for user-defined routines + ! written for ADAMS datasets extracted using the FAST-to-ADAMS + ! preprocessor. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(R8Ki), INTENT(IN ) :: TeetDef ! Rotor-teeter angular deflection, rad. +REAL(ReKi), INTENT(OUT) :: TeetMom ! Rotor-teeter restoring moment, N-m. +REAL(R8Ki), INTENT(IN ) :: TeetRate ! Rotor-teeter angular rate, rad/s +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +TeetMom = 0.0 + + + +RETURN +END SUBROUTINE UserTeet +!======================================================================= +SUBROUTINE UserTFrl ( TFrlDef, TFrlRate, ZTime, DirRoot, TFrlMom ) + + + ! This is a dummy routine for holding the place of a user-specified + ! tail-furl spring/damper. Modify this code to create your own device. + + ! NOTE: If you (the user) wants to switch on-or-off the tail-furl DOF at + ! runtime from this user-defined routine, then do the following: + ! (1) USE MODULE DOFs(). + ! (2) Type in "DOF_Flag(DOF_TFrl) = VALUE" where VALUE = .TRUE. or + ! .FALSE. depending on whether you want to turn-on or turn-off + ! the DOF, respectively. Turning off the DOF forces the + ! current RATE to remain fixed. If the rate is currently zero, + ! the current POSITION will remain fixed as well. + ! This technique is useful, for example, if the tail-furl hinge has + ! an electromagnetic latch that will unlock and relock the hinge under + ! certain specified conditions. + ! Note that this technique WILL NOT work for user-defined routines + ! written for ADAMS datasets extracted using the FAST-to-ADAMS + ! preprocessor. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(R8Ki), INTENT(IN ) :: TFrlDef ! Tail-furl angular deflection, rad. +REAL(ReKi), INTENT(OUT) :: TFrlMom ! Tail-furl restoring moment, N-m. +REAL(R8Ki), INTENT(IN ) :: TFrlRate ! Tail-furl angular rate, rad/s +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +TFrlMom = 0.0 + + + +RETURN +END SUBROUTINE UserTFrl +!======================================================================= +end module ED_UserSubs diff --git a/OpenFAST/modules/elastodyn/src/ElastoDyn.f90 b/OpenFAST/modules/elastodyn/src/ElastoDyn.f90 new file mode 100644 index 000000000..2e0c2814e --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ElastoDyn.f90 @@ -0,0 +1,11858 @@ +!********************************************************************************************************************************** +! The ElastoDyn.f90, ElastoDyn_IO.f90, and ElastoDyn_Types.f90 make up the ElastoDyn module of the +! FAST Modularization Framework. ElastoDyn_Types is auto-generated based on FAST_Registry.txt. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! Copyright (C) 2017-2018 Envision Energy USA, LTD. +! +! This file is part of ElastoDyn. +! +! 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 ElastoDyn + + USE ElastoDyn_IO + USE NWTC_LAPACK + + USE ED_UserSubs ! <- module not in the FAST Framework! + + USE ElastoDyn_AllBldNdOuts_IO + + IMPLICIT NONE + + PRIVATE + + REAL(R8Ki) :: MinPerturb = SQRT( EPSILON( 1.0_R8Ki ) ) ! minimum value for perturbation in ED jacobians + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: ED_Init ! Initialization routine + PUBLIC :: ED_End ! Ending routine (includes clean up) + + PUBLIC :: ED_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: ED_CalcOutput ! Routine for computing outputs + + PUBLIC :: ED_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: ED_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: ED_UpdateDiscState ! Tight coupling routine for updating discrete states + + PUBLIC :: ED_JacobianPInput ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the inputs (u) + PUBLIC :: ED_JacobianPContState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the continuous + ! states (x) + PUBLIC :: ED_JacobianPDiscState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the discrete + ! states (xd) + PUBLIC :: ED_JacobianPConstrState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the constraint + ! states (z) + + PUBLIC :: ED_GetOP ! Routine to pack the operating point values (for linearization) into arrays + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE ED_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(ED_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(ED_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(ED_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(ED_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(ED_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(ED_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(ED_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) ED_UpdateStates() is called in loose coupling & + !! (2) ED_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(ED_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + TYPE(ED_InputFile) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + INTEGER(IntKi) :: i ! loop counters + LOGICAL, PARAMETER :: GetAdamsVals = .FALSE. ! Determines if we should read Adams values and create (update) an Adams model + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + + CALL DispNVD( ED_Ver ) + + !............................................................................................ + ! Read the input file and validate the data + !............................................................................................ + p%BD4Blades = .NOT. InitInp%CompElast ! if we're not using ElastoDyn for the blades, use BeamDyn + p%UseAD14 = LEN_TRIM(InitInp%ADInputFile) > 0 ! if we're using AD14, we need to use the AD14 input files + + p%RootName = InitInp%RootName ! FAST already adds '.ED' to the root name + + CALL ED_ReadInput( InitInp%InputFile, InitInp%ADInputFile, InputFileData, GetAdamsVals, p%BD4Blades, Interval, p%RootName, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( p%BD4Blades ) THEN + + ! Set DOFs to FALSE for whatever values you don't want on for BeamDyn + InputFileData%FlapDOF1 = .FALSE. + InputFileData%FlapDOF2 = .FALSE. + InputFileData%EdgeDOF = .FALSE. + + ! Set other values not used for BeamDyn + InputFileData%OoPDefl = 0.0_ReKi + InputFileData%IPDefl = 0.0_ReKi + InputFileData%TipMass = 0.0_ReKi + InputFileData%TipRad = 0.0_ReKi + InputFileData%NBlGages = 0 + InputFileData%BldGagNd = 0 + InputFileData%BldNodes = 0 + + END IF + + + CALL ED_ValidateInput( InputFileData, p%BD4Blades, InitInp%Linearize, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + CALL ED_SetParameters( InputFileData, p, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + xd%DummyDiscState = 0. ! we don't have discrete states + z%DummyConstrState = 0. ! we don't have constraint states + + ! initialize the continuous states: + CALL Init_ContStates( x, p, InputFileData, OtherState, ErrStat2, ErrMsg2 ) ! initialize the continuous states + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! Initialize other states and misc variables: + CALL Init_MiscOtherStates( m, OtherState, p, x, InputFileData, ErrStat2, ErrMsg2 ) ! initialize the other states (must do this after ED_SetParameters) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !............................................................................................ + ! Define initial guess for the system inputs here: + !............................................................................................ + + ! allocate all the arrays that store data in the input type and initialize the values: + CALL Init_u( u, p, x, InputFileData, m, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !............................................................................................ + ! Define system output initializations (set up meshes) here: + !............................................................................................ + + CALL ED_AllocOutput(p, m, u, y, ErrStat2, ErrMsg2) ! u is sent so we can create sibling meshes + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + IF (p%BD4Blades) THEN + ! we need the initial outputs to send BeamDyn for its states. I should probably put them in + ! the InitOutput type, but I'm going to use the ED_Outputs instead + ! + ! ! set the coordinate system variables: + !CALL SetCoordSy( t, m%CoordSys, m%RtHS, u%BlPitchCom, p, x, ErrStat, ErrMsg ) + ! IF (ErrStat >= AbortErrLev) RETURN + ! + !CALL CalculatePositions( p, x, m%CoordSys, m%RtHS ) ! calculate positions + !CALL CalculateAngularPosVelPAcc(p, x, m%CoordSys, m%RtHS ) ! calculate angular positions, velocities, and partial accelerations, including partial angular quantities + !CALL CalculateLinearVelPAcc( p, x, m%CoordSys, m%RtHS ) ! calculate linear velocities and partial accelerations + + + + CALL ED_CalcOutput( 0.0_DbKi, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + END IF + + + !............................................................................................ + ! Define initialization-routine output here: + !............................................................................................ + CALL AllocAry( InitOut%WriteOutputHdr, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputHdr', errStat2, errMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( InitOut%WriteOutputUnt, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutputUnt', errStat2, errMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + do i=1,p%NumOuts + InitOut%WriteOutputHdr(i) = p%OutParam(i)%Name + InitOut%WriteOutputUnt(i) = p%OutParam(i)%Units + end do + + ! Set the info in WriteOutputHdr and WriteOutputUnt + CALL AllBldNdOuts_InitOut( InitOut, p, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + InitOut%Ver = ED_Ver + InitOut%NumBl = p%NumBl + InitOut%Gravity = p%Gravity + InitOut%BladeLength = p%TipRad - p%HubRad + InitOut%TowerHeight = p%TwrFlexL + InitOut%TowerBaseHeight = p%TowerBsHt + InitOut%PlatformPos = x%QT(1:6) + InitOut%HubHt = p%HubHt + InitOut%TwrBasePos = y%TowerLn2Mesh%Position(:,p%TwrNodes + 2) + InitOut%HubRad = p%HubRad + InitOut%RotSpeed = p%RotSpeed + InitOut%isFixed_GenDOF = .not. InputFileData%GenDOF + + + if (.not. p%BD4Blades) then + ALLOCATE(InitOut%BldRNodes(p%BldNodes), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + call CheckError( ErrStat2, ErrMsg2 ) + if (ErrStat2 >= AbortErrLev) return + END IF + InitOut%BldRNodes(:) = p%RNodes(:) + else + !Deal with BeamDyn case later + end if + + ALLOCATE(InitOut%TwrHNodes(p%TwrNodes), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + call CheckError( ErrStat2, ErrMsg2 ) + if (ErrStat2 >= AbortErrLev) return + END IF + InitOut%TwrHNodes(:) = p%HNodes(:) + + CALL AllocAry(InitOut%BlPitch, p%NumBl, 'BlPitch', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + InitOut%BlPitch = InputFileData%BlPitch(1:p%NumBl) + + !............................................................................................ + ! set up data needed for linearization analysis + !............................................................................................ + + if (InitInp%Linearize) then + call ED_Init_Jacobian(p, u, y, InitOut, ErrStat2, ErrMsg2) + call CheckError( ErrStat2, ErrMsg2 ) + if (ErrStat >= AbortErrLev) return + end if + + + !............................................................................................ + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + !............................................................................................ + + Interval = p%DT + + + ! Print the summary file if requested: + IF (InputFileData%SumPrint) THEN + CALL ED_PrintSum( p, OtherState, GetAdamsVals, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + ! Destroy the InputFileData structure (deallocate arrays) + + CALL ED_DestroyInputFile(InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_Init:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CALL ED_DestroyInputFile(InputFileData, ErrStat3, ErrMsg3 ) + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE ED_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE ED_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(ED_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(ED_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ED_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(ED_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL ED_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL ED_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL ED_DestroyContState( x, ErrStat, ErrMsg ) + CALL ED_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL ED_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL ED_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL ED_DestroyOutput( y, ErrStat, ErrMsg ) + + CALL ED_DestroyMisc( m, ErrStat, ErrMsg ) + + + +END SUBROUTINE ED_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ED_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current simulation time step n = 0,1,... + TYPE(ED_InputType), INTENT(INOUT) :: u(:) !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< Times associated with u(:), in seconds + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(ED_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(ED_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(ED_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + SELECT CASE ( p%method ) + + CASE (Method_RK4) + + CALL ED_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (Method_AB4) + + CALL ED_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (Method_ABM4) + + CALL ED_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE DEFAULT !bjj: we already checked this at initialization, but for completeness: + + ErrStat = ErrID_Fatal + ErrMsg = ' Error in ElastoDyn_UpdateStates: p%method must be 1 (RK4), 2 (AB4), or 3 (ABM4)' + RETURN + + END SELECT + + ! Make sure the rotor azimuth is not greater or equal to 360 degrees: + + ! bjj: per jmj, the subtraction of TwoPi here is so that we don't run into numerical issues with large GeAz (in large simulations) + ! this subtraction is okay because we use x%QT(DOF_GeAz) only in equations with SIN() and/or COS() so it doesn't matter + ! if there is a discontinunity in the channel. + ! bjj: why don't we just do a modulo on x%QT(DOF_GeAz) instead of using x%QT(DOF_DrTr) with it? + + IF ( ( x%QT(DOF_GeAz) + x%QT(DOF_DrTr) ) >= TwoPi_D ) x%QT(DOF_GeAz) = x%QT(DOF_GeAz) - TwoPi_D + + +END SUBROUTINE ED_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! This SUBROUTINE is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! NOTE: the descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +!! NOTE: no matter how many channels are selected for output, all of the outputs are calculated +!! All of the calculated output channels are placed into the m\%AllOuts(:), while the channels selected for outputs are +!! placed in the y\%WriteOutput(:) array. +SUBROUTINE ED_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ED_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(ED_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(ED_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, PARAMETER :: NDims = 3 + + REAL(ReKi) :: AngAccEB (NDims) ! Angular acceleration of the base plate (body B) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccEN (NDims) ! Angular acceleration of the nacelle (body N) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccEH (NDims) ! Angular acceleration of the hub (body N) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccER (NDims) ! Angular acceleration of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccEX (NDims) ! Angular acceleration of the platform (body X) in the inertia frame (body E for earth). +! REAL(ReKi) :: ComDenom ! Common denominator used in several expressions. +! REAL(ReKi) :: CThrstys ! Estimate of the ys-location of the center of thrust. +! REAL(ReKi) :: CThrstzs ! Estimate of the zs-location of the center of thrust. + REAL(R8Ki) :: FrcMGagB (NDims) ! Total force at the blade element (body M) / blade strain gage location (point S) due to the blade above the strain gage. + REAL(ReKi) :: FrcFGagT (NDims) ! Total force at the tower element (body F) / tower strain gage location (point T) due to the nacelle and rotor and tower above the strain gage. + REAL(ReKi) :: FrcONcRt (NDims) ! Total force at the yaw bearing (point O ) due to the nacelle, generator, and rotor + REAL(ReKi) :: FrcPRot (NDims) ! Total force at the teeter pin (point P ) due to the rotor + REAL(ReKi) :: FrcT0Trb (NDims) ! Total force at the base of flexible portion of the tower (point T(0)) due to the entire wind turbine + REAL(ReKi) :: FZHydro (NDims) ! Total platform hydrodynamic force at the platform reference (point Z) +! REAL(ReKi) :: HHWndVec (NDims) ! Hub-height wind vector in the AeroDyn coordinate system + REAL(ReKi) :: LinAccEIMU(NDims) ! Total linear acceleration of the nacelle IMU (point IMU) in the inertia frame (body E for earth) + REAL(ReKi) :: LinAccEO (NDims) ! Total linear acceleration of the base plate (point O) in the inertia frame (body E for earth) + REAL(ReKi) :: LinAccEZ (NDims) ! Total linear acceleration of the platform refernce (point Z) in the inertia frame (body E for earth) + REAL(ReKi) :: MomBNcRt (NDims) ! Total moment at the base plate (body B) / yaw bearing (point O) due to the nacelle, generator, and rotor. + REAL(ReKi) :: MomFGagT (NDims) ! Total moment at the tower element (body F) / tower strain gage location (point T) due to the nacelle and rotor and tower above the strain gage. + REAL(ReKi) :: MomLPRot (NDims) ! Total moment at the low-speed shaft (body L) / teeter pin (point P) due to the rotor. + REAL(ReKi) :: MomMGagB (NDims) ! Total moment at the blade element (body M) / blade strain gage location (point S) due to the blade above the strain gage. + REAL(ReKi) :: MomNGnRt (NDims) ! Total moment at the nacelle (body N) / specified point on rotor-furl axis (point V) due to the structure that furls with the rotor, generator, and rotor. + REAL(ReKi) :: MomNTail (NDims) ! Total moment at the nacelle (body N) / specified point on tail-furl axis (point W) due to the tail. + REAL(ReKi) :: MomX0Trb (NDims) ! Total moment at the tower base (body X) / base of flexible portion of the tower (point T(0)) due to the entire wind turbine. + REAL(ReKi) :: MXHydro (NDims) ! Total platform hydrodynamic moment acting at the platform (body X) / platform reference (point Z). + REAL(R8Ki) :: rOPO (NDims) ! Position vector from the undeflected tower top (point O prime) to the deflected tower top (point O). + REAL(R8Ki) :: rOSTip (NDims) ! Position vector from the deflected tower top (point O) to the deflected blade tip (point S tip). + REAL(R8Ki) :: rOSTipxn ! Component of rOSTip directed along the xn-axis. + REAL(R8Ki) :: rOSTipyn ! Component of rOSTip directed along the yn-axis. + REAL(R8Ki) :: rOSTipzn ! Component of rOSTip directed along the zn-axis. + REAL(R8Ki) :: rTPT (NDims) ! Position vector from the undeflected tower node (point T prime) to the deflected node (point T) + REAL(R8Ki) :: rSPS (NDims) ! Position vector from the undeflected blade node (point S prime) to the deflected node (point S) + REAL(R8Ki) :: rSTipPSTip(NDims) ! Position vector from the undeflected blade tip (point S tip prime) to the deflected blade tip (point S tip). + REAL(R8Ki) :: TmpVec (NDims) ! A temporary vector used in various computations. + REAL(R8Ki) :: TmpVec2 (NDims) ! A temporary vector. + + REAL(ReKi) :: LinAccES (NDims,0:p%TipNode,p%NumBl) ! Total linear acceleration of a point on a blade (point S) in the inertia frame (body E for earth). + REAL(ReKi) :: LinAccET (NDims,0:p%TwrNodes) ! Total linear acceleration of a point on the tower (point T) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccEF (NDims,0:p%TwrNodes) ! Total angular acceleration of tower element J (body F) in the inertia frame (body E for earth). + REAL(ReKi) :: FrcS0B (NDims,p%NumBl) ! Total force at the blade root (point S(0)) due to the blade. + REAL(ReKi) :: FTTower (NDims,p%TwrNodes) ! Total hydrodynamic + aerodynamic force per unit length acting on the tower at point T. + REAL(ReKi) :: MFHydro (NDims,p%TwrNodes) ! Total hydrodynamic + aerodynamic moment per unit length acting on a tower element (body F) at point T. + REAL(ReKi) :: MomH0B (NDims,p%NumBl) ! Total moment at the hub (body H) / blade root (point S(0)) due to the blade. + + + INTEGER(IntKi) :: I ! Generic index + INTEGER(IntKi) :: J, J2 ! Loops through nodes / elements + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: NodeNum ! Mesh node number for given blade/node + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message + + + LOGICAL, PARAMETER :: UpdateValues = .TRUE. ! determines if the OtherState values need to be updated + TYPE(ED_ContinuousStateType) :: dxdt ! Continuous state derivs at t + + ! Initialize some output values + ErrStat = ErrID_None + ErrMsg = "" + + + ! SEE IF THESE NEED TO BE CALLED (i.e., if UpdateStates was called, these values are already calculated) + IF ( UpdateValues ) THEN + ! Update the OtherState data by calculating the derivative... + !OtherState%HSSBrTrqC = SIGN( u%HSSBrTrqC, x%QDT(DOF_GeAz) ) + CALL ED_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) ! sets m%QD2T = dxdt%QDT + CALL ED_DestroyContState( dxdt, ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + + !.............................. + ! Outputs for HydroDyn, UsrPtfm and UsrTwr + !.............................. + + !u_UsrPtfm%X = x_ED%QT(1:6) + !u_UsrPtfm%XD = x_ED%QDT(1:6) + + !u_UsrTwr%X(:,J) = (/ OtherSt_ED%RtHS%rT(1,J), -OtherSt_ED%RtHS%rT(3,J), OtherSt_ED%RtHS%rT( 2,J)+ p%PtfmRefzt,& + ! OtherSt_ED%RtHS%AngPosEF(1,J), -OtherSt_ED%RtHS%AngPosEF(3,J), OtherSt_ED%RtHS%AngPosEF(2,J) /) + !u_UsrTwr%XD(:,J) = (/ OtherSt_ED%RtHS%LinVelET(1,J), -OtherSt_ED%RtHS%LinVelET(3,J), OtherSt_ED%RtHS%LinVelET(2,J),& + ! OtherSt_ED%RtHS%AngVelEF(1,J), -OtherSt_ED%RtHS%AngVelEF(3,J), OtherSt_ED%RtHS%AngVelEF(2,J) /) + + + + + ! Array m%AllOuts() is initialized to 0.0 in initialization, so we are not going to reinitialize it here. + + !............................................................................................................................... + ! Calculate all of the total forces and moments using all of the partial forces and moments calculated in RtHS(). Also, + ! calculate all of the total angular and linear accelerations using all of the partial accelerations calculated in RtHS(). + ! To do this, first initialize the variables using the portions not associated with the accelerations. Then add the portions + ! associated with the accelerations one by one: + !............................................................................................................................... + + AngAccEB = m%RtHS%AngAccEBt + AngAccEH = m%RtHS%AngAccEHt + AngAccEN = m%RtHS%AngAccENt + AngAccER = m%RtHS%AngAccERt + AngAccEX = m%RtHS%AngAccEXt + LinAccEIMU = m%RtHS%LinAccEIMUt + LinAccEO = m%RtHS%LinAccEOt + LinAccEZ = m%RtHS%LinAccEZt + FrcONcRt = m%RtHS%FrcONcRtt + FrcPRot = m%RtHS%FrcPRott + FrcT0Trb = m%RtHS%FrcT0Trbt + + ! was FZHydro = m%RtHS%FZHydrot + FZHydro = u%PlatformPtMesh%Force(DOF_Sg,1)*m%RtHS%PLinVelEZ(DOF_Sg,0,:) & + + u%PlatformPtMesh%Force(DOF_Sw,1)*m%RtHS%PLinVelEZ(DOF_Sw,0,:) & + + u%PlatformPtMesh%Force(DOF_Hv,1)*m%RtHS%PLinVelEZ(DOF_Hv,0,:) + + MomBNcRt = m%RtHS%MomBNcRtt + MomLPRot = m%RtHS%MomLPRott + MomNGnRt = m%RtHS%MomNGnRtt + MomNTail = m%RtHS%MomNTailt + MomX0Trb = m%RtHS%MomX0Trbt + + ! was MXHydro = m%RtHS%MXHydrot + MXHydro = u%PlatformPtMesh%Moment(DOF_R-3,1)*m%RtHS%PAngVelEX(DOF_R ,0,:) & + + u%PlatformPtMesh%Moment(DOF_P-3,1)*m%RtHS%PAngVelEX(DOF_P ,0,:) & + + u%PlatformPtMesh%Moment(DOF_Y-3,1)*m%RtHS%PAngVelEX(DOF_Y ,0,:) + + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + AngAccEB = AngAccEB + m%RtHS%PAngVelEB (p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + AngAccEH = AngAccEH + m%RtHS%PAngVelEH (p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + AngAccEN = AngAccEN + m%RtHS%PAngVelEN (p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + AngAccER = AngAccER + m%RtHS%PAngVelER (p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + LinAccEIMU = LinAccEIMU + m%RtHS%PLinVelEIMU(p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + LinAccEO = LinAccEO + m%RtHS%PLinVelEO (p%DOFs%SrtPS(I),0,:)*m%QD2T(p%DOFs%SrtPS(I)) + FrcONcRt = FrcONcRt + m%RtHS%PFrcONcRt (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + FrcPRot = FrcPRot + m%RtHS%PFrcPRot (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + FrcT0Trb = FrcT0Trb + m%RtHS%PFrcT0Trb (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + MomBNcRt = MomBNcRt + m%RtHS%PMomBNcRt (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + MomLPRot = MomLPRot + m%RtHS%PMomLPRot (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + MomNGnRt = MomNGnRt + m%RtHS%PMomNGnRt (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + MomNTail = MomNTail + m%RtHS%PMomNTail (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + MomX0Trb = MomX0Trb + m%RtHS%PMomX0Trb (:,p%DOFs%SrtPS(I) )*m%QD2T(p%DOFs%SrtPS(I)) + ENDDO ! I - All active (enabled) DOFs + DO I = 1,p%DOFs%NPYE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + AngAccEX = AngAccEX + m%RtHS%PAngVelEX (p%DOFs%PYE (I),0,:)*m%QD2T(p%DOFs%PYE (I)) + LinAccEZ = LinAccEZ + m%RtHS%PLinVelEZ (p%DOFs%PYE (I),0,:)*m%QD2T(p%DOFs%PYE (I)) + + + FZHydro = FZHydro + (- u%PtfmAddedMass(DOF_Sg,p%DOFs%PYE(I))*m%RtHS%PLinVelEZ(DOF_Sg,0,:) & ! was FZHydro = FZHydro + m%RtHS%PFZHydro(p%DOFs%PYE(I),:)*m%QD2T(p%DOFs%PYE (I)) + - u%PtfmAddedMass(DOF_Sw,p%DOFs%PYE(I))*m%RtHS%PLinVelEZ(DOF_Sw,0,:) & + - u%PtfmAddedMass(DOF_Hv,p%DOFs%PYE(I))*m%RtHS%PLinVelEZ(DOF_Hv,0,:) ) & + *m%QD2T(p%DOFs%PYE (I)) + ! was MXHydro = MXHydro + m%RtHS%PMXHydro (p%DOFs%PYE (I), :)*m%QD2T(p%DOFs%PYE (I)) + MXHydro = MXHydro + (- u%PtfmAddedMass(DOF_R ,p%DOFs%PYE(I))*m%RtHS%PAngVelEX(DOF_R ,0,:) & + - u%PtfmAddedMass(DOF_P ,p%DOFs%PYE(I))*m%RtHS%PAngVelEX(DOF_P ,0,:) & + - u%PtfmAddedMass(DOF_Y ,p%DOFs%PYE(I))*m%RtHS%PAngVelEX(DOF_Y ,0,:) ) & + *m%QD2T(p%DOFs%PYE (I)) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + + + + DO K = 1,p%NumBl ! Loop through all blades + + FrcS0B (: ,K) = m%RtHS%FrcS0Bt (:,K ) + MomH0B (: ,K) = m%RtHS%MomH0Bt (:,K ) + + DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + FrcS0B (: ,K) = FrcS0B (: ,K) + m%RtHS%PFrcS0B (:,K, p%DOFs%PSE(K,I) )*m%QD2T(p%DOFs%PSE(K,I)) + MomH0B (: ,K) = MomH0B (: ,K) + m%RtHS%PMomH0B (:,K, p%DOFs%PSE(K,I) )*m%QD2T(p%DOFs%PSE(K,I)) + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + DO J = 0,p%TipNode ! Loop through the blade nodes / elements + + LinAccES(:,J,K) = m%RtHS%LinAccESt(:,K,J) + + DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + LinAccES(:,J,K) = LinAccES(:,J,K) + m%RtHS%PLinVelES(K,J,p%DOFs%PSE(K,I),0,:)*m%QD2T(p%DOFs%PSE(K,I)) + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + ENDDO ! J - Blade nodes / elements + + ENDDO ! K - All blades + + DO J = 0,p%TwrNodes ! Loop through the tower nodes / elements, starting at the tower base (0) + + LinAccET(:,J) = m%RtHS%LinAccETt(:,J) + AngAccEF(:,J) = m%RtHS%AngAccEFt(:,J) + + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + LinAccET(:,J) = LinAccET(:,J) + m%RtHS%PLinVelET(J,p%DOFs%PTE(I),0,:)*m%QD2T(p%DOFs%PTE(I)) + AngAccEF(:,J) = AngAccEF(:,J) + m%RtHS%PAngVelEF(J,p%DOFs%PTE(I),0,:)*m%QD2T(p%DOFs%PTE(I)) + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + + ENDDO ! J - Tower nodes / elements + + + DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements + + FTTower (:,J) = m%RtHS%FTHydrot (:,J) + MFHydro (:,J) = m%RtHS%MFHydrot (:,J) + + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + FTTower (:,J) = FTTower (:,J) + m%RtHS%PFTHydro (:,J,p%DOFs%PTE(I) )*m%QD2T(p%DOFs%PTE(I)) + MFHydro (:,J) = MFHydro (:,J) + m%RtHS%PMFHydro (:,J,p%DOFs%PTE(I) )*m%QD2T(p%DOFs%PTE(I)) + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + + ENDDO ! J - Tower nodes / elements + + + ! Convert the units of the forces and moments from N and N-m + ! to kN and kN-m: + + FrcONcRt = 0.001*FrcONcRt + FrcPRot = 0.001*FrcPRot + FrcT0Trb = 0.001*FrcT0Trb + FZHydro = 0.001*FZHydro + MomBNcRt = 0.001*MomBNcRt + MomLPRot = 0.001*MomLPRot + MomNGnRt = 0.001*MomNGnRt + MomNTail = 0.001*MomNTail + MomX0Trb = 0.001*MomX0Trb + MXHydro = 0.001*MXHydro + FrcS0B = 0.001*FrcS0B + MomH0B = 0.001*MomH0B + + + !............................................................................................................................... + ! set the values in the AllOuts array: + !............................................................................................................................... + ! Define the output channel specifying the current simulation time: + + m%AllOuts( Time) = REAL( t, ReKi ) + + + ! Blade (1-3) Tip Motions: + + DO K = 1,p%NumBl + rSTipPSTip = m%RtHS%rS0S(:,K,p%TipNode) - p%BldFlexL*m%CoordSys%j3(K,:) ! Position vector from the undeflected blade tip (point S tip prime) to the deflected blade tip (point S tip) of blade 1. + rOSTip = m%RtHS%rS (:,K,p%TipNode) - m%RtHS%rO ! Position vector from the deflected tower top (point O) to the deflected blade tip (point S tip) of blade 1. + rOSTipxn = DOT_PRODUCT( rOSTip, m%CoordSys%d1 ) ! Component of rOSTip directed along the xn-axis. + rOSTipyn = -1.0*DOT_PRODUCT( rOSTip, m%CoordSys%d3 ) ! Component of rOSTip directed along the yn-axis. + rOSTipzn = DOT_PRODUCT( rOSTip, m%CoordSys%d2 ) ! Component of rOSTip directed along the zn-axis. + + IF (.NOT. p%BD4Blades) THEN + m%AllOuts( TipDxc(K) ) = DOT_PRODUCT( rSTipPSTip, m%CoordSys%i1(K, :) ) + m%AllOuts( TipDyc(K) ) = DOT_PRODUCT( rSTipPSTip, m%CoordSys%i2(K, :) ) + m%AllOuts( TipDzc(K) ) = DOT_PRODUCT( rSTipPSTip, m%CoordSys%i3(K, :) ) + m%AllOuts( TipDxb(K) ) = DOT_PRODUCT( rSTipPSTip, m%CoordSys%j1(K, :) ) + m%AllOuts( TipDyb(K) ) = DOT_PRODUCT( rSTipPSTip, m%CoordSys%j2(K, :) ) + !JASON: USE TipNode HERE INSTEAD OF BldNodes IF YOU ALLOCATE AND DEFINE n1, n2, n3, m1, m2, AND m3 TO USE TipNode. THIS WILL REQUIRE THAT THE AERODYNAMIC AND STRUCTURAL TWISTS, AeroTwst() AND ThetaS(), BE KNOWN AT THE TIP!!! + m%AllOuts( TipALxb(K) ) = DOT_PRODUCT( LinAccES(:,p%TipNode,K), m%CoordSys%n1(K,p%BldNodes,:) ) + m%AllOuts( TipALyb(K) ) = DOT_PRODUCT( LinAccES(:,p%TipNode,K), m%CoordSys%n2(K,p%BldNodes,:) ) + m%AllOuts( TipALzb(K) ) = DOT_PRODUCT( LinAccES(:,p%TipNode,K), m%CoordSys%n3(K,p%BldNodes,:) ) + m%AllOuts( TipRDxb(K) ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,K,p%TipNode), m%CoordSys%j1(K, :) )*R2D + m%AllOuts( TipRDyb(K) ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,K,p%TipNode), m%CoordSys%j2(K, :) )*R2D + ! There is no sense computing AllOuts( TipRDzc(K) ) here since it is always zero for FAST simulation results. + IF ( rOSTipzn > 0.0 ) THEN ! Tip of blade K is above the yaw bearing. + m%AllOuts(TipClrnc(K) ) = SQRT( rOSTipxn*rOSTipxn + rOSTipyn*rOSTipyn + rOSTipzn*rOSTipzn ) ! Absolute distance from the tower top / yaw bearing to the tip of blade 1. + ELSE ! Tip of blade K is below the yaw bearing. + m%AllOuts(TipClrnc(K) ) = SQRT( rOSTipxn*rOSTipxn + rOSTipyn*rOSTipyn ) ! Perpendicular distance from the yaw axis / tower centerline to the tip of blade 1. + ENDIF + END IF + + END DO !K + + ! Blade (1-3) Local Span Motions: + + DO K = 1,p%NumBl + DO I = 1, p%NBlGages + + m%AllOuts( SpnALxb(I,K) ) = DOT_PRODUCT( LinAccES(:,p%BldGagNd(I),K), m%CoordSys%n1(K,p%BldGagNd(I),:) ) + m%AllOuts( SpnALyb(I,K) ) = DOT_PRODUCT( LinAccES(:,p%BldGagNd(I),K), m%CoordSys%n2(K,p%BldGagNd(I),:) ) + m%AllOuts( SpnALzb(I,K) ) = DOT_PRODUCT( LinAccES(:,p%BldGagNd(I),K), m%CoordSys%n3(K,p%BldGagNd(I),:) ) + + rSPS = m%RtHS%rS0S(:,K,p%BldGagNd(I)) - p%RNodes(p%BldGagNd(I))*m%CoordSys%j3(K,:) + + m%AllOuts( SpnTDxb(I,K) ) = DOT_PRODUCT( rSPS, m%CoordSys%j1(K,:) ) + m%AllOuts( SpnTDyb(I,K) ) = DOT_PRODUCT( rSPS, m%CoordSys%j2(K,:) ) + m%AllOuts( SpnTDzb(I,K) ) = DOT_PRODUCT( rSPS, m%CoordSys%j3(K,:) ) + + m%AllOuts( SpnRDxb(I,K) ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,K,p%BldGagNd(I)), m%CoordSys%j1(K,:) )*R2D + m%AllOuts( SpnRDyb(I,K) ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,K,p%BldGagNd(I)), m%CoordSys%j2(K,:) )*R2D + !m%AllOuts( SpnRDzb(I,K) ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,K,p%BldGagNd(I)), m%CoordSys%j3(K,:) )*R2D ! this is always zero for FAST + + END DO !I + END DO !K + + + + ! Blade Pitch Motions: + + m%AllOuts(PtchPMzc1) = u%BlPitchCom(1)*R2D +IF ( p%NumBl > 1 ) THEN + m%AllOuts(PtchPMzc2) = u%BlPitchCom(2)*R2D + IF ( p%NumBl > 2 ) THEN ! 3-blader + + m%AllOuts(PtchPMzc3) = u%BlPitchCom(3)*R2D + + ELSE ! 2-blader + + + ! Teeter Motions: + + m%AllOuts( TeetPya) = x%QT (DOF_Teet)*R2D + m%AllOuts( TeetVya) = x%QDT (DOF_Teet)*R2D + m%AllOuts( TeetAya) = m%QD2T(DOF_Teet)*R2D + + ENDIF +END IF + + ! Shaft Motions: + + y%LSSTipPxa = x%QT (DOF_GeAz) + x%QT (DOF_DrTr) + p%AzimB1Up + PiBy2 + if (.not. m%IgnoreMod) CALL Zero2TwoPi(y%LSSTipPxa) ! Return value between 0 and 2pi (LSSTipPxa is used only in calculations of SIN and COS, so it's okay to take MOD/MODULO here; this wouldn't be oaky for linearization) + m%AllOuts(LSSTipPxa) = y%LSSTipPxa*R2D + + m%AllOuts(LSSGagPxa) = x%QT (DOF_GeAz) + p%AzimB1Up + PiBy2 + if (.not. m%IgnoreMod) CALL Zero2TwoPi(m%AllOuts(LSSGagPxa)) ! Return value between 0 and 2pi + m%AllOuts(LSSGagPxa) = m%AllOuts(LSSGagPxa)*R2D ! convert to degrees + + m%AllOuts( LSSTipVxa) = ( x%QDT (DOF_GeAz) + x%QDT (DOF_DrTr) )*RPS2RPM + m%AllOuts( LSSTipAxa) = ( m%QD2T(DOF_GeAz) + m%QD2T(DOF_DrTr) )*R2D + m%AllOuts( LSSGagVxa) = x%QDT (DOF_GeAz) *RPS2RPM + m%AllOuts( LSSGagAxa) = m%QD2T(DOF_GeAz) *R2D + m%AllOuts( HSShftV) = ABS(p%GBRatio)*m%AllOuts(LSSGagVxa) + m%AllOuts( HSShftA) = ABS(p%GBRatio)*m%AllOuts(LSSGagAxa) + + !IF ( .NOT. EqualRealNos( m%AllOuts(WindVxi), 0.0_ReKi ) ) THEN ! .TRUE. if the denominator in the following equation is not zero. + ! m%AllOuts(TipSpdRat) = ( x%QDT (DOF_GeAz) + x%QDT (DOF_DrTr) )*p%AvgNrmTpRd / m%AllOuts( WindVxi) + !ELSE + ! m%AllOuts(TipSpdRat) = 0.0 + !ENDIF + + + ! Nacelle IMU Motions: + + m%AllOuts(NcIMUTVxs) = DOT_PRODUCT( m%RtHS%LinVelEIMU, m%CoordSys%c1 ) + m%AllOuts(NcIMUTVys) = -1.0*DOT_PRODUCT( m%RtHS%LinVelEIMU, m%CoordSys%c3 ) + m%AllOuts(NcIMUTVzs) = DOT_PRODUCT( m%RtHS%LinVelEIMU, m%CoordSys%c2 ) + m%AllOuts(NcIMUTAxs) = DOT_PRODUCT( LinAccEIMU, m%CoordSys%c1 ) + m%AllOuts(NcIMUTAys) = -1.0*DOT_PRODUCT( LinAccEIMU, m%CoordSys%c3 ) + m%AllOuts(NcIMUTAzs) = DOT_PRODUCT( LinAccEIMU, m%CoordSys%c2 ) + m%AllOuts(NcIMURVxs) = DOT_PRODUCT( m%RtHS%AngVelER , m%CoordSys%c1 )*R2D + m%AllOuts(NcIMURVys) = -1.0*DOT_PRODUCT( m%RtHS%AngVelER , m%CoordSys%c3 )*R2D + m%AllOuts(NcIMURVzs) = DOT_PRODUCT( m%RtHS%AngVelER , m%CoordSys%c2 )*R2D + m%AllOuts(NcIMURAxs) = DOT_PRODUCT( AngAccER , m%CoordSys%c1 )*R2D + m%AllOuts(NcIMURAys) = -1.0*DOT_PRODUCT( AngAccER , m%CoordSys%c3 )*R2D + m%AllOuts(NcIMURAzs) = DOT_PRODUCT( AngAccER , m%CoordSys%c2 )*R2D + + + ! Rotor-Furl Motions: + + m%AllOuts( RotFurlP) = x%QT (DOF_RFrl)*R2D + m%AllOuts( RotFurlV) = x%QDT (DOF_RFrl)*R2D + m%AllOuts( RotFurlA) = m%QD2T(DOF_RFrl)*R2D + + + ! Tail-Furl Motions: + + m%AllOuts(TailFurlP) = x%QT (DOF_TFrl)*R2D + m%AllOuts(TailFurlV) = x%QDT (DOF_TFrl)*R2D + m%AllOuts(TailFurlA) = m%QD2T(DOF_TFrl)*R2D + + + ! Yaw Motions: + + m%AllOuts( YawPzn) = x%QT (DOF_Yaw )*R2D + m%AllOuts( YawVzn) = x%QDT (DOF_Yaw )*R2D + m%AllOuts( YawAzn) = m%QD2T(DOF_Yaw )*R2D + + + ! Tower-Top / Yaw Bearing Motions: + + rOPO = m%RtHS%rT0O - p%TwrFlexL*m%CoordSys%a2 ! Position vector from the undeflected tower top (point O prime) to the deflected tower top (point O). + + ! p%TwrNodes+1 is the tower top: + J = p%TwrNodes+1 + m%AllOuts(TwrTpTDxi) = m%RtHS%rO(1) - y%TowerLn2Mesh%Position(1,J) + m%AllOuts(TwrTpTDyi) = -1.*m%RtHS%rO(3) - y%TowerLn2Mesh%Position(2,J) + m%AllOuts(TwrTpTDzi) = m%RtHS%rO(2) - y%TowerLn2Mesh%Position(3,J) + p%PtfmRefzt + m%AllOuts(YawBrTDxp) = DOT_PRODUCT( rOPO, m%CoordSys%b1 ) + m%AllOuts(YawBrTDyp) = -DOT_PRODUCT( rOPO, m%CoordSys%b3 ) + m%AllOuts(YawBrTDzp) = DOT_PRODUCT( rOPO, m%CoordSys%b2 ) + m%AllOuts(YawBrTDxt) = DOT_PRODUCT( rOPO, m%CoordSys%a1 ) + m%AllOuts(YawBrTDyt) = -DOT_PRODUCT( rOPO, m%CoordSys%a3 ) + m%AllOuts(YawBrTDzt) = DOT_PRODUCT( rOPO, m%CoordSys%a2 ) + m%AllOuts(YawBrTAxp) = DOT_PRODUCT( LinAccEO, m%CoordSys%b1 ) + m%AllOuts(YawBrTAyp) = -DOT_PRODUCT( LinAccEO, m%CoordSys%b3 ) + m%AllOuts(YawBrTAzp) = DOT_PRODUCT( LinAccEO, m%CoordSys%b2 ) + m%AllOuts(YawBrRDxt) = DOT_PRODUCT( m%RtHS%AngPosXB, m%CoordSys%a1 )*R2D + m%AllOuts(YawBrRDyt) = -DOT_PRODUCT( m%RtHS%AngPosXB, m%CoordSys%a3 )*R2D + ! There is no sense computing m%AllOuts(YawBrRDzt) here since it is always zero for FAST simulation results. + m%AllOuts(YawBrRVxp) = DOT_PRODUCT( m%RtHS%AngVelEB, m%CoordSys%b1 )*R2D + m%AllOuts(YawBrRVyp) = -DOT_PRODUCT( m%RtHS%AngVelEB, m%CoordSys%b3 )*R2D + m%AllOuts(YawBrRVzp) = DOT_PRODUCT( m%RtHS%AngVelEB, m%CoordSys%b2 )*R2D + m%AllOuts(YawBrRAxp) = DOT_PRODUCT( AngAccEB, m%CoordSys%b1 )*R2D + m%AllOuts(YawBrRAyp) = -DOT_PRODUCT( AngAccEB, m%CoordSys%b3 )*R2D + m%AllOuts(YawBrRAzp) = DOT_PRODUCT( AngAccEB, m%CoordSys%b2 )*R2D + + + ! Local Tower Motions: + + DO I = 1, p%NTwGages + + m%AllOuts( TwHtALxt(I) ) = DOT_PRODUCT( LinAccET(:,p%TwrGagNd(I)), m%CoordSys%t1(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtALyt(I) ) = -1.0*DOT_PRODUCT( LinAccET(:,p%TwrGagNd(I)), m%CoordSys%t3(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtALzt(I) ) = DOT_PRODUCT( LinAccET(:,p%TwrGagNd(I)), m%CoordSys%t2(p%TwrGagNd(I),:) ) + + rTPT = m%RtHS%rT0T(:,p%TwrGagNd(I)) - p%HNodes(p%TwrGagNd(I))*m%CoordSys%a2(:) + + m%AllOuts( TwHtTDxt(I) ) = DOT_PRODUCT( rTPT, m%CoordSys%a1 ) + m%AllOuts( TwHtTDyt(I) ) = -1.0*DOT_PRODUCT( rTPT, m%CoordSys%a3 ) + m%AllOuts( TwHtTDzt(I) ) = DOT_PRODUCT( rTPT, m%CoordSys%a2 ) + + m%AllOuts( TwHtRDxt(I) ) = DOT_PRODUCT( m%RtHS%AngPosXF(:,p%TwrGagNd(I)), m%CoordSys%a1 )*R2D !why is this zero??? + m%AllOuts( TwHtRDyt(I) ) = -1.0*DOT_PRODUCT( m%RtHS%AngPosXF(:,p%TwrGagNd(I)), m%CoordSys%a3 )*R2D + ! m%AllOuts( TwHtRDzt(I) ) = DOT_PRODUCT( m%RtHS%AngPosXF(:,p%TwrGagNd(I)), m%CoordSys%a2 )*R2D !this will always be 0 in FAST, so no need to calculate + + + m%AllOuts( TwHtTPxi(I) ) = m%RtHS%rT(1,p%TwrGagNd(I)) + m%AllOuts( TwHtTPyi(I) ) = -1.0*m%RtHS%rT(3,p%TwrGagNd(I)) + m%AllOuts( TwHtTPzi(I) ) = m%RtHS%rT(2,p%TwrGagNd(I)) + p%PtfmRefzt + + m%AllOuts( TwHtRPxi(I) ) = m%RtHS%AngPosEF(1,p%TwrGagNd(I))*R2D + m%AllOuts( TwHtRPyi(I) ) = -m%RtHS%AngPosEF(3,p%TwrGagNd(I))*R2D + m%AllOuts( TwHtRPzi(I) ) = m%RtHS%AngPosEF(2,p%TwrGagNd(I))*R2D + + END DO !I + + ! Platform Motions: + + m%AllOuts( PtfmTDxt) = DOT_PRODUCT( m%RtHS%rZ, m%CoordSys%a1 ) + m%AllOuts( PtfmTDyt) = -DOT_PRODUCT( m%RtHS%rZ, m%CoordSys%a3 ) + m%AllOuts( PtfmTDzt) = DOT_PRODUCT( m%RtHS%rZ, m%CoordSys%a2 ) + m%AllOuts( PtfmTDxi) = x%QT (DOF_Sg ) + m%AllOuts( PtfmTDyi) = x%QT (DOF_Sw ) + m%AllOuts( PtfmTDzi) = x%QT (DOF_Hv ) + m%AllOuts( PtfmTVxt) = DOT_PRODUCT( m%RtHS%LinVelEZ, m%CoordSys%a1 ) + m%AllOuts( PtfmTVyt) = -DOT_PRODUCT( m%RtHS%LinVelEZ, m%CoordSys%a3 ) + m%AllOuts( PtfmTVzt) = DOT_PRODUCT( m%RtHS%LinVelEZ, m%CoordSys%a2 ) + m%AllOuts( PtfmTVxi) = x%QDT (DOF_Sg ) + m%AllOuts( PtfmTVyi) = x%QDT (DOF_Sw ) + m%AllOuts( PtfmTVzi) = x%QDT (DOF_Hv ) + m%AllOuts( PtfmTAxt) = DOT_PRODUCT( LinAccEZ, m%CoordSys%a1 ) + m%AllOuts( PtfmTAyt) = -DOT_PRODUCT( LinAccEZ, m%CoordSys%a3 ) + m%AllOuts( PtfmTAzt) = DOT_PRODUCT( LinAccEZ, m%CoordSys%a2 ) + m%AllOuts( PtfmTAxi) = m%QD2T(DOF_Sg ) + m%AllOuts( PtfmTAyi) = m%QD2T(DOF_Sw ) + m%AllOuts( PtfmTAzi) = m%QD2T(DOF_Hv ) + m%AllOuts( PtfmRDxi) = x%QT (DOF_R )*R2D + m%AllOuts( PtfmRDyi) = x%QT (DOF_P )*R2D + m%AllOuts( PtfmRDzi) = x%QT (DOF_Y )*R2D + m%AllOuts( PtfmRVxt) = DOT_PRODUCT( m%RtHS%AngVelEX, m%CoordSys%a1 )*R2D + m%AllOuts( PtfmRVyt) = -DOT_PRODUCT( m%RtHS%AngVelEX, m%CoordSys%a3 )*R2D + m%AllOuts( PtfmRVzt) = DOT_PRODUCT( m%RtHS%AngVelEX, m%CoordSys%a2 )*R2D + m%AllOuts( PtfmRVxi) = x%QDT (DOF_R )*R2D + m%AllOuts( PtfmRVyi) = x%QDT (DOF_P )*R2D + m%AllOuts( PtfmRVzi) = x%QDT (DOF_Y )*R2D + m%AllOuts( PtfmRAxt) = DOT_PRODUCT( AngAccEX, m%CoordSys%a1 )*R2D + m%AllOuts( PtfmRAyt) = -DOT_PRODUCT( AngAccEX, m%CoordSys%a3 )*R2D + m%AllOuts( PtfmRAzt) = DOT_PRODUCT( AngAccEX, m%CoordSys%a2 )*R2D + m%AllOuts( PtfmRAxi) = m%QD2T(DOF_R )*R2D + m%AllOuts( PtfmRAyi) = m%QD2T(DOF_P )*R2D + m%AllOuts( PtfmRAzi) = m%QD2T(DOF_Y )*R2D + + + + ! Blade Root Loads: + + DO K=1,p%NumBl + m%AllOuts( RootFxc(K) ) = DOT_PRODUCT( FrcS0B(:,K), m%CoordSys%i1(K,:) ) + m%AllOuts( RootFyc(K) ) = DOT_PRODUCT( FrcS0B(:,K), m%CoordSys%i2(K,:) ) + m%AllOuts( RootFzc(K) ) = DOT_PRODUCT( FrcS0B(:,K), m%CoordSys%i3(K,:) ) + m%AllOuts( RootFxb(K) ) = DOT_PRODUCT( FrcS0B(:,K), m%CoordSys%j1(K,:) ) + m%AllOuts( RootFyb(K) ) = DOT_PRODUCT( FrcS0B(:,K), m%CoordSys%j2(K,:) ) + m%AllOuts( RootMxc(K) ) = DOT_PRODUCT( MomH0B(:,K), m%CoordSys%i1(K,:) ) + m%AllOuts( RootMyc(K) ) = DOT_PRODUCT( MomH0B(:,K), m%CoordSys%i2(K,:) ) + m%AllOuts( RootMzc(K) ) = DOT_PRODUCT( MomH0B(:,K), m%CoordSys%i3(K,:) ) + m%AllOuts( RootMxb(K) ) = DOT_PRODUCT( MomH0B(:,K), m%CoordSys%j1(K,:) ) + m%AllOuts( RootMyb(K) ) = DOT_PRODUCT( MomH0B(:,K), m%CoordSys%j2(K,:) ) + END DO !K + + + ! Blade Local Span Loads: + + DO K = 1,p%NumBl + DO I = 1,p%NBlGages + + ! Initialize FrcMGagB and MomMGagB using the tip brake effects: + + FrcMGagB = m%RtHS%FSTipDrag(:,K) - p%TipMass(K)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,p%TipNode,K) ) + MomMGagB = CROSS_PRODUCT( m%RtHS%rS0S(:,K,p%TipNode) - m%RtHS%rS0S(:,K,p%BldGagNd(I)), FrcMGagB ) + + ! Integrate to find FrcMGagB and MomMGagB using all of the nodes / elements above the current strain gage location: + DO J = ( p%BldGagNd(I) + 1 ),p%BldNodes ! Loop through blade nodes / elements above strain gage node + + TmpVec2 = m%RtHS%FSAero(:,K,J) - p%MassB(K,J)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,J,K) ) ! Portion of FrcMGagB associated with element J + FrcMGagB = FrcMGagB + TmpVec2*p%DRNodes(J) + + TmpVec = CROSS_PRODUCT( m%RtHS%rS0S(:,K,J) - m%RtHS%rS0S(:,K,p%BldGagNd(I)), TmpVec2 ) ! Portion of MomMGagB associated with element J + MomMGagB = MomMGagB + ( TmpVec + m%RtHS%MMAero(:,K,J) )*p%DRNodes(J) + + ENDDO ! J - Blade nodes / elements above strain gage node + + ! Add the effects of 1/2 the strain gage element: + ! NOTE: for the radius in this calculation, assume that there is no + ! shortening effect (due to blade bending) within the element. Thus, + ! the moment arm for the force is 1/4 of p%DRNodes() and the element + ! length is 1/2 of p%DRNodes(). + + TmpVec2 = m%RtHS%FSAero(:,K,p%BldGagNd(I)) - p%MassB(K,p%BldGagNd(I))* ( p%Gravity*m%CoordSys%z2 + LinAccES(:,p%BldGagNd(I),K) ) ! Portion of FrcMGagB associated with 1/2 of the strain gage element + FrcMGagB = FrcMGagB + TmpVec2 * 0.5 * p%DRNodes(p%BldGagNd(I)) ! Portion of FrcMGagB associated with 1/2 of the strain gage element + FrcMGagB = 0.001*FrcMGagB ! Convert the local force to kN + + + TmpVec = CROSS_PRODUCT( ( 0.25_R8Ki*p%DRNodes(p%BldGagNd(I)) )*m%CoordSys%j3(K,:), TmpVec2 ) ! Portion of MomMGagB associated with 1/2 of the strain gage element + + MomMGagB = MomMGagB + ( TmpVec + m%RtHS%MMAero(:,K,p%BldGagNd(I)) )* ( 0.5 *p%DRNodes(p%BldGagNd(I)) ) + MomMGagB = 0.001*MomMGagB ! Convert the local moment to kN-m + + + m%AllOuts(SpnFLxb(I,K)) = DOT_PRODUCT( FrcMGagB, m%CoordSys%n1(K,p%BldGagNd(I),:) ) + m%AllOuts(SpnFLyb(I,K)) = DOT_PRODUCT( FrcMGagB, m%CoordSys%n2(K,p%BldGagNd(I),:) ) + m%AllOuts(SpnFLzb(I,K)) = DOT_PRODUCT( FrcMGagB, m%CoordSys%n3(K,p%BldGagNd(I),:) ) + + m%AllOuts(SpnMLxb(I,K)) = DOT_PRODUCT( MomMGagB, m%CoordSys%n1(K,p%BldGagNd(I),:) ) + m%AllOuts(SpnMLyb(I,K)) = DOT_PRODUCT( MomMGagB, m%CoordSys%n2(K,p%BldGagNd(I),:) ) + m%AllOuts(SpnMLzb(I,K)) = DOT_PRODUCT( MomMGagB, m%CoordSys%n3(K,p%BldGagNd(I),:) ) + END DO ! I + END DO ! K + + + + ! Hub and Rotor Loads: + + !ComDenom = 0.5*p%AirDens*p%ProjArea*m%AllOuts( WindVxi)*m%AllOuts( WindVxi) ! Common denominator used in several expressions + + m%AllOuts(LSShftFxa) = DOT_PRODUCT( FrcPRot, m%CoordSys%e1 ) + m%AllOuts(LSShftFya) = DOT_PRODUCT( FrcPRot, m%CoordSys%e2 ) + m%AllOuts(LSShftFza) = DOT_PRODUCT( FrcPRot, m%CoordSys%e3 ) + m%AllOuts(LSShftFys) = -DOT_PRODUCT( FrcPRot, m%CoordSys%c3 ) + m%AllOuts(LSShftFzs) = DOT_PRODUCT( FrcPRot, m%CoordSys%c2 ) + m%AllOuts(LSShftMxa) = DOT_PRODUCT( MomLPRot, m%CoordSys%e1 ) + m%AllOuts(LSSTipMya) = DOT_PRODUCT( MomLPRot, m%CoordSys%e2 ) + m%AllOuts(LSSTipMza) = DOT_PRODUCT( MomLPRot, m%CoordSys%e3 ) + m%AllOuts(LSSTipMys) = -DOT_PRODUCT( MomLPRot, m%CoordSys%c3 ) + m%AllOuts(LSSTipMzs) = DOT_PRODUCT( MomLPRot, m%CoordSys%c2 ) + +! IF ( .NOT. EqualRealNos( m%AllOuts(LSShftFxa), 0.0_ReKi ) ) THEN ! .TRUE. if the denominator in the following equations is not zero. +! +! CThrstys = -m%AllOuts(LSSTipMzs)/m%AllOuts(LSShftFxa) ! Estimate of the ys-location of the center of thrust +! CThrstzs = m%AllOuts(LSSTipMys)/m%AllOuts(LSShftFxa) ! Estimate of the zs-location of the center of thrust +! +!! m%AllOuts(CThrstAzm) = MOD( ( ATAN2( -CThrstzs, -CThrstys ) + p%AzimB1Up )*R2D + 360.0 + 90.0, 360.0 ) !bjj: IgnoreMod was used for linearization... perhaps these outputs should not use the MOD function; only WriteOutputs should have that... +!! m%AllOuts(CThrstRad) = MIN( 1.0, SQRT( CThrstys*CThrstys + CThrstzs*CThrstzs )/p%AvgNrmTpRd ) +! +! ELSE +! +! !m%AllOuts(CThrstAzm) = 0.0 +! !m%AllOuts(CThrstRad) = 0.0 +! +! ENDIF + + m%AllOuts( RotPwr) = ( x%QDT(DOF_GeAz) + x%QDT(DOF_DrTr) )*m%AllOuts(LSShftMxa) + + !IF ( .NOT. EqualRealNos( ComDenom, 0.0_ReKi ) ) THEN ! .TRUE. if the denominator in the following equations is not zero. + ! + ! m%AllOuts( RotCq) = 1000.0*m%AllOuts(LSShftMxa) / ( ComDenom*p%TipRad ) + ! m%AllOuts( RotCp) = 1000.0*m%AllOuts( RotPwr) / ( ComDenom*m%AllOuts( WindVxi) ) + ! m%AllOuts( RotCt) = 1000.0*m%AllOuts(LSShftFxa) / ComDenom + ! + !ELSE + ! + ! m%AllOuts( RotCq) = 0.0 + ! m%AllOuts( RotCp) = 0.0 + ! m%AllOuts( RotCt) = 0.0 + ! + !ENDIF + + + ! Shaft Strain Gage Loads: + + m%AllOuts(LSSGagMya) = m%AllOuts(LSSTipMya) + p%ShftGagL*m%AllOuts(LSShftFza) + m%AllOuts(LSSGagMza) = m%AllOuts(LSSTipMza) - p%ShftGagL*m%AllOuts(LSShftFya) + m%AllOuts(LSSGagMys) = m%AllOuts(LSSTipMys) + p%ShftGagL*m%AllOuts(LSShftFzs) + m%AllOuts(LSSGagMzs) = m%AllOuts(LSSTipMzs) - p%ShftGagL*m%AllOuts(LSShftFys) + + + ! Generator and High-Speed Shaft Loads: + + m%AllOuts( HSShftTq) = m%AllOuts(LSShftMxa)*m%RtHS%GBoxEffFac/ABS(p%GBRatio) + m%AllOuts(HSShftPwr) = m%AllOuts( HSShftTq)*ABS(p%GBRatio)*x%QDT(DOF_GeAz) + m%AllOuts(HSSBrTq) = OtherState%HSSBrTrq*0.001_ReKi + + + !IF ( .NOT. EqualRealNos( ComDenom, 0.0_ReKi ) ) THEN ! .TRUE. if the denominator in the following equations is not zero (ComDenom is the same as it is calculated above). + ! + ! m%AllOuts( HSShftCq) = 1000.0*m%AllOuts( HSShftTq) / ( ComDenom*p%TipRad ) + ! m%AllOuts( HSShftCp) = 1000.0*m%AllOuts(HSShftPwr) / ( ComDenom*m%AllOuts( WindVxi) ) + ! m%AllOuts( GenCq) = 1000.0*m%AllOuts( GenTq) / ( ComDenom*p%TipRad ) + ! m%AllOuts( GenCp) = 1000.0*m%AllOuts( GenPwr) / ( ComDenom*m%AllOuts( WindVxi) ) + ! + !ELSE + ! + ! m%AllOuts( HSShftCq) = 0.0 + ! m%AllOuts( HSShftCp) = 0.0 + ! m%AllOuts( GenCq) = 0.0 + ! m%AllOuts( GenCp) = 0.0 + ! + !ENDIF + + + ! Rotor-Furl Axis Loads: + + m%AllOuts(RFrlBrM ) = DOT_PRODUCT( MomNGnRt, m%CoordSys%rfa ) + + + ! Tail-Furl Axis Loads: + + m%AllOuts(TFrlBrM ) = DOT_PRODUCT( MomNTail, m%CoordSys%tfa ) + + + ! Tower-Top / Yaw Bearing Loads: + + m%AllOuts( YawBrFxn) = DOT_PRODUCT( FrcONcRt, m%CoordSys%d1 ) + m%AllOuts( YawBrFyn) = -DOT_PRODUCT( FrcONcRt, m%CoordSys%d3 ) + m%AllOuts( YawBrFzn) = DOT_PRODUCT( FrcONcRt, m%CoordSys%d2 ) + m%AllOuts( YawBrFxp) = DOT_PRODUCT( FrcONcRt, m%CoordSys%b1 ) + m%AllOuts( YawBrFyp) = -DOT_PRODUCT( FrcONcRt, m%CoordSys%b3 ) + m%AllOuts( YawBrMxn) = DOT_PRODUCT( MomBNcRt, m%CoordSys%d1 ) + m%AllOuts( YawBrMyn) = -DOT_PRODUCT( MomBNcRt, m%CoordSys%d3 ) + m%AllOuts( YawBrMzn) = DOT_PRODUCT( MomBNcRt, m%CoordSys%d2 ) + m%AllOuts( YawBrMxp) = DOT_PRODUCT( MomBNcRt, m%CoordSys%b1 ) + m%AllOuts( YawBrMyp) = -DOT_PRODUCT( MomBNcRt, m%CoordSys%b3 ) + + + ! Tower Base Loads: + + m%AllOuts( TwrBsFxt) = DOT_PRODUCT( FrcT0Trb, m%CoordSys%a1 ) + m%AllOuts( TwrBsFyt) = -DOT_PRODUCT( FrcT0Trb, m%CoordSys%a3 ) + m%AllOuts( TwrBsFzt) = DOT_PRODUCT( FrcT0Trb, m%CoordSys%a2 ) + m%AllOuts( TwrBsMxt) = DOT_PRODUCT( MomX0Trb, m%CoordSys%a1 ) + m%AllOuts( TwrBsMyt) = -DOT_PRODUCT( MomX0Trb, m%CoordSys%a3 ) + m%AllOuts( TwrBsMzt) = DOT_PRODUCT( MomX0Trb, m%CoordSys%a2 ) + + + ! Local Tower Loads: + + FrcONcRt = 1000.0*FrcONcRt ! Convert the units of these forces and moments + MomBNcRt = 1000.0*MomBNcRt ! from kN and kN-m back to N and N-m, respectively. + + DO I=1,p%NTwGages + + ! Initialize FrcFGagT and MomFGagT using the tower-top and yaw bearing mass effects: + FrcFGagT = FrcONcRt - p%YawBrMass*( p%Gravity*m%CoordSys%z2 + LinAccEO ) + MomFGagT = CROSS_PRODUCT( m%RtHS%rZO - m%RtHS%rZT(:,p%TwrGagNd(I)), FrcFGagT ) + MomFGagT = MomFGagT + MomBNcRt + + ! Integrate to find FrcFGagT and MomFGagT using all of the nodes / elements above the current strain gage location: + DO J = ( p%TwrGagNd(I) + 1 ),p%TwrNodes ! Loop through tower nodes / elements above strain gage node + TmpVec2 = FTTower(:,J) - p%MassT(J)*( p%Gravity*m%CoordSys%z2 + LinAccET(:,J) ) ! Portion of FrcFGagT associated with element J + FrcFGagT = FrcFGagT + TmpVec2*p%DHNodes(J) + + TmpVec = CROSS_PRODUCT( m%RtHS%rZT(:,J) - m%RtHS%rZT(:,p%TwrGagNd(I)), TmpVec2 ) ! Portion of MomFGagT associated with element J + MomFGagT = MomFGagT + ( TmpVec + MFHydro(:,J) )*p%DHNodes(J) + ENDDO ! J -Tower nodes / elements above strain gage node + + ! Add the effects of 1/2 the strain gage element: + ! NOTE: for the radius in this calculation, assume that there is no shortening + ! effect (due to tower bending) within the element. Thus, the moment arm + ! for the force is 1/4 of DHNodes() and the element length is 1/2 of DHNodes(). + + TmpVec2 = FTTower(:,p%TwrGagNd(I)) - p%MassT(p%TwrGagNd(I))*( p%Gravity*m%CoordSys%z2 + LinAccET(:,p%TwrGagNd(I))) + + FrcFGagT = FrcFGagT + TmpVec2 * 0.5 * p%DHNodes(p%TwrGagNd(I)) + FrcFGagT = 0.001*FrcFGagT ! Convert the local force to kN + + TmpVec = CROSS_PRODUCT( ( 0.25_R8Ki*p%DHNodes( p%TwrGagNd(I)) )*m%CoordSys%a2, TmpVec2 ) ! Portion of MomFGagT associated with 1/2 of the strain gage element + TmpVec = TmpVec + MFHydro(:,p%TwrGagNd(I)) + MomFGagT = MomFGagT + TmpVec * 0.5 * p%DHNodes(p%TwrGagNd(I)) + MomFGagT = 0.001*MomFGagT ! Convert the local moment to kN-m + + m%AllOuts( TwHtFLxt(I) ) = DOT_PRODUCT( FrcFGagT, m%CoordSys%t1(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtFLyt(I) ) = -1.*DOT_PRODUCT( FrcFGagT, m%CoordSys%t3(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtFLzt(I) ) = DOT_PRODUCT( FrcFGagT, m%CoordSys%t2(p%TwrGagNd(I),:) ) + + m%AllOuts( TwHtMLxt(I) ) = DOT_PRODUCT( MomFGagT, m%CoordSys%t1(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtMLyt(I) ) = -1.*DOT_PRODUCT( MomFGagT, m%CoordSys%t3(p%TwrGagNd(I),:) ) + m%AllOuts( TwHtMLzt(I) ) = DOT_PRODUCT( MomFGagT, m%CoordSys%t2(p%TwrGagNd(I),:) ) + + END DO + + + ! ! Platform Loads: + ! + !m%AllOuts( PtfmFxt) = DOT_PRODUCT( FZHydro, m%CoordSys%a1 ) + !m%AllOuts( PtfmFyt) = -DOT_PRODUCT( FZHydro, m%CoordSys%a3 ) + !m%AllOuts( PtfmFzt) = DOT_PRODUCT( FZHydro, m%CoordSys%a2 ) + !m%AllOuts( PtfmFxi) = DOT_PRODUCT( FZHydro, m%CoordSys%z1 ) + !m%AllOuts( PtfmFyi) = -DOT_PRODUCT( FZHydro, m%CoordSys%z3 ) + !m%AllOuts( PtfmFzi) = DOT_PRODUCT( FZHydro, m%CoordSys%z2 ) + !m%AllOuts( PtfmMxt) = DOT_PRODUCT( MXHydro, m%CoordSys%a1 ) + !m%AllOuts( PtfmMyt) = -DOT_PRODUCT( MXHydro, m%CoordSys%a3 ) + !m%AllOuts( PtfmMzt) = DOT_PRODUCT( MXHydro, m%CoordSys%a2 ) + !m%AllOuts( PtfmMxi) = DOT_PRODUCT( MXHydro, m%CoordSys%z1 ) + !m%AllOuts( PtfmMyi) = -DOT_PRODUCT( MXHydro, m%CoordSys%z3 ) + !m%AllOuts( PtfmMzi) = DOT_PRODUCT( MXHydro, m%CoordSys%z2 ) + ! + + ! Internal p%DOFs outputs: + + m%AllOuts( Q_B1E1 ) = x%QT( DOF_BE(1,1) ) + m%AllOuts( Q_B1F1 ) = x%QT( DOF_BF(1,1) ) + m%AllOuts( Q_B1F2 ) = x%QT( DOF_BF(1,2) ) + m%AllOuts( Q_DrTr ) = x%QT( DOF_DrTr ) + m%AllOuts( Q_GeAz ) = x%QT( DOF_GeAz ) + m%AllOuts( Q_RFrl ) = x%QT( DOF_RFrl ) + m%AllOuts( Q_TFrl ) = x%QT( DOF_TFrl ) + m%AllOuts( Q_Yaw ) = x%QT( DOF_Yaw ) + m%AllOuts( Q_TFA1 ) = x%QT( DOF_TFA1 ) + m%AllOuts( Q_TSS1 ) = x%QT( DOF_TSS1 ) + m%AllOuts( Q_TFA2 ) = x%QT( DOF_TFA2 ) + m%AllOuts( Q_TSS2 ) = x%QT( DOF_TSS2 ) + m%AllOuts( Q_Sg ) = x%QT( DOF_Sg ) + m%AllOuts( Q_Sw ) = x%QT( DOF_Sw ) + m%AllOuts( Q_Hv ) = x%QT( DOF_Hv ) + m%AllOuts( Q_R ) = x%QT( DOF_R ) + m%AllOuts( Q_P ) = x%QT( DOF_P ) + m%AllOuts( Q_Y ) = x%QT( DOF_Y ) + + m%AllOuts( QD_B1E1 ) = x%QDT( DOF_BE(1,1) ) + m%AllOuts( QD_B1F1 ) = x%QDT( DOF_BF(1,1) ) + m%AllOuts( QD_B1F2 ) = x%QDT( DOF_BF(1,2) ) + m%AllOuts( QD_DrTr ) = x%QDT( DOF_DrTr ) + m%AllOuts( QD_GeAz ) = x%QDT( DOF_GeAz ) + m%AllOuts( QD_RFrl ) = x%QDT( DOF_RFrl ) + m%AllOuts( QD_TFrl ) = x%QDT( DOF_TFrl ) + m%AllOuts( QD_Yaw ) = x%QDT( DOF_Yaw ) + m%AllOuts( QD_TFA1 ) = x%QDT( DOF_TFA1 ) + m%AllOuts( QD_TSS1 ) = x%QDT( DOF_TSS1 ) + m%AllOuts( QD_TFA2 ) = x%QDT( DOF_TFA2 ) + m%AllOuts( QD_TSS2 ) = x%QDT( DOF_TSS2 ) + m%AllOuts( QD_Sg ) = x%QDT( DOF_Sg ) + m%AllOuts( QD_Sw ) = x%QDT( DOF_Sw ) + m%AllOuts( QD_Hv ) = x%QDT( DOF_Hv ) + m%AllOuts( QD_R ) = x%QDT( DOF_R ) + m%AllOuts( QD_P ) = x%QDT( DOF_P ) + m%AllOuts( QD_Y ) = x%QDT( DOF_Y ) + + m%AllOuts( QD2_B1E1 ) = m%QD2T( DOF_BE(1,1) ) + m%AllOuts( QD2_B2E1 ) = m%QD2T( DOF_BE(2,1) ) + m%AllOuts( QD2_B1F1 ) = m%QD2T( DOF_BF(1,1) ) + m%AllOuts( QD2_B2F1 ) = m%QD2T( DOF_BF(2,1) ) + m%AllOuts( QD2_B1F2 ) = m%QD2T( DOF_BF(1,2) ) + m%AllOuts( QD2_B2F2 ) = m%QD2T( DOF_BF(2,2) ) + m%AllOuts( QD2_DrTr ) = m%QD2T( DOF_DrTr ) + m%AllOuts( QD2_GeAz ) = m%QD2T( DOF_GeAz ) + m%AllOuts( QD2_RFrl ) = m%QD2T( DOF_RFrl ) + m%AllOuts( QD2_TFrl ) = m%QD2T( DOF_TFrl ) + m%AllOuts( QD2_Yaw ) = m%QD2T( DOF_Yaw ) + m%AllOuts( QD2_TFA1 ) = m%QD2T( DOF_TFA1 ) + m%AllOuts( QD2_TSS1 ) = m%QD2T( DOF_TSS1 ) + m%AllOuts( QD2_TFA2 ) = m%QD2T( DOF_TFA2 ) + m%AllOuts( QD2_TSS2 ) = m%QD2T( DOF_TSS2 ) + m%AllOuts( QD2_Sg ) = m%QD2T( DOF_Sg ) + m%AllOuts( QD2_Sw ) = m%QD2T( DOF_Sw ) + m%AllOuts( QD2_Hv ) = m%QD2T( DOF_Hv ) + m%AllOuts( QD2_R ) = m%QD2T( DOF_R ) + m%AllOuts( QD2_P ) = m%QD2T( DOF_P ) + m%AllOuts( QD2_Y ) = m%QD2T( DOF_Y ) + +IF ( p%NumBl > 1 ) THEN + + m%AllOuts( Q_B2E1 ) = x%QT( DOF_BE(2,1) ) + m%AllOuts( Q_B2F1 ) = x%QT( DOF_BF(2,1) ) + m%AllOuts( Q_B2F2 ) = x%QT( DOF_BF(2,2) ) + + m%AllOuts( QD_B2E1 ) = x%QDT( DOF_BE(2,1) ) + m%AllOuts( QD_B2F1 ) = x%QDT( DOF_BF(2,1) ) + m%AllOuts( QD_B2F2 ) = x%QDT( DOF_BF(2,2) ) + + IF ( p%NumBl > 2 ) THEN + m%AllOuts( Q_B3E1 ) = x%QT( DOF_BE(3,1) ) + m%AllOuts( Q_B3F1 ) = x%QT( DOF_BF(3,1) ) + m%AllOuts( Q_B3F2 ) = x%QT( DOF_BF(3,2) ) + + m%AllOuts( QD_B3E1 ) = x%QDT( DOF_BE(3,1) ) + m%AllOuts( QD_B3F1 ) = x%QDT( DOF_BF(3,1) ) + m%AllOuts( QD_B3F2 ) = x%QDT( DOF_BF(3,2) ) + + m%AllOuts( QD2_B3E1 ) = m%QD2T( DOF_BE(3,1) ) + m%AllOuts( QD2_B3F1 ) = m%QD2T( DOF_BF(3,1) ) + m%AllOuts( QD2_B3F2 ) = m%QD2T( DOF_BF(3,2) ) + ELSE + m%AllOuts( Q_Teet ) = x%QT( DOF_Teet ) + m%AllOuts( QD_Teet ) = x%QDT( DOF_Teet ) + m%AllOuts( QD2_Teet ) = m%QD2T( DOF_Teet ) + END IF + +END IF + + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) array with the proper sign: + !............................................................................................................................... + + DO I = 1,p%NumOuts ! Loop through all selected output channels + + y%WriteOutput(I) = p%OutParam(I)%SignM * m%AllOuts( p%OutParam(I)%Indx ) + + ENDDO ! I - All selected output channels + + IF ( .NOT. p%BD4Blades ) THEN + y%WriteOutput(p%NumOuts+1:) = 0.0_ReKi + + ! Now we need to populate the blade node outputs here + call Calc_WriteAllBldNdOutput( p, u, m, y, LinAccES, ErrStat2, ErrMsg2 ) ! Call after normal writeoutput. Will just postpend data on here. + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ED_CalcOutput') + ENDIF + + + !............................................................................................................................... + ! Outputs required for AeroDyn + !............................................................................................................................... + + !JASON: WE SHOULD REALLY BE PASSING TO AERODYN THE LINEAR VELOCITIES OF THE AERODYNAMIC CENTER IN THE INERTIA FRAME, NOT SIMPLY THE LINEAR VELOCITIES OF POINT S. + ! IS THERE ANY WAY OF GETTING THIS VELOCITY?<--DO THIS, WHEN YOU ADD THE COUPLED MODE SHAPES!!!! + + !........... + ! Blade elements: + !........... + IF ( ALLOCATED(y%BladeLn2Mesh) ) THEN + DO K = 1,p%NumBl ! Loop through all blades + DO J = 0,p%TipNode ! Loop through the blade nodes / elements + + J2 = J + if (j==0) then + ! blade root + NodeNum = p%BldNodes + 2 + if (p%UseAD14) j2 = 1 + elseif (j==p%TipNode) then + ! blade tip + NodeNum = p%BldNodes + 1 + if (p%UseAD14) j2 = p%BldNodes + else + NodeNum = J + end if + + if (p%UseAD14) then + ! Translational Displacement (first calculate absolute position) + y%BladeLn2Mesh(K)%TranslationDisp(1,NodeNum) = m%RtHS%rS (1,K,J2) + m%RtHS%rSAerCen(1,J2,K) ! = the distance from the undeflected tower centerline to the current blade aerodynamic center in the xi ( z1) direction + y%BladeLn2Mesh(K)%TranslationDisp(2,NodeNum) = -1.*m%RtHS%rS (3,K,J2) - m%RtHS%rSAerCen(3,J2,K) ! = the distance from the undeflected tower centerline to the current blade aerodynamic center in the yi (-z3) direction + y%BladeLn2Mesh(K)%TranslationDisp(3,NodeNum) = m%RtHS%rS (2,K,J2) + m%RtHS%rSAerCen(2,J2,K) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade aerodynamic center in the zi ( z2) direction + + ! Orientation + y%BladeLn2Mesh(K)%Orientation(1,1,NodeNum) = m%CoordSys%te1(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(2,1,NodeNum) = m%CoordSys%te2(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(3,1,NodeNum) = m%CoordSys%te3(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(1,2,NodeNum) = -1.*m%CoordSys%te1(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(2,2,NodeNum) = -1.*m%CoordSys%te2(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(3,2,NodeNum) = -1.*m%CoordSys%te3(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(1,3,NodeNum) = m%CoordSys%te1(K,J2,2) + y%BladeLn2Mesh(K)%Orientation(2,3,NodeNum) = m%CoordSys%te2(K,J2,2) + y%BladeLn2Mesh(K)%Orientation(3,3,NodeNum) = m%CoordSys%te3(K,J2,2) + + else + ! Translational Displacement (first calculate absolute position) + y%BladeLn2Mesh(K)%TranslationDisp(1,NodeNum) = m%RtHS%rS (1,K,J2) ! = the distance from the undeflected tower centerline to the current blade node in the xi ( z1) direction + y%BladeLn2Mesh(K)%TranslationDisp(2,NodeNum) = -1.*m%RtHS%rS (3,K,J2) ! = the distance from the undeflected tower centerline to the current blade node in the yi (-z3) direction + y%BladeLn2Mesh(K)%TranslationDisp(3,NodeNum) = m%RtHS%rS (2,K,J2) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade node in the zi ( z2) direction + + ! Orientation + y%BladeLn2Mesh(K)%Orientation(1,1,NodeNum) = m%CoordSys%n1(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(2,1,NodeNum) = m%CoordSys%n2(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(3,1,NodeNum) = m%CoordSys%n3(K,J2,1) + y%BladeLn2Mesh(K)%Orientation(1,2,NodeNum) = -1.*m%CoordSys%n1(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(2,2,NodeNum) = -1.*m%CoordSys%n2(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(3,2,NodeNum) = -1.*m%CoordSys%n3(K,J2,3) + y%BladeLn2Mesh(K)%Orientation(1,3,NodeNum) = m%CoordSys%n1(K,J2,2) + y%BladeLn2Mesh(K)%Orientation(2,3,NodeNum) = m%CoordSys%n2(K,J2,2) + y%BladeLn2Mesh(K)%Orientation(3,3,NodeNum) = m%CoordSys%n3(K,J2,2) + end if + + ! Translational Displacement (get displacement, not absolute position): + y%BladeLn2Mesh(K)%TranslationDisp(:,NodeNum) = y%BladeLn2Mesh(K)%TranslationDisp(:,NodeNum) - y%BladeLn2Mesh(K)%Position(:,NodeNum) + + ! Translational Velocity + y%BladeLn2Mesh(K)%TranslationVel(1,NodeNum) = m%RtHS%LinVelES(1,J2,K) + y%BladeLn2Mesh(K)%TranslationVel(2,NodeNum) = -1.*m%RtHS%LinVelES(3,J2,K) + y%BladeLn2Mesh(K)%TranslationVel(3,NodeNum) = m%RtHS%LinVelES(2,J2,K) + + ! Rotational Velocity + y%BladeLn2Mesh(K)%RotationVel(1,NodeNum) = m%RtHS%AngVelEM(1,J2,K) + y%BladeLn2Mesh(K)%RotationVel(2,NodeNum) = -1.*m%RtHS%AngVelEM(3,J2,K) + y%BladeLn2Mesh(K)%RotationVel(3,NodeNum) = m%RtHS%AngVelEM(2,J2,K) + + ! Translational Acceleration + y%BladeLn2Mesh(K)%TranslationAcc(1,NodeNum) = LinAccES(1,J2,K) + y%BladeLn2Mesh(K)%TranslationAcc(2,NodeNum) = -1.*LinAccES(3,J2,K) + y%BladeLn2Mesh(K)%TranslationAcc(3,NodeNum) = LinAccES(2,J2,K) + + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + + END DO !K = 1,p%NumBl + END IF + + + !........... + ! Hub (for Lidar and AeroDyn15): + !........... + + ! Translation (absolute position - starting position): + y%HubPtMotion%TranslationDisp(1,1) = m%RtHS%rQ(1) + y%HubPtMotion%TranslationDisp(2,1) = -1.*m%RtHS%rQ(3) + y%HubPtMotion%TranslationDisp(3,1) = m%RtHS%rQ(2) + p%PtfmRefzt + y%HubPtMotion%TranslationDisp = y%HubPtMotion%TranslationDisp - y%HubPtMotion%Position ! relative position + + ! Orientation: + y%HubPtMotion%Orientation(1,1,1) = m%CoordSys%g1(1) + y%HubPtMotion%Orientation(2,1,1) = m%CoordSys%g2(1) + y%HubPtMotion%Orientation(3,1,1) = m%CoordSys%g3(1) + y%HubPtMotion%Orientation(1,2,1) = -1.*m%CoordSys%g1(3) + y%HubPtMotion%Orientation(2,2,1) = -1.*m%CoordSys%g2(3) + y%HubPtMotion%Orientation(3,2,1) = -1.*m%CoordSys%g3(3) + y%HubPtMotion%Orientation(1,3,1) = m%CoordSys%g1(2) + y%HubPtMotion%Orientation(2,3,1) = m%CoordSys%g2(2) + y%HubPtMotion%Orientation(3,3,1) = m%CoordSys%g3(2) + + ! Rotational velocity: + y%HubPtMotion%RotationVel(1,1) = m%RtHS%AngVelEH(1) + y%HubPtMotion%RotationVel(2,1) = -1.*m%RtHS%AngVelEH(3) + y%HubPtMotion%RotationVel(3,1) = m%RtHS%AngVelEH(2) + + !........... + ! Blade roots (BeamDyn/AeroDyn v15): + !........... + + DO K=1,p%NumBl + + ! Translation displacement ! rS at the root + y%BladeRootMotion(K)%TranslationDisp(1,1) = m%RtHS%rS (1,K,0) ! = the distance from the undeflected tower centerline to the current blade node in the xi ( z1) direction + y%BladeRootMotion(K)%TranslationDisp(2,1) = -1.*m%RtHS%rS (3,K,0) ! = the distance from the undeflected tower centerline to the current blade node in the yi (-z3) direction + y%BladeRootMotion(K)%TranslationDisp(3,1) = m%RtHS%rS (2,K,0) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade node in the zi ( z2) direction + y%BladeRootMotion(K)%TranslationDisp = y%BladeRootMotion(K)%TranslationDisp - y%BladeRootMotion(K)%Position ! make it relative + + + ! Orientation + y%BladeRootMotion(K)%Orientation(1,1,1) = m%CoordSys%j1(K,1) + y%BladeRootMotion(K)%Orientation(2,1,1) = m%CoordSys%j2(K,1) + y%BladeRootMotion(K)%Orientation(3,1,1) = m%CoordSys%j3(K,1) + y%BladeRootMotion(K)%Orientation(1,2,1) = -1.*m%CoordSys%j1(K,3) + y%BladeRootMotion(K)%Orientation(2,2,1) = -1.*m%CoordSys%j2(K,3) + y%BladeRootMotion(K)%Orientation(3,2,1) = -1.*m%CoordSys%j3(K,3) + y%BladeRootMotion(K)%Orientation(1,3,1) = m%CoordSys%j1(K,2) + y%BladeRootMotion(K)%Orientation(2,3,1) = m%CoordSys%j2(K,2) + y%BladeRootMotion(K)%Orientation(3,3,1) = m%CoordSys%j3(K,2) + + ! Translation velocity + y%BladeRootMotion(K)%TranslationVel(1,1) = m%RtHS%LinVelES(1,0,K) + y%BladeRootMotion(K)%TranslationVel(2,1) = -1.*m%RtHS%LinVelES(3,0,K) + y%BladeRootMotion(K)%TranslationVel(3,1) = m%RtHS%LinVelES(2,0,K) + + ! Rotation velocity + y%BladeRootMotion(K)%RotationVel(1,1) = m%RtHS%AngVelEH(1) + y%BladeRootMotion(K)%RotationVel(2,1) = -1.*m%RtHS%AngVelEH(3) + y%BladeRootMotion(K)%RotationVel(3,1) = m%RtHS%AngVelEH(2) + + ! Translation acceleration + y%BladeRootMotion(K)%TranslationAcc(1,1) = LinAccES(1,0,K) + y%BladeRootMotion(K)%TranslationAcc(2,1) = -1.*LinAccES(3,0,K) + y%BladeRootMotion(K)%TranslationAcc(3,1) = LinAccES(2,0,K) + + ! Rotation acceleration + y%BladeRootMotion(K)%RotationAcc(1,1) = AngAccEH(1) + y%BladeRootMotion(K)%RotationAcc(2,1) = -1.*AngAccEH(3) + y%BladeRootMotion(K)%RotationAcc(3,1) = AngAccEH(2) + + END DO + + !........... + ! Hub (for AeroDyn v14): + !........... + + ! the hub position should use rQ instead of rP, but AeroDyn 14 treats + ! teeter deflections like blade deflections: + + y%HubPtMotion14%TranslationDisp(1,1) = m%RtHS%rP(1) + y%HubPtMotion14%TranslationDisp(2,1) = -1.*m%RtHS%rP(3) + y%HubPtMotion14%TranslationDisp(3,1) = m%RtHS%rP(2) + p%PtfmRefzt + + y%HubPtMotion14%TranslationDisp = y%HubPtMotion14%TranslationDisp - y%HubPtMotion14%Position + + ! Hub orientation should use the g instead of e system, but the current version + ! of AeroDyn calculates forces normal and tangential to the cone of rotation + + y%HubPtMotion14%Orientation(1,1,1) = m%CoordSys%e1(1) + y%HubPtMotion14%Orientation(2,1,1) = m%CoordSys%e2(1) + y%HubPtMotion14%Orientation(3,1,1) = m%CoordSys%e3(1) + y%HubPtMotion14%Orientation(1,2,1) = -1.*m%CoordSys%e1(3) + y%HubPtMotion14%Orientation(2,2,1) = -1.*m%CoordSys%e2(3) + y%HubPtMotion14%Orientation(3,2,1) = -1.*m%CoordSys%e3(3) + y%HubPtMotion14%Orientation(1,3,1) = m%CoordSys%e1(2) + y%HubPtMotion14%Orientation(2,3,1) = m%CoordSys%e2(2) + y%HubPtMotion14%Orientation(3,3,1) = m%CoordSys%e3(2) + + ! Note the hub rotational velocity should be AngVelEH instead AngVelEL, but AeroDyn (13.00.00) + ! treats teeter deflections like blade deflections: + + y%HubPtMotion14%RotationVel(1,1) = m%RtHS%AngVelEL(1) + y%HubPtMotion14%RotationVel(2,1) = -1.*m%RtHS%AngVelEL(3) + y%HubPtMotion14%RotationVel(3,1) = m%RtHS%AngVelEL(2) + + !........... + ! Blade roots (AeroDyn v14): + !........... + + ! Blade root orientations should use the j instead of i system, but the current version + ! of AeroDyn calculates forces normal and tangential to the cone of rotation + + DO K=1,p%NumBl + + y%BladeRootMotion14%Orientation(1,1,K) = m%CoordSys%i1(K,1) + y%BladeRootMotion14%Orientation(2,1,K) = m%CoordSys%i2(K,1) + y%BladeRootMotion14%Orientation(3,1,K) = m%CoordSys%i3(K,1) + y%BladeRootMotion14%Orientation(1,2,K) = -1.*m%CoordSys%i1(K,3) + y%BladeRootMotion14%Orientation(2,2,K) = -1.*m%CoordSys%i2(K,3) + y%BladeRootMotion14%Orientation(3,2,K) = -1.*m%CoordSys%i3(K,3) + y%BladeRootMotion14%Orientation(1,3,K) = m%CoordSys%i1(K,2) + y%BladeRootMotion14%Orientation(2,3,K) = m%CoordSys%i2(K,2) + y%BladeRootMotion14%Orientation(3,3,K) = m%CoordSys%i3(K,2) + + END DO + + + !........... + ! Rotor furl: + !........... + + ! Rotor furl position should be rP instead of rV, but AeroDyn needs this for the HubVDue2Yaw calculation: + + y%RotorFurlMotion14%TranslationDisp(1,1) = m%RtHS%rV(1) + y%RotorFurlMotion14%TranslationDisp(2,1) = -1.*m%RtHS%rV(3) + y%RotorFurlMotion14%TranslationDisp(3,1) = m%RtHS%rV(2) + p%PtfmRefzt + + y%RotorFurlMotion14%TranslationDisp = y%RotorFurlMotion14%TranslationDisp - y%RotorFurlMotion14%Position + + ! Rotor furl orientation (note the different order than hub and blade root!) + + y%RotorFurlMotion14%Orientation(1,1,1) = m%CoordSys%c1(1) + y%RotorFurlMotion14%Orientation(2,1,1) = -1.*m%CoordSys%c3(1) + y%RotorFurlMotion14%Orientation(3,1,1) = m%CoordSys%c2(1) + y%RotorFurlMotion14%Orientation(1,2,1) = -1.*m%CoordSys%c1(3) + y%RotorFurlMotion14%Orientation(2,2,1) = m%CoordSys%c3(3) + y%RotorFurlMotion14%Orientation(3,2,1) = -1.*m%CoordSys%c2(3) + y%RotorFurlMotion14%Orientation(1,3,1) = m%CoordSys%c1(2) + y%RotorFurlMotion14%Orientation(2,3,1) = -1.*m%CoordSys%c3(2) + y%RotorFurlMotion14%Orientation(3,3,1) = m%CoordSys%c2(2) + + ! rotaional velocity: + y%RotorFurlMotion14%RotationVel(1,1) = m%RtHS%AngVelER(1) + y%RotorFurlMotion14%RotationVel(2,1) = -1.*m%RtHS%AngVelER(3) + y%RotorFurlMotion14%RotationVel(3,1) = m%RtHS%AngVelER(2) + + !........... + ! Nacelle : + !........... + + y%NacelleMotion%TranslationDisp(1,1) = m%RtHS%rO(1) + y%NacelleMotion%TranslationDisp(2,1) = -1.*m%RtHS%rO(3) + y%NacelleMotion%TranslationDisp(3,1) = m%RtHS%rO(2) + p%PtfmRefzt + + y%NacelleMotion%TranslationDisp = y%NacelleMotion%TranslationDisp - y%NacelleMotion%Position + + ! Nacelle orientation (note the different order than hub and blade root!) + + y%NacelleMotion%Orientation(1,1,1) = m%CoordSys%d1(1) + y%NacelleMotion%Orientation(2,1,1) = -1.*m%CoordSys%d3(1) + y%NacelleMotion%Orientation(3,1,1) = m%CoordSys%d2(1) + y%NacelleMotion%Orientation(1,2,1) = -1.*m%CoordSys%d1(3) + y%NacelleMotion%Orientation(2,2,1) = m%CoordSys%d3(3) + y%NacelleMotion%Orientation(3,2,1) = -1.*m%CoordSys%d2(3) + y%NacelleMotion%Orientation(1,3,1) = m%CoordSys%d1(2) + y%NacelleMotion%Orientation(2,3,1) = -1.*m%CoordSys%d3(2) + y%NacelleMotion%Orientation(3,3,1) = m%CoordSys%d2(2) + + y%NacelleMotion%RotationVel(1,1) = m%RtHS%AngVelEN(1) + y%NacelleMotion%RotationVel(2,1) = -1.*m%RtHS%AngVelEN(3) + y%NacelleMotion%RotationVel(3,1) = m%RtHS%AngVelEN(2) + + y%NacelleMotion%TranslationVel(1,1) = m%RtHS%LinVelEO(1) + y%NacelleMotion%TranslationVel(2,1) = -1.*m%RtHS%LinVelEO(3) + y%NacelleMotion%TranslationVel(3,1) = m%RtHS%LinVelEO(2) + + y%NacelleMotion%RotationAcc( 1,1) = AngAccEN(1) + y%NacelleMotion%RotationAcc( 2,1) = -1.*AngAccEN(3) + y%NacelleMotion%RotationAcc( 3,1) = AngAccEN(2) + + y%NacelleMotion%TranslationAcc(1,1) = LinAccEO(1) + y%NacelleMotion%TranslationAcc(2,1) = -1.*LinAccEO(3) + y%NacelleMotion%TranslationAcc(3,1) = LinAccEO(2) + + + !........... + ! Tower : + !........... + + ! Tower base position should be rT(0) instead of rZ, but AeroDyn needs this for the HubVDue2Yaw calculation: + y%TowerBaseMotion14%TranslationDisp(1,1) = m%RtHS%rZ(1) + y%TowerBaseMotion14%TranslationDisp(2,1) = -1.*m%RtHS%rZ(3) + y%TowerBaseMotion14%TranslationDisp(3,1) = m%RtHS%rZ(2) + p%PtfmRefzt + + y%TowerBaseMotion14%TranslationDisp = y%TowerBaseMotion14%TranslationDisp - y%TowerBaseMotion14%Position + + y%TowerBaseMotion14%RotationVel(1,1) = m%RtHS%AngVelEX(1) + y%TowerBaseMotion14%RotationVel(2,1) = -1.*m%RtHS%AngVelEX(3) + y%TowerBaseMotion14%RotationVel(3,1) = m%RtHS%AngVelEX(2) + + !............................................................................................................................... + ! Outputs required for HydroDyn + !............................................................................................................................... + + y%PlatformPtMesh%TranslationDisp(1,1) = x%QT(DOF_Sg) + y%PlatformPtMesh%TranslationDisp(2,1) = x%QT(DOF_Sw) + y%PlatformPtMesh%TranslationDisp(3,1) = x%QT(DOF_Hv) + + y%PlatformPtMesh%RotationVel(1,1) = x%QDT(DOF_R ) + y%PlatformPtMesh%RotationVel(2,1) = x%QDT(DOF_P ) + y%PlatformPtMesh%RotationVel(3,1) = x%QDT(DOF_Y ) + + y%PlatformPtMesh%TranslationVel(1,1) = x%QDT(DOF_Sg) + y%PlatformPtMesh%TranslationVel(2,1) = x%QDT(DOF_Sw) + y%PlatformPtMesh%TranslationVel(3,1) = x%QDT(DOF_Hv) + + + CALL SmllRotTrans( 'platform displacement (ED_CalcOutput)', x%QT(DOF_R ),x%QT(DOF_P ),x%QT(DOF_Y ), & + y%PlatformPtMesh%Orientation(:,:,1), errstat=ErrStat, errmsg=ErrMsg ) + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//' (occurred at '//TRIM(Num2LStr(t))//' s)' + !IF (ErrStat >= AbortErrLev) RETURN + + y%PlatformPtMesh%RotationAcc(1,1) = m%QD2T(DOF_R ) + y%PlatformPtMesh%RotationAcc(2,1) = m%QD2T(DOF_P ) + y%PlatformPtMesh%RotationAcc(3,1) = m%QD2T(DOF_Y ) + + y%PlatformPtMesh%TranslationAcc(1,1) = m%QD2T(DOF_Sg) + y%PlatformPtMesh%TranslationAcc(2,1) = m%QD2T(DOF_Sw) + y%PlatformPtMesh%TranslationAcc(3,1) = m%QD2T(DOF_Hv) + + !............................................................................................................................... + ! Outputs required for external tower loads + !............................................................................................................................... + + DO J=1,p%TwrNodes + y%TowerLn2Mesh%TranslationDisp(1,J) = m%RtHS%rT( 1,J) - y%TowerLn2Mesh%Position(1,J) + y%TowerLn2Mesh%TranslationDisp(2,J) = -1.*m%RtHS%rT( 3,J) - y%TowerLn2Mesh%Position(2,J) + y%TowerLn2Mesh%TranslationDisp(3,J) = m%RtHS%rT( 2,J) - y%TowerLn2Mesh%Position(3,J) + p%PtfmRefzt + + y%TowerLn2Mesh%Orientation(1,1,J) = m%CoordSys%t1(J,1) + y%TowerLn2Mesh%Orientation(3,1,J) = m%CoordSys%t2(J,1) + y%TowerLn2Mesh%Orientation(2,1,J) = -1.*m%CoordSys%t3(J,1) + y%TowerLn2Mesh%Orientation(1,2,J) = -1.*m%CoordSys%t1(J,3) + y%TowerLn2Mesh%Orientation(3,2,J) = -1.*m%CoordSys%t2(J,3) + y%TowerLn2Mesh%Orientation(2,2,J) = m%CoordSys%t3(J,3) + y%TowerLn2Mesh%Orientation(1,3,J) = m%CoordSys%t1(J,2) + y%TowerLn2Mesh%Orientation(3,3,J) = m%CoordSys%t2(J,2) + y%TowerLn2Mesh%Orientation(2,3,J) = -1.*m%CoordSys%t3(J,2) + + y%TowerLn2Mesh%TranslationVel(1,J) = m%RtHS%LinVelET(1,J) + y%TowerLn2Mesh%TranslationVel(2,J) = -1.*m%RtHS%LinVelET(3,J) + y%TowerLn2Mesh%TranslationVel(3,J) = m%RtHS%LinVelET(2,J) + + y%TowerLn2Mesh%RotationVel(1,J) = m%RtHS%AngVelEF(1,J) + y%TowerLn2Mesh%RotationVel(2,J) = -1.*m%RtHS%AngVelEF(3,J) + y%TowerLn2Mesh%RotationVel(3,J) = m%RtHS%AngVelEF(2,J) + + y%TowerLn2Mesh%TranslationAcc(1,J) = LinAccET(1,J) + y%TowerLn2Mesh%TranslationAcc(2,J) = -1.*LinAccET(3,J) + y%TowerLn2Mesh%TranslationAcc(3,J) = LinAccET(2,J) + + y%TowerLn2Mesh%RotationAcc(1,J) = AngAccEF(1,J) + y%TowerLn2Mesh%RotationAcc(2,J) = -1.*AngAccEF(3,J) + y%TowerLn2Mesh%RotationAcc(3,J) = AngAccEF(2,J) + + END DO + + + ! p%TwrNodes+1 is the tower top: + J = p%TwrNodes+1 + + y%TowerLn2Mesh%TranslationDisp(1,J) = m%RtHS%rO(1) - y%TowerLn2Mesh%Position(1,J) + y%TowerLn2Mesh%TranslationDisp(2,J) = -1.*m%RtHS%rO(3) - y%TowerLn2Mesh%Position(2,J) + y%TowerLn2Mesh%TranslationDisp(3,J) = m%RtHS%rO(2) - y%TowerLn2Mesh%Position(3,J) + p%PtfmRefzt + + y%TowerLn2Mesh%Orientation(1,1,J) = m%CoordSys%b1(1) + y%TowerLn2Mesh%Orientation(3,1,J) = m%CoordSys%b2(1) + y%TowerLn2Mesh%Orientation(2,1,J) = -1.*m%CoordSys%b3(1) + y%TowerLn2Mesh%Orientation(1,2,J) = -1.*m%CoordSys%b1(3) + y%TowerLn2Mesh%Orientation(3,2,J) = -1.*m%CoordSys%b2(3) + y%TowerLn2Mesh%Orientation(2,2,J) = m%CoordSys%b3(3) + y%TowerLn2Mesh%Orientation(1,3,J) = m%CoordSys%b1(2) + y%TowerLn2Mesh%Orientation(3,3,J) = m%CoordSys%b2(2) + y%TowerLn2Mesh%Orientation(2,3,J) = -1.*m%CoordSys%b3(2) + + y%TowerLn2Mesh%TranslationVel(1,J) = m%RtHS%LinVelEO(1) + y%TowerLn2Mesh%TranslationVel(2,J) = -1.*m%RtHS%LinVelEO(3) + y%TowerLn2Mesh%TranslationVel(3,J) = m%RtHS%LinVelEO(2) + + y%TowerLn2Mesh%RotationVel(1,J) = m%RtHS%AngVelEB(1) + y%TowerLn2Mesh%RotationVel(2,J) = -1.*m%RtHS%AngVelEB(3) + y%TowerLn2Mesh%RotationVel(3,J) = m%RtHS%AngVelEB(2) + + y%TowerLn2Mesh%TranslationAcc(1,J) = LinAccEO(1) + y%TowerLn2Mesh%TranslationAcc(2,J) = -1.*LinAccEO(3) + y%TowerLn2Mesh%TranslationAcc(3,J) = LinAccEO(2) + + y%TowerLn2Mesh%RotationAcc(1,J) = AngAccEB(1) + y%TowerLn2Mesh%RotationAcc(2,J) = -1.*AngAccEB(3) + y%TowerLn2Mesh%RotationAcc(3,J) = AngAccEB(2) + + + ! p%TwrNodes+2 is the tower base: + J = p%TwrNodes+2 + + y%TowerLn2Mesh%TranslationDisp(1,J) = m%RtHS%rZ(1) + m%RtHS%rZT0(1) - y%TowerLn2Mesh%Position(1,J) + y%TowerLn2Mesh%TranslationDisp(2,J) = -1.*m%RtHS%rZ(3) - m%RtHS%rZT0(3) - y%TowerLn2Mesh%Position(2,J) + y%TowerLn2Mesh%TranslationDisp(3,J) = m%RtHS%rZ(2) + m%RtHS%rZT0(2) - y%TowerLn2Mesh%Position(3,J) + p%PtfmRefzt + + y%TowerLn2Mesh%Orientation(1,1,J) = m%CoordSys%a1(1) + y%TowerLn2Mesh%Orientation(3,1,J) = m%CoordSys%a2(1) + y%TowerLn2Mesh%Orientation(2,1,J) = -1.*m%CoordSys%a3(1) + y%TowerLn2Mesh%Orientation(1,2,J) = -1.*m%CoordSys%a1(3) + y%TowerLn2Mesh%Orientation(3,2,J) = -1.*m%CoordSys%a2(3) + y%TowerLn2Mesh%Orientation(2,2,J) = m%CoordSys%a3(3) + y%TowerLn2Mesh%Orientation(1,3,J) = m%CoordSys%a1(2) + y%TowerLn2Mesh%Orientation(3,3,J) = m%CoordSys%a2(2) + y%TowerLn2Mesh%Orientation(2,3,J) = -1.*m%CoordSys%a3(2) + + y%TowerLn2Mesh%TranslationVel(1,J) = m%RtHS%LinVelET(1,0) + y%TowerLn2Mesh%TranslationVel(2,J) = -1.*m%RtHS%LinVelET(3,0) + y%TowerLn2Mesh%TranslationVel(3,J) = m%RtHS%LinVelET(2,0) + + y%TowerLn2Mesh%RotationVel(1,J) = m%RtHS%AngVelEF(1,0) + y%TowerLn2Mesh%RotationVel(2,J) = -1.*m%RtHS%AngVelEF(3,0) + y%TowerLn2Mesh%RotationVel(3,J) = m%RtHS%AngVelEF(2,0) + + y%TowerLn2Mesh%TranslationAcc(1,J) = LinAccET(1,0) + y%TowerLn2Mesh%TranslationAcc(2,J) = -1.*LinAccET(3,0) + y%TowerLn2Mesh%TranslationAcc(3,J) = LinAccET(2,0) + + y%TowerLn2Mesh%RotationAcc(1,J) = AngAccEF(1,0) + y%TowerLn2Mesh%RotationAcc(2,J) = -1.*AngAccEF(3,0) + y%TowerLn2Mesh%RotationAcc(3,J) = AngAccEF(2,0) + + !............................................................................................................................... + ! Outputs required for ServoDyn + !............................................................................................................................... + + y%Yaw = x%QT( DOF_Yaw) + y%YawRate = x%QDT(DOF_Yaw) + y%YawAngle = x%QT( DOF_Yaw) + x%QT(DOF_Y) !crude approximation for yaw error... (without subtracting it from the wind direction) + y%BlPitch = u%BlPitchCom !OtherState%BlPitch + y%LSS_Spd = x%QDT(DOF_GeAz) + y%HSS_Spd = ABS(p%GBRatio)*x%QDT(DOF_GeAz) + y%RotSpeed = x%QDT(DOF_GeAz) + x%QDT(DOF_DrTr) + + IF ( t > 0.0_DbKi ) THEN + + ! Calculate tower-top acceleration (fore-aft mode only) in the tower-top system: + + LinAccEO = m%RtHS%LinAccEOt + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + LinAccEO = LinAccEO + m%RtHS%PLinVelEO(p%DOFs%PTE(I),0,:)*m%QD2T(p%DOFs%PTE(I)) + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + + y%TwrAccel = DOT_PRODUCT( LinAccEO, m%CoordSys%b1 ) + ELSE + y%TwrAccel = 0 + END IF + + !Control outputs for Bladed DLL: + y%RotPwr = m%AllOuts( RotPwr)*1000. + DO K=1,p%NumBl + y%RootMxc(K) = m%AllOuts( RootMxc(K) )*1000. + y%RootMyc(K) = m%AllOuts( RootMyc(K) )*1000. + END DO + y%YawBrTAxp = m%AllOuts( YawBrTAxp) + y%YawBrTAyp = m%AllOuts( YawBrTAyp) + !y%LSSTipPxa = m%AllOuts( LSSTipPxa)*D2R ! bjj: did this above already + + y%LSSTipMxa = m%AllOuts(LSShftMxa)*1000. + y%LSSTipMya = m%AllOuts(LSSTipMya)*1000. ! Rotating hub My (GL co-ords) (Nm) + y%LSSTipMza = m%AllOuts(LSSTipMza)*1000. ! Rotating hub Mz (GL co-ords) (Nm) + y%LSSTipMys = m%AllOuts(LSSTipMys)*1000. ! Fixed hub My (GL co-ords) (Nm) + y%LSSTipMzs = m%AllOuts(LSSTipMzs)*1000. ! Fixed hub Mz (GL co-ords) (Nm) + y%YawBrMyn = m%AllOuts( YawBrMyn)*1000. ! Yaw bearing My (GL co-ords) (Nm) !tower accel + y%YawBrMzn = m%AllOuts( YawBrMzn)*1000. ! Yaw bearing Mz (GL co-ords) (Nm) + y%NcIMURAxs = m%AllOuts(NcIMURAxs)*D2R ! Nacelle roll acceleration (rad/s^2) -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + y%NcIMURAys = m%AllOuts(NcIMURAys)*D2R ! Nacelle nodding acceleration (rad/s^2) + y%NcIMURAzs = m%AllOuts(NcIMURAzs)*D2R ! Nacelle yaw acceleration (rad/s^2) -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + + + RETURN + + +END SUBROUTINE ED_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +SUBROUTINE ED_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ED_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(ED_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: dxdt !< Continuous state derivatives at t [intent in so we don't need to allocate/deallocate constantly] + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! LOCAL variables + LOGICAL, PARAMETER :: UpdateValues = .TRUE. ! determines if the OtherState values need to be updated + + INTEGER(IntKi) :: I ! Loops through some or all of the DOFs. + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CalcContStateDeriv' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + !OtherState%HSSBrTrqC = SIGN( u%HSSBrTrqC, x%QDT(DOF_GeAz) ) !need correct value of x%QDT(DOF_GeAz) here + + ! Compute the first time derivatives of the continuous states here: + + ! See if the values stored in m%RtHS and m%CoordSys need to be updated: + IF ( UpdateValues ) THEN + + !OtherState%BlPitch = u%BlPitchCom + + ! set the coordinate system variables: + CALL SetCoordSy( t, m%CoordSys, m%RtHS, u%BlPitchCom, p, x, ErrStat2, ErrMsg2 ) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CalculatePositions( p, x, m%CoordSys, m%RtHS ) ! calculate positions + CALL CalculateAngularPosVelPAcc(p, x, m%CoordSys, m%RtHS ) ! calculate angular positions, velocities, and partial accelerations, including partial angular quantities + CALL CalculateLinearVelPAcc( p, x, m%CoordSys, m%RtHS ) ! calculate linear velocities and partial accelerations + CALL CalculateForcesMoments( p, x, m%CoordSys, u, m%RtHS ) ! calculate the forces and moments (requires AeroBladeForces and AeroBladeMoments) + + END IF + + !..................................... + ! TeetMom, RFrlMom, TFrlMom (possibly from user routines) + ! bjj: we will want to revisit these routines: + !..................................... + + ! Compute the moments from teeter springs and dampers, rotor-furl springs and dampers, tail-furl springs and dampers + + CALL Teeter ( t, p, m%RtHS%TeetAng, m%RtHS%TeetAngVel, m%RtHS%TeetMom ) ! Compute moment from teeter springs and dampers, TeetMom; NOTE: TeetMom will be zero for a 3-blader since TeetAng = TeetAngVel = 0 + CALL RFurling( t, p, x%QT(DOF_RFrl), x%QDT(DOF_RFrl), m%RtHS%RFrlMom ) ! Compute moment from rotor-furl springs and dampers, RFrlMom + CALL TFurling( t, p, x%QT(DOF_TFrl), x%QDT(DOF_TFrl), m%RtHS%TFrlMom ) ! Compute moment from tail-furl springs and dampers, TFrlMom + + !bjj: note m%RtHS%GBoxEffFac needed in OtherState only to fix HSSBrTrq (and used in FillAugMat) + m%RtHS%GBoxEffFac = p%GBoxEff**OtherState%SgnPrvLSTQ ! = GBoxEff if SgnPrvLSTQ = 1 OR 1/GBoxEff if SgnPrvLSTQ = -1 + + CALL FillAugMat( p, x, m%CoordSys, u, OtherState%HSSBrTrq, m%RtHS, m%AugMat ) + + + ! Invert the matrix to solve for the accelerations. The accelerations are returned by Gauss() in the first NActvDOF elements + ! of the solution vector, SolnVec(). These are transfered to the proper index locations of the acceleration vector QD2T() + ! using the vector subscript array SrtPS(), after Gauss() has been called: + ! NOTE: QD2T( SrtPS(1:NActvDOF) ) cannot be sent directly because arrays sections with vector subscripts must not be used + ! in INTENT(OUT) arguments. + + IF ( p%DOFs%NActvDOF > 0 ) THEN + m%AugMat_factor = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1:p%DOFs%NActvDOF) ) + m%SolnVec = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1+p%DOFs%NActvDOF) ) + + + CALL LAPACK_getrf( M=p%DOFs%NActvDOF, N=p%DOFs%NActvDOF, A=m%AugMat_factor, IPIV=m%AugMat_pivot, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL LAPACK_getrs( TRANS='N',N=p%DOFs%NActvDOF, A=m%AugMat_factor,IPIV=m%AugMat_pivot, B=m%SolnVec, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + + !CALL GaussElim( m%AugMat( p%DOFs%SrtPS( 1: p%DOFs%NActvDOF ), & + ! p%DOFs%SrtPSNAUG(1:(p%DOFs%NActvDOF+1)) ), & + ! p%DOFs%NActvDOF, SolnVec, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + !bjj: if the deriv is INTENT(OUT), this is reallocated each time: +IF (.NOT. ALLOCATED(dxdt%qt) ) THEN + CALL AllocAry( dxdt%qt, SIZE(x%qt), 'dxdt%qt', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN +END IF + +IF (.NOT. ALLOCATED(dxdt%qdt) ) THEN + CALL AllocAry( dxdt%qdt, SIZE(x%qdt), 'dxdt%qdt', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN +END IF + + dxdt%QT = x%QDT + + dxdt%QDT = 0.0 + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dxdt%QDT(p%DOFs%SrtPS(I)) = m%SolnVec(I) ! dxdt%QDT = m%QD2T + ENDDO ! I - All active (enabled) DOFs + + m%QD2T = dxdt%QDT + + + ! Let's calculate the sign (+/-1) of the low-speed shaft torque for this time step and store it in SgnPrvLSTQ. + ! This will be used during the next call to RtHS (bjj: currently violates framework, but DOE wants a hack for HSS brake). + ! need m%QD2T set before calling this + + !OtherState%SgnPrvLSTQ = SignLSSTrq(p, m) + + +END SUBROUTINE ED_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +SUBROUTINE ED_UpdateDiscState( t, n, u, 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(ED_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ED_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(ED_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + + ! StateData%DiscState = + +END SUBROUTINE ED_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE ED_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(ED_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(ED_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ED_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0. + +END SUBROUTINE ED_CalcConstrStateResidual +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets the parameters, based on the data stored in InputFileData +SUBROUTINE ED_SetParameters( InputFileData, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The module's parameter data + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! Local variables +! INTEGER(IntKi) :: K ! Loop counter (for blades) + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + + + ! Set parameters from primary input file + CALL SetPrimaryParameters( p, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + p%DT24 = p%DT/24.0_DbKi ! Time-step parameter needed for Solver(). + + + ! Set furling parameters + CALL SetFurlParameters( p, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Set blade parameters + CALL SetBladeParameters( p, InputFileData%InpBl, InputFileData%InpBlMesh, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Set tower parameters + CALL SetTowerParameters( p, InputFileData, ErrStat2, ErrMsg2 ) ! It requires p%TwrFlexL, and p%TwrNodes to be set first. + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Set the remaining (calculuated) parameters (basically the former Coeff routine) + CALL SetOtherParameters( p, InputFileData, ErrStat2, ErrMsg2 ) ! requires MANY things to be set first + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllBldNdOuts_SetParameters( p, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + !p%BldNd_NumOuts = 0_IntKi + !p%BldNd_TotNumOuts = 0_IntKi + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_SetParameters:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE ED_SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine initializes the ActiveDOF data type as well as the variables related to DOFs, including p%NAug and p%NDOF. +!! It assumes that p\%NumBl is set. +SUBROUTINE Init_DOFparameters( InputFileData, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The module's parameter data + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! Local variables + INTEGER(IntKi) :: K ! Loop counter (for blades) + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + + IF ( p%NumBl == 2 ) THEN + p%NDOF = 22 + ELSE + p%NDOF = ED_MaxDOFs + ENDIF + + p%NAug = p%NDOF + 1 + + ! ........................................................................................................................... + ! allocate and set DOF_Flag and DOF_Desc + ! ........................................................................................................................... + CALL AllocAry( p%DOF_Flag, p%NDOF, 'DOF_Flag', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%DOF_Desc, p%NDOF, 'DOF_Desc', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + p%DOF_Flag = .false. + p%DOF_Desc = '' + IF ( p%NumBl == 2 ) THEN ! the 3rd blade overwrites the DOF_Teet position of the array, so don't use an "ELSE" for this statement + p%DOF_Flag(DOF_Teet) = InputFileData%TeetDOF + p%DOF_Desc(DOF_Teet) = 'Hub teetering DOF (internal DOF index = DOF_Teet), rad' + END IF ! + + + DO K = 1,p%NumBl + p%DOF_Flag( DOF_BF(K,1) ) = InputFileData%FlapDOF1 + p%DOF_Desc( DOF_BF(K,1) ) = '1st flapwise bending-mode DOF of blade '//TRIM(Num2LStr( K ))// & + ' (internal DOF index = DOF_BF(' //TRIM(Num2LStr( K ))//',1)), m' + + p%DOF_Flag( DOF_BE(K,1) ) = InputFileData%EdgeDOF + p%DOF_Desc( DOF_BE(K,1) ) = '1st edgewise bending-mode DOF of blade '//TRIM(Num2LStr( K ))// & + ' (internal DOF index = DOF_BE(' //TRIM(Num2LStr( K ))//',1)), m' + + p%DOF_Flag( DOF_BF(K,2) ) = InputFileData%FlapDOF2 + p%DOF_Desc( DOF_BF(K,2) ) = '2nd flapwise bending-mode DOF of blade '//TRIM(Num2LStr( K ))// & + ' (internal DOF index = DOF_BF(' //TRIM(Num2LStr( K ))//',2)), m' + ENDDO ! K - All blades + + p%DOF_Flag(DOF_DrTr) = InputFileData%DrTrDOF + p%DOF_Desc(DOF_DrTr) = 'Drivetrain rotational-flexibility DOF (internal DOF index = DOF_DrTr), rad' + p%DOF_Flag(DOF_GeAz) = InputFileData%GenDOF + p%DOF_Desc(DOF_GeAz) = 'Variable speed generator DOF (internal DOF index = DOF_GeAz), rad' + p%DOF_Flag(DOF_RFrl) = InputFileData%RFrlDOF + p%DOF_Desc(DOF_RFrl) = 'Rotor-furl DOF (internal DOF index = DOF_RFrl), rad' + p%DOF_Flag(DOF_TFrl) = InputFileData%TFrlDOF + p%DOF_Desc(DOF_TFrl) = 'Tail-furl DOF (internal DOF index = DOF_TFrl), rad' + p%DOF_Flag(DOF_Yaw ) = InputFileData%YawDOF + p%DOF_Desc(DOF_Yaw ) = 'Nacelle yaw DOF (internal DOF index = DOF_Yaw), rad' + p%DOF_Flag(DOF_TFA1) = InputFileData%TwFADOF1 + p%DOF_Desc(DOF_TFA1) = '1st tower fore-aft bending mode DOF (internal DOF index = DOF_TFA1), m' + p%DOF_Flag(DOF_TSS1) = InputFileData%TwSSDOF1 + p%DOF_Desc(DOF_TSS1) = '1st tower side-to-side bending mode DOF (internal DOF index = DOF_TSS1), m' + p%DOF_Flag(DOF_TFA2) = InputFileData%TwFADOF2 + p%DOF_Desc(DOF_TFA2) = '2nd tower fore-aft bending mode DOF (internal DOF index = DOF_TFA2), m' + p%DOF_Flag(DOF_TSS2) = InputFileData%TwSSDOF2 + p%DOF_Desc(DOF_TSS2) = '2nd tower side-to-side bending mode DOF (internal DOF index = DOF_TSS2), m' + p%DOF_Flag(DOF_Sg ) = InputFileData%PtfmSgDOF + p%DOF_Desc(DOF_Sg ) = 'Platform horizontal surge translation DOF (internal DOF index = DOF_Sg), m' + p%DOF_Flag(DOF_Sw ) = InputFileData%PtfmSwDOF + p%DOF_Desc(DOF_Sw ) = 'Platform horizontal sway translation DOF (internal DOF index = DOF_Sw), m' + p%DOF_Flag(DOF_Hv ) = InputFileData%PtfmHvDOF + p%DOF_Desc(DOF_Hv ) = 'Platform vertical heave translation DOF (internal DOF index = DOF_Hv), m' + p%DOF_Flag(DOF_R ) = InputFileData%PtfmRDOF + p%DOF_Desc(DOF_R ) = 'Platform roll tilt rotation DOF (internal DOF index = DOF_R), rad' + p%DOF_Flag(DOF_P ) = InputFileData%PtfmPDOF + p%DOF_Desc(DOF_P ) = 'Platform pitch tilt rotation DOF (internal DOF index = DOF_P), rad' + p%DOF_Flag(DOF_Y ) = InputFileData%PtfmYDOF + p%DOF_Desc(DOF_Y ) = 'Platform yaw rotation DOF (internal DOF index = DOF_Y), rad' + + ! ........................................................................................................................... + ! allocate the arrays stored in the p%DOFs structure: + ! ........................................................................................................................... + + ! BJJ: note that this method will cause an error if allocating data that has already been allocated... + + ALLOCATE ( p%DOFs%NPSBE(p%NumBl), p%DOFs%NPSE(p%NumBl), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs NPSBE and NPSE arrays.' ) + RETURN + ENDIF + + + ALLOCATE ( p%DOFs%PCE(p%NDOF), p%DOFs%PDE(p%NDOF), p%DOFs%PIE(p%NDOF), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs PCE, PDE, and PIE arrays.' ) + RETURN + ENDIF + + + ALLOCATE ( p%DOFs%PTTE(p%NDOF), p%DOFs%PTE(p%NDOF), p%DOFs%PS(p%NDOF), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs PTTE, PTE, and PS arrays.' ) + RETURN + ENDIF + + + ALLOCATE ( p%DOFs%PUE(p%NDOF), p%DOFs%PYE(p%NDOF), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs PUE and PYE arrays.' ) + RETURN + ENDIF + + +!bjj was ALLOCATE ( p%DOFs%PSBE(p%NumBl,3), p%DOFs%PSE(p%NumBl,p%NDOF), STAT=ErrStat ) + ALLOCATE ( p%DOFs%PSBE(p%NumBl,(NumBE+NumBF)), p%DOFs%PSE(p%NumBl,p%NDOF), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs PSBE and PSE arrays.' ) + RETURN + ENDIF + + + ALLOCATE ( p%DOFs%SrtPS(p%NDOF), p%DOFs%SrtPSNAUG(p%NAug), p%DOFs%Diag(p%NDOF), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveAOFs SrtPS, SrtPSNAUG, and Diag arrays.' ) + RETURN + ENDIF + + + !............................................................................................................................... + ! Allocate and Initialize arrays for DOFS that contribute to the angular velocity of the hub and blade elements + !............................................................................................................................... + ! Define arrays of DOF indices (pointers) that contribute to the angular + ! velocities of each rigid body of the wind turbine in the inertia frame: + ! NOTE: We must include ALL of the appropriate DOF indices in these arrays, + ! not just the indices of the enabled DOFs, since disabling a DOF only + ! implies that each DOF acceleration is zero--it does not imply + ! that each DOF velocity is zero (for example, consider disabled + ! generator DOF, which still spins at constant speed). + + + + IF ( p%NumBl == 2 ) THEN ! 2-blader + p%NPH = 12 ! Number of DOFs that contribute to the angular velocity of the hub (body H) in the inertia frame. + p%NPM = 15 ! Number of DOFs that contribute to the angular velocity of the blade elements (body M) in the inertia frame. + ELSE ! 3-blader + p%NPH = 11 ! Number of DOFs that contribute to the angular velocity of the hub (body H) in the inertia frame. + p%NPM = 14 ! Number of DOFs that contribute to the angular velocity of the blade elements (body M) in the inertia frame. + ENDIF + + + ALLOCATE ( p%PH(p%NPH), p%PM(p%NumBl,p%NPM), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ExitThisRoutine( ErrID_Fatal, ' Could not allocate memory for the ActiveDOFs PH and PM arrays.' ) + RETURN + ENDIF + + ! Array of DOF indices (pointers) that contribute to the angular velocity of the hub (body H) in the inertia frame: + p%PH(1:11) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl, DOF_GeAz, DOF_DrTr /) + + IF ( p%NumBl == 2 ) THEN ! 2-blader (add DOF_Teet to the arrays) + + p%PH(12) = DOF_Teet + + ! Array of DOF indices (pointers) that contribute to the angular velocity of the blade elements (body M) in the inertia frame: + DO K = 1,p%NumBl ! Loop through all blades + p%PM(K,:) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl, DOF_GeAz, DOF_DrTr, & + DOF_Teet, DOF_BF(K,1) , DOF_BE(K,1) , DOF_BF(K,2) /) + ENDDO ! K - All blades + + ELSE ! 3-blader + + ! Array of DOF indices (pointers) that contribute to the angular velocity of the blade elements (body M) in the inertia frame: + DO K = 1,p%NumBl ! Loop through all blades + p%PM(K,:) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl, DOF_GeAz, DOF_DrTr, & + DOF_BF(K,1) , DOF_BE(K,1) , DOF_BF(K,2) /) + ENDDO ! K - All blades + + ENDIF + + + !............................................................................................................................... + ! Calculate the number of active (enabled) DOFs in the model, p%DOFs%NActvDOF: + !............................................................................................................................... + CALL SetEnabledDOFIndexArrays( p ) + + RETURN + + +CONTAINS + !............................................................................................................................ + SUBROUTINE ExitThisRoutine(ErrID,Msg) + ! This subroutine cleans up all the allocatable arrays, closes the file, and sets the error status/message + !............................................................................................................................ + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error ID (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error in Init_DOFparameters: '//TRIM(ErrMsg) + END IF + + + END SUBROUTINE ExitThisRoutine + +END SUBROUTINE Init_DOFparameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> SHP calculates the Derive-derivative of the shape function ModShpAry at Fract. +!! NOTE: This function only works for Deriv = 0, 1, or 2. +FUNCTION SHP(Fract, FlexL, ModShpAry, Deriv, ErrStat, ErrMsg) +!.................................................................................................................................. + + ! Passed variables: + + REAL(ReKi), INTENT(IN ) :: FlexL !< Length of flexible beam, (m) + REAL(ReKi), INTENT(IN ) :: Fract !< Fractional distance along flexible beam, 0<=Frac<=1 + REAL(ReKi), INTENT(IN ) :: ModShpAry(:) !< Array holding mode shape coefficients (2:PolyOrd) + REAL(ReKi) :: SHP !< The shape function returned by this function. + + INTEGER(IntKi), INTENT(IN ) :: Deriv !< Which derivative to compute Deriv = 0 (regular function SHP), 1 (D(SHP)/DZ), 2 (D2(SHP)/DZ2) + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< A error level that indicates if/what error occurred + CHARACTER(*), INTENT(OUT) :: ErrMsg !< A message indicating the error if one occurred + + + ! Local variables: + + INTEGER(IntKi) :: CoefTmp ! Temporary coefficient + INTEGER(IntKi) :: I ! Counts through polynomial array. + INTEGER(IntKi) :: J ! I+1 + INTEGER(IntKi) :: Swtch(0:2) ! Corresponds to which derivative to compute. Sets all portions of the coefficient = 0 except those that are relevant. + + + IF ( Deriv < 0 .OR. Deriv > 2 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Function SHP input Deriv='//TRIM(Num2LStr(Deriv))//' is invalid. Deriv must be 0, 1, or 2.' + RETURN + ELSEIF ( Fract < 0.0_ReKi .OR. Fract > 1.0_ReKi ) THEN + ErrStat = ErrID_Warn + ErrMsg = 'Function SHP input Fract='//TRIM(Num2LStr(Fract))//' does not meet the condition 0<=Fract<=1.' + ELSE + ErrStat = ErrID_None + END IF + + Swtch = 0 ! Initialize Swtch(:) to 0 + Swtch(Deriv) = 1 + SHP = 0.0 + + DO I = 1,SIZE(ModShpAry,DIM=1,KIND=IntKi) ! =2,PolyOrd + J = I + 1 + CoefTmp = Swtch(0) + Swtch(1)*J + Swtch(2)*I*J + + IF ( (J == 2) .AND. (Deriv == 2) ) THEN !bjj this could be removed as Fract**0 = 1 (0**0 = 1 in Fortran) + SHP = ModShpAry(I)*CoefTmp /( FlexL**Deriv ) + ELSE + SHP = SHP + ModShpAry(I)*CoefTmp*( Fract**( J - Deriv ) )/( FlexL**Deriv ) + ENDIF + ENDDO !I + + RETURN + +END FUNCTION SHP +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine allocates the coordinate systems in the ED_CoordSys type. +SUBROUTINE Alloc_CoordSys( CoordSys, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + +IMPLICIT NONE + + ! passed arguments + +TYPE(ED_CoordSys), INTENT(OUT) :: CoordSys !< The coordinate systems, with arrays to be allocated +TYPE(ED_ParameterType), INTENT(IN) :: p !< Parameters of the structural dynamics module + +INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status +CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err msg + + + ! local variables + +CHARACTER(200), PARAMETER :: ErrTxt = 'coordinate system arrays in SUBROUTINE Alloc_CoordSys.' + + + ! Initialize ErrStat and ErrMsg + +ErrStat = ErrID_None +ErrMsg = "" + + + ! Allocate coordinate system arrays: + +ALLOCATE ( CoordSys%i1(p%NumBl,3), CoordSys%i2(p%NumBl,3), CoordSys%i3(p%NumBl,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the i1, i2, and i3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +ALLOCATE ( CoordSys%j1(p%NumBl,3), CoordSys%j2(p%NumBl,3), CoordSys%j3(p%NumBl,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the j1, j2, and j3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +ALLOCATE ( CoordSys%m1(p%NumBl,p%BldNodes,3), CoordSys%m2(p%NumBl,p%BldNodes,3), & + CoordSys%m3(p%NumBl,p%BldNodes,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the m1, m2, and m3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +ALLOCATE ( CoordSys%n1(p%NumBl,0:p%TipNode,3), CoordSys%n2(p%NumBl,0:p%TipNode,3), & + CoordSys%n3(p%NumBl,0:p%TipNode,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the n1, n2, and n3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +ALLOCATE ( CoordSys%t1(p%TwrNodes,3), CoordSys%t2(p%TwrNodes,3), CoordSys%t3(p%TwrNodes,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the t1, t2, and t3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +ALLOCATE ( CoordSys%te1(p%NumBl,p%BldNodes,3), CoordSys%te2(p%NumBl,p%BldNodes,3), & + CoordSys%te3(p%NumBl,p%BldNodes,3), STAT=ErrStat ) !this argument doesn't work in IVF 10.1: , ERRMSG=ErrMsg +IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating the te1, te2, and te3 '//TRIM(ErrTxt)//' '//TRIM(ErrMsg) + RETURN +END IF + + +RETURN +END SUBROUTINE Alloc_CoordSys +!---------------------------------------------------------------------------------------------------------------------------------- +!> This takes the blade input file data and sets the corresponding blade parameters, performing linear interpolation of the +!! input data to the specified blade mesh. +!! This routine assumes p\%HubRad and p\%BldFlexL are already set. +SUBROUTINE SetBladeParameters( p, BladeInData, BladeMeshData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The parameters of the structural dynamics module + TYPE(BladeInputData), INTENT(IN) :: BladeInData(:) !< Program input data for all blades + TYPE(ED_BladeMeshInputData), INTENT(IN) :: BladeMeshData(:) !< Program input mesh data for all blades + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + REAL(ReKi) :: x ! Fractional location between two points in linear interpolation + INTEGER(IntKi ) :: K ! Blade number + INTEGER(IntKi ) :: J ! Index for the node arrays + INTEGER(IntKi) :: InterpInd ! Index for the interpolation routine + LOGICAL :: SetAdmVals ! Logical to determine if Adams inputs should be set + + ! initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + IF (p%BD4Blades) THEN + SetAdmVals = .FALSE. + ELSE + SetAdmVals = ALLOCATED( BladeInData(1)%GJStff ) + END IF + + + ! .............................................................................................................................. + ! Set the blade discretization information here: + ! .............................................................................................................................. + + DO K=1,1 ! we're going to assume the discretization is the same for all blades + + IF (p%BD4Blades) THEN + p%BldNodes = 0 + ELSE + p%BldNodes = BladeMeshData(K)%BldNodes + END IF + + p%TipNode = p%BldNodes + 1 ! The index for the blade tip and tower top nodes + + END DO + + ! .......... Allocate arrays for the blade parameters being set in this routine ..........: + + CALL Alloc_BladeParameters( p, SetAdmVals, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + IF ( .not. p%BD4Blades) then + + DO K=1,1 ! we're going to assume the discretization is the same for all blades + + IF ( allocated( BladeMeshData(K)%Chord ) ) THEN + + p%RNodes = BladeMeshData(K)%RNodes - p%HubRad ! Radius to blade analysis nodes relative to root ( 0 < RNodes(:) < p%BldFlexL ) (Convert RNodes to be relative to the hub) + + p%DRNodes(1) = 2.0*p%RNodes(1) + DO J = 2,p%BldNodes + p%DRNodes(J) = 2.0*( p%RNodes(J) - p%RNodes(J-1) ) - p%DRNodes(J-1) + END DO + + p%Chord = BladeMeshData(K)%Chord + p%AeroTwst = BladeMeshData(K)%AeroTwst + p%CAeroTwst = COS(p%AeroTwst) + p%SAeroTwst = SIN(p%AeroTwst) + + ELSE + + + ! DRNodes (Let's use constant-spaced nodes for now, but the rest of the code is written to handle variable-spaced nodes-- + ! this will be a future input!): + p%DRNodes = p%BldFlexL/p%BldNodes !array + + ! RNodes: + p%RNodes(1) = 0.5*p%DRNodes(1) + DO J=2,p%BldNodes + p%RNodes(J) = p%RNodes( J - 1 ) + 0.5*( p%DRNodes(J) + p%DRNodes( J - 1 ) ) + END DO + + ! these values aren't used (at least they shouldn't be): + p%Chord = 0.0_ReKi + p%AeroTwst = 0.0_ReKi + p%CAeroTwst = 1.0_ReKi + p%SAeroTwst = 0.0_ReKi + + END IF + + + END DO + + + ! .............................................................................................................................. + ! Interpolate the blade properties to this discretization: + ! .............................................................................................................................. + + ! Array definitions: + + ! Input Interp Description + ! ----- ------ ----------- + ! BlFract RNodesNorm Fractional radius (0 at root, 1 at tip) + ! PitchAx PitchAxis Pitch axis (0 at LE, 1 at TE) + ! StrcTwst ThetaS Structural twist + ! BMassDen MassB Lineal mass density + ! FlpStff StiffBF Flapwise stiffness + ! EdgStff StiffBE Edgewise stiffness + ! GJStff StiffBGJ Blade torsional stiffness + ! EAStff StiffBEA Blade extensional stiffness + ! Alpha BAlpha Blade flap/twist coupling coefficient + ! FlpIner InerBFlp Blade flap (about local structural yb-axis) mass inertia per unit length + ! EdgIner InerBEdg Blade edge (about local structural xb-axis) mass inertia per unit length + ! PrecrvRef RefAxisxb Blade offset for defining the reference axis from the pitch axis for precurved blades (along xb-axis) + ! PreswpRef RefAxisyb Blade offset for defining the reference axis from the pitch axis for preswept blades (along yb-axis) + ! FlpcgOf cgOffBFlp Blade flap mass cg offset + ! EdgcgOf cgOffBEdg Blade edge mass cg offset + ! FlpEAOf EAOffBFlp Blade flap elastic axis offset + ! EdgEAOf EAOffBEdg Blade edge elastic axis offset + + + ! Define RNodesNorm() which is common to all the blades: + + p%RNodesNorm = p%RNodes/p%BldFlexL ! Normalized radius to analysis nodes relative to hub ( 0 < RNodesNorm(:) < 1 ) + + + + ! Perform a linear interpolation of the input data to map to the meshed data for simulation: + + DO K=1,p%NumBl + InterpInd = 1 + + p%ThetaS (K,0) = BladeInData(K)%StrcTwst(1) + p%ThetaS (K,p%TipNode) = BladeInData(K)%StrcTwst(BladeInData(K)%NBlInpSt) + + + DO J=1,p%BldNodes + + ! Get the index into BlFract for all of the arrays, using the NWTC Subroutine Library + !p%ThetaS (K,J) = InterpStp( p%RNodesNorm(J), BladeInData(K)%BlFract, BladeInData(K)%StrcTwst, & + ! InterpInd, BladeInData(K)%NBlInpSt ) + p%PitchAxis(K,J) = InterpStp( p%RNodesNorm(J), BladeInData(K)%BlFract, BladeInData(K)%PitchAx, & + InterpInd, BladeInData(K)%NBlInpSt ) + + + ! The remaining arrays will have the same x value for the linear interpolation, + ! so we'll do it manually (with a local subroutine) instead of calling the InterpStp routine again + IF ( BladeInData(K)%NBlInpSt < 2_IntKi ) THEN + x = 1.0 + InterpInd = 0 + ELSE + x = ( p%RNodesNorm(J) - BladeInData(K)%BlFract(InterpInd) ) / & + ( BladeInData(K)%BlFract(InterpInd+1) - BladeInData(K)%BlFract(InterpInd) ) + END IF + + p%ThetaS (K,J) = InterpAry( x, BladeInData(K)%StrcTwst, InterpInd ) + p%MassB (K,J) = InterpAry( x, BladeInData(K)%BMassDen, InterpInd ) + p%StiffBF (K,J) = InterpAry( x, BladeInData(K)%FlpStff , InterpInd ) + p%StiffBE (K,J) = InterpAry( x, BladeInData(K)%EdgStff , InterpInd ) + + IF ( SetAdmVals ) THEN + p%StiffBGJ (K,J) = InterpAry( x, BladeInData(K)%GJStff , InterpInd ) + p%StiffBEA (K,J) = InterpAry( x, BladeInData(K)%EAStff , InterpInd ) + p%BAlpha (K,J) = InterpAry( x, BladeInData(K)%Alpha , InterpInd ) + p%InerBFlp (K,J) = InterpAry( x, BladeInData(K)%FlpIner , InterpInd ) + p%InerBEdg (K,J) = InterpAry( x, BladeInData(K)%EdgIner , InterpInd ) + p%RefAxisxb(K,J) = InterpAry( x, BladeInData(K)%PrecrvRef, InterpInd ) + p%RefAxisyb(K,J) = InterpAry( x, BladeInData(K)%PreswpRef, InterpInd ) + p%cgOffBFlp(K,J) = InterpAry( x, BladeInData(K)%FlpcgOf , InterpInd ) + p%cgOffBEdg(K,J) = InterpAry( x, BladeInData(K)%EdgcgOf , InterpInd ) + p%EAOffBFlp(K,J) = InterpAry( x, BladeInData(K)%FlpEAOf , InterpInd ) + p%EAOffBEdg(K,J) = InterpAry( x, BladeInData(K)%EdgEAOf , InterpInd ) + END IF + + + + END DO ! J (Blade nodes) + + IF ( SetAdmVals ) THEN + ! Set the valus for the tip node + p%RefAxisxb(K,p%TipNode) = BladeInData(K)%PrecrvRef( BladeInData(K)%NBlInpSt ) + p%RefAxisyb(K,p%TipNode) = BladeInData(K)%PreswpRef( BladeInData(K)%NBlInpSt ) + END IF + + + ! Set the blade damping and stiffness tuner + p%BldFDamp(K,:) = BladeInData(K)%BldFlDmp + p%BldEDamp(K,:) = BladeInData(K)%BldEdDmp + p%FStTunr (K,:) = BladeInData(K)%FlStTunr + + + + ! Set the mode shape arrays + p%BldEdgSh(:,K) = BladeInData(K)%BldEdgSh + p%BldFl1Sh(:,K) = BladeInData(K)%BldFl1Sh + p%BldFl2Sh(:,K) = BladeInData(K)%BldFl2Sh + + + END DO ! ( Blades ) + + + else + + p%ThetaS = 0.0_ReKi + + ! Set the blade damping and stiffness tuner + p%BldFDamp = 0.0_ReKi + p%BldEDamp = 0.0_ReKi + p%FStTunr = 0.0_ReKi + + ! Set the mode shape arrays + p%BldEdgSh = 0.0_ReKi + p%BldFl1Sh = 0.0_ReKi + p%BldFl2Sh = 0.0_ReKi + + end if + + p%CThetaS = COS(REAL(p%ThetaS,R8Ki)) + p%SThetaS = SIN(REAL(p%ThetaS,R8Ki)) + + +RETURN + + +CONTAINS +!.................................................................................................................................. + FUNCTION InterpAry( x, YAry, Ind ) + ! This subroutine is used to interpolate the arrays more efficiently (all arrays have the same X value) + ! See InterpStpReal() for comparison. This assumes we already know Ind and that + ! x = ( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + + + REAL(ReKi), INTENT(IN) :: x ! the relative distance between Ind and Ind+ 1 + REAL(ReKi), INTENT(IN) :: YAry (:) ! Array of Y values to be interpolated. + INTEGER(IntKi) , INTENT(IN) :: Ind ! the index into the array + + REAL(ReKi) :: InterpAry ! the value calculated in this function + + IF ( Ind >= SIZE(YAry) ) THEN + InterpAry = YAry( SIZE(YAry) ) + ELSE + InterpAry = ( YAry(Ind+1) - YAry(Ind) ) * x + YAry(Ind) + END IF + + END FUNCTION InterpAry +!.................................................................................................................................. +END SUBROUTINE SetBladeParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays for the blade parameters. +SUBROUTINE Alloc_BladeParameters( p, AllocAdams, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The parameters of the structural dynamics module + LOGICAL, INTENT(IN) :: AllocAdams !< Logical to determine if Adams inputs should be allocated + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err msg + + + ! Allocate arrays to hold the blade analysis nodes. + CALL AllocAry ( p%RNodes, p%BldNodes, 'RNodes' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%DRNodes, p%BldNodes, 'DRNodes' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%Chord, p%BldNodes, 'Chord' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%AeroTwst, p%BldNodes, 'AeroTwst' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%CAeroTwst, p%BldNodes, 'CAeroTwst', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%SAeroTwst, p%BldNodes, 'SAeroTwst', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + + ! Allocate arrays to hold blade data at the analysis nodes. + CALL AllocAry ( p%RNodesNorm, p%BldNodes, 'RNodesNorm' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%PitchAxis, p%NumBl, p%BldNodes, 'PitchAxis' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + ALLOCATE( p%ThetaS( p%NumBl,0:P%TipNode) & + , p%CThetaS(p%NumBl,0:P%TipNode) & + , p%SThetaS(p%NumBl,0:P%TipNode), STAT=ErrStat ) + IF (ErrStat /= 0) then + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating ThetaS, CThetaS, and SThetaS' + END IF + + + CALL AllocAry ( p%MassB, p%NumBl, p%BldNodes, 'MassB' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffBF, p%NumBl, p%BldNodes, 'StiffBF' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffBE, p%NumBl, p%BldNodes, 'StiffBE' , ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + + IF ( AllocAdams ) THEN + CALL AllocAry ( p%StiffBGJ, p%NumBl, p%BldNodes, 'StiffBGJ' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffBEA, p%NumBl, p%BldNodes, 'StiffBEA' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%BAlpha, p%NumBl, p%BldNodes, 'BAlpha' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%InerBFlp, p%NumBl, p%BldNodes, 'InerBFlp' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%InerBEdg, p%NumBl, p%BldNodes, 'InerBEdg' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%RefAxisxb, p%NumBl, p%TipNode, 'RefAxisxb' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%RefAxisyb, p%NumBl, p%TipNode, 'RefAxisyb' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%cgOffBFlp, p%NumBl, p%BldNodes, 'cgOffBFlp' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%cgOffBEdg, p%NumBl, p%BldNodes, 'cgOffBEdg' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%EAOffBFlp, p%NumBl, p%BldNodes, 'EAOffBFlp' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%EAOffBEdg, p%NumBl, p%BldNodes, 'EAOffBEdg' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + END IF + + CALL AllocAry ( p%BldEDamp, p%NumBl, NumBE, 'BldEDamp' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%BldFDamp, p%NumBl, NumBF, 'BldFDamp' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%FStTunr, p%NumBl, NumBF, 'FStTunr' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + ! Allocate space for the mode shape arrays: + + ALLOCATE( p%BldEdgSh(2:PolyOrd,p%NumBl), p%BldFl1Sh(2:PolyOrd,p%NumBl), p%BldFl2Sh(2:PolyOrd,p%NumBl), STAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating BldEdgSh, BldFl1Sh, and BldFl2Sh arrays.' + RETURN + END IF + + +END SUBROUTINE Alloc_BladeParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays for the tower parameters. +SUBROUTINE Alloc_TowerParameters( p, AllocAdams, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The parameters of the structural dynamics module + LOGICAL, INTENT(IN) :: AllocAdams !< Logical to determine if Adams inputs should be allocated + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err msg + + + + + ! Allocate arrays to hold tower data at the analysis nodes. + CALL AllocAry ( p%HNodesNorm, p%TwrNodes, 'HNodesNorm', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%HNodes, p%TwrNodes, 'HNodes' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%DHNodes, p%TwrNodes, 'DHNodes' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%MassT, p%TwrNodes, 'MassT' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffTFA, p%TwrNodes, 'StiffTFA' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffTSS, p%TwrNodes, 'StiffTSS' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + IF ( AllocAdams ) THEN + CALL AllocAry ( p%StiffTGJ, p%TwrNodes, 'StiffTGJ' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%StiffTEA, p%TwrNodes, 'StiffTEA' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%InerTFA, p%TwrNodes, 'InerTFA' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%InerTSS, p%TwrNodes, 'InerTSS' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%cgOffTFA, p%TwrNodes, 'cgOffTFA' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( p%cgOffTSS, p%TwrNodes, 'cgOffTSS' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + END IF + + ! ! these are for HydroDyn? + !CALL AllocAry ( p%DiamT, p%TwrNodes, 'DiamT' , ErrStat, ErrMsg ) + !IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry ( p%CAT, p%TwrNodes, 'CAT' , ErrStat, ErrMsg ) + !IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry ( p%CDT, p%TwrNodes, 'CDT' , ErrStat, ErrMsg ) + !IF ( ErrStat /= ErrID_None ) RETURN + + + + ! ! Allocate space for the mode shape arrays: + ! + !ALLOCATE( p%BldEdgSh(2:PolyOrd,p%NumBl), p%BldFl1Sh(2:PolyOrd,p%NumBl), p%BldFl2Sh(2:PolyOrd,p%NumBl), STAT = ErrStat ) + !IF ( ErrStat /= 0 ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = ' Error allocating BldEdgSh, BldFl1Sh, and BldFl2Sh arrays.' + ! RETURN + !END IF + + + +END SUBROUTINE Alloc_TowerParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the remaining parameters (replacing the former FAST Initialize routine), first allocating necessary arrays. +!! It requires p\%NDOF, p\%NumBl, p\%TTopNode, p\%TipNode to be set before calling this routine. +SUBROUTINE SetOtherParameters( p, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The parameters of the structural dynamics module + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err msg + + + + + ! Allocate the arrays needed in the Coeff routine: + + !CALL AllocAry( p%AxRedTFA, 2, 2_IntKi, p%TTopNode, 'AxRedTFA', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( p%AxRedTSS, 2, 2_IntKi, p%TTopNode, 'AxRedTSS', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( p%AxRedBld, p%NumBl, 3_IntKi, 3_IntKi, p%TipNode, 'AxRedBld', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%BldCG, p%NumBl, 'BldCG', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%KBF, p%NumBl, 2_IntKi, 2_IntKi, 'KBF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%KBE, p%NumBl, 1_IntKi, 1_IntKi, 'KBE', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%CBF, p%NumBl, 2_IntKi, 2_IntKi, 'CBF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%CBE, p%NumBl, 1_IntKi, 1_IntKi, 'CBE', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%SecondMom,p%NumBl, 'SecondMom', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%FirstMom, p%NumBl, 'FirstMom', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%FreqBE, p%NumBl, NumBE, 3_IntKi, 'FreqBE', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%FreqBF, p%NumBl, NumBF, 3_IntKi, 'FreqBF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%BldMass, p%NumBl, 'BldMass', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%rSAerCenn1,p%NumBl,p%BldNodes, 'rSAerCenn1', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%rSAerCenn2,p%NumBl,p%BldNodes, 'rSAerCenn2', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry(p%BElmntMass, p%BldNodes, p%NumBl, 'BElmntMass', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry(p%TElmntMass, p%TwrNodes, 'TElmntMass', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + !CALL AllocAry( p%AxRedBld, p%NumBl, 3_IntKi, 3_IntKi, p%TipNode, 'AxRedBld', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + ALLOCATE ( p%AxRedBld(p%NumBl, 3_IntKi, 3_IntKi, 0:p%TipNode) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating AxRedBld array.' + RETURN + END IF + + + ALLOCATE ( p%TwrFASF(2,0:p%TTopNode,0:2) , & + p%TwrSSSF(2,0:p%TTopNode,0:2) , & + p%AxRedTFA(2,2,0:p%TTopNode) , & + p%AxRedTSS(2,2,0:p%TTopNode) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating TwrFASF, TwrSSSF, AxRedTFA, and p%AxRedTSS arrays.' + RETURN + END IF + + ALLOCATE ( p%TwistedSF(p%NumBl,2,3,0:p%TipNode,0:2) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating TwistedSF array.' + RETURN + END IF + + + CALL Coeff(p, InputFileData, ErrStat, ErrMsg) + IF ( ErrStat /= ErrID_None ) RETURN + + +END SUBROUTINE SetOtherParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays in the RtHndSide data structure. +!! It requires p\%TwrNodes, p\%NumBl, p\%TipNode, p\%NDOF, p\%BldNodes to be set before calling this routine. +SUBROUTINE Alloc_RtHS( RtHS, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHS !< RtHndSide data type + TYPE(ED_ParameterType), INTENT(IN) :: p !< Parameters of the structural dynamics module + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! local variables: + INTEGER(IntKi), PARAMETER :: Dims = 3 ! The position arrays all must be allocated with a dimension for X,Y,and Z + CHARACTER(*), PARAMETER :: RoutineName = 'Alloc_RtHS' + + ! positions: + !CALL AllocAry( RtHS%rZT, Dims, p%TwrNodes, 'rZT', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%rT, Dims, p%TwrNodes, 'rT', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%rT0T, Dims, p%TwrNodes, 'rT0T', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( RtHS%rQS, Dims, p%NumBl,p%TipNode, 'rQS', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( RtHS%rS, Dims, p%NumBl,p%TipNode, 'rS', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%rS0S, Dims, p%NumBl,p%TipNode, 'rS0S', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%rPS0, Dims, p%NumBl, 'rPS0', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%rSAerCen, Dims, p%TipNode, p%NumBl,'rSAerCen', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + ! tower + allocate(RtHS%rZT( Dims, 0:p%TwrNodes), & + RtHS%AngPosEF( Dims, 0:p%TwrNodes), & + RtHS%AngPosXF( Dims, 0:p%TwrNodes), & + RtHS%AngVelEF( Dims, 0:p%TwrNodes), & + RtHS%LinVelET( Dims, 0:p%TwrNodes), & + RtHS%AngAccEFt(Dims, 0:p%TwrNodes), & + RtHS%LinAccETt(Dims, 0:p%TwrNodes), & + STAT=ErrStat) + if (ErrStat /= 0) then + ErrStat = ErrID_Fatal + ErrMsg = "Error allocating rZT, AngPosEF, AngPosXF, LinVelET, AngVelEF, LinAccETt, and AngAccEFt arrays." + RETURN + end if + + + ! blades + allocate(RtHS%rS( Dims, p%NumBl,0:p%TipNode), & + RtHS%rQS(Dims, p%NumBl,0:p%TipNode), STAT=ErrStat) + if (ErrStat /= 0) then + ErrStat = ErrID_Fatal + ErrMsg = "Error allocating rS and rQS." + RETURN + end if + + + ! angular velocities (including partial angular velocities): + !CALL AllocAry( RtHS%AngVelEF, Dims, p%TwrNodes, 'AngVelEF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( RtHS%AngPosEF, Dims, p%TwrNodes, 'AngPosEF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( RtHS%AngPosXF, Dims, p%TwrNodes, 'AngPosXF', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + + ! These angular velocities are allocated to start numbering a dimension with 0 instead of 1: + ALLOCATE ( RtHS%PAngVelEB(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEB array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PAngVelER(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelER array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PAngVelEX(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEX array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PAngVelEA(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEA array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PAngVelEF(0:p%TwrNodes, p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEF array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PAngVelEG( p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEG array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PAngVelEH( p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEH array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PAngVelEL( p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEL array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PAngVelEM(p%NumBl,0:p%TipNode,p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEM array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PAngVelEN( p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PAngVelEN array.' + RETURN + ENDIF + + ! angular accelerations: + !CALL AllocAry( RtHS%AngAccEFt, Dims, p%TwrNodes, 'AngAccEFt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + ! linear velocities (including partial linear velocities): + !CALL AllocAry( RtHS%LinVelET, Dims, p%TwrNodes, 'LinVelET', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + !CALL AllocAry( RtHS%LinVelESm2, p%NumBl, 'LinVelESm2',ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN ! The m2-component (closest to tip) of LinVelES + ALLOCATE( RtHS%LinVelES( Dims, 0:p%TipNode, p%NumBl ), & + RtHS%AngVelEM( Dims, 0:p%TipNode, p%NumBl ), STAT=ErrStat ) + IF (ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":Error allocating LinVelES and AngVelEM." + RETURN + END IF + + ! These linear velocities are allocated to start numbering a dimension with 0 instead of 1: + + ALLOCATE ( RtHS%PLinVelEIMU(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEIMU array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelEO(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEO array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelES(p%NumBl,0:p%TipNode,p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelES array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelET(0:p%TwrNodes,p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelET array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelEZ(p%NDOF,0:1,Dims) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEZ array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelEC(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEC array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelED(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelED array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelEI(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEI array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelEJ(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEJ array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelEK(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEK array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelEP(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEP array.' + RETURN + ENDIF + ALLOCATE ( RtHS%PLinVelEQ(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEQ array.' + RETURN + ENDIF + + ALLOCATE ( RtHS%PLinVelEU(p%NDOF,0:1,3) , & + RtHS%PLinVelEV(p%NDOF,0:1,3) , & + RtHS%PLinVelEW(p%NDOF,0:1,3) , & + RtHS%PLinVelEY(p%NDOF,0:1,3) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the PLinVelEU, PLinVelEV, PLinVelEW and PLinVelEY arrays.' + RETURN + ENDIF + + + ALLOCATE( RtHS%LinAccESt( Dims, p%NumBl, 0:p%TipNode ), STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for LinAccESt.' + RETURN + ENDIF + + ALLOCATE(RtHS%AngPosHM(Dims, p%NumBl, 0:p%TipNode), STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the AngPosHM arrays.' + RETURN + ENDIF + + !CALL AllocAry( RtHS%LinAccESt, Dims, p%NumBl, p%TipNode,'LinAccESt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + !CALL AllocAry( RtHS%LinAccETt, Dims, p%TwrNodes, 'LinAccETt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcS0B, Dims, p%NumBl,p%NDOF, 'PFrcS0B', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%FrcS0Bt, Dims, p%NumBl, 'FrcS0Bt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomH0B, Dims, p%NumBl, p%NDOF, 'PMomH0B', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%MomH0Bt, Dims, p%NumBl, 'MomH0Bt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcPRot, Dims, p%NDOF, 'PFrcPRot', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomLPRot, Dims, p%NDOF, 'PMomLPRot', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomNGnRt, Dims, p%NDOF, 'PMomNGnRt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomNTail, Dims, p%NDOF, 'PMomNTail', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcONcRt, Dims, p%NDOF, 'PFrcONcRt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomBNcRt, Dims, p%NDOF, 'PMomBNcRt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcT0Trb, Dims, p%NDOF, 'PFrcT0Trb', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomX0Trb, Dims, p%NDOF, 'PMomX0Trb', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%FSAero, Dims, p%NumBl,p%BldNodes,'FSAero', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%MMAero, Dims, p%NumBl,p%BldNodes,'MMAero', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%FSTipDrag, Dims, p%NumBl, 'FSTipDrag', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFTHydro, Dims, p%TwrNodes, p%NDOF,'PFTHydro', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMFHydro, Dims, p%TwrNodes, p%NDOF,'PMFHydro', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%FTHydrot, Dims, p%TwrNodes, 'FTHydrot', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%MFHydrot, Dims, p%TwrNodes, 'MFHydrot', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + + CALL AllocAry( RtHS%PFrcVGnRt, Dims, p%NDOF, 'PFrcVGnRt', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcWTail, Dims, p%NDOF, 'PFrcWTail', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PFrcZAll, Dims, p%NDOF, 'PFrcZAll', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( RtHS%PMomXAll, Dims, p%NDOF, 'PMomXAll', ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) RETURN + +END SUBROUTINE Alloc_RtHS +!---------------------------------------------------------------------------------------------------------------------------------- +!> This takes the tower input file data and sets the corresponding tower parameters, performing linear interpolation of the +!! input data to the specified tower mesh. +!! It requires p\%TwrFlexL, and p\%TwrNodes to be set first. +SUBROUTINE SetTowerParameters( p, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + + REAL(ReKi) :: x ! Fractional location between two points in linear interpolation + INTEGER(IntKi ) :: J ! Index for the node arrays + INTEGER(IntKi) :: InterpInd ! Index for the interpolation routine + LOGICAL :: SetAdmVals ! Logical to determine if Adams inputs should be set + + + ! Initialize data + ErrStat = ErrID_None + ErrMsg = '' + SetAdmVals = ALLOCATED( InputFileData%TwGJStif ) + + CALL Alloc_TowerParameters( p, SetAdmVals, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + !............................................................................................................................... + ! Define the tower discretization arrays: + !............................................................................................................................... + + ! DHNodes (Let's use constant-spaced nodes for now, but the rest of the code is written to handle variable-spaced nodes-- + ! this will be a future input!): + p%DHNodes = p%TwrFlexL/p%TwrNodes + + ! HNodes: + p%HNodes(1) = 0.5*p%DHNodes(1) + DO J=2,p%TwrNodes + p%HNodes(J) = p%HNodes( J - 1 ) + 0.5*( p%DHNodes(J) + p%DHNodes( J - 1 ) ) + END DO + + ! HNodesNorm: + p%HNodesNorm = p%HNodes/p%TwrFlexL + + + !............................................................................................................................... + ! Interpolate the input data to the tower discretization + !............................................................................................................................... + ! Array definitions: + + ! Input Interp Description + ! ----- ------ ----------- + ! HtFract HNodesNorm Fractional height (0 at top of rigid section, 1 at tower top) + ! TMassDen MassT Lineal mass density + ! TwFAStif StiffTFA Tower fore-aft stiffness + ! TwSSStif StiffTSS Tower side-to-side stiffness + ! TwGJStif StiffTGJ Tower torsional stiffness + ! TwEAStif StiffTEA Tower extensional stiffness + ! TwFAIner InerTFA Tower fore-aft (about yt-axis) mass inertia per unit length + ! TwSSIner InerTSS Tower side-to-side (about xt-axis) mass inertia per unit length + ! TwFAcgOf cgOffTFA Tower fore-aft mass cg offset + ! TwSScgOf cgOffTSS Tower side-to-side mass cg offset + + InterpInd = 1 + + + DO J=1,p%TwrNodes + + ! Get the index into HtFract for all of the arrays, using the NWTC Subroutine Library + p%MassT (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TMassDen, InterpInd, InputFileData%NTwInpSt ) + p%StiffTFA (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwFAStif, InterpInd, InputFileData%NTwInpSt ) + p%StiffTSS (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwSSStif, InterpInd, InputFileData%NTwInpSt ) + END DO ! J + + + IF ( SetAdmVals ) THEN ! An ADAMS model will be created; thus, read in all the cols. + DO J=1,p%TwrNodes + p%StiffTGJ (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwGJStif, InterpInd, InputFileData%NTwInpSt ) + p%StiffTEA (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwEAStif, InterpInd, InputFileData%NTwInpSt ) + p%InerTFA (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwFAIner, InterpInd, InputFileData%NTwInpSt ) + p%InerTSS (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwSSIner, InterpInd, InputFileData%NTwInpSt ) + p%cgOffTFA (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwFAcgOf, InterpInd, InputFileData%NTwInpSt ) + p%cgOffTSS (J) = InterpStp( p%HNodesNorm(J), InputFileData%HtFract, InputFileData%TwSScgOf, InterpInd, InputFileData%NTwInpSt ) + END DO ! J + END IF + + + !............................................................................................................................... + ! Set other tower parameters: + !............................................................................................................................... + + p%TTopNode = p%TwrNodes + 1 + + ! ! these are for HydroDyn ? + !p%DiamT(:) = InputFileData%TwrDiam + !p%CAT(:) = InputFileData%TwrCA + !p%CDT(:) = InputFileData%TwrCD + ! + +RETURN + + +CONTAINS +!.................................................................................................................................. + !> This subroutine is used to interpolate the arrays more efficiently (all arrays have the same X value) + !! See InterpStpReal() for comparison. This assumes we already know Ind and that + !! x = ( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + FUNCTION InterpAry( x, YAry, Ind ) + + REAL(ReKi), INTENT(IN) :: x !< the relative distance between Ind and Ind+ 1 + REAL(ReKi), INTENT(IN) :: YAry (:) !< Array of Y values to be interpolated. + INTEGER(IntKi) , INTENT(IN) :: Ind !< the index into the array + + REAL(ReKi) :: InterpAry !< the value calculated in this function + + InterpAry = ( YAry(Ind+1) - YAry(Ind) ) * x + YAry(Ind) + + END FUNCTION InterpAry + +END SUBROUTINE SetTowerParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This takes the furling input file data and sets the corresponding furling parameters. +SUBROUTINE SetFurlParameters( p, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + + REAL(ReKi) :: x ! Fractional location between two points in linear interpolation +! INTEGER(IntKi ) :: J ! Index for the node arrays +! INTEGER(IntKi) :: InterpInd ! Index for the interpolation routine + + + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + + ! Direct copy of InputFileData to parameters + + p%RFrlMass = InputFileData%RFrlMass + p%BoomMass = InputFileData%BoomMass + p%TFinMass = InputFileData%TFinMass + p%TFrlIner = InputFileData%TFrlIner + + p%RFrlMod = InputFileData%RFrlMod + p%TFrlMod = InputFileData%TFrlMod + + p%RFrlSpr = InputFileData%RFrlSpr + p%RFrlDmp = InputFileData%RFrlDmp + p%RFrlCDmp = InputFileData%RFrlCDmp + p%RFrlUSSP = InputFileData%RFrlUSSP + p%RFrlDSSP = InputFileData%RFrlDSSP + p%RFrlDSSpr= InputFileData%RFrlDSSpr + p%RFrlUSSpr= InputFileData%RFrlUSSpr + p%RFrlUSDP = InputFileData%RFrlUSDP + p%RFrlDSDP = InputFileData%RFrlDSDP + p%RFrlUSDmp= InputFileData%RFrlUSDmp + p%RFrlDSDmp= InputFileData%RFrlDSDmp + + p%TFrlSpr = InputFileData%TFrlSpr + p%TFrlDmp = InputFileData%TFrlDmp + p%TFrlCDmp = InputFileData%TFrlCDmp + p%TFrlUSSP = InputFileData%TFrlUSSP + p%TFrlDSSP = InputFileData%TFrlDSSP + p%TFrlUSSpr= InputFileData%TFrlUSSpr + p%TFrlDSSpr= InputFileData%TFrlDSSpr + p%TFrlUSDP = InputFileData%TFrlUSDP + p%TFrlDSDP = InputFileData%TFrlDSDP + p%TFrlUSDmp= InputFileData%TFrlUSDmp + p%TFrlDSDmp= InputFileData%TFrlDSDmp + + p%RFrlPntxn = InputFileData%RFrlPntxn + p%RFrlPntyn = InputFileData%RFrlPntyn + p%RFrlPntzn = InputFileData%RFrlPntzn + + p%TFrlPntxn = InputFileData%TFrlPntxn + p%TFrlPntyn = InputFileData%TFrlPntyn + p%TFrlPntzn = InputFileData%TFrlPntzn + + + ! Store sine/cosine values instead of some input angles: + + p%CShftSkew = COS( REAL(InputFileData%ShftSkew,R8Ki) ) + p%SShftSkew = SIN( REAL(InputFileData%ShftSkew,R8Ki) ) + + p%CTFinSkew = COS( REAL(InputFileData%TFinSkew, R8Ki) ) + p%STFinSkew = SIN( REAL(InputFileData%TFinSkew, R8Ki) ) + p%CTFinTilt = COS( REAL(InputFileData%TFinTilt, R8Ki) ) + p%STFinTilt = SIN( REAL(InputFileData%TFinTilt, R8Ki) ) + p%CTFinBank = COS( REAL(InputFileData%TFinBank, R8Ki) ) + p%STFinBank = SIN( REAL(InputFileData%TFinBank, R8Ki) ) + + p%CRFrlSkew = COS( REAL(InputFileData%RFrlSkew, R8Ki) ) + p%SRFrlSkew = SIN( REAL(InputFileData%RFrlSkew, R8Ki) ) + p%CRFrlTilt = COS( REAL(InputFileData%RFrlTilt, R8Ki) ) + p%SRFrlTilt = SIN( REAL(InputFileData%RFrlTilt, R8Ki) ) + + p%CTFrlSkew = COS( REAL(InputFileData%TFrlSkew, R8Ki) ) + p%STFrlSkew = SIN( REAL(InputFileData%TFrlSkew, R8Ki) ) + p%CTFrlTilt = COS( REAL(InputFileData%TFrlTilt, R8Ki) ) + p%STFrlTilt = SIN( REAL(InputFileData%TFrlTilt, R8Ki) ) + + + ! Common multiplications of sines and cosines: + + p%CRFrlSkw2 = p%CRFrlSkew**2 + p%SRFrlSkw2 = p%SRFrlSkew**2 + p%CSRFrlSkw = p%CRFrlSkew*p%SRFrlSkew + p%CRFrlTlt2 = p%CRFrlTilt**2 + p%SRFrlTlt2 = p%SRFrlTilt**2 + p%CSRFrlTlt = p%CRFrlTilt*p%SRFrlTilt + + p%CTFrlSkw2 = p%CTFrlSkew**2 + p%STFrlSkw2 = p%STFrlSkew**2 + p%CSTFrlSkw = p%CTFrlSkew*p%STfrlSkew + p%CTFrlTlt2 = p%CTFrlTilt**2 + p%STFrlTlt2 = p%STFrlTilt**2 + p%CSTFrlTlt = p%CTFrlTilt*p%STFrlTilt + + + ! Calculate some positions: + + p%rWIxn = InputFileData%BoomCMxn - p%TFrlPntxn + p%rWIyn = InputFileData%BoomCMyn - p%TFrlPntyn + p%rWIzn = InputFileData%BoomCMzn - p%TFrlPntzn + + p%rWJxn = InputFileData%TFinCMxn - p%TFrlPntxn + p%rWJyn = InputFileData%TFinCMyn - p%TFrlPntyn + p%rWJzn = InputFileData%TFinCMzn - p%TFrlPntzn + + p%rWKxn = InputFileData%TFinCPxn - p%TFrlPntxn + p%rWKyn = InputFileData%TFinCPyn - p%TFrlPntyn + p%rWKzn = InputFileData%TFinCPzn - p%TFrlPntzn + + p%rVDxn = InputFileData%RFrlCMxn - p%RFrlPntxn + p%rVDyn = InputFileData%RFrlCMyn - p%RFrlPntyn + p%rVDzn = InputFileData%RFrlCMzn - p%RFrlPntzn + + p%rVPxn = 0.0_ReKi - p%RFrlPntxn + p%rVPyn = InputFileData%Yaw2Shft - p%RFrlPntyn + + + ! Note: These positions are also used for non-furling machines: + + p%rVPzn = InputFileData%Twr2Shft - p%RFrlPntzn + p%rVIMUxn = InputFileData%NcIMUxn - p%RFrlPntxn + p%rVIMUyn = InputFileData%NcIMUyn - p%RFrlPntyn + p%rVIMUzn = InputFileData%NcIMUzn - p%RFrlPntzn + +END SUBROUTINE SetFurlParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This takes the primary input file data and sets the corresponding parameters. +SUBROUTINE SetPrimaryParameters( p, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + +!bjj: ERROR CHECKING!!! + + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + !p%Twr2Shft = InputFileData%Twr2Shft + !p%HubIner = InputFileData%HubIner + !p%NacYIner = InputFileData%NacYIner + + + !............................................................................................................................... + ! Direct copy of variables: + !............................................................................................................................... + p%NumBl = InputFileData%NumBl + p%TipRad = InputFileData%TipRad + p%HubRad = InputFileData%HubRad + p%method = InputFileData%method + p%TwrNodes = InputFileData%TwrNodes + + p%PtfmCMxt = InputFileData%PtfmCMxt + p%PtfmCMyt = InputFileData%PtfmCMyt + + p%DT = InputFileData%DT + p%Gravity = InputFileData%Gravity + p%OverHang = InputFileData%OverHang + p%ShftGagL = InputFileData%ShftGagL + p%TowerHt = InputFileData%TowerHt + p%TowerBsHt = InputFileData%TowerBsHt + p%PtfmRefzt = InputFileData%PtfmRefzt + + p%HubMass = InputFileData%HubMass + p%GenIner = InputFileData%GenIner + p%NacMass = InputFileData%NacMass + p%YawBrMass = InputFileData%YawBrMass + p%PtfmMass = InputFileData%PtfmMass + p%PtfmRIner = InputFileData%PtfmRIner + p%PtfmPIner = InputFileData%PtfmPIner + p%PtfmYIner = InputFileData%PtfmYIner + p%GBoxEff = InputFileData%GBoxEff + p%GBRatio = InputFileData%GBRatio + p%DTTorSpr = InputFileData%DTTorSpr + p%DTTorDmp = InputFileData%DTTorDmp + + + p%NTwGages = InputFileData%NTwGages + p%TwrGagNd = InputFileData%TwrGagNd + p%NBlGages = InputFileData%NBlGages + p%BldGagNd = InputFileData%BldGagNd + !p%OutFile = InputFileData%OutFile + !p%OutFileFmt= InputFileData%OutFileFmt !wrbinoutput, wrtxtoutput??? + p%OutFmt = InputFileData%OutFmt + p%Tstart = InputFileData%Tstart + !p%DecFact = InputFileData%DecFact + p%NumOuts = InputFileData%NumOuts + + IF ( p%NumBl == 2 ) THEN + p%UndSling = InputFileData%UndSling + p%TeetMod = InputFileData%TeetMod + p%TeetDmpP = InputFileData%TeetDmpP + p%TeetDmp = InputFileData%TeetDmp + p%TeetCDmp = InputFileData%TeetCDmp + p%TeetSStP = InputFileData%TeetSStP + p%TeetHStP = InputFileData%TeetHStP + p%TeetSSSp = InputFileData%TeetSSSp + p%TeetHSSp = InputFileData%TeetHSSp + ELSE ! Three-bladed turbines don't use these parameters, so set them to zero. + p%UndSling = 0.0 + p%TeetMod = 0 + p%TeetDmpP = 0.0 + p%TeetDmp = 0.0 + p%TeetCDmp = 0.0 + p%TeetSStP = 0.0 + p%TeetHStP = 0.0 + p%TeetSSSp = 0.0 + p%TeetHSSp = 0.0 + END IF + + + CALL AllocAry( p%TipMass, p%NumBl, 'TipMass', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + p%TipMass = InputFileData%TipMass + + ! initialize all of the DOF parameters: + CALL Init_DOFparameters( InputFileData, p, ErrStat, ErrMsg ) !sets p%NDOF and p%NAug + IF (ErrStat >= AbortErrLev) RETURN + + ! Set parameters for output channels: + CALL SetOutParam(InputFileData%OutList, p, ErrStat, ErrMsg ) ! requires: p%NumOuts, p%NumBl, p%NBlGages, p%NTwGages; sets: p%OutParam. + IF (ErrStat >= AbortErrLev) RETURN + + IF ( InputFileData%TabDelim ) THEN + p%Delim = TAB + ELSE + p%Delim = ' ' + !ELSE + ! p%Delim = ',' + END IF + + !............................................................................................................................... + ! Calculate some indirect inputs: + !............................................................................................................................... + p%TwoPiNB = TwoPi_D/p%NumBl ! 2*Pi/NumBl is used in RtHS(). + + p%rZT0zt = p%TowerBsHt - p%PtfmRefzt ! zt-component of position vector rZT0. + p%RefTwrHt = p%TowerHt - p%PtfmRefzt ! Vertical distance between ElastoDyn's undisplaced tower height (variable TowerHt) and ElastoDyn's inertia frame reference point (variable PtfmRef). + p%TwrFlexL = p%TowerHt - p%TowerBsHt ! Height / length of the flexible portion of the tower. + p%BldFlexL = p%TipRad - p%HubRad ! Length of the flexible portion of the blade. + if (p%BD4Blades) p%BldFlexL = 0.0_ReKi + + p%rZYzt = InputFileData%PtfmCMzt - p%PtfmRefzt + + !............................................................................................................................... + ! set cosine and sine of Precone and Delta3 angles: + !............................................................................................................................... + CALL AllocAry( p%CosPreC, p%NumBl, 'CosPreC', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( p%SinPreC, p%NumBl, 'SinPreC', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + p%CosPreC = COS( REAL(InputFileData%Precone(1:p%NumBl),R8Ki) ) + p%SinPreC = SIN( REAL(InputFileData%Precone(1:p%NumBl),R8Ki) ) + + IF ( p%NumBl == 2 ) THEN + p%CosDel3 = COS( REAL(InputFileData%Delta3,R8Ki) ) + p%SinDel3 = SIN( REAL(InputFileData%Delta3,R8Ki) ) + ELSE + p%CosDel3 = 1.0_R8Ki + p%SinDel3 = 0.0_R8Ki + END IF + + !............................................................................................................................... + + ! Calculate the average tip radius normal to the shaft (AvgNrmTpRd) + ! and the swept area of the rotor (ProjArea): + + p%AvgNrmTpRd = p%TipRad*SUM(p%CosPreC)/p%NumBl ! Average tip radius normal to the saft. + p%ProjArea = pi*( p%AvgNrmTpRd**2 ) ! Swept area of the rotor projected onto the rotor plane (the plane normal to the low-speed shaft). + + p%RotSpeed = InputFileData%RotSpeed ! Rotor speed in rad/sec. + p%CShftTilt = COS( REAL(InputFileData%ShftTilt,R8Ki) ) + p%SShftTilt = SIN( REAL(InputFileData%ShftTilt,R8Ki) ) + + p%HubHt = p%TowerHt + InputFileData%Twr2Shft + p%OverHang*p%SShftTilt + + + ! Direct copy of InputFileData to parameters + + !p%FlapDOF1 = InputFileData%FlapDOF1 + !p%FlapDOF2 = InputFileData%FlapDOF2 + !p%EdgeDOF = InputFileData%EdgeDOF + !p%TeetDOF = InputFileData%TeetDOF + !p%DrTrDOF = InputFileData%DrTrDOF + !p%GenDOF = InputFileData%GenDOF + !p%YawDOF = InputFileData%YawDOF + !p%TwFADOF1 = InputFileData%TwFADOF1 + !p%TwFADOF2 = InputFileData%TwFADOF2 + !p%TwSSDOF1 = InputFileData%TwSSDOF1 + !p%TwSSDOF2 = InputFileData%TwSSDOF2 + !p%PtfmSgDOF = InputFileData%PtfmSgDOF + !p%PtfmSwDOF = InputFileData%PtfmSwDOF + !p%PtfmHvDOF = InputFileData%PtfmHvDOF + !p%PtfmRDOF = InputFileData%PtfmRDOF + !p%PtfmPDOF = InputFileData%PtfmPDOF + !p%PtfmYDOF = InputFileData%PtfmYDOF + !p%Azimuth = InputFileData%Azimuth + p%RotSpeed = InputFileData%RotSpeed + !p%TTDspFA = InputFileData%TTDspFA + !p%TTDspSS = InputFileData%TTDspSS + !p%PtfmSurge = InputFileData%PtfmSurge + !p%PtfmSway = InputFileData%PtfmSway + !p%PtfmHeave = InputFileData%PtfmHeave + !p%PtfmRoll = InputFileData%PtfmRoll + !p%PtfmPitch = InputFileData%PtfmPitch + !p%PtfmYaw = InputFileData%PtfmYaw + p%HubCM = InputFileData%HubCM + p%AzimB1Up = InputFileData%AzimB1Up + + p%NacCMxn = InputFileData%NacCMxn + p%NacCMyn = InputFileData%NacCMyn + p%NacCMzn = InputFileData%NacCMzn + !p%NcIMUxn = InputFileData%NcIMUxn + !p%NcIMUyn = InputFileData%NcIMUyn + !p%NcIMUzn = InputFileData%NcIMUzn + + + ! plus everything else from FAST_Initialize + + + +END SUBROUTINE SetPrimaryParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the continuous states of the module. +!! It assumes the parameters are set and that InputFileData contains initial conditions for the continuous states. +SUBROUTINE Init_ContStates( x, p, InputFileData, OtherState, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(ED_ContinuousStateType), INTENT(OUT) :: x !< Initial continuous states + TYPE(ED_ParameterType), INTENT(IN) :: p !< Parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + TYPE(ED_OtherStateType), INTENT(IN) :: OtherState !< Initial other states + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! local variables + REAL(ReKi) :: InitQE1(p%NumBl) ! Initial value of the 1st blade edge DOF + REAL(ReKi) :: InitQF1(p%NumBl) ! Initial value of the 1st blade flap DOF + REAL(ReKi) :: InitQF2(p%NumBl) ! Initial value of the 2nd blade flap DOF +! INTEGER(IntKi) :: I ! loop counter + + + ! First allocate the arrays stored here: + + CALL AllocAry( x%QT, p%NDOF, 'QT', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL AllocAry( x%QDT, p%NDOF, 'QDT', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + ! Calculate/apply the initial blade DOF values to the corresponding DOFs. + IF (.NOT. p%BD4Blades) THEN !Skipping subroutine if BeamDyn = TRUE + CALL InitBlDefl ( p, InputFileData, InitQF1, InitQF2, InitQE1, ErrStat, ErrMsg ) + ELSE + InitQF1 = 0.0_ReKi + InitQF2 = 0.0_ReKi + InitQE1 = 0.0_ReKi + END IF + + + x%QT ( DOF_BF(1:p%NumBl,1) ) = InitQF1 ! These come from InitBlDefl(). + x%QT ( DOF_BF(1:p%NumBl,2) ) = InitQF2 ! These come from InitBlDefl(). + x%QT ( DOF_BE(1:p%NumBl,1) ) = InitQE1 ! These come from InitBlDefl(). + x%QDT( DOF_BF(1:p%NumBl,1) ) = 0.0 + x%QDT( DOF_BF(1:p%NumBl,2) ) = 0.0 + x%QDT( DOF_BE(1:p%NumBl,1) ) = 0.0 + + ! Teeter Motion + + IF ( p%NumBl == 2 ) THEN !note, DOF_Teet doesn't exist for 3-bladed turbine, so don't include an ELSE here + + ! Set initial teeter angle to TeetDefl and initial teeter angular velocity to 0. + + x%QT (DOF_Teet) = InputFileData%TeetDefl + x%QDT(DOF_Teet) = 0.0 + ENDIF + + ! Generator azimuth + + ! Set initial generator azimuth angle. Turn rotor on, whether it is + ! fixed or variable speed. If it is fixed speed, set up the + ! fixed rpm. + + !JASON: CHANGE THESE MOD() FUNCTIONS INTO MODULO() FUNCTIONS SO THAT YOU CAN ELIMINATE ADDING 360: +! x%QT (DOF_GeAz) = MOD( (InputFileData%Azimuth - p%AzimB1Up)*R2D + 270.0 + 360.0, 360.0 )*D2R ! Internal position of blade 1 + + x%QT (DOF_GeAz) = REAL(InputFileData%Azimuth, R8Ki) - p%AzimB1Up - REAL(Piby2_D, R8Ki) + CALL Zero2TwoPi( x%QT (DOF_GeAz) ) + x%QDT(DOF_GeAz) = p%RotSpeed ! Rotor speed in rad/sec. + + + ! Shaft compliance + + ! The initial shaft compliance displacements and velocities are all zero. + ! They will remain zero if the drivetrain DOF is disabled: + + x%QT (DOF_DrTr) = 0.0 + x%QDT(DOF_DrTr) = 0.0 + + + + + ! Rotor-furl motion + + ! Set initial rotor-furl angle to RotFurl. If rotor-furl is off, this + ! becomes a fixed rotor-furl angle. + + x%QT (DOF_RFrl) = InputFileData%RotFurl + x%QDT(DOF_RFrl) = 0.0 + + + + ! Tail-furl motion + + ! Set initial tail-furl angle to TailFurl. If tail-furl is off, this becomes a fixed tail-furl angle. + + x%QT (DOF_TFrl) = InputFileData%TailFurl + x%QDT(DOF_TFrl) = 0.0 + + + + ! Yaw Motion + + ! Set initial yaw angle to NacYaw. If yaw is off, this becomes a fixed yaw angle. + + x%QT (DOF_Yaw) = InputFileData%NacYaw + x%QDT(DOF_Yaw) = 0.0 + + + + ! Tower motion + + ! Assign all the displacements to mode 1 unless it is disabled. If mode 1 + ! is disabled and mode 2 is enabled, assign all displacements to mode 2. + ! If both modes are disabled, set the displacements to zero. + + x%QT (DOF_TFA1) = 0.0 + x%QT (DOF_TSS1) = 0.0 + x%QT (DOF_TFA2) = 0.0 + x%QT (DOF_TSS2) = 0.0 + + IF ( InputFileData%TwFADOF1 ) THEN ! First fore-aft tower mode is enabled. + x%QT(DOF_TFA1) = InputFileData%TTDspFA + ELSEIF( InputFileData%TwFADOF2 ) THEN ! Second fore-aft tower mode is enabled, but first is not. + x%QT(DOF_TFA2) = InputFileData%TTDspFA + ENDIF + + IF ( InputFileData%TwSSDOF1 ) THEN ! First side-to-side tower mode is enabled. + x%QT(DOF_TSS1) = -InputFileData%TTDspSS + ELSEIF( InputFileData%TwSSDOF2 ) THEN ! Second side-to-side tower mode is enabled, but first is not. + x%QT(DOF_TSS2) = -InputFileData%TTDspSS + ENDIF + + x%QDT (DOF_TFA1) = 0.0 + x%QDT (DOF_TSS1) = 0.0 + x%QDT (DOF_TFA2) = 0.0 + x%QDT (DOF_TSS2) = 0.0 + + + + ! Platform Motion + + ! Set initial platform displacements. If platform DOFs are off, these + ! become fixed platform displacements. + + x%QT (DOF_Sg) = InputFileData%PtfmSurge + x%QT (DOF_Sw) = InputFileData%PtfmSway + x%QT (DOF_Hv) = InputFileData%PtfmHeave + x%QT (DOF_R ) = InputFileData%PtfmRoll + x%QT (DOF_P ) = InputFileData%PtfmPitch + x%QT (DOF_Y ) = InputFileData%PtfmYaw + x%QDT(DOF_Sg) = 0.0 + x%QDT(DOF_Sw) = 0.0 + x%QDT(DOF_Hv) = 0.0 + x%QDT(DOF_R ) = 0.0 + x%QDT(DOF_P ) = 0.0 + x%QDT(DOF_Y ) = 0.0 + + + + +END SUBROUTINE Init_ContStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the other states of the module. +!! It assumes the parameters are set and that InputFileData contains initial conditions for the continuous states. and p%NumBl is set +SUBROUTINE Init_MiscOtherStates( m, OtherState, p, x, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(ED_MiscVarType), INTENT(OUT) :: m !< Initial misc variables + TYPE(ED_OtherStateType), INTENT(OUT) :: OtherState !< Initial other states + TYPE(ED_ParameterType), INTENT(IN) :: p !< Parameters of the structural dynamics module + TYPE(ED_ContinuousStateType), INTENT(IN) :: x !< Initial continuous states + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + INTEGER(IntKi) :: I ! Generic loop counter. + + ! First allocate the arrays stored here: + + CALL Alloc_RtHS( m%RtHS, p, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL Alloc_CoordSys( m%CoordSys, p, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( m%QD2T, p%NDOF, 'm%QD2T', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ALLOCATE ( m%AllOuts(0:MaxOutPts) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the AllOuts array.' + RETURN + ENDIF + m%AllOuts = 0.0_ReKi + + m%IgnoreMod = .false. ! for general time steps, we don't ignore the modulos in ED_CalcOutput + + ! for loose coupling: + CALL AllocAry( OtherState%IC, ED_NMX, 'IC', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + + !CALL AllocAry(OtherState%BlPitch, p%NumBl, 'BlPitch', ErrStat, ErrMsg ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + ! OtherState%BlPitch = InputFileData%BlPitch(1:p%NumBl) + + CALL AllocAry( m%AugMat, p%NDOF, p%NAug, 'AugMat', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL AllocAry( m%OgnlGeAzRo, p%NAug, 'OgnlGeAzRo', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL AllocAry( m%SolnVec, p%DOFs%NActvDOF, 'SolnVec', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL AllocAry( m%AugMat_pivot, p%DOFs%NActvDOF, 'AugMat_pivot', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL AllocAry( m%AugMat_factor,p%DOFs%NActvDOF, p%DOFs%NActvDOF, 'AugMat_factor',ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Now initialize the IC array = (/NMX, NMX-1, ... , 1 /) + ! this keeps track of the position in the array of continuous states (stored in other states) + + OtherState%IC(1) = ED_NMX + DO I = 2,ED_NMX + OtherState%IC(I) = OtherState%IC(I-1) - 1 + ENDDO + + + ! ! Initialize the accelerations to zero. + ! + !OtherState%QD2 = 0.0_ReKi + + + OtherState%n = -1 ! we haven't updated OtherState%xdot, yet + + DO i = LBOUND(OtherState%xdot,1), UBOUND(OtherState%xdot,1) + CALL ED_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + ENDDO + + ! hacks for HSS brake function: + + OtherState%HSSBrTrq = 0.0_ReKi + OtherState%HSSBrTrqC = 0.0_ReKi + OtherState%SgnPrvLSTQ = 1 + OtherState%SgnLSTQ = 1 + + +END SUBROUTINE Init_MiscOtherStates + +!---------------------------------------------------------------------------------------------------------------------------------- + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 08-Jun-2020 17:05:31. +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + TYPE(ED_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 + + ! Local variables + + INTEGER :: ErrStat2 ! temporary (local) error status + INTEGER :: I ! Generic loop-counting index + INTEGER :: J ! Generic loop-counting index + INTEGER :: INDX ! Index for valid arrays + INTEGER :: startIndx ! Index for BeamDyn + + LOGICAL :: CheckOutListAgain ! Flag used to determine if output parameter starting with "M" is valid (or the negative of another parameter) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(978) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "AZIMUTH ","BLDPITCH1","BLDPITCH2","BLDPITCH3","BLPITCH1 ","BLPITCH2 ","BLPITCH3 ", & + "GENACCEL ","GENSPEED ","HSSBRTQ ","HSSHFTA ","HSSHFTPWR","HSSHFTTQ ","HSSHFTV ", & + "IPDEFL1 ","IPDEFL2 ","IPDEFL3 ","LSSGAGA ","LSSGAGAXA","LSSGAGAXS","LSSGAGFXA", & + "LSSGAGFXS","LSSGAGFYA","LSSGAGFYS","LSSGAGFZA","LSSGAGFZS","LSSGAGMXA","LSSGAGMXS", & + "LSSGAGMYA","LSSGAGMYS","LSSGAGMZA","LSSGAGMZS","LSSGAGP ","LSSGAGPXA","LSSGAGPXS", & + "LSSGAGV ","LSSGAGVXA","LSSGAGVXS","LSSHFTFXA","LSSHFTFXS","LSSHFTFYA","LSSHFTFYS", & + "LSSHFTFZA","LSSHFTFZS","LSSHFTMXA","LSSHFTMXS","LSSHFTPWR","LSSHFTTQ ","LSSTIPA ", & + "LSSTIPAXA","LSSTIPAXS","LSSTIPMYA","LSSTIPMYS","LSSTIPMZA","LSSTIPMZS","LSSTIPP ", & + "LSSTIPPXA","LSSTIPPXS","LSSTIPV ","LSSTIPVXA","LSSTIPVXS","NACYAW ","NACYAWA ", & + "NACYAWP ","NACYAWV ","NCIMURAXS","NCIMURAYS","NCIMURAZS","NCIMURVXS","NCIMURVYS", & + "NCIMURVZS","NCIMUTAXS","NCIMUTAYS","NCIMUTAZS","NCIMUTVXS","NCIMUTVYS","NCIMUTVZS", & + "OOPDEFL1 ","OOPDEFL2 ","OOPDEFL3 ","PTCHDEFL1","PTCHDEFL2","PTCHDEFL3","PTCHPMZB1", & + "PTCHPMZB2","PTCHPMZB3","PTCHPMZC1","PTCHPMZC2","PTCHPMZC3","PTFMHEAVE","PTFMPITCH", & + "PTFMRAXI ","PTFMRAXT ","PTFMRAYI ","PTFMRAYT ","PTFMRAZI ","PTFMRAZT ","PTFMRDXI ", & + "PTFMRDYI ","PTFMRDZI ","PTFMROLL ","PTFMRVXI ","PTFMRVXT ","PTFMRVYI ","PTFMRVYT ", & + "PTFMRVZI ","PTFMRVZT ","PTFMSURGE","PTFMSWAY ","PTFMTAXI ","PTFMTAXT ","PTFMTAYI ", & + "PTFMTAYT ","PTFMTAZI ","PTFMTAZT ","PTFMTDXI ","PTFMTDXT ","PTFMTDYI ","PTFMTDYT ", & + "PTFMTDZI ","PTFMTDZT ","PTFMTVXI ","PTFMTVXT ","PTFMTVYI ","PTFMTVYT ","PTFMTVZI ", & + "PTFMTVZT ","PTFMYAW ","QD2_B1E1 ","QD2_B1F1 ","QD2_B1F2 ","QD2_B2E1 ","QD2_B2F1 ", & + "QD2_B2F2 ","QD2_B3E1 ","QD2_B3F1 ","QD2_B3F2 ","QD2_DRTR ","QD2_GEAZ ","QD2_HV ", & + "QD2_P ","QD2_R ","QD2_RFRL ","QD2_SG ","QD2_SW ","QD2_TEET ","QD2_TFA1 ", & + "QD2_TFA2 ","QD2_TFRL ","QD2_TSS1 ","QD2_TSS2 ","QD2_Y ","QD2_YAW ","QD_B1E1 ", & + "QD_B1F1 ","QD_B1F2 ","QD_B2E1 ","QD_B2F1 ","QD_B2F2 ","QD_B3E1 ","QD_B3F1 ", & + "QD_B3F2 ","QD_DRTR ","QD_GEAZ ","QD_HV ","QD_P ","QD_R ","QD_RFRL ", & + "QD_SG ","QD_SW ","QD_TEET ","QD_TFA1 ","QD_TFA2 ","QD_TFRL ","QD_TSS1 ", & + "QD_TSS2 ","QD_Y ","QD_YAW ","Q_B1E1 ","Q_B1F1 ","Q_B1F2 ","Q_B2E1 ", & + "Q_B2F1 ","Q_B2F2 ","Q_B3E1 ","Q_B3F1 ","Q_B3F2 ","Q_DRTR ","Q_GEAZ ", & + "Q_HV ","Q_P ","Q_R ","Q_RFRL ","Q_SG ","Q_SW ","Q_TEET ", & + "Q_TFA1 ","Q_TFA2 ","Q_TFRL ","Q_TSS1 ","Q_TSS2 ","Q_Y ","Q_YAW ", & + "RFRLBRM ","ROLLDEFL1","ROLLDEFL2","ROLLDEFL3","ROOTFXB1 ","ROOTFXB2 ","ROOTFXB3 ", & + "ROOTFXC1 ","ROOTFXC2 ","ROOTFXC3 ","ROOTFYB1 ","ROOTFYB2 ","ROOTFYB3 ","ROOTFYC1 ", & + "ROOTFYC2 ","ROOTFYC3 ","ROOTFZB1 ","ROOTFZB2 ","ROOTFZB3 ","ROOTFZC1 ","ROOTFZC2 ", & + "ROOTFZC3 ","ROOTMEDG1","ROOTMEDG2","ROOTMEDG3","ROOTMFLP1","ROOTMFLP2","ROOTMFLP3", & + "ROOTMIP1 ","ROOTMIP2 ","ROOTMIP3 ","ROOTMOOP1","ROOTMOOP2","ROOTMOOP3","ROOTMXB1 ", & + "ROOTMXB2 ","ROOTMXB3 ","ROOTMXC1 ","ROOTMXC2 ","ROOTMXC3 ","ROOTMYB1 ","ROOTMYB2 ", & + "ROOTMYB3 ","ROOTMYC1 ","ROOTMYC2 ","ROOTMYC3 ","ROOTMZB1 ","ROOTMZB2 ","ROOTMZB3 ", & + "ROOTMZC1 ","ROOTMZC2 ","ROOTMZC3 ","ROTACCEL ","ROTFURL ","ROTFURLA ","ROTFURLP ", & + "ROTFURLV ","ROTPWR ","ROTSPEED ","ROTTEETA ","ROTTEETP ","ROTTEETV ","ROTTHRUST", & + "ROTTORQ ","SPN1ALXB1","SPN1ALXB2","SPN1ALXB3","SPN1ALYB1","SPN1ALYB2","SPN1ALYB3", & + "SPN1ALZB1","SPN1ALZB2","SPN1ALZB3","SPN1FLXB1","SPN1FLXB2","SPN1FLXB3","SPN1FLYB1", & + "SPN1FLYB2","SPN1FLYB3","SPN1FLZB1","SPN1FLZB2","SPN1FLZB3","SPN1MLXB1","SPN1MLXB2", & + "SPN1MLXB3","SPN1MLYB1","SPN1MLYB2","SPN1MLYB3","SPN1MLZB1","SPN1MLZB2","SPN1MLZB3", & + "SPN1RDXB1","SPN1RDXB2","SPN1RDXB3","SPN1RDYB1","SPN1RDYB2","SPN1RDYB3","SPN1RDZB1", & + "SPN1RDZB2","SPN1RDZB3","SPN1TDXB1","SPN1TDXB2","SPN1TDXB3","SPN1TDYB1","SPN1TDYB2", & + "SPN1TDYB3","SPN1TDZB1","SPN1TDZB2","SPN1TDZB3","SPN2ALXB1","SPN2ALXB2","SPN2ALXB3", & + "SPN2ALYB1","SPN2ALYB2","SPN2ALYB3","SPN2ALZB1","SPN2ALZB2","SPN2ALZB3","SPN2FLXB1", & + "SPN2FLXB2","SPN2FLXB3","SPN2FLYB1","SPN2FLYB2","SPN2FLYB3","SPN2FLZB1","SPN2FLZB2", & + "SPN2FLZB3","SPN2MLXB1","SPN2MLXB2","SPN2MLXB3","SPN2MLYB1","SPN2MLYB2","SPN2MLYB3", & + "SPN2MLZB1","SPN2MLZB2","SPN2MLZB3","SPN2RDXB1","SPN2RDXB2","SPN2RDXB3","SPN2RDYB1", & + "SPN2RDYB2","SPN2RDYB3","SPN2RDZB1","SPN2RDZB2","SPN2RDZB3","SPN2TDXB1","SPN2TDXB2", & + "SPN2TDXB3","SPN2TDYB1","SPN2TDYB2","SPN2TDYB3","SPN2TDZB1","SPN2TDZB2","SPN2TDZB3", & + "SPN3ALXB1","SPN3ALXB2","SPN3ALXB3","SPN3ALYB1","SPN3ALYB2","SPN3ALYB3","SPN3ALZB1", & + "SPN3ALZB2","SPN3ALZB3","SPN3FLXB1","SPN3FLXB2","SPN3FLXB3","SPN3FLYB1","SPN3FLYB2", & + "SPN3FLYB3","SPN3FLZB1","SPN3FLZB2","SPN3FLZB3","SPN3MLXB1","SPN3MLXB2","SPN3MLXB3", & + "SPN3MLYB1","SPN3MLYB2","SPN3MLYB3","SPN3MLZB1","SPN3MLZB2","SPN3MLZB3","SPN3RDXB1", & + "SPN3RDXB2","SPN3RDXB3","SPN3RDYB1","SPN3RDYB2","SPN3RDYB3","SPN3RDZB1","SPN3RDZB2", & + "SPN3RDZB3","SPN3TDXB1","SPN3TDXB2","SPN3TDXB3","SPN3TDYB1","SPN3TDYB2","SPN3TDYB3", & + "SPN3TDZB1","SPN3TDZB2","SPN3TDZB3","SPN4ALXB1","SPN4ALXB2","SPN4ALXB3","SPN4ALYB1", & + "SPN4ALYB2","SPN4ALYB3","SPN4ALZB1","SPN4ALZB2","SPN4ALZB3","SPN4FLXB1","SPN4FLXB2", & + "SPN4FLXB3","SPN4FLYB1","SPN4FLYB2","SPN4FLYB3","SPN4FLZB1","SPN4FLZB2","SPN4FLZB3", & + "SPN4MLXB1","SPN4MLXB2","SPN4MLXB3","SPN4MLYB1","SPN4MLYB2","SPN4MLYB3","SPN4MLZB1", & + "SPN4MLZB2","SPN4MLZB3","SPN4RDXB1","SPN4RDXB2","SPN4RDXB3","SPN4RDYB1","SPN4RDYB2", & + "SPN4RDYB3","SPN4RDZB1","SPN4RDZB2","SPN4RDZB3","SPN4TDXB1","SPN4TDXB2","SPN4TDXB3", & + "SPN4TDYB1","SPN4TDYB2","SPN4TDYB3","SPN4TDZB1","SPN4TDZB2","SPN4TDZB3","SPN5ALXB1", & + "SPN5ALXB2","SPN5ALXB3","SPN5ALYB1","SPN5ALYB2","SPN5ALYB3","SPN5ALZB1","SPN5ALZB2", & + "SPN5ALZB3","SPN5FLXB1","SPN5FLXB2","SPN5FLXB3","SPN5FLYB1","SPN5FLYB2","SPN5FLYB3", & + "SPN5FLZB1","SPN5FLZB2","SPN5FLZB3","SPN5MLXB1","SPN5MLXB2","SPN5MLXB3","SPN5MLYB1", & + "SPN5MLYB2","SPN5MLYB3","SPN5MLZB1","SPN5MLZB2","SPN5MLZB3","SPN5RDXB1","SPN5RDXB2", & + "SPN5RDXB3","SPN5RDYB1","SPN5RDYB2","SPN5RDYB3","SPN5RDZB1","SPN5RDZB2","SPN5RDZB3", & + "SPN5TDXB1","SPN5TDXB2","SPN5TDXB3","SPN5TDYB1","SPN5TDYB2","SPN5TDYB3","SPN5TDZB1", & + "SPN5TDZB2","SPN5TDZB3","SPN6ALXB1","SPN6ALXB2","SPN6ALXB3","SPN6ALYB1","SPN6ALYB2", & + "SPN6ALYB3","SPN6ALZB1","SPN6ALZB2","SPN6ALZB3","SPN6FLXB1","SPN6FLXB2","SPN6FLXB3", & + "SPN6FLYB1","SPN6FLYB2","SPN6FLYB3","SPN6FLZB1","SPN6FLZB2","SPN6FLZB3","SPN6MLXB1", & + "SPN6MLXB2","SPN6MLXB3","SPN6MLYB1","SPN6MLYB2","SPN6MLYB3","SPN6MLZB1","SPN6MLZB2", & + "SPN6MLZB3","SPN6RDXB1","SPN6RDXB2","SPN6RDXB3","SPN6RDYB1","SPN6RDYB2","SPN6RDYB3", & + "SPN6RDZB1","SPN6RDZB2","SPN6RDZB3","SPN6TDXB1","SPN6TDXB2","SPN6TDXB3","SPN6TDYB1", & + "SPN6TDYB2","SPN6TDYB3","SPN6TDZB1","SPN6TDZB2","SPN6TDZB3","SPN7ALXB1","SPN7ALXB2", & + "SPN7ALXB3","SPN7ALYB1","SPN7ALYB2","SPN7ALYB3","SPN7ALZB1","SPN7ALZB2","SPN7ALZB3", & + "SPN7FLXB1","SPN7FLXB2","SPN7FLXB3","SPN7FLYB1","SPN7FLYB2","SPN7FLYB3","SPN7FLZB1", & + "SPN7FLZB2","SPN7FLZB3","SPN7MLXB1","SPN7MLXB2","SPN7MLXB3","SPN7MLYB1","SPN7MLYB2", & + "SPN7MLYB3","SPN7MLZB1","SPN7MLZB2","SPN7MLZB3","SPN7RDXB1","SPN7RDXB2","SPN7RDXB3", & + "SPN7RDYB1","SPN7RDYB2","SPN7RDYB3","SPN7RDZB1","SPN7RDZB2","SPN7RDZB3","SPN7TDXB1", & + "SPN7TDXB2","SPN7TDXB3","SPN7TDYB1","SPN7TDYB2","SPN7TDYB3","SPN7TDZB1","SPN7TDZB2", & + "SPN7TDZB3","SPN8ALXB1","SPN8ALXB2","SPN8ALXB3","SPN8ALYB1","SPN8ALYB2","SPN8ALYB3", & + "SPN8ALZB1","SPN8ALZB2","SPN8ALZB3","SPN8FLXB1","SPN8FLXB2","SPN8FLXB3","SPN8FLYB1", & + "SPN8FLYB2","SPN8FLYB3","SPN8FLZB1","SPN8FLZB2","SPN8FLZB3","SPN8MLXB1","SPN8MLXB2", & + "SPN8MLXB3","SPN8MLYB1","SPN8MLYB2","SPN8MLYB3","SPN8MLZB1","SPN8MLZB2","SPN8MLZB3", & + "SPN8RDXB1","SPN8RDXB2","SPN8RDXB3","SPN8RDYB1","SPN8RDYB2","SPN8RDYB3","SPN8RDZB1", & + "SPN8RDZB2","SPN8RDZB3","SPN8TDXB1","SPN8TDXB2","SPN8TDXB3","SPN8TDYB1","SPN8TDYB2", & + "SPN8TDYB3","SPN8TDZB1","SPN8TDZB2","SPN8TDZB3","SPN9ALXB1","SPN9ALXB2","SPN9ALXB3", & + "SPN9ALYB1","SPN9ALYB2","SPN9ALYB3","SPN9ALZB1","SPN9ALZB2","SPN9ALZB3","SPN9FLXB1", & + "SPN9FLXB2","SPN9FLXB3","SPN9FLYB1","SPN9FLYB2","SPN9FLYB3","SPN9FLZB1","SPN9FLZB2", & + "SPN9FLZB3","SPN9MLXB1","SPN9MLXB2","SPN9MLXB3","SPN9MLYB1","SPN9MLYB2","SPN9MLYB3", & + "SPN9MLZB1","SPN9MLZB2","SPN9MLZB3","SPN9RDXB1","SPN9RDXB2","SPN9RDXB3","SPN9RDYB1", & + "SPN9RDYB2","SPN9RDYB3","SPN9RDZB1","SPN9RDZB2","SPN9RDZB3","SPN9TDXB1","SPN9TDXB2", & + "SPN9TDXB3","SPN9TDYB1","SPN9TDYB2","SPN9TDYB3","SPN9TDZB1","SPN9TDZB2","SPN9TDZB3", & + "TAILFURL ","TAILFURLA","TAILFURLP","TAILFURLV","TEETAYA ","TEETDEFL ","TEETPYA ", & + "TEETVYA ","TFRLBRM ","TIP2TWR1 ","TIP2TWR2 ","TIP2TWR3 ","TIPALXB1 ","TIPALXB2 ", & + "TIPALXB3 ","TIPALYB1 ","TIPALYB2 ","TIPALYB3 ","TIPALZB1 ","TIPALZB2 ","TIPALZB3 ", & + "TIPCLRNC1","TIPCLRNC2","TIPCLRNC3","TIPDXB1 ","TIPDXB2 ","TIPDXB3 ","TIPDXC1 ", & + "TIPDXC2 ","TIPDXC3 ","TIPDYB1 ","TIPDYB2 ","TIPDYB3 ","TIPDYC1 ","TIPDYC2 ", & + "TIPDYC3 ","TIPDZB1 ","TIPDZB2 ","TIPDZB3 ","TIPDZC1 ","TIPDZC2 ","TIPDZC3 ", & + "TIPRDXB1 ","TIPRDXB2 ","TIPRDXB3 ","TIPRDYB1 ","TIPRDYB2 ","TIPRDYB3 ","TIPRDZB1 ", & + "TIPRDZB2 ","TIPRDZB3 ","TIPRDZC1 ","TIPRDZC2 ","TIPRDZC3 ","TTDSPAX ","TTDSPFA ", & + "TTDSPPTCH","TTDSPROLL","TTDSPSS ","TTDSPTWST","TWHT1ALXT","TWHT1ALYT","TWHT1ALZT", & + "TWHT1FLXT","TWHT1FLYT","TWHT1FLZT","TWHT1MLXT","TWHT1MLYT","TWHT1MLZT","TWHT1RDXT", & + "TWHT1RDYT","TWHT1RDZT","TWHT1RPXI","TWHT1RPYI","TWHT1RPZI","TWHT1TDXT","TWHT1TDYT", & + "TWHT1TDZT","TWHT1TPXI","TWHT1TPYI","TWHT1TPZI","TWHT2ALXT","TWHT2ALYT","TWHT2ALZT", & + "TWHT2FLXT","TWHT2FLYT","TWHT2FLZT","TWHT2MLXT","TWHT2MLYT","TWHT2MLZT","TWHT2RDXT", & + "TWHT2RDYT","TWHT2RDZT","TWHT2RPXI","TWHT2RPYI","TWHT2RPZI","TWHT2TDXT","TWHT2TDYT", & + "TWHT2TDZT","TWHT2TPXI","TWHT2TPYI","TWHT2TPZI","TWHT3ALXT","TWHT3ALYT","TWHT3ALZT", & + "TWHT3FLXT","TWHT3FLYT","TWHT3FLZT","TWHT3MLXT","TWHT3MLYT","TWHT3MLZT","TWHT3RDXT", & + "TWHT3RDYT","TWHT3RDZT","TWHT3RPXI","TWHT3RPYI","TWHT3RPZI","TWHT3TDXT","TWHT3TDYT", & + "TWHT3TDZT","TWHT3TPXI","TWHT3TPYI","TWHT3TPZI","TWHT4ALXT","TWHT4ALYT","TWHT4ALZT", & + "TWHT4FLXT","TWHT4FLYT","TWHT4FLZT","TWHT4MLXT","TWHT4MLYT","TWHT4MLZT","TWHT4RDXT", & + "TWHT4RDYT","TWHT4RDZT","TWHT4RPXI","TWHT4RPYI","TWHT4RPZI","TWHT4TDXT","TWHT4TDYT", & + "TWHT4TDZT","TWHT4TPXI","TWHT4TPYI","TWHT4TPZI","TWHT5ALXT","TWHT5ALYT","TWHT5ALZT", & + "TWHT5FLXT","TWHT5FLYT","TWHT5FLZT","TWHT5MLXT","TWHT5MLYT","TWHT5MLZT","TWHT5RDXT", & + "TWHT5RDYT","TWHT5RDZT","TWHT5RPXI","TWHT5RPYI","TWHT5RPZI","TWHT5TDXT","TWHT5TDYT", & + "TWHT5TDZT","TWHT5TPXI","TWHT5TPYI","TWHT5TPZI","TWHT6ALXT","TWHT6ALYT","TWHT6ALZT", & + "TWHT6FLXT","TWHT6FLYT","TWHT6FLZT","TWHT6MLXT","TWHT6MLYT","TWHT6MLZT","TWHT6RDXT", & + "TWHT6RDYT","TWHT6RDZT","TWHT6RPXI","TWHT6RPYI","TWHT6RPZI","TWHT6TDXT","TWHT6TDYT", & + "TWHT6TDZT","TWHT6TPXI","TWHT6TPYI","TWHT6TPZI","TWHT7ALXT","TWHT7ALYT","TWHT7ALZT", & + "TWHT7FLXT","TWHT7FLYT","TWHT7FLZT","TWHT7MLXT","TWHT7MLYT","TWHT7MLZT","TWHT7RDXT", & + "TWHT7RDYT","TWHT7RDZT","TWHT7RPXI","TWHT7RPYI","TWHT7RPZI","TWHT7TDXT","TWHT7TDYT", & + "TWHT7TDZT","TWHT7TPXI","TWHT7TPYI","TWHT7TPZI","TWHT8ALXT","TWHT8ALYT","TWHT8ALZT", & + "TWHT8FLXT","TWHT8FLYT","TWHT8FLZT","TWHT8MLXT","TWHT8MLYT","TWHT8MLZT","TWHT8RDXT", & + "TWHT8RDYT","TWHT8RDZT","TWHT8RPXI","TWHT8RPYI","TWHT8RPZI","TWHT8TDXT","TWHT8TDYT", & + "TWHT8TDZT","TWHT8TPXI","TWHT8TPYI","TWHT8TPZI","TWHT9ALXT","TWHT9ALYT","TWHT9ALZT", & + "TWHT9FLXT","TWHT9FLYT","TWHT9FLZT","TWHT9MLXT","TWHT9MLYT","TWHT9MLZT","TWHT9RDXT", & + "TWHT9RDYT","TWHT9RDZT","TWHT9RPXI","TWHT9RPYI","TWHT9RPZI","TWHT9TDXT","TWHT9TDYT", & + "TWHT9TDZT","TWHT9TPXI","TWHT9TPYI","TWHT9TPZI","TWRBSFXT ","TWRBSFYT ","TWRBSFZT ", & + "TWRBSMXT ","TWRBSMYT ","TWRBSMZT ","TWRCLRNC1","TWRCLRNC2","TWRCLRNC3","TWRTPTDXI", & + "TWRTPTDYI","TWRTPTDZI","TWSTDEFL1","TWSTDEFL2","TWSTDEFL3","YAWACCEL ","YAWAZN ", & + "YAWAZP ","YAWBRFXN ","YAWBRFXP ","YAWBRFYN ","YAWBRFYP ","YAWBRFZN ","YAWBRFZP ", & + "YAWBRMXN ","YAWBRMXP ","YAWBRMYN ","YAWBRMYP ","YAWBRMZN ","YAWBRMZP ","YAWBRRAXP", & + "YAWBRRAYP","YAWBRRAZP","YAWBRRDXT","YAWBRRDYT","YAWBRRDZT","YAWBRRVXP","YAWBRRVYP", & + "YAWBRRVZP","YAWBRTAXP","YAWBRTAYP","YAWBRTAZP","YAWBRTDXI","YAWBRTDXP","YAWBRTDXT", & + "YAWBRTDYI","YAWBRTDYP","YAWBRTDYT","YAWBRTDZI","YAWBRTDZP","YAWBRTDZT","YAWPOS ", & + "YAWPZN ","YAWPZP ","YAWRATE ","YAWVZN ","YAWVZP "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(978) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + LSSTipPxa , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , & + HSShftA , HSShftV , HSSBrTq , HSShftA , HSShftPwr , HSShftTq , HSShftV , & + TipDyc1 , TipDyc2 , TipDyc3 , LSSGagAxa , LSSGagAxa , LSSGagAxa , LSShftFxa , & + LSShftFxa , LSShftFya , LSShftFys , LSShftFza , LSShftFzs , LSShftMxa , LSShftMxa , & + LSSGagMya , LSSGagMys , LSSGagMza , LSSGagMzs , LSSGagPxa , LSSGagPxa , LSSGagPxa , & + LSSGagVxa , LSSGagVxa , LSSGagVxa , LSShftFxa , LSShftFxa , LSShftFya , LSShftFys , & + LSShftFza , LSShftFzs , LSShftMxa , LSShftMxa , RotPwr , LSShftMxa , LSSTipAxa , & + LSSTipAxa , LSSTipAxa , LSSTipMya , LSSTipMys , LSSTipMza , LSSTipMzs , LSSTipPxa , & + LSSTipPxa , LSSTipPxa , LSSTipVxa , LSSTipVxa , LSSTipVxa , YawPzn , YawAzn , & + YawPzn , YawVzn , NcIMURAxs , NcIMURAys , NcIMURAzs , NcIMURVxs , NcIMURVys , & + NcIMURVzs , NcIMUTAxs , NcIMUTAys , NcIMUTAzs , NcIMUTVxs , NcIMUTVys , NcIMUTVzs , & + TipDxc1 , TipDxc2 , TipDxc3 , TipRDyb1 , TipRDyb2 , TipRDyb3 , PtchPMzc1 , & + PtchPMzc2 , PtchPMzc3 , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , PtfmTDzi , PtfmRDyi , & + PtfmRAxi , PtfmRAxt , PtfmRAyi , PtfmRAyt , PtfmRAzi , PtfmRAzt , PtfmRDxi , & + PtfmRDyi , PtfmRDzi , PtfmRDxi , PtfmRVxi , PtfmRVxt , PtfmRVyi , PtfmRVyt , & + PtfmRVzi , PtfmRVzt , PtfmTDxi , PtfmTDyi , PtfmTAxi , PtfmTAxt , PtfmTAyi , & + PtfmTAyt , PtfmTAzi , PtfmTAzt , PtfmTDxi , PtfmTDxt , PtfmTDyi , PtfmTDyt , & + PtfmTDzi , PtfmTDzt , PtfmTVxi , PtfmTVxt , PtfmTVyi , PtfmTVyt , PtfmTVzi , & + PtfmTVzt , PtfmRDzi , QD2_B1E1 , QD2_B1F1 , QD2_B1F2 , QD2_B2E1 , QD2_B2F1 , & + QD2_B2F2 , QD2_B3E1 , QD2_B3F1 , QD2_B3F2 , QD2_DrTr , QD2_GeAz , QD2_Hv , & + QD2_P , QD2_R , QD2_RFrl , QD2_Sg , QD2_Sw , QD2_Teet , QD2_TFA1 , & + QD2_TFA2 , QD2_TFrl , QD2_TSS1 , QD2_TSS2 , QD2_Y , QD2_Yaw , QD_B1E1 , & + QD_B1F1 , QD_B1F2 , QD_B2E1 , QD_B2F1 , QD_B2F2 , QD_B3E1 , QD_B3F1 , & + QD_B3F2 , QD_DrTr , QD_GeAz , QD_Hv , QD_P , QD_R , QD_RFrl , & + QD_Sg , QD_Sw , QD_Teet , QD_TFA1 , QD_TFA2 , QD_TFrl , QD_TSS1 , & + QD_TSS2 , QD_Y , QD_Yaw , Q_B1E1 , Q_B1F1 , Q_B1F2 , Q_B2E1 , & + Q_B2F1 , Q_B2F2 , Q_B3E1 , Q_B3F1 , Q_B3F2 , Q_DrTr , Q_GeAz , & + Q_Hv , Q_P , Q_R , Q_RFrl , Q_Sg , Q_Sw , Q_Teet , & + Q_TFA1 , Q_TFA2 , Q_TFrl , Q_TSS1 , Q_TSS2 , Q_Y , Q_Yaw , & + RFrlBrM , TipRDxb1 , TipRDxb2 , TipRDxb3 , RootFxb1 , RootFxb2 , RootFxb3 , & + RootFxc1 , RootFxc2 , RootFxc3 , RootFyb1 , RootFyb2 , RootFyb3 , RootFyc1 , & + RootFyc2 , RootFyc3 , RootFzc1 , RootFzc2 , RootFzc3 , RootFzc1 , RootFzc2 , & + RootFzc3 , RootMxb1 , RootMxb2 , RootMxb3 , RootMyb1 , RootMyb2 , RootMyb3 , & + RootMxc1 , RootMxc2 , RootMxc3 , RootMyc1 , RootMyc2 , RootMyc3 , RootMxb1 , & + RootMxb2 , RootMxb3 , RootMxc1 , RootMxc2 , RootMxc3 , RootMyb1 , RootMyb2 , & + RootMyb3 , RootMyc1 , RootMyc2 , RootMyc3 , RootMzc1 , RootMzc2 , RootMzc3 , & + RootMzc1 , RootMzc2 , RootMzc3 , LSSTipAxa , RotFurlP , RotFurlA , RotFurlP , & + RotFurlV , RotPwr , LSSTipVxa , TeetAya , TeetPya , TeetVya , LSShftFxa , & + LSShftMxa , Spn1ALxb1 , Spn1ALxb2 , Spn1ALxb3 , Spn1ALyb1 , Spn1ALyb2 , Spn1ALyb3 , & + Spn1ALzb1 , Spn1ALzb2 , Spn1ALzb3 , Spn1FLxb1 , Spn1FLxb2 , Spn1FLxb3 , Spn1FLyb1 , & + Spn1FLyb2 , Spn1FLyb3 , Spn1FLzb1 , Spn1FLzb2 , Spn1FLzb3 , Spn1MLxb1 , Spn1MLxb2 , & + Spn1MLxb3 , Spn1MLyb1 , Spn1MLyb2 , Spn1MLyb3 , Spn1MLzb1 , Spn1MLzb2 , Spn1MLzb3 , & + Spn1RDxb1 , Spn1RDxb2 , Spn1RDxb3 , Spn1RDyb1 , Spn1RDyb2 , Spn1RDyb3 , Spn1RDzb1 , & + Spn1RDzb2 , Spn1RDzb3 , Spn1TDxb1 , Spn1TDxb2 , Spn1TDxb3 , Spn1TDyb1 , Spn1TDyb2 , & + Spn1TDyb3 , Spn1TDzb1 , Spn1TDzb2 , Spn1TDzb3 , Spn2ALxb1 , Spn2ALxb2 , Spn2ALxb3 , & + Spn2ALyb1 , Spn2ALyb2 , Spn2ALyb3 , Spn2ALzb1 , Spn2ALzb2 , Spn2ALzb3 , Spn2FLxb1 , & + Spn2FLxb2 , Spn2FLxb3 , Spn2FLyb1 , Spn2FLyb2 , Spn2FLyb3 , Spn2FLzb1 , Spn2FLzb2 , & + Spn2FLzb3 , Spn2MLxb1 , Spn2MLxb2 , Spn2MLxb3 , Spn2MLyb1 , Spn2MLyb2 , Spn2MLyb3 , & + Spn2MLzb1 , Spn2MLzb2 , Spn2MLzb3 , Spn2RDxb1 , Spn2RDxb2 , Spn2RDxb3 , Spn2RDyb1 , & + Spn2RDyb2 , Spn2RDyb3 , Spn2RDzb1 , Spn2RDzb2 , Spn2RDzb3 , Spn2TDxb1 , Spn2TDxb2 , & + Spn2TDxb3 , Spn2TDyb1 , Spn2TDyb2 , Spn2TDyb3 , Spn2TDzb1 , Spn2TDzb2 , Spn2TDzb3 , & + Spn3ALxb1 , Spn3ALxb2 , Spn3ALxb3 , Spn3ALyb1 , Spn3ALyb2 , Spn3ALyb3 , Spn3ALzb1 , & + Spn3ALzb2 , Spn3ALzb3 , Spn3FLxb1 , Spn3FLxb2 , Spn3FLxb3 , Spn3FLyb1 , Spn3FLyb2 , & + Spn3FLyb3 , Spn3FLzb1 , Spn3FLzb2 , Spn3FLzb3 , Spn3MLxb1 , Spn3MLxb2 , Spn3MLxb3 , & + Spn3MLyb1 , Spn3MLyb2 , Spn3MLyb3 , Spn3MLzb1 , Spn3MLzb2 , Spn3MLzb3 , Spn3RDxb1 , & + Spn3RDxb2 , Spn3RDxb3 , Spn3RDyb1 , Spn3RDyb2 , Spn3RDyb3 , Spn3RDzb1 , Spn3RDzb2 , & + Spn3RDzb3 , Spn3TDxb1 , Spn3TDxb2 , Spn3TDxb3 , Spn3TDyb1 , Spn3TDyb2 , Spn3TDyb3 , & + Spn3TDzb1 , Spn3TDzb2 , Spn3TDzb3 , Spn4ALxb1 , Spn4ALxb2 , Spn4ALxb3 , Spn4ALyb1 , & + Spn4ALyb2 , Spn4ALyb3 , Spn4ALzb1 , Spn4ALzb2 , Spn4ALzb3 , Spn4FLxb1 , Spn4FLxb2 , & + Spn4FLxb3 , Spn4FLyb1 , Spn4FLyb2 , Spn4FLyb3 , Spn4FLzb1 , Spn4FLzb2 , Spn4FLzb3 , & + Spn4MLxb1 , Spn4MLxb2 , Spn4MLxb3 , Spn4MLyb1 , Spn4MLyb2 , Spn4MLyb3 , Spn4MLzb1 , & + Spn4MLzb2 , Spn4MLzb3 , Spn4RDxb1 , Spn4RDxb2 , Spn4RDxb3 , Spn4RDyb1 , Spn4RDyb2 , & + Spn4RDyb3 , Spn4RDzb1 , Spn4RDzb2 , Spn4RDzb3 , Spn4TDxb1 , Spn4TDxb2 , Spn4TDxb3 , & + Spn4TDyb1 , Spn4TDyb2 , Spn4TDyb3 , Spn4TDzb1 , Spn4TDzb2 , Spn4TDzb3 , Spn5ALxb1 , & + Spn5ALxb2 , Spn5ALxb3 , Spn5ALyb1 , Spn5ALyb2 , Spn5ALyb3 , Spn5ALzb1 , Spn5ALzb2 , & + Spn5ALzb3 , Spn5FLxb1 , Spn5FLxb2 , Spn5FLxb3 , Spn5FLyb1 , Spn5FLyb2 , Spn5FLyb3 , & + Spn5FLzb1 , Spn5FLzb2 , Spn5FLzb3 , Spn5MLxb1 , Spn5MLxb2 , Spn5MLxb3 , Spn5MLyb1 , & + Spn5MLyb2 , Spn5MLyb3 , Spn5MLzb1 , Spn5MLzb2 , Spn5MLzb3 , Spn5RDxb1 , Spn5RDxb2 , & + Spn5RDxb3 , Spn5RDyb1 , Spn5RDyb2 , Spn5RDyb3 , Spn5RDzb1 , Spn5RDzb2 , Spn5RDzb3 , & + Spn5TDxb1 , Spn5TDxb2 , Spn5TDxb3 , Spn5TDyb1 , Spn5TDyb2 , Spn5TDyb3 , Spn5TDzb1 , & + Spn5TDzb2 , Spn5TDzb3 , Spn6ALxb1 , Spn6ALxb2 , Spn6ALxb3 , Spn6ALyb1 , Spn6ALyb2 , & + Spn6ALyb3 , Spn6ALzb1 , Spn6ALzb2 , Spn6ALzb3 , Spn6FLxb1 , Spn6FLxb2 , Spn6FLxb3 , & + Spn6FLyb1 , Spn6FLyb2 , Spn6FLyb3 , Spn6FLzb1 , Spn6FLzb2 , Spn6FLzb3 , Spn6MLxb1 , & + Spn6MLxb2 , Spn6MLxb3 , Spn6MLyb1 , Spn6MLyb2 , Spn6MLyb3 , Spn6MLzb1 , Spn6MLzb2 , & + Spn6MLzb3 , Spn6RDxb1 , Spn6RDxb2 , Spn6RDxb3 , Spn6RDyb1 , Spn6RDyb2 , Spn6RDyb3 , & + Spn6RDzb1 , Spn6RDzb2 , Spn6RDzb3 , Spn6TDxb1 , Spn6TDxb2 , Spn6TDxb3 , Spn6TDyb1 , & + Spn6TDyb2 , Spn6TDyb3 , Spn6TDzb1 , Spn6TDzb2 , Spn6TDzb3 , Spn7ALxb1 , Spn7ALxb2 , & + Spn7ALxb3 , Spn7ALyb1 , Spn7ALyb2 , Spn7ALyb3 , Spn7ALzb1 , Spn7ALzb2 , Spn7ALzb3 , & + Spn7FLxb1 , Spn7FLxb2 , Spn7FLxb3 , Spn7FLyb1 , Spn7FLyb2 , Spn7FLyb3 , Spn7FLzb1 , & + Spn7FLzb2 , Spn7FLzb3 , Spn7MLxb1 , Spn7MLxb2 , Spn7MLxb3 , Spn7MLyb1 , Spn7MLyb2 , & + Spn7MLyb3 , Spn7MLzb1 , Spn7MLzb2 , Spn7MLzb3 , Spn7RDxb1 , Spn7RDxb2 , Spn7RDxb3 , & + Spn7RDyb1 , Spn7RDyb2 , Spn7RDyb3 , Spn7RDzb1 , Spn7RDzb2 , Spn7RDzb3 , Spn7TDxb1 , & + Spn7TDxb2 , Spn7TDxb3 , Spn7TDyb1 , Spn7TDyb2 , Spn7TDyb3 , Spn7TDzb1 , Spn7TDzb2 , & + Spn7TDzb3 , Spn8ALxb1 , Spn8ALxb2 , Spn8ALxb3 , Spn8ALyb1 , Spn8ALyb2 , Spn8ALyb3 , & + Spn8ALzb1 , Spn8ALzb2 , Spn8ALzb3 , Spn8FLxb1 , Spn8FLxb2 , Spn8FLxb3 , Spn8FLyb1 , & + Spn8FLyb2 , Spn8FLyb3 , Spn8FLzb1 , Spn8FLzb2 , Spn8FLzb3 , Spn8MLxb1 , Spn8MLxb2 , & + Spn8MLxb3 , Spn8MLyb1 , Spn8MLyb2 , Spn8MLyb3 , Spn8MLzb1 , Spn8MLzb2 , Spn8MLzb3 , & + Spn8RDxb1 , Spn8RDxb2 , Spn8RDxb3 , Spn8RDyb1 , Spn8RDyb2 , Spn8RDyb3 , Spn8RDzb1 , & + Spn8RDzb2 , Spn8RDzb3 , Spn8TDxb1 , Spn8TDxb2 , Spn8TDxb3 , Spn8TDyb1 , Spn8TDyb2 , & + Spn8TDyb3 , Spn8TDzb1 , Spn8TDzb2 , Spn8TDzb3 , Spn9ALxb1 , Spn9ALxb2 , Spn9ALxb3 , & + Spn9ALyb1 , Spn9ALyb2 , Spn9ALyb3 , Spn9ALzb1 , Spn9ALzb2 , Spn9ALzb3 , Spn9FLxb1 , & + Spn9FLxb2 , Spn9FLxb3 , Spn9FLyb1 , Spn9FLyb2 , Spn9FLyb3 , Spn9FLzb1 , Spn9FLzb2 , & + Spn9FLzb3 , Spn9MLxb1 , Spn9MLxb2 , Spn9MLxb3 , Spn9MLyb1 , Spn9MLyb2 , Spn9MLyb3 , & + Spn9MLzb1 , Spn9MLzb2 , Spn9MLzb3 , Spn9RDxb1 , Spn9RDxb2 , Spn9RDxb3 , Spn9RDyb1 , & + Spn9RDyb2 , Spn9RDyb3 , Spn9RDzb1 , Spn9RDzb2 , Spn9RDzb3 , Spn9TDxb1 , Spn9TDxb2 , & + Spn9TDxb3 , Spn9TDyb1 , Spn9TDyb2 , Spn9TDyb3 , Spn9TDzb1 , Spn9TDzb2 , Spn9TDzb3 , & + TailFurlP , TailFurlA , TailFurlP , TailFurlV , TeetAya , TeetPya , TeetPya , & + TeetVya , TFrlBrM , TipClrnc1 , TipClrnc2 , TipClrnc3 , TipALxb1 , TipALxb2 , & + TipALxb3 , TipALyb1 , TipALyb2 , TipALyb3 , TipALzb1 , TipALzb2 , TipALzb3 , & + TipClrnc1 , TipClrnc2 , TipClrnc3 , TipDxb1 , TipDxb2 , TipDxb3 , TipDxc1 , & + TipDxc2 , TipDxc3 , TipDyb1 , TipDyb2 , TipDyb3 , TipDyc1 , TipDyc2 , & + TipDyc3 , TipDzc1 , TipDzc2 , TipDzc3 , TipDzc1 , TipDzc2 , TipDzc3 , & + TipRDxb1 , TipRDxb2 , TipRDxb3 , TipRDyb1 , TipRDyb2 , TipRDyb3 , TipRDzc1 , & + TipRDzc2 , TipRDzc3 , TipRDzc1 , TipRDzc2 , TipRDzc3 , YawBrTDzt , YawBrTDxt , & + YawBrRDyt , YawBrRDxt , YawBrTDyt , YawBrRDzt , TwHt1ALxt , TwHt1ALyt , TwHt1ALzt , & + TwHt1FLxt , TwHt1FLyt , TwHt1FLzt , TwHt1MLxt , TwHt1MLyt , TwHt1MLzt , TwHt1RDxt , & + TwHt1RDyt , TwHt1RDzt , TwHt1RPxi , TwHt1RPyi , TwHt1RPzi , TwHt1TDxt , TwHt1TDyt , & + TwHt1TDzt , TwHt1TPxi , TwHt1TPyi , TwHt1TPzi , TwHt2ALxt , TwHt2ALyt , TwHt2ALzt , & + TwHt2FLxt , TwHt2FLyt , TwHt2FLzt , TwHt2MLxt , TwHt2MLyt , TwHt2MLzt , TwHt2RDxt , & + TwHt2RDyt , TwHt2RDzt , TwHt2RPxi , TwHt2RPyi , TwHt2RPzi , TwHt2TDxt , TwHt2TDyt , & + TwHt2TDzt , TwHt2TPxi , TwHt2TPyi , TwHt2TPzi , TwHt3ALxt , TwHt3ALyt , TwHt3ALzt , & + TwHt3FLxt , TwHt3FLyt , TwHt3FLzt , TwHt3MLxt , TwHt3MLyt , TwHt3MLzt , TwHt3RDxt , & + TwHt3RDyt , TwHt3RDzt , TwHt3RPxi , TwHt3RPyi , TwHt3RPzi , TwHt3TDxt , TwHt3TDyt , & + TwHt3TDzt , TwHt3TPxi , TwHt3TPyi , TwHt3TPzi , TwHt4ALxt , TwHt4ALyt , TwHt4ALzt , & + TwHt4FLxt , TwHt4FLyt , TwHt4FLzt , TwHt4MLxt , TwHt4MLyt , TwHt4MLzt , TwHt4RDxt , & + TwHt4RDyt , TwHt4RDzt , TwHt4RPxi , TwHt4RPyi , TwHt4RPzi , TwHt4TDxt , TwHt4TDyt , & + TwHt4TDzt , TwHt4TPxi , TwHt4TPyi , TwHt4TPzi , TwHt5ALxt , TwHt5ALyt , TwHt5ALzt , & + TwHt5FLxt , TwHt5FLyt , TwHt5FLzt , TwHt5MLxt , TwHt5MLyt , TwHt5MLzt , TwHt5RDxt , & + TwHt5RDyt , TwHt5RDzt , TwHt5RPxi , TwHt5RPyi , TwHt5RPzi , TwHt5TDxt , TwHt5TDyt , & + TwHt5TDzt , TwHt5TPxi , TwHt5TPyi , TwHt5TPzi , TwHt6ALxt , TwHt6ALyt , TwHt6ALzt , & + TwHt6FLxt , TwHt6FLyt , TwHt6FLzt , TwHt6MLxt , TwHt6MLyt , TwHt6MLzt , TwHt6RDxt , & + TwHt6RDyt , TwHt6RDzt , TwHt6RPxi , TwHt6RPyi , TwHt6RPzi , TwHt6TDxt , TwHt6TDyt , & + TwHt6TDzt , TwHt6TPxi , TwHt6TPyi , TwHt6TPzi , TwHt7ALxt , TwHt7ALyt , TwHt7ALzt , & + TwHt7FLxt , TwHt7FLyt , TwHt7FLzt , TwHt7MLxt , TwHt7MLyt , TwHt7MLzt , TwHt7RDxt , & + TwHt7RDyt , TwHt7RDzt , TwHt7RPxi , TwHt7RPyi , TwHt7RPzi , TwHt7TDxt , TwHt7TDyt , & + TwHt7TDzt , TwHt7TPxi , TwHt7TPyi , TwHt7TPzi , TwHt8ALxt , TwHt8ALyt , TwHt8ALzt , & + TwHt8FLxt , TwHt8FLyt , TwHt8FLzt , TwHt8MLxt , TwHt8MLyt , TwHt8MLzt , TwHt8RDxt , & + TwHt8RDyt , TwHt8RDzt , TwHt8RPxi , TwHt8RPyi , TwHt8RPzi , TwHt8TDxt , TwHt8TDyt , & + TwHt8TDzt , TwHt8TPxi , TwHt8TPyi , TwHt8TPzi , TwHt9ALxt , TwHt9ALyt , TwHt9ALzt , & + TwHt9FLxt , TwHt9FLyt , TwHt9FLzt , TwHt9MLxt , TwHt9MLyt , TwHt9MLzt , TwHt9RDxt , & + TwHt9RDyt , TwHt9RDzt , TwHt9RPxi , TwHt9RPyi , TwHt9RPzi , TwHt9TDxt , TwHt9TDyt , & + TwHt9TDzt , TwHt9TPxi , TwHt9TPyi , TwHt9TPzi , TwrBsFxt , TwrBsFyt , TwrBsFzt , & + TwrBsMxt , TwrBsMyt , TwrBsMzt , TipClrnc1 , TipClrnc2 , TipClrnc3 , TwrTpTDxi , & + TwrTpTDyi , TwrTpTDzi , TipRDzc1 , TipRDzc2 , TipRDzc3 , YawAzn , YawAzn , & + YawAzn , YawBrFxn , YawBrFxp , YawBrFyn , YawBrFyp , YawBrFzn , YawBrFzn , & + YawBrMxn , YawBrMxp , YawBrMyn , YawBrMyp , YawBrMzn , YawBrMzn , YawBrRAxp , & + YawBrRAyp , YawBrRAzp , YawBrRDxt , YawBrRDyt , YawBrRDzt , YawBrRVxp , YawBrRVyp , & + YawBrRVzp , YawBrTAxp , YawBrTAyp , YawBrTAzp , TwrTpTDxi , YawBrTDxp , YawBrTDxt , & + TwrTpTDyi , YawBrTDyp , YawBrTDyt , TwrTpTDzi , YawBrTDzp , YawBrTDzt , YawPzn , & + YawPzn , YawPzn , YawVzn , YawVzn , YawVzn /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(978) = (/ & ! This lists the units corresponding to the allowed parameters + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg/s^2) ","(rpm) ","(kN-m) ","(deg/s^2) ","(kW) ","(kN-m) ","(rpm) ", & + "(m) ","(m) ","(m) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ", & + "(rpm) ","(rpm) ","(rpm) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kW) ","(kN-m) ","(deg/s^2) ", & + "(deg/s^2) ","(deg/s^2) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(rpm) ","(rpm) ","(rpm) ","(deg) ","(deg/s^2) ", & + "(deg) ","(deg/s) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(deg/s) ","(deg/s) ", & + "(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m) ","(m) ","(m) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(deg) ", & + "(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(deg/s^2) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(deg/s) ","(deg/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(deg) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(rad/s^2) ","(rad/s^2) ","(m/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(m/s^2) ","(m/s^2) ","(rad/s^2) ","(m/s^2) ", & + "(m/s^2) ","(rad/s^2) ","(m/s^2) ","(m/s^2) ","(rad/s^2) ","(rad/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(rad/s) ","(rad/s) ","(m/s) ","(rad/s) ","(rad/s) ","(rad/s) ", & + "(m/s) ","(m/s) ","(rad/s) ","(m/s) ","(m/s) ","(rad/s) ","(m/s) ", & + "(m/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(rad) ","(rad) ", & + "(m) ","(rad) ","(rad) ","(rad) ","(m) ","(m) ","(rad) ", & + "(m) ","(m) ","(rad) ","(m) ","(m) ","(rad) ","(rad) ", & + "(kN-m) ","(deg) ","(deg) ","(deg) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(deg/s^2) ","(deg) ","(deg/s^2) ","(deg) ", & + "(deg/s) ","(kW) ","(rpm) ","(deg/s^2) ","(deg) ","(deg/s) ","(kN) ", & + "(kN-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(deg) ","(deg/s^2) ","(deg) ","(deg/s) ","(deg/s^2) ","(deg) ","(deg) ", & + "(deg/s) ","(kN-m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(deg) ","(deg) ","(m) ","(deg) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(kN) ","(kN) ","(kN) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(deg) ","(deg) ","(deg) ","(deg/s^2) ","(deg/s^2) ", & + "(deg/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg/s^2) ", & + "(deg/s^2) ","(deg/s^2) ","(deg) ","(deg) ","(deg) ","(deg/s) ","(deg/s) ", & + "(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(deg) ", & + "(deg) ","(deg) ","(deg/s) ","(deg/s) ","(deg/s) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... +if (p%BD4Blades) then + startIndx = 1 +else + startIndx = p%NumBl+1 +end if + + DO I = startIndx,3 ! Invalid blades + + ! motions + + InvalidOutput( TipDxc( I) ) = .TRUE. + InvalidOutput( TipDyc( I) ) = .TRUE. + InvalidOutput( TipDzc( I) ) = .TRUE. + InvalidOutput( TipDxb( I) ) = .TRUE. + InvalidOutput( TipDyb( I) ) = .TRUE. + InvalidOutput( TipALxb( I) ) = .TRUE. + InvalidOutput( TipALyb( I) ) = .TRUE. + InvalidOutput( TipALzb( I) ) = .TRUE. + InvalidOutput( TipRDxb( I) ) = .TRUE. + InvalidOutput( TipRDyb( I) ) = .TRUE. + InvalidOutput( TipRDzc( I) ) = .TRUE. + InvalidOutput( TipClrnc( I) ) = .TRUE. + + ! loads + + InvalidOutput( RootFxc( I) ) = .TRUE. + InvalidOutput( RootFyc( I) ) = .TRUE. + InvalidOutput( RootFzc( I) ) = .TRUE. + InvalidOutput( RootFxb( I) ) = .TRUE. + InvalidOutput( RootFyb( I) ) = .TRUE. + InvalidOutput( RootMxc( I) ) = .TRUE. + InvalidOutput( RootMyc( I) ) = .TRUE. + InvalidOutput( RootMzc( I) ) = .TRUE. + InvalidOutput( RootMxb( I) ) = .TRUE. + InvalidOutput( RootMyb( I) ) = .TRUE. + + ! Blade node motions + + InvalidOutput( SpnALxb(:,I) ) = .TRUE. + InvalidOutput( SpnALyb(:,I) ) = .TRUE. + InvalidOutput( SpnALzb(:,I) ) = .TRUE. + + InvalidOutput( SpnTDxb(:,I) ) = .TRUE. + InvalidOutput( SpnTDyb(:,I) ) = .TRUE. + InvalidOutput( SpnTDzb(:,I) ) = .TRUE. + + InvalidOutput( SpnRDxb(:,I) ) = .TRUE. + InvalidOutput( SpnRDyb(:,I) ) = .TRUE. + InvalidOutput( SpnRDzb(:,I) ) = .TRUE. + + ! Blade node loads + + InvalidOutput( SpnMLxb(:,I) ) = .TRUE. + InvalidOutput( SpnMLyb(:,I) ) = .TRUE. + InvalidOutput( SpnMLzb(:,I) ) = .TRUE. + + InvalidOutput( SpnFLxb(:,I) ) = .TRUE. + InvalidOutput( SpnFLyb(:,I) ) = .TRUE. + InvalidOutput( SpnFLzb(:,I) ) = .TRUE. + + END DO + + + DO I = 1,p%NumBl + + DO J = p%NBlGages+1,9 ! Invalid blade gages + + InvalidOutput( SpnALxb(J,I) ) = .TRUE. + InvalidOutput( SpnALyb(J,I) ) = .TRUE. + InvalidOutput( SpnALzb(J,I) ) = .TRUE. + + InvalidOutput( SpnTDxb(J,I) ) = .TRUE. + InvalidOutput( SpnTDyb(J,I) ) = .TRUE. + InvalidOutput( SpnTDzb(J,I) ) = .TRUE. + + InvalidOutput( SpnRDxb(J,I) ) = .TRUE. + InvalidOutput( SpnRDyb(J,I) ) = .TRUE. + InvalidOutput( SpnRDzb(J,I) ) = .TRUE. + + ! Loads + + InvalidOutput( SpnMLxb(J,I) ) = .TRUE. + InvalidOutput( SpnMLyb(J,I) ) = .TRUE. + InvalidOutput( SpnMLzb(J,I) ) = .TRUE. + + InvalidOutput( SpnFLxb(J,I) ) = .TRUE. + InvalidOutput( SpnFLyb(J,I) ) = .TRUE. + InvalidOutput( SpnFLzb(J,I) ) = .TRUE. + + + END DO !J + + END DO !I + + DO J = p%NTwGages+1,9 !Invalid tower gages + + ! Motions + + InvalidOutput( TwHtALxt(J) ) = .TRUE. + InvalidOutput( TwHtALyt(J) ) = .TRUE. + InvalidOutput( TwHtALzt(J) ) = .TRUE. + + InvalidOutput( TwHtTDxt(J) ) = .TRUE. + InvalidOutput( TwHtTDyt(J) ) = .TRUE. + InvalidOutput( TwHtTDzt(J) ) = .TRUE. + + InvalidOutput( TwHtRDxt(J) ) = .TRUE. + InvalidOutput( TwHtRDyt(J) ) = .TRUE. + InvalidOutput( TwHtRDzt(J) ) = .TRUE. + + InvalidOutput( TwHtTPxi(J) ) = .TRUE. + InvalidOutput( TwHtTPyi(J) ) = .TRUE. + InvalidOutput( TwHtTPzi(J) ) = .TRUE. + + InvalidOutput( TwHtRPxi(J) ) = .TRUE. + InvalidOutput( TwHtRPyi(J) ) = .TRUE. + InvalidOutput( TwHtRPzi(J) ) = .TRUE. + + ! Loads + + InvalidOutput( TwHtMLxt(J) ) = .TRUE. + InvalidOutput( TwHtMLyt(J) ) = .TRUE. + InvalidOutput( TwHtMLzt(J) ) = .TRUE. + + InvalidOutput( TwHtFLxt(J) ) = .TRUE. + InvalidOutput( TwHtFLyt(J) ) = .TRUE. + InvalidOutput( TwHtFLzt(J) ) = .TRUE. + + END DO + + IF ( p%NumBl < 3_IntKi ) THEN + InvalidOutput(PtchPMzc3) = .TRUE. + + InvalidOutput( Q_B3E1) = .TRUE. + InvalidOutput( Q_B3F1) = .TRUE. + InvalidOutput( Q_B3F2) = .TRUE. + + InvalidOutput( QD_B3E1) = .TRUE. + InvalidOutput( QD_B3F1) = .TRUE. + InvalidOutput( QD_B3F2) = .TRUE. + + InvalidOutput( QD2_B3E1) = .TRUE. + InvalidOutput( QD2_B3F1) = .TRUE. + InvalidOutput( QD2_B3F2) = .TRUE. + ELSE IF ( p%NumBl > 2_IntKi ) THEN + InvalidOutput( TeetPya) = .TRUE. + InvalidOutput( TeetVya) = .TRUE. + InvalidOutput( TeetAya) = .TRUE. + + InvalidOutput( Q_Teet) = .TRUE. + InvalidOutput( QD_Teet) = .TRUE. + InvalidOutput( QD2_Teet) = .TRUE. + END IF + + InvalidOutput(HSSBrTq) = p%method == Method_RK4 + + IF ( p%BD4Blades ) THEN + InvalidOutput( Q_B1E1) = .TRUE. + InvalidOutput( Q_B1F1) = .TRUE. + InvalidOutput( Q_B1F2) = .TRUE. + + InvalidOutput( QD_B1E1) = .TRUE. + InvalidOutput( QD_B1F1) = .TRUE. + InvalidOutput( QD_B1F2) = .TRUE. + + InvalidOutput( QD2_B1E1) = .TRUE. + InvalidOutput( QD2_B1F1) = .TRUE. + InvalidOutput( QD2_B1F2) = .TRUE. + + InvalidOutput( Q_B2E1) = .TRUE. + InvalidOutput( Q_B2F1) = .TRUE. + InvalidOutput( Q_B2F2) = .TRUE. + + InvalidOutput( QD_B2E1) = .TRUE. + InvalidOutput( QD_B2F1) = .TRUE. + InvalidOutput( QD_B2F2) = .TRUE. + + InvalidOutput( QD2_B2E1) = .TRUE. + InvalidOutput( QD2_B2F1) = .TRUE. + InvalidOutput( QD2_B2F2) = .TRUE. + + InvalidOutput( Q_B3E1) = .TRUE. + InvalidOutput( Q_B3F1) = .TRUE. + InvalidOutput( Q_B3F2) = .TRUE. + + InvalidOutput( QD_B3E1) = .TRUE. + InvalidOutput( QD_B3F1) = .TRUE. + InvalidOutput( QD_B3F2) = .TRUE. + + InvalidOutput( QD2_B3E1) = .TRUE. + InvalidOutput( QD2_B3F1) = .TRUE. + InvalidOutput( QD2_B3F2) = .TRUE. + END IF +! ................. End of validity checking ................. + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the ElastoDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = Time ! pick any valid channel (I just picked "Time" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** +!> This routine is used to compute rotor (blade and hub) properties: +!! KBF(), KBE(), CBF(), CBE(), FreqBF(), FreqBE(), AxRedBld(), +!! TwistedSF(), BldMass(), FirstMom(), SecondMom(), BldCG(), +!! RotMass, RotIner, Hubg1Iner, Hubg2Iner, rSAerCenn1(), and +!! rSAerCenn2(), BElmtMass() +!! tower properties: +!! KTFA(), KTSS(), CTFA(), CTSS(), FreqTFA(), FreqTSS(), +!! AxRedTFA(), AxRedTSS(), TwrFASF(), TwrSSSF(), TwrMass, and +!! TwrTpMass, TElmtMass() +!! structure that furls with the rotor (not including rotor) properties: +!! RrfaIner +!! tail boom properties: +!! AtfaIner +!! and nacelle properties: +!! Nacd2Iner +SUBROUTINE Coeff(p,InputFileData, ErrStat, ErrMsg) +!.................................................................................................................................. + + ! Passed variables + + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< all the data in the ElastoDyn input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message when ErrStat =/ ErrID_None + + + ! Local variables. + + REAL(ReKi) :: AxRdBld (3,3) ! Temporary result holding the current addition to the p%AxRedBld() array. + REAL(ReKi) :: AxRdBldOld(3,3) ! Previous AxRdBld (i.e., AxRdBld from the previous node) + REAL(ReKi) :: AxRdTFA (2,2) ! Temporary result holding the current addition to the AxRedTFA() array. + REAL(ReKi) :: AxRdTFAOld(2,2) ! Previous AxRdTFA (i.e., AxRdTFA from the previous node) + REAL(ReKi) :: AxRdTSS (2,2) ! Temporary result holding the current addition to the AxRedTSS() array. + REAL(ReKi) :: AxRdTSSOld(2,2) ! Previous AxRdTSS (i.e., AxRdTSS from the previous node) + REAL(ReKi) :: TmpDist ! Temporary distance used in the calculation of the aero center locations. + REAL(ReKi) :: TmpDistj1 ! Temporary distance used in the calculation of the aero center locations. + REAL(ReKi) :: TmpDistj2 ! Temporary distance used in the calculation of the aero center locations. + REAL(ReKi) :: ElmntStff ! (Temporary) stiffness of an element. + REAL(ReKi) :: ElStffFA ! (Temporary) tower fore-aft stiffness of an element + REAL(ReKi) :: ElStffSS ! (Temporary) tower side-to-side stiffness of an element + REAL(ReKi) :: FMomAbvNd (p%NumBl,p%BldNodes) ! FMomAbvNd(K,J) = portion of the first moment of blade K about the rotor centerline (not root, like FirstMom(K)) associated with everything above node J (including tip brake masses). + REAL(ReKi) :: KBECent (p%NumBl,1,1) ! Centrifugal-term of generalized edgewise stiffness of the blades. + REAL(ReKi) :: KBFCent (p%NumBl,2,2) ! Centrifugal-term of generalized flapwise stiffness of the blades. + REAL(ReKi) :: KTFAGrav (2,2) ! Gravitational-term of generalized fore-aft stiffness of the tower. + REAL(ReKi) :: KTSSGrav (2,2) ! Gravitational-term of generalized side-to-side stiffness of the tower. + REAL(ReKi) :: MBE (p%NumBl,1,1) ! Generalized edgewise mass of the blades. + REAL(ReKi) :: MBF (p%NumBl,2,2) ! Generalized flapwise mass of the blades. + REAL(ReKi) :: MTFA (2,2) ! Generalized fore-aft mass of the tower. + REAL(ReKi) :: MTSS (2,2) ! Generalized side-to-side mass of the tower. + REAL(ReKi) :: Shape ! Temporary result holding a value from the SHP function + REAL(ReKi) :: Shape1 ! Temporary result holding a value from the SHP function + REAL(ReKi) :: Shape2 ! Temporary result holding a value from the SHP function + REAL(ReKi) :: TMssAbvNd (p%TwrNodes) ! Portion of the tower mass associated with everything above node J (including tower-top effects) + REAL(ReKi) :: TwstdSF (2,3,0:1) ! Temperory result holding the current addition to the TwistedSF() array. + REAL(ReKi) :: TwstdSFOld(2,3,0:1) ! Previous TwstdSF (i.e., TwstdSF from the previous node) + + INTEGER(IntKi) :: I ! Generic index. + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: L ! Generic index + + + ErrStat = ErrID_None + ErrMsg = '' + + !............................................................................................................................... + ! Calculate the distances from point S on a blade to the aerodynamic center in the j1 and j2 directions: + !............................................................................................................................... + + DO K = 1,p%NumBl ! Loop through the blades + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + TmpDist = ( 0.25 - p%PitchAxis(K,J) )*p%Chord(J) ! Distance along the chordline from point S (25% chord) to the aerodynamic center of the blade element J--positive towards the trailing edge. + TmpDistj1 = TmpDist*p%SAeroTwst(J) ! Distance along the j1-axis from point S (25% chord) to the aerodynamic center of the blade element J + TmpDistj2 = TmpDist*p%CAeroTwst(J) ! Distance along the j2-axis from point S (25% chord) to the aerodynamic center of the blade element J + p%rSAerCenn1(K,J) = TmpDistj1*p%CThetaS(K,J) - TmpDistj2*p%SThetaS(K,J) + p%rSAerCenn2(K,J) = TmpDistj1*p%SThetaS(K,J) + TmpDistj2*p%CThetaS(K,J) + + ENDDO ! J - Blade nodes / elements + + ENDDO ! K - Blades + + + !............................................................................................................................... + ! Calculate the structure that furls with the rotor inertia term: + !............................................................................................................................... + + p%RrfaIner = InputFileData%RFrlIner - p%RFrlMass*( (p%rVDxn**2 )*( 1.0 - p%CRFrlSkw2*p%CRFrlTlt2 ) & + + (p%rVDzn**2 )* p%CRFrlTlt2 & + + (p%rVDyn**2 )*( 1.0 - p%SRFrlSkw2*p%CRFrlTlt2 ) & + - 2.0*p%rVDxn*p%rVDzn* p%CRFrlSkew*p%CSRFrlTlt & + - 2.0*p%rVDxn*p%rVDyn* p%CSRFrlSkw*p%CRFrlTlt2 & + - 2.0*p%rVDzn*p%rVDyn* p%SRFrlSkew*p%CSRFrlTlt ) + IF ( p%RrfaIner < 0.0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' RFrlIner must not be less than RFrlMass*( perpendicular distance between rotor-furl'// & + ' axis and CM of the structure that furls with the rotor [not including rotor] )^2.' + RETURN + END IF + + !............................................................................................................................... + ! Calculate the tail boom inertia term: + !............................................................................................................................... + + p%AtfaIner = p%TFrlIner - p%BoomMass*( p%rWIxn*p%rWIxn*( 1.0 - p%CTFrlSkw2*p%CTFrlTlt2 ) & + + p%rWIzn*p%rWIzn* p%CTFrlTlt2 & + + p%rWIyn*p%rWIyn*( 1.0 - p%STFrlSkw2*p%CTFrlTlt2 ) & + - 2.0*p%rWIxn*p%rWIzn* p%CTFrlSkew*p%CSTFrlTlt & + - 2.0*p%rWIxn*p%rWIyn* p%CSTFrlSkw*p%CTFrlTlt2 & + - 2.0*p%rWIzn*p%rWIyn* p%STFrlSkew*p%CSTFrlTlt ) + IF ( p%AtfaIner < 0.0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' TFrlIner must not be less than BoomMass*( perpendicular distance between tail-furl'// & + ' axis and tail boom CM )^2.' + RETURN + ENDIF + + !............................................................................................................................... + ! Calculate the nacelle inertia terms: + !............................................................................................................................... + + p%Nacd2Iner = InputFileData%NacYIner - p%NacMass*( p%NacCMxn**2 + p%NacCMyn**2 ) ! Nacelle inertia about the d2-axis + IF ( p%Nacd2Iner < 0.0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' NacYIner must not be less than NacMass*( NacCMxn^2 + NacCMyn^2 ).' + RETURN + END IF + + ! Calculate hub inertia about its centerline passing through its c.g.. + ! This calculation assumes that the hub for a 2-blader is essentially + ! a uniform cylinder whose centerline is transverse through the cylinder + ! passing through its c.g.. That is, for a 2-blader, Hubg1Iner = + ! Hubg2Iner is the inertia of the hub about both the g1- and g2- axes. For + ! 3-bladers, Hubg1Iner is simply equal to HubIner and Hubg2Iner is zero. + ! Also, Initialize RotMass and RotIner to associated hub properties: + + IF ( p%NumBl == 2 ) THEN ! 2-blader + p%Hubg1Iner = ( InputFileData%HubIner - p%HubMass*( ( p%UndSling - p%HubCM )**2 ) )/( p%CosDel3**2 ) + p%Hubg2Iner = p%Hubg1Iner + IF ( p%Hubg1Iner < 0.0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' HubIner must not be less than HubMass*( UndSling - HubCM )^2 for 2-blader.' + RETURN + END IF + ELSE ! 3-blader + p%Hubg1Iner = InputFileData%HubIner + p%Hubg2Iner = 0.0 + ENDIF + + p%RotMass = p%HubMass + p%RotIner = p%Hubg1Iner + + + !............................................................................................................................... + + ! Initialize several variables to 0.0: + + p%KBF = 0.0 + p%KBE = 0.0 + KBFCent = 0.0 + KBECent = 0.0 + + p%TwrMass = 0.0 + p%KTFA = 0.0 + p%KTSS = 0.0 + KTFAGrav = 0.0 + KTSSGrav = 0.0 + + + + DO K = 1,p%NumBl ! Loop through the blades + + + ! Initialize BldMass(), FirstMom(), and SecondMom() using TipMass() effects: + + p%BldMass (K) = p%TipMass(K) + p%FirstMom (K) = p%TipMass(K)*p%BldFlexL + p%SecondMom(K) = p%TipMass(K)*p%BldFlexL*p%BldFlexL + + + DO J = p%BldNodes,1,-1 ! Loop through the blade nodes / elements in reverse + + + ! Calculate the mass of the current element + + p%BElmntMass(J,K) = p%MassB(K,J)*p%DRNodes(J) ! Mass of blade element J + + + ! Integrate to find some blade properties which will be output in .fsm + + p%BldMass (K) = p%BldMass (K) + p%BElmntMass(J,K) + p%FirstMom (K) = p%FirstMom (K) + p%BElmntMass(J,K)*p%RNodes(J) + p%SecondMom(K) = p%SecondMom(K) + p%BElmntMass(J,K)*p%RNodes(J)*p%RNodes(J) + + + ! Integrate to find FMomAbvNd: + + FMomAbvNd (K,J) = ( 0.5*p%BElmntMass(J,K) )*( p%HubRad + p%RNodes(J ) + 0.5*p%DRNodes(J ) ) + + IF ( J == p%BldNodes ) THEN ! Outermost blade element + ! Add the TipMass() effects: + + FMomAbvNd(K,J) = FmomAbvNd(K,J) + p%TipMass(K)*p%TipRad + ELSE ! All other blade elements + ! Add to FMomAbvNd(K,J) the effects from the (not yet used) portion of element J+1 + + FMomAbvNd(K,J) = FMomAbvNd(K,J) + FMomAbvNd(K,J+1) & + + ( 0.5*p%BElmntMass(J+1,K) )*( p%HubRad + p%RNodes(J+1) - 0.5*p%DRNodes(J+1) ) + ENDIF + + + ENDDO ! J - Blade nodes / elements in reverse + + IF (.NOT. p%BD4Blades) THEN + ! Calculate BldCG() using FirstMom() and BldMass(); and calculate + ! RotMass and RotIner: + + p%BldCG (K) = p%FirstMom (K) / p%BldMass (K) + p%RotMass = p%RotMass + p%BldMass (K) + p%RotIner = p%RotIner + ( p%SecondMom(K) + p%BldMass (K)*p%HubRad*( 2.0*p%BldCG(K) + p%HubRad ) )*( p%CosPreC(K)**2 ) + END IF + + ENDDO ! K - Blades + + + + DO K = 1,p%NumBl ! Loop through the blades + + + ! Initialize the generalized blade masses using tip mass effects: + + MBF(K,1,1) = p%TipMass(K) + MBF(K,2,2) = p%TipMass(K) + MBE(K,1,1) = p%TipMass(K) + + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + + ! Integrate to find the generalized mass of the blade (including tip mass effects). + ! Ignore the cross-correlation terms of MBF (i.e. MBF(i,j) where i /= j) since + ! these terms will never be used. + + Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 0, ErrStat, ErrMsg ) + Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 0, ErrStat, ErrMsg ) + MBF (K,1,1) = MBF (K,1,1) + p%BElmntMass(J,K)*Shape1*Shape1 + MBF (K,2,2) = MBF (K,2,2) + p%BElmntMass(J,K)*Shape2*Shape2 + + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 0, ErrStat, ErrMsg ) + MBE (K,1,1) = MBE (K,1,1) + p%BElmntMass(J,K)*Shape *Shape + + + ! Integrate to find the generalized stiffness of the blade (not including centrifugal + ! effects). + + ElmntStff = p%StiffBF(K,J)*p%DRNodes(J) ! Flapwise stiffness of blade element J + Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg ) + Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg ) + p%KBF (K,1,1) = p%KBF (K,1,1) + ElmntStff*Shape1*Shape1 + p%KBF (K,1,2) = p%KBF (K,1,2) + ElmntStff*Shape1*Shape2 + p%KBF (K,2,1) = p%KBF (K,2,1) + ElmntStff*Shape2*Shape1 + p%KBF (K,2,2) = p%KBF (K,2,2) + ElmntStff*Shape2*Shape2 + + ElmntStff = p%StiffBE(K,J)*p%DRNodes(J) ! Edgewise stiffness of blade element J + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg ) + p%KBE (K,1,1) = p%KBE (K,1,1) + ElmntStff*Shape *Shape + + + ! Integrate to find the centrifugal-term of the generalized flapwise and edgewise + ! stiffness of the blades. Ignore the cross-correlation terms of KBFCent (i.e. + ! KBFCent(i,j) where i /= j) since these terms will never be used. + + ElmntStff = FMomAbvNd(K,J)*p%DRNodes(J)*p%RotSpeed**2 ! Centrifugal stiffness of blade element J + + Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 1, ErrStat, ErrMsg ) + Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 1, ErrStat, ErrMsg ) + KBFCent(K,1,1) = KBFCent(K,1,1) + ElmntStff*Shape1*Shape1 + KBFCent(K,2,2) = KBFCent(K,2,2) + ElmntStff*Shape2*Shape2 + + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 1, ErrStat, ErrMsg ) + KBECent(K,1,1) = KBECent(K,1,1) + ElmntStff*Shape *Shape + + + ! Calculate the 2nd derivatives of the twisted shape functions: + + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,1,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Phi1(J) for blade K + p%TwistedSF(K,2,1,J,2) = -Shape*p%SThetaS(K,J) ! 2nd deriv. of Psi1(J) for blade K + + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,2,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Phi2(J) for blade K + p%TwistedSF(K,2,2,J,2) = -Shape*p%SThetaS(K,J) ! 2nd deriv. of Psi2(J) for blade K + + Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,3,J,2) = Shape*p%SThetaS(K,J) ! 2nd deriv. of Phi3(J) for blade K + p%TwistedSF(K,2,3,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Psi3(J) for blade K + + + ! Integrate to find the 1st derivatives of the twisted shape functions: + + DO I = 1,2 ! Loop through Phi and Psi + DO L = 1,3 ! Loop through all blade DOFs + TwstdSF ( I,L, 1) = p%TwistedSF(K,I,L,J,2)*0.5*p%DRNodes(J) + p%TwistedSF (K,I,L,J,1) = TwstdSF ( I,L, 1) + ENDDO ! L - All blade DOFs + ENDDO ! I - Phi and Psi + + IF ( J /= 1 ) THEN ! All but the innermost blade element + ! Add the effects from the (not yet used) portion of element J-1 + + DO I = 1,2 ! Loop through Phi and Psi + DO L = 1,3 ! Loop through all blade DOFs + p%TwistedSF(K,I,L,J,1) = p%TwistedSF(K,I,L,J,1) + p%TwistedSF(K,I,L,J-1,1) & + + TwstdSFOld( I,L, 1) + ENDDO ! L - All blade DOFs + ENDDO ! I - Phi and Psi + ENDIF + + + ! Integrate to find the twisted shape functions themselves (i.e., their zeroeth derivative): + + DO I = 1,2 ! Loop through Phi and Psi + DO L = 1,3 ! Loop through all blade DOFs + TwstdSF ( I,L, 0) = p%TwistedSF(K,I,L,J,1)*0.5*p%DRNodes(J) + p%TwistedSF (K,I,L,J,0) = TwstdSF ( I,L, 0) + ENDDO ! L - All blade DOFs + ENDDO ! I - Phi and Psi + + IF ( J /= 1 ) THEN ! All but the innermost blade element + ! Add the effects from the (not yet used) portion of element J-1 + + DO I = 1,2 ! Loop through Phi and Psi + DO L = 1,3 ! Loop through all blade DOFs + p%TwistedSF(K,I,L,J,0) = p%TwistedSF(K,I,L,J,0) + p%TwistedSF(K,I,L,J-1,0) & + + TwstdSFOld( I,L, 0) + ENDDO ! L - All blade DOFs + ENDDO ! I - Phi and Psi + ENDIF + + + ! Integrate to find the blade axial reduction shape functions: + + DO I = 1,3 ! Loop through all blade DOFs + DO L = 1,3 ! Loop through all blade DOFs + AxRdBld ( I,L ) = 0.5*p%DRNodes(J)*( & + p%TwistedSF(K,1,I,J,1)*p%TwistedSF(K,1,L,J,1) & + + p%TwistedSF(K,2,I,J,1)*p%TwistedSF(K,2,L,J,1) ) + p%AxRedBld (K,I,L,J) = AxRdBld(I,L) + ENDDO ! L - All blade DOFs + ENDDO ! I - All blade DOFs + + IF ( J /= 1 ) THEN ! All but the innermost blade element + ! Add the effects from the (not yet used) portion of element J-1 + + DO I = 1,3 ! Loop through all blade DOFs + DO L = 1,3 ! Loop through all blade DOFs + p%AxRedBld(K,I,L,J) = p%AxRedBld(K,I,L,J) + p%AxRedBld(K,I,L,J-1) & + + AxRdBldOld(I,L) + ENDDO ! L - All blade DOFs + ENDDO ! I - All blade DOFs + ENDIF + + + ! Store the TwstdSF and AxRdBld terms of the current element (these will be used for the next element) + + TwstdSFOld = TwstdSF + AxRdBldOld = AxRdBld + + + ENDDO ! J - Blade nodes / elements + + + + + IF (p%BD4Blades) THEN + + !p%KBF ( K,:,: ) = 0.0_ReKi + + ! the 1st and zeroeth derivatives of the twisted shape functions at the blade root: + p%TwistedSF(K,:,:,:,1) = 0.0_ReKi + p%TwistedSF(K,:,:,:,0) = 0.0_ReKi + p%AxRedBld( K,:,:,: ) = 0.0_ReKi + ELSE + + ! Apply the flapwise modal stiffness tuners of the blades to KBF(): + + DO I = 1,2 ! Loop through flap DOFs + DO L = 1,2 ! Loop through flap DOFs + p%KBF(K,I,L) = SQRT( p%FStTunr(K,I)*p%FStTunr(K,L) )*p%KBF(K,I,L) + ENDDO ! L - Flap DOFs + ENDDO ! I - Flap DOFs + + ! Calculate the blade natural frequencies: + + DO I = 1,NumBF ! Loop through flap DOFs + p%FreqBF(K,I,1) = Inv2Pi*SQRT( p%KBF(K,I,I) /( MBF(K,I,I) - p%TipMass(K) ) ) ! Natural blade I-flap frequency w/o centrifugal stiffening nor tip mass effects + p%FreqBF(K,I,2) = Inv2Pi*SQRT( p%KBF(K,I,I) / MBF(K,I,I) ) ! Natural blade I-flap frequency w/o centrifugal stiffening, but w/ tip mass effects + p%FreqBF(K,I,3) = Inv2Pi*SQRT( ( p%KBF(K,I,I) + KBFCent(K,I,I) )/ MBF(K,I,I) ) ! Natural blade I-flap frequency w/ centrifugal stiffening and tip mass effects + ENDDO ! I - Flap DOFs + + p%FreqBE (K,1,1) = Inv2Pi*SQRT( p%KBE(K,1,1) /( MBE(K,1,1) - p%TipMass(K) ) ) ! Natural blade 1-edge frequency w/o centrifugal stiffening nor tip mass effects + p%FreqBE (K,1,2) = Inv2Pi*SQRT( p%KBE(K,1,1) / MBE(K,1,1) ) ! Natural Blade 1-edge frequency w/o centrifugal stiffening, but w/ tip mass effects + p%FreqBE (K,1,3) = Inv2Pi*SQRT( ( p%KBE(K,1,1) + KBECent(K,1,1) )/ MBE(K,1,1) ) ! Natural Blade 1-edge frequency w/ centrifugal stiffening and tip mass effects + + + ! Calculate the generalized damping of the blades: + + DO I = 1,NumBF ! Loop through flap DOFs + DO L = 1,NumBF ! Loop through flap DOFs + p%CBF(K,I,L) = ( 0.01*p%BldFDamp(K,L) )*p%KBF(K,I,L)/( Pi*p%FreqBF(K,L,1) ) + ENDDO ! L - Flap DOFs + ENDDO ! I - Flap DOFs + + p%CBE (K,1,1) = ( 0.01*p%BldEDamp(K,1) )*p%KBE(K,1,1)/( Pi*p%FreqBE(K,1,1) ) + + + ! Calculate the 2nd derivatives of the twisted shape functions at the blade root: + + Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,1,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Phi1(0) for blade K + p%TwistedSF(K,2,1,0,2) = -Shape*p%SThetaS(K,0) ! 2nd deriv. of Psi1(0) for blade K + + Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,2,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Phi2(0) for blade K + p%TwistedSF(K,2,2,0,2) = -Shape*p%SThetaS(K,0) ! 2nd deriv. of Psi2(0) for blade K + + Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,3,0,2) = Shape*p%SThetaS(K,0) ! 2nd deriv. of Phi3(0) for blade K + p%TwistedSF(K,2,3,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Psi3(0) for blade K + + + ! Calculate the 2nd derivatives of the twisted shape functions at the tip: + + Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,1,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Phi1(p%TipNode) for blade K + p%TwistedSF(K,2,1,p%TipNode,2) = -Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Psi1(p%TipNode) for blade K + + Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,2,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Phi2(p%TipNode) for blade K + p%TwistedSF(K,2,2,p%TipNode,2) = -Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Psi2(p%TipNode) for blade K + + Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg ) + p%TwistedSF(K,1,3,p%TipNode,2) = Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Phi3(p%TipNode) for blade K + p%TwistedSF(K,2,3,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Psi3(p%TipNode) for blade K + + + ! Integrate to find the 1st and zeroeth derivatives of the twisted shape functions + ! at the tip: + + DO I = 1,2 ! Loop through Phi and Psi + DO L = 1,3 ! Loop through all blade DOFs + p%TwistedSF(K,I,L,p%TipNode,1) = p%TwistedSF(K,I,L,p%BldNodes,1) + TwstdSFOld(I,L,1) + p%TwistedSF(K,I,L,p%TipNode,0) = p%TwistedSF(K,I,L,p%BldNodes,0) + TwstdSFOld(I,L,0) + ENDDO ! L - All blade DOFs + ENDDO ! I - Phi and Psi + + ! the 1st and zeroeth derivatives of the twisted shape functions at the blade root: + p%TwistedSF(K,:,:,0,1) = 0.0_ReKi + p%TwistedSF(K,:,:,0,0) = 0.0_ReKi + p%AxRedBld( K,:,:,0 ) = 0.0_ReKi + + ! Integrate to find the blade axial reduction shape functions at the tip: + + DO I = 1,3 ! Loop through all blade DOFs + DO L = 1,3 ! Loop through all blade DOFs + p%AxRedBld(K,I,L,p%TipNode) = p%AxRedBld(K,I,L,p%BldNodes) + AxRdBldOld(I,L) + ENDDO ! L - All blade DOFs + ENDDO ! I - All blade DOFs + END IF ! p%BD4Blades + + + ENDDO ! K - Blades + + + + ! Calculate the tower-top mass: + + p%TwrTpMass = p%RotMass + p%RFrlMass + p%BoomMass + p%TFinMass + p%NacMass + p%YawBrMass + + + DO J = p%TwrNodes,1,-1 ! Loop through the tower nodes / elements in reverse + + + ! Calculate the mass of the current element + + p%TElmntMass(J) = p%MassT(J)*p%DHNodes(J) ! Mass of tower element J + + + ! Integrate to find the tower mass which will be output in .fsm + + p%TwrMass = p%TwrMass + p%TElmntMass(J) + + + ! Integrate to find TMssAbvNd: + + TMssAbvNd (J) = 0.5*p%TElmntMass(J) + + IF ( J == p%TwrNodes ) THEN ! Uppermost tower element + ! Add the TwrTpMass effects: + + TMssAbvNd(J) = TMssAbvNd(J) + p%TwrTpMass + ELSE ! All other tower elements + ! Add to TMssAbvNd(J) the effects from the (not yet used) portion of element J+1 + + TMssAbvNd(J) = 0.5*p%TElmntMass(J+1) + TMssAbvNd(J) + TMssAbvNd(J+1) + ENDIF + + + ENDDO ! J - Tower nodes / elements in reverse + + + + ! Initialize the generalized tower masses using tower-top mass effects: + + DO I = 1,2 ! Loop through all tower modes in a single direction + MTFA(I,I) = p%TwrTpMass + MTSS(I,I) = p%TwrTpMass + ENDDO ! I - All tower modes in a single direction + + ! set values for tower base (note that we haven't corrctly defined the values for (:,0,2) in the arrays below): + p%TwrFASF( :,0,0:1) = 0.0_ReKi + p%TwrSSSF( :,0,0:1) = 0.0_ReKi + p%AxRedTFA(:,:,0) = 0.0_ReKi + p%AxRedTSS(:,:,0) = 0.0_ReKi + + DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements + + + ! Calculate the tower shape functions (all derivatives): + + p%TwrFASF(1,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 2, ErrStat, ErrMsg ) + p%TwrFASF(2,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 2, ErrStat, ErrMsg ) + p%TwrFASF(1,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 1, ErrStat, ErrMsg ) + p%TwrFASF(2,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 1, ErrStat, ErrMsg ) + p%TwrFASF(1,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 0, ErrStat, ErrMsg ) + p%TwrFASF(2,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 0, ErrStat, ErrMsg ) + + p%TwrSSSF(1,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 2, ErrStat, ErrMsg ) + p%TwrSSSF(2,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 2, ErrStat, ErrMsg ) + p%TwrSSSF(1,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 1, ErrStat, ErrMsg ) + p%TwrSSSF(2,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 1, ErrStat, ErrMsg ) + p%TwrSSSF(1,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 0, ErrStat, ErrMsg ) + p%TwrSSSF(2,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 0, ErrStat, ErrMsg ) + + + ! Integrate to find the generalized mass of the tower (including tower-top mass effects). + ! Ignore the cross-correlation terms of MTFA (i.e. MTFA(i,j) where i /= j) and MTSS + ! since these terms will never be used. + + + DO I = 1,2 ! Loop through all tower DOFs in one direction + MTFA (I,I) = MTFA (I,I) + p%TElmntMass(J)*p%TwrFASF(I,J,0)**2 + MTSS (I,I) = MTSS (I,I) + p%TElmntMass(J)*p%TwrSSSF(I,J,0)**2 + ENDDO ! I - through all tower DOFs in one direction + + + ! Integrate to find the generalized stiffness of the tower (not including gravitational + ! effects). + + ElStffFA = p%StiffTFA(J)*p%DHNodes(J) ! Fore-aft stiffness of tower element J + ElStffSS = p%StiffTSS(J)*p%DHNodes(J) ! Side-to-side stiffness of tower element J + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + p%KTFA (I,L) = p%KTFA (I,L) + ElStffFA *p%TwrFASF(I,J,2)*p%TwrFASF(L,J,2) + p%KTSS (I,L) = p%KTSS (I,L) + ElStffSS *p%TwrSSSF(I,J,2)*p%TwrSSSF(L,J,2) + ENDDO ! L - All tower DOFs in one direction + ENDDO ! I - through all tower DOFs in one direction + + + ! Integrate to find the gravitational-term of the generalized stiffness of the tower. + ! Ignore the cross-correlation terms of KTFAGrav (i.e. KTFAGrav(i,j) where i /= j) + ! and KTSSGrav since these terms will never be used. + + ElmntStff = -TMssAbvNd(J)*p%DHNodes(J)*p%Gravity ! Gravitational stiffness of tower element J + + DO I = 1,2 ! Loop through all tower DOFs in one direction + KTFAGrav(I,I) = KTFAGrav(I,I) + ElmntStff*p%TwrFASF(I,J,1)**2 + KTSSGrav(I,I) = KTSSGrav(I,I) + ElmntStff*p%TwrSSSF(I,J,1)**2 + ENDDO + + + ! Integrate to find the tower axial reduction shape functions: + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + AxRdTFA (I,L) = 0.5*p%DHNodes(J)*p%TwrFASF(I,J,1)*p%TwrFASF(L,J,1) + AxRdTSS (I,L) = 0.5*p%DHNodes(J)*p%TwrSSSF(I,J,1)*p%TwrSSSF(L,J,1) + + p%AxRedTFA(I,L,J) = AxRdTFA(I,L) + p%AxRedTSS(I,L,J) = AxRdTSS(I,L) + ENDDO ! L - All tower DOFs in one direction + ENDDO + + IF ( J /= 1 ) THEN ! All but the lowermost tower element + ! Add the effects from the (not yet used) portion of element J-1 + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + p%AxRedTFA(I,L,J) = p%AxRedTFA(I,L,J) + p%AxRedTFA(I,L,J-1)+ AxRdTFAOld(I,L) + p%AxRedTSS(I,L,J) = p%AxRedTSS(I,L,J) + p%AxRedTSS(I,L,J-1)+ AxRdTSSOld(I,L) + ENDDO ! L - All tower DOFs in one direction + ENDDO + ENDIF + + + ! Store the AxRdTFA and AxRdTSS terms of the current element (these will be used for the next element) + + AxRdTFAOld = AxRdTFA + AxRdTSSOld = AxRdTSS + + + ENDDO ! J - Tower nodes / elements + + + ! Apply the modal stiffness tuners of the tower to KTFA() and KTSS(): + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + p%KTFA(I,L) = SQRT( InputFileData%FAStTunr(I)*InputFileData%FAStTunr(L) )*p%KTFA(I,L) + + p%KTSS(I,L) = SQRT( InputFileData%SSStTunr(I)*InputFileData%SSStTunr(L) )*p%KTSS(I,L) + ENDDO ! L - All tower DOFs in one direction + ENDDO ! I - through all tower DOFs in one direction + + + ! Calculate the tower natural frequencies: + + DO I = 1,2 ! Loop through all tower DOFs in one direction + p%FreqTFA(I,1) = Inv2Pi*SQRT( p%KTFA(I,I) /( MTFA(I,I) - p%TwrTpMass ) ) ! Natural tower I-fore-aft frequency w/o gravitational destiffening nor tower-top mass effects + p%FreqTFA(I,2) = Inv2Pi*SQRT( ( p%KTFA(I,I) + KTFAGrav(I,I) )/ MTFA(I,I) ) ! Natural tower I-fore-aft frequency w/ gravitational destiffening and tower-top mass effects + p%FreqTSS(I,1) = Inv2Pi*SQRT( p%KTSS(I,I) /( MTSS(I,I) - p%TwrTpMass ) ) ! Natural tower I-side-to-side frequency w/o gravitational destiffening nor tower-top mass effects + p%FreqTSS(I,2) = Inv2Pi*SQRT( ( p%KTSS(I,I) + KTSSGrav(I,I) )/ MTSS(I,I) ) ! Natural tower I-side-to-side frequency w/ gravitational destiffening and tower-top mass effects + ENDDO ! I - All tower DOFs in one direction + + + ! Calculate the generalized damping of the tower: + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + p%CTFA(I,L) = ( 0.01*InputFileData%TwrFADmp(L) )*p%KTFA(I,L)/( Pi*p%FreqTFA(L,1) ) + + p%CTSS(I,L) = ( 0.01*InputFileData%TwrSSDmp(L) )*p%KTSS(I,L)/( Pi*p%FreqTSS(L,1) ) + ENDDO ! L - All tower DOFs in one direction + ENDDO ! I - All tower DOFs in one direction + + + ! Calculate the tower shape functions (all derivatives) at the tower-top: + + p%TwrFASF(1,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 2, ErrStat, ErrMsg ) + p%TwrFASF(2,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 2, ErrStat, ErrMsg ) + p%TwrFASF(1,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 1, ErrStat, ErrMsg ) + p%TwrFASF(2,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 1, ErrStat, ErrMsg ) + p%TwrFASF(1,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 0, ErrStat, ErrMsg ) + p%TwrFASF(2,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 0, ErrStat, ErrMsg ) + + p%TwrSSSF(1,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 2, ErrStat, ErrMsg ) + p%TwrSSSF(2,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 2, ErrStat, ErrMsg ) + p%TwrSSSF(1,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 1, ErrStat, ErrMsg ) + p%TwrSSSF(2,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 1, ErrStat, ErrMsg ) + p%TwrSSSF(1,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 0, ErrStat, ErrMsg ) + p%TwrSSSF(2,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 0, ErrStat, ErrMsg ) + + + ! Integrate to find the tower axial reduction shape functions at the tower-top: + + DO I = 1,2 ! Loop through all tower DOFs in one direction + DO L = 1,2 ! Loop through all tower DOFs in one direction + p%AxRedTFA(I,L,p%TTopNode) = p%AxRedTFA(I,L,p%TwrNodes)+ AxRdTFAOld(I,L) + p%AxRedTSS(I,L,p%TTopNode) = p%AxRedTSS(I,L,p%TwrNodes)+ AxRdTSSOld(I,L) + ENDDO ! L - All tower DOFs in one direction + ENDDO + + + ! Calculate the turbine mass: + + p%TurbMass = p%TwrTpMass + p%TwrMass + + + RETURN +END SUBROUTINE Coeff +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the initial blade deflections. +!! Base the intial values of the blade DOFs, INITQF1, INITQF2, and +!! INITQE1, on OoPDefl and IPDefl. +!! Write messages to the screen if the specified initial tip displacements +!! are incompatible with the enabled DOFs. +SUBROUTINE InitBlDefl ( p, InputFileData, InitQF1, InitQF2, InitQE1, ErrStat, ErrMsg ) +!.................................................................................................................................. + + + ! Passed variables: + TYPE(ED_ParameterType), INTENT(IN) :: p !< parameters of the structural dynamics module + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< all the data in the ElastoDyn input file + + REAL(ReKi), INTENT(OUT) :: InitQE1(p%NumBl) !< Initial edge deflection (output). + REAL(ReKi), INTENT(OUT) :: InitQF1(p%NumBl) !< Initial flap deflection for mode 1 (output). + REAL(ReKi), INTENT(OUT) :: InitQF2(p%NumBl) !< Initial flap deflection for mode 2 (output). + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(ErrMsgLen), INTENT(OUT) :: ErrMsg !< Error message when ErrStat =/ ErrID_None + + + ! Local variables: + REAL(ReKi) :: A(2,3) ! Augmented matrix for solution of initial deflections. + REAL(ReKi) :: CosPitch ! Cosine of the pitch for this blade. + REAL(ReKi) :: Det ! Determinate of right-hand side of A. + REAL(ReKi) :: SinPitch ! Sine of the pitch for this blade. + REAL(ReKi) :: TotResid ! Generator torque. + + INTEGER(IntKi) :: K ! Blade number + + ! some warning messages + CHARACTER(*), PARAMETER :: Approx = ' An approximate characterization of the specified blade deflection will be made.' + CHARACTER(*), PARAMETER :: BadIP = ' Initial blade in-plane tip displacement will be ignored.' + CHARACTER(*), PARAMETER :: BadOoP = ' Initial blade out-of-plane tip displacement will be ignored.' + CHARACTER(*), PARAMETER :: Ignore = ' All initial blade tip displacements will be ignored.' + + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + InitQE1 = 0.0 + InitQF1 = 0.0 + InitQF2 = 0.0 + !bjj: replace InitQF1 and InitQF2 with an array to avoid so much duplication of logic here... + + DO K=1,p%NumBl + + ! Calculate the array of deflections(???). + + CosPitch = COS( InputFileData%BlPitch(K) ) + SinPitch = SIN( InputFileData%BlPitch(K) ) + + A(1,2) = p%TwistedSF(K,1,3,p%TipNode,0)*CosPitch + p%TwistedSF(K,2,3,p%TipNode,0)*SinPitch + A(2,2) = -p%TwistedSF(K,1,3,p%TipNode,0)*SinPitch + p%TwistedSF(K,2,3,p%TipNode,0)*CosPitch + A(1,3) = InputFileData%OoPDefl + A(2,3) = InputFileData%IPDefl + + IF ( InputFileData%FlapDOF1 ) THEN ! Blade flap mode 1 is enabled + + A(1,1) = p%TwistedSF(K,1,1,p%TipNode,0)*CosPitch + p%TwistedSF(K,2,1,p%TipNode,0)*SinPitch + A(2,1) = -p%TwistedSF(K,1,1,p%TipNode,0)*SinPitch + p%TwistedSF(K,2,1,p%TipNode,0)*CosPitch + + DET = ( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) + + IF ( .NOT. EqualRealNos( DET, 0.0_ReKi ) ) THEN ! Apply all flap deflection to mode 1 + + InitQF1(K) = ( A(1,3)*A(2,2) - A(1,2)*A(2,3) )/DET + InitQE1(K) = ( A(1,1)*A(2,3) - A(1,3)*A(2,1) )/DET + + ELSEIF ( .NOT. InputFileData%EdgeDOF ) THEN ! Blade edge mode 1 is not enabled which caused DET = 0. + + InitQE1(K) = 0.0 + + IF ( .NOT. EqualRealNos( A(1,1), 0.0_ReKi ) ) THEN + IF ( .NOT. EqualRealNos( A(2,1), 0.0_ReKi ) ) THEN ! Find a solution of the 2 equations in 1 variable that + ! minimizes the sum of the squares of the equation's residuals. + + InitQF1(K) = ( A(1,1)*A(1,3) + A(2,1)*A(2,3) )/( A(1,1)**2 + A(2,1)**2 ) + + TotResid = SQRT( ( A(1,1)*InitQF1(K) - A(1,3) )**2 + ( A(2,1)*InitQF1(K) - A(2,3) )**2 ) + + IF ( .NOT. EqualRealNos( TotResid, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, Approx ) + ENDIF + + ELSE !A(1,1) /= 0; A(2,1) == 0 + + InitQF1(K) = A(1,3)/A(1,1) + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + + ENDIF + + ELSE ! A(1,1) == 0 + + IF ( .NOT. EqualRealNos( InputFileData%OoPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadOoP ) + END IF + + IF ( .NOT. EqualRealNos( A(2,1), 0.0_ReKi ) ) THEN + InitQF1(K) = A(2,3)/A(2,1) + ELSE + InitQF1(K) = 0.0 + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + + ENDIF + ENDIF + + ELSE ! It is impossible to find any "good" solution, so ignore the initial tip displacements + + InitQF1(K) = 0.0 + InitQE1(K) = 0.0 + + IF ( ( InputFileData%OoPDefl /= 0.0 ) .OR. ( InputFileData%IPDefl /= 0.0 ) ) THEN + CALL CheckError( ErrID_Warn, Ignore ) + ENDIF + + ENDIF + + ELSE ! Blade flap mode 1 is not enabled. + + InitQF1(K) = 0.0 + + IF ( InputFileData%FlapDOF2 ) THEN ! Blade flap mode 2 is enabled. + + A(1,1) = p%TwistedSF(K,1,2,p%TipNode,0)*CosPitch + p%TwistedSF(K,2,2,p%TipNode,0)*SinPitch + A(2,1) = -p%TwistedSF(K,1,2,p%TipNode,0)*SinPitch + p%TwistedSF(K,2,2,p%TipNode,0)*CosPitch + + DET = ( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) + + IF ( .NOT. EqualRealNos( DET, 0.0_ReKi ) ) THEN ! Apply all flap deflection to mode 2 + InitQF2 = ( A(1,3)*A(2,2) - A(1,2)*A(2,3) )/DET + InitQE1 = ( A(1,1)*A(2,3) - A(1,3)*A(2,1) )/DET + + ELSEIF ( .NOT. InputFileData%EdgeDOF ) THEN ! Blade edge mode 1 is not enabled which caused DET = 0. + + InitQE1(K) = 0.0 + + IF ( .NOT. EqualRealNos( A(1,1), 0.0_ReKi ) ) THEN + IF ( .NOT. EqualRealNos( A(2,1), 0.0_ReKi ) ) THEN ! Find a solution of the 2 equations in 1 variable that + ! minimizes the sum of the squares of the equation's residuals + InitQF2(K) = ( A(1,1)*A(1,3) + A(2,1)*A(2,3) )/( A(1,1)**2 + A(2,1)**2 ) + + TotResid = SQRT( ( A(1,1)*InitQF2(K) - A(1,3))**2 + ( A(2,1)*InitQF2(K) - A(2,3) )**2 ) + + IF ( .NOT. EqualRealNos( TotResid, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, Approx ) + ENDIF + ELSE + InitQF2(K) = A(1,3)/A(1,1) + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + ENDIF + ELSE + IF ( .NOT. EqualRealNos( InputFileData%OoPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadOoP ) + END IF + + IF ( .NOT. EqualRealNos( A(2,1), 0.0_ReKi ) ) THEN + InitQF2(K) = A(2,3)/A(2,1) + ELSE + InitQF2(K) = 0.0 + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + + ENDIF + ENDIF + + ELSE ! It is impossible to find any "good" solution, so ignore + ! the initial tip displacements. + InitQF2(K) = 0.0 + InitQE1(K) = 0.0 + + IF ( .NOT. EqualRealNos( InputFileData%OoPDefl, 0.0_ReKi ) .OR. & + .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, Ignore ) + ENDIF + ENDIF + + ELSE ! Blade flap mode 2 is not enabled. + + InitQF2(K) = 0.0 + + IF ( .NOT. EqualRealNos( A(1,2), 0.0_ReKi ) ) THEN + + IF ( .NOT. EqualRealNos( A(2,2), 0.0_ReKi ) ) THEN ! Find a solution of the 2 equations in 1 variable that minimizes + ! the sum of the squares of the equation's residuals. + InitQE1(K) = ( A(1,2)*A(1,3) + A(2,2)*A(2,3) )/( A(1,2)**2 + A(2,2)**2 ) + + TotResid = SQRT( ( A(1,2)*InitQE1(K) - A(1,3) )**2 + ( A(2,2)*InitQE1(K) - A(2,3) )**2) + + IF ( .NOT. EqualRealNos( TotResid, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, Approx ) + ENDIF + + ELSE + + InitQE1(K) = A(1,3)/A(1,2) + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + + ENDIF + + ELSE + + IF ( .NOT. EqualRealNos( InputFileData%OoPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadOoP ) + END IF + + IF ( .NOT. EqualRealNos( A(2,2), 0.0_ReKi ) ) THEN + InitQE1(K) = A(2,3)/A(2,2) + ELSE + InitQE1(K) = 0.0 + + IF ( .NOT. EqualRealNos( InputFileData%IPDefl, 0.0_ReKi ) ) THEN + CALL CheckError( ErrID_Warn, BadIP ) + ENDIF + + ENDIF + + ENDIF + + ENDIF + + ENDIF + + END DO !K + + RETURN +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'InitBlDefl:Blade '//TRIM(Num2LStr(K))// & + ' initial blade tip displacements are Incompat with enabled DOFs: '//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE InitBlDefl +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used create arrays of DOF indices (pointers / (vector susbscript arrays) that contribute to the QD2T-related +!! linear accelerations of various points within the system in the inertia frame, based on which DOFs are presently enabled. +!! NOTE: The order in which the DOFs are tested within this routine and hence the order in which the DOF indices appear in the +!! vector subscript arrays, determines the order in which the states will appear in the linearized model created by FAST +!! when AnalMode == 2. This order is not necessarily sorted from smallest to largest DOF index. +!! bjj: note that this routine is now called only in the initialization routine. It is not available during time simulation. +SUBROUTINE SetEnabledDOFIndexArrays( p ) +!---------------------------------------------------------------------------------------------------------------------------------- + + ! passed variables + TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module + + ! Local Variables: + INTEGER(IntKi) :: I ! Loops through all DOFs. + INTEGER(IntKi) :: K ! Loops through blades. + + + + ! Initialize total counts to zero. + + p%DOFs%NActvDOF = 0 + p%DOFs%NPCE = 0 + p%DOFs%NPDE = 0 + p%DOFs%NPIE = 0 + p%DOFs%NPTTE = 0 + p%DOFs%NPTE = 0 + p%DOFs%NPSBE(:) = 0 + p%DOFs%NPSE (:) = 0 + p%DOFs%NPUE = 0 + p%DOFs%NPYE = 0 + + + ! Test each DOF and include the appropriate indices in the subscript arrays + ! and total counts: + + IF ( p%DOF_Flag(DOF_Sg ) ) THEN ! Platform surge. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Sg + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Sg + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_Sg + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_Sg + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_Sg + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Sg + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_Sg + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_Sg + + ENDIF + + + IF ( p%DOF_Flag(DOF_Sw ) ) THEN ! Platform sway. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Sw + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Sw + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_Sw + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_Sw + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_Sw + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Sw + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_Sw + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_Sw + + ENDIF + + + IF ( p%DOF_Flag(DOF_Hv ) ) THEN ! Platform heave. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Hv + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Hv + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_Hv + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_Hv + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_Hv + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Hv + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_Hv + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_Hv + + ENDIF + + + IF ( p%DOF_Flag(DOF_R ) ) THEN ! Platform roll. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_R + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_R + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_R + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_R + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_R + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_R + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_R + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_R + + ENDIF + + + IF ( p%DOF_Flag(DOF_P ) ) THEN ! Platform pitch. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_P + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_P + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_P + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_P + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_P + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_P + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_P + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_P + + ENDIF + + + IF ( p%DOF_Flag(DOF_Y ) ) THEN ! Platform yaw. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + p%DOFs%NPYE = p%DOFs%NPYE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Y + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Y + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_Y + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_Y + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_Y + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Y + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_Y + p%DOFs%PYE ( p%DOFs%NPYE ) = DOF_Y + + ENDIF + + + IF ( p%DOF_Flag(DOF_TFA1) ) THEN ! 1st tower fore-aft. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTTE = p%DOFs%NPTTE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_TFA1 + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_TFA1 + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_TFA1 + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_TFA1 + p%DOFs%PTTE ( p%DOFs%NPTTE ) = DOF_TFA1 + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_TFA1 + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_TFA1 + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_TFA1 + + ENDIF + + + IF ( p%DOF_Flag(DOF_TSS1) ) THEN ! 1st tower side-to-side. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTTE = p%DOFs%NPTTE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_TSS1 + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_TSS1 + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_TSS1 + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_TSS1 + p%DOFs%PTTE ( p%DOFs%NPTTE ) = DOF_TSS1 + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_TSS1 + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_TSS1 + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_TSS1 + + ENDIF + + + IF ( p%DOF_Flag(DOF_TFA2) ) THEN ! 2nd tower fore-aft. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTTE = p%DOFs%NPTTE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_TFA2 + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_TFA2 + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_TFA2 + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_TFA2 + p%DOFs%PTTE ( p%DOFs%NPTTE ) = DOF_TFA2 + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_TFA2 + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_TFA2 + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_TFA2 + + ENDIF + + + IF ( p%DOF_Flag(DOF_TSS2) ) THEN ! 2nd tower side-to-side. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPTTE = p%DOFs%NPTTE + 1 + p%DOFs%NPTE = p%DOFs%NPTE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_TSS2 + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_TSS2 + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_TSS2 + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_TSS2 + p%DOFs%PTTE ( p%DOFs%NPTTE ) = DOF_TSS2 + p%DOFs%PTE ( p%DOFs%NPTE ) = DOF_TSS2 + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_TSS2 + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_TSS2 + + ENDIF + + + IF ( p%DOF_Flag(DOF_Yaw ) ) THEN ! Nacelle yaw. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + p%DOFs%NPUE = p%DOFs%NPUE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Yaw + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Yaw + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_Yaw + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_Yaw + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Yaw + p%DOFs%PUE ( p%DOFs%NPUE ) = DOF_Yaw + + ENDIF + + + IF ( p%DOF_Flag(DOF_TFrl) ) THEN ! Tail-furl. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPIE = p%DOFs%NPIE + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_TFrl + p%DOFs%PIE ( p%DOFs%NPIE ) = DOF_TFrl + + ENDIF + + + IF ( p%DOF_Flag(DOF_RFrl) ) THEN ! Rotor-furl. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPDE = p%DOFs%NPDE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_RFrl + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_RFrl + p%DOFs%PDE ( p%DOFs%NPDE ) = DOF_RFrl + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_RFrl + + ENDIF + + + IF ( p%DOF_Flag(DOF_GeAz) ) THEN ! Generator azimuth. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_GeAz + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_GeAz + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_GeAz + + ENDIF + + + IF ( p%DOF_Flag(DOF_DrTr) ) THEN ! Drivetrain torsion. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_DrTr + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_DrTr + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_DrTr + + ENDIF + + + IF ( p%NumBl == 2 ) THEN + IF ( p%DOF_Flag(DOF_Teet ) ) THEN ! Rotor-teeter. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPCE = p%DOFs%NPCE + 1 + p%DOFs%NPSE (:) = p%DOFs%NPSE (:) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_Teet + p%DOFs%PCE ( p%DOFs%NPCE ) = DOF_Teet + p%DOFs%PSE (:,p%DOFs%NPSE (:)) = DOF_Teet + + ENDIF + ENDIF + + + DO K = 1,p%NumBl ! Loop through all blades + IF ( p%DOF_Flag(DOF_BF(K,1)) ) THEN ! 1st blade flap. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPSBE(K) = p%DOFs%NPSBE(K) + 1 + p%DOFs%NPSE (K) = p%DOFs%NPSE (K) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_BF(K,1) + p%DOFs%PSBE (K,p%DOFs%NPSBE(K)) = DOF_BF(K,1) + p%DOFs%PSE (K,p%DOFs%NPSE (K)) = DOF_BF(K,1) + + ENDIF + ENDDO ! K - Blades + + + DO K = 1,p%NumBl ! Loop through all blades + IF ( p%DOF_Flag(DOF_BE(K,1)) ) THEN ! 1st blade edge. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPSBE(K) = p%DOFs%NPSBE(K) + 1 + p%DOFs%NPSE (K) = p%DOFs%NPSE (K) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_BE(K,1) + p%DOFs%PSBE (K,p%DOFs%NPSBE(K)) = DOF_BE(K,1) + p%DOFs%PSE (K,p%DOFs%NPSE (K)) = DOF_BE(K,1) + + ENDIF + ENDDO ! K - Blades + + + DO K = 1,p%NumBl ! Loop through all blades + IF ( p%DOF_Flag(DOF_BF(K,2)) ) THEN ! 2nd blade flap. + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + p%DOFs%NPSBE(K) = p%DOFs%NPSBE(K) + 1 + p%DOFs%NPSE (K) = p%DOFs%NPSE (K) + 1 + + p%DOFs%PS ( p%DOFs%NActvDOF) = DOF_BF(K,2) + p%DOFs%PSBE (K,p%DOFs%NPSBE(K)) = DOF_BF(K,2) + p%DOFs%PSE (K,p%DOFs%NPSE (K)) = DOF_BF(K,2) + + ENDIF + ENDDO ! K - Blades + + + + ! Compute the sorted (from smallest to largest p%DOFs index) version of PS(), + ! SrtPS(), and SrtPSNAUG(). At the same time compute Diag(), which is an + ! array containing the indices of SrtPS() associated with each enabled + ! DOF; that is, SrtPS(Diag(I)) = I: + ! NOTE: This calculation is recomputing NActvDOF as computed above. This is + ! of no concern however, since the resulting value will be the same. + + p%DOFs%NActvDOF = 0 + DO I = 1,p%NDOF ! Loop through all DOFs + IF ( p%DOF_Flag(I) ) THEN ! .TRUE. if the corresponding DOF is enabled + + p%DOFs%NActvDOF = p%DOFs%NActvDOF + 1 + + p%DOFs%SrtPS (p%DOFs%NActvDOF) = I + p%DOFs%SrtPSNAUG (p%DOFs%NActvDOF) = I + p%DOFs%Diag (I ) = p%DOFs%NActvDOF + + ENDIF + ENDDO ! I - All DOFs + + p%DOFs%SrtPSNAUG ( p%DOFs%NActvDOF + 1 ) = p%NAug + + + RETURN +END SUBROUTINE SetEnabledDOFIndexArrays +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to define the internal coordinate systems for this particular time step. +!! It also sets the TeeterAng and TeetAngVel for this time step. +SUBROUTINE SetCoordSy( t, CoordSys, RtHSdat, BlPitch, p, x, ErrStat, ErrMsg ) + + ! Subroutine arguments (passed variables) + + REAL(DbKi), INTENT(IN) :: t !< Current simulation time, in seconds (used only for SmllRotTrans error messages) + REAL(ReKi), INTENT(IN) :: BlPitch (:) !< The current blade pitch + TYPE(ED_CoordSys), INTENT(INOUT) :: CoordSys !< The coordinate systems to be set + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module + TYPE(ED_ParameterType), INTENT(IN) :: p !< The module's parameters + TYPE(ED_ContinuousStateType), INTENT(IN) :: x !< The module's continuous states + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables + + REAL(R8Ki) :: CAzimuth ! COS( rotor azimuth angle ). + REAL(R8Ki) :: CgRotAng ! COS( gRotAng ). + REAL(R8Ki) :: CNacYaw ! COS( nacelle yaw angle ). + REAL(R8Ki) :: CosPitch ! COS( the current pitch angle ). + REAL(R8Ki) :: CPitPTwstA ! COS( BlPitch(K) + AeroTwst(J) ) found using the sum of angles formulae of cosine. + REAL(R8Ki) :: CPitPTwstS ! COS( BlPitch(K) + ThetaS(K,J) ) found using the sum of angles formulae of cosine. + REAL(R8Ki) :: CRotFurl ! COS( rotor-furl angle ). + REAL(R8Ki) :: CTailFurl ! COS( tail-furl angle ). + REAL(R8Ki) :: CTeetAng ! COS( TeetAng ). + REAL(R8Ki) :: g1Prime (3) ! = g1. + REAL(R8Ki) :: g2Prime (3) ! completes the right-handed gPrime-vector triad + REAL(R8Ki) :: g3Prime (3) ! = g3 rotated about g1 so that parallel to the pitching axis of blade K (i.e., the current blade in the blade loop). + REAL(R8Ki) :: gRotAng ! Angle of rotation about g1 to get from the g to the gPrime system. + REAL(R8Ki) :: Lj1 (3) ! vector / direction Lj1 at node J for blade K. + REAL(R8Ki) :: Lj2 (3) ! vector / direction Lj2 at node J for blade K. + REAL(R8Ki) :: Lj3 (3) ! vector / direction Lj3 at node J for blade K. + REAL(R8Ki) :: SAzimuth ! SIN( rotor azimuth angle ). + REAL(R8Ki) :: SgRotAng ! SIN( gRotAng ). + REAL(R8Ki) :: SinPitch ! SIN( the current pitch angle ). + REAL(R8Ki) :: SNacYaw ! SIN( nacelle yaw angle ). + REAL(R8Ki) :: SPitPTwstA ! SIN( BlPitch(K) + AeroTwst(J) ) found using the sum of angles formulae of sine. + REAL(R8Ki) :: SPitPTwstS ! SIN( BlPitch(K) + ThetaS(K,J) ) found using the sum of angles formulae of sine. + REAL(R8Ki) :: SRotFurl ! SIN( rotor-furl angle ). + REAL(R8Ki) :: STailFurl ! SIN( tail-furl angle ). + REAL(R8Ki) :: STeetAng ! SIN( TeetAng ). + REAL(R8Ki) :: ThetaFA ! Tower fore-aft tilt deflection angle. + REAL(R8Ki) :: ThetaIP ! Blade in-plane deflection angle at node J for blade K. + REAL(R8Ki) :: ThetaLxb ! Blade deflection angle about the Lxb (n1) -axis at node J for blade K. + REAL(R8Ki) :: ThetaLyb ! Blade deflection angle about the Lyb (n2) -axis at node J for blade K. + REAL(R8Ki) :: ThetaOoP ! Blade out-of-plane deflection angle at node J for blade K. + REAL(R8Ki) :: ThetaSS ! Tower side-to-side tilt deflection angle. + REAL(R8Ki) :: TransMat (3,3) ! The resulting transformation matrix due to three orthogonal rotations, (-). + + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + + + INTEGER(IntKi) :: ErrStat2 ! Temporary error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message + + + ErrStat = ErrID_None + ErrMsg = '' + + ! Inertial frame coordinate system: + + CoordSys%z1 = (/ 1.0_R8Ki, 0.0_R8Ki, 0.0_R8Ki /) ! Vector / direction z1 (= xi from the IEC coord. system). + CoordSys%z2 = (/ 0.0_R8Ki, 1.0_R8Ki, 0.0_R8Ki /) ! Vector / direction z2 (= zi from the IEC coord. system). + CoordSys%z3 = (/ 0.0_R8Ki, 0.0_R8Ki, 1.0_R8Ki /) ! Vector / direction z3 (= -yi from the IEC coord. system). + + + ! Tower base / platform coordinate system: + + CALL SmllRotTrans( 'platform displacement (ElastoDyn SetCoordSy)', x%QT(DOF_R), x%QT(DOF_Y), -x%QT(DOF_P), TransMat, TRIM(Num2LStr(t))//' s', ErrStat2, ErrMsg2 ) ! Get the transformation matrix, TransMat, from inertial frame to tower base / platform coordinate systems. + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CoordSys%a1 = TransMat(1,1)*CoordSys%z1 + TransMat(1,2)*CoordSys%z2 + TransMat(1,3)*CoordSys%z3 ! Vector / direction a1 (= xt from the IEC coord. system). + CoordSys%a2 = TransMat(2,1)*CoordSys%z1 + TransMat(2,2)*CoordSys%z2 + TransMat(2,3)*CoordSys%z3 ! Vector / direction a2 (= zt from the IEC coord. system). + CoordSys%a3 = TransMat(3,1)*CoordSys%z1 + TransMat(3,2)*CoordSys%z2 + TransMat(3,3)*CoordSys%z3 ! Vector / direction a3 (= -yt from the IEC coord. system). + + + DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements + + + ! Tower element-fixed coordinate system: + + ThetaFA = -p%TwrFASF(1,J ,1)*x%QT(DOF_TFA1) - p%TwrFASF(2,J ,1)*x%QT(DOF_TFA2) + ThetaSS = p%TwrSSSF(1,J ,1)*x%QT(DOF_TSS1) + p%TwrSSSF(2,J ,1)*x%QT(DOF_TSS2) + + CALL SmllRotTrans( 'tower deflection (ElastoDyn SetCoordSy)', ThetaSS, 0.0_R8Ki, ThetaFA, TransMat, TRIM(Num2LStr(t))//' s', ErrStat2, ErrMsg2 ) ! Get the transformation matrix, TransMat, from tower-base to tower element-fixed coordinate systems. + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CoordSys%t1(J,:) = TransMat(1,1)*CoordSys%a1 + TransMat(1,2)*CoordSys%a2 + TransMat(1,3)*CoordSys%a3 ! Vector / direction t1 for tower node J (= Lxt from the IEC coord. system). + CoordSys%t2(J,:) = TransMat(2,1)*CoordSys%a1 + TransMat(2,2)*CoordSys%a2 + TransMat(2,3)*CoordSys%a3 ! Vector / direction t2 for tower node J (= Lzt from the IEC coord. system). + CoordSys%t3(J,:) = TransMat(3,1)*CoordSys%a1 + TransMat(3,2)*CoordSys%a2 + TransMat(3,3)*CoordSys%a3 ! Vector / direction t3 for tower node J (= -Lyt from the IEC coord. system). + + + ENDDO ! J - Tower nodes / elements + + + ! Tower-top / base plate coordinate system: + + ThetaFA = -p%TwrFASF(1,p%TTopNode,1)*x%QT(DOF_TFA1) - p%TwrFASF(2,p%TTopNode,1)*x%QT(DOF_TFA2) + ThetaSS = p%TwrSSSF(1,p%TTopNode,1)*x%QT(DOF_TSS1) + p%TwrSSSF(2,p%TTopNode,1)*x%QT(DOF_TSS2) + + CALL SmllRotTrans( 'tower deflection (ElastoDyn SetCoordSy)', ThetaSS, 0.0_R8Ki, ThetaFA, TransMat, TRIM(Num2LStr(t))//' s', ErrStat2, ErrMsg2 ) ! Get the transformation matrix, TransMat, from tower-base to tower-top/base-plate coordinate systems. + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CoordSys%b1 = TransMat(1,1)*CoordSys%a1 + TransMat(1,2)*CoordSys%a2 + TransMat(1,3)*CoordSys%a3 ! Vector / direction b1 (= xp from the IEC coord. system). + CoordSys%b2 = TransMat(2,1)*CoordSys%a1 + TransMat(2,2)*CoordSys%a2 + TransMat(2,3)*CoordSys%a3 ! Vector / direction b2 (= zp from the IEC coord. system). + CoordSys%b3 = TransMat(3,1)*CoordSys%a1 + TransMat(3,2)*CoordSys%a2 + TransMat(3,3)*CoordSys%a3 ! Vector / direction b3 (= -yp from the IEC coord. system). + + + ! Nacelle / yaw coordinate system: + + CNacYaw = COS( x%QT(DOF_Yaw ) ) + SNacYaw = SIN( x%QT(DOF_Yaw ) ) + + CoordSys%d1 = CNacYaw*CoordSys%b1 - SNacYaw*CoordSys%b3 ! Vector / direction d1 (= xn from the IEC coord. system). + CoordSys%d2 = CoordSys%b2 ! Vector / direction d2 (= zn from the IEC coord. system). + CoordSys%d3 = SNacYaw*CoordSys%b1 + CNacYaw*CoordSys%b3 ! Vector / direction d3 (= -yn from the IEC coord. system). + + + ! Rotor-furl coordinate system: + + CRotFurl = COS( x%QT(DOF_RFrl) ) + SRotFurl = SIN( x%QT(DOF_RFrl) ) + + CoordSys%rf1 = ( ( 1.0 - p%CRFrlSkw2*p%CRFrlTlt2 )*CRotFurl + p%CRFrlSkw2*p%CRFrlTlt2 )*CoordSys%d1 & + + ( p%CRFrlSkew*p%CSRFrlTlt*( 1.0 - CRotFurl ) - p%SRFrlSkew*p%CRFrlTilt*SRotFurl )*CoordSys%d2 & + + ( p%CSRFrlSkw*p%CRFrlTlt2*( CRotFurl - 1.0 ) - p%SRFrlTilt*SRotFurl )*CoordSys%d3 + CoordSys%rf2 = ( p%CRFrlSkew*p%CSRFrlTlt*( 1.0 - CRotFurl ) + p%SRFrlSkew*p%CRFrlTilt*SRotFurl )*CoordSys%d1 & + + ( p%CRFrlTlt2* CRotFurl + p%SRFrlTlt2 )*CoordSys%d2 & + + ( p%SRFrlSkew*p%CSRFrlTlt*( CRotFurl - 1.0 ) + p%CRFrlSkew*p%CRFrlTilt*SRotFurl )*CoordSys%d3 + CoordSys%rf3 = ( p%CSRFrlSkw*p%CRFrlTlt2*( CRotFurl - 1.0 ) + p%SRFrlTilt*SRotFurl )*CoordSys%d1 & + + ( p%SRFrlSkew*p%CSRFrlTlt*( CRotFurl - 1.0 ) - p%CRFrlSkew*p%CRFrlTilt*SRotFurl )*CoordSys%d2 & + + ( ( 1.0 - p%SRFrlSkw2*p%CRFrlTlt2 )*CRotFurl + p%SRFrlSkw2*p%CRFrlTlt2 )*CoordSys%d3 + CoordSys%rfa = p%CRFrlSkew*p%CRFrlTilt*CoordSys%d1 + p%SRFrlTilt*CoordSys%d2 - p%SRFrlSkew*p%CRFrlTilt*CoordSys%d3 + + + ! Shaft coordinate system: + + CoordSys%c1 = p%CShftSkew*p%CShftTilt*CoordSys%rf1 + p%SShftTilt*CoordSys%rf2 - p%SShftSkew*p%CShftTilt*CoordSys%rf3 ! Vector / direction c1 (= xs from the IEC coord. system). + CoordSys%c2 = -p%CShftSkew*p%SShftTilt*CoordSys%rf1 + p%CShftTilt*CoordSys%rf2 + p%SShftSkew*p%SShftTilt*CoordSys%rf3 ! Vector / direction c2 (= zs from the IEC coord. system). + CoordSys%c3 = p%SShftSkew* CoordSys%rf1 + p%CShftSkew* CoordSys%rf3 ! Vector / direction c3 (= -ys from the IEC coord. system). + + + ! Azimuth coordinate system: + + CAzimuth = COS( x%QT(DOF_DrTr) + x%QT(DOF_GeAz) ) + SAzimuth = SIN( x%QT(DOF_DrTr) + x%QT(DOF_GeAz) ) + + CoordSys%e1 = CoordSys%c1 ! Vector / direction e1 (= xa from the IEC coord. system). + CoordSys%e2 = CAzimuth*CoordSys%c2 + SAzimuth*CoordSys%c3 ! Vector / direction e2 (= ya from the IEC coord. system). + CoordSys%e3 = -SAzimuth*CoordSys%c2 + CAzimuth*CoordSys%c3 ! Vector / direction e3 (= za from the IEC coord. system). + + + ! Teeter coordinate system: + + ! Lets define TeetAng, which is the current teeter angle (= QT(DOF_Teet) for + ! 2-blader or 0 for 3-blader) and is used in place of QT(DOF_Teet) + ! throughout SUBROUTINE RtHS(). Doing it this way, we can run the same + ! equations of motion for both the 2 and 3-blader configurations even + ! though a 3-blader does not have a teetering DOF. + + IF ( p%NumBl == 2 ) THEN ! 2-blader + RtHSdat%TeetAng = x%QT (DOF_Teet) + RtHSdat%TeetAngVel = x%QDT(DOF_Teet) + ELSE ! 3-blader + RtHSdat%TeetAng = 0.0 ! Teeter is not an available DOF for a 3-blader + RtHSdat%TeetAngVel = 0.0 ! Teeter is not an available DOF for a 3-blader + ENDIF + CTeetAng = COS( RtHSdat%TeetAng ) + STeetAng = SIN( RtHSdat%TeetAng ) + + CoordSys%f1 = CTeetAng*CoordSys%e1 - STeetAng*CoordSys%e3 ! Vector / direction f1. + CoordSys%f2 = CoordSys%e2 ! Vector / direction f2. + CoordSys%f3 = STeetAng*CoordSys%e1 + CTeetAng*CoordSys%e3 ! Vector / direction f3. + + + ! Hub / delta-3 coordinate system: + + CoordSys%g1 = CoordSys%f1 ! Vector / direction g1 (= xh from the IEC coord. system). + CoordSys%g2 = p%CosDel3*CoordSys%f2 + p%SinDel3*CoordSys%f3 ! Vector / direction g2 (= yh from the IEC coord. system). + CoordSys%g3 = -p%SinDel3*CoordSys%f2 + p%CosDel3*CoordSys%f3 ! Vector / direction g3 (= zh from the IEC coord. system). + + + DO K = 1,p%NumBl ! Loop through all blades + + + ! Hub (Prime) coordinate system rotated to match blade K. + + gRotAng = p%TwoPiNB*(K-1) + CgRotAng = COS( gRotAng ) + SgRotAng = SIN( gRotAng ) + + g1Prime = CoordSys%g1 + g2Prime = CgRotAng*CoordSys%g2 + SgRotAng*CoordSys%g3 + g3Prime = -SgRotAng*CoordSys%g2 + CgRotAng*CoordSys%g3 + + + ! Coned coordinate system: + + CoordSys%i1(K,:) = p%CosPreC(K)*g1Prime - p%SinPreC(K)*g3Prime ! i1(K,:) = vector / direction i1 for blade K (= xcK from the IEC coord. system). + CoordSys%i2(K,:) = g2Prime ! i2(K,:) = vector / direction i2 for blade K (= ycK from the IEC coord. system). + CoordSys%i3(K,:) = p%SinPreC(K)*g1Prime + p%CosPreC(K)*g3Prime ! i3(K,:) = vector / direction i3 for blade K (= zcK from the IEC coord. system). + + + ! Blade / pitched coordinate system: + + CosPitch = COS( REAL(BlPitch(K),R8Ki) ) + SinPitch = SIN( REAL(BlPitch(K),R8Ki) ) + + CoordSys%j1(K,:) = CosPitch*CoordSys%i1(K,:) - SinPitch*CoordSys%i2(K,:) ! j1(K,:) = vector / direction j1 for blade K (= xbK from the IEC coord. system). + CoordSys%j2(K,:) = SinPitch*CoordSys%i1(K,:) + CosPitch*CoordSys%i2(K,:) ! j2(K,:) = vector / direction j2 for blade K (= ybK from the IEC coord. system). + CoordSys%j3(K,:) = CoordSys%i3(K,:) ! j3(K,:) = vector / direction j3 for blade K (= zbK from the IEC coord. system). + + + DO J = 0,p%TipNode ! Loop through the blade nodes / elements + + + ! Blade coordinate system aligned with local structural axes (not element fixed): + + Lj1 = p%CThetaS(K,J)*CoordSys%j1(K,:) - p%SThetaS(K,J)*CoordSys%j2(K,:) ! vector / direction Lj1 at node J for blade K + Lj2 = p%SThetaS(K,J)*CoordSys%j1(K,:) + p%CThetaS(K,J)*CoordSys%j2(K,:) ! vector / direction Lj2 at node J for blade K + Lj3 = CoordSys%j3(K,:) ! vector / direction Lj3 at node J for blade K + + + ! Blade element-fixed coordinate system aligned with local structural axes: + + ThetaOoP = p%TwistedSF(K,1,1,J,1)*x%QT( DOF_BF(K,1) ) & + + p%TwistedSF(K,1,2,J,1)*x%QT( DOF_BF(K,2) ) & + + p%TwistedSF(K,1,3,J,1)*x%QT( DOF_BE(K,1) ) + ThetaIP = - p%TwistedSF(K,2,1,J,1)*x%QT( DOF_BF(K,1) ) & + - p%TwistedSF(K,2,2,J,1)*x%QT( DOF_BF(K,2) ) & + - p%TwistedSF(K,2,3,J,1)*x%QT( DOF_BE(K,1) ) + + ThetaLxb = p%CThetaS(K,J)*ThetaIP - p%SThetaS(K,J)*ThetaOoP + ThetaLyb = p%SThetaS(K,J)*ThetaIP + p%CThetaS(K,J)*ThetaOoP + + CALL SmllRotTrans( 'blade deflection (ElastoDyn SetCoordSy)', ThetaLxb, ThetaLyb, 0.0_R8Ki, TransMat, TRIM(Num2LStr(t))//' s', ErrStat2, ErrMsg2 ) ! Get the transformation matrix, TransMat, from blade coordinate system aligned with local structural axes (not element fixed) to blade element-fixed coordinate system aligned with local structural axes. + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CoordSys%n1(K,J,:) = TransMat(1,1)*Lj1 + TransMat(1,2)*Lj2 + TransMat(1,3)*Lj3 ! Vector / direction n1 for node J of blade K (= LxbK from the IEC coord. system). + CoordSys%n2(K,J,:) = TransMat(2,1)*Lj1 + TransMat(2,2)*Lj2 + TransMat(2,3)*Lj3 ! Vector / direction n2 for node J of blade K (= LybK from the IEC coord. system). + CoordSys%n3(K,J,:) = TransMat(3,1)*Lj1 + TransMat(3,2)*Lj2 + TransMat(3,3)*Lj3 ! Vector / direction n3 for node J of blade K (= LzbK from the IEC coord. system). + + ! skip these next CoordSys variables at the root and the tip; they are required only for AD14: + + if (j == 0 .or. j==p%TipNode) cycle + + + ! Blade element-fixed coordinate system used for calculating and returning + ! aerodynamics loads: + ! This coordinate system is rotated about positive n3 by the angle + ! BlPitch(K) + ThetaS(K,J) and is coincident with the i-vector triad + ! when the blade is undeflected. + + CPitPTwstS = CosPitch*p%CThetaS(K,J) - SinPitch*p%SThetaS(K,J) ! = COS( BlPitch(K) + ThetaS(K,J) ) found using the sum of angles formulae of cosine. + SPitPTwstS = CosPitch*p%SThetaS(K,J) + SinPitch*p%CThetaS(K,J) ! = SIN( BlPitch(K) + ThetaS(K,J) ) found using the sum of angles formulae of sine. + + CoordSys%m1(K,J,:) = CPitPTwstS*CoordSys%n1(K,J,:) + SPitPTwstS*CoordSys%n2(K,J,:) ! m1(K,J,:) = vector / direction m1 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn). + CoordSys%m2(K,J,:) = -SPitPTwstS*CoordSys%n1(K,J,:) + CPitPTwstS*CoordSys%n2(K,J,:) ! m2(K,J,:) = vector / direction m2 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn). + CoordSys%m3(K,J,:) = CoordSys%n3(K,J,:) ! m3(K,J,:) = vector / direction m3 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn). + + + ! Calculate the trailing edge coordinate system used in noise calculations. + ! This coordinate system is blade element-fixed and oriented with the local + ! aerodynamic axes (te2 points toward trailing edge, te1 points toward + ! suction surface): + + CPitPTwstA = CosPitch*p%CAeroTwst(J) - SinPitch*p%SAeroTwst(J) ! = COS( BlPitch(K) + AeroTwst(J) ) found using the sum of angles formulae of cosine. + SPitPTwstA = CosPitch*p%SAeroTwst(J) + SinPitch*p%CAeroTwst(J) ! = SIN( BlPitch(K) + AeroTwst(J) ) found using the sum of angles formulae of sine. + + CoordSys%te1(K,J,:) = CPitPTwstA*CoordSys%m1(K,J,:) - SPitPTwstA*CoordSys%m2(K,J,:) ! te1(K,J,:) = vector / direction te1 for node J of blade K (used to calc. noise and to calc. and return aerodynamic loads from AeroDyn). + CoordSys%te2(K,J,:) = SPitPTwstA*CoordSys%m1(K,J,:) + CPitPTwstA*CoordSys%m2(K,J,:) ! te2(K,J,:) = vector / direction te2 for node J of blade K (used to calc. noise and to calc. and return aerodynamic loads from AeroDyn). + CoordSys%te3(K,J,:) = CoordSys%m3(K,J,:) ! te3(K,J,:) = vector / direction te3 for node J of blade K (used to calc. noise and to calc. and return aerodynamic loads from AeroDyn). + + + ENDDO ! J - Blade nodes / elements + + + ENDDO ! K - Blades + + + ! Tail-furl coordinate system: + + CTailFurl = COS( x%QT(DOF_TFrl) ) + STailFurl = SIN( x%QT(DOF_TFrl) ) + + CoordSys%tf1 = ( ( 1.0 - p%CTFrlSkw2*p%CTFrlTlt2 )*CTailFurl + p%CTFrlSkw2*p%CTFrlTlt2 )*CoordSys%d1 & + + ( p%CTFrlSkew*p%CSTFrlTlt*( 1.0 - CTailFurl ) - p%STFrlSkew*p%CTFrlTilt*STailFurl )*CoordSys%d2 & + + ( p%CSTFrlSkw*p%CTFrlTlt2*( CTailFurl - 1.0 ) - p%STFrlTilt*STailFurl )*CoordSys%d3 + CoordSys%tf2 = ( p%CTFrlSkew*p%CSTFrlTlt*( 1.0 - CTailFurl ) + p%STFrlSkew*p%CTFrlTilt*STailFurl )*CoordSys%d1 & + + ( p%CTFrlTlt2* CTailFurl + p%STFrlTlt2 )*CoordSys%d2 & + + ( p%STFrlSkew*p%CSTFrlTlt*( CTailFurl - 1.0 ) + p%CTFrlSkew*p%CTFrlTilt*STailFurl )*CoordSys%d3 + CoordSys%tf3 = ( p%CSTFrlSkw*p%CTFrlTlt2*( CTailFurl - 1.0 ) + p%STFrlTilt*STailFurl )*CoordSys%d1 & + + ( p%STFrlSkew*p%CSTFrlTlt*( CTailFurl - 1.0 ) - p%CTFrlSkew*p%CTFrlTilt*STailFurl )*CoordSys%d2 & + + ( ( 1.0 - p%STFrlSkw2*p%CTFrlTlt2 )*CTailFurl + p%STFrlSkw2*p%CTFrlTlt2 )*CoordSys%d3 + CoordSys%tfa = p%CTFrlSkew*p%CTFrlTilt*CoordSys%d1 + p%STFrlTilt*CoordSys%d2 - p%STFrlSkew*p%CTFrlTilt*CoordSys%d3 + + + ! Tail fin coordinate system: + + CoordSys%p1 = ( p%CTFinSkew*p%CTFinTilt )*CoordSys%tf1 & ! Vector / direction p1 (= tail fin x). + + ( p%STFinTilt )*CoordSys%tf2 & + + ( - p%STFinSkew*p%CTFinTilt )*CoordSys%tf3 + CoordSys%p2 = ( p%STFinSkew*p%STFinBank - p%CTFinSkew*p%STFinTilt*p%CTFinBank )*CoordSys%tf1 & ! Vector / direction p2 (= tail fin z). + + ( p%CTFinTilt*p%CTFinBank )*CoordSys%tf2 & + + ( p%CTFinSkew*p%STFinBank + p%STFinSkew*p%STFinTilt*p%CTFinBank )*CoordSys%tf3 + CoordSys%p3 = ( p%STFinSkew*p%CTFinBank + p%CTFinSkew*p%STFinTilt*p%STFinBank )*CoordSys%tf1 & ! Vector / direction p3 (= tail fin -y). + + ( - p%CTFinTilt*p%STFinBank )*CoordSys%tf2 & + + ( p%CTFinSkew*p%CTFinBank - p%STFinSkew*p%STFinTilt*p%STFinBank )*CoordSys%tf3 + + RETURN +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SetCoordSy:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + END IF + + END IF + + + END SUBROUTINE CheckError +!---------------------------------------------------------------------------------------------------------------------------------- +END SUBROUTINE SetCoordSy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes the rotor-furl moment due to rotor-furl deflection and rate. +SUBROUTINE RFurling( t, p, RFrlDef, RFrlRate, RFrlMom ) +!.................................................................................................................................. + + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: t !< simulation time + TYPE(ED_ParameterType), INTENT(IN) :: p !< parameters from the structural dynamics module + + REAL(R8Ki), INTENT(IN ) :: RFrlDef !< The rotor-furl deflection, x%QT(DOF_RFrl) + REAL(ReKi), INTENT(OUT) :: RFrlMom !< The total moment supplied by the springs, and dampers + REAL(R8Ki), INTENT(IN ) :: RFrlRate !< The rotor-furl rate, x%QDT(DOF_RFrl) + + + ! Local variables: + REAL(ReKi) :: RFrlDMom ! The moment supplied by the rotor-furl dampers + REAL(ReKi) :: RFrlSMom ! The moment supplied by the rotor-furl springs + + + SELECT CASE ( p%RFrlMod ) ! Which rotor-furl model are we using? + + CASE ( 0_IntKi ) ! None! + + + RFrlMom = 0.0 + + + CASE ( 1_IntKi ) ! Standard (using inputs from the FAST furling input file). + + + ! Linear spring: + + RFrlSMom = -p%RFrlSpr*RFrlDef + + + ! Add spring-stops: + + IF ( RFrlDef > p%RFrlUSSP ) THEN ! Up-stop + RFrlSMom = RFrlSMom - p%RFrlUSSpr*( RFrlDef - p%RFrlUSSP ) + ELSEIF ( RFrlDef < p%RFrlDSSP ) THEN ! Down-stop + RFrlSMom = RFrlSMom - p%RFrlDSSpr*( RFrlDef - p%RFrlDSSP ) + ENDIF + + + ! Linear damper: + + RFrlDMom = -p%RFrlDmp*RFrlRate + + + ! Add coulomb friction: + + IF ( RFrlRate /= 0.0 ) THEN + RFrlDMom = RFrlDMom - SIGN( p%RFrlCDmp, real(RFrlRate,ReKi) ) + ENDIF + + + ! Add damper-stops: + + IF ( RFrlDef > p%RFrlUSDP ) THEN ! Up-stop + RFrlDMom = RFrlDMom - p%RFrlUSDmp*RFrlRate + ELSEIF ( RFrlDef < p%RFrlDSDP ) THEN ! Down-stop + RFrlDMom = RFrlDMom - p%RFrlDSDmp*RFrlRate + ENDIF + + + ! Total up all the moments. + + RFrlMom = RFrlSMom + RFrlDMom + + + CASE ( 2_IntKi ) ! User-defined rotor-furl spring/damper model. + + + CALL UserRFrl ( RFrlDef, RFrlRate, t, p%RootName, RFrlMom ) + + + END SELECT + + RETURN +END SUBROUTINE RFurling +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes the teeter moment due to teeter deflection and rate. +SUBROUTINE Teeter( t, p, TeetDef, TeetRate, TeetMom ) +!.................................................................................................................................. + + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: t !< simulation time + TYPE(ED_ParameterType), INTENT(IN) :: p !< parameters from the structural dynamics module + REAL(R8Ki), INTENT(IN ) :: TeetDef !< The teeter deflection, x%QT(DOF_Teet). + REAL(ReKi), INTENT(OUT) :: TeetMom !< The total moment supplied by the stop, spring, and damper. + REAL(R8Ki), INTENT(IN ) :: TeetRate !< The teeter rate, x%QDT(DOF_Teet). + + + ! Local variables: + REAL(ReKi) :: AbsDef ! Absolute value of the teeter deflection. + REAL(ReKi) :: SprgDef ! Deflection past the spring. + REAL(ReKi) :: StopDef ! Deflection past the stop. + REAL(ReKi) :: TeetDMom ! The moment supplied by the damper. + REAL(ReKi) :: TeetFMom ! The moment supplied by Coulomb-friction damping. + REAL(ReKi) :: TeetKMom ! The moment supplied by the spring. + REAL(ReKi) :: TeetSMom ! The moment supplied by the stop. + + + + SELECT CASE ( p%TeetMod ) ! Which teeter model are we using? + + CASE ( 0_IntKi ) ! None! + + + TeetMom = 0.0_ReKi + + + CASE ( 1_IntKi ) ! Standard (using inputs from the primary FAST input file). + + + ! Compute the absulute value of the deflection. + + AbsDef = ABS( TeetDef ) + + + ! Linear teeter spring. + + SprgDef = AbsDef - p%TeetSStP + + IF ( SprgDef > 0.0_ReKi ) THEN + TeetKMom = -SIGN( SprgDef*p%TeetSSSp, real(TeetDef,ReKi) ) + ELSE + TeetKMom = 0.0_ReKi + ENDIF + + + ! Compute teeter-stop moment if hard stop has been contacted. + + StopDef = AbsDef - p%TeetHStP + + IF ( StopDef > 0.0_ReKi ) THEN + TeetSMom = -p%TeetHSSp*SIGN( StopDef, real(TeetDef,reKi) ) + ELSE + TeetSMom = 0.0_ReKi + ENDIF + + + ! Compute linear teeter-damper moment. + + IF ( ABS(TeetDef) > p%TeetDmpP ) THEN + TeetDMom = -p%TeetDmp*TeetRate + ELSE + TeetDMom = 0.0_ReKi + END IF + + + + ! Add coulomb friction to the teeter hinge. + + IF ( .NOT. EqualRealNos( TeetRate, 0.0_R8Ki ) ) THEN + TeetFMom = 0.0_ReKi + ELSE + TeetFMom = -SIGN( p%TeetCDmp, real(TeetRate,reKi) ) + ENDIF + + + ! Total up all the moments. + + TeetMom = TeetSMom + TeetDMom + TeetKMom + TeetFMom + + + CASE ( 2_IntKi ) ! User-defined teeter spring/damper model. + + + CALL UserTeet ( TeetDef, TeetRate, t, p%RootName, TeetMom ) + + + END SELECT + + + RETURN +END SUBROUTINE Teeter +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes the tail-furl moment due to tail-furl deflection and rate. +SUBROUTINE TFurling( t, p, TFrlDef, TFrlRate, TFrlMom ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: t !< simulation time + TYPE(ED_ParameterType), INTENT(IN) :: p !< parameters from the structural dynamics module + + REAL(R8Ki), INTENT(IN ) :: TFrlDef !< The tail-furl deflection, QT(DOF_TFrl). + REAL(ReKi), INTENT(OUT) :: TFrlMom !< The total moment supplied by the springs, and dampers. + REAL(R8Ki), INTENT(IN ) :: TFrlRate !< The tail-furl rate, QDT(DOF_TFrl). + + + ! Local variables: + + REAL(ReKi) :: TFrlDMom ! The moment supplied by the tail-furl dampers. + REAL(ReKi) :: TFrlSMom ! The moment supplied by the tail-furl springs. + + + + SELECT CASE ( p%TFrlMod ) ! Which tail-furl model are we using? + + CASE ( 0_IntKi ) ! None! + + + TFrlMom = 0.0 + + + CASE ( 1_IntKi ) ! Standard (using inputs from the FAST furling input file). + + + ! Linear spring: + + TFrlSMom = -p%TFrlSpr*TFrlDef + + + ! Add spring-stops: + + IF ( TFrlDef > p%TFrlUSSP ) THEN ! Up-stop + TFrlSMom = TFrlSMom - p%TFrlUSSpr*( TFrlDef - p%TFrlUSSP ) + ELSEIF ( TFrlDef < p%TFrlDSSP ) THEN ! Down-stop + TFrlSMom = TFrlSMom - p%TFrlDSSpr*( TFrlDef - p%TFrlDSSP ) + ENDIF + + + ! Linear damper: + + TFrlDMom = -p%TFrlDmp*TFrlRate + + + ! Add coulomb friction: + + IF ( .NOT. EqualRealNos( TFrlRate, 0.0_R8Ki) ) THEN + TFrlDMom = TFrlDMom - SIGN( p%TFrlCDmp, real(TFrlRate,reKi) ) + ENDIF + + + ! Add damper-stops: + + IF ( TFrlDef > p%TFrlUSDP ) THEN ! Up-stop + TFrlDMom = TFrlDMom - p%TFrlUSDmp*TFrlRate + ELSEIF ( TFrlDef < p%TFrlDSDP ) THEN ! Down-stop + TFrlDMom = TFrlDMom - p%TFrlDSDmp*TFrlRate + ENDIF + + + ! Total up all the moments. + + TFrlMom = TFrlSMom + TFrlDMom + + + CASE ( 2 ) ! User-defined tail-furl spring/damper model. + + + CALL UserTFrl ( TFrlDef, TFrlRate, t, p%RootName, TFrlMom ) + + + END SELECT + + + RETURN +END SUBROUTINE TFurling +!---------------------------------------------------------------------------------------------------------------------------------- +!> This function calculates the sign (+/-1) of the low-speed shaft torque for +!! this time step. MomLPRot is the moment on the +!! low-speed shaft at the teeter pin caused by the rotor. +FUNCTION SignLSSTrq( p, m ) + + ! Passed variables + + TYPE(ED_ParameterType), INTENT(IN) :: p !< Parameters + TYPE(ED_MiscVarType), INTENT(IN) :: m !< Misc variables + + INTEGER(IntKi) :: SignLSSTrq !< The sign of the LSS_Trq, output from this function + + ! Local variables + + REAL(ReKi) :: MomLPRot (3) ! The total moment on the low-speed shaft at point P caused by the rotor. + INTEGER(IntKi) :: I ! loop counter + + + MomLPRot = m%RtHS%MomLPRott ! Initialize MomLPRot using MomLPRott + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + MomLPRot = MomLPRot + m%RtHS%PMomLPRot(:,p%DOFs%SrtPS(I))*m%QD2T(p%DOFs%SrtPS(I)) ! Add the moments associated with the accelerations of the DOFs + + ENDDO ! I - All active (enabled) DOFs + + ! MomLProt has now been found. Now dot this with e1 to get the + ! low-speed shaft torque and take the SIGN of the result: + + SignLSSTrq = NINT( SIGN( 1.0_R8Ki, DOT_PRODUCT( MomLPRot, m%CoordSys%e1 ) ) ) + +END FUNCTION SignLSSTrq +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to calculate the positions stored in other states that are used in both the +!! CalcOutput and CalcContStateDeriv routines. +SUBROUTINE CalculatePositions( p, x, CoordSys, RtHSdat ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set) + + !Local variables + REAL(R8Ki) :: rK (3) ! Position vector from inertial frame origin to tail fin center of pressure (point K). + !REAL(R8Ki) :: rQ (3) ! Position vector from inertial frame origin to apex of rotation (point Q). + + INTEGER(IntKi) :: J ! Counter for elements + INTEGER(IntKi) :: K ! Counter for blades + + !------------------------------------------------------------------------------------------------- + ! Positions + !------------------------------------------------------------------------------------------------- + + ! Define the position vectors between the various points on the wind turbine + ! that are not dependent on the distributed tower or blade parameters: + + RtHSdat%rZ = x%QT(DOF_Sg)* CoordSys%z1 + x%QT(DOF_Hv)* CoordSys%z2 - x%QT(DOF_Sw)* CoordSys%z3 ! Position vector from inertia frame origin to platform reference (point Z). + RtHSdat%rZY = p%rZYzt* CoordSys%a2 + p%PtfmCMxt*CoordSys%a1 - p%PtfmCMyt*CoordSys%a3 ! Position vector from platform reference (point Z) to platform mass center (point Y). + RtHSdat%rZT0 = p%rZT0zt* CoordSys%a2 ! Position vector from platform reference (point Z) to tower base (point T(0)) + RtHSdat%rZO = ( x%QT(DOF_TFA1) + x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from platform reference (point Z) to tower-top / base plate (point O). + + ( p%RefTwrHt - 0.5*( p%AxRedTFA(1,1,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) & + + p%AxRedTFA(2,2,p%TTopNode)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) & + + 2.0*p%AxRedTFA(1,2,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) & + + p%AxRedTSS(1,1,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) & + + p%AxRedTSS(2,2,p%TTopNode)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) & + + 2.0*p%AxRedTSS(1,2,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 & + + ( x%QT(DOF_TSS1) + x%QT(DOF_TSS2) )*CoordSys%a3 + RtHSdat%rOU = p%NacCMxn*CoordSys%d1 + p%NacCMzn *CoordSys%d2 - p%NacCMyn *CoordSys%d3 ! Position vector from tower-top / base plate (point O) to nacelle center of mass (point U). + RtHSdat%rOV = p%RFrlPntxn*CoordSys%d1 + p%RFrlPntzn*CoordSys%d2 - p%RFrlPntyn*CoordSys%d3 ! Position vector from tower-top / base plate (point O) to specified point on rotor-furl axis (point V). + RtHSdat%rVIMU = p%rVIMUxn*CoordSys%rf1 + p%rVIMUzn *CoordSys%rf2 - p%rVIMUyn *CoordSys%rf3 ! Position vector from specified point on rotor-furl axis (point V) to nacelle IMU (point IMU). + RtHSdat%rVD = p%rVDxn*CoordSys%rf1 + p%rVDzn *CoordSys%rf2 - p%rVDyn *CoordSys%rf3 ! Position vector from specified point on rotor-furl axis (point V) to center of mass of structure that furls with the rotor (not including rotor) (point D). + RtHSdat%rVP = p%rVPxn*CoordSys%rf1 + p%rVPzn *CoordSys%rf2 - p%rVPyn *CoordSys%rf3 + p%OverHang*CoordSys%c1 ! Position vector from specified point on rotor-furl axis (point V) to teeter pin (point P). + RtHSdat%rPQ = -p%UndSling*CoordSys%g1 ! Position vector from teeter pin (point P) to apex of rotation (point Q). + RtHSdat%rQC = p%HubCM*CoordSys%g1 ! Position vector from apex of rotation (point Q) to hub center of mass (point C). + RtHSdat%rOW = p%TFrlPntxn*CoordSys%d1 + p%TFrlPntzn *CoordSys%d2 - p%TFrlPntyn*CoordSys%d3 ! Position vector from tower-top / base plate (point O) to specified point on tail-furl axis (point W). + RtHSdat%rWI = p%rWIxn*CoordSys%tf1 + p%rWIzn*CoordSys%tf2 - p%rWIyn*CoordSys%tf3 ! Position vector from specified point on tail-furl axis (point W) to tail boom center of mass (point I). + RtHSdat%rWJ = p%rWJxn*CoordSys%tf1 + p%rWJzn*CoordSys%tf2 - p%rWJyn*CoordSys%tf3 ! Position vector from specified point on tail-furl axis (point W) to tail fin center of mass (point J). + RtHSdat%rWK = p%rWKxn*CoordSys%tf1 + p%rWKzn*CoordSys%tf2 - p%rWKyn*CoordSys%tf3 ! Position vector from specified point on tail-furl axis (point W) to tail fin center of pressure (point K). + RtHSdat%rPC = RtHSdat%rPQ + RtHSdat%rQC ! Position vector from teeter pin (point P) to hub center of mass (point C). + RtHSdat%rT0O = RtHSdat%rZO - RtHSdat%rZT0 ! Position vector from the tower base (point T(0)) to tower-top / base plate (point O). + RtHSdat%rO = RtHSdat%rZ + RtHSdat%rZO ! Position vector from inertial frame origin to tower-top / base plate (point O). + RtHSdat%rV = RtHSdat%rO + RtHSdat%rOV ! Position vector from inertial frame origin to specified point on rotor-furl axis (point V) + !RtHSdat%rP = RtHSdat%rO + RtHSdat%rOV + RtHSdat%rVP ! Position vector from inertial frame origin to teeter pin (point P). + RtHSdat%rP = RtHSdat%rV + RtHSdat%rVP ! Position vector from inertial frame origin to teeter pin (point P). + RtHSdat%rQ = RtHSdat%rP + RtHSdat%rPQ ! Position vector from inertial frame origin to apex of rotation (point Q). + rK = RtHSdat%rO + RtHSdat%rOW + RtHSdat%rWK ! Position vector from inertial frame origin to tail fin center of pressure (point K). + + + DO K = 1,p%NumBl ! Loop through all blades + + ! Calculate the position vector of the tip: + RtHSdat%rS0S(:,K,p%TipNode) = ( p%TwistedSF(K,1,1,p%TipNode,0)*x%QT( DOF_BF(K,1) ) & ! Position vector from the blade root (point S(0)) to the blade tip (point S(p%BldFlexL)). + + p%TwistedSF(K,1,2,p%TipNode,0)*x%QT( DOF_BF(K,2) ) & + + p%TwistedSF(K,1,3,p%TipNode,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j1(K,:) & + + ( p%TwistedSF(K,2,1,p%TipNode,0)*x%QT( DOF_BF(K,1) ) & + + p%TwistedSF(K,2,2,p%TipNode,0)*x%QT( DOF_BF(K,2) ) & + + p%TwistedSF(K,2,3,p%TipNode,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j2(K,:) & + + ( p%BldFlexL - 0.5* & + ( p%AxRedBld(K,1,1,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,1) ) & + + p%AxRedBld(K,2,2,p%TipNode)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BF(K,2) ) & + + p%AxRedBld(K,3,3,p%TipNode)*x%QT( DOF_BE(K,1) )*x%QT( DOF_BE(K,1) ) & + + 2.*p%AxRedBld(K,1,2,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,2) ) & + + 2.*p%AxRedBld(K,2,3,p%TipNode)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BE(K,1) ) & + + 2.*p%AxRedBld(K,1,3,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BE(K,1) ) ) )*CoordSys%j3(K,:) + RtHSdat%rQS (:,K,p%TipNode) = RtHSdat%rS0S(:,K,p%TipNode) + p%HubRad*CoordSys%j3(K,:) ! Position vector from apex of rotation (point Q) to the blade tip (point S(p%BldFlexL)). + RtHSdat%rS (:,K,p%TipNode) = RtHSdat%rQS (:,K,p%TipNode) + RtHSdat%rQ ! Position vector from inertial frame origin to the blade tip (point S(p%BldFlexL)). + + ! position vectors for blade root node: + RtHSdat%rQS (:,K,0) = p%HubRad*CoordSys%j3(K,:) + RtHSdat%rS (:,K,0) = p%HubRad*CoordSys%j3(K,:) + RtHSdat%rQ + + + ! Calculate the position vector from the teeter pin to the blade root: + + RtHSdat%rPS0(:,K) = RtHSdat%rPQ + p%HubRad*CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)). + + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + + ! Calculate the position vector of the current node: + + RtHSdat%rS0S(:,K,J) = ( p%TwistedSF(K,1,1,J,0)*x%QT( DOF_BF(K,1) ) & ! Position vector from the blade root (point S(0)) to the current node (point S(RNodes(J)). + + p%TwistedSF(K,1,2,J,0)*x%QT( DOF_BF(K,2) ) & + + p%TwistedSF(K,1,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j1(K,:) & + + ( p%TwistedSF(K,2,1,J,0)*x%QT( DOF_BF(K,1) ) & + + p%TwistedSF(K,2,2,J,0)*x%QT( DOF_BF(K,2) ) & + + p%TwistedSF(K,2,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j2(K,:) & + + ( p%RNodes(J) - 0.5* & + ( p%AxRedBld(K,1,1,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,1) ) & + + p%AxRedBld(K,2,2,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BF(K,2) ) & + + p%AxRedBld(K,3,3,J)*x%QT( DOF_BE(K,1) )*x%QT( DOF_BE(K,1) ) & + + 2.0*p%AxRedBld(K,1,2,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,2) ) & + + 2.0*p%AxRedBld(K,2,3,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BE(K,1) ) & + + 2.0*p%AxRedBld(K,1,3,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BE(K,1) ) ) )*CoordSys%j3(K,:) + RtHSdat%rQS (:,K,J) = RtHSdat%rS0S(:,K,J) + p%HubRad*CoordSys%j3(K,:) ! Position vector from apex of rotation (point Q) to the current node (point S(RNodes(J)). + RtHSdat%rS (:,K,J) = RtHSdat%rQS (:,K,J) + RtHSdat%rQ ! Position vector from inertial frame origin to the current node (point S(RNodes(J)). + + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + + + + END DO !K = 1,p%NumBl + + + + + !---------------------------------------------------------------------------------------------------- + ! Get the tower element positions + !---------------------------------------------------------------------------------------------------- + RtHSdat%rZT (:,0) = RtHSdat%rZT0 + DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements + + + ! Calculate the position vector of the current node: + + RtHSdat%rT0T(:,J) = ( p%TwrFASF(1,J,0)*x%QT(DOF_TFA1) + p%TwrFASF(2,J,0)*x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from base of flexible portion of tower (point T(0)) to current node (point T(J)). + + ( p%HNodes(J) - 0.5*( p%AxRedTFA(1,1,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) & + + p%AxRedTFA(2,2,J)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) & + + 2.0*p%AxRedTFA(1,2,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) & + + p%AxRedTSS(1,1,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) & + + p%AxRedTSS(2,2,J)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) & + + 2.0*p%AxRedTSS(1,2,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 & + + ( p%TwrSSSF(1,J,0)*x%QT(DOF_TSS1) + p%TwrSSSF(2,J,0)*x%QT(DOF_TSS2) )*CoordSys%a3 + RtHSdat%rZT (:,J) = RtHSdat%rZT0 + RtHSdat%rT0T(:,J) ! Position vector from platform reference (point Z) to the current node (point T(HNodes(J)). + + + RtHSdat%rT(:,J) = RtHSdat%rZ + RtHSdat%rZT (:,J) ! Position vector from inertial frame origin to the current node (point T(HNodes(J)). + + END DO + + +END SUBROUTINE CalculatePositions +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to calculate the angular positions, velocities, and partial accelerations stored in other states that are used in +!! both the CalcOutput and CalcContStateDeriv routines. +SUBROUTINE CalculateAngularPosVelPAcc( p, x, CoordSys, RtHSdat ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set) + + !Local variables + + REAL(ReKi) :: AngVelHM (3) ! Angular velocity of eleMent J of blade K (body M) in the hub (body H). +! REAL(ReKi) :: AngVelEN (3) ! Angular velocity of the nacelle (body N) in the inertia frame (body E for earth). + REAL(ReKi) :: AngAccELt (3) ! Portion of the angular acceleration of the low-speed shaft (body L) in the inertia frame (body E for earth) associated with everything but the QD2T()'s. + INTEGER(IntKi) :: J ! Counter for elements + INTEGER(IntKi) :: K ! Counter for blades + + !------------------------------------------------------------------------------------------------- + ! Angular and partial angular velocities + !------------------------------------------------------------------------------------------------- + + ! Define the angular and partial angular velocities of all of the rigid bodies in the inertia frame: + ! NOTE: PAngVelEN(I,D,:) = the Dth-derivative of the partial angular velocity of DOF I for body N in body E. + + RtHSdat%PAngVelEX( :,0,:) = 0.0 + RtHSdat%PAngVelEX(DOF_R ,0,:) = CoordSys%z1 + RtHSdat%PAngVelEX(DOF_P ,0,:) = -CoordSys%z3 + RtHSdat%PAngVelEX(DOF_Y ,0,:) = CoordSys%z2 + RtHSdat%AngVelEX = x%QDT(DOF_R )*RtHSdat%PAngVelEX(DOF_R ,0,:) & + + x%QDT(DOF_P )*RtHSdat%PAngVelEX(DOF_P ,0,:) & + + x%QDT(DOF_Y )*RtHSdat%PAngVelEX(DOF_Y ,0,:) + RtHSdat%AngPosEX = x%QT (DOF_R )*RtHSdat%PAngVelEX(DOF_R ,0,:) & + + x%QT (DOF_P )*RtHSdat%PAngVelEX(DOF_P ,0,:) & + + x%QT (DOF_Y )*RtHSdat%PAngVelEX(DOF_Y ,0,:) + + RtHSdat%PAngVelEB( :,0,:) = RtHSdat%PAngVelEX(:,0,:) + RtHSdat%PAngVelEB(DOF_TFA1,0,:) = -p%TwrFASF(1,p%TTopNode,1)*CoordSys%a3 + RtHSdat%PAngVelEB(DOF_TSS1,0,:) = p%TwrSSSF(1,p%TTopNode,1)*CoordSys%a1 + RtHSdat%PAngVelEB(DOF_TFA2,0,:) = -p%TwrFASF(2,p%TTopNode,1)*CoordSys%a3 + RtHSdat%PAngVelEB(DOF_TSS2,0,:) = p%TwrSSSF(2,p%TTopNode,1)*CoordSys%a1 + RtHSdat%AngVelEB = RtHSdat%AngVelEX + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,0,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,0,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,0,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,0,:) + RtHSdat%AngPosXB = x%QT (DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,0,:) & + + x%QT (DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,0,:) & + + x%QT (DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,0,:) & + + x%QT (DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,0,:) + + RtHSdat%PAngVelEN( :,0,:)= RtHSdat%PAngVelEB(:,0,:) + RtHSdat%PAngVelEN(DOF_Yaw ,0,:)= CoordSys%d2 + RtHSdat%AngVelEN = RtHSdat%AngVelEB + x%QDT(DOF_Yaw )*RtHSdat%PAngVelEN(DOF_Yaw ,0,:) + + RtHSdat%PAngVelER( :,0,:)= RtHSdat%PAngVelEN(:,0,:) + RtHSdat%PAngVelER(DOF_RFrl,0,:)= CoordSys%rfa + RtHSdat%AngVelER = RtHSdat%AngVelEN + x%QDT(DOF_RFrl)*RtHSdat%PAngVelER(DOF_RFrl,0,:) + + RtHSdat%PAngVelEL( :,0,:)= RtHSdat%PAngVelER(:,0,:) + RtHSdat%PAngVelEL(DOF_GeAz,0,:)= CoordSys%c1 + RtHSdat%PAngVelEL(DOF_DrTr,0,:)= CoordSys%c1 + RtHSdat%AngVelEL = RtHSdat%AngVelER + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEL(DOF_GeAz,0,:) & + + x%QDT(DOF_DrTr)*RtHSdat%PAngVelEL(DOF_DrTr,0,:) + + RtHSdat%PAngVelEH( :,0,:)= RtHSdat%PAngVelEL(:,0,:) + RtHSdat%AngVelEH = RtHSdat%AngVelEL +IF ( p%NumBl == 2 ) THEN ! 2-blader + RtHSdat%PAngVelEH(DOF_Teet,0,:)= CoordSys%f2 + RtHSdat%AngVelEH = RtHSdat%AngVelEH + x%QDT(DOF_Teet)*RtHSdat%PAngVelEH(DOF_Teet,0,:) +ENDIF + + RtHSdat%PAngVelEG( :,0,:) = RtHSdat%PAngVelER(:,0,:) + RtHSdat%PAngVelEG(DOF_GeAz,0,:) = p%GBRatio*CoordSys%c1 + RtHSdat%AngVelEG = RtHSdat%AngVelER + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEG(DOF_GeAz,0,:) + + RtHSdat%PAngVelEA( :,0,:) = RtHSdat%PAngVelEN(:,0,:) + RtHSdat%PAngVelEA(DOF_TFrl,0,:) = CoordSys%tfa + RtHSdat%AngVelEA = RtHSdat%AngVelEN + x%QDT(DOF_TFrl)*RtHSdat%PAngVelEA(DOF_TFrl,0,:) + + + + ! Define the 1st derivatives of the partial angular velocities of all + ! of the rigid bodies in the inertia frame and the portion of the angular + ! acceleration of the rigid bodies in the inertia frame associated with + ! everything but the QD2T()'s: + + RtHSdat%PAngVelEX( :,1,:) = 0.0 + RtHSdat%AngAccEXt = 0.0 + + RtHSdat%PAngVelEB( :,1,:) = RtHSdat%PAngVelEX(:,1,:) + RtHSdat%PAngVelEB(DOF_TFA1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TFA1,0,:) ) + RtHSdat%PAngVelEB(DOF_TSS1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TSS1,0,:) ) + RtHSdat%PAngVelEB(DOF_TFA2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TFA2,0,:) ) + RtHSdat%PAngVelEB(DOF_TSS2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TSS2,0,:) ) + RtHSdat%AngAccEBt = RtHSdat%AngAccEXt + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,1,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,1,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,1,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,1,:) + + RtHSdat%PAngVelEN( :,1,:) = RtHSdat%PAngVelEB(:,1,:) + RtHSdat%PAngVelEN(DOF_Yaw ,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEB, RtHSdat%PAngVelEN(DOF_Yaw ,0,:) ) + RtHSdat%AngAccENt = RtHSdat%AngAccEBt + x%QDT(DOF_Yaw )*RtHSdat%PAngVelEN(DOF_Yaw ,1,:) + + RtHSdat%PAngVelER( :,1,:) = RtHSdat%PAngVelEN(:,1,:) + RtHSdat%PAngVelER(DOF_RFrl,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%PAngVelER(DOF_RFrl,0,:) ) + RtHSdat%AngAccERt = RtHSdat%AngAccENt + x%QDT(DOF_RFrl)*RtHSdat%PAngVelER(DOF_RFrl,1,:) + + RtHSdat%PAngVelEL( :,1,:) = RtHSdat%PAngVelER(:,1,:) + RtHSdat%PAngVelEL(DOF_GeAz,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEL(DOF_GeAz,0,:) ) + RtHSdat%PAngVelEL(DOF_DrTr,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEL(DOF_DrTr,0,:) ) + AngAccELt = RtHSdat%AngAccERt + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEL(DOF_GeAz,1,:) & + + x%QDT(DOF_DrTr)*RtHSdat%PAngVelEL(DOF_DrTr,1,:) + + RtHSdat%PAngVelEH( :,1,:) = RtHSdat%PAngVelEL(:,1,:) + RtHSdat%AngAccEHt = AngAccELt +IF ( p%NumBl == 2 ) THEN ! 2-blader + RtHSdat%PAngVelEH(DOF_Teet,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%PAngVelEH(DOF_Teet,0,:) ) + RtHSdat%AngAccEHt = RtHSdat%AngAccEHt + x%QDT(DOF_Teet)*RtHSdat%PAngVelEH(DOF_Teet,1,:) +ENDIF + + RtHSdat%PAngVelEG( :,1,:) = RtHSdat%PAngVelER(:,1,:) + RtHSdat%PAngVelEG(DOF_GeAz,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEG(DOF_GeAz,0,:) ) + RtHSdat%AngAccEGt = RtHSdat%AngAccERt + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEG(DOF_GeAz,1,:) + + RtHSdat%PAngVelEA( :,1,:) = RtHSdat%PAngVelEN(:,1,:) + RtHSdat%PAngVelEA(DOF_TFrl,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%PAngVelEA(DOF_TFrl,0,:) ) + RtHSdat%AngAccEAt = RtHSdat%AngAccENt + x%QDT(DOF_TFrl)*RtHSdat%PAngVelEA(DOF_TFrl,1,:) + + + + DO K = 1,p%NumBl ! Loop through all blades + + DO J = 0,p%TipNode ! Loop through the blade nodes / elements + ! Define the partial angular velocities of the current node (body M(RNodes(J))) in the inertia frame: + ! NOTE: PAngVelEM(K,J,I,D,:) = the Dth-derivative of the partial angular velocity + ! of DOF I for body M of blade K, element J in body E. + + RtHSdat%PAngVelEM(K,J, :,0,:) = RtHSdat%PAngVelEH(:,0,:) + RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) = - p%TwistedSF(K,2,1,J,1)*CoordSys%j1(K,:) & + + p%TwistedSF(K,1,1,J,1)*CoordSys%j2(K,:) + RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) = - p%TwistedSF(K,2,2,J,1)*CoordSys%j1(K,:) & + + p%TwistedSF(K,1,2,J,1)*CoordSys%j2(K,:) + RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:) = - p%TwistedSF(K,2,3,J,1)*CoordSys%j1(K,:) & + + p%TwistedSF(K,1,3,J,1)*CoordSys%j2(K,:) + AngVelHM = x%QDT(DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) & + + x%QDT(DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) & + + x%QDT(DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:) + RtHSdat%AngVelEM(:,J,K ) = RtHSdat%AngVelEH + AngVelHM + RtHSdat%AngPosHM(:,K,J ) = x%QT (DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) & + + x%QT (DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) & + + x%QT (DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:) + + + ! Define the 1st derivatives of the partial angular velocities of the current node (body M(RNodes(J))) in the inertia frame: + + ! NOTE: These are currently unused by the code, therefore, they need not + ! be calculated. Thus, they are currently commented out. If it + ! turns out that they are ever needed (i.e., if inertias of the + ! blade elements are ever added, etc...) simply uncomment out these computations: + ! RtHSdat%PAngVelEM(K,J, :,1,:) = RtHSdat%PAngVelEH(:,1,:) + ! RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BF(K,1),0,:) ) + ! RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BF(K,2),0,:) ) + ! RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BE(K,1),0,:) ) + + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + + END DO !K = 1,p%NumBl + + + !............... + ! tower values: + !............... + + DO J = 0,p%TwrNodes ! Loop through the tower nodes / elements + + ! Define the partial angular velocities (and their 1st derivatives) of the + ! current node (body F(HNodes(J)) in the inertia frame. + ! Also define the overall angular velocity of the current node in the inertia frame. + ! Also, define the portion of the angular acceleration of the current node + ! in the inertia frame associated with everything but the QD2T()'s: + + ! NOTE: PAngVelEF(J,I,D,:) = the Dth-derivative of the partial angular velocity + ! of DOF I for body F of element J in body E. + + RtHSdat%PAngVelEF (J, :,0,:) = RtHSdat%PAngVelEX(:,0,:) + RtHSdat%PAngVelEF (J,DOF_TFA1,0,:) = -p%TwrFASF(1,J,1)*CoordSys%a3 + RtHSdat%PAngVelEF (J,DOF_TSS1,0,:) = p%TwrSSSF(1,J,1)*CoordSys%a1 + RtHSdat%PAngVelEF (J,DOF_TFA2,0,:) = -p%TwrFASF(2,J,1)*CoordSys%a3 + RtHSdat%PAngVelEF (J,DOF_TSS2,0,:) = p%TwrSSSF(2,J,1)*CoordSys%a1 + + RtHSdat%PAngVelEF (J, :,1,:) = RtHSdat%PAngVelEX(:,1,:) + RtHSdat%PAngVelEF (J,DOF_TFA1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) ) + RtHSdat%PAngVelEF (J,DOF_TSS1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) ) + RtHSdat%PAngVelEF (J,DOF_TFA2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) ) + RtHSdat%PAngVelEF (J,DOF_TSS2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS2,0,:) ) + + + RtHSdat%AngVelEF (:,J) = RtHSdat%AngVelEX + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,0,:) + + RtHSdat%AngPosXF (:,J) = x%QT (DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) & + + x%QT (DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) & + + x%QT (DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) & + + x%QT (DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,0,:) + RtHSdat%AngPosEF (:,J) = RtHSdat%AngPosEX + RtHSdat%AngPosXF(:,J) + RtHSdat%AngAccEFt(:,J) = RtHSdat%AngAccEXt + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,1,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,1,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,1,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,1,:) + + END DO ! J + + +END SUBROUTINE CalculateAngularPosVelPAcc +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to calculate the linear velocities and accelerations stored in other states that are used in +!! both the CalcOutput and CalcContStateDeriv routines. +SUBROUTINE CalculateLinearVelPAcc( p, x, CoordSys, RtHSdat ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set) + + ! Local variables + REAL(ReKi) :: LinAccEKt (3) ! "Portion of the linear acceleration of the tail fin center of pressure (point K) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" + REAL(ReKi) :: LinAccEPt (3) ! "Portion of the linear acceleration of the teeter pin (point P) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" + REAL(ReKi) :: LinAccEQt (3) ! "Portion of the linear acceleration of the apex of rotation (point Q) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" + REAL(ReKi) :: LinAccEVt (3) ! "Portion of the linear acceleration of the selected point on the rotor-furl axis (point V) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" + REAL(ReKi) :: LinAccEWt (3) ! "Portion of the linear acceleration of the selected point on the tail-furl axis (point W) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" + REAL(ReKi) :: LinVelEK (3) ! "Linear velocity of tail fin center-of-pressure (point K) in the inertia frame" + REAL(ReKi) :: LinVelHS (3) ! "Relative linear velocity of the current point on the current blade (point S) in the hub frame (body H)" + REAL(ReKi) :: LinVelXO (3) ! "Relative linear velocity of the tower-top / base plate (point O) in the platform (body X)" + REAL(ReKi) :: LinVelXT (3) ! "Relative linear velocity of the current point on the tower (point T) in the platform (body X)" + + REAL(ReKi) :: EwAXrWI (3) ! = AngVelEA X rWI + REAL(ReKi) :: EwAXrWJ (3) ! = AngVelEA X rWJ + REAL(ReKi) :: EwAXrWK (3) ! = AngVelEA X rWK + REAL(ReKi) :: EwHXrPQ (3) ! = AngVelEH X rPQ + REAL(ReKi) :: EwHXrQC (3) ! = AngVelEH X rQC + REAL(ReKi) :: EwHXrQS (3) ! = AngVelEH X rQS of the current blade point S. + REAL(ReKi) :: EwNXrOU (3) ! = AngVelEN X rOU + REAL(ReKi) :: EwNXrOV (3) ! = AngVelEN X rOV + REAL(ReKi) :: EwNXrOW (3) ! = AngVelEN X rOW + REAL(ReKi) :: EwRXrVD (3) ! = AngVelER X rVD + REAL(ReKi) :: EwRXrVIMU (3) ! = AngVelER X rVIMU + REAL(ReKi) :: EwRXrVP (3) ! = AngVelER X rVP + REAL(ReKi) :: EwXXrZO (3) ! = AngVelEX X rZO + REAL(ReKi) :: EwXXrZT (3) ! = AngVelEX X rZT + REAL(ReKi) :: EwXXrZY (3) ! = AngVelEX X rZY + + REAL(ReKi) :: TmpVec0 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec1 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec2 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec3 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec4 (3) ! A temporary vector used in various computations. + + INTEGER(IntKi) :: I ! Loops through some or all of the DOFs + INTEGER(IntKi) :: J ! Counter for elements + INTEGER(IntKi) :: K ! Counter for blades + + + ! Initializations: + + RtHSdat%LinAccECt = 0.0 + RtHSdat%LinAccEDt = 0.0 + RtHSdat%LinAccEIMUt = 0.0 + RtHSdat%LinAccEIt = 0.0 + RtHSdat%LinAccEJt = 0.0 + LinAccEKt = 0.0 + RtHSdat%LinAccEOt = 0.0 + LinAccEPt = 0.0 + LinAccEQt = 0.0 + RtHSdat%LinAccESt = 0.0 + RtHSdat%LinAccETt = 0.0 + RtHSdat%LinAccEUt = 0.0 + LinAccEVt = 0.0 + LinAccEWt = 0.0 + RtHSdat%LinAccEYt = 0.0 + RtHSdat%LinAccEZt = 0.0 + + + !------------------------------------------------------------------------------------------------- + ! Partial linear velocities and accelerations + !------------------------------------------------------------------------------------------------- + + ! Define the partial linear velocities (and their 1st derivatives) of all of + ! the points on the wind turbine in the inertia frame that are not + ! dependent on the distributed tower or blade parameters. Also, define + ! the portion of the linear acceleration of the points in the inertia + ! frame associated with everything but the QD2T()'s: + ! NOTE: PLinVelEX(I,D,:) = the Dth-derivative of the partial linear velocity + ! of DOF I for point X in body E. + + EwXXrZY = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%rZY ) ! + EwXXrZO = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%rZO ) ! + EwNXrOU = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%rOU ) ! + EwNXrOV = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%rOV ) ! + EwRXrVD = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%rVD ) ! Cross products + EwRXrVIMU = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%rVIMU ) ! that are used + EwRXrVP = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%rVP ) ! in the following + EwHXrPQ = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%rPQ ) ! DO...LOOPs + EwHXrQC = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%rQC ) ! + EwNXrOW = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%rOW ) ! + EwAXrWI = CROSS_PRODUCT( RtHSdat%AngVelEA, RtHSdat%rWI ) ! + EwAXrWJ = CROSS_PRODUCT( RtHSdat%AngVelEA, RtHSdat%rWJ ) ! + EwAXrWK = CROSS_PRODUCT( RtHSdat%AngVelEA, RtHSdat%rWK ) ! + + + RtHSdat%PLinVelEZ( :,:,:) = 0.0 + RtHSdat%PLinVelEZ(DOF_Sg ,0,:) = CoordSys%z1 + RtHSdat%PLinVelEZ(DOF_Sw ,0,:) = -CoordSys%z3 + RtHSdat%PLinVelEZ(DOF_Hv ,0,:) = CoordSys%z2 + + RtHSdat%LinVelEZ = x%QDT(DOF_Sg )*RtHSdat%PLinVelEZ(DOF_Sg ,0,:) & + + x%QDT(DOF_Sw )*RtHSdat%PLinVelEZ(DOF_Sw ,0,:) & + + x%QDT(DOF_Hv )*RtHSdat%PLinVelEZ(DOF_Hv ,0,:) + + + RtHSdat%PLinVelEY( :,:,:) = RtHSdat%PLinVelEZ(:,:,:) + DO I = 1,NPX ! Loop through all DOFs associated with the angular motion of the platform (body X) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I) ,0,:), RtHSdat%rZY ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I) ,0,:), EwXXrZY ) + + RtHSdat%PLinVelEY(PX(I),0,:) = TmpVec0 + RtHSdat%PLinVelEY(PX(I) ,0,:) + RtHSdat%PLinVelEY(PX(I),1,:) = TmpVec1 + RtHSdat%PLinVelEY(PX(I) ,1,:) + + RtHSdat%LinAccEYt = RtHSdat%LinAccEYt + x%QDT(PX(I) )*RtHSdat%PLinVelEY(PX(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the platform (body X) + + + RtHSdat%PLinVelEO( :,:,:) = RtHSdat%PLinVelEZ(:,:,:) + RtHSdat%PLinVelEO(DOF_TFA1,0,:) = CoordSys%a1 - ( p%AxRedTFA(1,1,p%TTopNode)* x%QT(DOF_TFA1) & + + p%AxRedTFA(1,2,p%TTopNode)* x%QT(DOF_TFA2) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TSS1,0,:) = CoordSys%a3 - ( p%AxRedTSS(1,1,p%TTopNode)* x%QT(DOF_TSS1) & + + p%AxRedTSS(1,2,p%TTopNode)* x%QT(DOF_TSS2) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TFA2,0,:) = CoordSys%a1 - ( p%AxRedTFA(2,2,p%TTopNode)* x%QT(DOF_TFA2) & + + p%AxRedTFA(1,2,p%TTopNode)* x%QT(DOF_TFA1) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TSS2,0,:) = CoordSys%a3 - ( p%AxRedTSS(2,2,p%TTopNode)* x%QT(DOF_TSS2) & + + p%AxRedTSS(1,2,p%TTopNode)* x%QT(DOF_TSS1) )*CoordSys%a2 + + TmpVec1 = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PLinVelEO(DOF_TFA1,0,:) ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PLinVelEO(DOF_TSS1,0,:) ) + TmpVec3 = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PLinVelEO(DOF_TFA2,0,:) ) + TmpVec4 = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PLinVelEO(DOF_TSS2,0,:) ) + + RtHSdat%PLinVelEO(DOF_TFA1,1,:) = TmpVec1 - ( p%AxRedTFA(1,1,p%TTopNode)*x%QDT(DOF_TFA1) & + + p%AxRedTFA(1,2,p%TTopNode)*x%QDT(DOF_TFA2) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TSS1,1,:) = TmpVec2 - ( p%AxRedTSS(1,1,p%TTopNode)*x%QDT(DOF_TSS1) & + + p%AxRedTSS(1,2,p%TTopNode)*x%QDT(DOF_TSS2) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TFA2,1,:) = TmpVec3 - ( p%AxRedTFA(2,2,p%TTopNode)*x%QDT(DOF_TFA2) & + + p%AxRedTFA(1,2,p%TTopNode)*x%QDT(DOF_TFA1) )*CoordSys%a2 + RtHSdat%PLinVelEO(DOF_TSS2,1,:) = TmpVec4 - ( p%AxRedTSS(2,2,p%TTopNode)*x%QDT(DOF_TSS2) & + + p%AxRedTSS(1,2,p%TTopNode)*x%QDT(DOF_TSS1) )*CoordSys%a2 + + LinVelXO = x%QDT(DOF_TFA1)*RtHSdat%PLinVelEO(DOF_TFA1,0,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PLinVelEO(DOF_TSS1,0,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PLinVelEO(DOF_TFA2,0,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PLinVelEO(DOF_TSS2,0,:) + RtHSdat%LinAccEOt = x%QDT(DOF_TFA1)*RtHSdat%PLinVelEO(DOF_TFA1,1,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PLinVelEO(DOF_TSS1,1,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PLinVelEO(DOF_TFA2,1,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PLinVelEO(DOF_TSS2,1,:) + + RtHSdat%LinVelEO = LinVelXO + RtHSdat%LinVelEZ + DO I = 1,NPX ! Loop through all DOFs associated with the angular motion of the platform (body X) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I) ,0,:), RtHSdat%rZO ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I) ,0,:), EwXXrZO + LinVelXO ) + + RtHSdat%PLinVelEO(PX(I),0,:) = TmpVec0 + RtHSdat%PLinVelEO(PX(I) ,0,:) + RtHSdat%PLinVelEO(PX(I),1,:) = TmpVec1 + RtHSdat%PLinVelEO(PX(I) ,1,:) + + RtHSdat%LinVelEO = RtHSdat%LinVelEO + x%QDT(PX(I) )*RtHSdat%PLinVelEO(PX(I) ,0,:) + RtHSdat%LinAccEOt = RtHSdat%LinAccEOt + x%QDT(PX(I) )*RtHSdat%PLinVelEO(PX(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the platform (body X) + + + RtHSdat%PLinVelEU( :,:,:) = RtHSdat%PLinVelEO(:,:,:) + DO I = 1,NPN ! Loop through all DOFs associated with the angular motion of the nacelle (body N) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), RtHSdat%rOU ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), EwNXrOU ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,1,:), RtHSdat%rOU ) + + RtHSdat%PLinVelEU(PN(I),0,:) = TmpVec0 + RtHSdat%PLinVelEU(PN(I) ,0,:) + RtHSdat%PLinVelEU(PN(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEU(PN(I) ,1,:) + + RtHSdat%LinAccEUt = RtHSdat%LinAccEUt + x%QDT(PN(I) )*RtHSdat%PLinVelEU(PN(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the nacelle (body N) + + + RtHSdat%PLinVelEV( :,:,:) = RtHSdat%PLinVelEO(:,:,:) + DO I = 1,NPN ! Loop through all DOFs associated with the angular motion of the nacelle (body N) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), RtHSdat%rOV ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), EwNXrOV ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,1,:), RtHSdat%rOV ) + + RtHSdat%PLinVelEV(PN(I),0,:) = TmpVec0 + RtHSdat%PLinVelEV(PN(I) ,0,:) + RtHSdat%PLinVelEV(PN(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEV(PN(I) ,1,:) + + LinAccEVt = LinAccEVt + x%QDT(PN(I) )*RtHSdat%PLinVelEV(PN(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the nacelle (body N) + + + RtHSdat%PLinVelED( :,:,:) = RtHSdat%PLinVelEV(:,:,:) + DO I = 1,NPR ! Loop through all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), RtHSdat%rVD ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), EwRXrVD ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,1,:), RtHSdat%rVD ) + + RtHSdat%PLinVelED(PR(I),0,:) = TmpVec0 + RtHSdat%PLinVelED(PR(I) ,0,:) + RtHSdat%PLinVelED(PR(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelED(PR(I) ,1,:) + + RtHSdat%LinAccEDt = RtHSdat%LinAccEDt + x%QDT(PR(I) )*RtHSdat%PLinVelED(PR(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + + RtHSdat%PLinVelEIMU( :,:,:) = RtHSdat%PLinVelEV(:,:,:) + RtHSdat%LinVelEIMU = RtHSdat%LinVelEZ + DO I = 1,NPR ! Loop through all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), RtHSdat%rVIMU ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), EwRXrVIMU ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,1,:), RtHSdat%rVIMU ) + + RtHSdat%PLinVelEIMU(PR(I),0,:) = TmpVec0 + RtHSdat%PLinVelEIMU(PR(I) ,0,:) + RtHSdat%PLinVelEIMU(PR(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEIMU(PR(I) ,1,:) + + RtHSdat%LinVelEIMU = RtHSdat%LinVelEIMU + x%QDT(PR(I) )*RtHSdat%PLinVelEIMU(PR(I) ,0,:) + RtHSdat%LinAccEIMUt = RtHSdat%LinAccEIMUt + x%QDT(PR(I) )*RtHSdat%PLinVelEIMU(PR(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + + RtHSdat%PLinVelEP( :,:,:) = RtHSdat%PLinVelEV(:,:,:) + DO I = 1,NPR ! Loop through all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), RtHSdat%rVP ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,0,:), EwRXrVP ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelER(PR(I) ,1,:), RtHSdat%rVP ) + + RtHSdat%PLinVelEP(PR(I),0,:) = TmpVec0 + RtHSdat%PLinVelEP(PR(I) ,0,:) + RtHSdat%PLinVelEP(PR(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEP(PR(I) ,1,:) + + LinAccEPt = LinAccEPt + x%QDT(PR(I) )*RtHSdat%PLinVelEP(PR(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the structure that furls with the rotor (not including rotor) (body R) + + + RtHSdat%PLinVelEQ( :,:,:) = RtHSdat%PLinVelEP(:,:,:) + RtHSdat%LinVelEQ = RtHSdat%LinVelEZ + DO I = 1,p%NPH ! Loop through all DOFs associated with the angular motion of the hub (body H) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,0,:), RtHSdat%rPQ ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,0,:), EwHXrPQ ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,1,:), RtHSdat%rPQ ) + + RtHSdat%PLinVelEQ(p%PH(I),0,:) = TmpVec0 + RtHSdat%PLinVelEQ(p%PH(I) ,0,:) + RtHSdat%PLinVelEQ(p%PH(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEQ(p%PH(I) ,1,:) + + RtHSdat%LinVelEQ = RtHSdat%LinVelEQ + x%QDT(p%PH(I) )*RtHSdat%PLinVelEQ(p%PH(I) ,0,:) + LinAccEQt = LinAccEQt + x%QDT(p%PH(I) )*RtHSdat%PLinVelEQ(p%PH(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the hub (body H) + + + RtHSdat%PLinVelEC( :,:,:) = RtHSdat%PLinVelEQ(:,:,:) + DO I = 1,p%NPH ! Loop through all DOFs associated with the angular motion of the hub (body H) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,0,:), RtHSdat%rQC ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,0,:), EwHXrQC ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I) ,1,:), RtHSdat%rQC ) + + RtHSdat%PLinVelEC(p%PH(I),0,:) = TmpVec0 + RtHSdat%PLinVelEC(p%PH(I) ,0,:) + RtHSdat%PLinVelEC(p%PH(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEC(p%PH(I) ,1,:) + + RtHSdat%LinAccECt = RtHSdat%LinAccECt + x%QDT(p%PH(I) )*RtHSdat%PLinVelEC(p%PH(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the hub (body H) + + + + + DO K = 1,p%NumBl ! Loop through all blades + + DO J = 0,p%TipNode ! Loop through the blade nodes / elements + + ! Define the partial linear velocities (and their 1st derivatives) of the + ! current node (point S(RNodes(J))) in the inertia frame. Also define + ! the overall linear velocity of the current node in the inertia frame. + ! Also, define the portion of the linear acceleration of the current node + ! in the inertia frame associated with everything but the QD2T()'s: + + EwHXrQS = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%rQS(:,K,J) ) + + RtHSdat%PLinVelES(K,J, :,:,:) = RtHSdat%PLinVelEQ(:,:,:) + RtHSdat%PLinVelES(K,J,DOF_BF(K,1),0,:) = p%TwistedSF(K,1,1,J,0) *CoordSys%j1(K,:) & !bjj: this line can be optimized + + p%TwistedSF(K,2,1,J,0) *CoordSys%j2(K,:) & + - ( p%AxRedBld(K,1,1,J)*x%QT ( DOF_BF(K,1) ) & + + p%AxRedBld(K,1,2,J)*x%QT ( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,3,J)*x%QT ( DOF_BE(K,1) ) )*CoordSys%j3(K,:) + RtHSdat%PLinVelES(K,J,DOF_BE(K,1),0,:) = p%TwistedSF(K,1,3,J,0) *CoordSys%j1(K,:) & + + p%TwistedSF(K,2,3,J,0) *CoordSys%j2(K,:) & + - ( p%AxRedBld(K,3,3,J)*x%QT ( DOF_BE(K,1) ) & + + p%AxRedBld(K,2,3,J)*x%QT ( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,3,J)*x%QT ( DOF_BF(K,1) ) )*CoordSys%j3(K,:) + RtHSdat%PLinVelES(K,J,DOF_BF(K,2),0,:) = p%TwistedSF(K,1,2,J,0) *CoordSys%j1(K,:) & + + p%TwistedSF(K,2,2,J,0) *CoordSys%j2(K,:) & + - ( p%AxRedBld(K,2,2,J)*x%QT ( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,2,J)*x%QT ( DOF_BF(K,1) ) & + + p%AxRedBld(K,2,3,J)*x%QT ( DOF_BE(K,1) ) )*CoordSys%j3(K,:) + + TmpVec1 = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%PLinVelES(K,J,DOF_BF(K,1),0,:) ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%PLinVelES(K,J,DOF_BE(K,1),0,:) ) + TmpVec3 = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%PLinVelES(K,J,DOF_BF(K,2),0,:) ) + + RtHSdat%PLinVelES(K,J,DOF_BF(K,1),1,:) = TmpVec1 & + - ( p%AxRedBld(K,1,1,J)*x%QDT( DOF_BF(K,1) ) & + + p%AxRedBld(K,1,2,J)*x%QDT( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,3,J)*x%QDT( DOF_BE(K,1) ) )*CoordSys%j3(K,:) + RtHSdat%PLinVelES(K,J,DOF_BE(K,1),1,:) = TmpVec2 & + - ( p%AxRedBld(K,3,3,J)*x%QDT( DOF_BE(K,1) ) & + + p%AxRedBld(K,2,3,J)*x%QDT( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,3,J)*x%QDT( DOF_BF(K,1) ) )*CoordSys%j3(K,:) + RtHSdat%PLinVelES(K,J,DOF_BF(K,2),1,:) = TmpVec3 & + - ( p%AxRedBld(K,2,2,J)*x%QDT( DOF_BF(K,2) ) & + + p%AxRedBld(K,1,2,J)*x%QDT( DOF_BF(K,1) ) & + + p%AxRedBld(K,2,3,J)*x%QDT( DOF_BE(K,1) ) )*CoordSys%j3(K,:) + + LinVelHS = x%QDT( DOF_BF(K,1) )*RtHSdat%PLinVelES(K,J,DOF_BF(K,1),0,:) & + + x%QDT( DOF_BE(K,1) )*RtHSdat%PLinVelES(K,J,DOF_BE(K,1),0,:) & + + x%QDT( DOF_BF(K,2) )*RtHSdat%PLinVelES(K,J,DOF_BF(K,2),0,:) + RtHSdat%LinAccESt(:,K,J) = x%QDT( DOF_BF(K,1) )*RtHSdat%PLinVelES(K,J,DOF_BF(K,1),1,:) & + + x%QDT( DOF_BE(K,1) )*RtHSdat%PLinVelES(K,J,DOF_BE(K,1),1,:) & + + x%QDT( DOF_BF(K,2) )*RtHSdat%PLinVelES(K,J,DOF_BF(K,2),1,:) + + RtHSdat%LinVelES(:,J,K) = LinVelHS + RtHSdat%LinVelEZ + DO I = 1,p%NPH ! Loop through all DOFs associated with the angular motion of the hub (body H) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I),0,:), RtHSdat%rQS(:,K,J) ) !bjj: this line can be optimized + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I),0,:), EwHXrQS + LinVelHS ) !bjj: this line can be optimized + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEH(p%PH(I),1,:), RtHSdat%rQS(:,K,J) ) !bjj: this line can be optimized + + RtHSdat%PLinVelES(K,J,p%PH(I),0,:) = RtHSdat%PLinVelES(K,J,p%PH(I),0,:) + TmpVec0 !bjj: this line can be optimized + RtHSdat%PLinVelES(K,J,p%PH(I),1,:) = RtHSdat%PLinVelES(K,J,p%PH(I),1,:) + TmpVec1 + TmpVec2 !bjj: this line can be optimized + + RtHSdat%LinVelES(:,J,K) = RtHSdat%LinVelES(:,J,K) + x%QDT(p%PH(I))*RtHSdat%PLinVelES(K,J,p%PH(I),0,:) !bjj: this line can be optimized + RtHSdat%LinAccESt(:,K,J) = RtHSdat%LinAccESt(:,K,J) + x%QDT(p%PH(I))*RtHSdat%PLinVelES(K,J,p%PH(I),1,:) !bjj: this line can be optimized + + END DO ! I - all DOFs associated with the angular motion of the hub (body H) + + END DO !J = 0,p%TipNodes ! Loop through the blade nodes / elements + + + !JASON: USE TipNode HERE INSTEAD OF BldNodes IF YOU ALLOCATE AND DEFINE n1, n2, n3, m1, m2, AND m3 TO USE TipNode. THIS WILL REQUIRE THAT THE AERODYNAMIC AND STRUCTURAL TWISTS, AeroTwst() AND ThetaS(), BE KNOWN AT THE TIP!!! + !IF (.NOT. p%BD4Blades) THEN + ! RtHSdat%LinVelESm2(K) = DOT_PRODUCT( RtHSdat%LinVelES(:,p%TipNode,K), CoordSys%m2(K,p%BldNodes,:) ) + !END IF + + END DO !K = 1,p%NumBl + + + RtHSdat%PLinVelEW( :,:,:) = RtHSdat%PLinVelEO(:,:,:) + DO I = 1,NPN ! Loop through all DOFs associated with the angular motion of the nacelle (body N) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), RtHSdat%rOW ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,0,:), EwNXrOW ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEN(PN(I) ,1,:), RtHSdat%rOW ) + + RtHSdat%PLinVelEW(PN(I),0,:) = TmpVec0 + RtHSdat%PLinVelEW(PN(I) ,0,:) + RtHSdat%PLinVelEW(PN(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEW(PN(I) ,1,:) + + LinAccEWt = LinAccEWt + x%QDT(PN(I) )*RtHSdat%PLinVelEW(PN(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the nacelle (body N) + + + RtHSdat%PLinVelEI( :,:,:) = RtHSdat%PLinVelEW(:,:,:) + DO I = 1,NPA ! Loop through all DOFs associated with the angular motion of the tail (body A) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), RtHSdat%rWI ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), EwAXrWI ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,1,:), RtHSdat%rWI ) + + RtHSdat%PLinVelEI(PA(I),0,:) = TmpVec0 + RtHSdat%PLinVelEI(PA(I) ,0,:) + RtHSdat%PLinVelEI(PA(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEI(PA(I) ,1,:) + + RtHSdat%LinAccEIt = RtHSdat%LinAccEIt + x%QDT(PA(I) )*RtHSdat%PLinVelEI(PA(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the tail (body A) + + + RtHSdat%PLinVelEJ( :,:,:) = RtHSdat%PLinVelEW(:,:,:) + DO I = 1,NPA ! Loop through all DOFs associated with the angular motion of the tail (body A) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), RtHSdat%rWJ ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), EwAXrWJ ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,1,:), RtHSdat%rWJ ) + + RtHSdat%PLinVelEJ(PA(I),0,:) = TmpVec0 + RtHSdat%PLinVelEJ(PA(I) ,0,:) + RtHSdat%PLinVelEJ(PA(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEJ(PA(I) ,1,:) + + RtHSdat%LinAccEJt = RtHSdat%LinAccEJt + x%QDT(PA(I) )*RtHSdat%PLinVelEJ(PA(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the tail (body A) + + RtHSdat%PLinVelEK( :,:,:) = RtHSdat%PLinVelEW(:,:,:) + LinVelEK = RtHSdat%LinVelEZ + DO I = 1,NPA ! Loop through all DOFs associated with the angular motion of the tail (body A) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), RtHSdat%rWK ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,0,:), EwAXrWK ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%PAngVelEA(PA(I) ,1,:), RtHSdat%rWK ) + + RtHSdat%PLinVelEK(PA(I),0,:) = TmpVec0 + RtHSdat%PLinVelEK(PA(I) ,0,:) + RtHSdat%PLinVelEK(PA(I),1,:) = TmpVec1 + TmpVec2 + RtHSdat%PLinVelEK(PA(I) ,1,:) + + LinVelEK = LinVelEK + x%QDT(PA(I) )*RtHSdat%PLinVelEK(PA(I) ,0,:) + LinAccEKt = LinAccEKt + x%QDT(PA(I) )*RtHSdat%PLinVelEK(PA(I) ,1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the tail (body A) + + + + DO J = 0,p%TwrNodes ! Loop through the tower nodes / elements + + + ! Define the partial linear velocities (and their 1st derivatives) of the current node (point T(HNodes(J))) in the inertia frame. + ! Also define the overall linear velocity of the current node in the inertia frame. + ! Also, define the portion of the linear acceleration of the current node in the inertia frame associated with + ! everything but the QD2T()'s: + + EwXXrZT = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%rZT(:,J) ) + + RtHSdat%PLinVelET(J, :,:,:) = RtHSdat%PLinVelEZ(:,:,:) !bjj: can this line be optimized + RtHSdat%PLinVelET(J,DOF_TFA1,0,:) = p%TwrFASF(1,J,0)*CoordSys%a1 - ( p%AxRedTFA(1,1,J)* x%QT(DOF_TFA1) & + + p%AxRedTFA(1,2,J)* x%QT(DOF_TFA2) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TSS1,0,:) = p%TwrSSSF(1,J,0)*CoordSys%a3 - ( p%AxRedTSS(1,1,J)* x%QT(DOF_TSS1) & + + p%AxRedTSS(1,2,J)* x%QT(DOF_TSS2) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TFA2,0,:) = p%TwrFASF(2,J,0)*CoordSys%a1 - ( p%AxRedTFA(2,2,J)* x%QT(DOF_TFA2) & + + p%AxRedTFA(1,2,J)* x%QT(DOF_TFA1) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TSS2,0,:) = p%TwrSSSF(2,J,0)*CoordSys%a3 - ( p%AxRedTSS(2,2,J)* x%QT(DOF_TSS2) & + + p%AxRedTSS(1,2,J)* x%QT(DOF_TSS1) )*CoordSys%a2 + + TmpVec1 = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PLinVelET(J,DOF_TFA1,0,:) ) + TmpVec2 = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PLinVelET(J,DOF_TSS1,0,:) ) + TmpVec3 = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PLinVelET(J,DOF_TFA2,0,:) ) + TmpVec4 = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PLinVelET(J,DOF_TSS2,0,:) ) + + RtHSdat%PLinVelET(J,DOF_TFA1,1,:) = TmpVec1 - ( p%AxRedTFA(1,1,J)*x%QDT(DOF_TFA1) & + + p%AxRedTFA(1,2,J)*x%QDT(DOF_TFA2) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TSS1,1,:) = TmpVec2 - ( p%AxRedTSS(1,1,J)*x%QDT(DOF_TSS1) & + + p%AxRedTSS(1,2,J)*x%QDT(DOF_TSS2) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TFA2,1,:) = TmpVec3 - ( p%AxRedTFA(2,2,J)*x%QDT(DOF_TFA2) & + + p%AxRedTFA(1,2,J)*x%QDT(DOF_TFA1) )*CoordSys%a2 + RtHSdat%PLinVelET(J,DOF_TSS2,1,:) = TmpVec4 - ( p%AxRedTSS(2,2,J)*x%QDT(DOF_TSS2) & + + p%AxRedTSS(1,2,J)*x%QDT(DOF_TSS1) )*CoordSys%a2 + + LinVelXT = x%QDT(DOF_TFA1)*RtHSdat%PLinVelET(J,DOF_TFA1,0,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PLinVelET(J,DOF_TSS1,0,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PLinVelET(J,DOF_TFA2,0,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PLinVelET(J,DOF_TSS2,0,:) + RtHSdat%LinAccETt(:,J) = x%QDT(DOF_TFA1)*RtHSdat%PLinVelET(J,DOF_TFA1,1,:) & + + x%QDT(DOF_TSS1)*RtHSdat%PLinVelET(J,DOF_TSS1,1,:) & + + x%QDT(DOF_TFA2)*RtHSdat%PLinVelET(J,DOF_TFA2,1,:) & + + x%QDT(DOF_TSS2)*RtHSdat%PLinVelET(J,DOF_TSS2,1,:) + + RtHSdat%LinVelET(:,J) = LinVelXT + RtHSdat%LinVelEZ + DO I = 1,NPX ! Loop through all DOFs associated with the angular motion of the platform (body X) + + TmpVec0 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I),0,:), RtHSdat%rZT(:,J) ) + TmpVec1 = CROSS_PRODUCT( RtHSdat%PAngVelEX(PX(I),0,:), EwXXrZT + LinVelXT ) + + RtHSdat%PLinVelET(J,PX(I),0,:) = RtHSdat%PLinVelET(J,PX(I),0,:) + TmpVec0 + RtHSdat%PLinVelET(J,PX(I),1,:) = RtHSdat%PLinVelET(J,PX(I),1,:) + TmpVec1 + + RtHSdat%LinVelET( :, J) = RtHSdat%LinVelET( :, J) + x%QDT(PX(I))*RtHSdat%PLinVelET(J,PX(I),0,:) + RtHSdat%LinAccETt(:, J) = RtHSdat%LinAccETt(:, J) + x%QDT(PX(I))*RtHSdat%PLinVelET(J,PX(I),1,:) + + ENDDO ! I - all DOFs associated with the angular motion of the platform (body X) + + + END DO ! J + + +END SUBROUTINE CalculateLinearVelPAcc +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to calculate the forces and moments stored in other states that are used in +!! both the CalcOutput and CalcContStateDeriv routines. +SUBROUTINE CalculateForcesMoments( p, x, CoordSys, u, RtHSdat ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time + TYPE(ED_InputType), INTENT(IN ) :: u !< The aero (blade) & nacelle forces/moments + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set) + + ! Local variables + REAL(ReKi) :: TmpVec (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec1 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec2 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec3 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec4 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec5 (3) ! A temporary vector used in various computations. + +!REAL(ReKi) :: rSAerCen (3) ! Position vector from a blade analysis node (point S) on the current blade to the aerodynamic center associated with the element. + REAL(ReKi), PARAMETER :: FKAero (3) = 0.0 ! The tail fin aerodynamic force acting at point K, the center-of-pressure of the tail fin. (bjj: should be an input) + REAL(ReKi), PARAMETER :: MAAero (3) = 0.0 ! The tail fin aerodynamic moment acting at point K, the center-of-pressure of the tail fin. (bjj: should be an input) + + + INTEGER(IntKi) :: I ! Loops through some or all of the DOFs + INTEGER(IntKi) :: J ! Counter for elements + INTEGER(IntKi) :: K ! Counter for blades + INTEGER(IntKi) :: NodeNum ! Node number for blade element (on a single mesh) + +!..................................... +! Compute forces and moments from properties related to Aero inputs +!FSTipDrag +!FSAero and MMAero +!..................................... + DO K = 1,p%NumBl ! Loop through all blades + + ! Calculate the tip drag forces if necessary: + !bjj: add this back when we've figured out how to handle the tip brakes: + !RtHSdat%FSTipDrag(:,K) = m%CoordSys%m2(K,p%BldNodes,:)*SIGN( 0.5*p%AirDens*(RtHSdat%LinVelESm2(K)**2)*u%TBDrCon(K), -1.*RtHSdat%LinVelESm2(K) ) + RtHSdat%FSTipDrag = 0.0_ReKi ! Calculate the tip drag forces if necessary + + + ! Calculate the normal and tangential aerodynamic forces and the aerodynamic + ! pitching moment at the current element per unit span by calling AeroDyn, + ! if necessary: + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + + ! Calculate the aerodynamic pitching moment arm (i.e., the position vector + ! from point S on the blade to the aerodynamic center of the element): + + RtHSdat%rSAerCen(:,J,K) = p%rSAerCenn1(K,J)*CoordSys%n1(K,J,:) + p%rSAerCenn2(K,J)*CoordSys%n2(K,J,:) + +! rPAerCen = m%RtHS%rPQ + m%RtHS%rQS(:,K,J) + m%RtHS%rSAerCen(:,J,K) ! Position vector from teeter pin (point P) to blade analysis node aerodynamic center. +! rAerCen = m%RtHS%rS (:,K,J) + m%RtHS%rSAerCen(:,J,K) ! Position vector from inertial frame origin to blade analysis node aerodynamic center. + + + ! fill FSAero() and MMAero() with the forces resulting from inputs u%BladeLn2Mesh(K)%Force(1:2,:) and u%BladeLn2Mesh(K)%Moment(3,:): + ! [except, we're ignoring the additional nodes we added on the mesh end points] + + NodeNum = J ! we're ignoring the root and tip + + if (p%UseAD14) then + RtHSdat%FSAero(:,K,J) = ( u%BladePtLoads(K)%Force(1,NodeNum) * CoordSys%te1(K,J,:) & + + u%BladePtLoads(K)%Force(2,NodeNum) * CoordSys%te2(K,J,:) ) / p%DRNodes(J) + + RtHSdat%MMAero(:,K,J) = CROSS_PRODUCT( RtHSdat%rSAerCen(:,J,K), RtHSdat%FSAero(:,K,J) )& + + u%BladePtLoads(K)%Moment(3,NodeNum)/p%DRNodes(J) * CoordSys%te3(K,J,:) + else + RtHSdat%FSAero(1,K,J) = u%BladePtLoads(K)%Force(1,NodeNum) / p%DRNodes(J) + RtHSdat%FSAero(2,K,J) = u%BladePtLoads(K)%Force(3,NodeNum) / p%DRNodes(J) + RtHSdat%FSAero(3,K,J) = -u%BladePtLoads(K)%Force(2,NodeNum) / p%DRNodes(J) + + RtHSdat%MMAero(1,K,J) = u%BladePtLoads(K)%Moment(1,NodeNum) / p%DRNodes(J) + RtHSdat%MMAero(2,K,J) = u%BladePtLoads(K)%Moment(3,NodeNum) / p%DRNodes(J) + RtHSdat%MMAero(3,K,J) = -u%BladePtLoads(K)%Moment(2,NodeNum) / p%DRNodes(J) + end if + + + END DO !J + END DO ! K + + +!..................................... +! PFrcS0B and PMomH0B +!..................................... +DO K = 1,p%NumBl ! Loop through all blades + + ! Initialize the partial forces and moments (including those associated + ! with the QD2T()'s and those that are not) at the blade root (point S(0)) + ! using the tip brake effects: + + RtHSdat%PFrcS0B(:,K,:) = 0.0 ! Initialize these partial + RtHSdat%PMomH0B(:,K,:) = 0.0 ! forces and moments to zero + DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + TmpVec1 = -p%TipMass(K)*RtHSdat%PLinVelES(K,p%TipNode,p%DOFs%PSE(K,I),0,:) ! The portion of PFrcS0B associated with the tip brake + + RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) = TmpVec1 + RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) = CROSS_PRODUCT( RtHSdat%rS0S(:,K,p%TipNode), TmpVec1 ) ! The portion of PMomH0B associated with the tip brake + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + ! Integrate to find the partial forces and moments (including those associated + ! with the QD2T()'s and those that are not) at the blade root (point S(0)): + + DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + TmpVec1 = -p%BElmntMass(J,K)*RtHSdat%PLinVelES(K,J,p%DOFs%PSE(K,I),0,:) ! The portion of PFrcS0B associated with blade element J + + RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) = RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) + TmpVec1 + RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) = RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) + & + CROSS_PRODUCT( RtHSdat%rS0S(:,K,J), TmpVec1 ) ! The portion of PMomH0B associated with blade element J + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + END DO + + + END DO + + +!..................................... +! FrcS0Bt and MomH0Bt +!..................................... + DO K = 1,p%NumBl ! Loop through all blades + + TmpVec1 = RtHSdat%FSTipDrag(:,K) - p%TipMass(K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,p%TipNode) ) ! The portion of FrcS0Bt associated with the tip brake + RtHSdat%FrcS0Bt(:,K) = TmpVec1 + RtHSdat%MomH0Bt(:,K) = CROSS_PRODUCT( RtHSdat%rS0S(:,K,p%TipNode), TmpVec1 ) ! The portion of MomH0Bt associated with the tip brake + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + TmpVec1 = RtHSdat%FSAero(:,K,J)*p%DRNodes(J) - p%BElmntMass(J,K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,J) ) ! The portion of FrcS0Bt associated with blade element J + TmpVec2 = CROSS_PRODUCT( RtHSdat%rS0S(:,K,J), TmpVec1 ) ! The portion of MomH0Bt associated with blade element J + TmpVec3 = RtHSdat%MMAero(:,K,J)*p%DRNodes(J) ! The total external moment applied to blade element J + + RtHSdat%FrcS0Bt(:,K) = RtHSdat%FrcS0Bt(:,K) + TmpVec1 + RtHSdat%MomH0Bt(:,K) = RtHSdat%MomH0Bt(:,K) + TmpVec2 + TmpVec3 + + END DO !J + + END DO !K + + +!..................................... +! PFrcPRot AND PMomLPRot: +! ( requires PFrcS0B and PMomH0B) +!..................................... + ! Initialize the partial forces and moments (including those associated + ! with the QD2T()'s and those that are not) at the teeter pin (point P) using the hub mass effects: + + RtHSdat%PFrcPRot = 0.0 ! Initialize these partial + RtHSdat%PMomLPRot = 0.0 ! forces and moments to zero + DO I = 1,p%DOFs%NPCE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) + + TmpVec1 = -p%HubMass*RtHSdat%PLinVelEC(p%DOFs%PCE(I),0,:) ! The portion of PFrcPRot associated with the HubMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rPC, TmpVec1 ) ! The portion of PMomLPRot associated with the HubMass + + RtHSdat%PFrcPRot (:,p%DOFs%PCE(I)) = TmpVec1 + RtHSdat%PMomLPRot(:,p%DOFs%PCE(I)) = TmpVec2 - p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%PAngVelEH(p%DOFs%PCE(I),0,:) ) & + - p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%PAngVelEH(p%DOFs%PCE(I),0,:) ) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) + + + DO K = 1,p%NumBl ! Loop through all blades + + ! Calculate the position vector from the teeter pin to the blade root: + + !rPS0(:,K) = RtHSdat%rPQ + p%HubRad*CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)). + + ! Add the blade effects to the partial forces and moments (including those associated with the QD2T()'s and those that are + ! not) at the teeter pin (point P): + + DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + TmpVec = CROSS_PRODUCT( RtHSdat%rPS0(:,K), RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) ) ! The portion of PMomLPRot associated with PFrcS0B. + + RtHSdat%PFrcPRot (:,p%DOFs%PSE(K,I)) = RtHSdat%PFrcPRot (:,p%DOFs%PSE(K,I)) + RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) + RtHSdat%PMomLPRot(:,p%DOFs%PSE(K,I)) = RtHSdat%PMomLPRot(:,p%DOFs%PSE(K,I)) + RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I))+TmpVec + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K + + + END DO ! K + +!..................................... +! FrcPRott and MomLPRott: +! (requires FrcS0Bt and MomH0Bt) +!..................................... + + TmpVec1 = -p%HubMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccECt ) ! The portion of FrcPRott associated with the HubMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rPC, TmpVec1 ) ! The portion of MomLPRott associated with the HubMass + TmpVec = p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%AngVelEH ) & ! = ( Hub inertia dyadic ) dot ( angular velocity of hub in the inertia frame ) + + p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%AngVelEH ) + TmpVec3 = CROSS_PRODUCT( -RtHSdat%AngVelEH, TmpVec ) ! = ( -angular velocity of hub in the inertia frame ) cross ( TmpVec ) + + RtHSdat%FrcPRott(1) = TmpVec1(1) + u%HubPtLoad%Force(1,1) + RtHSdat%FrcPRott(2) = TmpVec1(2) + u%HubPtLoad%Force(3,1) + RtHSdat%FrcPRott(3) = TmpVec1(3) - u%HubPtLoad%Force(2,1) + + RtHSdat%MomLPRott = TmpVec2 + TmpVec3 - p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%AngAccEHt ) & + - p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%AngAccEHt ) + + RtHSdat%MomLPRott(1) = RtHSdat%MomLPRott(1) + u%HubPtLoad%Moment(1,1) + RtHSdat%MomLPRott(2) = RtHSdat%MomLPRott(2) + u%HubPtLoad%Moment(3,1) + RtHSdat%MomLPRott(3) = RtHSdat%MomLPRott(3) - u%HubPtLoad%Moment(2,1) + + DO K = 1,p%NumBl ! Loop through all blades + + ! Calculate the position vector from the teeter pin to the blade root: + + !rPS0 = RtHSdat%rPQ + p%HubRad*m%CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)). + + TmpVec = CROSS_PRODUCT( RtHSdat%rPS0(:,K), RtHSdat%FrcS0Bt(:,K) ) ! The portion of MomLPRott associated with FrcS0Bt. + + RtHSdat%FrcPRott = RtHSdat%FrcPRott + RtHSdat%FrcS0Bt(:,K) + RtHSdat%MomLPRott = RtHSdat%MomLPRott + RtHSdat%MomH0Bt(:,K) + TmpVec + + END DO ! K + + + ! Define the partial forces and moments (including those associated with + ! the QD2T()'s and those that are not) at the specified point on the + ! rotor-furl axis (point V) / nacelle (body N) using the structure that + ! furls with the rotor, generator, and rotor effects. + +!..................................... +! PMomNGnRt and PFrcVGnRt +! (requires PMomLPRot and PFrcPRot) +!..................................... + RtHSdat%PFrcVGnRt = RtHSdat%PFrcPRot ! Initialize these partial forces and + RtHSdat%PMomNGnRt = RtHSdat%PMomLPRot ! moments using the rotor effects + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + TmpVec = CROSS_PRODUCT( RtHSdat%rVP, RtHSdat%PFrcPRot(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomNGnRt associated with the PFrcPRot + + RtHSdat%PMomNGnRt(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomNGnRt(:,p%DOFs%SrtPS(I)) + TmpVec + + ENDDO ! I - All active (enabled) DOFs + DO I = 1,p%DOFs%NPDE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) + + TmpVec1 = -p%RFrlMass*RtHSdat%PLinVelED(p%DOFs%PDE(I) ,0,:) ! The portion of PFrcVGnRt associated with the RFrlMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rVD, TmpVec1 ) ! The portion of PMomNGnRt associated with the RFrlMass + + RtHSdat%PFrcVGnRt(:,p%DOFs%PDE(I) ) = RtHSdat%PFrcVGnRt(:,p%DOFs%PDE(I) ) + TmpVec1 + + RtHSdat%PMomNGnRt(:,p%DOFs%PDE(I) ) = RtHSdat%PMomNGnRt(:,p%DOFs%PDE(I) ) + TmpVec2 & + - p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%PAngVelER(p%DOFs%PDE(I) ,0,:) ) & + - p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1 , RtHSdat%PAngVelEG(p%DOFs%PDE(I) ,0,:) ) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) + IF ( p%DOF_Flag(DOF_GeAz) ) THEN + + RtHSdat%PMomNGnRt(:,DOF_GeAz) = RtHSdat%PMomNGnRt(:,DOF_GeAz) & ! The previous loop (DO I = 1,NPDE) misses the DOF_GeAz-contribution to: ( Generator inertia dyadic ) dot ( partial angular velocity of the generator in the inertia frame ) + - p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1, RtHSdat%PAngVelEG(DOF_GeAz,0,:) ) ! Thus, add this contribution if necessary. + + ENDIF + +!..................................... +! FrcVGnRtt and MomNGnRtt +! (requires FrcPRott and MomLPRott) +!..................................... + TmpVec1 = -p%RFrlMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEDt ) ! The portion of FrcVGnRtt associated with the RFrlMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rVD , TmpVec1 ) ! The portion of MomNGnRtt associated with the RFrlMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rVP , RtHSdat%FrcPRott ) ! The portion of MomNGnRtt associated with the FrcPRott + TmpVec = p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%AngVelER ) ! = ( R inertia dyadic ) dot ( angular velocity of structure that furls with the rotor in the inertia frame ) + TmpVec4 = CROSS_PRODUCT( -RtHSdat%AngVelER, TmpVec ) ! = ( -angular velocity of structure that furls with the rotor in the inertia frame ) cross ( TmpVec ) + TmpVec = p%GenIner*CoordSys%c1* DOT_PRODUCT( CoordSys%c1 , RtHSdat%AngVelEG ) ! = ( Generator inertia dyadic ) dot ( angular velocity of generator in the inertia frame ) + TmpVec5 = CROSS_PRODUCT( -RtHSdat%AngVelEG, TmpVec ) ! = ( -angular velocity of generator in the inertia frame ) cross ( TmpVec ) + + RtHSdat%FrcVGnRtt = RtHSdat%FrcPRott + TmpVec1 + RtHSdat%MomNGnRtt = RtHSdat%MomLPRott + TmpVec2 + TmpVec3 + TmpVec4 + TmpVec5 & + - p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%AngAccERt ) & + - p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1 , RtHSdat%AngAccEGt ) + + +!..................................... +! PFrcWTail and PMomNTail +!..................................... + ! Define the partial forces and moments (including those associated with the QD2T()'s and + ! those that are not) at the specified point on the tail-furl axis (point W) / nacelle (body N) using the tail effects. + + RtHSdat%PFrcWTail = 0.0 ! Initialize these partial + RtHSdat%PMomNTail = 0.0 ! forces and moments to zero + DO I = 1,p%DOFs%NPIE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) + + TmpVec1 = -p%BoomMass*RtHSdat%PLinVelEI(p%DOFs%PIE(I),0,:) ! The portion of PFrcWTail associated with the BoomMass + TmpVec2 = -p%TFinMass*RtHSdat%PLinVelEJ(p%DOFs%PIE(I),0,:) ! The portion of PFrcWTail associated with the TFinMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rWI, TmpVec1 ) ! The portion of PMomNTail associated with the BoomMass + TmpVec4 = CROSS_PRODUCT( RtHSdat%rWJ, TmpVec2 ) ! The portion of PMomNTail associated with the TFinMass + + RtHSdat%PFrcWTail(:,p%DOFs%PIE(I)) = TmpVec1 + TmpVec2 + RtHSdat%PMomNTail(:,p%DOFs%PIE(I)) = TmpVec3 + TmpVec4 - p%AtfaIner*CoordSys%tfa* & + DOT_PRODUCT( CoordSys%tfa, RtHSdat%PAngVelEA(p%DOFs%PIE(I),0,:) ) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) + +!..................................... +! FrcWTailt and MomNTailt +! (requires FKAero and MAAero) +!..................................... + + TmpVec1 = -p%BoomMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEIt ) ! The portion of FrcWTailt associated with the BoomMass + TmpVec2 = -p%TFinMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEJt ) ! The portion of FrcWTailt associated with the TFinMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rWI , TmpVec1 ) ! The portion of MomNTailt associated with the BoomMass + TmpVec4 = CROSS_PRODUCT( RtHSdat%rWJ , TmpVec2 ) ! The portion of MomNTailt associated with the TFinMass + TmpVec = p%AtfaIner*CoordSys%tfa*DOT_PRODUCT( CoordSys%tfa, RtHSdat%AngVelEA ) ! = ( A inertia dyadic ) dot ( angular velocity of the tail in the inertia frame ) + TmpVec5 = CROSS_PRODUCT( -RtHSdat%AngVelEA, TmpVec ) ! = ( -angular velocity of the tail in the inertia frame ) cross ( TmpVec ) + + RtHSdat%FrcWTailt = FKAero + TmpVec1 + TmpVec2 + RtHSdat%MomNTailt = MAAero + TmpVec3 + TmpVec4 + TmpVec5 & + + CROSS_PRODUCT( RtHSdat%rWK , FKAero ) & ! The portion of MomNTailt associated with FKAero + - p%AtfaIner*CoordSys%tfa*DOT_PRODUCT( CoordSys%tfa, RtHSdat%AngAccEAt ) + +!..................................... +! PFrcONcRt and PMomBNcRt +! (requires PFrcVGnRt, PMomNGnRt, PFrcWTail, PMomNTail, ) +!..................................... + + ! Define the partial forces and moments (including those associated with + ! the QD2T()'s and those that are not) at the yaw bearing (point O) / + ! base plate (body B) using the nacelle, generator, rotor, and tail effects. + + RtHSdat%PFrcONcRt = RtHSdat%PFrcVGnRt + RtHSdat%PFrcWTail ! Initialize these partial forces and moments using + RtHSdat%PMomBNcRt = RtHSdat%PMomNGnRt + RtHSdat%PMomNTail ! the rotor, rotor-furl, generator, and tail effects + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + TmpVec = CROSS_PRODUCT( RtHSdat%rOV, RtHSdat%PFrcVGnRt(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomBNcRt associated with the PFrcVGnRt + + RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) + TmpVec + + ENDDO ! I - All active (enabled) DOFs + DO I = 1,p%DOFs%NPIE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) + + TmpVec = CROSS_PRODUCT( RtHSdat%rOW, RtHSdat%PFrcWTail(:,p%DOFs%PIE(I) ) ) ! The portion of PMomBNcRt associated with the PFrcWTail + + RtHSdat%PMomBNcRt(:,p%DOFs%PIE(I) ) = RtHSdat%PMomBNcRt(:,p%DOFs%PIE(I) ) + TmpVec + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) + DO I = 1,p%DOFs%NPUE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) + + TmpVec1 = -p%NacMass*RtHSdat%PLinVelEU(p%DOFs%PUE(I),0,:) ! The portion of PFrcONcRt associated with the NacMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rOU, TmpVec1 ) ! The portion of PMomBNcRt associated with the NacMass + + RtHSdat%PFrcONcRt(:,p%DOFs%PUE(I) ) = RtHSdat%PFrcONcRt(:,p%DOFs%PUE(I) ) + TmpVec1 + RtHSdat%PMomBNcRt(:,p%DOFs%PUE(I) ) = RtHSdat%PMomBNcRt(:,p%DOFs%PUE(I) ) + TmpVec2 - p%Nacd2Iner*CoordSys%d2* & + DOT_PRODUCT( CoordSys%d2, RtHSdat%PAngVelEN(p%DOFs%PUE(I),0,:) ) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) + + +!..................................... +! FrcONcRtt and MomBNcRtt +! (requires FrcVGnRtt, MomNGnRtt, FrcWTailt, MomNTailt) +!..................................... + + TmpVec1 = -p%NacMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEUt ) ! The portion of FrcONcRtt associated with the NacMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rOU, TmpVec1 ) ! The portion of MomBNcRtt associated with the NacMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rOV, RtHSdat%FrcVGnRtt ) ! The portion of MomBNcRtt associated with the FrcVGnRtt + TmpVec4 = CROSS_PRODUCT( RtHSdat%rOW, RtHSdat%FrcWTailt ) ! The portion of MomBNcRtt associated with the FrcWTailt + TmpVec = p%Nacd2Iner*CoordSys%d2*DOT_PRODUCT( CoordSys%d2, RtHSdat%AngVelEN ) ! = ( Nacelle inertia dyadic ) dot ( angular velocity of nacelle in the inertia frame ) + + RtHSdat%FrcONcRtt = RtHSdat%FrcVGnRtt + RtHSdat%FrcWTailt + TmpVec1 + (/ u%NacelleLoads%Force(1,1), u%NacelleLoads%Force(3,1), -u%NacelleLoads%Force(2,1) /) + + RtHSdat%MomBNcRtt = RtHSdat%MomNGnRtt + RtHSdat%MomNTailt + TmpVec2 + TmpVec3 + TmpVec4 & + + CROSS_PRODUCT( -RtHSdat%AngVelEN, TmpVec ) & ! = ( -angular velocity of nacelle in the inertia frame ) cross ( TmpVec ) & + - p%Nacd2Iner*CoordSys%d2*DOT_PRODUCT( CoordSys%d2, RtHSdat%AngAccENt ) & + + (/ u%NacelleLoads%Moment(1,1), u%NacelleLoads%Moment(3,1), -u%NacelleLoads%Moment(2,1) /) + +!..................................... +! PFTHydro and PMFHydro +! (requires TwrAddedMass) +!..................................... + + ! Compute the partial hydrodynamic forces and moments per unit length + ! (including those associated with the QD2T()'s and those that are not) at the current tower element (point T) / (body F): + + ! NOTE: These forces are named PFTHydro, PMFHydro, FTHydrot, and MFHydrot. However, the names should not imply that the + ! forces are a result of hydrodynamic contributions only. These tower forces contain contributions from any external + ! load acting on the tower other than loads transmitted from aerodynamics. For example, these tower forces contain + ! contributions from foundation stiffness and damping [not floating] or mooring line restoring and damping, + ! as well as hydrostatic and hydrodynamic contributions [offshore]. + + DO J=1,p%TwrNodes + + RtHSdat%PFTHydro(:,J,:) = 0.0 + RtHSdat%PMFHydro(:,J,:) = 0.0 + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower + + RtHSdat%PFTHydro(:,J,p%DOFs%PTE(I)) = & + CoordSys%z1*( - u%TwrAddedMass(DOF_Sg,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Sg,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Sg,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_Sg,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Sg,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Sg,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) & + - CoordSys%z3*( - u%TwrAddedMass(DOF_Sw,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Sw,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Sw,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_Sw,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Sw,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Sw,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) & + + CoordSys%z2*( - u%TwrAddedMass(DOF_Hv,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Hv,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Hv,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_Hv,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Hv,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Hv,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) + RtHSdat%PMFHydro(:,J,p%DOFs%PTE(I)) = & + CoordSys%z1*( - u%TwrAddedMass(DOF_R ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_R ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_R ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_R ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_R ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_R ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) & + - CoordSys%z3*( - u%TwrAddedMass(DOF_P ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_P ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_P ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_P ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_P ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_P ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) & + + CoordSys%z2*( - u%TwrAddedMass(DOF_Y ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Y ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Y ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) & + - u%TwrAddedMass(DOF_Y ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) & + + u%TwrAddedMass(DOF_Y ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) & + - u%TwrAddedMass(DOF_Y ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) + + END DO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower + END DO !J + +!..................................... +! FTHydrot and MFHydrot +! (requires TwrAddedMass) +!..................................... + + DO J=1,p%TwrNodes + RtHSdat%FTHydrot(:,J) = CoordSys%z1*( u%TowerPtLoads%Force(DOF_Sg,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_Sg,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_Sg,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_Sg,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_Sg,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_Sg,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_Sg,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) & + - CoordSys%z3*( u%TowerPtLoads%Force(DOF_Sw,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_Sw,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_Sw,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_Sw,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_Sw,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_Sw,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_Sw,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) & + + CoordSys%z2*( u%TowerPtLoads%Force(DOF_Hv,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_Hv,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_Hv,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_Hv,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_Hv,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_Hv,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_Hv,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) + RtHSdat%MFHydrot(:,J) = CoordSys%z1*( u%TowerPtLoads%Moment(DOF_R-3,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_R ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_R ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_R ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_R ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_R ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_R ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) & + - CoordSys%z3*( u%TowerPtLoads%Moment(DOF_P-3 ,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_P ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_P ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_P ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_P ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_P ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_P ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) & + + CoordSys%z2*( u%TowerPtLoads%Moment(DOF_Y-3 ,J)/p%DHNodes(J) & + - u%TwrAddedMass(DOF_Y ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) & + + u%TwrAddedMass(DOF_Y ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) & + - u%TwrAddedMass(DOF_Y ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) & + - u%TwrAddedMass(DOF_Y ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) & + + u%TwrAddedMass(DOF_Y ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) & + - u%TwrAddedMass(DOF_Y ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) + + END DO !J + +!..................................... +! PFrcT0Trb and PMomX0Trb +! (requires PFrcONcRt, PMomBNcRt, PFrcT0Trb, PMomX0Trb, PFTHydro, PMFHydro) +!..................................... + + ! Initialize the partial forces and moments (including those associated + ! with the QD2T()'s and those that are not) at the tower base (point T(0)) using everything but the tower: + + RtHSdat%PFrcT0Trb = RtHSdat%PFrcONcRt ! Initialize these partial forces and moments + RtHSdat%PMomX0Trb = RtHSdat%PMomBNcRt ! using all of the effects above the yaw bearing + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + TmpVec = CROSS_PRODUCT( RtHSdat%rT0O, RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomX0Trb associated with the PFrcONcRt + + RtHSdat%PMomX0Trb(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomX0Trb(:,p%DOFs%SrtPS(I)) + TmpVec + + ENDDO ! I - All active (enabled) DOFs + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + + TmpVec1 = -p%YawBrMass*RtHSdat%PLinVelEO(p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with the YawBrMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of PMomX0Trb associated with the YawBrMass + + RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) + TmpVec1 + RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) + TmpVec2 + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O) + + TmpVec1 = -p%YawBrMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEOt ) ! The portion of FrcT0Trbt associated with the YawBrMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of MomX0Trbt associated with the YawBrMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rT0O, RtHSdat%FrcONcRtt ) ! The portion of MomX0Trbt associated with the FrcONcRtt + + RtHSdat%FrcT0Trbt = RtHSdat%FrcONcRtt + TmpVec1 + RtHSdat%MomX0Trbt = RtHSdat%MomBNcRtt + TmpVec2 + TmpVec3 + + ! Integrate to find the total partial forces and moments (including those + ! associated with the QD2T()'s and those that are not) at the tower base (point T(0)): + DO J=1,p%TwrNodes + + DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower + + TmpVec1 = RtHSdat%PFTHydro(:,J,p%DOFs%PTE(I))*p%DHNodes(J) - p%TElmntMass(J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with tower element J + TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of PMomX0Trb associated with tower element J + TmpVec3 = RtHSdat%PMFHydro(:,J,p%DOFs%PTE(I))*p%DHNodes(J) ! The added moment applied at tower element J + + RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) + TmpVec1 + RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) + TmpVec2 + TmpVec3 + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower + + TmpVec1 = ( RtHSdat%FTHydrot(:,J) )*p%DHNodes(J) & + - p%TElmntMass(J)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccETt(:,J) ) ! The portion of FrcT0Trbt associated with tower element J + TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of MomX0Trbt associated with tower element J + TmpVec3 = ( RtHSdat%MFHydrot(:,J) )*p%DHNodes(J) ! The external moment applied to tower element J + + RtHSdat%FrcT0Trbt = RtHSdat%FrcT0Trbt + TmpVec1 + + RtHSdat%MomX0Trbt = RtHSdat%MomX0Trbt + TmpVec2 + TmpVec3 + + END DO !J + +!..................................... +! PFZHydro and PMXHydro +! ( requires PtfmAddedMass ) +!..................................... + + !.................................................................................................................................. + ! Compute the partial platform forces and moments (including those associated with the QD2T()'s and those that are not) at the + ! platform reference (point Z) / (body X). + ! + ! NOTE: These forces are named PFZHydro, PMXHydro, FZHydrot, and MXHydrot. However, the names should not imply that the forces + ! are a result of hydrodynamic contributions only. These platform forces contain contributions from any external load acting + ! on the platform other than loads transmitted from the wind turbine. For example, these platform forces contain contributions + ! from foundation stiffness and damping [not floating] or mooring line restoring and damping [floating], as well as hydrostatic + ! and hydrodynamic contributions [offshore]. + !bjj: m%RtHS%PFZHydro, %PMXHydro, %FZHydrot, and %MXHydrot are not used in the output routine anymore + ! (because of their dependence on inputs, u) + + RtHSdat%PFZHydro = 0.0 + RtHSdat%PMXHydro = 0.0 + DO I = 1,p%DOFs%NPYE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + + RtHSdat%PFZHydro(p%DOFs%PYE(I),:) = - u%PtfmAddedMass(DOF_Sg,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Sg,0,:) & + - u%PtfmAddedMass(DOF_Sw,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Sw,0,:) & + - u%PtfmAddedMass(DOF_Hv,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Hv,0,:) + RtHSdat%PMXHydro(p%DOFs%PYE(I),:) = - u%PtfmAddedMass(DOF_R ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_R ,0,:) & + - u%PtfmAddedMass(DOF_P ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_P ,0,:) & + - u%PtfmAddedMass(DOF_Y ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_Y ,0,:) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + + RtHSdat%FZHydrot = u%PlatformPtMesh%Force(DOF_Sg,1)*RtHSdat%PLinVelEZ(DOF_Sg,0,:) & + + u%PlatformPtMesh%Force(DOF_Sw,1)*RtHSdat%PLinVelEZ(DOF_Sw,0,:) & + + u%PlatformPtMesh%Force(DOF_Hv,1)*RtHSdat%PLinVelEZ(DOF_Hv,0,:) + RtHSdat%MXHydrot = u%PlatformPtMesh%Moment(DOF_R-3,1)*RtHSdat%PAngVelEX(DOF_R ,0,:) & + + u%PlatformPtMesh%Moment(DOF_P-3,1)*RtHSdat%PAngVelEX(DOF_P ,0,:) & + + u%PlatformPtMesh%Moment(DOF_Y-3,1)*RtHSdat%PAngVelEX(DOF_Y ,0,:) + +!..................................... +! PFrcZAll and PMomXAll +! (requires PFrcT0Trb, PMomX0Trb, PFZHydro, PMXHydro ) +!..................................... + + ! Define the partial forces and moments (including those associated with the QD2T()'s and those that are not) at the + ! platform reference (point Z) / (body X) using the turbine and platform effects: + + RtHSdat%PFrcZAll = RtHSdat%PFrcT0Trb ! Initialize these partial forces and moments + RtHSdat%PMomXAll = RtHSdat%PMomX0Trb ! using the effects from the wind turbine + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + TmpVec = CROSS_PRODUCT( RtHSdat%rZT0, RtHSdat%PFrcT0Trb(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomXAll associated with the PFrcT0Trb + + RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) + TmpVec + + ENDDO ! I - All active (enabled) DOFs + DO I = 1,p%DOFs%NPYE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + + TmpVec1 = -p%PtfmMass*RtHSdat%PLinVelEY(p%DOFs%PYE(I),0,:) ! The portion of PFrcZAll associated with the PtfmMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 ) ! The portion of PMomXAll associated with the PtfmMass + + RtHSdat%PFrcZAll(:,p%DOFs%PYE(I)) = RtHSdat%PFrcZAll(:,p%DOFs%PYE(I) ) + RtHSdat%PFZHydro(p%DOFs%PYE(I),:) + TmpVec1 + RtHSdat%PMomXAll(:,p%DOFs%PYE(I)) = RtHSdat%PMomXAll(:,p%DOFs%PYE(I) ) + RtHSdat%PMXHydro(p%DOFs%PYE(I),:) + TmpVec2 & + - p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) & + - p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) & + - p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) + + ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) + +!..................................... +! FrcZAllt and MomXAllt +! (requires FrcT0Trbt, MomX0Trbt) +!..................................... + + TmpVec1 = -p%PtfmMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEYt ) ! The portion of FrcZAllt associated with the PtfmMass + TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 ) ! The portion of MomXAllt associated with the PtfmMass + TmpVec3 = CROSS_PRODUCT( RtHSdat%rZT0 , RtHSdat%FrcT0Trbt ) ! The portion of MomXAllt associated with the FrcT0Trbt + TmpVec = p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%AngVelEX ) & ! = ( Platform inertia dyadic ) dot ( angular velocity of platform in the inertia frame ) + + p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%AngVelEX ) & + + p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%AngVelEX ) + TmpVec4 = CROSS_PRODUCT( -RtHSdat%AngVelEX, TmpVec ) ! = ( -angular velocity of platform in the inertia frame ) cross ( TmpVec ) + + RtHSdat%FrcZAllt = RtHSdat%FrcT0Trbt + RtHSdat%FZHydrot + TmpVec1 + RtHSdat%MomXAllt = RtHSdat%MomX0Trbt + RtHSdat%MXHydrot + TmpVec2 + TmpVec3 + TmpVec4 + + +END SUBROUTINE CalculateForcesMoments +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to populate the AugMat matrix for RtHS (CalcContStateDeriv) +SUBROUTINE FillAugMat( p, x, CoordSys, u, HSSBrTrq, RtHSdat, AugMat ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time + TYPE(ED_InputType), INTENT(IN ) :: u !< The aero blade forces/moments + TYPE(ED_RtHndSide), INTENT(IN ) :: RtHSdat !< data from the RtHndSid module (contains positions to be set) + REAL(ReKi), INTENT(IN ) :: HSSBrTrq !< SIGN( u%HSSBrTrqC, x%QDT(DOF_GeAz) ) or corrected value from FixHSS + REAL(R8Ki), INTENT(OUT) :: AugMat(:,:) !< the return matrix + + ! Local variables + REAL(ReKi) :: TmpVec (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec1 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: TmpVec3 (3) ! A temporary vector used in various computations. + REAL(ReKi) :: GBoxTrq ! Gearbox torque on the LSS side in N-m (calculated from inputs and parameters). + REAL(ReKi) :: GBoxEffFac2 ! A second gearbox efficiency factor = ( 1 / GBoxEff^SgnPrvLSTQ - 1 ) + + INTEGER(IntKi) :: I ! Loops through some or all of the DOFs + INTEGER(IntKi) :: J ! Counter for elements + INTEGER(IntKi) :: K ! Counter for blades + INTEGER(IntKi) :: L ! Generic index + + + ! Initialize the matrix: + + AugMat = 0.0 + GBoxTrq = ( u%GenTrq + HSSBrTrq )*ABS(p%GBRatio) ! bjj: do we use HSSBrTrqC or HSSBrTrq? + + DO K = 1,p%NumBl ! Loop through all blades + + + ! Initialize the portions of the mass matrix on and below the diagonal associated with purely blade DOFs (these portions can't + ! be calculated using partial loads) using the tip mass effects. + ! Also, initialize the portions of the forcing vector associated with purely blade DOFs (these portions can't be calculated + ! using partial loads) using the tip mass effects: + ! NOTE: The vector subscript array, PSBE(), used in the following loops must be sorted from smallest to largest DOF index in + ! order for the loops to work to enter values only on and below the diagonal of AugMat(): + + + DO L = 1,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the tip of blade K (point S(p%BldFlexL)) + DO I = L,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs greater than or equal to L + AugMat(p%DOFs%PSBE(K,I),p%DOFs%PSBE(K,L)) = p%TipMass(K)*& + DOT_PRODUCT( RtHSdat%PLinVelES(K, p%TipNode, p%DOFs%PSBE(K,I),0,:), & ! [C(q,t)]B + RtHSdat%PLinVelES(K, p%TipNode, p%DOFs%PSBE(K,L),0,:) ) + ENDDO ! I - All active (enabled) blade DOFs greater than or equal to L + ENDDO ! L - All active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the tip of blade K (point S(p%BldFlexL)) + + TmpVec1 = RtHSdat%FSTipDrag(:,K) - p%TipMass(K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,p%TipNode) ) ! The portion of FrcS0Bt associated with the tip brake + DO I = 1,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the tip of blade K (point S(p%BldFlexL)) + AugMat(p%DOFs%PSBE(K,I), p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelES(K,p%TipNode,p%DOFs%PSBE(K,I),0,:), & ! {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + TmpVec1 ) ! NOTE: TmpVec1 is still the portion of FrcS0Bt associated with the tip brake + ENDDO ! I - All active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the tip of blade K (point S(p%BldFlexL)) + + + + DO J = 1,p%BldNodes ! Loop through the blade nodes / elements + + + ! Integrate to find the portions of the mass matrix on and below the diagonal associated with purely blade DOFs (these portions + ! can't be calculated using partial loads). Also, integrate to find the portions of the forcing vector associated with + ! purely blade DOFs (these portions can't be calculated using partial loads): + ! NOTE: The vector subscript array, PSBE(), used in the following loops must + ! be sorted from smallest to largest DOF index in order for the loops + ! to work to enter values only on and below the diagonal of AugMat(): + + DO L = 1,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + DO I = L,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs greater than or equal to L + AugMat(p%DOFs%PSBE(K,I),p%DOFs%PSBE(K,L)) = AugMat(p%DOFs%PSBE(K,I),p%DOFs%PSBE(K,L)) + p%BElmntMass(J,K)*& + DOT_PRODUCT( RtHSdat%PLinVelES(K,J,p%DOFs%PSBE(K,I),0,:), & ! [C(q,t)]B + RtHSdat%PLinVelES(K,J,p%DOFs%PSBE(K,L),0,:) ) + ENDDO ! I - All active (enabled) blade DOFs greater than or equal to L + ENDDO ! L - All active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + + TmpVec1 = RtHSdat%FSAero(:,K,J)*p%DRNodes(J) - p%BElmntMass(J,K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,J) ) ! The portion of FrcS0Bt associated with blade element J + TmpVec3 = RtHSdat%MMAero(:,K,J)*p%DRNodes(J) ! The total external moment applied to blade element J + DO I = 1,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + AugMat(p%DOFs%PSBE(K,I), p%NAug) = AugMat(p%DOFs%PSBE(K,I), p%NAug) & ! {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + + DOT_PRODUCT( RtHSdat%PLinVelES(K,J,p%DOFs%PSBE(K,I),0,:), TmpVec1 ) & ! NOTE: TmpVec1 is still the portion of FrcS0Bt associated with blade element J + + DOT_PRODUCT( RtHSdat%PAngVelEM(K,J,p%DOFs%PSBE(K,I),0,:), TmpVec3 ) ! and TmpVec3 is still the total external moment applied to blade element J + ENDDO ! I - All active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + + + ENDDO ! J - Blade nodes / elements + + + + + ! Initialize the portions of the mass matrix below the diagonal associated + ! with the teeter and pure blade DOFs using the partial loads at the teeter pin; only do this if necessary: + + IF ( ( p%NumBl == 2 ) .AND. ( p%DOF_Flag(DOF_Teet) ) ) THEN + DO L = 1,p%DOFs%NPSBE(K) ! Loop through all active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + AugMat(DOF_Teet,p%DOFs%PSBE(K,L)) = -DOT_PRODUCT( RtHSdat%PAngVelEH(DOF_Teet,0,:), & + RtHSdat%PMomLPRot(:,p%DOFs%PSBE(K,L)) ) ! [C(q,t)]B + ENDDO ! L - All active (enabled) blade DOFs that contribute to the QD2T-related linear accelerations of the blade + ENDIF + + + + ! If the associated DOFs are enabled, add the blade elasticity and damping + ! forces to the forcing vector (these portions can't be calculated using + ! partial loads): + + IF ( p%DOF_Flag(DOF_BF(K,1)) ) THEN + AugMat( DOF_BF(K,1),p%NAug) = AugMat(DOF_BF(K,1),p%NAug) & ! + - p%KBF(K,1,1)*x%QT( DOF_BF(K,1)) & + - p%KBF(K,1,2)*x%QT( DOF_BF(K,2)) & + - p%CBF(K,1,1)*x%QDT(DOF_BF(K,1)) & + - p%CBF(K,1,2)*x%QDT(DOF_BF(K,2)) + ENDIF + IF ( p%DOF_Flag(DOF_BF(K,2)) ) THEN + AugMat( DOF_BF(K,2),p%NAug) = AugMat(DOF_BF(K,2),p%NAug) & ! {-f(qd,q,t)}ElasticB + {-f(qd,q,t)}DampB + - p%KBF(K,2,1)*x%QT( DOF_BF(K,1)) & + - p%KBF(K,2,2)*x%QT( DOF_BF(K,2)) & + - p%CBF(K,2,1)*x%QDT(DOF_BF(K,1)) & + - p%CBF(K,2,2)*x%QDT(DOF_BF(K,2)) + ENDIF + IF ( p%DOF_Flag(DOF_BE(K,1)) ) THEN + AugMat( DOF_BE(K,1),p%NAug) = AugMat(DOF_BE(K,1),p%NAug) & ! + - p%KBE(K,1,1)*x%QT( DOF_BE(K,1)) & + - p%CBE(K,1,1)*x%QDT(DOF_BE(K,1)) + ENDIF + + + END DO !k + + + ! Initialize the portions of the mass matrix on and below the diagonal + ! associated with purely tower DOFs (these portions can't be calculated + ! using partial loads) using the yaw bearing mass effects. + ! Also, initialize the portions of the forcing vector associated with + ! purely blade DOFs (these portions can't be calculated using partial + ! loads) using the yaw bearing mass effects: + ! NOTE: The vector subscript array, PTTE(), used in the following loops must + ! be sorted from smallest to largest DOF index in order for the loops + ! to work to enter values only on and below the diagonal of AugMat(): + + DO L = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O) + DO I = L,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs greater than or equal to L + AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) = p%YawBrMass*DOT_PRODUCT( RtHSdat%PLinVelEO(p%DOFs%PTTE(I),0,:), & ! [C(q,t)]T of YawBrMass + RtHSdat%PLinVelEO(p%DOFs%PTTE(L),0,:) ) + ENDDO ! I - All active (enabled) tower DOFs greater than or equal to L + ENDDO ! L - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O) + + TmpVec1 = -p%YawBrMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEOt ) ! The portion of FrcT0Trbt associated with the YawBrMass + DO I = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O) + AugMat(p%DOFs%PTTE(I), p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelEO(p%DOFs%PTTE(I),0,:), & ! {-f(qd,q,t)}T + {-f(qd,q,t)}GravT of YawBrMass + TmpVec1 ) ! NOTE: TmpVec1 is still the portion of FrcT0Trbt associated with YawBrMass + ENDDO ! I - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O) + + + + + + DO J = 1,p%TwrNodes + + !.................................................................................................................................. + ! Integrate to find the portions of the mass matrix on and below the diagonal associated with purely tower DOFs (these portions + ! can't be calculated using partial loads). Also, integrate to find the portions of the forcing vector associated with purely + ! tower DOFs (these portions can't be calculated using partial loads). + ! NOTE: The vector subscript array, PTTE(), used in the following loops must be sorted from smallest to largest DOF index in order + ! for the loops to work to enter values only on and below the diagonal of AugMat(): + !.................................................................................................................................. + + DO L = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the tower + DO I = L,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs greater than or equal to L + AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) = AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) & + + p%TElmntMass(J) *DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), & + RtHSdat%PLinVelET(J,p%DOFs%PTTE(L),0,:) ) & ! [C(q,t)]T + [C(q,t)]HydroT + - p%DHNodes(J)*DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), & + RtHSdat%PFTHydro (:,J,p%DOFs%PTTE(L) ) ) & + - p%DHNodes(J)*DOT_PRODUCT( RtHSdat%PAngVelEF(J,p%DOFs%PTTE(I),0,:), & + RtHSdat%PMFHydro (:,J,p%DOFs%PTTE(L) ) ) + ENDDO ! I - All active (enabled) tower DOFs greater than or equal to L + ENDDO ! L - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the tower + + TmpVec1 = ( RtHSdat%FTHydrot(:,J) )*p%DHNodes(J) & + - p%TElmntMass(J)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccETt(:,J) ) ! The portion of FrcT0Trbt associated with tower element J + TmpVec3 = ( RtHSdat%MFHydrot(:,J) )*p%DHNodes(J) ! The external moment applied to tower element J + DO I = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the tower + AugMat(p%DOFs%PTTE(I), p%NAug) = AugMat(p%DOFs%PTTE(I), p%NAug) & ! {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + + DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), TmpVec1 ) & ! NOTE: TmpVec1 is still the portion of FrcT0Trbt associated with tower element J + + DOT_PRODUCT( RtHSdat%PAngVelEF(J,p%DOFs%PTTE(I),0,:), TmpVec3 ) ! and TmpVec3 is still the total external moment to tower element J + ENDDO ! I - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the tower + + ENDDO ! J - Tower nodes / elements + + !.................................................................................................................................. + ! If the associated DOFs are enabled, add the tower elasticity and damping forces to the forcing vector (these portions can't be + ! calculated using partial loads): + !.................................................................................................................................. + + IF ( p%DOF_Flag(DOF_TFA1) ) THEN + AugMat( DOF_TFA1,p%NAug) = AugMat(DOF_TFA1,p%NAug) & + - p%KTFA(1,1)*x%QT( DOF_TFA1) - p%KTFA(1,2)*x%QT( DOF_TFA2) & ! + - p%CTFA(1,1)*x%QDT(DOF_TFA1) - p%CTFA(1,2)*x%QDT(DOF_TFA2) + ENDIF + IF ( p%DOF_Flag(DOF_TSS1) ) THEN + AugMat( DOF_TSS1,p%NAug) = AugMat(DOF_TSS1,p%NAug) & + - p%KTSS(1,1)*x%QT( DOF_TSS1) - p%KTSS(1,2)*x%QT( DOF_TSS2) & ! {-f(qd,q,t)}ElasticT + {-f(qd,q,t)}DampT + - p%CTSS(1,1)*x%QDT(DOF_TSS1) - p%CTSS(1,2)*x%QDT(DOF_TSS2) + ENDIF + IF ( p%DOF_Flag(DOF_TFA2) ) THEN + AugMat( DOF_TFA2,p%NAug) = AugMat(DOF_TFA2,p%NAug) & + - p%KTFA(2,1)*x%QT( DOF_TFA1) - p%KTFA(2,2)*x%QT( DOF_TFA2) & ! + - p%CTFA(2,1)*x%QDT(DOF_TFA1) - p%CTFA(2,2)*x%QDT(DOF_TFA2) + ENDIF + IF ( p%DOF_Flag(DOF_TSS2) ) THEN + AugMat( DOF_TSS2,p%NAug) = AugMat(DOF_TSS2,p%NAug) & + - p%KTSS(2,1)*x%QT( DOF_TSS1) - p%KTSS(2,2)*x%QT( DOF_TSS2) & ! + - p%CTSS(2,1)*x%QDT(DOF_TSS1) - p%CTSS(2,2)*x%QDT(DOF_TSS2) + ENDIF + + + +!.................................................................................................................................. +! Now that all of the partial loads have been found, let's fill in the portions of the mass matrix on and below the diagonal that +! may be calculated with the help of the partial loads. +! Also, let's fill in the portions of the forcing vector that may be calculated with the help of the partial loads. +! Also let's add in additional terms to the forcing function that can't be added with the help of the partial loads. +! +! NOTE: The vector subscript array, SrtPS(), used in the following loops must be sorted from smallest to largest DOF index in order +! for the loops to work to enter values only on and below the diagonal of AugMat(): +!.................................................................................................................................. + + IF ( p%DOF_Flag (DOF_Sg ) ) THEN + DO I = p%DOFs%Diag(DOF_Sg ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_Sg ) = -1.*DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Sg ,0,:), RtHSdat%PFrcZAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_Sg , p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Sg ,0,:), RtHSdat%FrcZAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}R + {-f(qd,q,t)}H + {-f(qd,q,t)}B + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}AeroA + ENDIF + + IF ( p%DOF_Flag (DOF_Sw ) ) THEN + DO I = p%DOFs%Diag(DOF_Sw ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_Sw ) = -1.*DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Sw ,0,:), RtHSdat%PFrcZAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_Sw , p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Sw ,0,:), RtHSdat%FrcZAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}R + {-f(qd,q,t)}H + {-f(qd,q,t)}B + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}AeroA + ENDIF + + IF ( p%DOF_Flag (DOF_Hv ) ) THEN + DO I = p%DOFs%Diag(DOF_Hv ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_Hv ) = -1.*DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Hv ,0,:), RtHSdat%PFrcZAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_Hv , p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelEZ(DOF_Hv ,0,:), RtHSdat%FrcZAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}GravX + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + ENDIF + + IF ( p%DOF_Flag (DOF_R ) ) THEN + DO I = p%DOFs%Diag(DOF_R ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + + AugMat(p%DOFs%SrtPS(I),DOF_R ) = -1.*DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_R ,0,:), RtHSdat%PMomXAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_R , p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_R ,0,:), RtHSdat%MomXAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}GravX + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + ENDIF + + IF ( p%DOF_Flag (DOF_P ) ) THEN + DO I = p%DOFs%Diag(DOF_P ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_P ) = -1.*DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_P ,0,:), RtHSdat%PMomXAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_P ,p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_P ,0,:), RtHSdat%MomXAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}GravX + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + END IF + + IF ( p%DOF_Flag (DOF_Y ) ) THEN + DO I = p%DOFs%Diag(DOF_Y ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_Y ) = -1.*DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_Y ,0,:), RtHSdat%PMomXAll (:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]X + [C(q,t)]HydroX + [C(q,t)]T + [C(q,t)]HydroT + [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_Y , p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEX(DOF_Y ,0,:), RtHSdat%MomXAllt ) ! {-f(qd,q,t)}X + {-f(qd,q,t)}GravX + {-f(qd,q,t)}HydroX + {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT + {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + ENDIF + + IF ( p%DOF_Flag (DOF_TFA1) ) THEN + DO I = p%DOFs%Diag(DOF_TFA1),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_TFA1) = AugMat(p%DOFs%SrtPS(I),DOF_TFA1) & + - DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TFA1,0,:), & + RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) & ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + - DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TFA1,0,:), & + RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_TFA1, p%NAug) = AugMat(DOF_TFA1, p%NAug) & + + DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TFA1,0,:), RtHSdat%FrcONcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TFA1,0,:), RtHSdat%MomBNcRtt ) + ENDIF + + IF ( p%DOF_Flag (DOF_TSS1) ) THEN + DO I = p%DOFs%Diag(DOF_TSS1),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_TSS1) = AugMat(p%DOFs%SrtPS(I),DOF_TSS1) & + - DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TSS1,0,:), & + RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) & ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + - DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TSS1,0,:), & + RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_TSS1, p%NAug) = AugMat(DOF_TSS1, p%NAug) & + + DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TSS1,0,:), RtHSdat%FrcONcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TSS1,0,:), RtHSdat%MomBNcRtt ) + ENDIF + + IF ( p%DOF_Flag (DOF_TFA2) ) THEN + DO I = p%DOFs%Diag(DOF_TFA2),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_TFA2) = AugMat(p%DOFs%SrtPS(I),DOF_TFA2) & + - DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TFA2,0,:), & + RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) & ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + - DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TFA2,0,:), & + RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_TFA2, p%NAug) = AugMat(DOF_TFA2, p%NAug) & + + DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TFA2,0,:), RtHSdat%FrcONcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TFA2,0,:), RtHSdat%MomBNcRtt ) + ENDIF + + IF ( p%DOF_Flag (DOF_TSS2) ) THEN + DO I = p%DOFs%Diag(DOF_TSS2),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_TSS2) = AugMat(p%DOFs%SrtPS(I),DOF_TSS2) & + - DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TSS2,0,:), & + RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) & ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + - DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TSS2,0,:), & + RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_TSS2, p%NAug) = AugMat(DOF_TSS2, p%NAug) & + + DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TSS2,0,:), RtHSdat%FrcONcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TSS2,0,:), RtHSdat%MomBNcRtt ) + ENDIF + + IF ( p%DOF_Flag (DOF_Yaw ) ) THEN + DO I = p%DOFs%Diag(DOF_Yaw ),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_Yaw ) = -DOT_PRODUCT( RtHSdat%PAngVelEN(DOF_Yaw ,0,:), RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_Yaw , p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEN(DOF_Yaw ,0,:), RtHSdat%MomBNcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + u%YawMom ! + {-f(qd,q,t)}SpringYaw + {-f(qd,q,t)}DampYaw; NOTE: The neutral yaw rate, YawRateNeut, defaults to zero. It is only used for yaw control. + ENDIF + + + IF ( p%DOF_Flag (DOF_RFrl) ) THEN + DO I = p%DOFs%Diag(DOF_RFrl),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_RFrl) = -DOT_PRODUCT( RtHSdat%PAngVelER(DOF_RFrl,0,:), & + RtHSdat%PMomNGnRt(:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_RFrl, p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelER(DOF_RFrl,0,:), RtHSdat%MomNGnRtt ) & ! {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + + RtHSdat%RFrlMom ! + {-f(qd,q,t)}SpringRF + {-f(qd,q,t)}DampRF + ENDIF + + TmpVec = p%GenIner*CoordSys%c1*DOT_PRODUCT( CoordSys%c1, RtHSdat%PAngVelEG(DOF_GeAz,0,:) ) ! = ( generator inertia dyadic ) Dot ( partial angular velocity of G in E for DOF_GeAz ) + + IF ( p%DOF_Flag (DOF_GeAz) ) THEN + DO I = p%DOFs%Diag(DOF_GeAz),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_GeAz) = -DOT_PRODUCT( RtHSdat%PAngVelEL(DOF_GeAz,0,:), RtHSdat%PMomLPRot(:,p%DOFs%SrtPS(I)) )! [C(q,t)]H + [C(q,t)]B + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_GeAz, p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEL(DOF_GeAz,0,:), RtHSdat%MomLPRott ) & ! {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + - GBoxTrq ! + {-f(qd,q,t)}Gen + {-f(qd,q,t)}Brake + + + ! The previous loop (DO I = p%DOFs%Diag(DOF_GeAz),p%DOFs%NActvDOF) misses the + ! generator inertia-contribution to the mass matrix and forcing function. + ! Thus, add these in as well: + + + AugMat(DOF_GeAz, DOF_GeAz) = AugMat(DOF_GeAz,DOF_GeAz) & + + DOT_PRODUCT( RtHSdat%PAngVelEG(DOF_GeAz,0,:), TmpVec ) ! [C(q,t)]G + AugMat(DOF_GeAz, p%NAug) = AugMat(DOF_GeAz, p%NAug) & + - DOT_PRODUCT( RtHSdat%AngAccEGt , TmpVec ) ! {-f(qd,q,t)}G + + + ENDIF + + IF ( p%DOF_Flag (DOF_DrTr) ) THEN + DO I = p%DOFs%Diag(DOF_DrTr),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal + AugMat(p%DOFs%SrtPS(I),DOF_DrTr) = -DOT_PRODUCT( RtHSdat%PAngVelEL(DOF_DrTr,0,:), RtHSdat%PMomLPRot(:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]H + [C(q,t)]B + ENDDO ! I - All active (enabled) DOFs on or below the diagonal + AugMat(DOF_DrTr, p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEL(DOF_DrTr,0,:), RtHSdat%MomLPRott ) & ! {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + - p%DTTorSpr*x%QT (DOF_DrTr) & ! + {-f(qd,q,t)}ElasticDrive + - p%DTTorDmp*x%QDT(DOF_DrTr) ! + {-f(qd,q,t)}DampDrive + ENDIF + + IF ( p%DOF_Flag (DOF_TFrl) ) THEN + ! The tail-furl DOF does not affect any DOF index larger than DOF_TFrl. Therefore, there is no need to perform the loop: DO I = Diag(DOF_TFrl),NActvDOF + AugMat(DOF_TFrl, DOF_TFrl) = -DOT_PRODUCT( RtHSdat%PAngVelEA(DOF_TFrl,0,:), RtHSdat%PMomNTail(:,DOF_TFrl) ) ! [C(q,t)]A + AugMat(DOF_TFrl, p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEA(DOF_TFrl,0,:), RtHSdat%MomNTailt ) & ! {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA + + RtHSdat%TFrlMom ! + {-f(qd,q,t)}SpringTF + {-f(qd,q,t)}DampTF + ENDIF + + IF ( ( p%NumBl == 2 ) .AND. ( p%DOF_Flag(DOF_Teet) ) ) THEN + ! The teeter DOF does not affect any DOF index larger than DOF_Teet. Therefore, there is no need to perform the loop: DO I = Diag(DOF_Teet),NActvDOF + AugMat(DOF_Teet, DOF_Teet) = -DOT_PRODUCT( RtHSdat%PAngVelEH(DOF_Teet,0,:), RtHSdat%PMomLPRot(:,DOF_Teet) ) ! [C(q,t)]H + [C(q,t)]B + AugMat(DOF_Teet, p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEH(DOF_Teet,0,:), RtHSdat%MomLPRott ) & ! {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + + RtHSdat%TeetMom ! + {-f(qd,q,t)}SpringTeet + {-f(qd,q,t)}DampTeet + ENDIF + !.................................................................................................................................. + ! So far, we have only filled in the portions of the mass matrix on and below the diagonal. Because the mass matrix is symmetric + ! up to this point, let's fill in the portion above the diagonal by mirroring the values from below: + ! NOTE: The vector subscript array, SrtPS(), used in the following loops must be sorted from smallest to largest DOF index in order + ! for the loops to work to enter values only on and below the diagonal of AugMat(): + !.................................................................................................................................. + + DO L = 2,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs above the diagonal (columns) + DO I = 1,L-1 ! Loop through all active (enabled) DOFs above the diagonal (rows) + AugMat(p%DOFs%SrtPS(I),p%DOFs%SrtPS(L)) = AugMat(p%DOFs%SrtPS(L),p%DOFs%SrtPS(I)) + ENDDO ! I - All active (enabled) DOFs above the diagonal (rows) + ENDDO ! L - All active (enabled) DOFs above the diagonal (columns) + + ! Let's add the gearbox friction terms to the mass matrix and forcing + ! function. These only effect the equation for the generator azimuth DOF. + ! NOTE: the MASS MATRIX WILL NO LONGER BE SYMMETRIC after adding these + ! terms, unless the gearbox efficiency, GBoxEff, was set to 100%: + + + GBoxEffFac2 = ( 1.0/RtHSdat%GBoxEffFac - 1.0 ) ! = ( 1 / GBoxEff^SgnPrvLSTQ - 1 ) + !TmpVec = p%GenIner*CoordSys%c1*DOT_PRODUCT( CoordSys%c1, RtHSdat%PAngVelEG(DOF_GeAz,0,:) ) ! = ( generator inertia dyadic ) Dot ( partial angular velocity of G in E for DOF_GeAz ) + + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + AugMat(DOF_GeAz,p%DOFs%SrtPS(I)) = AugMat(DOF_GeAz,p%DOFs%SrtPS(I)) & ! NOTE: TmpVec is still = ( generator inertia dyadic ) Dot ( partial angular velocity of G in E for DOF_GeAz ) in the following equation + + GBoxEffFac2* DOT_PRODUCT( RtHSdat%PAngVelEG(p%DOFs%SrtPS(I),0,:), TmpVec ) ! [C(q,t)]GBFric + + ENDDO ! I - All active (enabled) DOFs + + AugMat( DOF_GeAz, p%NAug) = AugMat(DOF_GeAz, p%NAug) & ! NOTE: TmpVec is still = ( generator inertia dyadic ) Dot ( partial angular velocity of G in E for DOF_GeAz ) in the following equation + - GBoxEffFac2*( DOT_PRODUCT( RtHSdat%AngAccEGt , TmpVec ) + GBoxTrq ) ! {-f(qd,q,t)}GBFric + + + + +END SUBROUTINE FillAugMat +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates the arrays and meshes stored in the ED_OutputType data structure (y), based on the parameters (p). +!! Inputs (u) are included only so that output meshes can be siblings of the inputs. +!! The routine assumes that the arrays/meshes are not currently allocated (It will produce a fatal error otherwise.) +!! Also note that this must be called after init_u() so that the misc variables that contain the orientations are set. +SUBROUTINE ED_AllocOutput( p, m, u, y, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_MiscVarType), INTENT(IN ) :: m !< Misc vars (initial positions, set in Init_Inputs()) + TYPE(ED_InputType), INTENT(INOUT) :: u !< Input meshes (sibling) + TYPE(ED_OutputType), INTENT(INOUT) :: y !< Outputs to be allocated + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + REAL(R8Ki) :: Orientation(3,3) + REAL(ReKi) :: Position(3) + INTEGER(IntKi) :: NodeNum ! node number + INTEGER(IntKi) :: J, K ! loop counters + INTEGER(IntKi) :: ErrStat2 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message (ErrMsg) + + + ! initialize variables: + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL AllocAry( y%WriteOutput, p%numOuts + p%BldNd_TotNumOuts, 'WriteOutput', errStat2, errMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( y%BlPitch, p%NumBl, 'BlPitch', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + !....................................................... + ! Create Line2 Mesh for motion outputs on blades: + !....................................................... + IF ( .NOT. p%BD4Blades) THEN + ALLOCATE( y%BladeLn2Mesh(p%NumBl), Stat=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL CheckError( ErrID_Fatal, 'ED: Could not allocate space for y%BladeLn2Mesh{p%NumBl}' ) + RETURN + END IF + + DO K = 1,p%NumBl + + CALL MeshCreate( BlankMesh = y%BladeLn2Mesh(K) & + , NNodes = p%BldNodes+2 & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , TranslationVel = .TRUE. & + , RotationAcc = .TRUE. & + , TranslationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + DO J = 1,p%BldNodes + CALL MeshPositionNode ( y%BladeLn2Mesh(K), J, u%BladePtLoads(K)%Position(:,J), ErrStat2, ErrMsg2, Orient=u%BladePtLoads(K)%RefOrientation(:,:,J) ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + ! now add position/orientation of nodes for AD14 or AD15 + if (p%UseAD14) then ! position/orientation of nodes for AeroDyn v14 or v15 + + ! Use orientation at p%BldNodes for the extra node at the blade tip + CALL MeshPositionNode ( y%BladeLn2Mesh(K), p%BldNodes + 1, (/0.0_ReKi, 0.0_ReKi, p%BldFlexL /), ErrStat2, ErrMsg2, Orient=u%BladePtLoads(K)%RefOrientation(:,:,p%BldNodes) ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Use orientation at node 1 for the blade root + CALL MeshPositionNode ( y%BladeLn2Mesh(K), p%BldNodes + 2, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi /), ErrStat2, ErrMsg2, Orient=u%BladePtLoads(K)%RefOrientation(:,:,1), ref=.true. ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + else + + ! position the nodes on the blade root and blade tip: + DO J = 0,p%TipNode,p%TipNode + if (j==0) then ! blade root + NodeNum = p%BldNodes + 2 + y%BladeLn2Mesh(K)%RefNode = NodeNum + elseif (j==p%TipNode) then ! blade tip + NodeNum = p%BldNodes + 1 + end if + + Orientation(1,1) = m%CoordSys%n1(K,J,1) + Orientation(2,1) = m%CoordSys%n2(K,J,1) + Orientation(3,1) = m%CoordSys%n3(K,J,1) + Orientation(1,2) = -1.*m%CoordSys%n1(K,J,3) + Orientation(2,2) = -1.*m%CoordSys%n2(K,J,3) + Orientation(3,2) = -1.*m%CoordSys%n3(K,J,3) + Orientation(1,3) = m%CoordSys%n1(K,J,2) + Orientation(2,3) = m%CoordSys%n2(K,J,2) + Orientation(3,3) = m%CoordSys%n3(K,J,2) + + ! Translational Displacement + position(1) = m%RtHS%rS (1,K,J) ! = the distance from the undeflected tower centerline to the current blade node in the xi ( z1) direction + position(2) = -1.*m%RtHS%rS (3,K,J) ! = the distance from the undeflected tower centerline to the current blade node in the yi (-z3) direction + position(3) = m%RtHS%rS (2,K,J) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade node in the zi ( z2) direction + + + CALL MeshPositionNode ( y%BladeLn2Mesh(K), NodeNum, position, ErrStat2, ErrMsg2, Orient=Orientation ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + END DO ! nodes + + end if ! position/orientation of nodes for AeroDyn v14 or v15 + + ! create elements: + DO J = 2,p%TipNode !p%BldNodes + 1 + + CALL MeshConstructElement ( Mesh = y%BladeLn2Mesh(K) & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + END DO ! J (blade nodes) + + ! add the other extra element, connecting the first node on the blade: + CALL MeshConstructElement ( Mesh = y%BladeLn2Mesh(K) & + , Xelement = ELEMENT_LINE2 & + , P1 = p%BldNodes + 2 & ! node1 number (extra node at root) + , P2 = 1 & ! node2 number (first node on blade) + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! that's our entire mesh: + CALL MeshCommit ( y%BladeLn2Mesh(K), ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + END DO + + END IF + + !....................................................... + ! Create Point Mesh for Motions Output at Platform Reference Point: + !....................................................... + + CALL MeshCopy ( SrcMesh = u%PlatformPtMesh & + , DestMesh = y%PlatformPtMesh & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , TranslationVel = .TRUE. & + , RotationAcc = .TRUE. & + , TranslationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets y%PlatformPtMesh%RemapFlag = .TRUE. + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !....................................................... + ! Create Line2 Mesh for Motions Output on Tower Line2 Mesh: + ! first p%TwrNodes nodes are the same as the input TowerPtLoads mesh + !....................................................... + + CALL MeshCreate( BlankMesh = y%TowerLn2Mesh & + , IOS = COMPONENT_OUTPUT & + , NNodes = p%TwrNodes + 2 & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , TranslationVel = .TRUE. & + , RotationAcc = .TRUE. & + , TranslationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + ! position the nodes on the tower: + DO J = 1,p%TwrNodes + CALL MeshPositionNode ( y%TowerLn2Mesh, J, u%TowerPtLoads%Position(:,J), ErrStat2, ErrMsg2, & + orient = u%TowerPtLoads%RefOrientation(:,:,J) ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + ! for now, we're going to add two nodes, one at the beginning and the other at the end + ! they're numbered this way so that I don't have to redo all the loops in the computational part of the code + ! I am not going to use them in my input. + CALL MeshPositionNode ( y%TowerLn2Mesh, p%TwrNodes + 1, (/0.0_ReKi, 0.0_ReKi, p%TowerHt /), ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + CALL MeshPositionNode ( y%TowerLn2Mesh, p%TwrNodes + 2, (/0.0_ReKi, 0.0_ReKi, p%TowerBsHt /), ErrStat2, ErrMsg2, ref=.true. ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + + ! create line2 elements from the tower nodes (we've alread checked that p%TwrNodes is a positive number): + DO J = 2,p%TwrNodes+1 !the plus 1 includes one of the end nodes + CALL MeshConstructElement ( Mesh = y%TowerLn2Mesh & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + ! add the other extra element, connecting the first node: + CALL MeshConstructElement ( Mesh = y%TowerLn2Mesh & + , Xelement = ELEMENT_LINE2 & + , P1 = p%TwrNodes + 2 & ! node1 number + , P2 = 1 & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + + ! that's our entire mesh: + CALL MeshCommit ( y%TowerLn2Mesh, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + !....................................................... + ! Create Point Meshes for motions AeroDyn/BeamDyn needs: + !....................................................... + + ! -------------- Hub ----------------------------------- + !BJJ: sibling of u%HubPtLoad + CALL MeshCopy ( SrcMesh = u%HubPtLoad & + , DestMesh = y%HubPtMotion & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + ! -------------- pseudo-Hub (for AD v14) ----------------------------------- + CALL MeshCreate( BlankMesh = y%HubPtMotion14 & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + ! pseudo-Hub position and orientation (relative here as before, but should not be) + + CALL MeshPositionNode ( y%HubPtMotion14, 1, (/0.0_ReKi, 0.0_ReKi, p%HubHt /), ErrStat, ErrMsg ) !orientation is identity by default + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CommitPointMesh( y%HubPtMotion14 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! -------------- Blade Roots ----------------------------------- + ALLOCATE( y%BladeRootMotion(p%NumBl), Stat=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL CheckError( ErrID_Fatal, 'ED: Could not allocate space for y%BladeRootMotions{p%NumBl}' ) + RETURN + END IF + + + DO k=1,p%NumBl + CALL MeshCreate( BlankMesh = y%BladeRootMotion(k) & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationVel = .TRUE. & + ,RotationAcc = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + + CALL MeshCreate( BlankMesh = y%BladeRootMotion14 & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = p%NumBl & + , Orientation = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + DO K=1,p%NumBl + + Orientation(1,1) = p%CosPreC(K) + Orientation(2,1) = 0.0_R8Ki + Orientation(3,1) = 1.0_R8Ki * p%SinPreC(K) + + Orientation(1,2) = 0.0_R8Ki + Orientation(2,2) = 1.0_R8Ki + Orientation(3,2) = 0.0_R8Ki + + Orientation(1,3) = -1.0_R8Ki * p%SinPreC(K) + Orientation(2,3) = 0.0_R8Ki + Orientation(3,3) = p%CosPreC(K) + + Position(1) = p%HubRad*p%SinPreC(K) + Position(2) = 0.0_ReKi + Position(3) = p%HubRad*p%CosPreC(K) + + CALL MeshPositionNode ( y%BladeRootMotion14, K, Position, & + ErrStat, ErrMsg, Orient=Orientation ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + + position(1) = m%RtHS%rS (1,K,0) ! = the distance from the undeflected tower centerline to the current blade node in the xi ( z1) direction + position(2) = -1.*m%RtHS%rS (3,K,0) ! = the distance from the undeflected tower centerline to the current blade node in the yi (-z3) direction + position(3) = m%RtHS%rS (2,K,0) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade node in the zi ( z2) direction + + + Orientation(1,1) = m%CoordSys%j1(K,1) + Orientation(2,1) = m%CoordSys%j2(K,1) + Orientation(3,1) = m%CoordSys%j3(K,1) + Orientation(1,2) = -1.*m%CoordSys%j1(K,3) + Orientation(2,2) = -1.*m%CoordSys%j2(K,3) + Orientation(3,2) = -1.*m%CoordSys%j3(K,3) + Orientation(1,3) = m%CoordSys%j1(K,2) + Orientation(2,3) = m%CoordSys%j2(K,2) + Orientation(3,3) = m%CoordSys%j3(K,2) + + CALL MeshPositionNode ( y%BladeRootMotion(K), 1, Position, & + ErrStat, ErrMsg, Orient=Orientation ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + END DO + + CALL CommitPointMesh( y%BladeRootMotion14 ) + IF (ErrStat >= AbortErrLev) RETURN + + DO k=1,p%NumBl + CALL CommitPointMesh( y%BladeRootMotion(K) ) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + + ! -------------- Rotor Furl ----------------------------------- + CALL MeshCreate( BlankMesh = y%RotorFurlMotion14 & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + +!bjj: FIX THIS>>>> +!call wrscr(newline//'fix RotorFurlMotion initialization') + CALL MeshPositionNode ( y%RotorFurlMotion14, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi /), ErrStat, ErrMsg ) !orientation is identity by default +!<<<<<FIX THIS + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CommitPointMesh( y%RotorFurlMotion14 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! -------------- Nacelle ----------------------------------- + CALL MeshCopy ( SrcMesh = u%NacelleLoads & + , DestMesh = y%NacelleMotion & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets y%NacelleMotion%RemapFlag = .TRUE. + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + + ! -------------- Tower Base----------------------------------- + CALL MeshCreate( BlankMesh = y%TowerBaseMotion14 & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + , TranslationDisp = .TRUE. & + , RotationVel = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + +!bjj: FIX THIS>>>> +!call wrscr(newline//'fix TowerBaseMotion14 initialization') + CALL MeshPositionNode ( y%TowerBaseMotion14, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi /), ErrStat, ErrMsg ) !orientation is identity by default +!<<<<<FIX THIS + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CommitPointMesh( y%TowerBaseMotion14 ) + IF (ErrStat >= AbortErrLev) RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CommitPointMesh(NewMesh) + ! This routine makes every node a point element and then commits the mesh. + + TYPE(MeshType), INTENT(INOUT) :: NewMesh + + INTEGER(IntKi) :: Node + + DO Node = 1,NewMesh%Nnodes + + ! create an element from this point + CALL MeshConstructElement ( Mesh = NewMesh & + , Xelement = ELEMENT_POINT & + , P1 = Node & ! node number + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + END DO + + ! that's our entire mesh: + CALL MeshCommit ( NewMesh, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + END SUBROUTINE CommitPointMesh + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + ! Passed arguments + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_AllocOutput:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + END IF + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ED_AllocOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates the arrays stored in the ED_InputType data structure (u), based on the parameters (p). +!! The routine assumes that the arrays are not currently allocated (It will produce a fatal error otherwise.) It also initializes the inputs +SUBROUTINE Init_u( u, p, x, InputFileData, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputType), INTENT(INOUT) :: u !< Inputs to be allocated + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states + TYPE(ED_InputFile), INTENT(IN ) :: InputFileData !< Data stored in the module's input file + TYPE(ED_MiscVarType), INTENT(INOUT) :: m !< Misc variables (used to calculate initial position/orientation for meshes) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + REAL(R8Ki) :: Orientation(3,3) ! reference orientation matrix + REAL(ReKi) :: Position(3) ! position vector + TYPE(ED_ContinuousStateType) :: x_tmp ! continuous states (set to 0) + INTEGER(IntKi) :: J, K ! loop counters + INTEGER(IntKi) :: NodeNum ! number of current blade node + INTEGER(IntKi) :: ErrStat2 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message (ErrMsg) + CHARACTER(*), PARAMETER :: RoutineName = 'Init_u' + + ! initialize variables: + + ErrStat = ErrID_None + ErrMsg = "" + + !....................................................... + ! allocate the u%BlPitchCom array + !....................................................... + + CALL AllocAry( u%BlPitchCom, p%NumBl, 'BlPitchCom', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! will initialize u%BlPitchCom later, after getting undisplaced positions + + !....................................................... + ! we're going to calculate the non-displaced positions of + ! several variables so we can set up meshes properly later. + ! want inputs and states initialized to 0 first. + !....................................................... + CALL ED_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + x_tmp%qt = 0.0_ReKi + x_tmp%qdt = 0.0_ReKi + x_tmp%QT (DOF_GeAz) = - p%AzimB1Up - REAL(Piby2_D, R8Ki) + CALL Zero2TwoPi( x_tmp%QT (DOF_GeAz) ) + + u%BlPitchCom = 0.0_ReKi + + ! set the coordinate system variables: + CALL SetCoordSy( -p%DT, m%CoordSys, m%RtHS, u%BlPitchCom, p, x_tmp, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL CalculatePositions( p, x_tmp, m%CoordSys, m%RtHS ) ! calculate positions + + CALL ED_DestroyContState(x_tmp, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !....................................................... + ! initialize the u%BlPitchCom array + !....................................................... + ! was allocated above to call SetCoordSy and CalculatePositions with undisplaced values + u%BlPitchCom = InputFileData%BlPitch(1:p%NumBl) + + + !....................................................... + ! Create Line2 Meshes for loads input on blades: + !....................................................... + + IF (.not. p%BD4Blades) THEN + ALLOCATE( u%BladePtLoads(p%NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, "Could not allocate u%BladePtLoads", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + + + DO K=1,p%NumBl + + CALL MeshCreate( BlankMesh = u%BladePtLoads(K) & + ,IOS = COMPONENT_INPUT & + ,NNodes = p%BldNodes & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + if (p%UseAD14) then + ! position the nodes on the blades: + DO J = 1,p%BldNodes + + NodeNum = J + + Orientation(1,1) = p%CAeroTwst(J) + Orientation(2,1) = p%SAeroTwst(J) + Orientation(3,1) = 0.0_ReKi + + Orientation(1,2) = -p%SAeroTwst(J) + Orientation(2,2) = p%CAeroTwst(J) + Orientation(3,2) = 0.0_ReKi + + Orientation(1,3) = 0.0_ReKi + Orientation(2,3) = 0.0_ReKi + Orientation(3,3) = 1.0_ReKi + + CALL MeshPositionNode ( u%BladePtLoads(K), NodeNum, (/0.0_ReKi, 0.0_ReKi, p%RNodes(J) /), ErrStat2, ErrMsg2, Orient=Orientation ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END DO ! nodes + else + ! position the nodes on the blades: + DO J = 1,p%BldNodes + NodeNum = J + + Orientation(1,1) = m%CoordSys%n1(K,J,1) + Orientation(2,1) = m%CoordSys%n2(K,J,1) + Orientation(3,1) = m%CoordSys%n3(K,J,1) + Orientation(1,2) = -1.*m%CoordSys%n1(K,J,3) + Orientation(2,2) = -1.*m%CoordSys%n2(K,J,3) + Orientation(3,2) = -1.*m%CoordSys%n3(K,J,3) + Orientation(1,3) = m%CoordSys%n1(K,J,2) + Orientation(2,3) = m%CoordSys%n2(K,J,2) + Orientation(3,3) = m%CoordSys%n3(K,J,2) + + ! Translational Displacement + position(1) = m%RtHS%rS (1,K,J) ! = the distance from the undeflected tower centerline to the current blade node in the xi ( z1) direction + position(2) = -1.*m%RtHS%rS (3,K,J) ! = the distance from the undeflected tower centerline to the current blade node in the yi (-z3) direction + position(3) = m%RtHS%rS (2,K,J) + p%PtfmRefzt ! = the distance from the nominal tower base position (i.e., the undeflected position of the tower base) to the current blade node in the zi ( z2) direction + + + CALL MeshPositionNode ( u%BladePtLoads(K), NodeNum, position, ErrStat2, ErrMsg2, Orient=Orientation ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END DO ! nodes + end if ! position/orientation of nodes for AeroDyn v14 or v15 + + ! create elements: + DO J = 1,p%BldNodes !p%BldNodes + 1 + + CALL MeshConstructElement ( Mesh = u%BladePtLoads(K) & + , Xelement = ELEMENT_POINT & + , P1 = J & ! node1 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END DO ! J (blade nodes) + + ! that's our entire mesh: + CALL MeshCommit ( u%BladePtLoads(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + ! initialize it + u%BladePtLoads(K)%Moment = 0.0_ReKi + u%BladePtLoads(K)%Force = 0.0_ReKi + + + END DO ! blades + END IF ! p%BD4Blades + + + !....................................................... + ! Create Point Mesh for loads input at hub point (from BeamDyn): + !....................................................... + + CALL MeshCreate( BlankMesh = u%HubPtLoad & + ,IOS = COMPONENT_INPUT & + ,NNodes = 1 & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! place single node at hub; position affects mapping/coupling with other modules + Position(1) = m%RtHS%rQ(1) + Position(2) = -1.*m%RtHS%rQ(3) + Position(3) = m%RtHS%rQ(2) + p%PtfmRefzt + + Orientation(1,1) = m%CoordSys%g1(1) + Orientation(2,1) = m%CoordSys%g2(1) + Orientation(3,1) = m%CoordSys%g3(1) + Orientation(1,2) = -1.*m%CoordSys%g1(3) + Orientation(2,2) = -1.*m%CoordSys%g2(3) + Orientation(3,2) = -1.*m%CoordSys%g3(3) + Orientation(1,3) = m%CoordSys%g1(2) + Orientation(2,3) = m%CoordSys%g2(2) + Orientation(3,3) = m%CoordSys%g3(2) + + CALL MeshPositionNode ( u%HubPtLoad, 1, Position, ErrStat2, ErrMsg2, orient=Orientation ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! create an element from this point + CALL MeshConstructElement ( Mesh = u%HubPtLoad & + , Xelement = ELEMENT_POINT & + , P1 = 1 & ! node number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! that's our entire mesh: + CALL MeshCommit ( u%HubPtLoad, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! initailize it + u%HubPtLoad%Moment = 0.0_ReKi + u%HubPtLoad%Force = 0.0_ReKi + + + !....................................................... + ! Create Point Mesh for loads input at Platform Reference Point: + !....................................................... + + CALL MeshCreate( BlankMesh = u%PlatformPtMesh & + ,IOS = COMPONENT_INPUT & + ,NNodes = 1 & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! place single node at platform reference point; position affects mapping/coupling with other modules + CALL MeshPositionNode ( u%PlatformPtMesh, 1, (/0.0_ReKi, 0.0_ReKi, p%PtfmRefzt /), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! create an element from this point + CALL MeshConstructElement ( Mesh = u%PlatformPtMesh & + , Xelement = ELEMENT_POINT & + , P1 = 1 & ! node number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! that's our entire mesh: + CALL MeshCommit ( u%PlatformPtMesh, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! initialize fields + u%PlatformPtMesh%Moment = 0.0_ReKi + u%PlatformPtMesh%Force = 0.0_ReKi + + !....................................................... + ! Create Point Mesh for loads input at nacelle: + !....................................................... + + CALL MeshCreate( BlankMesh = u%NacelleLoads & + ,IOS = COMPONENT_OUTPUT & + ,NNodes = 1 & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL MeshPositionNode ( u%NacelleLoads, 1, (/0.0_ReKi, 0.0_ReKi, p%TowerHt /), ErrStat2, ErrMsg2 ) ! orientation is identity by default + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! create an element from this point + CALL MeshConstructElement ( Mesh = u%NacelleLoads & + , Xelement = ELEMENT_POINT & + , P1 = 1 & ! node number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + CALL MeshCommit ( u%NacelleLoads, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! initialize fields + u%NacelleLoads%Force = 0.0_ReKi + u%NacelleLoads%Moment = 0.0_ReKi + + !....................................................... + ! Create u%TwrAddedMass for loads input on tower: + ! SHOULD REMOVE EVENTUALLY + !....................................................... + + CALL AllocAry( u%TwrAddedMass, 6_IntKi, 6_IntKi, p%TwrNodes, 'TwrAddedMass', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! initialize it + u%TwrAddedMass = 0.0_ReKi + + !....................................................... + ! Create point Mesh for lumped load input on tower: + ! note that this does not contain the end points + !....................................................... + + CALL MeshCreate( BlankMesh = u%TowerPtLoads & + ,IOS = COMPONENT_INPUT & + ,NNodes = p%TwrNodes & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! position the nodes on the tower: + DO J = 1,p%TwrNodes + CALL MeshPositionNode ( u%TowerPtLoads, J, (/0.0_ReKi, 0.0_ReKi, p%HNodes(J) + p%TowerBsHt /), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END DO + + ! create elements: + DO J = 1,p%TwrNodes + CALL MeshConstructElement ( Mesh = u%TowerPtLoads & + , Xelement = ELEMENT_POINT & + , P1 = J & ! node1 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END DO + + + ! that's our entire mesh: + CALL MeshCommit ( u%TowerPtLoads, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! initialize fields + u%TowerPtLoads%Moment = 0.0_ReKi + u%TowerPtLoads%Force = 0.0_ReKi + + !....................................................... + ! initialize all remaining inputs (non-allocatable): + !....................................................... + + u%PtfmAddedMass = 0.0_ReKi + u%YawMom = 0.0_ReKi + u%GenTrq = 0.0_ReKi + u%HSSBrTrqC = 0.0_ReKi + + CALL Cleanup() + +CONTAINS + !............................................................................................................................... + SUBROUTINE Cleanup() + ! This subroutine cleans up if the error for returning to calling routine + !............................................................................................................................... + !......................................................................................................................... + ! close files, deallocate local arrays + !......................................................................................................................... + CALL ED_DestroyContState( x_tmp, ErrStat2, ErrMsg2 ) + + END SUBROUTINE Cleanup + +END SUBROUTINE Init_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." Sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE ED_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ED_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ED_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 + + ! local variables + + TYPE(ED_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(ED_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(ED_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(ED_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(ED_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(ED_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(ED_InputType) :: u_interp ! interpolated value of inputs + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL ED_CopyContState( x, k1, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL ED_CopyContState( x, k2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL ED_CopyContState( x, k3, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL ED_CopyContState( x, k4, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL ED_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + CALL ED_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! interpolate u to find u_interp = u(t) + CALL ED_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN +! HSSBrTrq_at_t = u_interp%HSSBrTrqC +! OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, x%QDT(DOF_GeAz) ) +! OtherState%HSSBrTrq = OtherState%HSSBrTrqC + + ! find xdot at t + CALL ED_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k1%qt = p%dt * xdot%qt + k1%qdt = p%dt * xdot%qdt + + x_tmp%qt = x%qt + 0.5 * k1%qt + x_tmp%qdt = x%qdt + 0.5 * k1%qdt + + ! interpolate u to find u_interp = u(t + dt/2) + CALL ED_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN +! u_interp%HSSBrTrqC = max(0.0_ReKi, min(u_interp%HSSBrTrqC, HSSBrTrq_at_t )) ! hack for extrapolation of limits +! OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, x_tmp%QDT(DOF_GeAz) ) +! OtherState%HSSBrTrq = OtherState%HSSBrTrqC + + ! find xdot at t + dt/2 + CALL ED_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k2%qt = p%dt * xdot%qt + k2%qdt = p%dt * xdot%qdt + + x_tmp%qt = x%qt + 0.5 * k2%qt + x_tmp%qdt = x%qdt + 0.5 * k2%qdt + + ! find xdot at t + dt/2 +! u_interp%HSSBrTrqC = max(0.0_ReKi, min(u_interp%HSSBrTrqC, HSSBrTrq_at_t )) ! hack for extrapolation of limits +! OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, x_tmp%QDT(DOF_GeAz) ) +! OtherState%HSSBrTrq = OtherState%HSSBrTrqC + CALL ED_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k3%qt = p%dt * xdot%qt + k3%qdt = p%dt * xdot%qdt + + x_tmp%qt = x%qt + k3%qt + x_tmp%qdt = x%qdt + k3%qdt + + ! interpolate u to find u_interp = u(t + dt) + CALL ED_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN +! u_interp%HSSBrTrqC = max(0.0_ReKi, min(u_interp%HSSBrTrqC, HSSBrTrq_at_t )) ! hack for extrapolation of limits +! OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, x_tmp%QDT(DOF_GeAz) ) +! OtherState%HSSBrTrq = OtherState%HSSBrTrqC + + ! find xdot at t + dt + CALL ED_CalcContStateDeriv( t + p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k4%qt = p%dt * xdot%qt + k4%qdt = p%dt * xdot%qdt + + x%qt = x%qt + ( k1%qt + 2. * k2%qt + 2. * k3%qt + k4%qt ) / 6. + x%qdt = x%qdt + ( k1%qdt + 2. * k2%qdt + 2. * k3%qdt + k4%qdt ) / 6. + + ! clean up local variables: + CALL ExitThisRoutine( ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL ED_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + + CALL ED_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_RK4:'//TRIM(Msg) + ErrStat = MAX(ErrStat,ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE ED_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE ED_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ED_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ED_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 + + + ! local variables + TYPE(ED_InputType) :: u_interp + TYPE(ED_ContinuousStateType) :: xdot + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + if (OtherState%n .lt. n) then + + OtherState%n = n + + ! Update IC() index so IC(1) is the location of xdot values at n. + ! (this allows us to shift the indices into the array, not copy all of the values) + OtherState%IC = CSHIFT( OtherState%IC, -1 ) ! circular shift of all values to the right + + elseif (OtherState%n .gt. n) then + + CALL CheckError( ErrID_Fatal, ' Backing up in time is not supported with a multistep method.') + RETURN + + endif + + + ! Allocate the input arrays + CALL ED_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! need xdot at t + CALL ED_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + IF (EqualRealNos( x%qdt(DOF_GeAz) ,0.0_R8Ki ) ) THEN + OtherState%HSSBrTrqC = u_interp%HSSBrTrqC + ELSE + OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, real(x%qdt(DOF_GeAz),ReKi) ) ! hack for HSS brake (need correct sign) + END IF + OtherState%HSSBrTrq = OtherState%HSSBrTrqC + OtherState%SgnPrvLSTQ = OtherState%SgnLSTQ(OtherState%IC(2)) + + CALL ED_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + + CALL ED_CopyContState(xdot, OtherState%xdot ( OtherState%IC(1) ), MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + if (n .le. 2) then + + CALL ED_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + else + + x%qt = x%qt + p%DT24 * ( 55.*OtherState%xdot(OtherState%IC(1))%qt - 59.*OtherState%xdot(OtherState%IC(2))%qt & + + 37.*OtherState%xdot(OtherState%IC(3))%qt - 9.*OtherState%xdot(OtherState%IC(4))%qt ) + + x%qdt = x%qdt + p%DT24 * ( 55.*OtherState%xdot(OtherState%IC(1))%qdt - 59.*OtherState%xdot(OtherState%IC(2))%qdt & + + 37.*OtherState%xdot(OtherState%IC(3))%qdt - 9.*OtherState%xdot(OtherState%IC(4))%qdt ) + + + ! Make sure the HSS brake will not reverse the direction of the HSS + ! for the next time step. Do this by computing the predicted value + ! of x%qt(); QD(DOF_GeAz,IC(NMX)) as will be done during the next time step. + ! Only do this after the first few time steps since it doesn't work + ! for the Runga-Kutta integration scheme. + + + CALL FixHSSBrTq ( 'P', p, x, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + endif + + OtherState%SgnPrvLSTQ = SignLSSTrq(p, m) + OtherState%SgnLSTQ(OtherState%IC(1)) = OtherState%SgnPrvLSTQ + + + ! clean up local variables: + CALL ExitThisRoutine() + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL ED_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( xdot, ErrStat2, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_AB4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE ED_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: \n +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: \n +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE ED_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ED_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ED_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 + + ! local variables + + TYPE(ED_InputType) :: u_interp ! Inputs at t + TYPE(ED_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(ED_ContinuousStateType) :: xdot_pred ! Derivative of continuous states at t + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! predict: + + CALL ED_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ED_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + if (n .gt. 2_IntKi) then + + ! correct: + + ! allocate the arrays in u_interp + CALL ED_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ED_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + u_interp%HSSBrTrqC = max(0.0_ReKi, min(u_interp%HSSBrTrqC, ABS( OtherState%HSSBrTrqC) )) ! hack for extrapolation of limits (OtherState%HSSBrTrqC is HSSBrTrqC at t) + IF (EqualRealNos( x_pred%qdt(DOF_GeAz) ,0.0_R8Ki ) ) THEN + OtherState%HSSBrTrqC = u_interp%HSSBrTrqC + ELSE + OtherState%HSSBrTrqC = SIGN( u_interp%HSSBrTrqC, real(x_pred%qdt(DOF_GeAz),ReKi) ) ! hack for HSS brake (need correct sign) + END IF + OtherState%HSSBrTrq = OtherState%HSSBrTrqC + + CALL ED_CalcContStateDeriv(t + p%dt, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + x%qt = x%qt + p%DT24 * ( 9. * xdot_pred%qt + 19. * OtherState%xdot(OtherState%IC(1))%qt & + - 5. * OtherState%xdot(OtherState%IC(2))%qt & + + 1. * OtherState%xdot(OtherState%IC(3))%qt ) + + x%qdt = x%qdt + p%DT24 * ( 9. * xdot_pred%qdt + 19. * OtherState%xdot(OtherState%IC(1))%qdt & + - 5. * OtherState%xdot(OtherState%IC(2))%qdt & + + 1. * OtherState%xdot(OtherState%IC(3))%qdt ) + + + ! Make sure the HSS brake has not reversed the direction of the HSS: + + CALL FixHSSBrTq ( 'C', p, x, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + OtherState%SgnPrvLSTQ = SignLSSTrq(p, m) + OtherState%SgnLSTQ(OtherState%IC(1)) = OtherState%SgnPrvLSTQ + + else + + x%qt = x_pred%qt + x%qdt = x_pred%qdt + + endif + + + ! clean up local variables: + CALL ExitThisRoutine() + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL ED_DestroyContState( xdot_pred, ErrStat3, ErrMsg3 ) + CALL ED_DestroyContState( x_pred, ErrStat3, ErrMsg3 ) + CALL ED_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ED_ABM4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE ED_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine generates the summary file, which contains a regurgitation of the input data and interpolated flexible body data. +SUBROUTINE ED_PrintSum( p, OtherState, GenerateAdamsModel, ErrStat, ErrMsg ) + + ! passed variables + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters of the structural dynamics module + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states of the structural dynamics module + LOGICAL, INTENT(IN ) :: GenerateAdamsModel !< Logical to determine if Adams inputs were read/should be summarized + 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 ! Index for the nodes. + INTEGER(IntKi) :: K ! Generic index (also for the blade number). + INTEGER(IntKi) :: UnSu ! I/O unit number for the summary output file + + CHARACTER(*), PARAMETER :: Fmt1 = "(34X,3(6X,'Blade',I2,:))" ! Format for outputting blade headings. + CHARACTER(*), PARAMETER :: Fmt2 = "(34X,3(6X,A,:))" ! Format for outputting blade headings. + CHARACTER(*), PARAMETER :: FmtDat = '(A,T35,3(:,F13.3))' ! Format for outputting mass and modal data. + CHARACTER(*), PARAMETER :: FmtDatT = '(A,T35,1(:,F13.8))' ! Format for outputting time steps. + CHARACTER(100) :: RotorType ! Text description of rotor. + + CHARACTER(30) :: OutPFmtS ! Format to print list of selected output channel names to summary file + CHARACTER(30) :: OutPFmt ! Format to print list of selected output channels to summary file + CHARACTER(10) :: DOFEnabled ! String to say if a DOF is enabled or disabled + CHARACTER(ChanLen),PARAMETER :: TitleStr(2) = (/ 'Parameter', 'Units ' /) + CHARACTER(ChanLen),PARAMETER :: TitleStrLines(2) = (/ '---------------', '---------------' /) + + ! Open the summary file and give it a heading. + + CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL OpenFOutFile ( UnSu, TRIM( p%RootName )//'.sum', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + ! Heading: + WRITE (UnSu,'(/,A)') 'This summary information was generated by '//TRIM( GetNVD(ED_Ver) )// & + ' on '//CurDate()//' at '//CurTime()//'.' + !WRITE (UnSu,'(//,1X,A)') TRIM( p%FTitle ) + + + !.................................. + ! Turbine features. + !.................................. + + WRITE (UnSu,'(//,A,/)') 'Turbine features:' + + IF ( p%OverHang > 0.0 ) THEN + RotorType = 'Downwind,' + ELSE + RotorType = 'Upwind,' + ENDIF + IF ( p%NumBl == 2 ) THEN + RotorType = TRIM(RotorType)//' two-bladed rotor' + IF ( p%DOF_Flag(DOF_Teet) ) THEN + RotorType = TRIM(RotorType)//' with teetering hub.' + ELSE + RotorType = TRIM(RotorType)//' with rigid hub.' + ENDIF + ELSE + RotorType = TRIM(RotorType)//' three-bladed rotor with rigid hub.' + ENDIF + + WRITE (UnSu,'(A)') ' '//TRIM(RotorType) + + WRITE (UnSu,'(A)') ' The model has '//TRIM(Num2LStr( p%DOFs%NActvDOF ))//' of '// & + TRIM(Num2LStr( p%NDOF ))//' DOFs active (enabled) at start-up.' + + DO I=1,p%NDOF + + IF ( p%DOF_Flag( I ) ) THEN + DOFEnabled = 'Enabled' + ELSE + DOFEnabled = 'Disabled' + END IF + + K = INDEX( p%DOF_Desc(I), ' (internal DOF index' ) + IF (K == 0) K = LEN_TRIM(p%DOF_Desc(I)) + + WRITE ( UnSu, '(1x,A10,1x,A)' ) DOFEnabled, p%DOF_Desc(I)(:K) + + + END DO + + + ! Time steps. + + WRITE (UnSu,'(//,A,/)') 'Time steps:' + + WRITE (UnSu,FmtDatT) ' Structural (s) ', p%DT + + ! Some calculated parameters. + + WRITE (UnSu,'(//,A,/)') 'Some calculated parameters:' + + WRITE (UnSu,FmtDat ) ' Hub-Height (m) ', p%HubHt + WRITE (UnSu,FmtDat ) ' Flexible Tower Length (m) ', p%TwrFlexL +IF (.NOT. p%BD4Blades) THEN + WRITE (UnSu,FmtDat ) ' Flexible Blade Length (m) ', p%BldFlexL +ELSE + WRITE (UnSu,'(A)' ) ' Flexible Blade Length (m) N/A' +END IF + + ! Rotor properties: + + WRITE (UnSu,'(//,A,/)') 'Rotor mass properties:' + + WRITE (UnSu,FmtDat ) ' Rotor Mass (kg) ', p%RotMass + WRITE (UnSu,FmTDat ) ' Rotor Inertia (kg-m^2)', p%RotINer + + WRITE (UnSu,Fmt1 ) ( K, K=1,p%NumBl ) + WRITE (UnSu,Fmt2 ) ( '-------', K=1,p%NumBl ) + +IF (.NOT. p%BD4Blades) THEN + + WRITE (UnSu,FmtDat ) ' Mass (kg) ', ( p%BldMass (K), K=1,p%NumBl ) + WRITE (UnSu,FmtDat ) ' Second Mass Moment (kg-m^2)', ( p%SecondMom(K), K=1,p%NumBl ) + WRITE (UnSu,FmtDat ) ' First Mass Moment (kg-m) ', ( p%FirstMom (K), K=1,p%NumBl ) + WRITE (UnSu,FmtDat ) ' Center of Mass (m) ', ( p%BldCG (K), K=1,p%NumBl ) + +ELSE + + WRITE (UnSu,'(A)' ) ' Mass (kg) N/A' + WRITE (UnSu,'(A)' ) ' Second Mass Moment (kg-m^2) N/A' + WRITE (UnSu,'(A)' ) ' First Mass Moment (kg-m) N/A' + WRITE (UnSu,'(A)' ) ' Center of Mass (m) N/A' + +END IF + + ! Output additional masses: + + WRITE (UnSu,'(//,A,/)') 'Additional mass properties:' + + WRITE (UnSu,FmtDat ) ' Tower-top Mass (kg) ', p%TwrTpMass + WRITE (UnSu,FmtDat ) ' Tower Mass (kg) ', p%TwrMass + !WRITE (UnSu,FmtDat ) ' Turbine Mass (kg) ', p%TurbMass + WRITE (UnSu,FmtDat ) ' Platform Mass (kg) ', p%PtfmMass + WRITE (UnSu,FmtDat ) ' Mass Incl. Platform (kg) ', p%TurbMass + p%PtfmMass !TotalMass !bjj TotalMass not used anywhere else so removed it + + + ! Interpolated tower properties. + + WRITE (UnSu,"(//,'Interpolated tower properties:',/)") + IF ( GenerateAdamsModel ) THEN ! An ADAMS model will be created; thus, print out all the cols. + + WRITE (UnSu,'(A)') 'Node TwFract HNodes DHNodes TMassDen FAStiff SSStiff'// & + ' GJStiff EAStiff FAIner SSIner FAcgOff SScgOff' + WRITE (UnSu,'(A)') ' (-) (-) (m) (m) (kg/m) (Nm^2) (Nm^2)'// & + ' (Nm^2) (N) (kg m) (kg m) (m) (m)' + + DO I=1,p%TwrNodes + WRITE(UnSu,'(I4,3F9.3,F10.3,4ES11.3,2F10.3,2F9.3)') I, p%HNodesNorm(I), p%HNodes(I), p%DHNodes(I), p%MassT(I), & + p%StiffTFA(I), p%StiffTSS(I), p%StiffTGJ(I), p%StiffTEA(I), & + p%InerTFA(I), p%InerTSS(I), p%cgOffTFA(I), p%cgOffTSS(I) + ENDDO ! I + + ELSE ! Only FAST will be run; thus, only print out the necessary cols. + + WRITE (UnSu,'(A)') 'Node TwFract HNodes DHNodes TMassDen FAStiff SSStiff' + WRITE (UnSu,'(A)') ' (-) (-) (m) (m) (kg/m) (Nm^2) (Nm^2)' + + DO I=1,p%TwrNodes + WRITE(UnSu,'(I4,3F9.3,F10.3,2ES11.3)') I, p%HNodesNorm(I), p%HNodes(I), p%DHNodes(I), p%MassT(I), & + p%StiffTFA(I), p%StiffTSS(I) + ENDDO ! I + + ENDIF + + + ! Interpolated blade properties. +IF (.NOT. p%BD4Blades) THEN + + DO K=1,p%NumBl + + WRITE (UnSu,'(//,A,I1,A,/)') 'Interpolated blade ', K, ' properties:' + IF ( GenerateAdamsModel ) THEN ! An ADAMS model will be created; thus, print out all the cols. + + WRITE (UnSu,'(A)') 'Node BlFract RNodes DRNodes PitchAxis StrcTwst BMassDen FlpStff EdgStff'// & + ' GJStff EAStff Alpha FlpIner EdgIner PrecrvRef PreswpRef FlpcgOf EdgcgOf'// & + ' FlpEAOf EdgEAOf' + WRITE (UnSu,'(A)') ' (-) (-) (m) (m) (-) (deg) (kg/m) (Nm^2) (Nm^2)'// & + ' (Nm^2) (Nm^2) (-) (kg m) (kg m) (m) (m) (m) (m)'// & + ' (m) (m)' + + DO I=1,p%BldNodes + + WRITE(UnSu,'(I4,3F9.3,3F10.3,4ES11.3,F9.3,4F10.3,4F9.3)') I, p%RNodesNorm(I), p%RNodes(I) + p%HubRad, p%DRNodes(I), & + p%PitchAxis(K,I), p%ThetaS(K,I)*R2D, p%MassB(K,I), & + p%StiffBF(K,I), p%StiffBE(K,I), & + p%StiffBGJ(K,I), p%StiffBEA(K,I), & + p%BAlpha(K,I), p%InerBFlp(K,I), p%InerBEdg(K,I), & + p%RefAxisxb(K,I), p%RefAxisyb(K,I), & + p%cgOffBFlp(K,I), p%cgOffBEdg(K,I), & + p%EAOffBFlp(K,I), p%EAOffBEdg(K,I) + ENDDO ! I + + ELSE ! Only FAST will be run; thus, only print out the necessary cols. + + WRITE (UnSu,'(A)') 'Node BlFract RNodes DRNodes PitchAxis StrcTwst BMassDen FlpStff EdgStff' + WRITE (UnSu,'(A)') ' (-) (-) (m) (m) (-) (deg) (kg/m) (Nm^2) (Nm^2)' + + DO I=1,p%BldNodes + WRITE(UnSu,'(I4,3F9.3,3F10.3,2ES11.3)') I, p%RNodesNorm(I), p%RNodes(I) + p%HubRad, p%DRNodes(I), & + p%PitchAxis(K,I),p%ThetaS(K,I)*R2D, p%MassB(K,I), & + p%StiffBF(K,I), p%StiffBE(K,I) + ENDDO ! I + + ENDIF + + ENDDO ! K + +END IF + + OutPFmt = '( I4, 3X,A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + OutPFmtS = '( A4, 3X,A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + WRITE (UnSu,'(//,A,//)') 'Requested Outputs:' + !WRITE (UnSu,"(/, ' Col Parameter Units', /, ' --- -------------- ----------')") + WRITE (UnSu,OutPFmtS) "Col", TitleStr + WRITE (UnSu,OutPFmtS) "---", TitleStrLines + DO I = 0,p%NumOuts + WRITE (UnSu,OutPFmt) I, p%OutParam(I)%Name, p%OutParam(I)%Units + END DO + + IF (.not. p%BD4Blades) THEN + WRITE (UnSu,'(2x,A)') + WRITE (UnSu,'(2x,A)') + WRITE (UnSu,'(2x,A)') 'Requested Output Channels at each blade station:' + WRITE (UnSu,OutPFmtS) "Col", TitleStr + WRITE (UnSu,OutPFmtS) "---", TitleStrLines + !WRITE (UnSu,'(2x,A)') 'Col Parameter Units' + !WRITE (UnSu,'(2x,A)') '---- -------------- ----------' + DO I = 1,p%BldNd_NumOuts + WRITE (UnSu,OutPFmt) I, p%BldNd_OutParam(I)%Name, p%BldNd_OutParam(I)%Units + END DO + ENDIF + + CLOSE(UnSu) + +RETURN +END SUBROUTINE ED_PrintSum +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to adjust the HSSBrTrq value if the absolute +!! magnitudue of the HSS brake torque was strong enough to reverse +!! the direction of the HSS, which is a physically impossible +!! situation. The problem arises since we are integrating in +!! discrete time, not continuous time. +SUBROUTINE FixHSSBrTq ( Integrator, p, x, OtherState, m, ErrStat, ErrMsg ) + + + ! Passed variables: + + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters of the structural dynamics module + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states of the structural dynamics module + TYPE(ED_MiscVarType), INTENT(INOUT) :: m !< misc (optimization) variables + TYPE(ED_ContinuousStateType),INTENT(INOUT) :: x !< Continuous states of the structural dynamics module at n+1 + CHARACTER(1), INTENT(IN ) :: Integrator !< A string holding the current integrator being used. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables: + + REAL(ReKi) :: RqdFrcGeAz ! The force term required to produce RqdQD2GeAz. + REAL(ReKi) :: RqdQD2GeAz ! The required QD2T(DOF_GeAz) to cause the HSS to stop rotating. + + INTEGER :: I ! Loops through all DOFs. + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FixHSSBrTq' + + + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( .NOT. p%DOF_Flag(DOF_GeAz) .OR. EqualRealNos(OtherState%HSSBrTrqC, 0.0_ReKi ) ) RETURN + + + ! The absolute magnitude of the HSS brake must have been too great + ! that the HSS direction was reversed. What should have happened + ! is that the HSS should have stopped rotating. In other words, + ! QD(DOF_GeAz,IC(NMX)) should equal zero! Determining what + ! QD2T(DOF_GeAz) will make QD(DOF_GeAz,IC(NMX)) = 0, depends on + ! which integrator we are using. + + + SELECT CASE (Integrator) + + CASE ('C') ! Corrector + + ! Find the required QD2T(DOF_GeAz) to cause the HSS to stop rotating (RqdQD2GeAz). + ! This is found by solving the corrector formula for QD2(DOF_GeAz,IC(NMX)) + ! when QD(DOF_GeAz,IC(NMX)) equals zero. + + RqdQD2GeAz = ( - OtherState%xdot(OtherState%IC(1))%qt (DOF_GeAz)/ p%DT24 & + - 19.0*OtherState%xdot(OtherState%IC(1))%qdt(DOF_GeAz) & + + 5.0*OtherState%xdot(OtherState%IC(2))%qdt(DOF_GeAz) & + - OtherState%xdot(OtherState%IC(3))%qdt(DOF_GeAz) ) / 9.0 + + CASE ('P') ! Predictor + + ! Find the required QD2T(DOF_GeAz) to cause the HSS to stop rotating (RqdQD2GeAz). + ! This is found by solving the predictor formula for QD2(DOF_GeAz,IC(1)) + ! when QD(DOF_GeAz,IC(NMX)) equals zero. + + RqdQD2GeAz = ( - OtherState%xdot(OtherState%IC(1))%qt( DOF_GeAz) / p%DT24 & + + 59.0*OtherState%xdot(OtherState%IC(2))%qdt(DOF_GeAz) & + - 37.0*OtherState%xdot(OtherState%IC(3))%qdt(DOF_GeAz) & + + 9.0*OtherState%xdot(OtherState%IC(4))%qdt(DOF_GeAz) )/55.0 + + END SELECT + + + ! Rearrange the augmented matrix of equations of motion to account + ! for the known acceleration of the generator azimuth DOF. To + ! do this, make the known inertia like an applied force to the + ! system. Then set force QD2T(DOF_GeAz) to equal the known + ! acceleration in the augmented matrix of equations of motion: + ! Here is how the new equations are derived. First partition the + ! augmented matrix as follows, where Qa are the unknown + ! accelerations, Qb are the known accelerations, Fa are the + ! known forces, and Fb are the unknown forces: + ! [Caa Cab]{Qa}={Fa} + ! [Cba Cbb]{Qb}={Fb} + ! By rearranging, the equations for the unknown and known + ! accelerations are as follows: + ! [Caa]{Qa}={Fa}-[Cab]{Qb} and [I]{Qb}={Qb} + ! Combining these two sets of equations into one set yields: + ! [Caa 0]{Qa}={{Fa}-[Cab]{Qb}} + ! [ 0 I]{Qb}={ {Qb}} + ! Once this equation is solved, the unknown force can be found from: + ! {Fb}=[Cba]{Qa}+[Cbb]{Qb} + + m%OgnlGeAzRo = m%AugMat(DOF_GeAz,:) ! used for HSS Brake hack; copy this row before modifying the old matrix + + + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + m%AugMat(p%DOFs%SrtPS(I), p%NAUG) = m%AugMat(p%DOFs%SrtPS(I),p%NAUG) & + - m%AugMat(p%DOFs%SrtPS(I),DOF_GeAz)*RqdQD2GeAz ! {{Fa}-[Cab]{Qb}} + m%AugMat(p%DOFs%SrtPS(I),DOF_GeAz) = 0.0 ! [0] + m%AugMat(DOF_GeAz, p%DOFs%SrtPS(I)) = 0.0 ! [0] + + ENDDO ! I - All active (enabled) DOFs + + m%AugMat(DOF_GeAz,DOF_GeAz) = 1.0 ! [I]{Qb}={Qb} + m%AugMat(DOF_GeAz, p%NAUG) = RqdQD2GeAz ! + + + ! Invert the matrix to solve for the new (updated) accelerations. Like in + ! CalcContStateDeriv(), the accelerations are returned by Gauss() in the first NActvDOF + ! elements of the solution vector, SolnVec(). These are transfered to the + ! proper index locations of the acceleration vector QD2T() using the + ! vector subscript array SrtPS(), after Gauss() has been called: + + ! Invert the matrix to solve for the accelerations. The accelerations are returned by Gauss() in the first NActvDOF elements + ! of the solution vector, SolnVec(). These are transfered to the proper index locations of the acceleration vector QD2T() + ! using the vector subscript array SrtPS(), after Gauss() has been called: + + m%AugMat_factor = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1:p%DOFs%NActvDOF) ) + m%SolnVec = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1+p%DOFs%NActvDOF) ) + + CALL LAPACK_getrf( M=p%DOFs%NActvDOF, N=p%DOFs%NActvDOF, A=m%AugMat_factor, IPIV=m%AugMat_pivot, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL LAPACK_getrs( TRANS='N',N=p%DOFs%NActvDOF, A=m%AugMat_factor,IPIV=m%AugMat_pivot, B=m%SolnVec, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Find the force required to produce RqdQD2GeAz from the equations of + ! motion using the new accelerations: + + RqdFrcGeAz = 0.0 + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + ! bjj: use m%SolnVec(I) instead of m%QD2T(p%DOFs%SrtPS(I)) here; then update m%QD2T(p%DOFs%SrtPS(I)) + ! later if necessary + !RqdFrcGeAz = RqdFrcGeAz + OgnlGeAzRo(SrtPS(I))*m%QD2T(p%DOFs%SrtPS(I)) ! {Fb}=[Cba]{Qa}+[Cbb]{Qb} + RqdFrcGeAz = RqdFrcGeAz + m%OgnlGeAzRo(p%DOFs%SrtPS(I))*m%SolnVec(I) ! {Fb}=[Cba]{Qa}+[Cbb]{Qb} + ENDDO ! I - All active (enabled) DOFs + + + ! Find the HSSBrTrq necessary to bring about this force: + + OtherState%HSSBrTrq = OtherState%HSSBrTrqC & + + ( ( m%OgnlGeAzRo(p%NAUG) - RqdFrcGeAz )*m%RtHS%GBoxEffFac/ABS(p%GBRatio) ) + + + ! Make sure this new HSSBrTrq isn't larger in absolute magnitude than + ! the original HSSBrTrq. Indeed, the new HSSBrTrq can't be larger than + ! the old HSSBrTrq, since the old HSSBrTrq was found solely as a + ! function of time--and is thus the maximum possible at the current + ! time. If the new HSSBrTrq is larger, then the reversal in direction + ! was caused by factors other than the HSS brake--thus the original HSS + ! brake torque values were OK to begin with. Thus, restore the + ! variables changed by this subroutine, back to their original values: + + IF ( ABS( OtherState%HSSBrTrq ) > ABS( OtherState%HSSBrTrqC ) ) THEN + + OtherState%HSSBrTrq = OtherState%HSSBrTrqC !OtherState%HSSBrTrqC = SIGN( u%HSSBrTrqC, x%QDT(DOF_GeAz) ) + !m%QD2T = QD2TC + + ELSE + + ! overwrite QD2T with the new values + m%QD2T = 0.0 + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + m%QD2T(p%DOFs%SrtPS(I)) = m%SolnVec(I) + ENDDO ! I - All active (enabled) DOFs + + + ! Use the new accelerations to update the DOF values. Again, this + ! depends on the integrator type: + + SELECT CASE (Integrator) + + CASE ('C') ! Corrector + + ! Update QD and QD2 with the new accelerations using the corrector. + ! This will make QD(DOF_GeAz,IC(NMX)) equal to zero and adjust all + ! of the other QDs as necessary. + ! The Q's are unnaffected by this change. + + x%qdt = OtherState%xdot(OtherState%IC(1))%qt & ! qd at n + + p%DT24 * ( 9. * m%QD2T & ! the value we just changed + + 19. * OtherState%xdot(OtherState%IC(1))%qdt & + - 5. * OtherState%xdot(OtherState%IC(2))%qdt & + + 1. * OtherState%xdot(OtherState%IC(3))%qdt ) + + + + CASE ('P') ! Predictor + + ! Update QD and QD2 with the new accelerations using predictor. + + x%qdt = OtherState%xdot(OtherState%IC(1))%qt + & ! qd at n + p%DT24 * ( 55.*m%QD2T & ! the value we just changed + - 59.*OtherState%xdot(OtherState%IC(2))%qdt & + + 37.*OtherState%xdot(OtherState%IC(3))%qdt & + - 9.*OtherState%xdot(OtherState%IC(4))%qdt ) + + OtherState%xdot ( OtherState%IC(1) )%qdt = m%QD2T ! fix the history + + + END SELECT + + ENDIF + + RETURN +END SUBROUTINE FixHSSBrTq +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in ED_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ED_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(ED_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ED_OutputType), INTENT(INOUT) :: 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(ED_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 the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + + + ! local variables + TYPE(ED_OutputType) :: y_p + TYPE(ED_OutputType) :: y_m + TYPE(ED_ContinuousStateType) :: x_p + TYPE(ED_ContinuousStateType) :: x_m + TYPE(ED_InputType) :: u_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, j + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + m%IgnoreMod = .true. ! to compute perturbations, we need to ignore the modulo function + + ! make a copy of the inputs to perturb + call ED_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + + IF ( PRESENT( dYdu ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate dYdu if necessary + if (.not. allocated(dYdu)) then + call AllocAry(dYdu, p%Jac_ny, size(p%Jac_u_indx,1)+1, 'dYdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call ED_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ED_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta u + call ED_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call ED_Perturb_u( p, i, 1, u_perturb, delta ) + + ! compute y at u_op + delta u + call ED_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get u_op - delta u + call ED_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call ED_Perturb_u( p, i, -1, u_perturb, delta ) + + ! compute y at u_op - delta u + call ED_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta, dYdu(:,i) ) + + end do + + ! now do the extended input: sum the p%NumBl blade pitch columns + dYdu(:,size(p%Jac_u_indx,1)+1) = dYdu(:,size(p%Jac_u_indx,1)-p%NumBl-1) ! last NumBl+2 columns are: GenTrq, YawMom, and BlPitchCom + do i=2,p%NumBl + dYdu(:,size(p%Jac_u_indx,1)+1) = dYdu(:,size(p%Jac_u_indx,1)+1) + dYdu(:,size(p%Jac_u_indx,1)-p%NumBl-2+i) + end do + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call ED_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call ED_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + END IF + + + IF ( PRESENT( dXdu ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate dXdu if necessary + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, p%DOFs%NActvDOF * 2, size(p%Jac_u_indx,1)+1, 'dXdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta u + call ED_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call ED_Perturb_u( p, i, 1, u_perturb, delta ) + + ! compute x at u_op + delta u + call ED_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get u_op - delta u + call ED_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call ED_Perturb_u( p, i, -1, u_perturb, delta ) + + ! compute x at u_op - delta u + call ED_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do j=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dXdu(j, i) = x_p%QT( p%DOFs%PS(j) ) - x_m%QT( p%DOFs%PS(j) ) + end do + do j=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dXdu(j+p%DOFs%NActvDOF, i) = x_p%QDT( p%DOFs%PS(j) ) - x_m%QDT( p%DOFs%PS(j) ) + end do + dXdu(:,i) = dXdu(:,i) / (2*delta) + + end do + + + ! now do the extended input: sum the p%NumBl blade pitch columns + dXdu(:,size(p%Jac_u_indx,1)+1) = dXdu(:,size(p%Jac_u_indx,1)-p%NumBl-1) ! last NumBl+2 columns are: GenTrq, YawMom, and BlPitchCom + do i=2,p%NumBl + dXdu(:,size(p%Jac_u_indx,1)+1) = dXdu(:,size(p%Jac_u_indx,1)+1) + dXdu(:,size(p%Jac_u_indx,1)-p%NumBl-2+i) + end do + + + call ED_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call ED_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + + END IF + + + + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF + + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + call cleanup() + +contains + subroutine cleanup() + call ED_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call ED_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call ED_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call ED_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call ED_DestroyInput( u_perturb, ErrStat2, ErrMsg2 ) + m%IgnoreMod = .false. + end subroutine cleanup + +END SUBROUTINE ED_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 ED_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(ED_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ED_OutputType), INTENT(INOUT) :: 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(ED_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] + + ! local variables + TYPE(ED_OutputType) :: y_p + TYPE(ED_OutputType) :: y_m + TYPE(ED_ContinuousStateType) :: x_p + TYPE(ED_ContinuousStateType) :: x_m + TYPE(ED_ContinuousStateType) :: x_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, j + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_JacobianPContState' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + m%IgnoreMod = .true. ! to get true perturbations, we can't use the modulo function + + ! make a copy of the continuous states to perturb + call ED_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + IF ( PRESENT( dYdx ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + + ! allocate dYdx if necessary + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%Jac_ny, p%DOFs%NActvDOF*2, 'dYdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call ED_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ED_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + do i=1,p%DOFs%NActvDOF*2 + + ! get x_op + delta x + call ED_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call ED_Perturb_x( p, i, 1, x_perturb, delta ) + + ! compute y at x_op + delta x + call ED_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get x_op - delta x + call ED_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call ED_Perturb_x( p, i, -1, x_perturb, delta ) + + ! compute y at x_op - delta x + call ED_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta, dYdx(:,i) ) + + end do + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call ED_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call ED_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + 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 dXdx if necessary + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, p%DOFs%NActvDOF * 2, p%DOFs%NActvDOF * 2, 'dXdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + do i=1,p%DOFs%NActvDOF * 2 + + ! get x_op + delta x + call ED_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ED_Perturb_x( p, i, 1, x_perturb, delta ) + + ! compute x at x_op + delta x + call ED_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get x_op - delta x + call ED_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ED_Perturb_x( p, i, -1, x_perturb, delta ) + + ! compute x at x_op - delta x + call ED_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! get central difference: + + ! we may have had an error allocating memory, so we'll check + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do j=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dXdx(j, i) = x_p%QT( p%DOFs%PS(j) ) - x_m%QT( p%DOFs%PS(j) ) + end do + do j=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dXdx(j+p%DOFs%NActvDOF, i) = x_p%QDT( p%DOFs%PS(j) ) - x_m%QDT( p%DOFs%PS(j) ) + end do + dXdx(:,i) = dXdx(:,i) / (2*delta) + + end do + + call ED_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call ED_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + END IF + + IF ( PRESENT( dXddx ) ) THEN + if (allocated(dXddx)) deallocate(dXddx) + END IF + + IF ( PRESENT( dZdx ) ) THEN + if (allocated(dZdx)) deallocate(dZdx) + END IF + + call cleanup() + +contains + subroutine cleanup() + call ED_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call ED_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call ED_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call ED_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call ED_DestroyContState(x_perturb, ErrStat2, ErrMsg2 ) + m%IgnoreMod = .false. + end subroutine cleanup + +END SUBROUTINE ED_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 ED_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(ED_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ED_OutputType), INTENT(INOUT) :: 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(ED_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) :: dYdxd(:,:) !< Partial derivatives of output functions + !! (Y) with respect to the discrete + !! states (xd) [intent in to avoid deallocation] + REAL(ReKi), 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(ReKi), 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(ReKi), 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 ED_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 ED_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(ED_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ED_OutputType), INTENT(INOUT) :: 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(ED_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) :: dYdz(:,:) !< Partial derivatives of output functions (Y) with respect + !! to the constraint states (z) [intent in to avoid deallocation] + REAL(ReKi), 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(ReKi), 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(ReKi), 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 ED_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized outputs. +SUBROUTINE ED_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) + + TYPE(ED_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(ED_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(ED_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + 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,j,k, index_last, index_next + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Init_Jacobian_y' + LOGICAL :: Mask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + logical, allocatable :: AllOut(:) + + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! determine how many outputs there are in the Jacobians + p%Jac_ny = 0 + if (allocated(y%BladeLn2Mesh)) then + do i=1,p%NumBl + p%Jac_ny = p%Jac_ny + y%BladeLn2Mesh(i)%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node on each blade + end do + end if + + p%Jac_ny = p%Jac_ny & + + y%PlatformPtMesh%NNodes * 18 & ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + + y%TowerLn2Mesh%NNodes * 18 & ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + + y%HubPtMotion%NNodes * 9 & ! 3 TranslationDisp, Orientation, and RotationVel at each node + + y%NacelleMotion%NNodes * 18 & ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + + 3 & ! Yaw, YawRate, and HSS_Spd + + p%NumOuts + p%BldNd_TotNumOuts ! WriteOutput values + + do i=1,p%NumBl + p%Jac_ny = p%Jac_ny + y%BladeRootMotion(i)%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each (1) node on each blade + end do + + + !................. + ! set linearization output names: + !................. + CALL AllocAry(InitOut%LinNames_y, p%Jac_ny, 'LinNames_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%RotFrame_y, p%Jac_ny, 'RotFrame_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%RotFrame_y = .false. ! note that meshes are in the global, not rotating frame + + ! note that this Mask is for the y%HubPtMotion mesh ONLY. The others pack *all* of the motion fields + Mask = .false. + Mask(MASKID_TRANSLATIONDISP) = .true. + Mask(MASKID_ORIENTATION) = .true. + Mask(MASKID_ROTATIONVEL) = .true. + + index_next = 1 + if (allocated(y%BladeLn2Mesh)) then + index_last = index_next + do i=1,p%NumBl + call PackMotionMesh_Names(y%BladeLn2Mesh(i), 'Blade '//trim(num2lstr(i)), InitOut%LinNames_y, index_next) + end do + !InitOut%RotFrame_y(index_last:index_next-1) = .true. ! values on the mesh are in global, not rotating frame + end if + call PackMotionMesh_Names(y%PlatformPtMesh, 'Platform', InitOut%LinNames_y, index_next) + call PackMotionMesh_Names(y%TowerLn2Mesh, 'Tower', InitOut%LinNames_y, index_next) + call PackMotionMesh_Names(y%HubPtMotion, 'Hub', InitOut%LinNames_y, index_next, FieldMask=Mask) + index_last = index_next + do i=1,p%NumBl + call PackMotionMesh_Names(y%BladeRootMotion(i), 'Blade root '//trim(num2lstr(i)), InitOut%LinNames_y, index_next) + end do + !InitOut%RotFrame_y(index_last:index_next-1) = .true. ! values on the mesh are in global, not rotating frame + + call PackMotionMesh_Names(y%NacelleMotion, 'Nacelle', InitOut%LinNames_y, index_next) + InitOut%LinNames_y(index_next) = 'Yaw, rad'; index_next = index_next+1 + InitOut%LinNames_y(index_next) = 'YawRate, rad/s'; index_next = index_next+1 + InitOut%LinNames_y(index_next) = 'HSS_Spd, rad/s' + + do i=1,p%NumOuts + p%BldNd_TotNumOuts + InitOut%LinNames_y(i+index_next) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) !trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + end do + + + !! check for AllOuts in rotating frame + allocate( AllOut(0:MaxOutPts), STAT=ErrStat2 ) ! allocate starting at zero to account for invalid output channels + if (ErrStat2 /=0 ) then + call SetErrStat(ErrID_Info, 'error allocating temporary space for AllOut',ErrStat,ErrMsg,RoutineName) + return; + end if + + AllOut = .false. + do k=1,3 + AllOut(TipDxc( k)) = .true. + AllOut(TipDyc( k)) = .true. + AllOut(TipDzc( k)) = .true. + AllOut(TipDxb( k)) = .true. + AllOut(TipDyb( k)) = .true. + AllOut(TipALxb( k)) = .true. + AllOut(TipALyb( k)) = .true. + AllOut(TipALzb( k)) = .true. + AllOut(TipRDxb( k)) = .true. + AllOut(TipRDyb( k)) = .true. + AllOut(TipRDzc( k)) = .true. + AllOut(TipClrnc(k)) = .true. + AllOut(PtchPMzc(k)) = .true. + AllOut(RootFxc( k)) = .true. + AllOut(RootFyc( k)) = .true. + AllOut(RootFzc( k)) = .true. + AllOut(RootFxb( k)) = .true. + AllOut(RootFyb( k)) = .true. + AllOut(RootMxc( k)) = .true. + AllOut(RootMyc( k)) = .true. + AllOut(RootMzc( k)) = .true. + AllOut(RootMxb( k)) = .true. + AllOut(RootMyb( k)) = .true. + + do j=1,9 + AllOut(SpnALxb( j,k)) = .true. + AllOut(SpnALyb( j,k)) = .true. + AllOut(SpnALzb( j,k)) = .true. + AllOut(SpnFLxb( j,k)) = .true. + AllOut(SpnFLyb( j,k)) = .true. + AllOut(SpnFLzb( j,k)) = .true. + AllOut(SpnMLxb( j,k)) = .true. + AllOut(SpnMLyb( j,k)) = .true. + AllOut(SpnMLzb( j,k)) = .true. + AllOut(SpnTDxb( j,k)) = .true. + AllOut(SpnTDyb( j,k)) = .true. + AllOut(SpnTDzb( j,k)) = .true. + AllOut(SpnRDxb( j,k)) = .true. + AllOut(SpnRDyb( j,k)) = .true. + AllOut(SpnRDzb( j,k)) = .true. + end do + end do + + do i=1,p%NumOuts + InitOut%RotFrame_y(i+index_next) = AllOut( p%OutParam(i)%Indx ) + end do + + do i=1, p%BldNd_TotNumOuts + InitOut%RotFrame_y(i+p%NumOuts+index_next) = .true. + end do + + deallocate(AllOut) + + +END SUBROUTINE ED_Init_Jacobian_y +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized continuous states. +SUBROUTINE ED_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) + + TYPE(ED_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(ED_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Init_Jacobian_x' + + ! local variables: + INTEGER(IntKi) :: i + + ErrStat = ErrID_None + ErrMsg = "" + + + ! allocate space for the row/column names and for perturbation sizes + call allocAry(p%dx, p%NDof, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%LinNames_x, p%DOFs%NActvDOF*2, 'LinNames_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%RotFrame_x, p%DOFs%NActvDOF*2, 'RotFrame_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%DerivOrder_x, p%DOFs%NActvDOF*2, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! All Elastodyn continuous states are max order = 2 + if ( allocated(InitOut%DerivOrder_x) ) InitOut%DerivOrder_x = 2 + + p%dx = 0.0_R8Ki ! initialize in case we have only 1 blade + + ! set perturbation sizes: p%dx + p%dx(DOF_Sg :DOF_Hv) = 0.2_R8Ki * D2R_D * max(p%TowerHt, 1.0_ReKi) ! platform translational displacement states + p%dx(DOF_R :DOF_Y ) = 2.0_R8Ki * D2R_D ! platform rotational states + p%dx(DOF_TFA1:DOF_TSS1) = 0.020_R8Ki * D2R_D * p%TwrFlexL ! tower deflection states: 1st tower + p%dx(DOF_TFA2:DOF_TSS2) = 0.002_R8Ki * D2R_D * p%TwrFlexL ! tower deflection states: 2nd tower + p%dx(DOF_Yaw :DOF_TFrl) = 2.0_R8Ki * D2R_D ! nacelle-yaw, rotor-furl, generator azimuth, drivetrain, and tail-furl rotational states + + do i=1,p%NumBl + p%dx(DOF_BF(i,1))= 0.20_R8Ki * D2R_D * p%BldFlexL ! blade-deflection states: 1st blade flap mode + p%dx(DOF_BF(i,2))= 0.02_R8Ki * D2R_D * p%BldFlexL ! blade-deflection states: 2nd blade flap mode for blades (1/10 of the other perturbations) + p%dx(DOF_BE(i,1))= 0.20_R8Ki * D2R_D * p%BldFlexL ! blade-deflection states: 1st blade edge mode + end do + + if ( p%NumBl == 2 ) then + p%dx(DOF_Teet) = 2.0_R8Ki * D2R_D ! rotor-teeter rotational state + end if + + !Set some limits in case perturbation is very small + do i=1,p%NDof + p%dx(i) = max(p%dx(i), MinPerturb) + end do + + InitOut%RotFrame_x = .false. + do i=1,p%DOFs%NActvDOF + if ( p%DOFs%PS(i) >= DOF_BF(1,1) ) then + if ( p%NumBl == 2 ) then + InitOut%RotFrame_x(i) = p%DOFs%PS(i) < DOF_Teet + else + InitOut%RotFrame_x(i) = .true. ! = p%DOFs%PS(i) <= DOF_BF (MaxBl,NumBF) + end if + end if + end do + + ! set linearization output names: + do i=1,p%DOFs%NActvDOF + InitOut%LinNames_x(i) = p%DOF_Desc( p%DOFs%PS(i) ) + end do + + do i=1,p%DOFs%NActvDOF + InitOut%LinNames_x(i+p%DOFs%NActvDOF) = 'First time derivative of '//trim(InitOut%LinNames_x(i))//'/s' + InitOut%RotFrame_x(i+p%DOFs%NActvDOF) = InitOut%RotFrame_x(i) + end do + +END SUBROUTINE ED_Init_Jacobian_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing corresponding linearization routines ! +SUBROUTINE ED_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) + + TYPE(ED_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(ED_InputType) , INTENT(IN ) :: u !< inputs + TYPE(ED_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(ED_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Init_Jacobian' + + ! local variables: + INTEGER(IntKi) :: i, j, k, index, index_last, nu, i_meshField, m + REAL(R8Ki) :: MaxThrust, MaxTorque + REAL(R8Ki) :: ScaleLength + + + + ErrStat = ErrID_None + ErrMsg = "" + + + call ED_Init_Jacobian_y( p, y, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ED_Init_Jacobian_x( p, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + + ! determine how many inputs there are in the Jacobians + nu = 0; + if (allocated(u%BladePtLoads)) then + do i=1,p%NumBl + nu = nu + u%BladePtLoads(i)%NNodes * 6 ! 3 forces + 3 moments at each node on each blade + end do + end if + nu = nu & + + u%PlatformPtMesh%NNodes * 6 & ! 3 forces + 3 moments at each node + + u%TowerPtLoads%NNodes * 6 & ! 3 forces + 3 moments at each node + + u%HubPtLoad%NNodes * 6 & ! 3 forces + 3 moments at each node + + u%NacelleLoads%NNodes * 6 & ! 3 forces + 3 moments at each node + + p%NumBl & ! blade pitch command (BlPitchCom) + + 2 ! YawMom and GenTrq + + ! note: all other inputs are ignored + + !.................... + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! (see elastodyn::ed_perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index of the acceleration/load field + ! column 3 is the node + !.................... + + !............... + ! ED input mappings stored in p%Jac_u_indx: + !............... + call AllocAry(p%Jac_u_indx, nu, 3, 'p%Jac_u_indx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + + index = 1 + if (allocated(u%BladePtLoads)) then + !Module/Mesh/Field: u%BladePtLoads(1)%Force = 1; + !Module/Mesh/Field: u%BladePtLoads(1)%Moment = 2; + !Module/Mesh/Field: u%BladePtLoads(2)%Force = 3; + !Module/Mesh/Field: u%BladePtLoads(2)%Moment = 4; + !Module/Mesh/Field: u%BladePtLoads(3)%Force = 5; + !Module/Mesh/Field: u%BladePtLoads(3)%Moment = 6; + do k=1,p%NumBl + + do i_meshField = 1,2 + do i=1,u%BladePtLoads(k)%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField + (k-1)*2 !Module/Mesh/Field: u%BladePtLoads(k)%{Force/Moment} = m + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !i_meshField + end do !k + + end if + + !if MaxBl ever changes (i.e., MaxBl /=3), we need to modify this accordingly: + do i_meshField = 7,8 + do i=1,u%PlatformPtMesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%PlatformPtMesh%Force = 7; u%PlatformPtMesh%Moment = 8; + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + do i_meshField = 9,10 + do i=1,u%TowerPtLoads%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%TowerPtLoads%Force = 9; u%TowerPtLoads%Moment = 10; + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + do i_meshField = 11,12 + do i=1,u%HubPtLoad%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%HubPtLoad%Force = 11; u%HubPtLoad%Moment = 12; + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + do i_meshField = 13,14 + do i=1,u%NacelleLoads%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%NacelleLoads%Force = 13; u%NacelleLoads%Moment = 14; + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do + + do i_meshField = 1,p%NumBl ! scalars + p%Jac_u_indx(index,1) = 15 !Module/Mesh/Field: u%BlPitchCom = 15; + p%Jac_u_indx(index,2) = 1 !index: n/a + p%Jac_u_indx(index,3) = i_meshField !Node: blade + index = index + 1 + end do + + do i_meshField = 16,17 ! scalars + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%YawMom = 16; u%GenTrq = 17; + p%Jac_u_indx(index,2) = 1 !index: j + p%Jac_u_indx(index,3) = 1 !Node: i + index = index + 1 + end do + + !................ + ! input perturbations, du: + !................ + call AllocAry(p%du, 17, 'p%du', ErrStat2, ErrMsg2) ! 17 = number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! p%TipRad is set to 0 for BeamDyn simulations, so we're using a copy of the value from the input file here + ScaleLength = max(p%TipRad, p%TowerHt, 1.0_ReKi) + MaxThrust = 490.0_R8Ki * pi_D / 9.0_R8Ki * ScaleLength**2 + MaxTorque = 122.5_R8Ki * pi_D / 27.0_R8Ki * ScaleLength**3 + + if (allocated(u%BladePtLoads)) then + do k=1,p%NumBl + p%du(2*k-1) = MaxThrust / real(100*p%NumBl*u%BladePtLoads(k)%NNodes,R8Ki) ! u%BladePtLoads(k)%Force = 2*k-1 + p%du(2*k ) = MaxTorque / real(100*p%NumBl*u%BladePtLoads(k)%NNodes,R8Ki) ! u%BladePtLoads(k)%Moment = 2*k + end do !k + else + p%du(1:6) = 0.0_R8Ki + end if + + p%du( 7) = MaxThrust / 100.0_R8Ki ! u%PlatformPtMesh%Force = 7 + p%du( 8) = MaxTorque / 100.0_R8Ki ! u%PlatformPtMesh%Moment = 8 + p%du( 9) = MaxThrust / real(100*u%TowerPtLoads%NNodes,R8Ki) ! u%TowerPtLoads%Force = 9 + p%du(10) = MaxTorque / real(100*u%TowerPtLoads%NNodes,R8Ki) ! u%TowerPtLoads%Moment = 10 + p%du(11) = MaxThrust / 100.0_R8Ki ! u%HubPtLoad%Force = 11 + p%du(12) = MaxTorque / 100.0_R8Ki ! u%HubPtLoad%Moment = 12 + p%du(13) = MaxThrust / 100.0_R8Ki ! u%NacelleLoads%Force = 13 + p%du(14) = MaxTorque / 100.0_R8Ki ! u%NacelleLoads%Moment = 14 + p%du(15) = 2.0_R8Ki * D2R_D ! u%BlPitchCom = 15 + p%du(16) = MaxTorque / 100.0_R8Ki ! u%YawMom = 16 + p%du(17) = MaxTorque / (100.0_R8Ki*p%GBRatio) ! u%GenTrq = 17 + + !Set some limits in case perturbation is very small + do i=1,size(p%du) + p%du(i) = max(p%du(i), MinPerturb) + end do + + !................ + ! names of the columns, InitOut%LinNames_u: + !................ + call AllocAry(InitOut%LinNames_u, nu+1, 'LinNames_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%RotFrame_u, nu+1, 'RotFrame_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%IsLoad_u, nu+1, 'IsLoad_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%IsLoad_u = .true. ! most of ED's inputs are loads; we will override the non-load inputs below. + InitOut%RotFrame_u = .false. + index = 1 + if (allocated(u%BladePtLoads)) then + index_last = index + do k=1,p%NumBl + call PackLoadMesh_Names(u%BladePtLoads(k), 'Blade '//trim(num2lstr(k)), InitOut%LinNames_u, index) + end do + !InitOut%RotFrame_u(index_last:index-1) = .true. ! values on the mesh are in global, not rotating frame + end if + call PackLoadMesh_Names(u%PlatformPtMesh, 'Platform', InitOut%LinNames_u, index) + call PackLoadMesh_Names(u%TowerPtLoads, 'Tower', InitOut%LinNames_u, index) + call PackLoadMesh_Names(u%HubPtLoad, 'Hub', InitOut%LinNames_u, index) + call PackLoadMesh_Names(u%NacelleLoads, 'Nacelle', InitOut%LinNames_u, index) + + do k = 1,p%NumBl ! scalars + InitOut%LinNames_u(index) = 'Blade '//trim(num2lstr(k))//' pitch command, rad' + InitOut%IsLoad_u( index) = .false. + InitOut%RotFrame_u(index) = .true. + index = index + 1 + end do + + InitOut%LinNames_u(index) = 'Yaw moment, Nm' ; index = index + 1 + InitOut%LinNames_u(index) = 'Generator torque, Nm' ; index = index + 1 + InitOut%LinNames_u(index) = 'Extended input: collective blade-pitch command, rad' + InitOut%IsLoad_u( index) = .false. + +END SUBROUTINE ED_Init_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine elastodyn::ed_init_jacobian is consistant with this routine! +SUBROUTINE ED_Perturb_u( p, n, perturb_sign, u, du ) + + TYPE(ED_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(ED_InputType) , INTENT(INOUT) :: u !< perturbed ED inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + + + ! local variables + INTEGER :: fieldIndx + INTEGER :: node + + + fieldIndx = p%Jac_u_indx(n,2) + node = p%Jac_u_indx(n,3) + + du = p%du( p%Jac_u_indx(n,1) ) + + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( p%Jac_u_indx(n,1) ) + + CASE ( 1) !Module/Mesh/Field: u%BladePtLoads(1)%Force = 1 + u%BladePtLoads(1)%Force( fieldIndx,node) = u%BladePtLoads(1)%Force( fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%BladePtLoads(1)%Moment = 2 + u%BladePtLoads(1)%Moment(fieldIndx,node) = u%BladePtLoads(1)%Moment(fieldIndx,node) + du * perturb_sign + CASE ( 3) !Module/Mesh/Field: u%BladePtLoads(2)%Force = 3 + u%BladePtLoads(2)%Force( fieldIndx,node) = u%BladePtLoads(2)%Force( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%BladePtLoads(2)%Moment = 4 + u%BladePtLoads(2)%Moment(fieldIndx,node) = u%BladePtLoads(2)%Moment(fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%BladePtLoads(2)%Force = 5 + u%BladePtLoads(3)%Force( fieldIndx,node) = u%BladePtLoads(3)%Force( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%BladePtLoads(2)%Moment = 6 + u%BladePtLoads(3)%Moment(fieldIndx,node) = u%BladePtLoads(3)%Moment(fieldIndx,node) + du * perturb_sign + + CASE ( 7) !Module/Mesh/Field: u%PlatformPtMesh%Force = 7 + u%PlatformPtMesh%Force( fieldIndx,node) = u%PlatformPtMesh%Force( fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%PlatformPtMesh%Moment = 8 + u%PlatformPtMesh%Moment(fieldIndx,node) = u%PlatformPtMesh%Moment(fieldIndx,node) + du * perturb_sign + + CASE ( 9) !Module/Mesh/Field: u%TowerPtLoads%Force = 9 + u%TowerPtLoads%Force( fieldIndx,node) = u%TowerPtLoads%Force( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%TowerPtLoads%Moment = 10 + u%TowerPtLoads%Moment(fieldIndx,node) = u%TowerPtLoads%Moment(fieldIndx,node) + du * perturb_sign + + CASE (11) !Module/Mesh/Field: u%HubPtLoad%Force = 11 + u%HubPtLoad%Force( fieldIndx,node) = u%HubPtLoad%Force( fieldIndx,node) + du * perturb_sign + CASE (12) !Module/Mesh/Field: u%HubPtLoad%Moment = 12 + u%HubPtLoad%Moment(fieldIndx,node) = u%HubPtLoad%Moment(fieldIndx,node) + du * perturb_sign + + CASE (13) !Module/Mesh/Field: u%NacelleLoads%Force = 13 + u%NacelleLoads%Force( fieldIndx,node) = u%NacelleLoads%Force( fieldIndx,node) + du * perturb_sign + CASE (14) !Module/Mesh/Field: u%NacelleLoads%Moment = 14 + u%NacelleLoads%Moment(fieldIndx,node) = u%NacelleLoads%Moment(fieldIndx,node) + du * perturb_sign + + CASE (15) !Module/Mesh/Field: u%BlPitchCom = 15 + u%BlPitchCom(node) = u%BlPitchCom(node) + du * perturb_sign + CASE (16) !Module/Mesh/Field: u%YawMom = 16 + u%YawMom = u%YawMom + du * perturb_sign + CASE (17) !Module/Mesh/Field: u%GenTrq = 17 + u%GenTrq = u%GenTrq + du * perturb_sign + + END SELECT + +END SUBROUTINE ED_Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the continuous state array. +!! Do not change this without making sure subroutine elastodyn::ed_init_jacobian is consistant with this routine! +SUBROUTINE ED_Perturb_x( p, n, perturb_sign, x, dx ) + + TYPE(ED_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(ED_ContinuousStateType) , INTENT(INOUT) :: x !< perturbed ED states + REAL( R8Ki ) , INTENT( OUT) :: dx !< amount that specific state was perturbed + + + ! local variables + integer(intKi) :: indx + + + if (n > p%DOFs%NActvDOF) then + indx = p%DOFs%PS(n-p%DOFs%NActvDOF) + dx = p%dx( indx ) + + x%QDT( indx ) = x%QDT( indx ) + dx * perturb_sign + else + indx = p%DOFs%PS(n) + dx = p%dx( indx ) + + x%QT( indx ) = x%QT( indx ) + dx * perturb_sign + end if + +END SUBROUTINE ED_Perturb_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine elastodyn::ed_init_jacobian is consistant with this routine! +SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) + + TYPE(ED_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(ED_OutputType) , INTENT(IN ) :: y_p !< ED outputs at \f$ u + \Delta u \f$ or \f$ x + \Delta x \f$ (p=plus) + TYPE(ED_OutputType) , INTENT(IN ) :: y_m !< ED outputs at \f$ u - \Delta u \f$ or \f$ x - \Delta x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta = \Delta u \f$ or \f$ delta = \Delta x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial x_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + INTEGER(IntKi) :: k ! loop over blades + INTEGER(IntKi) :: indx_first ! index indicating next value of dY to be filled + LOGICAL :: Mask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + + + Mask = .false. + Mask(MASKID_TRANSLATIONDISP) = .true. + Mask(MASKID_ORIENTATION) = .true. + Mask(MASKID_ROTATIONVEL) = .true. + + + indx_first = 1 + if (allocated(y_p%BladeLn2Mesh)) then + do k=1,p%NumBl + call PackMotionMesh_dY(y_p%BladeLn2Mesh(k), y_m%BladeLn2Mesh(k), dY, indx_first) + end do + end if + + call PackMotionMesh_dY(y_p%PlatformPtMesh, y_m%PlatformPtMesh, dY, indx_first) + call PackMotionMesh_dY(y_p%TowerLn2Mesh, y_m%TowerLn2Mesh, dY, indx_first) + call PackMotionMesh_dY(y_p%HubPtMotion, y_m%HubPtMotion, dY, indx_first, FieldMask=Mask) + do k=1,p%NumBl + call PackMotionMesh_dY(y_p%BladeRootMotion(k), y_m%BladeRootMotion(k), dY, indx_first) + end do + call PackMotionMesh_dY(y_p%NacelleMotion, y_m%NacelleMotion, dY, indx_first) + + dY(indx_first) = y_p%Yaw - y_m%Yaw; indx_first = indx_first + 1 + dY(indx_first) = y_p%YawRate - y_m%YawRate; indx_first = indx_first + 1 + dY(indx_first) = y_p%HSS_Spd - y_m%HSS_Spd; indx_first = indx_first + 1 + + !indx_last = indx_first + p%NumOuts - 1 + do k=1,p%NumOuts + p%BldNd_TotNumOuts + dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) + end do + + dY = dY / (2.0_R8Ki*delta) + +END SUBROUTINE Compute_dY +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE ED_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, y_op, x_op, dx_op, xd_op, z_op, NeedLogMap ) + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(ED_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ED_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ED_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ED_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ED_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(ED_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 + LOGICAL, OPTIONAL, INTENT(IN ) :: NeedLogMap !< whether a y_op values should contain log maps instead of full orientation matrices + + + + INTEGER(IntKi) :: i, k, index + INTEGER(IntKi) :: ny + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_GetOP' + LOGICAL :: ReturnLogMap + TYPE(ED_ContinuousStateType) :: dx !< derivative of continuous states at operating point + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + !.................................. + IF ( PRESENT( u_op ) ) THEN + if (.not. allocated(u_op)) then + call AllocAry(u_op, size(p%Jac_u_indx,1)+1,'u_op',ErrStat2,ErrMsg2) ! +1 for extended input here + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + index = 1 + if (allocated(u%BladePtLoads)) then + do k=1,p%NumBl + call PackLoadMesh(u%BladePtLoads(k), u_op, index) + end do + end if + call PackLoadMesh(u%PlatformPtMesh, u_op, index) + call PackLoadMesh(u%TowerPtLoads, u_op, index) + call PackLoadMesh(u%HubPtLoad, u_op, index) + call PackLoadMesh(u%NacelleLoads, u_op, index) + + do k = 1,p%NumBl ! scalars + u_op(index) = u%BlPitchCom(k) + index = index + 1 + end do + u_op(index) = u%YawMom ; index = index + 1 + u_op(index) = u%GenTrq ; index = index + 1 + + ! extended input: + u_op(index) = u%BlPitchCom(1) + + do k = 2,p%NumBl + if (.not. EqualRealNos( u%BlPitchCom(1), u%BlPitchCom(k) ) ) then + call SetErrStat(ErrID_Info,"Operating point of collective pitch extended input is invalid because "// & + "the commanded blade pitch angles are not the same for each blade.", ErrStat, ErrMsg, RoutineName) + exit + end if + end do + + END IF + + !.................................. + IF ( PRESENT( y_op ) ) THEN + if (present(NeedLogMap)) then + ReturnLogMap = NeedLogMap + else + ReturnLogMap = .false. + end if + + if (.not. allocated(y_op)) then + ! our operating point includes DCM (orientation) matrices, not just small angles like the perturbation matrices do + ny = p%Jac_ny + y%PlatformPtMesh%NNodes * 6 & ! Jac_ny has 3 for Orientation, but we need 9 at each node + + y%TowerLn2Mesh%NNodes * 6 & ! Jac_ny has 3 for Orientation, but we need 9 at each node + + y%HubPtMotion%NNodes * 6 & ! Jac_ny has 3 for Orientation, but we need 9 at each node + + y%NacelleMotion%NNodes * 6 ! Jac_ny has 3 for Orientation, but we need 9 at each node + + if (allocated(y%BladeLn2Mesh)) then + do k=1,p%NumBl + ny = ny + y%BladeLn2Mesh(k)%NNodes * 6 ! Jac_ny has 3 for Orientation, but we need 9 (at each node on each blade) + end do + end if + do k=1,p%NumBl + ny = ny + y%BladeRootMotion(k)%NNodes * 6 ! Jac_ny has 3 for Orientation, but we need 9 at each node on each blade + end do + + call AllocAry(y_op, ny,'y_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + + + Mask = .false. + Mask(MASKID_TRANSLATIONDISP) = .true. + Mask(MASKID_ORIENTATION) = .true. + Mask(MASKID_ROTATIONVEL) = .true. + + index = 1 + if (allocated(y%BladeLn2Mesh)) then + do k=1,p%NumBl + call PackMotionMesh(y%BladeLn2Mesh(k), y_op, index, UseLogMaps=ReturnLogMap) + end do + end if + call PackMotionMesh(y%PlatformPtMesh, y_op, index, UseLogMaps=ReturnLogMap) + call PackMotionMesh(y%TowerLn2Mesh, y_op, index, UseLogMaps=ReturnLogMap) + call PackMotionMesh(y%HubPtMotion, y_op, index, FieldMask=Mask, UseLogMaps=ReturnLogMap) + do k=1,p%NumBl + call PackMotionMesh(y%BladeRootMotion(k), y_op, index, UseLogMaps=ReturnLogMap) + end do + call PackMotionMesh(y%NacelleMotion, y_op, index, UseLogMaps=ReturnLogMap) + + y_op(index) = y%Yaw ; index = index + 1 + y_op(index) = y%YawRate ; index = index + 1 + y_op(index) = y%HSS_Spd + + do i=1,p%NumOuts + p%BldNd_TotNumOuts + y_op(i+index) = y%WriteOutput(i) + end do + + END IF + + !.................................. + IF ( PRESENT( x_op ) ) THEN + + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%DOFs%NActvDOF * 2,'x_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + do i=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + x_op(i) = x%QT( p%DOFs%PS(i) ) + end do + do i=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + x_op(i+p%DOFs%NActvDOF) = x%QDT( p%DOFs%PS(i) ) + end do + + END IF + + !.................................. + IF ( PRESENT( dx_op ) ) THEN + + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%DOFs%NActvDOF * 2,'dx_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + call ED_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call ED_DestroyContState( dx, ErrStat2, ErrMsg2) + return + end if + + do i=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dx_op(i) = dx%QT( p%DOFs%PS(i) ) + end do + do i=1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + dx_op(i+p%DOFs%NActvDOF) = dx%QDT( p%DOFs%PS(i) ) + end do + + call ED_DestroyContState( dx, ErrStat2, ErrMsg2) + + END IF + + !.................................. + IF ( PRESENT( xd_op ) ) THEN + END IF + + !.................................. + IF ( PRESENT( z_op ) ) THEN + END IF + +END SUBROUTINE ED_GetOP +!---------------------------------------------------------------------------------------------------------------------------------- + + +END MODULE ElastoDyn +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/elastodyn/src/ElastoDyn_AllBldNdOuts_IO.f90 b/OpenFAST/modules/elastodyn/src/ElastoDyn_AllBldNdOuts_IO.f90 new file mode 100644 index 000000000..91c2ed066 --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ElastoDyn_AllBldNdOuts_IO.f90 @@ -0,0 +1,665 @@ +! This module is an add on to ElastoDyn to allow output of blade structural data at each blade node when BeamDyn is not used +! +! Copyright 2016 Envision Energy +! + +MODULE ElastoDyn_AllBldNdOuts_IO + + USE NWTC_Library + USE ElastoDyn_Types + + IMPLICIT NONE + + PRIVATE + + + PUBLIC :: AllBldNdOuts_InitOut + PUBLIC :: Calc_WriteAllBldNdOutput + PUBLIC :: AllBldNdOuts_SetParameters + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen-6 ! The NREL allowed channel name length is usually 20. We are making these of the form B#N###namesuffix + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 14-Dec-2017 10:34:30. + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + + ! Local Span Motions: + + INTEGER(IntKi), PARAMETER :: BldNd_ALx = 1 + INTEGER(IntKi), PARAMETER :: BldNd_ALy = 2 + INTEGER(IntKi), PARAMETER :: BldNd_ALz = 3 + INTEGER(IntKi), PARAMETER :: BldNd_TDx = 4 + INTEGER(IntKi), PARAMETER :: BldNd_TDy = 5 + INTEGER(IntKi), PARAMETER :: BldNd_TDz = 6 + INTEGER(IntKi), PARAMETER :: BldNd_RDx = 7 + INTEGER(IntKi), PARAMETER :: BldNd_RDy = 8 + INTEGER(IntKi), PARAMETER :: BldNd_RDz = 9 + + + ! Local Span Loads: + + INTEGER(IntKi), PARAMETER :: BldNd_MLx = 10 + INTEGER(IntKi), PARAMETER :: BldNd_MLy = 11 + INTEGER(IntKi), PARAMETER :: BldNd_MLz = 12 + INTEGER(IntKi), PARAMETER :: BldNd_FLx = 13 + INTEGER(IntKi), PARAMETER :: BldNd_FLy = 14 + INTEGER(IntKi), PARAMETER :: BldNd_FLz = 15 + INTEGER(IntKi), PARAMETER :: BldNd_MLxNT = 16 + INTEGER(IntKi), PARAMETER :: BldNd_MlyNT = 17 + INTEGER(IntKi), PARAMETER :: BldNd_FLxNT = 18 + INTEGER(IntKi), PARAMETER :: BldNd_FlyNT = 19 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER, PUBLIC :: BldNd_MaxOutPts = 19 + +!End of code generated by Matlab script +! =================================================================================================== + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is blade:node:channel (channel iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteAllBldNdOutput routine as well. +SUBROUTINE AllBldNdOuts_InitOut( InitOut, p, ErrStat, ErrMsg ) + + + TYPE(ED_InitOutputType), INTENT(INOUT) :: InitOut ! output data + TYPE(ED_ParameterType), INTENT(IN ) :: p ! The module parameters + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + INTEGER(IntKi) :: INDX ! Index count within WriteOutput + INTEGER(IntKi) :: IdxBlade ! Counter to which blade we are on + INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(62) :: ChanPrefix ! Name prefix (B#N###) + CHARACTER(6) :: TmpChar ! Temporary char array to hold the node digits (3 places only!!!!) + CHARACTER(*), PARAMETER :: RoutineName = ('AllBldNdOuts_InitOut') + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + ! First set a counter so we know where in the output array we are in + ! NOTE: we populate invalid names as well (some names are not valid outputs for certain configurations). That means we will have zeros in those values. + INDX = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal ElastoDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts) + + ! Populate the header and unit lines for all blades and nodes +#ifndef OUTPUT_CHANNEL_NAMES_AS_DISTANCE + ! ! Warn if we will run into issues with more than 999 nodes. + IF (p%BldNodes > 999 ) CALL SetErrStat(ErrID_Severe,'More than 999 blade nodes in use. Output channel headers will not '// & + 'correctly reflect blade stations beyond 999. Modifications to the variable ChanLen in FAST are required.',ErrStat,ErrMsg,RoutineName) + + ! Populate the header an unit lines for all blades and nodes + ! Loop through all the outputs we requested here: + DO IdxChan=1,p%BldNd_NumOuts + + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + + ! 3 digit node number + WRITE (TmpChar,'(I3.3)') IdxNode + ChanPrefix = 'B' // TRIM(Num2LStr(IdxBlade)) // 'N' // TRIM(TmpChar) + + ! Now write to the header + InitOut%WriteOutputHdr(INDX) = TRIM(ChanPrefix) // TRIM(p%BldNd_OutParam(IdxChan)%Name) + InitOut%WriteOutputUnt(INDX) = p%BldNd_OutParam(IdxChan)%Units + + ! Increment the index to the Header arrays + INDX = INDX + 1 + ENDDO + + END DO + END DO + +#else + ! output format the name of the channel with the distance in cm from the root of the blade instead of by node number. + + ! Loop through all the outputs we requested here: + DO IdxChan=1,p%BldNd_NumOuts + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + + ! Node defined by distance along blade + WRITE (TmpChar,'(I6.6)') NINT( 1000.0_ReKi * p%RNodes( IdxNode ) ) + ChanPrefix = 'B' // TRIM(Num2LStr(IdxBlade)) // '_Z' // TRIM(TmpChar) //'_' + + + ! Now write to the header + InitOut%WriteOutputHdr(INDX) = TRIM(ChanPrefix) // TRIM(p%BldNd_OutParam(IdxChan)%Name) + InitOut%WriteOutputUnt(INDX) = p%BldNd_OutParam(IdxChan)%Units + + ! Increment the index to the Header arrays + INDX = INDX + 1 + ENDDO + + ENDDO + ENDDO + +#endif + + +END SUBROUTINE AllBldNdOuts_InitOut + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine populates the headers with the blade node outputs. The iteration cycle is blade:node:channel (channel iterated +!! fastest). If this iteration order is changed, it should be changed in the Calc_WriteAllBldNdOutput routine as well. +SUBROUTINE Calc_WriteAllBldNdOutput( p, u, m, y, LinAccES, ErrStat, ErrMsg ) + TYPE(ED_ParameterType), INTENT(IN ) :: p ! The module parameters + TYPE(ED_InputType), INTENT(IN ) :: u ! inputs + TYPE(ED_MiscVarType), INTENT(INOUT) :: m ! misc variables + TYPE(ED_OutputType), INTENT(INOUT) :: y ! outputs + REAL(ReKi), INTENT(IN ) :: LinAccES(:,0:,:) ! Total linear acceleration of a point on a blade (point S) in the inertia frame (body E for earth). NOTE: zero index start. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT( OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: OutIdx ! Index count within WriteOutput + INTEGER(IntKi) :: IdxBlade ! Counter to which blade we are on + INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on + INTEGER(IntKi) :: J ! Generic counter for moment and force summation + INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting. + CHARACTER(5) :: ChanPrefix ! Name prefix ( B#N### or B#D#### ) + CHARACTER(2) :: TmpChar ! Temporary char array to hold the node digits (2 places only!!!!) + CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteAllBldNdOutput' +! REAL(ReKi) :: ct, st ! cosine, sine of theta +! REAL(ReKi) :: cp, sp ! cosine, sine of phi +! REAL(ReKi) :: Tmp(3) + REAL(ReKi) :: OutVal ! Temporary variable to hold the value to output to the channel. + + ! Variables used in the CalcOutput routine that are needed here for coordinate transforms + REAL(R8Ki) :: rSPS (3) ! Position vector from the undeflected blade node (point S prime) to the deflected node (point S) + REAL(R8Ki) :: TmpVec (3) ! A temporary vector used in various computations. + REAL(R8Ki) :: TmpVec2 (3) ! A temporary vector. + + + ! Initialize some things + ErrMsg = '' + ErrStat = ErrID_None + + + ! Populate the header an unit lines for all blades and nodes + ! First set a counter so we know where in the output array we are in + OutIdx = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal ElastoDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts) + + ! Loop through all the outputs we requested here: + DO IdxChan=1,p%BldNd_NumOuts + + SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output + CASE (0) ! Invalid channel + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_ALx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( LinAccES(:,IdxNode,IdxBlade), m%CoordSys%n1(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_ALy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( LinAccES(:,IdxNode,IdxBlade), m%CoordSys%n2(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_ALz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( LinAccES(:,IdxNode,IdxBlade), m%CoordSys%n3(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_TDx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + rSPS = m%RtHS%rS0S(:,IdxBlade,IdxNode) - p%RNodes(IdxNode)*m%CoordSys%j3(IdxBlade,:) + y%WriteOutput( OutIdx ) = DOT_PRODUCT( rSPS, m%CoordSys%j1(IdxBlade,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_TDy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + rSPS = m%RtHS%rS0S(:,IdxBlade,IdxNode) - p%RNodes(IdxNode)*m%CoordSys%j3(IdxBlade,:) + y%WriteOutput( OutIdx ) = DOT_PRODUCT( rSPS, m%CoordSys%j2(IdxBlade,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_TDz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + rSPS = m%RtHS%rS0S(:,IdxBlade,IdxNode) - p%RNodes(IdxNode)*m%CoordSys%j3(IdxBlade,:) + y%WriteOutput( OutIdx ) = DOT_PRODUCT( rSPS, m%CoordSys%j3(IdxBlade,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_RDx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,IdxBlade,IdxNode), m%CoordSys%j1(IdxBlade,:) )*R2D + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_RDy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,IdxBlade,IdxNode), m%CoordSys%j2(IdxBlade,:) )*R2D + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_RDz ) ! See note in ElastoDyn.f90 + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + ! y%WriteOutput( OutIdx ) = DOT_PRODUCT( m%RtHS%AngPosHM(:,IdxBlade,IdxNode), m%CoordSys%j3(IdxBlade,:) )*R2D ! this is always zero for FAST + y%WriteOutput( OutIdx ) = 0.0_Reki + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_FLx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( FrcMGagB(), m%CoordSys%n1(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_FLy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( FrcMGagB(), m%CoordSys%n2(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_FLz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( FrcMGagB(), m%CoordSys%n3(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_MLx ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( MomMGagB(), m%CoordSys%n1(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_MLy ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( MomMGagB(), m%CoordSys%n2(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_MLz ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( MomMGagB(), m%CoordSys%n3(IdxBlade,IdxNode,:) ) + OutIdx = OutIdx + 1 + END DO + END DO + + ! Output blade loads in the blade coordinate system. + CASE ( BldNd_FLxNT ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( FrcMGagB(), CoordSysNT1() ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_FLyNT ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( FrcMGagB(), CoordSysNT2() ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_MLxNT ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( MomMGagB(), CoordSysNT1() ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE ( BldNd_MLyNT ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = DOT_PRODUCT( MomMGagB(), CoordSysNT2() ) + OutIdx = OutIdx + 1 + END DO + END DO + + CASE DEFAULT + CALL SetErrStat( ErrID_Severe, "Coding error. Output channel not properly set.",ErrStat,ErrMsg,RoutineName ) + DO IdxBlade=1,p%BldNd_BladesOut + DO IdxNode=1,p%BldNodes + y%WriteOutput( OutIdx ) = 0.0_ReKi + OutIdx = OutIdx + 1 + END DO + END DO + + END SELECT + END DO + +contains +function CoordSysNT1() + REAL(ReKi) :: CoordSysNT1 (3) ! A temporary matrix for removing the structural twist from the local output forces and moments, dimension 1 + ! removed + CoordSysNT1(:) = p%CThetaS(IdxBlade,IdxNode)*m%CoordSys%n1(IdxBlade,IdxNode,:) + p%SThetaS(IdxBlade,IdxNode)*m%CoordSys%n2(IdxBlade,IdxNode,:) + +end function CoordSysNT1 + +function CoordSysNT2() + REAL(ReKi) :: CoordSysNT2 (3) ! A temporary matrix for removing the structural twist from the local output forces and moments, dimension 2 + + CoordSysNT2(:) = -p%SThetaS(IdxBlade,IdxNode)*m%CoordSys%n1(IdxBlade,IdxNode,:) + p%CThetaS(IdxBlade,IdxNode)*m%CoordSys%n2(IdxBlade,IdxNode,:) + +end function CoordSysNT2 + + +function FrcMGagB() + REAL(R8Ki) :: FrcMGagB (3) ! Total force at the blade element (body M) / blade strain gage location (point S) due to the blade above the strain gage. + + ! Initialize FrcMGagB using the tip brake effects: + + FrcMGagB = m%RtHS%FSTipDrag(:,IdxBlade) - p%TipMass(IdxBlade)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,p%TipNode,IdxBlade) ) + + ! Integrate to find FrcMGagB and MomMGagB using all of the nodes / elements above the current strain gage location: + DO J = ( IdxNode + 1 ),p%BldNodes ! Loop through blade nodes / elements above strain gage node + + TmpVec2 = m%RtHS%FSAero(:,IdxBlade,J) - p%MassB(IdxBlade,J)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,J,IdxBlade) ) ! Portion of FrcMGagB associated with element J + FrcMGagB = FrcMGagB + TmpVec2*p%DRNodes(J) + + ENDDO ! J - Blade nodes / elements above strain gage node + + ! Add the effects of 1/2 the strain gage element: + ! NOTE: for the radius in this calculation, assume that there is no + ! shortening effect (due to blade bending) within the element. Thus, + ! the moment arm for the force is 1/4 of p%DRNodes() and the element + ! length is 1/2 of p%DRNodes(). + + TmpVec2 = m%RtHS%FSAero(:,IdxBlade,IdxNode) - p%MassB(IdxBlade,IdxNode)* ( p%Gravity*m%CoordSys%z2 + LinAccES(:,IdxNode,IdxBlade) ) ! Portion of FrcMGagB associated with 1/2 of the strain gage element + FrcMGagB = FrcMGagB + TmpVec2 * 0.5 * p%DRNodes(IdxNode) ! Portion of FrcMGagB associated with 1/2 of the strain gage element + FrcMGagB = 0.001*FrcMGagB ! Convert the local force to kN + +end function FrcMGagB + +function MomMGagB() + REAL(ReKi) :: MomMGagB (3) ! Total moment at the blade element (body M) / blade strain gage location (point S) due to the blade above the strain gage. + + ! Initialize MomMGagB using the tip brake effects: + + TmpVec2 = m%RtHS%FSTipDrag(:,IdxBlade) - p%TipMass(IdxBlade)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,p%TipNode,IdxBlade) ) ! Portion of FrcMGagB + MomMGagB = CROSS_PRODUCT( m%RtHS%rS0S(:,IdxBlade,p%TipNode) - m%RtHS%rS0S(:,IdxBlade,IdxNode), TmpVec2 ) + + ! Integrate to find FrcMGagB and MomMGagB using all of the nodes / elements above the current strain gage location: + DO J = ( IdxNode + 1 ),p%BldNodes ! Loop through blade nodes / elements above strain gage node + + TmpVec2 = m%RtHS%FSAero(:,IdxBlade,J) - p%MassB(IdxBlade,J)*( p%Gravity*m%CoordSys%z2 + LinAccES(:,J,IdxBlade) ) ! Portion of FrcMGagB associated with element J + TmpVec = CROSS_PRODUCT( m%RtHS%rS0S(:,IdxBlade,J) - m%RtHS%rS0S(:,IdxBlade,IdxNode), TmpVec2 ) ! Portion of MomMGagB associated with element J + MomMGagB = MomMGagB + ( TmpVec + m%RtHS%MMAero(:,IdxBlade,J) )*p%DRNodes(J) + + ENDDO ! J - Blade nodes / elements above strain gage node + + ! Add the effects of 1/2 the strain gage element: + ! NOTE: for the radius in this calculation, assume that there is no + ! shortening effect (due to blade bending) within the element. Thus, + ! the moment arm for the force is 1/4 of p%DRNodes() and the element + ! length is 1/2 of p%DRNodes(). + + TmpVec2 = m%RtHS%FSAero(:,IdxBlade,IdxNode) - p%MassB(IdxBlade,IdxNode)* ( p%Gravity*m%CoordSys%z2 + LinAccES(:,IdxNode,IdxBlade) ) ! Portion of FrcMGagB associated with 1/2 of the strain gage element + TmpVec = CROSS_PRODUCT( ( 0.25_R8Ki*p%DRNodes(IdxNode) )*m%CoordSys%j3(IdxBlade,:), TmpVec2 ) ! Portion of MomMGagB associated with 1/2 of the strain gage element + + MomMGagB = MomMGagB + ( TmpVec + m%RtHS%MMAero(:,IdxBlade,IdxNode) )* ( 0.5 *p%DRNodes(IdxNode) ) + MomMGagB = 0.001*MomMGagB ! Convert the local moment to kN-m + +end function MomMGagB + +END SUBROUTINE Calc_WriteAllBldNdOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates and sets the parameters for the nodal outputs. +SUBROUTINE AllBldNdOuts_SetParameters( p, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + + ! Passed variables: + + TYPE(ED_InputFile), INTENT(IN ) :: InputFileData !< Data stored in the module's input file + TYPE(ED_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(IntKi) :: k ! Blade number + integer(IntKi) :: j ! node number + character(*), parameter :: RoutineName = 'AllBldNdOuts_ValidateInputData' + + ErrStat = ErrID_None + ErrMsg = "" + + ! Check if the requested blades exist + IF ( (InputFileData%BldNd_BladesOut < 0_IntKi) .OR. (InputFileData%BldNd_BladesOut > p%NumBl) ) THEN + CALL SetErrStat( ErrID_Warn, " Number of blades to output data at all bladed nodes (BldNd_BladesOut) must be between 0 and "//TRIM(Num2LStr(p%NumBl))//".", ErrStat, ErrMsg, RoutineName) + p%BldNd_BladesOut = 0_IntKi + ELSE + p%BldNd_BladesOut = InputFileData%BldNd_BladesOut + ENDIF + + + ! Check if the requested blade nodes are valid + ! InputFileData%BldNd_BlOutNd + + + + ! Set the parameter to store number of requested Blade Node output sets + IF ( p%BD4Blades .and. InputFileData%BldNd_NumOuts > 0 ) THEN + p%BldNd_BladesOut = 0_IntKi + p%BldNd_NumOuts = 0_IntKi + CALL SetErrStat( ErrID_Warn,' AllBldNdOuts option not available in ElastoDyn when BeamDyn is used. Turning off these outputs.',ErrStat,ErrMsg,"SetPrimaryParameters" ) + ELSE + p%BldNd_NumOuts = InputFileData%BldNd_NumOuts + ENDIF + + ! Set the total number of outputs ( requested channel groups * number requested nodes * number requested blades ) + p%BldNd_TotNumOuts = p%BldNodes*p%BldNd_BladesOut*p%BldNd_NumOuts !p%BldNd_NumOuts * size(p%BldNd_BlOutNd) * size(p%BldNd_BladesOut) + +! ! Check if the blade node array to output is valid: p%BldNd_BlOutNd +! ! TODO: this value is not read in by the input file reading yet, so setting to all blade nodes +! ! -- check if list handed in is of nodes that exist (not sure this is ever checked) +! ! -- copy values over +! +! ! Temporary workaround here: +! ALLOCATE ( p%BldNd_BlOutNd(1:p%BldNodes) , STAT=ErrStat2 ) +! IF ( ErrStat2 /= 0_IntKi ) THEN +! CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the ElastoDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) +! RETURN +! ENDIF +! DO I=1,p%BldNodes ! put all nodes in the list +! p%BldNd_BlOutNd(i) = i +! ENDDO + + +! ! Check if the requested blades are actually in use: +! ! TODO: this value is not read in by the input file reading yet, so setting to all blades +! ! -- check if list handed in is of blades that exist (not sure this is ever checked) +! ! -- copy values over +! ALLOCATE ( p%BldNd_BladesOut(1:p%NumBl), STAT=ErrStat2 ) +! IF ( ErrStat2 /= 0_IntKi ) THEN +! CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the ElastoDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) +! RETURN +! ENDIF +! DO I=1,p%NumBl ! put all blades in the list +! p%BldNd_BladesOut(i) = i +! ENDDO + + if (p%BldNd_TotNumOuts > 0) then + call BldNdOuts_SetOutParam(InputFileData%BldNd_OutList, p, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + end if + + +END SUBROUTINE AllBldNdOuts_SetParameters + + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 14-Dec-2017 10:34:30. +SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: BldNd_OutList(:) !< The list out user-requested outputs + TYPE(ED_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 + + ! Local variables + + 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 :: InvalidOutput(1:BldNd_MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "BldNdOuts_SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(42) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ALX ","ALY ","ALZ ","AX ","AY ","AZ ","FLX ","FLXNT","FLY ","FLYNT", & + "FLZ ","FLZNT","FX ","FXL ","FY ","FYL ","FZ ","FZL ","MLX ","MLXNT", & + "MLY ","MLYNT","MLZ ","MLZNT","MX ","MXL ","MY ","MYL ","MZ ","MZL ", & + "RDX ","RDY ","RDZ ","RX ","RY ","RZ ","TDX ","TDY ","TDZ ","UXB ", & + "UYB ","UZB "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(42) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + BldNd_ALx , BldNd_ALy , BldNd_ALz , BldNd_ALx , BldNd_ALy , BldNd_ALz , BldNd_FLx , BldNd_FLxNT , BldNd_FLy , BldNd_FlyNT , & + BldNd_FLz , BldNd_FLz , BldNd_FLx , BldNd_FLxNT , BldNd_FLy , BldNd_FlyNT , BldNd_FLz , BldNd_FLz , BldNd_MLx , BldNd_MLxNT , & + BldNd_MLy , BldNd_MlyNT , BldNd_MLz , BldNd_MLz , BldNd_MLx , BldNd_MLxNT , BldNd_MLy , BldNd_MlyNT , BldNd_MLz , BldNd_MLz , & + BldNd_RDx , BldNd_RDy , BldNd_RDz , BldNd_RDx , BldNd_RDy , BldNd_RDz , BldNd_TDx , BldNd_TDy , BldNd_TDz , BldNd_TDx , & + BldNd_TDy , BldNd_TDz /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(42) = (/ & ! This lists the units corresponding to the allowed parameters + "(m/s^2)","(m/s^2)","(m/s^2)","(m/s^2)","(m/s^2)","(m/s^2)","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%BldNd_OutParam(1:p%BldNd_NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the ElastoDyn BldNd_OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%BldNd_NumOuts + + p%BldNd_OutParam(I)%Name = BldNd_OutList(I) + OutListTmp = BldNd_OutList(I) + p%BldNd_OutParam(I)%SignM = 1 ! this won't be used + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + IF ( Indx > 0 ) THEN ! we found the channel name + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 + ELSE + p%BldNd_OutParam(I)%Indx = ParamIndxAry(Indx) + p%BldNd_OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%BldNd_OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%BldNd_OutParam(I)%Units = "INVALID" + p%BldNd_OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%BldNd_OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE BldNdOuts_SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +END MODULE ElastoDyn_AllBldNdOuts_IO diff --git a/OpenFAST/modules/elastodyn/src/ElastoDyn_IO.f90 b/OpenFAST/modules/elastodyn/src/ElastoDyn_IO.f90 new file mode 100644 index 000000000..d097d0801 --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ElastoDyn_IO.f90 @@ -0,0 +1,5271 @@ +!********************************************************************************************************************************** +! The ElastoDyn.f90, ElastoDyn_IO.f90 and ElastoDyn_Types.f90 make up the ElastoDyn module of the +! FAST Modularization Framework. ElastoDyn_Types is auto-generated based on FAST_Registry.txt. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! This file is part of ElastoDyn. +! +! 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. +! +!********************************************************************************************************************************** +!> This module contains definitions of compile-time PARAMETERS for the ElastoDyn module. +!! Every variable defined here MUST have the PARAMETER attribute. +MODULE ElastoDyn_Parameters + + USE NWTC_Library + + USE ElastoDyn_AllBldNdOuts_IO + + TYPE(ProgDesc), PARAMETER :: ED_Ver = ProgDesc( 'ElastoDyn', '', '' ) + + REAL(ReKi), PARAMETER :: SmallAngleLimit_Deg = 15.0 ! Largest input angle considered "small" (used as a check on input data), degrees + + + ! Parameters related to degrees of freedom (formerly MODULE DOFs) + + INTEGER(IntKi), PARAMETER :: MaxBl = 3 ! Maximum number of blades allowed in simulation + INTEGER(IntKi), PARAMETER :: NumBE = 1 ! Number of blade-edge modes + INTEGER(IntKi), PARAMETER :: NumBF = 2 ! Number of blade-flap modes + + INTEGER(IntKi), PARAMETER :: DOF_Sg = 1 ! DOF index for platform surge + INTEGER(IntKi), PARAMETER :: DOF_Sw = 2 ! DOF index for platform sway + INTEGER(IntKi), PARAMETER :: DOF_Hv = 3 ! DOF index for platform heave + INTEGER(IntKi), PARAMETER :: DOF_R = 4 ! DOF index for platform roll + INTEGER(IntKi), PARAMETER :: DOF_P = 5 ! DOF index for platform pitch + INTEGER(IntKi), PARAMETER :: DOF_Y = 6 ! DOF index for platform yaw + INTEGER(IntKi), PARAMETER :: DOF_TFA1 = 7 ! DOF index for 1st tower fore-aft mode + INTEGER(IntKi), PARAMETER :: DOF_TSS1 = 8 ! DOF index for 1st tower side-to-side mode + INTEGER(IntKi), PARAMETER :: DOF_TFA2 = 9 ! DOF index for 2nd tower fore-aft mode + INTEGER(IntKi), PARAMETER :: DOF_TSS2 = 10 ! DOF index for 2nd tower side-to-side mode + INTEGER(IntKi), PARAMETER :: DOF_Yaw = 11 ! DOF index for nacelle-yaw + INTEGER(IntKi), PARAMETER :: DOF_RFrl = 12 ! DOF index for rotor-furl + INTEGER(IntKi), PARAMETER :: DOF_GeAz = 13 ! DOF index for the generator azimuth + INTEGER(IntKi), PARAMETER :: DOF_DrTr = 14 ! DOF index for drivetrain rotational-flexibility + INTEGER(IntKi), PARAMETER :: DOF_TFrl = 15 ! DOF index for tail-furl + + INTEGER(IntKi), PARAMETER :: DOF_BE (MaxBl,NumBE) = RESHAPE( & ! DOF indices for blade edge: + (/ 17, 20, 23 /), (/MaxBl,NumBE/) ) ! 1st blade edge mode for blades 1,2, and 3, respectively 17 + 3*(K-1) + INTEGER(IntKi), PARAMETER :: DOF_BF (MaxBl,NumBF) = RESHAPE( & ! DOF indices for blade flap: + (/ 16, 19, 22, & ! 1st blade flap mode for blades 1,2, and 3, respectively 16 + 3*(K-1) + 18, 21, 24 /), (/MaxBl,NumBF/) ) ! 2nd blade flap mode for blades 1,2, and 3, respectively 18 + 3*(K-1) + + + INTEGER(IntKi), PARAMETER :: DOF_Teet = 22 !DOF_TFrl + 2*(NumBE+NumBF)+ 1 ! DOF index for rotor-teeter + INTEGER(IntKi), PARAMETER :: ED_MaxDOFs = 24 + + + INTEGER(IntKi), PARAMETER :: NPA = 9 ! Number of DOFs that contribute to the angular velocity of the tail (body A) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPB = 7 ! Number of DOFs that contribute to the angular velocity of the tower top / baseplate (body B) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPF = 7 ! Number of DOFs that contribute to the angular velocity of the tower elements (body F) in the inertia frame (body F) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPG = 10 ! Number of DOFs that contribute to the angular velocity of the generator (body G) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPL = 11 ! Number of DOFs that contribute to the angular velocity of the low-speed shaft (body L) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPN = 8 ! Number of DOFs that contribute to the angular velocity of the nacelle (body N) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPR = 9 ! Number of DOFs that contribute to the angular velocity of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame. + INTEGER(IntKi), PARAMETER :: NPX = 3 ! Number of DOFs that contribute to the angular velocity of the platform (body X) in the inertia frame. + + INTEGER(IntKi), PARAMETER :: PX(NPX) = (/ DOF_R, DOF_P, DOF_Y /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the platform (body X) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PF(NPF) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2 /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the tower elements (body F) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PB(NPB) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2 /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the tower top / baseplate (body B) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PN(NPN) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the nacelle (body N) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PR(NPR) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PL(NPL) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl, DOF_GeAz, DOF_DrTr /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the low-speed shaft (body L) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PG(NPG) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_RFrl, DOF_GeAz /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the generator (body G) in the inertia frame. + INTEGER(IntKi), PARAMETER :: PA(NPA) = (/ DOF_R, DOF_P, DOF_Y, DOF_TFA1, DOF_TSS1, DOF_TFA2, DOF_TSS2, DOF_Yaw, DOF_TFrl /) ! Array of DOF indices (pointers) that contribute to the angular velocity of the tail (body A) in the inertia frame. + + + ! Parameters related to coupling scheme + + INTEGER(IntKi), PARAMETER :: Method_RK4 = 1 + INTEGER(IntKi), PARAMETER :: Method_AB4 = 2 + INTEGER(IntKi), PARAMETER :: Method_ABM4 = 3 + + + INTEGER(IntKi), PARAMETER :: PolyOrd = 6 ! Order of the polynomial describing the mode shape + + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 08-Jun-2020 13:26:29. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Blade 1 Tip Motions: + + INTEGER(IntKi), PARAMETER :: TipDxc1 = 1 + INTEGER(IntKi), PARAMETER :: TipDyc1 = 2 + INTEGER(IntKi), PARAMETER :: TipDzc1 = 3 + INTEGER(IntKi), PARAMETER :: TipDxb1 = 4 + INTEGER(IntKi), PARAMETER :: TipDyb1 = 5 + INTEGER(IntKi), PARAMETER :: TipALxb1 = 6 + INTEGER(IntKi), PARAMETER :: TipALyb1 = 7 + INTEGER(IntKi), PARAMETER :: TipALzb1 = 8 + INTEGER(IntKi), PARAMETER :: TipRDxb1 = 9 + INTEGER(IntKi), PARAMETER :: TipRDyb1 = 10 + INTEGER(IntKi), PARAMETER :: TipRDzc1 = 11 + INTEGER(IntKi), PARAMETER :: TipClrnc1 = 12 + + + ! Blade 2 Tip Motions: + + INTEGER(IntKi), PARAMETER :: TipDxc2 = 13 + INTEGER(IntKi), PARAMETER :: TipDyc2 = 14 + INTEGER(IntKi), PARAMETER :: TipDzc2 = 15 + INTEGER(IntKi), PARAMETER :: TipDxb2 = 16 + INTEGER(IntKi), PARAMETER :: TipDyb2 = 17 + INTEGER(IntKi), PARAMETER :: TipALxb2 = 18 + INTEGER(IntKi), PARAMETER :: TipALyb2 = 19 + INTEGER(IntKi), PARAMETER :: TipALzb2 = 20 + INTEGER(IntKi), PARAMETER :: TipRDxb2 = 21 + INTEGER(IntKi), PARAMETER :: TipRDyb2 = 22 + INTEGER(IntKi), PARAMETER :: TipRDzc2 = 23 + INTEGER(IntKi), PARAMETER :: TipClrnc2 = 24 + + + ! Blade 3 Tip Motions: + + INTEGER(IntKi), PARAMETER :: TipDxc3 = 25 + INTEGER(IntKi), PARAMETER :: TipDyc3 = 26 + INTEGER(IntKi), PARAMETER :: TipDzc3 = 27 + INTEGER(IntKi), PARAMETER :: TipDxb3 = 28 + INTEGER(IntKi), PARAMETER :: TipDyb3 = 29 + INTEGER(IntKi), PARAMETER :: TipALxb3 = 30 + INTEGER(IntKi), PARAMETER :: TipALyb3 = 31 + INTEGER(IntKi), PARAMETER :: TipALzb3 = 32 + INTEGER(IntKi), PARAMETER :: TipRDxb3 = 33 + INTEGER(IntKi), PARAMETER :: TipRDyb3 = 34 + INTEGER(IntKi), PARAMETER :: TipRDzc3 = 35 + INTEGER(IntKi), PARAMETER :: TipClrnc3 = 36 + + + ! Blade 1 Local Span Motions: + + INTEGER(IntKi), PARAMETER :: Spn1ALxb1 = 37 + INTEGER(IntKi), PARAMETER :: Spn1ALyb1 = 38 + INTEGER(IntKi), PARAMETER :: Spn1ALzb1 = 39 + INTEGER(IntKi), PARAMETER :: Spn2ALxb1 = 40 + INTEGER(IntKi), PARAMETER :: Spn2ALyb1 = 41 + INTEGER(IntKi), PARAMETER :: Spn2ALzb1 = 42 + INTEGER(IntKi), PARAMETER :: Spn3ALxb1 = 43 + INTEGER(IntKi), PARAMETER :: Spn3ALyb1 = 44 + INTEGER(IntKi), PARAMETER :: Spn3ALzb1 = 45 + INTEGER(IntKi), PARAMETER :: Spn4ALxb1 = 46 + INTEGER(IntKi), PARAMETER :: Spn4ALyb1 = 47 + INTEGER(IntKi), PARAMETER :: Spn4ALzb1 = 48 + INTEGER(IntKi), PARAMETER :: Spn5ALxb1 = 49 + INTEGER(IntKi), PARAMETER :: Spn5ALyb1 = 50 + INTEGER(IntKi), PARAMETER :: Spn5ALzb1 = 51 + INTEGER(IntKi), PARAMETER :: Spn6ALxb1 = 52 + INTEGER(IntKi), PARAMETER :: Spn6ALyb1 = 53 + INTEGER(IntKi), PARAMETER :: Spn6ALzb1 = 54 + INTEGER(IntKi), PARAMETER :: Spn7ALxb1 = 55 + INTEGER(IntKi), PARAMETER :: Spn7ALyb1 = 56 + INTEGER(IntKi), PARAMETER :: Spn7ALzb1 = 57 + INTEGER(IntKi), PARAMETER :: Spn8ALxb1 = 58 + INTEGER(IntKi), PARAMETER :: Spn8ALyb1 = 59 + INTEGER(IntKi), PARAMETER :: Spn8ALzb1 = 60 + INTEGER(IntKi), PARAMETER :: Spn9ALxb1 = 61 + INTEGER(IntKi), PARAMETER :: Spn9ALyb1 = 62 + INTEGER(IntKi), PARAMETER :: Spn9ALzb1 = 63 + INTEGER(IntKi), PARAMETER :: Spn1TDxb1 = 64 + INTEGER(IntKi), PARAMETER :: Spn1TDyb1 = 65 + INTEGER(IntKi), PARAMETER :: Spn1TDzb1 = 66 + INTEGER(IntKi), PARAMETER :: Spn2TDxb1 = 67 + INTEGER(IntKi), PARAMETER :: Spn2TDyb1 = 68 + INTEGER(IntKi), PARAMETER :: Spn2TDzb1 = 69 + INTEGER(IntKi), PARAMETER :: Spn3TDxb1 = 70 + INTEGER(IntKi), PARAMETER :: Spn3TDyb1 = 71 + INTEGER(IntKi), PARAMETER :: Spn3TDzb1 = 72 + INTEGER(IntKi), PARAMETER :: Spn4TDxb1 = 73 + INTEGER(IntKi), PARAMETER :: Spn4TDyb1 = 74 + INTEGER(IntKi), PARAMETER :: Spn4TDzb1 = 75 + INTEGER(IntKi), PARAMETER :: Spn5TDxb1 = 76 + INTEGER(IntKi), PARAMETER :: Spn5TDyb1 = 77 + INTEGER(IntKi), PARAMETER :: Spn5TDzb1 = 78 + INTEGER(IntKi), PARAMETER :: Spn6TDxb1 = 79 + INTEGER(IntKi), PARAMETER :: Spn6TDyb1 = 80 + INTEGER(IntKi), PARAMETER :: Spn6TDzb1 = 81 + INTEGER(IntKi), PARAMETER :: Spn7TDxb1 = 82 + INTEGER(IntKi), PARAMETER :: Spn7TDyb1 = 83 + INTEGER(IntKi), PARAMETER :: Spn7TDzb1 = 84 + INTEGER(IntKi), PARAMETER :: Spn8TDxb1 = 85 + INTEGER(IntKi), PARAMETER :: Spn8TDyb1 = 86 + INTEGER(IntKi), PARAMETER :: Spn8TDzb1 = 87 + INTEGER(IntKi), PARAMETER :: Spn9TDxb1 = 88 + INTEGER(IntKi), PARAMETER :: Spn9TDyb1 = 89 + INTEGER(IntKi), PARAMETER :: Spn9TDzb1 = 90 + INTEGER(IntKi), PARAMETER :: Spn1RDxb1 = 91 + INTEGER(IntKi), PARAMETER :: Spn1RDyb1 = 92 + INTEGER(IntKi), PARAMETER :: Spn1RDzb1 = 93 + INTEGER(IntKi), PARAMETER :: Spn2RDxb1 = 94 + INTEGER(IntKi), PARAMETER :: Spn2RDyb1 = 95 + INTEGER(IntKi), PARAMETER :: Spn2RDzb1 = 96 + INTEGER(IntKi), PARAMETER :: Spn3RDxb1 = 97 + INTEGER(IntKi), PARAMETER :: Spn3RDyb1 = 98 + INTEGER(IntKi), PARAMETER :: Spn3RDzb1 = 99 + INTEGER(IntKi), PARAMETER :: Spn4RDxb1 = 100 + INTEGER(IntKi), PARAMETER :: Spn4RDyb1 = 101 + INTEGER(IntKi), PARAMETER :: Spn4RDzb1 = 102 + INTEGER(IntKi), PARAMETER :: Spn5RDxb1 = 103 + INTEGER(IntKi), PARAMETER :: Spn5RDyb1 = 104 + INTEGER(IntKi), PARAMETER :: Spn5RDzb1 = 105 + INTEGER(IntKi), PARAMETER :: Spn6RDxb1 = 106 + INTEGER(IntKi), PARAMETER :: Spn6RDyb1 = 107 + INTEGER(IntKi), PARAMETER :: Spn6RDzb1 = 108 + INTEGER(IntKi), PARAMETER :: Spn7RDxb1 = 109 + INTEGER(IntKi), PARAMETER :: Spn7RDyb1 = 110 + INTEGER(IntKi), PARAMETER :: Spn7RDzb1 = 111 + INTEGER(IntKi), PARAMETER :: Spn8RDxb1 = 112 + INTEGER(IntKi), PARAMETER :: Spn8RDyb1 = 113 + INTEGER(IntKi), PARAMETER :: Spn8RDzb1 = 114 + INTEGER(IntKi), PARAMETER :: Spn9RDxb1 = 115 + INTEGER(IntKi), PARAMETER :: Spn9RDyb1 = 116 + INTEGER(IntKi), PARAMETER :: Spn9RDzb1 = 117 + + + ! Blade 2 Local Span Motions: + + INTEGER(IntKi), PARAMETER :: Spn1ALxb2 = 118 + INTEGER(IntKi), PARAMETER :: Spn1ALyb2 = 119 + INTEGER(IntKi), PARAMETER :: Spn1ALzb2 = 120 + INTEGER(IntKi), PARAMETER :: Spn2ALxb2 = 121 + INTEGER(IntKi), PARAMETER :: Spn2ALyb2 = 122 + INTEGER(IntKi), PARAMETER :: Spn2ALzb2 = 123 + INTEGER(IntKi), PARAMETER :: Spn3ALxb2 = 124 + INTEGER(IntKi), PARAMETER :: Spn3ALyb2 = 125 + INTEGER(IntKi), PARAMETER :: Spn3ALzb2 = 126 + INTEGER(IntKi), PARAMETER :: Spn4ALxb2 = 127 + INTEGER(IntKi), PARAMETER :: Spn4ALyb2 = 128 + INTEGER(IntKi), PARAMETER :: Spn4ALzb2 = 129 + INTEGER(IntKi), PARAMETER :: Spn5ALxb2 = 130 + INTEGER(IntKi), PARAMETER :: Spn5ALyb2 = 131 + INTEGER(IntKi), PARAMETER :: Spn5ALzb2 = 132 + INTEGER(IntKi), PARAMETER :: Spn6ALxb2 = 133 + INTEGER(IntKi), PARAMETER :: Spn6ALyb2 = 134 + INTEGER(IntKi), PARAMETER :: Spn6ALzb2 = 135 + INTEGER(IntKi), PARAMETER :: Spn7ALxb2 = 136 + INTEGER(IntKi), PARAMETER :: Spn7ALyb2 = 137 + INTEGER(IntKi), PARAMETER :: Spn7ALzb2 = 138 + INTEGER(IntKi), PARAMETER :: Spn8ALxb2 = 139 + INTEGER(IntKi), PARAMETER :: Spn8ALyb2 = 140 + INTEGER(IntKi), PARAMETER :: Spn8ALzb2 = 141 + INTEGER(IntKi), PARAMETER :: Spn9ALxb2 = 142 + INTEGER(IntKi), PARAMETER :: Spn9ALyb2 = 143 + INTEGER(IntKi), PARAMETER :: Spn9ALzb2 = 144 + INTEGER(IntKi), PARAMETER :: Spn1TDxb2 = 145 + INTEGER(IntKi), PARAMETER :: Spn1TDyb2 = 146 + INTEGER(IntKi), PARAMETER :: Spn1TDzb2 = 147 + INTEGER(IntKi), PARAMETER :: Spn2TDxb2 = 148 + INTEGER(IntKi), PARAMETER :: Spn2TDyb2 = 149 + INTEGER(IntKi), PARAMETER :: Spn2TDzb2 = 150 + INTEGER(IntKi), PARAMETER :: Spn3TDxb2 = 151 + INTEGER(IntKi), PARAMETER :: Spn3TDyb2 = 152 + INTEGER(IntKi), PARAMETER :: Spn3TDzb2 = 153 + INTEGER(IntKi), PARAMETER :: Spn4TDxb2 = 154 + INTEGER(IntKi), PARAMETER :: Spn4TDyb2 = 155 + INTEGER(IntKi), PARAMETER :: Spn4TDzb2 = 156 + INTEGER(IntKi), PARAMETER :: Spn5TDxb2 = 157 + INTEGER(IntKi), PARAMETER :: Spn5TDyb2 = 158 + INTEGER(IntKi), PARAMETER :: Spn5TDzb2 = 159 + INTEGER(IntKi), PARAMETER :: Spn6TDxb2 = 160 + INTEGER(IntKi), PARAMETER :: Spn6TDyb2 = 161 + INTEGER(IntKi), PARAMETER :: Spn6TDzb2 = 162 + INTEGER(IntKi), PARAMETER :: Spn7TDxb2 = 163 + INTEGER(IntKi), PARAMETER :: Spn7TDyb2 = 164 + INTEGER(IntKi), PARAMETER :: Spn7TDzb2 = 165 + INTEGER(IntKi), PARAMETER :: Spn8TDxb2 = 166 + INTEGER(IntKi), PARAMETER :: Spn8TDyb2 = 167 + INTEGER(IntKi), PARAMETER :: Spn8TDzb2 = 168 + INTEGER(IntKi), PARAMETER :: Spn9TDxb2 = 169 + INTEGER(IntKi), PARAMETER :: Spn9TDyb2 = 170 + INTEGER(IntKi), PARAMETER :: Spn9TDzb2 = 171 + INTEGER(IntKi), PARAMETER :: Spn1RDxb2 = 172 + INTEGER(IntKi), PARAMETER :: Spn1RDyb2 = 173 + INTEGER(IntKi), PARAMETER :: Spn1RDzb2 = 174 + INTEGER(IntKi), PARAMETER :: Spn2RDxb2 = 175 + INTEGER(IntKi), PARAMETER :: Spn2RDyb2 = 176 + INTEGER(IntKi), PARAMETER :: Spn2RDzb2 = 177 + INTEGER(IntKi), PARAMETER :: Spn3RDxb2 = 178 + INTEGER(IntKi), PARAMETER :: Spn3RDyb2 = 179 + INTEGER(IntKi), PARAMETER :: Spn3RDzb2 = 180 + INTEGER(IntKi), PARAMETER :: Spn4RDxb2 = 181 + INTEGER(IntKi), PARAMETER :: Spn4RDyb2 = 182 + INTEGER(IntKi), PARAMETER :: Spn4RDzb2 = 183 + INTEGER(IntKi), PARAMETER :: Spn5RDxb2 = 184 + INTEGER(IntKi), PARAMETER :: Spn5RDyb2 = 185 + INTEGER(IntKi), PARAMETER :: Spn5RDzb2 = 186 + INTEGER(IntKi), PARAMETER :: Spn6RDxb2 = 187 + INTEGER(IntKi), PARAMETER :: Spn6RDyb2 = 188 + INTEGER(IntKi), PARAMETER :: Spn6RDzb2 = 189 + INTEGER(IntKi), PARAMETER :: Spn7RDxb2 = 190 + INTEGER(IntKi), PARAMETER :: Spn7RDyb2 = 191 + INTEGER(IntKi), PARAMETER :: Spn7RDzb2 = 192 + INTEGER(IntKi), PARAMETER :: Spn8RDxb2 = 193 + INTEGER(IntKi), PARAMETER :: Spn8RDyb2 = 194 + INTEGER(IntKi), PARAMETER :: Spn8RDzb2 = 195 + INTEGER(IntKi), PARAMETER :: Spn9RDxb2 = 196 + INTEGER(IntKi), PARAMETER :: Spn9RDyb2 = 197 + INTEGER(IntKi), PARAMETER :: Spn9RDzb2 = 198 + + + ! Blade 3 Local Span Motions: + + INTEGER(IntKi), PARAMETER :: Spn1ALxb3 = 199 + INTEGER(IntKi), PARAMETER :: Spn1ALyb3 = 200 + INTEGER(IntKi), PARAMETER :: Spn1ALzb3 = 201 + INTEGER(IntKi), PARAMETER :: Spn2ALxb3 = 202 + INTEGER(IntKi), PARAMETER :: Spn2ALyb3 = 203 + INTEGER(IntKi), PARAMETER :: Spn2ALzb3 = 204 + INTEGER(IntKi), PARAMETER :: Spn3ALxb3 = 205 + INTEGER(IntKi), PARAMETER :: Spn3ALyb3 = 206 + INTEGER(IntKi), PARAMETER :: Spn3ALzb3 = 207 + INTEGER(IntKi), PARAMETER :: Spn4ALxb3 = 208 + INTEGER(IntKi), PARAMETER :: Spn4ALyb3 = 209 + INTEGER(IntKi), PARAMETER :: Spn4ALzb3 = 210 + INTEGER(IntKi), PARAMETER :: Spn5ALxb3 = 211 + INTEGER(IntKi), PARAMETER :: Spn5ALyb3 = 212 + INTEGER(IntKi), PARAMETER :: Spn5ALzb3 = 213 + INTEGER(IntKi), PARAMETER :: Spn6ALxb3 = 214 + INTEGER(IntKi), PARAMETER :: Spn6ALyb3 = 215 + INTEGER(IntKi), PARAMETER :: Spn6ALzb3 = 216 + INTEGER(IntKi), PARAMETER :: Spn7ALxb3 = 217 + INTEGER(IntKi), PARAMETER :: Spn7ALyb3 = 218 + INTEGER(IntKi), PARAMETER :: Spn7ALzb3 = 219 + INTEGER(IntKi), PARAMETER :: Spn8ALxb3 = 220 + INTEGER(IntKi), PARAMETER :: Spn8ALyb3 = 221 + INTEGER(IntKi), PARAMETER :: Spn8ALzb3 = 222 + INTEGER(IntKi), PARAMETER :: Spn9ALxb3 = 223 + INTEGER(IntKi), PARAMETER :: Spn9ALyb3 = 224 + INTEGER(IntKi), PARAMETER :: Spn9ALzb3 = 225 + INTEGER(IntKi), PARAMETER :: Spn1TDxb3 = 226 + INTEGER(IntKi), PARAMETER :: Spn1TDyb3 = 227 + INTEGER(IntKi), PARAMETER :: Spn1TDzb3 = 228 + INTEGER(IntKi), PARAMETER :: Spn2TDxb3 = 229 + INTEGER(IntKi), PARAMETER :: Spn2TDyb3 = 230 + INTEGER(IntKi), PARAMETER :: Spn2TDzb3 = 231 + INTEGER(IntKi), PARAMETER :: Spn3TDxb3 = 232 + INTEGER(IntKi), PARAMETER :: Spn3TDyb3 = 233 + INTEGER(IntKi), PARAMETER :: Spn3TDzb3 = 234 + INTEGER(IntKi), PARAMETER :: Spn4TDxb3 = 235 + INTEGER(IntKi), PARAMETER :: Spn4TDyb3 = 236 + INTEGER(IntKi), PARAMETER :: Spn4TDzb3 = 237 + INTEGER(IntKi), PARAMETER :: Spn5TDxb3 = 238 + INTEGER(IntKi), PARAMETER :: Spn5TDyb3 = 239 + INTEGER(IntKi), PARAMETER :: Spn5TDzb3 = 240 + INTEGER(IntKi), PARAMETER :: Spn6TDxb3 = 241 + INTEGER(IntKi), PARAMETER :: Spn6TDyb3 = 242 + INTEGER(IntKi), PARAMETER :: Spn6TDzb3 = 243 + INTEGER(IntKi), PARAMETER :: Spn7TDxb3 = 244 + INTEGER(IntKi), PARAMETER :: Spn7TDyb3 = 245 + INTEGER(IntKi), PARAMETER :: Spn7TDzb3 = 246 + INTEGER(IntKi), PARAMETER :: Spn8TDxb3 = 247 + INTEGER(IntKi), PARAMETER :: Spn8TDyb3 = 248 + INTEGER(IntKi), PARAMETER :: Spn8TDzb3 = 249 + INTEGER(IntKi), PARAMETER :: Spn9TDxb3 = 250 + INTEGER(IntKi), PARAMETER :: Spn9TDyb3 = 251 + INTEGER(IntKi), PARAMETER :: Spn9TDzb3 = 252 + INTEGER(IntKi), PARAMETER :: Spn1RDxb3 = 253 + INTEGER(IntKi), PARAMETER :: Spn1RDyb3 = 254 + INTEGER(IntKi), PARAMETER :: Spn1RDzb3 = 255 + INTEGER(IntKi), PARAMETER :: Spn2RDxb3 = 256 + INTEGER(IntKi), PARAMETER :: Spn2RDyb3 = 257 + INTEGER(IntKi), PARAMETER :: Spn2RDzb3 = 258 + INTEGER(IntKi), PARAMETER :: Spn3RDxb3 = 259 + INTEGER(IntKi), PARAMETER :: Spn3RDyb3 = 260 + INTEGER(IntKi), PARAMETER :: Spn3RDzb3 = 261 + INTEGER(IntKi), PARAMETER :: Spn4RDxb3 = 262 + INTEGER(IntKi), PARAMETER :: Spn4RDyb3 = 263 + INTEGER(IntKi), PARAMETER :: Spn4RDzb3 = 264 + INTEGER(IntKi), PARAMETER :: Spn5RDxb3 = 265 + INTEGER(IntKi), PARAMETER :: Spn5RDyb3 = 266 + INTEGER(IntKi), PARAMETER :: Spn5RDzb3 = 267 + INTEGER(IntKi), PARAMETER :: Spn6RDxb3 = 268 + INTEGER(IntKi), PARAMETER :: Spn6RDyb3 = 269 + INTEGER(IntKi), PARAMETER :: Spn6RDzb3 = 270 + INTEGER(IntKi), PARAMETER :: Spn7RDxb3 = 271 + INTEGER(IntKi), PARAMETER :: Spn7RDyb3 = 272 + INTEGER(IntKi), PARAMETER :: Spn7RDzb3 = 273 + INTEGER(IntKi), PARAMETER :: Spn8RDxb3 = 274 + INTEGER(IntKi), PARAMETER :: Spn8RDyb3 = 275 + INTEGER(IntKi), PARAMETER :: Spn8RDzb3 = 276 + INTEGER(IntKi), PARAMETER :: Spn9RDxb3 = 277 + INTEGER(IntKi), PARAMETER :: Spn9RDyb3 = 278 + INTEGER(IntKi), PARAMETER :: Spn9RDzb3 = 279 + + + ! Blade Pitch Motions: + + INTEGER(IntKi), PARAMETER :: PtchPMzc1 = 280 + INTEGER(IntKi), PARAMETER :: PtchPMzc2 = 281 + INTEGER(IntKi), PARAMETER :: PtchPMzc3 = 282 + + + ! Teeter Motions: + + INTEGER(IntKi), PARAMETER :: TeetPya = 283 + INTEGER(IntKi), PARAMETER :: TeetVya = 284 + INTEGER(IntKi), PARAMETER :: TeetAya = 285 + + + ! Shaft Motions: + + INTEGER(IntKi), PARAMETER :: LSSTipPxa = 286 + INTEGER(IntKi), PARAMETER :: LSSTipVxa = 287 + INTEGER(IntKi), PARAMETER :: LSSTipAxa = 288 + INTEGER(IntKi), PARAMETER :: LSSGagPxa = 289 + INTEGER(IntKi), PARAMETER :: LSSGagVxa = 290 + INTEGER(IntKi), PARAMETER :: LSSGagAxa = 291 + INTEGER(IntKi), PARAMETER :: HSShftV = 292 + INTEGER(IntKi), PARAMETER :: HSShftA = 293 + + + ! Nacelle IMU Motions: + + INTEGER(IntKi), PARAMETER :: NcIMUTVxs = 294 + INTEGER(IntKi), PARAMETER :: NcIMUTVys = 295 + INTEGER(IntKi), PARAMETER :: NcIMUTVzs = 296 + INTEGER(IntKi), PARAMETER :: NcIMUTAxs = 297 + INTEGER(IntKi), PARAMETER :: NcIMUTAys = 298 + INTEGER(IntKi), PARAMETER :: NcIMUTAzs = 299 + INTEGER(IntKi), PARAMETER :: NcIMURVxs = 300 + INTEGER(IntKi), PARAMETER :: NcIMURVys = 301 + INTEGER(IntKi), PARAMETER :: NcIMURVzs = 302 + INTEGER(IntKi), PARAMETER :: NcIMURAxs = 303 + INTEGER(IntKi), PARAMETER :: NcIMURAys = 304 + INTEGER(IntKi), PARAMETER :: NcIMURAzs = 305 + + + ! Rotor-Furl Motions: + + INTEGER(IntKi), PARAMETER :: RotFurlP = 306 + INTEGER(IntKi), PARAMETER :: RotFurlV = 307 + INTEGER(IntKi), PARAMETER :: RotFurlA = 308 + + + ! Tail-Furl Motions: + + INTEGER(IntKi), PARAMETER :: TailFurlP = 309 + INTEGER(IntKi), PARAMETER :: TailFurlV = 310 + INTEGER(IntKi), PARAMETER :: TailFurlA = 311 + + + ! Nacelle Yaw Motions: + + INTEGER(IntKi), PARAMETER :: YawPzn = 312 + INTEGER(IntKi), PARAMETER :: YawVzn = 313 + INTEGER(IntKi), PARAMETER :: YawAzn = 314 + + + ! Tower-Top / Yaw Bearing Motions: + + INTEGER(IntKi), PARAMETER :: TwrTpTDxi = 315 + INTEGER(IntKi), PARAMETER :: TwrTpTDyi = 316 + INTEGER(IntKi), PARAMETER :: TwrTpTDzi = 317 + INTEGER(IntKi), PARAMETER :: YawBrTDxp = 318 + INTEGER(IntKi), PARAMETER :: YawBrTDyp = 319 + INTEGER(IntKi), PARAMETER :: YawBrTDzp = 320 + INTEGER(IntKi), PARAMETER :: YawBrTDxt = 321 + INTEGER(IntKi), PARAMETER :: YawBrTDyt = 322 + INTEGER(IntKi), PARAMETER :: YawBrTDzt = 323 + INTEGER(IntKi), PARAMETER :: YawBrTAxp = 324 + INTEGER(IntKi), PARAMETER :: YawBrTAyp = 325 + INTEGER(IntKi), PARAMETER :: YawBrTAzp = 326 + INTEGER(IntKi), PARAMETER :: YawBrRDxt = 327 + INTEGER(IntKi), PARAMETER :: YawBrRDyt = 328 + INTEGER(IntKi), PARAMETER :: YawBrRDzt = 329 + INTEGER(IntKi), PARAMETER :: YawBrRVxp = 330 + INTEGER(IntKi), PARAMETER :: YawBrRVyp = 331 + INTEGER(IntKi), PARAMETER :: YawBrRVzp = 332 + INTEGER(IntKi), PARAMETER :: YawBrRAxp = 333 + INTEGER(IntKi), PARAMETER :: YawBrRAyp = 334 + INTEGER(IntKi), PARAMETER :: YawBrRAzp = 335 + + + ! Local Tower Motions: + + INTEGER(IntKi), PARAMETER :: TwHt1ALxt = 336 + INTEGER(IntKi), PARAMETER :: TwHt1ALyt = 337 + INTEGER(IntKi), PARAMETER :: TwHt1ALzt = 338 + INTEGER(IntKi), PARAMETER :: TwHt2ALxt = 339 + INTEGER(IntKi), PARAMETER :: TwHt2ALyt = 340 + INTEGER(IntKi), PARAMETER :: TwHt2ALzt = 341 + INTEGER(IntKi), PARAMETER :: TwHt3ALxt = 342 + INTEGER(IntKi), PARAMETER :: TwHt3ALyt = 343 + INTEGER(IntKi), PARAMETER :: TwHt3ALzt = 344 + INTEGER(IntKi), PARAMETER :: TwHt4ALxt = 345 + INTEGER(IntKi), PARAMETER :: TwHt4ALyt = 346 + INTEGER(IntKi), PARAMETER :: TwHt4ALzt = 347 + INTEGER(IntKi), PARAMETER :: TwHt5ALxt = 348 + INTEGER(IntKi), PARAMETER :: TwHt5ALyt = 349 + INTEGER(IntKi), PARAMETER :: TwHt5ALzt = 350 + INTEGER(IntKi), PARAMETER :: TwHt6ALxt = 351 + INTEGER(IntKi), PARAMETER :: TwHt6ALyt = 352 + INTEGER(IntKi), PARAMETER :: TwHt6ALzt = 353 + INTEGER(IntKi), PARAMETER :: TwHt7ALxt = 354 + INTEGER(IntKi), PARAMETER :: TwHt7ALyt = 355 + INTEGER(IntKi), PARAMETER :: TwHt7ALzt = 356 + INTEGER(IntKi), PARAMETER :: TwHt8ALxt = 357 + INTEGER(IntKi), PARAMETER :: TwHt8ALyt = 358 + INTEGER(IntKi), PARAMETER :: TwHt8ALzt = 359 + INTEGER(IntKi), PARAMETER :: TwHt9ALxt = 360 + INTEGER(IntKi), PARAMETER :: TwHt9ALyt = 361 + INTEGER(IntKi), PARAMETER :: TwHt9ALzt = 362 + INTEGER(IntKi), PARAMETER :: TwHt1TDxt = 363 + INTEGER(IntKi), PARAMETER :: TwHt1TDyt = 364 + INTEGER(IntKi), PARAMETER :: TwHt1TDzt = 365 + INTEGER(IntKi), PARAMETER :: TwHt2TDxt = 366 + INTEGER(IntKi), PARAMETER :: TwHt2TDyt = 367 + INTEGER(IntKi), PARAMETER :: TwHt2TDzt = 368 + INTEGER(IntKi), PARAMETER :: TwHt3TDxt = 369 + INTEGER(IntKi), PARAMETER :: TwHt3TDyt = 370 + INTEGER(IntKi), PARAMETER :: TwHt3TDzt = 371 + INTEGER(IntKi), PARAMETER :: TwHt4TDxt = 372 + INTEGER(IntKi), PARAMETER :: TwHt4TDyt = 373 + INTEGER(IntKi), PARAMETER :: TwHt4TDzt = 374 + INTEGER(IntKi), PARAMETER :: TwHt5TDxt = 375 + INTEGER(IntKi), PARAMETER :: TwHt5TDyt = 376 + INTEGER(IntKi), PARAMETER :: TwHt5TDzt = 377 + INTEGER(IntKi), PARAMETER :: TwHt6TDxt = 378 + INTEGER(IntKi), PARAMETER :: TwHt6TDyt = 379 + INTEGER(IntKi), PARAMETER :: TwHt6TDzt = 380 + INTEGER(IntKi), PARAMETER :: TwHt7TDxt = 381 + INTEGER(IntKi), PARAMETER :: TwHt7TDyt = 382 + INTEGER(IntKi), PARAMETER :: TwHt7TDzt = 383 + INTEGER(IntKi), PARAMETER :: TwHt8TDxt = 384 + INTEGER(IntKi), PARAMETER :: TwHt8TDyt = 385 + INTEGER(IntKi), PARAMETER :: TwHt8TDzt = 386 + INTEGER(IntKi), PARAMETER :: TwHt9TDxt = 387 + INTEGER(IntKi), PARAMETER :: TwHt9TDyt = 388 + INTEGER(IntKi), PARAMETER :: TwHt9TDzt = 389 + INTEGER(IntKi), PARAMETER :: TwHt1RDxt = 390 + INTEGER(IntKi), PARAMETER :: TwHt1RDyt = 391 + INTEGER(IntKi), PARAMETER :: TwHt1RDzt = 392 + INTEGER(IntKi), PARAMETER :: TwHt2RDxt = 393 + INTEGER(IntKi), PARAMETER :: TwHt2RDyt = 394 + INTEGER(IntKi), PARAMETER :: TwHt2RDzt = 395 + INTEGER(IntKi), PARAMETER :: TwHt3RDxt = 396 + INTEGER(IntKi), PARAMETER :: TwHt3RDyt = 397 + INTEGER(IntKi), PARAMETER :: TwHt3RDzt = 398 + INTEGER(IntKi), PARAMETER :: TwHt4RDxt = 399 + INTEGER(IntKi), PARAMETER :: TwHt4RDyt = 400 + INTEGER(IntKi), PARAMETER :: TwHt4RDzt = 401 + INTEGER(IntKi), PARAMETER :: TwHt5RDxt = 402 + INTEGER(IntKi), PARAMETER :: TwHt5RDyt = 403 + INTEGER(IntKi), PARAMETER :: TwHt5RDzt = 404 + INTEGER(IntKi), PARAMETER :: TwHt6RDxt = 405 + INTEGER(IntKi), PARAMETER :: TwHt6RDyt = 406 + INTEGER(IntKi), PARAMETER :: TwHt6RDzt = 407 + INTEGER(IntKi), PARAMETER :: TwHt7RDxt = 408 + INTEGER(IntKi), PARAMETER :: TwHt7RDyt = 409 + INTEGER(IntKi), PARAMETER :: TwHt7RDzt = 410 + INTEGER(IntKi), PARAMETER :: TwHt8RDxt = 411 + INTEGER(IntKi), PARAMETER :: TwHt8RDyt = 412 + INTEGER(IntKi), PARAMETER :: TwHt8RDzt = 413 + INTEGER(IntKi), PARAMETER :: TwHt9RDxt = 414 + INTEGER(IntKi), PARAMETER :: TwHt9RDyt = 415 + INTEGER(IntKi), PARAMETER :: TwHt9RDzt = 416 + INTEGER(IntKi), PARAMETER :: TwHt1TPxi = 417 + INTEGER(IntKi), PARAMETER :: TwHt1TPyi = 418 + INTEGER(IntKi), PARAMETER :: TwHt1TPzi = 419 + INTEGER(IntKi), PARAMETER :: TwHt2TPxi = 420 + INTEGER(IntKi), PARAMETER :: TwHt2TPyi = 421 + INTEGER(IntKi), PARAMETER :: TwHt2TPzi = 422 + INTEGER(IntKi), PARAMETER :: TwHt3TPxi = 423 + INTEGER(IntKi), PARAMETER :: TwHt3TPyi = 424 + INTEGER(IntKi), PARAMETER :: TwHt3TPzi = 425 + INTEGER(IntKi), PARAMETER :: TwHt4TPxi = 426 + INTEGER(IntKi), PARAMETER :: TwHt4TPyi = 427 + INTEGER(IntKi), PARAMETER :: TwHt4TPzi = 428 + INTEGER(IntKi), PARAMETER :: TwHt5TPxi = 429 + INTEGER(IntKi), PARAMETER :: TwHt5TPyi = 430 + INTEGER(IntKi), PARAMETER :: TwHt5TPzi = 431 + INTEGER(IntKi), PARAMETER :: TwHt6TPxi = 432 + INTEGER(IntKi), PARAMETER :: TwHt6TPyi = 433 + INTEGER(IntKi), PARAMETER :: TwHt6TPzi = 434 + INTEGER(IntKi), PARAMETER :: TwHt7TPxi = 435 + INTEGER(IntKi), PARAMETER :: TwHt7TPyi = 436 + INTEGER(IntKi), PARAMETER :: TwHt7TPzi = 437 + INTEGER(IntKi), PARAMETER :: TwHt8TPxi = 438 + INTEGER(IntKi), PARAMETER :: TwHt8TPyi = 439 + INTEGER(IntKi), PARAMETER :: TwHt8TPzi = 440 + INTEGER(IntKi), PARAMETER :: TwHt9TPxi = 441 + INTEGER(IntKi), PARAMETER :: TwHt9TPyi = 442 + INTEGER(IntKi), PARAMETER :: TwHt9TPzi = 443 + INTEGER(IntKi), PARAMETER :: TwHt1RPxi = 444 + INTEGER(IntKi), PARAMETER :: TwHt1RPyi = 445 + INTEGER(IntKi), PARAMETER :: TwHt1RPzi = 446 + INTEGER(IntKi), PARAMETER :: TwHt2RPxi = 447 + INTEGER(IntKi), PARAMETER :: TwHt2RPyi = 448 + INTEGER(IntKi), PARAMETER :: TwHt2RPzi = 449 + INTEGER(IntKi), PARAMETER :: TwHt3RPxi = 450 + INTEGER(IntKi), PARAMETER :: TwHt3RPyi = 451 + INTEGER(IntKi), PARAMETER :: TwHt3RPzi = 452 + INTEGER(IntKi), PARAMETER :: TwHt4RPxi = 453 + INTEGER(IntKi), PARAMETER :: TwHt4RPyi = 454 + INTEGER(IntKi), PARAMETER :: TwHt4RPzi = 455 + INTEGER(IntKi), PARAMETER :: TwHt5RPxi = 456 + INTEGER(IntKi), PARAMETER :: TwHt5RPyi = 457 + INTEGER(IntKi), PARAMETER :: TwHt5RPzi = 458 + INTEGER(IntKi), PARAMETER :: TwHt6RPxi = 459 + INTEGER(IntKi), PARAMETER :: TwHt6RPyi = 460 + INTEGER(IntKi), PARAMETER :: TwHt6RPzi = 461 + INTEGER(IntKi), PARAMETER :: TwHt7RPxi = 462 + INTEGER(IntKi), PARAMETER :: TwHt7RPyi = 463 + INTEGER(IntKi), PARAMETER :: TwHt7RPzi = 464 + INTEGER(IntKi), PARAMETER :: TwHt8RPxi = 465 + INTEGER(IntKi), PARAMETER :: TwHt8RPyi = 466 + INTEGER(IntKi), PARAMETER :: TwHt8RPzi = 467 + INTEGER(IntKi), PARAMETER :: TwHt9RPxi = 468 + INTEGER(IntKi), PARAMETER :: TwHt9RPyi = 469 + INTEGER(IntKi), PARAMETER :: TwHt9RPzi = 470 + + + ! Platform Motions: + + INTEGER(IntKi), PARAMETER :: PtfmTDxt = 471 + INTEGER(IntKi), PARAMETER :: PtfmTDyt = 472 + INTEGER(IntKi), PARAMETER :: PtfmTDzt = 473 + INTEGER(IntKi), PARAMETER :: PtfmTDxi = 474 + INTEGER(IntKi), PARAMETER :: PtfmTDyi = 475 + INTEGER(IntKi), PARAMETER :: PtfmTDzi = 476 + INTEGER(IntKi), PARAMETER :: PtfmTVxt = 477 + INTEGER(IntKi), PARAMETER :: PtfmTVyt = 478 + INTEGER(IntKi), PARAMETER :: PtfmTVzt = 479 + INTEGER(IntKi), PARAMETER :: PtfmTVxi = 480 + INTEGER(IntKi), PARAMETER :: PtfmTVyi = 481 + INTEGER(IntKi), PARAMETER :: PtfmTVzi = 482 + INTEGER(IntKi), PARAMETER :: PtfmTAxt = 483 + INTEGER(IntKi), PARAMETER :: PtfmTAyt = 484 + INTEGER(IntKi), PARAMETER :: PtfmTAzt = 485 + INTEGER(IntKi), PARAMETER :: PtfmTAxi = 486 + INTEGER(IntKi), PARAMETER :: PtfmTAyi = 487 + INTEGER(IntKi), PARAMETER :: PtfmTAzi = 488 + INTEGER(IntKi), PARAMETER :: PtfmRDxi = 489 + INTEGER(IntKi), PARAMETER :: PtfmRDyi = 490 + INTEGER(IntKi), PARAMETER :: PtfmRDzi = 491 + INTEGER(IntKi), PARAMETER :: PtfmRVxt = 492 + INTEGER(IntKi), PARAMETER :: PtfmRVyt = 493 + INTEGER(IntKi), PARAMETER :: PtfmRVzt = 494 + INTEGER(IntKi), PARAMETER :: PtfmRVxi = 495 + INTEGER(IntKi), PARAMETER :: PtfmRVyi = 496 + INTEGER(IntKi), PARAMETER :: PtfmRVzi = 497 + INTEGER(IntKi), PARAMETER :: PtfmRAxt = 498 + INTEGER(IntKi), PARAMETER :: PtfmRAyt = 499 + INTEGER(IntKi), PARAMETER :: PtfmRAzt = 500 + INTEGER(IntKi), PARAMETER :: PtfmRAxi = 501 + INTEGER(IntKi), PARAMETER :: PtfmRAyi = 502 + INTEGER(IntKi), PARAMETER :: PtfmRAzi = 503 + + + ! Blade 1 Root Loads: + + INTEGER(IntKi), PARAMETER :: RootFxc1 = 504 + INTEGER(IntKi), PARAMETER :: RootFyc1 = 505 + INTEGER(IntKi), PARAMETER :: RootFzc1 = 506 + INTEGER(IntKi), PARAMETER :: RootFxb1 = 507 + INTEGER(IntKi), PARAMETER :: RootFyb1 = 508 + INTEGER(IntKi), PARAMETER :: RootMxc1 = 509 + INTEGER(IntKi), PARAMETER :: RootMyc1 = 510 + INTEGER(IntKi), PARAMETER :: RootMzc1 = 511 + INTEGER(IntKi), PARAMETER :: RootMxb1 = 512 + INTEGER(IntKi), PARAMETER :: RootMyb1 = 513 + + + ! Blade 2 Root Loads: + + INTEGER(IntKi), PARAMETER :: RootFxc2 = 514 + INTEGER(IntKi), PARAMETER :: RootFyc2 = 515 + INTEGER(IntKi), PARAMETER :: RootFzc2 = 516 + INTEGER(IntKi), PARAMETER :: RootFxb2 = 517 + INTEGER(IntKi), PARAMETER :: RootFyb2 = 518 + INTEGER(IntKi), PARAMETER :: RootMxc2 = 519 + INTEGER(IntKi), PARAMETER :: RootMyc2 = 520 + INTEGER(IntKi), PARAMETER :: RootMzc2 = 521 + INTEGER(IntKi), PARAMETER :: RootMxb2 = 522 + INTEGER(IntKi), PARAMETER :: RootMyb2 = 523 + + + ! Blade 3 Root Loads: + + INTEGER(IntKi), PARAMETER :: RootFxc3 = 524 + INTEGER(IntKi), PARAMETER :: RootFyc3 = 525 + INTEGER(IntKi), PARAMETER :: RootFzc3 = 526 + INTEGER(IntKi), PARAMETER :: RootFxb3 = 527 + INTEGER(IntKi), PARAMETER :: RootFyb3 = 528 + INTEGER(IntKi), PARAMETER :: RootMxc3 = 529 + INTEGER(IntKi), PARAMETER :: RootMyc3 = 530 + INTEGER(IntKi), PARAMETER :: RootMzc3 = 531 + INTEGER(IntKi), PARAMETER :: RootMxb3 = 532 + INTEGER(IntKi), PARAMETER :: RootMyb3 = 533 + + + ! Blade 1 Local Span Loads: + + INTEGER(IntKi), PARAMETER :: Spn1MLxb1 = 534 + INTEGER(IntKi), PARAMETER :: Spn1MLyb1 = 535 + INTEGER(IntKi), PARAMETER :: Spn1MLzb1 = 536 + INTEGER(IntKi), PARAMETER :: Spn2MLxb1 = 537 + INTEGER(IntKi), PARAMETER :: Spn2MLyb1 = 538 + INTEGER(IntKi), PARAMETER :: Spn2MLzb1 = 539 + INTEGER(IntKi), PARAMETER :: Spn3MLxb1 = 540 + INTEGER(IntKi), PARAMETER :: Spn3MLyb1 = 541 + INTEGER(IntKi), PARAMETER :: Spn3MLzb1 = 542 + INTEGER(IntKi), PARAMETER :: Spn4MLxb1 = 543 + INTEGER(IntKi), PARAMETER :: Spn4MLyb1 = 544 + INTEGER(IntKi), PARAMETER :: Spn4MLzb1 = 545 + INTEGER(IntKi), PARAMETER :: Spn5MLxb1 = 546 + INTEGER(IntKi), PARAMETER :: Spn5MLyb1 = 547 + INTEGER(IntKi), PARAMETER :: Spn5MLzb1 = 548 + INTEGER(IntKi), PARAMETER :: Spn6MLxb1 = 549 + INTEGER(IntKi), PARAMETER :: Spn6MLyb1 = 550 + INTEGER(IntKi), PARAMETER :: Spn6MLzb1 = 551 + INTEGER(IntKi), PARAMETER :: Spn7MLxb1 = 552 + INTEGER(IntKi), PARAMETER :: Spn7MLyb1 = 553 + INTEGER(IntKi), PARAMETER :: Spn7MLzb1 = 554 + INTEGER(IntKi), PARAMETER :: Spn8MLxb1 = 555 + INTEGER(IntKi), PARAMETER :: Spn8MLyb1 = 556 + INTEGER(IntKi), PARAMETER :: Spn8MLzb1 = 557 + INTEGER(IntKi), PARAMETER :: Spn9MLxb1 = 558 + INTEGER(IntKi), PARAMETER :: Spn9MLyb1 = 559 + INTEGER(IntKi), PARAMETER :: Spn9MLzb1 = 560 + INTEGER(IntKi), PARAMETER :: Spn1FLxb1 = 561 + INTEGER(IntKi), PARAMETER :: Spn1FLyb1 = 562 + INTEGER(IntKi), PARAMETER :: Spn1FLzb1 = 563 + INTEGER(IntKi), PARAMETER :: Spn2FLxb1 = 564 + INTEGER(IntKi), PARAMETER :: Spn2FLyb1 = 565 + INTEGER(IntKi), PARAMETER :: Spn2FLzb1 = 566 + INTEGER(IntKi), PARAMETER :: Spn3FLxb1 = 567 + INTEGER(IntKi), PARAMETER :: Spn3FLyb1 = 568 + INTEGER(IntKi), PARAMETER :: Spn3FLzb1 = 569 + INTEGER(IntKi), PARAMETER :: Spn4FLxb1 = 570 + INTEGER(IntKi), PARAMETER :: Spn4FLyb1 = 571 + INTEGER(IntKi), PARAMETER :: Spn4FLzb1 = 572 + INTEGER(IntKi), PARAMETER :: Spn5FLxb1 = 573 + INTEGER(IntKi), PARAMETER :: Spn5FLyb1 = 574 + INTEGER(IntKi), PARAMETER :: Spn5FLzb1 = 575 + INTEGER(IntKi), PARAMETER :: Spn6FLxb1 = 576 + INTEGER(IntKi), PARAMETER :: Spn6FLyb1 = 577 + INTEGER(IntKi), PARAMETER :: Spn6FLzb1 = 578 + INTEGER(IntKi), PARAMETER :: Spn7FLxb1 = 579 + INTEGER(IntKi), PARAMETER :: Spn7FLyb1 = 580 + INTEGER(IntKi), PARAMETER :: Spn7FLzb1 = 581 + INTEGER(IntKi), PARAMETER :: Spn8FLxb1 = 582 + INTEGER(IntKi), PARAMETER :: Spn8FLyb1 = 583 + INTEGER(IntKi), PARAMETER :: Spn8FLzb1 = 584 + INTEGER(IntKi), PARAMETER :: Spn9FLxb1 = 585 + INTEGER(IntKi), PARAMETER :: Spn9FLyb1 = 586 + INTEGER(IntKi), PARAMETER :: Spn9FLzb1 = 587 + + + ! Blade 2 Local Span Loads: + + INTEGER(IntKi), PARAMETER :: Spn1MLxb2 = 588 + INTEGER(IntKi), PARAMETER :: Spn1MLyb2 = 589 + INTEGER(IntKi), PARAMETER :: Spn1MLzb2 = 590 + INTEGER(IntKi), PARAMETER :: Spn2MLxb2 = 591 + INTEGER(IntKi), PARAMETER :: Spn2MLyb2 = 592 + INTEGER(IntKi), PARAMETER :: Spn2MLzb2 = 593 + INTEGER(IntKi), PARAMETER :: Spn3MLxb2 = 594 + INTEGER(IntKi), PARAMETER :: Spn3MLyb2 = 595 + INTEGER(IntKi), PARAMETER :: Spn3MLzb2 = 596 + INTEGER(IntKi), PARAMETER :: Spn4MLxb2 = 597 + INTEGER(IntKi), PARAMETER :: Spn4MLyb2 = 598 + INTEGER(IntKi), PARAMETER :: Spn4MLzb2 = 599 + INTEGER(IntKi), PARAMETER :: Spn5MLxb2 = 600 + INTEGER(IntKi), PARAMETER :: Spn5MLyb2 = 601 + INTEGER(IntKi), PARAMETER :: Spn5MLzb2 = 602 + INTEGER(IntKi), PARAMETER :: Spn6MLxb2 = 603 + INTEGER(IntKi), PARAMETER :: Spn6MLyb2 = 604 + INTEGER(IntKi), PARAMETER :: Spn6MLzb2 = 605 + INTEGER(IntKi), PARAMETER :: Spn7MLxb2 = 606 + INTEGER(IntKi), PARAMETER :: Spn7MLyb2 = 607 + INTEGER(IntKi), PARAMETER :: Spn7MLzb2 = 608 + INTEGER(IntKi), PARAMETER :: Spn8MLxb2 = 609 + INTEGER(IntKi), PARAMETER :: Spn8MLyb2 = 610 + INTEGER(IntKi), PARAMETER :: Spn8MLzb2 = 611 + INTEGER(IntKi), PARAMETER :: Spn9MLxb2 = 612 + INTEGER(IntKi), PARAMETER :: Spn9MLyb2 = 613 + INTEGER(IntKi), PARAMETER :: Spn9MLzb2 = 614 + INTEGER(IntKi), PARAMETER :: Spn1FLxb2 = 615 + INTEGER(IntKi), PARAMETER :: Spn1FLyb2 = 616 + INTEGER(IntKi), PARAMETER :: Spn1FLzb2 = 617 + INTEGER(IntKi), PARAMETER :: Spn2FLxb2 = 618 + INTEGER(IntKi), PARAMETER :: Spn2FLyb2 = 619 + INTEGER(IntKi), PARAMETER :: Spn2FLzb2 = 620 + INTEGER(IntKi), PARAMETER :: Spn3FLxb2 = 621 + INTEGER(IntKi), PARAMETER :: Spn3FLyb2 = 622 + INTEGER(IntKi), PARAMETER :: Spn3FLzb2 = 623 + INTEGER(IntKi), PARAMETER :: Spn4FLxb2 = 624 + INTEGER(IntKi), PARAMETER :: Spn4FLyb2 = 625 + INTEGER(IntKi), PARAMETER :: Spn4FLzb2 = 626 + INTEGER(IntKi), PARAMETER :: Spn5FLxb2 = 627 + INTEGER(IntKi), PARAMETER :: Spn5FLyb2 = 628 + INTEGER(IntKi), PARAMETER :: Spn5FLzb2 = 629 + INTEGER(IntKi), PARAMETER :: Spn6FLxb2 = 630 + INTEGER(IntKi), PARAMETER :: Spn6FLyb2 = 631 + INTEGER(IntKi), PARAMETER :: Spn6FLzb2 = 632 + INTEGER(IntKi), PARAMETER :: Spn7FLxb2 = 633 + INTEGER(IntKi), PARAMETER :: Spn7FLyb2 = 634 + INTEGER(IntKi), PARAMETER :: Spn7FLzb2 = 635 + INTEGER(IntKi), PARAMETER :: Spn8FLxb2 = 636 + INTEGER(IntKi), PARAMETER :: Spn8FLyb2 = 637 + INTEGER(IntKi), PARAMETER :: Spn8FLzb2 = 638 + INTEGER(IntKi), PARAMETER :: Spn9FLxb2 = 639 + INTEGER(IntKi), PARAMETER :: Spn9FLyb2 = 640 + INTEGER(IntKi), PARAMETER :: Spn9FLzb2 = 641 + + + ! Blade 3 Local Span Loads: + + INTEGER(IntKi), PARAMETER :: Spn1MLxb3 = 642 + INTEGER(IntKi), PARAMETER :: Spn1MLyb3 = 643 + INTEGER(IntKi), PARAMETER :: Spn1MLzb3 = 644 + INTEGER(IntKi), PARAMETER :: Spn2MLxb3 = 645 + INTEGER(IntKi), PARAMETER :: Spn2MLyb3 = 646 + INTEGER(IntKi), PARAMETER :: Spn2MLzb3 = 647 + INTEGER(IntKi), PARAMETER :: Spn3MLxb3 = 648 + INTEGER(IntKi), PARAMETER :: Spn3MLyb3 = 649 + INTEGER(IntKi), PARAMETER :: Spn3MLzb3 = 650 + INTEGER(IntKi), PARAMETER :: Spn4MLxb3 = 651 + INTEGER(IntKi), PARAMETER :: Spn4MLyb3 = 652 + INTEGER(IntKi), PARAMETER :: Spn4MLzb3 = 653 + INTEGER(IntKi), PARAMETER :: Spn5MLxb3 = 654 + INTEGER(IntKi), PARAMETER :: Spn5MLyb3 = 655 + INTEGER(IntKi), PARAMETER :: Spn5MLzb3 = 656 + INTEGER(IntKi), PARAMETER :: Spn6MLxb3 = 657 + INTEGER(IntKi), PARAMETER :: Spn6MLyb3 = 658 + INTEGER(IntKi), PARAMETER :: Spn6MLzb3 = 659 + INTEGER(IntKi), PARAMETER :: Spn7MLxb3 = 660 + INTEGER(IntKi), PARAMETER :: Spn7MLyb3 = 661 + INTEGER(IntKi), PARAMETER :: Spn7MLzb3 = 662 + INTEGER(IntKi), PARAMETER :: Spn8MLxb3 = 663 + INTEGER(IntKi), PARAMETER :: Spn8MLyb3 = 664 + INTEGER(IntKi), PARAMETER :: Spn8MLzb3 = 665 + INTEGER(IntKi), PARAMETER :: Spn9MLxb3 = 666 + INTEGER(IntKi), PARAMETER :: Spn9MLyb3 = 667 + INTEGER(IntKi), PARAMETER :: Spn9MLzb3 = 668 + INTEGER(IntKi), PARAMETER :: Spn1FLxb3 = 669 + INTEGER(IntKi), PARAMETER :: Spn1FLyb3 = 670 + INTEGER(IntKi), PARAMETER :: Spn1FLzb3 = 671 + INTEGER(IntKi), PARAMETER :: Spn2FLxb3 = 672 + INTEGER(IntKi), PARAMETER :: Spn2FLyb3 = 673 + INTEGER(IntKi), PARAMETER :: Spn2FLzb3 = 674 + INTEGER(IntKi), PARAMETER :: Spn3FLxb3 = 675 + INTEGER(IntKi), PARAMETER :: Spn3FLyb3 = 676 + INTEGER(IntKi), PARAMETER :: Spn3FLzb3 = 677 + INTEGER(IntKi), PARAMETER :: Spn4FLxb3 = 678 + INTEGER(IntKi), PARAMETER :: Spn4FLyb3 = 679 + INTEGER(IntKi), PARAMETER :: Spn4FLzb3 = 680 + INTEGER(IntKi), PARAMETER :: Spn5FLxb3 = 681 + INTEGER(IntKi), PARAMETER :: Spn5FLyb3 = 682 + INTEGER(IntKi), PARAMETER :: Spn5FLzb3 = 683 + INTEGER(IntKi), PARAMETER :: Spn6FLxb3 = 684 + INTEGER(IntKi), PARAMETER :: Spn6FLyb3 = 685 + INTEGER(IntKi), PARAMETER :: Spn6FLzb3 = 686 + INTEGER(IntKi), PARAMETER :: Spn7FLxb3 = 687 + INTEGER(IntKi), PARAMETER :: Spn7FLyb3 = 688 + INTEGER(IntKi), PARAMETER :: Spn7FLzb3 = 689 + INTEGER(IntKi), PARAMETER :: Spn8FLxb3 = 690 + INTEGER(IntKi), PARAMETER :: Spn8FLyb3 = 691 + INTEGER(IntKi), PARAMETER :: Spn8FLzb3 = 692 + INTEGER(IntKi), PARAMETER :: Spn9FLxb3 = 693 + INTEGER(IntKi), PARAMETER :: Spn9FLyb3 = 694 + INTEGER(IntKi), PARAMETER :: Spn9FLzb3 = 695 + + + ! Hub and Rotor Loads: + + INTEGER(IntKi), PARAMETER :: LSShftFxa = 696 + INTEGER(IntKi), PARAMETER :: LSShftFya = 697 + INTEGER(IntKi), PARAMETER :: LSShftFza = 698 + INTEGER(IntKi), PARAMETER :: LSShftFys = 699 + INTEGER(IntKi), PARAMETER :: LSShftFzs = 700 + INTEGER(IntKi), PARAMETER :: LSShftMxa = 701 + INTEGER(IntKi), PARAMETER :: LSSTipMya = 702 + INTEGER(IntKi), PARAMETER :: LSSTipMza = 703 + INTEGER(IntKi), PARAMETER :: LSSTipMys = 704 + INTEGER(IntKi), PARAMETER :: LSSTipMzs = 705 + INTEGER(IntKi), PARAMETER :: RotPwr = 706 + + + ! Shaft Strain Gage Loads: + + INTEGER(IntKi), PARAMETER :: LSSGagMya = 707 + INTEGER(IntKi), PARAMETER :: LSSGagMza = 708 + INTEGER(IntKi), PARAMETER :: LSSGagMys = 709 + INTEGER(IntKi), PARAMETER :: LSSGagMzs = 710 + + + ! High-Speed Shaft Loads: + + INTEGER(IntKi), PARAMETER :: HSShftTq = 711 + INTEGER(IntKi), PARAMETER :: HSSBrTq = 712 + INTEGER(IntKi), PARAMETER :: HSShftPwr = 713 + + + ! Rotor-Furl Bearing Loads: + + INTEGER(IntKi), PARAMETER :: RFrlBrM = 714 + + + ! Tail-Furl Bearing Loads: + + INTEGER(IntKi), PARAMETER :: TFrlBrM = 715 + + + ! Tower-Top / Yaw Bearing Loads: + + INTEGER(IntKi), PARAMETER :: YawBrFxn = 716 + INTEGER(IntKi), PARAMETER :: YawBrFyn = 717 + INTEGER(IntKi), PARAMETER :: YawBrFzn = 718 + INTEGER(IntKi), PARAMETER :: YawBrFxp = 719 + INTEGER(IntKi), PARAMETER :: YawBrFyp = 720 + INTEGER(IntKi), PARAMETER :: YawBrMxn = 721 + INTEGER(IntKi), PARAMETER :: YawBrMyn = 722 + INTEGER(IntKi), PARAMETER :: YawBrMzn = 723 + INTEGER(IntKi), PARAMETER :: YawBrMxp = 724 + INTEGER(IntKi), PARAMETER :: YawBrMyp = 725 + + + ! Tower Base Loads: + + INTEGER(IntKi), PARAMETER :: TwrBsFxt = 726 + INTEGER(IntKi), PARAMETER :: TwrBsFyt = 727 + INTEGER(IntKi), PARAMETER :: TwrBsFzt = 728 + INTEGER(IntKi), PARAMETER :: TwrBsMxt = 729 + INTEGER(IntKi), PARAMETER :: TwrBsMyt = 730 + INTEGER(IntKi), PARAMETER :: TwrBsMzt = 731 + + + ! Local Tower Loads: + + INTEGER(IntKi), PARAMETER :: TwHt1MLxt = 732 + INTEGER(IntKi), PARAMETER :: TwHt1MLyt = 733 + INTEGER(IntKi), PARAMETER :: TwHt1MLzt = 734 + INTEGER(IntKi), PARAMETER :: TwHt2MLxt = 735 + INTEGER(IntKi), PARAMETER :: TwHt2MLyt = 736 + INTEGER(IntKi), PARAMETER :: TwHt2MLzt = 737 + INTEGER(IntKi), PARAMETER :: TwHt3MLxt = 738 + INTEGER(IntKi), PARAMETER :: TwHt3MLyt = 739 + INTEGER(IntKi), PARAMETER :: TwHt3MLzt = 740 + INTEGER(IntKi), PARAMETER :: TwHt4MLxt = 741 + INTEGER(IntKi), PARAMETER :: TwHt4MLyt = 742 + INTEGER(IntKi), PARAMETER :: TwHt4MLzt = 743 + INTEGER(IntKi), PARAMETER :: TwHt5MLxt = 744 + INTEGER(IntKi), PARAMETER :: TwHt5MLyt = 745 + INTEGER(IntKi), PARAMETER :: TwHt5MLzt = 746 + INTEGER(IntKi), PARAMETER :: TwHt6MLxt = 747 + INTEGER(IntKi), PARAMETER :: TwHt6MLyt = 748 + INTEGER(IntKi), PARAMETER :: TwHt6MLzt = 749 + INTEGER(IntKi), PARAMETER :: TwHt7MLxt = 750 + INTEGER(IntKi), PARAMETER :: TwHt7MLyt = 751 + INTEGER(IntKi), PARAMETER :: TwHt7MLzt = 752 + INTEGER(IntKi), PARAMETER :: TwHt8MLxt = 753 + INTEGER(IntKi), PARAMETER :: TwHt8MLyt = 754 + INTEGER(IntKi), PARAMETER :: TwHt8MLzt = 755 + INTEGER(IntKi), PARAMETER :: TwHt9MLxt = 756 + INTEGER(IntKi), PARAMETER :: TwHt9MLyt = 757 + INTEGER(IntKi), PARAMETER :: TwHt9MLzt = 758 + INTEGER(IntKi), PARAMETER :: TwHt1FLxt = 759 + INTEGER(IntKi), PARAMETER :: TwHt1FLyt = 760 + INTEGER(IntKi), PARAMETER :: TwHt1FLzt = 761 + INTEGER(IntKi), PARAMETER :: TwHt2FLxt = 762 + INTEGER(IntKi), PARAMETER :: TwHt2FLyt = 763 + INTEGER(IntKi), PARAMETER :: TwHt2FLzt = 764 + INTEGER(IntKi), PARAMETER :: TwHt3FLxt = 765 + INTEGER(IntKi), PARAMETER :: TwHt3FLyt = 766 + INTEGER(IntKi), PARAMETER :: TwHt3FLzt = 767 + INTEGER(IntKi), PARAMETER :: TwHt4FLxt = 768 + INTEGER(IntKi), PARAMETER :: TwHt4FLyt = 769 + INTEGER(IntKi), PARAMETER :: TwHt4FLzt = 770 + INTEGER(IntKi), PARAMETER :: TwHt5FLxt = 771 + INTEGER(IntKi), PARAMETER :: TwHt5FLyt = 772 + INTEGER(IntKi), PARAMETER :: TwHt5FLzt = 773 + INTEGER(IntKi), PARAMETER :: TwHt6FLxt = 774 + INTEGER(IntKi), PARAMETER :: TwHt6FLyt = 775 + INTEGER(IntKi), PARAMETER :: TwHt6FLzt = 776 + INTEGER(IntKi), PARAMETER :: TwHt7FLxt = 777 + INTEGER(IntKi), PARAMETER :: TwHt7FLyt = 778 + INTEGER(IntKi), PARAMETER :: TwHt7FLzt = 779 + INTEGER(IntKi), PARAMETER :: TwHt8FLxt = 780 + INTEGER(IntKi), PARAMETER :: TwHt8FLyt = 781 + INTEGER(IntKi), PARAMETER :: TwHt8FLzt = 782 + INTEGER(IntKi), PARAMETER :: TwHt9FLxt = 783 + INTEGER(IntKi), PARAMETER :: TwHt9FLyt = 784 + INTEGER(IntKi), PARAMETER :: TwHt9FLzt = 785 + + + ! Internal Degrees of Freedom: + + INTEGER(IntKi), PARAMETER :: Q_B1E1 = 786 + INTEGER(IntKi), PARAMETER :: Q_B2E1 = 787 + INTEGER(IntKi), PARAMETER :: Q_B3E1 = 788 + INTEGER(IntKi), PARAMETER :: Q_B1F1 = 789 + INTEGER(IntKi), PARAMETER :: Q_B2F1 = 790 + INTEGER(IntKi), PARAMETER :: Q_B3F1 = 791 + INTEGER(IntKi), PARAMETER :: Q_B1F2 = 792 + INTEGER(IntKi), PARAMETER :: Q_B2F2 = 793 + INTEGER(IntKi), PARAMETER :: Q_B3F2 = 794 + INTEGER(IntKi), PARAMETER :: Q_Teet = 795 + INTEGER(IntKi), PARAMETER :: Q_DrTr = 796 + INTEGER(IntKi), PARAMETER :: Q_GeAz = 797 + INTEGER(IntKi), PARAMETER :: Q_RFrl = 798 + INTEGER(IntKi), PARAMETER :: Q_TFrl = 799 + INTEGER(IntKi), PARAMETER :: Q_Yaw = 800 + INTEGER(IntKi), PARAMETER :: Q_TFA1 = 801 + INTEGER(IntKi), PARAMETER :: Q_TSS1 = 802 + INTEGER(IntKi), PARAMETER :: Q_TFA2 = 803 + INTEGER(IntKi), PARAMETER :: Q_TSS2 = 804 + INTEGER(IntKi), PARAMETER :: Q_Sg = 805 + INTEGER(IntKi), PARAMETER :: Q_Sw = 806 + INTEGER(IntKi), PARAMETER :: Q_Hv = 807 + INTEGER(IntKi), PARAMETER :: Q_R = 808 + INTEGER(IntKi), PARAMETER :: Q_P = 809 + INTEGER(IntKi), PARAMETER :: Q_Y = 810 + INTEGER(IntKi), PARAMETER :: QD_B1E1 = 811 + INTEGER(IntKi), PARAMETER :: QD_B2E1 = 812 + INTEGER(IntKi), PARAMETER :: QD_B3E1 = 813 + INTEGER(IntKi), PARAMETER :: QD_B1F1 = 814 + INTEGER(IntKi), PARAMETER :: QD_B2F1 = 815 + INTEGER(IntKi), PARAMETER :: QD_B3F1 = 816 + INTEGER(IntKi), PARAMETER :: QD_B1F2 = 817 + INTEGER(IntKi), PARAMETER :: QD_B2F2 = 818 + INTEGER(IntKi), PARAMETER :: QD_B3F2 = 819 + INTEGER(IntKi), PARAMETER :: QD_Teet = 820 + INTEGER(IntKi), PARAMETER :: QD_DrTr = 821 + INTEGER(IntKi), PARAMETER :: QD_GeAz = 822 + INTEGER(IntKi), PARAMETER :: QD_RFrl = 823 + INTEGER(IntKi), PARAMETER :: QD_TFrl = 824 + INTEGER(IntKi), PARAMETER :: QD_Yaw = 825 + INTEGER(IntKi), PARAMETER :: QD_TFA1 = 826 + INTEGER(IntKi), PARAMETER :: QD_TSS1 = 827 + INTEGER(IntKi), PARAMETER :: QD_TFA2 = 828 + INTEGER(IntKi), PARAMETER :: QD_TSS2 = 829 + INTEGER(IntKi), PARAMETER :: QD_Sg = 830 + INTEGER(IntKi), PARAMETER :: QD_Sw = 831 + INTEGER(IntKi), PARAMETER :: QD_Hv = 832 + INTEGER(IntKi), PARAMETER :: QD_R = 833 + INTEGER(IntKi), PARAMETER :: QD_P = 834 + INTEGER(IntKi), PARAMETER :: QD_Y = 835 + INTEGER(IntKi), PARAMETER :: QD2_B1E1 = 836 + INTEGER(IntKi), PARAMETER :: QD2_B2E1 = 837 + INTEGER(IntKi), PARAMETER :: QD2_B3E1 = 838 + INTEGER(IntKi), PARAMETER :: QD2_B1F1 = 839 + INTEGER(IntKi), PARAMETER :: QD2_B2F1 = 840 + INTEGER(IntKi), PARAMETER :: QD2_B3F1 = 841 + INTEGER(IntKi), PARAMETER :: QD2_B1F2 = 842 + INTEGER(IntKi), PARAMETER :: QD2_B2F2 = 843 + INTEGER(IntKi), PARAMETER :: QD2_B3F2 = 844 + INTEGER(IntKi), PARAMETER :: QD2_Teet = 845 + INTEGER(IntKi), PARAMETER :: QD2_DrTr = 846 + INTEGER(IntKi), PARAMETER :: QD2_GeAz = 847 + INTEGER(IntKi), PARAMETER :: QD2_RFrl = 848 + INTEGER(IntKi), PARAMETER :: QD2_TFrl = 849 + INTEGER(IntKi), PARAMETER :: QD2_Yaw = 850 + INTEGER(IntKi), PARAMETER :: QD2_TFA1 = 851 + INTEGER(IntKi), PARAMETER :: QD2_TSS1 = 852 + INTEGER(IntKi), PARAMETER :: QD2_TFA2 = 853 + INTEGER(IntKi), PARAMETER :: QD2_TSS2 = 854 + INTEGER(IntKi), PARAMETER :: QD2_Sg = 855 + INTEGER(IntKi), PARAMETER :: QD2_Sw = 856 + INTEGER(IntKi), PARAMETER :: QD2_Hv = 857 + INTEGER(IntKi), PARAMETER :: QD2_R = 858 + INTEGER(IntKi), PARAMETER :: QD2_P = 859 + INTEGER(IntKi), PARAMETER :: QD2_Y = 860 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 860 + +!End of code generated by Matlab script +! =================================================================================================== + + +INTEGER, PARAMETER :: TipDxc( 3) = (/TipDxc1, TipDxc2, TipDxc3/) +INTEGER, PARAMETER :: TipDyc( 3) = (/TipDyc1, TipDyc2, TipDyc3/) +INTEGER, PARAMETER :: TipDzc( 3) = (/TipDzc1, TipDzc2, TipDzc3/) +INTEGER, PARAMETER :: TipDxb( 3) = (/TipDxb1, TipDxb2, TipDxb3/) +INTEGER, PARAMETER :: TipDyb( 3) = (/TipDyb1, TipDyb2, TipDyb3/) +INTEGER, PARAMETER :: TipALxb(3) = (/TipALxb1, TipALxb2, TipALxb3/) +INTEGER, PARAMETER :: TipALyb(3) = (/TipALyb1, TipALyb2, TipALyb3/) +INTEGER, PARAMETER :: TipALzb(3) = (/TipALzb1, TipALzb2, TipALzb3/) +INTEGER, PARAMETER :: TipRDxb(3) = (/TipRDxb1, TipRDxb2, TipRDxb3/) +INTEGER, PARAMETER :: TipRDyb(3) = (/TipRDyb1, TipRDyb2, TipRDyb3/) +INTEGER, PARAMETER :: TipRDzc(3) = (/TipRDzc1, TipRDzc2, TipRDzc3/) +INTEGER, PARAMETER :: TipClrnc(3) = (/TipClrnc1,TipClrnc2,TipClrnc3/) +INTEGER, PARAMETER :: PtchPMzc(3) = (/PtchPMzc1,PtchPMzc2,PtchPMzc3/) + +INTEGER, PARAMETER :: RootFxc(3) = (/ RootFxc1,RootFxc2,RootFxc3 /) +INTEGER, PARAMETER :: RootFyc(3) = (/ RootFyc1,RootFyc2,RootFyc3 /) +INTEGER, PARAMETER :: RootFzc(3) = (/ RootFzc1,RootFzc2,RootFzc3 /) +INTEGER, PARAMETER :: RootFxb(3) = (/ RootFxb1,RootFxb2,RootFxb3 /) +INTEGER, PARAMETER :: RootFyb(3) = (/ RootFyb1,RootFyb2,RootFyb3 /) +INTEGER, PARAMETER :: RootMxc(3) = (/ RootMxc1,RootMxc2,RootMxc3 /) +INTEGER, PARAMETER :: RootMyc(3) = (/ RootMyc1,RootMyc2,RootMyc3 /) +INTEGER, PARAMETER :: RootMzc(3) = (/ RootMzc1,RootMzc2,RootMzc3 /) +INTEGER, PARAMETER :: RootMxb(3) = (/ RootMxb1,RootMxb2,RootMxb3 /) +INTEGER, PARAMETER :: RootMyb(3) = (/ RootMyb1,RootMyb2,RootMyb3 /) + +INTEGER, PARAMETER :: SpnALxb(9, 3) = RESHAPE( (/ & + Spn1ALxb1,Spn2ALxb1,Spn3ALxb1,Spn4ALxb1,Spn5ALxb1,Spn6ALxb1,Spn7ALxb1,Spn8ALxb1,Spn9ALxb1, & + Spn1ALxb2,Spn2ALxb2,Spn3ALxb2,Spn4ALxb2,Spn5ALxb2,Spn6ALxb2,Spn7ALxb2,Spn8ALxb2,Spn9ALxb2, & + Spn1ALxb3,Spn2ALxb3,Spn3ALxb3,Spn4ALxb3,Spn5ALxb3,Spn6ALxb3,Spn7ALxb3,Spn8ALxb3,Spn9ALxb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnALyb(9, 3) = RESHAPE( (/ & + Spn1ALyb1,Spn2ALyb1,Spn3ALyb1,Spn4ALyb1,Spn5ALyb1,Spn6ALyb1,Spn7ALyb1,Spn8ALyb1,Spn9ALyb1, & + Spn1ALyb2,Spn2ALyb2,Spn3ALyb2,Spn4ALyb2,Spn5ALyb2,Spn6ALyb2,Spn7ALyb2,Spn8ALyb2,Spn9ALyb2, & + Spn1ALyb3,Spn2ALyb3,Spn3ALyb3,Spn4ALyb3,Spn5ALyb3,Spn6ALyb3,Spn7ALyb3,Spn8ALyb3,Spn9ALyb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnALzb(9, 3) = RESHAPE( (/ & + Spn1ALzb1,Spn2ALzb1,Spn3ALzb1,Spn4ALzb1,Spn5ALzb1,Spn6ALzb1,Spn7ALzb1,Spn8ALzb1,Spn9ALzb1, & + Spn1ALzb2,Spn2ALzb2,Spn3ALzb2,Spn4ALzb2,Spn5ALzb2,Spn6ALzb2,Spn7ALzb2,Spn8ALzb2,Spn9ALzb2, & + Spn1ALzb3,Spn2ALzb3,Spn3ALzb3,Spn4ALzb3,Spn5ALzb3,Spn6ALzb3,Spn7ALzb3,Spn8ALzb3,Spn9ALzb3 & + /), (/9, 3/) ) + +INTEGER, PARAMETER :: SpnFLxb(9,3) = RESHAPE( (/ & + Spn1FLxb1,Spn2FLxb1,Spn3FLxb1,Spn4FLxb1,Spn5FLxb1,Spn6FLxb1,Spn7FLxb1,Spn8FLxb1,Spn9FLxb1, & + Spn1FLxb2,Spn2FLxb2,Spn3FLxb2,Spn4FLxb2,Spn5FLxb2,Spn6FLxb2,Spn7FLxb2,Spn8FLxb2,Spn9FLxb2, & + Spn1FLxb3,Spn2FLxb3,Spn3FLxb3,Spn4FLxb3,Spn5FLxb3,Spn6FLxb3,Spn7FLxb3,Spn8FLxb3,Spn9FLxb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnFLyb(9,3) = RESHAPE( (/ & + Spn1FLyb1,Spn2FLyb1,Spn3FLyb1,Spn4FLyb1,Spn5FLyb1,Spn6FLyb1,Spn7FLyb1,Spn8FLyb1,Spn9FLyb1, & + Spn1FLyb2,Spn2FLyb2,Spn3FLyb2,Spn4FLyb2,Spn5FLyb2,Spn6FLyb2,Spn7FLyb2,Spn8FLyb2,Spn9FLyb2, & + Spn1FLyb3,Spn2FLyb3,Spn3FLyb3,Spn4FLyb3,Spn5FLyb3,Spn6FLyb3,Spn7FLyb3,Spn8FLyb3,Spn9FLyb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnFLzb(9,3) = RESHAPE( (/ & + Spn1FLzb1,Spn2FLzb1,Spn3FLzb1,Spn4FLzb1,Spn5FLzb1,Spn6FLzb1,Spn7FLzb1,Spn8FLzb1,Spn9FLzb1, & + Spn1FLzb2,Spn2FLzb2,Spn3FLzb2,Spn4FLzb2,Spn5FLzb2,Spn6FLzb2,Spn7FLzb2,Spn8FLzb2,Spn9FLzb2, & + Spn1FLzb3,Spn2FLzb3,Spn3FLzb3,Spn4FLzb3,Spn5FLzb3,Spn6FLzb3,Spn7FLzb3,Spn8FLzb3,Spn9FLzb3 & + /), (/9, 3/) ) + +INTEGER, PARAMETER :: SpnMLxb(9,3) = RESHAPE( (/ & + Spn1MLxb1,Spn2MLxb1,Spn3MLxb1,Spn4MLxb1,Spn5MLxb1,Spn6MLxb1,Spn7MLxb1,Spn8MLxb1,Spn9MLxb1, & + Spn1MLxb2,Spn2MLxb2,Spn3MLxb2,Spn4MLxb2,Spn5MLxb2,Spn6MLxb2,Spn7MLxb2,Spn8MLxb2,Spn9MLxb2, & + Spn1MLxb3,Spn2MLxb3,Spn3MLxb3,Spn4MLxb3,Spn5MLxb3,Spn6MLxb3,Spn7MLxb3,Spn8MLxb3,Spn9MLxb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnMLyb(9,3) = RESHAPE( (/ & + Spn1MLyb1,Spn2MLyb1,Spn3MLyb1,Spn4MLyb1,Spn5MLyb1,Spn6MLyb1,Spn7MLyb1,Spn8MLyb1,Spn9MLyb1, & + Spn1MLyb2,Spn2MLyb2,Spn3MLyb2,Spn4MLyb2,Spn5MLyb2,Spn6MLyb2,Spn7MLyb2,Spn8MLyb2,Spn9MLyb2, & + Spn1MLyb3,Spn2MLyb3,Spn3MLyb3,Spn4MLyb3,Spn5MLyb3,Spn6MLyb3,Spn7MLyb3,Spn8MLyb3,Spn9MLyb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnMLzb(9,3) = RESHAPE( (/ & + Spn1MLzb1,Spn2MLzb1,Spn3MLzb1,Spn4MLzb1,Spn5MLzb1,Spn6MLzb1,Spn7MLzb1,Spn8MLzb1,Spn9MLzb1, & + Spn1MLzb2,Spn2MLzb2,Spn3MLzb2,Spn4MLzb2,Spn5MLzb2,Spn6MLzb2,Spn7MLzb2,Spn8MLzb2,Spn9MLzb2, & + Spn1MLzb3,Spn2MLzb3,Spn3MLzb3,Spn4MLzb3,Spn5MLzb3,Spn6MLzb3,Spn7MLzb3,Spn8MLzb3,Spn9MLzb3 & + /), (/9, 3/) ) + +INTEGER, PARAMETER :: SpnTDxb(9,3) = RESHAPE( (/ & + Spn1TDxb1,Spn2TDxb1,Spn3TDxb1,Spn4TDxb1,Spn5TDxb1,Spn6TDxb1,Spn7TDxb1,Spn8TDxb1,Spn9TDxb1, & + Spn1TDxb2,Spn2TDxb2,Spn3TDxb2,Spn4TDxb2,Spn5TDxb2,Spn6TDxb2,Spn7TDxb2,Spn8TDxb2,Spn9TDxb2, & + Spn1TDxb3,Spn2TDxb3,Spn3TDxb3,Spn4TDxb3,Spn5TDxb3,Spn6TDxb3,Spn7TDxb3,Spn8TDxb3,Spn9TDxb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnTDyb(9,3) = RESHAPE( (/ & + Spn1TDyb1,Spn2TDyb1,Spn3TDyb1,Spn4TDyb1,Spn5TDyb1,Spn6TDyb1,Spn7TDyb1,Spn8TDyb1,Spn9TDyb1, & + Spn1TDyb2,Spn2TDyb2,Spn3TDyb2,Spn4TDyb2,Spn5TDyb2,Spn6TDyb2,Spn7TDyb2,Spn8TDyb2,Spn9TDyb2, & + Spn1TDyb3,Spn2TDyb3,Spn3TDyb3,Spn4TDyb3,Spn5TDyb3,Spn6TDyb3,Spn7TDyb3,Spn8TDyb3,Spn9TDyb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnTDzb(9,3) = RESHAPE( (/ & + Spn1TDzb1,Spn2TDzb1,Spn3TDzb1,Spn4TDzb1,Spn5TDzb1,Spn6TDzb1,Spn7TDzb1,Spn8TDzb1,Spn9TDzb1, & + Spn1TDzb2,Spn2TDzb2,Spn3TDzb2,Spn4TDzb2,Spn5TDzb2,Spn6TDzb2,Spn7TDzb2,Spn8TDzb2,Spn9TDzb2, & + Spn1TDzb3,Spn2TDzb3,Spn3TDzb3,Spn4TDzb3,Spn5TDzb3,Spn6TDzb3,Spn7TDzb3,Spn8TDzb3,Spn9TDzb3 & + /), (/9, 3/) ) + +INTEGER, PARAMETER :: SpnRDxb(9,3) = RESHAPE( (/ & + Spn1RDxb1,Spn2RDxb1,Spn3RDxb1,Spn4RDxb1,Spn5RDxb1,Spn6RDxb1,Spn7RDxb1,Spn8RDxb1,Spn9RDxb1, & + Spn1RDxb2,Spn2RDxb2,Spn3RDxb2,Spn4RDxb2,Spn5RDxb2,Spn6RDxb2,Spn7RDxb2,Spn8RDxb2,Spn9RDxb2, & + Spn1RDxb3,Spn2RDxb3,Spn3RDxb3,Spn4RDxb3,Spn5RDxb3,Spn6RDxb3,Spn7RDxb3,Spn8RDxb3,Spn9RDxb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnRDyb(9,3) = RESHAPE( (/ & + Spn1RDyb1,Spn2RDyb1,Spn3RDyb1,Spn4RDyb1,Spn5RDyb1,Spn6RDyb1,Spn7RDyb1,Spn8RDyb1,Spn9RDyb1, & + Spn1RDyb2,Spn2RDyb2,Spn3RDyb2,Spn4RDyb2,Spn5RDyb2,Spn6RDyb2,Spn7RDyb2,Spn8RDyb2,Spn9RDyb2, & + Spn1RDyb3,Spn2RDyb3,Spn3RDyb3,Spn4RDyb3,Spn5RDyb3,Spn6RDyb3,Spn7RDyb3,Spn8RDyb3,Spn9RDyb3 & + /), (/9, 3/) ) +INTEGER, PARAMETER :: SpnRDzb(9,3) = RESHAPE( (/ & + Spn1RDzb1,Spn2RDzb1,Spn3RDzb1,Spn4RDzb1,Spn5RDzb1,Spn6RDzb1,Spn7RDzb1,Spn8RDzb1,Spn9RDzb1, & + Spn1RDzb2,Spn2RDzb2,Spn3RDzb2,Spn4RDzb2,Spn5RDzb2,Spn6RDzb2,Spn7RDzb2,Spn8RDzb2,Spn9RDzb2, & + Spn1RDzb3,Spn2RDzb3,Spn3RDzb3,Spn4RDzb3,Spn5RDzb3,Spn6RDzb3,Spn7RDzb3,Spn8RDzb3,Spn9RDzb3 & + /), (/9, 3/) ) + + +INTEGER, PARAMETER :: TwHtALxt(9) = (/ & + TwHt1ALxt,TwHt2ALxt,TwHt3ALxt,TwHt4ALxt,TwHt5ALxt,TwHt6ALxt,TwHt7ALxt,TwHt8ALxt,TwHt9ALxt /) +INTEGER, PARAMETER :: TwHtALyt(9) = (/ & + TwHt1ALyt,TwHt2ALyt,TwHt3ALyt,TwHt4ALyt,TwHt5ALyt,TwHt6ALyt,TwHt7ALyt,TwHt8ALyt,TwHt9ALyt /) +INTEGER, PARAMETER :: TwHtALzt(9) = (/ & + TwHt1ALzt,TwHt2ALzt,TwHt3ALzt,TwHt4ALzt,TwHt5ALzt,TwHt6ALzt,TwHt7ALzt,TwHt8ALzt,TwHt9ALzt /) + +INTEGER, PARAMETER :: TwHtMLxt(9) = (/ & + TwHt1MLxt,TwHt2MLxt,TwHt3MLxt,TwHt4MLxt,TwHt5MLxt,TwHt6MLxt,TwHt7MLxt,TwHt8MLxt,TwHt9MLxt /) +INTEGER, PARAMETER :: TwHtMLyt(9) = (/ & + TwHt1MLyt,TwHt2MLyt,TwHt3MLyt,TwHt4MLyt,TwHt5MLyt,TwHt6MLyt,TwHt7MLyt,TwHt8MLyt,TwHt9MLyt /) +INTEGER, PARAMETER :: TwHtMLzt(9) = (/ & + TwHt1MLzt,TwHt2MLzt,TwHt3MLzt,TwHt4MLzt,TwHt5MLzt,TwHt6MLzt,TwHt7MLzt,TwHt8MLzt,TwHt9MLzt /) + +INTEGER, PARAMETER :: TwHtFLxt(9) = (/ & + TwHt1FLxt,TwHt2FLxt,TwHt3FLxt,TwHt4FLxt,TwHt5FLxt,TwHt6FLxt,TwHt7FLxt,TwHt8FLxt,TwHt9FLxt /) +INTEGER, PARAMETER :: TwHtFLyt(9) = (/ & + TwHt1FLyt,TwHt2FLyt,TwHt3FLyt,TwHt4FLyt,TwHt5FLyt,TwHt6FLyt,TwHt7FLyt,TwHt8FLyt,TwHt9FLyt /) +INTEGER, PARAMETER :: TwHtFLzt(9) = (/ & + TwHt1FLzt,TwHt2FLzt,TwHt3FLzt,TwHt4FLzt,TwHt5FLzt,TwHt6FLzt,TwHt7FLzt,TwHt8FLzt,TwHt9FLzt /) + +INTEGER, PARAMETER :: TwHtTDxt(9) = (/ & + TwHt1TDxt,TwHt2TDxt,TwHt3TDxt,TwHt4TDxt,TwHt5TDxt,TwHt6TDxt,TwHt7TDxt,TwHt8TDxt,TwHt9TDxt /) +INTEGER, PARAMETER :: TwHtTDyt(9) = (/ & + TwHt1TDyt,TwHt2TDyt,TwHt3TDyt,TwHt4TDyt,TwHt5TDyt,TwHt6TDyt,TwHt7TDyt,TwHt8TDyt,TwHt9TDyt /) +INTEGER, PARAMETER :: TwHtTDzt(9) = (/ & + TwHt1TDzt,TwHt2TDzt,TwHt3TDzt,TwHt4TDzt,TwHt5TDzt,TwHt6TDzt,TwHt7TDzt,TwHt8TDzt,TwHt9TDzt /) + +INTEGER, PARAMETER :: TwHtRDxt(9) = (/ & + TwHt1RDxt,TwHt2RDxt,TwHt3RDxt,TwHt4RDxt,TwHt5RDxt,TwHt6RDxt,TwHt7RDxt,TwHt8RDxt,TwHt9RDxt /) +INTEGER, PARAMETER :: TwHtRDyt(9) = (/ & + TwHt1RDyt,TwHt2RDyt,TwHt3RDyt,TwHt4RDyt,TwHt5RDyt,TwHt6RDyt,TwHt7RDyt,TwHt8RDyt,TwHt9RDyt /) +INTEGER, PARAMETER :: TwHtRDzt(9) = (/ & + TwHt1RDzt,TwHt2RDzt,TwHt3RDzt,TwHt4RDzt,TwHt5RDzt,TwHt6RDzt,TwHt7RDzt,TwHt8RDzt,TwHt9RDzt /) + +INTEGER, PARAMETER :: TwHtTPxi(9) = (/ & + TwHt1TPxi,TwHt2TPxi,TwHt3TPxi,TwHt4TPxi,TwHt5TPxi,TwHt6TPxi,TwHt7TPxi,TwHt8TPxi,TwHt9TPxi /) +INTEGER, PARAMETER :: TwHtTPyi(9) = (/ & + TwHt1TPyi,TwHt2TPyi,TwHt3TPyi,TwHt4TPyi,TwHt5TPyi,TwHt6TPyi,TwHt7TPyi,TwHt8TPyi,TwHt9TPyi /) +INTEGER, PARAMETER :: TwHtTPzi(9) = (/ & + TwHt1TPzi,TwHt2TPzi,TwHt3TPzi,TwHt4TPzi,TwHt5TPzi,TwHt6TPzi,TwHt7TPzi,TwHt8TPzi,TwHt9TPzi /) + +INTEGER, PARAMETER :: TwHtRPxi(9) = (/ & + TwHt1RPxi,TwHt2RPxi,TwHt3RPxi,TwHt4RPxi,TwHt5RPxi,TwHt6RPxi,TwHt7RPxi,TwHt8RPxi,TwHt9RPxi /) +INTEGER, PARAMETER :: TwHtRPyi(9) = (/ & + TwHt1RPyi,TwHt2RPyi,TwHt3RPyi,TwHt4RPyi,TwHt5RPyi,TwHt6RPyi,TwHt7RPyi,TwHt8RPyi,TwHt9RPyi /) +INTEGER, PARAMETER :: TwHtRPzi(9) = (/ & + TwHt1RPzi,TwHt2RPzi,TwHt3RPzi,TwHt4RPzi,TwHt5RPzi,TwHt6RPzi,TwHt7RPzi,TwHt8RPzi,TwHt9RPzi /) + +END MODULE ElastoDyn_Parameters +!********************************************************************************************************************************** +!> This module contains file I/O routines and data validation routines. +MODULE ElastoDyn_IO + + USE ElastoDyn_Parameters + USE ElastoDyn_Types + + IMPLICIT NONE + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reads the input file and stores all the data in the ED_InputFile structure. +!! It does not perform data validation. +SUBROUTINE ED_ReadInput( InputFileName, MeshFile, InputFileData, ReadAdmVals, BD4Blades, Default_DT, OutFileRoot, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + REAL(DbKi), INTENT(IN) :: Default_DT !< The default DT (from glue code) + + CHARACTER(*), INTENT(IN) :: InputFileName !< Name of the input file + CHARACTER(*), INTENT(IN) :: MeshFile !< File that contains the blade mesh information (AeroDyn input file for now) -- later this info will be defined in one of the ED input files. + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of all the output files written by this routine. + + TYPE(ED_InputFile), INTENT(OUT) :: InputFileData !< Data stored in the module's input file + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + LOGICAL, INTENT(IN) :: ReadAdmVals !< Determines if we should read the Adams-only values + LOGICAL, INTENT(IN) :: BD4Blades !< Determines if we should read the blade values (true=don't read this file; use BeamDyn for blades instead) + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(*), PARAMETER :: RoutineName = 'ED_ReadInput' + + CHARACTER(1024) :: BldFile(MaxBl) ! File that contains the blade information (specified in the primary input file) + CHARACTER(1024) :: FurlFile ! File that contains the furl information (specified in the primary input file) + CHARACTER(1024) :: TwrFile ! File that contains the tower information (specified in the primary input file) + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = '' + + InputFileData%DT = Default_DT ! the glue code's suggested DT for the module (may be overwritten in ReadPrimaryFile()) + + ! get the primary/platform input-file data + ! sets UnEcho, BldFile, FurlFile, TwrFile + + CALL ReadPrimaryFile( InputFileName, InputFileData, BldFile, FurlFile, TwrFile, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + + ! get the furling input-file data + InputFileData%Furling = .FALSE. ! Furling is not supported in this version of ElastoDyn + + IF ( InputFileData%Furling ) THEN + CALL ReadFurlFile( FurlFile, InputFileData, UnEcho, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + ELSE ! initialize all of the data that would be read by ReadFurlFile() + InputFileData%RFrlDOF = .FALSE. + InputFileData%TFrlDOF = .FALSE. + InputFileData%RotFurl = 0.0_ReKi ! Radians + InputFileData%TailFurl = 0.0_ReKi + InputFileData%Yaw2Shft = 0.0 + InputFileData%ShftSkew = 0.0 + InputFileData%RFrlCMxn = 0.0 + InputFileData%RFrlCMyn = 0.0 + InputFileData%RFrlCMzn = 0.0 + InputFileData%BoomCMxn = 0.0 + InputFileData%BoomCMyn = 0.0 + InputFileData%BoomCMzn = 0.0 + InputFileData%TFinCMxn = 0.0 + InputFileData%TFinCMyn = 0.0 + InputFileData%TFinCMzn = 0.0 + InputFileData%TFinCPxn = 0.0 + InputFileData%TFinCPyn = 0.0 + InputFileData%TFinCPzn = 0.0 + InputFileData%TFinSkew = 0.0 + InputFileData%TFinTilt = 0.0 + InputFileData%TFinBank = 0.0 + InputFileData%RFrlPntxn = 0.0 + InputFileData%RFrlPntyn = 0.0 + InputFileData%RFrlPntzn = 0.0 + InputFileData%RFrlSkew = 0.0 + InputFileData%RFrlTilt = 0.0 + InputFileData%TFrlPntxn = 0.0 + InputFileData%TFrlPntyn = 0.0 + InputFileData%TFrlPntzn = 0.0 + InputFileData%TFrlSkew = 0.0 + InputFileData%TFrlTilt = 0.0 + InputFileData%RFrlMass = 0.0 + InputFileData%BoomMass = 0.0 + InputFileData%TFinMass = 0.0 + InputFileData%RFrlIner = 0.0 + InputFileData%TFrlIner = 0.0 + InputFileData%RFrlMod = 0 + InputFileData%RFrlSpr = 0.0 + InputFileData%RFrlDmp = 0.0 + InputFileData%RFrlCDmp = 0.0 + InputFileData%RFrlUSSP = 0.0 + InputFileData%RFrlDSSP = 0.0 + InputFileData%RFrlUSSpr = 0.0 + InputFileData%RFrlDSSpr = 0.0 + InputFileData%RFrlUSDP = 0.0 + InputFileData%RFrlDSDP = 0.0 + InputFileData%RFrlUSDmp = 0.0 + InputFileData%RFrlDSDmp = 0.0 + InputFileData%TFrlMod = 0 + InputFileData%TFrlSpr = 0.0 + InputFileData%TFrlDmp = 0.0 + InputFileData%TFrlCDmp = 0.0 + InputFileData%TFrlUSSP = 0.0 + InputFileData%TFrlDSSP = 0.0 + InputFileData%TFrlUSSpr = 0.0 + InputFileData%TFrlDSSpr = 0.0 + InputFileData%TFrlUSDP = 0.0 + InputFileData%TFrlDSDP = 0.0 + InputFileData%TFrlUSDmp = 0.0 + InputFileData%TFrlDSDmp = 0.0 + END IF + + + ! get the blade input-file data (from blade and mesh files) + IF (.NOT. BD4Blades) THEN + CALL ReadBladeInputs ( BldFile, MeshFile, ReadAdmVals, InputFileData, UnEcho, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + END IF + + ! get the tower input-file data + + CALL ReadTowerFile( TwrFile, InputFileData, ReadAdmVals, UnEcho, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + + + + ! close the echo file (if opened) + + CALL Cleanup() + + +CONTAINS + !............................................................................................................................... + SUBROUTINE Cleanup() + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + END SUBROUTINE Cleanup + +END SUBROUTINE ED_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine validates the input file data +SUBROUTINE ED_ValidateInput( InputFileData, BD4Blades, Linearize, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + LOGICAL, INTENT(IN) :: BD4Blades !< Determines if we should validate the blade values (true=don't validate; use BeamDyn for blades instead) + LOGICAL, INTENT(IN) :: Linearize !< Flag indicating glue code wants to linearize this module + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! Local variables: + INTEGER(IntKi) :: K ! Blade number + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + CHARACTER(*), PARAMETER :: RoutineName = 'ED_ValidateInput' + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + ! validate the primary input data + CALL ValidatePrimaryData( InputFileData, BD4Blades, Linearize, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! validate the furling input data + CALL ValidateFurlData ( InputFileData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! validate the blade input data + IF (.NOT. BD4Blades) THEN + DO K = 1,InputFileData%NumBl + CALL ValidateBladeData ( InputFileData%InpBl(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':Blade'//TRIM(Num2LStr(K))) + END DO + + !bjj: validate blade discretization, too: + END IF + + + ! validate the tower input data + CALL ValidateTowerData ( InputFileData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! validate the Output parameters: + ! CALL ChckOutLst( InputFileData%OutList, p, ErrStat, ErrMsg ) + +END SUBROUTINE ED_ValidateInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads the data from the blade and mesh inputs files. +!! This routines assumes that InputFileData%NumBl has already been set. +SUBROUTINE ReadBladeInputs ( BldFile, MeshFile, ReadAdmVals, InputFileData, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData !< Input file data Data for Blade K stored in the module's input file + CHARACTER(*), INTENT(IN) :: BldFile(:) !< The array of file names containing blade information + CHARACTER(*), INTENT(IN) :: MeshFile !< The file names containing blade mesh information (for now, the aerodyn primary file) + INTEGER(IntKi), INTENT(IN) :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error ID + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Message describing error + LOGICAL, INTENT(IN) :: ReadAdmVals !< Logical to determine if Adams inputs should be read from file + + + ! Local variables: + INTEGER(IntKi) :: K ! Blade number + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + LOGICAL :: ReadFile ! determines if an input file for a blade is the same as the file for the previous blade + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + CHARACTER(*), PARAMETER :: RoutineName = 'ReadBladeInputs' + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + + ! Allocate space for the input file data + ALLOCATE( InputFileData%InpBlMesh( 1_IntKi ), STAT=ErrStat2 ) ! for now, we're assuming the discretization is the same on all blades + IF ( ErrStat2 /= 0 ) THEN + call SetErrStat(ErrID_Fatal,'Error allocating InpBlMesh array',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ALLOCATE( InputFileData%InpBl( InputFileData%NumBl ), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + call SetErrStat(ErrID_Fatal,'Error allocating InpBl array',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Get the blade discretization here: + IF ( len_trim(MeshFile) == 0 ) THEN + InputFileData%InpBlMesh(1)%BldNodes = InputFileData%BldNodes + ELSE + ! we will get the discretization from AeroDyn's input file + CALL ReadBladeMeshFileAD( InputFileData%InpBlMesh(1), MeshFile, UnEc, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + ! Read the input file(s) for all of the blades: + ReadFile = .TRUE. + DO K = 1,InputFileData%NumBl + + IF ( ReadFile ) THEN + + ! Add a separator to the echo file if appropriate. + + IF ( UnEc > 0 ) THEN + WRITE (UnEc,'(//,A,/)') 'Blade '//TRIM( Num2LStr( K ) )//' input data from file "'//TRIM( BldFile(K) )//'":' + END IF + + CALL ReadBladeFile( BldFile(K), InputFileData%InpBl(K), ReadAdmVals, UnEc, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + ELSE + CALL ED_CopyBladeInputData( InputFileData%InpBl(K-1), InputFileData%InpBl(K), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + ! bjj: we could just read the file again... + + END IF + + ! If the next file is the same as this one, don't read it again: + + IF ( K /= InputFileData%NumBl ) ReadFile = BldFile(K) /= BldFile( K + 1 ) + + END DO + + + RETURN + +END SUBROUTINE ReadBladeInputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads a blade input file. +SUBROUTINE ReadBladeFile ( BldFile, BladeKInputFileData, ReadAdmVals, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + TYPE(BladeInputData), INTENT(INOUT) :: BladeKInputFileData !< Data for Blade K stored in the module's input file + CHARACTER(*), INTENT(IN) :: BldFile !< Name of the blade input file data + LOGICAL, INTENT(IN) :: ReadAdmVals !< Logical to determine if Adams inputs should be read from file + INTEGER(IntKi), INTENT(IN) :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local variables: + + REAL(ReKi) :: AdjBlMs ! Factor to adjust blade mass density. + REAL(ReKi) :: AdjEdSt ! Factor to adjust edge stiffness. + REAL(ReKi) :: AdjFlSt ! Factor to adjust flap stiffness. + + REAL(ReKi) :: TmpRAry(17) ! Temporary variable to read table from file (up to 17 columns) + + INTEGER(IntKi) :: I ! A generic DO index. + INTEGER( IntKi ) :: UnIn ! Unit number for reading file + INTEGER( IntKi ) :: NInputCols ! Number of columns to be read from the file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName='ReadBladeFile' + + ErrStat = ErrID_None + ErrMsg = "" + + UnIn = -1 + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + + + ! Open the input file for blade K. + + CALL OpenFInpFile ( UnIn, BldFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- HEADER ------------------------------------------------------- + + ! Skip the header. + + CALL ReadCom ( UnIn, BldFile, 'unused blade file header line 1', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, BldFile, 'unused blade file header line 2', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- BLADE PARAMETERS --------------------------------------------- + + ! Skip the comment line. + + CALL ReadCom ( UnIn, BldFile, 'blade parameters', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NBlInpSt - Number of blade input stations. + + CALL ReadVar ( UnIn, BldFile, BladeKInputFileData%NBlInpSt, 'NBlInpSt', 'Number of blade input stations', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! .......... Allocate the arrays based on this NBlInpSt input .......... + CALL Alloc_BladeInputProperties( BladeKInputFileData, ReadAdmVals, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! BldFlDmp - Blade structural damping ratios in flapwise direction. + + CALL ReadAryLines( UnIn, BldFile, BladeKInputFileData%BldFlDmp, SIZE(BladeKInputFileData%BldFlDmp), 'BldFlDmp', & + 'Blade structural damping ratios in flapwise direction', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! BldEdDmp - Blade structural damping ratios in edgewise direction. + + CALL ReadAryLines( UnIn, BldFile, BladeKInputFileData%BldEdDmp, SIZE(BladeKInputFileData%BldEdDmp), 'BldEdDmp', & + 'Blade structural damping ratios in edgewise direction', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! -------------- BLADE ADJUSTMENT FACTORS ------------------------------------- + + + ! Skip the comment line. + + CALL ReadCom ( UnIn, BldFile, 'blade adjustment factors', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! FlStTunr(1) - Blade flapwise modal stiffness tuners. + + CALL ReadAryLines ( UnIn, BldFile, BladeKInputFileData%FlStTunr, SIZE(BladeKInputFileData%FlStTunr), 'FlStTunr', & + 'Blade flapwise modal stiffness tuners', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! AdjBlMs - Factor to adjust blade mass density. + + CALL ReadVar ( UnIn, BldFile, AdjBlMs, 'AdjBlMs', 'Factor to adjust blade mass density', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! AdjFlSt - Factor to adjust blade flap stiffness. + + CALL ReadVar ( UnIn, BldFile, AdjFlSt, 'AdjFlSt', 'Factor to adjust blade flap stiffness', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! AdjEdSt - Factor to adjust blade edge stiffness. + + CALL ReadVar ( UnIn, BldFile, AdjEdSt, 'AdjEdSt', 'Factor to adjust blade edge stiffness', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Check the locally-defined adjustment factors: AdjBlMs, AdjFlSt, AdjEdSt + + IF ( AdjBlMs <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjBlMs must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + IF ( AdjFlSt <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjFlSt must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + IF ( AdjEdSt <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjEdSt must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + + ! -------------- DISTRIBUTED BLADE PROPERTIES --------------------------------- + + + ! Skip the comment lines. + + CALL ReadCom ( UnIn, BldFile, 'distributed blade parameters' , ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadCom ( UnIn, BldFile, 'distributed-blade-parameter names', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadCom ( UnIn, BldFile, 'distributed-blade-parameter units', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Read the table. + + IF ( ReadAdmVals ) THEN + NInputCols = 17 + ELSE + NInputCols = 6 + END IF + + + DO I=1,BladeKInputFileData%NBlInpSt + + CALL ReadAry( UnIn, BldFile, TmpRAry, NInputCols, 'Line'//TRIM(Num2LStr(I)), 'Blade input station table', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + BladeKInputFileData%BlFract( I) = TmpRAry(1) + BladeKInputFileData%PitchAx( I) = TmpRAry(2) + BladeKInputFileData%StrcTwst(I) = TmpRAry(3)*D2R ! Input in degrees; converted to radians here + BladeKInputFileData%BMassDen(I) = TmpRAry(4)*AdjBlMs ! Apply the correction factors to the elemental data. + BladeKInputFileData%FlpStff( I) = TmpRAry(5)*AdjFlSt ! Apply the correction factors to the elemental data. + BladeKInputFileData%EdgStff( I) = TmpRAry(6)*AdjEdSt ! Apply the correction factors to the elemental data. + + IF ( NInputCols > 6 ) THEN + BladeKInputFileData%GJStff( I) = TmpRAry( 7) + BladeKInputFileData%EAStff( I) = TmpRAry( 8) + BladeKInputFileData%Alpha( I) = TmpRAry( 9) + BladeKInputFileData%FlpIner( I) = TmpRAry(10) + BladeKInputFileData%EdgIner( I) = TmpRAry(11) + BladeKInputFileData%PrecrvRef(I) = TmpRAry(12) + BladeKInputFileData%PreswpRef(I) = TmpRAry(13) + BladeKInputFileData%FlpcgOf( I) = TmpRAry(14) + BladeKInputFileData%EdgcgOf( I) = TmpRAry(15) + BladeKInputFileData%FlpEAOf( I) = TmpRAry(16) + BladeKInputFileData%EdgEAOf( I) = TmpRAry(17) + END IF + ENDDO ! I + + + + ! -------------- BLADE MODE SHAPES -------------------------------------------- + + + ! Skip the comment line. + + CALL ReadCom ( UnIn, BldFile, 'blade mode shapes', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BldFl1Sh - Blade-flap mode-1 shape coefficients. + CALL ReadAryLines ( UnIn, BldFile, BladeKInputFileData%BldFl1Sh, SIZE(BladeKInputFileData%BldFl1Sh), 'BldFl1Sh', & + 'Blade-flap mode-1 shape coefficients', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BldFl2Sh - Blade-flap mode-2 shape coefficients. + + CALL ReadAryLines ( UnIn, BldFile, BladeKInputFileData%BldFl2Sh, SIZE(BladeKInputFileData%BldFl2Sh), 'BldFl2Sh', & + 'Blade-flap mode-2 shape coefficients', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BldEdgSh - Blade-edge mode shape coefficients. + + CALL ReadAryLines ( UnIn, BldFile, BladeKInputFileData%BldEdgSh, SIZE(BladeKInputFileData%BldEdgSh), 'BldEdgSh', & + 'Blade-edge mode shape coefficients', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! -------------- END OF FILE -------------------------------------------- + + ! Close the blade file. + + call Cleanup() + RETURN + + +CONTAINS + + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE( UnIn ) + END SUBROUTINE Cleanup + +END SUBROUTINE ReadBladeFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the AeroDyn v14.00.00 input file to get the +!! blade discretization used in the structural dynamics module. +SUBROUTINE ReadBladeMeshFileAD( BladeKInputFileMesh, MeshFile, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + + TYPE(ED_BladeMeshInputData), INTENT(INOUT) :: BladeKInputFileMesh !< All the data in the ElastoDyn input file + CHARACTER(*), INTENT(IN) :: MeshFile !< Name of the AeroDyn input file data (for mesh) + + INTEGER(IntKi), INTENT(IN) :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + INTEGER(IntKi), PARAMETER :: NInputCols = 4 ! Number of input columns to be read from the file + REAL(ReKi) :: TmpRAry(NInputCols) ! Temporary variable to read table from file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: NumLin2Skp ! number of lines to read + INTEGER(IntKi) :: NumFoil ! number of airfoil lines to skip in the AD input file. + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName = 'ReadBladeMeshFileAD' + CHARACTER(1024) :: Line ! Temporary string. +! CHARACTER(1024) :: TmpStr(1) ! Temporary string. + + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the AeroDyn input file. + + CALL OpenFInpFile ( UnIn, MeshFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Add a separator to the echo file if appropriate. + + IF ( UnEc > 0 ) WRITE (UnEc,'(//,A,/)') 'Mesh input data from (AeroDyn input) file "'//TRIM( MeshFile )//'":' + + + ! -------------- HEADER ------------------------------------------------------- + ! BJJ: This file is AeroDyn's input file. Until we decide on a format for the + ! structural dynamics input, we will get this information from AeroDyn like we + ! used to. + + DO I = 1,9 + CALL ReadCom ( UnIn, MeshFile, 'AeroDyn input (for structural dynamics mesh)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! See if the next line is "NEWTOWER". If it is, read 7 more lines. If not, read 5 more lines. + + CALL ReadVar( UnIn, MeshFile, Line, VarName='NewTowerModel?', VarDescr='Check for tower influence model', ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Check if this is the "special string" to indicate the new tower influence model + + CALL Conv2UC( Line ) + IF ( INDEX(Line, "NEWTOWER" ) > 0 ) THEN + NumLin2Skp = 7 + ELSE + NumLin2Skp = 5 + END IF + + DO I = 1,NumLin2Skp + CALL ReadCom ( UnIn, MeshFile, 'AeroDyn input (for structural dynamics mesh)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END DO + + CALL ReadVar ( UnIn, MeshFile, NumFoil, 'NumFoil', & + 'Number of airfoil lines to skip in AeroDyn input (for structural dynamics mesh)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + DO I = 1,NumFoil + CALL ReadCom ( UnIn, MeshFile, 'AeroDyn input (for structural dynamics mesh)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END DO + + + ! -------------- Blade Mesh Data -------------------------------------------------- + + ! Read in the number of blade elements + CALL ReadVar( UnIn, MeshFile, BladeKInputFileMesh%BldNodes, 'BldNodes', 'Number of blade elements', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Allocate the arrays to store input + CALL Alloc_BladeMeshInputProperties( BladeKInputFileMesh, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Read comment line for the element table + CALL ReadCom( UnIn, MeshFile, 'Blade element table headers', ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + DO I = 1, BladeKInputFileMesh%BldNodes + + CALL ReadAry( UnIn, MeshFile, TmpRAry, NInputCols, 'Blade element line'//TRIM(Num2LStr(I)), 'Blade element input table', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + BladeKInputFileMesh%RNodes( I) = TmpRAry(1) + BladeKInputFileMesh%AeroTwst(I) = TmpRAry(2)*D2R !Convert input file data (degrees) to radians + BladeKInputFileMesh%Chord( I) = TmpRAry(4) + + END DO + + !bjj: move this to a validation routine if we plan to keep AD14 stuff in ElastoDyn: + IF ( ANY( BladeKInputFileMesh%Chord < 0.0_ReKi ) ) THEN + call SetErrStat( ErrID_Fatal, 'Chord length must be larger than 0 meters.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + ! Close the input file: + + CALL cleanup() + RETURN + + +CONTAINS + SUBROUTINE Cleanup() + CLOSE( UnIn ) + END SUBROUTINE Cleanup +END SUBROUTINE ReadBladeMeshFileAD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads the furling file input and converts units as appropriate. +SUBROUTINE ReadFurlFile( FurlFile, InputFileData, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables: + + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the ElastoDyn input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + INTEGER(IntKi), INTENT(IN) :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: FurlFile !< Name of the furling input file data + + ! Local variables: + + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*),PARAMETER :: RoutineName = 'ReadFurlFile' + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the furling input file. + + CALL OpenFInpFile ( UnIn, FurlFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Add a separator to the echo file if appropriate. + + IF ( UnEc > 0 ) WRITE (UnEc,'(//,A,/)') 'Furling input data from file "'//TRIM( FurlFile )//'":' + + + ! -------------- FILE HEADER --------------------------------------------------- + + CALL ReadCom ( UnIn, FurlFile, 'unused tower furling header line 1', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, FurlFile, 'unused tower furling header line 2', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, FurlFile, 'unused tower furling header line 3', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- Furling FEATURE SWITCHES -------------------------------------- + + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'degree of freedom switches (cont)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! RFrlDOF - Rotor-furl DOF. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDOF, 'RFrlDOF', 'Rotor-furl DOF (flag)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlDOF - Tail-furl DOF. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDOF, 'TFrlDOF', 'Tail-furl DOF (flag)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- Furling INITIAL CONDITIONS ------------------------------------ + + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'initial conditions (cont)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RotFurl - Initial or fixed rotor-furl angle (read in degrees, converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RotFurl, 'RotFurl', 'Initial or fixed rotor-furl angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%RotFurl = InputFileData%RotFurl*D2R + + + ! TailFurl - Initial or fixed tail-furl angle (read in degrees, converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TailFurl, 'TailFurl', 'Initial or fixed tail-furl angle (deg)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%TailFurl = InputFileData%TailFurl*D2R + + + ! -------------- TURBINE CONFIGURATION (CONT) --------------------------------- + + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'turbine configuration (cont)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Yaw2Shft - Lateral distance from yaw axis to rotor shaft. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%Yaw2Shft, 'Yaw2Shft', & + 'Lateral distance from yaw axis to rotor shaft (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! ShftSkew - Rotor shaft skew angle (read in degrees and converted to radians here). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%ShftSkew, 'ShftSkew', 'Rotor shaft skew angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%ShftSkew = InputFileData%ShftSkew *D2R + + + ! RFrlCMxn - Downwind distance from tower-top to CM of structure that furls with the rotor (not including rotor). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlCMxn, 'RFrlCMxn', & + 'Downwind distance from tower-top to rotor-furl CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlCMyn - Lateral distance from tower-top to CM of structure that furls with the rotor (not including rotor). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlCMyn, 'RFrlCMyn', & + 'Lateral distance from tower-top to rotor-furl CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlCMzn - Vertical distance from tower-top to CM of structure that furls with the rotor (not including rotor). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlCMzn, 'RFrlCMzn', & + 'Vertical distance from tower-top to rotor-furl CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BoomCMxn - Downwind distance from tower-top to tail boom CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%BoomCMxn, 'BoomCMxn', & + 'Downwind distance from tower-top to tail boom CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BoomCMyn - Lateral distance from tower-top to tail boom CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%BoomCMyn, 'BoomCMyn', & + 'Lateral distance from tower-top to tail boom CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! BoomCMzn - Vertical distance from tower-top to tail boom CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%BoomCMzn, 'BoomCMzn', & + 'Vertical distance from tower-top to tail boom CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCMxn - Downwind distance from tower-top to tail fin CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCMxn, 'TFinCMxn', & + 'Downwind distance from tower-top to tail fin CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCMyn - Lateral distance from tower-top to tail fin CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCMyn, 'TFinCMyn', & + 'Lateral distance from tower-top to tail fin CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCMzn - Vertical distance from tower-top to tail fin CM. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCMzn, 'TFinCMzn', & + 'Vertical distance from tower-top to tail fin CM (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCPxn - Downwind distance from tower-top to tail fin CP. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCPxn, 'TFinCPxn', & + 'Downwind distance from tower-top to tail fin CP (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCPyn - Lateral distance from tower-top to tail fin CP. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCPyn, 'TFinCPyn', & + 'Lateral distance from tower-top to tail fin CP (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinCPzn - Vertical distance from tower-top to tail fin CP. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinCPzn, 'TFinCPzn', & + 'Vertical distance from tower-top to tail fin CP (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinSkew - Tail fin chordline skew angle (read in degrees, converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinSkew, 'TFinSkew', 'Tail fin chordline skew angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFinSkew = InputFileData%TFinSkew*D2R + + + ! TFinTilt - Tail fin chordline tilt angle (read in degrees, converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinTilt, 'TFinTilt', 'Tail fin chordline tilt angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFinTilt = InputFileData%TFinTilt *D2R + + + ! TFinBank - Tail fin planform bank angle (read in degrees, converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinBank, 'TFinBank', 'Tail fin planform bank angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFinBank = InputFileData%TFinBank *D2R + + + ! RFrlPntxn - Downwind distance from tower-top to arbitrary point on rotor-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlPntxn, 'RFrlPntxn', & + 'Downwind distance from tower-top to arbitrary point on rotor-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlPntyn - Lateral distance from tower-top to arbitrary point on rotor-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlPntyn, 'RFrlPntyn', & + 'Lateral distance from tower-top to arbitrary point on rotor-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlPntzn - Vertical distance from tower-top to arbitrary point on rotor-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlPntzn, 'RFrlPntzn', & + 'Vertical distance from tower-top to arbitrary point on rotor-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlSkew - Rotor-furl axis skew angle (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlSkew, 'RFrlSkew', 'Rotor-furl axis skew angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlSkew = InputFileData%RFrlSkew*D2R + + + ! RFrlTilt - Rotor-furl axis tilt angle (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlTilt, 'RFrlTilt', 'Rotor-furl axis tilt angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlTilt = InputFileData%RFrlTilt*D2R + + + ! TFrlPntxn - Downwind distance from tower-top to arbitrary point on tail-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlPntxn, 'TFrlPntxn', & + 'Downwind distance from tower-top to arbitrary point on tail-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlPntyn - Lateral distance from tower-top to arbitrary point on tail-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlPntyn, 'TFrlPntyn', & + 'Lateral distance from tower-top to arbitrary point on tail-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlPntzn - Vertical distance from tower-top to arbitrary point on tail-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlPntzn, 'TFrlPntzn', & + 'Vertical distance from tower-top to arbitrary point on tail-furl axis (m)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlSkew - Tail-furl axis skew angle (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlSkew, 'TFrlSkew', 'Tail-furl axis skew angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlSkew = InputFileData%TFrlSkew *D2R + + + ! TFrlTilt - Tail-furl axis tilt angle (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlTilt, 'TFrlTilt', 'Tail-furl axis tilt angle (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlTilt = InputFileData%TFrlTilt *D2R + + + ! -------------- MASS AND INERTIA (CONT) -------------------------------------- + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'mass and inertia (cont)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! RFrlMass - Mass of structure that furls with the rotor (not including rotor). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlMass, 'RFrlMass', 'Rotor-furl mass (kg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! BoomMass - Tail boom mass. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%BoomMass, 'BoomMass', 'Tail boom mass (kg)',ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFinMass - Tail fin mass. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFinMass, 'TFinMass', 'Tail fin mass (kg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlIner - Inertia of structure that furls with the rotor about the rotor-furl axis (not including rotor). + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlIner, 'RFrlIner', 'Rotor-furl inertia about rotor-furl axis (kg m^2)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlIner - Tail boom inertia about tail-furl axis. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlIner, 'TFrlIner', 'Tail boom inertia about tail-furl axis (kg m^2)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! -------------- ROTOR-FURL --------------------------------------------------- + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'Section heading: Rotor-Furl', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlMod - Rotor-furl spring/damper model switch. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlMod, 'RFrlMod', 'Rotor-furl spring/damper model switch', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlSpr - Rotor-furl spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlSpr, 'RFrlSpr', 'Rotor-furl spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlDmp - Rotor-furl damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDmp, 'RFrlDmp', 'Rotor-furl damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlCDmp - Rotor-furl rate-independent Coulomb-damping moment. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlCDmp, 'RFrlCDmp', 'Rotor-furl rate-independent Coulomb-damping moment (N-m)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlUSSP - Rotor-furl up-stop spring position (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlUSSP, 'RFrlUSSP', 'Rotor-furl up-stop spring position (deg)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlUSSP = InputFileData%RFrlUSSP*D2R + + + ! RFrlDSSP - Rotor-furl down-stop spring position (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDSSP, 'RFrlDSSP', 'Rotor-furl down-stop spring position (deg)', & + ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlDSSP = InputFileData%RFrlDSSP*D2R + + + ! RFrlUSSpr - Rotor-furl up-stop spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlUSSpr, 'RFrlUSSpr', 'Rotor-furl up-stop spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlDSSpr - Rotor-furl down-stop spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDSSpr, 'RFrlDSSpr', 'Rotor-furl down-stop spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlUSDP - Rotor-furl up-stop damper position (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlUSDP, 'RFrlUSDP', 'Rotor-furl up-stop damper position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlUSDP = InputFileData%RFrlUSDP*D2R + + + ! RFrlDSDP - Rotor-furl down-stop damper position (read in degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDSDP, 'RFrlDSDP', 'Rotor-furl down-stop damper position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%RFrlDSDP = InputFileData%RFrlDSDP*D2R + + + ! RFrlUSDmp - Rotor-furl up-stop damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlUSDmp, 'RFrlUSDmp', 'Rotor-furl up-stop damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! RFrlDSDmp - Rotor-furl down-stop damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%RFrlDSDmp, 'RFrlDSDmp', 'Rotor-furl down-stop damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- TAIL-FURL ---------------------------------------------------- + + ! Skip the comment line. + + CALL ReadCom ( UnIn, FurlFile, 'tail-furl', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlMod - Tail-furl spring/damper model switch. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlMod, 'TFrlMod', 'Tail-furl spring/damper model switch', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlSpr - Tail-furl spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlSpr, 'TFrlSpr', 'Tail-furl spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlDmp - Tail-furl damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDmp, 'TFrlDmp', 'Tail-furl damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlCDmp - Tail-furl rate-independent Coulomb-damping moment. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlCDmp, 'TFrlCDmp', 'Tail-furl rate-independent Coulomb-damping moment (N-m)', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlUSSP - Tail-furl up-stop spring position (read as degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlUSSP, 'TFrlUSSP', 'Tail-furl up-stop spring position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlUSSP = InputFileData%TFrlUSSP*D2R + + + ! TFrlDSSP - Tail-furl down-stop spring position (read as degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDSSP, 'TFrlDSSP', 'Tail-furl down-stop spring position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlDSSP = InputFileData%TFrlDSSP*D2R + + + ! TFrlUSSpr - Tail-furl up-stop spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlUSSpr, 'TFrlUSSpr', 'Tail-furl up-stop spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlDSSpr - Tail-furl down-stop spring constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDSSpr, 'TFrlDSSpr', 'Tail-furl down-stop spring constant (N-m/rad)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlUSDP - Tail-furl up-stop damper position. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlUSDP, 'TFrlUSDP', 'Tail-furl up-stop damper position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlUSDP = InputFileData%TFrlUSDP*D2R + + + ! TFrlDSDP - Tail-furl down-stop damper position (read as degrees and converted to radians here) + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDSDP, 'TFrlDSDP', 'Tail-furl down-stop damper position (deg)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%TFrlDSDP = InputFileData%TFrlDSDP*D2R + + + ! TFrlUSDmp - Tail-furl up-stop damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlUSDmp, 'TFrlUSDmp', 'Tail-furl up-stop damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TFrlDSDmp - Tail-furl down-stop damping constant. + + CALL ReadVar ( UnIn, FurlFile, InputFileData%TFrlDSDmp, 'TFrlDSDmp', 'Tail-furl down-stop damping constant (N-m/(rad/s))', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Close the ElastoDyn furling file: + + call Cleanup() + + RETURN +CONTAINS + SUBROUTINE Cleanup() + CLOSE( UnIn ) + END SUBROUTINE Cleanup +END SUBROUTINE ReadFurlFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads the tower file input. +SUBROUTINE ReadTowerFile( TwrFile, InputFileData, ReadAdmVals, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables: + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + INTEGER(IntKi), INTENT(IN) :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + LOGICAL, INTENT(IN) :: ReadAdmVals !< Logical to determine if Adams inputs should be read from file + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: TwrFile !< Name of the tower input file data + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the ElastoDyn input file + + + ! Local variables: + + REAL(ReKi) :: AdjFASt ! Factor to adjust tower fore-aft stiffness + REAL(ReKi) :: AdjSSSt ! Factor to adjust tower side-to-side stiffness + REAL(ReKi) :: AdjTwMa ! Factor to adjust tower mass density + + REAL(ReKi) :: TmpRAry(10) ! Temporary variable to read table from file (up to 10 columns) + + INTEGER(IntKi) :: I ! A generic DO index. + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: NInputCols ! Number of columns to be read from the file + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Err msg + CHARACTER(*), PARAMETER :: RoutineName = 'ReadTowerFile' + + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Open the tower input file. + + CALL OpenFInpFile ( UnIn, TwrFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Add a separator to the echo file if appropriate. + IF ( UnEc > 0 ) WRITE (UnEc,'(//,A,/)') 'Tower input data from file "'//TRIM( TwrFile )//'":' + + + ! -------------- FILE HEADER --------------------------------------------------- + + CALL ReadCom ( UnIn, TwrFile, 'unused tower file header line 1', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, TwrFile, 'unused tower file header line 2', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- TOWER PARAMETERS --------------------------------------------- + + CALL ReadCom ( UnIn, TwrFile, 'heading for tower parameters', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! NTwInpSt - Number of tower input stations. + + CALL ReadVar ( UnIn, TwrFile, InputFileData%NTwInpSt, 'NTwInpSt', 'Number of tower input stations', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Allocate the input arrays based on this NTwInpSt input + CALL Alloc_TowerInputProperties( InputFileData, ReadAdmVals, ErrStat, ErrMsg ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwrFADmp - Tower fore-aft structural damping ratios. + + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwrFADmp, SIZE(InputFileData%TwrFADmp), 'TwrFADmp', & + 'Tower fore-aft structural damping ratios (%)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwrSSDmp - Tower side-to-side structural damping ratios. + + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwrSSDmp, SIZE(InputFileData%TwrSSDmp), 'TwrSSDmp', & + 'Tower side-to-side structural damping ratios (%)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- TOWER ADJUSTMENT FACTORS ------------------------------------- + + + ! Skip the comment line. + CALL ReadCom ( UnIn, TwrFile, 'heading for tower adjustment factors', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! FAStTunr - Tower fore-aft modal stiffness tuners. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%FAStTunr, SIZE(InputFileData%FAStTunr), 'FAStTunr', & + 'Tower fore-aft modal stiffness tuners (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! SSStTunr - Tower side-to-side modal stiffness tuners. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%SSStTunr, SIZE(InputFileData%SSStTunr), 'SSStTunr', & + 'Tower side-to-side modal stiffness tuners (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! AdjTwMa - Factor to adjust tower mass density. + + CALL ReadVar ( UnIn, TwrFile, AdjTwMa, 'AdjTwMa', 'Factor to adjust tower mass density (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! AdjFASt - Factor to adjust tower fore-aft stiffness. + + CALL ReadVar ( UnIn, TwrFile, AdjFASt, 'AdjFASt', 'Factor to adjust tower fore-aft stiffness (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! AdjSSSt - Factor to adjust tower side-to-side stiffness. + + CALL ReadVar ( UnIn, TwrFile, AdjSSSt, 'AdjSSSt', 'Factor to adjust tower side-to-side stiffness (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Check the locally-defined adjustment factors: AdjTwMa, AdjFASt, AdjSSSt + + IF ( AdjTwMa <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjTwMa must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + IF ( AdjFASt <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjFASt must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + IF ( AdjSSSt <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'AdjSSSt must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + END IF + + + ! -------------- DISTRIBUTED TOWER PROPERTIES --------------------------------- + + ! Skip the comment lines. + CALL ReadCom ( UnIn, TwrFile, 'heading for distributed tower parameters', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, TwrFile, 'distributed-tower-parameter names', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadCom ( UnIn, TwrFile, 'distributed-tower-parameter units', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! Read the table. + + IF ( ReadAdmVals ) THEN + NInputCols = 10 + ELSE + NInputCols = 4 + END IF + + + DO I=1,InputFileData%NTwInpSt + + CALL ReadAry( UnIn, TwrFile, TmpRAry, NInputCols, 'Line'//TRIM(Num2LStr(I)), 'Tower input station table', & + ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + InputFileData%HtFract( I) = TmpRAry(1) + InputFileData%TMassDen(I) = TmpRAry(2)*AdjTwMa ! Apply the correction factors to the elemental data. + InputFileData%TwFAStif(I) = TmpRAry(3)*AdjFASt ! Apply the correction factors to the elemental data. + InputFileData%TwSSStif(I) = TmpRAry(4)*AdjSSSt ! Apply the correction factors to the elemental data. + + IF ( NInputCols > 4 ) THEN + InputFileData%TwGJStif(I) = TmpRAry( 5) + InputFileData%TwEAStif(I) = TmpRAry( 6) + InputFileData%TwFAIner(I) = TmpRAry( 7) + InputFileData%TwSSIner(I) = TmpRAry( 8) + InputFileData%TwFAcgOf(I) = TmpRAry( 9) + InputFileData%TwSScgOf(I) = TmpRAry(10) + END IF + + END DO ! I + + + ! -------------- TOWER FORE-AFT MODE SHAPES ----------------------------------- + + + ! Skip the comment line. + CALL ReadCom ( UnIn, TwrFile, 'heading for tower fore-aft mode shapes', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwFAM1Sh - Tower fore-aft mode-1 shape coefficients. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwFAM1Sh, SIZE(InputFileData%TwFAM1Sh), 'TwFAM1Sh', & + 'Tower fore-aft mode-1 shape coefficients (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwFAM2Sh - Tower fore-aft mode-2 shape coefficients. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwFAM2Sh, SIZE(InputFileData%TwFAM2Sh), 'TwFAM2Sh', & + 'Tower fore-aft mode-2 shape coefficients (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! -------------- TOWER SIDE-TO-SIDE MODE SHAPES ------------------------------- + + + ! Skip the comment line. + CALL ReadCom ( UnIn, TwrFile, 'heading for tower side-to-side mode shapes', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwSSM1Sh - Tower side-to-side mode-1 shape coefficients. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwSSM1Sh, SIZE(InputFileData%TwSSM1Sh), 'TwSSM1Sh', & + 'Tower side-to-side mode-1 shape coefficients (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! TwSSM2Sh - Tower side-to-side mode-2 shape coefficients. + CALL ReadAryLines ( UnIn, TwrFile, InputFileData%TwSSM2Sh, SIZE(InputFileData%TwSSM2Sh), 'TwSSM2Sh', & + 'Tower side-to-side mode-2 shape coefficients (-)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Close the tower file. + CALL Cleanup() + + + RETURN +CONTAINS + SUBROUTINE Cleanup() + CLOSE( UnIn ) + END SUBROUTINE Cleanup +END SUBROUTINE ReadTowerFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary ElastoDyn input file and places the values it reads in the InputFileData structure. +!! It opens an echo file if requested and returns the (still-open) echo file to the calling routine. +!! It also returns the names of the BldFile, FurlFile, and TrwFile for further reading of inputs. +SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, BldFile, FurlFile, TwrFile, OutFileRoot, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + INTEGER(IntKi), INTENT(OUT) :: UnEc !< I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(OUT) :: TwrFile !< name of the file containing tower inputs + CHARACTER(*), INTENT(OUT) :: FurlFile !< name of the file containing furling inputs + CHARACTER(*), INTENT(OUT) :: BldFile(MaxBl) !< name of the files containing blade inputs + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of the echo file, possibly opened in this routine + + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the ElastoDyn input file + + ! Local variables: + INTEGER(IntKi) :: I ! loop counter +! INTEGER(IntKi) :: NumOuts ! Number of output channel names read from the file + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: IOS + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(ErrMsgLen) :: ErrMsg_NoAllBldNdOuts ! Temporary Error message + CHARACTER(*), PARAMETER :: RoutineName = 'ReadPrimaryFile' + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + Echo = .FALSE. + UnEc = -1 ! Echo file not opened, yet + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! Allocate arrays for input, based on maximum allowed number of blades and outputs + CALL AllocAry( InputFileData%BlPitch, MaxBl, 'BlPitch input array', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%PreCone, MaxBl, 'Precone input array', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%TipMass, MaxBl, 'TipMass input array', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%OutList, MaxOutPts, "ElastoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Allocate array for holding the list of node outputs + CALL AllocAry( InputFileData%BldNd_OutList, BldNd_MaxOutPts, "BldNd_Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 ! the number of times we've read the file (used for the Echo variable) + DO + !-------------------------- HEADER --------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'File Header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadStr( UnIn, InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- SIMULATION CONTROL -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Simulation Control', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Echo - Echo input to "<RootName>.ech". + + CALL ReadVar( UnIn, InputFile, Echo, 'Echo', 'Echo switch', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, ED_Ver ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(ED_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".',ErrStat,ErrMsg,RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + END DO + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr( ' Heading of the '//TRIM(ED_Ver%Name)//' input file: ' ) + CALL WrScr( ' '//TRIM( FTitle ) ) + END IF + + ! Method - Integration method for loose coupling + CALL ReadVar( UnIn, InputFile, InputFileData%method, "Method", "Requested integration method for ElastoDyn {1: RK4, 2: AB4, or 3: ABM4}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! DT - Requested integration time for ElastoDyn (seconds): + CALL ReadVar( UnIn, InputFile, Line, "DT", "Requested integration time for ElastoDyn (seconds)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DT + READ( Line, *, IOSTAT=IOS) InputFileData%DT + IF ( IOS /= 0 ) THEN + CALL CheckIOS ( IOS, InputFile, "DT", NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + RETURN + END IF + END IF + + !---------------------- ENVIRONMENTAL CONDITION --------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Environmental Condition', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Gravity - Gravitational acceleration (m/s^2): + CALL ReadVar( UnIn, InputFile, InputFileData%Gravity, "Gravity", "Gravitational acceleration (m/s^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- DEGREES OF FREEDOM -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Feature Flags', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! FlapDOF1 - First flapwise blade mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%FlapDOF1, "FlapDOF1", "First flapwise blade mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! FlapDOF2 - Second flapwise blade mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%FlapDOF2, "FlapDOF2", "Second flapwise blade mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! EdgeDOF - Edgewise blade mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%EdgeDOF, "EdgeDOF", "Edgewise blade mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetDOF - Rotor-teeter DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetDOF, "TeetDOF", "Rotor-teeter DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! DrTrDOF - Drivetrain rotational-flexibility DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%DrTrDOF, "DrTrDOF", "Drivetrain rotational-flexibility DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! GenDOF - Generator DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%GenDOF, "GenDOF", "Generator DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! YawDOF - Nacelle-yaw DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%YawDOF, "YawDOF", "Nacelle-yaw DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwFADOF1 - First tower fore-aft bending-mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TwFADOF1, "TwFADOF1", "First tower fore-aft bending-mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwFADOF2 - Second tower fore-aft bending-mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TwFADOF2, "TwFADOF2", "Second tower fore-aft bending-mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwSSDOF1 - First tower side-to-side bending-mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TwSSDOF1, "TwSSDOF1", "First tower side-to-side bending-mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwSSDOF2 - Second tower side-to-side bending-mode DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TwSSDOF2, "TwSSDOF2", "Second tower side-to-side bending-mode DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmSgDOF - Platform horizontal surge translation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmSgDOF, "PtfmSgDOF", "Platform horizontal surge translation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmSwDOF - Platform horizontal sway translation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmSwDOF, "PtfmSwDOF", "Platform horizontal sway translation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmHvDOF - Platform vertical heave translation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmHvDOF, "PtfmHvDOF", "Platform vertical heave translation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmRDOF - Platform roll tilt rotation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmRDOF, "PtfmRDOF", "Platform roll tilt rotation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmPDOF - Platform pitch tilt rotation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmPDOF, "PtfmPDOF", "Platform pitch tilt rotation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmYDOF - Platform yaw rotation DOF (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmYDOF, "PtfmYDOF", "Platform yaw rotation DOF (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- INITIAL CONDITIONS -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Initial Conditions', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! OoPDefl - Initial out-of-plane blade-tip displacement (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%OoPDefl, "OoPDefl", "Initial out-of-plane blade-tip displacement (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! IPDefl - Initial in-plane blade-tip deflection (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%IPDefl, "IPDefl", "Initial in-plane blade-tip deflection (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! BlPitch - Initial blade pitch angles (deg) (read from file in degrees and converted to radians here): + CALL ReadAryLines( UnIn, InputFile, InputFileData%BlPitch, MaxBl, "BlPitch", "Initial blade pitch angles (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%BlPitch = InputFileData%BlPitch*D2R + + ! TeetDefl - Initial teeter angle (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetDefl, "TeetDefl", "Initial teeter angle (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%TeetDefl = InputFileData%TeetDefl*D2R + + ! Azimuth - Initial azimuth angle for blade 1 (degrees) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%Azimuth, "Azimuth", "Initial azimuth angle for blade 1 (degrees)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%Azimuth = InputFileData%Azimuth*D2R + + ! RotSpeed - Initial rotor speed (RPM) (read in RPM and converted to rad/sec here): + CALL ReadVar( UnIn, InputFile, InputFileData%RotSpeed, "RotSpeed", "Initial rotor speed (RPM)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%RotSpeed = InputFileData%RotSpeed*RPM2RPS + + ! NacYaw - Initial nacelle-yaw angle (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%NacYaw, "NacYaw", "Initial nacelle-yaw angle (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%NacYaw = InputFileData%NacYaw*D2R + + ! TTDspFA - Initial fore-aft tower-top displacement (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%TTDspFA, "TTDspFA", "Initial fore-aft tower-top displacement (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TTDspSS - Initial side-to-side tower-top displacement (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%TTDspSS, "TTDspSS", "Initial side-to-side tower-top displacement (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmSurge - Initial horizontal surge translational displacement of platform (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmSurge, "PtfmSurge", "Initial horizontal surge translational displacement of platform (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmSway - Initial horizontal sway translational displacement of platform (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmSway, "PtfmSway", "Initial horizontal sway translational displacement of platform (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmHeave - Initial vertical heave translational displacement of platform (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmHeave, "PtfmHeave", "Initial vertical heave translational displacement of platform (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmRoll - Initial roll tilt rotational displacement of platform (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmRoll, "PtfmRoll", "Initial roll tilt rotational displacement of platform (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%PtfmRoll = InputFileData%PtfmRoll*D2R + + ! PtfmPitch - Initial pitch tilt rotational displacement of platform (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmPitch, "PtfmPitch", "Initial pitch tilt rotational displacement of platform (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%PtfmPitch = InputFileData%PtfmPitch*D2R + + ! PtfmYaw - Initial yaw rotational displacement of platform (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmYaw, "PtfmYaw", "Initial yaw rotational displacement of platform (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%PtfmYaw = InputFileData%PtfmYaw*D2R + + !---------------------- TURBINE CONFIGURATION ----------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Turbine Configuration', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NumBl - Number of blades (-): + CALL ReadVar( UnIn, InputFile, InputFileData%NumBl, "NumBl", "Number of blades (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TipRad - Preconed blade-tip radius (distance from the rotor apex to the blade tip) (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%TipRad, "TipRad", "Preconed blade-tip radius (distance from the rotor apex to the blade tip) (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! HubRad - Preconed hub radius (distance from the rotor apex to the blade root) (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%HubRad, "HubRad", "Preconed hub radius (distance from the rotor apex to the blade root) (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PreCone - Rotor precone angles (deg) (read from file in degrees and converted to radians here): + CALL ReadAryLines( UnIn, InputFile, InputFileData%PreCone, MaxBl, "PreCone", "Rotor precone angles (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%PreCone = InputFileData%PreCone*D2R + + ! HubCM - Distance from rotor apex to hub mass (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%HubCM, "HubCM", "Distance from rotor apex to hub mass (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! UndSling - Undersling length (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%UndSling, "UndSling", "Undersling length (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Delta3 - Delta-3 angle for teetering rotors (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%Delta3, "Delta3", "Delta-3 angle for teetering rotors (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%Delta3 = InputFileData%Delta3*D2R + + ! AzimB1Up - Azimuth value to use for I/O when blade 1 points up (degrees) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%AzimB1Up, "AzimB1Up", "Azimuth value to use for I/O when blade 1 points up (degrees)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%AzimB1Up = InputFileData%AzimB1Up*D2R + + ! OverHang - Distance from yaw axis to rotor apex or teeter pin (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%OverHang, "OverHang", "Distance from yaw axis to rotor apex or teeter pin (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! ShftGagL - Distance from hub or teeter pin to shaft strain gages (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%ShftGagL, "ShftGagL", "Distance from hub or teeter pin to shaft strain gages (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! ShftTilt - Rotor shaft tilt angle (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%ShftTilt, "ShftTilt", "Rotor shaft tilt angle (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%ShftTilt = InputFileData%ShftTilt*D2R + + ! NacCMxn - Downwind distance from tower-top to nacelle CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NacCMxn, "NacCMxn", "Downwind distance from tower-top to nacelle CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NacCMyn - Lateral distance from tower-top to nacelle CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NacCMyn, "NacCMyn", "Lateral distance from tower-top to nacelle CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NacCMzn - Vertical distance from tower-top to nacelle CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NacCMzn, "NacCMzn", "Vertical distance from tower-top to nacelle CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NcIMUxn - Downwind distance from the tower-top to the nacelle IMU (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NcIMUxn, "NcIMUxn", "Downwind distance from the tower-top to the nacelle IMU (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NcIMUyn - Lateral distance from the tower-top to the nacelle IMU (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NcIMUyn, "NcIMUyn", "Lateral distance from the tower-top to the nacelle IMU (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NcIMUzn - Vertical distance from the tower-top to the nacelle IMU (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%NcIMUzn, "NcIMUzn", "Vertical distance from the tower-top to the nacelle IMU (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Twr2Shft - Vertical distance from the tower-top to the rotor shaft (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%Twr2Shft, "Twr2Shft", "Vertical distance from the tower-top to the rotor shaft (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TowerHt - Height of tower above ground level [onshore] or MSL [offshore] (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%TowerHt, "TowerHt", "Height of tower above ground level [onshore] or MSL [offshore] (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TowerBsHt - Height of tower base above ground level [onshore] or MSL [offshore] (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%TowerBsHt, "TowerBsHt", "Height of tower base above ground level [onshore] or MSL [offshore] (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmCMxt - Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmCMxt, "PtfmCMxt", "Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmCMyt - Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmCMyt, "PtfmCMzt", "Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmCMzt - Vertical distance from the ground [onshore] or MSL [offshore] to the platform CM (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmCMzt, "PtfmCMzt", "Vertical distance from the ground [onshore] or MSL [offshore] to the platform CM (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmRefzt - Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point (meters): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmRefzt, "PtfmRefzt", "Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point (meters)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- MASS AND INERTIA ---------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Mass and Inertia', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TipMass - Tip-brake masses (kg): + CALL ReadAryLines( UnIn, InputFile, InputFileData%TipMass, MaxBl, "TipMass", "Tip-brake masses (kg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! HubMass - Hub mass (kg): + CALL ReadVar( UnIn, InputFile, InputFileData%HubMass, "HubMass", "Hub mass (kg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! HubIner - Hub inertia about teeter axis (2-blader) or rotor axis (3-blader) (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%HubIner, "HubIner", "Hub inertia about teeter axis (2-blader) or rotor axis (3-blader) (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! GenIner - Generator inertia about HSS (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%GenIner, "GenIner", "Generator inertia about HSS (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NacMass - Nacelle mass (kg): + CALL ReadVar( UnIn, InputFile, InputFileData%NacMass, "NacMass", "Nacelle mass (kg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NacYIner - Nacelle yaw inertia (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%NacYIner, "NacYIner", "Nacelle yaw inertia (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! YawBrMass - Yaw bearing mass (kg): + CALL ReadVar( UnIn, InputFile, InputFileData%YawBrMass, "YawBrMass", "Yaw bearing mass (kg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmMass - Platform mass (kg): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmMass, "PtfmMass", "Platform mass (kg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmRIner - Platform inertia for roll tilt rotation about the platform CM (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmRIner, "PtfmRIner", "Platform inertia for roll tilt rotation about the platform CM (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmPIner - Platform inertia for pitch tilt rotation about the platform CM (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmPIner, "PtfmPIner", "Platform inertia for pitch tilt rotation about the platform CM (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! PtfmYIner - Platform inertia for yaw rotation about the platform CM (kg m^2): + CALL ReadVar( UnIn, InputFile, InputFileData%PtfmYIner, "PtfmYIner", "Platform inertia for yaw rotation about the platform CM (kg m^2)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- BLADE --------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Blade', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! BldNodes - Number of blade nodes (per blade) used for analysis (-): + CALL ReadVar( UnIn, InputFile, InputFileData%BldNodes, "BldNodes", "Number of blade nodes (per blade) used for analysis (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! InpBl - Blade file Input data for individual blades (see BladeInputData type): + DO I = 1,MaxBl + CALL ReadVar ( UnIn, InputFile, BldFile(I), 'BldFile('//TRIM(Num2Lstr(I))//')', 'Name of the file containing properties for blade '//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( BldFile(I) ) ) BldFile(I) = TRIM(PriPath)//TRIM(BldFile(I)) + END DO + + !---------------------- ROTOR-TEETER -------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Rotor-Teeter', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetMod - Rotor-teeter spring/damper model switch (-): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetMod, "TeetMod", "Rotor-teeter spring/damper model switch (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetDmpP - Rotor-teeter damper position (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetDmpP, "TeetDmpP", "Rotor-teeter damper position (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%TeetDmpP = InputFileData%TeetDmpP*D2R + + ! TeetDmp - Rotor-teeter damping constant (N-m/(rad/s)): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetDmp, "TeetDmp", "Rotor-teeter damping constant (N-m/(rad/s))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetCDmp - Rotor-teeter rate-independent Coulomb-damping (N-m): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetCDmp, "TeetCDmp", "Rotor-teeter rate-independent Coulomb-damping (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetSStP - Rotor-teeter soft-stop position (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetSStP, "TeetSStP", "Rotor-teeter soft-stop position (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%TeetSStP = InputFileData%TeetSStP*D2R + + ! TeetHStP - Rotor-teeter hard-stop position (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetHStP, "TeetHStP", "Rotor-teeter hard-stop position (deg)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%TeetHStP = InputFileData%TeetHStP*D2R + + ! TeetSSSp - Rotor-teeter soft-stop linear-spring constant (N-m/rad): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetSSSp, "TeetSSSp", "Rotor-teeter soft-stop linear-spring constant (N-m/rad)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TeetHSSp - Rotor-teeter hard-stop linear-spring constant (N-m/rad): + CALL ReadVar( UnIn, InputFile, InputFileData%TeetHSSp, "TeetHSSp", "Rotor-teeter hard-stop linear-spring constant (N-m/rad)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- DRIVETRAIN ---------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Drivetrain', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! GBoxEff - Gearbox efficiency (%) (read from file in % and converted to fraction here): + CALL ReadVar( UnIn, InputFile, InputFileData%GBoxEff, "GBoxEff", "Gearbox efficiency (%)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%GBoxEff = InputFileData%GBoxEff*0.01_ReKi + + ! GBRatio - Gearbox ratio (-): + CALL ReadVar( UnIn, InputFile, InputFileData%GBRatio, "GBRatio", "Gearbox ratio (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! DTTorSpr - Drivetrain torsional spring (N-m/rad): + CALL ReadVar( UnIn, InputFile, InputFileData%DTTorSpr, "DTTorSpr", "Drivetrain torsional spring (N-m/rad)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! DTTorDmp - Drivetrain torsional damper (N-m/(rad/s)): + CALL ReadVar( UnIn, InputFile, InputFileData%DTTorDmp, "DTTorDmp", "Drivetrain torsional damper (N-m/(rad/s))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- FURLING ------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Furling', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Furling - Use Additional Furling parameters? (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%Furling, "Furling", "Use Additional Furling parameters? (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! FurlFile - Name of the file containing furling parameters: + CALL ReadVar ( UnIn, InputFile, FurlFile, 'FurlFile', 'Name of the file containing furling parameters', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( FurlFile ) ) FurlFile = TRIM(PriPath)//TRIM(FurlFile) + + !---------------------- TOWER --------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Tower', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwrNodes - Number of tower nodes used in the analysis (-): + CALL ReadVar( UnIn, InputFile, InputFileData%TwrNodes, "TwrNodes", "Number of tower nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! TwrFile - Name of the file containing tower properties: + CALL ReadVar ( UnIn, InputFile, TwrFile, 'TwrFile', 'Name of the file containing tower properties', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( TwrFile ) ) TwrFile = TRIM(PriPath)//TRIM(TwrFile) + + !---------------------- OUTPUT -------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Output', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! SumPrint - Print summary data to <RootName>.sum (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! OutFile - Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-): + CALL ReadVar( UnIn, InputFile, InputFileData%OutFile, "OutFile", "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! OutFileFmt - Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both): + !CALL ReadVar( UnIn, InputFile, InputFileData%OutFileFmt, "OutFileFmt", "Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + ! TabDelim - Flag to cause tab-delimited text output (delimited by space otherwise) (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TabDelim, "TabDelim", "Flag to cause tab-delimited text output (delimited by space otherwise) (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! OutFmt - Format used for module's text tabular output (except time); resulting field should be 10 characters (-): + CALL ReadVar( UnIn, InputFile, InputFileData%OutFmt, "OutFmt", "Format used for module's text tabular output (except time); resulting field should be 10 characters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Tstart - Time to start module's tabular output (seconds): + CALL ReadVar( UnIn, InputFile, InputFileData%Tstart, "Tstart", "Time to start module's tabular output (seconds)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! DecFact - Decimation factor for module's tabular output (1=output every step) (-): + CALL ReadVar( UnIn, InputFile, InputFileData%DecFact, "DecFact", "Decimation factor for module's tabular output (1=output every step) (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NTwGages - Number of tower strain gages (-): + CALL ReadVar( UnIn, InputFile, InputFileData%NTwGages, "NTwGages", "Number of tower strain gages (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + IF ( InputFileData%NTwGages > SIZE(InputFileData%TwrGagNd) ) THEN + CALL SetErrStat( ErrID_Warn, 'Number of tower strain gages exceeds '// & + TRIM(Num2LStr(SIZE(InputFileData%TwrGagNd)))//'.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%NTwGages = SIZE(InputFileData%TwrGagNd) + END IF + + ! TwrGagNd - Nodes closest to the tower strain gages (-): + CALL ReadAry( UnIn, InputFile, InputFileData%TwrGagNd, InputFileData%NTwGages, "TwrGagNd", "Nodes closest to the tower strain gages (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! NBlGages - Number of blade strain gages (-): + CALL ReadVar( UnIn, InputFile, InputFileData%NBlGages, "NBlGages", "Number of blade strain gages (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + IF ( InputFileData%NBlGages > SIZE(InputFileData%BldGagNd) ) THEN + CALL SetErrStat( ErrID_Warn, 'Number of blade strain gages exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%BldGagNd))) //'.', ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + InputFileData%NBlGages = SIZE(InputFileData%BldGagNd) + END IF + + ! BldGagNd - Nodes closest to the blade strain gages (-): + CALL ReadAry( UnIn, InputFile, InputFileData%BldGagNd, InputFileData%NBlGages, "BldGagNd", "Nodes closest to the blade strain gages (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- OUTLIST -------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + !----------- OUTLIST ----------------------------------------------------------- + ! In case there is something ill-formed in the additional nodal outputs section, we will simply ignore it and assume that this section does not exist. + ErrMsg_NoAllBldNdOuts='Nodal outputs section of ElastoDyn input file not found or improperly formatted.' + + !----------- OUTLIST for BldNd ----------------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList for Blade node channels', ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + + ! Number of blade nodes to output: will modify this at some point for arrays + ! TODO: In a future release, allow this to be an array of N blade numbers (change BldNd_BladesOut to an array if we do that). + ! Will likely require reading this line in as a string (BldNd_BladesOut_Str) and parsing it + CALL ReadVar( UnIn, InputFile, InputFileData%BldNd_BladesOut, 'BldNd_BladesOut', 'Which blades to output node data on.'//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + + ! Which blades to output for: will add this at some point + ! TODO: Parse this string into an array of nodes to output at (one idea is to set an array of boolean to T/F for which nodes to output). At present, we ignore it entirely. + CALL ReadVar( UnIn, InputFile, InputFileData%BldNd_BlOutNd_Str, 'BldNd_BlOutNd_Str', 'Which nodes to output node data on.'//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + + ! Section header for outlist + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + + + ! OutList - List of user-requested output channels at each node(-): + CALL ReadOutputList ( UnIn, InputFile, InputFileData%BldNd_OutList, InputFileData%BldNd_NumOuts, 'BldNd_OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + IF ( ErrStat2 >= AbortErrLev ) THEN + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + CALL Cleanup() + RETURN + ENDIF + !---------------------- END OF FILE ----------------------------------------- + + call cleanup() + RETURN + + +CONTAINS + SUBROUTINE cleanup() + CLOSE ( UnIn ) + END SUBROUTINE cleanup +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays for the blade mesh properties from the input file. +SUBROUTINE Alloc_BladeMeshInputProperties( BladeKInputFileMesh, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_BladeMeshInputData), INTENT(INOUT) :: BladeKInputFileMesh !< Data for Blade K stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err msg + + + IF ( BladeKInputFileMesh%BldNodes < 1 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating arrays for blade mesh input properties: BldNodes must be at least 1.' + RETURN + END IF + + CALL AllocAry ( BladeKInputFileMesh%RNodes, BladeKInputFileMesh%BldNodes, 'RNodes' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileMesh%AeroTwst, BladeKInputFileMesh%BldNodes, 'AeroTwst', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileMesh%Chord, BladeKInputFileMesh%BldNodes, 'Chord' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + +END SUBROUTINE Alloc_BladeMeshInputProperties +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays for the blade properties from the input file. +SUBROUTINE Alloc_BladeInputProperties( BladeKInputFileData, AllocAdams, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(BladeInputData), INTENT(INOUT) :: BladeKInputFileData !< Data for Blade K stored in the module's input file + LOGICAL, INTENT(IN) :: AllocAdams !< Logical to determine if we should allocate the arrays only used for Adams + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Err message + + + IF ( BladeKInputFileData%NBlInpSt < 1 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating arrays for blade input properties: NBlInpSt must be at least 1.' + RETURN + END IF + + + ! Allocate the arrays. + + CALL AllocAry ( BladeKInputFileData%BlFract, BladeKInputFileData%NBlInpSt, 'BlFract' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%PitchAx, BladeKInputFileData%NBlInpSt, 'PitchAx' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%StrcTwst, BladeKInputFileData%NBlInpSt, 'StrcTwst' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%BMassDen, BladeKInputFileData%NBlInpSt, 'BMassDen' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%FlpStff, BladeKInputFileData%NBlInpSt, 'FlpStff' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%EdgStff, BladeKInputFileData%NBlInpSt, 'EdgStff' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + + IF ( AllocAdams ) THEN + CALL AllocAry ( BladeKInputFileData%GJStff, BladeKInputFileData%NBlInpSt, 'GJStff' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%EAStff, BladeKInputFileData%NBlInpSt, 'EAStff' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%Alpha, BladeKInputFileData%NBlInpSt, 'Alpha' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%FlpIner, BladeKInputFileData%NBlInpSt, 'FlpIner' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%EdgIner, BladeKInputFileData%NBlInpSt, 'EdgIner' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%PrecrvRef,BladeKInputFileData%NBlInpSt, 'PrecrvRef', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%PreswpRef,BladeKInputFileData%NBlInpSt, 'PreswpRef', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%FlpcgOf, BladeKInputFileData%NBlInpSt, 'FlpcgOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%EdgcgOf, BladeKInputFileData%NBlInpSt, 'EdgcgOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%FlpEAOf, BladeKInputFileData%NBlInpSt, 'FlpEAOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%EdgEAOf, BladeKInputFileData%NBlInpSt, 'EdgEAOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + END IF + + + ! BJJ: note that these used to be allocated 2:PolyOrd : + + CALL AllocAry ( BladeKInputFileData%BldFl1Sh, PolyOrd-1, 'BldFl1Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%BldFl2Sh, PolyOrd-1, 'BldFl2Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( BladeKInputFileData%BldEdgSh, PolyOrd-1, 'BldEdgSh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + +END SUBROUTINE Alloc_BladeInputProperties +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine allocates arrays for the tower properties from the input file. +SUBROUTINE Alloc_TowerInputProperties( InputFileData, AllocAdams, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the ElastoDyn input file + LOGICAL, INTENT(IN) :: AllocAdams !< Determines if the columns for Adams data will be read + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + IF ( InputFileData%NTwInpSt < 1 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating arrays for tower input properties: NTwInpSt must be at least 1.' + RETURN + END IF + + + ! Allocate the arrays. + + CALL AllocAry ( InputFileData%HtFract, InputFileData%NTwInpSt, 'HtFract' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TMassDen, InputFileData%NTwInpSt, 'TMassDen' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwFAStif, InputFileData%NTwInpSt, 'TwFAStif' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwSSStif, InputFileData%NTwInpSt, 'TwSSStif' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + IF ( AllocAdams ) THEN + CALL AllocAry ( InputFileData%TwGJStif, InputFileData%NTwInpSt, 'TwGJStif' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwEAStif, InputFileData%NTwInpSt, 'TwEAStif' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwFAIner, InputFileData%NTwInpSt, 'TwFAIner' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwSSIner, InputFileData%NTwInpSt, 'TwSSIner' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwFAcgOf, InputFileData%NTwInpSt, 'TwFAcgOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwSScgOf, InputFileData%NTwInpSt, 'TwSScgOf' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + END IF + + + ! BJJ: note that these used to be allocated 2:PolyOrd : + CALL AllocAry ( InputFileData%TwFAM1Sh, PolyOrd-1, 'TwFAM1Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwFAM2Sh, PolyOrd-1, 'TwFAM2Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwSSM1Sh, PolyOrd-1, 'TwSSM1Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry ( InputFileData%TwSSM2Sh, PolyOrd-1, 'TwSSM2Sh' , ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + +END SUBROUTINE Alloc_TowerInputProperties +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks the blade file input data for errors. +SUBROUTINE ValidateBladeData ( BladeKInputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(BladeInputData), INTENT(IN) :: BladeKInputFileData !< Data for Blade K stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER :: I ! Loop counter + INTEGER(IntKi) :: ErrStat2 ! Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message + CHARACTER(*), PARAMETER :: RoutineName = 'ValidateBladeData' + + + ErrStat = ErrID_None + ErrMsg= '' + + + ! Check that BlFract goes from 0.0 to 1.0 in increasing order: + + IF ( .NOT. EqualRealNos( BladeKInputFileData%BlFract(1), 0.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'BlFract(1) must be 0.0.',ErrStat,ErrMsg,RoutineName) + END IF + + IF ( BladeKInputFileData%NBlInpSt /= 1_IntKi .AND. & + .NOT. EqualRealNos( BladeKInputFileData%BlFract(BladeKInputFileData%NBlInpSt), 1.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'BlFract('//TRIM( Num2LStr( BladeKInputFileData%NBlInpSt ) )//') must be 1.0.',ErrStat,ErrMsg,RoutineName) + END IF + + DO I = 2,BladeKInputFileData%NBlInpSt + IF ( BladeKInputFileData%BlFract(I) <= BladeKInputFileData%BlFract(I-1) ) THEN + CALL SetErrStat( ErrID_Fatal,'BlFract('//TRIM( Num2LStr( I ) )//') must be greater than BlFract('& + //TRIM( Num2LStr(I-1) )//').',ErrStat,ErrMsg,RoutineName) + ENDIF + END DO + + + DO I = 1,BladeKInputFileData%NBlInpSt + + ! Check that PitchAx is contained in [0.0, 1.0]: + IF ( ( BladeKInputFileData%PitchAx(I) ) < 0.0_ReKi .OR. ( BladeKInputFileData%PitchAx(I) > 1.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'PitchAx('//TRIM( Num2LStr( I ) )//') must be between 0 and 1 (inclusive).',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that StrcTwst is contained in (-pi,pi] radians ( i.e., (-180.0, 180.0] degrees): + IF ( ( BladeKInputFileData%StrcTwst(I) <= -pi ) .OR. ( BladeKInputFileData%StrcTwst(I) > pi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'StrcTwst('//TRIM( Num2LStr( I ) ) // & + ') must be greater than -180 and less than or equal to 180.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that BMassDen is contained in (0.0, inf): + IF ( BladeKInputFileData%BMassDen(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'BMassDen('//TRIM( Num2LStr( I ) )//') must be greater than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that FlpStff is contained in (0.0, inf): + IF ( BladeKInputFileData%FlpStff (I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'FlpStff('//TRIM( Num2LStr( I ) )//') must be greater than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that EdgStff is contained in (0.0, inf): + IF ( BladeKInputFileData%EdgStff (I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'EdgStff('//TRIM( Num2LStr( I ) )//') must be greater than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + + ! Check values for Adams input + + IF ( ALLOCATED(BladeKInputFileData%GJStff) ) THEN ! We assume that if GJStff is allocated, we are using ADAMS inputs + + ! The reference axis must be coincident with the pitch axis at the blade root (I == 1): + IF ( .NOT. EqualRealNos( BladeKInputFileData%PrecrvRef(1), 0.0_ReKi ) .OR. & + .NOT. EqualRealNos( BladeKInputFileData%PreswpRef(1), 0.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Both PrecrvRef(1) and PreswpRef(1) must be zero '//& + '(the reference axis must be coincident with the pitch axis at the blade root).',ErrStat,ErrMsg,RoutineName) + END IF + + + DO I = 1,BladeKInputFileData%NBlInpSt + + ! Check that GJStff is contained in (0.0, inf): + IF ( BladeKInputFileData%GJStff(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'GJStff('//TRIM( Num2LStr( I ) )//') must be greater than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that EAStff is contained in (0.0, inf): + IF ( BladeKInputFileData%EAStff(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'EAStff('//TRIM( Num2LStr( I ) )//') must be greater than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that Alpha is contained in (-1.0, 1): + IF ( ( BladeKInputFileData%Alpha(I) <= -1.0_ReKi ) .OR. ( BladeKInputFileData%Alpha(I) >= 1.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Alpha('//TRIM( Num2LStr( I ) )//') (the blade flap/twist'// & + ' coupling coefficient) must be between -1 and 1 (exclusive).',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that FlpIner is contained in [0.0, inf): + IF ( BladeKInputFileData%FlpIner(I) < 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'FlpIner('//TRIM( Num2LStr( I ) )//') must not be less than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that EdgIner is contained in [0.0, inf): + IF ( BladeKInputFileData%EdgIner(I) < 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'EdgIner('//TRIM( Num2LStr( I ) )//') must not be less than zero.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that PrecrvRef is 0.0 for Adams models: + IF ( .NOT. EqualRealNos( BladeKInputFileData%PrecrvRef(I), 0.0_ReKi) ) THEN + CALL SetErrStat( ErrID_Fatal,'PrecrvRef('//TRIM( Num2LStr( I ) )//') must be zero for Adams models.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check that GJStff is contained in (0.0, inf): + IF ( .NOT. EqualRealNos( BladeKInputFileData%PreswpRef(I), 0.0_ReKi) ) THEN + CALL SetErrStat( ErrID_Fatal,'PreswpRef('//TRIM( Num2LStr( I ) )//') must be zero for Adams models.',ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + END IF ! check for Adams models + + + ! Check that the blade damping is not negative: + + IF ( ANY( BladeKInputFileData%BldFlDmp < 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal,'BldFlDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( ANY( BladeKInputFileData%BldEdDmp < 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal,'BldEdDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + + + ! Check that the stiffness tuner isn't negative: + + IF ( ANY( BladeKInputFileData%FlStTunr <= 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal,'FlStTunr must be greater than zero.',ErrStat,ErrMsg,RoutineName) + + + ! Check that the mode shape coefficients are valid: + + CALL ValidateModeShapeCoeffs(BladeKInputFileData%BldFl1Sh, 'blade flap mode 1', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL ValidateModeShapeCoeffs(BladeKInputFileData%BldFl2Sh, 'blade flap mode 2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL ValidateModeShapeCoeffs(BladeKInputFileData%BldEdgSh, 'blade edge', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + +END SUBROUTINE ValidateBladeData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks that the mode shape coefficients add to 1.0, within numerical tolerance (currently 0.0015). +SUBROUTINE ValidateModeShapeCoeffs( Coeffs, ShpDesc, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(ReKi), INTENT(IN ) :: Coeffs(:) !< Mode shape coefficients + CHARACTER(*), INTENT(IN) :: ShpDesc !< Description of the mode shape for the error message + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! local variables + REAL(ReKi) :: Displ ! Blade tip/tower top displacement for a mode shape + + + ! Check that the mode shape coefficients add to 1.0: + + Displ = SUM( Coeffs ) +! bjj this new check seems to be a bit too restrictive for the input data: +! IF ( .NOT. EqualRealNos( Displ, 1.0_ReKi ) ) THEN + IF ( ABS( Displ - 1.0_ReKi ) > 0.0015_ReKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Mode shape coefficients for '//TRIM(ShpDesc)//' must add to 1.0.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + +END SUBROUTINE ValidateModeShapeCoeffs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks the tower file input data for errors +SUBROUTINE ValidateTowerData ( InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(ED_InputFile), INTENT(IN ) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER :: I ! Loop counter + INTEGER(IntKi) :: ErrStat2 ! Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message + CHARACTER(*), PARAMETER :: RoutineName = 'ValidateTowerData' + + ErrStat = ErrID_None + ErrMsg= '' + + + + ! Check that HtFract goes from 0.0 to 1.0 in increasing order: + + IF ( .NOT. EqualRealNos( InputFileData%HtFract(1), 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'HtFract(1) must be 0.0.', ErrStat, ErrMsg, RoutineName) + + IF ( InputFileData%NTwInpSt /= 1 .AND. & + .NOT. EqualRealNos( InputFileData%HtFract(InputFileData%NTwInpSt), 1.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'HtFract('//TRIM( Num2LStr( InputFileData%NTwInpSt ) )//') must be 1.0.', ErrStat, ErrMsg, RoutineName) + END IF + + DO I = 2,InputFileData%NTwInpSt + IF ( InputFileData%HtFract(I) <= InputFileData%HtFract(I-1) ) THEN + CALL SetErrStat( ErrID_Fatal, 'HtFract('//TRIM( Num2LStr( I ) )//') must be greater than HtFract('& + //TRIM( Num2LStr(I-1) )//').', ErrStat, ErrMsg, RoutineName) + + ENDIF + END DO + + + ! Check the input arrays: + + DO I = 1,InputFileData%NTwInpSt + IF ( InputFileData%TMassDen(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TMassDen('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( InputFileData%TwFAStif(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwFAStif('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( InputFileData%TwSSStif(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwSSStif('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + END DO + + ! Check Adams inputs + + IF ( ALLOCATED( InputFileData%TwGJStif ) ) THEN ! Assume that all of the Adams tower data is allocated + + DO I = 1,InputFileData%NTwInpSt + IF ( InputFileData%TwGJStif(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwGJStif('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( InputFileData%TwEAStif(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwEAStif('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( InputFileData%TwFAIner(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwFAIner('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( InputFileData%TwSSIner(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwSSIner('//TRIM(Num2LStr( I ))//') must be greater than zero.', ErrStat, ErrMsg, RoutineName) + END IF + END DO + + END IF ! Check items for Adams + + + + ! Check that the tower damping (TwrFADmp) is contained in the range [0, 100]: + + IF ( ANY( InputFileData%TwrFADmp < 0.0_ReKi ) .OR. ANY( InputFileData%TwrFADmp > 100.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwrFADmp must be between 0 and 100 (inclusive).', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( ANY( InputFileData%TwrSSDmp < 0.0_ReKi ) .OR. ANY( InputFileData%TwrSSDmp > 100.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'TwrSSDmp must be between 0 and 100 (inclusive).', ErrStat, ErrMsg, RoutineName) + END IF + + + ! Check that the tower tuners are positive numbers: + + IF ( ANY( InputFileData%FAStTunr <= 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'FAStTunr must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( ANY( InputFileData%SSStTunr <= 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'SSStTunr must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + + + + ! Validate the mode shape coefficients: + + CALL ValidateModeShapeCoeffs( InputFileData%TwFAM1Sh, 'tower fore-aft mode 1', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL ValidateModeShapeCoeffs( InputFileData%TwFAM2Sh, 'tower fore-aft mode 2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL ValidateModeShapeCoeffs( InputFileData%TwSSM1Sh, 'tower side-to-side mode 1', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL ValidateModeShapeCoeffs( InputFileData%TwSSM2Sh, 'tower side-to-side mode 2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +END SUBROUTINE ValidateTowerData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the furling inputs. +SUBROUTINE ValidateFurlData( InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< All the data in the ElastoDyn input file + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: +! CHARACTER(1024) :: TmpMsg ! a temporary message (so I don't have to keep typing the same error message) + REAL(ReKi) :: SmallAngleLimit_Rad ! Largest input angle considered "small" (check in input file), radians + CHARACTER(*), PARAMETER :: RoutineName = 'ValidateFurlData' + + ! Initialize error status and angle limit defined locally (in correct units) + + ErrStat = ErrID_None + ErrMsg = '' + SmallAngleLimit_Rad = SmallAngleLimit_Deg*D2R + + + ! note that all angles are assumed to be in radians here: + + ! Check that angles are in the range (-pi, pi] radians (i.e., (-180, 180] degrees ): + ! NOTE: these are local subroutines, with ErrStat and ErrMsg INTENT(INOUT) + + CALL CheckAngle180Range( InputFileData%RotFurl, 'RotFurl' ) + CALL CheckAngle180Range( InputFileData%TailFurl, 'TailFurl' ) + CALL CheckAngle180Range( InputFileData%TFinSkew, 'TFinSkew' ) + CALL CheckAngle180Range( InputFileData%TFinBank, 'TFinBank' ) + CALL CheckAngle180Range( InputFileData%RFrlSkew, 'RFrlSkew' ) + CALL CheckAngle180Range( InputFileData%TFrlSkew, 'TFrlSkew' ) + + CALL CheckAngle180Range( InputFileData%RFrlUSSP, 'RFrlUSSP' ) + CALL CheckAngle180Range( InputFileData%TFrlUSSP, 'TFrlUSSP' ) + CALL CheckAngle180Range( InputFileData%RFrlUSDP, 'RFrlUSDP' ) + CALL CheckAngle180Range( InputFileData%TFrlUSDP, 'TFrlUSDP' ) + + CALL CheckAngle180Range( InputFileData%RFrlDSSP, 'RFrlDSSP' ) + IF ( InputFileData%RFrlDSSP > InputFileData%RFrlUSSP ) THEN + CALL SetErrStat( ErrID_Fatal,'RFrlDSSP must not be larger than RFrlUSSP.',ErrStat,ErrMsg,RoutineName) + END IF + + CALL CheckAngle180Range( InputFileData%RFrlDSDP, 'RFrlDSDP' ) + IF ( InputFileData%RFrlDSDP > InputFileData%RFrlUSDP ) THEN + CALL SetErrStat( ErrID_Fatal,'RFrlDSDP must not be larger than RFrlUSDP.',ErrStat,ErrMsg,RoutineName) + END IF + + CALL CheckAngle180Range( InputFileData%TFrlDSSP, 'TFrlDSSP' ) + IF ( InputFileData%TFrlDSSP > InputFileData%TFrlUSSP ) THEN + CALL SetErrStat( ErrID_Fatal,'TFrlDSSP must not be larger than TFrlUSSP.',ErrStat,ErrMsg,RoutineName) + END IF + + CALL CheckAngle180Range( InputFileData%TFrlDSDP, 'TFrlDSDP' ) + IF ( InputFileData%TFrlDSDP > InputFileData%TFrlUSDP ) THEN + CALL SetErrStat( ErrID_Fatal,'TFrlDSDP must not be larger than TFrlUSDP.',ErrStat,ErrMsg,RoutineName) + END IF + + + ! Check that tilt angles are in the range [-pi/2, pi/2] radians (i.e., [-90, 90] degrees ): + + IF ( ABS( InputFileData%TFinTilt ) > PiBy2 ) THEN + CALL SetErrStat(ErrID_Fatal,'TFinTilt must be between -pi/2 and pi/2 radians (i.e., in the range [-90, 90] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + IF ( ABS( InputFileData%RFrlTilt ) > PiBy2 ) THEN + CALL SetErrStat(ErrID_Fatal,'RFrlTilt must be between -pi/2 and pi/2 radians (i.e., in the range [-90, 90] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + IF ( ABS( InputFileData%TFrlTilt ) > PiBy2 ) THEN + CALL SetErrStat(ErrID_Fatal,'TFrlTilt must be between -pi/2 and pi/2 radians (i.e., in the range [-90, 90] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + + + + ! Check for violations of the small-angle assumption (15-degree limit, using radians): + + IF ( ABS( InputFileData%ShftSkew ) > SmallAngleLimit_Rad ) THEN + CALL SetErrStat( ErrID_Fatal,'ShftSkew should only be used to skew the shaft a few degrees away from the zero-yaw ' & + //'position and must not be used as a replacement for the yaw angle. '& + //'ShftSkew must be between -'//TRIM(Num2LStr(SmallAngleLimit_Rad))//' and ' & + //TRIM(Num2LStr(SmallAngleLimit_Rad))//' radians.',ErrStat,ErrMsg,RoutineName ) + END IF + + + ! Warn if tail is defined upwind of the tower: + + IF ( InputFileData%BoomCMxn < 0.0_ReKi ) THEN ! Print out warning when tail boom CM defined upwind of the tower. + CALL SetErrStat( ErrID_Warn,'WARNING: Tail boom CM is defined upwind of the tower (BoomCMxn < 0).',ErrStat,ErrMsg,RoutineName) + ENDIF + + IF ( InputFileData%TFinCMxn < 0.0_ReKi ) THEN ! Print out warning when tail fin CM defined upwind of the tower. + CALL SetErrStat( ErrID_Warn,'WARNING: Tail fin CM is defined upwind of the tower (TFinCMxn < 0).',ErrStat,ErrMsg,RoutineName) + ENDIF + + IF ( InputFileData%TFinCPxn < 0.0_ReKi ) THEN ! Print out warning when tail fin CP defined upwind of the tower. + CALL SetErrStat( ErrID_Warn,'WARNING: Tail fin CP is defined upwind of the tower (TFinCPxn < 0).',ErrStat,ErrMsg,RoutineName) + ENDIF + + + ! Check that mass, inertias, damping, etc. values aren't negative: + + IF (InputFileData%RFrlMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'RFrlMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF (InputFileData%BoomMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'BoomMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF (InputFileData%TFinMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'TFinMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF (InputFileData%RFrlIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'RFrlIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF (InputFileData%TFrlIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'TFrlIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF (InputFileData%RFrlSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'RFrlSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'RFrlDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlCDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'RFrlCDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlUSSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'RFrlUSSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlDSSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'RFrlDSSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlUSDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'RFrlUSDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RFrlDSDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'RFrlDSDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'TFrlSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'TFrlDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlCDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'TFrlCDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlUSSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TFrlUSSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlDSSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TFrlDSSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlUSDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TFrlUSDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TFrlDSDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TFrlDSDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + + + ! Check that furling models are valid: + + IF ( InputFileData%TFrlMod < 0 .OR. InputFileData%TFrlMod > 2 ) THEN + CALL SetErrStat( ErrID_Fatal, 'TFrlMod must be 0, 1, or 2.',ErrStat,ErrMsg,RoutineName) + END IF + + IF ( InputFileData%RFrlMod < 0 .OR. InputFileData%RFrlMod > 2 ) THEN + CALL SetErrStat( ErrID_Fatal, 'RFrlMod must be 0, 1, or 2.',ErrStat,ErrMsg,RoutineName ) + END IF + + + ! ! bjj: THESE ARE checks for tail fin aerodynamics, which should be in aerodyn, in my opinion + !IF ( InputFileData%TFinArea < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TFinArea must not be negative.',ErrStat,ErrMsg,RoutineName) + + !IF ( TFinMod < 0 .OR. TFinMod > 2 ) THEN + ! CALL SetErrors( ErrID_Fatal,'TFinMod must be 0, 1, or 2.') + !END IF + + + RETURN + +CONTAINS + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine checks that an angle is in the range (-pi, pi] radians. If not, ErrStat = ErrID_Fatal + !! Note that all values are assumed to be in radians, even if read in degrees (-180 deg, 180 deg] + SUBROUTINE CheckAngle180Range( Var, VarDesc ) + !............................................................................................................................... + REAL(ReKi), INTENT(IN) :: Var ! Variable to check + CHARACTER(*), INTENT(IN) :: VarDesc ! Description of variable (used in error message) + + IF ( ( Var <= -pi ) .OR. ( Var > pi ) ) THEN + CALL SetErrStat(ErrID_Fatal, TRIM(VarDesc)// & + ' must be greater than -pi radians and less than or equal to pi radians '// & + '(i.e., in the range (-180, 180] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + + END SUBROUTINE CheckAngle180Range + !------------------------------------------------------------------------------------------------------------------------------- + END SUBROUTINE ValidateFurlData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the primary input file. +!! note that all angles are assumed to be in radians in this routine: +SUBROUTINE ValidatePrimaryData( InputFileData, BD4Blades, Linearize, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< All the data in the ElastoDyn input file + LOGICAL, INTENT(IN) :: BD4Blades !< Use BeamDyn for blades, thus ignore ElastoDyn blade info + LOGICAL, INTENT(IN) :: Linearize !< Flag indicating glue code wants to linearize this module + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + REAL(ReKi) :: SmallAngleLimit_Rad ! Largest input angle considered "small" (check in input file), radians + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: K ! blade number + INTEGER(IntKi) :: FmtWidth ! width of the field returned by the specified OutFmt + INTEGER(IntKi) :: ErrStat2 ! Temporary error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary rror message + CHARACTER(*), PARAMETER :: RoutineName = 'ValidatePrimaryData' + + ! Initialize error status and angle limit defined locally (in correct units) + + ErrStat = ErrID_None + ErrMsg = '' + SmallAngleLimit_Rad = SmallAngleLimit_Deg*D2R + + ! Make sure the number of blades is valid: + IF (BD4Blades) THEN + IF ( ( InputFileData%NumBl < 1 ) .OR. ( InputFileData%NumBl > MaxBl ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'NumBl must be 1, 2, or 3 for BeamDyn simulations.',ErrStat,ErrMsg,RoutineName) + END IF + ELSE + IF ( ( InputFileData%NumBl < 2 ) .OR. ( InputFileData%NumBl > MaxBl ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'NumBl must be either 2 or 3.',ErrStat,ErrMsg,RoutineName) + END IF + END IF + + ! Make sure the specified integration method makes sense: + IF ( InputFileData%method .ne. Method_RK4) THEN + IF ( InputFileData%method .ne. Method_AB4) THEN + IF ( InputFileData%method .ne. Method_ABM4) THEN + CALL SetErrStat( ErrID_Fatal, 'Integration method must be 1 (RK4), 2 (AB4), or 3 (ABM4)',ErrStat,ErrMsg,RoutineName ) + END IF + END IF + END IF + + + ! make sure GBoxEff is 100% for now + IF ( .NOT. EqualRealNos( InputFileData%GBoxEff, 1.0_ReKi ) .and. InputFileData%method == method_rk4 ) & + CALL SetErrStat( ErrID_Fatal, 'GBoxEff must be 1 (i.e., 100%) when using RK4.',ErrStat,ErrMsg,RoutineName) + + + ! Don't allow these parameters to be negative (i.e., they must be in the range (0,inf)): + IF ( InputFileData%Gravity < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'Gravity must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%RotSpeed < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'RotSpeed must not be negative.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%TipRad < 0.0_ReKi) CALL SetErrStat(ErrID_Fatal,'TipRad must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%HubRad < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'HubRad must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%DTTorSpr < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'DTTorSpr must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%DTTorDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'DTTorDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%PtfmMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'PtfmMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%PtfmRIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'PtfmRIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%PtfmPIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'PtfmPIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%PtfmYIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'PtfmYIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%YawBrMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'YawBrMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%NacMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'NacMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%HubMass < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'HubMass must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%Twr2Shft < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'Twr2Shft must not be negative.',ErrStat,ErrMsg,RoutineName) + + DO K=1,InputFileData%NumBl + IF ( InputFileData%TipMass(K) < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TipMass('//TRIM( Num2LStr( K ) )//') must not be negative.',ErrStat,ErrMsg,RoutineName) + ENDDO ! K + + IF ( InputFileData%NacYIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'NacYIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%GenIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'GenIner must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%HubIner < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'HubIner must not be negative.',ErrStat,ErrMsg,RoutineName) + + ! Check that TowerHt is in the range [0,inf): + IF ( InputFileData%TowerHt <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TowerHt must be greater than zero.',ErrStat,ErrMsg,RoutineName ) + + ! Check that these integers are in appropriate ranges: + IF ( InputFileData%TwrNodes < 1_IntKi ) CALL SetErrStat( ErrID_Fatal, 'TwrNodes must not be less than 1.',ErrStat,ErrMsg,RoutineName ) + + IF ( InputFileData%BldNodes < 1_IntKi .AND. .NOT. BD4Blades) CALL SetErrStat( ErrID_Fatal, 'BldNodes must not be less than 1.',ErrStat,ErrMsg,RoutineName ) + + ! Check that the gearbox efficiency is valid: + IF ( ( InputFileData%GBoxEff <= 0.0_ReKi ) .OR. ( InputFileData%GBoxEff > 1.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'GBoxEff must be in the range (0,1] (i.e., (0,100] percent).',ErrStat,ErrMsg,RoutineName ) + ENDIF + + ! warn if 2nd modes are enabled without their corresponding 1st modes + + IF ( InputFileData%FlapDOF2 .AND. ( .NOT. InputFileData%FlapDOF1 ) ) THEN ! Print out warning when flap mode 1 is not enabled and flap mode 2 is enabled + CALL SetErrStat( ErrID_Warn, '2nd blade flap mode is enabled without the 1st. '//& + ' This designation is recommended only for debugging purposes.',ErrStat,ErrMsg,RoutineName ) + ENDIF + + IF ( InputFileData%TwFADOF2 .AND. ( .NOT. InputFileData%TwFADOF1 ) ) THEN ! Print out warning when tower fore-aft mode 1 is not enabled and fore-aft mode 2 is enabled + CALL SetErrStat( ErrID_Warn, '2nd tower fore-aft mode is enabled without the 1st. '//& + ' This designation is recommended only for debugging purposes.',ErrStat,ErrMsg,RoutineName ) + ENDIF + + IF ( InputFileData%TwSSDOF2 .AND. ( .NOT. InputFileData%TwSSDOF1 ) ) THEN ! Print out warning when tower side-to-side mode 1 is not enabled and side-to-side mode 2 is enabled + CALL SetErrStat( ErrID_Warn, '2nd tower side-to-side mode is enabled without the 1st. '//& + ' This designation is recommended only for debugging purposes.',ErrStat,ErrMsg,RoutineName ) + ENDIF + + + ! Check that turbine configuration makes sense: + + IF ( InputFileData%Furling ) THEN + IF ( InputFileData%OverHang > 0.0_ReKi ) THEN ! Print out warning when downwind turbine is modeled with furling. + CALL SetErrStat( ErrID_Warn, 'Furling designation (Furling = True) specified for downwind rotor '// & + 'configuration (OverHang > 0). Check for possible errors in the input file(s).',ErrStat,ErrMsg,RoutineName) + END IF + ENDIF + + IF ( InputFileData%TowerBsHt >= InputFileData%TowerHt ) CALL SetErrStat( ErrID_Fatal, 'TowerBsHt must be less than TowerHt.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%PtfmCMzt > InputFileData%TowerBsHt ) & + CALL SetErrStat( ErrID_Fatal, 'PtfmCMzt must not be greater than TowerBsHt.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%PtfmRefzt > InputFileData%TowerBsHt ) & + CALL SetErrStat( ErrID_Fatal, 'PtfmRefzt must not be greater than TowerBsHt.',ErrStat,ErrMsg,RoutineName) + + IF (.NOT. BD4Blades ) THEN + IF (InputFileData%HubRad >= InputFileData%TipRad ) & + CALL SetErrStat( ErrID_Fatal, 'HubRad must be less than TipRad.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%TowerHt + InputFileData%Twr2Shft + InputFileData%OverHang*SIN(InputFileData%ShftTilt) & + <= InputFileData%TipRad ) THEN + CALL SetErrStat( ErrID_Fatal, 'TowerHt + Twr2Shft + OverHang*SIN(ShftTilt) must be greater than TipRad.',ErrStat,ErrMsg,RoutineName) + END IF + END IF + + + IF ( InputFileData%NumBl == 2_IntKi ) THEN + IF ( ( InputFileData%TeetDefl <= -pi ) .OR. ( InputFileData%TeetDefl > pi ) ) & + CALL SetErrStat( ErrID_Fatal, 'TeetDefl must be in the range (-pi, pi] radians (i.e., [-180,180] degrees).',ErrStat,ErrMsg,RoutineName) + + IF ( ABS( InputFileData%Delta3 ) >= PiBy2 ) & + CALL SetErrStat( ErrID_Fatal, 'Delta3 must be in the range (pi/2, pi/2) radians (i.e., (-90, 90) degrees).',ErrStat,ErrMsg,RoutineName) + + IF ( ( InputFileData%TeetSStP < 0.0_ReKi ) .OR. ( InputFileData%TeetSStP > pi ) ) & + CALL SetErrStat( ErrID_Fatal, 'TeetSStP must be in the range [0, pi] radians (i.e., [0,180] degrees).',ErrStat,ErrMsg,RoutineName) + + IF ( ( InputFileData%TeetDmpP < 0.0_ReKi ) .OR. ( InputFileData%TeetDmpP > pi ) ) & + CALL SetErrStat( ErrID_Fatal, 'TeetDmpP must be in the range [0, pi] radians (i.e., [0,180] degrees).',ErrStat,ErrMsg,RoutineName) + + IF ( ( InputFileData%TeetHStP < InputFileData%TeetSStP ) .OR. ( InputFileData%TeetHStP > pi ) ) & + CALL SetErrStat( ErrID_Fatal, 'TeetHStP must be in the range [TeetSStP, pi] radians (i.e., [TeetSStP, 180] degrees).',ErrStat,ErrMsg,RoutineName) + + IF ( ( InputFileData%TeetMod /= 0_IntKi ) .AND. ( InputFileData%TeetMod /= 1_IntKi ) .AND. & + ( InputFileData%TeetMod /= 2_IntKi ) ) & + CALL SetErrStat( ErrID_Fatal, 'TeetMod must be 0, 1, or 2.',ErrStat,ErrMsg,RoutineName) + + IF ( InputFileData%TeetDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TeetDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TeetCDmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TeetCDmp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TeetSSSp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TeetSSSp must not be negative.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%TeetHSSp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'TeetHSSp must not be negative.',ErrStat,ErrMsg,RoutineName) + + ! TeetCDmp isn't allowed to be non-zero in this verison. + IF (.NOT. EqualRealNos( InputFileData%TeetCDmp, 0.0_ReKi )) & + CALL SetErrStat( ErrID_Fatal, 'TeetCDmp must be 0 in this version of ElastoDyn.',ErrStat,ErrMsg,RoutineName) + ENDIF + + ! check these angles for appropriate ranges: + IF ( ( InputFileData%NacYaw <= -pi ) .OR. ( InputFileData%NacYaw > pi ) ) & + CALL SetErrStat( ErrID_Fatal, 'NacYaw must be in the range (-pi, pi] radians (i.e., (-180, 180] degrees).',ErrStat,ErrMsg,RoutineName) + IF ( ( InputFileData%Azimuth < 0.0_ReKi ) .OR. ( InputFileData%Azimuth >= TwoPi ) ) & + CALL SetErrStat( ErrID_Fatal, 'Azimuth must be in the range [0, 2pi) radians (i.e., [0, 360) degrees).',ErrStat,ErrMsg,RoutineName) + IF ( ( InputFileData%AzimB1Up < 0.0_ReKi ) .OR. ( InputFileData%AzimB1Up >= TwoPi ) ) & + CALL SetErrStat( ErrID_Fatal, 'AzimB1Up must be in the range [0, 2pi) radians (i.e., [0, 360) degrees).',ErrStat,ErrMsg,RoutineName) + + DO K=1,InputFileData%NumBl + IF ( ( InputFileData%BlPitch(K) <= -pi ) .OR. ( InputFileData%BlPitch(K) > pi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'BlPitch('//TRIM(Num2LStr(K))//')'//' must be greater than -pi radians and '// & + 'less than or equal to pi radians (i.e., in the range (-180, 180] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + IF ( ABS( InputFileData%PreCone(K) ) >= PiBy2 ) & + CALL SetErrStat( ErrID_Fatal, 'PreCone('//TRIM( Num2LStr( K ) )//') must be in the range (-pi/2, pi/2) '//& + 'radians (i.e., (-90, 90) degrees).',ErrStat,ErrMsg,RoutineName) + END DO + + ! Check that these angles are in the range [-pi/2, pi/2] radians (i.e., [-90, 90] degrees ): + IF ( ABS( InputFileData%ShftTilt ) > PiBy2 ) THEN + CALL SetErrStat(ErrID_Fatal,'ShftTilt must be between -pi/2 and pi/2 radians (i.e., in the range [-90, 90] degrees).',ErrStat,ErrMsg,RoutineName) + END IF + + + ! Check for violations of the small-angle assumption (15-degree limit, using radians): + IF ( ABS( InputFileData%PtfmRoll ) > SmallAngleLimit_Rad ) THEN + CALL SetErrStat( ErrID_Fatal, 'PtfmRoll must be between -'//TRIM(Num2LStr(SmallAngleLimit_Rad))//' and ' & + //TRIM(Num2LStr(SmallAngleLimit_Rad))//' radians.',ErrStat,ErrMsg,RoutineName) + END IF + + IF ( ABS( InputFileData%PtfmPitch ) > SmallAngleLimit_Rad ) THEN + CALL SetErrStat( ErrID_Fatal, 'PtfmPitch must be between -'//TRIM(Num2LStr(SmallAngleLimit_Rad))//' and ' & + //TRIM(Num2LStr(SmallAngleLimit_Rad))//' radians.',ErrStat,ErrMsg,RoutineName) + END IF + + IF ( ABS( InputFileData%PtfmYaw ) > SmallAngleLimit_Rad ) THEN + CALL SetErrStat( ErrID_Fatal, 'PtfmYaw must be between -'//TRIM(Num2LStr(SmallAngleLimit_Rad))//' and ' & + //TRIM(Num2LStr(SmallAngleLimit_Rad))//' radians.',ErrStat,ErrMsg,RoutineName) + END IF + + ! Check the output parameters: + IF ( InputFileData%DecFact < 1_IntKi ) CALL SetErrStat( ErrID_Fatal, 'DecFact must be greater than 0.',ErrStat,ErrMsg,RoutineName ) + + IF ( ( InputFileData%NTwGages < 0_IntKi ) .OR. ( InputFileData%NTwGages > 9_IntKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'NTwGages must be between 0 and 9 (inclusive).',ErrStat,ErrMsg,RoutineName) + ELSE + ! Check to see if all TwrGagNd(:) analysis points are existing analysis points: + + DO I=1,InputFileData%NTwGages + IF ( InputFileData%TwrGagNd(I) < 1_IntKi .OR. InputFileData%TwrGagNd(I) > InputFileData%TwrNodes ) THEN + CALL SetErrStat( ErrID_Fatal, ' All TwrGagNd values must be between 1 and '//& + TRIM( Num2LStr( InputFileData%TwrNodes ) )//' (inclusive).',ErrStat,ErrMsg,RoutineName) + EXIT ! stop checking this loop + END IF + END DO + + END IF + + + IF ( ( InputFileData%NBlGages < 0_IntKi ) .OR. ( InputFileData%NBlGages > 9_IntKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'NBlGages must be between 0 and 9 (inclusive).',ErrStat,ErrMsg,RoutineName) + ELSE + + ! Check to see if all BldGagNd(:) analysis points are existing analysis points: + + DO I=1,InputFileData%NBlGages + IF ( InputFileData%BldGagNd(I) < 1_IntKi .OR. InputFileData%BldGagNd(I) > InputFileData%InpBlMesh(1)%BldNodes ) THEN + CALL SetErrStat( ErrID_Fatal, ' All BldGagNd values must be between 1 and '//& + TRIM( Num2LStr( InputFileData%InpBlMesh(1)%BldNodes ) )//' (inclusive).',ErrStat,ErrMsg,RoutineName) + EXIT ! stop checking this loop + END IF + END DO + + END IF + + !bjj: since ED doesn't actually use OutFmt at this point, I'm going to remove this check and warning message + !!!! ! Check that InputFileData%OutFmt is a valid format specifier and will fit over the column headings + !!!!CALL ChkRealFmtStr( InputFileData%OutFmt, 'OutFmt', FmtWidth, ErrStat2, ErrMsg2 ) + !!!!CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName ) + !!!!IF ( FmtWidth /= ChanLen ) CALL SetErrStat(ErrID_Warn, 'OutFmt produces a column width of '//TRIM(Num2LStr(FmtWidth))//& + !!!! ' instead of '//TRIM(Num2LStr(ChanLen))//' characters.',ErrStat,ErrMsg,RoutineName ) + + + RETURN + +END SUBROUTINE ValidatePrimaryData +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE ElastoDyn_IO +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/elastodyn/src/ElastoDyn_Registry.txt b/OpenFAST/modules/elastodyn/src/ElastoDyn_Registry.txt new file mode 100644 index 000000000..ed6dc2c2b --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ElastoDyn_Registry.txt @@ -0,0 +1,873 @@ +################################################################################################################################### +# Registry for ElastoDyn in the FAST Modularization Framework +# This Registry file is used to create MODULE ElastoDyn_Types which contains all of the user-defined types needed in ElastoDyn. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + +# ElastoDyn Constants +param ElastoDyn/ED - IntKi ED_NMX - 4 - "Used in updating predictor-corrector values (size of state history)" - + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef ElastoDyn/ED InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ InitInputType CHARACTER(1024) ADInputFile - - - "Name of the AeroDyn input file (in this verison, that is where we'll get the blade mesh info" - +typedef ^ InitInputType LOGICAL CompElast - - - "flag to determine if ElastoDyn is computing blade loads (true) or BeamDyn is (false)" - +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType IntKi NumBl - - - "Number of blades on the turbine" - +typedef ^ InitOutputType ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ InitOutputType ReKi BlPitch {:} - - "Initial blade pitch angles" radians +typedef ^ InitOutputType ReKi BladeLength - - - "Blade length (for AeroDyn)" meters +typedef ^ InitOutputType ReKi TowerHeight - - - "Tower Height" meters +typedef ^ InitOutputType ReKi TowerBaseHeight - - - "Tower Base Height" meters +typedef ^ InitOutputType ReKi HubHt - - - "Height of the hub" meters +typedef ^ InitOutputType ReKi BldRNodes {:} - - "Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL )" +typedef ^ InitOutputType ReKi TwrHNodes {:} - - "Location of variable-spaced tower nodes (relative to the tower rigid base height" +typedef ^ InitOutputType ReKi PlatformPos {6} - - "Initial platform position (6 DOFs)" +typedef ^ InitOutputType ReKi TwrBasePos {3} - - "initial position of the tower base (for SrvD)" m +typedef ^ InitOutputType ReKi HubRad - - - "Preconed hub radius (distance from the rotor apex to the blade root)" m +typedef ^ InitOutputType ReKi RotSpeed - - - "Initial or fixed rotor speed" rad/s +typedef ^ InitOutputType LOGICAL isFixed_GenDOF - - - "whether the generator is fixed or free" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states 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" - +typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - + +# ..... Blade Input file data ........................................................................................................... +typedef ElastoDyn/ED BladeInputData IntKi NBlInpSt - - - "Number of blade input stations" - +typedef ^ BladeInputData ReKi BlFract {:} - - "Blade fractional radius for distributed input data" - +typedef ^ BladeInputData ReKi PitchAx {:} - - "Pitch axis for distributed input data" - +typedef ^ BladeInputData ReKi StrcTwst {:} - - "Structural twist for distributed input data" radians +typedef ^ BladeInputData ReKi BMassDen {:} - - "Blade mass density for distributed input data" +typedef ^ BladeInputData ReKi FlpStff {:} - - "Blade flap stiffness for distributed input data" +typedef ^ BladeInputData ReKi EdgStff {:} - - "Blade edge stiffness for distributed input data" +typedef ^ BladeInputData ReKi GJStff {:} - - "Blade torsional stiffness for a given input station" +typedef ^ BladeInputData ReKi EAStff {:} - - "Blade extensional stiffness for a given input station" +typedef ^ BladeInputData ReKi Alpha {:} - - "Blade coupling coefficient between flap and twist for a given input station" +typedef ^ BladeInputData ReKi FlpIner {:} - - "Blade flap (about local structural yb-axis) mass inertia per unit length for a given input station" +typedef ^ BladeInputData ReKi EdgIner {:} - - "Blade edge (about local structural xb-axis) mass inertia per unit length for a given input station" +typedef ^ BladeInputData ReKi PrecrvRef {:} - - "Offset for defining the reference axis from the pitch axis for precurved blades at a given input station" +typedef ^ BladeInputData ReKi PreswpRef {:} - - "Offset for defining the reference axis from the pitch axis for preswept blades at a given input station" +typedef ^ BladeInputData ReKi FlpcgOf {:} - - "Blade flap (along local aerodynamic xb-axis) mass cg offset for a given input station" +typedef ^ BladeInputData ReKi EdgcgOf {:} - - "Blade edge (along local aerodynamic yb-axis) mass cg offset for a given input station" +typedef ^ BladeInputData ReKi FlpEAOf {:} - - "Blade flap (along local aerodynamic xb-axis) elastic axis offset for a given input station" +typedef ^ BladeInputData ReKi EdgEAOf {:} - - "Blade edge (along local aerodynamic yb-axis) elastic axis offset for a given input station" +typedef ^ BladeInputData ReKi BldFlDmp 2 - - "Blade structural damping ratios in flapwise direction" +typedef ^ BladeInputData ReKi BldEdDmp 1 - - "Blade structural damping ratios in edgewise direction" +typedef ^ BladeInputData ReKi FlStTunr 2 - - "Blade flapwise modal stiffness tuners (input)" +typedef ^ BladeInputData ReKi BldFl1Sh {:} - - "Blade-flap-mode-1 shape coefficients" +typedef ^ BladeInputData ReKi BldFl2Sh {:} - - "Blade-flap-mode-2 shape coefficients" +typedef ^ BladeInputData ReKi BldEdgSh {:} - - "Blade-edge-mode shape coefficients" + + +# ..... Blade Mesh Input file data ........................................................................................................... +typedef ElastoDyn/ED ED_BladeMeshInputData IntKi BldNodes - - - "Number of blade nodes used for analysis" - +typedef ^ ED_BladeMeshInputData ReKi RNodes {:} - - "Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL )" +typedef ^ ED_BladeMeshInputData ReKi AeroTwst {:} - - "Aerodynamic twist of the blade at the analysis nodes" radians +typedef ^ ED_BladeMeshInputData ReKi Chord {:} - - "Chord of the blade at the analysis nodes" + + +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary Input file data ........................................................................................................... +typedef ElastoDyn/ED ED_InputFile DbKi DT - - - "Requested integration time for ElastoDyn" seconds +typedef ^ ED_InputFile ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ ED_InputFile LOGICAL FlapDOF1 - - - "First flapwise blade mode DOF" - +typedef ^ ED_InputFile LOGICAL FlapDOF2 - - - "Second flapwise blade mode DOF" - +typedef ^ ED_InputFile LOGICAL EdgeDOF - - - "Edgewise blade mode DOF" - +typedef ^ ED_InputFile LOGICAL TeetDOF - - - "Rotor-teeter DOF" - +typedef ^ ED_InputFile LOGICAL DrTrDOF - - - "Drivetrain rotational-flexibility DOF" - +typedef ^ ED_InputFile LOGICAL GenDOF - - - "Generator DOF" - +typedef ^ ED_InputFile LOGICAL YawDOF - - - "Nacelle-yaw DOF" - +typedef ^ ED_InputFile LOGICAL TwFADOF1 - - - "First tower fore-aft bending-mode DOF" - +typedef ^ ED_InputFile LOGICAL TwFADOF2 - - - "Second tower fore-aft bending-mode DOF" - +typedef ^ ED_InputFile LOGICAL TwSSDOF1 - - - "First tower side-to-side bending-mode DOF" - +typedef ^ ED_InputFile LOGICAL TwSSDOF2 - - - "Second tower side-to-side bending-mode DOF" - +typedef ^ ED_InputFile LOGICAL PtfmSgDOF - - - "Platform horizontal surge translation DOF" - +typedef ^ ED_InputFile LOGICAL PtfmSwDOF - - - "Platform horizontal sway translation DOF" - +typedef ^ ED_InputFile LOGICAL PtfmHvDOF - - - "Platform vertical heave translation DOF" - +typedef ^ ED_InputFile LOGICAL PtfmRDOF - - - "Platform roll tilt rotation DOF" - +typedef ^ ED_InputFile LOGICAL PtfmPDOF - - - "Platform pitch tilt rotation DOF" - +typedef ^ ED_InputFile LOGICAL PtfmYDOF - - - "Platform yaw rotation DOF" - +typedef ^ ED_InputFile ReKi OoPDefl - - - "Initial out-of-plane blade-tip displacement" meters +typedef ^ ED_InputFile ReKi IPDefl - - - "Initial in-plane blade-tip deflection" meters +typedef ^ ED_InputFile ReKi BlPitch {:} - - "Initial blade pitch angles" radians +typedef ^ ED_InputFile ReKi TeetDefl - - - "Initial teeter angle" radians +typedef ^ ED_InputFile R8Ki Azimuth - - - "Initial azimuth angle for blade 1" radians +typedef ^ ED_InputFile ReKi RotSpeed - - - "Initial rotor speed" rad/s +typedef ^ ED_InputFile ReKi NacYaw - - - "Initial nacelle-yaw angle" radians +typedef ^ ED_InputFile ReKi TTDspFA - - - "Initial fore-aft tower-top displacement" meters +typedef ^ ED_InputFile ReKi TTDspSS - - - "Initial side-to-side tower-top displacement" meters +typedef ^ ED_InputFile ReKi PtfmSurge - - - "Initial horizontal surge translational displacement of platform" meters +typedef ^ ED_InputFile ReKi PtfmSway - - - "Initial horizontal sway translational displacement of platform" meters +typedef ^ ED_InputFile ReKi PtfmHeave - - - "Initial vertical heave translational displacement of platform" meters +typedef ^ ED_InputFile ReKi PtfmRoll - - - "Initial roll tilt rotational displacement of platform" radians +typedef ^ ED_InputFile ReKi PtfmPitch - - - "Initial pitch tilt rotational displacement of platform" radians +typedef ^ ED_InputFile ReKi PtfmYaw - - - "Initial yaw rotational displacement of platform" radians +typedef ^ ED_InputFile IntKi NumBl - - - "Number of blades" - +typedef ^ ED_InputFile ReKi TipRad - - - "Preconed blade-tip radius (distance from the rotor apex to the blade tip)" meters +typedef ^ ED_InputFile ReKi HubRad - - - "Preconed hub radius (distance from the rotor apex to the blade root)" meters +typedef ^ ED_InputFile ReKi PreCone {:} - - "Rotor precone angles" radians +typedef ^ ED_InputFile ReKi HubCM - - - "Distance from rotor apex to hub mass" meters +typedef ^ ED_InputFile ReKi UndSling - - - "Undersling length" meters +typedef ^ ED_InputFile ReKi Delta3 - - - "Delta-3 angle for teetering rotors" radians +typedef ^ ED_InputFile R8Ki AzimB1Up - - - "Azimuth value to use for I/O when blade 1 points up" radians +typedef ^ ED_InputFile ReKi OverHang - - - "Distance from yaw axis to rotor apex or teeter pin" meters +typedef ^ ED_InputFile ReKi ShftGagL - - - "Distance from hub or teeter pin to shaft strain gages" meters +typedef ^ ED_InputFile ReKi ShftTilt - - - "Rotor shaft tilt angle" radians +typedef ^ ED_InputFile ReKi NacCMxn - - - "Downwind distance from tower-top to nacelle CM" meters +typedef ^ ED_InputFile ReKi NacCMyn - - - "Lateral distance from tower-top to nacelle CM" meters +typedef ^ ED_InputFile ReKi NacCMzn - - - "Vertical distance from tower-top to nacelle CM" meters +typedef ^ ED_InputFile ReKi NcIMUxn - - - "Downwind distance from the tower-top to the nacelle IMU" meters +typedef ^ ED_InputFile ReKi NcIMUyn - - - "Lateral distance from the tower-top to the nacelle IMU" meters +typedef ^ ED_InputFile ReKi NcIMUzn - - - "Vertical distance from the tower-top to the nacelle IMU" meters +typedef ^ ED_InputFile ReKi Twr2Shft - - - "Vertical distance from the tower-top to the rotor shaft" meters +typedef ^ ED_InputFile ReKi TowerHt - - - "Height of tower above ground level [onshore] or MSL [offshore]" meters +typedef ^ ED_InputFile ReKi TowerBsHt - - - "Height of tower base above ground level [onshore] or MSL [offshore]" meters +typedef ^ ED_InputFile ReKi PtfmCMxt - - - "Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM" meters +typedef ^ ED_InputFile ReKi PtfmCMyt - - - "Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM" meters +typedef ^ ED_InputFile ReKi PtfmCMzt - - - "Vertical distance from the ground [onshore] or MSL [offshore] to the platform CM" meters +typedef ^ ED_InputFile ReKi PtfmRefzt - - - "Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point" meters +typedef ^ ED_InputFile ReKi TipMass {:} - - "Tip-brake masses" kg +typedef ^ ED_InputFile ReKi HubMass - - - "Hub mass" kg +typedef ^ ED_InputFile ReKi HubIner - - - "Hub inertia about teeter axis (2-blader) or rotor axis (3-blader)" "kg m^2" +typedef ^ ED_InputFile ReKi GenIner - - - "Generator inertia about HSS" "kg m^2" +typedef ^ ED_InputFile ReKi NacMass - - - "Nacelle mass" kg +typedef ^ ED_InputFile ReKi NacYIner - - - "Nacelle yaw inertia" "kg m^2" +typedef ^ ED_InputFile ReKi YawBrMass - - - "Yaw bearing mass" kg +typedef ^ ED_InputFile ReKi PtfmMass - - - "Platform mass" kg +typedef ^ ED_InputFile ReKi PtfmRIner - - - "Platform inertia for roll tilt rotation about the platform CM" "kg m^2" +typedef ^ ED_InputFile ReKi PtfmPIner - - - "Platform inertia for pitch tilt rotation about the platform CM" "kg m^2" +typedef ^ ED_InputFile ReKi PtfmYIner - - - "Platform inertia for yaw rotation about the platform CM" "kg m^2" +typedef ^ ED_InputFile ReKi BldNodes - - - "Number of blade nodes (per blade) used for analysis" - +typedef ^ ED_InputFile ED_BladeMeshInputData InpBlMesh {:} - - "Input data for blade discretizations (could be on each blade)" "see BladeMeshInputData" +typedef ^ ED_InputFile BladeInputData InpBl {:} - - "Input data for individual blades" "see BladeInputData type" +typedef ^ ED_InputFile IntKi TeetMod - - - "Rotor-teeter spring/damper model switch" - +typedef ^ ED_InputFile ReKi TeetDmpP - - - "Rotor-teeter damper position" radians +typedef ^ ED_InputFile ReKi TeetDmp - - - "Rotor-teeter damping constant" N-m/(rad/s) +typedef ^ ED_InputFile ReKi TeetCDmp - - - "Rotor-teeter rate-independent Coulomb-damping" N-m +typedef ^ ED_InputFile ReKi TeetSStP - - - "Rotor-teeter soft-stop position" radians +typedef ^ ED_InputFile ReKi TeetHStP - - - "Rotor-teeter hard-stop position" radians +typedef ^ ED_InputFile ReKi TeetSSSp - - - "Rotor-teeter soft-stop linear-spring constant" N-m/rad +typedef ^ ED_InputFile ReKi TeetHSSp - - - "Rotor-teeter hard-stop linear-spring constant" N-m/rad +typedef ^ ED_InputFile ReKi GBoxEff - - - "Gearbox efficiency" % +typedef ^ ED_InputFile ReKi GBRatio - - - "Gearbox ratio" - +typedef ^ ED_InputFile ReKi DTTorSpr - - - "Drivetrain torsional spring" N-m/rad +typedef ^ ED_InputFile ReKi DTTorDmp - - - "Drivetrain torsional damper" N-m/(rad/s) +typedef ^ ED_InputFile LOGICAL Furling - - - "Use Additional Furling parameters?" - +typedef ^ ED_InputFile IntKi TwrNodes - - - "Number of tower nodes used in the analysis" - +typedef ^ ED_InputFile LOGICAL SumPrint - - - "Print summary data to <RootName>.sum" - +typedef ^ ED_InputFile IntKi OutFile - - - "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both)" - +#typedef ^ ED_InputFile IntKi OutFileFmt - - - "Format for module tabular (time-marching) output: {1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both}" - +typedef ^ ED_InputFile LOGICAL TabDelim - - - "Flag to cause tab-delimited text output (delimited by space otherwise)" - +typedef ^ ED_InputFile CHARACTER(20) OutFmt - - - "Format used for module's text tabular output (except time); resulting field should be 10 characters" - +typedef ^ ED_InputFile DbKi Tstart - - - "Time to start module's tabular output" seconds +typedef ^ ED_InputFile IntKi DecFact - - - "Decimation factor for module's tabular output (1=output every step)" - +typedef ^ ED_InputFile IntKi NTwGages - - - "Number of tower strain gages" - +typedef ^ ED_InputFile IntKi TwrGagNd 9 - - "Nodes closest to the tower strain gages" - +typedef ^ ED_InputFile IntKi NBlGages - - - "Number of blade strain gages" - +typedef ^ ED_InputFile IntKi BldGagNd 9 - - "Nodes closest to the blade strain gages" - +typedef ^ ED_InputFile IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ED_InputFile CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - + +# ..... Tower Input file data ........................................................................................................... +typedef ^ ED_InputFile IntKi NTwInpSt - - - "Number of tower input stations" - +typedef ^ ED_InputFile ReKi TwrFADmp 2 - - "Tower fore-aft structural damping ratios" % +typedef ^ ED_InputFile ReKi TwrSSDmp 2 - - "Tower side-to-side structural damping ratios" % +typedef ^ ED_InputFile ReKi FAStTunr 2 - - "Tower fore-aft modal stiffness tuners" - +typedef ^ ED_InputFile ReKi SSStTunr 2 - - "Tower side-to-side modal stiffness tuners" - +typedef ^ ED_InputFile ReKi HtFract {:} - - "Fractional height of the flexible portion of tower for a given input station" - +typedef ^ ED_InputFile ReKi TMassDen {:} - - "Tower mass density for a given input station" kg/m +typedef ^ ED_InputFile ReKi TwFAStif {:} - - "Tower fore-aft stiffness for a given input station" Nm^2 +typedef ^ ED_InputFile ReKi TwSSStif {:} - - "Tower side-to-side stiffness for a given input station" Nm^2 +typedef ^ ED_InputFile ReKi TwFAM1Sh {:} - - "Tower fore-aft mode-1 shape coefficients" - +typedef ^ ED_InputFile ReKi TwFAM2Sh {:} - - "Tower fore-aft mode-2 shape coefficients" - +typedef ^ ED_InputFile ReKi TwSSM1Sh {:} - - "Tower side-to-side mode-1 shape coefficients" - +typedef ^ ED_InputFile ReKi TwSSM2Sh {:} - - "Tower side-to-side mode-2 shape coefficients" - +# ..... Tower Input file data (ADAMS only) ........................................................................................................... +typedef ^ ED_InputFile ReKi TwGJStif {:} - - "Tower torsional stiffness for a given input station" Nm^2 +typedef ^ ED_InputFile ReKi TwEAStif {:} - - "Tower extensional stiffness for a given input station" N +typedef ^ ED_InputFile ReKi TwFAIner {:} - - "Tower fore-aft (about yt-axis) mass inertia per unit length for a given input station" "kg m" +typedef ^ ED_InputFile ReKi TwSSIner {:} - - "Tower side-to-side (about xt-axis) mass inertia per unit length for a given input station" "kg m" +typedef ^ ED_InputFile ReKi TwFAcgOf {:} - - "Tower fore-aft (along the xt-axis) mass cg offset for a given input station" meters +typedef ^ ED_InputFile ReKi TwSScgOf {:} - - "Tower fore-aft (along the yt-axis) mass cg offset for a given input station" meters +# ..... Furling Input file data ........................................................................................................... +typedef ^ ED_InputFile LOGICAL RFrlDOF - - - "Rotor-furl DOF" - +typedef ^ ED_InputFile LOGICAL TFrlDOF - - - "Tail-furl DOF" - +typedef ^ ED_InputFile ReKi RotFurl - - - "Initial or fixed rotor-furl angle" radians +typedef ^ ED_InputFile ReKi TailFurl - - - "Initial or fixed tail-furl angle" radians +typedef ^ ED_InputFile ReKi Yaw2Shft - - - "Lateral distance from the yaw axis to the rotor shaft" meters +typedef ^ ED_InputFile ReKi ShftSkew - - - "Rotor shaft skew angle" radians +typedef ^ ED_InputFile ReKi RFrlCMxn - - - "Downwind distance from tower-top to rotor-furl CM" meters +typedef ^ ED_InputFile ReKi RFrlCMyn - - - "Lateral distance from tower-top to rotor-furl CM" meters +typedef ^ ED_InputFile ReKi RFrlCMzn - - - "Vertical distance from tower-top to rotor-furl CM" meters +typedef ^ ED_InputFile ReKi BoomCMxn - - - "Downwind distance from tower-top to tail boom CM" meters +typedef ^ ED_InputFile ReKi BoomCMyn - - - "Lateral distance from tower-top to tail boom CM" meters +typedef ^ ED_InputFile ReKi BoomCMzn - - - "Vertical distance from tower-top to tail boom CM" meters +typedef ^ ED_InputFile ReKi TFinCMxn - - - "Downwind distance from tower-top to tail fin CM" meters +typedef ^ ED_InputFile ReKi TFinCMyn - - - "Lateral distance from tower-top to tail fin CM" meters +typedef ^ ED_InputFile ReKi TFinCMzn - - - "Vertical distance from tower-top to tail fin CM" meters +typedef ^ ED_InputFile ReKi TFinCPxn - - - "Downwind distance from tower-top to tail fin CP" meters +typedef ^ ED_InputFile ReKi TFinCPyn - - - "Lateral distance from tower-top to tail fin CP" meters +typedef ^ ED_InputFile ReKi TFinCPzn - - - "Vertical distance from tower-top to tail fin CP" meters +typedef ^ ED_InputFile ReKi TFinSkew - - - "Tail fin chordline skew angle" radians +typedef ^ ED_InputFile ReKi TFinTilt - - - "Tail fin chordline tilt angle" radians +typedef ^ ED_InputFile ReKi TFinBank - - - "Tail fin planform bank angle" radians +typedef ^ ED_InputFile ReKi RFrlPntxn - - - "Downwind distance from tower-top to arbitrary point on rotor-furl axis" meters +typedef ^ ED_InputFile ReKi RFrlPntyn - - - "Lateral distance from tower-top to arbitrary point on rotor-furl axis" meters +typedef ^ ED_InputFile ReKi RFrlPntzn - - - "Vertical distance from tower-top to arbitrary point on rotor-furl axis" meters +typedef ^ ED_InputFile ReKi RFrlSkew - - - "Rotor-furl axis skew angle" radians +typedef ^ ED_InputFile ReKi RFrlTilt - - - "Rotor-furl axis tilt angle" radians +typedef ^ ED_InputFile ReKi TFrlPntxn - - - "Downwind distance from tower-top to arbitrary point on tail-furl axis" meters +typedef ^ ED_InputFile ReKi TFrlPntyn - - - "Lateral distance from tower-top to arbitrary point on tail-furl axis" meters +typedef ^ ED_InputFile ReKi TFrlPntzn - - - "Vertical distance from tower-top to arbitrary point on tail-furl axis" meters +typedef ^ ED_InputFile ReKi TFrlSkew - - - "Rotor-furl axis skew angle" radians +typedef ^ ED_InputFile ReKi TFrlTilt - - - "Rotor-furl axis tilt angle" radians +typedef ^ ED_InputFile ReKi RFrlMass - - - "Rotor-furl mass" kg +typedef ^ ED_InputFile ReKi BoomMass - - - "Tail boom mass" kg +typedef ^ ED_InputFile ReKi TFinMass - - - "Tail fin mass" kg +typedef ^ ED_InputFile ReKi RFrlIner - - - "Rotor-furl inertia about rotor-furl axis" "kg m^2" +typedef ^ ED_InputFile ReKi TFrlIner - - - "Tail boom inertia about tail-furl axis" "kg m^2" +typedef ^ ED_InputFile IntKi RFrlMod - - - "Rotor-furl spring/damper model switch" - +typedef ^ ED_InputFile ReKi RFrlSpr - - - "Rotor-furl spring constant" N-m/rad +typedef ^ ED_InputFile ReKi RFrlDmp - - - "Rotor-furl damping constant" N-m/(rad/s) +typedef ^ ED_InputFile ReKi RFrlCDmp - - - "Rotor-furl rate-independent Coulomb-damping moment" N-m +typedef ^ ED_InputFile ReKi RFrlUSSP - - - "Rotor-furl up-stop spring position" radians +typedef ^ ED_InputFile ReKi RFrlDSSP - - - "Rotor-furl down-stop spring position" radians +typedef ^ ED_InputFile ReKi RFrlUSSpr - - - "Rotor-furl up-stop spring constant" N-m/rad +typedef ^ ED_InputFile ReKi RFrlDSSpr - - - "Rotor-furl down-stop spring constant" N-m/rad +typedef ^ ED_InputFile ReKi RFrlUSDP - - - "Rotor-furl up-stop damper position" radians +typedef ^ ED_InputFile ReKi RFrlDSDP - - - "Rotor-furl down-stop damper position" radians +typedef ^ ED_InputFile ReKi RFrlUSDmp - - - "Rotor-furl up-stop damping constant" N-m/(rad/s) +typedef ^ ED_InputFile ReKi RFrlDSDmp - - - "Rotor-furl down-stop damping constant" N-m/(rad/s) +typedef ^ ED_InputFile IntKi TFrlMod - - - "Tail-furl spring/damper model switch" - +typedef ^ ED_InputFile ReKi TFrlSpr - - - "Tail-furl spring constant" N-m/rad +typedef ^ ED_InputFile ReKi TFrlDmp - - - "Tail-furl damping constant" N-m/(rad/s) +typedef ^ ED_InputFile ReKi TFrlCDmp - - - "Tail-furl rate-independent Coulomb-damping moment" N-m +typedef ^ ED_InputFile ReKi TFrlUSSP - - - "Tail-furl up-stop spring position" radians +typedef ^ ED_InputFile ReKi TFrlDSSP - - - "Tail-furl down-stop spring position" radians +typedef ^ ED_InputFile ReKi TFrlUSSpr - - - "Tail-furl up-stop spring constant" N-m/rad +typedef ^ ED_InputFile ReKi TFrlDSSpr - - - "Tail-furl down-stop spring constant" N-m/rad +typedef ^ ED_InputFile ReKi TFrlUSDP - - - "Tail-furl up-stop damper position" radians +typedef ^ ED_InputFile ReKi TFrlDSDP - - - "Tail-furl down-stop damper position" radians +typedef ^ ED_InputFile ReKi TFrlUSDmp - - - "Tail-furl up-stop damping constant" N-m/(rad/s) +typedef ^ ED_InputFile ReKi TFrlDSDmp - - - "Tail-furl down-stop damping constant" N-m/(rad/s) +typedef ^ ED_InputFile IntKi method - - - "Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4])" - + +# ..... ED_AllBldNdOuts compile option ............................................................................................ +typedef ^ ED_InputFile IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (ED_AllBldNdOuts)" - +typedef ^ ED_InputFile CHARACTER(ChanLen) BldNd_OutList {:} - - "List of user-requested output channels (ED_AllBldNdOuts)" - +#typedef ^ ED_InputFile IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (ED_AllBldNdOuts)" - +typedef ^ ED_InputFile CHARACTER(1024) BldNd_BlOutNd_Str - - - "String to parse for the blade nodes to actually output (ED_AllBldNdOuts)" - +typedef ^ ED_InputFile IntKi BldNd_BladesOut - - - "The blades to output (ED_AllBldNdOuts)" - + +# ..... Internal data types ....................................................................................................... + +# ..... Internal data types: Coordinate Systems ................................................................................... +# This type defines coordinate sytems used internally by FAST. The 3 components of each vector correspond to the z1, z2, and z3 components of the individual vectors. +# NOTE: the orientations of most of these coordinate systems will change every time step. +typedef ^ ED_CoordSys R8Ki a1 3 - - "Vector / direction a1 (= xt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki a2 3 - - "Vector / direction a2 (= zt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki a3 3 - - "Vector / direction a3 (= -yt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki b1 3 - - "Vector / direction b1 (= xp from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki b2 3 - - "Vector / direction b2 (= zp from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki b3 3 - - "Vector / direction b3 (= -yp from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki c1 3 - - "Vector / direction c1 (= xs from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki c2 3 - - "Vector / direction c2 (= zs from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki c3 3 - - "Vector / direction c3 (= -ys from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki d1 3 - - "Vector / direction d1 (= xn from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki d2 3 - - "Vector / direction d2 (= zn from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki d3 3 - - "Vector / direction d3 (= -yn from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki e1 3 - - "Vector / direction e1 (= xa from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki e2 3 - - "Vector / direction e2 (= ya from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki e3 3 - - "Vector / direction e3 (= za from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki f1 3 - - "Vector / direction f1" - +typedef ^ ED_CoordSys R8Ki f2 3 - - "Vector / direction f2" - +typedef ^ ED_CoordSys R8Ki f3 3 - - "Vector / direction f3" - +typedef ^ ED_CoordSys R8Ki g1 3 - - "Vector / direction g1 (= xh from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki g2 3 - - "Vector / direction g2 (= yh from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki g3 3 - - "Vector / direction g3 (= zh from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki i1 {:}{:} - - "i1(K,:) = vector / direction i1 for blade K (= xcK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki i2 {:}{:} - - "i2(K,:) = vector / direction i2 for blade K (= ycK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki i3 {:}{:} - - "i3(K,:) = vector / direction i3 for blade K (= zcK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki j1 {:}{:} - - "j1(K,:) = vector / direction j1 for blade K (= xbK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki j2 {:}{:} - - "j2(K,:) = vector / direction j2 for blade K (= ybK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki j3 {:}{:} - - "j3(K,:) = vector / direction j3 for blade K (= zbK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki m1 {:}{:}{:} - - "m1(K,J,:) = vector / direction m1 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki m2 {:}{:}{:} - - "m2(K,J,:) = vector / direction m2 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki m3 {:}{:}{:} - - "m3(K,J,:) = vector / direction m3 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki n1 {:}{:}{:} - - "n1(K,J,:) = vector / direction n1 for node J of blade K (= LxbK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki n2 {:}{:}{:} - - "n2(K,J,:) = vector / direction n2 for node J of blade K (= LybK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki n3 {:}{:}{:} - - "n3(K,J,:) = vector / direction n3 for node J of blade K (= LzbK from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki p1 3 - - "Vector / direction p1 (used to calc. and return tail aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki p2 3 - - "Vector / direction p2 (used to calc. and return tail aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki p3 3 - - "Vector / direction p3 (used to calc. and return tail aerodynamic loads from AeroDyn)" - +typedef ^ ED_CoordSys R8Ki rf1 3 - - "Vector / direction rf1 (rotor-furl coordinate system = d1 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki rf2 3 - - "Vector / direction rf2 (rotor-furl coordinate system = d2 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki rf3 3 - - "Vector / direction rf3 (rotor-furl coordinate system = d3 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki rfa 3 - - "Vector / direction of the rotor-furl axis" - +typedef ^ ED_CoordSys R8Ki t1 {:}{:} - - "Vector / direction t1 for tower node J (= Lxt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki t2 {:}{:} - - "Vector / direction t2 for tower node J (= Lzt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki t3 {:}{:} - - "Vector / direction t3 for tower node J (= -Lyt from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki te1 {:}{:}{:} - - "te1(K,J,:) = vector / direction te1 for node J of blade K (used to calc. noise)" - +typedef ^ ED_CoordSys R8Ki te2 {:}{:}{:} - - "te2(K,J,:) = vector / direction te2 for node J of blade K (used to calc. noise)" - +typedef ^ ED_CoordSys R8Ki te3 {:}{:}{:} - - "te3(K,J,:) = vector / direction te3 for node J of blade K (used to calc. noise)" - +typedef ^ ED_CoordSys R8Ki tf1 3 - - "Vector / direction tf1 (tail-furl coordinate system = d1 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki tf2 3 - - "Vector / direction tf2 (tail-furl coordinate system = d2 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki tf3 3 - - "Vector / direction tf3 (tail-furl coordinate system = d3 when rotor-furl angle = 0)" - +typedef ^ ED_CoordSys R8Ki tfa 3 - - "Vector / direction of the tail-furl axis" - +typedef ^ ED_CoordSys R8Ki z1 3 - - "Vector / direction z1 (= xi from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki z2 3 - - "Vector / direction z2 (= zi from the IEC coord. system)" - +typedef ^ ED_CoordSys R8Ki z3 3 - - "Vector / direction z3 (= -yi from the IEC coord. system)" - + +# ..... Internal data types: Enabled DOFs ........................................................................................ +# This type defines variables associated with the module's degrees of freedom (DOFs) +# NOTE: The number of active DOFs may change with time. +typedef ^ ED_ActiveDOFs IntKi NActvDOF - - - "The number of active (enabled) DOFs in the model" - +typedef ^ ED_ActiveDOFs IntKi NPCE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPDE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPIE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPTE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPTTE - - - "Number of tower DOFs that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPSBE {:} - - "Number of blade DOFs that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPSE {:} - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPUE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi NPYE - - - "Number of DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PCE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PDE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PIE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PTE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PTTE {:} - - "Array of tower DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PS {:} - - "Array of DOF indices (pointers) to the active (enabled) DOFs/states" +typedef ^ ED_ActiveDOFs IntKi PSBE {:}{:} - - "Array of blade DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PSE {:}{:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PUE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi PYE {:} - - "Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) in the inertia frame, based on which DOFs are presently enabled" +typedef ^ ED_ActiveDOFs IntKi SrtPS {:} - - "Sorted (from smallest to largest DOF index) version of PS()" +typedef ^ ED_ActiveDOFs IntKi SrtPSNAUG {:} - - "SrtPS() with the additional value of NAUG" +typedef ^ ED_ActiveDOFs IntKi Diag {:} - - "Array containing the indices of SrtPS() associated with each enabled DOF; that is, SrtPS(Diag(I)) = I" + +# ..... Internal data types: Right Hand Side ................................................................................... +# RtHS Positions: +typedef ^ ED_RtHndSide R8Ki rO 3 - - "Position vector from inertial frame origin to tower-top / base plate (point O)" m +typedef ^ ED_RtHndSide R8Ki rQS {:}{:}{:} - - "Position vector from the apex of rotation (point Q) to a point on a blade (point S)" m +typedef ^ ED_RtHndSide R8Ki rS {:}{:}{:} - - "Position vector from inertial frame origin to a point on a blade (point S)" m +typedef ^ ED_RtHndSide R8Ki rS0S {:}{:}{:} - - "Position vector from the blade root (point S(0)) to a point on a blade (point S)" m +typedef ^ ED_RtHndSide R8Ki rT {:}{:} - - "Position vector from inertial frame origin to the current node (point T(HNodes(J))" m +typedef ^ ED_RtHndSide R8Ki rT0O 3 - - "Position vector from the tower base (point T(0)) to tower-top / base plate (point O)" m +typedef ^ ED_RtHndSide R8Ki rT0T {:}{:} - - "Position vector from a height of TowerBsHt (base of flexible portion of tower) (point T(0)) to a point on the tower (point T)" m +typedef ^ ED_RtHndSide R8Ki rZ 3 - - "Position vector from inertia frame origin to platform reference (point Z)" m +typedef ^ ED_RtHndSide R8Ki rZO 3 - - "Position vector from platform reference (point Z) to tower-top / base plate (point O)" m +typedef ^ ED_RtHndSide R8Ki rZT {:}{:} - - "Position vector from platform reference (point Z) to a point on a tower (point T)" m +typedef ^ ED_RtHndSide R8Ki rPQ 3 - - "Position vector from teeter pin (point P) to apex of rotation (point Q)" m +typedef ^ ED_RtHndSide R8Ki rP 3 - - "Position vector from inertial frame origin to teeter pin (point P)" m +typedef ^ ED_RtHndSide R8Ki rV 3 - - "Position vector from inertial frame origin to specified point on rotor-furl axis (point V)" m +typedef ^ ED_RtHndSide R8Ki rZY 3 - - "Position vector from platform reference (point Z) to platform mass center (point Y)" m +typedef ^ ED_RtHndSide R8Ki rOU 3 - - "Position vector from tower-top / base plate (point O) to nacelle center of mass (point U)." m +typedef ^ ED_RtHndSide R8Ki rOV 3 - - "Position vector from tower-top / base plate (point O) to specified point on rotor-furl axis (point V)" m +typedef ^ ED_RtHndSide R8Ki rVD 3 - - "Position vector from specified point on rotor-furl axis (point V) to center of mass of structure that furls with the rotor (not including rotor) (point D)" m +typedef ^ ED_RtHndSide R8Ki rOW 3 - - "Position vector from tower-top / base plate (point O) to specified point on tail-furl axis (point W)" m +typedef ^ ED_RtHndSide R8Ki rPC 3 - - "Position vector from teeter pin (point P) to hub center of mass (point C)" m +typedef ^ ED_RtHndSide R8Ki rPS0 {:}{:} - - "Position vector from teeter pin (point P) to blade root (point S(0))" m +typedef ^ ED_RtHndSide R8Ki rQ 3 - - "Position vector from inertial frame origin to apex of rotation (point Q)" m +typedef ^ ED_RtHndSide R8Ki rQC 3 - - "Position vector from apex of rotation (point Q) to hub center of mass (point C)" m +typedef ^ ED_RtHndSide R8Ki rVIMU 3 - - "Position vector from specified point on rotor-furl axis (point V) to nacelle IMU (point IMU)" m +typedef ^ ED_RtHndSide R8Ki rVP 3 - - "Position vector from specified point on rotor-furl axis (point V) to teeter pin (point P)" m +typedef ^ ED_RtHndSide R8Ki rWI 3 - - "Position vector from specified point on tail-furl axis (point W) to tail boom center of mass (point I)" m +typedef ^ ED_RtHndSide R8Ki rWJ 3 - - "Position vector from specified point on tail-furl axis (point W) to tail fin center of mass (point J)" m +typedef ^ ED_RtHndSide R8Ki rWK 3 - - "Position vector from specified point on tail-furl axis (point W) to tail fin center of pressure (point K)" m +typedef ^ ED_RtHndSide R8Ki rZT0 3 - - "Position vector from platform reference (point Z) to tower base (point T(0))" m +# RtHS Angular positions +typedef ^ ED_RtHndSide ReKi AngPosEF {:}{:} - - "Angular position of the current point on the tower (body F) in the inertial frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngPosXF {:}{:} - - "Angular position of the current point on the tower (body F) in the platform (body X)" +typedef ^ ED_RtHndSide ReKi AngPosHM {:}{:}{:} - - "Angular position of eleMent J of blade K (body M) in the hub (body H)" +typedef ^ ED_RtHndSide ReKi AngPosXB 3 - - "Angular position of the base plate (body B) in the platform (body X)" +typedef ^ ED_RtHndSide ReKi AngPosEX 3 - - "Angular position of the platform (body X) in the inertial frame (body E for earth)" +# RtHS Angular velocities +typedef ^ ED_RtHndSide ReKi PAngVelEA {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the tail (body A) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEF {:}{:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of tower element J (body F) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEG {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the generator (body G) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEH {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the hub (body H) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEL {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the low-speed shaft (body L) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEM {:}{:}{:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of eleMent J of blade K (body M) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEM {:}{:}{:} - - "Angular velocity of of eleMent J of blade K (body M) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEN {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the nacelle (body N) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEA 3 - - "Angular velocity of the tail (body A) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEB {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the base plate (body B) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelER {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PAngVelEX {:}{:}{:} - - "Partial angular velocity (and its 1st time derivative) of the platform (body B) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEG 3 - - "Angular velocity of the generator (body G) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEH 3 - - "Angular velocity of the hub (body H) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEL 3 - - "Angular velocity of the low-speed shaft (body L) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEN 3 - - "Angular velocity of the nacelle (body N) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEB 3 - - "Angular velocity of the base plate (body B) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelER 3 - - "Angular velocity of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngVelEX 3 - - "Angular velocity of the platform (body X) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide R8Ki TeetAngVel - - - "Angular velocity of the teeter motion" +# RtHS Angular accelerations +typedef ^ ED_RtHndSide ReKi AngAccEBt 3 - - "Portion of the angular acceleration of the base plate (body B) in the inertia frame (body E for earth) associated with everything but the QD2T()s" +typedef ^ ED_RtHndSide ReKi AngAccERt 3 - - "Portion of the angular acceleration of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth) associated with everything but the QD2T()s" +typedef ^ ED_RtHndSide ReKi AngAccEXt 3 - - "Portion of the angular acceleration of the platform (body X) in the inertia frame (body E for earth) associated with everything but the QD2T()s" +typedef ^ ED_RtHndSide ReKi AngAccEFt {:}{:} - - "Portion of the angular acceleration of tower element J (body F) in the inertia frame (body E for earth) associated with everything but the QD2T()s" +typedef ^ ED_RtHndSide ReKi AngVelEF {:}{:} - - "Angular velocity of the current point on the tower (body F) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi AngAccEAt 3 - - "Portion of the angular acceleration of the tail (body A) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi AngAccEGt 3 - - "Portion of the angular acceleration of the generator (body G) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi AngAccEHt 3 - - "Portion of the angular acceleration of the hub (body H) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi AngAccELt 3 - - "Portion of the angular acceleration of the low-speed shaft (body L) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi AngAccENt 3 - - "Portion of the angular acceleration of the nacelle (body N) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +# RtHS Linear +typedef ^ ED_RtHndSide ReKi LinAccECt 3 - - "Portion of the linear acceleration of the hub center of mass (point C) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEDt 3 - - "Portion of the linear acceleration of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEIt 3 - - "Portion of the linear acceleration of the tail boom center of mass (point I) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEJt 3 - - "Portion of the linear acceleration of the tail fin center of mass (point J) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinAccEKt 3 - - "Portion of the linear acceleration of the tail fin center of pressure (point K) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinAccEPt 3 - - "Portion of the linear acceleration of the teeter pin (point P) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinAccEQt 3 - - "Portion of the linear acceleration of the apex of rotation (point Q) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEUt 3 - - "Portion of the linear acceleration of the nacelle center of mass (point U) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinAccEVt 3 - - "Portion of the linear acceleration of the selected point on the rotor-furl axis (point V) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinAccEWt 3 - - "Portion of the linear acceleration of the selected point on the tail-furl axis (point W) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEYt 3 - - "Portion of the linear acceleration of the platform center of mass (point Y) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi LinVelEK 3 - - "Linear velocity of tail fin center-of-pressure (point K) in the inertia frame" +typedef ^ ED_RtHndSide ReKi LinVelES {:}{:}{:} - - "Linear velocity of current point on the current blade (point S) in the inertia frame" +#typedef ^ ED_RtHndSide ReKi LinVelHS 3 - - "Relative linear velocity of the current point on the current blade (point S) in the hub frame (body H)" +#typedef ^ ED_RtHndSide ReKi LinVelXO 3 - - "Relative linear velocity of the tower-top / base plate (point O) in the platform (body X)" +#typedef ^ ED_RtHndSide ReKi LinVelXT 3 - - "Relative linear velocity of the current point on the tower (point T) in the platform (body X)" +typedef ^ ED_RtHndSide ReKi LinVelEQ 3 - - "Linear velocity of of the apex of rotation (point Q) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi LinVelET {:}{:} - - "Linear velocity of current point on the tower (point T) in the inertia frame" +typedef ^ ED_RtHndSide ReKi LinVelESm2 {:} - - "The m2-component (closest to tip) of LinVelES" +typedef ^ ED_RtHndSide ReKi PLinVelEIMU {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the nacelle IMU (point IMU) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEO {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the base plate (point O) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelES {:}{:}{:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of a point on a blade (point S) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelET {:}{:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of a point on the tower (point T) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEZ {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the platform reference point (point Z) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEC {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the hub center of mass (point C) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelED {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEI {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the tail boom center of mass (point I) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEJ {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the tail fin center of mass (point J) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEK {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the tail fin center of pressure(point K) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEP {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the teeter pin (point P) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEQ {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the apex of rotation (point Q) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEU {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the nacelle center of mass (point U) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEV {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the selected point on the rotor-furl axis (point V) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEW {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the selected point on the tail-furl axis (point W) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi PLinVelEY {:}{:}{:} - - "Partial linear velocity (and its 1st time derivative) of the platform mass center (point Y) in the inertia frame (body E for earth)" +typedef ^ ED_RtHndSide ReKi LinAccEIMUt 3 - - "Portion of the linear acceleration of the nacelle IMU (point IMU) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEOt 3 - - "Portion of the linear acceleration of the base plate (point O) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccESt {:}{:}{:} - - "Portion of the linear acceleration of a point on a blade (point S) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccETt {:}{:} - - "Portion of the linear acceleration of a point on the tower (point T) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinAccEZt 3 - - "Portion of the linear acceleration of the platform reference (point Z) in the inertia frame (body E for earth) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi LinVelEIMU 3 - - "Linear velocity of the nacelle IMU (point IMU) in the inertia frame" +typedef ^ ED_RtHndSide ReKi LinVelEZ 3 - - "Linear velocity of platform reference (point Z) in the inertia frame" +typedef ^ ED_RtHndSide ReKi LinVelEO 3 - - "Linear velocity of the base plate (point O) in the inertia frame (body E for earth)" +# RtHS Forces and Moments +typedef ^ ED_RtHndSide ReKi FrcONcRtt 3 - - "Portion of the force at yaw bearing (point O) due to the nacelle, generator, and rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FrcPRott 3 - - "Portion of the force at the teeter pin (point P) due to the rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FrcS0Bt {:}{:} - - "Portion of the force at the blade root (point S(0)) due to the blade associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FrcT0Trbt 3 - - "Portion of the force at tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FSAero {:}{:}{:} - - "The aerodynamic force per unit span acting on a blade at point S" +typedef ^ ED_RtHndSide ReKi FSTipDrag {:}{:} - - "The aerodynamic force at a blade tip resulting from tip drag" +typedef ^ ED_RtHndSide ReKi FTHydrot {:}{:} - - "Portion of the hydrodynamic force (& all other external forces, including aerodynamic) per unit length acting on the tower at point T associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FZHydrot 3 - - "Portion of the platform hydrodynamic force at the platform reference (point Z) associated with everything but the QD2T()'s" + +typedef ^ ED_RtHndSide ReKi MFHydrot {:}{:} - - "Portion of the hydrodynamic moment (and all other external moments, including aerodynamic) per unit length acting on a tower element (body F) at point T associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomBNcRtt 3 - - "Portion of the moment at the base plate (body B) / yaw bearing (point O) due to the nacelle, generator, and rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomH0Bt {:}{:} - - "Portion of the moment at the hub (body H) / blade root (point S(0)) due to the blade associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomLPRott 3 - - "Portion of the moment at the teeter pin (point P) on the low-speed shaft (body L) due to the rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomNGnRtt 3 - - "Portion of the moment at the nacelle (body N) / selected point on rotor-furl axis (point V) due the structure that furls with the rotor, generator, and rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomNTailt 3 - - "Portion of the moment at the nacelle (body N) / selected point on tail-furl axis (point W) due the tail associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MomX0Trbt 3 - - "Portion of the moment at the platform (body X) / tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi MMAero {:}{:}{:} - - "The aerodynamic moment per unit span acting on a blade at point S" +typedef ^ ED_RtHndSide ReKi MXHydrot 3 - - "Portion of the platform hydrodynamic moment acting at the platform (body X) / platform reference (point Z) associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi PFrcONcRt {:}{:} - - "Partial force at the yaw bearing (point O) due to the nacelle, generator, and rotor" +typedef ^ ED_RtHndSide ReKi PFrcPRot {:}{:} - - "Partial force at the teeter pin (point P) due to the rotor" +typedef ^ ED_RtHndSide ReKi PFrcS0B {:}{:}{:} - - "Partial force at the blade root (point S(0)) due to the blade" +typedef ^ ED_RtHndSide ReKi PFrcT0Trb {:}{:} - - "Partial force at the tower base (point T(0)) due to the turbine" +typedef ^ ED_RtHndSide ReKi PFTHydro {:}{:}{:} - - "Partial hydrodynamic force per unit length acting on the tower at point T" +typedef ^ ED_RtHndSide ReKi PFZHydro {6}{3} - - "Partial platform hydrodynamic force at the platform reference (point Z)" +typedef ^ ED_RtHndSide ReKi PMFHydro {:}{:}{:} - - "Partial hydrodynamic moment per unit length acting on a tower element (body F) at point T" +typedef ^ ED_RtHndSide ReKi PMomBNcRt {:}{:} - - "Partial moment at the base plate (body B) / yaw bearing (point O) due the nacelle, generator, and rotor" +typedef ^ ED_RtHndSide ReKi PMomH0B {:}{:}{:} - - "Partial moment at the hub (body H) / blade root (point S(0)) due to the blade" +typedef ^ ED_RtHndSide ReKi PMomLPRot {:}{:} - - "Partial moment at the teeter pin (point P) on the low-speed shaft (body L) due to the rotor" +typedef ^ ED_RtHndSide ReKi PMomNGnRt {:}{:} - - "Partial moment at the nacelle (body N) / selected point on rotor-furl axis (point V) due the structure that furls with the rotor, generator, and rotor" +typedef ^ ED_RtHndSide ReKi PMomNTail {:}{:} - - "Partial moment at the nacelle (body N) / selected point on tail-furl axis (point W) due the tail" +typedef ^ ED_RtHndSide ReKi PMomX0Trb {:}{:} - - "Partial moment at the platform (body X) / tower base (point T(0)) due to the turbine" +typedef ^ ED_RtHndSide ReKi PMXHydro {6}{3} - - "Partial platform hydrodynamic moment at the platform (body X) / platform reference (point Z)" +typedef ^ ED_RtHndSide R8Ki TeetAng - - - "Current teeter angle = QT(DOF_Teet) for 2-blader or 0 for 3-blader (this is used in place of QT(DOF_Teet) throughout RtHS()" +typedef ^ ED_RtHndSide ReKi FrcVGnRtt 3 - - "Portion of the force at the rotor-furl axis (point V) due to the structure that furls with the rotor, generator, and rotor associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FrcWTailt 3 - - "Portion of the force at the tail-furl axis (point W) due to the tail associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi FrcZAllt 3 - - "Portion of the force at platform reference (point Z) due to everything associated with everything but the QD2T()'s" +#typedef ^ ED_RtHndSide ReKi FKAero 3 - - "The tail fin aerodynamic force acting at point K, the center-of-pressure of the tail fin" +#typedef ^ ED_RtHndSide ReKi MAAero 3 - - "The tail fin aerodynamic moment acting at point K, the center-of-pressure of the tail fin" +typedef ^ ED_RtHndSide ReKi MomXAllt 3 - - "Portion of the moment at the platform (body X) / platform reference (point Z) due to everything associated with everything but the QD2T()'s" +typedef ^ ED_RtHndSide ReKi PFrcVGnRt {:}{:} - - "Partial force at the rotor-furl axis (point V) due to the structure that furls with the rotor, generator, and rotor" +typedef ^ ED_RtHndSide ReKi PFrcWTail {:}{:} - - "Partial force at the tail-furl axis (point W) due to the tail" +typedef ^ ED_RtHndSide ReKi PFrcZAll {:}{:} - - "Partial force at the platform reference (point Z) due to everything" +typedef ^ ED_RtHndSide ReKi PMomXAll {:}{:} - - "Partial moment at the platform (body X) / platform reference (point Z) due to the everything" +typedef ^ ED_RtHndSide ReKi TeetMom - - - "The total moment supplied by the stop, spring, and damper of the teeter mechanism" +typedef ^ ED_RtHndSide ReKi TFrlMom - - - "The total tail-furl spring and damper moment" +typedef ^ ED_RtHndSide ReKi RFrlMom - - - "The total rotor-furl spring and damper moment" +typedef ^ ED_RtHndSide ReKi GBoxEffFac - - - "The factor used to apply the gearbox efficiency effects to the equation associated with the generator DOF" +typedef ^ ED_RtHndSide ReKi rSAerCen {:}{:}{:} - - "aerodynamic pitching moment arm (i.e., the position vector from point S on the blade to the aerodynamic center of the element)" + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType R8Ki QT {:} - - "Current estimate of Q (displacement matrix) for each degree of freedom" - +typedef ^ ContinuousStateType ^ QDT {:} - - "Current estimate of QD (velocity matrix) for each degree of freedom" + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - + +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - + +# Define "other" states here: +typedef ^ OtherStateType IntKi n - - - "tracks time step for which OtherState was updated" +typedef ^ OtherStateType ED_ContinuousStateType xdot {ED_NMX} - - "previous state deriv for multi-step" +typedef ^ OtherStateType IntKi IC {:} - - "Array which stores pointers to predictor-corrector results" +typedef ^ OtherStateType ReKi HSSBrTrq - - - "HSSBrTrq from update states; a hack to get this working with a single integrator" - +typedef ^ OtherStateType ReKi HSSBrTrqC - - - "Commanded HSS brake torque (adjusted for sign)" N-m +typedef ^ OtherStateType IntKi SgnPrvLSTQ - - - "The sign of the low-speed shaft torque from the previous call to RtHS(). This is calculated at the end of RtHS(). NOTE: The low-speed shaft torque is assumed to be positive at the beginning of the run!" - +typedef ^ OtherStateType IntKi SgnLSTQ {ED_NMX} - - "history of sign of LSTQ" + +# ..... Misc Vars ................................................................................................................ +typedef ^ MiscVarType ED_CoordSys CoordSys - - - "Coordinate systems in the FAST framework" - +typedef ^ MiscVarType ED_RtHndSide RtHS - - - "Values used in calculating the right-hand-side RtHS (and outputs)" +typedef ^ MiscVarType ReKi AllOuts {:} - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" +typedef ^ MiscVarType R8Ki AugMat {:}{:} - - "The augmented matrix used for the solution of the QD2T()s" +typedef ^ MiscVarType R8Ki AugMat_factor {:}{:} - - "factored version of AugMat matrix" +typedef ^ MiscVarType R8Ki SolnVec {:} - - "b in the equation Ax=b (last column of AugMat)" +typedef ^ MiscVarType IntKi AugMat_pivot {:} - - "Pivot column for AugMat in LAPACK factorization" +typedef ^ MiscVarType ReKi OgnlGeAzRo {:} - - "Original DOF_GeAz row in AugMat" - +typedef ^ MiscVarType R8Ki QD2T {:} - - "Solution (acceleration) vector; the first time derivative of QDT" +typedef ^ MiscVarType Logical IgnoreMod - - - "whether to ignore the modulo in ED outputs (necessary for linearization perturbations)" - + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ParameterType DbKi DT24 - - - "=DT/24 (used in loose coupling)" seconds +typedef ^ ParameterType IntKi BldNodes - - - "Number of blade nodes used in the analysis" - +typedef ^ ParameterType IntKi TipNode - - - "Index of the additional node located at the blade tip = BldNodes + 1" - +typedef ^ ParameterType IntKi NDOF - - - "Number of total degrees of freedom (DOFs)" - +typedef ^ ParameterType R8Ki TwoPiNB - - - "Two pi divided by the number of blades" radians +typedef ^ ParameterType IntKi NAug - - - "Dimension of augmented solution matrix" - +typedef ^ ParameterType IntKi NPH - - - "Number of DOFs that contribute to the angular velocity of the hub (body H) in the inertia frame" +typedef ^ ParameterType IntKi PH {:} - - "Array of DOF indices (pointers) that contribute to the angular velocity of the hub (body H) in the inertia frame" +typedef ^ ParameterType IntKi NPM - - - "Number of DOFs that contribute to the angular velocity of the blade elements (body M) in the inertia frame" +typedef ^ ParameterType IntKi PM {:}{:} - - "Array of DOF indices (pointers) that contribute to the angular velocity of the blade elements (body M) in the inertia frame" +typedef ^ ParameterType LOGICAL DOF_Flag {:} - - "Array which stores values of the feature flags for each DOF" +typedef ^ ParameterType CHARACTER(99) DOF_Desc {:} - - "Array which stores descriptions of each DOF" +typedef ^ ParameterType ED_ActiveDOFs DOFs - - - "Active degrees of freedom in the model" +typedef ^ ParameterType IntKi NumOuts - 0 - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Output format for tabular data" - +typedef ^ ParameterType IntKi NBlGages - 0 - "Number of blade strain gages" - +typedef ^ ParameterType IntKi NTwGages - 0 - "Number of tower strain gages" - +typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" - +typedef ^ ParameterType ReKi AvgNrmTpRd - - - "Average tip radius normal to the shaft" meters +typedef ^ ParameterType R8Ki AzimB1Up - - - "Azimuth value to use for I/O when blade 1 points up" radians +typedef ^ ParameterType R8Ki CosDel3 - 1.0 - "Cosine of the Delta-3 angle for teetering rotors" +typedef ^ ParameterType R8Ki CosPreC {:} - - "Cosines of the precone angles" +typedef ^ ParameterType R8Ki CRFrlSkew - - - "Cosine of the rotor-furl axis skew angle" +typedef ^ ParameterType R8Ki CRFrlSkw2 - - - "Cosine-squared of the rotor-furl axis skew angle" +typedef ^ ParameterType R8Ki CRFrlTilt - - - "Cosine of the rotor-furl axis tilt angle" +typedef ^ ParameterType R8Ki CRFrlTlt2 - - - "Cosine-squared of the rotor-furl axis tilt angle" +typedef ^ ParameterType R8Ki CShftSkew - - - "Cosine of the shaft skew angle" +typedef ^ ParameterType R8Ki CShftTilt - - - "Cosine of the shaft tilt angle" +typedef ^ ParameterType R8Ki CSRFrlSkw - - - "Cosine*Sine of the rotor-furl axis skew angle" +typedef ^ ParameterType R8Ki CSRFrlTlt - - - "Cosine*Sine of the rotor-furl axis tilt angle" +typedef ^ ParameterType R8Ki CSTFrlSkw - - - "Cosine*Sine of the tail-furl axis skew angle" +typedef ^ ParameterType R8Ki CSTFrlTlt - - - "Cosine*Sine of the tail-furl axis tilt angle" +typedef ^ ParameterType R8Ki CTFinBank - - - "Cosine of the tail fin planform bank angle" +typedef ^ ParameterType R8Ki CTFinSkew - - - "Cosine of the tail fin chordline skew angle" +typedef ^ ParameterType R8Ki CTFinTilt - - - "Cosine of the tail fin chordline tilt angle" +typedef ^ ParameterType R8Ki CTFrlSkew - - - "Cosine of the tail-furl axis skew angle" +typedef ^ ParameterType R8Ki CTFrlSkw2 - - - "Cosine-squared of the tail-furl axis skew angle" +typedef ^ ParameterType R8Ki CTFrlTilt - - - "Cosine of the tail-furl axis tilt angle" +typedef ^ ParameterType R8Ki CTFrlTlt2 - - - "Cosine-squared of the tail-furl axis tilt angle" +typedef ^ ParameterType ReKi HubHt - - - "Hub-height as computed using FAST inputs [= TowerHt + Twr2Shft + OverHang*SIN( ShftTilt ) ] (was FASTHH)" +typedef ^ ParameterType ReKi HubCM - - - "Distance from rotor apex to hub mass" +typedef ^ ParameterType ReKi HubRad - - - "Preconed hub radius" +typedef ^ ParameterType ReKi NacCMxn - - - "Downwind distance from tower-top to nacelle CM" +typedef ^ ParameterType ReKi NacCMyn - - - "Lateral distance from tower-top to nacelle CM" +typedef ^ ParameterType ReKi NacCMzn - - - "Vertical distance from tower-top to nacelle CM" +typedef ^ ParameterType ReKi OverHang - - - "Distance from yaw axis to rotor apex or teeter pin" +typedef ^ ParameterType ReKi ProjArea - - - "Swept area of the rotor projected onto the rotor plane (the plane normal to the low-speed shaft)" +typedef ^ ParameterType ReKi PtfmRefzt - - - "Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point" +typedef ^ ParameterType ReKi RefTwrHt - - - "Vertical distance between FAST's undisplaced tower height (variable TowerHt) and FAST's inertia frame reference point (variable PtfmRef); that is, RefTwrHt = TowerHt - PtfmRefzt" +typedef ^ ParameterType ReKi RFrlPntxn - - - "Downwind distance from tower-top to arbitrary point on rotor-furl axis" +typedef ^ ParameterType ReKi RFrlPntyn - - - "Lateral distance from tower-top to arbitrary point on rotor-furl axis" +typedef ^ ParameterType ReKi RFrlPntzn - - - "Vertical distance from tower-top to arbitrary point on rotor-furl axis" +typedef ^ ParameterType ReKi rVDxn - - - "xn-component of position vector Rvd" +typedef ^ ParameterType ReKi rVDyn - - - "yn-component of position vector rVD" +typedef ^ ParameterType ReKi rVDzn - - - "zn-component of position vector rVD" +typedef ^ ParameterType ReKi rVIMUxn - - - "xn-component of position vector rVIMU" +typedef ^ ParameterType ReKi rVIMUyn - - - "yn-component of position vector rVIMU" +typedef ^ ParameterType ReKi rVIMUzn - - - "zn-component of position vector rVIMU" +typedef ^ ParameterType ReKi rVPxn - - - "xn-component of position vector rVP" +typedef ^ ParameterType ReKi rVPyn - - - "yn-component of position vector rVP" +typedef ^ ParameterType ReKi rVPzn - - - "zn-component of position vector rVP" +typedef ^ ParameterType ReKi rWIxn - - - "xn-component of position vector rWI" +typedef ^ ParameterType ReKi rWIyn - - - "yn-component of position vector rWI" +typedef ^ ParameterType ReKi rWIzn - - - "zn-component of position vector rWI" +typedef ^ ParameterType ReKi rWJxn - - - "xn-component of position vector rWJ" +typedef ^ ParameterType ReKi rWJyn - - - "yn-component of position vector rWJ" +typedef ^ ParameterType ReKi rWJzn - - - "zn-component of position vector rWJ" +typedef ^ ParameterType ReKi rWKxn - - - "xn-component of position vector rWK" +typedef ^ ParameterType ReKi rWKyn - - - "yn-component of position vector rWK" +typedef ^ ParameterType ReKi rWKzn - - - "zn-component of position vector rWK" +typedef ^ ParameterType ReKi rZT0zt - - - "zt-component of position vector rZT0" +typedef ^ ParameterType ReKi rZYzt - - - "zt-component of position vector rZY" +typedef ^ ParameterType R8Ki SinDel3 - - - "Sine of the Delta-3 angle for teetering rotors" +typedef ^ ParameterType R8Ki SinPreC {:} - - "Sines of the precone angles" +typedef ^ ParameterType R8Ki SRFrlSkew - - - "Sine of the rotor-furl axis skew angle" +typedef ^ ParameterType R8Ki SRFrlSkw2 - - - "Sine-squared of the rotor-furl axis skew angle" +typedef ^ ParameterType R8Ki SRFrlTilt - - - "Sine of the rotor-furl axis tilt angle" +typedef ^ ParameterType R8Ki SRFrlTlt2 - - - "Sine-squared of the rotor-furl axis tilt angle" +typedef ^ ParameterType R8Ki SShftSkew - - - "Sine of the shaft skew angle" +typedef ^ ParameterType R8Ki SShftTilt - - - "Sine of the shaft tilt angle" +typedef ^ ParameterType R8Ki STFinBank - - - "Sine of the tail fin planform bank angle" +typedef ^ ParameterType R8Ki STFinSkew - - - "Sine of the tail fin chordline skew angle" +typedef ^ ParameterType R8Ki STFinTilt - - - "Sine of the tail fin chordline tilt angle" +typedef ^ ParameterType R8Ki STFrlSkew - - - "Sine of the tail-furl axis skew angle" +typedef ^ ParameterType R8Ki STFrlSkw2 - - - "Sine-squared of the tail-furl axis skew angle" +typedef ^ ParameterType R8Ki STFrlTilt - - - "Sine of the tail-furl axis tilt angle" +typedef ^ ParameterType R8Ki STFrlTlt2 - - - "Sine-squared of the tail-furl axis tilt angle" +typedef ^ ParameterType ReKi TFrlPntxn - - - "Downwind distance from tower-top to arbitrary point on tail-furl axis" +typedef ^ ParameterType ReKi TFrlPntyn - - - "Lateral distance from tower-top to arbitrary point on tail-furl axis" +typedef ^ ParameterType ReKi TFrlPntzn - - - "Vertical distance from tower-top to arbitrary point on tail-furl axis" +typedef ^ ParameterType ReKi TipRad - - - "Preconed blade-tip radius" +typedef ^ ParameterType ReKi TowerHt - - - "Height of tower above ground level" +typedef ^ ParameterType ReKi TowerBsHt - - - "Height of tower base above ground level [onshore] or MSL [offshore]" meters +typedef ^ ParameterType ReKi UndSling - - - "Undersling length" +typedef ^ ParameterType IntKi NumBl - - - "Number of turbine blades" - +typedef ^ ParameterType ReKi AxRedTFA {:}{:}{:} - - "The axial-reduction terms for the fore-aft tower mode shapes" +typedef ^ ParameterType ReKi AxRedTSS {:}{:}{:} - - "The axial-reduction terms for the side-to-side tower mode shapes" +typedef ^ ParameterType ReKi CTFA {2}{2} - - "Generalized damping of tower in fore-aft direction" +typedef ^ ParameterType ReKi CTSS {2}{2} - - "Generalized damping of tower in side-to-side direction" +typedef ^ ParameterType ReKi DHNodes {:} - - "Length of variable-length tower elements" +typedef ^ ParameterType ReKi HNodes {:} - - "Location of variable-spaced tower nodes (relative to the tower rigid base height" +typedef ^ ParameterType ReKi HNodesNorm {:} - - "Normalized location of variable-spaced tower nodes (relative to the tower rigid base height) (0 < HNodesNorm(:) < 1)" +typedef ^ ParameterType ReKi KTFA {2}{2} - - "Generalized stiffness of tower in fore-aft direction" +typedef ^ ParameterType ReKi KTSS {2}{2} - - "Generalized stiffness of tower in side-to-side direction" +typedef ^ ParameterType ReKi MassT {:} - - "Interpolated lineal mass density of tower" +typedef ^ ParameterType ReKi StiffTSS {:} - - "Interpolated side-side tower stiffness" +typedef ^ ParameterType ReKi TwrFASF {:}{:}{:} - - "Tower fore-aft shape functions" +typedef ^ ParameterType ReKi TwrFlexL - - - "Height / length of the flexible portion of the tower" +typedef ^ ParameterType ReKi TwrSSSF {:}{:}{:} - - "Tower side-to-side shape functions" +typedef ^ ParameterType IntKi TTopNode - - - "Index of the additional node located at the tower-top = TwrNodes + 1" +typedef ^ ParameterType IntKi TwrNodes - - - "Number of tower nodes used in the analysis" +typedef ^ ParameterType ReKi InerTFA {:} - - "Interpolated tower fore-aft (about yt-axis) mass inertia per unit length" +typedef ^ ParameterType ReKi InerTSS {:} - - "Interpolated tower side-to-side (about xt-axis) mass inertia per unit length" +typedef ^ ParameterType ReKi StiffTGJ {:} - - "Interpolated tower torsional stiffness" +typedef ^ ParameterType ReKi StiffTEA {:} - - "Interpolated tower extensional stiffness" +typedef ^ ParameterType ReKi StiffTFA {:} - - "Interpolated fore-aft tower stiffness" +typedef ^ ParameterType ReKi cgOffTFA {:} - - "Interpolated tower fore-aft mass cg offset" +typedef ^ ParameterType ReKi cgOffTSS {:} - - "Interpolated tower side-to-side mass cg offset" +typedef ^ ParameterType ReKi AtfaIner - - - "Inertia of tail boom about the tail-furl axis whose origin is the tail boom center of mass" +typedef ^ ParameterType ReKi BldCG {:} - - "Blade center of mass wrt the blade root" +typedef ^ ParameterType ReKi BldMass {:} - - "Blade masses" +typedef ^ ParameterType ReKi BoomMass - - - "Tail boom mass" +typedef ^ ParameterType ReKi FirstMom {:} - - "First mass moment of inertia of blades wrt the root" +typedef ^ ParameterType ReKi GenIner - - - "Generator inertia about HSS" +typedef ^ ParameterType ReKi Hubg1Iner - - - "Inertia of hub about g1-axis (rotor centerline)" +typedef ^ ParameterType ReKi Hubg2Iner - - - "Inertia of hub about g2-axis (transverse to the cyclinder and passing through its c.g.)" +typedef ^ ParameterType ReKi HubMass - - - "Hub mass" +typedef ^ ParameterType ReKi Nacd2Iner - - - "Inertia of nacelle about the d2-axis whose origin is the nacelle center of mass" +typedef ^ ParameterType ReKi NacMass - - - "Nacelle mass" +typedef ^ ParameterType ReKi PtfmMass - - - "Platform mass" +typedef ^ ParameterType ReKi PtfmPIner - - - "Platform inertia for pitch tilt rotation about the platform CM." +typedef ^ ParameterType ReKi PtfmRIner - - - "Platform inertia for roll tilt rotation about the platform CM." +typedef ^ ParameterType ReKi PtfmYIner - - - "Platform inertia for yaw rotation about the platform CM." +typedef ^ ParameterType ReKi RFrlMass - - - "Rotor-furl mass" +typedef ^ ParameterType ReKi RotIner - - - "Inertia of rotor about its centerline" +typedef ^ ParameterType ReKi RotMass - - - "Rotor mass (blades, tips, and hub)" +typedef ^ ParameterType ReKi RrfaIner - - - "Inertia of structure that furls with the rotor (not including rotor) about the rotor-furl axis whose origin is the center of mass of the structure that furls with the rotor (not including rotor)" +typedef ^ ParameterType ReKi SecondMom {:} - - "Second mass moment of inertia of blades wrt the root" +typedef ^ ParameterType ReKi TFinMass - - - "Tail fin mass" +typedef ^ ParameterType ReKi TFrlIner - - - "Tail boom inertia about tail-furl axis" +typedef ^ ParameterType ReKi TipMass {:} - - "Tip-brake masses" +typedef ^ ParameterType ReKi TurbMass - - - "Mass of turbine (tower + rotor + nacelle)" +typedef ^ ParameterType ReKi TwrMass - - - "Mass of tower" +typedef ^ ParameterType ReKi TwrTpMass - - - "Tower-top mass (rotor + nacelle)" +typedef ^ ParameterType ReKi YawBrMass - - - "Yaw bearing mass" +#typedef ^ ParameterType ReKi AirDens - - - "Air density = RHO" +typedef ^ ParameterType ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ ParameterType ReKi PitchAxis {:}{:} - - "Pitch axis for analysis nodes" - +typedef ^ ParameterType ReKi AeroTwst {:} - - "Aerodynamic twist of the blade at the analysis nodes" +typedef ^ ParameterType ReKi AxRedBld {:}{:}{:}{:} - - "The axial-reduction terms of the blade shape function" +typedef ^ ParameterType ReKi BAlpha {:}{:} - - "Interpolated blade coupling coefficient between flap and twist" +typedef ^ ParameterType ReKi BldEDamp {:}{:} - - "Blade edgewise damping coefficients" +typedef ^ ParameterType ReKi BldFDamp {:}{:} - - "Blade flapwise damping coefficients" +typedef ^ ParameterType ReKi BldFlexL - - - "Flexible blade length" +typedef ^ ParameterType ReKi CAeroTwst {:} - - "Cosine of the aerodynamic twist of the blade at the analysis nodes" +typedef ^ ParameterType ReKi CBE {:}{:}{:} - - "Generalized edgewise damping of the blades" +typedef ^ ParameterType ReKi CBF {:}{:}{:} - - "Generalized flapwise damping of the blades" +typedef ^ ParameterType ReKi cgOffBEdg {:}{:} - - "Interpolated blade edge (along local aerodynamic yb-axis) mass cg offset" +typedef ^ ParameterType ReKi cgOffBFlp {:}{:} - - "Interpolated blade flap (along local aerodynamic xb-axis) mass cg offset" +typedef ^ ParameterType ReKi Chord {:} - - "Chord of the blade at the analysis nodes" +typedef ^ ParameterType R8Ki CThetaS {:}{:} - - "COS( ThetaS )" +typedef ^ ParameterType ReKi DRNodes {:} - - "Length of variable-spaced blade elements" +typedef ^ ParameterType ReKi EAOffBEdg {:}{:} - - "Interpolated blade edge (along local aerodynamic yb-axis) elastic axis offset" +typedef ^ ParameterType ReKi EAOffBFlp {:}{:} - - "Interpolated blade flap (along local aerodynamic xb-axis) elastic axis offset" +typedef ^ ParameterType ReKi FStTunr {:}{:} - - "Blade flapwise modal stiffness tuners (stored for all blades)" +typedef ^ ParameterType ReKi InerBEdg {:}{:} - - "Interpolated blade edge (about local structural xb-axis) mass inertia per unit length" +typedef ^ ParameterType ReKi InerBFlp {:}{:} - - "Interpolated blade flap (about local structural yb-axis) mass inertia per unit length" +typedef ^ ParameterType ReKi KBE {:}{:}{:} - - "Generalized edgewise stiffness of the blades" +typedef ^ ParameterType ReKi KBF {:}{:}{:} - - "Generalized flapwise stiffness of the blades" +typedef ^ ParameterType ReKi MassB {:}{:} - - "Interpolated lineal blade mass density" +typedef ^ ParameterType ReKi RefAxisxb {:}{:} - - "Interpolated Offset for defining the reference axis from the pitch axis for precurved blades at a given input station (along xb-axis)" +typedef ^ ParameterType ReKi RefAxisyb {:}{:} - - "Interpolated Offset for defining the reference axis from the pitch axis for preswept blades at a given input station (along yb-axis)" +typedef ^ ParameterType ReKi RNodes {:} - - "Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL )" +typedef ^ ParameterType ReKi RNodesNorm {:} - - "Normalized radius to analysis nodes relative to hub ( 0 < RNodesNorm(:) < 1 )" +typedef ^ ParameterType ReKi rSAerCenn1 {:}{:} - - "Distance from point S on a blade to the aerodynamic center in the n1 direction (m)" +typedef ^ ParameterType ReKi rSAerCenn2 {:}{:} - - "Distance from point S on a blade to the aerodynamic center in the n2 direction (m)" +typedef ^ ParameterType ReKi SAeroTwst {:} - - "Sine of the aerodynamic twist of the blade at the analysis nodes" +typedef ^ ParameterType ReKi StiffBE {:}{:} - - "Interpolated edgewise blade stiffness" +typedef ^ ParameterType ReKi StiffBEA {:}{:} - - "Interpolated blade extensional stiffness" +typedef ^ ParameterType ReKi StiffBF {:}{:} - - "Interpolated flapwise blade stiffness" +typedef ^ ParameterType ReKi StiffBGJ {:}{:} - - "Interpolated blade torsional stiffness" +typedef ^ ParameterType R8Ki SThetaS {:}{:} - - "SIN( ThetaS )" +typedef ^ ParameterType ReKi ThetaS {:}{:} - - "Structural twist for analysis nodes" radians +typedef ^ ParameterType ReKi TwistedSF {:}{:}{:}{:}{:} - - "Interpolated lineal blade mass density" +typedef ^ ParameterType ReKi BldFl1Sh {:}{:} - - "Blade-flap-mode-1 shape coefficients" +typedef ^ ParameterType ReKi BldFl2Sh {:}{:} - - "Blade-flap-mode-2 shape coefficients" +typedef ^ ParameterType ReKi BldEdgSh {:}{:} - - "Blade-edge-mode shape coefficients" +# parameters from modes (Blade & Tower frequencies) -- these could probably be replaced by local variables (initialization only) +typedef ^ ParameterType ReKi FreqBE {:}{:}{:} - - "Blade edgewise natural frequencies (both w/ and w/o centrifugal stiffening)" +typedef ^ ParameterType ReKi FreqBF {:}{:}{:} - - "Blade flapwise natural frequencies (both w/ and w/o centrifugal stiffening)" +typedef ^ ParameterType ReKi FreqTFA {2}{2} - - "Computed fore-aft tower natural frequencies" +typedef ^ ParameterType ReKi FreqTSS {2}{2} - - "Computed side-to-side tower natural frequencies" +typedef ^ ParameterType ReKi TeetCDmp - - - "Rotor-teeter rate-independent Coulomb-damping" +typedef ^ ParameterType ReKi TeetDmp - - - "Rotor-teeter damping constant" +typedef ^ ParameterType ReKi TeetDmpP - - - "Rotor-teeter damper position" +typedef ^ ParameterType ReKi TeetHSSp - - - "Rotor-teeter hard-stop linear-spring constant" +typedef ^ ParameterType ReKi TeetHStP - - - "Rotor-teeter hard-stop position" +typedef ^ ParameterType ReKi TeetSSSp - - - "Rotor-teeter soft-stop linear-spring constant" +typedef ^ ParameterType ReKi TeetSStP - - - "Rotor-teeter soft-stop position" +typedef ^ ParameterType IntKi TeetMod - - - "Rotor-teeter spring/damper model switch" +typedef ^ ParameterType ReKi TFrlCDmp - - - "Tail-furl rate-independent Coulomb-damping moment" +typedef ^ ParameterType ReKi TFrlDmp - - - "Tail-furl damping constant" +typedef ^ ParameterType ReKi TFrlDSDmp - - - "Tail-furl down-stop damping constant" +typedef ^ ParameterType ReKi TFrlDSDP - - - "Tail-furl down-stop damper position" +typedef ^ ParameterType ReKi TFrlDSSP - - - "Tail-furl down-stop spring position" +typedef ^ ParameterType ReKi TFrlDSSpr - - - "Tail-furl down-stop spring constant" +typedef ^ ParameterType ReKi TFrlSpr - - - "Tail-furl spring constant" +typedef ^ ParameterType ReKi TFrlUSDmp - - - "Tail-furl up-stop damping constant" +typedef ^ ParameterType ReKi TFrlUSDP - - - "Tail-furl up-stop damper position" +typedef ^ ParameterType ReKi TFrlUSSP - - - "Tail-furl up-stop spring position" +typedef ^ ParameterType ReKi TFrlUSSpr - - - "Tail-furl up-stop spring constant" +typedef ^ ParameterType IntKi TFrlMod - - - "Tail-furl spring/damper model switch" +typedef ^ ParameterType ReKi RFrlCDmp - - - "Rotor-furl rate-independent Coulomb-damping moment" +typedef ^ ParameterType ReKi RFrlDmp - - - "Rotor-furl damping constant" +typedef ^ ParameterType ReKi RFrlDSDmp - - - "Rotor-furl down-stop damping constant" +typedef ^ ParameterType ReKi RFrlDSDP - - - "Rotor-furl down-stop damper position" +typedef ^ ParameterType ReKi RFrlDSSP - - - "Rotor-furl down-stop spring position" +typedef ^ ParameterType ReKi RFrlDSSpr - - - "Rotor-furl down-stop spring constant" +typedef ^ ParameterType ReKi RFrlSpr - - - "Rotor-furl spring constant" +typedef ^ ParameterType ReKi RFrlUSDmp - - - "Rotor-furl up-stop damping constant" +typedef ^ ParameterType ReKi RFrlUSDP - - - "Rotor-furl up-stop damper position" +typedef ^ ParameterType ReKi RFrlUSSP - - - "Rotor-furl up-stop spring position" +typedef ^ ParameterType ReKi RFrlUSSpr - - - "Rotor-furl up-stop spring constant" +typedef ^ ParameterType IntKi RFrlMod - - - "Rotor-furl spring/damper model switch" +typedef ^ ParameterType ReKi ShftGagL - - - "Distance from hub or teeter pin to shaft strain gages" +typedef ^ ParameterType IntKi BldGagNd 9 - - "Nodes closest to the blade strain gages" +typedef ^ ParameterType IntKi TwrGagNd 9 - - "Nodes closest to the tower strain gages" +typedef ^ ParameterType DbKi TStart - - - "Time to begin tabular output" +typedef ^ ParameterType ReKi DTTorDmp - - - "Drivetrain torsional damper" +typedef ^ ParameterType ReKi DTTorSpr - - - "Drivetrain torsional spring" +typedef ^ ParameterType ReKi GBRatio - - - "Gearbox ratio" +typedef ^ ParameterType ReKi GBoxEff - - - "Gearbox efficiency" +typedef ^ ParameterType ReKi RotSpeed - - - "Initial or fixed rotor speed" rad/s +typedef ^ ParameterType CHARACTER(1024) RootName - - - "RootName for writing output files" +typedef ^ ParameterType ReKi BElmntMass {:}{:} - - "Mass of the blade elements" +typedef ^ ParameterType ReKi TElmntMass {:} - - "Mass of the tower elements" +typedef ^ ParameterType IntKi method - - - "Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4])" - +typedef ^ ParameterType ReKi PtfmCMxt - - - "Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM" meters +typedef ^ ParameterType ReKi PtfmCMyt - - - "Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM" meters +typedef ^ ParameterType LOGICAL BD4Blades - - - "flag to determine if BeamDyn is computing blade loads (true) or ElastoDyn is (false)" - +typedef ^ ParameterType LOGICAL UseAD14 - - - "flag to determine if AeroDyn14 is being used. Will remove this later when we've replaced AD14." - +# .... ED_AllBlNds option ........................................................................................................ +typedef ^ ParameterType IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (ED_AllBldNdOuts)" - +typedef ^ ParameterType IntKi BldNd_TotNumOuts - - - "Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- ED_AllBldNdOuts)" - +typedef ^ ParameterType OutParmType BldNd_OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +#typedef ^ ParameterType IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (ED_AllBldNdOuts)" - +typedef ^ ParameterType IntKi BldNd_BladesOut - - - "The blades to output (ED_AllBldNdOuts)" - + +typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ParameterType R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" +typedef ^ ParameterType R8Ki dx {:} - - "vector that determines size of perturbation for x (continuous states)" +typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef ^ InputType MeshType BladePtLoads {:} - - "A mesh on each blade, containing aerodynamic forces and moments (formerly AeroBladeForce and AeroBladeMoment)" +typedef ^ InputType MeshType PlatformPtMesh - - - "A mesh at the platform reference (point Z), containing force: surge/xi (1), sway/yi (2), and heave/zi (3)-components; and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components acting at the platform (body X) / platform reference (point Z) associated with everything but the QD2T()s" N +typedef ^ InputType MeshType TowerPtLoads - - - "Tower line2 mesh with forces: surge/xi (1), sway/yi (2), and heave/zi (3)-components of the portion of the tower force at the current tower node (point T); and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components of the portion of the tower moment acting at the current tower node" N/m +typedef ^ InputType MeshType HubPtLoad - - - "A mesh at the teeter pin, containing forces: surge/xi (1), sway/yi (2), and heave/zi (3)-components; and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components acting at the hub. Passed from BeamDyn" +typedef ^ InputType MeshType NacelleLoads - - - "From ServoDyn/TMD: loads on the nacelle." +# Define inputs that are not on a mesh here: +typedef ^ InputType ReKi TwrAddedMass {:}{:}{:} - - "6-by-6 added mass matrix of the tower elements, per unit length-bjj: place on a mesh" "per unit length" +typedef ^ InputType ReKi PtfmAddedMass {6}{6} - - "Platform added mass matrix" "kg, kg-m, kg-m^2" +typedef ^ InputType ReKi BlPitchCom {:} - 2pi "Commanded blade pitch angles" radians +typedef ^ InputType ReKi YawMom - - - "Torque transmitted through the yaw bearing" N-m +typedef ^ InputType ReKi GenTrq - - - "Electrical generator torque" N-m +typedef ^ InputType ReKi HSSBrTrqC - - - "Commanded HSS brake torque" N-m + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType BladeLn2Mesh {:} - - "A mesh on each blade, containing positions and orientations of the blade elements" +typedef ^ OutputType MeshType PlatformPtMesh - - - "Platform reference point positions/orientations/velocities/accelerations" - +typedef ^ OutputType MeshType TowerLn2Mesh - - - "Tower line2 mesh with positions/orientations/velocities/accelerations" - +typedef ^ OutputType MeshType HubPtMotion14 - - - "For AeroDyn v14: motions of the hub" +typedef ^ OutputType MeshType HubPtMotion - - - "For AeroDyn and Lidar(InflowWind): motions of the hub" +typedef ^ OutputType MeshType BladeRootMotion14 - - - "For AeroDyn v14: motions of the blade roots" +typedef ^ OutputType MeshType BladeRootMotion {:} - - "For AeroDyn/BeamDyn: motions at the blade roots" +typedef ^ OutputType MeshType RotorFurlMotion14 - - - "For AeroDyn14: motions of the rotor furl point." +typedef ^ OutputType MeshType NacelleMotion - - - "For AeroDyn14 & ServoDyn/TMD: motions of the nacelle." +typedef ^ OutputType MeshType TowerBaseMotion14 - - - "For AeroDyn 14: motions of the tower base" + +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ OutputType ReKi BlPitch {:} - 2pi "Current blade pitch angles" radians +typedef ^ OutputType ReKi Yaw - - 2pi "Current nacelle yaw" radians +typedef ^ OutputType ReKi YawRate - - - "Current nacelle yaw rate" rad/s +typedef ^ OutputType ReKi LSS_Spd - - - "Low-speed shaft (LSS) speed at entrance to gearbox" rad/s +typedef ^ OutputType ReKi HSS_Spd - - - "High-speed shaft (HSS) speed" rad/s +typedef ^ OutputType ReKi RotSpeed - - - "Rotor azimuth angular speed" rad/s +typedef ^ OutputType ReKi TwrAccel - - - "Tower acceleration for tower feedback control (user routine only)" m/s^2 +typedef ^ OutputType ReKi YawAngle - - 2pi "Yaw angle to be used for yaw error calculations" radians +typedef ^ OutputType ReKi RootMyc 3 - - "Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3)" N-m +typedef ^ OutputType ReKi YawBrTAxp - - - "Tower-top / yaw bearing fore-aft (translational) acceleration (absolute)" m/s^2 +typedef ^ OutputType ReKi YawBrTAyp - - - "Tower-top / yaw bearing side-to-side (translational) acceleration (absolute)" m/s^2 +typedef ^ OutputType ReKi LSSTipPxa - - 2pi "Rotor azimuth angle (position)" radians +typedef ^ OutputType ReKi RootMxc 3 - - "In-plane moment (i.e., the moment caused by in-plane forces) at the blade root" N-m +typedef ^ OutputType ReKi LSSTipMxa - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ OutputType ReKi LSSTipMya - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ OutputType ReKi LSSTipMza - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ OutputType ReKi LSSTipMys - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ OutputType ReKi LSSTipMzs - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ OutputType ReKi YawBrMyn - - - "Rotating (with nacelle) tower-top / yaw bearing pitch moment" N-m +typedef ^ OutputType ReKi YawBrMzn - - - "Tower-top / yaw bearing yaw moment" N-m +typedef ^ OutputType ReKi NcIMURAxs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ OutputType ReKi NcIMURAys - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ OutputType ReKi NcIMURAzs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ OutputType ReKi RotPwr - - - "Rotor power (this is equivalent to the low-speed shaft power)" W diff --git a/OpenFAST/modules/elastodyn/src/ElastoDyn_Types.f90 b/OpenFAST/modules/elastodyn/src/ElastoDyn_Types.f90 new file mode 100644 index 000000000..35338dc22 --- /dev/null +++ b/OpenFAST/modules/elastodyn/src/ElastoDyn_Types.f90 @@ -0,0 +1,25173 @@ +!STARTOFREGISTRYGENERATEDFILE 'ElastoDyn_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 +!********************************************************************************************************************************* +! ElastoDyn_Types +!................................................................................................................................. +! This file is part of ElastoDyn. +! +! 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 ElastoDyn. 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 ElastoDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: ED_NMX = 4 ! Used in updating predictor-corrector values (size of state history) [-] +! ========= ED_InitInputType ======= + TYPE, PUBLIC :: ED_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + CHARACTER(1024) :: ADInputFile !< Name of the AeroDyn input file (in this verison, that is where we'll get the blade mesh info [-] + LOGICAL :: CompElast !< flag to determine if ElastoDyn is computing blade loads (true) or BeamDyn is (false) [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + END TYPE ED_InitInputType +! ======================= +! ========= ED_InitOutputType ======= + TYPE, PUBLIC :: ED_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + INTEGER(IntKi) :: NumBl !< Number of blades on the turbine [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitch !< Initial blade pitch angles [radians] + REAL(ReKi) :: BladeLength !< Blade length (for AeroDyn) [meters] + REAL(ReKi) :: TowerHeight !< Tower Height [meters] + REAL(ReKi) :: TowerBaseHeight !< Tower Base Height [meters] + REAL(ReKi) :: HubHt !< Height of the hub [meters] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldRNodes !< Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL ) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwrHNodes !< Location of variable-spaced tower nodes (relative to the tower rigid base height [-] + REAL(ReKi) , DIMENSION(1:6) :: PlatformPos !< Initial platform position (6 DOFs) [-] + REAL(ReKi) , DIMENSION(1:3) :: TwrBasePos !< initial position of the tower base (for SrvD) [m] + REAL(ReKi) :: HubRad !< Preconed hub radius (distance from the rotor apex to the blade root) [m] + REAL(ReKi) :: RotSpeed !< Initial or fixed rotor speed [rad/s] + LOGICAL :: isFixed_GenDOF !< whether the generator is fixed or free [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + END TYPE ED_InitOutputType +! ======================= +! ========= BladeInputData ======= + TYPE, PUBLIC :: BladeInputData + INTEGER(IntKi) :: NBlInpSt !< Number of blade input stations [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlFract !< Blade fractional radius for distributed input data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PitchAx !< Pitch axis for distributed input data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StrcTwst !< Structural twist for distributed input data [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BMassDen !< Blade mass density for distributed input data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FlpStff !< Blade flap stiffness for distributed input data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EdgStff !< Blade edge stiffness for distributed input data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: GJStff !< Blade torsional stiffness for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EAStff !< Blade extensional stiffness for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Alpha !< Blade coupling coefficient between flap and twist for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FlpIner !< Blade flap (about local structural yb-axis) mass inertia per unit length for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EdgIner !< Blade edge (about local structural xb-axis) mass inertia per unit length for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PrecrvRef !< Offset for defining the reference axis from the pitch axis for precurved blades at a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PreswpRef !< Offset for defining the reference axis from the pitch axis for preswept blades at a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FlpcgOf !< Blade flap (along local aerodynamic xb-axis) mass cg offset for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EdgcgOf !< Blade edge (along local aerodynamic yb-axis) mass cg offset for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FlpEAOf !< Blade flap (along local aerodynamic xb-axis) elastic axis offset for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: EdgEAOf !< Blade edge (along local aerodynamic yb-axis) elastic axis offset for a given input station [-] + REAL(ReKi) , DIMENSION(1:2) :: BldFlDmp !< Blade structural damping ratios in flapwise direction [-] + REAL(ReKi) , DIMENSION(1:1) :: BldEdDmp !< Blade structural damping ratios in edgewise direction [-] + REAL(ReKi) , DIMENSION(1:2) :: FlStTunr !< Blade flapwise modal stiffness tuners (input) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldFl1Sh !< Blade-flap-mode-1 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldFl2Sh !< Blade-flap-mode-2 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldEdgSh !< Blade-edge-mode shape coefficients [-] + END TYPE BladeInputData +! ======================= +! ========= ED_BladeMeshInputData ======= + TYPE, PUBLIC :: ED_BladeMeshInputData + INTEGER(IntKi) :: BldNodes !< Number of blade nodes used for analysis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RNodes !< Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL ) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AeroTwst !< Aerodynamic twist of the blade at the analysis nodes [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Chord !< Chord of the blade at the analysis nodes [-] + END TYPE ED_BladeMeshInputData +! ======================= +! ========= ED_InputFile ======= + TYPE, PUBLIC :: ED_InputFile + REAL(DbKi) :: DT !< Requested integration time for ElastoDyn [seconds] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + LOGICAL :: FlapDOF1 !< First flapwise blade mode DOF [-] + LOGICAL :: FlapDOF2 !< Second flapwise blade mode DOF [-] + LOGICAL :: EdgeDOF !< Edgewise blade mode DOF [-] + LOGICAL :: TeetDOF !< Rotor-teeter DOF [-] + LOGICAL :: DrTrDOF !< Drivetrain rotational-flexibility DOF [-] + LOGICAL :: GenDOF !< Generator DOF [-] + LOGICAL :: YawDOF !< Nacelle-yaw DOF [-] + LOGICAL :: TwFADOF1 !< First tower fore-aft bending-mode DOF [-] + LOGICAL :: TwFADOF2 !< Second tower fore-aft bending-mode DOF [-] + LOGICAL :: TwSSDOF1 !< First tower side-to-side bending-mode DOF [-] + LOGICAL :: TwSSDOF2 !< Second tower side-to-side bending-mode DOF [-] + LOGICAL :: PtfmSgDOF !< Platform horizontal surge translation DOF [-] + LOGICAL :: PtfmSwDOF !< Platform horizontal sway translation DOF [-] + LOGICAL :: PtfmHvDOF !< Platform vertical heave translation DOF [-] + LOGICAL :: PtfmRDOF !< Platform roll tilt rotation DOF [-] + LOGICAL :: PtfmPDOF !< Platform pitch tilt rotation DOF [-] + LOGICAL :: PtfmYDOF !< Platform yaw rotation DOF [-] + REAL(ReKi) :: OoPDefl !< Initial out-of-plane blade-tip displacement [meters] + REAL(ReKi) :: IPDefl !< Initial in-plane blade-tip deflection [meters] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitch !< Initial blade pitch angles [radians] + REAL(ReKi) :: TeetDefl !< Initial teeter angle [radians] + REAL(R8Ki) :: Azimuth !< Initial azimuth angle for blade 1 [radians] + REAL(ReKi) :: RotSpeed !< Initial rotor speed [rad/s] + REAL(ReKi) :: NacYaw !< Initial nacelle-yaw angle [radians] + REAL(ReKi) :: TTDspFA !< Initial fore-aft tower-top displacement [meters] + REAL(ReKi) :: TTDspSS !< Initial side-to-side tower-top displacement [meters] + REAL(ReKi) :: PtfmSurge !< Initial horizontal surge translational displacement of platform [meters] + REAL(ReKi) :: PtfmSway !< Initial horizontal sway translational displacement of platform [meters] + REAL(ReKi) :: PtfmHeave !< Initial vertical heave translational displacement of platform [meters] + REAL(ReKi) :: PtfmRoll !< Initial roll tilt rotational displacement of platform [radians] + REAL(ReKi) :: PtfmPitch !< Initial pitch tilt rotational displacement of platform [radians] + REAL(ReKi) :: PtfmYaw !< Initial yaw rotational displacement of platform [radians] + INTEGER(IntKi) :: NumBl !< Number of blades [-] + REAL(ReKi) :: TipRad !< Preconed blade-tip radius (distance from the rotor apex to the blade tip) [meters] + REAL(ReKi) :: HubRad !< Preconed hub radius (distance from the rotor apex to the blade root) [meters] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PreCone !< Rotor precone angles [radians] + REAL(ReKi) :: HubCM !< Distance from rotor apex to hub mass [meters] + REAL(ReKi) :: UndSling !< Undersling length [meters] + REAL(ReKi) :: Delta3 !< Delta-3 angle for teetering rotors [radians] + REAL(R8Ki) :: AzimB1Up !< Azimuth value to use for I/O when blade 1 points up [radians] + REAL(ReKi) :: OverHang !< Distance from yaw axis to rotor apex or teeter pin [meters] + REAL(ReKi) :: ShftGagL !< Distance from hub or teeter pin to shaft strain gages [meters] + REAL(ReKi) :: ShftTilt !< Rotor shaft tilt angle [radians] + REAL(ReKi) :: NacCMxn !< Downwind distance from tower-top to nacelle CM [meters] + REAL(ReKi) :: NacCMyn !< Lateral distance from tower-top to nacelle CM [meters] + REAL(ReKi) :: NacCMzn !< Vertical distance from tower-top to nacelle CM [meters] + REAL(ReKi) :: NcIMUxn !< Downwind distance from the tower-top to the nacelle IMU [meters] + REAL(ReKi) :: NcIMUyn !< Lateral distance from the tower-top to the nacelle IMU [meters] + REAL(ReKi) :: NcIMUzn !< Vertical distance from the tower-top to the nacelle IMU [meters] + REAL(ReKi) :: Twr2Shft !< Vertical distance from the tower-top to the rotor shaft [meters] + REAL(ReKi) :: TowerHt !< Height of tower above ground level [onshore] or MSL [offshore] [meters] + REAL(ReKi) :: TowerBsHt !< Height of tower base above ground level [onshore] or MSL [offshore] [meters] + REAL(ReKi) :: PtfmCMxt !< Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM [meters] + REAL(ReKi) :: PtfmCMyt !< Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM [meters] + REAL(ReKi) :: PtfmCMzt !< Vertical distance from the ground [onshore] or MSL [offshore] to the platform CM [meters] + REAL(ReKi) :: PtfmRefzt !< Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point [meters] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TipMass !< Tip-brake masses [kg] + REAL(ReKi) :: HubMass !< Hub mass [kg] + REAL(ReKi) :: HubIner !< Hub inertia about teeter axis (2-blader) or rotor axis (3-blader) [kg m^2] + REAL(ReKi) :: GenIner !< Generator inertia about HSS [kg m^2] + REAL(ReKi) :: NacMass !< Nacelle mass [kg] + REAL(ReKi) :: NacYIner !< Nacelle yaw inertia [kg m^2] + REAL(ReKi) :: YawBrMass !< Yaw bearing mass [kg] + REAL(ReKi) :: PtfmMass !< Platform mass [kg] + REAL(ReKi) :: PtfmRIner !< Platform inertia for roll tilt rotation about the platform CM [kg m^2] + REAL(ReKi) :: PtfmPIner !< Platform inertia for pitch tilt rotation about the platform CM [kg m^2] + REAL(ReKi) :: PtfmYIner !< Platform inertia for yaw rotation about the platform CM [kg m^2] + REAL(ReKi) :: BldNodes !< Number of blade nodes (per blade) used for analysis [-] + TYPE(ED_BladeMeshInputData) , DIMENSION(:), ALLOCATABLE :: InpBlMesh !< Input data for blade discretizations (could be on each blade) [see BladeMeshInputData] + TYPE(BladeInputData) , DIMENSION(:), ALLOCATABLE :: InpBl !< Input data for individual blades [see BladeInputData type] + INTEGER(IntKi) :: TeetMod !< Rotor-teeter spring/damper model switch [-] + REAL(ReKi) :: TeetDmpP !< Rotor-teeter damper position [radians] + REAL(ReKi) :: TeetDmp !< Rotor-teeter damping constant [N-m/(rad/s)] + REAL(ReKi) :: TeetCDmp !< Rotor-teeter rate-independent Coulomb-damping [N-m] + REAL(ReKi) :: TeetSStP !< Rotor-teeter soft-stop position [radians] + REAL(ReKi) :: TeetHStP !< Rotor-teeter hard-stop position [radians] + REAL(ReKi) :: TeetSSSp !< Rotor-teeter soft-stop linear-spring constant [N-m/rad] + REAL(ReKi) :: TeetHSSp !< Rotor-teeter hard-stop linear-spring constant [N-m/rad] + REAL(ReKi) :: GBoxEff !< Gearbox efficiency [%] + REAL(ReKi) :: GBRatio !< Gearbox ratio [-] + REAL(ReKi) :: DTTorSpr !< Drivetrain torsional spring [N-m/rad] + REAL(ReKi) :: DTTorDmp !< Drivetrain torsional damper [N-m/(rad/s)] + LOGICAL :: Furling !< Use Additional Furling parameters? [-] + INTEGER(IntKi) :: TwrNodes !< Number of tower nodes used in the analysis [-] + LOGICAL :: SumPrint !< Print summary data to <RootName>.sum [-] + INTEGER(IntKi) :: OutFile !< Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) [-] + LOGICAL :: TabDelim !< Flag to cause tab-delimited text output (delimited by space otherwise) [-] + CHARACTER(20) :: OutFmt !< Format used for module's text tabular output (except time); resulting field should be 10 characters [-] + REAL(DbKi) :: Tstart !< Time to start module's tabular output [seconds] + INTEGER(IntKi) :: DecFact !< Decimation factor for module's tabular output (1=output every step) [-] + INTEGER(IntKi) :: NTwGages !< Number of tower strain gages [-] + INTEGER(IntKi) , DIMENSION(1:9) :: TwrGagNd !< Nodes closest to the tower strain gages [-] + INTEGER(IntKi) :: NBlGages !< Number of blade strain gages [-] + INTEGER(IntKi) , DIMENSION(1:9) :: BldGagNd !< Nodes closest to the blade strain gages [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + INTEGER(IntKi) :: NTwInpSt !< Number of tower input stations [-] + REAL(ReKi) , DIMENSION(1:2) :: TwrFADmp !< Tower fore-aft structural damping ratios [%] + REAL(ReKi) , DIMENSION(1:2) :: TwrSSDmp !< Tower side-to-side structural damping ratios [%] + REAL(ReKi) , DIMENSION(1:2) :: FAStTunr !< Tower fore-aft modal stiffness tuners [-] + REAL(ReKi) , DIMENSION(1:2) :: SSStTunr !< Tower side-to-side modal stiffness tuners [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HtFract !< Fractional height of the flexible portion of tower for a given input station [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TMassDen !< Tower mass density for a given input station [kg/m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwFAStif !< Tower fore-aft stiffness for a given input station [Nm^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwSSStif !< Tower side-to-side stiffness for a given input station [Nm^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwFAM1Sh !< Tower fore-aft mode-1 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwFAM2Sh !< Tower fore-aft mode-2 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwSSM1Sh !< Tower side-to-side mode-1 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwSSM2Sh !< Tower side-to-side mode-2 shape coefficients [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwGJStif !< Tower torsional stiffness for a given input station [Nm^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwEAStif !< Tower extensional stiffness for a given input station [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwFAIner !< Tower fore-aft (about yt-axis) mass inertia per unit length for a given input station [kg m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwSSIner !< Tower side-to-side (about xt-axis) mass inertia per unit length for a given input station [kg m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwFAcgOf !< Tower fore-aft (along the xt-axis) mass cg offset for a given input station [meters] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TwSScgOf !< Tower fore-aft (along the yt-axis) mass cg offset for a given input station [meters] + LOGICAL :: RFrlDOF !< Rotor-furl DOF [-] + LOGICAL :: TFrlDOF !< Tail-furl DOF [-] + REAL(ReKi) :: RotFurl !< Initial or fixed rotor-furl angle [radians] + REAL(ReKi) :: TailFurl !< Initial or fixed tail-furl angle [radians] + REAL(ReKi) :: Yaw2Shft !< Lateral distance from the yaw axis to the rotor shaft [meters] + REAL(ReKi) :: ShftSkew !< Rotor shaft skew angle [radians] + REAL(ReKi) :: RFrlCMxn !< Downwind distance from tower-top to rotor-furl CM [meters] + REAL(ReKi) :: RFrlCMyn !< Lateral distance from tower-top to rotor-furl CM [meters] + REAL(ReKi) :: RFrlCMzn !< Vertical distance from tower-top to rotor-furl CM [meters] + REAL(ReKi) :: BoomCMxn !< Downwind distance from tower-top to tail boom CM [meters] + REAL(ReKi) :: BoomCMyn !< Lateral distance from tower-top to tail boom CM [meters] + REAL(ReKi) :: BoomCMzn !< Vertical distance from tower-top to tail boom CM [meters] + REAL(ReKi) :: TFinCMxn !< Downwind distance from tower-top to tail fin CM [meters] + REAL(ReKi) :: TFinCMyn !< Lateral distance from tower-top to tail fin CM [meters] + REAL(ReKi) :: TFinCMzn !< Vertical distance from tower-top to tail fin CM [meters] + REAL(ReKi) :: TFinCPxn !< Downwind distance from tower-top to tail fin CP [meters] + REAL(ReKi) :: TFinCPyn !< Lateral distance from tower-top to tail fin CP [meters] + REAL(ReKi) :: TFinCPzn !< Vertical distance from tower-top to tail fin CP [meters] + REAL(ReKi) :: TFinSkew !< Tail fin chordline skew angle [radians] + REAL(ReKi) :: TFinTilt !< Tail fin chordline tilt angle [radians] + REAL(ReKi) :: TFinBank !< Tail fin planform bank angle [radians] + REAL(ReKi) :: RFrlPntxn !< Downwind distance from tower-top to arbitrary point on rotor-furl axis [meters] + REAL(ReKi) :: RFrlPntyn !< Lateral distance from tower-top to arbitrary point on rotor-furl axis [meters] + REAL(ReKi) :: RFrlPntzn !< Vertical distance from tower-top to arbitrary point on rotor-furl axis [meters] + REAL(ReKi) :: RFrlSkew !< Rotor-furl axis skew angle [radians] + REAL(ReKi) :: RFrlTilt !< Rotor-furl axis tilt angle [radians] + REAL(ReKi) :: TFrlPntxn !< Downwind distance from tower-top to arbitrary point on tail-furl axis [meters] + REAL(ReKi) :: TFrlPntyn !< Lateral distance from tower-top to arbitrary point on tail-furl axis [meters] + REAL(ReKi) :: TFrlPntzn !< Vertical distance from tower-top to arbitrary point on tail-furl axis [meters] + REAL(ReKi) :: TFrlSkew !< Rotor-furl axis skew angle [radians] + REAL(ReKi) :: TFrlTilt !< Rotor-furl axis tilt angle [radians] + REAL(ReKi) :: RFrlMass !< Rotor-furl mass [kg] + REAL(ReKi) :: BoomMass !< Tail boom mass [kg] + REAL(ReKi) :: TFinMass !< Tail fin mass [kg] + REAL(ReKi) :: RFrlIner !< Rotor-furl inertia about rotor-furl axis [kg m^2] + REAL(ReKi) :: TFrlIner !< Tail boom inertia about tail-furl axis [kg m^2] + INTEGER(IntKi) :: RFrlMod !< Rotor-furl spring/damper model switch [-] + REAL(ReKi) :: RFrlSpr !< Rotor-furl spring constant [N-m/rad] + REAL(ReKi) :: RFrlDmp !< Rotor-furl damping constant [N-m/(rad/s)] + REAL(ReKi) :: RFrlCDmp !< Rotor-furl rate-independent Coulomb-damping moment [N-m] + REAL(ReKi) :: RFrlUSSP !< Rotor-furl up-stop spring position [radians] + REAL(ReKi) :: RFrlDSSP !< Rotor-furl down-stop spring position [radians] + REAL(ReKi) :: RFrlUSSpr !< Rotor-furl up-stop spring constant [N-m/rad] + REAL(ReKi) :: RFrlDSSpr !< Rotor-furl down-stop spring constant [N-m/rad] + REAL(ReKi) :: RFrlUSDP !< Rotor-furl up-stop damper position [radians] + REAL(ReKi) :: RFrlDSDP !< Rotor-furl down-stop damper position [radians] + REAL(ReKi) :: RFrlUSDmp !< Rotor-furl up-stop damping constant [N-m/(rad/s)] + REAL(ReKi) :: RFrlDSDmp !< Rotor-furl down-stop damping constant [N-m/(rad/s)] + INTEGER(IntKi) :: TFrlMod !< Tail-furl spring/damper model switch [-] + REAL(ReKi) :: TFrlSpr !< Tail-furl spring constant [N-m/rad] + REAL(ReKi) :: TFrlDmp !< Tail-furl damping constant [N-m/(rad/s)] + REAL(ReKi) :: TFrlCDmp !< Tail-furl rate-independent Coulomb-damping moment [N-m] + REAL(ReKi) :: TFrlUSSP !< Tail-furl up-stop spring position [radians] + REAL(ReKi) :: TFrlDSSP !< Tail-furl down-stop spring position [radians] + REAL(ReKi) :: TFrlUSSpr !< Tail-furl up-stop spring constant [N-m/rad] + REAL(ReKi) :: TFrlDSSpr !< Tail-furl down-stop spring constant [N-m/rad] + REAL(ReKi) :: TFrlUSDP !< Tail-furl up-stop damper position [radians] + REAL(ReKi) :: TFrlDSDP !< Tail-furl down-stop damper position [radians] + REAL(ReKi) :: TFrlUSDmp !< Tail-furl up-stop damping constant [N-m/(rad/s)] + REAL(ReKi) :: TFrlDSDmp !< Tail-furl down-stop damping constant [N-m/(rad/s)] + INTEGER(IntKi) :: method !< Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4]) [-] + INTEGER(IntKi) :: BldNd_NumOuts !< Number of requested output channels per blade node (ED_AllBldNdOuts) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: BldNd_OutList !< List of user-requested output channels (ED_AllBldNdOuts) [-] + CHARACTER(1024) :: BldNd_BlOutNd_Str !< String to parse for the blade nodes to actually output (ED_AllBldNdOuts) [-] + INTEGER(IntKi) :: BldNd_BladesOut !< The blades to output (ED_AllBldNdOuts) [-] + END TYPE ED_InputFile +! ======================= +! ========= ED_CoordSys ======= + TYPE, PUBLIC :: ED_CoordSys + REAL(R8Ki) , DIMENSION(1:3) :: a1 !< Vector / direction a1 (= xt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: a2 !< Vector / direction a2 (= zt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: a3 !< Vector / direction a3 (= -yt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: b1 !< Vector / direction b1 (= xp from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: b2 !< Vector / direction b2 (= zp from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: b3 !< Vector / direction b3 (= -yp from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: c1 !< Vector / direction c1 (= xs from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: c2 !< Vector / direction c2 (= zs from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: c3 !< Vector / direction c3 (= -ys from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: d1 !< Vector / direction d1 (= xn from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: d2 !< Vector / direction d2 (= zn from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: d3 !< Vector / direction d3 (= -yn from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: e1 !< Vector / direction e1 (= xa from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: e2 !< Vector / direction e2 (= ya from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: e3 !< Vector / direction e3 (= za from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: f1 !< Vector / direction f1 [-] + REAL(R8Ki) , DIMENSION(1:3) :: f2 !< Vector / direction f2 [-] + REAL(R8Ki) , DIMENSION(1:3) :: f3 !< Vector / direction f3 [-] + REAL(R8Ki) , DIMENSION(1:3) :: g1 !< Vector / direction g1 (= xh from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: g2 !< Vector / direction g2 (= yh from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: g3 !< Vector / direction g3 (= zh from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: i1 !< i1(K,:) = vector / direction i1 for blade K (= xcK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: i2 !< i2(K,:) = vector / direction i2 for blade K (= ycK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: i3 !< i3(K,:) = vector / direction i3 for blade K (= zcK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: j1 !< j1(K,:) = vector / direction j1 for blade K (= xbK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: j2 !< j2(K,:) = vector / direction j2 for blade K (= ybK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: j3 !< j3(K,:) = vector / direction j3 for blade K (= zbK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: m1 !< m1(K,J,:) = vector / direction m1 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: m2 !< m2(K,J,:) = vector / direction m2 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: m3 !< m3(K,J,:) = vector / direction m3 for node J of blade K (used to calc. and return aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: n1 !< n1(K,J,:) = vector / direction n1 for node J of blade K (= LxbK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: n2 !< n2(K,J,:) = vector / direction n2 for node J of blade K (= LybK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: n3 !< n3(K,J,:) = vector / direction n3 for node J of blade K (= LzbK from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: p1 !< Vector / direction p1 (used to calc. and return tail aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(1:3) :: p2 !< Vector / direction p2 (used to calc. and return tail aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(1:3) :: p3 !< Vector / direction p3 (used to calc. and return tail aerodynamic loads from AeroDyn) [-] + REAL(R8Ki) , DIMENSION(1:3) :: rf1 !< Vector / direction rf1 (rotor-furl coordinate system = d1 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: rf2 !< Vector / direction rf2 (rotor-furl coordinate system = d2 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: rf3 !< Vector / direction rf3 (rotor-furl coordinate system = d3 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: rfa !< Vector / direction of the rotor-furl axis [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: t1 !< Vector / direction t1 for tower node J (= Lxt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: t2 !< Vector / direction t2 for tower node J (= Lzt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: t3 !< Vector / direction t3 for tower node J (= -Lyt from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: te1 !< te1(K,J,:) = vector / direction te1 for node J of blade K (used to calc. noise) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: te2 !< te2(K,J,:) = vector / direction te2 for node J of blade K (used to calc. noise) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: te3 !< te3(K,J,:) = vector / direction te3 for node J of blade K (used to calc. noise) [-] + REAL(R8Ki) , DIMENSION(1:3) :: tf1 !< Vector / direction tf1 (tail-furl coordinate system = d1 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: tf2 !< Vector / direction tf2 (tail-furl coordinate system = d2 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: tf3 !< Vector / direction tf3 (tail-furl coordinate system = d3 when rotor-furl angle = 0) [-] + REAL(R8Ki) , DIMENSION(1:3) :: tfa !< Vector / direction of the tail-furl axis [-] + REAL(R8Ki) , DIMENSION(1:3) :: z1 !< Vector / direction z1 (= xi from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: z2 !< Vector / direction z2 (= zi from the IEC coord. system) [-] + REAL(R8Ki) , DIMENSION(1:3) :: z3 !< Vector / direction z3 (= -yi from the IEC coord. system) [-] + END TYPE ED_CoordSys +! ======================= +! ========= ED_ActiveDOFs ======= + TYPE, PUBLIC :: ED_ActiveDOFs + INTEGER(IntKi) :: NActvDOF !< The number of active (enabled) DOFs in the model [-] + INTEGER(IntKi) :: NPCE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPDE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPIE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPTE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPTTE !< Number of tower DOFs that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NPSBE !< Number of blade DOFs that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NPSE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPUE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) :: NPYE !< Number of DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PCE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the hub center of mass (point C) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PDE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PIE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PTE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PTTE !< Array of tower DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the tower nodes (point T) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PS !< Array of DOF indices (pointers) to the active (enabled) DOFs/states [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: PSBE !< Array of blade DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: PSE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the blade nodes (point S) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PUE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PYE !< Array of DOF indices (pointers) that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y) in the inertia frame, based on which DOFs are presently enabled [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: SrtPS !< Sorted (from smallest to largest DOF index) version of PS() [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: SrtPSNAUG !< SrtPS() with the additional value of NAUG [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Diag !< Array containing the indices of SrtPS() associated with each enabled DOF; that is, SrtPS(Diag(I)) = I [-] + END TYPE ED_ActiveDOFs +! ======================= +! ========= ED_RtHndSide ======= + TYPE, PUBLIC :: ED_RtHndSide + REAL(R8Ki) , DIMENSION(1:3) :: rO !< Position vector from inertial frame origin to tower-top / base plate (point O) [m] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: rQS !< Position vector from the apex of rotation (point Q) to a point on a blade (point S) [m] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: rS !< Position vector from inertial frame origin to a point on a blade (point S) [m] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: rS0S !< Position vector from the blade root (point S(0)) to a point on a blade (point S) [m] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: rT !< Position vector from inertial frame origin to the current node (point T(HNodes(J)) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rT0O !< Position vector from the tower base (point T(0)) to tower-top / base plate (point O) [m] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: rT0T !< Position vector from a height of TowerBsHt (base of flexible portion of tower) (point T(0)) to a point on the tower (point T) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rZ !< Position vector from inertia frame origin to platform reference (point Z) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rZO !< Position vector from platform reference (point Z) to tower-top / base plate (point O) [m] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: rZT !< Position vector from platform reference (point Z) to a point on a tower (point T) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rPQ !< Position vector from teeter pin (point P) to apex of rotation (point Q) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rP !< Position vector from inertial frame origin to teeter pin (point P) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rV !< Position vector from inertial frame origin to specified point on rotor-furl axis (point V) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rZY !< Position vector from platform reference (point Z) to platform mass center (point Y) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rOU !< Position vector from tower-top / base plate (point O) to nacelle center of mass (point U). [m] + REAL(R8Ki) , DIMENSION(1:3) :: rOV !< Position vector from tower-top / base plate (point O) to specified point on rotor-furl axis (point V) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rVD !< Position vector from specified point on rotor-furl axis (point V) to center of mass of structure that furls with the rotor (not including rotor) (point D) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rOW !< Position vector from tower-top / base plate (point O) to specified point on tail-furl axis (point W) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rPC !< Position vector from teeter pin (point P) to hub center of mass (point C) [m] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: rPS0 !< Position vector from teeter pin (point P) to blade root (point S(0)) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rQ !< Position vector from inertial frame origin to apex of rotation (point Q) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rQC !< Position vector from apex of rotation (point Q) to hub center of mass (point C) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rVIMU !< Position vector from specified point on rotor-furl axis (point V) to nacelle IMU (point IMU) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rVP !< Position vector from specified point on rotor-furl axis (point V) to teeter pin (point P) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rWI !< Position vector from specified point on tail-furl axis (point W) to tail boom center of mass (point I) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rWJ !< Position vector from specified point on tail-furl axis (point W) to tail fin center of mass (point J) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rWK !< Position vector from specified point on tail-furl axis (point W) to tail fin center of pressure (point K) [m] + REAL(R8Ki) , DIMENSION(1:3) :: rZT0 !< Position vector from platform reference (point Z) to tower base (point T(0)) [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AngPosEF !< Angular position of the current point on the tower (body F) in the inertial frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AngPosXF !< Angular position of the current point on the tower (body F) in the platform (body X) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AngPosHM !< Angular position of eleMent J of blade K (body M) in the hub (body H) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngPosXB !< Angular position of the base plate (body B) in the platform (body X) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngPosEX !< Angular position of the platform (body X) in the inertial frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEA !< Partial angular velocity (and its 1st time derivative) of the tail (body A) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: PAngVelEF !< Partial angular velocity (and its 1st time derivative) of tower element J (body F) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEG !< Partial angular velocity (and its 1st time derivative) of the generator (body G) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEH !< Partial angular velocity (and its 1st time derivative) of the hub (body H) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEL !< Partial angular velocity (and its 1st time derivative) of the low-speed shaft (body L) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: PAngVelEM !< Partial angular velocity (and its 1st time derivative) of eleMent J of blade K (body M) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AngVelEM !< Angular velocity of of eleMent J of blade K (body M) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEN !< Partial angular velocity (and its 1st time derivative) of the nacelle (body N) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEA !< Angular velocity of the tail (body A) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEB !< Partial angular velocity (and its 1st time derivative) of the base plate (body B) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelER !< Partial angular velocity (and its 1st time derivative) of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PAngVelEX !< Partial angular velocity (and its 1st time derivative) of the platform (body B) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEG !< Angular velocity of the generator (body G) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEH !< Angular velocity of the hub (body H) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEL !< Angular velocity of the low-speed shaft (body L) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEN !< Angular velocity of the nacelle (body N) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEB !< Angular velocity of the base plate (body B) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelER !< Angular velocity of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngVelEX !< Angular velocity of the platform (body X) in the inertia frame (body E for earth) [-] + REAL(R8Ki) :: TeetAngVel !< Angular velocity of the teeter motion [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccEBt !< Portion of the angular acceleration of the base plate (body B) in the inertia frame (body E for earth) associated with everything but the QD2T()s [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccERt !< Portion of the angular acceleration of the structure that furls with the rotor (not including rotor) (body R) in the inertia frame (body E for earth) associated with everything but the QD2T()s [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccEXt !< Portion of the angular acceleration of the platform (body X) in the inertia frame (body E for earth) associated with everything but the QD2T()s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AngAccEFt !< Portion of the angular acceleration of tower element J (body F) in the inertia frame (body E for earth) associated with everything but the QD2T()s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AngVelEF !< Angular velocity of the current point on the tower (body F) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccEAt !< Portion of the angular acceleration of the tail (body A) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccEGt !< Portion of the angular acceleration of the generator (body G) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccEHt !< Portion of the angular acceleration of the hub (body H) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: AngAccENt !< Portion of the angular acceleration of the nacelle (body N) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccECt !< Portion of the linear acceleration of the hub center of mass (point C) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEDt !< Portion of the linear acceleration of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEIt !< Portion of the linear acceleration of the tail boom center of mass (point I) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEJt !< Portion of the linear acceleration of the tail fin center of mass (point J) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEUt !< Portion of the linear acceleration of the nacelle center of mass (point U) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEYt !< Portion of the linear acceleration of the platform center of mass (point Y) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: LinVelES !< Linear velocity of current point on the current blade (point S) in the inertia frame [-] + REAL(ReKi) , DIMENSION(1:3) :: LinVelEQ !< Linear velocity of of the apex of rotation (point Q) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: LinVelET !< Linear velocity of current point on the tower (point T) in the inertia frame [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LinVelESm2 !< The m2-component (closest to tip) of LinVelES [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEIMU !< Partial linear velocity (and its 1st time derivative) of the nacelle IMU (point IMU) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEO !< Partial linear velocity (and its 1st time derivative) of the base plate (point O) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: PLinVelES !< Partial linear velocity (and its 1st time derivative) of a point on a blade (point S) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: PLinVelET !< Partial linear velocity (and its 1st time derivative) of a point on the tower (point T) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEZ !< Partial linear velocity (and its 1st time derivative) of the platform reference point (point Z) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEC !< Partial linear velocity (and its 1st time derivative) of the hub center of mass (point C) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelED !< Partial linear velocity (and its 1st time derivative) of the center of mass of the structure that furls with the rotor (not including rotor) (point D) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEI !< Partial linear velocity (and its 1st time derivative) of the tail boom center of mass (point I) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEJ !< Partial linear velocity (and its 1st time derivative) of the tail fin center of mass (point J) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEK !< Partial linear velocity (and its 1st time derivative) of the tail fin center of pressure(point K) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEP !< Partial linear velocity (and its 1st time derivative) of the teeter pin (point P) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEQ !< Partial linear velocity (and its 1st time derivative) of the apex of rotation (point Q) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEU !< Partial linear velocity (and its 1st time derivative) of the nacelle center of mass (point U) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEV !< Partial linear velocity (and its 1st time derivative) of the selected point on the rotor-furl axis (point V) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEW !< Partial linear velocity (and its 1st time derivative) of the selected point on the tail-furl axis (point W) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PLinVelEY !< Partial linear velocity (and its 1st time derivative) of the platform mass center (point Y) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEIMUt !< Portion of the linear acceleration of the nacelle IMU (point IMU) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEOt !< Portion of the linear acceleration of the base plate (point O) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: LinAccESt !< Portion of the linear acceleration of a point on a blade (point S) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: LinAccETt !< Portion of the linear acceleration of a point on the tower (point T) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinAccEZt !< Portion of the linear acceleration of the platform reference (point Z) in the inertia frame (body E for earth) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: LinVelEIMU !< Linear velocity of the nacelle IMU (point IMU) in the inertia frame [-] + REAL(ReKi) , DIMENSION(1:3) :: LinVelEZ !< Linear velocity of platform reference (point Z) in the inertia frame [-] + REAL(ReKi) , DIMENSION(1:3) :: LinVelEO !< Linear velocity of the base plate (point O) in the inertia frame (body E for earth) [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcONcRtt !< Portion of the force at yaw bearing (point O) due to the nacelle, generator, and rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcPRott !< Portion of the force at the teeter pin (point P) due to the rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FrcS0Bt !< Portion of the force at the blade root (point S(0)) due to the blade associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcT0Trbt !< Portion of the force at tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: FSAero !< The aerodynamic force per unit span acting on a blade at point S [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FSTipDrag !< The aerodynamic force at a blade tip resulting from tip drag [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FTHydrot !< Portion of the hydrodynamic force (& all other external forces, including aerodynamic) per unit length acting on the tower at point T associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: FZHydrot !< Portion of the platform hydrodynamic force at the platform reference (point Z) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MFHydrot !< Portion of the hydrodynamic moment (and all other external moments, including aerodynamic) per unit length acting on a tower element (body F) at point T associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomBNcRtt !< Portion of the moment at the base plate (body B) / yaw bearing (point O) due to the nacelle, generator, and rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MomH0Bt !< Portion of the moment at the hub (body H) / blade root (point S(0)) due to the blade associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomLPRott !< Portion of the moment at the teeter pin (point P) on the low-speed shaft (body L) due to the rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomNGnRtt !< Portion of the moment at the nacelle (body N) / selected point on rotor-furl axis (point V) due the structure that furls with the rotor, generator, and rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomNTailt !< Portion of the moment at the nacelle (body N) / selected point on tail-furl axis (point W) due the tail associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomX0Trbt !< Portion of the moment at the platform (body X) / tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: MMAero !< The aerodynamic moment per unit span acting on a blade at point S [-] + REAL(ReKi) , DIMENSION(1:3) :: MXHydrot !< Portion of the platform hydrodynamic moment acting at the platform (body X) / platform reference (point Z) associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcONcRt !< Partial force at the yaw bearing (point O) due to the nacelle, generator, and rotor [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcPRot !< Partial force at the teeter pin (point P) due to the rotor [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PFrcS0B !< Partial force at the blade root (point S(0)) due to the blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcT0Trb !< Partial force at the tower base (point T(0)) due to the turbine [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PFTHydro !< Partial hydrodynamic force per unit length acting on the tower at point T [-] + REAL(ReKi) , DIMENSION(1:6,1:3) :: PFZHydro !< Partial platform hydrodynamic force at the platform reference (point Z) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PMFHydro !< Partial hydrodynamic moment per unit length acting on a tower element (body F) at point T [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomBNcRt !< Partial moment at the base plate (body B) / yaw bearing (point O) due the nacelle, generator, and rotor [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: PMomH0B !< Partial moment at the hub (body H) / blade root (point S(0)) due to the blade [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomLPRot !< Partial moment at the teeter pin (point P) on the low-speed shaft (body L) due to the rotor [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomNGnRt !< Partial moment at the nacelle (body N) / selected point on rotor-furl axis (point V) due the structure that furls with the rotor, generator, and rotor [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomNTail !< Partial moment at the nacelle (body N) / selected point on tail-furl axis (point W) due the tail [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomX0Trb !< Partial moment at the platform (body X) / tower base (point T(0)) due to the turbine [-] + REAL(ReKi) , DIMENSION(1:6,1:3) :: PMXHydro !< Partial platform hydrodynamic moment at the platform (body X) / platform reference (point Z) [-] + REAL(R8Ki) :: TeetAng !< Current teeter angle = QT(DOF_Teet) for 2-blader or 0 for 3-blader (this is used in place of QT(DOF_Teet) throughout RtHS() [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcVGnRtt !< Portion of the force at the rotor-furl axis (point V) due to the structure that furls with the rotor, generator, and rotor associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcWTailt !< Portion of the force at the tail-furl axis (point W) due to the tail associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: FrcZAllt !< Portion of the force at platform reference (point Z) due to everything associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(1:3) :: MomXAllt !< Portion of the moment at the platform (body X) / platform reference (point Z) due to everything associated with everything but the QD2T()'s [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcVGnRt !< Partial force at the rotor-furl axis (point V) due to the structure that furls with the rotor, generator, and rotor [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcWTail !< Partial force at the tail-furl axis (point W) due to the tail [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PFrcZAll !< Partial force at the platform reference (point Z) due to everything [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PMomXAll !< Partial moment at the platform (body X) / platform reference (point Z) due to the everything [-] + REAL(ReKi) :: TeetMom !< The total moment supplied by the stop, spring, and damper of the teeter mechanism [-] + REAL(ReKi) :: TFrlMom !< The total tail-furl spring and damper moment [-] + REAL(ReKi) :: RFrlMom !< The total rotor-furl spring and damper moment [-] + REAL(ReKi) :: GBoxEffFac !< The factor used to apply the gearbox efficiency effects to the equation associated with the generator DOF [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: rSAerCen !< aerodynamic pitching moment arm (i.e., the position vector from point S on the blade to the aerodynamic center of the element) [-] + END TYPE ED_RtHndSide +! ======================= +! ========= ED_ContinuousStateType ======= + TYPE, PUBLIC :: ED_ContinuousStateType + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QT !< Current estimate of Q (displacement matrix) for each degree of freedom [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QDT !< Current estimate of QD (velocity matrix) for each degree of freedom [-] + END TYPE ED_ContinuousStateType +! ======================= +! ========= ED_DiscreteStateType ======= + TYPE, PUBLIC :: ED_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE ED_DiscreteStateType +! ======================= +! ========= ED_ConstraintStateType ======= + TYPE, PUBLIC :: ED_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE ED_ConstraintStateType +! ======================= +! ========= ED_OtherStateType ======= + TYPE, PUBLIC :: ED_OtherStateType + INTEGER(IntKi) :: n !< tracks time step for which OtherState was updated [-] + TYPE(ED_ContinuousStateType) , DIMENSION(ED_NMX) :: xdot !< previous state deriv for multi-step [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IC !< Array which stores pointers to predictor-corrector results [-] + REAL(ReKi) :: HSSBrTrq !< HSSBrTrq from update states; a hack to get this working with a single integrator [-] + REAL(ReKi) :: HSSBrTrqC !< Commanded HSS brake torque (adjusted for sign) [N-m] + INTEGER(IntKi) :: SgnPrvLSTQ !< The sign of the low-speed shaft torque from the previous call to RtHS(). This is calculated at the end of RtHS(). NOTE: The low-speed shaft torque is assumed to be positive at the beginning of the run! [-] + INTEGER(IntKi) , DIMENSION(ED_NMX) :: SgnLSTQ !< history of sign of LSTQ [-] + END TYPE ED_OtherStateType +! ======================= +! ========= ED_MiscVarType ======= + TYPE, PUBLIC :: ED_MiscVarType + TYPE(ED_CoordSys) :: CoordSys !< Coordinate systems in the FAST framework [-] + TYPE(ED_RtHndSide) :: RtHS !< Values used in calculating the right-hand-side RtHS (and outputs) [-] + 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(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: AugMat !< The augmented matrix used for the solution of the QD2T()s [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: AugMat_factor !< factored version of AugMat matrix [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: SolnVec !< b in the equation Ax=b (last column of AugMat) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AugMat_pivot !< Pivot column for AugMat in LAPACK factorization [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OgnlGeAzRo !< Original DOF_GeAz row in AugMat [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QD2T !< Solution (acceleration) vector; the first time derivative of QDT [-] + LOGICAL :: IgnoreMod !< whether to ignore the modulo in ED outputs (necessary for linearization perturbations) [-] + END TYPE ED_MiscVarType +! ======================= +! ========= ED_ParameterType ======= + TYPE, PUBLIC :: ED_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + REAL(DbKi) :: DT24 !< =DT/24 (used in loose coupling) [seconds] + INTEGER(IntKi) :: BldNodes !< Number of blade nodes used in the analysis [-] + INTEGER(IntKi) :: TipNode !< Index of the additional node located at the blade tip = BldNodes + 1 [-] + INTEGER(IntKi) :: NDOF !< Number of total degrees of freedom (DOFs) [-] + REAL(R8Ki) :: TwoPiNB !< Two pi divided by the number of blades [radians] + INTEGER(IntKi) :: NAug !< Dimension of augmented solution matrix [-] + INTEGER(IntKi) :: NPH !< Number of DOFs that contribute to the angular velocity of the hub (body H) in the inertia frame [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: PH !< Array of DOF indices (pointers) that contribute to the angular velocity of the hub (body H) in the inertia frame [-] + INTEGER(IntKi) :: NPM !< Number of DOFs that contribute to the angular velocity of the blade elements (body M) in the inertia frame [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: PM !< Array of DOF indices (pointers) that contribute to the angular velocity of the blade elements (body M) in the inertia frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: DOF_Flag !< Array which stores values of the feature flags for each DOF [-] + CHARACTER(99) , DIMENSION(:), ALLOCATABLE :: DOF_Desc !< Array which stores descriptions of each DOF [-] + TYPE(ED_ActiveDOFs) :: DOFs !< Active degrees of freedom in the model [-] + INTEGER(IntKi) :: NumOuts = 0 !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(20) :: OutFmt !< Output format for tabular data [-] + INTEGER(IntKi) :: NBlGages = 0 !< Number of blade strain gages [-] + INTEGER(IntKi) :: NTwGages = 0 !< Number of tower strain gages [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + REAL(ReKi) :: AvgNrmTpRd !< Average tip radius normal to the shaft [meters] + REAL(R8Ki) :: AzimB1Up !< Azimuth value to use for I/O when blade 1 points up [radians] + REAL(R8Ki) :: CosDel3 = 1.0 !< Cosine of the Delta-3 angle for teetering rotors [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: CosPreC !< Cosines of the precone angles [-] + REAL(R8Ki) :: CRFrlSkew !< Cosine of the rotor-furl axis skew angle [-] + REAL(R8Ki) :: CRFrlSkw2 !< Cosine-squared of the rotor-furl axis skew angle [-] + REAL(R8Ki) :: CRFrlTilt !< Cosine of the rotor-furl axis tilt angle [-] + REAL(R8Ki) :: CRFrlTlt2 !< Cosine-squared of the rotor-furl axis tilt angle [-] + REAL(R8Ki) :: CShftSkew !< Cosine of the shaft skew angle [-] + REAL(R8Ki) :: CShftTilt !< Cosine of the shaft tilt angle [-] + REAL(R8Ki) :: CSRFrlSkw !< Cosine*Sine of the rotor-furl axis skew angle [-] + REAL(R8Ki) :: CSRFrlTlt !< Cosine*Sine of the rotor-furl axis tilt angle [-] + REAL(R8Ki) :: CSTFrlSkw !< Cosine*Sine of the tail-furl axis skew angle [-] + REAL(R8Ki) :: CSTFrlTlt !< Cosine*Sine of the tail-furl axis tilt angle [-] + REAL(R8Ki) :: CTFinBank !< Cosine of the tail fin planform bank angle [-] + REAL(R8Ki) :: CTFinSkew !< Cosine of the tail fin chordline skew angle [-] + REAL(R8Ki) :: CTFinTilt !< Cosine of the tail fin chordline tilt angle [-] + REAL(R8Ki) :: CTFrlSkew !< Cosine of the tail-furl axis skew angle [-] + REAL(R8Ki) :: CTFrlSkw2 !< Cosine-squared of the tail-furl axis skew angle [-] + REAL(R8Ki) :: CTFrlTilt !< Cosine of the tail-furl axis tilt angle [-] + REAL(R8Ki) :: CTFrlTlt2 !< Cosine-squared of the tail-furl axis tilt angle [-] + REAL(ReKi) :: HubHt !< Hub-height as computed using FAST inputs [= TowerHt + Twr2Shft + OverHang*SIN( ShftTilt ) ] (was FASTHH) [-] + REAL(ReKi) :: HubCM !< Distance from rotor apex to hub mass [-] + REAL(ReKi) :: HubRad !< Preconed hub radius [-] + REAL(ReKi) :: NacCMxn !< Downwind distance from tower-top to nacelle CM [-] + REAL(ReKi) :: NacCMyn !< Lateral distance from tower-top to nacelle CM [-] + REAL(ReKi) :: NacCMzn !< Vertical distance from tower-top to nacelle CM [-] + REAL(ReKi) :: OverHang !< Distance from yaw axis to rotor apex or teeter pin [-] + REAL(ReKi) :: ProjArea !< Swept area of the rotor projected onto the rotor plane (the plane normal to the low-speed shaft) [-] + REAL(ReKi) :: PtfmRefzt !< Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point [-] + REAL(ReKi) :: RefTwrHt !< Vertical distance between FAST's undisplaced tower height (variable TowerHt) and FAST's inertia frame reference point (variable PtfmRef); that is, RefTwrHt = TowerHt - PtfmRefzt [-] + REAL(ReKi) :: RFrlPntxn !< Downwind distance from tower-top to arbitrary point on rotor-furl axis [-] + REAL(ReKi) :: RFrlPntyn !< Lateral distance from tower-top to arbitrary point on rotor-furl axis [-] + REAL(ReKi) :: RFrlPntzn !< Vertical distance from tower-top to arbitrary point on rotor-furl axis [-] + REAL(ReKi) :: rVDxn !< xn-component of position vector Rvd [-] + REAL(ReKi) :: rVDyn !< yn-component of position vector rVD [-] + REAL(ReKi) :: rVDzn !< zn-component of position vector rVD [-] + REAL(ReKi) :: rVIMUxn !< xn-component of position vector rVIMU [-] + REAL(ReKi) :: rVIMUyn !< yn-component of position vector rVIMU [-] + REAL(ReKi) :: rVIMUzn !< zn-component of position vector rVIMU [-] + REAL(ReKi) :: rVPxn !< xn-component of position vector rVP [-] + REAL(ReKi) :: rVPyn !< yn-component of position vector rVP [-] + REAL(ReKi) :: rVPzn !< zn-component of position vector rVP [-] + REAL(ReKi) :: rWIxn !< xn-component of position vector rWI [-] + REAL(ReKi) :: rWIyn !< yn-component of position vector rWI [-] + REAL(ReKi) :: rWIzn !< zn-component of position vector rWI [-] + REAL(ReKi) :: rWJxn !< xn-component of position vector rWJ [-] + REAL(ReKi) :: rWJyn !< yn-component of position vector rWJ [-] + REAL(ReKi) :: rWJzn !< zn-component of position vector rWJ [-] + REAL(ReKi) :: rWKxn !< xn-component of position vector rWK [-] + REAL(ReKi) :: rWKyn !< yn-component of position vector rWK [-] + REAL(ReKi) :: rWKzn !< zn-component of position vector rWK [-] + REAL(ReKi) :: rZT0zt !< zt-component of position vector rZT0 [-] + REAL(ReKi) :: rZYzt !< zt-component of position vector rZY [-] + REAL(R8Ki) :: SinDel3 !< Sine of the Delta-3 angle for teetering rotors [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: SinPreC !< Sines of the precone angles [-] + REAL(R8Ki) :: SRFrlSkew !< Sine of the rotor-furl axis skew angle [-] + REAL(R8Ki) :: SRFrlSkw2 !< Sine-squared of the rotor-furl axis skew angle [-] + REAL(R8Ki) :: SRFrlTilt !< Sine of the rotor-furl axis tilt angle [-] + REAL(R8Ki) :: SRFrlTlt2 !< Sine-squared of the rotor-furl axis tilt angle [-] + REAL(R8Ki) :: SShftSkew !< Sine of the shaft skew angle [-] + REAL(R8Ki) :: SShftTilt !< Sine of the shaft tilt angle [-] + REAL(R8Ki) :: STFinBank !< Sine of the tail fin planform bank angle [-] + REAL(R8Ki) :: STFinSkew !< Sine of the tail fin chordline skew angle [-] + REAL(R8Ki) :: STFinTilt !< Sine of the tail fin chordline tilt angle [-] + REAL(R8Ki) :: STFrlSkew !< Sine of the tail-furl axis skew angle [-] + REAL(R8Ki) :: STFrlSkw2 !< Sine-squared of the tail-furl axis skew angle [-] + REAL(R8Ki) :: STFrlTilt !< Sine of the tail-furl axis tilt angle [-] + REAL(R8Ki) :: STFrlTlt2 !< Sine-squared of the tail-furl axis tilt angle [-] + REAL(ReKi) :: TFrlPntxn !< Downwind distance from tower-top to arbitrary point on tail-furl axis [-] + REAL(ReKi) :: TFrlPntyn !< Lateral distance from tower-top to arbitrary point on tail-furl axis [-] + REAL(ReKi) :: TFrlPntzn !< Vertical distance from tower-top to arbitrary point on tail-furl axis [-] + REAL(ReKi) :: TipRad !< Preconed blade-tip radius [-] + REAL(ReKi) :: TowerHt !< Height of tower above ground level [-] + REAL(ReKi) :: TowerBsHt !< Height of tower base above ground level [onshore] or MSL [offshore] [meters] + REAL(ReKi) :: UndSling !< Undersling length [-] + INTEGER(IntKi) :: NumBl !< Number of turbine blades [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AxRedTFA !< The axial-reduction terms for the fore-aft tower mode shapes [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AxRedTSS !< The axial-reduction terms for the side-to-side tower mode shapes [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: CTFA !< Generalized damping of tower in fore-aft direction [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: CTSS !< Generalized damping of tower in side-to-side direction [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DHNodes !< Length of variable-length tower elements [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HNodes !< Location of variable-spaced tower nodes (relative to the tower rigid base height [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HNodesNorm !< Normalized location of variable-spaced tower nodes (relative to the tower rigid base height) (0 < HNodesNorm(:) < 1) [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: KTFA !< Generalized stiffness of tower in fore-aft direction [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: KTSS !< Generalized stiffness of tower in side-to-side direction [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: MassT !< Interpolated lineal mass density of tower [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StiffTSS !< Interpolated side-side tower stiffness [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: TwrFASF !< Tower fore-aft shape functions [-] + REAL(ReKi) :: TwrFlexL !< Height / length of the flexible portion of the tower [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: TwrSSSF !< Tower side-to-side shape functions [-] + INTEGER(IntKi) :: TTopNode !< Index of the additional node located at the tower-top = TwrNodes + 1 [-] + INTEGER(IntKi) :: TwrNodes !< Number of tower nodes used in the analysis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: InerTFA !< Interpolated tower fore-aft (about yt-axis) mass inertia per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: InerTSS !< Interpolated tower side-to-side (about xt-axis) mass inertia per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StiffTGJ !< Interpolated tower torsional stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StiffTEA !< Interpolated tower extensional stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StiffTFA !< Interpolated fore-aft tower stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: cgOffTFA !< Interpolated tower fore-aft mass cg offset [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: cgOffTSS !< Interpolated tower side-to-side mass cg offset [-] + REAL(ReKi) :: AtfaIner !< Inertia of tail boom about the tail-furl axis whose origin is the tail boom center of mass [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldCG !< Blade center of mass wrt the blade root [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BldMass !< Blade masses [-] + REAL(ReKi) :: BoomMass !< Tail boom mass [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FirstMom !< First mass moment of inertia of blades wrt the root [-] + REAL(ReKi) :: GenIner !< Generator inertia about HSS [-] + REAL(ReKi) :: Hubg1Iner !< Inertia of hub about g1-axis (rotor centerline) [-] + REAL(ReKi) :: Hubg2Iner !< Inertia of hub about g2-axis (transverse to the cyclinder and passing through its c.g.) [-] + REAL(ReKi) :: HubMass !< Hub mass [-] + REAL(ReKi) :: Nacd2Iner !< Inertia of nacelle about the d2-axis whose origin is the nacelle center of mass [-] + REAL(ReKi) :: NacMass !< Nacelle mass [-] + REAL(ReKi) :: PtfmMass !< Platform mass [-] + REAL(ReKi) :: PtfmPIner !< Platform inertia for pitch tilt rotation about the platform CM. [-] + REAL(ReKi) :: PtfmRIner !< Platform inertia for roll tilt rotation about the platform CM. [-] + REAL(ReKi) :: PtfmYIner !< Platform inertia for yaw rotation about the platform CM. [-] + REAL(ReKi) :: RFrlMass !< Rotor-furl mass [-] + REAL(ReKi) :: RotIner !< Inertia of rotor about its centerline [-] + REAL(ReKi) :: RotMass !< Rotor mass (blades, tips, and hub) [-] + REAL(ReKi) :: RrfaIner !< Inertia of structure that furls with the rotor (not including rotor) about the rotor-furl axis whose origin is the center of mass of the structure that furls with the rotor (not including rotor) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SecondMom !< Second mass moment of inertia of blades wrt the root [-] + REAL(ReKi) :: TFinMass !< Tail fin mass [-] + REAL(ReKi) :: TFrlIner !< Tail boom inertia about tail-furl axis [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TipMass !< Tip-brake masses [-] + REAL(ReKi) :: TurbMass !< Mass of turbine (tower + rotor + nacelle) [-] + REAL(ReKi) :: TwrMass !< Mass of tower [-] + REAL(ReKi) :: TwrTpMass !< Tower-top mass (rotor + nacelle) [-] + REAL(ReKi) :: YawBrMass !< Yaw bearing mass [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PitchAxis !< Pitch axis for analysis nodes [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AeroTwst !< Aerodynamic twist of the blade at the analysis nodes [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: AxRedBld !< The axial-reduction terms of the blade shape function [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BAlpha !< Interpolated blade coupling coefficient between flap and twist [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BldEDamp !< Blade edgewise damping coefficients [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BldFDamp !< Blade flapwise damping coefficients [-] + REAL(ReKi) :: BldFlexL !< Flexible blade length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CAeroTwst !< Cosine of the aerodynamic twist of the blade at the analysis nodes [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CBE !< Generalized edgewise damping of the blades [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: CBF !< Generalized flapwise damping of the blades [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: cgOffBEdg !< Interpolated blade edge (along local aerodynamic yb-axis) mass cg offset [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: cgOffBFlp !< Interpolated blade flap (along local aerodynamic xb-axis) mass cg offset [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Chord !< Chord of the blade at the analysis nodes [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: CThetaS !< COS( ThetaS ) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DRNodes !< Length of variable-spaced blade elements [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: EAOffBEdg !< Interpolated blade edge (along local aerodynamic yb-axis) elastic axis offset [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: EAOffBFlp !< Interpolated blade flap (along local aerodynamic xb-axis) elastic axis offset [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FStTunr !< Blade flapwise modal stiffness tuners (stored for all blades) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: InerBEdg !< Interpolated blade edge (about local structural xb-axis) mass inertia per unit length [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: InerBFlp !< Interpolated blade flap (about local structural yb-axis) mass inertia per unit length [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: KBE !< Generalized edgewise stiffness of the blades [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: KBF !< Generalized flapwise stiffness of the blades [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MassB !< Interpolated lineal blade mass density [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: RefAxisxb !< Interpolated Offset for defining the reference axis from the pitch axis for precurved blades at a given input station (along xb-axis) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: RefAxisyb !< Interpolated Offset for defining the reference axis from the pitch axis for preswept blades at a given input station (along yb-axis) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RNodes !< Radius to analysis nodes relative to hub ( 0 < RNodes(:) < BldFlexL ) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RNodesNorm !< Normalized radius to analysis nodes relative to hub ( 0 < RNodesNorm(:) < 1 ) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rSAerCenn1 !< Distance from point S on a blade to the aerodynamic center in the n1 direction (m) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rSAerCenn2 !< Distance from point S on a blade to the aerodynamic center in the n2 direction (m) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SAeroTwst !< Sine of the aerodynamic twist of the blade at the analysis nodes [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: StiffBE !< Interpolated edgewise blade stiffness [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: StiffBEA !< Interpolated blade extensional stiffness [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: StiffBF !< Interpolated flapwise blade stiffness [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: StiffBGJ !< Interpolated blade torsional stiffness [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SThetaS !< SIN( ThetaS ) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ThetaS !< Structural twist for analysis nodes [radians] + REAL(ReKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: TwistedSF !< Interpolated lineal blade mass density [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BldFl1Sh !< Blade-flap-mode-1 shape coefficients [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BldFl2Sh !< Blade-flap-mode-2 shape coefficients [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BldEdgSh !< Blade-edge-mode shape coefficients [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: FreqBE !< Blade edgewise natural frequencies (both w/ and w/o centrifugal stiffening) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: FreqBF !< Blade flapwise natural frequencies (both w/ and w/o centrifugal stiffening) [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: FreqTFA !< Computed fore-aft tower natural frequencies [-] + REAL(ReKi) , DIMENSION(1:2,1:2) :: FreqTSS !< Computed side-to-side tower natural frequencies [-] + REAL(ReKi) :: TeetCDmp !< Rotor-teeter rate-independent Coulomb-damping [-] + REAL(ReKi) :: TeetDmp !< Rotor-teeter damping constant [-] + REAL(ReKi) :: TeetDmpP !< Rotor-teeter damper position [-] + REAL(ReKi) :: TeetHSSp !< Rotor-teeter hard-stop linear-spring constant [-] + REAL(ReKi) :: TeetHStP !< Rotor-teeter hard-stop position [-] + REAL(ReKi) :: TeetSSSp !< Rotor-teeter soft-stop linear-spring constant [-] + REAL(ReKi) :: TeetSStP !< Rotor-teeter soft-stop position [-] + INTEGER(IntKi) :: TeetMod !< Rotor-teeter spring/damper model switch [-] + REAL(ReKi) :: TFrlCDmp !< Tail-furl rate-independent Coulomb-damping moment [-] + REAL(ReKi) :: TFrlDmp !< Tail-furl damping constant [-] + REAL(ReKi) :: TFrlDSDmp !< Tail-furl down-stop damping constant [-] + REAL(ReKi) :: TFrlDSDP !< Tail-furl down-stop damper position [-] + REAL(ReKi) :: TFrlDSSP !< Tail-furl down-stop spring position [-] + REAL(ReKi) :: TFrlDSSpr !< Tail-furl down-stop spring constant [-] + REAL(ReKi) :: TFrlSpr !< Tail-furl spring constant [-] + REAL(ReKi) :: TFrlUSDmp !< Tail-furl up-stop damping constant [-] + REAL(ReKi) :: TFrlUSDP !< Tail-furl up-stop damper position [-] + REAL(ReKi) :: TFrlUSSP !< Tail-furl up-stop spring position [-] + REAL(ReKi) :: TFrlUSSpr !< Tail-furl up-stop spring constant [-] + INTEGER(IntKi) :: TFrlMod !< Tail-furl spring/damper model switch [-] + REAL(ReKi) :: RFrlCDmp !< Rotor-furl rate-independent Coulomb-damping moment [-] + REAL(ReKi) :: RFrlDmp !< Rotor-furl damping constant [-] + REAL(ReKi) :: RFrlDSDmp !< Rotor-furl down-stop damping constant [-] + REAL(ReKi) :: RFrlDSDP !< Rotor-furl down-stop damper position [-] + REAL(ReKi) :: RFrlDSSP !< Rotor-furl down-stop spring position [-] + REAL(ReKi) :: RFrlDSSpr !< Rotor-furl down-stop spring constant [-] + REAL(ReKi) :: RFrlSpr !< Rotor-furl spring constant [-] + REAL(ReKi) :: RFrlUSDmp !< Rotor-furl up-stop damping constant [-] + REAL(ReKi) :: RFrlUSDP !< Rotor-furl up-stop damper position [-] + REAL(ReKi) :: RFrlUSSP !< Rotor-furl up-stop spring position [-] + REAL(ReKi) :: RFrlUSSpr !< Rotor-furl up-stop spring constant [-] + INTEGER(IntKi) :: RFrlMod !< Rotor-furl spring/damper model switch [-] + REAL(ReKi) :: ShftGagL !< Distance from hub or teeter pin to shaft strain gages [-] + INTEGER(IntKi) , DIMENSION(1:9) :: BldGagNd !< Nodes closest to the blade strain gages [-] + INTEGER(IntKi) , DIMENSION(1:9) :: TwrGagNd !< Nodes closest to the tower strain gages [-] + REAL(DbKi) :: TStart !< Time to begin tabular output [-] + REAL(ReKi) :: DTTorDmp !< Drivetrain torsional damper [-] + REAL(ReKi) :: DTTorSpr !< Drivetrain torsional spring [-] + REAL(ReKi) :: GBRatio !< Gearbox ratio [-] + REAL(ReKi) :: GBoxEff !< Gearbox efficiency [-] + REAL(ReKi) :: RotSpeed !< Initial or fixed rotor speed [rad/s] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BElmntMass !< Mass of the blade elements [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TElmntMass !< Mass of the tower elements [-] + INTEGER(IntKi) :: method !< Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4]) [-] + REAL(ReKi) :: PtfmCMxt !< Downwind distance from the ground [onshore] or MSL [offshore] to the platform CM [meters] + REAL(ReKi) :: PtfmCMyt !< Lateral distance from the ground [onshore] or MSL [offshore] to the platform CM [meters] + LOGICAL :: BD4Blades !< flag to determine if BeamDyn is computing blade loads (true) or ElastoDyn is (false) [-] + LOGICAL :: UseAD14 !< flag to determine if AeroDyn14 is being used. Will remove this later when we've replaced AD14. [-] + INTEGER(IntKi) :: BldNd_NumOuts !< Number of requested output channels per blade node (ED_AllBldNdOuts) [-] + INTEGER(IntKi) :: BldNd_TotNumOuts !< Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- ED_AllBldNdOuts) [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: BldNd_OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + INTEGER(IntKi) :: BldNd_BladesOut !< The blades to output (ED_AllBldNdOuts) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: dx !< vector that determines size of perturbation for x (continuous states) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-] + END TYPE ED_ParameterType +! ======================= +! ========= ED_InputType ======= + TYPE, PUBLIC :: ED_InputType + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladePtLoads !< A mesh on each blade, containing aerodynamic forces and moments (formerly AeroBladeForce and AeroBladeMoment) [-] + TYPE(MeshType) :: PlatformPtMesh !< A mesh at the platform reference (point Z), containing force: surge/xi (1), sway/yi (2), and heave/zi (3)-components; and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components acting at the platform (body X) / platform reference (point Z) associated with everything but the QD2T()s [N] + TYPE(MeshType) :: TowerPtLoads !< Tower line2 mesh with forces: surge/xi (1), sway/yi (2), and heave/zi (3)-components of the portion of the tower force at the current tower node (point T); and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components of the portion of the tower moment acting at the current tower node [N/m] + TYPE(MeshType) :: HubPtLoad !< A mesh at the teeter pin, containing forces: surge/xi (1), sway/yi (2), and heave/zi (3)-components; and moments: roll/xi (1), pitch/yi (2), and yaw/zi (3)-components acting at the hub. Passed from BeamDyn [-] + TYPE(MeshType) :: NacelleLoads !< From ServoDyn/TMD: loads on the nacelle. [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: TwrAddedMass !< 6-by-6 added mass matrix of the tower elements, per unit length-bjj: place on a mesh [per unit length] + REAL(ReKi) , DIMENSION(1:6,1:6) :: PtfmAddedMass !< Platform added mass matrix [kg, kg-m, kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchCom !< Commanded blade pitch angles [radians] + REAL(ReKi) :: YawMom !< Torque transmitted through the yaw bearing [N-m] + REAL(ReKi) :: GenTrq !< Electrical generator torque [N-m] + REAL(ReKi) :: HSSBrTrqC !< Commanded HSS brake torque [N-m] + END TYPE ED_InputType +! ======================= +! ========= ED_OutputType ======= + TYPE, PUBLIC :: ED_OutputType + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladeLn2Mesh !< A mesh on each blade, containing positions and orientations of the blade elements [-] + TYPE(MeshType) :: PlatformPtMesh !< Platform reference point positions/orientations/velocities/accelerations [-] + TYPE(MeshType) :: TowerLn2Mesh !< Tower line2 mesh with positions/orientations/velocities/accelerations [-] + TYPE(MeshType) :: HubPtMotion14 !< For AeroDyn v14: motions of the hub [-] + TYPE(MeshType) :: HubPtMotion !< For AeroDyn and Lidar(InflowWind): motions of the hub [-] + TYPE(MeshType) :: BladeRootMotion14 !< For AeroDyn v14: motions of the blade roots [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: BladeRootMotion !< For AeroDyn/BeamDyn: motions at the blade roots [-] + TYPE(MeshType) :: RotorFurlMotion14 !< For AeroDyn14: motions of the rotor furl point. [-] + TYPE(MeshType) :: NacelleMotion !< For AeroDyn14 & ServoDyn/TMD: motions of the nacelle. [-] + TYPE(MeshType) :: TowerBaseMotion14 !< For AeroDyn 14: motions of the tower base [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitch !< Current blade pitch angles [radians] + REAL(ReKi) :: Yaw !< Current nacelle yaw [radians] + REAL(ReKi) :: YawRate !< Current nacelle yaw rate [rad/s] + REAL(ReKi) :: LSS_Spd !< Low-speed shaft (LSS) speed at entrance to gearbox [rad/s] + REAL(ReKi) :: HSS_Spd !< High-speed shaft (HSS) speed [rad/s] + REAL(ReKi) :: RotSpeed !< Rotor azimuth angular speed [rad/s] + REAL(ReKi) :: TwrAccel !< Tower acceleration for tower feedback control (user routine only) [m/s^2] + REAL(ReKi) :: YawAngle !< Yaw angle to be used for yaw error calculations [radians] + REAL(ReKi) , DIMENSION(1:3) :: RootMyc !< Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3) [N-m] + REAL(ReKi) :: YawBrTAxp !< Tower-top / yaw bearing fore-aft (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: YawBrTAyp !< Tower-top / yaw bearing side-to-side (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: LSSTipPxa !< Rotor azimuth angle (position) [radians] + REAL(ReKi) , DIMENSION(1:3) :: RootMxc !< In-plane moment (i.e., the moment caused by in-plane forces) at the blade root [N-m] + REAL(ReKi) :: LSSTipMxa !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMya !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMza !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMys !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMzs !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: YawBrMyn !< Rotating (with nacelle) tower-top / yaw bearing pitch moment [N-m] + REAL(ReKi) :: YawBrMzn !< Tower-top / yaw bearing yaw moment [N-m] + REAL(ReKi) :: NcIMURAxs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAys !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAzs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: RotPwr !< Rotor power (this is equivalent to the low-speed shaft power) [W] + END TYPE ED_OutputType +! ======================= +CONTAINS + SUBROUTINE ED_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(ED_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 = 'ED_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%ADInputFile = SrcInitInputData%ADInputFile + DstInitInputData%CompElast = SrcInitInputData%CompElast + DstInitInputData%RootName = SrcInitInputData%RootName + END SUBROUTINE ED_CopyInitInput + + SUBROUTINE ED_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(ED_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ED_DestroyInitInput + + SUBROUTINE ED_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(ED_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 = 'ED_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1*LEN(InData%ADInputFile) ! ADInputFile + Int_BufSz = Int_BufSz + 1 ! CompElast + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%ADInputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%ADInputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompElast, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE ED_PackInitInput + + SUBROUTINE ED_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(ED_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 = 'ED_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%ADInputFile) + OutData%ADInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CompElast = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompElast) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE ED_UnPackInitInput + + SUBROUTINE ED_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(ED_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 = 'ED_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%NumBl = SrcInitOutputData%NumBl + DstInitOutputData%Gravity = SrcInitOutputData%Gravity +IF (ALLOCATED(SrcInitOutputData%BlPitch)) THEN + i1_l = LBOUND(SrcInitOutputData%BlPitch,1) + i1_u = UBOUND(SrcInitOutputData%BlPitch,1) + IF (.NOT. ALLOCATED(DstInitOutputData%BlPitch)) THEN + ALLOCATE(DstInitOutputData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%BlPitch = SrcInitOutputData%BlPitch +ENDIF + DstInitOutputData%BladeLength = SrcInitOutputData%BladeLength + DstInitOutputData%TowerHeight = SrcInitOutputData%TowerHeight + DstInitOutputData%TowerBaseHeight = SrcInitOutputData%TowerBaseHeight + DstInitOutputData%HubHt = SrcInitOutputData%HubHt +IF (ALLOCATED(SrcInitOutputData%BldRNodes)) THEN + i1_l = LBOUND(SrcInitOutputData%BldRNodes,1) + i1_u = UBOUND(SrcInitOutputData%BldRNodes,1) + IF (.NOT. ALLOCATED(DstInitOutputData%BldRNodes)) THEN + ALLOCATE(DstInitOutputData%BldRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%BldRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%BldRNodes = SrcInitOutputData%BldRNodes +ENDIF +IF (ALLOCATED(SrcInitOutputData%TwrHNodes)) THEN + i1_l = LBOUND(SrcInitOutputData%TwrHNodes,1) + i1_u = UBOUND(SrcInitOutputData%TwrHNodes,1) + IF (.NOT. ALLOCATED(DstInitOutputData%TwrHNodes)) THEN + ALLOCATE(DstInitOutputData%TwrHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%TwrHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%TwrHNodes = SrcInitOutputData%TwrHNodes +ENDIF + DstInitOutputData%PlatformPos = SrcInitOutputData%PlatformPos + DstInitOutputData%TwrBasePos = SrcInitOutputData%TwrBasePos + DstInitOutputData%HubRad = SrcInitOutputData%HubRad + DstInitOutputData%RotSpeed = SrcInitOutputData%RotSpeed + DstInitOutputData%isFixed_GenDOF = SrcInitOutputData%isFixed_GenDOF +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF + END SUBROUTINE ED_CopyInitOutput + + SUBROUTINE ED_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(ED_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%BlPitch)) THEN + DEALLOCATE(InitOutputData%BlPitch) +ENDIF +IF (ALLOCATED(InitOutputData%BldRNodes)) THEN + DEALLOCATE(InitOutputData%BldRNodes) +ENDIF +IF (ALLOCATED(InitOutputData%TwrHNodes)) THEN + DEALLOCATE(InitOutputData%TwrHNodes) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF + END SUBROUTINE ED_DestroyInitOutput + + SUBROUTINE ED_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(ED_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 = 'ED_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + 1 ! NumBl + Re_BufSz = Re_BufSz + 1 ! Gravity + Int_BufSz = Int_BufSz + 1 ! BlPitch allocated yes/no + IF ( ALLOCATED(InData%BlPitch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitch) ! BlPitch + END IF + Re_BufSz = Re_BufSz + 1 ! BladeLength + Re_BufSz = Re_BufSz + 1 ! TowerHeight + Re_BufSz = Re_BufSz + 1 ! TowerBaseHeight + Re_BufSz = Re_BufSz + 1 ! HubHt + Int_BufSz = Int_BufSz + 1 ! BldRNodes allocated yes/no + IF ( ALLOCATED(InData%BldRNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldRNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldRNodes) ! BldRNodes + END IF + Int_BufSz = Int_BufSz + 1 ! TwrHNodes allocated yes/no + IF ( ALLOCATED(InData%TwrHNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwrHNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrHNodes) ! TwrHNodes + END IF + Re_BufSz = Re_BufSz + SIZE(InData%PlatformPos) ! PlatformPos + Re_BufSz = Re_BufSz + SIZE(InData%TwrBasePos) ! TwrBasePos + Re_BufSz = Re_BufSz + 1 ! HubRad + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Int_BufSz = Int_BufSz + 1 ! isFixed_GenDOF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlPitch) ) 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%BlPitch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitch,1), UBOUND(InData%BlPitch,1) + ReKiBuf(Re_Xferred) = InData%BlPitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerBaseHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubHt + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldRNodes) ) 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%BldRNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldRNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldRNodes,1), UBOUND(InData%BldRNodes,1) + ReKiBuf(Re_Xferred) = InData%BldRNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrHNodes) ) 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%TwrHNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrHNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwrHNodes,1), UBOUND(InData%TwrHNodes,1) + ReKiBuf(Re_Xferred) = InData%TwrHNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%PlatformPos,1), UBOUND(InData%PlatformPos,1) + ReKiBuf(Re_Xferred) = InData%PlatformPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%TwrBasePos,1), UBOUND(InData%TwrBasePos,1) + ReKiBuf(Re_Xferred) = InData%TwrBasePos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%HubRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%isFixed_GenDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) 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%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) 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%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) 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%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_PackInitOutput + + SUBROUTINE ED_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(ED_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 = 'ED_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitch 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%BlPitch)) DEALLOCATE(OutData%BlPitch) + ALLOCATE(OutData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitch,1), UBOUND(OutData%BlPitch,1) + OutData%BlPitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerBaseHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldRNodes 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%BldRNodes)) DEALLOCATE(OutData%BldRNodes) + ALLOCATE(OutData%BldRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldRNodes,1), UBOUND(OutData%BldRNodes,1) + OutData%BldRNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrHNodes 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%TwrHNodes)) DEALLOCATE(OutData%TwrHNodes) + ALLOCATE(OutData%TwrHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwrHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwrHNodes,1), UBOUND(OutData%TwrHNodes,1) + OutData%TwrHNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%PlatformPos,1) + i1_u = UBOUND(OutData%PlatformPos,1) + DO i1 = LBOUND(OutData%PlatformPos,1), UBOUND(OutData%PlatformPos,1) + OutData%PlatformPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%TwrBasePos,1) + i1_u = UBOUND(OutData%TwrBasePos,1) + DO i1 = LBOUND(OutData%TwrBasePos,1), UBOUND(OutData%TwrBasePos,1) + OutData%TwrBasePos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%HubRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%isFixed_GenDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%isFixed_GenDOF) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x 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%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x 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%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x 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%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_UnPackInitOutput + + SUBROUTINE ED_CopyBladeInputData( SrcBladeInputDataData, DstBladeInputDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladeInputData), INTENT(IN) :: SrcBladeInputDataData + TYPE(BladeInputData), INTENT(INOUT) :: DstBladeInputDataData + 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 = 'ED_CopyBladeInputData' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladeInputDataData%NBlInpSt = SrcBladeInputDataData%NBlInpSt +IF (ALLOCATED(SrcBladeInputDataData%BlFract)) THEN + i1_l = LBOUND(SrcBladeInputDataData%BlFract,1) + i1_u = UBOUND(SrcBladeInputDataData%BlFract,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%BlFract)) THEN + ALLOCATE(DstBladeInputDataData%BlFract(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%BlFract.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%BlFract = SrcBladeInputDataData%BlFract +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%PitchAx)) THEN + i1_l = LBOUND(SrcBladeInputDataData%PitchAx,1) + i1_u = UBOUND(SrcBladeInputDataData%PitchAx,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%PitchAx)) THEN + ALLOCATE(DstBladeInputDataData%PitchAx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%PitchAx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%PitchAx = SrcBladeInputDataData%PitchAx +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%StrcTwst)) THEN + i1_l = LBOUND(SrcBladeInputDataData%StrcTwst,1) + i1_u = UBOUND(SrcBladeInputDataData%StrcTwst,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%StrcTwst)) THEN + ALLOCATE(DstBladeInputDataData%StrcTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%StrcTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%StrcTwst = SrcBladeInputDataData%StrcTwst +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%BMassDen)) THEN + i1_l = LBOUND(SrcBladeInputDataData%BMassDen,1) + i1_u = UBOUND(SrcBladeInputDataData%BMassDen,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%BMassDen)) THEN + ALLOCATE(DstBladeInputDataData%BMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%BMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%BMassDen = SrcBladeInputDataData%BMassDen +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%FlpStff)) THEN + i1_l = LBOUND(SrcBladeInputDataData%FlpStff,1) + i1_u = UBOUND(SrcBladeInputDataData%FlpStff,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%FlpStff)) THEN + ALLOCATE(DstBladeInputDataData%FlpStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%FlpStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%FlpStff = SrcBladeInputDataData%FlpStff +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%EdgStff)) THEN + i1_l = LBOUND(SrcBladeInputDataData%EdgStff,1) + i1_u = UBOUND(SrcBladeInputDataData%EdgStff,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%EdgStff)) THEN + ALLOCATE(DstBladeInputDataData%EdgStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%EdgStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%EdgStff = SrcBladeInputDataData%EdgStff +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%GJStff)) THEN + i1_l = LBOUND(SrcBladeInputDataData%GJStff,1) + i1_u = UBOUND(SrcBladeInputDataData%GJStff,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%GJStff)) THEN + ALLOCATE(DstBladeInputDataData%GJStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%GJStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%GJStff = SrcBladeInputDataData%GJStff +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%EAStff)) THEN + i1_l = LBOUND(SrcBladeInputDataData%EAStff,1) + i1_u = UBOUND(SrcBladeInputDataData%EAStff,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%EAStff)) THEN + ALLOCATE(DstBladeInputDataData%EAStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%EAStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%EAStff = SrcBladeInputDataData%EAStff +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%Alpha)) THEN + i1_l = LBOUND(SrcBladeInputDataData%Alpha,1) + i1_u = UBOUND(SrcBladeInputDataData%Alpha,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%Alpha)) THEN + ALLOCATE(DstBladeInputDataData%Alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%Alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%Alpha = SrcBladeInputDataData%Alpha +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%FlpIner)) THEN + i1_l = LBOUND(SrcBladeInputDataData%FlpIner,1) + i1_u = UBOUND(SrcBladeInputDataData%FlpIner,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%FlpIner)) THEN + ALLOCATE(DstBladeInputDataData%FlpIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%FlpIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%FlpIner = SrcBladeInputDataData%FlpIner +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%EdgIner)) THEN + i1_l = LBOUND(SrcBladeInputDataData%EdgIner,1) + i1_u = UBOUND(SrcBladeInputDataData%EdgIner,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%EdgIner)) THEN + ALLOCATE(DstBladeInputDataData%EdgIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%EdgIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%EdgIner = SrcBladeInputDataData%EdgIner +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%PrecrvRef)) THEN + i1_l = LBOUND(SrcBladeInputDataData%PrecrvRef,1) + i1_u = UBOUND(SrcBladeInputDataData%PrecrvRef,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%PrecrvRef)) THEN + ALLOCATE(DstBladeInputDataData%PrecrvRef(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%PrecrvRef.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%PrecrvRef = SrcBladeInputDataData%PrecrvRef +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%PreswpRef)) THEN + i1_l = LBOUND(SrcBladeInputDataData%PreswpRef,1) + i1_u = UBOUND(SrcBladeInputDataData%PreswpRef,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%PreswpRef)) THEN + ALLOCATE(DstBladeInputDataData%PreswpRef(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%PreswpRef.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%PreswpRef = SrcBladeInputDataData%PreswpRef +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%FlpcgOf)) THEN + i1_l = LBOUND(SrcBladeInputDataData%FlpcgOf,1) + i1_u = UBOUND(SrcBladeInputDataData%FlpcgOf,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%FlpcgOf)) THEN + ALLOCATE(DstBladeInputDataData%FlpcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%FlpcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%FlpcgOf = SrcBladeInputDataData%FlpcgOf +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%EdgcgOf)) THEN + i1_l = LBOUND(SrcBladeInputDataData%EdgcgOf,1) + i1_u = UBOUND(SrcBladeInputDataData%EdgcgOf,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%EdgcgOf)) THEN + ALLOCATE(DstBladeInputDataData%EdgcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%EdgcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%EdgcgOf = SrcBladeInputDataData%EdgcgOf +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%FlpEAOf)) THEN + i1_l = LBOUND(SrcBladeInputDataData%FlpEAOf,1) + i1_u = UBOUND(SrcBladeInputDataData%FlpEAOf,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%FlpEAOf)) THEN + ALLOCATE(DstBladeInputDataData%FlpEAOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%FlpEAOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%FlpEAOf = SrcBladeInputDataData%FlpEAOf +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%EdgEAOf)) THEN + i1_l = LBOUND(SrcBladeInputDataData%EdgEAOf,1) + i1_u = UBOUND(SrcBladeInputDataData%EdgEAOf,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%EdgEAOf)) THEN + ALLOCATE(DstBladeInputDataData%EdgEAOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%EdgEAOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%EdgEAOf = SrcBladeInputDataData%EdgEAOf +ENDIF + DstBladeInputDataData%BldFlDmp = SrcBladeInputDataData%BldFlDmp + DstBladeInputDataData%BldEdDmp = SrcBladeInputDataData%BldEdDmp + DstBladeInputDataData%FlStTunr = SrcBladeInputDataData%FlStTunr +IF (ALLOCATED(SrcBladeInputDataData%BldFl1Sh)) THEN + i1_l = LBOUND(SrcBladeInputDataData%BldFl1Sh,1) + i1_u = UBOUND(SrcBladeInputDataData%BldFl1Sh,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%BldFl1Sh)) THEN + ALLOCATE(DstBladeInputDataData%BldFl1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%BldFl1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%BldFl1Sh = SrcBladeInputDataData%BldFl1Sh +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%BldFl2Sh)) THEN + i1_l = LBOUND(SrcBladeInputDataData%BldFl2Sh,1) + i1_u = UBOUND(SrcBladeInputDataData%BldFl2Sh,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%BldFl2Sh)) THEN + ALLOCATE(DstBladeInputDataData%BldFl2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%BldFl2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%BldFl2Sh = SrcBladeInputDataData%BldFl2Sh +ENDIF +IF (ALLOCATED(SrcBladeInputDataData%BldEdgSh)) THEN + i1_l = LBOUND(SrcBladeInputDataData%BldEdgSh,1) + i1_u = UBOUND(SrcBladeInputDataData%BldEdgSh,1) + IF (.NOT. ALLOCATED(DstBladeInputDataData%BldEdgSh)) THEN + ALLOCATE(DstBladeInputDataData%BldEdgSh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeInputDataData%BldEdgSh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeInputDataData%BldEdgSh = SrcBladeInputDataData%BldEdgSh +ENDIF + END SUBROUTINE ED_CopyBladeInputData + + SUBROUTINE ED_DestroyBladeInputData( BladeInputDataData, ErrStat, ErrMsg ) + TYPE(BladeInputData), INTENT(INOUT) :: BladeInputDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyBladeInputData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladeInputDataData%BlFract)) THEN + DEALLOCATE(BladeInputDataData%BlFract) +ENDIF +IF (ALLOCATED(BladeInputDataData%PitchAx)) THEN + DEALLOCATE(BladeInputDataData%PitchAx) +ENDIF +IF (ALLOCATED(BladeInputDataData%StrcTwst)) THEN + DEALLOCATE(BladeInputDataData%StrcTwst) +ENDIF +IF (ALLOCATED(BladeInputDataData%BMassDen)) THEN + DEALLOCATE(BladeInputDataData%BMassDen) +ENDIF +IF (ALLOCATED(BladeInputDataData%FlpStff)) THEN + DEALLOCATE(BladeInputDataData%FlpStff) +ENDIF +IF (ALLOCATED(BladeInputDataData%EdgStff)) THEN + DEALLOCATE(BladeInputDataData%EdgStff) +ENDIF +IF (ALLOCATED(BladeInputDataData%GJStff)) THEN + DEALLOCATE(BladeInputDataData%GJStff) +ENDIF +IF (ALLOCATED(BladeInputDataData%EAStff)) THEN + DEALLOCATE(BladeInputDataData%EAStff) +ENDIF +IF (ALLOCATED(BladeInputDataData%Alpha)) THEN + DEALLOCATE(BladeInputDataData%Alpha) +ENDIF +IF (ALLOCATED(BladeInputDataData%FlpIner)) THEN + DEALLOCATE(BladeInputDataData%FlpIner) +ENDIF +IF (ALLOCATED(BladeInputDataData%EdgIner)) THEN + DEALLOCATE(BladeInputDataData%EdgIner) +ENDIF +IF (ALLOCATED(BladeInputDataData%PrecrvRef)) THEN + DEALLOCATE(BladeInputDataData%PrecrvRef) +ENDIF +IF (ALLOCATED(BladeInputDataData%PreswpRef)) THEN + DEALLOCATE(BladeInputDataData%PreswpRef) +ENDIF +IF (ALLOCATED(BladeInputDataData%FlpcgOf)) THEN + DEALLOCATE(BladeInputDataData%FlpcgOf) +ENDIF +IF (ALLOCATED(BladeInputDataData%EdgcgOf)) THEN + DEALLOCATE(BladeInputDataData%EdgcgOf) +ENDIF +IF (ALLOCATED(BladeInputDataData%FlpEAOf)) THEN + DEALLOCATE(BladeInputDataData%FlpEAOf) +ENDIF +IF (ALLOCATED(BladeInputDataData%EdgEAOf)) THEN + DEALLOCATE(BladeInputDataData%EdgEAOf) +ENDIF +IF (ALLOCATED(BladeInputDataData%BldFl1Sh)) THEN + DEALLOCATE(BladeInputDataData%BldFl1Sh) +ENDIF +IF (ALLOCATED(BladeInputDataData%BldFl2Sh)) THEN + DEALLOCATE(BladeInputDataData%BldFl2Sh) +ENDIF +IF (ALLOCATED(BladeInputDataData%BldEdgSh)) THEN + DEALLOCATE(BladeInputDataData%BldEdgSh) +ENDIF + END SUBROUTINE ED_DestroyBladeInputData + + SUBROUTINE ED_PackBladeInputData( 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(BladeInputData), 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 = 'ED_PackBladeInputData' + ! 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 ! NBlInpSt + Int_BufSz = Int_BufSz + 1 ! BlFract allocated yes/no + IF ( ALLOCATED(InData%BlFract) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlFract upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlFract) ! BlFract + END IF + Int_BufSz = Int_BufSz + 1 ! PitchAx allocated yes/no + IF ( ALLOCATED(InData%PitchAx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PitchAx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PitchAx) ! PitchAx + END IF + Int_BufSz = Int_BufSz + 1 ! StrcTwst allocated yes/no + IF ( ALLOCATED(InData%StrcTwst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StrcTwst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StrcTwst) ! StrcTwst + END IF + Int_BufSz = Int_BufSz + 1 ! BMassDen allocated yes/no + IF ( ALLOCATED(InData%BMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BMassDen) ! BMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! FlpStff allocated yes/no + IF ( ALLOCATED(InData%FlpStff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FlpStff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FlpStff) ! FlpStff + END IF + Int_BufSz = Int_BufSz + 1 ! EdgStff allocated yes/no + IF ( ALLOCATED(InData%EdgStff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EdgStff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgStff) ! EdgStff + END IF + Int_BufSz = Int_BufSz + 1 ! GJStff allocated yes/no + IF ( ALLOCATED(InData%GJStff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! GJStff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GJStff) ! GJStff + END IF + Int_BufSz = Int_BufSz + 1 ! EAStff allocated yes/no + IF ( ALLOCATED(InData%EAStff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EAStff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EAStff) ! EAStff + END IF + Int_BufSz = Int_BufSz + 1 ! Alpha allocated yes/no + IF ( ALLOCATED(InData%Alpha) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Alpha upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Alpha) ! Alpha + END IF + Int_BufSz = Int_BufSz + 1 ! FlpIner allocated yes/no + IF ( ALLOCATED(InData%FlpIner) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FlpIner upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FlpIner) ! FlpIner + END IF + Int_BufSz = Int_BufSz + 1 ! EdgIner allocated yes/no + IF ( ALLOCATED(InData%EdgIner) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EdgIner upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgIner) ! EdgIner + END IF + Int_BufSz = Int_BufSz + 1 ! PrecrvRef allocated yes/no + IF ( ALLOCATED(InData%PrecrvRef) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PrecrvRef upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PrecrvRef) ! PrecrvRef + END IF + Int_BufSz = Int_BufSz + 1 ! PreswpRef allocated yes/no + IF ( ALLOCATED(InData%PreswpRef) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PreswpRef upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PreswpRef) ! PreswpRef + END IF + Int_BufSz = Int_BufSz + 1 ! FlpcgOf allocated yes/no + IF ( ALLOCATED(InData%FlpcgOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FlpcgOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FlpcgOf) ! FlpcgOf + END IF + Int_BufSz = Int_BufSz + 1 ! EdgcgOf allocated yes/no + IF ( ALLOCATED(InData%EdgcgOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EdgcgOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgcgOf) ! EdgcgOf + END IF + Int_BufSz = Int_BufSz + 1 ! FlpEAOf allocated yes/no + IF ( ALLOCATED(InData%FlpEAOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FlpEAOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FlpEAOf) ! FlpEAOf + END IF + Int_BufSz = Int_BufSz + 1 ! EdgEAOf allocated yes/no + IF ( ALLOCATED(InData%EdgEAOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! EdgEAOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EdgEAOf) ! EdgEAOf + END IF + Re_BufSz = Re_BufSz + SIZE(InData%BldFlDmp) ! BldFlDmp + Re_BufSz = Re_BufSz + SIZE(InData%BldEdDmp) ! BldEdDmp + Re_BufSz = Re_BufSz + SIZE(InData%FlStTunr) ! FlStTunr + Int_BufSz = Int_BufSz + 1 ! BldFl1Sh allocated yes/no + IF ( ALLOCATED(InData%BldFl1Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldFl1Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldFl1Sh) ! BldFl1Sh + END IF + Int_BufSz = Int_BufSz + 1 ! BldFl2Sh allocated yes/no + IF ( ALLOCATED(InData%BldFl2Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldFl2Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldFl2Sh) ! BldFl2Sh + END IF + Int_BufSz = Int_BufSz + 1 ! BldEdgSh allocated yes/no + IF ( ALLOCATED(InData%BldEdgSh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldEdgSh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldEdgSh) ! BldEdgSh + 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%NBlInpSt + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlFract) ) 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%BlFract,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlFract,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlFract,1), UBOUND(InData%BlFract,1) + ReKiBuf(Re_Xferred) = InData%BlFract(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PitchAx) ) 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%PitchAx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitchAx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PitchAx,1), UBOUND(InData%PitchAx,1) + ReKiBuf(Re_Xferred) = InData%PitchAx(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StrcTwst) ) 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%StrcTwst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StrcTwst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StrcTwst,1), UBOUND(InData%StrcTwst,1) + ReKiBuf(Re_Xferred) = InData%StrcTwst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BMassDen) ) 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%BMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BMassDen,1), UBOUND(InData%BMassDen,1) + ReKiBuf(Re_Xferred) = InData%BMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FlpStff) ) 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%FlpStff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FlpStff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FlpStff,1), UBOUND(InData%FlpStff,1) + ReKiBuf(Re_Xferred) = InData%FlpStff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgStff) ) 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%EdgStff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgStff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EdgStff,1), UBOUND(InData%EdgStff,1) + ReKiBuf(Re_Xferred) = InData%EdgStff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GJStff) ) 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%GJStff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GJStff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%GJStff,1), UBOUND(InData%GJStff,1) + ReKiBuf(Re_Xferred) = InData%GJStff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EAStff) ) 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%EAStff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EAStff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EAStff,1), UBOUND(InData%EAStff,1) + ReKiBuf(Re_Xferred) = InData%EAStff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Alpha) ) 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%Alpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Alpha,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Alpha,1), UBOUND(InData%Alpha,1) + ReKiBuf(Re_Xferred) = InData%Alpha(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FlpIner) ) 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%FlpIner,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FlpIner,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FlpIner,1), UBOUND(InData%FlpIner,1) + ReKiBuf(Re_Xferred) = InData%FlpIner(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgIner) ) 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%EdgIner,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgIner,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EdgIner,1), UBOUND(InData%EdgIner,1) + ReKiBuf(Re_Xferred) = InData%EdgIner(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PrecrvRef) ) 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%PrecrvRef,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PrecrvRef,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PrecrvRef,1), UBOUND(InData%PrecrvRef,1) + ReKiBuf(Re_Xferred) = InData%PrecrvRef(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PreswpRef) ) 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%PreswpRef,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PreswpRef,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PreswpRef,1), UBOUND(InData%PreswpRef,1) + ReKiBuf(Re_Xferred) = InData%PreswpRef(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FlpcgOf) ) 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%FlpcgOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FlpcgOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FlpcgOf,1), UBOUND(InData%FlpcgOf,1) + ReKiBuf(Re_Xferred) = InData%FlpcgOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgcgOf) ) 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%EdgcgOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgcgOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EdgcgOf,1), UBOUND(InData%EdgcgOf,1) + ReKiBuf(Re_Xferred) = InData%EdgcgOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FlpEAOf) ) 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%FlpEAOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FlpEAOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FlpEAOf,1), UBOUND(InData%FlpEAOf,1) + ReKiBuf(Re_Xferred) = InData%FlpEAOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EdgEAOf) ) 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%EdgEAOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EdgEAOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%EdgEAOf,1), UBOUND(InData%EdgEAOf,1) + ReKiBuf(Re_Xferred) = InData%EdgEAOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%BldFlDmp,1), UBOUND(InData%BldFlDmp,1) + ReKiBuf(Re_Xferred) = InData%BldFlDmp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%BldEdDmp,1), UBOUND(InData%BldEdDmp,1) + ReKiBuf(Re_Xferred) = InData%BldEdDmp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FlStTunr,1), UBOUND(InData%FlStTunr,1) + ReKiBuf(Re_Xferred) = InData%FlStTunr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%BldFl1Sh) ) 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%BldFl1Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl1Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldFl1Sh,1), UBOUND(InData%BldFl1Sh,1) + ReKiBuf(Re_Xferred) = InData%BldFl1Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldFl2Sh) ) 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%BldFl2Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl2Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldFl2Sh,1), UBOUND(InData%BldFl2Sh,1) + ReKiBuf(Re_Xferred) = InData%BldFl2Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldEdgSh) ) 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%BldEdgSh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldEdgSh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldEdgSh,1), UBOUND(InData%BldEdgSh,1) + ReKiBuf(Re_Xferred) = InData%BldEdgSh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_PackBladeInputData + + SUBROUTINE ED_UnPackBladeInputData( 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(BladeInputData), 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 = 'ED_UnPackBladeInputData' + ! 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%NBlInpSt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlFract 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%BlFract)) DEALLOCATE(OutData%BlFract) + ALLOCATE(OutData%BlFract(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlFract.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlFract,1), UBOUND(OutData%BlFract,1) + OutData%BlFract(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PitchAx 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%PitchAx)) DEALLOCATE(OutData%PitchAx) + ALLOCATE(OutData%PitchAx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PitchAx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PitchAx,1), UBOUND(OutData%PitchAx,1) + OutData%PitchAx(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StrcTwst 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%StrcTwst)) DEALLOCATE(OutData%StrcTwst) + ALLOCATE(OutData%StrcTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StrcTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StrcTwst,1), UBOUND(OutData%StrcTwst,1) + OutData%StrcTwst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BMassDen 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%BMassDen)) DEALLOCATE(OutData%BMassDen) + ALLOCATE(OutData%BMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BMassDen,1), UBOUND(OutData%BMassDen,1) + OutData%BMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FlpStff 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%FlpStff)) DEALLOCATE(OutData%FlpStff) + ALLOCATE(OutData%FlpStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FlpStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FlpStff,1), UBOUND(OutData%FlpStff,1) + OutData%FlpStff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgStff 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%EdgStff)) DEALLOCATE(OutData%EdgStff) + ALLOCATE(OutData%EdgStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EdgStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EdgStff,1), UBOUND(OutData%EdgStff,1) + OutData%EdgStff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GJStff 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%GJStff)) DEALLOCATE(OutData%GJStff) + ALLOCATE(OutData%GJStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GJStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%GJStff,1), UBOUND(OutData%GJStff,1) + OutData%GJStff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EAStff 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%EAStff)) DEALLOCATE(OutData%EAStff) + ALLOCATE(OutData%EAStff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EAStff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EAStff,1), UBOUND(OutData%EAStff,1) + OutData%EAStff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Alpha 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%Alpha)) DEALLOCATE(OutData%Alpha) + ALLOCATE(OutData%Alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Alpha,1), UBOUND(OutData%Alpha,1) + OutData%Alpha(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FlpIner 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%FlpIner)) DEALLOCATE(OutData%FlpIner) + ALLOCATE(OutData%FlpIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FlpIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FlpIner,1), UBOUND(OutData%FlpIner,1) + OutData%FlpIner(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgIner 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%EdgIner)) DEALLOCATE(OutData%EdgIner) + ALLOCATE(OutData%EdgIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EdgIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EdgIner,1), UBOUND(OutData%EdgIner,1) + OutData%EdgIner(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PrecrvRef 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%PrecrvRef)) DEALLOCATE(OutData%PrecrvRef) + ALLOCATE(OutData%PrecrvRef(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PrecrvRef.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PrecrvRef,1), UBOUND(OutData%PrecrvRef,1) + OutData%PrecrvRef(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PreswpRef 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%PreswpRef)) DEALLOCATE(OutData%PreswpRef) + ALLOCATE(OutData%PreswpRef(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PreswpRef.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PreswpRef,1), UBOUND(OutData%PreswpRef,1) + OutData%PreswpRef(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FlpcgOf 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%FlpcgOf)) DEALLOCATE(OutData%FlpcgOf) + ALLOCATE(OutData%FlpcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FlpcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FlpcgOf,1), UBOUND(OutData%FlpcgOf,1) + OutData%FlpcgOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgcgOf 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%EdgcgOf)) DEALLOCATE(OutData%EdgcgOf) + ALLOCATE(OutData%EdgcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EdgcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EdgcgOf,1), UBOUND(OutData%EdgcgOf,1) + OutData%EdgcgOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FlpEAOf 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%FlpEAOf)) DEALLOCATE(OutData%FlpEAOf) + ALLOCATE(OutData%FlpEAOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FlpEAOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FlpEAOf,1), UBOUND(OutData%FlpEAOf,1) + OutData%FlpEAOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EdgEAOf 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%EdgEAOf)) DEALLOCATE(OutData%EdgEAOf) + ALLOCATE(OutData%EdgEAOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EdgEAOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%EdgEAOf,1), UBOUND(OutData%EdgEAOf,1) + OutData%EdgEAOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%BldFlDmp,1) + i1_u = UBOUND(OutData%BldFlDmp,1) + DO i1 = LBOUND(OutData%BldFlDmp,1), UBOUND(OutData%BldFlDmp,1) + OutData%BldFlDmp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%BldEdDmp,1) + i1_u = UBOUND(OutData%BldEdDmp,1) + DO i1 = LBOUND(OutData%BldEdDmp,1), UBOUND(OutData%BldEdDmp,1) + OutData%BldEdDmp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FlStTunr,1) + i1_u = UBOUND(OutData%FlStTunr,1) + DO i1 = LBOUND(OutData%FlStTunr,1), UBOUND(OutData%FlStTunr,1) + OutData%FlStTunr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldFl1Sh 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%BldFl1Sh)) DEALLOCATE(OutData%BldFl1Sh) + ALLOCATE(OutData%BldFl1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldFl1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldFl1Sh,1), UBOUND(OutData%BldFl1Sh,1) + OutData%BldFl1Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldFl2Sh 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%BldFl2Sh)) DEALLOCATE(OutData%BldFl2Sh) + ALLOCATE(OutData%BldFl2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldFl2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldFl2Sh,1), UBOUND(OutData%BldFl2Sh,1) + OutData%BldFl2Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldEdgSh 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%BldEdgSh)) DEALLOCATE(OutData%BldEdgSh) + ALLOCATE(OutData%BldEdgSh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldEdgSh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldEdgSh,1), UBOUND(OutData%BldEdgSh,1) + OutData%BldEdgSh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_UnPackBladeInputData + + SUBROUTINE ED_CopyBladeMeshInputData( SrcBladeMeshInputDataData, DstBladeMeshInputDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_BladeMeshInputData), INTENT(IN) :: SrcBladeMeshInputDataData + TYPE(ED_BladeMeshInputData), INTENT(INOUT) :: DstBladeMeshInputDataData + 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 = 'ED_CopyBladeMeshInputData' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladeMeshInputDataData%BldNodes = SrcBladeMeshInputDataData%BldNodes +IF (ALLOCATED(SrcBladeMeshInputDataData%RNodes)) THEN + i1_l = LBOUND(SrcBladeMeshInputDataData%RNodes,1) + i1_u = UBOUND(SrcBladeMeshInputDataData%RNodes,1) + IF (.NOT. ALLOCATED(DstBladeMeshInputDataData%RNodes)) THEN + ALLOCATE(DstBladeMeshInputDataData%RNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeMeshInputDataData%RNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeMeshInputDataData%RNodes = SrcBladeMeshInputDataData%RNodes +ENDIF +IF (ALLOCATED(SrcBladeMeshInputDataData%AeroTwst)) THEN + i1_l = LBOUND(SrcBladeMeshInputDataData%AeroTwst,1) + i1_u = UBOUND(SrcBladeMeshInputDataData%AeroTwst,1) + IF (.NOT. ALLOCATED(DstBladeMeshInputDataData%AeroTwst)) THEN + ALLOCATE(DstBladeMeshInputDataData%AeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeMeshInputDataData%AeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeMeshInputDataData%AeroTwst = SrcBladeMeshInputDataData%AeroTwst +ENDIF +IF (ALLOCATED(SrcBladeMeshInputDataData%Chord)) THEN + i1_l = LBOUND(SrcBladeMeshInputDataData%Chord,1) + i1_u = UBOUND(SrcBladeMeshInputDataData%Chord,1) + IF (.NOT. ALLOCATED(DstBladeMeshInputDataData%Chord)) THEN + ALLOCATE(DstBladeMeshInputDataData%Chord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladeMeshInputDataData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladeMeshInputDataData%Chord = SrcBladeMeshInputDataData%Chord +ENDIF + END SUBROUTINE ED_CopyBladeMeshInputData + + SUBROUTINE ED_DestroyBladeMeshInputData( BladeMeshInputDataData, ErrStat, ErrMsg ) + TYPE(ED_BladeMeshInputData), INTENT(INOUT) :: BladeMeshInputDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyBladeMeshInputData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladeMeshInputDataData%RNodes)) THEN + DEALLOCATE(BladeMeshInputDataData%RNodes) +ENDIF +IF (ALLOCATED(BladeMeshInputDataData%AeroTwst)) THEN + DEALLOCATE(BladeMeshInputDataData%AeroTwst) +ENDIF +IF (ALLOCATED(BladeMeshInputDataData%Chord)) THEN + DEALLOCATE(BladeMeshInputDataData%Chord) +ENDIF + END SUBROUTINE ED_DestroyBladeMeshInputData + + SUBROUTINE ED_PackBladeMeshInputData( 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(ED_BladeMeshInputData), 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 = 'ED_PackBladeMeshInputData' + ! 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 ! BldNodes + Int_BufSz = Int_BufSz + 1 ! RNodes allocated yes/no + IF ( ALLOCATED(InData%RNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RNodes) ! RNodes + END IF + Int_BufSz = Int_BufSz + 1 ! AeroTwst allocated yes/no + IF ( ALLOCATED(InData%AeroTwst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AeroTwst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AeroTwst) ! AeroTwst + END IF + Int_BufSz = Int_BufSz + 1 ! Chord allocated yes/no + IF ( ALLOCATED(InData%Chord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Chord) ! Chord + 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%BldNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%RNodes) ) 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%RNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RNodes,1), UBOUND(InData%RNodes,1) + ReKiBuf(Re_Xferred) = InData%RNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AeroTwst) ) 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%AeroTwst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AeroTwst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AeroTwst,1), UBOUND(InData%AeroTwst,1) + ReKiBuf(Re_Xferred) = InData%AeroTwst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Chord) ) 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%Chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Chord,1), UBOUND(InData%Chord,1) + ReKiBuf(Re_Xferred) = InData%Chord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_PackBladeMeshInputData + + SUBROUTINE ED_UnPackBladeMeshInputData( 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(ED_BladeMeshInputData), 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 = 'ED_UnPackBladeMeshInputData' + ! 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%BldNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RNodes 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%RNodes)) DEALLOCATE(OutData%RNodes) + ALLOCATE(OutData%RNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RNodes,1), UBOUND(OutData%RNodes,1) + OutData%RNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AeroTwst 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%AeroTwst)) DEALLOCATE(OutData%AeroTwst) + ALLOCATE(OutData%AeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AeroTwst,1), UBOUND(OutData%AeroTwst,1) + OutData%AeroTwst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Chord 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%Chord)) DEALLOCATE(OutData%Chord) + ALLOCATE(OutData%Chord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Chord,1), UBOUND(OutData%Chord,1) + OutData%Chord(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_UnPackBladeMeshInputData + + SUBROUTINE ED_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(ED_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'ED_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DT = SrcInputFileData%DT + DstInputFileData%Gravity = SrcInputFileData%Gravity + DstInputFileData%FlapDOF1 = SrcInputFileData%FlapDOF1 + DstInputFileData%FlapDOF2 = SrcInputFileData%FlapDOF2 + DstInputFileData%EdgeDOF = SrcInputFileData%EdgeDOF + DstInputFileData%TeetDOF = SrcInputFileData%TeetDOF + DstInputFileData%DrTrDOF = SrcInputFileData%DrTrDOF + DstInputFileData%GenDOF = SrcInputFileData%GenDOF + DstInputFileData%YawDOF = SrcInputFileData%YawDOF + DstInputFileData%TwFADOF1 = SrcInputFileData%TwFADOF1 + DstInputFileData%TwFADOF2 = SrcInputFileData%TwFADOF2 + DstInputFileData%TwSSDOF1 = SrcInputFileData%TwSSDOF1 + DstInputFileData%TwSSDOF2 = SrcInputFileData%TwSSDOF2 + DstInputFileData%PtfmSgDOF = SrcInputFileData%PtfmSgDOF + DstInputFileData%PtfmSwDOF = SrcInputFileData%PtfmSwDOF + DstInputFileData%PtfmHvDOF = SrcInputFileData%PtfmHvDOF + DstInputFileData%PtfmRDOF = SrcInputFileData%PtfmRDOF + DstInputFileData%PtfmPDOF = SrcInputFileData%PtfmPDOF + DstInputFileData%PtfmYDOF = SrcInputFileData%PtfmYDOF + DstInputFileData%OoPDefl = SrcInputFileData%OoPDefl + DstInputFileData%IPDefl = SrcInputFileData%IPDefl +IF (ALLOCATED(SrcInputFileData%BlPitch)) THEN + i1_l = LBOUND(SrcInputFileData%BlPitch,1) + i1_u = UBOUND(SrcInputFileData%BlPitch,1) + IF (.NOT. ALLOCATED(DstInputFileData%BlPitch)) THEN + ALLOCATE(DstInputFileData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BlPitch = SrcInputFileData%BlPitch +ENDIF + DstInputFileData%TeetDefl = SrcInputFileData%TeetDefl + DstInputFileData%Azimuth = SrcInputFileData%Azimuth + DstInputFileData%RotSpeed = SrcInputFileData%RotSpeed + DstInputFileData%NacYaw = SrcInputFileData%NacYaw + DstInputFileData%TTDspFA = SrcInputFileData%TTDspFA + DstInputFileData%TTDspSS = SrcInputFileData%TTDspSS + DstInputFileData%PtfmSurge = SrcInputFileData%PtfmSurge + DstInputFileData%PtfmSway = SrcInputFileData%PtfmSway + DstInputFileData%PtfmHeave = SrcInputFileData%PtfmHeave + DstInputFileData%PtfmRoll = SrcInputFileData%PtfmRoll + DstInputFileData%PtfmPitch = SrcInputFileData%PtfmPitch + DstInputFileData%PtfmYaw = SrcInputFileData%PtfmYaw + DstInputFileData%NumBl = SrcInputFileData%NumBl + DstInputFileData%TipRad = SrcInputFileData%TipRad + DstInputFileData%HubRad = SrcInputFileData%HubRad +IF (ALLOCATED(SrcInputFileData%PreCone)) THEN + i1_l = LBOUND(SrcInputFileData%PreCone,1) + i1_u = UBOUND(SrcInputFileData%PreCone,1) + IF (.NOT. ALLOCATED(DstInputFileData%PreCone)) THEN + ALLOCATE(DstInputFileData%PreCone(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%PreCone.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%PreCone = SrcInputFileData%PreCone +ENDIF + DstInputFileData%HubCM = SrcInputFileData%HubCM + DstInputFileData%UndSling = SrcInputFileData%UndSling + DstInputFileData%Delta3 = SrcInputFileData%Delta3 + DstInputFileData%AzimB1Up = SrcInputFileData%AzimB1Up + DstInputFileData%OverHang = SrcInputFileData%OverHang + DstInputFileData%ShftGagL = SrcInputFileData%ShftGagL + DstInputFileData%ShftTilt = SrcInputFileData%ShftTilt + DstInputFileData%NacCMxn = SrcInputFileData%NacCMxn + DstInputFileData%NacCMyn = SrcInputFileData%NacCMyn + DstInputFileData%NacCMzn = SrcInputFileData%NacCMzn + DstInputFileData%NcIMUxn = SrcInputFileData%NcIMUxn + DstInputFileData%NcIMUyn = SrcInputFileData%NcIMUyn + DstInputFileData%NcIMUzn = SrcInputFileData%NcIMUzn + DstInputFileData%Twr2Shft = SrcInputFileData%Twr2Shft + DstInputFileData%TowerHt = SrcInputFileData%TowerHt + DstInputFileData%TowerBsHt = SrcInputFileData%TowerBsHt + DstInputFileData%PtfmCMxt = SrcInputFileData%PtfmCMxt + DstInputFileData%PtfmCMyt = SrcInputFileData%PtfmCMyt + DstInputFileData%PtfmCMzt = SrcInputFileData%PtfmCMzt + DstInputFileData%PtfmRefzt = SrcInputFileData%PtfmRefzt +IF (ALLOCATED(SrcInputFileData%TipMass)) THEN + i1_l = LBOUND(SrcInputFileData%TipMass,1) + i1_u = UBOUND(SrcInputFileData%TipMass,1) + IF (.NOT. ALLOCATED(DstInputFileData%TipMass)) THEN + ALLOCATE(DstInputFileData%TipMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TipMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TipMass = SrcInputFileData%TipMass +ENDIF + DstInputFileData%HubMass = SrcInputFileData%HubMass + DstInputFileData%HubIner = SrcInputFileData%HubIner + DstInputFileData%GenIner = SrcInputFileData%GenIner + DstInputFileData%NacMass = SrcInputFileData%NacMass + DstInputFileData%NacYIner = SrcInputFileData%NacYIner + DstInputFileData%YawBrMass = SrcInputFileData%YawBrMass + DstInputFileData%PtfmMass = SrcInputFileData%PtfmMass + DstInputFileData%PtfmRIner = SrcInputFileData%PtfmRIner + DstInputFileData%PtfmPIner = SrcInputFileData%PtfmPIner + DstInputFileData%PtfmYIner = SrcInputFileData%PtfmYIner + DstInputFileData%BldNodes = SrcInputFileData%BldNodes +IF (ALLOCATED(SrcInputFileData%InpBlMesh)) THEN + i1_l = LBOUND(SrcInputFileData%InpBlMesh,1) + i1_u = UBOUND(SrcInputFileData%InpBlMesh,1) + IF (.NOT. ALLOCATED(DstInputFileData%InpBlMesh)) THEN + ALLOCATE(DstInputFileData%InpBlMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%InpBlMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputFileData%InpBlMesh,1), UBOUND(SrcInputFileData%InpBlMesh,1) + CALL ED_Copyblademeshinputdata( SrcInputFileData%InpBlMesh(i1), DstInputFileData%InpBlMesh(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInputFileData%InpBl)) THEN + i1_l = LBOUND(SrcInputFileData%InpBl,1) + i1_u = UBOUND(SrcInputFileData%InpBl,1) + IF (.NOT. ALLOCATED(DstInputFileData%InpBl)) THEN + ALLOCATE(DstInputFileData%InpBl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%InpBl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputFileData%InpBl,1), UBOUND(SrcInputFileData%InpBl,1) + CALL ED_Copybladeinputdata( SrcInputFileData%InpBl(i1), DstInputFileData%InpBl(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInputFileData%TeetMod = SrcInputFileData%TeetMod + DstInputFileData%TeetDmpP = SrcInputFileData%TeetDmpP + DstInputFileData%TeetDmp = SrcInputFileData%TeetDmp + DstInputFileData%TeetCDmp = SrcInputFileData%TeetCDmp + DstInputFileData%TeetSStP = SrcInputFileData%TeetSStP + DstInputFileData%TeetHStP = SrcInputFileData%TeetHStP + DstInputFileData%TeetSSSp = SrcInputFileData%TeetSSSp + DstInputFileData%TeetHSSp = SrcInputFileData%TeetHSSp + DstInputFileData%GBoxEff = SrcInputFileData%GBoxEff + DstInputFileData%GBRatio = SrcInputFileData%GBRatio + DstInputFileData%DTTorSpr = SrcInputFileData%DTTorSpr + DstInputFileData%DTTorDmp = SrcInputFileData%DTTorDmp + DstInputFileData%Furling = SrcInputFileData%Furling + DstInputFileData%TwrNodes = SrcInputFileData%TwrNodes + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%OutFile = SrcInputFileData%OutFile + DstInputFileData%TabDelim = SrcInputFileData%TabDelim + DstInputFileData%OutFmt = SrcInputFileData%OutFmt + DstInputFileData%Tstart = SrcInputFileData%Tstart + DstInputFileData%DecFact = SrcInputFileData%DecFact + DstInputFileData%NTwGages = SrcInputFileData%NTwGages + DstInputFileData%TwrGagNd = SrcInputFileData%TwrGagNd + DstInputFileData%NBlGages = SrcInputFileData%NBlGages + DstInputFileData%BldGagNd = SrcInputFileData%BldGagNd + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + DstInputFileData%NTwInpSt = SrcInputFileData%NTwInpSt + DstInputFileData%TwrFADmp = SrcInputFileData%TwrFADmp + DstInputFileData%TwrSSDmp = SrcInputFileData%TwrSSDmp + DstInputFileData%FAStTunr = SrcInputFileData%FAStTunr + DstInputFileData%SSStTunr = SrcInputFileData%SSStTunr +IF (ALLOCATED(SrcInputFileData%HtFract)) THEN + i1_l = LBOUND(SrcInputFileData%HtFract,1) + i1_u = UBOUND(SrcInputFileData%HtFract,1) + IF (.NOT. ALLOCATED(DstInputFileData%HtFract)) THEN + ALLOCATE(DstInputFileData%HtFract(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%HtFract.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%HtFract = SrcInputFileData%HtFract +ENDIF +IF (ALLOCATED(SrcInputFileData%TMassDen)) THEN + i1_l = LBOUND(SrcInputFileData%TMassDen,1) + i1_u = UBOUND(SrcInputFileData%TMassDen,1) + IF (.NOT. ALLOCATED(DstInputFileData%TMassDen)) THEN + ALLOCATE(DstInputFileData%TMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TMassDen = SrcInputFileData%TMassDen +ENDIF +IF (ALLOCATED(SrcInputFileData%TwFAStif)) THEN + i1_l = LBOUND(SrcInputFileData%TwFAStif,1) + i1_u = UBOUND(SrcInputFileData%TwFAStif,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwFAStif)) THEN + ALLOCATE(DstInputFileData%TwFAStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwFAStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwFAStif = SrcInputFileData%TwFAStif +ENDIF +IF (ALLOCATED(SrcInputFileData%TwSSStif)) THEN + i1_l = LBOUND(SrcInputFileData%TwSSStif,1) + i1_u = UBOUND(SrcInputFileData%TwSSStif,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwSSStif)) THEN + ALLOCATE(DstInputFileData%TwSSStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwSSStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwSSStif = SrcInputFileData%TwSSStif +ENDIF +IF (ALLOCATED(SrcInputFileData%TwFAM1Sh)) THEN + i1_l = LBOUND(SrcInputFileData%TwFAM1Sh,1) + i1_u = UBOUND(SrcInputFileData%TwFAM1Sh,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwFAM1Sh)) THEN + ALLOCATE(DstInputFileData%TwFAM1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwFAM1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwFAM1Sh = SrcInputFileData%TwFAM1Sh +ENDIF +IF (ALLOCATED(SrcInputFileData%TwFAM2Sh)) THEN + i1_l = LBOUND(SrcInputFileData%TwFAM2Sh,1) + i1_u = UBOUND(SrcInputFileData%TwFAM2Sh,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwFAM2Sh)) THEN + ALLOCATE(DstInputFileData%TwFAM2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwFAM2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwFAM2Sh = SrcInputFileData%TwFAM2Sh +ENDIF +IF (ALLOCATED(SrcInputFileData%TwSSM1Sh)) THEN + i1_l = LBOUND(SrcInputFileData%TwSSM1Sh,1) + i1_u = UBOUND(SrcInputFileData%TwSSM1Sh,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwSSM1Sh)) THEN + ALLOCATE(DstInputFileData%TwSSM1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwSSM1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwSSM1Sh = SrcInputFileData%TwSSM1Sh +ENDIF +IF (ALLOCATED(SrcInputFileData%TwSSM2Sh)) THEN + i1_l = LBOUND(SrcInputFileData%TwSSM2Sh,1) + i1_u = UBOUND(SrcInputFileData%TwSSM2Sh,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwSSM2Sh)) THEN + ALLOCATE(DstInputFileData%TwSSM2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwSSM2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwSSM2Sh = SrcInputFileData%TwSSM2Sh +ENDIF +IF (ALLOCATED(SrcInputFileData%TwGJStif)) THEN + i1_l = LBOUND(SrcInputFileData%TwGJStif,1) + i1_u = UBOUND(SrcInputFileData%TwGJStif,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwGJStif)) THEN + ALLOCATE(DstInputFileData%TwGJStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwGJStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwGJStif = SrcInputFileData%TwGJStif +ENDIF +IF (ALLOCATED(SrcInputFileData%TwEAStif)) THEN + i1_l = LBOUND(SrcInputFileData%TwEAStif,1) + i1_u = UBOUND(SrcInputFileData%TwEAStif,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwEAStif)) THEN + ALLOCATE(DstInputFileData%TwEAStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwEAStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwEAStif = SrcInputFileData%TwEAStif +ENDIF +IF (ALLOCATED(SrcInputFileData%TwFAIner)) THEN + i1_l = LBOUND(SrcInputFileData%TwFAIner,1) + i1_u = UBOUND(SrcInputFileData%TwFAIner,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwFAIner)) THEN + ALLOCATE(DstInputFileData%TwFAIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwFAIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwFAIner = SrcInputFileData%TwFAIner +ENDIF +IF (ALLOCATED(SrcInputFileData%TwSSIner)) THEN + i1_l = LBOUND(SrcInputFileData%TwSSIner,1) + i1_u = UBOUND(SrcInputFileData%TwSSIner,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwSSIner)) THEN + ALLOCATE(DstInputFileData%TwSSIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwSSIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwSSIner = SrcInputFileData%TwSSIner +ENDIF +IF (ALLOCATED(SrcInputFileData%TwFAcgOf)) THEN + i1_l = LBOUND(SrcInputFileData%TwFAcgOf,1) + i1_u = UBOUND(SrcInputFileData%TwFAcgOf,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwFAcgOf)) THEN + ALLOCATE(DstInputFileData%TwFAcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwFAcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwFAcgOf = SrcInputFileData%TwFAcgOf +ENDIF +IF (ALLOCATED(SrcInputFileData%TwSScgOf)) THEN + i1_l = LBOUND(SrcInputFileData%TwSScgOf,1) + i1_u = UBOUND(SrcInputFileData%TwSScgOf,1) + IF (.NOT. ALLOCATED(DstInputFileData%TwSScgOf)) THEN + ALLOCATE(DstInputFileData%TwSScgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%TwSScgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%TwSScgOf = SrcInputFileData%TwSScgOf +ENDIF + DstInputFileData%RFrlDOF = SrcInputFileData%RFrlDOF + DstInputFileData%TFrlDOF = SrcInputFileData%TFrlDOF + DstInputFileData%RotFurl = SrcInputFileData%RotFurl + DstInputFileData%TailFurl = SrcInputFileData%TailFurl + DstInputFileData%Yaw2Shft = SrcInputFileData%Yaw2Shft + DstInputFileData%ShftSkew = SrcInputFileData%ShftSkew + DstInputFileData%RFrlCMxn = SrcInputFileData%RFrlCMxn + DstInputFileData%RFrlCMyn = SrcInputFileData%RFrlCMyn + DstInputFileData%RFrlCMzn = SrcInputFileData%RFrlCMzn + DstInputFileData%BoomCMxn = SrcInputFileData%BoomCMxn + DstInputFileData%BoomCMyn = SrcInputFileData%BoomCMyn + DstInputFileData%BoomCMzn = SrcInputFileData%BoomCMzn + DstInputFileData%TFinCMxn = SrcInputFileData%TFinCMxn + DstInputFileData%TFinCMyn = SrcInputFileData%TFinCMyn + DstInputFileData%TFinCMzn = SrcInputFileData%TFinCMzn + DstInputFileData%TFinCPxn = SrcInputFileData%TFinCPxn + DstInputFileData%TFinCPyn = SrcInputFileData%TFinCPyn + DstInputFileData%TFinCPzn = SrcInputFileData%TFinCPzn + DstInputFileData%TFinSkew = SrcInputFileData%TFinSkew + DstInputFileData%TFinTilt = SrcInputFileData%TFinTilt + DstInputFileData%TFinBank = SrcInputFileData%TFinBank + DstInputFileData%RFrlPntxn = SrcInputFileData%RFrlPntxn + DstInputFileData%RFrlPntyn = SrcInputFileData%RFrlPntyn + DstInputFileData%RFrlPntzn = SrcInputFileData%RFrlPntzn + DstInputFileData%RFrlSkew = SrcInputFileData%RFrlSkew + DstInputFileData%RFrlTilt = SrcInputFileData%RFrlTilt + DstInputFileData%TFrlPntxn = SrcInputFileData%TFrlPntxn + DstInputFileData%TFrlPntyn = SrcInputFileData%TFrlPntyn + DstInputFileData%TFrlPntzn = SrcInputFileData%TFrlPntzn + DstInputFileData%TFrlSkew = SrcInputFileData%TFrlSkew + DstInputFileData%TFrlTilt = SrcInputFileData%TFrlTilt + DstInputFileData%RFrlMass = SrcInputFileData%RFrlMass + DstInputFileData%BoomMass = SrcInputFileData%BoomMass + DstInputFileData%TFinMass = SrcInputFileData%TFinMass + DstInputFileData%RFrlIner = SrcInputFileData%RFrlIner + DstInputFileData%TFrlIner = SrcInputFileData%TFrlIner + DstInputFileData%RFrlMod = SrcInputFileData%RFrlMod + DstInputFileData%RFrlSpr = SrcInputFileData%RFrlSpr + DstInputFileData%RFrlDmp = SrcInputFileData%RFrlDmp + DstInputFileData%RFrlCDmp = SrcInputFileData%RFrlCDmp + DstInputFileData%RFrlUSSP = SrcInputFileData%RFrlUSSP + DstInputFileData%RFrlDSSP = SrcInputFileData%RFrlDSSP + DstInputFileData%RFrlUSSpr = SrcInputFileData%RFrlUSSpr + DstInputFileData%RFrlDSSpr = SrcInputFileData%RFrlDSSpr + DstInputFileData%RFrlUSDP = SrcInputFileData%RFrlUSDP + DstInputFileData%RFrlDSDP = SrcInputFileData%RFrlDSDP + DstInputFileData%RFrlUSDmp = SrcInputFileData%RFrlUSDmp + DstInputFileData%RFrlDSDmp = SrcInputFileData%RFrlDSDmp + DstInputFileData%TFrlMod = SrcInputFileData%TFrlMod + DstInputFileData%TFrlSpr = SrcInputFileData%TFrlSpr + DstInputFileData%TFrlDmp = SrcInputFileData%TFrlDmp + DstInputFileData%TFrlCDmp = SrcInputFileData%TFrlCDmp + DstInputFileData%TFrlUSSP = SrcInputFileData%TFrlUSSP + DstInputFileData%TFrlDSSP = SrcInputFileData%TFrlDSSP + DstInputFileData%TFrlUSSpr = SrcInputFileData%TFrlUSSpr + DstInputFileData%TFrlDSSpr = SrcInputFileData%TFrlDSSpr + DstInputFileData%TFrlUSDP = SrcInputFileData%TFrlUSDP + DstInputFileData%TFrlDSDP = SrcInputFileData%TFrlDSDP + DstInputFileData%TFrlUSDmp = SrcInputFileData%TFrlUSDmp + DstInputFileData%TFrlDSDmp = SrcInputFileData%TFrlDSDmp + DstInputFileData%method = SrcInputFileData%method + DstInputFileData%BldNd_NumOuts = SrcInputFileData%BldNd_NumOuts +IF (ALLOCATED(SrcInputFileData%BldNd_OutList)) THEN + i1_l = LBOUND(SrcInputFileData%BldNd_OutList,1) + i1_u = UBOUND(SrcInputFileData%BldNd_OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%BldNd_OutList)) THEN + ALLOCATE(DstInputFileData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BldNd_OutList = SrcInputFileData%BldNd_OutList +ENDIF + DstInputFileData%BldNd_BlOutNd_Str = SrcInputFileData%BldNd_BlOutNd_Str + DstInputFileData%BldNd_BladesOut = SrcInputFileData%BldNd_BladesOut + END SUBROUTINE ED_CopyInputFile + + SUBROUTINE ED_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(ED_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%BlPitch)) THEN + DEALLOCATE(InputFileData%BlPitch) +ENDIF +IF (ALLOCATED(InputFileData%PreCone)) THEN + DEALLOCATE(InputFileData%PreCone) +ENDIF +IF (ALLOCATED(InputFileData%TipMass)) THEN + DEALLOCATE(InputFileData%TipMass) +ENDIF +IF (ALLOCATED(InputFileData%InpBlMesh)) THEN +DO i1 = LBOUND(InputFileData%InpBlMesh,1), UBOUND(InputFileData%InpBlMesh,1) + CALL ED_Destroyblademeshinputdata( InputFileData%InpBlMesh(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputFileData%InpBlMesh) +ENDIF +IF (ALLOCATED(InputFileData%InpBl)) THEN +DO i1 = LBOUND(InputFileData%InpBl,1), UBOUND(InputFileData%InpBl,1) + CALL ED_Destroybladeinputdata( InputFileData%InpBl(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputFileData%InpBl) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF +IF (ALLOCATED(InputFileData%HtFract)) THEN + DEALLOCATE(InputFileData%HtFract) +ENDIF +IF (ALLOCATED(InputFileData%TMassDen)) THEN + DEALLOCATE(InputFileData%TMassDen) +ENDIF +IF (ALLOCATED(InputFileData%TwFAStif)) THEN + DEALLOCATE(InputFileData%TwFAStif) +ENDIF +IF (ALLOCATED(InputFileData%TwSSStif)) THEN + DEALLOCATE(InputFileData%TwSSStif) +ENDIF +IF (ALLOCATED(InputFileData%TwFAM1Sh)) THEN + DEALLOCATE(InputFileData%TwFAM1Sh) +ENDIF +IF (ALLOCATED(InputFileData%TwFAM2Sh)) THEN + DEALLOCATE(InputFileData%TwFAM2Sh) +ENDIF +IF (ALLOCATED(InputFileData%TwSSM1Sh)) THEN + DEALLOCATE(InputFileData%TwSSM1Sh) +ENDIF +IF (ALLOCATED(InputFileData%TwSSM2Sh)) THEN + DEALLOCATE(InputFileData%TwSSM2Sh) +ENDIF +IF (ALLOCATED(InputFileData%TwGJStif)) THEN + DEALLOCATE(InputFileData%TwGJStif) +ENDIF +IF (ALLOCATED(InputFileData%TwEAStif)) THEN + DEALLOCATE(InputFileData%TwEAStif) +ENDIF +IF (ALLOCATED(InputFileData%TwFAIner)) THEN + DEALLOCATE(InputFileData%TwFAIner) +ENDIF +IF (ALLOCATED(InputFileData%TwSSIner)) THEN + DEALLOCATE(InputFileData%TwSSIner) +ENDIF +IF (ALLOCATED(InputFileData%TwFAcgOf)) THEN + DEALLOCATE(InputFileData%TwFAcgOf) +ENDIF +IF (ALLOCATED(InputFileData%TwSScgOf)) THEN + DEALLOCATE(InputFileData%TwSScgOf) +ENDIF +IF (ALLOCATED(InputFileData%BldNd_OutList)) THEN + DEALLOCATE(InputFileData%BldNd_OutList) +ENDIF + END SUBROUTINE ED_DestroyInputFile + + SUBROUTINE ED_PackInputFile( 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(ED_InputFile), 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 = 'ED_PackInputFile' + ! 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 + Db_BufSz = Db_BufSz + 1 ! DT + Re_BufSz = Re_BufSz + 1 ! Gravity + Int_BufSz = Int_BufSz + 1 ! FlapDOF1 + Int_BufSz = Int_BufSz + 1 ! FlapDOF2 + Int_BufSz = Int_BufSz + 1 ! EdgeDOF + Int_BufSz = Int_BufSz + 1 ! TeetDOF + Int_BufSz = Int_BufSz + 1 ! DrTrDOF + Int_BufSz = Int_BufSz + 1 ! GenDOF + Int_BufSz = Int_BufSz + 1 ! YawDOF + Int_BufSz = Int_BufSz + 1 ! TwFADOF1 + Int_BufSz = Int_BufSz + 1 ! TwFADOF2 + Int_BufSz = Int_BufSz + 1 ! TwSSDOF1 + Int_BufSz = Int_BufSz + 1 ! TwSSDOF2 + Int_BufSz = Int_BufSz + 1 ! PtfmSgDOF + Int_BufSz = Int_BufSz + 1 ! PtfmSwDOF + Int_BufSz = Int_BufSz + 1 ! PtfmHvDOF + Int_BufSz = Int_BufSz + 1 ! PtfmRDOF + Int_BufSz = Int_BufSz + 1 ! PtfmPDOF + Int_BufSz = Int_BufSz + 1 ! PtfmYDOF + Re_BufSz = Re_BufSz + 1 ! OoPDefl + Re_BufSz = Re_BufSz + 1 ! IPDefl + Int_BufSz = Int_BufSz + 1 ! BlPitch allocated yes/no + IF ( ALLOCATED(InData%BlPitch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitch) ! BlPitch + END IF + Re_BufSz = Re_BufSz + 1 ! TeetDefl + Db_BufSz = Db_BufSz + 1 ! Azimuth + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Re_BufSz = Re_BufSz + 1 ! NacYaw + Re_BufSz = Re_BufSz + 1 ! TTDspFA + Re_BufSz = Re_BufSz + 1 ! TTDspSS + Re_BufSz = Re_BufSz + 1 ! PtfmSurge + Re_BufSz = Re_BufSz + 1 ! PtfmSway + Re_BufSz = Re_BufSz + 1 ! PtfmHeave + Re_BufSz = Re_BufSz + 1 ! PtfmRoll + Re_BufSz = Re_BufSz + 1 ! PtfmPitch + Re_BufSz = Re_BufSz + 1 ! PtfmYaw + Int_BufSz = Int_BufSz + 1 ! NumBl + Re_BufSz = Re_BufSz + 1 ! TipRad + Re_BufSz = Re_BufSz + 1 ! HubRad + Int_BufSz = Int_BufSz + 1 ! PreCone allocated yes/no + IF ( ALLOCATED(InData%PreCone) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PreCone upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PreCone) ! PreCone + END IF + Re_BufSz = Re_BufSz + 1 ! HubCM + Re_BufSz = Re_BufSz + 1 ! UndSling + Re_BufSz = Re_BufSz + 1 ! Delta3 + Db_BufSz = Db_BufSz + 1 ! AzimB1Up + Re_BufSz = Re_BufSz + 1 ! OverHang + Re_BufSz = Re_BufSz + 1 ! ShftGagL + Re_BufSz = Re_BufSz + 1 ! ShftTilt + Re_BufSz = Re_BufSz + 1 ! NacCMxn + Re_BufSz = Re_BufSz + 1 ! NacCMyn + Re_BufSz = Re_BufSz + 1 ! NacCMzn + Re_BufSz = Re_BufSz + 1 ! NcIMUxn + Re_BufSz = Re_BufSz + 1 ! NcIMUyn + Re_BufSz = Re_BufSz + 1 ! NcIMUzn + Re_BufSz = Re_BufSz + 1 ! Twr2Shft + Re_BufSz = Re_BufSz + 1 ! TowerHt + Re_BufSz = Re_BufSz + 1 ! TowerBsHt + Re_BufSz = Re_BufSz + 1 ! PtfmCMxt + Re_BufSz = Re_BufSz + 1 ! PtfmCMyt + Re_BufSz = Re_BufSz + 1 ! PtfmCMzt + Re_BufSz = Re_BufSz + 1 ! PtfmRefzt + Int_BufSz = Int_BufSz + 1 ! TipMass allocated yes/no + IF ( ALLOCATED(InData%TipMass) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TipMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TipMass) ! TipMass + END IF + Re_BufSz = Re_BufSz + 1 ! HubMass + Re_BufSz = Re_BufSz + 1 ! HubIner + Re_BufSz = Re_BufSz + 1 ! GenIner + Re_BufSz = Re_BufSz + 1 ! NacMass + Re_BufSz = Re_BufSz + 1 ! NacYIner + Re_BufSz = Re_BufSz + 1 ! YawBrMass + Re_BufSz = Re_BufSz + 1 ! PtfmMass + Re_BufSz = Re_BufSz + 1 ! PtfmRIner + Re_BufSz = Re_BufSz + 1 ! PtfmPIner + Re_BufSz = Re_BufSz + 1 ! PtfmYIner + Re_BufSz = Re_BufSz + 1 ! BldNodes + Int_BufSz = Int_BufSz + 1 ! InpBlMesh allocated yes/no + IF ( ALLOCATED(InData%InpBlMesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InpBlMesh upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%InpBlMesh,1), UBOUND(InData%InpBlMesh,1) + Int_BufSz = Int_BufSz + 3 ! InpBlMesh: size of buffers for each call to pack subtype + CALL ED_Packblademeshinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBlMesh(i1), ErrStat2, ErrMsg2, .TRUE. ) ! InpBlMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InpBlMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InpBlMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InpBlMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InpBl allocated yes/no + IF ( ALLOCATED(InData%InpBl) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InpBl upper/lower bounds for each dimension + DO i1 = LBOUND(InData%InpBl,1), UBOUND(InData%InpBl,1) + Int_BufSz = Int_BufSz + 3 ! InpBl: size of buffers for each call to pack subtype + CALL ED_Packbladeinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBl(i1), ErrStat2, ErrMsg2, .TRUE. ) ! InpBl + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InpBl + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InpBl + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InpBl + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! TeetMod + Re_BufSz = Re_BufSz + 1 ! TeetDmpP + Re_BufSz = Re_BufSz + 1 ! TeetDmp + Re_BufSz = Re_BufSz + 1 ! TeetCDmp + Re_BufSz = Re_BufSz + 1 ! TeetSStP + Re_BufSz = Re_BufSz + 1 ! TeetHStP + Re_BufSz = Re_BufSz + 1 ! TeetSSSp + Re_BufSz = Re_BufSz + 1 ! TeetHSSp + Re_BufSz = Re_BufSz + 1 ! GBoxEff + Re_BufSz = Re_BufSz + 1 ! GBRatio + Re_BufSz = Re_BufSz + 1 ! DTTorSpr + Re_BufSz = Re_BufSz + 1 ! DTTorDmp + Int_BufSz = Int_BufSz + 1 ! Furling + Int_BufSz = Int_BufSz + 1 ! TwrNodes + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! OutFile + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Db_BufSz = Db_BufSz + 1 ! Tstart + Int_BufSz = Int_BufSz + 1 ! DecFact + Int_BufSz = Int_BufSz + 1 ! NTwGages + Int_BufSz = Int_BufSz + SIZE(InData%TwrGagNd) ! TwrGagNd + Int_BufSz = Int_BufSz + 1 ! NBlGages + Int_BufSz = Int_BufSz + SIZE(InData%BldGagNd) ! BldGagNd + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + END IF + Int_BufSz = Int_BufSz + 1 ! NTwInpSt + Re_BufSz = Re_BufSz + SIZE(InData%TwrFADmp) ! TwrFADmp + Re_BufSz = Re_BufSz + SIZE(InData%TwrSSDmp) ! TwrSSDmp + Re_BufSz = Re_BufSz + SIZE(InData%FAStTunr) ! FAStTunr + Re_BufSz = Re_BufSz + SIZE(InData%SSStTunr) ! SSStTunr + Int_BufSz = Int_BufSz + 1 ! HtFract allocated yes/no + IF ( ALLOCATED(InData%HtFract) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! HtFract upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HtFract) ! HtFract + END IF + Int_BufSz = Int_BufSz + 1 ! TMassDen allocated yes/no + IF ( ALLOCATED(InData%TMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TMassDen) ! TMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! TwFAStif allocated yes/no + IF ( ALLOCATED(InData%TwFAStif) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwFAStif upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwFAStif) ! TwFAStif + END IF + Int_BufSz = Int_BufSz + 1 ! TwSSStif allocated yes/no + IF ( ALLOCATED(InData%TwSSStif) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwSSStif upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwSSStif) ! TwSSStif + END IF + Int_BufSz = Int_BufSz + 1 ! TwFAM1Sh allocated yes/no + IF ( ALLOCATED(InData%TwFAM1Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwFAM1Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwFAM1Sh) ! TwFAM1Sh + END IF + Int_BufSz = Int_BufSz + 1 ! TwFAM2Sh allocated yes/no + IF ( ALLOCATED(InData%TwFAM2Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwFAM2Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwFAM2Sh) ! TwFAM2Sh + END IF + Int_BufSz = Int_BufSz + 1 ! TwSSM1Sh allocated yes/no + IF ( ALLOCATED(InData%TwSSM1Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwSSM1Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwSSM1Sh) ! TwSSM1Sh + END IF + Int_BufSz = Int_BufSz + 1 ! TwSSM2Sh allocated yes/no + IF ( ALLOCATED(InData%TwSSM2Sh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwSSM2Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwSSM2Sh) ! TwSSM2Sh + END IF + Int_BufSz = Int_BufSz + 1 ! TwGJStif allocated yes/no + IF ( ALLOCATED(InData%TwGJStif) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwGJStif upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwGJStif) ! TwGJStif + END IF + Int_BufSz = Int_BufSz + 1 ! TwEAStif allocated yes/no + IF ( ALLOCATED(InData%TwEAStif) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwEAStif upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwEAStif) ! TwEAStif + END IF + Int_BufSz = Int_BufSz + 1 ! TwFAIner allocated yes/no + IF ( ALLOCATED(InData%TwFAIner) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwFAIner upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwFAIner) ! TwFAIner + END IF + Int_BufSz = Int_BufSz + 1 ! TwSSIner allocated yes/no + IF ( ALLOCATED(InData%TwSSIner) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwSSIner upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwSSIner) ! TwSSIner + END IF + Int_BufSz = Int_BufSz + 1 ! TwFAcgOf allocated yes/no + IF ( ALLOCATED(InData%TwFAcgOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwFAcgOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwFAcgOf) ! TwFAcgOf + END IF + Int_BufSz = Int_BufSz + 1 ! TwSScgOf allocated yes/no + IF ( ALLOCATED(InData%TwSScgOf) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TwSScgOf upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwSScgOf) ! TwSScgOf + END IF + Int_BufSz = Int_BufSz + 1 ! RFrlDOF + Int_BufSz = Int_BufSz + 1 ! TFrlDOF + Re_BufSz = Re_BufSz + 1 ! RotFurl + Re_BufSz = Re_BufSz + 1 ! TailFurl + Re_BufSz = Re_BufSz + 1 ! Yaw2Shft + Re_BufSz = Re_BufSz + 1 ! ShftSkew + Re_BufSz = Re_BufSz + 1 ! RFrlCMxn + Re_BufSz = Re_BufSz + 1 ! RFrlCMyn + Re_BufSz = Re_BufSz + 1 ! RFrlCMzn + Re_BufSz = Re_BufSz + 1 ! BoomCMxn + Re_BufSz = Re_BufSz + 1 ! BoomCMyn + Re_BufSz = Re_BufSz + 1 ! BoomCMzn + Re_BufSz = Re_BufSz + 1 ! TFinCMxn + Re_BufSz = Re_BufSz + 1 ! TFinCMyn + Re_BufSz = Re_BufSz + 1 ! TFinCMzn + Re_BufSz = Re_BufSz + 1 ! TFinCPxn + Re_BufSz = Re_BufSz + 1 ! TFinCPyn + Re_BufSz = Re_BufSz + 1 ! TFinCPzn + Re_BufSz = Re_BufSz + 1 ! TFinSkew + Re_BufSz = Re_BufSz + 1 ! TFinTilt + Re_BufSz = Re_BufSz + 1 ! TFinBank + Re_BufSz = Re_BufSz + 1 ! RFrlPntxn + Re_BufSz = Re_BufSz + 1 ! RFrlPntyn + Re_BufSz = Re_BufSz + 1 ! RFrlPntzn + Re_BufSz = Re_BufSz + 1 ! RFrlSkew + Re_BufSz = Re_BufSz + 1 ! RFrlTilt + Re_BufSz = Re_BufSz + 1 ! TFrlPntxn + Re_BufSz = Re_BufSz + 1 ! TFrlPntyn + Re_BufSz = Re_BufSz + 1 ! TFrlPntzn + Re_BufSz = Re_BufSz + 1 ! TFrlSkew + Re_BufSz = Re_BufSz + 1 ! TFrlTilt + Re_BufSz = Re_BufSz + 1 ! RFrlMass + Re_BufSz = Re_BufSz + 1 ! BoomMass + Re_BufSz = Re_BufSz + 1 ! TFinMass + Re_BufSz = Re_BufSz + 1 ! RFrlIner + Re_BufSz = Re_BufSz + 1 ! TFrlIner + Int_BufSz = Int_BufSz + 1 ! RFrlMod + Re_BufSz = Re_BufSz + 1 ! RFrlSpr + Re_BufSz = Re_BufSz + 1 ! RFrlDmp + Re_BufSz = Re_BufSz + 1 ! RFrlCDmp + Re_BufSz = Re_BufSz + 1 ! RFrlUSSP + Re_BufSz = Re_BufSz + 1 ! RFrlDSSP + Re_BufSz = Re_BufSz + 1 ! RFrlUSSpr + Re_BufSz = Re_BufSz + 1 ! RFrlDSSpr + Re_BufSz = Re_BufSz + 1 ! RFrlUSDP + Re_BufSz = Re_BufSz + 1 ! RFrlDSDP + Re_BufSz = Re_BufSz + 1 ! RFrlUSDmp + Re_BufSz = Re_BufSz + 1 ! RFrlDSDmp + Int_BufSz = Int_BufSz + 1 ! TFrlMod + Re_BufSz = Re_BufSz + 1 ! TFrlSpr + Re_BufSz = Re_BufSz + 1 ! TFrlDmp + Re_BufSz = Re_BufSz + 1 ! TFrlCDmp + Re_BufSz = Re_BufSz + 1 ! TFrlUSSP + Re_BufSz = Re_BufSz + 1 ! TFrlDSSP + Re_BufSz = Re_BufSz + 1 ! TFrlUSSpr + Re_BufSz = Re_BufSz + 1 ! TFrlDSSpr + Re_BufSz = Re_BufSz + 1 ! TFrlUSDP + Re_BufSz = Re_BufSz + 1 ! TFrlDSDP + Re_BufSz = Re_BufSz + 1 ! TFrlUSDmp + Re_BufSz = Re_BufSz + 1 ! TFrlDSDmp + Int_BufSz = Int_BufSz + 1 ! method + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutList allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BldNd_OutList)*LEN(InData%BldNd_OutList) ! BldNd_OutList + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%BldNd_BlOutNd_Str) ! BldNd_BlOutNd_Str + Int_BufSz = Int_BufSz + 1 ! BldNd_BladesOut + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FlapDOF1, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FlapDOF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%EdgeDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TeetDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DrTrDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%YawDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwFADOF1, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwFADOF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwSSDOF1, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TwSSDOF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%OoPDefl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%IPDefl + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlPitch) ) 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%BlPitch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitch,1), UBOUND(InData%BlPitch,1) + ReKiBuf(Re_Xferred) = InData%BlPitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TeetDefl + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Azimuth + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TTDspFA + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TTDspSS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmSurge + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmSway + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmHeave + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRoll + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmPitch + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmYaw + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TipRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubRad + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PreCone) ) 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%PreCone,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PreCone,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PreCone,1), UBOUND(InData%PreCone,1) + ReKiBuf(Re_Xferred) = InData%PreCone(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%HubCM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UndSling + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Delta3 + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%AzimB1Up + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%OverHang + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShftGagL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShftTilt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMUxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMUyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMUzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Twr2Shft + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerBsHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCMxt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCMyt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCMzt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRefzt + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TipMass) ) 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%TipMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TipMass,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TipMass,1), UBOUND(InData%TipMass,1) + ReKiBuf(Re_Xferred) = InData%TipMass(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%HubMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmPIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmYIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BldNodes + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%InpBlMesh) ) 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%InpBlMesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpBlMesh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InpBlMesh,1), UBOUND(InData%InpBlMesh,1) + CALL ED_Packblademeshinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBlMesh(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpBlMesh + 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%InpBl) ) 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%InpBl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpBl,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InpBl,1), UBOUND(InData%InpBl,1) + CALL ED_Packbladeinputdata( Re_Buf, Db_Buf, Int_Buf, InData%InpBl(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpBl + 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 + IntKiBuf(Int_Xferred) = InData%TeetMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetDmpP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetSStP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetHStP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetSSSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetHSSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GBoxEff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GBRatio + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DTTorSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DTTorDmp + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Furling, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%Tstart + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DecFact + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NTwGages + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TwrGagNd,1), UBOUND(InData%TwrGagNd,1) + IntKiBuf(Int_Xferred) = InData%TwrGagNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NBlGages + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%BldGagNd,1), UBOUND(InData%BldGagNd,1) + IntKiBuf(Int_Xferred) = InData%BldGagNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NTwInpSt + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TwrFADmp,1), UBOUND(InData%TwrFADmp,1) + ReKiBuf(Re_Xferred) = InData%TwrFADmp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%TwrSSDmp,1), UBOUND(InData%TwrSSDmp,1) + ReKiBuf(Re_Xferred) = InData%TwrSSDmp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FAStTunr,1), UBOUND(InData%FAStTunr,1) + ReKiBuf(Re_Xferred) = InData%FAStTunr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SSStTunr,1), UBOUND(InData%SSStTunr,1) + ReKiBuf(Re_Xferred) = InData%SSStTunr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%HtFract) ) 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%HtFract,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HtFract,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%HtFract,1), UBOUND(InData%HtFract,1) + ReKiBuf(Re_Xferred) = InData%HtFract(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TMassDen) ) 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%TMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TMassDen,1), UBOUND(InData%TMassDen,1) + ReKiBuf(Re_Xferred) = InData%TMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwFAStif) ) 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%TwFAStif,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwFAStif,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwFAStif,1), UBOUND(InData%TwFAStif,1) + ReKiBuf(Re_Xferred) = InData%TwFAStif(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwSSStif) ) 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%TwSSStif,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwSSStif,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwSSStif,1), UBOUND(InData%TwSSStif,1) + ReKiBuf(Re_Xferred) = InData%TwSSStif(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwFAM1Sh) ) 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%TwFAM1Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwFAM1Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwFAM1Sh,1), UBOUND(InData%TwFAM1Sh,1) + ReKiBuf(Re_Xferred) = InData%TwFAM1Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwFAM2Sh) ) 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%TwFAM2Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwFAM2Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwFAM2Sh,1), UBOUND(InData%TwFAM2Sh,1) + ReKiBuf(Re_Xferred) = InData%TwFAM2Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwSSM1Sh) ) 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%TwSSM1Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwSSM1Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwSSM1Sh,1), UBOUND(InData%TwSSM1Sh,1) + ReKiBuf(Re_Xferred) = InData%TwSSM1Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwSSM2Sh) ) 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%TwSSM2Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwSSM2Sh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwSSM2Sh,1), UBOUND(InData%TwSSM2Sh,1) + ReKiBuf(Re_Xferred) = InData%TwSSM2Sh(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwGJStif) ) 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%TwGJStif,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwGJStif,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwGJStif,1), UBOUND(InData%TwGJStif,1) + ReKiBuf(Re_Xferred) = InData%TwGJStif(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwEAStif) ) 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%TwEAStif,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwEAStif,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwEAStif,1), UBOUND(InData%TwEAStif,1) + ReKiBuf(Re_Xferred) = InData%TwEAStif(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwFAIner) ) 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%TwFAIner,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwFAIner,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwFAIner,1), UBOUND(InData%TwFAIner,1) + ReKiBuf(Re_Xferred) = InData%TwFAIner(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwSSIner) ) 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%TwSSIner,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwSSIner,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwSSIner,1), UBOUND(InData%TwSSIner,1) + ReKiBuf(Re_Xferred) = InData%TwSSIner(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwFAcgOf) ) 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%TwFAcgOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwFAcgOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwFAcgOf,1), UBOUND(InData%TwFAcgOf,1) + ReKiBuf(Re_Xferred) = InData%TwFAcgOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwSScgOf) ) 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%TwSScgOf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwSScgOf,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TwSScgOf,1), UBOUND(InData%TwSScgOf,1) + ReKiBuf(Re_Xferred) = InData%TwSScgOf(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%RFrlDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TFrlDOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotFurl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TailFurl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Yaw2Shft + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShftSkew + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlCMxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlCMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlCMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BoomCMxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BoomCMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BoomCMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCMxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCPxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCPyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinCPzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinSkew + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinTilt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinBank + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlSkew + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlTilt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlSkew + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlTilt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BoomMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFinMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlIner + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RFrlMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSDmp + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TFrlMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSDmp + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%method + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_OutList) ) 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%BldNd_OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutList,1), UBOUND(InData%BldNd_OutList,1) + DO I = 1, LEN(InData%BldNd_OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%BldNd_BlOutNd_Str) + IntKiBuf(Int_Xferred) = ICHAR(InData%BldNd_BlOutNd_Str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%BldNd_BladesOut + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_PackInputFile + + SUBROUTINE ED_UnPackInputFile( 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(ED_InputFile), 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 = 'ED_UnPackInputFile' + ! 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FlapDOF1 = TRANSFER(IntKiBuf(Int_Xferred), OutData%FlapDOF1) + Int_Xferred = Int_Xferred + 1 + OutData%FlapDOF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%FlapDOF2) + Int_Xferred = Int_Xferred + 1 + OutData%EdgeDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%EdgeDOF) + Int_Xferred = Int_Xferred + 1 + OutData%TeetDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TeetDOF) + Int_Xferred = Int_Xferred + 1 + OutData%DrTrDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%DrTrDOF) + Int_Xferred = Int_Xferred + 1 + OutData%GenDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenDOF) + Int_Xferred = Int_Xferred + 1 + OutData%YawDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%YawDOF) + Int_Xferred = Int_Xferred + 1 + OutData%TwFADOF1 = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwFADOF1) + Int_Xferred = Int_Xferred + 1 + OutData%TwFADOF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwFADOF2) + Int_Xferred = Int_Xferred + 1 + OutData%TwSSDOF1 = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwSSDOF1) + Int_Xferred = Int_Xferred + 1 + OutData%TwSSDOF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%TwSSDOF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmSgDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgDOF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmSwDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwDOF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmHvDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvDOF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmRDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRDOF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmPDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPDOF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmYDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYDOF) + Int_Xferred = Int_Xferred + 1 + OutData%OoPDefl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%IPDefl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitch 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%BlPitch)) DEALLOCATE(OutData%BlPitch) + ALLOCATE(OutData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitch,1), UBOUND(OutData%BlPitch,1) + OutData%BlPitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%TeetDefl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Azimuth = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacYaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TTDspFA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TTDspSS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmSurge = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmSway = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmHeave = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmRoll = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmPitch = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmYaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TipRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PreCone 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%PreCone)) DEALLOCATE(OutData%PreCone) + ALLOCATE(OutData%PreCone(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PreCone.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PreCone,1), UBOUND(OutData%PreCone,1) + OutData%PreCone(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%HubCM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UndSling = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Delta3 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AzimB1Up = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%OverHang = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShftGagL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShftTilt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMUxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMUyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMUzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Twr2Shft = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerBsHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCMxt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCMyt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCMzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmRefzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TipMass 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%TipMass)) DEALLOCATE(OutData%TipMass) + ALLOCATE(OutData%TipMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TipMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TipMass,1), UBOUND(OutData%TipMass,1) + OutData%TipMass(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%HubMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacYIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmRIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmPIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmYIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BldNodes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpBlMesh 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%InpBlMesh)) DEALLOCATE(OutData%InpBlMesh) + ALLOCATE(OutData%InpBlMesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InpBlMesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InpBlMesh,1), UBOUND(OutData%InpBlMesh,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 ED_Unpackblademeshinputdata( Re_Buf, Db_Buf, Int_Buf, OutData%InpBlMesh(i1), ErrStat2, ErrMsg2 ) ! InpBlMesh + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpBl 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%InpBl)) DEALLOCATE(OutData%InpBl) + ALLOCATE(OutData%InpBl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InpBl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InpBl,1), UBOUND(OutData%InpBl,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 ED_Unpackbladeinputdata( Re_Buf, Db_Buf, Int_Buf, OutData%InpBl(i1), ErrStat2, ErrMsg2 ) ! InpBl + 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 DO + END IF + OutData%TeetMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TeetDmpP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetSStP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetHStP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetSSSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetHSSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GBoxEff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GBRatio = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DTTorSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DTTorDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Furling = TRANSFER(IntKiBuf(Int_Xferred), OutData%Furling) + Int_Xferred = Int_Xferred + 1 + OutData%TwrNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%OutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Tstart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DecFact = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NTwGages = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TwrGagNd,1) + i1_u = UBOUND(OutData%TwrGagNd,1) + DO i1 = LBOUND(OutData%TwrGagNd,1), UBOUND(OutData%TwrGagNd,1) + OutData%TwrGagNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NBlGages = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%BldGagNd,1) + i1_u = UBOUND(OutData%BldGagNd,1) + DO i1 = LBOUND(OutData%BldGagNd,1), UBOUND(OutData%BldGagNd,1) + OutData%BldGagNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%NTwInpSt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TwrFADmp,1) + i1_u = UBOUND(OutData%TwrFADmp,1) + DO i1 = LBOUND(OutData%TwrFADmp,1), UBOUND(OutData%TwrFADmp,1) + OutData%TwrFADmp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%TwrSSDmp,1) + i1_u = UBOUND(OutData%TwrSSDmp,1) + DO i1 = LBOUND(OutData%TwrSSDmp,1), UBOUND(OutData%TwrSSDmp,1) + OutData%TwrSSDmp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FAStTunr,1) + i1_u = UBOUND(OutData%FAStTunr,1) + DO i1 = LBOUND(OutData%FAStTunr,1), UBOUND(OutData%FAStTunr,1) + OutData%FAStTunr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SSStTunr,1) + i1_u = UBOUND(OutData%SSStTunr,1) + DO i1 = LBOUND(OutData%SSStTunr,1), UBOUND(OutData%SSStTunr,1) + OutData%SSStTunr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HtFract 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%HtFract)) DEALLOCATE(OutData%HtFract) + ALLOCATE(OutData%HtFract(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HtFract.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%HtFract,1), UBOUND(OutData%HtFract,1) + OutData%HtFract(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TMassDen 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%TMassDen)) DEALLOCATE(OutData%TMassDen) + ALLOCATE(OutData%TMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TMassDen,1), UBOUND(OutData%TMassDen,1) + OutData%TMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwFAStif 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%TwFAStif)) DEALLOCATE(OutData%TwFAStif) + ALLOCATE(OutData%TwFAStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwFAStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwFAStif,1), UBOUND(OutData%TwFAStif,1) + OutData%TwFAStif(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwSSStif 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%TwSSStif)) DEALLOCATE(OutData%TwSSStif) + ALLOCATE(OutData%TwSSStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwSSStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwSSStif,1), UBOUND(OutData%TwSSStif,1) + OutData%TwSSStif(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwFAM1Sh 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%TwFAM1Sh)) DEALLOCATE(OutData%TwFAM1Sh) + ALLOCATE(OutData%TwFAM1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwFAM1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwFAM1Sh,1), UBOUND(OutData%TwFAM1Sh,1) + OutData%TwFAM1Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwFAM2Sh 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%TwFAM2Sh)) DEALLOCATE(OutData%TwFAM2Sh) + ALLOCATE(OutData%TwFAM2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwFAM2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwFAM2Sh,1), UBOUND(OutData%TwFAM2Sh,1) + OutData%TwFAM2Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwSSM1Sh 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%TwSSM1Sh)) DEALLOCATE(OutData%TwSSM1Sh) + ALLOCATE(OutData%TwSSM1Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwSSM1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwSSM1Sh,1), UBOUND(OutData%TwSSM1Sh,1) + OutData%TwSSM1Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwSSM2Sh 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%TwSSM2Sh)) DEALLOCATE(OutData%TwSSM2Sh) + ALLOCATE(OutData%TwSSM2Sh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwSSM2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwSSM2Sh,1), UBOUND(OutData%TwSSM2Sh,1) + OutData%TwSSM2Sh(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwGJStif 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%TwGJStif)) DEALLOCATE(OutData%TwGJStif) + ALLOCATE(OutData%TwGJStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwGJStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwGJStif,1), UBOUND(OutData%TwGJStif,1) + OutData%TwGJStif(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwEAStif 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%TwEAStif)) DEALLOCATE(OutData%TwEAStif) + ALLOCATE(OutData%TwEAStif(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwEAStif.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwEAStif,1), UBOUND(OutData%TwEAStif,1) + OutData%TwEAStif(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwFAIner 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%TwFAIner)) DEALLOCATE(OutData%TwFAIner) + ALLOCATE(OutData%TwFAIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwFAIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwFAIner,1), UBOUND(OutData%TwFAIner,1) + OutData%TwFAIner(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwSSIner 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%TwSSIner)) DEALLOCATE(OutData%TwSSIner) + ALLOCATE(OutData%TwSSIner(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwSSIner.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwSSIner,1), UBOUND(OutData%TwSSIner,1) + OutData%TwSSIner(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwFAcgOf 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%TwFAcgOf)) DEALLOCATE(OutData%TwFAcgOf) + ALLOCATE(OutData%TwFAcgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwFAcgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwFAcgOf,1), UBOUND(OutData%TwFAcgOf,1) + OutData%TwFAcgOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwSScgOf 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%TwSScgOf)) DEALLOCATE(OutData%TwSScgOf) + ALLOCATE(OutData%TwSScgOf(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TwSScgOf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TwSScgOf,1), UBOUND(OutData%TwSScgOf,1) + OutData%TwSScgOf(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%RFrlDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%RFrlDOF) + Int_Xferred = Int_Xferred + 1 + OutData%TFrlDOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TFrlDOF) + Int_Xferred = Int_Xferred + 1 + OutData%RotFurl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TailFurl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Yaw2Shft = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShftSkew = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlCMxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlCMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlCMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BoomCMxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BoomCMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BoomCMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCMxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCPxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCPyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinCPzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinSkew = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinTilt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinBank = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlSkew = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlTilt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlPntxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlPntyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlPntzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlSkew = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlTilt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BoomMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFinMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RFrlSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TFrlSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%method = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutList 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%BldNd_OutList)) DEALLOCATE(OutData%BldNd_OutList) + ALLOCATE(OutData%BldNd_OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutList,1), UBOUND(OutData%BldNd_OutList,1) + DO I = 1, LEN(OutData%BldNd_OutList) + OutData%BldNd_OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%BldNd_BlOutNd_Str) + OutData%BldNd_BlOutNd_Str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%BldNd_BladesOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_UnPackInputFile + + SUBROUTINE ED_CopyCoordSys( SrcCoordSysData, DstCoordSysData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_CoordSys), INTENT(IN) :: SrcCoordSysData + TYPE(ED_CoordSys), INTENT(INOUT) :: DstCoordSysData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyCoordSys' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCoordSysData%a1 = SrcCoordSysData%a1 + DstCoordSysData%a2 = SrcCoordSysData%a2 + DstCoordSysData%a3 = SrcCoordSysData%a3 + DstCoordSysData%b1 = SrcCoordSysData%b1 + DstCoordSysData%b2 = SrcCoordSysData%b2 + DstCoordSysData%b3 = SrcCoordSysData%b3 + DstCoordSysData%c1 = SrcCoordSysData%c1 + DstCoordSysData%c2 = SrcCoordSysData%c2 + DstCoordSysData%c3 = SrcCoordSysData%c3 + DstCoordSysData%d1 = SrcCoordSysData%d1 + DstCoordSysData%d2 = SrcCoordSysData%d2 + DstCoordSysData%d3 = SrcCoordSysData%d3 + DstCoordSysData%e1 = SrcCoordSysData%e1 + DstCoordSysData%e2 = SrcCoordSysData%e2 + DstCoordSysData%e3 = SrcCoordSysData%e3 + DstCoordSysData%f1 = SrcCoordSysData%f1 + DstCoordSysData%f2 = SrcCoordSysData%f2 + DstCoordSysData%f3 = SrcCoordSysData%f3 + DstCoordSysData%g1 = SrcCoordSysData%g1 + DstCoordSysData%g2 = SrcCoordSysData%g2 + DstCoordSysData%g3 = SrcCoordSysData%g3 +IF (ALLOCATED(SrcCoordSysData%i1)) THEN + i1_l = LBOUND(SrcCoordSysData%i1,1) + i1_u = UBOUND(SrcCoordSysData%i1,1) + i2_l = LBOUND(SrcCoordSysData%i1,2) + i2_u = UBOUND(SrcCoordSysData%i1,2) + IF (.NOT. ALLOCATED(DstCoordSysData%i1)) THEN + ALLOCATE(DstCoordSysData%i1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%i1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%i1 = SrcCoordSysData%i1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%i2)) THEN + i1_l = LBOUND(SrcCoordSysData%i2,1) + i1_u = UBOUND(SrcCoordSysData%i2,1) + i2_l = LBOUND(SrcCoordSysData%i2,2) + i2_u = UBOUND(SrcCoordSysData%i2,2) + IF (.NOT. ALLOCATED(DstCoordSysData%i2)) THEN + ALLOCATE(DstCoordSysData%i2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%i2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%i2 = SrcCoordSysData%i2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%i3)) THEN + i1_l = LBOUND(SrcCoordSysData%i3,1) + i1_u = UBOUND(SrcCoordSysData%i3,1) + i2_l = LBOUND(SrcCoordSysData%i3,2) + i2_u = UBOUND(SrcCoordSysData%i3,2) + IF (.NOT. ALLOCATED(DstCoordSysData%i3)) THEN + ALLOCATE(DstCoordSysData%i3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%i3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%i3 = SrcCoordSysData%i3 +ENDIF +IF (ALLOCATED(SrcCoordSysData%j1)) THEN + i1_l = LBOUND(SrcCoordSysData%j1,1) + i1_u = UBOUND(SrcCoordSysData%j1,1) + i2_l = LBOUND(SrcCoordSysData%j1,2) + i2_u = UBOUND(SrcCoordSysData%j1,2) + IF (.NOT. ALLOCATED(DstCoordSysData%j1)) THEN + ALLOCATE(DstCoordSysData%j1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%j1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%j1 = SrcCoordSysData%j1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%j2)) THEN + i1_l = LBOUND(SrcCoordSysData%j2,1) + i1_u = UBOUND(SrcCoordSysData%j2,1) + i2_l = LBOUND(SrcCoordSysData%j2,2) + i2_u = UBOUND(SrcCoordSysData%j2,2) + IF (.NOT. ALLOCATED(DstCoordSysData%j2)) THEN + ALLOCATE(DstCoordSysData%j2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%j2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%j2 = SrcCoordSysData%j2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%j3)) THEN + i1_l = LBOUND(SrcCoordSysData%j3,1) + i1_u = UBOUND(SrcCoordSysData%j3,1) + i2_l = LBOUND(SrcCoordSysData%j3,2) + i2_u = UBOUND(SrcCoordSysData%j3,2) + IF (.NOT. ALLOCATED(DstCoordSysData%j3)) THEN + ALLOCATE(DstCoordSysData%j3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%j3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%j3 = SrcCoordSysData%j3 +ENDIF +IF (ALLOCATED(SrcCoordSysData%m1)) THEN + i1_l = LBOUND(SrcCoordSysData%m1,1) + i1_u = UBOUND(SrcCoordSysData%m1,1) + i2_l = LBOUND(SrcCoordSysData%m1,2) + i2_u = UBOUND(SrcCoordSysData%m1,2) + i3_l = LBOUND(SrcCoordSysData%m1,3) + i3_u = UBOUND(SrcCoordSysData%m1,3) + IF (.NOT. ALLOCATED(DstCoordSysData%m1)) THEN + ALLOCATE(DstCoordSysData%m1(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%m1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%m1 = SrcCoordSysData%m1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%m2)) THEN + i1_l = LBOUND(SrcCoordSysData%m2,1) + i1_u = UBOUND(SrcCoordSysData%m2,1) + i2_l = LBOUND(SrcCoordSysData%m2,2) + i2_u = UBOUND(SrcCoordSysData%m2,2) + i3_l = LBOUND(SrcCoordSysData%m2,3) + i3_u = UBOUND(SrcCoordSysData%m2,3) + IF (.NOT. ALLOCATED(DstCoordSysData%m2)) THEN + ALLOCATE(DstCoordSysData%m2(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%m2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%m2 = SrcCoordSysData%m2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%m3)) THEN + i1_l = LBOUND(SrcCoordSysData%m3,1) + i1_u = UBOUND(SrcCoordSysData%m3,1) + i2_l = LBOUND(SrcCoordSysData%m3,2) + i2_u = UBOUND(SrcCoordSysData%m3,2) + i3_l = LBOUND(SrcCoordSysData%m3,3) + i3_u = UBOUND(SrcCoordSysData%m3,3) + IF (.NOT. ALLOCATED(DstCoordSysData%m3)) THEN + ALLOCATE(DstCoordSysData%m3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%m3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%m3 = SrcCoordSysData%m3 +ENDIF +IF (ALLOCATED(SrcCoordSysData%n1)) THEN + i1_l = LBOUND(SrcCoordSysData%n1,1) + i1_u = UBOUND(SrcCoordSysData%n1,1) + i2_l = LBOUND(SrcCoordSysData%n1,2) + i2_u = UBOUND(SrcCoordSysData%n1,2) + i3_l = LBOUND(SrcCoordSysData%n1,3) + i3_u = UBOUND(SrcCoordSysData%n1,3) + IF (.NOT. ALLOCATED(DstCoordSysData%n1)) THEN + ALLOCATE(DstCoordSysData%n1(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%n1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%n1 = SrcCoordSysData%n1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%n2)) THEN + i1_l = LBOUND(SrcCoordSysData%n2,1) + i1_u = UBOUND(SrcCoordSysData%n2,1) + i2_l = LBOUND(SrcCoordSysData%n2,2) + i2_u = UBOUND(SrcCoordSysData%n2,2) + i3_l = LBOUND(SrcCoordSysData%n2,3) + i3_u = UBOUND(SrcCoordSysData%n2,3) + IF (.NOT. ALLOCATED(DstCoordSysData%n2)) THEN + ALLOCATE(DstCoordSysData%n2(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%n2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%n2 = SrcCoordSysData%n2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%n3)) THEN + i1_l = LBOUND(SrcCoordSysData%n3,1) + i1_u = UBOUND(SrcCoordSysData%n3,1) + i2_l = LBOUND(SrcCoordSysData%n3,2) + i2_u = UBOUND(SrcCoordSysData%n3,2) + i3_l = LBOUND(SrcCoordSysData%n3,3) + i3_u = UBOUND(SrcCoordSysData%n3,3) + IF (.NOT. ALLOCATED(DstCoordSysData%n3)) THEN + ALLOCATE(DstCoordSysData%n3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%n3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%n3 = SrcCoordSysData%n3 +ENDIF + DstCoordSysData%p1 = SrcCoordSysData%p1 + DstCoordSysData%p2 = SrcCoordSysData%p2 + DstCoordSysData%p3 = SrcCoordSysData%p3 + DstCoordSysData%rf1 = SrcCoordSysData%rf1 + DstCoordSysData%rf2 = SrcCoordSysData%rf2 + DstCoordSysData%rf3 = SrcCoordSysData%rf3 + DstCoordSysData%rfa = SrcCoordSysData%rfa +IF (ALLOCATED(SrcCoordSysData%t1)) THEN + i1_l = LBOUND(SrcCoordSysData%t1,1) + i1_u = UBOUND(SrcCoordSysData%t1,1) + i2_l = LBOUND(SrcCoordSysData%t1,2) + i2_u = UBOUND(SrcCoordSysData%t1,2) + IF (.NOT. ALLOCATED(DstCoordSysData%t1)) THEN + ALLOCATE(DstCoordSysData%t1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%t1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%t1 = SrcCoordSysData%t1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%t2)) THEN + i1_l = LBOUND(SrcCoordSysData%t2,1) + i1_u = UBOUND(SrcCoordSysData%t2,1) + i2_l = LBOUND(SrcCoordSysData%t2,2) + i2_u = UBOUND(SrcCoordSysData%t2,2) + IF (.NOT. ALLOCATED(DstCoordSysData%t2)) THEN + ALLOCATE(DstCoordSysData%t2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%t2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%t2 = SrcCoordSysData%t2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%t3)) THEN + i1_l = LBOUND(SrcCoordSysData%t3,1) + i1_u = UBOUND(SrcCoordSysData%t3,1) + i2_l = LBOUND(SrcCoordSysData%t3,2) + i2_u = UBOUND(SrcCoordSysData%t3,2) + IF (.NOT. ALLOCATED(DstCoordSysData%t3)) THEN + ALLOCATE(DstCoordSysData%t3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%t3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%t3 = SrcCoordSysData%t3 +ENDIF +IF (ALLOCATED(SrcCoordSysData%te1)) THEN + i1_l = LBOUND(SrcCoordSysData%te1,1) + i1_u = UBOUND(SrcCoordSysData%te1,1) + i2_l = LBOUND(SrcCoordSysData%te1,2) + i2_u = UBOUND(SrcCoordSysData%te1,2) + i3_l = LBOUND(SrcCoordSysData%te1,3) + i3_u = UBOUND(SrcCoordSysData%te1,3) + IF (.NOT. ALLOCATED(DstCoordSysData%te1)) THEN + ALLOCATE(DstCoordSysData%te1(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%te1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%te1 = SrcCoordSysData%te1 +ENDIF +IF (ALLOCATED(SrcCoordSysData%te2)) THEN + i1_l = LBOUND(SrcCoordSysData%te2,1) + i1_u = UBOUND(SrcCoordSysData%te2,1) + i2_l = LBOUND(SrcCoordSysData%te2,2) + i2_u = UBOUND(SrcCoordSysData%te2,2) + i3_l = LBOUND(SrcCoordSysData%te2,3) + i3_u = UBOUND(SrcCoordSysData%te2,3) + IF (.NOT. ALLOCATED(DstCoordSysData%te2)) THEN + ALLOCATE(DstCoordSysData%te2(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%te2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%te2 = SrcCoordSysData%te2 +ENDIF +IF (ALLOCATED(SrcCoordSysData%te3)) THEN + i1_l = LBOUND(SrcCoordSysData%te3,1) + i1_u = UBOUND(SrcCoordSysData%te3,1) + i2_l = LBOUND(SrcCoordSysData%te3,2) + i2_u = UBOUND(SrcCoordSysData%te3,2) + i3_l = LBOUND(SrcCoordSysData%te3,3) + i3_u = UBOUND(SrcCoordSysData%te3,3) + IF (.NOT. ALLOCATED(DstCoordSysData%te3)) THEN + ALLOCATE(DstCoordSysData%te3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCoordSysData%te3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCoordSysData%te3 = SrcCoordSysData%te3 +ENDIF + DstCoordSysData%tf1 = SrcCoordSysData%tf1 + DstCoordSysData%tf2 = SrcCoordSysData%tf2 + DstCoordSysData%tf3 = SrcCoordSysData%tf3 + DstCoordSysData%tfa = SrcCoordSysData%tfa + DstCoordSysData%z1 = SrcCoordSysData%z1 + DstCoordSysData%z2 = SrcCoordSysData%z2 + DstCoordSysData%z3 = SrcCoordSysData%z3 + END SUBROUTINE ED_CopyCoordSys + + SUBROUTINE ED_DestroyCoordSys( CoordSysData, ErrStat, ErrMsg ) + TYPE(ED_CoordSys), INTENT(INOUT) :: CoordSysData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyCoordSys' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(CoordSysData%i1)) THEN + DEALLOCATE(CoordSysData%i1) +ENDIF +IF (ALLOCATED(CoordSysData%i2)) THEN + DEALLOCATE(CoordSysData%i2) +ENDIF +IF (ALLOCATED(CoordSysData%i3)) THEN + DEALLOCATE(CoordSysData%i3) +ENDIF +IF (ALLOCATED(CoordSysData%j1)) THEN + DEALLOCATE(CoordSysData%j1) +ENDIF +IF (ALLOCATED(CoordSysData%j2)) THEN + DEALLOCATE(CoordSysData%j2) +ENDIF +IF (ALLOCATED(CoordSysData%j3)) THEN + DEALLOCATE(CoordSysData%j3) +ENDIF +IF (ALLOCATED(CoordSysData%m1)) THEN + DEALLOCATE(CoordSysData%m1) +ENDIF +IF (ALLOCATED(CoordSysData%m2)) THEN + DEALLOCATE(CoordSysData%m2) +ENDIF +IF (ALLOCATED(CoordSysData%m3)) THEN + DEALLOCATE(CoordSysData%m3) +ENDIF +IF (ALLOCATED(CoordSysData%n1)) THEN + DEALLOCATE(CoordSysData%n1) +ENDIF +IF (ALLOCATED(CoordSysData%n2)) THEN + DEALLOCATE(CoordSysData%n2) +ENDIF +IF (ALLOCATED(CoordSysData%n3)) THEN + DEALLOCATE(CoordSysData%n3) +ENDIF +IF (ALLOCATED(CoordSysData%t1)) THEN + DEALLOCATE(CoordSysData%t1) +ENDIF +IF (ALLOCATED(CoordSysData%t2)) THEN + DEALLOCATE(CoordSysData%t2) +ENDIF +IF (ALLOCATED(CoordSysData%t3)) THEN + DEALLOCATE(CoordSysData%t3) +ENDIF +IF (ALLOCATED(CoordSysData%te1)) THEN + DEALLOCATE(CoordSysData%te1) +ENDIF +IF (ALLOCATED(CoordSysData%te2)) THEN + DEALLOCATE(CoordSysData%te2) +ENDIF +IF (ALLOCATED(CoordSysData%te3)) THEN + DEALLOCATE(CoordSysData%te3) +ENDIF + END SUBROUTINE ED_DestroyCoordSys + + SUBROUTINE ED_PackCoordSys( 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(ED_CoordSys), 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 = 'ED_PackCoordSys' + ! 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 + Db_BufSz = Db_BufSz + SIZE(InData%a1) ! a1 + Db_BufSz = Db_BufSz + SIZE(InData%a2) ! a2 + Db_BufSz = Db_BufSz + SIZE(InData%a3) ! a3 + Db_BufSz = Db_BufSz + SIZE(InData%b1) ! b1 + Db_BufSz = Db_BufSz + SIZE(InData%b2) ! b2 + Db_BufSz = Db_BufSz + SIZE(InData%b3) ! b3 + Db_BufSz = Db_BufSz + SIZE(InData%c1) ! c1 + Db_BufSz = Db_BufSz + SIZE(InData%c2) ! c2 + Db_BufSz = Db_BufSz + SIZE(InData%c3) ! c3 + Db_BufSz = Db_BufSz + SIZE(InData%d1) ! d1 + Db_BufSz = Db_BufSz + SIZE(InData%d2) ! d2 + Db_BufSz = Db_BufSz + SIZE(InData%d3) ! d3 + Db_BufSz = Db_BufSz + SIZE(InData%e1) ! e1 + Db_BufSz = Db_BufSz + SIZE(InData%e2) ! e2 + Db_BufSz = Db_BufSz + SIZE(InData%e3) ! e3 + Db_BufSz = Db_BufSz + SIZE(InData%f1) ! f1 + Db_BufSz = Db_BufSz + SIZE(InData%f2) ! f2 + Db_BufSz = Db_BufSz + SIZE(InData%f3) ! f3 + Db_BufSz = Db_BufSz + SIZE(InData%g1) ! g1 + Db_BufSz = Db_BufSz + SIZE(InData%g2) ! g2 + Db_BufSz = Db_BufSz + SIZE(InData%g3) ! g3 + Int_BufSz = Int_BufSz + 1 ! i1 allocated yes/no + IF ( ALLOCATED(InData%i1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! i1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%i1) ! i1 + END IF + Int_BufSz = Int_BufSz + 1 ! i2 allocated yes/no + IF ( ALLOCATED(InData%i2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! i2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%i2) ! i2 + END IF + Int_BufSz = Int_BufSz + 1 ! i3 allocated yes/no + IF ( ALLOCATED(InData%i3) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! i3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%i3) ! i3 + END IF + Int_BufSz = Int_BufSz + 1 ! j1 allocated yes/no + IF ( ALLOCATED(InData%j1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! j1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%j1) ! j1 + END IF + Int_BufSz = Int_BufSz + 1 ! j2 allocated yes/no + IF ( ALLOCATED(InData%j2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! j2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%j2) ! j2 + END IF + Int_BufSz = Int_BufSz + 1 ! j3 allocated yes/no + IF ( ALLOCATED(InData%j3) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! j3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%j3) ! j3 + END IF + Int_BufSz = Int_BufSz + 1 ! m1 allocated yes/no + IF ( ALLOCATED(InData%m1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! m1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%m1) ! m1 + END IF + Int_BufSz = Int_BufSz + 1 ! m2 allocated yes/no + IF ( ALLOCATED(InData%m2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! m2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%m2) ! m2 + END IF + Int_BufSz = Int_BufSz + 1 ! m3 allocated yes/no + IF ( ALLOCATED(InData%m3) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! m3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%m3) ! m3 + END IF + Int_BufSz = Int_BufSz + 1 ! n1 allocated yes/no + IF ( ALLOCATED(InData%n1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! n1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%n1) ! n1 + END IF + Int_BufSz = Int_BufSz + 1 ! n2 allocated yes/no + IF ( ALLOCATED(InData%n2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! n2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%n2) ! n2 + END IF + Int_BufSz = Int_BufSz + 1 ! n3 allocated yes/no + IF ( ALLOCATED(InData%n3) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! n3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%n3) ! n3 + END IF + Db_BufSz = Db_BufSz + SIZE(InData%p1) ! p1 + Db_BufSz = Db_BufSz + SIZE(InData%p2) ! p2 + Db_BufSz = Db_BufSz + SIZE(InData%p3) ! p3 + Db_BufSz = Db_BufSz + SIZE(InData%rf1) ! rf1 + Db_BufSz = Db_BufSz + SIZE(InData%rf2) ! rf2 + Db_BufSz = Db_BufSz + SIZE(InData%rf3) ! rf3 + Db_BufSz = Db_BufSz + SIZE(InData%rfa) ! rfa + Int_BufSz = Int_BufSz + 1 ! t1 allocated yes/no + IF ( ALLOCATED(InData%t1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! t1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%t1) ! t1 + END IF + Int_BufSz = Int_BufSz + 1 ! t2 allocated yes/no + IF ( ALLOCATED(InData%t2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! t2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%t2) ! t2 + END IF + Int_BufSz = Int_BufSz + 1 ! t3 allocated yes/no + IF ( ALLOCATED(InData%t3) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! t3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%t3) ! t3 + END IF + Int_BufSz = Int_BufSz + 1 ! te1 allocated yes/no + IF ( ALLOCATED(InData%te1) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! te1 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%te1) ! te1 + END IF + Int_BufSz = Int_BufSz + 1 ! te2 allocated yes/no + IF ( ALLOCATED(InData%te2) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! te2 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%te2) ! te2 + END IF + Int_BufSz = Int_BufSz + 1 ! te3 allocated yes/no + IF ( ALLOCATED(InData%te3) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! te3 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%te3) ! te3 + END IF + Db_BufSz = Db_BufSz + SIZE(InData%tf1) ! tf1 + Db_BufSz = Db_BufSz + SIZE(InData%tf2) ! tf2 + Db_BufSz = Db_BufSz + SIZE(InData%tf3) ! tf3 + Db_BufSz = Db_BufSz + SIZE(InData%tfa) ! tfa + Db_BufSz = Db_BufSz + SIZE(InData%z1) ! z1 + Db_BufSz = Db_BufSz + SIZE(InData%z2) ! z2 + Db_BufSz = Db_BufSz + SIZE(InData%z3) ! z3 + 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%a1,1), UBOUND(InData%a1,1) + DbKiBuf(Db_Xferred) = InData%a1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%a2,1), UBOUND(InData%a2,1) + DbKiBuf(Db_Xferred) = InData%a2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%a3,1), UBOUND(InData%a3,1) + DbKiBuf(Db_Xferred) = InData%a3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%b1,1), UBOUND(InData%b1,1) + DbKiBuf(Db_Xferred) = InData%b1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%b2,1), UBOUND(InData%b2,1) + DbKiBuf(Db_Xferred) = InData%b2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%b3,1), UBOUND(InData%b3,1) + DbKiBuf(Db_Xferred) = InData%b3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%c1,1), UBOUND(InData%c1,1) + DbKiBuf(Db_Xferred) = InData%c1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%c2,1), UBOUND(InData%c2,1) + DbKiBuf(Db_Xferred) = InData%c2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%c3,1), UBOUND(InData%c3,1) + DbKiBuf(Db_Xferred) = InData%c3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%d1,1), UBOUND(InData%d1,1) + DbKiBuf(Db_Xferred) = InData%d1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%d2,1), UBOUND(InData%d2,1) + DbKiBuf(Db_Xferred) = InData%d2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%d3,1), UBOUND(InData%d3,1) + DbKiBuf(Db_Xferred) = InData%d3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%e1,1), UBOUND(InData%e1,1) + DbKiBuf(Db_Xferred) = InData%e1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%e2,1), UBOUND(InData%e2,1) + DbKiBuf(Db_Xferred) = InData%e2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%e3,1), UBOUND(InData%e3,1) + DbKiBuf(Db_Xferred) = InData%e3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%f1,1), UBOUND(InData%f1,1) + DbKiBuf(Db_Xferred) = InData%f1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%f2,1), UBOUND(InData%f2,1) + DbKiBuf(Db_Xferred) = InData%f2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%f3,1), UBOUND(InData%f3,1) + DbKiBuf(Db_Xferred) = InData%f3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%g1,1), UBOUND(InData%g1,1) + DbKiBuf(Db_Xferred) = InData%g1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%g2,1), UBOUND(InData%g2,1) + DbKiBuf(Db_Xferred) = InData%g2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%g3,1), UBOUND(InData%g3,1) + DbKiBuf(Db_Xferred) = InData%g3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%i1) ) 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%i1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%i1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%i1,2), UBOUND(InData%i1,2) + DO i1 = LBOUND(InData%i1,1), UBOUND(InData%i1,1) + DbKiBuf(Db_Xferred) = InData%i1(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%i2) ) 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%i2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%i2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%i2,2), UBOUND(InData%i2,2) + DO i1 = LBOUND(InData%i2,1), UBOUND(InData%i2,1) + DbKiBuf(Db_Xferred) = InData%i2(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%i3) ) 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%i3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%i3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%i3,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%i3,2), UBOUND(InData%i3,2) + DO i1 = LBOUND(InData%i3,1), UBOUND(InData%i3,1) + DbKiBuf(Db_Xferred) = InData%i3(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%j1) ) 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%j1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%j1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%j1,2), UBOUND(InData%j1,2) + DO i1 = LBOUND(InData%j1,1), UBOUND(InData%j1,1) + DbKiBuf(Db_Xferred) = InData%j1(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%j2) ) 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%j2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%j2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%j2,2), UBOUND(InData%j2,2) + DO i1 = LBOUND(InData%j2,1), UBOUND(InData%j2,1) + DbKiBuf(Db_Xferred) = InData%j2(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%j3) ) 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%j3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%j3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%j3,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%j3,2), UBOUND(InData%j3,2) + DO i1 = LBOUND(InData%j3,1), UBOUND(InData%j3,1) + DbKiBuf(Db_Xferred) = InData%j3(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m1) ) 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%m1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%m1,3), UBOUND(InData%m1,3) + DO i2 = LBOUND(InData%m1,2), UBOUND(InData%m1,2) + DO i1 = LBOUND(InData%m1,1), UBOUND(InData%m1,1) + DbKiBuf(Db_Xferred) = InData%m1(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m2) ) 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%m2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%m2,3), UBOUND(InData%m2,3) + DO i2 = LBOUND(InData%m2,2), UBOUND(InData%m2,2) + DO i1 = LBOUND(InData%m2,1), UBOUND(InData%m2,1) + DbKiBuf(Db_Xferred) = InData%m2(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m3) ) 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%m3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m3,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m3,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m3,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%m3,3), UBOUND(InData%m3,3) + DO i2 = LBOUND(InData%m3,2), UBOUND(InData%m3,2) + DO i1 = LBOUND(InData%m3,1), UBOUND(InData%m3,1) + DbKiBuf(Db_Xferred) = InData%m3(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%n1) ) 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%n1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%n1,3), UBOUND(InData%n1,3) + DO i2 = LBOUND(InData%n1,2), UBOUND(InData%n1,2) + DO i1 = LBOUND(InData%n1,1), UBOUND(InData%n1,1) + DbKiBuf(Db_Xferred) = InData%n1(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%n2) ) 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%n2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%n2,3), UBOUND(InData%n2,3) + DO i2 = LBOUND(InData%n2,2), UBOUND(InData%n2,2) + DO i1 = LBOUND(InData%n2,1), UBOUND(InData%n2,1) + DbKiBuf(Db_Xferred) = InData%n2(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%n3) ) 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%n3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n3,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%n3,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%n3,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%n3,3), UBOUND(InData%n3,3) + DO i2 = LBOUND(InData%n3,2), UBOUND(InData%n3,2) + DO i1 = LBOUND(InData%n3,1), UBOUND(InData%n3,1) + DbKiBuf(Db_Xferred) = InData%n3(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%p1,1), UBOUND(InData%p1,1) + DbKiBuf(Db_Xferred) = InData%p1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%p2,1), UBOUND(InData%p2,1) + DbKiBuf(Db_Xferred) = InData%p2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%p3,1), UBOUND(InData%p3,1) + DbKiBuf(Db_Xferred) = InData%p3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rf1,1), UBOUND(InData%rf1,1) + DbKiBuf(Db_Xferred) = InData%rf1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rf2,1), UBOUND(InData%rf2,1) + DbKiBuf(Db_Xferred) = InData%rf2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rf3,1), UBOUND(InData%rf3,1) + DbKiBuf(Db_Xferred) = InData%rf3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rfa,1), UBOUND(InData%rfa,1) + DbKiBuf(Db_Xferred) = InData%rfa(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%t1) ) 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%t1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%t1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%t1,2), UBOUND(InData%t1,2) + DO i1 = LBOUND(InData%t1,1), UBOUND(InData%t1,1) + DbKiBuf(Db_Xferred) = InData%t1(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%t2) ) 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%t2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%t2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%t2,2), UBOUND(InData%t2,2) + DO i1 = LBOUND(InData%t2,1), UBOUND(InData%t2,1) + DbKiBuf(Db_Xferred) = InData%t2(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%t3) ) 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%t3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%t3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%t3,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%t3,2), UBOUND(InData%t3,2) + DO i1 = LBOUND(InData%t3,1), UBOUND(InData%t3,1) + DbKiBuf(Db_Xferred) = InData%t3(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%te1) ) 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%te1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te1,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te1,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te1,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%te1,3), UBOUND(InData%te1,3) + DO i2 = LBOUND(InData%te1,2), UBOUND(InData%te1,2) + DO i1 = LBOUND(InData%te1,1), UBOUND(InData%te1,1) + DbKiBuf(Db_Xferred) = InData%te1(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%te2) ) 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%te2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te2,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te2,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te2,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%te2,3), UBOUND(InData%te2,3) + DO i2 = LBOUND(InData%te2,2), UBOUND(InData%te2,2) + DO i1 = LBOUND(InData%te2,1), UBOUND(InData%te2,1) + DbKiBuf(Db_Xferred) = InData%te2(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%te3) ) 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%te3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te3,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te3,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te3,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%te3,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%te3,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%te3,3), UBOUND(InData%te3,3) + DO i2 = LBOUND(InData%te3,2), UBOUND(InData%te3,2) + DO i1 = LBOUND(InData%te3,1), UBOUND(InData%te3,1) + DbKiBuf(Db_Xferred) = InData%te3(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%tf1,1), UBOUND(InData%tf1,1) + DbKiBuf(Db_Xferred) = InData%tf1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%tf2,1), UBOUND(InData%tf2,1) + DbKiBuf(Db_Xferred) = InData%tf2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%tf3,1), UBOUND(InData%tf3,1) + DbKiBuf(Db_Xferred) = InData%tf3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%tfa,1), UBOUND(InData%tfa,1) + DbKiBuf(Db_Xferred) = InData%tfa(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%z1,1), UBOUND(InData%z1,1) + DbKiBuf(Db_Xferred) = InData%z1(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%z2,1), UBOUND(InData%z2,1) + DbKiBuf(Db_Xferred) = InData%z2(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%z3,1), UBOUND(InData%z3,1) + DbKiBuf(Db_Xferred) = InData%z3(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE ED_PackCoordSys + + SUBROUTINE ED_UnPackCoordSys( 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(ED_CoordSys), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_UnPackCoordSys' + ! 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%a1,1) + i1_u = UBOUND(OutData%a1,1) + DO i1 = LBOUND(OutData%a1,1), UBOUND(OutData%a1,1) + OutData%a1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%a2,1) + i1_u = UBOUND(OutData%a2,1) + DO i1 = LBOUND(OutData%a2,1), UBOUND(OutData%a2,1) + OutData%a2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%a3,1) + i1_u = UBOUND(OutData%a3,1) + DO i1 = LBOUND(OutData%a3,1), UBOUND(OutData%a3,1) + OutData%a3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%b1,1) + i1_u = UBOUND(OutData%b1,1) + DO i1 = LBOUND(OutData%b1,1), UBOUND(OutData%b1,1) + OutData%b1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%b2,1) + i1_u = UBOUND(OutData%b2,1) + DO i1 = LBOUND(OutData%b2,1), UBOUND(OutData%b2,1) + OutData%b2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%b3,1) + i1_u = UBOUND(OutData%b3,1) + DO i1 = LBOUND(OutData%b3,1), UBOUND(OutData%b3,1) + OutData%b3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%c1,1) + i1_u = UBOUND(OutData%c1,1) + DO i1 = LBOUND(OutData%c1,1), UBOUND(OutData%c1,1) + OutData%c1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%c2,1) + i1_u = UBOUND(OutData%c2,1) + DO i1 = LBOUND(OutData%c2,1), UBOUND(OutData%c2,1) + OutData%c2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%c3,1) + i1_u = UBOUND(OutData%c3,1) + DO i1 = LBOUND(OutData%c3,1), UBOUND(OutData%c3,1) + OutData%c3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%d1,1) + i1_u = UBOUND(OutData%d1,1) + DO i1 = LBOUND(OutData%d1,1), UBOUND(OutData%d1,1) + OutData%d1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%d2,1) + i1_u = UBOUND(OutData%d2,1) + DO i1 = LBOUND(OutData%d2,1), UBOUND(OutData%d2,1) + OutData%d2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%d3,1) + i1_u = UBOUND(OutData%d3,1) + DO i1 = LBOUND(OutData%d3,1), UBOUND(OutData%d3,1) + OutData%d3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%e1,1) + i1_u = UBOUND(OutData%e1,1) + DO i1 = LBOUND(OutData%e1,1), UBOUND(OutData%e1,1) + OutData%e1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%e2,1) + i1_u = UBOUND(OutData%e2,1) + DO i1 = LBOUND(OutData%e2,1), UBOUND(OutData%e2,1) + OutData%e2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%e3,1) + i1_u = UBOUND(OutData%e3,1) + DO i1 = LBOUND(OutData%e3,1), UBOUND(OutData%e3,1) + OutData%e3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%f1,1) + i1_u = UBOUND(OutData%f1,1) + DO i1 = LBOUND(OutData%f1,1), UBOUND(OutData%f1,1) + OutData%f1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%f2,1) + i1_u = UBOUND(OutData%f2,1) + DO i1 = LBOUND(OutData%f2,1), UBOUND(OutData%f2,1) + OutData%f2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%f3,1) + i1_u = UBOUND(OutData%f3,1) + DO i1 = LBOUND(OutData%f3,1), UBOUND(OutData%f3,1) + OutData%f3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%g1,1) + i1_u = UBOUND(OutData%g1,1) + DO i1 = LBOUND(OutData%g1,1), UBOUND(OutData%g1,1) + OutData%g1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%g2,1) + i1_u = UBOUND(OutData%g2,1) + DO i1 = LBOUND(OutData%g2,1), UBOUND(OutData%g2,1) + OutData%g2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%g3,1) + i1_u = UBOUND(OutData%g3,1) + DO i1 = LBOUND(OutData%g3,1), UBOUND(OutData%g3,1) + OutData%g3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! i1 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%i1)) DEALLOCATE(OutData%i1) + ALLOCATE(OutData%i1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%i1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%i1,2), UBOUND(OutData%i1,2) + DO i1 = LBOUND(OutData%i1,1), UBOUND(OutData%i1,1) + OutData%i1(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! i2 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%i2)) DEALLOCATE(OutData%i2) + ALLOCATE(OutData%i2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%i2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%i2,2), UBOUND(OutData%i2,2) + DO i1 = LBOUND(OutData%i2,1), UBOUND(OutData%i2,1) + OutData%i2(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! i3 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%i3)) DEALLOCATE(OutData%i3) + ALLOCATE(OutData%i3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%i3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%i3,2), UBOUND(OutData%i3,2) + DO i1 = LBOUND(OutData%i3,1), UBOUND(OutData%i3,1) + OutData%i3(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! j1 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%j1)) DEALLOCATE(OutData%j1) + ALLOCATE(OutData%j1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%j1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%j1,2), UBOUND(OutData%j1,2) + DO i1 = LBOUND(OutData%j1,1), UBOUND(OutData%j1,1) + OutData%j1(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! j2 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%j2)) DEALLOCATE(OutData%j2) + ALLOCATE(OutData%j2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%j2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%j2,2), UBOUND(OutData%j2,2) + DO i1 = LBOUND(OutData%j2,1), UBOUND(OutData%j2,1) + OutData%j2(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! j3 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%j3)) DEALLOCATE(OutData%j3) + ALLOCATE(OutData%j3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%j3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%j3,2), UBOUND(OutData%j3,2) + DO i1 = LBOUND(OutData%j3,1), UBOUND(OutData%j3,1) + OutData%j3(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m1 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%m1)) DEALLOCATE(OutData%m1) + ALLOCATE(OutData%m1(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%m1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%m1,3), UBOUND(OutData%m1,3) + DO i2 = LBOUND(OutData%m1,2), UBOUND(OutData%m1,2) + DO i1 = LBOUND(OutData%m1,1), UBOUND(OutData%m1,1) + OutData%m1(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m2 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%m2)) DEALLOCATE(OutData%m2) + ALLOCATE(OutData%m2(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%m2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%m2,3), UBOUND(OutData%m2,3) + DO i2 = LBOUND(OutData%m2,2), UBOUND(OutData%m2,2) + DO i1 = LBOUND(OutData%m2,1), UBOUND(OutData%m2,1) + OutData%m2(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m3 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%m3)) DEALLOCATE(OutData%m3) + ALLOCATE(OutData%m3(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%m3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%m3,3), UBOUND(OutData%m3,3) + DO i2 = LBOUND(OutData%m3,2), UBOUND(OutData%m3,2) + DO i1 = LBOUND(OutData%m3,1), UBOUND(OutData%m3,1) + OutData%m3(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! n1 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%n1)) DEALLOCATE(OutData%n1) + ALLOCATE(OutData%n1(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%n1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%n1,3), UBOUND(OutData%n1,3) + DO i2 = LBOUND(OutData%n1,2), UBOUND(OutData%n1,2) + DO i1 = LBOUND(OutData%n1,1), UBOUND(OutData%n1,1) + OutData%n1(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! n2 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%n2)) DEALLOCATE(OutData%n2) + ALLOCATE(OutData%n2(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%n2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%n2,3), UBOUND(OutData%n2,3) + DO i2 = LBOUND(OutData%n2,2), UBOUND(OutData%n2,2) + DO i1 = LBOUND(OutData%n2,1), UBOUND(OutData%n2,1) + OutData%n2(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! n3 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%n3)) DEALLOCATE(OutData%n3) + ALLOCATE(OutData%n3(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%n3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%n3,3), UBOUND(OutData%n3,3) + DO i2 = LBOUND(OutData%n3,2), UBOUND(OutData%n3,2) + DO i1 = LBOUND(OutData%n3,1), UBOUND(OutData%n3,1) + OutData%n3(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%p1,1) + i1_u = UBOUND(OutData%p1,1) + DO i1 = LBOUND(OutData%p1,1), UBOUND(OutData%p1,1) + OutData%p1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%p2,1) + i1_u = UBOUND(OutData%p2,1) + DO i1 = LBOUND(OutData%p2,1), UBOUND(OutData%p2,1) + OutData%p2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%p3,1) + i1_u = UBOUND(OutData%p3,1) + DO i1 = LBOUND(OutData%p3,1), UBOUND(OutData%p3,1) + OutData%p3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rf1,1) + i1_u = UBOUND(OutData%rf1,1) + DO i1 = LBOUND(OutData%rf1,1), UBOUND(OutData%rf1,1) + OutData%rf1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rf2,1) + i1_u = UBOUND(OutData%rf2,1) + DO i1 = LBOUND(OutData%rf2,1), UBOUND(OutData%rf2,1) + OutData%rf2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rf3,1) + i1_u = UBOUND(OutData%rf3,1) + DO i1 = LBOUND(OutData%rf3,1), UBOUND(OutData%rf3,1) + OutData%rf3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rfa,1) + i1_u = UBOUND(OutData%rfa,1) + DO i1 = LBOUND(OutData%rfa,1), UBOUND(OutData%rfa,1) + OutData%rfa(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! t1 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%t1)) DEALLOCATE(OutData%t1) + ALLOCATE(OutData%t1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%t1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%t1,2), UBOUND(OutData%t1,2) + DO i1 = LBOUND(OutData%t1,1), UBOUND(OutData%t1,1) + OutData%t1(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! t2 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%t2)) DEALLOCATE(OutData%t2) + ALLOCATE(OutData%t2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%t2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%t2,2), UBOUND(OutData%t2,2) + DO i1 = LBOUND(OutData%t2,1), UBOUND(OutData%t2,1) + OutData%t2(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! t3 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%t3)) DEALLOCATE(OutData%t3) + ALLOCATE(OutData%t3(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%t3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%t3,2), UBOUND(OutData%t3,2) + DO i1 = LBOUND(OutData%t3,1), UBOUND(OutData%t3,1) + OutData%t3(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! te1 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%te1)) DEALLOCATE(OutData%te1) + ALLOCATE(OutData%te1(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%te1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%te1,3), UBOUND(OutData%te1,3) + DO i2 = LBOUND(OutData%te1,2), UBOUND(OutData%te1,2) + DO i1 = LBOUND(OutData%te1,1), UBOUND(OutData%te1,1) + OutData%te1(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! te2 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%te2)) DEALLOCATE(OutData%te2) + ALLOCATE(OutData%te2(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%te2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%te2,3), UBOUND(OutData%te2,3) + DO i2 = LBOUND(OutData%te2,2), UBOUND(OutData%te2,2) + DO i1 = LBOUND(OutData%te2,1), UBOUND(OutData%te2,1) + OutData%te2(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! te3 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%te3)) DEALLOCATE(OutData%te3) + ALLOCATE(OutData%te3(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%te3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%te3,3), UBOUND(OutData%te3,3) + DO i2 = LBOUND(OutData%te3,2), UBOUND(OutData%te3,2) + DO i1 = LBOUND(OutData%te3,1), UBOUND(OutData%te3,1) + OutData%te3(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%tf1,1) + i1_u = UBOUND(OutData%tf1,1) + DO i1 = LBOUND(OutData%tf1,1), UBOUND(OutData%tf1,1) + OutData%tf1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%tf2,1) + i1_u = UBOUND(OutData%tf2,1) + DO i1 = LBOUND(OutData%tf2,1), UBOUND(OutData%tf2,1) + OutData%tf2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%tf3,1) + i1_u = UBOUND(OutData%tf3,1) + DO i1 = LBOUND(OutData%tf3,1), UBOUND(OutData%tf3,1) + OutData%tf3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%tfa,1) + i1_u = UBOUND(OutData%tfa,1) + DO i1 = LBOUND(OutData%tfa,1), UBOUND(OutData%tfa,1) + OutData%tfa(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%z1,1) + i1_u = UBOUND(OutData%z1,1) + DO i1 = LBOUND(OutData%z1,1), UBOUND(OutData%z1,1) + OutData%z1(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%z2,1) + i1_u = UBOUND(OutData%z2,1) + DO i1 = LBOUND(OutData%z2,1), UBOUND(OutData%z2,1) + OutData%z2(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%z3,1) + i1_u = UBOUND(OutData%z3,1) + DO i1 = LBOUND(OutData%z3,1), UBOUND(OutData%z3,1) + OutData%z3(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE ED_UnPackCoordSys + + SUBROUTINE ED_CopyActiveDOFs( SrcActiveDOFsData, DstActiveDOFsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_ActiveDOFs), INTENT(IN) :: SrcActiveDOFsData + TYPE(ED_ActiveDOFs), INTENT(INOUT) :: DstActiveDOFsData + 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 = 'ED_CopyActiveDOFs' +! + ErrStat = ErrID_None + ErrMsg = "" + DstActiveDOFsData%NActvDOF = SrcActiveDOFsData%NActvDOF + DstActiveDOFsData%NPCE = SrcActiveDOFsData%NPCE + DstActiveDOFsData%NPDE = SrcActiveDOFsData%NPDE + DstActiveDOFsData%NPIE = SrcActiveDOFsData%NPIE + DstActiveDOFsData%NPTE = SrcActiveDOFsData%NPTE + DstActiveDOFsData%NPTTE = SrcActiveDOFsData%NPTTE +IF (ALLOCATED(SrcActiveDOFsData%NPSBE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%NPSBE,1) + i1_u = UBOUND(SrcActiveDOFsData%NPSBE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%NPSBE)) THEN + ALLOCATE(DstActiveDOFsData%NPSBE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%NPSBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%NPSBE = SrcActiveDOFsData%NPSBE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%NPSE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%NPSE,1) + i1_u = UBOUND(SrcActiveDOFsData%NPSE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%NPSE)) THEN + ALLOCATE(DstActiveDOFsData%NPSE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%NPSE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%NPSE = SrcActiveDOFsData%NPSE +ENDIF + DstActiveDOFsData%NPUE = SrcActiveDOFsData%NPUE + DstActiveDOFsData%NPYE = SrcActiveDOFsData%NPYE +IF (ALLOCATED(SrcActiveDOFsData%PCE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PCE,1) + i1_u = UBOUND(SrcActiveDOFsData%PCE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PCE)) THEN + ALLOCATE(DstActiveDOFsData%PCE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PCE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PCE = SrcActiveDOFsData%PCE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PDE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PDE,1) + i1_u = UBOUND(SrcActiveDOFsData%PDE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PDE)) THEN + ALLOCATE(DstActiveDOFsData%PDE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PDE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PDE = SrcActiveDOFsData%PDE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PIE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PIE,1) + i1_u = UBOUND(SrcActiveDOFsData%PIE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PIE)) THEN + ALLOCATE(DstActiveDOFsData%PIE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PIE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PIE = SrcActiveDOFsData%PIE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PTE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PTE,1) + i1_u = UBOUND(SrcActiveDOFsData%PTE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PTE)) THEN + ALLOCATE(DstActiveDOFsData%PTE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PTE = SrcActiveDOFsData%PTE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PTTE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PTTE,1) + i1_u = UBOUND(SrcActiveDOFsData%PTTE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PTTE)) THEN + ALLOCATE(DstActiveDOFsData%PTTE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PTTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PTTE = SrcActiveDOFsData%PTTE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PS)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PS,1) + i1_u = UBOUND(SrcActiveDOFsData%PS,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PS)) THEN + ALLOCATE(DstActiveDOFsData%PS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PS = SrcActiveDOFsData%PS +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PSBE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PSBE,1) + i1_u = UBOUND(SrcActiveDOFsData%PSBE,1) + i2_l = LBOUND(SrcActiveDOFsData%PSBE,2) + i2_u = UBOUND(SrcActiveDOFsData%PSBE,2) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PSBE)) THEN + ALLOCATE(DstActiveDOFsData%PSBE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PSBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PSBE = SrcActiveDOFsData%PSBE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PSE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PSE,1) + i1_u = UBOUND(SrcActiveDOFsData%PSE,1) + i2_l = LBOUND(SrcActiveDOFsData%PSE,2) + i2_u = UBOUND(SrcActiveDOFsData%PSE,2) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PSE)) THEN + ALLOCATE(DstActiveDOFsData%PSE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PSE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PSE = SrcActiveDOFsData%PSE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PUE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PUE,1) + i1_u = UBOUND(SrcActiveDOFsData%PUE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PUE)) THEN + ALLOCATE(DstActiveDOFsData%PUE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PUE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PUE = SrcActiveDOFsData%PUE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%PYE)) THEN + i1_l = LBOUND(SrcActiveDOFsData%PYE,1) + i1_u = UBOUND(SrcActiveDOFsData%PYE,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%PYE)) THEN + ALLOCATE(DstActiveDOFsData%PYE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%PYE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%PYE = SrcActiveDOFsData%PYE +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%SrtPS)) THEN + i1_l = LBOUND(SrcActiveDOFsData%SrtPS,1) + i1_u = UBOUND(SrcActiveDOFsData%SrtPS,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%SrtPS)) THEN + ALLOCATE(DstActiveDOFsData%SrtPS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%SrtPS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%SrtPS = SrcActiveDOFsData%SrtPS +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%SrtPSNAUG)) THEN + i1_l = LBOUND(SrcActiveDOFsData%SrtPSNAUG,1) + i1_u = UBOUND(SrcActiveDOFsData%SrtPSNAUG,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%SrtPSNAUG)) THEN + ALLOCATE(DstActiveDOFsData%SrtPSNAUG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%SrtPSNAUG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%SrtPSNAUG = SrcActiveDOFsData%SrtPSNAUG +ENDIF +IF (ALLOCATED(SrcActiveDOFsData%Diag)) THEN + i1_l = LBOUND(SrcActiveDOFsData%Diag,1) + i1_u = UBOUND(SrcActiveDOFsData%Diag,1) + IF (.NOT. ALLOCATED(DstActiveDOFsData%Diag)) THEN + ALLOCATE(DstActiveDOFsData%Diag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstActiveDOFsData%Diag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstActiveDOFsData%Diag = SrcActiveDOFsData%Diag +ENDIF + END SUBROUTINE ED_CopyActiveDOFs + + SUBROUTINE ED_DestroyActiveDOFs( ActiveDOFsData, ErrStat, ErrMsg ) + TYPE(ED_ActiveDOFs), INTENT(INOUT) :: ActiveDOFsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyActiveDOFs' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ActiveDOFsData%NPSBE)) THEN + DEALLOCATE(ActiveDOFsData%NPSBE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%NPSE)) THEN + DEALLOCATE(ActiveDOFsData%NPSE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PCE)) THEN + DEALLOCATE(ActiveDOFsData%PCE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PDE)) THEN + DEALLOCATE(ActiveDOFsData%PDE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PIE)) THEN + DEALLOCATE(ActiveDOFsData%PIE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PTE)) THEN + DEALLOCATE(ActiveDOFsData%PTE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PTTE)) THEN + DEALLOCATE(ActiveDOFsData%PTTE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PS)) THEN + DEALLOCATE(ActiveDOFsData%PS) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PSBE)) THEN + DEALLOCATE(ActiveDOFsData%PSBE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PSE)) THEN + DEALLOCATE(ActiveDOFsData%PSE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PUE)) THEN + DEALLOCATE(ActiveDOFsData%PUE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%PYE)) THEN + DEALLOCATE(ActiveDOFsData%PYE) +ENDIF +IF (ALLOCATED(ActiveDOFsData%SrtPS)) THEN + DEALLOCATE(ActiveDOFsData%SrtPS) +ENDIF +IF (ALLOCATED(ActiveDOFsData%SrtPSNAUG)) THEN + DEALLOCATE(ActiveDOFsData%SrtPSNAUG) +ENDIF +IF (ALLOCATED(ActiveDOFsData%Diag)) THEN + DEALLOCATE(ActiveDOFsData%Diag) +ENDIF + END SUBROUTINE ED_DestroyActiveDOFs + + SUBROUTINE ED_PackActiveDOFs( 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(ED_ActiveDOFs), 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 = 'ED_PackActiveDOFs' + ! 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 ! NActvDOF + Int_BufSz = Int_BufSz + 1 ! NPCE + Int_BufSz = Int_BufSz + 1 ! NPDE + Int_BufSz = Int_BufSz + 1 ! NPIE + Int_BufSz = Int_BufSz + 1 ! NPTE + Int_BufSz = Int_BufSz + 1 ! NPTTE + Int_BufSz = Int_BufSz + 1 ! NPSBE allocated yes/no + IF ( ALLOCATED(InData%NPSBE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NPSBE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NPSBE) ! NPSBE + END IF + Int_BufSz = Int_BufSz + 1 ! NPSE allocated yes/no + IF ( ALLOCATED(InData%NPSE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NPSE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NPSE) ! NPSE + END IF + Int_BufSz = Int_BufSz + 1 ! NPUE + Int_BufSz = Int_BufSz + 1 ! NPYE + Int_BufSz = Int_BufSz + 1 ! PCE allocated yes/no + IF ( ALLOCATED(InData%PCE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PCE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PCE) ! PCE + END IF + Int_BufSz = Int_BufSz + 1 ! PDE allocated yes/no + IF ( ALLOCATED(InData%PDE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PDE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PDE) ! PDE + END IF + Int_BufSz = Int_BufSz + 1 ! PIE allocated yes/no + IF ( ALLOCATED(InData%PIE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PIE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PIE) ! PIE + END IF + Int_BufSz = Int_BufSz + 1 ! PTE allocated yes/no + IF ( ALLOCATED(InData%PTE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PTE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PTE) ! PTE + END IF + Int_BufSz = Int_BufSz + 1 ! PTTE allocated yes/no + IF ( ALLOCATED(InData%PTTE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PTTE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PTTE) ! PTTE + END IF + Int_BufSz = Int_BufSz + 1 ! PS allocated yes/no + IF ( ALLOCATED(InData%PS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PS upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PS) ! PS + END IF + Int_BufSz = Int_BufSz + 1 ! PSBE allocated yes/no + IF ( ALLOCATED(InData%PSBE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PSBE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PSBE) ! PSBE + END IF + Int_BufSz = Int_BufSz + 1 ! PSE allocated yes/no + IF ( ALLOCATED(InData%PSE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PSE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PSE) ! PSE + END IF + Int_BufSz = Int_BufSz + 1 ! PUE allocated yes/no + IF ( ALLOCATED(InData%PUE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PUE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PUE) ! PUE + END IF + Int_BufSz = Int_BufSz + 1 ! PYE allocated yes/no + IF ( ALLOCATED(InData%PYE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PYE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PYE) ! PYE + END IF + Int_BufSz = Int_BufSz + 1 ! SrtPS allocated yes/no + IF ( ALLOCATED(InData%SrtPS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SrtPS upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SrtPS) ! SrtPS + END IF + Int_BufSz = Int_BufSz + 1 ! SrtPSNAUG allocated yes/no + IF ( ALLOCATED(InData%SrtPSNAUG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SrtPSNAUG upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SrtPSNAUG) ! SrtPSNAUG + END IF + Int_BufSz = Int_BufSz + 1 ! Diag allocated yes/no + IF ( ALLOCATED(InData%Diag) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Diag upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Diag) ! Diag + 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%NActvDOF + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPCE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPDE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPIE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPTE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPTTE + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NPSBE) ) 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%NPSBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NPSBE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NPSBE,1), UBOUND(InData%NPSBE,1) + IntKiBuf(Int_Xferred) = InData%NPSBE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NPSE) ) 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%NPSE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NPSE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NPSE,1), UBOUND(InData%NPSE,1) + IntKiBuf(Int_Xferred) = InData%NPSE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NPUE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPYE + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PCE) ) 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%PCE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PCE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PCE,1), UBOUND(InData%PCE,1) + IntKiBuf(Int_Xferred) = InData%PCE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PDE) ) 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%PDE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PDE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PDE,1), UBOUND(InData%PDE,1) + IntKiBuf(Int_Xferred) = InData%PDE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PIE) ) 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%PIE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PIE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PIE,1), UBOUND(InData%PIE,1) + IntKiBuf(Int_Xferred) = InData%PIE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PTE) ) 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%PTE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PTE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PTE,1), UBOUND(InData%PTE,1) + IntKiBuf(Int_Xferred) = InData%PTE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PTTE) ) 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%PTTE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PTTE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PTTE,1), UBOUND(InData%PTTE,1) + IntKiBuf(Int_Xferred) = InData%PTTE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PS) ) 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%PS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PS,1), UBOUND(InData%PS,1) + IntKiBuf(Int_Xferred) = InData%PS(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PSBE) ) 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%PSBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PSBE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PSBE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PSBE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PSBE,2), UBOUND(InData%PSBE,2) + DO i1 = LBOUND(InData%PSBE,1), UBOUND(InData%PSBE,1) + IntKiBuf(Int_Xferred) = InData%PSBE(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PSE) ) 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%PSE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PSE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PSE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PSE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PSE,2), UBOUND(InData%PSE,2) + DO i1 = LBOUND(InData%PSE,1), UBOUND(InData%PSE,1) + IntKiBuf(Int_Xferred) = InData%PSE(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PUE) ) 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%PUE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PUE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PUE,1), UBOUND(InData%PUE,1) + IntKiBuf(Int_Xferred) = InData%PUE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PYE) ) 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%PYE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PYE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PYE,1), UBOUND(InData%PYE,1) + IntKiBuf(Int_Xferred) = InData%PYE(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SrtPS) ) 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%SrtPS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SrtPS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SrtPS,1), UBOUND(InData%SrtPS,1) + IntKiBuf(Int_Xferred) = InData%SrtPS(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SrtPSNAUG) ) 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%SrtPSNAUG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SrtPSNAUG,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SrtPSNAUG,1), UBOUND(InData%SrtPSNAUG,1) + IntKiBuf(Int_Xferred) = InData%SrtPSNAUG(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Diag) ) 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%Diag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Diag,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Diag,1), UBOUND(InData%Diag,1) + IntKiBuf(Int_Xferred) = InData%Diag(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_PackActiveDOFs + + SUBROUTINE ED_UnPackActiveDOFs( 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(ED_ActiveDOFs), 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 = 'ED_UnPackActiveDOFs' + ! 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%NActvDOF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPCE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPDE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPIE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPTE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPTTE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NPSBE 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%NPSBE)) DEALLOCATE(OutData%NPSBE) + ALLOCATE(OutData%NPSBE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NPSBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NPSBE,1), UBOUND(OutData%NPSBE,1) + OutData%NPSBE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NPSE 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%NPSE)) DEALLOCATE(OutData%NPSE) + ALLOCATE(OutData%NPSE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NPSE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NPSE,1), UBOUND(OutData%NPSE,1) + OutData%NPSE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NPUE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPYE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PCE 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%PCE)) DEALLOCATE(OutData%PCE) + ALLOCATE(OutData%PCE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PCE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PCE,1), UBOUND(OutData%PCE,1) + OutData%PCE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PDE 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%PDE)) DEALLOCATE(OutData%PDE) + ALLOCATE(OutData%PDE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PDE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PDE,1), UBOUND(OutData%PDE,1) + OutData%PDE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PIE 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%PIE)) DEALLOCATE(OutData%PIE) + ALLOCATE(OutData%PIE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PIE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PIE,1), UBOUND(OutData%PIE,1) + OutData%PIE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PTE 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%PTE)) DEALLOCATE(OutData%PTE) + ALLOCATE(OutData%PTE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PTE,1), UBOUND(OutData%PTE,1) + OutData%PTE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PTTE 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%PTTE)) DEALLOCATE(OutData%PTTE) + ALLOCATE(OutData%PTTE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PTTE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PTTE,1), UBOUND(OutData%PTTE,1) + OutData%PTTE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PS 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%PS)) DEALLOCATE(OutData%PS) + ALLOCATE(OutData%PS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PS,1), UBOUND(OutData%PS,1) + OutData%PS(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PSBE 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%PSBE)) DEALLOCATE(OutData%PSBE) + ALLOCATE(OutData%PSBE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PSBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PSBE,2), UBOUND(OutData%PSBE,2) + DO i1 = LBOUND(OutData%PSBE,1), UBOUND(OutData%PSBE,1) + OutData%PSBE(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PSE 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%PSE)) DEALLOCATE(OutData%PSE) + ALLOCATE(OutData%PSE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PSE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PSE,2), UBOUND(OutData%PSE,2) + DO i1 = LBOUND(OutData%PSE,1), UBOUND(OutData%PSE,1) + OutData%PSE(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PUE 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%PUE)) DEALLOCATE(OutData%PUE) + ALLOCATE(OutData%PUE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PUE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PUE,1), UBOUND(OutData%PUE,1) + OutData%PUE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PYE 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%PYE)) DEALLOCATE(OutData%PYE) + ALLOCATE(OutData%PYE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PYE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PYE,1), UBOUND(OutData%PYE,1) + OutData%PYE(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SrtPS 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%SrtPS)) DEALLOCATE(OutData%SrtPS) + ALLOCATE(OutData%SrtPS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SrtPS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SrtPS,1), UBOUND(OutData%SrtPS,1) + OutData%SrtPS(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SrtPSNAUG 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%SrtPSNAUG)) DEALLOCATE(OutData%SrtPSNAUG) + ALLOCATE(OutData%SrtPSNAUG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SrtPSNAUG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SrtPSNAUG,1), UBOUND(OutData%SrtPSNAUG,1) + OutData%SrtPSNAUG(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Diag 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%Diag)) DEALLOCATE(OutData%Diag) + ALLOCATE(OutData%Diag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Diag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Diag,1), UBOUND(OutData%Diag,1) + OutData%Diag(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_UnPackActiveDOFs + + SUBROUTINE ED_CopyRtHndSide( SrcRtHndSideData, DstRtHndSideData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_RtHndSide), INTENT(IN) :: SrcRtHndSideData + TYPE(ED_RtHndSide), INTENT(INOUT) :: DstRtHndSideData + 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 = 'ED_CopyRtHndSide' +! + ErrStat = ErrID_None + ErrMsg = "" + DstRtHndSideData%rO = SrcRtHndSideData%rO +IF (ALLOCATED(SrcRtHndSideData%rQS)) THEN + i1_l = LBOUND(SrcRtHndSideData%rQS,1) + i1_u = UBOUND(SrcRtHndSideData%rQS,1) + i2_l = LBOUND(SrcRtHndSideData%rQS,2) + i2_u = UBOUND(SrcRtHndSideData%rQS,2) + i3_l = LBOUND(SrcRtHndSideData%rQS,3) + i3_u = UBOUND(SrcRtHndSideData%rQS,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%rQS)) THEN + ALLOCATE(DstRtHndSideData%rQS(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rQS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rQS = SrcRtHndSideData%rQS +ENDIF +IF (ALLOCATED(SrcRtHndSideData%rS)) THEN + i1_l = LBOUND(SrcRtHndSideData%rS,1) + i1_u = UBOUND(SrcRtHndSideData%rS,1) + i2_l = LBOUND(SrcRtHndSideData%rS,2) + i2_u = UBOUND(SrcRtHndSideData%rS,2) + i3_l = LBOUND(SrcRtHndSideData%rS,3) + i3_u = UBOUND(SrcRtHndSideData%rS,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%rS)) THEN + ALLOCATE(DstRtHndSideData%rS(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rS = SrcRtHndSideData%rS +ENDIF +IF (ALLOCATED(SrcRtHndSideData%rS0S)) THEN + i1_l = LBOUND(SrcRtHndSideData%rS0S,1) + i1_u = UBOUND(SrcRtHndSideData%rS0S,1) + i2_l = LBOUND(SrcRtHndSideData%rS0S,2) + i2_u = UBOUND(SrcRtHndSideData%rS0S,2) + i3_l = LBOUND(SrcRtHndSideData%rS0S,3) + i3_u = UBOUND(SrcRtHndSideData%rS0S,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%rS0S)) THEN + ALLOCATE(DstRtHndSideData%rS0S(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rS0S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rS0S = SrcRtHndSideData%rS0S +ENDIF +IF (ALLOCATED(SrcRtHndSideData%rT)) THEN + i1_l = LBOUND(SrcRtHndSideData%rT,1) + i1_u = UBOUND(SrcRtHndSideData%rT,1) + i2_l = LBOUND(SrcRtHndSideData%rT,2) + i2_u = UBOUND(SrcRtHndSideData%rT,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%rT)) THEN + ALLOCATE(DstRtHndSideData%rT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rT = SrcRtHndSideData%rT +ENDIF + DstRtHndSideData%rT0O = SrcRtHndSideData%rT0O +IF (ALLOCATED(SrcRtHndSideData%rT0T)) THEN + i1_l = LBOUND(SrcRtHndSideData%rT0T,1) + i1_u = UBOUND(SrcRtHndSideData%rT0T,1) + i2_l = LBOUND(SrcRtHndSideData%rT0T,2) + i2_u = UBOUND(SrcRtHndSideData%rT0T,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%rT0T)) THEN + ALLOCATE(DstRtHndSideData%rT0T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rT0T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rT0T = SrcRtHndSideData%rT0T +ENDIF + DstRtHndSideData%rZ = SrcRtHndSideData%rZ + DstRtHndSideData%rZO = SrcRtHndSideData%rZO +IF (ALLOCATED(SrcRtHndSideData%rZT)) THEN + i1_l = LBOUND(SrcRtHndSideData%rZT,1) + i1_u = UBOUND(SrcRtHndSideData%rZT,1) + i2_l = LBOUND(SrcRtHndSideData%rZT,2) + i2_u = UBOUND(SrcRtHndSideData%rZT,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%rZT)) THEN + ALLOCATE(DstRtHndSideData%rZT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rZT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rZT = SrcRtHndSideData%rZT +ENDIF + DstRtHndSideData%rPQ = SrcRtHndSideData%rPQ + DstRtHndSideData%rP = SrcRtHndSideData%rP + DstRtHndSideData%rV = SrcRtHndSideData%rV + DstRtHndSideData%rZY = SrcRtHndSideData%rZY + DstRtHndSideData%rOU = SrcRtHndSideData%rOU + DstRtHndSideData%rOV = SrcRtHndSideData%rOV + DstRtHndSideData%rVD = SrcRtHndSideData%rVD + DstRtHndSideData%rOW = SrcRtHndSideData%rOW + DstRtHndSideData%rPC = SrcRtHndSideData%rPC +IF (ALLOCATED(SrcRtHndSideData%rPS0)) THEN + i1_l = LBOUND(SrcRtHndSideData%rPS0,1) + i1_u = UBOUND(SrcRtHndSideData%rPS0,1) + i2_l = LBOUND(SrcRtHndSideData%rPS0,2) + i2_u = UBOUND(SrcRtHndSideData%rPS0,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%rPS0)) THEN + ALLOCATE(DstRtHndSideData%rPS0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rPS0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rPS0 = SrcRtHndSideData%rPS0 +ENDIF + DstRtHndSideData%rQ = SrcRtHndSideData%rQ + DstRtHndSideData%rQC = SrcRtHndSideData%rQC + DstRtHndSideData%rVIMU = SrcRtHndSideData%rVIMU + DstRtHndSideData%rVP = SrcRtHndSideData%rVP + DstRtHndSideData%rWI = SrcRtHndSideData%rWI + DstRtHndSideData%rWJ = SrcRtHndSideData%rWJ + DstRtHndSideData%rWK = SrcRtHndSideData%rWK + DstRtHndSideData%rZT0 = SrcRtHndSideData%rZT0 +IF (ALLOCATED(SrcRtHndSideData%AngPosEF)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngPosEF,1) + i1_u = UBOUND(SrcRtHndSideData%AngPosEF,1) + i2_l = LBOUND(SrcRtHndSideData%AngPosEF,2) + i2_u = UBOUND(SrcRtHndSideData%AngPosEF,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngPosEF)) THEN + ALLOCATE(DstRtHndSideData%AngPosEF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngPosEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngPosEF = SrcRtHndSideData%AngPosEF +ENDIF +IF (ALLOCATED(SrcRtHndSideData%AngPosXF)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngPosXF,1) + i1_u = UBOUND(SrcRtHndSideData%AngPosXF,1) + i2_l = LBOUND(SrcRtHndSideData%AngPosXF,2) + i2_u = UBOUND(SrcRtHndSideData%AngPosXF,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngPosXF)) THEN + ALLOCATE(DstRtHndSideData%AngPosXF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngPosXF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngPosXF = SrcRtHndSideData%AngPosXF +ENDIF +IF (ALLOCATED(SrcRtHndSideData%AngPosHM)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngPosHM,1) + i1_u = UBOUND(SrcRtHndSideData%AngPosHM,1) + i2_l = LBOUND(SrcRtHndSideData%AngPosHM,2) + i2_u = UBOUND(SrcRtHndSideData%AngPosHM,2) + i3_l = LBOUND(SrcRtHndSideData%AngPosHM,3) + i3_u = UBOUND(SrcRtHndSideData%AngPosHM,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngPosHM)) THEN + ALLOCATE(DstRtHndSideData%AngPosHM(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngPosHM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngPosHM = SrcRtHndSideData%AngPosHM +ENDIF + DstRtHndSideData%AngPosXB = SrcRtHndSideData%AngPosXB + DstRtHndSideData%AngPosEX = SrcRtHndSideData%AngPosEX +IF (ALLOCATED(SrcRtHndSideData%PAngVelEA)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEA,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEA,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEA,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEA,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEA,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEA,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEA)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEA(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEA = SrcRtHndSideData%PAngVelEA +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEF)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEF,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEF,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEF,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEF,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEF,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEF,3) + i4_l = LBOUND(SrcRtHndSideData%PAngVelEF,4) + i4_u = UBOUND(SrcRtHndSideData%PAngVelEF,4) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEF)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEF(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 DstRtHndSideData%PAngVelEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEF = SrcRtHndSideData%PAngVelEF +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEG)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEG,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEG,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEG,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEG,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEG,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEG,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEG)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEG(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEG = SrcRtHndSideData%PAngVelEG +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEH)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEH,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEH,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEH,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEH,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEH,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEH,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEH)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEH(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEH = SrcRtHndSideData%PAngVelEH +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEL)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEL,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEL,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEL,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEL,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEL,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEL,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEL)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEL = SrcRtHndSideData%PAngVelEL +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEM)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEM,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEM,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEM,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEM,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEM,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEM,3) + i4_l = LBOUND(SrcRtHndSideData%PAngVelEM,4) + i4_u = UBOUND(SrcRtHndSideData%PAngVelEM,4) + i5_l = LBOUND(SrcRtHndSideData%PAngVelEM,5) + i5_u = UBOUND(SrcRtHndSideData%PAngVelEM,5) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEM)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEM(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 DstRtHndSideData%PAngVelEM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEM = SrcRtHndSideData%PAngVelEM +ENDIF +IF (ALLOCATED(SrcRtHndSideData%AngVelEM)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngVelEM,1) + i1_u = UBOUND(SrcRtHndSideData%AngVelEM,1) + i2_l = LBOUND(SrcRtHndSideData%AngVelEM,2) + i2_u = UBOUND(SrcRtHndSideData%AngVelEM,2) + i3_l = LBOUND(SrcRtHndSideData%AngVelEM,3) + i3_u = UBOUND(SrcRtHndSideData%AngVelEM,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngVelEM)) THEN + ALLOCATE(DstRtHndSideData%AngVelEM(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngVelEM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngVelEM = SrcRtHndSideData%AngVelEM +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEN)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEN,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEN,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEN,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEN,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEN,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEN,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEN)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEN(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEN = SrcRtHndSideData%PAngVelEN +ENDIF + DstRtHndSideData%AngVelEA = SrcRtHndSideData%AngVelEA +IF (ALLOCATED(SrcRtHndSideData%PAngVelEB)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEB,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEB,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEB,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEB,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEB,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEB,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEB)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEB = SrcRtHndSideData%PAngVelEB +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelER)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelER,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelER,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelER,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelER,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelER,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelER,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelER)) THEN + ALLOCATE(DstRtHndSideData%PAngVelER(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelER.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelER = SrcRtHndSideData%PAngVelER +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PAngVelEX)) THEN + i1_l = LBOUND(SrcRtHndSideData%PAngVelEX,1) + i1_u = UBOUND(SrcRtHndSideData%PAngVelEX,1) + i2_l = LBOUND(SrcRtHndSideData%PAngVelEX,2) + i2_u = UBOUND(SrcRtHndSideData%PAngVelEX,2) + i3_l = LBOUND(SrcRtHndSideData%PAngVelEX,3) + i3_u = UBOUND(SrcRtHndSideData%PAngVelEX,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PAngVelEX)) THEN + ALLOCATE(DstRtHndSideData%PAngVelEX(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PAngVelEX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PAngVelEX = SrcRtHndSideData%PAngVelEX +ENDIF + DstRtHndSideData%AngVelEG = SrcRtHndSideData%AngVelEG + DstRtHndSideData%AngVelEH = SrcRtHndSideData%AngVelEH + DstRtHndSideData%AngVelEL = SrcRtHndSideData%AngVelEL + DstRtHndSideData%AngVelEN = SrcRtHndSideData%AngVelEN + DstRtHndSideData%AngVelEB = SrcRtHndSideData%AngVelEB + DstRtHndSideData%AngVelER = SrcRtHndSideData%AngVelER + DstRtHndSideData%AngVelEX = SrcRtHndSideData%AngVelEX + DstRtHndSideData%TeetAngVel = SrcRtHndSideData%TeetAngVel + DstRtHndSideData%AngAccEBt = SrcRtHndSideData%AngAccEBt + DstRtHndSideData%AngAccERt = SrcRtHndSideData%AngAccERt + DstRtHndSideData%AngAccEXt = SrcRtHndSideData%AngAccEXt +IF (ALLOCATED(SrcRtHndSideData%AngAccEFt)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngAccEFt,1) + i1_u = UBOUND(SrcRtHndSideData%AngAccEFt,1) + i2_l = LBOUND(SrcRtHndSideData%AngAccEFt,2) + i2_u = UBOUND(SrcRtHndSideData%AngAccEFt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngAccEFt)) THEN + ALLOCATE(DstRtHndSideData%AngAccEFt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngAccEFt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngAccEFt = SrcRtHndSideData%AngAccEFt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%AngVelEF)) THEN + i1_l = LBOUND(SrcRtHndSideData%AngVelEF,1) + i1_u = UBOUND(SrcRtHndSideData%AngVelEF,1) + i2_l = LBOUND(SrcRtHndSideData%AngVelEF,2) + i2_u = UBOUND(SrcRtHndSideData%AngVelEF,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%AngVelEF)) THEN + ALLOCATE(DstRtHndSideData%AngVelEF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%AngVelEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%AngVelEF = SrcRtHndSideData%AngVelEF +ENDIF + DstRtHndSideData%AngAccEAt = SrcRtHndSideData%AngAccEAt + DstRtHndSideData%AngAccEGt = SrcRtHndSideData%AngAccEGt + DstRtHndSideData%AngAccEHt = SrcRtHndSideData%AngAccEHt + DstRtHndSideData%AngAccENt = SrcRtHndSideData%AngAccENt + DstRtHndSideData%LinAccECt = SrcRtHndSideData%LinAccECt + DstRtHndSideData%LinAccEDt = SrcRtHndSideData%LinAccEDt + DstRtHndSideData%LinAccEIt = SrcRtHndSideData%LinAccEIt + DstRtHndSideData%LinAccEJt = SrcRtHndSideData%LinAccEJt + DstRtHndSideData%LinAccEUt = SrcRtHndSideData%LinAccEUt + DstRtHndSideData%LinAccEYt = SrcRtHndSideData%LinAccEYt +IF (ALLOCATED(SrcRtHndSideData%LinVelES)) THEN + i1_l = LBOUND(SrcRtHndSideData%LinVelES,1) + i1_u = UBOUND(SrcRtHndSideData%LinVelES,1) + i2_l = LBOUND(SrcRtHndSideData%LinVelES,2) + i2_u = UBOUND(SrcRtHndSideData%LinVelES,2) + i3_l = LBOUND(SrcRtHndSideData%LinVelES,3) + i3_u = UBOUND(SrcRtHndSideData%LinVelES,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%LinVelES)) THEN + ALLOCATE(DstRtHndSideData%LinVelES(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%LinVelES.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%LinVelES = SrcRtHndSideData%LinVelES +ENDIF + DstRtHndSideData%LinVelEQ = SrcRtHndSideData%LinVelEQ +IF (ALLOCATED(SrcRtHndSideData%LinVelET)) THEN + i1_l = LBOUND(SrcRtHndSideData%LinVelET,1) + i1_u = UBOUND(SrcRtHndSideData%LinVelET,1) + i2_l = LBOUND(SrcRtHndSideData%LinVelET,2) + i2_u = UBOUND(SrcRtHndSideData%LinVelET,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%LinVelET)) THEN + ALLOCATE(DstRtHndSideData%LinVelET(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%LinVelET.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%LinVelET = SrcRtHndSideData%LinVelET +ENDIF +IF (ALLOCATED(SrcRtHndSideData%LinVelESm2)) THEN + i1_l = LBOUND(SrcRtHndSideData%LinVelESm2,1) + i1_u = UBOUND(SrcRtHndSideData%LinVelESm2,1) + IF (.NOT. ALLOCATED(DstRtHndSideData%LinVelESm2)) THEN + ALLOCATE(DstRtHndSideData%LinVelESm2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%LinVelESm2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%LinVelESm2 = SrcRtHndSideData%LinVelESm2 +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEIMU)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEIMU,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEIMU,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEIMU,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEIMU,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEIMU,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEIMU,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEIMU)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEIMU(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEIMU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEIMU = SrcRtHndSideData%PLinVelEIMU +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEO)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEO,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEO,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEO,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEO,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEO,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEO,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEO)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEO(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEO.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEO = SrcRtHndSideData%PLinVelEO +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelES)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelES,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelES,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelES,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelES,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelES,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelES,3) + i4_l = LBOUND(SrcRtHndSideData%PLinVelES,4) + i4_u = UBOUND(SrcRtHndSideData%PLinVelES,4) + i5_l = LBOUND(SrcRtHndSideData%PLinVelES,5) + i5_u = UBOUND(SrcRtHndSideData%PLinVelES,5) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelES)) THEN + ALLOCATE(DstRtHndSideData%PLinVelES(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 DstRtHndSideData%PLinVelES.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelES = SrcRtHndSideData%PLinVelES +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelET)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelET,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelET,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelET,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelET,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelET,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelET,3) + i4_l = LBOUND(SrcRtHndSideData%PLinVelET,4) + i4_u = UBOUND(SrcRtHndSideData%PLinVelET,4) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelET)) THEN + ALLOCATE(DstRtHndSideData%PLinVelET(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 DstRtHndSideData%PLinVelET.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelET = SrcRtHndSideData%PLinVelET +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEZ)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEZ,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEZ,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEZ,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEZ,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEZ,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEZ,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEZ)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEZ(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEZ = SrcRtHndSideData%PLinVelEZ +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEC)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEC,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEC,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEC,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEC,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEC,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEC,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEC)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEC(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEC = SrcRtHndSideData%PLinVelEC +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelED)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelED,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelED,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelED,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelED,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelED,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelED,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelED)) THEN + ALLOCATE(DstRtHndSideData%PLinVelED(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelED = SrcRtHndSideData%PLinVelED +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEI)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEI,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEI,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEI,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEI,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEI,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEI,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEI)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEI(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEI = SrcRtHndSideData%PLinVelEI +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEJ)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEJ,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEJ,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEJ,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEJ,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEJ,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEJ,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEJ)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEJ(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEJ = SrcRtHndSideData%PLinVelEJ +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEK)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEK,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEK,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEK,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEK,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEK,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEK,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEK)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEK(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEK = SrcRtHndSideData%PLinVelEK +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEP)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEP,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEP,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEP,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEP,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEP,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEP,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEP)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEP = SrcRtHndSideData%PLinVelEP +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEQ)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEQ,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEQ,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEQ,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEQ,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEQ,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEQ,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEQ)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEQ(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEQ = SrcRtHndSideData%PLinVelEQ +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEU)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEU,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEU,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEU,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEU,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEU,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEU,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEU)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEU(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEU = SrcRtHndSideData%PLinVelEU +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEV)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEV,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEV,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEV,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEV,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEV,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEV,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEV)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEV(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEV = SrcRtHndSideData%PLinVelEV +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEW)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEW,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEW,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEW,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEW,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEW,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEW,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEW)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEW(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEW = SrcRtHndSideData%PLinVelEW +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PLinVelEY)) THEN + i1_l = LBOUND(SrcRtHndSideData%PLinVelEY,1) + i1_u = UBOUND(SrcRtHndSideData%PLinVelEY,1) + i2_l = LBOUND(SrcRtHndSideData%PLinVelEY,2) + i2_u = UBOUND(SrcRtHndSideData%PLinVelEY,2) + i3_l = LBOUND(SrcRtHndSideData%PLinVelEY,3) + i3_u = UBOUND(SrcRtHndSideData%PLinVelEY,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PLinVelEY)) THEN + ALLOCATE(DstRtHndSideData%PLinVelEY(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PLinVelEY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PLinVelEY = SrcRtHndSideData%PLinVelEY +ENDIF + DstRtHndSideData%LinAccEIMUt = SrcRtHndSideData%LinAccEIMUt + DstRtHndSideData%LinAccEOt = SrcRtHndSideData%LinAccEOt +IF (ALLOCATED(SrcRtHndSideData%LinAccESt)) THEN + i1_l = LBOUND(SrcRtHndSideData%LinAccESt,1) + i1_u = UBOUND(SrcRtHndSideData%LinAccESt,1) + i2_l = LBOUND(SrcRtHndSideData%LinAccESt,2) + i2_u = UBOUND(SrcRtHndSideData%LinAccESt,2) + i3_l = LBOUND(SrcRtHndSideData%LinAccESt,3) + i3_u = UBOUND(SrcRtHndSideData%LinAccESt,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%LinAccESt)) THEN + ALLOCATE(DstRtHndSideData%LinAccESt(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%LinAccESt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%LinAccESt = SrcRtHndSideData%LinAccESt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%LinAccETt)) THEN + i1_l = LBOUND(SrcRtHndSideData%LinAccETt,1) + i1_u = UBOUND(SrcRtHndSideData%LinAccETt,1) + i2_l = LBOUND(SrcRtHndSideData%LinAccETt,2) + i2_u = UBOUND(SrcRtHndSideData%LinAccETt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%LinAccETt)) THEN + ALLOCATE(DstRtHndSideData%LinAccETt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%LinAccETt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%LinAccETt = SrcRtHndSideData%LinAccETt +ENDIF + DstRtHndSideData%LinAccEZt = SrcRtHndSideData%LinAccEZt + DstRtHndSideData%LinVelEIMU = SrcRtHndSideData%LinVelEIMU + DstRtHndSideData%LinVelEZ = SrcRtHndSideData%LinVelEZ + DstRtHndSideData%LinVelEO = SrcRtHndSideData%LinVelEO + DstRtHndSideData%FrcONcRtt = SrcRtHndSideData%FrcONcRtt + DstRtHndSideData%FrcPRott = SrcRtHndSideData%FrcPRott +IF (ALLOCATED(SrcRtHndSideData%FrcS0Bt)) THEN + i1_l = LBOUND(SrcRtHndSideData%FrcS0Bt,1) + i1_u = UBOUND(SrcRtHndSideData%FrcS0Bt,1) + i2_l = LBOUND(SrcRtHndSideData%FrcS0Bt,2) + i2_u = UBOUND(SrcRtHndSideData%FrcS0Bt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%FrcS0Bt)) THEN + ALLOCATE(DstRtHndSideData%FrcS0Bt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%FrcS0Bt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%FrcS0Bt = SrcRtHndSideData%FrcS0Bt +ENDIF + DstRtHndSideData%FrcT0Trbt = SrcRtHndSideData%FrcT0Trbt +IF (ALLOCATED(SrcRtHndSideData%FSAero)) THEN + i1_l = LBOUND(SrcRtHndSideData%FSAero,1) + i1_u = UBOUND(SrcRtHndSideData%FSAero,1) + i2_l = LBOUND(SrcRtHndSideData%FSAero,2) + i2_u = UBOUND(SrcRtHndSideData%FSAero,2) + i3_l = LBOUND(SrcRtHndSideData%FSAero,3) + i3_u = UBOUND(SrcRtHndSideData%FSAero,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%FSAero)) THEN + ALLOCATE(DstRtHndSideData%FSAero(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%FSAero.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%FSAero = SrcRtHndSideData%FSAero +ENDIF +IF (ALLOCATED(SrcRtHndSideData%FSTipDrag)) THEN + i1_l = LBOUND(SrcRtHndSideData%FSTipDrag,1) + i1_u = UBOUND(SrcRtHndSideData%FSTipDrag,1) + i2_l = LBOUND(SrcRtHndSideData%FSTipDrag,2) + i2_u = UBOUND(SrcRtHndSideData%FSTipDrag,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%FSTipDrag)) THEN + ALLOCATE(DstRtHndSideData%FSTipDrag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%FSTipDrag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%FSTipDrag = SrcRtHndSideData%FSTipDrag +ENDIF +IF (ALLOCATED(SrcRtHndSideData%FTHydrot)) THEN + i1_l = LBOUND(SrcRtHndSideData%FTHydrot,1) + i1_u = UBOUND(SrcRtHndSideData%FTHydrot,1) + i2_l = LBOUND(SrcRtHndSideData%FTHydrot,2) + i2_u = UBOUND(SrcRtHndSideData%FTHydrot,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%FTHydrot)) THEN + ALLOCATE(DstRtHndSideData%FTHydrot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%FTHydrot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%FTHydrot = SrcRtHndSideData%FTHydrot +ENDIF + DstRtHndSideData%FZHydrot = SrcRtHndSideData%FZHydrot +IF (ALLOCATED(SrcRtHndSideData%MFHydrot)) THEN + i1_l = LBOUND(SrcRtHndSideData%MFHydrot,1) + i1_u = UBOUND(SrcRtHndSideData%MFHydrot,1) + i2_l = LBOUND(SrcRtHndSideData%MFHydrot,2) + i2_u = UBOUND(SrcRtHndSideData%MFHydrot,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%MFHydrot)) THEN + ALLOCATE(DstRtHndSideData%MFHydrot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%MFHydrot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%MFHydrot = SrcRtHndSideData%MFHydrot +ENDIF + DstRtHndSideData%MomBNcRtt = SrcRtHndSideData%MomBNcRtt +IF (ALLOCATED(SrcRtHndSideData%MomH0Bt)) THEN + i1_l = LBOUND(SrcRtHndSideData%MomH0Bt,1) + i1_u = UBOUND(SrcRtHndSideData%MomH0Bt,1) + i2_l = LBOUND(SrcRtHndSideData%MomH0Bt,2) + i2_u = UBOUND(SrcRtHndSideData%MomH0Bt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%MomH0Bt)) THEN + ALLOCATE(DstRtHndSideData%MomH0Bt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%MomH0Bt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%MomH0Bt = SrcRtHndSideData%MomH0Bt +ENDIF + DstRtHndSideData%MomLPRott = SrcRtHndSideData%MomLPRott + DstRtHndSideData%MomNGnRtt = SrcRtHndSideData%MomNGnRtt + DstRtHndSideData%MomNTailt = SrcRtHndSideData%MomNTailt + DstRtHndSideData%MomX0Trbt = SrcRtHndSideData%MomX0Trbt +IF (ALLOCATED(SrcRtHndSideData%MMAero)) THEN + i1_l = LBOUND(SrcRtHndSideData%MMAero,1) + i1_u = UBOUND(SrcRtHndSideData%MMAero,1) + i2_l = LBOUND(SrcRtHndSideData%MMAero,2) + i2_u = UBOUND(SrcRtHndSideData%MMAero,2) + i3_l = LBOUND(SrcRtHndSideData%MMAero,3) + i3_u = UBOUND(SrcRtHndSideData%MMAero,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%MMAero)) THEN + ALLOCATE(DstRtHndSideData%MMAero(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%MMAero.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%MMAero = SrcRtHndSideData%MMAero +ENDIF + DstRtHndSideData%MXHydrot = SrcRtHndSideData%MXHydrot +IF (ALLOCATED(SrcRtHndSideData%PFrcONcRt)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcONcRt,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcONcRt,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcONcRt,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcONcRt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcONcRt)) THEN + ALLOCATE(DstRtHndSideData%PFrcONcRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcONcRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcONcRt = SrcRtHndSideData%PFrcONcRt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFrcPRot)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcPRot,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcPRot,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcPRot,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcPRot,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcPRot)) THEN + ALLOCATE(DstRtHndSideData%PFrcPRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcPRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcPRot = SrcRtHndSideData%PFrcPRot +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFrcS0B)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcS0B,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcS0B,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcS0B,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcS0B,2) + i3_l = LBOUND(SrcRtHndSideData%PFrcS0B,3) + i3_u = UBOUND(SrcRtHndSideData%PFrcS0B,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcS0B)) THEN + ALLOCATE(DstRtHndSideData%PFrcS0B(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcS0B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcS0B = SrcRtHndSideData%PFrcS0B +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFrcT0Trb)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcT0Trb,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcT0Trb,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcT0Trb,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcT0Trb,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcT0Trb)) THEN + ALLOCATE(DstRtHndSideData%PFrcT0Trb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcT0Trb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcT0Trb = SrcRtHndSideData%PFrcT0Trb +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFTHydro)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFTHydro,1) + i1_u = UBOUND(SrcRtHndSideData%PFTHydro,1) + i2_l = LBOUND(SrcRtHndSideData%PFTHydro,2) + i2_u = UBOUND(SrcRtHndSideData%PFTHydro,2) + i3_l = LBOUND(SrcRtHndSideData%PFTHydro,3) + i3_u = UBOUND(SrcRtHndSideData%PFTHydro,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFTHydro)) THEN + ALLOCATE(DstRtHndSideData%PFTHydro(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFTHydro.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFTHydro = SrcRtHndSideData%PFTHydro +ENDIF + DstRtHndSideData%PFZHydro = SrcRtHndSideData%PFZHydro +IF (ALLOCATED(SrcRtHndSideData%PMFHydro)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMFHydro,1) + i1_u = UBOUND(SrcRtHndSideData%PMFHydro,1) + i2_l = LBOUND(SrcRtHndSideData%PMFHydro,2) + i2_u = UBOUND(SrcRtHndSideData%PMFHydro,2) + i3_l = LBOUND(SrcRtHndSideData%PMFHydro,3) + i3_u = UBOUND(SrcRtHndSideData%PMFHydro,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMFHydro)) THEN + ALLOCATE(DstRtHndSideData%PMFHydro(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMFHydro.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMFHydro = SrcRtHndSideData%PMFHydro +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomBNcRt)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomBNcRt,1) + i1_u = UBOUND(SrcRtHndSideData%PMomBNcRt,1) + i2_l = LBOUND(SrcRtHndSideData%PMomBNcRt,2) + i2_u = UBOUND(SrcRtHndSideData%PMomBNcRt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomBNcRt)) THEN + ALLOCATE(DstRtHndSideData%PMomBNcRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomBNcRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomBNcRt = SrcRtHndSideData%PMomBNcRt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomH0B)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomH0B,1) + i1_u = UBOUND(SrcRtHndSideData%PMomH0B,1) + i2_l = LBOUND(SrcRtHndSideData%PMomH0B,2) + i2_u = UBOUND(SrcRtHndSideData%PMomH0B,2) + i3_l = LBOUND(SrcRtHndSideData%PMomH0B,3) + i3_u = UBOUND(SrcRtHndSideData%PMomH0B,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomH0B)) THEN + ALLOCATE(DstRtHndSideData%PMomH0B(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomH0B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomH0B = SrcRtHndSideData%PMomH0B +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomLPRot)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomLPRot,1) + i1_u = UBOUND(SrcRtHndSideData%PMomLPRot,1) + i2_l = LBOUND(SrcRtHndSideData%PMomLPRot,2) + i2_u = UBOUND(SrcRtHndSideData%PMomLPRot,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomLPRot)) THEN + ALLOCATE(DstRtHndSideData%PMomLPRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomLPRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomLPRot = SrcRtHndSideData%PMomLPRot +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomNGnRt)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomNGnRt,1) + i1_u = UBOUND(SrcRtHndSideData%PMomNGnRt,1) + i2_l = LBOUND(SrcRtHndSideData%PMomNGnRt,2) + i2_u = UBOUND(SrcRtHndSideData%PMomNGnRt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomNGnRt)) THEN + ALLOCATE(DstRtHndSideData%PMomNGnRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomNGnRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomNGnRt = SrcRtHndSideData%PMomNGnRt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomNTail)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomNTail,1) + i1_u = UBOUND(SrcRtHndSideData%PMomNTail,1) + i2_l = LBOUND(SrcRtHndSideData%PMomNTail,2) + i2_u = UBOUND(SrcRtHndSideData%PMomNTail,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomNTail)) THEN + ALLOCATE(DstRtHndSideData%PMomNTail(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomNTail.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomNTail = SrcRtHndSideData%PMomNTail +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomX0Trb)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomX0Trb,1) + i1_u = UBOUND(SrcRtHndSideData%PMomX0Trb,1) + i2_l = LBOUND(SrcRtHndSideData%PMomX0Trb,2) + i2_u = UBOUND(SrcRtHndSideData%PMomX0Trb,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomX0Trb)) THEN + ALLOCATE(DstRtHndSideData%PMomX0Trb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomX0Trb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomX0Trb = SrcRtHndSideData%PMomX0Trb +ENDIF + DstRtHndSideData%PMXHydro = SrcRtHndSideData%PMXHydro + DstRtHndSideData%TeetAng = SrcRtHndSideData%TeetAng + DstRtHndSideData%FrcVGnRtt = SrcRtHndSideData%FrcVGnRtt + DstRtHndSideData%FrcWTailt = SrcRtHndSideData%FrcWTailt + DstRtHndSideData%FrcZAllt = SrcRtHndSideData%FrcZAllt + DstRtHndSideData%MomXAllt = SrcRtHndSideData%MomXAllt +IF (ALLOCATED(SrcRtHndSideData%PFrcVGnRt)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcVGnRt,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcVGnRt,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcVGnRt,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcVGnRt,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcVGnRt)) THEN + ALLOCATE(DstRtHndSideData%PFrcVGnRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcVGnRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcVGnRt = SrcRtHndSideData%PFrcVGnRt +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFrcWTail)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcWTail,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcWTail,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcWTail,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcWTail,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcWTail)) THEN + ALLOCATE(DstRtHndSideData%PFrcWTail(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcWTail.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcWTail = SrcRtHndSideData%PFrcWTail +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PFrcZAll)) THEN + i1_l = LBOUND(SrcRtHndSideData%PFrcZAll,1) + i1_u = UBOUND(SrcRtHndSideData%PFrcZAll,1) + i2_l = LBOUND(SrcRtHndSideData%PFrcZAll,2) + i2_u = UBOUND(SrcRtHndSideData%PFrcZAll,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PFrcZAll)) THEN + ALLOCATE(DstRtHndSideData%PFrcZAll(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PFrcZAll.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PFrcZAll = SrcRtHndSideData%PFrcZAll +ENDIF +IF (ALLOCATED(SrcRtHndSideData%PMomXAll)) THEN + i1_l = LBOUND(SrcRtHndSideData%PMomXAll,1) + i1_u = UBOUND(SrcRtHndSideData%PMomXAll,1) + i2_l = LBOUND(SrcRtHndSideData%PMomXAll,2) + i2_u = UBOUND(SrcRtHndSideData%PMomXAll,2) + IF (.NOT. ALLOCATED(DstRtHndSideData%PMomXAll)) THEN + ALLOCATE(DstRtHndSideData%PMomXAll(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%PMomXAll.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%PMomXAll = SrcRtHndSideData%PMomXAll +ENDIF + DstRtHndSideData%TeetMom = SrcRtHndSideData%TeetMom + DstRtHndSideData%TFrlMom = SrcRtHndSideData%TFrlMom + DstRtHndSideData%RFrlMom = SrcRtHndSideData%RFrlMom + DstRtHndSideData%GBoxEffFac = SrcRtHndSideData%GBoxEffFac +IF (ALLOCATED(SrcRtHndSideData%rSAerCen)) THEN + i1_l = LBOUND(SrcRtHndSideData%rSAerCen,1) + i1_u = UBOUND(SrcRtHndSideData%rSAerCen,1) + i2_l = LBOUND(SrcRtHndSideData%rSAerCen,2) + i2_u = UBOUND(SrcRtHndSideData%rSAerCen,2) + i3_l = LBOUND(SrcRtHndSideData%rSAerCen,3) + i3_u = UBOUND(SrcRtHndSideData%rSAerCen,3) + IF (.NOT. ALLOCATED(DstRtHndSideData%rSAerCen)) THEN + ALLOCATE(DstRtHndSideData%rSAerCen(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRtHndSideData%rSAerCen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstRtHndSideData%rSAerCen = SrcRtHndSideData%rSAerCen +ENDIF + END SUBROUTINE ED_CopyRtHndSide + + SUBROUTINE ED_DestroyRtHndSide( RtHndSideData, ErrStat, ErrMsg ) + TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHndSideData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyRtHndSide' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(RtHndSideData%rQS)) THEN + DEALLOCATE(RtHndSideData%rQS) +ENDIF +IF (ALLOCATED(RtHndSideData%rS)) THEN + DEALLOCATE(RtHndSideData%rS) +ENDIF +IF (ALLOCATED(RtHndSideData%rS0S)) THEN + DEALLOCATE(RtHndSideData%rS0S) +ENDIF +IF (ALLOCATED(RtHndSideData%rT)) THEN + DEALLOCATE(RtHndSideData%rT) +ENDIF +IF (ALLOCATED(RtHndSideData%rT0T)) THEN + DEALLOCATE(RtHndSideData%rT0T) +ENDIF +IF (ALLOCATED(RtHndSideData%rZT)) THEN + DEALLOCATE(RtHndSideData%rZT) +ENDIF +IF (ALLOCATED(RtHndSideData%rPS0)) THEN + DEALLOCATE(RtHndSideData%rPS0) +ENDIF +IF (ALLOCATED(RtHndSideData%AngPosEF)) THEN + DEALLOCATE(RtHndSideData%AngPosEF) +ENDIF +IF (ALLOCATED(RtHndSideData%AngPosXF)) THEN + DEALLOCATE(RtHndSideData%AngPosXF) +ENDIF +IF (ALLOCATED(RtHndSideData%AngPosHM)) THEN + DEALLOCATE(RtHndSideData%AngPosHM) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEA)) THEN + DEALLOCATE(RtHndSideData%PAngVelEA) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEF)) THEN + DEALLOCATE(RtHndSideData%PAngVelEF) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEG)) THEN + DEALLOCATE(RtHndSideData%PAngVelEG) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEH)) THEN + DEALLOCATE(RtHndSideData%PAngVelEH) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEL)) THEN + DEALLOCATE(RtHndSideData%PAngVelEL) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEM)) THEN + DEALLOCATE(RtHndSideData%PAngVelEM) +ENDIF +IF (ALLOCATED(RtHndSideData%AngVelEM)) THEN + DEALLOCATE(RtHndSideData%AngVelEM) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEN)) THEN + DEALLOCATE(RtHndSideData%PAngVelEN) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEB)) THEN + DEALLOCATE(RtHndSideData%PAngVelEB) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelER)) THEN + DEALLOCATE(RtHndSideData%PAngVelER) +ENDIF +IF (ALLOCATED(RtHndSideData%PAngVelEX)) THEN + DEALLOCATE(RtHndSideData%PAngVelEX) +ENDIF +IF (ALLOCATED(RtHndSideData%AngAccEFt)) THEN + DEALLOCATE(RtHndSideData%AngAccEFt) +ENDIF +IF (ALLOCATED(RtHndSideData%AngVelEF)) THEN + DEALLOCATE(RtHndSideData%AngVelEF) +ENDIF +IF (ALLOCATED(RtHndSideData%LinVelES)) THEN + DEALLOCATE(RtHndSideData%LinVelES) +ENDIF +IF (ALLOCATED(RtHndSideData%LinVelET)) THEN + DEALLOCATE(RtHndSideData%LinVelET) +ENDIF +IF (ALLOCATED(RtHndSideData%LinVelESm2)) THEN + DEALLOCATE(RtHndSideData%LinVelESm2) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEIMU)) THEN + DEALLOCATE(RtHndSideData%PLinVelEIMU) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEO)) THEN + DEALLOCATE(RtHndSideData%PLinVelEO) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelES)) THEN + DEALLOCATE(RtHndSideData%PLinVelES) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelET)) THEN + DEALLOCATE(RtHndSideData%PLinVelET) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEZ)) THEN + DEALLOCATE(RtHndSideData%PLinVelEZ) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEC)) THEN + DEALLOCATE(RtHndSideData%PLinVelEC) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelED)) THEN + DEALLOCATE(RtHndSideData%PLinVelED) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEI)) THEN + DEALLOCATE(RtHndSideData%PLinVelEI) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEJ)) THEN + DEALLOCATE(RtHndSideData%PLinVelEJ) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEK)) THEN + DEALLOCATE(RtHndSideData%PLinVelEK) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEP)) THEN + DEALLOCATE(RtHndSideData%PLinVelEP) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEQ)) THEN + DEALLOCATE(RtHndSideData%PLinVelEQ) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEU)) THEN + DEALLOCATE(RtHndSideData%PLinVelEU) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEV)) THEN + DEALLOCATE(RtHndSideData%PLinVelEV) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEW)) THEN + DEALLOCATE(RtHndSideData%PLinVelEW) +ENDIF +IF (ALLOCATED(RtHndSideData%PLinVelEY)) THEN + DEALLOCATE(RtHndSideData%PLinVelEY) +ENDIF +IF (ALLOCATED(RtHndSideData%LinAccESt)) THEN + DEALLOCATE(RtHndSideData%LinAccESt) +ENDIF +IF (ALLOCATED(RtHndSideData%LinAccETt)) THEN + DEALLOCATE(RtHndSideData%LinAccETt) +ENDIF +IF (ALLOCATED(RtHndSideData%FrcS0Bt)) THEN + DEALLOCATE(RtHndSideData%FrcS0Bt) +ENDIF +IF (ALLOCATED(RtHndSideData%FSAero)) THEN + DEALLOCATE(RtHndSideData%FSAero) +ENDIF +IF (ALLOCATED(RtHndSideData%FSTipDrag)) THEN + DEALLOCATE(RtHndSideData%FSTipDrag) +ENDIF +IF (ALLOCATED(RtHndSideData%FTHydrot)) THEN + DEALLOCATE(RtHndSideData%FTHydrot) +ENDIF +IF (ALLOCATED(RtHndSideData%MFHydrot)) THEN + DEALLOCATE(RtHndSideData%MFHydrot) +ENDIF +IF (ALLOCATED(RtHndSideData%MomH0Bt)) THEN + DEALLOCATE(RtHndSideData%MomH0Bt) +ENDIF +IF (ALLOCATED(RtHndSideData%MMAero)) THEN + DEALLOCATE(RtHndSideData%MMAero) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcONcRt)) THEN + DEALLOCATE(RtHndSideData%PFrcONcRt) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcPRot)) THEN + DEALLOCATE(RtHndSideData%PFrcPRot) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcS0B)) THEN + DEALLOCATE(RtHndSideData%PFrcS0B) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcT0Trb)) THEN + DEALLOCATE(RtHndSideData%PFrcT0Trb) +ENDIF +IF (ALLOCATED(RtHndSideData%PFTHydro)) THEN + DEALLOCATE(RtHndSideData%PFTHydro) +ENDIF +IF (ALLOCATED(RtHndSideData%PMFHydro)) THEN + DEALLOCATE(RtHndSideData%PMFHydro) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomBNcRt)) THEN + DEALLOCATE(RtHndSideData%PMomBNcRt) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomH0B)) THEN + DEALLOCATE(RtHndSideData%PMomH0B) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomLPRot)) THEN + DEALLOCATE(RtHndSideData%PMomLPRot) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomNGnRt)) THEN + DEALLOCATE(RtHndSideData%PMomNGnRt) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomNTail)) THEN + DEALLOCATE(RtHndSideData%PMomNTail) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomX0Trb)) THEN + DEALLOCATE(RtHndSideData%PMomX0Trb) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcVGnRt)) THEN + DEALLOCATE(RtHndSideData%PFrcVGnRt) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcWTail)) THEN + DEALLOCATE(RtHndSideData%PFrcWTail) +ENDIF +IF (ALLOCATED(RtHndSideData%PFrcZAll)) THEN + DEALLOCATE(RtHndSideData%PFrcZAll) +ENDIF +IF (ALLOCATED(RtHndSideData%PMomXAll)) THEN + DEALLOCATE(RtHndSideData%PMomXAll) +ENDIF +IF (ALLOCATED(RtHndSideData%rSAerCen)) THEN + DEALLOCATE(RtHndSideData%rSAerCen) +ENDIF + END SUBROUTINE ED_DestroyRtHndSide + + SUBROUTINE ED_PackRtHndSide( 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(ED_RtHndSide), 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 = 'ED_PackRtHndSide' + ! 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 + Db_BufSz = Db_BufSz + SIZE(InData%rO) ! rO + Int_BufSz = Int_BufSz + 1 ! rQS allocated yes/no + IF ( ALLOCATED(InData%rQS) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rQS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rQS) ! rQS + END IF + Int_BufSz = Int_BufSz + 1 ! rS allocated yes/no + IF ( ALLOCATED(InData%rS) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rS) ! rS + END IF + Int_BufSz = Int_BufSz + 1 ! rS0S allocated yes/no + IF ( ALLOCATED(InData%rS0S) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rS0S upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rS0S) ! rS0S + END IF + Int_BufSz = Int_BufSz + 1 ! rT allocated yes/no + IF ( ALLOCATED(InData%rT) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rT upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rT) ! rT + END IF + Db_BufSz = Db_BufSz + SIZE(InData%rT0O) ! rT0O + Int_BufSz = Int_BufSz + 1 ! rT0T allocated yes/no + IF ( ALLOCATED(InData%rT0T) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rT0T upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rT0T) ! rT0T + END IF + Db_BufSz = Db_BufSz + SIZE(InData%rZ) ! rZ + Db_BufSz = Db_BufSz + SIZE(InData%rZO) ! rZO + Int_BufSz = Int_BufSz + 1 ! rZT allocated yes/no + IF ( ALLOCATED(InData%rZT) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rZT upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rZT) ! rZT + END IF + Db_BufSz = Db_BufSz + SIZE(InData%rPQ) ! rPQ + Db_BufSz = Db_BufSz + SIZE(InData%rP) ! rP + Db_BufSz = Db_BufSz + SIZE(InData%rV) ! rV + Db_BufSz = Db_BufSz + SIZE(InData%rZY) ! rZY + Db_BufSz = Db_BufSz + SIZE(InData%rOU) ! rOU + Db_BufSz = Db_BufSz + SIZE(InData%rOV) ! rOV + Db_BufSz = Db_BufSz + SIZE(InData%rVD) ! rVD + Db_BufSz = Db_BufSz + SIZE(InData%rOW) ! rOW + Db_BufSz = Db_BufSz + SIZE(InData%rPC) ! rPC + Int_BufSz = Int_BufSz + 1 ! rPS0 allocated yes/no + IF ( ALLOCATED(InData%rPS0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rPS0 upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%rPS0) ! rPS0 + END IF + Db_BufSz = Db_BufSz + SIZE(InData%rQ) ! rQ + Db_BufSz = Db_BufSz + SIZE(InData%rQC) ! rQC + Db_BufSz = Db_BufSz + SIZE(InData%rVIMU) ! rVIMU + Db_BufSz = Db_BufSz + SIZE(InData%rVP) ! rVP + Db_BufSz = Db_BufSz + SIZE(InData%rWI) ! rWI + Db_BufSz = Db_BufSz + SIZE(InData%rWJ) ! rWJ + Db_BufSz = Db_BufSz + SIZE(InData%rWK) ! rWK + Db_BufSz = Db_BufSz + SIZE(InData%rZT0) ! rZT0 + Int_BufSz = Int_BufSz + 1 ! AngPosEF allocated yes/no + IF ( ALLOCATED(InData%AngPosEF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AngPosEF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngPosEF) ! AngPosEF + END IF + Int_BufSz = Int_BufSz + 1 ! AngPosXF allocated yes/no + IF ( ALLOCATED(InData%AngPosXF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AngPosXF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngPosXF) ! AngPosXF + END IF + Int_BufSz = Int_BufSz + 1 ! AngPosHM allocated yes/no + IF ( ALLOCATED(InData%AngPosHM) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AngPosHM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngPosHM) ! AngPosHM + END IF + Re_BufSz = Re_BufSz + SIZE(InData%AngPosXB) ! AngPosXB + Re_BufSz = Re_BufSz + SIZE(InData%AngPosEX) ! AngPosEX + Int_BufSz = Int_BufSz + 1 ! PAngVelEA allocated yes/no + IF ( ALLOCATED(InData%PAngVelEA) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEA) ! PAngVelEA + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEF allocated yes/no + IF ( ALLOCATED(InData%PAngVelEF) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! PAngVelEF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEF) ! PAngVelEF + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEG allocated yes/no + IF ( ALLOCATED(InData%PAngVelEG) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEG) ! PAngVelEG + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEH allocated yes/no + IF ( ALLOCATED(InData%PAngVelEH) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEH upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEH) ! PAngVelEH + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEL allocated yes/no + IF ( ALLOCATED(InData%PAngVelEL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEL) ! PAngVelEL + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEM allocated yes/no + IF ( ALLOCATED(InData%PAngVelEM) ) THEN + Int_BufSz = Int_BufSz + 2*5 ! PAngVelEM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEM) ! PAngVelEM + END IF + Int_BufSz = Int_BufSz + 1 ! AngVelEM allocated yes/no + IF ( ALLOCATED(InData%AngVelEM) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AngVelEM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEM) ! AngVelEM + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEN allocated yes/no + IF ( ALLOCATED(InData%PAngVelEN) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEN upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEN) ! PAngVelEN + END IF + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEA) ! AngVelEA + Int_BufSz = Int_BufSz + 1 ! PAngVelEB allocated yes/no + IF ( ALLOCATED(InData%PAngVelEB) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEB) ! PAngVelEB + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelER allocated yes/no + IF ( ALLOCATED(InData%PAngVelER) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelER upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelER) ! PAngVelER + END IF + Int_BufSz = Int_BufSz + 1 ! PAngVelEX allocated yes/no + IF ( ALLOCATED(InData%PAngVelEX) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PAngVelEX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PAngVelEX) ! PAngVelEX + END IF + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEG) ! AngVelEG + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEH) ! AngVelEH + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEL) ! AngVelEL + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEN) ! AngVelEN + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEB) ! AngVelEB + Re_BufSz = Re_BufSz + SIZE(InData%AngVelER) ! AngVelER + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEX) ! AngVelEX + Db_BufSz = Db_BufSz + 1 ! TeetAngVel + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEBt) ! AngAccEBt + Re_BufSz = Re_BufSz + SIZE(InData%AngAccERt) ! AngAccERt + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEXt) ! AngAccEXt + Int_BufSz = Int_BufSz + 1 ! AngAccEFt allocated yes/no + IF ( ALLOCATED(InData%AngAccEFt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AngAccEFt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEFt) ! AngAccEFt + END IF + Int_BufSz = Int_BufSz + 1 ! AngVelEF allocated yes/no + IF ( ALLOCATED(InData%AngVelEF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AngVelEF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngVelEF) ! AngVelEF + END IF + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEAt) ! AngAccEAt + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEGt) ! AngAccEGt + Re_BufSz = Re_BufSz + SIZE(InData%AngAccEHt) ! AngAccEHt + Re_BufSz = Re_BufSz + SIZE(InData%AngAccENt) ! AngAccENt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccECt) ! LinAccECt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEDt) ! LinAccEDt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEIt) ! LinAccEIt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEJt) ! LinAccEJt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEUt) ! LinAccEUt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEYt) ! LinAccEYt + Int_BufSz = Int_BufSz + 1 ! LinVelES allocated yes/no + IF ( ALLOCATED(InData%LinVelES) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! LinVelES upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinVelES) ! LinVelES + END IF + Re_BufSz = Re_BufSz + SIZE(InData%LinVelEQ) ! LinVelEQ + Int_BufSz = Int_BufSz + 1 ! LinVelET allocated yes/no + IF ( ALLOCATED(InData%LinVelET) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LinVelET upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinVelET) ! LinVelET + END IF + Int_BufSz = Int_BufSz + 1 ! LinVelESm2 allocated yes/no + IF ( ALLOCATED(InData%LinVelESm2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinVelESm2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinVelESm2) ! LinVelESm2 + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEIMU allocated yes/no + IF ( ALLOCATED(InData%PLinVelEIMU) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEIMU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEIMU) ! PLinVelEIMU + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEO allocated yes/no + IF ( ALLOCATED(InData%PLinVelEO) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEO upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEO) ! PLinVelEO + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelES allocated yes/no + IF ( ALLOCATED(InData%PLinVelES) ) THEN + Int_BufSz = Int_BufSz + 2*5 ! PLinVelES upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelES) ! PLinVelES + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelET allocated yes/no + IF ( ALLOCATED(InData%PLinVelET) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! PLinVelET upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelET) ! PLinVelET + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEZ allocated yes/no + IF ( ALLOCATED(InData%PLinVelEZ) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEZ) ! PLinVelEZ + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEC allocated yes/no + IF ( ALLOCATED(InData%PLinVelEC) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEC) ! PLinVelEC + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelED allocated yes/no + IF ( ALLOCATED(InData%PLinVelED) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelED upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelED) ! PLinVelED + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEI allocated yes/no + IF ( ALLOCATED(InData%PLinVelEI) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEI) ! PLinVelEI + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEJ allocated yes/no + IF ( ALLOCATED(InData%PLinVelEJ) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEJ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEJ) ! PLinVelEJ + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEK allocated yes/no + IF ( ALLOCATED(InData%PLinVelEK) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEK upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEK) ! PLinVelEK + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEP allocated yes/no + IF ( ALLOCATED(InData%PLinVelEP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEP) ! PLinVelEP + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEQ allocated yes/no + IF ( ALLOCATED(InData%PLinVelEQ) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEQ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEQ) ! PLinVelEQ + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEU allocated yes/no + IF ( ALLOCATED(InData%PLinVelEU) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEU) ! PLinVelEU + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEV allocated yes/no + IF ( ALLOCATED(InData%PLinVelEV) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEV) ! PLinVelEV + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEW allocated yes/no + IF ( ALLOCATED(InData%PLinVelEW) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEW) ! PLinVelEW + END IF + Int_BufSz = Int_BufSz + 1 ! PLinVelEY allocated yes/no + IF ( ALLOCATED(InData%PLinVelEY) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PLinVelEY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PLinVelEY) ! PLinVelEY + END IF + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEIMUt) ! LinAccEIMUt + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEOt) ! LinAccEOt + Int_BufSz = Int_BufSz + 1 ! LinAccESt allocated yes/no + IF ( ALLOCATED(InData%LinAccESt) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! LinAccESt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinAccESt) ! LinAccESt + END IF + Int_BufSz = Int_BufSz + 1 ! LinAccETt allocated yes/no + IF ( ALLOCATED(InData%LinAccETt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LinAccETt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinAccETt) ! LinAccETt + END IF + Re_BufSz = Re_BufSz + SIZE(InData%LinAccEZt) ! LinAccEZt + Re_BufSz = Re_BufSz + SIZE(InData%LinVelEIMU) ! LinVelEIMU + Re_BufSz = Re_BufSz + SIZE(InData%LinVelEZ) ! LinVelEZ + Re_BufSz = Re_BufSz + SIZE(InData%LinVelEO) ! LinVelEO + Re_BufSz = Re_BufSz + SIZE(InData%FrcONcRtt) ! FrcONcRtt + Re_BufSz = Re_BufSz + SIZE(InData%FrcPRott) ! FrcPRott + Int_BufSz = Int_BufSz + 1 ! FrcS0Bt allocated yes/no + IF ( ALLOCATED(InData%FrcS0Bt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FrcS0Bt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FrcS0Bt) ! FrcS0Bt + END IF + Re_BufSz = Re_BufSz + SIZE(InData%FrcT0Trbt) ! FrcT0Trbt + Int_BufSz = Int_BufSz + 1 ! FSAero allocated yes/no + IF ( ALLOCATED(InData%FSAero) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FSAero upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSAero) ! FSAero + END IF + Int_BufSz = Int_BufSz + 1 ! FSTipDrag allocated yes/no + IF ( ALLOCATED(InData%FSTipDrag) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FSTipDrag upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FSTipDrag) ! FSTipDrag + END IF + Int_BufSz = Int_BufSz + 1 ! FTHydrot allocated yes/no + IF ( ALLOCATED(InData%FTHydrot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FTHydrot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FTHydrot) ! FTHydrot + END IF + Re_BufSz = Re_BufSz + SIZE(InData%FZHydrot) ! FZHydrot + Int_BufSz = Int_BufSz + 1 ! MFHydrot allocated yes/no + IF ( ALLOCATED(InData%MFHydrot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MFHydrot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MFHydrot) ! MFHydrot + END IF + Re_BufSz = Re_BufSz + SIZE(InData%MomBNcRtt) ! MomBNcRtt + Int_BufSz = Int_BufSz + 1 ! MomH0Bt allocated yes/no + IF ( ALLOCATED(InData%MomH0Bt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MomH0Bt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MomH0Bt) ! MomH0Bt + END IF + Re_BufSz = Re_BufSz + SIZE(InData%MomLPRott) ! MomLPRott + Re_BufSz = Re_BufSz + SIZE(InData%MomNGnRtt) ! MomNGnRtt + Re_BufSz = Re_BufSz + SIZE(InData%MomNTailt) ! MomNTailt + Re_BufSz = Re_BufSz + SIZE(InData%MomX0Trbt) ! MomX0Trbt + Int_BufSz = Int_BufSz + 1 ! MMAero allocated yes/no + IF ( ALLOCATED(InData%MMAero) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! MMAero upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MMAero) ! MMAero + END IF + Re_BufSz = Re_BufSz + SIZE(InData%MXHydrot) ! MXHydrot + Int_BufSz = Int_BufSz + 1 ! PFrcONcRt allocated yes/no + IF ( ALLOCATED(InData%PFrcONcRt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcONcRt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcONcRt) ! PFrcONcRt + END IF + Int_BufSz = Int_BufSz + 1 ! PFrcPRot allocated yes/no + IF ( ALLOCATED(InData%PFrcPRot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcPRot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcPRot) ! PFrcPRot + END IF + Int_BufSz = Int_BufSz + 1 ! PFrcS0B allocated yes/no + IF ( ALLOCATED(InData%PFrcS0B) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PFrcS0B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcS0B) ! PFrcS0B + END IF + Int_BufSz = Int_BufSz + 1 ! PFrcT0Trb allocated yes/no + IF ( ALLOCATED(InData%PFrcT0Trb) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcT0Trb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcT0Trb) ! PFrcT0Trb + END IF + Int_BufSz = Int_BufSz + 1 ! PFTHydro allocated yes/no + IF ( ALLOCATED(InData%PFTHydro) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PFTHydro upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFTHydro) ! PFTHydro + END IF + Re_BufSz = Re_BufSz + SIZE(InData%PFZHydro) ! PFZHydro + Int_BufSz = Int_BufSz + 1 ! PMFHydro allocated yes/no + IF ( ALLOCATED(InData%PMFHydro) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PMFHydro upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMFHydro) ! PMFHydro + END IF + Int_BufSz = Int_BufSz + 1 ! PMomBNcRt allocated yes/no + IF ( ALLOCATED(InData%PMomBNcRt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomBNcRt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomBNcRt) ! PMomBNcRt + END IF + Int_BufSz = Int_BufSz + 1 ! PMomH0B allocated yes/no + IF ( ALLOCATED(InData%PMomH0B) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PMomH0B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomH0B) ! PMomH0B + END IF + Int_BufSz = Int_BufSz + 1 ! PMomLPRot allocated yes/no + IF ( ALLOCATED(InData%PMomLPRot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomLPRot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomLPRot) ! PMomLPRot + END IF + Int_BufSz = Int_BufSz + 1 ! PMomNGnRt allocated yes/no + IF ( ALLOCATED(InData%PMomNGnRt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomNGnRt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomNGnRt) ! PMomNGnRt + END IF + Int_BufSz = Int_BufSz + 1 ! PMomNTail allocated yes/no + IF ( ALLOCATED(InData%PMomNTail) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomNTail upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomNTail) ! PMomNTail + END IF + Int_BufSz = Int_BufSz + 1 ! PMomX0Trb allocated yes/no + IF ( ALLOCATED(InData%PMomX0Trb) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomX0Trb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomX0Trb) ! PMomX0Trb + END IF + Re_BufSz = Re_BufSz + SIZE(InData%PMXHydro) ! PMXHydro + Db_BufSz = Db_BufSz + 1 ! TeetAng + Re_BufSz = Re_BufSz + SIZE(InData%FrcVGnRtt) ! FrcVGnRtt + Re_BufSz = Re_BufSz + SIZE(InData%FrcWTailt) ! FrcWTailt + Re_BufSz = Re_BufSz + SIZE(InData%FrcZAllt) ! FrcZAllt + Re_BufSz = Re_BufSz + SIZE(InData%MomXAllt) ! MomXAllt + Int_BufSz = Int_BufSz + 1 ! PFrcVGnRt allocated yes/no + IF ( ALLOCATED(InData%PFrcVGnRt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcVGnRt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcVGnRt) ! PFrcVGnRt + END IF + Int_BufSz = Int_BufSz + 1 ! PFrcWTail allocated yes/no + IF ( ALLOCATED(InData%PFrcWTail) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcWTail upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcWTail) ! PFrcWTail + END IF + Int_BufSz = Int_BufSz + 1 ! PFrcZAll allocated yes/no + IF ( ALLOCATED(InData%PFrcZAll) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PFrcZAll upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PFrcZAll) ! PFrcZAll + END IF + Int_BufSz = Int_BufSz + 1 ! PMomXAll allocated yes/no + IF ( ALLOCATED(InData%PMomXAll) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PMomXAll upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PMomXAll) ! PMomXAll + END IF + Re_BufSz = Re_BufSz + 1 ! TeetMom + Re_BufSz = Re_BufSz + 1 ! TFrlMom + Re_BufSz = Re_BufSz + 1 ! RFrlMom + Re_BufSz = Re_BufSz + 1 ! GBoxEffFac + Int_BufSz = Int_BufSz + 1 ! rSAerCen allocated yes/no + IF ( ALLOCATED(InData%rSAerCen) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! rSAerCen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rSAerCen) ! rSAerCen + 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%rO,1), UBOUND(InData%rO,1) + DbKiBuf(Db_Xferred) = InData%rO(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%rQS) ) 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%rQS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rQS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rQS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rQS,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rQS,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rQS,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rQS,3), UBOUND(InData%rQS,3) + DO i2 = LBOUND(InData%rQS,2), UBOUND(InData%rQS,2) + DO i1 = LBOUND(InData%rQS,1), UBOUND(InData%rQS,1) + DbKiBuf(Db_Xferred) = InData%rQS(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rS) ) 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%rS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rS,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rS,3), UBOUND(InData%rS,3) + DO i2 = LBOUND(InData%rS,2), UBOUND(InData%rS,2) + DO i1 = LBOUND(InData%rS,1), UBOUND(InData%rS,1) + DbKiBuf(Db_Xferred) = InData%rS(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rS0S) ) 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%rS0S,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS0S,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rS0S,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS0S,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rS0S,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rS0S,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rS0S,3), UBOUND(InData%rS0S,3) + DO i2 = LBOUND(InData%rS0S,2), UBOUND(InData%rS0S,2) + DO i1 = LBOUND(InData%rS0S,1), UBOUND(InData%rS0S,1) + DbKiBuf(Db_Xferred) = InData%rS0S(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rT) ) 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%rT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rT,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rT,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rT,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rT,2), UBOUND(InData%rT,2) + DO i1 = LBOUND(InData%rT,1), UBOUND(InData%rT,1) + DbKiBuf(Db_Xferred) = InData%rT(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%rT0O,1), UBOUND(InData%rT0O,1) + DbKiBuf(Db_Xferred) = InData%rT0O(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%rT0T) ) 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%rT0T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rT0T,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rT0T,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rT0T,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rT0T,2), UBOUND(InData%rT0T,2) + DO i1 = LBOUND(InData%rT0T,1), UBOUND(InData%rT0T,1) + DbKiBuf(Db_Xferred) = InData%rT0T(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%rZ,1), UBOUND(InData%rZ,1) + DbKiBuf(Db_Xferred) = InData%rZ(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rZO,1), UBOUND(InData%rZO,1) + DbKiBuf(Db_Xferred) = InData%rZO(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%rZT) ) 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%rZT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rZT,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rZT,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rZT,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rZT,2), UBOUND(InData%rZT,2) + DO i1 = LBOUND(InData%rZT,1), UBOUND(InData%rZT,1) + DbKiBuf(Db_Xferred) = InData%rZT(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%rPQ,1), UBOUND(InData%rPQ,1) + DbKiBuf(Db_Xferred) = InData%rPQ(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rP,1), UBOUND(InData%rP,1) + DbKiBuf(Db_Xferred) = InData%rP(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rV,1), UBOUND(InData%rV,1) + DbKiBuf(Db_Xferred) = InData%rV(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rZY,1), UBOUND(InData%rZY,1) + DbKiBuf(Db_Xferred) = InData%rZY(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rOU,1), UBOUND(InData%rOU,1) + DbKiBuf(Db_Xferred) = InData%rOU(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rOV,1), UBOUND(InData%rOV,1) + DbKiBuf(Db_Xferred) = InData%rOV(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rVD,1), UBOUND(InData%rVD,1) + DbKiBuf(Db_Xferred) = InData%rVD(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rOW,1), UBOUND(InData%rOW,1) + DbKiBuf(Db_Xferred) = InData%rOW(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rPC,1), UBOUND(InData%rPC,1) + DbKiBuf(Db_Xferred) = InData%rPC(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%rPS0) ) 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%rPS0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rPS0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rPS0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rPS0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rPS0,2), UBOUND(InData%rPS0,2) + DO i1 = LBOUND(InData%rPS0,1), UBOUND(InData%rPS0,1) + DbKiBuf(Db_Xferred) = InData%rPS0(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%rQ,1), UBOUND(InData%rQ,1) + DbKiBuf(Db_Xferred) = InData%rQ(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rQC,1), UBOUND(InData%rQC,1) + DbKiBuf(Db_Xferred) = InData%rQC(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rVIMU,1), UBOUND(InData%rVIMU,1) + DbKiBuf(Db_Xferred) = InData%rVIMU(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rVP,1), UBOUND(InData%rVP,1) + DbKiBuf(Db_Xferred) = InData%rVP(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rWI,1), UBOUND(InData%rWI,1) + DbKiBuf(Db_Xferred) = InData%rWI(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rWJ,1), UBOUND(InData%rWJ,1) + DbKiBuf(Db_Xferred) = InData%rWJ(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rWK,1), UBOUND(InData%rWK,1) + DbKiBuf(Db_Xferred) = InData%rWK(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rZT0,1), UBOUND(InData%rZT0,1) + DbKiBuf(Db_Xferred) = InData%rZT0(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%AngPosEF) ) 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%AngPosEF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosEF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngPosEF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosEF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AngPosEF,2), UBOUND(InData%AngPosEF,2) + DO i1 = LBOUND(InData%AngPosEF,1), UBOUND(InData%AngPosEF,1) + ReKiBuf(Re_Xferred) = InData%AngPosEF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngPosXF) ) 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%AngPosXF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosXF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngPosXF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosXF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AngPosXF,2), UBOUND(InData%AngPosXF,2) + DO i1 = LBOUND(InData%AngPosXF,1), UBOUND(InData%AngPosXF,1) + ReKiBuf(Re_Xferred) = InData%AngPosXF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngPosHM) ) 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%AngPosHM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosHM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngPosHM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosHM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngPosHM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngPosHM,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AngPosHM,3), UBOUND(InData%AngPosHM,3) + DO i2 = LBOUND(InData%AngPosHM,2), UBOUND(InData%AngPosHM,2) + DO i1 = LBOUND(InData%AngPosHM,1), UBOUND(InData%AngPosHM,1) + ReKiBuf(Re_Xferred) = InData%AngPosHM(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%AngPosXB,1), UBOUND(InData%AngPosXB,1) + ReKiBuf(Re_Xferred) = InData%AngPosXB(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngPosEX,1), UBOUND(InData%AngPosEX,1) + ReKiBuf(Re_Xferred) = InData%AngPosEX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%PAngVelEA) ) 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%PAngVelEA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEA,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEA,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEA,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEA,3), UBOUND(InData%PAngVelEA,3) + DO i2 = LBOUND(InData%PAngVelEA,2), UBOUND(InData%PAngVelEA,2) + DO i1 = LBOUND(InData%PAngVelEA,1), UBOUND(InData%PAngVelEA,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEA(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEF) ) 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%PAngVelEF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEF,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEF,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEF,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%PAngVelEF,4), UBOUND(InData%PAngVelEF,4) + DO i3 = LBOUND(InData%PAngVelEF,3), UBOUND(InData%PAngVelEF,3) + DO i2 = LBOUND(InData%PAngVelEF,2), UBOUND(InData%PAngVelEF,2) + DO i1 = LBOUND(InData%PAngVelEF,1), UBOUND(InData%PAngVelEF,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEF(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEG) ) 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%PAngVelEG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEG,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEG,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEG,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEG,3), UBOUND(InData%PAngVelEG,3) + DO i2 = LBOUND(InData%PAngVelEG,2), UBOUND(InData%PAngVelEG,2) + DO i1 = LBOUND(InData%PAngVelEG,1), UBOUND(InData%PAngVelEG,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEG(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEH) ) 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%PAngVelEH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEH,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEH,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEH,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEH,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEH,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEH,3), UBOUND(InData%PAngVelEH,3) + DO i2 = LBOUND(InData%PAngVelEH,2), UBOUND(InData%PAngVelEH,2) + DO i1 = LBOUND(InData%PAngVelEH,1), UBOUND(InData%PAngVelEH,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEH(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEL) ) 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%PAngVelEL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEL,3), UBOUND(InData%PAngVelEL,3) + DO i2 = LBOUND(InData%PAngVelEL,2), UBOUND(InData%PAngVelEL,2) + DO i1 = LBOUND(InData%PAngVelEL,1), UBOUND(InData%PAngVelEL,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEM) ) 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%PAngVelEM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEM,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEM,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEM,4) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEM,5) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEM,5) + Int_Xferred = Int_Xferred + 2 + + DO i5 = LBOUND(InData%PAngVelEM,5), UBOUND(InData%PAngVelEM,5) + DO i4 = LBOUND(InData%PAngVelEM,4), UBOUND(InData%PAngVelEM,4) + DO i3 = LBOUND(InData%PAngVelEM,3), UBOUND(InData%PAngVelEM,3) + DO i2 = LBOUND(InData%PAngVelEM,2), UBOUND(InData%PAngVelEM,2) + DO i1 = LBOUND(InData%PAngVelEM,1), UBOUND(InData%PAngVelEM,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEM(i1,i2,i3,i4,i5) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngVelEM) ) 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%AngVelEM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngVelEM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngVelEM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngVelEM,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngVelEM,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngVelEM,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AngVelEM,3), UBOUND(InData%AngVelEM,3) + DO i2 = LBOUND(InData%AngVelEM,2), UBOUND(InData%AngVelEM,2) + DO i1 = LBOUND(InData%AngVelEM,1), UBOUND(InData%AngVelEM,1) + ReKiBuf(Re_Xferred) = InData%AngVelEM(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEN) ) 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%PAngVelEN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEN,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEN,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEN,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEN,3), UBOUND(InData%PAngVelEN,3) + DO i2 = LBOUND(InData%PAngVelEN,2), UBOUND(InData%PAngVelEN,2) + DO i1 = LBOUND(InData%PAngVelEN,1), UBOUND(InData%PAngVelEN,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEN(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%AngVelEA,1), UBOUND(InData%AngVelEA,1) + ReKiBuf(Re_Xferred) = InData%AngVelEA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%PAngVelEB) ) 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%PAngVelEB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEB,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEB,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEB,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEB,3), UBOUND(InData%PAngVelEB,3) + DO i2 = LBOUND(InData%PAngVelEB,2), UBOUND(InData%PAngVelEB,2) + DO i1 = LBOUND(InData%PAngVelEB,1), UBOUND(InData%PAngVelEB,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEB(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelER) ) 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%PAngVelER,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelER,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelER,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelER,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelER,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelER,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelER,3), UBOUND(InData%PAngVelER,3) + DO i2 = LBOUND(InData%PAngVelER,2), UBOUND(InData%PAngVelER,2) + DO i1 = LBOUND(InData%PAngVelER,1), UBOUND(InData%PAngVelER,1) + ReKiBuf(Re_Xferred) = InData%PAngVelER(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PAngVelEX) ) 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%PAngVelEX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEX,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEX,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PAngVelEX,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PAngVelEX,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PAngVelEX,3), UBOUND(InData%PAngVelEX,3) + DO i2 = LBOUND(InData%PAngVelEX,2), UBOUND(InData%PAngVelEX,2) + DO i1 = LBOUND(InData%PAngVelEX,1), UBOUND(InData%PAngVelEX,1) + ReKiBuf(Re_Xferred) = InData%PAngVelEX(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%AngVelEG,1), UBOUND(InData%AngVelEG,1) + ReKiBuf(Re_Xferred) = InData%AngVelEG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelEH,1), UBOUND(InData%AngVelEH,1) + ReKiBuf(Re_Xferred) = InData%AngVelEH(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelEL,1), UBOUND(InData%AngVelEL,1) + ReKiBuf(Re_Xferred) = InData%AngVelEL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelEN,1), UBOUND(InData%AngVelEN,1) + ReKiBuf(Re_Xferred) = InData%AngVelEN(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelEB,1), UBOUND(InData%AngVelEB,1) + ReKiBuf(Re_Xferred) = InData%AngVelEB(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelER,1), UBOUND(InData%AngVelER,1) + ReKiBuf(Re_Xferred) = InData%AngVelER(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngVelEX,1), UBOUND(InData%AngVelEX,1) + ReKiBuf(Re_Xferred) = InData%AngVelEX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%TeetAngVel + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%AngAccEBt,1), UBOUND(InData%AngAccEBt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEBt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngAccERt,1), UBOUND(InData%AngAccERt,1) + ReKiBuf(Re_Xferred) = InData%AngAccERt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngAccEXt,1), UBOUND(InData%AngAccEXt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEXt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%AngAccEFt) ) 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%AngAccEFt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngAccEFt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngAccEFt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngAccEFt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AngAccEFt,2), UBOUND(InData%AngAccEFt,2) + DO i1 = LBOUND(InData%AngAccEFt,1), UBOUND(InData%AngAccEFt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEFt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngVelEF) ) 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%AngVelEF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngVelEF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngVelEF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngVelEF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AngVelEF,2), UBOUND(InData%AngVelEF,2) + DO i1 = LBOUND(InData%AngVelEF,1), UBOUND(InData%AngVelEF,1) + ReKiBuf(Re_Xferred) = InData%AngVelEF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%AngAccEAt,1), UBOUND(InData%AngAccEAt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEAt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngAccEGt,1), UBOUND(InData%AngAccEGt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEGt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngAccEHt,1), UBOUND(InData%AngAccEHt,1) + ReKiBuf(Re_Xferred) = InData%AngAccEHt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%AngAccENt,1), UBOUND(InData%AngAccENt,1) + ReKiBuf(Re_Xferred) = InData%AngAccENt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccECt,1), UBOUND(InData%LinAccECt,1) + ReKiBuf(Re_Xferred) = InData%LinAccECt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEDt,1), UBOUND(InData%LinAccEDt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEDt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEIt,1), UBOUND(InData%LinAccEIt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEIt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEJt,1), UBOUND(InData%LinAccEJt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEJt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEUt,1), UBOUND(InData%LinAccEUt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEUt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEYt,1), UBOUND(InData%LinAccEYt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEYt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%LinVelES) ) 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%LinVelES,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelES,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinVelES,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelES,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinVelES,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelES,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%LinVelES,3), UBOUND(InData%LinVelES,3) + DO i2 = LBOUND(InData%LinVelES,2), UBOUND(InData%LinVelES,2) + DO i1 = LBOUND(InData%LinVelES,1), UBOUND(InData%LinVelES,1) + ReKiBuf(Re_Xferred) = InData%LinVelES(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%LinVelEQ,1), UBOUND(InData%LinVelEQ,1) + ReKiBuf(Re_Xferred) = InData%LinVelEQ(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%LinVelET) ) 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%LinVelET,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelET,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinVelET,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelET,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LinVelET,2), UBOUND(InData%LinVelET,2) + DO i1 = LBOUND(InData%LinVelET,1), UBOUND(InData%LinVelET,1) + ReKiBuf(Re_Xferred) = InData%LinVelET(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinVelESm2) ) 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%LinVelESm2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinVelESm2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinVelESm2,1), UBOUND(InData%LinVelESm2,1) + ReKiBuf(Re_Xferred) = InData%LinVelESm2(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEIMU) ) 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%PLinVelEIMU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEIMU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEIMU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEIMU,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEIMU,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEIMU,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEIMU,3), UBOUND(InData%PLinVelEIMU,3) + DO i2 = LBOUND(InData%PLinVelEIMU,2), UBOUND(InData%PLinVelEIMU,2) + DO i1 = LBOUND(InData%PLinVelEIMU,1), UBOUND(InData%PLinVelEIMU,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEIMU(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEO) ) 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%PLinVelEO,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEO,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEO,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEO,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEO,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEO,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEO,3), UBOUND(InData%PLinVelEO,3) + DO i2 = LBOUND(InData%PLinVelEO,2), UBOUND(InData%PLinVelEO,2) + DO i1 = LBOUND(InData%PLinVelEO,1), UBOUND(InData%PLinVelEO,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEO(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelES) ) 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%PLinVelES,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelES,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelES,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelES,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelES,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelES,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelES,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelES,4) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelES,5) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelES,5) + Int_Xferred = Int_Xferred + 2 + + DO i5 = LBOUND(InData%PLinVelES,5), UBOUND(InData%PLinVelES,5) + DO i4 = LBOUND(InData%PLinVelES,4), UBOUND(InData%PLinVelES,4) + DO i3 = LBOUND(InData%PLinVelES,3), UBOUND(InData%PLinVelES,3) + DO i2 = LBOUND(InData%PLinVelES,2), UBOUND(InData%PLinVelES,2) + DO i1 = LBOUND(InData%PLinVelES,1), UBOUND(InData%PLinVelES,1) + ReKiBuf(Re_Xferred) = InData%PLinVelES(i1,i2,i3,i4,i5) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelET) ) 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%PLinVelET,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelET,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelET,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelET,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelET,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelET,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelET,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelET,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%PLinVelET,4), UBOUND(InData%PLinVelET,4) + DO i3 = LBOUND(InData%PLinVelET,3), UBOUND(InData%PLinVelET,3) + DO i2 = LBOUND(InData%PLinVelET,2), UBOUND(InData%PLinVelET,2) + DO i1 = LBOUND(InData%PLinVelET,1), UBOUND(InData%PLinVelET,1) + ReKiBuf(Re_Xferred) = InData%PLinVelET(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEZ) ) 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%PLinVelEZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEZ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEZ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEZ,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEZ,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEZ,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEZ,3), UBOUND(InData%PLinVelEZ,3) + DO i2 = LBOUND(InData%PLinVelEZ,2), UBOUND(InData%PLinVelEZ,2) + DO i1 = LBOUND(InData%PLinVelEZ,1), UBOUND(InData%PLinVelEZ,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEZ(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEC) ) 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%PLinVelEC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEC,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEC,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEC,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEC,3), UBOUND(InData%PLinVelEC,3) + DO i2 = LBOUND(InData%PLinVelEC,2), UBOUND(InData%PLinVelEC,2) + DO i1 = LBOUND(InData%PLinVelEC,1), UBOUND(InData%PLinVelEC,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEC(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelED) ) 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%PLinVelED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelED,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelED,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelED,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelED,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelED,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelED,3), UBOUND(InData%PLinVelED,3) + DO i2 = LBOUND(InData%PLinVelED,2), UBOUND(InData%PLinVelED,2) + DO i1 = LBOUND(InData%PLinVelED,1), UBOUND(InData%PLinVelED,1) + ReKiBuf(Re_Xferred) = InData%PLinVelED(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEI) ) 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%PLinVelEI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEI,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEI,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEI,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEI,3), UBOUND(InData%PLinVelEI,3) + DO i2 = LBOUND(InData%PLinVelEI,2), UBOUND(InData%PLinVelEI,2) + DO i1 = LBOUND(InData%PLinVelEI,1), UBOUND(InData%PLinVelEI,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEI(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEJ) ) 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%PLinVelEJ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEJ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEJ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEJ,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEJ,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEJ,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEJ,3), UBOUND(InData%PLinVelEJ,3) + DO i2 = LBOUND(InData%PLinVelEJ,2), UBOUND(InData%PLinVelEJ,2) + DO i1 = LBOUND(InData%PLinVelEJ,1), UBOUND(InData%PLinVelEJ,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEJ(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEK) ) 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%PLinVelEK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEK,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEK,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEK,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEK,3), UBOUND(InData%PLinVelEK,3) + DO i2 = LBOUND(InData%PLinVelEK,2), UBOUND(InData%PLinVelEK,2) + DO i1 = LBOUND(InData%PLinVelEK,1), UBOUND(InData%PLinVelEK,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEK(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEP) ) 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%PLinVelEP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEP,3), UBOUND(InData%PLinVelEP,3) + DO i2 = LBOUND(InData%PLinVelEP,2), UBOUND(InData%PLinVelEP,2) + DO i1 = LBOUND(InData%PLinVelEP,1), UBOUND(InData%PLinVelEP,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEP(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEQ) ) 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%PLinVelEQ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEQ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEQ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEQ,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEQ,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEQ,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEQ,3), UBOUND(InData%PLinVelEQ,3) + DO i2 = LBOUND(InData%PLinVelEQ,2), UBOUND(InData%PLinVelEQ,2) + DO i1 = LBOUND(InData%PLinVelEQ,1), UBOUND(InData%PLinVelEQ,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEQ(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEU) ) 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%PLinVelEU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEU,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEU,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEU,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEU,3), UBOUND(InData%PLinVelEU,3) + DO i2 = LBOUND(InData%PLinVelEU,2), UBOUND(InData%PLinVelEU,2) + DO i1 = LBOUND(InData%PLinVelEU,1), UBOUND(InData%PLinVelEU,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEU(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEV) ) 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%PLinVelEV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEV,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEV,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEV,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEV,3), UBOUND(InData%PLinVelEV,3) + DO i2 = LBOUND(InData%PLinVelEV,2), UBOUND(InData%PLinVelEV,2) + DO i1 = LBOUND(InData%PLinVelEV,1), UBOUND(InData%PLinVelEV,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEV(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEW) ) 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%PLinVelEW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEW,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEW,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEW,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEW,3), UBOUND(InData%PLinVelEW,3) + DO i2 = LBOUND(InData%PLinVelEW,2), UBOUND(InData%PLinVelEW,2) + DO i1 = LBOUND(InData%PLinVelEW,1), UBOUND(InData%PLinVelEW,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEW(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PLinVelEY) ) 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%PLinVelEY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEY,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PLinVelEY,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PLinVelEY,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PLinVelEY,3), UBOUND(InData%PLinVelEY,3) + DO i2 = LBOUND(InData%PLinVelEY,2), UBOUND(InData%PLinVelEY,2) + DO i1 = LBOUND(InData%PLinVelEY,1), UBOUND(InData%PLinVelEY,1) + ReKiBuf(Re_Xferred) = InData%PLinVelEY(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%LinAccEIMUt,1), UBOUND(InData%LinAccEIMUt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEIMUt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinAccEOt,1), UBOUND(InData%LinAccEOt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEOt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%LinAccESt) ) 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%LinAccESt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinAccESt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinAccESt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinAccESt,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinAccESt,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinAccESt,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%LinAccESt,3), UBOUND(InData%LinAccESt,3) + DO i2 = LBOUND(InData%LinAccESt,2), UBOUND(InData%LinAccESt,2) + DO i1 = LBOUND(InData%LinAccESt,1), UBOUND(InData%LinAccESt,1) + ReKiBuf(Re_Xferred) = InData%LinAccESt(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinAccETt) ) 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%LinAccETt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinAccETt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinAccETt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinAccETt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LinAccETt,2), UBOUND(InData%LinAccETt,2) + DO i1 = LBOUND(InData%LinAccETt,1), UBOUND(InData%LinAccETt,1) + ReKiBuf(Re_Xferred) = InData%LinAccETt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%LinAccEZt,1), UBOUND(InData%LinAccEZt,1) + ReKiBuf(Re_Xferred) = InData%LinAccEZt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinVelEIMU,1), UBOUND(InData%LinVelEIMU,1) + ReKiBuf(Re_Xferred) = InData%LinVelEIMU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinVelEZ,1), UBOUND(InData%LinVelEZ,1) + ReKiBuf(Re_Xferred) = InData%LinVelEZ(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinVelEO,1), UBOUND(InData%LinVelEO,1) + ReKiBuf(Re_Xferred) = InData%LinVelEO(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FrcONcRtt,1), UBOUND(InData%FrcONcRtt,1) + ReKiBuf(Re_Xferred) = InData%FrcONcRtt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FrcPRott,1), UBOUND(InData%FrcPRott,1) + ReKiBuf(Re_Xferred) = InData%FrcPRott(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%FrcS0Bt) ) 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%FrcS0Bt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FrcS0Bt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FrcS0Bt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FrcS0Bt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FrcS0Bt,2), UBOUND(InData%FrcS0Bt,2) + DO i1 = LBOUND(InData%FrcS0Bt,1), UBOUND(InData%FrcS0Bt,1) + ReKiBuf(Re_Xferred) = InData%FrcS0Bt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%FrcT0Trbt,1), UBOUND(InData%FrcT0Trbt,1) + ReKiBuf(Re_Xferred) = InData%FrcT0Trbt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%FSAero) ) 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%FSAero,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSAero,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSAero,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSAero,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSAero,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSAero,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FSAero,3), UBOUND(InData%FSAero,3) + DO i2 = LBOUND(InData%FSAero,2), UBOUND(InData%FSAero,2) + DO i1 = LBOUND(InData%FSAero,1), UBOUND(InData%FSAero,1) + ReKiBuf(Re_Xferred) = InData%FSAero(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FSTipDrag) ) 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%FSTipDrag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSTipDrag,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FSTipDrag,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FSTipDrag,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FSTipDrag,2), UBOUND(InData%FSTipDrag,2) + DO i1 = LBOUND(InData%FSTipDrag,1), UBOUND(InData%FSTipDrag,1) + ReKiBuf(Re_Xferred) = InData%FSTipDrag(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FTHydrot) ) 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%FTHydrot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTHydrot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FTHydrot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FTHydrot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FTHydrot,2), UBOUND(InData%FTHydrot,2) + DO i1 = LBOUND(InData%FTHydrot,1), UBOUND(InData%FTHydrot,1) + ReKiBuf(Re_Xferred) = InData%FTHydrot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%FZHydrot,1), UBOUND(InData%FZHydrot,1) + ReKiBuf(Re_Xferred) = InData%FZHydrot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%MFHydrot) ) 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%MFHydrot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MFHydrot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MFHydrot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MFHydrot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MFHydrot,2), UBOUND(InData%MFHydrot,2) + DO i1 = LBOUND(InData%MFHydrot,1), UBOUND(InData%MFHydrot,1) + ReKiBuf(Re_Xferred) = InData%MFHydrot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%MomBNcRtt,1), UBOUND(InData%MomBNcRtt,1) + ReKiBuf(Re_Xferred) = InData%MomBNcRtt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%MomH0Bt) ) 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%MomH0Bt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MomH0Bt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MomH0Bt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MomH0Bt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MomH0Bt,2), UBOUND(InData%MomH0Bt,2) + DO i1 = LBOUND(InData%MomH0Bt,1), UBOUND(InData%MomH0Bt,1) + ReKiBuf(Re_Xferred) = InData%MomH0Bt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%MomLPRott,1), UBOUND(InData%MomLPRott,1) + ReKiBuf(Re_Xferred) = InData%MomLPRott(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%MomNGnRtt,1), UBOUND(InData%MomNGnRtt,1) + ReKiBuf(Re_Xferred) = InData%MomNGnRtt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%MomNTailt,1), UBOUND(InData%MomNTailt,1) + ReKiBuf(Re_Xferred) = InData%MomNTailt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%MomX0Trbt,1), UBOUND(InData%MomX0Trbt,1) + ReKiBuf(Re_Xferred) = InData%MomX0Trbt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%MMAero) ) 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%MMAero,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMAero,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MMAero,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMAero,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MMAero,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMAero,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%MMAero,3), UBOUND(InData%MMAero,3) + DO i2 = LBOUND(InData%MMAero,2), UBOUND(InData%MMAero,2) + DO i1 = LBOUND(InData%MMAero,1), UBOUND(InData%MMAero,1) + ReKiBuf(Re_Xferred) = InData%MMAero(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i1 = LBOUND(InData%MXHydrot,1), UBOUND(InData%MXHydrot,1) + ReKiBuf(Re_Xferred) = InData%MXHydrot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%PFrcONcRt) ) 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%PFrcONcRt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcONcRt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcONcRt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcONcRt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcONcRt,2), UBOUND(InData%PFrcONcRt,2) + DO i1 = LBOUND(InData%PFrcONcRt,1), UBOUND(InData%PFrcONcRt,1) + ReKiBuf(Re_Xferred) = InData%PFrcONcRt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFrcPRot) ) 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%PFrcPRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcPRot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcPRot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcPRot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcPRot,2), UBOUND(InData%PFrcPRot,2) + DO i1 = LBOUND(InData%PFrcPRot,1), UBOUND(InData%PFrcPRot,1) + ReKiBuf(Re_Xferred) = InData%PFrcPRot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFrcS0B) ) 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%PFrcS0B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcS0B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcS0B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcS0B,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcS0B,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcS0B,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PFrcS0B,3), UBOUND(InData%PFrcS0B,3) + DO i2 = LBOUND(InData%PFrcS0B,2), UBOUND(InData%PFrcS0B,2) + DO i1 = LBOUND(InData%PFrcS0B,1), UBOUND(InData%PFrcS0B,1) + ReKiBuf(Re_Xferred) = InData%PFrcS0B(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFrcT0Trb) ) 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%PFrcT0Trb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcT0Trb,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcT0Trb,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcT0Trb,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcT0Trb,2), UBOUND(InData%PFrcT0Trb,2) + DO i1 = LBOUND(InData%PFrcT0Trb,1), UBOUND(InData%PFrcT0Trb,1) + ReKiBuf(Re_Xferred) = InData%PFrcT0Trb(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFTHydro) ) 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%PFTHydro,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFTHydro,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFTHydro,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFTHydro,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFTHydro,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFTHydro,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PFTHydro,3), UBOUND(InData%PFTHydro,3) + DO i2 = LBOUND(InData%PFTHydro,2), UBOUND(InData%PFTHydro,2) + DO i1 = LBOUND(InData%PFTHydro,1), UBOUND(InData%PFTHydro,1) + ReKiBuf(Re_Xferred) = InData%PFTHydro(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i2 = LBOUND(InData%PFZHydro,2), UBOUND(InData%PFZHydro,2) + DO i1 = LBOUND(InData%PFZHydro,1), UBOUND(InData%PFZHydro,1) + ReKiBuf(Re_Xferred) = InData%PFZHydro(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%PMFHydro) ) 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%PMFHydro,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMFHydro,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMFHydro,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMFHydro,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMFHydro,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMFHydro,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PMFHydro,3), UBOUND(InData%PMFHydro,3) + DO i2 = LBOUND(InData%PMFHydro,2), UBOUND(InData%PMFHydro,2) + DO i1 = LBOUND(InData%PMFHydro,1), UBOUND(InData%PMFHydro,1) + ReKiBuf(Re_Xferred) = InData%PMFHydro(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomBNcRt) ) 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%PMomBNcRt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomBNcRt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomBNcRt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomBNcRt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomBNcRt,2), UBOUND(InData%PMomBNcRt,2) + DO i1 = LBOUND(InData%PMomBNcRt,1), UBOUND(InData%PMomBNcRt,1) + ReKiBuf(Re_Xferred) = InData%PMomBNcRt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomH0B) ) 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%PMomH0B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomH0B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomH0B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomH0B,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomH0B,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomH0B,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PMomH0B,3), UBOUND(InData%PMomH0B,3) + DO i2 = LBOUND(InData%PMomH0B,2), UBOUND(InData%PMomH0B,2) + DO i1 = LBOUND(InData%PMomH0B,1), UBOUND(InData%PMomH0B,1) + ReKiBuf(Re_Xferred) = InData%PMomH0B(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomLPRot) ) 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%PMomLPRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomLPRot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomLPRot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomLPRot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomLPRot,2), UBOUND(InData%PMomLPRot,2) + DO i1 = LBOUND(InData%PMomLPRot,1), UBOUND(InData%PMomLPRot,1) + ReKiBuf(Re_Xferred) = InData%PMomLPRot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomNGnRt) ) 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%PMomNGnRt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomNGnRt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomNGnRt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomNGnRt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomNGnRt,2), UBOUND(InData%PMomNGnRt,2) + DO i1 = LBOUND(InData%PMomNGnRt,1), UBOUND(InData%PMomNGnRt,1) + ReKiBuf(Re_Xferred) = InData%PMomNGnRt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomNTail) ) 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%PMomNTail,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomNTail,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomNTail,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomNTail,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomNTail,2), UBOUND(InData%PMomNTail,2) + DO i1 = LBOUND(InData%PMomNTail,1), UBOUND(InData%PMomNTail,1) + ReKiBuf(Re_Xferred) = InData%PMomNTail(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomX0Trb) ) 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%PMomX0Trb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomX0Trb,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomX0Trb,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomX0Trb,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomX0Trb,2), UBOUND(InData%PMomX0Trb,2) + DO i1 = LBOUND(InData%PMomX0Trb,1), UBOUND(InData%PMomX0Trb,1) + ReKiBuf(Re_Xferred) = InData%PMomX0Trb(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i2 = LBOUND(InData%PMXHydro,2), UBOUND(InData%PMXHydro,2) + DO i1 = LBOUND(InData%PMXHydro,1), UBOUND(InData%PMXHydro,1) + ReKiBuf(Re_Xferred) = InData%PMXHydro(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DbKiBuf(Db_Xferred) = InData%TeetAng + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%FrcVGnRtt,1), UBOUND(InData%FrcVGnRtt,1) + ReKiBuf(Re_Xferred) = InData%FrcVGnRtt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FrcWTailt,1), UBOUND(InData%FrcWTailt,1) + ReKiBuf(Re_Xferred) = InData%FrcWTailt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FrcZAllt,1), UBOUND(InData%FrcZAllt,1) + ReKiBuf(Re_Xferred) = InData%FrcZAllt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%MomXAllt,1), UBOUND(InData%MomXAllt,1) + ReKiBuf(Re_Xferred) = InData%MomXAllt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%PFrcVGnRt) ) 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%PFrcVGnRt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcVGnRt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcVGnRt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcVGnRt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcVGnRt,2), UBOUND(InData%PFrcVGnRt,2) + DO i1 = LBOUND(InData%PFrcVGnRt,1), UBOUND(InData%PFrcVGnRt,1) + ReKiBuf(Re_Xferred) = InData%PFrcVGnRt(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFrcWTail) ) 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%PFrcWTail,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcWTail,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcWTail,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcWTail,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcWTail,2), UBOUND(InData%PFrcWTail,2) + DO i1 = LBOUND(InData%PFrcWTail,1), UBOUND(InData%PFrcWTail,1) + ReKiBuf(Re_Xferred) = InData%PFrcWTail(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PFrcZAll) ) 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%PFrcZAll,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcZAll,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PFrcZAll,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PFrcZAll,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PFrcZAll,2), UBOUND(InData%PFrcZAll,2) + DO i1 = LBOUND(InData%PFrcZAll,1), UBOUND(InData%PFrcZAll,1) + ReKiBuf(Re_Xferred) = InData%PFrcZAll(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PMomXAll) ) 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%PMomXAll,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomXAll,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PMomXAll,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PMomXAll,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PMomXAll,2), UBOUND(InData%PMomXAll,2) + DO i1 = LBOUND(InData%PMomXAll,1), UBOUND(InData%PMomXAll,1) + ReKiBuf(Re_Xferred) = InData%PMomXAll(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TeetMom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlMom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlMom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GBoxEffFac + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%rSAerCen) ) 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%rSAerCen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCen,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rSAerCen,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCen,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rSAerCen,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCen,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%rSAerCen,3), UBOUND(InData%rSAerCen,3) + DO i2 = LBOUND(InData%rSAerCen,2), UBOUND(InData%rSAerCen,2) + DO i1 = LBOUND(InData%rSAerCen,1), UBOUND(InData%rSAerCen,1) + ReKiBuf(Re_Xferred) = InData%rSAerCen(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE ED_PackRtHndSide + + SUBROUTINE ED_UnPackRtHndSide( 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(ED_RtHndSide), 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 = 'ED_UnPackRtHndSide' + ! 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%rO,1) + i1_u = UBOUND(OutData%rO,1) + DO i1 = LBOUND(OutData%rO,1), UBOUND(OutData%rO,1) + OutData%rO(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rQS 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%rQS)) DEALLOCATE(OutData%rQS) + ALLOCATE(OutData%rQS(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%rQS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rQS,3), UBOUND(OutData%rQS,3) + DO i2 = LBOUND(OutData%rQS,2), UBOUND(OutData%rQS,2) + DO i1 = LBOUND(OutData%rQS,1), UBOUND(OutData%rQS,1) + OutData%rQS(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rS 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%rS)) DEALLOCATE(OutData%rS) + ALLOCATE(OutData%rS(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%rS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rS,3), UBOUND(OutData%rS,3) + DO i2 = LBOUND(OutData%rS,2), UBOUND(OutData%rS,2) + DO i1 = LBOUND(OutData%rS,1), UBOUND(OutData%rS,1) + OutData%rS(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rS0S 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%rS0S)) DEALLOCATE(OutData%rS0S) + ALLOCATE(OutData%rS0S(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%rS0S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rS0S,3), UBOUND(OutData%rS0S,3) + DO i2 = LBOUND(OutData%rS0S,2), UBOUND(OutData%rS0S,2) + DO i1 = LBOUND(OutData%rS0S,1), UBOUND(OutData%rS0S,1) + OutData%rS0S(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rT 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%rT)) DEALLOCATE(OutData%rT) + ALLOCATE(OutData%rT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rT,2), UBOUND(OutData%rT,2) + DO i1 = LBOUND(OutData%rT,1), UBOUND(OutData%rT,1) + OutData%rT(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%rT0O,1) + i1_u = UBOUND(OutData%rT0O,1) + DO i1 = LBOUND(OutData%rT0O,1), UBOUND(OutData%rT0O,1) + OutData%rT0O(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rT0T 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%rT0T)) DEALLOCATE(OutData%rT0T) + ALLOCATE(OutData%rT0T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rT0T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rT0T,2), UBOUND(OutData%rT0T,2) + DO i1 = LBOUND(OutData%rT0T,1), UBOUND(OutData%rT0T,1) + OutData%rT0T(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%rZ,1) + i1_u = UBOUND(OutData%rZ,1) + DO i1 = LBOUND(OutData%rZ,1), UBOUND(OutData%rZ,1) + OutData%rZ(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rZO,1) + i1_u = UBOUND(OutData%rZO,1) + DO i1 = LBOUND(OutData%rZO,1), UBOUND(OutData%rZO,1) + OutData%rZO(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rZT 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%rZT)) DEALLOCATE(OutData%rZT) + ALLOCATE(OutData%rZT(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rZT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rZT,2), UBOUND(OutData%rZT,2) + DO i1 = LBOUND(OutData%rZT,1), UBOUND(OutData%rZT,1) + OutData%rZT(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%rPQ,1) + i1_u = UBOUND(OutData%rPQ,1) + DO i1 = LBOUND(OutData%rPQ,1), UBOUND(OutData%rPQ,1) + OutData%rPQ(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rP,1) + i1_u = UBOUND(OutData%rP,1) + DO i1 = LBOUND(OutData%rP,1), UBOUND(OutData%rP,1) + OutData%rP(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rV,1) + i1_u = UBOUND(OutData%rV,1) + DO i1 = LBOUND(OutData%rV,1), UBOUND(OutData%rV,1) + OutData%rV(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rZY,1) + i1_u = UBOUND(OutData%rZY,1) + DO i1 = LBOUND(OutData%rZY,1), UBOUND(OutData%rZY,1) + OutData%rZY(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rOU,1) + i1_u = UBOUND(OutData%rOU,1) + DO i1 = LBOUND(OutData%rOU,1), UBOUND(OutData%rOU,1) + OutData%rOU(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rOV,1) + i1_u = UBOUND(OutData%rOV,1) + DO i1 = LBOUND(OutData%rOV,1), UBOUND(OutData%rOV,1) + OutData%rOV(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rVD,1) + i1_u = UBOUND(OutData%rVD,1) + DO i1 = LBOUND(OutData%rVD,1), UBOUND(OutData%rVD,1) + OutData%rVD(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rOW,1) + i1_u = UBOUND(OutData%rOW,1) + DO i1 = LBOUND(OutData%rOW,1), UBOUND(OutData%rOW,1) + OutData%rOW(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rPC,1) + i1_u = UBOUND(OutData%rPC,1) + DO i1 = LBOUND(OutData%rPC,1), UBOUND(OutData%rPC,1) + OutData%rPC(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rPS0 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%rPS0)) DEALLOCATE(OutData%rPS0) + ALLOCATE(OutData%rPS0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rPS0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rPS0,2), UBOUND(OutData%rPS0,2) + DO i1 = LBOUND(OutData%rPS0,1), UBOUND(OutData%rPS0,1) + OutData%rPS0(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%rQ,1) + i1_u = UBOUND(OutData%rQ,1) + DO i1 = LBOUND(OutData%rQ,1), UBOUND(OutData%rQ,1) + OutData%rQ(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rQC,1) + i1_u = UBOUND(OutData%rQC,1) + DO i1 = LBOUND(OutData%rQC,1), UBOUND(OutData%rQC,1) + OutData%rQC(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rVIMU,1) + i1_u = UBOUND(OutData%rVIMU,1) + DO i1 = LBOUND(OutData%rVIMU,1), UBOUND(OutData%rVIMU,1) + OutData%rVIMU(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rVP,1) + i1_u = UBOUND(OutData%rVP,1) + DO i1 = LBOUND(OutData%rVP,1), UBOUND(OutData%rVP,1) + OutData%rVP(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rWI,1) + i1_u = UBOUND(OutData%rWI,1) + DO i1 = LBOUND(OutData%rWI,1), UBOUND(OutData%rWI,1) + OutData%rWI(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rWJ,1) + i1_u = UBOUND(OutData%rWJ,1) + DO i1 = LBOUND(OutData%rWJ,1), UBOUND(OutData%rWJ,1) + OutData%rWJ(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rWK,1) + i1_u = UBOUND(OutData%rWK,1) + DO i1 = LBOUND(OutData%rWK,1), UBOUND(OutData%rWK,1) + OutData%rWK(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rZT0,1) + i1_u = UBOUND(OutData%rZT0,1) + DO i1 = LBOUND(OutData%rZT0,1), UBOUND(OutData%rZT0,1) + OutData%rZT0(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngPosEF 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%AngPosEF)) DEALLOCATE(OutData%AngPosEF) + ALLOCATE(OutData%AngPosEF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngPosEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AngPosEF,2), UBOUND(OutData%AngPosEF,2) + DO i1 = LBOUND(OutData%AngPosEF,1), UBOUND(OutData%AngPosEF,1) + OutData%AngPosEF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngPosXF 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%AngPosXF)) DEALLOCATE(OutData%AngPosXF) + ALLOCATE(OutData%AngPosXF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngPosXF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AngPosXF,2), UBOUND(OutData%AngPosXF,2) + DO i1 = LBOUND(OutData%AngPosXF,1), UBOUND(OutData%AngPosXF,1) + OutData%AngPosXF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngPosHM 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%AngPosHM)) DEALLOCATE(OutData%AngPosHM) + ALLOCATE(OutData%AngPosHM(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%AngPosHM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AngPosHM,3), UBOUND(OutData%AngPosHM,3) + DO i2 = LBOUND(OutData%AngPosHM,2), UBOUND(OutData%AngPosHM,2) + DO i1 = LBOUND(OutData%AngPosHM,1), UBOUND(OutData%AngPosHM,1) + OutData%AngPosHM(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%AngPosXB,1) + i1_u = UBOUND(OutData%AngPosXB,1) + DO i1 = LBOUND(OutData%AngPosXB,1), UBOUND(OutData%AngPosXB,1) + OutData%AngPosXB(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngPosEX,1) + i1_u = UBOUND(OutData%AngPosEX,1) + DO i1 = LBOUND(OutData%AngPosEX,1), UBOUND(OutData%AngPosEX,1) + OutData%AngPosEX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEA 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%PAngVelEA)) DEALLOCATE(OutData%PAngVelEA) + ALLOCATE(OutData%PAngVelEA(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%PAngVelEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEA,3), UBOUND(OutData%PAngVelEA,3) + DO i2 = LBOUND(OutData%PAngVelEA,2), UBOUND(OutData%PAngVelEA,2) + DO i1 = LBOUND(OutData%PAngVelEA,1), UBOUND(OutData%PAngVelEA,1) + OutData%PAngVelEA(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEF 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%PAngVelEF)) DEALLOCATE(OutData%PAngVelEF) + ALLOCATE(OutData%PAngVelEF(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%PAngVelEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%PAngVelEF,4), UBOUND(OutData%PAngVelEF,4) + DO i3 = LBOUND(OutData%PAngVelEF,3), UBOUND(OutData%PAngVelEF,3) + DO i2 = LBOUND(OutData%PAngVelEF,2), UBOUND(OutData%PAngVelEF,2) + DO i1 = LBOUND(OutData%PAngVelEF,1), UBOUND(OutData%PAngVelEF,1) + OutData%PAngVelEF(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEG 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%PAngVelEG)) DEALLOCATE(OutData%PAngVelEG) + ALLOCATE(OutData%PAngVelEG(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%PAngVelEG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEG,3), UBOUND(OutData%PAngVelEG,3) + DO i2 = LBOUND(OutData%PAngVelEG,2), UBOUND(OutData%PAngVelEG,2) + DO i1 = LBOUND(OutData%PAngVelEG,1), UBOUND(OutData%PAngVelEG,1) + OutData%PAngVelEG(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEH 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%PAngVelEH)) DEALLOCATE(OutData%PAngVelEH) + ALLOCATE(OutData%PAngVelEH(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%PAngVelEH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEH,3), UBOUND(OutData%PAngVelEH,3) + DO i2 = LBOUND(OutData%PAngVelEH,2), UBOUND(OutData%PAngVelEH,2) + DO i1 = LBOUND(OutData%PAngVelEH,1), UBOUND(OutData%PAngVelEH,1) + OutData%PAngVelEH(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEL 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%PAngVelEL)) DEALLOCATE(OutData%PAngVelEL) + ALLOCATE(OutData%PAngVelEL(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%PAngVelEL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEL,3), UBOUND(OutData%PAngVelEL,3) + DO i2 = LBOUND(OutData%PAngVelEL,2), UBOUND(OutData%PAngVelEL,2) + DO i1 = LBOUND(OutData%PAngVelEL,1), UBOUND(OutData%PAngVelEL,1) + OutData%PAngVelEL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEM 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%PAngVelEM)) DEALLOCATE(OutData%PAngVelEM) + ALLOCATE(OutData%PAngVelEM(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%PAngVelEM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i5 = LBOUND(OutData%PAngVelEM,5), UBOUND(OutData%PAngVelEM,5) + DO i4 = LBOUND(OutData%PAngVelEM,4), UBOUND(OutData%PAngVelEM,4) + DO i3 = LBOUND(OutData%PAngVelEM,3), UBOUND(OutData%PAngVelEM,3) + DO i2 = LBOUND(OutData%PAngVelEM,2), UBOUND(OutData%PAngVelEM,2) + DO i1 = LBOUND(OutData%PAngVelEM,1), UBOUND(OutData%PAngVelEM,1) + OutData%PAngVelEM(i1,i2,i3,i4,i5) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngVelEM 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%AngVelEM)) DEALLOCATE(OutData%AngVelEM) + ALLOCATE(OutData%AngVelEM(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%AngVelEM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AngVelEM,3), UBOUND(OutData%AngVelEM,3) + DO i2 = LBOUND(OutData%AngVelEM,2), UBOUND(OutData%AngVelEM,2) + DO i1 = LBOUND(OutData%AngVelEM,1), UBOUND(OutData%AngVelEM,1) + OutData%AngVelEM(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEN 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%PAngVelEN)) DEALLOCATE(OutData%PAngVelEN) + ALLOCATE(OutData%PAngVelEN(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%PAngVelEN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEN,3), UBOUND(OutData%PAngVelEN,3) + DO i2 = LBOUND(OutData%PAngVelEN,2), UBOUND(OutData%PAngVelEN,2) + DO i1 = LBOUND(OutData%PAngVelEN,1), UBOUND(OutData%PAngVelEN,1) + OutData%PAngVelEN(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%AngVelEA,1) + i1_u = UBOUND(OutData%AngVelEA,1) + DO i1 = LBOUND(OutData%AngVelEA,1), UBOUND(OutData%AngVelEA,1) + OutData%AngVelEA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEB 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%PAngVelEB)) DEALLOCATE(OutData%PAngVelEB) + ALLOCATE(OutData%PAngVelEB(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%PAngVelEB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEB,3), UBOUND(OutData%PAngVelEB,3) + DO i2 = LBOUND(OutData%PAngVelEB,2), UBOUND(OutData%PAngVelEB,2) + DO i1 = LBOUND(OutData%PAngVelEB,1), UBOUND(OutData%PAngVelEB,1) + OutData%PAngVelEB(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelER 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%PAngVelER)) DEALLOCATE(OutData%PAngVelER) + ALLOCATE(OutData%PAngVelER(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%PAngVelER.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelER,3), UBOUND(OutData%PAngVelER,3) + DO i2 = LBOUND(OutData%PAngVelER,2), UBOUND(OutData%PAngVelER,2) + DO i1 = LBOUND(OutData%PAngVelER,1), UBOUND(OutData%PAngVelER,1) + OutData%PAngVelER(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PAngVelEX 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%PAngVelEX)) DEALLOCATE(OutData%PAngVelEX) + ALLOCATE(OutData%PAngVelEX(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%PAngVelEX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PAngVelEX,3), UBOUND(OutData%PAngVelEX,3) + DO i2 = LBOUND(OutData%PAngVelEX,2), UBOUND(OutData%PAngVelEX,2) + DO i1 = LBOUND(OutData%PAngVelEX,1), UBOUND(OutData%PAngVelEX,1) + OutData%PAngVelEX(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%AngVelEG,1) + i1_u = UBOUND(OutData%AngVelEG,1) + DO i1 = LBOUND(OutData%AngVelEG,1), UBOUND(OutData%AngVelEG,1) + OutData%AngVelEG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelEH,1) + i1_u = UBOUND(OutData%AngVelEH,1) + DO i1 = LBOUND(OutData%AngVelEH,1), UBOUND(OutData%AngVelEH,1) + OutData%AngVelEH(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelEL,1) + i1_u = UBOUND(OutData%AngVelEL,1) + DO i1 = LBOUND(OutData%AngVelEL,1), UBOUND(OutData%AngVelEL,1) + OutData%AngVelEL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelEN,1) + i1_u = UBOUND(OutData%AngVelEN,1) + DO i1 = LBOUND(OutData%AngVelEN,1), UBOUND(OutData%AngVelEN,1) + OutData%AngVelEN(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelEB,1) + i1_u = UBOUND(OutData%AngVelEB,1) + DO i1 = LBOUND(OutData%AngVelEB,1), UBOUND(OutData%AngVelEB,1) + OutData%AngVelEB(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelER,1) + i1_u = UBOUND(OutData%AngVelER,1) + DO i1 = LBOUND(OutData%AngVelER,1), UBOUND(OutData%AngVelER,1) + OutData%AngVelER(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngVelEX,1) + i1_u = UBOUND(OutData%AngVelEX,1) + DO i1 = LBOUND(OutData%AngVelEX,1), UBOUND(OutData%AngVelEX,1) + OutData%AngVelEX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%TeetAngVel = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%AngAccEBt,1) + i1_u = UBOUND(OutData%AngAccEBt,1) + DO i1 = LBOUND(OutData%AngAccEBt,1), UBOUND(OutData%AngAccEBt,1) + OutData%AngAccEBt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngAccERt,1) + i1_u = UBOUND(OutData%AngAccERt,1) + DO i1 = LBOUND(OutData%AngAccERt,1), UBOUND(OutData%AngAccERt,1) + OutData%AngAccERt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngAccEXt,1) + i1_u = UBOUND(OutData%AngAccEXt,1) + DO i1 = LBOUND(OutData%AngAccEXt,1), UBOUND(OutData%AngAccEXt,1) + OutData%AngAccEXt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngAccEFt 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%AngAccEFt)) DEALLOCATE(OutData%AngAccEFt) + ALLOCATE(OutData%AngAccEFt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngAccEFt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AngAccEFt,2), UBOUND(OutData%AngAccEFt,2) + DO i1 = LBOUND(OutData%AngAccEFt,1), UBOUND(OutData%AngAccEFt,1) + OutData%AngAccEFt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngVelEF 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%AngVelEF)) DEALLOCATE(OutData%AngVelEF) + ALLOCATE(OutData%AngVelEF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngVelEF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AngVelEF,2), UBOUND(OutData%AngVelEF,2) + DO i1 = LBOUND(OutData%AngVelEF,1), UBOUND(OutData%AngVelEF,1) + OutData%AngVelEF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%AngAccEAt,1) + i1_u = UBOUND(OutData%AngAccEAt,1) + DO i1 = LBOUND(OutData%AngAccEAt,1), UBOUND(OutData%AngAccEAt,1) + OutData%AngAccEAt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngAccEGt,1) + i1_u = UBOUND(OutData%AngAccEGt,1) + DO i1 = LBOUND(OutData%AngAccEGt,1), UBOUND(OutData%AngAccEGt,1) + OutData%AngAccEGt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngAccEHt,1) + i1_u = UBOUND(OutData%AngAccEHt,1) + DO i1 = LBOUND(OutData%AngAccEHt,1), UBOUND(OutData%AngAccEHt,1) + OutData%AngAccEHt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AngAccENt,1) + i1_u = UBOUND(OutData%AngAccENt,1) + DO i1 = LBOUND(OutData%AngAccENt,1), UBOUND(OutData%AngAccENt,1) + OutData%AngAccENt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccECt,1) + i1_u = UBOUND(OutData%LinAccECt,1) + DO i1 = LBOUND(OutData%LinAccECt,1), UBOUND(OutData%LinAccECt,1) + OutData%LinAccECt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEDt,1) + i1_u = UBOUND(OutData%LinAccEDt,1) + DO i1 = LBOUND(OutData%LinAccEDt,1), UBOUND(OutData%LinAccEDt,1) + OutData%LinAccEDt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEIt,1) + i1_u = UBOUND(OutData%LinAccEIt,1) + DO i1 = LBOUND(OutData%LinAccEIt,1), UBOUND(OutData%LinAccEIt,1) + OutData%LinAccEIt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEJt,1) + i1_u = UBOUND(OutData%LinAccEJt,1) + DO i1 = LBOUND(OutData%LinAccEJt,1), UBOUND(OutData%LinAccEJt,1) + OutData%LinAccEJt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEUt,1) + i1_u = UBOUND(OutData%LinAccEUt,1) + DO i1 = LBOUND(OutData%LinAccEUt,1), UBOUND(OutData%LinAccEUt,1) + OutData%LinAccEUt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEYt,1) + i1_u = UBOUND(OutData%LinAccEYt,1) + DO i1 = LBOUND(OutData%LinAccEYt,1), UBOUND(OutData%LinAccEYt,1) + OutData%LinAccEYt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinVelES 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%LinVelES)) DEALLOCATE(OutData%LinVelES) + ALLOCATE(OutData%LinVelES(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%LinVelES.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%LinVelES,3), UBOUND(OutData%LinVelES,3) + DO i2 = LBOUND(OutData%LinVelES,2), UBOUND(OutData%LinVelES,2) + DO i1 = LBOUND(OutData%LinVelES,1), UBOUND(OutData%LinVelES,1) + OutData%LinVelES(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%LinVelEQ,1) + i1_u = UBOUND(OutData%LinVelEQ,1) + DO i1 = LBOUND(OutData%LinVelEQ,1), UBOUND(OutData%LinVelEQ,1) + OutData%LinVelEQ(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinVelET 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%LinVelET)) DEALLOCATE(OutData%LinVelET) + ALLOCATE(OutData%LinVelET(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinVelET.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LinVelET,2), UBOUND(OutData%LinVelET,2) + DO i1 = LBOUND(OutData%LinVelET,1), UBOUND(OutData%LinVelET,1) + OutData%LinVelET(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinVelESm2 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%LinVelESm2)) DEALLOCATE(OutData%LinVelESm2) + ALLOCATE(OutData%LinVelESm2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinVelESm2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinVelESm2,1), UBOUND(OutData%LinVelESm2,1) + OutData%LinVelESm2(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEIMU 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%PLinVelEIMU)) DEALLOCATE(OutData%PLinVelEIMU) + ALLOCATE(OutData%PLinVelEIMU(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%PLinVelEIMU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEIMU,3), UBOUND(OutData%PLinVelEIMU,3) + DO i2 = LBOUND(OutData%PLinVelEIMU,2), UBOUND(OutData%PLinVelEIMU,2) + DO i1 = LBOUND(OutData%PLinVelEIMU,1), UBOUND(OutData%PLinVelEIMU,1) + OutData%PLinVelEIMU(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEO 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%PLinVelEO)) DEALLOCATE(OutData%PLinVelEO) + ALLOCATE(OutData%PLinVelEO(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%PLinVelEO.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEO,3), UBOUND(OutData%PLinVelEO,3) + DO i2 = LBOUND(OutData%PLinVelEO,2), UBOUND(OutData%PLinVelEO,2) + DO i1 = LBOUND(OutData%PLinVelEO,1), UBOUND(OutData%PLinVelEO,1) + OutData%PLinVelEO(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelES 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%PLinVelES)) DEALLOCATE(OutData%PLinVelES) + ALLOCATE(OutData%PLinVelES(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%PLinVelES.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i5 = LBOUND(OutData%PLinVelES,5), UBOUND(OutData%PLinVelES,5) + DO i4 = LBOUND(OutData%PLinVelES,4), UBOUND(OutData%PLinVelES,4) + DO i3 = LBOUND(OutData%PLinVelES,3), UBOUND(OutData%PLinVelES,3) + DO i2 = LBOUND(OutData%PLinVelES,2), UBOUND(OutData%PLinVelES,2) + DO i1 = LBOUND(OutData%PLinVelES,1), UBOUND(OutData%PLinVelES,1) + OutData%PLinVelES(i1,i2,i3,i4,i5) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelET 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%PLinVelET)) DEALLOCATE(OutData%PLinVelET) + ALLOCATE(OutData%PLinVelET(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%PLinVelET.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%PLinVelET,4), UBOUND(OutData%PLinVelET,4) + DO i3 = LBOUND(OutData%PLinVelET,3), UBOUND(OutData%PLinVelET,3) + DO i2 = LBOUND(OutData%PLinVelET,2), UBOUND(OutData%PLinVelET,2) + DO i1 = LBOUND(OutData%PLinVelET,1), UBOUND(OutData%PLinVelET,1) + OutData%PLinVelET(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEZ 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%PLinVelEZ)) DEALLOCATE(OutData%PLinVelEZ) + ALLOCATE(OutData%PLinVelEZ(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%PLinVelEZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEZ,3), UBOUND(OutData%PLinVelEZ,3) + DO i2 = LBOUND(OutData%PLinVelEZ,2), UBOUND(OutData%PLinVelEZ,2) + DO i1 = LBOUND(OutData%PLinVelEZ,1), UBOUND(OutData%PLinVelEZ,1) + OutData%PLinVelEZ(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEC 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%PLinVelEC)) DEALLOCATE(OutData%PLinVelEC) + ALLOCATE(OutData%PLinVelEC(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%PLinVelEC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEC,3), UBOUND(OutData%PLinVelEC,3) + DO i2 = LBOUND(OutData%PLinVelEC,2), UBOUND(OutData%PLinVelEC,2) + DO i1 = LBOUND(OutData%PLinVelEC,1), UBOUND(OutData%PLinVelEC,1) + OutData%PLinVelEC(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelED 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%PLinVelED)) DEALLOCATE(OutData%PLinVelED) + ALLOCATE(OutData%PLinVelED(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%PLinVelED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelED,3), UBOUND(OutData%PLinVelED,3) + DO i2 = LBOUND(OutData%PLinVelED,2), UBOUND(OutData%PLinVelED,2) + DO i1 = LBOUND(OutData%PLinVelED,1), UBOUND(OutData%PLinVelED,1) + OutData%PLinVelED(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEI 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%PLinVelEI)) DEALLOCATE(OutData%PLinVelEI) + ALLOCATE(OutData%PLinVelEI(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%PLinVelEI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEI,3), UBOUND(OutData%PLinVelEI,3) + DO i2 = LBOUND(OutData%PLinVelEI,2), UBOUND(OutData%PLinVelEI,2) + DO i1 = LBOUND(OutData%PLinVelEI,1), UBOUND(OutData%PLinVelEI,1) + OutData%PLinVelEI(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEJ 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%PLinVelEJ)) DEALLOCATE(OutData%PLinVelEJ) + ALLOCATE(OutData%PLinVelEJ(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%PLinVelEJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEJ,3), UBOUND(OutData%PLinVelEJ,3) + DO i2 = LBOUND(OutData%PLinVelEJ,2), UBOUND(OutData%PLinVelEJ,2) + DO i1 = LBOUND(OutData%PLinVelEJ,1), UBOUND(OutData%PLinVelEJ,1) + OutData%PLinVelEJ(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEK 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%PLinVelEK)) DEALLOCATE(OutData%PLinVelEK) + ALLOCATE(OutData%PLinVelEK(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%PLinVelEK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEK,3), UBOUND(OutData%PLinVelEK,3) + DO i2 = LBOUND(OutData%PLinVelEK,2), UBOUND(OutData%PLinVelEK,2) + DO i1 = LBOUND(OutData%PLinVelEK,1), UBOUND(OutData%PLinVelEK,1) + OutData%PLinVelEK(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEP 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%PLinVelEP)) DEALLOCATE(OutData%PLinVelEP) + ALLOCATE(OutData%PLinVelEP(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%PLinVelEP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEP,3), UBOUND(OutData%PLinVelEP,3) + DO i2 = LBOUND(OutData%PLinVelEP,2), UBOUND(OutData%PLinVelEP,2) + DO i1 = LBOUND(OutData%PLinVelEP,1), UBOUND(OutData%PLinVelEP,1) + OutData%PLinVelEP(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEQ 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%PLinVelEQ)) DEALLOCATE(OutData%PLinVelEQ) + ALLOCATE(OutData%PLinVelEQ(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%PLinVelEQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEQ,3), UBOUND(OutData%PLinVelEQ,3) + DO i2 = LBOUND(OutData%PLinVelEQ,2), UBOUND(OutData%PLinVelEQ,2) + DO i1 = LBOUND(OutData%PLinVelEQ,1), UBOUND(OutData%PLinVelEQ,1) + OutData%PLinVelEQ(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEU 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%PLinVelEU)) DEALLOCATE(OutData%PLinVelEU) + ALLOCATE(OutData%PLinVelEU(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%PLinVelEU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEU,3), UBOUND(OutData%PLinVelEU,3) + DO i2 = LBOUND(OutData%PLinVelEU,2), UBOUND(OutData%PLinVelEU,2) + DO i1 = LBOUND(OutData%PLinVelEU,1), UBOUND(OutData%PLinVelEU,1) + OutData%PLinVelEU(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEV 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%PLinVelEV)) DEALLOCATE(OutData%PLinVelEV) + ALLOCATE(OutData%PLinVelEV(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%PLinVelEV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEV,3), UBOUND(OutData%PLinVelEV,3) + DO i2 = LBOUND(OutData%PLinVelEV,2), UBOUND(OutData%PLinVelEV,2) + DO i1 = LBOUND(OutData%PLinVelEV,1), UBOUND(OutData%PLinVelEV,1) + OutData%PLinVelEV(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEW 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%PLinVelEW)) DEALLOCATE(OutData%PLinVelEW) + ALLOCATE(OutData%PLinVelEW(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%PLinVelEW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEW,3), UBOUND(OutData%PLinVelEW,3) + DO i2 = LBOUND(OutData%PLinVelEW,2), UBOUND(OutData%PLinVelEW,2) + DO i1 = LBOUND(OutData%PLinVelEW,1), UBOUND(OutData%PLinVelEW,1) + OutData%PLinVelEW(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PLinVelEY 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%PLinVelEY)) DEALLOCATE(OutData%PLinVelEY) + ALLOCATE(OutData%PLinVelEY(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%PLinVelEY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PLinVelEY,3), UBOUND(OutData%PLinVelEY,3) + DO i2 = LBOUND(OutData%PLinVelEY,2), UBOUND(OutData%PLinVelEY,2) + DO i1 = LBOUND(OutData%PLinVelEY,1), UBOUND(OutData%PLinVelEY,1) + OutData%PLinVelEY(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%LinAccEIMUt,1) + i1_u = UBOUND(OutData%LinAccEIMUt,1) + DO i1 = LBOUND(OutData%LinAccEIMUt,1), UBOUND(OutData%LinAccEIMUt,1) + OutData%LinAccEIMUt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinAccEOt,1) + i1_u = UBOUND(OutData%LinAccEOt,1) + DO i1 = LBOUND(OutData%LinAccEOt,1), UBOUND(OutData%LinAccEOt,1) + OutData%LinAccEOt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinAccESt 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%LinAccESt)) DEALLOCATE(OutData%LinAccESt) + ALLOCATE(OutData%LinAccESt(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%LinAccESt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%LinAccESt,3), UBOUND(OutData%LinAccESt,3) + DO i2 = LBOUND(OutData%LinAccESt,2), UBOUND(OutData%LinAccESt,2) + DO i1 = LBOUND(OutData%LinAccESt,1), UBOUND(OutData%LinAccESt,1) + OutData%LinAccESt(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinAccETt 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%LinAccETt)) DEALLOCATE(OutData%LinAccETt) + ALLOCATE(OutData%LinAccETt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinAccETt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LinAccETt,2), UBOUND(OutData%LinAccETt,2) + DO i1 = LBOUND(OutData%LinAccETt,1), UBOUND(OutData%LinAccETt,1) + OutData%LinAccETt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%LinAccEZt,1) + i1_u = UBOUND(OutData%LinAccEZt,1) + DO i1 = LBOUND(OutData%LinAccEZt,1), UBOUND(OutData%LinAccEZt,1) + OutData%LinAccEZt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinVelEIMU,1) + i1_u = UBOUND(OutData%LinVelEIMU,1) + DO i1 = LBOUND(OutData%LinVelEIMU,1), UBOUND(OutData%LinVelEIMU,1) + OutData%LinVelEIMU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinVelEZ,1) + i1_u = UBOUND(OutData%LinVelEZ,1) + DO i1 = LBOUND(OutData%LinVelEZ,1), UBOUND(OutData%LinVelEZ,1) + OutData%LinVelEZ(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinVelEO,1) + i1_u = UBOUND(OutData%LinVelEO,1) + DO i1 = LBOUND(OutData%LinVelEO,1), UBOUND(OutData%LinVelEO,1) + OutData%LinVelEO(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FrcONcRtt,1) + i1_u = UBOUND(OutData%FrcONcRtt,1) + DO i1 = LBOUND(OutData%FrcONcRtt,1), UBOUND(OutData%FrcONcRtt,1) + OutData%FrcONcRtt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FrcPRott,1) + i1_u = UBOUND(OutData%FrcPRott,1) + DO i1 = LBOUND(OutData%FrcPRott,1), UBOUND(OutData%FrcPRott,1) + OutData%FrcPRott(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FrcS0Bt 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%FrcS0Bt)) DEALLOCATE(OutData%FrcS0Bt) + ALLOCATE(OutData%FrcS0Bt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FrcS0Bt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FrcS0Bt,2), UBOUND(OutData%FrcS0Bt,2) + DO i1 = LBOUND(OutData%FrcS0Bt,1), UBOUND(OutData%FrcS0Bt,1) + OutData%FrcS0Bt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%FrcT0Trbt,1) + i1_u = UBOUND(OutData%FrcT0Trbt,1) + DO i1 = LBOUND(OutData%FrcT0Trbt,1), UBOUND(OutData%FrcT0Trbt,1) + OutData%FrcT0Trbt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSAero 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%FSAero)) DEALLOCATE(OutData%FSAero) + ALLOCATE(OutData%FSAero(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%FSAero.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FSAero,3), UBOUND(OutData%FSAero,3) + DO i2 = LBOUND(OutData%FSAero,2), UBOUND(OutData%FSAero,2) + DO i1 = LBOUND(OutData%FSAero,1), UBOUND(OutData%FSAero,1) + OutData%FSAero(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FSTipDrag 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%FSTipDrag)) DEALLOCATE(OutData%FSTipDrag) + ALLOCATE(OutData%FSTipDrag(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FSTipDrag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FSTipDrag,2), UBOUND(OutData%FSTipDrag,2) + DO i1 = LBOUND(OutData%FSTipDrag,1), UBOUND(OutData%FSTipDrag,1) + OutData%FSTipDrag(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FTHydrot 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%FTHydrot)) DEALLOCATE(OutData%FTHydrot) + ALLOCATE(OutData%FTHydrot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FTHydrot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FTHydrot,2), UBOUND(OutData%FTHydrot,2) + DO i1 = LBOUND(OutData%FTHydrot,1), UBOUND(OutData%FTHydrot,1) + OutData%FTHydrot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%FZHydrot,1) + i1_u = UBOUND(OutData%FZHydrot,1) + DO i1 = LBOUND(OutData%FZHydrot,1), UBOUND(OutData%FZHydrot,1) + OutData%FZHydrot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MFHydrot 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%MFHydrot)) DEALLOCATE(OutData%MFHydrot) + ALLOCATE(OutData%MFHydrot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MFHydrot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MFHydrot,2), UBOUND(OutData%MFHydrot,2) + DO i1 = LBOUND(OutData%MFHydrot,1), UBOUND(OutData%MFHydrot,1) + OutData%MFHydrot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%MomBNcRtt,1) + i1_u = UBOUND(OutData%MomBNcRtt,1) + DO i1 = LBOUND(OutData%MomBNcRtt,1), UBOUND(OutData%MomBNcRtt,1) + OutData%MomBNcRtt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MomH0Bt 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%MomH0Bt)) DEALLOCATE(OutData%MomH0Bt) + ALLOCATE(OutData%MomH0Bt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MomH0Bt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MomH0Bt,2), UBOUND(OutData%MomH0Bt,2) + DO i1 = LBOUND(OutData%MomH0Bt,1), UBOUND(OutData%MomH0Bt,1) + OutData%MomH0Bt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%MomLPRott,1) + i1_u = UBOUND(OutData%MomLPRott,1) + DO i1 = LBOUND(OutData%MomLPRott,1), UBOUND(OutData%MomLPRott,1) + OutData%MomLPRott(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%MomNGnRtt,1) + i1_u = UBOUND(OutData%MomNGnRtt,1) + DO i1 = LBOUND(OutData%MomNGnRtt,1), UBOUND(OutData%MomNGnRtt,1) + OutData%MomNGnRtt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%MomNTailt,1) + i1_u = UBOUND(OutData%MomNTailt,1) + DO i1 = LBOUND(OutData%MomNTailt,1), UBOUND(OutData%MomNTailt,1) + OutData%MomNTailt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%MomX0Trbt,1) + i1_u = UBOUND(OutData%MomX0Trbt,1) + DO i1 = LBOUND(OutData%MomX0Trbt,1), UBOUND(OutData%MomX0Trbt,1) + OutData%MomX0Trbt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMAero 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%MMAero)) DEALLOCATE(OutData%MMAero) + ALLOCATE(OutData%MMAero(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%MMAero.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%MMAero,3), UBOUND(OutData%MMAero,3) + DO i2 = LBOUND(OutData%MMAero,2), UBOUND(OutData%MMAero,2) + DO i1 = LBOUND(OutData%MMAero,1), UBOUND(OutData%MMAero,1) + OutData%MMAero(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%MXHydrot,1) + i1_u = UBOUND(OutData%MXHydrot,1) + DO i1 = LBOUND(OutData%MXHydrot,1), UBOUND(OutData%MXHydrot,1) + OutData%MXHydrot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcONcRt 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%PFrcONcRt)) DEALLOCATE(OutData%PFrcONcRt) + ALLOCATE(OutData%PFrcONcRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcONcRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcONcRt,2), UBOUND(OutData%PFrcONcRt,2) + DO i1 = LBOUND(OutData%PFrcONcRt,1), UBOUND(OutData%PFrcONcRt,1) + OutData%PFrcONcRt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcPRot 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%PFrcPRot)) DEALLOCATE(OutData%PFrcPRot) + ALLOCATE(OutData%PFrcPRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcPRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcPRot,2), UBOUND(OutData%PFrcPRot,2) + DO i1 = LBOUND(OutData%PFrcPRot,1), UBOUND(OutData%PFrcPRot,1) + OutData%PFrcPRot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcS0B 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%PFrcS0B)) DEALLOCATE(OutData%PFrcS0B) + ALLOCATE(OutData%PFrcS0B(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%PFrcS0B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PFrcS0B,3), UBOUND(OutData%PFrcS0B,3) + DO i2 = LBOUND(OutData%PFrcS0B,2), UBOUND(OutData%PFrcS0B,2) + DO i1 = LBOUND(OutData%PFrcS0B,1), UBOUND(OutData%PFrcS0B,1) + OutData%PFrcS0B(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcT0Trb 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%PFrcT0Trb)) DEALLOCATE(OutData%PFrcT0Trb) + ALLOCATE(OutData%PFrcT0Trb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcT0Trb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcT0Trb,2), UBOUND(OutData%PFrcT0Trb,2) + DO i1 = LBOUND(OutData%PFrcT0Trb,1), UBOUND(OutData%PFrcT0Trb,1) + OutData%PFrcT0Trb(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFTHydro 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%PFTHydro)) DEALLOCATE(OutData%PFTHydro) + ALLOCATE(OutData%PFTHydro(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%PFTHydro.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PFTHydro,3), UBOUND(OutData%PFTHydro,3) + DO i2 = LBOUND(OutData%PFTHydro,2), UBOUND(OutData%PFTHydro,2) + DO i1 = LBOUND(OutData%PFTHydro,1), UBOUND(OutData%PFTHydro,1) + OutData%PFTHydro(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%PFZHydro,1) + i1_u = UBOUND(OutData%PFZHydro,1) + i2_l = LBOUND(OutData%PFZHydro,2) + i2_u = UBOUND(OutData%PFZHydro,2) + DO i2 = LBOUND(OutData%PFZHydro,2), UBOUND(OutData%PFZHydro,2) + DO i1 = LBOUND(OutData%PFZHydro,1), UBOUND(OutData%PFZHydro,1) + OutData%PFZHydro(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMFHydro 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%PMFHydro)) DEALLOCATE(OutData%PMFHydro) + ALLOCATE(OutData%PMFHydro(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%PMFHydro.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PMFHydro,3), UBOUND(OutData%PMFHydro,3) + DO i2 = LBOUND(OutData%PMFHydro,2), UBOUND(OutData%PMFHydro,2) + DO i1 = LBOUND(OutData%PMFHydro,1), UBOUND(OutData%PMFHydro,1) + OutData%PMFHydro(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomBNcRt 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%PMomBNcRt)) DEALLOCATE(OutData%PMomBNcRt) + ALLOCATE(OutData%PMomBNcRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomBNcRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomBNcRt,2), UBOUND(OutData%PMomBNcRt,2) + DO i1 = LBOUND(OutData%PMomBNcRt,1), UBOUND(OutData%PMomBNcRt,1) + OutData%PMomBNcRt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomH0B 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%PMomH0B)) DEALLOCATE(OutData%PMomH0B) + ALLOCATE(OutData%PMomH0B(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%PMomH0B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PMomH0B,3), UBOUND(OutData%PMomH0B,3) + DO i2 = LBOUND(OutData%PMomH0B,2), UBOUND(OutData%PMomH0B,2) + DO i1 = LBOUND(OutData%PMomH0B,1), UBOUND(OutData%PMomH0B,1) + OutData%PMomH0B(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomLPRot 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%PMomLPRot)) DEALLOCATE(OutData%PMomLPRot) + ALLOCATE(OutData%PMomLPRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomLPRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomLPRot,2), UBOUND(OutData%PMomLPRot,2) + DO i1 = LBOUND(OutData%PMomLPRot,1), UBOUND(OutData%PMomLPRot,1) + OutData%PMomLPRot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomNGnRt 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%PMomNGnRt)) DEALLOCATE(OutData%PMomNGnRt) + ALLOCATE(OutData%PMomNGnRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomNGnRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomNGnRt,2), UBOUND(OutData%PMomNGnRt,2) + DO i1 = LBOUND(OutData%PMomNGnRt,1), UBOUND(OutData%PMomNGnRt,1) + OutData%PMomNGnRt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomNTail 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%PMomNTail)) DEALLOCATE(OutData%PMomNTail) + ALLOCATE(OutData%PMomNTail(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomNTail.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomNTail,2), UBOUND(OutData%PMomNTail,2) + DO i1 = LBOUND(OutData%PMomNTail,1), UBOUND(OutData%PMomNTail,1) + OutData%PMomNTail(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomX0Trb 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%PMomX0Trb)) DEALLOCATE(OutData%PMomX0Trb) + ALLOCATE(OutData%PMomX0Trb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomX0Trb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomX0Trb,2), UBOUND(OutData%PMomX0Trb,2) + DO i1 = LBOUND(OutData%PMomX0Trb,1), UBOUND(OutData%PMomX0Trb,1) + OutData%PMomX0Trb(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%PMXHydro,1) + i1_u = UBOUND(OutData%PMXHydro,1) + i2_l = LBOUND(OutData%PMXHydro,2) + i2_u = UBOUND(OutData%PMXHydro,2) + DO i2 = LBOUND(OutData%PMXHydro,2), UBOUND(OutData%PMXHydro,2) + DO i1 = LBOUND(OutData%PMXHydro,1), UBOUND(OutData%PMXHydro,1) + OutData%PMXHydro(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%TeetAng = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%FrcVGnRtt,1) + i1_u = UBOUND(OutData%FrcVGnRtt,1) + DO i1 = LBOUND(OutData%FrcVGnRtt,1), UBOUND(OutData%FrcVGnRtt,1) + OutData%FrcVGnRtt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FrcWTailt,1) + i1_u = UBOUND(OutData%FrcWTailt,1) + DO i1 = LBOUND(OutData%FrcWTailt,1), UBOUND(OutData%FrcWTailt,1) + OutData%FrcWTailt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FrcZAllt,1) + i1_u = UBOUND(OutData%FrcZAllt,1) + DO i1 = LBOUND(OutData%FrcZAllt,1), UBOUND(OutData%FrcZAllt,1) + OutData%FrcZAllt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%MomXAllt,1) + i1_u = UBOUND(OutData%MomXAllt,1) + DO i1 = LBOUND(OutData%MomXAllt,1), UBOUND(OutData%MomXAllt,1) + OutData%MomXAllt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcVGnRt 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%PFrcVGnRt)) DEALLOCATE(OutData%PFrcVGnRt) + ALLOCATE(OutData%PFrcVGnRt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcVGnRt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcVGnRt,2), UBOUND(OutData%PFrcVGnRt,2) + DO i1 = LBOUND(OutData%PFrcVGnRt,1), UBOUND(OutData%PFrcVGnRt,1) + OutData%PFrcVGnRt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcWTail 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%PFrcWTail)) DEALLOCATE(OutData%PFrcWTail) + ALLOCATE(OutData%PFrcWTail(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcWTail.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcWTail,2), UBOUND(OutData%PFrcWTail,2) + DO i1 = LBOUND(OutData%PFrcWTail,1), UBOUND(OutData%PFrcWTail,1) + OutData%PFrcWTail(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PFrcZAll 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%PFrcZAll)) DEALLOCATE(OutData%PFrcZAll) + ALLOCATE(OutData%PFrcZAll(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PFrcZAll.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PFrcZAll,2), UBOUND(OutData%PFrcZAll,2) + DO i1 = LBOUND(OutData%PFrcZAll,1), UBOUND(OutData%PFrcZAll,1) + OutData%PFrcZAll(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PMomXAll 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%PMomXAll)) DEALLOCATE(OutData%PMomXAll) + ALLOCATE(OutData%PMomXAll(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PMomXAll.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PMomXAll,2), UBOUND(OutData%PMomXAll,2) + DO i1 = LBOUND(OutData%PMomXAll,1), UBOUND(OutData%PMomXAll,1) + OutData%PMomXAll(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%TeetMom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlMom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlMom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GBoxEffFac = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rSAerCen 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%rSAerCen)) DEALLOCATE(OutData%rSAerCen) + ALLOCATE(OutData%rSAerCen(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%rSAerCen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%rSAerCen,3), UBOUND(OutData%rSAerCen,3) + DO i2 = LBOUND(OutData%rSAerCen,2), UBOUND(OutData%rSAerCen,2) + DO i1 = LBOUND(OutData%rSAerCen,1), UBOUND(OutData%rSAerCen,1) + OutData%rSAerCen(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE ED_UnPackRtHndSide + + SUBROUTINE ED_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(ED_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%QT)) THEN + i1_l = LBOUND(SrcContStateData%QT,1) + i1_u = UBOUND(SrcContStateData%QT,1) + IF (.NOT. ALLOCATED(DstContStateData%QT)) THEN + ALLOCATE(DstContStateData%QT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%QT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%QT = SrcContStateData%QT +ENDIF +IF (ALLOCATED(SrcContStateData%QDT)) THEN + i1_l = LBOUND(SrcContStateData%QDT,1) + i1_u = UBOUND(SrcContStateData%QDT,1) + IF (.NOT. ALLOCATED(DstContStateData%QDT)) THEN + ALLOCATE(DstContStateData%QDT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%QDT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%QDT = SrcContStateData%QDT +ENDIF + END SUBROUTINE ED_CopyContState + + SUBROUTINE ED_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(ED_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%QT)) THEN + DEALLOCATE(ContStateData%QT) +ENDIF +IF (ALLOCATED(ContStateData%QDT)) THEN + DEALLOCATE(ContStateData%QDT) +ENDIF + END SUBROUTINE ED_DestroyContState + + SUBROUTINE ED_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(ED_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 = 'ED_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 + Int_BufSz = Int_BufSz + 1 ! QT allocated yes/no + IF ( ALLOCATED(InData%QT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! QT upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QT) ! QT + END IF + Int_BufSz = Int_BufSz + 1 ! QDT allocated yes/no + IF ( ALLOCATED(InData%QDT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! QDT upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QDT) ! QDT + 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%QT) ) 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%QT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%QT,1), UBOUND(InData%QT,1) + DbKiBuf(Db_Xferred) = InData%QT(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QDT) ) 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%QDT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QDT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%QDT,1), UBOUND(InData%QDT,1) + DbKiBuf(Db_Xferred) = InData%QDT(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_PackContState + + SUBROUTINE ED_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(ED_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QT 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%QT)) DEALLOCATE(OutData%QT) + ALLOCATE(OutData%QT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%QT,1), UBOUND(OutData%QT,1) + OutData%QT(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QDT 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%QDT)) DEALLOCATE(OutData%QDT) + ALLOCATE(OutData%QDT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QDT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%QDT,1), UBOUND(OutData%QDT,1) + OutData%QDT(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE ED_UnPackContState + + SUBROUTINE ED_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(ED_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 = 'ED_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE ED_CopyDiscState + + SUBROUTINE ED_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(ED_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ED_DestroyDiscState + + SUBROUTINE ED_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(ED_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 = 'ED_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 ED_PackDiscState + + SUBROUTINE ED_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(ED_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 = 'ED_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 ED_UnPackDiscState + + SUBROUTINE ED_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(ED_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 = 'ED_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE ED_CopyConstrState + + SUBROUTINE ED_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(ED_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ED_DestroyConstrState + + SUBROUTINE ED_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(ED_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 = 'ED_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 ED_PackConstrState + + SUBROUTINE ED_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(ED_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 = 'ED_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 ED_UnPackConstrState + + SUBROUTINE ED_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(ED_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%n = SrcOtherStateData%n + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL ED_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +IF (ALLOCATED(SrcOtherStateData%IC)) THEN + i1_l = LBOUND(SrcOtherStateData%IC,1) + i1_u = UBOUND(SrcOtherStateData%IC,1) + IF (.NOT. ALLOCATED(DstOtherStateData%IC)) THEN + ALLOCATE(DstOtherStateData%IC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%IC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%IC = SrcOtherStateData%IC +ENDIF + DstOtherStateData%HSSBrTrq = SrcOtherStateData%HSSBrTrq + DstOtherStateData%HSSBrTrqC = SrcOtherStateData%HSSBrTrqC + DstOtherStateData%SgnPrvLSTQ = SrcOtherStateData%SgnPrvLSTQ + DstOtherStateData%SgnLSTQ = SrcOtherStateData%SgnLSTQ + END SUBROUTINE ED_CopyOtherState + + SUBROUTINE ED_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL ED_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO +IF (ALLOCATED(OtherStateData%IC)) THEN + DEALLOCATE(OtherStateData%IC) +ENDIF + END SUBROUTINE ED_DestroyOtherState + + SUBROUTINE ED_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(ED_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 = 'ED_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 + Int_BufSz = Int_BufSz + 1 ! n + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 1 ! IC allocated yes/no + IF ( ALLOCATED(InData%IC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IC upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IC) ! IC + END IF + Re_BufSz = Re_BufSz + 1 ! HSSBrTrq + Re_BufSz = Re_BufSz + 1 ! HSSBrTrqC + Int_BufSz = Int_BufSz + 1 ! SgnPrvLSTQ + Int_BufSz = Int_BufSz + SIZE(InData%SgnLSTQ) ! SgnLSTQ + 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%n + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 + IF ( .NOT. ALLOCATED(InData%IC) ) 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%IC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IC,1), UBOUND(InData%IC,1) + IntKiBuf(Int_Xferred) = InData%IC(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%HSSBrTrq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSSBrTrqC + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SgnPrvLSTQ + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%SgnLSTQ,1), UBOUND(InData%SgnLSTQ,1) + IntKiBuf(Int_Xferred) = InData%SgnLSTQ(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE ED_PackOtherState + + SUBROUTINE ED_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(ED_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_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%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%xdot,1) + i1_u = UBOUND(OutData%xdot,1) + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 ED_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IC 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%IC)) DEALLOCATE(OutData%IC) + ALLOCATE(OutData%IC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IC,1), UBOUND(OutData%IC,1) + OutData%IC(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%HSSBrTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSSBrTrqC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SgnPrvLSTQ = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SgnLSTQ,1) + i1_u = UBOUND(OutData%SgnLSTQ,1) + DO i1 = LBOUND(OutData%SgnLSTQ,1), UBOUND(OutData%SgnLSTQ,1) + OutData%SgnLSTQ(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE ED_UnPackOtherState + + SUBROUTINE ED_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(ED_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL ED_Copycoordsys( SrcMiscData%CoordSys, DstMiscData%CoordSys, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ED_Copyrthndside( SrcMiscData%RtHS, DstMiscData%RtHS, 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) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF +IF (ALLOCATED(SrcMiscData%AugMat)) THEN + i1_l = LBOUND(SrcMiscData%AugMat,1) + i1_u = UBOUND(SrcMiscData%AugMat,1) + i2_l = LBOUND(SrcMiscData%AugMat,2) + i2_u = UBOUND(SrcMiscData%AugMat,2) + IF (.NOT. ALLOCATED(DstMiscData%AugMat)) THEN + ALLOCATE(DstMiscData%AugMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AugMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AugMat = SrcMiscData%AugMat +ENDIF +IF (ALLOCATED(SrcMiscData%AugMat_factor)) THEN + i1_l = LBOUND(SrcMiscData%AugMat_factor,1) + i1_u = UBOUND(SrcMiscData%AugMat_factor,1) + i2_l = LBOUND(SrcMiscData%AugMat_factor,2) + i2_u = UBOUND(SrcMiscData%AugMat_factor,2) + IF (.NOT. ALLOCATED(DstMiscData%AugMat_factor)) THEN + ALLOCATE(DstMiscData%AugMat_factor(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AugMat_factor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AugMat_factor = SrcMiscData%AugMat_factor +ENDIF +IF (ALLOCATED(SrcMiscData%SolnVec)) THEN + i1_l = LBOUND(SrcMiscData%SolnVec,1) + i1_u = UBOUND(SrcMiscData%SolnVec,1) + IF (.NOT. ALLOCATED(DstMiscData%SolnVec)) THEN + ALLOCATE(DstMiscData%SolnVec(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SolnVec.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SolnVec = SrcMiscData%SolnVec +ENDIF +IF (ALLOCATED(SrcMiscData%AugMat_pivot)) THEN + i1_l = LBOUND(SrcMiscData%AugMat_pivot,1) + i1_u = UBOUND(SrcMiscData%AugMat_pivot,1) + IF (.NOT. ALLOCATED(DstMiscData%AugMat_pivot)) THEN + ALLOCATE(DstMiscData%AugMat_pivot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AugMat_pivot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AugMat_pivot = SrcMiscData%AugMat_pivot +ENDIF +IF (ALLOCATED(SrcMiscData%OgnlGeAzRo)) THEN + i1_l = LBOUND(SrcMiscData%OgnlGeAzRo,1) + i1_u = UBOUND(SrcMiscData%OgnlGeAzRo,1) + IF (.NOT. ALLOCATED(DstMiscData%OgnlGeAzRo)) THEN + ALLOCATE(DstMiscData%OgnlGeAzRo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%OgnlGeAzRo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%OgnlGeAzRo = SrcMiscData%OgnlGeAzRo +ENDIF +IF (ALLOCATED(SrcMiscData%QD2T)) THEN + i1_l = LBOUND(SrcMiscData%QD2T,1) + i1_u = UBOUND(SrcMiscData%QD2T,1) + IF (.NOT. ALLOCATED(DstMiscData%QD2T)) THEN + ALLOCATE(DstMiscData%QD2T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%QD2T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%QD2T = SrcMiscData%QD2T +ENDIF + DstMiscData%IgnoreMod = SrcMiscData%IgnoreMod + END SUBROUTINE ED_CopyMisc + + SUBROUTINE ED_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(ED_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL ED_Destroycoordsys( MiscData%CoordSys, ErrStat, ErrMsg ) + CALL ED_Destroyrthndside( MiscData%RtHS, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF +IF (ALLOCATED(MiscData%AugMat)) THEN + DEALLOCATE(MiscData%AugMat) +ENDIF +IF (ALLOCATED(MiscData%AugMat_factor)) THEN + DEALLOCATE(MiscData%AugMat_factor) +ENDIF +IF (ALLOCATED(MiscData%SolnVec)) THEN + DEALLOCATE(MiscData%SolnVec) +ENDIF +IF (ALLOCATED(MiscData%AugMat_pivot)) THEN + DEALLOCATE(MiscData%AugMat_pivot) +ENDIF +IF (ALLOCATED(MiscData%OgnlGeAzRo)) THEN + DEALLOCATE(MiscData%OgnlGeAzRo) +ENDIF +IF (ALLOCATED(MiscData%QD2T)) THEN + DEALLOCATE(MiscData%QD2T) +ENDIF + END SUBROUTINE ED_DestroyMisc + + SUBROUTINE ED_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(ED_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 = 'ED_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! CoordSys: size of buffers for each call to pack subtype + CALL ED_Packcoordsys( Re_Buf, Db_Buf, Int_Buf, InData%CoordSys, ErrStat2, ErrMsg2, .TRUE. ) ! CoordSys + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! CoordSys + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! CoordSys + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! CoordSys + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! RtHS: size of buffers for each call to pack subtype + CALL ED_Packrthndside( Re_Buf, Db_Buf, Int_Buf, InData%RtHS, ErrStat2, ErrMsg2, .TRUE. ) ! RtHS + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RtHS + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RtHS + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RtHS + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + 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 + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + END IF + Int_BufSz = Int_BufSz + 1 ! AugMat allocated yes/no + IF ( ALLOCATED(InData%AugMat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AugMat upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%AugMat) ! AugMat + END IF + Int_BufSz = Int_BufSz + 1 ! AugMat_factor allocated yes/no + IF ( ALLOCATED(InData%AugMat_factor) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AugMat_factor upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%AugMat_factor) ! AugMat_factor + END IF + Int_BufSz = Int_BufSz + 1 ! SolnVec allocated yes/no + IF ( ALLOCATED(InData%SolnVec) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SolnVec upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%SolnVec) ! SolnVec + END IF + Int_BufSz = Int_BufSz + 1 ! AugMat_pivot allocated yes/no + IF ( ALLOCATED(InData%AugMat_pivot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AugMat_pivot upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AugMat_pivot) ! AugMat_pivot + END IF + Int_BufSz = Int_BufSz + 1 ! OgnlGeAzRo allocated yes/no + IF ( ALLOCATED(InData%OgnlGeAzRo) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OgnlGeAzRo upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OgnlGeAzRo) ! OgnlGeAzRo + END IF + Int_BufSz = Int_BufSz + 1 ! QD2T allocated yes/no + IF ( ALLOCATED(InData%QD2T) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! QD2T upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%QD2T) ! QD2T + END IF + Int_BufSz = Int_BufSz + 1 ! IgnoreMod + 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 ED_Packcoordsys( Re_Buf, Db_Buf, Int_Buf, InData%CoordSys, ErrStat2, ErrMsg2, OnlySize ) ! CoordSys + 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 ED_Packrthndside( Re_Buf, Db_Buf, Int_Buf, InData%RtHS, ErrStat2, ErrMsg2, OnlySize ) ! RtHS + 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%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AugMat) ) 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%AugMat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AugMat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AugMat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AugMat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AugMat,2), UBOUND(InData%AugMat,2) + DO i1 = LBOUND(InData%AugMat,1), UBOUND(InData%AugMat,1) + DbKiBuf(Db_Xferred) = InData%AugMat(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AugMat_factor) ) 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%AugMat_factor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AugMat_factor,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AugMat_factor,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AugMat_factor,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AugMat_factor,2), UBOUND(InData%AugMat_factor,2) + DO i1 = LBOUND(InData%AugMat_factor,1), UBOUND(InData%AugMat_factor,1) + DbKiBuf(Db_Xferred) = InData%AugMat_factor(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SolnVec) ) 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%SolnVec,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SolnVec,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SolnVec,1), UBOUND(InData%SolnVec,1) + DbKiBuf(Db_Xferred) = InData%SolnVec(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AugMat_pivot) ) 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%AugMat_pivot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AugMat_pivot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AugMat_pivot,1), UBOUND(InData%AugMat_pivot,1) + IntKiBuf(Int_Xferred) = InData%AugMat_pivot(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OgnlGeAzRo) ) 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%OgnlGeAzRo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OgnlGeAzRo,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OgnlGeAzRo,1), UBOUND(InData%OgnlGeAzRo,1) + ReKiBuf(Re_Xferred) = InData%OgnlGeAzRo(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%QD2T) ) 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%QD2T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%QD2T,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%QD2T,1), UBOUND(InData%QD2T,1) + DbKiBuf(Db_Xferred) = InData%QD2T(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%IgnoreMod, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_PackMisc + + SUBROUTINE ED_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(ED_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_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 + 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 ED_Unpackcoordsys( Re_Buf, Db_Buf, Int_Buf, OutData%CoordSys, ErrStat2, ErrMsg2 ) ! CoordSys + 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 ED_Unpackrthndside( Re_Buf, Db_Buf, Int_Buf, OutData%RtHS, ErrStat2, ErrMsg2 ) ! RtHS + 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 + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AugMat 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%AugMat)) DEALLOCATE(OutData%AugMat) + ALLOCATE(OutData%AugMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AugMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AugMat,2), UBOUND(OutData%AugMat,2) + DO i1 = LBOUND(OutData%AugMat,1), UBOUND(OutData%AugMat,1) + OutData%AugMat(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AugMat_factor 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%AugMat_factor)) DEALLOCATE(OutData%AugMat_factor) + ALLOCATE(OutData%AugMat_factor(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AugMat_factor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AugMat_factor,2), UBOUND(OutData%AugMat_factor,2) + DO i1 = LBOUND(OutData%AugMat_factor,1), UBOUND(OutData%AugMat_factor,1) + OutData%AugMat_factor(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SolnVec 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%SolnVec)) DEALLOCATE(OutData%SolnVec) + ALLOCATE(OutData%SolnVec(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SolnVec.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SolnVec,1), UBOUND(OutData%SolnVec,1) + OutData%SolnVec(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AugMat_pivot 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%AugMat_pivot)) DEALLOCATE(OutData%AugMat_pivot) + ALLOCATE(OutData%AugMat_pivot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AugMat_pivot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AugMat_pivot,1), UBOUND(OutData%AugMat_pivot,1) + OutData%AugMat_pivot(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OgnlGeAzRo 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%OgnlGeAzRo)) DEALLOCATE(OutData%OgnlGeAzRo) + ALLOCATE(OutData%OgnlGeAzRo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OgnlGeAzRo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OgnlGeAzRo,1), UBOUND(OutData%OgnlGeAzRo,1) + OutData%OgnlGeAzRo(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! QD2T 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%QD2T)) DEALLOCATE(OutData%QD2T) + ALLOCATE(OutData%QD2T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%QD2T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%QD2T,1), UBOUND(OutData%QD2T,1) + OutData%QD2T(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%IgnoreMod = TRANSFER(IntKiBuf(Int_Xferred), OutData%IgnoreMod) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_UnPackMisc + + SUBROUTINE ED_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_ParameterType), INTENT(IN) :: SrcParamData + TYPE(ED_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) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%DT24 = SrcParamData%DT24 + DstParamData%BldNodes = SrcParamData%BldNodes + DstParamData%TipNode = SrcParamData%TipNode + DstParamData%NDOF = SrcParamData%NDOF + DstParamData%TwoPiNB = SrcParamData%TwoPiNB + DstParamData%NAug = SrcParamData%NAug + DstParamData%NPH = SrcParamData%NPH +IF (ALLOCATED(SrcParamData%PH)) THEN + i1_l = LBOUND(SrcParamData%PH,1) + i1_u = UBOUND(SrcParamData%PH,1) + IF (.NOT. ALLOCATED(DstParamData%PH)) THEN + ALLOCATE(DstParamData%PH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PH = SrcParamData%PH +ENDIF + DstParamData%NPM = SrcParamData%NPM +IF (ALLOCATED(SrcParamData%PM)) THEN + i1_l = LBOUND(SrcParamData%PM,1) + i1_u = UBOUND(SrcParamData%PM,1) + i2_l = LBOUND(SrcParamData%PM,2) + i2_u = UBOUND(SrcParamData%PM,2) + IF (.NOT. ALLOCATED(DstParamData%PM)) THEN + ALLOCATE(DstParamData%PM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PM = SrcParamData%PM +ENDIF +IF (ALLOCATED(SrcParamData%DOF_Flag)) THEN + i1_l = LBOUND(SrcParamData%DOF_Flag,1) + i1_u = UBOUND(SrcParamData%DOF_Flag,1) + IF (.NOT. ALLOCATED(DstParamData%DOF_Flag)) THEN + ALLOCATE(DstParamData%DOF_Flag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOF_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DOF_Flag = SrcParamData%DOF_Flag +ENDIF +IF (ALLOCATED(SrcParamData%DOF_Desc)) THEN + i1_l = LBOUND(SrcParamData%DOF_Desc,1) + i1_u = UBOUND(SrcParamData%DOF_Desc,1) + IF (.NOT. ALLOCATED(DstParamData%DOF_Desc)) THEN + ALLOCATE(DstParamData%DOF_Desc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOF_Desc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DOF_Desc = SrcParamData%DOF_Desc +ENDIF + CALL ED_Copyactivedofs( SrcParamData%DOFs, DstParamData%DOFs, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%NBlGages = SrcParamData%NBlGages + DstParamData%NTwGages = SrcParamData%NTwGages +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%Delim = SrcParamData%Delim + DstParamData%AvgNrmTpRd = SrcParamData%AvgNrmTpRd + DstParamData%AzimB1Up = SrcParamData%AzimB1Up + DstParamData%CosDel3 = SrcParamData%CosDel3 +IF (ALLOCATED(SrcParamData%CosPreC)) THEN + i1_l = LBOUND(SrcParamData%CosPreC,1) + i1_u = UBOUND(SrcParamData%CosPreC,1) + IF (.NOT. ALLOCATED(DstParamData%CosPreC)) THEN + ALLOCATE(DstParamData%CosPreC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CosPreC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CosPreC = SrcParamData%CosPreC +ENDIF + DstParamData%CRFrlSkew = SrcParamData%CRFrlSkew + DstParamData%CRFrlSkw2 = SrcParamData%CRFrlSkw2 + DstParamData%CRFrlTilt = SrcParamData%CRFrlTilt + DstParamData%CRFrlTlt2 = SrcParamData%CRFrlTlt2 + DstParamData%CShftSkew = SrcParamData%CShftSkew + DstParamData%CShftTilt = SrcParamData%CShftTilt + DstParamData%CSRFrlSkw = SrcParamData%CSRFrlSkw + DstParamData%CSRFrlTlt = SrcParamData%CSRFrlTlt + DstParamData%CSTFrlSkw = SrcParamData%CSTFrlSkw + DstParamData%CSTFrlTlt = SrcParamData%CSTFrlTlt + DstParamData%CTFinBank = SrcParamData%CTFinBank + DstParamData%CTFinSkew = SrcParamData%CTFinSkew + DstParamData%CTFinTilt = SrcParamData%CTFinTilt + DstParamData%CTFrlSkew = SrcParamData%CTFrlSkew + DstParamData%CTFrlSkw2 = SrcParamData%CTFrlSkw2 + DstParamData%CTFrlTilt = SrcParamData%CTFrlTilt + DstParamData%CTFrlTlt2 = SrcParamData%CTFrlTlt2 + DstParamData%HubHt = SrcParamData%HubHt + DstParamData%HubCM = SrcParamData%HubCM + DstParamData%HubRad = SrcParamData%HubRad + DstParamData%NacCMxn = SrcParamData%NacCMxn + DstParamData%NacCMyn = SrcParamData%NacCMyn + DstParamData%NacCMzn = SrcParamData%NacCMzn + DstParamData%OverHang = SrcParamData%OverHang + DstParamData%ProjArea = SrcParamData%ProjArea + DstParamData%PtfmRefzt = SrcParamData%PtfmRefzt + DstParamData%RefTwrHt = SrcParamData%RefTwrHt + DstParamData%RFrlPntxn = SrcParamData%RFrlPntxn + DstParamData%RFrlPntyn = SrcParamData%RFrlPntyn + DstParamData%RFrlPntzn = SrcParamData%RFrlPntzn + DstParamData%rVDxn = SrcParamData%rVDxn + DstParamData%rVDyn = SrcParamData%rVDyn + DstParamData%rVDzn = SrcParamData%rVDzn + DstParamData%rVIMUxn = SrcParamData%rVIMUxn + DstParamData%rVIMUyn = SrcParamData%rVIMUyn + DstParamData%rVIMUzn = SrcParamData%rVIMUzn + DstParamData%rVPxn = SrcParamData%rVPxn + DstParamData%rVPyn = SrcParamData%rVPyn + DstParamData%rVPzn = SrcParamData%rVPzn + DstParamData%rWIxn = SrcParamData%rWIxn + DstParamData%rWIyn = SrcParamData%rWIyn + DstParamData%rWIzn = SrcParamData%rWIzn + DstParamData%rWJxn = SrcParamData%rWJxn + DstParamData%rWJyn = SrcParamData%rWJyn + DstParamData%rWJzn = SrcParamData%rWJzn + DstParamData%rWKxn = SrcParamData%rWKxn + DstParamData%rWKyn = SrcParamData%rWKyn + DstParamData%rWKzn = SrcParamData%rWKzn + DstParamData%rZT0zt = SrcParamData%rZT0zt + DstParamData%rZYzt = SrcParamData%rZYzt + DstParamData%SinDel3 = SrcParamData%SinDel3 +IF (ALLOCATED(SrcParamData%SinPreC)) THEN + i1_l = LBOUND(SrcParamData%SinPreC,1) + i1_u = UBOUND(SrcParamData%SinPreC,1) + IF (.NOT. ALLOCATED(DstParamData%SinPreC)) THEN + ALLOCATE(DstParamData%SinPreC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%SinPreC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%SinPreC = SrcParamData%SinPreC +ENDIF + DstParamData%SRFrlSkew = SrcParamData%SRFrlSkew + DstParamData%SRFrlSkw2 = SrcParamData%SRFrlSkw2 + DstParamData%SRFrlTilt = SrcParamData%SRFrlTilt + DstParamData%SRFrlTlt2 = SrcParamData%SRFrlTlt2 + DstParamData%SShftSkew = SrcParamData%SShftSkew + DstParamData%SShftTilt = SrcParamData%SShftTilt + DstParamData%STFinBank = SrcParamData%STFinBank + DstParamData%STFinSkew = SrcParamData%STFinSkew + DstParamData%STFinTilt = SrcParamData%STFinTilt + DstParamData%STFrlSkew = SrcParamData%STFrlSkew + DstParamData%STFrlSkw2 = SrcParamData%STFrlSkw2 + DstParamData%STFrlTilt = SrcParamData%STFrlTilt + DstParamData%STFrlTlt2 = SrcParamData%STFrlTlt2 + DstParamData%TFrlPntxn = SrcParamData%TFrlPntxn + DstParamData%TFrlPntyn = SrcParamData%TFrlPntyn + DstParamData%TFrlPntzn = SrcParamData%TFrlPntzn + DstParamData%TipRad = SrcParamData%TipRad + DstParamData%TowerHt = SrcParamData%TowerHt + DstParamData%TowerBsHt = SrcParamData%TowerBsHt + DstParamData%UndSling = SrcParamData%UndSling + DstParamData%NumBl = SrcParamData%NumBl +IF (ALLOCATED(SrcParamData%AxRedTFA)) THEN + i1_l = LBOUND(SrcParamData%AxRedTFA,1) + i1_u = UBOUND(SrcParamData%AxRedTFA,1) + i2_l = LBOUND(SrcParamData%AxRedTFA,2) + i2_u = UBOUND(SrcParamData%AxRedTFA,2) + i3_l = LBOUND(SrcParamData%AxRedTFA,3) + i3_u = UBOUND(SrcParamData%AxRedTFA,3) + IF (.NOT. ALLOCATED(DstParamData%AxRedTFA)) THEN + ALLOCATE(DstParamData%AxRedTFA(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%AxRedTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AxRedTFA = SrcParamData%AxRedTFA +ENDIF +IF (ALLOCATED(SrcParamData%AxRedTSS)) THEN + i1_l = LBOUND(SrcParamData%AxRedTSS,1) + i1_u = UBOUND(SrcParamData%AxRedTSS,1) + i2_l = LBOUND(SrcParamData%AxRedTSS,2) + i2_u = UBOUND(SrcParamData%AxRedTSS,2) + i3_l = LBOUND(SrcParamData%AxRedTSS,3) + i3_u = UBOUND(SrcParamData%AxRedTSS,3) + IF (.NOT. ALLOCATED(DstParamData%AxRedTSS)) THEN + ALLOCATE(DstParamData%AxRedTSS(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%AxRedTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AxRedTSS = SrcParamData%AxRedTSS +ENDIF + DstParamData%CTFA = SrcParamData%CTFA + DstParamData%CTSS = SrcParamData%CTSS +IF (ALLOCATED(SrcParamData%DHNodes)) THEN + i1_l = LBOUND(SrcParamData%DHNodes,1) + i1_u = UBOUND(SrcParamData%DHNodes,1) + IF (.NOT. ALLOCATED(DstParamData%DHNodes)) THEN + ALLOCATE(DstParamData%DHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DHNodes = SrcParamData%DHNodes +ENDIF +IF (ALLOCATED(SrcParamData%HNodes)) THEN + i1_l = LBOUND(SrcParamData%HNodes,1) + i1_u = UBOUND(SrcParamData%HNodes,1) + IF (.NOT. ALLOCATED(DstParamData%HNodes)) THEN + ALLOCATE(DstParamData%HNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%HNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%HNodes = SrcParamData%HNodes +ENDIF +IF (ALLOCATED(SrcParamData%HNodesNorm)) THEN + i1_l = LBOUND(SrcParamData%HNodesNorm,1) + i1_u = UBOUND(SrcParamData%HNodesNorm,1) + IF (.NOT. ALLOCATED(DstParamData%HNodesNorm)) THEN + ALLOCATE(DstParamData%HNodesNorm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%HNodesNorm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%HNodesNorm = SrcParamData%HNodesNorm +ENDIF + DstParamData%KTFA = SrcParamData%KTFA + DstParamData%KTSS = SrcParamData%KTSS +IF (ALLOCATED(SrcParamData%MassT)) THEN + i1_l = LBOUND(SrcParamData%MassT,1) + i1_u = UBOUND(SrcParamData%MassT,1) + IF (.NOT. ALLOCATED(DstParamData%MassT)) THEN + ALLOCATE(DstParamData%MassT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MassT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MassT = SrcParamData%MassT +ENDIF +IF (ALLOCATED(SrcParamData%StiffTSS)) THEN + i1_l = LBOUND(SrcParamData%StiffTSS,1) + i1_u = UBOUND(SrcParamData%StiffTSS,1) + IF (.NOT. ALLOCATED(DstParamData%StiffTSS)) THEN + ALLOCATE(DstParamData%StiffTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffTSS = SrcParamData%StiffTSS +ENDIF +IF (ALLOCATED(SrcParamData%TwrFASF)) THEN + i1_l = LBOUND(SrcParamData%TwrFASF,1) + i1_u = UBOUND(SrcParamData%TwrFASF,1) + i2_l = LBOUND(SrcParamData%TwrFASF,2) + i2_u = UBOUND(SrcParamData%TwrFASF,2) + i3_l = LBOUND(SrcParamData%TwrFASF,3) + i3_u = UBOUND(SrcParamData%TwrFASF,3) + IF (.NOT. ALLOCATED(DstParamData%TwrFASF)) THEN + ALLOCATE(DstParamData%TwrFASF(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%TwrFASF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwrFASF = SrcParamData%TwrFASF +ENDIF + DstParamData%TwrFlexL = SrcParamData%TwrFlexL +IF (ALLOCATED(SrcParamData%TwrSSSF)) THEN + i1_l = LBOUND(SrcParamData%TwrSSSF,1) + i1_u = UBOUND(SrcParamData%TwrSSSF,1) + i2_l = LBOUND(SrcParamData%TwrSSSF,2) + i2_u = UBOUND(SrcParamData%TwrSSSF,2) + i3_l = LBOUND(SrcParamData%TwrSSSF,3) + i3_u = UBOUND(SrcParamData%TwrSSSF,3) + IF (.NOT. ALLOCATED(DstParamData%TwrSSSF)) THEN + ALLOCATE(DstParamData%TwrSSSF(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%TwrSSSF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwrSSSF = SrcParamData%TwrSSSF +ENDIF + DstParamData%TTopNode = SrcParamData%TTopNode + DstParamData%TwrNodes = SrcParamData%TwrNodes +IF (ALLOCATED(SrcParamData%InerTFA)) THEN + i1_l = LBOUND(SrcParamData%InerTFA,1) + i1_u = UBOUND(SrcParamData%InerTFA,1) + IF (.NOT. ALLOCATED(DstParamData%InerTFA)) THEN + ALLOCATE(DstParamData%InerTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%InerTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%InerTFA = SrcParamData%InerTFA +ENDIF +IF (ALLOCATED(SrcParamData%InerTSS)) THEN + i1_l = LBOUND(SrcParamData%InerTSS,1) + i1_u = UBOUND(SrcParamData%InerTSS,1) + IF (.NOT. ALLOCATED(DstParamData%InerTSS)) THEN + ALLOCATE(DstParamData%InerTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%InerTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%InerTSS = SrcParamData%InerTSS +ENDIF +IF (ALLOCATED(SrcParamData%StiffTGJ)) THEN + i1_l = LBOUND(SrcParamData%StiffTGJ,1) + i1_u = UBOUND(SrcParamData%StiffTGJ,1) + IF (.NOT. ALLOCATED(DstParamData%StiffTGJ)) THEN + ALLOCATE(DstParamData%StiffTGJ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffTGJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffTGJ = SrcParamData%StiffTGJ +ENDIF +IF (ALLOCATED(SrcParamData%StiffTEA)) THEN + i1_l = LBOUND(SrcParamData%StiffTEA,1) + i1_u = UBOUND(SrcParamData%StiffTEA,1) + IF (.NOT. ALLOCATED(DstParamData%StiffTEA)) THEN + ALLOCATE(DstParamData%StiffTEA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffTEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffTEA = SrcParamData%StiffTEA +ENDIF +IF (ALLOCATED(SrcParamData%StiffTFA)) THEN + i1_l = LBOUND(SrcParamData%StiffTFA,1) + i1_u = UBOUND(SrcParamData%StiffTFA,1) + IF (.NOT. ALLOCATED(DstParamData%StiffTFA)) THEN + ALLOCATE(DstParamData%StiffTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffTFA = SrcParamData%StiffTFA +ENDIF +IF (ALLOCATED(SrcParamData%cgOffTFA)) THEN + i1_l = LBOUND(SrcParamData%cgOffTFA,1) + i1_u = UBOUND(SrcParamData%cgOffTFA,1) + IF (.NOT. ALLOCATED(DstParamData%cgOffTFA)) THEN + ALLOCATE(DstParamData%cgOffTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%cgOffTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%cgOffTFA = SrcParamData%cgOffTFA +ENDIF +IF (ALLOCATED(SrcParamData%cgOffTSS)) THEN + i1_l = LBOUND(SrcParamData%cgOffTSS,1) + i1_u = UBOUND(SrcParamData%cgOffTSS,1) + IF (.NOT. ALLOCATED(DstParamData%cgOffTSS)) THEN + ALLOCATE(DstParamData%cgOffTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%cgOffTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%cgOffTSS = SrcParamData%cgOffTSS +ENDIF + DstParamData%AtfaIner = SrcParamData%AtfaIner +IF (ALLOCATED(SrcParamData%BldCG)) THEN + i1_l = LBOUND(SrcParamData%BldCG,1) + i1_u = UBOUND(SrcParamData%BldCG,1) + IF (.NOT. ALLOCATED(DstParamData%BldCG)) THEN + ALLOCATE(DstParamData%BldCG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldCG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldCG = SrcParamData%BldCG +ENDIF +IF (ALLOCATED(SrcParamData%BldMass)) THEN + i1_l = LBOUND(SrcParamData%BldMass,1) + i1_u = UBOUND(SrcParamData%BldMass,1) + IF (.NOT. ALLOCATED(DstParamData%BldMass)) THEN + ALLOCATE(DstParamData%BldMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldMass = SrcParamData%BldMass +ENDIF + DstParamData%BoomMass = SrcParamData%BoomMass +IF (ALLOCATED(SrcParamData%FirstMom)) THEN + i1_l = LBOUND(SrcParamData%FirstMom,1) + i1_u = UBOUND(SrcParamData%FirstMom,1) + IF (.NOT. ALLOCATED(DstParamData%FirstMom)) THEN + ALLOCATE(DstParamData%FirstMom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FirstMom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FirstMom = SrcParamData%FirstMom +ENDIF + DstParamData%GenIner = SrcParamData%GenIner + DstParamData%Hubg1Iner = SrcParamData%Hubg1Iner + DstParamData%Hubg2Iner = SrcParamData%Hubg2Iner + DstParamData%HubMass = SrcParamData%HubMass + DstParamData%Nacd2Iner = SrcParamData%Nacd2Iner + DstParamData%NacMass = SrcParamData%NacMass + DstParamData%PtfmMass = SrcParamData%PtfmMass + DstParamData%PtfmPIner = SrcParamData%PtfmPIner + DstParamData%PtfmRIner = SrcParamData%PtfmRIner + DstParamData%PtfmYIner = SrcParamData%PtfmYIner + DstParamData%RFrlMass = SrcParamData%RFrlMass + DstParamData%RotIner = SrcParamData%RotIner + DstParamData%RotMass = SrcParamData%RotMass + DstParamData%RrfaIner = SrcParamData%RrfaIner +IF (ALLOCATED(SrcParamData%SecondMom)) THEN + i1_l = LBOUND(SrcParamData%SecondMom,1) + i1_u = UBOUND(SrcParamData%SecondMom,1) + IF (.NOT. ALLOCATED(DstParamData%SecondMom)) THEN + ALLOCATE(DstParamData%SecondMom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%SecondMom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%SecondMom = SrcParamData%SecondMom +ENDIF + DstParamData%TFinMass = SrcParamData%TFinMass + DstParamData%TFrlIner = SrcParamData%TFrlIner +IF (ALLOCATED(SrcParamData%TipMass)) THEN + i1_l = LBOUND(SrcParamData%TipMass,1) + i1_u = UBOUND(SrcParamData%TipMass,1) + IF (.NOT. ALLOCATED(DstParamData%TipMass)) THEN + ALLOCATE(DstParamData%TipMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TipMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TipMass = SrcParamData%TipMass +ENDIF + DstParamData%TurbMass = SrcParamData%TurbMass + DstParamData%TwrMass = SrcParamData%TwrMass + DstParamData%TwrTpMass = SrcParamData%TwrTpMass + DstParamData%YawBrMass = SrcParamData%YawBrMass + DstParamData%Gravity = SrcParamData%Gravity +IF (ALLOCATED(SrcParamData%PitchAxis)) THEN + i1_l = LBOUND(SrcParamData%PitchAxis,1) + i1_u = UBOUND(SrcParamData%PitchAxis,1) + i2_l = LBOUND(SrcParamData%PitchAxis,2) + i2_u = UBOUND(SrcParamData%PitchAxis,2) + IF (.NOT. ALLOCATED(DstParamData%PitchAxis)) THEN + ALLOCATE(DstParamData%PitchAxis(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PitchAxis.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PitchAxis = SrcParamData%PitchAxis +ENDIF +IF (ALLOCATED(SrcParamData%AeroTwst)) THEN + i1_l = LBOUND(SrcParamData%AeroTwst,1) + i1_u = UBOUND(SrcParamData%AeroTwst,1) + IF (.NOT. ALLOCATED(DstParamData%AeroTwst)) THEN + ALLOCATE(DstParamData%AeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AeroTwst = SrcParamData%AeroTwst +ENDIF +IF (ALLOCATED(SrcParamData%AxRedBld)) THEN + i1_l = LBOUND(SrcParamData%AxRedBld,1) + i1_u = UBOUND(SrcParamData%AxRedBld,1) + i2_l = LBOUND(SrcParamData%AxRedBld,2) + i2_u = UBOUND(SrcParamData%AxRedBld,2) + i3_l = LBOUND(SrcParamData%AxRedBld,3) + i3_u = UBOUND(SrcParamData%AxRedBld,3) + i4_l = LBOUND(SrcParamData%AxRedBld,4) + i4_u = UBOUND(SrcParamData%AxRedBld,4) + IF (.NOT. ALLOCATED(DstParamData%AxRedBld)) THEN + ALLOCATE(DstParamData%AxRedBld(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%AxRedBld.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AxRedBld = SrcParamData%AxRedBld +ENDIF +IF (ALLOCATED(SrcParamData%BAlpha)) THEN + i1_l = LBOUND(SrcParamData%BAlpha,1) + i1_u = UBOUND(SrcParamData%BAlpha,1) + i2_l = LBOUND(SrcParamData%BAlpha,2) + i2_u = UBOUND(SrcParamData%BAlpha,2) + IF (.NOT. ALLOCATED(DstParamData%BAlpha)) THEN + ALLOCATE(DstParamData%BAlpha(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BAlpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BAlpha = SrcParamData%BAlpha +ENDIF +IF (ALLOCATED(SrcParamData%BldEDamp)) THEN + i1_l = LBOUND(SrcParamData%BldEDamp,1) + i1_u = UBOUND(SrcParamData%BldEDamp,1) + i2_l = LBOUND(SrcParamData%BldEDamp,2) + i2_u = UBOUND(SrcParamData%BldEDamp,2) + IF (.NOT. ALLOCATED(DstParamData%BldEDamp)) THEN + ALLOCATE(DstParamData%BldEDamp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldEDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldEDamp = SrcParamData%BldEDamp +ENDIF +IF (ALLOCATED(SrcParamData%BldFDamp)) THEN + i1_l = LBOUND(SrcParamData%BldFDamp,1) + i1_u = UBOUND(SrcParamData%BldFDamp,1) + i2_l = LBOUND(SrcParamData%BldFDamp,2) + i2_u = UBOUND(SrcParamData%BldFDamp,2) + IF (.NOT. ALLOCATED(DstParamData%BldFDamp)) THEN + ALLOCATE(DstParamData%BldFDamp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldFDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldFDamp = SrcParamData%BldFDamp +ENDIF + DstParamData%BldFlexL = SrcParamData%BldFlexL +IF (ALLOCATED(SrcParamData%CAeroTwst)) THEN + i1_l = LBOUND(SrcParamData%CAeroTwst,1) + i1_u = UBOUND(SrcParamData%CAeroTwst,1) + IF (.NOT. ALLOCATED(DstParamData%CAeroTwst)) THEN + ALLOCATE(DstParamData%CAeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CAeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CAeroTwst = SrcParamData%CAeroTwst +ENDIF +IF (ALLOCATED(SrcParamData%CBE)) THEN + i1_l = LBOUND(SrcParamData%CBE,1) + i1_u = UBOUND(SrcParamData%CBE,1) + i2_l = LBOUND(SrcParamData%CBE,2) + i2_u = UBOUND(SrcParamData%CBE,2) + i3_l = LBOUND(SrcParamData%CBE,3) + i3_u = UBOUND(SrcParamData%CBE,3) + IF (.NOT. ALLOCATED(DstParamData%CBE)) THEN + ALLOCATE(DstParamData%CBE(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%CBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CBE = SrcParamData%CBE +ENDIF +IF (ALLOCATED(SrcParamData%CBF)) THEN + i1_l = LBOUND(SrcParamData%CBF,1) + i1_u = UBOUND(SrcParamData%CBF,1) + i2_l = LBOUND(SrcParamData%CBF,2) + i2_u = UBOUND(SrcParamData%CBF,2) + i3_l = LBOUND(SrcParamData%CBF,3) + i3_u = UBOUND(SrcParamData%CBF,3) + IF (.NOT. ALLOCATED(DstParamData%CBF)) THEN + ALLOCATE(DstParamData%CBF(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%CBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CBF = SrcParamData%CBF +ENDIF +IF (ALLOCATED(SrcParamData%cgOffBEdg)) THEN + i1_l = LBOUND(SrcParamData%cgOffBEdg,1) + i1_u = UBOUND(SrcParamData%cgOffBEdg,1) + i2_l = LBOUND(SrcParamData%cgOffBEdg,2) + i2_u = UBOUND(SrcParamData%cgOffBEdg,2) + IF (.NOT. ALLOCATED(DstParamData%cgOffBEdg)) THEN + ALLOCATE(DstParamData%cgOffBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%cgOffBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%cgOffBEdg = SrcParamData%cgOffBEdg +ENDIF +IF (ALLOCATED(SrcParamData%cgOffBFlp)) THEN + i1_l = LBOUND(SrcParamData%cgOffBFlp,1) + i1_u = UBOUND(SrcParamData%cgOffBFlp,1) + i2_l = LBOUND(SrcParamData%cgOffBFlp,2) + i2_u = UBOUND(SrcParamData%cgOffBFlp,2) + IF (.NOT. ALLOCATED(DstParamData%cgOffBFlp)) THEN + ALLOCATE(DstParamData%cgOffBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%cgOffBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%cgOffBFlp = SrcParamData%cgOffBFlp +ENDIF +IF (ALLOCATED(SrcParamData%Chord)) THEN + i1_l = LBOUND(SrcParamData%Chord,1) + i1_u = UBOUND(SrcParamData%Chord,1) + IF (.NOT. ALLOCATED(DstParamData%Chord)) THEN + ALLOCATE(DstParamData%Chord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Chord = SrcParamData%Chord +ENDIF +IF (ALLOCATED(SrcParamData%CThetaS)) THEN + i1_l = LBOUND(SrcParamData%CThetaS,1) + i1_u = UBOUND(SrcParamData%CThetaS,1) + i2_l = LBOUND(SrcParamData%CThetaS,2) + i2_u = UBOUND(SrcParamData%CThetaS,2) + IF (.NOT. ALLOCATED(DstParamData%CThetaS)) THEN + ALLOCATE(DstParamData%CThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CThetaS = SrcParamData%CThetaS +ENDIF +IF (ALLOCATED(SrcParamData%DRNodes)) THEN + i1_l = LBOUND(SrcParamData%DRNodes,1) + i1_u = UBOUND(SrcParamData%DRNodes,1) + IF (.NOT. ALLOCATED(DstParamData%DRNodes)) THEN + ALLOCATE(DstParamData%DRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DRNodes = SrcParamData%DRNodes +ENDIF +IF (ALLOCATED(SrcParamData%EAOffBEdg)) THEN + i1_l = LBOUND(SrcParamData%EAOffBEdg,1) + i1_u = UBOUND(SrcParamData%EAOffBEdg,1) + i2_l = LBOUND(SrcParamData%EAOffBEdg,2) + i2_u = UBOUND(SrcParamData%EAOffBEdg,2) + IF (.NOT. ALLOCATED(DstParamData%EAOffBEdg)) THEN + ALLOCATE(DstParamData%EAOffBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%EAOffBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%EAOffBEdg = SrcParamData%EAOffBEdg +ENDIF +IF (ALLOCATED(SrcParamData%EAOffBFlp)) THEN + i1_l = LBOUND(SrcParamData%EAOffBFlp,1) + i1_u = UBOUND(SrcParamData%EAOffBFlp,1) + i2_l = LBOUND(SrcParamData%EAOffBFlp,2) + i2_u = UBOUND(SrcParamData%EAOffBFlp,2) + IF (.NOT. ALLOCATED(DstParamData%EAOffBFlp)) THEN + ALLOCATE(DstParamData%EAOffBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%EAOffBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%EAOffBFlp = SrcParamData%EAOffBFlp +ENDIF +IF (ALLOCATED(SrcParamData%FStTunr)) THEN + i1_l = LBOUND(SrcParamData%FStTunr,1) + i1_u = UBOUND(SrcParamData%FStTunr,1) + i2_l = LBOUND(SrcParamData%FStTunr,2) + i2_u = UBOUND(SrcParamData%FStTunr,2) + IF (.NOT. ALLOCATED(DstParamData%FStTunr)) THEN + ALLOCATE(DstParamData%FStTunr(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FStTunr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FStTunr = SrcParamData%FStTunr +ENDIF +IF (ALLOCATED(SrcParamData%InerBEdg)) THEN + i1_l = LBOUND(SrcParamData%InerBEdg,1) + i1_u = UBOUND(SrcParamData%InerBEdg,1) + i2_l = LBOUND(SrcParamData%InerBEdg,2) + i2_u = UBOUND(SrcParamData%InerBEdg,2) + IF (.NOT. ALLOCATED(DstParamData%InerBEdg)) THEN + ALLOCATE(DstParamData%InerBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%InerBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%InerBEdg = SrcParamData%InerBEdg +ENDIF +IF (ALLOCATED(SrcParamData%InerBFlp)) THEN + i1_l = LBOUND(SrcParamData%InerBFlp,1) + i1_u = UBOUND(SrcParamData%InerBFlp,1) + i2_l = LBOUND(SrcParamData%InerBFlp,2) + i2_u = UBOUND(SrcParamData%InerBFlp,2) + IF (.NOT. ALLOCATED(DstParamData%InerBFlp)) THEN + ALLOCATE(DstParamData%InerBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%InerBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%InerBFlp = SrcParamData%InerBFlp +ENDIF +IF (ALLOCATED(SrcParamData%KBE)) THEN + i1_l = LBOUND(SrcParamData%KBE,1) + i1_u = UBOUND(SrcParamData%KBE,1) + i2_l = LBOUND(SrcParamData%KBE,2) + i2_u = UBOUND(SrcParamData%KBE,2) + i3_l = LBOUND(SrcParamData%KBE,3) + i3_u = UBOUND(SrcParamData%KBE,3) + IF (.NOT. ALLOCATED(DstParamData%KBE)) THEN + ALLOCATE(DstParamData%KBE(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%KBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KBE = SrcParamData%KBE +ENDIF +IF (ALLOCATED(SrcParamData%KBF)) THEN + i1_l = LBOUND(SrcParamData%KBF,1) + i1_u = UBOUND(SrcParamData%KBF,1) + i2_l = LBOUND(SrcParamData%KBF,2) + i2_u = UBOUND(SrcParamData%KBF,2) + i3_l = LBOUND(SrcParamData%KBF,3) + i3_u = UBOUND(SrcParamData%KBF,3) + IF (.NOT. ALLOCATED(DstParamData%KBF)) THEN + ALLOCATE(DstParamData%KBF(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%KBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KBF = SrcParamData%KBF +ENDIF +IF (ALLOCATED(SrcParamData%MassB)) THEN + i1_l = LBOUND(SrcParamData%MassB,1) + i1_u = UBOUND(SrcParamData%MassB,1) + i2_l = LBOUND(SrcParamData%MassB,2) + i2_u = UBOUND(SrcParamData%MassB,2) + IF (.NOT. ALLOCATED(DstParamData%MassB)) THEN + ALLOCATE(DstParamData%MassB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MassB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MassB = SrcParamData%MassB +ENDIF +IF (ALLOCATED(SrcParamData%RefAxisxb)) THEN + i1_l = LBOUND(SrcParamData%RefAxisxb,1) + i1_u = UBOUND(SrcParamData%RefAxisxb,1) + i2_l = LBOUND(SrcParamData%RefAxisxb,2) + i2_u = UBOUND(SrcParamData%RefAxisxb,2) + IF (.NOT. ALLOCATED(DstParamData%RefAxisxb)) THEN + ALLOCATE(DstParamData%RefAxisxb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%RefAxisxb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%RefAxisxb = SrcParamData%RefAxisxb +ENDIF +IF (ALLOCATED(SrcParamData%RefAxisyb)) THEN + i1_l = LBOUND(SrcParamData%RefAxisyb,1) + i1_u = UBOUND(SrcParamData%RefAxisyb,1) + i2_l = LBOUND(SrcParamData%RefAxisyb,2) + i2_u = UBOUND(SrcParamData%RefAxisyb,2) + IF (.NOT. ALLOCATED(DstParamData%RefAxisyb)) THEN + ALLOCATE(DstParamData%RefAxisyb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%RefAxisyb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%RefAxisyb = SrcParamData%RefAxisyb +ENDIF +IF (ALLOCATED(SrcParamData%RNodes)) THEN + i1_l = LBOUND(SrcParamData%RNodes,1) + i1_u = UBOUND(SrcParamData%RNodes,1) + IF (.NOT. ALLOCATED(DstParamData%RNodes)) THEN + ALLOCATE(DstParamData%RNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%RNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%RNodes = SrcParamData%RNodes +ENDIF +IF (ALLOCATED(SrcParamData%RNodesNorm)) THEN + i1_l = LBOUND(SrcParamData%RNodesNorm,1) + i1_u = UBOUND(SrcParamData%RNodesNorm,1) + IF (.NOT. ALLOCATED(DstParamData%RNodesNorm)) THEN + ALLOCATE(DstParamData%RNodesNorm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%RNodesNorm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%RNodesNorm = SrcParamData%RNodesNorm +ENDIF +IF (ALLOCATED(SrcParamData%rSAerCenn1)) THEN + i1_l = LBOUND(SrcParamData%rSAerCenn1,1) + i1_u = UBOUND(SrcParamData%rSAerCenn1,1) + i2_l = LBOUND(SrcParamData%rSAerCenn1,2) + i2_u = UBOUND(SrcParamData%rSAerCenn1,2) + IF (.NOT. ALLOCATED(DstParamData%rSAerCenn1)) THEN + ALLOCATE(DstParamData%rSAerCenn1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rSAerCenn1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rSAerCenn1 = SrcParamData%rSAerCenn1 +ENDIF +IF (ALLOCATED(SrcParamData%rSAerCenn2)) THEN + i1_l = LBOUND(SrcParamData%rSAerCenn2,1) + i1_u = UBOUND(SrcParamData%rSAerCenn2,1) + i2_l = LBOUND(SrcParamData%rSAerCenn2,2) + i2_u = UBOUND(SrcParamData%rSAerCenn2,2) + IF (.NOT. ALLOCATED(DstParamData%rSAerCenn2)) THEN + ALLOCATE(DstParamData%rSAerCenn2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rSAerCenn2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rSAerCenn2 = SrcParamData%rSAerCenn2 +ENDIF +IF (ALLOCATED(SrcParamData%SAeroTwst)) THEN + i1_l = LBOUND(SrcParamData%SAeroTwst,1) + i1_u = UBOUND(SrcParamData%SAeroTwst,1) + IF (.NOT. ALLOCATED(DstParamData%SAeroTwst)) THEN + ALLOCATE(DstParamData%SAeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%SAeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%SAeroTwst = SrcParamData%SAeroTwst +ENDIF +IF (ALLOCATED(SrcParamData%StiffBE)) THEN + i1_l = LBOUND(SrcParamData%StiffBE,1) + i1_u = UBOUND(SrcParamData%StiffBE,1) + i2_l = LBOUND(SrcParamData%StiffBE,2) + i2_u = UBOUND(SrcParamData%StiffBE,2) + IF (.NOT. ALLOCATED(DstParamData%StiffBE)) THEN + ALLOCATE(DstParamData%StiffBE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffBE = SrcParamData%StiffBE +ENDIF +IF (ALLOCATED(SrcParamData%StiffBEA)) THEN + i1_l = LBOUND(SrcParamData%StiffBEA,1) + i1_u = UBOUND(SrcParamData%StiffBEA,1) + i2_l = LBOUND(SrcParamData%StiffBEA,2) + i2_u = UBOUND(SrcParamData%StiffBEA,2) + IF (.NOT. ALLOCATED(DstParamData%StiffBEA)) THEN + ALLOCATE(DstParamData%StiffBEA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffBEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffBEA = SrcParamData%StiffBEA +ENDIF +IF (ALLOCATED(SrcParamData%StiffBF)) THEN + i1_l = LBOUND(SrcParamData%StiffBF,1) + i1_u = UBOUND(SrcParamData%StiffBF,1) + i2_l = LBOUND(SrcParamData%StiffBF,2) + i2_u = UBOUND(SrcParamData%StiffBF,2) + IF (.NOT. ALLOCATED(DstParamData%StiffBF)) THEN + ALLOCATE(DstParamData%StiffBF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffBF = SrcParamData%StiffBF +ENDIF +IF (ALLOCATED(SrcParamData%StiffBGJ)) THEN + i1_l = LBOUND(SrcParamData%StiffBGJ,1) + i1_u = UBOUND(SrcParamData%StiffBGJ,1) + i2_l = LBOUND(SrcParamData%StiffBGJ,2) + i2_u = UBOUND(SrcParamData%StiffBGJ,2) + IF (.NOT. ALLOCATED(DstParamData%StiffBGJ)) THEN + ALLOCATE(DstParamData%StiffBGJ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%StiffBGJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%StiffBGJ = SrcParamData%StiffBGJ +ENDIF +IF (ALLOCATED(SrcParamData%SThetaS)) THEN + i1_l = LBOUND(SrcParamData%SThetaS,1) + i1_u = UBOUND(SrcParamData%SThetaS,1) + i2_l = LBOUND(SrcParamData%SThetaS,2) + i2_u = UBOUND(SrcParamData%SThetaS,2) + IF (.NOT. ALLOCATED(DstParamData%SThetaS)) THEN + ALLOCATE(DstParamData%SThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%SThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%SThetaS = SrcParamData%SThetaS +ENDIF +IF (ALLOCATED(SrcParamData%ThetaS)) THEN + i1_l = LBOUND(SrcParamData%ThetaS,1) + i1_u = UBOUND(SrcParamData%ThetaS,1) + i2_l = LBOUND(SrcParamData%ThetaS,2) + i2_u = UBOUND(SrcParamData%ThetaS,2) + IF (.NOT. ALLOCATED(DstParamData%ThetaS)) THEN + ALLOCATE(DstParamData%ThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ThetaS = SrcParamData%ThetaS +ENDIF +IF (ALLOCATED(SrcParamData%TwistedSF)) THEN + i1_l = LBOUND(SrcParamData%TwistedSF,1) + i1_u = UBOUND(SrcParamData%TwistedSF,1) + i2_l = LBOUND(SrcParamData%TwistedSF,2) + i2_u = UBOUND(SrcParamData%TwistedSF,2) + i3_l = LBOUND(SrcParamData%TwistedSF,3) + i3_u = UBOUND(SrcParamData%TwistedSF,3) + i4_l = LBOUND(SrcParamData%TwistedSF,4) + i4_u = UBOUND(SrcParamData%TwistedSF,4) + i5_l = LBOUND(SrcParamData%TwistedSF,5) + i5_u = UBOUND(SrcParamData%TwistedSF,5) + IF (.NOT. ALLOCATED(DstParamData%TwistedSF)) THEN + ALLOCATE(DstParamData%TwistedSF(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 DstParamData%TwistedSF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TwistedSF = SrcParamData%TwistedSF +ENDIF +IF (ALLOCATED(SrcParamData%BldFl1Sh)) THEN + i1_l = LBOUND(SrcParamData%BldFl1Sh,1) + i1_u = UBOUND(SrcParamData%BldFl1Sh,1) + i2_l = LBOUND(SrcParamData%BldFl1Sh,2) + i2_u = UBOUND(SrcParamData%BldFl1Sh,2) + IF (.NOT. ALLOCATED(DstParamData%BldFl1Sh)) THEN + ALLOCATE(DstParamData%BldFl1Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldFl1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldFl1Sh = SrcParamData%BldFl1Sh +ENDIF +IF (ALLOCATED(SrcParamData%BldFl2Sh)) THEN + i1_l = LBOUND(SrcParamData%BldFl2Sh,1) + i1_u = UBOUND(SrcParamData%BldFl2Sh,1) + i2_l = LBOUND(SrcParamData%BldFl2Sh,2) + i2_u = UBOUND(SrcParamData%BldFl2Sh,2) + IF (.NOT. ALLOCATED(DstParamData%BldFl2Sh)) THEN + ALLOCATE(DstParamData%BldFl2Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldFl2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldFl2Sh = SrcParamData%BldFl2Sh +ENDIF +IF (ALLOCATED(SrcParamData%BldEdgSh)) THEN + i1_l = LBOUND(SrcParamData%BldEdgSh,1) + i1_u = UBOUND(SrcParamData%BldEdgSh,1) + i2_l = LBOUND(SrcParamData%BldEdgSh,2) + i2_u = UBOUND(SrcParamData%BldEdgSh,2) + IF (.NOT. ALLOCATED(DstParamData%BldEdgSh)) THEN + ALLOCATE(DstParamData%BldEdgSh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldEdgSh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BldEdgSh = SrcParamData%BldEdgSh +ENDIF +IF (ALLOCATED(SrcParamData%FreqBE)) THEN + i1_l = LBOUND(SrcParamData%FreqBE,1) + i1_u = UBOUND(SrcParamData%FreqBE,1) + i2_l = LBOUND(SrcParamData%FreqBE,2) + i2_u = UBOUND(SrcParamData%FreqBE,2) + i3_l = LBOUND(SrcParamData%FreqBE,3) + i3_u = UBOUND(SrcParamData%FreqBE,3) + IF (.NOT. ALLOCATED(DstParamData%FreqBE)) THEN + ALLOCATE(DstParamData%FreqBE(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%FreqBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FreqBE = SrcParamData%FreqBE +ENDIF +IF (ALLOCATED(SrcParamData%FreqBF)) THEN + i1_l = LBOUND(SrcParamData%FreqBF,1) + i1_u = UBOUND(SrcParamData%FreqBF,1) + i2_l = LBOUND(SrcParamData%FreqBF,2) + i2_u = UBOUND(SrcParamData%FreqBF,2) + i3_l = LBOUND(SrcParamData%FreqBF,3) + i3_u = UBOUND(SrcParamData%FreqBF,3) + IF (.NOT. ALLOCATED(DstParamData%FreqBF)) THEN + ALLOCATE(DstParamData%FreqBF(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%FreqBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FreqBF = SrcParamData%FreqBF +ENDIF + DstParamData%FreqTFA = SrcParamData%FreqTFA + DstParamData%FreqTSS = SrcParamData%FreqTSS + DstParamData%TeetCDmp = SrcParamData%TeetCDmp + DstParamData%TeetDmp = SrcParamData%TeetDmp + DstParamData%TeetDmpP = SrcParamData%TeetDmpP + DstParamData%TeetHSSp = SrcParamData%TeetHSSp + DstParamData%TeetHStP = SrcParamData%TeetHStP + DstParamData%TeetSSSp = SrcParamData%TeetSSSp + DstParamData%TeetSStP = SrcParamData%TeetSStP + DstParamData%TeetMod = SrcParamData%TeetMod + DstParamData%TFrlCDmp = SrcParamData%TFrlCDmp + DstParamData%TFrlDmp = SrcParamData%TFrlDmp + DstParamData%TFrlDSDmp = SrcParamData%TFrlDSDmp + DstParamData%TFrlDSDP = SrcParamData%TFrlDSDP + DstParamData%TFrlDSSP = SrcParamData%TFrlDSSP + DstParamData%TFrlDSSpr = SrcParamData%TFrlDSSpr + DstParamData%TFrlSpr = SrcParamData%TFrlSpr + DstParamData%TFrlUSDmp = SrcParamData%TFrlUSDmp + DstParamData%TFrlUSDP = SrcParamData%TFrlUSDP + DstParamData%TFrlUSSP = SrcParamData%TFrlUSSP + DstParamData%TFrlUSSpr = SrcParamData%TFrlUSSpr + DstParamData%TFrlMod = SrcParamData%TFrlMod + DstParamData%RFrlCDmp = SrcParamData%RFrlCDmp + DstParamData%RFrlDmp = SrcParamData%RFrlDmp + DstParamData%RFrlDSDmp = SrcParamData%RFrlDSDmp + DstParamData%RFrlDSDP = SrcParamData%RFrlDSDP + DstParamData%RFrlDSSP = SrcParamData%RFrlDSSP + DstParamData%RFrlDSSpr = SrcParamData%RFrlDSSpr + DstParamData%RFrlSpr = SrcParamData%RFrlSpr + DstParamData%RFrlUSDmp = SrcParamData%RFrlUSDmp + DstParamData%RFrlUSDP = SrcParamData%RFrlUSDP + DstParamData%RFrlUSSP = SrcParamData%RFrlUSSP + DstParamData%RFrlUSSpr = SrcParamData%RFrlUSSpr + DstParamData%RFrlMod = SrcParamData%RFrlMod + DstParamData%ShftGagL = SrcParamData%ShftGagL + DstParamData%BldGagNd = SrcParamData%BldGagNd + DstParamData%TwrGagNd = SrcParamData%TwrGagNd + DstParamData%TStart = SrcParamData%TStart + DstParamData%DTTorDmp = SrcParamData%DTTorDmp + DstParamData%DTTorSpr = SrcParamData%DTTorSpr + DstParamData%GBRatio = SrcParamData%GBRatio + DstParamData%GBoxEff = SrcParamData%GBoxEff + DstParamData%RotSpeed = SrcParamData%RotSpeed + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%BElmntMass)) THEN + i1_l = LBOUND(SrcParamData%BElmntMass,1) + i1_u = UBOUND(SrcParamData%BElmntMass,1) + i2_l = LBOUND(SrcParamData%BElmntMass,2) + i2_u = UBOUND(SrcParamData%BElmntMass,2) + IF (.NOT. ALLOCATED(DstParamData%BElmntMass)) THEN + ALLOCATE(DstParamData%BElmntMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BElmntMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BElmntMass = SrcParamData%BElmntMass +ENDIF +IF (ALLOCATED(SrcParamData%TElmntMass)) THEN + i1_l = LBOUND(SrcParamData%TElmntMass,1) + i1_u = UBOUND(SrcParamData%TElmntMass,1) + IF (.NOT. ALLOCATED(DstParamData%TElmntMass)) THEN + ALLOCATE(DstParamData%TElmntMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TElmntMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TElmntMass = SrcParamData%TElmntMass +ENDIF + DstParamData%method = SrcParamData%method + DstParamData%PtfmCMxt = SrcParamData%PtfmCMxt + DstParamData%PtfmCMyt = SrcParamData%PtfmCMyt + DstParamData%BD4Blades = SrcParamData%BD4Blades + DstParamData%UseAD14 = SrcParamData%UseAD14 + DstParamData%BldNd_NumOuts = SrcParamData%BldNd_NumOuts + DstParamData%BldNd_TotNumOuts = SrcParamData%BldNd_TotNumOuts +IF (ALLOCATED(SrcParamData%BldNd_OutParam)) THEN + i1_l = LBOUND(SrcParamData%BldNd_OutParam,1) + i1_u = UBOUND(SrcParamData%BldNd_OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%BldNd_OutParam)) THEN + ALLOCATE(DstParamData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%BldNd_OutParam,1), UBOUND(SrcParamData%BldNd_OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%BldNd_OutParam(i1), DstParamData%BldNd_OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%BldNd_BladesOut = SrcParamData%BldNd_BladesOut +IF (ALLOCATED(SrcParamData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcParamData%Jac_u_indx,1) + i1_u = UBOUND(SrcParamData%Jac_u_indx,1) + i2_l = LBOUND(SrcParamData%Jac_u_indx,2) + i2_u = UBOUND(SrcParamData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstParamData%Jac_u_indx)) THEN + ALLOCATE(DstParamData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jac_u_indx = SrcParamData%Jac_u_indx +ENDIF +IF (ALLOCATED(SrcParamData%du)) THEN + i1_l = LBOUND(SrcParamData%du,1) + i1_u = UBOUND(SrcParamData%du,1) + IF (.NOT. ALLOCATED(DstParamData%du)) THEN + ALLOCATE(DstParamData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%du = SrcParamData%du +ENDIF +IF (ALLOCATED(SrcParamData%dx)) THEN + i1_l = LBOUND(SrcParamData%dx,1) + i1_u = UBOUND(SrcParamData%dx,1) + IF (.NOT. ALLOCATED(DstParamData%dx)) THEN + ALLOCATE(DstParamData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%dx = SrcParamData%dx +ENDIF + DstParamData%Jac_ny = SrcParamData%Jac_ny + END SUBROUTINE ED_CopyParam + + SUBROUTINE ED_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(ED_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%PH)) THEN + DEALLOCATE(ParamData%PH) +ENDIF +IF (ALLOCATED(ParamData%PM)) THEN + DEALLOCATE(ParamData%PM) +ENDIF +IF (ALLOCATED(ParamData%DOF_Flag)) THEN + DEALLOCATE(ParamData%DOF_Flag) +ENDIF +IF (ALLOCATED(ParamData%DOF_Desc)) THEN + DEALLOCATE(ParamData%DOF_Desc) +ENDIF + CALL ED_Destroyactivedofs( ParamData%DOFs, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%CosPreC)) THEN + DEALLOCATE(ParamData%CosPreC) +ENDIF +IF (ALLOCATED(ParamData%SinPreC)) THEN + DEALLOCATE(ParamData%SinPreC) +ENDIF +IF (ALLOCATED(ParamData%AxRedTFA)) THEN + DEALLOCATE(ParamData%AxRedTFA) +ENDIF +IF (ALLOCATED(ParamData%AxRedTSS)) THEN + DEALLOCATE(ParamData%AxRedTSS) +ENDIF +IF (ALLOCATED(ParamData%DHNodes)) THEN + DEALLOCATE(ParamData%DHNodes) +ENDIF +IF (ALLOCATED(ParamData%HNodes)) THEN + DEALLOCATE(ParamData%HNodes) +ENDIF +IF (ALLOCATED(ParamData%HNodesNorm)) THEN + DEALLOCATE(ParamData%HNodesNorm) +ENDIF +IF (ALLOCATED(ParamData%MassT)) THEN + DEALLOCATE(ParamData%MassT) +ENDIF +IF (ALLOCATED(ParamData%StiffTSS)) THEN + DEALLOCATE(ParamData%StiffTSS) +ENDIF +IF (ALLOCATED(ParamData%TwrFASF)) THEN + DEALLOCATE(ParamData%TwrFASF) +ENDIF +IF (ALLOCATED(ParamData%TwrSSSF)) THEN + DEALLOCATE(ParamData%TwrSSSF) +ENDIF +IF (ALLOCATED(ParamData%InerTFA)) THEN + DEALLOCATE(ParamData%InerTFA) +ENDIF +IF (ALLOCATED(ParamData%InerTSS)) THEN + DEALLOCATE(ParamData%InerTSS) +ENDIF +IF (ALLOCATED(ParamData%StiffTGJ)) THEN + DEALLOCATE(ParamData%StiffTGJ) +ENDIF +IF (ALLOCATED(ParamData%StiffTEA)) THEN + DEALLOCATE(ParamData%StiffTEA) +ENDIF +IF (ALLOCATED(ParamData%StiffTFA)) THEN + DEALLOCATE(ParamData%StiffTFA) +ENDIF +IF (ALLOCATED(ParamData%cgOffTFA)) THEN + DEALLOCATE(ParamData%cgOffTFA) +ENDIF +IF (ALLOCATED(ParamData%cgOffTSS)) THEN + DEALLOCATE(ParamData%cgOffTSS) +ENDIF +IF (ALLOCATED(ParamData%BldCG)) THEN + DEALLOCATE(ParamData%BldCG) +ENDIF +IF (ALLOCATED(ParamData%BldMass)) THEN + DEALLOCATE(ParamData%BldMass) +ENDIF +IF (ALLOCATED(ParamData%FirstMom)) THEN + DEALLOCATE(ParamData%FirstMom) +ENDIF +IF (ALLOCATED(ParamData%SecondMom)) THEN + DEALLOCATE(ParamData%SecondMom) +ENDIF +IF (ALLOCATED(ParamData%TipMass)) THEN + DEALLOCATE(ParamData%TipMass) +ENDIF +IF (ALLOCATED(ParamData%PitchAxis)) THEN + DEALLOCATE(ParamData%PitchAxis) +ENDIF +IF (ALLOCATED(ParamData%AeroTwst)) THEN + DEALLOCATE(ParamData%AeroTwst) +ENDIF +IF (ALLOCATED(ParamData%AxRedBld)) THEN + DEALLOCATE(ParamData%AxRedBld) +ENDIF +IF (ALLOCATED(ParamData%BAlpha)) THEN + DEALLOCATE(ParamData%BAlpha) +ENDIF +IF (ALLOCATED(ParamData%BldEDamp)) THEN + DEALLOCATE(ParamData%BldEDamp) +ENDIF +IF (ALLOCATED(ParamData%BldFDamp)) THEN + DEALLOCATE(ParamData%BldFDamp) +ENDIF +IF (ALLOCATED(ParamData%CAeroTwst)) THEN + DEALLOCATE(ParamData%CAeroTwst) +ENDIF +IF (ALLOCATED(ParamData%CBE)) THEN + DEALLOCATE(ParamData%CBE) +ENDIF +IF (ALLOCATED(ParamData%CBF)) THEN + DEALLOCATE(ParamData%CBF) +ENDIF +IF (ALLOCATED(ParamData%cgOffBEdg)) THEN + DEALLOCATE(ParamData%cgOffBEdg) +ENDIF +IF (ALLOCATED(ParamData%cgOffBFlp)) THEN + DEALLOCATE(ParamData%cgOffBFlp) +ENDIF +IF (ALLOCATED(ParamData%Chord)) THEN + DEALLOCATE(ParamData%Chord) +ENDIF +IF (ALLOCATED(ParamData%CThetaS)) THEN + DEALLOCATE(ParamData%CThetaS) +ENDIF +IF (ALLOCATED(ParamData%DRNodes)) THEN + DEALLOCATE(ParamData%DRNodes) +ENDIF +IF (ALLOCATED(ParamData%EAOffBEdg)) THEN + DEALLOCATE(ParamData%EAOffBEdg) +ENDIF +IF (ALLOCATED(ParamData%EAOffBFlp)) THEN + DEALLOCATE(ParamData%EAOffBFlp) +ENDIF +IF (ALLOCATED(ParamData%FStTunr)) THEN + DEALLOCATE(ParamData%FStTunr) +ENDIF +IF (ALLOCATED(ParamData%InerBEdg)) THEN + DEALLOCATE(ParamData%InerBEdg) +ENDIF +IF (ALLOCATED(ParamData%InerBFlp)) THEN + DEALLOCATE(ParamData%InerBFlp) +ENDIF +IF (ALLOCATED(ParamData%KBE)) THEN + DEALLOCATE(ParamData%KBE) +ENDIF +IF (ALLOCATED(ParamData%KBF)) THEN + DEALLOCATE(ParamData%KBF) +ENDIF +IF (ALLOCATED(ParamData%MassB)) THEN + DEALLOCATE(ParamData%MassB) +ENDIF +IF (ALLOCATED(ParamData%RefAxisxb)) THEN + DEALLOCATE(ParamData%RefAxisxb) +ENDIF +IF (ALLOCATED(ParamData%RefAxisyb)) THEN + DEALLOCATE(ParamData%RefAxisyb) +ENDIF +IF (ALLOCATED(ParamData%RNodes)) THEN + DEALLOCATE(ParamData%RNodes) +ENDIF +IF (ALLOCATED(ParamData%RNodesNorm)) THEN + DEALLOCATE(ParamData%RNodesNorm) +ENDIF +IF (ALLOCATED(ParamData%rSAerCenn1)) THEN + DEALLOCATE(ParamData%rSAerCenn1) +ENDIF +IF (ALLOCATED(ParamData%rSAerCenn2)) THEN + DEALLOCATE(ParamData%rSAerCenn2) +ENDIF +IF (ALLOCATED(ParamData%SAeroTwst)) THEN + DEALLOCATE(ParamData%SAeroTwst) +ENDIF +IF (ALLOCATED(ParamData%StiffBE)) THEN + DEALLOCATE(ParamData%StiffBE) +ENDIF +IF (ALLOCATED(ParamData%StiffBEA)) THEN + DEALLOCATE(ParamData%StiffBEA) +ENDIF +IF (ALLOCATED(ParamData%StiffBF)) THEN + DEALLOCATE(ParamData%StiffBF) +ENDIF +IF (ALLOCATED(ParamData%StiffBGJ)) THEN + DEALLOCATE(ParamData%StiffBGJ) +ENDIF +IF (ALLOCATED(ParamData%SThetaS)) THEN + DEALLOCATE(ParamData%SThetaS) +ENDIF +IF (ALLOCATED(ParamData%ThetaS)) THEN + DEALLOCATE(ParamData%ThetaS) +ENDIF +IF (ALLOCATED(ParamData%TwistedSF)) THEN + DEALLOCATE(ParamData%TwistedSF) +ENDIF +IF (ALLOCATED(ParamData%BldFl1Sh)) THEN + DEALLOCATE(ParamData%BldFl1Sh) +ENDIF +IF (ALLOCATED(ParamData%BldFl2Sh)) THEN + DEALLOCATE(ParamData%BldFl2Sh) +ENDIF +IF (ALLOCATED(ParamData%BldEdgSh)) THEN + DEALLOCATE(ParamData%BldEdgSh) +ENDIF +IF (ALLOCATED(ParamData%FreqBE)) THEN + DEALLOCATE(ParamData%FreqBE) +ENDIF +IF (ALLOCATED(ParamData%FreqBF)) THEN + DEALLOCATE(ParamData%FreqBF) +ENDIF +IF (ALLOCATED(ParamData%BElmntMass)) THEN + DEALLOCATE(ParamData%BElmntMass) +ENDIF +IF (ALLOCATED(ParamData%TElmntMass)) THEN + DEALLOCATE(ParamData%TElmntMass) +ENDIF +IF (ALLOCATED(ParamData%BldNd_OutParam)) THEN +DO i1 = LBOUND(ParamData%BldNd_OutParam,1), UBOUND(ParamData%BldNd_OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%BldNd_OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%BldNd_OutParam) +ENDIF +IF (ALLOCATED(ParamData%Jac_u_indx)) THEN + DEALLOCATE(ParamData%Jac_u_indx) +ENDIF +IF (ALLOCATED(ParamData%du)) THEN + DEALLOCATE(ParamData%du) +ENDIF +IF (ALLOCATED(ParamData%dx)) THEN + DEALLOCATE(ParamData%dx) +ENDIF + END SUBROUTINE ED_DestroyParam + + SUBROUTINE ED_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(ED_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 = 'ED_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 + Db_BufSz = Db_BufSz + 1 ! DT + Db_BufSz = Db_BufSz + 1 ! DT24 + Int_BufSz = Int_BufSz + 1 ! BldNodes + Int_BufSz = Int_BufSz + 1 ! TipNode + Int_BufSz = Int_BufSz + 1 ! NDOF + Db_BufSz = Db_BufSz + 1 ! TwoPiNB + Int_BufSz = Int_BufSz + 1 ! NAug + Int_BufSz = Int_BufSz + 1 ! NPH + Int_BufSz = Int_BufSz + 1 ! PH allocated yes/no + IF ( ALLOCATED(InData%PH) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PH upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PH) ! PH + END IF + Int_BufSz = Int_BufSz + 1 ! NPM + Int_BufSz = Int_BufSz + 1 ! PM allocated yes/no + IF ( ALLOCATED(InData%PM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PM upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%PM) ! PM + END IF + Int_BufSz = Int_BufSz + 1 ! DOF_Flag allocated yes/no + IF ( ALLOCATED(InData%DOF_Flag) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DOF_Flag upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOF_Flag) ! DOF_Flag + END IF + Int_BufSz = Int_BufSz + 1 ! DOF_Desc allocated yes/no + IF ( ALLOCATED(InData%DOF_Desc) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DOF_Desc upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOF_Desc)*LEN(InData%DOF_Desc) ! DOF_Desc + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DOFs: size of buffers for each call to pack subtype + CALL ED_Packactivedofs( Re_Buf, Db_Buf, Int_Buf, InData%DOFs, ErrStat2, ErrMsg2, .TRUE. ) ! DOFs + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DOFs + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DOFs + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DOFs + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1 ! NBlGages + Int_BufSz = Int_BufSz + 1 ! NTwGages + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Re_BufSz = Re_BufSz + 1 ! AvgNrmTpRd + Db_BufSz = Db_BufSz + 1 ! AzimB1Up + Db_BufSz = Db_BufSz + 1 ! CosDel3 + Int_BufSz = Int_BufSz + 1 ! CosPreC allocated yes/no + IF ( ALLOCATED(InData%CosPreC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CosPreC upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%CosPreC) ! CosPreC + END IF + Db_BufSz = Db_BufSz + 1 ! CRFrlSkew + Db_BufSz = Db_BufSz + 1 ! CRFrlSkw2 + Db_BufSz = Db_BufSz + 1 ! CRFrlTilt + Db_BufSz = Db_BufSz + 1 ! CRFrlTlt2 + Db_BufSz = Db_BufSz + 1 ! CShftSkew + Db_BufSz = Db_BufSz + 1 ! CShftTilt + Db_BufSz = Db_BufSz + 1 ! CSRFrlSkw + Db_BufSz = Db_BufSz + 1 ! CSRFrlTlt + Db_BufSz = Db_BufSz + 1 ! CSTFrlSkw + Db_BufSz = Db_BufSz + 1 ! CSTFrlTlt + Db_BufSz = Db_BufSz + 1 ! CTFinBank + Db_BufSz = Db_BufSz + 1 ! CTFinSkew + Db_BufSz = Db_BufSz + 1 ! CTFinTilt + Db_BufSz = Db_BufSz + 1 ! CTFrlSkew + Db_BufSz = Db_BufSz + 1 ! CTFrlSkw2 + Db_BufSz = Db_BufSz + 1 ! CTFrlTilt + Db_BufSz = Db_BufSz + 1 ! CTFrlTlt2 + Re_BufSz = Re_BufSz + 1 ! HubHt + Re_BufSz = Re_BufSz + 1 ! HubCM + Re_BufSz = Re_BufSz + 1 ! HubRad + Re_BufSz = Re_BufSz + 1 ! NacCMxn + Re_BufSz = Re_BufSz + 1 ! NacCMyn + Re_BufSz = Re_BufSz + 1 ! NacCMzn + Re_BufSz = Re_BufSz + 1 ! OverHang + Re_BufSz = Re_BufSz + 1 ! ProjArea + Re_BufSz = Re_BufSz + 1 ! PtfmRefzt + Re_BufSz = Re_BufSz + 1 ! RefTwrHt + Re_BufSz = Re_BufSz + 1 ! RFrlPntxn + Re_BufSz = Re_BufSz + 1 ! RFrlPntyn + Re_BufSz = Re_BufSz + 1 ! RFrlPntzn + Re_BufSz = Re_BufSz + 1 ! rVDxn + Re_BufSz = Re_BufSz + 1 ! rVDyn + Re_BufSz = Re_BufSz + 1 ! rVDzn + Re_BufSz = Re_BufSz + 1 ! rVIMUxn + Re_BufSz = Re_BufSz + 1 ! rVIMUyn + Re_BufSz = Re_BufSz + 1 ! rVIMUzn + Re_BufSz = Re_BufSz + 1 ! rVPxn + Re_BufSz = Re_BufSz + 1 ! rVPyn + Re_BufSz = Re_BufSz + 1 ! rVPzn + Re_BufSz = Re_BufSz + 1 ! rWIxn + Re_BufSz = Re_BufSz + 1 ! rWIyn + Re_BufSz = Re_BufSz + 1 ! rWIzn + Re_BufSz = Re_BufSz + 1 ! rWJxn + Re_BufSz = Re_BufSz + 1 ! rWJyn + Re_BufSz = Re_BufSz + 1 ! rWJzn + Re_BufSz = Re_BufSz + 1 ! rWKxn + Re_BufSz = Re_BufSz + 1 ! rWKyn + Re_BufSz = Re_BufSz + 1 ! rWKzn + Re_BufSz = Re_BufSz + 1 ! rZT0zt + Re_BufSz = Re_BufSz + 1 ! rZYzt + Db_BufSz = Db_BufSz + 1 ! SinDel3 + Int_BufSz = Int_BufSz + 1 ! SinPreC allocated yes/no + IF ( ALLOCATED(InData%SinPreC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SinPreC upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%SinPreC) ! SinPreC + END IF + Db_BufSz = Db_BufSz + 1 ! SRFrlSkew + Db_BufSz = Db_BufSz + 1 ! SRFrlSkw2 + Db_BufSz = Db_BufSz + 1 ! SRFrlTilt + Db_BufSz = Db_BufSz + 1 ! SRFrlTlt2 + Db_BufSz = Db_BufSz + 1 ! SShftSkew + Db_BufSz = Db_BufSz + 1 ! SShftTilt + Db_BufSz = Db_BufSz + 1 ! STFinBank + Db_BufSz = Db_BufSz + 1 ! STFinSkew + Db_BufSz = Db_BufSz + 1 ! STFinTilt + Db_BufSz = Db_BufSz + 1 ! STFrlSkew + Db_BufSz = Db_BufSz + 1 ! STFrlSkw2 + Db_BufSz = Db_BufSz + 1 ! STFrlTilt + Db_BufSz = Db_BufSz + 1 ! STFrlTlt2 + Re_BufSz = Re_BufSz + 1 ! TFrlPntxn + Re_BufSz = Re_BufSz + 1 ! TFrlPntyn + Re_BufSz = Re_BufSz + 1 ! TFrlPntzn + Re_BufSz = Re_BufSz + 1 ! TipRad + Re_BufSz = Re_BufSz + 1 ! TowerHt + Re_BufSz = Re_BufSz + 1 ! TowerBsHt + Re_BufSz = Re_BufSz + 1 ! UndSling + Int_BufSz = Int_BufSz + 1 ! NumBl + Int_BufSz = Int_BufSz + 1 ! AxRedTFA allocated yes/no + IF ( ALLOCATED(InData%AxRedTFA) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AxRedTFA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxRedTFA) ! AxRedTFA + END IF + Int_BufSz = Int_BufSz + 1 ! AxRedTSS allocated yes/no + IF ( ALLOCATED(InData%AxRedTSS) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AxRedTSS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxRedTSS) ! AxRedTSS + END IF + Re_BufSz = Re_BufSz + SIZE(InData%CTFA) ! CTFA + Re_BufSz = Re_BufSz + SIZE(InData%CTSS) ! CTSS + Int_BufSz = Int_BufSz + 1 ! DHNodes allocated yes/no + IF ( ALLOCATED(InData%DHNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DHNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DHNodes) ! DHNodes + END IF + Int_BufSz = Int_BufSz + 1 ! HNodes allocated yes/no + IF ( ALLOCATED(InData%HNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! HNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HNodes) ! HNodes + END IF + Int_BufSz = Int_BufSz + 1 ! HNodesNorm allocated yes/no + IF ( ALLOCATED(InData%HNodesNorm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! HNodesNorm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HNodesNorm) ! HNodesNorm + END IF + Re_BufSz = Re_BufSz + SIZE(InData%KTFA) ! KTFA + Re_BufSz = Re_BufSz + SIZE(InData%KTSS) ! KTSS + Int_BufSz = Int_BufSz + 1 ! MassT allocated yes/no + IF ( ALLOCATED(InData%MassT) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MassT upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MassT) ! MassT + END IF + Int_BufSz = Int_BufSz + 1 ! StiffTSS allocated yes/no + IF ( ALLOCATED(InData%StiffTSS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StiffTSS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffTSS) ! StiffTSS + END IF + Int_BufSz = Int_BufSz + 1 ! TwrFASF allocated yes/no + IF ( ALLOCATED(InData%TwrFASF) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! TwrFASF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrFASF) ! TwrFASF + END IF + Re_BufSz = Re_BufSz + 1 ! TwrFlexL + Int_BufSz = Int_BufSz + 1 ! TwrSSSF allocated yes/no + IF ( ALLOCATED(InData%TwrSSSF) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! TwrSSSF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrSSSF) ! TwrSSSF + END IF + Int_BufSz = Int_BufSz + 1 ! TTopNode + Int_BufSz = Int_BufSz + 1 ! TwrNodes + Int_BufSz = Int_BufSz + 1 ! InerTFA allocated yes/no + IF ( ALLOCATED(InData%InerTFA) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InerTFA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InerTFA) ! InerTFA + END IF + Int_BufSz = Int_BufSz + 1 ! InerTSS allocated yes/no + IF ( ALLOCATED(InData%InerTSS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InerTSS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InerTSS) ! InerTSS + END IF + Int_BufSz = Int_BufSz + 1 ! StiffTGJ allocated yes/no + IF ( ALLOCATED(InData%StiffTGJ) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StiffTGJ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffTGJ) ! StiffTGJ + END IF + Int_BufSz = Int_BufSz + 1 ! StiffTEA allocated yes/no + IF ( ALLOCATED(InData%StiffTEA) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StiffTEA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffTEA) ! StiffTEA + END IF + Int_BufSz = Int_BufSz + 1 ! StiffTFA allocated yes/no + IF ( ALLOCATED(InData%StiffTFA) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StiffTFA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffTFA) ! StiffTFA + END IF + Int_BufSz = Int_BufSz + 1 ! cgOffTFA allocated yes/no + IF ( ALLOCATED(InData%cgOffTFA) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! cgOffTFA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%cgOffTFA) ! cgOffTFA + END IF + Int_BufSz = Int_BufSz + 1 ! cgOffTSS allocated yes/no + IF ( ALLOCATED(InData%cgOffTSS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! cgOffTSS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%cgOffTSS) ! cgOffTSS + END IF + Re_BufSz = Re_BufSz + 1 ! AtfaIner + Int_BufSz = Int_BufSz + 1 ! BldCG allocated yes/no + IF ( ALLOCATED(InData%BldCG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldCG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldCG) ! BldCG + END IF + Int_BufSz = Int_BufSz + 1 ! BldMass allocated yes/no + IF ( ALLOCATED(InData%BldMass) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldMass) ! BldMass + END IF + Re_BufSz = Re_BufSz + 1 ! BoomMass + Int_BufSz = Int_BufSz + 1 ! FirstMom allocated yes/no + IF ( ALLOCATED(InData%FirstMom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FirstMom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FirstMom) ! FirstMom + END IF + Re_BufSz = Re_BufSz + 1 ! GenIner + Re_BufSz = Re_BufSz + 1 ! Hubg1Iner + Re_BufSz = Re_BufSz + 1 ! Hubg2Iner + Re_BufSz = Re_BufSz + 1 ! HubMass + Re_BufSz = Re_BufSz + 1 ! Nacd2Iner + Re_BufSz = Re_BufSz + 1 ! NacMass + Re_BufSz = Re_BufSz + 1 ! PtfmMass + Re_BufSz = Re_BufSz + 1 ! PtfmPIner + Re_BufSz = Re_BufSz + 1 ! PtfmRIner + Re_BufSz = Re_BufSz + 1 ! PtfmYIner + Re_BufSz = Re_BufSz + 1 ! RFrlMass + Re_BufSz = Re_BufSz + 1 ! RotIner + Re_BufSz = Re_BufSz + 1 ! RotMass + Re_BufSz = Re_BufSz + 1 ! RrfaIner + Int_BufSz = Int_BufSz + 1 ! SecondMom allocated yes/no + IF ( ALLOCATED(InData%SecondMom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SecondMom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SecondMom) ! SecondMom + END IF + Re_BufSz = Re_BufSz + 1 ! TFinMass + Re_BufSz = Re_BufSz + 1 ! TFrlIner + Int_BufSz = Int_BufSz + 1 ! TipMass allocated yes/no + IF ( ALLOCATED(InData%TipMass) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TipMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TipMass) ! TipMass + END IF + Re_BufSz = Re_BufSz + 1 ! TurbMass + Re_BufSz = Re_BufSz + 1 ! TwrMass + Re_BufSz = Re_BufSz + 1 ! TwrTpMass + Re_BufSz = Re_BufSz + 1 ! YawBrMass + Re_BufSz = Re_BufSz + 1 ! Gravity + Int_BufSz = Int_BufSz + 1 ! PitchAxis allocated yes/no + IF ( ALLOCATED(InData%PitchAxis) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PitchAxis upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PitchAxis) ! PitchAxis + END IF + Int_BufSz = Int_BufSz + 1 ! AeroTwst allocated yes/no + IF ( ALLOCATED(InData%AeroTwst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AeroTwst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AeroTwst) ! AeroTwst + END IF + Int_BufSz = Int_BufSz + 1 ! AxRedBld allocated yes/no + IF ( ALLOCATED(InData%AxRedBld) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! AxRedBld upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxRedBld) ! AxRedBld + END IF + Int_BufSz = Int_BufSz + 1 ! BAlpha allocated yes/no + IF ( ALLOCATED(InData%BAlpha) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BAlpha upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BAlpha) ! BAlpha + END IF + Int_BufSz = Int_BufSz + 1 ! BldEDamp allocated yes/no + IF ( ALLOCATED(InData%BldEDamp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldEDamp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldEDamp) ! BldEDamp + END IF + Int_BufSz = Int_BufSz + 1 ! BldFDamp allocated yes/no + IF ( ALLOCATED(InData%BldFDamp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldFDamp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldFDamp) ! BldFDamp + END IF + Re_BufSz = Re_BufSz + 1 ! BldFlexL + Int_BufSz = Int_BufSz + 1 ! CAeroTwst allocated yes/no + IF ( ALLOCATED(InData%CAeroTwst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CAeroTwst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CAeroTwst) ! CAeroTwst + END IF + Int_BufSz = Int_BufSz + 1 ! CBE allocated yes/no + IF ( ALLOCATED(InData%CBE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CBE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBE) ! CBE + END IF + Int_BufSz = Int_BufSz + 1 ! CBF allocated yes/no + IF ( ALLOCATED(InData%CBF) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! CBF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBF) ! CBF + END IF + Int_BufSz = Int_BufSz + 1 ! cgOffBEdg allocated yes/no + IF ( ALLOCATED(InData%cgOffBEdg) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! cgOffBEdg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%cgOffBEdg) ! cgOffBEdg + END IF + Int_BufSz = Int_BufSz + 1 ! cgOffBFlp allocated yes/no + IF ( ALLOCATED(InData%cgOffBFlp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! cgOffBFlp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%cgOffBFlp) ! cgOffBFlp + END IF + Int_BufSz = Int_BufSz + 1 ! Chord allocated yes/no + IF ( ALLOCATED(InData%Chord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Chord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Chord) ! Chord + END IF + Int_BufSz = Int_BufSz + 1 ! CThetaS allocated yes/no + IF ( ALLOCATED(InData%CThetaS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CThetaS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%CThetaS) ! CThetaS + END IF + Int_BufSz = Int_BufSz + 1 ! DRNodes allocated yes/no + IF ( ALLOCATED(InData%DRNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DRNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DRNodes) ! DRNodes + END IF + Int_BufSz = Int_BufSz + 1 ! EAOffBEdg allocated yes/no + IF ( ALLOCATED(InData%EAOffBEdg) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! EAOffBEdg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EAOffBEdg) ! EAOffBEdg + END IF + Int_BufSz = Int_BufSz + 1 ! EAOffBFlp allocated yes/no + IF ( ALLOCATED(InData%EAOffBFlp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! EAOffBFlp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%EAOffBFlp) ! EAOffBFlp + END IF + Int_BufSz = Int_BufSz + 1 ! FStTunr allocated yes/no + IF ( ALLOCATED(InData%FStTunr) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FStTunr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FStTunr) ! FStTunr + END IF + Int_BufSz = Int_BufSz + 1 ! InerBEdg allocated yes/no + IF ( ALLOCATED(InData%InerBEdg) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InerBEdg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InerBEdg) ! InerBEdg + END IF + Int_BufSz = Int_BufSz + 1 ! InerBFlp allocated yes/no + IF ( ALLOCATED(InData%InerBFlp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InerBFlp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InerBFlp) ! InerBFlp + END IF + Int_BufSz = Int_BufSz + 1 ! KBE allocated yes/no + IF ( ALLOCATED(InData%KBE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! KBE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBE) ! KBE + END IF + Int_BufSz = Int_BufSz + 1 ! KBF allocated yes/no + IF ( ALLOCATED(InData%KBF) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! KBF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBF) ! KBF + END IF + Int_BufSz = Int_BufSz + 1 ! MassB allocated yes/no + IF ( ALLOCATED(InData%MassB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MassB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MassB) ! MassB + END IF + Int_BufSz = Int_BufSz + 1 ! RefAxisxb allocated yes/no + IF ( ALLOCATED(InData%RefAxisxb) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RefAxisxb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RefAxisxb) ! RefAxisxb + END IF + Int_BufSz = Int_BufSz + 1 ! RefAxisyb allocated yes/no + IF ( ALLOCATED(InData%RefAxisyb) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RefAxisyb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RefAxisyb) ! RefAxisyb + END IF + Int_BufSz = Int_BufSz + 1 ! RNodes allocated yes/no + IF ( ALLOCATED(InData%RNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RNodes) ! RNodes + END IF + Int_BufSz = Int_BufSz + 1 ! RNodesNorm allocated yes/no + IF ( ALLOCATED(InData%RNodesNorm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RNodesNorm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RNodesNorm) ! RNodesNorm + END IF + Int_BufSz = Int_BufSz + 1 ! rSAerCenn1 allocated yes/no + IF ( ALLOCATED(InData%rSAerCenn1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rSAerCenn1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rSAerCenn1) ! rSAerCenn1 + END IF + Int_BufSz = Int_BufSz + 1 ! rSAerCenn2 allocated yes/no + IF ( ALLOCATED(InData%rSAerCenn2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rSAerCenn2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rSAerCenn2) ! rSAerCenn2 + END IF + Int_BufSz = Int_BufSz + 1 ! SAeroTwst allocated yes/no + IF ( ALLOCATED(InData%SAeroTwst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SAeroTwst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SAeroTwst) ! SAeroTwst + END IF + Int_BufSz = Int_BufSz + 1 ! StiffBE allocated yes/no + IF ( ALLOCATED(InData%StiffBE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StiffBE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffBE) ! StiffBE + END IF + Int_BufSz = Int_BufSz + 1 ! StiffBEA allocated yes/no + IF ( ALLOCATED(InData%StiffBEA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StiffBEA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffBEA) ! StiffBEA + END IF + Int_BufSz = Int_BufSz + 1 ! StiffBF allocated yes/no + IF ( ALLOCATED(InData%StiffBF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StiffBF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffBF) ! StiffBF + END IF + Int_BufSz = Int_BufSz + 1 ! StiffBGJ allocated yes/no + IF ( ALLOCATED(InData%StiffBGJ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StiffBGJ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StiffBGJ) ! StiffBGJ + END IF + Int_BufSz = Int_BufSz + 1 ! SThetaS allocated yes/no + IF ( ALLOCATED(InData%SThetaS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SThetaS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%SThetaS) ! SThetaS + END IF + Int_BufSz = Int_BufSz + 1 ! ThetaS allocated yes/no + IF ( ALLOCATED(InData%ThetaS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ThetaS upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ThetaS) ! ThetaS + END IF + Int_BufSz = Int_BufSz + 1 ! TwistedSF allocated yes/no + IF ( ALLOCATED(InData%TwistedSF) ) THEN + Int_BufSz = Int_BufSz + 2*5 ! TwistedSF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwistedSF) ! TwistedSF + END IF + Int_BufSz = Int_BufSz + 1 ! BldFl1Sh allocated yes/no + IF ( ALLOCATED(InData%BldFl1Sh) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldFl1Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldFl1Sh) ! BldFl1Sh + END IF + Int_BufSz = Int_BufSz + 1 ! BldFl2Sh allocated yes/no + IF ( ALLOCATED(InData%BldFl2Sh) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldFl2Sh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldFl2Sh) ! BldFl2Sh + END IF + Int_BufSz = Int_BufSz + 1 ! BldEdgSh allocated yes/no + IF ( ALLOCATED(InData%BldEdgSh) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BldEdgSh upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BldEdgSh) ! BldEdgSh + END IF + Int_BufSz = Int_BufSz + 1 ! FreqBE allocated yes/no + IF ( ALLOCATED(InData%FreqBE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FreqBE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FreqBE) ! FreqBE + END IF + Int_BufSz = Int_BufSz + 1 ! FreqBF allocated yes/no + IF ( ALLOCATED(InData%FreqBF) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FreqBF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FreqBF) ! FreqBF + END IF + Re_BufSz = Re_BufSz + SIZE(InData%FreqTFA) ! FreqTFA + Re_BufSz = Re_BufSz + SIZE(InData%FreqTSS) ! FreqTSS + Re_BufSz = Re_BufSz + 1 ! TeetCDmp + Re_BufSz = Re_BufSz + 1 ! TeetDmp + Re_BufSz = Re_BufSz + 1 ! TeetDmpP + Re_BufSz = Re_BufSz + 1 ! TeetHSSp + Re_BufSz = Re_BufSz + 1 ! TeetHStP + Re_BufSz = Re_BufSz + 1 ! TeetSSSp + Re_BufSz = Re_BufSz + 1 ! TeetSStP + Int_BufSz = Int_BufSz + 1 ! TeetMod + Re_BufSz = Re_BufSz + 1 ! TFrlCDmp + Re_BufSz = Re_BufSz + 1 ! TFrlDmp + Re_BufSz = Re_BufSz + 1 ! TFrlDSDmp + Re_BufSz = Re_BufSz + 1 ! TFrlDSDP + Re_BufSz = Re_BufSz + 1 ! TFrlDSSP + Re_BufSz = Re_BufSz + 1 ! TFrlDSSpr + Re_BufSz = Re_BufSz + 1 ! TFrlSpr + Re_BufSz = Re_BufSz + 1 ! TFrlUSDmp + Re_BufSz = Re_BufSz + 1 ! TFrlUSDP + Re_BufSz = Re_BufSz + 1 ! TFrlUSSP + Re_BufSz = Re_BufSz + 1 ! TFrlUSSpr + Int_BufSz = Int_BufSz + 1 ! TFrlMod + Re_BufSz = Re_BufSz + 1 ! RFrlCDmp + Re_BufSz = Re_BufSz + 1 ! RFrlDmp + Re_BufSz = Re_BufSz + 1 ! RFrlDSDmp + Re_BufSz = Re_BufSz + 1 ! RFrlDSDP + Re_BufSz = Re_BufSz + 1 ! RFrlDSSP + Re_BufSz = Re_BufSz + 1 ! RFrlDSSpr + Re_BufSz = Re_BufSz + 1 ! RFrlSpr + Re_BufSz = Re_BufSz + 1 ! RFrlUSDmp + Re_BufSz = Re_BufSz + 1 ! RFrlUSDP + Re_BufSz = Re_BufSz + 1 ! RFrlUSSP + Re_BufSz = Re_BufSz + 1 ! RFrlUSSpr + Int_BufSz = Int_BufSz + 1 ! RFrlMod + Re_BufSz = Re_BufSz + 1 ! ShftGagL + Int_BufSz = Int_BufSz + SIZE(InData%BldGagNd) ! BldGagNd + Int_BufSz = Int_BufSz + SIZE(InData%TwrGagNd) ! TwrGagNd + Db_BufSz = Db_BufSz + 1 ! TStart + Re_BufSz = Re_BufSz + 1 ! DTTorDmp + Re_BufSz = Re_BufSz + 1 ! DTTorSpr + Re_BufSz = Re_BufSz + 1 ! GBRatio + Re_BufSz = Re_BufSz + 1 ! GBoxEff + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! BElmntMass allocated yes/no + IF ( ALLOCATED(InData%BElmntMass) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BElmntMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BElmntMass) ! BElmntMass + END IF + Int_BufSz = Int_BufSz + 1 ! TElmntMass allocated yes/no + IF ( ALLOCATED(InData%TElmntMass) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TElmntMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TElmntMass) ! TElmntMass + END IF + Int_BufSz = Int_BufSz + 1 ! method + Re_BufSz = Re_BufSz + 1 ! PtfmCMxt + Re_BufSz = Re_BufSz + 1 ! PtfmCMyt + Int_BufSz = Int_BufSz + 1 ! BD4Blades + Int_BufSz = Int_BufSz + 1 ! UseAD14 + Int_BufSz = Int_BufSz + 1 ! BldNd_NumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_TotNumOuts + Int_BufSz = Int_BufSz + 1 ! BldNd_OutParam allocated yes/no + IF ( ALLOCATED(InData%BldNd_OutParam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BldNd_OutParam upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + Int_BufSz = Int_BufSz + 3 ! BldNd_OutParam: size of buffers for each call to pack subtype + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BldNd_OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BldNd_OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BldNd_OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BldNd_OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BldNd_BladesOut + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 1 ! du allocated yes/no + IF ( ALLOCATED(InData%du) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! du upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%du) ! du + END IF + Int_BufSz = Int_BufSz + 1 ! dx allocated yes/no + IF ( ALLOCATED(InData%dx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dx upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%dx) ! dx + END IF + Int_BufSz = Int_BufSz + 1 ! Jac_ny + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT24 + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TipNode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NDOF + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TwoPiNB + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NAug + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPH + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PH) ) 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%PH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PH,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PH,1), UBOUND(InData%PH,1) + IntKiBuf(Int_Xferred) = InData%PH(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NPM + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PM) ) 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%PM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PM,2), UBOUND(InData%PM,2) + DO i1 = LBOUND(InData%PM,1), UBOUND(InData%PM,1) + IntKiBuf(Int_Xferred) = InData%PM(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DOF_Flag) ) 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%DOF_Flag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOF_Flag,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DOF_Flag,1), UBOUND(InData%DOF_Flag,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%DOF_Flag(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DOF_Desc) ) 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%DOF_Desc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOF_Desc,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DOF_Desc,1), UBOUND(InData%DOF_Desc,1) + DO I = 1, LEN(InData%DOF_Desc) + IntKiBuf(Int_Xferred) = ICHAR(InData%DOF_Desc(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + CALL ED_Packactivedofs( Re_Buf, Db_Buf, Int_Buf, InData%DOFs, ErrStat2, ErrMsg2, OnlySize ) ! DOFs + 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 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NBlGages + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NTwGages + 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 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%AvgNrmTpRd + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%AzimB1Up + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CosDel3 + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CosPreC) ) 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%CosPreC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CosPreC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CosPreC,1), UBOUND(InData%CosPreC,1) + DbKiBuf(Db_Xferred) = InData%CosPreC(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%CRFrlSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CRFrlSkw2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CRFrlTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CRFrlTlt2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CShftSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CShftTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CSRFrlSkw + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CSRFrlTlt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CSTFrlSkw + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CSTFrlTlt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFinBank + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFinSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFinTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFrlSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFrlSkw2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFrlTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%CTFrlTlt2 + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubCM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacCMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%OverHang + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ProjArea + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRefzt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefTwrHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlPntzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVDxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVDyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVDzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVIMUxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVIMUyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVIMUzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVPxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVPyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rVPzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWIxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWIyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWIzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWJxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWJyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWJzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWKxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWKyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rWKzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rZT0zt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rZYzt + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SinDel3 + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SinPreC) ) 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%SinPreC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SinPreC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SinPreC,1), UBOUND(InData%SinPreC,1) + DbKiBuf(Db_Xferred) = InData%SinPreC(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%SRFrlSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SRFrlSkw2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SRFrlTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SRFrlTlt2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SShftSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SShftTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFinBank + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFinSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFinTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFrlSkew + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFrlSkw2 + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFrlTilt + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%STFrlTlt2 + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntxn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlPntzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TipRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerBsHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UndSling + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AxRedTFA) ) 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%AxRedTFA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTFA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedTFA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTFA,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedTFA,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTFA,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AxRedTFA,3), UBOUND(InData%AxRedTFA,3) + DO i2 = LBOUND(InData%AxRedTFA,2), UBOUND(InData%AxRedTFA,2) + DO i1 = LBOUND(InData%AxRedTFA,1), UBOUND(InData%AxRedTFA,1) + ReKiBuf(Re_Xferred) = InData%AxRedTFA(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxRedTSS) ) 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%AxRedTSS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTSS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedTSS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTSS,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedTSS,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedTSS,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AxRedTSS,3), UBOUND(InData%AxRedTSS,3) + DO i2 = LBOUND(InData%AxRedTSS,2), UBOUND(InData%AxRedTSS,2) + DO i1 = LBOUND(InData%AxRedTSS,1), UBOUND(InData%AxRedTSS,1) + ReKiBuf(Re_Xferred) = InData%AxRedTSS(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i2 = LBOUND(InData%CTFA,2), UBOUND(InData%CTFA,2) + DO i1 = LBOUND(InData%CTFA,1), UBOUND(InData%CTFA,1) + ReKiBuf(Re_Xferred) = InData%CTFA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%CTSS,2), UBOUND(InData%CTSS,2) + DO i1 = LBOUND(InData%CTSS,1), UBOUND(InData%CTSS,1) + ReKiBuf(Re_Xferred) = InData%CTSS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%DHNodes) ) 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%DHNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DHNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DHNodes,1), UBOUND(InData%DHNodes,1) + ReKiBuf(Re_Xferred) = InData%DHNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%HNodes) ) 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%HNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%HNodes,1), UBOUND(InData%HNodes,1) + ReKiBuf(Re_Xferred) = InData%HNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%HNodesNorm) ) 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%HNodesNorm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HNodesNorm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%HNodesNorm,1), UBOUND(InData%HNodesNorm,1) + ReKiBuf(Re_Xferred) = InData%HNodesNorm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i2 = LBOUND(InData%KTFA,2), UBOUND(InData%KTFA,2) + DO i1 = LBOUND(InData%KTFA,1), UBOUND(InData%KTFA,1) + ReKiBuf(Re_Xferred) = InData%KTFA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%KTSS,2), UBOUND(InData%KTSS,2) + DO i1 = LBOUND(InData%KTSS,1), UBOUND(InData%KTSS,1) + ReKiBuf(Re_Xferred) = InData%KTSS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%MassT) ) 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%MassT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MassT,1), UBOUND(InData%MassT,1) + ReKiBuf(Re_Xferred) = InData%MassT(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffTSS) ) 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%StiffTSS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffTSS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StiffTSS,1), UBOUND(InData%StiffTSS,1) + ReKiBuf(Re_Xferred) = InData%StiffTSS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwrFASF) ) 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%TwrFASF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrFASF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrFASF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrFASF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrFASF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrFASF,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%TwrFASF,3), UBOUND(InData%TwrFASF,3) + DO i2 = LBOUND(InData%TwrFASF,2), UBOUND(InData%TwrFASF,2) + DO i1 = LBOUND(InData%TwrFASF,1), UBOUND(InData%TwrFASF,1) + ReKiBuf(Re_Xferred) = InData%TwrFASF(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TwrFlexL + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TwrSSSF) ) 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%TwrSSSF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrSSSF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrSSSF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrSSSF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrSSSF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrSSSF,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%TwrSSSF,3), UBOUND(InData%TwrSSSF,3) + DO i2 = LBOUND(InData%TwrSSSF,2), UBOUND(InData%TwrSSSF,2) + DO i1 = LBOUND(InData%TwrSSSF,1), UBOUND(InData%TwrSSSF,1) + ReKiBuf(Re_Xferred) = InData%TwrSSSF(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%TTopNode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TwrNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%InerTFA) ) 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%InerTFA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerTFA,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InerTFA,1), UBOUND(InData%InerTFA,1) + ReKiBuf(Re_Xferred) = InData%InerTFA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InerTSS) ) 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%InerTSS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerTSS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InerTSS,1), UBOUND(InData%InerTSS,1) + ReKiBuf(Re_Xferred) = InData%InerTSS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffTGJ) ) 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%StiffTGJ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffTGJ,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StiffTGJ,1), UBOUND(InData%StiffTGJ,1) + ReKiBuf(Re_Xferred) = InData%StiffTGJ(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffTEA) ) 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%StiffTEA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffTEA,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StiffTEA,1), UBOUND(InData%StiffTEA,1) + ReKiBuf(Re_Xferred) = InData%StiffTEA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffTFA) ) 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%StiffTFA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffTFA,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StiffTFA,1), UBOUND(InData%StiffTFA,1) + ReKiBuf(Re_Xferred) = InData%StiffTFA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%cgOffTFA) ) 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%cgOffTFA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffTFA,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%cgOffTFA,1), UBOUND(InData%cgOffTFA,1) + ReKiBuf(Re_Xferred) = InData%cgOffTFA(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%cgOffTSS) ) 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%cgOffTSS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffTSS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%cgOffTSS,1), UBOUND(InData%cgOffTSS,1) + ReKiBuf(Re_Xferred) = InData%cgOffTSS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%AtfaIner + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldCG) ) 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%BldCG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldCG,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldCG,1), UBOUND(InData%BldCG,1) + ReKiBuf(Re_Xferred) = InData%BldCG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldMass) ) 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%BldMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldMass,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldMass,1), UBOUND(InData%BldMass,1) + ReKiBuf(Re_Xferred) = InData%BldMass(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BoomMass + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FirstMom) ) 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%FirstMom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FirstMom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FirstMom,1), UBOUND(InData%FirstMom,1) + ReKiBuf(Re_Xferred) = InData%FirstMom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%GenIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Hubg1Iner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Hubg2Iner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Nacd2Iner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmPIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmYIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotIner + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RrfaIner + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SecondMom) ) 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%SecondMom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SecondMom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SecondMom,1), UBOUND(InData%SecondMom,1) + ReKiBuf(Re_Xferred) = InData%SecondMom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TFinMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlIner + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TipMass) ) 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%TipMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TipMass,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TipMass,1), UBOUND(InData%TipMass,1) + ReKiBuf(Re_Xferred) = InData%TipMass(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TurbMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwrMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwrTpMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMass + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PitchAxis) ) 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%PitchAxis,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitchAxis,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PitchAxis,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitchAxis,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PitchAxis,2), UBOUND(InData%PitchAxis,2) + DO i1 = LBOUND(InData%PitchAxis,1), UBOUND(InData%PitchAxis,1) + ReKiBuf(Re_Xferred) = InData%PitchAxis(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AeroTwst) ) 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%AeroTwst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AeroTwst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AeroTwst,1), UBOUND(InData%AeroTwst,1) + ReKiBuf(Re_Xferred) = InData%AeroTwst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxRedBld) ) 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%AxRedBld,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedBld,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedBld,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedBld,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedBld,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedBld,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxRedBld,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxRedBld,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%AxRedBld,4), UBOUND(InData%AxRedBld,4) + DO i3 = LBOUND(InData%AxRedBld,3), UBOUND(InData%AxRedBld,3) + DO i2 = LBOUND(InData%AxRedBld,2), UBOUND(InData%AxRedBld,2) + DO i1 = LBOUND(InData%AxRedBld,1), UBOUND(InData%AxRedBld,1) + ReKiBuf(Re_Xferred) = InData%AxRedBld(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BAlpha) ) 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%BAlpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BAlpha,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BAlpha,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BAlpha,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BAlpha,2), UBOUND(InData%BAlpha,2) + DO i1 = LBOUND(InData%BAlpha,1), UBOUND(InData%BAlpha,1) + ReKiBuf(Re_Xferred) = InData%BAlpha(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldEDamp) ) 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%BldEDamp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldEDamp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldEDamp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldEDamp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldEDamp,2), UBOUND(InData%BldEDamp,2) + DO i1 = LBOUND(InData%BldEDamp,1), UBOUND(InData%BldEDamp,1) + ReKiBuf(Re_Xferred) = InData%BldEDamp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldFDamp) ) 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%BldFDamp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFDamp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldFDamp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFDamp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldFDamp,2), UBOUND(InData%BldFDamp,2) + DO i1 = LBOUND(InData%BldFDamp,1), UBOUND(InData%BldFDamp,1) + ReKiBuf(Re_Xferred) = InData%BldFDamp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BldFlexL + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CAeroTwst) ) 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%CAeroTwst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CAeroTwst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CAeroTwst,1), UBOUND(InData%CAeroTwst,1) + ReKiBuf(Re_Xferred) = InData%CAeroTwst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CBE) ) 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%CBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CBE,3), UBOUND(InData%CBE,3) + DO i2 = LBOUND(InData%CBE,2), UBOUND(InData%CBE,2) + DO i1 = LBOUND(InData%CBE,1), UBOUND(InData%CBE,1) + ReKiBuf(Re_Xferred) = InData%CBE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CBF) ) 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%CBF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBF,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%CBF,3), UBOUND(InData%CBF,3) + DO i2 = LBOUND(InData%CBF,2), UBOUND(InData%CBF,2) + DO i1 = LBOUND(InData%CBF,1), UBOUND(InData%CBF,1) + ReKiBuf(Re_Xferred) = InData%CBF(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%cgOffBEdg) ) 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%cgOffBEdg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffBEdg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%cgOffBEdg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffBEdg,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%cgOffBEdg,2), UBOUND(InData%cgOffBEdg,2) + DO i1 = LBOUND(InData%cgOffBEdg,1), UBOUND(InData%cgOffBEdg,1) + ReKiBuf(Re_Xferred) = InData%cgOffBEdg(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%cgOffBFlp) ) 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%cgOffBFlp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffBFlp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%cgOffBFlp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%cgOffBFlp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%cgOffBFlp,2), UBOUND(InData%cgOffBFlp,2) + DO i1 = LBOUND(InData%cgOffBFlp,1), UBOUND(InData%cgOffBFlp,1) + ReKiBuf(Re_Xferred) = InData%cgOffBFlp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Chord) ) 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%Chord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Chord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Chord,1), UBOUND(InData%Chord,1) + ReKiBuf(Re_Xferred) = InData%Chord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CThetaS) ) 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%CThetaS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CThetaS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CThetaS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CThetaS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CThetaS,2), UBOUND(InData%CThetaS,2) + DO i1 = LBOUND(InData%CThetaS,1), UBOUND(InData%CThetaS,1) + DbKiBuf(Db_Xferred) = InData%CThetaS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DRNodes) ) 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%DRNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DRNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DRNodes,1), UBOUND(InData%DRNodes,1) + ReKiBuf(Re_Xferred) = InData%DRNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EAOffBEdg) ) 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%EAOffBEdg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EAOffBEdg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EAOffBEdg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EAOffBEdg,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%EAOffBEdg,2), UBOUND(InData%EAOffBEdg,2) + DO i1 = LBOUND(InData%EAOffBEdg,1), UBOUND(InData%EAOffBEdg,1) + ReKiBuf(Re_Xferred) = InData%EAOffBEdg(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%EAOffBFlp) ) 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%EAOffBFlp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EAOffBFlp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%EAOffBFlp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%EAOffBFlp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%EAOffBFlp,2), UBOUND(InData%EAOffBFlp,2) + DO i1 = LBOUND(InData%EAOffBFlp,1), UBOUND(InData%EAOffBFlp,1) + ReKiBuf(Re_Xferred) = InData%EAOffBFlp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FStTunr) ) 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%FStTunr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FStTunr,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FStTunr,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FStTunr,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FStTunr,2), UBOUND(InData%FStTunr,2) + DO i1 = LBOUND(InData%FStTunr,1), UBOUND(InData%FStTunr,1) + ReKiBuf(Re_Xferred) = InData%FStTunr(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InerBEdg) ) 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%InerBEdg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerBEdg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InerBEdg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerBEdg,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InerBEdg,2), UBOUND(InData%InerBEdg,2) + DO i1 = LBOUND(InData%InerBEdg,1), UBOUND(InData%InerBEdg,1) + ReKiBuf(Re_Xferred) = InData%InerBEdg(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InerBFlp) ) 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%InerBFlp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerBFlp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InerBFlp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InerBFlp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InerBFlp,2), UBOUND(InData%InerBFlp,2) + DO i1 = LBOUND(InData%InerBFlp,1), UBOUND(InData%InerBFlp,1) + ReKiBuf(Re_Xferred) = InData%InerBFlp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%KBE) ) 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%KBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%KBE,3), UBOUND(InData%KBE,3) + DO i2 = LBOUND(InData%KBE,2), UBOUND(InData%KBE,2) + DO i1 = LBOUND(InData%KBE,1), UBOUND(InData%KBE,1) + ReKiBuf(Re_Xferred) = InData%KBE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%KBF) ) 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%KBF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBF,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%KBF,3), UBOUND(InData%KBF,3) + DO i2 = LBOUND(InData%KBF,2), UBOUND(InData%KBF,2) + DO i1 = LBOUND(InData%KBF,1), UBOUND(InData%KBF,1) + ReKiBuf(Re_Xferred) = InData%KBF(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MassB) ) 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%MassB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MassB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MassB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MassB,2), UBOUND(InData%MassB,2) + DO i1 = LBOUND(InData%MassB,1), UBOUND(InData%MassB,1) + ReKiBuf(Re_Xferred) = InData%MassB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RefAxisxb) ) 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%RefAxisxb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RefAxisxb,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RefAxisxb,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RefAxisxb,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RefAxisxb,2), UBOUND(InData%RefAxisxb,2) + DO i1 = LBOUND(InData%RefAxisxb,1), UBOUND(InData%RefAxisxb,1) + ReKiBuf(Re_Xferred) = InData%RefAxisxb(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RefAxisyb) ) 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%RefAxisyb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RefAxisyb,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RefAxisyb,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RefAxisyb,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%RefAxisyb,2), UBOUND(InData%RefAxisyb,2) + DO i1 = LBOUND(InData%RefAxisyb,1), UBOUND(InData%RefAxisyb,1) + ReKiBuf(Re_Xferred) = InData%RefAxisyb(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RNodes) ) 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%RNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RNodes,1), UBOUND(InData%RNodes,1) + ReKiBuf(Re_Xferred) = InData%RNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RNodesNorm) ) 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%RNodesNorm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RNodesNorm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RNodesNorm,1), UBOUND(InData%RNodesNorm,1) + ReKiBuf(Re_Xferred) = InData%RNodesNorm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rSAerCenn1) ) 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%rSAerCenn1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCenn1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rSAerCenn1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCenn1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rSAerCenn1,2), UBOUND(InData%rSAerCenn1,2) + DO i1 = LBOUND(InData%rSAerCenn1,1), UBOUND(InData%rSAerCenn1,1) + ReKiBuf(Re_Xferred) = InData%rSAerCenn1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rSAerCenn2) ) 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%rSAerCenn2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCenn2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rSAerCenn2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rSAerCenn2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rSAerCenn2,2), UBOUND(InData%rSAerCenn2,2) + DO i1 = LBOUND(InData%rSAerCenn2,1), UBOUND(InData%rSAerCenn2,1) + ReKiBuf(Re_Xferred) = InData%rSAerCenn2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SAeroTwst) ) 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%SAeroTwst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SAeroTwst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SAeroTwst,1), UBOUND(InData%SAeroTwst,1) + ReKiBuf(Re_Xferred) = InData%SAeroTwst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffBE) ) 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%StiffBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StiffBE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StiffBE,2), UBOUND(InData%StiffBE,2) + DO i1 = LBOUND(InData%StiffBE,1), UBOUND(InData%StiffBE,1) + ReKiBuf(Re_Xferred) = InData%StiffBE(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffBEA) ) 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%StiffBEA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBEA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StiffBEA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBEA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StiffBEA,2), UBOUND(InData%StiffBEA,2) + DO i1 = LBOUND(InData%StiffBEA,1), UBOUND(InData%StiffBEA,1) + ReKiBuf(Re_Xferred) = InData%StiffBEA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffBF) ) 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%StiffBF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StiffBF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StiffBF,2), UBOUND(InData%StiffBF,2) + DO i1 = LBOUND(InData%StiffBF,1), UBOUND(InData%StiffBF,1) + ReKiBuf(Re_Xferred) = InData%StiffBF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StiffBGJ) ) 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%StiffBGJ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBGJ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StiffBGJ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StiffBGJ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StiffBGJ,2), UBOUND(InData%StiffBGJ,2) + DO i1 = LBOUND(InData%StiffBGJ,1), UBOUND(InData%StiffBGJ,1) + ReKiBuf(Re_Xferred) = InData%StiffBGJ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SThetaS) ) 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%SThetaS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SThetaS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SThetaS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SThetaS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%SThetaS,2), UBOUND(InData%SThetaS,2) + DO i1 = LBOUND(InData%SThetaS,1), UBOUND(InData%SThetaS,1) + DbKiBuf(Db_Xferred) = InData%SThetaS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ThetaS) ) 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%ThetaS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ThetaS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ThetaS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ThetaS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ThetaS,2), UBOUND(InData%ThetaS,2) + DO i1 = LBOUND(InData%ThetaS,1), UBOUND(InData%ThetaS,1) + ReKiBuf(Re_Xferred) = InData%ThetaS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TwistedSF) ) 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%TwistedSF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwistedSF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwistedSF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwistedSF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwistedSF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwistedSF,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwistedSF,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwistedSF,4) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwistedSF,5) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwistedSF,5) + Int_Xferred = Int_Xferred + 2 + + DO i5 = LBOUND(InData%TwistedSF,5), UBOUND(InData%TwistedSF,5) + DO i4 = LBOUND(InData%TwistedSF,4), UBOUND(InData%TwistedSF,4) + DO i3 = LBOUND(InData%TwistedSF,3), UBOUND(InData%TwistedSF,3) + DO i2 = LBOUND(InData%TwistedSF,2), UBOUND(InData%TwistedSF,2) + DO i1 = LBOUND(InData%TwistedSF,1), UBOUND(InData%TwistedSF,1) + ReKiBuf(Re_Xferred) = InData%TwistedSF(i1,i2,i3,i4,i5) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldFl1Sh) ) 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%BldFl1Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl1Sh,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldFl1Sh,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl1Sh,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldFl1Sh,2), UBOUND(InData%BldFl1Sh,2) + DO i1 = LBOUND(InData%BldFl1Sh,1), UBOUND(InData%BldFl1Sh,1) + ReKiBuf(Re_Xferred) = InData%BldFl1Sh(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldFl2Sh) ) 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%BldFl2Sh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl2Sh,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldFl2Sh,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldFl2Sh,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldFl2Sh,2), UBOUND(InData%BldFl2Sh,2) + DO i1 = LBOUND(InData%BldFl2Sh,1), UBOUND(InData%BldFl2Sh,1) + ReKiBuf(Re_Xferred) = InData%BldFl2Sh(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BldEdgSh) ) 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%BldEdgSh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldEdgSh,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BldEdgSh,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldEdgSh,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BldEdgSh,2), UBOUND(InData%BldEdgSh,2) + DO i1 = LBOUND(InData%BldEdgSh,1), UBOUND(InData%BldEdgSh,1) + ReKiBuf(Re_Xferred) = InData%BldEdgSh(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FreqBE) ) 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%FreqBE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FreqBE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FreqBE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FreqBE,3), UBOUND(InData%FreqBE,3) + DO i2 = LBOUND(InData%FreqBE,2), UBOUND(InData%FreqBE,2) + DO i1 = LBOUND(InData%FreqBE,1), UBOUND(InData%FreqBE,1) + ReKiBuf(Re_Xferred) = InData%FreqBE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FreqBF) ) 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%FreqBF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FreqBF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBF,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FreqBF,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FreqBF,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FreqBF,3), UBOUND(InData%FreqBF,3) + DO i2 = LBOUND(InData%FreqBF,2), UBOUND(InData%FreqBF,2) + DO i1 = LBOUND(InData%FreqBF,1), UBOUND(InData%FreqBF,1) + ReKiBuf(Re_Xferred) = InData%FreqBF(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i2 = LBOUND(InData%FreqTFA,2), UBOUND(InData%FreqTFA,2) + DO i1 = LBOUND(InData%FreqTFA,1), UBOUND(InData%FreqTFA,1) + ReKiBuf(Re_Xferred) = InData%FreqTFA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%FreqTSS,2), UBOUND(InData%FreqTSS,2) + DO i1 = LBOUND(InData%FreqTSS,1), UBOUND(InData%FreqTSS,1) + ReKiBuf(Re_Xferred) = InData%FreqTSS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + ReKiBuf(Re_Xferred) = InData%TeetCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetDmpP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetHSSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetHStP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetSSSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TeetSStP + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TeetMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlDSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TFrlUSSpr + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TFrlMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlCDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlDSSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSDP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RFrlUSSpr + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RFrlMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShftGagL + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%BldGagNd,1), UBOUND(InData%BldGagNd,1) + IntKiBuf(Int_Xferred) = InData%BldGagNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%TwrGagNd,1), UBOUND(InData%TwrGagNd,1) + IntKiBuf(Int_Xferred) = InData%TwrGagNd(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%TStart + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DTTorDmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DTTorSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GBRatio + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GBoxEff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%BElmntMass) ) 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%BElmntMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BElmntMass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BElmntMass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BElmntMass,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BElmntMass,2), UBOUND(InData%BElmntMass,2) + DO i1 = LBOUND(InData%BElmntMass,1), UBOUND(InData%BElmntMass,1) + ReKiBuf(Re_Xferred) = InData%BElmntMass(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TElmntMass) ) 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%TElmntMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TElmntMass,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TElmntMass,1), UBOUND(InData%TElmntMass,1) + ReKiBuf(Re_Xferred) = InData%TElmntMass(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%method + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCMxt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCMyt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BD4Blades, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseAD14, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BldNd_TotNumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BldNd_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%BldNd_OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BldNd_OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BldNd_OutParam,1), UBOUND(InData%BldNd_OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%BldNd_OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! BldNd_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 + IntKiBuf(Int_Xferred) = InData%BldNd_BladesOut + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%du) ) 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%du,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%du,1), UBOUND(InData%du,1) + DbKiBuf(Db_Xferred) = InData%du(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dx) ) 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%dx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dx,1), UBOUND(InData%dx,1) + DbKiBuf(Db_Xferred) = InData%dx(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_PackParam + + SUBROUTINE ED_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(ED_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) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DT24 = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%BldNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TipNode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NDOF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwoPiNB = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%NAug = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPH = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PH 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%PH)) DEALLOCATE(OutData%PH) + ALLOCATE(OutData%PH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PH,1), UBOUND(OutData%PH,1) + OutData%PH(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NPM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PM 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%PM)) DEALLOCATE(OutData%PM) + ALLOCATE(OutData%PM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PM,2), UBOUND(OutData%PM,2) + DO i1 = LBOUND(OutData%PM,1), UBOUND(OutData%PM,1) + OutData%PM(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOF_Flag 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%DOF_Flag)) DEALLOCATE(OutData%DOF_Flag) + ALLOCATE(OutData%DOF_Flag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOF_Flag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DOF_Flag,1), UBOUND(OutData%DOF_Flag,1) + OutData%DOF_Flag(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%DOF_Flag(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOF_Desc 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%DOF_Desc)) DEALLOCATE(OutData%DOF_Desc) + ALLOCATE(OutData%DOF_Desc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOF_Desc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DOF_Desc,1), UBOUND(OutData%DOF_Desc,1) + DO I = 1, LEN(OutData%DOF_Desc) + OutData%DOF_Desc(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 ED_Unpackactivedofs( Re_Buf, Db_Buf, Int_Buf, OutData%DOFs, ErrStat2, ErrMsg2 ) ! DOFs + 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%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NBlGages = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NTwGages = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%AvgNrmTpRd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AzimB1Up = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CosDel3 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CosPreC 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%CosPreC)) DEALLOCATE(OutData%CosPreC) + ALLOCATE(OutData%CosPreC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CosPreC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CosPreC,1), UBOUND(OutData%CosPreC,1) + OutData%CosPreC(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%CRFrlSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CRFrlSkw2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CRFrlTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CRFrlTlt2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CShftSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CShftTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CSRFrlSkw = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CSRFrlTlt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CSTFrlSkw = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CSTFrlTlt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFinBank = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFinSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFinTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFrlSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFrlSkw2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFrlTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%CTFrlTlt2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%HubHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubCM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacCMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%OverHang = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ProjArea = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmRefzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefTwrHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlPntzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVDxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVDyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVDzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVIMUxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVIMUyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVIMUzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVPxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVPyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rVPzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWIxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWIyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWIzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWJxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWJyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWJzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWKxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWKyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rWKzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rZT0zt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rZYzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SinDel3 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SinPreC 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%SinPreC)) DEALLOCATE(OutData%SinPreC) + ALLOCATE(OutData%SinPreC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SinPreC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SinPreC,1), UBOUND(OutData%SinPreC,1) + OutData%SinPreC(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%SRFrlSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SRFrlSkw2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SRFrlTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SRFrlTlt2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SShftSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SShftTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFinBank = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFinSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFinTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFrlSkew = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFrlSkw2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFrlTilt = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%STFrlTlt2 = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%TFrlPntxn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlPntyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlPntzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TipRad = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TowerBsHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UndSling = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxRedTFA 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%AxRedTFA)) DEALLOCATE(OutData%AxRedTFA) + ALLOCATE(OutData%AxRedTFA(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%AxRedTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AxRedTFA,3), UBOUND(OutData%AxRedTFA,3) + DO i2 = LBOUND(OutData%AxRedTFA,2), UBOUND(OutData%AxRedTFA,2) + DO i1 = LBOUND(OutData%AxRedTFA,1), UBOUND(OutData%AxRedTFA,1) + OutData%AxRedTFA(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxRedTSS 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%AxRedTSS)) DEALLOCATE(OutData%AxRedTSS) + ALLOCATE(OutData%AxRedTSS(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%AxRedTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AxRedTSS,3), UBOUND(OutData%AxRedTSS,3) + DO i2 = LBOUND(OutData%AxRedTSS,2), UBOUND(OutData%AxRedTSS,2) + DO i1 = LBOUND(OutData%AxRedTSS,1), UBOUND(OutData%AxRedTSS,1) + OutData%AxRedTSS(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%CTFA,1) + i1_u = UBOUND(OutData%CTFA,1) + i2_l = LBOUND(OutData%CTFA,2) + i2_u = UBOUND(OutData%CTFA,2) + DO i2 = LBOUND(OutData%CTFA,2), UBOUND(OutData%CTFA,2) + DO i1 = LBOUND(OutData%CTFA,1), UBOUND(OutData%CTFA,1) + OutData%CTFA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%CTSS,1) + i1_u = UBOUND(OutData%CTSS,1) + i2_l = LBOUND(OutData%CTSS,2) + i2_u = UBOUND(OutData%CTSS,2) + DO i2 = LBOUND(OutData%CTSS,2), UBOUND(OutData%CTSS,2) + DO i1 = LBOUND(OutData%CTSS,1), UBOUND(OutData%CTSS,1) + OutData%CTSS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DHNodes 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%DHNodes)) DEALLOCATE(OutData%DHNodes) + ALLOCATE(OutData%DHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DHNodes,1), UBOUND(OutData%DHNodes,1) + OutData%DHNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HNodes 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%HNodes)) DEALLOCATE(OutData%HNodes) + ALLOCATE(OutData%HNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%HNodes,1), UBOUND(OutData%HNodes,1) + OutData%HNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HNodesNorm 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%HNodesNorm)) DEALLOCATE(OutData%HNodesNorm) + ALLOCATE(OutData%HNodesNorm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HNodesNorm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%HNodesNorm,1), UBOUND(OutData%HNodesNorm,1) + OutData%HNodesNorm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%KTFA,1) + i1_u = UBOUND(OutData%KTFA,1) + i2_l = LBOUND(OutData%KTFA,2) + i2_u = UBOUND(OutData%KTFA,2) + DO i2 = LBOUND(OutData%KTFA,2), UBOUND(OutData%KTFA,2) + DO i1 = LBOUND(OutData%KTFA,1), UBOUND(OutData%KTFA,1) + OutData%KTFA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%KTSS,1) + i1_u = UBOUND(OutData%KTSS,1) + i2_l = LBOUND(OutData%KTSS,2) + i2_u = UBOUND(OutData%KTSS,2) + DO i2 = LBOUND(OutData%KTSS,2), UBOUND(OutData%KTSS,2) + DO i1 = LBOUND(OutData%KTSS,1), UBOUND(OutData%KTSS,1) + OutData%KTSS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MassT 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%MassT)) DEALLOCATE(OutData%MassT) + ALLOCATE(OutData%MassT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MassT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MassT,1), UBOUND(OutData%MassT,1) + OutData%MassT(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffTSS 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%StiffTSS)) DEALLOCATE(OutData%StiffTSS) + ALLOCATE(OutData%StiffTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StiffTSS,1), UBOUND(OutData%StiffTSS,1) + OutData%StiffTSS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrFASF 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%TwrFASF)) DEALLOCATE(OutData%TwrFASF) + ALLOCATE(OutData%TwrFASF(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%TwrFASF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%TwrFASF,3), UBOUND(OutData%TwrFASF,3) + DO i2 = LBOUND(OutData%TwrFASF,2), UBOUND(OutData%TwrFASF,2) + DO i1 = LBOUND(OutData%TwrFASF,1), UBOUND(OutData%TwrFASF,1) + OutData%TwrFASF(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%TwrFlexL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrSSSF 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%TwrSSSF)) DEALLOCATE(OutData%TwrSSSF) + ALLOCATE(OutData%TwrSSSF(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%TwrSSSF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%TwrSSSF,3), UBOUND(OutData%TwrSSSF,3) + DO i2 = LBOUND(OutData%TwrSSSF,2), UBOUND(OutData%TwrSSSF,2) + DO i1 = LBOUND(OutData%TwrSSSF,1), UBOUND(OutData%TwrSSSF,1) + OutData%TwrSSSF(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%TTopNode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TwrNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InerTFA 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%InerTFA)) DEALLOCATE(OutData%InerTFA) + ALLOCATE(OutData%InerTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InerTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InerTFA,1), UBOUND(OutData%InerTFA,1) + OutData%InerTFA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InerTSS 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%InerTSS)) DEALLOCATE(OutData%InerTSS) + ALLOCATE(OutData%InerTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InerTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InerTSS,1), UBOUND(OutData%InerTSS,1) + OutData%InerTSS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffTGJ 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%StiffTGJ)) DEALLOCATE(OutData%StiffTGJ) + ALLOCATE(OutData%StiffTGJ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffTGJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StiffTGJ,1), UBOUND(OutData%StiffTGJ,1) + OutData%StiffTGJ(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffTEA 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%StiffTEA)) DEALLOCATE(OutData%StiffTEA) + ALLOCATE(OutData%StiffTEA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffTEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StiffTEA,1), UBOUND(OutData%StiffTEA,1) + OutData%StiffTEA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffTFA 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%StiffTFA)) DEALLOCATE(OutData%StiffTFA) + ALLOCATE(OutData%StiffTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StiffTFA,1), UBOUND(OutData%StiffTFA,1) + OutData%StiffTFA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! cgOffTFA 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%cgOffTFA)) DEALLOCATE(OutData%cgOffTFA) + ALLOCATE(OutData%cgOffTFA(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%cgOffTFA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%cgOffTFA,1), UBOUND(OutData%cgOffTFA,1) + OutData%cgOffTFA(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! cgOffTSS 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%cgOffTSS)) DEALLOCATE(OutData%cgOffTSS) + ALLOCATE(OutData%cgOffTSS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%cgOffTSS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%cgOffTSS,1), UBOUND(OutData%cgOffTSS,1) + OutData%cgOffTSS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%AtfaIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldCG 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%BldCG)) DEALLOCATE(OutData%BldCG) + ALLOCATE(OutData%BldCG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldCG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldCG,1), UBOUND(OutData%BldCG,1) + OutData%BldCG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldMass 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%BldMass)) DEALLOCATE(OutData%BldMass) + ALLOCATE(OutData%BldMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldMass,1), UBOUND(OutData%BldMass,1) + OutData%BldMass(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%BoomMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FirstMom 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%FirstMom)) DEALLOCATE(OutData%FirstMom) + ALLOCATE(OutData%FirstMom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FirstMom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FirstMom,1), UBOUND(OutData%FirstMom,1) + OutData%FirstMom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%GenIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Hubg1Iner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Hubg2Iner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HubMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Nacd2Iner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmPIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmRIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmYIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RrfaIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SecondMom 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%SecondMom)) DEALLOCATE(OutData%SecondMom) + ALLOCATE(OutData%SecondMom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SecondMom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SecondMom,1), UBOUND(OutData%SecondMom,1) + OutData%SecondMom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%TFinMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlIner = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TipMass 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%TipMass)) DEALLOCATE(OutData%TipMass) + ALLOCATE(OutData%TipMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TipMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TipMass,1), UBOUND(OutData%TipMass,1) + OutData%TipMass(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%TurbMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TwrMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TwrTpMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMass = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PitchAxis 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%PitchAxis)) DEALLOCATE(OutData%PitchAxis) + ALLOCATE(OutData%PitchAxis(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PitchAxis.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PitchAxis,2), UBOUND(OutData%PitchAxis,2) + DO i1 = LBOUND(OutData%PitchAxis,1), UBOUND(OutData%PitchAxis,1) + OutData%PitchAxis(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AeroTwst 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%AeroTwst)) DEALLOCATE(OutData%AeroTwst) + ALLOCATE(OutData%AeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AeroTwst,1), UBOUND(OutData%AeroTwst,1) + OutData%AeroTwst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxRedBld 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%AxRedBld)) DEALLOCATE(OutData%AxRedBld) + ALLOCATE(OutData%AxRedBld(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%AxRedBld.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%AxRedBld,4), UBOUND(OutData%AxRedBld,4) + DO i3 = LBOUND(OutData%AxRedBld,3), UBOUND(OutData%AxRedBld,3) + DO i2 = LBOUND(OutData%AxRedBld,2), UBOUND(OutData%AxRedBld,2) + DO i1 = LBOUND(OutData%AxRedBld,1), UBOUND(OutData%AxRedBld,1) + OutData%AxRedBld(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BAlpha 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%BAlpha)) DEALLOCATE(OutData%BAlpha) + ALLOCATE(OutData%BAlpha(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BAlpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BAlpha,2), UBOUND(OutData%BAlpha,2) + DO i1 = LBOUND(OutData%BAlpha,1), UBOUND(OutData%BAlpha,1) + OutData%BAlpha(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldEDamp 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%BldEDamp)) DEALLOCATE(OutData%BldEDamp) + ALLOCATE(OutData%BldEDamp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldEDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldEDamp,2), UBOUND(OutData%BldEDamp,2) + DO i1 = LBOUND(OutData%BldEDamp,1), UBOUND(OutData%BldEDamp,1) + OutData%BldEDamp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldFDamp 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%BldFDamp)) DEALLOCATE(OutData%BldFDamp) + ALLOCATE(OutData%BldFDamp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldFDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldFDamp,2), UBOUND(OutData%BldFDamp,2) + DO i1 = LBOUND(OutData%BldFDamp,1), UBOUND(OutData%BldFDamp,1) + OutData%BldFDamp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%BldFlexL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CAeroTwst 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%CAeroTwst)) DEALLOCATE(OutData%CAeroTwst) + ALLOCATE(OutData%CAeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CAeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CAeroTwst,1), UBOUND(OutData%CAeroTwst,1) + OutData%CAeroTwst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBE 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%CBE)) DEALLOCATE(OutData%CBE) + ALLOCATE(OutData%CBE(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%CBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CBE,3), UBOUND(OutData%CBE,3) + DO i2 = LBOUND(OutData%CBE,2), UBOUND(OutData%CBE,2) + DO i1 = LBOUND(OutData%CBE,1), UBOUND(OutData%CBE,1) + OutData%CBE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBF 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%CBF)) DEALLOCATE(OutData%CBF) + ALLOCATE(OutData%CBF(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%CBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%CBF,3), UBOUND(OutData%CBF,3) + DO i2 = LBOUND(OutData%CBF,2), UBOUND(OutData%CBF,2) + DO i1 = LBOUND(OutData%CBF,1), UBOUND(OutData%CBF,1) + OutData%CBF(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! cgOffBEdg 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%cgOffBEdg)) DEALLOCATE(OutData%cgOffBEdg) + ALLOCATE(OutData%cgOffBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%cgOffBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%cgOffBEdg,2), UBOUND(OutData%cgOffBEdg,2) + DO i1 = LBOUND(OutData%cgOffBEdg,1), UBOUND(OutData%cgOffBEdg,1) + OutData%cgOffBEdg(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! cgOffBFlp 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%cgOffBFlp)) DEALLOCATE(OutData%cgOffBFlp) + ALLOCATE(OutData%cgOffBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%cgOffBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%cgOffBFlp,2), UBOUND(OutData%cgOffBFlp,2) + DO i1 = LBOUND(OutData%cgOffBFlp,1), UBOUND(OutData%cgOffBFlp,1) + OutData%cgOffBFlp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Chord 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%Chord)) DEALLOCATE(OutData%Chord) + ALLOCATE(OutData%Chord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Chord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Chord,1), UBOUND(OutData%Chord,1) + OutData%Chord(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CThetaS 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%CThetaS)) DEALLOCATE(OutData%CThetaS) + ALLOCATE(OutData%CThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CThetaS,2), UBOUND(OutData%CThetaS,2) + DO i1 = LBOUND(OutData%CThetaS,1), UBOUND(OutData%CThetaS,1) + OutData%CThetaS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DRNodes 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%DRNodes)) DEALLOCATE(OutData%DRNodes) + ALLOCATE(OutData%DRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DRNodes,1), UBOUND(OutData%DRNodes,1) + OutData%DRNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EAOffBEdg 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%EAOffBEdg)) DEALLOCATE(OutData%EAOffBEdg) + ALLOCATE(OutData%EAOffBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EAOffBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%EAOffBEdg,2), UBOUND(OutData%EAOffBEdg,2) + DO i1 = LBOUND(OutData%EAOffBEdg,1), UBOUND(OutData%EAOffBEdg,1) + OutData%EAOffBEdg(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! EAOffBFlp 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%EAOffBFlp)) DEALLOCATE(OutData%EAOffBFlp) + ALLOCATE(OutData%EAOffBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%EAOffBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%EAOffBFlp,2), UBOUND(OutData%EAOffBFlp,2) + DO i1 = LBOUND(OutData%EAOffBFlp,1), UBOUND(OutData%EAOffBFlp,1) + OutData%EAOffBFlp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FStTunr 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%FStTunr)) DEALLOCATE(OutData%FStTunr) + ALLOCATE(OutData%FStTunr(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FStTunr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FStTunr,2), UBOUND(OutData%FStTunr,2) + DO i1 = LBOUND(OutData%FStTunr,1), UBOUND(OutData%FStTunr,1) + OutData%FStTunr(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InerBEdg 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%InerBEdg)) DEALLOCATE(OutData%InerBEdg) + ALLOCATE(OutData%InerBEdg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InerBEdg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InerBEdg,2), UBOUND(OutData%InerBEdg,2) + DO i1 = LBOUND(OutData%InerBEdg,1), UBOUND(OutData%InerBEdg,1) + OutData%InerBEdg(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InerBFlp 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%InerBFlp)) DEALLOCATE(OutData%InerBFlp) + ALLOCATE(OutData%InerBFlp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InerBFlp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InerBFlp,2), UBOUND(OutData%InerBFlp,2) + DO i1 = LBOUND(OutData%InerBFlp,1), UBOUND(OutData%InerBFlp,1) + OutData%InerBFlp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBE 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%KBE)) DEALLOCATE(OutData%KBE) + ALLOCATE(OutData%KBE(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%KBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%KBE,3), UBOUND(OutData%KBE,3) + DO i2 = LBOUND(OutData%KBE,2), UBOUND(OutData%KBE,2) + DO i1 = LBOUND(OutData%KBE,1), UBOUND(OutData%KBE,1) + OutData%KBE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBF 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%KBF)) DEALLOCATE(OutData%KBF) + ALLOCATE(OutData%KBF(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%KBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%KBF,3), UBOUND(OutData%KBF,3) + DO i2 = LBOUND(OutData%KBF,2), UBOUND(OutData%KBF,2) + DO i1 = LBOUND(OutData%KBF,1), UBOUND(OutData%KBF,1) + OutData%KBF(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MassB 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%MassB)) DEALLOCATE(OutData%MassB) + ALLOCATE(OutData%MassB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MassB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MassB,2), UBOUND(OutData%MassB,2) + DO i1 = LBOUND(OutData%MassB,1), UBOUND(OutData%MassB,1) + OutData%MassB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RefAxisxb 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%RefAxisxb)) DEALLOCATE(OutData%RefAxisxb) + ALLOCATE(OutData%RefAxisxb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RefAxisxb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RefAxisxb,2), UBOUND(OutData%RefAxisxb,2) + DO i1 = LBOUND(OutData%RefAxisxb,1), UBOUND(OutData%RefAxisxb,1) + OutData%RefAxisxb(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RefAxisyb 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%RefAxisyb)) DEALLOCATE(OutData%RefAxisyb) + ALLOCATE(OutData%RefAxisyb(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RefAxisyb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%RefAxisyb,2), UBOUND(OutData%RefAxisyb,2) + DO i1 = LBOUND(OutData%RefAxisyb,1), UBOUND(OutData%RefAxisyb,1) + OutData%RefAxisyb(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RNodes 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%RNodes)) DEALLOCATE(OutData%RNodes) + ALLOCATE(OutData%RNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RNodes,1), UBOUND(OutData%RNodes,1) + OutData%RNodes(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RNodesNorm 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%RNodesNorm)) DEALLOCATE(OutData%RNodesNorm) + ALLOCATE(OutData%RNodesNorm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RNodesNorm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RNodesNorm,1), UBOUND(OutData%RNodesNorm,1) + OutData%RNodesNorm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rSAerCenn1 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%rSAerCenn1)) DEALLOCATE(OutData%rSAerCenn1) + ALLOCATE(OutData%rSAerCenn1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rSAerCenn1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rSAerCenn1,2), UBOUND(OutData%rSAerCenn1,2) + DO i1 = LBOUND(OutData%rSAerCenn1,1), UBOUND(OutData%rSAerCenn1,1) + OutData%rSAerCenn1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rSAerCenn2 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%rSAerCenn2)) DEALLOCATE(OutData%rSAerCenn2) + ALLOCATE(OutData%rSAerCenn2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rSAerCenn2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rSAerCenn2,2), UBOUND(OutData%rSAerCenn2,2) + DO i1 = LBOUND(OutData%rSAerCenn2,1), UBOUND(OutData%rSAerCenn2,1) + OutData%rSAerCenn2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SAeroTwst 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%SAeroTwst)) DEALLOCATE(OutData%SAeroTwst) + ALLOCATE(OutData%SAeroTwst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SAeroTwst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SAeroTwst,1), UBOUND(OutData%SAeroTwst,1) + OutData%SAeroTwst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffBE 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%StiffBE)) DEALLOCATE(OutData%StiffBE) + ALLOCATE(OutData%StiffBE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StiffBE,2), UBOUND(OutData%StiffBE,2) + DO i1 = LBOUND(OutData%StiffBE,1), UBOUND(OutData%StiffBE,1) + OutData%StiffBE(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffBEA 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%StiffBEA)) DEALLOCATE(OutData%StiffBEA) + ALLOCATE(OutData%StiffBEA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffBEA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StiffBEA,2), UBOUND(OutData%StiffBEA,2) + DO i1 = LBOUND(OutData%StiffBEA,1), UBOUND(OutData%StiffBEA,1) + OutData%StiffBEA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffBF 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%StiffBF)) DEALLOCATE(OutData%StiffBF) + ALLOCATE(OutData%StiffBF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StiffBF,2), UBOUND(OutData%StiffBF,2) + DO i1 = LBOUND(OutData%StiffBF,1), UBOUND(OutData%StiffBF,1) + OutData%StiffBF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StiffBGJ 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%StiffBGJ)) DEALLOCATE(OutData%StiffBGJ) + ALLOCATE(OutData%StiffBGJ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StiffBGJ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StiffBGJ,2), UBOUND(OutData%StiffBGJ,2) + DO i1 = LBOUND(OutData%StiffBGJ,1), UBOUND(OutData%StiffBGJ,1) + OutData%StiffBGJ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SThetaS 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%SThetaS)) DEALLOCATE(OutData%SThetaS) + ALLOCATE(OutData%SThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%SThetaS,2), UBOUND(OutData%SThetaS,2) + DO i1 = LBOUND(OutData%SThetaS,1), UBOUND(OutData%SThetaS,1) + OutData%SThetaS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ThetaS 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%ThetaS)) DEALLOCATE(OutData%ThetaS) + ALLOCATE(OutData%ThetaS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ThetaS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ThetaS,2), UBOUND(OutData%ThetaS,2) + DO i1 = LBOUND(OutData%ThetaS,1), UBOUND(OutData%ThetaS,1) + OutData%ThetaS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwistedSF 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%TwistedSF)) DEALLOCATE(OutData%TwistedSF) + ALLOCATE(OutData%TwistedSF(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%TwistedSF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i5 = LBOUND(OutData%TwistedSF,5), UBOUND(OutData%TwistedSF,5) + DO i4 = LBOUND(OutData%TwistedSF,4), UBOUND(OutData%TwistedSF,4) + DO i3 = LBOUND(OutData%TwistedSF,3), UBOUND(OutData%TwistedSF,3) + DO i2 = LBOUND(OutData%TwistedSF,2), UBOUND(OutData%TwistedSF,2) + DO i1 = LBOUND(OutData%TwistedSF,1), UBOUND(OutData%TwistedSF,1) + OutData%TwistedSF(i1,i2,i3,i4,i5) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldFl1Sh 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%BldFl1Sh)) DEALLOCATE(OutData%BldFl1Sh) + ALLOCATE(OutData%BldFl1Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldFl1Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldFl1Sh,2), UBOUND(OutData%BldFl1Sh,2) + DO i1 = LBOUND(OutData%BldFl1Sh,1), UBOUND(OutData%BldFl1Sh,1) + OutData%BldFl1Sh(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldFl2Sh 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%BldFl2Sh)) DEALLOCATE(OutData%BldFl2Sh) + ALLOCATE(OutData%BldFl2Sh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldFl2Sh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldFl2Sh,2), UBOUND(OutData%BldFl2Sh,2) + DO i1 = LBOUND(OutData%BldFl2Sh,1), UBOUND(OutData%BldFl2Sh,1) + OutData%BldFl2Sh(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldEdgSh 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%BldEdgSh)) DEALLOCATE(OutData%BldEdgSh) + ALLOCATE(OutData%BldEdgSh(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldEdgSh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BldEdgSh,2), UBOUND(OutData%BldEdgSh,2) + DO i1 = LBOUND(OutData%BldEdgSh,1), UBOUND(OutData%BldEdgSh,1) + OutData%BldEdgSh(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FreqBE 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%FreqBE)) DEALLOCATE(OutData%FreqBE) + ALLOCATE(OutData%FreqBE(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%FreqBE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FreqBE,3), UBOUND(OutData%FreqBE,3) + DO i2 = LBOUND(OutData%FreqBE,2), UBOUND(OutData%FreqBE,2) + DO i1 = LBOUND(OutData%FreqBE,1), UBOUND(OutData%FreqBE,1) + OutData%FreqBE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FreqBF 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%FreqBF)) DEALLOCATE(OutData%FreqBF) + ALLOCATE(OutData%FreqBF(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%FreqBF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FreqBF,3), UBOUND(OutData%FreqBF,3) + DO i2 = LBOUND(OutData%FreqBF,2), UBOUND(OutData%FreqBF,2) + DO i1 = LBOUND(OutData%FreqBF,1), UBOUND(OutData%FreqBF,1) + OutData%FreqBF(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%FreqTFA,1) + i1_u = UBOUND(OutData%FreqTFA,1) + i2_l = LBOUND(OutData%FreqTFA,2) + i2_u = UBOUND(OutData%FreqTFA,2) + DO i2 = LBOUND(OutData%FreqTFA,2), UBOUND(OutData%FreqTFA,2) + DO i1 = LBOUND(OutData%FreqTFA,1), UBOUND(OutData%FreqTFA,1) + OutData%FreqTFA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%FreqTSS,1) + i1_u = UBOUND(OutData%FreqTSS,1) + i2_l = LBOUND(OutData%FreqTSS,2) + i2_u = UBOUND(OutData%FreqTSS,2) + DO i2 = LBOUND(OutData%FreqTSS,2), UBOUND(OutData%FreqTSS,2) + DO i1 = LBOUND(OutData%FreqTSS,1), UBOUND(OutData%FreqTSS,1) + OutData%FreqTSS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%TeetCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetDmpP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetHSSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetHStP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetSSSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetSStP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TeetMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TFrlCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlDSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlUSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TFrlMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RFrlCDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlDSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSDP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlUSSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RFrlMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ShftGagL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%BldGagNd,1) + i1_u = UBOUND(OutData%BldGagNd,1) + DO i1 = LBOUND(OutData%BldGagNd,1), UBOUND(OutData%BldGagNd,1) + OutData%BldGagNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%TwrGagNd,1) + i1_u = UBOUND(OutData%TwrGagNd,1) + DO i1 = LBOUND(OutData%TwrGagNd,1), UBOUND(OutData%TwrGagNd,1) + OutData%TwrGagNd(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%TStart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DTTorDmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DTTorSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GBRatio = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GBoxEff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BElmntMass 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%BElmntMass)) DEALLOCATE(OutData%BElmntMass) + ALLOCATE(OutData%BElmntMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BElmntMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BElmntMass,2), UBOUND(OutData%BElmntMass,2) + DO i1 = LBOUND(OutData%BElmntMass,1), UBOUND(OutData%BElmntMass,1) + OutData%BElmntMass(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TElmntMass 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%TElmntMass)) DEALLOCATE(OutData%TElmntMass) + ALLOCATE(OutData%TElmntMass(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TElmntMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TElmntMass,1), UBOUND(OutData%TElmntMass,1) + OutData%TElmntMass(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%method = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmCMxt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCMyt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BD4Blades = TRANSFER(IntKiBuf(Int_Xferred), OutData%BD4Blades) + Int_Xferred = Int_Xferred + 1 + OutData%UseAD14 = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseAD14) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BldNd_TotNumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BldNd_OutParam 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%BldNd_OutParam)) DEALLOCATE(OutData%BldNd_OutParam) + ALLOCATE(OutData%BldNd_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BldNd_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BldNd_OutParam,1), UBOUND(OutData%BldNd_OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%BldNd_OutParam(i1), ErrStat2, ErrMsg2 ) ! BldNd_OutParam + 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 DO + END IF + OutData%BldNd_BladesOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du 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%du)) DEALLOCATE(OutData%du) + ALLOCATE(OutData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%du,1), UBOUND(OutData%du,1) + OutData%du(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dx 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%dx)) DEALLOCATE(OutData%dx) + ALLOCATE(OutData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dx,1), UBOUND(OutData%dx,1) + OutData%dx(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ED_UnPackParam + + SUBROUTINE ED_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_InputType), INTENT(INOUT) :: SrcInputData + TYPE(ED_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) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%BladePtLoads)) THEN + i1_l = LBOUND(SrcInputData%BladePtLoads,1) + i1_u = UBOUND(SrcInputData%BladePtLoads,1) + IF (.NOT. ALLOCATED(DstInputData%BladePtLoads)) THEN + ALLOCATE(DstInputData%BladePtLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%BladePtLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInputData%BladePtLoads,1), UBOUND(SrcInputData%BladePtLoads,1) + CALL MeshCopy( SrcInputData%BladePtLoads(i1), DstInputData%BladePtLoads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcInputData%PlatformPtMesh, DstInputData%PlatformPtMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%TowerPtLoads, DstInputData%TowerPtLoads, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%HubPtLoad, DstInputData%HubPtLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%NacelleLoads, DstInputData%NacelleLoads, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%TwrAddedMass)) THEN + i1_l = LBOUND(SrcInputData%TwrAddedMass,1) + i1_u = UBOUND(SrcInputData%TwrAddedMass,1) + i2_l = LBOUND(SrcInputData%TwrAddedMass,2) + i2_u = UBOUND(SrcInputData%TwrAddedMass,2) + i3_l = LBOUND(SrcInputData%TwrAddedMass,3) + i3_u = UBOUND(SrcInputData%TwrAddedMass,3) + IF (.NOT. ALLOCATED(DstInputData%TwrAddedMass)) THEN + ALLOCATE(DstInputData%TwrAddedMass(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%TwrAddedMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%TwrAddedMass = SrcInputData%TwrAddedMass +ENDIF + DstInputData%PtfmAddedMass = SrcInputData%PtfmAddedMass +IF (ALLOCATED(SrcInputData%BlPitchCom)) THEN + i1_l = LBOUND(SrcInputData%BlPitchCom,1) + i1_u = UBOUND(SrcInputData%BlPitchCom,1) + IF (.NOT. ALLOCATED(DstInputData%BlPitchCom)) THEN + ALLOCATE(DstInputData%BlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%BlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%BlPitchCom = SrcInputData%BlPitchCom +ENDIF + DstInputData%YawMom = SrcInputData%YawMom + DstInputData%GenTrq = SrcInputData%GenTrq + DstInputData%HSSBrTrqC = SrcInputData%HSSBrTrqC + END SUBROUTINE ED_CopyInput + + SUBROUTINE ED_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(ED_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%BladePtLoads)) THEN +DO i1 = LBOUND(InputData%BladePtLoads,1), UBOUND(InputData%BladePtLoads,1) + CALL MeshDestroy( InputData%BladePtLoads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InputData%BladePtLoads) +ENDIF + CALL MeshDestroy( InputData%PlatformPtMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%TowerPtLoads, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%HubPtLoad, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%NacelleLoads, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%TwrAddedMass)) THEN + DEALLOCATE(InputData%TwrAddedMass) +ENDIF +IF (ALLOCATED(InputData%BlPitchCom)) THEN + DEALLOCATE(InputData%BlPitchCom) +ENDIF + END SUBROUTINE ED_DestroyInput + + SUBROUTINE ED_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(ED_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 = 'ED_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 ! BladePtLoads allocated yes/no + IF ( ALLOCATED(InData%BladePtLoads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladePtLoads upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%BladePtLoads,1), UBOUND(InData%BladePtLoads,1) + Int_BufSz = Int_BufSz + 3 ! BladePtLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladePtLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladePtLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladePtLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladePtLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladePtLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! PlatformPtMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PlatformPtMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PlatformPtMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PlatformPtMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PlatformPtMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TowerPtLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%TowerPtLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TowerPtLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TowerPtLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TowerPtLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TowerPtLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HubPtLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubPtLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubPtLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubPtLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubPtLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! NacelleLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%NacelleLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! NacelleLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NacelleLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NacelleLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NacelleLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! TwrAddedMass allocated yes/no + IF ( ALLOCATED(InData%TwrAddedMass) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! TwrAddedMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TwrAddedMass) ! TwrAddedMass + END IF + Re_BufSz = Re_BufSz + SIZE(InData%PtfmAddedMass) ! PtfmAddedMass + Int_BufSz = Int_BufSz + 1 ! BlPitchCom allocated yes/no + IF ( ALLOCATED(InData%BlPitchCom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchCom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchCom) ! BlPitchCom + END IF + Re_BufSz = Re_BufSz + 1 ! YawMom + Re_BufSz = Re_BufSz + 1 ! GenTrq + Re_BufSz = Re_BufSz + 1 ! HSSBrTrqC + 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%BladePtLoads) ) 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%BladePtLoads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladePtLoads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladePtLoads,1), UBOUND(InData%BladePtLoads,1) + CALL MeshPack( InData%BladePtLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladePtLoads + 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 + CALL MeshPack( InData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PlatformPtMesh + 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 MeshPack( InData%TowerPtLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TowerPtLoads + 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 MeshPack( InData%HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubPtLoad + 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 MeshPack( InData%NacelleLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! NacelleLoads + 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%TwrAddedMass) ) 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%TwrAddedMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrAddedMass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrAddedMass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrAddedMass,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TwrAddedMass,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TwrAddedMass,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%TwrAddedMass,3), UBOUND(InData%TwrAddedMass,3) + DO i2 = LBOUND(InData%TwrAddedMass,2), UBOUND(InData%TwrAddedMass,2) + DO i1 = LBOUND(InData%TwrAddedMass,1), UBOUND(InData%TwrAddedMass,1) + ReKiBuf(Re_Xferred) = InData%TwrAddedMass(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i2 = LBOUND(InData%PtfmAddedMass,2), UBOUND(InData%PtfmAddedMass,2) + DO i1 = LBOUND(InData%PtfmAddedMass,1), UBOUND(InData%PtfmAddedMass,1) + ReKiBuf(Re_Xferred) = InData%PtfmAddedMass(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%BlPitchCom) ) 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%BlPitchCom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchCom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchCom,1), UBOUND(InData%BlPitchCom,1) + ReKiBuf(Re_Xferred) = InData%BlPitchCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%YawMom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenTrq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSSBrTrqC + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ED_PackInput + + SUBROUTINE ED_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(ED_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) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ED_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 ! BladePtLoads 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%BladePtLoads)) DEALLOCATE(OutData%BladePtLoads) + ALLOCATE(OutData%BladePtLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladePtLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladePtLoads,1), UBOUND(OutData%BladePtLoads,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 MeshUnpack( OutData%BladePtLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladePtLoads + 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 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 MeshUnpack( OutData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PlatformPtMesh + 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 MeshUnpack( OutData%TowerPtLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TowerPtLoads + 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 MeshUnpack( OutData%HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubPtLoad + 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 MeshUnpack( OutData%NacelleLoads, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! NacelleLoads + 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 ! TwrAddedMass 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%TwrAddedMass)) DEALLOCATE(OutData%TwrAddedMass) + ALLOCATE(OutData%TwrAddedMass(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%TwrAddedMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%TwrAddedMass,3), UBOUND(OutData%TwrAddedMass,3) + DO i2 = LBOUND(OutData%TwrAddedMass,2), UBOUND(OutData%TwrAddedMass,2) + DO i1 = LBOUND(OutData%TwrAddedMass,1), UBOUND(OutData%TwrAddedMass,1) + OutData%TwrAddedMass(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%PtfmAddedMass,1) + i1_u = UBOUND(OutData%PtfmAddedMass,1) + i2_l = LBOUND(OutData%PtfmAddedMass,2) + i2_u = UBOUND(OutData%PtfmAddedMass,2) + DO i2 = LBOUND(OutData%PtfmAddedMass,2), UBOUND(OutData%PtfmAddedMass,2) + DO i1 = LBOUND(OutData%PtfmAddedMass,1), UBOUND(OutData%PtfmAddedMass,1) + OutData%PtfmAddedMass(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchCom 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%BlPitchCom)) DEALLOCATE(OutData%BlPitchCom) + ALLOCATE(OutData%BlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchCom,1), UBOUND(OutData%BlPitchCom,1) + OutData%BlPitchCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%YawMom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSSBrTrqC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ED_UnPackInput + + SUBROUTINE ED_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ED_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(ED_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'ED_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%BladeLn2Mesh)) THEN + i1_l = LBOUND(SrcOutputData%BladeLn2Mesh,1) + i1_u = UBOUND(SrcOutputData%BladeLn2Mesh,1) + IF (.NOT. ALLOCATED(DstOutputData%BladeLn2Mesh)) THEN + ALLOCATE(DstOutputData%BladeLn2Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BladeLn2Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOutputData%BladeLn2Mesh,1), UBOUND(SrcOutputData%BladeLn2Mesh,1) + CALL MeshCopy( SrcOutputData%BladeLn2Mesh(i1), DstOutputData%BladeLn2Mesh(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcOutputData%PlatformPtMesh, DstOutputData%PlatformPtMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%TowerLn2Mesh, DstOutputData%TowerLn2Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%HubPtMotion14, DstOutputData%HubPtMotion14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%HubPtMotion, DstOutputData%HubPtMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%BladeRootMotion14, DstOutputData%BladeRootMotion14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%BladeRootMotion)) THEN + i1_l = LBOUND(SrcOutputData%BladeRootMotion,1) + i1_u = UBOUND(SrcOutputData%BladeRootMotion,1) + IF (.NOT. ALLOCATED(DstOutputData%BladeRootMotion)) THEN + ALLOCATE(DstOutputData%BladeRootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BladeRootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOutputData%BladeRootMotion,1), UBOUND(SrcOutputData%BladeRootMotion,1) + CALL MeshCopy( SrcOutputData%BladeRootMotion(i1), DstOutputData%BladeRootMotion(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcOutputData%RotorFurlMotion14, DstOutputData%RotorFurlMotion14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%NacelleMotion, DstOutputData%NacelleMotion, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%TowerBaseMotion14, DstOutputData%TowerBaseMotion14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF +IF (ALLOCATED(SrcOutputData%BlPitch)) THEN + i1_l = LBOUND(SrcOutputData%BlPitch,1) + i1_u = UBOUND(SrcOutputData%BlPitch,1) + IF (.NOT. ALLOCATED(DstOutputData%BlPitch)) THEN + ALLOCATE(DstOutputData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%BlPitch = SrcOutputData%BlPitch +ENDIF + DstOutputData%Yaw = SrcOutputData%Yaw + DstOutputData%YawRate = SrcOutputData%YawRate + DstOutputData%LSS_Spd = SrcOutputData%LSS_Spd + DstOutputData%HSS_Spd = SrcOutputData%HSS_Spd + DstOutputData%RotSpeed = SrcOutputData%RotSpeed + DstOutputData%TwrAccel = SrcOutputData%TwrAccel + DstOutputData%YawAngle = SrcOutputData%YawAngle + DstOutputData%RootMyc = SrcOutputData%RootMyc + DstOutputData%YawBrTAxp = SrcOutputData%YawBrTAxp + DstOutputData%YawBrTAyp = SrcOutputData%YawBrTAyp + DstOutputData%LSSTipPxa = SrcOutputData%LSSTipPxa + DstOutputData%RootMxc = SrcOutputData%RootMxc + DstOutputData%LSSTipMxa = SrcOutputData%LSSTipMxa + DstOutputData%LSSTipMya = SrcOutputData%LSSTipMya + DstOutputData%LSSTipMza = SrcOutputData%LSSTipMza + DstOutputData%LSSTipMys = SrcOutputData%LSSTipMys + DstOutputData%LSSTipMzs = SrcOutputData%LSSTipMzs + DstOutputData%YawBrMyn = SrcOutputData%YawBrMyn + DstOutputData%YawBrMzn = SrcOutputData%YawBrMzn + DstOutputData%NcIMURAxs = SrcOutputData%NcIMURAxs + DstOutputData%NcIMURAys = SrcOutputData%NcIMURAys + DstOutputData%NcIMURAzs = SrcOutputData%NcIMURAzs + DstOutputData%RotPwr = SrcOutputData%RotPwr + END SUBROUTINE ED_CopyOutput + + SUBROUTINE ED_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(ED_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ED_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%BladeLn2Mesh)) THEN +DO i1 = LBOUND(OutputData%BladeLn2Mesh,1), UBOUND(OutputData%BladeLn2Mesh,1) + CALL MeshDestroy( OutputData%BladeLn2Mesh(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OutputData%BladeLn2Mesh) +ENDIF + CALL MeshDestroy( OutputData%PlatformPtMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%TowerLn2Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%HubPtMotion14, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%HubPtMotion, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%BladeRootMotion14, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%BladeRootMotion)) THEN +DO i1 = LBOUND(OutputData%BladeRootMotion,1), UBOUND(OutputData%BladeRootMotion,1) + CALL MeshDestroy( OutputData%BladeRootMotion(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OutputData%BladeRootMotion) +ENDIF + CALL MeshDestroy( OutputData%RotorFurlMotion14, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%NacelleMotion, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%TowerBaseMotion14, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF +IF (ALLOCATED(OutputData%BlPitch)) THEN + DEALLOCATE(OutputData%BlPitch) +ENDIF + END SUBROUTINE ED_DestroyOutput + + SUBROUTINE ED_PackOutput( 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(ED_OutputType), 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 = 'ED_PackOutput' + ! 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 ! BladeLn2Mesh allocated yes/no + IF ( ALLOCATED(InData%BladeLn2Mesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeLn2Mesh upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%BladeLn2Mesh,1), UBOUND(InData%BladeLn2Mesh,1) + Int_BufSz = Int_BufSz + 3 ! BladeLn2Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeLn2Mesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeLn2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeLn2Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeLn2Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeLn2Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! PlatformPtMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PlatformPtMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PlatformPtMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PlatformPtMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PlatformPtMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TowerLn2Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%TowerLn2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TowerLn2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TowerLn2Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TowerLn2Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TowerLn2Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HubPtMotion14: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubPtMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubPtMotion14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubPtMotion14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubPtMotion14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubPtMotion14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HubPtMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%HubPtMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HubPtMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HubPtMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HubPtMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HubPtMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! BladeRootMotion14: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeRootMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeRootMotion14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeRootMotion14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeRootMotion14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeRootMotion14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! BladeRootMotion allocated yes/no + IF ( ALLOCATED(InData%BladeRootMotion) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeRootMotion upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BladeRootMotion,1), UBOUND(InData%BladeRootMotion,1) + Int_BufSz = Int_BufSz + 3 ! BladeRootMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! BladeRootMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeRootMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeRootMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeRootMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! RotorFurlMotion14: size of buffers for each call to pack subtype + CALL MeshPack( InData%RotorFurlMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! RotorFurlMotion14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RotorFurlMotion14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RotorFurlMotion14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RotorFurlMotion14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! NacelleMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%NacelleMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! NacelleMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NacelleMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NacelleMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NacelleMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TowerBaseMotion14: size of buffers for each call to pack subtype + CALL MeshPack( InData%TowerBaseMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TowerBaseMotion14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TowerBaseMotion14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TowerBaseMotion14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TowerBaseMotion14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + Int_BufSz = Int_BufSz + 1 ! BlPitch allocated yes/no + IF ( ALLOCATED(InData%BlPitch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitch) ! BlPitch + END IF + Re_BufSz = Re_BufSz + 1 ! Yaw + Re_BufSz = Re_BufSz + 1 ! YawRate + Re_BufSz = Re_BufSz + 1 ! LSS_Spd + Re_BufSz = Re_BufSz + 1 ! HSS_Spd + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Re_BufSz = Re_BufSz + 1 ! TwrAccel + Re_BufSz = Re_BufSz + 1 ! YawAngle + Re_BufSz = Re_BufSz + SIZE(InData%RootMyc) ! RootMyc + Re_BufSz = Re_BufSz + 1 ! YawBrTAxp + Re_BufSz = Re_BufSz + 1 ! YawBrTAyp + Re_BufSz = Re_BufSz + 1 ! LSSTipPxa + Re_BufSz = Re_BufSz + SIZE(InData%RootMxc) ! RootMxc + Re_BufSz = Re_BufSz + 1 ! LSSTipMxa + Re_BufSz = Re_BufSz + 1 ! LSSTipMya + Re_BufSz = Re_BufSz + 1 ! LSSTipMza + Re_BufSz = Re_BufSz + 1 ! LSSTipMys + Re_BufSz = Re_BufSz + 1 ! LSSTipMzs + Re_BufSz = Re_BufSz + 1 ! YawBrMyn + Re_BufSz = Re_BufSz + 1 ! YawBrMzn + Re_BufSz = Re_BufSz + 1 ! NcIMURAxs + Re_BufSz = Re_BufSz + 1 ! NcIMURAys + Re_BufSz = Re_BufSz + 1 ! NcIMURAzs + Re_BufSz = Re_BufSz + 1 ! RotPwr + 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%BladeLn2Mesh) ) 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%BladeLn2Mesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeLn2Mesh,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeLn2Mesh,1), UBOUND(InData%BladeLn2Mesh,1) + CALL MeshPack( InData%BladeLn2Mesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeLn2Mesh + 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 + CALL MeshPack( InData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PlatformPtMesh + 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 MeshPack( InData%TowerLn2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TowerLn2Mesh + 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 MeshPack( InData%HubPtMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubPtMotion14 + 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 MeshPack( InData%HubPtMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HubPtMotion + 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 MeshPack( InData%BladeRootMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeRootMotion14 + 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%BladeRootMotion) ) 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%BladeRootMotion,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeRootMotion,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeRootMotion,1), UBOUND(InData%BladeRootMotion,1) + CALL MeshPack( InData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! BladeRootMotion + 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 + CALL MeshPack( InData%RotorFurlMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! RotorFurlMotion14 + 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 MeshPack( InData%NacelleMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! NacelleMotion + 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 MeshPack( InData%TowerBaseMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TowerBaseMotion14 + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlPitch) ) 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%BlPitch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitch,1), UBOUND(InData%BlPitch,1) + ReKiBuf(Re_Xferred) = InData%BlPitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Yaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRate + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSS_Spd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSS_Spd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwrAccel + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawAngle + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RootMyc,1), UBOUND(InData%RootMyc,1) + ReKiBuf(Re_Xferred) = InData%RootMyc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%YawBrTAxp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrTAyp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipPxa + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RootMxc,1), UBOUND(InData%RootMxc,1) + ReKiBuf(Re_Xferred) = InData%RootMxc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%LSSTipMxa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMya + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMza + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAxs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotPwr + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ED_PackOutput + + SUBROUTINE ED_UnPackOutput( 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(ED_OutputType), 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 = 'ED_UnPackOutput' + ! 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 ! BladeLn2Mesh 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%BladeLn2Mesh)) DEALLOCATE(OutData%BladeLn2Mesh) + ALLOCATE(OutData%BladeLn2Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeLn2Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeLn2Mesh,1), UBOUND(OutData%BladeLn2Mesh,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 MeshUnpack( OutData%BladeLn2Mesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeLn2Mesh + 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 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 MeshUnpack( OutData%PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PlatformPtMesh + 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 MeshUnpack( OutData%TowerLn2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TowerLn2Mesh + 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 MeshUnpack( OutData%HubPtMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubPtMotion14 + 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 MeshUnpack( OutData%HubPtMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HubPtMotion + 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 MeshUnpack( OutData%BladeRootMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeRootMotion14 + 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 ! BladeRootMotion 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%BladeRootMotion)) DEALLOCATE(OutData%BladeRootMotion) + ALLOCATE(OutData%BladeRootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeRootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeRootMotion,1), UBOUND(OutData%BladeRootMotion,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 MeshUnpack( OutData%BladeRootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! BladeRootMotion + 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 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 MeshUnpack( OutData%RotorFurlMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! RotorFurlMotion14 + 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 MeshUnpack( OutData%NacelleMotion, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! NacelleMotion + 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 MeshUnpack( OutData%TowerBaseMotion14, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TowerBaseMotion14 + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitch 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%BlPitch)) DEALLOCATE(OutData%BlPitch) + ALLOCATE(OutData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitch,1), UBOUND(OutData%BlPitch,1) + OutData%BlPitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Yaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRate = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSS_Spd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSS_Spd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TwrAccel = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawAngle = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RootMyc,1) + i1_u = UBOUND(OutData%RootMyc,1) + DO i1 = LBOUND(OutData%RootMyc,1), UBOUND(OutData%RootMyc,1) + OutData%RootMyc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%YawBrTAxp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrTAyp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipPxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RootMxc,1) + i1_u = UBOUND(OutData%RootMxc,1) + DO i1 = LBOUND(OutData%RootMxc,1), UBOUND(OutData%RootMxc,1) + OutData%RootMxc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%LSSTipMxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMya = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMza = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAxs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ED_UnPackOutput + + + SUBROUTINE ED_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ED_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(ED_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL ED_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ED_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ED_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ED_Input_ExtrapInterp + + + SUBROUTINE ED_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(ED_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(ED_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(ED_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%BladePtLoads) .AND. ALLOCATED(u1%BladePtLoads)) THEN + DO i1 = LBOUND(u_out%BladePtLoads,1),UBOUND(u_out%BladePtLoads,1) + CALL MeshExtrapInterp1(u1%BladePtLoads(i1), u2%BladePtLoads(i1), tin, u_out%BladePtLoads(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp1(u1%PlatformPtMesh, u2%PlatformPtMesh, tin, u_out%PlatformPtMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%TowerPtLoads, u2%TowerPtLoads, tin, u_out%TowerPtLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%HubPtLoad, u2%HubPtLoad, tin, u_out%HubPtLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%NacelleLoads, u2%NacelleLoads, tin, u_out%NacelleLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%TwrAddedMass) .AND. ALLOCATED(u1%TwrAddedMass)) THEN + DO i3 = LBOUND(u_out%TwrAddedMass,3),UBOUND(u_out%TwrAddedMass,3) + DO i2 = LBOUND(u_out%TwrAddedMass,2),UBOUND(u_out%TwrAddedMass,2) + DO i1 = LBOUND(u_out%TwrAddedMass,1),UBOUND(u_out%TwrAddedMass,1) + b = -(u1%TwrAddedMass(i1,i2,i3) - u2%TwrAddedMass(i1,i2,i3)) + u_out%TwrAddedMass(i1,i2,i3) = u1%TwrAddedMass(i1,i2,i3) + b * ScaleFactor + END DO + END DO + END DO +END IF ! check if allocated + DO i2 = LBOUND(u_out%PtfmAddedMass,2),UBOUND(u_out%PtfmAddedMass,2) + DO i1 = LBOUND(u_out%PtfmAddedMass,1),UBOUND(u_out%PtfmAddedMass,1) + b = -(u1%PtfmAddedMass(i1,i2) - u2%PtfmAddedMass(i1,i2)) + u_out%PtfmAddedMass(i1,i2) = u1%PtfmAddedMass(i1,i2) + b * ScaleFactor + END DO + END DO +IF (ALLOCATED(u_out%BlPitchCom) .AND. ALLOCATED(u1%BlPitchCom)) THEN + DO i1 = LBOUND(u_out%BlPitchCom,1),UBOUND(u_out%BlPitchCom,1) + CALL Angles_ExtrapInterp( u1%BlPitchCom(i1), u2%BlPitchCom(i1), tin, u_out%BlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated + b = -(u1%YawMom - u2%YawMom) + u_out%YawMom = u1%YawMom + b * ScaleFactor + b = -(u1%GenTrq - u2%GenTrq) + u_out%GenTrq = u1%GenTrq + b * ScaleFactor + b = -(u1%HSSBrTrqC - u2%HSSBrTrqC) + u_out%HSSBrTrqC = u1%HSSBrTrqC + b * ScaleFactor + END SUBROUTINE ED_Input_ExtrapInterp1 + + + SUBROUTINE ED_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(ED_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(ED_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(ED_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(ED_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i03 ! dim3 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + INTEGER :: i3 ! dim3 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%BladePtLoads) .AND. ALLOCATED(u1%BladePtLoads)) THEN + DO i1 = LBOUND(u_out%BladePtLoads,1),UBOUND(u_out%BladePtLoads,1) + CALL MeshExtrapInterp2(u1%BladePtLoads(i1), u2%BladePtLoads(i1), u3%BladePtLoads(i1), tin, u_out%BladePtLoads(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp2(u1%PlatformPtMesh, u2%PlatformPtMesh, u3%PlatformPtMesh, tin, u_out%PlatformPtMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%TowerPtLoads, u2%TowerPtLoads, u3%TowerPtLoads, tin, u_out%TowerPtLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%HubPtLoad, u2%HubPtLoad, u3%HubPtLoad, tin, u_out%HubPtLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%NacelleLoads, u2%NacelleLoads, u3%NacelleLoads, tin, u_out%NacelleLoads, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%TwrAddedMass) .AND. ALLOCATED(u1%TwrAddedMass)) THEN + DO i3 = LBOUND(u_out%TwrAddedMass,3),UBOUND(u_out%TwrAddedMass,3) + DO i2 = LBOUND(u_out%TwrAddedMass,2),UBOUND(u_out%TwrAddedMass,2) + DO i1 = LBOUND(u_out%TwrAddedMass,1),UBOUND(u_out%TwrAddedMass,1) + b = (t(3)**2*(u1%TwrAddedMass(i1,i2,i3) - u2%TwrAddedMass(i1,i2,i3)) + t(2)**2*(-u1%TwrAddedMass(i1,i2,i3) + u3%TwrAddedMass(i1,i2,i3)))* scaleFactor + c = ( (t(2)-t(3))*u1%TwrAddedMass(i1,i2,i3) + t(3)*u2%TwrAddedMass(i1,i2,i3) - t(2)*u3%TwrAddedMass(i1,i2,i3) ) * scaleFactor + u_out%TwrAddedMass(i1,i2,i3) = u1%TwrAddedMass(i1,i2,i3) + b + c * t_out + END DO + END DO + END DO +END IF ! check if allocated + DO i2 = LBOUND(u_out%PtfmAddedMass,2),UBOUND(u_out%PtfmAddedMass,2) + DO i1 = LBOUND(u_out%PtfmAddedMass,1),UBOUND(u_out%PtfmAddedMass,1) + b = (t(3)**2*(u1%PtfmAddedMass(i1,i2) - u2%PtfmAddedMass(i1,i2)) + t(2)**2*(-u1%PtfmAddedMass(i1,i2) + u3%PtfmAddedMass(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%PtfmAddedMass(i1,i2) + t(3)*u2%PtfmAddedMass(i1,i2) - t(2)*u3%PtfmAddedMass(i1,i2) ) * scaleFactor + u_out%PtfmAddedMass(i1,i2) = u1%PtfmAddedMass(i1,i2) + b + c * t_out + END DO + END DO +IF (ALLOCATED(u_out%BlPitchCom) .AND. ALLOCATED(u1%BlPitchCom)) THEN + DO i1 = LBOUND(u_out%BlPitchCom,1),UBOUND(u_out%BlPitchCom,1) + CALL Angles_ExtrapInterp( u1%BlPitchCom(i1), u2%BlPitchCom(i1), u3%BlPitchCom(i1), tin, u_out%BlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated + b = (t(3)**2*(u1%YawMom - u2%YawMom) + t(2)**2*(-u1%YawMom + u3%YawMom))* scaleFactor + c = ( (t(2)-t(3))*u1%YawMom + t(3)*u2%YawMom - t(2)*u3%YawMom ) * scaleFactor + u_out%YawMom = u1%YawMom + b + c * t_out + b = (t(3)**2*(u1%GenTrq - u2%GenTrq) + t(2)**2*(-u1%GenTrq + u3%GenTrq))* scaleFactor + c = ( (t(2)-t(3))*u1%GenTrq + t(3)*u2%GenTrq - t(2)*u3%GenTrq ) * scaleFactor + u_out%GenTrq = u1%GenTrq + b + c * t_out + b = (t(3)**2*(u1%HSSBrTrqC - u2%HSSBrTrqC) + t(2)**2*(-u1%HSSBrTrqC + u3%HSSBrTrqC))* scaleFactor + c = ( (t(2)-t(3))*u1%HSSBrTrqC + t(3)*u2%HSSBrTrqC - t(2)*u3%HSSBrTrqC ) * scaleFactor + u_out%HSSBrTrqC = u1%HSSBrTrqC + b + c * t_out + END SUBROUTINE ED_Input_ExtrapInterp2 + + + SUBROUTINE ED_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ED_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(ED_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL ED_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ED_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ED_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ED_Output_ExtrapInterp + + + SUBROUTINE ED_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(ED_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(ED_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(ED_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%BladeLn2Mesh) .AND. ALLOCATED(y1%BladeLn2Mesh)) THEN + DO i1 = LBOUND(y_out%BladeLn2Mesh,1),UBOUND(y_out%BladeLn2Mesh,1) + CALL MeshExtrapInterp1(y1%BladeLn2Mesh(i1), y2%BladeLn2Mesh(i1), tin, y_out%BladeLn2Mesh(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp1(y1%PlatformPtMesh, y2%PlatformPtMesh, tin, y_out%PlatformPtMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%TowerLn2Mesh, y2%TowerLn2Mesh, tin, y_out%TowerLn2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%HubPtMotion14, y2%HubPtMotion14, tin, y_out%HubPtMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%HubPtMotion, y2%HubPtMotion, tin, y_out%HubPtMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%BladeRootMotion14, y2%BladeRootMotion14, tin, y_out%BladeRootMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%BladeRootMotion) .AND. ALLOCATED(y1%BladeRootMotion)) THEN + DO i1 = LBOUND(y_out%BladeRootMotion,1),UBOUND(y_out%BladeRootMotion,1) + CALL MeshExtrapInterp1(y1%BladeRootMotion(i1), y2%BladeRootMotion(i1), tin, y_out%BladeRootMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp1(y1%RotorFurlMotion14, y2%RotorFurlMotion14, tin, y_out%RotorFurlMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%NacelleMotion, y2%NacelleMotion, tin, y_out%NacelleMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%TowerBaseMotion14, y2%TowerBaseMotion14, tin, y_out%TowerBaseMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlPitch) .AND. ALLOCATED(y1%BlPitch)) THEN + DO i1 = LBOUND(y_out%BlPitch,1),UBOUND(y_out%BlPitch,1) + CALL Angles_ExtrapInterp( y1%BlPitch(i1), y2%BlPitch(i1), tin, y_out%BlPitch(i1), tin_out ) + END DO +END IF ! check if allocated + CALL Angles_ExtrapInterp( y1%Yaw, y2%Yaw, tin, y_out%Yaw, tin_out ) + b = -(y1%YawRate - y2%YawRate) + y_out%YawRate = y1%YawRate + b * ScaleFactor + b = -(y1%LSS_Spd - y2%LSS_Spd) + y_out%LSS_Spd = y1%LSS_Spd + b * ScaleFactor + b = -(y1%HSS_Spd - y2%HSS_Spd) + y_out%HSS_Spd = y1%HSS_Spd + b * ScaleFactor + b = -(y1%RotSpeed - y2%RotSpeed) + y_out%RotSpeed = y1%RotSpeed + b * ScaleFactor + b = -(y1%TwrAccel - y2%TwrAccel) + y_out%TwrAccel = y1%TwrAccel + b * ScaleFactor + CALL Angles_ExtrapInterp( y1%YawAngle, y2%YawAngle, tin, y_out%YawAngle, tin_out ) + DO i1 = LBOUND(y_out%RootMyc,1),UBOUND(y_out%RootMyc,1) + b = -(y1%RootMyc(i1) - y2%RootMyc(i1)) + y_out%RootMyc(i1) = y1%RootMyc(i1) + b * ScaleFactor + END DO + b = -(y1%YawBrTAxp - y2%YawBrTAxp) + y_out%YawBrTAxp = y1%YawBrTAxp + b * ScaleFactor + b = -(y1%YawBrTAyp - y2%YawBrTAyp) + y_out%YawBrTAyp = y1%YawBrTAyp + b * ScaleFactor + CALL Angles_ExtrapInterp( y1%LSSTipPxa, y2%LSSTipPxa, tin, y_out%LSSTipPxa, tin_out ) + DO i1 = LBOUND(y_out%RootMxc,1),UBOUND(y_out%RootMxc,1) + b = -(y1%RootMxc(i1) - y2%RootMxc(i1)) + y_out%RootMxc(i1) = y1%RootMxc(i1) + b * ScaleFactor + END DO + b = -(y1%LSSTipMxa - y2%LSSTipMxa) + y_out%LSSTipMxa = y1%LSSTipMxa + b * ScaleFactor + b = -(y1%LSSTipMya - y2%LSSTipMya) + y_out%LSSTipMya = y1%LSSTipMya + b * ScaleFactor + b = -(y1%LSSTipMza - y2%LSSTipMza) + y_out%LSSTipMza = y1%LSSTipMza + b * ScaleFactor + b = -(y1%LSSTipMys - y2%LSSTipMys) + y_out%LSSTipMys = y1%LSSTipMys + b * ScaleFactor + b = -(y1%LSSTipMzs - y2%LSSTipMzs) + y_out%LSSTipMzs = y1%LSSTipMzs + b * ScaleFactor + b = -(y1%YawBrMyn - y2%YawBrMyn) + y_out%YawBrMyn = y1%YawBrMyn + b * ScaleFactor + b = -(y1%YawBrMzn - y2%YawBrMzn) + y_out%YawBrMzn = y1%YawBrMzn + b * ScaleFactor + b = -(y1%NcIMURAxs - y2%NcIMURAxs) + y_out%NcIMURAxs = y1%NcIMURAxs + b * ScaleFactor + b = -(y1%NcIMURAys - y2%NcIMURAys) + y_out%NcIMURAys = y1%NcIMURAys + b * ScaleFactor + b = -(y1%NcIMURAzs - y2%NcIMURAzs) + y_out%NcIMURAzs = y1%NcIMURAzs + b * ScaleFactor + b = -(y1%RotPwr - y2%RotPwr) + y_out%RotPwr = y1%RotPwr + b * ScaleFactor + END SUBROUTINE ED_Output_ExtrapInterp1 + + + SUBROUTINE ED_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(ED_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(ED_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(ED_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(ED_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ED_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%BladeLn2Mesh) .AND. ALLOCATED(y1%BladeLn2Mesh)) THEN + DO i1 = LBOUND(y_out%BladeLn2Mesh,1),UBOUND(y_out%BladeLn2Mesh,1) + CALL MeshExtrapInterp2(y1%BladeLn2Mesh(i1), y2%BladeLn2Mesh(i1), y3%BladeLn2Mesh(i1), tin, y_out%BladeLn2Mesh(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp2(y1%PlatformPtMesh, y2%PlatformPtMesh, y3%PlatformPtMesh, tin, y_out%PlatformPtMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%TowerLn2Mesh, y2%TowerLn2Mesh, y3%TowerLn2Mesh, tin, y_out%TowerLn2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%HubPtMotion14, y2%HubPtMotion14, y3%HubPtMotion14, tin, y_out%HubPtMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%HubPtMotion, y2%HubPtMotion, y3%HubPtMotion, tin, y_out%HubPtMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%BladeRootMotion14, y2%BladeRootMotion14, y3%BladeRootMotion14, tin, y_out%BladeRootMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%BladeRootMotion) .AND. ALLOCATED(y1%BladeRootMotion)) THEN + DO i1 = LBOUND(y_out%BladeRootMotion,1),UBOUND(y_out%BladeRootMotion,1) + CALL MeshExtrapInterp2(y1%BladeRootMotion(i1), y2%BladeRootMotion(i1), y3%BladeRootMotion(i1), tin, y_out%BladeRootMotion(i1), tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated + CALL MeshExtrapInterp2(y1%RotorFurlMotion14, y2%RotorFurlMotion14, y3%RotorFurlMotion14, tin, y_out%RotorFurlMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%NacelleMotion, y2%NacelleMotion, y3%NacelleMotion, tin, y_out%NacelleMotion, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%TowerBaseMotion14, y2%TowerBaseMotion14, y3%TowerBaseMotion14, tin, y_out%TowerBaseMotion14, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlPitch) .AND. ALLOCATED(y1%BlPitch)) THEN + DO i1 = LBOUND(y_out%BlPitch,1),UBOUND(y_out%BlPitch,1) + CALL Angles_ExtrapInterp( y1%BlPitch(i1), y2%BlPitch(i1), y3%BlPitch(i1), tin, y_out%BlPitch(i1), tin_out ) + END DO +END IF ! check if allocated + CALL Angles_ExtrapInterp( y1%Yaw, y2%Yaw, y3%Yaw, tin, y_out%Yaw, tin_out ) + b = (t(3)**2*(y1%YawRate - y2%YawRate) + t(2)**2*(-y1%YawRate + y3%YawRate))* scaleFactor + c = ( (t(2)-t(3))*y1%YawRate + t(3)*y2%YawRate - t(2)*y3%YawRate ) * scaleFactor + y_out%YawRate = y1%YawRate + b + c * t_out + b = (t(3)**2*(y1%LSS_Spd - y2%LSS_Spd) + t(2)**2*(-y1%LSS_Spd + y3%LSS_Spd))* scaleFactor + c = ( (t(2)-t(3))*y1%LSS_Spd + t(3)*y2%LSS_Spd - t(2)*y3%LSS_Spd ) * scaleFactor + y_out%LSS_Spd = y1%LSS_Spd + b + c * t_out + b = (t(3)**2*(y1%HSS_Spd - y2%HSS_Spd) + t(2)**2*(-y1%HSS_Spd + y3%HSS_Spd))* scaleFactor + c = ( (t(2)-t(3))*y1%HSS_Spd + t(3)*y2%HSS_Spd - t(2)*y3%HSS_Spd ) * scaleFactor + y_out%HSS_Spd = y1%HSS_Spd + b + c * t_out + b = (t(3)**2*(y1%RotSpeed - y2%RotSpeed) + t(2)**2*(-y1%RotSpeed + y3%RotSpeed))* scaleFactor + c = ( (t(2)-t(3))*y1%RotSpeed + t(3)*y2%RotSpeed - t(2)*y3%RotSpeed ) * scaleFactor + y_out%RotSpeed = y1%RotSpeed + b + c * t_out + b = (t(3)**2*(y1%TwrAccel - y2%TwrAccel) + t(2)**2*(-y1%TwrAccel + y3%TwrAccel))* scaleFactor + c = ( (t(2)-t(3))*y1%TwrAccel + t(3)*y2%TwrAccel - t(2)*y3%TwrAccel ) * scaleFactor + y_out%TwrAccel = y1%TwrAccel + b + c * t_out + CALL Angles_ExtrapInterp( y1%YawAngle, y2%YawAngle, y3%YawAngle, tin, y_out%YawAngle, tin_out ) + DO i1 = LBOUND(y_out%RootMyc,1),UBOUND(y_out%RootMyc,1) + b = (t(3)**2*(y1%RootMyc(i1) - y2%RootMyc(i1)) + t(2)**2*(-y1%RootMyc(i1) + y3%RootMyc(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%RootMyc(i1) + t(3)*y2%RootMyc(i1) - t(2)*y3%RootMyc(i1) ) * scaleFactor + y_out%RootMyc(i1) = y1%RootMyc(i1) + b + c * t_out + END DO + b = (t(3)**2*(y1%YawBrTAxp - y2%YawBrTAxp) + t(2)**2*(-y1%YawBrTAxp + y3%YawBrTAxp))* scaleFactor + c = ( (t(2)-t(3))*y1%YawBrTAxp + t(3)*y2%YawBrTAxp - t(2)*y3%YawBrTAxp ) * scaleFactor + y_out%YawBrTAxp = y1%YawBrTAxp + b + c * t_out + b = (t(3)**2*(y1%YawBrTAyp - y2%YawBrTAyp) + t(2)**2*(-y1%YawBrTAyp + y3%YawBrTAyp))* scaleFactor + c = ( (t(2)-t(3))*y1%YawBrTAyp + t(3)*y2%YawBrTAyp - t(2)*y3%YawBrTAyp ) * scaleFactor + y_out%YawBrTAyp = y1%YawBrTAyp + b + c * t_out + CALL Angles_ExtrapInterp( y1%LSSTipPxa, y2%LSSTipPxa, y3%LSSTipPxa, tin, y_out%LSSTipPxa, tin_out ) + DO i1 = LBOUND(y_out%RootMxc,1),UBOUND(y_out%RootMxc,1) + b = (t(3)**2*(y1%RootMxc(i1) - y2%RootMxc(i1)) + t(2)**2*(-y1%RootMxc(i1) + y3%RootMxc(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%RootMxc(i1) + t(3)*y2%RootMxc(i1) - t(2)*y3%RootMxc(i1) ) * scaleFactor + y_out%RootMxc(i1) = y1%RootMxc(i1) + b + c * t_out + END DO + b = (t(3)**2*(y1%LSSTipMxa - y2%LSSTipMxa) + t(2)**2*(-y1%LSSTipMxa + y3%LSSTipMxa))* scaleFactor + c = ( (t(2)-t(3))*y1%LSSTipMxa + t(3)*y2%LSSTipMxa - t(2)*y3%LSSTipMxa ) * scaleFactor + y_out%LSSTipMxa = y1%LSSTipMxa + b + c * t_out + b = (t(3)**2*(y1%LSSTipMya - y2%LSSTipMya) + t(2)**2*(-y1%LSSTipMya + y3%LSSTipMya))* scaleFactor + c = ( (t(2)-t(3))*y1%LSSTipMya + t(3)*y2%LSSTipMya - t(2)*y3%LSSTipMya ) * scaleFactor + y_out%LSSTipMya = y1%LSSTipMya + b + c * t_out + b = (t(3)**2*(y1%LSSTipMza - y2%LSSTipMza) + t(2)**2*(-y1%LSSTipMza + y3%LSSTipMza))* scaleFactor + c = ( (t(2)-t(3))*y1%LSSTipMza + t(3)*y2%LSSTipMza - t(2)*y3%LSSTipMza ) * scaleFactor + y_out%LSSTipMza = y1%LSSTipMza + b + c * t_out + b = (t(3)**2*(y1%LSSTipMys - y2%LSSTipMys) + t(2)**2*(-y1%LSSTipMys + y3%LSSTipMys))* scaleFactor + c = ( (t(2)-t(3))*y1%LSSTipMys + t(3)*y2%LSSTipMys - t(2)*y3%LSSTipMys ) * scaleFactor + y_out%LSSTipMys = y1%LSSTipMys + b + c * t_out + b = (t(3)**2*(y1%LSSTipMzs - y2%LSSTipMzs) + t(2)**2*(-y1%LSSTipMzs + y3%LSSTipMzs))* scaleFactor + c = ( (t(2)-t(3))*y1%LSSTipMzs + t(3)*y2%LSSTipMzs - t(2)*y3%LSSTipMzs ) * scaleFactor + y_out%LSSTipMzs = y1%LSSTipMzs + b + c * t_out + b = (t(3)**2*(y1%YawBrMyn - y2%YawBrMyn) + t(2)**2*(-y1%YawBrMyn + y3%YawBrMyn))* scaleFactor + c = ( (t(2)-t(3))*y1%YawBrMyn + t(3)*y2%YawBrMyn - t(2)*y3%YawBrMyn ) * scaleFactor + y_out%YawBrMyn = y1%YawBrMyn + b + c * t_out + b = (t(3)**2*(y1%YawBrMzn - y2%YawBrMzn) + t(2)**2*(-y1%YawBrMzn + y3%YawBrMzn))* scaleFactor + c = ( (t(2)-t(3))*y1%YawBrMzn + t(3)*y2%YawBrMzn - t(2)*y3%YawBrMzn ) * scaleFactor + y_out%YawBrMzn = y1%YawBrMzn + b + c * t_out + b = (t(3)**2*(y1%NcIMURAxs - y2%NcIMURAxs) + t(2)**2*(-y1%NcIMURAxs + y3%NcIMURAxs))* scaleFactor + c = ( (t(2)-t(3))*y1%NcIMURAxs + t(3)*y2%NcIMURAxs - t(2)*y3%NcIMURAxs ) * scaleFactor + y_out%NcIMURAxs = y1%NcIMURAxs + b + c * t_out + b = (t(3)**2*(y1%NcIMURAys - y2%NcIMURAys) + t(2)**2*(-y1%NcIMURAys + y3%NcIMURAys))* scaleFactor + c = ( (t(2)-t(3))*y1%NcIMURAys + t(3)*y2%NcIMURAys - t(2)*y3%NcIMURAys ) * scaleFactor + y_out%NcIMURAys = y1%NcIMURAys + b + c * t_out + b = (t(3)**2*(y1%NcIMURAzs - y2%NcIMURAzs) + t(2)**2*(-y1%NcIMURAzs + y3%NcIMURAzs))* scaleFactor + c = ( (t(2)-t(3))*y1%NcIMURAzs + t(3)*y2%NcIMURAzs - t(2)*y3%NcIMURAzs ) * scaleFactor + y_out%NcIMURAzs = y1%NcIMURAzs + b + c * t_out + b = (t(3)**2*(y1%RotPwr - y2%RotPwr) + t(2)**2*(-y1%RotPwr + y3%RotPwr))* scaleFactor + c = ( (t(2)-t(3))*y1%RotPwr + t(3)*y2%RotPwr - t(2)*y3%RotPwr ) * scaleFactor + y_out%RotPwr = y1%RotPwr + b + c * t_out + END SUBROUTINE ED_Output_ExtrapInterp2 + +END MODULE ElastoDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/extptfm/CMakeLists.txt b/OpenFAST/modules/extptfm/CMakeLists.txt new file mode 100644 index 000000000..384212ab1 --- /dev/null +++ b/OpenFAST/modules/extptfm/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/ExtPtfm_MCKF_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/ExtPtfm_MCKF_Types.f90) +endif() + +add_library(extptfm_mckflib + src/ExtPtfm_MCKF.f90 + src/ExtPtfm_MCKF_IO.f90 + src/ExtPtfm_MCKF_Types.f90 +) + +target_link_libraries(extptfm_mckflib nwtclibs) + +install(TARGETS extptfm_mckflib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/extptfm/README.md b/OpenFAST/modules/extptfm/README.md new file mode 100644 index 000000000..a8235e6f1 --- /dev/null +++ b/OpenFAST/modules/extptfm/README.md @@ -0,0 +1,4 @@ +# ExtPtfm Module + +## Overview +A module for external platform loading (m, c, k, f) in OpenFAST diff --git a/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF.f90 b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF.f90 new file mode 100644 index 000000000..e5c32f033 --- /dev/null +++ b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF.f90 @@ -0,0 +1,1196 @@ +!********************************************************************************************************************************** +!> ## ExtPtfm_MCKF +!! The ExtPtfm_MCKF and ExtPtfm_MCKF_Types modules make up a template for creating user-defined calculations in the FAST Modularization +!! Framework. ExtPtfm_MCKF_Types will be auto-generated by the FAST registry program, based on the variables specified in the +!! ExtPtfm_MCKF_Registry.txt file. +!! +!! This template file contains comments in the style required for Doxygen, and it contains methods for handling errors. +!! +!! "ExtPtfm_MCKF" should be replaced with the name of your module. Example: ElastoDyn \n +!! "ExtPtfm" (in ExtPtfm_*) should be replaced with the module name or an abbreviation of it. Example: ED +! .................................................................................................................................. +!! ## LICENSING +!! Copyright (C) 2012-2013, 2015-2016 National Renewable Energy Laboratory +!! +!! This file is part of ExtPtfm_MCKF. +!! +!! 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 ExtPtfm_MCKF + + USE ExtPtfm_MCKF_Types + USE ExtPtfm_MCKF_Parameters ! ID_*, N_INPUTS, N_OUTPUTS + USE NWTC_Library + USE NWTC_LAPACK + + IMPLICIT NONE + + PRIVATE + + CHARACTER(len=1), parameter :: XYZ(3)=(/'X','Y','Z'/) + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: ExtPtfm_Init ! Initialization routine + PUBLIC :: ExtPtfm_End ! Ending routine (includes clean up) + PUBLIC :: ExtPtfm_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: ExtPtfm_CalcOutput ! Routine for computing outputs + PUBLIC :: ExtPtfm_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: ExtPtfm_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: ExtPtfm_UpdateDiscState ! Tight coupling routine for updating discrete states + PUBLIC :: ExtPtfm_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 :: ExtPtfm_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 :: ExtPtfm_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 :: ExtPtfm_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 :: ExtPtfm_GetOP ! Routine to get the operating-point values for linearization (from data structures to arrays) + + + + +CONTAINS + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Helper functions for the module + +!> This routine sets the error status and error message for a routine, it's a simplified version of SetErrStat from NWTC_Library +subroutine SetErrStatSimple(ErrStat, ErrMess, RoutineName, LineNumber) + INTEGER(IntKi), INTENT(INOUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(INOUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + CHARACTER(*), INTENT(IN ) :: RoutineName ! Name of the routine error occurred in + INTEGER(IntKi), INTENT(IN), OPTIONAL :: LineNumber ! Line of input file + if (ErrStat /= ErrID_None) then + write(ErrMess,'(A)') TRIM(RoutineName)//':'//TRIM(ErrMess) + if (present(LineNumber)) then + ErrMess = TRIM(ErrMess)//' Line: '//TRIM(Num2LStr(LineNumber))//'.' + endif + end if +end subroutine SetErrStatSimple + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE ExtPtfm_Init( InitInp, u, p, x, xd, z, OtherState, y, m, dt_gluecode, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + use ExtPtfm_MCKF_IO, only: ReadPrimaryFile, SetOutParam, ExtPtfm_PrintSum + TYPE(ExtPtfm_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(ExtPtfm_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(ExtPtfm_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(ExtPtfm_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(ExtPtfm_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(ExtPtfm_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (logical, etc) + TYPE(ExtPtfm_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(ExtPtfm_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(INOUT) :: dt_gluecode !< Coupling interval in seconds: the rate that + !! (1) ExtPtfm_UpdateStates() is called in loose coupling & + !! (2) ExtPtfm_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(ExtPtfm_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + 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 ! Loop counter + TYPE(ExtPtfm_InputFile) :: InputFileData ! Data stored in the module's input file + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + call NWTC_Init( ) + ! Display the module information + call DispNVD( ExtPtfm_Ver ) + ! Initialize parameters + p%NumOuts = 0 + p%nTot = -1 + p%nCB = -1 + + call ReadPrimaryFile(InitInp%InputFile, p, InitInp%RootName, InputFileData, ErrStat, ErrMsg); if(Failed()) return + + ! --- Setting Params from Input file data + p%IntMethod = InputFileData%IntMethod + if (InputFileData%DT<0) then + p%EP_DeltaT = dt_gluecode + else + p%EP_DeltaT = InputFileData%DT + endif + ! Setting p%OutParam from OutList + call SetOutParam(InputFileData%OutList, InputFileData%NumOuts, p, ErrStat, ErrMsg); if(Failed()) return + ! Set the constant state matrices A,B,C,D + call SetStateMatrices(p, ErrStat, ErrMsg) + + ! --- Allocate and init continuous states + call AllocAry( x%qm , p%nCB,'CB DOF positions' , ErrStat,ErrMsg); if(Failed()) return + call AllocAry( x%qmdot , p%nCB,'CB DOF velocities', ErrStat,ErrMsg); if(Failed()) return + if (allocated(InputFileData%InitPosList)) then + if (size(InputFileData%InitPosList)/=p%nCB) then + CALL SetErrStat(ErrID_Fatal, 'The number of elements of `InitPosList` ('//trim(Num2LStr(size(InputFileData%InitPosList)))//') does not match the number of CB modes: '//trim(Num2LStr(p%nCB)), ErrStat, ErrMsg, 'ExtPtfm_Init'); + return + endif + do I=1,p%nCB; + x%qm(I)=InputFileData%InitPosList(I); + end do + else + do I=1,p%nCB; x%qm (I)=0; end do + endif + if (allocated(InputFileData%InitVelList)) then + if (size(InputFileData%InitVelList)/=p%nCB) then + CALL SetErrStat(ErrID_Fatal, 'The number of elements of `InitVelList` ('//trim(Num2LStr(size(InputFileData%InitVelList)))//') does not match the number of CB modes: '//trim(Num2LStr(p%nCB)), ErrStat, ErrMsg, 'ExtPtfm_Init'); + return + endif + do I=1,p%nCB; + x%qmdot(I)=InputFileData%InitVelList(I); + enddo + else + do I=1,p%nCB; x%qmdot(I)=0; end do + endif + + ! Other states + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + ! allocate OtherState%xdot if using multi-step method; initialize n + if ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) THEN + allocate( OtherState%xdot(4), STAT=ErrStat ) + ErrMsg='Error allocating OtherState%xdot' + if(Failed()) return + endif + + ! Initialize Misc Variables: + !m%EquilStart = InputFileData%EquilStart + m%EquilStart = .False. ! Feature not yet implemented + + m%Indx = 1 ! used to optimize interpolation of loads in time + call AllocAry( m%F_at_t, p%nTot,'Loads at t', ErrStat,ErrMsg); if(Failed()) return + do I=1,p%nTot; m%F_at_t(I)=0; end do + call AllocAry( m%xFlat, 2*p%nCB,'xFlat', ErrStat,ErrMsg); if(Failed()) return + do I=1,2*p%nCB; m%xFlat(I)=0; end do + do I=1,N_INPUTS; m%uFlat(I)=0; end do + + ! Define initial guess (set up mesh first) for the system inputs here: + call Init_meshes(u, y, InitInp, ErrStat, ErrMsg); if(Failed()) return + + ! --- Outputs + CALL AllocAry( m%AllOuts, ID_QStart+3*p%nCBFull-1, "ExtPtfm AllOut", ErrStat,ErrMsg ); if(Failed()) return + m%AllOuts(1:ID_QStart+3*p%nCBFull-1) = 0.0 + call AllocAry( y%WriteOutput, p%NumOuts,'WriteOutput', ErrStat,ErrMsg); if(Failed()) return + call AllocAry(InitOut%WriteOutputHdr,p%NumOuts,'WriteOutputHdr',ErrStat,ErrMsg); if(Failed()) return + call AllocAry(InitOut%WriteOutputUnt,p%NumOuts,'WriteOutputUnt',ErrStat,ErrMsg); if(Failed()) return + y%WriteOutput(1:p%NumOuts) = 0.0 + InitOut%WriteOutputHdr(1:p%NumOuts) = p%OutParam(1:p%NumOuts)%Name + InitOut%WriteOutputUnt(1:p%NumOuts) = p%OutParam(1:p%NumOuts)%Units + InitOut%Ver = ExtPtfm_Ver + + if (InitInp%Linearize) then + ! TODO The linearization features are in place but waiting for glue-code changes, and testing. + CALL SetErrStat( ErrID_Fatal, 'ExtPtfm_MCKF linearization analysis is currently not supported by the glue code.', ErrStat, ErrMsg, 'ExtPtfm_Init'); + if(Failed())return + !Appropriate Jacobian row/column names and rotating-frame flags here: + CALL AllocAry(InitOut%LinNames_y, 6+p%NumOuts , 'LinNames_y', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%RotFrame_y, 6+p%NumOuts , 'RotFrame_y', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%LinNames_x, 2*p%nCB , 'LinNames_x', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%RotFrame_x, 2*p%nCB , 'RotFrame_x', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%LinNames_u, N_INPUTS , 'LinNames_u', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%RotFrame_u, N_INPUTS , 'RotFrame_u', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%IsLoad_u , N_INPUTS , 'IsLoad_u' , ErrStat, ErrMsg); if(Failed()) return + ! LinNames_y + do I=1,3; + InitOut%LinNames_y(I) = 'Interface node '//XYZ(I)//' force, N' + InitOut%LinNames_y(I+3) = 'Interface node '//XYZ(I)//' moment, Nm' + enddo + do i=1,p%NumOuts + InitOut%LinNames_y(N_OUTPUTS+i) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + end do + ! LinNames_u + do I=1,3; + InitOut%LinNames_u(I+ 0) = 'Interface node '//XYZ(I)//' translation displacement, m' + InitOut%LinNames_u(I+ 3) = 'Interface node '//XYZ(I)//' rotation, rad' + InitOut%LinNames_u(I+ 6) = 'Interface node '//XYZ(I)//' translation velocity, m/s' + InitOut%LinNames_u(I+ 9) = 'Interface node '//XYZ(I)//' rotation velocity, rad/s' + InitOut%LinNames_u(I+12) = 'Interface node '//XYZ(I)//' translation acceleration, m/s^2' + InitOut%LinNames_u(I+15) = 'Interface node '//XYZ(I)//' rotation acceleration, rad/s^2' + enddo + ! LinNames_x + do I=1,p%nCB; + InitOut%LinNames_x(I) = 'Mode '//trim(Num2LStr(p%ActiveCBDOF(I)))//' displacement, -'; + InitOut%LinNames_x(I+p%nCB) = 'Mode '//trim(Num2LStr(p%ActiveCBDOF(I)))//' velocity, -'; + enddo + ! + InitOut%RotFrame_x = .false. ! note that meshes are in the global, not rotating frame + InitOut%RotFrame_y = .false. ! note that meshes are in the global, not rotating frame + InitOut%RotFrame_u = .false. ! note that meshes are in the global, not rotating frame + InitOut%IsLoad_u = .false. ! the inputs are not loads but kinematics + end if + + ! --- Summary file + if (InputFileData%SumPrint) then + call ExtPtfm_PrintSum(x, p, m, InitInp%RootName, ErrStat, ErrMsg); if(Failed()) return + endif + +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_Init') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetStateMatrices( p, ErrStat, ErrMsg) +!.................................................................................................................................. + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< All the parameter matrices stored in this input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + ! Local variables: + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: nX ! Number of states + INTEGER(IntKi) :: nU ! Number of inputs + INTEGER(IntKi) :: nY ! Number of ouputs + INTEGER(IntKi) :: n1 ! Number of interface DOF + INTEGER(IntKi) :: n2 ! Number of CB DOF + real(ReKi), dimension(:,:), allocatable :: I22 + ! Init + nX = 2*p%nCB + nU = 3*6 + nY = 6 + n1 = 6 + n2 = p%nCB + if (allocated(p%AMat)) deallocate(p%AMat) + if (allocated(p%BMat)) deallocate(p%BMat) + if (allocated(p%CMat)) deallocate(p%CMat) + if (allocated(p%DMat)) deallocate(p%DMat) + if (allocated(p%M11)) deallocate(p%M11) + if (allocated(p%M12)) deallocate(p%M12) + if (allocated(p%M22)) deallocate(p%M22) + if (allocated(p%M21)) deallocate(p%M21) + if (allocated(p%C11)) deallocate(p%C11) + if (allocated(p%C12)) deallocate(p%C12) + if (allocated(p%C22)) deallocate(p%C22) + if (allocated(p%C21)) deallocate(p%C21) + if (allocated(p%K11)) deallocate(p%C11) + if (allocated(p%K22)) deallocate(p%C22) + ! Allocation + call allocAry(p%AMat, nX, nX, 'p%AMat', ErrStat, ErrMsg); if(Failed()) return ; p%AMat(1:nX,1:nX) =0 + call allocAry(p%BMat, nX, nU, 'p%BMat', ErrStat, ErrMsg); if(Failed()) return ; p%BMat(1:nX,1:nU) =0 + call allocAry(p%FX , nX, 'p%FX' , ErrStat, ErrMsg); if(Failed()) return ; p%Fx (1:nX) =0 + call allocAry(p%CMat, nY, nX, 'p%CMat', ErrStat, ErrMsg); if(Failed()) return ; p%CMat(1:nY,1:nX) =0 + call allocAry(p%DMat, nY, nU, 'p%DMat', ErrStat, ErrMsg); if(Failed()) return ; p%DMat(1:nY,1:nU) =0 + call allocAry(p%FY , nY, 'p%FY' , ErrStat, ErrMsg); if(Failed()) return ; p%FY (1:nY) =0 + call allocAry(p%M11 , n1, n1, 'p%M11' , ErrStat, ErrMsg); if(Failed()) return ; p%M11 (1:n1,1:n1) =0 + call allocAry(p%K11 , n1, n1, 'p%K11' , ErrStat, ErrMsg); if(Failed()) return ; p%K11 (1:n1,1:n1) =0 + call allocAry(p%C11 , n1, n1, 'p%C11' , ErrStat, ErrMsg); if(Failed()) return ; p%C11 (1:n1,1:n1) =0 + call allocAry(p%M22 , n2, n2, 'p%M22' , ErrStat, ErrMsg); if(Failed()) return ; p%M22 (1:n2,1:n2) =0 + call allocAry(p%K22 , n2, n2, 'p%K22' , ErrStat, ErrMsg); if(Failed()) return ; p%K22 (1:n2,1:n2) =0 + call allocAry(p%C22 , n2, n2, 'p%C22' , ErrStat, ErrMsg); if(Failed()) return ; p%C22 (1:n2,1:n2) =0 + call allocAry(p%M12 , n1, n2, 'p%M12' , ErrStat, ErrMsg); if(Failed()) return ; p%M12 (1:n1,1:n2) =0 + call allocAry(p%C12 , n1, n2, 'p%C12' , ErrStat, ErrMsg); if(Failed()) return ; p%C12 (1:n1,1:n2) =0 + call allocAry(p%M21 , n2, n1, 'p%M21' , ErrStat, ErrMsg); if(Failed()) return ; p%M21 (1:n2,1:n1) =0 + call allocAry(p%C21 , n2, n1, 'p%C21' , ErrStat, ErrMsg); if(Failed()) return ; p%C21 (1:n2,1:n1) =0 + call allocAry( I22 , n2, n2, ' I22' , ErrStat, ErrMsg); if(Failed()) return ; I22 (1:n2,1:n2) =0 + do I=1,n2 ; I22(I,I)=1; enddo ! Identity matrix + ! Submatrices + p%M11(1:n1,1:n1) = p%Mass(1:n1 ,1:n1 ) + p%C11(1:n1,1:n1) = p%Damp(1:n1 ,1:n1 ) + p%K11(1:n1,1:n1) = p%Stff(1:n1 ,1:n1 ) + p%M12(1:n1,1:n2) = p%Mass(1:n1 ,n1+1:n1+n2) + p%C12(1:n1,1:n2) = p%Damp(1:n1 ,n1+1:n1+n2) + p%M21(1:n2,1:n1) = p%Mass(n1+1:n1+n2,1:n1 ) + p%C21(1:n2,1:n1) = p%Damp(n1+1:n1+n2,1:n1 ) + p%M22(1:n2,1:n2) = p%Mass(n1+1:n1+n2,n1+1:n1+n2) + p%C22(1:n2,1:n2) = p%Damp(n1+1:n1+n2,n1+1:n1+n2) + p%K22(1:n2,1:n2) = p%Stff(n1+1:n1+n2,n1+1:n1+n2) + ! A matrix + p%AMat(1:n2 ,n2+1:nX) = I22 (1:n2,1:n2) + p%AMat(n2+1:nX,1:n2 ) = -p%K22(1:n2,1:n2) + p%AMat(n2+1:nX,n2+1:nX) = -p%C22(1:n2,1:n2) + ! B matrix + p%BMat(n2+1:nX,7 :12 ) = -p%C21(1:n2,1:6) + p%BMat(n2+1:nX,13:18 ) = -p%M21(1:n2,1:6) + ! C matrix + p%CMat(1:nY,1:n2 ) = matmul(p%M12,p%K22) + p%CMat(1:nY,n2+1:nX) = matmul(p%M12,p%C22) - p%C12 + ! D matrix + p%DMat(1:nY,1:6 ) = -p%K11 + p%DMat(1:nY,7:12 ) = -p%C11 + matmul(p%M12,p%C21) + p%DMat(1:nY,13:18 ) = -p%M11 + matmul(p%M12,p%M21) +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_SetStateMatrices') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE SetStateMatrices +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_meshes(u, y, InitInp, ErrStat, ErrMsg) + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(ExtPtfm_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Create the input and output meshes associated with platform loads + CALL MeshCreate( BlankMesh = u%PtfmMesh , & + IOS = COMPONENT_INPUT , & + Nnodes = 1 , & + ErrStat = ErrStat , & + ErrMess = ErrMsg , & + TranslationDisp = .TRUE. , & + Orientation = .TRUE. , & + TranslationVel = .TRUE. , & + RotationVel = .TRUE. , & + TranslationAcc = .TRUE. , & + RotationAcc = .TRUE.) + if(Failed()) return + + ! Create the node on the mesh, the node is located at the PlatformRefzt, to match ElastoDyn + CALL MeshPositionNode (u%PtfmMesh, 1, (/0.0_ReKi, 0.0_ReKi, InitInp%PtfmRefzt/), ErrStat, ErrMsg ); if(Failed()) return + ! Create the mesh element + CALL MeshConstructElement ( u%PtfmMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1 ); if(Failed()) return + CALL MeshCommit ( u%PtfmMesh, ErrStat, ErrMsg ); if(Failed()) return + ! the output mesh is a sibling of the input: + CALL MeshCopy( SrcMesh=u%PtfmMesh, DestMesh=y%PtfmMesh, CtrlCode=MESH_SIBLING, IOS=COMPONENT_OUTPUT, & + ErrStat=ErrStat, ErrMess=ErrMsg, Force=.TRUE., Moment=.TRUE. ) + if(Failed()) return +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'Init_meshes') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE Init_meshes +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE ExtPtfm_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(ExtPtfm_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(ExtPtfm_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(ExtPtfm_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 + ! Place any last minute operations or calculations here: + ! Close files here (but because of checkpoint-restart capability, it is not recommended to have files open during the simulation): + ! Destroy the input data: + call ExtPtfm_DestroyInput( u, ErrStat, ErrMsg ); if(Failed()) return + ! Destroy the parameter data: + call ExtPtfm_DestroyParam( p, ErrStat, ErrMsg ); if(Failed()) return + ! Destroy the state data: + call ExtPtfm_DestroyContState( x, ErrStat,ErrMsg); if(Failed()) return + call ExtPtfm_DestroyDiscState( xd, ErrStat,ErrMsg); if(Failed()) return + call ExtPtfm_DestroyConstrState( z, ErrStat,ErrMsg); if(Failed()) return + call ExtPtfm_DestroyOtherState( OtherState, ErrStat,ErrMsg); if(Failed()) return + ! Destroy the output data: + call ExtPtfm_DestroyOutput( y, ErrStat, ErrMsg ); if(Failed()) return + ! Destroy the misc data: + call ExtPtfm_DestroyMisc( m, ErrStat, ErrMsg ); if(Failed()) return +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_End') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_End + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE ExtPtfm_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(ExtPtfm_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 + ! local variables + TYPE(ExtPtfm_ContinuousStateType) :: xdot ! Continuous state derivs at t + TYPE(ExtPtfm_InputType) :: u_interp + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! need xdot at t + CALL ExtPtfm_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL ExtPtfm_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat, ErrMsg) + CALL ExtPtfm_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) ! initializes xdot + CALL ExtPtfm_DestroyInput( u_interp, ErrStat, ErrMsg) ! we don't need this local copy anymore + if (n .le. 2) then + OtherState%n = n + CALL ExtPtfm_CopyContState(xdot, OtherState%xdot(3-n), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + else + if (OtherState%n .lt. n) then + OtherState%n = n + CALL ExtPtfm_CopyContState(OtherState%xdot(3), OtherState%xdot(4), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState(OtherState%xdot(2), OtherState%xdot(3), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState(OtherState%xdot(1), OtherState%xdot(2), MESH_UPDATECOPY, ErrStat, ErrMsg ) + elseif (OtherState%n .gt. n) then + ErrStat = ErrID_Fatal + ErrMsg = ' Backing up in time is not supported with a multistep method ' + RETURN + endif + CALL ExtPtfm_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date + x%qm = x%qm + (p%EP_DeltaT / 24.) * ( 55.*OtherState%xdot(1)%qm - 59.*OtherState%xdot(2)%qm + 37.*OtherState%xdot(3)%qm & + - 9. * OtherState%xdot(4)%qm ) + x%qmdot = x%qmdot + (p%EP_DeltaT / 24.) * ( 55.*OtherState%xdot(1)%qmdot - 59.*OtherState%xdot(2)%qmdot & + + 37.*OtherState%xdot(3)%qmdot - 9.*OtherState%xdot(4)%qmdot ) + endif + CALL ExtPtfm_DestroyContState(xdot, ErrStat, ErrMsg) + CALL ExtPtfm_DestroyInput(u_interp, ErrStat, ErrMsg) + +END SUBROUTINE ExtPtfm_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE ExtPtfm_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output ! TODO TODO TODO IN + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(ExtPtfm_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 + ! local variables + TYPE(ExtPtfm_InputType) :: u_interp ! Continuous states at t + TYPE(ExtPtfm_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(ExtPtfm_ContinuousStateType) :: xdot_pred ! Continuous states at t + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + CALL ExtPtfm_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) !initialize x_pred + CALL ExtPtfm_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) + if (n .gt. 2) then + CALL ExtPtfm_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp + CALL ExtPtfm_Input_ExtrapInterp(u, utimes, u_interp, t + p%EP_DeltaT, ErrStat, ErrMsg) + CALL ExtPtfm_CalcContStateDeriv(t + p%EP_DeltaT, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat, ErrMsg ) ! initializes xdot_pred + CALL ExtPtfm_DestroyInput( u_interp, ErrStat, ErrMsg) ! local copy no longer needed + + x%qm = x%qm + (p%EP_DeltaT / 24.) * ( 9. * xdot_pred%qm + 19. * OtherState%xdot(1)%qm - 5. * OtherState%xdot(2)%qm & + + 1. * OtherState%xdot(3)%qm ) + + x%qmdot = x%qmdot + (p%EP_DeltaT / 24.) * ( 9. * xdot_pred%qmdot + 19. * OtherState%xdot(1)%qmdot - 5. * OtherState%xdot(2)%qmdot & + + 1. * OtherState%xdot(3)%qmdot ) + CALL ExtPtfm_DestroyContState( xdot_pred, ErrStat, ErrMsg) ! local copy no longer needed + else + x%qm = x_pred%qm + x%qmdot = x_pred%qmdot + endif + CALL ExtPtfm_DestroyContState( x_pred, ErrStat, ErrMsg) ! local copy no longer needed +END SUBROUTINE ExtPtfm_ABM4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE ExtPtfm_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(ExtPtfm_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 + ! local variables + TYPE(ExtPtfm_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(ExtPtfm_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(ExtPtfm_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(ExtPtfm_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(ExtPtfm_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(ExtPtfm_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(ExtPtfm_InputType) :: u_interp ! interpolated value of inputs + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + !bjj: the state type contains allocatable arrays, so we must first allocate space: + CALL ExtPtfm_CopyContState( x, k1, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState( x, k2, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState( x, k3, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState( x, k4, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL ExtPtfm_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat, ErrMsg ) + + ! interpolate u to find u_interp = u(t) + CALL ExtPtfm_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL ExtPtfm_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat, ErrMsg ) + + ! find xdot at t + CALL ExtPtfm_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) !initializes xdot + + k1%qm = p%EP_DeltaT * xdot%qm + k1%qmdot = p%EP_DeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k1%qm + x_tmp%qmdot = x%qmdot + 0.5 * k1%qmdot + + ! interpolate u to find u_interp = u(t + dt/2) + CALL ExtPtfm_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%EP_DeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt/2 + CALL ExtPtfm_CalcContStateDeriv( t + 0.5*p%EP_DeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k2%qm = p%EP_DeltaT * xdot%qm + k2%qmdot = p%EP_DeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k2%qm + x_tmp%qmdot = x%qmdot + 0.5 * k2%qmdot + + ! find xdot at t + dt/2 + CALL ExtPtfm_CalcContStateDeriv( t + 0.5*p%EP_DeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k3%qm = p%EP_DeltaT * xdot%qm + k3%qmdot = p%EP_DeltaT * xdot%qmdot + x_tmp%qm = x%qm + k3%qm + x_tmp%qmdot = x%qmdot + k3%qmdot + + ! interpolate u to find u_interp = u(t + dt) + CALL ExtPtfm_Input_ExtrapInterp(u, utimes, u_interp, t + p%EP_DeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt + CALL ExtPtfm_CalcContStateDeriv( t + p%EP_DeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k4%qm = p%EP_DeltaT * xdot%qm + k4%qmdot = p%EP_DeltaT * xdot%qmdot + x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. + x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. + CALL ExitThisRoutine() +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) + CALL ExtPtfm_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + CALL ExtPtfm_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + END SUBROUTINE ExitThisRoutine + +END SUBROUTINE ExtPtfm_RK4 + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ExtPtfm_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(ExtPtfm_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes (output from this routine only + !! because of record keeping in routines that copy meshes) + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(ExtPtfm_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(ExtPtfm_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(ExtPtfm_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 variables + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + if ( p%nCB == 0) return ! no modes = no states + if (p%IntMethod .eq. 1) then + call ExtPtfm_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + elseif (p%IntMethod .eq. 2) then + call ExtPtfm_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + elseif (p%IntMethod .eq. 3) then + call ExtPtfm_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + else + call SetErrStat(ErrID_Fatal,'Invalid time integration method:'//Num2LStr(p%IntMethod),ErrStat,ErrMsg,'ExtPtfm_UpdateState') + end IF +END SUBROUTINE ExtPtfm_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE ExtPtfm_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ExtPtfm_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + 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 !< Generic counters + real(ReKi), dimension(6) :: Fc !< Output coupling force + ! Compute the loads `fr1 fr2` at t (fr1 without added mass) by time interpolation of the inputs loads p%Forces + call InterpStpMat(REAL(t,ReKi), p%times, p%Forces, m%Indx, p%nTimeSteps, m%F_at_t) + + ! --- Flatening vectors and using linear state formulation y=Cx+Du+Fy + ! u flat (x1, \dot{x1}, \ddot{x1}) + m%uFlat(1:3) = u%PtfmMesh%TranslationDisp(:,1) + m%uFlat(4:6) = GetSmllRotAngs(u%PtfmMesh%Orientation(:,:,1), ErrStat, ErrMsg); CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_CalcOutput') + m%uFlat(7:9 ) = u%PtfmMesh%TranslationVel(:,1) + m%uFlat(10:12) = u%PtfmMesh%RotationVel (:,1) + m%uFlat(13:15) = u%PtfmMesh%TranslationAcc(:,1) + m%uFlat(16:18) = u%PtfmMesh%RotationAcc (:,1) + + !--- Computing output: y = Cx + Du + Fy + ! + if (p%nCB>0) then + ! x flat + m%xFlat( 1:p%nCB ) = x%qm (1:p%nCB) + m%xFlat(p%nCB+1:2*p%nCB) = x%qmdot(1:p%nCB) + + ! >>> MATMUL implementation + !Fc = matmul(p%CMat, m%xFlat) + matmul(p%DMat, m%uFlat) + m%F_at_t(1:6) - matmul(p%M12, m%F_at_t(6+1:6+p%nCB)) + + ! >>> LAPACK implementation + Fc(1:6) = m%F_at_t(1:6) ! Fc = F1r + ... + ! GEMV(TRS, M , N , alpha , A , LDA, X ,INCX, Beta , Y, IncY) + CALL LAPACK_GEMV('n', 6 , 2*p%nCB, 1.0_ReKi, p%CMat, 6 , m%xFlat , 1, 1.0_ReKi, Fc, 1 ) ! = C*x + (F1r) + CALL LAPACK_GEMV('n', 6 , 18 , 1.0_ReKi, p%DMat, 6 , m%uFlat , 1, 1.0_ReKi, Fc, 1 ) ! + D*u + CALL LAPACK_GEMV('n', 6 , p%nCB , -1.0_ReKi, p%M12 , 6 , m%F_at_t(6+1:6+p%nCB), 1, 1.0_ReKi, Fc, 1 ) ! - M12*F2r + else + Fc = matmul(p%DMat, m%uFlat) + m%F_at_t(1:6) + endif + + ! Update the output mesh + do i=1,3 + y%PtfmMesh%Force(I,1) = Fc(I) + y%PtfmMesh%Moment(I,1) = Fc(I+3) + enddo + + ! --- All Outputs + m%AllOuts(ID_PtfFx) = y%PtfmMesh%Force (1,1) + m%AllOuts(ID_PtfFy) = y%PtfmMesh%Force (2,1) + m%AllOuts(ID_PtfFz) = y%PtfmMesh%Force (3,1) + m%AllOuts(ID_PtfMx) = y%PtfmMesh%Moment(1,1) + m%AllOuts(ID_PtfMy) = y%PtfmMesh%Moment(2,1) + m%AllOuts(ID_PtfMz) = y%PtfmMesh%Moment(3,1) + m%AllOuts(ID_InpFx) = m%F_at_t(1) + m%AllOuts(ID_InpFy) = m%F_at_t(2) + m%AllOuts(ID_InpFz) = m%F_at_t(3) + m%AllOuts(ID_InpMx) = m%F_at_t(4) + m%AllOuts(ID_InpMy) = m%F_at_t(5) + m%AllOuts(ID_InpMz) = m%F_at_t(6) + !y%WriteOutput(ID_WaveElev) = .. ! TODO + do i=1,p%nCB + m%AllOuts(ID_QStart + 0*p%nCBFull -1 + p%ActiveCBDOF(I)) = x%qm (I) ! CBQ - DOF Positions + m%AllOuts(ID_QStart + 1*p%nCBFull -1 + p%ActiveCBDOF(I)) = x%qmdot(I) ! CBQD - DOF Velocities + m%AllOuts(ID_QStart + 2*p%nCBFull -1 + p%ActiveCBDOF(I)) = m%F_at_t(6+I) ! CBF - DOF Forces + enddo + ! --- Selected output channels only + do I = 1,p%NumOuts + if (p%OutParam(I)%Indx>0) then + y%WriteOutput(I) = p%OutParam(I)%SignM * m%AllOuts( p%OutParam(I)%Indx ) + else + y%WriteOutput(I) = -9.9999e20 + endif + enddo +END SUBROUTINE ExtPtfm_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> This is a tight coupling routine for computing derivatives of continuous states. +SUBROUTINE ExtPtfm_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ExtPtfm_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ExtPtfm_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t + 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 + ! Allocation of output dxdt (since intent(out)) + call AllocAry(dxdt%qm, p%nCB, 'dxdt%qm', ErrStat, ErrMsg); if(Failed()) return + call AllocAry(dxdt%qmdot, p%nCB, 'dxdt%qmdot', ErrStat, ErrMsg); if(Failed()) return + if ( p%nCB == 0 ) return + do I=1,p%nCB; dxdt%qm (I)=0; enddo + do I=1,p%nCB; dxdt%qmdot(I)=0; enddo + + ! Compute the loads `fr1 fr2` at t (fr1 without added mass) by time interpolation of the inputs loads p%F + call InterpStpMat(REAL(t,ReKi), p%times, p%Forces, m%Indx, p%nTimeSteps, m%F_at_t) + + ! u flat (x1, \dot{x1}, \ddot{x1}) + m%uFlat(1:3) = u%PtfmMesh%TranslationDisp(:,1) + m%uFlat(4:6) = GetSmllRotAngs(u%PtfmMesh%Orientation(:,:,1), ErrStat, ErrMsg); if(Failed()) return + m%uFlat(7:9 ) = u%PtfmMesh%TranslationVel(:,1) + m%uFlat(10:12) = u%PtfmMesh%RotationVel (:,1) + m%uFlat(13:15) = u%PtfmMesh%TranslationAcc(:,1) + m%uFlat(16:18) = u%PtfmMesh%RotationAcc (:,1) + + ! --- Computation of qm and qmdot + ! >>> Latex formulae: + ! \ddot{x2} = -K22 x2 - C22 \dot{x2} - C21 \dot{x1} - M21 \ddot{x1} + fr2 + ! >>> MATMUL IMPLEMENTATION + !dxdt%qm= x%qmdot + !dxdt%qmdot = - matmul(p%K22,x%qm) - matmul(p%C22,x%qmdot) & + ! - matmul(p%C21,m%uFlat(7:12)) - matmul(p%M21, m%uFlat(13:18)) + m%F_at_t(6+1:6+p%nCB) + ! >>> BLAS IMPLEMENTATION + ! COPY( N , X , INCX, Y , INCY) + CALL LAPACK_COPY(p%nCB, x%qmdot , 1 , dxdt%qm , 1 ) ! qmdot=qmdot + CALL LAPACK_COPY(p%nCB, m%F_at_t(6+1:6+p%nCB), 1 , dxdt%qmdot , 1 ) ! qmddot = fr2 + ! GEMV(TRS, M , N , alpha , A , LDA , X ,INCX, Beta , Y , IncY) + CALL LAPACK_GEMV('n', p%nCB, p%nCB , -1.0_ReKi, p%K22, p%nCB, x%qm , 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - K22 x2 + CALL LAPACK_GEMV('n', p%nCB, 6 , -1.0_ReKi, p%C21, p%nCB, m%uFlat(7:12) , 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - C21 \dot{x1} + CALL LAPACK_GEMV('n', p%nCB, p%nCB , -1.0_ReKi, p%C22, p%nCB, x%qmdot , 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - C22 \dot{x2} + CALL LAPACK_GEMV('n', p%nCB, 6 , -1.0_ReKi, p%M21, p%nCB, m%uFlat(13:18), 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - M21 \ddot{x1} + +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_CalcContStateDeriv') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for updating discrete states. +SUBROUTINE ExtPtfm_UpdateDiscState( t, n, u, 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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ExtPtfm_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t, Output: Discrete states at t + Interval + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ExtPtfm_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 + ErrStat = ErrID_None + ErrMsg = "" + ! Update discrete states here: + xd%DummyDiscState = 0.0_Reki +END SUBROUTINE ExtPtfm_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for solving for the residual of the constraint state functions. +SUBROUTINE ExtPtfm_CalcConstrStateResidual( t, u, p, x, xd, z, OtherState, m, Z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ExtPtfm_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ExtPtfm_ConstraintStateType), INTENT( OUT) :: Z_residual !< Residual of the constraint state functions 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 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! Solve for the residual of the constraint state functions here: + Z_residual%DummyConstrState = 0.0_ReKi + +END SUBROUTINE ExtPtfm_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in ExtPtfm_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ExtPtfm_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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ExtPtfm_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(ExtPtfm_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 the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + INTEGER(IntKi) :: i,j ! Loop index + INTEGER(IntKi) :: idx ! Index of output channel in AllOuts + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (present(dYdu)) then + ! allocate and set dYdu + if (.not. allocated(dYdu)) then + call AllocAry(dYdu, N_OUTPUTS+p%NumOuts, N_INPUTS, 'dYdu', ErrStat, ErrMsg); if(Failed()) return + do i=1,size(dYdu,1); do j=1,size(dYdu,2); dYdu(i,j)=0.0_ReKi; enddo;enddo + end if + dYdu(1:6,1:N_INPUTS) = p%DMat(1:6,1:N_INPUTS) + !dYdu is zero except if WriteOutput is the interface loads + do i = 1,p%NumOuts + idx = p%OutParam(i)%Indx + if (idx==ID_PtfFx) then; dYdu(6+i,1:N_INPUTS) = p%DMat(1,1:N_INPUTS) + elseif (idx==ID_PtfFy) then; dYdu(6+i,1:N_INPUTS) = p%DMat(2,1:N_INPUTS) + elseif (idx==ID_PtfFx) then; dYdu(6+i,1:N_INPUTS) = p%DMat(3,1:N_INPUTS) + elseif (idx==ID_PtfMz) then; dYdu(6+i,1:N_INPUTS) = p%DMat(4,1:N_INPUTS) + elseif (idx==ID_PtfMy) then; dYdu(6+i,1:N_INPUTS) = p%DMat(5,1:N_INPUTS) + elseif (idx==ID_PtfMz) then; dYdu(6+i,1:N_INPUTS) = p%DMat(6,1:N_INPUTS) + else ; dYdu(6+i,1:N_INPUTS) = 0.0_ReKi + endif + end do + end if + if (present(dXdu)) then + ! allocate and set dXdu + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, 2*p%nCB, N_INPUTS, 'dXdu', ErrStat, ErrMsg); if(Failed()) return + do i=1,size(dXdu,1); do j=1,size(dXdu,2); dXdu(i,j)=0.0_ReKi; enddo;enddo + end if + dXdu(1:2*p%nCB,1:N_INPUTS) = p%BMat(1:2*p%nCB,1:N_INPUTS) + end if + if (present(dXddu)) then + end if + if (present(dZdu)) then + end if +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_JacobianPInput') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_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 ExtPtfm_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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ExtPtfm_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(ExtPtfm_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] + INTEGER(IntKi) :: i,j ! Loop index + INTEGER(IntKi) :: idx ! Index of output channel in AllOuts + INTEGER(IntKi) :: iDOF ! Mode number + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (present(dYdx)) then + ! allocate and set dYdx + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, N_OUTPUTS+p%NumOuts, 2*p%nCB, 'dYdx', ErrStat, ErrMsg); if(Failed()) return + do i=1,size(dYdx,1); do j=1,size(dYdx,2); dYdx(i,j)=0.0_ReKi; enddo;enddo + end if + dYdx(1:6,1:2*p%nCB) = p%CMat(1:6, 1:2*p%nCB) + ! WriteOutputs + do i = 1,p%NumOuts + idx = p%OutParam(i)%Indx + iDOF = mod(idx-ID_QSTART, p%nCB)+1 + ! if output is an interface load dYdx is a row of the Cmatrix + if (idx==ID_PtfFx) then; dYdx(6+i,1:2*p%nCB) = p%CMat(1,1:2*p%nCB) + elseif (idx==ID_PtfFy) then; dYdx(6+i,1:2*p%nCB) = p%CMat(2,1:2*p%nCB) + elseif (idx==ID_PtfFx) then; dYdx(6+i,1:2*p%nCB) = p%CMat(3,1:2*p%nCB) + elseif (idx==ID_PtfMx) then; dYdx(6+i,1:2*p%nCB) = p%CMat(4,1:2*p%nCB) + elseif (idx==ID_PtfMy) then; dYdx(6+i,1:2*p%nCB) = p%CMat(5,1:2*p%nCB) + elseif (idx==ID_PtfMz) then; dYdx(6+i,1:2*p%nCB) = p%CMat(6,1:2*p%nCB) + ! Below we look at the index, we assumed an order for the outputs + ! where after the index ID_Qstart, the AllOutputs are: Q,QDot and Qf + ! An alternative coulbe to look at the name of the DOF instead: + ! e.g. if (index(p%OutParam,'CBQ_')>0) then ... (see SetOutParam) + else if ((idx-ID_QStart>= 0 ) .and. (idx-ID_QStart<p%nCB) ) then + ! Output is a DOF position, dYdx has a 1 at the proper location + dYdx(6+i,1:2*p%nCB ) = 0.0_ReKi + dYdx(6+i, iDOF) = 1.0_ReKi ! TODO TODO TODO ALLDOF_2_DOF + else if ((idx-ID_QStart>= p%nCB) .and. (idx-ID_QStart<2*p%nCB) ) then + ! Output is a DOF velocity, dYdx has a 1 at the proper location + dYdx(6+i,1:2*p%nCB ) = 0.0_ReKi + dYdx(6+i,p%nCB + iDOF) = 1.0_ReKi ! TODO TODO TODO ALLDOF_2_DOF + else ! e.g. WaveElevation or CB Forces + dYdx(6+i,1:2*p%nCB ) = 0.0_ReKi + endif + end do + end if + if (present(dXdx)) then + ! allocate and set dXdx + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, 2*p%nCB, 2*p%nCB, 'dXdx', ErrStat, ErrMsg); if(Failed()) return + do i=1,size(dXdx,1); do j=1,size(dXdx,2); dXdx(i,j)=0.0_ReKi; enddo;enddo + end if + dXdx(1:2*p%nCB,1:2*p%nCB) = p%AMat(1:2*p%nCB,1:2*p%nCB) + end if + if (present(dXddx)) then + end if + if (present(dZdx)) then + end if +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_JacobianPInput') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_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 ExtPtfm_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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ExtPtfm_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(ExtPtfm_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 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (present(dYdxd)) then + end if + if (present(dXdxd)) then + end if + if (present(dXddxd)) then + end if + if (present(dZdxd)) then + end if +END SUBROUTINE ExtPtfm_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 ExtPtfm_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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ExtPtfm_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(ExtPtfm_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 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (present(dYdz)) then + end if + if (present(dXdz)) then + end if + if (present(dXddz)) then + end if + if (present(dZdz)) then + end if +END SUBROUTINE ExtPtfm_JacobianPConstrState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE ExtPtfm_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(ExtPtfm_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ExtPtfm_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ExtPtfm_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(ExtPtfm_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) :: I + TYPE(ExtPtfm_ContinuousStateType) :: dx !< derivative of continuous states at operating point + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + + if ( present( u_op ) ) then + if (.not. allocated(u_op)) then + call AllocAry(u_op, N_INPUTS, 'u_op', ErrStat, ErrMsg); if(Failed())return + endif + u_op(1:3) = u%PtfmMesh%TranslationDisp(:,1) + u_op(4:6) = GetSmllRotAngs(u%PtfmMesh%Orientation(:,:,1), ErrStat, ErrMsg); if(Failed())return + u_op(7:9 ) = u%PtfmMesh%TranslationVel(:,1) + u_op(10:12) = u%PtfmMesh%RotationVel (:,1) + u_op(13:15) = u%PtfmMesh%TranslationAcc(:,1) + u_op(16:18) = u%PtfmMesh%RotationAcc (:,1) + end if + + if ( present( y_op ) ) then + if (.not. allocated(y_op)) then + call AllocAry(y_op, N_OUTPUTS+p%NumOuts, 'y_op', ErrStat, ErrMsg); if(Failed())return + endif + ! Update the output mesh + y_op(1:3)=y%PtfmMesh%Force(1:3,1) + y_op(4:6)=y%PtfmMesh%Moment(1:3,1) + do i=1,p%NumOuts + y_op(i+N_OUTPUTS) = y%WriteOutput(i) + end do + end if + + if ( present( x_op ) ) then + if (.not. allocated(x_op)) then + call AllocAry(x_op, 2*p%nCB, 'x_op', ErrStat, ErrMsg); if (Failed())return + endif + x_op(1:p%nCB) = x%qm(1:p%nCB) + x_op(p%nCB+1:2*p%nCB) = x%qmdot(1:p%nCB) + end if + + if ( present( dx_op ) ) then + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, 2*p%nCB, 'dx_op', ErrStat, ErrMsg); if (Failed())return + endif + call ExtPtfm_CalcContStateDeriv(t, u, p, x, xd, z, OtherState, m, dx, ErrStat, ErrMsg); if(Failed()) return + dx_op(1:p%nCB) = dx%qm(1:p%nCB) + dx_op(p%nCB+1:2*p%nCB) = dx%qmdot(1:p%nCB) + end if + + if ( present( xd_op ) ) then + end if + + if ( present( z_op ) ) then + end if + +contains + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_GetOP') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ExtPtfm_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +END MODULE ExtPtfm_MCKF +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Driver.f90 b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Driver.f90 new file mode 100644 index 000000000..cdde2f09b --- /dev/null +++ b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Driver.f90 @@ -0,0 +1,105 @@ +!********************************************************************************************************************************** +!> ## ExtPtfm_MCKF_Driver: This code tests the template modules +!!.................................................................................................................................. +!! LICENSING +!! Copyright (C) 2016 National Renewable Energy Laboratory +!! +!! This file is part of ExtPtfm_MCKF. +!! +!! 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. +!********************************************************************************************************************************** +PROGRAM ExtPtfm_Driver + + USE NWTC_Library + USE ExtPtfm_MCKF + USE ExtPtfm_MCKF_Types + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 1 !< Number of inputs sent to ExtPtfm_UpdateStates + ! Program variables + REAL(DbKi) :: Time !< Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval !< Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) !< Variable for storing time associated with inputs, in seconds + CHARACTER(1024) :: InputFile !< A CHARACTER string containing the name of the primary input file + + TYPE(ExtPtfm_InitInputType) :: InitInData !< Input data for initialization + TYPE(ExtPtfm_InitOutputType) :: InitOutData !< Output data from initialization + + TYPE(ExtPtfm_ContinuousStateType) :: x !< Continuous states + TYPE(ExtPtfm_DiscreteStateType) :: xd !< Discrete states + TYPE(ExtPtfm_ConstraintStateType) :: z !< Constraint states + TYPE(ExtPtfm_ConstraintStateType) :: Z_residual !< Residual of the constraint state functions (Z) + TYPE(ExtPtfm_OtherStateType) :: OtherState !< Other states + TYPE(ExtPtfm_MiscVarType) :: misc !< Optimization variables + TYPE(ExtPtfm_ParameterType) :: p !< Parameters + TYPE(ExtPtfm_InputType) :: u(NumInp) !< System inputs + TYPE(ExtPtfm_OutputType) :: y !< System outputs + ! + + INTEGER(IntKi) :: n !< Loop counter (for time step) + INTEGER(IntKi) :: ErrStat !< Status of error message + CHARACTER(ErrMsgLen) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + InputFile='' + call CheckArgs(InputFile, ErrStat) + ! Populate the InitInData data structure here: + IF (LEN_TRIM(InputFile) == 0) THEN ! no input file was specified + ErrStat = ErrID_Fatal + ErrMsg = 'The required input file was not specified on the command line.' + CALL WrScr( ErrMsg ) + STOP 1 + END IF + + InitInData%InputFile = InputFile + TimeInterval = 0.001 ! Glue code's request for delta time (likely based on information from other modules) + + ! Initialize the module + CALL ExtPtfm_Init( InitInData, u(1), p, x, xd, z, OtherState, y, misc, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + ! Destroy initialization data + CALL ExtPtfm_DestroyInitInput( InitInData, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + DO n = 0,2 + Time = n*TimeInterval + InputTime(1) = Time + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + ! Calculate outputs at n + CALL ExtPtfm_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + CALL ExtPtfm_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + END DO + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL ExtPtfm_End( u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + STOP 1 + END IF +END PROGRAM ExtPtfm_Driver diff --git a/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_IO.f90 b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_IO.f90 new file mode 100644 index 000000000..d0e2868d1 --- /dev/null +++ b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_IO.f90 @@ -0,0 +1,911 @@ +!********************************************************************************************************************************** +! The ExtPtfm_MCKF.f90, ExtPtfm_MCKF_IO.f90 and ExtPtfm_MCKF_Types.f90 make up the ExtPtfm_MCKF module of the +! FAST Modularization Framework. ExtPtfm_MCKF_Types is auto-generated based on FAST_Registry.txt. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! This file is part of ExtPtfm_MCKF. +! +! 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. +! +!********************************************************************************************************************************** +!> This module contains definitions of compile-time PARAMETERS for the ExtPtfm_MCKF module. +!! Every variable defined here MUST have the PARAMETER attribute. +MODULE ExtPtfm_MCKF_Parameters + USE NWTC_Library + + TYPE(ProgDesc), PARAMETER :: ExtPtfm_Ver = ProgDesc( 'ExtPtfm_MCKF', '', '' ) !< module date/version information + ! + INTEGER(IntKi), parameter :: N_INPUTS = 18 + INTEGER(IntKi), parameter :: N_OUTPUTS = 6 + + + CHARACTER(len=4), DIMENSION(3), PARAMETER :: StrIntMethod = (/'RK4 ','AB4 ','ABM4'/) + + ! Variables for output channels + INTEGER(IntKi), PARAMETER :: FILEFORMAT_GUYANASCII = 0 + INTEGER(IntKi), PARAMETER :: FILEFORMAT_FLEXASCII = 1 + + ! Variables for output channels + INTEGER(IntKi), PARAMETER :: MaxOutChs = 9 + 3*200 ! Maximum number of output channels + ! Harcoded to outputs of 200 CB modes + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + INTEGER(IntKi), PARAMETER :: ID_Time = 0 + INTEGER(IntKi), PARAMETER :: ID_PtfFx = 1 + INTEGER(IntKi), PARAMETER :: ID_PtfFy = 2 + INTEGER(IntKi), PARAMETER :: ID_PtfFz = 3 + INTEGER(IntKi), PARAMETER :: ID_PtfMx = 4 + INTEGER(IntKi), PARAMETER :: ID_PtfMy = 5 + INTEGER(IntKi), PARAMETER :: ID_PtfMz = 6 + INTEGER(IntKi), PARAMETER :: ID_WaveElev = 7 + INTEGER(IntKi), PARAMETER :: ID_InpFx = 8 + INTEGER(IntKi), PARAMETER :: ID_InpFy = 9 + INTEGER(IntKi), PARAMETER :: ID_InpFz = 10 + INTEGER(IntKi), PARAMETER :: ID_InpMx = 11 + INTEGER(IntKi), PARAMETER :: ID_InpMy = 12 + INTEGER(IntKi), PARAMETER :: ID_InpMz = 13 + INTEGER(IntKi), PARAMETER :: ID_QStart = 14 +END MODULE ExtPtfm_MCKF_Parameters + +!********************************************************************************************************************************** +!> This module contains file I/O routines and data validation routines. +MODULE ExtPtfm_MCKF_IO + + USE ExtPtfm_MCKF_Parameters + USE ExtPtfm_MCKF_Types + + IMPLICIT NONE + private + + public :: ReadPrimaryFile + public :: SetOutParam + public :: ExtPtfm_PrintSum + +CONTAINS +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Helper functions for the module +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the error status and error message for a routine, it's a simplified version of SetErrStat from NWTC_Library +subroutine SetErrStatSimple(ErrStat, ErrMess, RoutineName, LineNumber) + INTEGER(IntKi), INTENT(INOUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(INOUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + CHARACTER(*), INTENT(IN ) :: RoutineName ! Name of the routine error occurred in + INTEGER(IntKi), INTENT(IN), OPTIONAL :: LineNumber ! Line of input file + if (ErrStat /= ErrID_None) then + print*,'ErrMess',ErrMess + write(ErrMess,'(A)') TRIM(RoutineName)//':'//TRIM(ErrMess) + if (present(LineNumber)) then + ErrMess = TRIM(ErrMess)//' Line: '//TRIM(Num2LStr(LineNumber))//'.' + endif + end if +end subroutine SetErrStatSimple + +subroutine disp2r8(u,varname,a) + integer,intent(in) ::u + character(len=*),intent(in)::varname + real(ReKi),intent(in),dimension(:,:) ::a + integer :: n, m,i + character(len=20) :: fmt + character(len=*),parameter :: RFMT='EN13.3E2' + n=size(a,1) + m=size(a,2) + if (n>0 .and. m>0) then + write(u,"(A,A)") varname,"=[" + write(fmt,*) m + do i=1,n-1 + write(u,"("//adjustl(fmt)//RFMT//")") a(i,:) + enddo + i=n + write(u,"("//trim(fmt)//RFMT//",A)") a(i,:), " ];" + else + write(u,'(A,A)') varname,'=[];' + endif +end subroutine +subroutine disp1r8(u,varname,a) + integer,intent(in) ::u + character(len=*),intent(in)::varname + real(ReKi),intent(in),dimension(:) ::a + integer :: n + character(len=20) :: fmt + character(len=*),parameter :: RFMT='EN13.3E2' + n=size(a,1) + if (n>0) then + write(fmt,*) n + write(u,"(A,"//adjustl(fmt)//RFMT//",A)") varname//" =[ ", a(:), " ];" + else + write(u,'(A,A)') varname,'=[];' + endif +end subroutine +subroutine disp1i(u,varname,a) + integer,intent(in) ::u + character(len=*),intent(in)::varname + integer(IntKi),intent(in),dimension(:) ::a + integer :: n + character(len=20) :: fmt + character(len=*),parameter :: RFMT='I5' + n=size(a,1) + if (n>0) then + write(fmt,*) n + write(u,"(A,"//adjustl(fmt)//RFMT//",A)") varname//" =[ ", a(:), " ];" + else + write(u,'(A,A)') varname,'=[];' + endif +end subroutine + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Helper functions to read primary file +real(ReKi) function ReadFloatFromStr(s, VarName, iStat, Msg ) result(myfloat) + character(len=*), intent(in) :: s + character(len=*), intent(in) :: VarName + character(len=*), intent(inout) :: Msg + integer, intent(out) :: iStat + read(s,*, iostat=iStat ) myfloat + if (iStat /= 0) then + iStat=ErrID_Fatal + Msg = trim(Msg)//'Error extracting float while reading '//VarName + endif +end function ReadFloatFromStr +integer function ReadIntFromStr(s, VarName, iStat, Msg ) result(myint) + character(len=*), intent(in) :: s + character(len=*), intent(in) :: VarName + character(len=*), intent(inout) :: Msg + integer, intent(out) :: iStat + read(s,*, iostat=iStat ) myint + if (iStat /= 0) then + iStat=ErrID_Fatal + Msg = trim(Msg)//'Error extracting integer while reading '//VarName + endif +end function ReadIntFromStr +subroutine ReadRealMatrix(fid, FileName, Mat, VarName, nLines,nRows, iStat, Msg, iLine ) + integer, intent(in) :: fid + real(ReKi), dimension(:,:), allocatable :: Mat + character(len=*), intent(in) :: FileName + character(len=*), intent(in) :: VarName + integer, intent(in) :: nLines + integer, intent(in) :: nRows + integer, intent(out) :: iStat + integer, intent(inout) :: iLine + character(len=*), intent(inout) :: Msg + ! local variables + integer :: i + call allocAry( Mat, nLines, nRows, VarName, iStat, Msg); + if (iStat /= 0) return + !Read Stiffness + DO I =1,nLines + iLine=iLine+1 + ! TODO use ReadCAryFromStr when available in the NWTCIO, it performs more checks + CALL ReadAry( fid, FileName, Mat(I,:), nRows, trim(VarName)//' Line '//Num2LStr(iLine), VarName, iStat, Msg) + if (iStat /= 0) return + ENDDO +end subroutine + + +SUBROUTINE SetOutParam(OutList, NumOuts_in, p, ErrStat, ErrMsg ) +! This routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +! warning if any of the channels are not available outputs from the module. +! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +! the sign is set to 0 if the channel is invalid. +! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!.................................................................................................................................. + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + INTEGER(IntKi), INTENT(IN) :: NumOuts_in !< Effective number of output channels + TYPE(ExtPtfm_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 + ! Local variables + INTEGER :: I ! Generic loop-counting index + INTEGER :: INDX ! Index for valid arrays + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(13) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "INPF_FX ","INPF_FY ","INPF_FZ ","INPF_MX ","INPF_MY ","INPF_MZ ",& + "INTRFFX ","INTRFFY ","INTRFFZ ","INTRFMX ","INTRFMY ","INTRFMZ ",& + "WAVELEV "/) + CHARACTER(OutStrLenM1), PARAMETER :: ParamUnitsAry(13) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ",& + "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(m) "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(13) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + ID_InpFx, ID_InpFy, ID_InpFz, ID_InpMx, ID_InpMy, ID_InpMz,& + ID_PtfFx, ID_PtfFy, ID_PtfFz, ID_PtfMx, ID_PtfMy, ID_PtfMz,& + ID_WaveElev /) + character(ErrMsgLen) :: WarnMsg !Warning Message + ErrStat = ErrID_None + ErrMsg = "" + WarnMsg = "" + + p%NumOuts = NumOuts_in + allocate(p%OutParam(0:p%NumOuts) , stat=ErrStat ) + if ( ErrStat /= 0_IntKi ) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for the InflowWind OutParam array.", ErrStat, ErrMsg, RoutineName) + return + endif + + ! Set index, name, and units for the time output channel: + p%OutParam(0)%Indx = 0 + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + ! Set index, name, and units for all of the output channels. + do I = 1,p%NumOuts + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + p%OutParam(I)%Indx = 0 + p%OutParam(I)%Units = "(NA)" + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + ! Reverse the sign of the channel if the prefix is "-", "_" or "M" + if ( index( "-_M", OutListTmp(1:1) ) > 0 ) then + p%OutParam(I)%SignM = -1 + OutListTmp = OutListTmp(2:) + else + p%OutParam(I)%SignM = 1 + end if + ! Find the index of the channel in the AllOut list + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + if (Indx>0) then + p%OutParam(I)%Indx = ParamIndxAry(Indx) + p%OutParam(I)%Units = ParamUnitsAry(Indx) + else if (index(OutListTmp,'CBQ_') > 0 ) then + call setDOFChannel(5,ID_QStart+0*p%nCBFull-1); if(Failed()) return ! NOTE: using full CB + else if (index(OutListTmp,'CBQD_') > 0 ) then + call setDOFChannel(6,ID_QStart+1*p%nCBFull-1); if(Failed()) return ! NOTE: using full CB + else if (index(OutListTmp,'CBF_') > 0 ) then + call setDOFChannel(5,ID_QStart+2*p%nCBFull-1); if(Failed()) return ! NOTE: using full CB + else + call setInvalidChannel() ! INVALID + endif + !write(*,*) p%OutParam(I)%Name, p%OutParam(I)%Indx, p%OutParam(I)%Units + end do + if (len(WarnMsg)>0) then + call SetErrStat(ErrID_Warn, WarnMsg,ErrStat,ErrMsg,'ExtPtfm_SetOutParam') + write(*,'(A)')trim(WarnMsg) + endif + return +contains + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_SetOutParam') + Failed = ErrStat >= AbortErrLev + end function Failed + subroutine setDOFChannel(nCharBefore,nOffset) + !> Sets channel when the channel name has the form "YYYY_XXX" where XXX is a DOF number + integer, intent(in) :: nCharBefore !< Number of characters to ignore in OutListTmp + integer, intent(in) :: nOffset !< Index offset to add to iDOF + integer :: idof ! index of CB DOF extracted from + iDOF = ReadIntFromStr(OutListTmp(nCharBefore:), 'Output channel '//trim(OutList(I)), ErrStat, ErrMsg); + if(ErrStat/=0) return + if ( any( p%ActiveCBDOF== iDOF ) ) then + p%OutParam(I)%Indx = nOffset+iDOF + p%OutParam(I)%Units = '(-)' + else +! if ((iDOF> p%nCB) .or. (iDOF<1)) then + call setInvalidChannel() ! INVALID +! else + endif + end subroutine + subroutine setInvalidChannel() + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%Indx = 0 + WarnMsg=trim(WarnMsg)//TRIM(p%OutParam(I)%Name)//" is not an available output channel."//CHAR(10) +! call SetErrStat(ErrID_Warn, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,'ExtPtfm_SetOutParam') +! write(*,*)TRIM(p%OutParam(I)%Name)//" is not an available output channel." + end subroutine +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!> Checks that all inputs were correctly read +subroutine CheckInputs(Inp, p, ErrStat, ErrMsg) + TYPE(ExtPtfm_InputFile), INTENT(INOUT) :: Inp !< Data stored in the module's input file + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< All the parameter matrices stored in this input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + ErrStat = ErrID_None + ErrMsg = "" + if (ErrStat/=0) return + if (p%nTot<0) then ; ErrStat=ErrID_Fatal; ErrMsg='The total number of DOF was not set'; return; endif + if (.not.allocated(p%Mass)) then ; ErrStat=ErrID_Fatal; ErrMsg='The mass matrix was not allocated.' ; return; endif + if (.not.allocated(p%Stff)) then ; ErrStat=ErrID_Fatal; ErrMsg='The stiffness matrix was not allocated.' ; return; endif + if (.not.allocated(p%Damp)) then ; ErrStat=ErrID_Fatal; ErrMsg='The damping matrix was not allocated.' ; return; endif + if (.not.allocated(p%Forces)) then ; ErrStat=ErrID_Fatal; ErrMsg='The loads were not allocated.';return; endif + if (.not.allocated(p%times)) then ; ErrStat=ErrID_Fatal; ErrMsg='The time vector was not allocated.'; return; endif + if (allocated(Inp%ActiveCBDOF)) then + if (maxval(Inp%ActiveCBDOF)>size(p%Mass,1)-6) then + ErrStat=ErrID_Fatal; ErrMsg='The maximum index of `ActiveCBDOF` (active CB DOF) should be less than the total number of CB DOF.'; return; + endif + endif +end subroutine CheckInputs +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadPrimaryFile(InputFile, p, OutFileRoot, InputFileData, ErrStat, ErrMsg) +!.................................................................................................................................. + ! Passed variables + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< All the parameter matrices stored in this input file + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of all the output files written by this routine. + TYPE(ExtPtfm_InputFile), INTENT(OUT) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + ! Local variables: + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: N ! Number of list elements + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: UnEc ! Unit number for echo + INTEGER(IntKi) :: iLine ! Current position in file + CHARACTER(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + CHARACTER(1024) :: PriPath ! Path name of the primary file + LOGICAL :: Echo + ! --- Initialization + ErrStat = ErrID_None + ErrMsg = "" + Echo = .FALSE. + UnEc = -1 ! Echo file not opened, yet + CALL GetPath(InputFile, PriPath) ! Input files will be relative to the path where the primary input file is located. + CALL AllocAry(InputFileData%OutList, MaxOutChs, "ExtPtfm Input File's Outlist", ErrStat, ErrMsg); if(Failed()) return + + ! Get an available unit number for the file. + CALL GetNewUnit(UnIn, ErrStat, ErrMsg); if(Failed()) return + ! Open the Primary input file. + CALL OpenFInpFile(UnIn, InputFile, ErrStat, ErrMsg); if(Failed()) return + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + I = 1 ! the number of times we've read the file (used for the Echo variable) + DO + iLine=1 + !-------------------------- HEADER --------------------------------------------- + CALL ReadCom(UnIn, InputFile, 'File Header', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return; + CALL ReadStr(UnIn, InputFile, Line, 'Header', 'File Header: File Description', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + !---------------------- SIMULATION CONTROL -------------------------------------- + CALL ReadCom(UnIn, InputFile, 'Section Header: Simulation Control', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + ! Echo - Echo input to "<RootName>.ech". + CALL ReadVar(UnIn, InputFile, Echo, 'Echo','Echo switch', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + CALL OpenEcho(UnEc, TRIM(OutFileRoot)//'.ech', ErrStat, ErrMsg, ExtPtfm_Ver ); if(Failed()) return; + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(ExtPtfm_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + REWIND( UnIn, IOSTAT=ErrStat ) + IF (ErrStat /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".',ErrStat,ErrMsg,'ExtPtfm_ReadPrimaryFile' ); + IF (ErrStat >= AbortErrLev) RETURN + END IF + END DO + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr(' Heading of the '//TRIM(ExtPtfm_Ver%Name)//' input file: ') + CALL WrScr(' '//TRIM( Line )) + END IF + + ! DT - Requested integration time for ElastoDyn (seconds): + InputFileData%DT=-1 + CALL ReadVar( UnIn, InputFile, Line, "DT", "Integration time for ExtPtfm (s)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DT + READ(Line, *, IOSTAT=ErrStat) InputFileData%DT + IF ( ErrStat /= 0 ) THEN + CALL CheckIOS(ErrStat, InputFile, "DT", NumType, ErrStat, ErrMsg); if(Failed()) return + END IF + END IF + ! Method - Integration method for loose coupling + CALL ReadVar( UnIn, InputFile, InputFileData%IntMethod, "IntMethod", "Integration method for ExtPtfm {1: RK4, 2: AB4, or 3: ABM4}", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + + !---------------------- REDUCTION INPUTS --------------------------------------------------- + CALL ReadCom(UnIn, InputFile, 'Section Header: ReductionInputs', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! File Format switch + CALL ReadVar(UnIn, InputFile, InputFileData%FileFormat, "FileFormat", "File format switch", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! Reduction Filename + CALL ReadVar(UnIn, InputFile, InputFileData%RedFile , 'Red_FileName', 'Path containing Guyan/Craig-Bampton inputs', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + IF ( PathIsRelative(InputFileData%RedFile) ) InputFileData%RedFile = TRIM(PriPath)//TRIM(InputFileData%RedFile) + CALL ReadVar(UnIn, InputFile, InputFileData%RedFileCst, 'RedCst_FileName', 'Path containing Guyan/Craig-Bampton constant inputs', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + IF ( PathIsRelative(InputFileData%RedFileCst) ) InputFileData%RedFileCst = TRIM(PriPath)//TRIM(InputFileData%RedFileCst) + CALL ReadVar(UnIn, InputFile, N , 'NActiveCBDOF','Number of active CB mode listed in ActiveCBDOF, -1 for all modes', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + if (N<0) then + CALL ReadCom(UnIn, InputFile, 'ActiveCBDOF', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + elseif (N==0) then + ! Allocating ActiveDOF of size 0 => Guyan modes only + CALL AllocAry(InputFileData%ActiveCBDOF, N, 'ActiveCBDOF', ErrStat, ErrMsg ); if (Failed()) return + CALL ReadCom(UnIn, InputFile, 'ActiveCBDOF', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + else + CALL AllocAry(InputFileData%ActiveCBDOF, N, 'ActiveCBDOF', ErrStat, ErrMsg ); if (Failed()) return + CALL ReadAry(UnIn, InputFile, InputFileData%ActiveCBDOF, N, 'ActiveCBDOF', 'List of active CB modes', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + endif + ! TODO TODO TODO CALL ReadVar(UnIn, InputFile, InputFileData%EquilStart, 'EquilStart','Find the equilibrium initial positions for the CB modes', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + CALL ReadVar(UnIn, InputFile, N , 'NInitPosList','Number of initial positions listed in InitPosList', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + if (N<=0) then + CALL ReadCom(UnIn, InputFile, 'InitPosList', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + else + CALL AllocAry(InputFileData%InitPosList, N, 'InitPosList', ErrStat, ErrMsg ); if (Failed()) return + CALL ReadAry(UnIn, InputFile, InputFileData%InitPosList, N, 'InitPosList', 'Initial positions', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + endif + CALL ReadVar(UnIn, InputFile, N , 'NInitVelList','Number of initial velocties listed in InitVelList', ErrStat, ErrMsg, UnEc ); if(LineFailed()) return + if (N<=0) then + CALL ReadCom(UnIn, InputFile, 'InitVelList', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + else + CALL AllocAry(InputFileData%InitVelList, N, 'InitVelList', ErrStat, ErrMsg ); if (Failed()) return + CALL ReadAry(UnIn, InputFile, InputFileData%InitVelList, N, 'InitVelList', 'Initial velocities', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + endif + !---------------------- OUTPUT -------------------------------------------------- + CALL ReadCom(UnIn, InputFile, 'Section Header: Output', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! SumPrint - Print summary data to <RootName>.sum (flag): + CALL ReadVar(UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! OutFile - Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-): + CALL ReadVar(UnIn, InputFile, InputFileData%OutFile , "OutFile", "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! TabDelim - Flag to cause tab-delimited text output (delimited by space otherwise) (flag): + CALL ReadVar(UnIn, InputFile, InputFileData%TabDelim, "TabDelim", "Flag to cause tab-delimited text output (delimited by space otherwise) (flag)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! OutFmt - Format used for module's text tabular output (except time); resulting field should be 10 characters (-): + CALL ReadVar(UnIn, InputFile, InputFileData%OutFmt , "OutFmt", "Format used for module's text tabular output (except time); resulting field should be 10 characters (-)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! Tstart - Time to start module's tabular output (seconds): + CALL ReadVar(UnIn, InputFile, InputFileData%Tstart , "Tstart", "Time to start module's tabular output (seconds)", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + !---------------------- OUTLIST -------------------------------------------- + CALL ReadCom(UnIn, InputFile, 'Section Header: OutList', ErrStat, ErrMsg, UnEc); if(LineFailed()) return + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList(UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat, ErrMsg, UnEc); if(LineFailed()) return + !---------------------- END OF FILE ----------------------------------------- + call cleanup() + + ! --- Reading Reduced file + call ReadReducedFile(InputFileData%RedFile, p, InputFileData%FileFormat, ErrStat, ErrMsg); if(Failed()) return; + ! Checking that everyting was correctly read and set + call CheckInputs(InputFileData, p, ErrStat, ErrMsg); if(Failed()) return + + + ! --- Reducing the number of DOF if needed + p%nCBFull=p%nCB + if (allocated(InputFileData%ActiveCBDOF)) then + call allocAry(p%ActiveCBDOF, size(InputFileData%ActiveCBDOF), 'ActiveCBDOF', ErrStat, ErrMsg); if(Failed()) return + do I=1,size(InputFileData%ActiveCBDOF) + p%ActiveCBDOF(I) = InputFileData%ActiveCBDOF(I); + enddo + call ReduceNumberOfDOF(p, ErrStat, ErrMsg); + else + call allocAry(p%ActiveCBDOF, p%nCBFull, 'ActiveCBDOF', ErrStat, ErrMsg); if(Failed()) return + do I=1,p%nCBFull + p%ActiveCBDOF(I) = I + enddo + endif + + return + +CONTAINS + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_ReadPrimaryFile') + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + logical function LineFailed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_ReadPrimaryFile',iLine) + LineFailed = ErrStat >= AbortErrLev + if(LineFailed) call cleanup() + iLine=iLine+1 ! Increase line number + end function LineFailed + subroutine cleanup() + if (UnIn>0) close(UnIn) + if (UnEc>0) close(UnEc) + end subroutine cleanup +END SUBROUTINE ReadPrimaryFile + +!> Reduce the number of degrees of freedom given as input +SUBROUTINE ReduceNumberOfDOF(p, ErrStat, ErrMsg) + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< All the parameter matrices stored in this input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + integer(IntKi) :: nActive + integer(IntKi), dimension(:), allocatable :: FullActiveCBDOF + integer(IntKi) :: I + + ! Preprending 1-6 to ActiveDOF + call allocAry(FullActiveCBDOF, size(p%ActiveCBDOF)+6, 'FullActiveCBDOF', ErrStat, ErrMsg); if(Failed()) return + FullActiveCBDOF(1:6)=(/1,2,3,4,5,6/) + do I=1,size(p%ActiveCBDOF); + FullActiveCBDOF(I+6)=p%ActiveCBDOF(I)+6; + enddo + nActive=size(FullActiveCBDOF) + + ! Reducing matrices and load matrix + call SquareMatRed(p%Mass) + call SquareMatRed(p%Stff) + call SquareMatRed(p%Damp) + call TimeMatRed(p%Forces) + + ! Trigger + p%nCB = size(p%ActiveCBDOF) + p%nTot= p%nCB+6 +CONTAINS + !> Takes M and returns M(I,I) where I is a list of indexes to keep + subroutine SquareMatRed(M) + real(Reki), dimension(:,:), allocatable :: M + real(Reki), dimension(:,:), allocatable :: tmp + integer(IntKi) :: I,J + ! Storing M to a tmp array + call allocAry( tmp, size(M,1), size(M,2), 'Mtmp', ErrStat, ErrMsg); if(Failed()) return + tmp=M + ! Reallocating M and storing only the desired DOF + deallocate(M) + call allocAry(M, nActive, nActive, 'M', ErrStat, ErrMsg); if(Failed()) return + do I=1,nActive + do J=1,nActive + M(I,J) = tmp(FullActiveCBDOF(I), FullActiveCBDOF(J)) + enddo + enddo + deallocate(tmp) + end subroutine + !> Takes M and returns M(:,I) where I is a list of indexes to keep + subroutine TimeMatRed(M) + real(Reki), dimension(:,:), allocatable :: M + real(Reki), dimension(:,:), allocatable :: tmp + integer(IntKi) :: I,J + ! Storing M to a tmp array + call allocAry( tmp, size(M,1), size(M,2), 'MTimeTmp', ErrStat, ErrMsg); if(Failed()) return + tmp=M + ! Reallocating M and storing only the desired DOF + deallocate(M) + call allocAry(M, size(tmp,1), nActive, 'MTime', ErrStat, ErrMsg); if(Failed()) return + do I=1,size(tmp,1) + do J=1,nActive + M(I,J) = tmp(I, FullActiveCBDOF(J)) + enddo + enddo + deallocate(tmp) + end subroutine + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_ReduceNumberOfDOF') + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE ReduceNumberOfDOF + + +!.................................................................................................................................. +SUBROUTINE ReadReducedFile( InputFile, p, FileFormat, ErrStat, ErrMsg ) +!.................................................................................................................................. + ! Passed variables + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: p !< All the parameter matrices stored in this input file + INTEGER(IntKi), INTENT(IN) :: FileFormat !< File format for reduction inputs + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + ! Local variables: + REAL(ReKi), dimension(:),allocatable :: TmpAry ! temporary array for reading row from file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: iLine ! Current position in file + CHARACTER(4096) :: Line ! Temporary storage of a line from the input file (to compare with "default") + ErrStat = ErrID_None + ErrMsg = "" + if (FileFormat==FILEFORMAT_GUYANASCII) then + call ReadGuyanASCII() + elseif (FileFormat==FILEFORMAT_FLEXASCII) then + call ReadFlexASCII() + else + call SetErrStat(ErrID_Fatal, 'FileFormat not implemented: '//trim(Num2LStr(FileFormat)), ErrStat, ErrMsg, 'ExtPtfm_ReadReducedFile') + return + endif + ! --- The code below can detect between FlexASCII and GuyanASCII format by looking at the two first lines + ! Get an available unit number for the file. + !CALL GetNewUnit( UnIn, ErrStat, ErrMsg ); if(Failed()) return + !! Open the Primary input file. + !CALL OpenFInpFile ( UnIn, InputFile, ErrStat, ErrMsg ); if(Failed()) return + !iLine=1 + !!-------------------------- Read the first two lines + !CALL ReadStr( UnIn, InputFile, Line, 'Line'//Num2LStr(iLine), 'External Platform MCKF file', ErrStat, ErrMsg) + !if(Failed()) return + !iLine=iLine+1 + !CALL ReadStr( UnIn, InputFile, Line2, 'Line'//Num2LStr(iLine), 'External Platform MCKF file', ErrStat, ErrMsg) + !if(Failed()) return + !iLine=iLine+1 + !call CONV2UC(Line) + !call CONV2UC(Line2) + !call cleanup() + !!-------------------------- Detecting file format + !if (index(Line2,'#MASS')==1) then + ! write(*,*) 'File detected as Guyan ASCII file format: '//trim(InputFile) + ! call ReadGuyanASCII() + !else if (index(Line2,'FLEX 5 FORMAT')>=1) then + ! write(*,*) 'File detected as FLEX ASCII file format: '//trim(InputFile) + ! call ReadFlexASCII() + !endif + +CONTAINS + !> + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_ReadReducedFile') + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + !> + subroutine cleanup() + close( UnIn ) + if (allocated(TmpAry)) deallocate(TmpAry) + end subroutine cleanup + + !> Reads a FLEX ASCII file for Guyan or CraigBampton reductions + SUBROUTINE ReadFlexASCII() + REAL(ReKi) :: dt !< time step + REAL(ReKi) :: T !< total simulation time + + T=-1 + dt=-1 + ! Get an available unit number for the file. + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ); if ( ErrStat /= 0 ) return + ! Open the Primary input file. + CALL OpenFInpFile(UnIn, InputFile, ErrStat, ErrMsg); if ( ErrStat /= 0 ) return + + ! --- Reading file line by line + ErrStat=0 + iLine=0 + do while (ErrStat==0) + iLine=iLine+1 + read(UnIn,'(A)', iostat=ErrStat) Line + if (ErrStat/=0) then + if (ErrStat < 0) then + ErrStat=0 ! End of file is fine + else + ErrMsg='Error while reading file '//trim(InputFile)// ' line '//Num2LStr(iLine) + endif + exit + endif + ! Line content is analyzed as case incensitive + call Conv2UC(Line) + if (index(Line,'!DIMENSION')==1) then + p%nTot = ReadIntFromStr(Line(12:), '`dimension`, file '//trim(InputFile)//', line '//Num2LStr(iLine), ErrStat, ErrMsg); if (ErrStat /= 0) exit + p%nCB=p%nTot-6 + + else if (index(Line,'!TIME INCREMENT IN SIMULATION:')==1) then + dt = ReadFloatFromStr(Line(31:), '`time increment`, file '//trim(InputFile)//', line '//Num2LStr(iLine), ErrStat, ErrMsg); if (ErrStat /= 0) exit + + else if (index(Line,'!TOTAL SIMULATION TIME IN FILE:')==1) then + T = ReadFloatFromStr(Line(32:), '`total simulation time`, file '//trim(InputFile)//', line '//Num2LStr(iLine), ErrStat, ErrMsg ); if (ErrStat /= 0) exit + + else if (index(Line,'!MASS MATRIX')==1) then + iLine=iLine+1 + CALL ReadCom( UnIn, InputFile, 'Comment - Line '//Num2LStr(iLine), ErrStat, ErrMsg); if (ErrStat /= 0) exit + if (p%nTot<0) exit + call ReadRealMatrix(UnIn, InputFile, p%Mass, 'Mass Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + + else if (index(Line,'!STIFFNESS MATRIX')==1) then + iLine=iLine+1 + CALL ReadCom( UnIn, InputFile, 'Comment - Line '//Num2LStr(iLine), ErrStat, ErrMsg); if (ErrStat /= 0) exit + if (p%nTot<0) exit + call ReadRealMatrix(UnIn, InputFile, p%Stff, 'Stiffness Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + + else if (index(Line,'!DAMPING MATRIX')==1) then + iLine=iLine+1 + CALL ReadCom( UnIn, InputFile, 'Comment - Line '//Num2LStr(iLine), ErrStat, ErrMsg); if (ErrStat /= 0) exit + if (p%nTot<0) exit + call ReadRealMatrix(UnIn, InputFile, p%Damp, 'Damping Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + + else if (index(Line,'!LOADING')==1) then + iLine=iLine+1 + CALL ReadCom( UnIn, InputFile, 'Comment - Line '//Num2LStr(iLine), ErrStat, ErrMsg) + if (ErrStat /= 0) exit + p%nTimeSteps = nint(T/dt)+1 + if (p%nTot<0) exit + call allocAry( p%Forces, max(1,p%nTimeSteps), p%nTot, 'p%Forces' , ErrStat, ErrMsg); if (ErrStat /= 0) exit + call allocAry( p%times , max(1,p%nTimeSteps), 'p%times', ErrStat, ErrMsg); if (ErrStat /= 0) exit + if (p%nTimeSteps == 0) then + p%Forces= 0.0_ReKi + p%times = 0.0_ReKi + p%nTimeSteps = 1 + else + allocate(TmpAry(1:p%nTot+1)) + do i=1,p%nTimeSteps + iLine=iLine+1 + TmpAry(1:p%nTot+1)=-999.9E-09 + read(UnIn, fmt='(A)', iostat=ErrStat) Line + if (ErrStat/=0) then + ErrStat = ErrID_Fatal + ErrMSg='Failed to read line '//trim(Num2LStr(iLine))//' (out of '//trim(Num2LStr(p%nTimeSteps))//' expected lines) in file: '//trim(InputFile) + exit + end if + ! Extract fields (ReadR8AryFromStr is in NWTC_IO) + CALL ReadAry(Line, TmpAry, p%nTot+1, 'Forces', 'Forces', ErrStat, ErrMsg) + if (ErrStat/=0) then + ErrStat = ErrID_Fatal + ErrMsg='Failed to extract fields from line '//trim(Num2LStr(iLine))//'. '//trim(ErrMsg)//'. Check that the number of columns is correct in file: '//trim(InputFile) + exit + end if + if (ErrStat /= 0) exit + p%times(i) = TmpAry(1) + p%Forces(i,:) = TmpAry(2:p%nTot+1) + end do + end if + + elseif (index(Line,'!')==1) then + !write(*,*) 'Ignored comment: '//trim(Line) + else + ! Ignore unsupported lines + !write(*,*) 'Ignored line: '//trim(Line) + endif + enddo + close( UnIn ) + END SUBROUTINE ReadFlexASCII + + !> Reads a Guyan ASCII file + SUBROUTINE ReadGuyanASCII() + ! Guyan reduction has 6 DOF, 0 CB DOFs + p%nCB = 0 + p%nTot = 6 + ! Get an available unit number for the file. + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ); if ( ErrStat /= 0 ) return + ! Open the Primary input file. + CALL OpenFInpFile ( UnIn, InputFile, ErrStat, ErrMsg ); if ( ErrStat /= 0 ) return + + !-------------------------- HEADER --------------------------------------------- + CALL ReadStr( UnIn, InputFile, Line, 'Header line', 'File Header: External Platform MCKF Matrices (line 1)', ErrStat, ErrMsg) + if ( ErrStat /= 0 ) return + !---------------------- MASS MATRIX -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Mass Matrix', ErrStat, ErrMsg) + if ( ErrStat /= 0 ) return + CALL ReadRealMatrix(UnIn, InputFile, p%Mass, 'Mass Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + if ( ErrStat /= 0 ) return + !---------------------- DAMPING MATRIX -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Damping Matrix', ErrStat, ErrMsg) + if ( ErrStat /= 0 ) return + CALL ReadRealMatrix(UnIn, InputFile, p%Damp, 'Damping Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + if ( ErrStat /= 0 ) return + !---------------------- STIFFNESS MATRIX -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Stiffness Matrix', ErrStat, ErrMsg) + if ( ErrStat /= 0 ) return + CALL ReadRealMatrix(UnIn, InputFile, p%Stff, 'Stiffness Matrix', p%nTot, p%nTot, ErrStat, ErrMsg, iLine) + if ( ErrStat /= 0 ) return + !---------------------- LOAD time-history -------------------------------------- + p%nTimeSteps = 0 + CALL ReadCom( UnIn, InputFile, 'Section Header: Loads time-history', ErrStat, ErrMsg) + CALL ReadCom( UnIn, InputFile, 'Loads time-history table channel names', ErrStat, ErrMsg) + CALL ReadCom( UnIn, InputFile, 'Loads time-history table channel units', ErrStat, ErrMsg) + allocate(TmpAry(1:p%nTot+1)) + if (ErrStat < AbortErrLev) then + ! let's figure out how many rows of data are in the time-history table: + read( UnIn, *, IOSTAT=ErrStat ) TmpAry + do while (ErrStat==0) + p%nTimeSteps = p%nTimeSteps + 1 + read( UnIn, *, IOSTAT=ErrStat ) TmpAry + end do + end if + call allocAry( p%Forces, max(1,p%nTimeSteps), p%nTot, 'p%Forces', ErrStat, ErrMsg); if ( ErrStat /= 0 ) return + call allocAry( p%times , max(1,p%nTimeSteps), 'p%times' , ErrStat, ErrMsg); if ( ErrStat /= 0 ) return + if (p%nTimeSteps == 0) then + p%Forces = 0.0_ReKi + p%times = 0.0_ReKi + p%nTimeSteps = 1 + else + rewind(UnIn) + do i=1,25 ! skip the first 25 rows of the file until we get to the data for the time-history table + read(UnIn,*,IOSTAT=ErrStat) line + end do + do i=1,p%nTimeSteps + read(UnIn, fmt='(A)', iostat=ErrStat) Line + if (ErrStat/=0) then + ErrStat = ErrID_Fatal + ErrMSg='Failed to read line '//trim(Num2LStr(iLine))//' (out of '//trim(Num2LStr(p%nTimeSteps))//' expected lines) in file: '//trim(InputFile) + exit + end if + ! Extract fields (ReadR8AryFromStr is in NWTC_IO) + CALL ReadAry(Line, TmpAry, p%nTot+1, 'Forces', 'Forces', ErrStat, ErrMsg) + if (ErrStat/=0) then + ErrStat = ErrID_Fatal + ErrMsg='Failed to extract fields from line '//trim(Num2LStr(iLine))//'. '//trim(ErrMsg)//'. Check that the number of columns is correct in file: '//trim(InputFile) + exit + end if + if ( ErrStat /= 0 ) return + p%times(i) = TmpAry(1) + p%Forces(i,:) = TmpAry(2:p%nTot+1) + end do + end if + !---------------------- END OF FILE ----------------------------------------- + close( UnIn ) + END SUBROUTINE ReadGuyanASCII +END SUBROUTINE ReadReducedFile + +!> This routine generates the summary file, which contains a regurgitation of the input data and interpolated flexible body data. +SUBROUTINE ExtPtfm_PrintSum(x, p, m, RootName, ErrStat, ErrMsg) + ! passed variables + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN) :: x !< Initial continuous states + TYPE(ExtPtfm_ParameterType), INTENT(IN ) :: p !< Parameters of the structural dynamics module + TYPE(ExtPtfm_MiscVarType), INTENT(IN ) :: m !< Misc variables for optimization (not copied in glue code) + CHARACTER(*), INTENT(IN ) :: RootName !< Root Name to write the summary file + 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 ! Loop counter + INTEGER(IntKi) :: UnSu ! I/O unit number for the summary output file +! CHARACTER(*), PARAMETER :: Fmt1 = "(34X,3(6X,'Blade',I2,:))" ! Format for outputting blade headings. +! CHARACTER(*), PARAMETER :: Fmt2 = "(34X,3(6X,A,:))" ! Format for outputting blade headings. +! CHARACTER(*), PARAMETER :: FmtDat = '(A,T35,3(:,F13.3))' ! Format for outputting mass and modal data. +! CHARACTER(*), PARAMETER :: FmtDatT = '(A,T35,1(:,F13.8))' ! Format for outputting time steps. + CHARACTER(30) :: OutPFmtS ! Format to print list of selected output channel names to summary file + CHARACTER(30) :: OutPFmt ! Format to print list of selected output channels to summary file + CHARACTER(ChanLen),PARAMETER :: TitleStr(2) = (/ 'Parameter', 'Units ' /) + CHARACTER(ChanLen),PARAMETER :: TitleStrLines(2) = (/ '---------------', '---------------' /) + ErrStat = ErrID_None + ErrMsg = "" + ! TODO TODO TODO YAML FORMAT + ! TODO TODO TODO ONLY Open Summary if no optional unit given + + ! Open the summary file and give it a heading. + CALL GetNewUnit(UnSu, ErrStat, ErrMsg); + CALL OpenFOutFile(UnSu, TRIM( RootName )//'.sum', ErrStat, ErrMsg) + IF ( ErrStat /= ErrID_None ) RETURN + ! Heading: + WRITE (UnSu,'(/,A)') '!This summary information was generated by '//TRIM( GetNVD(ExtPtfm_Ver) )// & + ' on '//CurDate()//' at '//CurTime()//'.' + + write(UnSu,'(A)') '!Module input file' + write(UnSu,'(A,A)') 'Time integration method : ',StrIntMethod(p%IntMethod) + write(UnSu,'(A,F13.8)')'Integration time step : ',p%EP_DeltaT + write(UnSu,'(A)') '!Reduction input file' + write(UnSu,'(A,I0)') 'Number of time steps : ',p%nTimeSteps + write(UnSu,'(A,F13.8)')'Start time : ',p%times(1) + write(UnSu,'(A,F13.8)')'End time : ',p%times(p%nTimeSteps) + write(UnSu,'(A,I0)') 'Total number of DOF (input) : ',p%nCBFull+6 + write(UnSu,'(A,I0)') 'Number of CB modes (input) : ',p%nCBFull + write(UnSu,'(A)') '!Degrees of freedom' + write(UnSu,'(A,I0)') 'Total number of DOF (active) : ',p%nTot + write(UnSu,'(A,I0)') 'Number of CB modes (active) : ',p%nCB + call disp1i(UnSu, 'ActiveCBDOF',p%ActiveCBDOF) +! + if (m%EquilStart) then + write(UnSu,'(A)')'!Initial conditions (before equilibrium)' + else + write(UnSu,'(A)')'!Initial conditions (no equilibrium will be computed)' + endif + call disp1r8(UnSu, 'qm' ,x%qm) + call disp1r8(UnSu, 'qmdot',x%qmdot) + + write(UnSu,'(A)')'!State matrices' + call disp2r8(UnSu, 'A',p%AMat) + call disp2r8(UnSu, 'B',p%BMat) + call disp2r8(UnSu, 'C',p%CMat) + call disp2r8(UnSu, 'D',p%DMat) + write(UnSu,'(A)')'!Input matrices' + call disp2r8(UnSu, 'M',p%Mass) + call disp2r8(UnSu, 'K',p%Stff) + call disp2r8(UnSu, 'C',p%Damp) +! call disp2r8(UnSu, 'F',p%Forces) + write(UnSu,'(A)')'!Input sub-matrices' + call disp2r8(UnSu, 'M11',p%M11) + call disp2r8(UnSu, 'M12',p%M12) + call disp2r8(UnSu, 'M21',p%M21) + call disp2r8(UnSu, 'M22',p%M22) + call disp2r8(UnSu, 'K11',p%K11) + call disp2r8(UnSu, 'K22',p%K22) + call disp2r8(UnSu, 'C11',p%C11) + call disp2r8(UnSu, 'C12',p%C12) + call disp2r8(UnSu, 'C21',p%C21) + call disp2r8(UnSu, 'C22',p%C22) + + OutPFmt = '( I4, 3X,A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + OutPFmtS = '( A4, 3X,A '//TRIM(Num2LStr(ChanLen))//',1 X, A'//TRIM(Num2LStr(ChanLen))//' )' + write(UnSu,'(//,A,//)') '!Requested Outputs:' + write(UnSu,OutPFmtS) "Col", TitleStr + write(UnSu,OutPFmtS) "---", TitleStrLines + DO I = 0,p%NumOuts + write (UnSu,OutPFmt) I, p%OutParam(I)%Name, p%OutParam(I)%Units + END DO + + call cleanup() + +CONTAINS + !> + logical function Failed() + CALL SetErrStatSimple(ErrStat, ErrMsg, 'ExtPtfm_PrintSum') + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + !> + subroutine cleanup() + if (UnSu>0) close(UnSu) + end subroutine cleanup +END SUBROUTINE ExtPtfm_PrintSum + +END MODULE ExtPtfm_MCKF_IO diff --git a/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt new file mode 100644 index 000000000..df8b051a8 --- /dev/null +++ b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt @@ -0,0 +1,129 @@ +################################################################################################################################### +# Registry for ExtPtfm_MCKF in the FAST Modularization Framework +# This Registry file is used to create MODULE ExtPtfm_MCKF_Types, which contains all of the user-defined types needed in ExtPtfm_MCKF. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# +# Entries are of the form +# keyword <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value from the previous line. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef ExtPtfm_MCKF/ExtPtfm InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ ^ LOGICAL Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ ^ ReKi PtfmRefzt - - - "Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point" meters +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" + +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary Input file data ........................................................................................................... +typedef ExtPtfm_MCKF/ExtPtfm ExtPtfm_InputFile DbKi DT - - - "Requested integration time for ElastoDyn" seconds +typedef ^ ^ IntKi IntMethod - - - "Integration Method (1=RK4, 2=AB4, 3=ABM4)" - +typedef ^ ^ IntKi FileFormat - - - "File format switch" - +typedef ^ ^ CHARACTER(1024) RedFile - - - "File containing reduction inputs" - +typedef ^ ^ CHARACTER(1024) RedFileCst - - - "File containing constant reduction inputs" - +typedef ^ ^ LOGICAL EquilStart - - - "Flag to determine the equilibrium positions of the CB modes at initialization (first call)" - +typedef ^ ^ IntKi ActiveCBDOF {:} - - "List of active CB DOF" - +typedef ^ ^ ReKi InitPosList {:} - - "Initial positions of the CB DOFs" - +typedef ^ ^ ReKi InitVelList {:} - - "Initial velocities of the CB DOFs" - +typedef ^ ^ LOGICAL SumPrint - - - "Print summary data to <RootName>.sum" - +typedef ^ ^ IntKi OutFile - - - "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both)" - +typedef ^ ^ LOGICAL TabDelim - - - "Flag to cause tab-delimited text output (delimited by space otherwise)" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "Format used for module's text tabular output (except time); resulting field should be 10 characters" - +typedef ^ ^ DbKi Tstart - - - "Time to start module's tabular output" seconds +typedef ^ ^ IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ^ CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - + + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ ^ LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +typedef ^ ^ LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +typedef ^ ^ LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi qm {:} - - "Internal CraigBampton positions" - +typedef ^ ContinuousStateType ReKi qmdot {:} - - "Internal CraigBampton velocities" - + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - + +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - + +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType ExtPtfm_ContinuousStateType xdot {:} - - "Previous state derivs for m-step time integrator" +typedef ^ ^ IntKi n - - - "Tracks time step for which OtherState was updated last" +#typedef ^ OtherStateType IntKi 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 xFlat {:} - - "Flattened vector of states" +typedef ^ MiscVarType ReKi uFlat {18} - - "Flattened vector of inputs" +typedef ^ MiscVarType ReKi F_at_t {:} - - "The 6 interface loads and Craig-Bampton loads at t (force and moment acting at the platform reference (no added-mass effects); positive forces are in the direction of motion)." "N, N-m" +typedef ^ MiscVarType IntKi Indx - - - "Index into times, to speed up interpolation" - +typedef ^ MiscVarType LOGICAL EquilStart - - - "Flag to determine the equilibrium position of the CB DOF at initialization (first call)" - +typedef ^ ^ ReKi AllOuts {:} - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" + + +# ..... 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 Mass {:}{:} - - "Mass matrix" "kg, kg-m, kg-m^2" +typedef ^ ParameterType ReKi Damp {:}{:} - - "Damping matrix" - +typedef ^ ParameterType ReKi Stff {:}{:} - - "Stiffness matrix" - +typedef ^ ParameterType ReKi Forces {:}{:} - - "Prescribed reduced loads, the 3 platform forces (in N) and moments (Nm) acting at the platform reference, associated with everything but the added-mass effects; positive forces are in the direction of motion." "N, N-m" +typedef ^ ^ ReKi times {:} - - "the time associated with each row of Forces" "s" +typedef ^ ^ ReKi AMat {:}{:} - - "State matrix A" "" +typedef ^ ^ ReKi BMat {:}{:} - - "State matrix B" "" +typedef ^ ^ ReKi CMat {:}{:} - - "State matrix C" "" +typedef ^ ^ ReKi DMat {:}{:} - - "State matrix D" "" +typedef ^ ^ ReKi FX {:} - - "State constant Fx" "" +typedef ^ ^ ReKi FY {:} - - "Output constant Fy" "" +typedef ^ ^ ReKi M11 {:}{:} - - "Matrix M11" "" +typedef ^ ^ ReKi M12 {:}{:} - - "Matrix M12" "" +typedef ^ ^ ReKi M22 {:}{:} - - "Matrix M22" "" +typedef ^ ^ ReKi M21 {:}{:} - - "Matrix M21" "" +typedef ^ ^ ReKi K11 {:}{:} - - "Matrix K11" "" +typedef ^ ^ ReKi K22 {:}{:} - - "Matrix K22" "" +typedef ^ ^ ReKi C11 {:}{:} - - "Matrix C11" "" +typedef ^ ^ ReKi C12 {:}{:} - - "Matrix C12" "" +typedef ^ ^ ReKi C22 {:}{:} - - "Matrix C22" "" +typedef ^ ^ ReKi C21 {:}{:} - - "Matrix C21" "" +typedef ^ ^ DbKi EP_DeltaT - - - "Time step (for integration of continuous states)" "seconds" +typedef ^ ^ IntKi nTimeSteps - - - "Number of values of Forces and times" - +typedef ^ ^ IntKi nCB - - - "Number of CraigBampton modes active" - +typedef ^ ^ IntKi nCBFull - - - "Totla number of CraigBampton modes given as input" - +typedef ^ ^ IntKi nTot - - - "Total number of debrees of freedom (CB + interface)" - +typedef ^ ^ IntKi NumOuts - - - "Number of values in WriteOutput" - +typedef ^ ^ IntKi IntMethod - - - "Integration Method (1=RK4, 2=AB4, 3=ABM4)" - +typedef ^ ^ IntKi ActiveCBDOF {:} - - "List of active CB DOF" - +typedef ^ ^ OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ^ IntKi OutParamLinIndx {:}{:} - - "Index into WriteOutput for linearization analysis" - + +# ..... Inputs .................................................................................................................... +typedef ^ InputType MeshType PtfmMesh - - - "Displacements at the platform reference point" - + + +# ..... Outputs ................................................................................................................... +typedef ^ OutputType MeshType PtfmMesh - - - "Loads at the platform reference point" - +typedef ^ ^ ReKi WriteOutput {:} - - "Example of data to be written to an output file" "s,-" + diff --git a/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 new file mode 100644 index 000000000..dcd7770cc --- /dev/null +++ b/OpenFAST/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 @@ -0,0 +1,5046 @@ +!STARTOFREGISTRYGENERATEDFILE 'ExtPtfm_MCKF_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 +!********************************************************************************************************************************* +! ExtPtfm_MCKF_Types +!................................................................................................................................. +! This file is part of ExtPtfm_MCKF. +! +! 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 ExtPtfm_MCKF. 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 ExtPtfm_MCKF_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= ExtPtfm_InitInputType ======= + TYPE, PUBLIC :: ExtPtfm_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + REAL(ReKi) :: PtfmRefzt !< Vertical distance from the ground [onshore] or MSL [offshore] to the platform reference point [meters] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + END TYPE ExtPtfm_InitInputType +! ======================= +! ========= ExtPtfm_InputFile ======= + TYPE, PUBLIC :: ExtPtfm_InputFile + REAL(DbKi) :: DT !< Requested integration time for ElastoDyn [seconds] + INTEGER(IntKi) :: IntMethod !< Integration Method (1=RK4, 2=AB4, 3=ABM4) [-] + INTEGER(IntKi) :: FileFormat !< File format switch [-] + CHARACTER(1024) :: RedFile !< File containing reduction inputs [-] + CHARACTER(1024) :: RedFileCst !< File containing constant reduction inputs [-] + LOGICAL :: EquilStart !< Flag to determine the equilibrium positions of the CB modes at initialization (first call) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ActiveCBDOF !< List of active CB DOF [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: InitPosList !< Initial positions of the CB DOFs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: InitVelList !< Initial velocities of the CB DOFs [-] + LOGICAL :: SumPrint !< Print summary data to <RootName>.sum [-] + INTEGER(IntKi) :: OutFile !< Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) [-] + LOGICAL :: TabDelim !< Flag to cause tab-delimited text output (delimited by space otherwise) [-] + CHARACTER(20) :: OutFmt !< Format used for module's text tabular output (except time); resulting field should be 10 characters [-] + REAL(DbKi) :: Tstart !< Time to start module's tabular output [seconds] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + END TYPE ExtPtfm_InputFile +! ======================= +! ========= ExtPtfm_InitOutputType ======= + TYPE, PUBLIC :: ExtPtfm_InitOutputType + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + END TYPE ExtPtfm_InitOutputType +! ======================= +! ========= ExtPtfm_ContinuousStateType ======= + TYPE, PUBLIC :: ExtPtfm_ContinuousStateType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qm !< Internal CraigBampton positions [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdot !< Internal CraigBampton velocities [-] + END TYPE ExtPtfm_ContinuousStateType +! ======================= +! ========= ExtPtfm_DiscreteStateType ======= + TYPE, PUBLIC :: ExtPtfm_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE ExtPtfm_DiscreteStateType +! ======================= +! ========= ExtPtfm_ConstraintStateType ======= + TYPE, PUBLIC :: ExtPtfm_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE ExtPtfm_ConstraintStateType +! ======================= +! ========= ExtPtfm_OtherStateType ======= + TYPE, PUBLIC :: ExtPtfm_OtherStateType + TYPE(ExtPtfm_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< Previous state derivs for m-step time integrator [-] + INTEGER(IntKi) :: n !< Tracks time step for which OtherState was updated last [-] + END TYPE ExtPtfm_OtherStateType +! ======================= +! ========= ExtPtfm_MiscVarType ======= + TYPE, PUBLIC :: ExtPtfm_MiscVarType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: xFlat !< Flattened vector of states [-] + REAL(ReKi) , DIMENSION(1:18) :: uFlat !< Flattened vector of inputs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F_at_t !< The 6 interface loads and Craig-Bampton loads at t (force and moment acting at the platform reference (no added-mass effects); positive forces are in the direction of motion). [N, N-m] + INTEGER(IntKi) :: Indx !< Index into times, to speed up interpolation [-] + LOGICAL :: EquilStart !< Flag to determine the equilibrium position of the CB DOF at initialization (first call) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [see OutListParameters.xlsx spreadsheet] + END TYPE ExtPtfm_MiscVarType +! ======================= +! ========= ExtPtfm_ParameterType ======= + TYPE, PUBLIC :: ExtPtfm_ParameterType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Mass !< Mass matrix [kg, kg-m, kg-m^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Damp !< Damping matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Stff !< Stiffness matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Forces !< Prescribed reduced loads, the 3 platform forces (in N) and moments (Nm) acting at the platform reference, associated with everything but the added-mass effects; positive forces are in the direction of motion. [N, N-m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: times !< the time associated with each row of Forces [s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AMat !< State matrix A [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BMat !< State matrix B [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMat !< State matrix C [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DMat !< State matrix D [] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< State constant Fx [] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Output constant Fy [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M11 !< Matrix M11 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M12 !< Matrix M12 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M22 !< Matrix M22 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M21 !< Matrix M21 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K11 !< Matrix K11 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K22 !< Matrix K22 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C11 !< Matrix C11 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C12 !< Matrix C12 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C22 !< Matrix C22 [] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C21 !< Matrix C21 [] + REAL(DbKi) :: EP_DeltaT !< Time step (for integration of continuous states) [seconds] + INTEGER(IntKi) :: nTimeSteps !< Number of values of Forces and times [-] + INTEGER(IntKi) :: nCB !< Number of CraigBampton modes active [-] + INTEGER(IntKi) :: nCBFull !< Totla number of CraigBampton modes given as input [-] + INTEGER(IntKi) :: nTot !< Total number of debrees of freedom (CB + interface) [-] + INTEGER(IntKi) :: NumOuts !< Number of values in WriteOutput [-] + INTEGER(IntKi) :: IntMethod !< Integration Method (1=RK4, 2=AB4, 3=ABM4) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ActiveCBDOF !< List of active CB DOF [-] + 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 linearization analysis [-] + END TYPE ExtPtfm_ParameterType +! ======================= +! ========= ExtPtfm_InputType ======= + TYPE, PUBLIC :: ExtPtfm_InputType + TYPE(MeshType) :: PtfmMesh !< Displacements at the platform reference point [-] + END TYPE ExtPtfm_InputType +! ======================= +! ========= ExtPtfm_OutputType ======= + TYPE, PUBLIC :: ExtPtfm_OutputType + TYPE(MeshType) :: PtfmMesh !< Loads at the platform reference point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Example of data to be written to an output file [s,-] + END TYPE ExtPtfm_OutputType +! ======================= +CONTAINS + SUBROUTINE ExtPtfm_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(ExtPtfm_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 = 'ExtPtfm_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%PtfmRefzt = SrcInitInputData%PtfmRefzt + DstInitInputData%RootName = SrcInitInputData%RootName + END SUBROUTINE ExtPtfm_CopyInitInput + + SUBROUTINE ExtPtfm_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ExtPtfm_DestroyInitInput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! Linearize + Re_BufSz = Re_BufSz + 1 ! PtfmRefzt + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmRefzt + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE ExtPtfm_PackInitInput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmRefzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE ExtPtfm_UnPackInitInput + + SUBROUTINE ExtPtfm_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(ExtPtfm_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'ExtPtfm_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DT = SrcInputFileData%DT + DstInputFileData%IntMethod = SrcInputFileData%IntMethod + DstInputFileData%FileFormat = SrcInputFileData%FileFormat + DstInputFileData%RedFile = SrcInputFileData%RedFile + DstInputFileData%RedFileCst = SrcInputFileData%RedFileCst + DstInputFileData%EquilStart = SrcInputFileData%EquilStart +IF (ALLOCATED(SrcInputFileData%ActiveCBDOF)) THEN + i1_l = LBOUND(SrcInputFileData%ActiveCBDOF,1) + i1_u = UBOUND(SrcInputFileData%ActiveCBDOF,1) + IF (.NOT. ALLOCATED(DstInputFileData%ActiveCBDOF)) THEN + ALLOCATE(DstInputFileData%ActiveCBDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ActiveCBDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ActiveCBDOF = SrcInputFileData%ActiveCBDOF +ENDIF +IF (ALLOCATED(SrcInputFileData%InitPosList)) THEN + i1_l = LBOUND(SrcInputFileData%InitPosList,1) + i1_u = UBOUND(SrcInputFileData%InitPosList,1) + IF (.NOT. ALLOCATED(DstInputFileData%InitPosList)) THEN + ALLOCATE(DstInputFileData%InitPosList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%InitPosList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%InitPosList = SrcInputFileData%InitPosList +ENDIF +IF (ALLOCATED(SrcInputFileData%InitVelList)) THEN + i1_l = LBOUND(SrcInputFileData%InitVelList,1) + i1_u = UBOUND(SrcInputFileData%InitVelList,1) + IF (.NOT. ALLOCATED(DstInputFileData%InitVelList)) THEN + ALLOCATE(DstInputFileData%InitVelList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%InitVelList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%InitVelList = SrcInputFileData%InitVelList +ENDIF + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%OutFile = SrcInputFileData%OutFile + DstInputFileData%TabDelim = SrcInputFileData%TabDelim + DstInputFileData%OutFmt = SrcInputFileData%OutFmt + DstInputFileData%Tstart = SrcInputFileData%Tstart + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + END SUBROUTINE ExtPtfm_CopyInputFile + + SUBROUTINE ExtPtfm_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%ActiveCBDOF)) THEN + DEALLOCATE(InputFileData%ActiveCBDOF) +ENDIF +IF (ALLOCATED(InputFileData%InitPosList)) THEN + DEALLOCATE(InputFileData%InitPosList) +ENDIF +IF (ALLOCATED(InputFileData%InitVelList)) THEN + DEALLOCATE(InputFileData%InitVelList) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF + END SUBROUTINE ExtPtfm_DestroyInputFile + + SUBROUTINE ExtPtfm_PackInputFile( 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(ExtPtfm_InputFile), 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 = 'ExtPtfm_PackInputFile' + ! 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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! FileFormat + Int_BufSz = Int_BufSz + 1*LEN(InData%RedFile) ! RedFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RedFileCst) ! RedFileCst + Int_BufSz = Int_BufSz + 1 ! EquilStart + Int_BufSz = Int_BufSz + 1 ! ActiveCBDOF allocated yes/no + IF ( ALLOCATED(InData%ActiveCBDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActiveCBDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ActiveCBDOF) ! ActiveCBDOF + END IF + Int_BufSz = Int_BufSz + 1 ! InitPosList allocated yes/no + IF ( ALLOCATED(InData%InitPosList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InitPosList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InitPosList) ! InitPosList + END IF + Int_BufSz = Int_BufSz + 1 ! InitVelList allocated yes/no + IF ( ALLOCATED(InData%InitVelList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InitVelList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%InitVelList) ! InitVelList + END IF + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! OutFile + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Db_BufSz = Db_BufSz + 1 ! Tstart + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%FileFormat + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RedFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%RedFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RedFileCst) + IntKiBuf(Int_Xferred) = ICHAR(InData%RedFileCst(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%EquilStart, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ActiveCBDOF) ) 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%ActiveCBDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActiveCBDOF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActiveCBDOF,1), UBOUND(InData%ActiveCBDOF,1) + IntKiBuf(Int_Xferred) = InData%ActiveCBDOF(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InitPosList) ) 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%InitPosList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InitPosList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InitPosList,1), UBOUND(InData%InitPosList,1) + ReKiBuf(Re_Xferred) = InData%InitPosList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%InitVelList) ) 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%InitVelList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InitVelList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InitVelList,1), UBOUND(InData%InitVelList,1) + ReKiBuf(Re_Xferred) = InData%InitVelList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%Tstart + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE ExtPtfm_PackInputFile + + SUBROUTINE ExtPtfm_UnPackInputFile( 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(ExtPtfm_InputFile), 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 = 'ExtPtfm_UnPackInputFile' + ! 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FileFormat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RedFile) + OutData%RedFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RedFileCst) + OutData%RedFileCst(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%EquilStart = TRANSFER(IntKiBuf(Int_Xferred), OutData%EquilStart) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ActiveCBDOF 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%ActiveCBDOF)) DEALLOCATE(OutData%ActiveCBDOF) + ALLOCATE(OutData%ActiveCBDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActiveCBDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActiveCBDOF,1), UBOUND(OutData%ActiveCBDOF,1) + OutData%ActiveCBDOF(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InitPosList 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%InitPosList)) DEALLOCATE(OutData%InitPosList) + ALLOCATE(OutData%InitPosList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InitPosList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InitPosList,1), UBOUND(OutData%InitPosList,1) + OutData%InitPosList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InitVelList 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%InitVelList)) DEALLOCATE(OutData%InitVelList) + ALLOCATE(OutData%InitVelList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InitVelList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InitVelList,1), UBOUND(OutData%InitVelList,1) + OutData%InitVelList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%OutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Tstart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackInputFile + + SUBROUTINE ExtPtfm_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(ExtPtfm_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 = 'ExtPtfm_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 +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF + END SUBROUTINE ExtPtfm_CopyInitOutput + + SUBROUTINE ExtPtfm_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF + END SUBROUTINE ExtPtfm_DestroyInitOutput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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 + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) 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%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) 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%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_PackInitOutput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x 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%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x 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%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackInitOutput + + SUBROUTINE ExtPtfm_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%qm)) THEN + i1_l = LBOUND(SrcContStateData%qm,1) + i1_u = UBOUND(SrcContStateData%qm,1) + IF (.NOT. ALLOCATED(DstContStateData%qm)) THEN + ALLOCATE(DstContStateData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qm = SrcContStateData%qm +ENDIF +IF (ALLOCATED(SrcContStateData%qmdot)) THEN + i1_l = LBOUND(SrcContStateData%qmdot,1) + i1_u = UBOUND(SrcContStateData%qmdot,1) + IF (.NOT. ALLOCATED(DstContStateData%qmdot)) THEN + ALLOCATE(DstContStateData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qmdot = SrcContStateData%qmdot +ENDIF + END SUBROUTINE ExtPtfm_CopyContState + + SUBROUTINE ExtPtfm_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%qm)) THEN + DEALLOCATE(ContStateData%qm) +ENDIF +IF (ALLOCATED(ContStateData%qmdot)) THEN + DEALLOCATE(ContStateData%qmdot) +ENDIF + END SUBROUTINE ExtPtfm_DestroyContState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 + Int_BufSz = Int_BufSz + 1 ! qm allocated yes/no + IF ( ALLOCATED(InData%qm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qm) ! qm + END IF + Int_BufSz = Int_BufSz + 1 ! qmdot allocated yes/no + IF ( ALLOCATED(InData%qmdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qmdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qmdot) ! qmdot + 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%qm) ) 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%qm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%qm,1), UBOUND(InData%qm,1) + ReKiBuf(Re_Xferred) = InData%qm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%qmdot) ) 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%qmdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%qmdot,1), UBOUND(InData%qmdot,1) + ReKiBuf(Re_Xferred) = InData%qmdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_PackContState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qm 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%qm)) DEALLOCATE(OutData%qm) + ALLOCATE(OutData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%qm,1), UBOUND(OutData%qm,1) + OutData%qm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdot 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%qmdot)) DEALLOCATE(OutData%qmdot) + ALLOCATE(OutData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%qmdot,1), UBOUND(OutData%qmdot,1) + OutData%qmdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackContState + + SUBROUTINE ExtPtfm_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(ExtPtfm_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 = 'ExtPtfm_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE ExtPtfm_CopyDiscState + + SUBROUTINE ExtPtfm_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ExtPtfm_DestroyDiscState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ExtPtfm_PackDiscState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ExtPtfm_UnPackDiscState + + SUBROUTINE ExtPtfm_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(ExtPtfm_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 = 'ExtPtfm_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE ExtPtfm_CopyConstrState + + SUBROUTINE ExtPtfm_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ExtPtfm_DestroyConstrState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ExtPtfm_PackConstrState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ExtPtfm_UnPackConstrState + + SUBROUTINE ExtPtfm_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(ExtPtfm_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%xdot)) THEN + i1_l = LBOUND(SrcOtherStateData%xdot,1) + i1_u = UBOUND(SrcOtherStateData%xdot,1) + IF (.NOT. ALLOCATED(DstOtherStateData%xdot)) THEN + ALLOCATE(DstOtherStateData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL ExtPtfm_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstOtherStateData%n = SrcOtherStateData%n + END SUBROUTINE ExtPtfm_CopyOtherState + + SUBROUTINE ExtPtfm_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%xdot)) THEN +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL ExtPtfm_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OtherStateData%xdot) +ENDIF + END SUBROUTINE ExtPtfm_DestroyOtherState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 + Int_BufSz = Int_BufSz + 1 ! xdot allocated yes/no + IF ( ALLOCATED(InData%xdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xdot upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! n + 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%xdot) ) 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%xdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 + IntKiBuf(Int_Xferred) = InData%n + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ExtPtfm_PackOtherState + + SUBROUTINE ExtPtfm_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(ExtPtfm_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdot 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%xdot)) DEALLOCATE(OutData%xdot) + ALLOCATE(OutData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 ExtPtfm_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END IF + OutData%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ExtPtfm_UnPackOtherState + + SUBROUTINE ExtPtfm_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%xFlat)) THEN + i1_l = LBOUND(SrcMiscData%xFlat,1) + i1_u = UBOUND(SrcMiscData%xFlat,1) + IF (.NOT. ALLOCATED(DstMiscData%xFlat)) THEN + ALLOCATE(DstMiscData%xFlat(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%xFlat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%xFlat = SrcMiscData%xFlat +ENDIF + DstMiscData%uFlat = SrcMiscData%uFlat +IF (ALLOCATED(SrcMiscData%F_at_t)) THEN + i1_l = LBOUND(SrcMiscData%F_at_t,1) + i1_u = UBOUND(SrcMiscData%F_at_t,1) + IF (.NOT. ALLOCATED(DstMiscData%F_at_t)) THEN + ALLOCATE(DstMiscData%F_at_t(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_at_t.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%F_at_t = SrcMiscData%F_at_t +ENDIF + DstMiscData%Indx = SrcMiscData%Indx + DstMiscData%EquilStart = SrcMiscData%EquilStart +IF (ALLOCATED(SrcMiscData%AllOuts)) THEN + i1_l = LBOUND(SrcMiscData%AllOuts,1) + i1_u = UBOUND(SrcMiscData%AllOuts,1) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF + END SUBROUTINE ExtPtfm_CopyMisc + + SUBROUTINE ExtPtfm_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%xFlat)) THEN + DEALLOCATE(MiscData%xFlat) +ENDIF +IF (ALLOCATED(MiscData%F_at_t)) THEN + DEALLOCATE(MiscData%F_at_t) +ENDIF +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF + END SUBROUTINE ExtPtfm_DestroyMisc + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ! xFlat allocated yes/no + IF ( ALLOCATED(InData%xFlat) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xFlat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%xFlat) ! xFlat + END IF + Re_BufSz = Re_BufSz + SIZE(InData%uFlat) ! uFlat + Int_BufSz = Int_BufSz + 1 ! F_at_t allocated yes/no + IF ( ALLOCATED(InData%F_at_t) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F_at_t upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_at_t) ! F_at_t + END IF + Int_BufSz = Int_BufSz + 1 ! Indx + Int_BufSz = Int_BufSz + 1 ! EquilStart + 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 + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + 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%xFlat) ) 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%xFlat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xFlat,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xFlat,1), UBOUND(InData%xFlat,1) + ReKiBuf(Re_Xferred) = InData%xFlat(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%uFlat,1), UBOUND(InData%uFlat,1) + ReKiBuf(Re_Xferred) = InData%uFlat(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%F_at_t) ) 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%F_at_t,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_at_t,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_at_t,1), UBOUND(InData%F_at_t,1) + ReKiBuf(Re_Xferred) = InData%F_at_t(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Indx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%EquilStart, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_PackMisc + + SUBROUTINE ExtPtfm_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(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_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 ! xFlat 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%xFlat)) DEALLOCATE(OutData%xFlat) + ALLOCATE(OutData%xFlat(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xFlat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xFlat,1), UBOUND(OutData%xFlat,1) + OutData%xFlat(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%uFlat,1) + i1_u = UBOUND(OutData%uFlat,1) + DO i1 = LBOUND(OutData%uFlat,1), UBOUND(OutData%uFlat,1) + OutData%uFlat(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_at_t 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%F_at_t)) DEALLOCATE(OutData%F_at_t) + ALLOCATE(OutData%F_at_t(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_at_t.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_at_t,1), UBOUND(OutData%F_at_t,1) + OutData%F_at_t(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%EquilStart = TRANSFER(IntKiBuf(Int_Xferred), OutData%EquilStart) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOuts 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%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackMisc + + SUBROUTINE ExtPtfm_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ParameterType), INTENT(IN) :: SrcParamData + TYPE(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcParamData%Mass)) THEN + i1_l = LBOUND(SrcParamData%Mass,1) + i1_u = UBOUND(SrcParamData%Mass,1) + i2_l = LBOUND(SrcParamData%Mass,2) + i2_u = UBOUND(SrcParamData%Mass,2) + IF (.NOT. ALLOCATED(DstParamData%Mass)) THEN + ALLOCATE(DstParamData%Mass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Mass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Mass = SrcParamData%Mass +ENDIF +IF (ALLOCATED(SrcParamData%Damp)) THEN + i1_l = LBOUND(SrcParamData%Damp,1) + i1_u = UBOUND(SrcParamData%Damp,1) + i2_l = LBOUND(SrcParamData%Damp,2) + i2_u = UBOUND(SrcParamData%Damp,2) + IF (.NOT. ALLOCATED(DstParamData%Damp)) THEN + ALLOCATE(DstParamData%Damp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Damp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Damp = SrcParamData%Damp +ENDIF +IF (ALLOCATED(SrcParamData%Stff)) THEN + i1_l = LBOUND(SrcParamData%Stff,1) + i1_u = UBOUND(SrcParamData%Stff,1) + i2_l = LBOUND(SrcParamData%Stff,2) + i2_u = UBOUND(SrcParamData%Stff,2) + IF (.NOT. ALLOCATED(DstParamData%Stff)) THEN + ALLOCATE(DstParamData%Stff(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Stff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Stff = SrcParamData%Stff +ENDIF +IF (ALLOCATED(SrcParamData%Forces)) THEN + i1_l = LBOUND(SrcParamData%Forces,1) + i1_u = UBOUND(SrcParamData%Forces,1) + i2_l = LBOUND(SrcParamData%Forces,2) + i2_u = UBOUND(SrcParamData%Forces,2) + IF (.NOT. ALLOCATED(DstParamData%Forces)) THEN + ALLOCATE(DstParamData%Forces(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Forces.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Forces = SrcParamData%Forces +ENDIF +IF (ALLOCATED(SrcParamData%times)) THEN + i1_l = LBOUND(SrcParamData%times,1) + i1_u = UBOUND(SrcParamData%times,1) + IF (.NOT. ALLOCATED(DstParamData%times)) THEN + ALLOCATE(DstParamData%times(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%times.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%times = SrcParamData%times +ENDIF +IF (ALLOCATED(SrcParamData%AMat)) THEN + i1_l = LBOUND(SrcParamData%AMat,1) + i1_u = UBOUND(SrcParamData%AMat,1) + i2_l = LBOUND(SrcParamData%AMat,2) + i2_u = UBOUND(SrcParamData%AMat,2) + IF (.NOT. ALLOCATED(DstParamData%AMat)) THEN + ALLOCATE(DstParamData%AMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AMat = SrcParamData%AMat +ENDIF +IF (ALLOCATED(SrcParamData%BMat)) THEN + i1_l = LBOUND(SrcParamData%BMat,1) + i1_u = UBOUND(SrcParamData%BMat,1) + i2_l = LBOUND(SrcParamData%BMat,2) + i2_u = UBOUND(SrcParamData%BMat,2) + IF (.NOT. ALLOCATED(DstParamData%BMat)) THEN + ALLOCATE(DstParamData%BMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BMat = SrcParamData%BMat +ENDIF +IF (ALLOCATED(SrcParamData%CMat)) THEN + i1_l = LBOUND(SrcParamData%CMat,1) + i1_u = UBOUND(SrcParamData%CMat,1) + i2_l = LBOUND(SrcParamData%CMat,2) + i2_u = UBOUND(SrcParamData%CMat,2) + IF (.NOT. ALLOCATED(DstParamData%CMat)) THEN + ALLOCATE(DstParamData%CMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CMat = SrcParamData%CMat +ENDIF +IF (ALLOCATED(SrcParamData%DMat)) THEN + i1_l = LBOUND(SrcParamData%DMat,1) + i1_u = UBOUND(SrcParamData%DMat,1) + i2_l = LBOUND(SrcParamData%DMat,2) + i2_u = UBOUND(SrcParamData%DMat,2) + IF (.NOT. ALLOCATED(DstParamData%DMat)) THEN + ALLOCATE(DstParamData%DMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DMat = SrcParamData%DMat +ENDIF +IF (ALLOCATED(SrcParamData%FX)) THEN + i1_l = LBOUND(SrcParamData%FX,1) + i1_u = UBOUND(SrcParamData%FX,1) + IF (.NOT. ALLOCATED(DstParamData%FX)) THEN + ALLOCATE(DstParamData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FX = SrcParamData%FX +ENDIF +IF (ALLOCATED(SrcParamData%FY)) THEN + i1_l = LBOUND(SrcParamData%FY,1) + i1_u = UBOUND(SrcParamData%FY,1) + IF (.NOT. ALLOCATED(DstParamData%FY)) THEN + ALLOCATE(DstParamData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FY = SrcParamData%FY +ENDIF +IF (ALLOCATED(SrcParamData%M11)) THEN + i1_l = LBOUND(SrcParamData%M11,1) + i1_u = UBOUND(SrcParamData%M11,1) + i2_l = LBOUND(SrcParamData%M11,2) + i2_u = UBOUND(SrcParamData%M11,2) + IF (.NOT. ALLOCATED(DstParamData%M11)) THEN + ALLOCATE(DstParamData%M11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%M11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%M11 = SrcParamData%M11 +ENDIF +IF (ALLOCATED(SrcParamData%M12)) THEN + i1_l = LBOUND(SrcParamData%M12,1) + i1_u = UBOUND(SrcParamData%M12,1) + i2_l = LBOUND(SrcParamData%M12,2) + i2_u = UBOUND(SrcParamData%M12,2) + IF (.NOT. ALLOCATED(DstParamData%M12)) THEN + ALLOCATE(DstParamData%M12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%M12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%M12 = SrcParamData%M12 +ENDIF +IF (ALLOCATED(SrcParamData%M22)) THEN + i1_l = LBOUND(SrcParamData%M22,1) + i1_u = UBOUND(SrcParamData%M22,1) + i2_l = LBOUND(SrcParamData%M22,2) + i2_u = UBOUND(SrcParamData%M22,2) + IF (.NOT. ALLOCATED(DstParamData%M22)) THEN + ALLOCATE(DstParamData%M22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%M22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%M22 = SrcParamData%M22 +ENDIF +IF (ALLOCATED(SrcParamData%M21)) THEN + i1_l = LBOUND(SrcParamData%M21,1) + i1_u = UBOUND(SrcParamData%M21,1) + i2_l = LBOUND(SrcParamData%M21,2) + i2_u = UBOUND(SrcParamData%M21,2) + IF (.NOT. ALLOCATED(DstParamData%M21)) THEN + ALLOCATE(DstParamData%M21(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%M21.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%M21 = SrcParamData%M21 +ENDIF +IF (ALLOCATED(SrcParamData%K11)) THEN + i1_l = LBOUND(SrcParamData%K11,1) + i1_u = UBOUND(SrcParamData%K11,1) + i2_l = LBOUND(SrcParamData%K11,2) + i2_u = UBOUND(SrcParamData%K11,2) + IF (.NOT. ALLOCATED(DstParamData%K11)) THEN + ALLOCATE(DstParamData%K11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%K11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%K11 = SrcParamData%K11 +ENDIF +IF (ALLOCATED(SrcParamData%K22)) THEN + i1_l = LBOUND(SrcParamData%K22,1) + i1_u = UBOUND(SrcParamData%K22,1) + i2_l = LBOUND(SrcParamData%K22,2) + i2_u = UBOUND(SrcParamData%K22,2) + IF (.NOT. ALLOCATED(DstParamData%K22)) THEN + ALLOCATE(DstParamData%K22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%K22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%K22 = SrcParamData%K22 +ENDIF +IF (ALLOCATED(SrcParamData%C11)) THEN + i1_l = LBOUND(SrcParamData%C11,1) + i1_u = UBOUND(SrcParamData%C11,1) + i2_l = LBOUND(SrcParamData%C11,2) + i2_u = UBOUND(SrcParamData%C11,2) + IF (.NOT. ALLOCATED(DstParamData%C11)) THEN + ALLOCATE(DstParamData%C11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C11 = SrcParamData%C11 +ENDIF +IF (ALLOCATED(SrcParamData%C12)) THEN + i1_l = LBOUND(SrcParamData%C12,1) + i1_u = UBOUND(SrcParamData%C12,1) + i2_l = LBOUND(SrcParamData%C12,2) + i2_u = UBOUND(SrcParamData%C12,2) + IF (.NOT. ALLOCATED(DstParamData%C12)) THEN + ALLOCATE(DstParamData%C12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C12 = SrcParamData%C12 +ENDIF +IF (ALLOCATED(SrcParamData%C22)) THEN + i1_l = LBOUND(SrcParamData%C22,1) + i1_u = UBOUND(SrcParamData%C22,1) + i2_l = LBOUND(SrcParamData%C22,2) + i2_u = UBOUND(SrcParamData%C22,2) + IF (.NOT. ALLOCATED(DstParamData%C22)) THEN + ALLOCATE(DstParamData%C22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C22 = SrcParamData%C22 +ENDIF +IF (ALLOCATED(SrcParamData%C21)) THEN + i1_l = LBOUND(SrcParamData%C21,1) + i1_u = UBOUND(SrcParamData%C21,1) + i2_l = LBOUND(SrcParamData%C21,2) + i2_u = UBOUND(SrcParamData%C21,2) + IF (.NOT. ALLOCATED(DstParamData%C21)) THEN + ALLOCATE(DstParamData%C21(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C21.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C21 = SrcParamData%C21 +ENDIF + DstParamData%EP_DeltaT = SrcParamData%EP_DeltaT + DstParamData%nTimeSteps = SrcParamData%nTimeSteps + DstParamData%nCB = SrcParamData%nCB + DstParamData%nCBFull = SrcParamData%nCBFull + DstParamData%nTot = SrcParamData%nTot + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%IntMethod = SrcParamData%IntMethod +IF (ALLOCATED(SrcParamData%ActiveCBDOF)) THEN + i1_l = LBOUND(SrcParamData%ActiveCBDOF,1) + i1_u = UBOUND(SrcParamData%ActiveCBDOF,1) + IF (.NOT. ALLOCATED(DstParamData%ActiveCBDOF)) THEN + ALLOCATE(DstParamData%ActiveCBDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ActiveCBDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ActiveCBDOF = SrcParamData%ActiveCBDOF +ENDIF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%OutParamLinIndx)) THEN + i1_l = LBOUND(SrcParamData%OutParamLinIndx,1) + i1_u = UBOUND(SrcParamData%OutParamLinIndx,1) + i2_l = LBOUND(SrcParamData%OutParamLinIndx,2) + i2_u = UBOUND(SrcParamData%OutParamLinIndx,2) + IF (.NOT. ALLOCATED(DstParamData%OutParamLinIndx)) THEN + ALLOCATE(DstParamData%OutParamLinIndx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParamLinIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%OutParamLinIndx = SrcParamData%OutParamLinIndx +ENDIF + END SUBROUTINE ExtPtfm_CopyParam + + SUBROUTINE ExtPtfm_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%Mass)) THEN + DEALLOCATE(ParamData%Mass) +ENDIF +IF (ALLOCATED(ParamData%Damp)) THEN + DEALLOCATE(ParamData%Damp) +ENDIF +IF (ALLOCATED(ParamData%Stff)) THEN + DEALLOCATE(ParamData%Stff) +ENDIF +IF (ALLOCATED(ParamData%Forces)) THEN + DEALLOCATE(ParamData%Forces) +ENDIF +IF (ALLOCATED(ParamData%times)) THEN + DEALLOCATE(ParamData%times) +ENDIF +IF (ALLOCATED(ParamData%AMat)) THEN + DEALLOCATE(ParamData%AMat) +ENDIF +IF (ALLOCATED(ParamData%BMat)) THEN + DEALLOCATE(ParamData%BMat) +ENDIF +IF (ALLOCATED(ParamData%CMat)) THEN + DEALLOCATE(ParamData%CMat) +ENDIF +IF (ALLOCATED(ParamData%DMat)) THEN + DEALLOCATE(ParamData%DMat) +ENDIF +IF (ALLOCATED(ParamData%FX)) THEN + DEALLOCATE(ParamData%FX) +ENDIF +IF (ALLOCATED(ParamData%FY)) THEN + DEALLOCATE(ParamData%FY) +ENDIF +IF (ALLOCATED(ParamData%M11)) THEN + DEALLOCATE(ParamData%M11) +ENDIF +IF (ALLOCATED(ParamData%M12)) THEN + DEALLOCATE(ParamData%M12) +ENDIF +IF (ALLOCATED(ParamData%M22)) THEN + DEALLOCATE(ParamData%M22) +ENDIF +IF (ALLOCATED(ParamData%M21)) THEN + DEALLOCATE(ParamData%M21) +ENDIF +IF (ALLOCATED(ParamData%K11)) THEN + DEALLOCATE(ParamData%K11) +ENDIF +IF (ALLOCATED(ParamData%K22)) THEN + DEALLOCATE(ParamData%K22) +ENDIF +IF (ALLOCATED(ParamData%C11)) THEN + DEALLOCATE(ParamData%C11) +ENDIF +IF (ALLOCATED(ParamData%C12)) THEN + DEALLOCATE(ParamData%C12) +ENDIF +IF (ALLOCATED(ParamData%C22)) THEN + DEALLOCATE(ParamData%C22) +ENDIF +IF (ALLOCATED(ParamData%C21)) THEN + DEALLOCATE(ParamData%C21) +ENDIF +IF (ALLOCATED(ParamData%ActiveCBDOF)) THEN + DEALLOCATE(ParamData%ActiveCBDOF) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%OutParamLinIndx)) THEN + DEALLOCATE(ParamData%OutParamLinIndx) +ENDIF + END SUBROUTINE ExtPtfm_DestroyParam + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ! Mass allocated yes/no + IF ( ALLOCATED(InData%Mass) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Mass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Mass) ! Mass + END IF + Int_BufSz = Int_BufSz + 1 ! Damp allocated yes/no + IF ( ALLOCATED(InData%Damp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Damp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Damp) ! Damp + END IF + Int_BufSz = Int_BufSz + 1 ! Stff allocated yes/no + IF ( ALLOCATED(InData%Stff) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Stff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Stff) ! Stff + END IF + Int_BufSz = Int_BufSz + 1 ! Forces allocated yes/no + IF ( ALLOCATED(InData%Forces) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Forces upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Forces) ! Forces + END IF + Int_BufSz = Int_BufSz + 1 ! times allocated yes/no + IF ( ALLOCATED(InData%times) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! times upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%times) ! times + END IF + Int_BufSz = Int_BufSz + 1 ! AMat allocated yes/no + IF ( ALLOCATED(InData%AMat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AMat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AMat) ! AMat + END IF + Int_BufSz = Int_BufSz + 1 ! BMat allocated yes/no + IF ( ALLOCATED(InData%BMat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BMat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BMat) ! BMat + END IF + Int_BufSz = Int_BufSz + 1 ! CMat allocated yes/no + IF ( ALLOCATED(InData%CMat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMat) ! CMat + END IF + Int_BufSz = Int_BufSz + 1 ! DMat allocated yes/no + IF ( ALLOCATED(InData%DMat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DMat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DMat) ! DMat + END IF + Int_BufSz = Int_BufSz + 1 ! FX allocated yes/no + IF ( ALLOCATED(InData%FX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FX) ! FX + END IF + Int_BufSz = Int_BufSz + 1 ! FY allocated yes/no + IF ( ALLOCATED(InData%FY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FY) ! FY + END IF + Int_BufSz = Int_BufSz + 1 ! M11 allocated yes/no + IF ( ALLOCATED(InData%M11) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M11 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M11) ! M11 + END IF + Int_BufSz = Int_BufSz + 1 ! M12 allocated yes/no + IF ( ALLOCATED(InData%M12) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M12 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M12) ! M12 + END IF + Int_BufSz = Int_BufSz + 1 ! M22 allocated yes/no + IF ( ALLOCATED(InData%M22) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M22 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M22) ! M22 + END IF + Int_BufSz = Int_BufSz + 1 ! M21 allocated yes/no + IF ( ALLOCATED(InData%M21) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M21 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M21) ! M21 + END IF + Int_BufSz = Int_BufSz + 1 ! K11 allocated yes/no + IF ( ALLOCATED(InData%K11) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K11 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K11) ! K11 + END IF + Int_BufSz = Int_BufSz + 1 ! K22 allocated yes/no + IF ( ALLOCATED(InData%K22) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K22 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K22) ! K22 + END IF + Int_BufSz = Int_BufSz + 1 ! C11 allocated yes/no + IF ( ALLOCATED(InData%C11) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C11 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C11) ! C11 + END IF + Int_BufSz = Int_BufSz + 1 ! C12 allocated yes/no + IF ( ALLOCATED(InData%C12) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C12 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C12) ! C12 + END IF + Int_BufSz = Int_BufSz + 1 ! C22 allocated yes/no + IF ( ALLOCATED(InData%C22) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C22 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C22) ! C22 + END IF + Int_BufSz = Int_BufSz + 1 ! C21 allocated yes/no + IF ( ALLOCATED(InData%C21) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C21 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C21) ! C21 + END IF + Db_BufSz = Db_BufSz + 1 ! EP_DeltaT + Int_BufSz = Int_BufSz + 1 ! nTimeSteps + Int_BufSz = Int_BufSz + 1 ! nCB + Int_BufSz = Int_BufSz + 1 ! nCBFull + Int_BufSz = Int_BufSz + 1 ! nTot + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! ActiveCBDOF allocated yes/no + IF ( ALLOCATED(InData%ActiveCBDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActiveCBDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ActiveCBDOF) ! ActiveCBDOF + END IF + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OutParamLinIndx allocated yes/no + IF ( ALLOCATED(InData%OutParamLinIndx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OutParamLinIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutParamLinIndx) ! OutParamLinIndx + 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%Mass) ) 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%Mass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Mass,2), UBOUND(InData%Mass,2) + DO i1 = LBOUND(InData%Mass,1), UBOUND(InData%Mass,1) + ReKiBuf(Re_Xferred) = InData%Mass(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Damp) ) 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%Damp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Damp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Damp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Damp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Damp,2), UBOUND(InData%Damp,2) + DO i1 = LBOUND(InData%Damp,1), UBOUND(InData%Damp,1) + ReKiBuf(Re_Xferred) = InData%Damp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Stff) ) 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%Stff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stff,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Stff,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Stff,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Stff,2), UBOUND(InData%Stff,2) + DO i1 = LBOUND(InData%Stff,1), UBOUND(InData%Stff,1) + ReKiBuf(Re_Xferred) = InData%Stff(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Forces) ) 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%Forces,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Forces,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Forces,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Forces,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Forces,2), UBOUND(InData%Forces,2) + DO i1 = LBOUND(InData%Forces,1), UBOUND(InData%Forces,1) + ReKiBuf(Re_Xferred) = InData%Forces(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%times) ) 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%times,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%times,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%times,1), UBOUND(InData%times,1) + ReKiBuf(Re_Xferred) = InData%times(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AMat) ) 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%AMat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AMat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AMat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AMat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AMat,2), UBOUND(InData%AMat,2) + DO i1 = LBOUND(InData%AMat,1), UBOUND(InData%AMat,1) + ReKiBuf(Re_Xferred) = InData%AMat(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BMat) ) 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%BMat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BMat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BMat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BMat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BMat,2), UBOUND(InData%BMat,2) + DO i1 = LBOUND(InData%BMat,1), UBOUND(InData%BMat,1) + ReKiBuf(Re_Xferred) = InData%BMat(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CMat) ) 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%CMat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CMat,2), UBOUND(InData%CMat,2) + DO i1 = LBOUND(InData%CMat,1), UBOUND(InData%CMat,1) + ReKiBuf(Re_Xferred) = InData%CMat(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DMat) ) 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%DMat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DMat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DMat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DMat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%DMat,2), UBOUND(InData%DMat,2) + DO i1 = LBOUND(InData%DMat,1), UBOUND(InData%DMat,1) + ReKiBuf(Re_Xferred) = InData%DMat(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FX) ) 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%FX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FX,1), UBOUND(InData%FX,1) + ReKiBuf(Re_Xferred) = InData%FX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FY) ) 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%FY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FY,1), UBOUND(InData%FY,1) + ReKiBuf(Re_Xferred) = InData%FY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M11) ) 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%M11,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M11,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M11,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M11,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M11,2), UBOUND(InData%M11,2) + DO i1 = LBOUND(InData%M11,1), UBOUND(InData%M11,1) + ReKiBuf(Re_Xferred) = InData%M11(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M12) ) 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%M12,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M12,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M12,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M12,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M12,2), UBOUND(InData%M12,2) + DO i1 = LBOUND(InData%M12,1), UBOUND(InData%M12,1) + ReKiBuf(Re_Xferred) = InData%M12(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M22) ) 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%M22,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M22,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M22,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M22,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M22,2), UBOUND(InData%M22,2) + DO i1 = LBOUND(InData%M22,1), UBOUND(InData%M22,1) + ReKiBuf(Re_Xferred) = InData%M22(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M21) ) 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%M21,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M21,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M21,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M21,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M21,2), UBOUND(InData%M21,2) + DO i1 = LBOUND(InData%M21,1), UBOUND(InData%M21,1) + ReKiBuf(Re_Xferred) = InData%M21(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%K11) ) 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%K11,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K11,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K11,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K11,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%K11,2), UBOUND(InData%K11,2) + DO i1 = LBOUND(InData%K11,1), UBOUND(InData%K11,1) + ReKiBuf(Re_Xferred) = InData%K11(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%K22) ) 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%K22,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K22,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K22,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K22,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%K22,2), UBOUND(InData%K22,2) + DO i1 = LBOUND(InData%K22,1), UBOUND(InData%K22,1) + ReKiBuf(Re_Xferred) = InData%K22(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C11) ) 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%C11,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C11,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C11,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C11,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C11,2), UBOUND(InData%C11,2) + DO i1 = LBOUND(InData%C11,1), UBOUND(InData%C11,1) + ReKiBuf(Re_Xferred) = InData%C11(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C12) ) 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%C12,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C12,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C12,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C12,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C12,2), UBOUND(InData%C12,2) + DO i1 = LBOUND(InData%C12,1), UBOUND(InData%C12,1) + ReKiBuf(Re_Xferred) = InData%C12(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C22) ) 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%C22,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C22,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C22,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C22,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C22,2), UBOUND(InData%C22,2) + DO i1 = LBOUND(InData%C22,1), UBOUND(InData%C22,1) + ReKiBuf(Re_Xferred) = InData%C22(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C21) ) 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%C21,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C21,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C21,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C21,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C21,2), UBOUND(InData%C21,2) + DO i1 = LBOUND(InData%C21,1), UBOUND(InData%C21,1) + ReKiBuf(Re_Xferred) = InData%C21(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DbKiBuf(Db_Xferred) = InData%EP_DeltaT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nTimeSteps + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nCB + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nCBFull + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nTot + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ActiveCBDOF) ) 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%ActiveCBDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActiveCBDOF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActiveCBDOF,1), UBOUND(InData%ActiveCBDOF,1) + IntKiBuf(Int_Xferred) = InData%ActiveCBDOF(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + 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 + END SUBROUTINE ExtPtfm_PackParam + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 ! Mass 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%Mass)) DEALLOCATE(OutData%Mass) + ALLOCATE(OutData%Mass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Mass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Mass,2), UBOUND(OutData%Mass,2) + DO i1 = LBOUND(OutData%Mass,1), UBOUND(OutData%Mass,1) + OutData%Mass(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Damp 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%Damp)) DEALLOCATE(OutData%Damp) + ALLOCATE(OutData%Damp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Damp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Damp,2), UBOUND(OutData%Damp,2) + DO i1 = LBOUND(OutData%Damp,1), UBOUND(OutData%Damp,1) + OutData%Damp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Stff 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%Stff)) DEALLOCATE(OutData%Stff) + ALLOCATE(OutData%Stff(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Stff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Stff,2), UBOUND(OutData%Stff,2) + DO i1 = LBOUND(OutData%Stff,1), UBOUND(OutData%Stff,1) + OutData%Stff(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Forces 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%Forces)) DEALLOCATE(OutData%Forces) + ALLOCATE(OutData%Forces(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Forces.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Forces,2), UBOUND(OutData%Forces,2) + DO i1 = LBOUND(OutData%Forces,1), UBOUND(OutData%Forces,1) + OutData%Forces(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! times 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%times)) DEALLOCATE(OutData%times) + ALLOCATE(OutData%times(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%times.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%times,1), UBOUND(OutData%times,1) + OutData%times(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AMat 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%AMat)) DEALLOCATE(OutData%AMat) + ALLOCATE(OutData%AMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AMat,2), UBOUND(OutData%AMat,2) + DO i1 = LBOUND(OutData%AMat,1), UBOUND(OutData%AMat,1) + OutData%AMat(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BMat 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%BMat)) DEALLOCATE(OutData%BMat) + ALLOCATE(OutData%BMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BMat,2), UBOUND(OutData%BMat,2) + DO i1 = LBOUND(OutData%BMat,1), UBOUND(OutData%BMat,1) + OutData%BMat(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMat 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%CMat)) DEALLOCATE(OutData%CMat) + ALLOCATE(OutData%CMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CMat,2), UBOUND(OutData%CMat,2) + DO i1 = LBOUND(OutData%CMat,1), UBOUND(OutData%CMat,1) + OutData%CMat(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DMat 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%DMat)) DEALLOCATE(OutData%DMat) + ALLOCATE(OutData%DMat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DMat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%DMat,2), UBOUND(OutData%DMat,2) + DO i1 = LBOUND(OutData%DMat,1), UBOUND(OutData%DMat,1) + OutData%DMat(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FX 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%FX)) DEALLOCATE(OutData%FX) + ALLOCATE(OutData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FX,1), UBOUND(OutData%FX,1) + OutData%FX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FY 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%FY)) DEALLOCATE(OutData%FY) + ALLOCATE(OutData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FY,1), UBOUND(OutData%FY,1) + OutData%FY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M11 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%M11)) DEALLOCATE(OutData%M11) + ALLOCATE(OutData%M11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M11,2), UBOUND(OutData%M11,2) + DO i1 = LBOUND(OutData%M11,1), UBOUND(OutData%M11,1) + OutData%M11(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M12 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%M12)) DEALLOCATE(OutData%M12) + ALLOCATE(OutData%M12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M12,2), UBOUND(OutData%M12,2) + DO i1 = LBOUND(OutData%M12,1), UBOUND(OutData%M12,1) + OutData%M12(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M22 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%M22)) DEALLOCATE(OutData%M22) + ALLOCATE(OutData%M22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M22,2), UBOUND(OutData%M22,2) + DO i1 = LBOUND(OutData%M22,1), UBOUND(OutData%M22,1) + OutData%M22(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M21 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%M21)) DEALLOCATE(OutData%M21) + ALLOCATE(OutData%M21(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M21.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M21,2), UBOUND(OutData%M21,2) + DO i1 = LBOUND(OutData%M21,1), UBOUND(OutData%M21,1) + OutData%M21(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K11 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%K11)) DEALLOCATE(OutData%K11) + ALLOCATE(OutData%K11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%K11,2), UBOUND(OutData%K11,2) + DO i1 = LBOUND(OutData%K11,1), UBOUND(OutData%K11,1) + OutData%K11(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K22 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%K22)) DEALLOCATE(OutData%K22) + ALLOCATE(OutData%K22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%K22,2), UBOUND(OutData%K22,2) + DO i1 = LBOUND(OutData%K22,1), UBOUND(OutData%K22,1) + OutData%K22(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C11 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%C11)) DEALLOCATE(OutData%C11) + ALLOCATE(OutData%C11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C11,2), UBOUND(OutData%C11,2) + DO i1 = LBOUND(OutData%C11,1), UBOUND(OutData%C11,1) + OutData%C11(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C12 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%C12)) DEALLOCATE(OutData%C12) + ALLOCATE(OutData%C12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C12,2), UBOUND(OutData%C12,2) + DO i1 = LBOUND(OutData%C12,1), UBOUND(OutData%C12,1) + OutData%C12(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C22 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%C22)) DEALLOCATE(OutData%C22) + ALLOCATE(OutData%C22(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C22.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C22,2), UBOUND(OutData%C22,2) + DO i1 = LBOUND(OutData%C22,1), UBOUND(OutData%C22,1) + OutData%C22(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C21 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%C21)) DEALLOCATE(OutData%C21) + ALLOCATE(OutData%C21(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C21.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C21,2), UBOUND(OutData%C21,2) + DO i1 = LBOUND(OutData%C21,1), UBOUND(OutData%C21,1) + OutData%C21(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%EP_DeltaT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%nTimeSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nCB = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nCBFull = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nTot = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ActiveCBDOF 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%ActiveCBDOF)) DEALLOCATE(OutData%ActiveCBDOF) + ALLOCATE(OutData%ActiveCBDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActiveCBDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActiveCBDOF,1), UBOUND(OutData%ActiveCBDOF,1) + OutData%ActiveCBDOF(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParamLinIndx 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%OutParamLinIndx)) DEALLOCATE(OutData%OutParamLinIndx) + ALLOCATE(OutData%OutParamLinIndx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParamLinIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OutParamLinIndx,2), UBOUND(OutData%OutParamLinIndx,2) + DO i1 = LBOUND(OutData%OutParamLinIndx,1), UBOUND(OutData%OutParamLinIndx,1) + OutData%OutParamLinIndx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackParam + + SUBROUTINE ExtPtfm_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: SrcInputData + TYPE(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%PtfmMesh, DstInputData%PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE ExtPtfm_CopyInput + + SUBROUTINE ExtPtfm_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%PtfmMesh, ErrStat, ErrMsg ) + END SUBROUTINE ExtPtfm_DestroyInput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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 = 'ExtPtfm_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtfmMesh + 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 MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtfmMesh + 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 ExtPtfm_PackInput + + SUBROUTINE ExtPtfm_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(ExtPtfm_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_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 + 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 MeshUnpack( OutData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtfmMesh + 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 ExtPtfm_UnPackInput + + SUBROUTINE ExtPtfm_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'ExtPtfm_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%PtfmMesh, DstOutputData%PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE ExtPtfm_CopyOutput + + SUBROUTINE ExtPtfm_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%PtfmMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE ExtPtfm_DestroyOutput + + SUBROUTINE ExtPtfm_PackOutput( 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(ExtPtfm_OutputType), 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 = 'ExtPtfm_PackOutput' + ! 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 ! PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtfmMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtfmMesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_PackOutput + + SUBROUTINE ExtPtfm_UnPackOutput( 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(ExtPtfm_OutputType), 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 = 'ExtPtfm_UnPackOutput' + ! 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 MeshUnpack( OutData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtfmMesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE ExtPtfm_UnPackOutput + + + SUBROUTINE ExtPtfm_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL ExtPtfm_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ExtPtfm_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ExtPtfm_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ExtPtfm_Input_ExtrapInterp + + + SUBROUTINE ExtPtfm_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%PtfmMesh, u2%PtfmMesh, tin, u_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE ExtPtfm_Input_ExtrapInterp1 + + + SUBROUTINE ExtPtfm_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%PtfmMesh, u2%PtfmMesh, u3%PtfmMesh, tin, u_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE ExtPtfm_Input_ExtrapInterp2 + + + SUBROUTINE ExtPtfm_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL ExtPtfm_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ExtPtfm_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ExtPtfm_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ExtPtfm_Output_ExtrapInterp + + + SUBROUTINE ExtPtfm_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%PtfmMesh, y2%PtfmMesh, tin, y_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE ExtPtfm_Output_ExtrapInterp1 + + + SUBROUTINE ExtPtfm_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(ExtPtfm_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%PtfmMesh, y2%PtfmMesh, y3%PtfmMesh, tin, y_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE ExtPtfm_Output_ExtrapInterp2 + +END MODULE ExtPtfm_MCKF_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/feamooring/CMakeLists.txt b/OpenFAST/modules/feamooring/CMakeLists.txt new file mode 100644 index 000000000..c9009c443 --- /dev/null +++ b/OpenFAST/modules/feamooring/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/FEAM_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/FEAMooring_Types.f90) +endif() + +set(FEAM_LIBS_SOURCES + src/FEAM.f90 + src/FEAMooring_Types.f90 +) + +add_library(feamlib ${FEAM_LIBS_SOURCES}) +target_link_libraries(feamlib nwtclibs) + +install(TARGETS feamlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +add_executable(feam_driver src/FEAM_Driver.f90) +target_link_libraries(feam_driver feamlib) + +install(TARGETS feam_driver + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) diff --git a/OpenFAST/modules/feamooring/README.md b/OpenFAST/modules/feamooring/README.md new file mode 100644 index 000000000..77b1b0562 --- /dev/null +++ b/OpenFAST/modules/feamooring/README.md @@ -0,0 +1,27 @@ +# FEAMooring Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/FEAMooring/). + +## Overview +A TAMU-led team, in partnership with ABS and NREL, was selected for funding +under topic area 1.3 of DE-FOA-0000415 to develop an open-source +mooring-dynamics module for the analysis of floating offshore wind turbines. +This project led to the development of FEAMooring (or FEAM), a +finite-element-based mooring-dynamics module that has been coupled into +OpenFAST. FEAMooring can also be driven as a standalone code to compute mooring +dynamics uncoupled from OpenFAST. + +FEAMooring calculates the mooring-line reaction forces at the fairlead +positions of the floating platform considering the mooring dynamics, including +inertia and drag forces at each line element. The module can analyze several +kinds of mooring systems, including catenary mooring, taut mooring, vertical +tendons, etc. provided that the proper line geometry and properties are +specified. While powerful, FEAMooring has the following limitations: + +- Only single uniform moorings lines between the fairlead and anchor are + considered; it is not possible to model multi-segmented lines, line + interconnections, or weights/tanks +- Mooring-line bending stiffness is not considered +- Seabed friction is not considered +- Interface does not support coupling to HydroDyn; the added mass, drag, and + buoyancy calculations assume still water diff --git a/OpenFAST/modules/feamooring/src/FEAM.f90 b/OpenFAST/modules/feamooring/src/FEAM.f90 new file mode 100644 index 000000000..7402e939f --- /dev/null +++ b/OpenFAST/modules/feamooring/src/FEAM.f90 @@ -0,0 +1,2885 @@ +!********************************************************************************************************************************** +! This file is part of FEAMooring. +! +! Copyright (C) 2014-2016 NREL/TAMU +! +! 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 FEAMooring + + USE FEAMooring_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: FEAM_Ver = ProgDesc( 'FEAMooring', 'v1.02.01', '23-Jul-2016' ) + +! ===================================================================================================" +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 09-Dec-2014 14:03:37. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array y%AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: FairT1 = 1 + INTEGER(IntKi), PARAMETER :: FairT2 = 2 + INTEGER(IntKi), PARAMETER :: FairT3 = 3 + INTEGER(IntKi), PARAMETER :: FairT4 = 4 + INTEGER(IntKi), PARAMETER :: FairT5 = 5 + INTEGER(IntKi), PARAMETER :: FairT6 = 6 + INTEGER(IntKi), PARAMETER :: FairT7 = 7 + INTEGER(IntKi), PARAMETER :: FairT8 = 8 + INTEGER(IntKi), PARAMETER :: FairT9 = 9 + INTEGER(IntKi), PARAMETER :: FairT10 = 10 + INTEGER(IntKi), PARAMETER :: AnchT1 = 11 + INTEGER(IntKi), PARAMETER :: AnchT2 = 12 + INTEGER(IntKi), PARAMETER :: AnchT3 = 13 + INTEGER(IntKi), PARAMETER :: AnchT4 = 14 + INTEGER(IntKi), PARAMETER :: AnchT5 = 15 + INTEGER(IntKi), PARAMETER :: AnchT6 = 16 + INTEGER(IntKi), PARAMETER :: AnchT7 = 17 + INTEGER(IntKi), PARAMETER :: AnchT8 = 18 + INTEGER(IntKi), PARAMETER :: AnchT9 = 19 + INTEGER(IntKi), PARAMETER :: AnchT10 = 20 + + ! Category: + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 20 + +!End of code generated by Matlab script + + INTEGER(IntKi), PARAMETER :: FairT(10) = (/ FairT1, FairT2, FairT3, FairT4, FairT5, FairT6, FairT7, FairT8, FairT9, FairT10 /) + INTEGER(IntKi), PARAMETER :: AnchT(10) = (/ AnchT1, AnchT2, AnchT3, AnchT4, AnchT5, AnchT6, AnchT7, AnchT8, AnchT9, AnchT10 /) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: FEAM_Init ! Initialization routine + PUBLIC :: FEAM_Solve + PUBLIC :: FEAM_End ! Ending routine (includes clean up) + PUBLIC :: FEAM_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + PUBLIC :: FEAM_CalcOutput ! Routine for computing outputs + + + CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FEAM_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, InitOut, ErrStat, ErrMsg ) +! 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. +! The initial states and initial guess for the input are defined. +!.................................................................................................................................. + + TYPE(FEAM_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(FEAM_InputType), INTENT( OUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(FEAM_ParameterType), INTENT( OUT) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT( OUT) :: x ! Initial continuous states + TYPE(FEAM_DiscreteStateType), INTENT( OUT) :: xd ! Initial discrete states. + TYPE(FEAM_ConstraintStateType), INTENT( OUT) :: z ! Initial guess of the constraint states. + TYPE(FEAM_OtherStateType), INTENT( OUT) :: OtherState ! Initial other states + TYPE(FEAM_OutputType), INTENT( OUT) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + TYPE(FEAM_MiscVarType), INTENT( OUT) :: misc ! Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval ! Coupling interval in seconds: the rate that + ! (1) FEAM_UpdateStates() is called in loose coupling & + ! (2) FEAM_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + TYPE(FEAM_InitOutputType), INTENT( OUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(FEAM_InputFile) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + REAL(ReKi) :: Dist ! A temporary real value + REAL(ReKi) :: Curv ! A temporary real value + REAL(ReKi) :: Temp ! A temporary real value + INTEGER(IntKi) :: I ! Generic loop index + INTEGER(IntKi) :: J ! Generic loop index + + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + + CALL DispNVD( FEAM_Ver ) + + + !............................................................................................ + ! Read the input file and validate the data + ! (note p%NumBl and p%RootName must be set first!) + !............................................................................................ + p%RootName = TRIM(InitInp%RootName) ! all of the output file names from this module will end with '.FEAM.*' + + CALL FEAM_ReadInput( InitInp%InputFile, InputFileData, p%RootName, Interval, InitInp%gravity, InitInp%WtrDens, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + CALL FEAM_SetParameters( InputFileData, p, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + !............................................................................................ + ! Define initialization-routine output here (we're doing this near the beginning because + ! we use LAnch{x|y|z}i and LFair{x|y|z}t to compute some parameters: + !............................................................................................ + + CALL Init_InitOut(p, InputFileData, InitInp, InitOut, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !............................................................................................ + ! Define additional parameters based on InitOut data and necessary for state initializion here: + !............................................................................................ + + DO I = 1,p%NumLines + Dist = SQRT( ( InitOut%LFairxt(I) - InitOut%LAnchxi(I) )**2 + & + ( InitOut%LFairyt(I) - InitOut%LAnchyi(I) )**2 + & + ( InitOut%LFairzt(I) - InitOut%LAnchzi(I) )**2 ) + + Curv = 0.0 + DO J = 1,p%NumElems + Curv = Curv + p%Elength(I) + ENDDO + + p%GLUZR(I,1,1) = InitOut%LAnchxi(I) + p%GLUZR(I,1,3) = InitOut%LAnchyi(I) + p%GLUZR(I,1,5) = InitOut%LAnchzi(I) + + p%GLUZR(I,1,2) = (InitOut%LFairxt(I) - InitOut%LAnchxi(I))/Dist + p%GLUZR(I,1,4) = (InitOut%LFairyt(I) - InitOut%LAnchyi(I))/Dist + p%GLUZR(I,1,6) = (InitOut%LFairzt(I) - InitOut%LAnchzi(I))/Dist + + Temp = 0.0 + DO J = 2,p%NumElems+1 + Temp = Temp+p%Elength(I) + p%GLUZR(I,J,1) = InitOut%LAnchxi(I)+(InitOut%LFairxt(I)- InitOut%LAnchxi(I))*Temp/Curv + p%GLUZR(I,J,3) = InitOut%LAnchyi(I)+(InitOut%LFairyt(I)- InitOut%LAnchyi(I))*Temp/Curv + p%GLUZR(I,J,5) = InitOut%LAnchzi(I)+(InitOut%LFairzt(I)- InitOut%LAnchzi(I))*Temp/Curv + + p%GLUZR(I,J,2) = (InitOut%LFairxt(I)-InitOut%LAnchxi(I))/Dist + p%GLUZR(I,J,4) = (InitOut%LFairyt(I)-InitOut%LAnchyi(I))/Dist + p%GLUZR(I,J,6) = (InitOut%LFairzt(I)-InitOut%LAnchzi(I))/Dist + ENDDO + ENDDO + + + DO I = 1,p%NumLines + p%GP(I,1) = InitOut%LFairxt(I) + p%GP(I,2) = InitOut%LFairyt(I) + p%GP(I,3) = InitOut%LFairzt(I) + ENDDO + + ! INPUT BOUNDARY VALUE + DO I = 1,p%NumLines + p%Bvp(I,1) = InitOut%LAnchxi(I) + p%Bvp(I,2) = InitOut%LAnchyi(I) + p%Bvp(I,3) = InitOut%LAnchzi(I) + ENDDO + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + + CALL Init_MiscVars(p, misc, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL Init_States(p, x, xd, z, OtherState, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL FEAM_Solve(0.0_Dbki, 0, u, p, x, xd, z, OtherState, misc, .false., ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! Revert back fairlead position for dynamic analysis (and mesh initialization) + DO I = 1,p%NumLines + p%GP(I,1) = InitOut%LFairxt(I) - InitInp%PtfmInit(1) + p%GP(I,2) = InitOut%LFairyt(I) - InitInp%PtfmInit(2) + p%GP(I,3) = InitOut%LFairzt(I) - InitInp%PtfmInit(3) + END DO + + + !............................................................................................ + ! Define initial guess for the system inputs here: + !............................................................................................ + + ! Create Line mesh + CALL CreateLineMesh( u, p, misc, ErrStat, ErrMsg ) + + ! Create Platform point mesh + CALL CreatePtFairleadMesh( u, p, y, ErrStat, ErrMsg ) + + !......................................................................................... + ! initialization for WaveAcc0, etc, which TAMU had in HydroDyn + !......................................................................................... + p%NStepWave = InitInp%NStepWave + ALLOCATE( p%WaveAcc0 ( 0:p%NStepWave, u%HydroForceLineMesh%NNodes, 3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL CheckError(ErrID_Fatal, "FEAM_Init:Error allocating p%WaveAcc0z") + ALLOCATE( p%WaveTime ( 0:p%NStepWave ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL CheckError(ErrID_Fatal, "FEAM_Init:Error allocating p%WaveTime") + ALLOCATE( p%WaveVel0 ( 0:p%NStepWave, u%HydroForceLineMesh%NNodes, 3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL CheckError(ErrID_Fatal, "FEAM_Init:Error allocating p%WaveVel0") + + DO i=0,p%NStepWave + p%WaveTime = i*p%DT !bjj: just made up some monotonic sequence here + END DO + + p%WaveAcc0 = 0.0_ReKi + p%WaveVel0 = 0.0_ReKi + + + + + !............................................................................................ + ! Define system output initializations (set up mesh) here: + !............................................................................................ + CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + y%WriteOutput = 0 + + !............................................................................................ + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + !............................................................................................ + + Interval = p%DT + + ! Clean up the local variable: + CALL FEAM_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) + + RETURN + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'Error in FEAM_Init: '//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CALL FEAM_DestroyInputFile(InputFileData, ErrStat3, ErrMsg3 ) + END IF + + END IF + + END SUBROUTINE CheckError + !---------------------------------------------------------------------------------------------------------------------------------- +END SUBROUTINE FEAM_Init +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_States(p, x, xd, z, OtherState, ErrStat, ErrMsg) + + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states. + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states. + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! Initial other states + + 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 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'Init_States' + + INTEGER(IntKi) :: I, J, K + INTEGER(IntKi) :: MM, NN, NE ! counters + + ErrStat = ErrID_None + ErrMsg = "" + + ! continuous states + CALL AllocAry( x%GLU, p%NumLines, 8*p%NumElems+7, 'GLU', ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( x%GLDU, p%NumLines, 8*p%NumElems+7, 'GLDU', ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) RETURN + + + ! discrete states + + xd%DummyDiscState = 0 + + ! constraint states + + ! these are initialized in FEAM_Solve() + + ! other states: + + CALL AllocAry( OtherState%GLU0, p%NumLines,8*p%NumElems+7, 'GLU0', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OtherState%GLDDU, p%NumLines,8*p%NumElems+7, 'GLDDU', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OtherState%GFORC0, p%NumLines,p%NumElems,p%NBAND, 'GFORC0', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OtherState%GMASS0, p%NumLines,p%NumElems,p%NBAND,p%NBAND,'GMASS0', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OtherState%FAST_FPA,p%NumLines,p%NDIM, 'FAST_FPA',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OtherState%FAST_RP, p%NumLines,p%NDIM, 'FAST_RP', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + OtherState%BottomTouch = .FALSE. + + OtherState%GFORC0 = 0.0_ReKi + OtherState%GMASS0 = 0.0_ReKi + + OtherState%FAST_FPA = p%GP + OtherState%FAST_RP = 0.0 + + OtherState%INCR = 0 + + OtherState%RSDF = 0.0_ReKi + + OtherState%FORC0 = 0.0_ReKi + OtherState%EMAS0 = 0.0_ReKi + + + OtherState%GLU0 = 0.0_ReKi + OtherState%GLDDU = 0.0_ReKi + x%GLU = 0.0 + x%GLDU = 0.0 + + DO I = 1,p%NumLines + + !SET THE INITIAL VALUE TO GLOBE VECTOR GLU + DO NN = 1,p%NumElems+1 + DO J = 1,p%NDIM + DO K = 1,2 + MM = p%IDOF(J,K)+(NN-1)*p%NHBD + x%GLU( I,MM) = p%GLUZR(I,NN,p%IDOF(J,K)) + OtherState%GLU0( I,MM) = x%GLU(I,MM) + x%GLDU( I,MM) = 0. + OtherState%GLDDU(I,MM) = 0. + END DO + END DO + END DO + + DO NE = 1,p%NumElems + DO J = 1,3 + MM = p%JDOF(J)+(NE-1)*p%NHBD + x%GLU(I,MM) = p%GTZER(I,J+2*(NE-1)) + OtherState%GLU0(I,MM) = x%GLU(I,MM) + END DO + END DO + + ENDDO + +END SUBROUTINE Init_States +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_miscVars(p,misc,ErrStat,ErrMsg) + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + + 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 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'Init_miscVars' + + ErrStat = ErrID_None + ErrMsg = "" + + CALL AllocAry(misc%Line_Coordinate,p%NumLines, p%NumElems+1, p%NDIM,'Line_Coordinate',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%Line_Tangent, p%NumLines, p%NumElems+1, p%NDIM,'Line_Tangent', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%GLF, p%NumLines, 8*p%NumElems+7, 'GLF', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%GLK, p%NumLines, 8*p%NumElems+7,p%NBAND,'GLK', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%FAST_FP, p%NumLines, p%NDIM, 'FAST_FP', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! holds absolute position of input mesh + CALL AllocAry(misc%FAIR_T, p%NumLines, 'FAIR_T', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%ANCH_T, p%NumLines, 'ANCH_T', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%FAIR_ANG, p%NumLines, p%NDIM, 'FAIR_ANG', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%ANCH_ANG, p%NumLines, p%NDIM, 'ANCH_ANG', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(misc%F_Lines, p%NumLines, p%NDIM, 'F_Lines', ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + misc%LastIndWave = 1 + + +END SUBROUTINE Init_miscVars +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_InitOut(p,InputFileData,InitInp, InitOut,ErrStat,ErrMsg) + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_InputFile), INTENT(IN ) :: InputFileData ! Data stored in the module's input file + TYPE(FEAM_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(FEAM_InitOutputType), INTENT(INOUT) :: InitOut ! Output for initialization routine + + 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 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'Init_InitOut' + + integer(intKi) :: I ! loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + + InitOut%Ver = FEAM_Ver + + CALL AllocAry(InitOut%WriteOutputHdr,p%NumOuts,'WriteOutputHdr',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%WriteOutputUnt,p%NumOuts,'WriteOutputUnt',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL AllocAry(InitOut%LAnchxi, p%NumLines, 'LAnchxi', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%LAnchyi, p%NumLines, 'LAnchyi', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%LAnchzi, p%NumLines, 'LAnchzi', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%LFairxt, p%NumLines, 'LFairxt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%LFairyt, p%NumLines, 'LFairyt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOut%LFairzt, p%NumLines, 'LFairzt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + + DO I = 1,p%NumLines + InitOut%LAnchxi(I) = InputFileData%LRadAnch(I) *COS(InputFileData%LAngAnch(I)) + InitOut%LAnchyi(I) = InputFileData%LRadAnch(I) *SIN(InputFileData%LAngAnch(I)) ! Convert the radius, azimuth angle, and depth of the current anchor to x-, y-, and z-coordinates into the inertial frame coordinate system + InitOut%LAnchzi(I) = -InputFileData%LDpthAnch(I) ! + InitOut%LFairxt(I) = InputFileData%LRadFair(I) *COS(InputFileData%LAngFair(I)) + InitInp%PtfmInit(1) ! Add platform initial position to obtain static fairlead offset at initial time + InitOut%LFairyt(I) = InputFileData%LRadFair(I) *SIN(InputFileData%LAngFair(I)) + InitInp%PtfmInit(2) ! Add platform initial position to obtain static fairlead offset at initial time + InitOut%LFairzt(I) = -InputFileData%LDrftFair(I) + InitInp%PtfmInit(3) ! Add platform initial position to obtain static fairlead offset at initial time + END DO + + do i=1,p%NumOuts + InitOut%WriteOutputHdr(i) = p%OutParam(i)%Name + InitOut%WriteOutputUnt(i) = p%OutParam(i)%Units + end do + + +END SUBROUTINE Init_InitOut +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FEAM_Solve( t, n, u, p, x, xd, z, OtherState, misc, Dyn, ErrStat, ErrMsg ) + + TYPE(FEAM_InputType), INTENT(INOUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: xd ! Initial discrete states. + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: z ! Initial guess of the constraint states. + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! other states + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + + LOGICAL , INTENT(IN ) :: Dyn ! flag for dynamic or static analysis + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Passed variables: +! INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation +! CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + REAL(DbKi), INTENT(IN) :: t ! Current time + INTEGER(IntKi), INTENT(IN) :: n ! Current step + REAL(ReKi) :: RHSR0(6) ! Temporary variable (old right hand side R) + REAL(ReKi) :: C0,C00 ! Temporary variable + REAL(ReKi) :: VP ! Temporary variable + REAL(ReKi) :: SUM1,SUM2,SUM3,SUMA,SUMB,SUMC ! Temporary variable + REAL(ReKi) :: ERR1,ERR2,ERR3 ! Temporary variable + REAL(ReKi) :: IVERT,TEMP ! Temporary variable + + + INTEGER(IntKi) :: MM,NN,LEG,NE ! Generic index + INTEGER(IntKi) :: I,J,K,L ! Generic index +! INTEGER(IntKi) :: Sttus ! Status returned by an attempted allocation or READ. + + LOGICAL :: Iteration1 ! Static iteration flag [-] + LOGICAL :: Iteration2 ! Static iteration flag [-] + + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + ! SET A COEFFICIENT TO DOUBLE BOUNDARY FORCE IN TIME DOMAIN + ! AND DN IN STATISTICS CALCULATION + + IF(DYN) THEN + C0 = 2.0 + C00 = 2.0/p%DT + ELSE + C0 = 1.0 + C00 = 0.0 + ENDIF + + Iteration1 = .FALSE. + Iteration2 = .FALSE. + + DO WHILE ((.NOT. Iteration1).OR.(.NOT. Iteration2)) + + DO LEG = 1, p%NumLines ! Start LEG Loop + + ! INITAILIZE FORCE VECTOR AND STIFFNESS MATRIX + DO I = 1,p%NEQ(LEG) + misc%GLF(LEG,I) = 0.0 + DO J = 1,p%NBAND + misc%GLK(LEG,I,J)=0.0 + ENDDO + ENDDO + + DO NE = 1, p%NumElems ! Start Element Loop + + ! 1. INPUT DISPLACEMENT + DO I = 1,p%NDIM + DO J = 1,4 + MM=p%IDOF(I,J)+(NE-1)*p%NHBD + misc%U ( I,J)= x%GLU( LEG,MM) + misc%U0( I,J)=OtherState%GLU0( LEG,MM) + misc%DU( I,J)= x%GLDU( LEG,MM) + misc%DDU(I,J)=OtherState%GLDDU(LEG,MM) + ENDDO + ENDDO + + ! 2. INPUT LAGRANGIAN MULTIPLIER + DO I = 1,3 + MM=p%JDOF(I)+(NE-1)*p%NHBD + z%TSN(I)=x%GLU(LEG,MM) + z%TZER(I)=p%GTZER(LEG,I+2*(NE-1)) + ENDDO + + ! 3. INPUT EXTERNAL FORCE AND MASS OF PREVIOUS TIME STEP + IF(OtherState%INCR.NE.0) THEN + DO I = 1,p%NDIM + DO J = 1,4 + MM=p%IDOF(I,J) + OtherState%FORC0(MM)=OtherState%GFORC0(LEG,NE,MM) + DO K = 1,p%NDIM + DO L = 1,4 + NN=p%IDOF(K,L) + OtherState%EMAS0(MM,NN)=OtherState%GMASS0(LEG,NE,MM,NN) + ENDDO + ENDDO + ENDDO + ENDDO + !ELSE ! IF OtherState%INCR == 0 + ! BJJ 7-Jan-2016: Unless I'm missing something, I don't see how OtherState%FORC0 and OtherState%EMAS0 get + ! set in this case... and both values are used in the call to Element(). + ENDIF + + ! 4. AND OTHER INFORMATION NEEDED IN ELEMNT + + CALL Element(t, n, LEG, NE, u, p, x, xd, z, OtherState, misc, ErrStat, ErrMsg) + + ! SAVE THE EXTERNAL FORCE AND MASS FOR NEXT TIME STEP + ! AND GET THE NODAL INTERACTION FORCE (STATIC & DYNAMIC) + + DO I = 1,p%NDIM + DO J = 1,4 + MM=p%IDOF(I,J) + OtherState%GFORC0(LEG,NE,MM)=misc%FORCE(MM) + DO K = 1,p%NDIM + DO L = 1,4 + NN=p%IDOF(K,L) + OtherState%GMASS0(LEG,NE,MM,NN)=misc%EMASS(MM,NN) + ENDDO + ENDDO + ENDDO + ENDDO + + IF(NE.EQ.p%NumElems)THEN + DO I = 1,p%NDIM + misc%SLIN (I) = p%GSL(LEG,2,I) + misc%FP (I) = p%GP(LEG,I) + misc%R (I) = misc%U(I,3) + misc%RP (I) = misc%U(I,4)/p%Elength(LEG) + ENDDO + + DO I=1,p%NDIM + OtherState%FAST_RP(LEG,I) = misc%RP(I) + ENDDO + + ! First run for BXA + IF(DYN) THEN + DO I = 1,p%NDIM + misc%FP(I) = OtherState%FAST_FPA(LEG,I) ! bjj: OtherState%FAST_FPA are values at t (couldn't we just replace them with call to extrap-interp?) + ENDDO + ENDIF + + CALL Couple (p, x, OtherState, misc, ErrStat, ErrMsg) + + DO I = 1,2*p%NDIM + RHSR0(I)=misc%RHSR(I) + END DO + + ! Second run for BX + IF(DYN) THEN + DO I = 1,p%NDIM + misc%FP(I) = misc%FAST_FP(LEG,I) ! bjj: misc%FAST_FPA are values at t+dt + ENDDO + ENDIF + + CALL Couple (p, x, OtherState, misc, ErrStat, ErrMsg) + + DO I = 1,2*p%NDIM + MM=p%NHBD+I + OtherState%RSDF(MM)=OtherState%RSDF(MM)+misc%RHSR(I) + IF(DYN) OtherState%RSDF(MM)=OtherState%RSDF(MM)+RHSR0(I) + DO J = 1,2*p%NDIM + NN=p%NHBD+J + misc%ESTIF(MM,NN)=misc%ESTIF(MM,NN)+misc%STIFR(I,J) + ENDDO + ENDDO + ENDIF + + ! ASSEMBLE THE STIFF MATRIX AND FORCE VECTOR + DO I = 1,p%NBAND + MM=I+(NE-1)*p%NHBD + misc%GLF(LEG,MM)=misc%GLF(LEG,MM)+OtherState%RSDF(I) + DO J = I,p%NBAND + NN=J-I+1 + misc%GLK(LEG,MM,NN)=misc%GLK(LEG,MM,NN)+misc%ESTIF(I,J) + ENDDO + ENDDO + ENDDO ! End Element loop + + ! APPLY ESSENTIAL BOUNDARY CONDITIONS TO GLOBAL MATRIX + DO L = 1,p%NDIM + MM=p%IDOF(L,1) + VP=p%Bvp(LEG,L)-x%GLU(LEG,MM) + IF(OtherState%INCR.NE.0.OR. .NOT. DYN) VP=0. + I=MM-p%NBAND + DO K = 1,p%NBAND-1 + I=I+1 + IF(I.GE.1) THEN + J=MM-I+1 + misc%GLF(LEG,I)=misc%GLF(LEG,I)-misc%GLK(LEG,I,J)*VP + misc%GLK(LEG,I,J)=0. + ENDIF + ENDDO + misc%GLK(LEG,MM,1)=1. + misc%GLF(LEG,MM)=VP + I=MM + DO K = 2,p%NBAND + I=I+1 + IF(I.LE.p%NEQ(LEG)) THEN + misc%GLF(LEG,I)=misc%GLF(LEG,I)-misc%GLK(LEG,MM,K)*VP + misc%GLK(LEG,MM,K)=0. + ENDIF + ENDDO + ENDDO + ENDDO ! End LEG loop + + ! Solver + CALL Solve(p, x, OtherState, ErrStat, ErrMsg) + + ! 1. STATIC ITERATION (CONVERGENCE) + IF(.NOT.DYN) THEN + SUM1=0.0 + SUM2=0.0 + SUM3=0.0 + SUMA=0.0 + SUMB=0.0 + SUMC=0.0 + DO LEG = 1,p%NumLines + DO I = 1,p%NEQ(LEG) + x%GLU(LEG,I)=x%GLU(LEG,I)+misc%GLF(LEG,I) + ENDDO + + DO I = 1,p%NumElems+1 + DO J = 1,p%NDIM + SUM1=SUM1+misc%GLF(LEG,(I-1)*p%NHBD+2*J-1)**2 + SUMA=SUMA+x%GLU(LEG,(I-1)*p%NHBD+2*J-1)**2 + SUM2=SUM2+misc%GLF(LEG,(I-1)*p%NHBD+2*J)**2 + SUMB=SUMB+x%GLU(LEG,(I-1)*p%NHBD+2*J)**2 + ENDDO + SUM3=SUM3+misc%GLF(LEG,I*p%NHBD-1)**2 + SUMC=SUMC+x%GLU(LEG,I*p%NHBD-1)**2 + ENDDO + ENDDO + + ERR1=SQRT(SUM1/SUMA) + ERR2=SQRT(SUM2/SUMB) + ERR3=SQRT(SUM3/SUMC) + + IF(ERR1.GT.p%Eps.OR.ERR2.GT.p%Eps.OR.ERR3.GT.p%Eps.OR.OtherState%INCR.EQ.0) THEN + OtherState%INCR=OtherState%INCR+1 + IF(OtherState%INCR.GT.p%MaxIter) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'FEAM_Solve:No Convergence' + RETURN + END IF + ELSE IF(.NOT.OtherState%BottomTouch) THEN + call wrscr('Number of iterations without Seabed :'//trim(num2lstr(OtherState%INCR))) + OtherState%BottomTouch = .TRUE. + OtherState%INCR = 0 + Iteration1 = .TRUE. + ELSE IF(OtherState%BottomTouch) THEN + call wrScr( 'Number of final iterations :'//trim(num2lstr(OtherState%INCR))) + OtherState%INCR = 0 + Iteration2 = .TRUE. + + !SET THE STATIC VALUE TO LINE MESH + DO I = 1, p%NumLines + DO NN = 1,p%NumElems+1 + DO J = 1,p%NDIM + MM = p%IDOF(J,1)+(NN-1)*p%NHBD + misc%Line_Coordinate(I,NN,J) = x%GLU(I,MM) + misc%Line_Tangent(I,NN,J) = x%GLU(I,MM+1) + END DO + END DO + END DO + END IF + END IF + + ! Run DO-LOOP Once for Dynamic Analysis + IF(DYN) THEN + Iteration1 = .TRUE. + Iteration2 = .TRUE. + END IF + + ENDDO ! DO WHILE LOOP + + ! 2. DYNAMIC INTEGRATION + IF(DYN) THEN + DO LEG=1,p%NumLines + DO I=1,p%NEQ(LEG) + IVERT=(I/8)*8+5 + OtherState%GLU0(LEG,I)=x%GLU(LEG,I) + x%GLU(LEG,I)=x%GLU(LEG,I)+misc%GLF(LEG,I) + TEMP=misc%GLF(LEG,I)*2.0/p%DT-x%GLDU(LEG,I) + OtherState%GLDDU(LEG,I)=(TEMP-x%GLDU(LEG,I))/p%DT + x%GLDU(LEG,I)=TEMP + END DO + ENDDO + + OtherState%INCR = OtherState%INCR + 1 + ENDIF + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'FEAM_Solve:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + !CALL FEAM_DestroyInputFile(InputFileData, ErrStat3, ErrMsg3 ) + END IF + + END IF + + END SUBROUTINE CheckError + !............................................................................................................................... + SUBROUTINE Element(t, step, NumLinein,NumElemin, u, p, x, xd, z, OtherState, misc, ErrStat, ErrMsg) + + TYPE(FEAM_InputType), INTENT(INOUT) :: u ! An initial guess for the input; input mesh must be defined + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: xd ! discrete states + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: z ! constraint states + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! other states + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Passed variables: + + REAL(ReKi) :: A1,A2,A3,A4,A5 + REAL(ReKi) :: TEMP,TEMP1,TEMP2,TEMP3 + REAL(ReKi) :: ELK(15,15),ELC(15,15) + REAL(ReKi) :: RMAST(4,4),ADDMT(4,4,4,4),RDAMP(4,4),ADAMP(4,4,4,4) + REAL(ReKi) :: W,HGHT,Y + REAL(ReKi) :: UU(4,4,3,3),POST(3),RDOT(3) + REAL(ReKi) :: TIME,ABSV + REAL(ReKi) :: WVV(3),WVA(3),ACN(3),VLN(3) + REAL(ReKi) :: FTEMP(15),F0(3),F1(3),F2(3) + REAL(ReKi) :: RMOD + REAL(DbKi) :: t + + INTEGER(IntKi) :: MM,NN,II ! Generic index + INTEGER(IntKi) :: I,J,K,L,M,N ! Generic index + INTEGER(IntKi) :: NumLinein, NumElemin, NumNodes ! Generic index + INTEGER(IntKi) :: step + + + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + ! SET COEFFICIENT FOR STATIC AND DYNAMIC CALCULATION + + IF(.NOT.DYN) THEN + A1 = 0. + A2 = 1. + A3 = 1. + A4 = 0. + A5 = 0. + ELSE + A1 = 4.0/(p%DT*p%DT) + A2 = 2. + A3 = 3. + A4 =-1. + A5 = 4.0/p%DT + IF(OtherState%INCR.EQ.0) THEN + A3=2. + A4=0. + END IF + END IF + + ! SLOPE TIMES ELEML FOR THE FORMATION OF K,M MATRIX + + DO I=1,p%NDIM + DO J=2,4,2 + misc%U( I,J)=misc%U( I,J)*p%Elength(NumLineIn) + misc%U0( I,J)=misc%U0( I,J)*p%Elength(NumLineIn) + misc%DU( I,J)=misc%DU( I,J)*p%Elength(NumLineIn) + misc%DDU(I,J)=misc%DDU(I,J)*p%Elength(NumLineIn) + END DO + END DO + + ! CALCULATE U(J,M)*U(K,N) ORDER ARRAY FOR USE OF DOT PRODUCT + + DO J=1,p%NDIM + DO M=1,4 + DO K=1,p%NDIM + DO N=1,4 + UU(M,N,J,K) = misc%U(J,M)*misc%U(K,N) + END DO + END DO + END DO + END DO + + ! CALCULATE MASS MATRIX,K1+K2 AND TANGENTIAL STIFFNESS KT0 + + DO I=1,p%NDIM + DO J=1,4 + MM=p%IDOF(I,J) + DO K=1,p%NDIM + DO L=1,4 + NN=p%IDOF(K,L) + IF(NN.GE.MM) THEN + TEMP1=0. + DO M=1,4 + DO N=1,4 + TEMP1=TEMP1+p%RADDM(M,N,J,L)*UU(M,N,I,K) + END DO + END DO + IF(I.EQ.K) THEN + TEMP1=p%RMASS(J,L)*p%Elength(NumLineIn)-TEMP1/p%Elength(NumLineIn) + misc%EMASS(MM,NN)=p%LDMassDen(NumLineIn)*TEMP1+p%LMassDen(NumLineIn)*p%RMASS(J,L)*p%Elength(NumLineIn) + TEMP2=0. + DO M=1,3 + TEMP2 = TEMP2+p%STEN(M,J,L)*z%TSN(M) + END DO + ELK(MM,NN) = TEMP2/p%Elength(NumLineIn) + misc%ESTIF(MM,NN) = ELK(MM,NN)+A1*(A3* misc%EMASS(MM,NN)+A4*OtherState%EMAS0(MM,NN))*0.5 + ELSE + misc%EMASS(MM,NN)=-p%LDMassDen(NumLineIn)*TEMP1/p%Elength(NumLineIn) + misc%ESTIF(MM,NN)= A1*(A3*misc%EMASS(MM,NN)+A4*OtherState%EMAS0(MM,NN))*0.5 + END IF + misc%EMASS(NN,MM) = misc%EMASS(MM,NN) + misc%ESTIF(NN,MM) = misc%ESTIF(MM,NN) + ELK(NN,MM) = ELK(MM,NN) + END IF + END DO + END DO + END DO + END DO + + ! CALCULATE TANGENTIAL STIFFNESS KT1 + + DO I=1,p%NDIM + DO J=1,4 + MM=p%IDOF(I,J) + DO K=1,3 + NN=p%JDOF(K) + + TEMP1=0. + DO M=1,4 + TEMP1=TEMP1 + p%STEN(K,J,M)*misc%U(I,M) + END DO + + misc%ESTIF(MM,NN) = A2*TEMP1/p%Elength(NumLineIn) + misc%ESTIF(NN,MM) = misc%ESTIF(MM,NN) + END DO + END DO + END DO + + ! CALCULATE TANGENTIAL STIFFNESS DT1 + + DO I=1,3 + MM=p%JDOF(I) + DO J=1,3 + NN=p%JDOF(J) + IF(NN.GE.MM) THEN + + misc%ESTIF(MM,NN) =-A2*p%PMPN(I,J)*p%Elength(NumLineIn)/p%LEAStiff(NumLineIn) + misc%ESTIF(NN,MM) = misc%ESTIF(MM,NN) + + END IF + END DO + END DO + + + ! CALCULATE TANGENTIAL STEFFNESS AND FORCE FROM POSSIBLE + ! TOUCHING OF A ELASTIC FOUNDATION WITH QUADRATIC SPRING + ! IN VERTICAL DIRECTION + + DO I=1,p%NBAND + misc%FORCE(I)=0. + END DO + + IF(OtherState%BottomTouch) THEN + + II=p%NDIM + DO N=1,p%NTRAP + W=p%Elength(NumLineIn)/(p%NTRAP-1) + IF(N.EQ.1.OR.N.EQ.p%NTRAP) W=0.5*W + HGHT=0. + DO J=1,4 + HGHT=HGHT+p%SHAPT(N,J)*misc%U(II,J) + END DO + Y=HGHT-p%BottmElev(NumLineIn) + IF(Y.LT.0) THEN + DO L=1,4 + MM=p%IDOF(II,L) + misc%FORCE(MM)=misc%FORCE(MM)+p%SHAPT(N,L)*W*p%BottmStiff(NumLineIn)*Y*Y + DO K=1,4 + NN=p%IDOF(II,K) + IF(NN.GE.MM) THEN + misc%ESTIF(MM,NN) = misc%ESTIF(MM,NN)-p%SHAPT(N,L)*p%SHAPT(N,K)*W*p%BottmStiff(NumLineIn)*Y*2.0 + misc%ESTIF(NN,MM) = misc%ESTIF(MM,NN) + END IF + END DO + END DO + END IF + END DO + END IF + + ! CALCULATE FORCE FROM CONSTANT DISTRIBUTED LOAD (GRAVITY) + + DO I=1,p%NDIM + DO L=1,4 + NN=p%IDOF(I,L) + misc%FORCE(NN) = misc%FORCE(NN)+p%GRAV(I)*p%AM(L)*p%Elength(NumLineIn) + END DO + END DO + + ! CALCULATE HYDRDYNAMIC FORCE FROM MORISON EQUATION + ! USE GAUSS QUADRATURE INTEGRATION + IF(DYN) THEN + DO N=1,p%NGAUSS + W=p%GAUSSW(N)*p%Elength(NumLineIn) + DO K=1,p%NDIM + TEMP1=0. + TEMP2=0. + DO J=1,4 + TEMP1=TEMP1+p%SHAP(N,J)*misc%U(K,J) + TEMP2=TEMP2+p%SHAP(N,J)*misc%DU(K,J) + END DO + POST(K)=TEMP1 + RDOT(K)=TEMP2 + END DO + + NumNodes = (NumLinein-1)*(p%NumElems+1) + NumElemin + 1 + DO L=1, p%NDIM + WVV(L) = InterpWrappedStpReal ( REAL(t, ReKi), p%WaveTime(:), p%WaveVel0(:, NumNodes, L), & + misc%LastIndWave, p%NStepWave + 1 ) + WVA(L) = InterpWrappedStpReal ( REAL(t, ReKi), p%WaveTime(:), p%WaveAcc0(:, NumNodes, L), & + misc%LastIndWave, p%NStepWave + 1 ) + END DO + + DO I=1,p%NDIM + TEMP1=0. + TEMP2=0. + DO J=1,p%NDIM + DO K=1,4 + DO M=1,4 + TEMP1=TEMP1+WVA(J)*UU(K,M,J,I)*p%SHAPS(N,K)*p%SHAPS(N,M) + TEMP2=TEMP2+(WVV(J)-RDOT(J))*p%SHAPS(N,K)*p%SHAPS(N,M)*UU(K,M,J,I) + END DO + END DO + END DO + ACN(I)=WVA(I)-TEMP1/(p%Elength(NumLineIn)*p%Elength(NumLineIn)) + VLN(I)=(WVV(I)-RDOT(I))-TEMP2/(p%Elength(NumLineIn)*p%Elength(NumLineIn)) + END DO + + ABSV = 0. + DO I=1,p%NDIM + ABSV=ABSV+VLN(I)*VLN(I) + END DO + ABSV=SQRT(ABSV) + + DO I=1,p%NDIM + DO L=1,4 + MM=p%IDOF(I,L) + misc%FORCE(MM)=misc%FORCE(MM)+(p%LineCI(NumLineIn)*ACN(I)+p%LineCD(NumLineIn)*ABSV*VLN(I))*p%SHAP(N,L)*W + END DO + END DO + END DO + END IF + + ! CALCULATE THE RESIDUE FORCE Fil-K*U + + DO I=1,15 + OtherState%RSDF(I)=0. + END DO + + DO I=1,p%NDIM + DO J=1,4 + MM=p%IDOF(I,J) + DO K=1,p%NDIM + DO L=1,4 + NN=p%IDOF(K,L) + OtherState%RSDF(MM)=OtherState%RSDF(MM)-A2*ELK(MM,NN)*misc%U(K,L)+A5*(A3*misc%EMASS(MM,NN)+A4*OtherState%EMAS0(MM,NN))*0.5*misc%DU(K,L) + END DO + END DO + + OtherState%RSDF(MM)=OtherState%RSDF(MM)+A3*misc%FORCE(MM)+A4*OtherState%FORC0(MM) + + END DO + END DO + + ! CALCULATE THE RESIDUE AXIAL EXTENSION Gm BOTH FOR + ! EXTENSIBLE AND INEXTENSIBLE CASE. IF THE LIN + ! IS IN WATER, THE HYDROSTATIC PRESSURE IS EXTRACTED FROM + ! LAMBDA. THE INEXTENSIBLE IS A APPROXIMATION + + DO N=1,3 + MM=p%JDOF(N) + TEMP1=0. + DO J=1,p%NDIM + DO K=1,4 + DO L=1,4 + TEMP1=TEMP1+p%STEN(N,K,L)*UU(K,L,J,J) + END DO + END DO + END DO + TEMP1 = 0.5*(TEMP1/p%Elength(NumLineIn) - p%PM(N)*p%Elength(NumLineIn)) + TEMP2=0. + DO J=1,3 + TEMP2 = TEMP2+p%PMPN(N,J)*(z%TSN(J)-z%TZER(J)) + END DO + TEMP2=TEMP2*p%Elength(NumLineIn) + OtherState%RSDF(MM) = -A2*(TEMP1-TEMP2/p%LEAStiff(NumLineIn)) + END DO + + ! MULTIPLY ROWS AND COLUMNS ASSOCIATED WITH SLOPES BY ELEMENT LENGTH + + DO I=1,p%NDIM + DO J=2,4,2 + M=p%IDOF(I,J) + DO N=1,p%NBAND + misc%ESTIF(M,N) = misc%ESTIF(M,N)*p%Elength(NumLineIn) + misc%ESTIF(N,M) = misc%ESTIF(N,M)*p%Elength(NumLineIn) + END DO + OtherState%RSDF(M) = OtherState%RSDF(M)*p%Elength(NumLineIn) + END DO + END DO + + RETURN + END SUBROUTINE Element + !............................................................................................................................... + SUBROUTINE Solve(p, x, OtherState, ErrStat, ErrMsg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! other states + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi), PARAMETER :: NRM=1024 + INTEGER(IntKi), PARAMETER :: NCM=15 + REAL(ReKi) :: BAND(NRM,NCM),RHS(NRM),FACTOR + INTEGER(IntKi) :: MEQNS,NPIV,NPIVOT,LSTSUB,NROW,NCOL,ICOL,JCOL,IJK,JKI,NEQNS + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + DO LEG=1,p%NumLines + NEQNS=p%NEQ(LEG) + DO I=1,NEQNS + RHS(I)=misc%GLF(LEG,I) + DO J=1,p%NBAND + BAND(I,J)=misc%GLK(LEG,I,J) + END DO + END DO + + ! Linesolver + MEQNS=NEQNS-1 + DO NPIV=1,MEQNS + NPIVOT=NPIV+1 + LSTSUB=NPIV+p%NBAND-1 + IF(LSTSUB.GT.NEQNS) THEN + LSTSUB=NEQNS + ENDIF + + DO NROW=NPIVOT,LSTSUB + + NCOL=NROW-NPIV+1 + FACTOR=BAND(NPIV,NCOL)/BAND(NPIV,1) + DO NCOL=NROW,LSTSUB + ICOL=NCOL-NROW+1 + JCOL=NCOL-NPIV+1 + BAND(NROW,ICOL)=BAND(NROW,ICOL)-FACTOR*BAND(NPIV,JCOL) + end do + RHS(NROW)=RHS(NROW)-FACTOR*RHS(NPIV) + end do + end do + + ! Back substitution + DO IJK=2,NEQNS + NPIV=NEQNS-IJK+2 + + RHS(NPIV)=RHS(NPIV)/BAND(NPIV,1) + LSTSUB=NPIV-p%NBAND+1 + IF(LSTSUB.LT.1) THEN + LSTSUB=1 + ENDIF + NPIVOT=NPIV-1 + DO JKI=LSTSUB,NPIVOT + NROW=NPIVOT-JKI+LSTSUB + NCOL=NPIV-NROW+1 + FACTOR=BAND(NROW,NCOL) + RHS(NROW)=RHS(NROW)-FACTOR*RHS(NPIV) + end do + end do + RHS(1)=RHS(1)/BAND(1,1) + + DO I=1,NEQNS + misc%GLF(LEG,I)=RHS(I) + END DO + END DO + + END SUBROUTINE Solve + !............................................................................................................................... + SUBROUTINE Couple(p, x, OtherState, misc, ErrStat, ErrMsg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Initial continuous states + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! other states + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! 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) :: FORCE(3) + REAL(ReKi) :: DELTA(3,3) + REAL(ReKi) :: TEMP + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + ! DELTA(I,J) IS THE KRONECKER DELTA + CALL Eye(DELTA, ErrStat, ErrMsg) !bjj: this is not valid Fortran 2003: DATA DELTA/ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0/ + + ! CALCULATE CONTRIBUTION OF LINEAR SPRING + ! SPRING FORCE = SLIN*(X + PLOC + THETA X PLOC - R) ! Equation for N(n) + + DO I=1,p%NDIM + TEMP=misc%FP(I)-misc%R(I) + FORCE(I)=misc%SLIN(I)*TEMP + END DO + + ! RIGHT HAND SIDE FOR R AND X EQUATIONS + + DO I=1,p%NDIM + misc%RHSR(2*I-1) = FORCE(I) + misc%RHSR(2*I) = 0.0 + END DO + + ! STIFFNESS COEFFICIENTS Krr,Krx,Kxx + + DO I=1,p%NDIM + DO J=1,p%NDIM + misc%STIFR(2*I-1,2*J-1) = misc%SLIN(I)*DELTA(I,J) + END DO + END DO + + ! STIFFNESS COEFFICIENT Kr'r' + + DO I=1,p%NDIM + DO J=1,p%NDIM + misc%STIFR(2*I,2*J)= 0.0 + END DO + END DO + + END SUBROUTINE Couple + !............................................................................................................................... +END SUBROUTINE FEAM_Solve +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FEAM_End ( u, p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) +! This routine is called at the end of the simulation. +!.................................................................................................................................. + + TYPE(FEAM_InputType), INTENT(INOUT) :: u ! System inputs + TYPE(FEAM_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! Other states + TYPE(FEAM_OutputType), INTENT(INOUT) :: y ! System outputs + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL FEAM_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL FEAM_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL FEAM_DestroyContState( x, ErrStat, ErrMsg ) + CALL FEAM_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL FEAM_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL FEAM_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL FEAM_DestroyMisc( misc, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL FEAM_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE FEAM_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 FEAM_UpdateStates ( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, misc, 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(FEAM_InputType), INTENT(INOUT) :: Inputs(:) ! Inputs at InputTimes (intent out only for record keeping in ExtrapInterp) + REAL(DbKi), INTENT(IN ) :: InputTimes(:) ! Times in seconds associated with Inputs + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + Interval + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: z ! Input: Discrete states at t; + ! Output: Constraint states at t + Interval + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherState ! Input: Other states at t; + ! Output: Other states at t + Interval + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + +! TYPE(FEAM_ContinuousStateType) :: dxdt ! Continuous state derivatives at t + TYPE(FEAM_InputType) :: u ! Inputs at t +! TYPE(FEAM_InputFile) :: InputFileData ! Data stored in the module's input file + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + INTEGER(IntKi) :: I ! Generic loop index + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_UpdateStates' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get the inputs, based on the array of values sent by the glue code: + + CALL FEAM_CopyInput( Inputs(1), u, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !bjj: this gives us extrapolated values at t+dt; but we should use FEAM_Input_ExtrapInterp + + IF ( ErrStat >= AbortErrLev ) THEN + call cleanup() + RETURN + END IF + + + !bjj: as far as I can tell, + ! misc%FAST_FP is absolute position of u%PtFairleadDisplacement at t+dt, + ! and OtherState%FAST_FPA is the absolute position of u%PtFairleadDisplacement at t + DO I = 1,u%PtFairleadDisplacement%NNodes + misc%FAST_FP(I,1) = u%PtFairleadDisplacement%Position(1,I) + u%PtFairleadDisplacement%TranslationDisp(1,I) !X + misc%FAST_FP(I,2) = u%PtFairleadDisplacement%Position(2,I) + u%PtFairleadDisplacement%TranslationDisp(2,I) !Y + misc%FAST_FP(I,3) = u%PtFairleadDisplacement%Position(3,I) + u%PtFairleadDisplacement%TranslationDisp(3,I) !Z + END DO + + CALL FEAM_Solve(t, n, u, p, x, xd, z, OtherState, misc, .true., ErrStat2, ErrMsg2 ) ! @yb: This is the time integration, correct? + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !Save current fairlead position for next step integration + DO I = 1,u%PtFairleadDisplacement%NNodes + OtherState%FAST_FPA(I,1) = misc%FAST_FP(I,1) + OtherState%FAST_FPA(I,2) = misc%FAST_FP(I,2) + OtherState%FAST_FPA(I,3) = misc%FAST_FP(I,3) + END DO + + call cleanup() + + return +contains + subroutine cleanup() + CALL FEAM_DestroyInput(u,ErrStat2,ErrMsg2) + end subroutine cleanup + +END SUBROUTINE FEAM_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE FEAM_CalcOutput ( t, u, p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(FEAM_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(FEAM_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at t + TYPE(FEAM_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(FEAM_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + TYPE(FEAM_OutputType), INTENT(INOUT) :: y ! Outputs computed at t (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + REAL(ReKi) :: AllOuts(MaxOutPts) ! All the the available output channels + INTEGER(IntKi) :: I,J ! Generic loop index +! INTEGER(IntKi) :: K ! Blade index +! INTEGER(IntKi) :: ErrStat2 +! CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: LEG ! Generic index + REAL(ReKi) :: TEMP ! Temporary storage + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + DO LEG=1,p%NumLines + + ! Fairlead & Anchor tensions Output + misc%FAIR_T(LEG) = x%GLU(LEG,(p%NumElems+1)*p%NHBD-1) + misc%ANCH_T(LEG) = x%GLU(LEG,p%NHBD-1) + + ! Fairlead & Anchor angle output + DO I=1, p%NDIM + misc%FAIR_ANG(LEG,I) = x%GLU(LEG,p%NumElems*p%NHBD+I*2) + misc%ANCH_ANG(LEG,I) = x%GLU(LEG,I*2) + ENDDO + + ! Line element displacement & tangent vector output + DO I=1, p%NumElems+1 + DO J=1, p%NDIM + misc%Line_Coordinate(LEG,I,J) = x%GLU(LEG,(I-1)*p%NHBD+J*2-1) + misc%Line_Tangent( LEG,I,J) = x%GLU(LEG,(I-1)*p%NHBD+J*2 ) + ENDDO + ENDDO + + ! OtherState%FAST_RP is set in UpdateStates (FEAM_Solve); seems like we should just recalculate it here: + TEMP = SQRT(OtherState%FAST_RP(LEG,1)**2+OtherState%FAST_RP(LEG,2)**2+OtherState%FAST_RP(LEG,3)**2) + DO J=1,p%NDIM + misc%F_Lines(LEG,J) = misc%FAIR_T(LEG)*(-OtherState%FAST_RP(LEG,J)/TEMP) + END DO + + ENDDO + + DO i = 1,y%PtFairleadLoad%NNodes + y%PtFairleadLoad%Force(1,i) = misc%F_Lines(i,1) + y%PtFairleadLoad%Force(2,i) = misc%F_Lines(i,2) + y%PtFairleadLoad%Force(3,i) = misc%F_Lines(i,3) + END DO + + !Below Outputs are available + !misc%FAIR_T : Fairlead tension [N] + !misc%FAIR_ANG(Line #, Direction) : Fairlead angle [rad] + !misc%ANCH_T : Anchor tension [N] + !misc%ANCH_ANG(Line #, Direction) : Anchor angle [rad] + + DO i=1,MIN(10,p%NumLines) ! 10 tension outputs + AllOuts(FairT(i)) = misc%FAIR_T(i)/1000 + AllOuts(AnchT(i)) = misc%ANCH_T(i)/1000 + END DO + + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) array with the proper sign: + !............................................................................................................................... + + DO I = 1,p%NumOuts ! Loop through all selected output channels + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + ENDDO ! I - All selected output channels + + RETURN +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE FEAM_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FEAM_ReadInput( InputFileName, InputFileData, OutFileRoot, Default_DT, Default_grav, Default_WaterDens, ErrStat, ErrMsg ) +! This subroutine reads the input file and stores all the data in the SrvD_InputFile structure. +! It does not perform data validation. +!.................................................................................................................................. + + ! Passed variables + + CHARACTER(*), INTENT(IN) :: InputFileName ! Name of the input file + CHARACTER(*), INTENT(IN) :: OutFileRoot ! The rootname of all the output files written by this routine. + + !BJJ MODIFIED HERE ONLY FOR TESTING: + TYPE(FEAM_InputFile), INTENT(OUT) :: InputFileData ! Data stored in the module's input file + REAL(DbKi), INTENT(IN) :: Default_DT ! The default DT (from glue code) + REAL(ReKi), INTENT(IN) :: Default_grav ! The default gravity (from glue code) + REAL(ReKi), INTENT(IN) :: Default_WaterDens ! The default water density (from glue code) + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = '' + + InputFileData%DT = Default_DT + InputFileData%gravity = Default_grav + InputFileData%WtrDens = Default_WaterDens + + ! get the primary/platform input-file data + + CALL ReadPrimaryFile( InputFileName, InputFileData, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! we may need to read additional files here (e.g., Bladed Interface) + + + ! close any echo file that was opened + + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE FEAM_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, OutFileRoot, UnEc, ErrStat, ErrMsg ) +! This routine reads in the primary FEAMooring input file and places the values it reads in the InputFileData structure. +! It opens and prints to an echo file if requested. +!.................................................................................................................................. + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(OUT) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + + CHARACTER(*), INTENT(IN) :: InputFile ! Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + CHARACTER(*), INTENT(IN) :: OutFileRoot ! The rootname of the echo file, possibly opened in this routine + + TYPE(FEAM_InputFile), INTENT(INOUT) :: InputFileData ! All the data in the FEAMooring input file + + ! Local variables: + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: J ! loop counter +! INTEGER(IntKi) :: NumOuts ! Number of output channel names read from the file + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 , IOS ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + CALL AllocAry( InputFileData%OutList, MaxOutPts, "FEAMooring Input File's Outlist", ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + DO + !-------------------------- HEADER --------------------------------------------- + + CALL ReadCom( UnIn, InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadStr( UnIn, InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + !---------------------- SIMULATION CONTROL -------------------------------------- + + CALL ReadCom( UnIn, InputFile, 'Section Header: Simulation Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Echo - Echo input to "<RootName>.ech". + + CALL ReadVar( UnIn, InputFile, Echo, 'Echo', 'Echo switch', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, FEAM_Ver ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(FEAM_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL CheckError( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".' ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + END DO + + CALL WrScr( ' Heading of the '//TRIM(FEAM_Ver%Name)//' input file: '//TRIM( FTitle ) ) + + + ! DT - Requested integration time for FEAMooring (seconds): + CALL ReadVar( UnIn, InputFile, Line, "DT", "Requested integration time for FEAMooring (seconds)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DT + READ( Line, *, IOSTAT=IOS) InputFileData%DT + CALL CheckIOS ( IOS, InputFile, 'DT', NumType, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2, ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + ! NumLines - Number of Mooring lines: + CALL ReadVar( UnIn, InputFile, InputFileData%NumLines, "NumLines", "Number of Mooring lines", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! NumElems - Number of elements per line: + CALL ReadVar( UnIn, InputFile, InputFileData%NumElems, "NumElems", "Number of elements per line", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Gravity - Gravitational constant: + CALL ReadVar( UnIn, InputFile, Line, "Gravity", "Gravitational constant", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%gravity + READ( Line, *, IOSTAT=IOS) InputFileData%Gravity + CALL CheckIOS ( IOS, InputFile, 'Gravity', NumType, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2, ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + ! WtrDens - Water density: + CALL ReadVar( UnIn, InputFile, Line, "WtrDens", "Water density", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%WtrDens + READ( Line, *, IOSTAT=IOS) InputFileData%WtrDens + CALL CheckIOS ( IOS, InputFile, 'WtrDens', NumType, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2, ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + ! MaxIter - Maximum number of static iterations: + CALL ReadVar( UnIn, InputFile, InputFileData%MaxIter, "MaxIter", "Maximum number of static iterations", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Eps - Static iteration tolerance: + CALL ReadVar( UnIn, InputFile, InputFileData%Eps, "Eps", "Static iteration tolerance", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Allocate arrays for input, based on maximum allowed number of blades and outputs + CALL AllocAry( InputFileData%LEAStiff, InputFileData%NumLines, 'Axial Stiffness array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LineCI, InputFileData%NumLines, 'LineCI array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LineCD, InputFileData%NumLines, 'LineCD array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LMassDen, InputFileData%NumLines, 'Mass Density array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LDMassDen, InputFileData%NumLines, 'Displaced Mass Density array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%BottmStiff, InputFileData%NumLines, 'Bottom Stiffness array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LUnstrLen, InputFileData%NumLines, 'Unstretched Length', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LRadAnch, InputFileData%NumLines, 'Anchor Radius array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LAngAnch, InputFileData%NumLines, 'Anchor Angle array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LDpthAnch, InputFileData%NumLines, 'Anchor Depth array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LRadFair, InputFileData%NumLines, 'Fairlead Radius array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LAngFair, InputFileData%NumLines, 'Fairlead Angle array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%LDrftFair, InputFileData%NumLines, 'Fairlead Draft array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%Tension, InputFileData%NumLines, 'Line Top Tension array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%GSL, InputFileData%NumLines, 2, 3, 'Linear Stiffness array', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + DO J=1,InputFileData%NumLines + + !---------------------- MOORING PROPERTIES ------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Material Properties', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LEAStiff - Axial Stiffness: + CALL ReadVar( UnIn, InputFile, InputFileData%LEAStiff(J), "LEAStiff", "Axial Stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LMassDen - Mass Density: + CALL ReadVar( UnIn, InputFile, InputFileData%LMassDen(J), "LMassDen", "Mass Density", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LDMassDen - Displaced Mass Density: + CALL ReadVar( UnIn, InputFile, InputFileData%LDMassDen(J), "LDMassDen", "Displaced Mass Density", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LineCI - Inertia Coefficient: + CALL ReadVar( UnIn, InputFile, InputFileData%LineCI(J), "LineCI", "Inertia Coefficient", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LineCD - Drag Coefficient: + CALL ReadVar( UnIn, InputFile, InputFileData%LineCD(J), "LineCD", "Drag Coefficient", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LUnstrLen - Total length: + CALL ReadVar( UnIn, InputFile, InputFileData%LUnstrLen(J), "LUnstrLen", "Total length", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! BottmStiff - Bottom Stiffness: + CALL ReadVar( UnIn, InputFile, InputFileData%BottmStiff(J), "BottmStiff", "Bottom Stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LRadAnch - Anchor Radius: + CALL ReadVar( UnIn, InputFile, InputFileData%LRadAnch(J), "LRadAnch", "Anchor Radius", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LAngAnch - Anchor Angle: + CALL ReadVar( UnIn, InputFile, InputFileData%LAngAnch(J), "LRadAnch", "Anchor Angle", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LDpthAnch - Anchor Depth: + CALL ReadVar( UnIn, InputFile, InputFileData%LDpthAnch(J), "LDpthAnch", "Anchor Depth", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LRadFair - Fairlead Radius: + CALL ReadVar( UnIn, InputFile, InputFileData%LRadFair(J), "LRadFair", "Fairlead Radius", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LAngFair - Fairlead Radius: + CALL ReadVar( UnIn, InputFile, InputFileData%LAngFair(J), "LAngFair", "Fairlead Angle", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! LDrftFair - Fairlead Draft: + CALL ReadVar( UnIn, InputFile, InputFileData%LDrftFair(J), "LDrftFair", "Fairlead Draft", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Tension - Line Top Tension: + CALL ReadVar( UnIn, InputFile, InputFileData%Tension(J), "Tension", "Line Top Tension", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GSL - Linear Stiffness: + CALL ReadAryLines( UnIn, InputFile, InputFileData%GSL(J,2,:), SIZE(InputFileData%GSL,3), "GSL", "Linear Stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + InputFileData%LAngAnch(J) = InputFileData%LAngAnch(J)*D2R ! Convert the azimuth angle of the current + InputFileData%LAngFair(J) = InputFileData%LAngFair(J)*D2R ! anchor and fairlead from degrees to radians. + + ENDDO + + !---------------------- OUTPUT -------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Output', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! SumPrint - Print summary data to <RootName>.sum (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutFile - Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-): + CALL ReadVar( UnIn, InputFile, InputFileData%OutFile, "OutFile", "Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! ! OutFileFmt - Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both): + !CALL ReadVar( UnIn, InputFile, InputFileData%OutFileFmt, "OutFileFmt", "Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + ! TabDelim - Flag to cause tab-delimited text output (delimited by space otherwise) (flag): + CALL ReadVar( UnIn, InputFile, InputFileData%TabDelim, "TabDelim", "Flag to cause tab-delimited text output (delimited by space otherwise) (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutFmt - Format used for module's text tabult output (except time); resulting field should be 10 characters (-): + CALL ReadVar( UnIn, InputFile, InputFileData%OutFmt, "OutFmt", "Format used for module's text tabular output (except time); resulting field should be 10 characters (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Tstart - Time to start module's tabular output (seconds): + CALL ReadVar( UnIn, InputFile, InputFileData%Tstart, "Tstart", "Time to start module's tabular output (seconds)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + ! + ! ! DecFact - Decimation factor for module's tabular output (1=output every step) (-): + !CALL ReadVar( UnIn, InputFile, InputFileData%DecFact, "DecFact", "Decimation factor for module's tabular output (1=output every step) (-)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- OUTLIST -------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- END OF FILE ----------------------------------------- + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) + ! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FEAM_SetParameters( InputFileData, p, ErrStat, ErrMsg ) +! This subroutine sets the parameters, based on the data stored in InputFileData +!.................................................................................................................................. + + TYPE(FEAM_InputFile), INTENT(IN) :: InputFileData ! Data stored in the module's input file + TYPE(FEAM_ParameterType), INTENT(INOUT) :: p ! The module's parameter data + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! Local variables + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + p%DT = InputFileData%DT + + ! Set parameters from primary input file + CALL SetPrimaryParameters( p, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !............................................. + ! Parameters for file output + !............................................. + p%NumOuts = InputFileData%NumOuts + + CALL SetOutParam(InputFileData%OutList, p, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( InputFileData%TabDelim ) THEN + p%Delim = TAB + ELSE + p%Delim = ' ' + END IF + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE FEAM_SetParameters +!--------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetPrimaryParameters( p, InputFileData, ErrStat, ErrMsg ) +! This takes the primary input file data and sets the corresponding parameters. +!.................................................................................................................................. + + IMPLICIT NONE + + + ! Passed variables + + TYPE(FEAM_ParameterType), INTENT(INOUT) :: p ! Parameters of the structural dynamics module + TYPE(FEAM_InputFile), INTENT(IN) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + REAL(ReKi) :: GPS(6),SHAPSS(6,4),PS(6,3) + REAL(ReKi) :: W,S,SS,SSS + INTEGER(IntKi) :: I ! Generic loop index + INTEGER(IntKi) :: M ! Generic loop index + INTEGER(IntKi) :: N ! Generic loop index + INTEGER(IntKi) :: J ! Generic loop index + INTEGER(IntKi) :: K ! Generic loop index + INTEGER(IntKi) :: L ! Generic loop index + INTEGER(IntKi) :: NN, LEG + + !bjj: ERROR CHECKING!!! + + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + !............................................................................................................................... + ! Direct copy of scalar variables variables: + !............................................................................................................................... + p%NumLines = InputFileData%NumLines + p%NumElems = InputFileData%NumElems + p%NDIM = 3 + p%NHBD = 8 + + p%Gravity = InputFileData%Gravity ! Gravity + p%WtrDens = InputFileData%WtrDens ! Water density + p%MaxIter = InputFileData%MaxIter ! Number of maximum static iteration + p%Eps = InputFileData%Eps ! Static iteration tolerance + + + !............................................................................................................................... + ! allocate arrays + !............................................................................................................................... + + CALL AllocAry( p%GSL, p%NumLines, 2, 3, 'Linear Stiffness array', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%GP, p%NumLines, 3, 'GP', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%NEQ, p%NumLines, 'NEQ', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%Elength, p%NumLines, 'Elength', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%BottmElev, p%NumLines, 'BottmElev', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%BottmStiff, p%NumLines, 'BottmStiff', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%LMassDen, p%NumLines, 'LMassDen', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%LDMassDen, p%NumLines, 'LDMassDen', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%LEAStiff, p%NumLines, 'LEAStiff', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%LineCI, p%NumLines, 'LineCI', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%LineCD, p%NumLines, 'LineCD', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%Bvp, p%NumLines, 3, 'Bvp', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%GLUZR, p%NumLines, p%NumElems+1, 2*p%NDIM, 'GLUZR', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( p%GTZER, p%NumLines, 2*p%NumElems+1, 'GTZER', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + !............................................................................................................................... + ! Direct copy of variables: + !............................................................................................................................... + p%NEQ(:) = (p%NumElems+1)*p%NHBD-1 ! number of equations + + DO I = 1, p%NumLines + p%GSL (I,:,:) = InputFileData%GSL (I,:,:) !bjj: todo: Inspector flags this as unintialized + p%LineCI (I) = InputFileData%LineCI (I) + p%LineCD (I) = InputFileData%LineCD (I) + p%Elength (I) = InputFileData%LUnstrLen(I)/p%NumElems + p%BottmElev (I) = -InputFileData%LDpthAnch (I) + p%BottmStiff (I) = InputFileData%BottmStiff (I) + p%LMassDen (I) = InputFileData%LMassDen (I) + p%LDMassDen (I) = InputFileData%LDMassDen (I) + p%LEAStiff (I) = InputFileData%LEAStiff (I) + ENDDO + + + ! set p%GTZER + + DO I=1,2*p%NumElems+1 + p%GTZER(:,I) = InputFileData%Tension(:) + ENDDO + + DO I = 1,p%NumLines + NN = 2*p%NumElems+1 + DO J = 3,NN-2,2 + p%GTZER(I,J) = 0.5*(p%GTZER(I,J-1)+p%GTZER(I,J+1)) + ENDDO + + p%GTZER(I,1) = 2.0*p%GTZER(I,2 )-p%GTZER(I,3) + p%GTZER(I,NN) = 2.0*p%GTZER(I,NN-1)-p%GTZER(I,NN-2) + END DO + !............... + + ! Line Static Analysis + DO LEG = 1, p%NumLines ! Start LEG Loop + DO I = 1,p%NDIM + p%GRAV(I)=0.0 + ENDDO + p%GRAV(p%NDIM)=-p%Gravity*(p%LMassDen(LEG)-p%LDMassDen(LEG)) + ENDDO + + + ! SET UP 6 POINT GAUSSIAN QUADRATURE INTEGRATION + ! VALUES FROM ABRAMOWITZ AND STEGUN, P. 916 + ! CHANGE INTEGRATION INTERVAL FROM (-1,1) TO (0,1) + + p%NGAUSS = 6 + GPS(4) = 0.238619186083197 + GPS(5) = 0.661209386466265 + GPS(6) = 0.932469514203152 + p%GAUSSW(4) = 0.467913934572691 + p%GAUSSW(5) = 0.360761573048139 + p%GAUSSW(6) = 0.171324492379170 + GPS(1) = -GPS(6) + GPS(2) = -GPS(5) + GPS(3) = -GPS(4) + p%GAUSSW(1) = p%GAUSSW(6) + p%GAUSSW(2) = p%GAUSSW(5) + p%GAUSSW(3) = p%GAUSSW(4) + + DO I = 1,p%NGAUSS + GPS(I) = (GPS(I) + 1.)/2. + p%GAUSSW(I) = p%GAUSSW(I)/2. + ENDDO + + + ! CALCULATE SHAPE FUNCTIONS + ! SAVE VALUES AND FIRST DERIVATIVES FOR USE IN THE PROGRAM + + DO N=1,p%NGAUSS + S = GPS(N) + SS = S*S + SSS = S*SS + + p%SHAP(N,1) = 1. - 3.*SS + 2.*SSS + p%SHAPS(N,1) = - 6.*S + 6.*SS + SHAPSS(N,1) = - 6. + 12.*S + + p%SHAP(N,2) = S - 2.*SS + SSS + p%SHAPS(N,2) = 1. - 4.*S + 3.*SS + SHAPSS(N,2) = - 4. + 6.*S + + p%SHAP(N,3) = 3.*SS - 2.*SSS + p%SHAPS(N,3) = 6.*S - 6.*SS + SHAPSS(N,3) = 6. - 12.*S + + p%SHAP(N,4) = -SS + SSS + p%SHAPS(N,4) = -2.*S + 3.*SS + SHAPSS(N,4) = -2. + 6.*S + + PS(N,1) = 1. - 3.*S + 2.*SS + PS(N,2) = 4.*S - 4.*SS + PS(N,3) = 2.*SS - S + ENDDO + + ! CALCULATE SHAPE FUNCTIONS FOR TRANPEZOIDE INTEGRATION + ! SAVE VALUES FOR USE IN THE PROGRAM + + p%NTRAP = 10 + DO N=1,p%NTRAP + S = 1.0*(N-1)/REAL((p%NTRAP-1),ReKi) + SS = S*S + SSS = S*SS + + p%SHAPT(N,1) = 1. - 3.*SS + 2.*SSS + p%SHAPTS(N,1)= - 6.*S + 6.*SS + p%SHAPT(N,2) = S - 2.*SS + SSS + p%SHAPTS(N,2)= 1. - 4.*S + 3.*SS + p%SHAPT(N,3) = 3.*SS - 2.*SSS + p%SHAPTS(N,3)= 6.*S - 6.*SS + p%SHAPT(N,4) = -SS + SSS + p%SHAPTS(N,4)= -2.*S + 3.*SS + END DO + + ! CALCULATE CONSTANT ARRAYS FOR STIFFNESS AND MASS + ! CALCULATE THE INTEGRAL OF P(M)*P(N) + ! SBEND IS FOR BENDING STIFFNESS INT EI A''A'' DS + ! STEN IS FOR TENSION (I.E., LAGRANGE MULTIPLIER) STIFFNESS + ! PMPN IS FOR TANGENTIAL STIFFNESS Dmn + ! RMASS IS MULTIPLIED BY MASS + ADDED MASS + ! RADDM IS MULTIPLIED BY -ADDED MASS TO SUBTRACT AXIAL COMPONENT + + DO I = 1,4 + p%AM(I) = 0. + DO L = 1,4 + p%SBEND(I,L) = 0. + p%STEN(1,I,L) = 0. + p%STEN(2,I,L) = 0. + p%STEN(3,I,L) = 0. + p%RMASS(I,L) = 0. + + DO M = 1,4 + DO K = 1,4 + p%RADDM(I,L,M,K) = 0. + ENDDO + ENDDO + ENDDO + ENDDO + + DO I=1,3 + p%PM(I) = 0. + DO L = 1,3 + p%PMPN(I,L) = 0. + DO K = 1,4 + p%PPA(I,L,K) = 0. + ENDDO + ENDDO + ENDDO + + ! INTEGRATE BY GAUSSIAN QUADRATURE + + DO N = 1,p%NGAUSS + W = p%GAUSSW(N) + + DO I = 1,4 + p%AM(I)=p%AM(I)+p%SHAP(N,I)*W + + DO L = 1,4 + p%SBEND(I,L) = p%SBEND(I,L) + SHAPSS(N,I)*SHAPSS(N,L)*W + p%STEN(1,I,L) = p%STEN(1,I,L) + PS(N,1)*p%SHAPS(N,I)*p%SHAPS(N,L)*W + p%STEN(2,I,L) = p%STEN(2,I,L) + PS(N,2)*p%SHAPS(N,I)*p%SHAPS(N,L)*W + p%STEN(3,I,L) = p%STEN(3,I,L) + PS(N,3)*p%SHAPS(N,I)*p%SHAPS(N,L)*W + p%RMASS(I,L) = p%RMASS(I,L) + p%SHAP(N,I)*p%SHAP(N,L)*W + + DO M = 1,4 + DO K = 1,4 + p%RADDM(I,L,M,K) = p%RADDM(I,L,M,K) + p%SHAPS(N,I)*p%SHAPS(N,L)*p%SHAP(N,M)*p%SHAP(N,K)*W + ENDDO + ENDDO + ENDDO + ENDDO + + DO I = 1,3 + p%PM(I) = p%PM(I) + PS(N,I)*W + DO L = 1,3 + p%PMPN(I,L) = p%PMPN(I,L) + PS(N,I)*PS(N,L)*W + DO K = 1,4 + p%PPA(I,L,K) = p%PPA(I,L,K) + PS(N,I)*PS(N,L)*p%SHAP(N,K)*W + ENDDO + ENDDO + END DO + + ENDDO + + ! SET COUNTERS + ! + ! NDIM IS THE NUMBER OF SPACE DIMENSIONS (2 OR 3) + ! THERE ARE NDOF = 2*NDIM DEGREES OF FREEDOM PER NODE + ! + ! EACH DEGREE OF FREEDOM (J,I) HAS AN ASSOCIATED DEGREE OF + ! FREEDOM NUMBER WITHIN THE ELEMENT. IDOF(J,I) = DOF NUMBER + ! ASSOCIATED WITH DOF (J,I). JDOF(I) = DOF NUMBER ASSOCIATED + ! WITH LAMBDA(I) + ! |1 2 7 8| + ! FOR 2D, IDOF = |3 4 9 10|, JDOF = |5 6 11| + ! + ! |1 2 9 10| + ! FOR 3D, IDOF = |3 4 11 12|, JDOF = |7 8 15| + ! |5 6 13 14| + ! + N = 0 + DO J = 1,p%NDIM + DO I = 1,2 + N = N+1 + p%IDOF(J,I) = N + ENDDO + ENDDO + + N = N+2 + DO J = 1,p%NDIM + DO I = 3,4 + N = N+1 + p%IDOF(J,I) = N + ENDDO + ENDDO + + p%NBAND = N+1 + + IF(p%NDIM.EQ.2) THEN + p%JDOF(1) = 5 + p%JDOF(2) = 6 + p%JDOF(3) = 11 + ELSE + p%JDOF(1) = 7 + p%JDOF(2) = 8 + p%JDOF(3) = 15 + ENDIF + + ! ! initialize all of the DOF parameters: + !CALL Init_DOFparameters( InputFileData, p, ErrStat, ErrMsg ) !sets p%NDOF and p%NAug + ! IF (ErrStat >= AbortErrLev) RETURN + ! + ! ! Set parameters for output channels: + !CALL SetOutParam(InputFileData%OutList, p, ErrStat, ErrMsg ) ! requires: p%NumOuts, p%NumBl, p%NBlGages, p%NTwGages; sets: p%OutParam. + ! IF (ErrStat >= AbortErrLev) RETURN + ! + !IF ( InputFileData%TabDelim ) THEN + ! p%Delim = TAB + !ELSE + ! p%Delim = ' ' + !END IF + +END SUBROUTINE SetPrimaryParameters + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 09-Dec-2014 14:03:37. +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +! This routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +! warning if any of the channels are not available outputs from the module. +! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +! the sign is set to 0 if the channel is invalid. +! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) ! The list out user-requested outputs + TYPE(FEAM_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 + + ! Local variables + + 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(20) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ANCHT1 ","ANCHT10 ","ANCHT2 ","ANCHT3 ","ANCHT4 ","ANCHT5 ","ANCHT6 ", & + "ANCHT7 ","ANCHT8 ","ANCHT9 ","FAIRT1 ","FAIRT10 ","FAIRT2 ","FAIRT3 ", & + "FAIRT4 ","FAIRT5 ","FAIRT6 ","FAIRT7 ","FAIRT8 ","FAIRT9 "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(20) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + AnchT1 , AnchT10 , AnchT2 , AnchT3 , AnchT4 , AnchT5 , AnchT6 , & + AnchT7 , AnchT8 , AnchT9 , FairT1 , FairT10 , FairT2 , FairT3 , & + FairT4 , FairT5 , FairT6 , FairT7 , FairT8 , FairT9 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(20) = (/ & ! This lists the units corresponding to the allowed parameters + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "Error allocating memory for the FEAM OutParam array." + RETURN + ELSE + ErrStat = ErrID_None + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = Time ! pick any valid channel (I just picked "Time" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + ErrStat = ErrID_Warn + ErrMsg = p%OutParam(I)%Name//" is not an available output channel. "//TRIM(ErrMsg) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateLineMesh( u, p, misc, ErrStat, ErrMsg ) + + TYPE(FEAM_InputType), INTENT(INOUT) :: u ! Inputs to be allocated + TYPE(FEAM_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: misc ! misc/optimization variables + + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + REAL(R8Ki), DIMENSION(3,3) :: R ! Rotation matrix transfering local frame coordinates to the global frame. @todo: do you prefer 0 index? + REAL(ReKi), DIMENSION(3,3) :: USkewed ! Skew symmetrix matrix. @todo: do you prefer 0 index? + REAL(ReKi), DIMENSION(3,3) :: USkewedSquare ! Square of skew symmetrix matrix + REAL(ReKi), DIMENSION(3) :: uHat ! unit vector + REAL(ReKi), DIMENSION(3) :: refAxis ! reference axis unit vector. Should be oriented with the vertical Z global axis (opposite of gravity) + REAL(ReKi), DIMENSION(3) :: lineAxis ! vector of a straitgh-line segment parallel to the local z axis of the line element. Equals OtherState%Line_Tangent + REAL(ReKi), DIMENSION(3) :: lineCrossRef ! cross product, lineAxis (cross) refAxis + REAL(ReKi) :: lineDotRef ! dot product, lineAXis (dot) refAxis + REAL(ReKi) :: theta + REAL(ReKi) :: norm + INTEGER :: I, J, K + + INTEGER :: numNodes +! REAL :: Orient(3,3) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! initialize R to zero + !R(1,1)=0.0 , R(1,2)=0.0 , R(1,3)=0.0 + !R(2,1)=0.0 , R(2,2)=0.0 , R(2,3)=0.0 + !R(3,1)=0.0 , R(3,2)=0.0 , R(3,3)=0.0 + R = 0.0 + + !! initialize USkewed to zero + !USkewed(1,1)=0.0 , USkewed(1,2)=0.0 , USkewed(1,3)=0.0 + !USkewed(2,1)=0.0 , USkewed(2,2)=0.0 , USkewed(2,3)=0.0 + !USkewed(3,1)=0.0 , USkewed(3,2)=0.0 , USkewed(3,3)=0.0 + USkewed = 0.0 + + ! initialize USkewed to zero + !USkewedSquare(1,1)=0.0 , USkewedSquare(1,2)=0.0 , USkewedSquare(1,3)=0.0 + !USkewedSquare(2,1)=0.0 , USkewedSquare(2,2)=0.0 , USkewedSquare(2,3)=0.0 + !USkewedSquare(3,1)=0.0 , USkewedSquare(3,2)=0.0 , USkewedSquare(3,3)=0.0 + USkewedSquare = 0.0 + + ! Initialize the reference axis. This should be fixed. This is assumed to be fixed relative to the global reference frame used in FAST: + ! the FAST inertia frame coordinate system--X positive downwind, Y to left when viewing downwind and Z vertical, opposite gravity. + ! We want to determine the sequence of rotations needed to convert the misc%Line_Tangent + refAxis(1)=0.0 + refAxis(2)=0.0 + refAxis(3)=1.0 + + ! initialize lineAxis + lineAxis(1)=0.0 + lineAxis(2)=0.0 + lineAxis(3)=1.0 + + ! initialize cross product variable + lineCrossRef(1)=0.0 + lineCrossRef(2)=0.0 + lineCrossRef(3)=0.0 + + ! initialize uHat + uHat(1)=0.0 + uHat(2)=0.0 + uHat(3)=1.0 + + theta = 0.0 + norm = 0.0 + + + ! Create the input and output meshes associated with lumped loads + + p%NumNodes = p%NumLines * (p%NumElems+1) + CALL MeshCreate( BlankMesh = u%HydroForceLineMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NumNodes & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + DO I=1, p%NumLines ! cycle through number of lines + DO J=1, p%NumElems+1 ! cycle through number of element in a line + + ! START Rotation Matrix Calculation <-------------------------------------------------------------------------+ + ! | + ! We are basically implementing this matlab pseudocode: ! | + ! ! | + ! line_axis = [ 0.0, 1.0, 0.0 ]; ! | + ! reference_axis = [ 1.0, 0.0, 0.0 ]; ! | + ! theta = acos( dot(line_axis,reference_axis) ); ! | + ! if norm( cross(line_axis,reference_axis) )==0 ! | + ! u = [0,0,0]; ! | + ! else ! | + ! u = cross(line_axis,reference_axis)/norm(cross(line_axis,reference_axis)); ! | + ! end ! | + ! u_skewed = [ 0 -u(3) u(2) ; ! | + ! u(3) 0 -u(1) ; ! | + ! -u(2) u(1) 0 ]; ! | + ! R = eye(3) + sin(theta)*u_skewed + (1-cos(theta))*u_skewed*u_skewed ! | + ! | + DO K=1, p%NDIM ! | + lineAxis(K) = misc%Line_Tangent(I,J,K) ! | + END DO ! | + ! | + lineDotRef = lineAxis(3) ! refAxis(1)*lineAxis(1) = 0, refAxis(2)*lineAxis(2) = 0, ! | + ! make sure we don't have numerical issues that make the value outside +/-1 + lineDotRef = min( 1.0_ReKi, lineDotRef ) + lineDotRef = max( -1.0_ReKi, lineDotRef ) + theta = ACOS( lineDotRef ) + + lineCrossRef(1) = lineAxis(2)*refAXis(3) - lineAxis(3)*refAxis(2) ! | + lineCrossRef(2) = lineAxis(3)*refAXis(1) - lineAxis(1)*refAxis(3) ! | + lineCrossRef(3) = lineAxis(1)*refAXis(2) - lineAxis(2)*refAxis(1) ! | + norm = SQRT( lineCrossRef(1)**2 + lineCrossRef(2)**2 + lineCrossRef(3)**2 ) ! | + ! | + IF( norm.EQ.0.0 ) THEN ! Shouldn't test for equality among REAL's... this is bad programming on my part.! | + uHat(1) = 0.0 ! | + uHat(2) = 0.0 ! | + uHat(3) = 0.0 ! | + ELSE ! | + uHat(1) = lineCrossRef(1)/norm ! | + uHat(2) = lineCrossRef(2)/norm ! | + uHat(3) = lineCrossRef(3)/norm ! | + ENDIF ! | + ! | + USkewed(1,1) = 0.0 + USkewed(1,2) = -uHat(3) + USkewed(1,3) = uHat(2) ! | + USkewed(2,1) = uHat(3) + USkewed(2,2) = 0.0 + USkewed(2,3) = -uHat(1) + USkewed(3,1) = -uHat(2) + USkewed(3,2) = uHat(1) + USkewed(3,3) = 0.0 ! | + ! | + ! now let's square USkewed ! | + ! first row ! | + USkewedSquare(1,1) = USkewed(1,1)*USkewed(1,1) + USkewed(1,2)*USkewed(2,1) + USkewed(1,3)*USkewed(3,1) ! | + USkewedSquare(1,2) = USkewed(1,1)*USkewed(1,2) + USkewed(1,2)*USkewed(2,2) + USkewed(1,3)*USkewed(3,2) ! | + USkewedSquare(1,3) = USkewed(1,1)*USkewed(1,3) + USkewed(1,2)*USkewed(2,3) + USkewed(1,3)*USkewed(3,3) ! | + ! | + ! second row ! | + USkewedSquare(2,1) = USkewed(2,1)*USkewed(1,1) + USkewed(2,2)*USkewed(2,1) + USkewed(2,3)*USkewed(3,1) ! | + USkewedSquare(2,2) = USkewed(2,1)*USkewed(1,2) + USkewed(2,2)*USkewed(2,2) + USkewed(2,3)*USkewed(3,2) ! | + USkewedSquare(2,3) = USkewed(2,1)*USkewed(1,3) + USkewed(2,2)*USkewed(2,3) + USkewed(2,3)*USkewed(3,3) ! | + ! | + ! third row ! | + USkewedSquare(3,1) = USkewed(3,1)*USkewed(1,1) + USkewed(3,2)*USkewed(2,1) + USkewed(3,3)*USkewed(3,1) ! | + USkewedSquare(3,2) = USkewed(3,1)*USkewed(1,2) + USkewed(3,2)*USkewed(2,2) + USkewed(3,3)*USkewed(3,2) ! | + USkewedSquare(3,3) = USkewed(3,1)*USkewed(1,3) + USkewed(3,2)*USkewed(2,3) + USkewed(3,3)*USkewed(3,3) ! | + ! | + ! lastly, calculate this: R = eye(3) + sin(theta)*u_skewed + (1-cos(theta))*u_skewed*u_skewed ! | + R(1,1) = 1.0 + SIN(theta)*USkewed(1,1) + (1-COS(theta))*USkewedSquare(1,1) ! | + R(1,2) = 0.0 + SIN(theta)*USkewed(1,2) + (1-COS(theta))*USkewedSquare(1,2) ! | + R(1,3) = 0.0 + SIN(theta)*USkewed(1,3) + (1-COS(theta))*USkewedSquare(1,3) ! | + ! | + R(2,1) = 0.0 + SIN(theta)*USkewed(2,1) + (1-COS(theta))*USkewedSquare(2,1) ! | + R(2,2) = 1.0 + SIN(theta)*USkewed(2,2) + (1-COS(theta))*USkewedSquare(2,2) ! | + R(2,3) = 0.0 + SIN(theta)*USkewed(2,3) + (1-COS(theta))*USkewedSquare(2,3) ! | + ! | + R(3,1) = 0.0 + SIN(theta)*USkewed(3,1) + (1-COS(theta))*USkewedSquare(3,1) ! | + R(3,2) = 0.0 + SIN(theta)*USkewed(3,2) + (1-COS(theta))*USkewedSquare(3,2) ! | + R(3,3) = 1.0 + SIN(theta)*USkewed(3,3) + (1-COS(theta))*USkewedSquare(3,3) ! | + ! END CALCULATE Rotation Matrix +-------------------------------------------------------------------------------+ + ! @todo: the reference orienttion R needs to be commited to the Mesh. + + + NumNodes = (I-1)*(p%NumElems+1) + J + CALL MeshPositionNode (u%HydroForceLineMesh & + , numNodes & + , misc%Line_Coordinate(I,J,:) & + , ErrStat & + , ErrMsg & + , orient=R) + IF (ErrStat >= AbortErrLev) RETURN + + ! Create the mesh element + IF ( J < p%NumElems+1) THEN + NumNodes = (I-1)*(p%NumElems+1) + J + 1 + CALL MeshConstructElement (u%HydroForceLineMesh & + , Xelement = ELEMENT_LINE2 & + , P1 = numNodes - 1 & ! node1 number + , P2 = numNodes & ! node2 number + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + END DO + + ! add the other extra element, connecting the first node on the mooring line: + + + END DO + + CALL MeshCommit ( u%HydroForceLineMesh, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + +END SUBROUTINE CreateLineMesh +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreatePtFairleadMesh( u, p, y, ErrStat, ErrMsg ) + + TYPE(FEAM_InputType), INTENT(INOUT) :: u ! Inputs to be allocated + TYPE(FEAM_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(FEAM_OutputType ), INTENT( OUT) :: y ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + INTEGER :: I ! J + INTEGER :: numNodes + REAL(ReKi) :: Pos(3) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + numNodes = p%numLines + + ! Create the input and output meshes associated with lumped loads + + CALL MeshCreate( BlankMesh = u%PtFairleadDisplacement & + ,IOS = COMPONENT_INPUT & + ,Nnodes = numNodes & + ,TranslationDisp = .TRUE. & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + ! Create the node on the mesh + DO I=1, numNodes + + Pos(1) = p%GP(I,1) + Pos(2) = p%GP(I,2) + Pos(3) = p%GP(I,3) + + CALL MeshPositionNode ( u%PtFairleadDisplacement & + , I & + , Pos & + , ErrStat & + , ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Create the mesh element + + CALL MeshConstructElement ( u%PtFairleadDisplacement & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , I ) + IF (ErrStat >= AbortErrLev) RETURN + + ENDDO + + CALL MeshCommit ( u%PtFairleadDisplacement, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + ! now, copy the input PtFairleadDisplacement to output + ! PtFairleadLoad to complete this + CALL MeshCopy ( SrcMesh = u%PtFairleadDisplacement , & + DestMesh = y%PtFairleadLoad , & + CtrlCode = MESH_SIBLING , & + IOS = COMPONENT_OUTPUT , & + Force = .TRUE. , & + ErrStat = ErrStat , & + ErrMess = ErrMsg ) + + ! End mesh initialization + + +END SUBROUTINE CreatePtFairleadMesh +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE FEAMooring +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/feamooring/src/FEAM_Driver.f90 b/OpenFAST/modules/feamooring/src/FEAM_Driver.f90 new file mode 100644 index 000000000..55d53fe76 --- /dev/null +++ b/OpenFAST/modules/feamooring/src/FEAM_Driver.f90 @@ -0,0 +1,228 @@ +PROGRAM Main + + USE FEAMooring_Types + USE FEAMooring + + USE NWTC_Library + + IMPLICIT NONE + + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(DbKi) :: dt_global ! fixed/constant global time step + REAL(DbKi) :: t_initial ! time at initialization + REAL(DbKi) :: t_final ! time at simulation end + REAL(DbKi) :: t_global ! global-loop time marker + + INTEGER(IntKi) :: n_t_final ! total number of time steps + INTEGER(IntKi) :: n_t_global ! global-loop time counter + + TYPE (FEAM_InitInputType) :: FEAM_InitInput + TYPE (FEAM_ParameterType) :: FEAM_Parameter + TYPE (FEAM_ContinuousStateType) :: FEAM_ContinuousState + TYPE (FEAM_InitOutputType) :: FEAM_InitOutput + TYPE (FEAM_DiscreteStateType) :: FEAM_DiscreteState + TYPE (FEAM_ConstraintStateType) :: FEAM_ConstraintState + TYPE (FEAM_OtherStateType) :: FEAM_OtherState + TYPE (FEAM_MiscVarType) :: FEAM_MiscVar + + TYPE (FEAM_InputType), ALLOCATABLE :: FEAM_Input(:) + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: FEAM_InputTimes + + TYPE (FEAM_OutputType) :: FEAM_Output + + INTEGER(IntKi) :: FEAM_interp_order ! order of interpolation/extrapolation + + ! Local variables + Integer(IntKi) :: i ! counter for various loops + Integer(IntKi) :: j ! counter for various loops + integer(intKi) :: Un + + ! ------------------------------------------------------------------------- + ! Initialization of glue-code time-step variables + ! ------------------------------------------------------------------------- + + t_initial = 0. + t_final = 50 !500 + + ! specify time increment; currently, all modules will be time integrated with this increment size + dt_global = 0.01 + n_t_final = ((t_final - t_initial) / dt_global ) - 1 + t_global = t_initial + + ! @bonnie : is this right? What's a good interp order? + ! @marco: the interp order is specified in the FAST input file. It can be 0, 1, or 2 + FEAM_interp_order = 0 + + ! MAP: allocate Input and Output arrays; used for interpolation and extrapolation + Allocate(FEAM_InputTimes(FEAM_interp_order + 1)) + + ! @bonnie : This is in the FAST developers glue code example, but it's probably not needed here. + Allocate(FEAM_Input(FEAM_interp_order + 1)) + + ! set the FEAM input file name and other environment terms. + FEAM_InitInput%InputFile = "FE_Mooring.dat" ! @bonnie : This needs to be set according to what is in the FAST input file. + FEAM_InitInput%NStepWave = 1 ! an arbitrary number > 0 (to set the size of the wave data, which currently contains all zero values) + FEAM_InitInput%gravity = 9.81 ! This need to be according to g used in ElastoDyn + FEAM_InitInput%WtrDens = 1025 ! This needs to be set according to seawater density in HydroDyn + FEAM_InitInput%PtfmInit = 0.0 + FEAM_InitInput%RootName = "FE_Mooring.FEAM" + + CALL GetNewUnit( Un ) + OPEN(Unit=Un,FILE='FEAM.out',STATUS='UNKNOWN') + !OPEN(Unit=2,FILE='FEAM_TTN1.out',STATUS='UNKNOWN') + !OPEN(Unit=3,FILE='FEAM_TTN2.out',STATUS='UNKNOWN') + !OPEN(Unit=4,FILE='FEAM_TTN3.out',STATUS='UNKNOWN') + + ! call the initialization routine + CALL FEAM_Init( FEAM_InitInput , & + FEAM_Input(1) , & + FEAM_Parameter , & + FEAM_ContinuousState , & + FEAM_DiscreteState , & + FEAM_ConstraintState , & + FEAM_OtherState , & + FEAM_Output , & + FEAM_MiscVar , & + dt_global , & + FEAM_InitOutput , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + CALL FEAM_DestroyInitInput ( FEAM_InitInput , ErrStat, ErrMsg ) + CALL FEAM_DestroyInitOutput ( FEAM_InitOutput , ErrStat, ErrMsg ) + + CALL DispNVD( FEAM_InitOutput%Ver ) + + + FEAM_Input(1)%PtFairleadDisplacement%TranslationDisp = 0.0 + + DO i = 2, FEAM_interp_order + 1 + CALL FEAM_CopyInput( FEAM_Input(1), FEAM_Input(i), MESH_NEWCOPY, ErrStat, ErrMsg ) + END DO + + DO i = 1, FEAM_interp_order + 1 + FEAM_InputTimes(i) = t_initial - (i - 1) * dt_global + ENDDO + + + + ! ------------------------------------------------------------------------- + ! BEGIN time marching + ! ------------------------------------------------------------------------- + CALL FEAM_CalcOutput( t_global , & + FEAM_Input(1) , & + FEAM_Parameter , & + FEAM_ContinuousState , & + FEAM_DiscreteState , & + FEAM_ConstraintState , & + FEAM_OtherState , & + FEAM_Output , & + FEAM_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + DO n_t_global = 0, n_t_final + + t_global = t_initial + dt_global*n_t_global + + !========== NOTE ====== <-----------------------------------------+ + FEAM_InputTimes(1) = t_global + dt_global + !FEAM_InputTimes(2) = FEAM_InputTimes(1) - dt_global + !FEAM_InputTimes(3) = FEAM_InputTimes(2) - dt_global + + ! Sinusoidal platform motion + FEAM_Input(1)%PtFairleadDisplacement%TranslationDisp(1,1) = 20*SIN(0.0005*n_t_global) + FEAM_Input(1)%PtFairleadDisplacement%TranslationDisp(1,2) = 20*SIN(0.0005*n_t_global) + FEAM_Input(1)%PtFairleadDisplacement%TranslationDisp(1,3) = 20*SIN(0.0005*n_t_global) + + !FEAM_Input(2)%PtFairleadDisplacement%TranslationDisp(1,1) = .001*n_t_global + !FEAM_Input(3)%PtFairleadDisplacement%TranslationDisp(1,1) = .001*n_t_global + !=========================================================================== + + + ! @bonnie & @jason: the FAST glue code will update the new fairlead position + ! based on the new platform position in the global frame. + CALL FEAM_UpdateStates( t_global , & + n_t_global , & + FEAM_Input , & + FEAM_InputTimes , & + FEAM_Parameter , & + FEAM_ContinuousState , & + FEAM_DiscreteState , & + FEAM_ConstraintState , & + FEAM_OtherState , & + FEAM_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + CALL FEAM_CalcOutput( t_global , & + FEAM_Input(1) , & + FEAM_Parameter , & + FEAM_ContinuousState , & + FEAM_DiscreteState , & + FEAM_ConstraintState , & + FEAM_OtherState , & + FEAM_Output , & + FEAM_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + ! update the global time step by one delta t + t_global = ( n_t_global + 1 )* dt_global + t_initial + + WRITE(Un,100) t_global, FEAM_Input(1)%PtFairleadDisplacement%TranslationDisp(1,1), & + ((FEAM_Output%PtFairleadLoad%Force(i,j), i=1,3),j=1,3) + !WRITE(*,*) t_global + + END DO + ! ------------------------------------------------------------------------- + ! END time marching + ! ------------------------------------------------------------------------- + + ! Destroy all objects + CALL FEAM_End( FEAM_Input(1) , & + FEAM_Parameter , & + FEAM_ContinuousState , & + FEAM_DiscreteState , & + FEAM_ConstraintState , & + FEAM_OtherState , & + FEAM_Output , & + FEAM_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + do j = 2,FEAM_interp_order+1 + call FEAM_DestroyInput( FEAM_Input(j), ErrStat, ErrMsg) + end do + + DEALLOCATE(FEAM_Input) + DEALLOCATE(FEAM_InputTimes) + + CALL WrScr( "Program has ended" ) + close (un) + +100 FORMAT(2(1X,F8.3),9(1X,E12.5)) + +END PROGRAM Main diff --git a/OpenFAST/modules/feamooring/src/FEAM_Registry.txt b/OpenFAST/modules/feamooring/src/FEAM_Registry.txt new file mode 100644 index 000000000..c0482b23b --- /dev/null +++ b/OpenFAST/modules/feamooring/src/FEAM_Registry.txt @@ -0,0 +1,219 @@ +################################################################################################################################### +# Registry for FEMooring in the FAST Modularization Framework +# This Registry file is used to create MODULE FEMooring_Types which contains all of the user-defined types needed in FEMooring. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +#bjj NOTE: All variables initialized here should be double-checked that they are properly initialized in the new framework (i.e. can run twice) + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary Input file data ........................................................................................................... +typedef FEAMooring/FEAM FEAM_InputFile DbKi DT - - - "Communication interval for mooring dynamics" s +typedef ^ ^ ReKi LineCI {:} - - "Mooring line inertia coefficient" - +typedef ^ ^ ReKi LineCD {:} - - "Mooring line drag coefficient" - +typedef ^ ^ ReKi LEAStiff {:} - - "Mooring line axial stiffness" - +typedef ^ ^ ReKi LMassDen {:} - - "Mooring line mass per unit length" - +typedef ^ ^ ReKi LDMassDen {:} - - "Mooring line displaced mass per unit length" - +typedef ^ ^ ReKi BottmStiff {:} - - "Seabed spring stiffness" - +typedef ^ ^ ReKi LRadAnch {:} - - "Anchor Radius" - +typedef ^ ^ ReKi LAngAnch {:} - - "Anchor Angle" - +typedef ^ ^ ReKi LDpthAnch {:} - - "Anchor Depth" - +typedef ^ ^ ReKi LRadFair {:} - - "Fairlead Radius" - +typedef ^ ^ ReKi LAngFair {:} - - "Fairlead Radius" - +typedef ^ ^ ReKi LDrftFair {:} - - "Fairlead Draft" - +typedef ^ ^ ReKi LUnstrLen {:} - - "Line unstretched length" - +typedef ^ ^ ReKi Tension {:} - - "Line Top Tension" - +typedef ^ ^ ReKi GSL {:}{:}{:} - - "Linear spring stiffness at fairlead" - +typedef ^ ^ ReKi GSR {:}{:} - - "Rotational spring stiffness at fairlead" - +typedef ^ ^ ReKi GE {:}{:}{:} - - "Reference tangent vector at fairlead" - +typedef ^ ^ IntKi NumLines - - - "Number of lines" +typedef ^ ^ IntKi NumElems - - - "Number of elements" - +typedef ^ ^ ReKi Eps - - - "Tolerance for static iteration" +typedef ^ ^ ReKi Gravity - - - "Gravity" +typedef ^ ^ ReKi WtrDens - - - "Water density" +typedef ^ ^ IntKi MaxIter - - - "Maximum number of iteration step for static analysis" +typedef ^ ^ LOGICAL SumPrint - - - "Print summary data to <RootName>.fsm?" - +typedef ^ ^ IntKi OutFile - - - "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both)" - +typedef ^ ^ LOGICAL TabDelim - - - "Use tab delimiters in text tabular output file?" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "Format used for text tabular output (except time)" - +typedef ^ ^ DbKi Tstart - - - "Time to start module's tabular output" s +typedef ^ ^ IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ^ CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - + + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef FEAMooring/FEAM InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ ReKi PtfmInit {6} - - "Platform Initial Position" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ ReKi WaveAcc0 {:}{:}{:} - - "" - +typedef ^ ^ ReKi WaveTime {:} - - "" - +typedef ^ ^ ReKi WaveVel0 {:}{:}{:} - - "" - +typedef ^ ^ ReKi Gravity - - - "Gravity" +typedef ^ ^ ReKi WtrDens - - - "Water density" + +# Define outputs from the initialization routine here: +typedef FEAMooring/FEAM InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ ^ ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ ^ ReKi LAnchxi {:} - - "Anchor coordinate" - +typedef ^ ^ ReKi LAnchyi {:} - - "Anchor coordinate" - +typedef ^ ^ ReKi LAnchzi {:} - - "Anchor coordinate" - +typedef ^ ^ ReKi LFairxt {:} - - "Fairlead coordinate" - +typedef ^ ^ ReKi LFairyt {:} - - "Fairlead coordinate" - +typedef ^ ^ ReKi LFairzt {:} - - "Fairlead coordinate" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef FEAMooring/FEAM ContinuousStateType ReKi GLU {:}{:} - - "Global matrix U (displacement)" - +typedef ^ ^ ReKi GLDU {:}{:} - - "Global matrix DU (velocity)" - + + + +# Define discrete (nondifferentiable) states here: +typedef FEAMooring/FEAM DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - + + +# Define constraint states here: +typedef FEAMooring/FEAM ConstraintStateType ReKi TSN {3} - - "Lagrangian multiplier" - +typedef ^ ^ ReKi TZER {3} - - "Lagrangian multiplier" - + + +# Define any other states, including integer or logical states here: +typedef FEAMooring/FEAM OtherStateType ReKi GLU0 {:}{:} - - "Global matrix U0 (previous state)" - +typedef ^ ^ ReKi GLDDU {:}{:} - - "Global matrix DDU (accleration) -- other state" - +typedef ^ ^ LOGICAL BottomTouch - - - "Bottom touch flag" +# saved from previous time step +typedef ^ ^ ReKi GFORC0 {:}{:}{:} - - "Old element force matrix" - +typedef ^ ^ ReKi GMASS0 {:}{:}{:}{:} - - "Old element mass matrix" - +typedef ^ ^ ReKi FAST_FPA {:}{:} - - "Fairlead position - inputs from previous time step (we should replace this with a call to extrap-interp)" - +typedef ^ ^ ReKi FAST_RP {:}{:} - - "Fairlead tangent - part of output computation that was calculated in UpdateStates" - +typedef ^ ^ IntKi INCR - - - "FEAM step" +typedef ^ ^ ReKi RSDF {15} - - "Line residue force - modifies values from previous call to FEAM_Solve" +#bjj: these might be local variables, but they weren't initialized when INCR==0, so I'm not sure +typedef ^ ^ ReKi FORC0 {15} - - - "Local old element force matrix" - +typedef ^ ^ ReKi EMAS0 {15}{15} - - "Local old element mass matrix" - + + + +# ..... 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. +# these could be local variables: +typedef ^ MiscVarType ReKi GLF {:}{:} - - "Global forcing matrix" - +typedef ^ ^ ReKi GLK {:}{:}{:} - - "Global stiffness matrix" - +typedef ^ ^ ReKi EMASS {15}{15} - - "Line element mass" +typedef ^ ^ ReKi ESTIF {15}{15} - - "Line element stiffness" +typedef ^ ^ ReKi FAST_FP {:}{:} - - "Fairlead position at t+dt" - +typedef ^ ^ ReKi FORCE {15} - - "Line external force" +typedef ^ ^ ReKi FP {3} - - "Fairlead position - used in Couple routine" - +typedef ^ ^ ReKi U {3}{4} - - "Local matrix U" - +typedef ^ ^ ReKi U0 {3}{4} - - "Local matrix U0" - +typedef ^ ^ ReKi DU {3}{4} - - "Local matrix DU" - +typedef ^ ^ ReKi DDU {3}{4} - - "Local matrix DDU" - +typedef ^ ^ ReKi R {3} - - "POSITION VECTOR OF NODE OF ROD ELEMENT" - +typedef ^ ^ ReKi RP {3} - - "DR/DS AT R (TANGENT - NEED NOT BE UNIT VECTOR)" - +typedef ^ ^ ReKi RHSR {6} - - "RIGHT HAND SIDE CONTRIBUTION TO 6 DEGREES OF FREEDOM OF ROD NODE" - +typedef ^ ^ ReKi SLIN {3} - - "LINEAR SPRING CONSTANT - portion of p%GSL" "(UNITS OF FORCE/LENGTH)" +typedef ^ ^ ReKi STIFR {6}{6} - - "STIFFNESS COEFFICIENTS FOR 6 DEGREES OF FREEDOM OF ROD NODE (X,DX/DS,Y,DY/DS,Z,DZ/DS)" - +# these values for WriteOutput could be local variables: +typedef ^ ^ ReKi FAIR_ANG {:}{:} - - "Fairlead angle" - +typedef ^ ^ ReKi FAIR_T {:} - - "Fairlead tension" - +typedef ^ ^ ReKi ANCH_ANG {:}{:} - - "Anchor angle" - +typedef ^ ^ ReKi ANCH_T {:} - - "Anchor tension" - +typedef ^ ^ ReKi Line_Coordinate {:}{:}{:} - - "Mooring line coordinate" - +typedef ^ ^ ReKi Line_Tangent {:}{:}{:} - - "Mooring line tangent vector" - +typedef ^ ^ ReKi F_Lines {:}{:} - - "Mooring restoring force" +# optimization variables: +typedef ^ ^ IntKi LastIndWave - - - "FEAM step" + + +# ..... Parameters ................................................................................................................ +# Define parameters here: +# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: +typedef FEAMooring/FEAM ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ^ ReKi GRAV {3} - - "Gravity" - +# parameters from Mooring +typedef ^ ^ ReKi Eps - - - "Tolerance for static iteration" +typedef ^ ^ ReKi Gravity - - - "Gravity" +typedef ^ ^ ReKi WtrDens - - - "Water density" +typedef ^ ^ IntKi MaxIter - - - "Maximum number of iteration step for static analysis" +typedef ^ ^ IntKi NHBD - - - "Bandwidth = (NBAND+1)/2" +typedef ^ ^ IntKi NDIM - - - "Dimension = 3" +typedef ^ ^ IntKi NEQ {:} - - "Number of equation" +typedef ^ ^ IntKi NBAND - - - "Bandwidth" +typedef ^ ^ IntKi NumLines - - - "Number of lines" +typedef ^ ^ IntKi NumElems - - - "Number of elements" +typedef ^ ^ IntKi NumNodes - - - "Number of nodes" +typedef ^ ^ ReKi GSL {:}{:}{:} - - "Linear spring stiffness at fairlead" - +typedef ^ ^ ReKi GP {:}{:} - - "Fairlead position" - +typedef ^ ^ ReKi Elength {:} - - "Element length" - +typedef ^ ^ ReKi BottmElev {:} - - "Bottom elevation" - +typedef ^ ^ ReKi BottmStiff {:} - - "Bottom stiffness" - +typedef ^ ^ ReKi LMassDen {:} - - "Line mass per unit length" - +typedef ^ ^ ReKi LDMassDen {:} - - "Line displaced mass per unit length" - +typedef ^ ^ ReKi LEAStiff {:} - - "Line axial stiffness" - +typedef ^ ^ ReKi LineCI {:} - - "Line inertia coefficient" - +typedef ^ ^ ReKi LineCD {:} - - "Line drag coefficient" - +typedef ^ ^ ReKi Bvp {:}{:} - - "Boundary condtion" - +typedef ^ ^ ReKi WaveAcc0 {:}{:}{:} - - "" - +typedef ^ ^ ReKi WaveTime {:} - - "" - +typedef ^ ^ ReKi WaveVel0 {:}{:}{:} - - "" - +typedef ^ ^ IntKi NStepWave - - - "Number of wave steps" + +# parameters from Shape Functions +typedef ^ ^ ReKi SHAP {6}{4} - - "Shape function" +typedef ^ ^ ReKi SHAPS {6}{4} - - "Shape function" +typedef ^ ^ ReKi GAUSSW {6} - - "Shape function" +typedef ^ ^ IntKi NGAUSS - - - "6 POINT GAUSSIAN QUADRATURE INTEGRATION" +typedef ^ ^ ReKi SHAPT {10}{4} - - "Shape function" +typedef ^ ^ ReKi SHAPTS {10}{4} - - "Shape function" +typedef ^ ^ IntKi NTRAP - - - "10 TRANPEZOIDE INTEGRATION point" +typedef ^ ^ ReKi SBEND {4}{4} - - "Internal" +typedef ^ ^ ReKi STEN {3}{4}{4} - - "Internal" +typedef ^ ^ ReKi RMASS {4}{4} - - "Internal" +typedef ^ ^ ReKi RADDM {4}{4}{4}{4} - - "Internal" +typedef ^ ^ ReKi PMPN {3}{3} - - "Internal" +typedef ^ ^ ReKi AM {4} - - "Internal" +typedef ^ ^ ReKi PM {3} - - "Internal" +typedef ^ ^ IntKi IDOF {3}{4} - - "Internal" +typedef ^ ^ IntKi JDOF {3} - - "Internal" +typedef ^ ^ ReKi PPA {3}{3}{4} - - "Internal" +typedef ^ ^ ReKi PtfmRefzt - - - "Platform reference" +# parameters for output +typedef ^ ^ IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ^ CHARACTER(1) Delim - - - "Column delimiter for output text files" - + +# parameters that used to be other states +typedef ^ ^ ReKi GLUZR {:}{:}{:} - - "Line coordinate & direction cosine" - +typedef ^ ^ ReKi GTZER {:}{:} - - "Line tension" - + + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef FEAMooring/FEAM InputType MeshType HydroForceLineMesh - - - "Meshed input data" - +typedef ^ ^ MeshType PtFairleadDisplacement - - - "Meshed input data" - + + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +# Define outputs that are not on this mesh here: +typedef FEAMooring/FEAM OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ ^ MeshType PtFairleadLoad - - - "Meshed output data" - +typedef ^ ^ MeshType LineMeshPosition - - - "Meshed output data" - diff --git a/OpenFAST/modules/feamooring/src/FEAMooring_Types.f90 b/OpenFAST/modules/feamooring/src/FEAMooring_Types.f90 new file mode 100644 index 000000000..ffed53236 --- /dev/null +++ b/OpenFAST/modules/feamooring/src/FEAMooring_Types.f90 @@ -0,0 +1,7286 @@ +!STARTOFREGISTRYGENERATEDFILE 'FEAMooring_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 +!********************************************************************************************************************************* +! FEAMooring_Types +!................................................................................................................................. +! This file is part of FEAMooring. +! +! 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 FEAMooring. 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 FEAMooring_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= FEAM_InputFile ======= + TYPE, PUBLIC :: FEAM_InputFile + REAL(DbKi) :: DT !< Communication interval for mooring dynamics [s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineCI !< Mooring line inertia coefficient [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineCD !< Mooring line drag coefficient [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LEAStiff !< Mooring line axial stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LMassDen !< Mooring line mass per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LDMassDen !< Mooring line displaced mass per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BottmStiff !< Seabed spring stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LRadAnch !< Anchor Radius [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LAngAnch !< Anchor Angle [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LDpthAnch !< Anchor Depth [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LRadFair !< Fairlead Radius [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LAngFair !< Fairlead Radius [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LDrftFair !< Fairlead Draft [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LUnstrLen !< Line unstretched length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Tension !< Line Top Tension [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GSL !< Linear spring stiffness at fairlead [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GSR !< Rotational spring stiffness at fairlead [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GE !< Reference tangent vector at fairlead [-] + INTEGER(IntKi) :: NumLines !< Number of lines [-] + INTEGER(IntKi) :: NumElems !< Number of elements [-] + REAL(ReKi) :: Eps !< Tolerance for static iteration [-] + REAL(ReKi) :: Gravity !< Gravity [-] + REAL(ReKi) :: WtrDens !< Water density [-] + INTEGER(IntKi) :: MaxIter !< Maximum number of iteration step for static analysis [-] + LOGICAL :: SumPrint !< Print summary data to <RootName>.fsm? [-] + INTEGER(IntKi) :: OutFile !< Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) [-] + LOGICAL :: TabDelim !< Use tab delimiters in text tabular output file? [-] + CHARACTER(20) :: OutFmt !< Format used for text tabular output (except time) [-] + REAL(DbKi) :: Tstart !< Time to start module's tabular output [s] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + END TYPE FEAM_InputFile +! ======================= +! ========= FEAM_InitInputType ======= + TYPE, PUBLIC :: FEAM_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(1:6) :: PtfmInit !< Platform Initial Position [-] + INTEGER(IntKi) :: NStepWave !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc0 !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel0 !< [-] + REAL(ReKi) :: Gravity !< Gravity [-] + REAL(ReKi) :: WtrDens !< Water density [-] + END TYPE FEAM_InitInputType +! ======================= +! ========= FEAM_InitOutputType ======= + TYPE, PUBLIC :: FEAM_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LAnchxi !< Anchor coordinate [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LAnchyi !< Anchor coordinate [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LAnchzi !< Anchor coordinate [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LFairxt !< Fairlead coordinate [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LFairyt !< Fairlead coordinate [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LFairzt !< Fairlead coordinate [-] + END TYPE FEAM_InitOutputType +! ======================= +! ========= FEAM_ContinuousStateType ======= + TYPE, PUBLIC :: FEAM_ContinuousStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GLU !< Global matrix U (displacement) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GLDU !< Global matrix DU (velocity) [-] + END TYPE FEAM_ContinuousStateType +! ======================= +! ========= FEAM_DiscreteStateType ======= + TYPE, PUBLIC :: FEAM_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE FEAM_DiscreteStateType +! ======================= +! ========= FEAM_ConstraintStateType ======= + TYPE, PUBLIC :: FEAM_ConstraintStateType + REAL(ReKi) , DIMENSION(1:3) :: TSN !< Lagrangian multiplier [-] + REAL(ReKi) , DIMENSION(1:3) :: TZER !< Lagrangian multiplier [-] + END TYPE FEAM_ConstraintStateType +! ======================= +! ========= FEAM_OtherStateType ======= + TYPE, PUBLIC :: FEAM_OtherStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GLU0 !< Global matrix U0 (previous state) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GLDDU !< Global matrix DDU (accleration) -- other state [-] + LOGICAL :: BottomTouch !< Bottom touch flag [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GFORC0 !< Old element force matrix [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: GMASS0 !< Old element mass matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FAST_FPA !< Fairlead position - inputs from previous time step (we should replace this with a call to extrap-interp) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FAST_RP !< Fairlead tangent - part of output computation that was calculated in UpdateStates [-] + INTEGER(IntKi) :: INCR !< FEAM step [-] + REAL(ReKi) , DIMENSION(1:15) :: RSDF !< Line residue force - modifies values from previous call to FEAM_Solve [-] + REAL(ReKi) , DIMENSION(1:15) :: FORC0 !< - [Local old element force matrix] + REAL(ReKi) , DIMENSION(1:15,1:15) :: EMAS0 !< Local old element mass matrix [-] + END TYPE FEAM_OtherStateType +! ======================= +! ========= FEAM_MiscVarType ======= + TYPE, PUBLIC :: FEAM_MiscVarType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GLF !< Global forcing matrix [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GLK !< Global stiffness matrix [-] + REAL(ReKi) , DIMENSION(1:15,1:15) :: EMASS !< Line element mass [-] + REAL(ReKi) , DIMENSION(1:15,1:15) :: ESTIF !< Line element stiffness [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FAST_FP !< Fairlead position at t+dt [-] + REAL(ReKi) , DIMENSION(1:15) :: FORCE !< Line external force [-] + REAL(ReKi) , DIMENSION(1:3) :: FP !< Fairlead position - used in Couple routine [-] + REAL(ReKi) , DIMENSION(1:3,1:4) :: U !< Local matrix U [-] + REAL(ReKi) , DIMENSION(1:3,1:4) :: U0 !< Local matrix U0 [-] + REAL(ReKi) , DIMENSION(1:3,1:4) :: DU !< Local matrix DU [-] + REAL(ReKi) , DIMENSION(1:3,1:4) :: DDU !< Local matrix DDU [-] + REAL(ReKi) , DIMENSION(1:3) :: R !< POSITION VECTOR OF NODE OF ROD ELEMENT [-] + REAL(ReKi) , DIMENSION(1:3) :: RP !< DR/DS AT R (TANGENT - NEED NOT BE UNIT VECTOR) [-] + REAL(ReKi) , DIMENSION(1:6) :: RHSR !< RIGHT HAND SIDE CONTRIBUTION TO 6 DEGREES OF FREEDOM OF ROD NODE [-] + REAL(ReKi) , DIMENSION(1:3) :: SLIN !< LINEAR SPRING CONSTANT - portion of p%GSL [(UNITS OF FORCE/LENGTH)] + REAL(ReKi) , DIMENSION(1:6,1:6) :: STIFR !< STIFFNESS COEFFICIENTS FOR 6 DEGREES OF FREEDOM OF ROD NODE (X,DX/DS,Y,DY/DS,Z,DZ/DS) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FAIR_ANG !< Fairlead angle [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FAIR_T !< Fairlead tension [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ANCH_ANG !< Anchor angle [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ANCH_T !< Anchor tension [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Line_Coordinate !< Mooring line coordinate [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Line_Tangent !< Mooring line tangent vector [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_Lines !< Mooring restoring force [-] + INTEGER(IntKi) :: LastIndWave !< FEAM step [-] + END TYPE FEAM_MiscVarType +! ======================= +! ========= FEAM_ParameterType ======= + TYPE, PUBLIC :: FEAM_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + REAL(ReKi) , DIMENSION(1:3) :: GRAV !< Gravity [-] + REAL(ReKi) :: Eps !< Tolerance for static iteration [-] + REAL(ReKi) :: Gravity !< Gravity [-] + REAL(ReKi) :: WtrDens !< Water density [-] + INTEGER(IntKi) :: MaxIter !< Maximum number of iteration step for static analysis [-] + INTEGER(IntKi) :: NHBD !< Bandwidth = (NBAND+1)/2 [-] + INTEGER(IntKi) :: NDIM !< Dimension = 3 [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NEQ !< Number of equation [-] + INTEGER(IntKi) :: NBAND !< Bandwidth [-] + INTEGER(IntKi) :: NumLines !< Number of lines [-] + INTEGER(IntKi) :: NumElems !< Number of elements [-] + INTEGER(IntKi) :: NumNodes !< Number of nodes [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GSL !< Linear spring stiffness at fairlead [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GP !< Fairlead position [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Elength !< Element length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BottmElev !< Bottom elevation [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BottmStiff !< Bottom stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LMassDen !< Line mass per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LDMassDen !< Line displaced mass per unit length [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LEAStiff !< Line axial stiffness [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineCI !< Line inertia coefficient [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineCD !< Line drag coefficient [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Bvp !< Boundary condtion [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc0 !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel0 !< [-] + INTEGER(IntKi) :: NStepWave !< Number of wave steps [-] + REAL(ReKi) , DIMENSION(1:6,1:4) :: SHAP !< Shape function [-] + REAL(ReKi) , DIMENSION(1:6,1:4) :: SHAPS !< Shape function [-] + REAL(ReKi) , DIMENSION(1:6) :: GAUSSW !< Shape function [-] + INTEGER(IntKi) :: NGAUSS !< 6 POINT GAUSSIAN QUADRATURE INTEGRATION [-] + REAL(ReKi) , DIMENSION(1:10,1:4) :: SHAPT !< Shape function [-] + REAL(ReKi) , DIMENSION(1:10,1:4) :: SHAPTS !< Shape function [-] + INTEGER(IntKi) :: NTRAP !< 10 TRANPEZOIDE INTEGRATION point [-] + REAL(ReKi) , DIMENSION(1:4,1:4) :: SBEND !< Internal [-] + REAL(ReKi) , DIMENSION(1:3,1:4,1:4) :: STEN !< Internal [-] + REAL(ReKi) , DIMENSION(1:4,1:4) :: RMASS !< Internal [-] + REAL(ReKi) , DIMENSION(1:4,1:4,1:4,1:4) :: RADDM !< Internal [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: PMPN !< Internal [-] + REAL(ReKi) , DIMENSION(1:4) :: AM !< Internal [-] + REAL(ReKi) , DIMENSION(1:3) :: PM !< Internal [-] + INTEGER(IntKi) , DIMENSION(1:3,1:4) :: IDOF !< Internal [-] + INTEGER(IntKi) , DIMENSION(1:3) :: JDOF !< Internal [-] + REAL(ReKi) , DIMENSION(1:3,1:3,1:4) :: PPA !< Internal [-] + REAL(ReKi) :: PtfmRefzt !< Platform reference [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: GLUZR !< Line coordinate & direction cosine [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: GTZER !< Line tension [-] + END TYPE FEAM_ParameterType +! ======================= +! ========= FEAM_InputType ======= + TYPE, PUBLIC :: FEAM_InputType + TYPE(MeshType) :: HydroForceLineMesh !< Meshed input data [-] + TYPE(MeshType) :: PtFairleadDisplacement !< Meshed input data [-] + END TYPE FEAM_InputType +! ======================= +! ========= FEAM_OutputType ======= + TYPE, PUBLIC :: FEAM_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + TYPE(MeshType) :: PtFairleadLoad !< Meshed output data [-] + TYPE(MeshType) :: LineMeshPosition !< Meshed output data [-] + END TYPE FEAM_OutputType +! ======================= +CONTAINS + SUBROUTINE FEAM_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(FEAM_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'FEAM_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DT = SrcInputFileData%DT +IF (ALLOCATED(SrcInputFileData%LineCI)) THEN + i1_l = LBOUND(SrcInputFileData%LineCI,1) + i1_u = UBOUND(SrcInputFileData%LineCI,1) + IF (.NOT. ALLOCATED(DstInputFileData%LineCI)) THEN + ALLOCATE(DstInputFileData%LineCI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LineCI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LineCI = SrcInputFileData%LineCI +ENDIF +IF (ALLOCATED(SrcInputFileData%LineCD)) THEN + i1_l = LBOUND(SrcInputFileData%LineCD,1) + i1_u = UBOUND(SrcInputFileData%LineCD,1) + IF (.NOT. ALLOCATED(DstInputFileData%LineCD)) THEN + ALLOCATE(DstInputFileData%LineCD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LineCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LineCD = SrcInputFileData%LineCD +ENDIF +IF (ALLOCATED(SrcInputFileData%LEAStiff)) THEN + i1_l = LBOUND(SrcInputFileData%LEAStiff,1) + i1_u = UBOUND(SrcInputFileData%LEAStiff,1) + IF (.NOT. ALLOCATED(DstInputFileData%LEAStiff)) THEN + ALLOCATE(DstInputFileData%LEAStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LEAStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LEAStiff = SrcInputFileData%LEAStiff +ENDIF +IF (ALLOCATED(SrcInputFileData%LMassDen)) THEN + i1_l = LBOUND(SrcInputFileData%LMassDen,1) + i1_u = UBOUND(SrcInputFileData%LMassDen,1) + IF (.NOT. ALLOCATED(DstInputFileData%LMassDen)) THEN + ALLOCATE(DstInputFileData%LMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LMassDen = SrcInputFileData%LMassDen +ENDIF +IF (ALLOCATED(SrcInputFileData%LDMassDen)) THEN + i1_l = LBOUND(SrcInputFileData%LDMassDen,1) + i1_u = UBOUND(SrcInputFileData%LDMassDen,1) + IF (.NOT. ALLOCATED(DstInputFileData%LDMassDen)) THEN + ALLOCATE(DstInputFileData%LDMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LDMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LDMassDen = SrcInputFileData%LDMassDen +ENDIF +IF (ALLOCATED(SrcInputFileData%BottmStiff)) THEN + i1_l = LBOUND(SrcInputFileData%BottmStiff,1) + i1_u = UBOUND(SrcInputFileData%BottmStiff,1) + IF (.NOT. ALLOCATED(DstInputFileData%BottmStiff)) THEN + ALLOCATE(DstInputFileData%BottmStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%BottmStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%BottmStiff = SrcInputFileData%BottmStiff +ENDIF +IF (ALLOCATED(SrcInputFileData%LRadAnch)) THEN + i1_l = LBOUND(SrcInputFileData%LRadAnch,1) + i1_u = UBOUND(SrcInputFileData%LRadAnch,1) + IF (.NOT. ALLOCATED(DstInputFileData%LRadAnch)) THEN + ALLOCATE(DstInputFileData%LRadAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LRadAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LRadAnch = SrcInputFileData%LRadAnch +ENDIF +IF (ALLOCATED(SrcInputFileData%LAngAnch)) THEN + i1_l = LBOUND(SrcInputFileData%LAngAnch,1) + i1_u = UBOUND(SrcInputFileData%LAngAnch,1) + IF (.NOT. ALLOCATED(DstInputFileData%LAngAnch)) THEN + ALLOCATE(DstInputFileData%LAngAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LAngAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LAngAnch = SrcInputFileData%LAngAnch +ENDIF +IF (ALLOCATED(SrcInputFileData%LDpthAnch)) THEN + i1_l = LBOUND(SrcInputFileData%LDpthAnch,1) + i1_u = UBOUND(SrcInputFileData%LDpthAnch,1) + IF (.NOT. ALLOCATED(DstInputFileData%LDpthAnch)) THEN + ALLOCATE(DstInputFileData%LDpthAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LDpthAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LDpthAnch = SrcInputFileData%LDpthAnch +ENDIF +IF (ALLOCATED(SrcInputFileData%LRadFair)) THEN + i1_l = LBOUND(SrcInputFileData%LRadFair,1) + i1_u = UBOUND(SrcInputFileData%LRadFair,1) + IF (.NOT. ALLOCATED(DstInputFileData%LRadFair)) THEN + ALLOCATE(DstInputFileData%LRadFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LRadFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LRadFair = SrcInputFileData%LRadFair +ENDIF +IF (ALLOCATED(SrcInputFileData%LAngFair)) THEN + i1_l = LBOUND(SrcInputFileData%LAngFair,1) + i1_u = UBOUND(SrcInputFileData%LAngFair,1) + IF (.NOT. ALLOCATED(DstInputFileData%LAngFair)) THEN + ALLOCATE(DstInputFileData%LAngFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LAngFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LAngFair = SrcInputFileData%LAngFair +ENDIF +IF (ALLOCATED(SrcInputFileData%LDrftFair)) THEN + i1_l = LBOUND(SrcInputFileData%LDrftFair,1) + i1_u = UBOUND(SrcInputFileData%LDrftFair,1) + IF (.NOT. ALLOCATED(DstInputFileData%LDrftFair)) THEN + ALLOCATE(DstInputFileData%LDrftFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LDrftFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LDrftFair = SrcInputFileData%LDrftFair +ENDIF +IF (ALLOCATED(SrcInputFileData%LUnstrLen)) THEN + i1_l = LBOUND(SrcInputFileData%LUnstrLen,1) + i1_u = UBOUND(SrcInputFileData%LUnstrLen,1) + IF (.NOT. ALLOCATED(DstInputFileData%LUnstrLen)) THEN + ALLOCATE(DstInputFileData%LUnstrLen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LUnstrLen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LUnstrLen = SrcInputFileData%LUnstrLen +ENDIF +IF (ALLOCATED(SrcInputFileData%Tension)) THEN + i1_l = LBOUND(SrcInputFileData%Tension,1) + i1_u = UBOUND(SrcInputFileData%Tension,1) + IF (.NOT. ALLOCATED(DstInputFileData%Tension)) THEN + ALLOCATE(DstInputFileData%Tension(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%Tension.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%Tension = SrcInputFileData%Tension +ENDIF +IF (ALLOCATED(SrcInputFileData%GSL)) THEN + i1_l = LBOUND(SrcInputFileData%GSL,1) + i1_u = UBOUND(SrcInputFileData%GSL,1) + i2_l = LBOUND(SrcInputFileData%GSL,2) + i2_u = UBOUND(SrcInputFileData%GSL,2) + i3_l = LBOUND(SrcInputFileData%GSL,3) + i3_u = UBOUND(SrcInputFileData%GSL,3) + IF (.NOT. ALLOCATED(DstInputFileData%GSL)) THEN + ALLOCATE(DstInputFileData%GSL(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%GSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%GSL = SrcInputFileData%GSL +ENDIF +IF (ALLOCATED(SrcInputFileData%GSR)) THEN + i1_l = LBOUND(SrcInputFileData%GSR,1) + i1_u = UBOUND(SrcInputFileData%GSR,1) + i2_l = LBOUND(SrcInputFileData%GSR,2) + i2_u = UBOUND(SrcInputFileData%GSR,2) + IF (.NOT. ALLOCATED(DstInputFileData%GSR)) THEN + ALLOCATE(DstInputFileData%GSR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%GSR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%GSR = SrcInputFileData%GSR +ENDIF +IF (ALLOCATED(SrcInputFileData%GE)) THEN + i1_l = LBOUND(SrcInputFileData%GE,1) + i1_u = UBOUND(SrcInputFileData%GE,1) + i2_l = LBOUND(SrcInputFileData%GE,2) + i2_u = UBOUND(SrcInputFileData%GE,2) + i3_l = LBOUND(SrcInputFileData%GE,3) + i3_u = UBOUND(SrcInputFileData%GE,3) + IF (.NOT. ALLOCATED(DstInputFileData%GE)) THEN + ALLOCATE(DstInputFileData%GE(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%GE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%GE = SrcInputFileData%GE +ENDIF + DstInputFileData%NumLines = SrcInputFileData%NumLines + DstInputFileData%NumElems = SrcInputFileData%NumElems + DstInputFileData%Eps = SrcInputFileData%Eps + DstInputFileData%Gravity = SrcInputFileData%Gravity + DstInputFileData%WtrDens = SrcInputFileData%WtrDens + DstInputFileData%MaxIter = SrcInputFileData%MaxIter + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%OutFile = SrcInputFileData%OutFile + DstInputFileData%TabDelim = SrcInputFileData%TabDelim + DstInputFileData%OutFmt = SrcInputFileData%OutFmt + DstInputFileData%Tstart = SrcInputFileData%Tstart + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + END SUBROUTINE FEAM_CopyInputFile + + SUBROUTINE FEAM_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(FEAM_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%LineCI)) THEN + DEALLOCATE(InputFileData%LineCI) +ENDIF +IF (ALLOCATED(InputFileData%LineCD)) THEN + DEALLOCATE(InputFileData%LineCD) +ENDIF +IF (ALLOCATED(InputFileData%LEAStiff)) THEN + DEALLOCATE(InputFileData%LEAStiff) +ENDIF +IF (ALLOCATED(InputFileData%LMassDen)) THEN + DEALLOCATE(InputFileData%LMassDen) +ENDIF +IF (ALLOCATED(InputFileData%LDMassDen)) THEN + DEALLOCATE(InputFileData%LDMassDen) +ENDIF +IF (ALLOCATED(InputFileData%BottmStiff)) THEN + DEALLOCATE(InputFileData%BottmStiff) +ENDIF +IF (ALLOCATED(InputFileData%LRadAnch)) THEN + DEALLOCATE(InputFileData%LRadAnch) +ENDIF +IF (ALLOCATED(InputFileData%LAngAnch)) THEN + DEALLOCATE(InputFileData%LAngAnch) +ENDIF +IF (ALLOCATED(InputFileData%LDpthAnch)) THEN + DEALLOCATE(InputFileData%LDpthAnch) +ENDIF +IF (ALLOCATED(InputFileData%LRadFair)) THEN + DEALLOCATE(InputFileData%LRadFair) +ENDIF +IF (ALLOCATED(InputFileData%LAngFair)) THEN + DEALLOCATE(InputFileData%LAngFair) +ENDIF +IF (ALLOCATED(InputFileData%LDrftFair)) THEN + DEALLOCATE(InputFileData%LDrftFair) +ENDIF +IF (ALLOCATED(InputFileData%LUnstrLen)) THEN + DEALLOCATE(InputFileData%LUnstrLen) +ENDIF +IF (ALLOCATED(InputFileData%Tension)) THEN + DEALLOCATE(InputFileData%Tension) +ENDIF +IF (ALLOCATED(InputFileData%GSL)) THEN + DEALLOCATE(InputFileData%GSL) +ENDIF +IF (ALLOCATED(InputFileData%GSR)) THEN + DEALLOCATE(InputFileData%GSR) +ENDIF +IF (ALLOCATED(InputFileData%GE)) THEN + DEALLOCATE(InputFileData%GE) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF + END SUBROUTINE FEAM_DestroyInputFile + + SUBROUTINE FEAM_PackInputFile( 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(FEAM_InputFile), 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 = 'FEAM_PackInputFile' + ! 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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! LineCI allocated yes/no + IF ( ALLOCATED(InData%LineCI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineCI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LineCI) ! LineCI + END IF + Int_BufSz = Int_BufSz + 1 ! LineCD allocated yes/no + IF ( ALLOCATED(InData%LineCD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineCD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LineCD) ! LineCD + END IF + Int_BufSz = Int_BufSz + 1 ! LEAStiff allocated yes/no + IF ( ALLOCATED(InData%LEAStiff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LEAStiff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LEAStiff) ! LEAStiff + END IF + Int_BufSz = Int_BufSz + 1 ! LMassDen allocated yes/no + IF ( ALLOCATED(InData%LMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LMassDen) ! LMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! LDMassDen allocated yes/no + IF ( ALLOCATED(InData%LDMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LDMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LDMassDen) ! LDMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! BottmStiff allocated yes/no + IF ( ALLOCATED(InData%BottmStiff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BottmStiff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BottmStiff) ! BottmStiff + END IF + Int_BufSz = Int_BufSz + 1 ! LRadAnch allocated yes/no + IF ( ALLOCATED(InData%LRadAnch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LRadAnch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LRadAnch) ! LRadAnch + END IF + Int_BufSz = Int_BufSz + 1 ! LAngAnch allocated yes/no + IF ( ALLOCATED(InData%LAngAnch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LAngAnch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LAngAnch) ! LAngAnch + END IF + Int_BufSz = Int_BufSz + 1 ! LDpthAnch allocated yes/no + IF ( ALLOCATED(InData%LDpthAnch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LDpthAnch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LDpthAnch) ! LDpthAnch + END IF + Int_BufSz = Int_BufSz + 1 ! LRadFair allocated yes/no + IF ( ALLOCATED(InData%LRadFair) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LRadFair upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LRadFair) ! LRadFair + END IF + Int_BufSz = Int_BufSz + 1 ! LAngFair allocated yes/no + IF ( ALLOCATED(InData%LAngFair) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LAngFair upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LAngFair) ! LAngFair + END IF + Int_BufSz = Int_BufSz + 1 ! LDrftFair allocated yes/no + IF ( ALLOCATED(InData%LDrftFair) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LDrftFair upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LDrftFair) ! LDrftFair + END IF + Int_BufSz = Int_BufSz + 1 ! LUnstrLen allocated yes/no + IF ( ALLOCATED(InData%LUnstrLen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LUnstrLen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LUnstrLen) ! LUnstrLen + END IF + Int_BufSz = Int_BufSz + 1 ! Tension allocated yes/no + IF ( ALLOCATED(InData%Tension) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Tension upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Tension) ! Tension + END IF + Int_BufSz = Int_BufSz + 1 ! GSL allocated yes/no + IF ( ALLOCATED(InData%GSL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GSL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GSL) ! GSL + END IF + Int_BufSz = Int_BufSz + 1 ! GSR allocated yes/no + IF ( ALLOCATED(InData%GSR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GSR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GSR) ! GSR + END IF + Int_BufSz = Int_BufSz + 1 ! GE allocated yes/no + IF ( ALLOCATED(InData%GE) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GE upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GE) ! GE + END IF + Int_BufSz = Int_BufSz + 1 ! NumLines + Int_BufSz = Int_BufSz + 1 ! NumElems + Re_BufSz = Re_BufSz + 1 ! Eps + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDens + Int_BufSz = Int_BufSz + 1 ! MaxIter + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! OutFile + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Db_BufSz = Db_BufSz + 1 ! Tstart + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LineCI) ) 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%LineCI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineCI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineCI,1), UBOUND(InData%LineCI,1) + ReKiBuf(Re_Xferred) = InData%LineCI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LineCD) ) 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%LineCD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineCD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineCD,1), UBOUND(InData%LineCD,1) + ReKiBuf(Re_Xferred) = InData%LineCD(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LEAStiff) ) 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%LEAStiff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LEAStiff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LEAStiff,1), UBOUND(InData%LEAStiff,1) + ReKiBuf(Re_Xferred) = InData%LEAStiff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LMassDen) ) 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%LMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LMassDen,1), UBOUND(InData%LMassDen,1) + ReKiBuf(Re_Xferred) = InData%LMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LDMassDen) ) 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%LDMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LDMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LDMassDen,1), UBOUND(InData%LDMassDen,1) + ReKiBuf(Re_Xferred) = InData%LDMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BottmStiff) ) 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%BottmStiff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BottmStiff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BottmStiff,1), UBOUND(InData%BottmStiff,1) + ReKiBuf(Re_Xferred) = InData%BottmStiff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LRadAnch) ) 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%LRadAnch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LRadAnch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LRadAnch,1), UBOUND(InData%LRadAnch,1) + ReKiBuf(Re_Xferred) = InData%LRadAnch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LAngAnch) ) 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%LAngAnch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LAngAnch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LAngAnch,1), UBOUND(InData%LAngAnch,1) + ReKiBuf(Re_Xferred) = InData%LAngAnch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LDpthAnch) ) 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%LDpthAnch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LDpthAnch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LDpthAnch,1), UBOUND(InData%LDpthAnch,1) + ReKiBuf(Re_Xferred) = InData%LDpthAnch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LRadFair) ) 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%LRadFair,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LRadFair,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LRadFair,1), UBOUND(InData%LRadFair,1) + ReKiBuf(Re_Xferred) = InData%LRadFair(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LAngFair) ) 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%LAngFair,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LAngFair,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LAngFair,1), UBOUND(InData%LAngFair,1) + ReKiBuf(Re_Xferred) = InData%LAngFair(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LDrftFair) ) 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%LDrftFair,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LDrftFair,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LDrftFair,1), UBOUND(InData%LDrftFair,1) + ReKiBuf(Re_Xferred) = InData%LDrftFair(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LUnstrLen) ) 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%LUnstrLen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LUnstrLen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LUnstrLen,1), UBOUND(InData%LUnstrLen,1) + ReKiBuf(Re_Xferred) = InData%LUnstrLen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Tension) ) 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%Tension,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tension,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Tension,1), UBOUND(InData%Tension,1) + ReKiBuf(Re_Xferred) = InData%Tension(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GSL) ) 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%GSL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GSL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GSL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GSL,3), UBOUND(InData%GSL,3) + DO i2 = LBOUND(InData%GSL,2), UBOUND(InData%GSL,2) + DO i1 = LBOUND(InData%GSL,1), UBOUND(InData%GSL,1) + ReKiBuf(Re_Xferred) = InData%GSL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GSR) ) 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%GSR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GSR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSR,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GSR,2), UBOUND(InData%GSR,2) + DO i1 = LBOUND(InData%GSR,1), UBOUND(InData%GSR,1) + ReKiBuf(Re_Xferred) = InData%GSR(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GE) ) 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%GE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GE,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GE,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GE,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GE,3), UBOUND(InData%GE,3) + DO i2 = LBOUND(InData%GE,2), UBOUND(InData%GE,2) + DO i1 = LBOUND(InData%GE,1), UBOUND(InData%GE,1) + ReKiBuf(Re_Xferred) = InData%GE(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumLines + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumElems + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Eps + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MaxIter + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%Tstart + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE FEAM_PackInputFile + + SUBROUTINE FEAM_UnPackInputFile( 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(FEAM_InputFile), 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 = 'FEAM_UnPackInputFile' + ! 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineCI 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%LineCI)) DEALLOCATE(OutData%LineCI) + ALLOCATE(OutData%LineCI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineCI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineCI,1), UBOUND(OutData%LineCI,1) + OutData%LineCI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineCD 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%LineCD)) DEALLOCATE(OutData%LineCD) + ALLOCATE(OutData%LineCD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineCD,1), UBOUND(OutData%LineCD,1) + OutData%LineCD(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LEAStiff 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%LEAStiff)) DEALLOCATE(OutData%LEAStiff) + ALLOCATE(OutData%LEAStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LEAStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LEAStiff,1), UBOUND(OutData%LEAStiff,1) + OutData%LEAStiff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LMassDen 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%LMassDen)) DEALLOCATE(OutData%LMassDen) + ALLOCATE(OutData%LMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LMassDen,1), UBOUND(OutData%LMassDen,1) + OutData%LMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LDMassDen 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%LDMassDen)) DEALLOCATE(OutData%LDMassDen) + ALLOCATE(OutData%LDMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LDMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LDMassDen,1), UBOUND(OutData%LDMassDen,1) + OutData%LDMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BottmStiff 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%BottmStiff)) DEALLOCATE(OutData%BottmStiff) + ALLOCATE(OutData%BottmStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BottmStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BottmStiff,1), UBOUND(OutData%BottmStiff,1) + OutData%BottmStiff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LRadAnch 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%LRadAnch)) DEALLOCATE(OutData%LRadAnch) + ALLOCATE(OutData%LRadAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LRadAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LRadAnch,1), UBOUND(OutData%LRadAnch,1) + OutData%LRadAnch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LAngAnch 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%LAngAnch)) DEALLOCATE(OutData%LAngAnch) + ALLOCATE(OutData%LAngAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LAngAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LAngAnch,1), UBOUND(OutData%LAngAnch,1) + OutData%LAngAnch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LDpthAnch 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%LDpthAnch)) DEALLOCATE(OutData%LDpthAnch) + ALLOCATE(OutData%LDpthAnch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LDpthAnch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LDpthAnch,1), UBOUND(OutData%LDpthAnch,1) + OutData%LDpthAnch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LRadFair 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%LRadFair)) DEALLOCATE(OutData%LRadFair) + ALLOCATE(OutData%LRadFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LRadFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LRadFair,1), UBOUND(OutData%LRadFair,1) + OutData%LRadFair(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LAngFair 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%LAngFair)) DEALLOCATE(OutData%LAngFair) + ALLOCATE(OutData%LAngFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LAngFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LAngFair,1), UBOUND(OutData%LAngFair,1) + OutData%LAngFair(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LDrftFair 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%LDrftFair)) DEALLOCATE(OutData%LDrftFair) + ALLOCATE(OutData%LDrftFair(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LDrftFair.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LDrftFair,1), UBOUND(OutData%LDrftFair,1) + OutData%LDrftFair(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LUnstrLen 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%LUnstrLen)) DEALLOCATE(OutData%LUnstrLen) + ALLOCATE(OutData%LUnstrLen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LUnstrLen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LUnstrLen,1), UBOUND(OutData%LUnstrLen,1) + OutData%LUnstrLen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Tension 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%Tension)) DEALLOCATE(OutData%Tension) + ALLOCATE(OutData%Tension(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Tension.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Tension,1), UBOUND(OutData%Tension,1) + OutData%Tension(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GSL 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%GSL)) DEALLOCATE(OutData%GSL) + ALLOCATE(OutData%GSL(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%GSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GSL,3), UBOUND(OutData%GSL,3) + DO i2 = LBOUND(OutData%GSL,2), UBOUND(OutData%GSL,2) + DO i1 = LBOUND(OutData%GSL,1), UBOUND(OutData%GSL,1) + OutData%GSL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GSR 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%GSR)) DEALLOCATE(OutData%GSR) + ALLOCATE(OutData%GSR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GSR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GSR,2), UBOUND(OutData%GSR,2) + DO i1 = LBOUND(OutData%GSR,1), UBOUND(OutData%GSR,1) + OutData%GSR(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GE 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%GE)) DEALLOCATE(OutData%GE) + ALLOCATE(OutData%GE(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%GE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GE,3), UBOUND(OutData%GE,3) + DO i2 = LBOUND(OutData%GE,2), UBOUND(OutData%GE,2) + DO i1 = LBOUND(OutData%GE,1), UBOUND(OutData%GE,1) + OutData%GE(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%NumLines = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumElems = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Eps = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MaxIter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%OutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Tstart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE FEAM_UnPackInputFile + + SUBROUTINE FEAM_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%PtfmInit = SrcInitInputData%PtfmInit + DstInitInputData%NStepWave = SrcInitInputData%NStepWave +IF (ALLOCATED(SrcInitInputData%WaveAcc0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveAcc0,1) + i1_u = UBOUND(SrcInitInputData%WaveAcc0,1) + i2_l = LBOUND(SrcInitInputData%WaveAcc0,2) + i2_u = UBOUND(SrcInitInputData%WaveAcc0,2) + i3_l = LBOUND(SrcInitInputData%WaveAcc0,3) + i3_u = UBOUND(SrcInitInputData%WaveAcc0,3) + IF (.NOT. ALLOCATED(DstInitInputData%WaveAcc0)) THEN + ALLOCATE(DstInitInputData%WaveAcc0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveAcc0 = SrcInitInputData%WaveAcc0 +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveVel0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveVel0,1) + i1_u = UBOUND(SrcInitInputData%WaveVel0,1) + i2_l = LBOUND(SrcInitInputData%WaveVel0,2) + i2_u = UBOUND(SrcInitInputData%WaveVel0,2) + i3_l = LBOUND(SrcInitInputData%WaveVel0,3) + i3_u = UBOUND(SrcInitInputData%WaveVel0,3) + IF (.NOT. ALLOCATED(DstInitInputData%WaveVel0)) THEN + ALLOCATE(DstInitInputData%WaveVel0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveVel0 = SrcInitInputData%WaveVel0 +ENDIF + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%WtrDens = SrcInitInputData%WtrDens + END SUBROUTINE FEAM_CopyInitInput + + SUBROUTINE FEAM_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(FEAM_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveAcc0)) THEN + DEALLOCATE(InitInputData%WaveAcc0) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF +IF (ALLOCATED(InitInputData%WaveVel0)) THEN + DEALLOCATE(InitInputData%WaveVel0) +ENDIF + END SUBROUTINE FEAM_DestroyInitInput + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + SIZE(InData%PtfmInit) ! PtfmInit + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! WaveAcc0 allocated yes/no + IF ( ALLOCATED(InData%WaveAcc0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc0) ! WaveAcc0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel0 allocated yes/no + IF ( ALLOCATED(InData%WaveVel0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel0) ! WaveVel0 + END IF + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDens + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%PtfmInit,1), UBOUND(InData%PtfmInit,1) + ReKiBuf(Re_Xferred) = InData%PtfmInit(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveAcc0) ) 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%WaveAcc0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc0,3), UBOUND(InData%WaveAcc0,3) + DO i2 = LBOUND(InData%WaveAcc0,2), UBOUND(InData%WaveAcc0,2) + DO i1 = LBOUND(InData%WaveAcc0,1), UBOUND(InData%WaveAcc0,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel0) ) 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%WaveVel0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel0,3), UBOUND(InData%WaveVel0,3) + DO i2 = LBOUND(InData%WaveVel0,2), UBOUND(InData%WaveVel0,2) + DO i1 = LBOUND(InData%WaveVel0,1), UBOUND(InData%WaveVel0,1) + ReKiBuf(Re_Xferred) = InData%WaveVel0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FEAM_PackInitInput + + SUBROUTINE FEAM_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(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%PtfmInit,1) + i1_u = UBOUND(OutData%PtfmInit,1) + DO i1 = LBOUND(OutData%PtfmInit,1), UBOUND(OutData%PtfmInit,1) + OutData%PtfmInit(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc0 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%WaveAcc0)) DEALLOCATE(OutData%WaveAcc0) + ALLOCATE(OutData%WaveAcc0(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%WaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc0,3), UBOUND(OutData%WaveAcc0,3) + DO i2 = LBOUND(OutData%WaveAcc0,2), UBOUND(OutData%WaveAcc0,2) + DO i1 = LBOUND(OutData%WaveAcc0,1), UBOUND(OutData%WaveAcc0,1) + OutData%WaveAcc0(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel0 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%WaveVel0)) DEALLOCATE(OutData%WaveVel0) + ALLOCATE(OutData%WaveVel0(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%WaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel0,3), UBOUND(OutData%WaveVel0,3) + DO i2 = LBOUND(OutData%WaveVel0,2), UBOUND(OutData%WaveVel0,2) + DO i1 = LBOUND(OutData%WaveVel0,1), UBOUND(OutData%WaveVel0,1) + OutData%WaveVel0(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FEAM_UnPackInitInput + + SUBROUTINE FEAM_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(FEAM_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 = 'FEAM_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%LAnchxi)) THEN + i1_l = LBOUND(SrcInitOutputData%LAnchxi,1) + i1_u = UBOUND(SrcInitOutputData%LAnchxi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LAnchxi)) THEN + ALLOCATE(DstInitOutputData%LAnchxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LAnchxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LAnchxi = SrcInitOutputData%LAnchxi +ENDIF +IF (ALLOCATED(SrcInitOutputData%LAnchyi)) THEN + i1_l = LBOUND(SrcInitOutputData%LAnchyi,1) + i1_u = UBOUND(SrcInitOutputData%LAnchyi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LAnchyi)) THEN + ALLOCATE(DstInitOutputData%LAnchyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LAnchyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LAnchyi = SrcInitOutputData%LAnchyi +ENDIF +IF (ALLOCATED(SrcInitOutputData%LAnchzi)) THEN + i1_l = LBOUND(SrcInitOutputData%LAnchzi,1) + i1_u = UBOUND(SrcInitOutputData%LAnchzi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LAnchzi)) THEN + ALLOCATE(DstInitOutputData%LAnchzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LAnchzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LAnchzi = SrcInitOutputData%LAnchzi +ENDIF +IF (ALLOCATED(SrcInitOutputData%LFairxt)) THEN + i1_l = LBOUND(SrcInitOutputData%LFairxt,1) + i1_u = UBOUND(SrcInitOutputData%LFairxt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LFairxt)) THEN + ALLOCATE(DstInitOutputData%LFairxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LFairxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LFairxt = SrcInitOutputData%LFairxt +ENDIF +IF (ALLOCATED(SrcInitOutputData%LFairyt)) THEN + i1_l = LBOUND(SrcInitOutputData%LFairyt,1) + i1_u = UBOUND(SrcInitOutputData%LFairyt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LFairyt)) THEN + ALLOCATE(DstInitOutputData%LFairyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LFairyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LFairyt = SrcInitOutputData%LFairyt +ENDIF +IF (ALLOCATED(SrcInitOutputData%LFairzt)) THEN + i1_l = LBOUND(SrcInitOutputData%LFairzt,1) + i1_u = UBOUND(SrcInitOutputData%LFairzt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LFairzt)) THEN + ALLOCATE(DstInitOutputData%LFairzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LFairzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LFairzt = SrcInitOutputData%LFairzt +ENDIF + END SUBROUTINE FEAM_CopyInitOutput + + SUBROUTINE FEAM_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(FEAM_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LAnchxi)) THEN + DEALLOCATE(InitOutputData%LAnchxi) +ENDIF +IF (ALLOCATED(InitOutputData%LAnchyi)) THEN + DEALLOCATE(InitOutputData%LAnchyi) +ENDIF +IF (ALLOCATED(InitOutputData%LAnchzi)) THEN + DEALLOCATE(InitOutputData%LAnchzi) +ENDIF +IF (ALLOCATED(InitOutputData%LFairxt)) THEN + DEALLOCATE(InitOutputData%LFairxt) +ENDIF +IF (ALLOCATED(InitOutputData%LFairyt)) THEN + DEALLOCATE(InitOutputData%LFairyt) +ENDIF +IF (ALLOCATED(InitOutputData%LFairzt)) THEN + DEALLOCATE(InitOutputData%LFairzt) +ENDIF + END SUBROUTINE FEAM_DestroyInitOutput + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + 1 ! LAnchxi allocated yes/no + IF ( ALLOCATED(InData%LAnchxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LAnchxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LAnchxi) ! LAnchxi + END IF + Int_BufSz = Int_BufSz + 1 ! LAnchyi allocated yes/no + IF ( ALLOCATED(InData%LAnchyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LAnchyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LAnchyi) ! LAnchyi + END IF + Int_BufSz = Int_BufSz + 1 ! LAnchzi allocated yes/no + IF ( ALLOCATED(InData%LAnchzi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LAnchzi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LAnchzi) ! LAnchzi + END IF + Int_BufSz = Int_BufSz + 1 ! LFairxt allocated yes/no + IF ( ALLOCATED(InData%LFairxt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LFairxt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LFairxt) ! LFairxt + END IF + Int_BufSz = Int_BufSz + 1 ! LFairyt allocated yes/no + IF ( ALLOCATED(InData%LFairyt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LFairyt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LFairyt) ! LFairyt + END IF + Int_BufSz = Int_BufSz + 1 ! LFairzt allocated yes/no + IF ( ALLOCATED(InData%LFairzt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LFairzt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LFairzt) ! LFairzt + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 + IF ( .NOT. ALLOCATED(InData%LAnchxi) ) 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%LAnchxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LAnchxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LAnchxi,1), UBOUND(InData%LAnchxi,1) + ReKiBuf(Re_Xferred) = InData%LAnchxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LAnchyi) ) 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%LAnchyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LAnchyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LAnchyi,1), UBOUND(InData%LAnchyi,1) + ReKiBuf(Re_Xferred) = InData%LAnchyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LAnchzi) ) 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%LAnchzi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LAnchzi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LAnchzi,1), UBOUND(InData%LAnchzi,1) + ReKiBuf(Re_Xferred) = InData%LAnchzi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LFairxt) ) 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%LFairxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LFairxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LFairxt,1), UBOUND(InData%LFairxt,1) + ReKiBuf(Re_Xferred) = InData%LFairxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LFairyt) ) 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%LFairyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LFairyt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LFairyt,1), UBOUND(InData%LFairyt,1) + ReKiBuf(Re_Xferred) = InData%LFairyt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LFairzt) ) 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%LFairzt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LFairzt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LFairzt,1), UBOUND(InData%LFairzt,1) + ReKiBuf(Re_Xferred) = InData%LFairzt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FEAM_PackInitOutput + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LAnchxi 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%LAnchxi)) DEALLOCATE(OutData%LAnchxi) + ALLOCATE(OutData%LAnchxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LAnchxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LAnchxi,1), UBOUND(OutData%LAnchxi,1) + OutData%LAnchxi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LAnchyi 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%LAnchyi)) DEALLOCATE(OutData%LAnchyi) + ALLOCATE(OutData%LAnchyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LAnchyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LAnchyi,1), UBOUND(OutData%LAnchyi,1) + OutData%LAnchyi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LAnchzi 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%LAnchzi)) DEALLOCATE(OutData%LAnchzi) + ALLOCATE(OutData%LAnchzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LAnchzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LAnchzi,1), UBOUND(OutData%LAnchzi,1) + OutData%LAnchzi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LFairxt 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%LFairxt)) DEALLOCATE(OutData%LFairxt) + ALLOCATE(OutData%LFairxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LFairxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LFairxt,1), UBOUND(OutData%LFairxt,1) + OutData%LFairxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LFairyt 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%LFairyt)) DEALLOCATE(OutData%LFairyt) + ALLOCATE(OutData%LFairyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LFairyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LFairyt,1), UBOUND(OutData%LFairyt,1) + OutData%LFairyt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LFairzt 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%LFairzt)) DEALLOCATE(OutData%LFairzt) + ALLOCATE(OutData%LFairzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LFairzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LFairzt,1), UBOUND(OutData%LFairzt,1) + OutData%LFairzt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FEAM_UnPackInitOutput + + SUBROUTINE FEAM_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(FEAM_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 = 'FEAM_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%GLU)) THEN + i1_l = LBOUND(SrcContStateData%GLU,1) + i1_u = UBOUND(SrcContStateData%GLU,1) + i2_l = LBOUND(SrcContStateData%GLU,2) + i2_u = UBOUND(SrcContStateData%GLU,2) + IF (.NOT. ALLOCATED(DstContStateData%GLU)) THEN + ALLOCATE(DstContStateData%GLU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%GLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%GLU = SrcContStateData%GLU +ENDIF +IF (ALLOCATED(SrcContStateData%GLDU)) THEN + i1_l = LBOUND(SrcContStateData%GLDU,1) + i1_u = UBOUND(SrcContStateData%GLDU,1) + i2_l = LBOUND(SrcContStateData%GLDU,2) + i2_u = UBOUND(SrcContStateData%GLDU,2) + IF (.NOT. ALLOCATED(DstContStateData%GLDU)) THEN + ALLOCATE(DstContStateData%GLDU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%GLDU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%GLDU = SrcContStateData%GLDU +ENDIF + END SUBROUTINE FEAM_CopyContState + + SUBROUTINE FEAM_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(FEAM_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%GLU)) THEN + DEALLOCATE(ContStateData%GLU) +ENDIF +IF (ALLOCATED(ContStateData%GLDU)) THEN + DEALLOCATE(ContStateData%GLDU) +ENDIF + END SUBROUTINE FEAM_DestroyContState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + Int_BufSz = Int_BufSz + 1 ! GLU allocated yes/no + IF ( ALLOCATED(InData%GLU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GLU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLU) ! GLU + END IF + Int_BufSz = Int_BufSz + 1 ! GLDU allocated yes/no + IF ( ALLOCATED(InData%GLDU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GLDU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLDU) ! GLDU + 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%GLU) ) 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%GLU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GLU,2), UBOUND(InData%GLU,2) + DO i1 = LBOUND(InData%GLU,1), UBOUND(InData%GLU,1) + ReKiBuf(Re_Xferred) = InData%GLU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GLDU) ) 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%GLDU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLDU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLDU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLDU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GLDU,2), UBOUND(InData%GLDU,2) + DO i1 = LBOUND(InData%GLDU,1), UBOUND(InData%GLDU,1) + ReKiBuf(Re_Xferred) = InData%GLDU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FEAM_PackContState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLU 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%GLU)) DEALLOCATE(OutData%GLU) + ALLOCATE(OutData%GLU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GLU,2), UBOUND(OutData%GLU,2) + DO i1 = LBOUND(OutData%GLU,1), UBOUND(OutData%GLU,1) + OutData%GLU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLDU 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%GLDU)) DEALLOCATE(OutData%GLDU) + ALLOCATE(OutData%GLDU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GLDU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GLDU,2), UBOUND(OutData%GLDU,2) + DO i1 = LBOUND(OutData%GLDU,1), UBOUND(OutData%GLDU,1) + OutData%GLDU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FEAM_UnPackContState + + SUBROUTINE FEAM_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(FEAM_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 = 'FEAM_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE FEAM_CopyDiscState + + SUBROUTINE FEAM_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(FEAM_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FEAM_DestroyDiscState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 FEAM_PackDiscState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 FEAM_UnPackDiscState + + SUBROUTINE FEAM_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(FEAM_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%TSN = SrcConstrStateData%TSN + DstConstrStateData%TZER = SrcConstrStateData%TZER + END SUBROUTINE FEAM_CopyConstrState + + SUBROUTINE FEAM_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(FEAM_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FEAM_DestroyConstrState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + SIZE(InData%TSN) ! TSN + Re_BufSz = Re_BufSz + SIZE(InData%TZER) ! TZER + 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%TSN,1), UBOUND(InData%TSN,1) + ReKiBuf(Re_Xferred) = InData%TSN(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%TZER,1), UBOUND(InData%TZER,1) + ReKiBuf(Re_Xferred) = InData%TZER(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FEAM_PackConstrState + + SUBROUTINE FEAM_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(FEAM_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_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 + i1_l = LBOUND(OutData%TSN,1) + i1_u = UBOUND(OutData%TSN,1) + DO i1 = LBOUND(OutData%TSN,1), UBOUND(OutData%TSN,1) + OutData%TSN(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%TZER,1) + i1_u = UBOUND(OutData%TZER,1) + DO i1 = LBOUND(OutData%TZER,1), UBOUND(OutData%TZER,1) + OutData%TZER(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FEAM_UnPackConstrState + + SUBROUTINE FEAM_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(FEAM_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) :: 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 = 'FEAM_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%GLU0)) THEN + i1_l = LBOUND(SrcOtherStateData%GLU0,1) + i1_u = UBOUND(SrcOtherStateData%GLU0,1) + i2_l = LBOUND(SrcOtherStateData%GLU0,2) + i2_u = UBOUND(SrcOtherStateData%GLU0,2) + IF (.NOT. ALLOCATED(DstOtherStateData%GLU0)) THEN + ALLOCATE(DstOtherStateData%GLU0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%GLU0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%GLU0 = SrcOtherStateData%GLU0 +ENDIF +IF (ALLOCATED(SrcOtherStateData%GLDDU)) THEN + i1_l = LBOUND(SrcOtherStateData%GLDDU,1) + i1_u = UBOUND(SrcOtherStateData%GLDDU,1) + i2_l = LBOUND(SrcOtherStateData%GLDDU,2) + i2_u = UBOUND(SrcOtherStateData%GLDDU,2) + IF (.NOT. ALLOCATED(DstOtherStateData%GLDDU)) THEN + ALLOCATE(DstOtherStateData%GLDDU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%GLDDU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%GLDDU = SrcOtherStateData%GLDDU +ENDIF + DstOtherStateData%BottomTouch = SrcOtherStateData%BottomTouch +IF (ALLOCATED(SrcOtherStateData%GFORC0)) THEN + i1_l = LBOUND(SrcOtherStateData%GFORC0,1) + i1_u = UBOUND(SrcOtherStateData%GFORC0,1) + i2_l = LBOUND(SrcOtherStateData%GFORC0,2) + i2_u = UBOUND(SrcOtherStateData%GFORC0,2) + i3_l = LBOUND(SrcOtherStateData%GFORC0,3) + i3_u = UBOUND(SrcOtherStateData%GFORC0,3) + IF (.NOT. ALLOCATED(DstOtherStateData%GFORC0)) THEN + ALLOCATE(DstOtherStateData%GFORC0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%GFORC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%GFORC0 = SrcOtherStateData%GFORC0 +ENDIF +IF (ALLOCATED(SrcOtherStateData%GMASS0)) THEN + i1_l = LBOUND(SrcOtherStateData%GMASS0,1) + i1_u = UBOUND(SrcOtherStateData%GMASS0,1) + i2_l = LBOUND(SrcOtherStateData%GMASS0,2) + i2_u = UBOUND(SrcOtherStateData%GMASS0,2) + i3_l = LBOUND(SrcOtherStateData%GMASS0,3) + i3_u = UBOUND(SrcOtherStateData%GMASS0,3) + i4_l = LBOUND(SrcOtherStateData%GMASS0,4) + i4_u = UBOUND(SrcOtherStateData%GMASS0,4) + IF (.NOT. ALLOCATED(DstOtherStateData%GMASS0)) THEN + ALLOCATE(DstOtherStateData%GMASS0(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 DstOtherStateData%GMASS0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%GMASS0 = SrcOtherStateData%GMASS0 +ENDIF +IF (ALLOCATED(SrcOtherStateData%FAST_FPA)) THEN + i1_l = LBOUND(SrcOtherStateData%FAST_FPA,1) + i1_u = UBOUND(SrcOtherStateData%FAST_FPA,1) + i2_l = LBOUND(SrcOtherStateData%FAST_FPA,2) + i2_u = UBOUND(SrcOtherStateData%FAST_FPA,2) + IF (.NOT. ALLOCATED(DstOtherStateData%FAST_FPA)) THEN + ALLOCATE(DstOtherStateData%FAST_FPA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%FAST_FPA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%FAST_FPA = SrcOtherStateData%FAST_FPA +ENDIF +IF (ALLOCATED(SrcOtherStateData%FAST_RP)) THEN + i1_l = LBOUND(SrcOtherStateData%FAST_RP,1) + i1_u = UBOUND(SrcOtherStateData%FAST_RP,1) + i2_l = LBOUND(SrcOtherStateData%FAST_RP,2) + i2_u = UBOUND(SrcOtherStateData%FAST_RP,2) + IF (.NOT. ALLOCATED(DstOtherStateData%FAST_RP)) THEN + ALLOCATE(DstOtherStateData%FAST_RP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%FAST_RP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%FAST_RP = SrcOtherStateData%FAST_RP +ENDIF + DstOtherStateData%INCR = SrcOtherStateData%INCR + DstOtherStateData%RSDF = SrcOtherStateData%RSDF + DstOtherStateData%FORC0 = SrcOtherStateData%FORC0 + DstOtherStateData%EMAS0 = SrcOtherStateData%EMAS0 + END SUBROUTINE FEAM_CopyOtherState + + SUBROUTINE FEAM_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(FEAM_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%GLU0)) THEN + DEALLOCATE(OtherStateData%GLU0) +ENDIF +IF (ALLOCATED(OtherStateData%GLDDU)) THEN + DEALLOCATE(OtherStateData%GLDDU) +ENDIF +IF (ALLOCATED(OtherStateData%GFORC0)) THEN + DEALLOCATE(OtherStateData%GFORC0) +ENDIF +IF (ALLOCATED(OtherStateData%GMASS0)) THEN + DEALLOCATE(OtherStateData%GMASS0) +ENDIF +IF (ALLOCATED(OtherStateData%FAST_FPA)) THEN + DEALLOCATE(OtherStateData%FAST_FPA) +ENDIF +IF (ALLOCATED(OtherStateData%FAST_RP)) THEN + DEALLOCATE(OtherStateData%FAST_RP) +ENDIF + END SUBROUTINE FEAM_DestroyOtherState + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + Int_BufSz = Int_BufSz + 1 ! GLU0 allocated yes/no + IF ( ALLOCATED(InData%GLU0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GLU0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLU0) ! GLU0 + END IF + Int_BufSz = Int_BufSz + 1 ! GLDDU allocated yes/no + IF ( ALLOCATED(InData%GLDDU) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GLDDU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLDDU) ! GLDDU + END IF + Int_BufSz = Int_BufSz + 1 ! BottomTouch + Int_BufSz = Int_BufSz + 1 ! GFORC0 allocated yes/no + IF ( ALLOCATED(InData%GFORC0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GFORC0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GFORC0) ! GFORC0 + END IF + Int_BufSz = Int_BufSz + 1 ! GMASS0 allocated yes/no + IF ( ALLOCATED(InData%GMASS0) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! GMASS0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GMASS0) ! GMASS0 + END IF + Int_BufSz = Int_BufSz + 1 ! FAST_FPA allocated yes/no + IF ( ALLOCATED(InData%FAST_FPA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FAST_FPA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FAST_FPA) ! FAST_FPA + END IF + Int_BufSz = Int_BufSz + 1 ! FAST_RP allocated yes/no + IF ( ALLOCATED(InData%FAST_RP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FAST_RP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FAST_RP) ! FAST_RP + END IF + Int_BufSz = Int_BufSz + 1 ! INCR + Re_BufSz = Re_BufSz + SIZE(InData%RSDF) ! RSDF + Re_BufSz = Re_BufSz + SIZE(InData%FORC0) ! FORC0 + Re_BufSz = Re_BufSz + SIZE(InData%EMAS0) ! EMAS0 + 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%GLU0) ) 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%GLU0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLU0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLU0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLU0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GLU0,2), UBOUND(InData%GLU0,2) + DO i1 = LBOUND(InData%GLU0,1), UBOUND(InData%GLU0,1) + ReKiBuf(Re_Xferred) = InData%GLU0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GLDDU) ) 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%GLDDU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLDDU,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLDDU,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLDDU,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GLDDU,2), UBOUND(InData%GLDDU,2) + DO i1 = LBOUND(InData%GLDDU,1), UBOUND(InData%GLDDU,1) + ReKiBuf(Re_Xferred) = InData%GLDDU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%BottomTouch, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%GFORC0) ) 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%GFORC0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GFORC0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GFORC0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GFORC0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GFORC0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GFORC0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GFORC0,3), UBOUND(InData%GFORC0,3) + DO i2 = LBOUND(InData%GFORC0,2), UBOUND(InData%GFORC0,2) + DO i1 = LBOUND(InData%GFORC0,1), UBOUND(InData%GFORC0,1) + ReKiBuf(Re_Xferred) = InData%GFORC0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GMASS0) ) 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%GMASS0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GMASS0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GMASS0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GMASS0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GMASS0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GMASS0,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GMASS0,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GMASS0,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%GMASS0,4), UBOUND(InData%GMASS0,4) + DO i3 = LBOUND(InData%GMASS0,3), UBOUND(InData%GMASS0,3) + DO i2 = LBOUND(InData%GMASS0,2), UBOUND(InData%GMASS0,2) + DO i1 = LBOUND(InData%GMASS0,1), UBOUND(InData%GMASS0,1) + ReKiBuf(Re_Xferred) = InData%GMASS0(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FAST_FPA) ) 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%FAST_FPA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_FPA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FAST_FPA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_FPA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FAST_FPA,2), UBOUND(InData%FAST_FPA,2) + DO i1 = LBOUND(InData%FAST_FPA,1), UBOUND(InData%FAST_FPA,1) + ReKiBuf(Re_Xferred) = InData%FAST_FPA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FAST_RP) ) 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%FAST_RP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_RP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FAST_RP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_RP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FAST_RP,2), UBOUND(InData%FAST_RP,2) + DO i1 = LBOUND(InData%FAST_RP,1), UBOUND(InData%FAST_RP,1) + ReKiBuf(Re_Xferred) = InData%FAST_RP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%INCR + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RSDF,1), UBOUND(InData%RSDF,1) + ReKiBuf(Re_Xferred) = InData%RSDF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FORC0,1), UBOUND(InData%FORC0,1) + ReKiBuf(Re_Xferred) = InData%FORC0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%EMAS0,2), UBOUND(InData%EMAS0,2) + DO i1 = LBOUND(InData%EMAS0,1), UBOUND(InData%EMAS0,1) + ReKiBuf(Re_Xferred) = InData%EMAS0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE FEAM_PackOtherState + + SUBROUTINE FEAM_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(FEAM_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) :: 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 = 'FEAM_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLU0 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%GLU0)) DEALLOCATE(OutData%GLU0) + ALLOCATE(OutData%GLU0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GLU0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GLU0,2), UBOUND(OutData%GLU0,2) + DO i1 = LBOUND(OutData%GLU0,1), UBOUND(OutData%GLU0,1) + OutData%GLU0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLDDU 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%GLDDU)) DEALLOCATE(OutData%GLDDU) + ALLOCATE(OutData%GLDDU(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GLDDU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GLDDU,2), UBOUND(OutData%GLDDU,2) + DO i1 = LBOUND(OutData%GLDDU,1), UBOUND(OutData%GLDDU,1) + OutData%GLDDU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%BottomTouch = TRANSFER(IntKiBuf(Int_Xferred), OutData%BottomTouch) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GFORC0 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%GFORC0)) DEALLOCATE(OutData%GFORC0) + ALLOCATE(OutData%GFORC0(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%GFORC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GFORC0,3), UBOUND(OutData%GFORC0,3) + DO i2 = LBOUND(OutData%GFORC0,2), UBOUND(OutData%GFORC0,2) + DO i1 = LBOUND(OutData%GFORC0,1), UBOUND(OutData%GFORC0,1) + OutData%GFORC0(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GMASS0 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%GMASS0)) DEALLOCATE(OutData%GMASS0) + ALLOCATE(OutData%GMASS0(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%GMASS0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%GMASS0,4), UBOUND(OutData%GMASS0,4) + DO i3 = LBOUND(OutData%GMASS0,3), UBOUND(OutData%GMASS0,3) + DO i2 = LBOUND(OutData%GMASS0,2), UBOUND(OutData%GMASS0,2) + DO i1 = LBOUND(OutData%GMASS0,1), UBOUND(OutData%GMASS0,1) + OutData%GMASS0(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FAST_FPA 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%FAST_FPA)) DEALLOCATE(OutData%FAST_FPA) + ALLOCATE(OutData%FAST_FPA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FAST_FPA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FAST_FPA,2), UBOUND(OutData%FAST_FPA,2) + DO i1 = LBOUND(OutData%FAST_FPA,1), UBOUND(OutData%FAST_FPA,1) + OutData%FAST_FPA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FAST_RP 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%FAST_RP)) DEALLOCATE(OutData%FAST_RP) + ALLOCATE(OutData%FAST_RP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FAST_RP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FAST_RP,2), UBOUND(OutData%FAST_RP,2) + DO i1 = LBOUND(OutData%FAST_RP,1), UBOUND(OutData%FAST_RP,1) + OutData%FAST_RP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%INCR = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RSDF,1) + i1_u = UBOUND(OutData%RSDF,1) + DO i1 = LBOUND(OutData%RSDF,1), UBOUND(OutData%RSDF,1) + OutData%RSDF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FORC0,1) + i1_u = UBOUND(OutData%FORC0,1) + DO i1 = LBOUND(OutData%FORC0,1), UBOUND(OutData%FORC0,1) + OutData%FORC0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%EMAS0,1) + i1_u = UBOUND(OutData%EMAS0,1) + i2_l = LBOUND(OutData%EMAS0,2) + i2_u = UBOUND(OutData%EMAS0,2) + DO i2 = LBOUND(OutData%EMAS0,2), UBOUND(OutData%EMAS0,2) + DO i1 = LBOUND(OutData%EMAS0,1), UBOUND(OutData%EMAS0,1) + OutData%EMAS0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE FEAM_UnPackOtherState + + SUBROUTINE FEAM_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%GLF)) THEN + i1_l = LBOUND(SrcMiscData%GLF,1) + i1_u = UBOUND(SrcMiscData%GLF,1) + i2_l = LBOUND(SrcMiscData%GLF,2) + i2_u = UBOUND(SrcMiscData%GLF,2) + IF (.NOT. ALLOCATED(DstMiscData%GLF)) THEN + ALLOCATE(DstMiscData%GLF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%GLF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%GLF = SrcMiscData%GLF +ENDIF +IF (ALLOCATED(SrcMiscData%GLK)) THEN + i1_l = LBOUND(SrcMiscData%GLK,1) + i1_u = UBOUND(SrcMiscData%GLK,1) + i2_l = LBOUND(SrcMiscData%GLK,2) + i2_u = UBOUND(SrcMiscData%GLK,2) + i3_l = LBOUND(SrcMiscData%GLK,3) + i3_u = UBOUND(SrcMiscData%GLK,3) + IF (.NOT. ALLOCATED(DstMiscData%GLK)) THEN + ALLOCATE(DstMiscData%GLK(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%GLK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%GLK = SrcMiscData%GLK +ENDIF + DstMiscData%EMASS = SrcMiscData%EMASS + DstMiscData%ESTIF = SrcMiscData%ESTIF +IF (ALLOCATED(SrcMiscData%FAST_FP)) THEN + i1_l = LBOUND(SrcMiscData%FAST_FP,1) + i1_u = UBOUND(SrcMiscData%FAST_FP,1) + i2_l = LBOUND(SrcMiscData%FAST_FP,2) + i2_u = UBOUND(SrcMiscData%FAST_FP,2) + IF (.NOT. ALLOCATED(DstMiscData%FAST_FP)) THEN + ALLOCATE(DstMiscData%FAST_FP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FAST_FP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FAST_FP = SrcMiscData%FAST_FP +ENDIF + DstMiscData%FORCE = SrcMiscData%FORCE + DstMiscData%FP = SrcMiscData%FP + DstMiscData%U = SrcMiscData%U + DstMiscData%U0 = SrcMiscData%U0 + DstMiscData%DU = SrcMiscData%DU + DstMiscData%DDU = SrcMiscData%DDU + DstMiscData%R = SrcMiscData%R + DstMiscData%RP = SrcMiscData%RP + DstMiscData%RHSR = SrcMiscData%RHSR + DstMiscData%SLIN = SrcMiscData%SLIN + DstMiscData%STIFR = SrcMiscData%STIFR +IF (ALLOCATED(SrcMiscData%FAIR_ANG)) THEN + i1_l = LBOUND(SrcMiscData%FAIR_ANG,1) + i1_u = UBOUND(SrcMiscData%FAIR_ANG,1) + i2_l = LBOUND(SrcMiscData%FAIR_ANG,2) + i2_u = UBOUND(SrcMiscData%FAIR_ANG,2) + IF (.NOT. ALLOCATED(DstMiscData%FAIR_ANG)) THEN + ALLOCATE(DstMiscData%FAIR_ANG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FAIR_ANG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FAIR_ANG = SrcMiscData%FAIR_ANG +ENDIF +IF (ALLOCATED(SrcMiscData%FAIR_T)) THEN + i1_l = LBOUND(SrcMiscData%FAIR_T,1) + i1_u = UBOUND(SrcMiscData%FAIR_T,1) + IF (.NOT. ALLOCATED(DstMiscData%FAIR_T)) THEN + ALLOCATE(DstMiscData%FAIR_T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FAIR_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FAIR_T = SrcMiscData%FAIR_T +ENDIF +IF (ALLOCATED(SrcMiscData%ANCH_ANG)) THEN + i1_l = LBOUND(SrcMiscData%ANCH_ANG,1) + i1_u = UBOUND(SrcMiscData%ANCH_ANG,1) + i2_l = LBOUND(SrcMiscData%ANCH_ANG,2) + i2_u = UBOUND(SrcMiscData%ANCH_ANG,2) + IF (.NOT. ALLOCATED(DstMiscData%ANCH_ANG)) THEN + ALLOCATE(DstMiscData%ANCH_ANG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ANCH_ANG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ANCH_ANG = SrcMiscData%ANCH_ANG +ENDIF +IF (ALLOCATED(SrcMiscData%ANCH_T)) THEN + i1_l = LBOUND(SrcMiscData%ANCH_T,1) + i1_u = UBOUND(SrcMiscData%ANCH_T,1) + IF (.NOT. ALLOCATED(DstMiscData%ANCH_T)) THEN + ALLOCATE(DstMiscData%ANCH_T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ANCH_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ANCH_T = SrcMiscData%ANCH_T +ENDIF +IF (ALLOCATED(SrcMiscData%Line_Coordinate)) THEN + i1_l = LBOUND(SrcMiscData%Line_Coordinate,1) + i1_u = UBOUND(SrcMiscData%Line_Coordinate,1) + i2_l = LBOUND(SrcMiscData%Line_Coordinate,2) + i2_u = UBOUND(SrcMiscData%Line_Coordinate,2) + i3_l = LBOUND(SrcMiscData%Line_Coordinate,3) + i3_u = UBOUND(SrcMiscData%Line_Coordinate,3) + IF (.NOT. ALLOCATED(DstMiscData%Line_Coordinate)) THEN + ALLOCATE(DstMiscData%Line_Coordinate(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line_Coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Line_Coordinate = SrcMiscData%Line_Coordinate +ENDIF +IF (ALLOCATED(SrcMiscData%Line_Tangent)) THEN + i1_l = LBOUND(SrcMiscData%Line_Tangent,1) + i1_u = UBOUND(SrcMiscData%Line_Tangent,1) + i2_l = LBOUND(SrcMiscData%Line_Tangent,2) + i2_u = UBOUND(SrcMiscData%Line_Tangent,2) + i3_l = LBOUND(SrcMiscData%Line_Tangent,3) + i3_u = UBOUND(SrcMiscData%Line_Tangent,3) + IF (.NOT. ALLOCATED(DstMiscData%Line_Tangent)) THEN + ALLOCATE(DstMiscData%Line_Tangent(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line_Tangent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Line_Tangent = SrcMiscData%Line_Tangent +ENDIF +IF (ALLOCATED(SrcMiscData%F_Lines)) THEN + i1_l = LBOUND(SrcMiscData%F_Lines,1) + i1_u = UBOUND(SrcMiscData%F_Lines,1) + i2_l = LBOUND(SrcMiscData%F_Lines,2) + i2_u = UBOUND(SrcMiscData%F_Lines,2) + IF (.NOT. ALLOCATED(DstMiscData%F_Lines)) THEN + ALLOCATE(DstMiscData%F_Lines(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_Lines.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%F_Lines = SrcMiscData%F_Lines +ENDIF + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + END SUBROUTINE FEAM_CopyMisc + + SUBROUTINE FEAM_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(FEAM_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%GLF)) THEN + DEALLOCATE(MiscData%GLF) +ENDIF +IF (ALLOCATED(MiscData%GLK)) THEN + DEALLOCATE(MiscData%GLK) +ENDIF +IF (ALLOCATED(MiscData%FAST_FP)) THEN + DEALLOCATE(MiscData%FAST_FP) +ENDIF +IF (ALLOCATED(MiscData%FAIR_ANG)) THEN + DEALLOCATE(MiscData%FAIR_ANG) +ENDIF +IF (ALLOCATED(MiscData%FAIR_T)) THEN + DEALLOCATE(MiscData%FAIR_T) +ENDIF +IF (ALLOCATED(MiscData%ANCH_ANG)) THEN + DEALLOCATE(MiscData%ANCH_ANG) +ENDIF +IF (ALLOCATED(MiscData%ANCH_T)) THEN + DEALLOCATE(MiscData%ANCH_T) +ENDIF +IF (ALLOCATED(MiscData%Line_Coordinate)) THEN + DEALLOCATE(MiscData%Line_Coordinate) +ENDIF +IF (ALLOCATED(MiscData%Line_Tangent)) THEN + DEALLOCATE(MiscData%Line_Tangent) +ENDIF +IF (ALLOCATED(MiscData%F_Lines)) THEN + DEALLOCATE(MiscData%F_Lines) +ENDIF + END SUBROUTINE FEAM_DestroyMisc + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 ! GLF allocated yes/no + IF ( ALLOCATED(InData%GLF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GLF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLF) ! GLF + END IF + Int_BufSz = Int_BufSz + 1 ! GLK allocated yes/no + IF ( ALLOCATED(InData%GLK) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GLK upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLK) ! GLK + END IF + Re_BufSz = Re_BufSz + SIZE(InData%EMASS) ! EMASS + Re_BufSz = Re_BufSz + SIZE(InData%ESTIF) ! ESTIF + Int_BufSz = Int_BufSz + 1 ! FAST_FP allocated yes/no + IF ( ALLOCATED(InData%FAST_FP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FAST_FP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FAST_FP) ! FAST_FP + END IF + Re_BufSz = Re_BufSz + SIZE(InData%FORCE) ! FORCE + Re_BufSz = Re_BufSz + SIZE(InData%FP) ! FP + Re_BufSz = Re_BufSz + SIZE(InData%U) ! U + Re_BufSz = Re_BufSz + SIZE(InData%U0) ! U0 + Re_BufSz = Re_BufSz + SIZE(InData%DU) ! DU + Re_BufSz = Re_BufSz + SIZE(InData%DDU) ! DDU + Re_BufSz = Re_BufSz + SIZE(InData%R) ! R + Re_BufSz = Re_BufSz + SIZE(InData%RP) ! RP + Re_BufSz = Re_BufSz + SIZE(InData%RHSR) ! RHSR + Re_BufSz = Re_BufSz + SIZE(InData%SLIN) ! SLIN + Re_BufSz = Re_BufSz + SIZE(InData%STIFR) ! STIFR + Int_BufSz = Int_BufSz + 1 ! FAIR_ANG allocated yes/no + IF ( ALLOCATED(InData%FAIR_ANG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FAIR_ANG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FAIR_ANG) ! FAIR_ANG + END IF + Int_BufSz = Int_BufSz + 1 ! FAIR_T allocated yes/no + IF ( ALLOCATED(InData%FAIR_T) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FAIR_T upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FAIR_T) ! FAIR_T + END IF + Int_BufSz = Int_BufSz + 1 ! ANCH_ANG allocated yes/no + IF ( ALLOCATED(InData%ANCH_ANG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ANCH_ANG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ANCH_ANG) ! ANCH_ANG + END IF + Int_BufSz = Int_BufSz + 1 ! ANCH_T allocated yes/no + IF ( ALLOCATED(InData%ANCH_T) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ANCH_T upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ANCH_T) ! ANCH_T + END IF + Int_BufSz = Int_BufSz + 1 ! Line_Coordinate allocated yes/no + IF ( ALLOCATED(InData%Line_Coordinate) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Line_Coordinate upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Line_Coordinate) ! Line_Coordinate + END IF + Int_BufSz = Int_BufSz + 1 ! Line_Tangent allocated yes/no + IF ( ALLOCATED(InData%Line_Tangent) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Line_Tangent upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Line_Tangent) ! Line_Tangent + END IF + Int_BufSz = Int_BufSz + 1 ! F_Lines allocated yes/no + IF ( ALLOCATED(InData%F_Lines) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_Lines upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_Lines) ! F_Lines + END IF + Int_BufSz = Int_BufSz + 1 ! LastIndWave + 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%GLF) ) 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%GLF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GLF,2), UBOUND(InData%GLF,2) + DO i1 = LBOUND(InData%GLF,1), UBOUND(InData%GLF,1) + ReKiBuf(Re_Xferred) = InData%GLF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GLK) ) 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%GLK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLK,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLK,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLK,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GLK,3), UBOUND(InData%GLK,3) + DO i2 = LBOUND(InData%GLK,2), UBOUND(InData%GLK,2) + DO i1 = LBOUND(InData%GLK,1), UBOUND(InData%GLK,1) + ReKiBuf(Re_Xferred) = InData%GLK(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i2 = LBOUND(InData%EMASS,2), UBOUND(InData%EMASS,2) + DO i1 = LBOUND(InData%EMASS,1), UBOUND(InData%EMASS,1) + ReKiBuf(Re_Xferred) = InData%EMASS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%ESTIF,2), UBOUND(InData%ESTIF,2) + DO i1 = LBOUND(InData%ESTIF,1), UBOUND(InData%ESTIF,1) + ReKiBuf(Re_Xferred) = InData%ESTIF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%FAST_FP) ) 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%FAST_FP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_FP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FAST_FP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAST_FP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FAST_FP,2), UBOUND(InData%FAST_FP,2) + DO i1 = LBOUND(InData%FAST_FP,1), UBOUND(InData%FAST_FP,1) + ReKiBuf(Re_Xferred) = InData%FAST_FP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%FORCE,1), UBOUND(InData%FORCE,1) + ReKiBuf(Re_Xferred) = InData%FORCE(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%FP,1), UBOUND(InData%FP,1) + ReKiBuf(Re_Xferred) = InData%FP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%U,2), UBOUND(InData%U,2) + DO i1 = LBOUND(InData%U,1), UBOUND(InData%U,1) + ReKiBuf(Re_Xferred) = InData%U(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%U0,2), UBOUND(InData%U0,2) + DO i1 = LBOUND(InData%U0,1), UBOUND(InData%U0,1) + ReKiBuf(Re_Xferred) = InData%U0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%DU,2), UBOUND(InData%DU,2) + DO i1 = LBOUND(InData%DU,1), UBOUND(InData%DU,1) + ReKiBuf(Re_Xferred) = InData%DU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%DDU,2), UBOUND(InData%DDU,2) + DO i1 = LBOUND(InData%DDU,1), UBOUND(InData%DDU,1) + ReKiBuf(Re_Xferred) = InData%DDU(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%R,1), UBOUND(InData%R,1) + ReKiBuf(Re_Xferred) = InData%R(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%RP,1), UBOUND(InData%RP,1) + ReKiBuf(Re_Xferred) = InData%RP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%RHSR,1), UBOUND(InData%RHSR,1) + ReKiBuf(Re_Xferred) = InData%RHSR(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SLIN,1), UBOUND(InData%SLIN,1) + ReKiBuf(Re_Xferred) = InData%SLIN(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%STIFR,2), UBOUND(InData%STIFR,2) + DO i1 = LBOUND(InData%STIFR,1), UBOUND(InData%STIFR,1) + ReKiBuf(Re_Xferred) = InData%STIFR(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%FAIR_ANG) ) 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%FAIR_ANG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAIR_ANG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FAIR_ANG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAIR_ANG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FAIR_ANG,2), UBOUND(InData%FAIR_ANG,2) + DO i1 = LBOUND(InData%FAIR_ANG,1), UBOUND(InData%FAIR_ANG,1) + ReKiBuf(Re_Xferred) = InData%FAIR_ANG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FAIR_T) ) 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%FAIR_T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FAIR_T,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FAIR_T,1), UBOUND(InData%FAIR_T,1) + ReKiBuf(Re_Xferred) = InData%FAIR_T(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ANCH_ANG) ) 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%ANCH_ANG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANCH_ANG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ANCH_ANG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANCH_ANG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ANCH_ANG,2), UBOUND(InData%ANCH_ANG,2) + DO i1 = LBOUND(InData%ANCH_ANG,1), UBOUND(InData%ANCH_ANG,1) + ReKiBuf(Re_Xferred) = InData%ANCH_ANG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ANCH_T) ) 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%ANCH_T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ANCH_T,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ANCH_T,1), UBOUND(InData%ANCH_T,1) + ReKiBuf(Re_Xferred) = InData%ANCH_T(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Line_Coordinate) ) 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%Line_Coordinate,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Coordinate,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Line_Coordinate,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Coordinate,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Line_Coordinate,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Coordinate,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Line_Coordinate,3), UBOUND(InData%Line_Coordinate,3) + DO i2 = LBOUND(InData%Line_Coordinate,2), UBOUND(InData%Line_Coordinate,2) + DO i1 = LBOUND(InData%Line_Coordinate,1), UBOUND(InData%Line_Coordinate,1) + ReKiBuf(Re_Xferred) = InData%Line_Coordinate(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Line_Tangent) ) 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%Line_Tangent,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Tangent,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Line_Tangent,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Tangent,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Line_Tangent,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line_Tangent,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Line_Tangent,3), UBOUND(InData%Line_Tangent,3) + DO i2 = LBOUND(InData%Line_Tangent,2), UBOUND(InData%Line_Tangent,2) + DO i1 = LBOUND(InData%Line_Tangent,1), UBOUND(InData%Line_Tangent,1) + ReKiBuf(Re_Xferred) = InData%Line_Tangent(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_Lines) ) 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%F_Lines,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Lines,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_Lines,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Lines,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_Lines,2), UBOUND(InData%F_Lines,2) + DO i1 = LBOUND(InData%F_Lines,1), UBOUND(InData%F_Lines,1) + ReKiBuf(Re_Xferred) = InData%F_Lines(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%LastIndWave + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FEAM_PackMisc + + SUBROUTINE FEAM_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(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_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 ! GLF 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%GLF)) DEALLOCATE(OutData%GLF) + ALLOCATE(OutData%GLF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GLF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GLF,2), UBOUND(OutData%GLF,2) + DO i1 = LBOUND(OutData%GLF,1), UBOUND(OutData%GLF,1) + OutData%GLF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLK 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%GLK)) DEALLOCATE(OutData%GLK) + ALLOCATE(OutData%GLK(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%GLK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GLK,3), UBOUND(OutData%GLK,3) + DO i2 = LBOUND(OutData%GLK,2), UBOUND(OutData%GLK,2) + DO i1 = LBOUND(OutData%GLK,1), UBOUND(OutData%GLK,1) + OutData%GLK(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%EMASS,1) + i1_u = UBOUND(OutData%EMASS,1) + i2_l = LBOUND(OutData%EMASS,2) + i2_u = UBOUND(OutData%EMASS,2) + DO i2 = LBOUND(OutData%EMASS,2), UBOUND(OutData%EMASS,2) + DO i1 = LBOUND(OutData%EMASS,1), UBOUND(OutData%EMASS,1) + OutData%EMASS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%ESTIF,1) + i1_u = UBOUND(OutData%ESTIF,1) + i2_l = LBOUND(OutData%ESTIF,2) + i2_u = UBOUND(OutData%ESTIF,2) + DO i2 = LBOUND(OutData%ESTIF,2), UBOUND(OutData%ESTIF,2) + DO i1 = LBOUND(OutData%ESTIF,1), UBOUND(OutData%ESTIF,1) + OutData%ESTIF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FAST_FP 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%FAST_FP)) DEALLOCATE(OutData%FAST_FP) + ALLOCATE(OutData%FAST_FP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FAST_FP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FAST_FP,2), UBOUND(OutData%FAST_FP,2) + DO i1 = LBOUND(OutData%FAST_FP,1), UBOUND(OutData%FAST_FP,1) + OutData%FAST_FP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%FORCE,1) + i1_u = UBOUND(OutData%FORCE,1) + DO i1 = LBOUND(OutData%FORCE,1), UBOUND(OutData%FORCE,1) + OutData%FORCE(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%FP,1) + i1_u = UBOUND(OutData%FP,1) + DO i1 = LBOUND(OutData%FP,1), UBOUND(OutData%FP,1) + OutData%FP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%U,1) + i1_u = UBOUND(OutData%U,1) + i2_l = LBOUND(OutData%U,2) + i2_u = UBOUND(OutData%U,2) + DO i2 = LBOUND(OutData%U,2), UBOUND(OutData%U,2) + DO i1 = LBOUND(OutData%U,1), UBOUND(OutData%U,1) + OutData%U(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%U0,1) + i1_u = UBOUND(OutData%U0,1) + i2_l = LBOUND(OutData%U0,2) + i2_u = UBOUND(OutData%U0,2) + DO i2 = LBOUND(OutData%U0,2), UBOUND(OutData%U0,2) + DO i1 = LBOUND(OutData%U0,1), UBOUND(OutData%U0,1) + OutData%U0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%DU,1) + i1_u = UBOUND(OutData%DU,1) + i2_l = LBOUND(OutData%DU,2) + i2_u = UBOUND(OutData%DU,2) + DO i2 = LBOUND(OutData%DU,2), UBOUND(OutData%DU,2) + DO i1 = LBOUND(OutData%DU,1), UBOUND(OutData%DU,1) + OutData%DU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%DDU,1) + i1_u = UBOUND(OutData%DDU,1) + i2_l = LBOUND(OutData%DDU,2) + i2_u = UBOUND(OutData%DDU,2) + DO i2 = LBOUND(OutData%DDU,2), UBOUND(OutData%DDU,2) + DO i1 = LBOUND(OutData%DDU,1), UBOUND(OutData%DDU,1) + OutData%DDU(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%R,1) + i1_u = UBOUND(OutData%R,1) + DO i1 = LBOUND(OutData%R,1), UBOUND(OutData%R,1) + OutData%R(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%RP,1) + i1_u = UBOUND(OutData%RP,1) + DO i1 = LBOUND(OutData%RP,1), UBOUND(OutData%RP,1) + OutData%RP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%RHSR,1) + i1_u = UBOUND(OutData%RHSR,1) + DO i1 = LBOUND(OutData%RHSR,1), UBOUND(OutData%RHSR,1) + OutData%RHSR(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SLIN,1) + i1_u = UBOUND(OutData%SLIN,1) + DO i1 = LBOUND(OutData%SLIN,1), UBOUND(OutData%SLIN,1) + OutData%SLIN(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%STIFR,1) + i1_u = UBOUND(OutData%STIFR,1) + i2_l = LBOUND(OutData%STIFR,2) + i2_u = UBOUND(OutData%STIFR,2) + DO i2 = LBOUND(OutData%STIFR,2), UBOUND(OutData%STIFR,2) + DO i1 = LBOUND(OutData%STIFR,1), UBOUND(OutData%STIFR,1) + OutData%STIFR(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FAIR_ANG 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%FAIR_ANG)) DEALLOCATE(OutData%FAIR_ANG) + ALLOCATE(OutData%FAIR_ANG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FAIR_ANG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FAIR_ANG,2), UBOUND(OutData%FAIR_ANG,2) + DO i1 = LBOUND(OutData%FAIR_ANG,1), UBOUND(OutData%FAIR_ANG,1) + OutData%FAIR_ANG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FAIR_T 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%FAIR_T)) DEALLOCATE(OutData%FAIR_T) + ALLOCATE(OutData%FAIR_T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FAIR_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FAIR_T,1), UBOUND(OutData%FAIR_T,1) + OutData%FAIR_T(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ANCH_ANG 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%ANCH_ANG)) DEALLOCATE(OutData%ANCH_ANG) + ALLOCATE(OutData%ANCH_ANG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ANCH_ANG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ANCH_ANG,2), UBOUND(OutData%ANCH_ANG,2) + DO i1 = LBOUND(OutData%ANCH_ANG,1), UBOUND(OutData%ANCH_ANG,1) + OutData%ANCH_ANG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ANCH_T 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%ANCH_T)) DEALLOCATE(OutData%ANCH_T) + ALLOCATE(OutData%ANCH_T(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ANCH_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ANCH_T,1), UBOUND(OutData%ANCH_T,1) + OutData%ANCH_T(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line_Coordinate 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%Line_Coordinate)) DEALLOCATE(OutData%Line_Coordinate) + ALLOCATE(OutData%Line_Coordinate(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%Line_Coordinate.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Line_Coordinate,3), UBOUND(OutData%Line_Coordinate,3) + DO i2 = LBOUND(OutData%Line_Coordinate,2), UBOUND(OutData%Line_Coordinate,2) + DO i1 = LBOUND(OutData%Line_Coordinate,1), UBOUND(OutData%Line_Coordinate,1) + OutData%Line_Coordinate(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line_Tangent 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%Line_Tangent)) DEALLOCATE(OutData%Line_Tangent) + ALLOCATE(OutData%Line_Tangent(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%Line_Tangent.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Line_Tangent,3), UBOUND(OutData%Line_Tangent,3) + DO i2 = LBOUND(OutData%Line_Tangent,2), UBOUND(OutData%Line_Tangent,2) + DO i1 = LBOUND(OutData%Line_Tangent,1), UBOUND(OutData%Line_Tangent,1) + OutData%Line_Tangent(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_Lines 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%F_Lines)) DEALLOCATE(OutData%F_Lines) + ALLOCATE(OutData%F_Lines(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_Lines.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_Lines,2), UBOUND(OutData%F_Lines,2) + DO i1 = LBOUND(OutData%F_Lines,1), UBOUND(OutData%F_Lines,1) + OutData%F_Lines(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FEAM_UnPackMisc + + SUBROUTINE FEAM_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_ParameterType), INTENT(IN) :: SrcParamData + TYPE(FEAM_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 = 'FEAM_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%GRAV = SrcParamData%GRAV + DstParamData%Eps = SrcParamData%Eps + DstParamData%Gravity = SrcParamData%Gravity + DstParamData%WtrDens = SrcParamData%WtrDens + DstParamData%MaxIter = SrcParamData%MaxIter + DstParamData%NHBD = SrcParamData%NHBD + DstParamData%NDIM = SrcParamData%NDIM +IF (ALLOCATED(SrcParamData%NEQ)) THEN + i1_l = LBOUND(SrcParamData%NEQ,1) + i1_u = UBOUND(SrcParamData%NEQ,1) + IF (.NOT. ALLOCATED(DstParamData%NEQ)) THEN + ALLOCATE(DstParamData%NEQ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NEQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NEQ = SrcParamData%NEQ +ENDIF + DstParamData%NBAND = SrcParamData%NBAND + DstParamData%NumLines = SrcParamData%NumLines + DstParamData%NumElems = SrcParamData%NumElems + DstParamData%NumNodes = SrcParamData%NumNodes +IF (ALLOCATED(SrcParamData%GSL)) THEN + i1_l = LBOUND(SrcParamData%GSL,1) + i1_u = UBOUND(SrcParamData%GSL,1) + i2_l = LBOUND(SrcParamData%GSL,2) + i2_u = UBOUND(SrcParamData%GSL,2) + i3_l = LBOUND(SrcParamData%GSL,3) + i3_u = UBOUND(SrcParamData%GSL,3) + IF (.NOT. ALLOCATED(DstParamData%GSL)) THEN + ALLOCATE(DstParamData%GSL(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%GSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%GSL = SrcParamData%GSL +ENDIF +IF (ALLOCATED(SrcParamData%GP)) THEN + i1_l = LBOUND(SrcParamData%GP,1) + i1_u = UBOUND(SrcParamData%GP,1) + i2_l = LBOUND(SrcParamData%GP,2) + i2_u = UBOUND(SrcParamData%GP,2) + IF (.NOT. ALLOCATED(DstParamData%GP)) THEN + ALLOCATE(DstParamData%GP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%GP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%GP = SrcParamData%GP +ENDIF +IF (ALLOCATED(SrcParamData%Elength)) THEN + i1_l = LBOUND(SrcParamData%Elength,1) + i1_u = UBOUND(SrcParamData%Elength,1) + IF (.NOT. ALLOCATED(DstParamData%Elength)) THEN + ALLOCATE(DstParamData%Elength(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elength.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Elength = SrcParamData%Elength +ENDIF +IF (ALLOCATED(SrcParamData%BottmElev)) THEN + i1_l = LBOUND(SrcParamData%BottmElev,1) + i1_u = UBOUND(SrcParamData%BottmElev,1) + IF (.NOT. ALLOCATED(DstParamData%BottmElev)) THEN + ALLOCATE(DstParamData%BottmElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BottmElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BottmElev = SrcParamData%BottmElev +ENDIF +IF (ALLOCATED(SrcParamData%BottmStiff)) THEN + i1_l = LBOUND(SrcParamData%BottmStiff,1) + i1_u = UBOUND(SrcParamData%BottmStiff,1) + IF (.NOT. ALLOCATED(DstParamData%BottmStiff)) THEN + ALLOCATE(DstParamData%BottmStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BottmStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BottmStiff = SrcParamData%BottmStiff +ENDIF +IF (ALLOCATED(SrcParamData%LMassDen)) THEN + i1_l = LBOUND(SrcParamData%LMassDen,1) + i1_u = UBOUND(SrcParamData%LMassDen,1) + IF (.NOT. ALLOCATED(DstParamData%LMassDen)) THEN + ALLOCATE(DstParamData%LMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%LMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%LMassDen = SrcParamData%LMassDen +ENDIF +IF (ALLOCATED(SrcParamData%LDMassDen)) THEN + i1_l = LBOUND(SrcParamData%LDMassDen,1) + i1_u = UBOUND(SrcParamData%LDMassDen,1) + IF (.NOT. ALLOCATED(DstParamData%LDMassDen)) THEN + ALLOCATE(DstParamData%LDMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%LDMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%LDMassDen = SrcParamData%LDMassDen +ENDIF +IF (ALLOCATED(SrcParamData%LEAStiff)) THEN + i1_l = LBOUND(SrcParamData%LEAStiff,1) + i1_u = UBOUND(SrcParamData%LEAStiff,1) + IF (.NOT. ALLOCATED(DstParamData%LEAStiff)) THEN + ALLOCATE(DstParamData%LEAStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%LEAStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%LEAStiff = SrcParamData%LEAStiff +ENDIF +IF (ALLOCATED(SrcParamData%LineCI)) THEN + i1_l = LBOUND(SrcParamData%LineCI,1) + i1_u = UBOUND(SrcParamData%LineCI,1) + IF (.NOT. ALLOCATED(DstParamData%LineCI)) THEN + ALLOCATE(DstParamData%LineCI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%LineCI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%LineCI = SrcParamData%LineCI +ENDIF +IF (ALLOCATED(SrcParamData%LineCD)) THEN + i1_l = LBOUND(SrcParamData%LineCD,1) + i1_u = UBOUND(SrcParamData%LineCD,1) + IF (.NOT. ALLOCATED(DstParamData%LineCD)) THEN + ALLOCATE(DstParamData%LineCD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%LineCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%LineCD = SrcParamData%LineCD +ENDIF +IF (ALLOCATED(SrcParamData%Bvp)) THEN + i1_l = LBOUND(SrcParamData%Bvp,1) + i1_u = UBOUND(SrcParamData%Bvp,1) + i2_l = LBOUND(SrcParamData%Bvp,2) + i2_u = UBOUND(SrcParamData%Bvp,2) + IF (.NOT. ALLOCATED(DstParamData%Bvp)) THEN + ALLOCATE(DstParamData%Bvp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Bvp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Bvp = SrcParamData%Bvp +ENDIF +IF (ALLOCATED(SrcParamData%WaveAcc0)) THEN + i1_l = LBOUND(SrcParamData%WaveAcc0,1) + i1_u = UBOUND(SrcParamData%WaveAcc0,1) + i2_l = LBOUND(SrcParamData%WaveAcc0,2) + i2_u = UBOUND(SrcParamData%WaveAcc0,2) + i3_l = LBOUND(SrcParamData%WaveAcc0,3) + i3_u = UBOUND(SrcParamData%WaveAcc0,3) + IF (.NOT. ALLOCATED(DstParamData%WaveAcc0)) THEN + ALLOCATE(DstParamData%WaveAcc0(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%WaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveAcc0 = SrcParamData%WaveAcc0 +ENDIF +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF +IF (ALLOCATED(SrcParamData%WaveVel0)) THEN + i1_l = LBOUND(SrcParamData%WaveVel0,1) + i1_u = UBOUND(SrcParamData%WaveVel0,1) + i2_l = LBOUND(SrcParamData%WaveVel0,2) + i2_u = UBOUND(SrcParamData%WaveVel0,2) + i3_l = LBOUND(SrcParamData%WaveVel0,3) + i3_u = UBOUND(SrcParamData%WaveVel0,3) + IF (.NOT. ALLOCATED(DstParamData%WaveVel0)) THEN + ALLOCATE(DstParamData%WaveVel0(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%WaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveVel0 = SrcParamData%WaveVel0 +ENDIF + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%SHAP = SrcParamData%SHAP + DstParamData%SHAPS = SrcParamData%SHAPS + DstParamData%GAUSSW = SrcParamData%GAUSSW + DstParamData%NGAUSS = SrcParamData%NGAUSS + DstParamData%SHAPT = SrcParamData%SHAPT + DstParamData%SHAPTS = SrcParamData%SHAPTS + DstParamData%NTRAP = SrcParamData%NTRAP + DstParamData%SBEND = SrcParamData%SBEND + DstParamData%STEN = SrcParamData%STEN + DstParamData%RMASS = SrcParamData%RMASS + DstParamData%RADDM = SrcParamData%RADDM + DstParamData%PMPN = SrcParamData%PMPN + DstParamData%AM = SrcParamData%AM + DstParamData%PM = SrcParamData%PM + DstParamData%IDOF = SrcParamData%IDOF + DstParamData%JDOF = SrcParamData%JDOF + DstParamData%PPA = SrcParamData%PPA + DstParamData%PtfmRefzt = SrcParamData%PtfmRefzt + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%Delim = SrcParamData%Delim +IF (ALLOCATED(SrcParamData%GLUZR)) THEN + i1_l = LBOUND(SrcParamData%GLUZR,1) + i1_u = UBOUND(SrcParamData%GLUZR,1) + i2_l = LBOUND(SrcParamData%GLUZR,2) + i2_u = UBOUND(SrcParamData%GLUZR,2) + i3_l = LBOUND(SrcParamData%GLUZR,3) + i3_u = UBOUND(SrcParamData%GLUZR,3) + IF (.NOT. ALLOCATED(DstParamData%GLUZR)) THEN + ALLOCATE(DstParamData%GLUZR(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%GLUZR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%GLUZR = SrcParamData%GLUZR +ENDIF +IF (ALLOCATED(SrcParamData%GTZER)) THEN + i1_l = LBOUND(SrcParamData%GTZER,1) + i1_u = UBOUND(SrcParamData%GTZER,1) + i2_l = LBOUND(SrcParamData%GTZER,2) + i2_u = UBOUND(SrcParamData%GTZER,2) + IF (.NOT. ALLOCATED(DstParamData%GTZER)) THEN + ALLOCATE(DstParamData%GTZER(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%GTZER.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%GTZER = SrcParamData%GTZER +ENDIF + END SUBROUTINE FEAM_CopyParam + + SUBROUTINE FEAM_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(FEAM_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%NEQ)) THEN + DEALLOCATE(ParamData%NEQ) +ENDIF +IF (ALLOCATED(ParamData%GSL)) THEN + DEALLOCATE(ParamData%GSL) +ENDIF +IF (ALLOCATED(ParamData%GP)) THEN + DEALLOCATE(ParamData%GP) +ENDIF +IF (ALLOCATED(ParamData%Elength)) THEN + DEALLOCATE(ParamData%Elength) +ENDIF +IF (ALLOCATED(ParamData%BottmElev)) THEN + DEALLOCATE(ParamData%BottmElev) +ENDIF +IF (ALLOCATED(ParamData%BottmStiff)) THEN + DEALLOCATE(ParamData%BottmStiff) +ENDIF +IF (ALLOCATED(ParamData%LMassDen)) THEN + DEALLOCATE(ParamData%LMassDen) +ENDIF +IF (ALLOCATED(ParamData%LDMassDen)) THEN + DEALLOCATE(ParamData%LDMassDen) +ENDIF +IF (ALLOCATED(ParamData%LEAStiff)) THEN + DEALLOCATE(ParamData%LEAStiff) +ENDIF +IF (ALLOCATED(ParamData%LineCI)) THEN + DEALLOCATE(ParamData%LineCI) +ENDIF +IF (ALLOCATED(ParamData%LineCD)) THEN + DEALLOCATE(ParamData%LineCD) +ENDIF +IF (ALLOCATED(ParamData%Bvp)) THEN + DEALLOCATE(ParamData%Bvp) +ENDIF +IF (ALLOCATED(ParamData%WaveAcc0)) THEN + DEALLOCATE(ParamData%WaveAcc0) +ENDIF +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF +IF (ALLOCATED(ParamData%WaveVel0)) THEN + DEALLOCATE(ParamData%WaveVel0) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%GLUZR)) THEN + DEALLOCATE(ParamData%GLUZR) +ENDIF +IF (ALLOCATED(ParamData%GTZER)) THEN + DEALLOCATE(ParamData%GTZER) +ENDIF + END SUBROUTINE FEAM_DestroyParam + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + Db_BufSz = Db_BufSz + 1 ! DT + Re_BufSz = Re_BufSz + SIZE(InData%GRAV) ! GRAV + Re_BufSz = Re_BufSz + 1 ! Eps + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDens + Int_BufSz = Int_BufSz + 1 ! MaxIter + Int_BufSz = Int_BufSz + 1 ! NHBD + Int_BufSz = Int_BufSz + 1 ! NDIM + Int_BufSz = Int_BufSz + 1 ! NEQ allocated yes/no + IF ( ALLOCATED(InData%NEQ) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NEQ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NEQ) ! NEQ + END IF + Int_BufSz = Int_BufSz + 1 ! NBAND + Int_BufSz = Int_BufSz + 1 ! NumLines + Int_BufSz = Int_BufSz + 1 ! NumElems + Int_BufSz = Int_BufSz + 1 ! NumNodes + Int_BufSz = Int_BufSz + 1 ! GSL allocated yes/no + IF ( ALLOCATED(InData%GSL) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GSL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GSL) ! GSL + END IF + Int_BufSz = Int_BufSz + 1 ! GP allocated yes/no + IF ( ALLOCATED(InData%GP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GP) ! GP + END IF + Int_BufSz = Int_BufSz + 1 ! Elength allocated yes/no + IF ( ALLOCATED(InData%Elength) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Elength upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Elength) ! Elength + END IF + Int_BufSz = Int_BufSz + 1 ! BottmElev allocated yes/no + IF ( ALLOCATED(InData%BottmElev) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BottmElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BottmElev) ! BottmElev + END IF + Int_BufSz = Int_BufSz + 1 ! BottmStiff allocated yes/no + IF ( ALLOCATED(InData%BottmStiff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BottmStiff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BottmStiff) ! BottmStiff + END IF + Int_BufSz = Int_BufSz + 1 ! LMassDen allocated yes/no + IF ( ALLOCATED(InData%LMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LMassDen) ! LMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! LDMassDen allocated yes/no + IF ( ALLOCATED(InData%LDMassDen) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LDMassDen upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LDMassDen) ! LDMassDen + END IF + Int_BufSz = Int_BufSz + 1 ! LEAStiff allocated yes/no + IF ( ALLOCATED(InData%LEAStiff) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LEAStiff upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LEAStiff) ! LEAStiff + END IF + Int_BufSz = Int_BufSz + 1 ! LineCI allocated yes/no + IF ( ALLOCATED(InData%LineCI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineCI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LineCI) ! LineCI + END IF + Int_BufSz = Int_BufSz + 1 ! LineCD allocated yes/no + IF ( ALLOCATED(InData%LineCD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineCD upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LineCD) ! LineCD + END IF + Int_BufSz = Int_BufSz + 1 ! Bvp allocated yes/no + IF ( ALLOCATED(InData%Bvp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Bvp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Bvp) ! Bvp + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc0 allocated yes/no + IF ( ALLOCATED(InData%WaveAcc0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc0) ! WaveAcc0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel0 allocated yes/no + IF ( ALLOCATED(InData%WaveVel0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel0) ! WaveVel0 + END IF + Int_BufSz = Int_BufSz + 1 ! NStepWave + Re_BufSz = Re_BufSz + SIZE(InData%SHAP) ! SHAP + Re_BufSz = Re_BufSz + SIZE(InData%SHAPS) ! SHAPS + Re_BufSz = Re_BufSz + SIZE(InData%GAUSSW) ! GAUSSW + Int_BufSz = Int_BufSz + 1 ! NGAUSS + Re_BufSz = Re_BufSz + SIZE(InData%SHAPT) ! SHAPT + Re_BufSz = Re_BufSz + SIZE(InData%SHAPTS) ! SHAPTS + Int_BufSz = Int_BufSz + 1 ! NTRAP + Re_BufSz = Re_BufSz + SIZE(InData%SBEND) ! SBEND + Re_BufSz = Re_BufSz + SIZE(InData%STEN) ! STEN + Re_BufSz = Re_BufSz + SIZE(InData%RMASS) ! RMASS + Re_BufSz = Re_BufSz + SIZE(InData%RADDM) ! RADDM + Re_BufSz = Re_BufSz + SIZE(InData%PMPN) ! PMPN + Re_BufSz = Re_BufSz + SIZE(InData%AM) ! AM + Re_BufSz = Re_BufSz + SIZE(InData%PM) ! PM + Int_BufSz = Int_BufSz + SIZE(InData%IDOF) ! IDOF + Int_BufSz = Int_BufSz + SIZE(InData%JDOF) ! JDOF + Re_BufSz = Re_BufSz + SIZE(InData%PPA) ! PPA + Re_BufSz = Re_BufSz + 1 ! PtfmRefzt + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! GLUZR allocated yes/no + IF ( ALLOCATED(InData%GLUZR) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! GLUZR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GLUZR) ! GLUZR + END IF + Int_BufSz = Int_BufSz + 1 ! GTZER allocated yes/no + IF ( ALLOCATED(InData%GTZER) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! GTZER upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GTZER) ! GTZER + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%GRAV,1), UBOUND(InData%GRAV,1) + ReKiBuf(Re_Xferred) = InData%GRAV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%Eps + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MaxIter + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NHBD + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NDIM + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NEQ) ) 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%NEQ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NEQ,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NEQ,1), UBOUND(InData%NEQ,1) + IntKiBuf(Int_Xferred) = InData%NEQ(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NBAND + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumLines + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumElems + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%GSL) ) 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%GSL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GSL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GSL,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GSL,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GSL,3), UBOUND(InData%GSL,3) + DO i2 = LBOUND(InData%GSL,2), UBOUND(InData%GSL,2) + DO i1 = LBOUND(InData%GSL,1), UBOUND(InData%GSL,1) + ReKiBuf(Re_Xferred) = InData%GSL(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GP) ) 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%GP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GP,2), UBOUND(InData%GP,2) + DO i1 = LBOUND(InData%GP,1), UBOUND(InData%GP,1) + ReKiBuf(Re_Xferred) = InData%GP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Elength) ) 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%Elength,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elength,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Elength,1), UBOUND(InData%Elength,1) + ReKiBuf(Re_Xferred) = InData%Elength(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BottmElev) ) 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%BottmElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BottmElev,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BottmElev,1), UBOUND(InData%BottmElev,1) + ReKiBuf(Re_Xferred) = InData%BottmElev(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BottmStiff) ) 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%BottmStiff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BottmStiff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BottmStiff,1), UBOUND(InData%BottmStiff,1) + ReKiBuf(Re_Xferred) = InData%BottmStiff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LMassDen) ) 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%LMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LMassDen,1), UBOUND(InData%LMassDen,1) + ReKiBuf(Re_Xferred) = InData%LMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LDMassDen) ) 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%LDMassDen,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LDMassDen,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LDMassDen,1), UBOUND(InData%LDMassDen,1) + ReKiBuf(Re_Xferred) = InData%LDMassDen(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LEAStiff) ) 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%LEAStiff,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LEAStiff,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LEAStiff,1), UBOUND(InData%LEAStiff,1) + ReKiBuf(Re_Xferred) = InData%LEAStiff(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LineCI) ) 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%LineCI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineCI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineCI,1), UBOUND(InData%LineCI,1) + ReKiBuf(Re_Xferred) = InData%LineCI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LineCD) ) 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%LineCD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineCD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineCD,1), UBOUND(InData%LineCD,1) + ReKiBuf(Re_Xferred) = InData%LineCD(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Bvp) ) 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%Bvp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Bvp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Bvp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Bvp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Bvp,2), UBOUND(InData%Bvp,2) + DO i1 = LBOUND(InData%Bvp,1), UBOUND(InData%Bvp,1) + ReKiBuf(Re_Xferred) = InData%Bvp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc0) ) 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%WaveAcc0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc0,3), UBOUND(InData%WaveAcc0,3) + DO i2 = LBOUND(InData%WaveAcc0,2), UBOUND(InData%WaveAcc0,2) + DO i1 = LBOUND(InData%WaveAcc0,1), UBOUND(InData%WaveAcc0,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel0) ) 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%WaveVel0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel0,3), UBOUND(InData%WaveVel0,3) + DO i2 = LBOUND(InData%WaveVel0,2), UBOUND(InData%WaveVel0,2) + DO i1 = LBOUND(InData%WaveVel0,1), UBOUND(InData%WaveVel0,1) + ReKiBuf(Re_Xferred) = InData%WaveVel0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%SHAP,2), UBOUND(InData%SHAP,2) + DO i1 = LBOUND(InData%SHAP,1), UBOUND(InData%SHAP,1) + ReKiBuf(Re_Xferred) = InData%SHAP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%SHAPS,2), UBOUND(InData%SHAPS,2) + DO i1 = LBOUND(InData%SHAPS,1), UBOUND(InData%SHAPS,1) + ReKiBuf(Re_Xferred) = InData%SHAPS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%GAUSSW,1), UBOUND(InData%GAUSSW,1) + ReKiBuf(Re_Xferred) = InData%GAUSSW(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NGAUSS + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%SHAPT,2), UBOUND(InData%SHAPT,2) + DO i1 = LBOUND(InData%SHAPT,1), UBOUND(InData%SHAPT,1) + ReKiBuf(Re_Xferred) = InData%SHAPT(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%SHAPTS,2), UBOUND(InData%SHAPTS,2) + DO i1 = LBOUND(InData%SHAPTS,1), UBOUND(InData%SHAPTS,1) + ReKiBuf(Re_Xferred) = InData%SHAPTS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IntKiBuf(Int_Xferred) = InData%NTRAP + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%SBEND,2), UBOUND(InData%SBEND,2) + DO i1 = LBOUND(InData%SBEND,1), UBOUND(InData%SBEND,1) + ReKiBuf(Re_Xferred) = InData%SBEND(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i3 = LBOUND(InData%STEN,3), UBOUND(InData%STEN,3) + DO i2 = LBOUND(InData%STEN,2), UBOUND(InData%STEN,2) + DO i1 = LBOUND(InData%STEN,1), UBOUND(InData%STEN,1) + ReKiBuf(Re_Xferred) = InData%STEN(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + DO i2 = LBOUND(InData%RMASS,2), UBOUND(InData%RMASS,2) + DO i1 = LBOUND(InData%RMASS,1), UBOUND(InData%RMASS,1) + ReKiBuf(Re_Xferred) = InData%RMASS(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i4 = LBOUND(InData%RADDM,4), UBOUND(InData%RADDM,4) + DO i3 = LBOUND(InData%RADDM,3), UBOUND(InData%RADDM,3) + DO i2 = LBOUND(InData%RADDM,2), UBOUND(InData%RADDM,2) + DO i1 = LBOUND(InData%RADDM,1), UBOUND(InData%RADDM,1) + ReKiBuf(Re_Xferred) = InData%RADDM(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + DO i2 = LBOUND(InData%PMPN,2), UBOUND(InData%PMPN,2) + DO i1 = LBOUND(InData%PMPN,1), UBOUND(InData%PMPN,1) + ReKiBuf(Re_Xferred) = InData%PMPN(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%AM,1), UBOUND(InData%AM,1) + ReKiBuf(Re_Xferred) = InData%AM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%PM,1), UBOUND(InData%PM,1) + ReKiBuf(Re_Xferred) = InData%PM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%IDOF,2), UBOUND(InData%IDOF,2) + DO i1 = LBOUND(InData%IDOF,1), UBOUND(InData%IDOF,1) + IntKiBuf(Int_Xferred) = InData%IDOF(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%JDOF,1), UBOUND(InData%JDOF,1) + IntKiBuf(Int_Xferred) = InData%JDOF(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i3 = LBOUND(InData%PPA,3), UBOUND(InData%PPA,3) + DO i2 = LBOUND(InData%PPA,2), UBOUND(InData%PPA,2) + DO i1 = LBOUND(InData%PPA,1), UBOUND(InData%PPA,1) + ReKiBuf(Re_Xferred) = InData%PPA(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + ReKiBuf(Re_Xferred) = InData%PtfmRefzt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%GLUZR) ) 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%GLUZR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLUZR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLUZR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLUZR,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GLUZR,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GLUZR,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%GLUZR,3), UBOUND(InData%GLUZR,3) + DO i2 = LBOUND(InData%GLUZR,2), UBOUND(InData%GLUZR,2) + DO i1 = LBOUND(InData%GLUZR,1), UBOUND(InData%GLUZR,1) + ReKiBuf(Re_Xferred) = InData%GLUZR(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GTZER) ) 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%GTZER,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GTZER,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%GTZER,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GTZER,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%GTZER,2), UBOUND(InData%GTZER,2) + DO i1 = LBOUND(InData%GTZER,1), UBOUND(InData%GTZER,1) + ReKiBuf(Re_Xferred) = InData%GTZER(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FEAM_PackParam + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%GRAV,1) + i1_u = UBOUND(OutData%GRAV,1) + DO i1 = LBOUND(OutData%GRAV,1), UBOUND(OutData%GRAV,1) + OutData%GRAV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%Eps = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MaxIter = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NHBD = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NDIM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NEQ 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%NEQ)) DEALLOCATE(OutData%NEQ) + ALLOCATE(OutData%NEQ(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NEQ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NEQ,1), UBOUND(OutData%NEQ,1) + OutData%NEQ(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NBAND = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumLines = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumElems = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GSL 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%GSL)) DEALLOCATE(OutData%GSL) + ALLOCATE(OutData%GSL(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%GSL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GSL,3), UBOUND(OutData%GSL,3) + DO i2 = LBOUND(OutData%GSL,2), UBOUND(OutData%GSL,2) + DO i1 = LBOUND(OutData%GSL,1), UBOUND(OutData%GSL,1) + OutData%GSL(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GP 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%GP)) DEALLOCATE(OutData%GP) + ALLOCATE(OutData%GP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GP,2), UBOUND(OutData%GP,2) + DO i1 = LBOUND(OutData%GP,1), UBOUND(OutData%GP,1) + OutData%GP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elength 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%Elength)) DEALLOCATE(OutData%Elength) + ALLOCATE(OutData%Elength(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elength.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Elength,1), UBOUND(OutData%Elength,1) + OutData%Elength(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BottmElev 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%BottmElev)) DEALLOCATE(OutData%BottmElev) + ALLOCATE(OutData%BottmElev(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BottmElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BottmElev,1), UBOUND(OutData%BottmElev,1) + OutData%BottmElev(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BottmStiff 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%BottmStiff)) DEALLOCATE(OutData%BottmStiff) + ALLOCATE(OutData%BottmStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BottmStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BottmStiff,1), UBOUND(OutData%BottmStiff,1) + OutData%BottmStiff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LMassDen 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%LMassDen)) DEALLOCATE(OutData%LMassDen) + ALLOCATE(OutData%LMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LMassDen,1), UBOUND(OutData%LMassDen,1) + OutData%LMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LDMassDen 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%LDMassDen)) DEALLOCATE(OutData%LDMassDen) + ALLOCATE(OutData%LDMassDen(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LDMassDen.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LDMassDen,1), UBOUND(OutData%LDMassDen,1) + OutData%LDMassDen(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LEAStiff 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%LEAStiff)) DEALLOCATE(OutData%LEAStiff) + ALLOCATE(OutData%LEAStiff(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LEAStiff.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LEAStiff,1), UBOUND(OutData%LEAStiff,1) + OutData%LEAStiff(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineCI 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%LineCI)) DEALLOCATE(OutData%LineCI) + ALLOCATE(OutData%LineCI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineCI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineCI,1), UBOUND(OutData%LineCI,1) + OutData%LineCI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineCD 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%LineCD)) DEALLOCATE(OutData%LineCD) + ALLOCATE(OutData%LineCD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineCD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineCD,1), UBOUND(OutData%LineCD,1) + OutData%LineCD(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Bvp 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%Bvp)) DEALLOCATE(OutData%Bvp) + ALLOCATE(OutData%Bvp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Bvp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Bvp,2), UBOUND(OutData%Bvp,2) + DO i1 = LBOUND(OutData%Bvp,1), UBOUND(OutData%Bvp,1) + OutData%Bvp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc0 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%WaveAcc0)) DEALLOCATE(OutData%WaveAcc0) + ALLOCATE(OutData%WaveAcc0(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%WaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc0,3), UBOUND(OutData%WaveAcc0,3) + DO i2 = LBOUND(OutData%WaveAcc0,2), UBOUND(OutData%WaveAcc0,2) + DO i1 = LBOUND(OutData%WaveAcc0,1), UBOUND(OutData%WaveAcc0,1) + OutData%WaveAcc0(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel0 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%WaveVel0)) DEALLOCATE(OutData%WaveVel0) + ALLOCATE(OutData%WaveVel0(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%WaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel0,3), UBOUND(OutData%WaveVel0,3) + DO i2 = LBOUND(OutData%WaveVel0,2), UBOUND(OutData%WaveVel0,2) + DO i1 = LBOUND(OutData%WaveVel0,1), UBOUND(OutData%WaveVel0,1) + OutData%WaveVel0(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SHAP,1) + i1_u = UBOUND(OutData%SHAP,1) + i2_l = LBOUND(OutData%SHAP,2) + i2_u = UBOUND(OutData%SHAP,2) + DO i2 = LBOUND(OutData%SHAP,2), UBOUND(OutData%SHAP,2) + DO i1 = LBOUND(OutData%SHAP,1), UBOUND(OutData%SHAP,1) + OutData%SHAP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%SHAPS,1) + i1_u = UBOUND(OutData%SHAPS,1) + i2_l = LBOUND(OutData%SHAPS,2) + i2_u = UBOUND(OutData%SHAPS,2) + DO i2 = LBOUND(OutData%SHAPS,2), UBOUND(OutData%SHAPS,2) + DO i1 = LBOUND(OutData%SHAPS,1), UBOUND(OutData%SHAPS,1) + OutData%SHAPS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%GAUSSW,1) + i1_u = UBOUND(OutData%GAUSSW,1) + DO i1 = LBOUND(OutData%GAUSSW,1), UBOUND(OutData%GAUSSW,1) + OutData%GAUSSW(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%NGAUSS = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SHAPT,1) + i1_u = UBOUND(OutData%SHAPT,1) + i2_l = LBOUND(OutData%SHAPT,2) + i2_u = UBOUND(OutData%SHAPT,2) + DO i2 = LBOUND(OutData%SHAPT,2), UBOUND(OutData%SHAPT,2) + DO i1 = LBOUND(OutData%SHAPT,1), UBOUND(OutData%SHAPT,1) + OutData%SHAPT(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%SHAPTS,1) + i1_u = UBOUND(OutData%SHAPTS,1) + i2_l = LBOUND(OutData%SHAPTS,2) + i2_u = UBOUND(OutData%SHAPTS,2) + DO i2 = LBOUND(OutData%SHAPTS,2), UBOUND(OutData%SHAPTS,2) + DO i1 = LBOUND(OutData%SHAPTS,1), UBOUND(OutData%SHAPTS,1) + OutData%SHAPTS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%NTRAP = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SBEND,1) + i1_u = UBOUND(OutData%SBEND,1) + i2_l = LBOUND(OutData%SBEND,2) + i2_u = UBOUND(OutData%SBEND,2) + DO i2 = LBOUND(OutData%SBEND,2), UBOUND(OutData%SBEND,2) + DO i1 = LBOUND(OutData%SBEND,1), UBOUND(OutData%SBEND,1) + OutData%SBEND(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%STEN,1) + i1_u = UBOUND(OutData%STEN,1) + i2_l = LBOUND(OutData%STEN,2) + i2_u = UBOUND(OutData%STEN,2) + i3_l = LBOUND(OutData%STEN,3) + i3_u = UBOUND(OutData%STEN,3) + DO i3 = LBOUND(OutData%STEN,3), UBOUND(OutData%STEN,3) + DO i2 = LBOUND(OutData%STEN,2), UBOUND(OutData%STEN,2) + DO i1 = LBOUND(OutData%STEN,1), UBOUND(OutData%STEN,1) + OutData%STEN(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + i1_l = LBOUND(OutData%RMASS,1) + i1_u = UBOUND(OutData%RMASS,1) + i2_l = LBOUND(OutData%RMASS,2) + i2_u = UBOUND(OutData%RMASS,2) + DO i2 = LBOUND(OutData%RMASS,2), UBOUND(OutData%RMASS,2) + DO i1 = LBOUND(OutData%RMASS,1), UBOUND(OutData%RMASS,1) + OutData%RMASS(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%RADDM,1) + i1_u = UBOUND(OutData%RADDM,1) + i2_l = LBOUND(OutData%RADDM,2) + i2_u = UBOUND(OutData%RADDM,2) + i3_l = LBOUND(OutData%RADDM,3) + i3_u = UBOUND(OutData%RADDM,3) + i4_l = LBOUND(OutData%RADDM,4) + i4_u = UBOUND(OutData%RADDM,4) + DO i4 = LBOUND(OutData%RADDM,4), UBOUND(OutData%RADDM,4) + DO i3 = LBOUND(OutData%RADDM,3), UBOUND(OutData%RADDM,3) + DO i2 = LBOUND(OutData%RADDM,2), UBOUND(OutData%RADDM,2) + DO i1 = LBOUND(OutData%RADDM,1), UBOUND(OutData%RADDM,1) + OutData%RADDM(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + i1_l = LBOUND(OutData%PMPN,1) + i1_u = UBOUND(OutData%PMPN,1) + i2_l = LBOUND(OutData%PMPN,2) + i2_u = UBOUND(OutData%PMPN,2) + DO i2 = LBOUND(OutData%PMPN,2), UBOUND(OutData%PMPN,2) + DO i1 = LBOUND(OutData%PMPN,1), UBOUND(OutData%PMPN,1) + OutData%PMPN(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%AM,1) + i1_u = UBOUND(OutData%AM,1) + DO i1 = LBOUND(OutData%AM,1), UBOUND(OutData%AM,1) + OutData%AM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%PM,1) + i1_u = UBOUND(OutData%PM,1) + DO i1 = LBOUND(OutData%PM,1), UBOUND(OutData%PM,1) + OutData%PM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%IDOF,1) + i1_u = UBOUND(OutData%IDOF,1) + i2_l = LBOUND(OutData%IDOF,2) + i2_u = UBOUND(OutData%IDOF,2) + DO i2 = LBOUND(OutData%IDOF,2), UBOUND(OutData%IDOF,2) + DO i1 = LBOUND(OutData%IDOF,1), UBOUND(OutData%IDOF,1) + OutData%IDOF(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%JDOF,1) + i1_u = UBOUND(OutData%JDOF,1) + DO i1 = LBOUND(OutData%JDOF,1), UBOUND(OutData%JDOF,1) + OutData%JDOF(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%PPA,1) + i1_u = UBOUND(OutData%PPA,1) + i2_l = LBOUND(OutData%PPA,2) + i2_u = UBOUND(OutData%PPA,2) + i3_l = LBOUND(OutData%PPA,3) + i3_u = UBOUND(OutData%PPA,3) + DO i3 = LBOUND(OutData%PPA,3), UBOUND(OutData%PPA,3) + DO i2 = LBOUND(OutData%PPA,2), UBOUND(OutData%PPA,2) + DO i1 = LBOUND(OutData%PPA,1), UBOUND(OutData%PPA,1) + OutData%PPA(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + OutData%PtfmRefzt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GLUZR 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%GLUZR)) DEALLOCATE(OutData%GLUZR) + ALLOCATE(OutData%GLUZR(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%GLUZR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%GLUZR,3), UBOUND(OutData%GLUZR,3) + DO i2 = LBOUND(OutData%GLUZR,2), UBOUND(OutData%GLUZR,2) + DO i1 = LBOUND(OutData%GLUZR,1), UBOUND(OutData%GLUZR,1) + OutData%GLUZR(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GTZER 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%GTZER)) DEALLOCATE(OutData%GTZER) + ALLOCATE(OutData%GTZER(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GTZER.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%GTZER,2), UBOUND(OutData%GTZER,2) + DO i1 = LBOUND(OutData%GTZER,1), UBOUND(OutData%GTZER,1) + OutData%GTZER(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FEAM_UnPackParam + + SUBROUTINE FEAM_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_InputType), INTENT(INOUT) :: SrcInputData + TYPE(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%HydroForceLineMesh, DstInputData%HydroForceLineMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%PtFairleadDisplacement, DstInputData%PtFairleadDisplacement, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FEAM_CopyInput + + SUBROUTINE FEAM_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(FEAM_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%HydroForceLineMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%PtFairleadDisplacement, ErrStat, ErrMsg ) + END SUBROUTINE FEAM_DestroyInput + + SUBROUTINE FEAM_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(FEAM_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 = 'FEAM_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! HydroForceLineMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%HydroForceLineMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! HydroForceLineMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HydroForceLineMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HydroForceLineMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HydroForceLineMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! PtFairleadDisplacement: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtFairleadDisplacement + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtFairleadDisplacement + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtFairleadDisplacement + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtFairleadDisplacement + 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 MeshPack( InData%HydroForceLineMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! HydroForceLineMesh + 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 MeshPack( InData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtFairleadDisplacement + 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 FEAM_PackInput + + SUBROUTINE FEAM_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(FEAM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_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 + 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 MeshUnpack( OutData%HydroForceLineMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! HydroForceLineMesh + 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 MeshUnpack( OutData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtFairleadDisplacement + 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 FEAM_UnPackInput + + SUBROUTINE FEAM_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAM_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(FEAM_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'FEAM_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + CALL MeshCopy( SrcOutputData%PtFairleadLoad, DstOutputData%PtFairleadLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%LineMeshPosition, DstOutputData%LineMeshPosition, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FEAM_CopyOutput + + SUBROUTINE FEAM_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(FEAM_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + CALL MeshDestroy( OutputData%PtFairleadLoad, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%LineMeshPosition, ErrStat, ErrMsg ) + END SUBROUTINE FEAM_DestroyOutput + + SUBROUTINE FEAM_PackOutput( 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(FEAM_OutputType), 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 = 'FEAM_PackOutput' + ! 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 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PtFairleadLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtFairleadLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtFairleadLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtFairleadLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtFairleadLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LineMeshPosition: size of buffers for each call to pack subtype + CALL MeshPack( InData%LineMeshPosition, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LineMeshPosition + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LineMeshPosition + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LineMeshPosition + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LineMeshPosition + 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 + + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + CALL MeshPack( InData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtFairleadLoad + 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 MeshPack( InData%LineMeshPosition, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LineMeshPosition + 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 FEAM_PackOutput + + SUBROUTINE FEAM_UnPackOutput( 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(FEAM_OutputType), 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 = 'FEAM_UnPackOutput' + ! 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 MeshUnpack( OutData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtFairleadLoad + 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 MeshUnpack( OutData%LineMeshPosition, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LineMeshPosition + 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 FEAM_UnPackOutput + + + SUBROUTINE FEAM_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(FEAM_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(FEAM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL FEAM_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL FEAM_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL FEAM_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE FEAM_Input_ExtrapInterp + + + SUBROUTINE FEAM_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(FEAM_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(FEAM_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(FEAM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%HydroForceLineMesh, u2%HydroForceLineMesh, tin, u_out%HydroForceLineMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%PtFairleadDisplacement, u2%PtFairleadDisplacement, tin, u_out%PtFairleadDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE FEAM_Input_ExtrapInterp1 + + + SUBROUTINE FEAM_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(FEAM_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(FEAM_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(FEAM_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(FEAM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%HydroForceLineMesh, u2%HydroForceLineMesh, u3%HydroForceLineMesh, tin, u_out%HydroForceLineMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%PtFairleadDisplacement, u2%PtFairleadDisplacement, u3%PtFairleadDisplacement, tin, u_out%PtFairleadDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE FEAM_Input_ExtrapInterp2 + + + SUBROUTINE FEAM_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(FEAM_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(FEAM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL FEAM_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL FEAM_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL FEAM_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE FEAM_Output_ExtrapInterp + + + SUBROUTINE FEAM_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(FEAM_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(FEAM_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(FEAM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + CALL MeshExtrapInterp1(y1%PtFairleadLoad, y2%PtFairleadLoad, tin, y_out%PtFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%LineMeshPosition, y2%LineMeshPosition, tin, y_out%LineMeshPosition, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE FEAM_Output_ExtrapInterp1 + + + SUBROUTINE FEAM_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(FEAM_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(FEAM_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(FEAM_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(FEAM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'FEAM_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + CALL MeshExtrapInterp2(y1%PtFairleadLoad, y2%PtFairleadLoad, y3%PtFairleadLoad, tin, y_out%PtFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%LineMeshPosition, y2%LineMeshPosition, y3%LineMeshPosition, tin, y_out%LineMeshPosition, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE FEAM_Output_ExtrapInterp2 + +END MODULE FEAMooring_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/feamooring/test/FE_Mooring.dat b/OpenFAST/modules/feamooring/test/FE_Mooring.dat new file mode 100644 index 000000000..4fa836860 --- /dev/null +++ b/OpenFAST/modules/feamooring/test/FE_Mooring.dat @@ -0,0 +1,77 @@ +---------------------- FEAMOORING FILE ----------------------------------------- +NREL 5.0 MW offshore baseline floating platform input properties for the OC3-Hywind spar-buoy. +---------------------- SIMULATION CONTROL -------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) + default DT - Communication interval for module (s) + 3 NumLines - Number of lines + 20 NumElem - Total number of elements per line + default Gravity - Gravitational acceleration (m/s^2) + default WtrDens - Water density (kg/m^3) + 100 MaxIter - Maximum number of static iterations + 1e-4 Eps - Static iteration tolerance +---------------------- MOORING LINES 1 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 0.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 0.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 2 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 120.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 120.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 3 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 240.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 240.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to <RootName>.sum (flag) (currently unused) + 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) +True TabDelim - Use tab delimiters in text tabular output file? (flag) (currently unused) +"ES10.3E2" OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (quoted string) (currently unused) + 5 TStart - Time to begin tabular output (s) (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"FairT1, AnchT1" +"FairT2, AnchT2" +"FairT3, AnchT3" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_ITIBarge4_FEAMooring.dat b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_ITIBarge4_FEAMooring.dat new file mode 100644 index 000000000..43d4b428a --- /dev/null +++ b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_ITIBarge4_FEAMooring.dat @@ -0,0 +1,172 @@ +---------------------- FEAMOORING FILE ----------------------------------------- +NREL 5.0 MW offshore baseline floating platform input properties for the ITI Barge. #rho=1025; WtrDpth=150 +---------------------- SIMULATION CONTROL -------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) + default DT - Communication interval for module (s) + 8 NumLines - Number of lines + 20 NumElem - Total number of elements per line + default Gravity - Gravitational acceleration (m/s^2) + default WtrDens - Water density (kg/m^3) + 100 MaxIter - Maximum number of static iterations + 1e-4 Eps - Static iteration tolerance +---------------------- MOORING LINES 1 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 23.965 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 45.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 2 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 66.035 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 45.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 3 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 113.965 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 135.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 4 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 156.035 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 135.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 5 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 203.965 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 225.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 6 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 246.035 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 225.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 7 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 293.965 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 315.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 8 ------------------------------------------- + 589.0E6 LEAStiff - Axial stiffness + 130.403 LMassDen - Mass per unit length of the element + 5.2687 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 704.84125 LineCD - The drag force per unit length / unit relative vel squared. + 473.312 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 423.422 LRadAnch (m) + 336.035 LAngAnch (deg) + 150.0 LDpthAnch (m) + 28.2843 LRadFair (m) + 315.0 LAngFair (deg) + 4.0 LDrftFair (m) + 2.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to <RootName>.sum (flag) (currently unused) + 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) +True TabDelim - Use tab delimiters in text tabular output file? (flag) (currently unused) +"ES10.3E2" OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (quoted string) (currently unused) + 5 TStart - Time to begin tabular output (s) (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"FairT1" +"FairT2" +"FairT3" +"FairT4" +"FairT5" +"FairT6" +"FairT7" +"FairT8" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_MIT_NREL_TLP_FEAMooring.dat b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_MIT_NREL_TLP_FEAMooring.dat new file mode 100644 index 000000000..c45168dd1 --- /dev/null +++ b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_MIT_NREL_TLP_FEAMooring.dat @@ -0,0 +1,172 @@ +---------------------- FEAMOORING FILE ----------------------------------------- +NREL 5.0 MW offshore baseline floating platform input properties for the MIT/NREL TLP. #rho=1025; WtrDpth=200 +---------------------- SIMULATION CONTROL -------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) + default DT - Communication interval for module (s) + 8 NumLines - Number of lines + 20 NumElem - Total number of elements per line + default Gravity - Gravitational acceleration (m/s^2) + default WtrDens - Water density (kg/m^3) + 100 MaxIter - Maximum number of static iterations + 1e-4 Eps - Static iteration tolerance +---------------------- MOORING LINES 1 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 0.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 0.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension (N) + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 2 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 90.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 90.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 3 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 180.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 180.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 4 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 270.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 270.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 5 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 0.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 0.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 6 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 90.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 90.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 7 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 180.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 180.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 8 ------------------------------------------- + 1.5E+09 LEAStiff - Axial stiffness + 116.027 LMassDen - Mass per unit length of the element + 12.984 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 1106.4875 LineCD - The drag force per unit length / unit relative vel squared. +152.11 LStrLen (m) 151.730 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 27.00 LRadAnch (m) + 270.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 27.0 LRadFair (m) + 270.0 LAngFair (deg) + 47.89 LDrftFair (m) + 4.0E6 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to <RootName>.sum (flag) (currently unused) + 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) +True TabDelim - Use tab delimiters in text tabular output file? (flag) (currently unused) +"ES10.3E2" OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (quoted string) (currently unused) + 5 TStart - Time to begin tabular output (s) (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"FairT1, AnchT1" +"FairT2, AnchT2" +"FairT3, AnchT3" +"FairT4, AnchT4" +"FairT5, AnchT5" +"FairT6, AnchT6" +"FairT7, AnchT7" +"FairT8, AnchT8" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC3Hywind_FEAMooring.dat b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC3Hywind_FEAMooring.dat new file mode 100644 index 000000000..4fa836860 --- /dev/null +++ b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC3Hywind_FEAMooring.dat @@ -0,0 +1,77 @@ +---------------------- FEAMOORING FILE ----------------------------------------- +NREL 5.0 MW offshore baseline floating platform input properties for the OC3-Hywind spar-buoy. +---------------------- SIMULATION CONTROL -------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) + default DT - Communication interval for module (s) + 3 NumLines - Number of lines + 20 NumElem - Total number of elements per line + default Gravity - Gravitational acceleration (m/s^2) + default WtrDens - Water density (kg/m^3) + 100 MaxIter - Maximum number of static iterations + 1e-4 Eps - Static iteration tolerance +---------------------- MOORING LINES 1 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 0.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 0.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 2 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 120.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 120.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 3 ------------------------------------------- + 384.243E6 LEAStiff - Axial stiffness + 77.7 LMassDen - Mass per unit length of the element + 6.521 LDMassDen - Displaced mass per unit length of the element +0 6.47 LineCI - The inertia force per unit length / unit accel. + 46.13 LineCD - The drag force per unit length / unit relative vel squared. + 902.2 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 853.87 LRadAnch + 240.0 LAngAnch + 320.0 LDpthAnch + 5.2 LRadFair + 240.0 LAngFair + 70.0 LDrftFair + 9E5 4.7E5 Tension - Initial top tension + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to <RootName>.sum (flag) (currently unused) + 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) +True TabDelim - Use tab delimiters in text tabular output file? (flag) (currently unused) +"ES10.3E2" OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (quoted string) (currently unused) + 5 TStart - Time to begin tabular output (s) (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"FairT1, AnchT1" +"FairT2, AnchT2" +"FairT3, AnchT3" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC4DeepCwindSemi_FEAMooring.dat b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC4DeepCwindSemi_FEAMooring.dat new file mode 100644 index 000000000..0078789f2 --- /dev/null +++ b/OpenFAST/modules/feamooring/test/NRELOffshrBsline5MW_OC4DeepCwindSemi_FEAMooring.dat @@ -0,0 +1,77 @@ +---------------------- FEAMOORING FILE ----------------------------------------- +NREL 5.0 MW offshore baseline floating platform input properties for the OC4DeepCwindSemi +---------------------- SIMULATION CONTROL -------------------------------------- +False Echo - Echo input data to <RootName>.ech (flag) +default DT - Communication interval for module (s) + 3 NumLines - Number of lines + 20 NumElem - Total number of elements per line +default Gravity - Gravitational acceleration (m/s^2) +default WtrDens - Water density (kg/m^3) + 100 MaxIter - Maximum number of static iterations + 1e-4 Eps - Static iteration tolerance +---------------------- MOORING LINES 1 ------------------------------------------- + 7.536E8 LEAStiff - Axial stiffness + 113.35 LMassDen - Mass per unit length of the element + 4.72 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 6.67377 LineCD - The drag force per unit length / unit relative vel. squared + 835.35 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 837.6 LRadAnch (m) + 60.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 40.868 LRadFair (m) + 60.0 LAngFair (deg) + 14.0 LDrftFair (m) + 1.0E6 Tension - Initial top tension (N) + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 2 ------------------------------------------- + 7.536E8 LEAStiff - Axial stiffness + 113.35 LMassDen - Mass per unit length of the element + 4.72 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 6.67377 LineCD - The drag force per unit length / unit relative vel. squared + 835.35 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 837.6 LRadAnch (m) + 180.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 40.868 LRadFair (m) + 180.0 LAngFair (deg) + 14.0 LDrftFair (m) + 1.4E6 Tension - Initial top tension (N) + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- MOORING LINES 3 ------------------------------------------- + 7.536E8 LEAStiff - Axial stiffness + 113.35 LMassDen - Mass per unit length of the element + 4.72 LDMassDen - Displaced mass per unit length of the element + 0 LineCI - The inertia force per unit length / unit accel. + 6.67377 LineCD - The drag force per unit length / unit relative vel. squared + 835.35 LUnstrLen - Unstretched length + 1.0E4 BottmStiff - Seabed stiffness + 837.6 LRadAnch (m) + 300.0 LAngAnch (deg) + 200.0 LDpthAnch (m) + 40.868 LRadFair (m) + 300.0 LAngFair (deg) + 14.0 LDrftFair (m) + 1.0E6 Tension - Initial top tension (N) + 1.0E10 GSL21 - The linear spring stiffness in x-direction between mooring & platform + 1.0E10 GSL22 - The linear spring stiffness in y-direction between mooring & platform + 1.0E10 GSL23 - The linear spring stiffness in z-direction between mooring & platform +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to <RootName>.FEAM.sum (flag) (currently unused) + 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) +True TabDelim - Use tab delimiters in text tabular output file? (flag) (currently unused) +"ES10.3E2" OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (quoted string) (currently unused) + 0 TStart - Time to begin tabular output (s) (currently unused) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"FairT1, AnchT1" +"FairT2, AnchT2" +"FairT3, AnchT3" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/OpenFAST/modules/hydrodyn/CMakeLists.txt b/OpenFAST/modules/hydrodyn/CMakeLists.txt new file mode 100644 index 000000000..5626c445f --- /dev/null +++ b/OpenFAST/modules/hydrodyn/CMakeLists.txt @@ -0,0 +1,75 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/Conv_Radiation.txt ${CMAKE_CURRENT_LIST_DIR}/src/Conv_Radiation_Types.f90) + generate_f90_types(src/Current.txt ${CMAKE_CURRENT_LIST_DIR}/src/Current_Types.f90) + generate_f90_types(src/HydroDyn.txt ${CMAKE_CURRENT_LIST_DIR}/src/HydroDyn_Types.f90) + generate_f90_types(src/Morison.txt ${CMAKE_CURRENT_LIST_DIR}/src/Morison_Types.f90) + generate_f90_types(src/SS_Radiation.txt ${CMAKE_CURRENT_LIST_DIR}/src/SS_Radiation_Types.f90) + generate_f90_types(src/SS_Excitation.txt ${CMAKE_CURRENT_LIST_DIR}/src/SS_Excitation_Types.f90) + generate_f90_types(src/WAMIT.txt ${CMAKE_CURRENT_LIST_DIR}/src/WAMIT_Types.f90) + generate_f90_types(src/WAMIT2.txt ${CMAKE_CURRENT_LIST_DIR}/src/WAMIT2_Types.f90) + generate_f90_types(src/Waves.txt ${CMAKE_CURRENT_LIST_DIR}/src/Waves_Types.f90) + generate_f90_types(src/Waves2.txt ${CMAKE_CURRENT_LIST_DIR}/src/Waves2_Types.f90) +endif() + +set(HYDRODYN_SOURCES + src/Conv_Radiation.f90 + src/Current.f90 + src/HydroDyn.f90 + src/HydroDyn_Input.f90 + src/HydroDyn_Output.f90 + src/Morison.f90 + src/Morison_Output.f90 + src/SS_Radiation.f90 + src/SS_Excitation.f90 + src/UserWaves.f90 + src/WAMIT.f90 + src/WAMIT2.f90 + src/WAMIT2_Output.f90 + src/WAMIT_Interp.f90 + src/WAMIT_Output.f90 + src/Waves.f90 + src/Waves2.f90 + src/Waves2_Output.f90 + src/Conv_Radiation_Types.f90 + src/Current_Types.f90 + src/HydroDyn_Types.f90 + src/Morison_Types.f90 + src/SS_Radiation_Types.f90 + src/SS_Excitation_Types.f90 + src/WAMIT_Types.f90 + src/WAMIT2_Types.f90 + src/Waves_Types.f90 + src/Waves2_Types.f90 +) + +add_library(hydrodynlib ${HYDRODYN_SOURCES}) +target_link_libraries(hydrodynlib nwtclibs) + +add_executable(hydrodyn_driver src/HydroDyn_DriverCode.f90) +target_link_libraries(hydrodyn_driver hydrodynlib nwtclibs versioninfolib) + +#add_executable(ss_radiation +# src/SS_Radiation_DriverCode.f90) +#target_link_libraries(ss_radiation hydrodynlib nwtclibs) + +install(TARGETS hydrodynlib hydrodyn_driver + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/hydrodyn/README.md b/OpenFAST/modules/hydrodyn/README.md new file mode 100644 index 000000000..4ffa369fa --- /dev/null +++ b/OpenFAST/modules/hydrodyn/README.md @@ -0,0 +1,21 @@ +# HydroDyn Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/HydroDyn/). + +## Overview +HydroDyn is a time-domain hydrodynamics module that has been coupled into the +OpenFAST wind turbine computer-aided engineering (CAE) tool to enable +aero-hydro-servo-elastic simulation of offshore wind turbines. HydroDyn is +applicable to both fixed-bottom and floating offshore substructures. It can +also be driven as a standalone code to compute hydrodynamic loading uncoupled +from OpenFAST. + +HydroDyn allows for multiple approaches for calculating the hydrodynamic loads +on a structure: a potential-flow theory solution, a strip-theory solution, or a +combination of the two. Waves in HydroDyn can be regular (periodic) or +irregular (stochastic) and long-crested (unidirectional) or short-crested (with +wave energy spread across a range of directions). HydroDyn treats waves using +first-order (linear Airy) or first- plus second-order wave theory with the +option to include directional spreading, but no wave stretching or higher order +wave theories are included. To minimize computational expense, Fast Fourier +Transforms are applied in the summation of all wave frequency components. diff --git a/OpenFAST/modules/hydrodyn/src/Conv_Radiation.f90 b/OpenFAST/modules/hydrodyn/src/Conv_Radiation.f90 new file mode 100644 index 000000000..54040d15a --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Conv_Radiation.f90 @@ -0,0 +1,785 @@ +!********************************************************************************************************************************** +! The Conv_Radiation and Conv_Radiation_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. Conv_Radiations_Types will be auto-generated based on a description of the variables for the module. +! +! "Conv_Radiation" should be replaced with the name of your module. Example: HydroDyn +! "Conv_Rdtn" (in Conv_Rdtn_*) should be replaced with the module name or an abbreviation of it. Example: HD +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of Conv_Radiation. +! +! 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 Conv_Radiation + + USE Conv_Radiation_Types + USE NWTC_Library + USE NWTC_FFTPACK + + IMPLICIT NONE + + PRIVATE + + REAL(DbKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) !< The number slighty greater than unity in the precision of DbKi. + + + TYPE(ProgDesc), PARAMETER :: Conv_Rdtn_ProgDesc = ProgDesc( 'Conv_Radiation', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Conv_Rdtn_Init ! Initialization routine + PUBLIC :: Conv_Rdtn_End ! Ending routine (includes clean up) + + PUBLIC :: Conv_Rdtn_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: Conv_Rdtn_CalcOutput ! Routine for computing outputs + + PUBLIC :: Conv_Rdtn_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: Conv_Rdtn_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: Conv_Rdtn_UpdateDiscState ! Tight coupling routine for updating discrete states + + +CONTAINS + +SUBROUTINE ShiftValuesLeft(XDHistory, NSteps) +! This routine shifts every entry in XDHistory such that XDHistory(K+1,I) is now stored in XDHistory(K,I) +! + REAL(ReKi), INTENT(INOUT) :: XDHistory (:,:) ! The time history of the 3 components of the translational velocity (in m/s) of the WAMIT reference and the 3 components of the rotational (angular) velocity (in rad/s) of the platform relative to the inertial frame + INTEGER(IntKi), INTENT(IN ) :: NSteps ! Number of elements in the array + + INTEGER(IntKi) :: I +! INTEGER(IntKi) :: J + INTEGER(IntKi) :: K + + DO K = 0,NSteps-2 + DO I = 1,6 ! Loop through all DOFs + XDHistory(K,I) = XDHistory(K+1,I) + END DO + END DO + +END SUBROUTINE ShiftValuesLeft + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Conv_Rdtn_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(Conv_Rdtn_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Conv_Rdtn_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Conv_Rdtn_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Conv_Rdtn_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Conv_Rdtn_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Conv_Rdtn_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Conv_Rdtn_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Conv_Rdtn_UpdateStates() is called in loose coupling & + !! (2) Conv_Rdtn_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Conv_Rdtn_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + REAL(SiKi) :: Omega ! Wave frequency (rad/s) + REAL(DbKi) :: Krnl_Fact ! Factor used to scale the magnitude of the RdtnKnrl as required by the discrete time (co)sine transform (-) + REAL(DbKi) :: RdtnTMax ! Analysis time for wave radiation kernel calculations (sec), may be different from Init_Data%RdtnTMax + REAL(ReKi) :: RdtnDOmega ! Frequency step for wave radiation kernel calculations (rad/s) + REAL(ReKi) :: RdtnOmegaMax ! Maximum frequency used in the (co)sine transform to fine the radiation impulse response functions (rad/s) + REAL(DbKi), ALLOCATABLE :: RdtnTime (:) ! Simulation times at which the instantaneous values of the wave radiation kernel are determined (sec) + LOGICAL :: RdtnFrmAM ! Determine the wave radiation kernel from the frequency-dependent hydrodynamic added mass matrix? (.TRUE = yes, .FALSE. = determine the wave radiation kernel from the frequency-dependent hydrodynamic damping matrix) !JASON: SHOULD YOU MAKE THIS AN INPUT???<--JASON: IT IS NOT WISE TO COMPUTE THE RADIATION KERNEL FROM THE FREQUENCY-DEPENDENT ADDED MASS MATRIX, UNLESS A CORRECTION IS APPLIED. THIS IS DESCRIBED IN THE WAMIT USER'S GUIDE!!!! + INTEGER :: NStepRdtn2 ! ( NStepRdtn-1 )/2 + INTEGER :: Indx ! Cycles through the upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic added mass and damping matrices from the radiation problem + INTEGER :: I ! Generic index + INTEGER :: J ! Generic index + INTEGER :: K ! Generic index + INTEGER :: LastInd ! Index into the arrays saved from the last call as a starting point for this call + + TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" +!TODO +!BJJ: This was uninitialized; not sure how it should be set >>> +!PRINT *, 'Greg, please initialize this variable:RdtnFrmA' +RdtnFrmAM = .FALSE. +!<<< + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + + + ! If HighFreq is greater than + ! RdtnOmegaMax, Abort because RdtnDT must be reduced in order to have + ! sufficient accuracy in the computation of the radiation impulse response + ! functions: + + p%RdtnDT = InitInp%RdtnDT + RdtnOmegaMax = Pi / InitInp%RdtnDT + + IF ( InitInp%HighFreq > RdtnOmegaMax ) THEN ! .TRUE. if the highest frequency component (not counting infinity) in the WAMIT file is greater than RdtnOmegaMax + ErrMsg = ' Based on the frequency range found in "'//TRIM(InitInp%WAMITFile)//'.1",' // & + ' RdtnDT must be set smaller than '//TRIM(Num2LStr( Pi/InitInp%HighFreq ))//' sec'// & + ' in order to accurately compute the radiation impulse response functions.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + + u%Velocity = 0.0 !this is an initial guess; + + + ! Perform some initialization computations including calculating the total + ! number of frequency components = total number of time steps in the wave, + ! radiation kernel, calculating the frequency step, and ALLOCATing the + ! arrays: + ! NOTE: RdtnDOmega = Pi/RdtnTMax since, in the (co)sine transforms: + ! Omega = (K-1)*RdtnDOmega + ! Time = (J-1)*RdtnDT + ! and therefore: + ! Omega*Time = (K-1)*(J-1)*RdtnDOmega*RdtnDT + ! = (K-1)*(J-1)*Pi/(NStepRdtn-1) [see NWTC_FFTPACK] + ! or: + ! RdtnDOmega = Pi/((NStepRdtn-1)*RdtnDT) + ! = Pi/RdtnTMax + + p%NStepRdtn = CEILING ( InitInp%RdtnTMax/p%RdtnDT ) ! Set NStepRdtn to an odd integer + + IF ( MOD(p%NStepRdtn,2) == 0 ) p%NStepRdtn = p%NStepRdtn + 1 ! larger or equal to RdtnTMax/RdtnDT. + + NStepRdtn2 = MAX( ( p%NStepRdtn-1 )/2, 1 ) ! Make sure that NStepRdtn-1 is an even product of small factors (PSF) that is greater + p%NStepRdtn = 2*PSF ( NStepRdtn2, 9 ) + 1 ! or equal to RdtnTMax/RdtnDT to ensure that the (co)sine transform is efficient. + + p%NStepRdtn1 = p%NStepRdtn + 1 ! Save the value of NStepRdtn + 1 for future use. + !NStepRdtn2 = ( p%NStepRdtn-1 )/2 ! Update the value of NStepRdtn2 based on the value needed for NStepRdtn. + RdtnTMax = ( p%NStepRdtn-1 )*p%RdtnDT ! Update the value of RdtnTMax based on the value needed for NStepRdtn. + RdtnDOmega = Pi/RdtnTMax ! Compute the frequency step for wave radiation kernel calculations. + + ALLOCATE ( RdtnTime (0:p%NStepRdtn-1 ) , STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating memory for the RdtnTime array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( p%RdtnKrnl (0:p%NStepRdtn-1,6,6) , STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating memory for the RdtnKrnl array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( xd%XDHistory(0:p%NStepRdtn ,6 ) , STAT=ErrStat ) ! In the numerical convolution we must have NStepRdtn1 elements within the XDHistory array, which is one more than the NStepRdtn elements that are in the RdtnKrnl array + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating memory for the XDHistory array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Initialize all elements of the xd%XDHistory array with the intial values of u%Velocity + DO K = 0,p%NStepRdtn-1 + DO J = 1,6 ! Loop through all DOFs + xd%XDHistory(K,J) = u%Velocity(J) + END DO + END DO + + LastInd = 1 + IF ( RdtnFrmAM ) THEN ! .TRUE. if we will determine the wave radiation kernel from the frequency-dependent hydrodynamic added mass matrix + + + + ! Calculate the factor needed by the discrete sine transform in the + ! calculation of the wave radiation kernel: + + Krnl_Fact = -1.0_DbKi/p%RdtnDT ! This factor is needed by the discrete time sine transform + + + + ! Compute all frequency components (including zero) of the sine transform + ! of the wave radiation kernel: + + DO I = 0,p%NStepRdtn-1 ! Loop through all frequency components (including zero) of the sine transform + + + ! Calculate the array of simulation times at which the instantaneous values + ! of the wave radiation kernel are to be determined: + + RdtnTime(I) = I*p%RdtnDT + + + ! Compute the frequency of this component: + + Omega = I*RdtnDOmega + + + ! Compute the upper-triangular portion (diagonal and above) of the sine + ! transform of the wave radiation kernel: + + Indx = 0 + DO J = 1,6 ! Loop through all rows of RdtnKrnl + DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + Indx = Indx + 1 + p%RdtnKrnl(I,J,K) = Krnl_Fact*Omega*( InterpStp( Omega, InitInp%HdroFreq(:), & + InitInp%HdroAddMs(: ,Indx), LastInd, InitInp%NInpFreq ) & + - InitInp%HdroAddMs(InitInp%NInpFreq,Indx) ) + END DO ! K - All columns of RdtnKrnl above and including the diagonal + END DO ! J - All rows of RdtnKrnl + + + END DO ! I - All frequency components (including zero) of the sine transform + + + + ! Compute the sine transforms to find the time-domain representation of + ! the wave radiation kernel: + + CALL InitSINT ( p%NStepRdtn, FFT_Data, .TRUE., ErrStat ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error Initializating Sine Transforms' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO J = 1,6 ! Loop through all rows of RdtnKrnl + DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + CALL ApplySINT( p%RdtnKrnl(:,J,K), FFT_Data, ErrStat ) + IF ( ErrStat /= ErrID_None ) RETURN + END DO ! K - All columns of RdtnKrnl above and including the diagonal + DO K = J+1,6 ! Loop through all rows of RdtnKrnl below the diagonal + DO I = 0,p%NStepRdtn-1 ! Loop through all frequency components (including zero) of the sine transform + p%RdtnKrnl(I,K,J) = p%RdtnKrnl(I,J,K) + END DO ! I - All frequency components (including zero) of the sine transform + END DO ! K - All rows of RdtnKrnl below the diagonal + END DO ! J - All rows of RdtnKrnl + + CALL ExitSINT(FFT_Data, ErrStat) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error Cleaning up Sine Transforms' + ErrStat = ErrID_Fatal + RETURN + END IF + + + ELSE ! We must be determining the wave radiation kernel from the frequency-dependent hydrodynamic damping matrix + + + + ! Calculate the factor needed by the discrete cosine transform in the + ! calculation of the wave radiation kernel: + + Krnl_Fact = 1.0/p%RdtnDT ! This factor is needed by the discrete time cosine transform + + + + ! Compute all frequency components (including zero) of the cosine transform + ! of the wave radiation kernel: + + DO I = 0,p%NStepRdtn-1 ! Loop through all frequency components (including zero) of the cosine transform + + + ! Calculate the array of simulation times at which the instantaneous values + ! of the wave radiation kernel are to be determined: + + RdtnTime(I) = I*p%RdtnDT + + + ! Compute the frequency of this component: + + Omega = I*RdtnDOmega + + + ! Compute the upper-triangular portion (diagonal and above) of the cosine + ! transform of the wave radiation kernel: + + Indx = 0 + DO J = 1,6 ! Loop through all rows of RdtnKrnl + DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + Indx = Indx + 1 + p%RdtnKrnl(I,J,K) = Krnl_Fact*InterpStp ( Omega, InitInp%HdroFreq(:), InitInp%HdroDmpng(:,Indx), LastInd, InitInp%NInpFreq ) + END DO ! K - All columns of RdtnKrnl above and including the diagonal + END DO ! J - All rows of RdtnKrnl + + + END DO ! I - All frequency components (including zero) of the cosine transform + + + + ! Compute the cosine transforms to find the time-domain representation of + ! the wave radiation kernel: + + CALL InitCOST ( p%NStepRdtn, FFT_Data, .TRUE., ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error Initializating Cosine Transforms' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO J = 1,6 ! Loop through all rows of RdtnKrnl + DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + CALL ApplyCOST( p%RdtnKrnl(:,J,K), FFT_Data, ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error applying Cosine Transform' + ErrStat = ErrID_Fatal + RETURN + END IF + END DO ! K - All columns of RdtnKrnl above and including the diagonal + DO K = J+1,6 ! Loop through all rows of RdtnKrnl below the diagonal + DO I = 0,p%NStepRdtn-1 ! Loop through all radiation time steps + p%RdtnKrnl(I,K,J) = p%RdtnKrnl(I,J,K) + END DO ! I - All radiation time steps + END DO ! K - All rows of RdtnKrnl below the diagonal + END DO ! J - All rows of RdtnKrnl + + CALL ExitCOST(FFT_Data, ErrStat) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = 'Error cleaning up Cosine Transforms' + ErrStat = ErrID_Fatal + RETURN + END IF + + + END IF + + ! IF ( InitInp%UnSum > 0 ) THEN + ! + ! ! Write the header for this section + ! WRITE( InitInp%UnSum, '(//)' ) + ! WRITE( InitInp%UnSum, '(A)' ) 'Radiation memory effect kernel' + ! WRITE( InitInp%UnSum, '(//)' ) + ! WRITE( InitInp%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' n ' , ' t ', ' K11 ', ' K12 ', ' K13 ', ' K14 ', ' K15 ', ' K16 ', ' K22 ', ' K23 ', ' K24 ', ' K25 ', ' K26 ', ' K33 ', ' K34 ', ' K35 ', 'K36 ', ' K44 ', ' K45 ', ' K46 ', ' K55 ', ' K56 ', ' K66 ' + ! WRITE( InitInp%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' (-) ' , ' (s) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)' + ! + ! ! Write the data + ! DO I = 0,p%NStepRdtn-1 + ! + ! WRITE( InitInp%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%RdtnDT, p%RdtnKrnl(I,1,1), p%RdtnKrnl(I,1,2), p%RdtnKrnl(I,1,3), p%RdtnKrnl(I,1,4), p%RdtnKrnl(I,1,5), p%RdtnKrnl(I,1,6), p%RdtnKrnl(I,2,2), p%RdtnKrnl(I,2,3), p%RdtnKrnl(I,2,4), p%RdtnKrnl(I,2,5), p%RdtnKrnl(I,2,6), p%RdtnKrnl(I,3,3), p%RdtnKrnl(I,3,4), p%RdtnKrnl(I,3,5), p%RdtnKrnl(I,3,6), p%RdtnKrnl(I,4,4), p%RdtnKrnl(I,4,5), p%RdtnKrnl(I,4,6), p%RdtnKrnl(I,5,5), p%RdtnKrnl(I,5,6), p%RdtnKrnl(I,6,6) + ! + ! END DO + ! + !END IF + + + IF ( ALLOCATED( RdtnTime ) ) DEALLOCATE( RdtnTime ) + + + + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + + Interval = p%RdtnDT + + m%LastIndRdtn = 0 + OtherState%IndRdtn = 0 + + ! bjj: these initializations don't matter, but I don't like seeing the compilation warning in IVF: + x%DummyContState = 0.0 + z%DummyConstrState = 0.0 + y%F_Rdtn = 0.0 + InitOut%DummyInitOut = 0 + +END SUBROUTINE Conv_Rdtn_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Conv_Rdtn_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Conv_Rdtn_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Conv_Rdtn_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL Conv_Rdtn_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL Conv_Rdtn_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL Conv_Rdtn_DestroyContState( x, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL Conv_Rdtn_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL Conv_Rdtn_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE Conv_Rdtn_End + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(Conv_Rdtn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(Conv_Rdtn_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + + TYPE(Conv_Rdtn_InputType) :: u !< Instantaneous inputs + INTEGER(IntKi) :: ErrStat2 !< Error status of the operation (secondary error) + CHARACTER(ErrMsgLen) :: ErrMsg2 !< Error message if ErrStat2 /= ErrID_None + + + ! Initialize variables + + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + + ! This subroutine contains an example of how the states could be updated. Developers will + ! want to adjust the logic as necessary for their own situations. + + + ! Get the inputs at time t, based on the array of values sent by the glue code: + + CALL Conv_Rdtn_Input_ExtrapInterp( Inputs, InputTimes, u, t, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Update discrete states: + ! Note that xd [discrete state] is changed in Conv_Rdtn_UpdateDiscState() so xd will now contain values at t+Interval + ! We'll first make a copy that contains xd at time t, which will be used in computing the constraint states + + CALL Conv_Rdtn_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + + ! Integrate (update) continuous states (x) here: + + !x = function of dxdt and x + + + ! Destroy local variables before returning + + CALL Conv_Rdtn_DestroyInput( u, ErrStat2, ErrMsg2) + + +END SUBROUTINE Conv_Rdtn_UpdateStates + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE Conv_Rdtn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Conv_Rdtn_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Conv_Rdtn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Conv_Rdtn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m !< Initial 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) :: F_Rdtn (6) + REAL(ReKi) :: F_RdtnDT (6) ! The portion of the total load contribution from wave radiation damping associated with the convolution integral proportional to ( RdtnDT - RdtnRmndr ) (N, N-m) + + INTEGER :: I ! Generic index + INTEGER :: J ! Generic index + INTEGER :: K ! Generic index + + INTEGER(IntKi) :: MaxInd + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Perform numerical convolution to determine the load contribution from wave + ! radiation damping: + + MaxInd = MIN(p%NStepRdtn-1,OtherState%IndRdtn) ! Note: xd%IndRdtn index is from the previous time-step since this state was for the previous time-step + + DO I = 1,6 ! Loop through all wave radiation damping forces and moments + + F_RdtnDT (I) = 0.0 + ! F_RdtnRmndr(I) = 0.0 + + DO J = 1,6 ! Loop through all platform DOFs + + DO K = 0, MaxInd ! Loop through all NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) + F_RdtnDT(I) = F_RdtnDT(I) - p%RdtnKrnl(MaxInd-K,I,J)*xd%XDHistory(K,J) + END DO + !DO K = MAX(0,xd%IndRdtn-p%NStepRdtn ),xd%IndRdtn-1 ! Loop through all NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) + ! F_RdtnDT (I) = F_RdtnDT (I) - p%RdtnKrnl(xd%IndRdtn-1-K,I,J)*xd%XDHistory(MOD(K,p%NStepRdtn1),J) + !END DO ! K - All NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) + + !DO K = MAX(0,xd%IndRdtn-p%NStepRdtn+1),xd%IndRdtn ! Loop through all NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) + ! F_RdtnRmndr(I) = F_RdtnRmndr(I) - p%RdtnKrnl(xd%IndRdtn -K,I,J)*xd%XDHistory(MOD(K,p%NStepRdtn1),J) + !END DO ! K - All NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) + + END DO ! J - All platform DOFs + + !F_Rdtn (I) = ( p%RdtnDT - xd%RdtnRmndr )*F_RdtnDT(I) + xd%RdtnRmndr*F_RdtnRmndr(I) + + END DO ! I - All wave radiation damping forces and moments + + y%F_Rdtn = p%RdtnDT*F_RdtnDT !F_Rdtn + +END SUBROUTINE Conv_Rdtn_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +SUBROUTINE Conv_Rdtn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + TYPE(Conv_Rdtn_InputType), INTENT(IN ) :: u ! Inputs at Time + TYPE(Conv_Rdtn_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at Time + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at Time + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at Time + TYPE(Conv_Rdtn_OtherStateType), INTENT(IN ) :: OtherState ! Other states at Time + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m ! Initial misc/optimization variables + TYPE(Conv_Rdtn_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + dxdt%DummyContState = 0.0 + + +END SUBROUTINE Conv_Rdtn_CalcContStateDeriv + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states. +SUBROUTINE Conv_Rdtn_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(Conv_Rdtn_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Conv_Rdtn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Conv_Rdtn_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at Time (output: other states at Time + Interval) + !! THIS (intent out) BREAKS THE FRAMEWORK (but we don't care at this level) + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local Variables + REAL(ReKi) :: IncrmntUD ! Incremental change in UD over a single radiation time step (m/s, rad/s) + REAL(ReKi) :: RdtnRmndr ! Fractional amount of the p%RdtnDT timestep + INTEGER(IntKi) :: J ! Generic index + INTEGER(IntKi) :: K ! Generic index + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + ! Find the index xd%IndRdtn, where RdtnTime(IndRdtn) is the largest value in + ! RdtnTime(:) that is less than or equal to Time and find the amount of + ! time remaining from this calculation: + ! NOTE: Time is scaled by OnePlusEps to ensure that xd%IndRdtn increments in + ! steps of 1 when RdtnDT = DT, even in the presence of numerical + ! precision errors. + + OtherState%IndRdtn = FLOOR ( ( Time*OnePlusEps )/p%RdtnDT ) + RdtnRmndr = Time - ( OtherState%IndRdtn*p%RdtnDT ) ! = Time - RdtnTime(IndRdtn); however, RdtnTime(:) has a maximum index of NStepRdtn-1 + + ! This subroutine can only be called at integer multiples of p%RdtnDT, if RdtnRmdr > 0, then this requirement has been violated! + IF (RdtnRmndr > EPSILON(0.0_ReKi) ) THEN + ErrStat = ErrID_FATAL + ErrMsg = "Conv_Rdtn_UpdateDiscState() must be called at integer multiples of the radiation timestep." + RETURN + END IF + + ! Save the new values of u%Velocity in xd%XDHistory if: + ! (1) we are on the initialization pass where Time = 0.0, + ! (2) we have increased in time by at least RdtnDT, or + ! (3) the time has not changed since the last time we have increased in + ! time by at least RdtnDT (i.e., on a call to the corrector) + ! When saving the new values, interpolate to find all of the values + ! between index LastIndRdtn and index IndRdtn. Also, if the XDHistory + ! array is full, use MOD(Index,NStepRdtn1) to replace the oldest values + ! with the newest values: + ! NOTE: When IndRdtn > LastIndRdtn, IndRdtn will equal LastIndRdtn + 1 if DT <= RdtnDT; + ! When IndRdtn > LastIndRdtn, IndRdtn will be greater than LastIndRdtn + 1 if DT > RdtnDT. + !BJJ: this needs a better check so that it is ALWAYS done (MATLAB/Simulink could possibly avoid this step by starting at Time>0, OR there may be some numerical issues where this is NOT EXACTLY zero) + + IF ( OtherState%IndRdtn < (p%NStepRdtn) ) THEN + DO J = 1,6 ! Loop through all platform DOFs + xd%XDHistory(OtherState%IndRdtn,J) = u%Velocity(J) ! XDHistory was allocated as a zero-based array! + END DO ! J - All platform DOFs + ELSE + !CALL ShiftValuesLeft( xd%XDHistory, p%NStepRdtn ) ! This is NOT to be used GJH + ! Shift the stored history by one index + DO K = 0,p%NStepRdtn-2 + DO J = 1,6 ! Loop through all DOFs + xd%XDHistory(K,J) = xd%XDHistory(K+1,J) + END DO + END DO + DO J = 1,6 ! Loop through all platform DOFs + xd%XDHistory(p%NStepRdtn-1,J) = u%Velocity(J) ! Set the last array element to the current velocity + END DO ! J - All platform DOFs + END IF + + ! IF ( Time == 0.0_DbKi ) THEN ! (1) .TRUE. if we are on the initialization pass where Time = 0.0 (and IndRdtn = 0) + ! + ! DO J = 1,6 ! Loop through all platform DOFs + ! xd%XDHistory(xd%IndRdtn,J) = u%Velocity(J) + ! END DO ! J - All platform DOFs + ! + ! xd%LastIndRdtn = xd%IndRdtn ! Save the value of IndRdtn for the next call to this routine (in this case IndRdtn = 0) + ! + ! ELSEIF ( xd%IndRdtn > xd%LastIndRdtn ) THEN ! (2) .TRUE. if we have increased in time by at least RdtnDT + ! + ! DO J = 1,6 ! Loop through all platform DOFs + ! + ! IncrmntUD = ( p%RdtnDT/( Time - ( xd%LastIndRdtn*p%RdtnDT ) ) ) * & + ! ( u%Velocity(J) - xd%XDHistory(MOD(xd%LastIndRdtn ,p%NStepRdtn1),J) ) + ! + ! DO K = xd%LastIndRdtn +1,xd%IndRdtn ! Loop through all radiation time steps where the time history of UD has yet to be stored + ! xd%XDHistory(MOD(K,p%NStepRdtn1),J) = xd%XDHistory(MOD(xd%LastIndRdtn ,p%NStepRdtn1),J) & + ! + ( K - xd%LastIndRdtn )*IncrmntUD + ! END DO ! K - All radiation time steps where the time history of UD has yet to be stored + ! + ! END DO ! J - All platform DOFs + ! + ! xd%LastIndRdtn2 = xd%LastIndRdtn ! Save the value of LastIndRdtn for the next call to this routine + ! xd%LastIndRdtn = xd%IndRdtn ! Save the value of IndRdtn for the next call to this routine + ! xd%LastTime = Time ! Save the value of Time associated with LastIndRdtn for the next call to this routine + ! + !!BJJ: this needs a better check in case there may be some numerical issues where this is NOT EXACTLY the same... + ! ELSEIF ( Time == xd%LastTime ) THEN ! (3). .TRUE. if the time has not changed since the last time we have increased in time by at least RdtnDt (i.e., on a call to the corrector) + ! + ! DO J = 1,6 ! Loop through all platform DOFs + ! + ! IncrmntUD = ( p%RdtnDT/( Time - ( xd%LastIndRdtn2*p%RdtnDT ) ) ) * & + ! ( u%Velocity(J) - xd%XDHistory(MOD(xd%LastIndRdtn2,p%NStepRdtn1),J) ) + ! + ! DO K = xd%LastIndRdtn2+1,xd%IndRdtn ! Loop through all radiation time steps where the time history of UD should be updated + ! xd%XDHistory(MOD(K,p%NStepRdtn1),J) = xd%XDHistory(MOD(xd%LastIndRdtn2,p%NStepRdtn1),J) & + ! + ( K - xd%LastIndRdtn2 )*IncrmntUD + ! END DO ! K - All radiation time steps where the time history of UD should be updated + ! + ! END DO ! J - All platform DOFs + ! + ! END IF + +END SUBROUTINE Conv_Rdtn_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations. +SUBROUTINE Conv_Rdtn_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Conv_Rdtn_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Conv_Rdtn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(Conv_Rdtn_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at Time + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(Conv_Rdtn_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0 + +END SUBROUTINE Conv_Rdtn_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE Conv_Radiation +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/Conv_Radiation.txt b/OpenFAST/modules/hydrodyn/src/Conv_Radiation.txt new file mode 100644 index 000000000..82a4f09dc --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Conv_Radiation.txt @@ -0,0 +1,87 @@ +################################################################################################################################### +# Registry for Conv_Radiation in the FAST Modularization Framework +# This Registry file is used to create MODULE Conv_Radiation which contains all of the user-defined types needed in Conv_Radiation. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Conv_Radiation/Conv_Rdtn InitInputType DbKi RdtnDT - - - "" - +typedef ^ ^ CHARACTER(80) RdtnDTChr +typedef ^ ^ ReKi HighFreq - - - "" - +typedef ^ ^ CHARACTER(1024) WAMITFile - - - "" - +typedef ^ ^ SiKi HdroAddMs {:}{:} - - "" - +typedef ^ ^ SiKi HdroFreq {:} - - "" - +typedef ^ ^ SiKi HdroDmpng {:}{:} - - "" - +typedef ^ ^ INTEGER NInpFreq - - - "" - +typedef ^ ^ DbKi RdtnTMax - - - "" - +typedef ^ ^ INTEGER UnSum - - - "" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType INTEGER DummyInitOut - - - "" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType ReKi XDHistory {:}{:} - - "" - +typedef ^ ^ DbKi LastTime - - - "" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# +# +# Define any data that are integer or logical states here: +typedef ^ OtherStateType INTEGER IndRdtn - - - "" - + +# ..... 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 INTEGER LastIndRdtn - - - "" - + + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ^ DbKi RdtnDT - - - "" - +typedef ^ ^ SiKi RdtnKrnl {:}{:}{:} - - "" - +typedef ^ ^ INTEGER NStepRdtn - - - "" - +typedef ^ ^ INTEGER NStepRdtn1 - - - "" - +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +#typedef^ InputType MeshType MeshedInput - - - "Meshed input data" - +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi Velocity {6} - - "" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +#typedef^ OutputType MeshType MeshedOutput - - - "Meshed output data" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi F_Rdtn {6} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/Conv_Radiation_Types.f90 b/OpenFAST/modules/hydrodyn/src/Conv_Radiation_Types.f90 new file mode 100644 index 000000000..cbbf1b386 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Conv_Radiation_Types.f90 @@ -0,0 +1,2097 @@ +!STARTOFREGISTRYGENERATEDFILE 'Conv_Radiation_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 +!********************************************************************************************************************************* +! Conv_Radiation_Types +!................................................................................................................................. +! This file is part of Conv_Radiation. +! +! 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 Conv_Radiation. 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 Conv_Radiation_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Conv_Rdtn_InitInputType ======= + TYPE, PUBLIC :: Conv_Rdtn_InitInputType + REAL(DbKi) :: RdtnDT !< [-] + CHARACTER(80) :: RdtnDTChr + REAL(ReKi) :: HighFreq !< [-] + CHARACTER(1024) :: WAMITFile !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: HdroAddMs !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: HdroFreq !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: HdroDmpng !< [-] + INTEGER(IntKi) :: NInpFreq !< [-] + REAL(DbKi) :: RdtnTMax !< [-] + INTEGER(IntKi) :: UnSum !< [-] + END TYPE Conv_Rdtn_InitInputType +! ======================= +! ========= Conv_Rdtn_InitOutputType ======= + TYPE, PUBLIC :: Conv_Rdtn_InitOutputType + INTEGER(IntKi) :: DummyInitOut !< [-] + END TYPE Conv_Rdtn_InitOutputType +! ======================= +! ========= Conv_Rdtn_ContinuousStateType ======= + TYPE, PUBLIC :: Conv_Rdtn_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Conv_Rdtn_ContinuousStateType +! ======================= +! ========= Conv_Rdtn_DiscreteStateType ======= + TYPE, PUBLIC :: Conv_Rdtn_DiscreteStateType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: XDHistory !< [-] + REAL(DbKi) :: LastTime !< [-] + END TYPE Conv_Rdtn_DiscreteStateType +! ======================= +! ========= Conv_Rdtn_ConstraintStateType ======= + TYPE, PUBLIC :: Conv_Rdtn_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Conv_Rdtn_ConstraintStateType +! ======================= +! ========= Conv_Rdtn_OtherStateType ======= + TYPE, PUBLIC :: Conv_Rdtn_OtherStateType + INTEGER(IntKi) :: IndRdtn !< [-] + END TYPE Conv_Rdtn_OtherStateType +! ======================= +! ========= Conv_Rdtn_MiscVarType ======= + TYPE, PUBLIC :: Conv_Rdtn_MiscVarType + INTEGER(IntKi) :: LastIndRdtn !< [-] + END TYPE Conv_Rdtn_MiscVarType +! ======================= +! ========= Conv_Rdtn_ParameterType ======= + TYPE, PUBLIC :: Conv_Rdtn_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + REAL(DbKi) :: RdtnDT !< [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: RdtnKrnl !< [-] + INTEGER(IntKi) :: NStepRdtn !< [-] + INTEGER(IntKi) :: NStepRdtn1 !< [-] + END TYPE Conv_Rdtn_ParameterType +! ======================= +! ========= Conv_Rdtn_InputType ======= + TYPE, PUBLIC :: Conv_Rdtn_InputType + REAL(ReKi) , DIMENSION(1:6) :: Velocity !< [-] + END TYPE Conv_Rdtn_InputType +! ======================= +! ========= Conv_Rdtn_OutputType ======= + TYPE, PUBLIC :: Conv_Rdtn_OutputType + REAL(ReKi) , DIMENSION(1:6) :: F_Rdtn !< [-] + END TYPE Conv_Rdtn_OutputType +! ======================= +CONTAINS + SUBROUTINE Conv_Rdtn_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%RdtnDT = SrcInitInputData%RdtnDT + DstInitInputData%RdtnDTChr = SrcInitInputData%RdtnDTChr + DstInitInputData%HighFreq = SrcInitInputData%HighFreq + DstInitInputData%WAMITFile = SrcInitInputData%WAMITFile +IF (ALLOCATED(SrcInitInputData%HdroAddMs)) THEN + i1_l = LBOUND(SrcInitInputData%HdroAddMs,1) + i1_u = UBOUND(SrcInitInputData%HdroAddMs,1) + i2_l = LBOUND(SrcInitInputData%HdroAddMs,2) + i2_u = UBOUND(SrcInitInputData%HdroAddMs,2) + IF (.NOT. ALLOCATED(DstInitInputData%HdroAddMs)) THEN + ALLOCATE(DstInitInputData%HdroAddMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%HdroAddMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%HdroAddMs = SrcInitInputData%HdroAddMs +ENDIF +IF (ALLOCATED(SrcInitInputData%HdroFreq)) THEN + i1_l = LBOUND(SrcInitInputData%HdroFreq,1) + i1_u = UBOUND(SrcInitInputData%HdroFreq,1) + IF (.NOT. ALLOCATED(DstInitInputData%HdroFreq)) THEN + ALLOCATE(DstInitInputData%HdroFreq(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%HdroFreq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%HdroFreq = SrcInitInputData%HdroFreq +ENDIF +IF (ALLOCATED(SrcInitInputData%HdroDmpng)) THEN + i1_l = LBOUND(SrcInitInputData%HdroDmpng,1) + i1_u = UBOUND(SrcInitInputData%HdroDmpng,1) + i2_l = LBOUND(SrcInitInputData%HdroDmpng,2) + i2_u = UBOUND(SrcInitInputData%HdroDmpng,2) + IF (.NOT. ALLOCATED(DstInitInputData%HdroDmpng)) THEN + ALLOCATE(DstInitInputData%HdroDmpng(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%HdroDmpng.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%HdroDmpng = SrcInitInputData%HdroDmpng +ENDIF + DstInitInputData%NInpFreq = SrcInitInputData%NInpFreq + DstInitInputData%RdtnTMax = SrcInitInputData%RdtnTMax + DstInitInputData%UnSum = SrcInitInputData%UnSum + END SUBROUTINE Conv_Rdtn_CopyInitInput + + SUBROUTINE Conv_Rdtn_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%HdroAddMs)) THEN + DEALLOCATE(InitInputData%HdroAddMs) +ENDIF +IF (ALLOCATED(InitInputData%HdroFreq)) THEN + DEALLOCATE(InitInputData%HdroFreq) +ENDIF +IF (ALLOCATED(InitInputData%HdroDmpng)) THEN + DEALLOCATE(InitInputData%HdroDmpng) +ENDIF + END SUBROUTINE Conv_Rdtn_DestroyInitInput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Db_BufSz = Db_BufSz + 1 ! RdtnDT + Int_BufSz = Int_BufSz + 1*LEN(InData%RdtnDTChr) ! RdtnDTChr + Re_BufSz = Re_BufSz + 1 ! HighFreq + Int_BufSz = Int_BufSz + 1*LEN(InData%WAMITFile) ! WAMITFile + Int_BufSz = Int_BufSz + 1 ! HdroAddMs allocated yes/no + IF ( ALLOCATED(InData%HdroAddMs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! HdroAddMs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HdroAddMs) ! HdroAddMs + END IF + Int_BufSz = Int_BufSz + 1 ! HdroFreq allocated yes/no + IF ( ALLOCATED(InData%HdroFreq) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! HdroFreq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HdroFreq) ! HdroFreq + END IF + Int_BufSz = Int_BufSz + 1 ! HdroDmpng allocated yes/no + IF ( ALLOCATED(InData%HdroDmpng) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! HdroDmpng upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%HdroDmpng) ! HdroDmpng + END IF + Int_BufSz = Int_BufSz + 1 ! NInpFreq + Db_BufSz = Db_BufSz + 1 ! RdtnTMax + Int_BufSz = Int_BufSz + 1 ! UnSum + 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 + + DbKiBuf(Db_Xferred) = InData%RdtnDT + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(InData%RdtnDTChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%RdtnDTChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%HighFreq + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%WAMITFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%WAMITFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%HdroAddMs) ) 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%HdroAddMs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroAddMs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroAddMs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroAddMs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%HdroAddMs,2), UBOUND(InData%HdroAddMs,2) + DO i1 = LBOUND(InData%HdroAddMs,1), UBOUND(InData%HdroAddMs,1) + ReKiBuf(Re_Xferred) = InData%HdroAddMs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%HdroFreq) ) 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%HdroFreq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroFreq,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%HdroFreq,1), UBOUND(InData%HdroFreq,1) + ReKiBuf(Re_Xferred) = InData%HdroFreq(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%HdroDmpng) ) 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%HdroDmpng,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroDmpng,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroDmpng,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroDmpng,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%HdroDmpng,2), UBOUND(InData%HdroDmpng,2) + DO i1 = LBOUND(InData%HdroDmpng,1), UBOUND(InData%HdroDmpng,1) + ReKiBuf(Re_Xferred) = InData%HdroDmpng(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NInpFreq + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%RdtnTMax + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackInitInput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_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%RdtnDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(OutData%RdtnDTChr) + OutData%RdtnDTChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%HighFreq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%WAMITFile) + OutData%WAMITFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HdroAddMs 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%HdroAddMs)) DEALLOCATE(OutData%HdroAddMs) + ALLOCATE(OutData%HdroAddMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroAddMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%HdroAddMs,2), UBOUND(OutData%HdroAddMs,2) + DO i1 = LBOUND(OutData%HdroAddMs,1), UBOUND(OutData%HdroAddMs,1) + OutData%HdroAddMs(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HdroFreq 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%HdroFreq)) DEALLOCATE(OutData%HdroFreq) + ALLOCATE(OutData%HdroFreq(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroFreq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%HdroFreq,1), UBOUND(OutData%HdroFreq,1) + OutData%HdroFreq(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HdroDmpng 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%HdroDmpng)) DEALLOCATE(OutData%HdroDmpng) + ALLOCATE(OutData%HdroDmpng(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroDmpng.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%HdroDmpng,2), UBOUND(OutData%HdroDmpng,2) + DO i1 = LBOUND(OutData%HdroDmpng,1), UBOUND(OutData%HdroDmpng,1) + OutData%HdroDmpng(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%NInpFreq = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RdtnTMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackInitInput + + SUBROUTINE Conv_Rdtn_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Conv_Rdtn_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 = 'Conv_Rdtn_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%DummyInitOut = SrcInitOutputData%DummyInitOut + END SUBROUTINE Conv_Rdtn_CopyInitOutput + + SUBROUTINE Conv_Rdtn_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyInitOutput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Int_BufSz = Int_BufSz + 1 ! DummyInitOut + 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%DummyInitOut + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackInitOutput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + OutData%DummyInitOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackInitOutput + + SUBROUTINE Conv_Rdtn_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Conv_Rdtn_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 = 'Conv_Rdtn_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Conv_Rdtn_CopyContState + + SUBROUTINE Conv_Rdtn_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyContState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 Conv_Rdtn_PackContState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackContState + + SUBROUTINE Conv_Rdtn_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Conv_Rdtn_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) :: 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 = 'Conv_Rdtn_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcDiscStateData%XDHistory)) THEN + i1_l = LBOUND(SrcDiscStateData%XDHistory,1) + i1_u = UBOUND(SrcDiscStateData%XDHistory,1) + i2_l = LBOUND(SrcDiscStateData%XDHistory,2) + i2_u = UBOUND(SrcDiscStateData%XDHistory,2) + IF (.NOT. ALLOCATED(DstDiscStateData%XDHistory)) THEN + ALLOCATE(DstDiscStateData%XDHistory(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%XDHistory.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstDiscStateData%XDHistory = SrcDiscStateData%XDHistory +ENDIF + DstDiscStateData%LastTime = SrcDiscStateData%LastTime + END SUBROUTINE Conv_Rdtn_CopyDiscState + + SUBROUTINE Conv_Rdtn_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(DiscStateData%XDHistory)) THEN + DEALLOCATE(DiscStateData%XDHistory) +ENDIF + END SUBROUTINE Conv_Rdtn_DestroyDiscState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Int_BufSz = Int_BufSz + 1 ! XDHistory allocated yes/no + IF ( ALLOCATED(InData%XDHistory) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! XDHistory upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%XDHistory) ! XDHistory + END IF + Db_BufSz = Db_BufSz + 1 ! LastTime + 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%XDHistory) ) 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%XDHistory,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XDHistory,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%XDHistory,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XDHistory,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%XDHistory,2), UBOUND(InData%XDHistory,2) + DO i1 = LBOUND(InData%XDHistory,1), UBOUND(InData%XDHistory,1) + ReKiBuf(Re_Xferred) = InData%XDHistory(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DbKiBuf(Db_Xferred) = InData%LastTime + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackDiscState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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) :: 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 = 'Conv_Rdtn_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! XDHistory 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%XDHistory)) DEALLOCATE(OutData%XDHistory) + ALLOCATE(OutData%XDHistory(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%XDHistory.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%XDHistory,2), UBOUND(OutData%XDHistory,2) + DO i1 = LBOUND(OutData%XDHistory,1), UBOUND(OutData%XDHistory,1) + OutData%XDHistory(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%LastTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackDiscState + + SUBROUTINE Conv_Rdtn_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Conv_Rdtn_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 = 'Conv_Rdtn_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Conv_Rdtn_CopyConstrState + + SUBROUTINE Conv_Rdtn_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyConstrState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 Conv_Rdtn_PackConstrState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackConstrState + + SUBROUTINE Conv_Rdtn_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Conv_Rdtn_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 = 'Conv_Rdtn_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%IndRdtn = SrcOtherStateData%IndRdtn + END SUBROUTINE Conv_Rdtn_CopyOtherState + + SUBROUTINE Conv_Rdtn_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyOtherState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Int_BufSz = Int_BufSz + 1 ! IndRdtn + 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%IndRdtn + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackOtherState + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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%IndRdtn = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackOtherState + + SUBROUTINE Conv_Rdtn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Conv_Rdtn_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 = 'Conv_Rdtn_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastIndRdtn = SrcMiscData%LastIndRdtn + END SUBROUTINE Conv_Rdtn_CopyMisc + + SUBROUTINE Conv_Rdtn_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyMisc + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 ! LastIndRdtn + 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%LastIndRdtn + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackMisc + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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%LastIndRdtn = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackMisc + + SUBROUTINE Conv_Rdtn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%RdtnDT = SrcParamData%RdtnDT +IF (ALLOCATED(SrcParamData%RdtnKrnl)) THEN + i1_l = LBOUND(SrcParamData%RdtnKrnl,1) + i1_u = UBOUND(SrcParamData%RdtnKrnl,1) + i2_l = LBOUND(SrcParamData%RdtnKrnl,2) + i2_u = UBOUND(SrcParamData%RdtnKrnl,2) + i3_l = LBOUND(SrcParamData%RdtnKrnl,3) + i3_u = UBOUND(SrcParamData%RdtnKrnl,3) + IF (.NOT. ALLOCATED(DstParamData%RdtnKrnl)) THEN + ALLOCATE(DstParamData%RdtnKrnl(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%RdtnKrnl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%RdtnKrnl = SrcParamData%RdtnKrnl +ENDIF + DstParamData%NStepRdtn = SrcParamData%NStepRdtn + DstParamData%NStepRdtn1 = SrcParamData%NStepRdtn1 + END SUBROUTINE Conv_Rdtn_CopyParam + + SUBROUTINE Conv_Rdtn_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%RdtnKrnl)) THEN + DEALLOCATE(ParamData%RdtnKrnl) +ENDIF + END SUBROUTINE Conv_Rdtn_DestroyParam + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Db_BufSz = Db_BufSz + 1 ! DT + Db_BufSz = Db_BufSz + 1 ! RdtnDT + Int_BufSz = Int_BufSz + 1 ! RdtnKrnl allocated yes/no + IF ( ALLOCATED(InData%RdtnKrnl) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! RdtnKrnl upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RdtnKrnl) ! RdtnKrnl + END IF + Int_BufSz = Int_BufSz + 1 ! NStepRdtn + Int_BufSz = Int_BufSz + 1 ! NStepRdtn1 + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%RdtnDT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%RdtnKrnl) ) 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%RdtnKrnl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RdtnKrnl,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RdtnKrnl,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RdtnKrnl,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RdtnKrnl,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RdtnKrnl,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%RdtnKrnl,3), UBOUND(InData%RdtnKrnl,3) + DO i2 = LBOUND(InData%RdtnKrnl,2), UBOUND(InData%RdtnKrnl,2) + DO i1 = LBOUND(InData%RdtnKrnl,1), UBOUND(InData%RdtnKrnl,1) + ReKiBuf(Re_Xferred) = InData%RdtnKrnl(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepRdtn + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepRdtn1 + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_PackParam + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%RdtnDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RdtnKrnl 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%RdtnKrnl)) DEALLOCATE(OutData%RdtnKrnl) + ALLOCATE(OutData%RdtnKrnl(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%RdtnKrnl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%RdtnKrnl,3), UBOUND(OutData%RdtnKrnl,3) + DO i2 = LBOUND(OutData%RdtnKrnl,2), UBOUND(OutData%RdtnKrnl,2) + DO i1 = LBOUND(OutData%RdtnKrnl,1), UBOUND(OutData%RdtnKrnl,1) + OutData%RdtnKrnl(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%NStepRdtn = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepRdtn1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Conv_Rdtn_UnPackParam + + SUBROUTINE Conv_Rdtn_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: SrcInputData + TYPE(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%Velocity = SrcInputData%Velocity + END SUBROUTINE Conv_Rdtn_CopyInput + + SUBROUTINE Conv_Rdtn_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyInput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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 = 'Conv_Rdtn_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 + Re_BufSz = Re_BufSz + SIZE(InData%Velocity) ! Velocity + 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%Velocity,1), UBOUND(InData%Velocity,1) + ReKiBuf(Re_Xferred) = InData%Velocity(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE Conv_Rdtn_PackInput + + SUBROUTINE Conv_Rdtn_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(Conv_Rdtn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_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 + i1_l = LBOUND(OutData%Velocity,1) + i1_u = UBOUND(OutData%Velocity,1) + DO i1 = LBOUND(OutData%Velocity,1), UBOUND(OutData%Velocity,1) + OutData%Velocity(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE Conv_Rdtn_UnPackInput + + SUBROUTINE Conv_Rdtn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: SrcOutputData + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Conv_Rdtn_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%F_Rdtn = SrcOutputData%F_Rdtn + END SUBROUTINE Conv_Rdtn_CopyOutput + + SUBROUTINE Conv_Rdtn_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Conv_Rdtn_DestroyOutput + + SUBROUTINE Conv_Rdtn_PackOutput( 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(Conv_Rdtn_OutputType), 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 = 'Conv_Rdtn_PackOutput' + ! 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%F_Rdtn) ! F_Rdtn + 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%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) + ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE Conv_Rdtn_PackOutput + + SUBROUTINE Conv_Rdtn_UnPackOutput( 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(Conv_Rdtn_OutputType), 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 = 'Conv_Rdtn_UnPackOutput' + ! 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%F_Rdtn,1) + i1_u = UBOUND(OutData%F_Rdtn,1) + DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) + OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE Conv_Rdtn_UnPackOutput + + + SUBROUTINE Conv_Rdtn_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Conv_Rdtn_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Conv_Rdtn_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Conv_Rdtn_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Conv_Rdtn_Input_ExtrapInterp + + + SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(u_out%Velocity,1),UBOUND(u_out%Velocity,1) + b = -(u1%Velocity(i1) - u2%Velocity(i1)) + u_out%Velocity(i1) = u1%Velocity(i1) + b * ScaleFactor + END DO + END SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1 + + + SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(u_out%Velocity,1),UBOUND(u_out%Velocity,1) + b = (t(3)**2*(u1%Velocity(i1) - u2%Velocity(i1)) + t(2)**2*(-u1%Velocity(i1) + u3%Velocity(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%Velocity(i1) + t(3)*u2%Velocity(i1) - t(2)*u3%Velocity(i1) ) * scaleFactor + u_out%Velocity(i1) = u1%Velocity(i1) + b + c * t_out + END DO + END SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2 + + + SUBROUTINE Conv_Rdtn_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Conv_Rdtn_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Conv_Rdtn_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Conv_Rdtn_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Conv_Rdtn_Output_ExtrapInterp + + + SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(y_out%F_Rdtn,1),UBOUND(y_out%F_Rdtn,1) + b = -(y1%F_Rdtn(i1) - y2%F_Rdtn(i1)) + y_out%F_Rdtn(i1) = y1%F_Rdtn(i1) + b * ScaleFactor + END DO + END SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1 + + + SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Conv_Rdtn_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(y_out%F_Rdtn,1),UBOUND(y_out%F_Rdtn,1) + b = (t(3)**2*(y1%F_Rdtn(i1) - y2%F_Rdtn(i1)) + t(2)**2*(-y1%F_Rdtn(i1) + y3%F_Rdtn(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%F_Rdtn(i1) + t(3)*y2%F_Rdtn(i1) - t(2)*y3%F_Rdtn(i1) ) * scaleFactor + y_out%F_Rdtn(i1) = y1%F_Rdtn(i1) + b + c * t_out + END DO + END SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2 + +END MODULE Conv_Radiation_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/Current.f90 b/OpenFAST/modules/hydrodyn/src/Current.f90 new file mode 100644 index 000000000..a7415f677 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Current.f90 @@ -0,0 +1,323 @@ +!********************************************************************************************************************************** +! The Current and Current_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. Currents_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of Current. +! +! 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 Current + + USE Current_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: Current_ProgDesc = ProgDesc( 'Current', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Current_Init ! Initialization routine + PUBLIC :: Current_End ! Ending routine (includes clean up) + +CONTAINS + +!======================================================================= +!JASON: MOVE THIS USER-DEFINED ROUTINE (UserCurrent) TO THE UserSubs.f90 OF HydroDyn WHEN THE PLATFORM LOADING FUNCTIONALITY HAS BEEN DOCUMENTED!!!!! +!> This is a dummy routine for holding the place of a user-specified +!! current profile. Modify this code to create your own profile. +SUBROUTINE UserCurrent ( zi, WtrDpth, DirRoot, CurrVxi, CurrVyi ) + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(OUT) :: CurrVxi !< xi-component of the current velocity at elevation zi, m/s. + REAL(SiKi), INTENT(OUT) :: CurrVyi !< yi-component of the current velocity at elevation zi, m/s. + REAL(SiKi), INTENT(IN ) :: WtrDpth !< Water depth ( WtrDpth > 0 ), meters. + REAL(SiKi), INTENT(IN ) :: zi !< Elevation (-WtrDpth <= zi <= 0 ), meters. + + CHARACTER(*), INTENT(IN ) :: DirRoot !< The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + + CurrVxi = 0.0 + CurrVyi = 0.0 + + + + RETURN + +END SUBROUTINE UserCurrent + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes the x and y current components for a given water elevation +SUBROUTINE Calc_Current( InitInp, z, h , DirRoot, CurrVxi, CurrVyi ) +!---------------------------------------------------------------------------------------------------------------------------------- + + ! This routine is used to initialize the variables associated with + ! current. + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(OUT) :: CurrVxi !< xi-component of the current velocity at elevation z (m/s) + REAL(SiKi), INTENT(OUT) :: CurrVyi !< yi-component of the current velocity at elevation z (m/s) + + REAL(SiKi), INTENT(IN ) :: h !< Water depth (meters) This quantity must be positive-valued + REAL(SiKi), INTENT(IN ) :: z !< Elevation relative to the mean sea level (meters) + CHARACTER(*), INTENT(IN ) :: DirRoot !< The name of the root file including the full path to the current working directory. + !! This may be useful if you want this routine to write a permanent record of what it does + !! to be stored with the simulation results: the results should be stored in a file whose name + !! (including path) is generated by appending any suitable extension to DirRoot. + TYPE(Current_InitInputType), INTENT(IN ) :: InitInp !< Initialization data for the current module + + + ! Local Variables: + + REAL(ReKi) :: CurrSSV ! Magnitude of sub -surface current velocity at elevation z (m/s) + REAL(ReKi) :: CurrNSV ! Magnitude of near-surface current velocity at elevation z (m/s) + + + + ! If elevation z lies between the seabed and the mean sea level, compute the + ! xi- and yi-components of the current (which depends on which current + ! profile model is selected), else set CurrVxi and CurrVyi to zero: + + IF ( ( z < -h ) .OR. ( z > 0.0 ) ) THEN ! .TRUE. if elevation z lies below the seabed or above mean sea level (exclusive) + + + CurrVxi = 0.0 ! Set both the xi- and yi-direction + CurrVyi = 0.0 ! current velocities to zero + + + ELSE ! Elevation z must lie between the seabed and the mean sea level (inclusive) + + + SELECT CASE ( InitInp%CurrMod ) ! Which current profile model are we using? + + CASE ( 0 ) ! None! + + CurrVxi = 0.0 ! Set both the xi- and yi-direction + CurrVyi = 0.0 ! current velocities to zero + + + CASE ( 1 ) ! Standard (using inputs from PtfmFile). + + CurrSSV = InitInp%CurrSSV0*( ( z + h )/h )**(1.0/7.0) + CurrNSV = MAX( InitInp%CurrNSV0*( ( z + InitInp%CurrNSRef )/InitInp%CurrNSRef ) , 0.0_SiKi ) + + CurrVxi = InitInp%CurrDIV*COS( D2R*InitInp%CurrDIDir ) + CurrSSV*COS( D2R*InitInp%CurrSSDir ) + & + CurrNSV*COS( D2R*InitInp%CurrNSDir ) + + CurrVyi = InitInp%CurrDIV*SIN( D2R*InitInp%CurrDIDir ) + CurrSSV*SIN( D2R*InitInp%CurrSSDir ) + & + CurrNSV*SIN( D2R*InitInp%CurrNSDir ) + + + CASE ( 2 ) ! User-defined current profile model. + + CALL UserCurrent ( z, h, DirRoot, CurrVxi, CurrVyi ) + + ENDSELECT + + END IF + + RETURN + +END SUBROUTINE Calc_Current + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Current_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Current_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(Current_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Current_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Current_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Current_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Current_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Current_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Current_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Current_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Current_UpdateStates() is called in loose coupling & + !! (2) Current_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Current_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + + + ! Local Variables: + + REAL(SiKi) :: CurrVxi ! xi-component of the current velocity at elevation z (m/s) + REAL(SiKi) :: CurrVyi ! yi-component of the current velocity at elevation z (m/s) + REAL(SiKi) :: CurrVxi0 ! xi-component of the current velocity at zi = 0.0 meters (m/s) + REAL(SiKi) :: CurrVyi0 ! yi-component of the current velocity at zi = 0.0 meters (m/s) + REAL(SiKi) :: CurrVxiS ! xi-component of the current velocity at zi = -SmllNmbr meters (m/s) + REAL(SiKi) :: CurrVyiS ! yi-component of the current velocity at zi = -SmllNmbr meters (m/s) + REAL(SiKi), PARAMETER :: SmllNmbr = 9.999E-4 ! A small number representing epsilon for taking numerical derivatives. + + INTEGER :: I ! Generic index + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + + + ! IF there are Morison elements, then compute the current components at each morison node elevation + + IF ( InitInp%NMorisonNodes > 0 ) THEN + + ALLOCATE ( InitOut%CurrVxi( InitInp%NMorisonNodes ) , STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating memory for the CurrVxi array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%CurrVyi( InitInp%NMorisonNodes ) , STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating memory for the CurrVyi array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Loop over all of the points where current information is required + + DO I = 1, InitInp%NMorisonNodes + + CALL Calc_Current( InitInp, InitInp%MorisonNodezi(I), InitInp%WtrDpth, InitInp%DirRoot, CurrVxi, CurrVyi ) + + InitOut%CurrVxi(I) = CurrVxi + InitOut%CurrVyi(I) = CurrVyi + + END DO + + END IF + + + ! Compute the partial derivative for wave stretching + CALL Calc_Current( InitInp, 0.0_SiKi, InitInp%WtrDpth, InitInp%DirRoot, CurrVxi0, CurrVyi0 ) + CALL Calc_Current( InitInp, -SmllNmbr, InitInp%WtrDpth, InitInp%DirRoot, CurrVxiS, CurrVyiS ) + + InitOut%PCurrVxiPz0 = ( CurrVxi0 - CurrVxiS )/SmllNmbr ! xi-direction + InitOut%PCurrVyiPz0 = ( CurrVyi0 - CurrVyiS )/SmllNmbr ! yi-direction + + + u%DummyInput = 0.0 + p%DT = Interval + x%DummyContState = 0.0 + xd%DummyDiscState = 0.0 + z%DummyConstrState = 0.0 + OtherState%DummyOtherState = 0 + y%DummyOutput = 0.0 + m%DummyMiscVar = 0 + +END SUBROUTINE Current_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Current_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Current_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Current_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Current_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Current_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Current_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Current_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(Current_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Current_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 + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL Current_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL Current_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL Current_DestroyContState( x, ErrStat, ErrMsg ) + CALL Current_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL Current_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL Current_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL Current_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL Current_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE Current_End +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE Current +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/Current.txt b/OpenFAST/modules/hydrodyn/src/Current.txt new file mode 100644 index 000000000..5008b1b0a --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Current.txt @@ -0,0 +1,88 @@ +################################################################################################################################### +# Registry for Waves in the FAST Modularization Framework +# This Registry file is used to create MODULE Current_Types which contains all of the user-defined types needed in Current. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Current/Current InitInputType SiKi CurrSSV0 - - - "" - +typedef ^ ^ CHARACTER(80) CurrSSDirChr - - - "" - +typedef ^ ^ SiKi CurrSSDir - - - "" - +typedef ^ ^ SiKi CurrNSRef - - - "" - +typedef ^ ^ SiKi CurrNSV0 - - - "" - +typedef ^ ^ SiKi CurrNSDir - - - "" - +typedef ^ ^ SiKi CurrDIV - - - "" - +typedef ^ ^ SiKi CurrDIDir - - - "" - +typedef ^ ^ INTEGER CurrMod - - - "" - +typedef ^ ^ SiKi WtrDpth - - - "" - +typedef ^ ^ SiKi MorisonNodezi {:} - - "" - +typedef ^ ^ INTEGER NMorisonNodes - - - "" - +typedef ^ ^ CHARACTER(1024) DirRoot - "" - "" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType SiKi CurrVxi {:} - - "" - +typedef ^ ^ SiKi CurrVyi {:} - - "" - +typedef ^ ^ SiKi PCurrVxiPz0 - - - "" - +typedef ^ ^ SiKi PCurrVyiPz0 - - - "" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# +# +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType IntKi 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/optimization 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 DbKi DT - - - "Time step for continuous state integration and discrete state update" seconds +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +#typedef^ InputType MeshType MeshedInput - - - "Meshed input data" - +# Define inputs that are not on this mesh here: +typedef ^ InputType SiKi DummyInput - - - "Remove this variable if you have input data" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +#typedef^ OutputType MeshType MeshedOutput - - - "Meshed output data" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType SiKi DummyOutput - - - "Remove this variable if you have output data" - \ No newline at end of file diff --git a/OpenFAST/modules/hydrodyn/src/Current_Types.f90 b/OpenFAST/modules/hydrodyn/src/Current_Types.f90 new file mode 100644 index 000000000..f262434bc --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Current_Types.f90 @@ -0,0 +1,1906 @@ +!STARTOFREGISTRYGENERATEDFILE 'Current_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 +!********************************************************************************************************************************* +! Current_Types +!................................................................................................................................. +! This file is part of Current. +! +! 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 Current. 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 Current_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Current_InitInputType ======= + TYPE, PUBLIC :: Current_InitInputType + REAL(SiKi) :: CurrSSV0 !< [-] + CHARACTER(80) :: CurrSSDirChr !< [-] + REAL(SiKi) :: CurrSSDir !< [-] + REAL(SiKi) :: CurrNSRef !< [-] + REAL(SiKi) :: CurrNSV0 !< [-] + REAL(SiKi) :: CurrNSDir !< [-] + REAL(SiKi) :: CurrDIV !< [-] + REAL(SiKi) :: CurrDIDir !< [-] + INTEGER(IntKi) :: CurrMod !< [-] + REAL(SiKi) :: WtrDpth !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: MorisonNodezi !< [-] + INTEGER(IntKi) :: NMorisonNodes !< [-] + CHARACTER(1024) :: DirRoot !< [-] + END TYPE Current_InitInputType +! ======================= +! ========= Current_InitOutputType ======= + TYPE, PUBLIC :: Current_InitOutputType + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: CurrVxi !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: CurrVyi !< [-] + REAL(SiKi) :: PCurrVxiPz0 !< [-] + REAL(SiKi) :: PCurrVyiPz0 !< [-] + END TYPE Current_InitOutputType +! ======================= +! ========= Current_ContinuousStateType ======= + TYPE, PUBLIC :: Current_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Current_ContinuousStateType +! ======================= +! ========= Current_DiscreteStateType ======= + TYPE, PUBLIC :: Current_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE Current_DiscreteStateType +! ======================= +! ========= Current_ConstraintStateType ======= + TYPE, PUBLIC :: Current_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Current_ConstraintStateType +! ======================= +! ========= Current_OtherStateType ======= + TYPE, PUBLIC :: Current_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE Current_OtherStateType +! ======================= +! ========= Current_MiscVarType ======= + TYPE, PUBLIC :: Current_MiscVarType + REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE Current_MiscVarType +! ======================= +! ========= Current_ParameterType ======= + TYPE, PUBLIC :: Current_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration and discrete state update [seconds] + END TYPE Current_ParameterType +! ======================= +! ========= Current_InputType ======= + TYPE, PUBLIC :: Current_InputType + REAL(SiKi) :: DummyInput !< Remove this variable if you have input data [-] + END TYPE Current_InputType +! ======================= +! ========= Current_OutputType ======= + TYPE, PUBLIC :: Current_OutputType + REAL(SiKi) :: DummyOutput !< Remove this variable if you have output data [-] + END TYPE Current_OutputType +! ======================= +CONTAINS + SUBROUTINE Current_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Current_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 = 'Current_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%CurrSSV0 = SrcInitInputData%CurrSSV0 + DstInitInputData%CurrSSDirChr = SrcInitInputData%CurrSSDirChr + DstInitInputData%CurrSSDir = SrcInitInputData%CurrSSDir + DstInitInputData%CurrNSRef = SrcInitInputData%CurrNSRef + DstInitInputData%CurrNSV0 = SrcInitInputData%CurrNSV0 + DstInitInputData%CurrNSDir = SrcInitInputData%CurrNSDir + DstInitInputData%CurrDIV = SrcInitInputData%CurrDIV + DstInitInputData%CurrDIDir = SrcInitInputData%CurrDIDir + DstInitInputData%CurrMod = SrcInitInputData%CurrMod + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth +IF (ALLOCATED(SrcInitInputData%MorisonNodezi)) THEN + i1_l = LBOUND(SrcInitInputData%MorisonNodezi,1) + i1_u = UBOUND(SrcInitInputData%MorisonNodezi,1) + IF (.NOT. ALLOCATED(DstInitInputData%MorisonNodezi)) THEN + ALLOCATE(DstInitInputData%MorisonNodezi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MorisonNodezi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%MorisonNodezi = SrcInitInputData%MorisonNodezi +ENDIF + DstInitInputData%NMorisonNodes = SrcInitInputData%NMorisonNodes + DstInitInputData%DirRoot = SrcInitInputData%DirRoot + END SUBROUTINE Current_CopyInitInput + + SUBROUTINE Current_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Current_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%MorisonNodezi)) THEN + DEALLOCATE(InitInputData%MorisonNodezi) +ENDIF + END SUBROUTINE Current_DestroyInitInput + + SUBROUTINE Current_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(Current_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 = 'Current_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 + Re_BufSz = Re_BufSz + 1 ! CurrSSV0 + Int_BufSz = Int_BufSz + 1*LEN(InData%CurrSSDirChr) ! CurrSSDirChr + Re_BufSz = Re_BufSz + 1 ! CurrSSDir + Re_BufSz = Re_BufSz + 1 ! CurrNSRef + Re_BufSz = Re_BufSz + 1 ! CurrNSV0 + Re_BufSz = Re_BufSz + 1 ! CurrNSDir + Re_BufSz = Re_BufSz + 1 ! CurrDIV + Re_BufSz = Re_BufSz + 1 ! CurrDIDir + Int_BufSz = Int_BufSz + 1 ! CurrMod + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Int_BufSz = Int_BufSz + 1 ! MorisonNodezi allocated yes/no + IF ( ALLOCATED(InData%MorisonNodezi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MorisonNodezi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MorisonNodezi) ! MorisonNodezi + END IF + Int_BufSz = Int_BufSz + 1 ! NMorisonNodes + Int_BufSz = Int_BufSz + 1*LEN(InData%DirRoot) ! DirRoot + 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%CurrSSV0 + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%CurrSSDirChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%CurrSSDirChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%CurrSSDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CurrNSRef + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CurrNSV0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CurrNSDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CurrDIV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CurrDIDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CurrMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%MorisonNodezi) ) 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%MorisonNodezi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MorisonNodezi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MorisonNodezi,1), UBOUND(InData%MorisonNodezi,1) + ReKiBuf(Re_Xferred) = InData%MorisonNodezi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NMorisonNodes + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%DirRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%DirRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Current_PackInitInput + + SUBROUTINE Current_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(Current_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 = 'Current_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%CurrSSV0 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%CurrSSDirChr) + OutData%CurrSSDirChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CurrSSDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrNSRef = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrNSV0 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrNSDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrDIV = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrDIDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%CurrMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WtrDpth = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MorisonNodezi 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%MorisonNodezi)) DEALLOCATE(OutData%MorisonNodezi) + ALLOCATE(OutData%MorisonNodezi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MorisonNodezi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MorisonNodezi,1), UBOUND(OutData%MorisonNodezi,1) + OutData%MorisonNodezi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NMorisonNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%DirRoot) + OutData%DirRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Current_UnPackInitInput + + SUBROUTINE Current_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Current_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 = 'Current_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%CurrVxi)) THEN + i1_l = LBOUND(SrcInitOutputData%CurrVxi,1) + i1_u = UBOUND(SrcInitOutputData%CurrVxi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%CurrVxi)) THEN + ALLOCATE(DstInitOutputData%CurrVxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%CurrVxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%CurrVxi = SrcInitOutputData%CurrVxi +ENDIF +IF (ALLOCATED(SrcInitOutputData%CurrVyi)) THEN + i1_l = LBOUND(SrcInitOutputData%CurrVyi,1) + i1_u = UBOUND(SrcInitOutputData%CurrVyi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%CurrVyi)) THEN + ALLOCATE(DstInitOutputData%CurrVyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%CurrVyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%CurrVyi = SrcInitOutputData%CurrVyi +ENDIF + DstInitOutputData%PCurrVxiPz0 = SrcInitOutputData%PCurrVxiPz0 + DstInitOutputData%PCurrVyiPz0 = SrcInitOutputData%PCurrVyiPz0 + END SUBROUTINE Current_CopyInitOutput + + SUBROUTINE Current_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Current_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%CurrVxi)) THEN + DEALLOCATE(InitOutputData%CurrVxi) +ENDIF +IF (ALLOCATED(InitOutputData%CurrVyi)) THEN + DEALLOCATE(InitOutputData%CurrVyi) +ENDIF + END SUBROUTINE Current_DestroyInitOutput + + SUBROUTINE Current_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(Current_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 = 'Current_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 + Int_BufSz = Int_BufSz + 1 ! CurrVxi allocated yes/no + IF ( ALLOCATED(InData%CurrVxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CurrVxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CurrVxi) ! CurrVxi + END IF + Int_BufSz = Int_BufSz + 1 ! CurrVyi allocated yes/no + IF ( ALLOCATED(InData%CurrVyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CurrVyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CurrVyi) ! CurrVyi + END IF + Re_BufSz = Re_BufSz + 1 ! PCurrVxiPz0 + Re_BufSz = Re_BufSz + 1 ! PCurrVyiPz0 + 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%CurrVxi) ) 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%CurrVxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CurrVxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CurrVxi,1), UBOUND(InData%CurrVxi,1) + ReKiBuf(Re_Xferred) = InData%CurrVxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CurrVyi) ) 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%CurrVyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CurrVyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CurrVyi,1), UBOUND(InData%CurrVyi,1) + ReKiBuf(Re_Xferred) = InData%CurrVyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%PCurrVxiPz0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PCurrVyiPz0 + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_PackInitOutput + + SUBROUTINE Current_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(Current_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 = 'Current_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CurrVxi 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%CurrVxi)) DEALLOCATE(OutData%CurrVxi) + ALLOCATE(OutData%CurrVxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CurrVxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CurrVxi,1), UBOUND(OutData%CurrVxi,1) + OutData%CurrVxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CurrVyi 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%CurrVyi)) DEALLOCATE(OutData%CurrVyi) + ALLOCATE(OutData%CurrVyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CurrVyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CurrVyi,1), UBOUND(OutData%CurrVyi,1) + OutData%CurrVyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%PCurrVxiPz0 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%PCurrVyiPz0 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackInitOutput + + SUBROUTINE Current_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Current_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 = 'Current_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Current_CopyContState + + SUBROUTINE Current_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Current_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyContState + + SUBROUTINE Current_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(Current_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 = 'Current_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 Current_PackContState + + SUBROUTINE Current_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(Current_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 = 'Current_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackContState + + SUBROUTINE Current_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Current_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 = 'Current_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE Current_CopyDiscState + + SUBROUTINE Current_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Current_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyDiscState + + SUBROUTINE Current_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(Current_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 = 'Current_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 Current_PackDiscState + + SUBROUTINE Current_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(Current_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 = 'Current_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackDiscState + + SUBROUTINE Current_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Current_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 = 'Current_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Current_CopyConstrState + + SUBROUTINE Current_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Current_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyConstrState + + SUBROUTINE Current_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(Current_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 = 'Current_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 Current_PackConstrState + + SUBROUTINE Current_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(Current_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 = 'Current_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackConstrState + + SUBROUTINE Current_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Current_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 = 'Current_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Current_CopyOtherState + + SUBROUTINE Current_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Current_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyOtherState + + SUBROUTINE Current_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(Current_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 = 'Current_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Current_PackOtherState + + SUBROUTINE Current_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(Current_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 = 'Current_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Current_UnPackOtherState + + SUBROUTINE Current_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Current_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 = 'Current_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE Current_CopyMisc + + SUBROUTINE Current_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Current_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyMisc + + SUBROUTINE Current_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(Current_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 = 'Current_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 Current_PackMisc + + SUBROUTINE Current_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(Current_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 = 'Current_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 Current_UnPackMisc + + SUBROUTINE Current_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Current_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 = 'Current_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + END SUBROUTINE Current_CopyParam + + SUBROUTINE Current_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Current_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyParam + + SUBROUTINE Current_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(Current_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 = 'Current_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 + Db_BufSz = Db_BufSz + 1 ! DT + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Current_PackParam + + SUBROUTINE Current_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(Current_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 = 'Current_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Current_UnPackParam + + SUBROUTINE Current_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_InputType), INTENT(IN) :: SrcInputData + TYPE(Current_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Current_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%DummyInput = SrcInputData%DummyInput + END SUBROUTINE Current_CopyInput + + SUBROUTINE Current_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Current_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyInput + + SUBROUTINE Current_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(Current_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 = 'Current_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 + Re_BufSz = Re_BufSz + 1 ! DummyInput + 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%DummyInput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_PackInput + + SUBROUTINE Current_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(Current_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Current_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 + OutData%DummyInput = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackInput + + SUBROUTINE Current_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Current_OutputType), INTENT(IN) :: SrcOutputData + TYPE(Current_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Current_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%DummyOutput = SrcOutputData%DummyOutput + END SUBROUTINE Current_CopyOutput + + SUBROUTINE Current_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Current_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Current_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Current_DestroyOutput + + SUBROUTINE Current_PackOutput( 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(Current_OutputType), 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 = 'Current_PackOutput' + ! 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 ! DummyOutput + 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%DummyOutput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_PackOutput + + SUBROUTINE Current_UnPackOutput( 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(Current_OutputType), 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 = 'Current_UnPackOutput' + ! 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%DummyOutput = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Current_UnPackOutput + + + SUBROUTINE Current_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Current_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Current_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Current_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Current_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Current_Input_ExtrapInterp + + + SUBROUTINE Current_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%DummyInput - u2%DummyInput) + u_out%DummyInput = u1%DummyInput + b * ScaleFactor + END SUBROUTINE Current_Input_ExtrapInterp1 + + + SUBROUTINE Current_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Current_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%DummyInput - u2%DummyInput) + t(2)**2*(-u1%DummyInput + u3%DummyInput))* scaleFactor + c = ( (t(2)-t(3))*u1%DummyInput + t(3)*u2%DummyInput - t(2)*u3%DummyInput ) * scaleFactor + u_out%DummyInput = u1%DummyInput + b + c * t_out + END SUBROUTINE Current_Input_ExtrapInterp2 + + + SUBROUTINE Current_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Current_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Current_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Current_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Current_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Current_Output_ExtrapInterp + + + SUBROUTINE Current_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(y1%DummyOutput - y2%DummyOutput) + y_out%DummyOutput = y1%DummyOutput + b * ScaleFactor + END SUBROUTINE Current_Output_ExtrapInterp1 + + + SUBROUTINE Current_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Current_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Current_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(y1%DummyOutput - y2%DummyOutput) + t(2)**2*(-y1%DummyOutput + y3%DummyOutput))* scaleFactor + c = ( (t(2)-t(3))*y1%DummyOutput + t(3)*y2%DummyOutput - t(2)*y3%DummyOutput ) * scaleFactor + y_out%DummyOutput = y1%DummyOutput + b + c * t_out + END SUBROUTINE Current_Output_ExtrapInterp2 + +END MODULE Current_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn.f90 b/OpenFAST/modules/hydrodyn/src/HydroDyn.f90 new file mode 100644 index 000000000..9f1b60fb8 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn.f90 @@ -0,0 +1,3365 @@ +!********************************************************************************************************************************** +! The HydroDyn and HydroDyn_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. HydroDyns_Types will be auto-generated based on a description of the variables for the module. +! +! "HydroDyn" should be replaced with the name of your module. Example: HydroDyn +! "HydroDyn" (in HydroDyn_*) should be replaced with the module name or an abbreviation of it. Example: HD +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 HydroDyn + + USE HydroDyn_Types + USE NWTC_Library + USE WAMIT + USE WAMIT2 + USE HydroDyn_Input + USE HydroDyn_Output + USE Current + USE Waves2 +#ifdef USE_FIT + USE FIT_MODULES + USE FIT_Types +#endif + IMPLICIT NONE + + PRIVATE + + + TYPE(ProgDesc), PARAMETER :: HydroDyn_ProgDesc = ProgDesc( 'HydroDyn', '', '' ) + + + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: HydroDyn_Init ! Initialization routine + PUBLIC :: HydroDyn_End ! Ending routine (includes clean up) + + PUBLIC :: HydroDyn_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: HydroDyn_CalcOutput ! Routine for computing outputs + + PUBLIC :: HydroDyn_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: HydroDyn_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + !PUBLIC :: HydroDyn_UpdateDiscState ! Tight coupling routine for updating discrete states + + PUBLIC :: HD_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 :: HD_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 :: HD_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 :: HD_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 :: HD_GetOP !< Routine to pack the operating point values (for linearization) into arrays + + CONTAINS + +SUBROUTINE WvStretch_Init(WaveStMod, WtrDpth, NStepWave, NNodes, & + NWaveElev, WaveElev, WaveKinzi, WaveTime, & + WaveVel0, WaveAcc0, WaveDynP0, & + WavePVel0, WavePAcc0, WavePDynP0, & + WaveVel , WaveAcc , WaveDynP , & + nodeInWater, ErrStat, ErrMsg ) + + + INTEGER, INTENT(IN ) :: WaveStMod + REAL(SiKi), INTENT(IN ) :: WtrDpth + INTEGER, INTENT(IN ) :: NStepWave + INTEGER, INTENT(IN ) :: NNodes !< TODO: WHY are there both NNodes and NWaveElev ??? GJH 2/1/2016 + INTEGER, INTENT(IN ) :: NWaveElev + REAL(SiKi), INTENT(IN ) :: WaveElev(0:,:) + REAL(SiKi), INTENT(IN ) :: WaveKinzi(:) + REAL(SiKi), INTENT(IN ) :: WaveTime(0:) + REAL(SiKi), INTENT(IN ) :: WaveVel0(0:,:,:) !< Wave velocity in Global coordinate system at Z = 0. Each point in this array has a corresponding entry (same index #) in the WaveVel array + REAL(SiKi), INTENT(IN ) :: WaveAcc0(0:,:,:) + REAL(SiKi), INTENT(IN ) :: WaveDynP0(0:,:) + REAL(SiKi), INTENT(IN ) :: WavePVel0(0:,:,:) !< Wave velocity in Global coordinate system at Z = 0. Each point in this array has a corresponding entry (same index #) in the WaveVel array + REAL(SiKi), INTENT(IN ) :: WavePAcc0(0:,:,:) + REAL(SiKi), INTENT(IN ) :: WavePDynP0(0:,:) + REAL(SiKi), INTENT(INOUT) :: WaveVel(0:,:,:) + REAL(SiKi), INTENT(INOUT) :: WaveAcc(0:,:,:) + REAL(SiKi), INTENT(INOUT) :: WaveDynP(0:,:) + INTEGER(IntKi), INTENT(INOUT) :: nodeInWater(0:,:) + 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, J !< Local loop counters + REAL(SiKi) :: wavekinzloc ,WavePVel0loc + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + + DO I = 0,NStepWave-1 ! Loop through all time steps + + DO J = 1,NNodes + + SELECT CASE ( WaveStMod ) ! Which model are we using to extrapolate the incident wave kinematics to the instantaneous free surface? + + CASE ( 0 ) ! None = no stretching. + ! Since we have no stretching, the wave kinematics between the seabed and + ! the mean sea level are left unchanged; below the seabed or above the + ! mean sea level, the wave kinematics are zero: + IF ( ( WaveKinzi(J) < -WtrDpth ) .OR. ( WaveKinzi(J) > 0.0 ) ) THEN ! .TRUE. if the elevation of the point defined by WaveKinzi(J) lies below the seabed or above mean sea level (exclusive) + + WaveDynP (I,J ) = 0.0 + WaveVel (I,J,:) = 0.0 + WaveAcc (I,J,:) = 0.0 + nodeInWater(I,J ) = 0 + ELSE + nodeInWater(I,J ) = 1 + END IF + CASE ( 1 ) ! Vertical stretching. + + + ! Vertical stretching says that the wave kinematics above the mean sea level + ! equal the wave kinematics at the mean sea level. The wave kinematics + ! below the mean sea level are left unchanged: + IF ( ( WaveKinzi(J) < -WtrDpth ) .OR. ( WaveKinzi(J) > WaveElev(I,J) ) ) THEN ! .TRUE. if the elevation of the point defined by WaveKinzi(J) lies below the seabed or above the instantaneous wave elevation (exclusive) + + WaveDynP (I,J ) = 0.0 + WaveVel (I,J,:) = 0.0 + WaveAcc (I,J,:) = 0.0 + nodeInWater(I,J ) = 0 + ELSE + nodeInWater(I,J ) = 1 + IF ( WaveKinzi(J) >= 0.0_ReKi ) THEN + ! Set the wave kinematics to the kinematics at mean sea level for locations above MSL, but below the wave elevation. + WaveDynP (I,J ) = WaveDynP0 (I,J ) + WaveVel (I,J,:) = WaveVel0 (I,J,:) + WaveAcc (I,J,:) = WaveAcc0 (I,J,:) + END IF + ! Otherwise, do nothing because the kinematics have already be set correctly via the various Waves modules + END IF + + + + + CASE ( 2 ) ! Extrapolation stretching. + + + ! Extrapolation stretching uses a linear Taylor expansion of the wave + ! kinematics (and their partial derivatives with respect to z) at the mean + ! sea level to find the wave kinematics above the mean sea level. The + ! wave kinematics below the mean sea level are left unchanged: + + + IF ( ( WaveKinzi(J) < -WtrDpth ) .OR. ( WaveKinzi(J) > WaveElev(I,J) ) ) THEN ! .TRUE. if the elevation of the point defined by WaveKinzi(J) lies below the seabed or above the instantaneous wave elevation (exclusive) + + WaveDynP (I,J ) = 0.0 + WaveVel (I,J,:) = 0.0 + WaveAcc (I,J,:) = 0.0 + nodeInWater(I,J ) = 0 + ELSE + nodeInWater(I,J ) = 1 + wavekinzloc = WaveKinzi(J) + WavePVel0loc = WavePVel0 (I,J,1) + IF ( WaveKinzi(J) >= 0.0_ReKi ) THEN + ! Set the wave kinematics to the kinematics at mean sea level for locations above MSL, but below the wave elevation. + WaveDynP (I,J ) = WaveDynP0 (I,J ) + WaveKinzi(J)*WavePDynP0 (I,J ) + WaveVel (I,J,:) = WaveVel0 (I,J,:) + WaveKinzi(J)*WavePVel0 (I,J,:) + WaveAcc (I,J,:) = WaveAcc0 (I,J,:) + WaveKinzi(J)*WavePAcc0 (I,J,:) + END IF + ! Otherwise, do nothing because the kinematics have already be set correctly via the various Waves modules + END IF + + + CASE ( 3 ) ! Wheeler stretching. + + + ! Wheeler stretching says that wave kinematics calculated using Airy theory + ! at the mean sea level should actually be applied at the instantaneous + ! free surface and that Airy wave kinematics computed at locations between + ! the seabed and the mean sea level should be shifted vertically to new + ! locations in proportion to their elevation above the seabed. + ! + ! Computing the wave kinematics with Wheeler stretching requires that first + ! say that the wave kinematics we computed at the elevations defined by + ! the WaveKinzi0Prime(:) array are actual applied at the elevations found + ! by stretching the elevations in the WaveKinzi0Prime(:) array using the + ! instantaneous wave elevation--these new elevations are stored in the + ! WaveKinzi0St(:) array. Next, we interpolate the wave kinematics + ! computed without stretching to the desired elevations (defined in the + ! WaveKinzi(:) array) using the WaveKinzi0St(:) array: + + + ENDSELECT + END DO ! J - All points where the incident wave kinematics will be computed + END DO ! I - All time steps + + ! Set the ending timestep to the same as the first timestep + WaveDynP (NStepWave,: ) = WaveDynP (0,: ) + WaveVel (NStepWave,:,:) = WaveVel (0,:,:) + WaveAcc (NStepWave,:,:) = WaveAcc (0,:,:) + +END SUBROUTINE WvStretch_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(HydroDyn_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine. TODO: This does not follow the template due to the interface of HydroDyn_CopyInitInput() + TYPE(HydroDyn_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(HydroDyn_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(HydroDyn_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(HydroDyn_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(HydroDyn_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(HydroDyn_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(HydroDyn_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) HydroDyn_UpdateStates() is called in loose coupling & + !! (2) HydroDyn_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(HydroDyn_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + CHARACTER(1024) :: SummaryName ! name of the HydroDyn summary file + TYPE(HydroDyn_InitInputType) :: InitLocal ! Local version of the initialization data, needed because the framework data (InitInp) is read-only + TYPE(Waves_InitOutputType) :: Waves_InitOut ! Initialization Outputs from the Waves module initialization +! TYPE(Waves2_InitOutputType) :: Waves2_InitOut ! Initialization Outputs from the Waves2 module initialization + TYPE(Current_InitOutputType) :: Current_InitOut ! Initialization Outputs from the Current module initialization +! LOGICAL :: hasWAMITOuts ! Are there any WAMIT-related outputs +! LOGICAL :: hasMorisonOuts ! Are there any Morison-related outputs +! INTEGER :: numHydroOuts ! total number of WAMIT and Morison outputs + INTEGER :: I, J ! Generic counters + REAL(SiKi) :: WaveNmbr ! Wavenumber of the current frequency component (1/meter) + ! These are dummy variables to satisfy the framework, but are not used + + TYPE(Waves_InputType) :: Waves_u ! Waves module initial guess for the input; the input mesh is not defined because it is not used by the waves module + TYPE(Waves_ParameterType) :: Waves_p ! Waves module parameters + TYPE(Waves_ContinuousStateType) :: Waves_x ! Waves module initial continuous states + TYPE(Waves_DiscreteStateType) :: Waves_xd ! Waves module discrete states + TYPE(Waves_ConstraintStateType) :: Waves_z ! Waves module initial guess of the constraint states + TYPE(Waves_OtherStateType) :: WavesOtherState ! Waves module other states + TYPE(Waves_MiscVarType) :: Waves_m ! Waves module misc/optimization data + TYPE(Waves_OutputType) :: Waves_y ! Waves module outputs + + + TYPE(Current_InputType) :: Current_u ! Current module initial guess for the input; the input mesh is not defined because it is not used by the Current module + TYPE(Current_ParameterType) :: Current_p ! Current module parameters + TYPE(Current_ContinuousStateType) :: Current_x ! Current module initial continuous states + TYPE(Current_DiscreteStateType) :: Current_xd ! Current module discrete states + TYPE(Current_ConstraintStateType) :: Current_z ! Current module initial guess of the constraint states + TYPE(Current_OtherStateType) :: CurrentOtherState ! Current module other states + TYPE(Current_OutputType) :: Current_y ! Current module outputs + TYPE(Current_MiscVarType) :: Current_m ! Current module misc/optimization data + + +#ifdef USE_FIT + ! FIT - related data + TYPE(FIT_InitInputType) :: FITInitData + TYPE(FIT_InputType) :: FIT_u ! FIT module initial guess for the input; the input mesh is not defined because it is not used by the waves module + TYPE(FIT_ParameterType) :: FIT_p ! FIT module parameters + TYPE(FIT_ContinuousStateType) :: FIT_x ! FIT module initial continuous states + TYPE(FIT_DiscreteStateType) :: FIT_xd ! FIT module discrete states + TYPE(FIT_ConstraintStateType) :: FIT_z ! FIT module initial guess of the constraint states + TYPE(FIT_OtherStateType) :: FIT_OtherState ! FIT module other/optimization states + TYPE(FIT_OutputType) :: FIT_y ! FIT module outputs + TYPE(FIT_InitOutputType) :: FIT_InitOut ! Initialization Outputs from the FIT module initialization +#endif + + Real(ReKi) :: Np + Real(ReKi) :: dftreal + Real(ReKi) :: dftimag + + ! Wave Stretching Data + REAL(SiKi), ALLOCATABLE :: tmpWaveKinzi(: ) + INTEGER :: tmpNWaveElev + REAL(SiKi), ALLOCATABLE :: tmpWaveElevxi(: ) + REAL(SiKi), ALLOCATABLE :: tmpWaveElevyi(: ) + REAL(SiKi), ALLOCATABLE :: WaveElevSt (:,: ) + REAL(SiKi), ALLOCATABLE :: WaveVel0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveAcc0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveDynP0 (:,: ) + REAL(SiKi), ALLOCATABLE :: WaveVel2S0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveAcc2S0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveDynP2S0 (:,: ) + REAL(SiKi), ALLOCATABLE :: WaveVel2D0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveAcc2D0 (:,:,:) + REAL(SiKi), ALLOCATABLE :: WaveDynP2D0 (:,: ) + + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Init' + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + p%UnOutFile = -1 !bjj: this was being written to the screen when I had an error in my HD input file, so I'm going to initialize here. + +#ifdef BETA_BUILD + CALL DispBetaNotice( "This is a beta version of HydroDyn and is for testing purposes only."//NewLine//"This version includes user waves, WaveMod=6 and the ability to write example user waves." ) +#endif + ! Copy the initialization input data to a local version because the framework states InitInp should have INTENT (IN), but due to an issue the the + ! copy routine, we needed to make it (INOUT), which means we actually don't need this local version!! I'm leaving this with the idea that the + ! copy routine will get modified so that InitInp can have INTENT (IN) again. GJH 4-Apr-2013 + + CALL HydroDyn_CopyInitInput( InitInp, InitLocal, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + + ! Display the module information + + CALL DispNVD( HydroDyn_ProgDesc ) + + + + + IF ( InitInp%UseInputFile ) THEN + + + ! Parse all HydroDyn-related input files and populate the *_InitInputType derived types + + CALL HydroDynInput_GetInput( InitLocal, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + END IF + + + ! Start with the glue code's timestep. This may be altered in the Input file processing, and we will check that afterwards. + + InitLocal%DT = Interval + + + ! Verify all the necessary initialization data. Do this at the HydroDynInput module-level + ! because the HydroDynInput module is also responsible for parsing all this + ! initialization data from a file + + + CALL HydroDynInput_ProcessInitData( InitLocal, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Since the Convolution Radiation module is currently the only module which requires knowledge of the time step size, + ! we will set Hydrodyn's time step to be that of the Convolution radiation module if it is being used. Otherwise, we + ! will set it to be equal to the glue-codes + IF ((Initlocal%PotMod == 1) .AND. (Initlocal%WAMIT%RdtnMod == 1) ) THEN + + + p%DT = InitLocal%WAMIT%Conv_Rdtn%RdtnDT + +#ifdef USE_FIT + ELSE IF (Initlocal%PotMod == 2) THEN + ! This is the FIT potential flow model and the time step needs to be >= the driver timestep, and and integer multiple if larger + ! We example WaveDT for this timestep size because FIT is tied to WaveDT + IF ( ( .NOT. EqualRealNos(mod(real(Initlocal%Waves%WaveDT,ReKi), real(Interval,ReKi)) , 0.0_ReKi) ) .OR. Initlocal%Waves%WaveDT <= 0.0_DbKi ) THEn + CALL SetErrStat(ErrID_Fatal,'The value of WaveDT is not greater than zero and an integer multiple of the glue code timestep.',ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + ELSE + p%DT = Interval ! If the above check is ok, then we can still set the module DT to the glue-code dt + + END IF +#endif + + ELSE + + p%DT = Interval + END IF + + ! Open a summary of the HydroDyn Initialization. Note: OutRootName must be set by the caller because there may not be an input file to obtain this rootname from. + + IF ( InitLocal%HDSum ) THEN + + SummaryName = TRIM(InitLocal%OutRootName)//'.HD.sum' + CALL HDOut_OpenSum( InitLocal%UnSum, SummaryName, HydroDyn_ProgDesc, ErrStat2, ErrMsg2 ) !this must be called before the Waves_Init() routine so that the appropriate wave data can be written to the summary file + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ELSE + + InitLocal%UnSum = -1 + + END IF + + ! Copy Additional preload, stiffness, and damping to the parameters + p%AddF0 = InitLocal%AddF0 + p%AddCLin = InitLocal%AddCLin + p%AddBLin = InitLocal%AddBLin + p%AddBQuad = InitLocal%AddBQuad + + + ! Set summary unit number in Waves, Radiation, and Morison initialization input data + + InitLocal%Waves%UnSum = InitLocal%UnSum + InitLocal%WAMIT%Conv_Rdtn%UnSum = InitLocal%UnSum + InitLocal%Morison%UnSum = InitLocal%UnSum + + + ! Now call each sub-module's *_Init subroutine + ! to fully initialize each sub-module based on the necessary initialization data + + + ! Initialize Current module + + CALL Current_Init(InitLocal%Current, Current_u, Current_p, Current_x, Current_xd, Current_z, CurrentOtherState, & + Current_y, Current_m, Interval, Current_InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Verify that Current_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'Current Module attempted to change timestep interval, but this is not allowed. Current Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + + ! Move initialization output data from Current module into the initialization input data for the Waves module + + IF (ALLOCATED(Current_InitOut%CurrVxi)) CALL Move_Alloc( Current_InitOut%CurrVxi, InitLocal%Waves%CurrVxi ) + IF (ALLOCATED(Current_InitOut%CurrVyi)) CALL Move_Alloc( Current_InitOut%CurrVyi, InitLocal%Waves%CurrVyi ) + + InitLocal%Waves%PCurrVxiPz0 = Current_InitOut%PCurrVxiPz0 + InitLocal%Waves%PCurrVyiPz0 = Current_InitOut%PCurrVyiPz0 + + + ! Copy the WaveElevXY data in from the HydroDyn InitLocal (already a copy of InitInp) + + IF (ALLOCATED(InitLocal%WaveElevXY)) CALL MOVE_ALLOC(InitLocal%WaveElevXY, InitLocal%Waves%WaveElevXY) + + ! Initialize Waves module + +!========================================================================== +! Initialize Wave Stretching data for 1st Order Waves +!========================================================================== + IF (InitLocal%Waves%WaveStMod > 0) THEN + ! Allocate the temporary storage array for the WvKinxi + ALLOCATE ( tmpWaveKinzi(InitLocal%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for tmpWaveKinzi array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + + + + tmpWaveKinzi = InitLocal%Waves%WaveKinzi + InitLocal%Waves%WaveKinzi = 0.0_ReKi ! Force all zi coordinates to 0.0 for this version of the Waves initialization + + + ! We will use the user-requested wave elevation arrays to compute the wave elevations for stretching at ALL node locations. + ! We are going to store the user-requested wave elevation output locations so that we can restore them after we done. + IF (InitLocal%Waves%NWaveElev > 0) THEN + tmpNWaveElev = InitLocal%Waves%NWaveElev + CALL MOVE_ALLOC( InitLocal%Waves%WaveElevxi, tmpWaveElevxi ) ! (from, to) + CALL MOVE_ALLOC( InitLocal%Waves%WaveElevyi, tmpWaveElevyi ) + END IF + + + ALLOCATE ( InitLocal%Waves%WaveElevxi(InitLocal%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for tmpWaveKinzi array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + ALLOCATE ( InitLocal%Waves%WaveElevyi(InitLocal%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for tmpWaveKinzi array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + + InitLocal%Waves%NWaveElev = InitLocal%Waves%NWaveKin + InitLocal%Waves%WaveElevxi = InitLocal%Waves%WaveKinxi + InitLocal%Waves%WaveElevyi = InitLocal%Waves%WaveKinyi + + + CALL Waves_Init(InitLocal%Waves, Waves_u, Waves_p, Waves_x, Waves_xd, Waves_z, WavesOtherState, & + Waves_y, Waves_m, Interval, Waves_InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Store the wave elevations coming out of the Waves_Init for use in the stretching calculations + ALLOCATE ( WaveElevSt(0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveElevSt array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + WaveElevSt = Waves_InitOut%WaveElev + + + ! We need to reset the wave elevation arrays + DEALLOCATE(InitLocal%Waves%WaveElevxi) + DEALLOCATE(InitLocal%Waves%WaveElevyi) + InitLocal%Waves%NWaveElev = tmpNWaveElev + + IF (InitLocal%Waves%NWaveElev > 0) THEN + CALL MOVE_ALLOC( tmpWaveElevxi, InitLocal%Waves%WaveElevxi ) ! (from, to) + CALL MOVE_ALLOC( tmpWaveElevyi, InitLocal%Waves%WaveElevyi ) + END IF + + ALLOCATE ( WaveDynP0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveVel0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveAcc0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc0.', ErrStat, ErrMsg, RoutineName) + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Copy the init output arrays into the MSL versions + WaveDynP0 = Waves_InitOut%WaveDynP + WaveAcc0 = Waves_InitOut%WaveAcc + WaveVel0 = Waves_InitOut%WaveVel + + + InitLocal%Waves%WaveKinzi = tmpWaveKinzi + + ! Deallocate data which will be allocated again within the Waves_Init routine + DEALLOCATE( Waves_InitOut%WaveDynP ) + DEALLOCATE( Waves_InitOut%WaveAcc ) + DEALLOCATE( Waves_InitOut%WaveVel ) + DEALLOCATE( Waves_InitOut%PWaveDynP0 ) + DEALLOCATE( Waves_InitOut%PWaveAcc0 ) + DEALLOCATE( Waves_InitOut%PWaveVel0 ) + DEALLOCATE( Waves_InitOut%WaveElevC0) + DEALLOCATE( Waves_InitOut%WaveDirArr) + DEALLOCATE( Waves_InitOut%WaveElev ) + DEALLOCATE( Waves_InitOut%WaveTime ) + DEALLOCATE( Waves_InitOut%NodeInWater ) + END IF +!========================================================================== + + CALL Waves_Init(InitLocal%Waves, Waves_u, Waves_p, Waves_x, Waves_xd, Waves_z, WavesOtherState, & + Waves_y, Waves_m, Interval, Waves_InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Verify that Waves_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'Waves Module attempted to change timestep interval, but this is not allowed. Waves Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + ! Copy the wave elevation time series corresponding to WaveElevXY to the output. + + IF (ALLOCATED(Waves_InitOut%WaveElevSeries)) CALL MOVE_ALLOC( Waves_InitOut%WaveElevSeries, InitOut%WaveElevSeries ) + IF (ALLOCATED(InitLocal%Waves%WaveElevXY)) CALL MOVE_ALLOC(InitLocal%Waves%WaveElevXY, InitLocal%WaveElevXY) ! move this back for waves2 later + + + ! Copy Waves initialization output into the initialization input type for the WAMIT module + p%NWaveElev = InitLocal%Waves%NWaveElev + p%NStepWave = Waves_InitOut%NStepWave + + CALL MOVE_ALLOC( Waves_InitOut%WaveTime, p%WaveTime ) + CALL MOVE_ALLOC( Waves_InitOut%WaveElev, p%WaveElev1 ) ! allocate p%WaveElev1, set p%WaveElev1 = Waves_InitOut%WaveElev, and deallocate Waves_InitOut%WaveElev + + ! Copy the first order wave elevation information to p%WaveElev1 so that we can output the total, first, and second order wave elevation separately + ALLOCATE ( p%WaveElev (0:p%NStepWave, p%NWaveElev ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Error allocating memory for the WaveElev array.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + p%WaveElev = p%WaveElev1 + + + + m%LastIndWave = 1 + + + IF ( InitLocal%Waves%WaveMod /= 6 ) THEN + + !---------------------------------- + ! Initialize Waves2 module + !---------------------------------- + + + IF (InitLocal%Waves2%WvDiffQTFF .OR. InitLocal%Waves2%WvSumQTFF ) THEN + ! Set a few things from the Waves module output + InitLocal%Waves2%NStepWave = Waves_InitOut%NStepWave + InitLocal%Waves2%NStepWave2 = Waves_InitOut%NStepWave2 + InitLocal%Waves2%WaveDOmega = Waves_InitOut%WaveDOmega + + ! Copy the WaveElevXY data in from the HydroDyn InitLocal, already a copy from InitInp + IF (ALLOCATED(InitLocal%WaveElevXY)) CALL MOVE_ALLOC(InitLocal%WaveElevXY, InitLocal%Waves2%WaveElevXY) + + ! Temporarily move arrays to init input for Waves2 (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%Waves2%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%Waves2%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%Waves2%WaveDirArr) + + !bjj: note that this doesn't get called if .not. (InitLocal%Waves2%WvDiffQTFF .OR. InitLocal%Waves2%WvSumQTFF), so p%waves2%* never get set + ! however, they get queried later in the code!!!! I've set these parameters in an "else" statement, below + +!========================================================================== +! Initialize Wave Stretching data for 2nd Order Waves +!========================================================================== + IF (InitLocal%Waves%WaveStMod > 0) THEN + ! Set the wave kinematics zi locations to zero to generate kinematics at MSL + InitLocal%Waves2%WaveKinzi = 0 + + ! We will use the user-requested wave elevation arrays to compute the wave elevations for stretching at ALL node locations. + ! We are going to store the user-requested wave elevation output locations so that we can restore them after we done. + IF (InitLocal%Waves2%NWaveElev > 0) THEN + tmpNWaveElev = InitLocal%Waves2%NWaveElev + CALL MOVE_ALLOC( InitLocal%Waves2%WaveElevxi, tmpWaveElevxi ) ! (from, to) + CALL MOVE_ALLOC( InitLocal%Waves2%WaveElevyi, tmpWaveElevyi ) + END IF + + + ALLOCATE ( InitLocal%Waves2%WaveElevxi(InitLocal%Waves2%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveElevxi array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + ALLOCATE ( InitLocal%Waves2%WaveElevyi(InitLocal%Waves2%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveElevyi array.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + + InitLocal%Waves2%NWaveElev = InitLocal%Waves2%NWaveKin + InitLocal%Waves2%WaveElevxi = InitLocal%Waves2%WaveKinxi + InitLocal%Waves2%WaveElevyi = InitLocal%Waves2%WaveKinyi + + CALL Waves2_Init(InitLocal%Waves2, m%u_Waves2, p%Waves2, x%Waves2, xd%Waves2, z%Waves2, OtherState%Waves2, & + y%Waves2, m%Waves2, Interval, InitOut%Waves2, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Store the wave elevations coming out of the Waves_Init for use in the stretching calculations + WaveElevSt = WaveElevSt + p%Waves2%WaveElev2 + + ! We need to reset the wave elevation arrays + DEALLOCATE(InitLocal%Waves2%WaveElevxi) + DEALLOCATE(InitLocal%Waves2%WaveElevyi) + InitLocal%Waves2%NWaveElev = tmpNWaveElev + + IF (InitLocal%Waves2%NWaveElev > 0) THEN + CALL MOVE_ALLOC( tmpWaveElevxi, InitLocal%Waves2%WaveElevxi ) ! (from, to) + CALL MOVE_ALLOC( tmpWaveElevyi, InitLocal%Waves2%WaveElevyi ) + END IF + + + ALLOCATE ( WaveDynP2D0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2D0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveVel2D0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2D0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveAcc2D0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2D0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveDynP2S0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2S0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveVel2S0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2S0.', ErrStat, ErrMsg, RoutineName) + + ALLOCATE ( WaveAcc2S0 (0:Waves_InitOut%NStepWave,InitLocal%Waves%NWaveKin,3), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2S0.', ErrStat, ErrMsg, RoutineName) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Copy the init output arrays into the MSL versions + WaveDynP2D0 = InitOut%Waves2%WaveDynP2D + WaveAcc2D0 = InitOut%Waves2%WaveAcc2D + WaveVel2D0 = InitOut%Waves2%WaveVel2D + WaveDynP2S0 = InitOut%Waves2%WaveDynP2S + WaveAcc2S0 = InitOut%Waves2%WaveAcc2S + WaveVel2S0 = InitOut%Waves2%WaveVel2S + + ! Reset the wave kinematics zi locations + InitLocal%Waves2%WaveKinzi = InitLocal%Waves%WaveKinzi + + ! Deallocate arrays which will be re-allocated in the next call to Waves2_Init + DEALLOCATE ( p%Waves2%WaveElev2 ) + DEALLOCATE ( InitOut%Waves2%WaveVel2D ) + DEALLOCATE ( InitOut%Waves2%WaveAcc2D ) + DEALLOCATE ( InitOut%Waves2%WaveDynP2D ) + DEALLOCATE ( InitOut%Waves2%WaveVel2S ) + DEALLOCATE ( InitOut%Waves2%WaveAcc2S ) + DEALLOCATE ( InitOut%Waves2%WaveDynP2S ) + + END IF +!========================================================================== + + + + + + + CALL Waves2_Init(InitLocal%Waves2, m%u_Waves2, p%Waves2, x%Waves2, xd%Waves2, z%Waves2, OtherState%Waves2, & + y%Waves2, m%Waves2, Interval, InitOut%Waves2, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! move arrays back + CALL MOVE_ALLOC(InitLocal%Waves2%WaveTime, p%WaveTime) + CALL MOVE_ALLOC(InitLocal%Waves2%WaveElevC0, Waves_InitOut%WaveElevC0) + CALL MOVE_ALLOC(InitLocal%Waves2%WaveDirArr, Waves_InitOut%WaveDirArr) + + ! Verify that Waves2_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'Waves2 Module attempted to change timestep interval, but this is not allowed. '// & + ' Waves2 Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + + ! If we calculated the wave elevation series data (for visualization purposes), add the second order corrections to the first order. + IF (ALLOCATED(InitLocal%Waves2%WaveElevXY)) THEN + ! Make sure the sizes of the two resulting arrays are identical... + IF ( SIZE(InitOut%WaveElevSeries,DIM=1) /= SIZE(InitOut%Waves2%WaveElevSeries2,DIM=1) .OR. & + SIZE(InitOut%WaveElevSeries,DIM=2) /= SIZE(InitOut%Waves2%WaveElevSeries2,DIM=2)) THEN + CALL SetErrStat(ErrID_Fatal,' WaveElevSeries arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + DO J=1,SIZE(InitOut%WaveElevSeries,DIM=2) + DO I = 0,p%NStepWave + InitOut%WaveElevSeries(I,J) = InitOut%Waves2%WaveElevSeries2(I,J) + InitOut%WaveElevSeries(I,J) + ENDDO + ENDDO + ENDIF + ENDIF + + ! If we calculated wave elevations, it is now stored in p%WaveElev. So we need to add the corrections. + IF (p%Waves2%NWaveElev > 0 ) THEN + ! Make sure the sizes of the two resulting arrays are identical... + IF ( SIZE(p%WaveElev,DIM=1) /= SIZE(p%Waves2%WaveElev2,DIM=1) .OR. & + SIZE(p%WaveElev,DIM=2) /= SIZE(p%Waves2%WaveElev2,DIM=2)) THEN + CALL SetErrStat(ErrID_Fatal,' WaveElev(NWaveElev) arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + DO J=1,SIZE(p%Waves2%WaveElev2,DIM=2) + DO I = 0,p%NStepWave + p%WaveElev(I,J) = p%Waves2%WaveElev2(I,J) + p%WaveElev(I,J) + ENDDO + ENDDO + ENDIF + ENDIF + + ! The acceleration, velocity, and dynamic pressures will get added to the parts passed to the morrison module later... + + ELSE + ! these need to be set to zero since we don't have a UseWaves2 flag: + p%Waves2%NWaveElev = 0 + p%Waves2%WvDiffQTFF = .FALSE. + p%Waves2%WvSumQTFF = .FALSE. + p%Waves2%NumOuts = 0 + + ENDIF + + + + + ! Is there a WAMIT body? + + IF ( InitLocal%PotMod == 1 ) THEN + + ! Copy Waves initialization output into the initialization input type for the WAMIT module + + InitLocal%WAMIT%RhoXg = Waves_InitOut%RhoXg + InitLocal%WAMIT%NStepWave = Waves_InitOut%NStepWave + InitLocal%WAMIT%NStepWave2 = Waves_InitOut%NStepWave2 + InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin + InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax + InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega + + + ! Init inputs for the SS_Excitation model (set this just in case it will be used) + InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir + CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) + + ! Temporarily move arrays to init input for WAMIT (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT%WaveDirArr) + + !----------------------------------------- + ! Initialize the WAMIT Calculations + !----------------------------------------- + + CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, & + y%WAMIT, m%WAMIT, Interval, InitOut%WAMIT, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + ! Generate Summary file information for WAMIT module + ! Compute the load contribution from hydrostatics: + IF ( InitLocal%UnSum > 0 ) THEN + + WRITE( InitLocal%UnSum, '(A11)') 'WAMIT Model' + WRITE( InitLocal%UnSum, '(A11)') '-----------' + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', p%WAMIT%PtfmVol0 + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', p%WAMIT%PtfmCOBxt + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', p%WAMIT%PtfmCOByt + WRITE( InitLocal%UnSum, '(/)' ) + WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,p%WAMIT%RhoXg*p%WAMIT%PtfmVol0,p%WAMIT%RhoXg*p%WAMIT%PtfmVol0*p%WAMIT%PtfmCOByt, -p%WAMIT%RhoXg*p%WAMIT%PtfmVol0*p%WAMIT%PtfmCOBxt, 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point + + END IF + + + ! Verify that WAMIT_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'WAMIT Module attempted to change timestep interval, but this is not allowed. WAMIT Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + ! move arrays back + CALL MOVE_ALLOC(InitLocal%WAMIT%WaveTime, p%WaveTime ) + CALL MOVE_ALLOC(InitLocal%WAMIT%WaveElevC0, Waves_InitOut%WaveElevC0) + CALL MOVE_ALLOC(InitLocal%WAMIT%WaveDirArr, Waves_InitOut%WaveDirArr) + + + !----------------------------------------- + ! Initialize the WAMIT2 Calculations + !----------------------------------------- + + ! Only call the WAMIT2_Init if one of the flags is set for a calculation + IF ( InitLocal%WAMIT2%MnDriftF .OR. InitLocal%WAMIT2%NewmanAppF .OR. InitLocal%WAMIT2%DiffQTFF .OR. InitLocal%WAMIT2%SumQTFF ) THEN + + + InitLocal%WAMIT2%RhoXg = Waves_InitOut%RhoXg + InitLocal%WAMIT2%NStepWave = Waves_InitOut%NStepWave + InitLocal%WAMIT2%NStepWave2 = Waves_InitOut%NStepWave2 + InitLocal%WAMIT2%WaveDirMin = Waves_InitOut%WaveDirMin + InitLocal%WAMIT2%WaveDirMax = Waves_InitOut%WaveDirMax + InitLocal%WAMIT2%WaveDOmega = Waves_InitOut%WaveDOmega + + ! Temporarily move arrays to init input for WAMIT2 (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT2%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT2%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT2%WaveDirArr) + + + CALL WAMIT2_Init(InitLocal%WAMIT2, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, z%WAMIT2, OtherState%WAMIT2, & + y%WAMIT2, m%WAMIT2, Interval, InitOut%WAMIT2, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! move arrays back + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveTime, p%WaveTime ) + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveElevC0, Waves_InitOut%WaveElevC0) + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveDirArr, Waves_InitOut%WaveDirArr) + + + ! Verify that WAMIT2_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'WAMIT2 Module attempted to change timestep interval, but this is not allowed. '// & + 'WAMIT2 Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + ELSE + + p%WAMIT2%NumOuts = 0 !This doesn't get initialized if we don't call WAMIT2_Init + + ENDIF + +#ifdef USE_FIT + ELSE IF ( InitLocal%PotMod == 2 ) THEN ! FIT + ! Set up the Initialization data for FIT + ! General + FITInitData%InputFile = InitLocal%PotFile + FITInitData%Gravity = InitLocal%Gravity + FITInitData%Rho = InitLocal%Waves%WtrDens + FITInitData%time_end = InitLocal%TMax + FITInitData%dtime = InitLocal%Waves%WaveDT ! Set the FIT module's timestep equal to the WaveDT timestep, this was checked earlier to make sure it is an integer muliple of the glue-code timestep! + ! Waves + ! Need to pre-process the incoming wave data to be compatible with FIT + + FITInitData%N_omega = Waves_InitOut%NStepWave2 + FITInitData%Wave_angle = Waves_InitOut%WaveDir + + ! allocate waves data arrays for FIT + CALL AllocAry( FITInitData%Wave_amp, FITInitData%N_omega, "Wave_amp", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( FITInitData%Wave_omega, FITInitData%N_omega, "Wave_omega", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( FITInitData%Wave_number, FITInitData%N_omega, "Wave_number", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( FITInitData%Wave_phase, FITInitData%N_omega, "Wave_phase", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Populate wave arrays + Np = 2*(Waves_InitOut%WaveDOmega + 1) + DO I = 1 , Waves_InitOut%NStepWave2 + + dftreal = Waves_InitOut%WaveElevC0( 1,ABS(I ) ) + dftimag = Waves_InitOut%WaveElevC0( 2, ABS(I ) )*SIGN(1,I) + FITInitData%Wave_amp (I) = sqrt( dftreal**2 + dftimag**2 ) * 2.0 / Np + FITInitData%Wave_omega (I) = I*Waves_InitOut%WaveDOmega + FITInitData%Wave_number(I) = I*Waves_InitOut%WaveDOmega**2. / InitLocal%Gravity + FITInitData%Wave_phase (I) = atan2( dftimag, dftreal ) + + END DO + + + ! Output + FITInitData%RootName = trim(InitLocal%OutRootName)//'.FIT' + + + CALL FIT_Init(FITInitData, u%FIT, p%FIT, FIT_x, xd%FIT, FIT_z, OtherState%FIT, y%FIT, Interval, FIT_InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) +#endif + + END IF + + + END IF ! Check for WaveMod = 6 + + + ! Are there Morison elements? + + IF ( InitLocal%Morison%NMembers > 0 ) THEN + + + ! Copy Waves initialization output into the initialization input type for the Morison module + + InitLocal%Morison%NStepWave = Waves_InitOut%NStepWave + + + ! Temporarily move array to init input for Morison (save some space) + CALL MOVE_ALLOC( p%WaveTime, InitLocal%Morison%WaveTime ) + + ! Permanently move these wave values to Morison init input (and note they are potentially modified by 2nd order stuff before being sent to Morison) + CALL MOVE_ALLOC( Waves_InitOut%WaveAcc, InitLocal%Morison%WaveAcc ) + CALL MOVE_ALLOC( Waves_InitOut%WaveDynP, InitLocal%Morison%WaveDynP ) + CALL MOVE_ALLOC( Waves_InitOut%WaveVel, InitLocal%Morison%WaveVel ) + CALL MOVE_ALLOC( Waves_InitOut%nodeInWater,InitLocal%Morison%nodeInWater ) ! moved to Morison%p%nodeInWater in the init routine + + + ! If we did some second order wave kinematics corrections to the acceleration, velocity or + ! dynamic pressure using the Waves2 module, then we need to add these to the values that we + ! will be passing into the Morrison module. + + ! Difference frequency results + IF ( p%Waves2%WvDiffQTFF ) THEN + + ! Dynamic pressure -- difference frequency terms + IF ( SIZE(InitLocal%Morison%WaveDynP,DIM=1) /= SIZE(InitOut%Waves2%WaveDynP2D,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveDynP,DIM=2) /= SIZE(InitOut%Waves2%WaveDynP2D,DIM=2)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveDynP arrays for first and second order wave elevations are of different sizes. '//NewLine// & + 'Morrison: '// TRIM(Num2LStr(SIZE(InitLocal%Morison%WaveDynP,DIM=1)))//'x'// & + TRIM(Num2LStr(SIZE(InitLocal%Morison%WaveDynP,DIM=2)))//NewLine// & + 'Waves2: '// TRIM(Num2LStr(SIZE(InitOut%Waves2%WaveDynP2D,DIM=1)))//'x'// & + TRIM(Num2LStr(SIZE(InitOut%Waves2%WaveDynP2D,DIM=2))), & + ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveDynP = InitLocal%Morison%WaveDynP + InitOut%Waves2%WaveDynP2D + IF (InitLocal%Waves%WaveStMod > 0 ) WaveDynP0 = WaveDynP0 + WaveDynP2D0 + ENDIF + + ! Particle velocity -- difference frequency terms + IF ( SIZE(InitLocal%Morison%WaveVel,DIM=1) /= SIZE(InitOut%Waves2%WaveVel2D,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveVel,DIM=2) /= SIZE(InitOut%Waves2%WaveVel2D,DIM=2) .OR. & + SIZE(InitLocal%Morison%WaveVel,DIM=3) /= SIZE(InitOut%Waves2%WaveVel2D,DIM=3)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveVel arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveVel = InitLocal%Morison%WaveVel + InitOut%Waves2%WaveVel2D + IF (InitLocal%Waves%WaveStMod > 0 ) WaveVel0 = WaveVel0 + WaveVel2D0 + ENDIF + + + ! Particle acceleration -- difference frequency terms + IF ( SIZE(InitLocal%Morison%WaveAcc,DIM=1) /= SIZE(InitOut%Waves2%WaveAcc2D,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveAcc,DIM=2) /= SIZE(InitOut%Waves2%WaveAcc2D,DIM=2) .OR. & + SIZE(InitLocal%Morison%WaveAcc,DIM=3) /= SIZE(InitOut%Waves2%WaveAcc2D,DIM=3)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveAcc arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveAcc = InitLocal%Morison%WaveAcc + InitOut%Waves2%WaveAcc2D + IF (InitLocal%Waves%WaveStMod > 0 ) WaveAcc0 = WaveAcc0 + WaveAcc2D0 + ENDIF + + ENDIF ! second order wave kinematics difference frequency results + + ! Sum frequency results + IF ( p%Waves2%WvSumQTFF ) THEN + + ! Dynamic pressure -- sum frequency terms + IF ( SIZE(InitLocal%Morison%WaveDynP,DIM=1) /= SIZE(InitOut%Waves2%WaveDynP2S,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveDynP,DIM=2) /= SIZE(InitOut%Waves2%WaveDynP2S,DIM=2)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveDynP arrays for first and second order wave elevations are of different sizes. '//NewLine// & + 'Morrison: '// TRIM(Num2LStr(SIZE(InitLocal%Morison%WaveDynP,DIM=1)))//'x'// & + TRIM(Num2LStr(SIZE(InitLocal%Morison%WaveDynP,DIM=2)))//NewLine// & + 'Waves2: '// TRIM(Num2LStr(SIZE(InitOut%Waves2%WaveDynP2D,DIM=1)))//'x'// & + TRIM(Num2LStr(SIZE(InitOut%Waves2%WaveDynP2D,DIM=2))), & + ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveDynP = InitLocal%Morison%WaveDynP + InitOut%Waves2%WaveDynP2S + IF (InitLocal%Waves%WaveStMod > 0 ) WaveDynP0 = WaveDynP0 + WaveDynP2S0 + ENDIF + + ! Particle velocity -- sum frequency terms + IF ( SIZE(InitLocal%Morison%WaveVel,DIM=1) /= SIZE(InitOut%Waves2%WaveVel2S,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveVel,DIM=2) /= SIZE(InitOut%Waves2%WaveVel2S,DIM=2) .OR. & + SIZE(InitLocal%Morison%WaveVel,DIM=3) /= SIZE(InitOut%Waves2%WaveVel2S,DIM=3)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveVel arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveVel = InitLocal%Morison%WaveVel + InitOut%Waves2%WaveVel2S + IF (InitLocal%Waves%WaveStMod > 0 ) WaveVel0 = WaveVel0 + WaveVel2S0 + ENDIF + + ! Particle velocity -- sum frequency terms + IF ( SIZE(InitLocal%Morison%WaveAcc,DIM=1) /= SIZE(InitOut%Waves2%WaveAcc2S,DIM=1) .OR. & + SIZE(InitLocal%Morison%WaveAcc,DIM=2) /= SIZE(InitOut%Waves2%WaveAcc2S,DIM=2) .OR. & + SIZE(InitLocal%Morison%WaveAcc,DIM=3) /= SIZE(InitOut%Waves2%WaveAcc2S,DIM=3)) THEN + CALL SetErrStat(ErrID_Fatal, & + ' WaveAcc arrays for first and second order wave elevations are of different sizes.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + ELSE + InitLocal%Morison%WaveAcc = InitLocal%Morison%WaveAcc + InitOut%Waves2%WaveAcc2S + IF (InitLocal%Waves%WaveStMod > 0 ) WaveAcc0 = WaveAcc0 + WaveAcc2S0 + ENDIF + + ENDIF ! second order wave kinematics sum frequency results + +!============================================================================== + ! TODO: 1/29/2016 GJH + ! This is where we need to perform Wave Stretching, now that the wave kinematics have been combined. + ! We will call a new subroutine to perform this work. + ! As an input, this code need the kinematics at the (X,Y,0) location which in a Z-line above/below all the nodes where kinematics are computed. + ! This code will alter the kinematics for stretching AND alter the nodeInWater array based on the combined wave elevation information + IF (InitLocal%Waves%WaveStMod > 0 ) THEN + call WvStretch_Init( InitLocal%Waves%WaveStMod, InitLocal%Waves%WtrDpth, InitLocal%Morison%NStepWave, InitLocal%Morison%NNodes, & + p%NWaveElev, WaveElevSt, InitLocal%Waves%WaveKinzi, InitLocal%Morison%WaveTime, & + WaveVel0, WaveAcc0, WaveDynP0, & + Waves_InitOut%PWaveVel0, Waves_InitOut%PWaveAcc0, Waves_InitOut%PWaveDynP0, & + InitLocal%Morison%WaveVel, InitLocal%Morison%WaveAcc, InitLocal%Morison%WaveDynP, & + InitLocal%Morison%nodeInWater, ErrStat, ErrMsg ) + DEALLOCATE(WaveElevSt) + DEALLOCATE(WaveVel0) + DEALLOCATE(WaveAcc0) + DEALLOCATE(WaveDynP0) + END IF +!============================================================================== + ! In this version, this can only be TRUE if the precomiler flag WRITE_WV_KIN set and WaveMod not equal to 5 or 6 and WvKinFile is a valid string + IF ( ( InitLocal%Waves%WaveMod == 5 .OR. InitLocal%Waves%WaveMod == 6 ) .AND. InitLocal%Echo ) THEN + call HDOut_WriteWvKinFiles( TRIM(InitLocal%Waves%WvKinFile)//'_ech', HydroDyn_ProgDesc, InitLocal%Morison%NStepWave, InitLocal%Morison%NNodes, & + p%NWaveElev, InitLocal%Morison%nodeInWater, p%WaveElev, InitLocal%Waves%WaveKinzi, InitLocal%Morison%WaveTime, & + InitLocal%Morison%WaveVel, InitLocal%Morison%WaveAcc, InitLocal%Morison%WaveDynP, & + ErrStat, ErrMsg ) + ELSE IF (InitLocal%Waves%WriteWvKin ) THEN + call HDOut_WriteWvKinFiles( TRIM(InitLocal%Waves%WvKinFile), HydroDyn_ProgDesc, InitLocal%Morison%NStepWave, InitLocal%Morison%NNodes, & + p%NWaveElev, InitLocal%Morison%nodeInWater, p%WaveElev, InitLocal%Waves%WaveKinzi, InitLocal%Morison%WaveTime, & + InitLocal%Morison%WaveVel, InitLocal%Morison%WaveAcc, InitLocal%Morison%WaveDynP, & + ErrStat, ErrMsg ) + END IF + + + + + + ! Check the output switch to see if Morison is needing to send outputs back to HydroDyn via the WriteOutput array + + IF ( InitLocal%OutSwtch > 0 ) THEN + InitLocal%Morison%OutSwtch = 2 ! only HydroDyn or the Driver code will write outputs to the file, that's why we are forcing this to 2. + ELSE + InitLocal%Morison%OutSwtch = 0 + END IF + + ! Initialize the Morison Element Calculations + + CALL Morison_Init(InitLocal%Morison, u%Morison, p%Morison, x%Morison, xd%Morison, z%Morison, OtherState%Morison, & + y%Morison, m%Morison, Interval, InitOut%Morison, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! move array back + CALL MOVE_ALLOC( InitLocal%Morison%WaveTime, p%WaveTime ) + + + IF ( u%Morison%DistribMesh%Committed ) THEN + ! we need the translation displacement mesh for loads transfer: + CALL MeshCopy ( SrcMesh = u%Morison%DistribMesh & + , DestMesh = m%MrsnDistribMesh_position & + , CtrlCode = MESH_NEWCOPY & + , IOS = COMPONENT_INPUT & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%MrsnDistribMesh_position') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + m%MrsnDistribMesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + + END IF + + IF ( u%Morison%LumpedMesh%Committed ) THEN + ! we need the translation displacement mesh for loads transfer: + CALL MeshCopy ( SrcMesh = u%Morison%LumpedMesh & + , DestMesh = m%MrsnLumpedMesh_position & + , CtrlCode = MESH_NEWCOPY & + , IOS = COMPONENT_INPUT & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%MrsnLumpedMesh_position') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + m%MrsnLumpedMesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + + END IF + ! Verify that Morison_Init() did not request a different Interval! + + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'Morison Module attempted to change timestep interval, but this is not allowed. Morison Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + END IF ! ( InitLocal%Morison%NMembers > 0 ) + +!=============================================== + p%PotMod = InitLocal%Potmod + IF ( InitLocal%UnSum > 0 ) THEN + + IF (InitLocal%Waves%WaveMod /= 0 .AND. InitLocal%Waves%WaveMod /= 6) THEN + ! Write the header for this section + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(1X,A15)' ) 'Wave Kinematics' + WRITE( InitLocal%UnSum, '(/)' ) + WRITE( InitLocal%UnSum, '(1X,A10,2X,A14,2X,A14,2X,A14,2X,A19,2X,A19)' ) & + ' m ', ' k ', ' Omega[m] ', ' Direction ', 'REAL(DFT{WaveElev})','IMAG(DFT{WaveElev})' + WRITE( InitLocal%UnSum, '(1X,A10,2X,A14,2X,A14,2X,A14,2X,A19,2X,A19)' ) & + ' (-) ', ' (1/m) ', ' (rad/s) ', ' (deg) ', ' (m) ',' (m) ' + + ! Write the data + DO I = -1*Waves_InitOut%NStepWave2+1,Waves_InitOut%NStepWave2 + WaveNmbr = WaveNumber ( I*Waves_InitOut%WaveDOmega, InitLocal%Gravity, InitLocal%Waves%WtrDpth ) + WRITE( InitLocal%UnSum, '(1X,I10,2X,ES14.5,2X,ES14.5,2X,ES14.5,2X,ES14.5,7X,ES14.5)' ) I, WaveNmbr, I*Waves_InitOut%WaveDOmega, & + Waves_InitOut%WaveDirArr(ABS(I)), Waves_InitOut%WaveElevC0( 1,ABS(I ) ) , Waves_InitOut%WaveElevC0( 2, ABS(I ) )*SIGN(1,I) + END DO + END IF + + + IF ( InitLocal%PotMod == 1 .AND. InitLocal%WAMIT%RdtnMod == 1) THEN + ! Write the header for this section + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(A)' ) 'Radiation memory effect kernel' + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' n ' , ' t ', ' K11 ', ' K12 ', ' K13 ', ' K14 ', ' K15 ', ' K16 ', ' K22 ', ' K23 ', ' K24 ', ' K25 ', ' K26 ', ' K33 ', ' K34 ', ' K35 ', 'K36 ', ' K44 ', ' K45 ', ' K46 ', ' K55 ', ' K56 ', ' K66 ' + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' (-) ' , ' (s) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)' + + ! Write the data + DO I = 0,p%WAMIT%Conv_Rdtn%NStepRdtn-1 + + WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%WAMIT%Conv_Rdtn%RdtnDT, p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,1), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,2), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,2), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,5,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,5,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,6,6) + + END DO + END IF + + END IF + +!========================================== + + ! Deallocate any remaining Waves Output data + IF(ALLOCATED( Waves_InitOut%WaveElevC0 )) DEALLOCATE( Waves_InitOut%WaveElevC0 ) + IF(ALLOCATED( Waves_InitOut%WaveAcc )) DEALLOCATE( Waves_InitOut%WaveAcc ) + IF(ALLOCATED( Waves_InitOut%WaveDynP )) DEALLOCATE( Waves_InitOut%WaveDynP ) + IF(ALLOCATED( Waves_InitOut%WaveTime )) DEALLOCATE( Waves_InitOut%WaveTime ) + IF(ALLOCATED( Waves_InitOut%WaveVel )) DEALLOCATE( Waves_InitOut%WaveVel ) + IF(ALLOCATED( Waves_InitOut%WaveElevC0 )) DEALLOCATE( Waves_InitOut%WaveElevC0 ) + !IF(ALLOCATED( InitLocal%WAMIT%WaveElevC0 )) DEALLOCATE( InitLocal%WAMIT%WaveElevC0) + + ! Close the summary file + IF ( InitLocal%HDSum ) THEN + CALL HDOut_CloseSum( InitLocal%UnSum, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END IF + + ! Define system output initializations (set up mesh) here: + + + ! Create the input and output meshes associated with lumped load at the WAMIT reference point (WRP) + + CALL MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + ! Create the node on the mesh + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + CALL MeshPositionNode (u%Mesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 & + ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL MeshCommit ( u%Mesh & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + CALL MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%Mesh') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + CALL MeshCopy ( SrcMesh = y%Mesh & + ,DestMesh = y%AllHdroOrigin & + ,CtrlCode = MESH_NEWCOPY & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%AllHdroOrigin') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + y%AllHdroOrigin%RemapFlag = .TRUE. + + ! we need the translation displacement mesh for loads transfer: + CALL MeshCopy ( SrcMesh = u%Mesh & + , DestMesh = m%AllHdroOrigin_position & + , CtrlCode = MESH_NEWCOPY & + , IOS = COMPONENT_INPUT & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + m%AllHdroOrigin_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + + + ! Create the Output file if requested + + p%OutSwtch = InitLocal%OutSwtch + p%Delim = '' + !p%Morison%Delim = p%Delim ! Need to set this from within Morison to follow framework + !p%WAMIT%Delim = p%Delim ! Need to set this from within Morison to follow framework + p%OutFmt = InitLocal%OutFmt + p%OutSFmt = InitLocal%OutSFmt + p%NumOuts = InitLocal%NumOuts + + CALL HDOUT_Init( HydroDyn_ProgDesc, InitLocal, y, p, m, InitOut, ErrStat2, ErrMsg2 ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Create some mesh mapping data + CALL MeshCopy ( SrcMesh = y%Mesh & + ,DestMesh = m%y_mapped & + ,CtrlCode = MESH_NEWCOPY & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + m%y_mapped%RemapFlag = .TRUE. + + CALL MeshMapCreate( y%Mesh, m%y_mapped, m%HD_MeshMap%HD_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( y%Morison%LumpedMesh%Committed ) THEN + CALL MeshMapCreate( y%Morison%LumpedMesh, m%y_mapped, m%HD_MeshMap%M_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ENDIF + IF ( y%Morison%DistribMesh%Committed ) THEN + CALL MeshMapCreate( y%Morison%DistribMesh, m%y_mapped, m%HD_MeshMap%M_L_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ENDIF + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Define initialization-routine output here: + InitOut%Ver = HydroDyn_ProgDesc + ! These three come directly from processing the inputs, and so will exist even if not using Morison elements: + InitOut%WtrDens = InitLocal%Morison%WtrDens + InitOut%WtrDpth = InitLocal%Morison%WtrDpth + InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL + + p%WtrDpth = InitOut%WtrDpth + + IF ( InitInp%hasIce ) THEN + IF ((InitLocal%Waves%WaveMod /= 0) .OR. (InitLocal%Current%CurrMod /= 0) ) THEN + CALL SetErrStat(ErrID_Fatal,'Waves and Current must be turned off in HydroDyn when ice loading is computed. Set WaveMod=0 and CurrMod=0.',ErrStat,ErrMsg,RoutineName) + END IF + END IF + + !............................................................................................ + ! Initialize Jacobian: + !............................................................................................ + if (InitInp%Linearize) then + call HD_Init_Jacobian( p, u, y, InitOut, ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + IF ( p%OutSwtch == 1 ) THEN ! Only HD-level output writing + ! HACK WE can tell FAST not to write any HD outputs by simply deallocating the WriteOutputHdr array! + DEALLOCATE ( InitOut%WriteOutputHdr ) + END IF + + ! Destroy the local initialization data + CALL CleanUp() + +CONTAINS +!................................ + SUBROUTINE CleanUp() + + CALL HydroDyn_DestroyInitInput( InitLocal, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyInitOutput( Waves_InitOut, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyInitOutput( Current_InitOut, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! These are dummy variables to satisfy the framework, but are not used again: + + CALL Waves_DestroyInput( Waves_u, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyParam( Waves_p, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyContState( Waves_x, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyDiscState( Waves_xd, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyConstrState( Waves_z, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyOtherState( WavesOtherState, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyOutput( Waves_y, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + CALL Current_DestroyInput( Current_u, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyParam( Current_p, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyContState( Current_x, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyDiscState( Current_xd, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyConstrState( Current_z, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyOtherState( CurrentOtherState, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyOutput( Current_y, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL Current_DestroyMisc( Current_m, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + END SUBROUTINE CleanUp +!................................ +END SUBROUTINE HydroDyn_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE HydroDyn_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(HydroDyn_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(HydroDyn_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(HydroDyn_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(HydroDyn_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + + ! Write the HydroDyn-level output file data if the user requested module-level output + ! and the current time has advanced since the last stored time step. + + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3) THEN + CALL HDOut_WriteOutputs( m%LastOutTime, y, p, m%Decimate, ErrStat, ErrMsg ) + END IF + + ! Close files here: + CALL HDOut_CloseOutput( p, ErrStat, ErrMsg ) + + + ! Destroy the input data: + + CALL HydroDyn_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL HydroDyn_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL HydroDyn_DestroyContState( x, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + ! Destroy misc variables: + + CALL HydroDyn_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL HydroDyn_DestroyOutput( y, ErrStat, ErrMsg ) + + +END SUBROUTINE HydroDyn_End + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE HydroDyn_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(HydroDyn_InputType), INTENT(INOUT ) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(HydroDyn_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(HydroDyn_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(HydroDyn_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter + TYPE(HydroDyn_ContinuousStateType) :: dxdt ! Continuous state derivatives at t + TYPE(HydroDyn_DiscreteStateType) :: xd_t ! Discrete states at t (copy) + TYPE(HydroDyn_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z) + TYPE(HydroDyn_InputType) :: u ! Instantaneous inputs + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (secondary error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + INTEGER :: nTime ! number of inputs + + TYPE(WAMIT_InputType), ALLOCATABLE :: Inputs_WAMIT(:) + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_UpdateStates' + + ! Create dummy variables required by framework but which are not used by the module + +#ifdef USE_FIT + TYPE(FIT_InputType), ALLOCATABLE :: Inputs_FIT(:) + TYPE(FIT_ConstraintStateType) :: FIT_z ! constraint states + TYPE(FIT_ContinuousStateType) :: FIT_x ! Input: Continuous states at t; +#endif + + REAL(ReKi) :: rotdisp(3) + ! Initialize variables + + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + + + ! Return without doing any work if the we are not using a potential flow model + IF ( p%PotMod == 0 ) RETURN + + ! Return without doing any work if the input mesh is not initialized (NOT USING WAMIT) + !IF ( .NOT. Inputs(1)%WAMIT%Mesh%Initialized ) RETURN + + nTime = size(Inputs) + + + ! Allocate array of WAMIT inputs + ! TODO: We should avoid allocating this at each time step if we can! + +!FIXME: Error handling appears to be broken here + + IF ( p%PotMod == 1 ) THEN + ALLOCATE( Inputs_WAMIT(nTime), STAT = ErrStat2 ) + IF (ErrStat2 /=0) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to allocate array Inputs_WAMIT.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + ! Loop over number of inputs and copy them into an array of WAMIT inputs + + DO I=1,nTime + + ! Copy the inputs from the HD mesh into the WAMIT mesh + CALL MeshCopy( Inputs(I)%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO + + + IF (ErrStat < AbortErrLev) THEN ! if there was an error copying the input meshes, we'll skip this step and then cleanup the temporary input meshes + ! Update the WAMIT module states + + CALL WAMIT_UpdateStates( t, n, Inputs_WAMIT, InputTimes, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + ! deallocate temporary inputs + DO I=1,nTime + CALL WAMIT_DestroyInput( Inputs_WAMIT(I), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + DEALLOCATE(Inputs_WAMIT) + +#ifdef USE_FIT + ELSE IF ( p%PotMod == 2 ) THEN ! FIT + + ALLOCATE( Inputs_FIT(nTime), STAT = ErrStat2 ) + IF (ErrStat2 /=0) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to allocate array Inputs_FIT.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + ! Loop over number of inputs and copy them into an array of FIT inputs + + DO I=1,nTime + + ! Copy the inputs from the HD mesh into the FIT input variables + + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( Inputs(I)%Mesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + Inputs_FIT(I)%roll = rotdisp(1) + Inputs_FIT(I)%pitch = rotdisp(2) + Inputs_FIT(I)%yaw = rotdisp(3) + Inputs_FIT(I)%si_t(:) = Inputs(I)%Mesh%TranslationDisp(:,1) + Inputs_FIT(I)%vel_t(:) = Inputs(I)%Mesh%TranslationVel (:,1) + END DO + + + + ! Update the FIT module states + + CALL FIT_UpdateStates( t, n, Inputs_FIT, InputTimes, p%FIT, FIT_x, xd%FIT, FIT_z, OtherState%FIT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! deallocate temporary inputs + DO I=1,nTime + CALL FIT_DestroyInput( Inputs_FIT(I), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + DEALLOCATE(Inputs_FIT) +#endif + + END IF + + +END SUBROUTINE HydroDyn_UpdateStates + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at Time (note that this is intent out because we're copying the u%mesh into m%u_wamit%mesh) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J ! Generic counters + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (secondary error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + +#ifdef USE_FIT + TYPE(FIT_ContinuousStateType) :: FIT_x ! Initial continuous states + TYPE(FIT_ConstraintStateType) :: FIT_z ! Initial guess of the constraint states + TYPE(FIT_InputType) :: Inputs_FIT +#endif + REAL(ReKi) :: WaveElev (p%NWaveElev) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi) :: WaveElev1(p%NWaveElev) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + + REAL(ReKi) :: q(6), qdot(6), qdotsq(6), qdotdot(6) + REAL(ReKi) :: rotdisp(3) ! small angle rotational displacements + REAL(ReKi) :: AllOuts(MaxHDOutputs) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute outputs here: + + + !------------------------------------------------------------------- + ! Additional stiffness, damping forces. These need to be placed on a point mesh which is located at the WAMIT reference point (WRP). + ! This mesh will need to get mapped by the glue code for use by either ElastoDyn or SubDyn. + !------------------------------------------------------------------- +!bjj: if these are false in the input file, the parameter verions of these variables don't get set: + + ! Deal with any output from the Waves2 module.... + IF (p%Waves2%WvDiffQTFF .OR. p%Waves2%WvSumQTFF ) THEN + + ! Waves2_CalcOutput is called only so that the wave elevations can be output (if requested). + CALL Waves2_CalcOutput( Time, m%u_Waves2, p%Waves2, x%Waves2, xd%Waves2, & + z%Waves2, OtherState%Waves2, y%Waves2, m%Waves2, ErrStat2, ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + END IF + +!FIXME: Error handling appears to be broken here. + + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + + q = reshape((/REAL(u%Mesh%TranslationDisp(:,1),ReKi),rotdisp(:)/),(/6/)) + qdot = reshape((/u%Mesh%TranslationVel(:,1),u%Mesh%RotationVel(:,1)/),(/6/)) + qdotsq = abs(qdot)*qdot + qdotdot = reshape((/u%Mesh%TranslationAcc(:,1),u%Mesh%RotationAcc(:,1)/),(/6/)) + + + ! Compute the load contirbution from user-supplied added stiffness and damping + + m%F_PtfmAdd = p%AddF0 - matmul(p%AddCLin, q) - matmul(p%AddBLin, qdot) - matmul(p%AddBQuad, qdotsq) + + ! Attach to the output point mesh + y%Mesh%Force (:,1) = m%F_PtfmAdd(1:3) + y%Mesh%Moment(:,1) = m%F_PtfmAdd(4:6) + + IF ( p%PotMod == 1 ) THEN + IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh + + ! Copy the inputs from the HD mesh into the WAMIT mesh + CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + CALL WAMIT_CalcOutput( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, & + z%WAMIT, OtherState%WAMIT, y%WAMIT, m%WAMIT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + + ! Add WAMIT forces to the HydroDyn output mesh + y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%WAMIT%Mesh%Force (:,1) + y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%WAMIT%Mesh%Moment(:,1) + + + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + m%F_Waves = m%WAMIT%F_Waves1 + + + END IF + +#ifdef USE_FIT + ELSE IF ( p%PotMod ==2 ) THEN !FIT + Inputs_FIT%roll = rotdisp(1) + Inputs_FIT%pitch = rotdisp(2) + Inputs_FIT%yaw = rotdisp(3) + Inputs_FIT%si_t(:) = u%Mesh%TranslationDisp(:,1) + Inputs_FIT%vel_t(:) = u%Mesh%TranslationVel (:,1) + CALL FIT_CalcOutput( Time, Inputs_FIT, p%FIT, FIT_x, xd%FIT, FIT_z, OtherState%FIT, y%FIT, ErrStat2, ErrMsg2 ) + + ! Add FIT forces to the HydroDyn output mesh + y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%FIT%F(:) + y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%FIT%M(:) +#endif + + END IF + + + IF ( m%u_WAMIT2%Mesh%Committed ) THEN ! Make sure we are using WAMIT2 / there is a valid mesh + + ! Copy the inputs from the HD mesh into the WAMIT2 mesh + CALL MeshCopy( u%Mesh, m%u_WAMIT2%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + CALL WAMIT2_CalcOutput( Time, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, & + z%WAMIT2, OtherState%WAMIT2, y%WAMIT2, m%WAMIT2, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + + ! Add WAMIT2 forces to the HydroDyn output mesh + y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%WAMIT2%Mesh%Force (:,1) + y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%WAMIT2%Mesh%Moment(:,1) + + ! Add the second order WAMIT forces to the first order WAMIT forces for the total (this is just to make the mesh match this misc var) + m%F_Waves = m%F_Waves + m%WAMIT2%F_Waves2 + + END IF + + + + IF ( u%Morison%LumpedMesh%Committed ) THEN ! Make sure we are using Morison / there is a valid mesh + CALL Morison_CalcOutput( Time, u%Morison, p%Morison, x%Morison, xd%Morison, & + z%Morison, OtherState%Morison, y%Morison, m%Morison, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + END IF + + + ! Integrate all the mesh loads onto the WAMIT reference Point (WRP) at (0,0,0) + m%F_Hydro = CalcLoadsAtWRP( y, u, m%y_mapped, m%AllHdroOrigin_position, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + + + ! Compute the wave elevations at the requested output locations for this time. Note that p%WaveElev has the second order added to it already. + + DO I=1,p%NWaveElev + WaveElev1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev1(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + WaveElev(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + + END DO + + + + + ! Write the HydroDyn-level output file data if the user requested module-level output + ! and the current time has advanced since the last stored time step. + + IF ( (p%OutSwtch == 1 .OR. p%OutSwtch == 3) .AND. ( Time > m%LastOutTime ) ) THEN + CALL HDOut_WriteOutputs( m%LastOutTime, y, p, m%Decimate, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + END IF + + + ! Map calculated results into the AllOuts Array + CALL HDOut_MapOutputs( Time, y, p%NWaveElev, WaveElev, WaveElev1, m%F_PtfmAdd, m%F_Waves, m%F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + + DO I = 1,p%NumOuts + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + END DO + + ! Aggregate the sub-module outputs + + IF ( p%OutSwtch > 0) THEN + + J = p%NumOuts + 1 + + IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN + DO I=1, p%WAMIT%NumOuts + y%WriteOutput(J) = y%WAMIT%WriteOutput(I) + J = J + 1 + END DO + END IF + + IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN + DO I=1, p%Waves2%NumOuts + y%WriteOutput(J) = y%Waves2%WriteOutput(I) + J = J + 1 + END DO + END IF + + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN + DO I=1, p%WAMIT2%NumOuts + y%WriteOutput(J) = y%WAMIT2%WriteOutput(I) + J = J + 1 + END DO + END IF + + IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + DO I=1, p%Morison%NumOuts + y%WriteOutput(J) = y%Morison%WriteOutput(I) + J = J + 1 + END DO + END IF + + END IF + + m%LastOutTime = Time + +END SUBROUTINE HydroDyn_CalcOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at Time (intent OUT only because we're copying the input mesh) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(HydroDyn_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 + + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CalcContStateDeriv' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh + + ! Copy the inputs from the HD mesh into the WAMIT mesh + CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, dxdt%WAMIT, ErrStat, ErrMsg ) + + END IF + +END SUBROUTINE HydroDyn_CalcContStateDeriv + + +!---------------------------------------------------------------------------------------------------------------------------------- +! Tight coupling routine for updating discrete states. Note that the WAMIT_UpdateDiscState violates the framework by having OtherStates +! be intent in/out. If/when this is fixed we can uncomment this routine. +!SUBROUTINE HydroDyn_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +! +! REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds +! INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval +! TYPE(HydroDyn_InputType), INTENT(IN ) :: u !< Inputs at Time +! TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters +! TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time +! TYPE(HydroDyn_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; +! !! Output: Discrete states at Time + Interval +! TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time +! TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states +! TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables +! INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation +! CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None +! +! +! ! Initialize ErrStat +! +! ErrStat = ErrID_None +! ErrMsg = "" +! +! +! ! Update discrete states +! +! IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh +! +! ! Copy the inputs from the HD mesh into the WAMIT mesh +! CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) +! IF ( ErrStat >= AbortErrLev ) RETURN +! +! CALL WAMIT_UpdateDiscState( Time, n, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, ErrStat, ErrMsg ) +! IF ( ErrStat >= AbortErrLev ) RETURN +! END IF +! +!END SUBROUTINE HydroDyn_UpdateDiscState + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE HydroDyn_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at Time (intent OUT only because we're copying the input mesh) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(HydroDyn_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh + + ! Copy the inputs from the HD mesh into the WAMIT mesh + CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + call WAMIT_CalcConstrStateResidual( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, z_residual%WAMIT, ErrStat, ErrMsg ) + + END IF + + +END SUBROUTINE HydroDyn_CalcConstrStateResidual + + +!---------------------------------------------------------------------------------------------------------------------------------- +FUNCTION CalcLoadsAtWRP( y, u, y_mapped, AllHdroOrigin_position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) + + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y ! Hydrodyn outputs + TYPE(HydroDyn_InputType), INTENT(IN ) :: u ! Hydrodyn inputs + TYPE(MeshType), INTENT(INOUT) :: y_mapped ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call + TYPE(MeshType), INTENT(IN ) :: AllHdroOrigin_position ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call + TYPE(MeshType), INTENT(IN ) :: MrsnLumpedMesh_Postion ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call + TYPE(MeshType), INTENT(IN ) :: MrsnDistribMesh_Position ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call + TYPE(HD_ModuleMapType), INTENT(INOUT) :: MeshMapData ! Map data structures + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi) :: CalcLoadsAtWRP(6) + + ! local variables + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + y%AllHdroOrigin%Force = 0.0 + y%AllHdroOrigin%Moment= 0.0 + + IF ( y%Mesh%Committed ) THEN + + ! Just transfer the loads because the meshes are at the same location (0,0,0) + + y%AllHdroOrigin%Force = y%Mesh%Force + y%AllHdroOrigin%Moment = y%Mesh%Moment + + END IF + + IF ( y%Morison%LumpedMesh%Committed ) THEN + + ! This is viscous drag associate with the WAMIT body and/or filled/flooded forces of the WAMIT body + + CALL Transfer_Point_to_Point( y%Morison%LumpedMesh, y_mapped, MeshMapData%M_P_2_WRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, AllHdroOrigin_position ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + y%AllHdroOrigin%Force = y%AllHdroOrigin%Force + y_mapped%Force + y%AllHdroOrigin%Moment = y%AllHdroOrigin%Moment + y_mapped%Moment + + END IF + + IF ( y%Morison%DistribMesh%Committed ) THEN + + CALL Transfer_Line2_to_Point( y%Morison%DistribMesh, y_mapped, MeshMapData%M_L_2_WRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, AllHdroOrigin_position ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + y%AllHdroOrigin%Force = y%AllHdroOrigin%Force + y_mapped%Force + y%AllHdroOrigin%Moment = y%AllHdroOrigin%Moment + y_mapped%Moment + + END IF + + CalcLoadsAtWRP(1:3) = y%AllHdroOrigin%Force(:,1) + CalcLoadsAtWRP(4:6) = y%AllHdroOrigin%Moment(:,1) + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//' CalcLoadsAtWRP:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + END IF + + END SUBROUTINE CheckError +END FUNCTION CalcLoadsAtWRP + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in HD_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 HD_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(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: 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(HydroDyn_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 the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + + + ! local variables + TYPE(HydroDyn_OutputType) :: y_p + TYPE(HydroDyn_OutputType) :: y_m + TYPE(HydroDyn_ContinuousStateType) :: x_p + TYPE(HydroDyn_ContinuousStateType) :: x_m + TYPE(HydroDyn_InputType) :: u_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, j, NN, offsetI, offsetJ + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid + NN = p%WAMIT%SS_Rdtn%N + p%WAMIT%SS_Exctn%N + + ! make a copy of the inputs to perturb + call HydroDyn_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + + IF ( PRESENT( dYdu ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate dYdu if necessary + if (.not. allocated(dYdu)) then + call AllocAry(dYdu, p%Jac_ny, size(p%Jac_u_indx,1)+1, 'dYdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call HydroDyn_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call HydroDyn_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + do i=1,size(p%Jac_u_indx,1) + + ! get u_op + delta u + call HydroDyn_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call HD_Perturb_u( p, i, 1, u_perturb, delta ) + + ! compute y at u_op + delta u + call HydroDyn_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get u_op - delta u + call HydroDyn_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call HD_Perturb_u( p, i, -1, u_perturb, delta ) + + ! compute y at u_op - delta u + call HydroDyn_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta, dYdu(:,i) ) + + end do + + ! p%WaveElev0 column + dYdu(:,size(p%Jac_u_indx,1)+1) = 0 + + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call HydroDyn_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call HydroDyn_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + + END IF + + + IF ( PRESENT( dXdu ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate dXdu if necessary + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, NN, size(p%Jac_u_indx,1)+1, 'dXdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + offsetI = 0 + dXdu = 0.0_R8Ki + + + do i = 1,p%WAMIT%SS_Exctn%N + dXdu(offsetI+i,size(p%Jac_u_indx,1)+1) = p%WAMIT%SS_Exctn%B(i) + end do + + + offsetI = NN - p%WAMIT%SS_Rdtn%N + offsetJ = size(p%Jac_u_indx,1)+1 - 13 + do j = 1, 6 + do i = 1,p%WAMIT%SS_Rdtn%N + dXdu(offsetI+i,offsetJ+j) = p%WAMIT%SS_Rdtn%B(i,j) + end do + end do + + + + + END IF + + + + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF + + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + call cleanup() + +contains + subroutine cleanup() + call HydroDyn_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyInput( u_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE HD_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 HD_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(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: 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(HydroDyn_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] + + ! local variables + TYPE(HydroDyn_OutputType) :: y_p + TYPE(HydroDyn_OutputType) :: y_m + TYPE(HydroDyn_ContinuousStateType) :: x_p + TYPE(HydroDyn_ContinuousStateType) :: x_m + TYPE(HydroDyn_ContinuousStateType) :: x_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, j, NN + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_JacobianPContState' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + NN = p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N + + ! make a copy of the continuous states to perturb + call HydroDyn_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + IF ( PRESENT( dYdx ) ) THEN + + + ! allocate dYdx if necessary + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%Jac_ny, NN, 'dYdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call HydroDyn_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call HydroDyn_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + + + do i=1,NN + + ! get x_op + delta x + call HydroDyn_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call HD_Perturb_x( p, i, 1, x_perturb, delta ) + + ! compute y at x_op + delta x + call HydroDyn_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get x_op - delta x + call HydroDyn_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call HD_Perturb_x( p, i, -1, x_perturb, delta ) + + ! compute y at x_op - delta x + call HydroDyn_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + ! get central difference: + call Compute_dY( p, y_p, y_m, delta, dYdx(:,i) ) + + end do + + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + call HydroDyn_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call HydroDyn_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + + 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 dXdu if necessary + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, NN, NN, 'dXdx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + dXdx = 0.0_R8Ki + + ! Analytical Jacobians from State-space models + if ( p%WAMIT%SS_Exctn%N > 0 ) then + do j=1,p%WAMIT%SS_Exctn%N + do i=1,p%WAMIT%SS_Exctn%N ! Loop through all active (enabled) DOFs + dXdx(i, j) = p%WAMIT%SS_Exctn%A(i,j) + end do + end do + end if + if ( p%WAMIT%SS_Rdtn%N > 0 ) then + do j=1,p%WAMIT%SS_Rdtn%N + do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all active (enabled) DOFs + dXdx(i+p%WAMIT%SS_Exctn%N, j+p%WAMIT%SS_Exctn%N) = p%WAMIT%SS_Rdtn%A(i,j) + end do + end do + end if + + END IF + + IF ( PRESENT( dXddx ) ) THEN + if (allocated(dXddx)) deallocate(dXddx) + END IF + + IF ( PRESENT( dZdx ) ) THEN + if (allocated(dZdx)) deallocate(dZdx) + END IF + + call cleanup() + +contains + subroutine cleanup() + call HydroDyn_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call HydroDyn_DestroyContState(x_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE HD_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 HD_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(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: 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(HydroDyn_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 HD_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 HD_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(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: 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(HydroDyn_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 HD_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized outputs. +SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) + + TYPE(HydroDyn_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(HydroDyn_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + 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,j,k, index_last, index_next + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_Init_Jacobian_y' + LOGICAL :: Mask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + logical, allocatable :: AllOut(:) + + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! determine how many outputs there are in the Jacobians + p%Jac_ny = 0 + if ( y%Morison%DistribMesh%Committed ) then + p%Jac_ny = p%Jac_ny + y%Morison%DistribMesh%NNodes * 6 ! 3 Force, Moment, at each node on the distributed loads mesh + p%Jac_ny = p%Jac_ny + y%Morison%LumpedMesh%NNodes * 6 ! 3 Force, Moment, at each node on the lumped loads mesh + end if + + p%Jac_ny = p%Jac_ny + y%Mesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point + p%Jac_ny = p%Jac_ny + y%AllHdroOrigin%NNodes * 6 ! 3 Force, Moment, of all HD loads integrated to the origin (0,0,0) + p%Jac_ny = p%Jac_ny + p%NumTotalOuts ! WriteOutput values + + + !................. + ! set linearization output names: + !................. + CALL AllocAry(InitOut%LinNames_y, p%Jac_ny, 'LinNames_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! LIN-TODO: Do we need RotFrame_y for this module? + !CALL AllocAry(InitOut%RotFrame_y, p%Jac_ny, 'RotFrame_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + + + + index_next = 1 + if ( y%Morison%DistribMesh%Committed ) then + index_last = index_next + call PackLoadMesh_Names(y%Morison%DistribMesh, 'DistribLoads', InitOut%LinNames_y, index_next) + index_last = index_next + call PackLoadMesh_Names(y%Morison%LumpedMesh, 'LumpedLoads', InitOut%LinNames_y, index_next) + end if + + + index_last = index_next + call PackLoadMesh_Names(y%Mesh, 'PlatformRefPtLoads', InitOut%LinNames_y, index_next) + + index_last = index_next + call PackLoadMesh_Names(y%AllHdroOrigin, 'AllHdroOrigin', InitOut%LinNames_y, index_next) + + index_last = index_next + + do i=1,p%NumTotalOuts + InitOut%LinNames_y(i+index_next-1) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) !trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + end do + + + +END SUBROUTINE HD_Init_Jacobian_y + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the Jacobian parameters and initialization outputs for the linearized continuous states. +SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) + + TYPE(HydroDyn_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(HydroDyn_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_Init_Jacobian_x' + + ! local variables: + INTEGER(IntKi) :: i, j, k, NN, spdof, indx + CHARACTER(10) :: modLabels(2), dofLabels(6) + ErrStat = ErrID_None + ErrMsg = "" + indx = 1 + NN = p%WAMIT%SS_Rdtn%N + p%WAMIT%SS_Exctn%N + if ( NN == 0 ) return + ! allocate space for the row/column names and for perturbation sizes + call allocAry(p%dx, NN, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%LinNames_x, NN, 'LinNames_x', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%DerivOrder_x, NN, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! All Hydrodyn continuous states are max order = 1 + if ( allocated(InitOut%DerivOrder_x) ) InitOut%DerivOrder_x = 1 + + ! set perturbation sizes: p%dx + + do i = 1, p%WAMIT%SS_Exctn%N + p%dx(i) = 20000.0_R8Ki * D2R_D + end do + + do i = 1, p%WAMIT%SS_Rdtn%N + p%dx(i+p%WAMIT%SS_Exctn%N) = 2.0_R8Ki * D2R_D + end do + + modLabels = (/'Exctn ','Rdtn '/) + dofLabels = (/'PtfmSg ','PtfmSw ','PtfmHv ','PtfmR ','PtfmP ','PtfmY '/) + + ! set linearization state names: + do k = 1, 2 ! 1 = Excitation, 2 = Radiation + + + do j = 1, 6 + + if (k == 1) then + spdof = p%WAMIT%SS_Exctn%spdof(j) + else + spdof = p%WAMIT%SS_Rdtn%spdof(j) + end if + + do i = 1,spdof + InitOut%LinNames_x(indx) = trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) + indx = indx + 1 + end do + end do + end do + +END SUBROUTINE HD_Init_Jacobian_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing corresponding linearization routines ! +SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) + + TYPE(HydroDyn_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(HydroDyn_InputType) , INTENT(IN ) :: u !< inputs + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(HydroDyn_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_Init_Jacobian' + + ! local variables: + INTEGER(IntKi) :: i, j, k, index, index_last, nu, i_meshField, m, meshFieldCount + REAL(R8Ki) :: MaxThrust, MaxTorque, perturb_t, perturb + REAL(R8Ki) :: ScaleLength + LOGICAL :: FieldMask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + + + + ErrStat = ErrID_None + ErrMsg = "" + + + call HD_Init_Jacobian_y( p, y, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call HD_Init_Jacobian_x( p, InitOut, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + + ! determine how many inputs there are in the Jacobians + nu = 0; + if ( u%Morison%DistribMesh%Committed ) then + nu = nu + u%Morison%DistribMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + nu = nu + u%Morison%LumpedMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + end if + + nu = nu + u%Mesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + + ! DO NOT Add the extended input WaveElev0 when computing the size of p%Jac_u_indx + + + ! note: all other inputs are ignored + + !.................... + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! (see hydrodyn::HD_perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index of the acceleration/load field + ! column 3 is the node + !.................... + + !............... + ! HD input mappings stored in p%Jac_u_indx: + !............... + call AllocAry(p%Jac_u_indx, nu, 3, 'p%Jac_u_indx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + index = 1 + meshFieldCount = 0 + if ( u%Morison%DistribMesh%Committed ) then + !Module/Mesh/Field: u%Morison%DistribMesh%TranslationDisp = 1; + !Module/Mesh/Field: u%Morison%DistribMesh%Orientation = 2; + !Module/Mesh/Field: u%Morison%DistribMesh%TranslationVel = 3; + !Module/Mesh/Field: u%Morison%DistribMesh%RotationVel = 4; + !Module/Mesh/Field: u%Morison%DistribMesh%TranslationAcc = 5; + !Module/Mesh/Field: u%Morison%DistribMesh%RotationAcc = 6; + + do i_meshField = 1,6 + do i=1,u%Morison%DistribMesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%Morison%DistribMesh%{TranslationDisp/Orientation/TranslationVel/RotationVel/TranslationAcc/RotationAcc} = m + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !i_meshField + meshFieldCount = 6 + !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationDisp = 7; + !Module/Mesh/Field: u%Morison%LumpedMesh%Orientation = 8; + !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationVel = 9; + !Module/Mesh/Field: u%Morison%LumpedMesh%RotationVel = 10; + !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationAcc = 11; + !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12; + + do i_meshField = 1,6 + do i=1,u%Morison%LumpedMesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = meshFieldCount + i_meshField !if this mesh is allocated, then the previous DistribMesh would have been allocated + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !i_meshField + meshFieldCount = meshFieldCount + 6 + end if + + !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 or 1; + !Module/Mesh/Field: u%Mesh%Orientation = 14 or 2; + !Module/Mesh/Field: u%Mesh%TranslationVel = 15 or 3; + !Module/Mesh/Field: u%Mesh%RotationVel = 16 or 4; + !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 or 5; + !Module/Mesh/Field: u%Mesh%RotationAcc = 18 or 6; + + do i_meshField = 1,6 + do i=1,u%Mesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = meshFieldCount + i_meshField + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do !i_meshField + + + !................ + ! input perturbations, du: + !................ + if ( u%Morison%DistribMesh%Committed ) then + call AllocAry(p%du, 18, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + else + call AllocAry(p%du, 6, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + end if + + perturb_t = 0.02_ReKi*D2R * max(p%WtrDpth,1.0_ReKi) ! translation input scaling ! LIN-TODO What about MSL offset? + perturb = 2*D2R ! rotational input scaling + + index = 0 + if ( u%Morison%DistribMesh%Committed ) then + p%du(1) = perturb_t ! u%Morison%DistribMesh%TranslationDisp + p%du(2) = perturb ! u%Morison%DistribMesh%Orientation + p%du(3) = perturb_t ! u%Morison%DistribMesh%TranslationVel + p%du(4) = perturb ! u%Morison%DistribMesh%RotationVel + p%du(5) = perturb_t ! u%Morison%DistribMesh%TranslationAcc + p%du(6) = perturb ! u%Morison%DistribMesh%RotationAcc + index = 6 + p%du(index + 1) = perturb_t ! u%Morison%LumpedMesh%TranslationDisp + p%du(index + 2) = perturb ! u%Morison%LumpedMesh%Orientation + p%du(index + 3) = perturb_t ! u%Morison%LumpedMesh%TranslationVel + p%du(index + 4) = perturb ! u%Morison%LumpedMesh%RotationVel + p%du(index + 5) = perturb_t ! u%Morison%LumpedMesh%TranslationAcc + p%du(index + 6) = perturb ! u%Morison%LumpedMesh%RotationAcc + index = index + 6 + end if + + + p%du(index + 1) = perturb_t ! u%Mesh%TranslationDisp + p%du(index + 2) = perturb ! u%Mesh%Orientation + p%du(index + 3) = perturb_t ! u%Mesh%TranslationVel + p%du(index + 4) = perturb ! u%Mesh%RotationVel + p%du(index + 5) = perturb_t ! u%Mesh%TranslationAcc + p%du(index + 6) = perturb ! u%Mesh%RotationAcc + index = index + 6 + + + + !................ + ! names of the columns, InitOut%LinNames_u: + !................ + call AllocAry(InitOut%LinNames_u, nu+1, 'LinNames_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + !LIN-TODO: We do not need any RotFrame info, right? + !call AllocAry(InitOut%RotFrame_u, nu+1, 'RotFrame_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! LIN-TODO: have we implemented IsLoad_u ? + call AllocAry(InitOut%IsLoad_u, nu+1, 'IsLoad_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%IsLoad_u = .false. ! HD's inputs are NOT loads + + index = 1 + if ( u%Morison%DistribMesh%Committed ) then + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVEL) = .true. + FieldMask(MASKID_ROTATIONVEL) = .true. + FieldMask(MASKID_TRANSLATIONACC) = .true. + FieldMask(MASKID_ROTATIONACC) = .true. + call PackMotionMesh_Names(u%Morison%DistribMesh, 'Morison-Distrib', InitOut%LinNames_u, index, FieldMask=FieldMask) + + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + FieldMask(MASKID_ROTATIONVel) = .true. + FieldMask(MASKID_TRANSLATIONACC) = .true. + FieldMask(MASKID_ROTATIONACC) = .true. + call PackMotionMesh_Names(u%Morison%LumpedMesh, 'Morison-Lumped', InitOut%LinNames_u, index, FieldMask=FieldMask) + end if + + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + FieldMask(MASKID_ROTATIONVel) = .true. + FieldMask(MASKID_TRANSLATIONACC) = .true. + FieldMask(MASKID_ROTATIONACC) = .true. + call PackMotionMesh_Names(u%Mesh, 'Platform-RefPt', InitOut%LinNames_u, index, FieldMask=FieldMask) + + InitOut%LinNames_u(index) = 'Extended input: wave elevation at platform ref point, m' + +END SUBROUTINE HD_Init_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine hydrodyn::HD_init_jacobian is consistant with this routine! +SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) + + TYPE(HydroDyn_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(HydroDyn_InputType) , INTENT(INOUT) :: u !< perturbed HD inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + + + ! local variables + integer :: fieldIndx + integer :: node + + + fieldIndx = p%Jac_u_indx(n,2) + node = p%Jac_u_indx(n,3) + + du = p%du( p%Jac_u_indx(n,1) ) + + ! determine which mesh we're trying to perturb and perturb the input: + + ! If we do not have Morison meshes, then the following select cases will vary + if ( u%Morison%DistribMesh%Committed ) then + + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 1) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationDisp = 1 + u%Morison%DistribMesh%TranslationDisp (fieldIndx,node) = u%Morison%DistribMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%Morison%DistribMesh%Orientation = 2 + CALL PerturbOrientationMatrix( u%Morison%DistribMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationVel = 3 + u%Morison%DistribMesh%TranslationVel( fieldIndx,node) = u%Morison%DistribMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%Morison%DistribMesh%RotationVel = 4 + u%Morison%DistribMesh%RotationVel (fieldIndx,node) = u%Morison%DistribMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationAcc = 5 + u%Morison%DistribMesh%TranslationAcc( fieldIndx,node) = u%Morison%DistribMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%Morison%DistribMesh%RotationAcc = 6 + u%Morison%DistribMesh%RotationAcc(fieldIndx,node) = u%Morison%DistribMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + + CASE ( 7) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationDisp = 7 + u%Morison%LumpedMesh%TranslationDisp (fieldIndx,node) = u%Morison%LumpedMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%Morison%LumpedMesh%Orientation = 8 + CALL PerturbOrientationMatrix( u%Morison%LumpedMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 9) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationVel = 9 + u%Morison%LumpedMesh%TranslationVel( fieldIndx,node) = u%Morison%LumpedMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%Morison%LumpedMesh%RotationVel = 10 + u%Morison%LumpedMesh%RotationVel (fieldIndx,node) = u%Morison%LumpedMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (11) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationAcc = 11 + u%Morison%LumpedMesh%TranslationAcc( fieldIndx,node) = u%Morison%LumpedMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (12) !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12 + u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) = u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + + CASE (13) !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 + u%Mesh%TranslationDisp (fieldIndx,node) = u%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE (14) !Module/Mesh/Field: u%Mesh%Orientation = 14 + CALL PerturbOrientationMatrix( u%Mesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (15) !Module/Mesh/Field: u%Mesh%TranslationVel = 15 + u%Mesh%TranslationVel( fieldIndx,node) = u%Mesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (16) !Module/Mesh/Field: u%Mesh%RotationVel = 16 + u%Mesh%RotationVel (fieldIndx,node) = u%Mesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (17) !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 + u%Mesh%TranslationAcc( fieldIndx,node) = u%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (18) !Module/Mesh/Field: u%Mesh%RotationAcc = 18 + u%Mesh%RotationAcc(fieldIndx,node) = u%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign + + + END SELECT + else + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE (1) !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 + u%Mesh%TranslationDisp (fieldIndx,node) = u%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE (2) !Module/Mesh/Field: u%Mesh%Orientation = 14 + CALL PerturbOrientationMatrix( u%Mesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (3) !Module/Mesh/Field: u%Mesh%TranslationVel = 15 + u%Mesh%TranslationVel( fieldIndx,node) = u%Mesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (4) !Module/Mesh/Field: u%Mesh%RotationVel = 16 + u%Mesh%RotationVel (fieldIndx,node) = u%Mesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (5) !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 + u%Mesh%TranslationAcc( fieldIndx,node) = u%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (6) !Module/Mesh/Field: u%Mesh%RotationAcc = 18 + u%Mesh%RotationAcc(fieldIndx,node) = u%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign + + END SELECT + end if + + +END SUBROUTINE HD_Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the continuous state array. +!! Do not change this without making sure subroutine HD_init_jacobian is consistant with this routine! +SUBROUTINE HD_Perturb_x( p, n, perturb_sign, x, dx ) + + TYPE(HydroDyn_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(HydroDyn_ContinuousStateType) , INTENT(INOUT) :: x !< perturbed ED states + REAL( R8Ki ) , INTENT( OUT) :: dx !< amount that specific state was perturbed + + + ! local variables + integer(intKi) :: indx + + dx = p%dx(n) + + if (n > p%WAMIT%SS_Exctn%N) then + indx = n - p%WAMIT%SS_Exctn%N + x%WAMIT%SS_Rdtn%x( indx ) = x%WAMIT%SS_Rdtn%x( indx ) + dx * perturb_sign + else + indx = n + x%WAMIT%SS_Exctn%x( indx ) = x%WAMIT%SS_Exctn%x( indx ) + dx * perturb_sign + end if + +END SUBROUTINE HD_Perturb_x + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine hydrodyn::HD_init_jacobian is consistant with this routine! +SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) + + TYPE(HydroDyn_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y_p !< HD outputs at \f$ u + \Delta u \f$ or \f$ x + \Delta x \f$ (p=plus) + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y_m !< HD outputs at \f$ u - \Delta u \f$ or \f$ x - \Delta x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta = \Delta u \f$ or \f$ delta = \Delta x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial x_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + + integer(IntKi) :: indx_first ! index indicating next value of dY to be filled + logical :: Mask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + integer(IntKi) :: k + + + + + indx_first = 1 + if ( y_p%Morison%DistribMesh%Committed ) then + call PackLoadMesh_dY(y_p%Morison%DistribMesh, y_m%Morison%DistribMesh, dY, indx_first) + call PackLoadMesh_dY(y_p%Morison%LumpedMesh , y_m%Morison%LumpedMesh , dY, indx_first) + end if + + call PackLoadMesh_dY(y_p%Mesh, y_m%Mesh, dY, indx_first) + call PackLoadMesh_dY(y_p%AllHdroOrigin, y_m%AllHdroOrigin, dY, indx_first) + + do k=1,p%NumTotalOuts + dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) + end do + + + + dY = dY / (2.0_R8Ki*delta) + +END SUBROUTINE Compute_dY + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE HD_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(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(HydroDyn_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) :: i, k, index, nu + INTEGER(IntKi) :: ny + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HD_GetOP' + TYPE(HydroDyn_ContinuousStateType) :: dx !< derivative of continuous states at operating point + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + !.................................. + IF ( PRESENT( u_op ) ) THEN + + if (.not. allocated(u_op)) then + + nu = size(p%Jac_u_indx,1) + + ! our operating point includes DCM (orientation) matrices, not just small angles like the perturbation matrices do + if ( u%Morison%DistribMesh%Committed ) then + nu = nu + u%Morison%DistribMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + + u%Morison%LumpedMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + + u%Mesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + nu = nu + 1 ! Extended input + else + nu = nu + u%Mesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + nu = nu + 1 ! Extended input + end if + + call AllocAry(u_op, nu,'u_op',ErrStat2,ErrMsg2) ! + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + + end if + + Mask = .false. + Mask(MASKID_TRANSLATIONDISP) = .true. + Mask(MASKID_ORIENTATION) = .true. + Mask(MASKID_TRANSLATIONVEL) = .true. + Mask(MASKID_ROTATIONVEL) = .true. + Mask(MASKID_TRANSLATIONACC) = .true. + Mask(MASKID_ROTATIONACC) = .true. + + index = 1 + if ( u%Morison%DistribMesh%Committed ) then + call PackMotionMesh(u%Morison%DistribMesh, u_op, index, FieldMask=Mask) + call PackMotionMesh(u%Morison%LumpedMesh , u_op, index, FieldMask=Mask) + end if + + call PackMotionMesh(u%Mesh, u_op, index, FieldMask=Mask) + + ! extended input: + u_op(index) = 0.0_R8Ki !u%WaveElev0 + + + END IF + + !.................................. + if ( PRESENT( y_op ) ) then + + if (.not. allocated(y_op)) then + call AllocAry(y_op, p%Jac_ny, 'y_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + index = 1 + if ( y%Morison%DistribMesh%Committed ) then + call PackLoadMesh(y%Morison%DistribMesh, y_op, index) + call PackLoadMesh(y%Morison%LumpedMesh , y_op, index) + end if + + call PackLoadMesh(y%Mesh, y_op, index) + call PackLoadMesh(y%AllHdroOrigin, y_op, index) + + index = index - 1 + do i=1,p%NumTotalOuts + y_op(i+index) = y%WriteOutput(i) + end do + + end if + + !.................................. + IF ( PRESENT( x_op ) ) THEN + + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N,'x_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + do i=1,p%WAMIT%SS_Exctn%N ! Loop through all DOFs + x_op(i) = x%WAMIT%SS_Exctn%x(i) + end do + do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all DOFs + x_op(i+p%WAMIT%SS_Exctn%N) = x%WAMIT%SS_Rdtn%x(i) + end do + + END IF + + !.................................. + IF ( PRESENT( dx_op ) ) THEN + + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N,'dx_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + call HydroDyn_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) + return + end if + + do i=1,p%WAMIT%SS_Exctn%N ! Loop through all DOFs + dx_op(i) = dx%WAMIT%SS_Exctn%x(i) + end do + do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all DOFs + dx_op(i+p%WAMIT%SS_Exctn%N) = dx%WAMIT%SS_Rdtn%x(i) + end do + + call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) + + END IF + + !.................................. + IF ( PRESENT( xd_op ) ) THEN + END IF + + !.................................. + IF ( PRESENT( z_op ) ) THEN + END IF + +END SUBROUTINE HD_GetOP + + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE HydroDyn +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn.txt b/OpenFAST/modules/hydrodyn/src/HydroDyn.txt new file mode 100644 index 000000000..ca379172d --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn.txt @@ -0,0 +1,209 @@ +################################################################################################################################### +################################################################################################################################### +# Registry for HydroDyn in the FAST Modularization Framework +# This Registry file is used to create MODULE HydroDyn which contains all of the user-defined types needed in HydroDyn. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt +usefrom Current.txt +usefrom Waves.txt +usefrom Waves2.txt +usefrom Conv_Radiation.txt +usefrom SS_Radiation.txt +usefrom SS_Excitation.txt +usefrom WAMIT.txt +usefrom WAMIT2.txt +usefrom Morison.txt +#usefrom FIT.txt +param HydroDyn/HydroDyn unused INTEGER MaxHDOutputs - 54 - "The maximum number of output channels supported by this module" - +typedef HydroDyn/HydroDyn InitInputType CHARACTER(1024) InputFile - - - "Supplied by Driver: full path and filename for the HydroDyn module" - +typedef ^ ^ LOGICAL UseInputFile - - - "Supplied by Driver: .TRUE. if using a input file, .FALSE. if all inputs are being passed in by the caller" - +typedef ^ ^ CHARACTER(1024) OutRootName - - - "Supplied by Driver: The name of the root file (without extension) including the full path" - +typedef ^ ^ Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ ^ DbKi DT - - - "Supplied by Driver: Simulation time step" "(sec)" +typedef ^ ^ ReKi Gravity - - - "Supplied by Driver: Gravitational acceleration" "(m/s^2)" +typedef ^ ^ DbKi TMax - - - "Supplied by Driver: The total simulation time" "(sec)" +typedef ^ ^ LOGICAL HasIce - - - "Supplied by Driver: Whether this simulation has ice loading (flag)" - +typedef ^ ^ SiKi WaveElevXY {:}{:} - - "Supplied by Driver: X-Y locations for WaveElevation output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number." "m,-" +typedef ^ ^ ReKi PtfmLocationX - - - "Supplied by Driver: X coordinate of platform location in the wave field" "m" +typedef ^ ^ ReKi PtfmLocationY - - - "Supplied by Driver: Y coordinate of platform location in the wave field" "m" +typedef ^ ^ CHARACTER(80) PtfmSgFChr - - - "Platform horizontal surge translation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmSgF - - - "Optionally Supplied by Driver: Platform horizontal surge translation force (flag)" - +typedef ^ ^ CHARACTER(80) PtfmSwFChr - - - "Platform horizontal sway translation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmSwF - - - "Optionally Supplied by Driver: Platform horizontal sway translation force (flag)" - +typedef ^ ^ CHARACTER(80) PtfmHvFChr - - - "Platform vertical heave translation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmHvF - - - "Optionally Supplied by Driver: Platform vertical heave translation force (flag)" - +typedef ^ ^ CHARACTER(80) PtfmRFChr - - - "Platform roll tilt rotation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmRF - - - "Optionally Supplied by Driver: Platform roll tilt rotation force (flag)" - +typedef ^ ^ CHARACTER(80) PtfmPFChr - - - "Platform pitch tilt rotation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmPF - - - "Optionally Supplied by Driver: Platform pitch tilt rotation force (flag)" - +typedef ^ ^ CHARACTER(80) PtfmYFChr - - - "Platform yaw rotation force (flag) or DEFAULT" - +typedef ^ ^ LOGICAL PtfmYF - - - "Optionally Supplied by Driver: Platform yaw rotation force (flag)" - +typedef ^ ^ ReKi AddF0 {6} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - +typedef ^ ^ ReKi AddCLin {6}{6} - - "Additional stiffness matrix" - +typedef ^ ^ ReKi AddBLin {6}{6} - - "Additional linear damping matrix" - +typedef ^ ^ ReKi AddBQuad {6}{6} - - "Additional quadratic damping (drag) matrix" - +typedef ^ ^ Waves_InitInputType Waves - - - "Initialization data for Waves module" - +typedef ^ ^ Waves2_InitInputType Waves2 - - - "Initialization data for Waves module" - +typedef ^ ^ Current_InitInputType Current - - - "Initialization data for Current module" - +typedef ^ ^ CHARACTER(1024) PotFile - - - "The name of the root potential flow file (without extension for WAMIT, complete name for FIT)" - +typedef ^ ^ WAMIT_InitInputType WAMIT - - - "Initialization data for WAMIT module" - +typedef ^ ^ WAMIT2_InitInputType WAMIT2 - - - "Initialization data for WAMIT2 module" - +typedef ^ ^ Morison_InitInputType Morison - - - "Initialization data for Morison module" - +typedef ^ ^ LOGICAL Echo - - - "Echo the input files to a file with the same name as the input but with a .echo extension [T/F]" - +typedef ^ ^ INTEGER PotMod - - - "1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model" - +typedef ^ ^ INTEGER NUserOutputs - - - "Number of Hydrodyn-level requested output channels" - +typedef ^ ^ CHARACTER(ChanLen) UserOutputs {:} - - "This should really be dimensioned with MaxOutPts" - +typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files]" - +typedef ^ ^ LOGICAL OutAll - - - "Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F]" - +typedef ^ ^ INTEGER NumOuts - - - "The number of outputs for this module as requested in the input file" - +typedef ^ ^ CHARACTER(ChanLen) OutList {54} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - +typedef ^ ^ LOGICAL HDSum - - - "Generate a HydroDyn summary file [T/F]" - +typedef ^ ^ INTEGER UnSum - - - "File unit for the HydroDyn summary file [-1 = no summary file]" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "Output format for numerical results" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "Output format for header strings" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType WAMIT_InitOutputType WAMIT - - - "Initialization output from the WAMIT module" - +typedef ^ ^ WAMIT2_InitOutputType WAMIT2 - - - "Initialization output from the WAMIT2 module" - +typedef ^ ^ Waves2_InitOutputType Waves2 - - - "Initialization output from the Waves2 module" - +typedef ^ ^ Morison_InitOutputType Morison - - - "Initialization output from the Morison module" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputHdr {:} - - "The is the list of all HD-related output channel header strings (includes all sub-module channels)" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "The is the list of all HD-related output channel unit strings (includes all sub-module channels)" - +typedef ^ ^ SiKi WaveElevSeries {:}{:} - - "Wave elevation time-series at each of the points given by WaveElevXY. First dimension is the timestep. Second dimension is XY point number corresponding to second dimension of WaveElevXY." (m) +typedef ^ ^ ProgDesc Ver - - - "Version of HydroDyn" +typedef ^ ^ ReKi WtrDens - - - "Water density" (kg/m^3) +typedef ^ ^ ReKi WtrDpth - - - "Water depth" (m) +typedef ^ ^ ReKi MSL2SWL - - - "Offset between still-water level and mean sea level" (m) +typedef ^ ^ CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ InitOutputType INTEGER DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - +typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - + + +# ..... HD_ModuleMapType .................................................................................................................... +typedef ^ HD_ModuleMapType MeshMapType HD_P_2_WRP_P +typedef ^ HD_ModuleMapType MeshMapType M_P_2_WRP_P +typedef ^ HD_ModuleMapType MeshMapType M_L_2_WRP_P + +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType WAMIT_ContinuousStateType WAMIT - - - "continuous states from the wamit module" - +typedef ^ ContinuousStateType WAMIT2_ContinuousStateType WAMIT2 - - - "continuous states from the wamit2 module" - +typedef ^ ContinuousStateType Waves2_ContinuousStateType Waves2 - - - "continuous states from the waves2 module" - +typedef ^ ContinuousStateType Morison_ContinuousStateType Morison - - - "continuous states from the Morison module" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType WAMIT_DiscreteStateType WAMIT - - - "discrete states from the wamit module" - +typedef ^ DiscreteStateType WAMIT2_DiscreteStateType WAMIT2 - - - "discrete states from the wamit2 module" - +#typedef ^ DiscreteStateType FIT_DiscreteStateType FIT - - - "discrete states from the FIT module" - +typedef ^ DiscreteStateType Waves2_DiscreteStateType Waves2 - - - "discrete states from the waves2 module" - +typedef ^ DiscreteStateType Morison_DiscreteStateType Morison - - - "discrete states from the Morison module" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType WAMIT_ConstraintStateType WAMIT - - - "constraint states from WAMIT (may be empty)" - +typedef ^ ConstraintStateType WAMIT2_ConstraintStateType WAMIT2 - - - "constraint states from WAMIT2 (may be empty)" - +typedef ^ ConstraintStateType Waves2_ConstraintStateType Waves2 - - - "constraint states from the waves2 module" - +typedef ^ ConstraintStateType Morison_ConstraintStateType Morison - - - "constraint states from the Morison module" - +# +# +# Define any other states here: +# +typedef ^ OtherStateType WAMIT_OtherStateType WAMIT - - - "OtherState information from the WAMIT module" - +typedef ^ OtherStateType WAMIT2_OtherStateType WAMIT2 - - - "OtherState information from the WAMIT2 module" - +#typedef ^ OtherStateType FIT_OtherStateType FIT - - - "OtherState information from the FIT module" - +typedef ^ OtherStateType Waves2_OtherStateType Waves2 - - - "OtherState information from the Waves2 module" - +typedef ^ ^ Morison_OtherStateType Morison - - - "OtherState information from the Morison module" - + +# ..... 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 MeshType y_mapped - - - "An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ ^ MeshType AllHdroOrigin_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ ^ MeshType MrsnLumpedMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ ^ MeshType MrsnDistribMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ ^ HD_ModuleMapType HD_MeshMap - - - +typedef ^ ^ INTEGER Decimate - - - "The output decimation counter" - +typedef ^ ^ DbKi LastOutTime - - - "Last time step which was written to the output file (sec)" - +typedef ^ ^ INTEGER LastIndWave - - - "The last index used in the wave kinematics arrays, used to optimize interpolation" - +typedef ^ ^ ReKi F_PtfmAdd {6} - - "The total forces and moments due to additional pre-load, stiffness, and damping" - +typedef ^ ^ ReKi F_Hydro {6} - - "The total hydrodynamic forces and moments integrated about the WAMIT reference point" - +typedef ^ ^ ReKi F_Waves {6} - - "The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules)" - +typedef ^ ^ WAMIT_MiscVarType WAMIT - - - "misc var information from the WAMIT module" - +typedef ^ ^ WAMIT2_MiscVarType WAMIT2 - - - "misc var information from the WAMIT2 module" - +typedef ^ ^ Waves2_MiscVarType Waves2 - - - "misc var information from the Waves2 module" - +typedef ^ ^ Morison_MiscVarType Morison - - - "misc var information from the Morison module" - +typedef ^ ^ WAMIT_InputType u_WAMIT - - - "WAMIT module inputs" - +typedef ^ ^ WAMIT2_InputType u_WAMIT2 - - - "WAMIT2 module inputs" - +typedef ^ ^ Waves2_InputType u_Waves2 - - - "Waves2 module inputs" - +# ..... 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 WAMIT_ParameterType WAMIT - - - "Parameter data for the WAMIT module" - +typedef ^ ParameterType WAMIT2_ParameterType WAMIT2 - - - "Parameter data for the WAMIT2 module" - +#typedef ^ ^ FIT_ParameterType FIT - - - "Parameter data for the FIT module" - +typedef ^ ParameterType Waves2_ParameterType Waves2 - - - "Parameter data for the Waves2 module" - +typedef ^ ^ Morison_ParameterType Morison - - - "Parameter data for the Morison module" - +typedef ^ ^ INTEGER PotMod - - - "1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model" - +typedef ^ ^ SiKi WaveTime {:} - - "Array of time samples, (sec)" - +typedef ^ ^ INTEGER NStepWave - - - "Number of data points in the wave kinematics arrays" - +typedef ^ ^ INTEGER NWaveElev - - - "Number of wave elevation outputs" - +typedef ^ ^ SiKi WaveElev {:}{:} - - "Total wave elevation" - +typedef ^ ^ SiKi WaveElev1 {:}{:} - - "First order wave elevation" - +typedef ^ ^ ReKi WtrDpth - - - "Water depth" (m) +typedef ^ ^ ReKi AddF0 {6} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - +typedef ^ ^ ReKi AddCLin {6}{6} - - "Additional stiffness matrix" - +typedef ^ ^ ReKi AddBLin {6}{6} - - "Additional linear damping matrix" - +typedef ^ ^ ReKi AddBQuad {6}{6} - - "Additional quadratic damping (drag) matrix" - +typedef ^ ^ DbKi DT - - - "Time step in seconds for integration of continuous states (if a fixed-step integrator is used) and update of discrete states" - +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "Number of HydroDyn module-level outputs (not the total number including sub-modules" - +typedef ^ ^ INTEGER NumTotalOuts - - - "Number of all requested outputs including sub-modules" - +typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files]" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "Output format for numerical results" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "Output format for header strings" - +typedef ^ ^ CHARACTER(ChanLen) Delim - - - "Delimiter string for outputs, defaults to tab-delimiters" - +typedef ^ ^ INTEGER UnOutFile - - - "File unit for the HydroDyn outputs" - +typedef ^ ^ INTEGER OutDec - - - "Write every OutDec time steps" - +typedef ^ ^ Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ^ R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" - +typedef ^ ^ R8Ki dx {:} - - "vector that determines size of perturbation for x (continuous states)" - +typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix" - +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType Morison_InputType Morison - - - "Morison module inputs" - +typedef ^ InputType MeshType Mesh - - - "Displacements at the WAMIT reference point in the inertial frame" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType WAMIT_OutputType WAMIT - - - "WAMIT module outputs" - +typedef ^ OutputType WAMIT2_OutputType WAMIT2 - - - "WAMIT2 module outputs" - +typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - +typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - +typedef ^ OutputType MeshType Mesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - +typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/OpenFAST/modules/hydrodyn/src/HydroDyn_DriverCode.f90 new file mode 100644 index 000000000..4172037f2 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -0,0 +1,1243 @@ +!********************************************************************************************************************************** +! HydroDyn_DriverCode: This code tests the template modules +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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. +! +!********************************************************************************************************************************** + +PROGRAM HydroDynDriver + + USE NWTC_Library + USE HydroDyn + USE HydroDyn_Types + USE HydroDyn_Output + USE ModMesh_Types + USE VersionInfo + + IMPLICIT NONE + + TYPE HD_Drvr_InitInput + LOGICAL :: Echo + REAL(ReKi) :: Gravity + CHARACTER(1024) :: HDInputFile + CHARACTER(1024) :: OutRootName + LOGICAL :: Linearize + INTEGER :: NSteps + REAL(DbKi) :: TimeInterval + INTEGER :: WAMITInputsMod + CHARACTER(1024) :: WAMITInputsFile + REAL(ReKi) :: uWAMITInSteady(6) + REAL(ReKi) :: uDotWAMITInSteady(6) + REAL(ReKi) :: uDotDotWAMITInSteady(6) + INTEGER :: MorisonInputsMod + CHARACTER(1024) :: MorisonInputsFile + REAL(ReKi) :: uMorisonInSteady(6) + REAL(ReKi) :: uDotMorisonInSteady(6) + REAL(ReKi) :: uDotDotMorisonInSteady(6) + LOGICAL :: WaveElevSeriesFlag !< Should we put together a wave elevation series and save it to file? + REAL(ReKi) :: WaveElevdX !< Spacing in the X direction for wave elevation series (m) + REAL(ReKi) :: WaveElevdY !< Spacing in the Y direction for the wave elevation series (m) + INTEGER(IntKi) :: WaveElevNX !< Number of points in the X direction for the wave elevation series (-) + INTEGER(IntKi) :: WaveElevNY !< Number of points in the X direction for the wave elevation series (-) + END TYPE HD_Drvr_InitInput + +! ----------------------------------------------------------------------------------- +! NOTE: this module and the ModMesh.f90 modules must use the Fortran compiler flag: +! /fpp because of they both have preprocessor statements +! ----------------------------------------------------------------------------------- + + + INTEGER(IntKi), PARAMETER :: NumInp = 1 ! Number of inputs sent to HydroDyn_UpdateStates + + ! Program variables + + REAL(DbKi) :: Time ! Variable for storing time, in seconds + + REAL(DbKi) :: InputTime(NumInp) ! Variable for storing time associated with inputs, in seconds + REAL(DbKi) :: Interval ! HD module requested time interval + INTEGER(B1Ki), ALLOCATABLE :: SaveAry(:) ! Array to store packed data structure + + TYPE(HydroDyn_InitInputType) :: InitInData ! Input data for initialization + TYPE(HydroDyn_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(HydroDyn_ContinuousStateType) :: x ! Continuous states + TYPE(HydroDyn_ContinuousStateType) :: x_new ! Continuous states at updated time + TYPE(HydroDyn_DiscreteStateType) :: xd ! Discrete states + TYPE(HydroDyn_DiscreteStateType) :: xd_new ! Discrete states at updated time + TYPE(HydroDyn_ConstraintStateType) :: z ! Constraint states + TYPE(HydroDyn_ConstraintStateType) :: z_residual ! Residual of the constraint state equations (Z) + TYPE(HydroDyn_OtherStateType) :: OtherState ! Other states + TYPE(HydroDyn_MiscVarType) :: m ! Misc/optimization variables + + TYPE(HydroDyn_ParameterType) :: p ! Parameters + !TYPE(HydroDyn_InputType) :: u ! System inputs [OLD STYLE] + TYPE(HydroDyn_InputType) :: u(NumInp) ! System inputs + TYPE(HydroDyn_OutputType) :: y ! System outputs + + TYPE(HydroDyn_ContinuousStateType) :: dxdt ! First time derivatives of the continuous states + + + INTEGER(IntKi) :: UnWAMITInp ! WAMIT Inputs file identifier + INTEGER(IntKi) :: UnMorisonInp ! Morison Inputs file identifier + INTEGER(IntKi) :: UnHD_Out ! Output file identifier + REAL(ReKi), ALLOCATABLE :: WAMITin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for WAMIT + REAL(ReKi), ALLOCATABLE :: Morisonin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for Morison elements + + TYPE(MeshType) :: PMesh ! Point mesh that we will use to map to Morison and u(1)%Mesh + TYPE(MeshMapType) :: Map_P_to_MorisonDist + TYPE(MeshMapType) :: Map_P_to_MorisonLumped + + INTEGER(IntKi) :: I ! Generic loop counter + INTEGER(IntKi) :: J ! Generic loop counter + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). + CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. + TYPE(HD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program + + integer :: StrtTime (8) ! Start time of simulation (including intialization) + integer :: SimStrtTime (8) ! Start time of simulation (after initialization) + real(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds + real(ReKi) :: UsrTime1 ! User CPU time for simulation initialization + real(ReKi) :: UsrTime2 ! User CPU time for simulation (without intialization) + real(DbKi) :: TiLstPrn ! The simulation time of the last print + real(DbKi) :: t_global ! Current simulation time (for global/FAST simulation) + real(DbKi) :: SttsTime ! Amount of time between screen status messages (sec) + integer :: n_SttsTime ! Number of time steps between screen status messages (-) + + + ! For testing + LOGICAL :: DoTight = .FALSE. + REAL(DbKi) :: maxAngle ! For debugging, see what the largest rotational angle input is for the simulation + CHARACTER(10) :: AngleMsg ! For debugging, a string version of the largest rotation input + INTEGER :: UnMeshDebug + CHARACTER(50) :: MeshDebugFile + + CHARACTER(20) :: FlagArg ! Flag argument from command line + CHARACTER(200) :: git_commit ! String containing the current git commit hash + + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'HydroDyn Driver', '', '' ) ! The version number of this program. + + ! Variables Init + Time = -99999 + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + + + ! TODO: Need to think some more about how to pass DRIVER-level initialization data to the HydroDyn module because if UseInputFile = .FALSE. + ! then the input processing code will still be querying the *Chr input data to look for the use of the 'DEFAULT' string and to set that + ! data to the driver's version instead of using a module-specific version. + ! Currently, these variables are: + ! InitInp%Waves%WavePkShpChr + ! InitInp%Current%CurrSSDirChr + ! InitInp%PtfmSgFChr + ! InitInp%PtfmSwFChr + ! InitInp%PtfmHvFChr + ! InitInp%PtfmRFChr + ! InitInp%PtfmPFChr + ! InitInp%PtfmYFChr + ! InitInp%Morison%InpMembers(k)%FillDensChr + ! + ! + + CALL NWTC_Init( ProgNameIn=version%Name ) + + drvrFilename = '' + CALL CheckArgs( drvrFilename, Flag=FlagArg ) + IF ( LEN( TRIM(FlagArg) ) > 0 ) CALL NormStop() + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + ! Parse the driver input file and run the simulation based on that file + CALL ReadDriverInputFile( drvrFilename, drvrInitInp, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + InitInData%Gravity = drvrInitInp%Gravity + InitInData%UseInputFile = .TRUE. + InitInData%InputFile = drvrInitInp%HDInputFile + InitInData%OutRootName = drvrInitInp%OutRootName + InitInData%TMax = drvrInitInp%NSteps * drvrInitInp%TimeInterval + InitInData%Linearize = drvrInitInp%Linearize + + ! Get the current time + call date_and_time ( Values=StrtTime ) ! Let's time the whole simulation + call cpu_time ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + SttsTime = 1.0 ! seconds + + ! figure out how many time steps we should go before writing screen output: + n_SttsTime = MAX( 1, NINT( SttsTime / drvrInitInp%TimeInterval ) ) ! this may not be the final TimeInterval, though!!! GJH 8/14/14 + + !BJJ: added this for IceFloe/IceDyn + InitInData%hasIce = .FALSE. + + + + + +!------------------------------------------------------------------------------------- +! Begin Simulation Setup +!------------------------------------------------------------------------------------- + + + IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN + + ! Open the WAMIT inputs data file + CALL GetNewUnit( UnWAMITInp ) + CALL OpenFInpFile ( UnWAMITInp, drvrInitInp%WAMITInputsFile, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) STOP + + + ALLOCATE ( WAMITin(drvrInitInp%NSteps, 19), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WAMITin array.' + CALL WrScr( ErrMsg ) + CLOSE( UnWAMITInp ) + STOP + END IF + + DO n = 1,drvrInitInp%NSteps + READ (UnWAMITInp,*,IOSTAT=ErrStat) (WAMITin (n,J), J=1,19) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error reading the WAMIT input time-series file. ' + CALL WrScr( ErrMsg ) + STOP + END IF + END DO + + ! Close the inputs file + CLOSE ( UnWAMITInp ) + END IF + + IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN + + ! Open the Morison inputs data file + CALL GetNewUnit( UnMorisonInp ) + CALL OpenFInpFile ( UnMorisonInp, drvrInitInp%MorisonInputsFile, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) STOP + + + ALLOCATE ( MorisonIn(drvrInitInp%NSteps, 19), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for MorisonIn array.' + CALL WrScr( ErrMsg ) + CLOSE( UnMorisonInp ) + STOP + END IF + + DO n = 1,drvrInitInp%NSteps + READ (UnMorisonInp,*,IOSTAT=ErrStat) (MorisonIn (n,J), J=1,19) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error reading the Morison input time-series file. ' + CALL WrScr( ErrMsg ) + STOP + END IF + END DO + + ! Close the inputs file + CLOSE ( UnMorisonInp ) + END IF + + + ! Setup the arrays for the wave elevation timeseries if requested by the driver input file + IF ( drvrInitInp%WaveElevSeriesFlag ) THEN + ALLOCATE ( InitInData%WaveElevXY(2,drvrInitInp%WaveElevNX*drvrInitInp%WaveElevNY), STAT=ErrStat ) + IF ( ErrStat >= ErrID_Fatal ) THEN + CALL HydroDyn_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + STOP + END IF + + ! Set the values + n = 0 ! Dummy counter we are using to get the current point number + DO I = 0,drvrInitInp%WaveElevNX-1 + DO J = 0, drvrInitInp%WaveElevNY-1 + n = n+1 + ! X dimension + InitInData%WaveElevXY(1,n) = drvrInitInp%WaveElevDX*(I - 0.5*(drvrInitInp%WaveElevNX-1)) + ! Y dimension + InitInData%WaveElevXY(2,n) = drvrInitInp%WaveElevDY*(J - 0.5*(drvrInitInp%WaveElevNY-1)) + ENDDO + ENDDO + ENDIF + + + ! Setup mesh for input motions for Morison and WAMIT + CALL MeshCreate( BlankMesh = PMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + IF ( ErrStat >= ErrID_Fatal ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + + CALL MeshPositionNode (PMesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat & + , ErrMsg ) + IF ( ErrStat >= ErrID_Fatal ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + + CALL MeshConstructElement( PMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1 ) + IF ( ErrStat >= ErrID_Fatal ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + + CALL MeshCommit ( PMesh, ErrStat, ErrMsg ) + IF ( ErrStat >= ErrID_Fatal ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + + + + ! Initialize the module + Interval = drvrInitInp%TimeInterval + CALL HydroDyn_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, Interval, InitOutData, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + IF ( Interval /= drvrInitInp%TimeInterval) THEN + CALL WrScr('The HydroDyn Module attempted to change timestep interval, but this is not allowed. The HydroDyn Module must use the Driver Interval.') + call HD_DvrCleanup() + + END IF + + + ! Write the gridded wave elevation data to a file + + IF ( drvrInitInp%WaveElevSeriesFlag ) CALL WaveElevGrid_Output (drvrInitInp, InitInData, InitOutData, p, ErrStat, ErrMsg) + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + + ! Destroy initialization data + + CALL HydroDyn_DestroyInitInput( InitInData, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + + + ! Set any steady-state inputs, once before the time-stepping loop + + IF ( u(1)%Mesh%Initialized ) THEN + + IF ( drvrInitInp%WAMITInputsMod /= 2 ) THEN + + + u(1)%Mesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) + + + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uWAMITInSteady(4), ReKi), REAL(drvrInitInp%uWAMITInSteady(5), ReKi), REAL(drvrInitInp%uWAMITInSteady(6), ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%Mesh%Orientation(:,:,1) = dcm + + u(1)%Mesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) + u(1)%Mesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) + u(1)%Mesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) + u(1)%Mesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) + + END IF + END IF + + + IF ( drvrInitInp%MorisonInputsMod /= 2 ) THEN + IF ( u(1)%Morison%DistribMesh%Initialized ) THEN + u(1)%Morison%DistribMesh%TranslationDisp(1,:) = drvrInitInp%uMorisonInSteady(1) + u(1)%Morison%DistribMesh%TranslationDisp(2,:) = drvrInitInp%uMorisonInSteady(2) + u(1)%Morison%DistribMesh%TranslationDisp(3,:) = drvrInitInp%uMorisonInSteady(3) + + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uMorisonInSteady(4),ReKi), REAL(drvrInitInp%uMorisonInSteady(5),ReKi), REAL(drvrInitInp%uMorisonInSteady(6),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + DO I = 1, u(1)%Morison%DistribMesh%nNodes + u(1)%Morison%DistribMesh%Orientation(:,:,I) = dcm + END DO + + u(1)%Morison%DistribMesh%TranslationVel(1,:) = drvrInitInp%uDotMorisonInSteady(1) + u(1)%Morison%DistribMesh%TranslationVel(2,:) = drvrInitInp%uDotMorisonInSteady(2) + u(1)%Morison%DistribMesh%TranslationVel(3,:) = drvrInitInp%uDotMorisonInSteady(3) + u(1)%Morison%DistribMesh%RotationVel(1,:) = drvrInitInp%uDotMorisonInSteady(4) + u(1)%Morison%DistribMesh%RotationVel(2,:) = drvrInitInp%uDotMorisonInSteady(5) + u(1)%Morison%DistribMesh%RotationVel(3,:) = drvrInitInp%uDotMorisonInSteady(6) + u(1)%Morison%DistribMesh%TranslationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(1) + u(1)%Morison%DistribMesh%TranslationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(2) + u(1)%Morison%DistribMesh%TranslationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(3) + u(1)%Morison%DistribMesh%RotationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(4) + u(1)%Morison%DistribMesh%RotationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(5) + u(1)%Morison%DistribMesh%RotationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(6) + END IF + IF ( u(1)%Morison%LumpedMesh%Initialized ) THEN + DO I = 1, u(1)%Morison%LumpedMesh%nNodes + u(1)%Morison%LumpedMesh%Orientation(:,:,I) = dcm + END DO + u(1)%Morison%LumpedMesh%TranslationVel(1,:) = drvrInitInp%uDotMorisonInSteady(1) + u(1)%Morison%LumpedMesh%TranslationVel(2,:) = drvrInitInp%uDotMorisonInSteady(2) + u(1)%Morison%LumpedMesh%TranslationVel(3,:) = drvrInitInp%uDotMorisonInSteady(3) + u(1)%Morison%LumpedMesh%RotationVel(1,:) = drvrInitInp%uDotMorisonInSteady(4) + u(1)%Morison%LumpedMesh%RotationVel(2,:) = drvrInitInp%uDotMorisonInSteady(5) + u(1)%Morison%LumpedMesh%RotationVel(3,:) = drvrInitInp%uDotMorisonInSteady(6) + u(1)%Morison%LumpedMesh%TranslationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(1) + u(1)%Morison%LumpedMesh%TranslationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(2) + u(1)%Morison%LumpedMesh%TranslationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(3) + u(1)%Morison%LumpedMesh%RotationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(4) + u(1)%Morison%LumpedMesh%RotationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(5) + u(1)%Morison%LumpedMesh%RotationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(6) + + END IF + END IF + + ! Setup mesh mapping for Morison motion + IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN + IF ( u(1)%Morison%DistribMesh%Initialized ) THEN + ! create mapping from PMesh (used for WAMIT mesh among others) to Morison. This will be used to map the motions for Morison timeseries inputs + CALL MeshMapCreate( PMesh, u(1)%Morison%DistribMesh, Map_P_to_MorisonDist, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) call HD_DvrCleanup() + ENDIF + IF ( u(1)%Morison%LumpedMesh%Initialized ) THEN + ! create mapping from PMesh (used for WAMIT mesh among others) to Morison. This will be used to map the motions for Morison timeseries inputs + CALL MeshMapCreate( PMesh, u(1)%Morison%LumpedMesh, Map_P_to_MorisonLumped, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) call HD_DvrCleanup() + ENDIF + ENDIF + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + Time = 0.0 + CALL SimStatus_FirstTime( TiLstPrn, PrevClockTime, SimStrtTime, UsrTime2, time, InitInData%TMax ) + + maxAngle = 0.0 + + DO n = 1, drvrInitInp%NSteps + + Time = (n-1) * drvrInitInp%TimeInterval + InputTime(1) = Time + + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + + IF ( u(1)%Mesh%Initialized ) THEN + + IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN + + + u(1)%Mesh%TranslationDisp(:,1) = WAMITin(n,2:4) + + + ! Compute direction cosine matrix from the rotation angles + + IF ( abs(WAMITin(n,5)) > maxAngle ) maxAngle = abs(WAMITin(n,5)) + IF ( abs(WAMITin(n,6)) > maxAngle ) maxAngle = abs(WAMITin(n,6)) + IF ( abs(WAMITin(n,7)) > maxAngle ) maxAngle = abs(WAMITin(n,7)) + + CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%Mesh%Orientation(:,:,1) = dcm + + + u(1)%Mesh%TranslationVel(:,1) = WAMITin(n,8:10) + u(1)%Mesh%RotationVel(:,1) = WAMITin(n,11:13) + u(1)%Mesh%TranslationAcc(:,1) = WAMITin(n,14:16) + u(1)%Mesh%RotationAcc(:,1) = WAMITin(n,17:19) + + END IF + + END IF + + + IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN + ! Set the Morison Inputs from a time series input file + PMesh%TranslationDisp(:,1) = MorisonIn(n,2:4) + + ! Compute direction cosine matrix from the rotation angles + IF ( abs(MorisonIn(n,5)) > maxAngle ) maxAngle = abs(MorisonIn(n,5)) + IF ( abs(MorisonIn(n,6)) > maxAngle ) maxAngle = abs(MorisonIn(n,6)) + IF ( abs(MorisonIn(n,7)) > maxAngle ) maxAngle = abs(MorisonIn(n,7)) + + CALL SmllRotTrans( 'InputRotation', REAL(MorisonIn(n,5),ReKi), REAL(MorisonIn(n,6),ReKi), REAL(MorisonIn(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + PMesh%Orientation(:,:,1) = dcm + + PMesh%TranslationVel(:,1) = MorisonIn(n,8:10) + PMesh%RotationVel(:,1) = MorisonIn(n,11:13) + PMesh%TranslationAcc(:,1) = MorisonIn(n,14:16) + PMesh%RotationAcc(:,1) = MorisonIn(n,17:19) + + IF ( u(1)%Morison%DistribMesh%Initialized ) THEN + CALL Transfer_Point_to_Line2( PMesh, u(1)%Morison%DistribMesh, Map_P_to_MorisonDist, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) call HD_DvrCleanup() + END IF + IF ( u(1)%Morison%LumpedMesh%Initialized ) THEN + CALL Transfer_Point_to_Point( PMesh, u(1)%Morison%LumpedMesh, Map_P_to_MorisonLumped, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) call HD_DvrCleanup() + END IF + END IF + + + ! Calculate outputs at n + + CALL HydroDyn_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + + + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + + CALL HydroDyn_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + + IF ( MOD( n + 1, n_SttsTime ) == 0 ) THEN + + CALL SimStatus( TiLstPrn, PrevClockTime, time, InitInData%TMax ) + + ENDIF + + ! Write output to a file which is managed by the driver program and not the individual modules + ! TODO + + END DO + + + +! For now, finish here. +call HD_DvrCleanup() + + + + CONTAINS + + +!==================================================================================================== +SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) +! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to +! any existing echo information +!---------------------------------------------------------------------------------------------------- + LOGICAL, INTENT( IN ) :: EchoFlag ! local version of echo flag + INTEGER, INTENT( IN ) :: UnEcho ! echo unit number + + + ! Close this module's echo file + + IF ( EchoFlag ) THEN + CLOSE(UnEcho) + END IF + + + +END SUBROUTINE CleanupEchoFile + +subroutine HD_DvrCleanup() + + ! Local variables + character(len(errMsg)) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + + + errStat2 = ErrID_None + errMsg2 = "" + + + + call HydroDyn_DestroyInitInput( InitInData, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'HD_DvrCleanup' ) + call HydroDyn_DestroyDiscState( xd_new, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'HD_DvrCleanup' ) + call HydroDyn_DestroyContState( x_new, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'HD_DvrCleanup' ) + call HydroDyn_End( u(1), p, x, xd, z, OtherState, y, m, errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'HD_DvrCleanup' ) + + if ( ErrStat /= ErrID_None ) then !This assumes PRESENT(ErrID) is also .TRUE. : + CALL WrScr(NewLine//NewLine//'Error status and messages after execution:'//NewLine//' ErrStat: '// & + TRIM(Num2LStr(ErrStat))//NewLine//' ErrMsg returned: '//TRIM(ErrMsg)//NewLine) + if ( time < 0.0 ) then + ErrMsg = 'at initialization' + else if ( time > InitInData%TMax ) then + ErrMsg = 'after computing the solution' + else + ErrMsg = 'at simulation time '//trim(Num2LStr(time))//' of '//trim(Num2LStr(InitInData%TMax))//' seconds' + end if + + + CALL ProgAbort( 'HydroDyn encountered an error '//trim(errMsg)//'.'//NewLine//' Simulation error level: '& + //trim(GetErrStr(errStat)), TrapErrors=.FALSE., TimeWait=3._ReKi ) ! wait 3 seconds (in case they double-clicked and got an error) + end if + + ! Print *, time + call RunTimes( StrtTime, REAL(UsrTime1,ReKi), SimStrtTime, REAL(UsrTime2,ReKi), time ) + call NormStop() + +end subroutine HD_DvrCleanup + + +SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) + + CHARACTER(1024), INTENT( IN ) :: inputFile + TYPE(HD_Drvr_InitInput), INTENT( OUT ) :: InitInp + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + + INTEGER :: I ! generic integer for counting + INTEGER :: J ! generic integer for counting + CHARACTER( 2) :: strI ! string version of the loop counter + + INTEGER :: UnIn ! Unit number for the input file + INTEGER :: UnEchoLocal ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFile ! Name of HydroDyn echo file + CHARACTER(1024) :: Line ! String to temporarially hold value of read line + CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name + CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement + CHARACTER(1024) :: FileName ! Name of HydroDyn input file + + REAL(ReKi) :: TmpRealVar2(2) !< Temporary real array size 2 + INTEGER(IntKi) :: TmpIntVar2(2) !< Temporary integer array size 2 + + + + ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input + UnEchoLocal = -1 + + FileName = TRIM(inputFile) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile ( UnIn, FileName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + CALL WrScr( 'Opening HydroDyn Driver input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'HydroDyn Driver input file header line 1', ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'HydroDyn Driver input file header line 2', ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! Echo Input Files. + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( InitInp%Echo ) THEN + + EchoFile = TRIM(FileName)//'.ech' + CALL GetNewUnit( UnEchoLocal ) + CALL OpenEcho ( UnEchoLocal, EchoFile, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + !ErrMsg = ' Failed to open Echo file.' + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + REWIND(UnIn) + + CALL ReadCom( UnIn, FileName, 'HydroDyn Driver input file header line 1', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read HydroDyn Driver input file header line 1.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'HydroDyn Driver input file header line 2', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read HydroDyn Driver input file header line 2.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat, ErrMsg, UnEchoLocal ) + !WRITE (UnEchoLocal,Frmt ) InitInp%Echo, 'Echo', 'Echo input file' + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Echo parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + END IF + !------------------------------------------------------------------------------------------------- + ! Environmental conditions section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! Gravity - Gravity. + + CALL ReadVar ( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Gravity parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! HYDRODYN section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'HYDRODYN header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! HDInputFile + + CALL ReadVar ( UnIn, FileName, InitInp%HDInputFile, 'HDInputFile', & + 'HydroDyn input filename', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read HDInputFile parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! OutRootName + + CALL ReadVar ( UnIn, FileName, InitInp%OutRootName, 'OutRootName', & + 'HydroDyn output root filename', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read OutRootName parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + ! Linearize + + CALL ReadVar ( UnIn, FileName, InitInp%Linearize, 'Linearize', & + 'Linearize parameter', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Linearize parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + ! NSteps + + CALL ReadVar ( UnIn, FileName, InitInp%NSteps, 'NSteps', & + 'Number of time steps in the HydroDyn simulation', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read NSteps parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! TimeInterval + + CALL ReadVar ( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', & + 'Time interval for any HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read TimeInterval parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! WAMIT INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'WAMIT INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + + ! WAMITInputsMod + + CALL ReadVar ( UnIn, FileName, InitInp%WAMITInputsMod, 'WAMITInputsMod', & + 'Model for the WAMIT inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read WAMITInputsMod parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! WAMITInputsFile + + CALL ReadVar ( UnIn, FileName, InitInp%WAMITInputsFile, 'WAMITInputsFile', & + 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read WAMITInputsFile parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! WAMIT STEADY STATE INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'WAMIT STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + + ! uWAMITInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uWAMITInSteady, 6, 'uWAMITInSteady', & + 'WAMIT Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uWAMITInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotWAMITInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotWAMITInSteady, 6, 'uDotWAMITInSteady', & + 'WAMIT Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotWAMITInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotDotWAMITInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotWAMITInSteady, 6, 'uDotDotWAMITInSteady', & + 'WAMIT Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotDotWAMITInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + IF ( InitInp%WAMITInputsMod /= 1 ) THEN + InitInp%uWAMITInSteady = 0.0 + InitInp%uDotWAMITInSteady = 0.0 + InitInp%uDotDotWAMITInSteady = 0.0 + END IF + + + !------------------------------------------------------------------------------------------------- + ! Morison INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Morison INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + + ! MorisonInputsMod + + CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsMod, 'MorisonInputsMod', & + 'Model for the Morison inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read MorisonInputsMod parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! MorisonInputsFile + + CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsFile, 'MorisonInputsFile', & + 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read MorisonInputsFile parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Morison STEADY STATE INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Morison STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + + ! uMorisonInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uMorisonInSteady, 6, 'uMorisonInSteady', & + 'Morison Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uMorisonInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotMorisonInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotMorisonInSteady, 6, 'uDotMorisonInSteady', & + 'Morison Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotMorisonInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotDotMorisonInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotMorisonInSteady, 6, 'uDotDotMorisonInSteady', & + 'Morison Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotDotMorisonInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + IF ( InitInp%MorisonInputsMod /= 1 ) THEN + InitInp%uMorisonInSteady = 0.0 + InitInp%uDotMorisonInSteady = 0.0 + InitInp%uDotDotMorisonInSteady = 0.0 + END IF + + + !------------------------------------------------------------------------------------------------- + !> ### Waves elevation series section + !------------------------------------------------------------------------------------------------- + + !> Header + +CALL ReadCom( UnIn, FileName, 'Waves multipoint elevation output header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + !> WaveElevSeriesFlag -- are we doing multipoint wave elevation output? + CALL ReadVar ( UnIn, FileName, InitInp%WaveElevSeriesFlag, 'WaveElevSeriesFlag', 'WaveElevSeriesFlag', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read WaveElevSeries parameter.' + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + !> WaveElevDX and WaveElevNY -- point spacing (m) + CALL ReadAry ( UnIn, FileName, TmpRealVar2, 2, 'WaveElevDX WaveElevDY', & + 'WaveElevSeries spacing -- WaveElevDX WaveElevDY', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Failed to read WaveElevDX and WaveElevDY parameters.',ErrStat,ErrMsg,'ReadDriverInputFile') + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + InitInp%WaveElevDX = TmpRealVar2(1) + InitInp%WaveElevDY = TmpRealVar2(2) + + + + !> WaveElevNX and WaveElevNY -- point spacing (m) + CALL ReadAry ( UnIn, FileName, TmpIntVar2, 2, 'WaveElevNX WaveElevNY', & + 'WaveElevSeries points -- WaveElevNX WaveElevNY', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,' Failed to read WaveElevNX and WaveElevNY parameters.',ErrStat,ErrMsg,'ReadDriverInputFile') + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + IF (MOD(TmpIntVar2(1),2) == 0) THEN + TmpIntVar2(1) = TmpIntVar2(1)+1 + CALL SetErrStat( ErrID_Warn, "Changing WaveElevNX to an odd number ("//TRIM(Num2LStr(TmpIntVar2(1)))// & + ") so that there is a point at the origin.",ErrStat,ErrMsg,'ReadDriverInputFile' ) + ENDIF + IF (MOD(TmpIntVar2(2),2) == 0) THEN + TmpIntVar2(2) = TmpIntVar2(2)+1 + CALL SetErrStat( ErrID_Warn, "Changing WaveElevNX to an odd number ("//TRIM(Num2LStr(TmpIntVar2(2)))// & + ") so that there is a point at the origin.",ErrStat,ErrMsg,'ReadDriverInputFile' ) + ENDIF + InitInp%WaveElevNX = TmpIntVar2(1) + InitInp%WaveElevNY = TmpIntVar2(2) + + + !> if the flag was false, set the spacing and number of points to 0 + IF ( .NOT. InitInp%WaveElevSeriesFlag ) THEN + InitInp%WaveElevDX = 0.0_ReKi + InitInp%WaveElevDY = 0.0_ReKi + InitInp%WaveElevNX = 0_IntKi + InitInp%WaveElevNY = 0_IntKi + ENDIF + + + + + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + +END SUBROUTINE ReadDriverInputFile + +SUBROUTINE WaveElevGrid_Output (drvrInitInp, HDynInitInp, HDynInitOut, HDyn_p, ErrStat, ErrMsg) + + TYPE(HD_drvr_InitInput), INTENT( IN ) :: drvrInitInp + TYPE(HydroDyn_InitInputType), INTENT( IN ) :: HDynInitInp + TYPE(HydroDyn_InitOutputType), INTENT( IN ) :: HDynInitOut ! Output data from initialization + TYPE(HydroDyn_ParameterType), INTENT( IN ) :: HDyn_p ! Output data from initialization + INTEGER, 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(1024) :: ErrMsgTmp !< Temporary variable for the error message + + INTEGER(IntKi) :: WaveElevFileUn !< Number for the output file for the wave elevation series + CHARACTER(1024) :: WaveElevFileName !< Name for the output file for the wave elevation series + CHARACTER(128) :: WaveElevFmt !< Format specifier for the output file for wave elevation series + + + WaveElevFmt = "(F14.7,3x,F14.7,3x,F14.7)" + + ErrMsg = "" + ErrStat = ErrID_None + ErrMsgTmp = "" + ErrStatTmp = ErrID_None + + + ! If we calculated the wave elevation at a set of coordinates for use with making movies, put it into an output file + WaveElevFileName = TRIM(drvrInitInp%OutRootName)//".WaveElev.out" + CALL GetNewUnit( WaveElevFileUn ) + + CALL OpenFOutFile( WaveElevFileUn, WaveElevFileName, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None) THEN + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + ! Write some useful header information +! WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(HDyn_Drv_ProgDesc))// & +! ' on '//CurDate()//' at '//CurTime()//'.' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated on '//CurDate()//' at '//CurTime()//'.' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wave elevations at a series of points '// & + 'through the entire timeseries.' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '## It is arranged as blocks of X,Y,Elevation at each timestep' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '## Each block is separated by two blank lines for use in gnuplot' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# WaveTMax = '//TRIM(Num2LStr(HDyn_p%WaveTime(HDyn_P%NStepWave))) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# NStepWave = '//TRIM(Num2LStr(HDyn_p%NStepWave)) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# GridXPoints = '//TRIM(Num2LStr(drvrInitInp%WaveElevNX)) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# GridYPoints = '//TRIM(Num2LStr(drvrInitInp%WaveElevNY)) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# GridDX = '//TRIM(Num2LStr(drvrInitInp%WaveElevDX)) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# GridDY = '//TRIM(Num2LStr(drvrInitInp%WaveElevDY)) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# MaxWaveElev = '//TRIM(Num2LStr(MAXVAL(HDynInitOut%WaveElevSeries))) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# MinWaveElev = '//TRIM(Num2LStr(MINVAL(HDynInitOut%WaveElevSeries))) + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# ' + + ! Timestep looping + DO I = 0,HDyn_p%NStepWave + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) NewLine + WRITE (WaveElevFileUn,'(A)', IOSTAT=ErrStatTmp ) '# Time: '//TRIM(Num2LStr(HDyn_p%WaveTime(I))) + ! Now output the X,Y, Elev info for this timestep + DO J=1,SIZE(HDynInitInp%WaveElevXY,DIM=2) + WRITE (WaveElevFileUn,WaveElevFmt, IOSTAT=ErrStatTmp ) HDynInitInp%WaveElevXY(1,J),& + HDynInitInp%WaveElevXY(2,J),HDynInitOut%WaveElevSeries(I,J) + ENDDO + + ENDDO + + ! Done. Close the file + CLOSE (WaveElevFileUn) + +END SUBROUTINE WaveElevGrid_Output + +!---------------------------------------------------------------------------------------------------------------------------------- + +END PROGRAM HydroDynDriver + diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn_Input.f90 b/OpenFAST/modules/hydrodyn/src/HydroDyn_Input.f90 new file mode 100644 index 000000000..025e7e322 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -0,0 +1,4324 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 HydroDyn_Input + + ! This MODULE stores variables used for input. + + USE NWTC_Library + USE HydroDyn_Types + USE HydroDyn_Output + USE Waves + USE Morison + USE WAMIT_Output + USE WAMIT2_Output + USE Waves2_Output + USE Morison_Output + USE NWTC_RandomNumber + IMPLICIT NONE + + PRIVATE :: CleanupEchoFile + PRIVATE :: CheckMeshOutput + +CONTAINS + +!==================================================================================================== +FUNCTION CheckMeshOutput( output, numMemberOut, MOutLst, numJointOut ) +! The routine +!---------------------------------------------------------------------------------------------------- +! + CHARACTER(ChanLen), INTENT ( IN ) :: output + INTEGER, INTENT ( IN ) :: numMemberOut + TYPE(Morison_MOutput), INTENT ( IN ) :: MOutLst(:) + INTEGER, INTENT ( IN ) :: numJointOut + !INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + !CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + LOGICAL :: CheckMeshOutput + + INTEGER :: ErrStat + CHARACTER(ChanLen) :: outputTmp + INTEGER :: indx1, indx2 + CHARACTER(4) :: testStr + outputTmp = TRIM(output) + + testStr = outputTmp(1:4) + CALL Conv2UC( testStr ) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + IF ( INDEX( '-_', outputTmp(1:1) ) > 0 ) THEN + + ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + outputTmp = outputTmp(2:) + testStr = outputTmp(1:4) + CALL Conv2UC( testStr ) + + ELSE IF ( INDEX( 'mM', outputTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + + IF ( ( INDEX( 'mM', outputTmp(2:2) ) > 0 ) .OR. ( INDEX( 'jJ', outputTmp(2:2) ) > 0 ) ) THEN + outputTmp = outputTmp(2:) + + END IF + + ELSE IF ( INDEX( 'jJ', outputTmp(1:1) ) == 0 .AND. ( testStr /= 'WAVE' ) ) THEN + ! Invalid output label because the label does not start: -M,-m,-J,-j,_M,_m,_J,_j,MM,mM,Mm,mm,MJ,mJ,Mj,mj, j,J,m,M + CheckMeshOutput = .FALSE. + RETURN + END IF + + IF (( INDEX( 'mM', outputTmp(1:1) ) > 0 ) .OR. ( INDEX( 'jJ', outputTmp(1:1) ) > 0 )) THEN + ! Read the second character, it should be a number from 1 to 9 + + READ( outputTmp(2:2), '(i1)', IOSTAT = ErrStat) indx1 + IF ( ErrStat /=0 ) THEN + ! Not a numerical digit!!! + CheckMeshOutput = .FALSE. + RETURN + END IF + + ! Examine members + IF ( INDEX( 'mM', outputTmp(1:1) ) > 0 ) THEN + IF ( indx1 > numMemberOut ) THEN + CheckMeshOutput = .FALSE. + RETURN + END IF + ! Now make sure the next letter is n or N and then look for the second index + IF ( INDEX( 'nN', outputTmp(3:3) ) == 0 ) THEN + ! Invalid member label + CheckMeshOutput = .FALSE. + RETURN + END IF + READ( outputTmp(4:4), '(i1)', IOSTAT = ErrStat) indx2 + IF ( indx2 > MOutLst(indx1)%NOutLoc ) THEN + CheckMeshOutput = .FALSE. + RETURN + END IF + + + END IF + + IF ( INDEX( 'jJ', outputTmp(1:1) ) > 0 ) THEN + IF ( indx1 > numJointOut ) THEN + CheckMeshOutput = .FALSE. + RETURN + END IF + END IF + ELSE + ! This should be a wave elevation channel + READ( outputTmp(5:5), '(i1)', IOSTAT = ErrStat) indx1 + IF ( ErrStat /=0 ) THEN + ! Not a numerical digit!!! + CheckMeshOutput = .FALSE. + RETURN + END IF + END IF + + CheckMeshOutput = .TRUE. + +END FUNCTION CheckMeshOutput + +!==================================================================================================== +SUBROUTINE PrintBadChannelWarning(NUserOutputs, UserOutputs , foundMask, ErrStat, ErrMsg ) +! The routine prints out warning messages if the user has requested invalid output channel names +! The errstat is set to ErrID_Warning if any element in foundMask is .FALSE. +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + LOGICAL, INTENT( IN ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER :: I + + ErrStat = ErrID_None + ErrMsg = '' + + DO I = 1, NUserOutputs + IF (.NOT. foundMask(I)) THEN + ErrMsg = ' A requested output channel is invalid' + CALL ProgWarn( 'The requested output channel is invalid: ' // UserOutputs(I) ) + ErrStat = ErrID_Warn + END IF + END DO + + + +END SUBROUTINE PrintBadChannelWarning + + +!==================================================================================================== +SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) +! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to +! any existing echo information +!---------------------------------------------------------------------------------------------------- + LOGICAL, INTENT( IN ) :: EchoFlag ! local version of echo flag + INTEGER, INTENT( IN ) :: UnEcho ! echo unit number + + + ! Close this module's echo file + + IF ( EchoFlag ) THEN + CLOSE(UnEcho) + END IF + + + +END SUBROUTINE CleanupEchoFile + + + + +!==================================================================================================== +SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) +! This public subroutine reads the input required for HydroDyn from the file whose name is an +! input parameter. +!---------------------------------------------------------------------------------------------------- + + + ! Passed variables + + TYPE(HydroDyn_InitInputType), INTENT( INOUT ) :: InitInp ! the hydrodyn data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + + INTEGER :: I ! generic integer for counting +! INTEGER :: J ! generic integer for counting + CHARACTER( 2) :: strI ! string version of the loop counter + + INTEGER :: UnIn ! Unit number for the input file +! LOGICAL :: EchoStore ! Stored version of NWTC_Library Echo variable +! INTEGER :: UnEchoStore ! Stored unit name for another module's echo file + INTEGER :: UnEchoLocal ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFile ! Name of HydroDyn echo file + CHARACTER(1024) :: Line ! String to temporarially hold value of read line +! CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name +! CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement + CHARACTER(1024) :: FileName ! Name of HydroDyn input file + CHARACTER( 35) :: Frmt ! Output format for logical parameters. (matches NWTC Subroutine Library format) +! INTEGER :: JointID ! Temporary storage of JointID read from HydroDyn input file +! INTEGER :: PropSetID ! Temporary storage of PropSetID read from HydroDyn input file +! INTEGER :: MemberID ! Temporary storage of MemberID read from HydroDyn input file + INTEGER, ALLOCATABLE :: tmpArray(:) ! Temporary array storage of the joint output list + CHARACTER(1) :: Line1 ! The first character of an input line + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + ! Initialize local data + + UnEchoLocal = -1 + Frmt = "( 2X, L11, 2X, A, T30, ' - ', A )" + ErrStat = ErrID_None + ErrMsg = "" + InitInp%Echo = .FALSE. ! initialize for error handling (cleanup() routine) + + !------------------------------------------------------------------------------------------------- + ! Open the file + !------------------------------------------------------------------------------------------------- + FileName = TRIM(InitInp%InputFile) + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !CALL WrScr( 'Opening HydroDyn input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'HydroDyn input file header line 1', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'HydroDyn input file header line 2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Echo Input Files. + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( InitInp%Echo ) THEN + + EchoFile = TRIM(InitInp%OutRootName)//'.HD.ech' + CALL OpenEcho ( UnEchoLocal, TRIM(EchoFile), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + REWIND(UnIn) + + CALL ReadCom( UnIn, FileName, 'HydroDyn input file header line 1', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + + CALL ReadCom( UnIn, FileName, 'HydroDyn input file header line 2', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + + ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. (bjj: is that still true?) + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + + END IF + !------------------------------------------------------------------------------------------------- + ! Environmental conditions section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WtrDens - Water density. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WtrDens, 'WtrDens', 'Water density', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WtrDpth - Water depth + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%WtrDpth, 'WtrDpth', 'Water depth', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! MSL2SWL + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%MSL2SWL, 'MSL2SWL', 'MSL to SWL offset', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Data section for waves + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Wave header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveMod - Wave kinematics model switch. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveModChr, 'WaveMod', 'Wave kinematics model switch', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%Waves%WaveModChr ) ! Convert Line to upper case. + + InitInp%Waves%WavePhase = 0.0 + InitInp%Waves%WaveNDAmp = .FALSE. + + + ! WaveStMod - Model switch for stretching incident wave kinematics to instantaneous free surface. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveStMod, 'WaveStMod', & + 'Model switch for stretching incident wave kinematics to instantaneous free surface', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! WaveTMax - Analysis time for incident wave calculations. + + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveTMax, 'WaveTMax', & + 'Analysis time for incident wave calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveDT - Time step for incident wave calculations + + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveDT, 'WaveDT', & + 'Time step for incident wave calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + + ! WaveHs - Significant wave height + + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveHs, 'WaveHs', 'Significant wave height', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! WaveTp - Peak spectral period. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveTp, 'WaveTp', 'Peak spectral period', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WavePkShp - Peak shape parameter. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WavePkShpChr, 'WavePkShp', 'Peak shape parameter', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvLowCOff - Low Cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s). + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WvLowCOff, 'WvLowCOff', 'Lower wave cut-off frequency', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! WvHiCOff - High Cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s). + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WvHiCOff, 'WvHiCOff', 'Upper wave cut-off frequency', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! WaveDir - Mean wave heading direction. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveDir, 'WaveDir', 'Mean wave heading direction', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveDirMod - Directional spreading function {0: None, 1: COS2S} (-) [Used only if WaveMod=2] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveDirMod, 'WaveDirMod', 'Directional spreading function', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveDirSpread - Spreading coefficient [only used if WaveMod=2 and WaveDirMod=1] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveDirSpread, 'WaveDirSpread', 'Wave direction spreading coefficient', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveNDir - The number of wave directions to calculate [must be odd; only used if WaveDirMod=1] + + CALL ReadVar (UnIn, FileName, InitInp%Waves%WaveNDir, 'WaveNDir', 'Number of wave directions to calculate', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveDirRange - Full range of the wave directions from WaveDir - WaveDirRange/2 to WaveDir + WaveDirRange/2 (only used if WaveMod=2 and WaveDirMod=1) + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveDirRange, 'WaveDirRange', 'Maximum wave heading direction', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Negative values should be treated as positive. + InitInp%Waves%WaveDirRange = ABS( InitInp%Waves%WaveDirRange ) + + + ! WaveSeed(1) + CALL ReadVar( UnIn, FileName, InitInp%Waves%WaveSeed(1), 'WaveSeed(1)', "Random seed #1", ErrStat2, ErrMsg2, UnEchoLocal) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + InitInp%Waves%RNG%RandSeed(1) = InitInp%Waves%WaveSeed(1) + + !WaveSeed(2) + CALL ReadVar( UnIn, FileName, Line, 'WaveSeed(2)', "Random seed #2", ErrStat2, ErrMsg2, UnEchoLocal) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + READ (Line,*,IOSTAT=ErrStat2) Line1 ! check the first character to make sure we don't have T/F, which can be interpreted as 1/-1 or 0 in Fortran + CALL Conv2UC( Line1 ) + IF ( (Line1 == 'T') .OR. (Line1 == 'F') ) THEN + CALL SetErrStat( ErrID_Fatal, ' WaveSeed(2): Invalid RNG type.', ErrStat, ErrMsg, 'HydroDynInput_GetInput') + CALL Cleanup() + RETURN + ENDIF + + READ (Line,*,IOSTAT=ErrStat2) InitInp%Waves%WaveSeed(2) + InitInp%Waves%RNG%RandSeed(2) = InitInp%Waves%WaveSeed(2) + + IF (ErrStat2 == 0) THEN ! the user entered a number + InitInp%Waves%RNG%RNG_type = "NORMAL" + InitInp%Waves%RNG%pRNG = pRNG_INTRINSIC + + ELSE + + InitInp%Waves%RNG%RNG_type = ADJUSTL( Line ) + CALL Conv2UC( InitInp%Waves%RNG%RNG_type ) + + IF ( InitInp%Waves%RNG%RNG_type == "RANLUX") THEN + InitInp%Waves%RNG%pRNG = pRNG_RANLUX + ELSE + CALL SetErrStat( ErrID_Fatal, ' WaveSeed(2): Invalid alternative random number generator.', ErrStat, ErrMsg, 'HydroDynInput_GetInput') + CALL Cleanup() + RETURN + ENDIF + + ENDIF + + ! WaveNDAmp - Flag for normally distributed amplitudes. + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WaveNDAmp, 'WaveNDAmp', 'Normally distributed amplitudes', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! WvKinFile + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%WvKinFile, 'WvKinFile', & + 'Root name of wave kinematics files', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + + ! NWaveElev + + CALL ReadVar ( UnIn, FileName, InitInp%Waves%NWaveElev, 'NWaveElev', & + 'Number of points where the incident wave elevations can be output', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! This check is needed here instead of being located in HydroDynInput_ProcessInputData() because + ! we need to allocate arrays. If _GetInput() was skipped, then these array would already have + ! been allocated and populated. + + IF ( InitInp%Waves%NWaveElev < 0 .OR. InitInp%Waves%NWaveElev > 9 ) THEN + + CALL SetErrStat( ErrID_Fatal, 'NWaveElev must be greater than or equal to zero and less than 10.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + + ELSE + + ! allocate space for the output location arrays: + CALL AllocAry( InitInp%Waves%WaveElevxi, InitInp%Waves%NWaveElev, 'WaveElevxi' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%Waves%WaveElevyi, InitInp%Waves%NWaveElev, 'WaveElevyi' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + END IF + + ! WaveElevxi + + CALL ReadAry ( UnIn, FileName, InitInp%Waves%WaveElevxi, InitInp%Waves%NWaveElev, 'WaveElevxi', & + 'List of xi-coordinates for points where the incident wave elevations can be output', ErrStat2, ErrMsg2, UnEchoLocal) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WaveElevyi + + CALL ReadAry ( UnIn, FileName, InitInp%Waves%WaveElevyi, InitInp%Waves%NWaveElev, 'WaveElevyi', & + 'List of yi-coordinates for points where the incident wave elevations can be output', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Data section for 2nd Order Waves + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Waves 2nd order', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvDiffQTFF - Second order waves -- difference forces + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvDiffQTFF, 'WvDiffQTFF', 'Full difference QTF second order kinematic forces flag', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvSumQTFF - Second order waves -- sum forces + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvSumQTFF, 'WvSumQTFF', 'Full sum QTF second order kinematic forces flag', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! WvLowCOffD -- Minimum frequency used in the difference methods (rad/s) [Only used if DiffQTF /= 0] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvLowCOffD, 'WvLowCOffD', 'Minimum frequency used in second order difference forces', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvHiCOffD -- Maximum frequency used in the difference methods (rad/s) [Only used if DiffQTF /= 0] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvHiCOffD, 'WvHiCOffD', 'Maximum frequency used in second order difference forces', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvLowCOffS -- Minimum frequency used in the sum-QTF (rad/s) [Only used if SumQTF /= 0] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvLowCOffS, 'WvLowCOffS', 'Minimum frequency used in second order sum forces', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WvHiCOffS -- Maximum frequency used in the sum-QTF (rad/s) [Only used if SumQTF /= 0] + + CALL ReadVar ( UnIn, FileName, InitInp%Waves2%WvHiCOffS, 'WvHiCOffS', 'Maximum frequency used in second order sum forces', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Data section for current + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Current header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! CurrMod - Current profile model switch + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrMod, 'CurrMod', 'Current profile model switch', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! CurrSSV0 - Sub-surface current velocity at still water level + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrSSV0, 'CurrSSV0', 'Sub-surface current velocity at still water level', & + ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! CurrSSDirChr - Sub-surface current heading direction + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrSSDirChr, 'CurrSSDirChr', 'Sub-surface current heading direction', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + CALL Conv2UC( InitInp%Current%CurrSSDirChr ) ! Convert Line to upper case. + + + ! CurrNSRef - Near-surface current reference depth. + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrNSRef, 'CurrNSRef', 'Near-surface current reference depth', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! CurrNSV0 - Near-surface current velocity at still water level. + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrNSV0, 'CurrNSV0', 'Near-surface current velocity at still water level', & + ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! CurrNSDir - Near-surface current heading direction. + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrNSDir, 'CurrNSDir', 'Near-surface current heading direction', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! CurrDIV - Depth-independent current velocity. + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrDIV, 'CurrDIV', 'Depth-independent current velocity', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! CurrDIDir - Depth-independent current heading direction. + + CALL ReadVar ( UnIn, FileName, InitInp%Current%CurrDIDir, 'CurrDIDir', 'Depth-independent current heading direction', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Data section for floating platform + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Floating platform header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! PotMod - State indicating potential flow model used in the simulation. 0=none, 1=WAMIT, 2=FIT + + CALL ReadVar ( UnIn, FileName, InitInp%PotMod, 'PotMod', 'Potential flow model', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PotFile - Root name of Potential flow data files (Could be WAMIT files or the FIT input file) + + CALL ReadVar ( UnIn, FileName, InitInp%PotFile, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! WAMITULEN - WAMIT characteristic body length scale + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%WAMITULEN, 'WAMITULEN', 'WAMIT characteristic body length scale', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PtfmVol0 - Displaced volume of water when the platform is in its undisplaced position + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmVol0, 'PtfmVol0', & + 'Displaced volume of water when the platform is in its undisplaced position', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PtfmCOBxt - The xt offset of the center of buoyancy (COB) from the WAMIT reference point + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmCOBxt, 'PtfmCOBxt', & + 'xt offset of the center of buoyancy (COB) from the WAMIT reference point', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PtfmCOByt - The yt offset of the center of buoyancy (COB) from the WAMIT reference point + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmCOByt, 'PtfmCOByt', & + 'yt offset of the center of buoyancy (COB) from the WAMIT reference point', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! ExctnMod - Wave Excitation model {0: None, 1: DFT, 2: state-space} (switch) + ! [STATE-SPACE REQUIRES *.ssexctn INPUT FILE] + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%ExctnMod, 'ExctnMod', & + 'Wave Excitation model', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! RdtnMod - Radiation memory-effect model {1: convolution, 2: state-space} (switch) + ! [STATE-SPACE REQUIRES *.ss INPUT FILE] + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnMod, 'RdtnMod', & + 'Radiation memory-effect model', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! RdtnTMax - Analysis time for wave radiation kernel calculations + ! NOTE: Use RdtnTMax = 0.0 to eliminate wave radiation damping + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnTMax, 'RdtnTMax', & + 'Analysis time for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! RdtnDT - Time step for wave radiation kernel calculations + + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%Conv_Rdtn%RdtnDTChr, 'RdtnDT', 'Time step for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + +!bjj: should we add this? +!test for numerical stability +! IF ( FP_InitData%RdtnDT <= FP_InitData%RdtnTMax*EPSILON(FP_InitData%RdtnDT) ) THEN ! Test RdtnDT and RdtnTMax to ensure numerical stability -- HINT: see the use of OnePlusEps." +! ErrMsg = ' RdtnDT must be greater than '//TRIM ( Num2LStr( RdtnTMax*EPSILON(RdtnDT) ) )//' seconds.' +! ErrStat = ErrID_Fatal +! CLOSE( UnIn ) +! RETURN +! END IF + + + + !------------------------------------------------------------------------------------------------- + ! Data section for 2nd order WAMIT forces + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, '2nd order forces header (WAMIT2 module)', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! MnDrift -- Mean drift forces computed from WAMIT file: {0: No mean drift, [7, 8, 9, 10, 11, or 12]: WAMIT file to use} + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT2%MnDrift, 'MnDrift', 'Mean drift forces computed from WAMIT file: {0: No mean drift, [7, 8, 9, 10, 11, or 12]: WAMIT file to use}', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NewmanApp -- Slow drift forces computed with Newman's approximation from WAMIT file: {0: No mean drift, [7, 8, 9, 10, 11, or 12]: WAMIT file to use} + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT2%NewmanApp, 'NewmanApp', 'Mean drift forces computed from WAMIT file: {0: No mean drift, [7, 8, 9, 10, 11, or 12]: WAMIT file to use}', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! DiffQTF -- Full Difference-Frequency forces computed with full QTFs from WAMIT file: {0: No difference-frequency forces, [10, 11, or 12]: WAMIT file to use} -- Only one of MnDrift, NewmanApp, or DiffQYT can be non-zero + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT2%DiffQTF, 'DiffQTF', 'Full Difference-Frequency forces computed with full QTFs from WAMIT file: '// & + '{0: No difference-frequency forces, [10, 11, or 12]: WAMIT file to use} -- Only one of MnDrift, NewmanApp, or DiffQYT can be non-zero', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! SumQTF -- Full Sum-Frequency forces computed with full QTFs from WAMIT file: {0: No Sum-frequency forces, [10, 11, or 12]: WAMIT file to use} + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT2%SumQTF, 'SumQTF', 'Full Sum-Frequency forces computed with full QTFs from WAMIT file: {0: No Sum-frequency forces, [10, 11, or 12]: WAMIT file to use}', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Data section for Floating platform force flags + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Floating platform force flags header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PtfmSgFChr - Platform horizontal surge translation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmSgFChr, 'PtfmSgFChr', 'Platform horizontal surge translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmSgFChr ) ! Convert Line to upper case. + + + ! PtfmSwFChr - Platform horizontal sway translation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmSwFChr, 'PtfmSwFChr', 'Platform horizontal sway translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmSwFChr ) ! Convert Line to upper case. + + + ! PtfmHvFChr - Platform vertical heave translation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmHvFChr, 'PtfmHvFChr', 'Platform vertical heave translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmHvFChr ) ! Convert Line to upper case. + + + ! PtfmRFChr - Platform roll tilt rotation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmRFChr, 'PtfmRFChr', 'Platform roll tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmRFChr ) ! Convert Line to upper case. + + + ! PtfmPFChr - Platform pitch tilt rotation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmPFChr, 'PtfmPFChr', 'Platform pitch tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmPFChr ) ! Convert Line to upper case. + + + ! PtfmYFChr - Platform yaw rotation force flag + + CALL ReadVar ( UnIn, FileName, InitInp%PtfmYFChr, 'PtfmYFChr', 'Platform yaw rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC( InitInp%PtfmYFChr ) ! Convert Line to upper case. + + + + !------------------------------------------------------------------------------------------------- + ! Floating Platform Additional Stiffness and Damping Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Additional stiffness and damping header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! AddF0 - Additional preload + + CALL ReadAry ( UnIn, FileName, InitInp%AddF0, 6, 'AddF0', & + ' Additional preload vector', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! AddCLin + + DO I=1,6 + + WRITE(strI,'(I1)') I + CALL ReadAry ( UnIn, FileName, InitInp%AddCLin(I,:), 6, 'AddCLin', & + ' Row '//strI//' of the additional linear stiffness matrix', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END DO + + + ! AddBLin + + DO I=1,6 + + WRITE(strI,'(I1)') I + CALL ReadAry ( UnIn, FileName, InitInp%AddBLin(I,:), 6, 'AddBLin', & + ' Row '//strI//' of the additional linear damping matrix', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END DO + + + ! AddBQuad + + DO I=1,6 + + WRITE(strI,'(I1)') I + CALL ReadAry ( UnIn, FileName, InitInp%AddBQuad(I,:), 6, 'AddBQuad', & + ' Row '//strI//' of the additional quadratic damping matrix', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END DO + + + !------------------------------------------------------------------------------------------------- + ! Axial Coefficients Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Axial coefs header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NAxCoef - Number of axial coefficients + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NAxCoefs, 'NAxCoefs', 'Number of axial coefficients', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Axial coefficient table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Axial coefficient table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Morison%NAxCoefs > 0 ) THEN + + + ! Allocate memory for Axial Coef-related arrays + + ALLOCATE ( InitInp%Morison%AxialCoefs(InitInp%Morison%NAxCoefs), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for AxialCoefs array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NAxCoefs + ! read the table entries AxCoefID CdAx CaAx in the HydroDyn input file + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%AxialCoefs(I)%AxCoefID, InitInp%Morison%AxialCoefs(I)%AxCd, InitInp%Morison%AxialCoefs(I)%AxCa, InitInp%Morison%AxialCoefs(I)%AxCp + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read axial coefficients.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member Joints Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Member joints header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NJoints - Number of member joints + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NJoints, 'NJoints', 'Number of member joints', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member joints table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member joints table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Morison%NJoints > 0 ) THEN + + + ! Allocate memory for Joint-related arrays + + ALLOCATE ( InitInp%Morison%InpJoints(InitInp%Morison%NJoints), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for InpJoints array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NJoints + ! read the table entries JointID Jointxi Jointyi Jointzi JointAxID JointOvrlp in the HydroDyn input file + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%InpJoints(I)%JointID, InitInp%Morison%InpJoints(I)%JointPos(1), InitInp%Morison%InpJoints(I)%JointPos(2), InitInp%Morison%InpJoints(I)%JointPos(3), InitInp%Morison%InpJoints(I)%JointAxID, InitInp%Morison%InpJoints(I)%JointOvrlp + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read joints.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + + + !------------------------------------------------------------------------------------------------- + ! Member Cross-section Properties Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Member cross-section properties header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NPropSets - Number of member cross-section property sets + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NPropSets, 'NPropSets', 'Number of member cross-section property sets', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member cross-section properties table header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member cross-section properties table header', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Morison%NPropSets > 0 ) THEN + + + ! Allocate memory for Member cross-section property set-related arrays + + ALLOCATE ( InitInp%Morison%MPropSets(InitInp%Morison%NPropSets), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for MPropSets array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + DO I = 1,InitInp%Morison%NPropSets + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat) InitInp%Morison%MPropSets(I)%PropSetID, InitInp%Morison%MPropSets(I)%PropD, InitInp%Morison%MPropSets(I)%PropThck + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read member cross-section properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + + + + !------------------------------------------------------------------------------------------------- + ! Simple hydrodynamic coefficients Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Simple hydrodynamic coefficients header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Header + + CALL ReadCom( UnIn, FileName, 'Simple hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Header + + CALL ReadCom( UnIn, FileName, 'Simple hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%SimplCd, InitInp%Morison%SimplCdMG, InitInp%Morison%SimplCa, InitInp%Morison%SimplCaMG, InitInp%Morison%SimplCp, InitInp%Morison%SimplCpMG, InitInp%Morison%SimplAxCa, InitInp%Morison%SimplAxCaMG, InitInp%Morison%SimplAxCp, InitInp%Morison%SimplAxCpMG + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read simple hydrodynamic coefficients.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + + + + !------------------------------------------------------------------------------------------------- + ! Depth-based Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Depth-based hydrodynamic coefficients header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NCoefDpth - Number of depth-based hydrodynamic coefficient property sets + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NCoefDpth, 'NCoefDpth', 'Number of depth-based hydrodynamic coefficient property sets', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Depth-based hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Depth-based hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NCoefDpth > 0 ) THEN + + + ! Allocate memory for depth-based coefficient arrays + + ALLOCATE ( InitInp%Morison%CoefDpths(InitInp%Morison%NCoefDpth), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for CoefDpths array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NCoefDpth + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%CoefDpths(I)%Dpth, InitInp%Morison%CoefDpths(I)%DpthCd, InitInp%Morison%CoefDpths(I)%DpthCdMG, & + InitInp%Morison%CoefDpths(I)%DpthCa, InitInp%Morison%CoefDpths(I)%DpthCaMG, InitInp%Morison%CoefDpths(I)%DpthCp, InitInp%Morison%CoefDpths(I)%DpthCpMG, & + InitInp%Morison%CoefDpths(I)%DpthAxCa, InitInp%Morison%CoefDpths(I)%DpthAxCaMG, InitInp%Morison%CoefDpths(I)%DpthAxCp, InitInp%Morison%CoefDpths(I)%DpthAxCpMG + END IF + + IF (ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read depth-based coefficient array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member-based Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Member-based hydrodynamic coefficients header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NCoefMembers - Number of member-based hydrodynamic coefficient property sets + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NCoefMembers, 'NCoefMembers', 'Number of member-based hydrodynamic coefficient property sets', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member-based hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member-based hydrodynamic coefficients table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NCoefMembers > 0 ) THEN + + + ! Allocate memory for Member-based coefficient arrays + + ALLOCATE ( InitInp%Morison%CoefMembers(InitInp%Morison%NCoefMembers), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for CoefMembers array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NCoefMembers + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%CoefMembers(I)%MemberID, & + InitInp%Morison%CoefMembers(I)%MemberCd1, InitInp%Morison%CoefMembers(I)%MemberCd2, & + InitInp%Morison%CoefMembers(I)%MemberCdMG1, InitInp%Morison%CoefMembers(I)%MemberCdMG2, & + InitInp%Morison%CoefMembers(I)%MemberCa1, InitInp%Morison%CoefMembers(I)%MemberCa2, & + InitInp%Morison%CoefMembers(I)%MemberCaMG1, InitInp%Morison%CoefMembers(I)%MemberCaMG2, & + InitInp%Morison%CoefMembers(I)%MemberCp1, InitInp%Morison%CoefMembers(I)%MemberCp2, & + InitInp%Morison%CoefMembers(I)%MemberCpMG1, InitInp%Morison%CoefMembers(I)%MemberCpMG2, & + InitInp%Morison%CoefMembers(I)%MemberAxCa1, InitInp%Morison%CoefMembers(I)%MemberAxCa2, & + InitInp%Morison%CoefMembers(I)%MemberAxCaMG1, InitInp%Morison%CoefMembers(I)%MemberAxCaMG2, & + InitInp%Morison%CoefMembers(I)%MemberAxCp1, InitInp%Morison%CoefMembers(I)%MemberAxCp2, & + InitInp%Morison%CoefMembers(I)%MemberAxCpMG1, InitInp%Morison%CoefMembers(I)%MemberAxCpMG2 + END IF + + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read member cross-section properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Members Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Members header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NMembers - Number of members in the input file + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NMembers, 'NMembers', 'Number of members', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Members table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Members table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NMembers > 0 ) THEN + + + ! Allocate memory for Members arrays + + ALLOCATE ( InitInp%Morison%InpMembers(InitInp%Morison%NMembers), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for InpMembers array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NMembers + !ReadStr ( UnIn, Fil, Line, 'Joint table', VarDescr, ErrStat ) + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%InpMembers(I)%MemberID, InitInp%Morison%InpMembers(I)%MJointID1, & + InitInp%Morison%InpMembers(I)%MJointID2, InitInp%Morison%InpMembers(I)%MPropSetID1, & + InitInp%Morison%InpMembers(I)%MPropSetID2, InitInp%Morison%InpMembers(I)%MDivSize, & + InitInp%Morison%InpMembers(I)%MCoefMod, InitInp%Morison%InpMembers(I)%PropPot + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read member properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Filled Members Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Filled members header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NFillGroups - Number of fill groups + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NFillGroups, 'NFillGroups', 'Number of fill groups', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Fill groups table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Fill groups table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NFillGroups > 0 ) THEN + + + ! Allocate memory for filled group arrays + + ALLOCATE ( InitInp%Morison%FilledGroups(InitInp%Morison%NFillGroups), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for FilledGroups array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NFillGroups + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%FilledGroups(I)%FillNumM + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read FillNumM.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + ALLOCATE ( InitInp%Morison%FilledGroups(I)%FillMList(InitInp%Morison%FilledGroups(I)%FillNumM), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for FillMList array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%FilledGroups(I)%FillNumM, InitInp%Morison%FilledGroups(I)%FillMList, & + InitInp%Morison%FilledGroups(I)%FillFSLoc, InitInp%Morison%FilledGroups(I)%FillDensChr + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read filled group properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Marine Growth by Depth Section + !------------------------------------------------------------------------------------------------- + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Marine growth by depth header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + + ! NMGDepths - Number marine growth depths + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NMGDepths, 'NMGDepths', 'Number marine growth depths', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Marine growth by depth table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Marine growth by depth table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NMGDepths > 0 ) THEN + + + ! Allocate memory for marine growth depths array + + ALLOCATE ( InitInp%Morison%MGDepths(InitInp%Morison%NMGDepths), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for MGDepths array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NMGDepths + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%MGDepths(I)%MGDpth, InitInp%Morison%MGDepths(I)%MGThck, InitInp%Morison%MGDepths(I)%MGDens + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read marine growth depth properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member Output List Section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Member output list header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NMOutputs - Number of members to output + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NMOutputs, 'NMOutputs', 'Number of members to output', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member output list table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Table header + + CALL ReadCom( UnIn, FileName, 'Member output list table header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Morison%NMOutputs > 0 ) THEN + + + ! Allocate memory for filled group arrays + + ALLOCATE ( InitInp%Morison%MOutLst(InitInp%Morison%NMOutputs), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for MOutLst array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + DO I = 1,InitInp%Morison%NMOutputs + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%MOutLst(I)%MemberID, InitInp%Morison%MOutLst(I)%NOutLoc + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read NOutLoc.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + ALLOCATE ( InitInp%Morison%MOutLst(I)%NodeLocs(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for NodeLocs array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + ALLOCATE ( InitInp%Morison%MOutLst(I)%Marker1(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for Marker1 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + + ALLOCATE ( InitInp%Morison%MOutLst(I)%Marker2(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for Marker2 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + ALLOCATE ( InitInp%Morison%MOutLst(I)%s(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for s array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + READ(Line,*,IOSTAT=ErrStat2) InitInp%Morison%MOutLst(I)%MemberID, InitInp%Morison%MOutLst(I)%NOutLoc, & + InitInp%Morison%MOutLst(I)%NodeLocs + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read member output list properties.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEchoLocal, '(A)' ) TRIM(Line) + END IF + + END IF + + END DO + + END IF + + !------------------------------------------------------------------------------------------------- + ! Joint Output List Section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Joint output list header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! NJOutputs - Number of joints to output + + CALL ReadVar ( UnIn, FileName, InitInp%Morison%NJOutputs, 'NJOutputs', 'Number of joints to output', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Morison%NJOutputs > 0 ) THEN + + ALLOCATE ( InitInp%Morison%JOutLst(InitInp%Morison%NJOutputs), STAT = ErrStat2 ) + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for JOutLst data structures.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + CALL AllocAry( tmpArray, InitInp%Morison%NJOutputs, 'temporary array for Joint outputs', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL ReadAry ( UnIn, FileName, tmpArray, InitInp%Morison%NJOutputs, 'JOutLst', 'Joint output list', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + DO I = 1,InitInp%Morison%NJOutputs + + InitInp%Morison%JOutLst(I)%JointID = tmpArray(I) + + END DO + + DEALLOCATE(tmpArray) + + ELSE + + ! There are no Joint Outputs, but there is a line to be parsed in the input file! + + ALLOCATE ( tmpArray(1), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for temporary array for Joint outputs.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL Cleanup() + RETURN + END IF + + CALL ReadAry ( UnIn, FileName, tmpArray, 1, 'JOutLst', 'Joint output list', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + DEALLOCATE(tmpArray) + !we just want to read the line for echoing purposes when there are actually 0 Joint Outputs. + + END IF + + !------------------------------------------------------------------------------------------------- + ! Data section for OUTPUT + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Output header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! HDSum - Whether or not to generate a summary file + + CALL ReadVar ( UnIn, FileName, InitInp%HDSum, 'HDSum', 'Generate a HydroDyn summary file', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! OutAll - Whether or not to output information for every member and joint + + CALL ReadVar ( UnIn, FileName, InitInp%OutAll, 'OutAll', 'Generate all member and joint outputs', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! OutSwtch - Specify how to write to an output file + + CALL ReadVar ( UnIn, FileName, InitInp%OutSwtch, 'OutSwtch', 'Specify how to write to an output file', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! OutFmt - Format for numerical outputs + + CALL ReadVar ( UnIn, FileName, InitInp%OutFmt, 'OutFmt', 'Format for numerical outputs', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! OutSFmt - Format for output column headers + + CALL ReadVar ( UnIn, FileName, InitInp%OutSFmt, 'OutSFmt', 'Format for output column headers', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Data section for FLOATING PLATFORM OUTPUTS + !------------------------------------------------------------------------------------------------- + + ! Header + + !CALL ReadCom( UnIn, FileName, 'Floating Platform Outputs header', ErrStat2, ErrMsg2, UnEchoLocal ) + ! + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + ! IF (ErrStat >= AbortErrLev) THEN + ! CALL CleanUp() + ! RETURN + ! END IF + CALL ReadCom( UnIn, FileName, 'Outputs header', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! OutList - list of requested parameters to output to a file + + !CALL ReadOutputList ( UnIn, FileName, InitInp%WAMIT%OutList, InitInp%WAMIT%NumOuts, & + ! 'OutList', 'List of floating platform outputs requested', ErrStat2, ErrMsg2, UnEchoLocal ) + ALLOCATE( InitInp%UserOutputs(2778), Stat=ErrStat2) !todo: bjj: what is this 2778? + IF (ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating UserOutputs.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF + + CALL ReadOutputList ( UnIn, FileName, InitInp%UserOutputs, InitInp%NUserOutputs, & + 'OutList', 'List of user requested outputs', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! + ! + !!------------------------------------------------------------------------------------------------- + !! Data section for MESH-BASED OUTPUTS + !!------------------------------------------------------------------------------------------------- + ! + ! ! Header + ! + !CALL ReadCom( UnIn, FileName, 'Mesh-based Outputs header', ErrStat2, ErrMsg2, UnEchoLocal ) + ! + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + ! IF (ErrStat >= AbortErrLev) THEN + ! CALL CleanUp() + ! RETURN + ! END IF + ! + ! ! OutList - list of requested parameters to output to a file + ! + !CALL ReadOutputList ( UnIn, FileName, InitInp%Morison%OutList, InitInp%Morison%NumOuts, & + ! 'OutList', 'List of mesh-based outputs requested', ErrStat2, ErrMsg2, UnEchoLocal ) + ! + !CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + !IF (ErrStat >= AbortErrLev) THEN + ! CALL CleanUp() + ! RETURN + !END IF + + !------------------------------------------------------------------------------------------------- + ! This is the end of the input file + !------------------------------------------------------------------------------------------------- + + CALL Cleanup() + + RETURN + +CONTAINS + !.............................. + SUBROUTINE Cleanup() + + IF (ALLOCATED(tmpArray)) DEALLOCATE(tmpArray) + + ! Close input file + CLOSE ( UnIn ) + + ! Cleanup the Echo file and global variables + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + + + END SUBROUTINE Cleanup + + +END SUBROUTINE HydroDynInput_GetInput + + + + + +!==================================================================================================== +SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) +! This private subroutine verifies the input required for HydroDyn is correctly specified. +!---------------------------------------------------------------------------------------------------- + + + ! Passed variables + + TYPE(HydroDyn_InitInputType), INTENT( INOUT ) :: InitInp ! the hydrodyn data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I ! Generic loop counter index + INTEGER :: J ! Generic loop counter index + INTEGER :: K ! Generic loop counter index + CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name + LOGICAL :: FoundID ! Boolean flag indicating whether an ID from one tables is found in one of the other input table + REAL(ReKi) :: MinDepth ! The minimum depth entry in the Depth-based Hydrodynamic coefficents table + REAL(ReKi) :: MaxDepth ! The maximum depth entry in the Depth-based Hydrodynamic coefficents table + REAL(ReKi) :: z1 + REAL(ReKi) :: z2 + REAL(ReKi) :: MinMembrDpth + REAL(ReKi) :: MaxMembrDpth +! CHARACTER(ChanLen), ALLOCATABLE :: tmpOutLst(:) ! + CHARACTER(3) :: TmpExtension ! Temporary variable for holding the file extension for 10d, 11d, 12d, 10s, 11s, 12s WAMIT files + LOGICAL :: TmpFileExist ! Temporary variable in checking the existance of an input file. + LOGICAL :: JointUsed + REAL(ReKi) :: l + REAL(ReKi) :: lvec(3) + LOGICAL, ALLOCATABLE :: foundMask(:) + INTEGER :: WaveModIn + + INTEGER(IntKi) :: ErrStat2, IOS + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDynInput_ProcessInitData' + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrStat2 = ErrID_None + ErrMsg = "" + ErrMsg2 = "" + + + !------------------------------------------------------------------------- + ! Check environmental conditions + !------------------------------------------------------------------------- + + + ! WtrDens - Water density. + + IF ( InitInp%Waves%WtrDens < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WtrDens must not be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! WtrDpth - Water depth + + IF ( InitInp%Morison%WtrDpth <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WtrDpth must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! MSL2SWL - Mean sea level to still water level + + IF ( InitInp%PotMod == 1 .AND. .NOT. EqualRealNos(InitInp%Morison%MSL2SWL, 0.0_ReKi) ) THEN + CALL SetErrStat( ErrID_Fatal,'MSL2SWL must be 0 when PotMod = 1 (WAMIT).',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + !IF ( .NOT. EqualRealNos(InitInp%Morison%MSL2SWL, 0.0_ReKi) ) THEN !TODO Alter this check when we support MSL2SWL + ! CALL SetErrStat( ErrID_Fatal,'MSL2SWL must be 0. Future versions of HydroDyn will once again support any value of MSL2SWL.' + ! RETURN + !END IF + + + ! WaveMod - Wave kinematics model switch. + + IF ( LEN_TRIM(InitInp%Waves%WaveModChr) > 1 ) THEN + + IF ( InitInp%Waves%WaveModChr(1:2) == '1P' ) THEN ! The user wants to specify the phase in place of a random phase + + READ (InitInp%Waves%WaveModChr(3:),*,IOSTAT=IOS ) InitInp%Waves%WavePhase + CALL CheckIOS ( IOS, "", 'WavePhase', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + WaveModIn = 1 + InitInp%Waves%WaveMod = 10 ! Internally define WaveMod = 10 to mean regular waves with a specified (nonrandom) phase + InitInp%Waves%WavePhase = InitInp%Waves%WavePhase*D2R ! Convert the phase from degrees to radians + + ELSE ! The user must have specified WaveMod incorrectly. + CALL SetErrStat( ErrID_Fatal,'WaveMod incorrectly specified',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + ! The line below only works for 1 digit reads + READ( InitInp%Waves%WaveModChr, *, IOSTAT=IOS ) InitInp%Waves%WaveMod + CALL CheckIOS ( IOS, "", 'WaveMod', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + WaveModIn = InitInp%Waves%WaveMod + + END IF ! LEN_TRIM(InitInp%Waves%WaveModChr) + + IF ( (WaveModIn == 6) .AND. .NOT. EqualRealNos(InitInp%Morison%MSL2SWL, 0.0_ReKi) ) THEN + CALL SetErrStat( ErrID_Fatal,'MSL2SWL must be 0 when WaveMod = 6.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + IF ( WaveModIn < 0 .OR. WaveModIn > 6 ) THEN + IF ( InitInp%PotMod == 1 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveMod must be 0, 1, 1P#, 2, 3, 4, 5, or 6.',ErrStat,ErrMsg,RoutineName) + RETURN +!ADP: This seems like a strange test on ErrStat... + ELSE IF ( ErrStat /= ErrID_None .OR. WaveModIn /= 5) THEN + CALL SetErrStat( ErrID_Fatal,'WaveMod must be 0, 1, 1P#, 2, 3, 4, or 5.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + ! Linearization Checks + ! LIN-TODO: + !errors if: + !if ( & + ! (WaveModIn /= 0) .or. & + ! (InitInp%Waves2%WvDiffQTFF /= .false.) .or. & + ! (InitInp%Waves2%WvSumQTFF /= .false.) .or. & + ! (InitInp%PotMod /= 0 .or. InitInp%PotMod /=1) .or. & + ! (InitInp%WAMIT%ExctnMod /=0 .or. InitInp%WAMIT%ExctnMod /=2) .or. & + ! (InitInp%WAMIT%RdtnMod /=0 .or. InitInp%WAMIT%RdtnMod /=2) .or. & + ! (InitInp%WAMIT2%MnDrift /=0) .or. & + ! (InitInp%WAMIT2%NewmanApp /= 0) .or. & + ! (InitInp%WAMIT2%SumQTF /= 0 ) ) then + ! + !end if + + + ! WaveStMod - Model switch for stretching incident wave kinematics to instantaneous free surface. + + ! TODO: We are only implementing WaveStMod = 0 (No stretching) at this point in time. 1 Mar 2013 GJH + + IF ( InitInp%Waves%WaveStMod /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveStMod must be 0. Future versions of HydroDyn will once again support other wave stretching models.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Waves%WaveMod /= 6 .AND. InitInp%Morison%NMembers > 0 .AND. InitInp%Waves%WaveMod > 0 ) THEN + + IF ( ( InitInp%Waves%WaveStMod /= 0 ) .AND. ( InitInp%Waves%WaveStMod /= 1 ) .AND. & + ( InitInp%Waves%WaveStMod /= 2 ) ) THEN ! (TODO: future version will support 3) .AND. ( InitInp%Waves%WaveStMod /= 3 ) ) THEN + ErrMsg = ' WaveStMod must be 0, 1, or 2.' !, or 3.' + ErrStat = ErrID_Fatal + + RETURN + END IF + + !IF ( ( InitInp%Waves%WaveStMod /= 3 ) .AND. ( InitInp%Waves%WaveMod == 5 ) ) THEN + ! ErrMsg = ' WaveStMod must be set to 3 when WaveMod is set to 5.' + ! ErrStat = ErrID_Fatal + ! + ! RETURN + !END IF + + + + ELSE !don't use this one + + ! NOTE: Do not read in WaveStMod for floating platforms since it is + ! inconsistent to use stretching (which is a nonlinear correction) for + ! the viscous drag term in Morison's equation while not accounting for + ! stretching in the diffraction and radiation problems (according to + ! Paul Sclavounos, there are such corrections). Instead, the viscous + ! drag term from Morison's equation is computed by integrating up to + ! the MSL, regardless of the instantaneous free surface elevation. + + InitInp%Waves%WaveStMod = 0 + + END IF + + + ! WaveTMax - Analysis time for incident wave calculations. + + IF ( InitInp%Waves%WaveMod == 0 ) THEN ! .TRUE if we have incident waves. + + ! TODO: Issue warning if WaveTMax was not already 0.0 in this case. + IF ( .NOT. EqualRealNos(InitInp%Waves%WaveTMax, 0.0_DbKi) ) THEN + CALL WrScr( ' Setting WaveTMax to 0.0 since WaveMod = 0' ) + InitInp%Waves%WaveTMax = 0.0 + END IF + IF ( .NOT. EqualRealNos(InitInp%Waves%WaveDir, 0.0_SiKi) ) THEN + CALL WrScr( ' Setting WaveDir to 0.0 since WaveMod = 0' ) + InitInp%Waves%WaveDir = 0.0 + END IF + ELSEIF ( InitInp%Waves%WaveMod == 5 ) THEN ! User wave elevation file reading in + IF (InitInp%TMax > InitInp%Waves%WaveTMax ) THEN + CALL SetErrstat( ErrID_Fatal, ' WaveTMax must be larger than the simulation time for user wave elevations (WaveMod == 5).',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE + IF (InitInp%TMax > InitInp%Waves%WaveTMax ) THEN + CALL WrScr( ' WaveTMax is less then the simulation time. Wave data will repeat every WaveTMax seconds.') + END IF + END IF + + + ! WaveDT - Time step for incident wave calculations + + IF ( InitInp%Waves%WaveMod > 0 ) THEN ! .TRUE if we have incident waves. + + IF ( InitInp%Waves%WaveDT <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveDT must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( (InitInp%Waves%WaveMod == 6) .AND. (.NOT. EqualRealNos(InitInp%Waves%WaveDT, InitInp%DT)) ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveDT must equal the simulation DT value when WaveMod = 6.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE + + InitInp%Waves%WaveDT = 0.0 + + END IF + + + ! WaveHs - Significant wave height + + IF ( ( InitInp%Waves%WaveMod /= 0 ) .AND. ( InitInp%Waves%WaveMod /= 4 ) .AND. ( InitInp%Waves%WaveMod /= 5 ) ) THEN ! .TRUE. (when WaveMod = 1, 2, 3, or 10) if we have plane progressive (regular), JONSWAP/Pierson-Moskowitz spectrum (irregular) waves, or white-noise waves, but not user-defined or GH Bladed wave data. + + IF ( InitInp%Waves%WaveHs <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveHs must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Waves%WaveHs = 0.0 + + END IF + + + ! WaveTp - Peak spectral period. + ! We commented out the if else block due to a bug when WaveMod == 3, and then WaveTp is hence set to 0.0. See line 1092 of Waves.f90 (as of 11/24/2014) GJH + !IF ( ( InitInp%Waves%WaveMod == 1 ) .OR. ( InitInp%Waves%WaveMod == 2 ) .OR. ( InitInp%Waves%WaveMod == 10 ) ) THEN ! .TRUE. (when WaveMod = 1, 2, or 10) if we have plane progressive (regular), JONSWAP/Pierson-Moskowitz spectrum (irregular) waves. + + IF ( InitInp%Waves%WaveTp <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveTp must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! ELSE + + ! InitInp%Waves%WaveTp = 0.0 + + ! END IF + + + ! WavePkShp - Peak shape parameter. + + CALL Conv2UC( InitInp%Waves%WavePkShpChr ) ! Convert Line to upper case. + + IF ( InitInp%Waves%WaveMod == 2 ) THEN ! .TRUE if we have JONSWAP/Pierson-Moskowitz spectrum (irregular) waves, but not GH Bladed wave data. + + IF ( TRIM(InitInp%Waves%WavePkShpChr) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value of the peak shape parameter, conditioned on significant wave height and peak spectral period. + + InitInp%Waves%WavePkShp = WavePkShpDefault ( InitInp%Waves%WaveHs, InitInp%Waves%WaveTp ) + + ELSE ! The input must have been specified numerically. + + READ (InitInp%Waves%WavePkShpChr,*,IOSTAT=IOS) InitInp%Waves%WavePkShp + CALL CheckIOS ( IOS, "", 'WavePkShp', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( ( InitInp%Waves%WavePkShp < 1.0 ) .OR. ( InitInp%Waves%WavePkShp > 7.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'WavePkShp must be greater than or equal to 1 and less than or equal to 7.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + END IF + + ELSE + + InitInp%Waves%WavePkShp = 1.0 + + END IF + + + ! WvLowCOff and WvHiCOff - Wave Cut-off frequency + + IF ( InitInp%Waves%WvLowCOff < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WvLowCOff must be greater than or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Threshold upper cut-off based on sampling rate + IF ( EqualRealNos(InitInp%Waves%WaveDT, 0.0_DbKi) ) THEN + InitInp%Waves%WvHiCOff = 10000.0; ! This is not going to be used because WaveDT is zero. + ELSE + InitInp%Waves%WvHiCOff = MIN( REAL( Pi/InitInp%Waves%WaveDT,SiKi), InitInp%Waves%WvHiCOff ) + END IF + + !TODO Issue warning if we changed WvHiCOff GJH 7/24/13 + + IF ( InitInp%Waves%WvLowCOff >= InitInp%Waves%WvHiCOff ) THEN + CALL SetErrSTat( ErrID_Fatal,'WvLowCOff must be less than WvHiCOff.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Copy over the first order frequency limits to the WAMIT2 module which needs them. + InitInp%WAMIT2%WvLowCOff = InitInp%Waves%WvLowCOff + InitInp%WAMIT2%WvHiCOff = InitInp%Waves%WvHiCOff + + + ! WaveDir - Wave heading direction. + + IF ( ( InitInp%Waves%WaveMod > 0 ) .AND. ( InitInp%Waves%WaveMod /= 6 ) ) THEN ! .TRUE if we have incident waves, but not user input wave data. + + IF ( ( InitInp%Waves%WaveDir <= -180.0 ) .OR. ( InitInp%Waves%WaveDir > 180.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveDir must be greater than -180 and less than or equal to 180.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Waves%WaveDir = 0.0 + + END IF + + + ! Multi-directional waves + + ! Check the WaveDirMod value + IF ( InitInp%Waves%WaveDirMod < 0 .OR. InitInp%Waves%WaveDirMod > 1 ) THEN + CALL SetErrStat( ErrID_Fatal,'WaveDirMod must be either 0 (No spreading) or 1 (COS2S spreading function)',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Check if we are doing multidirectional waves or not. + ! We can only use multi directional waves on WaveMod=2,3,4 + InitInp%Waves%WaveMultiDir = .FALSE. ! Set flag to false to start + IF ( InitInp%Waves%WaveMod >= 2 .AND. InitInp%Waves%WaveMod <= 4 .AND. InitInp%Waves%WaveDirMod == 1 ) THEN + InitInp%Waves%WaveMultiDir = .TRUE. + ELSEIF ( (InitInp%Waves%WaveMod < 2 .OR. InitInp%Waves%WaveMod >4) .AND. InitInp%Waves%WaveDirMod == 1 ) THEN + CALL SetErrStat( ErrID_Warn,'WaveDirMod unused unless WaveMod == 2, 3, or 4. Ignoring WaveDirMod.',ErrStat,ErrMsg,RoutineName) + ENDIF + + + ! Check to see if the for some reason the wave direction spreading range is set to zero. If it is, + ! we don't have any spreading, so we will turn off the multidirectional waves. + IF ( InitInp%Waves%WaveMultiDir .AND. EqualRealNos( InitInp%Waves%WaveDirRange, 0.0_SiKi ) ) THEN + CALL SetErrStat( ErrID_Warn,' WaveDirRange set to zero, so multidirectional waves are turned off.',ErrStat,ErrMsg,RoutineName) + InitInp%Waves%WaveMultiDir = .FALSE. + ENDIF + + + + ! We check the following only if we set WaveMultiDir to true, otherwise ignore them and set them to zero + IF ( InitInp%Waves%WaveMultiDir ) THEN + + ! Check WaveDirSpread + IF ( InitInp%Waves%WaveDirSpread <= 0.0 ) THEN + + CALL SetErrStat( ErrID_Fatal,'WaveDirSpread cannot negative or zero.',ErrStat,ErrMsg,RoutineName) + RETURN + + ENDIF + + + ! Check that the number of wave directions is a positive odd number. + ! -> If it is less than 0, error out. + ! -> If it is even, we will increment it by 1. + IF ( InitInp%Waves%WaveNDir <= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,' WaveNDir must be an odd number greater than 0.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! Check that the value for WaveNDir is odd + IF ( MODULO( InitInp%Waves%WaveNDir, 2_IntKi) == 0_IntKi ) THEN + InitInp%Waves%WaveNDir = InitInp%Waves%WaveNDir + 1 + CALL SetErrStat( ErrID_Warn,'WaveNDir must be odd. Changing the value to '//Num2LStr(InitInp%Waves%WaveNDir),ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Now check that the WaveDirRange is less than 360 degrees (not sure why we would want that) + IF ( InitInp%Waves%WaveDirRange > 360.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,' WaveDirRange should be less than a full circle.',ErrStat,ErrMsg,RoutineName) + ENDIF + + ELSE ! Set everything to zero if we aren't going to use it + + InitInp%Waves%WaveNDir = 1 ! Only one direction set -- this shouldn't get used later anyhow + InitInp%Waves%WaveDirRange = PiBy2 ! This is so that the constant C=1 in the COS2S function (it shouldn't get called, but in case it does) + InitInp%Waves%WaveDirSpread = 0.0 + + END IF + + + ! WaveSeed(1), !WaveSeed(2) + + IF ( .NOT. ( ( InitInp%Waves%WaveMod > 0 ) .AND. ( InitInp%Waves%WaveMod /= 5 ) .AND. ( InitInp%Waves%WaveMod /= 10 ) ) ) THEN !.TRUE. for plane progressive (regular) with random phase or irregular wave + + DO I = 1,2 + + InitInp%Waves%WaveSeed(I) = 0 + + END DO !I + + END IF + + + ! WvKinFile + + IF ( InitInp%Waves%WaveMod == 5 .OR. InitInp%Waves%WaveMod == 6 ) THEN ! .TRUE if we are to read user-supplied wave elevation or wave kinematics file(s). + + IF ( LEN_TRIM( InitInp%Waves%WvKinFile ) == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WvKinFile must not be an empty string.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( PathIsRelative( InitInp%Waves%WvKinFile ) ) THEN + CALL GetPath( TRIM(InitInp%InputFile), TmpPath ) + InitInp%Waves%WvKinFile = TRIM(TmpPath)//TRIM(InitInp%Waves%WvKinFile) + END IF + InitInp%Waves%WriteWvKin = .FALSE. + ELSE !don't use this one + +#ifdef WRITE_WV_KIN + IF ( LEN_TRIM( InitInp%Waves%WvKinFile ) == 0 ) THEN + InitInp%Waves%WriteWvKin = .FALSE. + ELSE + InitInp%Waves%WriteWvKin = .TRUE. + IF ( PathIsRelative( InitInp%Waves%WvKinFile ) ) THEN + CALL GetPath( TRIM(InitInp%InputFile), TmpPath ) + InitInp%Waves%WvKinFile = TRIM(TmpPath)//TRIM(InitInp%Waves%WvKinFile) + END IF + END IF + +#else + InitInp%Waves%WvKinFile = "" + InitInp%Waves%WriteWvKin = .FALSE. +#endif + END IF + + + ! NWaveElev + + IF ( InitInp%Waves%NWaveElev < 0 ) THEN + + CALL SetErrStat( ErrID_Fatal,'NWaveElev must not be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + + END IF + + + + !------------------------------------------------------------------------- + ! Check 2nd Order Waves section + !------------------------------------------------------------------------- + + + ! Difference frequency cutoffs + + ! WvLowCOffD and WvHiCOffD - Wave Cut-off frequency + IF ( InitInp%Waves2%WvLowCOffD < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WvLowCOffD must be greater than or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Check that the order given makes sense. + IF ( InitInp%Waves2%WvLowCOffD >= InitInp%Waves2%WvHiCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,'WvLowCOffD must be less than WvHiCOffD.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Sum frequency cutoffs + + ! WvLowCOffS and WvHiCOffD - Wave Cut-off frequency + IF ( InitInp%Waves2%WvLowCOffS < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WvLowCOffS must be greater than or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Check that the order given makes sense. + IF ( InitInp%Waves2%WvLowCOffS >= InitInp%Waves2%WvHiCOffS ) THEN + CALL SetErrStat( ErrID_Fatal,'WvLowCOffS must be less than WvHiCOffS.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Copy over the 2nd order limits to the WAMIT2 module which needs them. + InitInp%WAMIT2%WvLowCOffD = InitInp%Waves2%WvLowCOffD + InitInp%WAMIT2%WvHiCOffD = InitInp%Waves2%WvHiCOffD + InitInp%WAMIT2%WvLowCOffS = InitInp%Waves2%WvLowCOffS + InitInp%WAMIT2%WvHiCOffS = InitInp%Waves2%WvHiCOffS + + + + !------------------------------------------------------------------------- + ! Check Current section + !------------------------------------------------------------------------- + + + ! CurrMod - Current profile model switch + + IF ( ( InitInp%Current%CurrMod /= 0 ) .AND. ( InitInp%Current%CurrMod /= 1 ) .AND. ( InitInp%Current%CurrMod /= 2 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrMod must be 0, 1, or 2.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( ( InitInp%Current%CurrMod /= 0 ) .AND. ( InitInp%Waves%WaveMod == 6 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrMod must be set to 0 when WaveMod is set to 6: user-input wave data.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! CurrSSV0 - Sub-surface current velocity at still water level + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( InitInp%Current%CurrSSV0 < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrSSV0 must not be less than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrSSV0 = 0.0 + + END IF + + + ! CurrSSDirChr - Sub-surface current heading direction + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + + IF ( TRIM(InitInp%Current%CurrSSDirChr) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value of codirectionality between sub-surface current and incident wave propogation heading directions. + + IF ( InitInp%Waves%WaveMod == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrSSDir must not be set to ''DEFAULT'' when WaveMod is set to 0.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + InitInp%Current%CurrSSDir = InitInp%Waves%WaveDir + + ELSE ! The input must have been specified numerically. + + READ (InitInp%Current%CurrSSDirChr,*,IOSTAT=IOS) InitInp%Current%CurrSSDir + CALL CheckIOS ( IOS, "", 'CurrSSDir', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( ( InitInp%Current%CurrSSDir <= -180.0 ) .OR. ( InitInp%Current%CurrSSDir > 180.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrSSDir must be greater than -180 and less than or equal to 180.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + END IF + + + ELSE + + InitInp%Current%CurrSSDir = 0.0 + + END IF + + + ! CurrNSRef - Near-surface current reference depth. + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( InitInp%Current%CurrNSRef <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrNSRef must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrNSRef = 0.0 + + END IF + + + + ! CurrNSV0 - Near-surface current velocity at still water level. + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( InitInp%Current%CurrNSV0 < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrNSV0 must not be less than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrNSV0 = 0.0 + + END IF + + + ! CurrNSDir - Near-surface current heading direction. + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( ( InitInp%Current%CurrNSDir <= -180.0 ) .OR. ( InitInp%Current%CurrNSDir > 180.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrNSDir must be greater than -180 and less than or equal to 180.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrNSDir = 0.0 + + END IF + + + ! CurrDIV - Depth-independent current velocity. + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( InitInp%Current%CurrDIV < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrDIV must not be less than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrDIV = 0.0 + + END IF + + + ! CurrDIDir - Depth-independent current heading direction. + + IF ( InitInp%Current%CurrMod == 1 ) THEN ! .TRUE if we have standard current. + + IF ( ( InitInp%Current%CurrDIDir <= -180.0 ) .OR. ( InitInp%Current%CurrDIDir > 180.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'CurrDIDir must be greater than -180 and less than or equal to 180.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%Current%CurrDIDir = 0.0 + + END IF + + ! PotFile - Root name of potential flow files + + IF ( InitInp%PotMod > 0 ) THEN + IF ( LEN_TRIM( InitInp%PotFile ) == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'PotFile must not be an empty string.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! if this is a relative path, let's make it relative to the location of the main input file + ! tell the WAMIT and WAMIT2 modules what the filename is + + IF ( PathIsRelative( InitInp%PotFile ) ) THEN + CALL GetPath( TRIM(InitInp%InputFile), TmpPath ) + InitInp%PotFile = TRIM(TmpPath)//TRIM(InitInp%PotFile) + END IF + InitInp%WAMIT%WAMITFile = InitInp%PotFile + InitInp%WAMIT2%WAMITFile = InitInp%PotFile + + ! Set the flag for multidirectional waves for WAMIT2 module. It needs to know since the Newman approximation + ! can only use uni-directional waves. + InitInp%WAMIT2%WaveMultiDir = InitInp%Waves%WaveMultiDir + + ELSE + InitInp%PotFile = "" + InitInp%WAMIT%WAMITFile = "" + InitInp%WAMIT2%WAMITFile = "" + END IF + + ! Set the WAMIT file name on the Convolution module + InitInp%WAMIT%Conv_Rdtn%WAMITFile = InitInp%WAMIT%WAMITFile + + ! WAMITULEN - WAMIT characteristic body length scale + + IF ( InitInp%PotMod == 1 ) THEN + + InitInp%WAMIT2%WAMITULEN = InitInp%WAMIT%WAMITULEN ! Copy to the WAMIT2 module info + IF ( InitInp%WAMIT%WAMITULEN < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WAMITULEN must be positive.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE + + InitInp%WAMIT%WAMITULEN = 1.0 + InitInp%WAMIT2%WAMITULEN = 1.0 + + END IF + + + ! PtfmVol0 - Displaced volume of water when the platform is in its undisplaced position + + IF ( InitInp%PotMod == 1 ) THEN + + IF ( InitInp%WAMIT%PtfmVol0 < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'PtfmVol0 must not be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%WAMIT%PtfmVol0 = 0.0 + + END IF + + + ! RdtnTMax - Analysis time for wave radiation kernel calculations + ! NOTE: Use RdtnTMax = 0.0 to eliminate wave radiation damping + + IF ( InitInp%PotMod == 1 ) THEN + + IF ( InitInp%WAMIT%RdtnTMax < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'RdtnTMax must not be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE + + InitInp%WAMIT%RdtnTMax = 0.0 + + END IF + + ! RdtnDT - Time step for wave radiation kernel calculations + + IF ( InitInp%PotMod == 1 ) THEN + + CALL Conv2UC( InitInp%WAMIT%Conv_Rdtn%RdtnDTChr ) ! Convert Line to upper case. + + IF ( TRIM(InitInp%WAMIT%Conv_Rdtn%RdtnDTChr) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. + + InitInp%WAMIT%Conv_Rdtn%RdtnDT = InitInp%DT + + ELSE ! The input must have been specified numerically. + + READ (InitInp%WAMIT%Conv_Rdtn%RdtnDTChr,*,IOSTAT=IOS) InitInp%WAMIT%Conv_Rdtn%RdtnDT + CALL CheckIOS ( IOS, "", 'RdtnDT', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( InitInp%WAMIT%Conv_Rdtn%RdtnDT <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'RdtnDT must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + if ( (.not. ( EqualRealNos(InitInp%DT, InitInp%WAMIT%Conv_Rdtn%RdtnDT) ) ) .and. ( (InitInp%WAMIT%ExctnMod > 1) .or. (InitInp%WAMIT%RdtnMod > 0) ) ) then + call SetErrStat( ErrID_Fatal,'RdtnDT must be equal to the glue-code DT if PotMod = 1 and using RdtnMod > 0 or ExctnMod > 1.',ErrStat,ErrMsg,RoutineName) + return + end if + + ELSE + + InitInp%WAMIT%Conv_Rdtn%RdtnDT = 0.0 + + END IF + + !------------------------------------------------------------------------------------------------- + ! Data section for Floating platform force flags + !------------------------------------------------------------------------------------------------- + +!FIXME: ADP -- the error handling in this section is broken. + + ! If DEFAULT was requested, then the required value has already been set by the calling program + IF ( TRIM(InitInp%PtfmSgFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmSgFChr,*,IOSTAT=IOS) InitInp%PtfmSgF + CALL CheckIOS ( IOS, "", 'PtfmSgF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( TRIM(InitInp%PtfmSwFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmSwFChr,*,IOSTAT=IOS) InitInp%PtfmSwF + CALL CheckIOS ( IOS, "", 'PtfmSwF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( TRIM(InitInp%PtfmHvFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmHvFChr,*,IOSTAT=IOS) InitInp%PtfmHvF + CALL CheckIOS ( IOS, "", 'PtfmHvF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( TRIM(InitInp%PtfmRFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmRFChr,*,IOSTAT=IOS) InitInp%PtfmRF + CALL CheckIOS ( IOS, "", 'PtfmRF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( TRIM(InitInp%PtfmPFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmPFChr,*,IOSTAT=IOS) InitInp%PtfmPF + CALL CheckIOS ( IOS, "", 'PtfmPF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + IF ( TRIM(InitInp%PtfmYFChr) /= 'DEFAULT' ) THEN + + READ (InitInp%PtfmYFChr,*,IOSTAT=IOS) InitInp%PtfmYF + CALL CheckIOS ( IOS, "", 'PtfmYF', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + END IF + + + ! Add checks that all platform DOF flags are true. TODO: Allow true or false once these have been implemented + + IF ( ( .NOT. InitInp%PtfmSgF ) .OR. ( .NOT. InitInp%PtfmSwF ) .OR. ( .NOT. InitInp%PtfmHvF ) .OR. ( .NOT. InitInp%PtfmRF ) .OR. ( .NOT. InitInp%PtfmPF ) .OR. ( .NOT. InitInp%PtfmYF ) )THEN +! CALL SetErrStat( ErrID_Fatal,'All platform DOF parameters must be set to TRUE. Future versions of HydroDyn will support values of TRUE, FALSE, or DEFAULT.',ErrStat,ErrMsg,RoutineName) + CALL SetErrStat( ErrID_Warn,' Only the second-order floating platform force calculations (WAMIT2 sub-module) allow for selectively dissabling force DOF parameters, the first order (WAMIT sub-module) does not and will calculate all dimensions. Future versions of HydroDyn will support values of TRUE, FALSE, or DEFAULT for both modules.',ErrStat,ErrMsg,RoutineName) + END IF + + + + !------------------------------------------------------------------------------------------------- + ! Second order Forces Flags (WAMIT2 Module) + !------------------------------------------------------------------------------------------------- + ! We don't have separate inputs for the second order force component flags, rather they are taken + ! from the platform section in the input file and copied into the InitInp%WAMIT2 derived type. + ! Within the WAMIT2_Init subroutine, they are reset if necessary (some second order output files + ! from WAMIT don't support all force components -- i.e. the *.8 files). + + InitInp%WAMIT2%PtfmSgF2 = InitInp%PtfmSgF + InitInp%WAMIT2%PtfmSwF2 = InitInp%PtfmSwF + InitInp%WAMIT2%PtfmHvF2 = InitInp%PtfmHvF + InitInp%WAMIT2%PtfmRF2 = InitInp%PtfmRF + InitInp%WAMIT2%PtfmPF2 = InitInp%PtfmPF + InitInp%WAMIT2%PtfmYF2 = InitInp%PtfmYF + + + + !------------------------------------------------------------------------------------------------- + ! Second order Forces due to Waves section (WAMIT2 Module) + !------------------------------------------------------------------------------------------------- + + + ! Check that we only specified one of MnDrift, NewmanApp, or DiffQTF + ! (compared pairwise -- if any two are both true, we have a problem) + IF ( ( InitInp%WAMIT2%MnDrift /= 0 .AND. InitInp%WAMIT2%NewmanApp /= 0 ) .OR. & + ( InitInp%WAMIT2%DiffQTF /= 0 .AND. InitInp%WAMIT2%NewmanApp /= 0 ) .OR. & + ( InitInp%WAMIT2%MnDrift /= 0 .AND. InitInp%WAMIT2%DiffQTF /= 0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Check MnDrift and set the flag indicating WAMIT2 should perform the mean drift calculation. + ! Also make sure we have a valid input value for the file extension + + IF ( InitInp%WAMIT2%MnDrift == 0 ) THEN ! not using MnDrift + InitInp%WAMIT2%MnDriftF = .FALSE. + ELSE IF ( InitInp%WAMIT2%MnDrift == 7 .OR. InitInp%WAMIT2%MnDrift == 8 .OR. InitInp%WAMIT2%MnDrift == 9 .OR. & + InitInp%WAMIT2%MnDrift == 10 .OR. InitInp%WAMIT2%MnDrift == 11 .OR. InitInp%WAMIT2%MnDrift == 12 ) THEN ! Valid values for MnDrift + InitInp%WAMIT2%MnDriftF = .TRUE. + ELSE ! Must have received an invalid value + CALL SetErrStat( ErrID_Fatal,'MnDrift can only have values of 0, 7, 8, 9, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Check NewmanApp and set the flag indicating WAMIT2 should perform the mean drift calculation. + ! Also make sure we have a valid input value for the file extension + + IF ( InitInp%WAMIT2%NewmanApp == 0 ) THEN ! not using NewmanApp + InitInp%WAMIT2%NewmanAppF = .FALSE. + ELSE IF ( InitInp%WAMIT2%NewmanApp == 7 .OR. InitInp%WAMIT2%NewmanApp == 8 .OR. InitInp%WAMIT2%NewmanApp == 9 .OR. & + InitInp%WAMIT2%NewmanApp == 10 .OR. InitInp%WAMIT2%NewmanApp == 11 .OR. InitInp%WAMIT2%NewmanApp == 12 ) THEN ! Valid values for NewmanApp + InitInp%WAMIT2%NewmanAppF = .TRUE. + ELSE ! Must have received an invalid value + CALL SetErrStat( ErrID_Fatal,'NewmanApp can only have values of 0, 7, 8, 9, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Check DiffQTF and set the flag indicating WAMIT2 should perform the mean drift calculation. + ! Also make sure we have a valid input value for the file extension + + IF ( InitInp%WAMIT2%DiffQTF == 0 ) THEN ! not using DiffQTF method + InitInp%WAMIT2%DiffQTFF = .FALSE. + ELSE IF ( InitInp%WAMIT2%DiffQTF == 10 .OR. InitInp%WAMIT2%DiffQTF == 11 .OR. InitInp%WAMIT2%DiffQTF == 12 ) THEN ! Valid values for DiffQTF + InitInp%WAMIT2%DiffQTFF = .TRUE. + ELSE + CALL SetErrStat( ErrID_Fatal,'DiffQTF can only have values of 0, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Check SumQTF and set the flag indicating WAMIT2 should perform the mean drift calculation. + ! Also make sure we have a valid input value for the file extension + + IF ( InitInp%WAMIT2%SumQTF == 0 ) THEN ! not using SumQTF method + InitInp%WAMIT2%SumQTFF = .FALSE. + ELSE IF ( InitInp%WAMIT2%SumQTF == 10 .OR. InitInp%WAMIT2%SumQTF == 11 .OR. InitInp%WAMIT2%SumQTF == 12 ) THEN ! Valid values for SumQTF + InitInp%WAMIT2%SumQTFF = .TRUE. + ELSE + CALL SetErrStat( ErrID_Fatal,'SumQTF can only have values of 0, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! Check that the min / max diff frequencies make sense if using any DiffQTF method + IF ( InitInp%WAMIT2%DiffQTF /= 0 .OR. InitInp%WAMIT2%MnDrift /= 0 .OR. InitInp%WAMIT2%NewmanApp /=0 ) THEN + IF ( ( InitInp%WAMIT2%WvHiCOffD < InitInp%WAMIT2%WvLowCOffD ) .OR. ( InitInp%WAMIT2%WvLowCOffD < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'WvHiCOffD must be larger than WvLowCOffD. Both must be positive.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE ! set to zero since we don't need them + InitInp%WAMIT2%WvLowCOffD = 0.0 + InitInp%WAMIT2%WvHiCOffD = 0.0 + END IF + + + ! Check that the min / max diff frequencies make sense if using SumQTF + IF ( InitInp%WAMIT2%SumQTF /= 0 ) THEN + IF ( ( InitInp%WAMIT2%WvHiCOffS < InitInp%WAMIT2%WvLowCOffS ) .OR. ( InitInp%WAMIT2%WvLowCOffS < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'WvHiCOffS must be larger than WvLowCOffS. Both must be positive.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE ! set to zero since we don't need them + InitInp%WAMIT2%WvLowCOffS = 0.0 + InitInp%WAMIT2%WvHiCOffS = 0.0 + END IF + + + ! now that it has been established that the input parameters for second order are good, we check to make sure that the WAMIT files actually exist. + ! Check MnDrift file + IF ( InitInp%WAMIT2%MnDrift /= 0) THEN + ! Check if using QTF file types (10d, 11d, 12d) or not (7,8,9) + IF ( InitInp%WAMIT2%MnDrift <= 9 ) THEN + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%MnDrift)) + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + ELSE ! 10, 11, 12 + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%MnDrift))//'d' + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + ENDIF + IF ( .not. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal,'Cannot find the WAMIT file '//TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension)// & + ' required by the MnDrift option.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + ! Check existence of NewmanApp file + IF ( InitInp%WAMIT2%NewmanApp /= 0) THEN + ! Check if using QTF file types (10d, 11d, 12d) or not (7,8,9) + IF ( InitInp%WAMIT2%NewmanApp <= 9 ) THEN + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%NewmanApp)) + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + ELSE ! 10, 11, 12 + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%NewmanApp))//'d' + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + ENDIF + IF ( .not. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal,'Cannot find the WAMIT file '//TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension)// & + ' required by the NewmanApp option.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + IF ( InitInp%WAMIT2%DiffQTF /= 0) THEN + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%DiffQTF))//'d' + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + IF ( .not. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal,'Cannot find the WAMIT file '//TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension)// & + ' required by the DiffQTF option.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + IF ( InitInp%WAMIT2%SumQTF /= 0) THEN + TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%SumQTF))//'s' + INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) + IF ( .not. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal,'Cannot find the WAMIT file '//TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension)// & + ' required by the SumQTF option.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + !.................. + ! check for ExctnMod = 2 requirements + !.................. + if ( (InitInp%WAMIT%ExctnMod == 2) ) then + + if ( InitInp%Waves%WaveMod == 6 ) then + call SetErrStat( ErrID_Fatal, 'Externally generated full wave-kinematics time series cannot be used with state-space wave excitations. Set WaveMod 0, 1, 1P#, 2, 3, 4, or 5.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves%WaveDirMod /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Directional spreading cannot be used with state-space wave excitations. Set WaveDirMod=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves2%WvDiffQTFF ) then + call SetErrStat( ErrID_Fatal, 'Cannot use full difference-frequency 2nd-order wave kinematics with state-space wave excitations. Set WvDiffQTF=FALSE.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves2%WvSumQTFF ) then + call SetErrStat( ErrID_Fatal, 'Cannot use full summation-frequency 2nd-order wave kinematics with state-space wave excitations. Set WvSumQTF=FALSE.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%PotMod /= 1 ) then + call SetErrStat( ErrID_Fatal, 'Potential-flow model via WAMIT must be used with state-space wave excitations. Set PotMod= 1.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%MnDrift /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Mean-drift 2nd-order forces cannot be used with state-space wave excitations. Set MnDrift=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%NewmanApp /= 0 ) then + call SetErrStat( ErrID_Fatal, "Mean- and slow-drift 2nd-order forces computed with Newman's approximation cannot be used with state-space wave excitations. Set NewmanApp=0.", ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%DiffQTF /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Full difference-frequency 2nd-order forces computed with full QTF cannot be used with state-space wave excitations. Set DiffQTF=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%SumQTF /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Full summation-frequency 2nd-order forces computed with full QTF cannot be used with State-space wave excitations. Set SumQTF=0.', ErrStat, ErrMsg, RoutineName ) + end if + + end if + + !.................. + ! check for linearization + !.................. + if (InitInp%Linearize) then + + if ( InitInp%Waves%WaveMod /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Still water conditions must be used for linearization. Set WaveMod=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves%WaveDirMod /= 0 ) then + call SetErrStat( ErrID_Fatal, 'No directional spreading must be used for linearization. Set WaveDirMod=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves2%WvDiffQTFF ) then + call SetErrStat( ErrID_Fatal, 'Cannot use full difference-frequency 2nd-order wave kinematics for linearization. Set WvDiffQTF=FALSE.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%Waves2%WvSumQTFF ) then + call SetErrStat( ErrID_Fatal, 'Cannot use full summation-frequency 2nd-order wave kinematics for linearization. Set WvSumQTF=FALSE.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%PotMod > 1 ) then + call SetErrStat( ErrID_Fatal, 'Potential-flow model cannot be set to FIT for linearization. Set PotMod= 0 or 1.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( (InitInp%WAMIT%ExctnMod == 1) ) then + call SetErrStat( ErrID_Fatal, 'Cannot set wave excitation model to DFT for linearization. Set ExctnMod=0 or 2.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT%RdtnMod == 1 ) then + call SetErrStat( ErrID_Fatal, 'Cannot set wave radiation model to convolution for linearization. Set RdtnMod=0 or 2.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%MnDrift /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Mean-drift 2nd-order forces cannot be used for linearization. Set MnDrift=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%NewmanApp /= 0 ) then + call SetErrStat( ErrID_Fatal, "Mean- and slow-drift 2nd-order forces computed with Newman's approximation cannot be used for linearization. Set NewmanApp=0.", ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%DiffQTF /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Full difference-frequency 2nd-order forces computed with full QTF cannot be used for linearization. Set DiffQTF=0.', ErrStat, ErrMsg, RoutineName ) + end if + + if ( InitInp%WAMIT2%SumQTF /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Full summation-frequency 2nd-order forces computed with full QTF cannot be used for linearization. Set SumQTF=0.', ErrStat, ErrMsg, RoutineName ) + end if + + end if + + + + + + !------------------------------------------------------------------------------------------------- + ! Member Joints Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NJoints < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NJoints parameter cannot be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NJoints == 1 ) THEN + CALL SetErrStat( ErrID_Fatal,'NJoints parameter cannot be set to 1.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + + ! Check the axial coefs are >= 0 and IDs are unique + IF ( InitInp%Morison%NAxCoefs > 0 ) THEN + + DO I = 1,InitInp%Morison%NAxCoefs + + !IF ( .NOT. EqualRealNos(InitInp%Morison%AxialCoefs(I)%AxCd, 0.0) ) THEN + ! ErrMsg = ' AxCd must be equal to zero. Future versions will allow for non-zero axial coefficients.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + !IF ( .NOT. EqualRealNos(InitInp%Morison%AxialCoefs(I)%AxCa, 0.0) ) THEN + ! ErrMsg = ' AxCa must be equal to zero. Future versions will allow for non-zero axial coefficients.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + + ! TODO: Once Axial Coefs are working remove the above checks and uncomment the checks below. GJH 9/29/2013 + IF ( InitInp%Morison%AxialCoefs(I)%AxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'AxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%AxialCoefs(I)%AxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'AxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Make sure that the current AxCoefID is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NAxCoefs + IF ( InitInp%Morison%AxialCoefs(I)%AxCoefID == InitInp%Morison%AxialCoefs(J)%AxCoefID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate AxCoefIDs were found in the Axial Coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + END DO + + END IF + + + ! Check JointOvrlp values + InitInp%Morison%TotalPossibleSuperMembers = 0 + + IF ( InitInp%Morison%NJoints > 1 ) THEN + + ! Initialize Joints + DO I = 1,InitInp%Morison%NJoints + InitInp%Morison%InpJoints(I)%NConnections = 0 + END DO + + + + + DO I = 1,InitInp%Morison%NJoints + + ! Make sure that the current JointID is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NJoints + IF ( InitInp%Morison%InpJoints(I)%JointID == InitInp%Morison%InpJoints(J)%JointID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate JointIDs were found in the Member Joints table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + ! Add up total number of joints flagged with JoinOvrlp = 1 option + IF ( InitInp%Morison%InpJoints(I)%JointOvrlp == 1 ) THEN + InitInp%Morison%TotalPossibleSuperMembers = InitInp%Morison%TotalPossibleSuperMembers + 1 + END IF + + ! Check that every joint id is used at least once in the members table + JointUsed = .FALSE. + DO J = 1, InitInp%Morison%NMembers + + IF ( InitInp%Morison%InpMembers(J)%MJointID1 == InitInp%Morison%InpJoints(I)%JointID ) THEN + JointUsed = .TRUE. + EXIT + END IF + IF ( InitInp%Morison%InpMembers(J)%MJointID2 == InitInp%Morison%InpJoints(I)%JointID ) THEN + JointUsed = .TRUE. + EXIT + END IF + END DO + + IF ( .NOT. JointUsed ) THEN + CALL SetErrStat( ErrID_Fatal,'Every JointID in the Joints table must appear once in the Members table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ! TODO : Implement Super member elements. GJH 7/24/13 + + IF ( InitInp%Morison%InpJoints(I)%JointOvrlp /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'JointOvrlp parameter must be set to 0. Future versions of HydroDyn will support vales of 0 or 1.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + !IF ( ( InitInp%Morison%InpJoints(I)%JointOvrlp < 0 ) .OR. ( InitInp%Morison%InpJoints(I)%JointOvrlp > 1 ) ) THEN + ! ErrMsg = ' JointOvrlp parameter must be set to 0 or 1.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + + ! Make sure the axial coef id appears in the Ax table + IF ( InitInp%Morison%NAxCoefs > 0 ) THEN + InitInp%Morison%InpJoints(I)%JointAxIDIndx = -1 + DO J = 1,InitInp%Morison%NAxCoefs + IF ( InitInp%Morison%InpJoints(I)%JointAxID == InitInp%Morison%AxialCoefs(J)%AxCoefID ) & + InitInp%Morison%InpJoints(I)%JointAxIDIndx = J + END DO + IF ( InitInp%Morison%InpJoints(I)%JointAxIDIndx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'The specified JointAxID in the Joints Table does not appear in the Axial Coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE + ! TODO: Issue error because we need at least one Axial coef table entry GJH 8/1/31 + END IF + + END DO + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member Cross-section Properties Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NPropSets < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Number of member cross-section property sets must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NPropSets > 0 ) THEN + + DO I = 1,InitInp%Morison%NPropSets + + ! Make sure that the current JointID is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NPropSets + IF ( InitInp%Morison%MPropSets(I)%PropSetID == InitInp%Morison%MPropSets(J)%PropSetID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate PropSetIDs were found in the Member Cross-section Properties table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( ( InitInp%Morison%MPropSets(I)%PropD < 0 ) .OR. ( InitInp%Morison%MPropSets(I)%PropThck < 0 ) .OR. ( ( InitInp%Morison%MPropSets(I)%PropD - InitInp%Morison%MPropSets(I)%PropThck / 2.0 ) < 0) ) THEN + CALL SetErrStat( ErrID_Fatal,'PropD and PropThck must be greater than zero and (PropD - propThck/2 ) must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Simple hydrodynamic coefficients Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%SimplCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplAxCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Depth-based Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NCoefDpth < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpth must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + IF ( InitInp%Morison%NCoefDpth > 0 ) THEN + MinDepth = 99999999.0 + MaxDepth = -99999999.0 + DO I = 1,InitInp%Morison%NCoefDpth + + ! Record the minimum and maximum depths covered by this table. This will be used as part of a consistency check + ! in the members table, below. + IF ( InitInp%Morison%CoefDpths(I)%Dpth < MinDepth ) THEN + MinDepth = InitInp%Morison%CoefDpths(I)%Dpth + ELSE + CALL SetErrStat( ErrID_Fatal,'The rows of the Depth-based Hydrodynamic Coefficients table must be ordered with increasing depth (decreasing Z).',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%Dpth > MaxDepth ) THEN + MaxDepth = InitInp%Morison%CoefDpths(I)%Dpth + END IF + + ! Make sure that the current Dpth is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NCoefDpth + IF ( EqualRealNos( InitInp%Morison%CoefDpths(I)%Dpth, InitInp%Morison%CoefDpths(J)%Dpth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate Dpths were found in the Depth-based Hydrodynamic Coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( InitInp%Morison%CoefDpths(I)%DpthCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCp < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCp must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCpMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCpMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + ! TODO: Sort the table based on depth so that a linear interpolation can be easily performed between entries. + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member-based Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NCoefMembers < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembers must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NCoefMembers > 0 ) THEN + + DO I = 1,InitInp%Morison%NCoefMembers + + ! Make sure that the current MemberID is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NCoefMembers + IF ( InitInp%Morison%CoefMembers(I)%MemberID == InitInp%Morison%CoefMembers(J)%MemberID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate MemberIDs were found in the Member-based Hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + + + IF ( InitInp%Morison%CoefMembers(I)%MemberCd1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCd1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCd2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCd2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCdMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCdMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCdMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCdMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCa1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCa2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCaMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberCaMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberAxCa1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberAxCa2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberAxCaMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefMembers(I)%MemberAxCaMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Members Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NMembers < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NMembers in the Members table must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NMembers > 0 ) THEN + + ! Initialize all member data + DO I = 1,InitInp%Morison%NMembers + InitInp%Morison%InpMembers(I)%MJointID1Indx = -1 + InitInp%Morison%InpMembers(I)%MJointID2Indx = -1 + InitInp%Morison%InpMembers(I)%MPropSetID1Indx = -1 + InitInp%Morison%InpMembers(I)%MPropSetID2Indx = -1 + InitInp%Morison%InpMembers(I)%MmbrFilledIDIndx = -1 + InitInp%Morison%InpMembers(I)%MmbrCoefIDIndx = -1 + InitInp%Morison%InpMembers(I)%NumSplits = 0 + InitInp%Morison%InpMembers(I)%Splits = 0.0_ReKi + END DO + + DO I = 1,InitInp%Morison%NMembers + + ! Make sure that the current MemberID is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NMembers + IF ( InitInp%Morison%InpMembers(I)%MemberID == InitInp%Morison%InpMembers(J)%MemberID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate MemberIDs were found in the Members table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + ! Find JointID1 and JointID2 in the Joint table and then record their index locations in the Joint table + DO J = 1,InitInp%Morison%NJoints + IF ( InitInp%Morison%InpMembers(I)%MJointID1 == InitInp%Morison%InpJoints(J)%JointID ) THEN + InitInp%Morison%InpMembers(I)%MJointID1Indx = J + InitInp%Morison%InpJoints(J)%NConnections = InitInp%Morison%InpJoints(J)%NConnections + 1 + InitInp%Morison%InpJoints(J)%ConnectionList(InitInp%Morison%InpJoints(J)%NConnections) = I + END IF + IF ( InitInp%Morison%InpMembers(I)%MJointID2 == InitInp%Morison%InpJoints(J)%JointID ) THEN + InitInp%Morison%InpMembers(I)%MJointID2Indx = J + InitInp%Morison%InpJoints(J)%NConnections = InitInp%Morison%InpJoints(J)%NConnections + 1 + InitInp%Morison%InpJoints(J)%ConnectionList(InitInp%Morison%InpJoints(J)%NConnections) = I + END IF + END DO + + ! Make sure that a JointID entry in the Joints table was found + IF ( InitInp%Morison%InpMembers(I)%MJointID1Indx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'JointID1 in the Members table does not appear in the Joints table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%InpMembers(I)%MJointID2Indx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'JointID2 in the Members table does not appear in the Joints table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Make sure we do not have any zero length members + lvec = InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID1Indx)%JointPos - InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID2Indx)%JointPos + l = sqrt( lvec(1)*lvec(1) + lvec(2)*lvec(2) + lvec(3)*lvec(3) ) + IF ( EqualRealNos(0.0_ReKi, l) ) THEN + CALL SetErrStat( ErrID_Fatal,'A member cannot have zero length.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Find MPropSetID1 and MPropSetID2 in the Member cross-section properties table and then record their index locations + DO J = 1,InitInp%Morison%NPropSets + + + + IF ( InitInp%Morison%InpMembers(I)%MPropSetID1 == InitInp%Morison%MPropSets(J)%PropSetID ) THEN + InitInp%Morison%InpMembers(I)%MPropSetID1Indx = J + END IF + IF ( InitInp%Morison%InpMembers(I)%MPropSetID2 == InitInp%Morison%MPropSets(J)%PropSetID ) THEN + InitInp%Morison%InpMembers(I)%MPropSetID2Indx = J + END IF + END DO + + ! Make sure that a PropSetID entry in the Member cross-section properties table was found + IF ( InitInp%Morison%InpMembers(I)%MPropSetID1Indx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'MPropSetID1 in the Members table does not appear in the Member cross-section properties table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%InpMembers(I)%MPropSetID2Indx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'MPropSetID2 in the Members table does not appear in the Member cross-section properties table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! NOTE: We cannot test that MDivSize > MemberLength yet because there may be a joint overlap which is going to alter the final length of this member + + IF ( InitInp%Morison%InpMembers(I)%MDivSize <= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'MDivSize must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + IF ( ( InitInp%Morison%InpMembers(I)%MCoefMod /= 1 ) .AND. ( InitInp%Morison%InpMembers(I)%MCoefMod /= 2 ) .AND. ( InitInp%Morison%InpMembers(I)%MCoefMod /= 3 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'MCoefMod must be 1, 2, or 3.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%InpMembers(I)%MCoefMod == 2 ) THEN + IF ( InitInp%Morison%NCoefDpth == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpth must be greater than zero when a member is using a depth-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ! We will not extrapolate depth-based coefficient values, so make sure that the depth-based table has values that are outside the depth range of this member + ! NOTE: This is actually potentially overly conservative because the final member may be shorter due to joint overlap handling. + z1 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID1Indx )%JointPos(3) + z2 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID2Indx )%JointPos(3) + MinMembrDpth = min( z1, z2 ) + MaxMembrDpth = max( z1, z2 ) + IF ( ( MinMembrDpth < MinDepth ) .OR. ( MaxMembrDpth > MaxDepth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'This member uses a depth-based coefficient model, but the member depth is outside the range of values provided in the depth-based hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + END IF + + + IF ( InitInp%Morison%InpMembers(I)%MCoefMod == 3 ) THEN + IF ( InitInp%Morison%NCoefMembers == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembers must be greater than zero when a member is using a member-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ! Make sure this id appears in the Members table and mark it's location for future use + FoundID = .FALSE. + DO J = 1,InitInp%Morison%NCoefMembers + IF ( InitInp%Morison%CoefMembers(J)%MemberID == InitInp%Morison%InpMembers(I)%MemberID ) THEN + FoundID = .TRUE. + InitInp%Morison%InpMembers(I)%MmbrCoefIDIndx = J + END IF + END DO + + IF ( .NOT. FoundID ) THEN + CALL SetErrStat( ErrID_Fatal,'Could not locate the MemberID referenced in the Members table in the associated Member-based Hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END IF + + IF ( InitInp%Morison%InpMembers(I)%PropPot .AND. InitInp%PotMod == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'A member cannot have PropPot set to TRUE if PotMod = 0 in the FLOATING PLATFORM section.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Filled Members Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NFillGroups < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NFillGroups in the Filled-members table must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NFillGroups > 0 ) THEN + + DO I = 1,InitInp%Morison%NFillGroups + + IF ( InitInp%Morison%FilledGroups(I)%FillNumM < 1 ) THEN + CALL SetErrStat( ErrID_Fatal,'FillNumM in the Filled-members table must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + DO J = 1,InitInp%Morison%FilledGroups(I)%FillNumM + + DO K=1,InitInp%Morison%NMembers + IF ( InitInp%Morison%FilledGroups(I)%FillMList(J) == InitInp%Morison%InpMembers(K)%MemberID ) THEN + FoundID = .TRUE. + ! Check to make sure this member is not already part of another fill group! + IF ( InitInp%Morison%InpMembers(K)%MmbrFilledIDIndx /= -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'A member cannot be a part of more than one fill group!',ErrStat,ErrMsg,RoutineName) + END IF + + InitInp%Morison%InpMembers(k)%MmbrFilledIDIndx = I + + END IF + END DO + + END DO + + + + ! Make sure that the filled group members are connected + ! NOTE: This would be easier if the input mesh was already a FAST Framework mesh because then you could use the mesh routines to determine connectivity. + + !InitInp%Morison%FilledGroups(I)%FillMList(J) + + ! Make sure the FillFSLoc is within one of the group members + !InitInp%Morison%FilledGroups(I)%FillFSLoc + + + ! Deal with DEFAULT or create a REAL from the string + + IF ( TRIM(InitInp%Morison%FilledGroups(I)%FillDensChr) /= 'DEFAULT' ) THEN + + READ (InitInp%Morison%FilledGroups(I)%FillDensChr,*,IOSTAT=IOS) InitInp%Morison%FilledGroups(I)%FillDens + CALL CheckIOS ( IOS, "", 'FillDens', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + ELSE + InitInp%Morison%FilledGroups(I)%FillDens = InitInp%Waves%WtrDens + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Marine Growth by Depth Section + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%Morison%NMGDepths < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NMGDepths in the Marine growth table must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + IF ( InitInp%Morison%NMGDepths > 0 ) THEN + + InitInp%Morison%MGTop = -999999.0 + InitInp%Morison%MGBottom = 999999.0 + + DO I = 1,InitInp%Morison%NMGDepths + + ! Store the boundaries of the marine growth zone + IF ( InitInp%Morison%MGDepths(I)%MGDpth > InitInp%Morison%MGTop ) THEN + InitInp%Morison%MGTop = InitInp%Morison%MGDepths(I)%MGDpth + END IF + IF ( InitInp%Morison%MGDepths(I)%MGDpth < InitInp%Morison%MGBottom ) THEN + InitInp%Morison%MGBottom = InitInp%Morison%MGDepths(I)%MGDpth + ELSE + CALL SetErrStat( ErrID_Fatal,'The rows of the marine growth table must be ordered with increasing depth (decreasing Z).',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ! Make sure that the current MGDpth is not used elsewhere in the table. + DO J = I+1,InitInp%Morison%NMGDepths + IF ( EqualRealNos( InitInp%Morison%MGDepths(I)%MGDpth, InitInp%Morison%MGDepths(J)%MGDpth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate MGDpth were found in the Marine Growth table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( InitInp%Morison%MGDepths(I)%MGThck < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'MGThck in the Marine growth table must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%MGDepths(I)%MGDens < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'MGDens in the Marine growth table must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + END DO + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Member Output List Section + !------------------------------------------------------------------------------------------------- + + IF ( ( InitInp%Morison%NMOutputs < 0 ) .OR. ( InitInp%Morison%NMOutputs > 9 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'NMOutputs in the Member output list must be greater or equal to zero and less than 10.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NMOutputs > 0 ) THEN + + + DO I = 1,InitInp%Morison%NMOutputs + + InitInp%Morison%MOutLst(I)%MemberIDIndx = -1 + + ! Find MemberID in this Member output list table in the Members table + DO J = 1,InitInp%Morison%NMembers + IF ( InitInp%Morison%InpMembers(J)%MemberID == InitInp%Morison%MOutLst(I)%MemberID ) THEN + InitInp%Morison%MOutLst(I)%MemberIDIndx = J + END IF + END DO + + ! Make sure that a PropSetID entry in the Member cross-section properties table was found + IF ( InitInp%Morison%MOutLst(I)%MemberIDIndx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'MemberID in the Member output list table does not appear in the Members table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( ( InitInp%Morison%MOutLst(I)%NOutLoc < 1 ) .OR. ( InitInp%Morison%MOutLst(I)%NOutLoc > 9) ) THEN + CALL SetErrStat( ErrID_Fatal,'NOutLoc in the Member output list must be greater than zero and less than 10.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + DO J = 1,InitInp%Morison%MOutLst(I)%NOutLoc + IF ( ( InitInp%Morison%MOutLst(I)%NodeLocs(J) < 0.0 ) .OR. ( InitInp%Morison%MOutLst(I)%NodeLocs(J) > 1.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'NodeLocs in the Member output list must be greater or equal to 0.0 and less than or equal to 1.0.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + + END DO + + END IF + + !------------------------------------------------------------------------------------------------- + ! Joint Output List Section + !------------------------------------------------------------------------------------------------- + + !IF ( InitInp%Morison%NJOutputs /= 0 ) THEN ! TODO Remove this check and add back the other checks once Joint Outputs are supported + !CALL SetErrStat( ErrID_Fatal,'NJOutputs in the Joint output list must be equal to zero. Future versions of HydroDyn will support values greater or equal to zero and less than 10.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + + + IF ( ( InitInp%Morison%NJOutputs < 0 ) .OR. ( InitInp%Morison%NMOutputs > 9 ) ) THEN + CALL SetErrStat( ErrID_Fatal,'NJOutputs in the Joint output list must be greater or equal to zero and less than 10.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InitInp%Morison%NJOutputs > 0 ) THEN + + + DO I=1,InitInp%Morison%NJOutputs + + InitInp%Morison%JOutLst(I)%JointIDIndx = -1 + ! Find MemberID in this Member output list table in the Members table + DO J = 1,InitInp%Morison%NJoints + IF ( InitInp%Morison%InpJoints(J)%JointID == InitInp%Morison%JOutLst(I)%JointID ) THEN + InitInp%Morison%JOutLst(I)%JointIDIndx = J + EXIT + END IF + END DO + + ! Make sure that a PropSetID entry in the Member cross-section properties table was found + IF ( InitInp%Morison%JOutLst(I)%JointIDIndx == -1 ) THEN + CALL SetErrStat( ErrID_Fatal,'JointID in the Joint output list table does not appear in the Joints table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + END IF + + !------------------------------------------------------------------------------------------------- + ! Data section for OUTPUT + !------------------------------------------------------------------------------------------------- + + + ! OutAll - output all member and joint data + + IF ( InitInp%OutAll ) THEN !TODO: Alter this check once OutAll is supported + CALL SetErrStat( ErrID_Fatal,'OutAll must be FALSE. Future versions of HydroDyn will once again support values of either TRUE or FALSE.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + ! OutSwtch - output file switch + + IF ( InitInp%OutSwtch /= 1 .AND. InitInp%OutSwtch /= 2 .AND. InitInp%OutSwtch /= 3 ) THEN + CALL SetErrStat( ErrID_Fatal,'OutSwitch must be set to 1, 2, or 3.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + !InitInp%OutFmt + !InitInp%OutSFmt + + + ! OutList - list of requested parameters to output to a file + + + !---------------------------------------------------------- + ! Output List + !---------------------------------------------------------- + + ! First we need to extract module-specific output lists from the user-input list. + ! Any unidentified channels will be attached to the HydroDyn module's output list. + IF ( InitInp%NUserOutputs > 0 ) THEN + ALLOCATE ( foundMask(InitInp%NUserOutputs) , STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for temporary array: foundMask in the HydroDynInput_GetInput subroutine.',ErrStat,ErrMsg,RoutineName) + + RETURN + END IF + foundMask = .FALSE. + ! Extract Waves2 list + InitInp%Waves2%NumOuts = GetWaves2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Waves2%OutList, foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! Extract WAMIT list + InitInp%WAMIT%NumOuts = GetWAMITChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT%OutList, foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! Extract WAMIT2 list + InitInp%WAMIT2%NumOuts = GetWAMIT2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT2%OutList, foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! Extract Morison list + !foundMask = .FALSE. + InitInp%Morison%NumOuts = GetMorisonChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Morison%OutList, foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! Attach remaining items to the HydroDyn list + !foundMask = .FALSE. + InitInp%NumOuts = HDOut_GetChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%OutList , foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL PrintBadChannelWarning(InitInp%NUserOutputs, InitInp%UserOutputs , foundMask, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev ) RETURN + + DEALLOCATE(foundMask) + END IF + ! Now that we have the sub-lists organized, lets do some additional validation. + + + + + !---------------------------------------------------------- + ! Mesh-related Output List + !---------------------------------------------------------- + + IF ( InitInp%Morison%NumOuts > 0 ) THEN + + ! Create an output list for validated outputs + ALLOCATE ( InitInp%Morison%ValidOutList(InitInp%Morison%NumOuts), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating valid output list array.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + DO I =1, InitInp%Morison%NumOuts + + InitInp%Morison%ValidOutList(I) = CheckMeshOutput( InitInp%Morison%OutList(I), InitInp%Morison%NMOutputs, InitInp%Morison%MOutLst, InitInp%Morison%NJOutputs ) + + END DO + + END IF + + + !---------------------------------------------------------- + ! Populate data in sub-types from parent or other module types + !---------------------------------------------------------- + + ! Current + ! For wave kinematic calculations, the effective water depth is the user input water depth (positive valued) + MSL2SWL (positive when SWL is above MSL). + InitInp%Current%WtrDpth = InitInp%Morison%WtrDpth + InitInp%Morison%MSL2SWL ! Adjust for the MSL2SWL. + + + ! Waves + InitInp%Waves%Gravity = InitInp%Gravity + InitInp%Waves%UnSum = InitInp%UnSum + ! For wave kinematic calculations, the effective water depth is the user input water depth (positive valued) + MSL2SWL (positive when SWL is above MSL). + InitInp%Waves%WtrDpth = InitInp%Morison%WtrDpth + InitInp%Morison%MSL2SWL ! Adjust for the MSL2SWL + + ! Waves2 + IF (InitInp%Waves2%WvDiffQTFF .OR. InitInp%Waves2%WvSumQTFF ) THEN + InitInp%Waves2%WtrDens = InitInp%Waves%WtrDens + InitInp%Waves2%Gravity = InitInp%Gravity + InitInp%Waves2%UnSum = InitInp%UnSum + InitInp%Waves2%WtrDpth = InitInp%Waves%WtrDpth + InitInp%Waves2%WaveStMod = InitInp%Waves%WaveStMod + InitInp%Waves2%NWaveElev = InitInp%Waves%NWaveElev + CALL AllocAry( InitInp%Waves2%WaveElevxi, InitInp%Waves2%NWaveElev, 'WaveElevxi' , ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%Waves2%WaveElevyi, InitInp%Waves2%NWaveElev, 'WaveElevyi' , ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF ( ErrStat >= AbortErrLev ) RETURN + InitInp%Waves2%WaveElevxi = InitInp%Waves%WaveElevxi + InitInp%Waves2%WaveElevyi = InitInp%Waves%WaveElevyi + ENDIF + + ! WAMIT + InitInp%WAMIT%WtrDens = InitInp%Waves%WtrDens + InitInp%WAMIT%WaveMod = InitInp%Waves%WaveMod + InitInp%WAMIT%OutAll = InitInp%OutAll + InitInp%WAMIT%HasWAMIT = InitInp%PotMod == 1 + ! WAMIT2 + InitInp%WAMIT2%WtrDens = InitInp%Waves%WtrDens + InitInp%WAMIT2%WaveMod = InitInp%Waves%WaveMod + InitInp%WAMIT2%OutAll = InitInp%OutAll + InitInp%WAMIT2%HasWAMIT = InitInp%PotMod == 1 + ! Morison + InitInp%Morison%UnSum = InitInp%UnSum + InitInp%Morison%Gravity = InitInp%Gravity + InitInp%Morison%WtrDens = InitInp%Waves%WtrDens + InitInp%Morison%OutAll = InitInp%OutAll + + ! Process the input geometry and generate the simulation mesh representation + CALL Morison_ProcessMorisonGeometry( InitInp%Morison, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Set the number and global Z locations for the X and Y components of the current velocities + InitInp%Current%NMorisonNodes = InitInp%Morison%NNodes + + ALLOCATE ( InitInp%Current%MorisonNodezi(InitInp%Morison%NNodes), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for MorisonNodezi array.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + + + ! Establish the number and locations where the wave kinematics will be computed + InitInp%Waves%NWaveKin = InitInp%Morison%NNodes ! Number of points where the incident wave kinematics will be computed (-) + ALLOCATE ( InitInp%Waves%WaveKinxi(InitInp%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinxi array.',ErrStat,ErrMsg,RoutineName) + + RETURN + END IF + ALLOCATE ( InitInp%Waves%WaveKinyi(InitInp%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinyi array.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE ( InitInp%Waves%WaveKinzi(InitInp%Waves%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinzi array.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + DO I=1,InitInp%Morison%NNodes + InitInp%Waves%WaveKinxi(I) = InitInp%Morison%Nodes(I)%JointPos(1) ! xi-coordinates for points where the incident wave kinematics will be computed; + InitInp%Waves%WaveKinyi(I) = InitInp%Morison%Nodes(I)%JointPos(2) ! yi-coordinates for points where the incident wave kinematics will be computed; + InitInp%Waves%WaveKinzi(I) = InitInp%Morison%Nodes(I)%JointPos(3) - InitInp%Morison%MSL2SWL ! zi-coordinates for points where the incident wave kinematics will be computed, adjusted to the still water level(meters) + InitInp%Current%MorisonNodezi(I) = InitInp%Waves%WaveKinzi(I) + END DO + + + ! If we are using the Waves module, the node information must be copied over. + InitInp%Waves2%NWaveKin = InitInp%Waves%NWaveKin ! Number of points where the incident wave kinematics will be computed (-) + IF ( InitInp%Waves2%WvDiffQTFF .OR. InitInp%Waves2%WvSumQTFF ) THEN + ALLOCATE ( InitInp%Waves2%WaveKinxi(InitInp%Waves2%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinxi array for Waves2 module.',ErrStat,ErrMsg,RoutineName) + + RETURN + END IF + ALLOCATE ( InitInp%Waves2%WaveKinyi(InitInp%Waves2%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinyi array for Waves2 module.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE ( InitInp%Waves2%WaveKinzi(InitInp%Waves2%NWaveKin), STAT = ErrStat2 ) + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,'Error allocating space for WaveKinzi array for Waves2 module.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + InitInp%Waves2%WaveKinxi = InitInp%Waves%WaveKinxi + InitInp%Waves2%WaveKinyi = InitInp%Waves%WaveKinyi + InitInp%Waves2%WaveKinzi = InitInp%Waves%WaveKinzi + + ENDIF + +END SUBROUTINE HydroDynInput_ProcessInitData + +END MODULE HydroDyn_Input diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn_Output.f90 b/OpenFAST/modules/hydrodyn/src/HydroDyn_Output.f90 new file mode 100644 index 000000000..4f9f02318 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -0,0 +1,1127 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 HydroDyn_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + USE HydroDyn_Types + !USE HydroDyn_Output_Types + USE Waves + IMPLICIT NONE + + PRIVATE + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: AddFxi = 1 + INTEGER(IntKi), PARAMETER :: AddFyi = 2 + INTEGER(IntKi), PARAMETER :: AddFzi = 3 + INTEGER(IntKi), PARAMETER :: AddMxi = 4 + INTEGER(IntKi), PARAMETER :: AddMyi = 5 + INTEGER(IntKi), PARAMETER :: AddMzi = 6 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: HydroFxi = 7 + INTEGER(IntKi), PARAMETER :: HydroFyi = 8 + INTEGER(IntKi), PARAMETER :: HydroFzi = 9 + INTEGER(IntKi), PARAMETER :: HydroMxi = 10 + INTEGER(IntKi), PARAMETER :: HydroMyi = 11 + INTEGER(IntKi), PARAMETER :: HydroMzi = 12 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: Wave1Elev = 13 + INTEGER(IntKi), PARAMETER :: Wave1Elv1 = 14 + INTEGER(IntKi), PARAMETER :: Wave2Elev = 15 + INTEGER(IntKi), PARAMETER :: Wave2Elv1 = 16 + INTEGER(IntKi), PARAMETER :: Wave3Elev = 17 + INTEGER(IntKi), PARAMETER :: Wave3Elv1 = 18 + INTEGER(IntKi), PARAMETER :: Wave4Elev = 19 + INTEGER(IntKi), PARAMETER :: Wave4Elv1 = 20 + INTEGER(IntKi), PARAMETER :: Wave5Elev = 21 + INTEGER(IntKi), PARAMETER :: Wave5Elv1 = 22 + INTEGER(IntKi), PARAMETER :: Wave6Elev = 23 + INTEGER(IntKi), PARAMETER :: Wave6Elv1 = 24 + INTEGER(IntKi), PARAMETER :: Wave7Elev = 25 + INTEGER(IntKi), PARAMETER :: Wave7Elv1 = 26 + INTEGER(IntKi), PARAMETER :: Wave8Elev = 27 + INTEGER(IntKi), PARAMETER :: Wave8Elv1 = 28 + INTEGER(IntKi), PARAMETER :: Wave9Elev = 29 + INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 30 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: WavesFxi = 31 + INTEGER(IntKi), PARAMETER :: WavesFyi = 32 + INTEGER(IntKi), PARAMETER :: WavesFzi = 33 + INTEGER(IntKi), PARAMETER :: WavesMxi = 34 + INTEGER(IntKi), PARAMETER :: WavesMyi = 35 + INTEGER(IntKi), PARAMETER :: WavesMzi = 36 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: WRPSurge = 37 + INTEGER(IntKi), PARAMETER :: WRPSway = 38 + INTEGER(IntKi), PARAMETER :: WRPHeave = 39 + INTEGER(IntKi), PARAMETER :: WRPRoll = 40 + INTEGER(IntKi), PARAMETER :: WRPPitch = 41 + INTEGER(IntKi), PARAMETER :: WRPYaw = 42 + INTEGER(IntKi), PARAMETER :: WRPTVxi = 43 + INTEGER(IntKi), PARAMETER :: WRPTVyi = 44 + INTEGER(IntKi), PARAMETER :: WRPTVzi = 45 + INTEGER(IntKi), PARAMETER :: WRPRVxi = 46 + INTEGER(IntKi), PARAMETER :: WRPRVyi = 47 + INTEGER(IntKi), PARAMETER :: WRPRVzi = 48 + INTEGER(IntKi), PARAMETER :: WRPTAxi = 49 + INTEGER(IntKi), PARAMETER :: WRPTAyi = 50 + INTEGER(IntKi), PARAMETER :: WRPTAzi = 51 + INTEGER(IntKi), PARAMETER :: WRPRAxi = 52 + INTEGER(IntKi), PARAMETER :: WRPRAyi = 53 + INTEGER(IntKi), PARAMETER :: WRPRAzi = 54 + + !End of code generated by Matlab script + + + INTEGER, PARAMETER :: FHydro(6) = (/HydroFxi,HydroFyi,HydroFzi,HydroMxi,HydroMyi,HydroMzi/) + INTEGER, PARAMETER :: FAdd(6) = (/AddFxi,AddFyi,AddFzi,AddMxi,AddMyi,AddMzi/) + INTEGER, PARAMETER :: FWavesTot(6) = (/WavesFxi,WavesFyi,WavesFzi,WavesMxi,WavesMyi,WavesMzi/) + INTEGER, PARAMETER :: WRPMotions(6) = (/WRPSurge,WRPSway,WRPHeave,WRPRoll,WRPPitch,WRPYaw/) + INTEGER, PARAMETER :: WRPVel(6) = (/WRPTVxi,WRPTVyi,WRPTVzi,WRPRVxi,WRPRVyi,WRPRVzi/) + INTEGER, PARAMETER :: WRPAcc(6) = (/WRPTAxi,WRPTAyi,WRPTAzi,WRPRAxi,WRPRAyi,WRPRAzi/) + INTEGER, PARAMETER :: WaveElevi(9) = (/Wave1Elev,Wave2Elev,Wave3Elev,Wave4Elev,Wave5Elev,Wave6Elev,Wave7Elev,Wave8Elev,Wave9Elev/) + INTEGER, PARAMETER :: WaveElevi1(9) = (/Wave1Elv1,Wave2Elv1,Wave3Elv1,Wave4Elv1,Wave5Elv1,Wave6Elv1,Wave7Elv1,Wave8Elv1,Wave9Elv1/) + + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(54) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ADDFXI ","ADDFYI ","ADDFZI ","ADDMXI ","ADDMYI ","ADDMZI ", & + "HYDROFXI ","HYDROFYI ","HYDROFZI ","HYDROMXI ","HYDROMYI ","HYDROMZI ", & + "WAVE1ELEV","WAVE1ELV1", & + "WAVE2ELEV","WAVE2ELV1", & + "WAVE3ELEV","WAVE3ELV1", & + "WAVE4ELEV","WAVE4ELV1", & + "WAVE5ELEV","WAVE5ELV1", & + "WAVE6ELEV","WAVE6ELV1", & + "WAVE7ELEV","WAVE7ELV1", & + "WAVE8ELEV","WAVE8ELV1", & + "WAVE9ELEV","WAVE9ELV1", & + "WAVESFXI ","WAVESFYI ","WAVESFZI ","WAVESMXI ","WAVESMYI ","WAVESMZI ", & + "WRPHEAVE ","WRPPITCH ","WRPRAXI ","WRPRAYI ","WRPRAZI ","WRPROLL ", & + "WRPRVXI ","WRPRVYI ","WRPRVZI ","WRPSURGE ","WRPSWAY ","WRPTAXI ", & + "WRPTAYI ","WRPTAZI ","WRPTVXI ","WRPTVYI ","WRPTVZI ","WRPYAW "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(54) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + AddFxi , AddFyi , AddFzi , AddMxi , AddMyi , AddMzi , & + HydroFxi , HydroFyi , HydroFzi , HydroMxi , HydroMyi , HydroMzi , & + Wave1Elev , Wave1Elv1 , & + Wave2Elev , Wave2Elv1 , & + Wave3Elev , Wave3Elv1 , & + Wave4Elev , Wave4Elv1 , & + Wave5Elev , Wave5Elv1 , & + Wave6Elev , Wave6Elv1 , & + Wave7Elev , Wave7Elv1 , & + Wave8Elev , Wave8Elv1 , & + Wave9Elev , Wave9Elv1 , & + WavesFxi , WavesFyi , WavesFzi , WavesMxi , WavesMyi , WavesMzi , & + WRPHeave , WRPPitch , WRPRAxi , WRPRAyi , WRPRAzi , WRPRoll , & + WRPRVxi , WRPRVyi , WRPRVzi , WRPSurge , WRPSway , WRPTAxi , & + WRPTAyi , WRPTAzi , WRPTVxi , WRPTVyi , WRPTVzi , WRPYaw /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(54) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(rad) "/) + + + REAL(ReKi) :: AllOuts(MaxHDOutputs) ! Array of all possible outputs + + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: HDOut_CloseSum + PUBLIC :: HDOut_OpenSum + PUBLIC :: HDOut_MapOutputs + PUBLIC :: HDOut_WriteOutputs + PUBLIC :: HDOut_OpenOutput + PUBLIC :: HDOut_CloseOutput + PUBLIC :: HDOut_GetChannels + PUBLIC :: HDOUT_Init + PUBLIC :: HDOut_WriteWvKinFiles + +CONTAINS + +!==================================================================================================== +SUBROUTINE HDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER, INTENT( IN ) :: UnSum ! the unit number for the HydroDyn summary file + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + LOGICAL :: Err ! determines if an error exists + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + Err = .FALSE. + + ! Write any closing information in the summary file + + IF ( UnSum > 0 ) THEN + WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat) 'This summary file was closed on '//CurDate()//' at '//CurTime()//'.' + IF (ErrStat /= 0) THEN + Err = .TRUE. + ErrMsg = 'Problem writing to summary file' + END IF + END IF + + ! Close the file + + CLOSE( UnSum, IOSTAT=ErrStat ) + IF (ErrStat /= 0) THEN + Err = .TRUE. + ErrMsg = 'Problem closing summary file' + END IF + + IF ( Err ) ErrStat = ErrID_Fatal + + +END SUBROUTINE HDOut_CloseSum + +!==================================================================================================== +SUBROUTINE HDOut_OpenSum( UnSum, SummaryName, HD_Prog, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER, INTENT( OUT ) :: UnSum ! the unit number for the HydroDyn summary file + CHARACTER(*), INTENT( IN ) :: SummaryName ! the name of the HydroDyn summary file + TYPE(ProgDesc), INTENT( IN ) :: HD_Prog ! the name/version/date of the hydrodynamics program + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL GetNewUnit( UnSum ) + + CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + ! Write the summary file header + + WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat) 'This summary file was generated by '//TRIM( HD_Prog%Name )//& + ' '//TRIM( HD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' + +END SUBROUTINE HDOut_OpenSum + +!==================================================================================================== +SUBROUTINE HDOut_WriteWvKinFiles( Rootname, HD_Prog, NStepWave, NNodes, NWaveElev, nodeInWater, WaveElev, WaveKinzi, & + WaveTime, WaveVel, WaveAcc, WaveDynP, ErrStat, ErrMsg ) + + ! Passed variables + CHARACTER(*), INTENT( IN ) :: Rootname ! filename including full path, minus any file extension. + TYPE(ProgDesc), INTENT( IN ) :: HD_Prog ! the name/version/date of the hydrodynamics program + INTEGER, INTENT( IN ) :: NStepWave ! Number of time steps for the wave kinematics arrays + INTEGER, INTENT( IN ) :: NNodes ! Number of simulation nodes for the wave kinematics arrays + INTEGER, INTENT( IN ) :: NWaveElev ! Number of locations where wave elevations were requested + INTEGER, INTENT( IN ) :: nodeInWater(0:,: ) ! + REAL(SiKi), INTENT( IN ) :: WaveElev (0:,: ) ! Instantaneous wave elevations at requested locations + REAL(SiKi), INTENT( IN ) :: WaveKinzi(: ) ! The z-location of all the nodes + REAL(SiKi), INTENT( IN ) :: WaveTime (0: ) ! The time values for the wave kinematics (time) + REAL(SiKi), INTENT( IN ) :: WaveVel (0:,:,:) ! The wave velocities (time,node,component) + REAL(SiKi), INTENT( IN ) :: WaveAcc (0:,:,:) ! The wave accelerations (time,node,component) + REAL(SiKi), INTENT( IN ) :: WaveDynP(0:,:) ! The wave dynamic pressure (time,node) + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: UnWv ! file unit for writing the various wave kinematics files + CHARACTER(1024) :: WvName ! complete filename for one of the output files + CHARACTER(5) :: extension(7) + INTEGER :: i, j, iFile + CHARACTER(64) :: Frmt, Sfrmt + CHARACTER(ChanLen) :: Delim + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + extension = (/'.Vxi ','.Vyi ','.Vzi ','.Axi ','.Ayi ','.Azi ','.DynP'/) + Delim = '' + !Frmt = '('//TRIM(Int2LStr(NNodes))//'(:,A,ES11.4e2))' + Frmt = '(:,A,ES11.4e2)' + Sfrmt = '(:,A,A11)' + + + + DO iFile = 1,7 + + CALL GetNewUnit( UnWv ) + + WvName = Rootname // TRIM(extension(iFile)) + CALL OpenFOutFile ( UnWv, WvName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + + ! Write the summary file header + ! WRITE (UnWv,'(/,A/)', IOSTAT=ErrStat) 'This wave kinematics file was generated by '//TRIM( HD_Prog%Name )//& + WRITE (UnWv,'(A)', IOSTAT=ErrStat) 'This wave kinematics file was generated by '//TRIM( HD_Prog%Name )//& + ' '//TRIM( HD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' + + + DO i= 0,NStepWave-1 + DO j = 1, NNodes + IF ( nodeInWater(i,j) == 0 ) THEN + WRITE(UnWv,Sfrmt,ADVANCE='no') Delim, '##########' + ELSE + + SELECT CASE (iFile) + CASE (1) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveVel (i,j,1) + CASE (2) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveVel (i,j,2) + CASE (3) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveVel (i,j,3) + CASE (4) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveAcc (i,j,1) + CASE (5) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveAcc (i,j,2) + CASE (6) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveAcc (i,j,3) + CASE (7) + WRITE(UnWv,Frmt,ADVANCE='no') Delim, WaveDynP(i,j ) + END SELECT + END IF + END DO + WRITE (UnWv,'()', IOSTAT=ErrStat) ! write the line return + END DO + + CLOSE( UnWv, IOSTAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Problem closing wave kinematics file' + RETURN + END IF + END DO + + IF ( NWaveElev > 0 ) THEN + + CALL GetNewUnit( UnWv ) + + WvName = Rootname // '.Elev' + CALL OpenFOutFile ( UnWv, WvName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + + ! Write the summary file header + WRITE (UnWv,'(A)', IOSTAT=ErrStat) 'This wave kinematics file was generated by '//TRIM( HD_Prog%Name )//& + ' '//TRIM( HD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' + + + DO i= 0,NStepWave-1 + + Frmt = '('//TRIM(Int2LStr(NWaveElev))//'(:,A,ES11.4e2))' + WRITE(UnWv,Frmt) ( Delim, WaveElev(i,j) , j=1,NWaveElev ) + + END DO + + CLOSE( UnWv, IOSTAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Problem closing wave elevations file' + RETURN + END IF + + END IF + + +END SUBROUTINE HDOut_WriteWvKinFiles + +!==================================================================================================== +SUBROUTINE HDOut_MapOutputs( CurrentTime, y, NWaveElev, WaveElev, WaveElev1, F_Add, F_Waves, F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by HydroDyn_CalcOutput() at each time step. +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! HydroDyn's output data + INTEGER, INTENT( IN ) :: NWaveElev ! Number of wave elevation locations to output + REAL(ReKi), INTENT( IN ) :: WaveElev(:) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi), INTENT( IN ) :: WaveElev1(:) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi), INTENT( IN ) :: F_Add(6) + REAL(ReKi), INTENT( IN ) :: F_Waves(6) + REAL(ReKi), INTENT( IN ) :: F_Hydro(6) + REAL(ReKi), INTENT( IN ) :: q(6) ! WRP translations and rotations + REAL(ReKi), INTENT( IN ) :: qdot(6) ! WRP translational and rotational velocities + REAL(ReKi), INTENT( IN ) :: qdotdot(6) ! WRP translational and rotational accelerations + REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxHDOutputs) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + + ErrStat = ErrID_None + ErrMsg = "" + + + ! TODO: use y%mesh for the forces instead of individual parameters + + !AllOuts(Time) = REAL(CurrentTime,ReKi) + + AllOuts(FAdd) = F_Add + AllOuts(FWavesTot) = F_Waves + AllOuts(FHydro) = F_Hydro + AllOuts(WRPMotions) = q + AllOuts(WRPVel) = qdot + AllOuts(WRPAcc) = qdotdot + + DO I=1,NWaveElev + AllOuts(WaveElevi(I)) = WaveElev(I) + AllOuts(WaveElevi1(I))= WaveElev1(I) + END DO + + + +END SUBROUTINE HDOut_MapOutputs + +!==================================================================================================== +SUBROUTINE HDOut_WriteOutputs( Time, y, p, Decimate, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in HDOut_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + REAL(DbKi), INTENT( IN ) :: Time + TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! HydroDyn's output data + TYPE(HydroDyn_ParameterType), INTENT( IN ) :: p ! HydroDyn parameter data + INTEGER, INTENT( INOUT ) :: Decimate ! Output decimatation counter + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + IF (p%UnOutFile < 0 ) RETURN + + ! Initialize ErrStat and determine if it makes any sense to write output +!TODO: We should not have this check here, once per timestep! This should be resolved during initialization. GJH 7/7/2014 + IF ( ( (.NOT. ALLOCATED( p%OutParam )) .AND. (.NOT. ALLOCATED( p%WAMIT%OutParam ) ) .AND. (.NOT. ALLOCATED( p%WAMIT2%OutParam ) )& + .AND. (.NOT. ALLOCATED( p%Waves2%OutParam ) ) .AND. ( .NOT. ALLOCATED( p%Morison%OutParam ) ) ) ) THEN + ErrStat = ErrID_Warn + ErrMsg = ' Cannot write output to file because there are not a valid output list.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + ! Write the output parameters to the file + + !Frmt = '(F8.3,'//TRIM(Int2LStr(p%WAMIT%NumOuts+p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + + !WRITE(p%UnOutFile,Frmt) Time, ( p%Delim, y%WAMIT%WriteOutput(I), I=1,p%WAMIT%NumOuts), ( p%Delim, y%Morison%WriteOutput(I), I=1,p%Morison%NumOuts) + + IF ((Decimate .EQ. p%OutDec) .OR. (Decimate .EQ. 0)) THEN + + Decimate = 1 !reset counter + + Frmt = '(F10.4)' + + WRITE(p%UnOutFile,Frmt,ADVANCE='no') Time + + IF ( p%NumTotalOuts > 0 ) THEN + Frmt = '('//TRIM(Int2LStr(p%NumTotalOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WriteOutput(I) , I=1,p%NumTotalOuts ) + END IF + + ! ! HydroDyn Outputs + !IF (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0) THEN + !!IF (p%DoOutput) THEN + ! Frmt = '('//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WriteOutput(I) , I=1,p%NumOuts ) + !END IF + ! + ! ! WAMIT Outputs + !IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN + !!IF (p%WAMIT%DoOutput) THEN + ! Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WAMIT%WriteOutput(I) , I=1,p%WAMIT%NumOuts ) + !END IF + ! + ! ! Morison Outputs + !IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + !!IF (p%Morison%DoOutput) THEN + ! Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%Morison%WriteOutput(I), I=1,p%Morison%NumOuts ) + !END IF + + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return + + ELSE + Decimate = Decimate + 1 + ENDIF + + RETURN + +END SUBROUTINE HDOut_WriteOutputs + +!==================================================================================================== +SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +! NOTE: This routine must be called only after any sub-modules OUT_Init() subroutines have been called. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(ProgDesc), INTENT( IN ) :: HydroDyn_ProgDesc ! + TYPE(HydroDyn_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module + TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(HydroDyn_ParameterType), INTENT( INOUT ) :: p + TYPE(HydroDyn_MiscVarType), INTENT( INOUT ) :: m + TYPE(HydroDyn_InitOutputType), INTENT( INOUT ) :: InitOut + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter + INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array +! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! CHARACTER(200) :: Frmt ! a string to hold a format statement + LOGICAL :: hasWAMITOuts ! Are there any WAMIT-related outputs + LOGICAL :: hasWAMIT2Outs ! Are there any WAMIT-related outputs + LOGICAL :: hasWaves2Outs ! Are there any WAMIT-related outputs + LOGICAL :: hasMorisonOuts ! Are there any Morison-related outputs + + + + + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrMsg = "" + + + + + !------------------------------------------------------------------------------------------------- + ! Check that the variables in OutList are valid + !------------------------------------------------------------------------------------------------- + + + CALL HDOUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) RETURN + + + !IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + ! + ! ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for WriteOutput array.' + ! ErrStat = ErrID_Fatal + ! RETURN + ! END IF + ! y%WriteOutput = 0.0_ReKi + ! + ! ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ! ErrStat = ErrID_Fatal + ! RETURN + ! END IF + ! + ! ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ! ErrStat = ErrID_Fatal + ! RETURN + ! END IF + ! + ! DO I = 1,p%NumOuts + ! + ! InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + ! InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + ! + ! END DO + ! + ! END IF ! there are any requested outputs + + + + ! Aggregate the sub-module initialization outputs for the glue code + !IF ( p%OutSwtch == 2 .OR. p%OutSwtch == 3 ) THEN + + hasWAMITOuts = .FALSE. + hasWAMIT2Outs = .FALSE. + hasWaves2Outs = .FALSE. + hasMorisonOuts = .FALSE. + p%NumTotalOuts = p%NumOuts + m%LastOutTime = 0.0_DbKi + m%Decimate = 0 + p%OutDec = 1 !TODO: Remove this once the parameter has been added to the HD input file GJH 7/8/2014 + + IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN + hasWAMITOuts = .TRUE. + p%NumTotalOuts = p%NumTotalOuts + p%WAMIT%NumOuts + END IF + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN + hasWAMIT2Outs = .TRUE. + p%NumTotalOuts = p%NumTotalOuts + p%WAMIT2%NumOuts + END IF + IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN + hasWaves2Outs = .TRUE. + p%NumTotalOuts = p%NumTotalOuts + p%Waves2%NumOuts + END IF + IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + hasMorisonOuts = .TRUE. + p%NumTotalOuts = p%NumTotalOuts + p%Morison%NumOuts + END IF + + ! Allocate the aggregate arrays + + ALLOCATE ( InitOut%WriteOutputHdr ( p%NumTotalOuts ) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt ( p%NumTotalOuts ) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the WriteOutputUnt array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( y%WriteOutput ( p%NumTotalOuts ) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + y%WriteOutput = 0.0_ReKi ! bjj added this only so the Intel Inspector wouldn't complain about uninitialized memory access (was harmless) + + + ! Initialize the HD-level Hdr and Unt elements + DO I = 1,p%NumOuts + + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + + END DO + + + J = p%NumOuts + 1 + + IF ( hasWAMITOuts ) THEN + DO I=1, p%WAMIT%NumOuts + InitOut%WriteOutputHdr(J) = InitOut%WAMIT%WriteOutputHdr(I) + InitOut%WriteOutputUnt(J) = InitOut%WAMIT%WriteOutputUnt(I) + J = J + 1 + END DO + END IF + + IF ( hasWaves2Outs ) THEN + DO I=1, p%Waves2%NumOuts + InitOut%WriteOutputHdr(J) = InitOut%Waves2%WriteOutputHdr(I) + InitOut%WriteOutputUnt(J) = InitOut%Waves2%WriteOutputUnt(I) + J = J + 1 + END DO + END IF + + IF ( hasWAMIT2Outs ) THEN + DO I=1, p%WAMIT2%NumOuts + InitOut%WriteOutputHdr(J) = InitOut%WAMIT2%WriteOutputHdr(I) + InitOut%WriteOutputUnt(J) = InitOut%WAMIT2%WriteOutputUnt(I) + J = J + 1 + END DO + END IF + + IF ( hasMorisonOuts ) THEN + DO I=1, p%Morison%NumOuts + InitOut%WriteOutputHdr(J) = InitOut%Morison%WriteOutputHdr(I) + InitOut%WriteOutputUnt(J) = InitOut%Morison%WriteOutputUnt(I) + J = J + 1 + END DO + END IF + + !END IF + + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL HDOut_OpenOutput( HydroDyn_ProgDesc, InitInp%OutRootName, p, InitOut, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) RETURN + END IF + + + + RETURN + +END SUBROUTINE HDOUT_Init + +!==================================================================================================== +SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(ProgDesc) , INTENT( IN ) :: HydroDyn_ProgDesc + CHARACTER(1024), INTENT( IN ) :: OutRootName ! Root name for the output file + TYPE(HydroDyn_ParameterType), INTENT( INOUT ) :: p + TYPE(HydroDyn_InitOutPutType ),INTENT( IN ) :: InitOut ! + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter +! INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array + CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. + CHARACTER(200) :: Frmt ! a string to hold a format statement + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + + + + !------------------------------------------------------------------------------------------------- + ! Open the output file, if necessary, and write the header + !------------------------------------------------------------------------------------------------- + p%UnOutFile = -1 + IF ( (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) .OR. & + (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0 ) .OR. & + (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0 ) .OR. & + (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0 ) .OR. & + (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0 ) ) THEN ! Output has been requested so let's open an output file + + ! Open the file for output + OutFileName = TRIM(OutRootName)//'.HD.out' + CALL GetNewUnit( p%UnOutFile ) + + CALL OpenFOutFile ( p%UnOutFile, OutFileName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + ! Write the output file header + + WRITE (p%UnOutFile,'(/,A/)', IOSTAT=ErrStat) 'These predictions were generated by '//TRIM(HydroDyn_ProgDesc%Name)//& + ' on '//CurDate()//' at '//CurTime()//'.' + + ! Write three empty lines + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) + + ! Write the names of the output parameters: + Frmt = '(A8)' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') TRIM( 'Time' ) + + IF (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) + END IF + + IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT%WriteOutputHdr(I) ), I=1,p%WAMIT%NumOuts ) + END IF + + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputHdr(I) ), I=1,p%WAMIT2%NumOuts ) + END IF + + IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%Waves2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Waves2%WriteOutputHdr(I) ), I=1,p%Waves2%NumOuts ) + END IF + + IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputHdr(I) ), I=1,p%Morison%NumOuts ) + END IF + + + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return + + + ! Write the units of the output parameters: + + + Frmt = '(A8)' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') TRIM( '(sec)' ) + + IF (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) + END IF + + IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT%WriteOutputUnt(I) ), I=1,p%WAMIT%NumOuts ) + END IF + + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputUnt(I) ), I=1,p%WAMIT2%NumOuts ) + END IF + + IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%Waves2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Waves2%WriteOutputUnt(I) ), I=1,p%Waves2%NumOuts ) + END IF + + IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputUnt(I) ), I=1,p%Morison%NumOuts ) + END IF + + + + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return + + + + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE HDOut_OpenOutput + +!==================================================================================================== +FUNCTION HDOut_GetChannels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if they +! below to the list of available Morison channels. + +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + CHARACTER(ChanLen), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. + LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER HDOut_GetChannels ! The number of channels found in this module + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. + INTEGER :: count ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + LOGICAL :: CheckOutListAgain + LOGICAL :: newFoundMask (NUserOutputs) ! A mask indicating whether a user requested channel belongs to a module's output channels. + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + HDOut_GetChannels = 0 + + newFoundMask = .FALSE. + + DO I = 1,NUserOutputs + IF (.NOT. foundMask(I) ) THEN + OutListTmp = UserOutputs(I) + + CheckOutListAgain = .FALSE. + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + newFoundMask(I) = .TRUE. + foundMask(I) = .TRUE. + HDOut_GetChannels = HDOut_GetChannels + 1 + + !ELSE + ! foundMask(I) = .FALSE. + END IF + END IF +END DO + +IF ( HDOut_GetChannels > 0 ) THEN + + count = 1 + ! Test that num channels does not exceed max possible channels due to size of OutList + !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutList array in the GetHydroDynChannels function.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,NUserOutputs + IF ( newFoundMask(I) ) THEN + OutList(count) = UserOutputs(I) + count = count + 1 + END IF + + END DO + +END IF + +END FUNCTION HDOut_GetChannels + +!==================================================================================================== +SUBROUTINE HDOut_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! Note that the HydroDyn module must be initialized prior to calling this function (if it +! is being used) so that it can correctly determine if the Lines outputs are valid. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(HydroDyn_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the HD module +! INTEGER, INTENT(IN ) :: NumMemberNodes(*) ! the number of nodes on each of the first 9 members + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. +! INTEGER :: J ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + LOGICAL :: InvalidOutput(MaxHDOutputs) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat ) + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "Error allocating memory for the HydroDyn OutParam array." + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = "" + ENDIF + + InvalidOutput = .FALSE. + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = 1 ! pick any valid channel + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + ErrStat = ErrID_Warn + ErrMsg = p%OutParam(I)%Name//" is not an available output channel. "//TRIM(ErrMsg) + END IF + + END DO + + RETURN + +END SUBROUTINE HDOut_ChkOutLst + + +!==================================================================================================== +SUBROUTINE HDOut_CloseOutput ( p, ErrStat, ErrMsg ) +! This function cleans up after running the HydroDyn output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(HydroDyn_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the HydroDyn module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrMsg = "" + + Err = .FALSE. + + ! Write the summary file header + IF ( p%UnOutFile > -1 ) THEN + ! WRITE (p%UnOutFile,'(/,A/)', IOSTAT=ErrStat) 'This output file was closed on '//CurDate()//' at '//CurTime()//'.' + + !------------------------------------------------------------------------------------------------- + ! Close our output file + !------------------------------------------------------------------------------------------------- + CLOSE( p%UnOutFile, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + END IF + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error closing HydroDyn output file.' + END IF + + RETURN + +END SUBROUTINE HDOut_CloseOutput +!==================================================================================================== + + +!==================================================================================================== +END MODULE HydroDyn_Output diff --git a/OpenFAST/modules/hydrodyn/src/HydroDyn_Types.f90 b/OpenFAST/modules/hydrodyn/src/HydroDyn_Types.f90 new file mode 100644 index 000000000..1b6b52b75 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -0,0 +1,8405 @@ +!STARTOFREGISTRYGENERATEDFILE 'HydroDyn_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 +!********************************************************************************************************************************* +! HydroDyn_Types +!................................................................................................................................. +! This file is part of HydroDyn. +! +! 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 HydroDyn. 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 HydroDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE Current_Types +USE Waves_Types +USE Waves2_Types +USE Conv_Radiation_Types +USE SS_Radiation_Types +USE SS_Excitation_Types +USE WAMIT_Types +USE WAMIT2_Types +USE Morison_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxHDOutputs = 54 ! The maximum number of output channels supported by this module [-] +! ========= HydroDyn_InitInputType ======= + TYPE, PUBLIC :: HydroDyn_InitInputType + CHARACTER(1024) :: InputFile !< Supplied by Driver: full path and filename for the HydroDyn module [-] + LOGICAL :: UseInputFile !< Supplied by Driver: .TRUE. if using a input file, .FALSE. if all inputs are being passed in by the caller [-] + CHARACTER(1024) :: OutRootName !< Supplied by Driver: The name of the root file (without extension) including the full path [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + REAL(DbKi) :: DT !< Supplied by Driver: Simulation time step [(sec)] + REAL(ReKi) :: Gravity !< Supplied by Driver: Gravitational acceleration [(m/s^2)] + REAL(DbKi) :: TMax !< Supplied by Driver: The total simulation time [(sec)] + LOGICAL :: HasIce !< Supplied by Driver: Whether this simulation has ice loading (flag) [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< Supplied by Driver: X-Y locations for WaveElevation output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number. [m,-] + REAL(ReKi) :: PtfmLocationX !< Supplied by Driver: X coordinate of platform location in the wave field [m] + REAL(ReKi) :: PtfmLocationY !< Supplied by Driver: Y coordinate of platform location in the wave field [m] + CHARACTER(80) :: PtfmSgFChr !< Platform horizontal surge translation force (flag) or DEFAULT [-] + LOGICAL :: PtfmSgF !< Optionally Supplied by Driver: Platform horizontal surge translation force (flag) [-] + CHARACTER(80) :: PtfmSwFChr !< Platform horizontal sway translation force (flag) or DEFAULT [-] + LOGICAL :: PtfmSwF !< Optionally Supplied by Driver: Platform horizontal sway translation force (flag) [-] + CHARACTER(80) :: PtfmHvFChr !< Platform vertical heave translation force (flag) or DEFAULT [-] + LOGICAL :: PtfmHvF !< Optionally Supplied by Driver: Platform vertical heave translation force (flag) [-] + CHARACTER(80) :: PtfmRFChr !< Platform roll tilt rotation force (flag) or DEFAULT [-] + LOGICAL :: PtfmRF !< Optionally Supplied by Driver: Platform roll tilt rotation force (flag) [-] + CHARACTER(80) :: PtfmPFChr !< Platform pitch tilt rotation force (flag) or DEFAULT [-] + LOGICAL :: PtfmPF !< Optionally Supplied by Driver: Platform pitch tilt rotation force (flag) [-] + CHARACTER(80) :: PtfmYFChr !< Platform yaw rotation force (flag) or DEFAULT [-] + LOGICAL :: PtfmYF !< Optionally Supplied by Driver: Platform yaw rotation force (flag) [-] + REAL(ReKi) , DIMENSION(1:6) :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddCLin !< Additional stiffness matrix [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBLin !< Additional linear damping matrix [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBQuad !< Additional quadratic damping (drag) matrix [-] + TYPE(Waves_InitInputType) :: Waves !< Initialization data for Waves module [-] + TYPE(Waves2_InitInputType) :: Waves2 !< Initialization data for Waves module [-] + TYPE(Current_InitInputType) :: Current !< Initialization data for Current module [-] + CHARACTER(1024) :: PotFile !< The name of the root potential flow file (without extension for WAMIT, complete name for FIT) [-] + TYPE(WAMIT_InitInputType) :: WAMIT !< Initialization data for WAMIT module [-] + TYPE(WAMIT2_InitInputType) :: WAMIT2 !< Initialization data for WAMIT2 module [-] + TYPE(Morison_InitInputType) :: Morison !< Initialization data for Morison module [-] + LOGICAL :: Echo !< Echo the input files to a file with the same name as the input but with a .echo extension [T/F] [-] + INTEGER(IntKi) :: PotMod !< 1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model [-] + INTEGER(IntKi) :: NUserOutputs !< Number of Hydrodyn-level requested output channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: UserOutputs !< This should really be dimensioned with MaxOutPts [-] + INTEGER(IntKi) :: OutSwtch !< Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files] [-] + LOGICAL :: OutAll !< Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F] [-] + INTEGER(IntKi) :: NumOuts !< The number of outputs for this module as requested in the input file [-] + CHARACTER(ChanLen) , DIMENSION(1:54) :: OutList !< The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts [-] + LOGICAL :: HDSum !< Generate a HydroDyn summary file [T/F] [-] + INTEGER(IntKi) :: UnSum !< File unit for the HydroDyn summary file [-1 = no summary file] [-] + CHARACTER(20) :: OutFmt !< Output format for numerical results [-] + CHARACTER(20) :: OutSFmt !< Output format for header strings [-] + END TYPE HydroDyn_InitInputType +! ======================= +! ========= HydroDyn_InitOutputType ======= + TYPE, PUBLIC :: HydroDyn_InitOutputType + TYPE(WAMIT_InitOutputType) :: WAMIT !< Initialization output from the WAMIT module [-] + TYPE(WAMIT2_InitOutputType) :: WAMIT2 !< Initialization output from the WAMIT2 module [-] + TYPE(Waves2_InitOutputType) :: Waves2 !< Initialization output from the Waves2 module [-] + TYPE(Morison_InitOutputType) :: Morison !< Initialization output from the Morison module [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all HD-related output channel header strings (includes all sub-module channels) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< The is the list of all HD-related output channel unit strings (includes all sub-module channels) [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevSeries !< Wave elevation time-series at each of the points given by WaveElevXY. First dimension is the timestep. Second dimension is XY point number corresponding to second dimension of WaveElevXY. [(m)] + TYPE(ProgDesc) :: Ver !< Version of HydroDyn [-] + REAL(ReKi) :: WtrDens !< Water density [(kg/m^3)] + REAL(ReKi) :: WtrDpth !< Water depth [(m)] + REAL(ReKi) :: MSL2SWL !< Offset between still-water level and mean sea level [(m)] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + END TYPE HydroDyn_InitOutputType +! ======================= +! ========= HD_ModuleMapType ======= + TYPE, PUBLIC :: HD_ModuleMapType + TYPE(MeshMapType) :: HD_P_2_WRP_P + TYPE(MeshMapType) :: M_P_2_WRP_P + TYPE(MeshMapType) :: M_L_2_WRP_P + END TYPE HD_ModuleMapType +! ======================= +! ========= HydroDyn_ContinuousStateType ======= + TYPE, PUBLIC :: HydroDyn_ContinuousStateType + TYPE(WAMIT_ContinuousStateType) :: WAMIT !< continuous states from the wamit module [-] + TYPE(WAMIT2_ContinuousStateType) :: WAMIT2 !< continuous states from the wamit2 module [-] + TYPE(Waves2_ContinuousStateType) :: Waves2 !< continuous states from the waves2 module [-] + TYPE(Morison_ContinuousStateType) :: Morison !< continuous states from the Morison module [-] + END TYPE HydroDyn_ContinuousStateType +! ======================= +! ========= HydroDyn_DiscreteStateType ======= + TYPE, PUBLIC :: HydroDyn_DiscreteStateType + TYPE(WAMIT_DiscreteStateType) :: WAMIT !< discrete states from the wamit module [-] + TYPE(WAMIT2_DiscreteStateType) :: WAMIT2 !< discrete states from the wamit2 module [-] + TYPE(Waves2_DiscreteStateType) :: Waves2 !< discrete states from the waves2 module [-] + TYPE(Morison_DiscreteStateType) :: Morison !< discrete states from the Morison module [-] + END TYPE HydroDyn_DiscreteStateType +! ======================= +! ========= HydroDyn_ConstraintStateType ======= + TYPE, PUBLIC :: HydroDyn_ConstraintStateType + TYPE(WAMIT_ConstraintStateType) :: WAMIT !< constraint states from WAMIT (may be empty) [-] + TYPE(WAMIT2_ConstraintStateType) :: WAMIT2 !< constraint states from WAMIT2 (may be empty) [-] + TYPE(Waves2_ConstraintStateType) :: Waves2 !< constraint states from the waves2 module [-] + TYPE(Morison_ConstraintStateType) :: Morison !< constraint states from the Morison module [-] + END TYPE HydroDyn_ConstraintStateType +! ======================= +! ========= HydroDyn_OtherStateType ======= + TYPE, PUBLIC :: HydroDyn_OtherStateType + TYPE(WAMIT_OtherStateType) :: WAMIT !< OtherState information from the WAMIT module [-] + TYPE(WAMIT2_OtherStateType) :: WAMIT2 !< OtherState information from the WAMIT2 module [-] + TYPE(Waves2_OtherStateType) :: Waves2 !< OtherState information from the Waves2 module [-] + TYPE(Morison_OtherStateType) :: Morison !< OtherState information from the Morison module [-] + END TYPE HydroDyn_OtherStateType +! ======================= +! ========= HydroDyn_MiscVarType ======= + TYPE, PUBLIC :: HydroDyn_MiscVarType + TYPE(MeshType) :: y_mapped !< An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(MeshType) :: AllHdroOrigin_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(MeshType) :: MrsnLumpedMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(MeshType) :: MrsnDistribMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(HD_ModuleMapType) :: HD_MeshMap + INTEGER(IntKi) :: Decimate !< The output decimation counter [-] + REAL(DbKi) :: LastOutTime !< Last time step which was written to the output file (sec) [-] + INTEGER(IntKi) :: LastIndWave !< The last index used in the wave kinematics arrays, used to optimize interpolation [-] + REAL(ReKi) , DIMENSION(1:6) :: F_PtfmAdd !< The total forces and moments due to additional pre-load, stiffness, and damping [-] + REAL(ReKi) , DIMENSION(1:6) :: F_Hydro !< The total hydrodynamic forces and moments integrated about the WAMIT reference point [-] + REAL(ReKi) , DIMENSION(1:6) :: F_Waves !< The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules) [-] + TYPE(WAMIT_MiscVarType) :: WAMIT !< misc var information from the WAMIT module [-] + TYPE(WAMIT2_MiscVarType) :: WAMIT2 !< misc var information from the WAMIT2 module [-] + TYPE(Waves2_MiscVarType) :: Waves2 !< misc var information from the Waves2 module [-] + TYPE(Morison_MiscVarType) :: Morison !< misc var information from the Morison module [-] + TYPE(WAMIT_InputType) :: u_WAMIT !< WAMIT module inputs [-] + TYPE(WAMIT2_InputType) :: u_WAMIT2 !< WAMIT2 module inputs [-] + TYPE(Waves2_InputType) :: u_Waves2 !< Waves2 module inputs [-] + END TYPE HydroDyn_MiscVarType +! ======================= +! ========= HydroDyn_ParameterType ======= + TYPE, PUBLIC :: HydroDyn_ParameterType + TYPE(WAMIT_ParameterType) :: WAMIT !< Parameter data for the WAMIT module [-] + TYPE(WAMIT2_ParameterType) :: WAMIT2 !< Parameter data for the WAMIT2 module [-] + TYPE(Waves2_ParameterType) :: Waves2 !< Parameter data for the Waves2 module [-] + TYPE(Morison_ParameterType) :: Morison !< Parameter data for the Morison module [-] + INTEGER(IntKi) :: PotMod !< 1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Array of time samples, (sec) [-] + INTEGER(IntKi) :: NStepWave !< Number of data points in the wave kinematics arrays [-] + INTEGER(IntKi) :: NWaveElev !< Number of wave elevation outputs [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< Total wave elevation [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev1 !< First order wave elevation [-] + REAL(ReKi) :: WtrDpth !< Water depth [(m)] + REAL(ReKi) , DIMENSION(1:6) :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddCLin !< Additional stiffness matrix [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBLin !< Additional linear damping matrix [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBQuad !< Additional quadratic damping (drag) matrix [-] + REAL(DbKi) :: DT !< Time step in seconds for integration of continuous states (if a fixed-step integrator is used) and update of discrete states [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] + INTEGER(IntKi) :: NumOuts !< Number of HydroDyn module-level outputs (not the total number including sub-modules [-] + INTEGER(IntKi) :: NumTotalOuts !< Number of all requested outputs including sub-modules [-] + INTEGER(IntKi) :: OutSwtch !< Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files] [-] + CHARACTER(20) :: OutFmt !< Output format for numerical results [-] + CHARACTER(20) :: OutSFmt !< Output format for header strings [-] + CHARACTER(ChanLen) :: Delim !< Delimiter string for outputs, defaults to tab-delimiters [-] + INTEGER(IntKi) :: UnOutFile !< File unit for the HydroDyn outputs [-] + INTEGER(IntKi) :: OutDec !< Write every OutDec time steps [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: dx !< vector that determines size of perturbation for x (continuous states) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-] + END TYPE HydroDyn_ParameterType +! ======================= +! ========= HydroDyn_InputType ======= + TYPE, PUBLIC :: HydroDyn_InputType + TYPE(Morison_InputType) :: Morison !< Morison module inputs [-] + TYPE(MeshType) :: Mesh !< Displacements at the WAMIT reference point in the inertial frame [-] + END TYPE HydroDyn_InputType +! ======================= +! ========= HydroDyn_OutputType ======= + TYPE, PUBLIC :: HydroDyn_OutputType + TYPE(WAMIT_OutputType) :: WAMIT !< WAMIT module outputs [-] + TYPE(WAMIT2_OutputType) :: WAMIT2 !< WAMIT2 module outputs [-] + TYPE(Waves2_OutputType) :: Waves2 !< Waves2 module outputs [-] + TYPE(Morison_OutputType) :: Morison !< Morison module outputs [-] + TYPE(MeshType) :: Mesh !< Point Loads at the WAMIT reference point in the inertial frame [-] + TYPE(MeshType) :: AllHdroOrigin !< All HD-related loads integrated to the origin, (0,0,0) in the inertial frame [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + END TYPE HydroDyn_OutputType +! ======================= +CONTAINS + SUBROUTINE HydroDyn_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(HydroDyn_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 = 'HydroDyn_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%UseInputFile = SrcInitInputData%UseInputFile + DstInitInputData%OutRootName = SrcInitInputData%OutRootName + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%DT = SrcInitInputData%DT + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%TMax = SrcInitInputData%TMax + DstInitInputData%HasIce = SrcInitInputData%HasIce +IF (ALLOCATED(SrcInitInputData%WaveElevXY)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevXY,1) + i1_u = UBOUND(SrcInitInputData%WaveElevXY,1) + i2_l = LBOUND(SrcInitInputData%WaveElevXY,2) + i2_u = UBOUND(SrcInitInputData%WaveElevXY,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevXY)) THEN + ALLOCATE(DstInitInputData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevXY = SrcInitInputData%WaveElevXY +ENDIF + DstInitInputData%PtfmLocationX = SrcInitInputData%PtfmLocationX + DstInitInputData%PtfmLocationY = SrcInitInputData%PtfmLocationY + DstInitInputData%PtfmSgFChr = SrcInitInputData%PtfmSgFChr + DstInitInputData%PtfmSgF = SrcInitInputData%PtfmSgF + DstInitInputData%PtfmSwFChr = SrcInitInputData%PtfmSwFChr + DstInitInputData%PtfmSwF = SrcInitInputData%PtfmSwF + DstInitInputData%PtfmHvFChr = SrcInitInputData%PtfmHvFChr + DstInitInputData%PtfmHvF = SrcInitInputData%PtfmHvF + DstInitInputData%PtfmRFChr = SrcInitInputData%PtfmRFChr + DstInitInputData%PtfmRF = SrcInitInputData%PtfmRF + DstInitInputData%PtfmPFChr = SrcInitInputData%PtfmPFChr + DstInitInputData%PtfmPF = SrcInitInputData%PtfmPF + DstInitInputData%PtfmYFChr = SrcInitInputData%PtfmYFChr + DstInitInputData%PtfmYF = SrcInitInputData%PtfmYF + DstInitInputData%AddF0 = SrcInitInputData%AddF0 + DstInitInputData%AddCLin = SrcInitInputData%AddCLin + DstInitInputData%AddBLin = SrcInitInputData%AddBLin + DstInitInputData%AddBQuad = SrcInitInputData%AddBQuad + CALL Waves_CopyInitInput( SrcInitInputData%Waves, DstInitInputData%Waves, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyInitInput( SrcInitInputData%Waves2, DstInitInputData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Current_CopyInitInput( SrcInitInputData%Current, DstInitInputData%Current, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%PotFile = SrcInitInputData%PotFile + CALL WAMIT_CopyInitInput( SrcInitInputData%WAMIT, DstInitInputData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyInitInput( SrcInitInputData%WAMIT2, DstInitInputData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyInitInput( SrcInitInputData%Morison, DstInitInputData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%Echo = SrcInitInputData%Echo + DstInitInputData%PotMod = SrcInitInputData%PotMod + DstInitInputData%NUserOutputs = SrcInitInputData%NUserOutputs +IF (ALLOCATED(SrcInitInputData%UserOutputs)) THEN + i1_l = LBOUND(SrcInitInputData%UserOutputs,1) + i1_u = UBOUND(SrcInitInputData%UserOutputs,1) + IF (.NOT. ALLOCATED(DstInitInputData%UserOutputs)) THEN + ALLOCATE(DstInitInputData%UserOutputs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%UserOutputs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%UserOutputs = SrcInitInputData%UserOutputs +ENDIF + DstInitInputData%OutSwtch = SrcInitInputData%OutSwtch + DstInitInputData%OutAll = SrcInitInputData%OutAll + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + DstInitInputData%OutList = SrcInitInputData%OutList + DstInitInputData%HDSum = SrcInitInputData%HDSum + DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%OutFmt = SrcInitInputData%OutFmt + DstInitInputData%OutSFmt = SrcInitInputData%OutSFmt + END SUBROUTINE HydroDyn_CopyInitInput + + SUBROUTINE HydroDyn_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(HydroDyn_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveElevXY)) THEN + DEALLOCATE(InitInputData%WaveElevXY) +ENDIF + CALL Waves_DestroyInitInput( InitInputData%Waves, ErrStat, ErrMsg ) + CALL Waves2_DestroyInitInput( InitInputData%Waves2, ErrStat, ErrMsg ) + CALL Current_DestroyInitInput( InitInputData%Current, ErrStat, ErrMsg ) + CALL WAMIT_DestroyInitInput( InitInputData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyInitInput( InitInputData%WAMIT2, ErrStat, ErrMsg ) + CALL Morison_DestroyInitInput( InitInputData%Morison, ErrStat, ErrMsg ) +IF (ALLOCATED(InitInputData%UserOutputs)) THEN + DEALLOCATE(InitInputData%UserOutputs) +ENDIF + END SUBROUTINE HydroDyn_DestroyInitInput + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! UseInputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%OutRootName) ! OutRootName + Int_BufSz = Int_BufSz + 1 ! Linearize + Db_BufSz = Db_BufSz + 1 ! DT + Re_BufSz = Re_BufSz + 1 ! Gravity + Db_BufSz = Db_BufSz + 1 ! TMax + Int_BufSz = Int_BufSz + 1 ! HasIce + Int_BufSz = Int_BufSz + 1 ! WaveElevXY allocated yes/no + IF ( ALLOCATED(InData%WaveElevXY) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevXY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevXY) ! WaveElevXY + END IF + Re_BufSz = Re_BufSz + 1 ! PtfmLocationX + Re_BufSz = Re_BufSz + 1 ! PtfmLocationY + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmSgFChr) ! PtfmSgFChr + Int_BufSz = Int_BufSz + 1 ! PtfmSgF + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmSwFChr) ! PtfmSwFChr + Int_BufSz = Int_BufSz + 1 ! PtfmSwF + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmHvFChr) ! PtfmHvFChr + Int_BufSz = Int_BufSz + 1 ! PtfmHvF + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmRFChr) ! PtfmRFChr + Int_BufSz = Int_BufSz + 1 ! PtfmRF + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmPFChr) ! PtfmPFChr + Int_BufSz = Int_BufSz + 1 ! PtfmPF + Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmYFChr) ! PtfmYFChr + Int_BufSz = Int_BufSz + 1 ! PtfmYF + Re_BufSz = Re_BufSz + SIZE(InData%AddF0) ! AddF0 + Re_BufSz = Re_BufSz + SIZE(InData%AddCLin) ! AddCLin + Re_BufSz = Re_BufSz + SIZE(InData%AddBLin) ! AddBLin + Re_BufSz = Re_BufSz + SIZE(InData%AddBQuad) ! AddBQuad + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Waves: size of buffers for each call to pack subtype + CALL Waves_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Waves, ErrStat2, ErrMsg2, .TRUE. ) ! Waves + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Current: size of buffers for each call to pack subtype + CALL Current_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Current, ErrStat2, ErrMsg2, .TRUE. ) ! Current + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Current + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Current + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Current + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%PotFile) ! PotFile + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Echo + Int_BufSz = Int_BufSz + 1 ! PotMod + Int_BufSz = Int_BufSz + 1 ! NUserOutputs + Int_BufSz = Int_BufSz + 1 ! UserOutputs allocated yes/no + IF ( ALLOCATED(InData%UserOutputs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UserOutputs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%UserOutputs)*LEN(InData%UserOutputs) ! UserOutputs + END IF + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + Int_BufSz = Int_BufSz + 1 ! HDSum + Int_BufSz = Int_BufSz + 1 ! UnSum + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutRootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutRootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TMax + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%HasIce, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElevXY) ) 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%WaveElevXY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevXY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevXY,2), UBOUND(InData%WaveElevXY,2) + DO i1 = LBOUND(InData%WaveElevXY,1), UBOUND(InData%WaveElevXY,1) + ReKiBuf(Re_Xferred) = InData%WaveElevXY(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%PtfmLocationX + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmLocationY + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%PtfmSgFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSgFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%PtfmSwFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSwFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%PtfmHvFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmHvFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%PtfmRFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmRFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%PtfmPFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmPFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%PtfmYFChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmYFChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) + ReKiBuf(Re_Xferred) = InData%AddF0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) + DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) + ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) + DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) + ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) + DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) + ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + CALL Waves_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Waves, ErrStat2, ErrMsg2, OnlySize ) ! Waves + 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 Waves2_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Current_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Current, ErrStat2, ErrMsg2, OnlySize ) ! Current + 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%PotFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%PotFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + CALL WAMIT_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Morison_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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) = TRANSFER(InData%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PotMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NUserOutputs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%UserOutputs) ) 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%UserOutputs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UserOutputs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UserOutputs,1), UBOUND(InData%UserOutputs,1) + DO I = 1, LEN(InData%UserOutputs) + IntKiBuf(Int_Xferred) = ICHAR(InData%UserOutputs(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%HDSum, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE HydroDyn_PackInitInput + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutRootName) + OutData%OutRootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HasIce = TRANSFER(IntKiBuf(Int_Xferred), OutData%HasIce) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevXY 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%WaveElevXY)) DEALLOCATE(OutData%WaveElevXY) + ALLOCATE(OutData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevXY,2), UBOUND(OutData%WaveElevXY,2) + DO i1 = LBOUND(OutData%WaveElevXY,1), UBOUND(OutData%WaveElevXY,1) + OutData%WaveElevXY(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%PtfmLocationX = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmLocationY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%PtfmSgFChr) + OutData%PtfmSgFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmSgF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%PtfmSwFChr) + OutData%PtfmSwFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmSwF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%PtfmHvFChr) + OutData%PtfmHvFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmHvF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%PtfmRFChr) + OutData%PtfmRFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmRF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%PtfmPFChr) + OutData%PtfmPFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmPF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%PtfmYFChr) + OutData%PtfmYFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%PtfmYF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%AddF0,1) + i1_u = UBOUND(OutData%AddF0,1) + DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) + OutData%AddF0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AddCLin,1) + i1_u = UBOUND(OutData%AddCLin,1) + i2_l = LBOUND(OutData%AddCLin,2) + i2_u = UBOUND(OutData%AddCLin,2) + DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) + DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) + OutData%AddCLin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%AddBLin,1) + i1_u = UBOUND(OutData%AddBLin,1) + i2_l = LBOUND(OutData%AddBLin,2) + i2_u = UBOUND(OutData%AddBLin,2) + DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) + DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) + OutData%AddBLin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%AddBQuad,1) + i1_u = UBOUND(OutData%AddBQuad,1) + i2_l = LBOUND(OutData%AddBQuad,2) + i2_u = UBOUND(OutData%AddBQuad,2) + DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) + DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) + OutData%AddBQuad(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 Waves_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%Waves, ErrStat2, ErrMsg2 ) ! Waves + 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 Waves2_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Current_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%Current, ErrStat2, ErrMsg2 ) ! Current + 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%PotFile) + OutData%PotFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 WAMIT_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Morison_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 + OutData%PotMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NUserOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UserOutputs 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%UserOutputs)) DEALLOCATE(OutData%UserOutputs) + ALLOCATE(OutData%UserOutputs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UserOutputs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UserOutputs,1), UBOUND(OutData%UserOutputs,1) + DO I = 1, LEN(OutData%UserOutputs) + OutData%UserOutputs(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%OutList,1) + i1_u = UBOUND(OutData%OutList,1) + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%HDSum = TRANSFER(IntKiBuf(Int_Xferred), OutData%HDSum) + Int_Xferred = Int_Xferred + 1 + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE HydroDyn_UnPackInitInput + + SUBROUTINE HydroDyn_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_InitOutputType), INTENT(INOUT) :: SrcInitOutputData + TYPE(HydroDyn_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) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyInitOutput( SrcInitOutputData%WAMIT, DstInitOutputData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyInitOutput( SrcInitOutputData%WAMIT2, DstInitOutputData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyInitOutput( SrcInitOutputData%Waves2, DstInitOutputData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyInitOutput( SrcInitOutputData%Morison, DstInitOutputData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveElevSeries)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElevSeries,1) + i1_u = UBOUND(SrcInitOutputData%WaveElevSeries,1) + i2_l = LBOUND(SrcInitOutputData%WaveElevSeries,2) + i2_u = UBOUND(SrcInitOutputData%WaveElevSeries,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElevSeries)) THEN + ALLOCATE(DstInitOutputData%WaveElevSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElevSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElevSeries = SrcInitOutputData%WaveElevSeries +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%WtrDens = SrcInitOutputData%WtrDens + DstInitOutputData%WtrDpth = SrcInitOutputData%WtrDpth + DstInitOutputData%MSL2SWL = SrcInitOutputData%MSL2SWL +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF + END SUBROUTINE HydroDyn_CopyInitOutput + + SUBROUTINE HydroDyn_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(HydroDyn_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyInitOutput( InitOutputData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyInitOutput( InitOutputData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyInitOutput( InitOutputData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyInitOutput( InitOutputData%Morison, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF +IF (ALLOCATED(InitOutputData%WaveElevSeries)) THEN + DEALLOCATE(InitOutputData%WaveElevSeries) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF + END SUBROUTINE HydroDyn_DestroyInitOutput + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevSeries allocated yes/no + IF ( ALLOCATED(InData%WaveElevSeries) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevSeries upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevSeries) ! WaveElevSeries + END IF + 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 + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + 1 ! MSL2SWL + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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 WAMIT_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevSeries) ) 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%WaveElevSeries,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevSeries,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevSeries,2), UBOUND(InData%WaveElevSeries,2) + DO i1 = LBOUND(InData%WaveElevSeries,1), UBOUND(InData%WaveElevSeries,1) + ReKiBuf(Re_Xferred) = InData%WaveElevSeries(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + 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 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) 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%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) 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%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE HydroDyn_PackInitOutput + + SUBROUTINE HydroDyn_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(HydroDyn_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) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_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 WAMIT_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevSeries 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%WaveElevSeries)) DEALLOCATE(OutData%WaveElevSeries) + ALLOCATE(OutData%WaveElevSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevSeries,2), UBOUND(OutData%WaveElevSeries,2) + DO i1 = LBOUND(OutData%WaveElevSeries,1), UBOUND(OutData%WaveElevSeries,1) + OutData%WaveElevSeries(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + 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 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%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MSL2SWL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x 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%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x 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%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE HydroDyn_UnPackInitOutput + + SUBROUTINE HydroDyn_CopyHD_ModuleMapType( SrcHD_ModuleMapTypeData, DstHD_ModuleMapTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HD_ModuleMapType), INTENT(INOUT) :: SrcHD_ModuleMapTypeData + TYPE(HD_ModuleMapType), INTENT(INOUT) :: DstHD_ModuleMapTypeData + 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 = 'HydroDyn_CopyHD_ModuleMapType' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%HD_P_2_WRP_P, DstHD_ModuleMapTypeData%HD_P_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_P_2_WRP_P, DstHD_ModuleMapTypeData%M_P_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_L_2_WRP_P, DstHD_ModuleMapTypeData%M_L_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyHD_ModuleMapType + + SUBROUTINE HydroDyn_DestroyHD_ModuleMapType( HD_ModuleMapTypeData, ErrStat, ErrMsg ) + TYPE(HD_ModuleMapType), INTENT(INOUT) :: HD_ModuleMapTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyHD_ModuleMapType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%HD_P_2_WRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_P_2_WRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_L_2_WRP_P, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyHD_ModuleMapType + + SUBROUTINE HydroDyn_PackHD_ModuleMapType( 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(HD_ModuleMapType), 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 = 'HydroDyn_PackHD_ModuleMapType' + ! 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 ! HD_P_2_WRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_P_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_P_2_WRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_P_2_WRP_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_P_2_WRP_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_P_2_WRP_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! M_P_2_WRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_P_2_WRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! M_P_2_WRP_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! M_P_2_WRP_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! M_P_2_WRP_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! M_L_2_WRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_L_2_WRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! M_L_2_WRP_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! M_L_2_WRP_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! M_L_2_WRP_P + 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_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_P_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_P_2_WRP_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_P_2_WRP_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_L_2_WRP_P + 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 HydroDyn_PackHD_ModuleMapType + + SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( 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(HD_ModuleMapType), 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 = 'HydroDyn_UnPackHD_ModuleMapType' + ! 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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_P_2_WRP_P, ErrStat2, ErrMsg2 ) ! HD_P_2_WRP_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_P_2_WRP_P, ErrStat2, ErrMsg2 ) ! M_P_2_WRP_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_L_2_WRP_P, ErrStat2, ErrMsg2 ) ! M_L_2_WRP_P + 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 HydroDyn_UnPackHD_ModuleMapType + + SUBROUTINE HydroDyn_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(HydroDyn_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 = 'HydroDyn_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyContState( SrcContStateData%WAMIT, DstContStateData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyContState( SrcContStateData%WAMIT2, DstContStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyContState( SrcContStateData%Waves2, DstContStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyContState( SrcContStateData%Morison, DstContStateData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyContState + + SUBROUTINE HydroDyn_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(HydroDyn_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyContState( ContStateData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyContState( ContStateData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyContState( ContStateData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyContState( ContStateData%Morison, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyContState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + 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 WAMIT_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 HydroDyn_PackContState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + 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 WAMIT_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 HydroDyn_UnPackContState + + SUBROUTINE HydroDyn_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(HydroDyn_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 = 'HydroDyn_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyDiscState( SrcDiscStateData%WAMIT, DstDiscStateData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyDiscState( SrcDiscStateData%WAMIT2, DstDiscStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyDiscState( SrcDiscStateData%Waves2, DstDiscStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyDiscState( SrcDiscStateData%Morison, DstDiscStateData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyDiscState + + SUBROUTINE HydroDyn_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(HydroDyn_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyDiscState( DiscStateData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyDiscState( DiscStateData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyDiscState( DiscStateData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyDiscState( DiscStateData%Morison, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyDiscState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + 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 WAMIT_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 HydroDyn_PackDiscState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + 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 WAMIT_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 HydroDyn_UnPackDiscState + + SUBROUTINE HydroDyn_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(HydroDyn_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 = 'HydroDyn_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyConstrState( SrcConstrStateData%WAMIT, DstConstrStateData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyConstrState( SrcConstrStateData%WAMIT2, DstConstrStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyConstrState( SrcConstrStateData%Waves2, DstConstrStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyConstrState( SrcConstrStateData%Morison, DstConstrStateData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyConstrState + + SUBROUTINE HydroDyn_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(HydroDyn_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyConstrState( ConstrStateData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyConstrState( ConstrStateData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyConstrState( ConstrStateData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyConstrState( ConstrStateData%Morison, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyConstrState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + 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 WAMIT_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 HydroDyn_PackConstrState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + 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 WAMIT_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 HydroDyn_UnPackConstrState + + SUBROUTINE HydroDyn_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(HydroDyn_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 = 'HydroDyn_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyOtherState( SrcOtherStateData%WAMIT, DstOtherStateData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyOtherState( SrcOtherStateData%WAMIT2, DstOtherStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyOtherState( SrcOtherStateData%Waves2, DstOtherStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyOtherState( SrcOtherStateData%Morison, DstOtherStateData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyOtherState + + SUBROUTINE HydroDyn_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(HydroDyn_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyOtherState( OtherStateData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyOtherState( OtherStateData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyOtherState( OtherStateData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyOtherState( OtherStateData%Morison, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyOtherState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + 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 WAMIT_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 HydroDyn_PackOtherState + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + 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 WAMIT_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 HydroDyn_UnPackOtherState + + SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: SrcMiscData + TYPE(HydroDyn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcMiscData%y_mapped, DstMiscData%y_mapped, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcMiscData%AllHdroOrigin_position, DstMiscData%AllHdroOrigin_position, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcMiscData%MrsnLumpedMesh_position, DstMiscData%MrsnLumpedMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcMiscData%MrsnDistribMesh_position, DstMiscData%MrsnDistribMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_Copyhd_modulemaptype( SrcMiscData%HD_MeshMap, DstMiscData%HD_MeshMap, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%Decimate = SrcMiscData%Decimate + DstMiscData%LastOutTime = SrcMiscData%LastOutTime + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + DstMiscData%F_PtfmAdd = SrcMiscData%F_PtfmAdd + DstMiscData%F_Hydro = SrcMiscData%F_Hydro + DstMiscData%F_Waves = SrcMiscData%F_Waves + CALL WAMIT_CopyMisc( SrcMiscData%WAMIT, DstMiscData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyMisc( SrcMiscData%WAMIT2, DstMiscData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyMisc( SrcMiscData%Waves2, DstMiscData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyMisc( SrcMiscData%Morison, DstMiscData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT_CopyInput( SrcMiscData%u_WAMIT, DstMiscData%u_WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyInput( SrcMiscData%u_WAMIT2, DstMiscData%u_WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyInput( SrcMiscData%u_Waves2, DstMiscData%u_Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyMisc + + SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( MiscData%y_mapped, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%AllHdroOrigin_position, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%MrsnLumpedMesh_position, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%MrsnDistribMesh_position, ErrStat, ErrMsg ) + CALL HydroDyn_Destroyhd_modulemaptype( MiscData%HD_MeshMap, ErrStat, ErrMsg ) + CALL WAMIT_DestroyMisc( MiscData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyMisc( MiscData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyMisc( MiscData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyMisc( MiscData%Morison, ErrStat, ErrMsg ) + CALL WAMIT_DestroyInput( MiscData%u_WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyInput( MiscData%u_WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyInput( MiscData%u_Waves2, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyMisc + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! y_mapped: size of buffers for each call to pack subtype + CALL MeshPack( InData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! y_mapped + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_mapped + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_mapped + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_mapped + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AllHdroOrigin_position: size of buffers for each call to pack subtype + CALL MeshPack( InData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! AllHdroOrigin_position + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AllHdroOrigin_position + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AllHdroOrigin_position + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AllHdroOrigin_position + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! MrsnLumpedMesh_position: size of buffers for each call to pack subtype + CALL MeshPack( InData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnLumpedMesh_position + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MrsnLumpedMesh_position + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MrsnLumpedMesh_position + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MrsnLumpedMesh_position + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! MrsnDistribMesh_position: size of buffers for each call to pack subtype + CALL MeshPack( InData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnDistribMesh_position + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MrsnDistribMesh_position + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MrsnDistribMesh_position + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MrsnDistribMesh_position + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_MeshMap: size of buffers for each call to pack subtype + CALL HydroDyn_Packhd_modulemaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_MeshMap, ErrStat2, ErrMsg2, .TRUE. ) ! HD_MeshMap + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_MeshMap + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_MeshMap + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_MeshMap + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Decimate + Db_BufSz = Db_BufSz + 1 ! LastOutTime + Int_BufSz = Int_BufSz + 1 ! LastIndWave + Re_BufSz = Re_BufSz + SIZE(InData%F_PtfmAdd) ! F_PtfmAdd + Re_BufSz = Re_BufSz + SIZE(InData%F_Hydro) ! F_Hydro + Re_BufSz = Re_BufSz + SIZE(InData%F_Waves) ! F_Waves + Int_BufSz = Int_BufSz + 3 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! u_WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! u_WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! u_Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_Waves2 + 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 MeshPack( InData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! y_mapped + 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 MeshPack( InData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! AllHdroOrigin_position + 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 MeshPack( InData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! MrsnLumpedMesh_position + 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 MeshPack( InData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! MrsnDistribMesh_position + 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 HydroDyn_Packhd_modulemaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_MeshMap, ErrStat2, ErrMsg2, OnlySize ) ! HD_MeshMap + 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%Decimate + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%LastOutTime + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%LastIndWave + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%F_PtfmAdd,1), UBOUND(InData%F_PtfmAdd,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAdd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_Hydro,1), UBOUND(InData%F_Hydro,1) + ReKiBuf(Re_Xferred) = InData%F_Hydro(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_Waves,1), UBOUND(InData%F_Waves,1) + ReKiBuf(Re_Xferred) = InData%F_Waves(i1) + Re_Xferred = Re_Xferred + 1 + END DO + CALL WAMIT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 WAMIT_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! u_WAMIT + 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 WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! u_WAMIT2 + 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 Waves2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Waves2, ErrStat2, ErrMsg2, OnlySize ) ! u_Waves2 + 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 HydroDyn_PackMisc + + SUBROUTINE HydroDyn_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(HydroDyn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_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 + 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 MeshUnpack( OutData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! y_mapped + 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 MeshUnpack( OutData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! AllHdroOrigin_position + 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 MeshUnpack( OutData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! MrsnLumpedMesh_position + 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 MeshUnpack( OutData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! MrsnDistribMesh_position + 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 HydroDyn_Unpackhd_modulemaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_MeshMap, ErrStat2, ErrMsg2 ) ! HD_MeshMap + 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%Decimate = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%LastOutTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%F_PtfmAdd,1) + i1_u = UBOUND(OutData%F_PtfmAdd,1) + DO i1 = LBOUND(OutData%F_PtfmAdd,1), UBOUND(OutData%F_PtfmAdd,1) + OutData%F_PtfmAdd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_Hydro,1) + i1_u = UBOUND(OutData%F_Hydro,1) + DO i1 = LBOUND(OutData%F_Hydro,1), UBOUND(OutData%F_Hydro,1) + OutData%F_Hydro(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_Waves,1) + i1_u = UBOUND(OutData%F_Waves,1) + DO i1 = LBOUND(OutData%F_Waves,1), UBOUND(OutData%F_Waves,1) + OutData%F_Waves(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 WAMIT_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 WAMIT_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_WAMIT, ErrStat2, ErrMsg2 ) ! u_WAMIT + 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 WAMIT2_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_WAMIT2, ErrStat2, ErrMsg2 ) ! u_WAMIT2 + 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 Waves2_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_Waves2, ErrStat2, ErrMsg2 ) ! u_Waves2 + 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 HydroDyn_UnPackMisc + + SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_ParameterType), INTENT(IN) :: SrcParamData + TYPE(HydroDyn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyParam( SrcParamData%WAMIT, DstParamData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyParam( SrcParamData%WAMIT2, DstParamData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyParam( SrcParamData%Waves2, DstParamData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyParam( SrcParamData%Morison, DstParamData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%PotMod = SrcParamData%PotMod +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%NWaveElev = SrcParamData%NWaveElev +IF (ALLOCATED(SrcParamData%WaveElev)) THEN + i1_l = LBOUND(SrcParamData%WaveElev,1) + i1_u = UBOUND(SrcParamData%WaveElev,1) + i2_l = LBOUND(SrcParamData%WaveElev,2) + i2_u = UBOUND(SrcParamData%WaveElev,2) + IF (.NOT. ALLOCATED(DstParamData%WaveElev)) THEN + ALLOCATE(DstParamData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev = SrcParamData%WaveElev +ENDIF +IF (ALLOCATED(SrcParamData%WaveElev1)) THEN + i1_l = LBOUND(SrcParamData%WaveElev1,1) + i1_u = UBOUND(SrcParamData%WaveElev1,1) + i2_l = LBOUND(SrcParamData%WaveElev1,2) + i2_u = UBOUND(SrcParamData%WaveElev1,2) + IF (.NOT. ALLOCATED(DstParamData%WaveElev1)) THEN + ALLOCATE(DstParamData%WaveElev1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev1 = SrcParamData%WaveElev1 +ENDIF + DstParamData%WtrDpth = SrcParamData%WtrDpth + DstParamData%AddF0 = SrcParamData%AddF0 + DstParamData%AddCLin = SrcParamData%AddCLin + DstParamData%AddBLin = SrcParamData%AddBLin + DstParamData%AddBQuad = SrcParamData%AddBQuad + DstParamData%DT = SrcParamData%DT +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumTotalOuts = SrcParamData%NumTotalOuts + DstParamData%OutSwtch = SrcParamData%OutSwtch + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + DstParamData%UnOutFile = SrcParamData%UnOutFile + DstParamData%OutDec = SrcParamData%OutDec +IF (ALLOCATED(SrcParamData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcParamData%Jac_u_indx,1) + i1_u = UBOUND(SrcParamData%Jac_u_indx,1) + i2_l = LBOUND(SrcParamData%Jac_u_indx,2) + i2_u = UBOUND(SrcParamData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstParamData%Jac_u_indx)) THEN + ALLOCATE(DstParamData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jac_u_indx = SrcParamData%Jac_u_indx +ENDIF +IF (ALLOCATED(SrcParamData%du)) THEN + i1_l = LBOUND(SrcParamData%du,1) + i1_u = UBOUND(SrcParamData%du,1) + IF (.NOT. ALLOCATED(DstParamData%du)) THEN + ALLOCATE(DstParamData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%du = SrcParamData%du +ENDIF +IF (ALLOCATED(SrcParamData%dx)) THEN + i1_l = LBOUND(SrcParamData%dx,1) + i1_u = UBOUND(SrcParamData%dx,1) + IF (.NOT. ALLOCATED(DstParamData%dx)) THEN + ALLOCATE(DstParamData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%dx = SrcParamData%dx +ENDIF + DstParamData%Jac_ny = SrcParamData%Jac_ny + END SUBROUTINE HydroDyn_CopyParam + + SUBROUTINE HydroDyn_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(HydroDyn_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyParam( ParamData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyParam( ParamData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyParam( ParamData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyParam( ParamData%Morison, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF +IF (ALLOCATED(ParamData%WaveElev)) THEN + DEALLOCATE(ParamData%WaveElev) +ENDIF +IF (ALLOCATED(ParamData%WaveElev1)) THEN + DEALLOCATE(ParamData%WaveElev1) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%Jac_u_indx)) THEN + DEALLOCATE(ParamData%Jac_u_indx) +ENDIF +IF (ALLOCATED(ParamData%du)) THEN + DEALLOCATE(ParamData%du) +ENDIF +IF (ALLOCATED(ParamData%dx)) THEN + DEALLOCATE(ParamData%dx) +ENDIF + END SUBROUTINE HydroDyn_DestroyParam + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! PotMod + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NWaveElev + Int_BufSz = Int_BufSz + 1 ! WaveElev allocated yes/no + IF ( ALLOCATED(InData%WaveElev) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev) ! WaveElev + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev1 allocated yes/no + IF ( ALLOCATED(InData%WaveElev1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev1) ! WaveElev1 + END IF + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + SIZE(InData%AddF0) ! AddF0 + Re_BufSz = Re_BufSz + SIZE(InData%AddCLin) ! AddCLin + Re_BufSz = Re_BufSz + SIZE(InData%AddBLin) ! AddBLin + Re_BufSz = Re_BufSz + SIZE(InData%AddBQuad) ! AddBQuad + Db_BufSz = Db_BufSz + 1 ! DT + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumTotalOuts + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UnOutFile + Int_BufSz = Int_BufSz + 1 ! OutDec + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 1 ! du allocated yes/no + IF ( ALLOCATED(InData%du) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! du upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%du) ! du + END IF + Int_BufSz = Int_BufSz + 1 ! dx allocated yes/no + IF ( ALLOCATED(InData%dx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dx upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%dx) ! dx + END IF + Int_BufSz = Int_BufSz + 1 ! Jac_ny + 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 WAMIT_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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%PotMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NWaveElev + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElev) ) 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%WaveElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev,2), UBOUND(InData%WaveElev,2) + DO i1 = LBOUND(InData%WaveElev,1), UBOUND(InData%WaveElev,1) + ReKiBuf(Re_Xferred) = InData%WaveElev(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev1) ) 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%WaveElev1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev1,2), UBOUND(InData%WaveElev1,2) + DO i1 = LBOUND(InData%WaveElev1,1), UBOUND(InData%WaveElev1,1) + ReKiBuf(Re_Xferred) = InData%WaveElev1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) + ReKiBuf(Re_Xferred) = InData%AddF0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) + DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) + ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) + DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) + ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) + DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) + ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_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 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumTotalOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutDec + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%du) ) 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%du,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%du,1), UBOUND(InData%du,1) + DbKiBuf(Db_Xferred) = InData%du(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dx) ) 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%dx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dx,1), UBOUND(InData%dx,1) + DbKiBuf(Db_Xferred) = InData%dx(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE HydroDyn_PackParam + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 WAMIT_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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%PotMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NWaveElev = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev 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%WaveElev)) DEALLOCATE(OutData%WaveElev) + ALLOCATE(OutData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev,2), UBOUND(OutData%WaveElev,2) + DO i1 = LBOUND(OutData%WaveElev,1), UBOUND(OutData%WaveElev,1) + OutData%WaveElev(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev1 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%WaveElev1)) DEALLOCATE(OutData%WaveElev1) + ALLOCATE(OutData%WaveElev1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev1,2), UBOUND(OutData%WaveElev1,2) + DO i1 = LBOUND(OutData%WaveElev1,1), UBOUND(OutData%WaveElev1,1) + OutData%WaveElev1(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%AddF0,1) + i1_u = UBOUND(OutData%AddF0,1) + DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) + OutData%AddF0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%AddCLin,1) + i1_u = UBOUND(OutData%AddCLin,1) + i2_l = LBOUND(OutData%AddCLin,2) + i2_u = UBOUND(OutData%AddCLin,2) + DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) + DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) + OutData%AddCLin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%AddBLin,1) + i1_u = UBOUND(OutData%AddBLin,1) + i2_l = LBOUND(OutData%AddBLin,2) + i2_u = UBOUND(OutData%AddBLin,2) + DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) + DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) + OutData%AddBLin(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%AddBQuad,1) + i1_u = UBOUND(OutData%AddBQuad,1) + i2_l = LBOUND(OutData%AddBQuad,2) + i2_u = UBOUND(OutData%AddBQuad,2) + DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) + DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) + OutData%AddBQuad(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumTotalOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutDec = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du 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%du)) DEALLOCATE(OutData%du) + ALLOCATE(OutData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%du,1), UBOUND(OutData%du,1) + OutData%du(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dx 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%dx)) DEALLOCATE(OutData%dx) + ALLOCATE(OutData%dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dx,1), UBOUND(OutData%dx,1) + OutData%dx(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE HydroDyn_UnPackParam + + SUBROUTINE HydroDyn_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_InputType), INTENT(INOUT) :: SrcInputData + TYPE(HydroDyn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Morison_CopyInput( SrcInputData%Morison, DstInputData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%Mesh, DstInputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE HydroDyn_CopyInput + + SUBROUTINE HydroDyn_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(HydroDyn_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Morison_DestroyInput( InputData%Morison, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%Mesh, ErrStat, ErrMsg ) + END SUBROUTINE HydroDyn_DestroyInput + + SUBROUTINE HydroDyn_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(HydroDyn_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 = 'HydroDyn_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + 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 Morison_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 HydroDyn_PackInput + + SUBROUTINE HydroDyn_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(HydroDyn_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_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 + 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 Morison_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 HydroDyn_UnPackInput + + SUBROUTINE HydroDyn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'HydroDyn_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_CopyOutput( SrcOutputData%WAMIT, DstOutputData%WAMIT, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL WAMIT2_CopyOutput( SrcOutputData%WAMIT2, DstOutputData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Waves2_CopyOutput( SrcOutputData%Waves2, DstOutputData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Morison_CopyOutput( SrcOutputData%Morison, DstOutputData%Morison, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%AllHdroOrigin, DstOutputData%AllHdroOrigin, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE HydroDyn_CopyOutput + + SUBROUTINE HydroDyn_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL WAMIT_DestroyOutput( OutputData%WAMIT, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyOutput( OutputData%WAMIT2, ErrStat, ErrMsg ) + CALL Waves2_DestroyOutput( OutputData%Waves2, ErrStat, ErrMsg ) + CALL Morison_DestroyOutput( OutputData%Morison, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%AllHdroOrigin, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE HydroDyn_DestroyOutput + + SUBROUTINE HydroDyn_PackOutput( 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(HydroDyn_OutputType), 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 = 'HydroDyn_PackOutput' + ! 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 ! WAMIT: size of buffers for each call to pack subtype + CALL WAMIT_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype + CALL WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WAMIT2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WAMIT2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WAMIT2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype + CALL Waves2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Waves2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Waves2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Waves2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Morison: size of buffers for each call to pack subtype + CALL Morison_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, .TRUE. ) ! Morison + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Morison + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Morison + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Morison + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AllHdroOrigin: size of buffers for each call to pack subtype + CALL MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! AllHdroOrigin + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AllHdroOrigin + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AllHdroOrigin + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AllHdroOrigin + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 WAMIT_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + 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 WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + 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 Waves2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 + 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 Morison_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Morison, ErrStat2, ErrMsg2, OnlySize ) ! Morison + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! AllHdroOrigin + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE HydroDyn_PackOutput + + SUBROUTINE HydroDyn_UnPackOutput( 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(HydroDyn_OutputType), 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 = 'HydroDyn_UnPackOutput' + ! 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 WAMIT_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT, ErrStat2, ErrMsg2 ) ! WAMIT + 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 WAMIT2_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + 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 Waves2_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Waves2, ErrStat2, ErrMsg2 ) ! Waves2 + 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 Morison_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Morison, ErrStat2, ErrMsg2 ) ! Morison + 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 MeshUnpack( OutData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! AllHdroOrigin + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE HydroDyn_UnPackOutput + + + SUBROUTINE HydroDyn_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL HydroDyn_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL HydroDyn_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL HydroDyn_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE HydroDyn_Input_ExtrapInterp + + + SUBROUTINE HydroDyn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL Morison_Input_ExtrapInterp1( u1%Morison, u2%Morison, tin, u_out%Morison, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE HydroDyn_Input_ExtrapInterp1 + + + SUBROUTINE HydroDyn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL Morison_Input_ExtrapInterp2( u1%Morison, u2%Morison, u3%Morison, tin, u_out%Morison, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE HydroDyn_Input_ExtrapInterp2 + + + SUBROUTINE HydroDyn_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL HydroDyn_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL HydroDyn_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL HydroDyn_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE HydroDyn_Output_ExtrapInterp + + + SUBROUTINE HydroDyn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL WAMIT_Output_ExtrapInterp1( y1%WAMIT, y2%WAMIT, tin, y_out%WAMIT, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL WAMIT2_Output_ExtrapInterp1( y1%WAMIT2, y2%WAMIT2, tin, y_out%WAMIT2, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL Waves2_Output_ExtrapInterp1( y1%Waves2, y2%Waves2, tin, y_out%Waves2, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL Morison_Output_ExtrapInterp1( y1%Morison, y2%Morison, tin, y_out%Morison, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%AllHdroOrigin, y2%AllHdroOrigin, tin, y_out%AllHdroOrigin, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE HydroDyn_Output_ExtrapInterp1 + + + SUBROUTINE HydroDyn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL WAMIT_Output_ExtrapInterp2( y1%WAMIT, y2%WAMIT, y3%WAMIT, tin, y_out%WAMIT, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL WAMIT2_Output_ExtrapInterp2( y1%WAMIT2, y2%WAMIT2, y3%WAMIT2, tin, y_out%WAMIT2, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL Waves2_Output_ExtrapInterp2( y1%Waves2, y2%Waves2, y3%Waves2, tin, y_out%Waves2, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL Morison_Output_ExtrapInterp2( y1%Morison, y2%Morison, y3%Morison, tin, y_out%Morison, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%AllHdroOrigin, y2%AllHdroOrigin, y3%AllHdroOrigin, tin, y_out%AllHdroOrigin, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE HydroDyn_Output_ExtrapInterp2 + +END MODULE HydroDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/Morison.f90 b/OpenFAST/modules/hydrodyn/src/Morison.f90 new file mode 100644 index 000000000..0a52cef04 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Morison.f90 @@ -0,0 +1,4715 @@ +!********************************************************************************************************************************** +! The Morison and Morison_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. Morison_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of Morison. +! +! 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 +! +!********************************************************************************************************************************** +MODULE Morison + USE Waves + USE Morison_Types + USE Morison_Output + ! USE HydroDyn_Output_Types + USE NWTC_Library + + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: Morison_ProgDesc = ProgDesc( 'Morison', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + PUBLIC:: Morison_ProcessMorisonGeometry + + PUBLIC :: Morison_Init ! Initialization routine + PUBLIC :: Morison_End ! Ending routine (includes clean up) + + PUBLIC :: Morison_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: Morison_CalcOutput ! Routine for computing outputs + + PUBLIC :: Morison_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: Morison_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: Morison_UpdateDiscState ! Tight coupling routine for updating discrete states + + + +CONTAINS + +SUBROUTINE Morison_DirCosMtrx( pos0, pos1, DirCos ) + +! Compute the direction cosine matrix given two points along the axis of a cylinder + + REAL(ReKi), INTENT( IN ) :: pos0(3), pos1(3) + Real(ReKi), INTENT( OUT ) :: DirCos(3,3) + Real(DbKi) :: xz, xyz + Real(DbKi) :: x0, y0, z0 + Real(DbKi) :: x1, y1, z1 +! Real(DbKi) :: temp + + x0 = pos0(1) + y0 = pos0(2) + z0 = pos0(3) + x1 = pos1(1) + y1 = pos1(2) + z1 = pos1(3) + + ! Need to verify that z0 <= z1, but this was already handled in the element construction process!!! GJH 9/24/13 + !IF ( z0 > z1 ) THEN + ! temp = x0 + ! x0 = x1 + ! x1 = temp + ! temp = y0 + ! y0 = y1 + ! y1 = temp + ! temp = z0 + ! z0 = z1 + ! z1 = temp + !END IF + + xz = sqrt((x0-x1)*(x0-x1)+(z0-z1)*(z0-z1)) + xyz = sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)+(z0-z1)*(z0-z1)) + + IF ( xz==0 ) THEN + + IF (y1<y0) THEN + + DirCos = transpose(reshape((/ 1, 0, 0, 0, 0, -1, 0, 1, 0 /), shape(DirCos))) + + ELSE + + DirCos = transpose(reshape((/ 1, 0, 0, 0, 0, 1, 0, -1, 0 /), shape(DirCos))) + + END IF + + ELSE + + DirCos(1, 1) = -(z0-z1)/xz + DirCos(1, 2) = -(x0-x1)*(y0-y1)/(xz*xyz) + DirCos(1, 3) = (x1-x0)/xyz + + DirCos(2, 1) = 0.0 + DirCos(2, 2) = xz/xyz + DirCos(2, 3) = (y1-y0)/xyz + + DirCos(3, 1) = -(x1-x0)/xz + DirCos(3, 2) = -(y0-y1)*(z0-z1)/(xz*xyz) + DirCos(3, 3) = (z1-z0)/xyz + + ! DEBUG: TODO : Remove + !PRINT*, sqrt(DirCos(1,1)*DirCos(1,1) + DirCos(1,2)*DirCos(1,2)+DirCos(1,3)*DirCos(1,3)) + !PRINT*, sqrt(DirCos(2,1)*DirCos(2,1) + DirCos(2,2)*DirCos(2,2)+DirCos(2,3)*DirCos(2,3)) + !PRINT*, sqrt(DirCos(3,1)*DirCos(3,1) + DirCos(3,2)*DirCos(3,2)+DirCos(3,3)*DirCos(3,3)) + END IF + +END SUBROUTINE Morison_DirCosMtrx + +!==================================================================================================== +SUBROUTINE GetDistance ( a, b, l ) +! This private subroutine computes the distance between points a and b. +!---------------------------------------------------------------------------------------------------- + + REAL(ReKi), INTENT ( IN ) :: a(3) ! the position of point a + REAL(ReKi), INTENT ( IN ) :: b(3) ! the position of point b + REAL(ReKi), INTENT ( OUT ) :: l ! the distance between point a and b + + l = sqrt( ( a(1) - b(1) ) * ( a(1) - b(1) ) + ( a(2) - b(2) ) * ( a(2) - b(2) ) + ( a(3) - b(3) ) * ( a(3) - b(3) ) ) + +END SUBROUTINE GetDistance + +!==================================================================================================== +SUBROUTINE ElementCentroid ( Rs, Re, p1, h, DCM, centroid ) +! This private subroutine computes the centroid of a tapered right cylinder element. +!---------------------------------------------------------------------------------------------------- + + REAL(ReKi), INTENT ( IN ) :: Rs ! starting radius + REAL(ReKi), INTENT ( IN ) :: Re ! ending radius + REAL(ReKi), INTENT ( IN ) :: p1(3) ! starting point of the element in global coordinates + REAL(ReKi), INTENT ( IN ) :: h ! height of the element + REAL(ReKi), INTENT ( IN ) :: DCM(3,3) ! direction cosine matrix to transform local element coordinates to global coordinates + REAL(ReKi), INTENT ( OUT ) :: centroid(3) ! centroid of the element in local coordinates + + centroid(1) = 0.0 + centroid(2) = 0.0 + centroid(3) = h * (Rs*Rs + 2.0*Rs*Re + 3.0*Re*Re) / (4.0*( Rs*Rs + Rs*Re + Re*Re ) ) !( 2.0*Re + Rs ) / ( 3.0 * ( Rs + Re ) ) + centroid = matmul( DCM, centroid ) + p1 + +END SUBROUTINE ElementCentroid + +!==================================================================================================== +REAL(ReKi) FUNCTION ElementVolume ( Rs, Re, h ) +! This private function computes the volume of a tapered right cylinder element. +!---------------------------------------------------------------------------------------------------- + + REAL(ReKi), INTENT ( IN ) :: Rs ! starting radius + REAL(ReKi), INTENT ( IN ) :: Re ! ending radius + REAL(ReKi), INTENT ( IN ) :: h ! height of the element + + ElementVolume = Pi*h*( Rs*Rs + Re*Re + Rs*Re ) / 3.0 + +END FUNCTION ElementVolume + +!==================================================================================================== +SUBROUTINE FindInterpFactor( p, p1, p2, s ) + + REAL(ReKi), INTENT ( IN ) :: p, p1, p2 + REAL(ReKi), INTENT ( OUT ) :: s + + REAL(ReKi) :: dp +! find normalized interpolation factor, s, such: +! p = p1*(1-s) + p2*s +! *--------------*--------------------------------* +! p1 p p2 +! +! 0-----------------------------------------------1 +! <------- s ----> + + dp = p2 - p1 + IF ( EqualRealNos(dp, 0.0_ReKi) ) THEN + s = 0 + ELSE + s = ( p - p1 ) / dp + END IF + +END SUBROUTINE FindInterpFactor +!======================================================================= + +!======================================================================= +SUBROUTINE DistrBuoyancy( densWater, R, tMG, dRdz, Z, C, g, F_B ) + ! This calculates the distributed buoyancy forces and moments on a given node + + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: R ! Radius of node [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: dRdz ! Rate of change in radius with length at node [-] + REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of node [m] (not currently used) + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: g + REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Distributed force and moment vector [N/m and N-m/m] + + REAL(DbKi) :: Reff,ReffSq,ReffCub,f1,f2,f3 + + REAL(DbKi) :: CC(3,3) + + CC = REAL(C,DbKi) + Reff = REAL(R + tMG,DbKi) ! Effective radius after adding marine growth + + + + ReffSq = Reff*Reff + ReffCub = ReffSq*Reff + f1 = REAL(denswater,DbKi)*REAL(g,DbKi)*Pi_D + f2 = f1*ReffCub*REAL(dRdz,DbKi) + f3 = Reff*REAL(dRdz,DbKi)*REAL(Z,DbKi) + + + F_B(1) = f1*( (CC(1,1)*CC(3,1) + CC(1,2)*CC(3,2))*ReffSq - 2.0*CC(1,3)*f3 ) + F_B(2) = f1*( (CC(2,1)*CC(3,1) + CC(2,2)*CC(3,2))*ReffSq - 2.0*CC(2,3)*f3 ) + F_B(3) = f1*( (CC(3,1)*CC(3,1) + CC(3,2)*CC(3,2))*ReffSq - 2.0*CC(3,3)*f3 ) + F_B(4) = -f2*( CC(1,1)*CC(3,2) - CC(1,2)*CC(3,1) ) + F_B(5) = -f2*( CC(2,1)*CC(3,2) - CC(2,2)*CC(3,1) ) + F_B(6) = -f2*( CC(3,1)*CC(3,2) - CC(3,2)*CC(3,1) ) + + + + +END SUBROUTINE DistrBuoyancy + + +SUBROUTINE DistrInertialLoads( nodeIndx, densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, NStepWave, WaveAcc0, WaveDynP0, F_I, ErrStat, ErrMsg ) + + INTEGER, INTENT ( IN ) :: nodeIndx + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: Ca + REAL(ReKi), INTENT ( IN ) :: Cp + REAL(ReKi), INTENT ( IN ) :: AxCa + REAL(ReKi), INTENT ( IN ) :: AxCp + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( IN ) :: dRdZ + REAL(ReKi), INTENT ( IN ) :: k(3) + INTEGER, INTENT ( IN ) :: NStepWave + REAL(SiKi), INTENT ( IN ) :: WaveAcc0(0:,:,:) + REAL(SiKi), INTENT ( IN ) :: WaveDynP0(0:,:) + REAL(ReKi),ALLOCATABLE, INTENT ( OUT ) :: F_I(:,:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + REAL(ReKi) :: f, f1, f2, f3, adotk !, v_len + REAL(ReKi) :: v(3), af(3) !p0(3), m(3), + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate F_I + ALLOCATE ( F_I(0:NStepWave, 6), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating distributed inertial loads array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + f = (Ca + Cp)*densWater*Pi*(R+tMG)*(R+tMG) + f2 = AxCa*densWater*2.0*Pi*(R+tMG)*(R+tMG)*abs(dRdZ) + f1 = AxCp*2.0*Pi*(R+tMG)*dRdz + + DO I=0,NStepWave + + af = WaveAcc0(I,nodeIndx,:) + adotk = af(1)*k(1) + af(2)*k(2) + af(3)*k(3) + v = af - adotk*k + + ! NOTE: (k cross l) x k = l - (l dot k)k + + f3 = f1*WaveDynP0(I,nodeIndx) + + !CALL GetDistance( p0, v, v_len ) + !TODO What about multiplying by the magnitude? + + + + F_I(I,1) = f*v(1) + (f3 + f2*adotk)*k(1) + F_I(I,2) = f*v(2) + (f3 + f2*adotk)*k(2) + F_I(I,3) = f*v(3) + (f3 + f2*adotk)*k(3) + F_I(I,4) = 0.0 + F_I(I,5) = 0.0 + F_I(I,6) = 0.0 + + END DO + +END SUBROUTINE DistrInertialLoads + + + +SUBROUTINE DistrInertialLoads2( densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, WaveAcc, WaveDynP, F_I, ErrStat, ErrMsg ) + + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: Ca + REAL(ReKi), INTENT ( IN ) :: Cp + REAL(ReKi), INTENT ( IN ) :: AxCa + REAL(ReKi), INTENT ( IN ) :: AxCp + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( IN ) :: dRdZ + REAL(ReKi), INTENT ( IN ) :: k(3) + REAL(ReKi), INTENT ( IN ) :: WaveAcc(3) + REAL(ReKi), INTENT ( IN ) :: WaveDynP + REAL(ReKi), INTENT ( OUT ) :: F_I(3) + !REAL(ReKi), INTENT ( OUT ) :: F_I(3) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + REAL(ReKi) :: f, f1, f2, f3, v_len, adotk + REAL(ReKi) :: p0(3), m(3), v(3), af(3) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + f = (Ca + Cp)*densWater*Pi*(R+tMG)*(R+tMG) + f2 = AxCa*densWater*2.0*Pi*(R+tMG)*(R+tMG)*abs(dRdZ) + f1 = AxCp*2.0*Pi*(R+tMG)*dRdz + + adotk = WaveAcc(1)*k(1) + WaveAcc(2)*k(2) + WaveAcc(3)*k(3) + v = WaveAcc - adotk*k + + ! NOTE: (k cross l) x k = l - (l dot k)k + + f3 = f1*WaveDynP + + !CALL GetDistance( p0, v, v_len ) + !TODO What about multiplying by the magnitude? + + + + F_I(1) = f*v(1) + (f3 + f2*adotk)*k(1) + F_I(2) = f*v(2) + (f3 + f2*adotk)*k(2) + F_I(3) = f*v(3) + (f3 + f2*adotk)*k(3) + !F_I(4) = 0.0_ReKi + !F_I(5) = 0.0_ReKi + !F_I(6) = 0.0_ReKi + + + +END SUBROUTINE DistrInertialLoads2 + + +SUBROUTINE DistrMGLoads(MGdens, g, R, tMG, F_MG ) + REAL(ReKi), INTENT ( IN ) :: MGdens + REAL(ReKi), INTENT ( IN ) :: g + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( OUT ) :: F_MG(6) + + F_MG(:) = 0.0 + F_MG(3) = -MGdens*g*Pi* ( (R + tMG ) * ( R + tMG ) - R*R ) + +END SUBROUTINE DistrMGLoads + +SUBROUTINE DistrDragConst( densWater, Cd, R, tMG, DragConst ) + + ! This is used to minimize the computations which occur at each timestep + + REAL(ReKi), INTENT ( IN ) :: Cd + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( OUT ) :: DragConst + + DragConst = Cd*densWater*(R+tMG) + +END SUBROUTINE DistrDragConst + + +SUBROUTINE DistrFloodedBuoyancy( densFluid, Z_f, R, t, dRdz, Z, C, g, F_B ) + + REAL(ReKi), INTENT ( IN ) :: densFluid + REAL(ReKi), INTENT ( IN ) :: Z_f + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: t + REAL(ReKi), INTENT ( IN ) :: dRdz + REAL(ReKi), INTENT ( IN ) :: Z + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: g + REAL(ReKi), INTENT ( OUT ) :: F_B(6) + + REAL(DbKi) :: Zeff,Reff,ReffSq,ReffCub,f1,f2,f3 + + + REAL(DbKi) :: CC(3,3) + CC = REAL(C,DbKi) + + + Reff = REAL(R - t,DbKi) + Zeff = REAL(Z - Z_f,DbKi) + + ReffSq = Reff*Reff + ReffCub = ReffSq*Reff + f1 = -REAL(densFluid,DbKi)*REAL(g,DbKi)*Pi_D + f2 = f1*ReffCub*REAL(dRdz,DbKi) + f3 = Reff*REAL(dRdz,DbKi)*Zeff + + + + F_B(1) = f1*( (CC(1,1)*CC(3,1) + CC(1,2)*CC(3,2))*ReffSq - 2.0*CC(1,3)*f3 ) + F_B(2) = f1*( (CC(2,1)*CC(3,1) + CC(2,2)*CC(3,2))*ReffSq - 2.0*CC(2,3)*f3 ) + F_B(3) = f1*( (CC(3,1)*CC(3,1) + CC(3,2)*CC(3,2))*ReffSq - 2.0*CC(3,3)*f3 ) + F_B(4) = -f2*( CC(1,1)*CC(3,2) - CC(1,2)*CC(3,1) ) + F_B(5) = -f2*( CC(2,1)*CC(3,2) - CC(2,2)*CC(3,1) ) + F_B(6) = -f2*( CC(3,1)*CC(3,2) - CC(3,2)*CC(3,1) ) + +END SUBROUTINE DistrFloodedBuoyancy + +SUBROUTINE DistrAddedMass( densWater, Ca, AxCa, C, R, tMG, dRdZ, AM_M) + ! This calculates the distributed hydrodynamic added mass matrix for a given node. + + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: Ca ! Transverse added mass coefficient + REAL(ReKi), INTENT ( IN ) :: AxCa ! Axial added mass coefficient (applied to tapered portions) + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: R ! Radius at node [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: dRdZ ! Rate of change in radius with length at node [-] + REAL(ReKi), INTENT ( OUT ) :: AM_M(3,3) ! Distributed added mass matrix to be calculated [kg/m] + + REAL(ReKi) :: f,f2 + + f = Ca*densWater*Pi*(R+tMG)*(R+tMG) ! Transverse added mass scaler, applied to I - k*k^T + f2 = AxCa*2.0*densWater*Pi*abs(dRdZ)*(R+tMG)*(R+tMG) ! Axial added mass scaler, applied to k k^T + !AM_M = 0.0 + AM_M(1,1) = f*( C(2,3)*C(2,3) + C(3,3)*C(3,3) ) -f2*C(1,3)*C(1,3) !<----@mhall: why is the f2 term being subtracted rather than added? + AM_M(1,2) = f*( -C(1,3)*C(2,3) ) -f2*C(1,3)*C(2,3) + AM_M(1,3) = f*( -C(1,3)*C(3,3) ) -f2*C(1,3)*C(3,3) + + AM_M(2,1) = f*( -C(1,3)*C(2,3) ) -f2*C(2,3)*C(1,3) + AM_M(2,2) = f*( C(1,3)*C(1,3) + C(3,3)*C(3,3) ) -f2*C(2,3)*C(2,3) !<----@mhall: would it be cleaner to just use the k unit vector? (also, diagonal terms can be shortened (1-k*kT)) + AM_M(2,3) = f*( -C(2,3)*C(3,3) ) -f2*C(2,3)*C(3,3) + + AM_M(3,1) = f*( -C(1,3)*C(3,3) ) -f2*C(3,3)*C(1,3) + AM_M(3,2) = f*( -C(2,3)*C(3,3) ) -f2*C(3,3)*C(2,3) + AM_M(3,3) = f*( C(1,3)*C(1,3) + C(2,3)*C(2,3) ) -f2*C(3,3)*C(3,3) + + +END SUBROUTINE DistrAddedMass + + +SUBROUTINE DistrAddedMassMG( densMG, R, tMG, AM_MG) + + REAL(ReKi), INTENT ( IN ) :: densMG + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( OUT ) :: AM_MG + + AM_MG = densMG*Pi*((R+tMG)*(R+tMG) - R*R) + + +END SUBROUTINE DistrAddedMassMG + + +SUBROUTINE DistrAddedMassFlood( densFluid, R, t, AM_F) + + REAL(ReKi), INTENT ( IN ) :: densFluid + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: t + REAL(ReKi), INTENT ( OUT ) :: AM_F + + + AM_F = densFluid*Pi*(R-t)*(R-t) + +END SUBROUTINE DistrAddedMassFlood + + + +SUBROUTINE LumpDragConst( densWater, Cd, R, tMG, DragConst ) + + ! This is used to minimize the computations which occur at each timestep + + REAL(ReKi), INTENT ( IN ) :: Cd + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + REAL(ReKi), INTENT ( OUT ) :: DragConst + + DragConst = 0.5*Cd*densWater*(R+tMG)*(R+tMG) + +END SUBROUTINE LumpDragConst + + +SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg ) + + + INTEGER, INTENT ( IN ) :: nodeIndx + REAL(ReKi), INTENT ( IN ) :: Cp + REAL(ReKi), INTENT ( IN ) :: k(3) + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tMG + INTEGER, INTENT ( IN ) :: NStepWave + REAL(SiKi), INTENT ( IN ) :: WaveDynP(0:,:) + REAL(ReKi),ALLOCATABLE, INTENT ( OUT ) :: F_DP(:,:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Allocate F_DP + + ALLOCATE ( F_DP(0:NStepWave,6), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating distributed dynamic pressure loads array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I=0,NStepWave + F_DP(I,1) = Cp*k(1)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) + F_DP(I,2) = Cp*k(2)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) + F_DP(I,3) = Cp*k(3)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) + F_DP(I,4) = 0.0 + F_DP(I,5) = 0.0 + F_DP(I,6) = 0.0 + END DO + + +END SUBROUTINE LumpDynPressure + + + +SUBROUTINE LumpBuoyancy( sgn, densWater, R, tMG, Z, C, g, F_B ) + ! This calculates lumped buoyancy forces/moments on a member end. + + REAL(ReKi), INTENT ( IN ) :: sgn ! @mhall: this indicates if this is the start or end node so that direction is correct? + REAL(ReKi), INTENT ( IN ) :: densWater + REAL(ReKi), INTENT ( IN ) :: R ! Radius of end [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of end [m] + + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: g + REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Lumped force and moment vector [N and N-m] + + + REAL(DbKi) :: f, f1, f2, f3, Reff, Rsq,R_4 + Reff = REAL(R+tMG,DbKi) + Rsq = Reff**2 + R_4 = Rsq**2 + f = REAL(g,DbKi)*REAL(densWater,DbKi)*REAL(sgn,DbKi) + f1 = -REAL(Z,DbKi)*Pi_D*Rsq + f2 = f*Pi_D*R_4 + !f3 = C(3,1)*R_4 + + F_B(1) = C(1,3)*f1*f + F_B(2) = C(2,3)*f1*f + F_B(3) = C(3,3)*f1*f + F_B(4) = 0.25*( -C(3,2)*C(1,1) + C(1,2)*C(3,1) )*f2 ! TODO: We flipped the signs of the moments because 1 member tapered integrated moments were not zero. GJH 10/1/13 Jason is verifying. + F_B(5) = 0.25*( -C(3,2)*C(2,1) + C(2,2)*C(3,1) )*f2 + F_B(6) = 0.25*( -C(3,2)*C(3,1) + C(3,2)*C(3,1) )*f2 + + +END SUBROUTINE LumpBuoyancy + + + +SUBROUTINE LumpFloodedBuoyancy( sgn, densFill, R, tM, FillFS, Z, C, g, F_BF ) + + REAL(ReKi), INTENT ( IN ) :: sgn + REAL(ReKi), INTENT ( IN ) :: densFill + REAL(ReKi), INTENT ( IN ) :: R + REAL(ReKi), INTENT ( IN ) :: tM + REAL(ReKi), INTENT ( IN ) :: FillFS + REAL(ReKi), INTENT ( IN ) :: Z + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: g + REAL(ReKi), INTENT ( OUT ) :: F_BF(6) + + + REAL(ReKi) :: f, f1, f2 !, f3 + + f = -densFill*g*sgn + + f1 = -(Z - FillFS)*Pi* (R-tM)*(R-tM) + f2 = 0.25*Pi*(R-tM)*(R-tM)*(R-tM)*(R-tM) + + + F_BF(1) = C(1,3)*f1*f + F_BF(2) = C(2,3)*f1*f + F_BF(3) = C(3,3)*f1*f + F_BF(4) = (-C(1,1)*C(3,2) + C(1,2)*C(3,1))*f*f2 ! TODO: We flipped the signs of the moments because 1 member tapered integrated moments were not zero. GJH 10/1/13 Jason is verifying. + F_BF(5) = (-C(2,1)*C(3,2) + C(2,2)*C(3,1))*f*f2 + F_BF(6) = (-C(3,1)*C(3,2) + C(3,2)*C(3,1))*f*f2 + + +END SUBROUTINE LumpFloodedBuoyancy + +LOGICAL FUNCTION IsThisSplitValueUsed(nSplits, splits, checkVal) + + INTEGER, INTENT ( IN ) :: nSplits + REAL(ReKi), INTENT ( IN ) :: splits(:) + REAL(ReKi), INTENT ( IN ) :: checkVal + + INTEGER :: I + + DO I=1,nSplits + IF ( EqualRealNos(splits(I), checkVal ) ) THEN + IsThisSplitValueUsed = .TRUE. + RETURN + END IF +END DO + + IsThisSplitValueUsed = .FALSE. + +END FUNCTION IsThisSplitValueUsed +!==================================================================================================== +SUBROUTINE GetMaxSimQuantities( numMGDepths, MGTop, MGBottom, MSL2SWL, Zseabed, filledGroups, numJoints, joints, numMembers, members, maxNodes, maxElements, maxSuperMembers ) +! This private subroutine determines the maximum nodes, elements, and super members which may appear +! in the final simulation mesh. This is based on the following: +! 1) Member splitting at the marine growth boundaries ( new nodes and members ) +! 2) Member splitting due to internal subdivision ( new nodes and members ) +! 3) New nodes and super members if a joint marked with JointOvrlp = 1 (and additional conditions are satisfied) +! +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT ( IN ) :: numMGDepths ! number of MGDepths specified in the input table + REAL(ReKi), INTENT ( IN ) :: MGTop ! Global Z-value of the upper marine growth boundary + REAL(ReKi), INTENT ( IN ) :: MGBottom ! Global Z-value of the lower marine growth boundary + REAL(ReKi), INTENT ( IN ) :: MSL2SWL ! Global Z-value of mean sea level + REAL(ReKi), INTENT ( IN ) :: Zseabed ! Global Z-value of the top of the seabed + TYPE(Morison_FilledGroupType), allocatable, INTENT ( IN ) :: filledGroups(:) ! this might not be allocated, so add the allocatable type here + INTEGER, INTENT ( IN ) :: numJoints ! number of joints specified in the inputs + TYPE(Morison_JointType), INTENT ( IN ) :: joints(:) ! array of input joint data structures + INTEGER, INTENT ( IN ) :: numMembers ! number of members specified in the inputs + TYPE(Morison_MemberInputType), INTENT ( INOUT ) :: members(:) ! array of input member data structures + INTEGER, INTENT ( OUT ) :: maxNodes ! maximum number of nodes which may appear in the final simulation mesh + INTEGER, INTENT ( OUT ) :: maxElements ! maximum number of elements which may appear in the final simulation mesh + INTEGER, INTENT ( OUT ) :: maxSuperMembers ! maximum number of super members which may appear in the final simulation mesh + + ! Local variables + INTEGER :: WtrSplitCount = 0 ! number of possible new members due to splitting at water boundaries + INTEGER :: MGsplitCount = 0 ! number of possible new members due to splitting at marine growth boundaries + INTEGER :: maxSubMembers = 0 ! maximum added nodes and members due to member subdivision + INTEGER :: maxSuperMemNodes = 0 ! maximum number of new nodes due to super member generation + INTEGER :: I, J, j1, j2 ! generic integer for counting + TYPE(Morison_JointType) :: joint1, joint2 ! joint data structures + Real(ReKi) :: z1, z2 ! z values of the first and second joints + Real(ReKi) :: temp ! temporary variable + REAL(ReKi) :: memLen ! member length + INTEGER :: nSplits, totalSplits, nodeSplits + REAL(ReKi) :: possibleSplits(5) + ! Initialize quantities + maxNodes = numJoints + maxElements = numMembers + maxSuperMembers = 0 + maxSuperMemNodes = 0 + maxSubMembers = 0 + MGsplitCount = 0 + WtrSplitCount = 0 + nodeSplits = 0 + totalSplits = 0 + + ! Determine new members and nodes due to internal member subdivision + DO I = 1,numMembers + + + z1 = joints( members(I)%MJointID1Indx )%JointPos(3) + z2 = joints( members(I)%MJointID2Indx )%JointPos(3) + IF ( z1 > z2) THEN + temp = z1 + z1 = z2 + z2 = temp + END IF + + + + ! For this member, determine possible split conditions due to crossing through: + ! MSL, seabed, marine growth boundaries, filled free surface location. + ! + + ! Start with no splits. + nSplits = 0 + possibleSplits = -9999999.0 ! Initialize possibleSplit values to a number that never appears in the geometry. + + ! If the member is filled, add a possible split location at the global Z location of the filled free surface. + IF ( members(I)%MmbrFilledIDIndx /= -1 ) THEN + nSplits = 1 + ! The free surface is specified relative to the MSL. + possibleSplits(1) = filledGroups(members(I)%MmbrFilledIDIndx)%FillFSLoc + END IF + + + ! If the filled fluid hasn't already caused a split in the member at the still water line, then add a possible split there (at the water free surface, MSL2SWL). + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MSL2SWL )) THEN + nSplits = nSplits + 1 + possibleSplits(nSplits) = MSL2SWL + END IF + + ! If there are one more depth-defined marine growth regions, add a possible split at each boundary if one doesn't already exist. + IF ( numMGDepths > 0 ) THEN + + ! Recursively check to see if this + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MGTop) ) THEN + nSplits = nSplits + 1 + possibleSplits(nSplits) = MGTop + END IF + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MGBottom) ) THEN + nSplits = nSplits + 1 + possibleSplits(nSplits) = MGBottom + END IF + + END IF + + ! Add a possible split a the seabed if there isn't already one there. + ! Check if seabed is equal to other possibleSplits + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, Zseabed) ) THEN + nSplits = nSplits + 1 + possibleSplits(nSplits) = Zseabed + END IF + + + ! Now determine which possible splits this member actually crosses and record them in the member's data structure. + + DO J=1,nSplits + + IF ( z1 < possibleSplits(J) .AND. z2 > possibleSplits(J) ) THEN + members(I)%NumSplits = members(I)%NumSplits + 1 + members(I)%Splits(members(I)%NumSplits) = possibleSplits(J) + END IF + + END DO + ! Sort the splits from smallest Z value to largest Z value + CALL BSortReal ( members(I)%Splits, members(I)%NumSplits ) + totalSplits = totalSplits + members(I)%NumSplits + + ! ! Determine new members due to elements crossing the MSL or the seabed + !IF ( z2 > MSL2SWL ) THEN + ! IF ( z1 < MSL2SWL .AND. z1 >= Zseabed ) THEN + ! ! Split this member + ! WtrSplitCount = WtrSplitCount + 1 + ! members(I).WtrSplitState = 1 + ! END IF + ! IF ( z1 < Zseabed ) THEN + ! ! Split this member twice because it crosses both boundaries + ! WtrSplitCount = WtrSplitCount + 2 + ! members(I).WtrSplitState = 3 + ! END IF + !END IF + !IF ( z2 < MSL2SWL .AND. z2 >= Zseabed ) THEN + ! IF ( z1 < MGBottom ) THEN + ! ! Split this member + ! WtrSplitCount = WtrSplitCount + 1 + ! members(I).WtrSplitState = 2 + ! END IF + ! + !END IF + ! + ! ! Determine new members and nodes due to marine growth boundary splitting + ! members(I).MGSplitState = 0 + !IF ( numMGDepths > 0 ) THEN + ! + ! IF ( z2 > MGTop ) THEN + ! IF ( z1 < MGTop .AND. z1 >= MGBottom ) THEN + ! ! Split this member + ! MGsplitCount = MGsplitCount + 1 + ! members(I).MGSplitState = 1 + ! END IF + ! IF ( z1 < MGBottom ) THEN + ! ! Split this member twice because it crosses both boundaries + ! MGsplitCount = MGsplitCount + 2 + ! members(I).MGSplitState = 3 + ! END IF + ! END IF + ! IF ( z2 < MGTop .AND. z2 >= MGBottom ) THEN + ! IF ( z1 < MGBottom ) THEN + ! ! Split this member + ! MGsplitCount = MGsplitCount + 1 + ! members(I).MGSplitState = 2 + ! END IF + ! + ! END IF + ! + !END IF + + j1 = members(I)%MJointID1Indx + j2 = members(I)%MJointID2Indx + joint1 = joints(j1) ! note Inspector complains of uninitialized variables; this is due to copying types here (and some fields haven't been initialized) + joint2 = joints(j2) ! note Inspector complains of uninitialized variables; this is due to copying types here (and some fields haven't been initialized) + CALL GetDistance(joint1%JointPos, joint2%JointPos, memLen) + maxSubMembers = maxSubMembers + CEILING( memLen / members(I)%MDivSize ) - 1 + + END DO + + ! Look for all possible super member creation + DO I = 1,numJoints + + ! Check #1 are there more than 2 members connected to the joint? + IF ( joints(I)%JointOvrlp == 1 .AND. joints(I)%NConnections > 2) THEN + maxSuperMemNodes = maxSuperMemNodes + ( joints(I)%NConnections - 1 ) + maxSuperMembers = maxSuperMembers + 1 + ELSE + nodeSplits = nodeSplits + joints(I)%NConnections - 1 + END IF + + + END DO + + maxNodes = maxNodes + totalSplits*2 + nodeSplits + maxSubMembers + maxSuperMemNodes + maxElements = maxElements + totalSplits + maxSubMembers + + +END SUBROUTINE GetMaxSimQuantities + +SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElements, elements, NOutputs, OutParam, NMOutputs, MOutLst, distribToNodeIndx, NJOutputs, JOutLst, inLumpedMesh, outLumpedMesh, inDistribMesh, outDistribMesh, L_F_B, L_F_BF, D_F_B, D_F_BF, D_F_MG, g, ErrStat, ErrMsg ) !, numDistribMarkers, distribMarkers, numLumpedMarkers, lumpedMarkers + + REAL(ReKi), INTENT ( IN ) :: MSL2SWL + REAL(ReKi), INTENT ( IN ) :: WtrDpth + INTEGER, INTENT ( IN ) :: UnSum + INTEGER, INTENT ( IN ) :: numNodes + TYPE(Morison_NodeType), INTENT ( IN ) :: nodes(:) + INTEGER, INTENT ( IN ) :: numElements + TYPE(Morison_MemberType), INTENT ( IN ) :: elements(:) + INTEGER, INTENT ( IN ) :: NOutputs + TYPE(OutParmType), allocatable, INTENT ( IN ) :: OutParam(:) + INTEGER, INTENT ( IN ) :: NMOutputs + TYPE(Morison_MOutput), allocatable, INTENT ( IN ) :: MOutLst(:) + INTEGER, INTENT ( IN ) :: distribToNodeIndx(:) + INTEGER, INTENT ( IN ) :: NJOutputs + TYPE(Morison_JOutput), allocatable, INTENT ( IN ) :: JOutLst(:) + TYPE(MeshType), INTENT ( INOUT ) :: inLumpedMesh + TYPE(MeshType), INTENT ( INOUT ) :: outLumpedMesh + TYPE(MeshType), INTENT ( INOUT ) :: inDistribMesh + TYPE(MeshType), INTENT ( INOUT ) :: outDistribMesh + REAL(ReKi), INTENT ( IN ) :: L_F_B(:,:) ! Lumped buoyancy force associated with the member + REAL(ReKi), INTENT ( IN ) :: L_F_BF(:,:) ! Lumped buoyancy force associated flooded/filled fluid within the member + REAL(ReKi), INTENT ( IN ) :: D_F_B(:,:) ! Lumped buoyancy force associated with the member + REAL(ReKi), INTENT ( IN ) :: D_F_BF(:,:) ! Lumped buoyancy force associated flooded/filled fluid within the member + REAL(ReKi), INTENT ( IN ) :: D_F_MG(:,:) + REAL(ReKi), INTENT ( IN ) :: g ! gravity + !INTEGER, INTENT ( IN ) :: numDistribMarkers + !TYPE(Morison_NodeType), INTENT ( IN ) :: distribMarkers(:) + !INTEGER, INTENT ( IN ) :: numLumpedMarkers + !TYPE(Morison_NodeType), INTENT ( IN ) :: lumpedMarkers(:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J + REAL(ReKi) :: l ! length of an element + LOGICAL :: filledFlag ! flag indicating if element is filled/flooded + CHARACTER(2) :: strFmt + CHARACTER(ChanLen) :: strNodeType ! string indicating type of node: End, Interior, Super + REAL(ReKi) :: ident(3,3) ! identity matrix + REAL(ReKi) :: ExtBuoyancy(6) ! sum of all external buoyancy forces lumped at (0,0,0) + REAL(ReKi) :: IntBuoyancy(6) ! sum of all internal buoyancy forces lumped at (0,0,0) + REAL(ReKi) :: MG_Wt(6) ! weight of the marine growth as applied to (0,0,0) + TYPE(MeshType) :: WRP_Mesh ! mesh representing the WAMIT reference point (0,0,0) + TYPE(MeshType) :: WRP_Mesh_position ! mesh representing the WAMIT reference point (0,0,0) (with no displaced position) + TYPE(MeshMapType) :: M_L_2_P ! Map Morison Line2 to WRP_Mesh point + TYPE(MeshMapType) :: M_P_2_P ! Map Morison Point to WRP_Mesh point + REAL(ReKi) :: elementVol ! displaced volume of an element + REAL(ReKi) :: totalDisplVol ! total displaced volume of the structure + REAL(ReKi) :: totalVol ! total volume of structure + REAL(ReKi) :: MGvolume ! volume of the marine growth material + REAL(ReKi) :: totalMGVol ! + REAL(ReKi) :: totalFillVol ! + REAL(ReKi) :: elemCentroid(3) ! location of the element centroid + REAL(ReKi) :: COB(3) ! center of buoyancy location in global coordinates + INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location + REAL(ReKi) :: s ! The linear interpolation factor for the requested location + REAL(ReKi) :: outloc(3) ! Position of the requested member output + INTEGER :: mbrIndx, nodeIndx + CHARACTER(ChanLen) :: tmpName + REAL(ReKi) :: totalFillMass, mass_fill, fillVol + REAL(ReKi) :: totalMGMass, mass_MG + TYPE(Morison_NodeType) :: node1, node2 + REAL(ReKi) :: Cd1, Cd2, Ca1, Ca2, Cp1, Cp2, AxCa1, AxCa2, AxCp1, AxCp2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 ! tmp coefs + + ! Initialize data + ErrStat = ErrID_None + ErrMsg = "" + ExtBuoyancy = 0.0 + totalFillMass = 0.0 + totalDisplVol = 0.0 + totalVol = 0.0 + totalMGVol = 0.0 + totalFillVol = 0.0 + totalMGMass = 0.0 + COB = 0.0 + + ! Create identity matrix + CALL EYE(ident,ErrStat,ErrMsg) + + IF ( UnSum > 0 ) THEN + + + + !WRITE( UnSum, '(//)' ) + !WRITE( UnSum, '(A8)' ) 'Elements' + !WRITE( UnSum, '(/)' ) + !WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,5(2X,A12),2X,A12,17(2X,A12))' ) ' i ', 'node1','node2',' Length ', ' MGVolume ', ' MGDensity ', 'PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' CdMG1 ', ' Ca1 ', ' CaMG1 ', ' R1 ', ' t1 ',' Cd2 ', ' CdMG2 ', ' Ca2 ', ' CaMG2 ', ' R2 ', ' t2 ' + !WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,5(2X,A12),2X,A12,17(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (m^3) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ',' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ' + ! + + DO I = 1,numElements + + node1 = nodes(elements(I)%Node1Indx) + node2 = nodes(elements(I)%Node2Indx) + IF ( ( (node1%tMG > 0.0_ReKi ) .AND. EqualRealNos(node2%tMG,0.0_ReKi) ) .OR. ( (node2%tMG > 0.0_ReKi ) .AND. EqualRealNos(node1%tMG,0.0_ReKi) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'If one node of an element has MG, then both must. This is an internal code problem within HydroDyn.' + RETURN + END IF + CALL GetDistance( nodes(elements(I)%Node1Indx)%JointPos, nodes(elements(I)%Node2Indx)%JointPos, l ) + + + IF (elements(I)%PropPot) THEN + MGvolume = 0.0 + elementVol = 0.0 + ELSE + elementVol = ElementVolume(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, l) + MGvolume = elementVol - ElementVolume(elements(I)%R1, elements(I)%R2, l) + END IF + totalMGVol = totalMGVol + MGvolume + mass_MG = MGvolume*elements(I)%FillDens + totalMGMass = totalMGMass + mass_MG + CALL ElementCentroid(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, node1%JointPos, l, elements(I)%R_LToG, elemCentroid) + + COB = COB + elementVol*elemCentroid + + totalVol = totalVol + elementVol + + IF ( node2%JointPos(3) <= MSL2SWL .AND. node1%JointPos(3) >= -WtrDpth) totalDisplVol = totalDisplVol + elementVol + + IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN + ! filledFlag = .TRUE. + !IF ( ( node2%JointPos(3) <= elements(I)%FillFSLoc ) .AND. ( node1%JointPos(3) <= elements(I)%FillFSLoc ) ) THEN + fillVol = ElementVolume(elements(I)%R1 - elements(I)%t1, elements(I)%R2 - elements(I)%t2, l) + totalFillVol = totalFillVol + fillVol + mass_fill = elements(I)%FillDens*fillVol + totalFillMass = totalFillMass + mass_fill + !END IF + ELSE + ! mass_fill = 0.0 + ! filledFlag = .FALSE. + END IF + + !WRITE( UnSum, '(1X,I5,2X,I5,2X,I5,3(2X,ES12.5),2(2X,L12),2X,ES12.5,17(2X,ES12.5))' ) I, elements(I)%Node1Indx, elements(I)%Node2Indx, l, MGvolume, node1%MGdensity, elements(I)%PropPot, filledFlag, elements(I)%FillDens, elements(I)%FillFSLoc, mass_fill, elements(I)%Cd1, elements(I)%CdMG1, elements(I)%Ca1, elements(I)%CaMG1, elements(I)%R1, elements(I)%t1, elements(I)%Cd2, elements(I)%CdMG2, elements(I)%Ca2, elements(I)%CaMG2, elements(I)%R2, elements(I)%t2 + + END DO ! I = 1,numElements + + + + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A24)' ) 'Volume Calculations(m^3)' + WRITE( UnSum, '(A24)' ) '------------------------' + WRITE( UnSum, '(A27,ES12.5)' ) ' Structure Volume : ', totalVol + WRITE( UnSum, '(A27,ES12.5)' ) ' Submerged Volume : ', totalDisplVol + WRITE( UnSum, '(A27,ES12.5)' ) ' Marine Growth Volume : ', totalMGVol + WRITE( UnSum, '(A27,ES12.5)' ) ' Ballasted Volume : ', totalFillVol + WRITE( UnSum, '(A111)') ' NOTE: Structure, Submerged and Marine Growth volumes are based on members not modelled with WAMIT' + WRITE( UnSum, '(A149)') ' Ballasted volume is computed from all members which are marked as filled in the HydroDyn input file, regardless of PropPot flag' + + + + ! Sum all buoyancy loads to the COB + ! Do this by creating a temporary mesh which is for (0,0,0) + + !COB = COB / totalVol + + ! Write out the Center of Buoyancy (geometric center of the displaced volume) + !WRITE( UnSum, '(//)' ) + !WRITE( UnSum, '(A18)' ) 'Center of Buoyancy' + !WRITE( UnSum, '(3(2X,A10 ))' ) ' COBXi ', ' COBYi ', ' COBZi ' + !WRITE( UnSum, '(3(2X,A10 ))' ) ' (m) ', ' (m) ', ' (m) ' + !WRITE( UnSum, '(3(2X,F10.3))' ) COB(1) , COB(2) , COB(3) + + CALL MeshCreate( BlankMesh = WRP_Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ) + ! Create the node on the mesh + + CALL MeshPositionNode (WRP_Mesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat & + , ErrMsg & + ) + + IF ( ErrStat /= 0 ) RETURN + + + ! Create the mesh element + CALL MeshConstructElement ( WRP_Mesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , 1 & + ) + CALL MeshCommit ( WRP_Mesh & + , ErrStat & + , ErrMsg ) + + IF ( ErrStat /= ErrID_None ) RETURN + + ! we need the translation displacement mesh for loads transfer: + CALL MeshCopy ( SrcMesh = WRP_Mesh & + , DestMesh = WRP_Mesh_position & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_INPUT & + , TranslationDisp = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) ! automatically sets DestMesh%RemapFlag = .TRUE. + + IF ( ErrStat /= ErrID_None ) RETURN + WRP_Mesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + + WRP_Mesh%RemapFlag = .TRUE. + + + ! Attach the external distributed buoyancy loads to the distributed mesh so they can be transferred to the WRP + + ! Because of wave stretching and user-supplied waves, we may have loads above the still water line (SWL) which will be used + ! in the hydrodynamics for conditions where the wave height is > SWL. So we now need to check that the vertical position + ! is <= SWL for this summary file calculation. + + DO J = 1, outDistribMesh%Nnodes + if ( outDistribMesh%Position(3,J) <= MSL2SWL ) then + DO I=1,6 + + IF (I < 4 ) THEN + + outDistribMesh%Force(I ,J) = D_F_B(I,J) + + ELSE + + outDistribMesh%Moment(I-3,J) = D_F_B(I,J) + + END IF + + END DO ! DO I + end if ! <= MSL2SWL check + END DO ! DO J + + + ! Transfer the loads from the distributed mesh to the (0,0,0) point mesh + + CALL MeshMapCreate ( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg ) + !CALL CheckError( ErrStat, 'Message from MeshMapCreate HD_M_L_2_ED_P: '//NewLine//ErrMsg ) + CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + + ExtBuoyancy(1:3) = WRP_Mesh%Force (:,1) + ExtBuoyancy(4:6) = WRP_Mesh%Moment(:,1) + + + + ! Transfer the loads from the lumped mesh to the (0,0,0) point mesh + + ! Because of wave stretching and user-supplied waves, we may have loads above the still water line (SWL) which will be used + ! in the hydrodynamics for conditions where the wave height is > SWL. So we now need to check that the vertical position + ! is <= SWL for this summary file calculation. + + DO J = 1, outLumpedMesh%Nnodes + if ( outLumpedMesh%Position(3,J) <= MSL2SWL ) then + DO I=1,6 + + IF (I < 4 ) THEN + + outLumpedMesh%Force(I ,J) = L_F_B(I,J) + + ELSE + + outLumpedMesh%Moment(I-3,J) = L_F_B(I,J) + + END IF + + END DO ! DO I + end if ! <= MSL2SWL check + END DO ! DO J + + ! Remap for the lumped to WRP mesh transfer + WRP_Mesh%RemapFlag = .TRUE. + + CALL MeshMapCreate ( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg ) + CALL Transfer_Point_to_Point( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg, inLumpedMesh, WRP_Mesh_position ) + + ExtBuoyancy(1:3) = ExtBuoyancy(1:3) + WRP_Mesh%Force (:,1) + ExtBuoyancy(4:6) = ExtBuoyancy(4:6) + WRP_Mesh%Moment(:,1) + + + + ! Write the buoyancy table headers and the external results + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A45)' ) 'Buoyancy loads summed about ( 0.0, 0.0, 0.0 )' + WRITE( UnSum, '(A45)' ) '---------------------------------------------' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( UnSum, '(A18,6(2X,ES20.6))') 'External: ', ExtBuoyancy(1), ExtBuoyancy(2), ExtBuoyancy(3), ExtBuoyancy(4), ExtBuoyancy(5), ExtBuoyancy(6) + + + ! Now compute internal Buoyancy + + DO J = 1, outDistribMesh%Nnodes + + DO I=1,6 + + IF (I < 4 ) THEN + + outDistribMesh%Force(I,J ) = D_F_BF(I,J) + + ELSE + + outDistribMesh%Moment(I-3,J) = D_F_BF(I,J) + + END IF + + END DO ! DO I + + END DO ! DO J + + IntBuoyancy = 0.0 + CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + IntBuoyancy(1:3) = WRP_Mesh%Force(:,1) + IntBuoyancy(4:6) = WRP_Mesh%Moment(:,1) + + + DO J = 1, outLumpedMesh%Nnodes + + DO I=1,6 + + IF (I < 4 ) THEN + + outLumpedMesh%Force(I,J) = L_F_BF(I,J) + + ELSE + + outLumpedMesh%Moment(I-3,J) = L_F_BF(I,J) + + END IF + + END DO ! DO I + + END DO ! DO J + + CALL Transfer_Point_to_Point( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg, inLumpedMesh, WRP_Mesh_position ) + IntBuoyancy(1:3) = IntBuoyancy(1:3) + WRP_Mesh%Force(:,1) + IntBuoyancy(4:6) = IntBuoyancy(4:6) + WRP_Mesh%Moment(:,1) + + + ! clean up + + CALL MeshMapDestroy( M_P_2_P, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) + + WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Internal: ', IntBuoyancy(1), IntBuoyancy(2), IntBuoyancy(3), IntBuoyancy(4), IntBuoyancy(5), IntBuoyancy(6) + IntBuoyancy = IntBuoyancy + ExtBuoyancy + WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Total : ', IntBuoyancy(1), IntBuoyancy(2), IntBuoyancy(3), IntBuoyancy(4), IntBuoyancy(5), IntBuoyancy(6) + !WRITE( UnSum, '(/)' ) + WRITE( UnSum, '(A81)') ' NOTE: External buoyancy is based on members not modelled with WAMIT' + WRITE( UnSum, '(A150)') ' Internal buoyancy is computed from all members which are marked as filled in the HydroDyn input file, regardless of PropPot flag' + WRITE( UnSum, '(A88)') ' Total buoyancy does not include WAMIT-modelled buoyancy contribution' + + + + ! Now compute marine growth weight at the WRP + + DO J = 1, outDistribMesh%Nnodes + + DO I=1,6 + + IF (I < 4 ) THEN + + outDistribMesh%Force(I,J) = D_F_MG(I,J) + + ELSE + + outDistribMesh%Moment(I-3,J) = D_F_MG(I,J) + + END IF + + END DO ! DO I + + END DO ! DO J + + + MG_Wt = 0.0 + CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + MG_Wt(1:3) = WRP_Mesh%Force(:,1) + MG_Wt(4:6) = WRP_Mesh%Moment(:,1) + + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A36)' ) 'Weight loads about ( 0.0, 0.0, 0.0 )' + WRITE( UnSum, '(A36)' ) '------------------------------------' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' MGFxi ', ' MGFyi ', ' MGFzi ', ' MGMxi ', ' MGMyi ', ' MGMzi ' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Structure : ', M_Wt(1), M_Wt(2), M_Wt(3), M_Wt(4), M_Wt(5), M_Wt(6) + WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Marine Growth: ', MG_Wt(1), MG_Wt(2), MG_Wt(3), MG_Wt(4), MG_Wt(5), MG_Wt(6) + !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Filled Fluid : ', F_Wt(1), F_Wt(2), F_Wt(3), F_Wt(4), F_Wt(5), F_Wt(6) + !M_Wt = M_Wt + MG_Wt + F_Wt + !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Total : ', M_Wt(1), M_Wt(2), M_Wt(3), M_Wt(4), M_Wt(5), M_Wt(6) + + + CALL MeshMapDestroy( M_L_2_P, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy(WRP_Mesh, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy(WRP_Mesh_position, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) + + ! Write the header for this section + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A5)' ) 'Nodes' + WRITE( UnSum, '(/)' ) + WRITE( UnSum, '(1X,A5,24(2X,A10),2X,A5,2X,A15)' ) ' i ', 'JointIndx ', 'JointOvrlp', 'InpMbrIndx', ' Nxi ', ' Nyi ', ' Nzi ', 'InpMbrDist', ' R ', ' dRdZ ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', ' FillDens ', 'FillFSLoc ', ' Cd ', ' Ca ', ' Cp ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ', 'NConn ', 'Connection List' + WRITE( UnSum, '(1X,A5,24(2X,A10),2X,A5,2X,A15)' ) ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (m) ', ' (-) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' ' + + ! Write the data + DO I = 1,numNodes + WRITE(strFmt,'(I2)') nodes(I)%NConnections + IF ( nodes(I)%NodeType == 1 ) THEN + strNodeType = 'End ' + ELSE IF ( nodes(I)%NodeType == 2 ) THEN + strNodeType = 'Interior ' + ELSE IF ( nodes(I)%NodeType == 3 ) THEN + strNodeType = 'Super ' + ELSE + strNodeType = 'ERROR ' + END IF + + WRITE( UnSum, '(1X,I5,3(2X,I10),4(2X,F10.4),5(2X,ES10.3),2(2X,L10),10(2X,ES10.3),2X,I5,' // strFmt // '(2X,I4))' ) I, nodes(I)%JointIndx, nodes(I)%JointOvrlp, nodes(I)%InpMbrIndx, nodes(I)%JointPos, nodes(I)%InpMbrDist, nodes(I)%R, nodes(I)%DRDZ, nodes(I)%t, nodes(I)%tMG, nodes(I)%MGdensity, nodes(I)%PropPot, nodes(I)%FillFlag, nodes(I)%FillDensity, nodes(I)%FillFSLoc, nodes(I)%Cd, nodes(I)%Ca, nodes(I)%Cp, nodes(I)%AxCa, nodes(I)%AxCp, nodes(I)%JAxCd, nodes(I)%JAxCa, nodes(I)%JAxCp, nodes(I)%NConnections, nodes(I)%ConnectionList(1:nodes(I)%NConnections) + END DO + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A8)' ) 'Elements' + WRITE( UnSum, '(/)' ) + WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,13(2X,A12),2X,A12,21(2X,A12))' ) ' i ', 'node1','node2',' Length ', ' Volume ', ' MGVolume ', ' R1 ', ' tMG1 ', ' t1 ', ' R2 ', ' tMG2 ', ' t2 ', ' MGDens1 ', ' MGDens2 ', ' PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' Ca1 ', ' Cp1 ', ' AxCa1 ', ' AxCp1 ', ' JAxCd1 ', ' JAxCa1 ', ' JAxCp1 ', ' Cd2 ', ' Ca2 ', ' Cp2 ', ' AxCa2 ', ' AxCp2 ', ' JAxCd2 ', ' JAxCa2 ', ' JAxCp2 ' + WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,13(2X,A12),2X,A12,21(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (m^3) ', ' (m^3) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' + + + + + DO I = 1,numElements + + node1 = nodes(elements(I)%Node1Indx) + node2 = nodes(elements(I)%Node2Indx) + IF ( ( (node1%tMG > 0.0_ReKi ) .AND. EqualRealNos(node2%tMG,0.0_ReKi) ) .OR. ( (node2%tMG > 0.0_ReKi ) .AND. EqualRealNos(node1%tMG,0.0_ReKi) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'If one node of an element has MG, then both must. This is an internal code problem within HydroDyn.' + RETURN + END IF + CALL GetDistance( nodes(elements(I)%Node1Indx)%JointPos, nodes(elements(I)%Node2Indx)%JointPos, l ) + + + IF (elements(I)%PropPot) THEN + MGvolume = 0.0 + elementVol = 0.0 + ELSE + elementVol = ElementVolume(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, l) + MGvolume = elementVol - ElementVolume(elements(I)%R1, elements(I)%R2, l) + END IF + ! totalMGVol = totalMGVol + MGvolume + ! mass_MG = MGvolume*elements(I)%FillDens + ! totalMGMass = totalMGMass + mass_MG + CALL ElementCentroid(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, node1%JointPos, l, elements(I)%R_LToG, elemCentroid) + + ! COB = COB + elementVol*elemCentroid + + ! totalVol = totalVol + elementVol + + !IF ( node2%JointPos(3) <= MSL2SWL .AND. node1%JointPos(3) >= ) totalDisplVol = totalDisplVol + elementVol + + IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN + filledFlag = .TRUE. + !IF ( ( node2%JointPos(3) <= elements(I)%FillFSLoc ) .AND. ( node1%JointPos(3) <= elements(I)%FillFSLoc ) ) THEN + fillVol = ElementVolume(elements(I)%R1 - elements(I)%t1, elements(I)%R2 - elements(I)%t2, l) + ! totalFillVol = totalFillVol + fillVol + mass_fill = elements(I)%FillDens*fillVol + ! totalFillMass = totalFillMass + mass_fill + !END IF + ELSE + mass_fill = 0.0 + filledFlag = .FALSE. + END IF + + IF (EqualRealNos(node1%tMG,0.0_ReKi)) THEN + Cd1 = elements(I)%Cd1 + Cd2 = elements(I)%Cd2 + Ca1 = elements(I)%Ca1 + Ca2 = elements(I)%Ca2 + Cp1 = elements(I)%Cp1 + Cp2 = elements(I)%Cp2 + AxCa1 = elements(I)%AxCa1 + AxCa2 = elements(I)%AxCa2 + AxCp1 = elements(I)%AxCp1 + AxCp2 = elements(I)%AxCp2 + ELSE + Cd1 = elements(I)%CdMG1 + Cd2 = elements(I)%CdMG2 + Ca1 = elements(I)%CaMG1 + Ca2 = elements(I)%CaMG2 + Cp1 = elements(I)%CpMG1 + Cp2 = elements(I)%CpMG2 + AxCa1 = elements(I)%AxCaMG1 + AxCa2 = elements(I)%AxCaMG2 + AxCp1 = elements(I)%AxCpMG1 + AxCp2 = elements(I)%AxCpMG2 + END IF + + JAxCd1 = node1%JAxCd + JAxCa1 = node1%JAxCa + JAxCp1 = node1%JAxCp + JAxCd2 = node2%JAxCd + JAxCa2 = node2%JAxCa + JAxCp2 = node2%JAxCp + + WRITE( UnSum, '(1X,I5,2X,I5,2X,I5,11(2X,ES12.5),2(2X,L12),2X,ES12.5,21(2X,ES12.5))' ) I, & + elements(I)%Node1Indx, elements(I)%Node2Indx, l, elementVol, MGvolume, elements(I)%R1, & + node1%tMG, elements(I)%t1, elements(I)%R2, node2%tMG, elements(I)%t2, node1%MGdensity, node2%MGdensity, & + elements(I)%PropPot, filledFlag, elements(I)%FillDens, elements(I)%FillFSLoc, & + mass_fill, Cd1, Ca1, Cp1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & + Cd2, Ca2, Cp2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 + + END DO ! I = 1,numElements + + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A24)' ) 'Requested Member Outputs' + WRITE( UnSum, '(/)' ) + WRITE( UnSum, '(1X,A10,11(2X,A10))' ) ' Label ', ' Xi ', ' Yi ', ' Zi ', 'InpMbrIndx', ' StartXi ', ' StartYi ', ' StartZi ', ' EndXi ', ' EndYi ', ' EndZi ', ' Loc ' + WRITE( UnSum, '(1X,A10,11(2X,A10))' ) ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ' + + + DO I = 1,NOutputs + ! DO J=1, NMOutputs + !DO I=1, MOutLst(J)%NOutLoc + + + ! Get the member index and node index for this output label. If this is not a member output the indices will return 0 with no errcode. + ! CALL MrsnOut_GetMemberOutputInfo(WriteOutputHdr(I), NMOutputs, MOutLst, mbrIndx, nodeIndx, ErrStat, ErrMsg ) + ! IF (ErrStat >= AbortErrLev ) RETURN + ! IF ( mbrIndx > 0 ) THEN + tmpName = OutParam(I)%Name + IF (OutParam(I)%SignM == -1 ) tmpName = tmpName(2:10) + + IF ( ( INDEX( 'mM', tmpName(1:1) ) > 0 ) .AND. (OutParam(I)%Units /= 'INVALID' ) ) THEN + !Get Member index and Node index + read (tmpName(2:2),*) mbrIndx + read (tmpName(4:4),*) nodeIndx + + ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you want + ! to index into the nodes array or wave kinematics arrays + + m1 = MOutLst(mbrIndx)%Marker1(nodeIndx) + m2 = MOutLst(mbrIndx)%Marker2(nodeIndx) + s = MOutLst(mbrIndx)%s (nodeIndx) + + ! The member output is computed as a linear interpolation of the nearest two markers + node1 = nodes(distribToNodeIndx((m1))) + node2 = nodes(distribToNodeIndx((m2))) + + outLoc = node1%JointPos*(1-s) + node2%JointPos*s + WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10,7(2x,F10.4))' ) OutParam(I)%Name, outLoc, node1%InpMbrIndx, node1%JointPos, node2%JointPos, s + END IF + + ! END IF + !WRITE( UnSum, '(1X,A10,11(2X,ES10.3))' ) WriteOutputHdr(I) + ! END DO + END DO + + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A24)' ) 'Requested Joint Outputs' + WRITE( UnSum, '(/)' ) + WRITE( UnSum, '(1X,A10,5(2X,A10))' ) ' Label ', ' Xi ', ' Yi ', ' Zi ', 'InpJointID' + WRITE( UnSum, '(1X,A10,5(2X,A10))' ) ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ' + + + DO I = 1,NOutputs + ! DO J=1, NMOutputs + !DO I=1, MOutLst(J)%NOutLoc + + + ! Get the member index and node index for this output label. If this is not a member output the indices will return 0 with no errcode. + ! CALL MrsnOut_GetMemberOutputInfo(WriteOutputHdr(I), NMOutputs, MOutLst, mbrIndx, nodeIndx, ErrStat, ErrMsg ) + ! IF (ErrStat >= AbortErrLev ) RETURN + ! IF ( mbrIndx > 0 ) THEN + tmpName = OutParam(I)%Name + IF (OutParam(I)%SignM == -1 ) tmpName = tmpName(2:10) + + IF ( ( INDEX( 'jJ', tmpName(1:1) ) > 0 ) .AND. (OutParam(I)%Units /= 'INVALID') ) THEN + + !Get Member index and Node index + read (tmpName(2:2),*) nodeIndx + m1 = JOutLst(nodeIndx)%Markers(1) + WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10)' ) OutParam(I)%Name, nodes(m1)%JointPos, JOutLst(nodeIndx)%JointID + + END IF + + ! END IF + !WRITE( UnSum, '(1X,A10,11(2X,ES10.3))' ) WriteOutputHdr(I) + ! END DO + END DO + + END IF + +END SUBROUTINE WriteSummaryFile + +!==================================================================================================== +SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, numElements, node1, node2, originalElement, newNode, newElement, ErrStat, ErrMsg ) + !@mhall: This splits an element at a given global x, y, or z location? + + INTEGER, INTENT ( IN ) :: axis !@mhall: which axis to work with in calculating positions along element (global x,y, or z)? + REAL(ReKi), INTENT ( IN ) :: boundary !@mhall: [axis] coordinate of boundary? + INTEGER, INTENT ( IN ) :: iCurrentElement + INTEGER, INTENT ( INOUT ) :: numNodes + TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 !@mhall: element end nodes? + INTEGER, INTENT ( INOUT ) :: numElements + TYPE(Morison_MemberType), INTENT ( INOUT ) :: originalElement + TYPE(Morison_NodeType), INTENT ( OUT ) :: newNode + TYPE(Morison_MemberType), INTENT ( OUT ) :: newElement + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J + REAL(ReKi) :: s + INTEGER :: newNodeIndx, newElementIndx + + ErrStat = ErrID_None + ErrMsg = "" + + ! Create new node and element indices + newNodeIndx = numNodes + 1 + newElementIndx = numElements + 1 + + ! find normalized distance from 1nd node to the boundary + CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) + newNode = node1 ! copy all base node properties + + newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] + + !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates + DO I=axis,axis+1 + J = MOD(I,3) + 1 + newNode%JointPos(J) = node1%JointPos(J)*(1-s) + node2%JointPos(J)*s + END DO + + newNode%R_LToG = node1%R_LToG + ! Create the new node information. + ! Note that the caller will determine if this is an interior node (subdivide) or an endnode (split due to MG, MSL, seabed, filled free surface) + newNode%JointOvrlp = 0 + newNode%NConnections = 2 + newNode%ConnectionList(1) = iCurrentElement + newNode%ConnectionList(2) = newElementIndx + + + + ! Update node2 connectivity + DO I = 1,10 ! 10 is the maximum number of connecting elements for a node, this should probably be a parameter !! TODO + IF ( node2%ConnectionList(I) == iCurrentElement ) THEN + node2%ConnectionList(I) = newElementIndx + EXIT + END IF + END DO + + + ! Create the new element properties by first copying all the properties from the existing element + newElement = originalElement + ! Linearly interpolate the coef values based on depth + originalElement%R2 = originalElement%R1 * (1-s) + originalElement%R2*s + newElement%R1 = originalElement%R2 + originalElement%t2 = originalElement%t1 * (1-s) + originalElement%t2*s + originalElement%InpMbrDist2 = originalElement%InpMbrDist1 * (1-s) + originalElement%InpMbrDist2*s + newElement%t1 = originalElement%t2 + newElement%InpMbrDist1 = originalElement%InpMbrDist2 + + ! The end point of the new element is set to the original end point of the existing element, then + ! the starting point of the new element and the ending point of the existing element are set to the + ! newly created node + newElement%Node2Indx = originalElement%Node2Indx + originalElement%Node2Indx = newNodeIndx + newElement%Node1Indx = newNodeIndx + +END SUBROUTINE SplitElementOnZBoundary + + +!==================================================================================================== +!SUBROUTINE SplitElementsForMG(MGTop, MGBottom, numNodes, nodes, numElements, elements, ErrStat, ErrMsg) +! +! REAL(ReKi), INTENT ( IN ) :: MGTop +! REAL(ReKi), INTENT ( IN ) :: MGBottom +! INTEGER, INTENT ( INOUT ) :: numNodes +! TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) +! INTEGER, INTENT ( INOUT ) :: numElements +! TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) +! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs +! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! +! INTEGER :: I, J, K +! INTEGER :: node1Indx, node2Indx +! TYPE(Morison_NodeType) :: node1, node2, newNode, newNode2 +! TYPE(Morison_MemberType) :: element, newElement, newElement2 +! REAL(ReKi) :: zBoundary +! INTEGER :: origNumElements +! +! origNumElements = numElements +! +! DO I=1,origNumElements +! +! IF ( elements(I)%MGSplitState > 0 ) THEN +! +! node1Indx = elements(I)%Node1Indx +! node1 = nodes(node1Indx) +! node2Indx = elements(I)%Node2Indx +! node2 = nodes(node2Indx) +! element = elements(I) +! +! ! Intersects top boundary +! IF ( elements(I)%MGSplitState == 1 ) THEN +! zBoundary = MGTop +! ELSE ! Intersects the bottom boundary +! zBoundary = MGBottom +! END IF +! +! +! CALL SplitElementOnZBoundary( zBoundary, I, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) +! newNode%NodeType = 1 ! end node +! ! Update the number of nodes and elements by one each +! numNodes = numNodes + 1 +! newNode%JointIndx = numNodes +! numElements = numElements + 1 +! +! ! Copy the altered nodes and elements into the master arrays +! nodes(node1Indx) = node1 +! nodes(node2Indx) = node2 +! nodes(numNodes) = newNode +! elements(I) = element +! elements(numElements) = newElement +! +! ! If the original element spanned both marine growth boundaries, then we need to make an additional split +! IF ( elements(I)%MGSplitState == 3 ) THEN +! +! CALL SplitElementOnZBoundary( MGTop, numElements, numNodes, numElements, newNode, node2, newElement, newNode2, newElement2, ErrStat, ErrMsg ) +! newNode2%NodeType = 1 ! end node +! newNode2%JointIndx = numNodes + 1 +! ! Copy the altered nodes and elements into the master arrays +! nodes(numNodes) = newNode +! nodes(node2Indx) = node2 +! nodes(numNodes+1) = newNode2 +! elements(numElements) = newElement +! elements(numElements+1) = newElement2 +! +! ! Update the number of nodes and elements by one each +! numNodes = numNodes + 1 +! +! numElements = numElements + 1 +! +! END IF +! END IF +! END DO +!END SUBROUTINE SplitElementsForMG + +SUBROUTINE SplitElements(numNodes, nodes, numElements, elements, ErrStat, ErrMsg) + ! This splits all of the Morison elements according to already defined split locations, + ! adding resuling new nodes and elements to the respective master arrays. + + INTEGER, INTENT ( INOUT ) :: numNodes + TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) + INTEGER, INTENT ( INOUT ) :: numElements + TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J, iCurrent, nSplits !, K + REAL(ReKi) :: splits(5) + INTEGER :: node1Indx, node2Indx + TYPE(Morison_NodeType) :: node1, node2, newNode !, newNode2 + TYPE(Morison_MemberType) :: element, newElement !, newElement2 + REAL(ReKi) :: zBoundary + INTEGER :: origNumElements + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + origNumElements = numElements + + DO I=1,origNumElements + + IF ( elements(I)%NumSplits > 0 ) THEN + + + ! The splits are presorted from smallest Z to largest Z + nSplits = elements(I)%NumSplits + splits = elements(I)%Splits + iCurrent = I + + DO J=1,nSplits + + node1Indx = elements(iCurrent)%Node1Indx + node1 = nodes(node1Indx) + node2Indx = elements(iCurrent)%Node2Indx + node2 = nodes(node2Indx) + element = elements(iCurrent) + + CALL SplitElementOnZBoundary( 3, splits(J), iCurrent, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) + + ! Was this split due to the location of an elements free surface location crossing through the element? + IF ( element%MmbrFilledIDIndx /= -1 ) THEN + IF ( EqualRealNos(element%FillFSLoc, splits(J)) ) THEN + newElement%MmbrFilledIDIndx = -1 + END IF + END IF + + newNode%NodeType = 1 ! end node + ! Update the number of nodes and elements by one each + numNodes = numNodes + 1 + newNode%JointIndx = numNodes + numElements = numElements + 1 + + ! Copy the altered nodes and elements into the master arrays + !nodes(node1Indx) = node1 + nodes(node2Indx) = node2 + nodes(numNodes) = newNode + elements(iCurrent) = element + elements(numElements) = newElement + + + + ! now make element = newElement by setting iCurrent to numElements + iCurrent = numElements + + + END DO + + END IF + END DO +END SUBROUTINE SplitElements + +!==================================================================================================== +!SUBROUTINE SplitElementsForWtr(MSL2SWL, Zseabed, numNodes, nodes, numElements, elements, ErrStat, ErrMsg) +! +! REAL(ReKi), INTENT ( IN ) :: MSL2SWL +! REAL(ReKi), INTENT ( IN ) :: Zseabed +! INTEGER, INTENT ( INOUT ) :: numNodes +! TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) +! INTEGER, INTENT ( INOUT ) :: numElements +! TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) +! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs +! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! +! INTEGER :: I, J, K +! INTEGER :: node1Indx, node2Indx +! TYPE(Morison_NodeType) :: node1, node2, newNode, newNode2 +! TYPE(Morison_MemberType) :: element, newElement, newElement2 +! REAL(ReKi) :: zBoundary +! INTEGER :: origNumElements +! +! origNumElements = numElements +! +! DO I=1,origNumElements +! +! IF ( elements(I)%WtrSplitState > 0 ) THEN +! +! node1Indx = elements(I)%Node1Indx +! node1 = nodes(node1Indx) +! node2Indx = elements(I)%Node2Indx +! node2 = nodes(node2Indx) +! element = elements(I) +! +! ! Intersects top boundary +! IF ( elements(I)%WtrSplitState == 1 ) THEN +! zBoundary = MSL2SWL +! ELSE ! Intersects the bottom boundary +! zBoundary = Zseabed +! END IF +! +! +! CALL SplitElementOnZBoundary( zBoundary, I, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) +! newNode%NodeType = 1 ! end node +! ! Update the number of nodes and elements by one each +! numNodes = numNodes + 1 +! newNode%JointIndx = numNodes +! numElements = numElements + 1 +! +! ! Copy the altered nodes and elements into the master arrays +! nodes(node1Indx) = node1 +! nodes(node2Indx) = node2 +! nodes(numNodes) = newNode +! elements(I) = element +! elements(numElements) = newElement +! +! ! If the original element spanned both marine growth boundaries, then we need to make an additional split +! IF ( elements(I)%WtrSplitState == 3 ) THEN +! +! CALL SplitElementOnZBoundary( MSL2SWL, numElements, numNodes, numElements, newNode, node2, newElement, newNode2, newElement2, ErrStat, ErrMsg ) +! newNode2%NodeType = 1 ! end node +! newNode2%JointIndx = numNodes + 1 +! ! Copy the altered nodes and elements into the master arrays +! nodes(numNodes) = newNode +! nodes(node2Indx) = node2 +! nodes(numNodes+1) = newNode2 +! elements(numElements) = newElement +! elements(numElements+1) = newElement2 +! +! ! Update the number of nodes and elements by one each +! numNodes = numNodes + 1 +! +! numElements = numElements + 1 +! +! END IF +! END IF +! END DO +!END SUBROUTINE SplitElementsForWtr +!==================================================================================================== +SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, ErrMsg ) + ! This subdivides all of the (already-split) Morison elements according to each element's maximum desired + ! element length (MDivSize), adding resuling new nodes and elements to the respective master arrays. + + INTEGER, INTENT ( INOUT ) :: numNodes + TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) + INTEGER, INTENT ( INOUT ) :: numElements + TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + TYPE(Morison_NodeType) :: node1, node2, newNode + TYPE(Morison_MemberType) :: element, newElement + INTEGER :: numDiv + REAL(ReKi) :: divSize(3) + INTEGER :: I, J, K + REAL(ReKi) :: memLen ! Length of member [m] + INTEGER :: origNumElements + INTEGER :: node1Indx, node2Indx, elementIndx, axis + REAL(ReKi) :: start, Loc + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + origNumElements = numElements + + DO I=1,origNumElements + + CALL Morison_CopyMemberType( elements(I), element, MESH_NEWCOPY, ErrStat, ErrMsg ) ! element = elements(I); bjj: I'm replacing the "equals" here with the copy routine, + ! though at this point there are no allocatable/pointer fields in this type so no harm done. + ! mostly for me to remember that when Inspector complains about uninitialized values, it's + ! because not all *fields* have been initialized. + node1Indx = element%Node1Indx + CALL Morison_CopyNodeType( nodes(node1Indx), node1, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node1 = nodes(node1Indx); bjj: note that not all fields have been initialized, but maybe that's okay. + + node2Indx = element%Node2Indx ! We need this index for the last sub-element + CALL Morison_CopyNodeType( nodes(node2Indx), node2, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node2 = nodes(node2Indx); bjj: note that not all fields have been initialized, but maybe that's okay. + + elementIndx = I + + + CALL GetDistance(node1%JointPos, node2%JointPos, memLen) ! Calculate member length. + + + ! If the requested division size is less then the member length, we will subdivide the member + + IF ( element%MDivSize < memLen ) THEN + + ! Ensure a safe choice of x/y/z axis to use for splitting. + IF ( .NOT. ( EqualRealNos( node2%JointPos(3) , node1%JointPos(3) ) ) ) THEN + axis = 3 + ELSE IF ( .NOT. ( EqualRealNos( node2%JointPos(2) , node1%JointPos(2) ) ) ) THEN + axis = 2 + ELSE IF ( .NOT. ( EqualRealNos( node2%JointPos(1) , node1%JointPos(1) ) ) ) THEN + axis = 1 + ELSE + ! ERROR + END IF + + start = node1%JointPos(axis) + numDiv = CEILING( memLen / element%MDivSize ) + + DO K=1,3 + divSize(K) = (node2%JointPos(K) - node1%JointPos(K)) / numDiv + END DO + + DO J=1,numDiv - 1 + + loc = start + divSize(axis)*J + CALL SplitElementOnZBoundary( axis, loc, elementIndx, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) + newNode%NodeType = 2 ! interior node + newNode%JointIndx = -1 + ! Copy updated node and element information to the nodes and elements arrays + nodes(node1Indx) = node1 ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + nodes(node2Indx) = node2 ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + numNodes = numNodes + 1 + numElements = numElements + 1 + nodes(numNodes) = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + elements(elementIndx) = element ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + elements(numElements) = newElement ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + + node1 = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + element = newElement ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + node1Indx = numNodes + elementIndx = numElements + + + + + + ! Create a new node + !newNode = node2 + ! + !DO K=1,3 + ! newNode%JointPos = node1%JointPos(K) + divSize(K)*J + !END DO + ! + !numNodes = numNodes + 1 + !element%Node2Indx = numNodes + !nodes(numNodes) = newNode + ! + ! ! Create a new element + !newElement = element + !newElement%Node1Indx = numNodes + !element = newElement + !numElements = numElements + 1 + END DO + + !element%Node2Indx = node2Indx + + END IF + + END DO + + +END SUBROUTINE SubdivideMembers + +SUBROUTINE CreateSuperMembers( ) + + + + ! Determine if any of the joints flagged for overlap elimination (super member creation) satisfy the necessary requirements + !IF ( InitInp%NJoints > 0 ) THEN + ! + ! DO I = 1,InitInp%NJoints + ! + ! ! Check #1 are there more than 2 members connected to the joint? + ! IF ( InitInp%InpJoints(I)%JointOvrlp == 1 .AND. InitInp%InpJoints(I)%NConnections > 2) THEN + ! ! Check #2 are there two members whose local z-axis are the same? + ! CALL Get180Members(joint, InitInp%Joints, InitInp%Members, member1, member2) + ! + ! !zVect1 + ! !zVect2 + ! !dot(zVect1, zVect2) + ! + ! END IF + ! + ! + ! END DO + ! + ! + !END IF + + +END SUBROUTINE CreateSuperMembers + + +!==================================================================================================== +SUBROUTINE SetDepthBasedCoefs( z, NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) + + REAL(ReKi), INTENT ( IN ) :: z + INTEGER, INTENT (IN ) :: NCoefDpth + TYPE(Morison_CoefDpths), INTENT (IN ) :: CoefDpths(:) + REAL(ReKi), INTENT ( OUT) :: Cd + REAL(ReKi), INTENT ( OUT) :: CdMG + REAL(ReKi), INTENT ( OUT) :: Ca + REAL(ReKi), INTENT ( OUT) :: CaMG + REAL(ReKi), INTENT ( OUT) :: Cp + REAL(ReKi), INTENT ( OUT) :: CpMG + REAL(ReKi), INTENT ( OUT) :: AxCa + REAL(ReKi), INTENT ( OUT) :: AxCaMG + REAL(ReKi), INTENT ( OUT) :: AxCp + REAL(ReKi), INTENT ( OUT) :: AxCpMG + + INTEGER :: I, indx1, indx2 + REAL(ReKi) :: dd, s + LOGICAL :: foundLess + + + ! Find the table entry(ies) which match the node's depth value + ! The assumption here is that the depth table is stored from largest + ! to smallest in depth + + foundLess = .FALSE. + indx1 = 1 + indx2 = 1 + + DO I = 1, NCoefDpth + IF ( CoefDpths(I)%Dpth <= z .AND. .NOT. foundLess ) THEN + indx1 = I + foundLess = .TRUE. + END IF + IF ( CoefDpths(I)%Dpth >= z ) THEN + indx2 = I + END IF + + END DO + + ! Linearly interpolate the coef values based on depth + !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) + + dd = CoefDpths(indx1)%Dpth - CoefDpths(indx2)%Dpth + IF ( EqualRealNos(dd, 0.0_ReKi) ) THEN + s = 0 + ELSE + s = ( CoefDpths(indx1)%Dpth - z ) / dd + END IF + + Cd = CoefDpths(indx1)%DpthCd*(1-s) + CoefDpths(indx2)%DpthCd*s + Ca = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthCa*s + Cp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthCp*s + AxCa = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthAxCa*s + AxCp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthAxCp*s + CdMG = CoefDpths(indx1)%DpthCdMG*(1-s) + CoefDpths(indx2)%DpthCdMG*s + CaMG = CoefDpths(indx1)%DpthCaMG*(1-s) + CoefDpths(indx2)%DpthCaMG*s + CpMG = CoefDpths(indx1)%DpthCpMG*(1-s) + CoefDpths(indx2)%DpthCpMG*s + AxCaMG = CoefDpths(indx1)%DpthAxCaMG*(1-s) + CoefDpths(indx2)%DpthAxCaMG*s + AxCpMG = CoefDpths(indx1)%DpthAxCpMG*(1-s) + CoefDpths(indx2)%DpthAxCpMG*s + +END SUBROUTINE SetDepthBasedCoefs + + +!==================================================================================================== +SUBROUTINE SetSplitNodeProperties( numNodes, nodes, numElements, elements, ErrStat, ErrMsg ) +! This private subroutine generates the properties of nodes after the mesh has been split +! the input data. +!---------------------------------------------------------------------------------------------------- + + INTEGER, INTENT ( IN ) :: numNodes + INTEGER, INTENT ( IN ) :: numElements + TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) + TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + INTEGER :: I + TYPE(Morison_MemberType) :: element + REAL(ReKi) :: dR, dz +! REAL(ReKi) :: DirCos(3,3) + + ErrStat = ErrID_None + ErrMsg = "" + + + DO I=1,numNodes + + IF ( nodes(I)%NodeType /= 3 ) THEN + + ! End point or internal member node + ! Super member nodes already have their properties set + + + !element = elements(nodes(I)%ConnectionList(1)) + + ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array + + ! CALL Morison_DirCosMtrx( nodes(element%Node1Indx)%JointPos, nodes(element%Node2Indx)%JointPos, elements(nodes(I)%ConnectionList(1))%R_LToG ) + + element = elements(nodes(I)%ConnectionList(1)) + + nodes(I)%R_LToG = element%R_LToG + + nodes(I)%InpMbrIndx = element%InpMbrIndx + IF ( .NOT. ( ( nodes(element%Node1Indx)%tMG > 0 ) .AND. ( nodes(element%Node2Indx)%tMG > 0 ) .AND. (.NOT. element%PropPot) ) ) THEN + nodes(element%Node1Indx)%tMG = 0.0 + nodes(element%Node2Indx)%tMG = 0.0 + nodes(element%Node1Indx)%MGdensity = 0.0 + nodes(element%Node2Indx)%MGdensity = 0.0 + END IF + + !@mhall: if this node is Node 1 of the element in question... ? + IF ( element%Node1Indx == I ) THEN + + IF ( nodes(I)%tMG > 0 ) THEN + nodes(I)%Cd = element%CdMG1 + nodes(I)%Ca = element%CaMG1 + nodes(I)%Cp = element%CpMG1 + nodes(I)%AxCa = element%AxCaMG1 + nodes(I)%AxCp = element%AxCpMG1 + ELSE + nodes(I)%Cd = element%Cd1 + nodes(I)%Ca = element%Ca1 + nodes(I)%Cp = element%Cp1 + nodes(I)%AxCa = element%AxCa1 + nodes(I)%AxCp = element%AxCp1 + END IF + + nodes(I)%R = element%R1 + nodes(I)%t = element%t1 + nodes(I)%InpMbrDist = element%InpMbrDist1 + + !@mhall: otherwise this must be Node 2 of the element in question? + ELSE + + IF ( nodes(I)%tMG > 0 ) THEN + nodes(I)%Cd = element%CdMG2 + nodes(I)%Ca = element%CaMG2 + nodes(I)%Cp = element%CpMG2 + nodes(I)%AxCa = element%AxCaMG2 + nodes(I)%AxCp = element%AxCpMG2 + ELSE + nodes(I)%Cd = element%Cd2 + nodes(I)%Ca = element%Ca2 + nodes(I)%Cp = element%Cp2 + nodes(I)%AxCa = element%AxCa2 + nodes(I)%AxCp = element%AxCp2 + END IF + + nodes(I)%R = element%R2 + nodes(I)%t = element%t2 + nodes(I)%InpMbrDist = element%InpMbrDist2 + END IF + + CALL GetDistance( nodes(element%Node1Indx)%JointPos, nodes(element%Node2Indx)%JointPos, dz ) + dR = ( element%R2 + nodes(element%Node2Indx)%tMG ) - ( element%R1 + nodes(element%Node1Indx)%tMG ) + IF ( EqualRealNos(dR, 0.0_ReKi) ) dR = 0.0 + IF ( EqualRealNos(dz, 0.0_ReKi) ) THEN + nodes(I)%dRdz = 0.0 + ELSE + nodes(I)%dRdz = dR / dz + END IF + + nodes(I)%PropPot = element%PropPot + + IF ( element%MmbrFilledIDIndx /= -1 ) THEN + nodes(I)%FillFlag = .TRUE. + nodes(I)%FillFSLoc = element%FillFSLoc ! This is relative to the MSL. + nodes(I)%FillDensity = element%FillDens + + ELSE + nodes(I)%FillFSLoc = 0.0 ! This is the MSL. + nodes(I)%FillDensity = 0.0 + elements(nodes(I)%ConnectionList(1))%FillDens = 0.0 + elements(nodes(I)%ConnectionList(1))%FillFSLoc = 0.0 + END IF + + + + + END IF + +END DO + +END SUBROUTINE SetSplitNodeProperties + + +!==================================================================================================== +!SUBROUTINE SetMemberCoefs( SimplCd, SimplCdMG, SimplCa, SimplCaMG, CoefMembers, NCoefDpth, CoefDpths, element, node1, node2 ) +SUBROUTINE SetElementCoefs( SimplCd, SimplCdMG, SimplCa, SimplCaMG, SimplCp, SimplCpMG, SimplAxCa, SimplAxCaMG, SimplAxCp, SimplAxCpMG,CoefMembers, NCoefDpth, CoefDpths, numNodes, nodes, numElements, elements ) +! This private subroutine generates the Cd, Ca, Cp, CdMG, CaMG and CpMG coefs for the member based on +! the input data. +!---------------------------------------------------------------------------------------------------- + + REAL(ReKi), INTENT( IN ) :: SimplCd + REAL(ReKi), INTENT( IN ) :: SimplCdMG + REAL(ReKi), INTENT( IN ) :: SimplCa + REAL(ReKi), INTENT( IN ) :: SimplCaMG + REAL(ReKi), INTENT( IN ) :: SimplCp + REAL(ReKi), INTENT( IN ) :: SimplCpMG + REAL(ReKi), INTENT( IN ) :: SimplAxCa + REAL(ReKi), INTENT( IN ) :: SimplAxCaMG + REAL(ReKi), INTENT( IN ) :: SimplAxCp + REAL(ReKi), INTENT( IN ) :: SimplAxCpMG + TYPE(Morison_CoefMembers), allocatable, INTENT( IN ) :: CoefMembers(:) + INTEGER, INTENT( IN ) :: NCoefDpth + TYPE(Morison_CoefDpths), allocatable, INTENT( IN ) :: CoefDpths(:) + INTEGER, INTENT( IN ) :: numNodes + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) + TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) + + TYPE(Morison_NodeType) :: node1, node2 + + INTEGER :: MCoefMod + INTEGER :: I, J + REAL(ReKi) :: Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCp, AxCaMG, AxCpMG + DO I=1,numElements + + + MCoefMod = elements(I)%MCoefMod + node1 = nodes(elements(I)%Node1Indx) + node2 = nodes(elements(I)%Node2Indx) + + SELECT CASE ( MCoefMod ) + + CASE (1) + + elements(I)%Cd1 = SimplCd + elements(I)%Cd2 = SimplCd + elements(I)%Ca1 = SimplCa + elements(I)%Ca2 = SimplCa + elements(I)%Cp1 = SimplCp + elements(I)%Cp2 = SimplCp + elements(I)%AxCa1 = SimplAxCa + elements(I)%AxCa2 = SimplAxCa + elements(I)%AxCp1 = SimplAxCp + elements(I)%AxCp2 = SimplAxCp + elements(I)%CdMG1 = SimplCdMG + elements(I)%CdMG2 = SimplCdMG + elements(I)%CaMG1 = SimplCaMG + elements(I)%CaMG2 = SimplCaMG + elements(I)%CpMG1 = SimplCpMG + elements(I)%CpMG2 = SimplCpMG + elements(I)%AxCaMG1 = SimplAxCaMG + elements(I)%AxCaMG2 = SimplAxCaMG + elements(I)%AxCpMG1 = SimplAxCpMG + elements(I)%AxCpMG2 = SimplAxCpMG + + CASE (2) + + CALL SetDepthBasedCoefs( node1%JointPos(3), NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) + elements(I)%Cd1 = Cd + elements(I)%Ca1 = Ca + elements(I)%Cp1 = Cp + elements(I)%AxCa1 = AxCa + elements(I)%AxCp1 = AxCp + elements(I)%CdMG1 = CdMG + elements(I)%CaMG1 = CaMG + elements(I)%CpMG1 = CpMG + elements(I)%AxCaMG1 = AxCaMG + elements(I)%AxCpMG1 = AxCpMG + + CALL SetDepthBasedCoefs( node2%JointPos(3), NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) + elements(I)%Cd2 = Cd + elements(I)%Ca2 = Ca + elements(I)%Cp2 = Cp + elements(I)%AxCa2 = Ca + elements(I)%AxCp2 = Cp + elements(I)%CdMG2 = CdMG + elements(I)%CaMG2 = CaMG + elements(I)%CpMG2 = CpMG + elements(I)%AxCaMG2 = AxCaMG + elements(I)%AxCpMG2 = AxCpMG + + CASE (3) + + J = elements(I)%MmbrCoefIDIndx + elements(I)%Cd1 = CoefMembers(J)%MemberCd1 + elements(I)%Cd2 = CoefMembers(J)%MemberCd2 + elements(I)%Ca1 = CoefMembers(J)%MemberCa1 + elements(I)%Ca2 = CoefMembers(J)%MemberCa2 + elements(I)%Cp1 = CoefMembers(J)%MemberCp1 + elements(I)%Cp2 = CoefMembers(J)%MemberCp2 + elements(I)%AxCa1 = CoefMembers(J)%MemberAxCa1 + elements(I)%AxCa2 = CoefMembers(J)%MemberAxCa2 + elements(I)%AxCp1 = CoefMembers(J)%MemberAxCp1 + elements(I)%AxCp2 = CoefMembers(J)%MemberAxCp2 + elements(I)%CdMG1 = CoefMembers(J)%MemberCdMG1 + elements(I)%CdMG2 = CoefMembers(J)%MemberCdMG2 + elements(I)%CaMG1 = CoefMembers(J)%MemberCaMG1 + elements(I)%CaMG2 = CoefMembers(J)%MemberCaMG2 + elements(I)%CpMG1 = CoefMembers(J)%MemberCpMG1 + elements(I)%CpMG2 = CoefMembers(J)%MemberCpMG2 + elements(I)%AxCaMG1 = CoefMembers(J)%MemberAxCaMG1 + elements(I)%AxCaMG2 = CoefMembers(J)%MemberAxCaMG2 + elements(I)%AxCpMG1 = CoefMembers(J)%MemberAxCpMG1 + elements(I)%AxCpMG2 = CoefMembers(J)%MemberAxCpMG2 + + END SELECT + + + END DO + +END SUBROUTINE SetElementCoefs + + +SUBROUTINE SetAxialCoefs( NJoints, NAxCoefs, AxialCoefs, numNodes, nodes, numElements, elements ) + + INTEGER, INTENT( IN ) :: NJoints + INTEGER, INTENT( IN ) :: NAxCoefs + TYPE(Morison_AxialCoefType),INTENT( IN ) :: AxialCoefs(:) + INTEGER, INTENT( IN ) :: numNodes + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) + TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) + + ! TYPE(Morison_NodeType) :: node1, node2 + + INTEGER :: I !, J + + DO I=1,numNodes + + IF ( nodes(I)%JointAxIDIndx > 0 .AND. nodes(I)%JointIndx > 0 .AND. nodes(I)%JointIndx <= NJoints) THEN + nodes(I)%JAxCd = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCd + nodes(I)%JAxCa = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCa + nodes(I)%JAxCp = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCp + ELSE ! These are end nodes that were generated by the software, and hence do not have lumped axial loads, or they are interior nodes. + nodes(I)%JAxCd = 0.0 + nodes(I)%JAxCa = 0.0 + nodes(I)%JAxCp = 0.0 + END IF + + !node1 = nodes(elements(I)%Node1Indx) + !node2 = nodes(elements(I)%Node2Indx) + + END DO + +END SUBROUTINE SetAxialCoefs + + +SUBROUTINE SetNodeMG( numMGDepths, MGDepths, numNodes, nodes ) + + INTEGER, INTENT( IN ) :: numMGDepths + TYPE(Morison_MGDepthsType), allocatable, INTENT( IN ) :: MGDepths(:) + INTEGER, INTENT( IN ) :: numNodes + TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) + + INTEGER :: I, J + REAL(ReKi) :: z + INTEGER :: indx1, indx2 + REAL(ReKi) :: dd, s + LOGICAL :: foundLess = .FALSE. + + DO I=1,numNodes + + !Find the table entry(ies) which match the node's depth value + ! The assumption here is that the depth table is stored from largest + ! to smallest in depth + z = nodes(I)%JointPos(3) + foundLess = .FALSE. + indx1 = 0 + indx2 = 0 + DO J = 1, numMGDepths + IF ( MGDepths(J)%MGDpth <= z .AND. .NOT. foundLess ) THEN + indx1 = J + + foundLess = .TRUE. + END IF + IF ( MGDepths(J)%MGDpth >= z ) THEN + indx2 = J + END IF + + END DO + IF ( indx2 == 0 .OR. .NOT. foundLess ) THEN + !Not at a marine growth depth + nodes(I)%tMG = 0.0 + nodes(I)%MGdensity = 0.0 + ELSE + ! Linearly interpolate the coef values based on depth + !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) + + dd = MGDepths(indx1)%MGDpth - MGDepths(indx2)%MGDpth + IF ( EqualRealNos(dd, 0.0_ReKi) ) THEN + s = 0.0_ReKi + ELSE + s = ( MGDepths(indx1)%MGDpth - z ) / dd + END IF + nodes(I)%tMG = MGDepths(indx1)%MGThck*(1-s) + MGDepths(indx2)%MGThck*s + nodes(I)%MGdensity = MGDepths(indx1)%MGDens*(1-s) + MGDepths(indx2)%MGDens*s + END IF + + END DO + + +END SUBROUTINE SetNodeMG + + + +SUBROUTINE SetElementFillProps( numFillGroups, filledGroups, numElements, elements ) + + INTEGER, INTENT( IN ) :: numFillGroups + TYPE(Morison_FilledGroupType), allocatable, INTENT( IN ) :: filledGroups(:) ! this might not be allocated on entry + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) + + INTEGER :: I !, J + + DO I=1,numElements + + + IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN + + elements(I)%FillDens = filledGroups(elements(I)%MmbrFilledIDIndx)%FillDens + elements(I)%FillFSLoc = filledGroups(elements(I)%MmbrFilledIDIndx)%FillFSLoc + ELSE + elements(I)%FillDens = 0.0 + elements(I)%FillFSLoc = 0.0 + END IF + + + + END DO + + +END SUBROUTINE SetElementFillProps + +!SUBROUTINE CreateLumpedMarkers( numNodes, nodes, numElements, elements, numLumpedMarkers, lumpedMarkers, ErrStat, ErrMsg ) +! +! INTEGER, INTENT( IN ) :: numNodes +! INTEGER, INTENT( IN ) :: numElements +! TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) +! TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) +! INTEGER, INTENT( OUT ) :: numLumpedMarkers +! TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: lumpedMarkers(:) +! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs +! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! +! INTEGER :: I, J, count +! TYPE(Morison_MemberType) :: element +! +! numLumpedMarkers = 0 +! +! ! Count how many distributed markers we need to create by looping over the nodes +! DO I=1,numNodes +! IF ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) THEN +! ! end of a member that was not a part of super member creation +! numLumpedMarkers = numLumpedMarkers + 1 +! END IF +! END DO +! +! ! Allocate the array for the distributed markers +! ALLOCATE ( lumpedMarkers(numLumpedMarkers), STAT = ErrStat ) +! IF ( ErrStat /= ErrID_None ) THEN +! ErrMsg = ' Error allocating space for the lumped load markers array.' +! ErrStat = ErrID_Fatal +! RETURN +! END IF +! count = 1 +! DO I=1,numNodes +! +! IF ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0) THEN +! +! element = elements(nodes(I)%ConnectionList(1)) +! +! IF ( element%Node1Indx == I ) THEN +! lumpedMarkers(count)%Cd = element%Cd1 +! lumpedMarkers(count)%CdMG = element%CdMG1 +! lumpedMarkers(count)%Ca = element%Ca1 +! lumpedMarkers(count)%CaMG = element%CaMG1 +! lumpedMarkers(count)%R = element%R1 +! lumpedMarkers(count)%t = element%t1 +! ELSE +! lumpedMarkers(count)%Cd = element%Cd2 +! lumpedMarkers(count)%CdMG = element%CdMG2 +! lumpedMarkers(count)%Ca = element%Ca2 +! lumpedMarkers(count)%CaMG = element%CaMG2 +! lumpedMarkers(count)%R = element%R2 +! lumpedMarkers(count)%t = element%t2 +! END IF +! +! lumpedMarkers(count)%PropPot = element%PropPot +! lumpedMarkers(count)%tMG = nodes(I)%tMG +! lumpedMarkers(count)%MGdensity = nodes(I)%MGdensity +! +! +! ! Compute all initialization forces now so we have access to the element information +! +! !IF ( element%PropPot == .FALSE. ) THEN +! ! +! ! ! Member is not modeled with WAMIT +! ! CALL LumpedBuoyancy( ) +! ! CALL LumpedMGLoads( ) +! ! CALL LumpedDynPressure( ) +! ! CALL LumpedAddedMass( ) +! ! CALL LumpedAddedMassMG( ) +! ! CALL LumpedAddedMassFlood( ) ! Do we actually compute this??? TODO +! ! +! !END IF +! ! +! ! ! These are the only two loads we compute at initialization if the member is modeled with WAMIT +! !CALL LumpedDragConst( ) +! !CALL LumpedFloodedBuoyancy( ) +! +! +! count = count + 1 +! +! END IF +! +! END DO +! +!END SUBROUTINE CreateLumpedMarkers + + +SUBROUTINE SplitMeshNodes( numNodes, nodes, numElements, elements, numSplitNodes, splitNodes, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: numNodes + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) + TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) + INTEGER, INTENT( OUT ) :: numSplitNodes + TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: splitNodes(:) + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J, splitNodeIndx +! TYPE(Morison_MemberType) :: element + TYPE(Morison_NodeType) :: node1, node2, newNode + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + numSplitNodes = 0 + + ! Count how many distributed markers we need to create by looping over the nodes + DO I=1,numNodes + IF ( nodes(I)%NodeType == 1 ) THEN + ! Nodes at the end of members get one node for each connecting member + numSplitNodes = numSplitNodes + nodes(I)%NConnections + ELSE + ! Internal nodes and super member nodes only get one node + numSplitNodes = numSplitNodes + 1 + END IF + END DO + + ! Allocate the array for the distributed markers + ALLOCATE ( splitNodes(numSplitNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for split nodes array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + splitNodes(1:numNodes) = nodes(1:numNodes) + + IF ( numSplitNodes > numNodes ) THEN + + splitNodeIndx = numNodes + 1 + + DO I=1,numElements + ! Loop over elements in the processed mesh and create additional nodes/markers at the end of elements if that node connects to other elements + node1 = splitnodes(elements(I)%Node1Indx) + node2 = splitnodes(elements(I)%Node2Indx) + + IF (node1%NodeType == 1 ) THEN ! end node + IF ( node1%NConnections > 1 ) THEN + !create new node by copying the old one + newNode = node1 + newNode%NConnections = 1 + splitnodes(splitNodeIndx) = newNode + splitnodes(elements(I)%Node1Indx)%NConnections = node1%NConnections - 1 + !set the new node as the first node of this element + elements(I)%Node1Indx = splitNodeIndx + splitNodeIndx = splitNodeIndx + 1 + !NOTE: the node connection list entries are now bogus!!!! + END IF + + END IF + + IF (node2%NodeType == 1 ) THEN ! end node + IF ( node2%NConnections > 1 ) THEN + !create new node by copying the old one + newNode = node2 + newNode%NConnections = 1 + splitnodes(splitNodeIndx) = newNode + splitnodes(elements(I)%Node2Indx)%NConnections = node2%NConnections - 1 + !set the new node as the first node of this element + elements(I)%Node2Indx = splitNodeIndx + splitNodeIndx = splitNodeIndx + 1 + !NOTE: the node connection list entries are now bogus!!!! + END IF + + END IF + + END DO + + ! Fix connections + DO J = 1,numSplitNodes + splitnodes(J)%NConnections = 0 + END DO + + DO I = 1,numElements + + + DO J = 1,numSplitNodes + IF ( elements(I)%Node1Indx == J ) THEN + splitnodes(J)%NConnections = splitnodes(J)%NConnections + 1 + splitnodes(J)%ConnectionList(splitnodes(J)%NConnections) = I + END IF + IF ( elements(I)%Node2Indx == J ) THEN + splitnodes(J)%NConnections = splitnodes(J)%NConnections + 1 + splitnodes(J)%ConnectionList(splitnodes(J)%NConnections) = I + END IF + END DO + END DO + + END IF + +END SUBROUTINE SplitMeshNodes + + + +SUBROUTINE GenerateLumpedLoads( nodeIndx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: nodeIndx + REAL(ReKi), INTENT( IN ) :: sgn + TYPE(Morison_NodeType), INTENT( IN ) :: node + REAL(ReKi), INTENT( IN ) :: gravity + REAL(ReKi), INTENT( IN ) :: MSL2SWL + REAL(ReKi), INTENT( IN ) :: densWater + INTEGER, INTENT( IN ) :: NStepWave + REAL(SiKi), INTENT( IN ) :: WaveDynP(:,:) ! TODO: Verify it is ok to use (:,:) for the zero-based first array index GJH 2/5/14 + REAL(ReKi),ALLOCATABLE, INTENT( OUT ) :: F_DP(:,:) + REAL(ReKi), INTENT( OUT ) :: F_B(6) + REAL(ReKi), INTENT( OUT ) :: dragConst + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi) :: k(3) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + IF (.NOT. node%PropPot ) THEN + + k = sgn * node%R_LToG(:,3) + + CALL LumpDynPressure( nodeIndx, node%JAxCp, k, node%R, node%tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg) + + ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. + ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) + CALL LumpBuoyancy( sgn, densWater, node%R, node%tMG, node%JointPos(3) - MSL2SWL, node%R_LToG, gravity, F_B ) + + + ! This one is tricky because we need to calculate a signed volume which is the signed sum of all connecting elements and then split the + ! result across all the connecting nodes. + !CALL LumpAddedMass() + + ELSE + + ALLOCATE ( F_DP(0:NStepWave, 6), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating distributed dynamic pressure loads array.' + ErrStat = ErrID_Fatal + RETURN + END IF + F_DP = 0.0 + F_B = 0.0 + END IF + + + CALL LumpDragConst( densWater, node%Cd, node%R, node%tMG, dragConst ) + + + + +END SUBROUTINE GenerateLumpedLoads + + + +SUBROUTINE CreateLumpedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWave, WaveDynP, WaveAcc, numNodes, nodes, numElements, elements, & + numLumpedMarkers, lumpedMeshIn, lumpedMeshOut, lumpedToNodeIndx, L_An, & + L_F_B, L_F_I, L_F_BF, L_AM_M, L_dragConst, & + ErrStat, ErrMsg ) + + REAL(ReKi), INTENT( IN ) :: densWater + REAL(ReKi), INTENT( IN ) :: gravity + REAL(ReKi), INTENT( IN ) :: MSL2SWL + REAL(ReKi), INTENT( IN ) :: wtrDpth + INTEGER, INTENT( IN ) :: NStepWave + REAL(SiKi), INTENT( IN ) :: WaveDynP(0:,:) + REAL(SiKi), INTENT( IN ) :: WaveAcc(0:,:,:) + INTEGER, INTENT( IN ) :: numNodes + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) + TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) + INTEGER, INTENT( OUT ) :: numLumpedMarkers + !TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: lumpedMarkers(:) + TYPE(MeshType), INTENT( OUT ) :: lumpedMeshIn + TYPE(MeshType), INTENT( OUT ) :: lumpedMeshOut + INTEGER, ALLOCATABLE, INTENT( OUT ) :: lumpedToNodeIndx(:) + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_An(:,:) ! The signed/summed end cap Area x k of all connected members at a common joint + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_B(:,:) ! Buoyancy force associated with the member + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_I(:,:,:) ! Inertial force. TODO: Eventually the dynamic pressure will be included in this force! GJH 4/15/14 + !REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_DP(:,:,:) ! Dynamic pressure force + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_BF(:,:) ! Flooded buoyancy force + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_AM_M(:,:,:) ! Added mass of member + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_dragConst(:) ! + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + INTEGER :: I, J, M, count + TYPE(Morison_MemberType) :: element + TYPE(Morison_NodeType) :: node, node1, node2 + REAL(ReKi) :: L, sgn +! REAL(ReKi) :: k(3) + REAL(ReKi) :: z0 + REAL(ReKi),ALLOCATABLE :: F_DP(:,:) + REAL(ReKi) :: F_B(6) + REAL(ReKi) :: F_BF(6) + REAL(ReKi) :: Vmat(3,1), F_I(6), AM_M(6,6) !AM(6,6), + REAL(ReKi) :: dragConst + + + INTEGER, ALLOCATABLE :: nodeToLumpedIndx(:) + INTEGER, ALLOCATABLE :: commonNodeLst(:) + LOGICAL, ALLOCATABLE :: usedJointList(:) + INTEGER :: nCommon +! REAL(ReKi) :: CA + REAL(ReKi) :: AMfactor + REAL(ReKi) :: An(3), Vn(3), af(3) +! REAL(ReKi) :: AM11, AM22, AM33 + REAL(ReKi) :: f1, VnDotAf, Vmag !f2, + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + numLumpedMarkers = 0 + z0 = -(wtrDpth) ! The total sea depth is the still water depth of the seabed + + + + ! Count how many lumped markers we need to create by looping over the nodes + + DO I=1,numNodes + + IF ( (nodes(I)%NodeType == 3) .OR. ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) ) THEN + + numLumpedMarkers = numLumpedMarkers + 1 + + END IF + + END DO + + + ! Create the input and output meshes associated with lumped loads + + CALL MeshCreate( BlankMesh = lumpedMeshIn & + ,IOS = COMPONENT_INPUT & + ,Nnodes = numLumpedMarkers & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + + + + ! ! Allocate the array for the lumped markers + ! + !ALLOCATE ( lumpedMarkers(numLumpedMarkers), STAT = ErrStat ) + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for the lumped load markers array.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + + ALLOCATE ( commonNodeLst(10), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the commonNodeLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF + commonNodeLst = -1 + + ALLOCATE ( usedJointList(numNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the UsedJointList array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + usedJointList = .FALSE. + + ALLOCATE ( lumpedToNodeIndx(numLumpedMarkers), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( nodeToLumpedIndx(numNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + ALLOCATE ( L_F_B( 6, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped buoyancy forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_F_B = 0.0 + + ALLOCATE ( L_An( 3, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the L_An array.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_An = 0.0 + + ! This is + ALLOCATE ( L_F_I( 0:NStepWave, 6, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped inertial forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_F_I = 0.0 + + !ALLOCATE ( L_F_DP( 0:NStepWave, 6, numLumpedMarkers ), STAT = ErrStat ) + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for the lumped dynamic pressure forces/moments array.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + ! L_F_DP = 0.0 + + ALLOCATE ( L_F_BF( 6, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped buoyancy due to flooding forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_F_BF = 0.0 + + ALLOCATE ( L_AM_M( 6, 6, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped member added mass.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_AM_M = 0.0 + + ALLOCATE ( L_dragConst( numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped drag constants.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_dragConst = 0.0 + + ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads + ! For the buoyancy loads, loop over the elements and then apply one half of the resulting value + ! to each of the interior element nodes but the full value to an end node. This means that an internal member node will receive 1/2 of its + ! load from element A and 1/2 from element B. If it is the end of a member it will simply receive + ! the element A load. + + count = 1 + + DO I=1,numNodes + + ! exclude internal member nodes and end nodes which were connected to a joint made into a super member + + IF ( (nodes(I)%NodeType == 3) .OR. ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) ) THEN + + lumpedToNodeIndx(count) = I + nodeToLumpedIndx(I) = count + + ! If this is a super member node, then generate the lumped loads now, otherwise save it for the loop over elements + + IF ( nodes(I)%NodeType == 3 ) THEN + + END IF + + + + + ! Create the node on the mesh + + CALL MeshPositionNode (lumpedMeshIn & + , count & + , nodes(I)%JointPos & ! this info comes from FAST + , ErrStat & + , ErrMsg & + ) !, transpose(nodes(I)%R_LToG) ) + IF ( ErrStat /= 0 ) THEN + RETURN + END IF + + ! Create the mesh element + + CALL MeshConstructElement ( lumpedMeshIn & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , count & + ) + count = count + 1 + + + END IF + + END DO + + + + + ! CA is the added mass coefficient for three dimensional bodies in infinite fluid (far from boundaries) The default value is 2/Pi + + + AMfactor = 2.0 * densWater * Pi / 3.0 + + ! Loop over nodes again in order to create lumped axial drag. + + usedJointList = .FALSE. + commonNodeLst = -1 + + DO I=1,numNodes + + + + ! Determine bounds checking based on what load we are calculating, + ! This is for L_An + IF ( nodes(I)%JointPos(3) >= z0 ) THEN + + ! exclude internal member nodes and end nodes which were connected to a joint made into a super member + + + + ! If this is a super member node, then generate the lumped loads now, otherwise save it for the loop over elements + + IF ( nodes(I)%NodeType == 3 ) THEN + + ELSE + + IF ( nodes(I)%JointIndx /= -1 ) THEN ! TODO: MAYBE THIS SHOULD CHECK JointOvrlp value instead!! + + ! Have we already set the added mass for this node? + IF ( .NOT. usedJointList(nodes(I)%JointIndx) ) THEN + + nCommon = 0 + An = 0.0 + Vn = 0.0 + + DO J=1,numNodes + + ! must match joint index but also cannot be modeled using WAMIT + IF ( nodes(I)%JointIndx == nodes(J)%JointIndx ) THEN + + nCommon = nCommon + 1 + commonNodeLst(nCommon) = J + + ! Compute the signed area*outward facing normal of this member + sgn = 1.0 + + element = elements(nodes(J)%ConnectionList(1)) + + IF ( element%Node1Indx == J ) THEN + sgn = -1.0 ! Local coord sys points into element at starting node, so flip sign of local z vector + ELSE IF ( element%Node2Indx == J ) THEN + sgn = 1.0 ! Local coord sys points out of element at ending node, so leave sign of local z vector + ELSE + ErrMsg = 'Internal Error in CreateLumpedMesh: could not find element node index match.' + ErrStat = ErrID_FATAL + RETURN + END IF + ! Compute the signed volume of this member + f1 = (nodes(J)%R+nodes(J)%tMG)*(nodes(J)%R+nodes(J)%tMG)*(nodes(J)%R+nodes(J)%tMG) + Vn = Vn + sgn*f1*nodes(J)%R_LToG(:,3) + An = An + sgn*nodes(J)%R_LtoG(:,3)*Pi*(nodes(J)%R+nodes(J)%tMG)**2 + + END IF + + END DO + + nodes(I)%NConnectPreSplit = nCommon + + ! Divide the directed area equally across all connected markers + Vmag = sqrt(Dot_Product(Vn,Vn)) + + + + AM_M = 0.0 + IF ( (Vmag > 0.0) .AND. (.NOT. nodes(I)%PropPot) ) THEN + Vmat = RESHAPE(Vn,(/3,1/)) + AM_M(1:3,1:3) = (nodes(I)%JAxCa*AMfactor/(REAL( nCommon, ReKi)*Vmag) )*MatMul(Vmat,TRANSPOSE(Vmat)) + END IF + + DO J=1,nCommon + + IF ( nodes(I)%JointPos(3) >= z0 ) THEN + + L_An (:, nodeToLumpedIndx(commonNodeLst(J))) = An / nCommon + L_AM_M(:,:,nodeToLumpedIndx(commonNodeLst(J))) = AM_M + + DO M=0,NStepWave + ! The WaveAcc array has indices of (timeIndx, nodeIndx, vectorIndx), the nodeIndx needs to correspond to the total list of nodes for which + ! the wave kinematics were generated. We can use the nodeToLumpedIndx however for L_F_I and it's indices are (timeIndx, nodeIndx, vectorIndx) + + + F_I = 0.0 + IF ( (Vmag > 0.0) .AND. (.NOT. nodes(I)%PropPot) ) THEN + af = WaveAcc(M,commonNodeLst(J),:) + VnDotAf = Dot_Product(Vn,af) + F_I(1:3) = ( nodes(I)%JAxCa*AMfactor*VnDotAf / ( REAL( nCommon, ReKi ) * Vmag ) ) * Vn + END IF + L_F_I(M, :,nodeToLumpedIndx(commonNodeLst(J))) = F_I + END DO + + ELSE + ! Should we ever land in here? + L_An(:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 + L_AM_M(:,:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 + L_F_I(:,:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 + END IF + + END DO + + usedJointList(nodes(I)%JointIndx) = .TRUE. + END IF !IF ( .NOT. usedJointList(nodes(I)%JointIndx) ) + + END IF ! IF ( nodes(I)%JointIndx /= -1 ) + + END IF ! IF ( nodes(I)%NodeType == 3 ) THEN + + + + END IF ! ( nodes(I)%JointPos(3) >= z0 ) + + + + END DO ! I=1,numNodes + + + ! Loop over elements and identify those end nodes which have a JointOvrlp option of 0. + + DO I=1,numElements + + element = elements(I) + node1 = nodes(element%Node1Indx) + node2 = nodes(element%Node2Indx) + + CALL GetDistance( node1%JointPos, node2%JointPos, L ) + + IF ( node1%NodeType == 1 .AND. node1%JointOvrlp == 0 ) THEN + + !Process Lumped loads for this node + node = node1 + sgn = 1.0 + IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) )THEN + CALL GenerateLumpedLoads( element%Node1Indx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) + L_F_I(:, :, nodeToLumpedIndx(element%Node1Indx)) = L_F_I(:, :, nodeToLumpedIndx(element%Node1Indx)) + F_DP + ! L_F_DP(:, :, nodeToLumpedIndx(element%Node1Indx)) = F_DP + + L_dragConst(nodeToLumpedIndx(element%Node1Indx)) = dragConst + IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) )THEN + L_F_B (:, nodeToLumpedIndx(element%Node1Indx)) = F_B + END IF + + ELSE + F_BF = 0.0 + !L_F_DP(:, :, nodeToLumpedIndx(element%Node1Indx)) = 0.0 + L_F_B (:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 + L_dragConst(nodeToLumpedIndx(element%Node1Indx)) = 0.0 + + END IF + IF ( node%FillFlag ) THEN + IF ( (node%JointPos(3) <= (node%FillFSLoc)) .AND. (node%JointPos(3) >= z0) ) THEN + CALL LumpFloodedBuoyancy( sgn, node%FillDensity, node%R, node%t, node%FillFSLoc, node%JointPos(3) , node%R_LToG, gravity, F_BF ) + + L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = F_BF + ELSE + L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 + END IF + ELSE + L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 + END IF + + + ENDIF + + + IF ( node2%NodeType == 1 .AND. node2%JointOvrlp == 0 ) THEN + + !Process Lumped loads for this node + node = node2 + sgn = -1.0 + + ! Generate the loads regardless of node location, and then make the bounds check per load type because the range is different + CALL GenerateLumpedLoads( element%Node2Indx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) + IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) ) THEN + L_F_I(:, :, nodeToLumpedIndx(element%Node2Indx)) = L_F_I(:, :, nodeToLumpedIndx(element%Node2Indx)) + F_DP + !L_F_DP(:, :, nodeToLumpedIndx(element%Node2Indx)) = F_DP + + L_dragConst(nodeToLumpedIndx(element%Node2Indx)) = dragConst + + IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) ) THEN + L_F_B (:, nodeToLumpedIndx(element%Node2Indx)) = F_B + END IF + + ELSE + F_BF = 0.0 + !L_F_DP(:, :, nodeToLumpedIndx(element%Node2Indx)) = 0.0 + L_F_B (:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 + L_dragConst(nodeToLumpedIndx(element%Node2Indx)) = 0.0 + + END IF + IF ( node%FillFlag ) THEN + IF ( (node%JointPos(3) <= (node%FillFSLoc)) .AND. (node%JointPos(3) >= z0) ) THEN + CALL LumpFloodedBuoyancy( sgn, node%FillDensity, node%R, node%t, node%FillFSLoc, node%JointPos(3), node%R_LToG, gravity, F_BF ) + L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = F_BF + ELSE + L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 + END IF + ELSE + L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 + END IF + ENDIF + + + + + IF ( ErrStat /= 0 ) THEN + RETURN + END IF + + + END DO + + + CALL MeshCommit ( lumpedMeshIn & + , ErrStat & + , ErrMsg ) + + IF ( ErrStat /= 0 ) THEN + RETURN + END IF + + ! Initialize the inputs + DO I=1,lumpedMeshIn%Nnodes + lumpedMeshIn%Orientation(:,:,I) = lumpedMeshIn%RefOrientation(:,:,I) + END DO + lumpedMeshIn%TranslationDisp = 0.0 + lumpedMeshIn%TranslationVel = 0.0 + lumpedMeshIn%RotationVel = 0.0 + lumpedMeshIn%TranslationAcc = 0.0 + lumpedMeshIn%RotationAcc = 0.0 + + CALL MeshCopy ( SrcMesh = lumpedMeshIn & + ,DestMesh = lumpedMeshOut & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + lumpedMeshIn%RemapFlag = .TRUE. + lumpedMeshOut%RemapFlag = .TRUE. + + +END SUBROUTINE CreateLumpedMesh + +!subroutine ComputeDistributedLoadsAtNode( elementWaterState, densWater, JointZPos, & +! PropPot, R, dRdz, t, tMG, MGdensity, & +! R_LToG, Ca, Cp, AxCa, AxCp, Cd, WaveAcc, WaveDynP, D_dragConst_in, & +! D_AM_M, D_dragConst, D_F_I, ErrStat, ErrMsg ) +! +! INTEGER, INTENT( IN ) :: elementWaterState +! REAL(ReKi), INTENT( IN ) :: densWater +! REAL(ReKi), INTENT( IN ) :: JointZPos +! LOGICAL, INTENT( IN ) :: PropPot +! REAL(ReKi), INTENT( IN ) :: R +! REAL(ReKi), INTENT( IN ) :: dRdz +! REAL(ReKi), INTENT( IN ) :: t +! REAL(ReKi), INTENT( IN ) :: tMG +! REAL(ReKi), INTENT( IN ) :: MGdensity +! REAL(ReKi), INTENT( IN ) :: R_LToG(3,3) +! REAL(ReKi), INTENT( IN ) :: Ca +! REAL(ReKi), INTENT( IN ) :: Cp +! REAL(ReKi), INTENT( IN ) :: AxCa +! REAL(ReKi), INTENT( IN ) :: AxCp +! REAL(ReKi), INTENT( IN ) :: Cd +! REAL(ReKi), INTENT( IN ) :: WaveAcc(3) +! REAL(ReKi), INTENT( IN ) :: WaveDynP +! REAL(ReKi), INTENT( IN ) :: D_dragConst_in ! +! REAL(ReKi), INTENT( OUT ) :: D_AM_M(6,6) ! Added mass of member +! +! REAL(ReKi), INTENT( OUT ) :: D_dragConst ! +! REAL(ReKi), INTENT( OUT ) :: D_F_I(3) ! Inertial force associated with the member +! INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs +! CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! REAL(ReKi) :: k(3) +! +! +! IF ( .NOT. PropPot ) THEN ! Member is not modeled with WAMIT +! +! +! ! node is in the water, what about the entire element? +! IF ( elementWaterState == 1 ) THEN +! +! ! Element is in the water +! +! +! ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. +! ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) +! k = R_LToG(:,3) +! CALL DistrInertialLoads( densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, WaveAcc, WaveDynP, D_F_I, ErrStat, ErrMsg ) +! CALL DistrAddedMass( densWater, Ca, AxCa, R_LToG, R, tMG, dRdZ, D_AM_M ) +! +! ELSE +! ! Element is out of the water +! D_F_I (:) = 0.0 +! D_AM_M(:,:) = 0.0 ! This is not time-dependent +! END IF +! +! +! END IF ! IF ( .NOT. nodes(I)%PropPot ) +! +! ! These are the only two loads we compute at initialization if the member is modeled with WAMIT, they are also computed when Morison is used. +! IF ( elementWaterState == 1 )THEN +! ! element is in the water +! D_dragConst = D_dragConst_in +! ELSE +! D_dragConst = 0.0 +! END IF +! +!end subroutine ComputeDistributedLoadsAtNode + + +SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWave, WaveAcc, WaveDynP, numNodes, nodes, nodeInWater, numElements, elements, & + numDistribMarkers, distribMeshIn, distribMeshOut, distribToNodeIndx, D_F_I, & + D_F_B, D_F_DP, D_F_MG, D_F_BF, D_AM_M, D_AM_MG, D_AM_F, D_dragConst, elementWaterStateArr, & + Morison_Rad, ErrStat, ErrMsg ) + + REAL(ReKi), INTENT( IN ) :: densWater + REAL(ReKi), INTENT( IN ) :: gravity + REAL(ReKi), INTENT( IN ) :: MSL2SWL + REAL(ReKi), INTENT( IN ) :: wtrDpth + INTEGER, INTENT( IN ) :: NStepWave + REAL(SiKi), INTENT( IN ) :: WaveAcc(0:,:,:) + REAL(SiKi), INTENT( IN ) :: WaveDynP(0:,:) + INTEGER, INTENT( IN ) :: numNodes + INTEGER, INTENT( IN ) :: numElements + TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) + TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) + INTEGER(IntKi), INTENT( IN ) :: nodeInWater(0:,:) ! Flag indicating whether or not a node is in the water at a given wave time + INTEGER, INTENT( OUT ) :: numDistribMarkers + !TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: distribMarkers(:) + TYPE(MeshType), INTENT( OUT ) :: distribMeshIn + TYPE(MeshType), INTENT( OUT ) :: distribMeshOut + INTEGER, ALLOCATABLE, INTENT( OUT ) :: distribToNodeIndx(:) + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_I(:,:,:) + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_B(:,:) ! Buoyancy force associated with the member + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_DP(:,:,:) ! Dynamic pressure force + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_MG(:,:) ! Marine growth weight + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_BF(:,:) ! Flooded buoyancy force + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_M(:,:,:) ! Added mass of member + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_MG(:) ! Added mass of marine growth + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_F(:) ! Added mass of flooded fluid + REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_dragConst(:) ! + INTEGER,ALLOCATABLE, INTENT( OUT) :: elementWaterStateArr(:,:) + REAL(SiKi), ALLOCATABLE, INTENT( OUT ) :: Morison_Rad(:) ! radius of each node (for FAST visualization) + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + INTEGER :: I, J, count, node2Indx + INTEGER :: secondNodeWaterState + TYPE(Morison_MemberType) :: element + TYPE(Morison_NodeType) :: node1, node2 + REAL(ReKi) :: L + REAL(ReKi) :: k(3) + REAL(R8Ki) :: orientation(3,3) + + ! REAL(ReKi),ALLOCATABLE :: F_DP(:,:) + REAL(ReKi) :: F_B(6) + REAL(ReKi) :: F_BF(6) + REAL(ReKi),ALLOCATABLE :: F_I(:,:) + REAL(ReKi) :: z0 + INTEGER, ALLOCATABLE :: nodeToDistribIndx(:) + + numDistribMarkers = 0 + z0 = -(wtrDpth) ! The total sea depth is the still water depth of the seabed + + ! Count how many distributed markers we need to create by looping over the nodes + + DO I=1,numNodes + + IF ( nodes(I)%NodeType /= 3 ) THEN ! exclude super member nodes + + numDistribMarkers = numDistribMarkers + 1 + + END IF + + END DO + + + ! Create the input and output meshes associated with distributed loads + + CALL MeshCreate( BlankMesh = distribMeshIn & + ,IOS = COMPONENT_INPUT & + ,Nnodes = numDistribMarkers & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( Morison_Rad, numDistribMarkers, 'Morison_Rad', ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Allocate the array for the distributed markers + + !ALLOCATE ( distribMarkers(numDistribMarkers), STAT = ErrStat ) + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for the distributed load markers array.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + + ALLOCATE ( distribToNodeIndx(numDistribMarkers), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( nodeToDistribIndx(numNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + ALLOCATE ( elementWaterStateArr( 0:NStepWave, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the elementWaterStateArr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + elementWaterStateArr = 0 ! out of the water + + ALLOCATE ( D_F_I( 0:NStepWave, 6, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed inertial forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_F_I = 0.0 + + ALLOCATE ( D_F_B( 6, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed buoyancy forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_F_B = 0.0 + + ALLOCATE ( D_F_DP( 0:NStepWave, 6, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed dynamic pressure forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_F_DP = 0.0 + + ALLOCATE ( D_F_MG( 6, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed marine growth weight forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_F_MG = 0.0 + + ALLOCATE ( D_F_BF( 6, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed buoyancy due to flooding forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_F_BF = 0.0 + + + ALLOCATE ( D_AM_M( 3, 3, numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed added mass of flooded fluid.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_AM_M = 0.0 + + ALLOCATE ( D_AM_MG( numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed added mass of marine growth.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_AM_MG = 0.0 + + ALLOCATE ( D_AM_F( numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed added mass of flooded fluid.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_AM_F = 0.0 + + ALLOCATE ( D_dragConst( numDistribMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the distributed drag constants.' + ErrStat = ErrID_Fatal + RETURN + END IF + D_dragConst = 0.0 + + ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads <---@mhall: what does "create all loads" mean? + ! For the buoyancy loads, loop over the elements and then apply one half of the resulting value + ! to each of the interior element nodes but the full value to an end node. This means that an internal member node will receive 1/2 of its + ! load from element A and 1/2 from element B. If it is the end of a member it will simply receive + ! the element A load. <---@mhall: shouldn't end nodes only receive half too? + + count = 1 + + DO I=1,numNodes + + IF ( nodes(I)%NodeType /= 3 ) THEN + + ! End point or internal member node + + ! Find the node index for the other end of this element + !IF ( nodes(I)%NodeType == 1 ) THEN + ! element = elements(nodes(I)%ConnectionList(1)) + ! IF ( element%Node1Indx == I ) THEN + ! node2Indx = element%Node2Indx + ! ELSE + ! node2Indx = element%Node1Indx + ! END IF + !ELSE + ! node2Indx = -1 + !END IF + ! + ! ! Need to see if this node is connected to an element which goes above MSL2SWL or below Seabed. + !IF ( node2Indx > 0 ) THEN + ! IF ( nodes(node2Indx)%JointPos(3) > MSL2SWL ) THEN + ! secondNodeWaterState = 1 + ! ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN + ! secondNodeWaterState = 2 + ! ELSE + ! secondNodeWaterState = 0 + ! END IF + !ELSE + ! secondNodeWaterState = 0 + !END IF + + !CALL GetDistance( element + ! ! Compute all initialization forces now so we have access to the element information + ! + IF ( .NOT. nodes(I)%PropPot .AND. nodes(I)%JointPos(3) >= z0 ) THEN + + ! Member is not modeled with WAMIT + + k = nodes(I)%R_LToG(:,3) + + ! IF ( nodes(I)%JointPos(3) <= MSL2SWL .AND. nodes(I)%JointPos(3) >= z0 ) THEN + + + CALL DistrAddedMass( densWater, nodes(I)%Ca, nodes(I)%AxCa, nodes(I)%R_LToG, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdZ, D_AM_M(:,:,count) ) + ! IF ( secondNodeWaterState == 0 ) THEN + ! Element is in the water + + + !CALL DistrDynPressure( I, nodes(I)%AxCa,nodes(I)%AxCp, nodes(I)%R_LToG, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdz, NStepWave, WaveDynP, WaveAcc, F_DP, ErrStat, ErrMsg) + ! D_F_DP(:,:,count) = 0.0 !F_DP + ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. + ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) + CALL DistrBuoyancy( densWater, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdz, nodes(I)%JointPos(3) - MSL2SWL, nodes(I)%R_LToG, gravity, F_B ) + D_F_B(:,count) = F_B + ! ! Compute all initialization forces now so we have access to the element information + ! + ! IF ( ( .NOT. nodes(J)%PropPot ) .AND. ( nodes(J)%JointPos(3) >= z0 ) ) THEN + ! k = nodes(J)%R_LToG(:,3) + CALL DistrInertialLoads( I, densWater, nodes(I)%Ca, nodes(I)%Cp, nodes(I)%AxCa, nodes(I)%AxCp, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdZ, k, NStepWave, WaveAcc, WaveDynP, F_I, ErrStat, ErrMsg ) + D_F_I(:,:,count) = F_I + + ! END IF + + ! ELSE + ! Element is out of the water + ! D_F_DP(:,:,count) = 0.0 + ! D_F_B(:,count) = 0.0 + + ! END IF + + ! ELSE + ! NOTE: Everything was initialized to zero so this isn't really necessary. GJH 9/24/13 + + ! D_F_DP(:,:,count) = 0.0 + + ! D_F_B(:,count) = 0.0 + ! END IF + + ! IF ( ( nodes(I)%JointPos(3) >= z0 ) .AND. (secondNodeWaterState /= 2 ) ) THEN + ! if the node is at or above the seabed then the element is in the water + CALL DistrMGLoads( nodes(I)%MGdensity, gravity, nodes(I)%R, nodes(I)%tMG, D_F_MG(:,count) ) + CALL DistrAddedMassMG( nodes(I)%MGdensity, nodes(I)%R, nodes(I)%tMG, D_AM_MG(count) ) + ! ELSE + ! D_F_MG(:,count) = 0.0 + ! D_AM_MG(count)= 0.0 + ! END IF + + END IF ! IF ( .NOT. nodes(I)%PropPot ) + + ! This is always computed, but may be zereod out for any given timestep during the CalcOutput work <---@mhall: what is this? + CALL DistrDragConst( densWater, nodes(I)%Cd, nodes(I)%R, nodes(I)%tMG, D_dragConst(count) ) + + IF ( nodes(I)%FillFlag ) THEN + IF ( nodes(I)%JointPos(3) <= nodes(I)%FillFSLoc .AND. nodes(I)%JointPos(3) >= z0 ) THEN + + ! Find the node index for the other end of this element + IF ( nodes(I)%NodeType == 1 ) THEN + element = elements(nodes(I)%ConnectionList(1)) + IF ( element%Node1Indx == I ) THEN + node2Indx = element%Node2Indx + ELSE + node2Indx = element%Node1Indx + END IF + ELSE + node2Indx = -1 + END IF + + ! different check for filled element, based on free-surface location + IF ( node2Indx > 0 ) THEN + IF ( nodes(node2Indx)%JointPos(3) > nodes(I)%FillFSLoc ) THEN + secondNodeWaterState = 0 + ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN + secondNodeWaterState = 2 + ELSE + secondNodeWaterState = 1 + END IF + ELSE + secondNodeWaterState = 1 + END IF + + IF (secondNodeWaterState == 1 ) THEN + CALL DistrAddedMassFlood( nodes(I)%FillDensity, nodes(I)%R, nodes(I)%t, D_AM_F(count) ) + ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. + ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) + CALL DistrFloodedBuoyancy( nodes(I)%FillDensity, nodes(I)%FillFSLoc, nodes(I)%R, nodes(I)%t, nodes(I)%dRdZ, nodes(I)%JointPos(3) - MSL2SWL, nodes(I)%R_LToG, gravity, F_BF ) + D_F_BF(:,count ) = F_BF + ELSE + D_AM_F(count) = 0.0 + D_F_BF(:,count ) = 0.0 + END IF + + ELSE + ! NOTE: Everything was initialized to zero so this isn't really necessary. GJH 9/24/13 + D_AM_F(count) = 0.0 + D_F_BF(:,count ) = 0.0 + END IF + ELSE + D_AM_F(count) = 0.0 + D_F_BF(:,count ) = 0.0 + END IF + + + + ! Create the node on the mesh + + orientation = transpose(nodes(I)%R_LToG ) + CALL MeshPositionNode (distribMeshIn & + , count & + , nodes(I)%JointPos & ! this info comes from FAST + , ErrStat & + , ErrMsg & ! , orient = orientation & ! bjj: I need this orientation set for visualization. but, will it mess up calculations (because loads are in different positions?) + ) !, transpose(nodes(I)%R_LToG ) ) + IF ( ErrStat >= AbortErrLev ) RETURN + + Morison_Rad(count) = nodes(I)%R ! set this for FAST visualization + + distribToNodeIndx(count) = I + nodeToDistribIndx(I) = count + count = count + 1 + + END IF + + END DO + + ! Now for time-varying values + + DO count=1,numDistribMarkers + J = distribToNodeIndx(count) + DO I=0,NStepWave + IF ( nodes(J)%NodeType /= 3 ) THEN + + ! End point or internal member node + + ! Find the node index for the other end of this element + IF ( nodes(J)%NodeType == 1 ) THEN + element = elements(nodes(J)%ConnectionList(1)) + IF ( element%Node1Indx == J ) THEN + node2Indx = element%Node2Indx + ELSE + node2Indx = element%Node1Indx + END IF + ELSE + node2Indx = -1 + END IF + + ! Need to see if this node is connected to an element which goes above MSL2SWL or below Seabed. + IF ( node2Indx > 0 ) THEN + IF ( ( nodeInWater(I,node2Indx) == 0 ) .AND. ( nodes(node2Indx)%JointPos(3) >= z0 ) ) THEN + secondNodeWaterState = 0 + ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN + secondNodeWaterState = 2 + ELSE + secondNodeWaterState = 1 + END IF + ELSE + secondNodeWaterState = 1 + END IF + + + + + IF ( (nodeInWater(I,J) == 1) .AND. nodes(J)%JointPos(3) >= z0 ) THEN + IF ( secondNodeWaterState == 1 ) THEN + ! Element is in the water + elementWaterStateArr(I,count) = 1 + END IF + END IF + + END IF + + END DO ! DO I=0,NStepWave + END DO ! DO count=1,numDistribMarkers + + + ! End of time-varying values + + + DO I=1,numElements + + + ! Create the mesh element + + CALL MeshConstructElement ( distribMeshIn & + , ELEMENT_LINE2 & + , ErrStat & + , ErrMsg & + , nodeToDistribIndx(elements(I)%Node1Indx) & + , nodeToDistribIndx(elements(I)%Node2Indx) ) + + IF ( ErrStat /= 0 ) RETURN + + + END DO + + + CALL MeshCommit ( distribMeshIn & + , ErrStat & + , ErrMsg ) + + IF ( ErrStat /= 0 ) THEN + RETURN + END IF + + ! Initialize the inputs + DO I=1,distribMeshIn%Nnodes + distribMeshIn%Orientation(:,:,I) = distribMeshIn%RefOrientation(:,:,I) + END DO + distribMeshIn%TranslationDisp = 0.0 + distribMeshIn%TranslationVel = 0.0 + distribMeshIn%RotationVel = 0.0 + distribMeshIn%TranslationAcc = 0.0 + distribMeshIn%RotationAcc = 0.0 + + CALL MeshCopy ( SrcMesh = distribMeshIn & + ,DestMesh = distribMeshOut & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + distribMeshIn%RemapFlag = .TRUE. + distribMeshOut%RemapFlag = .TRUE. + +END SUBROUTINE CreateDistributedMesh + + + +!==================================================================================================== +SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) +! This public subroutine process the input geometry and parameters and eliminates joint overlaps, +! sub-divides members, sets joint-level properties, etc. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(Morison_InitInputType), INTENT( INOUT ) :: InitInp ! the Morison initialization data + !TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! tge Morison parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + + INTEGER :: I , J! j1, j2, tempINT ! generic integer for counting +! TYPE(Morison_JointType) :: joint1, joint2 +! Real(ReKi) :: z1 +! Real(ReKi) :: z2 + Real(ReKi) :: d + INTEGER :: temp + INTEGER :: prop1Indx, prop2Indx, node1Indx, node2Indx + INTEGER :: maxNodes = 0 + INTEGER :: maxElements = 0 + INTEGER :: maxSuperMembers = 0 + ! TYPE(Morison_NodeType) :: node1, node2, tempNode + TYPE(Morison_MemberPropType) :: propSet + INTEGER :: numSplitNodes + TYPE(Morison_NodeType),ALLOCATABLE :: splitNodes(:) + LOGICAL :: doSwap + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( InitInp%NMembers > 0 ) THEN + + + ! Determine the maximum number of nodes, elements, and super members which might be generated for the simulation mesh + CALL GetMaxSimQuantities( InitInp%NMGDepths, InitInp%MGTop, InitInp%MGBottom, InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%FilledGroups, InitInp%NJoints, InitInp%InpJoints, InitInp%NMembers, InitInp%InpMembers, maxNodes, maxElements, maxSuperMembers ) + + + ! Create a worse case size for the number of nodes and number of elements that will be generated for the simulation + ! marine growth split + super member split + member subdivision all creates new nodes + + ! marine growth split + member subdivision creates new elements + + ! Create a worse case size for the number of super members + + ! 1) Let's start by generating a mirror of the input mesh (joints and members) as the initial version of the simulation mesh + ! In doing so, create the initial mapping between the input mesh and this current version of the simulation mesh + + + ! Allocate memory for Joint-related arrays + + InitInp%NNodes = InitInp%NJoints + + ALLOCATE ( InitInp%Nodes(maxNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for Nodes array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + DO I = 1,InitInp%NNodes + ! Copy all necessary data from the input joints to these node data structures + InitInp%Nodes(I)%JointPos = InitInp%InpJoints(I)%JointPos + InitInp%Nodes(I)%JointAxIDIndx = InitInp%InpJoints(I)%JointAxIDIndx + InitInp%Nodes(I)%JointOvrlp = InitInp%InpJoints(I)%JointOvrlp + InitInp%Nodes(I)%NConnections = InitInp%InpJoints(I)%NConnections + InitInp%Nodes(I)%ConnectionList = InitInp%InpJoints(I)%ConnectionList + InitInp%Nodes(I)%JointIndx = I + InitInp%Nodes(I)%NodeType = 1 ! 1 = end of a member, 2 = interior of a member, 3 = super member node + InitInp%Nodes(I)%FillFSLoc = InitInp%MSL2SWL + InitInp%Nodes(I)%FillFlag = .FALSE. + InitInp%Nodes(I)%FillDensity = 0.0 + + + + END DO + + + ! Allocate memory for Members arrays + + InitInp%NElements = InitInp%NMembers + + ALLOCATE ( InitInp%Elements(maxElements), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for Elements array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + DO I = 1,InitInp%NMembers + + InitInp%Elements(I)%Node1Indx = InitInp%InpMembers(I)%MJointID1Indx ! Index of the first node in the Morison_NodeType array + InitInp%Elements(I)%Node2Indx = InitInp%InpMembers(I)%MJointID2Indx ! Index of the second node in the Morison_NodeType array + node1Indx = InitInp%Elements(I)%Node1Indx + node2Indx = InitInp%Elements(I)%Node2Indx + prop1Indx = InitInp%InpMembers(I)%MPropSetID1Indx + prop2Indx = InitInp%InpMembers(I)%MPropSetID2Indx + + ! Make sure that Node1 has the lower Z value, re-order if necessary + ! We need to do this because the local element coordinate system is defined such that the first node is located with a smaller global Z value + ! than the second node. + ! The local element coordinate system requires that Z1 <= Z2, and if Z1=Z2 then X1 <= X2, and if Z1=Z2, X1=X2 then Y1<Y2 + + InitInp%Elements(I)%InpMbrDist1 = 0.0 + InitInp%Elements(I)%InpMbrDist2 = 1.0 + doSwap = .FALSE. + + IF ( EqualRealNos(InitInp%Nodes(node1Indx)%JointPos(3), InitInp%Nodes(node2Indx)%JointPos(3) ) ) THEN ! Z1 = Z2 + IF ( EqualRealNos(InitInp%Nodes(node1Indx)%JointPos(1), InitInp%Nodes(node2Indx)%JointPos(1) ) ) THEN ! X1 = X2 + IF ( InitInp%Nodes(node1Indx)%JointPos(2) > InitInp%Nodes(node2Indx)%JointPos(2) ) THEN + doSwap = .TRUE. ! Y1 > Y2 + END IF + ELSE IF ( InitInp%Nodes(node1Indx)%JointPos(1) > InitInp%Nodes(node2Indx)%JointPos(1) ) THEN + doSwap = .TRUE. ! X1 > X2 + END IF + ELSE IF ( InitInp%Nodes(node1Indx)%JointPos(3) > InitInp%Nodes(node2Indx)%JointPos(3) ) THEN + doSwap = .TRUE. ! Z1 > Z2 + END IF + + IF ( doSwap ) THEN + + ! Swap node indices to satisfy orientation rules for element nodes + + InitInp%Elements(I)%Node1Indx = InitInp%InpMembers(I)%MJointID2Indx + InitInp%Elements(I)%Node2Indx = InitInp%InpMembers(I)%MJointID1Indx + node1Indx = InitInp%Elements(I)%Node1Indx + node2Indx = InitInp%Elements(I)%Node2Indx + temp = prop1Indx + prop1Indx = prop2Indx + prop2Indx = temp + InitInp%Elements(I)%InpMbrDist1 = 1.0 + InitInp%Elements(I)%InpMbrDist2 = 0.0 + ! --- Swap member coeffs if needed. + ! Fine in this loop since there is a unique CoefMember per Member (otherwise we could swap them several times). + J = InitInp%InpMembers(I)%MmbrCoefIDIndx ! Index in CoefMembers table + IF (J>0) THEN + ! NOTE: SWAP defined at the end of the current subroutine + CALL SWAP(InitInp%CoefMembers(J)%MemberCd1 , InitInp%CoefMembers(J)%MemberCd2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCa1 , InitInp%CoefMembers(J)%MemberCa2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCp1 , InitInp%CoefMembers(J)%MemberCp2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCa1 , InitInp%CoefMembers(J)%MemberAxCa2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCp1 , InitInp%CoefMembers(J)%MemberAxCp2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCdMG1 , InitInp%CoefMembers(J)%MemberCdMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCaMG1 , InitInp%CoefMembers(J)%MemberCaMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCpMG1 , InitInp%CoefMembers(J)%MemberCpMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCaMG1, InitInp%CoefMembers(J)%MemberAxCaMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCpMG1, InitInp%CoefMembers(J)%MemberAxCpMG2) + END IF + END IF + + propSet = InitInp%MPropSets(prop1Indx) + InitInp%Elements(I)%R1 = propSet%PropD / 2.0 + InitInp%Elements(I)%t1 = propSet%PropThck + + propSet = InitInp%MPropSets(prop2Indx) + InitInp%Elements(I)%R2 = propSet%PropD / 2.0 + InitInp%Elements(I)%t2 = propSet%PropThck + + InitInp%Elements(I)%NumSplits = InitInp%InpMembers(I)%NumSplits + InitInp%Elements(I)%Splits = InitInp%InpMembers(I)%Splits + !InitInp%Elements(I)%MGSplitState = InitInp%InpMembers(I)%MGSplitState + !InitInp%Elements(I)%WtrSplitState = InitInp%InpMembers(I)%WtrSplitState + InitInp%Elements(I)%MDivSize = InitInp%InpMembers(I)%MDivSize + InitInp%Elements(I)%MCoefMod = InitInp%InpMembers(I)%MCoefMod + InitInp%Elements(I)%MmbrCoefIDIndx = InitInp%InpMembers(I)%MmbrCoefIDIndx + InitInp%Elements(I)%MmbrFilledIDIndx = InitInp%InpMembers(I)%MmbrFilledIDIndx + + CALL GetDistance( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, d) + + InitInp%Elements(I)%InpMbrLen = d + InitInp%Elements(I)%InpMbrIndx = I + + ! Direction cosines matrix which transforms a point in member coordinates to the global inertial system + !CALL Morison_DirCosMtrx( node1%JointPos, node2%JointPos, InitInp%Elements(I)%R_LToG ) + + + InitInp%Elements(I)%PropPot = InitInp%InpMembers(I)%PropPot ! Flag specifying whether member is modelled in WAMIT [true = modelled in WAMIT, false = not modelled in WAMIT] + + + + + ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array + + CALL Morison_DirCosMtrx( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, InitInp%Elements(I)%R_LToG ) + ! InitInp%Nodes(node1Indx)%R_LToG = InitInp%Elements(I)%R_LToG + ! InitInp%Nodes(node2Indx)%R_LToG = InitInp%Elements(I)%R_LToG + END DO + + + + ! Set the fill properties onto the elements + + CALL SetElementFillProps( InitInp%NFillGroups, InitInp%FilledGroups, InitInp%NElements, InitInp%Elements ) + + ! Split the elements at certain depths according to still water line, internal filled free surface, marine growth transition depths, seabed dpeth, etc. as applicable. + CALL SplitElements(InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) + + ! Split element due to MSL2SWL location and seabed location + !CALL SplitElementsForWtr(InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) + + ! Split elements if they cross the marine growth boundary. + + !CALL SplitElementsForMG(InitInp%MGTop, InitInp%MGBottom, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) + + + ! Create any Super Members + !CALL CreateSuperMembers( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) + + ! Subdivide the members based on user-requested maximum division sizes (MDivSize) + + CALL SubdivideMembers( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) + + + + ! Set the element Cd, Ca, and Cp coefs + + CALL SetElementCoefs( InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, InitInp%SimplCpMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG,InitInp%CoefMembers, InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements ) + + + ! Set the axial coefs AxCd and AxCa + CALL SetAxialCoefs( InitInp%NJoints, InitInp%NAxCoefs, InitInp%AxialCoefs, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements ) + + ! Set the marine growth thickness and density information onto the nodes (this is not a per-element quantity, but a per-node quantity + + CALL SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%NNodes, InitInp%Nodes ) + + + ! Create duplicate nodes at the ends of elements so that only one element is connected to any given end node + + CALL SplitMeshNodes( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, numSplitNodes, splitNodes, ErrStat, ErrMsg ) + + IF (numSplitNodes > InitInp%NNodes ) THEN + + InitInp%NNodes = numSplitNodes + !Reallocate the Nodes array + DEALLOCATE ( InitInp%Nodes ) + ALLOCATE ( InitInp%Nodes(numSplitNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for Nodes array.' + ErrStat = ErrID_Fatal + RETURN + END IF + InitInp%Nodes = splitNodes + DEALLOCATE ( splitNodes ) + + END IF + + + ! Now that the nodes are split, we can push the element properties down to the individual nodes without an issue + + CALL SetSplitNodeProperties( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) + + + + + ! 6) Store information necessary to compute the user-requested member outputs and joint outputs. The requested output locations + ! may be located in between two simulation nodes, so quantities will need to be interpolated. qOutput = q1*s + q2*(1-s), where 0<= s <= 1. + + ! NOTE: since we need to mantain the input geometry, the altered members are now part of the simulation mesh and + ! we will generate a mapping between the input and simulation meshes which is needed to generate user-requested outputs. + + + + ELSE + + + ! No Morison elements, so no processing is necessary, but set nodes and elements to 0. + + ! p%NMorisonNodes = 0 + ! p%NMorisonElements = 0 + + END IF + CONTAINS + SUBROUTINE SWAP(x1,x2) + Real(Reki),intent(inout) :: x1,x2 + Real(Reki) :: tmp + tmp = x1 + x1 = x2 + x2 = tmp + END SUBROUTINE SWAP +END SUBROUTINE Morison_ProcessMorisonGeometry + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Morison_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine !intent out because of MOVE_ALLOC + TYPE(Morison_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Morison_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Morison_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Morison_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Morison_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Morison_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Morison_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Morison_UpdateStates() is called in loose coupling & + !! (2) Morison_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Morison_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! TYPE(Morison_InitInputType) :: InitLocal ! Local version of the input data for the geometry processing routine +! INTEGER, ALLOCATABLE :: distribToNodeIndx(:) +! INTEGER, ALLOCATABLE :: lumpedToNodeIndx(:) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + + ! InitLocal = InitInp + p%WtrDens = InitInp%WtrDens + p%NumOuts = InitInp%NumOuts + p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] + p%OutSwtch = InitInp%OutSwtch + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for MOutLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF +IF (ALLOCATED(InitInp%MOutLst) ) & + p%MOutLst = InitInp%MOutLst ! Member output data + + p%NJOutputs = InitInp%NJOutputs ! Number of joints to output [ >=0 and <10] + + ALLOCATE ( p%JOutLst(p%NJOutputs), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for JOutLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF +IF (ALLOCATED(InitInp%JOutLst) ) & + p%JOutLst = InitInp%JOutLst ! Joint output data + + + + + + p%NNodes = InitInp%NNodes + + ALLOCATE ( p%Nodes(p%NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for Nodes array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + p%Nodes = InitInp%Nodes + + + p%NStepWave= InitInp%NStepWave + + ALLOCATE ( p%WaveVel(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave velocities array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveVel = InitInp%WaveVel + + ALLOCATE ( p%WaveAcc(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave accelerations array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveAcc = InitInp%WaveAcc + + ALLOCATE ( p%WaveDynP(0:p%NStepWave, p%NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave dynamic pressure array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveDynP = InitInp%WaveDynP + + + + ALLOCATE ( p%WaveTime(0:p%NStepWave), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave time array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveTime = InitInp%WaveTime + + + CALL MOVE_ALLOC( InitInp%nodeInWater, p%nodeInWater ) + + + + ! Use the processed geometry information to create the distributed load mesh and associated marker parameters + + ! We are storing the parameters in the DistribMarkers data structure instead of trying to hold this information within the DistribMesh. But these two data structures + ! must always be in sync. For example, the 5th element of the DistribMarkers array must correspond to the 5th node in the DistribMesh data structure. + + CALL CreateDistributedMesh( InitInp%WtrDens, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NStepWave, InitInp%WaveAcc, InitInp%WaveDynP, & + p%NNodes, p%Nodes, p%nodeInWater, InitInp%NElements, InitInp%Elements, & + p%NDistribMarkers, u%DistribMesh, y%DistribMesh, p%distribToNodeIndx, p%D_F_I, & + p%D_F_B, p%D_F_DP, p%D_F_MG, p%D_F_BF, p%D_AM_M, p%D_AM_MG, p%D_AM_F, p%D_dragConst, p%elementWaterState, & ! + InitOut%Morison_Rad, ErrStat, ErrMsg ) + + + !@mhall: D_F_BF must become a variable rather than a parameter! <<<< + + + IF ( ErrStat > ErrID_None ) RETURN + + + CALL CreateLumpedMesh( InitInp%WtrDens, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NStepWave, InitInp%WaveDynP, InitInp%WaveAcc,p%NNodes, p%Nodes, InitInp%NElements, InitInp%Elements, & + p%NLumpedMarkers, u%LumpedMesh, y%LumpedMesh, p%lumpedToNodeIndx, p%L_An, & + p%L_F_B, p%L_F_I, p%L_F_BF, p%L_AM_M, p%L_dragConst, & + ErrStat, ErrMsg ) + IF ( ErrStat > ErrID_None ) RETURN + + + + ! CALL CreateSuperMesh( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, p%NSuperMarkers, p%SuperMarkers, InitOut%LumpedMesh, ErrStat, ErrMsg ) + + + + + + ! Define parameters here: + + + p%DT = Interval + + + ! Define initial system states here: + + x%DummyContState = 0 + xd%DummyDiscState = 0 + z%DummyConstrState = 0 + OtherState%DummyOtherState = 0 + m%LastIndWave = 1 + + IF ( p%OutSwtch > 0 ) THEN + ALLOCATE ( m%D_F_D(3,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_D array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_D = 0.0_ReKi + ALLOCATE ( m%D_F_I(3,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_I array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_I = 0.0_ReKi + ALLOCATE ( m%D_F_B(6,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_B array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_B = 0.0_ReKi + ALLOCATE ( m%D_F_AM(6,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_AM = 0.0_ReKi + ALLOCATE ( m%D_F_AM_M(6,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM_M array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_AM_M = 0.0_ReKi + ALLOCATE ( m%D_F_AM_MG(6,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM_MG array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_AM_MG = 0.0_ReKi + ALLOCATE ( m%D_F_AM_F(6,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM_F array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_F_AM_F = 0.0_ReKi + ALLOCATE ( m%D_FV(3,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FV array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_FV = 0.0_ReKi + ALLOCATE ( m%D_FA(3,y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FA array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_FA = 0.0_ReKi + ALLOCATE ( m%D_FDynP(y%DistribMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FDynP array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%D_FDynP = 0.0_ReKi + + ALLOCATE ( m%L_F_B(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_F_B array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_F_B = 0.0_ReKi + ALLOCATE ( m%L_F_D(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_F_D array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_F_D = 0.0_ReKi + ALLOCATE ( m%L_F_I(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_F_I array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_F_I = 0.0_ReKi + !ALLOCATE ( m%L_F_DP(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for L_F_DP array.' + ! ErrStat = ErrID_Fatal + ! RETURN + !END IF + ALLOCATE ( m%L_FV(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_FV array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_FV = 0.0_ReKi + ALLOCATE ( m%L_FA(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_FA array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_FA = 0.0_ReKi + ALLOCATE ( m%L_FDynP(y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_FDynP array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_FDynP = 0.0_ReKi + ALLOCATE ( m%L_F_AM(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for L_F_AM array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%L_F_AM = 0.0_ReKi + + ! Define initial guess for the system inputs here: + + ! u%DummyInput = 0 + + + ! Define system output initializations (set up mesh) here: + + + ! Define initialization-routine output here: + + ! Initialize the outputs + + CALL MrsnOUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) + IF ( ErrStat > ErrID_None ) RETURN + + ! Determine if we need to perform output file handling + + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL MrsnOUT_OpenOutput( Morison_ProgDesc%Name, TRIM(InitInp%OutRootName)//'.HD', p, InitOut, ErrStat, ErrMsg ) + IF ( ErrStat > ErrID_None ) RETURN + END IF + + END IF + + + ! Write Summary information now that everything has been initialized. + + CALL WriteSummaryFile( InitInp%UnSum, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, p%NumOuts, p%OutParam, p%NMOutputs, p%MOutLst, p%distribToNodeIndx, p%NJOutputs, p%JOutLst, u%LumpedMesh, y%LumpedMesh,u%DistribMesh, y%DistribMesh, p%L_F_B, p%L_F_BF, p%D_F_B, p%D_F_BF, p%D_F_MG, InitInp%Gravity, ErrStat, ErrMsg ) !p%NDistribMarkers, distribMarkers, p%NLumpedMarkers, lumpedMarkers, + IF ( ErrStat > ErrID_None ) RETURN + + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + + !Interval = p%DT + !Contains: + ! SUBROUTINE CleanUpInitOnErr + ! IF (ALLOCATED(sw(1)%array)) DEALLOCATE(sw(1)%array, STAT=aviFail) + ! END SUBROUTINE + +END SUBROUTINE Morison_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Morison_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Morison_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Morison_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Morison_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Morison_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(Morison_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Morison_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 + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL Morison_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Determine if we need to close the output file + + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL MrsnOut_CloseOutput( p, ErrStat, ErrMsg ) + END IF + + ! Destroy the parameter data: + + + CALL Morison_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL Morison_DestroyContState( x, ErrStat, ErrMsg ) + CALL Morison_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL Morison_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL Morison_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL Morison_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL Morison_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE Morison_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 Morison_UpdateStates( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at Time; + !! Output: Continuous states at Time + Interval + TYPE(Morison_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(Morison_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at Time; + !! Output: Constraint states at Time + Interval + TYPE(Morison_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at Time; + !! Output: Other states at Time + Interval + TYPE(Morison_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 + + ! Local variables + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + + +END SUBROUTINE Morison_UpdateStates +!> This routine is similar to InterpWrappedStpReal, except it returns only the slope for the interpolation. +!! By returning the slope based on Time, we don't have to calculate this for every variable (Yary) we want to interpolate. +!! NOTE: p%WaveTime (and most arrays here) start with index of 0 instead of 1, so we will subtract 1 from "normal" interpolation +!! schemes. +FUNCTION GetInterpolationSlope(Time, p, m, IntWrapIndx) RESULT( InterpSlope ) + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER, OPTIONAL, INTENT( OUT) :: IntWrapIndx + + REAL(SiKi) :: Time_SiKi + REAL(SiKi) :: TimeMod + REAL(ReKi) :: InterpSlope + + Time_SiKi = REAL(Time, SiKi) + TimeMod = MOD(Time_SiKi, p%WaveTime(p%NStepWave)) !p%WaveTime starts at index 0, so it has p%NStepWave+1 elements + IF ( TimeMod <= p%WaveTime(1) ) THEN !second element + m%LastIndWave = 0 + END IF + + IF ( TimeMod <= p%WaveTime(0) ) THEN + m%LastIndWave = 0 + InterpSlope = 0.0_ReKi ! returns values at m%LastIndWave + IF(PRESENT(IntWrapIndx)) IntWrapIndx = 0 + ELSE IF ( TimeMod >= p%WaveTime(p%NStepWave) ) THEN + m%LastIndWave = p%NStepWave-1 + InterpSlope = 1.0_ReKi ! returns values at p%NStepWave + IF(PRESENT(IntWrapIndx)) IntWrapIndx = p%NStepWave + ELSE + m%LastIndWave = MAX( MIN( m%LastIndWave, p%NStepWave-1 ), 0 ) + + DO + + IF ( TimeMod < p%WaveTime(m%LastIndWave) ) THEN + + m%LastIndWave = m%LastIndWave - 1 + + ELSE IF ( TimeMod >= p%WaveTime(m%LastIndWave+1) ) THEN + + m%LastIndWave = m%LastIndWave + 1 + + ELSE + IF(PRESENT(IntWrapIndx)) IntWrapIndx = m%LastIndWave + + InterpSlope = ( TimeMod - p%WaveTime(m%LastIndWave) )/( p%WaveTime(m%LastIndWave+1) - p%WaveTime(m%LastIndWave) ) + RETURN ! stop checking DO loop + END IF + + END DO + + END IF + +END FUNCTION GetInterpolationSlope +!> Use in conjunction with GetInterpolationSlope, to replace InterpWrappedStpReal here. +FUNCTION InterpolateWithSlope(InterpSlope, Ind, YAry) + REAL(ReKi), INTENT(IN) :: InterpSlope + INTEGER(IntKi), INTENT(IN ) :: Ind !< Misc/optimization variables + REAL(SiKi), INTENT(IN) :: YAry(0:) + REAL(ReKi) :: InterpolateWithSlope + + InterpolateWithSlope = ( YAry(Ind+1) - YAry(Ind) )*InterpSlope + YAry(Ind) + +END FUNCTION InterpolateWithSlope +!> Use in conjunction with GetInterpolationSlope, to replace InterpWrappedStpReal here. +FUNCTION InterpolateWithSlopeR(InterpSlope, Ind, YAry) + REAL(ReKi), INTENT(IN) :: InterpSlope + INTEGER(IntKi), INTENT(IN ) :: Ind !< Misc/optimization variables + REAL(ReKi), INTENT(IN) :: YAry(0:) + REAL(ReKi) :: InterpolateWithSlopeR + + InterpolateWithSlopeR = ( YAry(Ind+1) - YAry(Ind) )*InterpSlope + YAry(Ind) + +END FUNCTION InterpolateWithSlopeR +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Morison_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Morison_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(Morison_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) :: F_D(6), F_DP(6), D_F_I(3), kvec(3), v(3), vf(3), vrel(3), vmag + INTEGER :: I, J, K, nodeIndx, IntWrapIndx + REAL(ReKi) :: elementWaterState + REAL(ReKi) :: AllOuts(MaxMrsnOutputs) ! TODO: think about adding to OtherState + REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node + !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node + REAL(ReKi) :: dragFactor ! The lumped drag factor + REAL(ReKi) :: AnProd ! Dot product of the directional area of the joint + REAL(ReKi) :: F_B(6) + REAL(ReKi) :: C(3,3) + REAL(ReKi) :: sgn + REAL(ReKi) :: D_AM_M(6,6) + REAL(ReKi) :: nodeInWater + REAL(ReKi) :: D_dragConst ! The distributed drag factor + REAL(ReKi) :: InterpolationSlope + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + InterpolationSlope = GetInterpolationSlope(Time, p, m, IntWrapIndx) + + ! Compute outputs here: + + ! We need to attach the distributed drag force (D_F_D), distributed inertial force (D_F_I), and distributed dynamic pressure force (D_F_DP) to the Misc type so that we don't need to + ! allocate their data storage at each time step! If we could make them static local variables (like in C) then we could avoid adding them to the OtherState datatype. + ! The same is true for the lumped drag (L_F_D) and the lumped dynamic pressure (L_F_DP) + + DO J = 1, y%DistribMesh%Nnodes + + ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers + nodeIndx = p%distribToNodeIndx(J) + + ! Determine in or out of water status for the element which this node is a part of. + ! NOTE: This will find the closest WaveTime index (wvIndx) which is has waveTime(wvIndx) > = Time. If WaveDT = DT then waveTime(wvIndx) will equal Time + ! For WaveMod = 6 or WaveMod = 5 WaveDT must equal DT for the returned value of elementWaterState to be meaningful, for other WaveMod, + ! elementWaterState is the same for all time for a given node, J. + elementWaterState = REAL(p%elementWaterState(IntWrapIndx,J), ReKi) + + ! Determine the dynamic pressure at the marker + m%D_FDynP(J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveDynP(:,nodeIndx)) + + + DO I=1,3 + ! Determine the fluid acceleration and velocity at the marker + m%D_FA(I,J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveAcc(:,nodeIndx,I)) + m%D_FV(I,J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveVel(:,nodeIndx,I)) + + vrel(I) = m%D_FV(I,J) - u%DistribMesh%TranslationVel(I,J) + + m%D_F_I(I,J) = elementWaterState * InterpolateWithSlopeR(InterpolationSlope, m%LastIndWave, p%D_F_I(:,I,J) ) + END DO + + ! (k x vrel x k) + kvec = p%Nodes(nodeIndx)%R_LToG(:,3) + v = vrel - Dot_Product(kvec,vrel)*kvec + vmag = sqrt( v(1)*v(1) + v(2)*v(2) + v(3)*v(3) ) + + + ! Distributed added mass loads + ! need to multiply by elementInWater value to zero out loads when out of water + qdotdot2(1) = elementWaterState *u%DistribMesh%TranslationAcc(1,J) + qdotdot2(2) = elementWaterState *u%DistribMesh%TranslationAcc(2,J) + qdotdot2(3) = elementWaterState *u%DistribMesh%TranslationAcc(3,J) + ! calculated the added mass forces (moments are zero) + m%D_F_AM_M(1:3,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? + + DO I=1,6 + IF (I < 4 ) THEN + ! We are now combining the dynamic pressure term into the inertia term + m%D_F_AM_MG(I,J) = -p%D_AM_MG(J)*u%DistribMesh%TranslationAcc(I,J) + m%D_F_AM_F(:,J) = -p%D_AM_F(J)*u%DistribMesh%TranslationAcc(I,J) + m%D_F_AM(I,J) = m%D_F_AM_M(I,J) + m%D_F_AM_MG(I,J) + m%D_F_AM_F(I,J) + m%D_F_D(I,J) = elementWaterState * vmag*v(I) * p%D_dragConst(J) + m%D_F_B(I,J) = elementWaterState * p%D_F_B(I,J) + y%DistribMesh%Force(I,J) = m%D_F_AM(I,J) + m%D_F_D(I,J) + m%D_F_I(I,J) + m%D_F_B(I,J) + p%D_F_MG(I,J) + p%D_F_BF(I,J) + ELSE + m%D_F_B(I,J) = elementWaterState * p%D_F_B(I,J) + y%DistribMesh%Moment(I-3,J) = m%D_F_B(I,J) + p%D_F_BF(I,J) + END IF + END DO ! DO I + + + + ENDDO + + + ! NOTE: All wave kinematics have already been zeroed out above the SWL or instantaneous wave height (for WaveStMod > 0), so loads derived from the kinematics will be correct + ! without the use of a nodeInWater value, but other loads need to be multiplied by nodeInWater to zero them out above the SWL or instantaneous wave height. + + DO J = 1, y%LumpedMesh%Nnodes + + ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers + + nodeIndx = p%lumpedToNodeIndx(J) + nodeInWater = REAL(p%nodeInWater(IntWrapIndx,nodeIndx), ReKi) + ! Determine the dynamic pressure at the marker + m%L_FDynP(J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveDynP(:,nodeIndx)) + + + DO I=1,3 + ! Determine the fluid acceleration and velocity at the marker + m%L_FA(I,J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveAcc(:,nodeIndx,I)) + + m%L_FV(I,J) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveVel(:,nodeIndx,I)) + vrel(I) = m%L_FV(I,J) - u%LumpedMesh%TranslationVel(I,J) + END DO + + + + ! Compute the dot product of the relative velocity vector with the directional Area of the Joint + vmag = nodeInWater * ( vrel(1)*p%L_An(1,J) + vrel(2)*p%L_An(2,J) + vrel(3)*p%L_An(3,J) ) + AnProd = p%L_An(1,J)**2 + p%L_An(2,J)**2 + p%L_An(3,J)**2 + IF (EqualRealNos(AnProd, 0.0_ReKi)) THEN + dragFactor = 0.0 + ELSE + dragFactor = p%Nodes(nodeIndx)%JAxCd*p%WtrDens*abs(vmag)*vmag / ( 4.0_ReKi * AnProd ) + END IF + + + ! Lumped added mass loads + qdotdot = reshape((/u%LumpedMesh%TranslationAcc(:,J),u%LumpedMesh%RotationAcc(:,J)/),(/6/)) + m%L_F_AM(:,J) = matmul( p%L_AM_M(:,:,J) , ( - qdotdot) ) + DO I=1,3 + m%L_F_AM(I,J) = nodeInWater * m%L_F_AM(I,J) ! Note that the rotational components are zero because L_AM_M is populated with only the upper-left 3x3 + END DO + + DO I=1,6 + + ! We are now combining the dynamic pressure term into the inertia term + m%L_F_I(I,J) = InterpolateWithSlopeR(InterpolationSlope, m%LastIndWave, p%L_F_I(:,I,J)) + + IF (I < 4 ) THEN + + m%L_F_D(I,J) = p%L_An(I,J)*dragFactor + m%L_F_B(I,J) = nodeInWater*p%L_F_B(I,J) + y%LumpedMesh%Force(I,J) = m%L_F_AM(I,J) + m%L_F_D(I,J) + m%L_F_B(I,J) + m%L_F_I(I,J) + p%L_F_BF(I,J) + ELSE + m%L_F_B(I,J) = nodeInWater*p%L_F_B(I,J) + y%LumpedMesh%Moment(I-3,J) = m%L_F_AM(I,J) + m%L_F_B(I,J) + p%L_F_BF(I,J) + END IF + + + END DO + ENDDO + + ! OutSwtch determines whether or not to actually output results via the WriteOutput array + ! 1 = Morison will generate an output file of its own. 2 = the caller will handle the outputs, but + ! Morison needs to provide them. 3 = Both 1 and 2, 0 = No one needs the Morison outputs provided + ! via the WriteOutput array. + + IF ( p%OutSwtch > 0 ) THEN + + ! Map calculated results into the AllOuts Array + CALL MrsnOut_MapOutputs(Time, y, p, u, m, AllOuts, ErrStat, ErrMsg) + + + ! Put the output data in the WriteOutput array + + DO I = 1,p%NumOuts + + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + + END DO + + + ! Generate output into the output file + + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL MrsnOut_WriteOutputs( p%UnOutFile, Time, y, p, ErrStat, ErrMsg ) + END IF + END IF + + +END SUBROUTINE Morison_CalcOutput + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Morison_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(Morison_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + dxdt%DummyContState = 0.0 + + +END SUBROUTINE Morison_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +SUBROUTINE Morison_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Morison_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Morison_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + + ! StateData%DiscState = + +END SUBROUTINE Morison_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE Morison_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Morison_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(Morison_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0.0_ReKi + +END SUBROUTINE Morison_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE Morison +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/Morison.txt b/OpenFAST/modules/hydrodyn/src/Morison.txt new file mode 100644 index 000000000..5326fb452 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Morison.txt @@ -0,0 +1,356 @@ +################################################################################################################################### +# Registry for Morison in the FAST Modularization Framework +# This Registry file is used to create MODULE Morison which contains all of the user-defined types needed in Morison. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt +# +# +param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "" - +typedef Morison/Morison Morison_JointType INTEGER JointID - - - "" - +typedef ^ ^ ReKi JointPos {3} - - "" - +typedef ^ ^ INTEGER JointAxID - - - "" - +typedef ^ ^ INTEGER JointAxIDIndx - - - "" - +typedef ^ ^ INTEGER JointOvrlp - - - "" - +typedef ^ ^ INTEGER NConnections - - - "" - +typedef ^ ^ INTEGER ConnectionList {10} - - "" - +typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "" - +typedef ^ ^ ReKi PropD - - - "" - +typedef ^ ^ ReKi PropThck - - - "" - +typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "" - +typedef ^ ^ INTEGER FillMList {:} - - "" - +typedef ^ ^ ReKi FillFSLoc - - - "" - +typedef ^ ^ CHARACTER(80) FillDensChr - - - "" - +typedef ^ ^ ReKi FillDens - - - "" - +typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "" - +typedef ^ ^ ReKi DpthCd - - - "" - +typedef ^ ^ ReKi DpthCdMG - - - "" - +typedef ^ ^ ReKi DpthCa - - - "" - +typedef ^ ^ ReKi DpthCaMG - - - "" - +typedef ^ ^ ReKi DpthCp - - - "" - +typedef ^ ^ ReKi DpthCpMG - - - "" - +typedef ^ ^ ReKi DpthAxCa - - - "" - +typedef ^ ^ ReKi DpthAxCaMG - - - "" - +typedef ^ ^ ReKi DpthAxCp - - - "" - +typedef ^ ^ ReKi DpthAxCpMG - - - "" - +typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "" - +typedef ^ ^ ReKi AxCd - - - "" - +typedef ^ ^ ReKi AxCa - - - "" - +typedef ^ ^ ReKi AxCp - - - "" - +typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "" - +typedef ^ ^ INTEGER MJointID1 - - - "" - +typedef ^ ^ INTEGER MJointID2 - - - "" - +typedef ^ ^ INTEGER MJointID1Indx - - - "" - +typedef ^ ^ INTEGER MJointID2Indx - - - "" - +typedef ^ ^ INTEGER MPropSetID1 - - - "" - +typedef ^ ^ INTEGER MPropSetID2 - - - "" - +typedef ^ ^ INTEGER MPropSetID1Indx - - - "" - +typedef ^ ^ INTEGER MPropSetID2Indx - - - "" - +typedef ^ ^ ReKi MDivSize - - - "" - +typedef ^ ^ INTEGER MCoefMod - - - "" - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "" - +typedef ^ ^ LOGICAL PropPot - - - "" - +#typedef ^ ^ INTEGER MGSplitState - - - "" - +#typedef ^ ^ INTEGER WtrSplitState - - - "" - +typedef ^ ^ INTEGER NumSplits - - - "" - +typedef ^ ^ ReKi Splits {5} - - "" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "" - +typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "" - +typedef ^ ^ INTEGER JointIndx - - - "" - +typedef ^ ^ ReKi JointPos {3} - - "" - +typedef ^ ^ INTEGER JointOvrlp - - - "" - +typedef ^ ^ INTEGER JointAxIDIndx - - - "" - +typedef ^ ^ INTEGER NConnections - - - "" - +typedef ^ ^ INTEGER ConnectionList {10} - - "" - +typedef ^ ^ INTEGER NConnectPreSplit - - - "" - +typedef ^ ^ ReKi Cd - - - "" - +typedef ^ ^ ReKi CdMG - - - "" - +typedef ^ ^ ReKi Ca - - - "" - +typedef ^ ^ ReKi CaMG - - - "" - +typedef ^ ^ ReKi Cp - - - "" - +typedef ^ ^ ReKi CpMG - - - "" - +typedef ^ ^ ReKi JAxCd - - - "" - +typedef ^ ^ ReKi JAxCa - - - "" - +typedef ^ ^ ReKi JAxCp - - - "" - +typedef ^ ^ ReKi AxCa - - - "" - +typedef ^ ^ ReKi AxCp - - - "" - +typedef ^ ^ ReKi AxCaMG - - - "" - +typedef ^ ^ ReKi AxCpMG - - - "" - +typedef ^ ^ ReKi R - - - "" - +typedef ^ ^ ReKi t - - - "" - +typedef ^ ^ ReKi tMG - - - "" - +typedef ^ ^ ReKi dRdz - - - "" - +typedef ^ ^ ReKi MGdensity - - - "" - +typedef ^ ^ ReKi FillFSLoc - - - "" - +typedef ^ ^ LOGICAL FillFlag - - - "" - +typedef ^ ^ ReKi FillDensity - - - "" - +typedef ^ ^ INTEGER InpMbrIndx - - - "" - +typedef ^ ^ ReKi InpMbrDist - - - "" - +typedef ^ ^ LOGICAL PropPot - - - "" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "" - +typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "" - +typedef ^ ^ INTEGER Node2Indx - - - "" - +typedef ^ ^ ReKi R1 - - - "" - +typedef ^ ^ ReKi t1 - - - "" - +typedef ^ ^ ReKi R2 - - - "" - +typedef ^ ^ ReKi t2 - - - "" - +typedef ^ ^ ReKi Cd1 - - - "" - +typedef ^ ^ ReKi CdMG1 - - - "" - +typedef ^ ^ ReKi Ca1 - - - "" - +typedef ^ ^ ReKi CaMG1 - - - "" - +typedef ^ ^ ReKi Cp1 - - - "" - +typedef ^ ^ ReKi CpMG1 - - - "" - +typedef ^ ^ ReKi AxCa1 - - - "" - +typedef ^ ^ ReKi AxCaMG1 - - - "" - +typedef ^ ^ ReKi AxCp1 - - - "" - +typedef ^ ^ ReKi AxCpMG1 - - - "" - +typedef ^ ^ ReKi Cd2 - - - "" - +typedef ^ ^ ReKi CdMG2 - - - "" - +typedef ^ ^ ReKi Ca2 - - - "" - +typedef ^ ^ ReKi CaMG2 - - - "" - +typedef ^ ^ ReKi Cp2 - - - "" - +typedef ^ ^ ReKi CpMG2 - - - "" - +typedef ^ ^ ReKi AxCa2 - - - "" - +typedef ^ ^ ReKi AxCaMG2 - - - "" - +typedef ^ ^ ReKi AxCp2 - - - "" - +typedef ^ ^ ReKi AxCpMG2 - - - "" - +typedef ^ ^ ReKi InpMbrDist1 - - - "" - +typedef ^ ^ ReKi InpMbrDist2 - - - "" - +typedef ^ ^ ReKi InpMbrLen - - - "" - +typedef ^ ^ INTEGER InpMbrIndx - - - "" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "" - +#typedef ^ ^ INTEGER MGSplitState - - - "" - +#typedef ^ ^ INTEGER WtrSplitState - - - "" - +typedef ^ ^ INTEGER NumSplits - - - "" - +typedef ^ ^ ReKi Splits {5} - - "" - +typedef ^ ^ ReKi MGvolume - - - "" - +typedef ^ ^ ReKi MDivSize - - - "" - +typedef ^ ^ INTEGER MCoefMod - - - "" - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "" - +typedef ^ ^ ReKi FillFSLoc - - - "" - +typedef ^ ^ ReKi FillDens - - - "" - +typedef ^ ^ ReKi F_Bouy {6} - - "" - +typedef ^ ^ ReKi F_DP {6} - - "" - +typedef ^ ^ LOGICAL PropPot - - - "" - +typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "" - +typedef ^ ^ ReKi MemberCd1 - - - "" - +typedef ^ ^ ReKi MemberCd2 - - - "" - +typedef ^ ^ ReKi MemberCdMG1 - - - "" - +typedef ^ ^ ReKi MemberCdMG2 - - - "" - +typedef ^ ^ ReKi MemberCa1 - - - "" - +typedef ^ ^ ReKi MemberCa2 - - - "" - +typedef ^ ^ ReKi MemberCaMG1 - - - "" - +typedef ^ ^ ReKi MemberCaMG2 - - - "" - +typedef ^ ^ ReKi MemberCp1 - - - "" - +typedef ^ ^ ReKi MemberCp2 - - - "" - +typedef ^ ^ ReKi MemberCpMG1 - - - "" - +typedef ^ ^ ReKi MemberCpMG2 - - - "" - +typedef ^ ^ ReKi MemberAxCa1 - - - "" - +typedef ^ ^ ReKi MemberAxCa2 - - - "" - +typedef ^ ^ ReKi MemberAxCaMG1 - - - "" - +typedef ^ ^ ReKi MemberAxCaMG2 - - - "" - +typedef ^ ^ ReKi MemberAxCp1 - - - "" - +typedef ^ ^ ReKi MemberAxCp2 - - - "" - +typedef ^ ^ ReKi MemberAxCpMG1 - - - "" - +typedef ^ ^ ReKi MemberAxCpMG2 - - - "" - +typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "" - +typedef ^ ^ ReKi MGThck - - - "" - +typedef ^ ^ ReKi MGDens - - - "" - +typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "" - +typedef ^ ^ INTEGER NOutLoc - - - "" - +typedef ^ ^ ReKi NodeLocs {:} - - "" - +typedef ^ ^ INTEGER MemberIDIndx - - - "" - +typedef ^ ^ INTEGER Marker1 {:} - - "" - +typedef ^ ^ INTEGER Marker2 {:} - - "" - +typedef ^ ^ ReKi s {:} - - "" - +typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "" - +typedef ^ ^ INTEGER JointIDIndx - - - "" - +typedef ^ ^ INTEGER NumMarkers - - - "" - +typedef ^ ^ INTEGER Markers {10} - - "" - +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Morison/Morison InitInputType ReKi Gravity - - - "" - +typedef ^ ^ ReKi WtrDens - - - "" - +typedef ^ ^ ReKi WtrDpth - - - "" - +typedef ^ ^ ReKi MSL2SWL - - - "" - +typedef ^ ^ INTEGER NJoints - - - "" - +typedef ^ ^ INTEGER NNodes - - - "" - +typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "" - +typedef ^ ^ Morison_JointType InpJoints {:} - - "" - +typedef ^ ^ Morison_NodeType Nodes {:} - - "" - +typedef ^ ^ INTEGER NElements - - - "" - +typedef ^ ^ Morison_MemberType Elements {:} - - "" - +typedef ^ ^ INTEGER NAxCoefs - - - "" - +typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "" - +typedef ^ ^ INTEGER NPropSets - - - "" - +typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "" - +typedef ^ ^ ReKi SimplCd - - - "" - +typedef ^ ^ ReKi SimplCdMG - - - "" - +typedef ^ ^ ReKi SimplCa - - - "" - +typedef ^ ^ ReKi SimplCaMG - - - "" - +typedef ^ ^ ReKi SimplCp - - - "" - +typedef ^ ^ ReKi SimplCpMG - - - "" - +typedef ^ ^ ReKi SimplAxCa - - - "" - +typedef ^ ^ ReKi SimplAxCaMG - - - "" - +typedef ^ ^ ReKi SimplAxCp - - - "" - +typedef ^ ^ ReKi SimplAxCpMG - - - "" - +typedef ^ ^ INTEGER NCoefDpth - - - "" - +typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - +typedef ^ ^ INTEGER NCoefMembers - - - "" - +typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - +typedef ^ ^ INTEGER NMembers - - - "" - +typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "" - +typedef ^ ^ INTEGER NFillGroups - - - "" - +typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - +typedef ^ ^ INTEGER NMGDepths - - - "" - +typedef ^ ^ Morison_MGDepthsType MGDepths {:} - - "" - +typedef ^ ^ ReKi MGTop - - - "" - +typedef ^ ^ ReKi MGBottom - - - "" - +typedef ^ ^ INTEGER NMOutputs - - - "" - +typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - +typedef ^ ^ INTEGER NJOutputs - - - "" - +typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - +typedef ^ ^ CHARACTER(ChanLen) OutList {4032} - - "This list size needs to be the maximum # of possible outputs because of the use of ReadAry()" - +typedef ^ ^ LOGICAL ValidOutList {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER OutSwtch - - - "" - +typedef ^ ^ LOGICAL OutAll - - - "" - +typedef ^ ^ CHARACTER(1024) OutRootName - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - +typedef ^ ^ INTEGER UnSum - - - "" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - +typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - +typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType MeshType DistribMesh - - - "" - +typedef ^ ^ MeshType LumpedMesh - - - "" - +typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) +typedef ^ ^ CHARACTER(ChanLen) WriteOutputHdr {:} - - "" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# +# +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType IntKi 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 D_F_D {:}{:} - - "Distributed viscous drag loads" - +typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads" - +typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads" - +#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Distributed dynamic pressure loads" - +typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads" - +typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads" - +typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads" - +typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid" - +typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node" - +typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node" - +typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node" - +typedef ^ ^ ReKi L_F_B {:}{:} - - "" - +typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads" - +typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads" - +typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads" - +typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads" - +typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node" - +typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node" - +typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node" - +typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) +typedef ^ ^ ReKi WtrDens - - - "" - +typedef ^ ^ INTEGER NNodes - - - "" - +typedef ^ ^ Morison_NodeType Nodes {:} - - "" - +typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "" - +typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - +typedef ^ ^ ReKi D_dragConst {:} - - "" - +typedef ^ ^ ReKi L_An {:}{:} - - "" - +typedef ^ ^ ReKi L_F_B {:}{:} - - "" - +typedef ^ ^ ReKi L_F_I {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_F_DP {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_F_BF {:}{:} - - "" - +typedef ^ ^ ReKi L_AM_M {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_dragConst {:} - - "" - +typedef ^ ^ INTEGER NDistribMarkers - - - "" - +#typedef ^ ^ Morison_NodeType DistribMarkers {:} - - "" - +typedef ^ ^ INTEGER distribToNodeIndx {:} - - "" - +typedef ^ ^ INTEGER NLumpedMarkers - - - "" - +typedef ^ ^ INTEGER lumpedToNodeIndx {:} - - "" - +typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ INTEGER elementWaterState {:}{:} - - "State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2]" - +typedef ^ ^ INTEGER elementFillState {:} - - "State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2]" - +typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed buoyancy loads" - +typedef ^ ^ ReKi D_F_BF {:}{:} - - "Distributed filled buoyancy loads" - +typedef ^ ^ ReKi D_F_MG {:}{:} - - "Distributed marine growth loads" - +typedef ^ ^ ReKi D_AM_M {:}{:}{:} - - "Distributed member added mass matrix" - +typedef ^ ^ ReKi D_AM_MG {:} - - "Distributed marine growth added mass matrix (weight)" - +typedef ^ ^ ReKi D_AM_F {:} - - "Distributed added mass matrix due to flooding/filled fluid" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ INTEGER NMOutputs - - - "" - +typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - +typedef ^ ^ INTEGER NJOutputs - - - "" - +typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ INTEGER OutSwtch - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - +typedef ^ ^ CHARACTER(ChanLen) Delim - - - "" - +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType MeshType DistribMesh - - - "Distributed Loads Meshed input data" - +typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed input data" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType DistribMesh - - - "Distributed Loads Meshed output data" - +typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed output data" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/Morison_Output.f90 b/OpenFAST/modules/hydrodyn/src/Morison_Output.f90 new file mode 100644 index 000000000..f859a3a55 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Morison_Output.f90 @@ -0,0 +1,7698 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 Morison_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + !USE Morison + USE Morison_Types + !USE HydroDyn_Output_Types + USE Waves + IMPLICIT NONE + + PRIVATE + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter +! This code was generated by Write_ChckOutLst.m at 04-Jan-2014 12:13:30. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array y%AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: M1N1Axi = 1 + INTEGER(IntKi), PARAMETER :: M1N2Axi = 2 + INTEGER(IntKi), PARAMETER :: M1N3Axi = 3 + INTEGER(IntKi), PARAMETER :: M1N4Axi = 4 + INTEGER(IntKi), PARAMETER :: M1N5Axi = 5 + INTEGER(IntKi), PARAMETER :: M1N6Axi = 6 + INTEGER(IntKi), PARAMETER :: M1N7Axi = 7 + INTEGER(IntKi), PARAMETER :: M1N8Axi = 8 + INTEGER(IntKi), PARAMETER :: M1N9Axi = 9 + INTEGER(IntKi), PARAMETER :: M2N1Axi = 10 + INTEGER(IntKi), PARAMETER :: M2N2Axi = 11 + INTEGER(IntKi), PARAMETER :: M2N3Axi = 12 + INTEGER(IntKi), PARAMETER :: M2N4Axi = 13 + INTEGER(IntKi), PARAMETER :: M2N5Axi = 14 + INTEGER(IntKi), PARAMETER :: M2N6Axi = 15 + INTEGER(IntKi), PARAMETER :: M2N7Axi = 16 + INTEGER(IntKi), PARAMETER :: M2N8Axi = 17 + INTEGER(IntKi), PARAMETER :: M2N9Axi = 18 + INTEGER(IntKi), PARAMETER :: M3N1Axi = 19 + INTEGER(IntKi), PARAMETER :: M3N2Axi = 20 + INTEGER(IntKi), PARAMETER :: M3N3Axi = 21 + INTEGER(IntKi), PARAMETER :: M3N4Axi = 22 + INTEGER(IntKi), PARAMETER :: M3N5Axi = 23 + INTEGER(IntKi), PARAMETER :: M3N6Axi = 24 + INTEGER(IntKi), PARAMETER :: M3N7Axi = 25 + INTEGER(IntKi), PARAMETER :: M3N8Axi = 26 + INTEGER(IntKi), PARAMETER :: M3N9Axi = 27 + INTEGER(IntKi), PARAMETER :: M4N1Axi = 28 + INTEGER(IntKi), PARAMETER :: M4N2Axi = 29 + INTEGER(IntKi), PARAMETER :: M4N3Axi = 30 + INTEGER(IntKi), PARAMETER :: M4N4Axi = 31 + INTEGER(IntKi), PARAMETER :: M4N5Axi = 32 + INTEGER(IntKi), PARAMETER :: M4N6Axi = 33 + INTEGER(IntKi), PARAMETER :: M4N7Axi = 34 + INTEGER(IntKi), PARAMETER :: M4N8Axi = 35 + INTEGER(IntKi), PARAMETER :: M4N9Axi = 36 + INTEGER(IntKi), PARAMETER :: M5N1Axi = 37 + INTEGER(IntKi), PARAMETER :: M5N2Axi = 38 + INTEGER(IntKi), PARAMETER :: M5N3Axi = 39 + INTEGER(IntKi), PARAMETER :: M5N4Axi = 40 + INTEGER(IntKi), PARAMETER :: M5N5Axi = 41 + INTEGER(IntKi), PARAMETER :: M5N6Axi = 42 + INTEGER(IntKi), PARAMETER :: M5N7Axi = 43 + INTEGER(IntKi), PARAMETER :: M5N8Axi = 44 + INTEGER(IntKi), PARAMETER :: M5N9Axi = 45 + INTEGER(IntKi), PARAMETER :: M6N1Axi = 46 + INTEGER(IntKi), PARAMETER :: M6N2Axi = 47 + INTEGER(IntKi), PARAMETER :: M6N3Axi = 48 + INTEGER(IntKi), PARAMETER :: M6N4Axi = 49 + INTEGER(IntKi), PARAMETER :: M6N5Axi = 50 + INTEGER(IntKi), PARAMETER :: M6N6Axi = 51 + INTEGER(IntKi), PARAMETER :: M6N7Axi = 52 + INTEGER(IntKi), PARAMETER :: M6N8Axi = 53 + INTEGER(IntKi), PARAMETER :: M6N9Axi = 54 + INTEGER(IntKi), PARAMETER :: M7N1Axi = 55 + INTEGER(IntKi), PARAMETER :: M7N2Axi = 56 + INTEGER(IntKi), PARAMETER :: M7N3Axi = 57 + INTEGER(IntKi), PARAMETER :: M7N4Axi = 58 + INTEGER(IntKi), PARAMETER :: M7N5Axi = 59 + INTEGER(IntKi), PARAMETER :: M7N6Axi = 60 + INTEGER(IntKi), PARAMETER :: M7N7Axi = 61 + INTEGER(IntKi), PARAMETER :: M7N8Axi = 62 + INTEGER(IntKi), PARAMETER :: M7N9Axi = 63 + INTEGER(IntKi), PARAMETER :: M8N1Axi = 64 + INTEGER(IntKi), PARAMETER :: M8N2Axi = 65 + INTEGER(IntKi), PARAMETER :: M8N3Axi = 66 + INTEGER(IntKi), PARAMETER :: M8N4Axi = 67 + INTEGER(IntKi), PARAMETER :: M8N5Axi = 68 + INTEGER(IntKi), PARAMETER :: M8N6Axi = 69 + INTEGER(IntKi), PARAMETER :: M8N7Axi = 70 + INTEGER(IntKi), PARAMETER :: M8N8Axi = 71 + INTEGER(IntKi), PARAMETER :: M8N9Axi = 72 + INTEGER(IntKi), PARAMETER :: M9N1Axi = 73 + INTEGER(IntKi), PARAMETER :: M9N2Axi = 74 + INTEGER(IntKi), PARAMETER :: M9N3Axi = 75 + INTEGER(IntKi), PARAMETER :: M9N4Axi = 76 + INTEGER(IntKi), PARAMETER :: M9N5Axi = 77 + INTEGER(IntKi), PARAMETER :: M9N6Axi = 78 + INTEGER(IntKi), PARAMETER :: M9N7Axi = 79 + INTEGER(IntKi), PARAMETER :: M9N8Axi = 80 + INTEGER(IntKi), PARAMETER :: M9N9Axi = 81 + INTEGER(IntKi), PARAMETER :: M1N1Ayi = 82 + INTEGER(IntKi), PARAMETER :: M1N2Ayi = 83 + INTEGER(IntKi), PARAMETER :: M1N3Ayi = 84 + INTEGER(IntKi), PARAMETER :: M1N4Ayi = 85 + INTEGER(IntKi), PARAMETER :: M1N5Ayi = 86 + INTEGER(IntKi), PARAMETER :: M1N6Ayi = 87 + INTEGER(IntKi), PARAMETER :: M1N7Ayi = 88 + INTEGER(IntKi), PARAMETER :: M1N8Ayi = 89 + INTEGER(IntKi), PARAMETER :: M1N9Ayi = 90 + INTEGER(IntKi), PARAMETER :: M2N1Ayi = 91 + INTEGER(IntKi), PARAMETER :: M2N2Ayi = 92 + INTEGER(IntKi), PARAMETER :: M2N3Ayi = 93 + INTEGER(IntKi), PARAMETER :: M2N4Ayi = 94 + INTEGER(IntKi), PARAMETER :: M2N5Ayi = 95 + INTEGER(IntKi), PARAMETER :: M2N6Ayi = 96 + INTEGER(IntKi), PARAMETER :: M2N7Ayi = 97 + INTEGER(IntKi), PARAMETER :: M2N8Ayi = 98 + INTEGER(IntKi), PARAMETER :: M2N9Ayi = 99 + INTEGER(IntKi), PARAMETER :: M3N1Ayi = 100 + INTEGER(IntKi), PARAMETER :: M3N2Ayi = 101 + INTEGER(IntKi), PARAMETER :: M3N3Ayi = 102 + INTEGER(IntKi), PARAMETER :: M3N4Ayi = 103 + INTEGER(IntKi), PARAMETER :: M3N5Ayi = 104 + INTEGER(IntKi), PARAMETER :: M3N6Ayi = 105 + INTEGER(IntKi), PARAMETER :: M3N7Ayi = 106 + INTEGER(IntKi), PARAMETER :: M3N8Ayi = 107 + INTEGER(IntKi), PARAMETER :: M3N9Ayi = 108 + INTEGER(IntKi), PARAMETER :: M4N1Ayi = 109 + INTEGER(IntKi), PARAMETER :: M4N2Ayi = 110 + INTEGER(IntKi), PARAMETER :: M4N3Ayi = 111 + INTEGER(IntKi), PARAMETER :: M4N4Ayi = 112 + INTEGER(IntKi), PARAMETER :: M4N5Ayi = 113 + INTEGER(IntKi), PARAMETER :: M4N6Ayi = 114 + INTEGER(IntKi), PARAMETER :: M4N7Ayi = 115 + INTEGER(IntKi), PARAMETER :: M4N8Ayi = 116 + INTEGER(IntKi), PARAMETER :: M4N9Ayi = 117 + INTEGER(IntKi), PARAMETER :: M5N1Ayi = 118 + INTEGER(IntKi), PARAMETER :: M5N2Ayi = 119 + INTEGER(IntKi), PARAMETER :: M5N3Ayi = 120 + INTEGER(IntKi), PARAMETER :: M5N4Ayi = 121 + INTEGER(IntKi), PARAMETER :: M5N5Ayi = 122 + INTEGER(IntKi), PARAMETER :: M5N6Ayi = 123 + INTEGER(IntKi), PARAMETER :: M5N7Ayi = 124 + INTEGER(IntKi), PARAMETER :: M5N8Ayi = 125 + INTEGER(IntKi), PARAMETER :: M5N9Ayi = 126 + INTEGER(IntKi), PARAMETER :: M6N1Ayi = 127 + INTEGER(IntKi), PARAMETER :: M6N2Ayi = 128 + INTEGER(IntKi), PARAMETER :: M6N3Ayi = 129 + INTEGER(IntKi), PARAMETER :: M6N4Ayi = 130 + INTEGER(IntKi), PARAMETER :: M6N5Ayi = 131 + INTEGER(IntKi), PARAMETER :: M6N6Ayi = 132 + INTEGER(IntKi), PARAMETER :: M6N7Ayi = 133 + INTEGER(IntKi), PARAMETER :: M6N8Ayi = 134 + INTEGER(IntKi), PARAMETER :: M6N9Ayi = 135 + INTEGER(IntKi), PARAMETER :: M7N1Ayi = 136 + INTEGER(IntKi), PARAMETER :: M7N2Ayi = 137 + INTEGER(IntKi), PARAMETER :: M7N3Ayi = 138 + INTEGER(IntKi), PARAMETER :: M7N4Ayi = 139 + INTEGER(IntKi), PARAMETER :: M7N5Ayi = 140 + INTEGER(IntKi), PARAMETER :: M7N6Ayi = 141 + INTEGER(IntKi), PARAMETER :: M7N7Ayi = 142 + INTEGER(IntKi), PARAMETER :: M7N8Ayi = 143 + INTEGER(IntKi), PARAMETER :: M7N9Ayi = 144 + INTEGER(IntKi), PARAMETER :: M8N1Ayi = 145 + INTEGER(IntKi), PARAMETER :: M8N2Ayi = 146 + INTEGER(IntKi), PARAMETER :: M8N3Ayi = 147 + INTEGER(IntKi), PARAMETER :: M8N4Ayi = 148 + INTEGER(IntKi), PARAMETER :: M8N5Ayi = 149 + INTEGER(IntKi), PARAMETER :: M8N6Ayi = 150 + INTEGER(IntKi), PARAMETER :: M8N7Ayi = 151 + INTEGER(IntKi), PARAMETER :: M8N8Ayi = 152 + INTEGER(IntKi), PARAMETER :: M8N9Ayi = 153 + INTEGER(IntKi), PARAMETER :: M9N1Ayi = 154 + INTEGER(IntKi), PARAMETER :: M9N2Ayi = 155 + INTEGER(IntKi), PARAMETER :: M9N3Ayi = 156 + INTEGER(IntKi), PARAMETER :: M9N4Ayi = 157 + INTEGER(IntKi), PARAMETER :: M9N5Ayi = 158 + INTEGER(IntKi), PARAMETER :: M9N6Ayi = 159 + INTEGER(IntKi), PARAMETER :: M9N7Ayi = 160 + INTEGER(IntKi), PARAMETER :: M9N8Ayi = 161 + INTEGER(IntKi), PARAMETER :: M9N9Ayi = 162 + INTEGER(IntKi), PARAMETER :: M1N1Azi = 163 + INTEGER(IntKi), PARAMETER :: M1N2Azi = 164 + INTEGER(IntKi), PARAMETER :: M1N3Azi = 165 + INTEGER(IntKi), PARAMETER :: M1N4Azi = 166 + INTEGER(IntKi), PARAMETER :: M1N5Azi = 167 + INTEGER(IntKi), PARAMETER :: M1N6Azi = 168 + INTEGER(IntKi), PARAMETER :: M1N7Azi = 169 + INTEGER(IntKi), PARAMETER :: M1N8Azi = 170 + INTEGER(IntKi), PARAMETER :: M1N9Azi = 171 + INTEGER(IntKi), PARAMETER :: M2N1Azi = 172 + INTEGER(IntKi), PARAMETER :: M2N2Azi = 173 + INTEGER(IntKi), PARAMETER :: M2N3Azi = 174 + INTEGER(IntKi), PARAMETER :: M2N4Azi = 175 + INTEGER(IntKi), PARAMETER :: M2N5Azi = 176 + INTEGER(IntKi), PARAMETER :: M2N6Azi = 177 + INTEGER(IntKi), PARAMETER :: M2N7Azi = 178 + INTEGER(IntKi), PARAMETER :: M2N8Azi = 179 + INTEGER(IntKi), PARAMETER :: M2N9Azi = 180 + INTEGER(IntKi), PARAMETER :: M3N1Azi = 181 + INTEGER(IntKi), PARAMETER :: M3N2Azi = 182 + INTEGER(IntKi), PARAMETER :: M3N3Azi = 183 + INTEGER(IntKi), PARAMETER :: M3N4Azi = 184 + INTEGER(IntKi), PARAMETER :: M3N5Azi = 185 + INTEGER(IntKi), PARAMETER :: M3N6Azi = 186 + INTEGER(IntKi), PARAMETER :: M3N7Azi = 187 + INTEGER(IntKi), PARAMETER :: M3N8Azi = 188 + INTEGER(IntKi), PARAMETER :: M3N9Azi = 189 + INTEGER(IntKi), PARAMETER :: M4N1Azi = 190 + INTEGER(IntKi), PARAMETER :: M4N2Azi = 191 + INTEGER(IntKi), PARAMETER :: M4N3Azi = 192 + INTEGER(IntKi), PARAMETER :: M4N4Azi = 193 + INTEGER(IntKi), PARAMETER :: M4N5Azi = 194 + INTEGER(IntKi), PARAMETER :: M4N6Azi = 195 + INTEGER(IntKi), PARAMETER :: M4N7Azi = 196 + INTEGER(IntKi), PARAMETER :: M4N8Azi = 197 + INTEGER(IntKi), PARAMETER :: M4N9Azi = 198 + INTEGER(IntKi), PARAMETER :: M5N1Azi = 199 + INTEGER(IntKi), PARAMETER :: M5N2Azi = 200 + INTEGER(IntKi), PARAMETER :: M5N3Azi = 201 + INTEGER(IntKi), PARAMETER :: M5N4Azi = 202 + INTEGER(IntKi), PARAMETER :: M5N5Azi = 203 + INTEGER(IntKi), PARAMETER :: M5N6Azi = 204 + INTEGER(IntKi), PARAMETER :: M5N7Azi = 205 + INTEGER(IntKi), PARAMETER :: M5N8Azi = 206 + INTEGER(IntKi), PARAMETER :: M5N9Azi = 207 + INTEGER(IntKi), PARAMETER :: M6N1Azi = 208 + INTEGER(IntKi), PARAMETER :: M6N2Azi = 209 + INTEGER(IntKi), PARAMETER :: M6N3Azi = 210 + INTEGER(IntKi), PARAMETER :: M6N4Azi = 211 + INTEGER(IntKi), PARAMETER :: M6N5Azi = 212 + INTEGER(IntKi), PARAMETER :: M6N6Azi = 213 + INTEGER(IntKi), PARAMETER :: M6N7Azi = 214 + INTEGER(IntKi), PARAMETER :: M6N8Azi = 215 + INTEGER(IntKi), PARAMETER :: M6N9Azi = 216 + INTEGER(IntKi), PARAMETER :: M7N1Azi = 217 + INTEGER(IntKi), PARAMETER :: M7N2Azi = 218 + INTEGER(IntKi), PARAMETER :: M7N3Azi = 219 + INTEGER(IntKi), PARAMETER :: M7N4Azi = 220 + INTEGER(IntKi), PARAMETER :: M7N5Azi = 221 + INTEGER(IntKi), PARAMETER :: M7N6Azi = 222 + INTEGER(IntKi), PARAMETER :: M7N7Azi = 223 + INTEGER(IntKi), PARAMETER :: M7N8Azi = 224 + INTEGER(IntKi), PARAMETER :: M7N9Azi = 225 + INTEGER(IntKi), PARAMETER :: M8N1Azi = 226 + INTEGER(IntKi), PARAMETER :: M8N2Azi = 227 + INTEGER(IntKi), PARAMETER :: M8N3Azi = 228 + INTEGER(IntKi), PARAMETER :: M8N4Azi = 229 + INTEGER(IntKi), PARAMETER :: M8N5Azi = 230 + INTEGER(IntKi), PARAMETER :: M8N6Azi = 231 + INTEGER(IntKi), PARAMETER :: M8N7Azi = 232 + INTEGER(IntKi), PARAMETER :: M8N8Azi = 233 + INTEGER(IntKi), PARAMETER :: M8N9Azi = 234 + INTEGER(IntKi), PARAMETER :: M9N1Azi = 235 + INTEGER(IntKi), PARAMETER :: M9N2Azi = 236 + INTEGER(IntKi), PARAMETER :: M9N3Azi = 237 + INTEGER(IntKi), PARAMETER :: M9N4Azi = 238 + INTEGER(IntKi), PARAMETER :: M9N5Azi = 239 + INTEGER(IntKi), PARAMETER :: M9N6Azi = 240 + INTEGER(IntKi), PARAMETER :: M9N7Azi = 241 + INTEGER(IntKi), PARAMETER :: M9N8Azi = 242 + INTEGER(IntKi), PARAMETER :: M9N9Azi = 243 + INTEGER(IntKi), PARAMETER :: M1N1Vxi = 244 + INTEGER(IntKi), PARAMETER :: M1N2Vxi = 245 + INTEGER(IntKi), PARAMETER :: M1N3Vxi = 246 + INTEGER(IntKi), PARAMETER :: M1N4Vxi = 247 + INTEGER(IntKi), PARAMETER :: M1N5Vxi = 248 + INTEGER(IntKi), PARAMETER :: M1N6Vxi = 249 + INTEGER(IntKi), PARAMETER :: M1N7Vxi = 250 + INTEGER(IntKi), PARAMETER :: M1N8Vxi = 251 + INTEGER(IntKi), PARAMETER :: M1N9Vxi = 252 + INTEGER(IntKi), PARAMETER :: M2N1Vxi = 253 + INTEGER(IntKi), PARAMETER :: M2N2Vxi = 254 + INTEGER(IntKi), PARAMETER :: M2N3Vxi = 255 + INTEGER(IntKi), PARAMETER :: M2N4Vxi = 256 + INTEGER(IntKi), PARAMETER :: M2N5Vxi = 257 + INTEGER(IntKi), PARAMETER :: M2N6Vxi = 258 + INTEGER(IntKi), PARAMETER :: M2N7Vxi = 259 + INTEGER(IntKi), PARAMETER :: M2N8Vxi = 260 + INTEGER(IntKi), PARAMETER :: M2N9Vxi = 261 + INTEGER(IntKi), PARAMETER :: M3N1Vxi = 262 + INTEGER(IntKi), PARAMETER :: M3N2Vxi = 263 + INTEGER(IntKi), PARAMETER :: M3N3Vxi = 264 + INTEGER(IntKi), PARAMETER :: M3N4Vxi = 265 + INTEGER(IntKi), PARAMETER :: M3N5Vxi = 266 + INTEGER(IntKi), PARAMETER :: M3N6Vxi = 267 + INTEGER(IntKi), PARAMETER :: M3N7Vxi = 268 + INTEGER(IntKi), PARAMETER :: M3N8Vxi = 269 + INTEGER(IntKi), PARAMETER :: M3N9Vxi = 270 + INTEGER(IntKi), PARAMETER :: M4N1Vxi = 271 + INTEGER(IntKi), PARAMETER :: M4N2Vxi = 272 + INTEGER(IntKi), PARAMETER :: M4N3Vxi = 273 + INTEGER(IntKi), PARAMETER :: M4N4Vxi = 274 + INTEGER(IntKi), PARAMETER :: M4N5Vxi = 275 + INTEGER(IntKi), PARAMETER :: M4N6Vxi = 276 + INTEGER(IntKi), PARAMETER :: M4N7Vxi = 277 + INTEGER(IntKi), PARAMETER :: M4N8Vxi = 278 + INTEGER(IntKi), PARAMETER :: M4N9Vxi = 279 + INTEGER(IntKi), PARAMETER :: M5N1Vxi = 280 + INTEGER(IntKi), PARAMETER :: M5N2Vxi = 281 + INTEGER(IntKi), PARAMETER :: M5N3Vxi = 282 + INTEGER(IntKi), PARAMETER :: M5N4Vxi = 283 + INTEGER(IntKi), PARAMETER :: M5N5Vxi = 284 + INTEGER(IntKi), PARAMETER :: M5N6Vxi = 285 + INTEGER(IntKi), PARAMETER :: M5N7Vxi = 286 + INTEGER(IntKi), PARAMETER :: M5N8Vxi = 287 + INTEGER(IntKi), PARAMETER :: M5N9Vxi = 288 + INTEGER(IntKi), PARAMETER :: M6N1Vxi = 289 + INTEGER(IntKi), PARAMETER :: M6N2Vxi = 290 + INTEGER(IntKi), PARAMETER :: M6N3Vxi = 291 + INTEGER(IntKi), PARAMETER :: M6N4Vxi = 292 + INTEGER(IntKi), PARAMETER :: M6N5Vxi = 293 + INTEGER(IntKi), PARAMETER :: M6N6Vxi = 294 + INTEGER(IntKi), PARAMETER :: M6N7Vxi = 295 + INTEGER(IntKi), PARAMETER :: M6N8Vxi = 296 + INTEGER(IntKi), PARAMETER :: M6N9Vxi = 297 + INTEGER(IntKi), PARAMETER :: M7N1Vxi = 298 + INTEGER(IntKi), PARAMETER :: M7N2Vxi = 299 + INTEGER(IntKi), PARAMETER :: M7N3Vxi = 300 + INTEGER(IntKi), PARAMETER :: M7N4Vxi = 301 + INTEGER(IntKi), PARAMETER :: M7N5Vxi = 302 + INTEGER(IntKi), PARAMETER :: M7N6Vxi = 303 + INTEGER(IntKi), PARAMETER :: M7N7Vxi = 304 + INTEGER(IntKi), PARAMETER :: M7N8Vxi = 305 + INTEGER(IntKi), PARAMETER :: M7N9Vxi = 306 + INTEGER(IntKi), PARAMETER :: M8N1Vxi = 307 + INTEGER(IntKi), PARAMETER :: M8N2Vxi = 308 + INTEGER(IntKi), PARAMETER :: M8N3Vxi = 309 + INTEGER(IntKi), PARAMETER :: M8N4Vxi = 310 + INTEGER(IntKi), PARAMETER :: M8N5Vxi = 311 + INTEGER(IntKi), PARAMETER :: M8N6Vxi = 312 + INTEGER(IntKi), PARAMETER :: M8N7Vxi = 313 + INTEGER(IntKi), PARAMETER :: M8N8Vxi = 314 + INTEGER(IntKi), PARAMETER :: M8N9Vxi = 315 + INTEGER(IntKi), PARAMETER :: M9N1Vxi = 316 + INTEGER(IntKi), PARAMETER :: M9N2Vxi = 317 + INTEGER(IntKi), PARAMETER :: M9N3Vxi = 318 + INTEGER(IntKi), PARAMETER :: M9N4Vxi = 319 + INTEGER(IntKi), PARAMETER :: M9N5Vxi = 320 + INTEGER(IntKi), PARAMETER :: M9N6Vxi = 321 + INTEGER(IntKi), PARAMETER :: M9N7Vxi = 322 + INTEGER(IntKi), PARAMETER :: M9N8Vxi = 323 + INTEGER(IntKi), PARAMETER :: M9N9Vxi = 324 + INTEGER(IntKi), PARAMETER :: M1N1Vyi = 325 + INTEGER(IntKi), PARAMETER :: M1N2Vyi = 326 + INTEGER(IntKi), PARAMETER :: M1N3Vyi = 327 + INTEGER(IntKi), PARAMETER :: M1N4Vyi = 328 + INTEGER(IntKi), PARAMETER :: M1N5Vyi = 329 + INTEGER(IntKi), PARAMETER :: M1N6Vyi = 330 + INTEGER(IntKi), PARAMETER :: M1N7Vyi = 331 + INTEGER(IntKi), PARAMETER :: M1N8Vyi = 332 + INTEGER(IntKi), PARAMETER :: M1N9Vyi = 333 + INTEGER(IntKi), PARAMETER :: M2N1Vyi = 334 + INTEGER(IntKi), PARAMETER :: M2N2Vyi = 335 + INTEGER(IntKi), PARAMETER :: M2N3Vyi = 336 + INTEGER(IntKi), PARAMETER :: M2N4Vyi = 337 + INTEGER(IntKi), PARAMETER :: M2N5Vyi = 338 + INTEGER(IntKi), PARAMETER :: M2N6Vyi = 339 + INTEGER(IntKi), PARAMETER :: M2N7Vyi = 340 + INTEGER(IntKi), PARAMETER :: M2N8Vyi = 341 + INTEGER(IntKi), PARAMETER :: M2N9Vyi = 342 + INTEGER(IntKi), PARAMETER :: M3N1Vyi = 343 + INTEGER(IntKi), PARAMETER :: M3N2Vyi = 344 + INTEGER(IntKi), PARAMETER :: M3N3Vyi = 345 + INTEGER(IntKi), PARAMETER :: M3N4Vyi = 346 + INTEGER(IntKi), PARAMETER :: M3N5Vyi = 347 + INTEGER(IntKi), PARAMETER :: M3N6Vyi = 348 + INTEGER(IntKi), PARAMETER :: M3N7Vyi = 349 + INTEGER(IntKi), PARAMETER :: M3N8Vyi = 350 + INTEGER(IntKi), PARAMETER :: M3N9Vyi = 351 + INTEGER(IntKi), PARAMETER :: M4N1Vyi = 352 + INTEGER(IntKi), PARAMETER :: M4N2Vyi = 353 + INTEGER(IntKi), PARAMETER :: M4N3Vyi = 354 + INTEGER(IntKi), PARAMETER :: M4N4Vyi = 355 + INTEGER(IntKi), PARAMETER :: M4N5Vyi = 356 + INTEGER(IntKi), PARAMETER :: M4N6Vyi = 357 + INTEGER(IntKi), PARAMETER :: M4N7Vyi = 358 + INTEGER(IntKi), PARAMETER :: M4N8Vyi = 359 + INTEGER(IntKi), PARAMETER :: M4N9Vyi = 360 + INTEGER(IntKi), PARAMETER :: M5N1Vyi = 361 + INTEGER(IntKi), PARAMETER :: M5N2Vyi = 362 + INTEGER(IntKi), PARAMETER :: M5N3Vyi = 363 + INTEGER(IntKi), PARAMETER :: M5N4Vyi = 364 + INTEGER(IntKi), PARAMETER :: M5N5Vyi = 365 + INTEGER(IntKi), PARAMETER :: M5N6Vyi = 366 + INTEGER(IntKi), PARAMETER :: M5N7Vyi = 367 + INTEGER(IntKi), PARAMETER :: M5N8Vyi = 368 + INTEGER(IntKi), PARAMETER :: M5N9Vyi = 369 + INTEGER(IntKi), PARAMETER :: M6N1Vyi = 370 + INTEGER(IntKi), PARAMETER :: M6N2Vyi = 371 + INTEGER(IntKi), PARAMETER :: M6N3Vyi = 372 + INTEGER(IntKi), PARAMETER :: M6N4Vyi = 373 + INTEGER(IntKi), PARAMETER :: M6N5Vyi = 374 + INTEGER(IntKi), PARAMETER :: M6N6Vyi = 375 + INTEGER(IntKi), PARAMETER :: M6N7Vyi = 376 + INTEGER(IntKi), PARAMETER :: M6N8Vyi = 377 + INTEGER(IntKi), PARAMETER :: M6N9Vyi = 378 + INTEGER(IntKi), PARAMETER :: M7N1Vyi = 379 + INTEGER(IntKi), PARAMETER :: M7N2Vyi = 380 + INTEGER(IntKi), PARAMETER :: M7N3Vyi = 381 + INTEGER(IntKi), PARAMETER :: M7N4Vyi = 382 + INTEGER(IntKi), PARAMETER :: M7N5Vyi = 383 + INTEGER(IntKi), PARAMETER :: M7N6Vyi = 384 + INTEGER(IntKi), PARAMETER :: M7N7Vyi = 385 + INTEGER(IntKi), PARAMETER :: M7N8Vyi = 386 + INTEGER(IntKi), PARAMETER :: M7N9Vyi = 387 + INTEGER(IntKi), PARAMETER :: M8N1Vyi = 388 + INTEGER(IntKi), PARAMETER :: M8N2Vyi = 389 + INTEGER(IntKi), PARAMETER :: M8N3Vyi = 390 + INTEGER(IntKi), PARAMETER :: M8N4Vyi = 391 + INTEGER(IntKi), PARAMETER :: M8N5Vyi = 392 + INTEGER(IntKi), PARAMETER :: M8N6Vyi = 393 + INTEGER(IntKi), PARAMETER :: M8N7Vyi = 394 + INTEGER(IntKi), PARAMETER :: M8N8Vyi = 395 + INTEGER(IntKi), PARAMETER :: M8N9Vyi = 396 + INTEGER(IntKi), PARAMETER :: M9N1Vyi = 397 + INTEGER(IntKi), PARAMETER :: M9N2Vyi = 398 + INTEGER(IntKi), PARAMETER :: M9N3Vyi = 399 + INTEGER(IntKi), PARAMETER :: M9N4Vyi = 400 + INTEGER(IntKi), PARAMETER :: M9N5Vyi = 401 + INTEGER(IntKi), PARAMETER :: M9N6Vyi = 402 + INTEGER(IntKi), PARAMETER :: M9N7Vyi = 403 + INTEGER(IntKi), PARAMETER :: M9N8Vyi = 404 + INTEGER(IntKi), PARAMETER :: M9N9Vyi = 405 + INTEGER(IntKi), PARAMETER :: M1N1Vzi = 406 + INTEGER(IntKi), PARAMETER :: M1N2Vzi = 407 + INTEGER(IntKi), PARAMETER :: M1N3Vzi = 408 + INTEGER(IntKi), PARAMETER :: M1N4Vzi = 409 + INTEGER(IntKi), PARAMETER :: M1N5Vzi = 410 + INTEGER(IntKi), PARAMETER :: M1N6Vzi = 411 + INTEGER(IntKi), PARAMETER :: M1N7Vzi = 412 + INTEGER(IntKi), PARAMETER :: M1N8Vzi = 413 + INTEGER(IntKi), PARAMETER :: M1N9Vzi = 414 + INTEGER(IntKi), PARAMETER :: M2N1Vzi = 415 + INTEGER(IntKi), PARAMETER :: M2N2Vzi = 416 + INTEGER(IntKi), PARAMETER :: M2N3Vzi = 417 + INTEGER(IntKi), PARAMETER :: M2N4Vzi = 418 + INTEGER(IntKi), PARAMETER :: M2N5Vzi = 419 + INTEGER(IntKi), PARAMETER :: M2N6Vzi = 420 + INTEGER(IntKi), PARAMETER :: M2N7Vzi = 421 + INTEGER(IntKi), PARAMETER :: M2N8Vzi = 422 + INTEGER(IntKi), PARAMETER :: M2N9Vzi = 423 + INTEGER(IntKi), PARAMETER :: M3N1Vzi = 424 + INTEGER(IntKi), PARAMETER :: M3N2Vzi = 425 + INTEGER(IntKi), PARAMETER :: M3N3Vzi = 426 + INTEGER(IntKi), PARAMETER :: M3N4Vzi = 427 + INTEGER(IntKi), PARAMETER :: M3N5Vzi = 428 + INTEGER(IntKi), PARAMETER :: M3N6Vzi = 429 + INTEGER(IntKi), PARAMETER :: M3N7Vzi = 430 + INTEGER(IntKi), PARAMETER :: M3N8Vzi = 431 + INTEGER(IntKi), PARAMETER :: M3N9Vzi = 432 + INTEGER(IntKi), PARAMETER :: M4N1Vzi = 433 + INTEGER(IntKi), PARAMETER :: M4N2Vzi = 434 + INTEGER(IntKi), PARAMETER :: M4N3Vzi = 435 + INTEGER(IntKi), PARAMETER :: M4N4Vzi = 436 + INTEGER(IntKi), PARAMETER :: M4N5Vzi = 437 + INTEGER(IntKi), PARAMETER :: M4N6Vzi = 438 + INTEGER(IntKi), PARAMETER :: M4N7Vzi = 439 + INTEGER(IntKi), PARAMETER :: M4N8Vzi = 440 + INTEGER(IntKi), PARAMETER :: M4N9Vzi = 441 + INTEGER(IntKi), PARAMETER :: M5N1Vzi = 442 + INTEGER(IntKi), PARAMETER :: M5N2Vzi = 443 + INTEGER(IntKi), PARAMETER :: M5N3Vzi = 444 + INTEGER(IntKi), PARAMETER :: M5N4Vzi = 445 + INTEGER(IntKi), PARAMETER :: M5N5Vzi = 446 + INTEGER(IntKi), PARAMETER :: M5N6Vzi = 447 + INTEGER(IntKi), PARAMETER :: M5N7Vzi = 448 + INTEGER(IntKi), PARAMETER :: M5N8Vzi = 449 + INTEGER(IntKi), PARAMETER :: M5N9Vzi = 450 + INTEGER(IntKi), PARAMETER :: M6N1Vzi = 451 + INTEGER(IntKi), PARAMETER :: M6N2Vzi = 452 + INTEGER(IntKi), PARAMETER :: M6N3Vzi = 453 + INTEGER(IntKi), PARAMETER :: M6N4Vzi = 454 + INTEGER(IntKi), PARAMETER :: M6N5Vzi = 455 + INTEGER(IntKi), PARAMETER :: M6N6Vzi = 456 + INTEGER(IntKi), PARAMETER :: M6N7Vzi = 457 + INTEGER(IntKi), PARAMETER :: M6N8Vzi = 458 + INTEGER(IntKi), PARAMETER :: M6N9Vzi = 459 + INTEGER(IntKi), PARAMETER :: M7N1Vzi = 460 + INTEGER(IntKi), PARAMETER :: M7N2Vzi = 461 + INTEGER(IntKi), PARAMETER :: M7N3Vzi = 462 + INTEGER(IntKi), PARAMETER :: M7N4Vzi = 463 + INTEGER(IntKi), PARAMETER :: M7N5Vzi = 464 + INTEGER(IntKi), PARAMETER :: M7N6Vzi = 465 + INTEGER(IntKi), PARAMETER :: M7N7Vzi = 466 + INTEGER(IntKi), PARAMETER :: M7N8Vzi = 467 + INTEGER(IntKi), PARAMETER :: M7N9Vzi = 468 + INTEGER(IntKi), PARAMETER :: M8N1Vzi = 469 + INTEGER(IntKi), PARAMETER :: M8N2Vzi = 470 + INTEGER(IntKi), PARAMETER :: M8N3Vzi = 471 + INTEGER(IntKi), PARAMETER :: M8N4Vzi = 472 + INTEGER(IntKi), PARAMETER :: M8N5Vzi = 473 + INTEGER(IntKi), PARAMETER :: M8N6Vzi = 474 + INTEGER(IntKi), PARAMETER :: M8N7Vzi = 475 + INTEGER(IntKi), PARAMETER :: M8N8Vzi = 476 + INTEGER(IntKi), PARAMETER :: M8N9Vzi = 477 + INTEGER(IntKi), PARAMETER :: M9N1Vzi = 478 + INTEGER(IntKi), PARAMETER :: M9N2Vzi = 479 + INTEGER(IntKi), PARAMETER :: M9N3Vzi = 480 + INTEGER(IntKi), PARAMETER :: M9N4Vzi = 481 + INTEGER(IntKi), PARAMETER :: M9N5Vzi = 482 + INTEGER(IntKi), PARAMETER :: M9N6Vzi = 483 + INTEGER(IntKi), PARAMETER :: M9N7Vzi = 484 + INTEGER(IntKi), PARAMETER :: M9N8Vzi = 485 + INTEGER(IntKi), PARAMETER :: M9N9Vzi = 486 + INTEGER(IntKi), PARAMETER :: M1N1DynP = 487 + INTEGER(IntKi), PARAMETER :: M1N2DynP = 488 + INTEGER(IntKi), PARAMETER :: M1N3DynP = 489 + INTEGER(IntKi), PARAMETER :: M1N4DynP = 490 + INTEGER(IntKi), PARAMETER :: M1N5DynP = 491 + INTEGER(IntKi), PARAMETER :: M1N6DynP = 492 + INTEGER(IntKi), PARAMETER :: M1N7DynP = 493 + INTEGER(IntKi), PARAMETER :: M1N8DynP = 494 + INTEGER(IntKi), PARAMETER :: M1N9DynP = 495 + INTEGER(IntKi), PARAMETER :: M2N1DynP = 496 + INTEGER(IntKi), PARAMETER :: M2N2DynP = 497 + INTEGER(IntKi), PARAMETER :: M2N3DynP = 498 + INTEGER(IntKi), PARAMETER :: M2N4DynP = 499 + INTEGER(IntKi), PARAMETER :: M2N5DynP = 500 + INTEGER(IntKi), PARAMETER :: M2N6DynP = 501 + INTEGER(IntKi), PARAMETER :: M2N7DynP = 502 + INTEGER(IntKi), PARAMETER :: M2N8DynP = 503 + INTEGER(IntKi), PARAMETER :: M2N9DynP = 504 + INTEGER(IntKi), PARAMETER :: M3N1DynP = 505 + INTEGER(IntKi), PARAMETER :: M3N2DynP = 506 + INTEGER(IntKi), PARAMETER :: M3N3DynP = 507 + INTEGER(IntKi), PARAMETER :: M3N4DynP = 508 + INTEGER(IntKi), PARAMETER :: M3N5DynP = 509 + INTEGER(IntKi), PARAMETER :: M3N6DynP = 510 + INTEGER(IntKi), PARAMETER :: M3N7DynP = 511 + INTEGER(IntKi), PARAMETER :: M3N8DynP = 512 + INTEGER(IntKi), PARAMETER :: M3N9DynP = 513 + INTEGER(IntKi), PARAMETER :: M4N1DynP = 514 + INTEGER(IntKi), PARAMETER :: M4N2DynP = 515 + INTEGER(IntKi), PARAMETER :: M4N3DynP = 516 + INTEGER(IntKi), PARAMETER :: M4N4DynP = 517 + INTEGER(IntKi), PARAMETER :: M4N5DynP = 518 + INTEGER(IntKi), PARAMETER :: M4N6DynP = 519 + INTEGER(IntKi), PARAMETER :: M4N7DynP = 520 + INTEGER(IntKi), PARAMETER :: M4N8DynP = 521 + INTEGER(IntKi), PARAMETER :: M4N9DynP = 522 + INTEGER(IntKi), PARAMETER :: M5N1DynP = 523 + INTEGER(IntKi), PARAMETER :: M5N2DynP = 524 + INTEGER(IntKi), PARAMETER :: M5N3DynP = 525 + INTEGER(IntKi), PARAMETER :: M5N4DynP = 526 + INTEGER(IntKi), PARAMETER :: M5N5DynP = 527 + INTEGER(IntKi), PARAMETER :: M5N6DynP = 528 + INTEGER(IntKi), PARAMETER :: M5N7DynP = 529 + INTEGER(IntKi), PARAMETER :: M5N8DynP = 530 + INTEGER(IntKi), PARAMETER :: M5N9DynP = 531 + INTEGER(IntKi), PARAMETER :: M6N1DynP = 532 + INTEGER(IntKi), PARAMETER :: M6N2DynP = 533 + INTEGER(IntKi), PARAMETER :: M6N3DynP = 534 + INTEGER(IntKi), PARAMETER :: M6N4DynP = 535 + INTEGER(IntKi), PARAMETER :: M6N5DynP = 536 + INTEGER(IntKi), PARAMETER :: M6N6DynP = 537 + INTEGER(IntKi), PARAMETER :: M6N7DynP = 538 + INTEGER(IntKi), PARAMETER :: M6N8DynP = 539 + INTEGER(IntKi), PARAMETER :: M6N9DynP = 540 + INTEGER(IntKi), PARAMETER :: M7N1DynP = 541 + INTEGER(IntKi), PARAMETER :: M7N2DynP = 542 + INTEGER(IntKi), PARAMETER :: M7N3DynP = 543 + INTEGER(IntKi), PARAMETER :: M7N4DynP = 544 + INTEGER(IntKi), PARAMETER :: M7N5DynP = 545 + INTEGER(IntKi), PARAMETER :: M7N6DynP = 546 + INTEGER(IntKi), PARAMETER :: M7N7DynP = 547 + INTEGER(IntKi), PARAMETER :: M7N8DynP = 548 + INTEGER(IntKi), PARAMETER :: M7N9DynP = 549 + INTEGER(IntKi), PARAMETER :: M8N1DynP = 550 + INTEGER(IntKi), PARAMETER :: M8N2DynP = 551 + INTEGER(IntKi), PARAMETER :: M8N3DynP = 552 + INTEGER(IntKi), PARAMETER :: M8N4DynP = 553 + INTEGER(IntKi), PARAMETER :: M8N5DynP = 554 + INTEGER(IntKi), PARAMETER :: M8N6DynP = 555 + INTEGER(IntKi), PARAMETER :: M8N7DynP = 556 + INTEGER(IntKi), PARAMETER :: M8N8DynP = 557 + INTEGER(IntKi), PARAMETER :: M8N9DynP = 558 + INTEGER(IntKi), PARAMETER :: M9N1DynP = 559 + INTEGER(IntKi), PARAMETER :: M9N2DynP = 560 + INTEGER(IntKi), PARAMETER :: M9N3DynP = 561 + INTEGER(IntKi), PARAMETER :: M9N4DynP = 562 + INTEGER(IntKi), PARAMETER :: M9N5DynP = 563 + INTEGER(IntKi), PARAMETER :: M9N6DynP = 564 + INTEGER(IntKi), PARAMETER :: M9N7DynP = 565 + INTEGER(IntKi), PARAMETER :: M9N8DynP = 566 + INTEGER(IntKi), PARAMETER :: M9N9DynP = 567 + INTEGER(IntKi), PARAMETER :: M1N1STVxi = 568 + INTEGER(IntKi), PARAMETER :: M1N2STVxi = 569 + INTEGER(IntKi), PARAMETER :: M1N3STVxi = 570 + INTEGER(IntKi), PARAMETER :: M1N4STVxi = 571 + INTEGER(IntKi), PARAMETER :: M1N5STVxi = 572 + INTEGER(IntKi), PARAMETER :: M1N6STVxi = 573 + INTEGER(IntKi), PARAMETER :: M1N7STVxi = 574 + INTEGER(IntKi), PARAMETER :: M1N8STVxi = 575 + INTEGER(IntKi), PARAMETER :: M1N9STVxi = 576 + INTEGER(IntKi), PARAMETER :: M2N1STVxi = 577 + INTEGER(IntKi), PARAMETER :: M2N2STVxi = 578 + INTEGER(IntKi), PARAMETER :: M2N3STVxi = 579 + INTEGER(IntKi), PARAMETER :: M2N4STVxi = 580 + INTEGER(IntKi), PARAMETER :: M2N5STVxi = 581 + INTEGER(IntKi), PARAMETER :: M2N6STVxi = 582 + INTEGER(IntKi), PARAMETER :: M2N7STVxi = 583 + INTEGER(IntKi), PARAMETER :: M2N8STVxi = 584 + INTEGER(IntKi), PARAMETER :: M2N9STVxi = 585 + INTEGER(IntKi), PARAMETER :: M3N1STVxi = 586 + INTEGER(IntKi), PARAMETER :: M3N2STVxi = 587 + INTEGER(IntKi), PARAMETER :: M3N3STVxi = 588 + INTEGER(IntKi), PARAMETER :: M3N4STVxi = 589 + INTEGER(IntKi), PARAMETER :: M3N5STVxi = 590 + INTEGER(IntKi), PARAMETER :: M3N6STVxi = 591 + INTEGER(IntKi), PARAMETER :: M3N7STVxi = 592 + INTEGER(IntKi), PARAMETER :: M3N8STVxi = 593 + INTEGER(IntKi), PARAMETER :: M3N9STVxi = 594 + INTEGER(IntKi), PARAMETER :: M4N1STVxi = 595 + INTEGER(IntKi), PARAMETER :: M4N2STVxi = 596 + INTEGER(IntKi), PARAMETER :: M4N3STVxi = 597 + INTEGER(IntKi), PARAMETER :: M4N4STVxi = 598 + INTEGER(IntKi), PARAMETER :: M4N5STVxi = 599 + INTEGER(IntKi), PARAMETER :: M4N6STVxi = 600 + INTEGER(IntKi), PARAMETER :: M4N7STVxi = 601 + INTEGER(IntKi), PARAMETER :: M4N8STVxi = 602 + INTEGER(IntKi), PARAMETER :: M4N9STVxi = 603 + INTEGER(IntKi), PARAMETER :: M5N1STVxi = 604 + INTEGER(IntKi), PARAMETER :: M5N2STVxi = 605 + INTEGER(IntKi), PARAMETER :: M5N3STVxi = 606 + INTEGER(IntKi), PARAMETER :: M5N4STVxi = 607 + INTEGER(IntKi), PARAMETER :: M5N5STVxi = 608 + INTEGER(IntKi), PARAMETER :: M5N6STVxi = 609 + INTEGER(IntKi), PARAMETER :: M5N7STVxi = 610 + INTEGER(IntKi), PARAMETER :: M5N8STVxi = 611 + INTEGER(IntKi), PARAMETER :: M5N9STVxi = 612 + INTEGER(IntKi), PARAMETER :: M6N1STVxi = 613 + INTEGER(IntKi), PARAMETER :: M6N2STVxi = 614 + INTEGER(IntKi), PARAMETER :: M6N3STVxi = 615 + INTEGER(IntKi), PARAMETER :: M6N4STVxi = 616 + INTEGER(IntKi), PARAMETER :: M6N5STVxi = 617 + INTEGER(IntKi), PARAMETER :: M6N6STVxi = 618 + INTEGER(IntKi), PARAMETER :: M6N7STVxi = 619 + INTEGER(IntKi), PARAMETER :: M6N8STVxi = 620 + INTEGER(IntKi), PARAMETER :: M6N9STVxi = 621 + INTEGER(IntKi), PARAMETER :: M7N1STVxi = 622 + INTEGER(IntKi), PARAMETER :: M7N2STVxi = 623 + INTEGER(IntKi), PARAMETER :: M7N3STVxi = 624 + INTEGER(IntKi), PARAMETER :: M7N4STVxi = 625 + INTEGER(IntKi), PARAMETER :: M7N5STVxi = 626 + INTEGER(IntKi), PARAMETER :: M7N6STVxi = 627 + INTEGER(IntKi), PARAMETER :: M7N7STVxi = 628 + INTEGER(IntKi), PARAMETER :: M7N8STVxi = 629 + INTEGER(IntKi), PARAMETER :: M7N9STVxi = 630 + INTEGER(IntKi), PARAMETER :: M8N1STVxi = 631 + INTEGER(IntKi), PARAMETER :: M8N2STVxi = 632 + INTEGER(IntKi), PARAMETER :: M8N3STVxi = 633 + INTEGER(IntKi), PARAMETER :: M8N4STVxi = 634 + INTEGER(IntKi), PARAMETER :: M8N5STVxi = 635 + INTEGER(IntKi), PARAMETER :: M8N6STVxi = 636 + INTEGER(IntKi), PARAMETER :: M8N7STVxi = 637 + INTEGER(IntKi), PARAMETER :: M8N8STVxi = 638 + INTEGER(IntKi), PARAMETER :: M8N9STVxi = 639 + INTEGER(IntKi), PARAMETER :: M9N1STVxi = 640 + INTEGER(IntKi), PARAMETER :: M9N2STVxi = 641 + INTEGER(IntKi), PARAMETER :: M9N3STVxi = 642 + INTEGER(IntKi), PARAMETER :: M9N4STVxi = 643 + INTEGER(IntKi), PARAMETER :: M9N5STVxi = 644 + INTEGER(IntKi), PARAMETER :: M9N6STVxi = 645 + INTEGER(IntKi), PARAMETER :: M9N7STVxi = 646 + INTEGER(IntKi), PARAMETER :: M9N8STVxi = 647 + INTEGER(IntKi), PARAMETER :: M9N9STVxi = 648 + INTEGER(IntKi), PARAMETER :: M1N1STVyi = 649 + INTEGER(IntKi), PARAMETER :: M1N2STVyi = 650 + INTEGER(IntKi), PARAMETER :: M1N3STVyi = 651 + INTEGER(IntKi), PARAMETER :: M1N4STVyi = 652 + INTEGER(IntKi), PARAMETER :: M1N5STVyi = 653 + INTEGER(IntKi), PARAMETER :: M1N6STVyi = 654 + INTEGER(IntKi), PARAMETER :: M1N7STVyi = 655 + INTEGER(IntKi), PARAMETER :: M1N8STVyi = 656 + INTEGER(IntKi), PARAMETER :: M1N9STVyi = 657 + INTEGER(IntKi), PARAMETER :: M2N1STVyi = 658 + INTEGER(IntKi), PARAMETER :: M2N2STVyi = 659 + INTEGER(IntKi), PARAMETER :: M2N3STVyi = 660 + INTEGER(IntKi), PARAMETER :: M2N4STVyi = 661 + INTEGER(IntKi), PARAMETER :: M2N5STVyi = 662 + INTEGER(IntKi), PARAMETER :: M2N6STVyi = 663 + INTEGER(IntKi), PARAMETER :: M2N7STVyi = 664 + INTEGER(IntKi), PARAMETER :: M2N8STVyi = 665 + INTEGER(IntKi), PARAMETER :: M2N9STVyi = 666 + INTEGER(IntKi), PARAMETER :: M3N1STVyi = 667 + INTEGER(IntKi), PARAMETER :: M3N2STVyi = 668 + INTEGER(IntKi), PARAMETER :: M3N3STVyi = 669 + INTEGER(IntKi), PARAMETER :: M3N4STVyi = 670 + INTEGER(IntKi), PARAMETER :: M3N5STVyi = 671 + INTEGER(IntKi), PARAMETER :: M3N6STVyi = 672 + INTEGER(IntKi), PARAMETER :: M3N7STVyi = 673 + INTEGER(IntKi), PARAMETER :: M3N8STVyi = 674 + INTEGER(IntKi), PARAMETER :: M3N9STVyi = 675 + INTEGER(IntKi), PARAMETER :: M4N1STVyi = 676 + INTEGER(IntKi), PARAMETER :: M4N2STVyi = 677 + INTEGER(IntKi), PARAMETER :: M4N3STVyi = 678 + INTEGER(IntKi), PARAMETER :: M4N4STVyi = 679 + INTEGER(IntKi), PARAMETER :: M4N5STVyi = 680 + INTEGER(IntKi), PARAMETER :: M4N6STVyi = 681 + INTEGER(IntKi), PARAMETER :: M4N7STVyi = 682 + INTEGER(IntKi), PARAMETER :: M4N8STVyi = 683 + INTEGER(IntKi), PARAMETER :: M4N9STVyi = 684 + INTEGER(IntKi), PARAMETER :: M5N1STVyi = 685 + INTEGER(IntKi), PARAMETER :: M5N2STVyi = 686 + INTEGER(IntKi), PARAMETER :: M5N3STVyi = 687 + INTEGER(IntKi), PARAMETER :: M5N4STVyi = 688 + INTEGER(IntKi), PARAMETER :: M5N5STVyi = 689 + INTEGER(IntKi), PARAMETER :: M5N6STVyi = 690 + INTEGER(IntKi), PARAMETER :: M5N7STVyi = 691 + INTEGER(IntKi), PARAMETER :: M5N8STVyi = 692 + INTEGER(IntKi), PARAMETER :: M5N9STVyi = 693 + INTEGER(IntKi), PARAMETER :: M6N1STVyi = 694 + INTEGER(IntKi), PARAMETER :: M6N2STVyi = 695 + INTEGER(IntKi), PARAMETER :: M6N3STVyi = 696 + INTEGER(IntKi), PARAMETER :: M6N4STVyi = 697 + INTEGER(IntKi), PARAMETER :: M6N5STVyi = 698 + INTEGER(IntKi), PARAMETER :: M6N6STVyi = 699 + INTEGER(IntKi), PARAMETER :: M6N7STVyi = 700 + INTEGER(IntKi), PARAMETER :: M6N8STVyi = 701 + INTEGER(IntKi), PARAMETER :: M6N9STVyi = 702 + INTEGER(IntKi), PARAMETER :: M7N1STVyi = 703 + INTEGER(IntKi), PARAMETER :: M7N2STVyi = 704 + INTEGER(IntKi), PARAMETER :: M7N3STVyi = 705 + INTEGER(IntKi), PARAMETER :: M7N4STVyi = 706 + INTEGER(IntKi), PARAMETER :: M7N5STVyi = 707 + INTEGER(IntKi), PARAMETER :: M7N6STVyi = 708 + INTEGER(IntKi), PARAMETER :: M7N7STVyi = 709 + INTEGER(IntKi), PARAMETER :: M7N8STVyi = 710 + INTEGER(IntKi), PARAMETER :: M7N9STVyi = 711 + INTEGER(IntKi), PARAMETER :: M8N1STVyi = 712 + INTEGER(IntKi), PARAMETER :: M8N2STVyi = 713 + INTEGER(IntKi), PARAMETER :: M8N3STVyi = 714 + INTEGER(IntKi), PARAMETER :: M8N4STVyi = 715 + INTEGER(IntKi), PARAMETER :: M8N5STVyi = 716 + INTEGER(IntKi), PARAMETER :: M8N6STVyi = 717 + INTEGER(IntKi), PARAMETER :: M8N7STVyi = 718 + INTEGER(IntKi), PARAMETER :: M8N8STVyi = 719 + INTEGER(IntKi), PARAMETER :: M8N9STVyi = 720 + INTEGER(IntKi), PARAMETER :: M9N1STVyi = 721 + INTEGER(IntKi), PARAMETER :: M9N2STVyi = 722 + INTEGER(IntKi), PARAMETER :: M9N3STVyi = 723 + INTEGER(IntKi), PARAMETER :: M9N4STVyi = 724 + INTEGER(IntKi), PARAMETER :: M9N5STVyi = 725 + INTEGER(IntKi), PARAMETER :: M9N6STVyi = 726 + INTEGER(IntKi), PARAMETER :: M9N7STVyi = 727 + INTEGER(IntKi), PARAMETER :: M9N8STVyi = 728 + INTEGER(IntKi), PARAMETER :: M9N9STVyi = 729 + INTEGER(IntKi), PARAMETER :: M1N1STVzi = 730 + INTEGER(IntKi), PARAMETER :: M1N2STVzi = 731 + INTEGER(IntKi), PARAMETER :: M1N3STVzi = 732 + INTEGER(IntKi), PARAMETER :: M1N4STVzi = 733 + INTEGER(IntKi), PARAMETER :: M1N5STVzi = 734 + INTEGER(IntKi), PARAMETER :: M1N6STVzi = 735 + INTEGER(IntKi), PARAMETER :: M1N7STVzi = 736 + INTEGER(IntKi), PARAMETER :: M1N8STVzi = 737 + INTEGER(IntKi), PARAMETER :: M1N9STVzi = 738 + INTEGER(IntKi), PARAMETER :: M2N1STVzi = 739 + INTEGER(IntKi), PARAMETER :: M2N2STVzi = 740 + INTEGER(IntKi), PARAMETER :: M2N3STVzi = 741 + INTEGER(IntKi), PARAMETER :: M2N4STVzi = 742 + INTEGER(IntKi), PARAMETER :: M2N5STVzi = 743 + INTEGER(IntKi), PARAMETER :: M2N6STVzi = 744 + INTEGER(IntKi), PARAMETER :: M2N7STVzi = 745 + INTEGER(IntKi), PARAMETER :: M2N8STVzi = 746 + INTEGER(IntKi), PARAMETER :: M2N9STVzi = 747 + INTEGER(IntKi), PARAMETER :: M3N1STVzi = 748 + INTEGER(IntKi), PARAMETER :: M3N2STVzi = 749 + INTEGER(IntKi), PARAMETER :: M3N3STVzi = 750 + INTEGER(IntKi), PARAMETER :: M3N4STVzi = 751 + INTEGER(IntKi), PARAMETER :: M3N5STVzi = 752 + INTEGER(IntKi), PARAMETER :: M3N6STVzi = 753 + INTEGER(IntKi), PARAMETER :: M3N7STVzi = 754 + INTEGER(IntKi), PARAMETER :: M3N8STVzi = 755 + INTEGER(IntKi), PARAMETER :: M3N9STVzi = 756 + INTEGER(IntKi), PARAMETER :: M4N1STVzi = 757 + INTEGER(IntKi), PARAMETER :: M4N2STVzi = 758 + INTEGER(IntKi), PARAMETER :: M4N3STVzi = 759 + INTEGER(IntKi), PARAMETER :: M4N4STVzi = 760 + INTEGER(IntKi), PARAMETER :: M4N5STVzi = 761 + INTEGER(IntKi), PARAMETER :: M4N6STVzi = 762 + INTEGER(IntKi), PARAMETER :: M4N7STVzi = 763 + INTEGER(IntKi), PARAMETER :: M4N8STVzi = 764 + INTEGER(IntKi), PARAMETER :: M4N9STVzi = 765 + INTEGER(IntKi), PARAMETER :: M5N1STVzi = 766 + INTEGER(IntKi), PARAMETER :: M5N2STVzi = 767 + INTEGER(IntKi), PARAMETER :: M5N3STVzi = 768 + INTEGER(IntKi), PARAMETER :: M5N4STVzi = 769 + INTEGER(IntKi), PARAMETER :: M5N5STVzi = 770 + INTEGER(IntKi), PARAMETER :: M5N6STVzi = 771 + INTEGER(IntKi), PARAMETER :: M5N7STVzi = 772 + INTEGER(IntKi), PARAMETER :: M5N8STVzi = 773 + INTEGER(IntKi), PARAMETER :: M5N9STVzi = 774 + INTEGER(IntKi), PARAMETER :: M6N1STVzi = 775 + INTEGER(IntKi), PARAMETER :: M6N2STVzi = 776 + INTEGER(IntKi), PARAMETER :: M6N3STVzi = 777 + INTEGER(IntKi), PARAMETER :: M6N4STVzi = 778 + INTEGER(IntKi), PARAMETER :: M6N5STVzi = 779 + INTEGER(IntKi), PARAMETER :: M6N6STVzi = 780 + INTEGER(IntKi), PARAMETER :: M6N7STVzi = 781 + INTEGER(IntKi), PARAMETER :: M6N8STVzi = 782 + INTEGER(IntKi), PARAMETER :: M6N9STVzi = 783 + INTEGER(IntKi), PARAMETER :: M7N1STVzi = 784 + INTEGER(IntKi), PARAMETER :: M7N2STVzi = 785 + INTEGER(IntKi), PARAMETER :: M7N3STVzi = 786 + INTEGER(IntKi), PARAMETER :: M7N4STVzi = 787 + INTEGER(IntKi), PARAMETER :: M7N5STVzi = 788 + INTEGER(IntKi), PARAMETER :: M7N6STVzi = 789 + INTEGER(IntKi), PARAMETER :: M7N7STVzi = 790 + INTEGER(IntKi), PARAMETER :: M7N8STVzi = 791 + INTEGER(IntKi), PARAMETER :: M7N9STVzi = 792 + INTEGER(IntKi), PARAMETER :: M8N1STVzi = 793 + INTEGER(IntKi), PARAMETER :: M8N2STVzi = 794 + INTEGER(IntKi), PARAMETER :: M8N3STVzi = 795 + INTEGER(IntKi), PARAMETER :: M8N4STVzi = 796 + INTEGER(IntKi), PARAMETER :: M8N5STVzi = 797 + INTEGER(IntKi), PARAMETER :: M8N6STVzi = 798 + INTEGER(IntKi), PARAMETER :: M8N7STVzi = 799 + INTEGER(IntKi), PARAMETER :: M8N8STVzi = 800 + INTEGER(IntKi), PARAMETER :: M8N9STVzi = 801 + INTEGER(IntKi), PARAMETER :: M9N1STVzi = 802 + INTEGER(IntKi), PARAMETER :: M9N2STVzi = 803 + INTEGER(IntKi), PARAMETER :: M9N3STVzi = 804 + INTEGER(IntKi), PARAMETER :: M9N4STVzi = 805 + INTEGER(IntKi), PARAMETER :: M9N5STVzi = 806 + INTEGER(IntKi), PARAMETER :: M9N6STVzi = 807 + INTEGER(IntKi), PARAMETER :: M9N7STVzi = 808 + INTEGER(IntKi), PARAMETER :: M9N8STVzi = 809 + INTEGER(IntKi), PARAMETER :: M9N9STVzi = 810 + INTEGER(IntKi), PARAMETER :: M1N1STAxi = 811 + INTEGER(IntKi), PARAMETER :: M1N2STAxi = 812 + INTEGER(IntKi), PARAMETER :: M1N3STAxi = 813 + INTEGER(IntKi), PARAMETER :: M1N4STAxi = 814 + INTEGER(IntKi), PARAMETER :: M1N5STAxi = 815 + INTEGER(IntKi), PARAMETER :: M1N6STAxi = 816 + INTEGER(IntKi), PARAMETER :: M1N7STAxi = 817 + INTEGER(IntKi), PARAMETER :: M1N8STAxi = 818 + INTEGER(IntKi), PARAMETER :: M1N9STAxi = 819 + INTEGER(IntKi), PARAMETER :: M2N1STAxi = 820 + INTEGER(IntKi), PARAMETER :: M2N2STAxi = 821 + INTEGER(IntKi), PARAMETER :: M2N3STAxi = 822 + INTEGER(IntKi), PARAMETER :: M2N4STAxi = 823 + INTEGER(IntKi), PARAMETER :: M2N5STAxi = 824 + INTEGER(IntKi), PARAMETER :: M2N6STAxi = 825 + INTEGER(IntKi), PARAMETER :: M2N7STAxi = 826 + INTEGER(IntKi), PARAMETER :: M2N8STAxi = 827 + INTEGER(IntKi), PARAMETER :: M2N9STAxi = 828 + INTEGER(IntKi), PARAMETER :: M3N1STAxi = 829 + INTEGER(IntKi), PARAMETER :: M3N2STAxi = 830 + INTEGER(IntKi), PARAMETER :: M3N3STAxi = 831 + INTEGER(IntKi), PARAMETER :: M3N4STAxi = 832 + INTEGER(IntKi), PARAMETER :: M3N5STAxi = 833 + INTEGER(IntKi), PARAMETER :: M3N6STAxi = 834 + INTEGER(IntKi), PARAMETER :: M3N7STAxi = 835 + INTEGER(IntKi), PARAMETER :: M3N8STAxi = 836 + INTEGER(IntKi), PARAMETER :: M3N9STAxi = 837 + INTEGER(IntKi), PARAMETER :: M4N1STAxi = 838 + INTEGER(IntKi), PARAMETER :: M4N2STAxi = 839 + INTEGER(IntKi), PARAMETER :: M4N3STAxi = 840 + INTEGER(IntKi), PARAMETER :: M4N4STAxi = 841 + INTEGER(IntKi), PARAMETER :: M4N5STAxi = 842 + INTEGER(IntKi), PARAMETER :: M4N6STAxi = 843 + INTEGER(IntKi), PARAMETER :: M4N7STAxi = 844 + INTEGER(IntKi), PARAMETER :: M4N8STAxi = 845 + INTEGER(IntKi), PARAMETER :: M4N9STAxi = 846 + INTEGER(IntKi), PARAMETER :: M5N1STAxi = 847 + INTEGER(IntKi), PARAMETER :: M5N2STAxi = 848 + INTEGER(IntKi), PARAMETER :: M5N3STAxi = 849 + INTEGER(IntKi), PARAMETER :: M5N4STAxi = 850 + INTEGER(IntKi), PARAMETER :: M5N5STAxi = 851 + INTEGER(IntKi), PARAMETER :: M5N6STAxi = 852 + INTEGER(IntKi), PARAMETER :: M5N7STAxi = 853 + INTEGER(IntKi), PARAMETER :: M5N8STAxi = 854 + INTEGER(IntKi), PARAMETER :: M5N9STAxi = 855 + INTEGER(IntKi), PARAMETER :: M6N1STAxi = 856 + INTEGER(IntKi), PARAMETER :: M6N2STAxi = 857 + INTEGER(IntKi), PARAMETER :: M6N3STAxi = 858 + INTEGER(IntKi), PARAMETER :: M6N4STAxi = 859 + INTEGER(IntKi), PARAMETER :: M6N5STAxi = 860 + INTEGER(IntKi), PARAMETER :: M6N6STAxi = 861 + INTEGER(IntKi), PARAMETER :: M6N7STAxi = 862 + INTEGER(IntKi), PARAMETER :: M6N8STAxi = 863 + INTEGER(IntKi), PARAMETER :: M6N9STAxi = 864 + INTEGER(IntKi), PARAMETER :: M7N1STAxi = 865 + INTEGER(IntKi), PARAMETER :: M7N2STAxi = 866 + INTEGER(IntKi), PARAMETER :: M7N3STAxi = 867 + INTEGER(IntKi), PARAMETER :: M7N4STAxi = 868 + INTEGER(IntKi), PARAMETER :: M7N5STAxi = 869 + INTEGER(IntKi), PARAMETER :: M7N6STAxi = 870 + INTEGER(IntKi), PARAMETER :: M7N7STAxi = 871 + INTEGER(IntKi), PARAMETER :: M7N8STAxi = 872 + INTEGER(IntKi), PARAMETER :: M7N9STAxi = 873 + INTEGER(IntKi), PARAMETER :: M8N1STAxi = 874 + INTEGER(IntKi), PARAMETER :: M8N2STAxi = 875 + INTEGER(IntKi), PARAMETER :: M8N3STAxi = 876 + INTEGER(IntKi), PARAMETER :: M8N4STAxi = 877 + INTEGER(IntKi), PARAMETER :: M8N5STAxi = 878 + INTEGER(IntKi), PARAMETER :: M8N6STAxi = 879 + INTEGER(IntKi), PARAMETER :: M8N7STAxi = 880 + INTEGER(IntKi), PARAMETER :: M8N8STAxi = 881 + INTEGER(IntKi), PARAMETER :: M8N9STAxi = 882 + INTEGER(IntKi), PARAMETER :: M9N1STAxi = 883 + INTEGER(IntKi), PARAMETER :: M9N2STAxi = 884 + INTEGER(IntKi), PARAMETER :: M9N3STAxi = 885 + INTEGER(IntKi), PARAMETER :: M9N4STAxi = 886 + INTEGER(IntKi), PARAMETER :: M9N5STAxi = 887 + INTEGER(IntKi), PARAMETER :: M9N6STAxi = 888 + INTEGER(IntKi), PARAMETER :: M9N7STAxi = 889 + INTEGER(IntKi), PARAMETER :: M9N8STAxi = 890 + INTEGER(IntKi), PARAMETER :: M9N9STAxi = 891 + INTEGER(IntKi), PARAMETER :: M1N1STAyi = 892 + INTEGER(IntKi), PARAMETER :: M1N2STAyi = 893 + INTEGER(IntKi), PARAMETER :: M1N3STAyi = 894 + INTEGER(IntKi), PARAMETER :: M1N4STAyi = 895 + INTEGER(IntKi), PARAMETER :: M1N5STAyi = 896 + INTEGER(IntKi), PARAMETER :: M1N6STAyi = 897 + INTEGER(IntKi), PARAMETER :: M1N7STAyi = 898 + INTEGER(IntKi), PARAMETER :: M1N8STAyi = 899 + INTEGER(IntKi), PARAMETER :: M1N9STAyi = 900 + INTEGER(IntKi), PARAMETER :: M2N1STAyi = 901 + INTEGER(IntKi), PARAMETER :: M2N2STAyi = 902 + INTEGER(IntKi), PARAMETER :: M2N3STAyi = 903 + INTEGER(IntKi), PARAMETER :: M2N4STAyi = 904 + INTEGER(IntKi), PARAMETER :: M2N5STAyi = 905 + INTEGER(IntKi), PARAMETER :: M2N6STAyi = 906 + INTEGER(IntKi), PARAMETER :: M2N7STAyi = 907 + INTEGER(IntKi), PARAMETER :: M2N8STAyi = 908 + INTEGER(IntKi), PARAMETER :: M2N9STAyi = 909 + INTEGER(IntKi), PARAMETER :: M3N1STAyi = 910 + INTEGER(IntKi), PARAMETER :: M3N2STAyi = 911 + INTEGER(IntKi), PARAMETER :: M3N3STAyi = 912 + INTEGER(IntKi), PARAMETER :: M3N4STAyi = 913 + INTEGER(IntKi), PARAMETER :: M3N5STAyi = 914 + INTEGER(IntKi), PARAMETER :: M3N6STAyi = 915 + INTEGER(IntKi), PARAMETER :: M3N7STAyi = 916 + INTEGER(IntKi), PARAMETER :: M3N8STAyi = 917 + INTEGER(IntKi), PARAMETER :: M3N9STAyi = 918 + INTEGER(IntKi), PARAMETER :: M4N1STAyi = 919 + INTEGER(IntKi), PARAMETER :: M4N2STAyi = 920 + INTEGER(IntKi), PARAMETER :: M4N3STAyi = 921 + INTEGER(IntKi), PARAMETER :: M4N4STAyi = 922 + INTEGER(IntKi), PARAMETER :: M4N5STAyi = 923 + INTEGER(IntKi), PARAMETER :: M4N6STAyi = 924 + INTEGER(IntKi), PARAMETER :: M4N7STAyi = 925 + INTEGER(IntKi), PARAMETER :: M4N8STAyi = 926 + INTEGER(IntKi), PARAMETER :: M4N9STAyi = 927 + INTEGER(IntKi), PARAMETER :: M5N1STAyi = 928 + INTEGER(IntKi), PARAMETER :: M5N2STAyi = 929 + INTEGER(IntKi), PARAMETER :: M5N3STAyi = 930 + INTEGER(IntKi), PARAMETER :: M5N4STAyi = 931 + INTEGER(IntKi), PARAMETER :: M5N5STAyi = 932 + INTEGER(IntKi), PARAMETER :: M5N6STAyi = 933 + INTEGER(IntKi), PARAMETER :: M5N7STAyi = 934 + INTEGER(IntKi), PARAMETER :: M5N8STAyi = 935 + INTEGER(IntKi), PARAMETER :: M5N9STAyi = 936 + INTEGER(IntKi), PARAMETER :: M6N1STAyi = 937 + INTEGER(IntKi), PARAMETER :: M6N2STAyi = 938 + INTEGER(IntKi), PARAMETER :: M6N3STAyi = 939 + INTEGER(IntKi), PARAMETER :: M6N4STAyi = 940 + INTEGER(IntKi), PARAMETER :: M6N5STAyi = 941 + INTEGER(IntKi), PARAMETER :: M6N6STAyi = 942 + INTEGER(IntKi), PARAMETER :: M6N7STAyi = 943 + INTEGER(IntKi), PARAMETER :: M6N8STAyi = 944 + INTEGER(IntKi), PARAMETER :: M6N9STAyi = 945 + INTEGER(IntKi), PARAMETER :: M7N1STAyi = 946 + INTEGER(IntKi), PARAMETER :: M7N2STAyi = 947 + INTEGER(IntKi), PARAMETER :: M7N3STAyi = 948 + INTEGER(IntKi), PARAMETER :: M7N4STAyi = 949 + INTEGER(IntKi), PARAMETER :: M7N5STAyi = 950 + INTEGER(IntKi), PARAMETER :: M7N6STAyi = 951 + INTEGER(IntKi), PARAMETER :: M7N7STAyi = 952 + INTEGER(IntKi), PARAMETER :: M7N8STAyi = 953 + INTEGER(IntKi), PARAMETER :: M7N9STAyi = 954 + INTEGER(IntKi), PARAMETER :: M8N1STAyi = 955 + INTEGER(IntKi), PARAMETER :: M8N2STAyi = 956 + INTEGER(IntKi), PARAMETER :: M8N3STAyi = 957 + INTEGER(IntKi), PARAMETER :: M8N4STAyi = 958 + INTEGER(IntKi), PARAMETER :: M8N5STAyi = 959 + INTEGER(IntKi), PARAMETER :: M8N6STAyi = 960 + INTEGER(IntKi), PARAMETER :: M8N7STAyi = 961 + INTEGER(IntKi), PARAMETER :: M8N8STAyi = 962 + INTEGER(IntKi), PARAMETER :: M8N9STAyi = 963 + INTEGER(IntKi), PARAMETER :: M9N1STAyi = 964 + INTEGER(IntKi), PARAMETER :: M9N2STAyi = 965 + INTEGER(IntKi), PARAMETER :: M9N3STAyi = 966 + INTEGER(IntKi), PARAMETER :: M9N4STAyi = 967 + INTEGER(IntKi), PARAMETER :: M9N5STAyi = 968 + INTEGER(IntKi), PARAMETER :: M9N6STAyi = 969 + INTEGER(IntKi), PARAMETER :: M9N7STAyi = 970 + INTEGER(IntKi), PARAMETER :: M9N8STAyi = 971 + INTEGER(IntKi), PARAMETER :: M9N9STAyi = 972 + INTEGER(IntKi), PARAMETER :: M1N1STAzi = 973 + INTEGER(IntKi), PARAMETER :: M1N2STAzi = 974 + INTEGER(IntKi), PARAMETER :: M1N3STAzi = 975 + INTEGER(IntKi), PARAMETER :: M1N4STAzi = 976 + INTEGER(IntKi), PARAMETER :: M1N5STAzi = 977 + INTEGER(IntKi), PARAMETER :: M1N6STAzi = 978 + INTEGER(IntKi), PARAMETER :: M1N7STAzi = 979 + INTEGER(IntKi), PARAMETER :: M1N8STAzi = 980 + INTEGER(IntKi), PARAMETER :: M1N9STAzi = 981 + INTEGER(IntKi), PARAMETER :: M2N1STAzi = 982 + INTEGER(IntKi), PARAMETER :: M2N2STAzi = 983 + INTEGER(IntKi), PARAMETER :: M2N3STAzi = 984 + INTEGER(IntKi), PARAMETER :: M2N4STAzi = 985 + INTEGER(IntKi), PARAMETER :: M2N5STAzi = 986 + INTEGER(IntKi), PARAMETER :: M2N6STAzi = 987 + INTEGER(IntKi), PARAMETER :: M2N7STAzi = 988 + INTEGER(IntKi), PARAMETER :: M2N8STAzi = 989 + INTEGER(IntKi), PARAMETER :: M2N9STAzi = 990 + INTEGER(IntKi), PARAMETER :: M3N1STAzi = 991 + INTEGER(IntKi), PARAMETER :: M3N2STAzi = 992 + INTEGER(IntKi), PARAMETER :: M3N3STAzi = 993 + INTEGER(IntKi), PARAMETER :: M3N4STAzi = 994 + INTEGER(IntKi), PARAMETER :: M3N5STAzi = 995 + INTEGER(IntKi), PARAMETER :: M3N6STAzi = 996 + INTEGER(IntKi), PARAMETER :: M3N7STAzi = 997 + INTEGER(IntKi), PARAMETER :: M3N8STAzi = 998 + INTEGER(IntKi), PARAMETER :: M3N9STAzi = 999 + INTEGER(IntKi), PARAMETER :: M4N1STAzi = 1000 + INTEGER(IntKi), PARAMETER :: M4N2STAzi = 1001 + INTEGER(IntKi), PARAMETER :: M4N3STAzi = 1002 + INTEGER(IntKi), PARAMETER :: M4N4STAzi = 1003 + INTEGER(IntKi), PARAMETER :: M4N5STAzi = 1004 + INTEGER(IntKi), PARAMETER :: M4N6STAzi = 1005 + INTEGER(IntKi), PARAMETER :: M4N7STAzi = 1006 + INTEGER(IntKi), PARAMETER :: M4N8STAzi = 1007 + INTEGER(IntKi), PARAMETER :: M4N9STAzi = 1008 + INTEGER(IntKi), PARAMETER :: M5N1STAzi = 1009 + INTEGER(IntKi), PARAMETER :: M5N2STAzi = 1010 + INTEGER(IntKi), PARAMETER :: M5N3STAzi = 1011 + INTEGER(IntKi), PARAMETER :: M5N4STAzi = 1012 + INTEGER(IntKi), PARAMETER :: M5N5STAzi = 1013 + INTEGER(IntKi), PARAMETER :: M5N6STAzi = 1014 + INTEGER(IntKi), PARAMETER :: M5N7STAzi = 1015 + INTEGER(IntKi), PARAMETER :: M5N8STAzi = 1016 + INTEGER(IntKi), PARAMETER :: M5N9STAzi = 1017 + INTEGER(IntKi), PARAMETER :: M6N1STAzi = 1018 + INTEGER(IntKi), PARAMETER :: M6N2STAzi = 1019 + INTEGER(IntKi), PARAMETER :: M6N3STAzi = 1020 + INTEGER(IntKi), PARAMETER :: M6N4STAzi = 1021 + INTEGER(IntKi), PARAMETER :: M6N5STAzi = 1022 + INTEGER(IntKi), PARAMETER :: M6N6STAzi = 1023 + INTEGER(IntKi), PARAMETER :: M6N7STAzi = 1024 + INTEGER(IntKi), PARAMETER :: M6N8STAzi = 1025 + INTEGER(IntKi), PARAMETER :: M6N9STAzi = 1026 + INTEGER(IntKi), PARAMETER :: M7N1STAzi = 1027 + INTEGER(IntKi), PARAMETER :: M7N2STAzi = 1028 + INTEGER(IntKi), PARAMETER :: M7N3STAzi = 1029 + INTEGER(IntKi), PARAMETER :: M7N4STAzi = 1030 + INTEGER(IntKi), PARAMETER :: M7N5STAzi = 1031 + INTEGER(IntKi), PARAMETER :: M7N6STAzi = 1032 + INTEGER(IntKi), PARAMETER :: M7N7STAzi = 1033 + INTEGER(IntKi), PARAMETER :: M7N8STAzi = 1034 + INTEGER(IntKi), PARAMETER :: M7N9STAzi = 1035 + INTEGER(IntKi), PARAMETER :: M8N1STAzi = 1036 + INTEGER(IntKi), PARAMETER :: M8N2STAzi = 1037 + INTEGER(IntKi), PARAMETER :: M8N3STAzi = 1038 + INTEGER(IntKi), PARAMETER :: M8N4STAzi = 1039 + INTEGER(IntKi), PARAMETER :: M8N5STAzi = 1040 + INTEGER(IntKi), PARAMETER :: M8N6STAzi = 1041 + INTEGER(IntKi), PARAMETER :: M8N7STAzi = 1042 + INTEGER(IntKi), PARAMETER :: M8N8STAzi = 1043 + INTEGER(IntKi), PARAMETER :: M8N9STAzi = 1044 + INTEGER(IntKi), PARAMETER :: M9N1STAzi = 1045 + INTEGER(IntKi), PARAMETER :: M9N2STAzi = 1046 + INTEGER(IntKi), PARAMETER :: M9N3STAzi = 1047 + INTEGER(IntKi), PARAMETER :: M9N4STAzi = 1048 + INTEGER(IntKi), PARAMETER :: M9N5STAzi = 1049 + INTEGER(IntKi), PARAMETER :: M9N6STAzi = 1050 + INTEGER(IntKi), PARAMETER :: M9N7STAzi = 1051 + INTEGER(IntKi), PARAMETER :: M9N8STAzi = 1052 + INTEGER(IntKi), PARAMETER :: M9N9STAzi = 1053 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: M1N1FDxi = 1054 + INTEGER(IntKi), PARAMETER :: M1N2FDxi = 1055 + INTEGER(IntKi), PARAMETER :: M1N3FDxi = 1056 + INTEGER(IntKi), PARAMETER :: M1N4FDxi = 1057 + INTEGER(IntKi), PARAMETER :: M1N5FDxi = 1058 + INTEGER(IntKi), PARAMETER :: M1N6FDxi = 1059 + INTEGER(IntKi), PARAMETER :: M1N7FDxi = 1060 + INTEGER(IntKi), PARAMETER :: M1N8FDxi = 1061 + INTEGER(IntKi), PARAMETER :: M1N9FDxi = 1062 + INTEGER(IntKi), PARAMETER :: M2N1FDxi = 1063 + INTEGER(IntKi), PARAMETER :: M2N2FDxi = 1064 + INTEGER(IntKi), PARAMETER :: M2N3FDxi = 1065 + INTEGER(IntKi), PARAMETER :: M2N4FDxi = 1066 + INTEGER(IntKi), PARAMETER :: M2N5FDxi = 1067 + INTEGER(IntKi), PARAMETER :: M2N6FDxi = 1068 + INTEGER(IntKi), PARAMETER :: M2N7FDxi = 1069 + INTEGER(IntKi), PARAMETER :: M2N8FDxi = 1070 + INTEGER(IntKi), PARAMETER :: M2N9FDxi = 1071 + INTEGER(IntKi), PARAMETER :: M3N1FDxi = 1072 + INTEGER(IntKi), PARAMETER :: M3N2FDxi = 1073 + INTEGER(IntKi), PARAMETER :: M3N3FDxi = 1074 + INTEGER(IntKi), PARAMETER :: M3N4FDxi = 1075 + INTEGER(IntKi), PARAMETER :: M3N5FDxi = 1076 + INTEGER(IntKi), PARAMETER :: M3N6FDxi = 1077 + INTEGER(IntKi), PARAMETER :: M3N7FDxi = 1078 + INTEGER(IntKi), PARAMETER :: M3N8FDxi = 1079 + INTEGER(IntKi), PARAMETER :: M3N9FDxi = 1080 + INTEGER(IntKi), PARAMETER :: M4N1FDxi = 1081 + INTEGER(IntKi), PARAMETER :: M4N2FDxi = 1082 + INTEGER(IntKi), PARAMETER :: M4N3FDxi = 1083 + INTEGER(IntKi), PARAMETER :: M4N4FDxi = 1084 + INTEGER(IntKi), PARAMETER :: M4N5FDxi = 1085 + INTEGER(IntKi), PARAMETER :: M4N6FDxi = 1086 + INTEGER(IntKi), PARAMETER :: M4N7FDxi = 1087 + INTEGER(IntKi), PARAMETER :: M4N8FDxi = 1088 + INTEGER(IntKi), PARAMETER :: M4N9FDxi = 1089 + INTEGER(IntKi), PARAMETER :: M5N1FDxi = 1090 + INTEGER(IntKi), PARAMETER :: M5N2FDxi = 1091 + INTEGER(IntKi), PARAMETER :: M5N3FDxi = 1092 + INTEGER(IntKi), PARAMETER :: M5N4FDxi = 1093 + INTEGER(IntKi), PARAMETER :: M5N5FDxi = 1094 + INTEGER(IntKi), PARAMETER :: M5N6FDxi = 1095 + INTEGER(IntKi), PARAMETER :: M5N7FDxi = 1096 + INTEGER(IntKi), PARAMETER :: M5N8FDxi = 1097 + INTEGER(IntKi), PARAMETER :: M5N9FDxi = 1098 + INTEGER(IntKi), PARAMETER :: M6N1FDxi = 1099 + INTEGER(IntKi), PARAMETER :: M6N2FDxi = 1100 + INTEGER(IntKi), PARAMETER :: M6N3FDxi = 1101 + INTEGER(IntKi), PARAMETER :: M6N4FDxi = 1102 + INTEGER(IntKi), PARAMETER :: M6N5FDxi = 1103 + INTEGER(IntKi), PARAMETER :: M6N6FDxi = 1104 + INTEGER(IntKi), PARAMETER :: M6N7FDxi = 1105 + INTEGER(IntKi), PARAMETER :: M6N8FDxi = 1106 + INTEGER(IntKi), PARAMETER :: M6N9FDxi = 1107 + INTEGER(IntKi), PARAMETER :: M7N1FDxi = 1108 + INTEGER(IntKi), PARAMETER :: M7N2FDxi = 1109 + INTEGER(IntKi), PARAMETER :: M7N3FDxi = 1110 + INTEGER(IntKi), PARAMETER :: M7N4FDxi = 1111 + INTEGER(IntKi), PARAMETER :: M7N5FDxi = 1112 + INTEGER(IntKi), PARAMETER :: M7N6FDxi = 1113 + INTEGER(IntKi), PARAMETER :: M7N7FDxi = 1114 + INTEGER(IntKi), PARAMETER :: M7N8FDxi = 1115 + INTEGER(IntKi), PARAMETER :: M7N9FDxi = 1116 + INTEGER(IntKi), PARAMETER :: M8N1FDxi = 1117 + INTEGER(IntKi), PARAMETER :: M8N2FDxi = 1118 + INTEGER(IntKi), PARAMETER :: M8N3FDxi = 1119 + INTEGER(IntKi), PARAMETER :: M8N4FDxi = 1120 + INTEGER(IntKi), PARAMETER :: M8N5FDxi = 1121 + INTEGER(IntKi), PARAMETER :: M8N6FDxi = 1122 + INTEGER(IntKi), PARAMETER :: M8N7FDxi = 1123 + INTEGER(IntKi), PARAMETER :: M8N8FDxi = 1124 + INTEGER(IntKi), PARAMETER :: M8N9FDxi = 1125 + INTEGER(IntKi), PARAMETER :: M9N1FDxi = 1126 + INTEGER(IntKi), PARAMETER :: M9N2FDxi = 1127 + INTEGER(IntKi), PARAMETER :: M9N3FDxi = 1128 + INTEGER(IntKi), PARAMETER :: M9N4FDxi = 1129 + INTEGER(IntKi), PARAMETER :: M9N5FDxi = 1130 + INTEGER(IntKi), PARAMETER :: M9N6FDxi = 1131 + INTEGER(IntKi), PARAMETER :: M9N7FDxi = 1132 + INTEGER(IntKi), PARAMETER :: M9N8FDxi = 1133 + INTEGER(IntKi), PARAMETER :: M9N9FDxi = 1134 + INTEGER(IntKi), PARAMETER :: M1N1FDyi = 1135 + INTEGER(IntKi), PARAMETER :: M1N2FDyi = 1136 + INTEGER(IntKi), PARAMETER :: M1N3FDyi = 1137 + INTEGER(IntKi), PARAMETER :: M1N4FDyi = 1138 + INTEGER(IntKi), PARAMETER :: M1N5FDyi = 1139 + INTEGER(IntKi), PARAMETER :: M1N6FDyi = 1140 + INTEGER(IntKi), PARAMETER :: M1N7FDyi = 1141 + INTEGER(IntKi), PARAMETER :: M1N8FDyi = 1142 + INTEGER(IntKi), PARAMETER :: M1N9FDyi = 1143 + INTEGER(IntKi), PARAMETER :: M2N1FDyi = 1144 + INTEGER(IntKi), PARAMETER :: M2N2FDyi = 1145 + INTEGER(IntKi), PARAMETER :: M2N3FDyi = 1146 + INTEGER(IntKi), PARAMETER :: M2N4FDyi = 1147 + INTEGER(IntKi), PARAMETER :: M2N5FDyi = 1148 + INTEGER(IntKi), PARAMETER :: M2N6FDyi = 1149 + INTEGER(IntKi), PARAMETER :: M2N7FDyi = 1150 + INTEGER(IntKi), PARAMETER :: M2N8FDyi = 1151 + INTEGER(IntKi), PARAMETER :: M2N9FDyi = 1152 + INTEGER(IntKi), PARAMETER :: M3N1FDyi = 1153 + INTEGER(IntKi), PARAMETER :: M3N2FDyi = 1154 + INTEGER(IntKi), PARAMETER :: M3N3FDyi = 1155 + INTEGER(IntKi), PARAMETER :: M3N4FDyi = 1156 + INTEGER(IntKi), PARAMETER :: M3N5FDyi = 1157 + INTEGER(IntKi), PARAMETER :: M3N6FDyi = 1158 + INTEGER(IntKi), PARAMETER :: M3N7FDyi = 1159 + INTEGER(IntKi), PARAMETER :: M3N8FDyi = 1160 + INTEGER(IntKi), PARAMETER :: M3N9FDyi = 1161 + INTEGER(IntKi), PARAMETER :: M4N1FDyi = 1162 + INTEGER(IntKi), PARAMETER :: M4N2FDyi = 1163 + INTEGER(IntKi), PARAMETER :: M4N3FDyi = 1164 + INTEGER(IntKi), PARAMETER :: M4N4FDyi = 1165 + INTEGER(IntKi), PARAMETER :: M4N5FDyi = 1166 + INTEGER(IntKi), PARAMETER :: M4N6FDyi = 1167 + INTEGER(IntKi), PARAMETER :: M4N7FDyi = 1168 + INTEGER(IntKi), PARAMETER :: M4N8FDyi = 1169 + INTEGER(IntKi), PARAMETER :: M4N9FDyi = 1170 + INTEGER(IntKi), PARAMETER :: M5N1FDyi = 1171 + INTEGER(IntKi), PARAMETER :: M5N2FDyi = 1172 + INTEGER(IntKi), PARAMETER :: M5N3FDyi = 1173 + INTEGER(IntKi), PARAMETER :: M5N4FDyi = 1174 + INTEGER(IntKi), PARAMETER :: M5N5FDyi = 1175 + INTEGER(IntKi), PARAMETER :: M5N6FDyi = 1176 + INTEGER(IntKi), PARAMETER :: M5N7FDyi = 1177 + INTEGER(IntKi), PARAMETER :: M5N8FDyi = 1178 + INTEGER(IntKi), PARAMETER :: M5N9FDyi = 1179 + INTEGER(IntKi), PARAMETER :: M6N1FDyi = 1180 + INTEGER(IntKi), PARAMETER :: M6N2FDyi = 1181 + INTEGER(IntKi), PARAMETER :: M6N3FDyi = 1182 + INTEGER(IntKi), PARAMETER :: M6N4FDyi = 1183 + INTEGER(IntKi), PARAMETER :: M6N5FDyi = 1184 + INTEGER(IntKi), PARAMETER :: M6N6FDyi = 1185 + INTEGER(IntKi), PARAMETER :: M6N7FDyi = 1186 + INTEGER(IntKi), PARAMETER :: M6N8FDyi = 1187 + INTEGER(IntKi), PARAMETER :: M6N9FDyi = 1188 + INTEGER(IntKi), PARAMETER :: M7N1FDyi = 1189 + INTEGER(IntKi), PARAMETER :: M7N2FDyi = 1190 + INTEGER(IntKi), PARAMETER :: M7N3FDyi = 1191 + INTEGER(IntKi), PARAMETER :: M7N4FDyi = 1192 + INTEGER(IntKi), PARAMETER :: M7N5FDyi = 1193 + INTEGER(IntKi), PARAMETER :: M7N6FDyi = 1194 + INTEGER(IntKi), PARAMETER :: M7N7FDyi = 1195 + INTEGER(IntKi), PARAMETER :: M7N8FDyi = 1196 + INTEGER(IntKi), PARAMETER :: M7N9FDyi = 1197 + INTEGER(IntKi), PARAMETER :: M8N1FDyi = 1198 + INTEGER(IntKi), PARAMETER :: M8N2FDyi = 1199 + INTEGER(IntKi), PARAMETER :: M8N3FDyi = 1200 + INTEGER(IntKi), PARAMETER :: M8N4FDyi = 1201 + INTEGER(IntKi), PARAMETER :: M8N5FDyi = 1202 + INTEGER(IntKi), PARAMETER :: M8N6FDyi = 1203 + INTEGER(IntKi), PARAMETER :: M8N7FDyi = 1204 + INTEGER(IntKi), PARAMETER :: M8N8FDyi = 1205 + INTEGER(IntKi), PARAMETER :: M8N9FDyi = 1206 + INTEGER(IntKi), PARAMETER :: M9N1FDyi = 1207 + INTEGER(IntKi), PARAMETER :: M9N2FDyi = 1208 + INTEGER(IntKi), PARAMETER :: M9N3FDyi = 1209 + INTEGER(IntKi), PARAMETER :: M9N4FDyi = 1210 + INTEGER(IntKi), PARAMETER :: M9N5FDyi = 1211 + INTEGER(IntKi), PARAMETER :: M9N6FDyi = 1212 + INTEGER(IntKi), PARAMETER :: M9N7FDyi = 1213 + INTEGER(IntKi), PARAMETER :: M9N8FDyi = 1214 + INTEGER(IntKi), PARAMETER :: M9N9FDyi = 1215 + INTEGER(IntKi), PARAMETER :: M1N1FDzi = 1216 + INTEGER(IntKi), PARAMETER :: M1N2FDzi = 1217 + INTEGER(IntKi), PARAMETER :: M1N3FDzi = 1218 + INTEGER(IntKi), PARAMETER :: M1N4FDzi = 1219 + INTEGER(IntKi), PARAMETER :: M1N5FDzi = 1220 + INTEGER(IntKi), PARAMETER :: M1N6FDzi = 1221 + INTEGER(IntKi), PARAMETER :: M1N7FDzi = 1222 + INTEGER(IntKi), PARAMETER :: M1N8FDzi = 1223 + INTEGER(IntKi), PARAMETER :: M1N9FDzi = 1224 + INTEGER(IntKi), PARAMETER :: M2N1FDzi = 1225 + INTEGER(IntKi), PARAMETER :: M2N2FDzi = 1226 + INTEGER(IntKi), PARAMETER :: M2N3FDzi = 1227 + INTEGER(IntKi), PARAMETER :: M2N4FDzi = 1228 + INTEGER(IntKi), PARAMETER :: M2N5FDzi = 1229 + INTEGER(IntKi), PARAMETER :: M2N6FDzi = 1230 + INTEGER(IntKi), PARAMETER :: M2N7FDzi = 1231 + INTEGER(IntKi), PARAMETER :: M2N8FDzi = 1232 + INTEGER(IntKi), PARAMETER :: M2N9FDzi = 1233 + INTEGER(IntKi), PARAMETER :: M3N1FDzi = 1234 + INTEGER(IntKi), PARAMETER :: M3N2FDzi = 1235 + INTEGER(IntKi), PARAMETER :: M3N3FDzi = 1236 + INTEGER(IntKi), PARAMETER :: M3N4FDzi = 1237 + INTEGER(IntKi), PARAMETER :: M3N5FDzi = 1238 + INTEGER(IntKi), PARAMETER :: M3N6FDzi = 1239 + INTEGER(IntKi), PARAMETER :: M3N7FDzi = 1240 + INTEGER(IntKi), PARAMETER :: M3N8FDzi = 1241 + INTEGER(IntKi), PARAMETER :: M3N9FDzi = 1242 + INTEGER(IntKi), PARAMETER :: M4N1FDzi = 1243 + INTEGER(IntKi), PARAMETER :: M4N2FDzi = 1244 + INTEGER(IntKi), PARAMETER :: M4N3FDzi = 1245 + INTEGER(IntKi), PARAMETER :: M4N4FDzi = 1246 + INTEGER(IntKi), PARAMETER :: M4N5FDzi = 1247 + INTEGER(IntKi), PARAMETER :: M4N6FDzi = 1248 + INTEGER(IntKi), PARAMETER :: M4N7FDzi = 1249 + INTEGER(IntKi), PARAMETER :: M4N8FDzi = 1250 + INTEGER(IntKi), PARAMETER :: M4N9FDzi = 1251 + INTEGER(IntKi), PARAMETER :: M5N1FDzi = 1252 + INTEGER(IntKi), PARAMETER :: M5N2FDzi = 1253 + INTEGER(IntKi), PARAMETER :: M5N3FDzi = 1254 + INTEGER(IntKi), PARAMETER :: M5N4FDzi = 1255 + INTEGER(IntKi), PARAMETER :: M5N5FDzi = 1256 + INTEGER(IntKi), PARAMETER :: M5N6FDzi = 1257 + INTEGER(IntKi), PARAMETER :: M5N7FDzi = 1258 + INTEGER(IntKi), PARAMETER :: M5N8FDzi = 1259 + INTEGER(IntKi), PARAMETER :: M5N9FDzi = 1260 + INTEGER(IntKi), PARAMETER :: M6N1FDzi = 1261 + INTEGER(IntKi), PARAMETER :: M6N2FDzi = 1262 + INTEGER(IntKi), PARAMETER :: M6N3FDzi = 1263 + INTEGER(IntKi), PARAMETER :: M6N4FDzi = 1264 + INTEGER(IntKi), PARAMETER :: M6N5FDzi = 1265 + INTEGER(IntKi), PARAMETER :: M6N6FDzi = 1266 + INTEGER(IntKi), PARAMETER :: M6N7FDzi = 1267 + INTEGER(IntKi), PARAMETER :: M6N8FDzi = 1268 + INTEGER(IntKi), PARAMETER :: M6N9FDzi = 1269 + INTEGER(IntKi), PARAMETER :: M7N1FDzi = 1270 + INTEGER(IntKi), PARAMETER :: M7N2FDzi = 1271 + INTEGER(IntKi), PARAMETER :: M7N3FDzi = 1272 + INTEGER(IntKi), PARAMETER :: M7N4FDzi = 1273 + INTEGER(IntKi), PARAMETER :: M7N5FDzi = 1274 + INTEGER(IntKi), PARAMETER :: M7N6FDzi = 1275 + INTEGER(IntKi), PARAMETER :: M7N7FDzi = 1276 + INTEGER(IntKi), PARAMETER :: M7N8FDzi = 1277 + INTEGER(IntKi), PARAMETER :: M7N9FDzi = 1278 + INTEGER(IntKi), PARAMETER :: M8N1FDzi = 1279 + INTEGER(IntKi), PARAMETER :: M8N2FDzi = 1280 + INTEGER(IntKi), PARAMETER :: M8N3FDzi = 1281 + INTEGER(IntKi), PARAMETER :: M8N4FDzi = 1282 + INTEGER(IntKi), PARAMETER :: M8N5FDzi = 1283 + INTEGER(IntKi), PARAMETER :: M8N6FDzi = 1284 + INTEGER(IntKi), PARAMETER :: M8N7FDzi = 1285 + INTEGER(IntKi), PARAMETER :: M8N8FDzi = 1286 + INTEGER(IntKi), PARAMETER :: M8N9FDzi = 1287 + INTEGER(IntKi), PARAMETER :: M9N1FDzi = 1288 + INTEGER(IntKi), PARAMETER :: M9N2FDzi = 1289 + INTEGER(IntKi), PARAMETER :: M9N3FDzi = 1290 + INTEGER(IntKi), PARAMETER :: M9N4FDzi = 1291 + INTEGER(IntKi), PARAMETER :: M9N5FDzi = 1292 + INTEGER(IntKi), PARAMETER :: M9N6FDzi = 1293 + INTEGER(IntKi), PARAMETER :: M9N7FDzi = 1294 + INTEGER(IntKi), PARAMETER :: M9N8FDzi = 1295 + INTEGER(IntKi), PARAMETER :: M9N9FDzi = 1296 + INTEGER(IntKi), PARAMETER :: M1N1FIxi = 1297 + INTEGER(IntKi), PARAMETER :: M1N2FIxi = 1298 + INTEGER(IntKi), PARAMETER :: M1N3FIxi = 1299 + INTEGER(IntKi), PARAMETER :: M1N4FIxi = 1300 + INTEGER(IntKi), PARAMETER :: M1N5FIxi = 1301 + INTEGER(IntKi), PARAMETER :: M1N6FIxi = 1302 + INTEGER(IntKi), PARAMETER :: M1N7FIxi = 1303 + INTEGER(IntKi), PARAMETER :: M1N8FIxi = 1304 + INTEGER(IntKi), PARAMETER :: M1N9FIxi = 1305 + INTEGER(IntKi), PARAMETER :: M2N1FIxi = 1306 + INTEGER(IntKi), PARAMETER :: M2N2FIxi = 1307 + INTEGER(IntKi), PARAMETER :: M2N3FIxi = 1308 + INTEGER(IntKi), PARAMETER :: M2N4FIxi = 1309 + INTEGER(IntKi), PARAMETER :: M2N5FIxi = 1310 + INTEGER(IntKi), PARAMETER :: M2N6FIxi = 1311 + INTEGER(IntKi), PARAMETER :: M2N7FIxi = 1312 + INTEGER(IntKi), PARAMETER :: M2N8FIxi = 1313 + INTEGER(IntKi), PARAMETER :: M2N9FIxi = 1314 + INTEGER(IntKi), PARAMETER :: M3N1FIxi = 1315 + INTEGER(IntKi), PARAMETER :: M3N2FIxi = 1316 + INTEGER(IntKi), PARAMETER :: M3N3FIxi = 1317 + INTEGER(IntKi), PARAMETER :: M3N4FIxi = 1318 + INTEGER(IntKi), PARAMETER :: M3N5FIxi = 1319 + INTEGER(IntKi), PARAMETER :: M3N6FIxi = 1320 + INTEGER(IntKi), PARAMETER :: M3N7FIxi = 1321 + INTEGER(IntKi), PARAMETER :: M3N8FIxi = 1322 + INTEGER(IntKi), PARAMETER :: M3N9FIxi = 1323 + INTEGER(IntKi), PARAMETER :: M4N1FIxi = 1324 + INTEGER(IntKi), PARAMETER :: M4N2FIxi = 1325 + INTEGER(IntKi), PARAMETER :: M4N3FIxi = 1326 + INTEGER(IntKi), PARAMETER :: M4N4FIxi = 1327 + INTEGER(IntKi), PARAMETER :: M4N5FIxi = 1328 + INTEGER(IntKi), PARAMETER :: M4N6FIxi = 1329 + INTEGER(IntKi), PARAMETER :: M4N7FIxi = 1330 + INTEGER(IntKi), PARAMETER :: M4N8FIxi = 1331 + INTEGER(IntKi), PARAMETER :: M4N9FIxi = 1332 + INTEGER(IntKi), PARAMETER :: M5N1FIxi = 1333 + INTEGER(IntKi), PARAMETER :: M5N2FIxi = 1334 + INTEGER(IntKi), PARAMETER :: M5N3FIxi = 1335 + INTEGER(IntKi), PARAMETER :: M5N4FIxi = 1336 + INTEGER(IntKi), PARAMETER :: M5N5FIxi = 1337 + INTEGER(IntKi), PARAMETER :: M5N6FIxi = 1338 + INTEGER(IntKi), PARAMETER :: M5N7FIxi = 1339 + INTEGER(IntKi), PARAMETER :: M5N8FIxi = 1340 + INTEGER(IntKi), PARAMETER :: M5N9FIxi = 1341 + INTEGER(IntKi), PARAMETER :: M6N1FIxi = 1342 + INTEGER(IntKi), PARAMETER :: M6N2FIxi = 1343 + INTEGER(IntKi), PARAMETER :: M6N3FIxi = 1344 + INTEGER(IntKi), PARAMETER :: M6N4FIxi = 1345 + INTEGER(IntKi), PARAMETER :: M6N5FIxi = 1346 + INTEGER(IntKi), PARAMETER :: M6N6FIxi = 1347 + INTEGER(IntKi), PARAMETER :: M6N7FIxi = 1348 + INTEGER(IntKi), PARAMETER :: M6N8FIxi = 1349 + INTEGER(IntKi), PARAMETER :: M6N9FIxi = 1350 + INTEGER(IntKi), PARAMETER :: M7N1FIxi = 1351 + INTEGER(IntKi), PARAMETER :: M7N2FIxi = 1352 + INTEGER(IntKi), PARAMETER :: M7N3FIxi = 1353 + INTEGER(IntKi), PARAMETER :: M7N4FIxi = 1354 + INTEGER(IntKi), PARAMETER :: M7N5FIxi = 1355 + INTEGER(IntKi), PARAMETER :: M7N6FIxi = 1356 + INTEGER(IntKi), PARAMETER :: M7N7FIxi = 1357 + INTEGER(IntKi), PARAMETER :: M7N8FIxi = 1358 + INTEGER(IntKi), PARAMETER :: M7N9FIxi = 1359 + INTEGER(IntKi), PARAMETER :: M8N1FIxi = 1360 + INTEGER(IntKi), PARAMETER :: M8N2FIxi = 1361 + INTEGER(IntKi), PARAMETER :: M8N3FIxi = 1362 + INTEGER(IntKi), PARAMETER :: M8N4FIxi = 1363 + INTEGER(IntKi), PARAMETER :: M8N5FIxi = 1364 + INTEGER(IntKi), PARAMETER :: M8N6FIxi = 1365 + INTEGER(IntKi), PARAMETER :: M8N7FIxi = 1366 + INTEGER(IntKi), PARAMETER :: M8N8FIxi = 1367 + INTEGER(IntKi), PARAMETER :: M8N9FIxi = 1368 + INTEGER(IntKi), PARAMETER :: M9N1FIxi = 1369 + INTEGER(IntKi), PARAMETER :: M9N2FIxi = 1370 + INTEGER(IntKi), PARAMETER :: M9N3FIxi = 1371 + INTEGER(IntKi), PARAMETER :: M9N4FIxi = 1372 + INTEGER(IntKi), PARAMETER :: M9N5FIxi = 1373 + INTEGER(IntKi), PARAMETER :: M9N6FIxi = 1374 + INTEGER(IntKi), PARAMETER :: M9N7FIxi = 1375 + INTEGER(IntKi), PARAMETER :: M9N8FIxi = 1376 + INTEGER(IntKi), PARAMETER :: M9N9FIxi = 1377 + INTEGER(IntKi), PARAMETER :: M1N1FIyi = 1378 + INTEGER(IntKi), PARAMETER :: M1N2FIyi = 1379 + INTEGER(IntKi), PARAMETER :: M1N3FIyi = 1380 + INTEGER(IntKi), PARAMETER :: M1N4FIyi = 1381 + INTEGER(IntKi), PARAMETER :: M1N5FIyi = 1382 + INTEGER(IntKi), PARAMETER :: M1N6FIyi = 1383 + INTEGER(IntKi), PARAMETER :: M1N7FIyi = 1384 + INTEGER(IntKi), PARAMETER :: M1N8FIyi = 1385 + INTEGER(IntKi), PARAMETER :: M1N9FIyi = 1386 + INTEGER(IntKi), PARAMETER :: M2N1FIyi = 1387 + INTEGER(IntKi), PARAMETER :: M2N2FIyi = 1388 + INTEGER(IntKi), PARAMETER :: M2N3FIyi = 1389 + INTEGER(IntKi), PARAMETER :: M2N4FIyi = 1390 + INTEGER(IntKi), PARAMETER :: M2N5FIyi = 1391 + INTEGER(IntKi), PARAMETER :: M2N6FIyi = 1392 + INTEGER(IntKi), PARAMETER :: M2N7FIyi = 1393 + INTEGER(IntKi), PARAMETER :: M2N8FIyi = 1394 + INTEGER(IntKi), PARAMETER :: M2N9FIyi = 1395 + INTEGER(IntKi), PARAMETER :: M3N1FIyi = 1396 + INTEGER(IntKi), PARAMETER :: M3N2FIyi = 1397 + INTEGER(IntKi), PARAMETER :: M3N3FIyi = 1398 + INTEGER(IntKi), PARAMETER :: M3N4FIyi = 1399 + INTEGER(IntKi), PARAMETER :: M3N5FIyi = 1400 + INTEGER(IntKi), PARAMETER :: M3N6FIyi = 1401 + INTEGER(IntKi), PARAMETER :: M3N7FIyi = 1402 + INTEGER(IntKi), PARAMETER :: M3N8FIyi = 1403 + INTEGER(IntKi), PARAMETER :: M3N9FIyi = 1404 + INTEGER(IntKi), PARAMETER :: M4N1FIyi = 1405 + INTEGER(IntKi), PARAMETER :: M4N2FIyi = 1406 + INTEGER(IntKi), PARAMETER :: M4N3FIyi = 1407 + INTEGER(IntKi), PARAMETER :: M4N4FIyi = 1408 + INTEGER(IntKi), PARAMETER :: M4N5FIyi = 1409 + INTEGER(IntKi), PARAMETER :: M4N6FIyi = 1410 + INTEGER(IntKi), PARAMETER :: M4N7FIyi = 1411 + INTEGER(IntKi), PARAMETER :: M4N8FIyi = 1412 + INTEGER(IntKi), PARAMETER :: M4N9FIyi = 1413 + INTEGER(IntKi), PARAMETER :: M5N1FIyi = 1414 + INTEGER(IntKi), PARAMETER :: M5N2FIyi = 1415 + INTEGER(IntKi), PARAMETER :: M5N3FIyi = 1416 + INTEGER(IntKi), PARAMETER :: M5N4FIyi = 1417 + INTEGER(IntKi), PARAMETER :: M5N5FIyi = 1418 + INTEGER(IntKi), PARAMETER :: M5N6FIyi = 1419 + INTEGER(IntKi), PARAMETER :: M5N7FIyi = 1420 + INTEGER(IntKi), PARAMETER :: M5N8FIyi = 1421 + INTEGER(IntKi), PARAMETER :: M5N9FIyi = 1422 + INTEGER(IntKi), PARAMETER :: M6N1FIyi = 1423 + INTEGER(IntKi), PARAMETER :: M6N2FIyi = 1424 + INTEGER(IntKi), PARAMETER :: M6N3FIyi = 1425 + INTEGER(IntKi), PARAMETER :: M6N4FIyi = 1426 + INTEGER(IntKi), PARAMETER :: M6N5FIyi = 1427 + INTEGER(IntKi), PARAMETER :: M6N6FIyi = 1428 + INTEGER(IntKi), PARAMETER :: M6N7FIyi = 1429 + INTEGER(IntKi), PARAMETER :: M6N8FIyi = 1430 + INTEGER(IntKi), PARAMETER :: M6N9FIyi = 1431 + INTEGER(IntKi), PARAMETER :: M7N1FIyi = 1432 + INTEGER(IntKi), PARAMETER :: M7N2FIyi = 1433 + INTEGER(IntKi), PARAMETER :: M7N3FIyi = 1434 + INTEGER(IntKi), PARAMETER :: M7N4FIyi = 1435 + INTEGER(IntKi), PARAMETER :: M7N5FIyi = 1436 + INTEGER(IntKi), PARAMETER :: M7N6FIyi = 1437 + INTEGER(IntKi), PARAMETER :: M7N7FIyi = 1438 + INTEGER(IntKi), PARAMETER :: M7N8FIyi = 1439 + INTEGER(IntKi), PARAMETER :: M7N9FIyi = 1440 + INTEGER(IntKi), PARAMETER :: M8N1FIyi = 1441 + INTEGER(IntKi), PARAMETER :: M8N2FIyi = 1442 + INTEGER(IntKi), PARAMETER :: M8N3FIyi = 1443 + INTEGER(IntKi), PARAMETER :: M8N4FIyi = 1444 + INTEGER(IntKi), PARAMETER :: M8N5FIyi = 1445 + INTEGER(IntKi), PARAMETER :: M8N6FIyi = 1446 + INTEGER(IntKi), PARAMETER :: M8N7FIyi = 1447 + INTEGER(IntKi), PARAMETER :: M8N8FIyi = 1448 + INTEGER(IntKi), PARAMETER :: M8N9FIyi = 1449 + INTEGER(IntKi), PARAMETER :: M9N1FIyi = 1450 + INTEGER(IntKi), PARAMETER :: M9N2FIyi = 1451 + INTEGER(IntKi), PARAMETER :: M9N3FIyi = 1452 + INTEGER(IntKi), PARAMETER :: M9N4FIyi = 1453 + INTEGER(IntKi), PARAMETER :: M9N5FIyi = 1454 + INTEGER(IntKi), PARAMETER :: M9N6FIyi = 1455 + INTEGER(IntKi), PARAMETER :: M9N7FIyi = 1456 + INTEGER(IntKi), PARAMETER :: M9N8FIyi = 1457 + INTEGER(IntKi), PARAMETER :: M9N9FIyi = 1458 + INTEGER(IntKi), PARAMETER :: M1N1FIzi = 1459 + INTEGER(IntKi), PARAMETER :: M1N2FIzi = 1460 + INTEGER(IntKi), PARAMETER :: M1N3FIzi = 1461 + INTEGER(IntKi), PARAMETER :: M1N4FIzi = 1462 + INTEGER(IntKi), PARAMETER :: M1N5FIzi = 1463 + INTEGER(IntKi), PARAMETER :: M1N6FIzi = 1464 + INTEGER(IntKi), PARAMETER :: M1N7FIzi = 1465 + INTEGER(IntKi), PARAMETER :: M1N8FIzi = 1466 + INTEGER(IntKi), PARAMETER :: M1N9FIzi = 1467 + INTEGER(IntKi), PARAMETER :: M2N1FIzi = 1468 + INTEGER(IntKi), PARAMETER :: M2N2FIzi = 1469 + INTEGER(IntKi), PARAMETER :: M2N3FIzi = 1470 + INTEGER(IntKi), PARAMETER :: M2N4FIzi = 1471 + INTEGER(IntKi), PARAMETER :: M2N5FIzi = 1472 + INTEGER(IntKi), PARAMETER :: M2N6FIzi = 1473 + INTEGER(IntKi), PARAMETER :: M2N7FIzi = 1474 + INTEGER(IntKi), PARAMETER :: M2N8FIzi = 1475 + INTEGER(IntKi), PARAMETER :: M2N9FIzi = 1476 + INTEGER(IntKi), PARAMETER :: M3N1FIzi = 1477 + INTEGER(IntKi), PARAMETER :: M3N2FIzi = 1478 + INTEGER(IntKi), PARAMETER :: M3N3FIzi = 1479 + INTEGER(IntKi), PARAMETER :: M3N4FIzi = 1480 + INTEGER(IntKi), PARAMETER :: M3N5FIzi = 1481 + INTEGER(IntKi), PARAMETER :: M3N6FIzi = 1482 + INTEGER(IntKi), PARAMETER :: M3N7FIzi = 1483 + INTEGER(IntKi), PARAMETER :: M3N8FIzi = 1484 + INTEGER(IntKi), PARAMETER :: M3N9FIzi = 1485 + INTEGER(IntKi), PARAMETER :: M4N1FIzi = 1486 + INTEGER(IntKi), PARAMETER :: M4N2FIzi = 1487 + INTEGER(IntKi), PARAMETER :: M4N3FIzi = 1488 + INTEGER(IntKi), PARAMETER :: M4N4FIzi = 1489 + INTEGER(IntKi), PARAMETER :: M4N5FIzi = 1490 + INTEGER(IntKi), PARAMETER :: M4N6FIzi = 1491 + INTEGER(IntKi), PARAMETER :: M4N7FIzi = 1492 + INTEGER(IntKi), PARAMETER :: M4N8FIzi = 1493 + INTEGER(IntKi), PARAMETER :: M4N9FIzi = 1494 + INTEGER(IntKi), PARAMETER :: M5N1FIzi = 1495 + INTEGER(IntKi), PARAMETER :: M5N2FIzi = 1496 + INTEGER(IntKi), PARAMETER :: M5N3FIzi = 1497 + INTEGER(IntKi), PARAMETER :: M5N4FIzi = 1498 + INTEGER(IntKi), PARAMETER :: M5N5FIzi = 1499 + INTEGER(IntKi), PARAMETER :: M5N6FIzi = 1500 + INTEGER(IntKi), PARAMETER :: M5N7FIzi = 1501 + INTEGER(IntKi), PARAMETER :: M5N8FIzi = 1502 + INTEGER(IntKi), PARAMETER :: M5N9FIzi = 1503 + INTEGER(IntKi), PARAMETER :: M6N1FIzi = 1504 + INTEGER(IntKi), PARAMETER :: M6N2FIzi = 1505 + INTEGER(IntKi), PARAMETER :: M6N3FIzi = 1506 + INTEGER(IntKi), PARAMETER :: M6N4FIzi = 1507 + INTEGER(IntKi), PARAMETER :: M6N5FIzi = 1508 + INTEGER(IntKi), PARAMETER :: M6N6FIzi = 1509 + INTEGER(IntKi), PARAMETER :: M6N7FIzi = 1510 + INTEGER(IntKi), PARAMETER :: M6N8FIzi = 1511 + INTEGER(IntKi), PARAMETER :: M6N9FIzi = 1512 + INTEGER(IntKi), PARAMETER :: M7N1FIzi = 1513 + INTEGER(IntKi), PARAMETER :: M7N2FIzi = 1514 + INTEGER(IntKi), PARAMETER :: M7N3FIzi = 1515 + INTEGER(IntKi), PARAMETER :: M7N4FIzi = 1516 + INTEGER(IntKi), PARAMETER :: M7N5FIzi = 1517 + INTEGER(IntKi), PARAMETER :: M7N6FIzi = 1518 + INTEGER(IntKi), PARAMETER :: M7N7FIzi = 1519 + INTEGER(IntKi), PARAMETER :: M7N8FIzi = 1520 + INTEGER(IntKi), PARAMETER :: M7N9FIzi = 1521 + INTEGER(IntKi), PARAMETER :: M8N1FIzi = 1522 + INTEGER(IntKi), PARAMETER :: M8N2FIzi = 1523 + INTEGER(IntKi), PARAMETER :: M8N3FIzi = 1524 + INTEGER(IntKi), PARAMETER :: M8N4FIzi = 1525 + INTEGER(IntKi), PARAMETER :: M8N5FIzi = 1526 + INTEGER(IntKi), PARAMETER :: M8N6FIzi = 1527 + INTEGER(IntKi), PARAMETER :: M8N7FIzi = 1528 + INTEGER(IntKi), PARAMETER :: M8N8FIzi = 1529 + INTEGER(IntKi), PARAMETER :: M8N9FIzi = 1530 + INTEGER(IntKi), PARAMETER :: M9N1FIzi = 1531 + INTEGER(IntKi), PARAMETER :: M9N2FIzi = 1532 + INTEGER(IntKi), PARAMETER :: M9N3FIzi = 1533 + INTEGER(IntKi), PARAMETER :: M9N4FIzi = 1534 + INTEGER(IntKi), PARAMETER :: M9N5FIzi = 1535 + INTEGER(IntKi), PARAMETER :: M9N6FIzi = 1536 + INTEGER(IntKi), PARAMETER :: M9N7FIzi = 1537 + INTEGER(IntKi), PARAMETER :: M9N8FIzi = 1538 + INTEGER(IntKi), PARAMETER :: M9N9FIzi = 1539 + INTEGER(IntKi), PARAMETER :: M1N1FBxi = 1540 + INTEGER(IntKi), PARAMETER :: M1N2FBxi = 1541 + INTEGER(IntKi), PARAMETER :: M1N3FBxi = 1542 + INTEGER(IntKi), PARAMETER :: M1N4FBxi = 1543 + INTEGER(IntKi), PARAMETER :: M1N5FBxi = 1544 + INTEGER(IntKi), PARAMETER :: M1N6FBxi = 1545 + INTEGER(IntKi), PARAMETER :: M1N7FBxi = 1546 + INTEGER(IntKi), PARAMETER :: M1N8FBxi = 1547 + INTEGER(IntKi), PARAMETER :: M1N9FBxi = 1548 + INTEGER(IntKi), PARAMETER :: M2N1FBxi = 1549 + INTEGER(IntKi), PARAMETER :: M2N2FBxi = 1550 + INTEGER(IntKi), PARAMETER :: M2N3FBxi = 1551 + INTEGER(IntKi), PARAMETER :: M2N4FBxi = 1552 + INTEGER(IntKi), PARAMETER :: M2N5FBxi = 1553 + INTEGER(IntKi), PARAMETER :: M2N6FBxi = 1554 + INTEGER(IntKi), PARAMETER :: M2N7FBxi = 1555 + INTEGER(IntKi), PARAMETER :: M2N8FBxi = 1556 + INTEGER(IntKi), PARAMETER :: M2N9FBxi = 1557 + INTEGER(IntKi), PARAMETER :: M3N1FBxi = 1558 + INTEGER(IntKi), PARAMETER :: M3N2FBxi = 1559 + INTEGER(IntKi), PARAMETER :: M3N3FBxi = 1560 + INTEGER(IntKi), PARAMETER :: M3N4FBxi = 1561 + INTEGER(IntKi), PARAMETER :: M3N5FBxi = 1562 + INTEGER(IntKi), PARAMETER :: M3N6FBxi = 1563 + INTEGER(IntKi), PARAMETER :: M3N7FBxi = 1564 + INTEGER(IntKi), PARAMETER :: M3N8FBxi = 1565 + INTEGER(IntKi), PARAMETER :: M3N9FBxi = 1566 + INTEGER(IntKi), PARAMETER :: M4N1FBxi = 1567 + INTEGER(IntKi), PARAMETER :: M4N2FBxi = 1568 + INTEGER(IntKi), PARAMETER :: M4N3FBxi = 1569 + INTEGER(IntKi), PARAMETER :: M4N4FBxi = 1570 + INTEGER(IntKi), PARAMETER :: M4N5FBxi = 1571 + INTEGER(IntKi), PARAMETER :: M4N6FBxi = 1572 + INTEGER(IntKi), PARAMETER :: M4N7FBxi = 1573 + INTEGER(IntKi), PARAMETER :: M4N8FBxi = 1574 + INTEGER(IntKi), PARAMETER :: M4N9FBxi = 1575 + INTEGER(IntKi), PARAMETER :: M5N1FBxi = 1576 + INTEGER(IntKi), PARAMETER :: M5N2FBxi = 1577 + INTEGER(IntKi), PARAMETER :: M5N3FBxi = 1578 + INTEGER(IntKi), PARAMETER :: M5N4FBxi = 1579 + INTEGER(IntKi), PARAMETER :: M5N5FBxi = 1580 + INTEGER(IntKi), PARAMETER :: M5N6FBxi = 1581 + INTEGER(IntKi), PARAMETER :: M5N7FBxi = 1582 + INTEGER(IntKi), PARAMETER :: M5N8FBxi = 1583 + INTEGER(IntKi), PARAMETER :: M5N9FBxi = 1584 + INTEGER(IntKi), PARAMETER :: M6N1FBxi = 1585 + INTEGER(IntKi), PARAMETER :: M6N2FBxi = 1586 + INTEGER(IntKi), PARAMETER :: M6N3FBxi = 1587 + INTEGER(IntKi), PARAMETER :: M6N4FBxi = 1588 + INTEGER(IntKi), PARAMETER :: M6N5FBxi = 1589 + INTEGER(IntKi), PARAMETER :: M6N6FBxi = 1590 + INTEGER(IntKi), PARAMETER :: M6N7FBxi = 1591 + INTEGER(IntKi), PARAMETER :: M6N8FBxi = 1592 + INTEGER(IntKi), PARAMETER :: M6N9FBxi = 1593 + INTEGER(IntKi), PARAMETER :: M7N1FBxi = 1594 + INTEGER(IntKi), PARAMETER :: M7N2FBxi = 1595 + INTEGER(IntKi), PARAMETER :: M7N3FBxi = 1596 + INTEGER(IntKi), PARAMETER :: M7N4FBxi = 1597 + INTEGER(IntKi), PARAMETER :: M7N5FBxi = 1598 + INTEGER(IntKi), PARAMETER :: M7N6FBxi = 1599 + INTEGER(IntKi), PARAMETER :: M7N7FBxi = 1600 + INTEGER(IntKi), PARAMETER :: M7N8FBxi = 1601 + INTEGER(IntKi), PARAMETER :: M7N9FBxi = 1602 + INTEGER(IntKi), PARAMETER :: M8N1FBxi = 1603 + INTEGER(IntKi), PARAMETER :: M8N2FBxi = 1604 + INTEGER(IntKi), PARAMETER :: M8N3FBxi = 1605 + INTEGER(IntKi), PARAMETER :: M8N4FBxi = 1606 + INTEGER(IntKi), PARAMETER :: M8N5FBxi = 1607 + INTEGER(IntKi), PARAMETER :: M8N6FBxi = 1608 + INTEGER(IntKi), PARAMETER :: M8N7FBxi = 1609 + INTEGER(IntKi), PARAMETER :: M8N8FBxi = 1610 + INTEGER(IntKi), PARAMETER :: M8N9FBxi = 1611 + INTEGER(IntKi), PARAMETER :: M9N1FBxi = 1612 + INTEGER(IntKi), PARAMETER :: M9N2FBxi = 1613 + INTEGER(IntKi), PARAMETER :: M9N3FBxi = 1614 + INTEGER(IntKi), PARAMETER :: M9N4FBxi = 1615 + INTEGER(IntKi), PARAMETER :: M9N5FBxi = 1616 + INTEGER(IntKi), PARAMETER :: M9N6FBxi = 1617 + INTEGER(IntKi), PARAMETER :: M9N7FBxi = 1618 + INTEGER(IntKi), PARAMETER :: M9N8FBxi = 1619 + INTEGER(IntKi), PARAMETER :: M9N9FBxi = 1620 + INTEGER(IntKi), PARAMETER :: M1N1FByi = 1621 + INTEGER(IntKi), PARAMETER :: M1N2FByi = 1622 + INTEGER(IntKi), PARAMETER :: M1N3FByi = 1623 + INTEGER(IntKi), PARAMETER :: M1N4FByi = 1624 + INTEGER(IntKi), PARAMETER :: M1N5FByi = 1625 + INTEGER(IntKi), PARAMETER :: M1N6FByi = 1626 + INTEGER(IntKi), PARAMETER :: M1N7FByi = 1627 + INTEGER(IntKi), PARAMETER :: M1N8FByi = 1628 + INTEGER(IntKi), PARAMETER :: M1N9FByi = 1629 + INTEGER(IntKi), PARAMETER :: M2N1FByi = 1630 + INTEGER(IntKi), PARAMETER :: M2N2FByi = 1631 + INTEGER(IntKi), PARAMETER :: M2N3FByi = 1632 + INTEGER(IntKi), PARAMETER :: M2N4FByi = 1633 + INTEGER(IntKi), PARAMETER :: M2N5FByi = 1634 + INTEGER(IntKi), PARAMETER :: M2N6FByi = 1635 + INTEGER(IntKi), PARAMETER :: M2N7FByi = 1636 + INTEGER(IntKi), PARAMETER :: M2N8FByi = 1637 + INTEGER(IntKi), PARAMETER :: M2N9FByi = 1638 + INTEGER(IntKi), PARAMETER :: M3N1FByi = 1639 + INTEGER(IntKi), PARAMETER :: M3N2FByi = 1640 + INTEGER(IntKi), PARAMETER :: M3N3FByi = 1641 + INTEGER(IntKi), PARAMETER :: M3N4FByi = 1642 + INTEGER(IntKi), PARAMETER :: M3N5FByi = 1643 + INTEGER(IntKi), PARAMETER :: M3N6FByi = 1644 + INTEGER(IntKi), PARAMETER :: M3N7FByi = 1645 + INTEGER(IntKi), PARAMETER :: M3N8FByi = 1646 + INTEGER(IntKi), PARAMETER :: M3N9FByi = 1647 + INTEGER(IntKi), PARAMETER :: M4N1FByi = 1648 + INTEGER(IntKi), PARAMETER :: M4N2FByi = 1649 + INTEGER(IntKi), PARAMETER :: M4N3FByi = 1650 + INTEGER(IntKi), PARAMETER :: M4N4FByi = 1651 + INTEGER(IntKi), PARAMETER :: M4N5FByi = 1652 + INTEGER(IntKi), PARAMETER :: M4N6FByi = 1653 + INTEGER(IntKi), PARAMETER :: M4N7FByi = 1654 + INTEGER(IntKi), PARAMETER :: M4N8FByi = 1655 + INTEGER(IntKi), PARAMETER :: M4N9FByi = 1656 + INTEGER(IntKi), PARAMETER :: M5N1FByi = 1657 + INTEGER(IntKi), PARAMETER :: M5N2FByi = 1658 + INTEGER(IntKi), PARAMETER :: M5N3FByi = 1659 + INTEGER(IntKi), PARAMETER :: M5N4FByi = 1660 + INTEGER(IntKi), PARAMETER :: M5N5FByi = 1661 + INTEGER(IntKi), PARAMETER :: M5N6FByi = 1662 + INTEGER(IntKi), PARAMETER :: M5N7FByi = 1663 + INTEGER(IntKi), PARAMETER :: M5N8FByi = 1664 + INTEGER(IntKi), PARAMETER :: M5N9FByi = 1665 + INTEGER(IntKi), PARAMETER :: M6N1FByi = 1666 + INTEGER(IntKi), PARAMETER :: M6N2FByi = 1667 + INTEGER(IntKi), PARAMETER :: M6N3FByi = 1668 + INTEGER(IntKi), PARAMETER :: M6N4FByi = 1669 + INTEGER(IntKi), PARAMETER :: M6N5FByi = 1670 + INTEGER(IntKi), PARAMETER :: M6N6FByi = 1671 + INTEGER(IntKi), PARAMETER :: M6N7FByi = 1672 + INTEGER(IntKi), PARAMETER :: M6N8FByi = 1673 + INTEGER(IntKi), PARAMETER :: M6N9FByi = 1674 + INTEGER(IntKi), PARAMETER :: M7N1FByi = 1675 + INTEGER(IntKi), PARAMETER :: M7N2FByi = 1676 + INTEGER(IntKi), PARAMETER :: M7N3FByi = 1677 + INTEGER(IntKi), PARAMETER :: M7N4FByi = 1678 + INTEGER(IntKi), PARAMETER :: M7N5FByi = 1679 + INTEGER(IntKi), PARAMETER :: M7N6FByi = 1680 + INTEGER(IntKi), PARAMETER :: M7N7FByi = 1681 + INTEGER(IntKi), PARAMETER :: M7N8FByi = 1682 + INTEGER(IntKi), PARAMETER :: M7N9FByi = 1683 + INTEGER(IntKi), PARAMETER :: M8N1FByi = 1684 + INTEGER(IntKi), PARAMETER :: M8N2FByi = 1685 + INTEGER(IntKi), PARAMETER :: M8N3FByi = 1686 + INTEGER(IntKi), PARAMETER :: M8N4FByi = 1687 + INTEGER(IntKi), PARAMETER :: M8N5FByi = 1688 + INTEGER(IntKi), PARAMETER :: M8N6FByi = 1689 + INTEGER(IntKi), PARAMETER :: M8N7FByi = 1690 + INTEGER(IntKi), PARAMETER :: M8N8FByi = 1691 + INTEGER(IntKi), PARAMETER :: M8N9FByi = 1692 + INTEGER(IntKi), PARAMETER :: M9N1FByi = 1693 + INTEGER(IntKi), PARAMETER :: M9N2FByi = 1694 + INTEGER(IntKi), PARAMETER :: M9N3FByi = 1695 + INTEGER(IntKi), PARAMETER :: M9N4FByi = 1696 + INTEGER(IntKi), PARAMETER :: M9N5FByi = 1697 + INTEGER(IntKi), PARAMETER :: M9N6FByi = 1698 + INTEGER(IntKi), PARAMETER :: M9N7FByi = 1699 + INTEGER(IntKi), PARAMETER :: M9N8FByi = 1700 + INTEGER(IntKi), PARAMETER :: M9N9FByi = 1701 + INTEGER(IntKi), PARAMETER :: M1N1FBzi = 1702 + INTEGER(IntKi), PARAMETER :: M1N2FBzi = 1703 + INTEGER(IntKi), PARAMETER :: M1N3FBzi = 1704 + INTEGER(IntKi), PARAMETER :: M1N4FBzi = 1705 + INTEGER(IntKi), PARAMETER :: M1N5FBzi = 1706 + INTEGER(IntKi), PARAMETER :: M1N6FBzi = 1707 + INTEGER(IntKi), PARAMETER :: M1N7FBzi = 1708 + INTEGER(IntKi), PARAMETER :: M1N8FBzi = 1709 + INTEGER(IntKi), PARAMETER :: M1N9FBzi = 1710 + INTEGER(IntKi), PARAMETER :: M2N1FBzi = 1711 + INTEGER(IntKi), PARAMETER :: M2N2FBzi = 1712 + INTEGER(IntKi), PARAMETER :: M2N3FBzi = 1713 + INTEGER(IntKi), PARAMETER :: M2N4FBzi = 1714 + INTEGER(IntKi), PARAMETER :: M2N5FBzi = 1715 + INTEGER(IntKi), PARAMETER :: M2N6FBzi = 1716 + INTEGER(IntKi), PARAMETER :: M2N7FBzi = 1717 + INTEGER(IntKi), PARAMETER :: M2N8FBzi = 1718 + INTEGER(IntKi), PARAMETER :: M2N9FBzi = 1719 + INTEGER(IntKi), PARAMETER :: M3N1FBzi = 1720 + INTEGER(IntKi), PARAMETER :: M3N2FBzi = 1721 + INTEGER(IntKi), PARAMETER :: M3N3FBzi = 1722 + INTEGER(IntKi), PARAMETER :: M3N4FBzi = 1723 + INTEGER(IntKi), PARAMETER :: M3N5FBzi = 1724 + INTEGER(IntKi), PARAMETER :: M3N6FBzi = 1725 + INTEGER(IntKi), PARAMETER :: M3N7FBzi = 1726 + INTEGER(IntKi), PARAMETER :: M3N8FBzi = 1727 + INTEGER(IntKi), PARAMETER :: M3N9FBzi = 1728 + INTEGER(IntKi), PARAMETER :: M4N1FBzi = 1729 + INTEGER(IntKi), PARAMETER :: M4N2FBzi = 1730 + INTEGER(IntKi), PARAMETER :: M4N3FBzi = 1731 + INTEGER(IntKi), PARAMETER :: M4N4FBzi = 1732 + INTEGER(IntKi), PARAMETER :: M4N5FBzi = 1733 + INTEGER(IntKi), PARAMETER :: M4N6FBzi = 1734 + INTEGER(IntKi), PARAMETER :: M4N7FBzi = 1735 + INTEGER(IntKi), PARAMETER :: M4N8FBzi = 1736 + INTEGER(IntKi), PARAMETER :: M4N9FBzi = 1737 + INTEGER(IntKi), PARAMETER :: M5N1FBzi = 1738 + INTEGER(IntKi), PARAMETER :: M5N2FBzi = 1739 + INTEGER(IntKi), PARAMETER :: M5N3FBzi = 1740 + INTEGER(IntKi), PARAMETER :: M5N4FBzi = 1741 + INTEGER(IntKi), PARAMETER :: M5N5FBzi = 1742 + INTEGER(IntKi), PARAMETER :: M5N6FBzi = 1743 + INTEGER(IntKi), PARAMETER :: M5N7FBzi = 1744 + INTEGER(IntKi), PARAMETER :: M5N8FBzi = 1745 + INTEGER(IntKi), PARAMETER :: M5N9FBzi = 1746 + INTEGER(IntKi), PARAMETER :: M6N1FBzi = 1747 + INTEGER(IntKi), PARAMETER :: M6N2FBzi = 1748 + INTEGER(IntKi), PARAMETER :: M6N3FBzi = 1749 + INTEGER(IntKi), PARAMETER :: M6N4FBzi = 1750 + INTEGER(IntKi), PARAMETER :: M6N5FBzi = 1751 + INTEGER(IntKi), PARAMETER :: M6N6FBzi = 1752 + INTEGER(IntKi), PARAMETER :: M6N7FBzi = 1753 + INTEGER(IntKi), PARAMETER :: M6N8FBzi = 1754 + INTEGER(IntKi), PARAMETER :: M6N9FBzi = 1755 + INTEGER(IntKi), PARAMETER :: M7N1FBzi = 1756 + INTEGER(IntKi), PARAMETER :: M7N2FBzi = 1757 + INTEGER(IntKi), PARAMETER :: M7N3FBzi = 1758 + INTEGER(IntKi), PARAMETER :: M7N4FBzi = 1759 + INTEGER(IntKi), PARAMETER :: M7N5FBzi = 1760 + INTEGER(IntKi), PARAMETER :: M7N6FBzi = 1761 + INTEGER(IntKi), PARAMETER :: M7N7FBzi = 1762 + INTEGER(IntKi), PARAMETER :: M7N8FBzi = 1763 + INTEGER(IntKi), PARAMETER :: M7N9FBzi = 1764 + INTEGER(IntKi), PARAMETER :: M8N1FBzi = 1765 + INTEGER(IntKi), PARAMETER :: M8N2FBzi = 1766 + INTEGER(IntKi), PARAMETER :: M8N3FBzi = 1767 + INTEGER(IntKi), PARAMETER :: M8N4FBzi = 1768 + INTEGER(IntKi), PARAMETER :: M8N5FBzi = 1769 + INTEGER(IntKi), PARAMETER :: M8N6FBzi = 1770 + INTEGER(IntKi), PARAMETER :: M8N7FBzi = 1771 + INTEGER(IntKi), PARAMETER :: M8N8FBzi = 1772 + INTEGER(IntKi), PARAMETER :: M8N9FBzi = 1773 + INTEGER(IntKi), PARAMETER :: M9N1FBzi = 1774 + INTEGER(IntKi), PARAMETER :: M9N2FBzi = 1775 + INTEGER(IntKi), PARAMETER :: M9N3FBzi = 1776 + INTEGER(IntKi), PARAMETER :: M9N4FBzi = 1777 + INTEGER(IntKi), PARAMETER :: M9N5FBzi = 1778 + INTEGER(IntKi), PARAMETER :: M9N6FBzi = 1779 + INTEGER(IntKi), PARAMETER :: M9N7FBzi = 1780 + INTEGER(IntKi), PARAMETER :: M9N8FBzi = 1781 + INTEGER(IntKi), PARAMETER :: M9N9FBzi = 1782 + INTEGER(IntKi), PARAMETER :: M1N1MBxi = 1783 + INTEGER(IntKi), PARAMETER :: M1N2MBxi = 1784 + INTEGER(IntKi), PARAMETER :: M1N3MBxi = 1785 + INTEGER(IntKi), PARAMETER :: M1N4MBxi = 1786 + INTEGER(IntKi), PARAMETER :: M1N5MBxi = 1787 + INTEGER(IntKi), PARAMETER :: M1N6MBxi = 1788 + INTEGER(IntKi), PARAMETER :: M1N7MBxi = 1789 + INTEGER(IntKi), PARAMETER :: M1N8MBxi = 1790 + INTEGER(IntKi), PARAMETER :: M1N9MBxi = 1791 + INTEGER(IntKi), PARAMETER :: M2N1MBxi = 1792 + INTEGER(IntKi), PARAMETER :: M2N2MBxi = 1793 + INTEGER(IntKi), PARAMETER :: M2N3MBxi = 1794 + INTEGER(IntKi), PARAMETER :: M2N4MBxi = 1795 + INTEGER(IntKi), PARAMETER :: M2N5MBxi = 1796 + INTEGER(IntKi), PARAMETER :: M2N6MBxi = 1797 + INTEGER(IntKi), PARAMETER :: M2N7MBxi = 1798 + INTEGER(IntKi), PARAMETER :: M2N8MBxi = 1799 + INTEGER(IntKi), PARAMETER :: M2N9MBxi = 1800 + INTEGER(IntKi), PARAMETER :: M3N1MBxi = 1801 + INTEGER(IntKi), PARAMETER :: M3N2MBxi = 1802 + INTEGER(IntKi), PARAMETER :: M3N3MBxi = 1803 + INTEGER(IntKi), PARAMETER :: M3N4MBxi = 1804 + INTEGER(IntKi), PARAMETER :: M3N5MBxi = 1805 + INTEGER(IntKi), PARAMETER :: M3N6MBxi = 1806 + INTEGER(IntKi), PARAMETER :: M3N7MBxi = 1807 + INTEGER(IntKi), PARAMETER :: M3N8MBxi = 1808 + INTEGER(IntKi), PARAMETER :: M3N9MBxi = 1809 + INTEGER(IntKi), PARAMETER :: M4N1MBxi = 1810 + INTEGER(IntKi), PARAMETER :: M4N2MBxi = 1811 + INTEGER(IntKi), PARAMETER :: M4N3MBxi = 1812 + INTEGER(IntKi), PARAMETER :: M4N4MBxi = 1813 + INTEGER(IntKi), PARAMETER :: M4N5MBxi = 1814 + INTEGER(IntKi), PARAMETER :: M4N6MBxi = 1815 + INTEGER(IntKi), PARAMETER :: M4N7MBxi = 1816 + INTEGER(IntKi), PARAMETER :: M4N8MBxi = 1817 + INTEGER(IntKi), PARAMETER :: M4N9MBxi = 1818 + INTEGER(IntKi), PARAMETER :: M5N1MBxi = 1819 + INTEGER(IntKi), PARAMETER :: M5N2MBxi = 1820 + INTEGER(IntKi), PARAMETER :: M5N3MBxi = 1821 + INTEGER(IntKi), PARAMETER :: M5N4MBxi = 1822 + INTEGER(IntKi), PARAMETER :: M5N5MBxi = 1823 + INTEGER(IntKi), PARAMETER :: M5N6MBxi = 1824 + INTEGER(IntKi), PARAMETER :: M5N7MBxi = 1825 + INTEGER(IntKi), PARAMETER :: M5N8MBxi = 1826 + INTEGER(IntKi), PARAMETER :: M5N9MBxi = 1827 + INTEGER(IntKi), PARAMETER :: M6N1MBxi = 1828 + INTEGER(IntKi), PARAMETER :: M6N2MBxi = 1829 + INTEGER(IntKi), PARAMETER :: M6N3MBxi = 1830 + INTEGER(IntKi), PARAMETER :: M6N4MBxi = 1831 + INTEGER(IntKi), PARAMETER :: M6N5MBxi = 1832 + INTEGER(IntKi), PARAMETER :: M6N6MBxi = 1833 + INTEGER(IntKi), PARAMETER :: M6N7MBxi = 1834 + INTEGER(IntKi), PARAMETER :: M6N8MBxi = 1835 + INTEGER(IntKi), PARAMETER :: M6N9MBxi = 1836 + INTEGER(IntKi), PARAMETER :: M7N1MBxi = 1837 + INTEGER(IntKi), PARAMETER :: M7N2MBxi = 1838 + INTEGER(IntKi), PARAMETER :: M7N3MBxi = 1839 + INTEGER(IntKi), PARAMETER :: M7N4MBxi = 1840 + INTEGER(IntKi), PARAMETER :: M7N5MBxi = 1841 + INTEGER(IntKi), PARAMETER :: M7N6MBxi = 1842 + INTEGER(IntKi), PARAMETER :: M7N7MBxi = 1843 + INTEGER(IntKi), PARAMETER :: M7N8MBxi = 1844 + INTEGER(IntKi), PARAMETER :: M7N9MBxi = 1845 + INTEGER(IntKi), PARAMETER :: M8N1MBxi = 1846 + INTEGER(IntKi), PARAMETER :: M8N2MBxi = 1847 + INTEGER(IntKi), PARAMETER :: M8N3MBxi = 1848 + INTEGER(IntKi), PARAMETER :: M8N4MBxi = 1849 + INTEGER(IntKi), PARAMETER :: M8N5MBxi = 1850 + INTEGER(IntKi), PARAMETER :: M8N6MBxi = 1851 + INTEGER(IntKi), PARAMETER :: M8N7MBxi = 1852 + INTEGER(IntKi), PARAMETER :: M8N8MBxi = 1853 + INTEGER(IntKi), PARAMETER :: M8N9MBxi = 1854 + INTEGER(IntKi), PARAMETER :: M9N1MBxi = 1855 + INTEGER(IntKi), PARAMETER :: M9N2MBxi = 1856 + INTEGER(IntKi), PARAMETER :: M9N3MBxi = 1857 + INTEGER(IntKi), PARAMETER :: M9N4MBxi = 1858 + INTEGER(IntKi), PARAMETER :: M9N5MBxi = 1859 + INTEGER(IntKi), PARAMETER :: M9N6MBxi = 1860 + INTEGER(IntKi), PARAMETER :: M9N7MBxi = 1861 + INTEGER(IntKi), PARAMETER :: M9N8MBxi = 1862 + INTEGER(IntKi), PARAMETER :: M9N9MBxi = 1863 + INTEGER(IntKi), PARAMETER :: M1N1MByi = 1864 + INTEGER(IntKi), PARAMETER :: M1N2MByi = 1865 + INTEGER(IntKi), PARAMETER :: M1N3MByi = 1866 + INTEGER(IntKi), PARAMETER :: M1N4MByi = 1867 + INTEGER(IntKi), PARAMETER :: M1N5MByi = 1868 + INTEGER(IntKi), PARAMETER :: M1N6MByi = 1869 + INTEGER(IntKi), PARAMETER :: M1N7MByi = 1870 + INTEGER(IntKi), PARAMETER :: M1N8MByi = 1871 + INTEGER(IntKi), PARAMETER :: M1N9MByi = 1872 + INTEGER(IntKi), PARAMETER :: M2N1MByi = 1873 + INTEGER(IntKi), PARAMETER :: M2N2MByi = 1874 + INTEGER(IntKi), PARAMETER :: M2N3MByi = 1875 + INTEGER(IntKi), PARAMETER :: M2N4MByi = 1876 + INTEGER(IntKi), PARAMETER :: M2N5MByi = 1877 + INTEGER(IntKi), PARAMETER :: M2N6MByi = 1878 + INTEGER(IntKi), PARAMETER :: M2N7MByi = 1879 + INTEGER(IntKi), PARAMETER :: M2N8MByi = 1880 + INTEGER(IntKi), PARAMETER :: M2N9MByi = 1881 + INTEGER(IntKi), PARAMETER :: M3N1MByi = 1882 + INTEGER(IntKi), PARAMETER :: M3N2MByi = 1883 + INTEGER(IntKi), PARAMETER :: M3N3MByi = 1884 + INTEGER(IntKi), PARAMETER :: M3N4MByi = 1885 + INTEGER(IntKi), PARAMETER :: M3N5MByi = 1886 + INTEGER(IntKi), PARAMETER :: M3N6MByi = 1887 + INTEGER(IntKi), PARAMETER :: M3N7MByi = 1888 + INTEGER(IntKi), PARAMETER :: M3N8MByi = 1889 + INTEGER(IntKi), PARAMETER :: M3N9MByi = 1890 + INTEGER(IntKi), PARAMETER :: M4N1MByi = 1891 + INTEGER(IntKi), PARAMETER :: M4N2MByi = 1892 + INTEGER(IntKi), PARAMETER :: M4N3MByi = 1893 + INTEGER(IntKi), PARAMETER :: M4N4MByi = 1894 + INTEGER(IntKi), PARAMETER :: M4N5MByi = 1895 + INTEGER(IntKi), PARAMETER :: M4N6MByi = 1896 + INTEGER(IntKi), PARAMETER :: M4N7MByi = 1897 + INTEGER(IntKi), PARAMETER :: M4N8MByi = 1898 + INTEGER(IntKi), PARAMETER :: M4N9MByi = 1899 + INTEGER(IntKi), PARAMETER :: M5N1MByi = 1900 + INTEGER(IntKi), PARAMETER :: M5N2MByi = 1901 + INTEGER(IntKi), PARAMETER :: M5N3MByi = 1902 + INTEGER(IntKi), PARAMETER :: M5N4MByi = 1903 + INTEGER(IntKi), PARAMETER :: M5N5MByi = 1904 + INTEGER(IntKi), PARAMETER :: M5N6MByi = 1905 + INTEGER(IntKi), PARAMETER :: M5N7MByi = 1906 + INTEGER(IntKi), PARAMETER :: M5N8MByi = 1907 + INTEGER(IntKi), PARAMETER :: M5N9MByi = 1908 + INTEGER(IntKi), PARAMETER :: M6N1MByi = 1909 + INTEGER(IntKi), PARAMETER :: M6N2MByi = 1910 + INTEGER(IntKi), PARAMETER :: M6N3MByi = 1911 + INTEGER(IntKi), PARAMETER :: M6N4MByi = 1912 + INTEGER(IntKi), PARAMETER :: M6N5MByi = 1913 + INTEGER(IntKi), PARAMETER :: M6N6MByi = 1914 + INTEGER(IntKi), PARAMETER :: M6N7MByi = 1915 + INTEGER(IntKi), PARAMETER :: M6N8MByi = 1916 + INTEGER(IntKi), PARAMETER :: M6N9MByi = 1917 + INTEGER(IntKi), PARAMETER :: M7N1MByi = 1918 + INTEGER(IntKi), PARAMETER :: M7N2MByi = 1919 + INTEGER(IntKi), PARAMETER :: M7N3MByi = 1920 + INTEGER(IntKi), PARAMETER :: M7N4MByi = 1921 + INTEGER(IntKi), PARAMETER :: M7N5MByi = 1922 + INTEGER(IntKi), PARAMETER :: M7N6MByi = 1923 + INTEGER(IntKi), PARAMETER :: M7N7MByi = 1924 + INTEGER(IntKi), PARAMETER :: M7N8MByi = 1925 + INTEGER(IntKi), PARAMETER :: M7N9MByi = 1926 + INTEGER(IntKi), PARAMETER :: M8N1MByi = 1927 + INTEGER(IntKi), PARAMETER :: M8N2MByi = 1928 + INTEGER(IntKi), PARAMETER :: M8N3MByi = 1929 + INTEGER(IntKi), PARAMETER :: M8N4MByi = 1930 + INTEGER(IntKi), PARAMETER :: M8N5MByi = 1931 + INTEGER(IntKi), PARAMETER :: M8N6MByi = 1932 + INTEGER(IntKi), PARAMETER :: M8N7MByi = 1933 + INTEGER(IntKi), PARAMETER :: M8N8MByi = 1934 + INTEGER(IntKi), PARAMETER :: M8N9MByi = 1935 + INTEGER(IntKi), PARAMETER :: M9N1MByi = 1936 + INTEGER(IntKi), PARAMETER :: M9N2MByi = 1937 + INTEGER(IntKi), PARAMETER :: M9N3MByi = 1938 + INTEGER(IntKi), PARAMETER :: M9N4MByi = 1939 + INTEGER(IntKi), PARAMETER :: M9N5MByi = 1940 + INTEGER(IntKi), PARAMETER :: M9N6MByi = 1941 + INTEGER(IntKi), PARAMETER :: M9N7MByi = 1942 + INTEGER(IntKi), PARAMETER :: M9N8MByi = 1943 + INTEGER(IntKi), PARAMETER :: M9N9MByi = 1944 + INTEGER(IntKi), PARAMETER :: M1N1MBzi = 1945 + INTEGER(IntKi), PARAMETER :: M1N2MBzi = 1946 + INTEGER(IntKi), PARAMETER :: M1N3MBzi = 1947 + INTEGER(IntKi), PARAMETER :: M1N4MBzi = 1948 + INTEGER(IntKi), PARAMETER :: M1N5MBzi = 1949 + INTEGER(IntKi), PARAMETER :: M1N6MBzi = 1950 + INTEGER(IntKi), PARAMETER :: M1N7MBzi = 1951 + INTEGER(IntKi), PARAMETER :: M1N8MBzi = 1952 + INTEGER(IntKi), PARAMETER :: M1N9MBzi = 1953 + INTEGER(IntKi), PARAMETER :: M2N1MBzi = 1954 + INTEGER(IntKi), PARAMETER :: M2N2MBzi = 1955 + INTEGER(IntKi), PARAMETER :: M2N3MBzi = 1956 + INTEGER(IntKi), PARAMETER :: M2N4MBzi = 1957 + INTEGER(IntKi), PARAMETER :: M2N5MBzi = 1958 + INTEGER(IntKi), PARAMETER :: M2N6MBzi = 1959 + INTEGER(IntKi), PARAMETER :: M2N7MBzi = 1960 + INTEGER(IntKi), PARAMETER :: M2N8MBzi = 1961 + INTEGER(IntKi), PARAMETER :: M2N9MBzi = 1962 + INTEGER(IntKi), PARAMETER :: M3N1MBzi = 1963 + INTEGER(IntKi), PARAMETER :: M3N2MBzi = 1964 + INTEGER(IntKi), PARAMETER :: M3N3MBzi = 1965 + INTEGER(IntKi), PARAMETER :: M3N4MBzi = 1966 + INTEGER(IntKi), PARAMETER :: M3N5MBzi = 1967 + INTEGER(IntKi), PARAMETER :: M3N6MBzi = 1968 + INTEGER(IntKi), PARAMETER :: M3N7MBzi = 1969 + INTEGER(IntKi), PARAMETER :: M3N8MBzi = 1970 + INTEGER(IntKi), PARAMETER :: M3N9MBzi = 1971 + INTEGER(IntKi), PARAMETER :: M4N1MBzi = 1972 + INTEGER(IntKi), PARAMETER :: M4N2MBzi = 1973 + INTEGER(IntKi), PARAMETER :: M4N3MBzi = 1974 + INTEGER(IntKi), PARAMETER :: M4N4MBzi = 1975 + INTEGER(IntKi), PARAMETER :: M4N5MBzi = 1976 + INTEGER(IntKi), PARAMETER :: M4N6MBzi = 1977 + INTEGER(IntKi), PARAMETER :: M4N7MBzi = 1978 + INTEGER(IntKi), PARAMETER :: M4N8MBzi = 1979 + INTEGER(IntKi), PARAMETER :: M4N9MBzi = 1980 + INTEGER(IntKi), PARAMETER :: M5N1MBzi = 1981 + INTEGER(IntKi), PARAMETER :: M5N2MBzi = 1982 + INTEGER(IntKi), PARAMETER :: M5N3MBzi = 1983 + INTEGER(IntKi), PARAMETER :: M5N4MBzi = 1984 + INTEGER(IntKi), PARAMETER :: M5N5MBzi = 1985 + INTEGER(IntKi), PARAMETER :: M5N6MBzi = 1986 + INTEGER(IntKi), PARAMETER :: M5N7MBzi = 1987 + INTEGER(IntKi), PARAMETER :: M5N8MBzi = 1988 + INTEGER(IntKi), PARAMETER :: M5N9MBzi = 1989 + INTEGER(IntKi), PARAMETER :: M6N1MBzi = 1990 + INTEGER(IntKi), PARAMETER :: M6N2MBzi = 1991 + INTEGER(IntKi), PARAMETER :: M6N3MBzi = 1992 + INTEGER(IntKi), PARAMETER :: M6N4MBzi = 1993 + INTEGER(IntKi), PARAMETER :: M6N5MBzi = 1994 + INTEGER(IntKi), PARAMETER :: M6N6MBzi = 1995 + INTEGER(IntKi), PARAMETER :: M6N7MBzi = 1996 + INTEGER(IntKi), PARAMETER :: M6N8MBzi = 1997 + INTEGER(IntKi), PARAMETER :: M6N9MBzi = 1998 + INTEGER(IntKi), PARAMETER :: M7N1MBzi = 1999 + INTEGER(IntKi), PARAMETER :: M7N2MBzi = 2000 + INTEGER(IntKi), PARAMETER :: M7N3MBzi = 2001 + INTEGER(IntKi), PARAMETER :: M7N4MBzi = 2002 + INTEGER(IntKi), PARAMETER :: M7N5MBzi = 2003 + INTEGER(IntKi), PARAMETER :: M7N6MBzi = 2004 + INTEGER(IntKi), PARAMETER :: M7N7MBzi = 2005 + INTEGER(IntKi), PARAMETER :: M7N8MBzi = 2006 + INTEGER(IntKi), PARAMETER :: M7N9MBzi = 2007 + INTEGER(IntKi), PARAMETER :: M8N1MBzi = 2008 + INTEGER(IntKi), PARAMETER :: M8N2MBzi = 2009 + INTEGER(IntKi), PARAMETER :: M8N3MBzi = 2010 + INTEGER(IntKi), PARAMETER :: M8N4MBzi = 2011 + INTEGER(IntKi), PARAMETER :: M8N5MBzi = 2012 + INTEGER(IntKi), PARAMETER :: M8N6MBzi = 2013 + INTEGER(IntKi), PARAMETER :: M8N7MBzi = 2014 + INTEGER(IntKi), PARAMETER :: M8N8MBzi = 2015 + INTEGER(IntKi), PARAMETER :: M8N9MBzi = 2016 + INTEGER(IntKi), PARAMETER :: M9N1MBzi = 2017 + INTEGER(IntKi), PARAMETER :: M9N2MBzi = 2018 + INTEGER(IntKi), PARAMETER :: M9N3MBzi = 2019 + INTEGER(IntKi), PARAMETER :: M9N4MBzi = 2020 + INTEGER(IntKi), PARAMETER :: M9N5MBzi = 2021 + INTEGER(IntKi), PARAMETER :: M9N6MBzi = 2022 + INTEGER(IntKi), PARAMETER :: M9N7MBzi = 2023 + INTEGER(IntKi), PARAMETER :: M9N8MBzi = 2024 + INTEGER(IntKi), PARAMETER :: M9N9MBzi = 2025 + INTEGER(IntKi), PARAMETER :: M1N1FBFxi = 2026 + INTEGER(IntKi), PARAMETER :: M1N2FBFxi = 2027 + INTEGER(IntKi), PARAMETER :: M1N3FBFxi = 2028 + INTEGER(IntKi), PARAMETER :: M1N4FBFxi = 2029 + INTEGER(IntKi), PARAMETER :: M1N5FBFxi = 2030 + INTEGER(IntKi), PARAMETER :: M1N6FBFxi = 2031 + INTEGER(IntKi), PARAMETER :: M1N7FBFxi = 2032 + INTEGER(IntKi), PARAMETER :: M1N8FBFxi = 2033 + INTEGER(IntKi), PARAMETER :: M1N9FBFxi = 2034 + INTEGER(IntKi), PARAMETER :: M2N1FBFxi = 2035 + INTEGER(IntKi), PARAMETER :: M2N2FBFxi = 2036 + INTEGER(IntKi), PARAMETER :: M2N3FBFxi = 2037 + INTEGER(IntKi), PARAMETER :: M2N4FBFxi = 2038 + INTEGER(IntKi), PARAMETER :: M2N5FBFxi = 2039 + INTEGER(IntKi), PARAMETER :: M2N6FBFxi = 2040 + INTEGER(IntKi), PARAMETER :: M2N7FBFxi = 2041 + INTEGER(IntKi), PARAMETER :: M2N8FBFxi = 2042 + INTEGER(IntKi), PARAMETER :: M2N9FBFxi = 2043 + INTEGER(IntKi), PARAMETER :: M3N1FBFxi = 2044 + INTEGER(IntKi), PARAMETER :: M3N2FBFxi = 2045 + INTEGER(IntKi), PARAMETER :: M3N3FBFxi = 2046 + INTEGER(IntKi), PARAMETER :: M3N4FBFxi = 2047 + INTEGER(IntKi), PARAMETER :: M3N5FBFxi = 2048 + INTEGER(IntKi), PARAMETER :: M3N6FBFxi = 2049 + INTEGER(IntKi), PARAMETER :: M3N7FBFxi = 2050 + INTEGER(IntKi), PARAMETER :: M3N8FBFxi = 2051 + INTEGER(IntKi), PARAMETER :: M3N9FBFxi = 2052 + INTEGER(IntKi), PARAMETER :: M4N1FBFxi = 2053 + INTEGER(IntKi), PARAMETER :: M4N2FBFxi = 2054 + INTEGER(IntKi), PARAMETER :: M4N3FBFxi = 2055 + INTEGER(IntKi), PARAMETER :: M4N4FBFxi = 2056 + INTEGER(IntKi), PARAMETER :: M4N5FBFxi = 2057 + INTEGER(IntKi), PARAMETER :: M4N6FBFxi = 2058 + INTEGER(IntKi), PARAMETER :: M4N7FBFxi = 2059 + INTEGER(IntKi), PARAMETER :: M4N8FBFxi = 2060 + INTEGER(IntKi), PARAMETER :: M4N9FBFxi = 2061 + INTEGER(IntKi), PARAMETER :: M5N1FBFxi = 2062 + INTEGER(IntKi), PARAMETER :: M5N2FBFxi = 2063 + INTEGER(IntKi), PARAMETER :: M5N3FBFxi = 2064 + INTEGER(IntKi), PARAMETER :: M5N4FBFxi = 2065 + INTEGER(IntKi), PARAMETER :: M5N5FBFxi = 2066 + INTEGER(IntKi), PARAMETER :: M5N6FBFxi = 2067 + INTEGER(IntKi), PARAMETER :: M5N7FBFxi = 2068 + INTEGER(IntKi), PARAMETER :: M5N8FBFxi = 2069 + INTEGER(IntKi), PARAMETER :: M5N9FBFxi = 2070 + INTEGER(IntKi), PARAMETER :: M6N1FBFxi = 2071 + INTEGER(IntKi), PARAMETER :: M6N2FBFxi = 2072 + INTEGER(IntKi), PARAMETER :: M6N3FBFxi = 2073 + INTEGER(IntKi), PARAMETER :: M6N4FBFxi = 2074 + INTEGER(IntKi), PARAMETER :: M6N5FBFxi = 2075 + INTEGER(IntKi), PARAMETER :: M6N6FBFxi = 2076 + INTEGER(IntKi), PARAMETER :: M6N7FBFxi = 2077 + INTEGER(IntKi), PARAMETER :: M6N8FBFxi = 2078 + INTEGER(IntKi), PARAMETER :: M6N9FBFxi = 2079 + INTEGER(IntKi), PARAMETER :: M7N1FBFxi = 2080 + INTEGER(IntKi), PARAMETER :: M7N2FBFxi = 2081 + INTEGER(IntKi), PARAMETER :: M7N3FBFxi = 2082 + INTEGER(IntKi), PARAMETER :: M7N4FBFxi = 2083 + INTEGER(IntKi), PARAMETER :: M7N5FBFxi = 2084 + INTEGER(IntKi), PARAMETER :: M7N6FBFxi = 2085 + INTEGER(IntKi), PARAMETER :: M7N7FBFxi = 2086 + INTEGER(IntKi), PARAMETER :: M7N8FBFxi = 2087 + INTEGER(IntKi), PARAMETER :: M7N9FBFxi = 2088 + INTEGER(IntKi), PARAMETER :: M8N1FBFxi = 2089 + INTEGER(IntKi), PARAMETER :: M8N2FBFxi = 2090 + INTEGER(IntKi), PARAMETER :: M8N3FBFxi = 2091 + INTEGER(IntKi), PARAMETER :: M8N4FBFxi = 2092 + INTEGER(IntKi), PARAMETER :: M8N5FBFxi = 2093 + INTEGER(IntKi), PARAMETER :: M8N6FBFxi = 2094 + INTEGER(IntKi), PARAMETER :: M8N7FBFxi = 2095 + INTEGER(IntKi), PARAMETER :: M8N8FBFxi = 2096 + INTEGER(IntKi), PARAMETER :: M8N9FBFxi = 2097 + INTEGER(IntKi), PARAMETER :: M9N1FBFxi = 2098 + INTEGER(IntKi), PARAMETER :: M9N2FBFxi = 2099 + INTEGER(IntKi), PARAMETER :: M9N3FBFxi = 2100 + INTEGER(IntKi), PARAMETER :: M9N4FBFxi = 2101 + INTEGER(IntKi), PARAMETER :: M9N5FBFxi = 2102 + INTEGER(IntKi), PARAMETER :: M9N6FBFxi = 2103 + INTEGER(IntKi), PARAMETER :: M9N7FBFxi = 2104 + INTEGER(IntKi), PARAMETER :: M9N8FBFxi = 2105 + INTEGER(IntKi), PARAMETER :: M9N9FBFxi = 2106 + INTEGER(IntKi), PARAMETER :: M1N1FBFyi = 2107 + INTEGER(IntKi), PARAMETER :: M1N2FBFyi = 2108 + INTEGER(IntKi), PARAMETER :: M1N3FBFyi = 2109 + INTEGER(IntKi), PARAMETER :: M1N4FBFyi = 2110 + INTEGER(IntKi), PARAMETER :: M1N5FBFyi = 2111 + INTEGER(IntKi), PARAMETER :: M1N6FBFyi = 2112 + INTEGER(IntKi), PARAMETER :: M1N7FBFyi = 2113 + INTEGER(IntKi), PARAMETER :: M1N8FBFyi = 2114 + INTEGER(IntKi), PARAMETER :: M1N9FBFyi = 2115 + INTEGER(IntKi), PARAMETER :: M2N1FBFyi = 2116 + INTEGER(IntKi), PARAMETER :: M2N2FBFyi = 2117 + INTEGER(IntKi), PARAMETER :: M2N3FBFyi = 2118 + INTEGER(IntKi), PARAMETER :: M2N4FBFyi = 2119 + INTEGER(IntKi), PARAMETER :: M2N5FBFyi = 2120 + INTEGER(IntKi), PARAMETER :: M2N6FBFyi = 2121 + INTEGER(IntKi), PARAMETER :: M2N7FBFyi = 2122 + INTEGER(IntKi), PARAMETER :: M2N8FBFyi = 2123 + INTEGER(IntKi), PARAMETER :: M2N9FBFyi = 2124 + INTEGER(IntKi), PARAMETER :: M3N1FBFyi = 2125 + INTEGER(IntKi), PARAMETER :: M3N2FBFyi = 2126 + INTEGER(IntKi), PARAMETER :: M3N3FBFyi = 2127 + INTEGER(IntKi), PARAMETER :: M3N4FBFyi = 2128 + INTEGER(IntKi), PARAMETER :: M3N5FBFyi = 2129 + INTEGER(IntKi), PARAMETER :: M3N6FBFyi = 2130 + INTEGER(IntKi), PARAMETER :: M3N7FBFyi = 2131 + INTEGER(IntKi), PARAMETER :: M3N8FBFyi = 2132 + INTEGER(IntKi), PARAMETER :: M3N9FBFyi = 2133 + INTEGER(IntKi), PARAMETER :: M4N1FBFyi = 2134 + INTEGER(IntKi), PARAMETER :: M4N2FBFyi = 2135 + INTEGER(IntKi), PARAMETER :: M4N3FBFyi = 2136 + INTEGER(IntKi), PARAMETER :: M4N4FBFyi = 2137 + INTEGER(IntKi), PARAMETER :: M4N5FBFyi = 2138 + INTEGER(IntKi), PARAMETER :: M4N6FBFyi = 2139 + INTEGER(IntKi), PARAMETER :: M4N7FBFyi = 2140 + INTEGER(IntKi), PARAMETER :: M4N8FBFyi = 2141 + INTEGER(IntKi), PARAMETER :: M4N9FBFyi = 2142 + INTEGER(IntKi), PARAMETER :: M5N1FBFyi = 2143 + INTEGER(IntKi), PARAMETER :: M5N2FBFyi = 2144 + INTEGER(IntKi), PARAMETER :: M5N3FBFyi = 2145 + INTEGER(IntKi), PARAMETER :: M5N4FBFyi = 2146 + INTEGER(IntKi), PARAMETER :: M5N5FBFyi = 2147 + INTEGER(IntKi), PARAMETER :: M5N6FBFyi = 2148 + INTEGER(IntKi), PARAMETER :: M5N7FBFyi = 2149 + INTEGER(IntKi), PARAMETER :: M5N8FBFyi = 2150 + INTEGER(IntKi), PARAMETER :: M5N9FBFyi = 2151 + INTEGER(IntKi), PARAMETER :: M6N1FBFyi = 2152 + INTEGER(IntKi), PARAMETER :: M6N2FBFyi = 2153 + INTEGER(IntKi), PARAMETER :: M6N3FBFyi = 2154 + INTEGER(IntKi), PARAMETER :: M6N4FBFyi = 2155 + INTEGER(IntKi), PARAMETER :: M6N5FBFyi = 2156 + INTEGER(IntKi), PARAMETER :: M6N6FBFyi = 2157 + INTEGER(IntKi), PARAMETER :: M6N7FBFyi = 2158 + INTEGER(IntKi), PARAMETER :: M6N8FBFyi = 2159 + INTEGER(IntKi), PARAMETER :: M6N9FBFyi = 2160 + INTEGER(IntKi), PARAMETER :: M7N1FBFyi = 2161 + INTEGER(IntKi), PARAMETER :: M7N2FBFyi = 2162 + INTEGER(IntKi), PARAMETER :: M7N3FBFyi = 2163 + INTEGER(IntKi), PARAMETER :: M7N4FBFyi = 2164 + INTEGER(IntKi), PARAMETER :: M7N5FBFyi = 2165 + INTEGER(IntKi), PARAMETER :: M7N6FBFyi = 2166 + INTEGER(IntKi), PARAMETER :: M7N7FBFyi = 2167 + INTEGER(IntKi), PARAMETER :: M7N8FBFyi = 2168 + INTEGER(IntKi), PARAMETER :: M7N9FBFyi = 2169 + INTEGER(IntKi), PARAMETER :: M8N1FBFyi = 2170 + INTEGER(IntKi), PARAMETER :: M8N2FBFyi = 2171 + INTEGER(IntKi), PARAMETER :: M8N3FBFyi = 2172 + INTEGER(IntKi), PARAMETER :: M8N4FBFyi = 2173 + INTEGER(IntKi), PARAMETER :: M8N5FBFyi = 2174 + INTEGER(IntKi), PARAMETER :: M8N6FBFyi = 2175 + INTEGER(IntKi), PARAMETER :: M8N7FBFyi = 2176 + INTEGER(IntKi), PARAMETER :: M8N8FBFyi = 2177 + INTEGER(IntKi), PARAMETER :: M8N9FBFyi = 2178 + INTEGER(IntKi), PARAMETER :: M9N1FBFyi = 2179 + INTEGER(IntKi), PARAMETER :: M9N2FBFyi = 2180 + INTEGER(IntKi), PARAMETER :: M9N3FBFyi = 2181 + INTEGER(IntKi), PARAMETER :: M9N4FBFyi = 2182 + INTEGER(IntKi), PARAMETER :: M9N5FBFyi = 2183 + INTEGER(IntKi), PARAMETER :: M9N6FBFyi = 2184 + INTEGER(IntKi), PARAMETER :: M9N7FBFyi = 2185 + INTEGER(IntKi), PARAMETER :: M9N8FBFyi = 2186 + INTEGER(IntKi), PARAMETER :: M9N9FBFyi = 2187 + INTEGER(IntKi), PARAMETER :: M1N1FBFzi = 2188 + INTEGER(IntKi), PARAMETER :: M1N2FBFzi = 2189 + INTEGER(IntKi), PARAMETER :: M1N3FBFzi = 2190 + INTEGER(IntKi), PARAMETER :: M1N4FBFzi = 2191 + INTEGER(IntKi), PARAMETER :: M1N5FBFzi = 2192 + INTEGER(IntKi), PARAMETER :: M1N6FBFzi = 2193 + INTEGER(IntKi), PARAMETER :: M1N7FBFzi = 2194 + INTEGER(IntKi), PARAMETER :: M1N8FBFzi = 2195 + INTEGER(IntKi), PARAMETER :: M1N9FBFzi = 2196 + INTEGER(IntKi), PARAMETER :: M2N1FBFzi = 2197 + INTEGER(IntKi), PARAMETER :: M2N2FBFzi = 2198 + INTEGER(IntKi), PARAMETER :: M2N3FBFzi = 2199 + INTEGER(IntKi), PARAMETER :: M2N4FBFzi = 2200 + INTEGER(IntKi), PARAMETER :: M2N5FBFzi = 2201 + INTEGER(IntKi), PARAMETER :: M2N6FBFzi = 2202 + INTEGER(IntKi), PARAMETER :: M2N7FBFzi = 2203 + INTEGER(IntKi), PARAMETER :: M2N8FBFzi = 2204 + INTEGER(IntKi), PARAMETER :: M2N9FBFzi = 2205 + INTEGER(IntKi), PARAMETER :: M3N1FBFzi = 2206 + INTEGER(IntKi), PARAMETER :: M3N2FBFzi = 2207 + INTEGER(IntKi), PARAMETER :: M3N3FBFzi = 2208 + INTEGER(IntKi), PARAMETER :: M3N4FBFzi = 2209 + INTEGER(IntKi), PARAMETER :: M3N5FBFzi = 2210 + INTEGER(IntKi), PARAMETER :: M3N6FBFzi = 2211 + INTEGER(IntKi), PARAMETER :: M3N7FBFzi = 2212 + INTEGER(IntKi), PARAMETER :: M3N8FBFzi = 2213 + INTEGER(IntKi), PARAMETER :: M3N9FBFzi = 2214 + INTEGER(IntKi), PARAMETER :: M4N1FBFzi = 2215 + INTEGER(IntKi), PARAMETER :: M4N2FBFzi = 2216 + INTEGER(IntKi), PARAMETER :: M4N3FBFzi = 2217 + INTEGER(IntKi), PARAMETER :: M4N4FBFzi = 2218 + INTEGER(IntKi), PARAMETER :: M4N5FBFzi = 2219 + INTEGER(IntKi), PARAMETER :: M4N6FBFzi = 2220 + INTEGER(IntKi), PARAMETER :: M4N7FBFzi = 2221 + INTEGER(IntKi), PARAMETER :: M4N8FBFzi = 2222 + INTEGER(IntKi), PARAMETER :: M4N9FBFzi = 2223 + INTEGER(IntKi), PARAMETER :: M5N1FBFzi = 2224 + INTEGER(IntKi), PARAMETER :: M5N2FBFzi = 2225 + INTEGER(IntKi), PARAMETER :: M5N3FBFzi = 2226 + INTEGER(IntKi), PARAMETER :: M5N4FBFzi = 2227 + INTEGER(IntKi), PARAMETER :: M5N5FBFzi = 2228 + INTEGER(IntKi), PARAMETER :: M5N6FBFzi = 2229 + INTEGER(IntKi), PARAMETER :: M5N7FBFzi = 2230 + INTEGER(IntKi), PARAMETER :: M5N8FBFzi = 2231 + INTEGER(IntKi), PARAMETER :: M5N9FBFzi = 2232 + INTEGER(IntKi), PARAMETER :: M6N1FBFzi = 2233 + INTEGER(IntKi), PARAMETER :: M6N2FBFzi = 2234 + INTEGER(IntKi), PARAMETER :: M6N3FBFzi = 2235 + INTEGER(IntKi), PARAMETER :: M6N4FBFzi = 2236 + INTEGER(IntKi), PARAMETER :: M6N5FBFzi = 2237 + INTEGER(IntKi), PARAMETER :: M6N6FBFzi = 2238 + INTEGER(IntKi), PARAMETER :: M6N7FBFzi = 2239 + INTEGER(IntKi), PARAMETER :: M6N8FBFzi = 2240 + INTEGER(IntKi), PARAMETER :: M6N9FBFzi = 2241 + INTEGER(IntKi), PARAMETER :: M7N1FBFzi = 2242 + INTEGER(IntKi), PARAMETER :: M7N2FBFzi = 2243 + INTEGER(IntKi), PARAMETER :: M7N3FBFzi = 2244 + INTEGER(IntKi), PARAMETER :: M7N4FBFzi = 2245 + INTEGER(IntKi), PARAMETER :: M7N5FBFzi = 2246 + INTEGER(IntKi), PARAMETER :: M7N6FBFzi = 2247 + INTEGER(IntKi), PARAMETER :: M7N7FBFzi = 2248 + INTEGER(IntKi), PARAMETER :: M7N8FBFzi = 2249 + INTEGER(IntKi), PARAMETER :: M7N9FBFzi = 2250 + INTEGER(IntKi), PARAMETER :: M8N1FBFzi = 2251 + INTEGER(IntKi), PARAMETER :: M8N2FBFzi = 2252 + INTEGER(IntKi), PARAMETER :: M8N3FBFzi = 2253 + INTEGER(IntKi), PARAMETER :: M8N4FBFzi = 2254 + INTEGER(IntKi), PARAMETER :: M8N5FBFzi = 2255 + INTEGER(IntKi), PARAMETER :: M8N6FBFzi = 2256 + INTEGER(IntKi), PARAMETER :: M8N7FBFzi = 2257 + INTEGER(IntKi), PARAMETER :: M8N8FBFzi = 2258 + INTEGER(IntKi), PARAMETER :: M8N9FBFzi = 2259 + INTEGER(IntKi), PARAMETER :: M9N1FBFzi = 2260 + INTEGER(IntKi), PARAMETER :: M9N2FBFzi = 2261 + INTEGER(IntKi), PARAMETER :: M9N3FBFzi = 2262 + INTEGER(IntKi), PARAMETER :: M9N4FBFzi = 2263 + INTEGER(IntKi), PARAMETER :: M9N5FBFzi = 2264 + INTEGER(IntKi), PARAMETER :: M9N6FBFzi = 2265 + INTEGER(IntKi), PARAMETER :: M9N7FBFzi = 2266 + INTEGER(IntKi), PARAMETER :: M9N8FBFzi = 2267 + INTEGER(IntKi), PARAMETER :: M9N9FBFzi = 2268 + INTEGER(IntKi), PARAMETER :: M1N1MBFxi = 2269 + INTEGER(IntKi), PARAMETER :: M1N2MBFxi = 2270 + INTEGER(IntKi), PARAMETER :: M1N3MBFxi = 2271 + INTEGER(IntKi), PARAMETER :: M1N4MBFxi = 2272 + INTEGER(IntKi), PARAMETER :: M1N5MBFxi = 2273 + INTEGER(IntKi), PARAMETER :: M1N6MBFxi = 2274 + INTEGER(IntKi), PARAMETER :: M1N7MBFxi = 2275 + INTEGER(IntKi), PARAMETER :: M1N8MBFxi = 2276 + INTEGER(IntKi), PARAMETER :: M1N9MBFxi = 2277 + INTEGER(IntKi), PARAMETER :: M2N1MBFxi = 2278 + INTEGER(IntKi), PARAMETER :: M2N2MBFxi = 2279 + INTEGER(IntKi), PARAMETER :: M2N3MBFxi = 2280 + INTEGER(IntKi), PARAMETER :: M2N4MBFxi = 2281 + INTEGER(IntKi), PARAMETER :: M2N5MBFxi = 2282 + INTEGER(IntKi), PARAMETER :: M2N6MBFxi = 2283 + INTEGER(IntKi), PARAMETER :: M2N7MBFxi = 2284 + INTEGER(IntKi), PARAMETER :: M2N8MBFxi = 2285 + INTEGER(IntKi), PARAMETER :: M2N9MBFxi = 2286 + INTEGER(IntKi), PARAMETER :: M3N1MBFxi = 2287 + INTEGER(IntKi), PARAMETER :: M3N2MBFxi = 2288 + INTEGER(IntKi), PARAMETER :: M3N3MBFxi = 2289 + INTEGER(IntKi), PARAMETER :: M3N4MBFxi = 2290 + INTEGER(IntKi), PARAMETER :: M3N5MBFxi = 2291 + INTEGER(IntKi), PARAMETER :: M3N6MBFxi = 2292 + INTEGER(IntKi), PARAMETER :: M3N7MBFxi = 2293 + INTEGER(IntKi), PARAMETER :: M3N8MBFxi = 2294 + INTEGER(IntKi), PARAMETER :: M3N9MBFxi = 2295 + INTEGER(IntKi), PARAMETER :: M4N1MBFxi = 2296 + INTEGER(IntKi), PARAMETER :: M4N2MBFxi = 2297 + INTEGER(IntKi), PARAMETER :: M4N3MBFxi = 2298 + INTEGER(IntKi), PARAMETER :: M4N4MBFxi = 2299 + INTEGER(IntKi), PARAMETER :: M4N5MBFxi = 2300 + INTEGER(IntKi), PARAMETER :: M4N6MBFxi = 2301 + INTEGER(IntKi), PARAMETER :: M4N7MBFxi = 2302 + INTEGER(IntKi), PARAMETER :: M4N8MBFxi = 2303 + INTEGER(IntKi), PARAMETER :: M4N9MBFxi = 2304 + INTEGER(IntKi), PARAMETER :: M5N1MBFxi = 2305 + INTEGER(IntKi), PARAMETER :: M5N2MBFxi = 2306 + INTEGER(IntKi), PARAMETER :: M5N3MBFxi = 2307 + INTEGER(IntKi), PARAMETER :: M5N4MBFxi = 2308 + INTEGER(IntKi), PARAMETER :: M5N5MBFxi = 2309 + INTEGER(IntKi), PARAMETER :: M5N6MBFxi = 2310 + INTEGER(IntKi), PARAMETER :: M5N7MBFxi = 2311 + INTEGER(IntKi), PARAMETER :: M5N8MBFxi = 2312 + INTEGER(IntKi), PARAMETER :: M5N9MBFxi = 2313 + INTEGER(IntKi), PARAMETER :: M6N1MBFxi = 2314 + INTEGER(IntKi), PARAMETER :: M6N2MBFxi = 2315 + INTEGER(IntKi), PARAMETER :: M6N3MBFxi = 2316 + INTEGER(IntKi), PARAMETER :: M6N4MBFxi = 2317 + INTEGER(IntKi), PARAMETER :: M6N5MBFxi = 2318 + INTEGER(IntKi), PARAMETER :: M6N6MBFxi = 2319 + INTEGER(IntKi), PARAMETER :: M6N7MBFxi = 2320 + INTEGER(IntKi), PARAMETER :: M6N8MBFxi = 2321 + INTEGER(IntKi), PARAMETER :: M6N9MBFxi = 2322 + INTEGER(IntKi), PARAMETER :: M7N1MBFxi = 2323 + INTEGER(IntKi), PARAMETER :: M7N2MBFxi = 2324 + INTEGER(IntKi), PARAMETER :: M7N3MBFxi = 2325 + INTEGER(IntKi), PARAMETER :: M7N4MBFxi = 2326 + INTEGER(IntKi), PARAMETER :: M7N5MBFxi = 2327 + INTEGER(IntKi), PARAMETER :: M7N6MBFxi = 2328 + INTEGER(IntKi), PARAMETER :: M7N7MBFxi = 2329 + INTEGER(IntKi), PARAMETER :: M7N8MBFxi = 2330 + INTEGER(IntKi), PARAMETER :: M7N9MBFxi = 2331 + INTEGER(IntKi), PARAMETER :: M8N1MBFxi = 2332 + INTEGER(IntKi), PARAMETER :: M8N2MBFxi = 2333 + INTEGER(IntKi), PARAMETER :: M8N3MBFxi = 2334 + INTEGER(IntKi), PARAMETER :: M8N4MBFxi = 2335 + INTEGER(IntKi), PARAMETER :: M8N5MBFxi = 2336 + INTEGER(IntKi), PARAMETER :: M8N6MBFxi = 2337 + INTEGER(IntKi), PARAMETER :: M8N7MBFxi = 2338 + INTEGER(IntKi), PARAMETER :: M8N8MBFxi = 2339 + INTEGER(IntKi), PARAMETER :: M8N9MBFxi = 2340 + INTEGER(IntKi), PARAMETER :: M9N1MBFxi = 2341 + INTEGER(IntKi), PARAMETER :: M9N2MBFxi = 2342 + INTEGER(IntKi), PARAMETER :: M9N3MBFxi = 2343 + INTEGER(IntKi), PARAMETER :: M9N4MBFxi = 2344 + INTEGER(IntKi), PARAMETER :: M9N5MBFxi = 2345 + INTEGER(IntKi), PARAMETER :: M9N6MBFxi = 2346 + INTEGER(IntKi), PARAMETER :: M9N7MBFxi = 2347 + INTEGER(IntKi), PARAMETER :: M9N8MBFxi = 2348 + INTEGER(IntKi), PARAMETER :: M9N9MBFxi = 2349 + INTEGER(IntKi), PARAMETER :: M1N1MBFyi = 2350 + INTEGER(IntKi), PARAMETER :: M1N2MBFyi = 2351 + INTEGER(IntKi), PARAMETER :: M1N3MBFyi = 2352 + INTEGER(IntKi), PARAMETER :: M1N4MBFyi = 2353 + INTEGER(IntKi), PARAMETER :: M1N5MBFyi = 2354 + INTEGER(IntKi), PARAMETER :: M1N6MBFyi = 2355 + INTEGER(IntKi), PARAMETER :: M1N7MBFyi = 2356 + INTEGER(IntKi), PARAMETER :: M1N8MBFyi = 2357 + INTEGER(IntKi), PARAMETER :: M1N9MBFyi = 2358 + INTEGER(IntKi), PARAMETER :: M2N1MBFyi = 2359 + INTEGER(IntKi), PARAMETER :: M2N2MBFyi = 2360 + INTEGER(IntKi), PARAMETER :: M2N3MBFyi = 2361 + INTEGER(IntKi), PARAMETER :: M2N4MBFyi = 2362 + INTEGER(IntKi), PARAMETER :: M2N5MBFyi = 2363 + INTEGER(IntKi), PARAMETER :: M2N6MBFyi = 2364 + INTEGER(IntKi), PARAMETER :: M2N7MBFyi = 2365 + INTEGER(IntKi), PARAMETER :: M2N8MBFyi = 2366 + INTEGER(IntKi), PARAMETER :: M2N9MBFyi = 2367 + INTEGER(IntKi), PARAMETER :: M3N1MBFyi = 2368 + INTEGER(IntKi), PARAMETER :: M3N2MBFyi = 2369 + INTEGER(IntKi), PARAMETER :: M3N3MBFyi = 2370 + INTEGER(IntKi), PARAMETER :: M3N4MBFyi = 2371 + INTEGER(IntKi), PARAMETER :: M3N5MBFyi = 2372 + INTEGER(IntKi), PARAMETER :: M3N6MBFyi = 2373 + INTEGER(IntKi), PARAMETER :: M3N7MBFyi = 2374 + INTEGER(IntKi), PARAMETER :: M3N8MBFyi = 2375 + INTEGER(IntKi), PARAMETER :: M3N9MBFyi = 2376 + INTEGER(IntKi), PARAMETER :: M4N1MBFyi = 2377 + INTEGER(IntKi), PARAMETER :: M4N2MBFyi = 2378 + INTEGER(IntKi), PARAMETER :: M4N3MBFyi = 2379 + INTEGER(IntKi), PARAMETER :: M4N4MBFyi = 2380 + INTEGER(IntKi), PARAMETER :: M4N5MBFyi = 2381 + INTEGER(IntKi), PARAMETER :: M4N6MBFyi = 2382 + INTEGER(IntKi), PARAMETER :: M4N7MBFyi = 2383 + INTEGER(IntKi), PARAMETER :: M4N8MBFyi = 2384 + INTEGER(IntKi), PARAMETER :: M4N9MBFyi = 2385 + INTEGER(IntKi), PARAMETER :: M5N1MBFyi = 2386 + INTEGER(IntKi), PARAMETER :: M5N2MBFyi = 2387 + INTEGER(IntKi), PARAMETER :: M5N3MBFyi = 2388 + INTEGER(IntKi), PARAMETER :: M5N4MBFyi = 2389 + INTEGER(IntKi), PARAMETER :: M5N5MBFyi = 2390 + INTEGER(IntKi), PARAMETER :: M5N6MBFyi = 2391 + INTEGER(IntKi), PARAMETER :: M5N7MBFyi = 2392 + INTEGER(IntKi), PARAMETER :: M5N8MBFyi = 2393 + INTEGER(IntKi), PARAMETER :: M5N9MBFyi = 2394 + INTEGER(IntKi), PARAMETER :: M6N1MBFyi = 2395 + INTEGER(IntKi), PARAMETER :: M6N2MBFyi = 2396 + INTEGER(IntKi), PARAMETER :: M6N3MBFyi = 2397 + INTEGER(IntKi), PARAMETER :: M6N4MBFyi = 2398 + INTEGER(IntKi), PARAMETER :: M6N5MBFyi = 2399 + INTEGER(IntKi), PARAMETER :: M6N6MBFyi = 2400 + INTEGER(IntKi), PARAMETER :: M6N7MBFyi = 2401 + INTEGER(IntKi), PARAMETER :: M6N8MBFyi = 2402 + INTEGER(IntKi), PARAMETER :: M6N9MBFyi = 2403 + INTEGER(IntKi), PARAMETER :: M7N1MBFyi = 2404 + INTEGER(IntKi), PARAMETER :: M7N2MBFyi = 2405 + INTEGER(IntKi), PARAMETER :: M7N3MBFyi = 2406 + INTEGER(IntKi), PARAMETER :: M7N4MBFyi = 2407 + INTEGER(IntKi), PARAMETER :: M7N5MBFyi = 2408 + INTEGER(IntKi), PARAMETER :: M7N6MBFyi = 2409 + INTEGER(IntKi), PARAMETER :: M7N7MBFyi = 2410 + INTEGER(IntKi), PARAMETER :: M7N8MBFyi = 2411 + INTEGER(IntKi), PARAMETER :: M7N9MBFyi = 2412 + INTEGER(IntKi), PARAMETER :: M8N1MBFyi = 2413 + INTEGER(IntKi), PARAMETER :: M8N2MBFyi = 2414 + INTEGER(IntKi), PARAMETER :: M8N3MBFyi = 2415 + INTEGER(IntKi), PARAMETER :: M8N4MBFyi = 2416 + INTEGER(IntKi), PARAMETER :: M8N5MBFyi = 2417 + INTEGER(IntKi), PARAMETER :: M8N6MBFyi = 2418 + INTEGER(IntKi), PARAMETER :: M8N7MBFyi = 2419 + INTEGER(IntKi), PARAMETER :: M8N8MBFyi = 2420 + INTEGER(IntKi), PARAMETER :: M8N9MBFyi = 2421 + INTEGER(IntKi), PARAMETER :: M9N1MBFyi = 2422 + INTEGER(IntKi), PARAMETER :: M9N2MBFyi = 2423 + INTEGER(IntKi), PARAMETER :: M9N3MBFyi = 2424 + INTEGER(IntKi), PARAMETER :: M9N4MBFyi = 2425 + INTEGER(IntKi), PARAMETER :: M9N5MBFyi = 2426 + INTEGER(IntKi), PARAMETER :: M9N6MBFyi = 2427 + INTEGER(IntKi), PARAMETER :: M9N7MBFyi = 2428 + INTEGER(IntKi), PARAMETER :: M9N8MBFyi = 2429 + INTEGER(IntKi), PARAMETER :: M9N9MBFyi = 2430 + INTEGER(IntKi), PARAMETER :: M1N1MBFzi = 2431 + INTEGER(IntKi), PARAMETER :: M1N2MBFzi = 2432 + INTEGER(IntKi), PARAMETER :: M1N3MBFzi = 2433 + INTEGER(IntKi), PARAMETER :: M1N4MBFzi = 2434 + INTEGER(IntKi), PARAMETER :: M1N5MBFzi = 2435 + INTEGER(IntKi), PARAMETER :: M1N6MBFzi = 2436 + INTEGER(IntKi), PARAMETER :: M1N7MBFzi = 2437 + INTEGER(IntKi), PARAMETER :: M1N8MBFzi = 2438 + INTEGER(IntKi), PARAMETER :: M1N9MBFzi = 2439 + INTEGER(IntKi), PARAMETER :: M2N1MBFzi = 2440 + INTEGER(IntKi), PARAMETER :: M2N2MBFzi = 2441 + INTEGER(IntKi), PARAMETER :: M2N3MBFzi = 2442 + INTEGER(IntKi), PARAMETER :: M2N4MBFzi = 2443 + INTEGER(IntKi), PARAMETER :: M2N5MBFzi = 2444 + INTEGER(IntKi), PARAMETER :: M2N6MBFzi = 2445 + INTEGER(IntKi), PARAMETER :: M2N7MBFzi = 2446 + INTEGER(IntKi), PARAMETER :: M2N8MBFzi = 2447 + INTEGER(IntKi), PARAMETER :: M2N9MBFzi = 2448 + INTEGER(IntKi), PARAMETER :: M3N1MBFzi = 2449 + INTEGER(IntKi), PARAMETER :: M3N2MBFzi = 2450 + INTEGER(IntKi), PARAMETER :: M3N3MBFzi = 2451 + INTEGER(IntKi), PARAMETER :: M3N4MBFzi = 2452 + INTEGER(IntKi), PARAMETER :: M3N5MBFzi = 2453 + INTEGER(IntKi), PARAMETER :: M3N6MBFzi = 2454 + INTEGER(IntKi), PARAMETER :: M3N7MBFzi = 2455 + INTEGER(IntKi), PARAMETER :: M3N8MBFzi = 2456 + INTEGER(IntKi), PARAMETER :: M3N9MBFzi = 2457 + INTEGER(IntKi), PARAMETER :: M4N1MBFzi = 2458 + INTEGER(IntKi), PARAMETER :: M4N2MBFzi = 2459 + INTEGER(IntKi), PARAMETER :: M4N3MBFzi = 2460 + INTEGER(IntKi), PARAMETER :: M4N4MBFzi = 2461 + INTEGER(IntKi), PARAMETER :: M4N5MBFzi = 2462 + INTEGER(IntKi), PARAMETER :: M4N6MBFzi = 2463 + INTEGER(IntKi), PARAMETER :: M4N7MBFzi = 2464 + INTEGER(IntKi), PARAMETER :: M4N8MBFzi = 2465 + INTEGER(IntKi), PARAMETER :: M4N9MBFzi = 2466 + INTEGER(IntKi), PARAMETER :: M5N1MBFzi = 2467 + INTEGER(IntKi), PARAMETER :: M5N2MBFzi = 2468 + INTEGER(IntKi), PARAMETER :: M5N3MBFzi = 2469 + INTEGER(IntKi), PARAMETER :: M5N4MBFzi = 2470 + INTEGER(IntKi), PARAMETER :: M5N5MBFzi = 2471 + INTEGER(IntKi), PARAMETER :: M5N6MBFzi = 2472 + INTEGER(IntKi), PARAMETER :: M5N7MBFzi = 2473 + INTEGER(IntKi), PARAMETER :: M5N8MBFzi = 2474 + INTEGER(IntKi), PARAMETER :: M5N9MBFzi = 2475 + INTEGER(IntKi), PARAMETER :: M6N1MBFzi = 2476 + INTEGER(IntKi), PARAMETER :: M6N2MBFzi = 2477 + INTEGER(IntKi), PARAMETER :: M6N3MBFzi = 2478 + INTEGER(IntKi), PARAMETER :: M6N4MBFzi = 2479 + INTEGER(IntKi), PARAMETER :: M6N5MBFzi = 2480 + INTEGER(IntKi), PARAMETER :: M6N6MBFzi = 2481 + INTEGER(IntKi), PARAMETER :: M6N7MBFzi = 2482 + INTEGER(IntKi), PARAMETER :: M6N8MBFzi = 2483 + INTEGER(IntKi), PARAMETER :: M6N9MBFzi = 2484 + INTEGER(IntKi), PARAMETER :: M7N1MBFzi = 2485 + INTEGER(IntKi), PARAMETER :: M7N2MBFzi = 2486 + INTEGER(IntKi), PARAMETER :: M7N3MBFzi = 2487 + INTEGER(IntKi), PARAMETER :: M7N4MBFzi = 2488 + INTEGER(IntKi), PARAMETER :: M7N5MBFzi = 2489 + INTEGER(IntKi), PARAMETER :: M7N6MBFzi = 2490 + INTEGER(IntKi), PARAMETER :: M7N7MBFzi = 2491 + INTEGER(IntKi), PARAMETER :: M7N8MBFzi = 2492 + INTEGER(IntKi), PARAMETER :: M7N9MBFzi = 2493 + INTEGER(IntKi), PARAMETER :: M8N1MBFzi = 2494 + INTEGER(IntKi), PARAMETER :: M8N2MBFzi = 2495 + INTEGER(IntKi), PARAMETER :: M8N3MBFzi = 2496 + INTEGER(IntKi), PARAMETER :: M8N4MBFzi = 2497 + INTEGER(IntKi), PARAMETER :: M8N5MBFzi = 2498 + INTEGER(IntKi), PARAMETER :: M8N6MBFzi = 2499 + INTEGER(IntKi), PARAMETER :: M8N7MBFzi = 2500 + INTEGER(IntKi), PARAMETER :: M8N8MBFzi = 2501 + INTEGER(IntKi), PARAMETER :: M8N9MBFzi = 2502 + INTEGER(IntKi), PARAMETER :: M9N1MBFzi = 2503 + INTEGER(IntKi), PARAMETER :: M9N2MBFzi = 2504 + INTEGER(IntKi), PARAMETER :: M9N3MBFzi = 2505 + INTEGER(IntKi), PARAMETER :: M9N4MBFzi = 2506 + INTEGER(IntKi), PARAMETER :: M9N5MBFzi = 2507 + INTEGER(IntKi), PARAMETER :: M9N6MBFzi = 2508 + INTEGER(IntKi), PARAMETER :: M9N7MBFzi = 2509 + INTEGER(IntKi), PARAMETER :: M9N8MBFzi = 2510 + INTEGER(IntKi), PARAMETER :: M9N9MBFzi = 2511 + INTEGER(IntKi), PARAMETER :: M1N1FMGxi = 2512 + INTEGER(IntKi), PARAMETER :: M1N2FMGxi = 2513 + INTEGER(IntKi), PARAMETER :: M1N3FMGxi = 2514 + INTEGER(IntKi), PARAMETER :: M1N4FMGxi = 2515 + INTEGER(IntKi), PARAMETER :: M1N5FMGxi = 2516 + INTEGER(IntKi), PARAMETER :: M1N6FMGxi = 2517 + INTEGER(IntKi), PARAMETER :: M1N7FMGxi = 2518 + INTEGER(IntKi), PARAMETER :: M1N8FMGxi = 2519 + INTEGER(IntKi), PARAMETER :: M1N9FMGxi = 2520 + INTEGER(IntKi), PARAMETER :: M2N1FMGxi = 2521 + INTEGER(IntKi), PARAMETER :: M2N2FMGxi = 2522 + INTEGER(IntKi), PARAMETER :: M2N3FMGxi = 2523 + INTEGER(IntKi), PARAMETER :: M2N4FMGxi = 2524 + INTEGER(IntKi), PARAMETER :: M2N5FMGxi = 2525 + INTEGER(IntKi), PARAMETER :: M2N6FMGxi = 2526 + INTEGER(IntKi), PARAMETER :: M2N7FMGxi = 2527 + INTEGER(IntKi), PARAMETER :: M2N8FMGxi = 2528 + INTEGER(IntKi), PARAMETER :: M2N9FMGxi = 2529 + INTEGER(IntKi), PARAMETER :: M3N1FMGxi = 2530 + INTEGER(IntKi), PARAMETER :: M3N2FMGxi = 2531 + INTEGER(IntKi), PARAMETER :: M3N3FMGxi = 2532 + INTEGER(IntKi), PARAMETER :: M3N4FMGxi = 2533 + INTEGER(IntKi), PARAMETER :: M3N5FMGxi = 2534 + INTEGER(IntKi), PARAMETER :: M3N6FMGxi = 2535 + INTEGER(IntKi), PARAMETER :: M3N7FMGxi = 2536 + INTEGER(IntKi), PARAMETER :: M3N8FMGxi = 2537 + INTEGER(IntKi), PARAMETER :: M3N9FMGxi = 2538 + INTEGER(IntKi), PARAMETER :: M4N1FMGxi = 2539 + INTEGER(IntKi), PARAMETER :: M4N2FMGxi = 2540 + INTEGER(IntKi), PARAMETER :: M4N3FMGxi = 2541 + INTEGER(IntKi), PARAMETER :: M4N4FMGxi = 2542 + INTEGER(IntKi), PARAMETER :: M4N5FMGxi = 2543 + INTEGER(IntKi), PARAMETER :: M4N6FMGxi = 2544 + INTEGER(IntKi), PARAMETER :: M4N7FMGxi = 2545 + INTEGER(IntKi), PARAMETER :: M4N8FMGxi = 2546 + INTEGER(IntKi), PARAMETER :: M4N9FMGxi = 2547 + INTEGER(IntKi), PARAMETER :: M5N1FMGxi = 2548 + INTEGER(IntKi), PARAMETER :: M5N2FMGxi = 2549 + INTEGER(IntKi), PARAMETER :: M5N3FMGxi = 2550 + INTEGER(IntKi), PARAMETER :: M5N4FMGxi = 2551 + INTEGER(IntKi), PARAMETER :: M5N5FMGxi = 2552 + INTEGER(IntKi), PARAMETER :: M5N6FMGxi = 2553 + INTEGER(IntKi), PARAMETER :: M5N7FMGxi = 2554 + INTEGER(IntKi), PARAMETER :: M5N8FMGxi = 2555 + INTEGER(IntKi), PARAMETER :: M5N9FMGxi = 2556 + INTEGER(IntKi), PARAMETER :: M6N1FMGxi = 2557 + INTEGER(IntKi), PARAMETER :: M6N2FMGxi = 2558 + INTEGER(IntKi), PARAMETER :: M6N3FMGxi = 2559 + INTEGER(IntKi), PARAMETER :: M6N4FMGxi = 2560 + INTEGER(IntKi), PARAMETER :: M6N5FMGxi = 2561 + INTEGER(IntKi), PARAMETER :: M6N6FMGxi = 2562 + INTEGER(IntKi), PARAMETER :: M6N7FMGxi = 2563 + INTEGER(IntKi), PARAMETER :: M6N8FMGxi = 2564 + INTEGER(IntKi), PARAMETER :: M6N9FMGxi = 2565 + INTEGER(IntKi), PARAMETER :: M7N1FMGxi = 2566 + INTEGER(IntKi), PARAMETER :: M7N2FMGxi = 2567 + INTEGER(IntKi), PARAMETER :: M7N3FMGxi = 2568 + INTEGER(IntKi), PARAMETER :: M7N4FMGxi = 2569 + INTEGER(IntKi), PARAMETER :: M7N5FMGxi = 2570 + INTEGER(IntKi), PARAMETER :: M7N6FMGxi = 2571 + INTEGER(IntKi), PARAMETER :: M7N7FMGxi = 2572 + INTEGER(IntKi), PARAMETER :: M7N8FMGxi = 2573 + INTEGER(IntKi), PARAMETER :: M7N9FMGxi = 2574 + INTEGER(IntKi), PARAMETER :: M8N1FMGxi = 2575 + INTEGER(IntKi), PARAMETER :: M8N2FMGxi = 2576 + INTEGER(IntKi), PARAMETER :: M8N3FMGxi = 2577 + INTEGER(IntKi), PARAMETER :: M8N4FMGxi = 2578 + INTEGER(IntKi), PARAMETER :: M8N5FMGxi = 2579 + INTEGER(IntKi), PARAMETER :: M8N6FMGxi = 2580 + INTEGER(IntKi), PARAMETER :: M8N7FMGxi = 2581 + INTEGER(IntKi), PARAMETER :: M8N8FMGxi = 2582 + INTEGER(IntKi), PARAMETER :: M8N9FMGxi = 2583 + INTEGER(IntKi), PARAMETER :: M9N1FMGxi = 2584 + INTEGER(IntKi), PARAMETER :: M9N2FMGxi = 2585 + INTEGER(IntKi), PARAMETER :: M9N3FMGxi = 2586 + INTEGER(IntKi), PARAMETER :: M9N4FMGxi = 2587 + INTEGER(IntKi), PARAMETER :: M9N5FMGxi = 2588 + INTEGER(IntKi), PARAMETER :: M9N6FMGxi = 2589 + INTEGER(IntKi), PARAMETER :: M9N7FMGxi = 2590 + INTEGER(IntKi), PARAMETER :: M9N8FMGxi = 2591 + INTEGER(IntKi), PARAMETER :: M9N9FMGxi = 2592 + INTEGER(IntKi), PARAMETER :: M1N1FMGyi = 2593 + INTEGER(IntKi), PARAMETER :: M1N2FMGyi = 2594 + INTEGER(IntKi), PARAMETER :: M1N3FMGyi = 2595 + INTEGER(IntKi), PARAMETER :: M1N4FMGyi = 2596 + INTEGER(IntKi), PARAMETER :: M1N5FMGyi = 2597 + INTEGER(IntKi), PARAMETER :: M1N6FMGyi = 2598 + INTEGER(IntKi), PARAMETER :: M1N7FMGyi = 2599 + INTEGER(IntKi), PARAMETER :: M1N8FMGyi = 2600 + INTEGER(IntKi), PARAMETER :: M1N9FMGyi = 2601 + INTEGER(IntKi), PARAMETER :: M2N1FMGyi = 2602 + INTEGER(IntKi), PARAMETER :: M2N2FMGyi = 2603 + INTEGER(IntKi), PARAMETER :: M2N3FMGyi = 2604 + INTEGER(IntKi), PARAMETER :: M2N4FMGyi = 2605 + INTEGER(IntKi), PARAMETER :: M2N5FMGyi = 2606 + INTEGER(IntKi), PARAMETER :: M2N6FMGyi = 2607 + INTEGER(IntKi), PARAMETER :: M2N7FMGyi = 2608 + INTEGER(IntKi), PARAMETER :: M2N8FMGyi = 2609 + INTEGER(IntKi), PARAMETER :: M2N9FMGyi = 2610 + INTEGER(IntKi), PARAMETER :: M3N1FMGyi = 2611 + INTEGER(IntKi), PARAMETER :: M3N2FMGyi = 2612 + INTEGER(IntKi), PARAMETER :: M3N3FMGyi = 2613 + INTEGER(IntKi), PARAMETER :: M3N4FMGyi = 2614 + INTEGER(IntKi), PARAMETER :: M3N5FMGyi = 2615 + INTEGER(IntKi), PARAMETER :: M3N6FMGyi = 2616 + INTEGER(IntKi), PARAMETER :: M3N7FMGyi = 2617 + INTEGER(IntKi), PARAMETER :: M3N8FMGyi = 2618 + INTEGER(IntKi), PARAMETER :: M3N9FMGyi = 2619 + INTEGER(IntKi), PARAMETER :: M4N1FMGyi = 2620 + INTEGER(IntKi), PARAMETER :: M4N2FMGyi = 2621 + INTEGER(IntKi), PARAMETER :: M4N3FMGyi = 2622 + INTEGER(IntKi), PARAMETER :: M4N4FMGyi = 2623 + INTEGER(IntKi), PARAMETER :: M4N5FMGyi = 2624 + INTEGER(IntKi), PARAMETER :: M4N6FMGyi = 2625 + INTEGER(IntKi), PARAMETER :: M4N7FMGyi = 2626 + INTEGER(IntKi), PARAMETER :: M4N8FMGyi = 2627 + INTEGER(IntKi), PARAMETER :: M4N9FMGyi = 2628 + INTEGER(IntKi), PARAMETER :: M5N1FMGyi = 2629 + INTEGER(IntKi), PARAMETER :: M5N2FMGyi = 2630 + INTEGER(IntKi), PARAMETER :: M5N3FMGyi = 2631 + INTEGER(IntKi), PARAMETER :: M5N4FMGyi = 2632 + INTEGER(IntKi), PARAMETER :: M5N5FMGyi = 2633 + INTEGER(IntKi), PARAMETER :: M5N6FMGyi = 2634 + INTEGER(IntKi), PARAMETER :: M5N7FMGyi = 2635 + INTEGER(IntKi), PARAMETER :: M5N8FMGyi = 2636 + INTEGER(IntKi), PARAMETER :: M5N9FMGyi = 2637 + INTEGER(IntKi), PARAMETER :: M6N1FMGyi = 2638 + INTEGER(IntKi), PARAMETER :: M6N2FMGyi = 2639 + INTEGER(IntKi), PARAMETER :: M6N3FMGyi = 2640 + INTEGER(IntKi), PARAMETER :: M6N4FMGyi = 2641 + INTEGER(IntKi), PARAMETER :: M6N5FMGyi = 2642 + INTEGER(IntKi), PARAMETER :: M6N6FMGyi = 2643 + INTEGER(IntKi), PARAMETER :: M6N7FMGyi = 2644 + INTEGER(IntKi), PARAMETER :: M6N8FMGyi = 2645 + INTEGER(IntKi), PARAMETER :: M6N9FMGyi = 2646 + INTEGER(IntKi), PARAMETER :: M7N1FMGyi = 2647 + INTEGER(IntKi), PARAMETER :: M7N2FMGyi = 2648 + INTEGER(IntKi), PARAMETER :: M7N3FMGyi = 2649 + INTEGER(IntKi), PARAMETER :: M7N4FMGyi = 2650 + INTEGER(IntKi), PARAMETER :: M7N5FMGyi = 2651 + INTEGER(IntKi), PARAMETER :: M7N6FMGyi = 2652 + INTEGER(IntKi), PARAMETER :: M7N7FMGyi = 2653 + INTEGER(IntKi), PARAMETER :: M7N8FMGyi = 2654 + INTEGER(IntKi), PARAMETER :: M7N9FMGyi = 2655 + INTEGER(IntKi), PARAMETER :: M8N1FMGyi = 2656 + INTEGER(IntKi), PARAMETER :: M8N2FMGyi = 2657 + INTEGER(IntKi), PARAMETER :: M8N3FMGyi = 2658 + INTEGER(IntKi), PARAMETER :: M8N4FMGyi = 2659 + INTEGER(IntKi), PARAMETER :: M8N5FMGyi = 2660 + INTEGER(IntKi), PARAMETER :: M8N6FMGyi = 2661 + INTEGER(IntKi), PARAMETER :: M8N7FMGyi = 2662 + INTEGER(IntKi), PARAMETER :: M8N8FMGyi = 2663 + INTEGER(IntKi), PARAMETER :: M8N9FMGyi = 2664 + INTEGER(IntKi), PARAMETER :: M9N1FMGyi = 2665 + INTEGER(IntKi), PARAMETER :: M9N2FMGyi = 2666 + INTEGER(IntKi), PARAMETER :: M9N3FMGyi = 2667 + INTEGER(IntKi), PARAMETER :: M9N4FMGyi = 2668 + INTEGER(IntKi), PARAMETER :: M9N5FMGyi = 2669 + INTEGER(IntKi), PARAMETER :: M9N6FMGyi = 2670 + INTEGER(IntKi), PARAMETER :: M9N7FMGyi = 2671 + INTEGER(IntKi), PARAMETER :: M9N8FMGyi = 2672 + INTEGER(IntKi), PARAMETER :: M9N9FMGyi = 2673 + INTEGER(IntKi), PARAMETER :: M1N1FMGzi = 2674 + INTEGER(IntKi), PARAMETER :: M1N2FMGzi = 2675 + INTEGER(IntKi), PARAMETER :: M1N3FMGzi = 2676 + INTEGER(IntKi), PARAMETER :: M1N4FMGzi = 2677 + INTEGER(IntKi), PARAMETER :: M1N5FMGzi = 2678 + INTEGER(IntKi), PARAMETER :: M1N6FMGzi = 2679 + INTEGER(IntKi), PARAMETER :: M1N7FMGzi = 2680 + INTEGER(IntKi), PARAMETER :: M1N8FMGzi = 2681 + INTEGER(IntKi), PARAMETER :: M1N9FMGzi = 2682 + INTEGER(IntKi), PARAMETER :: M2N1FMGzi = 2683 + INTEGER(IntKi), PARAMETER :: M2N2FMGzi = 2684 + INTEGER(IntKi), PARAMETER :: M2N3FMGzi = 2685 + INTEGER(IntKi), PARAMETER :: M2N4FMGzi = 2686 + INTEGER(IntKi), PARAMETER :: M2N5FMGzi = 2687 + INTEGER(IntKi), PARAMETER :: M2N6FMGzi = 2688 + INTEGER(IntKi), PARAMETER :: M2N7FMGzi = 2689 + INTEGER(IntKi), PARAMETER :: M2N8FMGzi = 2690 + INTEGER(IntKi), PARAMETER :: M2N9FMGzi = 2691 + INTEGER(IntKi), PARAMETER :: M3N1FMGzi = 2692 + INTEGER(IntKi), PARAMETER :: M3N2FMGzi = 2693 + INTEGER(IntKi), PARAMETER :: M3N3FMGzi = 2694 + INTEGER(IntKi), PARAMETER :: M3N4FMGzi = 2695 + INTEGER(IntKi), PARAMETER :: M3N5FMGzi = 2696 + INTEGER(IntKi), PARAMETER :: M3N6FMGzi = 2697 + INTEGER(IntKi), PARAMETER :: M3N7FMGzi = 2698 + INTEGER(IntKi), PARAMETER :: M3N8FMGzi = 2699 + INTEGER(IntKi), PARAMETER :: M3N9FMGzi = 2700 + INTEGER(IntKi), PARAMETER :: M4N1FMGzi = 2701 + INTEGER(IntKi), PARAMETER :: M4N2FMGzi = 2702 + INTEGER(IntKi), PARAMETER :: M4N3FMGzi = 2703 + INTEGER(IntKi), PARAMETER :: M4N4FMGzi = 2704 + INTEGER(IntKi), PARAMETER :: M4N5FMGzi = 2705 + INTEGER(IntKi), PARAMETER :: M4N6FMGzi = 2706 + INTEGER(IntKi), PARAMETER :: M4N7FMGzi = 2707 + INTEGER(IntKi), PARAMETER :: M4N8FMGzi = 2708 + INTEGER(IntKi), PARAMETER :: M4N9FMGzi = 2709 + INTEGER(IntKi), PARAMETER :: M5N1FMGzi = 2710 + INTEGER(IntKi), PARAMETER :: M5N2FMGzi = 2711 + INTEGER(IntKi), PARAMETER :: M5N3FMGzi = 2712 + INTEGER(IntKi), PARAMETER :: M5N4FMGzi = 2713 + INTEGER(IntKi), PARAMETER :: M5N5FMGzi = 2714 + INTEGER(IntKi), PARAMETER :: M5N6FMGzi = 2715 + INTEGER(IntKi), PARAMETER :: M5N7FMGzi = 2716 + INTEGER(IntKi), PARAMETER :: M5N8FMGzi = 2717 + INTEGER(IntKi), PARAMETER :: M5N9FMGzi = 2718 + INTEGER(IntKi), PARAMETER :: M6N1FMGzi = 2719 + INTEGER(IntKi), PARAMETER :: M6N2FMGzi = 2720 + INTEGER(IntKi), PARAMETER :: M6N3FMGzi = 2721 + INTEGER(IntKi), PARAMETER :: M6N4FMGzi = 2722 + INTEGER(IntKi), PARAMETER :: M6N5FMGzi = 2723 + INTEGER(IntKi), PARAMETER :: M6N6FMGzi = 2724 + INTEGER(IntKi), PARAMETER :: M6N7FMGzi = 2725 + INTEGER(IntKi), PARAMETER :: M6N8FMGzi = 2726 + INTEGER(IntKi), PARAMETER :: M6N9FMGzi = 2727 + INTEGER(IntKi), PARAMETER :: M7N1FMGzi = 2728 + INTEGER(IntKi), PARAMETER :: M7N2FMGzi = 2729 + INTEGER(IntKi), PARAMETER :: M7N3FMGzi = 2730 + INTEGER(IntKi), PARAMETER :: M7N4FMGzi = 2731 + INTEGER(IntKi), PARAMETER :: M7N5FMGzi = 2732 + INTEGER(IntKi), PARAMETER :: M7N6FMGzi = 2733 + INTEGER(IntKi), PARAMETER :: M7N7FMGzi = 2734 + INTEGER(IntKi), PARAMETER :: M7N8FMGzi = 2735 + INTEGER(IntKi), PARAMETER :: M7N9FMGzi = 2736 + INTEGER(IntKi), PARAMETER :: M8N1FMGzi = 2737 + INTEGER(IntKi), PARAMETER :: M8N2FMGzi = 2738 + INTEGER(IntKi), PARAMETER :: M8N3FMGzi = 2739 + INTEGER(IntKi), PARAMETER :: M8N4FMGzi = 2740 + INTEGER(IntKi), PARAMETER :: M8N5FMGzi = 2741 + INTEGER(IntKi), PARAMETER :: M8N6FMGzi = 2742 + INTEGER(IntKi), PARAMETER :: M8N7FMGzi = 2743 + INTEGER(IntKi), PARAMETER :: M8N8FMGzi = 2744 + INTEGER(IntKi), PARAMETER :: M8N9FMGzi = 2745 + INTEGER(IntKi), PARAMETER :: M9N1FMGzi = 2746 + INTEGER(IntKi), PARAMETER :: M9N2FMGzi = 2747 + INTEGER(IntKi), PARAMETER :: M9N3FMGzi = 2748 + INTEGER(IntKi), PARAMETER :: M9N4FMGzi = 2749 + INTEGER(IntKi), PARAMETER :: M9N5FMGzi = 2750 + INTEGER(IntKi), PARAMETER :: M9N6FMGzi = 2751 + INTEGER(IntKi), PARAMETER :: M9N7FMGzi = 2752 + INTEGER(IntKi), PARAMETER :: M9N8FMGzi = 2753 + INTEGER(IntKi), PARAMETER :: M9N9FMGzi = 2754 + INTEGER(IntKi), PARAMETER :: M1N1FAMxi = 2755 + INTEGER(IntKi), PARAMETER :: M1N2FAMxi = 2756 + INTEGER(IntKi), PARAMETER :: M1N3FAMxi = 2757 + INTEGER(IntKi), PARAMETER :: M1N4FAMxi = 2758 + INTEGER(IntKi), PARAMETER :: M1N5FAMxi = 2759 + INTEGER(IntKi), PARAMETER :: M1N6FAMxi = 2760 + INTEGER(IntKi), PARAMETER :: M1N7FAMxi = 2761 + INTEGER(IntKi), PARAMETER :: M1N8FAMxi = 2762 + INTEGER(IntKi), PARAMETER :: M1N9FAMxi = 2763 + INTEGER(IntKi), PARAMETER :: M2N1FAMxi = 2764 + INTEGER(IntKi), PARAMETER :: M2N2FAMxi = 2765 + INTEGER(IntKi), PARAMETER :: M2N3FAMxi = 2766 + INTEGER(IntKi), PARAMETER :: M2N4FAMxi = 2767 + INTEGER(IntKi), PARAMETER :: M2N5FAMxi = 2768 + INTEGER(IntKi), PARAMETER :: M2N6FAMxi = 2769 + INTEGER(IntKi), PARAMETER :: M2N7FAMxi = 2770 + INTEGER(IntKi), PARAMETER :: M2N8FAMxi = 2771 + INTEGER(IntKi), PARAMETER :: M2N9FAMxi = 2772 + INTEGER(IntKi), PARAMETER :: M3N1FAMxi = 2773 + INTEGER(IntKi), PARAMETER :: M3N2FAMxi = 2774 + INTEGER(IntKi), PARAMETER :: M3N3FAMxi = 2775 + INTEGER(IntKi), PARAMETER :: M3N4FAMxi = 2776 + INTEGER(IntKi), PARAMETER :: M3N5FAMxi = 2777 + INTEGER(IntKi), PARAMETER :: M3N6FAMxi = 2778 + INTEGER(IntKi), PARAMETER :: M3N7FAMxi = 2779 + INTEGER(IntKi), PARAMETER :: M3N8FAMxi = 2780 + INTEGER(IntKi), PARAMETER :: M3N9FAMxi = 2781 + INTEGER(IntKi), PARAMETER :: M4N1FAMxi = 2782 + INTEGER(IntKi), PARAMETER :: M4N2FAMxi = 2783 + INTEGER(IntKi), PARAMETER :: M4N3FAMxi = 2784 + INTEGER(IntKi), PARAMETER :: M4N4FAMxi = 2785 + INTEGER(IntKi), PARAMETER :: M4N5FAMxi = 2786 + INTEGER(IntKi), PARAMETER :: M4N6FAMxi = 2787 + INTEGER(IntKi), PARAMETER :: M4N7FAMxi = 2788 + INTEGER(IntKi), PARAMETER :: M4N8FAMxi = 2789 + INTEGER(IntKi), PARAMETER :: M4N9FAMxi = 2790 + INTEGER(IntKi), PARAMETER :: M5N1FAMxi = 2791 + INTEGER(IntKi), PARAMETER :: M5N2FAMxi = 2792 + INTEGER(IntKi), PARAMETER :: M5N3FAMxi = 2793 + INTEGER(IntKi), PARAMETER :: M5N4FAMxi = 2794 + INTEGER(IntKi), PARAMETER :: M5N5FAMxi = 2795 + INTEGER(IntKi), PARAMETER :: M5N6FAMxi = 2796 + INTEGER(IntKi), PARAMETER :: M5N7FAMxi = 2797 + INTEGER(IntKi), PARAMETER :: M5N8FAMxi = 2798 + INTEGER(IntKi), PARAMETER :: M5N9FAMxi = 2799 + INTEGER(IntKi), PARAMETER :: M6N1FAMxi = 2800 + INTEGER(IntKi), PARAMETER :: M6N2FAMxi = 2801 + INTEGER(IntKi), PARAMETER :: M6N3FAMxi = 2802 + INTEGER(IntKi), PARAMETER :: M6N4FAMxi = 2803 + INTEGER(IntKi), PARAMETER :: M6N5FAMxi = 2804 + INTEGER(IntKi), PARAMETER :: M6N6FAMxi = 2805 + INTEGER(IntKi), PARAMETER :: M6N7FAMxi = 2806 + INTEGER(IntKi), PARAMETER :: M6N8FAMxi = 2807 + INTEGER(IntKi), PARAMETER :: M6N9FAMxi = 2808 + INTEGER(IntKi), PARAMETER :: M7N1FAMxi = 2809 + INTEGER(IntKi), PARAMETER :: M7N2FAMxi = 2810 + INTEGER(IntKi), PARAMETER :: M7N3FAMxi = 2811 + INTEGER(IntKi), PARAMETER :: M7N4FAMxi = 2812 + INTEGER(IntKi), PARAMETER :: M7N5FAMxi = 2813 + INTEGER(IntKi), PARAMETER :: M7N6FAMxi = 2814 + INTEGER(IntKi), PARAMETER :: M7N7FAMxi = 2815 + INTEGER(IntKi), PARAMETER :: M7N8FAMxi = 2816 + INTEGER(IntKi), PARAMETER :: M7N9FAMxi = 2817 + INTEGER(IntKi), PARAMETER :: M8N1FAMxi = 2818 + INTEGER(IntKi), PARAMETER :: M8N2FAMxi = 2819 + INTEGER(IntKi), PARAMETER :: M8N3FAMxi = 2820 + INTEGER(IntKi), PARAMETER :: M8N4FAMxi = 2821 + INTEGER(IntKi), PARAMETER :: M8N5FAMxi = 2822 + INTEGER(IntKi), PARAMETER :: M8N6FAMxi = 2823 + INTEGER(IntKi), PARAMETER :: M8N7FAMxi = 2824 + INTEGER(IntKi), PARAMETER :: M8N8FAMxi = 2825 + INTEGER(IntKi), PARAMETER :: M8N9FAMxi = 2826 + INTEGER(IntKi), PARAMETER :: M9N1FAMxi = 2827 + INTEGER(IntKi), PARAMETER :: M9N2FAMxi = 2828 + INTEGER(IntKi), PARAMETER :: M9N3FAMxi = 2829 + INTEGER(IntKi), PARAMETER :: M9N4FAMxi = 2830 + INTEGER(IntKi), PARAMETER :: M9N5FAMxi = 2831 + INTEGER(IntKi), PARAMETER :: M9N6FAMxi = 2832 + INTEGER(IntKi), PARAMETER :: M9N7FAMxi = 2833 + INTEGER(IntKi), PARAMETER :: M9N8FAMxi = 2834 + INTEGER(IntKi), PARAMETER :: M9N9FAMxi = 2835 + INTEGER(IntKi), PARAMETER :: M1N1FAMyi = 2836 + INTEGER(IntKi), PARAMETER :: M1N2FAMyi = 2837 + INTEGER(IntKi), PARAMETER :: M1N3FAMyi = 2838 + INTEGER(IntKi), PARAMETER :: M1N4FAMyi = 2839 + INTEGER(IntKi), PARAMETER :: M1N5FAMyi = 2840 + INTEGER(IntKi), PARAMETER :: M1N6FAMyi = 2841 + INTEGER(IntKi), PARAMETER :: M1N7FAMyi = 2842 + INTEGER(IntKi), PARAMETER :: M1N8FAMyi = 2843 + INTEGER(IntKi), PARAMETER :: M1N9FAMyi = 2844 + INTEGER(IntKi), PARAMETER :: M2N1FAMyi = 2845 + INTEGER(IntKi), PARAMETER :: M2N2FAMyi = 2846 + INTEGER(IntKi), PARAMETER :: M2N3FAMyi = 2847 + INTEGER(IntKi), PARAMETER :: M2N4FAMyi = 2848 + INTEGER(IntKi), PARAMETER :: M2N5FAMyi = 2849 + INTEGER(IntKi), PARAMETER :: M2N6FAMyi = 2850 + INTEGER(IntKi), PARAMETER :: M2N7FAMyi = 2851 + INTEGER(IntKi), PARAMETER :: M2N8FAMyi = 2852 + INTEGER(IntKi), PARAMETER :: M2N9FAMyi = 2853 + INTEGER(IntKi), PARAMETER :: M3N1FAMyi = 2854 + INTEGER(IntKi), PARAMETER :: M3N2FAMyi = 2855 + INTEGER(IntKi), PARAMETER :: M3N3FAMyi = 2856 + INTEGER(IntKi), PARAMETER :: M3N4FAMyi = 2857 + INTEGER(IntKi), PARAMETER :: M3N5FAMyi = 2858 + INTEGER(IntKi), PARAMETER :: M3N6FAMyi = 2859 + INTEGER(IntKi), PARAMETER :: M3N7FAMyi = 2860 + INTEGER(IntKi), PARAMETER :: M3N8FAMyi = 2861 + INTEGER(IntKi), PARAMETER :: M3N9FAMyi = 2862 + INTEGER(IntKi), PARAMETER :: M4N1FAMyi = 2863 + INTEGER(IntKi), PARAMETER :: M4N2FAMyi = 2864 + INTEGER(IntKi), PARAMETER :: M4N3FAMyi = 2865 + INTEGER(IntKi), PARAMETER :: M4N4FAMyi = 2866 + INTEGER(IntKi), PARAMETER :: M4N5FAMyi = 2867 + INTEGER(IntKi), PARAMETER :: M4N6FAMyi = 2868 + INTEGER(IntKi), PARAMETER :: M4N7FAMyi = 2869 + INTEGER(IntKi), PARAMETER :: M4N8FAMyi = 2870 + INTEGER(IntKi), PARAMETER :: M4N9FAMyi = 2871 + INTEGER(IntKi), PARAMETER :: M5N1FAMyi = 2872 + INTEGER(IntKi), PARAMETER :: M5N2FAMyi = 2873 + INTEGER(IntKi), PARAMETER :: M5N3FAMyi = 2874 + INTEGER(IntKi), PARAMETER :: M5N4FAMyi = 2875 + INTEGER(IntKi), PARAMETER :: M5N5FAMyi = 2876 + INTEGER(IntKi), PARAMETER :: M5N6FAMyi = 2877 + INTEGER(IntKi), PARAMETER :: M5N7FAMyi = 2878 + INTEGER(IntKi), PARAMETER :: M5N8FAMyi = 2879 + INTEGER(IntKi), PARAMETER :: M5N9FAMyi = 2880 + INTEGER(IntKi), PARAMETER :: M6N1FAMyi = 2881 + INTEGER(IntKi), PARAMETER :: M6N2FAMyi = 2882 + INTEGER(IntKi), PARAMETER :: M6N3FAMyi = 2883 + INTEGER(IntKi), PARAMETER :: M6N4FAMyi = 2884 + INTEGER(IntKi), PARAMETER :: M6N5FAMyi = 2885 + INTEGER(IntKi), PARAMETER :: M6N6FAMyi = 2886 + INTEGER(IntKi), PARAMETER :: M6N7FAMyi = 2887 + INTEGER(IntKi), PARAMETER :: M6N8FAMyi = 2888 + INTEGER(IntKi), PARAMETER :: M6N9FAMyi = 2889 + INTEGER(IntKi), PARAMETER :: M7N1FAMyi = 2890 + INTEGER(IntKi), PARAMETER :: M7N2FAMyi = 2891 + INTEGER(IntKi), PARAMETER :: M7N3FAMyi = 2892 + INTEGER(IntKi), PARAMETER :: M7N4FAMyi = 2893 + INTEGER(IntKi), PARAMETER :: M7N5FAMyi = 2894 + INTEGER(IntKi), PARAMETER :: M7N6FAMyi = 2895 + INTEGER(IntKi), PARAMETER :: M7N7FAMyi = 2896 + INTEGER(IntKi), PARAMETER :: M7N8FAMyi = 2897 + INTEGER(IntKi), PARAMETER :: M7N9FAMyi = 2898 + INTEGER(IntKi), PARAMETER :: M8N1FAMyi = 2899 + INTEGER(IntKi), PARAMETER :: M8N2FAMyi = 2900 + INTEGER(IntKi), PARAMETER :: M8N3FAMyi = 2901 + INTEGER(IntKi), PARAMETER :: M8N4FAMyi = 2902 + INTEGER(IntKi), PARAMETER :: M8N5FAMyi = 2903 + INTEGER(IntKi), PARAMETER :: M8N6FAMyi = 2904 + INTEGER(IntKi), PARAMETER :: M8N7FAMyi = 2905 + INTEGER(IntKi), PARAMETER :: M8N8FAMyi = 2906 + INTEGER(IntKi), PARAMETER :: M8N9FAMyi = 2907 + INTEGER(IntKi), PARAMETER :: M9N1FAMyi = 2908 + INTEGER(IntKi), PARAMETER :: M9N2FAMyi = 2909 + INTEGER(IntKi), PARAMETER :: M9N3FAMyi = 2910 + INTEGER(IntKi), PARAMETER :: M9N4FAMyi = 2911 + INTEGER(IntKi), PARAMETER :: M9N5FAMyi = 2912 + INTEGER(IntKi), PARAMETER :: M9N6FAMyi = 2913 + INTEGER(IntKi), PARAMETER :: M9N7FAMyi = 2914 + INTEGER(IntKi), PARAMETER :: M9N8FAMyi = 2915 + INTEGER(IntKi), PARAMETER :: M9N9FAMyi = 2916 + INTEGER(IntKi), PARAMETER :: M1N1FAMzi = 2917 + INTEGER(IntKi), PARAMETER :: M1N2FAMzi = 2918 + INTEGER(IntKi), PARAMETER :: M1N3FAMzi = 2919 + INTEGER(IntKi), PARAMETER :: M1N4FAMzi = 2920 + INTEGER(IntKi), PARAMETER :: M1N5FAMzi = 2921 + INTEGER(IntKi), PARAMETER :: M1N6FAMzi = 2922 + INTEGER(IntKi), PARAMETER :: M1N7FAMzi = 2923 + INTEGER(IntKi), PARAMETER :: M1N8FAMzi = 2924 + INTEGER(IntKi), PARAMETER :: M1N9FAMzi = 2925 + INTEGER(IntKi), PARAMETER :: M2N1FAMzi = 2926 + INTEGER(IntKi), PARAMETER :: M2N2FAMzi = 2927 + INTEGER(IntKi), PARAMETER :: M2N3FAMzi = 2928 + INTEGER(IntKi), PARAMETER :: M2N4FAMzi = 2929 + INTEGER(IntKi), PARAMETER :: M2N5FAMzi = 2930 + INTEGER(IntKi), PARAMETER :: M2N6FAMzi = 2931 + INTEGER(IntKi), PARAMETER :: M2N7FAMzi = 2932 + INTEGER(IntKi), PARAMETER :: M2N8FAMzi = 2933 + INTEGER(IntKi), PARAMETER :: M2N9FAMzi = 2934 + INTEGER(IntKi), PARAMETER :: M3N1FAMzi = 2935 + INTEGER(IntKi), PARAMETER :: M3N2FAMzi = 2936 + INTEGER(IntKi), PARAMETER :: M3N3FAMzi = 2937 + INTEGER(IntKi), PARAMETER :: M3N4FAMzi = 2938 + INTEGER(IntKi), PARAMETER :: M3N5FAMzi = 2939 + INTEGER(IntKi), PARAMETER :: M3N6FAMzi = 2940 + INTEGER(IntKi), PARAMETER :: M3N7FAMzi = 2941 + INTEGER(IntKi), PARAMETER :: M3N8FAMzi = 2942 + INTEGER(IntKi), PARAMETER :: M3N9FAMzi = 2943 + INTEGER(IntKi), PARAMETER :: M4N1FAMzi = 2944 + INTEGER(IntKi), PARAMETER :: M4N2FAMzi = 2945 + INTEGER(IntKi), PARAMETER :: M4N3FAMzi = 2946 + INTEGER(IntKi), PARAMETER :: M4N4FAMzi = 2947 + INTEGER(IntKi), PARAMETER :: M4N5FAMzi = 2948 + INTEGER(IntKi), PARAMETER :: M4N6FAMzi = 2949 + INTEGER(IntKi), PARAMETER :: M4N7FAMzi = 2950 + INTEGER(IntKi), PARAMETER :: M4N8FAMzi = 2951 + INTEGER(IntKi), PARAMETER :: M4N9FAMzi = 2952 + INTEGER(IntKi), PARAMETER :: M5N1FAMzi = 2953 + INTEGER(IntKi), PARAMETER :: M5N2FAMzi = 2954 + INTEGER(IntKi), PARAMETER :: M5N3FAMzi = 2955 + INTEGER(IntKi), PARAMETER :: M5N4FAMzi = 2956 + INTEGER(IntKi), PARAMETER :: M5N5FAMzi = 2957 + INTEGER(IntKi), PARAMETER :: M5N6FAMzi = 2958 + INTEGER(IntKi), PARAMETER :: M5N7FAMzi = 2959 + INTEGER(IntKi), PARAMETER :: M5N8FAMzi = 2960 + INTEGER(IntKi), PARAMETER :: M5N9FAMzi = 2961 + INTEGER(IntKi), PARAMETER :: M6N1FAMzi = 2962 + INTEGER(IntKi), PARAMETER :: M6N2FAMzi = 2963 + INTEGER(IntKi), PARAMETER :: M6N3FAMzi = 2964 + INTEGER(IntKi), PARAMETER :: M6N4FAMzi = 2965 + INTEGER(IntKi), PARAMETER :: M6N5FAMzi = 2966 + INTEGER(IntKi), PARAMETER :: M6N6FAMzi = 2967 + INTEGER(IntKi), PARAMETER :: M6N7FAMzi = 2968 + INTEGER(IntKi), PARAMETER :: M6N8FAMzi = 2969 + INTEGER(IntKi), PARAMETER :: M6N9FAMzi = 2970 + INTEGER(IntKi), PARAMETER :: M7N1FAMzi = 2971 + INTEGER(IntKi), PARAMETER :: M7N2FAMzi = 2972 + INTEGER(IntKi), PARAMETER :: M7N3FAMzi = 2973 + INTEGER(IntKi), PARAMETER :: M7N4FAMzi = 2974 + INTEGER(IntKi), PARAMETER :: M7N5FAMzi = 2975 + INTEGER(IntKi), PARAMETER :: M7N6FAMzi = 2976 + INTEGER(IntKi), PARAMETER :: M7N7FAMzi = 2977 + INTEGER(IntKi), PARAMETER :: M7N8FAMzi = 2978 + INTEGER(IntKi), PARAMETER :: M7N9FAMzi = 2979 + INTEGER(IntKi), PARAMETER :: M8N1FAMzi = 2980 + INTEGER(IntKi), PARAMETER :: M8N2FAMzi = 2981 + INTEGER(IntKi), PARAMETER :: M8N3FAMzi = 2982 + INTEGER(IntKi), PARAMETER :: M8N4FAMzi = 2983 + INTEGER(IntKi), PARAMETER :: M8N5FAMzi = 2984 + INTEGER(IntKi), PARAMETER :: M8N6FAMzi = 2985 + INTEGER(IntKi), PARAMETER :: M8N7FAMzi = 2986 + INTEGER(IntKi), PARAMETER :: M8N8FAMzi = 2987 + INTEGER(IntKi), PARAMETER :: M8N9FAMzi = 2988 + INTEGER(IntKi), PARAMETER :: M9N1FAMzi = 2989 + INTEGER(IntKi), PARAMETER :: M9N2FAMzi = 2990 + INTEGER(IntKi), PARAMETER :: M9N3FAMzi = 2991 + INTEGER(IntKi), PARAMETER :: M9N4FAMzi = 2992 + INTEGER(IntKi), PARAMETER :: M9N5FAMzi = 2993 + INTEGER(IntKi), PARAMETER :: M9N6FAMzi = 2994 + INTEGER(IntKi), PARAMETER :: M9N7FAMzi = 2995 + INTEGER(IntKi), PARAMETER :: M9N8FAMzi = 2996 + INTEGER(IntKi), PARAMETER :: M9N9FAMzi = 2997 + INTEGER(IntKi), PARAMETER :: M1N1FAGxi = 2998 + INTEGER(IntKi), PARAMETER :: M1N2FAGxi = 2999 + INTEGER(IntKi), PARAMETER :: M1N3FAGxi = 3000 + INTEGER(IntKi), PARAMETER :: M1N4FAGxi = 3001 + INTEGER(IntKi), PARAMETER :: M1N5FAGxi = 3002 + INTEGER(IntKi), PARAMETER :: M1N6FAGxi = 3003 + INTEGER(IntKi), PARAMETER :: M1N7FAGxi = 3004 + INTEGER(IntKi), PARAMETER :: M1N8FAGxi = 3005 + INTEGER(IntKi), PARAMETER :: M1N9FAGxi = 3006 + INTEGER(IntKi), PARAMETER :: M2N1FAGxi = 3007 + INTEGER(IntKi), PARAMETER :: M2N2FAGxi = 3008 + INTEGER(IntKi), PARAMETER :: M2N3FAGxi = 3009 + INTEGER(IntKi), PARAMETER :: M2N4FAGxi = 3010 + INTEGER(IntKi), PARAMETER :: M2N5FAGxi = 3011 + INTEGER(IntKi), PARAMETER :: M2N6FAGxi = 3012 + INTEGER(IntKi), PARAMETER :: M2N7FAGxi = 3013 + INTEGER(IntKi), PARAMETER :: M2N8FAGxi = 3014 + INTEGER(IntKi), PARAMETER :: M2N9FAGxi = 3015 + INTEGER(IntKi), PARAMETER :: M3N1FAGxi = 3016 + INTEGER(IntKi), PARAMETER :: M3N2FAGxi = 3017 + INTEGER(IntKi), PARAMETER :: M3N3FAGxi = 3018 + INTEGER(IntKi), PARAMETER :: M3N4FAGxi = 3019 + INTEGER(IntKi), PARAMETER :: M3N5FAGxi = 3020 + INTEGER(IntKi), PARAMETER :: M3N6FAGxi = 3021 + INTEGER(IntKi), PARAMETER :: M3N7FAGxi = 3022 + INTEGER(IntKi), PARAMETER :: M3N8FAGxi = 3023 + INTEGER(IntKi), PARAMETER :: M3N9FAGxi = 3024 + INTEGER(IntKi), PARAMETER :: M4N1FAGxi = 3025 + INTEGER(IntKi), PARAMETER :: M4N2FAGxi = 3026 + INTEGER(IntKi), PARAMETER :: M4N3FAGxi = 3027 + INTEGER(IntKi), PARAMETER :: M4N4FAGxi = 3028 + INTEGER(IntKi), PARAMETER :: M4N5FAGxi = 3029 + INTEGER(IntKi), PARAMETER :: M4N6FAGxi = 3030 + INTEGER(IntKi), PARAMETER :: M4N7FAGxi = 3031 + INTEGER(IntKi), PARAMETER :: M4N8FAGxi = 3032 + INTEGER(IntKi), PARAMETER :: M4N9FAGxi = 3033 + INTEGER(IntKi), PARAMETER :: M5N1FAGxi = 3034 + INTEGER(IntKi), PARAMETER :: M5N2FAGxi = 3035 + INTEGER(IntKi), PARAMETER :: M5N3FAGxi = 3036 + INTEGER(IntKi), PARAMETER :: M5N4FAGxi = 3037 + INTEGER(IntKi), PARAMETER :: M5N5FAGxi = 3038 + INTEGER(IntKi), PARAMETER :: M5N6FAGxi = 3039 + INTEGER(IntKi), PARAMETER :: M5N7FAGxi = 3040 + INTEGER(IntKi), PARAMETER :: M5N8FAGxi = 3041 + INTEGER(IntKi), PARAMETER :: M5N9FAGxi = 3042 + INTEGER(IntKi), PARAMETER :: M6N1FAGxi = 3043 + INTEGER(IntKi), PARAMETER :: M6N2FAGxi = 3044 + INTEGER(IntKi), PARAMETER :: M6N3FAGxi = 3045 + INTEGER(IntKi), PARAMETER :: M6N4FAGxi = 3046 + INTEGER(IntKi), PARAMETER :: M6N5FAGxi = 3047 + INTEGER(IntKi), PARAMETER :: M6N6FAGxi = 3048 + INTEGER(IntKi), PARAMETER :: M6N7FAGxi = 3049 + INTEGER(IntKi), PARAMETER :: M6N8FAGxi = 3050 + INTEGER(IntKi), PARAMETER :: M6N9FAGxi = 3051 + INTEGER(IntKi), PARAMETER :: M7N1FAGxi = 3052 + INTEGER(IntKi), PARAMETER :: M7N2FAGxi = 3053 + INTEGER(IntKi), PARAMETER :: M7N3FAGxi = 3054 + INTEGER(IntKi), PARAMETER :: M7N4FAGxi = 3055 + INTEGER(IntKi), PARAMETER :: M7N5FAGxi = 3056 + INTEGER(IntKi), PARAMETER :: M7N6FAGxi = 3057 + INTEGER(IntKi), PARAMETER :: M7N7FAGxi = 3058 + INTEGER(IntKi), PARAMETER :: M7N8FAGxi = 3059 + INTEGER(IntKi), PARAMETER :: M7N9FAGxi = 3060 + INTEGER(IntKi), PARAMETER :: M8N1FAGxi = 3061 + INTEGER(IntKi), PARAMETER :: M8N2FAGxi = 3062 + INTEGER(IntKi), PARAMETER :: M8N3FAGxi = 3063 + INTEGER(IntKi), PARAMETER :: M8N4FAGxi = 3064 + INTEGER(IntKi), PARAMETER :: M8N5FAGxi = 3065 + INTEGER(IntKi), PARAMETER :: M8N6FAGxi = 3066 + INTEGER(IntKi), PARAMETER :: M8N7FAGxi = 3067 + INTEGER(IntKi), PARAMETER :: M8N8FAGxi = 3068 + INTEGER(IntKi), PARAMETER :: M8N9FAGxi = 3069 + INTEGER(IntKi), PARAMETER :: M9N1FAGxi = 3070 + INTEGER(IntKi), PARAMETER :: M9N2FAGxi = 3071 + INTEGER(IntKi), PARAMETER :: M9N3FAGxi = 3072 + INTEGER(IntKi), PARAMETER :: M9N4FAGxi = 3073 + INTEGER(IntKi), PARAMETER :: M9N5FAGxi = 3074 + INTEGER(IntKi), PARAMETER :: M9N6FAGxi = 3075 + INTEGER(IntKi), PARAMETER :: M9N7FAGxi = 3076 + INTEGER(IntKi), PARAMETER :: M9N8FAGxi = 3077 + INTEGER(IntKi), PARAMETER :: M9N9FAGxi = 3078 + INTEGER(IntKi), PARAMETER :: M1N1FAGyi = 3079 + INTEGER(IntKi), PARAMETER :: M1N2FAGyi = 3080 + INTEGER(IntKi), PARAMETER :: M1N3FAGyi = 3081 + INTEGER(IntKi), PARAMETER :: M1N4FAGyi = 3082 + INTEGER(IntKi), PARAMETER :: M1N5FAGyi = 3083 + INTEGER(IntKi), PARAMETER :: M1N6FAGyi = 3084 + INTEGER(IntKi), PARAMETER :: M1N7FAGyi = 3085 + INTEGER(IntKi), PARAMETER :: M1N8FAGyi = 3086 + INTEGER(IntKi), PARAMETER :: M1N9FAGyi = 3087 + INTEGER(IntKi), PARAMETER :: M2N1FAGyi = 3088 + INTEGER(IntKi), PARAMETER :: M2N2FAGyi = 3089 + INTEGER(IntKi), PARAMETER :: M2N3FAGyi = 3090 + INTEGER(IntKi), PARAMETER :: M2N4FAGyi = 3091 + INTEGER(IntKi), PARAMETER :: M2N5FAGyi = 3092 + INTEGER(IntKi), PARAMETER :: M2N6FAGyi = 3093 + INTEGER(IntKi), PARAMETER :: M2N7FAGyi = 3094 + INTEGER(IntKi), PARAMETER :: M2N8FAGyi = 3095 + INTEGER(IntKi), PARAMETER :: M2N9FAGyi = 3096 + INTEGER(IntKi), PARAMETER :: M3N1FAGyi = 3097 + INTEGER(IntKi), PARAMETER :: M3N2FAGyi = 3098 + INTEGER(IntKi), PARAMETER :: M3N3FAGyi = 3099 + INTEGER(IntKi), PARAMETER :: M3N4FAGyi = 3100 + INTEGER(IntKi), PARAMETER :: M3N5FAGyi = 3101 + INTEGER(IntKi), PARAMETER :: M3N6FAGyi = 3102 + INTEGER(IntKi), PARAMETER :: M3N7FAGyi = 3103 + INTEGER(IntKi), PARAMETER :: M3N8FAGyi = 3104 + INTEGER(IntKi), PARAMETER :: M3N9FAGyi = 3105 + INTEGER(IntKi), PARAMETER :: M4N1FAGyi = 3106 + INTEGER(IntKi), PARAMETER :: M4N2FAGyi = 3107 + INTEGER(IntKi), PARAMETER :: M4N3FAGyi = 3108 + INTEGER(IntKi), PARAMETER :: M4N4FAGyi = 3109 + INTEGER(IntKi), PARAMETER :: M4N5FAGyi = 3110 + INTEGER(IntKi), PARAMETER :: M4N6FAGyi = 3111 + INTEGER(IntKi), PARAMETER :: M4N7FAGyi = 3112 + INTEGER(IntKi), PARAMETER :: M4N8FAGyi = 3113 + INTEGER(IntKi), PARAMETER :: M4N9FAGyi = 3114 + INTEGER(IntKi), PARAMETER :: M5N1FAGyi = 3115 + INTEGER(IntKi), PARAMETER :: M5N2FAGyi = 3116 + INTEGER(IntKi), PARAMETER :: M5N3FAGyi = 3117 + INTEGER(IntKi), PARAMETER :: M5N4FAGyi = 3118 + INTEGER(IntKi), PARAMETER :: M5N5FAGyi = 3119 + INTEGER(IntKi), PARAMETER :: M5N6FAGyi = 3120 + INTEGER(IntKi), PARAMETER :: M5N7FAGyi = 3121 + INTEGER(IntKi), PARAMETER :: M5N8FAGyi = 3122 + INTEGER(IntKi), PARAMETER :: M5N9FAGyi = 3123 + INTEGER(IntKi), PARAMETER :: M6N1FAGyi = 3124 + INTEGER(IntKi), PARAMETER :: M6N2FAGyi = 3125 + INTEGER(IntKi), PARAMETER :: M6N3FAGyi = 3126 + INTEGER(IntKi), PARAMETER :: M6N4FAGyi = 3127 + INTEGER(IntKi), PARAMETER :: M6N5FAGyi = 3128 + INTEGER(IntKi), PARAMETER :: M6N6FAGyi = 3129 + INTEGER(IntKi), PARAMETER :: M6N7FAGyi = 3130 + INTEGER(IntKi), PARAMETER :: M6N8FAGyi = 3131 + INTEGER(IntKi), PARAMETER :: M6N9FAGyi = 3132 + INTEGER(IntKi), PARAMETER :: M7N1FAGyi = 3133 + INTEGER(IntKi), PARAMETER :: M7N2FAGyi = 3134 + INTEGER(IntKi), PARAMETER :: M7N3FAGyi = 3135 + INTEGER(IntKi), PARAMETER :: M7N4FAGyi = 3136 + INTEGER(IntKi), PARAMETER :: M7N5FAGyi = 3137 + INTEGER(IntKi), PARAMETER :: M7N6FAGyi = 3138 + INTEGER(IntKi), PARAMETER :: M7N7FAGyi = 3139 + INTEGER(IntKi), PARAMETER :: M7N8FAGyi = 3140 + INTEGER(IntKi), PARAMETER :: M7N9FAGyi = 3141 + INTEGER(IntKi), PARAMETER :: M8N1FAGyi = 3142 + INTEGER(IntKi), PARAMETER :: M8N2FAGyi = 3143 + INTEGER(IntKi), PARAMETER :: M8N3FAGyi = 3144 + INTEGER(IntKi), PARAMETER :: M8N4FAGyi = 3145 + INTEGER(IntKi), PARAMETER :: M8N5FAGyi = 3146 + INTEGER(IntKi), PARAMETER :: M8N6FAGyi = 3147 + INTEGER(IntKi), PARAMETER :: M8N7FAGyi = 3148 + INTEGER(IntKi), PARAMETER :: M8N8FAGyi = 3149 + INTEGER(IntKi), PARAMETER :: M8N9FAGyi = 3150 + INTEGER(IntKi), PARAMETER :: M9N1FAGyi = 3151 + INTEGER(IntKi), PARAMETER :: M9N2FAGyi = 3152 + INTEGER(IntKi), PARAMETER :: M9N3FAGyi = 3153 + INTEGER(IntKi), PARAMETER :: M9N4FAGyi = 3154 + INTEGER(IntKi), PARAMETER :: M9N5FAGyi = 3155 + INTEGER(IntKi), PARAMETER :: M9N6FAGyi = 3156 + INTEGER(IntKi), PARAMETER :: M9N7FAGyi = 3157 + INTEGER(IntKi), PARAMETER :: M9N8FAGyi = 3158 + INTEGER(IntKi), PARAMETER :: M9N9FAGyi = 3159 + INTEGER(IntKi), PARAMETER :: M1N1FAGzi = 3160 + INTEGER(IntKi), PARAMETER :: M1N2FAGzi = 3161 + INTEGER(IntKi), PARAMETER :: M1N3FAGzi = 3162 + INTEGER(IntKi), PARAMETER :: M1N4FAGzi = 3163 + INTEGER(IntKi), PARAMETER :: M1N5FAGzi = 3164 + INTEGER(IntKi), PARAMETER :: M1N6FAGzi = 3165 + INTEGER(IntKi), PARAMETER :: M1N7FAGzi = 3166 + INTEGER(IntKi), PARAMETER :: M1N8FAGzi = 3167 + INTEGER(IntKi), PARAMETER :: M1N9FAGzi = 3168 + INTEGER(IntKi), PARAMETER :: M2N1FAGzi = 3169 + INTEGER(IntKi), PARAMETER :: M2N2FAGzi = 3170 + INTEGER(IntKi), PARAMETER :: M2N3FAGzi = 3171 + INTEGER(IntKi), PARAMETER :: M2N4FAGzi = 3172 + INTEGER(IntKi), PARAMETER :: M2N5FAGzi = 3173 + INTEGER(IntKi), PARAMETER :: M2N6FAGzi = 3174 + INTEGER(IntKi), PARAMETER :: M2N7FAGzi = 3175 + INTEGER(IntKi), PARAMETER :: M2N8FAGzi = 3176 + INTEGER(IntKi), PARAMETER :: M2N9FAGzi = 3177 + INTEGER(IntKi), PARAMETER :: M3N1FAGzi = 3178 + INTEGER(IntKi), PARAMETER :: M3N2FAGzi = 3179 + INTEGER(IntKi), PARAMETER :: M3N3FAGzi = 3180 + INTEGER(IntKi), PARAMETER :: M3N4FAGzi = 3181 + INTEGER(IntKi), PARAMETER :: M3N5FAGzi = 3182 + INTEGER(IntKi), PARAMETER :: M3N6FAGzi = 3183 + INTEGER(IntKi), PARAMETER :: M3N7FAGzi = 3184 + INTEGER(IntKi), PARAMETER :: M3N8FAGzi = 3185 + INTEGER(IntKi), PARAMETER :: M3N9FAGzi = 3186 + INTEGER(IntKi), PARAMETER :: M4N1FAGzi = 3187 + INTEGER(IntKi), PARAMETER :: M4N2FAGzi = 3188 + INTEGER(IntKi), PARAMETER :: M4N3FAGzi = 3189 + INTEGER(IntKi), PARAMETER :: M4N4FAGzi = 3190 + INTEGER(IntKi), PARAMETER :: M4N5FAGzi = 3191 + INTEGER(IntKi), PARAMETER :: M4N6FAGzi = 3192 + INTEGER(IntKi), PARAMETER :: M4N7FAGzi = 3193 + INTEGER(IntKi), PARAMETER :: M4N8FAGzi = 3194 + INTEGER(IntKi), PARAMETER :: M4N9FAGzi = 3195 + INTEGER(IntKi), PARAMETER :: M5N1FAGzi = 3196 + INTEGER(IntKi), PARAMETER :: M5N2FAGzi = 3197 + INTEGER(IntKi), PARAMETER :: M5N3FAGzi = 3198 + INTEGER(IntKi), PARAMETER :: M5N4FAGzi = 3199 + INTEGER(IntKi), PARAMETER :: M5N5FAGzi = 3200 + INTEGER(IntKi), PARAMETER :: M5N6FAGzi = 3201 + INTEGER(IntKi), PARAMETER :: M5N7FAGzi = 3202 + INTEGER(IntKi), PARAMETER :: M5N8FAGzi = 3203 + INTEGER(IntKi), PARAMETER :: M5N9FAGzi = 3204 + INTEGER(IntKi), PARAMETER :: M6N1FAGzi = 3205 + INTEGER(IntKi), PARAMETER :: M6N2FAGzi = 3206 + INTEGER(IntKi), PARAMETER :: M6N3FAGzi = 3207 + INTEGER(IntKi), PARAMETER :: M6N4FAGzi = 3208 + INTEGER(IntKi), PARAMETER :: M6N5FAGzi = 3209 + INTEGER(IntKi), PARAMETER :: M6N6FAGzi = 3210 + INTEGER(IntKi), PARAMETER :: M6N7FAGzi = 3211 + INTEGER(IntKi), PARAMETER :: M6N8FAGzi = 3212 + INTEGER(IntKi), PARAMETER :: M6N9FAGzi = 3213 + INTEGER(IntKi), PARAMETER :: M7N1FAGzi = 3214 + INTEGER(IntKi), PARAMETER :: M7N2FAGzi = 3215 + INTEGER(IntKi), PARAMETER :: M7N3FAGzi = 3216 + INTEGER(IntKi), PARAMETER :: M7N4FAGzi = 3217 + INTEGER(IntKi), PARAMETER :: M7N5FAGzi = 3218 + INTEGER(IntKi), PARAMETER :: M7N6FAGzi = 3219 + INTEGER(IntKi), PARAMETER :: M7N7FAGzi = 3220 + INTEGER(IntKi), PARAMETER :: M7N8FAGzi = 3221 + INTEGER(IntKi), PARAMETER :: M7N9FAGzi = 3222 + INTEGER(IntKi), PARAMETER :: M8N1FAGzi = 3223 + INTEGER(IntKi), PARAMETER :: M8N2FAGzi = 3224 + INTEGER(IntKi), PARAMETER :: M8N3FAGzi = 3225 + INTEGER(IntKi), PARAMETER :: M8N4FAGzi = 3226 + INTEGER(IntKi), PARAMETER :: M8N5FAGzi = 3227 + INTEGER(IntKi), PARAMETER :: M8N6FAGzi = 3228 + INTEGER(IntKi), PARAMETER :: M8N7FAGzi = 3229 + INTEGER(IntKi), PARAMETER :: M8N8FAGzi = 3230 + INTEGER(IntKi), PARAMETER :: M8N9FAGzi = 3231 + INTEGER(IntKi), PARAMETER :: M9N1FAGzi = 3232 + INTEGER(IntKi), PARAMETER :: M9N2FAGzi = 3233 + INTEGER(IntKi), PARAMETER :: M9N3FAGzi = 3234 + INTEGER(IntKi), PARAMETER :: M9N4FAGzi = 3235 + INTEGER(IntKi), PARAMETER :: M9N5FAGzi = 3236 + INTEGER(IntKi), PARAMETER :: M9N6FAGzi = 3237 + INTEGER(IntKi), PARAMETER :: M9N7FAGzi = 3238 + INTEGER(IntKi), PARAMETER :: M9N8FAGzi = 3239 + INTEGER(IntKi), PARAMETER :: M9N9FAGzi = 3240 + INTEGER(IntKi), PARAMETER :: M1N1FAFxi = 3241 + INTEGER(IntKi), PARAMETER :: M1N2FAFxi = 3242 + INTEGER(IntKi), PARAMETER :: M1N3FAFxi = 3243 + INTEGER(IntKi), PARAMETER :: M1N4FAFxi = 3244 + INTEGER(IntKi), PARAMETER :: M1N5FAFxi = 3245 + INTEGER(IntKi), PARAMETER :: M1N6FAFxi = 3246 + INTEGER(IntKi), PARAMETER :: M1N7FAFxi = 3247 + INTEGER(IntKi), PARAMETER :: M1N8FAFxi = 3248 + INTEGER(IntKi), PARAMETER :: M1N9FAFxi = 3249 + INTEGER(IntKi), PARAMETER :: M2N1FAFxi = 3250 + INTEGER(IntKi), PARAMETER :: M2N2FAFxi = 3251 + INTEGER(IntKi), PARAMETER :: M2N3FAFxi = 3252 + INTEGER(IntKi), PARAMETER :: M2N4FAFxi = 3253 + INTEGER(IntKi), PARAMETER :: M2N5FAFxi = 3254 + INTEGER(IntKi), PARAMETER :: M2N6FAFxi = 3255 + INTEGER(IntKi), PARAMETER :: M2N7FAFxi = 3256 + INTEGER(IntKi), PARAMETER :: M2N8FAFxi = 3257 + INTEGER(IntKi), PARAMETER :: M2N9FAFxi = 3258 + INTEGER(IntKi), PARAMETER :: M3N1FAFxi = 3259 + INTEGER(IntKi), PARAMETER :: M3N2FAFxi = 3260 + INTEGER(IntKi), PARAMETER :: M3N3FAFxi = 3261 + INTEGER(IntKi), PARAMETER :: M3N4FAFxi = 3262 + INTEGER(IntKi), PARAMETER :: M3N5FAFxi = 3263 + INTEGER(IntKi), PARAMETER :: M3N6FAFxi = 3264 + INTEGER(IntKi), PARAMETER :: M3N7FAFxi = 3265 + INTEGER(IntKi), PARAMETER :: M3N8FAFxi = 3266 + INTEGER(IntKi), PARAMETER :: M3N9FAFxi = 3267 + INTEGER(IntKi), PARAMETER :: M4N1FAFxi = 3268 + INTEGER(IntKi), PARAMETER :: M4N2FAFxi = 3269 + INTEGER(IntKi), PARAMETER :: M4N3FAFxi = 3270 + INTEGER(IntKi), PARAMETER :: M4N4FAFxi = 3271 + INTEGER(IntKi), PARAMETER :: M4N5FAFxi = 3272 + INTEGER(IntKi), PARAMETER :: M4N6FAFxi = 3273 + INTEGER(IntKi), PARAMETER :: M4N7FAFxi = 3274 + INTEGER(IntKi), PARAMETER :: M4N8FAFxi = 3275 + INTEGER(IntKi), PARAMETER :: M4N9FAFxi = 3276 + INTEGER(IntKi), PARAMETER :: M5N1FAFxi = 3277 + INTEGER(IntKi), PARAMETER :: M5N2FAFxi = 3278 + INTEGER(IntKi), PARAMETER :: M5N3FAFxi = 3279 + INTEGER(IntKi), PARAMETER :: M5N4FAFxi = 3280 + INTEGER(IntKi), PARAMETER :: M5N5FAFxi = 3281 + INTEGER(IntKi), PARAMETER :: M5N6FAFxi = 3282 + INTEGER(IntKi), PARAMETER :: M5N7FAFxi = 3283 + INTEGER(IntKi), PARAMETER :: M5N8FAFxi = 3284 + INTEGER(IntKi), PARAMETER :: M5N9FAFxi = 3285 + INTEGER(IntKi), PARAMETER :: M6N1FAFxi = 3286 + INTEGER(IntKi), PARAMETER :: M6N2FAFxi = 3287 + INTEGER(IntKi), PARAMETER :: M6N3FAFxi = 3288 + INTEGER(IntKi), PARAMETER :: M6N4FAFxi = 3289 + INTEGER(IntKi), PARAMETER :: M6N5FAFxi = 3290 + INTEGER(IntKi), PARAMETER :: M6N6FAFxi = 3291 + INTEGER(IntKi), PARAMETER :: M6N7FAFxi = 3292 + INTEGER(IntKi), PARAMETER :: M6N8FAFxi = 3293 + INTEGER(IntKi), PARAMETER :: M6N9FAFxi = 3294 + INTEGER(IntKi), PARAMETER :: M7N1FAFxi = 3295 + INTEGER(IntKi), PARAMETER :: M7N2FAFxi = 3296 + INTEGER(IntKi), PARAMETER :: M7N3FAFxi = 3297 + INTEGER(IntKi), PARAMETER :: M7N4FAFxi = 3298 + INTEGER(IntKi), PARAMETER :: M7N5FAFxi = 3299 + INTEGER(IntKi), PARAMETER :: M7N6FAFxi = 3300 + INTEGER(IntKi), PARAMETER :: M7N7FAFxi = 3301 + INTEGER(IntKi), PARAMETER :: M7N8FAFxi = 3302 + INTEGER(IntKi), PARAMETER :: M7N9FAFxi = 3303 + INTEGER(IntKi), PARAMETER :: M8N1FAFxi = 3304 + INTEGER(IntKi), PARAMETER :: M8N2FAFxi = 3305 + INTEGER(IntKi), PARAMETER :: M8N3FAFxi = 3306 + INTEGER(IntKi), PARAMETER :: M8N4FAFxi = 3307 + INTEGER(IntKi), PARAMETER :: M8N5FAFxi = 3308 + INTEGER(IntKi), PARAMETER :: M8N6FAFxi = 3309 + INTEGER(IntKi), PARAMETER :: M8N7FAFxi = 3310 + INTEGER(IntKi), PARAMETER :: M8N8FAFxi = 3311 + INTEGER(IntKi), PARAMETER :: M8N9FAFxi = 3312 + INTEGER(IntKi), PARAMETER :: M9N1FAFxi = 3313 + INTEGER(IntKi), PARAMETER :: M9N2FAFxi = 3314 + INTEGER(IntKi), PARAMETER :: M9N3FAFxi = 3315 + INTEGER(IntKi), PARAMETER :: M9N4FAFxi = 3316 + INTEGER(IntKi), PARAMETER :: M9N5FAFxi = 3317 + INTEGER(IntKi), PARAMETER :: M9N6FAFxi = 3318 + INTEGER(IntKi), PARAMETER :: M9N7FAFxi = 3319 + INTEGER(IntKi), PARAMETER :: M9N8FAFxi = 3320 + INTEGER(IntKi), PARAMETER :: M9N9FAFxi = 3321 + INTEGER(IntKi), PARAMETER :: M1N1FAFyi = 3322 + INTEGER(IntKi), PARAMETER :: M1N2FAFyi = 3323 + INTEGER(IntKi), PARAMETER :: M1N3FAFyi = 3324 + INTEGER(IntKi), PARAMETER :: M1N4FAFyi = 3325 + INTEGER(IntKi), PARAMETER :: M1N5FAFyi = 3326 + INTEGER(IntKi), PARAMETER :: M1N6FAFyi = 3327 + INTEGER(IntKi), PARAMETER :: M1N7FAFyi = 3328 + INTEGER(IntKi), PARAMETER :: M1N8FAFyi = 3329 + INTEGER(IntKi), PARAMETER :: M1N9FAFyi = 3330 + INTEGER(IntKi), PARAMETER :: M2N1FAFyi = 3331 + INTEGER(IntKi), PARAMETER :: M2N2FAFyi = 3332 + INTEGER(IntKi), PARAMETER :: M2N3FAFyi = 3333 + INTEGER(IntKi), PARAMETER :: M2N4FAFyi = 3334 + INTEGER(IntKi), PARAMETER :: M2N5FAFyi = 3335 + INTEGER(IntKi), PARAMETER :: M2N6FAFyi = 3336 + INTEGER(IntKi), PARAMETER :: M2N7FAFyi = 3337 + INTEGER(IntKi), PARAMETER :: M2N8FAFyi = 3338 + INTEGER(IntKi), PARAMETER :: M2N9FAFyi = 3339 + INTEGER(IntKi), PARAMETER :: M3N1FAFyi = 3340 + INTEGER(IntKi), PARAMETER :: M3N2FAFyi = 3341 + INTEGER(IntKi), PARAMETER :: M3N3FAFyi = 3342 + INTEGER(IntKi), PARAMETER :: M3N4FAFyi = 3343 + INTEGER(IntKi), PARAMETER :: M3N5FAFyi = 3344 + INTEGER(IntKi), PARAMETER :: M3N6FAFyi = 3345 + INTEGER(IntKi), PARAMETER :: M3N7FAFyi = 3346 + INTEGER(IntKi), PARAMETER :: M3N8FAFyi = 3347 + INTEGER(IntKi), PARAMETER :: M3N9FAFyi = 3348 + INTEGER(IntKi), PARAMETER :: M4N1FAFyi = 3349 + INTEGER(IntKi), PARAMETER :: M4N2FAFyi = 3350 + INTEGER(IntKi), PARAMETER :: M4N3FAFyi = 3351 + INTEGER(IntKi), PARAMETER :: M4N4FAFyi = 3352 + INTEGER(IntKi), PARAMETER :: M4N5FAFyi = 3353 + INTEGER(IntKi), PARAMETER :: M4N6FAFyi = 3354 + INTEGER(IntKi), PARAMETER :: M4N7FAFyi = 3355 + INTEGER(IntKi), PARAMETER :: M4N8FAFyi = 3356 + INTEGER(IntKi), PARAMETER :: M4N9FAFyi = 3357 + INTEGER(IntKi), PARAMETER :: M5N1FAFyi = 3358 + INTEGER(IntKi), PARAMETER :: M5N2FAFyi = 3359 + INTEGER(IntKi), PARAMETER :: M5N3FAFyi = 3360 + INTEGER(IntKi), PARAMETER :: M5N4FAFyi = 3361 + INTEGER(IntKi), PARAMETER :: M5N5FAFyi = 3362 + INTEGER(IntKi), PARAMETER :: M5N6FAFyi = 3363 + INTEGER(IntKi), PARAMETER :: M5N7FAFyi = 3364 + INTEGER(IntKi), PARAMETER :: M5N8FAFyi = 3365 + INTEGER(IntKi), PARAMETER :: M5N9FAFyi = 3366 + INTEGER(IntKi), PARAMETER :: M6N1FAFyi = 3367 + INTEGER(IntKi), PARAMETER :: M6N2FAFyi = 3368 + INTEGER(IntKi), PARAMETER :: M6N3FAFyi = 3369 + INTEGER(IntKi), PARAMETER :: M6N4FAFyi = 3370 + INTEGER(IntKi), PARAMETER :: M6N5FAFyi = 3371 + INTEGER(IntKi), PARAMETER :: M6N6FAFyi = 3372 + INTEGER(IntKi), PARAMETER :: M6N7FAFyi = 3373 + INTEGER(IntKi), PARAMETER :: M6N8FAFyi = 3374 + INTEGER(IntKi), PARAMETER :: M6N9FAFyi = 3375 + INTEGER(IntKi), PARAMETER :: M7N1FAFyi = 3376 + INTEGER(IntKi), PARAMETER :: M7N2FAFyi = 3377 + INTEGER(IntKi), PARAMETER :: M7N3FAFyi = 3378 + INTEGER(IntKi), PARAMETER :: M7N4FAFyi = 3379 + INTEGER(IntKi), PARAMETER :: M7N5FAFyi = 3380 + INTEGER(IntKi), PARAMETER :: M7N6FAFyi = 3381 + INTEGER(IntKi), PARAMETER :: M7N7FAFyi = 3382 + INTEGER(IntKi), PARAMETER :: M7N8FAFyi = 3383 + INTEGER(IntKi), PARAMETER :: M7N9FAFyi = 3384 + INTEGER(IntKi), PARAMETER :: M8N1FAFyi = 3385 + INTEGER(IntKi), PARAMETER :: M8N2FAFyi = 3386 + INTEGER(IntKi), PARAMETER :: M8N3FAFyi = 3387 + INTEGER(IntKi), PARAMETER :: M8N4FAFyi = 3388 + INTEGER(IntKi), PARAMETER :: M8N5FAFyi = 3389 + INTEGER(IntKi), PARAMETER :: M8N6FAFyi = 3390 + INTEGER(IntKi), PARAMETER :: M8N7FAFyi = 3391 + INTEGER(IntKi), PARAMETER :: M8N8FAFyi = 3392 + INTEGER(IntKi), PARAMETER :: M8N9FAFyi = 3393 + INTEGER(IntKi), PARAMETER :: M9N1FAFyi = 3394 + INTEGER(IntKi), PARAMETER :: M9N2FAFyi = 3395 + INTEGER(IntKi), PARAMETER :: M9N3FAFyi = 3396 + INTEGER(IntKi), PARAMETER :: M9N4FAFyi = 3397 + INTEGER(IntKi), PARAMETER :: M9N5FAFyi = 3398 + INTEGER(IntKi), PARAMETER :: M9N6FAFyi = 3399 + INTEGER(IntKi), PARAMETER :: M9N7FAFyi = 3400 + INTEGER(IntKi), PARAMETER :: M9N8FAFyi = 3401 + INTEGER(IntKi), PARAMETER :: M9N9FAFyi = 3402 + INTEGER(IntKi), PARAMETER :: M1N1FAFzi = 3403 + INTEGER(IntKi), PARAMETER :: M1N2FAFzi = 3404 + INTEGER(IntKi), PARAMETER :: M1N3FAFzi = 3405 + INTEGER(IntKi), PARAMETER :: M1N4FAFzi = 3406 + INTEGER(IntKi), PARAMETER :: M1N5FAFzi = 3407 + INTEGER(IntKi), PARAMETER :: M1N6FAFzi = 3408 + INTEGER(IntKi), PARAMETER :: M1N7FAFzi = 3409 + INTEGER(IntKi), PARAMETER :: M1N8FAFzi = 3410 + INTEGER(IntKi), PARAMETER :: M1N9FAFzi = 3411 + INTEGER(IntKi), PARAMETER :: M2N1FAFzi = 3412 + INTEGER(IntKi), PARAMETER :: M2N2FAFzi = 3413 + INTEGER(IntKi), PARAMETER :: M2N3FAFzi = 3414 + INTEGER(IntKi), PARAMETER :: M2N4FAFzi = 3415 + INTEGER(IntKi), PARAMETER :: M2N5FAFzi = 3416 + INTEGER(IntKi), PARAMETER :: M2N6FAFzi = 3417 + INTEGER(IntKi), PARAMETER :: M2N7FAFzi = 3418 + INTEGER(IntKi), PARAMETER :: M2N8FAFzi = 3419 + INTEGER(IntKi), PARAMETER :: M2N9FAFzi = 3420 + INTEGER(IntKi), PARAMETER :: M3N1FAFzi = 3421 + INTEGER(IntKi), PARAMETER :: M3N2FAFzi = 3422 + INTEGER(IntKi), PARAMETER :: M3N3FAFzi = 3423 + INTEGER(IntKi), PARAMETER :: M3N4FAFzi = 3424 + INTEGER(IntKi), PARAMETER :: M3N5FAFzi = 3425 + INTEGER(IntKi), PARAMETER :: M3N6FAFzi = 3426 + INTEGER(IntKi), PARAMETER :: M3N7FAFzi = 3427 + INTEGER(IntKi), PARAMETER :: M3N8FAFzi = 3428 + INTEGER(IntKi), PARAMETER :: M3N9FAFzi = 3429 + INTEGER(IntKi), PARAMETER :: M4N1FAFzi = 3430 + INTEGER(IntKi), PARAMETER :: M4N2FAFzi = 3431 + INTEGER(IntKi), PARAMETER :: M4N3FAFzi = 3432 + INTEGER(IntKi), PARAMETER :: M4N4FAFzi = 3433 + INTEGER(IntKi), PARAMETER :: M4N5FAFzi = 3434 + INTEGER(IntKi), PARAMETER :: M4N6FAFzi = 3435 + INTEGER(IntKi), PARAMETER :: M4N7FAFzi = 3436 + INTEGER(IntKi), PARAMETER :: M4N8FAFzi = 3437 + INTEGER(IntKi), PARAMETER :: M4N9FAFzi = 3438 + INTEGER(IntKi), PARAMETER :: M5N1FAFzi = 3439 + INTEGER(IntKi), PARAMETER :: M5N2FAFzi = 3440 + INTEGER(IntKi), PARAMETER :: M5N3FAFzi = 3441 + INTEGER(IntKi), PARAMETER :: M5N4FAFzi = 3442 + INTEGER(IntKi), PARAMETER :: M5N5FAFzi = 3443 + INTEGER(IntKi), PARAMETER :: M5N6FAFzi = 3444 + INTEGER(IntKi), PARAMETER :: M5N7FAFzi = 3445 + INTEGER(IntKi), PARAMETER :: M5N8FAFzi = 3446 + INTEGER(IntKi), PARAMETER :: M5N9FAFzi = 3447 + INTEGER(IntKi), PARAMETER :: M6N1FAFzi = 3448 + INTEGER(IntKi), PARAMETER :: M6N2FAFzi = 3449 + INTEGER(IntKi), PARAMETER :: M6N3FAFzi = 3450 + INTEGER(IntKi), PARAMETER :: M6N4FAFzi = 3451 + INTEGER(IntKi), PARAMETER :: M6N5FAFzi = 3452 + INTEGER(IntKi), PARAMETER :: M6N6FAFzi = 3453 + INTEGER(IntKi), PARAMETER :: M6N7FAFzi = 3454 + INTEGER(IntKi), PARAMETER :: M6N8FAFzi = 3455 + INTEGER(IntKi), PARAMETER :: M6N9FAFzi = 3456 + INTEGER(IntKi), PARAMETER :: M7N1FAFzi = 3457 + INTEGER(IntKi), PARAMETER :: M7N2FAFzi = 3458 + INTEGER(IntKi), PARAMETER :: M7N3FAFzi = 3459 + INTEGER(IntKi), PARAMETER :: M7N4FAFzi = 3460 + INTEGER(IntKi), PARAMETER :: M7N5FAFzi = 3461 + INTEGER(IntKi), PARAMETER :: M7N6FAFzi = 3462 + INTEGER(IntKi), PARAMETER :: M7N7FAFzi = 3463 + INTEGER(IntKi), PARAMETER :: M7N8FAFzi = 3464 + INTEGER(IntKi), PARAMETER :: M7N9FAFzi = 3465 + INTEGER(IntKi), PARAMETER :: M8N1FAFzi = 3466 + INTEGER(IntKi), PARAMETER :: M8N2FAFzi = 3467 + INTEGER(IntKi), PARAMETER :: M8N3FAFzi = 3468 + INTEGER(IntKi), PARAMETER :: M8N4FAFzi = 3469 + INTEGER(IntKi), PARAMETER :: M8N5FAFzi = 3470 + INTEGER(IntKi), PARAMETER :: M8N6FAFzi = 3471 + INTEGER(IntKi), PARAMETER :: M8N7FAFzi = 3472 + INTEGER(IntKi), PARAMETER :: M8N8FAFzi = 3473 + INTEGER(IntKi), PARAMETER :: M8N9FAFzi = 3474 + INTEGER(IntKi), PARAMETER :: M9N1FAFzi = 3475 + INTEGER(IntKi), PARAMETER :: M9N2FAFzi = 3476 + INTEGER(IntKi), PARAMETER :: M9N3FAFzi = 3477 + INTEGER(IntKi), PARAMETER :: M9N4FAFzi = 3478 + INTEGER(IntKi), PARAMETER :: M9N5FAFzi = 3479 + INTEGER(IntKi), PARAMETER :: M9N6FAFzi = 3480 + INTEGER(IntKi), PARAMETER :: M9N7FAFzi = 3481 + INTEGER(IntKi), PARAMETER :: M9N8FAFzi = 3482 + INTEGER(IntKi), PARAMETER :: M9N9FAFzi = 3483 + INTEGER(IntKi), PARAMETER :: M1N1FAxi = 3484 + INTEGER(IntKi), PARAMETER :: M1N2FAxi = 3485 + INTEGER(IntKi), PARAMETER :: M1N3FAxi = 3486 + INTEGER(IntKi), PARAMETER :: M1N4FAxi = 3487 + INTEGER(IntKi), PARAMETER :: M1N5FAxi = 3488 + INTEGER(IntKi), PARAMETER :: M1N6FAxi = 3489 + INTEGER(IntKi), PARAMETER :: M1N7FAxi = 3490 + INTEGER(IntKi), PARAMETER :: M1N8FAxi = 3491 + INTEGER(IntKi), PARAMETER :: M1N9FAxi = 3492 + INTEGER(IntKi), PARAMETER :: M2N1FAxi = 3493 + INTEGER(IntKi), PARAMETER :: M2N2FAxi = 3494 + INTEGER(IntKi), PARAMETER :: M2N3FAxi = 3495 + INTEGER(IntKi), PARAMETER :: M2N4FAxi = 3496 + INTEGER(IntKi), PARAMETER :: M2N5FAxi = 3497 + INTEGER(IntKi), PARAMETER :: M2N6FAxi = 3498 + INTEGER(IntKi), PARAMETER :: M2N7FAxi = 3499 + INTEGER(IntKi), PARAMETER :: M2N8FAxi = 3500 + INTEGER(IntKi), PARAMETER :: M2N9FAxi = 3501 + INTEGER(IntKi), PARAMETER :: M3N1FAxi = 3502 + INTEGER(IntKi), PARAMETER :: M3N2FAxi = 3503 + INTEGER(IntKi), PARAMETER :: M3N3FAxi = 3504 + INTEGER(IntKi), PARAMETER :: M3N4FAxi = 3505 + INTEGER(IntKi), PARAMETER :: M3N5FAxi = 3506 + INTEGER(IntKi), PARAMETER :: M3N6FAxi = 3507 + INTEGER(IntKi), PARAMETER :: M3N7FAxi = 3508 + INTEGER(IntKi), PARAMETER :: M3N8FAxi = 3509 + INTEGER(IntKi), PARAMETER :: M3N9FAxi = 3510 + INTEGER(IntKi), PARAMETER :: M4N1FAxi = 3511 + INTEGER(IntKi), PARAMETER :: M4N2FAxi = 3512 + INTEGER(IntKi), PARAMETER :: M4N3FAxi = 3513 + INTEGER(IntKi), PARAMETER :: M4N4FAxi = 3514 + INTEGER(IntKi), PARAMETER :: M4N5FAxi = 3515 + INTEGER(IntKi), PARAMETER :: M4N6FAxi = 3516 + INTEGER(IntKi), PARAMETER :: M4N7FAxi = 3517 + INTEGER(IntKi), PARAMETER :: M4N8FAxi = 3518 + INTEGER(IntKi), PARAMETER :: M4N9FAxi = 3519 + INTEGER(IntKi), PARAMETER :: M5N1FAxi = 3520 + INTEGER(IntKi), PARAMETER :: M5N2FAxi = 3521 + INTEGER(IntKi), PARAMETER :: M5N3FAxi = 3522 + INTEGER(IntKi), PARAMETER :: M5N4FAxi = 3523 + INTEGER(IntKi), PARAMETER :: M5N5FAxi = 3524 + INTEGER(IntKi), PARAMETER :: M5N6FAxi = 3525 + INTEGER(IntKi), PARAMETER :: M5N7FAxi = 3526 + INTEGER(IntKi), PARAMETER :: M5N8FAxi = 3527 + INTEGER(IntKi), PARAMETER :: M5N9FAxi = 3528 + INTEGER(IntKi), PARAMETER :: M6N1FAxi = 3529 + INTEGER(IntKi), PARAMETER :: M6N2FAxi = 3530 + INTEGER(IntKi), PARAMETER :: M6N3FAxi = 3531 + INTEGER(IntKi), PARAMETER :: M6N4FAxi = 3532 + INTEGER(IntKi), PARAMETER :: M6N5FAxi = 3533 + INTEGER(IntKi), PARAMETER :: M6N6FAxi = 3534 + INTEGER(IntKi), PARAMETER :: M6N7FAxi = 3535 + INTEGER(IntKi), PARAMETER :: M6N8FAxi = 3536 + INTEGER(IntKi), PARAMETER :: M6N9FAxi = 3537 + INTEGER(IntKi), PARAMETER :: M7N1FAxi = 3538 + INTEGER(IntKi), PARAMETER :: M7N2FAxi = 3539 + INTEGER(IntKi), PARAMETER :: M7N3FAxi = 3540 + INTEGER(IntKi), PARAMETER :: M7N4FAxi = 3541 + INTEGER(IntKi), PARAMETER :: M7N5FAxi = 3542 + INTEGER(IntKi), PARAMETER :: M7N6FAxi = 3543 + INTEGER(IntKi), PARAMETER :: M7N7FAxi = 3544 + INTEGER(IntKi), PARAMETER :: M7N8FAxi = 3545 + INTEGER(IntKi), PARAMETER :: M7N9FAxi = 3546 + INTEGER(IntKi), PARAMETER :: M8N1FAxi = 3547 + INTEGER(IntKi), PARAMETER :: M8N2FAxi = 3548 + INTEGER(IntKi), PARAMETER :: M8N3FAxi = 3549 + INTEGER(IntKi), PARAMETER :: M8N4FAxi = 3550 + INTEGER(IntKi), PARAMETER :: M8N5FAxi = 3551 + INTEGER(IntKi), PARAMETER :: M8N6FAxi = 3552 + INTEGER(IntKi), PARAMETER :: M8N7FAxi = 3553 + INTEGER(IntKi), PARAMETER :: M8N8FAxi = 3554 + INTEGER(IntKi), PARAMETER :: M8N9FAxi = 3555 + INTEGER(IntKi), PARAMETER :: M9N1FAxi = 3556 + INTEGER(IntKi), PARAMETER :: M9N2FAxi = 3557 + INTEGER(IntKi), PARAMETER :: M9N3FAxi = 3558 + INTEGER(IntKi), PARAMETER :: M9N4FAxi = 3559 + INTEGER(IntKi), PARAMETER :: M9N5FAxi = 3560 + INTEGER(IntKi), PARAMETER :: M9N6FAxi = 3561 + INTEGER(IntKi), PARAMETER :: M9N7FAxi = 3562 + INTEGER(IntKi), PARAMETER :: M9N8FAxi = 3563 + INTEGER(IntKi), PARAMETER :: M9N9FAxi = 3564 + INTEGER(IntKi), PARAMETER :: M1N1FAyi = 3565 + INTEGER(IntKi), PARAMETER :: M1N2FAyi = 3566 + INTEGER(IntKi), PARAMETER :: M1N3FAyi = 3567 + INTEGER(IntKi), PARAMETER :: M1N4FAyi = 3568 + INTEGER(IntKi), PARAMETER :: M1N5FAyi = 3569 + INTEGER(IntKi), PARAMETER :: M1N6FAyi = 3570 + INTEGER(IntKi), PARAMETER :: M1N7FAyi = 3571 + INTEGER(IntKi), PARAMETER :: M1N8FAyi = 3572 + INTEGER(IntKi), PARAMETER :: M1N9FAyi = 3573 + INTEGER(IntKi), PARAMETER :: M2N1FAyi = 3574 + INTEGER(IntKi), PARAMETER :: M2N2FAyi = 3575 + INTEGER(IntKi), PARAMETER :: M2N3FAyi = 3576 + INTEGER(IntKi), PARAMETER :: M2N4FAyi = 3577 + INTEGER(IntKi), PARAMETER :: M2N5FAyi = 3578 + INTEGER(IntKi), PARAMETER :: M2N6FAyi = 3579 + INTEGER(IntKi), PARAMETER :: M2N7FAyi = 3580 + INTEGER(IntKi), PARAMETER :: M2N8FAyi = 3581 + INTEGER(IntKi), PARAMETER :: M2N9FAyi = 3582 + INTEGER(IntKi), PARAMETER :: M3N1FAyi = 3583 + INTEGER(IntKi), PARAMETER :: M3N2FAyi = 3584 + INTEGER(IntKi), PARAMETER :: M3N3FAyi = 3585 + INTEGER(IntKi), PARAMETER :: M3N4FAyi = 3586 + INTEGER(IntKi), PARAMETER :: M3N5FAyi = 3587 + INTEGER(IntKi), PARAMETER :: M3N6FAyi = 3588 + INTEGER(IntKi), PARAMETER :: M3N7FAyi = 3589 + INTEGER(IntKi), PARAMETER :: M3N8FAyi = 3590 + INTEGER(IntKi), PARAMETER :: M3N9FAyi = 3591 + INTEGER(IntKi), PARAMETER :: M4N1FAyi = 3592 + INTEGER(IntKi), PARAMETER :: M4N2FAyi = 3593 + INTEGER(IntKi), PARAMETER :: M4N3FAyi = 3594 + INTEGER(IntKi), PARAMETER :: M4N4FAyi = 3595 + INTEGER(IntKi), PARAMETER :: M4N5FAyi = 3596 + INTEGER(IntKi), PARAMETER :: M4N6FAyi = 3597 + INTEGER(IntKi), PARAMETER :: M4N7FAyi = 3598 + INTEGER(IntKi), PARAMETER :: M4N8FAyi = 3599 + INTEGER(IntKi), PARAMETER :: M4N9FAyi = 3600 + INTEGER(IntKi), PARAMETER :: M5N1FAyi = 3601 + INTEGER(IntKi), PARAMETER :: M5N2FAyi = 3602 + INTEGER(IntKi), PARAMETER :: M5N3FAyi = 3603 + INTEGER(IntKi), PARAMETER :: M5N4FAyi = 3604 + INTEGER(IntKi), PARAMETER :: M5N5FAyi = 3605 + INTEGER(IntKi), PARAMETER :: M5N6FAyi = 3606 + INTEGER(IntKi), PARAMETER :: M5N7FAyi = 3607 + INTEGER(IntKi), PARAMETER :: M5N8FAyi = 3608 + INTEGER(IntKi), PARAMETER :: M5N9FAyi = 3609 + INTEGER(IntKi), PARAMETER :: M6N1FAyi = 3610 + INTEGER(IntKi), PARAMETER :: M6N2FAyi = 3611 + INTEGER(IntKi), PARAMETER :: M6N3FAyi = 3612 + INTEGER(IntKi), PARAMETER :: M6N4FAyi = 3613 + INTEGER(IntKi), PARAMETER :: M6N5FAyi = 3614 + INTEGER(IntKi), PARAMETER :: M6N6FAyi = 3615 + INTEGER(IntKi), PARAMETER :: M6N7FAyi = 3616 + INTEGER(IntKi), PARAMETER :: M6N8FAyi = 3617 + INTEGER(IntKi), PARAMETER :: M6N9FAyi = 3618 + INTEGER(IntKi), PARAMETER :: M7N1FAyi = 3619 + INTEGER(IntKi), PARAMETER :: M7N2FAyi = 3620 + INTEGER(IntKi), PARAMETER :: M7N3FAyi = 3621 + INTEGER(IntKi), PARAMETER :: M7N4FAyi = 3622 + INTEGER(IntKi), PARAMETER :: M7N5FAyi = 3623 + INTEGER(IntKi), PARAMETER :: M7N6FAyi = 3624 + INTEGER(IntKi), PARAMETER :: M7N7FAyi = 3625 + INTEGER(IntKi), PARAMETER :: M7N8FAyi = 3626 + INTEGER(IntKi), PARAMETER :: M7N9FAyi = 3627 + INTEGER(IntKi), PARAMETER :: M8N1FAyi = 3628 + INTEGER(IntKi), PARAMETER :: M8N2FAyi = 3629 + INTEGER(IntKi), PARAMETER :: M8N3FAyi = 3630 + INTEGER(IntKi), PARAMETER :: M8N4FAyi = 3631 + INTEGER(IntKi), PARAMETER :: M8N5FAyi = 3632 + INTEGER(IntKi), PARAMETER :: M8N6FAyi = 3633 + INTEGER(IntKi), PARAMETER :: M8N7FAyi = 3634 + INTEGER(IntKi), PARAMETER :: M8N8FAyi = 3635 + INTEGER(IntKi), PARAMETER :: M8N9FAyi = 3636 + INTEGER(IntKi), PARAMETER :: M9N1FAyi = 3637 + INTEGER(IntKi), PARAMETER :: M9N2FAyi = 3638 + INTEGER(IntKi), PARAMETER :: M9N3FAyi = 3639 + INTEGER(IntKi), PARAMETER :: M9N4FAyi = 3640 + INTEGER(IntKi), PARAMETER :: M9N5FAyi = 3641 + INTEGER(IntKi), PARAMETER :: M9N6FAyi = 3642 + INTEGER(IntKi), PARAMETER :: M9N7FAyi = 3643 + INTEGER(IntKi), PARAMETER :: M9N8FAyi = 3644 + INTEGER(IntKi), PARAMETER :: M9N9FAyi = 3645 + INTEGER(IntKi), PARAMETER :: M1N1FAzi = 3646 + INTEGER(IntKi), PARAMETER :: M1N2FAzi = 3647 + INTEGER(IntKi), PARAMETER :: M1N3FAzi = 3648 + INTEGER(IntKi), PARAMETER :: M1N4FAzi = 3649 + INTEGER(IntKi), PARAMETER :: M1N5FAzi = 3650 + INTEGER(IntKi), PARAMETER :: M1N6FAzi = 3651 + INTEGER(IntKi), PARAMETER :: M1N7FAzi = 3652 + INTEGER(IntKi), PARAMETER :: M1N8FAzi = 3653 + INTEGER(IntKi), PARAMETER :: M1N9FAzi = 3654 + INTEGER(IntKi), PARAMETER :: M2N1FAzi = 3655 + INTEGER(IntKi), PARAMETER :: M2N2FAzi = 3656 + INTEGER(IntKi), PARAMETER :: M2N3FAzi = 3657 + INTEGER(IntKi), PARAMETER :: M2N4FAzi = 3658 + INTEGER(IntKi), PARAMETER :: M2N5FAzi = 3659 + INTEGER(IntKi), PARAMETER :: M2N6FAzi = 3660 + INTEGER(IntKi), PARAMETER :: M2N7FAzi = 3661 + INTEGER(IntKi), PARAMETER :: M2N8FAzi = 3662 + INTEGER(IntKi), PARAMETER :: M2N9FAzi = 3663 + INTEGER(IntKi), PARAMETER :: M3N1FAzi = 3664 + INTEGER(IntKi), PARAMETER :: M3N2FAzi = 3665 + INTEGER(IntKi), PARAMETER :: M3N3FAzi = 3666 + INTEGER(IntKi), PARAMETER :: M3N4FAzi = 3667 + INTEGER(IntKi), PARAMETER :: M3N5FAzi = 3668 + INTEGER(IntKi), PARAMETER :: M3N6FAzi = 3669 + INTEGER(IntKi), PARAMETER :: M3N7FAzi = 3670 + INTEGER(IntKi), PARAMETER :: M3N8FAzi = 3671 + INTEGER(IntKi), PARAMETER :: M3N9FAzi = 3672 + INTEGER(IntKi), PARAMETER :: M4N1FAzi = 3673 + INTEGER(IntKi), PARAMETER :: M4N2FAzi = 3674 + INTEGER(IntKi), PARAMETER :: M4N3FAzi = 3675 + INTEGER(IntKi), PARAMETER :: M4N4FAzi = 3676 + INTEGER(IntKi), PARAMETER :: M4N5FAzi = 3677 + INTEGER(IntKi), PARAMETER :: M4N6FAzi = 3678 + INTEGER(IntKi), PARAMETER :: M4N7FAzi = 3679 + INTEGER(IntKi), PARAMETER :: M4N8FAzi = 3680 + INTEGER(IntKi), PARAMETER :: M4N9FAzi = 3681 + INTEGER(IntKi), PARAMETER :: M5N1FAzi = 3682 + INTEGER(IntKi), PARAMETER :: M5N2FAzi = 3683 + INTEGER(IntKi), PARAMETER :: M5N3FAzi = 3684 + INTEGER(IntKi), PARAMETER :: M5N4FAzi = 3685 + INTEGER(IntKi), PARAMETER :: M5N5FAzi = 3686 + INTEGER(IntKi), PARAMETER :: M5N6FAzi = 3687 + INTEGER(IntKi), PARAMETER :: M5N7FAzi = 3688 + INTEGER(IntKi), PARAMETER :: M5N8FAzi = 3689 + INTEGER(IntKi), PARAMETER :: M5N9FAzi = 3690 + INTEGER(IntKi), PARAMETER :: M6N1FAzi = 3691 + INTEGER(IntKi), PARAMETER :: M6N2FAzi = 3692 + INTEGER(IntKi), PARAMETER :: M6N3FAzi = 3693 + INTEGER(IntKi), PARAMETER :: M6N4FAzi = 3694 + INTEGER(IntKi), PARAMETER :: M6N5FAzi = 3695 + INTEGER(IntKi), PARAMETER :: M6N6FAzi = 3696 + INTEGER(IntKi), PARAMETER :: M6N7FAzi = 3697 + INTEGER(IntKi), PARAMETER :: M6N8FAzi = 3698 + INTEGER(IntKi), PARAMETER :: M6N9FAzi = 3699 + INTEGER(IntKi), PARAMETER :: M7N1FAzi = 3700 + INTEGER(IntKi), PARAMETER :: M7N2FAzi = 3701 + INTEGER(IntKi), PARAMETER :: M7N3FAzi = 3702 + INTEGER(IntKi), PARAMETER :: M7N4FAzi = 3703 + INTEGER(IntKi), PARAMETER :: M7N5FAzi = 3704 + INTEGER(IntKi), PARAMETER :: M7N6FAzi = 3705 + INTEGER(IntKi), PARAMETER :: M7N7FAzi = 3706 + INTEGER(IntKi), PARAMETER :: M7N8FAzi = 3707 + INTEGER(IntKi), PARAMETER :: M7N9FAzi = 3708 + INTEGER(IntKi), PARAMETER :: M8N1FAzi = 3709 + INTEGER(IntKi), PARAMETER :: M8N2FAzi = 3710 + INTEGER(IntKi), PARAMETER :: M8N3FAzi = 3711 + INTEGER(IntKi), PARAMETER :: M8N4FAzi = 3712 + INTEGER(IntKi), PARAMETER :: M8N5FAzi = 3713 + INTEGER(IntKi), PARAMETER :: M8N6FAzi = 3714 + INTEGER(IntKi), PARAMETER :: M8N7FAzi = 3715 + INTEGER(IntKi), PARAMETER :: M8N8FAzi = 3716 + INTEGER(IntKi), PARAMETER :: M8N9FAzi = 3717 + INTEGER(IntKi), PARAMETER :: M9N1FAzi = 3718 + INTEGER(IntKi), PARAMETER :: M9N2FAzi = 3719 + INTEGER(IntKi), PARAMETER :: M9N3FAzi = 3720 + INTEGER(IntKi), PARAMETER :: M9N4FAzi = 3721 + INTEGER(IntKi), PARAMETER :: M9N5FAzi = 3722 + INTEGER(IntKi), PARAMETER :: M9N6FAzi = 3723 + INTEGER(IntKi), PARAMETER :: M9N7FAzi = 3724 + INTEGER(IntKi), PARAMETER :: M9N8FAzi = 3725 + INTEGER(IntKi), PARAMETER :: M9N9FAzi = 3726 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: J1Vxi = 3727 + INTEGER(IntKi), PARAMETER :: J2Vxi = 3728 + INTEGER(IntKi), PARAMETER :: J3Vxi = 3729 + INTEGER(IntKi), PARAMETER :: J4Vxi = 3730 + INTEGER(IntKi), PARAMETER :: J5Vxi = 3731 + INTEGER(IntKi), PARAMETER :: J6Vxi = 3732 + INTEGER(IntKi), PARAMETER :: J7Vxi = 3733 + INTEGER(IntKi), PARAMETER :: J8Vxi = 3734 + INTEGER(IntKi), PARAMETER :: J9Vxi = 3735 + INTEGER(IntKi), PARAMETER :: J1Vyi = 3736 + INTEGER(IntKi), PARAMETER :: J2Vyi = 3737 + INTEGER(IntKi), PARAMETER :: J3Vyi = 3738 + INTEGER(IntKi), PARAMETER :: J4Vyi = 3739 + INTEGER(IntKi), PARAMETER :: J5Vyi = 3740 + INTEGER(IntKi), PARAMETER :: J6Vyi = 3741 + INTEGER(IntKi), PARAMETER :: J7Vyi = 3742 + INTEGER(IntKi), PARAMETER :: J8Vyi = 3743 + INTEGER(IntKi), PARAMETER :: J9Vyi = 3744 + INTEGER(IntKi), PARAMETER :: J1Vzi = 3745 + INTEGER(IntKi), PARAMETER :: J2Vzi = 3746 + INTEGER(IntKi), PARAMETER :: J3Vzi = 3747 + INTEGER(IntKi), PARAMETER :: J4Vzi = 3748 + INTEGER(IntKi), PARAMETER :: J5Vzi = 3749 + INTEGER(IntKi), PARAMETER :: J6Vzi = 3750 + INTEGER(IntKi), PARAMETER :: J7Vzi = 3751 + INTEGER(IntKi), PARAMETER :: J8Vzi = 3752 + INTEGER(IntKi), PARAMETER :: J9Vzi = 3753 + INTEGER(IntKi), PARAMETER :: J1Axi = 3754 + INTEGER(IntKi), PARAMETER :: J2Axi = 3755 + INTEGER(IntKi), PARAMETER :: J3Axi = 3756 + INTEGER(IntKi), PARAMETER :: J4Axi = 3757 + INTEGER(IntKi), PARAMETER :: J5Axi = 3758 + INTEGER(IntKi), PARAMETER :: J6Axi = 3759 + INTEGER(IntKi), PARAMETER :: J7Axi = 3760 + INTEGER(IntKi), PARAMETER :: J8Axi = 3761 + INTEGER(IntKi), PARAMETER :: J9Axi = 3762 + INTEGER(IntKi), PARAMETER :: J1Ayi = 3763 + INTEGER(IntKi), PARAMETER :: J2Ayi = 3764 + INTEGER(IntKi), PARAMETER :: J3Ayi = 3765 + INTEGER(IntKi), PARAMETER :: J4Ayi = 3766 + INTEGER(IntKi), PARAMETER :: J5Ayi = 3767 + INTEGER(IntKi), PARAMETER :: J6Ayi = 3768 + INTEGER(IntKi), PARAMETER :: J7Ayi = 3769 + INTEGER(IntKi), PARAMETER :: J8Ayi = 3770 + INTEGER(IntKi), PARAMETER :: J9Ayi = 3771 + INTEGER(IntKi), PARAMETER :: J1Azi = 3772 + INTEGER(IntKi), PARAMETER :: J2Azi = 3773 + INTEGER(IntKi), PARAMETER :: J3Azi = 3774 + INTEGER(IntKi), PARAMETER :: J4Azi = 3775 + INTEGER(IntKi), PARAMETER :: J5Azi = 3776 + INTEGER(IntKi), PARAMETER :: J6Azi = 3777 + INTEGER(IntKi), PARAMETER :: J7Azi = 3778 + INTEGER(IntKi), PARAMETER :: J8Azi = 3779 + INTEGER(IntKi), PARAMETER :: J9Azi = 3780 + INTEGER(IntKi), PARAMETER :: J1DynP = 3781 + INTEGER(IntKi), PARAMETER :: J2DynP = 3782 + INTEGER(IntKi), PARAMETER :: J3DynP = 3783 + INTEGER(IntKi), PARAMETER :: J4DynP = 3784 + INTEGER(IntKi), PARAMETER :: J5DynP = 3785 + INTEGER(IntKi), PARAMETER :: J6DynP = 3786 + INTEGER(IntKi), PARAMETER :: J7DynP = 3787 + INTEGER(IntKi), PARAMETER :: J8DynP = 3788 + INTEGER(IntKi), PARAMETER :: J9DynP = 3789 + INTEGER(IntKi), PARAMETER :: J1STVxi = 3790 + INTEGER(IntKi), PARAMETER :: J2STVxi = 3791 + INTEGER(IntKi), PARAMETER :: J3STVxi = 3792 + INTEGER(IntKi), PARAMETER :: J4STVxi = 3793 + INTEGER(IntKi), PARAMETER :: J5STVxi = 3794 + INTEGER(IntKi), PARAMETER :: J6STVxi = 3795 + INTEGER(IntKi), PARAMETER :: J7STVxi = 3796 + INTEGER(IntKi), PARAMETER :: J8STVxi = 3797 + INTEGER(IntKi), PARAMETER :: J9STVxi = 3798 + INTEGER(IntKi), PARAMETER :: J1STVyi = 3799 + INTEGER(IntKi), PARAMETER :: J2STVyi = 3800 + INTEGER(IntKi), PARAMETER :: J3STVyi = 3801 + INTEGER(IntKi), PARAMETER :: J4STVyi = 3802 + INTEGER(IntKi), PARAMETER :: J5STVyi = 3803 + INTEGER(IntKi), PARAMETER :: J6STVyi = 3804 + INTEGER(IntKi), PARAMETER :: J7STVyi = 3805 + INTEGER(IntKi), PARAMETER :: J8STVyi = 3806 + INTEGER(IntKi), PARAMETER :: J9STVyi = 3807 + INTEGER(IntKi), PARAMETER :: J1STVzi = 3808 + INTEGER(IntKi), PARAMETER :: J2STVzi = 3809 + INTEGER(IntKi), PARAMETER :: J3STVzi = 3810 + INTEGER(IntKi), PARAMETER :: J4STVzi = 3811 + INTEGER(IntKi), PARAMETER :: J5STVzi = 3812 + INTEGER(IntKi), PARAMETER :: J6STVzi = 3813 + INTEGER(IntKi), PARAMETER :: J7STVzi = 3814 + INTEGER(IntKi), PARAMETER :: J8STVzi = 3815 + INTEGER(IntKi), PARAMETER :: J9STVzi = 3816 + INTEGER(IntKi), PARAMETER :: J1STAxi = 3817 + INTEGER(IntKi), PARAMETER :: J2STAxi = 3818 + INTEGER(IntKi), PARAMETER :: J3STAxi = 3819 + INTEGER(IntKi), PARAMETER :: J4STAxi = 3820 + INTEGER(IntKi), PARAMETER :: J5STAxi = 3821 + INTEGER(IntKi), PARAMETER :: J6STAxi = 3822 + INTEGER(IntKi), PARAMETER :: J7STAxi = 3823 + INTEGER(IntKi), PARAMETER :: J8STAxi = 3824 + INTEGER(IntKi), PARAMETER :: J9STAxi = 3825 + INTEGER(IntKi), PARAMETER :: J1STAyi = 3826 + INTEGER(IntKi), PARAMETER :: J2STAyi = 3827 + INTEGER(IntKi), PARAMETER :: J3STAyi = 3828 + INTEGER(IntKi), PARAMETER :: J4STAyi = 3829 + INTEGER(IntKi), PARAMETER :: J5STAyi = 3830 + INTEGER(IntKi), PARAMETER :: J6STAyi = 3831 + INTEGER(IntKi), PARAMETER :: J7STAyi = 3832 + INTEGER(IntKi), PARAMETER :: J8STAyi = 3833 + INTEGER(IntKi), PARAMETER :: J9STAyi = 3834 + INTEGER(IntKi), PARAMETER :: J1STAzi = 3835 + INTEGER(IntKi), PARAMETER :: J2STAzi = 3836 + INTEGER(IntKi), PARAMETER :: J3STAzi = 3837 + INTEGER(IntKi), PARAMETER :: J4STAzi = 3838 + INTEGER(IntKi), PARAMETER :: J5STAzi = 3839 + INTEGER(IntKi), PARAMETER :: J6STAzi = 3840 + INTEGER(IntKi), PARAMETER :: J7STAzi = 3841 + INTEGER(IntKi), PARAMETER :: J8STAzi = 3842 + INTEGER(IntKi), PARAMETER :: J9STAzi = 3843 + + + ! Category: + + INTEGER(IntKi), PARAMETER :: J1FDxi = 3844 + INTEGER(IntKi), PARAMETER :: J2FDxi = 3845 + INTEGER(IntKi), PARAMETER :: J3FDxi = 3846 + INTEGER(IntKi), PARAMETER :: J4FDxi = 3847 + INTEGER(IntKi), PARAMETER :: J5FDxi = 3848 + INTEGER(IntKi), PARAMETER :: J6FDxi = 3849 + INTEGER(IntKi), PARAMETER :: J7FDxi = 3850 + INTEGER(IntKi), PARAMETER :: J8FDxi = 3851 + INTEGER(IntKi), PARAMETER :: J9FDxi = 3852 + INTEGER(IntKi), PARAMETER :: J1FDyi = 3853 + INTEGER(IntKi), PARAMETER :: J2FDyi = 3854 + INTEGER(IntKi), PARAMETER :: J3FDyi = 3855 + INTEGER(IntKi), PARAMETER :: J4FDyi = 3856 + INTEGER(IntKi), PARAMETER :: J5FDyi = 3857 + INTEGER(IntKi), PARAMETER :: J6FDyi = 3858 + INTEGER(IntKi), PARAMETER :: J7FDyi = 3859 + INTEGER(IntKi), PARAMETER :: J8FDyi = 3860 + INTEGER(IntKi), PARAMETER :: J9FDyi = 3861 + INTEGER(IntKi), PARAMETER :: J1FDzi = 3862 + INTEGER(IntKi), PARAMETER :: J2FDzi = 3863 + INTEGER(IntKi), PARAMETER :: J3FDzi = 3864 + INTEGER(IntKi), PARAMETER :: J4FDzi = 3865 + INTEGER(IntKi), PARAMETER :: J5FDzi = 3866 + INTEGER(IntKi), PARAMETER :: J6FDzi = 3867 + INTEGER(IntKi), PARAMETER :: J7FDzi = 3868 + INTEGER(IntKi), PARAMETER :: J8FDzi = 3869 + INTEGER(IntKi), PARAMETER :: J9FDzi = 3870 + INTEGER(IntKi), PARAMETER :: J1FBxi = 3871 + INTEGER(IntKi), PARAMETER :: J2FBxi = 3872 + INTEGER(IntKi), PARAMETER :: J3FBxi = 3873 + INTEGER(IntKi), PARAMETER :: J4FBxi = 3874 + INTEGER(IntKi), PARAMETER :: J5FBxi = 3875 + INTEGER(IntKi), PARAMETER :: J6FBxi = 3876 + INTEGER(IntKi), PARAMETER :: J7FBxi = 3877 + INTEGER(IntKi), PARAMETER :: J8FBxi = 3878 + INTEGER(IntKi), PARAMETER :: J9FBxi = 3879 + INTEGER(IntKi), PARAMETER :: J1FByi = 3880 + INTEGER(IntKi), PARAMETER :: J2FByi = 3881 + INTEGER(IntKi), PARAMETER :: J3FByi = 3882 + INTEGER(IntKi), PARAMETER :: J4FByi = 3883 + INTEGER(IntKi), PARAMETER :: J5FByi = 3884 + INTEGER(IntKi), PARAMETER :: J6FByi = 3885 + INTEGER(IntKi), PARAMETER :: J7FByi = 3886 + INTEGER(IntKi), PARAMETER :: J8FByi = 3887 + INTEGER(IntKi), PARAMETER :: J9FByi = 3888 + INTEGER(IntKi), PARAMETER :: J1FBzi = 3889 + INTEGER(IntKi), PARAMETER :: J2FBzi = 3890 + INTEGER(IntKi), PARAMETER :: J3FBzi = 3891 + INTEGER(IntKi), PARAMETER :: J4FBzi = 3892 + INTEGER(IntKi), PARAMETER :: J5FBzi = 3893 + INTEGER(IntKi), PARAMETER :: J6FBzi = 3894 + INTEGER(IntKi), PARAMETER :: J7FBzi = 3895 + INTEGER(IntKi), PARAMETER :: J8FBzi = 3896 + INTEGER(IntKi), PARAMETER :: J9FBzi = 3897 + INTEGER(IntKi), PARAMETER :: J1MBxi = 3898 + INTEGER(IntKi), PARAMETER :: J2MBxi = 3899 + INTEGER(IntKi), PARAMETER :: J3MBxi = 3900 + INTEGER(IntKi), PARAMETER :: J4MBxi = 3901 + INTEGER(IntKi), PARAMETER :: J5MBxi = 3902 + INTEGER(IntKi), PARAMETER :: J6MBxi = 3903 + INTEGER(IntKi), PARAMETER :: J7MBxi = 3904 + INTEGER(IntKi), PARAMETER :: J8MBxi = 3905 + INTEGER(IntKi), PARAMETER :: J9MBxi = 3906 + INTEGER(IntKi), PARAMETER :: J1MByi = 3907 + INTEGER(IntKi), PARAMETER :: J2MByi = 3908 + INTEGER(IntKi), PARAMETER :: J3MByi = 3909 + INTEGER(IntKi), PARAMETER :: J4MByi = 3910 + INTEGER(IntKi), PARAMETER :: J5MByi = 3911 + INTEGER(IntKi), PARAMETER :: J6MByi = 3912 + INTEGER(IntKi), PARAMETER :: J7MByi = 3913 + INTEGER(IntKi), PARAMETER :: J8MByi = 3914 + INTEGER(IntKi), PARAMETER :: J9MByi = 3915 + INTEGER(IntKi), PARAMETER :: J1MBzi = 3916 + INTEGER(IntKi), PARAMETER :: J2MBzi = 3917 + INTEGER(IntKi), PARAMETER :: J3MBzi = 3918 + INTEGER(IntKi), PARAMETER :: J4MBzi = 3919 + INTEGER(IntKi), PARAMETER :: J5MBzi = 3920 + INTEGER(IntKi), PARAMETER :: J6MBzi = 3921 + INTEGER(IntKi), PARAMETER :: J7MBzi = 3922 + INTEGER(IntKi), PARAMETER :: J8MBzi = 3923 + INTEGER(IntKi), PARAMETER :: J9MBzi = 3924 + INTEGER(IntKi), PARAMETER :: J1FBFxi = 3925 + INTEGER(IntKi), PARAMETER :: J2FBFxi = 3926 + INTEGER(IntKi), PARAMETER :: J3FBFxi = 3927 + INTEGER(IntKi), PARAMETER :: J4FBFxi = 3928 + INTEGER(IntKi), PARAMETER :: J5FBFxi = 3929 + INTEGER(IntKi), PARAMETER :: J6FBFxi = 3930 + INTEGER(IntKi), PARAMETER :: J7FBFxi = 3931 + INTEGER(IntKi), PARAMETER :: J8FBFxi = 3932 + INTEGER(IntKi), PARAMETER :: J9FBFxi = 3933 + INTEGER(IntKi), PARAMETER :: J1FBFyi = 3934 + INTEGER(IntKi), PARAMETER :: J2FBFyi = 3935 + INTEGER(IntKi), PARAMETER :: J3FBFyi = 3936 + INTEGER(IntKi), PARAMETER :: J4FBFyi = 3937 + INTEGER(IntKi), PARAMETER :: J5FBFyi = 3938 + INTEGER(IntKi), PARAMETER :: J6FBFyi = 3939 + INTEGER(IntKi), PARAMETER :: J7FBFyi = 3940 + INTEGER(IntKi), PARAMETER :: J8FBFyi = 3941 + INTEGER(IntKi), PARAMETER :: J9FBFyi = 3942 + INTEGER(IntKi), PARAMETER :: J1FBFzi = 3943 + INTEGER(IntKi), PARAMETER :: J2FBFzi = 3944 + INTEGER(IntKi), PARAMETER :: J3FBFzi = 3945 + INTEGER(IntKi), PARAMETER :: J4FBFzi = 3946 + INTEGER(IntKi), PARAMETER :: J5FBFzi = 3947 + INTEGER(IntKi), PARAMETER :: J6FBFzi = 3948 + INTEGER(IntKi), PARAMETER :: J7FBFzi = 3949 + INTEGER(IntKi), PARAMETER :: J8FBFzi = 3950 + INTEGER(IntKi), PARAMETER :: J9FBFzi = 3951 + INTEGER(IntKi), PARAMETER :: J1MBFxi = 3952 + INTEGER(IntKi), PARAMETER :: J2MBFxi = 3953 + INTEGER(IntKi), PARAMETER :: J3MBFxi = 3954 + INTEGER(IntKi), PARAMETER :: J4MBFxi = 3955 + INTEGER(IntKi), PARAMETER :: J5MBFxi = 3956 + INTEGER(IntKi), PARAMETER :: J6MBFxi = 3957 + INTEGER(IntKi), PARAMETER :: J7MBFxi = 3958 + INTEGER(IntKi), PARAMETER :: J8MBFxi = 3959 + INTEGER(IntKi), PARAMETER :: J9MBFxi = 3960 + INTEGER(IntKi), PARAMETER :: J1MBFyi = 3961 + INTEGER(IntKi), PARAMETER :: J2MBFyi = 3962 + INTEGER(IntKi), PARAMETER :: J3MBFyi = 3963 + INTEGER(IntKi), PARAMETER :: J4MBFyi = 3964 + INTEGER(IntKi), PARAMETER :: J5MBFyi = 3965 + INTEGER(IntKi), PARAMETER :: J6MBFyi = 3966 + INTEGER(IntKi), PARAMETER :: J7MBFyi = 3967 + INTEGER(IntKi), PARAMETER :: J8MBFyi = 3968 + INTEGER(IntKi), PARAMETER :: J9MBFyi = 3969 + INTEGER(IntKi), PARAMETER :: J1MBFzi = 3970 + INTEGER(IntKi), PARAMETER :: J2MBFzi = 3971 + INTEGER(IntKi), PARAMETER :: J3MBFzi = 3972 + INTEGER(IntKi), PARAMETER :: J4MBFzi = 3973 + INTEGER(IntKi), PARAMETER :: J5MBFzi = 3974 + INTEGER(IntKi), PARAMETER :: J6MBFzi = 3975 + INTEGER(IntKi), PARAMETER :: J7MBFzi = 3976 + INTEGER(IntKi), PARAMETER :: J8MBFzi = 3977 + INTEGER(IntKi), PARAMETER :: J9MBFzi = 3978 + INTEGER(IntKi), PARAMETER :: J1FIxi = 3979 + INTEGER(IntKi), PARAMETER :: J2FIxi = 3980 + INTEGER(IntKi), PARAMETER :: J3FIxi = 3981 + INTEGER(IntKi), PARAMETER :: J4FIxi = 3982 + INTEGER(IntKi), PARAMETER :: J5FIxi = 3983 + INTEGER(IntKi), PARAMETER :: J6FIxi = 3984 + INTEGER(IntKi), PARAMETER :: J7FIxi = 3985 + INTEGER(IntKi), PARAMETER :: J8FIxi = 3986 + INTEGER(IntKi), PARAMETER :: J9FIxi = 3987 + INTEGER(IntKi), PARAMETER :: J1FIyi = 3988 + INTEGER(IntKi), PARAMETER :: J2FIyi = 3989 + INTEGER(IntKi), PARAMETER :: J3FIyi = 3990 + INTEGER(IntKi), PARAMETER :: J4FIyi = 3991 + INTEGER(IntKi), PARAMETER :: J5FIyi = 3992 + INTEGER(IntKi), PARAMETER :: J6FIyi = 3993 + INTEGER(IntKi), PARAMETER :: J7FIyi = 3994 + INTEGER(IntKi), PARAMETER :: J8FIyi = 3995 + INTEGER(IntKi), PARAMETER :: J9FIyi = 3996 + INTEGER(IntKi), PARAMETER :: J1FIzi = 3997 + INTEGER(IntKi), PARAMETER :: J2FIzi = 3998 + INTEGER(IntKi), PARAMETER :: J3FIzi = 3999 + INTEGER(IntKi), PARAMETER :: J4FIzi = 4000 + INTEGER(IntKi), PARAMETER :: J5FIzi = 4001 + INTEGER(IntKi), PARAMETER :: J6FIzi = 4002 + INTEGER(IntKi), PARAMETER :: J7FIzi = 4003 + INTEGER(IntKi), PARAMETER :: J8FIzi = 4004 + INTEGER(IntKi), PARAMETER :: J9FIzi = 4005 + INTEGER(IntKi), PARAMETER :: J1FAMxi = 4006 + INTEGER(IntKi), PARAMETER :: J2FAMxi = 4007 + INTEGER(IntKi), PARAMETER :: J3FAMxi = 4008 + INTEGER(IntKi), PARAMETER :: J4FAMxi = 4009 + INTEGER(IntKi), PARAMETER :: J5FAMxi = 4010 + INTEGER(IntKi), PARAMETER :: J6FAMxi = 4011 + INTEGER(IntKi), PARAMETER :: J7FAMxi = 4012 + INTEGER(IntKi), PARAMETER :: J8FAMxi = 4013 + INTEGER(IntKi), PARAMETER :: J9FAMxi = 4014 + INTEGER(IntKi), PARAMETER :: J1FAMyi = 4015 + INTEGER(IntKi), PARAMETER :: J2FAMyi = 4016 + INTEGER(IntKi), PARAMETER :: J3FAMyi = 4017 + INTEGER(IntKi), PARAMETER :: J4FAMyi = 4018 + INTEGER(IntKi), PARAMETER :: J5FAMyi = 4019 + INTEGER(IntKi), PARAMETER :: J6FAMyi = 4020 + INTEGER(IntKi), PARAMETER :: J7FAMyi = 4021 + INTEGER(IntKi), PARAMETER :: J8FAMyi = 4022 + INTEGER(IntKi), PARAMETER :: J9FAMyi = 4023 + INTEGER(IntKi), PARAMETER :: J1FAMzi = 4024 + INTEGER(IntKi), PARAMETER :: J2FAMzi = 4025 + INTEGER(IntKi), PARAMETER :: J3FAMzi = 4026 + INTEGER(IntKi), PARAMETER :: J4FAMzi = 4027 + INTEGER(IntKi), PARAMETER :: J5FAMzi = 4028 + INTEGER(IntKi), PARAMETER :: J6FAMzi = 4029 + INTEGER(IntKi), PARAMETER :: J7FAMzi = 4030 + INTEGER(IntKi), PARAMETER :: J8FAMzi = 4031 + INTEGER(IntKi), PARAMETER :: J9FAMzi = 4032 + + +!End of code generated by Matlab script + + !INTEGER, PARAMETER :: WaveElevi(9) = (/Wave1Elev,Wave2Elev,Wave3Elev,Wave4Elev,Wave5Elev,Wave6Elev,Wave7Elev,Wave8Elev,Wave9Elev/) + + INTEGER, PARAMETER :: MNVi(3,9,9) = reshape((/M1N1Vxi,M1N1Vyi,M1N1Vzi, & + M1N2Vxi,M1N2Vyi,M1N2Vzi, & + M1N3Vxi,M1N3Vyi,M1N3Vzi, & + M1N4Vxi,M1N4Vyi,M1N4Vzi, & + M1N5Vxi,M1N5Vyi,M1N5Vzi, & + M1N6Vxi,M1N6Vyi,M1N6Vzi, & + M1N7Vxi,M1N7Vyi,M1N7Vzi, & + M1N8Vxi,M1N8Vyi,M1N8Vzi, & + M1N9Vxi,M1N9Vyi,M1N9Vzi, & + M2N1Vxi,M2N1Vyi,M2N1Vzi, & + M2N2Vxi,M2N2Vyi,M2N2Vzi, & + M2N3Vxi,M2N3Vyi,M2N3Vzi, & + M2N4Vxi,M2N4Vyi,M2N4Vzi, & + M2N5Vxi,M2N5Vyi,M2N5Vzi, & + M2N6Vxi,M2N6Vyi,M2N6Vzi, & + M2N7Vxi,M2N7Vyi,M2N7Vzi, & + M2N8Vxi,M2N8Vyi,M2N8Vzi, & + M2N9Vxi,M2N9Vyi,M2N9Vzi, & + M3N1Vxi,M3N1Vyi,M3N1Vzi, & + M3N2Vxi,M3N2Vyi,M3N2Vzi, & + M3N3Vxi,M3N3Vyi,M3N3Vzi, & + M3N4Vxi,M3N4Vyi,M3N4Vzi, & + M3N5Vxi,M3N5Vyi,M3N5Vzi, & + M3N6Vxi,M3N6Vyi,M3N6Vzi, & + M3N7Vxi,M3N7Vyi,M3N7Vzi, & + M3N8Vxi,M3N8Vyi,M3N8Vzi, & + M3N9Vxi,M3N9Vyi,M3N9Vzi, & + M4N1Vxi,M4N1Vyi,M4N1Vzi, & + M4N2Vxi,M4N2Vyi,M4N2Vzi, & + M4N3Vxi,M4N3Vyi,M4N3Vzi, & + M4N4Vxi,M4N4Vyi,M4N4Vzi, & + M4N5Vxi,M4N5Vyi,M4N5Vzi, & + M4N6Vxi,M4N6Vyi,M4N6Vzi, & + M4N7Vxi,M4N7Vyi,M4N7Vzi, & + M4N8Vxi,M4N8Vyi,M4N8Vzi, & + M4N9Vxi,M4N9Vyi,M4N9Vzi, & + M5N1Vxi,M5N1Vyi,M5N1Vzi, & + M5N2Vxi,M5N2Vyi,M5N2Vzi, & + M5N3Vxi,M5N3Vyi,M5N3Vzi, & + M5N4Vxi,M5N4Vyi,M5N4Vzi, & + M5N5Vxi,M5N5Vyi,M5N5Vzi, & + M5N6Vxi,M5N6Vyi,M5N6Vzi, & + M5N7Vxi,M5N7Vyi,M5N7Vzi, & + M5N8Vxi,M5N8Vyi,M5N8Vzi, & + M5N9Vxi,M5N9Vyi,M5N9Vzi, & + M6N1Vxi,M6N1Vyi,M6N1Vzi, & + M6N2Vxi,M6N2Vyi,M6N2Vzi, & + M6N3Vxi,M6N3Vyi,M6N3Vzi, & + M6N4Vxi,M6N4Vyi,M6N4Vzi, & + M6N5Vxi,M6N5Vyi,M6N5Vzi, & + M6N6Vxi,M6N6Vyi,M6N6Vzi, & + M6N7Vxi,M6N7Vyi,M6N7Vzi, & + M6N8Vxi,M6N8Vyi,M6N8Vzi, & + M6N9Vxi,M6N9Vyi,M6N9Vzi, & + M7N1Vxi,M7N1Vyi,M7N1Vzi, & + M7N2Vxi,M7N2Vyi,M7N2Vzi, & + M7N3Vxi,M7N3Vyi,M7N3Vzi, & + M7N4Vxi,M7N4Vyi,M7N4Vzi, & + M7N5Vxi,M7N5Vyi,M7N5Vzi, & + M7N6Vxi,M7N6Vyi,M7N6Vzi, & + M7N7Vxi,M7N7Vyi,M7N7Vzi, & + M7N8Vxi,M7N8Vyi,M7N8Vzi, & + M7N9Vxi,M7N9Vyi,M7N9Vzi, & + M8N1Vxi,M8N1Vyi,M8N1Vzi, & + M8N2Vxi,M8N2Vyi,M8N2Vzi, & + M8N3Vxi,M8N3Vyi,M8N3Vzi, & + M8N4Vxi,M8N4Vyi,M8N4Vzi, & + M8N5Vxi,M8N5Vyi,M8N5Vzi, & + M8N6Vxi,M8N6Vyi,M8N6Vzi, & + M8N7Vxi,M8N7Vyi,M8N7Vzi, & + M8N8Vxi,M8N8Vyi,M8N8Vzi, & + M8N9Vxi,M8N9Vyi,M8N9Vzi, & + M9N1Vxi,M9N1Vyi,M9N1Vzi, & + M9N2Vxi,M9N2Vyi,M9N2Vzi, & + M9N3Vxi,M9N3Vyi,M9N3Vzi, & + M9N4Vxi,M9N4Vyi,M9N4Vzi, & + M9N5Vxi,M9N5Vyi,M9N5Vzi, & + M9N6Vxi,M9N6Vyi,M9N6Vzi, & + M9N7Vxi,M9N7Vyi,M9N7Vzi, & + M9N8Vxi,M9N8Vyi,M9N8Vzi, & + M9N9Vxi,M9N9Vyi,M9N9Vzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNAi(3,9,9) = reshape((/M1N1Axi,M1N1Ayi,M1N1Azi, & + M1N2Axi,M1N2Ayi,M1N2Azi, & + M1N3Axi,M1N3Ayi,M1N3Azi, & + M1N4Axi,M1N4Ayi,M1N4Azi, & + M1N5Axi,M1N5Ayi,M1N5Azi, & + M1N6Axi,M1N6Ayi,M1N6Azi, & + M1N7Axi,M1N7Ayi,M1N7Azi, & + M1N8Axi,M1N8Ayi,M1N8Azi, & + M1N9Axi,M1N9Ayi,M1N9Azi, & + M2N1Axi,M2N1Ayi,M2N1Azi, & + M2N2Axi,M2N2Ayi,M2N2Azi, & + M2N3Axi,M2N3Ayi,M2N3Azi, & + M2N4Axi,M2N4Ayi,M2N4Azi, & + M2N5Axi,M2N5Ayi,M2N5Azi, & + M2N6Axi,M2N6Ayi,M2N6Azi, & + M2N7Axi,M2N7Ayi,M2N7Azi, & + M2N8Axi,M2N8Ayi,M2N8Azi, & + M2N9Axi,M2N9Ayi,M2N9Azi, & + M3N1Axi,M3N1Ayi,M3N1Azi, & + M3N2Axi,M3N2Ayi,M3N2Azi, & + M3N3Axi,M3N3Ayi,M3N3Azi, & + M3N4Axi,M3N4Ayi,M3N4Azi, & + M3N5Axi,M3N5Ayi,M3N5Azi, & + M3N6Axi,M3N6Ayi,M3N6Azi, & + M3N7Axi,M3N7Ayi,M3N7Azi, & + M3N8Axi,M3N8Ayi,M3N8Azi, & + M3N9Axi,M3N9Ayi,M3N9Azi, & + M4N1Axi,M4N1Ayi,M4N1Azi, & + M4N2Axi,M4N2Ayi,M4N2Azi, & + M4N3Axi,M4N3Ayi,M4N3Azi, & + M4N4Axi,M4N4Ayi,M4N4Azi, & + M4N5Axi,M4N5Ayi,M4N5Azi, & + M4N6Axi,M4N6Ayi,M4N6Azi, & + M4N7Axi,M4N7Ayi,M4N7Azi, & + M4N8Axi,M4N8Ayi,M4N8Azi, & + M4N9Axi,M4N9Ayi,M4N9Azi, & + M5N1Axi,M5N1Ayi,M5N1Azi, & + M5N2Axi,M5N2Ayi,M5N2Azi, & + M5N3Axi,M5N3Ayi,M5N3Azi, & + M5N4Axi,M5N4Ayi,M5N4Azi, & + M5N5Axi,M5N5Ayi,M5N5Azi, & + M5N6Axi,M5N6Ayi,M5N6Azi, & + M5N7Axi,M5N7Ayi,M5N7Azi, & + M5N8Axi,M5N8Ayi,M5N8Azi, & + M5N9Axi,M5N9Ayi,M5N9Azi, & + M6N1Axi,M6N1Ayi,M6N1Azi, & + M6N2Axi,M6N2Ayi,M6N2Azi, & + M6N3Axi,M6N3Ayi,M6N3Azi, & + M6N4Axi,M6N4Ayi,M6N4Azi, & + M6N5Axi,M6N5Ayi,M6N5Azi, & + M6N6Axi,M6N6Ayi,M6N6Azi, & + M6N7Axi,M6N7Ayi,M6N7Azi, & + M6N8Axi,M6N8Ayi,M6N8Azi, & + M6N9Axi,M6N9Ayi,M6N9Azi, & + M7N1Axi,M7N1Ayi,M7N1Azi, & + M7N2Axi,M7N2Ayi,M7N2Azi, & + M7N3Axi,M7N3Ayi,M7N3Azi, & + M7N4Axi,M7N4Ayi,M7N4Azi, & + M7N5Axi,M7N5Ayi,M7N5Azi, & + M7N6Axi,M7N6Ayi,M7N6Azi, & + M7N7Axi,M7N7Ayi,M7N7Azi, & + M7N8Axi,M7N8Ayi,M7N8Azi, & + M7N9Axi,M7N9Ayi,M7N9Azi, & + M8N1Axi,M8N1Ayi,M8N1Azi, & + M8N2Axi,M8N2Ayi,M8N2Azi, & + M8N3Axi,M8N3Ayi,M8N3Azi, & + M8N4Axi,M8N4Ayi,M8N4Azi, & + M8N5Axi,M8N5Ayi,M8N5Azi, & + M8N6Axi,M8N6Ayi,M8N6Azi, & + M8N7Axi,M8N7Ayi,M8N7Azi, & + M8N8Axi,M8N8Ayi,M8N8Azi, & + M8N9Axi,M8N9Ayi,M8N9Azi, & + M9N1Axi,M9N1Ayi,M9N1Azi, & + M9N2Axi,M9N2Ayi,M9N2Azi, & + M9N3Axi,M9N3Ayi,M9N3Azi, & + M9N4Axi,M9N4Ayi,M9N4Azi, & + M9N5Axi,M9N5Ayi,M9N5Azi, & + M9N6Axi,M9N6Ayi,M9N6Azi, & + M9N7Axi,M9N7Ayi,M9N7Azi, & + M9N8Axi,M9N8Ayi,M9N8Azi, & + M9N9Axi,M9N9Ayi,M9N9Azi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNSTVi(3,9,9) = reshape((/M1N1STVxi,M1N1STVyi,M1N1STVzi, & + M1N2STVxi,M1N2STVyi,M1N2STVzi, & + M1N3STVxi,M1N3STVyi,M1N3STVzi, & + M1N4STVxi,M1N4STVyi,M1N4STVzi, & + M1N5STVxi,M1N5STVyi,M1N5STVzi, & + M1N6STVxi,M1N6STVyi,M1N6STVzi, & + M1N7STVxi,M1N7STVyi,M1N7STVzi, & + M1N8STVxi,M1N8STVyi,M1N8STVzi, & + M1N9STVxi,M1N9STVyi,M1N9STVzi, & + M2N1STVxi,M2N1STVyi,M2N1STVzi, & + M2N2STVxi,M2N2STVyi,M2N2STVzi, & + M2N3STVxi,M2N3STVyi,M2N3STVzi, & + M2N4STVxi,M2N4STVyi,M2N4STVzi, & + M2N5STVxi,M2N5STVyi,M2N5STVzi, & + M2N6STVxi,M2N6STVyi,M2N6STVzi, & + M2N7STVxi,M2N7STVyi,M2N7STVzi, & + M2N8STVxi,M2N8STVyi,M2N8STVzi, & + M2N9STVxi,M2N9STVyi,M2N9STVzi, & + M3N1STVxi,M3N1STVyi,M3N1STVzi, & + M3N2STVxi,M3N2STVyi,M3N2STVzi, & + M3N3STVxi,M3N3STVyi,M3N3STVzi, & + M3N4STVxi,M3N4STVyi,M3N4STVzi, & + M3N5STVxi,M3N5STVyi,M3N5STVzi, & + M3N6STVxi,M3N6STVyi,M3N6STVzi, & + M3N7STVxi,M3N7STVyi,M3N7STVzi, & + M3N8STVxi,M3N8STVyi,M3N8STVzi, & + M3N9STVxi,M3N9STVyi,M3N9STVzi, & + M4N1STVxi,M4N1STVyi,M4N1STVzi, & + M4N2STVxi,M4N2STVyi,M4N2STVzi, & + M4N3STVxi,M4N3STVyi,M4N3STVzi, & + M4N4STVxi,M4N4STVyi,M4N4STVzi, & + M4N5STVxi,M4N5STVyi,M4N5STVzi, & + M4N6STVxi,M4N6STVyi,M4N6STVzi, & + M4N7STVxi,M4N7STVyi,M4N7STVzi, & + M4N8STVxi,M4N8STVyi,M4N8STVzi, & + M4N9STVxi,M4N9STVyi,M4N9STVzi, & + M5N1STVxi,M5N1STVyi,M5N1STVzi, & + M5N2STVxi,M5N2STVyi,M5N2STVzi, & + M5N3STVxi,M5N3STVyi,M5N3STVzi, & + M5N4STVxi,M5N4STVyi,M5N4STVzi, & + M5N5STVxi,M5N5STVyi,M5N5STVzi, & + M5N6STVxi,M5N6STVyi,M5N6STVzi, & + M5N7STVxi,M5N7STVyi,M5N7STVzi, & + M5N8STVxi,M5N8STVyi,M5N8STVzi, & + M5N9STVxi,M5N9STVyi,M5N9STVzi, & + M6N1STVxi,M6N1STVyi,M6N1STVzi, & + M6N2STVxi,M6N2STVyi,M6N2STVzi, & + M6N3STVxi,M6N3STVyi,M6N3STVzi, & + M6N4STVxi,M6N4STVyi,M6N4STVzi, & + M6N5STVxi,M6N5STVyi,M6N5STVzi, & + M6N6STVxi,M6N6STVyi,M6N6STVzi, & + M6N7STVxi,M6N7STVyi,M6N7STVzi, & + M6N8STVxi,M6N8STVyi,M6N8STVzi, & + M6N9STVxi,M6N9STVyi,M6N9STVzi, & + M7N1STVxi,M7N1STVyi,M7N1STVzi, & + M7N2STVxi,M7N2STVyi,M7N2STVzi, & + M7N3STVxi,M7N3STVyi,M7N3STVzi, & + M7N4STVxi,M7N4STVyi,M7N4STVzi, & + M7N5STVxi,M7N5STVyi,M7N5STVzi, & + M7N6STVxi,M7N6STVyi,M7N6STVzi, & + M7N7STVxi,M7N7STVyi,M7N7STVzi, & + M7N8STVxi,M7N8STVyi,M7N8STVzi, & + M7N9STVxi,M7N9STVyi,M7N9STVzi, & + M8N1STVxi,M8N1STVyi,M8N1STVzi, & + M8N2STVxi,M8N2STVyi,M8N2STVzi, & + M8N3STVxi,M8N3STVyi,M8N3STVzi, & + M8N4STVxi,M8N4STVyi,M8N4STVzi, & + M8N5STVxi,M8N5STVyi,M8N5STVzi, & + M8N6STVxi,M8N6STVyi,M8N6STVzi, & + M8N7STVxi,M8N7STVyi,M8N7STVzi, & + M8N8STVxi,M8N8STVyi,M8N8STVzi, & + M8N9STVxi,M8N9STVyi,M8N9STVzi, & + M9N1STVxi,M9N1STVyi,M9N1STVzi, & + M9N2STVxi,M9N2STVyi,M9N2STVzi, & + M9N3STVxi,M9N3STVyi,M9N3STVzi, & + M9N4STVxi,M9N4STVyi,M9N4STVzi, & + M9N5STVxi,M9N5STVyi,M9N5STVzi, & + M9N6STVxi,M9N6STVyi,M9N6STVzi, & + M9N7STVxi,M9N7STVyi,M9N7STVzi, & + M9N8STVxi,M9N8STVyi,M9N8STVzi, & + M9N9STVxi,M9N9STVyi,M9N9STVzi/), (/3,9,9/)) + + !INTEGER, PARAMETER :: MNSRVi(3,9,9) = reshape((/M1N1SRVxi,M1N1SRVyi,M1N1SRVzi, & + ! M1N2SRVxi,M1N2SRVyi,M1N2SRVzi, & + ! M1N3SRVxi,M1N3SRVyi,M1N3SRVzi, & + ! M1N4SRVxi,M1N4SRVyi,M1N4SRVzi, & + ! M1N5SRVxi,M1N5SRVyi,M1N5SRVzi, & + ! M1N6SRVxi,M1N6SRVyi,M1N6SRVzi, & + ! M1N7SRVxi,M1N7SRVyi,M1N7SRVzi, & + ! M1N8SRVxi,M1N8SRVyi,M1N8SRVzi, & + ! M1N9SRVxi,M1N9SRVyi,M1N9SRVzi, & + ! M2N1SRVxi,M2N1SRVyi,M2N1SRVzi, & + ! M2N2SRVxi,M2N2SRVyi,M2N2SRVzi, & + ! M2N3SRVxi,M2N3SRVyi,M2N3SRVzi, & + ! M2N4SRVxi,M2N4SRVyi,M2N4SRVzi, & + ! M2N5SRVxi,M2N5SRVyi,M2N5SRVzi, & + ! M2N6SRVxi,M2N6SRVyi,M2N6SRVzi, & + ! M2N7SRVxi,M2N7SRVyi,M2N7SRVzi, & + ! M2N8SRVxi,M2N8SRVyi,M2N8SRVzi, & + ! M2N9SRVxi,M2N9SRVyi,M2N9SRVzi, & + ! M3N1SRVxi,M3N1SRVyi,M3N1SRVzi, & + ! M3N2SRVxi,M3N2SRVyi,M3N2SRVzi, & + ! M3N3SRVxi,M3N3SRVyi,M3N3SRVzi, & + ! M3N4SRVxi,M3N4SRVyi,M3N4SRVzi, & + ! M3N5SRVxi,M3N5SRVyi,M3N5SRVzi, & + ! M3N6SRVxi,M3N6SRVyi,M3N6SRVzi, & + ! M3N7SRVxi,M3N7SRVyi,M3N7SRVzi, & + ! M3N8SRVxi,M3N8SRVyi,M3N8SRVzi, & + ! M3N9SRVxi,M3N9SRVyi,M3N9SRVzi, & + ! M4N1SRVxi,M4N1SRVyi,M4N1SRVzi, & + ! M4N2SRVxi,M4N2SRVyi,M4N2SRVzi, & + ! M4N3SRVxi,M4N3SRVyi,M4N3SRVzi, & + ! M4N4SRVxi,M4N4SRVyi,M4N4SRVzi, & + ! M4N5SRVxi,M4N5SRVyi,M4N5SRVzi, & + ! M4N6SRVxi,M4N6SRVyi,M4N6SRVzi, & + ! M4N7SRVxi,M4N7SRVyi,M4N7SRVzi, & + ! M4N8SRVxi,M4N8SRVyi,M4N8SRVzi, & + ! M4N9SRVxi,M4N9SRVyi,M4N9SRVzi, & + ! M5N1SRVxi,M5N1SRVyi,M5N1SRVzi, & + ! M5N2SRVxi,M5N2SRVyi,M5N2SRVzi, & + ! M5N3SRVxi,M5N3SRVyi,M5N3SRVzi, & + ! M5N4SRVxi,M5N4SRVyi,M5N4SRVzi, & + ! M5N5SRVxi,M5N5SRVyi,M5N5SRVzi, & + ! M5N6SRVxi,M5N6SRVyi,M5N6SRVzi, & + ! M5N7SRVxi,M5N7SRVyi,M5N7SRVzi, & + ! M5N8SRVxi,M5N8SRVyi,M5N8SRVzi, & + ! M5N9SRVxi,M5N9SRVyi,M5N9SRVzi, & + ! M6N1SRVxi,M6N1SRVyi,M6N1SRVzi, & + ! M6N2SRVxi,M6N2SRVyi,M6N2SRVzi, & + ! M6N3SRVxi,M6N3SRVyi,M6N3SRVzi, & + ! M6N4SRVxi,M6N4SRVyi,M6N4SRVzi, & + ! M6N5SRVxi,M6N5SRVyi,M6N5SRVzi, & + ! M6N6SRVxi,M6N6SRVyi,M6N6SRVzi, & + ! M6N7SRVxi,M6N7SRVyi,M6N7SRVzi, & + ! M6N8SRVxi,M6N8SRVyi,M6N8SRVzi, & + ! M6N9SRVxi,M6N9SRVyi,M6N9SRVzi, & + ! M7N1SRVxi,M7N1SRVyi,M7N1SRVzi, & + ! M7N2SRVxi,M7N2SRVyi,M7N2SRVzi, & + ! M7N3SRVxi,M7N3SRVyi,M7N3SRVzi, & + ! M7N4SRVxi,M7N4SRVyi,M7N4SRVzi, & + ! M7N5SRVxi,M7N5SRVyi,M7N5SRVzi, & + ! M7N6SRVxi,M7N6SRVyi,M7N6SRVzi, & + ! M7N7SRVxi,M7N7SRVyi,M7N7SRVzi, & + ! M7N8SRVxi,M7N8SRVyi,M7N8SRVzi, & + ! M7N9SRVxi,M7N9SRVyi,M7N9SRVzi, & + ! M8N1SRVxi,M8N1SRVyi,M8N1SRVzi, & + ! M8N2SRVxi,M8N2SRVyi,M8N2SRVzi, & + ! M8N3SRVxi,M8N3SRVyi,M8N3SRVzi, & + ! M8N4SRVxi,M8N4SRVyi,M8N4SRVzi, & + ! M8N5SRVxi,M8N5SRVyi,M8N5SRVzi, & + ! M8N6SRVxi,M8N6SRVyi,M8N6SRVzi, & + ! M8N7SRVxi,M8N7SRVyi,M8N7SRVzi, & + ! M8N8SRVxi,M8N8SRVyi,M8N8SRVzi, & + ! M8N9SRVxi,M8N9SRVyi,M8N9SRVzi, & + ! M9N1SRVxi,M9N1SRVyi,M9N1SRVzi, & + ! M9N2SRVxi,M9N2SRVyi,M9N2SRVzi, & + ! M9N3SRVxi,M9N3SRVyi,M9N3SRVzi, & + ! M9N4SRVxi,M9N4SRVyi,M9N4SRVzi, & + ! M9N5SRVxi,M9N5SRVyi,M9N5SRVzi, & + ! M9N6SRVxi,M9N6SRVyi,M9N6SRVzi, & + ! M9N7SRVxi,M9N7SRVyi,M9N7SRVzi, & + ! M9N8SRVxi,M9N8SRVyi,M9N8SRVzi, & + ! M9N9SRVxi,M9N9SRVyi,M9N9SRVzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNSTAi(3,9,9) = reshape((/M1N1STAxi,M1N1STAyi,M1N1STAzi, & + M1N2STAxi,M1N2STAyi,M1N2STAzi, & + M1N3STAxi,M1N3STAyi,M1N3STAzi, & + M1N4STAxi,M1N4STAyi,M1N4STAzi, & + M1N5STAxi,M1N5STAyi,M1N5STAzi, & + M1N6STAxi,M1N6STAyi,M1N6STAzi, & + M1N7STAxi,M1N7STAyi,M1N7STAzi, & + M1N8STAxi,M1N8STAyi,M1N8STAzi, & + M1N9STAxi,M1N9STAyi,M1N9STAzi, & + M2N1STAxi,M2N1STAyi,M2N1STAzi, & + M2N2STAxi,M2N2STAyi,M2N2STAzi, & + M2N3STAxi,M2N3STAyi,M2N3STAzi, & + M2N4STAxi,M2N4STAyi,M2N4STAzi, & + M2N5STAxi,M2N5STAyi,M2N5STAzi, & + M2N6STAxi,M2N6STAyi,M2N6STAzi, & + M2N7STAxi,M2N7STAyi,M2N7STAzi, & + M2N8STAxi,M2N8STAyi,M2N8STAzi, & + M2N9STAxi,M2N9STAyi,M2N9STAzi, & + M3N1STAxi,M3N1STAyi,M3N1STAzi, & + M3N2STAxi,M3N2STAyi,M3N2STAzi, & + M3N3STAxi,M3N3STAyi,M3N3STAzi, & + M3N4STAxi,M3N4STAyi,M3N4STAzi, & + M3N5STAxi,M3N5STAyi,M3N5STAzi, & + M3N6STAxi,M3N6STAyi,M3N6STAzi, & + M3N7STAxi,M3N7STAyi,M3N7STAzi, & + M3N8STAxi,M3N8STAyi,M3N8STAzi, & + M3N9STAxi,M3N9STAyi,M3N9STAzi, & + M4N1STAxi,M4N1STAyi,M4N1STAzi, & + M4N2STAxi,M4N2STAyi,M4N2STAzi, & + M4N3STAxi,M4N3STAyi,M4N3STAzi, & + M4N4STAxi,M4N4STAyi,M4N4STAzi, & + M4N5STAxi,M4N5STAyi,M4N5STAzi, & + M4N6STAxi,M4N6STAyi,M4N6STAzi, & + M4N7STAxi,M4N7STAyi,M4N7STAzi, & + M4N8STAxi,M4N8STAyi,M4N8STAzi, & + M4N9STAxi,M4N9STAyi,M4N9STAzi, & + M5N1STAxi,M5N1STAyi,M5N1STAzi, & + M5N2STAxi,M5N2STAyi,M5N2STAzi, & + M5N3STAxi,M5N3STAyi,M5N3STAzi, & + M5N4STAxi,M5N4STAyi,M5N4STAzi, & + M5N5STAxi,M5N5STAyi,M5N5STAzi, & + M5N6STAxi,M5N6STAyi,M5N6STAzi, & + M5N7STAxi,M5N7STAyi,M5N7STAzi, & + M5N8STAxi,M5N8STAyi,M5N8STAzi, & + M5N9STAxi,M5N9STAyi,M5N9STAzi, & + M6N1STAxi,M6N1STAyi,M6N1STAzi, & + M6N2STAxi,M6N2STAyi,M6N2STAzi, & + M6N3STAxi,M6N3STAyi,M6N3STAzi, & + M6N4STAxi,M6N4STAyi,M6N4STAzi, & + M6N5STAxi,M6N5STAyi,M6N5STAzi, & + M6N6STAxi,M6N6STAyi,M6N6STAzi, & + M6N7STAxi,M6N7STAyi,M6N7STAzi, & + M6N8STAxi,M6N8STAyi,M6N8STAzi, & + M6N9STAxi,M6N9STAyi,M6N9STAzi, & + M7N1STAxi,M7N1STAyi,M7N1STAzi, & + M7N2STAxi,M7N2STAyi,M7N2STAzi, & + M7N3STAxi,M7N3STAyi,M7N3STAzi, & + M7N4STAxi,M7N4STAyi,M7N4STAzi, & + M7N5STAxi,M7N5STAyi,M7N5STAzi, & + M7N6STAxi,M7N6STAyi,M7N6STAzi, & + M7N7STAxi,M7N7STAyi,M7N7STAzi, & + M7N8STAxi,M7N8STAyi,M7N8STAzi, & + M7N9STAxi,M7N9STAyi,M7N9STAzi, & + M8N1STAxi,M8N1STAyi,M8N1STAzi, & + M8N2STAxi,M8N2STAyi,M8N2STAzi, & + M8N3STAxi,M8N3STAyi,M8N3STAzi, & + M8N4STAxi,M8N4STAyi,M8N4STAzi, & + M8N5STAxi,M8N5STAyi,M8N5STAzi, & + M8N6STAxi,M8N6STAyi,M8N6STAzi, & + M8N7STAxi,M8N7STAyi,M8N7STAzi, & + M8N8STAxi,M8N8STAyi,M8N8STAzi, & + M8N9STAxi,M8N9STAyi,M8N9STAzi, & + M9N1STAxi,M9N1STAyi,M9N1STAzi, & + M9N2STAxi,M9N2STAyi,M9N2STAzi, & + M9N3STAxi,M9N3STAyi,M9N3STAzi, & + M9N4STAxi,M9N4STAyi,M9N4STAzi, & + M9N5STAxi,M9N5STAyi,M9N5STAzi, & + M9N6STAxi,M9N6STAyi,M9N6STAzi, & + M9N7STAxi,M9N7STAyi,M9N7STAzi, & + M9N8STAxi,M9N8STAyi,M9N8STAzi, & + M9N9STAxi,M9N9STAyi,M9N9STAzi/), (/3,9,9/)) + + !INTEGER, PARAMETER :: MNSRAi(3,9,9) = reshape((/M1N1SRAxi,M1N1SRAyi,M1N1SRAzi, & + ! M1N2SRAxi,M1N2SRAyi,M1N2SRAzi, & + ! M1N3SRAxi,M1N3SRAyi,M1N3SRAzi, & + ! M1N4SRAxi,M1N4SRAyi,M1N4SRAzi, & + ! M1N5SRAxi,M1N5SRAyi,M1N5SRAzi, & + ! M1N6SRAxi,M1N6SRAyi,M1N6SRAzi, & + ! M1N7SRAxi,M1N7SRAyi,M1N7SRAzi, & + ! M1N8SRAxi,M1N8SRAyi,M1N8SRAzi, & + ! M1N9SRAxi,M1N9SRAyi,M1N9SRAzi, & + ! M2N1SRAxi,M2N1SRAyi,M2N1SRAzi, & + ! M2N2SRAxi,M2N2SRAyi,M2N2SRAzi, & + ! M2N3SRAxi,M2N3SRAyi,M2N3SRAzi, & + ! M2N4SRAxi,M2N4SRAyi,M2N4SRAzi, & + ! M2N5SRAxi,M2N5SRAyi,M2N5SRAzi, & + ! M2N6SRAxi,M2N6SRAyi,M2N6SRAzi, & + ! M2N7SRAxi,M2N7SRAyi,M2N7SRAzi, & + ! M2N8SRAxi,M2N8SRAyi,M2N8SRAzi, & + ! M2N9SRAxi,M2N9SRAyi,M2N9SRAzi, & + ! M3N1SRAxi,M3N1SRAyi,M3N1SRAzi, & + ! M3N2SRAxi,M3N2SRAyi,M3N2SRAzi, & + ! M3N3SRAxi,M3N3SRAyi,M3N3SRAzi, & + ! M3N4SRAxi,M3N4SRAyi,M3N4SRAzi, & + ! M3N5SRAxi,M3N5SRAyi,M3N5SRAzi, & + ! M3N6SRAxi,M3N6SRAyi,M3N6SRAzi, & + ! M3N7SRAxi,M3N7SRAyi,M3N7SRAzi, & + ! M3N8SRAxi,M3N8SRAyi,M3N8SRAzi, & + ! M3N9SRAxi,M3N9SRAyi,M3N9SRAzi, & + ! M4N1SRAxi,M4N1SRAyi,M4N1SRAzi, & + ! M4N2SRAxi,M4N2SRAyi,M4N2SRAzi, & + ! M4N3SRAxi,M4N3SRAyi,M4N3SRAzi, & + ! M4N4SRAxi,M4N4SRAyi,M4N4SRAzi, & + ! M4N5SRAxi,M4N5SRAyi,M4N5SRAzi, & + ! M4N6SRAxi,M4N6SRAyi,M4N6SRAzi, & + ! M4N7SRAxi,M4N7SRAyi,M4N7SRAzi, & + ! M4N8SRAxi,M4N8SRAyi,M4N8SRAzi, & + ! M4N9SRAxi,M4N9SRAyi,M4N9SRAzi, & + ! M5N1SRAxi,M5N1SRAyi,M5N1SRAzi, & + ! M5N2SRAxi,M5N2SRAyi,M5N2SRAzi, & + ! M5N3SRAxi,M5N3SRAyi,M5N3SRAzi, & + ! M5N4SRAxi,M5N4SRAyi,M5N4SRAzi, & + ! M5N5SRAxi,M5N5SRAyi,M5N5SRAzi, & + ! M5N6SRAxi,M5N6SRAyi,M5N6SRAzi, & + ! M5N7SRAxi,M5N7SRAyi,M5N7SRAzi, & + ! M5N8SRAxi,M5N8SRAyi,M5N8SRAzi, & + ! M5N9SRAxi,M5N9SRAyi,M5N9SRAzi, & + ! M6N1SRAxi,M6N1SRAyi,M6N1SRAzi, & + ! M6N2SRAxi,M6N2SRAyi,M6N2SRAzi, & + ! M6N3SRAxi,M6N3SRAyi,M6N3SRAzi, & + ! M6N4SRAxi,M6N4SRAyi,M6N4SRAzi, & + ! M6N5SRAxi,M6N5SRAyi,M6N5SRAzi, & + ! M6N6SRAxi,M6N6SRAyi,M6N6SRAzi, & + ! M6N7SRAxi,M6N7SRAyi,M6N7SRAzi, & + ! M6N8SRAxi,M6N8SRAyi,M6N8SRAzi, & + ! M6N9SRAxi,M6N9SRAyi,M6N9SRAzi, & + ! M7N1SRAxi,M7N1SRAyi,M7N1SRAzi, & + ! M7N2SRAxi,M7N2SRAyi,M7N2SRAzi, & + ! M7N3SRAxi,M7N3SRAyi,M7N3SRAzi, & + ! M7N4SRAxi,M7N4SRAyi,M7N4SRAzi, & + ! M7N5SRAxi,M7N5SRAyi,M7N5SRAzi, & + ! M7N6SRAxi,M7N6SRAyi,M7N6SRAzi, & + ! M7N7SRAxi,M7N7SRAyi,M7N7SRAzi, & + ! M7N8SRAxi,M7N8SRAyi,M7N8SRAzi, & + ! M7N9SRAxi,M7N9SRAyi,M7N9SRAzi, & + ! M8N1SRAxi,M8N1SRAyi,M8N1SRAzi, & + ! M8N2SRAxi,M8N2SRAyi,M8N2SRAzi, & + ! M8N3SRAxi,M8N3SRAyi,M8N3SRAzi, & + ! M8N4SRAxi,M8N4SRAyi,M8N4SRAzi, & + ! M8N5SRAxi,M8N5SRAyi,M8N5SRAzi, & + ! M8N6SRAxi,M8N6SRAyi,M8N6SRAzi, & + ! M8N7SRAxi,M8N7SRAyi,M8N7SRAzi, & + ! M8N8SRAxi,M8N8SRAyi,M8N8SRAzi, & + ! M8N9SRAxi,M8N9SRAyi,M8N9SRAzi, & + ! M9N1SRAxi,M9N1SRAyi,M9N1SRAzi, & + ! M9N2SRAxi,M9N2SRAyi,M9N2SRAzi, & + ! M9N3SRAxi,M9N3SRAyi,M9N3SRAzi, & + ! M9N4SRAxi,M9N4SRAyi,M9N4SRAzi, & + ! M9N5SRAxi,M9N5SRAyi,M9N5SRAzi, & + ! M9N6SRAxi,M9N6SRAyi,M9N6SRAzi, & + ! M9N7SRAxi,M9N7SRAyi,M9N7SRAzi, & + ! M9N8SRAxi,M9N8SRAyi,M9N8SRAzi, & + ! M9N9SRAxi,M9N9SRAyi,M9N9SRAzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNDynP(9,9) = reshape((/M1N1DynP,M1N2DynP,M1N3DynP,M1N4DynP,M1N5DynP,M1N6DynP,M1N7DynP,M1N8DynP,M1N9DynP, & + M2N1DynP,M2N2DynP,M2N3DynP,M2N4DynP,M2N5DynP,M2N6DynP,M2N7DynP,M2N8DynP,M2N9DynP, & + M3N1DynP,M3N2DynP,M3N3DynP,M3N4DynP,M3N5DynP,M3N6DynP,M3N7DynP,M3N8DynP,M3N9DynP, & + M4N1DynP,M4N2DynP,M4N3DynP,M4N4DynP,M4N5DynP,M4N6DynP,M4N7DynP,M4N8DynP,M4N9DynP, & + M5N1DynP,M5N2DynP,M5N3DynP,M5N4DynP,M5N5DynP,M5N6DynP,M5N7DynP,M5N8DynP,M5N9DynP, & + M6N1DynP,M6N2DynP,M6N3DynP,M6N4DynP,M6N5DynP,M6N6DynP,M6N7DynP,M6N8DynP,M6N9DynP, & + M7N1DynP,M7N2DynP,M7N3DynP,M7N4DynP,M7N5DynP,M7N6DynP,M7N7DynP,M7N8DynP,M7N9DynP, & + M8N1DynP,M8N2DynP,M8N3DynP,M8N4DynP,M8N5DynP,M8N6DynP,M8N7DynP,M8N8DynP,M8N9DynP, & + M9N1DynP,M9N2DynP,M9N3DynP,M9N4DynP,M9N5DynP,M9N6DynP,M9N7DynP,M9N8DynP,M9N9DynP/), & + (/9,9/)) + + INTEGER, PARAMETER :: MNFDi(3,9,9) = reshape((/M1N1FDxi,M1N1FDyi,M1N1FDzi, & + M1N2FDxi,M1N2FDyi,M1N2FDzi, & + M1N3FDxi,M1N3FDyi,M1N3FDzi, & + M1N4FDxi,M1N4FDyi,M1N4FDzi, & + M1N5FDxi,M1N5FDyi,M1N5FDzi, & + M1N6FDxi,M1N6FDyi,M1N6FDzi, & + M1N7FDxi,M1N7FDyi,M1N7FDzi, & + M1N8FDxi,M1N8FDyi,M1N8FDzi, & + M1N9FDxi,M1N9FDyi,M1N9FDzi, & + M2N1FDxi,M2N1FDyi,M2N1FDzi, & + M2N2FDxi,M2N2FDyi,M2N2FDzi, & + M2N3FDxi,M2N3FDyi,M2N3FDzi, & + M2N4FDxi,M2N4FDyi,M2N4FDzi, & + M2N5FDxi,M2N5FDyi,M2N5FDzi, & + M2N6FDxi,M2N6FDyi,M2N6FDzi, & + M2N7FDxi,M2N7FDyi,M2N7FDzi, & + M2N8FDxi,M2N8FDyi,M2N8FDzi, & + M2N9FDxi,M2N9FDyi,M2N9FDzi, & + M3N1FDxi,M3N1FDyi,M3N1FDzi, & + M3N2FDxi,M3N2FDyi,M3N2FDzi, & + M3N3FDxi,M3N3FDyi,M3N3FDzi, & + M3N4FDxi,M3N4FDyi,M3N4FDzi, & + M3N5FDxi,M3N5FDyi,M3N5FDzi, & + M3N6FDxi,M3N6FDyi,M3N6FDzi, & + M3N7FDxi,M3N7FDyi,M3N7FDzi, & + M3N8FDxi,M3N8FDyi,M3N8FDzi, & + M3N9FDxi,M3N9FDyi,M3N9FDzi, & + M4N1FDxi,M4N1FDyi,M4N1FDzi, & + M4N2FDxi,M4N2FDyi,M4N2FDzi, & + M4N3FDxi,M4N3FDyi,M4N3FDzi, & + M4N4FDxi,M4N4FDyi,M4N4FDzi, & + M4N5FDxi,M4N5FDyi,M4N5FDzi, & + M4N6FDxi,M4N6FDyi,M4N6FDzi, & + M4N7FDxi,M4N7FDyi,M4N7FDzi, & + M4N8FDxi,M4N8FDyi,M4N8FDzi, & + M4N9FDxi,M4N9FDyi,M4N9FDzi, & + M5N1FDxi,M5N1FDyi,M5N1FDzi, & + M5N2FDxi,M5N2FDyi,M5N2FDzi, & + M5N3FDxi,M5N3FDyi,M5N3FDzi, & + M5N4FDxi,M5N4FDyi,M5N4FDzi, & + M5N5FDxi,M5N5FDyi,M5N5FDzi, & + M5N6FDxi,M5N6FDyi,M5N6FDzi, & + M5N7FDxi,M5N7FDyi,M5N7FDzi, & + M5N8FDxi,M5N8FDyi,M5N8FDzi, & + M5N9FDxi,M5N9FDyi,M5N9FDzi, & + M6N1FDxi,M6N1FDyi,M6N1FDzi, & + M6N2FDxi,M6N2FDyi,M6N2FDzi, & + M6N3FDxi,M6N3FDyi,M6N3FDzi, & + M6N4FDxi,M6N4FDyi,M6N4FDzi, & + M6N5FDxi,M6N5FDyi,M6N5FDzi, & + M6N6FDxi,M6N6FDyi,M6N6FDzi, & + M6N7FDxi,M6N7FDyi,M6N7FDzi, & + M6N8FDxi,M6N8FDyi,M6N8FDzi, & + M6N9FDxi,M6N9FDyi,M6N9FDzi, & + M7N1FDxi,M7N1FDyi,M7N1FDzi, & + M7N2FDxi,M7N2FDyi,M7N2FDzi, & + M7N3FDxi,M7N3FDyi,M7N3FDzi, & + M7N4FDxi,M7N4FDyi,M7N4FDzi, & + M7N5FDxi,M7N5FDyi,M7N5FDzi, & + M7N6FDxi,M7N6FDyi,M7N6FDzi, & + M7N7FDxi,M7N7FDyi,M7N7FDzi, & + M7N8FDxi,M7N8FDyi,M7N8FDzi, & + M7N9FDxi,M7N9FDyi,M7N9FDzi, & + M8N1FDxi,M8N1FDyi,M8N1FDzi, & + M8N2FDxi,M8N2FDyi,M8N2FDzi, & + M8N3FDxi,M8N3FDyi,M8N3FDzi, & + M8N4FDxi,M8N4FDyi,M8N4FDzi, & + M8N5FDxi,M8N5FDyi,M8N5FDzi, & + M8N6FDxi,M8N6FDyi,M8N6FDzi, & + M8N7FDxi,M8N7FDyi,M8N7FDzi, & + M8N8FDxi,M8N8FDyi,M8N8FDzi, & + M8N9FDxi,M8N9FDyi,M8N9FDzi, & + M9N1FDxi,M9N1FDyi,M9N1FDzi, & + M9N2FDxi,M9N2FDyi,M9N2FDzi, & + M9N3FDxi,M9N3FDyi,M9N3FDzi, & + M9N4FDxi,M9N4FDyi,M9N4FDzi, & + M9N5FDxi,M9N5FDyi,M9N5FDzi, & + M9N6FDxi,M9N6FDyi,M9N6FDzi, & + M9N7FDxi,M9N7FDyi,M9N7FDzi, & + M9N8FDxi,M9N8FDyi,M9N8FDzi, & + M9N9FDxi,M9N9FDyi,M9N9FDzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFIi(3,9,9) = reshape((/M1N1FIxi,M1N1FIyi,M1N1FIzi, & + M1N2FIxi,M1N2FIyi,M1N2FIzi, & + M1N3FIxi,M1N3FIyi,M1N3FIzi, & + M1N4FIxi,M1N4FIyi,M1N4FIzi, & + M1N5FIxi,M1N5FIyi,M1N5FIzi, & + M1N6FIxi,M1N6FIyi,M1N6FIzi, & + M1N7FIxi,M1N7FIyi,M1N7FIzi, & + M1N8FIxi,M1N8FIyi,M1N8FIzi, & + M1N9FIxi,M1N9FIyi,M1N9FIzi, & + M2N1FIxi,M2N1FIyi,M2N1FIzi, & + M2N2FIxi,M2N2FIyi,M2N2FIzi, & + M2N3FIxi,M2N3FIyi,M2N3FIzi, & + M2N4FIxi,M2N4FIyi,M2N4FIzi, & + M2N5FIxi,M2N5FIyi,M2N5FIzi, & + M2N6FIxi,M2N6FIyi,M2N6FIzi, & + M2N7FIxi,M2N7FIyi,M2N7FIzi, & + M2N8FIxi,M2N8FIyi,M2N8FIzi, & + M2N9FIxi,M2N9FIyi,M2N9FIzi, & + M3N1FIxi,M3N1FIyi,M3N1FIzi, & + M3N2FIxi,M3N2FIyi,M3N2FIzi, & + M3N3FIxi,M3N3FIyi,M3N3FIzi, & + M3N4FIxi,M3N4FIyi,M3N4FIzi, & + M3N5FIxi,M3N5FIyi,M3N5FIzi, & + M3N6FIxi,M3N6FIyi,M3N6FIzi, & + M3N7FIxi,M3N7FIyi,M3N7FIzi, & + M3N8FIxi,M3N8FIyi,M3N8FIzi, & + M3N9FIxi,M3N9FIyi,M3N9FIzi, & + M4N1FIxi,M4N1FIyi,M4N1FIzi, & + M4N2FIxi,M4N2FIyi,M4N2FIzi, & + M4N3FIxi,M4N3FIyi,M4N3FIzi, & + M4N4FIxi,M4N4FIyi,M4N4FIzi, & + M4N5FIxi,M4N5FIyi,M4N5FIzi, & + M4N6FIxi,M4N6FIyi,M4N6FIzi, & + M4N7FIxi,M4N7FIyi,M4N7FIzi, & + M4N8FIxi,M4N8FIyi,M4N8FIzi, & + M4N9FIxi,M4N9FIyi,M4N9FIzi, & + M5N1FIxi,M5N1FIyi,M5N1FIzi, & + M5N2FIxi,M5N2FIyi,M5N2FIzi, & + M5N3FIxi,M5N3FIyi,M5N3FIzi, & + M5N4FIxi,M5N4FIyi,M5N4FIzi, & + M5N5FIxi,M5N5FIyi,M5N5FIzi, & + M5N6FIxi,M5N6FIyi,M5N6FIzi, & + M5N7FIxi,M5N7FIyi,M5N7FIzi, & + M5N8FIxi,M5N8FIyi,M5N8FIzi, & + M5N9FIxi,M5N9FIyi,M5N9FIzi, & + M6N1FIxi,M6N1FIyi,M6N1FIzi, & + M6N2FIxi,M6N2FIyi,M6N2FIzi, & + M6N3FIxi,M6N3FIyi,M6N3FIzi, & + M6N4FIxi,M6N4FIyi,M6N4FIzi, & + M6N5FIxi,M6N5FIyi,M6N5FIzi, & + M6N6FIxi,M6N6FIyi,M6N6FIzi, & + M6N7FIxi,M6N7FIyi,M6N7FIzi, & + M6N8FIxi,M6N8FIyi,M6N8FIzi, & + M6N9FIxi,M6N9FIyi,M6N9FIzi, & + M7N1FIxi,M7N1FIyi,M7N1FIzi, & + M7N2FIxi,M7N2FIyi,M7N2FIzi, & + M7N3FIxi,M7N3FIyi,M7N3FIzi, & + M7N4FIxi,M7N4FIyi,M7N4FIzi, & + M7N5FIxi,M7N5FIyi,M7N5FIzi, & + M7N6FIxi,M7N6FIyi,M7N6FIzi, & + M7N7FIxi,M7N7FIyi,M7N7FIzi, & + M7N8FIxi,M7N8FIyi,M7N8FIzi, & + M7N9FIxi,M7N9FIyi,M7N9FIzi, & + M8N1FIxi,M8N1FIyi,M8N1FIzi, & + M8N2FIxi,M8N2FIyi,M8N2FIzi, & + M8N3FIxi,M8N3FIyi,M8N3FIzi, & + M8N4FIxi,M8N4FIyi,M8N4FIzi, & + M8N5FIxi,M8N5FIyi,M8N5FIzi, & + M8N6FIxi,M8N6FIyi,M8N6FIzi, & + M8N7FIxi,M8N7FIyi,M8N7FIzi, & + M8N8FIxi,M8N8FIyi,M8N8FIzi, & + M8N9FIxi,M8N9FIyi,M8N9FIzi, & + M9N1FIxi,M9N1FIyi,M9N1FIzi, & + M9N2FIxi,M9N2FIyi,M9N2FIzi, & + M9N3FIxi,M9N3FIyi,M9N3FIzi, & + M9N4FIxi,M9N4FIyi,M9N4FIzi, & + M9N5FIxi,M9N5FIyi,M9N5FIzi, & + M9N6FIxi,M9N6FIyi,M9N6FIzi, & + M9N7FIxi,M9N7FIyi,M9N7FIzi, & + M9N8FIxi,M9N8FIyi,M9N8FIzi, & + M9N9FIxi,M9N9FIyi,M9N9FIzi/), (/3,9,9/)) + + + + + INTEGER, PARAMETER :: MNFBi(3,9,9) = reshape((/M1N1FBxi,M1N1FByi,M1N1FBzi, & + M1N2FBxi,M1N2FByi,M1N2FBzi, & + M1N3FBxi,M1N3FByi,M1N3FBzi, & + M1N4FBxi,M1N4FByi,M1N4FBzi, & + M1N5FBxi,M1N5FByi,M1N5FBzi, & + M1N6FBxi,M1N6FByi,M1N6FBzi, & + M1N7FBxi,M1N7FByi,M1N7FBzi, & + M1N8FBxi,M1N8FByi,M1N8FBzi, & + M1N9FBxi,M1N9FByi,M1N9FBzi, & + M2N1FBxi,M2N1FByi,M2N1FBzi, & + M2N2FBxi,M2N2FByi,M2N2FBzi, & + M2N3FBxi,M2N3FByi,M2N3FBzi, & + M2N4FBxi,M2N4FByi,M2N4FBzi, & + M2N5FBxi,M2N5FByi,M2N5FBzi, & + M2N6FBxi,M2N6FByi,M2N6FBzi, & + M2N7FBxi,M2N7FByi,M2N7FBzi, & + M2N8FBxi,M2N8FByi,M2N8FBzi, & + M2N9FBxi,M2N9FByi,M2N9FBzi, & + M3N1FBxi,M3N1FByi,M3N1FBzi, & + M3N2FBxi,M3N2FByi,M3N2FBzi, & + M3N3FBxi,M3N3FByi,M3N3FBzi, & + M3N4FBxi,M3N4FByi,M3N4FBzi, & + M3N5FBxi,M3N5FByi,M3N5FBzi, & + M3N6FBxi,M3N6FByi,M3N6FBzi, & + M3N7FBxi,M3N7FByi,M3N7FBzi, & + M3N8FBxi,M3N8FByi,M3N8FBzi, & + M3N9FBxi,M3N9FByi,M3N9FBzi, & + M4N1FBxi,M4N1FByi,M4N1FBzi, & + M4N2FBxi,M4N2FByi,M4N2FBzi, & + M4N3FBxi,M4N3FByi,M4N3FBzi, & + M4N4FBxi,M4N4FByi,M4N4FBzi, & + M4N5FBxi,M4N5FByi,M4N5FBzi, & + M4N6FBxi,M4N6FByi,M4N6FBzi, & + M4N7FBxi,M4N7FByi,M4N7FBzi, & + M4N8FBxi,M4N8FByi,M4N8FBzi, & + M4N9FBxi,M4N9FByi,M4N9FBzi, & + M5N1FBxi,M5N1FByi,M5N1FBzi, & + M5N2FBxi,M5N2FByi,M5N2FBzi, & + M5N3FBxi,M5N3FByi,M5N3FBzi, & + M5N4FBxi,M5N4FByi,M5N4FBzi, & + M5N5FBxi,M5N5FByi,M5N5FBzi, & + M5N6FBxi,M5N6FByi,M5N6FBzi, & + M5N7FBxi,M5N7FByi,M5N7FBzi, & + M5N8FBxi,M5N8FByi,M5N8FBzi, & + M5N9FBxi,M5N9FByi,M5N9FBzi, & + M6N1FBxi,M6N1FByi,M6N1FBzi, & + M6N2FBxi,M6N2FByi,M6N2FBzi, & + M6N3FBxi,M6N3FByi,M6N3FBzi, & + M6N4FBxi,M6N4FByi,M6N4FBzi, & + M6N5FBxi,M6N5FByi,M6N5FBzi, & + M6N6FBxi,M6N6FByi,M6N6FBzi, & + M6N7FBxi,M6N7FByi,M6N7FBzi, & + M6N8FBxi,M6N8FByi,M6N8FBzi, & + M6N9FBxi,M6N9FByi,M6N9FBzi, & + M7N1FBxi,M7N1FByi,M7N1FBzi, & + M7N2FBxi,M7N2FByi,M7N2FBzi, & + M7N3FBxi,M7N3FByi,M7N3FBzi, & + M7N4FBxi,M7N4FByi,M7N4FBzi, & + M7N5FBxi,M7N5FByi,M7N5FBzi, & + M7N6FBxi,M7N6FByi,M7N6FBzi, & + M7N7FBxi,M7N7FByi,M7N7FBzi, & + M7N8FBxi,M7N8FByi,M7N8FBzi, & + M7N9FBxi,M7N9FByi,M7N9FBzi, & + M8N1FBxi,M8N1FByi,M8N1FBzi, & + M8N2FBxi,M8N2FByi,M8N2FBzi, & + M8N3FBxi,M8N3FByi,M8N3FBzi, & + M8N4FBxi,M8N4FByi,M8N4FBzi, & + M8N5FBxi,M8N5FByi,M8N5FBzi, & + M8N6FBxi,M8N6FByi,M8N6FBzi, & + M8N7FBxi,M8N7FByi,M8N7FBzi, & + M8N8FBxi,M8N8FByi,M8N8FBzi, & + M8N9FBxi,M8N9FByi,M8N9FBzi, & + M9N1FBxi,M9N1FByi,M9N1FBzi, & + M9N2FBxi,M9N2FByi,M9N2FBzi, & + M9N3FBxi,M9N3FByi,M9N3FBzi, & + M9N4FBxi,M9N4FByi,M9N4FBzi, & + M9N5FBxi,M9N5FByi,M9N5FBzi, & + M9N6FBxi,M9N6FByi,M9N6FBzi, & + M9N7FBxi,M9N7FByi,M9N7FBzi, & + M9N8FBxi,M9N8FByi,M9N8FBzi, & + M9N9FBxi,M9N9FByi,M9N9FBzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFBFi(3,9,9) = reshape((/M1N1FBFxi,M1N1FBFyi,M1N1FBFzi, & + M1N2FBFxi,M1N2FBFyi,M1N2FBFzi, & + M1N3FBFxi,M1N3FBFyi,M1N3FBFzi, & + M1N4FBFxi,M1N4FBFyi,M1N4FBFzi, & + M1N5FBFxi,M1N5FBFyi,M1N5FBFzi, & + M1N6FBFxi,M1N6FBFyi,M1N6FBFzi, & + M1N7FBFxi,M1N7FBFyi,M1N7FBFzi, & + M1N8FBFxi,M1N8FBFyi,M1N8FBFzi, & + M1N9FBFxi,M1N9FBFyi,M1N9FBFzi, & + M2N1FBFxi,M2N1FBFyi,M2N1FBFzi, & + M2N2FBFxi,M2N2FBFyi,M2N2FBFzi, & + M2N3FBFxi,M2N3FBFyi,M2N3FBFzi, & + M2N4FBFxi,M2N4FBFyi,M2N4FBFzi, & + M2N5FBFxi,M2N5FBFyi,M2N5FBFzi, & + M2N6FBFxi,M2N6FBFyi,M2N6FBFzi, & + M2N7FBFxi,M2N7FBFyi,M2N7FBFzi, & + M2N8FBFxi,M2N8FBFyi,M2N8FBFzi, & + M2N9FBFxi,M2N9FBFyi,M2N9FBFzi, & + M3N1FBFxi,M3N1FBFyi,M3N1FBFzi, & + M3N2FBFxi,M3N2FBFyi,M3N2FBFzi, & + M3N3FBFxi,M3N3FBFyi,M3N3FBFzi, & + M3N4FBFxi,M3N4FBFyi,M3N4FBFzi, & + M3N5FBFxi,M3N5FBFyi,M3N5FBFzi, & + M3N6FBFxi,M3N6FBFyi,M3N6FBFzi, & + M3N7FBFxi,M3N7FBFyi,M3N7FBFzi, & + M3N8FBFxi,M3N8FBFyi,M3N8FBFzi, & + M3N9FBFxi,M3N9FBFyi,M3N9FBFzi, & + M4N1FBFxi,M4N1FBFyi,M4N1FBFzi, & + M4N2FBFxi,M4N2FBFyi,M4N2FBFzi, & + M4N3FBFxi,M4N3FBFyi,M4N3FBFzi, & + M4N4FBFxi,M4N4FBFyi,M4N4FBFzi, & + M4N5FBFxi,M4N5FBFyi,M4N5FBFzi, & + M4N6FBFxi,M4N6FBFyi,M4N6FBFzi, & + M4N7FBFxi,M4N7FBFyi,M4N7FBFzi, & + M4N8FBFxi,M4N8FBFyi,M4N8FBFzi, & + M4N9FBFxi,M4N9FBFyi,M4N9FBFzi, & + M5N1FBFxi,M5N1FBFyi,M5N1FBFzi, & + M5N2FBFxi,M5N2FBFyi,M5N2FBFzi, & + M5N3FBFxi,M5N3FBFyi,M5N3FBFzi, & + M5N4FBFxi,M5N4FBFyi,M5N4FBFzi, & + M5N5FBFxi,M5N5FBFyi,M5N5FBFzi, & + M5N6FBFxi,M5N6FBFyi,M5N6FBFzi, & + M5N7FBFxi,M5N7FBFyi,M5N7FBFzi, & + M5N8FBFxi,M5N8FBFyi,M5N8FBFzi, & + M5N9FBFxi,M5N9FBFyi,M5N9FBFzi, & + M6N1FBFxi,M6N1FBFyi,M6N1FBFzi, & + M6N2FBFxi,M6N2FBFyi,M6N2FBFzi, & + M6N3FBFxi,M6N3FBFyi,M6N3FBFzi, & + M6N4FBFxi,M6N4FBFyi,M6N4FBFzi, & + M6N5FBFxi,M6N5FBFyi,M6N5FBFzi, & + M6N6FBFxi,M6N6FBFyi,M6N6FBFzi, & + M6N7FBFxi,M6N7FBFyi,M6N7FBFzi, & + M6N8FBFxi,M6N8FBFyi,M6N8FBFzi, & + M6N9FBFxi,M6N9FBFyi,M6N9FBFzi, & + M7N1FBFxi,M7N1FBFyi,M7N1FBFzi, & + M7N2FBFxi,M7N2FBFyi,M7N2FBFzi, & + M7N3FBFxi,M7N3FBFyi,M7N3FBFzi, & + M7N4FBFxi,M7N4FBFyi,M7N4FBFzi, & + M7N5FBFxi,M7N5FBFyi,M7N5FBFzi, & + M7N6FBFxi,M7N6FBFyi,M7N6FBFzi, & + M7N7FBFxi,M7N7FBFyi,M7N7FBFzi, & + M7N8FBFxi,M7N8FBFyi,M7N8FBFzi, & + M7N9FBFxi,M7N9FBFyi,M7N9FBFzi, & + M8N1FBFxi,M8N1FBFyi,M8N1FBFzi, & + M8N2FBFxi,M8N2FBFyi,M8N2FBFzi, & + M8N3FBFxi,M8N3FBFyi,M8N3FBFzi, & + M8N4FBFxi,M8N4FBFyi,M8N4FBFzi, & + M8N5FBFxi,M8N5FBFyi,M8N5FBFzi, & + M8N6FBFxi,M8N6FBFyi,M8N6FBFzi, & + M8N7FBFxi,M8N7FBFyi,M8N7FBFzi, & + M8N8FBFxi,M8N8FBFyi,M8N8FBFzi, & + M8N9FBFxi,M8N9FBFyi,M8N9FBFzi, & + M9N1FBFxi,M9N1FBFyi,M9N1FBFzi, & + M9N2FBFxi,M9N2FBFyi,M9N2FBFzi, & + M9N3FBFxi,M9N3FBFyi,M9N3FBFzi, & + M9N4FBFxi,M9N4FBFyi,M9N4FBFzi, & + M9N5FBFxi,M9N5FBFyi,M9N5FBFzi, & + M9N6FBFxi,M9N6FBFyi,M9N6FBFzi, & + M9N7FBFxi,M9N7FBFyi,M9N7FBFzi, & + M9N8FBFxi,M9N8FBFyi,M9N8FBFzi, & + M9N9FBFxi,M9N9FBFyi,M9N9FBFzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFMGi(3,9,9) = reshape((/M1N1FMGxi,M1N1FMGyi,M1N1FMGzi, & + M1N2FMGxi,M1N2FMGyi,M1N2FMGzi, & + M1N3FMGxi,M1N3FMGyi,M1N3FMGzi, & + M1N4FMGxi,M1N4FMGyi,M1N4FMGzi, & + M1N5FMGxi,M1N5FMGyi,M1N5FMGzi, & + M1N6FMGxi,M1N6FMGyi,M1N6FMGzi, & + M1N7FMGxi,M1N7FMGyi,M1N7FMGzi, & + M1N8FMGxi,M1N8FMGyi,M1N8FMGzi, & + M1N9FMGxi,M1N9FMGyi,M1N9FMGzi, & + M2N1FMGxi,M2N1FMGyi,M2N1FMGzi, & + M2N2FMGxi,M2N2FMGyi,M2N2FMGzi, & + M2N3FMGxi,M2N3FMGyi,M2N3FMGzi, & + M2N4FMGxi,M2N4FMGyi,M2N4FMGzi, & + M2N5FMGxi,M2N5FMGyi,M2N5FMGzi, & + M2N6FMGxi,M2N6FMGyi,M2N6FMGzi, & + M2N7FMGxi,M2N7FMGyi,M2N7FMGzi, & + M2N8FMGxi,M2N8FMGyi,M2N8FMGzi, & + M2N9FMGxi,M2N9FMGyi,M2N9FMGzi, & + M3N1FMGxi,M3N1FMGyi,M3N1FMGzi, & + M3N2FMGxi,M3N2FMGyi,M3N2FMGzi, & + M3N3FMGxi,M3N3FMGyi,M3N3FMGzi, & + M3N4FMGxi,M3N4FMGyi,M3N4FMGzi, & + M3N5FMGxi,M3N5FMGyi,M3N5FMGzi, & + M3N6FMGxi,M3N6FMGyi,M3N6FMGzi, & + M3N7FMGxi,M3N7FMGyi,M3N7FMGzi, & + M3N8FMGxi,M3N8FMGyi,M3N8FMGzi, & + M3N9FMGxi,M3N9FMGyi,M3N9FMGzi, & + M4N1FMGxi,M4N1FMGyi,M4N1FMGzi, & + M4N2FMGxi,M4N2FMGyi,M4N2FMGzi, & + M4N3FMGxi,M4N3FMGyi,M4N3FMGzi, & + M4N4FMGxi,M4N4FMGyi,M4N4FMGzi, & + M4N5FMGxi,M4N5FMGyi,M4N5FMGzi, & + M4N6FMGxi,M4N6FMGyi,M4N6FMGzi, & + M4N7FMGxi,M4N7FMGyi,M4N7FMGzi, & + M4N8FMGxi,M4N8FMGyi,M4N8FMGzi, & + M4N9FMGxi,M4N9FMGyi,M4N9FMGzi, & + M5N1FMGxi,M5N1FMGyi,M5N1FMGzi, & + M5N2FMGxi,M5N2FMGyi,M5N2FMGzi, & + M5N3FMGxi,M5N3FMGyi,M5N3FMGzi, & + M5N4FMGxi,M5N4FMGyi,M5N4FMGzi, & + M5N5FMGxi,M5N5FMGyi,M5N5FMGzi, & + M5N6FMGxi,M5N6FMGyi,M5N6FMGzi, & + M5N7FMGxi,M5N7FMGyi,M5N7FMGzi, & + M5N8FMGxi,M5N8FMGyi,M5N8FMGzi, & + M5N9FMGxi,M5N9FMGyi,M5N9FMGzi, & + M6N1FMGxi,M6N1FMGyi,M6N1FMGzi, & + M6N2FMGxi,M6N2FMGyi,M6N2FMGzi, & + M6N3FMGxi,M6N3FMGyi,M6N3FMGzi, & + M6N4FMGxi,M6N4FMGyi,M6N4FMGzi, & + M6N5FMGxi,M6N5FMGyi,M6N5FMGzi, & + M6N6FMGxi,M6N6FMGyi,M6N6FMGzi, & + M6N7FMGxi,M6N7FMGyi,M6N7FMGzi, & + M6N8FMGxi,M6N8FMGyi,M6N8FMGzi, & + M6N9FMGxi,M6N9FMGyi,M6N9FMGzi, & + M7N1FMGxi,M7N1FMGyi,M7N1FMGzi, & + M7N2FMGxi,M7N2FMGyi,M7N2FMGzi, & + M7N3FMGxi,M7N3FMGyi,M7N3FMGzi, & + M7N4FMGxi,M7N4FMGyi,M7N4FMGzi, & + M7N5FMGxi,M7N5FMGyi,M7N5FMGzi, & + M7N6FMGxi,M7N6FMGyi,M7N6FMGzi, & + M7N7FMGxi,M7N7FMGyi,M7N7FMGzi, & + M7N8FMGxi,M7N8FMGyi,M7N8FMGzi, & + M7N9FMGxi,M7N9FMGyi,M7N9FMGzi, & + M8N1FMGxi,M8N1FMGyi,M8N1FMGzi, & + M8N2FMGxi,M8N2FMGyi,M8N2FMGzi, & + M8N3FMGxi,M8N3FMGyi,M8N3FMGzi, & + M8N4FMGxi,M8N4FMGyi,M8N4FMGzi, & + M8N5FMGxi,M8N5FMGyi,M8N5FMGzi, & + M8N6FMGxi,M8N6FMGyi,M8N6FMGzi, & + M8N7FMGxi,M8N7FMGyi,M8N7FMGzi, & + M8N8FMGxi,M8N8FMGyi,M8N8FMGzi, & + M8N9FMGxi,M8N9FMGyi,M8N9FMGzi, & + M9N1FMGxi,M9N1FMGyi,M9N1FMGzi, & + M9N2FMGxi,M9N2FMGyi,M9N2FMGzi, & + M9N3FMGxi,M9N3FMGyi,M9N3FMGzi, & + M9N4FMGxi,M9N4FMGyi,M9N4FMGzi, & + M9N5FMGxi,M9N5FMGyi,M9N5FMGzi, & + M9N6FMGxi,M9N6FMGyi,M9N6FMGzi, & + M9N7FMGxi,M9N7FMGyi,M9N7FMGzi, & + M9N8FMGxi,M9N8FMGyi,M9N8FMGzi, & + M9N9FMGxi,M9N9FMGyi,M9N9FMGzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNMBi(3,9,9) = reshape((/M1N1MBxi,M1N1MByi,M1N1MBzi, & + M1N2MBxi,M1N2MByi,M1N2MBzi, & + M1N3MBxi,M1N3MByi,M1N3MBzi, & + M1N4MBxi,M1N4MByi,M1N4MBzi, & + M1N5MBxi,M1N5MByi,M1N5MBzi, & + M1N6MBxi,M1N6MByi,M1N6MBzi, & + M1N7MBxi,M1N7MByi,M1N7MBzi, & + M1N8MBxi,M1N8MByi,M1N8MBzi, & + M1N9MBxi,M1N9MByi,M1N9MBzi, & + M2N1MBxi,M2N1MByi,M2N1MBzi, & + M2N2MBxi,M2N2MByi,M2N2MBzi, & + M2N3MBxi,M2N3MByi,M2N3MBzi, & + M2N4MBxi,M2N4MByi,M2N4MBzi, & + M2N5MBxi,M2N5MByi,M2N5MBzi, & + M2N6MBxi,M2N6MByi,M2N6MBzi, & + M2N7MBxi,M2N7MByi,M2N7MBzi, & + M2N8MBxi,M2N8MByi,M2N8MBzi, & + M2N9MBxi,M2N9MByi,M2N9MBzi, & + M3N1MBxi,M3N1MByi,M3N1MBzi, & + M3N2MBxi,M3N2MByi,M3N2MBzi, & + M3N3MBxi,M3N3MByi,M3N3MBzi, & + M3N4MBxi,M3N4MByi,M3N4MBzi, & + M3N5MBxi,M3N5MByi,M3N5MBzi, & + M3N6MBxi,M3N6MByi,M3N6MBzi, & + M3N7MBxi,M3N7MByi,M3N7MBzi, & + M3N8MBxi,M3N8MByi,M3N8MBzi, & + M3N9MBxi,M3N9MByi,M3N9MBzi, & + M4N1MBxi,M4N1MByi,M4N1MBzi, & + M4N2MBxi,M4N2MByi,M4N2MBzi, & + M4N3MBxi,M4N3MByi,M4N3MBzi, & + M4N4MBxi,M4N4MByi,M4N4MBzi, & + M4N5MBxi,M4N5MByi,M4N5MBzi, & + M4N6MBxi,M4N6MByi,M4N6MBzi, & + M4N7MBxi,M4N7MByi,M4N7MBzi, & + M4N8MBxi,M4N8MByi,M4N8MBzi, & + M4N9MBxi,M4N9MByi,M4N9MBzi, & + M5N1MBxi,M5N1MByi,M5N1MBzi, & + M5N2MBxi,M5N2MByi,M5N2MBzi, & + M5N3MBxi,M5N3MByi,M5N3MBzi, & + M5N4MBxi,M5N4MByi,M5N4MBzi, & + M5N5MBxi,M5N5MByi,M5N5MBzi, & + M5N6MBxi,M5N6MByi,M5N6MBzi, & + M5N7MBxi,M5N7MByi,M5N7MBzi, & + M5N8MBxi,M5N8MByi,M5N8MBzi, & + M5N9MBxi,M5N9MByi,M5N9MBzi, & + M6N1MBxi,M6N1MByi,M6N1MBzi, & + M6N2MBxi,M6N2MByi,M6N2MBzi, & + M6N3MBxi,M6N3MByi,M6N3MBzi, & + M6N4MBxi,M6N4MByi,M6N4MBzi, & + M6N5MBxi,M6N5MByi,M6N5MBzi, & + M6N6MBxi,M6N6MByi,M6N6MBzi, & + M6N7MBxi,M6N7MByi,M6N7MBzi, & + M6N8MBxi,M6N8MByi,M6N8MBzi, & + M6N9MBxi,M6N9MByi,M6N9MBzi, & + M7N1MBxi,M7N1MByi,M7N1MBzi, & + M7N2MBxi,M7N2MByi,M7N2MBzi, & + M7N3MBxi,M7N3MByi,M7N3MBzi, & + M7N4MBxi,M7N4MByi,M7N4MBzi, & + M7N5MBxi,M7N5MByi,M7N5MBzi, & + M7N6MBxi,M7N6MByi,M7N6MBzi, & + M7N7MBxi,M7N7MByi,M7N7MBzi, & + M7N8MBxi,M7N8MByi,M7N8MBzi, & + M7N9MBxi,M7N9MByi,M7N9MBzi, & + M8N1MBxi,M8N1MByi,M8N1MBzi, & + M8N2MBxi,M8N2MByi,M8N2MBzi, & + M8N3MBxi,M8N3MByi,M8N3MBzi, & + M8N4MBxi,M8N4MByi,M8N4MBzi, & + M8N5MBxi,M8N5MByi,M8N5MBzi, & + M8N6MBxi,M8N6MByi,M8N6MBzi, & + M8N7MBxi,M8N7MByi,M8N7MBzi, & + M8N8MBxi,M8N8MByi,M8N8MBzi, & + M8N9MBxi,M8N9MByi,M8N9MBzi, & + M9N1MBxi,M9N1MByi,M9N1MBzi, & + M9N2MBxi,M9N2MByi,M9N2MBzi, & + M9N3MBxi,M9N3MByi,M9N3MBzi, & + M9N4MBxi,M9N4MByi,M9N4MBzi, & + M9N5MBxi,M9N5MByi,M9N5MBzi, & + M9N6MBxi,M9N6MByi,M9N6MBzi, & + M9N7MBxi,M9N7MByi,M9N7MBzi, & + M9N8MBxi,M9N8MByi,M9N8MBzi, & + M9N9MBxi,M9N9MByi,M9N9MBzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNMBFi(3,9,9) = reshape((/M1N1MBFxi,M1N1MBFyi,M1N1MBFzi, & + M1N2MBFxi,M1N2MBFyi,M1N2MBFzi, & + M1N3MBFxi,M1N3MBFyi,M1N3MBFzi, & + M1N4MBFxi,M1N4MBFyi,M1N4MBFzi, & + M1N5MBFxi,M1N5MBFyi,M1N5MBFzi, & + M1N6MBFxi,M1N6MBFyi,M1N6MBFzi, & + M1N7MBFxi,M1N7MBFyi,M1N7MBFzi, & + M1N8MBFxi,M1N8MBFyi,M1N8MBFzi, & + M1N9MBFxi,M1N9MBFyi,M1N9MBFzi, & + M2N1MBFxi,M2N1MBFyi,M2N1MBFzi, & + M2N2MBFxi,M2N2MBFyi,M2N2MBFzi, & + M2N3MBFxi,M2N3MBFyi,M2N3MBFzi, & + M2N4MBFxi,M2N4MBFyi,M2N4MBFzi, & + M2N5MBFxi,M2N5MBFyi,M2N5MBFzi, & + M2N6MBFxi,M2N6MBFyi,M2N6MBFzi, & + M2N7MBFxi,M2N7MBFyi,M2N7MBFzi, & + M2N8MBFxi,M2N8MBFyi,M2N8MBFzi, & + M2N9MBFxi,M2N9MBFyi,M2N9MBFzi, & + M3N1MBFxi,M3N1MBFyi,M3N1MBFzi, & + M3N2MBFxi,M3N2MBFyi,M3N2MBFzi, & + M3N3MBFxi,M3N3MBFyi,M3N3MBFzi, & + M3N4MBFxi,M3N4MBFyi,M3N4MBFzi, & + M3N5MBFxi,M3N5MBFyi,M3N5MBFzi, & + M3N6MBFxi,M3N6MBFyi,M3N6MBFzi, & + M3N7MBFxi,M3N7MBFyi,M3N7MBFzi, & + M3N8MBFxi,M3N8MBFyi,M3N8MBFzi, & + M3N9MBFxi,M3N9MBFyi,M3N9MBFzi, & + M4N1MBFxi,M4N1MBFyi,M4N1MBFzi, & + M4N2MBFxi,M4N2MBFyi,M4N2MBFzi, & + M4N3MBFxi,M4N3MBFyi,M4N3MBFzi, & + M4N4MBFxi,M4N4MBFyi,M4N4MBFzi, & + M4N5MBFxi,M4N5MBFyi,M4N5MBFzi, & + M4N6MBFxi,M4N6MBFyi,M4N6MBFzi, & + M4N7MBFxi,M4N7MBFyi,M4N7MBFzi, & + M4N8MBFxi,M4N8MBFyi,M4N8MBFzi, & + M4N9MBFxi,M4N9MBFyi,M4N9MBFzi, & + M5N1MBFxi,M5N1MBFyi,M5N1MBFzi, & + M5N2MBFxi,M5N2MBFyi,M5N2MBFzi, & + M5N3MBFxi,M5N3MBFyi,M5N3MBFzi, & + M5N4MBFxi,M5N4MBFyi,M5N4MBFzi, & + M5N5MBFxi,M5N5MBFyi,M5N5MBFzi, & + M5N6MBFxi,M5N6MBFyi,M5N6MBFzi, & + M5N7MBFxi,M5N7MBFyi,M5N7MBFzi, & + M5N8MBFxi,M5N8MBFyi,M5N8MBFzi, & + M5N9MBFxi,M5N9MBFyi,M5N9MBFzi, & + M6N1MBFxi,M6N1MBFyi,M6N1MBFzi, & + M6N2MBFxi,M6N2MBFyi,M6N2MBFzi, & + M6N3MBFxi,M6N3MBFyi,M6N3MBFzi, & + M6N4MBFxi,M6N4MBFyi,M6N4MBFzi, & + M6N5MBFxi,M6N5MBFyi,M6N5MBFzi, & + M6N6MBFxi,M6N6MBFyi,M6N6MBFzi, & + M6N7MBFxi,M6N7MBFyi,M6N7MBFzi, & + M6N8MBFxi,M6N8MBFyi,M6N8MBFzi, & + M6N9MBFxi,M6N9MBFyi,M6N9MBFzi, & + M7N1MBFxi,M7N1MBFyi,M7N1MBFzi, & + M7N2MBFxi,M7N2MBFyi,M7N2MBFzi, & + M7N3MBFxi,M7N3MBFyi,M7N3MBFzi, & + M7N4MBFxi,M7N4MBFyi,M7N4MBFzi, & + M7N5MBFxi,M7N5MBFyi,M7N5MBFzi, & + M7N6MBFxi,M7N6MBFyi,M7N6MBFzi, & + M7N7MBFxi,M7N7MBFyi,M7N7MBFzi, & + M7N8MBFxi,M7N8MBFyi,M7N8MBFzi, & + M7N9MBFxi,M7N9MBFyi,M7N9MBFzi, & + M8N1MBFxi,M8N1MBFyi,M8N1MBFzi, & + M8N2MBFxi,M8N2MBFyi,M8N2MBFzi, & + M8N3MBFxi,M8N3MBFyi,M8N3MBFzi, & + M8N4MBFxi,M8N4MBFyi,M8N4MBFzi, & + M8N5MBFxi,M8N5MBFyi,M8N5MBFzi, & + M8N6MBFxi,M8N6MBFyi,M8N6MBFzi, & + M8N7MBFxi,M8N7MBFyi,M8N7MBFzi, & + M8N8MBFxi,M8N8MBFyi,M8N8MBFzi, & + M8N9MBFxi,M8N9MBFyi,M8N9MBFzi, & + M9N1MBFxi,M9N1MBFyi,M9N1MBFzi, & + M9N2MBFxi,M9N2MBFyi,M9N2MBFzi, & + M9N3MBFxi,M9N3MBFyi,M9N3MBFzi, & + M9N4MBFxi,M9N4MBFyi,M9N4MBFzi, & + M9N5MBFxi,M9N5MBFyi,M9N5MBFzi, & + M9N6MBFxi,M9N6MBFyi,M9N6MBFzi, & + M9N7MBFxi,M9N7MBFyi,M9N7MBFzi, & + M9N8MBFxi,M9N8MBFyi,M9N8MBFzi, & + M9N9MBFxi,M9N9MBFyi,M9N9MBFzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFAMi(3,9,9) = reshape((/M1N1FAMxi,M1N1FAMyi,M1N1FAMzi, & + M1N2FAMxi,M1N2FAMyi,M1N2FAMzi, & + M1N3FAMxi,M1N3FAMyi,M1N3FAMzi, & + M1N4FAMxi,M1N4FAMyi,M1N4FAMzi, & + M1N5FAMxi,M1N5FAMyi,M1N5FAMzi, & + M1N6FAMxi,M1N6FAMyi,M1N6FAMzi, & + M1N7FAMxi,M1N7FAMyi,M1N7FAMzi, & + M1N8FAMxi,M1N8FAMyi,M1N8FAMzi, & + M1N9FAMxi,M1N9FAMyi,M1N9FAMzi, & + M2N1FAMxi,M2N1FAMyi,M2N1FAMzi, & + M2N2FAMxi,M2N2FAMyi,M2N2FAMzi, & + M2N3FAMxi,M2N3FAMyi,M2N3FAMzi, & + M2N4FAMxi,M2N4FAMyi,M2N4FAMzi, & + M2N5FAMxi,M2N5FAMyi,M2N5FAMzi, & + M2N6FAMxi,M2N6FAMyi,M2N6FAMzi, & + M2N7FAMxi,M2N7FAMyi,M2N7FAMzi, & + M2N8FAMxi,M2N8FAMyi,M2N8FAMzi, & + M2N9FAMxi,M2N9FAMyi,M2N9FAMzi, & + M3N1FAMxi,M3N1FAMyi,M3N1FAMzi, & + M3N2FAMxi,M3N2FAMyi,M3N2FAMzi, & + M3N3FAMxi,M3N3FAMyi,M3N3FAMzi, & + M3N4FAMxi,M3N4FAMyi,M3N4FAMzi, & + M3N5FAMxi,M3N5FAMyi,M3N5FAMzi, & + M3N6FAMxi,M3N6FAMyi,M3N6FAMzi, & + M3N7FAMxi,M3N7FAMyi,M3N7FAMzi, & + M3N8FAMxi,M3N8FAMyi,M3N8FAMzi, & + M3N9FAMxi,M3N9FAMyi,M3N9FAMzi, & + M4N1FAMxi,M4N1FAMyi,M4N1FAMzi, & + M4N2FAMxi,M4N2FAMyi,M4N2FAMzi, & + M4N3FAMxi,M4N3FAMyi,M4N3FAMzi, & + M4N4FAMxi,M4N4FAMyi,M4N4FAMzi, & + M4N5FAMxi,M4N5FAMyi,M4N5FAMzi, & + M4N6FAMxi,M4N6FAMyi,M4N6FAMzi, & + M4N7FAMxi,M4N7FAMyi,M4N7FAMzi, & + M4N8FAMxi,M4N8FAMyi,M4N8FAMzi, & + M4N9FAMxi,M4N9FAMyi,M4N9FAMzi, & + M5N1FAMxi,M5N1FAMyi,M5N1FAMzi, & + M5N2FAMxi,M5N2FAMyi,M5N2FAMzi, & + M5N3FAMxi,M5N3FAMyi,M5N3FAMzi, & + M5N4FAMxi,M5N4FAMyi,M5N4FAMzi, & + M5N5FAMxi,M5N5FAMyi,M5N5FAMzi, & + M5N6FAMxi,M5N6FAMyi,M5N6FAMzi, & + M5N7FAMxi,M5N7FAMyi,M5N7FAMzi, & + M5N8FAMxi,M5N8FAMyi,M5N8FAMzi, & + M5N9FAMxi,M5N9FAMyi,M5N9FAMzi, & + M6N1FAMxi,M6N1FAMyi,M6N1FAMzi, & + M6N2FAMxi,M6N2FAMyi,M6N2FAMzi, & + M6N3FAMxi,M6N3FAMyi,M6N3FAMzi, & + M6N4FAMxi,M6N4FAMyi,M6N4FAMzi, & + M6N5FAMxi,M6N5FAMyi,M6N5FAMzi, & + M6N6FAMxi,M6N6FAMyi,M6N6FAMzi, & + M6N7FAMxi,M6N7FAMyi,M6N7FAMzi, & + M6N8FAMxi,M6N8FAMyi,M6N8FAMzi, & + M6N9FAMxi,M6N9FAMyi,M6N9FAMzi, & + M7N1FAMxi,M7N1FAMyi,M7N1FAMzi, & + M7N2FAMxi,M7N2FAMyi,M7N2FAMzi, & + M7N3FAMxi,M7N3FAMyi,M7N3FAMzi, & + M7N4FAMxi,M7N4FAMyi,M7N4FAMzi, & + M7N5FAMxi,M7N5FAMyi,M7N5FAMzi, & + M7N6FAMxi,M7N6FAMyi,M7N6FAMzi, & + M7N7FAMxi,M7N7FAMyi,M7N7FAMzi, & + M7N8FAMxi,M7N8FAMyi,M7N8FAMzi, & + M7N9FAMxi,M7N9FAMyi,M7N9FAMzi, & + M8N1FAMxi,M8N1FAMyi,M8N1FAMzi, & + M8N2FAMxi,M8N2FAMyi,M8N2FAMzi, & + M8N3FAMxi,M8N3FAMyi,M8N3FAMzi, & + M8N4FAMxi,M8N4FAMyi,M8N4FAMzi, & + M8N5FAMxi,M8N5FAMyi,M8N5FAMzi, & + M8N6FAMxi,M8N6FAMyi,M8N6FAMzi, & + M8N7FAMxi,M8N7FAMyi,M8N7FAMzi, & + M8N8FAMxi,M8N8FAMyi,M8N8FAMzi, & + M8N9FAMxi,M8N9FAMyi,M8N9FAMzi, & + M9N1FAMxi,M9N1FAMyi,M9N1FAMzi, & + M9N2FAMxi,M9N2FAMyi,M9N2FAMzi, & + M9N3FAMxi,M9N3FAMyi,M9N3FAMzi, & + M9N4FAMxi,M9N4FAMyi,M9N4FAMzi, & + M9N5FAMxi,M9N5FAMyi,M9N5FAMzi, & + M9N6FAMxi,M9N6FAMyi,M9N6FAMzi, & + M9N7FAMxi,M9N7FAMyi,M9N7FAMzi, & + M9N8FAMxi,M9N8FAMyi,M9N8FAMzi, & + M9N9FAMxi,M9N9FAMyi,M9N9FAMzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFAGi(3,9,9) = reshape((/M1N1FAGxi,M1N1FAGyi,M1N1FAGzi, & + M1N2FAGxi,M1N2FAGyi,M1N2FAGzi, & + M1N3FAGxi,M1N3FAGyi,M1N3FAGzi, & + M1N4FAGxi,M1N4FAGyi,M1N4FAGzi, & + M1N5FAGxi,M1N5FAGyi,M1N5FAGzi, & + M1N6FAGxi,M1N6FAGyi,M1N6FAGzi, & + M1N7FAGxi,M1N7FAGyi,M1N7FAGzi, & + M1N8FAGxi,M1N8FAGyi,M1N8FAGzi, & + M1N9FAGxi,M1N9FAGyi,M1N9FAGzi, & + M2N1FAGxi,M2N1FAGyi,M2N1FAGzi, & + M2N2FAGxi,M2N2FAGyi,M2N2FAGzi, & + M2N3FAGxi,M2N3FAGyi,M2N3FAGzi, & + M2N4FAGxi,M2N4FAGyi,M2N4FAGzi, & + M2N5FAGxi,M2N5FAGyi,M2N5FAGzi, & + M2N6FAGxi,M2N6FAGyi,M2N6FAGzi, & + M2N7FAGxi,M2N7FAGyi,M2N7FAGzi, & + M2N8FAGxi,M2N8FAGyi,M2N8FAGzi, & + M2N9FAGxi,M2N9FAGyi,M2N9FAGzi, & + M3N1FAGxi,M3N1FAGyi,M3N1FAGzi, & + M3N2FAGxi,M3N2FAGyi,M3N2FAGzi, & + M3N3FAGxi,M3N3FAGyi,M3N3FAGzi, & + M3N4FAGxi,M3N4FAGyi,M3N4FAGzi, & + M3N5FAGxi,M3N5FAGyi,M3N5FAGzi, & + M3N6FAGxi,M3N6FAGyi,M3N6FAGzi, & + M3N7FAGxi,M3N7FAGyi,M3N7FAGzi, & + M3N8FAGxi,M3N8FAGyi,M3N8FAGzi, & + M3N9FAGxi,M3N9FAGyi,M3N9FAGzi, & + M4N1FAGxi,M4N1FAGyi,M4N1FAGzi, & + M4N2FAGxi,M4N2FAGyi,M4N2FAGzi, & + M4N3FAGxi,M4N3FAGyi,M4N3FAGzi, & + M4N4FAGxi,M4N4FAGyi,M4N4FAGzi, & + M4N5FAGxi,M4N5FAGyi,M4N5FAGzi, & + M4N6FAGxi,M4N6FAGyi,M4N6FAGzi, & + M4N7FAGxi,M4N7FAGyi,M4N7FAGzi, & + M4N8FAGxi,M4N8FAGyi,M4N8FAGzi, & + M4N9FAGxi,M4N9FAGyi,M4N9FAGzi, & + M5N1FAGxi,M5N1FAGyi,M5N1FAGzi, & + M5N2FAGxi,M5N2FAGyi,M5N2FAGzi, & + M5N3FAGxi,M5N3FAGyi,M5N3FAGzi, & + M5N4FAGxi,M5N4FAGyi,M5N4FAGzi, & + M5N5FAGxi,M5N5FAGyi,M5N5FAGzi, & + M5N6FAGxi,M5N6FAGyi,M5N6FAGzi, & + M5N7FAGxi,M5N7FAGyi,M5N7FAGzi, & + M5N8FAGxi,M5N8FAGyi,M5N8FAGzi, & + M5N9FAGxi,M5N9FAGyi,M5N9FAGzi, & + M6N1FAGxi,M6N1FAGyi,M6N1FAGzi, & + M6N2FAGxi,M6N2FAGyi,M6N2FAGzi, & + M6N3FAGxi,M6N3FAGyi,M6N3FAGzi, & + M6N4FAGxi,M6N4FAGyi,M6N4FAGzi, & + M6N5FAGxi,M6N5FAGyi,M6N5FAGzi, & + M6N6FAGxi,M6N6FAGyi,M6N6FAGzi, & + M6N7FAGxi,M6N7FAGyi,M6N7FAGzi, & + M6N8FAGxi,M6N8FAGyi,M6N8FAGzi, & + M6N9FAGxi,M6N9FAGyi,M6N9FAGzi, & + M7N1FAGxi,M7N1FAGyi,M7N1FAGzi, & + M7N2FAGxi,M7N2FAGyi,M7N2FAGzi, & + M7N3FAGxi,M7N3FAGyi,M7N3FAGzi, & + M7N4FAGxi,M7N4FAGyi,M7N4FAGzi, & + M7N5FAGxi,M7N5FAGyi,M7N5FAGzi, & + M7N6FAGxi,M7N6FAGyi,M7N6FAGzi, & + M7N7FAGxi,M7N7FAGyi,M7N7FAGzi, & + M7N8FAGxi,M7N8FAGyi,M7N8FAGzi, & + M7N9FAGxi,M7N9FAGyi,M7N9FAGzi, & + M8N1FAGxi,M8N1FAGyi,M8N1FAGzi, & + M8N2FAGxi,M8N2FAGyi,M8N2FAGzi, & + M8N3FAGxi,M8N3FAGyi,M8N3FAGzi, & + M8N4FAGxi,M8N4FAGyi,M8N4FAGzi, & + M8N5FAGxi,M8N5FAGyi,M8N5FAGzi, & + M8N6FAGxi,M8N6FAGyi,M8N6FAGzi, & + M8N7FAGxi,M8N7FAGyi,M8N7FAGzi, & + M8N8FAGxi,M8N8FAGyi,M8N8FAGzi, & + M8N9FAGxi,M8N9FAGyi,M8N9FAGzi, & + M9N1FAGxi,M9N1FAGyi,M9N1FAGzi, & + M9N2FAGxi,M9N2FAGyi,M9N2FAGzi, & + M9N3FAGxi,M9N3FAGyi,M9N3FAGzi, & + M9N4FAGxi,M9N4FAGyi,M9N4FAGzi, & + M9N5FAGxi,M9N5FAGyi,M9N5FAGzi, & + M9N6FAGxi,M9N6FAGyi,M9N6FAGzi, & + M9N7FAGxi,M9N7FAGyi,M9N7FAGzi, & + M9N8FAGxi,M9N8FAGyi,M9N8FAGzi, & + M9N9FAGxi,M9N9FAGyi,M9N9FAGzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFAFi(3,9,9) = reshape((/M1N1FAFxi,M1N1FAFyi,M1N1FAFzi, & + M1N2FAFxi,M1N2FAFyi,M1N2FAFzi, & + M1N3FAFxi,M1N3FAFyi,M1N3FAFzi, & + M1N4FAFxi,M1N4FAFyi,M1N4FAFzi, & + M1N5FAFxi,M1N5FAFyi,M1N5FAFzi, & + M1N6FAFxi,M1N6FAFyi,M1N6FAFzi, & + M1N7FAFxi,M1N7FAFyi,M1N7FAFzi, & + M1N8FAFxi,M1N8FAFyi,M1N8FAFzi, & + M1N9FAFxi,M1N9FAFyi,M1N9FAFzi, & + M2N1FAFxi,M2N1FAFyi,M2N1FAFzi, & + M2N2FAFxi,M2N2FAFyi,M2N2FAFzi, & + M2N3FAFxi,M2N3FAFyi,M2N3FAFzi, & + M2N4FAFxi,M2N4FAFyi,M2N4FAFzi, & + M2N5FAFxi,M2N5FAFyi,M2N5FAFzi, & + M2N6FAFxi,M2N6FAFyi,M2N6FAFzi, & + M2N7FAFxi,M2N7FAFyi,M2N7FAFzi, & + M2N8FAFxi,M2N8FAFyi,M2N8FAFzi, & + M2N9FAFxi,M2N9FAFyi,M2N9FAFzi, & + M3N1FAFxi,M3N1FAFyi,M3N1FAFzi, & + M3N2FAFxi,M3N2FAFyi,M3N2FAFzi, & + M3N3FAFxi,M3N3FAFyi,M3N3FAFzi, & + M3N4FAFxi,M3N4FAFyi,M3N4FAFzi, & + M3N5FAFxi,M3N5FAFyi,M3N5FAFzi, & + M3N6FAFxi,M3N6FAFyi,M3N6FAFzi, & + M3N7FAFxi,M3N7FAFyi,M3N7FAFzi, & + M3N8FAFxi,M3N8FAFyi,M3N8FAFzi, & + M3N9FAFxi,M3N9FAFyi,M3N9FAFzi, & + M4N1FAFxi,M4N1FAFyi,M4N1FAFzi, & + M4N2FAFxi,M4N2FAFyi,M4N2FAFzi, & + M4N3FAFxi,M4N3FAFyi,M4N3FAFzi, & + M4N4FAFxi,M4N4FAFyi,M4N4FAFzi, & + M4N5FAFxi,M4N5FAFyi,M4N5FAFzi, & + M4N6FAFxi,M4N6FAFyi,M4N6FAFzi, & + M4N7FAFxi,M4N7FAFyi,M4N7FAFzi, & + M4N8FAFxi,M4N8FAFyi,M4N8FAFzi, & + M4N9FAFxi,M4N9FAFyi,M4N9FAFzi, & + M5N1FAFxi,M5N1FAFyi,M5N1FAFzi, & + M5N2FAFxi,M5N2FAFyi,M5N2FAFzi, & + M5N3FAFxi,M5N3FAFyi,M5N3FAFzi, & + M5N4FAFxi,M5N4FAFyi,M5N4FAFzi, & + M5N5FAFxi,M5N5FAFyi,M5N5FAFzi, & + M5N6FAFxi,M5N6FAFyi,M5N6FAFzi, & + M5N7FAFxi,M5N7FAFyi,M5N7FAFzi, & + M5N8FAFxi,M5N8FAFyi,M5N8FAFzi, & + M5N9FAFxi,M5N9FAFyi,M5N9FAFzi, & + M6N1FAFxi,M6N1FAFyi,M6N1FAFzi, & + M6N2FAFxi,M6N2FAFyi,M6N2FAFzi, & + M6N3FAFxi,M6N3FAFyi,M6N3FAFzi, & + M6N4FAFxi,M6N4FAFyi,M6N4FAFzi, & + M6N5FAFxi,M6N5FAFyi,M6N5FAFzi, & + M6N6FAFxi,M6N6FAFyi,M6N6FAFzi, & + M6N7FAFxi,M6N7FAFyi,M6N7FAFzi, & + M6N8FAFxi,M6N8FAFyi,M6N8FAFzi, & + M6N9FAFxi,M6N9FAFyi,M6N9FAFzi, & + M7N1FAFxi,M7N1FAFyi,M7N1FAFzi, & + M7N2FAFxi,M7N2FAFyi,M7N2FAFzi, & + M7N3FAFxi,M7N3FAFyi,M7N3FAFzi, & + M7N4FAFxi,M7N4FAFyi,M7N4FAFzi, & + M7N5FAFxi,M7N5FAFyi,M7N5FAFzi, & + M7N6FAFxi,M7N6FAFyi,M7N6FAFzi, & + M7N7FAFxi,M7N7FAFyi,M7N7FAFzi, & + M7N8FAFxi,M7N8FAFyi,M7N8FAFzi, & + M7N9FAFxi,M7N9FAFyi,M7N9FAFzi, & + M8N1FAFxi,M8N1FAFyi,M8N1FAFzi, & + M8N2FAFxi,M8N2FAFyi,M8N2FAFzi, & + M8N3FAFxi,M8N3FAFyi,M8N3FAFzi, & + M8N4FAFxi,M8N4FAFyi,M8N4FAFzi, & + M8N5FAFxi,M8N5FAFyi,M8N5FAFzi, & + M8N6FAFxi,M8N6FAFyi,M8N6FAFzi, & + M8N7FAFxi,M8N7FAFyi,M8N7FAFzi, & + M8N8FAFxi,M8N8FAFyi,M8N8FAFzi, & + M8N9FAFxi,M8N9FAFyi,M8N9FAFzi, & + M9N1FAFxi,M9N1FAFyi,M9N1FAFzi, & + M9N2FAFxi,M9N2FAFyi,M9N2FAFzi, & + M9N3FAFxi,M9N3FAFyi,M9N3FAFzi, & + M9N4FAFxi,M9N4FAFyi,M9N4FAFzi, & + M9N5FAFxi,M9N5FAFyi,M9N5FAFzi, & + M9N6FAFxi,M9N6FAFyi,M9N6FAFzi, & + M9N7FAFxi,M9N7FAFyi,M9N7FAFzi, & + M9N8FAFxi,M9N8FAFyi,M9N8FAFzi, & + M9N9FAFxi,M9N9FAFyi,M9N9FAFzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: MNFAi(3,9,9) = reshape((/M1N1FAxi,M1N1FAyi,M1N1FAzi, & + M1N2FAxi,M1N2FAyi,M1N2FAzi, & + M1N3FAxi,M1N3FAyi,M1N3FAzi, & + M1N4FAxi,M1N4FAyi,M1N4FAzi, & + M1N5FAxi,M1N5FAyi,M1N5FAzi, & + M1N6FAxi,M1N6FAyi,M1N6FAzi, & + M1N7FAxi,M1N7FAyi,M1N7FAzi, & + M1N8FAxi,M1N8FAyi,M1N8FAzi, & + M1N9FAxi,M1N9FAyi,M1N9FAzi, & + M2N1FAxi,M2N1FAyi,M2N1FAzi, & + M2N2FAxi,M2N2FAyi,M2N2FAzi, & + M2N3FAxi,M2N3FAyi,M2N3FAzi, & + M2N4FAxi,M2N4FAyi,M2N4FAzi, & + M2N5FAxi,M2N5FAyi,M2N5FAzi, & + M2N6FAxi,M2N6FAyi,M2N6FAzi, & + M2N7FAxi,M2N7FAyi,M2N7FAzi, & + M2N8FAxi,M2N8FAyi,M2N8FAzi, & + M2N9FAxi,M2N9FAyi,M2N9FAzi, & + M3N1FAxi,M3N1FAyi,M3N1FAzi, & + M3N2FAxi,M3N2FAyi,M3N2FAzi, & + M3N3FAxi,M3N3FAyi,M3N3FAzi, & + M3N4FAxi,M3N4FAyi,M3N4FAzi, & + M3N5FAxi,M3N5FAyi,M3N5FAzi, & + M3N6FAxi,M3N6FAyi,M3N6FAzi, & + M3N7FAxi,M3N7FAyi,M3N7FAzi, & + M3N8FAxi,M3N8FAyi,M3N8FAzi, & + M3N9FAxi,M3N9FAyi,M3N9FAzi, & + M4N1FAxi,M4N1FAyi,M4N1FAzi, & + M4N2FAxi,M4N2FAyi,M4N2FAzi, & + M4N3FAxi,M4N3FAyi,M4N3FAzi, & + M4N4FAxi,M4N4FAyi,M4N4FAzi, & + M4N5FAxi,M4N5FAyi,M4N5FAzi, & + M4N6FAxi,M4N6FAyi,M4N6FAzi, & + M4N7FAxi,M4N7FAyi,M4N7FAzi, & + M4N8FAxi,M4N8FAyi,M4N8FAzi, & + M4N9FAxi,M4N9FAyi,M4N9FAzi, & + M5N1FAxi,M5N1FAyi,M5N1FAzi, & + M5N2FAxi,M5N2FAyi,M5N2FAzi, & + M5N3FAxi,M5N3FAyi,M5N3FAzi, & + M5N4FAxi,M5N4FAyi,M5N4FAzi, & + M5N5FAxi,M5N5FAyi,M5N5FAzi, & + M5N6FAxi,M5N6FAyi,M5N6FAzi, & + M5N7FAxi,M5N7FAyi,M5N7FAzi, & + M5N8FAxi,M5N8FAyi,M5N8FAzi, & + M5N9FAxi,M5N9FAyi,M5N9FAzi, & + M6N1FAxi,M6N1FAyi,M6N1FAzi, & + M6N2FAxi,M6N2FAyi,M6N2FAzi, & + M6N3FAxi,M6N3FAyi,M6N3FAzi, & + M6N4FAxi,M6N4FAyi,M6N4FAzi, & + M6N5FAxi,M6N5FAyi,M6N5FAzi, & + M6N6FAxi,M6N6FAyi,M6N6FAzi, & + M6N7FAxi,M6N7FAyi,M6N7FAzi, & + M6N8FAxi,M6N8FAyi,M6N8FAzi, & + M6N9FAxi,M6N9FAyi,M6N9FAzi, & + M7N1FAxi,M7N1FAyi,M7N1FAzi, & + M7N2FAxi,M7N2FAyi,M7N2FAzi, & + M7N3FAxi,M7N3FAyi,M7N3FAzi, & + M7N4FAxi,M7N4FAyi,M7N4FAzi, & + M7N5FAxi,M7N5FAyi,M7N5FAzi, & + M7N6FAxi,M7N6FAyi,M7N6FAzi, & + M7N7FAxi,M7N7FAyi,M7N7FAzi, & + M7N8FAxi,M7N8FAyi,M7N8FAzi, & + M7N9FAxi,M7N9FAyi,M7N9FAzi, & + M8N1FAxi,M8N1FAyi,M8N1FAzi, & + M8N2FAxi,M8N2FAyi,M8N2FAzi, & + M8N3FAxi,M8N3FAyi,M8N3FAzi, & + M8N4FAxi,M8N4FAyi,M8N4FAzi, & + M8N5FAxi,M8N5FAyi,M8N5FAzi, & + M8N6FAxi,M8N6FAyi,M8N6FAzi, & + M8N7FAxi,M8N7FAyi,M8N7FAzi, & + M8N8FAxi,M8N8FAyi,M8N8FAzi, & + M8N9FAxi,M8N9FAyi,M8N9FAzi, & + M9N1FAxi,M9N1FAyi,M9N1FAzi, & + M9N2FAxi,M9N2FAyi,M9N2FAzi, & + M9N3FAxi,M9N3FAyi,M9N3FAzi, & + M9N4FAxi,M9N4FAyi,M9N4FAzi, & + M9N5FAxi,M9N5FAyi,M9N5FAzi, & + M9N6FAxi,M9N6FAyi,M9N6FAzi, & + M9N7FAxi,M9N7FAyi,M9N7FAzi, & + M9N8FAxi,M9N8FAyi,M9N8FAzi, & + M9N9FAxi,M9N9FAyi,M9N9FAzi/), (/3,9,9/)) + + INTEGER, PARAMETER :: JVi(3,9) = reshape((/J1Vxi, J1Vyi, J1Vzi , & + J2Vxi, J2Vyi, J2Vzi , & + J3Vxi, J3Vyi, J3Vzi , & + J4Vxi, J4Vyi, J4Vzi , & + J5Vxi, J5Vyi, J5Vzi , & + J6Vxi, J6Vyi, J6Vzi , & + J7Vxi, J7Vyi, J7Vzi , & + J8Vxi, J8Vyi, J8Vzi , & + J9Vxi, J9Vyi, J9Vzi/), (/3,9/)) + + INTEGER, PARAMETER :: JAi(3,9) = reshape((/J1Axi, J1Ayi, J1Azi , & + J2Axi, J2Ayi, J2Azi , & + J3Axi, J3Ayi, J3Azi , & + J4Axi, J4Ayi, J4Azi , & + J5Axi, J5Ayi, J5Azi , & + J6Axi, J6Ayi, J6Azi , & + J7Axi, J7Ayi, J7Azi , & + J8Axi, J8Ayi, J8Azi , & + J9Axi, J9Ayi, J9Azi/), (/3,9/)) + + INTEGER, PARAMETER :: JDynP(9) = reshape((/J1DynP, J2DynP, J3DynP , & + J4DynP, J5DynP, J6DynP , & + J7DynP, J8DynP, J9DynP/), (/9/)) + + INTEGER, PARAMETER :: JSTVi(3,9) = reshape((/J1STVxi, J1STVyi, J1STVzi , & + J2STVxi, J2STVyi, J2STVzi , & + J3STVxi, J3STVyi, J3STVzi , & + J4STVxi, J4STVyi, J4STVzi , & + J5STVxi, J5STVyi, J5STVzi , & + J6STVxi, J6STVyi, J6STVzi , & + J7STVxi, J7STVyi, J7STVzi , & + J8STVxi, J8STVyi, J8STVzi , & + J9STVxi, J9STVyi, J9STVzi/), (/3,9/)) + + INTEGER, PARAMETER :: JSTAi(3,9) = reshape((/J1STAxi, J1STAyi, J1STAzi , & + J2STAxi, J2STAyi, J2STAzi , & + J3STAxi, J3STAyi, J3STAzi , & + J4STAxi, J4STAyi, J4STAzi , & + J5STAxi, J5STAyi, J5STAzi , & + J6STAxi, J6STAyi, J6STAzi , & + J7STAxi, J7STAyi, J7STAzi , & + J8STAxi, J8STAyi, J8STAzi , & + J9STAxi, J9STAyi, J9STAzi/), (/3,9/)) + + INTEGER, PARAMETER :: JFDi(3,9) = reshape((/J1FDxi, J1FDyi, J1FDzi , & + J2FDxi, J2FDyi, J2FDzi , & + J3FDxi, J3FDyi, J3FDzi , & + J4FDxi, J4FDyi, J4FDzi , & + J5FDxi, J5FDyi, J5FDzi , & + J6FDxi, J6FDyi, J6FDzi , & + J7FDxi, J7FDyi, J7FDzi , & + J8FDxi, J8FDyi, J8FDzi , & + J9FDxi, J9FDyi, J9FDzi/), (/3,9/)) + + INTEGER, PARAMETER :: JFBi(3,9) = reshape((/J1FBxi, J1FByi, J1FBzi , & + J2FBxi, J2FByi, J2FBzi , & + J3FBxi, J3FByi, J3FBzi , & + J4FBxi, J4FByi, J4FBzi , & + J5FBxi, J5FByi, J5FBzi , & + J6FBxi, J6FByi, J6FBzi , & + J7FBxi, J7FByi, J7FBzi , & + J8FBxi, J8FByi, J8FBzi , & + J9FBxi, J9FByi, J9FBzi/), (/3,9/)) + + INTEGER, PARAMETER :: JFIi(3,9) = reshape((/J1FIxi, J1FIyi, J1FIzi , & + J2FIxi, J2FIyi, J2FIzi , & + J3FIxi, J3FIyi, J3FIzi , & + J4FIxi, J4FIyi, J4FIzi , & + J5FIxi, J5FIyi, J5FIzi , & + J6FIxi, J6FIyi, J6FIzi , & + J7FIxi, J7FIyi, J7FIzi , & + J8FIxi, J8FIyi, J8FIzi , & + J9FIxi, J9FIyi, J9FIzi/), (/3,9/)) + + INTEGER, PARAMETER :: JMBi(3,9) = reshape((/J1MBxi, J1MByi, J1MBzi , & + J2MBxi, J2MByi, J2MBzi , & + J3MBxi, J3MByi, J3MBzi , & + J4MBxi, J4MByi, J4MBzi , & + J5MBxi, J5MByi, J5MBzi , & + J6MBxi, J6MByi, J6MBzi , & + J7MBxi, J7MByi, J7MBzi , & + J8MBxi, J8MByi, J8MBzi , & + J9MBxi, J9MByi, J9MBzi/), (/3,9/)) + + INTEGER, PARAMETER :: JFBFi(3,9) = reshape((/J1FBFxi, J1FBFyi, J1FBFzi , & + J2FBFxi, J2FBFyi, J2FBFzi , & + J3FBFxi, J3FBFyi, J3FBFzi , & + J4FBFxi, J4FBFyi, J4FBFzi , & + J5FBFxi, J5FBFyi, J5FBFzi , & + J6FBFxi, J6FBFyi, J6FBFzi , & + J7FBFxi, J7FBFyi, J7FBFzi , & + J8FBFxi, J8FBFyi, J8FBFzi , & + J9FBFxi, J9FBFyi, J9FBFzi/), (/3,9/)) + + INTEGER, PARAMETER :: JMBFi(3,9) = reshape((/J1MBFxi, J1MBFyi, J1MBFzi , & + J2MBFxi, J2MBFyi, J2MBFzi , & + J3MBFxi, J3MBFyi, J3MBFzi , & + J4MBFxi, J4MBFyi, J4MBFzi , & + J5MBFxi, J5MBFyi, J5MBFzi , & + J6MBFxi, J6MBFyi, J6MBFzi , & + J7MBFxi, J7MBFyi, J7MBFzi , & + J8MBFxi, J8MBFyi, J8MBFzi , & + J9MBFxi, J9MBFyi, J9MBFzi/), (/3,9/)) + + + + INTEGER, PARAMETER :: JFAMi(3,9) = reshape((/J1FAMxi, J1FAMyi, J1FAMzi , & + J2FAMxi, J2FAMyi, J2FAMzi , & + J3FAMxi, J3FAMyi, J3FAMzi , & + J4FAMxi, J4FAMyi, J4FAMzi , & + J5FAMxi, J5FAMyi, J5FAMzi , & + J6FAMxi, J6FAMyi, J6FAMzi , & + J7FAMxi, J7FAMyi, J7FAMzi , & + J8FAMxi, J8FAMyi, J8FAMzi , & + J9FAMxi, J9FAMyi, J9FAMzi/), (/3,9/)) + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 04-Jan-2014 12:13:30. + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(4032) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "J1AXI ","J1AYI ","J1AZI ","J1DYNP ","J1FAMXI ","J1FAMYI ","J1FAMZI ","J1FBFXI ","J1FBFYI ","J1FBFZI ", & + "J1FBXI ","J1FBYI ","J1FBZI ","J1FDXI ","J1FDYI ","J1FDZI ","J1FIXI ","J1FIYI ","J1FIZI ","J1MBFXI ", & + "J1MBFYI ","J1MBFZI ","J1MBXI ","J1MBYI ","J1MBZI ","J1STAXI ","J1STAYI ","J1STAZI ","J1STVXI ","J1STVYI ", & + "J1STVZI ","J1VXI ","J1VYI ","J1VZI ","J2AXI ","J2AYI ","J2AZI ","J2DYNP ","J2FAMXI ","J2FAMYI ", & + "J2FAMZI ","J2FBFXI ","J2FBFYI ","J2FBFZI ","J2FBXI ","J2FBYI ","J2FBZI ","J2FDXI ","J2FDYI ","J2FDZI ", & + "J2FIXI ","J2FIYI ","J2FIZI ","J2MBFXI ","J2MBFYI ","J2MBFZI ","J2MBXI ","J2MBYI ","J2MBZI ","J2STAXI ", & + "J2STAYI ","J2STAZI ","J2STVXI ","J2STVYI ","J2STVZI ","J2VXI ","J2VYI ","J2VZI ","J3AXI ","J3AYI ", & + "J3AZI ","J3DYNP ","J3FAMXI ","J3FAMYI ","J3FAMZI ","J3FBFXI ","J3FBFYI ","J3FBFZI ","J3FBXI ","J3FBYI ", & + "J3FBZI ","J3FDXI ","J3FDYI ","J3FDZI ","J3FIXI ","J3FIYI ","J3FIZI ","J3MBFXI ","J3MBFYI ","J3MBFZI ", & + "J3MBXI ","J3MBYI ","J3MBZI ","J3STAXI ","J3STAYI ","J3STAZI ","J3STVXI ","J3STVYI ","J3STVZI ","J3VXI ", & + "J3VYI ","J3VZI ","J4AXI ","J4AYI ","J4AZI ","J4DYNP ","J4FAMXI ","J4FAMYI ","J4FAMZI ","J4FBFXI ", & + "J4FBFYI ","J4FBFZI ","J4FBXI ","J4FBYI ","J4FBZI ","J4FDXI ","J4FDYI ","J4FDZI ","J4FIXI ","J4FIYI ", & + "J4FIZI ","J4MBFXI ","J4MBFYI ","J4MBFZI ","J4MBXI ","J4MBYI ","J4MBZI ","J4STAXI ","J4STAYI ","J4STAZI ", & + "J4STVXI ","J4STVYI ","J4STVZI ","J4VXI ","J4VYI ","J4VZI ","J5AXI ","J5AYI ","J5AZI ","J5DYNP ", & + "J5FAMXI ","J5FAMYI ","J5FAMZI ","J5FBFXI ","J5FBFYI ","J5FBFZI ","J5FBXI ","J5FBYI ","J5FBZI ","J5FDXI ", & + "J5FDYI ","J5FDZI ","J5FIXI ","J5FIYI ","J5FIZI ","J5MBFXI ","J5MBFYI ","J5MBFZI ","J5MBXI ","J5MBYI ", & + "J5MBZI ","J5STAXI ","J5STAYI ","J5STAZI ","J5STVXI ","J5STVYI ","J5STVZI ","J5VXI ","J5VYI ","J5VZI ", & + "J6AXI ","J6AYI ","J6AZI ","J6DYNP ","J6FAMXI ","J6FAMYI ","J6FAMZI ","J6FBFXI ","J6FBFYI ","J6FBFZI ", & + "J6FBXI ","J6FBYI ","J6FBZI ","J6FDXI ","J6FDYI ","J6FDZI ","J6FIXI ","J6FIYI ","J6FIZI ","J6MBFXI ", & + "J6MBFYI ","J6MBFZI ","J6MBXI ","J6MBYI ","J6MBZI ","J6STAXI ","J6STAYI ","J6STAZI ","J6STVXI ","J6STVYI ", & + "J6STVZI ","J6VXI ","J6VYI ","J6VZI ","J7AXI ","J7AYI ","J7AZI ","J7DYNP ","J7FAMXI ","J7FAMYI ", & + "J7FAMZI ","J7FBFXI ","J7FBFYI ","J7FBFZI ","J7FBXI ","J7FBYI ","J7FBZI ","J7FDXI ","J7FDYI ","J7FDZI ", & + "J7FIXI ","J7FIYI ","J7FIZI ","J7MBFXI ","J7MBFYI ","J7MBFZI ","J7MBXI ","J7MBYI ","J7MBZI ","J7STAXI ", & + "J7STAYI ","J7STAZI ","J7STVXI ","J7STVYI ","J7STVZI ","J7VXI ","J7VYI ","J7VZI ","J8AXI ","J8AYI ", & + "J8AZI ","J8DYNP ","J8FAMXI ","J8FAMYI ","J8FAMZI ","J8FBFXI ","J8FBFYI ","J8FBFZI ","J8FBXI ","J8FBYI ", & + "J8FBZI ","J8FDXI ","J8FDYI ","J8FDZI ","J8FIXI ","J8FIYI ","J8FIZI ","J8MBFXI ","J8MBFYI ","J8MBFZI ", & + "J8MBXI ","J8MBYI ","J8MBZI ","J8STAXI ","J8STAYI ","J8STAZI ","J8STVXI ","J8STVYI ","J8STVZI ","J8VXI ", & + "J8VYI ","J8VZI ","J9AXI ","J9AYI ","J9AZI ","J9DYNP ","J9FAMXI ","J9FAMYI ","J9FAMZI ","J9FBFXI ", & + "J9FBFYI ","J9FBFZI ","J9FBXI ","J9FBYI ","J9FBZI ","J9FDXI ","J9FDYI ","J9FDZI ","J9FIXI ","J9FIYI ", & + "J9FIZI ","J9MBFXI ","J9MBFYI ","J9MBFZI ","J9MBXI ","J9MBYI ","J9MBZI ","J9STAXI ","J9STAYI ","J9STAZI ", & + "J9STVXI ","J9STVYI ","J9STVZI ","J9VXI ","J9VYI ","J9VZI ","M1N1AXI ","M1N1AYI ","M1N1AZI ","M1N1DYNP ", & + "M1N1FAFXI","M1N1FAFYI","M1N1FAFZI","M1N1FAGXI","M1N1FAGYI","M1N1FAGZI","M1N1FAMXI","M1N1FAMYI","M1N1FAMZI","M1N1FAXI ", & + "M1N1FAYI ","M1N1FAZI ","M1N1FBFXI","M1N1FBFYI","M1N1FBFZI","M1N1FBXI ","M1N1FBYI ","M1N1FBZI ","M1N1FDXI ","M1N1FDYI ", & + "M1N1FDZI ","M1N1FIXI ","M1N1FIYI ","M1N1FIZI ","M1N1FMGXI","M1N1FMGYI","M1N1FMGZI","M1N1MBFXI","M1N1MBFYI","M1N1MBFZI", & + "M1N1MBXI ","M1N1MBYI ","M1N1MBZI ","M1N1STAXI","M1N1STAYI","M1N1STAZI","M1N1STVXI","M1N1STVYI","M1N1STVZI","M1N1VXI ", & + "M1N1VYI ","M1N1VZI ","M1N2AXI ","M1N2AYI ","M1N2AZI ","M1N2DYNP ","M1N2FAFXI","M1N2FAFYI","M1N2FAFZI","M1N2FAGXI", & + "M1N2FAGYI","M1N2FAGZI","M1N2FAMXI","M1N2FAMYI","M1N2FAMZI","M1N2FAXI ","M1N2FAYI ","M1N2FAZI ","M1N2FBFXI","M1N2FBFYI", & + "M1N2FBFZI","M1N2FBXI ","M1N2FBYI ","M1N2FBZI ","M1N2FDXI ","M1N2FDYI ","M1N2FDZI ","M1N2FIXI ","M1N2FIYI ","M1N2FIZI ", & + "M1N2FMGXI","M1N2FMGYI","M1N2FMGZI","M1N2MBFXI","M1N2MBFYI","M1N2MBFZI","M1N2MBXI ","M1N2MBYI ","M1N2MBZI ","M1N2STAXI", & + "M1N2STAYI","M1N2STAZI","M1N2STVXI","M1N2STVYI","M1N2STVZI","M1N2VXI ","M1N2VYI ","M1N2VZI ","M1N3AXI ","M1N3AYI ", & + "M1N3AZI ","M1N3DYNP ","M1N3FAFXI","M1N3FAFYI","M1N3FAFZI","M1N3FAGXI","M1N3FAGYI","M1N3FAGZI","M1N3FAMXI","M1N3FAMYI", & + "M1N3FAMZI","M1N3FAXI ","M1N3FAYI ","M1N3FAZI ","M1N3FBFXI","M1N3FBFYI","M1N3FBFZI","M1N3FBXI ","M1N3FBYI ","M1N3FBZI ", & + "M1N3FDXI ","M1N3FDYI ","M1N3FDZI ","M1N3FIXI ","M1N3FIYI ","M1N3FIZI ","M1N3FMGXI","M1N3FMGYI","M1N3FMGZI","M1N3MBFXI", & + "M1N3MBFYI","M1N3MBFZI","M1N3MBXI ","M1N3MBYI ","M1N3MBZI ","M1N3STAXI","M1N3STAYI","M1N3STAZI","M1N3STVXI","M1N3STVYI", & + "M1N3STVZI","M1N3VXI ","M1N3VYI ","M1N3VZI ","M1N4AXI ","M1N4AYI ","M1N4AZI ","M1N4DYNP ","M1N4FAFXI","M1N4FAFYI", & + "M1N4FAFZI","M1N4FAGXI","M1N4FAGYI","M1N4FAGZI","M1N4FAMXI","M1N4FAMYI","M1N4FAMZI","M1N4FAXI ","M1N4FAYI ","M1N4FAZI ", & + "M1N4FBFXI","M1N4FBFYI","M1N4FBFZI","M1N4FBXI ","M1N4FBYI ","M1N4FBZI ","M1N4FDXI ","M1N4FDYI ","M1N4FDZI ","M1N4FIXI ", & + "M1N4FIYI ","M1N4FIZI ","M1N4FMGXI","M1N4FMGYI","M1N4FMGZI","M1N4MBFXI","M1N4MBFYI","M1N4MBFZI","M1N4MBXI ","M1N4MBYI ", & + "M1N4MBZI ","M1N4STAXI","M1N4STAYI","M1N4STAZI","M1N4STVXI","M1N4STVYI","M1N4STVZI","M1N4VXI ","M1N4VYI ","M1N4VZI ", & + "M1N5AXI ","M1N5AYI ","M1N5AZI ","M1N5DYNP ","M1N5FAFXI","M1N5FAFYI","M1N5FAFZI","M1N5FAGXI","M1N5FAGYI","M1N5FAGZI", & + "M1N5FAMXI","M1N5FAMYI","M1N5FAMZI","M1N5FAXI ","M1N5FAYI ","M1N5FAZI ","M1N5FBFXI","M1N5FBFYI","M1N5FBFZI","M1N5FBXI ", & + "M1N5FBYI ","M1N5FBZI ","M1N5FDXI ","M1N5FDYI ","M1N5FDZI ","M1N5FIXI ","M1N5FIYI ","M1N5FIZI ","M1N5FMGXI","M1N5FMGYI", & + "M1N5FMGZI","M1N5MBFXI","M1N5MBFYI","M1N5MBFZI","M1N5MBXI ","M1N5MBYI ","M1N5MBZI ","M1N5STAXI","M1N5STAYI","M1N5STAZI", & + "M1N5STVXI","M1N5STVYI","M1N5STVZI","M1N5VXI ","M1N5VYI ","M1N5VZI ","M1N6AXI ","M1N6AYI ","M1N6AZI ","M1N6DYNP ", & + "M1N6FAFXI","M1N6FAFYI","M1N6FAFZI","M1N6FAGXI","M1N6FAGYI","M1N6FAGZI","M1N6FAMXI","M1N6FAMYI","M1N6FAMZI","M1N6FAXI ", & + "M1N6FAYI ","M1N6FAZI ","M1N6FBFXI","M1N6FBFYI","M1N6FBFZI","M1N6FBXI ","M1N6FBYI ","M1N6FBZI ","M1N6FDXI ","M1N6FDYI ", & + "M1N6FDZI ","M1N6FIXI ","M1N6FIYI ","M1N6FIZI ","M1N6FMGXI","M1N6FMGYI","M1N6FMGZI","M1N6MBFXI","M1N6MBFYI","M1N6MBFZI", & + "M1N6MBXI ","M1N6MBYI ","M1N6MBZI ","M1N6STAXI","M1N6STAYI","M1N6STAZI","M1N6STVXI","M1N6STVYI","M1N6STVZI","M1N6VXI ", & + "M1N6VYI ","M1N6VZI ","M1N7AXI ","M1N7AYI ","M1N7AZI ","M1N7DYNP ","M1N7FAFXI","M1N7FAFYI","M1N7FAFZI","M1N7FAGXI", & + "M1N7FAGYI","M1N7FAGZI","M1N7FAMXI","M1N7FAMYI","M1N7FAMZI","M1N7FAXI ","M1N7FAYI ","M1N7FAZI ","M1N7FBFXI","M1N7FBFYI", & + "M1N7FBFZI","M1N7FBXI ","M1N7FBYI ","M1N7FBZI ","M1N7FDXI ","M1N7FDYI ","M1N7FDZI ","M1N7FIXI ","M1N7FIYI ","M1N7FIZI ", & + "M1N7FMGXI","M1N7FMGYI","M1N7FMGZI","M1N7MBFXI","M1N7MBFYI","M1N7MBFZI","M1N7MBXI ","M1N7MBYI ","M1N7MBZI ","M1N7STAXI", & + "M1N7STAYI","M1N7STAZI","M1N7STVXI","M1N7STVYI","M1N7STVZI","M1N7VXI ","M1N7VYI ","M1N7VZI ","M1N8AXI ","M1N8AYI ", & + "M1N8AZI ","M1N8DYNP ","M1N8FAFXI","M1N8FAFYI","M1N8FAFZI","M1N8FAGXI","M1N8FAGYI","M1N8FAGZI","M1N8FAMXI","M1N8FAMYI", & + "M1N8FAMZI","M1N8FAXI ","M1N8FAYI ","M1N8FAZI ","M1N8FBFXI","M1N8FBFYI","M1N8FBFZI","M1N8FBXI ","M1N8FBYI ","M1N8FBZI ", & + "M1N8FDXI ","M1N8FDYI ","M1N8FDZI ","M1N8FIXI ","M1N8FIYI ","M1N8FIZI ","M1N8FMGXI","M1N8FMGYI","M1N8FMGZI","M1N8MBFXI", & + "M1N8MBFYI","M1N8MBFZI","M1N8MBXI ","M1N8MBYI ","M1N8MBZI ","M1N8STAXI","M1N8STAYI","M1N8STAZI","M1N8STVXI","M1N8STVYI", & + "M1N8STVZI","M1N8VXI ","M1N8VYI ","M1N8VZI ","M1N9AXI ","M1N9AYI ","M1N9AZI ","M1N9DYNP ","M1N9FAFXI","M1N9FAFYI", & + "M1N9FAFZI","M1N9FAGXI","M1N9FAGYI","M1N9FAGZI","M1N9FAMXI","M1N9FAMYI","M1N9FAMZI","M1N9FAXI ","M1N9FAYI ","M1N9FAZI ", & + "M1N9FBFXI","M1N9FBFYI","M1N9FBFZI","M1N9FBXI ","M1N9FBYI ","M1N9FBZI ","M1N9FDXI ","M1N9FDYI ","M1N9FDZI ","M1N9FIXI ", & + "M1N9FIYI ","M1N9FIZI ","M1N9FMGXI","M1N9FMGYI","M1N9FMGZI","M1N9MBFXI","M1N9MBFYI","M1N9MBFZI","M1N9MBXI ","M1N9MBYI ", & + "M1N9MBZI ","M1N9STAXI","M1N9STAYI","M1N9STAZI","M1N9STVXI","M1N9STVYI","M1N9STVZI","M1N9VXI ","M1N9VYI ","M1N9VZI ", & + "M2N1AXI ","M2N1AYI ","M2N1AZI ","M2N1DYNP ","M2N1FAFXI","M2N1FAFYI","M2N1FAFZI","M2N1FAGXI","M2N1FAGYI","M2N1FAGZI", & + "M2N1FAMXI","M2N1FAMYI","M2N1FAMZI","M2N1FAXI ","M2N1FAYI ","M2N1FAZI ","M2N1FBFXI","M2N1FBFYI","M2N1FBFZI","M2N1FBXI ", & + "M2N1FBYI ","M2N1FBZI ","M2N1FDXI ","M2N1FDYI ","M2N1FDZI ","M2N1FIXI ","M2N1FIYI ","M2N1FIZI ","M2N1FMGXI","M2N1FMGYI", & + "M2N1FMGZI","M2N1MBFXI","M2N1MBFYI","M2N1MBFZI","M2N1MBXI ","M2N1MBYI ","M2N1MBZI ","M2N1STAXI","M2N1STAYI","M2N1STAZI", & + "M2N1STVXI","M2N1STVYI","M2N1STVZI","M2N1VXI ","M2N1VYI ","M2N1VZI ","M2N2AXI ","M2N2AYI ","M2N2AZI ","M2N2DYNP ", & + "M2N2FAFXI","M2N2FAFYI","M2N2FAFZI","M2N2FAGXI","M2N2FAGYI","M2N2FAGZI","M2N2FAMXI","M2N2FAMYI","M2N2FAMZI","M2N2FAXI ", & + "M2N2FAYI ","M2N2FAZI ","M2N2FBFXI","M2N2FBFYI","M2N2FBFZI","M2N2FBXI ","M2N2FBYI ","M2N2FBZI ","M2N2FDXI ","M2N2FDYI ", & + "M2N2FDZI ","M2N2FIXI ","M2N2FIYI ","M2N2FIZI ","M2N2FMGXI","M2N2FMGYI","M2N2FMGZI","M2N2MBFXI","M2N2MBFYI","M2N2MBFZI", & + "M2N2MBXI ","M2N2MBYI ","M2N2MBZI ","M2N2STAXI","M2N2STAYI","M2N2STAZI","M2N2STVXI","M2N2STVYI","M2N2STVZI","M2N2VXI ", & + "M2N2VYI ","M2N2VZI ","M2N3AXI ","M2N3AYI ","M2N3AZI ","M2N3DYNP ","M2N3FAFXI","M2N3FAFYI","M2N3FAFZI","M2N3FAGXI", & + "M2N3FAGYI","M2N3FAGZI","M2N3FAMXI","M2N3FAMYI","M2N3FAMZI","M2N3FAXI ","M2N3FAYI ","M2N3FAZI ","M2N3FBFXI","M2N3FBFYI", & + "M2N3FBFZI","M2N3FBXI ","M2N3FBYI ","M2N3FBZI ","M2N3FDXI ","M2N3FDYI ","M2N3FDZI ","M2N3FIXI ","M2N3FIYI ","M2N3FIZI ", & + "M2N3FMGXI","M2N3FMGYI","M2N3FMGZI","M2N3MBFXI","M2N3MBFYI","M2N3MBFZI","M2N3MBXI ","M2N3MBYI ","M2N3MBZI ","M2N3STAXI", & + "M2N3STAYI","M2N3STAZI","M2N3STVXI","M2N3STVYI","M2N3STVZI","M2N3VXI ","M2N3VYI ","M2N3VZI ","M2N4AXI ","M2N4AYI ", & + "M2N4AZI ","M2N4DYNP ","M2N4FAFXI","M2N4FAFYI","M2N4FAFZI","M2N4FAGXI","M2N4FAGYI","M2N4FAGZI","M2N4FAMXI","M2N4FAMYI", & + "M2N4FAMZI","M2N4FAXI ","M2N4FAYI ","M2N4FAZI ","M2N4FBFXI","M2N4FBFYI","M2N4FBFZI","M2N4FBXI ","M2N4FBYI ","M2N4FBZI ", & + "M2N4FDXI ","M2N4FDYI ","M2N4FDZI ","M2N4FIXI ","M2N4FIYI ","M2N4FIZI ","M2N4FMGXI","M2N4FMGYI","M2N4FMGZI","M2N4MBFXI", & + "M2N4MBFYI","M2N4MBFZI","M2N4MBXI ","M2N4MBYI ","M2N4MBZI ","M2N4STAXI","M2N4STAYI","M2N4STAZI","M2N4STVXI","M2N4STVYI", & + "M2N4STVZI","M2N4VXI ","M2N4VYI ","M2N4VZI ","M2N5AXI ","M2N5AYI ","M2N5AZI ","M2N5DYNP ","M2N5FAFXI","M2N5FAFYI", & + "M2N5FAFZI","M2N5FAGXI","M2N5FAGYI","M2N5FAGZI","M2N5FAMXI","M2N5FAMYI","M2N5FAMZI","M2N5FAXI ","M2N5FAYI ","M2N5FAZI ", & + "M2N5FBFXI","M2N5FBFYI","M2N5FBFZI","M2N5FBXI ","M2N5FBYI ","M2N5FBZI ","M2N5FDXI ","M2N5FDYI ","M2N5FDZI ","M2N5FIXI ", & + "M2N5FIYI ","M2N5FIZI ","M2N5FMGXI","M2N5FMGYI","M2N5FMGZI","M2N5MBFXI","M2N5MBFYI","M2N5MBFZI","M2N5MBXI ","M2N5MBYI ", & + "M2N5MBZI ","M2N5STAXI","M2N5STAYI","M2N5STAZI","M2N5STVXI","M2N5STVYI","M2N5STVZI","M2N5VXI ","M2N5VYI ","M2N5VZI ", & + "M2N6AXI ","M2N6AYI ","M2N6AZI ","M2N6DYNP ","M2N6FAFXI","M2N6FAFYI","M2N6FAFZI","M2N6FAGXI","M2N6FAGYI","M2N6FAGZI", & + "M2N6FAMXI","M2N6FAMYI","M2N6FAMZI","M2N6FAXI ","M2N6FAYI ","M2N6FAZI ","M2N6FBFXI","M2N6FBFYI","M2N6FBFZI","M2N6FBXI ", & + "M2N6FBYI ","M2N6FBZI ","M2N6FDXI ","M2N6FDYI ","M2N6FDZI ","M2N6FIXI ","M2N6FIYI ","M2N6FIZI ","M2N6FMGXI","M2N6FMGYI", & + "M2N6FMGZI","M2N6MBFXI","M2N6MBFYI","M2N6MBFZI","M2N6MBXI ","M2N6MBYI ","M2N6MBZI ","M2N6STAXI","M2N6STAYI","M2N6STAZI", & + "M2N6STVXI","M2N6STVYI","M2N6STVZI","M2N6VXI ","M2N6VYI ","M2N6VZI ","M2N7AXI ","M2N7AYI ","M2N7AZI ","M2N7DYNP ", & + "M2N7FAFXI","M2N7FAFYI","M2N7FAFZI","M2N7FAGXI","M2N7FAGYI","M2N7FAGZI","M2N7FAMXI","M2N7FAMYI","M2N7FAMZI","M2N7FAXI ", & + "M2N7FAYI ","M2N7FAZI ","M2N7FBFXI","M2N7FBFYI","M2N7FBFZI","M2N7FBXI ","M2N7FBYI ","M2N7FBZI ","M2N7FDXI ","M2N7FDYI ", & + "M2N7FDZI ","M2N7FIXI ","M2N7FIYI ","M2N7FIZI ","M2N7FMGXI","M2N7FMGYI","M2N7FMGZI","M2N7MBFXI","M2N7MBFYI","M2N7MBFZI", & + "M2N7MBXI ","M2N7MBYI ","M2N7MBZI ","M2N7STAXI","M2N7STAYI","M2N7STAZI","M2N7STVXI","M2N7STVYI","M2N7STVZI","M2N7VXI ", & + "M2N7VYI ","M2N7VZI ","M2N8AXI ","M2N8AYI ","M2N8AZI ","M2N8DYNP ","M2N8FAFXI","M2N8FAFYI","M2N8FAFZI","M2N8FAGXI", & + "M2N8FAGYI","M2N8FAGZI","M2N8FAMXI","M2N8FAMYI","M2N8FAMZI","M2N8FAXI ","M2N8FAYI ","M2N8FAZI ","M2N8FBFXI","M2N8FBFYI", & + "M2N8FBFZI","M2N8FBXI ","M2N8FBYI ","M2N8FBZI ","M2N8FDXI ","M2N8FDYI ","M2N8FDZI ","M2N8FIXI ","M2N8FIYI ","M2N8FIZI ", & + "M2N8FMGXI","M2N8FMGYI","M2N8FMGZI","M2N8MBFXI","M2N8MBFYI","M2N8MBFZI","M2N8MBXI ","M2N8MBYI ","M2N8MBZI ","M2N8STAXI", & + "M2N8STAYI","M2N8STAZI","M2N8STVXI","M2N8STVYI","M2N8STVZI","M2N8VXI ","M2N8VYI ","M2N8VZI ","M2N9AXI ","M2N9AYI ", & + "M2N9AZI ","M2N9DYNP ","M2N9FAFXI","M2N9FAFYI","M2N9FAFZI","M2N9FAGXI","M2N9FAGYI","M2N9FAGZI","M2N9FAMXI","M2N9FAMYI", & + "M2N9FAMZI","M2N9FAXI ","M2N9FAYI ","M2N9FAZI ","M2N9FBFXI","M2N9FBFYI","M2N9FBFZI","M2N9FBXI ","M2N9FBYI ","M2N9FBZI ", & + "M2N9FDXI ","M2N9FDYI ","M2N9FDZI ","M2N9FIXI ","M2N9FIYI ","M2N9FIZI ","M2N9FMGXI","M2N9FMGYI","M2N9FMGZI","M2N9MBFXI", & + "M2N9MBFYI","M2N9MBFZI","M2N9MBXI ","M2N9MBYI ","M2N9MBZI ","M2N9STAXI","M2N9STAYI","M2N9STAZI","M2N9STVXI","M2N9STVYI", & + "M2N9STVZI","M2N9VXI ","M2N9VYI ","M2N9VZI ","M3N1AXI ","M3N1AYI ","M3N1AZI ","M3N1DYNP ","M3N1FAFXI","M3N1FAFYI", & + "M3N1FAFZI","M3N1FAGXI","M3N1FAGYI","M3N1FAGZI","M3N1FAMXI","M3N1FAMYI","M3N1FAMZI","M3N1FAXI ","M3N1FAYI ","M3N1FAZI ", & + "M3N1FBFXI","M3N1FBFYI","M3N1FBFZI","M3N1FBXI ","M3N1FBYI ","M3N1FBZI ","M3N1FDXI ","M3N1FDYI ","M3N1FDZI ","M3N1FIXI ", & + "M3N1FIYI ","M3N1FIZI ","M3N1FMGXI","M3N1FMGYI","M3N1FMGZI","M3N1MBFXI","M3N1MBFYI","M3N1MBFZI","M3N1MBXI ","M3N1MBYI ", & + "M3N1MBZI ","M3N1STAXI","M3N1STAYI","M3N1STAZI","M3N1STVXI","M3N1STVYI","M3N1STVZI","M3N1VXI ","M3N1VYI ","M3N1VZI ", & + "M3N2AXI ","M3N2AYI ","M3N2AZI ","M3N2DYNP ","M3N2FAFXI","M3N2FAFYI","M3N2FAFZI","M3N2FAGXI","M3N2FAGYI","M3N2FAGZI", & + "M3N2FAMXI","M3N2FAMYI","M3N2FAMZI","M3N2FAXI ","M3N2FAYI ","M3N2FAZI ","M3N2FBFXI","M3N2FBFYI","M3N2FBFZI","M3N2FBXI ", & + "M3N2FBYI ","M3N2FBZI ","M3N2FDXI ","M3N2FDYI ","M3N2FDZI ","M3N2FIXI ","M3N2FIYI ","M3N2FIZI ","M3N2FMGXI","M3N2FMGYI", & + "M3N2FMGZI","M3N2MBFXI","M3N2MBFYI","M3N2MBFZI","M3N2MBXI ","M3N2MBYI ","M3N2MBZI ","M3N2STAXI","M3N2STAYI","M3N2STAZI", & + "M3N2STVXI","M3N2STVYI","M3N2STVZI","M3N2VXI ","M3N2VYI ","M3N2VZI ","M3N3AXI ","M3N3AYI ","M3N3AZI ","M3N3DYNP ", & + "M3N3FAFXI","M3N3FAFYI","M3N3FAFZI","M3N3FAGXI","M3N3FAGYI","M3N3FAGZI","M3N3FAMXI","M3N3FAMYI","M3N3FAMZI","M3N3FAXI ", & + "M3N3FAYI ","M3N3FAZI ","M3N3FBFXI","M3N3FBFYI","M3N3FBFZI","M3N3FBXI ","M3N3FBYI ","M3N3FBZI ","M3N3FDXI ","M3N3FDYI ", & + "M3N3FDZI ","M3N3FIXI ","M3N3FIYI ","M3N3FIZI ","M3N3FMGXI","M3N3FMGYI","M3N3FMGZI","M3N3MBFXI","M3N3MBFYI","M3N3MBFZI", & + "M3N3MBXI ","M3N3MBYI ","M3N3MBZI ","M3N3STAXI","M3N3STAYI","M3N3STAZI","M3N3STVXI","M3N3STVYI","M3N3STVZI","M3N3VXI ", & + "M3N3VYI ","M3N3VZI ","M3N4AXI ","M3N4AYI ","M3N4AZI ","M3N4DYNP ","M3N4FAFXI","M3N4FAFYI","M3N4FAFZI","M3N4FAGXI", & + "M3N4FAGYI","M3N4FAGZI","M3N4FAMXI","M3N4FAMYI","M3N4FAMZI","M3N4FAXI ","M3N4FAYI ","M3N4FAZI ","M3N4FBFXI","M3N4FBFYI", & + "M3N4FBFZI","M3N4FBXI ","M3N4FBYI ","M3N4FBZI ","M3N4FDXI ","M3N4FDYI ","M3N4FDZI ","M3N4FIXI ","M3N4FIYI ","M3N4FIZI ", & + "M3N4FMGXI","M3N4FMGYI","M3N4FMGZI","M3N4MBFXI","M3N4MBFYI","M3N4MBFZI","M3N4MBXI ","M3N4MBYI ","M3N4MBZI ","M3N4STAXI", & + "M3N4STAYI","M3N4STAZI","M3N4STVXI","M3N4STVYI","M3N4STVZI","M3N4VXI ","M3N4VYI ","M3N4VZI ","M3N5AXI ","M3N5AYI ", & + "M3N5AZI ","M3N5DYNP ","M3N5FAFXI","M3N5FAFYI","M3N5FAFZI","M3N5FAGXI","M3N5FAGYI","M3N5FAGZI","M3N5FAMXI","M3N5FAMYI", & + "M3N5FAMZI","M3N5FAXI ","M3N5FAYI ","M3N5FAZI ","M3N5FBFXI","M3N5FBFYI","M3N5FBFZI","M3N5FBXI ","M3N5FBYI ","M3N5FBZI ", & + "M3N5FDXI ","M3N5FDYI ","M3N5FDZI ","M3N5FIXI ","M3N5FIYI ","M3N5FIZI ","M3N5FMGXI","M3N5FMGYI","M3N5FMGZI","M3N5MBFXI", & + "M3N5MBFYI","M3N5MBFZI","M3N5MBXI ","M3N5MBYI ","M3N5MBZI ","M3N5STAXI","M3N5STAYI","M3N5STAZI","M3N5STVXI","M3N5STVYI", & + "M3N5STVZI","M3N5VXI ","M3N5VYI ","M3N5VZI ","M3N6AXI ","M3N6AYI ","M3N6AZI ","M3N6DYNP ","M3N6FAFXI","M3N6FAFYI", & + "M3N6FAFZI","M3N6FAGXI","M3N6FAGYI","M3N6FAGZI","M3N6FAMXI","M3N6FAMYI","M3N6FAMZI","M3N6FAXI ","M3N6FAYI ","M3N6FAZI ", & + "M3N6FBFXI","M3N6FBFYI","M3N6FBFZI","M3N6FBXI ","M3N6FBYI ","M3N6FBZI ","M3N6FDXI ","M3N6FDYI ","M3N6FDZI ","M3N6FIXI ", & + "M3N6FIYI ","M3N6FIZI ","M3N6FMGXI","M3N6FMGYI","M3N6FMGZI","M3N6MBFXI","M3N6MBFYI","M3N6MBFZI","M3N6MBXI ","M3N6MBYI ", & + "M3N6MBZI ","M3N6STAXI","M3N6STAYI","M3N6STAZI","M3N6STVXI","M3N6STVYI","M3N6STVZI","M3N6VXI ","M3N6VYI ","M3N6VZI ", & + "M3N7AXI ","M3N7AYI ","M3N7AZI ","M3N7DYNP ","M3N7FAFXI","M3N7FAFYI","M3N7FAFZI","M3N7FAGXI","M3N7FAGYI","M3N7FAGZI", & + "M3N7FAMXI","M3N7FAMYI","M3N7FAMZI","M3N7FAXI ","M3N7FAYI ","M3N7FAZI ","M3N7FBFXI","M3N7FBFYI","M3N7FBFZI","M3N7FBXI ", & + "M3N7FBYI ","M3N7FBZI ","M3N7FDXI ","M3N7FDYI ","M3N7FDZI ","M3N7FIXI ","M3N7FIYI ","M3N7FIZI ","M3N7FMGXI","M3N7FMGYI", & + "M3N7FMGZI","M3N7MBFXI","M3N7MBFYI","M3N7MBFZI","M3N7MBXI ","M3N7MBYI ","M3N7MBZI ","M3N7STAXI","M3N7STAYI","M3N7STAZI", & + "M3N7STVXI","M3N7STVYI","M3N7STVZI","M3N7VXI ","M3N7VYI ","M3N7VZI ","M3N8AXI ","M3N8AYI ","M3N8AZI ","M3N8DYNP ", & + "M3N8FAFXI","M3N8FAFYI","M3N8FAFZI","M3N8FAGXI","M3N8FAGYI","M3N8FAGZI","M3N8FAMXI","M3N8FAMYI","M3N8FAMZI","M3N8FAXI ", & + "M3N8FAYI ","M3N8FAZI ","M3N8FBFXI","M3N8FBFYI","M3N8FBFZI","M3N8FBXI ","M3N8FBYI ","M3N8FBZI ","M3N8FDXI ","M3N8FDYI ", & + "M3N8FDZI ","M3N8FIXI ","M3N8FIYI ","M3N8FIZI ","M3N8FMGXI","M3N8FMGYI","M3N8FMGZI","M3N8MBFXI","M3N8MBFYI","M3N8MBFZI", & + "M3N8MBXI ","M3N8MBYI ","M3N8MBZI ","M3N8STAXI","M3N8STAYI","M3N8STAZI","M3N8STVXI","M3N8STVYI","M3N8STVZI","M3N8VXI ", & + "M3N8VYI ","M3N8VZI ","M3N9AXI ","M3N9AYI ","M3N9AZI ","M3N9DYNP ","M3N9FAFXI","M3N9FAFYI","M3N9FAFZI","M3N9FAGXI", & + "M3N9FAGYI","M3N9FAGZI","M3N9FAMXI","M3N9FAMYI","M3N9FAMZI","M3N9FAXI ","M3N9FAYI ","M3N9FAZI ","M3N9FBFXI","M3N9FBFYI", & + "M3N9FBFZI","M3N9FBXI ","M3N9FBYI ","M3N9FBZI ","M3N9FDXI ","M3N9FDYI ","M3N9FDZI ","M3N9FIXI ","M3N9FIYI ","M3N9FIZI ", & + "M3N9FMGXI","M3N9FMGYI","M3N9FMGZI","M3N9MBFXI","M3N9MBFYI","M3N9MBFZI","M3N9MBXI ","M3N9MBYI ","M3N9MBZI ","M3N9STAXI", & + "M3N9STAYI","M3N9STAZI","M3N9STVXI","M3N9STVYI","M3N9STVZI","M3N9VXI ","M3N9VYI ","M3N9VZI ","M4N1AXI ","M4N1AYI ", & + "M4N1AZI ","M4N1DYNP ","M4N1FAFXI","M4N1FAFYI","M4N1FAFZI","M4N1FAGXI","M4N1FAGYI","M4N1FAGZI","M4N1FAMXI","M4N1FAMYI", & + "M4N1FAMZI","M4N1FAXI ","M4N1FAYI ","M4N1FAZI ","M4N1FBFXI","M4N1FBFYI","M4N1FBFZI","M4N1FBXI ","M4N1FBYI ","M4N1FBZI ", & + "M4N1FDXI ","M4N1FDYI ","M4N1FDZI ","M4N1FIXI ","M4N1FIYI ","M4N1FIZI ","M4N1FMGXI","M4N1FMGYI","M4N1FMGZI","M4N1MBFXI", & + "M4N1MBFYI","M4N1MBFZI","M4N1MBXI ","M4N1MBYI ","M4N1MBZI ","M4N1STAXI","M4N1STAYI","M4N1STAZI","M4N1STVXI","M4N1STVYI", & + "M4N1STVZI","M4N1VXI ","M4N1VYI ","M4N1VZI ","M4N2AXI ","M4N2AYI ","M4N2AZI ","M4N2DYNP ","M4N2FAFXI","M4N2FAFYI", & + "M4N2FAFZI","M4N2FAGXI","M4N2FAGYI","M4N2FAGZI","M4N2FAMXI","M4N2FAMYI","M4N2FAMZI","M4N2FAXI ","M4N2FAYI ","M4N2FAZI ", & + "M4N2FBFXI","M4N2FBFYI","M4N2FBFZI","M4N2FBXI ","M4N2FBYI ","M4N2FBZI ","M4N2FDXI ","M4N2FDYI ","M4N2FDZI ","M4N2FIXI ", & + "M4N2FIYI ","M4N2FIZI ","M4N2FMGXI","M4N2FMGYI","M4N2FMGZI","M4N2MBFXI","M4N2MBFYI","M4N2MBFZI","M4N2MBXI ","M4N2MBYI ", & + "M4N2MBZI ","M4N2STAXI","M4N2STAYI","M4N2STAZI","M4N2STVXI","M4N2STVYI","M4N2STVZI","M4N2VXI ","M4N2VYI ","M4N2VZI ", & + "M4N3AXI ","M4N3AYI ","M4N3AZI ","M4N3DYNP ","M4N3FAFXI","M4N3FAFYI","M4N3FAFZI","M4N3FAGXI","M4N3FAGYI","M4N3FAGZI", & + "M4N3FAMXI","M4N3FAMYI","M4N3FAMZI","M4N3FAXI ","M4N3FAYI ","M4N3FAZI ","M4N3FBFXI","M4N3FBFYI","M4N3FBFZI","M4N3FBXI ", & + "M4N3FBYI ","M4N3FBZI ","M4N3FDXI ","M4N3FDYI ","M4N3FDZI ","M4N3FIXI ","M4N3FIYI ","M4N3FIZI ","M4N3FMGXI","M4N3FMGYI", & + "M4N3FMGZI","M4N3MBFXI","M4N3MBFYI","M4N3MBFZI","M4N3MBXI ","M4N3MBYI ","M4N3MBZI ","M4N3STAXI","M4N3STAYI","M4N3STAZI", & + "M4N3STVXI","M4N3STVYI","M4N3STVZI","M4N3VXI ","M4N3VYI ","M4N3VZI ","M4N4AXI ","M4N4AYI ","M4N4AZI ","M4N4DYNP ", & + "M4N4FAFXI","M4N4FAFYI","M4N4FAFZI","M4N4FAGXI","M4N4FAGYI","M4N4FAGZI","M4N4FAMXI","M4N4FAMYI","M4N4FAMZI","M4N4FAXI ", & + "M4N4FAYI ","M4N4FAZI ","M4N4FBFXI","M4N4FBFYI","M4N4FBFZI","M4N4FBXI ","M4N4FBYI ","M4N4FBZI ","M4N4FDXI ","M4N4FDYI ", & + "M4N4FDZI ","M4N4FIXI ","M4N4FIYI ","M4N4FIZI ","M4N4FMGXI","M4N4FMGYI","M4N4FMGZI","M4N4MBFXI","M4N4MBFYI","M4N4MBFZI", & + "M4N4MBXI ","M4N4MBYI ","M4N4MBZI ","M4N4STAXI","M4N4STAYI","M4N4STAZI","M4N4STVXI","M4N4STVYI","M4N4STVZI","M4N4VXI ", & + "M4N4VYI ","M4N4VZI ","M4N5AXI ","M4N5AYI ","M4N5AZI ","M4N5DYNP ","M4N5FAFXI","M4N5FAFYI","M4N5FAFZI","M4N5FAGXI", & + "M4N5FAGYI","M4N5FAGZI","M4N5FAMXI","M4N5FAMYI","M4N5FAMZI","M4N5FAXI ","M4N5FAYI ","M4N5FAZI ","M4N5FBFXI","M4N5FBFYI", & + "M4N5FBFZI","M4N5FBXI ","M4N5FBYI ","M4N5FBZI ","M4N5FDXI ","M4N5FDYI ","M4N5FDZI ","M4N5FIXI ","M4N5FIYI ","M4N5FIZI ", & + "M4N5FMGXI","M4N5FMGYI","M4N5FMGZI","M4N5MBFXI","M4N5MBFYI","M4N5MBFZI","M4N5MBXI ","M4N5MBYI ","M4N5MBZI ","M4N5STAXI", & + "M4N5STAYI","M4N5STAZI","M4N5STVXI","M4N5STVYI","M4N5STVZI","M4N5VXI ","M4N5VYI ","M4N5VZI ","M4N6AXI ","M4N6AYI ", & + "M4N6AZI ","M4N6DYNP ","M4N6FAFXI","M4N6FAFYI","M4N6FAFZI","M4N6FAGXI","M4N6FAGYI","M4N6FAGZI","M4N6FAMXI","M4N6FAMYI", & + "M4N6FAMZI","M4N6FAXI ","M4N6FAYI ","M4N6FAZI ","M4N6FBFXI","M4N6FBFYI","M4N6FBFZI","M4N6FBXI ","M4N6FBYI ","M4N6FBZI ", & + "M4N6FDXI ","M4N6FDYI ","M4N6FDZI ","M4N6FIXI ","M4N6FIYI ","M4N6FIZI ","M4N6FMGXI","M4N6FMGYI","M4N6FMGZI","M4N6MBFXI", & + "M4N6MBFYI","M4N6MBFZI","M4N6MBXI ","M4N6MBYI ","M4N6MBZI ","M4N6STAXI","M4N6STAYI","M4N6STAZI","M4N6STVXI","M4N6STVYI", & + "M4N6STVZI","M4N6VXI ","M4N6VYI ","M4N6VZI ","M4N7AXI ","M4N7AYI ","M4N7AZI ","M4N7DYNP ","M4N7FAFXI","M4N7FAFYI", & + "M4N7FAFZI","M4N7FAGXI","M4N7FAGYI","M4N7FAGZI","M4N7FAMXI","M4N7FAMYI","M4N7FAMZI","M4N7FAXI ","M4N7FAYI ","M4N7FAZI ", & + "M4N7FBFXI","M4N7FBFYI","M4N7FBFZI","M4N7FBXI ","M4N7FBYI ","M4N7FBZI ","M4N7FDXI ","M4N7FDYI ","M4N7FDZI ","M4N7FIXI ", & + "M4N7FIYI ","M4N7FIZI ","M4N7FMGXI","M4N7FMGYI","M4N7FMGZI","M4N7MBFXI","M4N7MBFYI","M4N7MBFZI","M4N7MBXI ","M4N7MBYI ", & + "M4N7MBZI ","M4N7STAXI","M4N7STAYI","M4N7STAZI","M4N7STVXI","M4N7STVYI","M4N7STVZI","M4N7VXI ","M4N7VYI ","M4N7VZI ", & + "M4N8AXI ","M4N8AYI ","M4N8AZI ","M4N8DYNP ","M4N8FAFXI","M4N8FAFYI","M4N8FAFZI","M4N8FAGXI","M4N8FAGYI","M4N8FAGZI", & + "M4N8FAMXI","M4N8FAMYI","M4N8FAMZI","M4N8FAXI ","M4N8FAYI ","M4N8FAZI ","M4N8FBFXI","M4N8FBFYI","M4N8FBFZI","M4N8FBXI ", & + "M4N8FBYI ","M4N8FBZI ","M4N8FDXI ","M4N8FDYI ","M4N8FDZI ","M4N8FIXI ","M4N8FIYI ","M4N8FIZI ","M4N8FMGXI","M4N8FMGYI", & + "M4N8FMGZI","M4N8MBFXI","M4N8MBFYI","M4N8MBFZI","M4N8MBXI ","M4N8MBYI ","M4N8MBZI ","M4N8STAXI","M4N8STAYI","M4N8STAZI", & + "M4N8STVXI","M4N8STVYI","M4N8STVZI","M4N8VXI ","M4N8VYI ","M4N8VZI ","M4N9AXI ","M4N9AYI ","M4N9AZI ","M4N9DYNP ", & + "M4N9FAFXI","M4N9FAFYI","M4N9FAFZI","M4N9FAGXI","M4N9FAGYI","M4N9FAGZI","M4N9FAMXI","M4N9FAMYI","M4N9FAMZI","M4N9FAXI ", & + "M4N9FAYI ","M4N9FAZI ","M4N9FBFXI","M4N9FBFYI","M4N9FBFZI","M4N9FBXI ","M4N9FBYI ","M4N9FBZI ","M4N9FDXI ","M4N9FDYI ", & + "M4N9FDZI ","M4N9FIXI ","M4N9FIYI ","M4N9FIZI ","M4N9FMGXI","M4N9FMGYI","M4N9FMGZI","M4N9MBFXI","M4N9MBFYI","M4N9MBFZI", & + "M4N9MBXI ","M4N9MBYI ","M4N9MBZI ","M4N9STAXI","M4N9STAYI","M4N9STAZI","M4N9STVXI","M4N9STVYI","M4N9STVZI","M4N9VXI ", & + "M4N9VYI ","M4N9VZI ","M5N1AXI ","M5N1AYI ","M5N1AZI ","M5N1DYNP ","M5N1FAFXI","M5N1FAFYI","M5N1FAFZI","M5N1FAGXI", & + "M5N1FAGYI","M5N1FAGZI","M5N1FAMXI","M5N1FAMYI","M5N1FAMZI","M5N1FAXI ","M5N1FAYI ","M5N1FAZI ","M5N1FBFXI","M5N1FBFYI", & + "M5N1FBFZI","M5N1FBXI ","M5N1FBYI ","M5N1FBZI ","M5N1FDXI ","M5N1FDYI ","M5N1FDZI ","M5N1FIXI ","M5N1FIYI ","M5N1FIZI ", & + "M5N1FMGXI","M5N1FMGYI","M5N1FMGZI","M5N1MBFXI","M5N1MBFYI","M5N1MBFZI","M5N1MBXI ","M5N1MBYI ","M5N1MBZI ","M5N1STAXI", & + "M5N1STAYI","M5N1STAZI","M5N1STVXI","M5N1STVYI","M5N1STVZI","M5N1VXI ","M5N1VYI ","M5N1VZI ","M5N2AXI ","M5N2AYI ", & + "M5N2AZI ","M5N2DYNP ","M5N2FAFXI","M5N2FAFYI","M5N2FAFZI","M5N2FAGXI","M5N2FAGYI","M5N2FAGZI","M5N2FAMXI","M5N2FAMYI", & + "M5N2FAMZI","M5N2FAXI ","M5N2FAYI ","M5N2FAZI ","M5N2FBFXI","M5N2FBFYI","M5N2FBFZI","M5N2FBXI ","M5N2FBYI ","M5N2FBZI ", & + "M5N2FDXI ","M5N2FDYI ","M5N2FDZI ","M5N2FIXI ","M5N2FIYI ","M5N2FIZI ","M5N2FMGXI","M5N2FMGYI","M5N2FMGZI","M5N2MBFXI", & + "M5N2MBFYI","M5N2MBFZI","M5N2MBXI ","M5N2MBYI ","M5N2MBZI ","M5N2STAXI","M5N2STAYI","M5N2STAZI","M5N2STVXI","M5N2STVYI", & + "M5N2STVZI","M5N2VXI ","M5N2VYI ","M5N2VZI ","M5N3AXI ","M5N3AYI ","M5N3AZI ","M5N3DYNP ","M5N3FAFXI","M5N3FAFYI", & + "M5N3FAFZI","M5N3FAGXI","M5N3FAGYI","M5N3FAGZI","M5N3FAMXI","M5N3FAMYI","M5N3FAMZI","M5N3FAXI ","M5N3FAYI ","M5N3FAZI ", & + "M5N3FBFXI","M5N3FBFYI","M5N3FBFZI","M5N3FBXI ","M5N3FBYI ","M5N3FBZI ","M5N3FDXI ","M5N3FDYI ","M5N3FDZI ","M5N3FIXI ", & + "M5N3FIYI ","M5N3FIZI ","M5N3FMGXI","M5N3FMGYI","M5N3FMGZI","M5N3MBFXI","M5N3MBFYI","M5N3MBFZI","M5N3MBXI ","M5N3MBYI ", & + "M5N3MBZI ","M5N3STAXI","M5N3STAYI","M5N3STAZI","M5N3STVXI","M5N3STVYI","M5N3STVZI","M5N3VXI ","M5N3VYI ","M5N3VZI ", & + "M5N4AXI ","M5N4AYI ","M5N4AZI ","M5N4DYNP ","M5N4FAFXI","M5N4FAFYI","M5N4FAFZI","M5N4FAGXI","M5N4FAGYI","M5N4FAGZI", & + "M5N4FAMXI","M5N4FAMYI","M5N4FAMZI","M5N4FAXI ","M5N4FAYI ","M5N4FAZI ","M5N4FBFXI","M5N4FBFYI","M5N4FBFZI","M5N4FBXI ", & + "M5N4FBYI ","M5N4FBZI ","M5N4FDXI ","M5N4FDYI ","M5N4FDZI ","M5N4FIXI ","M5N4FIYI ","M5N4FIZI ","M5N4FMGXI","M5N4FMGYI", & + "M5N4FMGZI","M5N4MBFXI","M5N4MBFYI","M5N4MBFZI","M5N4MBXI ","M5N4MBYI ","M5N4MBZI ","M5N4STAXI","M5N4STAYI","M5N4STAZI", & + "M5N4STVXI","M5N4STVYI","M5N4STVZI","M5N4VXI ","M5N4VYI ","M5N4VZI ","M5N5AXI ","M5N5AYI ","M5N5AZI ","M5N5DYNP ", & + "M5N5FAFXI","M5N5FAFYI","M5N5FAFZI","M5N5FAGXI","M5N5FAGYI","M5N5FAGZI","M5N5FAMXI","M5N5FAMYI","M5N5FAMZI","M5N5FAXI ", & + "M5N5FAYI ","M5N5FAZI ","M5N5FBFXI","M5N5FBFYI","M5N5FBFZI","M5N5FBXI ","M5N5FBYI ","M5N5FBZI ","M5N5FDXI ","M5N5FDYI ", & + "M5N5FDZI ","M5N5FIXI ","M5N5FIYI ","M5N5FIZI ","M5N5FMGXI","M5N5FMGYI","M5N5FMGZI","M5N5MBFXI","M5N5MBFYI","M5N5MBFZI", & + "M5N5MBXI ","M5N5MBYI ","M5N5MBZI ","M5N5STAXI","M5N5STAYI","M5N5STAZI","M5N5STVXI","M5N5STVYI","M5N5STVZI","M5N5VXI ", & + "M5N5VYI ","M5N5VZI ","M5N6AXI ","M5N6AYI ","M5N6AZI ","M5N6DYNP ","M5N6FAFXI","M5N6FAFYI","M5N6FAFZI","M5N6FAGXI", & + "M5N6FAGYI","M5N6FAGZI","M5N6FAMXI","M5N6FAMYI","M5N6FAMZI","M5N6FAXI ","M5N6FAYI ","M5N6FAZI ","M5N6FBFXI","M5N6FBFYI", & + "M5N6FBFZI","M5N6FBXI ","M5N6FBYI ","M5N6FBZI ","M5N6FDXI ","M5N6FDYI ","M5N6FDZI ","M5N6FIXI ","M5N6FIYI ","M5N6FIZI ", & + "M5N6FMGXI","M5N6FMGYI","M5N6FMGZI","M5N6MBFXI","M5N6MBFYI","M5N6MBFZI","M5N6MBXI ","M5N6MBYI ","M5N6MBZI ","M5N6STAXI", & + "M5N6STAYI","M5N6STAZI","M5N6STVXI","M5N6STVYI","M5N6STVZI","M5N6VXI ","M5N6VYI ","M5N6VZI ","M5N7AXI ","M5N7AYI ", & + "M5N7AZI ","M5N7DYNP ","M5N7FAFXI","M5N7FAFYI","M5N7FAFZI","M5N7FAGXI","M5N7FAGYI","M5N7FAGZI","M5N7FAMXI","M5N7FAMYI", & + "M5N7FAMZI","M5N7FAXI ","M5N7FAYI ","M5N7FAZI ","M5N7FBFXI","M5N7FBFYI","M5N7FBFZI","M5N7FBXI ","M5N7FBYI ","M5N7FBZI ", & + "M5N7FDXI ","M5N7FDYI ","M5N7FDZI ","M5N7FIXI ","M5N7FIYI ","M5N7FIZI ","M5N7FMGXI","M5N7FMGYI","M5N7FMGZI","M5N7MBFXI", & + "M5N7MBFYI","M5N7MBFZI","M5N7MBXI ","M5N7MBYI ","M5N7MBZI ","M5N7STAXI","M5N7STAYI","M5N7STAZI","M5N7STVXI","M5N7STVYI", & + "M5N7STVZI","M5N7VXI ","M5N7VYI ","M5N7VZI ","M5N8AXI ","M5N8AYI ","M5N8AZI ","M5N8DYNP ","M5N8FAFXI","M5N8FAFYI", & + "M5N8FAFZI","M5N8FAGXI","M5N8FAGYI","M5N8FAGZI","M5N8FAMXI","M5N8FAMYI","M5N8FAMZI","M5N8FAXI ","M5N8FAYI ","M5N8FAZI ", & + "M5N8FBFXI","M5N8FBFYI","M5N8FBFZI","M5N8FBXI ","M5N8FBYI ","M5N8FBZI ","M5N8FDXI ","M5N8FDYI ","M5N8FDZI ","M5N8FIXI ", & + "M5N8FIYI ","M5N8FIZI ","M5N8FMGXI","M5N8FMGYI","M5N8FMGZI","M5N8MBFXI","M5N8MBFYI","M5N8MBFZI","M5N8MBXI ","M5N8MBYI ", & + "M5N8MBZI ","M5N8STAXI","M5N8STAYI","M5N8STAZI","M5N8STVXI","M5N8STVYI","M5N8STVZI","M5N8VXI ","M5N8VYI ","M5N8VZI ", & + "M5N9AXI ","M5N9AYI ","M5N9AZI ","M5N9DYNP ","M5N9FAFXI","M5N9FAFYI","M5N9FAFZI","M5N9FAGXI","M5N9FAGYI","M5N9FAGZI", & + "M5N9FAMXI","M5N9FAMYI","M5N9FAMZI","M5N9FAXI ","M5N9FAYI ","M5N9FAZI ","M5N9FBFXI","M5N9FBFYI","M5N9FBFZI","M5N9FBXI ", & + "M5N9FBYI ","M5N9FBZI ","M5N9FDXI ","M5N9FDYI ","M5N9FDZI ","M5N9FIXI ","M5N9FIYI ","M5N9FIZI ","M5N9FMGXI","M5N9FMGYI", & + "M5N9FMGZI","M5N9MBFXI","M5N9MBFYI","M5N9MBFZI","M5N9MBXI ","M5N9MBYI ","M5N9MBZI ","M5N9STAXI","M5N9STAYI","M5N9STAZI", & + "M5N9STVXI","M5N9STVYI","M5N9STVZI","M5N9VXI ","M5N9VYI ","M5N9VZI ","M6N1AXI ","M6N1AYI ","M6N1AZI ","M6N1DYNP ", & + "M6N1FAFXI","M6N1FAFYI","M6N1FAFZI","M6N1FAGXI","M6N1FAGYI","M6N1FAGZI","M6N1FAMXI","M6N1FAMYI","M6N1FAMZI","M6N1FAXI ", & + "M6N1FAYI ","M6N1FAZI ","M6N1FBFXI","M6N1FBFYI","M6N1FBFZI","M6N1FBXI ","M6N1FBYI ","M6N1FBZI ","M6N1FDXI ","M6N1FDYI ", & + "M6N1FDZI ","M6N1FIXI ","M6N1FIYI ","M6N1FIZI ","M6N1FMGXI","M6N1FMGYI","M6N1FMGZI","M6N1MBFXI","M6N1MBFYI","M6N1MBFZI", & + "M6N1MBXI ","M6N1MBYI ","M6N1MBZI ","M6N1STAXI","M6N1STAYI","M6N1STAZI","M6N1STVXI","M6N1STVYI","M6N1STVZI","M6N1VXI ", & + "M6N1VYI ","M6N1VZI ","M6N2AXI ","M6N2AYI ","M6N2AZI ","M6N2DYNP ","M6N2FAFXI","M6N2FAFYI","M6N2FAFZI","M6N2FAGXI", & + "M6N2FAGYI","M6N2FAGZI","M6N2FAMXI","M6N2FAMYI","M6N2FAMZI","M6N2FAXI ","M6N2FAYI ","M6N2FAZI ","M6N2FBFXI","M6N2FBFYI", & + "M6N2FBFZI","M6N2FBXI ","M6N2FBYI ","M6N2FBZI ","M6N2FDXI ","M6N2FDYI ","M6N2FDZI ","M6N2FIXI ","M6N2FIYI ","M6N2FIZI ", & + "M6N2FMGXI","M6N2FMGYI","M6N2FMGZI","M6N2MBFXI","M6N2MBFYI","M6N2MBFZI","M6N2MBXI ","M6N2MBYI ","M6N2MBZI ","M6N2STAXI", & + "M6N2STAYI","M6N2STAZI","M6N2STVXI","M6N2STVYI","M6N2STVZI","M6N2VXI ","M6N2VYI ","M6N2VZI ","M6N3AXI ","M6N3AYI ", & + "M6N3AZI ","M6N3DYNP ","M6N3FAFXI","M6N3FAFYI","M6N3FAFZI","M6N3FAGXI","M6N3FAGYI","M6N3FAGZI","M6N3FAMXI","M6N3FAMYI", & + "M6N3FAMZI","M6N3FAXI ","M6N3FAYI ","M6N3FAZI ","M6N3FBFXI","M6N3FBFYI","M6N3FBFZI","M6N3FBXI ","M6N3FBYI ","M6N3FBZI ", & + "M6N3FDXI ","M6N3FDYI ","M6N3FDZI ","M6N3FIXI ","M6N3FIYI ","M6N3FIZI ","M6N3FMGXI","M6N3FMGYI","M6N3FMGZI","M6N3MBFXI", & + "M6N3MBFYI","M6N3MBFZI","M6N3MBXI ","M6N3MBYI ","M6N3MBZI ","M6N3STAXI","M6N3STAYI","M6N3STAZI","M6N3STVXI","M6N3STVYI", & + "M6N3STVZI","M6N3VXI ","M6N3VYI ","M6N3VZI ","M6N4AXI ","M6N4AYI ","M6N4AZI ","M6N4DYNP ","M6N4FAFXI","M6N4FAFYI", & + "M6N4FAFZI","M6N4FAGXI","M6N4FAGYI","M6N4FAGZI","M6N4FAMXI","M6N4FAMYI","M6N4FAMZI","M6N4FAXI ","M6N4FAYI ","M6N4FAZI ", & + "M6N4FBFXI","M6N4FBFYI","M6N4FBFZI","M6N4FBXI ","M6N4FBYI ","M6N4FBZI ","M6N4FDXI ","M6N4FDYI ","M6N4FDZI ","M6N4FIXI ", & + "M6N4FIYI ","M6N4FIZI ","M6N4FMGXI","M6N4FMGYI","M6N4FMGZI","M6N4MBFXI","M6N4MBFYI","M6N4MBFZI","M6N4MBXI ","M6N4MBYI ", & + "M6N4MBZI ","M6N4STAXI","M6N4STAYI","M6N4STAZI","M6N4STVXI","M6N4STVYI","M6N4STVZI","M6N4VXI ","M6N4VYI ","M6N4VZI ", & + "M6N5AXI ","M6N5AYI ","M6N5AZI ","M6N5DYNP ","M6N5FAFXI","M6N5FAFYI","M6N5FAFZI","M6N5FAGXI","M6N5FAGYI","M6N5FAGZI", & + "M6N5FAMXI","M6N5FAMYI","M6N5FAMZI","M6N5FAXI ","M6N5FAYI ","M6N5FAZI ","M6N5FBFXI","M6N5FBFYI","M6N5FBFZI","M6N5FBXI ", & + "M6N5FBYI ","M6N5FBZI ","M6N5FDXI ","M6N5FDYI ","M6N5FDZI ","M6N5FIXI ","M6N5FIYI ","M6N5FIZI ","M6N5FMGXI","M6N5FMGYI", & + "M6N5FMGZI","M6N5MBFXI","M6N5MBFYI","M6N5MBFZI","M6N5MBXI ","M6N5MBYI ","M6N5MBZI ","M6N5STAXI","M6N5STAYI","M6N5STAZI", & + "M6N5STVXI","M6N5STVYI","M6N5STVZI","M6N5VXI ","M6N5VYI ","M6N5VZI ","M6N6AXI ","M6N6AYI ","M6N6AZI ","M6N6DYNP ", & + "M6N6FAFXI","M6N6FAFYI","M6N6FAFZI","M6N6FAGXI","M6N6FAGYI","M6N6FAGZI","M6N6FAMXI","M6N6FAMYI","M6N6FAMZI","M6N6FAXI ", & + "M6N6FAYI ","M6N6FAZI ","M6N6FBFXI","M6N6FBFYI","M6N6FBFZI","M6N6FBXI ","M6N6FBYI ","M6N6FBZI ","M6N6FDXI ","M6N6FDYI ", & + "M6N6FDZI ","M6N6FIXI ","M6N6FIYI ","M6N6FIZI ","M6N6FMGXI","M6N6FMGYI","M6N6FMGZI","M6N6MBFXI","M6N6MBFYI","M6N6MBFZI", & + "M6N6MBXI ","M6N6MBYI ","M6N6MBZI ","M6N6STAXI","M6N6STAYI","M6N6STAZI","M6N6STVXI","M6N6STVYI","M6N6STVZI","M6N6VXI ", & + "M6N6VYI ","M6N6VZI ","M6N7AXI ","M6N7AYI ","M6N7AZI ","M6N7DYNP ","M6N7FAFXI","M6N7FAFYI","M6N7FAFZI","M6N7FAGXI", & + "M6N7FAGYI","M6N7FAGZI","M6N7FAMXI","M6N7FAMYI","M6N7FAMZI","M6N7FAXI ","M6N7FAYI ","M6N7FAZI ","M6N7FBFXI","M6N7FBFYI", & + "M6N7FBFZI","M6N7FBXI ","M6N7FBYI ","M6N7FBZI ","M6N7FDXI ","M6N7FDYI ","M6N7FDZI ","M6N7FIXI ","M6N7FIYI ","M6N7FIZI ", & + "M6N7FMGXI","M6N7FMGYI","M6N7FMGZI","M6N7MBFXI","M6N7MBFYI","M6N7MBFZI","M6N7MBXI ","M6N7MBYI ","M6N7MBZI ","M6N7STAXI", & + "M6N7STAYI","M6N7STAZI","M6N7STVXI","M6N7STVYI","M6N7STVZI","M6N7VXI ","M6N7VYI ","M6N7VZI ","M6N8AXI ","M6N8AYI ", & + "M6N8AZI ","M6N8DYNP ","M6N8FAFXI","M6N8FAFYI","M6N8FAFZI","M6N8FAGXI","M6N8FAGYI","M6N8FAGZI","M6N8FAMXI","M6N8FAMYI", & + "M6N8FAMZI","M6N8FAXI ","M6N8FAYI ","M6N8FAZI ","M6N8FBFXI","M6N8FBFYI","M6N8FBFZI","M6N8FBXI ","M6N8FBYI ","M6N8FBZI ", & + "M6N8FDXI ","M6N8FDYI ","M6N8FDZI ","M6N8FIXI ","M6N8FIYI ","M6N8FIZI ","M6N8FMGXI","M6N8FMGYI","M6N8FMGZI","M6N8MBFXI", & + "M6N8MBFYI","M6N8MBFZI","M6N8MBXI ","M6N8MBYI ","M6N8MBZI ","M6N8STAXI","M6N8STAYI","M6N8STAZI","M6N8STVXI","M6N8STVYI", & + "M6N8STVZI","M6N8VXI ","M6N8VYI ","M6N8VZI ","M6N9AXI ","M6N9AYI ","M6N9AZI ","M6N9DYNP ","M6N9FAFXI","M6N9FAFYI", & + "M6N9FAFZI","M6N9FAGXI","M6N9FAGYI","M6N9FAGZI","M6N9FAMXI","M6N9FAMYI","M6N9FAMZI","M6N9FAXI ","M6N9FAYI ","M6N9FAZI ", & + "M6N9FBFXI","M6N9FBFYI","M6N9FBFZI","M6N9FBXI ","M6N9FBYI ","M6N9FBZI ","M6N9FDXI ","M6N9FDYI ","M6N9FDZI ","M6N9FIXI ", & + "M6N9FIYI ","M6N9FIZI ","M6N9FMGXI","M6N9FMGYI","M6N9FMGZI","M6N9MBFXI","M6N9MBFYI","M6N9MBFZI","M6N9MBXI ","M6N9MBYI ", & + "M6N9MBZI ","M6N9STAXI","M6N9STAYI","M6N9STAZI","M6N9STVXI","M6N9STVYI","M6N9STVZI","M6N9VXI ","M6N9VYI ","M6N9VZI ", & + "M7N1AXI ","M7N1AYI ","M7N1AZI ","M7N1DYNP ","M7N1FAFXI","M7N1FAFYI","M7N1FAFZI","M7N1FAGXI","M7N1FAGYI","M7N1FAGZI", & + "M7N1FAMXI","M7N1FAMYI","M7N1FAMZI","M7N1FAXI ","M7N1FAYI ","M7N1FAZI ","M7N1FBFXI","M7N1FBFYI","M7N1FBFZI","M7N1FBXI ", & + "M7N1FBYI ","M7N1FBZI ","M7N1FDXI ","M7N1FDYI ","M7N1FDZI ","M7N1FIXI ","M7N1FIYI ","M7N1FIZI ","M7N1FMGXI","M7N1FMGYI", & + "M7N1FMGZI","M7N1MBFXI","M7N1MBFYI","M7N1MBFZI","M7N1MBXI ","M7N1MBYI ","M7N1MBZI ","M7N1STAXI","M7N1STAYI","M7N1STAZI", & + "M7N1STVXI","M7N1STVYI","M7N1STVZI","M7N1VXI ","M7N1VYI ","M7N1VZI ","M7N2AXI ","M7N2AYI ","M7N2AZI ","M7N2DYNP ", & + "M7N2FAFXI","M7N2FAFYI","M7N2FAFZI","M7N2FAGXI","M7N2FAGYI","M7N2FAGZI","M7N2FAMXI","M7N2FAMYI","M7N2FAMZI","M7N2FAXI ", & + "M7N2FAYI ","M7N2FAZI ","M7N2FBFXI","M7N2FBFYI","M7N2FBFZI","M7N2FBXI ","M7N2FBYI ","M7N2FBZI ","M7N2FDXI ","M7N2FDYI ", & + "M7N2FDZI ","M7N2FIXI ","M7N2FIYI ","M7N2FIZI ","M7N2FMGXI","M7N2FMGYI","M7N2FMGZI","M7N2MBFXI","M7N2MBFYI","M7N2MBFZI", & + "M7N2MBXI ","M7N2MBYI ","M7N2MBZI ","M7N2STAXI","M7N2STAYI","M7N2STAZI","M7N2STVXI","M7N2STVYI","M7N2STVZI","M7N2VXI ", & + "M7N2VYI ","M7N2VZI ","M7N3AXI ","M7N3AYI ","M7N3AZI ","M7N3DYNP ","M7N3FAFXI","M7N3FAFYI","M7N3FAFZI","M7N3FAGXI", & + "M7N3FAGYI","M7N3FAGZI","M7N3FAMXI","M7N3FAMYI","M7N3FAMZI","M7N3FAXI ","M7N3FAYI ","M7N3FAZI ","M7N3FBFXI","M7N3FBFYI", & + "M7N3FBFZI","M7N3FBXI ","M7N3FBYI ","M7N3FBZI ","M7N3FDXI ","M7N3FDYI ","M7N3FDZI ","M7N3FIXI ","M7N3FIYI ","M7N3FIZI ", & + "M7N3FMGXI","M7N3FMGYI","M7N3FMGZI","M7N3MBFXI","M7N3MBFYI","M7N3MBFZI","M7N3MBXI ","M7N3MBYI ","M7N3MBZI ","M7N3STAXI", & + "M7N3STAYI","M7N3STAZI","M7N3STVXI","M7N3STVYI","M7N3STVZI","M7N3VXI ","M7N3VYI ","M7N3VZI ","M7N4AXI ","M7N4AYI ", & + "M7N4AZI ","M7N4DYNP ","M7N4FAFXI","M7N4FAFYI","M7N4FAFZI","M7N4FAGXI","M7N4FAGYI","M7N4FAGZI","M7N4FAMXI","M7N4FAMYI", & + "M7N4FAMZI","M7N4FAXI ","M7N4FAYI ","M7N4FAZI ","M7N4FBFXI","M7N4FBFYI","M7N4FBFZI","M7N4FBXI ","M7N4FBYI ","M7N4FBZI ", & + "M7N4FDXI ","M7N4FDYI ","M7N4FDZI ","M7N4FIXI ","M7N4FIYI ","M7N4FIZI ","M7N4FMGXI","M7N4FMGYI","M7N4FMGZI","M7N4MBFXI", & + "M7N4MBFYI","M7N4MBFZI","M7N4MBXI ","M7N4MBYI ","M7N4MBZI ","M7N4STAXI","M7N4STAYI","M7N4STAZI","M7N4STVXI","M7N4STVYI", & + "M7N4STVZI","M7N4VXI ","M7N4VYI ","M7N4VZI ","M7N5AXI ","M7N5AYI ","M7N5AZI ","M7N5DYNP ","M7N5FAFXI","M7N5FAFYI", & + "M7N5FAFZI","M7N5FAGXI","M7N5FAGYI","M7N5FAGZI","M7N5FAMXI","M7N5FAMYI","M7N5FAMZI","M7N5FAXI ","M7N5FAYI ","M7N5FAZI ", & + "M7N5FBFXI","M7N5FBFYI","M7N5FBFZI","M7N5FBXI ","M7N5FBYI ","M7N5FBZI ","M7N5FDXI ","M7N5FDYI ","M7N5FDZI ","M7N5FIXI ", & + "M7N5FIYI ","M7N5FIZI ","M7N5FMGXI","M7N5FMGYI","M7N5FMGZI","M7N5MBFXI","M7N5MBFYI","M7N5MBFZI","M7N5MBXI ","M7N5MBYI ", & + "M7N5MBZI ","M7N5STAXI","M7N5STAYI","M7N5STAZI","M7N5STVXI","M7N5STVYI","M7N5STVZI","M7N5VXI ","M7N5VYI ","M7N5VZI ", & + "M7N6AXI ","M7N6AYI ","M7N6AZI ","M7N6DYNP ","M7N6FAFXI","M7N6FAFYI","M7N6FAFZI","M7N6FAGXI","M7N6FAGYI","M7N6FAGZI", & + "M7N6FAMXI","M7N6FAMYI","M7N6FAMZI","M7N6FAXI ","M7N6FAYI ","M7N6FAZI ","M7N6FBFXI","M7N6FBFYI","M7N6FBFZI","M7N6FBXI ", & + "M7N6FBYI ","M7N6FBZI ","M7N6FDXI ","M7N6FDYI ","M7N6FDZI ","M7N6FIXI ","M7N6FIYI ","M7N6FIZI ","M7N6FMGXI","M7N6FMGYI", & + "M7N6FMGZI","M7N6MBFXI","M7N6MBFYI","M7N6MBFZI","M7N6MBXI ","M7N6MBYI ","M7N6MBZI ","M7N6STAXI","M7N6STAYI","M7N6STAZI", & + "M7N6STVXI","M7N6STVYI","M7N6STVZI","M7N6VXI ","M7N6VYI ","M7N6VZI ","M7N7AXI ","M7N7AYI ","M7N7AZI ","M7N7DYNP ", & + "M7N7FAFXI","M7N7FAFYI","M7N7FAFZI","M7N7FAGXI","M7N7FAGYI","M7N7FAGZI","M7N7FAMXI","M7N7FAMYI","M7N7FAMZI","M7N7FAXI ", & + "M7N7FAYI ","M7N7FAZI ","M7N7FBFXI","M7N7FBFYI","M7N7FBFZI","M7N7FBXI ","M7N7FBYI ","M7N7FBZI ","M7N7FDXI ","M7N7FDYI ", & + "M7N7FDZI ","M7N7FIXI ","M7N7FIYI ","M7N7FIZI ","M7N7FMGXI","M7N7FMGYI","M7N7FMGZI","M7N7MBFXI","M7N7MBFYI","M7N7MBFZI", & + "M7N7MBXI ","M7N7MBYI ","M7N7MBZI ","M7N7STAXI","M7N7STAYI","M7N7STAZI","M7N7STVXI","M7N7STVYI","M7N7STVZI","M7N7VXI ", & + "M7N7VYI ","M7N7VZI ","M7N8AXI ","M7N8AYI ","M7N8AZI ","M7N8DYNP ","M7N8FAFXI","M7N8FAFYI","M7N8FAFZI","M7N8FAGXI", & + "M7N8FAGYI","M7N8FAGZI","M7N8FAMXI","M7N8FAMYI","M7N8FAMZI","M7N8FAXI ","M7N8FAYI ","M7N8FAZI ","M7N8FBFXI","M7N8FBFYI", & + "M7N8FBFZI","M7N8FBXI ","M7N8FBYI ","M7N8FBZI ","M7N8FDXI ","M7N8FDYI ","M7N8FDZI ","M7N8FIXI ","M7N8FIYI ","M7N8FIZI ", & + "M7N8FMGXI","M7N8FMGYI","M7N8FMGZI","M7N8MBFXI","M7N8MBFYI","M7N8MBFZI","M7N8MBXI ","M7N8MBYI ","M7N8MBZI ","M7N8STAXI", & + "M7N8STAYI","M7N8STAZI","M7N8STVXI","M7N8STVYI","M7N8STVZI","M7N8VXI ","M7N8VYI ","M7N8VZI ","M7N9AXI ","M7N9AYI ", & + "M7N9AZI ","M7N9DYNP ","M7N9FAFXI","M7N9FAFYI","M7N9FAFZI","M7N9FAGXI","M7N9FAGYI","M7N9FAGZI","M7N9FAMXI","M7N9FAMYI", & + "M7N9FAMZI","M7N9FAXI ","M7N9FAYI ","M7N9FAZI ","M7N9FBFXI","M7N9FBFYI","M7N9FBFZI","M7N9FBXI ","M7N9FBYI ","M7N9FBZI ", & + "M7N9FDXI ","M7N9FDYI ","M7N9FDZI ","M7N9FIXI ","M7N9FIYI ","M7N9FIZI ","M7N9FMGXI","M7N9FMGYI","M7N9FMGZI","M7N9MBFXI", & + "M7N9MBFYI","M7N9MBFZI","M7N9MBXI ","M7N9MBYI ","M7N9MBZI ","M7N9STAXI","M7N9STAYI","M7N9STAZI","M7N9STVXI","M7N9STVYI", & + "M7N9STVZI","M7N9VXI ","M7N9VYI ","M7N9VZI ","M8N1AXI ","M8N1AYI ","M8N1AZI ","M8N1DYNP ","M8N1FAFXI","M8N1FAFYI", & + "M8N1FAFZI","M8N1FAGXI","M8N1FAGYI","M8N1FAGZI","M8N1FAMXI","M8N1FAMYI","M8N1FAMZI","M8N1FAXI ","M8N1FAYI ","M8N1FAZI ", & + "M8N1FBFXI","M8N1FBFYI","M8N1FBFZI","M8N1FBXI ","M8N1FBYI ","M8N1FBZI ","M8N1FDXI ","M8N1FDYI ","M8N1FDZI ","M8N1FIXI ", & + "M8N1FIYI ","M8N1FIZI ","M8N1FMGXI","M8N1FMGYI","M8N1FMGZI","M8N1MBFXI","M8N1MBFYI","M8N1MBFZI","M8N1MBXI ","M8N1MBYI ", & + "M8N1MBZI ","M8N1STAXI","M8N1STAYI","M8N1STAZI","M8N1STVXI","M8N1STVYI","M8N1STVZI","M8N1VXI ","M8N1VYI ","M8N1VZI ", & + "M8N2AXI ","M8N2AYI ","M8N2AZI ","M8N2DYNP ","M8N2FAFXI","M8N2FAFYI","M8N2FAFZI","M8N2FAGXI","M8N2FAGYI","M8N2FAGZI", & + "M8N2FAMXI","M8N2FAMYI","M8N2FAMZI","M8N2FAXI ","M8N2FAYI ","M8N2FAZI ","M8N2FBFXI","M8N2FBFYI","M8N2FBFZI","M8N2FBXI ", & + "M8N2FBYI ","M8N2FBZI ","M8N2FDXI ","M8N2FDYI ","M8N2FDZI ","M8N2FIXI ","M8N2FIYI ","M8N2FIZI ","M8N2FMGXI","M8N2FMGYI", & + "M8N2FMGZI","M8N2MBFXI","M8N2MBFYI","M8N2MBFZI","M8N2MBXI ","M8N2MBYI ","M8N2MBZI ","M8N2STAXI","M8N2STAYI","M8N2STAZI", & + "M8N2STVXI","M8N2STVYI","M8N2STVZI","M8N2VXI ","M8N2VYI ","M8N2VZI ","M8N3AXI ","M8N3AYI ","M8N3AZI ","M8N3DYNP ", & + "M8N3FAFXI","M8N3FAFYI","M8N3FAFZI","M8N3FAGXI","M8N3FAGYI","M8N3FAGZI","M8N3FAMXI","M8N3FAMYI","M8N3FAMZI","M8N3FAXI ", & + "M8N3FAYI ","M8N3FAZI ","M8N3FBFXI","M8N3FBFYI","M8N3FBFZI","M8N3FBXI ","M8N3FBYI ","M8N3FBZI ","M8N3FDXI ","M8N3FDYI ", & + "M8N3FDZI ","M8N3FIXI ","M8N3FIYI ","M8N3FIZI ","M8N3FMGXI","M8N3FMGYI","M8N3FMGZI","M8N3MBFXI","M8N3MBFYI","M8N3MBFZI", & + "M8N3MBXI ","M8N3MBYI ","M8N3MBZI ","M8N3STAXI","M8N3STAYI","M8N3STAZI","M8N3STVXI","M8N3STVYI","M8N3STVZI","M8N3VXI ", & + "M8N3VYI ","M8N3VZI ","M8N4AXI ","M8N4AYI ","M8N4AZI ","M8N4DYNP ","M8N4FAFXI","M8N4FAFYI","M8N4FAFZI","M8N4FAGXI", & + "M8N4FAGYI","M8N4FAGZI","M8N4FAMXI","M8N4FAMYI","M8N4FAMZI","M8N4FAXI ","M8N4FAYI ","M8N4FAZI ","M8N4FBFXI","M8N4FBFYI", & + "M8N4FBFZI","M8N4FBXI ","M8N4FBYI ","M8N4FBZI ","M8N4FDXI ","M8N4FDYI ","M8N4FDZI ","M8N4FIXI ","M8N4FIYI ","M8N4FIZI ", & + "M8N4FMGXI","M8N4FMGYI","M8N4FMGZI","M8N4MBFXI","M8N4MBFYI","M8N4MBFZI","M8N4MBXI ","M8N4MBYI ","M8N4MBZI ","M8N4STAXI", & + "M8N4STAYI","M8N4STAZI","M8N4STVXI","M8N4STVYI","M8N4STVZI","M8N4VXI ","M8N4VYI ","M8N4VZI ","M8N5AXI ","M8N5AYI ", & + "M8N5AZI ","M8N5DYNP ","M8N5FAFXI","M8N5FAFYI","M8N5FAFZI","M8N5FAGXI","M8N5FAGYI","M8N5FAGZI","M8N5FAMXI","M8N5FAMYI", & + "M8N5FAMZI","M8N5FAXI ","M8N5FAYI ","M8N5FAZI ","M8N5FBFXI","M8N5FBFYI","M8N5FBFZI","M8N5FBXI ","M8N5FBYI ","M8N5FBZI ", & + "M8N5FDXI ","M8N5FDYI ","M8N5FDZI ","M8N5FIXI ","M8N5FIYI ","M8N5FIZI ","M8N5FMGXI","M8N5FMGYI","M8N5FMGZI","M8N5MBFXI", & + "M8N5MBFYI","M8N5MBFZI","M8N5MBXI ","M8N5MBYI ","M8N5MBZI ","M8N5STAXI","M8N5STAYI","M8N5STAZI","M8N5STVXI","M8N5STVYI", & + "M8N5STVZI","M8N5VXI ","M8N5VYI ","M8N5VZI ","M8N6AXI ","M8N6AYI ","M8N6AZI ","M8N6DYNP ","M8N6FAFXI","M8N6FAFYI", & + "M8N6FAFZI","M8N6FAGXI","M8N6FAGYI","M8N6FAGZI","M8N6FAMXI","M8N6FAMYI","M8N6FAMZI","M8N6FAXI ","M8N6FAYI ","M8N6FAZI ", & + "M8N6FBFXI","M8N6FBFYI","M8N6FBFZI","M8N6FBXI ","M8N6FBYI ","M8N6FBZI ","M8N6FDXI ","M8N6FDYI ","M8N6FDZI ","M8N6FIXI ", & + "M8N6FIYI ","M8N6FIZI ","M8N6FMGXI","M8N6FMGYI","M8N6FMGZI","M8N6MBFXI","M8N6MBFYI","M8N6MBFZI","M8N6MBXI ","M8N6MBYI ", & + "M8N6MBZI ","M8N6STAXI","M8N6STAYI","M8N6STAZI","M8N6STVXI","M8N6STVYI","M8N6STVZI","M8N6VXI ","M8N6VYI ","M8N6VZI ", & + "M8N7AXI ","M8N7AYI ","M8N7AZI ","M8N7DYNP ","M8N7FAFXI","M8N7FAFYI","M8N7FAFZI","M8N7FAGXI","M8N7FAGYI","M8N7FAGZI", & + "M8N7FAMXI","M8N7FAMYI","M8N7FAMZI","M8N7FAXI ","M8N7FAYI ","M8N7FAZI ","M8N7FBFXI","M8N7FBFYI","M8N7FBFZI","M8N7FBXI ", & + "M8N7FBYI ","M8N7FBZI ","M8N7FDXI ","M8N7FDYI ","M8N7FDZI ","M8N7FIXI ","M8N7FIYI ","M8N7FIZI ","M8N7FMGXI","M8N7FMGYI", & + "M8N7FMGZI","M8N7MBFXI","M8N7MBFYI","M8N7MBFZI","M8N7MBXI ","M8N7MBYI ","M8N7MBZI ","M8N7STAXI","M8N7STAYI","M8N7STAZI", & + "M8N7STVXI","M8N7STVYI","M8N7STVZI","M8N7VXI ","M8N7VYI ","M8N7VZI ","M8N8AXI ","M8N8AYI ","M8N8AZI ","M8N8DYNP ", & + "M8N8FAFXI","M8N8FAFYI","M8N8FAFZI","M8N8FAGXI","M8N8FAGYI","M8N8FAGZI","M8N8FAMXI","M8N8FAMYI","M8N8FAMZI","M8N8FAXI ", & + "M8N8FAYI ","M8N8FAZI ","M8N8FBFXI","M8N8FBFYI","M8N8FBFZI","M8N8FBXI ","M8N8FBYI ","M8N8FBZI ","M8N8FDXI ","M8N8FDYI ", & + "M8N8FDZI ","M8N8FIXI ","M8N8FIYI ","M8N8FIZI ","M8N8FMGXI","M8N8FMGYI","M8N8FMGZI","M8N8MBFXI","M8N8MBFYI","M8N8MBFZI", & + "M8N8MBXI ","M8N8MBYI ","M8N8MBZI ","M8N8STAXI","M8N8STAYI","M8N8STAZI","M8N8STVXI","M8N8STVYI","M8N8STVZI","M8N8VXI ", & + "M8N8VYI ","M8N8VZI ","M8N9AXI ","M8N9AYI ","M8N9AZI ","M8N9DYNP ","M8N9FAFXI","M8N9FAFYI","M8N9FAFZI","M8N9FAGXI", & + "M8N9FAGYI","M8N9FAGZI","M8N9FAMXI","M8N9FAMYI","M8N9FAMZI","M8N9FAXI ","M8N9FAYI ","M8N9FAZI ","M8N9FBFXI","M8N9FBFYI", & + "M8N9FBFZI","M8N9FBXI ","M8N9FBYI ","M8N9FBZI ","M8N9FDXI ","M8N9FDYI ","M8N9FDZI ","M8N9FIXI ","M8N9FIYI ","M8N9FIZI ", & + "M8N9FMGXI","M8N9FMGYI","M8N9FMGZI","M8N9MBFXI","M8N9MBFYI","M8N9MBFZI","M8N9MBXI ","M8N9MBYI ","M8N9MBZI ","M8N9STAXI", & + "M8N9STAYI","M8N9STAZI","M8N9STVXI","M8N9STVYI","M8N9STVZI","M8N9VXI ","M8N9VYI ","M8N9VZI ","M9N1AXI ","M9N1AYI ", & + "M9N1AZI ","M9N1DYNP ","M9N1FAFXI","M9N1FAFYI","M9N1FAFZI","M9N1FAGXI","M9N1FAGYI","M9N1FAGZI","M9N1FAMXI","M9N1FAMYI", & + "M9N1FAMZI","M9N1FAXI ","M9N1FAYI ","M9N1FAZI ","M9N1FBFXI","M9N1FBFYI","M9N1FBFZI","M9N1FBXI ","M9N1FBYI ","M9N1FBZI ", & + "M9N1FDXI ","M9N1FDYI ","M9N1FDZI ","M9N1FIXI ","M9N1FIYI ","M9N1FIZI ","M9N1FMGXI","M9N1FMGYI","M9N1FMGZI","M9N1MBFXI", & + "M9N1MBFYI","M9N1MBFZI","M9N1MBXI ","M9N1MBYI ","M9N1MBZI ","M9N1STAXI","M9N1STAYI","M9N1STAZI","M9N1STVXI","M9N1STVYI", & + "M9N1STVZI","M9N1VXI ","M9N1VYI ","M9N1VZI ","M9N2AXI ","M9N2AYI ","M9N2AZI ","M9N2DYNP ","M9N2FAFXI","M9N2FAFYI", & + "M9N2FAFZI","M9N2FAGXI","M9N2FAGYI","M9N2FAGZI","M9N2FAMXI","M9N2FAMYI","M9N2FAMZI","M9N2FAXI ","M9N2FAYI ","M9N2FAZI ", & + "M9N2FBFXI","M9N2FBFYI","M9N2FBFZI","M9N2FBXI ","M9N2FBYI ","M9N2FBZI ","M9N2FDXI ","M9N2FDYI ","M9N2FDZI ","M9N2FIXI ", & + "M9N2FIYI ","M9N2FIZI ","M9N2FMGXI","M9N2FMGYI","M9N2FMGZI","M9N2MBFXI","M9N2MBFYI","M9N2MBFZI","M9N2MBXI ","M9N2MBYI ", & + "M9N2MBZI ","M9N2STAXI","M9N2STAYI","M9N2STAZI","M9N2STVXI","M9N2STVYI","M9N2STVZI","M9N2VXI ","M9N2VYI ","M9N2VZI ", & + "M9N3AXI ","M9N3AYI ","M9N3AZI ","M9N3DYNP ","M9N3FAFXI","M9N3FAFYI","M9N3FAFZI","M9N3FAGXI","M9N3FAGYI","M9N3FAGZI", & + "M9N3FAMXI","M9N3FAMYI","M9N3FAMZI","M9N3FAXI ","M9N3FAYI ","M9N3FAZI ","M9N3FBFXI","M9N3FBFYI","M9N3FBFZI","M9N3FBXI ", & + "M9N3FBYI ","M9N3FBZI ","M9N3FDXI ","M9N3FDYI ","M9N3FDZI ","M9N3FIXI ","M9N3FIYI ","M9N3FIZI ","M9N3FMGXI","M9N3FMGYI", & + "M9N3FMGZI","M9N3MBFXI","M9N3MBFYI","M9N3MBFZI","M9N3MBXI ","M9N3MBYI ","M9N3MBZI ","M9N3STAXI","M9N3STAYI","M9N3STAZI", & + "M9N3STVXI","M9N3STVYI","M9N3STVZI","M9N3VXI ","M9N3VYI ","M9N3VZI ","M9N4AXI ","M9N4AYI ","M9N4AZI ","M9N4DYNP ", & + "M9N4FAFXI","M9N4FAFYI","M9N4FAFZI","M9N4FAGXI","M9N4FAGYI","M9N4FAGZI","M9N4FAMXI","M9N4FAMYI","M9N4FAMZI","M9N4FAXI ", & + "M9N4FAYI ","M9N4FAZI ","M9N4FBFXI","M9N4FBFYI","M9N4FBFZI","M9N4FBXI ","M9N4FBYI ","M9N4FBZI ","M9N4FDXI ","M9N4FDYI ", & + "M9N4FDZI ","M9N4FIXI ","M9N4FIYI ","M9N4FIZI ","M9N4FMGXI","M9N4FMGYI","M9N4FMGZI","M9N4MBFXI","M9N4MBFYI","M9N4MBFZI", & + "M9N4MBXI ","M9N4MBYI ","M9N4MBZI ","M9N4STAXI","M9N4STAYI","M9N4STAZI","M9N4STVXI","M9N4STVYI","M9N4STVZI","M9N4VXI ", & + "M9N4VYI ","M9N4VZI ","M9N5AXI ","M9N5AYI ","M9N5AZI ","M9N5DYNP ","M9N5FAFXI","M9N5FAFYI","M9N5FAFZI","M9N5FAGXI", & + "M9N5FAGYI","M9N5FAGZI","M9N5FAMXI","M9N5FAMYI","M9N5FAMZI","M9N5FAXI ","M9N5FAYI ","M9N5FAZI ","M9N5FBFXI","M9N5FBFYI", & + "M9N5FBFZI","M9N5FBXI ","M9N5FBYI ","M9N5FBZI ","M9N5FDXI ","M9N5FDYI ","M9N5FDZI ","M9N5FIXI ","M9N5FIYI ","M9N5FIZI ", & + "M9N5FMGXI","M9N5FMGYI","M9N5FMGZI","M9N5MBFXI","M9N5MBFYI","M9N5MBFZI","M9N5MBXI ","M9N5MBYI ","M9N5MBZI ","M9N5STAXI", & + "M9N5STAYI","M9N5STAZI","M9N5STVXI","M9N5STVYI","M9N5STVZI","M9N5VXI ","M9N5VYI ","M9N5VZI ","M9N6AXI ","M9N6AYI ", & + "M9N6AZI ","M9N6DYNP ","M9N6FAFXI","M9N6FAFYI","M9N6FAFZI","M9N6FAGXI","M9N6FAGYI","M9N6FAGZI","M9N6FAMXI","M9N6FAMYI", & + "M9N6FAMZI","M9N6FAXI ","M9N6FAYI ","M9N6FAZI ","M9N6FBFXI","M9N6FBFYI","M9N6FBFZI","M9N6FBXI ","M9N6FBYI ","M9N6FBZI ", & + "M9N6FDXI ","M9N6FDYI ","M9N6FDZI ","M9N6FIXI ","M9N6FIYI ","M9N6FIZI ","M9N6FMGXI","M9N6FMGYI","M9N6FMGZI","M9N6MBFXI", & + "M9N6MBFYI","M9N6MBFZI","M9N6MBXI ","M9N6MBYI ","M9N6MBZI ","M9N6STAXI","M9N6STAYI","M9N6STAZI","M9N6STVXI","M9N6STVYI", & + "M9N6STVZI","M9N6VXI ","M9N6VYI ","M9N6VZI ","M9N7AXI ","M9N7AYI ","M9N7AZI ","M9N7DYNP ","M9N7FAFXI","M9N7FAFYI", & + "M9N7FAFZI","M9N7FAGXI","M9N7FAGYI","M9N7FAGZI","M9N7FAMXI","M9N7FAMYI","M9N7FAMZI","M9N7FAXI ","M9N7FAYI ","M9N7FAZI ", & + "M9N7FBFXI","M9N7FBFYI","M9N7FBFZI","M9N7FBXI ","M9N7FBYI ","M9N7FBZI ","M9N7FDXI ","M9N7FDYI ","M9N7FDZI ","M9N7FIXI ", & + "M9N7FIYI ","M9N7FIZI ","M9N7FMGXI","M9N7FMGYI","M9N7FMGZI","M9N7MBFXI","M9N7MBFYI","M9N7MBFZI","M9N7MBXI ","M9N7MBYI ", & + "M9N7MBZI ","M9N7STAXI","M9N7STAYI","M9N7STAZI","M9N7STVXI","M9N7STVYI","M9N7STVZI","M9N7VXI ","M9N7VYI ","M9N7VZI ", & + "M9N8AXI ","M9N8AYI ","M9N8AZI ","M9N8DYNP ","M9N8FAFXI","M9N8FAFYI","M9N8FAFZI","M9N8FAGXI","M9N8FAGYI","M9N8FAGZI", & + "M9N8FAMXI","M9N8FAMYI","M9N8FAMZI","M9N8FAXI ","M9N8FAYI ","M9N8FAZI ","M9N8FBFXI","M9N8FBFYI","M9N8FBFZI","M9N8FBXI ", & + "M9N8FBYI ","M9N8FBZI ","M9N8FDXI ","M9N8FDYI ","M9N8FDZI ","M9N8FIXI ","M9N8FIYI ","M9N8FIZI ","M9N8FMGXI","M9N8FMGYI", & + "M9N8FMGZI","M9N8MBFXI","M9N8MBFYI","M9N8MBFZI","M9N8MBXI ","M9N8MBYI ","M9N8MBZI ","M9N8STAXI","M9N8STAYI","M9N8STAZI", & + "M9N8STVXI","M9N8STVYI","M9N8STVZI","M9N8VXI ","M9N8VYI ","M9N8VZI ","M9N9AXI ","M9N9AYI ","M9N9AZI ","M9N9DYNP ", & + "M9N9FAFXI","M9N9FAFYI","M9N9FAFZI","M9N9FAGXI","M9N9FAGYI","M9N9FAGZI","M9N9FAMXI","M9N9FAMYI","M9N9FAMZI","M9N9FAXI ", & + "M9N9FAYI ","M9N9FAZI ","M9N9FBFXI","M9N9FBFYI","M9N9FBFZI","M9N9FBXI ","M9N9FBYI ","M9N9FBZI ","M9N9FDXI ","M9N9FDYI ", & + "M9N9FDZI ","M9N9FIXI ","M9N9FIYI ","M9N9FIZI ","M9N9FMGXI","M9N9FMGYI","M9N9FMGZI","M9N9MBFXI","M9N9MBFYI","M9N9MBFZI", & + "M9N9MBXI ","M9N9MBYI ","M9N9MBZI ","M9N9STAXI","M9N9STAYI","M9N9STAZI","M9N9STVXI","M9N9STVYI","M9N9STVZI","M9N9VXI ", & + "M9N9VYI ","M9N9VZI "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(4032) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + J1Axi , J1Ayi , J1Azi , J1DynP , J1FAMxi , J1FAMyi , J1FAMzi , J1FBFxi , J1FBFyi , J1FBFzi , & + J1FBxi , J1FByi , J1FBzi , J1FDxi , J1FDyi , J1FDzi , J1FIxi , J1FIyi , J1FIzi , J1MBFxi , & + J1MBFyi , J1MBFzi , J1MBxi , J1MByi , J1MBzi , J1STAxi , J1STAyi , J1STAzi , J1STVxi , J1STVyi , & + J1STVzi , J1Vxi , J1Vyi , J1Vzi , J2Axi , J2Ayi , J2Azi , J2DynP , J2FAMxi , J2FAMyi , & + J2FAMzi , J2FBFxi , J2FBFyi , J2FBFzi , J2FBxi , J2FByi , J2FBzi , J2FDxi , J2FDyi , J2FDzi , & + J2FIxi , J2FIyi , J2FIzi , J2MBFxi , J2MBFyi , J2MBFzi , J2MBxi , J2MByi , J2MBzi , J2STAxi , & + J2STAyi , J2STAzi , J2STVxi , J2STVyi , J2STVzi , J2Vxi , J2Vyi , J2Vzi , J3Axi , J3Ayi , & + J3Azi , J3DynP , J3FAMxi , J3FAMyi , J3FAMzi , J3FBFxi , J3FBFyi , J3FBFzi , J3FBxi , J3FByi , & + J3FBzi , J3FDxi , J3FDyi , J3FDzi , J3FIxi , J3FIyi , J3FIzi , J3MBFxi , J3MBFyi , J3MBFzi , & + J3MBxi , J3MByi , J3MBzi , J3STAxi , J3STAyi , J3STAzi , J3STVxi , J3STVyi , J3STVzi , J3Vxi , & + J3Vyi , J3Vzi , J4Axi , J4Ayi , J4Azi , J4DynP , J4FAMxi , J4FAMyi , J4FAMzi , J4FBFxi , & + J4FBFyi , J4FBFzi , J4FBxi , J4FByi , J4FBzi , J4FDxi , J4FDyi , J4FDzi , J4FIxi , J4FIyi , & + J4FIzi , J4MBFxi , J4MBFyi , J4MBFzi , J4MBxi , J4MByi , J4MBzi , J4STAxi , J4STAyi , J4STAzi , & + J4STVxi , J4STVyi , J4STVzi , J4Vxi , J4Vyi , J4Vzi , J5Axi , J5Ayi , J5Azi , J5DynP , & + J5FAMxi , J5FAMyi , J5FAMzi , J5FBFxi , J5FBFyi , J5FBFzi , J5FBxi , J5FByi , J5FBzi , J5FDxi , & + J5FDyi , J5FDzi , J5FIxi , J5FIyi , J5FIzi , J5MBFxi , J5MBFyi , J5MBFzi , J5MBxi , J5MByi , & + J5MBzi , J5STAxi , J5STAyi , J5STAzi , J5STVxi , J5STVyi , J5STVzi , J5Vxi , J5Vyi , J5Vzi , & + J6Axi , J6Ayi , J6Azi , J6DynP , J6FAMxi , J6FAMyi , J6FAMzi , J6FBFxi , J6FBFyi , J6FBFzi , & + J6FBxi , J6FByi , J6FBzi , J6FDxi , J6FDyi , J6FDzi , J6FIxi , J6FIyi , J6FIzi , J6MBFxi , & + J6MBFyi , J6MBFzi , J6MBxi , J6MByi , J6MBzi , J6STAxi , J6STAyi , J6STAzi , J6STVxi , J6STVyi , & + J6STVzi , J6Vxi , J6Vyi , J6Vzi , J7Axi , J7Ayi , J7Azi , J7DynP , J7FAMxi , J7FAMyi , & + J7FAMzi , J7FBFxi , J7FBFyi , J7FBFzi , J7FBxi , J7FByi , J7FBzi , J7FDxi , J7FDyi , J7FDzi , & + J7FIxi , J7FIyi , J7FIzi , J7MBFxi , J7MBFyi , J7MBFzi , J7MBxi , J7MByi , J7MBzi , J7STAxi , & + J7STAyi , J7STAzi , J7STVxi , J7STVyi , J7STVzi , J7Vxi , J7Vyi , J7Vzi , J8Axi , J8Ayi , & + J8Azi , J8DynP , J8FAMxi , J8FAMyi , J8FAMzi , J8FBFxi , J8FBFyi , J8FBFzi , J8FBxi , J8FByi , & + J8FBzi , J8FDxi , J8FDyi , J8FDzi , J8FIxi , J8FIyi , J8FIzi , J8MBFxi , J8MBFyi , J8MBFzi , & + J8MBxi , J8MByi , J8MBzi , J8STAxi , J8STAyi , J8STAzi , J8STVxi , J8STVyi , J8STVzi , J8Vxi , & + J8Vyi , J8Vzi , J9Axi , J9Ayi , J9Azi , J9DynP , J9FAMxi , J9FAMyi , J9FAMzi , J9FBFxi , & + J9FBFyi , J9FBFzi , J9FBxi , J9FByi , J9FBzi , J9FDxi , J9FDyi , J9FDzi , J9FIxi , J9FIyi , & + J9FIzi , J9MBFxi , J9MBFyi , J9MBFzi , J9MBxi , J9MByi , J9MBzi , J9STAxi , J9STAyi , J9STAzi , & + J9STVxi , J9STVyi , J9STVzi , J9Vxi , J9Vyi , J9Vzi , M1N1Axi , M1N1Ayi , M1N1Azi , M1N1DynP , & + M1N1FAFxi , M1N1FAFyi , M1N1FAFzi , M1N1FAGxi , M1N1FAGyi , M1N1FAGzi , M1N1FAMxi , M1N1FAMyi , M1N1FAMzi , M1N1FAxi , & + M1N1FAyi , M1N1FAzi , M1N1FBFxi , M1N1FBFyi , M1N1FBFzi , M1N1FBxi , M1N1FByi , M1N1FBzi , M1N1FDxi , M1N1FDyi , & + M1N1FDzi , M1N1FIxi , M1N1FIyi , M1N1FIzi , M1N1FMGxi , M1N1FMGyi , M1N1FMGzi , M1N1MBFxi , M1N1MBFyi , M1N1MBFzi , & + M1N1MBxi , M1N1MByi , M1N1MBzi , M1N1STAxi , M1N1STAyi , M1N1STAzi , M1N1STVxi , M1N1STVyi , M1N1STVzi , M1N1Vxi , & + M1N1Vyi , M1N1Vzi , M1N2Axi , M1N2Ayi , M1N2Azi , M1N2DynP , M1N2FAFxi , M1N2FAFyi , M1N2FAFzi , M1N2FAGxi , & + M1N2FAGyi , M1N2FAGzi , M1N2FAMxi , M1N2FAMyi , M1N2FAMzi , M1N2FAxi , M1N2FAyi , M1N2FAzi , M1N2FBFxi , M1N2FBFyi , & + M1N2FBFzi , M1N2FBxi , M1N2FByi , M1N2FBzi , M1N2FDxi , M1N2FDyi , M1N2FDzi , M1N2FIxi , M1N2FIyi , M1N2FIzi , & + M1N2FMGxi , M1N2FMGyi , M1N2FMGzi , M1N2MBFxi , M1N2MBFyi , M1N2MBFzi , M1N2MBxi , M1N2MByi , M1N2MBzi , M1N2STAxi , & + M1N2STAyi , M1N2STAzi , M1N2STVxi , M1N2STVyi , M1N2STVzi , M1N2Vxi , M1N2Vyi , M1N2Vzi , M1N3Axi , M1N3Ayi , & + M1N3Azi , M1N3DynP , M1N3FAFxi , M1N3FAFyi , M1N3FAFzi , M1N3FAGxi , M1N3FAGyi , M1N3FAGzi , M1N3FAMxi , M1N3FAMyi , & + M1N3FAMzi , M1N3FAxi , M1N3FAyi , M1N3FAzi , M1N3FBFxi , M1N3FBFyi , M1N3FBFzi , M1N3FBxi , M1N3FByi , M1N3FBzi , & + M1N3FDxi , M1N3FDyi , M1N3FDzi , M1N3FIxi , M1N3FIyi , M1N3FIzi , M1N3FMGxi , M1N3FMGyi , M1N3FMGzi , M1N3MBFxi , & + M1N3MBFyi , M1N3MBFzi , M1N3MBxi , M1N3MByi , M1N3MBzi , M1N3STAxi , M1N3STAyi , M1N3STAzi , M1N3STVxi , M1N3STVyi , & + M1N3STVzi , M1N3Vxi , M1N3Vyi , M1N3Vzi , M1N4Axi , M1N4Ayi , M1N4Azi , M1N4DynP , M1N4FAFxi , M1N4FAFyi , & + M1N4FAFzi , M1N4FAGxi , M1N4FAGyi , M1N4FAGzi , M1N4FAMxi , M1N4FAMyi , M1N4FAMzi , M1N4FAxi , M1N4FAyi , M1N4FAzi , & + M1N4FBFxi , M1N4FBFyi , M1N4FBFzi , M1N4FBxi , M1N4FByi , M1N4FBzi , M1N4FDxi , M1N4FDyi , M1N4FDzi , M1N4FIxi , & + M1N4FIyi , M1N4FIzi , M1N4FMGxi , M1N4FMGyi , M1N4FMGzi , M1N4MBFxi , M1N4MBFyi , M1N4MBFzi , M1N4MBxi , M1N4MByi , & + M1N4MBzi , M1N4STAxi , M1N4STAyi , M1N4STAzi , M1N4STVxi , M1N4STVyi , M1N4STVzi , M1N4Vxi , M1N4Vyi , M1N4Vzi , & + M1N5Axi , M1N5Ayi , M1N5Azi , M1N5DynP , M1N5FAFxi , M1N5FAFyi , M1N5FAFzi , M1N5FAGxi , M1N5FAGyi , M1N5FAGzi , & + M1N5FAMxi , M1N5FAMyi , M1N5FAMzi , M1N5FAxi , M1N5FAyi , M1N5FAzi , M1N5FBFxi , M1N5FBFyi , M1N5FBFzi , M1N5FBxi , & + M1N5FByi , M1N5FBzi , M1N5FDxi , M1N5FDyi , M1N5FDzi , M1N5FIxi , M1N5FIyi , M1N5FIzi , M1N5FMGxi , M1N5FMGyi , & + M1N5FMGzi , M1N5MBFxi , M1N5MBFyi , M1N5MBFzi , M1N5MBxi , M1N5MByi , M1N5MBzi , M1N5STAxi , M1N5STAyi , M1N5STAzi , & + M1N5STVxi , M1N5STVyi , M1N5STVzi , M1N5Vxi , M1N5Vyi , M1N5Vzi , M1N6Axi , M1N6Ayi , M1N6Azi , M1N6DynP , & + M1N6FAFxi , M1N6FAFyi , M1N6FAFzi , M1N6FAGxi , M1N6FAGyi , M1N6FAGzi , M1N6FAMxi , M1N6FAMyi , M1N6FAMzi , M1N6FAxi , & + M1N6FAyi , M1N6FAzi , M1N6FBFxi , M1N6FBFyi , M1N6FBFzi , M1N6FBxi , M1N6FByi , M1N6FBzi , M1N6FDxi , M1N6FDyi , & + M1N6FDzi , M1N6FIxi , M1N6FIyi , M1N6FIzi , M1N6FMGxi , M1N6FMGyi , M1N6FMGzi , M1N6MBFxi , M1N6MBFyi , M1N6MBFzi , & + M1N6MBxi , M1N6MByi , M1N6MBzi , M1N6STAxi , M1N6STAyi , M1N6STAzi , M1N6STVxi , M1N6STVyi , M1N6STVzi , M1N6Vxi , & + M1N6Vyi , M1N6Vzi , M1N7Axi , M1N7Ayi , M1N7Azi , M1N7DynP , M1N7FAFxi , M1N7FAFyi , M1N7FAFzi , M1N7FAGxi , & + M1N7FAGyi , M1N7FAGzi , M1N7FAMxi , M1N7FAMyi , M1N7FAMzi , M1N7FAxi , M1N7FAyi , M1N7FAzi , M1N7FBFxi , M1N7FBFyi , & + M1N7FBFzi , M1N7FBxi , M1N7FByi , M1N7FBzi , M1N7FDxi , M1N7FDyi , M1N7FDzi , M1N7FIxi , M1N7FIyi , M1N7FIzi , & + M1N7FMGxi , M1N7FMGyi , M1N7FMGzi , M1N7MBFxi , M1N7MBFyi , M1N7MBFzi , M1N7MBxi , M1N7MByi , M1N7MBzi , M1N7STAxi , & + M1N7STAyi , M1N7STAzi , M1N7STVxi , M1N7STVyi , M1N7STVzi , M1N7Vxi , M1N7Vyi , M1N7Vzi , M1N8Axi , M1N8Ayi , & + M1N8Azi , M1N8DynP , M1N8FAFxi , M1N8FAFyi , M1N8FAFzi , M1N8FAGxi , M1N8FAGyi , M1N8FAGzi , M1N8FAMxi , M1N8FAMyi , & + M1N8FAMzi , M1N8FAxi , M1N8FAyi , M1N8FAzi , M1N8FBFxi , M1N8FBFyi , M1N8FBFzi , M1N8FBxi , M1N8FByi , M1N8FBzi , & + M1N8FDxi , M1N8FDyi , M1N8FDzi , M1N8FIxi , M1N8FIyi , M1N8FIzi , M1N8FMGxi , M1N8FMGyi , M1N8FMGzi , M1N8MBFxi , & + M1N8MBFyi , M1N8MBFzi , M1N8MBxi , M1N8MByi , M1N8MBzi , M1N8STAxi , M1N8STAyi , M1N8STAzi , M1N8STVxi , M1N8STVyi , & + M1N8STVzi , M1N8Vxi , M1N8Vyi , M1N8Vzi , M1N9Axi , M1N9Ayi , M1N9Azi , M1N9DynP , M1N9FAFxi , M1N9FAFyi , & + M1N9FAFzi , M1N9FAGxi , M1N9FAGyi , M1N9FAGzi , M1N9FAMxi , M1N9FAMyi , M1N9FAMzi , M1N9FAxi , M1N9FAyi , M1N9FAzi , & + M1N9FBFxi , M1N9FBFyi , M1N9FBFzi , M1N9FBxi , M1N9FByi , M1N9FBzi , M1N9FDxi , M1N9FDyi , M1N9FDzi , M1N9FIxi , & + M1N9FIyi , M1N9FIzi , M1N9FMGxi , M1N9FMGyi , M1N9FMGzi , M1N9MBFxi , M1N9MBFyi , M1N9MBFzi , M1N9MBxi , M1N9MByi , & + M1N9MBzi , M1N9STAxi , M1N9STAyi , M1N9STAzi , M1N9STVxi , M1N9STVyi , M1N9STVzi , M1N9Vxi , M1N9Vyi , M1N9Vzi , & + M2N1Axi , M2N1Ayi , M2N1Azi , M2N1DynP , M2N1FAFxi , M2N1FAFyi , M2N1FAFzi , M2N1FAGxi , M2N1FAGyi , M2N1FAGzi , & + M2N1FAMxi , M2N1FAMyi , M2N1FAMzi , M2N1FAxi , M2N1FAyi , M2N1FAzi , M2N1FBFxi , M2N1FBFyi , M2N1FBFzi , M2N1FBxi , & + M2N1FByi , M2N1FBzi , M2N1FDxi , M2N1FDyi , M2N1FDzi , M2N1FIxi , M2N1FIyi , M2N1FIzi , M2N1FMGxi , M2N1FMGyi , & + M2N1FMGzi , M2N1MBFxi , M2N1MBFyi , M2N1MBFzi , M2N1MBxi , M2N1MByi , M2N1MBzi , M2N1STAxi , M2N1STAyi , M2N1STAzi , & + M2N1STVxi , M2N1STVyi , M2N1STVzi , M2N1Vxi , M2N1Vyi , M2N1Vzi , M2N2Axi , M2N2Ayi , M2N2Azi , M2N2DynP , & + M2N2FAFxi , M2N2FAFyi , M2N2FAFzi , M2N2FAGxi , M2N2FAGyi , M2N2FAGzi , M2N2FAMxi , M2N2FAMyi , M2N2FAMzi , M2N2FAxi , & + M2N2FAyi , M2N2FAzi , M2N2FBFxi , M2N2FBFyi , M2N2FBFzi , M2N2FBxi , M2N2FByi , M2N2FBzi , M2N2FDxi , M2N2FDyi , & + M2N2FDzi , M2N2FIxi , M2N2FIyi , M2N2FIzi , M2N2FMGxi , M2N2FMGyi , M2N2FMGzi , M2N2MBFxi , M2N2MBFyi , M2N2MBFzi , & + M2N2MBxi , M2N2MByi , M2N2MBzi , M2N2STAxi , M2N2STAyi , M2N2STAzi , M2N2STVxi , M2N2STVyi , M2N2STVzi , M2N2Vxi , & + M2N2Vyi , M2N2Vzi , M2N3Axi , M2N3Ayi , M2N3Azi , M2N3DynP , M2N3FAFxi , M2N3FAFyi , M2N3FAFzi , M2N3FAGxi , & + M2N3FAGyi , M2N3FAGzi , M2N3FAMxi , M2N3FAMyi , M2N3FAMzi , M2N3FAxi , M2N3FAyi , M2N3FAzi , M2N3FBFxi , M2N3FBFyi , & + M2N3FBFzi , M2N3FBxi , M2N3FByi , M2N3FBzi , M2N3FDxi , M2N3FDyi , M2N3FDzi , M2N3FIxi , M2N3FIyi , M2N3FIzi , & + M2N3FMGxi , M2N3FMGyi , M2N3FMGzi , M2N3MBFxi , M2N3MBFyi , M2N3MBFzi , M2N3MBxi , M2N3MByi , M2N3MBzi , M2N3STAxi , & + M2N3STAyi , M2N3STAzi , M2N3STVxi , M2N3STVyi , M2N3STVzi , M2N3Vxi , M2N3Vyi , M2N3Vzi , M2N4Axi , M2N4Ayi , & + M2N4Azi , M2N4DynP , M2N4FAFxi , M2N4FAFyi , M2N4FAFzi , M2N4FAGxi , M2N4FAGyi , M2N4FAGzi , M2N4FAMxi , M2N4FAMyi , & + M2N4FAMzi , M2N4FAxi , M2N4FAyi , M2N4FAzi , M2N4FBFxi , M2N4FBFyi , M2N4FBFzi , M2N4FBxi , M2N4FByi , M2N4FBzi , & + M2N4FDxi , M2N4FDyi , M2N4FDzi , M2N4FIxi , M2N4FIyi , M2N4FIzi , M2N4FMGxi , M2N4FMGyi , M2N4FMGzi , M2N4MBFxi , & + M2N4MBFyi , M2N4MBFzi , M2N4MBxi , M2N4MByi , M2N4MBzi , M2N4STAxi , M2N4STAyi , M2N4STAzi , M2N4STVxi , M2N4STVyi , & + M2N4STVzi , M2N4Vxi , M2N4Vyi , M2N4Vzi , M2N5Axi , M2N5Ayi , M2N5Azi , M2N5DynP , M2N5FAFxi , M2N5FAFyi , & + M2N5FAFzi , M2N5FAGxi , M2N5FAGyi , M2N5FAGzi , M2N5FAMxi , M2N5FAMyi , M2N5FAMzi , M2N5FAxi , M2N5FAyi , M2N5FAzi , & + M2N5FBFxi , M2N5FBFyi , M2N5FBFzi , M2N5FBxi , M2N5FByi , M2N5FBzi , M2N5FDxi , M2N5FDyi , M2N5FDzi , M2N5FIxi , & + M2N5FIyi , M2N5FIzi , M2N5FMGxi , M2N5FMGyi , M2N5FMGzi , M2N5MBFxi , M2N5MBFyi , M2N5MBFzi , M2N5MBxi , M2N5MByi , & + M2N5MBzi , M2N5STAxi , M2N5STAyi , M2N5STAzi , M2N5STVxi , M2N5STVyi , M2N5STVzi , M2N5Vxi , M2N5Vyi , M2N5Vzi , & + M2N6Axi , M2N6Ayi , M2N6Azi , M2N6DynP , M2N6FAFxi , M2N6FAFyi , M2N6FAFzi , M2N6FAGxi , M2N6FAGyi , M2N6FAGzi , & + M2N6FAMxi , M2N6FAMyi , M2N6FAMzi , M2N6FAxi , M2N6FAyi , M2N6FAzi , M2N6FBFxi , M2N6FBFyi , M2N6FBFzi , M2N6FBxi , & + M2N6FByi , M2N6FBzi , M2N6FDxi , M2N6FDyi , M2N6FDzi , M2N6FIxi , M2N6FIyi , M2N6FIzi , M2N6FMGxi , M2N6FMGyi , & + M2N6FMGzi , M2N6MBFxi , M2N6MBFyi , M2N6MBFzi , M2N6MBxi , M2N6MByi , M2N6MBzi , M2N6STAxi , M2N6STAyi , M2N6STAzi , & + M2N6STVxi , M2N6STVyi , M2N6STVzi , M2N6Vxi , M2N6Vyi , M2N6Vzi , M2N7Axi , M2N7Ayi , M2N7Azi , M2N7DynP , & + M2N7FAFxi , M2N7FAFyi , M2N7FAFzi , M2N7FAGxi , M2N7FAGyi , M2N7FAGzi , M2N7FAMxi , M2N7FAMyi , M2N7FAMzi , M2N7FAxi , & + M2N7FAyi , M2N7FAzi , M2N7FBFxi , M2N7FBFyi , M2N7FBFzi , M2N7FBxi , M2N7FByi , M2N7FBzi , M2N7FDxi , M2N7FDyi , & + M2N7FDzi , M2N7FIxi , M2N7FIyi , M2N7FIzi , M2N7FMGxi , M2N7FMGyi , M2N7FMGzi , M2N7MBFxi , M2N7MBFyi , M2N7MBFzi , & + M2N7MBxi , M2N7MByi , M2N7MBzi , M2N7STAxi , M2N7STAyi , M2N7STAzi , M2N7STVxi , M2N7STVyi , M2N7STVzi , M2N7Vxi , & + M2N7Vyi , M2N7Vzi , M2N8Axi , M2N8Ayi , M2N8Azi , M2N8DynP , M2N8FAFxi , M2N8FAFyi , M2N8FAFzi , M2N8FAGxi , & + M2N8FAGyi , M2N8FAGzi , M2N8FAMxi , M2N8FAMyi , M2N8FAMzi , M2N8FAxi , M2N8FAyi , M2N8FAzi , M2N8FBFxi , M2N8FBFyi , & + M2N8FBFzi , M2N8FBxi , M2N8FByi , M2N8FBzi , M2N8FDxi , M2N8FDyi , M2N8FDzi , M2N8FIxi , M2N8FIyi , M2N8FIzi , & + M2N8FMGxi , M2N8FMGyi , M2N8FMGzi , M2N8MBFxi , M2N8MBFyi , M2N8MBFzi , M2N8MBxi , M2N8MByi , M2N8MBzi , M2N8STAxi , & + M2N8STAyi , M2N8STAzi , M2N8STVxi , M2N8STVyi , M2N8STVzi , M2N8Vxi , M2N8Vyi , M2N8Vzi , M2N9Axi , M2N9Ayi , & + M2N9Azi , M2N9DynP , M2N9FAFxi , M2N9FAFyi , M2N9FAFzi , M2N9FAGxi , M2N9FAGyi , M2N9FAGzi , M2N9FAMxi , M2N9FAMyi , & + M2N9FAMzi , M2N9FAxi , M2N9FAyi , M2N9FAzi , M2N9FBFxi , M2N9FBFyi , M2N9FBFzi , M2N9FBxi , M2N9FByi , M2N9FBzi , & + M2N9FDxi , M2N9FDyi , M2N9FDzi , M2N9FIxi , M2N9FIyi , M2N9FIzi , M2N9FMGxi , M2N9FMGyi , M2N9FMGzi , M2N9MBFxi , & + M2N9MBFyi , M2N9MBFzi , M2N9MBxi , M2N9MByi , M2N9MBzi , M2N9STAxi , M2N9STAyi , M2N9STAzi , M2N9STVxi , M2N9STVyi , & + M2N9STVzi , M2N9Vxi , M2N9Vyi , M2N9Vzi , M3N1Axi , M3N1Ayi , M3N1Azi , M3N1DynP , M3N1FAFxi , M3N1FAFyi , & + M3N1FAFzi , M3N1FAGxi , M3N1FAGyi , M3N1FAGzi , M3N1FAMxi , M3N1FAMyi , M3N1FAMzi , M3N1FAxi , M3N1FAyi , M3N1FAzi , & + M3N1FBFxi , M3N1FBFyi , M3N1FBFzi , M3N1FBxi , M3N1FByi , M3N1FBzi , M3N1FDxi , M3N1FDyi , M3N1FDzi , M3N1FIxi , & + M3N1FIyi , M3N1FIzi , M3N1FMGxi , M3N1FMGyi , M3N1FMGzi , M3N1MBFxi , M3N1MBFyi , M3N1MBFzi , M3N1MBxi , M3N1MByi , & + M3N1MBzi , M3N1STAxi , M3N1STAyi , M3N1STAzi , M3N1STVxi , M3N1STVyi , M3N1STVzi , M3N1Vxi , M3N1Vyi , M3N1Vzi , & + M3N2Axi , M3N2Ayi , M3N2Azi , M3N2DynP , M3N2FAFxi , M3N2FAFyi , M3N2FAFzi , M3N2FAGxi , M3N2FAGyi , M3N2FAGzi , & + M3N2FAMxi , M3N2FAMyi , M3N2FAMzi , M3N2FAxi , M3N2FAyi , M3N2FAzi , M3N2FBFxi , M3N2FBFyi , M3N2FBFzi , M3N2FBxi , & + M3N2FByi , M3N2FBzi , M3N2FDxi , M3N2FDyi , M3N2FDzi , M3N2FIxi , M3N2FIyi , M3N2FIzi , M3N2FMGxi , M3N2FMGyi , & + M3N2FMGzi , M3N2MBFxi , M3N2MBFyi , M3N2MBFzi , M3N2MBxi , M3N2MByi , M3N2MBzi , M3N2STAxi , M3N2STAyi , M3N2STAzi , & + M3N2STVxi , M3N2STVyi , M3N2STVzi , M3N2Vxi , M3N2Vyi , M3N2Vzi , M3N3Axi , M3N3Ayi , M3N3Azi , M3N3DynP , & + M3N3FAFxi , M3N3FAFyi , M3N3FAFzi , M3N3FAGxi , M3N3FAGyi , M3N3FAGzi , M3N3FAMxi , M3N3FAMyi , M3N3FAMzi , M3N3FAxi , & + M3N3FAyi , M3N3FAzi , M3N3FBFxi , M3N3FBFyi , M3N3FBFzi , M3N3FBxi , M3N3FByi , M3N3FBzi , M3N3FDxi , M3N3FDyi , & + M3N3FDzi , M3N3FIxi , M3N3FIyi , M3N3FIzi , M3N3FMGxi , M3N3FMGyi , M3N3FMGzi , M3N3MBFxi , M3N3MBFyi , M3N3MBFzi , & + M3N3MBxi , M3N3MByi , M3N3MBzi , M3N3STAxi , M3N3STAyi , M3N3STAzi , M3N3STVxi , M3N3STVyi , M3N3STVzi , M3N3Vxi , & + M3N3Vyi , M3N3Vzi , M3N4Axi , M3N4Ayi , M3N4Azi , M3N4DynP , M3N4FAFxi , M3N4FAFyi , M3N4FAFzi , M3N4FAGxi , & + M3N4FAGyi , M3N4FAGzi , M3N4FAMxi , M3N4FAMyi , M3N4FAMzi , M3N4FAxi , M3N4FAyi , M3N4FAzi , M3N4FBFxi , M3N4FBFyi , & + M3N4FBFzi , M3N4FBxi , M3N4FByi , M3N4FBzi , M3N4FDxi , M3N4FDyi , M3N4FDzi , M3N4FIxi , M3N4FIyi , M3N4FIzi , & + M3N4FMGxi , M3N4FMGyi , M3N4FMGzi , M3N4MBFxi , M3N4MBFyi , M3N4MBFzi , M3N4MBxi , M3N4MByi , M3N4MBzi , M3N4STAxi , & + M3N4STAyi , M3N4STAzi , M3N4STVxi , M3N4STVyi , M3N4STVzi , M3N4Vxi , M3N4Vyi , M3N4Vzi , M3N5Axi , M3N5Ayi , & + M3N5Azi , M3N5DynP , M3N5FAFxi , M3N5FAFyi , M3N5FAFzi , M3N5FAGxi , M3N5FAGyi , M3N5FAGzi , M3N5FAMxi , M3N5FAMyi , & + M3N5FAMzi , M3N5FAxi , M3N5FAyi , M3N5FAzi , M3N5FBFxi , M3N5FBFyi , M3N5FBFzi , M3N5FBxi , M3N5FByi , M3N5FBzi , & + M3N5FDxi , M3N5FDyi , M3N5FDzi , M3N5FIxi , M3N5FIyi , M3N5FIzi , M3N5FMGxi , M3N5FMGyi , M3N5FMGzi , M3N5MBFxi , & + M3N5MBFyi , M3N5MBFzi , M3N5MBxi , M3N5MByi , M3N5MBzi , M3N5STAxi , M3N5STAyi , M3N5STAzi , M3N5STVxi , M3N5STVyi , & + M3N5STVzi , M3N5Vxi , M3N5Vyi , M3N5Vzi , M3N6Axi , M3N6Ayi , M3N6Azi , M3N6DynP , M3N6FAFxi , M3N6FAFyi , & + M3N6FAFzi , M3N6FAGxi , M3N6FAGyi , M3N6FAGzi , M3N6FAMxi , M3N6FAMyi , M3N6FAMzi , M3N6FAxi , M3N6FAyi , M3N6FAzi , & + M3N6FBFxi , M3N6FBFyi , M3N6FBFzi , M3N6FBxi , M3N6FByi , M3N6FBzi , M3N6FDxi , M3N6FDyi , M3N6FDzi , M3N6FIxi , & + M3N6FIyi , M3N6FIzi , M3N6FMGxi , M3N6FMGyi , M3N6FMGzi , M3N6MBFxi , M3N6MBFyi , M3N6MBFzi , M3N6MBxi , M3N6MByi , & + M3N6MBzi , M3N6STAxi , M3N6STAyi , M3N6STAzi , M3N6STVxi , M3N6STVyi , M3N6STVzi , M3N6Vxi , M3N6Vyi , M3N6Vzi , & + M3N7Axi , M3N7Ayi , M3N7Azi , M3N7DynP , M3N7FAFxi , M3N7FAFyi , M3N7FAFzi , M3N7FAGxi , M3N7FAGyi , M3N7FAGzi , & + M3N7FAMxi , M3N7FAMyi , M3N7FAMzi , M3N7FAxi , M3N7FAyi , M3N7FAzi , M3N7FBFxi , M3N7FBFyi , M3N7FBFzi , M3N7FBxi , & + M3N7FByi , M3N7FBzi , M3N7FDxi , M3N7FDyi , M3N7FDzi , M3N7FIxi , M3N7FIyi , M3N7FIzi , M3N7FMGxi , M3N7FMGyi , & + M3N7FMGzi , M3N7MBFxi , M3N7MBFyi , M3N7MBFzi , M3N7MBxi , M3N7MByi , M3N7MBzi , M3N7STAxi , M3N7STAyi , M3N7STAzi , & + M3N7STVxi , M3N7STVyi , M3N7STVzi , M3N7Vxi , M3N7Vyi , M3N7Vzi , M3N8Axi , M3N8Ayi , M3N8Azi , M3N8DynP , & + M3N8FAFxi , M3N8FAFyi , M3N8FAFzi , M3N8FAGxi , M3N8FAGyi , M3N8FAGzi , M3N8FAMxi , M3N8FAMyi , M3N8FAMzi , M3N8FAxi , & + M3N8FAyi , M3N8FAzi , M3N8FBFxi , M3N8FBFyi , M3N8FBFzi , M3N8FBxi , M3N8FByi , M3N8FBzi , M3N8FDxi , M3N8FDyi , & + M3N8FDzi , M3N8FIxi , M3N8FIyi , M3N8FIzi , M3N8FMGxi , M3N8FMGyi , M3N8FMGzi , M3N8MBFxi , M3N8MBFyi , M3N8MBFzi , & + M3N8MBxi , M3N8MByi , M3N8MBzi , M3N8STAxi , M3N8STAyi , M3N8STAzi , M3N8STVxi , M3N8STVyi , M3N8STVzi , M3N8Vxi , & + M3N8Vyi , M3N8Vzi , M3N9Axi , M3N9Ayi , M3N9Azi , M3N9DynP , M3N9FAFxi , M3N9FAFyi , M3N9FAFzi , M3N9FAGxi , & + M3N9FAGyi , M3N9FAGzi , M3N9FAMxi , M3N9FAMyi , M3N9FAMzi , M3N9FAxi , M3N9FAyi , M3N9FAzi , M3N9FBFxi , M3N9FBFyi , & + M3N9FBFzi , M3N9FBxi , M3N9FByi , M3N9FBzi , M3N9FDxi , M3N9FDyi , M3N9FDzi , M3N9FIxi , M3N9FIyi , M3N9FIzi , & + M3N9FMGxi , M3N9FMGyi , M3N9FMGzi , M3N9MBFxi , M3N9MBFyi , M3N9MBFzi , M3N9MBxi , M3N9MByi , M3N9MBzi , M3N9STAxi , & + M3N9STAyi , M3N9STAzi , M3N9STVxi , M3N9STVyi , M3N9STVzi , M3N9Vxi , M3N9Vyi , M3N9Vzi , M4N1Axi , M4N1Ayi , & + M4N1Azi , M4N1DynP , M4N1FAFxi , M4N1FAFyi , M4N1FAFzi , M4N1FAGxi , M4N1FAGyi , M4N1FAGzi , M4N1FAMxi , M4N1FAMyi , & + M4N1FAMzi , M4N1FAxi , M4N1FAyi , M4N1FAzi , M4N1FBFxi , M4N1FBFyi , M4N1FBFzi , M4N1FBxi , M4N1FByi , M4N1FBzi , & + M4N1FDxi , M4N1FDyi , M4N1FDzi , M4N1FIxi , M4N1FIyi , M4N1FIzi , M4N1FMGxi , M4N1FMGyi , M4N1FMGzi , M4N1MBFxi , & + M4N1MBFyi , M4N1MBFzi , M4N1MBxi , M4N1MByi , M4N1MBzi , M4N1STAxi , M4N1STAyi , M4N1STAzi , M4N1STVxi , M4N1STVyi , & + M4N1STVzi , M4N1Vxi , M4N1Vyi , M4N1Vzi , M4N2Axi , M4N2Ayi , M4N2Azi , M4N2DynP , M4N2FAFxi , M4N2FAFyi , & + M4N2FAFzi , M4N2FAGxi , M4N2FAGyi , M4N2FAGzi , M4N2FAMxi , M4N2FAMyi , M4N2FAMzi , M4N2FAxi , M4N2FAyi , M4N2FAzi , & + M4N2FBFxi , M4N2FBFyi , M4N2FBFzi , M4N2FBxi , M4N2FByi , M4N2FBzi , M4N2FDxi , M4N2FDyi , M4N2FDzi , M4N2FIxi , & + M4N2FIyi , M4N2FIzi , M4N2FMGxi , M4N2FMGyi , M4N2FMGzi , M4N2MBFxi , M4N2MBFyi , M4N2MBFzi , M4N2MBxi , M4N2MByi , & + M4N2MBzi , M4N2STAxi , M4N2STAyi , M4N2STAzi , M4N2STVxi , M4N2STVyi , M4N2STVzi , M4N2Vxi , M4N2Vyi , M4N2Vzi , & + M4N3Axi , M4N3Ayi , M4N3Azi , M4N3DynP , M4N3FAFxi , M4N3FAFyi , M4N3FAFzi , M4N3FAGxi , M4N3FAGyi , M4N3FAGzi , & + M4N3FAMxi , M4N3FAMyi , M4N3FAMzi , M4N3FAxi , M4N3FAyi , M4N3FAzi , M4N3FBFxi , M4N3FBFyi , M4N3FBFzi , M4N3FBxi , & + M4N3FByi , M4N3FBzi , M4N3FDxi , M4N3FDyi , M4N3FDzi , M4N3FIxi , M4N3FIyi , M4N3FIzi , M4N3FMGxi , M4N3FMGyi , & + M4N3FMGzi , M4N3MBFxi , M4N3MBFyi , M4N3MBFzi , M4N3MBxi , M4N3MByi , M4N3MBzi , M4N3STAxi , M4N3STAyi , M4N3STAzi , & + M4N3STVxi , M4N3STVyi , M4N3STVzi , M4N3Vxi , M4N3Vyi , M4N3Vzi , M4N4Axi , M4N4Ayi , M4N4Azi , M4N4DynP , & + M4N4FAFxi , M4N4FAFyi , M4N4FAFzi , M4N4FAGxi , M4N4FAGyi , M4N4FAGzi , M4N4FAMxi , M4N4FAMyi , M4N4FAMzi , M4N4FAxi , & + M4N4FAyi , M4N4FAzi , M4N4FBFxi , M4N4FBFyi , M4N4FBFzi , M4N4FBxi , M4N4FByi , M4N4FBzi , M4N4FDxi , M4N4FDyi , & + M4N4FDzi , M4N4FIxi , M4N4FIyi , M4N4FIzi , M4N4FMGxi , M4N4FMGyi , M4N4FMGzi , M4N4MBFxi , M4N4MBFyi , M4N4MBFzi , & + M4N4MBxi , M4N4MByi , M4N4MBzi , M4N4STAxi , M4N4STAyi , M4N4STAzi , M4N4STVxi , M4N4STVyi , M4N4STVzi , M4N4Vxi , & + M4N4Vyi , M4N4Vzi , M4N5Axi , M4N5Ayi , M4N5Azi , M4N5DynP , M4N5FAFxi , M4N5FAFyi , M4N5FAFzi , M4N5FAGxi , & + M4N5FAGyi , M4N5FAGzi , M4N5FAMxi , M4N5FAMyi , M4N5FAMzi , M4N5FAxi , M4N5FAyi , M4N5FAzi , M4N5FBFxi , M4N5FBFyi , & + M4N5FBFzi , M4N5FBxi , M4N5FByi , M4N5FBzi , M4N5FDxi , M4N5FDyi , M4N5FDzi , M4N5FIxi , M4N5FIyi , M4N5FIzi , & + M4N5FMGxi , M4N5FMGyi , M4N5FMGzi , M4N5MBFxi , M4N5MBFyi , M4N5MBFzi , M4N5MBxi , M4N5MByi , M4N5MBzi , M4N5STAxi , & + M4N5STAyi , M4N5STAzi , M4N5STVxi , M4N5STVyi , M4N5STVzi , M4N5Vxi , M4N5Vyi , M4N5Vzi , M4N6Axi , M4N6Ayi , & + M4N6Azi , M4N6DynP , M4N6FAFxi , M4N6FAFyi , M4N6FAFzi , M4N6FAGxi , M4N6FAGyi , M4N6FAGzi , M4N6FAMxi , M4N6FAMyi , & + M4N6FAMzi , M4N6FAxi , M4N6FAyi , M4N6FAzi , M4N6FBFxi , M4N6FBFyi , M4N6FBFzi , M4N6FBxi , M4N6FByi , M4N6FBzi , & + M4N6FDxi , M4N6FDyi , M4N6FDzi , M4N6FIxi , M4N6FIyi , M4N6FIzi , M4N6FMGxi , M4N6FMGyi , M4N6FMGzi , M4N6MBFxi , & + M4N6MBFyi , M4N6MBFzi , M4N6MBxi , M4N6MByi , M4N6MBzi , M4N6STAxi , M4N6STAyi , M4N6STAzi , M4N6STVxi , M4N6STVyi , & + M4N6STVzi , M4N6Vxi , M4N6Vyi , M4N6Vzi , M4N7Axi , M4N7Ayi , M4N7Azi , M4N7DynP , M4N7FAFxi , M4N7FAFyi , & + M4N7FAFzi , M4N7FAGxi , M4N7FAGyi , M4N7FAGzi , M4N7FAMxi , M4N7FAMyi , M4N7FAMzi , M4N7FAxi , M4N7FAyi , M4N7FAzi , & + M4N7FBFxi , M4N7FBFyi , M4N7FBFzi , M4N7FBxi , M4N7FByi , M4N7FBzi , M4N7FDxi , M4N7FDyi , M4N7FDzi , M4N7FIxi , & + M4N7FIyi , M4N7FIzi , M4N7FMGxi , M4N7FMGyi , M4N7FMGzi , M4N7MBFxi , M4N7MBFyi , M4N7MBFzi , M4N7MBxi , M4N7MByi , & + M4N7MBzi , M4N7STAxi , M4N7STAyi , M4N7STAzi , M4N7STVxi , M4N7STVyi , M4N7STVzi , M4N7Vxi , M4N7Vyi , M4N7Vzi , & + M4N8Axi , M4N8Ayi , M4N8Azi , M4N8DynP , M4N8FAFxi , M4N8FAFyi , M4N8FAFzi , M4N8FAGxi , M4N8FAGyi , M4N8FAGzi , & + M4N8FAMxi , M4N8FAMyi , M4N8FAMzi , M4N8FAxi , M4N8FAyi , M4N8FAzi , M4N8FBFxi , M4N8FBFyi , M4N8FBFzi , M4N8FBxi , & + M4N8FByi , M4N8FBzi , M4N8FDxi , M4N8FDyi , M4N8FDzi , M4N8FIxi , M4N8FIyi , M4N8FIzi , M4N8FMGxi , M4N8FMGyi , & + M4N8FMGzi , M4N8MBFxi , M4N8MBFyi , M4N8MBFzi , M4N8MBxi , M4N8MByi , M4N8MBzi , M4N8STAxi , M4N8STAyi , M4N8STAzi , & + M4N8STVxi , M4N8STVyi , M4N8STVzi , M4N8Vxi , M4N8Vyi , M4N8Vzi , M4N9Axi , M4N9Ayi , M4N9Azi , M4N9DynP , & + M4N9FAFxi , M4N9FAFyi , M4N9FAFzi , M4N9FAGxi , M4N9FAGyi , M4N9FAGzi , M4N9FAMxi , M4N9FAMyi , M4N9FAMzi , M4N9FAxi , & + M4N9FAyi , M4N9FAzi , M4N9FBFxi , M4N9FBFyi , M4N9FBFzi , M4N9FBxi , M4N9FByi , M4N9FBzi , M4N9FDxi , M4N9FDyi , & + M4N9FDzi , M4N9FIxi , M4N9FIyi , M4N9FIzi , M4N9FMGxi , M4N9FMGyi , M4N9FMGzi , M4N9MBFxi , M4N9MBFyi , M4N9MBFzi , & + M4N9MBxi , M4N9MByi , M4N9MBzi , M4N9STAxi , M4N9STAyi , M4N9STAzi , M4N9STVxi , M4N9STVyi , M4N9STVzi , M4N9Vxi , & + M4N9Vyi , M4N9Vzi , M5N1Axi , M5N1Ayi , M5N1Azi , M5N1DynP , M5N1FAFxi , M5N1FAFyi , M5N1FAFzi , M5N1FAGxi , & + M5N1FAGyi , M5N1FAGzi , M5N1FAMxi , M5N1FAMyi , M5N1FAMzi , M5N1FAxi , M5N1FAyi , M5N1FAzi , M5N1FBFxi , M5N1FBFyi , & + M5N1FBFzi , M5N1FBxi , M5N1FByi , M5N1FBzi , M5N1FDxi , M5N1FDyi , M5N1FDzi , M5N1FIxi , M5N1FIyi , M5N1FIzi , & + M5N1FMGxi , M5N1FMGyi , M5N1FMGzi , M5N1MBFxi , M5N1MBFyi , M5N1MBFzi , M5N1MBxi , M5N1MByi , M5N1MBzi , M5N1STAxi , & + M5N1STAyi , M5N1STAzi , M5N1STVxi , M5N1STVyi , M5N1STVzi , M5N1Vxi , M5N1Vyi , M5N1Vzi , M5N2Axi , M5N2Ayi , & + M5N2Azi , M5N2DynP , M5N2FAFxi , M5N2FAFyi , M5N2FAFzi , M5N2FAGxi , M5N2FAGyi , M5N2FAGzi , M5N2FAMxi , M5N2FAMyi , & + M5N2FAMzi , M5N2FAxi , M5N2FAyi , M5N2FAzi , M5N2FBFxi , M5N2FBFyi , M5N2FBFzi , M5N2FBxi , M5N2FByi , M5N2FBzi , & + M5N2FDxi , M5N2FDyi , M5N2FDzi , M5N2FIxi , M5N2FIyi , M5N2FIzi , M5N2FMGxi , M5N2FMGyi , M5N2FMGzi , M5N2MBFxi , & + M5N2MBFyi , M5N2MBFzi , M5N2MBxi , M5N2MByi , M5N2MBzi , M5N2STAxi , M5N2STAyi , M5N2STAzi , M5N2STVxi , M5N2STVyi , & + M5N2STVzi , M5N2Vxi , M5N2Vyi , M5N2Vzi , M5N3Axi , M5N3Ayi , M5N3Azi , M5N3DynP , M5N3FAFxi , M5N3FAFyi , & + M5N3FAFzi , M5N3FAGxi , M5N3FAGyi , M5N3FAGzi , M5N3FAMxi , M5N3FAMyi , M5N3FAMzi , M5N3FAxi , M5N3FAyi , M5N3FAzi , & + M5N3FBFxi , M5N3FBFyi , M5N3FBFzi , M5N3FBxi , M5N3FByi , M5N3FBzi , M5N3FDxi , M5N3FDyi , M5N3FDzi , M5N3FIxi , & + M5N3FIyi , M5N3FIzi , M5N3FMGxi , M5N3FMGyi , M5N3FMGzi , M5N3MBFxi , M5N3MBFyi , M5N3MBFzi , M5N3MBxi , M5N3MByi , & + M5N3MBzi , M5N3STAxi , M5N3STAyi , M5N3STAzi , M5N3STVxi , M5N3STVyi , M5N3STVzi , M5N3Vxi , M5N3Vyi , M5N3Vzi , & + M5N4Axi , M5N4Ayi , M5N4Azi , M5N4DynP , M5N4FAFxi , M5N4FAFyi , M5N4FAFzi , M5N4FAGxi , M5N4FAGyi , M5N4FAGzi , & + M5N4FAMxi , M5N4FAMyi , M5N4FAMzi , M5N4FAxi , M5N4FAyi , M5N4FAzi , M5N4FBFxi , M5N4FBFyi , M5N4FBFzi , M5N4FBxi , & + M5N4FByi , M5N4FBzi , M5N4FDxi , M5N4FDyi , M5N4FDzi , M5N4FIxi , M5N4FIyi , M5N4FIzi , M5N4FMGxi , M5N4FMGyi , & + M5N4FMGzi , M5N4MBFxi , M5N4MBFyi , M5N4MBFzi , M5N4MBxi , M5N4MByi , M5N4MBzi , M5N4STAxi , M5N4STAyi , M5N4STAzi , & + M5N4STVxi , M5N4STVyi , M5N4STVzi , M5N4Vxi , M5N4Vyi , M5N4Vzi , M5N5Axi , M5N5Ayi , M5N5Azi , M5N5DynP , & + M5N5FAFxi , M5N5FAFyi , M5N5FAFzi , M5N5FAGxi , M5N5FAGyi , M5N5FAGzi , M5N5FAMxi , M5N5FAMyi , M5N5FAMzi , M5N5FAxi , & + M5N5FAyi , M5N5FAzi , M5N5FBFxi , M5N5FBFyi , M5N5FBFzi , M5N5FBxi , M5N5FByi , M5N5FBzi , M5N5FDxi , M5N5FDyi , & + M5N5FDzi , M5N5FIxi , M5N5FIyi , M5N5FIzi , M5N5FMGxi , M5N5FMGyi , M5N5FMGzi , M5N5MBFxi , M5N5MBFyi , M5N5MBFzi , & + M5N5MBxi , M5N5MByi , M5N5MBzi , M5N5STAxi , M5N5STAyi , M5N5STAzi , M5N5STVxi , M5N5STVyi , M5N5STVzi , M5N5Vxi , & + M5N5Vyi , M5N5Vzi , M5N6Axi , M5N6Ayi , M5N6Azi , M5N6DynP , M5N6FAFxi , M5N6FAFyi , M5N6FAFzi , M5N6FAGxi , & + M5N6FAGyi , M5N6FAGzi , M5N6FAMxi , M5N6FAMyi , M5N6FAMzi , M5N6FAxi , M5N6FAyi , M5N6FAzi , M5N6FBFxi , M5N6FBFyi , & + M5N6FBFzi , M5N6FBxi , M5N6FByi , M5N6FBzi , M5N6FDxi , M5N6FDyi , M5N6FDzi , M5N6FIxi , M5N6FIyi , M5N6FIzi , & + M5N6FMGxi , M5N6FMGyi , M5N6FMGzi , M5N6MBFxi , M5N6MBFyi , M5N6MBFzi , M5N6MBxi , M5N6MByi , M5N6MBzi , M5N6STAxi , & + M5N6STAyi , M5N6STAzi , M5N6STVxi , M5N6STVyi , M5N6STVzi , M5N6Vxi , M5N6Vyi , M5N6Vzi , M5N7Axi , M5N7Ayi , & + M5N7Azi , M5N7DynP , M5N7FAFxi , M5N7FAFyi , M5N7FAFzi , M5N7FAGxi , M5N7FAGyi , M5N7FAGzi , M5N7FAMxi , M5N7FAMyi , & + M5N7FAMzi , M5N7FAxi , M5N7FAyi , M5N7FAzi , M5N7FBFxi , M5N7FBFyi , M5N7FBFzi , M5N7FBxi , M5N7FByi , M5N7FBzi , & + M5N7FDxi , M5N7FDyi , M5N7FDzi , M5N7FIxi , M5N7FIyi , M5N7FIzi , M5N7FMGxi , M5N7FMGyi , M5N7FMGzi , M5N7MBFxi , & + M5N7MBFyi , M5N7MBFzi , M5N7MBxi , M5N7MByi , M5N7MBzi , M5N7STAxi , M5N7STAyi , M5N7STAzi , M5N7STVxi , M5N7STVyi , & + M5N7STVzi , M5N7Vxi , M5N7Vyi , M5N7Vzi , M5N8Axi , M5N8Ayi , M5N8Azi , M5N8DynP , M5N8FAFxi , M5N8FAFyi , & + M5N8FAFzi , M5N8FAGxi , M5N8FAGyi , M5N8FAGzi , M5N8FAMxi , M5N8FAMyi , M5N8FAMzi , M5N8FAxi , M5N8FAyi , M5N8FAzi , & + M5N8FBFxi , M5N8FBFyi , M5N8FBFzi , M5N8FBxi , M5N8FByi , M5N8FBzi , M5N8FDxi , M5N8FDyi , M5N8FDzi , M5N8FIxi , & + M5N8FIyi , M5N8FIzi , M5N8FMGxi , M5N8FMGyi , M5N8FMGzi , M5N8MBFxi , M5N8MBFyi , M5N8MBFzi , M5N8MBxi , M5N8MByi , & + M5N8MBzi , M5N8STAxi , M5N8STAyi , M5N8STAzi , M5N8STVxi , M5N8STVyi , M5N8STVzi , M5N8Vxi , M5N8Vyi , M5N8Vzi , & + M5N9Axi , M5N9Ayi , M5N9Azi , M5N9DynP , M5N9FAFxi , M5N9FAFyi , M5N9FAFzi , M5N9FAGxi , M5N9FAGyi , M5N9FAGzi , & + M5N9FAMxi , M5N9FAMyi , M5N9FAMzi , M5N9FAxi , M5N9FAyi , M5N9FAzi , M5N9FBFxi , M5N9FBFyi , M5N9FBFzi , M5N9FBxi , & + M5N9FByi , M5N9FBzi , M5N9FDxi , M5N9FDyi , M5N9FDzi , M5N9FIxi , M5N9FIyi , M5N9FIzi , M5N9FMGxi , M5N9FMGyi , & + M5N9FMGzi , M5N9MBFxi , M5N9MBFyi , M5N9MBFzi , M5N9MBxi , M5N9MByi , M5N9MBzi , M5N9STAxi , M5N9STAyi , M5N9STAzi , & + M5N9STVxi , M5N9STVyi , M5N9STVzi , M5N9Vxi , M5N9Vyi , M5N9Vzi , M6N1Axi , M6N1Ayi , M6N1Azi , M6N1DynP , & + M6N1FAFxi , M6N1FAFyi , M6N1FAFzi , M6N1FAGxi , M6N1FAGyi , M6N1FAGzi , M6N1FAMxi , M6N1FAMyi , M6N1FAMzi , M6N1FAxi , & + M6N1FAyi , M6N1FAzi , M6N1FBFxi , M6N1FBFyi , M6N1FBFzi , M6N1FBxi , M6N1FByi , M6N1FBzi , M6N1FDxi , M6N1FDyi , & + M6N1FDzi , M6N1FIxi , M6N1FIyi , M6N1FIzi , M6N1FMGxi , M6N1FMGyi , M6N1FMGzi , M6N1MBFxi , M6N1MBFyi , M6N1MBFzi , & + M6N1MBxi , M6N1MByi , M6N1MBzi , M6N1STAxi , M6N1STAyi , M6N1STAzi , M6N1STVxi , M6N1STVyi , M6N1STVzi , M6N1Vxi , & + M6N1Vyi , M6N1Vzi , M6N2Axi , M6N2Ayi , M6N2Azi , M6N2DynP , M6N2FAFxi , M6N2FAFyi , M6N2FAFzi , M6N2FAGxi , & + M6N2FAGyi , M6N2FAGzi , M6N2FAMxi , M6N2FAMyi , M6N2FAMzi , M6N2FAxi , M6N2FAyi , M6N2FAzi , M6N2FBFxi , M6N2FBFyi , & + M6N2FBFzi , M6N2FBxi , M6N2FByi , M6N2FBzi , M6N2FDxi , M6N2FDyi , M6N2FDzi , M6N2FIxi , M6N2FIyi , M6N2FIzi , & + M6N2FMGxi , M6N2FMGyi , M6N2FMGzi , M6N2MBFxi , M6N2MBFyi , M6N2MBFzi , M6N2MBxi , M6N2MByi , M6N2MBzi , M6N2STAxi , & + M6N2STAyi , M6N2STAzi , M6N2STVxi , M6N2STVyi , M6N2STVzi , M6N2Vxi , M6N2Vyi , M6N2Vzi , M6N3Axi , M6N3Ayi , & + M6N3Azi , M6N3DynP , M6N3FAFxi , M6N3FAFyi , M6N3FAFzi , M6N3FAGxi , M6N3FAGyi , M6N3FAGzi , M6N3FAMxi , M6N3FAMyi , & + M6N3FAMzi , M6N3FAxi , M6N3FAyi , M6N3FAzi , M6N3FBFxi , M6N3FBFyi , M6N3FBFzi , M6N3FBxi , M6N3FByi , M6N3FBzi , & + M6N3FDxi , M6N3FDyi , M6N3FDzi , M6N3FIxi , M6N3FIyi , M6N3FIzi , M6N3FMGxi , M6N3FMGyi , M6N3FMGzi , M6N3MBFxi , & + M6N3MBFyi , M6N3MBFzi , M6N3MBxi , M6N3MByi , M6N3MBzi , M6N3STAxi , M6N3STAyi , M6N3STAzi , M6N3STVxi , M6N3STVyi , & + M6N3STVzi , M6N3Vxi , M6N3Vyi , M6N3Vzi , M6N4Axi , M6N4Ayi , M6N4Azi , M6N4DynP , M6N4FAFxi , M6N4FAFyi , & + M6N4FAFzi , M6N4FAGxi , M6N4FAGyi , M6N4FAGzi , M6N4FAMxi , M6N4FAMyi , M6N4FAMzi , M6N4FAxi , M6N4FAyi , M6N4FAzi , & + M6N4FBFxi , M6N4FBFyi , M6N4FBFzi , M6N4FBxi , M6N4FByi , M6N4FBzi , M6N4FDxi , M6N4FDyi , M6N4FDzi , M6N4FIxi , & + M6N4FIyi , M6N4FIzi , M6N4FMGxi , M6N4FMGyi , M6N4FMGzi , M6N4MBFxi , M6N4MBFyi , M6N4MBFzi , M6N4MBxi , M6N4MByi , & + M6N4MBzi , M6N4STAxi , M6N4STAyi , M6N4STAzi , M6N4STVxi , M6N4STVyi , M6N4STVzi , M6N4Vxi , M6N4Vyi , M6N4Vzi , & + M6N5Axi , M6N5Ayi , M6N5Azi , M6N5DynP , M6N5FAFxi , M6N5FAFyi , M6N5FAFzi , M6N5FAGxi , M6N5FAGyi , M6N5FAGzi , & + M6N5FAMxi , M6N5FAMyi , M6N5FAMzi , M6N5FAxi , M6N5FAyi , M6N5FAzi , M6N5FBFxi , M6N5FBFyi , M6N5FBFzi , M6N5FBxi , & + M6N5FByi , M6N5FBzi , M6N5FDxi , M6N5FDyi , M6N5FDzi , M6N5FIxi , M6N5FIyi , M6N5FIzi , M6N5FMGxi , M6N5FMGyi , & + M6N5FMGzi , M6N5MBFxi , M6N5MBFyi , M6N5MBFzi , M6N5MBxi , M6N5MByi , M6N5MBzi , M6N5STAxi , M6N5STAyi , M6N5STAzi , & + M6N5STVxi , M6N5STVyi , M6N5STVzi , M6N5Vxi , M6N5Vyi , M6N5Vzi , M6N6Axi , M6N6Ayi , M6N6Azi , M6N6DynP , & + M6N6FAFxi , M6N6FAFyi , M6N6FAFzi , M6N6FAGxi , M6N6FAGyi , M6N6FAGzi , M6N6FAMxi , M6N6FAMyi , M6N6FAMzi , M6N6FAxi , & + M6N6FAyi , M6N6FAzi , M6N6FBFxi , M6N6FBFyi , M6N6FBFzi , M6N6FBxi , M6N6FByi , M6N6FBzi , M6N6FDxi , M6N6FDyi , & + M6N6FDzi , M6N6FIxi , M6N6FIyi , M6N6FIzi , M6N6FMGxi , M6N6FMGyi , M6N6FMGzi , M6N6MBFxi , M6N6MBFyi , M6N6MBFzi , & + M6N6MBxi , M6N6MByi , M6N6MBzi , M6N6STAxi , M6N6STAyi , M6N6STAzi , M6N6STVxi , M6N6STVyi , M6N6STVzi , M6N6Vxi , & + M6N6Vyi , M6N6Vzi , M6N7Axi , M6N7Ayi , M6N7Azi , M6N7DynP , M6N7FAFxi , M6N7FAFyi , M6N7FAFzi , M6N7FAGxi , & + M6N7FAGyi , M6N7FAGzi , M6N7FAMxi , M6N7FAMyi , M6N7FAMzi , M6N7FAxi , M6N7FAyi , M6N7FAzi , M6N7FBFxi , M6N7FBFyi , & + M6N7FBFzi , M6N7FBxi , M6N7FByi , M6N7FBzi , M6N7FDxi , M6N7FDyi , M6N7FDzi , M6N7FIxi , M6N7FIyi , M6N7FIzi , & + M6N7FMGxi , M6N7FMGyi , M6N7FMGzi , M6N7MBFxi , M6N7MBFyi , M6N7MBFzi , M6N7MBxi , M6N7MByi , M6N7MBzi , M6N7STAxi , & + M6N7STAyi , M6N7STAzi , M6N7STVxi , M6N7STVyi , M6N7STVzi , M6N7Vxi , M6N7Vyi , M6N7Vzi , M6N8Axi , M6N8Ayi , & + M6N8Azi , M6N8DynP , M6N8FAFxi , M6N8FAFyi , M6N8FAFzi , M6N8FAGxi , M6N8FAGyi , M6N8FAGzi , M6N8FAMxi , M6N8FAMyi , & + M6N8FAMzi , M6N8FAxi , M6N8FAyi , M6N8FAzi , M6N8FBFxi , M6N8FBFyi , M6N8FBFzi , M6N8FBxi , M6N8FByi , M6N8FBzi , & + M6N8FDxi , M6N8FDyi , M6N8FDzi , M6N8FIxi , M6N8FIyi , M6N8FIzi , M6N8FMGxi , M6N8FMGyi , M6N8FMGzi , M6N8MBFxi , & + M6N8MBFyi , M6N8MBFzi , M6N8MBxi , M6N8MByi , M6N8MBzi , M6N8STAxi , M6N8STAyi , M6N8STAzi , M6N8STVxi , M6N8STVyi , & + M6N8STVzi , M6N8Vxi , M6N8Vyi , M6N8Vzi , M6N9Axi , M6N9Ayi , M6N9Azi , M6N9DynP , M6N9FAFxi , M6N9FAFyi , & + M6N9FAFzi , M6N9FAGxi , M6N9FAGyi , M6N9FAGzi , M6N9FAMxi , M6N9FAMyi , M6N9FAMzi , M6N9FAxi , M6N9FAyi , M6N9FAzi , & + M6N9FBFxi , M6N9FBFyi , M6N9FBFzi , M6N9FBxi , M6N9FByi , M6N9FBzi , M6N9FDxi , M6N9FDyi , M6N9FDzi , M6N9FIxi , & + M6N9FIyi , M6N9FIzi , M6N9FMGxi , M6N9FMGyi , M6N9FMGzi , M6N9MBFxi , M6N9MBFyi , M6N9MBFzi , M6N9MBxi , M6N9MByi , & + M6N9MBzi , M6N9STAxi , M6N9STAyi , M6N9STAzi , M6N9STVxi , M6N9STVyi , M6N9STVzi , M6N9Vxi , M6N9Vyi , M6N9Vzi , & + M7N1Axi , M7N1Ayi , M7N1Azi , M7N1DynP , M7N1FAFxi , M7N1FAFyi , M7N1FAFzi , M7N1FAGxi , M7N1FAGyi , M7N1FAGzi , & + M7N1FAMxi , M7N1FAMyi , M7N1FAMzi , M7N1FAxi , M7N1FAyi , M7N1FAzi , M7N1FBFxi , M7N1FBFyi , M7N1FBFzi , M7N1FBxi , & + M7N1FByi , M7N1FBzi , M7N1FDxi , M7N1FDyi , M7N1FDzi , M7N1FIxi , M7N1FIyi , M7N1FIzi , M7N1FMGxi , M7N1FMGyi , & + M7N1FMGzi , M7N1MBFxi , M7N1MBFyi , M7N1MBFzi , M7N1MBxi , M7N1MByi , M7N1MBzi , M7N1STAxi , M7N1STAyi , M7N1STAzi , & + M7N1STVxi , M7N1STVyi , M7N1STVzi , M7N1Vxi , M7N1Vyi , M7N1Vzi , M7N2Axi , M7N2Ayi , M7N2Azi , M7N2DynP , & + M7N2FAFxi , M7N2FAFyi , M7N2FAFzi , M7N2FAGxi , M7N2FAGyi , M7N2FAGzi , M7N2FAMxi , M7N2FAMyi , M7N2FAMzi , M7N2FAxi , & + M7N2FAyi , M7N2FAzi , M7N2FBFxi , M7N2FBFyi , M7N2FBFzi , M7N2FBxi , M7N2FByi , M7N2FBzi , M7N2FDxi , M7N2FDyi , & + M7N2FDzi , M7N2FIxi , M7N2FIyi , M7N2FIzi , M7N2FMGxi , M7N2FMGyi , M7N2FMGzi , M7N2MBFxi , M7N2MBFyi , M7N2MBFzi , & + M7N2MBxi , M7N2MByi , M7N2MBzi , M7N2STAxi , M7N2STAyi , M7N2STAzi , M7N2STVxi , M7N2STVyi , M7N2STVzi , M7N2Vxi , & + M7N2Vyi , M7N2Vzi , M7N3Axi , M7N3Ayi , M7N3Azi , M7N3DynP , M7N3FAFxi , M7N3FAFyi , M7N3FAFzi , M7N3FAGxi , & + M7N3FAGyi , M7N3FAGzi , M7N3FAMxi , M7N3FAMyi , M7N3FAMzi , M7N3FAxi , M7N3FAyi , M7N3FAzi , M7N3FBFxi , M7N3FBFyi , & + M7N3FBFzi , M7N3FBxi , M7N3FByi , M7N3FBzi , M7N3FDxi , M7N3FDyi , M7N3FDzi , M7N3FIxi , M7N3FIyi , M7N3FIzi , & + M7N3FMGxi , M7N3FMGyi , M7N3FMGzi , M7N3MBFxi , M7N3MBFyi , M7N3MBFzi , M7N3MBxi , M7N3MByi , M7N3MBzi , M7N3STAxi , & + M7N3STAyi , M7N3STAzi , M7N3STVxi , M7N3STVyi , M7N3STVzi , M7N3Vxi , M7N3Vyi , M7N3Vzi , M7N4Axi , M7N4Ayi , & + M7N4Azi , M7N4DynP , M7N4FAFxi , M7N4FAFyi , M7N4FAFzi , M7N4FAGxi , M7N4FAGyi , M7N4FAGzi , M7N4FAMxi , M7N4FAMyi , & + M7N4FAMzi , M7N4FAxi , M7N4FAyi , M7N4FAzi , M7N4FBFxi , M7N4FBFyi , M7N4FBFzi , M7N4FBxi , M7N4FByi , M7N4FBzi , & + M7N4FDxi , M7N4FDyi , M7N4FDzi , M7N4FIxi , M7N4FIyi , M7N4FIzi , M7N4FMGxi , M7N4FMGyi , M7N4FMGzi , M7N4MBFxi , & + M7N4MBFyi , M7N4MBFzi , M7N4MBxi , M7N4MByi , M7N4MBzi , M7N4STAxi , M7N4STAyi , M7N4STAzi , M7N4STVxi , M7N4STVyi , & + M7N4STVzi , M7N4Vxi , M7N4Vyi , M7N4Vzi , M7N5Axi , M7N5Ayi , M7N5Azi , M7N5DynP , M7N5FAFxi , M7N5FAFyi , & + M7N5FAFzi , M7N5FAGxi , M7N5FAGyi , M7N5FAGzi , M7N5FAMxi , M7N5FAMyi , M7N5FAMzi , M7N5FAxi , M7N5FAyi , M7N5FAzi , & + M7N5FBFxi , M7N5FBFyi , M7N5FBFzi , M7N5FBxi , M7N5FByi , M7N5FBzi , M7N5FDxi , M7N5FDyi , M7N5FDzi , M7N5FIxi , & + M7N5FIyi , M7N5FIzi , M7N5FMGxi , M7N5FMGyi , M7N5FMGzi , M7N5MBFxi , M7N5MBFyi , M7N5MBFzi , M7N5MBxi , M7N5MByi , & + M7N5MBzi , M7N5STAxi , M7N5STAyi , M7N5STAzi , M7N5STVxi , M7N5STVyi , M7N5STVzi , M7N5Vxi , M7N5Vyi , M7N5Vzi , & + M7N6Axi , M7N6Ayi , M7N6Azi , M7N6DynP , M7N6FAFxi , M7N6FAFyi , M7N6FAFzi , M7N6FAGxi , M7N6FAGyi , M7N6FAGzi , & + M7N6FAMxi , M7N6FAMyi , M7N6FAMzi , M7N6FAxi , M7N6FAyi , M7N6FAzi , M7N6FBFxi , M7N6FBFyi , M7N6FBFzi , M7N6FBxi , & + M7N6FByi , M7N6FBzi , M7N6FDxi , M7N6FDyi , M7N6FDzi , M7N6FIxi , M7N6FIyi , M7N6FIzi , M7N6FMGxi , M7N6FMGyi , & + M7N6FMGzi , M7N6MBFxi , M7N6MBFyi , M7N6MBFzi , M7N6MBxi , M7N6MByi , M7N6MBzi , M7N6STAxi , M7N6STAyi , M7N6STAzi , & + M7N6STVxi , M7N6STVyi , M7N6STVzi , M7N6Vxi , M7N6Vyi , M7N6Vzi , M7N7Axi , M7N7Ayi , M7N7Azi , M7N7DynP , & + M7N7FAFxi , M7N7FAFyi , M7N7FAFzi , M7N7FAGxi , M7N7FAGyi , M7N7FAGzi , M7N7FAMxi , M7N7FAMyi , M7N7FAMzi , M7N7FAxi , & + M7N7FAyi , M7N7FAzi , M7N7FBFxi , M7N7FBFyi , M7N7FBFzi , M7N7FBxi , M7N7FByi , M7N7FBzi , M7N7FDxi , M7N7FDyi , & + M7N7FDzi , M7N7FIxi , M7N7FIyi , M7N7FIzi , M7N7FMGxi , M7N7FMGyi , M7N7FMGzi , M7N7MBFxi , M7N7MBFyi , M7N7MBFzi , & + M7N7MBxi , M7N7MByi , M7N7MBzi , M7N7STAxi , M7N7STAyi , M7N7STAzi , M7N7STVxi , M7N7STVyi , M7N7STVzi , M7N7Vxi , & + M7N7Vyi , M7N7Vzi , M7N8Axi , M7N8Ayi , M7N8Azi , M7N8DynP , M7N8FAFxi , M7N8FAFyi , M7N8FAFzi , M7N8FAGxi , & + M7N8FAGyi , M7N8FAGzi , M7N8FAMxi , M7N8FAMyi , M7N8FAMzi , M7N8FAxi , M7N8FAyi , M7N8FAzi , M7N8FBFxi , M7N8FBFyi , & + M7N8FBFzi , M7N8FBxi , M7N8FByi , M7N8FBzi , M7N8FDxi , M7N8FDyi , M7N8FDzi , M7N8FIxi , M7N8FIyi , M7N8FIzi , & + M7N8FMGxi , M7N8FMGyi , M7N8FMGzi , M7N8MBFxi , M7N8MBFyi , M7N8MBFzi , M7N8MBxi , M7N8MByi , M7N8MBzi , M7N8STAxi , & + M7N8STAyi , M7N8STAzi , M7N8STVxi , M7N8STVyi , M7N8STVzi , M7N8Vxi , M7N8Vyi , M7N8Vzi , M7N9Axi , M7N9Ayi , & + M7N9Azi , M7N9DynP , M7N9FAFxi , M7N9FAFyi , M7N9FAFzi , M7N9FAGxi , M7N9FAGyi , M7N9FAGzi , M7N9FAMxi , M7N9FAMyi , & + M7N9FAMzi , M7N9FAxi , M7N9FAyi , M7N9FAzi , M7N9FBFxi , M7N9FBFyi , M7N9FBFzi , M7N9FBxi , M7N9FByi , M7N9FBzi , & + M7N9FDxi , M7N9FDyi , M7N9FDzi , M7N9FIxi , M7N9FIyi , M7N9FIzi , M7N9FMGxi , M7N9FMGyi , M7N9FMGzi , M7N9MBFxi , & + M7N9MBFyi , M7N9MBFzi , M7N9MBxi , M7N9MByi , M7N9MBzi , M7N9STAxi , M7N9STAyi , M7N9STAzi , M7N9STVxi , M7N9STVyi , & + M7N9STVzi , M7N9Vxi , M7N9Vyi , M7N9Vzi , M8N1Axi , M8N1Ayi , M8N1Azi , M8N1DynP , M8N1FAFxi , M8N1FAFyi , & + M8N1FAFzi , M8N1FAGxi , M8N1FAGyi , M8N1FAGzi , M8N1FAMxi , M8N1FAMyi , M8N1FAMzi , M8N1FAxi , M8N1FAyi , M8N1FAzi , & + M8N1FBFxi , M8N1FBFyi , M8N1FBFzi , M8N1FBxi , M8N1FByi , M8N1FBzi , M8N1FDxi , M8N1FDyi , M8N1FDzi , M8N1FIxi , & + M8N1FIyi , M8N1FIzi , M8N1FMGxi , M8N1FMGyi , M8N1FMGzi , M8N1MBFxi , M8N1MBFyi , M8N1MBFzi , M8N1MBxi , M8N1MByi , & + M8N1MBzi , M8N1STAxi , M8N1STAyi , M8N1STAzi , M8N1STVxi , M8N1STVyi , M8N1STVzi , M8N1Vxi , M8N1Vyi , M8N1Vzi , & + M8N2Axi , M8N2Ayi , M8N2Azi , M8N2DynP , M8N2FAFxi , M8N2FAFyi , M8N2FAFzi , M8N2FAGxi , M8N2FAGyi , M8N2FAGzi , & + M8N2FAMxi , M8N2FAMyi , M8N2FAMzi , M8N2FAxi , M8N2FAyi , M8N2FAzi , M8N2FBFxi , M8N2FBFyi , M8N2FBFzi , M8N2FBxi , & + M8N2FByi , M8N2FBzi , M8N2FDxi , M8N2FDyi , M8N2FDzi , M8N2FIxi , M8N2FIyi , M8N2FIzi , M8N2FMGxi , M8N2FMGyi , & + M8N2FMGzi , M8N2MBFxi , M8N2MBFyi , M8N2MBFzi , M8N2MBxi , M8N2MByi , M8N2MBzi , M8N2STAxi , M8N2STAyi , M8N2STAzi , & + M8N2STVxi , M8N2STVyi , M8N2STVzi , M8N2Vxi , M8N2Vyi , M8N2Vzi , M8N3Axi , M8N3Ayi , M8N3Azi , M8N3DynP , & + M8N3FAFxi , M8N3FAFyi , M8N3FAFzi , M8N3FAGxi , M8N3FAGyi , M8N3FAGzi , M8N3FAMxi , M8N3FAMyi , M8N3FAMzi , M8N3FAxi , & + M8N3FAyi , M8N3FAzi , M8N3FBFxi , M8N3FBFyi , M8N3FBFzi , M8N3FBxi , M8N3FByi , M8N3FBzi , M8N3FDxi , M8N3FDyi , & + M8N3FDzi , M8N3FIxi , M8N3FIyi , M8N3FIzi , M8N3FMGxi , M8N3FMGyi , M8N3FMGzi , M8N3MBFxi , M8N3MBFyi , M8N3MBFzi , & + M8N3MBxi , M8N3MByi , M8N3MBzi , M8N3STAxi , M8N3STAyi , M8N3STAzi , M8N3STVxi , M8N3STVyi , M8N3STVzi , M8N3Vxi , & + M8N3Vyi , M8N3Vzi , M8N4Axi , M8N4Ayi , M8N4Azi , M8N4DynP , M8N4FAFxi , M8N4FAFyi , M8N4FAFzi , M8N4FAGxi , & + M8N4FAGyi , M8N4FAGzi , M8N4FAMxi , M8N4FAMyi , M8N4FAMzi , M8N4FAxi , M8N4FAyi , M8N4FAzi , M8N4FBFxi , M8N4FBFyi , & + M8N4FBFzi , M8N4FBxi , M8N4FByi , M8N4FBzi , M8N4FDxi , M8N4FDyi , M8N4FDzi , M8N4FIxi , M8N4FIyi , M8N4FIzi , & + M8N4FMGxi , M8N4FMGyi , M8N4FMGzi , M8N4MBFxi , M8N4MBFyi , M8N4MBFzi , M8N4MBxi , M8N4MByi , M8N4MBzi , M8N4STAxi , & + M8N4STAyi , M8N4STAzi , M8N4STVxi , M8N4STVyi , M8N4STVzi , M8N4Vxi , M8N4Vyi , M8N4Vzi , M8N5Axi , M8N5Ayi , & + M8N5Azi , M8N5DynP , M8N5FAFxi , M8N5FAFyi , M8N5FAFzi , M8N5FAGxi , M8N5FAGyi , M8N5FAGzi , M8N5FAMxi , M8N5FAMyi , & + M8N5FAMzi , M8N5FAxi , M8N5FAyi , M8N5FAzi , M8N5FBFxi , M8N5FBFyi , M8N5FBFzi , M8N5FBxi , M8N5FByi , M8N5FBzi , & + M8N5FDxi , M8N5FDyi , M8N5FDzi , M8N5FIxi , M8N5FIyi , M8N5FIzi , M8N5FMGxi , M8N5FMGyi , M8N5FMGzi , M8N5MBFxi , & + M8N5MBFyi , M8N5MBFzi , M8N5MBxi , M8N5MByi , M8N5MBzi , M8N5STAxi , M8N5STAyi , M8N5STAzi , M8N5STVxi , M8N5STVyi , & + M8N5STVzi , M8N5Vxi , M8N5Vyi , M8N5Vzi , M8N6Axi , M8N6Ayi , M8N6Azi , M8N6DynP , M8N6FAFxi , M8N6FAFyi , & + M8N6FAFzi , M8N6FAGxi , M8N6FAGyi , M8N6FAGzi , M8N6FAMxi , M8N6FAMyi , M8N6FAMzi , M8N6FAxi , M8N6FAyi , M8N6FAzi , & + M8N6FBFxi , M8N6FBFyi , M8N6FBFzi , M8N6FBxi , M8N6FByi , M8N6FBzi , M8N6FDxi , M8N6FDyi , M8N6FDzi , M8N6FIxi , & + M8N6FIyi , M8N6FIzi , M8N6FMGxi , M8N6FMGyi , M8N6FMGzi , M8N6MBFxi , M8N6MBFyi , M8N6MBFzi , M8N6MBxi , M8N6MByi , & + M8N6MBzi , M8N6STAxi , M8N6STAyi , M8N6STAzi , M8N6STVxi , M8N6STVyi , M8N6STVzi , M8N6Vxi , M8N6Vyi , M8N6Vzi , & + M8N7Axi , M8N7Ayi , M8N7Azi , M8N7DynP , M8N7FAFxi , M8N7FAFyi , M8N7FAFzi , M8N7FAGxi , M8N7FAGyi , M8N7FAGzi , & + M8N7FAMxi , M8N7FAMyi , M8N7FAMzi , M8N7FAxi , M8N7FAyi , M8N7FAzi , M8N7FBFxi , M8N7FBFyi , M8N7FBFzi , M8N7FBxi , & + M8N7FByi , M8N7FBzi , M8N7FDxi , M8N7FDyi , M8N7FDzi , M8N7FIxi , M8N7FIyi , M8N7FIzi , M8N7FMGxi , M8N7FMGyi , & + M8N7FMGzi , M8N7MBFxi , M8N7MBFyi , M8N7MBFzi , M8N7MBxi , M8N7MByi , M8N7MBzi , M8N7STAxi , M8N7STAyi , M8N7STAzi , & + M8N7STVxi , M8N7STVyi , M8N7STVzi , M8N7Vxi , M8N7Vyi , M8N7Vzi , M8N8Axi , M8N8Ayi , M8N8Azi , M8N8DynP , & + M8N8FAFxi , M8N8FAFyi , M8N8FAFzi , M8N8FAGxi , M8N8FAGyi , M8N8FAGzi , M8N8FAMxi , M8N8FAMyi , M8N8FAMzi , M8N8FAxi , & + M8N8FAyi , M8N8FAzi , M8N8FBFxi , M8N8FBFyi , M8N8FBFzi , M8N8FBxi , M8N8FByi , M8N8FBzi , M8N8FDxi , M8N8FDyi , & + M8N8FDzi , M8N8FIxi , M8N8FIyi , M8N8FIzi , M8N8FMGxi , M8N8FMGyi , M8N8FMGzi , M8N8MBFxi , M8N8MBFyi , M8N8MBFzi , & + M8N8MBxi , M8N8MByi , M8N8MBzi , M8N8STAxi , M8N8STAyi , M8N8STAzi , M8N8STVxi , M8N8STVyi , M8N8STVzi , M8N8Vxi , & + M8N8Vyi , M8N8Vzi , M8N9Axi , M8N9Ayi , M8N9Azi , M8N9DynP , M8N9FAFxi , M8N9FAFyi , M8N9FAFzi , M8N9FAGxi , & + M8N9FAGyi , M8N9FAGzi , M8N9FAMxi , M8N9FAMyi , M8N9FAMzi , M8N9FAxi , M8N9FAyi , M8N9FAzi , M8N9FBFxi , M8N9FBFyi , & + M8N9FBFzi , M8N9FBxi , M8N9FByi , M8N9FBzi , M8N9FDxi , M8N9FDyi , M8N9FDzi , M8N9FIxi , M8N9FIyi , M8N9FIzi , & + M8N9FMGxi , M8N9FMGyi , M8N9FMGzi , M8N9MBFxi , M8N9MBFyi , M8N9MBFzi , M8N9MBxi , M8N9MByi , M8N9MBzi , M8N9STAxi , & + M8N9STAyi , M8N9STAzi , M8N9STVxi , M8N9STVyi , M8N9STVzi , M8N9Vxi , M8N9Vyi , M8N9Vzi , M9N1Axi , M9N1Ayi , & + M9N1Azi , M9N1DynP , M9N1FAFxi , M9N1FAFyi , M9N1FAFzi , M9N1FAGxi , M9N1FAGyi , M9N1FAGzi , M9N1FAMxi , M9N1FAMyi , & + M9N1FAMzi , M9N1FAxi , M9N1FAyi , M9N1FAzi , M9N1FBFxi , M9N1FBFyi , M9N1FBFzi , M9N1FBxi , M9N1FByi , M9N1FBzi , & + M9N1FDxi , M9N1FDyi , M9N1FDzi , M9N1FIxi , M9N1FIyi , M9N1FIzi , M9N1FMGxi , M9N1FMGyi , M9N1FMGzi , M9N1MBFxi , & + M9N1MBFyi , M9N1MBFzi , M9N1MBxi , M9N1MByi , M9N1MBzi , M9N1STAxi , M9N1STAyi , M9N1STAzi , M9N1STVxi , M9N1STVyi , & + M9N1STVzi , M9N1Vxi , M9N1Vyi , M9N1Vzi , M9N2Axi , M9N2Ayi , M9N2Azi , M9N2DynP , M9N2FAFxi , M9N2FAFyi , & + M9N2FAFzi , M9N2FAGxi , M9N2FAGyi , M9N2FAGzi , M9N2FAMxi , M9N2FAMyi , M9N2FAMzi , M9N2FAxi , M9N2FAyi , M9N2FAzi , & + M9N2FBFxi , M9N2FBFyi , M9N2FBFzi , M9N2FBxi , M9N2FByi , M9N2FBzi , M9N2FDxi , M9N2FDyi , M9N2FDzi , M9N2FIxi , & + M9N2FIyi , M9N2FIzi , M9N2FMGxi , M9N2FMGyi , M9N2FMGzi , M9N2MBFxi , M9N2MBFyi , M9N2MBFzi , M9N2MBxi , M9N2MByi , & + M9N2MBzi , M9N2STAxi , M9N2STAyi , M9N2STAzi , M9N2STVxi , M9N2STVyi , M9N2STVzi , M9N2Vxi , M9N2Vyi , M9N2Vzi , & + M9N3Axi , M9N3Ayi , M9N3Azi , M9N3DynP , M9N3FAFxi , M9N3FAFyi , M9N3FAFzi , M9N3FAGxi , M9N3FAGyi , M9N3FAGzi , & + M9N3FAMxi , M9N3FAMyi , M9N3FAMzi , M9N3FAxi , M9N3FAyi , M9N3FAzi , M9N3FBFxi , M9N3FBFyi , M9N3FBFzi , M9N3FBxi , & + M9N3FByi , M9N3FBzi , M9N3FDxi , M9N3FDyi , M9N3FDzi , M9N3FIxi , M9N3FIyi , M9N3FIzi , M9N3FMGxi , M9N3FMGyi , & + M9N3FMGzi , M9N3MBFxi , M9N3MBFyi , M9N3MBFzi , M9N3MBxi , M9N3MByi , M9N3MBzi , M9N3STAxi , M9N3STAyi , M9N3STAzi , & + M9N3STVxi , M9N3STVyi , M9N3STVzi , M9N3Vxi , M9N3Vyi , M9N3Vzi , M9N4Axi , M9N4Ayi , M9N4Azi , M9N4DynP , & + M9N4FAFxi , M9N4FAFyi , M9N4FAFzi , M9N4FAGxi , M9N4FAGyi , M9N4FAGzi , M9N4FAMxi , M9N4FAMyi , M9N4FAMzi , M9N4FAxi , & + M9N4FAyi , M9N4FAzi , M9N4FBFxi , M9N4FBFyi , M9N4FBFzi , M9N4FBxi , M9N4FByi , M9N4FBzi , M9N4FDxi , M9N4FDyi , & + M9N4FDzi , M9N4FIxi , M9N4FIyi , M9N4FIzi , M9N4FMGxi , M9N4FMGyi , M9N4FMGzi , M9N4MBFxi , M9N4MBFyi , M9N4MBFzi , & + M9N4MBxi , M9N4MByi , M9N4MBzi , M9N4STAxi , M9N4STAyi , M9N4STAzi , M9N4STVxi , M9N4STVyi , M9N4STVzi , M9N4Vxi , & + M9N4Vyi , M9N4Vzi , M9N5Axi , M9N5Ayi , M9N5Azi , M9N5DynP , M9N5FAFxi , M9N5FAFyi , M9N5FAFzi , M9N5FAGxi , & + M9N5FAGyi , M9N5FAGzi , M9N5FAMxi , M9N5FAMyi , M9N5FAMzi , M9N5FAxi , M9N5FAyi , M9N5FAzi , M9N5FBFxi , M9N5FBFyi , & + M9N5FBFzi , M9N5FBxi , M9N5FByi , M9N5FBzi , M9N5FDxi , M9N5FDyi , M9N5FDzi , M9N5FIxi , M9N5FIyi , M9N5FIzi , & + M9N5FMGxi , M9N5FMGyi , M9N5FMGzi , M9N5MBFxi , M9N5MBFyi , M9N5MBFzi , M9N5MBxi , M9N5MByi , M9N5MBzi , M9N5STAxi , & + M9N5STAyi , M9N5STAzi , M9N5STVxi , M9N5STVyi , M9N5STVzi , M9N5Vxi , M9N5Vyi , M9N5Vzi , M9N6Axi , M9N6Ayi , & + M9N6Azi , M9N6DynP , M9N6FAFxi , M9N6FAFyi , M9N6FAFzi , M9N6FAGxi , M9N6FAGyi , M9N6FAGzi , M9N6FAMxi , M9N6FAMyi , & + M9N6FAMzi , M9N6FAxi , M9N6FAyi , M9N6FAzi , M9N6FBFxi , M9N6FBFyi , M9N6FBFzi , M9N6FBxi , M9N6FByi , M9N6FBzi , & + M9N6FDxi , M9N6FDyi , M9N6FDzi , M9N6FIxi , M9N6FIyi , M9N6FIzi , M9N6FMGxi , M9N6FMGyi , M9N6FMGzi , M9N6MBFxi , & + M9N6MBFyi , M9N6MBFzi , M9N6MBxi , M9N6MByi , M9N6MBzi , M9N6STAxi , M9N6STAyi , M9N6STAzi , M9N6STVxi , M9N6STVyi , & + M9N6STVzi , M9N6Vxi , M9N6Vyi , M9N6Vzi , M9N7Axi , M9N7Ayi , M9N7Azi , M9N7DynP , M9N7FAFxi , M9N7FAFyi , & + M9N7FAFzi , M9N7FAGxi , M9N7FAGyi , M9N7FAGzi , M9N7FAMxi , M9N7FAMyi , M9N7FAMzi , M9N7FAxi , M9N7FAyi , M9N7FAzi , & + M9N7FBFxi , M9N7FBFyi , M9N7FBFzi , M9N7FBxi , M9N7FByi , M9N7FBzi , M9N7FDxi , M9N7FDyi , M9N7FDzi , M9N7FIxi , & + M9N7FIyi , M9N7FIzi , M9N7FMGxi , M9N7FMGyi , M9N7FMGzi , M9N7MBFxi , M9N7MBFyi , M9N7MBFzi , M9N7MBxi , M9N7MByi , & + M9N7MBzi , M9N7STAxi , M9N7STAyi , M9N7STAzi , M9N7STVxi , M9N7STVyi , M9N7STVzi , M9N7Vxi , M9N7Vyi , M9N7Vzi , & + M9N8Axi , M9N8Ayi , M9N8Azi , M9N8DynP , M9N8FAFxi , M9N8FAFyi , M9N8FAFzi , M9N8FAGxi , M9N8FAGyi , M9N8FAGzi , & + M9N8FAMxi , M9N8FAMyi , M9N8FAMzi , M9N8FAxi , M9N8FAyi , M9N8FAzi , M9N8FBFxi , M9N8FBFyi , M9N8FBFzi , M9N8FBxi , & + M9N8FByi , M9N8FBzi , M9N8FDxi , M9N8FDyi , M9N8FDzi , M9N8FIxi , M9N8FIyi , M9N8FIzi , M9N8FMGxi , M9N8FMGyi , & + M9N8FMGzi , M9N8MBFxi , M9N8MBFyi , M9N8MBFzi , M9N8MBxi , M9N8MByi , M9N8MBzi , M9N8STAxi , M9N8STAyi , M9N8STAzi , & + M9N8STVxi , M9N8STVyi , M9N8STVzi , M9N8Vxi , M9N8Vyi , M9N8Vzi , M9N9Axi , M9N9Ayi , M9N9Azi , M9N9DynP , & + M9N9FAFxi , M9N9FAFyi , M9N9FAFzi , M9N9FAGxi , M9N9FAGyi , M9N9FAGzi , M9N9FAMxi , M9N9FAMyi , M9N9FAMzi , M9N9FAxi , & + M9N9FAyi , M9N9FAzi , M9N9FBFxi , M9N9FBFyi , M9N9FBFzi , M9N9FBxi , M9N9FByi , M9N9FBzi , M9N9FDxi , M9N9FDyi , & + M9N9FDzi , M9N9FIxi , M9N9FIyi , M9N9FIzi , M9N9FMGxi , M9N9FMGyi , M9N9FMGzi , M9N9MBFxi , M9N9MBFyi , M9N9MBFzi , & + M9N9MBxi , M9N9MByi , M9N9MBzi , M9N9STAxi , M9N9STAyi , M9N9STAzi , M9N9STVxi , M9N9STVyi , M9N9STVzi , M9N9Vxi , & + M9N9Vyi , M9N9Vzi /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(4032) = (/ & ! This lists the units corresponding to the allowed parameters + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) "/) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: MrsnOut_MapOutputs + PUBLIC :: MrsnOut_OpenOutput + PUBLIC :: MrsnOut_CloseOutput + PUBLIC :: MrsnOut_WriteOutputNames + PUBLIC :: MrsnOut_WriteOutputUnits + PUBLIC :: MrsnOut_WriteOutputs + PUBLIC :: MrsnOut_Init + PUBLIC :: MrsnOut_DestroyParam + PUBLIC :: GetMorisonChannels +CONTAINS + + +!==================================================================================================== +SUBROUTINE SetInvalidOutputs(NMOutputs, MOutLst, NJOutputs, JOutLst, InvalidOutput) +! This subroutine checks the user requested member and joint output lists and sets the unused items to +! invalid. +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NMOutputs + TYPE(Morison_MOutput), INTENT( IN ) :: MOutLst(:) + INTEGER, INTENT( IN ) :: NJOutputs + TYPE(Morison_JOutput), INTENT( IN ) :: JOutLst(:) + LOGICAL, INTENT( INOUT ) :: InvalidOutput(:) + + + +END SUBROUTINE SetInvalidOutputs + +!==================================================================================================== +SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by HydroDyn_CalcOutput() at each time step. +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(Morison_OutputType), INTENT( INOUT ) :: y ! Morison module's output data + TYPE(Morison_ParameterType), INTENT( IN ) :: p ! Morison module's parameter data + TYPE(Morison_InputType), INTENT( IN ) :: u ! Morison module's input data + TYPE(Morison_MiscVarType), INTENT( INOUT ) :: m ! Misc/optimization variables + REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxMrsnOutputs) ! Array of output data for all possible outputs + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I, J + + INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location + REAL(ReKi) :: s ! The linear interpolation factor for the requested location + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Only generate member-based outputs for the number of user-requested member outputs + + IF ( p%NumOuts > 0 ) THEN + DO J=1,p%NMOutputs + DO I=1,p%MOutLst(J)%NOutLoc + + ! These indices are in the DistribMesh index system, not the overall nodes index system, so distribToNodeIndx() mapping needs to be performed if you want to index into the nodes array or wave kinematics arrays + ! But, all of the D_* arrays are already using the DistribMesh index system, so we are OK for those + + m1 = p%MOutLst(J)%Marker1(I) + m2 = p%MOutLst(J)%Marker2(I) + s = p%MOutLst(J)%s (I) + + ! The member output is computed as a linear interpolation of the nearest two markers + + ! wave kinematics along the member + AllOuts(MNVi (:,I,J)) = m%D_FV (: ,m1)*(1-s) + m%D_FV (: ,m2)*s + AllOuts(MNAi (:,I,J)) = m%D_FA (: ,m1)*(1-s) + m%D_FA (: ,m2)*s + AllOuts(MNDynP( I,J)) = m%D_FDynP( m1)*(1-s) + m%D_FDynP( m2)*s + + ! Input motions + AllOuts(MNSTVi(:,I,J)) = u%DistribMesh%TranslationVel(: ,m1)*(1-s) + u%DistribMesh%TranslationVel(: ,m2)*s + ! AllOuts(MNSRVi(:,I,J)) = u%DistribMesh%RotationVel (: ,m1)*(1-s) + u%DistribMesh%RotationVel (: ,m2)*s + AllOuts(MNSTAi(:,I,J)) = u%DistribMesh%TranslationAcc(: ,m1)*(1-s) + u%DistribMesh%TranslationAcc(: ,m2)*s + ! AllOuts(MNSRAi(:,I,J)) = u%DistribMesh%RotationAcc (: ,m1)*(1-s) + u%DistribMesh%RotationAcc (: ,m2)*s + + ! transverse drag force + AllOuts(MNFDi (:,I,J)) = m%D_F_D (: ,m1)*(1-s) + m%D_F_D (: ,m2)*s + ! inertial force + AllOuts(MNFIi (:,I,J)) = m%D_F_I (: ,m1)*(1-s) + m%D_F_I (: ,m2)*s + + ! marine growth weight + AllOuts(MNFMGi(:,I,J)) = p%D_F_MG (1:3,m1)*(1-s) + p%D_F_MG (1:3,m2)*s + + ! buoyancy forces + AllOuts(MNFBi (:,I,J)) = m%D_F_B (1:3,m1)*(1-s) + m%D_F_B (1:3,m2)*s + AllOuts(MNFBFi(:,I,J)) = p%D_F_BF (1:3,m1)*(1-s) + p%D_F_BF (1:3,m2)*s + + ! buoyancy moments + AllOuts(MNMBi (:,I,J)) = m%D_F_B (4:6,m1)*(1-s) + m%D_F_B (4:6,m2)*s + AllOuts(MNMBFi(:,I,J)) = p%D_F_BF (4:6,m1)*(1-s) + p%D_F_BF (4:6,m2)*s + + ! added mass forces + AllOuts(MNFAGi(:,I,J)) = m%D_F_AM_MG(:,m1)*(1-s) + m%D_F_AM_MG(:,m2)*s ! due to marine growth + AllOuts(MNFAMi (:,I,J)) = m%D_F_AM_M(: ,m1)*(1-s) + m%D_F_AM_M(: ,m2)*s ! due to the structural member moving the fluid + AllOuts(MNFAFi (:,I,J)) = m%D_F_AM_F(: ,m1)*(1-s) + m%D_F_AM_F(: ,m2)*s ! due to the ballasted/flooded fluid + AllOuts(MNFAi (:,I,J)) = m%D_F_AM(: ,m1)*(1-s) + m%D_F_AM(: ,m2)*s ! the combined added mass force + + + END DO + END DO + + + ! Only generate joint-based outputs for the number of user-requested joint outputs + + DO I=1,p%NJOutputs + + ! Zero-out the channels because we will be accumulating results + AllOuts(JVi (:,I)) = 0.0 + AllOuts(JAi (:,I)) = 0.0 + AllOuts(JDynP( I)) = 0.0 + AllOuts(JSTVi (:,I)) = 0.0 + AllOuts(JSTAi (:,I)) = 0.0 + AllOuts(JFDi (:,I)) = 0.0 + AllOuts(JFIi (:,I)) = 0.0 + AllOuts(JFBi (:,I)) = 0.0 + AllOuts(JMBi (:,I)) = 0.0 + AllOuts(JFBFi(:,I)) = 0.0 + AllOuts(JMBFi(:,I)) = 0.0 + + AllOuts(JFAMi(:,I)) = 0.0 + + + ! Which of the lumped mesh marker does this Output Joint point to? + DO J=1,p%JOutLst(I)%NumMarkers + m1 = p%JOutlst(I)%Markers(J) + + ! Do not accumulate the wave kinematics and structural kinematics quantities + IF ( J == 1 ) THEN + AllOuts(JVi (:,I)) = m%L_FV (1:3,m1) ! fluid velocity + AllOuts(JAi (:,I)) = m%L_FA (1:3,m1) ! fluid acceleration + AllOuts(JDynP( I)) = m%L_FDynP( m1) ! fluid dynamic pressure + AllOuts(JSTVi (:,I)) = u%LumpedMesh%TranslationVel(: ,m1) ! structural velocity + AllOuts(JSTAi (:,I)) = u%LumpedMesh%TranslationAcc(: ,m1) ! structural acceleration + END IF + + AllOuts(JFDi (:,I)) = AllOuts(JFDi (:,I)) + m%L_F_D (1:3, m1) ! axial drag force + AllOuts(JFBi (:,I)) = AllOuts(JFBi (:,I)) + m%L_F_B (1:3, m1) ! buoyancy force + AllOuts(JMBi (:,I)) = AllOuts(JMBi (:,I)) + m%L_F_B (4:6, m1) ! buoyancy moment + AllOuts(JFBFi(:,I)) = AllOuts(JFBFi(:,I)) + p%L_F_BF(1:3, m1) ! ballasted/filled buoyancy force + AllOuts(JMBFi(:,I)) = AllOuts(JMBFi(:,I)) + p%L_F_BF(4:6, m1) ! ballasted/filled buoyancy moment + AllOuts(JFIi (:,I)) = AllOuts(JFIi(:,I)) + m%L_F_I (1:3, m1) ! inertial force + AllOuts(JFAMi(:,I)) = AllOuts(JFAMi(:,I)) + m%L_F_AM(1:3, m1) ! added mass force + + END DO + END DO + + + END IF +END SUBROUTINE MrsnOut_MapOutputs + +!==================================================================================================== +SUBROUTINE MrsnOut_OpenOutput( ProgName, OutRootName, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + CHARACTER(*), INTENT( IN ) :: ProgName + CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file + TYPE(Morison_ParameterType), INTENT( INOUT ) :: p + TYPE(Morison_InitOutPutType ), INTENT( IN ) :: InitOut ! + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter +! INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array + CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. + CHARACTER(200) :: Frmt ! a string to hold a format statement + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrMsg = "" + + !TODO Finish error handling + + !------------------------------------------------------------------------------------------------- + ! Open the output file, if necessary, and write the header + !------------------------------------------------------------------------------------------------- + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ! Open the file for output + OutFileName = TRIM(OutRootName)//'.MRSN.out' + CALL GetNewUnit( p%UnOutFile ) + + CALL OpenFOutFile ( p%UnOutFile, OutFileName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + + ! Write the output file header + + WRITE (p%UnOutFile,'(/,A/)', IOSTAT=ErrStat) 'These predictions were generated by '//TRIM(ProgName)//& + ' on '//CurDate()//' at '//CurTime()//'.' + + ! Write the names of the output parameters: + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(p%UnOutFile,Frmt) TRIM( 'Time' ), ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) + + + + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return + + + ! Write the units of the output parameters: + + + + WRITE(p%UnOutFile,Frmt) TRIM( 's'), ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) + + + WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return + + + + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE MrsnOut_OpenOutput + +!==================================================================================================== + + +!==================================================================================================== +SUBROUTINE MrsnOut_CloseOutput ( p, ErrStat, ErrMsg ) +! This function cleans up after running the HydroDyn output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the Morison module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + Err = .FALSE. + + !------------------------------------------------------------------------------------------------- + ! Close our output file + !------------------------------------------------------------------------------------------------- + CLOSE( p%UnOutFile, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE MrsnOut_CloseOutput +!==================================================================================================== + + +SUBROUTINE MrsnOut_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(Morison_ParameterType), INTENT( IN ) :: p ! Morison module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) + +END SUBROUTINE MrsnOut_WriteOutputNames + +!==================================================================================================== + + +SUBROUTINE MrsnOut_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(Morison_ParameterType), INTENT( IN ) :: p ! Morison module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) + +END SUBROUTINE MrsnOut_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE MrsnOut_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in MrsnOut_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + TYPE(Morison_OutputType), INTENT( IN ) :: y ! Morison module's output data + TYPE(Morison_ParameterType), INTENT( IN ) :: p ! Morison module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + ! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + + ! Initialize ErrStat and determine if it makes any sense to write output + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN + ErrStat = ErrID_Warn + ErrMsg = ' To write outputs for HydroDyn there must be a valid file ID and OutParam must be allocated.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + ! Write the output parameters to the file + + Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + + WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) + + + RETURN + + +END SUBROUTINE MrsnOut_WriteOutputs + +SUBROUTINE GetNeighboringMarkers(memberIndx, d, numMarkers, nodes, distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) + + INTEGER, INTENT( IN ) :: numMarkers + TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) + INTEGER, INTENT( IN ) :: distribToNodeIndx(:) + INTEGER, INTENT( IN ) :: memberIndx + REAL(ReKi), INTENT( IN ) :: d + INTEGER, INTENT( OUT ) :: m1 + INTEGER, INTENT( OUT ) :: m2 + REAL(ReKi), INTENT( OUT ) :: s + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + INTEGER :: I + REAL(ReKi) :: dLess + REAL(ReKi) :: dGreater + TYPE(Morison_NodeType) :: node + + !TODO: This is not working correctly! Fix it now! + + + ! Find all nodes which have the desired memberIndx and then look for the ones with the smallest neg and pos distance from the target point + + ErrStat = ErrID_None + ErrMsg = '' + dLess = -1000000.0 + dGreater = 1000000.0 + + + DO I=1,numMarkers + node = nodes(distribToNodeIndx(I)) + IF ( node%InpMbrIndx == memberIndx ) THEN + + IF ( node%InpMbrDist >= d ) THEN + IF ( node%InpMbrDist < dGreater ) THEN + dGreater = node%InpMbrDist + m2 = I + END IF + END IF + IF ( node%InpMbrDist <= d ) THEN + IF ( node%InpMbrDist > dLess ) THEN + dLess = node%InpMbrDist + m1 = I + END IF + END IF + END IF + + + END DO + + IF ( EqualRealNos(dGreater - dLess, 0.0_ReKi ) ) THEN + s = 0.0 + ELSE + s = (d - dLess ) / ( dGreater - dLess ) + END IF + +END SUBROUTINE GetNeighboringMarkers + + +!==================================================================================================== +SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(Morison_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module + TYPE(Morison_OutputType), INTENT( INOUT ) :: y ! Morison module's output data + TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! Morison module paramters + TYPE(Morison_InitOutputType ), INTENT( INOUT ) :: InitOut ! Morison module initialization output data + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter + INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array +! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: m1, m2, memberIndx ! marker1, marker2, and member indices + REAL(ReKi) :: s ! interpolation factor +! INTEGER :: count ! node index + + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! Check that the variables in OutList are valid + !------------------------------------------------------------------------------------------------- + +! MrsnOut_Data%NumOuts = HDO_InitData%NumOuts +if (p%NumOuts > 0 ) THEN + CALL MrsnOut_ChkOutLst( InitInp%OutList(1:p%NumOuts), InitInp%ValidOutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN +END IF + ! Set the number of outputs related to the OutAll flag + + IF ( InitInp%OutAll ) THEN + ! p%NumOutAll = InitInp%NMember*2*22 + InitInp%NJoints*19 + p%NumOutAll = 0 + ELSE + p%NumOutAll = 0 + END IF + + !------------------------------------------------------------------------------------------------- + ! Open the output file, if necessary, and write the header + !------------------------------------------------------------------------------------------------- + + IF ( InitInp%OutAll .OR. ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) ) THEN ! Output has been requested so let's open an output file + + ALLOCATE( y%WriteOutput( p%NumOuts + p%NumOutAll ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + y%WriteOutput = 0.0_ReKi + + ! Establish the mapping between a M1N1, M1N2, etc. M2N1, and the distributed mesh + !Verify that we have a member and node mapping for each and every requested output channel + DO I=1,p%NMOutputs + memberIndx = p%MOutLst(I)%MemberIDIndx + DO J=1,p%MOutLst(I)%NOutLoc + ! Need to search mesh for the two markers which surround the requested output location and then store those marker indices and compute the + ! scale factor based on how far they are from the requested output location. + ! Since this is being done on markers and not nodes, the subroutine must be called after the Morison_Init() subroutine is called + CALL GetNeighboringMarkers(memberIndx, p%MOutLst(I)%NodeLocs(J), p%NDistribMarkers, p%Nodes, p%distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) + + ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you + ! want to index into the nodes array or wave kinematics arrays + p%MOutLst(I)%Marker1(J) = m1 + p%MOutLst(I)%Marker2(J) = m2 ! The 2nd marker indx which is used to + p%MOutLst(I)%s(J) = s ! linear interpolation factor + + END DO + + END DO + + + ! We need to map each Output Joint the user requested to the correct marker in the lumped mesh + + DO I=1,p%NJOutputs + + p%JOutlst(I)%NumMarkers = 0 + + DO J=1,p%NLumpedMarkers + IF ( p%Nodes(p%lumpedToNodeIndx(J))%JointIndx == p%JOutlst(I)%JointIDIndx ) THEN + p%JOutlst(I)%NumMarkers = p%JOutlst(I)%NumMarkers + 1 + p%JOutlst(I)%Markers(p%JOutlst(I)%NumMarkers) = J + END IF + END DO + + END DO + + + ! These variables are to help follow the framework template, but the data in them is simply a copy of data + ! already available in the OutParam data structure + + ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts + p%NumOutAll), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts + p%NumOutAll), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + DO I = 1,p%NumOuts + + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + + END DO + + IF ( InitInp%OutAll ) THEN + ! Loop over joints + ! J1FDXi, ... + ! Loop over members + ! M1BEGFDXi, M1ENDFDXi, ... + !InitOut%WriteOutputHdr(p%NOuts+count) + END IF + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE MrsnOut_Init + +!==================================================================================================== +FUNCTION GetMorisonChannels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if they +! below to the list of available Morison channels. + +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + CHARACTER(ChanLen), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. + LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER GetMorisonChannels ! The number of channels found in this module + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. + INTEGER :: count ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. +! LOGICAL :: InvalidOutput(MaxMrsnOutputs) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + LOGICAL :: newFoundMask (NUserOutputs) ! A mask indicating whether a user requested channel belongs to a module's output channels. + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + GetMorisonChannels = 0 + + newFoundMask = .FALSE. + + DO I = 1,NUserOutputs + IF (.NOT. foundMask(I) ) THEN + OutListTmp = UserOutputs(I) + + CheckOutListAgain = .FALSE. + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + newFoundMask(I) = .TRUE. + foundMask(I) = .TRUE. + GetMorisonChannels = GetMorisonChannels + 1 + + !ELSE + ! foundMask(I) = .FALSE. + END IF + END IF +END DO + +IF ( GetMorisonChannels > 0 ) THEN + + count = 1 + ! Test that num channels does not exceed max possible channels due to size of OutList + !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutList array in the GetMorisonChannels function.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,NUserOutputs + IF ( newFoundMask(I) ) THEN + OutList(count) = UserOutputs(I) + count = count + 1 + END IF + + END DO + +END IF + +END FUNCTION GetMorisonChannels + +!==================================================================================================== +SUBROUTINE MrsnOut_ChkOutLst( OutList, ValidOutList, y, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! Note that the Morison module must be initialized prior to calling this function (if it +! is being used) so that it can correctly determine if the Lines outputs are valid. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + LOGICAL, INTENT( IN ) :: ValidOutList (:) ! An array holding the a flag for whether the elements are valid requested output channels. + TYPE(Morison_OutputType), INTENT( INOUT ) :: y ! Morison module output data + TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! Morison module parameter data + + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. +! INTEGER :: J ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + + + LOGICAL :: InvalidOutput(MaxMrsnOutputs) ! This array determines if the output channel is valid for this configuration + + LOGICAL :: CheckOutListAgain + + InvalidOutput = .FALSE. + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutParam array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Check user-requested member and joint outputs and node lists and set InvalidOutput array values as needed + !CALL SetInvalidOutputs(NMOutputs, MOutLst, NJOutputs, JOutLst, InvalidOutput) + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + + CALL WrScr(p%OutParam(I)%Name//' is not an available output channel.') + ErrMsg = ' An output channel was set as INVALID.' + ErrStat = ErrID_Warn + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + IF ( .NOT. ValidOutList(I) ) THEN + ErrMsg = ' An output channel was set as INVALID.' + CALL WrScr(p%OutParam(I)%Name//' is not an available output channel.') + ErrStat = ErrID_Warn + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 + END IF + + END DO + + + + + RETURN +END SUBROUTINE MrsnOut_ChkOutLst + + +!==================================================================================================== +SUBROUTINE MrsnOut_DestroyParam ( p, ErrStat, ErrMsg ) +! This function cleans up after running the HydroDyn output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the Morison module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + Err = .FALSE. + + + + !------------------------------------------------------------------------------------------------- + ! Deallocate arrays + !------------------------------------------------------------------------------------------------- + IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + !------------------------------------------------------------------------------------------------- + ! Reset number of outputs + !------------------------------------------------------------------------------------------------- + p%NumOuts = 0 + + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE MrsnOut_DestroyParam +!==================================================================================================== + + +END MODULE Morison_Output diff --git a/OpenFAST/modules/hydrodyn/src/Morison_Types.f90 b/OpenFAST/modules/hydrodyn/src/Morison_Types.f90 new file mode 100644 index 000000000..5a0989fc0 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Morison_Types.f90 @@ -0,0 +1,11249 @@ +!STARTOFREGISTRYGENERATEDFILE 'Morison_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 +!********************************************************************************************************************************* +! Morison_Types +!................................................................................................................................. +! This file is part of Morison. +! +! 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 Morison. 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 Morison_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxMrsnOutputs = 4032 ! [-] +! ========= Morison_JointType ======= + TYPE, PUBLIC :: Morison_JointType + INTEGER(IntKi) :: JointID !< [-] + REAL(ReKi) , DIMENSION(1:3) :: JointPos !< [-] + INTEGER(IntKi) :: JointAxID !< [-] + INTEGER(IntKi) :: JointAxIDIndx !< [-] + INTEGER(IntKi) :: JointOvrlp !< [-] + INTEGER(IntKi) :: NConnections !< [-] + INTEGER(IntKi) , DIMENSION(1:10) :: ConnectionList !< [-] + END TYPE Morison_JointType +! ======================= +! ========= Morison_MemberPropType ======= + TYPE, PUBLIC :: Morison_MemberPropType + INTEGER(IntKi) :: PropSetID !< [-] + REAL(ReKi) :: PropD !< [-] + REAL(ReKi) :: PropThck !< [-] + END TYPE Morison_MemberPropType +! ======================= +! ========= Morison_FilledGroupType ======= + TYPE, PUBLIC :: Morison_FilledGroupType + INTEGER(IntKi) :: FillNumM !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: FillMList !< [-] + REAL(ReKi) :: FillFSLoc !< [-] + CHARACTER(80) :: FillDensChr !< [-] + REAL(ReKi) :: FillDens !< [-] + END TYPE Morison_FilledGroupType +! ======================= +! ========= Morison_CoefDpths ======= + TYPE, PUBLIC :: Morison_CoefDpths + REAL(ReKi) :: Dpth !< [-] + REAL(ReKi) :: DpthCd !< [-] + REAL(ReKi) :: DpthCdMG !< [-] + REAL(ReKi) :: DpthCa !< [-] + REAL(ReKi) :: DpthCaMG !< [-] + REAL(ReKi) :: DpthCp !< [-] + REAL(ReKi) :: DpthCpMG !< [-] + REAL(ReKi) :: DpthAxCa !< [-] + REAL(ReKi) :: DpthAxCaMG !< [-] + REAL(ReKi) :: DpthAxCp !< [-] + REAL(ReKi) :: DpthAxCpMG !< [-] + END TYPE Morison_CoefDpths +! ======================= +! ========= Morison_AxialCoefType ======= + TYPE, PUBLIC :: Morison_AxialCoefType + INTEGER(IntKi) :: AxCoefID !< [-] + REAL(ReKi) :: AxCd !< [-] + REAL(ReKi) :: AxCa !< [-] + REAL(ReKi) :: AxCp !< [-] + END TYPE Morison_AxialCoefType +! ======================= +! ========= Morison_MemberInputType ======= + TYPE, PUBLIC :: Morison_MemberInputType + INTEGER(IntKi) :: MemberID !< [-] + INTEGER(IntKi) :: MJointID1 !< [-] + INTEGER(IntKi) :: MJointID2 !< [-] + INTEGER(IntKi) :: MJointID1Indx !< [-] + INTEGER(IntKi) :: MJointID2Indx !< [-] + INTEGER(IntKi) :: MPropSetID1 !< [-] + INTEGER(IntKi) :: MPropSetID2 !< [-] + INTEGER(IntKi) :: MPropSetID1Indx !< [-] + INTEGER(IntKi) :: MPropSetID2Indx !< [-] + REAL(ReKi) :: MDivSize !< [-] + INTEGER(IntKi) :: MCoefMod !< [-] + INTEGER(IntKi) :: MmbrCoefIDIndx !< [-] + INTEGER(IntKi) :: MmbrFilledIDIndx !< [-] + LOGICAL :: PropPot !< [-] + INTEGER(IntKi) :: NumSplits !< [-] + REAL(ReKi) , DIMENSION(1:5) :: Splits !< [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< [-] + END TYPE Morison_MemberInputType +! ======================= +! ========= Morison_NodeType ======= + TYPE, PUBLIC :: Morison_NodeType + INTEGER(IntKi) :: NodeType !< [-] + INTEGER(IntKi) :: JointIndx !< [-] + REAL(ReKi) , DIMENSION(1:3) :: JointPos !< [-] + INTEGER(IntKi) :: JointOvrlp !< [-] + INTEGER(IntKi) :: JointAxIDIndx !< [-] + INTEGER(IntKi) :: NConnections !< [-] + INTEGER(IntKi) , DIMENSION(1:10) :: ConnectionList !< [-] + INTEGER(IntKi) :: NConnectPreSplit !< [-] + REAL(ReKi) :: Cd !< [-] + REAL(ReKi) :: CdMG !< [-] + REAL(ReKi) :: Ca !< [-] + REAL(ReKi) :: CaMG !< [-] + REAL(ReKi) :: Cp !< [-] + REAL(ReKi) :: CpMG !< [-] + REAL(ReKi) :: JAxCd !< [-] + REAL(ReKi) :: JAxCa !< [-] + REAL(ReKi) :: JAxCp !< [-] + REAL(ReKi) :: AxCa !< [-] + REAL(ReKi) :: AxCp !< [-] + REAL(ReKi) :: AxCaMG !< [-] + REAL(ReKi) :: AxCpMG !< [-] + REAL(ReKi) :: R !< [-] + REAL(ReKi) :: t !< [-] + REAL(ReKi) :: tMG !< [-] + REAL(ReKi) :: dRdz !< [-] + REAL(ReKi) :: MGdensity !< [-] + REAL(ReKi) :: FillFSLoc !< [-] + LOGICAL :: FillFlag !< [-] + REAL(ReKi) :: FillDensity !< [-] + INTEGER(IntKi) :: InpMbrIndx !< [-] + REAL(ReKi) :: InpMbrDist !< [-] + LOGICAL :: PropPot !< [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< [-] + END TYPE Morison_NodeType +! ======================= +! ========= Morison_MemberType ======= + TYPE, PUBLIC :: Morison_MemberType + INTEGER(IntKi) :: Node1Indx !< [-] + INTEGER(IntKi) :: Node2Indx !< [-] + REAL(ReKi) :: R1 !< [-] + REAL(ReKi) :: t1 !< [-] + REAL(ReKi) :: R2 !< [-] + REAL(ReKi) :: t2 !< [-] + REAL(ReKi) :: Cd1 !< [-] + REAL(ReKi) :: CdMG1 !< [-] + REAL(ReKi) :: Ca1 !< [-] + REAL(ReKi) :: CaMG1 !< [-] + REAL(ReKi) :: Cp1 !< [-] + REAL(ReKi) :: CpMG1 !< [-] + REAL(ReKi) :: AxCa1 !< [-] + REAL(ReKi) :: AxCaMG1 !< [-] + REAL(ReKi) :: AxCp1 !< [-] + REAL(ReKi) :: AxCpMG1 !< [-] + REAL(ReKi) :: Cd2 !< [-] + REAL(ReKi) :: CdMG2 !< [-] + REAL(ReKi) :: Ca2 !< [-] + REAL(ReKi) :: CaMG2 !< [-] + REAL(ReKi) :: Cp2 !< [-] + REAL(ReKi) :: CpMG2 !< [-] + REAL(ReKi) :: AxCa2 !< [-] + REAL(ReKi) :: AxCaMG2 !< [-] + REAL(ReKi) :: AxCp2 !< [-] + REAL(ReKi) :: AxCpMG2 !< [-] + REAL(ReKi) :: InpMbrDist1 !< [-] + REAL(ReKi) :: InpMbrDist2 !< [-] + REAL(ReKi) :: InpMbrLen !< [-] + INTEGER(IntKi) :: InpMbrIndx !< [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< [-] + INTEGER(IntKi) :: NumSplits !< [-] + REAL(ReKi) , DIMENSION(1:5) :: Splits !< [-] + REAL(ReKi) :: MGvolume !< [-] + REAL(ReKi) :: MDivSize !< [-] + INTEGER(IntKi) :: MCoefMod !< [-] + INTEGER(IntKi) :: MmbrCoefIDIndx !< [-] + INTEGER(IntKi) :: MmbrFilledIDIndx !< [-] + REAL(ReKi) :: FillFSLoc !< [-] + REAL(ReKi) :: FillDens !< [-] + REAL(ReKi) , DIMENSION(1:6) :: F_Bouy !< [-] + REAL(ReKi) , DIMENSION(1:6) :: F_DP !< [-] + LOGICAL :: PropPot !< [-] + END TYPE Morison_MemberType +! ======================= +! ========= Morison_CoefMembers ======= + TYPE, PUBLIC :: Morison_CoefMembers + INTEGER(IntKi) :: MemberID !< [-] + REAL(ReKi) :: MemberCd1 !< [-] + REAL(ReKi) :: MemberCd2 !< [-] + REAL(ReKi) :: MemberCdMG1 !< [-] + REAL(ReKi) :: MemberCdMG2 !< [-] + REAL(ReKi) :: MemberCa1 !< [-] + REAL(ReKi) :: MemberCa2 !< [-] + REAL(ReKi) :: MemberCaMG1 !< [-] + REAL(ReKi) :: MemberCaMG2 !< [-] + REAL(ReKi) :: MemberCp1 !< [-] + REAL(ReKi) :: MemberCp2 !< [-] + REAL(ReKi) :: MemberCpMG1 !< [-] + REAL(ReKi) :: MemberCpMG2 !< [-] + REAL(ReKi) :: MemberAxCa1 !< [-] + REAL(ReKi) :: MemberAxCa2 !< [-] + REAL(ReKi) :: MemberAxCaMG1 !< [-] + REAL(ReKi) :: MemberAxCaMG2 !< [-] + REAL(ReKi) :: MemberAxCp1 !< [-] + REAL(ReKi) :: MemberAxCp2 !< [-] + REAL(ReKi) :: MemberAxCpMG1 !< [-] + REAL(ReKi) :: MemberAxCpMG2 !< [-] + END TYPE Morison_CoefMembers +! ======================= +! ========= Morison_MGDepthsType ======= + TYPE, PUBLIC :: Morison_MGDepthsType + REAL(ReKi) :: MGDpth !< [-] + REAL(ReKi) :: MGThck !< [-] + REAL(ReKi) :: MGDens !< [-] + END TYPE Morison_MGDepthsType +! ======================= +! ========= Morison_MOutput ======= + TYPE, PUBLIC :: Morison_MOutput + INTEGER(IntKi) :: MemberID !< [-] + INTEGER(IntKi) :: NOutLoc !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NodeLocs !< [-] + INTEGER(IntKi) :: MemberIDIndx !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Marker1 !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Marker2 !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: s !< [-] + END TYPE Morison_MOutput +! ======================= +! ========= Morison_JOutput ======= + TYPE, PUBLIC :: Morison_JOutput + INTEGER(IntKi) :: JointID !< [-] + INTEGER(IntKi) :: JointIDIndx !< [-] + INTEGER(IntKi) :: NumMarkers !< [-] + INTEGER(IntKi) , DIMENSION(1:10) :: Markers !< [-] + END TYPE Morison_JOutput +! ======================= +! ========= Morison_InitInputType ======= + TYPE, PUBLIC :: Morison_InitInputType + REAL(ReKi) :: Gravity !< [-] + REAL(ReKi) :: WtrDens !< [-] + REAL(ReKi) :: WtrDpth !< [-] + REAL(ReKi) :: MSL2SWL !< [-] + INTEGER(IntKi) :: NJoints !< [-] + INTEGER(IntKi) :: NNodes !< [-] + INTEGER(IntKi) :: TotalPossibleSuperMembers !< [-] + TYPE(Morison_JointType) , DIMENSION(:), ALLOCATABLE :: InpJoints !< [-] + TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< [-] + INTEGER(IntKi) :: NElements !< [-] + TYPE(Morison_MemberType) , DIMENSION(:), ALLOCATABLE :: Elements !< [-] + INTEGER(IntKi) :: NAxCoefs !< [-] + TYPE(Morison_AxialCoefType) , DIMENSION(:), ALLOCATABLE :: AxialCoefs !< [-] + INTEGER(IntKi) :: NPropSets !< [-] + TYPE(Morison_MemberPropType) , DIMENSION(:), ALLOCATABLE :: MPropSets !< [-] + REAL(ReKi) :: SimplCd !< [-] + REAL(ReKi) :: SimplCdMG !< [-] + REAL(ReKi) :: SimplCa !< [-] + REAL(ReKi) :: SimplCaMG !< [-] + REAL(ReKi) :: SimplCp !< [-] + REAL(ReKi) :: SimplCpMG !< [-] + REAL(ReKi) :: SimplAxCa !< [-] + REAL(ReKi) :: SimplAxCaMG !< [-] + REAL(ReKi) :: SimplAxCp !< [-] + REAL(ReKi) :: SimplAxCpMG !< [-] + INTEGER(IntKi) :: NCoefDpth !< [-] + TYPE(Morison_CoefDpths) , DIMENSION(:), ALLOCATABLE :: CoefDpths !< [-] + INTEGER(IntKi) :: NCoefMembers !< [-] + TYPE(Morison_CoefMembers) , DIMENSION(:), ALLOCATABLE :: CoefMembers !< [-] + INTEGER(IntKi) :: NMembers !< [-] + TYPE(Morison_MemberInputType) , DIMENSION(:), ALLOCATABLE :: InpMembers !< [-] + INTEGER(IntKi) :: NFillGroups !< [-] + TYPE(Morison_FilledGroupType) , DIMENSION(:), ALLOCATABLE :: FilledGroups !< [-] + INTEGER(IntKi) :: NMGDepths !< [-] + TYPE(Morison_MGDepthsType) , DIMENSION(:), ALLOCATABLE :: MGDepths !< [-] + REAL(ReKi) :: MGTop !< [-] + REAL(ReKi) :: MGBottom !< [-] + INTEGER(IntKi) :: NMOutputs !< [-] + TYPE(Morison_MOutput) , DIMENSION(:), ALLOCATABLE :: MOutLst !< [-] + INTEGER(IntKi) :: NJOutputs !< [-] + TYPE(Morison_JOutput) , DIMENSION(:), ALLOCATABLE :: JOutLst !< [-] + CHARACTER(ChanLen) , DIMENSION(1:4032) :: OutList !< This list size needs to be the maximum of possible outputs because of the use of ReadAry() [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: ValidOutList !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: OutSwtch !< [-] + LOGICAL :: OutAll !< [-] + CHARACTER(1024) :: OutRootName !< [-] + INTEGER(IntKi) :: UnOutFile !< [-] + INTEGER(IntKi) :: UnSum !< [-] + INTEGER(IntKi) :: NStepWave !< [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP !< [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] + END TYPE Morison_InitInputType +! ======================= +! ========= Morison_InitOutputType ======= + TYPE, PUBLIC :: Morison_InitOutputType + TYPE(MeshType) :: DistribMesh !< [-] + TYPE(MeshType) :: LumpedMesh !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: Morison_Rad !< radius of node (for FAST visualization) [(m)] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + END TYPE Morison_InitOutputType +! ======================= +! ========= Morison_ContinuousStateType ======= + TYPE, PUBLIC :: Morison_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Morison_ContinuousStateType +! ======================= +! ========= Morison_DiscreteStateType ======= + TYPE, PUBLIC :: Morison_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< [-] + END TYPE Morison_DiscreteStateType +! ======================= +! ========= Morison_ConstraintStateType ======= + TYPE, PUBLIC :: Morison_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Morison_ConstraintStateType +! ======================= +! ========= Morison_OtherStateType ======= + TYPE, PUBLIC :: Morison_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE Morison_OtherStateType +! ======================= +! ========= Morison_MiscVarType ======= + TYPE, PUBLIC :: Morison_MiscVarType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_D !< Distributed viscous drag loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_I !< Distributed inertial loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_B !< Distributed bounancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM !< Distributed total added mass loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_M !< Distributed member added mass loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_MG !< Distributed marine growth added mass (weight) loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_F !< Distributed added mass loads due to flooding/filled fluid [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_FV !< Fluid velocity at line element node [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_FA !< Fluid acceleration at line element node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_FDynP !< Fluid dynamic pressure at line element node [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_B !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_D !< Lumped viscous drag loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_I !< Lumped intertia loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_DP !< Lumped dynamic pressure loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_AM !< Lumped added mass loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_FV !< Fluid velocity at point element node [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_FA !< Fluid acceleration at point element node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: L_FDynP !< Fluid dynamic pressure at point element node [-] + INTEGER(IntKi) :: LastIndWave !< Last time index used in the wave kinematics arrays [-] + END TYPE Morison_MiscVarType +! ======================= +! ========= Morison_ParameterType ======= + TYPE, PUBLIC :: Morison_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [(sec)] + REAL(ReKi) :: WtrDens !< [-] + INTEGER(IntKi) :: NNodes !< [-] + TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_I !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_DP !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_dragConst !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_An !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_B !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_F_I !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_F_DP !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_BF !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_AM_M !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: L_dragConst !< [-] + INTEGER(IntKi) :: NDistribMarkers !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: distribToNodeIndx !< [-] + INTEGER(IntKi) :: NLumpedMarkers !< [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: lumpedToNodeIndx !< [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: elementWaterState !< State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2] [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: elementFillState !< State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2] [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_B !< Distributed buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_BF !< Distributed filled buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_MG !< Distributed marine growth loads [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_AM_M !< Distributed member added mass matrix [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_AM_MG !< Distributed marine growth added mass matrix (weight) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_AM_F !< Distributed added mass matrix due to flooding/filled fluid [-] + INTEGER(IntKi) :: NStepWave !< [-] + INTEGER(IntKi) :: NMOutputs !< [-] + TYPE(Morison_MOutput) , DIMENSION(:), ALLOCATABLE :: MOutLst !< [-] + INTEGER(IntKi) :: NJOutputs !< [-] + TYPE(Morison_JOutput) , DIMENSION(:), ALLOCATABLE :: JOutLst !< [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + INTEGER(IntKi) :: OutSwtch !< [-] + INTEGER(IntKi) :: UnOutFile !< [-] + CHARACTER(20) :: OutFmt !< [-] + CHARACTER(20) :: OutSFmt !< [-] + CHARACTER(ChanLen) :: Delim !< [-] + END TYPE Morison_ParameterType +! ======================= +! ========= Morison_InputType ======= + TYPE, PUBLIC :: Morison_InputType + TYPE(MeshType) :: DistribMesh !< Distributed Loads Meshed input data [-] + TYPE(MeshType) :: LumpedMesh !< Lumped Loads Meshed input data [-] + END TYPE Morison_InputType +! ======================= +! ========= Morison_OutputType ======= + TYPE, PUBLIC :: Morison_OutputType + TYPE(MeshType) :: DistribMesh !< Distributed Loads Meshed output data [-] + TYPE(MeshType) :: LumpedMesh !< Lumped Loads Meshed output data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + END TYPE Morison_OutputType +! ======================= +CONTAINS + SUBROUTINE Morison_CopyJointType( SrcJointTypeData, DstJointTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_JointType), INTENT(IN) :: SrcJointTypeData + TYPE(Morison_JointType), INTENT(INOUT) :: DstJointTypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyJointType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstJointTypeData%JointID = SrcJointTypeData%JointID + DstJointTypeData%JointPos = SrcJointTypeData%JointPos + DstJointTypeData%JointAxID = SrcJointTypeData%JointAxID + DstJointTypeData%JointAxIDIndx = SrcJointTypeData%JointAxIDIndx + DstJointTypeData%JointOvrlp = SrcJointTypeData%JointOvrlp + DstJointTypeData%NConnections = SrcJointTypeData%NConnections + DstJointTypeData%ConnectionList = SrcJointTypeData%ConnectionList + END SUBROUTINE Morison_CopyJointType + + SUBROUTINE Morison_DestroyJointType( JointTypeData, ErrStat, ErrMsg ) + TYPE(Morison_JointType), INTENT(INOUT) :: JointTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyJointType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyJointType + + SUBROUTINE Morison_PackJointType( 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(Morison_JointType), 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 = 'Morison_PackJointType' + ! 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 ! JointID + Re_BufSz = Re_BufSz + SIZE(InData%JointPos) ! JointPos + Int_BufSz = Int_BufSz + 1 ! JointAxID + Int_BufSz = Int_BufSz + 1 ! JointAxIDIndx + Int_BufSz = Int_BufSz + 1 ! JointOvrlp + Int_BufSz = Int_BufSz + 1 ! NConnections + Int_BufSz = Int_BufSz + SIZE(InData%ConnectionList) ! ConnectionList + 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%JointID + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%JointPos,1), UBOUND(InData%JointPos,1) + ReKiBuf(Re_Xferred) = InData%JointPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%JointAxID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%JointAxIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%JointOvrlp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NConnections + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%ConnectionList,1), UBOUND(InData%ConnectionList,1) + IntKiBuf(Int_Xferred) = InData%ConnectionList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE Morison_PackJointType + + SUBROUTINE Morison_UnPackJointType( 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(Morison_JointType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackJointType' + ! 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%JointID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%JointPos,1) + i1_u = UBOUND(OutData%JointPos,1) + DO i1 = LBOUND(OutData%JointPos,1), UBOUND(OutData%JointPos,1) + OutData%JointPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%JointAxID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%JointAxIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%JointOvrlp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NConnections = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%ConnectionList,1) + i1_u = UBOUND(OutData%ConnectionList,1) + DO i1 = LBOUND(OutData%ConnectionList,1), UBOUND(OutData%ConnectionList,1) + OutData%ConnectionList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE Morison_UnPackJointType + + SUBROUTINE Morison_CopyMemberPropType( SrcMemberPropTypeData, DstMemberPropTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MemberPropType), INTENT(IN) :: SrcMemberPropTypeData + TYPE(Morison_MemberPropType), INTENT(INOUT) :: DstMemberPropTypeData + 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 = 'Morison_CopyMemberPropType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMemberPropTypeData%PropSetID = SrcMemberPropTypeData%PropSetID + DstMemberPropTypeData%PropD = SrcMemberPropTypeData%PropD + DstMemberPropTypeData%PropThck = SrcMemberPropTypeData%PropThck + END SUBROUTINE Morison_CopyMemberPropType + + SUBROUTINE Morison_DestroyMemberPropType( MemberPropTypeData, ErrStat, ErrMsg ) + TYPE(Morison_MemberPropType), INTENT(INOUT) :: MemberPropTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberPropType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyMemberPropType + + SUBROUTINE Morison_PackMemberPropType( 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(Morison_MemberPropType), 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 = 'Morison_PackMemberPropType' + ! 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 ! PropSetID + Re_BufSz = Re_BufSz + 1 ! PropD + Re_BufSz = Re_BufSz + 1 ! PropThck + 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%PropSetID + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PropD + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PropThck + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackMemberPropType + + SUBROUTINE Morison_UnPackMemberPropType( 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(Morison_MemberPropType), 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 = 'Morison_UnPackMemberPropType' + ! 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%PropSetID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PropD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PropThck = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackMemberPropType + + SUBROUTINE Morison_CopyFilledGroupType( SrcFilledGroupTypeData, DstFilledGroupTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_FilledGroupType), INTENT(IN) :: SrcFilledGroupTypeData + TYPE(Morison_FilledGroupType), INTENT(INOUT) :: DstFilledGroupTypeData + 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 = 'Morison_CopyFilledGroupType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstFilledGroupTypeData%FillNumM = SrcFilledGroupTypeData%FillNumM +IF (ALLOCATED(SrcFilledGroupTypeData%FillMList)) THEN + i1_l = LBOUND(SrcFilledGroupTypeData%FillMList,1) + i1_u = UBOUND(SrcFilledGroupTypeData%FillMList,1) + IF (.NOT. ALLOCATED(DstFilledGroupTypeData%FillMList)) THEN + ALLOCATE(DstFilledGroupTypeData%FillMList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFilledGroupTypeData%FillMList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFilledGroupTypeData%FillMList = SrcFilledGroupTypeData%FillMList +ENDIF + DstFilledGroupTypeData%FillFSLoc = SrcFilledGroupTypeData%FillFSLoc + DstFilledGroupTypeData%FillDensChr = SrcFilledGroupTypeData%FillDensChr + DstFilledGroupTypeData%FillDens = SrcFilledGroupTypeData%FillDens + END SUBROUTINE Morison_CopyFilledGroupType + + SUBROUTINE Morison_DestroyFilledGroupType( FilledGroupTypeData, ErrStat, ErrMsg ) + TYPE(Morison_FilledGroupType), INTENT(INOUT) :: FilledGroupTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyFilledGroupType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(FilledGroupTypeData%FillMList)) THEN + DEALLOCATE(FilledGroupTypeData%FillMList) +ENDIF + END SUBROUTINE Morison_DestroyFilledGroupType + + SUBROUTINE Morison_PackFilledGroupType( 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(Morison_FilledGroupType), 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 = 'Morison_PackFilledGroupType' + ! 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 ! FillNumM + Int_BufSz = Int_BufSz + 1 ! FillMList allocated yes/no + IF ( ALLOCATED(InData%FillMList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FillMList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FillMList) ! FillMList + END IF + Re_BufSz = Re_BufSz + 1 ! FillFSLoc + Int_BufSz = Int_BufSz + 1*LEN(InData%FillDensChr) ! FillDensChr + Re_BufSz = Re_BufSz + 1 ! FillDens + 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%FillNumM + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FillMList) ) 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%FillMList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FillMList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FillMList,1), UBOUND(InData%FillMList,1) + IntKiBuf(Int_Xferred) = InData%FillMList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%FillFSLoc + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%FillDensChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%FillDensChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%FillDens + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackFilledGroupType + + SUBROUTINE Morison_UnPackFilledGroupType( 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(Morison_FilledGroupType), 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 = 'Morison_UnPackFilledGroupType' + ! 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%FillNumM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FillMList 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%FillMList)) DEALLOCATE(OutData%FillMList) + ALLOCATE(OutData%FillMList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FillMList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FillMList,1), UBOUND(OutData%FillMList,1) + OutData%FillMList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%FillFSLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%FillDensChr) + OutData%FillDensChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%FillDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackFilledGroupType + + SUBROUTINE Morison_CopyCoefDpths( SrcCoefDpthsData, DstCoefDpthsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_CoefDpths), INTENT(IN) :: SrcCoefDpthsData + TYPE(Morison_CoefDpths), INTENT(INOUT) :: DstCoefDpthsData + 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 = 'Morison_CopyCoefDpths' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCoefDpthsData%Dpth = SrcCoefDpthsData%Dpth + DstCoefDpthsData%DpthCd = SrcCoefDpthsData%DpthCd + DstCoefDpthsData%DpthCdMG = SrcCoefDpthsData%DpthCdMG + DstCoefDpthsData%DpthCa = SrcCoefDpthsData%DpthCa + DstCoefDpthsData%DpthCaMG = SrcCoefDpthsData%DpthCaMG + DstCoefDpthsData%DpthCp = SrcCoefDpthsData%DpthCp + DstCoefDpthsData%DpthCpMG = SrcCoefDpthsData%DpthCpMG + DstCoefDpthsData%DpthAxCa = SrcCoefDpthsData%DpthAxCa + DstCoefDpthsData%DpthAxCaMG = SrcCoefDpthsData%DpthAxCaMG + DstCoefDpthsData%DpthAxCp = SrcCoefDpthsData%DpthAxCp + DstCoefDpthsData%DpthAxCpMG = SrcCoefDpthsData%DpthAxCpMG + END SUBROUTINE Morison_CopyCoefDpths + + SUBROUTINE Morison_DestroyCoefDpths( CoefDpthsData, ErrStat, ErrMsg ) + TYPE(Morison_CoefDpths), INTENT(INOUT) :: CoefDpthsData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyCoefDpths' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyCoefDpths + + SUBROUTINE Morison_PackCoefDpths( 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(Morison_CoefDpths), 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 = 'Morison_PackCoefDpths' + ! 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 ! Dpth + Re_BufSz = Re_BufSz + 1 ! DpthCd + Re_BufSz = Re_BufSz + 1 ! DpthCdMG + Re_BufSz = Re_BufSz + 1 ! DpthCa + Re_BufSz = Re_BufSz + 1 ! DpthCaMG + Re_BufSz = Re_BufSz + 1 ! DpthCp + Re_BufSz = Re_BufSz + 1 ! DpthCpMG + Re_BufSz = Re_BufSz + 1 ! DpthAxCa + Re_BufSz = Re_BufSz + 1 ! DpthAxCaMG + Re_BufSz = Re_BufSz + 1 ! DpthAxCp + Re_BufSz = Re_BufSz + 1 ! DpthAxCpMG + 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%Dpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCdMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthCpMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCpMG + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackCoefDpths + + SUBROUTINE Morison_UnPackCoefDpths( 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(Morison_CoefDpths), 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 = 'Morison_UnPackCoefDpths' + ! 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%Dpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCdMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthCpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackCoefDpths + + SUBROUTINE Morison_CopyAxialCoefType( SrcAxialCoefTypeData, DstAxialCoefTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_AxialCoefType), INTENT(IN) :: SrcAxialCoefTypeData + TYPE(Morison_AxialCoefType), INTENT(INOUT) :: DstAxialCoefTypeData + 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 = 'Morison_CopyAxialCoefType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstAxialCoefTypeData%AxCoefID = SrcAxialCoefTypeData%AxCoefID + DstAxialCoefTypeData%AxCd = SrcAxialCoefTypeData%AxCd + DstAxialCoefTypeData%AxCa = SrcAxialCoefTypeData%AxCa + DstAxialCoefTypeData%AxCp = SrcAxialCoefTypeData%AxCp + END SUBROUTINE Morison_CopyAxialCoefType + + SUBROUTINE Morison_DestroyAxialCoefType( AxialCoefTypeData, ErrStat, ErrMsg ) + TYPE(Morison_AxialCoefType), INTENT(INOUT) :: AxialCoefTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyAxialCoefType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyAxialCoefType + + SUBROUTINE Morison_PackAxialCoefType( 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(Morison_AxialCoefType), 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 = 'Morison_PackAxialCoefType' + ! 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 ! AxCoefID + Re_BufSz = Re_BufSz + 1 ! AxCd + Re_BufSz = Re_BufSz + 1 ! AxCa + Re_BufSz = Re_BufSz + 1 ! AxCp + 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%AxCoefID + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCp + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackAxialCoefType + + SUBROUTINE Morison_UnPackAxialCoefType( 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(Morison_AxialCoefType), 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 = 'Morison_UnPackAxialCoefType' + ! 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%AxCoefID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AxCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackAxialCoefType + + SUBROUTINE Morison_CopyMemberInputType( SrcMemberInputTypeData, DstMemberInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MemberInputType), INTENT(IN) :: SrcMemberInputTypeData + TYPE(Morison_MemberInputType), INTENT(INOUT) :: DstMemberInputTypeData + 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 = 'Morison_CopyMemberInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMemberInputTypeData%MemberID = SrcMemberInputTypeData%MemberID + DstMemberInputTypeData%MJointID1 = SrcMemberInputTypeData%MJointID1 + DstMemberInputTypeData%MJointID2 = SrcMemberInputTypeData%MJointID2 + DstMemberInputTypeData%MJointID1Indx = SrcMemberInputTypeData%MJointID1Indx + DstMemberInputTypeData%MJointID2Indx = SrcMemberInputTypeData%MJointID2Indx + DstMemberInputTypeData%MPropSetID1 = SrcMemberInputTypeData%MPropSetID1 + DstMemberInputTypeData%MPropSetID2 = SrcMemberInputTypeData%MPropSetID2 + DstMemberInputTypeData%MPropSetID1Indx = SrcMemberInputTypeData%MPropSetID1Indx + DstMemberInputTypeData%MPropSetID2Indx = SrcMemberInputTypeData%MPropSetID2Indx + DstMemberInputTypeData%MDivSize = SrcMemberInputTypeData%MDivSize + DstMemberInputTypeData%MCoefMod = SrcMemberInputTypeData%MCoefMod + DstMemberInputTypeData%MmbrCoefIDIndx = SrcMemberInputTypeData%MmbrCoefIDIndx + DstMemberInputTypeData%MmbrFilledIDIndx = SrcMemberInputTypeData%MmbrFilledIDIndx + DstMemberInputTypeData%PropPot = SrcMemberInputTypeData%PropPot + DstMemberInputTypeData%NumSplits = SrcMemberInputTypeData%NumSplits + DstMemberInputTypeData%Splits = SrcMemberInputTypeData%Splits + DstMemberInputTypeData%R_LToG = SrcMemberInputTypeData%R_LToG + END SUBROUTINE Morison_CopyMemberInputType + + SUBROUTINE Morison_DestroyMemberInputType( MemberInputTypeData, ErrStat, ErrMsg ) + TYPE(Morison_MemberInputType), INTENT(INOUT) :: MemberInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberInputType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyMemberInputType + + SUBROUTINE Morison_PackMemberInputType( 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(Morison_MemberInputType), 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 = 'Morison_PackMemberInputType' + ! 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 ! MemberID + Int_BufSz = Int_BufSz + 1 ! MJointID1 + Int_BufSz = Int_BufSz + 1 ! MJointID2 + Int_BufSz = Int_BufSz + 1 ! MJointID1Indx + Int_BufSz = Int_BufSz + 1 ! MJointID2Indx + Int_BufSz = Int_BufSz + 1 ! MPropSetID1 + Int_BufSz = Int_BufSz + 1 ! MPropSetID2 + Int_BufSz = Int_BufSz + 1 ! MPropSetID1Indx + Int_BufSz = Int_BufSz + 1 ! MPropSetID2Indx + Re_BufSz = Re_BufSz + 1 ! MDivSize + Int_BufSz = Int_BufSz + 1 ! MCoefMod + Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx + Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx + Int_BufSz = Int_BufSz + 1 ! PropPot + Int_BufSz = Int_BufSz + 1 ! NumSplits + Re_BufSz = Re_BufSz + SIZE(InData%Splits) ! Splits + Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + 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%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MJointID1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MJointID2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MJointID1Indx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MJointID2Indx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MPropSetID1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MPropSetID2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MPropSetID1Indx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MPropSetID2Indx + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MDivSize + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MCoefMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrCoefIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrFilledIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumSplits + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%Splits,1), UBOUND(InData%Splits,1) + ReKiBuf(Re_Xferred) = InData%Splits(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) + DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) + ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE Morison_PackMemberInputType + + SUBROUTINE Morison_UnPackMemberInputType( 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(Morison_MemberInputType), 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 = 'Morison_UnPackMemberInputType' + ! 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%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MJointID1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MJointID2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MJointID1Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MJointID2Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MPropSetID1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MPropSetID2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MPropSetID1Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MPropSetID2Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MDivSize = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MCoefMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MmbrCoefIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MmbrFilledIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) + Int_Xferred = Int_Xferred + 1 + OutData%NumSplits = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%Splits,1) + i1_u = UBOUND(OutData%Splits,1) + DO i1 = LBOUND(OutData%Splits,1), UBOUND(OutData%Splits,1) + OutData%Splits(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%R_LToG,1) + i1_u = UBOUND(OutData%R_LToG,1) + i2_l = LBOUND(OutData%R_LToG,2) + i2_u = UBOUND(OutData%R_LToG,2) + DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) + DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) + OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE Morison_UnPackMemberInputType + + SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_NodeType), INTENT(IN) :: SrcNodeTypeData + TYPE(Morison_NodeType), INTENT(INOUT) :: DstNodeTypeData + 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 = 'Morison_CopyNodeType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstNodeTypeData%NodeType = SrcNodeTypeData%NodeType + DstNodeTypeData%JointIndx = SrcNodeTypeData%JointIndx + DstNodeTypeData%JointPos = SrcNodeTypeData%JointPos + DstNodeTypeData%JointOvrlp = SrcNodeTypeData%JointOvrlp + DstNodeTypeData%JointAxIDIndx = SrcNodeTypeData%JointAxIDIndx + DstNodeTypeData%NConnections = SrcNodeTypeData%NConnections + DstNodeTypeData%ConnectionList = SrcNodeTypeData%ConnectionList + DstNodeTypeData%NConnectPreSplit = SrcNodeTypeData%NConnectPreSplit + DstNodeTypeData%Cd = SrcNodeTypeData%Cd + DstNodeTypeData%CdMG = SrcNodeTypeData%CdMG + DstNodeTypeData%Ca = SrcNodeTypeData%Ca + DstNodeTypeData%CaMG = SrcNodeTypeData%CaMG + DstNodeTypeData%Cp = SrcNodeTypeData%Cp + DstNodeTypeData%CpMG = SrcNodeTypeData%CpMG + DstNodeTypeData%JAxCd = SrcNodeTypeData%JAxCd + DstNodeTypeData%JAxCa = SrcNodeTypeData%JAxCa + DstNodeTypeData%JAxCp = SrcNodeTypeData%JAxCp + DstNodeTypeData%AxCa = SrcNodeTypeData%AxCa + DstNodeTypeData%AxCp = SrcNodeTypeData%AxCp + DstNodeTypeData%AxCaMG = SrcNodeTypeData%AxCaMG + DstNodeTypeData%AxCpMG = SrcNodeTypeData%AxCpMG + DstNodeTypeData%R = SrcNodeTypeData%R + DstNodeTypeData%t = SrcNodeTypeData%t + DstNodeTypeData%tMG = SrcNodeTypeData%tMG + DstNodeTypeData%dRdz = SrcNodeTypeData%dRdz + DstNodeTypeData%MGdensity = SrcNodeTypeData%MGdensity + DstNodeTypeData%FillFSLoc = SrcNodeTypeData%FillFSLoc + DstNodeTypeData%FillFlag = SrcNodeTypeData%FillFlag + DstNodeTypeData%FillDensity = SrcNodeTypeData%FillDensity + DstNodeTypeData%InpMbrIndx = SrcNodeTypeData%InpMbrIndx + DstNodeTypeData%InpMbrDist = SrcNodeTypeData%InpMbrDist + DstNodeTypeData%PropPot = SrcNodeTypeData%PropPot + DstNodeTypeData%R_LToG = SrcNodeTypeData%R_LToG + END SUBROUTINE Morison_CopyNodeType + + SUBROUTINE Morison_DestroyNodeType( NodeTypeData, ErrStat, ErrMsg ) + TYPE(Morison_NodeType), INTENT(INOUT) :: NodeTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyNodeType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyNodeType + + SUBROUTINE Morison_PackNodeType( 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(Morison_NodeType), 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 = 'Morison_PackNodeType' + ! 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 ! NodeType + Int_BufSz = Int_BufSz + 1 ! JointIndx + Re_BufSz = Re_BufSz + SIZE(InData%JointPos) ! JointPos + Int_BufSz = Int_BufSz + 1 ! JointOvrlp + Int_BufSz = Int_BufSz + 1 ! JointAxIDIndx + Int_BufSz = Int_BufSz + 1 ! NConnections + Int_BufSz = Int_BufSz + SIZE(InData%ConnectionList) ! ConnectionList + Int_BufSz = Int_BufSz + 1 ! NConnectPreSplit + Re_BufSz = Re_BufSz + 1 ! Cd + Re_BufSz = Re_BufSz + 1 ! CdMG + Re_BufSz = Re_BufSz + 1 ! Ca + Re_BufSz = Re_BufSz + 1 ! CaMG + Re_BufSz = Re_BufSz + 1 ! Cp + Re_BufSz = Re_BufSz + 1 ! CpMG + Re_BufSz = Re_BufSz + 1 ! JAxCd + Re_BufSz = Re_BufSz + 1 ! JAxCa + Re_BufSz = Re_BufSz + 1 ! JAxCp + Re_BufSz = Re_BufSz + 1 ! AxCa + Re_BufSz = Re_BufSz + 1 ! AxCp + Re_BufSz = Re_BufSz + 1 ! AxCaMG + Re_BufSz = Re_BufSz + 1 ! AxCpMG + Re_BufSz = Re_BufSz + 1 ! R + Re_BufSz = Re_BufSz + 1 ! t + Re_BufSz = Re_BufSz + 1 ! tMG + Re_BufSz = Re_BufSz + 1 ! dRdz + Re_BufSz = Re_BufSz + 1 ! MGdensity + Re_BufSz = Re_BufSz + 1 ! FillFSLoc + Int_BufSz = Int_BufSz + 1 ! FillFlag + Re_BufSz = Re_BufSz + 1 ! FillDensity + Int_BufSz = Int_BufSz + 1 ! InpMbrIndx + Re_BufSz = Re_BufSz + 1 ! InpMbrDist + Int_BufSz = Int_BufSz + 1 ! PropPot + Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + 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%NodeType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%JointIndx + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%JointPos,1), UBOUND(InData%JointPos,1) + ReKiBuf(Re_Xferred) = InData%JointPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%JointOvrlp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%JointAxIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NConnections + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%ConnectionList,1), UBOUND(InData%ConnectionList,1) + IntKiBuf(Int_Xferred) = InData%ConnectionList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NConnectPreSplit + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CdMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ca + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CpMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%JAxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%JAxCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%JAxCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCpMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%R + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dRdz + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MGdensity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FillFSLoc + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FillFlag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FillDensity + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InpMbrIndx + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InpMbrDist + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) + DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) + ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE Morison_PackNodeType + + SUBROUTINE Morison_UnPackNodeType( 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(Morison_NodeType), 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 = 'Morison_UnPackNodeType' + ! 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%NodeType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%JointIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%JointPos,1) + i1_u = UBOUND(OutData%JointPos,1) + DO i1 = LBOUND(OutData%JointPos,1), UBOUND(OutData%JointPos,1) + OutData%JointPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%JointOvrlp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%JointAxIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NConnections = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%ConnectionList,1) + i1_u = UBOUND(OutData%ConnectionList,1) + DO i1 = LBOUND(OutData%ConnectionList,1), UBOUND(OutData%ConnectionList,1) + OutData%ConnectionList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NConnectPreSplit = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Cd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CdMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ca = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%JAxCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%JAxCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%JAxCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%R = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dRdz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MGdensity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FillFSLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FillFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%FillFlag) + Int_Xferred = Int_Xferred + 1 + OutData%FillDensity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InpMbrIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%InpMbrDist = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%R_LToG,1) + i1_u = UBOUND(OutData%R_LToG,1) + i2_l = LBOUND(OutData%R_LToG,2) + i2_u = UBOUND(OutData%R_LToG,2) + DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) + DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) + OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE Morison_UnPackNodeType + + SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MemberType), INTENT(IN) :: SrcMemberTypeData + TYPE(Morison_MemberType), INTENT(INOUT) :: DstMemberTypeData + 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 = 'Morison_CopyMemberType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMemberTypeData%Node1Indx = SrcMemberTypeData%Node1Indx + DstMemberTypeData%Node2Indx = SrcMemberTypeData%Node2Indx + DstMemberTypeData%R1 = SrcMemberTypeData%R1 + DstMemberTypeData%t1 = SrcMemberTypeData%t1 + DstMemberTypeData%R2 = SrcMemberTypeData%R2 + DstMemberTypeData%t2 = SrcMemberTypeData%t2 + DstMemberTypeData%Cd1 = SrcMemberTypeData%Cd1 + DstMemberTypeData%CdMG1 = SrcMemberTypeData%CdMG1 + DstMemberTypeData%Ca1 = SrcMemberTypeData%Ca1 + DstMemberTypeData%CaMG1 = SrcMemberTypeData%CaMG1 + DstMemberTypeData%Cp1 = SrcMemberTypeData%Cp1 + DstMemberTypeData%CpMG1 = SrcMemberTypeData%CpMG1 + DstMemberTypeData%AxCa1 = SrcMemberTypeData%AxCa1 + DstMemberTypeData%AxCaMG1 = SrcMemberTypeData%AxCaMG1 + DstMemberTypeData%AxCp1 = SrcMemberTypeData%AxCp1 + DstMemberTypeData%AxCpMG1 = SrcMemberTypeData%AxCpMG1 + DstMemberTypeData%Cd2 = SrcMemberTypeData%Cd2 + DstMemberTypeData%CdMG2 = SrcMemberTypeData%CdMG2 + DstMemberTypeData%Ca2 = SrcMemberTypeData%Ca2 + DstMemberTypeData%CaMG2 = SrcMemberTypeData%CaMG2 + DstMemberTypeData%Cp2 = SrcMemberTypeData%Cp2 + DstMemberTypeData%CpMG2 = SrcMemberTypeData%CpMG2 + DstMemberTypeData%AxCa2 = SrcMemberTypeData%AxCa2 + DstMemberTypeData%AxCaMG2 = SrcMemberTypeData%AxCaMG2 + DstMemberTypeData%AxCp2 = SrcMemberTypeData%AxCp2 + DstMemberTypeData%AxCpMG2 = SrcMemberTypeData%AxCpMG2 + DstMemberTypeData%InpMbrDist1 = SrcMemberTypeData%InpMbrDist1 + DstMemberTypeData%InpMbrDist2 = SrcMemberTypeData%InpMbrDist2 + DstMemberTypeData%InpMbrLen = SrcMemberTypeData%InpMbrLen + DstMemberTypeData%InpMbrIndx = SrcMemberTypeData%InpMbrIndx + DstMemberTypeData%R_LToG = SrcMemberTypeData%R_LToG + DstMemberTypeData%NumSplits = SrcMemberTypeData%NumSplits + DstMemberTypeData%Splits = SrcMemberTypeData%Splits + DstMemberTypeData%MGvolume = SrcMemberTypeData%MGvolume + DstMemberTypeData%MDivSize = SrcMemberTypeData%MDivSize + DstMemberTypeData%MCoefMod = SrcMemberTypeData%MCoefMod + DstMemberTypeData%MmbrCoefIDIndx = SrcMemberTypeData%MmbrCoefIDIndx + DstMemberTypeData%MmbrFilledIDIndx = SrcMemberTypeData%MmbrFilledIDIndx + DstMemberTypeData%FillFSLoc = SrcMemberTypeData%FillFSLoc + DstMemberTypeData%FillDens = SrcMemberTypeData%FillDens + DstMemberTypeData%F_Bouy = SrcMemberTypeData%F_Bouy + DstMemberTypeData%F_DP = SrcMemberTypeData%F_DP + DstMemberTypeData%PropPot = SrcMemberTypeData%PropPot + END SUBROUTINE Morison_CopyMemberType + + SUBROUTINE Morison_DestroyMemberType( MemberTypeData, ErrStat, ErrMsg ) + TYPE(Morison_MemberType), INTENT(INOUT) :: MemberTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyMemberType + + SUBROUTINE Morison_PackMemberType( 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(Morison_MemberType), 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 = 'Morison_PackMemberType' + ! 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 ! Node1Indx + Int_BufSz = Int_BufSz + 1 ! Node2Indx + Re_BufSz = Re_BufSz + 1 ! R1 + Re_BufSz = Re_BufSz + 1 ! t1 + Re_BufSz = Re_BufSz + 1 ! R2 + Re_BufSz = Re_BufSz + 1 ! t2 + Re_BufSz = Re_BufSz + 1 ! Cd1 + Re_BufSz = Re_BufSz + 1 ! CdMG1 + Re_BufSz = Re_BufSz + 1 ! Ca1 + Re_BufSz = Re_BufSz + 1 ! CaMG1 + Re_BufSz = Re_BufSz + 1 ! Cp1 + Re_BufSz = Re_BufSz + 1 ! CpMG1 + Re_BufSz = Re_BufSz + 1 ! AxCa1 + Re_BufSz = Re_BufSz + 1 ! AxCaMG1 + Re_BufSz = Re_BufSz + 1 ! AxCp1 + Re_BufSz = Re_BufSz + 1 ! AxCpMG1 + Re_BufSz = Re_BufSz + 1 ! Cd2 + Re_BufSz = Re_BufSz + 1 ! CdMG2 + Re_BufSz = Re_BufSz + 1 ! Ca2 + Re_BufSz = Re_BufSz + 1 ! CaMG2 + Re_BufSz = Re_BufSz + 1 ! Cp2 + Re_BufSz = Re_BufSz + 1 ! CpMG2 + Re_BufSz = Re_BufSz + 1 ! AxCa2 + Re_BufSz = Re_BufSz + 1 ! AxCaMG2 + Re_BufSz = Re_BufSz + 1 ! AxCp2 + Re_BufSz = Re_BufSz + 1 ! AxCpMG2 + Re_BufSz = Re_BufSz + 1 ! InpMbrDist1 + Re_BufSz = Re_BufSz + 1 ! InpMbrDist2 + Re_BufSz = Re_BufSz + 1 ! InpMbrLen + Int_BufSz = Int_BufSz + 1 ! InpMbrIndx + Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + Int_BufSz = Int_BufSz + 1 ! NumSplits + Re_BufSz = Re_BufSz + SIZE(InData%Splits) ! Splits + Re_BufSz = Re_BufSz + 1 ! MGvolume + Re_BufSz = Re_BufSz + 1 ! MDivSize + Int_BufSz = Int_BufSz + 1 ! MCoefMod + Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx + Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx + Re_BufSz = Re_BufSz + 1 ! FillFSLoc + Re_BufSz = Re_BufSz + 1 ! FillDens + Re_BufSz = Re_BufSz + SIZE(InData%F_Bouy) ! F_Bouy + Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP + Int_BufSz = Int_BufSz + 1 ! PropPot + 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%Node1Indx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Node2Indx + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%R1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%R2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ca1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCa1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CdMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ca2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CpMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCa2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AxCpMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InpMbrDist1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InpMbrDist2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InpMbrLen + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InpMbrIndx + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) + DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) + ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IntKiBuf(Int_Xferred) = InData%NumSplits + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%Splits,1), UBOUND(InData%Splits,1) + ReKiBuf(Re_Xferred) = InData%Splits(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%MGvolume + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MDivSize + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MCoefMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrCoefIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrFilledIDIndx + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FillFSLoc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FillDens + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%F_Bouy,1), UBOUND(InData%F_Bouy,1) + ReKiBuf(Re_Xferred) = InData%F_Bouy(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_DP,1), UBOUND(InData%F_DP,1) + ReKiBuf(Re_Xferred) = InData%F_DP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackMemberType + + SUBROUTINE Morison_UnPackMemberType( 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(Morison_MemberType), 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 = 'Morison_UnPackMemberType' + ! 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%Node1Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Node2Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%R1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%R2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CdMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ca1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CaMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cp1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CpMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCa1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCaMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCp1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCpMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cd2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CdMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ca2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CaMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cp2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CpMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCa2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCaMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCp2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AxCpMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InpMbrDist1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InpMbrDist2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InpMbrLen = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InpMbrIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%R_LToG,1) + i1_u = UBOUND(OutData%R_LToG,1) + i2_l = LBOUND(OutData%R_LToG,2) + i2_u = UBOUND(OutData%R_LToG,2) + DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) + DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) + OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%NumSplits = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%Splits,1) + i1_u = UBOUND(OutData%Splits,1) + DO i1 = LBOUND(OutData%Splits,1), UBOUND(OutData%Splits,1) + OutData%Splits(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%MGvolume = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MDivSize = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MCoefMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MmbrCoefIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MmbrFilledIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FillFSLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FillDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%F_Bouy,1) + i1_u = UBOUND(OutData%F_Bouy,1) + DO i1 = LBOUND(OutData%F_Bouy,1), UBOUND(OutData%F_Bouy,1) + OutData%F_Bouy(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_DP,1) + i1_u = UBOUND(OutData%F_DP,1) + DO i1 = LBOUND(OutData%F_DP,1), UBOUND(OutData%F_DP,1) + OutData%F_DP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_UnPackMemberType + + SUBROUTINE Morison_CopyCoefMembers( SrcCoefMembersData, DstCoefMembersData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_CoefMembers), INTENT(IN) :: SrcCoefMembersData + TYPE(Morison_CoefMembers), INTENT(INOUT) :: DstCoefMembersData + 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 = 'Morison_CopyCoefMembers' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCoefMembersData%MemberID = SrcCoefMembersData%MemberID + DstCoefMembersData%MemberCd1 = SrcCoefMembersData%MemberCd1 + DstCoefMembersData%MemberCd2 = SrcCoefMembersData%MemberCd2 + DstCoefMembersData%MemberCdMG1 = SrcCoefMembersData%MemberCdMG1 + DstCoefMembersData%MemberCdMG2 = SrcCoefMembersData%MemberCdMG2 + DstCoefMembersData%MemberCa1 = SrcCoefMembersData%MemberCa1 + DstCoefMembersData%MemberCa2 = SrcCoefMembersData%MemberCa2 + DstCoefMembersData%MemberCaMG1 = SrcCoefMembersData%MemberCaMG1 + DstCoefMembersData%MemberCaMG2 = SrcCoefMembersData%MemberCaMG2 + DstCoefMembersData%MemberCp1 = SrcCoefMembersData%MemberCp1 + DstCoefMembersData%MemberCp2 = SrcCoefMembersData%MemberCp2 + DstCoefMembersData%MemberCpMG1 = SrcCoefMembersData%MemberCpMG1 + DstCoefMembersData%MemberCpMG2 = SrcCoefMembersData%MemberCpMG2 + DstCoefMembersData%MemberAxCa1 = SrcCoefMembersData%MemberAxCa1 + DstCoefMembersData%MemberAxCa2 = SrcCoefMembersData%MemberAxCa2 + DstCoefMembersData%MemberAxCaMG1 = SrcCoefMembersData%MemberAxCaMG1 + DstCoefMembersData%MemberAxCaMG2 = SrcCoefMembersData%MemberAxCaMG2 + DstCoefMembersData%MemberAxCp1 = SrcCoefMembersData%MemberAxCp1 + DstCoefMembersData%MemberAxCp2 = SrcCoefMembersData%MemberAxCp2 + DstCoefMembersData%MemberAxCpMG1 = SrcCoefMembersData%MemberAxCpMG1 + DstCoefMembersData%MemberAxCpMG2 = SrcCoefMembersData%MemberAxCpMG2 + END SUBROUTINE Morison_CopyCoefMembers + + SUBROUTINE Morison_DestroyCoefMembers( CoefMembersData, ErrStat, ErrMsg ) + TYPE(Morison_CoefMembers), INTENT(INOUT) :: CoefMembersData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyCoefMembers' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyCoefMembers + + SUBROUTINE Morison_PackCoefMembers( 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(Morison_CoefMembers), 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 = 'Morison_PackCoefMembers' + ! 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 ! MemberID + Re_BufSz = Re_BufSz + 1 ! MemberCd1 + Re_BufSz = Re_BufSz + 1 ! MemberCd2 + Re_BufSz = Re_BufSz + 1 ! MemberCdMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCdMG2 + Re_BufSz = Re_BufSz + 1 ! MemberCa1 + Re_BufSz = Re_BufSz + 1 ! MemberCa2 + Re_BufSz = Re_BufSz + 1 ! MemberCaMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCaMG2 + Re_BufSz = Re_BufSz + 1 ! MemberCp1 + Re_BufSz = Re_BufSz + 1 ! MemberCp2 + Re_BufSz = Re_BufSz + 1 ! MemberCpMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCpMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCa1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCa2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCp1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCp2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG2 + 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%MemberID + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCdMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCa1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCa2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCpMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCa1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCa2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCpMG2 + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackCoefMembers + + SUBROUTINE Morison_UnPackCoefMembers( 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(Morison_CoefMembers), 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 = 'Morison_UnPackCoefMembers' + ! 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%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MemberCd1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCd2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCdMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCdMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCa1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCa2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCaMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCaMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCp1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCp2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCpMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberCpMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCa1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCa2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCaMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCaMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCp1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCp2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCpMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCpMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackCoefMembers + + SUBROUTINE Morison_CopyMGDepthsType( SrcMGDepthsTypeData, DstMGDepthsTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MGDepthsType), INTENT(IN) :: SrcMGDepthsTypeData + TYPE(Morison_MGDepthsType), INTENT(INOUT) :: DstMGDepthsTypeData + 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 = 'Morison_CopyMGDepthsType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMGDepthsTypeData%MGDpth = SrcMGDepthsTypeData%MGDpth + DstMGDepthsTypeData%MGThck = SrcMGDepthsTypeData%MGThck + DstMGDepthsTypeData%MGDens = SrcMGDepthsTypeData%MGDens + END SUBROUTINE Morison_CopyMGDepthsType + + SUBROUTINE Morison_DestroyMGDepthsType( MGDepthsTypeData, ErrStat, ErrMsg ) + TYPE(Morison_MGDepthsType), INTENT(INOUT) :: MGDepthsTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMGDepthsType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyMGDepthsType + + SUBROUTINE Morison_PackMGDepthsType( 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(Morison_MGDepthsType), 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 = 'Morison_PackMGDepthsType' + ! 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 ! MGDpth + Re_BufSz = Re_BufSz + 1 ! MGThck + Re_BufSz = Re_BufSz + 1 ! MGDens + 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%MGDpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MGThck + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MGDens + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_PackMGDepthsType + + SUBROUTINE Morison_UnPackMGDepthsType( 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(Morison_MGDepthsType), 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 = 'Morison_UnPackMGDepthsType' + ! 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%MGDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MGThck = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MGDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackMGDepthsType + + SUBROUTINE Morison_CopyMOutput( SrcMOutputData, DstMOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MOutput), INTENT(IN) :: SrcMOutputData + TYPE(Morison_MOutput), INTENT(INOUT) :: DstMOutputData + 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 = 'Morison_CopyMOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMOutputData%MemberID = SrcMOutputData%MemberID + DstMOutputData%NOutLoc = SrcMOutputData%NOutLoc +IF (ALLOCATED(SrcMOutputData%NodeLocs)) THEN + i1_l = LBOUND(SrcMOutputData%NodeLocs,1) + i1_u = UBOUND(SrcMOutputData%NodeLocs,1) + IF (.NOT. ALLOCATED(DstMOutputData%NodeLocs)) THEN + ALLOCATE(DstMOutputData%NodeLocs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%NodeLocs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%NodeLocs = SrcMOutputData%NodeLocs +ENDIF + DstMOutputData%MemberIDIndx = SrcMOutputData%MemberIDIndx +IF (ALLOCATED(SrcMOutputData%Marker1)) THEN + i1_l = LBOUND(SrcMOutputData%Marker1,1) + i1_u = UBOUND(SrcMOutputData%Marker1,1) + IF (.NOT. ALLOCATED(DstMOutputData%Marker1)) THEN + ALLOCATE(DstMOutputData%Marker1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%Marker1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%Marker1 = SrcMOutputData%Marker1 +ENDIF +IF (ALLOCATED(SrcMOutputData%Marker2)) THEN + i1_l = LBOUND(SrcMOutputData%Marker2,1) + i1_u = UBOUND(SrcMOutputData%Marker2,1) + IF (.NOT. ALLOCATED(DstMOutputData%Marker2)) THEN + ALLOCATE(DstMOutputData%Marker2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%Marker2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%Marker2 = SrcMOutputData%Marker2 +ENDIF +IF (ALLOCATED(SrcMOutputData%s)) THEN + i1_l = LBOUND(SrcMOutputData%s,1) + i1_u = UBOUND(SrcMOutputData%s,1) + IF (.NOT. ALLOCATED(DstMOutputData%s)) THEN + ALLOCATE(DstMOutputData%s(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%s.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%s = SrcMOutputData%s +ENDIF + END SUBROUTINE Morison_CopyMOutput + + SUBROUTINE Morison_DestroyMOutput( MOutputData, ErrStat, ErrMsg ) + TYPE(Morison_MOutput), INTENT(INOUT) :: MOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MOutputData%NodeLocs)) THEN + DEALLOCATE(MOutputData%NodeLocs) +ENDIF +IF (ALLOCATED(MOutputData%Marker1)) THEN + DEALLOCATE(MOutputData%Marker1) +ENDIF +IF (ALLOCATED(MOutputData%Marker2)) THEN + DEALLOCATE(MOutputData%Marker2) +ENDIF +IF (ALLOCATED(MOutputData%s)) THEN + DEALLOCATE(MOutputData%s) +ENDIF + END SUBROUTINE Morison_DestroyMOutput + + SUBROUTINE Morison_PackMOutput( 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(Morison_MOutput), 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 = 'Morison_PackMOutput' + ! 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 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NOutLoc + Int_BufSz = Int_BufSz + 1 ! NodeLocs allocated yes/no + IF ( ALLOCATED(InData%NodeLocs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeLocs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%NodeLocs) ! NodeLocs + END IF + Int_BufSz = Int_BufSz + 1 ! MemberIDIndx + Int_BufSz = Int_BufSz + 1 ! Marker1 allocated yes/no + IF ( ALLOCATED(InData%Marker1) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Marker1 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Marker1) ! Marker1 + END IF + Int_BufSz = Int_BufSz + 1 ! Marker2 allocated yes/no + IF ( ALLOCATED(InData%Marker2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Marker2 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Marker2) ! Marker2 + END IF + Int_BufSz = Int_BufSz + 1 ! s allocated yes/no + IF ( ALLOCATED(InData%s) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! s upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%s) ! s + 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%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NOutLoc + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeLocs) ) 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%NodeLocs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeLocs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodeLocs,1), UBOUND(InData%NodeLocs,1) + ReKiBuf(Re_Xferred) = InData%NodeLocs(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%MemberIDIndx + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Marker1) ) 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%Marker1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Marker1,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Marker1,1), UBOUND(InData%Marker1,1) + IntKiBuf(Int_Xferred) = InData%Marker1(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Marker2) ) 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%Marker2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Marker2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Marker2,1), UBOUND(InData%Marker2,1) + IntKiBuf(Int_Xferred) = InData%Marker2(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%s) ) 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%s,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%s,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%s,1), UBOUND(InData%s,1) + ReKiBuf(Re_Xferred) = InData%s(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Morison_PackMOutput + + SUBROUTINE Morison_UnPackMOutput( 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(Morison_MOutput), 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 = 'Morison_UnPackMOutput' + ! 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%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NOutLoc = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeLocs 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%NodeLocs)) DEALLOCATE(OutData%NodeLocs) + ALLOCATE(OutData%NodeLocs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeLocs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeLocs,1), UBOUND(OutData%NodeLocs,1) + OutData%NodeLocs(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%MemberIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Marker1 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%Marker1)) DEALLOCATE(OutData%Marker1) + ALLOCATE(OutData%Marker1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Marker1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Marker1,1), UBOUND(OutData%Marker1,1) + OutData%Marker1(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Marker2 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%Marker2)) DEALLOCATE(OutData%Marker2) + ALLOCATE(OutData%Marker2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Marker2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Marker2,1), UBOUND(OutData%Marker2,1) + OutData%Marker2(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! s 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%s)) DEALLOCATE(OutData%s) + ALLOCATE(OutData%s(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%s.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%s,1), UBOUND(OutData%s,1) + OutData%s(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Morison_UnPackMOutput + + SUBROUTINE Morison_CopyJOutput( SrcJOutputData, DstJOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_JOutput), INTENT(IN) :: SrcJOutputData + TYPE(Morison_JOutput), INTENT(INOUT) :: DstJOutputData + 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 = 'Morison_CopyJOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstJOutputData%JointID = SrcJOutputData%JointID + DstJOutputData%JointIDIndx = SrcJOutputData%JointIDIndx + DstJOutputData%NumMarkers = SrcJOutputData%NumMarkers + DstJOutputData%Markers = SrcJOutputData%Markers + END SUBROUTINE Morison_CopyJOutput + + SUBROUTINE Morison_DestroyJOutput( JOutputData, ErrStat, ErrMsg ) + TYPE(Morison_JOutput), INTENT(INOUT) :: JOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyJOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyJOutput + + SUBROUTINE Morison_PackJOutput( 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(Morison_JOutput), 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 = 'Morison_PackJOutput' + ! 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 ! JointID + Int_BufSz = Int_BufSz + 1 ! JointIDIndx + Int_BufSz = Int_BufSz + 1 ! NumMarkers + Int_BufSz = Int_BufSz + SIZE(InData%Markers) ! Markers + 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%JointID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%JointIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumMarkers + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%Markers,1), UBOUND(InData%Markers,1) + IntKiBuf(Int_Xferred) = InData%Markers(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE Morison_PackJOutput + + SUBROUTINE Morison_UnPackJOutput( 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(Morison_JOutput), 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 = 'Morison_UnPackJOutput' + ! 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%JointID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%JointIDIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumMarkers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%Markers,1) + i1_u = UBOUND(OutData%Markers,1) + DO i1 = LBOUND(OutData%Markers,1), UBOUND(OutData%Markers,1) + OutData%Markers(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE Morison_UnPackJOutput + + SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%WtrDens = SrcInitInputData%WtrDens + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL + DstInitInputData%NJoints = SrcInitInputData%NJoints + DstInitInputData%NNodes = SrcInitInputData%NNodes + DstInitInputData%TotalPossibleSuperMembers = SrcInitInputData%TotalPossibleSuperMembers +IF (ALLOCATED(SrcInitInputData%InpJoints)) THEN + i1_l = LBOUND(SrcInitInputData%InpJoints,1) + i1_u = UBOUND(SrcInitInputData%InpJoints,1) + IF (.NOT. ALLOCATED(DstInitInputData%InpJoints)) THEN + ALLOCATE(DstInitInputData%InpJoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%InpJoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%InpJoints,1), UBOUND(SrcInitInputData%InpJoints,1) + CALL Morison_Copyjointtype( SrcInitInputData%InpJoints(i1), DstInitInputData%InpJoints(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInitInputData%Nodes)) THEN + i1_l = LBOUND(SrcInitInputData%Nodes,1) + i1_u = UBOUND(SrcInitInputData%Nodes,1) + IF (.NOT. ALLOCATED(DstInitInputData%Nodes)) THEN + ALLOCATE(DstInitInputData%Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%Nodes,1), UBOUND(SrcInitInputData%Nodes,1) + CALL Morison_Copynodetype( SrcInitInputData%Nodes(i1), DstInitInputData%Nodes(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NElements = SrcInitInputData%NElements +IF (ALLOCATED(SrcInitInputData%Elements)) THEN + i1_l = LBOUND(SrcInitInputData%Elements,1) + i1_u = UBOUND(SrcInitInputData%Elements,1) + IF (.NOT. ALLOCATED(DstInitInputData%Elements)) THEN + ALLOCATE(DstInitInputData%Elements(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Elements.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%Elements,1), UBOUND(SrcInitInputData%Elements,1) + CALL Morison_Copymembertype( SrcInitInputData%Elements(i1), DstInitInputData%Elements(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NAxCoefs = SrcInitInputData%NAxCoefs +IF (ALLOCATED(SrcInitInputData%AxialCoefs)) THEN + i1_l = LBOUND(SrcInitInputData%AxialCoefs,1) + i1_u = UBOUND(SrcInitInputData%AxialCoefs,1) + IF (.NOT. ALLOCATED(DstInitInputData%AxialCoefs)) THEN + ALLOCATE(DstInitInputData%AxialCoefs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%AxialCoefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%AxialCoefs,1), UBOUND(SrcInitInputData%AxialCoefs,1) + CALL Morison_Copyaxialcoeftype( SrcInitInputData%AxialCoefs(i1), DstInitInputData%AxialCoefs(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NPropSets = SrcInitInputData%NPropSets +IF (ALLOCATED(SrcInitInputData%MPropSets)) THEN + i1_l = LBOUND(SrcInitInputData%MPropSets,1) + i1_u = UBOUND(SrcInitInputData%MPropSets,1) + IF (.NOT. ALLOCATED(DstInitInputData%MPropSets)) THEN + ALLOCATE(DstInitInputData%MPropSets(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%MPropSets,1), UBOUND(SrcInitInputData%MPropSets,1) + CALL Morison_Copymemberproptype( SrcInitInputData%MPropSets(i1), DstInitInputData%MPropSets(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%SimplCd = SrcInitInputData%SimplCd + DstInitInputData%SimplCdMG = SrcInitInputData%SimplCdMG + DstInitInputData%SimplCa = SrcInitInputData%SimplCa + DstInitInputData%SimplCaMG = SrcInitInputData%SimplCaMG + DstInitInputData%SimplCp = SrcInitInputData%SimplCp + DstInitInputData%SimplCpMG = SrcInitInputData%SimplCpMG + DstInitInputData%SimplAxCa = SrcInitInputData%SimplAxCa + DstInitInputData%SimplAxCaMG = SrcInitInputData%SimplAxCaMG + DstInitInputData%SimplAxCp = SrcInitInputData%SimplAxCp + DstInitInputData%SimplAxCpMG = SrcInitInputData%SimplAxCpMG + DstInitInputData%NCoefDpth = SrcInitInputData%NCoefDpth +IF (ALLOCATED(SrcInitInputData%CoefDpths)) THEN + i1_l = LBOUND(SrcInitInputData%CoefDpths,1) + i1_u = UBOUND(SrcInitInputData%CoefDpths,1) + IF (.NOT. ALLOCATED(DstInitInputData%CoefDpths)) THEN + ALLOCATE(DstInitInputData%CoefDpths(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefDpths.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%CoefDpths,1), UBOUND(SrcInitInputData%CoefDpths,1) + CALL Morison_Copycoefdpths( SrcInitInputData%CoefDpths(i1), DstInitInputData%CoefDpths(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NCoefMembers = SrcInitInputData%NCoefMembers +IF (ALLOCATED(SrcInitInputData%CoefMembers)) THEN + i1_l = LBOUND(SrcInitInputData%CoefMembers,1) + i1_u = UBOUND(SrcInitInputData%CoefMembers,1) + IF (.NOT. ALLOCATED(DstInitInputData%CoefMembers)) THEN + ALLOCATE(DstInitInputData%CoefMembers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefMembers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%CoefMembers,1), UBOUND(SrcInitInputData%CoefMembers,1) + CALL Morison_Copycoefmembers( SrcInitInputData%CoefMembers(i1), DstInitInputData%CoefMembers(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NMembers = SrcInitInputData%NMembers +IF (ALLOCATED(SrcInitInputData%InpMembers)) THEN + i1_l = LBOUND(SrcInitInputData%InpMembers,1) + i1_u = UBOUND(SrcInitInputData%InpMembers,1) + IF (.NOT. ALLOCATED(DstInitInputData%InpMembers)) THEN + ALLOCATE(DstInitInputData%InpMembers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%InpMembers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%InpMembers,1), UBOUND(SrcInitInputData%InpMembers,1) + CALL Morison_Copymemberinputtype( SrcInitInputData%InpMembers(i1), DstInitInputData%InpMembers(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NFillGroups = SrcInitInputData%NFillGroups +IF (ALLOCATED(SrcInitInputData%FilledGroups)) THEN + i1_l = LBOUND(SrcInitInputData%FilledGroups,1) + i1_u = UBOUND(SrcInitInputData%FilledGroups,1) + IF (.NOT. ALLOCATED(DstInitInputData%FilledGroups)) THEN + ALLOCATE(DstInitInputData%FilledGroups(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%FilledGroups.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%FilledGroups,1), UBOUND(SrcInitInputData%FilledGroups,1) + CALL Morison_Copyfilledgrouptype( SrcInitInputData%FilledGroups(i1), DstInitInputData%FilledGroups(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NMGDepths = SrcInitInputData%NMGDepths +IF (ALLOCATED(SrcInitInputData%MGDepths)) THEN + i1_l = LBOUND(SrcInitInputData%MGDepths,1) + i1_u = UBOUND(SrcInitInputData%MGDepths,1) + IF (.NOT. ALLOCATED(DstInitInputData%MGDepths)) THEN + ALLOCATE(DstInitInputData%MGDepths(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MGDepths.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%MGDepths,1), UBOUND(SrcInitInputData%MGDepths,1) + CALL Morison_Copymgdepthstype( SrcInitInputData%MGDepths(i1), DstInitInputData%MGDepths(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%MGTop = SrcInitInputData%MGTop + DstInitInputData%MGBottom = SrcInitInputData%MGBottom + DstInitInputData%NMOutputs = SrcInitInputData%NMOutputs +IF (ALLOCATED(SrcInitInputData%MOutLst)) THEN + i1_l = LBOUND(SrcInitInputData%MOutLst,1) + i1_u = UBOUND(SrcInitInputData%MOutLst,1) + IF (.NOT. ALLOCATED(DstInitInputData%MOutLst)) THEN + ALLOCATE(DstInitInputData%MOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%MOutLst,1), UBOUND(SrcInitInputData%MOutLst,1) + CALL Morison_Copymoutput( SrcInitInputData%MOutLst(i1), DstInitInputData%MOutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%NJOutputs = SrcInitInputData%NJOutputs +IF (ALLOCATED(SrcInitInputData%JOutLst)) THEN + i1_l = LBOUND(SrcInitInputData%JOutLst,1) + i1_u = UBOUND(SrcInitInputData%JOutLst,1) + IF (.NOT. ALLOCATED(DstInitInputData%JOutLst)) THEN + ALLOCATE(DstInitInputData%JOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%JOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitInputData%JOutLst,1), UBOUND(SrcInitInputData%JOutLst,1) + CALL Morison_Copyjoutput( SrcInitInputData%JOutLst(i1), DstInitInputData%JOutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstInitInputData%OutList = SrcInitInputData%OutList +IF (ALLOCATED(SrcInitInputData%ValidOutList)) THEN + i1_l = LBOUND(SrcInitInputData%ValidOutList,1) + i1_u = UBOUND(SrcInitInputData%ValidOutList,1) + IF (.NOT. ALLOCATED(DstInitInputData%ValidOutList)) THEN + ALLOCATE(DstInitInputData%ValidOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%ValidOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%ValidOutList = SrcInitInputData%ValidOutList +ENDIF + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + DstInitInputData%OutSwtch = SrcInitInputData%OutSwtch + DstInitInputData%OutAll = SrcInitInputData%OutAll + DstInitInputData%OutRootName = SrcInitInputData%OutRootName + DstInitInputData%UnOutFile = SrcInitInputData%UnOutFile + DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%NStepWave = SrcInitInputData%NStepWave +IF (ALLOCATED(SrcInitInputData%WaveAcc)) THEN + i1_l = LBOUND(SrcInitInputData%WaveAcc,1) + i1_u = UBOUND(SrcInitInputData%WaveAcc,1) + i2_l = LBOUND(SrcInitInputData%WaveAcc,2) + i2_u = UBOUND(SrcInitInputData%WaveAcc,2) + i3_l = LBOUND(SrcInitInputData%WaveAcc,3) + i3_u = UBOUND(SrcInitInputData%WaveAcc,3) + IF (.NOT. ALLOCATED(DstInitInputData%WaveAcc)) THEN + ALLOCATE(DstInitInputData%WaveAcc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveAcc = SrcInitInputData%WaveAcc +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveDynP)) THEN + i1_l = LBOUND(SrcInitInputData%WaveDynP,1) + i1_u = UBOUND(SrcInitInputData%WaveDynP,1) + i2_l = LBOUND(SrcInitInputData%WaveDynP,2) + i2_u = UBOUND(SrcInitInputData%WaveDynP,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveDynP)) THEN + ALLOCATE(DstInitInputData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveDynP = SrcInitInputData%WaveDynP +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveVel)) THEN + i1_l = LBOUND(SrcInitInputData%WaveVel,1) + i1_u = UBOUND(SrcInitInputData%WaveVel,1) + i2_l = LBOUND(SrcInitInputData%WaveVel,2) + i2_u = UBOUND(SrcInitInputData%WaveVel,2) + i3_l = LBOUND(SrcInitInputData%WaveVel,3) + i3_u = UBOUND(SrcInitInputData%WaveVel,3) + IF (.NOT. ALLOCATED(DstInitInputData%WaveVel)) THEN + ALLOCATE(DstInitInputData%WaveVel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveVel = SrcInitInputData%WaveVel +ENDIF +IF (ALLOCATED(SrcInitInputData%nodeInWater)) THEN + i1_l = LBOUND(SrcInitInputData%nodeInWater,1) + i1_u = UBOUND(SrcInitInputData%nodeInWater,1) + i2_l = LBOUND(SrcInitInputData%nodeInWater,2) + i2_u = UBOUND(SrcInitInputData%nodeInWater,2) + IF (.NOT. ALLOCATED(DstInitInputData%nodeInWater)) THEN + ALLOCATE(DstInitInputData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%nodeInWater = SrcInitInputData%nodeInWater +ENDIF + END SUBROUTINE Morison_CopyInitInput + + SUBROUTINE Morison_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Morison_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%InpJoints)) THEN +DO i1 = LBOUND(InitInputData%InpJoints,1), UBOUND(InitInputData%InpJoints,1) + CALL Morison_Destroyjointtype( InitInputData%InpJoints(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%InpJoints) +ENDIF +IF (ALLOCATED(InitInputData%Nodes)) THEN +DO i1 = LBOUND(InitInputData%Nodes,1), UBOUND(InitInputData%Nodes,1) + CALL Morison_Destroynodetype( InitInputData%Nodes(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%Nodes) +ENDIF +IF (ALLOCATED(InitInputData%Elements)) THEN +DO i1 = LBOUND(InitInputData%Elements,1), UBOUND(InitInputData%Elements,1) + CALL Morison_Destroymembertype( InitInputData%Elements(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%Elements) +ENDIF +IF (ALLOCATED(InitInputData%AxialCoefs)) THEN +DO i1 = LBOUND(InitInputData%AxialCoefs,1), UBOUND(InitInputData%AxialCoefs,1) + CALL Morison_Destroyaxialcoeftype( InitInputData%AxialCoefs(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%AxialCoefs) +ENDIF +IF (ALLOCATED(InitInputData%MPropSets)) THEN +DO i1 = LBOUND(InitInputData%MPropSets,1), UBOUND(InitInputData%MPropSets,1) + CALL Morison_Destroymemberproptype( InitInputData%MPropSets(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%MPropSets) +ENDIF +IF (ALLOCATED(InitInputData%CoefDpths)) THEN +DO i1 = LBOUND(InitInputData%CoefDpths,1), UBOUND(InitInputData%CoefDpths,1) + CALL Morison_Destroycoefdpths( InitInputData%CoefDpths(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%CoefDpths) +ENDIF +IF (ALLOCATED(InitInputData%CoefMembers)) THEN +DO i1 = LBOUND(InitInputData%CoefMembers,1), UBOUND(InitInputData%CoefMembers,1) + CALL Morison_Destroycoefmembers( InitInputData%CoefMembers(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%CoefMembers) +ENDIF +IF (ALLOCATED(InitInputData%InpMembers)) THEN +DO i1 = LBOUND(InitInputData%InpMembers,1), UBOUND(InitInputData%InpMembers,1) + CALL Morison_Destroymemberinputtype( InitInputData%InpMembers(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%InpMembers) +ENDIF +IF (ALLOCATED(InitInputData%FilledGroups)) THEN +DO i1 = LBOUND(InitInputData%FilledGroups,1), UBOUND(InitInputData%FilledGroups,1) + CALL Morison_Destroyfilledgrouptype( InitInputData%FilledGroups(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%FilledGroups) +ENDIF +IF (ALLOCATED(InitInputData%MGDepths)) THEN +DO i1 = LBOUND(InitInputData%MGDepths,1), UBOUND(InitInputData%MGDepths,1) + CALL Morison_Destroymgdepthstype( InitInputData%MGDepths(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%MGDepths) +ENDIF +IF (ALLOCATED(InitInputData%MOutLst)) THEN +DO i1 = LBOUND(InitInputData%MOutLst,1), UBOUND(InitInputData%MOutLst,1) + CALL Morison_Destroymoutput( InitInputData%MOutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%MOutLst) +ENDIF +IF (ALLOCATED(InitInputData%JOutLst)) THEN +DO i1 = LBOUND(InitInputData%JOutLst,1), UBOUND(InitInputData%JOutLst,1) + CALL Morison_Destroyjoutput( InitInputData%JOutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitInputData%JOutLst) +ENDIF +IF (ALLOCATED(InitInputData%ValidOutList)) THEN + DEALLOCATE(InitInputData%ValidOutList) +ENDIF +IF (ALLOCATED(InitInputData%WaveAcc)) THEN + DEALLOCATE(InitInputData%WaveAcc) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF +IF (ALLOCATED(InitInputData%WaveDynP)) THEN + DEALLOCATE(InitInputData%WaveDynP) +ENDIF +IF (ALLOCATED(InitInputData%WaveVel)) THEN + DEALLOCATE(InitInputData%WaveVel) +ENDIF +IF (ALLOCATED(InitInputData%nodeInWater)) THEN + DEALLOCATE(InitInputData%nodeInWater) +ENDIF + END SUBROUTINE Morison_DestroyInitInput + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + 1 ! MSL2SWL + Int_BufSz = Int_BufSz + 1 ! NJoints + Int_BufSz = Int_BufSz + 1 ! NNodes + Int_BufSz = Int_BufSz + 1 ! TotalPossibleSuperMembers + Int_BufSz = Int_BufSz + 1 ! InpJoints allocated yes/no + IF ( ALLOCATED(InData%InpJoints) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InpJoints upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%InpJoints,1), UBOUND(InData%InpJoints,1) + Int_BufSz = Int_BufSz + 3 ! InpJoints: size of buffers for each call to pack subtype + CALL Morison_Packjointtype( Re_Buf, Db_Buf, Int_Buf, InData%InpJoints(i1), ErrStat2, ErrMsg2, .TRUE. ) ! InpJoints + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InpJoints + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InpJoints + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InpJoints + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no + IF ( ALLOCATED(InData%Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Nodes upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + Int_BufSz = Int_BufSz + 3 ! Nodes: size of buffers for each call to pack subtype + CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Nodes + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Nodes + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Nodes + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Nodes + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NElements + Int_BufSz = Int_BufSz + 1 ! Elements allocated yes/no + IF ( ALLOCATED(InData%Elements) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Elements upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Elements,1), UBOUND(InData%Elements,1) + Int_BufSz = Int_BufSz + 3 ! Elements: size of buffers for each call to pack subtype + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Elements(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Elements + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Elements + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Elements + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Elements + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NAxCoefs + Int_BufSz = Int_BufSz + 1 ! AxialCoefs allocated yes/no + IF ( ALLOCATED(InData%AxialCoefs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AxialCoefs upper/lower bounds for each dimension + DO i1 = LBOUND(InData%AxialCoefs,1), UBOUND(InData%AxialCoefs,1) + Int_BufSz = Int_BufSz + 3 ! AxialCoefs: size of buffers for each call to pack subtype + CALL Morison_Packaxialcoeftype( Re_Buf, Db_Buf, Int_Buf, InData%AxialCoefs(i1), ErrStat2, ErrMsg2, .TRUE. ) ! AxialCoefs + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AxialCoefs + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AxialCoefs + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AxialCoefs + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NPropSets + Int_BufSz = Int_BufSz + 1 ! MPropSets allocated yes/no + IF ( ALLOCATED(InData%MPropSets) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MPropSets upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MPropSets,1), UBOUND(InData%MPropSets,1) + Int_BufSz = Int_BufSz + 3 ! MPropSets: size of buffers for each call to pack subtype + CALL Morison_Packmemberproptype( Re_Buf, Db_Buf, Int_Buf, InData%MPropSets(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MPropSets + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MPropSets + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MPropSets + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MPropSets + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Re_BufSz = Re_BufSz + 1 ! SimplCd + Re_BufSz = Re_BufSz + 1 ! SimplCdMG + Re_BufSz = Re_BufSz + 1 ! SimplCa + Re_BufSz = Re_BufSz + 1 ! SimplCaMG + Re_BufSz = Re_BufSz + 1 ! SimplCp + Re_BufSz = Re_BufSz + 1 ! SimplCpMG + Re_BufSz = Re_BufSz + 1 ! SimplAxCa + Re_BufSz = Re_BufSz + 1 ! SimplAxCaMG + Re_BufSz = Re_BufSz + 1 ! SimplAxCp + Re_BufSz = Re_BufSz + 1 ! SimplAxCpMG + Int_BufSz = Int_BufSz + 1 ! NCoefDpth + Int_BufSz = Int_BufSz + 1 ! CoefDpths allocated yes/no + IF ( ALLOCATED(InData%CoefDpths) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CoefDpths upper/lower bounds for each dimension + DO i1 = LBOUND(InData%CoefDpths,1), UBOUND(InData%CoefDpths,1) + Int_BufSz = Int_BufSz + 3 ! CoefDpths: size of buffers for each call to pack subtype + CALL Morison_Packcoefdpths( Re_Buf, Db_Buf, Int_Buf, InData%CoefDpths(i1), ErrStat2, ErrMsg2, .TRUE. ) ! CoefDpths + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! CoefDpths + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! CoefDpths + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! CoefDpths + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NCoefMembers + Int_BufSz = Int_BufSz + 1 ! CoefMembers allocated yes/no + IF ( ALLOCATED(InData%CoefMembers) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CoefMembers upper/lower bounds for each dimension + DO i1 = LBOUND(InData%CoefMembers,1), UBOUND(InData%CoefMembers,1) + Int_BufSz = Int_BufSz + 3 ! CoefMembers: size of buffers for each call to pack subtype + CALL Morison_Packcoefmembers( Re_Buf, Db_Buf, Int_Buf, InData%CoefMembers(i1), ErrStat2, ErrMsg2, .TRUE. ) ! CoefMembers + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! CoefMembers + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! CoefMembers + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! CoefMembers + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NMembers + Int_BufSz = Int_BufSz + 1 ! InpMembers allocated yes/no + IF ( ALLOCATED(InData%InpMembers) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InpMembers upper/lower bounds for each dimension + DO i1 = LBOUND(InData%InpMembers,1), UBOUND(InData%InpMembers,1) + Int_BufSz = Int_BufSz + 3 ! InpMembers: size of buffers for each call to pack subtype + CALL Morison_Packmemberinputtype( Re_Buf, Db_Buf, Int_Buf, InData%InpMembers(i1), ErrStat2, ErrMsg2, .TRUE. ) ! InpMembers + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InpMembers + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InpMembers + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InpMembers + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NFillGroups + Int_BufSz = Int_BufSz + 1 ! FilledGroups allocated yes/no + IF ( ALLOCATED(InData%FilledGroups) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FilledGroups upper/lower bounds for each dimension + DO i1 = LBOUND(InData%FilledGroups,1), UBOUND(InData%FilledGroups,1) + Int_BufSz = Int_BufSz + 3 ! FilledGroups: size of buffers for each call to pack subtype + CALL Morison_Packfilledgrouptype( Re_Buf, Db_Buf, Int_Buf, InData%FilledGroups(i1), ErrStat2, ErrMsg2, .TRUE. ) ! FilledGroups + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FilledGroups + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FilledGroups + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FilledGroups + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NMGDepths + Int_BufSz = Int_BufSz + 1 ! MGDepths allocated yes/no + IF ( ALLOCATED(InData%MGDepths) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MGDepths upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MGDepths,1), UBOUND(InData%MGDepths,1) + Int_BufSz = Int_BufSz + 3 ! MGDepths: size of buffers for each call to pack subtype + CALL Morison_Packmgdepthstype( Re_Buf, Db_Buf, Int_Buf, InData%MGDepths(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MGDepths + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MGDepths + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MGDepths + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MGDepths + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Re_BufSz = Re_BufSz + 1 ! MGTop + Re_BufSz = Re_BufSz + 1 ! MGBottom + Int_BufSz = Int_BufSz + 1 ! NMOutputs + Int_BufSz = Int_BufSz + 1 ! MOutLst allocated yes/no + IF ( ALLOCATED(InData%MOutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MOutLst upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MOutLst,1), UBOUND(InData%MOutLst,1) + Int_BufSz = Int_BufSz + 3 ! MOutLst: size of buffers for each call to pack subtype + CALL Morison_Packmoutput( Re_Buf, Db_Buf, Int_Buf, InData%MOutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MOutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MOutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MOutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MOutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NJOutputs + Int_BufSz = Int_BufSz + 1 ! JOutLst allocated yes/no + IF ( ALLOCATED(InData%JOutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! JOutLst upper/lower bounds for each dimension + DO i1 = LBOUND(InData%JOutLst,1), UBOUND(InData%JOutLst,1) + Int_BufSz = Int_BufSz + 3 ! JOutLst: size of buffers for each call to pack subtype + CALL Morison_Packjoutput( Re_Buf, Db_Buf, Int_Buf, InData%JOutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! JOutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! JOutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! JOutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! JOutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + Int_BufSz = Int_BufSz + 1 ! ValidOutList allocated yes/no + IF ( ALLOCATED(InData%ValidOutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ValidOutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ValidOutList) ! ValidOutList + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1*LEN(InData%OutRootName) ! OutRootName + Int_BufSz = Int_BufSz + 1 ! UnOutFile + Int_BufSz = Int_BufSz + 1 ! UnSum + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! WaveAcc allocated yes/no + IF ( ALLOCATED(InData%WaveAcc) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc) ! WaveAcc + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP allocated yes/no + IF ( ALLOCATED(InData%WaveDynP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP) ! WaveDynP + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel allocated yes/no + IF ( ALLOCATED(InData%WaveVel) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel) ! WaveVel + END IF + Int_BufSz = Int_BufSz + 1 ! nodeInWater allocated yes/no + IF ( ALLOCATED(InData%nodeInWater) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! nodeInWater upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater + 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%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TotalPossibleSuperMembers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%InpJoints) ) 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%InpJoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpJoints,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InpJoints,1), UBOUND(InData%InpJoints,1) + CALL Morison_Packjointtype( Re_Buf, Db_Buf, Int_Buf, InData%InpJoints(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpJoints + 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%Nodes) ) 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%Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, OnlySize ) ! Nodes + 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 + IntKiBuf(Int_Xferred) = InData%NElements + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Elements) ) 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%Elements,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elements,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Elements,1), UBOUND(InData%Elements,1) + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Elements(i1), ErrStat2, ErrMsg2, OnlySize ) ! Elements + 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 + IntKiBuf(Int_Xferred) = InData%NAxCoefs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AxialCoefs) ) 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%AxialCoefs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxialCoefs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AxialCoefs,1), UBOUND(InData%AxialCoefs,1) + CALL Morison_Packaxialcoeftype( Re_Buf, Db_Buf, Int_Buf, InData%AxialCoefs(i1), ErrStat2, ErrMsg2, OnlySize ) ! AxialCoefs + 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 + IntKiBuf(Int_Xferred) = InData%NPropSets + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%MPropSets) ) 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%MPropSets,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MPropSets,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MPropSets,1), UBOUND(InData%MPropSets,1) + CALL Morison_Packmemberproptype( Re_Buf, Db_Buf, Int_Buf, InData%MPropSets(i1), ErrStat2, ErrMsg2, OnlySize ) ! MPropSets + 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 + ReKiBuf(Re_Xferred) = InData%SimplCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplCdMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplCaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplCpMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCaMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCpMG + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NCoefDpth + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CoefDpths) ) 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%CoefDpths,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CoefDpths,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CoefDpths,1), UBOUND(InData%CoefDpths,1) + CALL Morison_Packcoefdpths( Re_Buf, Db_Buf, Int_Buf, InData%CoefDpths(i1), ErrStat2, ErrMsg2, OnlySize ) ! CoefDpths + 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 + IntKiBuf(Int_Xferred) = InData%NCoefMembers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%CoefMembers) ) 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%CoefMembers,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CoefMembers,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CoefMembers,1), UBOUND(InData%CoefMembers,1) + CALL Morison_Packcoefmembers( Re_Buf, Db_Buf, Int_Buf, InData%CoefMembers(i1), ErrStat2, ErrMsg2, OnlySize ) ! CoefMembers + 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 + IntKiBuf(Int_Xferred) = InData%NMembers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%InpMembers) ) 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%InpMembers,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpMembers,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InpMembers,1), UBOUND(InData%InpMembers,1) + CALL Morison_Packmemberinputtype( Re_Buf, Db_Buf, Int_Buf, InData%InpMembers(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpMembers + 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 + IntKiBuf(Int_Xferred) = InData%NFillGroups + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FilledGroups) ) 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%FilledGroups,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FilledGroups,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FilledGroups,1), UBOUND(InData%FilledGroups,1) + CALL Morison_Packfilledgrouptype( Re_Buf, Db_Buf, Int_Buf, InData%FilledGroups(i1), ErrStat2, ErrMsg2, OnlySize ) ! FilledGroups + 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 + IntKiBuf(Int_Xferred) = InData%NMGDepths + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%MGDepths) ) 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%MGDepths,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MGDepths,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MGDepths,1), UBOUND(InData%MGDepths,1) + CALL Morison_Packmgdepthstype( Re_Buf, Db_Buf, Int_Buf, InData%MGDepths(i1), ErrStat2, ErrMsg2, OnlySize ) ! MGDepths + 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 + ReKiBuf(Re_Xferred) = InData%MGTop + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MGBottom + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NMOutputs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%MOutLst) ) 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%MOutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MOutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MOutLst,1), UBOUND(InData%MOutLst,1) + CALL Morison_Packmoutput( Re_Buf, Db_Buf, Int_Buf, InData%MOutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! MOutLst + 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 + IntKiBuf(Int_Xferred) = InData%NJOutputs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%JOutLst) ) 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%JOutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JOutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%JOutLst,1), UBOUND(InData%JOutLst,1) + CALL Morison_Packjoutput( Re_Buf, Db_Buf, Int_Buf, InData%JOutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! JOutLst + 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 + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IF ( .NOT. ALLOCATED(InData%ValidOutList) ) 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%ValidOutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ValidOutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ValidOutList,1), UBOUND(InData%ValidOutList,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%ValidOutList(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutRootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutRootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveAcc) ) 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%WaveAcc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc,3), UBOUND(InData%WaveAcc,3) + DO i2 = LBOUND(InData%WaveAcc,2), UBOUND(InData%WaveAcc,2) + DO i1 = LBOUND(InData%WaveAcc,1), UBOUND(InData%WaveAcc,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP) ) 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%WaveDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP,2), UBOUND(InData%WaveDynP,2) + DO i1 = LBOUND(InData%WaveDynP,1), UBOUND(InData%WaveDynP,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel) ) 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%WaveVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel,3), UBOUND(InData%WaveVel,3) + DO i2 = LBOUND(InData%WaveVel,2), UBOUND(InData%WaveVel,2) + DO i1 = LBOUND(InData%WaveVel,1), UBOUND(InData%WaveVel,1) + ReKiBuf(Re_Xferred) = InData%WaveVel(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%nodeInWater) ) 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%nodeInWater,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%nodeInWater,2), UBOUND(InData%nodeInWater,2) + DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) + IntKiBuf(Int_Xferred) = InData%nodeInWater(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE Morison_PackInitInput + + SUBROUTINE Morison_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(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_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%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MSL2SWL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NJoints = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TotalPossibleSuperMembers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpJoints 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%InpJoints)) DEALLOCATE(OutData%InpJoints) + ALLOCATE(OutData%InpJoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InpJoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InpJoints,1), UBOUND(OutData%InpJoints,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 Morison_Unpackjointtype( Re_Buf, Db_Buf, Int_Buf, OutData%InpJoints(i1), ErrStat2, ErrMsg2 ) ! InpJoints + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes 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%Nodes)) DEALLOCATE(OutData%Nodes) + ALLOCATE(OutData%Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Nodes,1), UBOUND(OutData%Nodes,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 Morison_Unpacknodetype( Re_Buf, Db_Buf, Int_Buf, OutData%Nodes(i1), ErrStat2, ErrMsg2 ) ! Nodes + 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 DO + END IF + OutData%NElements = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elements 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%Elements)) DEALLOCATE(OutData%Elements) + ALLOCATE(OutData%Elements(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elements.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Elements,1), UBOUND(OutData%Elements,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 Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Elements(i1), ErrStat2, ErrMsg2 ) ! Elements + 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 DO + END IF + OutData%NAxCoefs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxialCoefs 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%AxialCoefs)) DEALLOCATE(OutData%AxialCoefs) + ALLOCATE(OutData%AxialCoefs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxialCoefs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AxialCoefs,1), UBOUND(OutData%AxialCoefs,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 Morison_Unpackaxialcoeftype( Re_Buf, Db_Buf, Int_Buf, OutData%AxialCoefs(i1), ErrStat2, ErrMsg2 ) ! AxialCoefs + 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 DO + END IF + OutData%NPropSets = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MPropSets 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%MPropSets)) DEALLOCATE(OutData%MPropSets) + ALLOCATE(OutData%MPropSets(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MPropSets,1), UBOUND(OutData%MPropSets,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 Morison_Unpackmemberproptype( Re_Buf, Db_Buf, Int_Buf, OutData%MPropSets(i1), ErrStat2, ErrMsg2 ) ! MPropSets + 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 DO + END IF + OutData%SimplCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplCdMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplCaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplCpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCaMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCpMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NCoefDpth = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CoefDpths 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%CoefDpths)) DEALLOCATE(OutData%CoefDpths) + ALLOCATE(OutData%CoefDpths(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefDpths.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CoefDpths,1), UBOUND(OutData%CoefDpths,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 Morison_Unpackcoefdpths( Re_Buf, Db_Buf, Int_Buf, OutData%CoefDpths(i1), ErrStat2, ErrMsg2 ) ! CoefDpths + 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 DO + END IF + OutData%NCoefMembers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CoefMembers 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%CoefMembers)) DEALLOCATE(OutData%CoefMembers) + ALLOCATE(OutData%CoefMembers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefMembers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CoefMembers,1), UBOUND(OutData%CoefMembers,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 Morison_Unpackcoefmembers( Re_Buf, Db_Buf, Int_Buf, OutData%CoefMembers(i1), ErrStat2, ErrMsg2 ) ! CoefMembers + 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 DO + END IF + OutData%NMembers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpMembers 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%InpMembers)) DEALLOCATE(OutData%InpMembers) + ALLOCATE(OutData%InpMembers(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InpMembers.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InpMembers,1), UBOUND(OutData%InpMembers,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 Morison_Unpackmemberinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%InpMembers(i1), ErrStat2, ErrMsg2 ) ! InpMembers + 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 DO + END IF + OutData%NFillGroups = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FilledGroups 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%FilledGroups)) DEALLOCATE(OutData%FilledGroups) + ALLOCATE(OutData%FilledGroups(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FilledGroups.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FilledGroups,1), UBOUND(OutData%FilledGroups,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 Morison_Unpackfilledgrouptype( Re_Buf, Db_Buf, Int_Buf, OutData%FilledGroups(i1), ErrStat2, ErrMsg2 ) ! FilledGroups + 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 DO + END IF + OutData%NMGDepths = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MGDepths 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%MGDepths)) DEALLOCATE(OutData%MGDepths) + ALLOCATE(OutData%MGDepths(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MGDepths.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MGDepths,1), UBOUND(OutData%MGDepths,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 Morison_Unpackmgdepthstype( Re_Buf, Db_Buf, Int_Buf, OutData%MGDepths(i1), ErrStat2, ErrMsg2 ) ! MGDepths + 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 DO + END IF + OutData%MGTop = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MGBottom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NMOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MOutLst 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%MOutLst)) DEALLOCATE(OutData%MOutLst) + ALLOCATE(OutData%MOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MOutLst,1), UBOUND(OutData%MOutLst,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 Morison_Unpackmoutput( Re_Buf, Db_Buf, Int_Buf, OutData%MOutLst(i1), ErrStat2, ErrMsg2 ) ! MOutLst + 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 DO + END IF + OutData%NJOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JOutLst 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%JOutLst)) DEALLOCATE(OutData%JOutLst) + ALLOCATE(OutData%JOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%JOutLst,1), UBOUND(OutData%JOutLst,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 Morison_Unpackjoutput( Re_Buf, Db_Buf, Int_Buf, OutData%JOutLst(i1), ErrStat2, ErrMsg2 ) ! JOutLst + 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 DO + END IF + i1_l = LBOUND(OutData%OutList,1) + i1_u = UBOUND(OutData%OutList,1) + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ValidOutList 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%ValidOutList)) DEALLOCATE(OutData%ValidOutList) + ALLOCATE(OutData%ValidOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ValidOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ValidOutList,1), UBOUND(OutData%ValidOutList,1) + OutData%ValidOutList(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%ValidOutList(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutRootName) + OutData%OutRootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc 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%WaveAcc)) DEALLOCATE(OutData%WaveAcc) + ALLOCATE(OutData%WaveAcc(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%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc,3), UBOUND(OutData%WaveAcc,3) + DO i2 = LBOUND(OutData%WaveAcc,2), UBOUND(OutData%WaveAcc,2) + DO i1 = LBOUND(OutData%WaveAcc,1), UBOUND(OutData%WaveAcc,1) + OutData%WaveAcc(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 ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDynP 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%WaveDynP)) DEALLOCATE(OutData%WaveDynP) + ALLOCATE(OutData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP,2), UBOUND(OutData%WaveDynP,2) + DO i1 = LBOUND(OutData%WaveDynP,1), UBOUND(OutData%WaveDynP,1) + OutData%WaveDynP(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel 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%WaveVel)) DEALLOCATE(OutData%WaveVel) + ALLOCATE(OutData%WaveVel(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%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel,3), UBOUND(OutData%WaveVel,3) + DO i2 = LBOUND(OutData%WaveVel,2), UBOUND(OutData%WaveVel,2) + DO i1 = LBOUND(OutData%WaveVel,1), UBOUND(OutData%WaveVel,1) + OutData%WaveVel(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 ! nodeInWater 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%nodeInWater)) DEALLOCATE(OutData%nodeInWater) + ALLOCATE(OutData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%nodeInWater,2), UBOUND(OutData%nodeInWater,2) + DO i1 = LBOUND(OutData%nodeInWater,1), UBOUND(OutData%nodeInWater,1) + OutData%nodeInWater(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE Morison_UnPackInitInput + + SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_InitOutputType), INTENT(INOUT) :: SrcInitOutputData + TYPE(Morison_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 = 'Morison_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInitOutputData%DistribMesh, DstInitOutputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInitOutputData%LumpedMesh, DstInitOutputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%Morison_Rad)) THEN + i1_l = LBOUND(SrcInitOutputData%Morison_Rad,1) + i1_u = UBOUND(SrcInitOutputData%Morison_Rad,1) + IF (.NOT. ALLOCATED(DstInitOutputData%Morison_Rad)) THEN + ALLOCATE(DstInitOutputData%Morison_Rad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%Morison_Rad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%Morison_Rad = SrcInitOutputData%Morison_Rad +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE Morison_CopyInitOutput + + SUBROUTINE Morison_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Morison_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InitOutputData%DistribMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InitOutputData%LumpedMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%Morison_Rad)) THEN + DEALLOCATE(InitOutputData%Morison_Rad) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE Morison_DestroyInitOutput + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 ! DistribMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Morison_Rad allocated yes/no + IF ( ALLOCATED(InData%Morison_Rad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Morison_Rad upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Morison_Rad) ! Morison_Rad + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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 MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh + 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 MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + 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%Morison_Rad) ) 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%Morison_Rad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Morison_Rad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Morison_Rad,1), UBOUND(InData%Morison_Rad,1) + ReKiBuf(Re_Xferred) = InData%Morison_Rad(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE Morison_PackInitOutput + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh + 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 MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + 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 ! Morison_Rad 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%Morison_Rad)) DEALLOCATE(OutData%Morison_Rad) + ALLOCATE(OutData%Morison_Rad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Morison_Rad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Morison_Rad,1), UBOUND(OutData%Morison_Rad,1) + OutData%Morison_Rad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE Morison_UnPackInitOutput + + SUBROUTINE Morison_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Morison_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 = 'Morison_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Morison_CopyContState + + SUBROUTINE Morison_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Morison_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyContState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 Morison_PackContState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackContState + + SUBROUTINE Morison_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Morison_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 = 'Morison_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE Morison_CopyDiscState + + SUBROUTINE Morison_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Morison_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyDiscState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 Morison_PackDiscState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackDiscState + + SUBROUTINE Morison_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Morison_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 = 'Morison_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Morison_CopyConstrState + + SUBROUTINE Morison_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Morison_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyConstrState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 Morison_PackConstrState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Morison_UnPackConstrState + + SUBROUTINE Morison_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Morison_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 = 'Morison_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Morison_CopyOtherState + + SUBROUTINE Morison_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Morison_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyOtherState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackOtherState + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_UnPackOtherState + + SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%D_F_D)) THEN + i1_l = LBOUND(SrcMiscData%D_F_D,1) + i1_u = UBOUND(SrcMiscData%D_F_D,1) + i2_l = LBOUND(SrcMiscData%D_F_D,2) + i2_u = UBOUND(SrcMiscData%D_F_D,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_D)) THEN + ALLOCATE(DstMiscData%D_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_D = SrcMiscData%D_F_D +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_I)) THEN + i1_l = LBOUND(SrcMiscData%D_F_I,1) + i1_u = UBOUND(SrcMiscData%D_F_I,1) + i2_l = LBOUND(SrcMiscData%D_F_I,2) + i2_u = UBOUND(SrcMiscData%D_F_I,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_I)) THEN + ALLOCATE(DstMiscData%D_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_I = SrcMiscData%D_F_I +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_B)) THEN + i1_l = LBOUND(SrcMiscData%D_F_B,1) + i1_u = UBOUND(SrcMiscData%D_F_B,1) + i2_l = LBOUND(SrcMiscData%D_F_B,2) + i2_u = UBOUND(SrcMiscData%D_F_B,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_B)) THEN + ALLOCATE(DstMiscData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_B = SrcMiscData%D_F_B +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_AM)) THEN + i1_l = LBOUND(SrcMiscData%D_F_AM,1) + i1_u = UBOUND(SrcMiscData%D_F_AM,1) + i2_l = LBOUND(SrcMiscData%D_F_AM,2) + i2_u = UBOUND(SrcMiscData%D_F_AM,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_AM)) THEN + ALLOCATE(DstMiscData%D_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_AM = SrcMiscData%D_F_AM +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_AM_M)) THEN + i1_l = LBOUND(SrcMiscData%D_F_AM_M,1) + i1_u = UBOUND(SrcMiscData%D_F_AM_M,1) + i2_l = LBOUND(SrcMiscData%D_F_AM_M,2) + i2_u = UBOUND(SrcMiscData%D_F_AM_M,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_M)) THEN + ALLOCATE(DstMiscData%D_F_AM_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_AM_M = SrcMiscData%D_F_AM_M +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_AM_MG)) THEN + i1_l = LBOUND(SrcMiscData%D_F_AM_MG,1) + i1_u = UBOUND(SrcMiscData%D_F_AM_MG,1) + i2_l = LBOUND(SrcMiscData%D_F_AM_MG,2) + i2_u = UBOUND(SrcMiscData%D_F_AM_MG,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_MG)) THEN + ALLOCATE(DstMiscData%D_F_AM_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_AM_MG = SrcMiscData%D_F_AM_MG +ENDIF +IF (ALLOCATED(SrcMiscData%D_F_AM_F)) THEN + i1_l = LBOUND(SrcMiscData%D_F_AM_F,1) + i1_u = UBOUND(SrcMiscData%D_F_AM_F,1) + i2_l = LBOUND(SrcMiscData%D_F_AM_F,2) + i2_u = UBOUND(SrcMiscData%D_F_AM_F,2) + IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_F)) THEN + ALLOCATE(DstMiscData%D_F_AM_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_F_AM_F = SrcMiscData%D_F_AM_F +ENDIF +IF (ALLOCATED(SrcMiscData%D_FV)) THEN + i1_l = LBOUND(SrcMiscData%D_FV,1) + i1_u = UBOUND(SrcMiscData%D_FV,1) + i2_l = LBOUND(SrcMiscData%D_FV,2) + i2_u = UBOUND(SrcMiscData%D_FV,2) + IF (.NOT. ALLOCATED(DstMiscData%D_FV)) THEN + ALLOCATE(DstMiscData%D_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_FV = SrcMiscData%D_FV +ENDIF +IF (ALLOCATED(SrcMiscData%D_FA)) THEN + i1_l = LBOUND(SrcMiscData%D_FA,1) + i1_u = UBOUND(SrcMiscData%D_FA,1) + i2_l = LBOUND(SrcMiscData%D_FA,2) + i2_u = UBOUND(SrcMiscData%D_FA,2) + IF (.NOT. ALLOCATED(DstMiscData%D_FA)) THEN + ALLOCATE(DstMiscData%D_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_FA = SrcMiscData%D_FA +ENDIF +IF (ALLOCATED(SrcMiscData%D_FDynP)) THEN + i1_l = LBOUND(SrcMiscData%D_FDynP,1) + i1_u = UBOUND(SrcMiscData%D_FDynP,1) + IF (.NOT. ALLOCATED(DstMiscData%D_FDynP)) THEN + ALLOCATE(DstMiscData%D_FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%D_FDynP = SrcMiscData%D_FDynP +ENDIF +IF (ALLOCATED(SrcMiscData%L_F_B)) THEN + i1_l = LBOUND(SrcMiscData%L_F_B,1) + i1_u = UBOUND(SrcMiscData%L_F_B,1) + i2_l = LBOUND(SrcMiscData%L_F_B,2) + i2_u = UBOUND(SrcMiscData%L_F_B,2) + IF (.NOT. ALLOCATED(DstMiscData%L_F_B)) THEN + ALLOCATE(DstMiscData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_F_B = SrcMiscData%L_F_B +ENDIF +IF (ALLOCATED(SrcMiscData%L_F_D)) THEN + i1_l = LBOUND(SrcMiscData%L_F_D,1) + i1_u = UBOUND(SrcMiscData%L_F_D,1) + i2_l = LBOUND(SrcMiscData%L_F_D,2) + i2_u = UBOUND(SrcMiscData%L_F_D,2) + IF (.NOT. ALLOCATED(DstMiscData%L_F_D)) THEN + ALLOCATE(DstMiscData%L_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_F_D = SrcMiscData%L_F_D +ENDIF +IF (ALLOCATED(SrcMiscData%L_F_I)) THEN + i1_l = LBOUND(SrcMiscData%L_F_I,1) + i1_u = UBOUND(SrcMiscData%L_F_I,1) + i2_l = LBOUND(SrcMiscData%L_F_I,2) + i2_u = UBOUND(SrcMiscData%L_F_I,2) + IF (.NOT. ALLOCATED(DstMiscData%L_F_I)) THEN + ALLOCATE(DstMiscData%L_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_F_I = SrcMiscData%L_F_I +ENDIF +IF (ALLOCATED(SrcMiscData%L_F_DP)) THEN + i1_l = LBOUND(SrcMiscData%L_F_DP,1) + i1_u = UBOUND(SrcMiscData%L_F_DP,1) + i2_l = LBOUND(SrcMiscData%L_F_DP,2) + i2_u = UBOUND(SrcMiscData%L_F_DP,2) + IF (.NOT. ALLOCATED(DstMiscData%L_F_DP)) THEN + ALLOCATE(DstMiscData%L_F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_F_DP = SrcMiscData%L_F_DP +ENDIF +IF (ALLOCATED(SrcMiscData%L_F_AM)) THEN + i1_l = LBOUND(SrcMiscData%L_F_AM,1) + i1_u = UBOUND(SrcMiscData%L_F_AM,1) + i2_l = LBOUND(SrcMiscData%L_F_AM,2) + i2_u = UBOUND(SrcMiscData%L_F_AM,2) + IF (.NOT. ALLOCATED(DstMiscData%L_F_AM)) THEN + ALLOCATE(DstMiscData%L_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_AM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_F_AM = SrcMiscData%L_F_AM +ENDIF +IF (ALLOCATED(SrcMiscData%L_FV)) THEN + i1_l = LBOUND(SrcMiscData%L_FV,1) + i1_u = UBOUND(SrcMiscData%L_FV,1) + i2_l = LBOUND(SrcMiscData%L_FV,2) + i2_u = UBOUND(SrcMiscData%L_FV,2) + IF (.NOT. ALLOCATED(DstMiscData%L_FV)) THEN + ALLOCATE(DstMiscData%L_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_FV = SrcMiscData%L_FV +ENDIF +IF (ALLOCATED(SrcMiscData%L_FA)) THEN + i1_l = LBOUND(SrcMiscData%L_FA,1) + i1_u = UBOUND(SrcMiscData%L_FA,1) + i2_l = LBOUND(SrcMiscData%L_FA,2) + i2_u = UBOUND(SrcMiscData%L_FA,2) + IF (.NOT. ALLOCATED(DstMiscData%L_FA)) THEN + ALLOCATE(DstMiscData%L_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_FA = SrcMiscData%L_FA +ENDIF +IF (ALLOCATED(SrcMiscData%L_FDynP)) THEN + i1_l = LBOUND(SrcMiscData%L_FDynP,1) + i1_u = UBOUND(SrcMiscData%L_FDynP,1) + IF (.NOT. ALLOCATED(DstMiscData%L_FDynP)) THEN + ALLOCATE(DstMiscData%L_FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%L_FDynP = SrcMiscData%L_FDynP +ENDIF + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + END SUBROUTINE Morison_CopyMisc + + SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Morison_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%D_F_D)) THEN + DEALLOCATE(MiscData%D_F_D) +ENDIF +IF (ALLOCATED(MiscData%D_F_I)) THEN + DEALLOCATE(MiscData%D_F_I) +ENDIF +IF (ALLOCATED(MiscData%D_F_B)) THEN + DEALLOCATE(MiscData%D_F_B) +ENDIF +IF (ALLOCATED(MiscData%D_F_AM)) THEN + DEALLOCATE(MiscData%D_F_AM) +ENDIF +IF (ALLOCATED(MiscData%D_F_AM_M)) THEN + DEALLOCATE(MiscData%D_F_AM_M) +ENDIF +IF (ALLOCATED(MiscData%D_F_AM_MG)) THEN + DEALLOCATE(MiscData%D_F_AM_MG) +ENDIF +IF (ALLOCATED(MiscData%D_F_AM_F)) THEN + DEALLOCATE(MiscData%D_F_AM_F) +ENDIF +IF (ALLOCATED(MiscData%D_FV)) THEN + DEALLOCATE(MiscData%D_FV) +ENDIF +IF (ALLOCATED(MiscData%D_FA)) THEN + DEALLOCATE(MiscData%D_FA) +ENDIF +IF (ALLOCATED(MiscData%D_FDynP)) THEN + DEALLOCATE(MiscData%D_FDynP) +ENDIF +IF (ALLOCATED(MiscData%L_F_B)) THEN + DEALLOCATE(MiscData%L_F_B) +ENDIF +IF (ALLOCATED(MiscData%L_F_D)) THEN + DEALLOCATE(MiscData%L_F_D) +ENDIF +IF (ALLOCATED(MiscData%L_F_I)) THEN + DEALLOCATE(MiscData%L_F_I) +ENDIF +IF (ALLOCATED(MiscData%L_F_DP)) THEN + DEALLOCATE(MiscData%L_F_DP) +ENDIF +IF (ALLOCATED(MiscData%L_F_AM)) THEN + DEALLOCATE(MiscData%L_F_AM) +ENDIF +IF (ALLOCATED(MiscData%L_FV)) THEN + DEALLOCATE(MiscData%L_FV) +ENDIF +IF (ALLOCATED(MiscData%L_FA)) THEN + DEALLOCATE(MiscData%L_FA) +ENDIF +IF (ALLOCATED(MiscData%L_FDynP)) THEN + DEALLOCATE(MiscData%L_FDynP) +ENDIF + END SUBROUTINE Morison_DestroyMisc + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 ! D_F_D allocated yes/no + IF ( ALLOCATED(InData%D_F_D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_D) ! D_F_D + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_I allocated yes/no + IF ( ALLOCATED(InData%D_F_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_I) ! D_F_I + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_B allocated yes/no + IF ( ALLOCATED(InData%D_F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_B) ! D_F_B + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_AM allocated yes/no + IF ( ALLOCATED(InData%D_F_AM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_AM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM) ! D_F_AM + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_AM_M allocated yes/no + IF ( ALLOCATED(InData%D_F_AM_M) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_M) ! D_F_AM_M + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_AM_MG allocated yes/no + IF ( ALLOCATED(InData%D_F_AM_MG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_MG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_MG) ! D_F_AM_MG + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_AM_F allocated yes/no + IF ( ALLOCATED(InData%D_F_AM_F) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_F upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_F) ! D_F_AM_F + END IF + Int_BufSz = Int_BufSz + 1 ! D_FV allocated yes/no + IF ( ALLOCATED(InData%D_FV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_FV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_FV) ! D_FV + END IF + Int_BufSz = Int_BufSz + 1 ! D_FA allocated yes/no + IF ( ALLOCATED(InData%D_FA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_FA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_FA) ! D_FA + END IF + Int_BufSz = Int_BufSz + 1 ! D_FDynP allocated yes/no + IF ( ALLOCATED(InData%D_FDynP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! D_FDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_FDynP) ! D_FDynP + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_B allocated yes/no + IF ( ALLOCATED(InData%L_F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_B) ! L_F_B + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_D allocated yes/no + IF ( ALLOCATED(InData%L_F_D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_D) ! L_F_D + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_I allocated yes/no + IF ( ALLOCATED(InData%L_F_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_I) ! L_F_I + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_DP allocated yes/no + IF ( ALLOCATED(InData%L_F_DP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_DP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_DP) ! L_F_DP + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_AM allocated yes/no + IF ( ALLOCATED(InData%L_F_AM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_AM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_AM) ! L_F_AM + END IF + Int_BufSz = Int_BufSz + 1 ! L_FV allocated yes/no + IF ( ALLOCATED(InData%L_FV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_FV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_FV) ! L_FV + END IF + Int_BufSz = Int_BufSz + 1 ! L_FA allocated yes/no + IF ( ALLOCATED(InData%L_FA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_FA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_FA) ! L_FA + END IF + Int_BufSz = Int_BufSz + 1 ! L_FDynP allocated yes/no + IF ( ALLOCATED(InData%L_FDynP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! L_FDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_FDynP) ! L_FDynP + END IF + Int_BufSz = Int_BufSz + 1 ! LastIndWave + 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%D_F_D) ) 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%D_F_D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_D,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_D,2), UBOUND(InData%D_F_D,2) + DO i1 = LBOUND(InData%D_F_D,1), UBOUND(InData%D_F_D,1) + ReKiBuf(Re_Xferred) = InData%D_F_D(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_I) ) 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%D_F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_I,2), UBOUND(InData%D_F_I,2) + DO i1 = LBOUND(InData%D_F_I,1), UBOUND(InData%D_F_I,1) + ReKiBuf(Re_Xferred) = InData%D_F_I(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_B) ) 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%D_F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_B,2), UBOUND(InData%D_F_B,2) + DO i1 = LBOUND(InData%D_F_B,1), UBOUND(InData%D_F_B,1) + ReKiBuf(Re_Xferred) = InData%D_F_B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_AM) ) 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%D_F_AM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_AM,2), UBOUND(InData%D_F_AM,2) + DO i1 = LBOUND(InData%D_F_AM,1), UBOUND(InData%D_F_AM,1) + ReKiBuf(Re_Xferred) = InData%D_F_AM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_AM_M) ) 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%D_F_AM_M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_M,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_AM_M,2), UBOUND(InData%D_F_AM_M,2) + DO i1 = LBOUND(InData%D_F_AM_M,1), UBOUND(InData%D_F_AM_M,1) + ReKiBuf(Re_Xferred) = InData%D_F_AM_M(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_AM_MG) ) 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%D_F_AM_MG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_MG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_MG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_MG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_AM_MG,2), UBOUND(InData%D_F_AM_MG,2) + DO i1 = LBOUND(InData%D_F_AM_MG,1), UBOUND(InData%D_F_AM_MG,1) + ReKiBuf(Re_Xferred) = InData%D_F_AM_MG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_AM_F) ) 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%D_F_AM_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_F,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_F,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_F,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_AM_F,2), UBOUND(InData%D_F_AM_F,2) + DO i1 = LBOUND(InData%D_F_AM_F,1), UBOUND(InData%D_F_AM_F,1) + ReKiBuf(Re_Xferred) = InData%D_F_AM_F(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_FV) ) 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%D_FV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FV,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_FV,2), UBOUND(InData%D_FV,2) + DO i1 = LBOUND(InData%D_FV,1), UBOUND(InData%D_FV,1) + ReKiBuf(Re_Xferred) = InData%D_FV(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_FA) ) 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%D_FA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_FA,2), UBOUND(InData%D_FA,2) + DO i1 = LBOUND(InData%D_FA,1), UBOUND(InData%D_FA,1) + ReKiBuf(Re_Xferred) = InData%D_FA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_FDynP) ) 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%D_FDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FDynP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%D_FDynP,1), UBOUND(InData%D_FDynP,1) + ReKiBuf(Re_Xferred) = InData%D_FDynP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_B) ) 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%L_F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_B,2), UBOUND(InData%L_F_B,2) + DO i1 = LBOUND(InData%L_F_B,1), UBOUND(InData%L_F_B,1) + ReKiBuf(Re_Xferred) = InData%L_F_B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_D) ) 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%L_F_D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_D,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_D,2), UBOUND(InData%L_F_D,2) + DO i1 = LBOUND(InData%L_F_D,1), UBOUND(InData%L_F_D,1) + ReKiBuf(Re_Xferred) = InData%L_F_D(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_I) ) 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%L_F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_I,2), UBOUND(InData%L_F_I,2) + DO i1 = LBOUND(InData%L_F_I,1), UBOUND(InData%L_F_I,1) + ReKiBuf(Re_Xferred) = InData%L_F_I(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_DP) ) 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%L_F_DP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_DP,2), UBOUND(InData%L_F_DP,2) + DO i1 = LBOUND(InData%L_F_DP,1), UBOUND(InData%L_F_DP,1) + ReKiBuf(Re_Xferred) = InData%L_F_DP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_AM) ) 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%L_F_AM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_AM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_AM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_AM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_AM,2), UBOUND(InData%L_F_AM,2) + DO i1 = LBOUND(InData%L_F_AM,1), UBOUND(InData%L_F_AM,1) + ReKiBuf(Re_Xferred) = InData%L_F_AM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_FV) ) 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%L_FV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FV,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_FV,2), UBOUND(InData%L_FV,2) + DO i1 = LBOUND(InData%L_FV,1), UBOUND(InData%L_FV,1) + ReKiBuf(Re_Xferred) = InData%L_FV(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_FA) ) 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%L_FA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_FA,2), UBOUND(InData%L_FA,2) + DO i1 = LBOUND(InData%L_FA,1), UBOUND(InData%L_FA,1) + ReKiBuf(Re_Xferred) = InData%L_FA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_FDynP) ) 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%L_FDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FDynP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%L_FDynP,1), UBOUND(InData%L_FDynP,1) + ReKiBuf(Re_Xferred) = InData%L_FDynP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%LastIndWave + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackMisc + + SUBROUTINE Morison_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(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_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 ! D_F_D 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%D_F_D)) DEALLOCATE(OutData%D_F_D) + ALLOCATE(OutData%D_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_D,2), UBOUND(OutData%D_F_D,2) + DO i1 = LBOUND(OutData%D_F_D,1), UBOUND(OutData%D_F_D,1) + OutData%D_F_D(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_I 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%D_F_I)) DEALLOCATE(OutData%D_F_I) + ALLOCATE(OutData%D_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_I,2), UBOUND(OutData%D_F_I,2) + DO i1 = LBOUND(OutData%D_F_I,1), UBOUND(OutData%D_F_I,1) + OutData%D_F_I(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_B 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%D_F_B)) DEALLOCATE(OutData%D_F_B) + ALLOCATE(OutData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_B,2), UBOUND(OutData%D_F_B,2) + DO i1 = LBOUND(OutData%D_F_B,1), UBOUND(OutData%D_F_B,1) + OutData%D_F_B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM 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%D_F_AM)) DEALLOCATE(OutData%D_F_AM) + ALLOCATE(OutData%D_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_AM,2), UBOUND(OutData%D_F_AM,2) + DO i1 = LBOUND(OutData%D_F_AM,1), UBOUND(OutData%D_F_AM,1) + OutData%D_F_AM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_M 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%D_F_AM_M)) DEALLOCATE(OutData%D_F_AM_M) + ALLOCATE(OutData%D_F_AM_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_AM_M,2), UBOUND(OutData%D_F_AM_M,2) + DO i1 = LBOUND(OutData%D_F_AM_M,1), UBOUND(OutData%D_F_AM_M,1) + OutData%D_F_AM_M(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_MG 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%D_F_AM_MG)) DEALLOCATE(OutData%D_F_AM_MG) + ALLOCATE(OutData%D_F_AM_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_AM_MG,2), UBOUND(OutData%D_F_AM_MG,2) + DO i1 = LBOUND(OutData%D_F_AM_MG,1), UBOUND(OutData%D_F_AM_MG,1) + OutData%D_F_AM_MG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_F 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%D_F_AM_F)) DEALLOCATE(OutData%D_F_AM_F) + ALLOCATE(OutData%D_F_AM_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_AM_F,2), UBOUND(OutData%D_F_AM_F,2) + DO i1 = LBOUND(OutData%D_F_AM_F,1), UBOUND(OutData%D_F_AM_F,1) + OutData%D_F_AM_F(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FV 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%D_FV)) DEALLOCATE(OutData%D_FV) + ALLOCATE(OutData%D_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_FV,2), UBOUND(OutData%D_FV,2) + DO i1 = LBOUND(OutData%D_FV,1), UBOUND(OutData%D_FV,1) + OutData%D_FV(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FA 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%D_FA)) DEALLOCATE(OutData%D_FA) + ALLOCATE(OutData%D_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_FA,2), UBOUND(OutData%D_FA,2) + DO i1 = LBOUND(OutData%D_FA,1), UBOUND(OutData%D_FA,1) + OutData%D_FA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FDynP 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%D_FDynP)) DEALLOCATE(OutData%D_FDynP) + ALLOCATE(OutData%D_FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%D_FDynP,1), UBOUND(OutData%D_FDynP,1) + OutData%D_FDynP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_B 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%L_F_B)) DEALLOCATE(OutData%L_F_B) + ALLOCATE(OutData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_B,2), UBOUND(OutData%L_F_B,2) + DO i1 = LBOUND(OutData%L_F_B,1), UBOUND(OutData%L_F_B,1) + OutData%L_F_B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_D 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%L_F_D)) DEALLOCATE(OutData%L_F_D) + ALLOCATE(OutData%L_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_D,2), UBOUND(OutData%L_F_D,2) + DO i1 = LBOUND(OutData%L_F_D,1), UBOUND(OutData%L_F_D,1) + OutData%L_F_D(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_I 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%L_F_I)) DEALLOCATE(OutData%L_F_I) + ALLOCATE(OutData%L_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_I,2), UBOUND(OutData%L_F_I,2) + DO i1 = LBOUND(OutData%L_F_I,1), UBOUND(OutData%L_F_I,1) + OutData%L_F_I(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_DP 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%L_F_DP)) DEALLOCATE(OutData%L_F_DP) + ALLOCATE(OutData%L_F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_DP,2), UBOUND(OutData%L_F_DP,2) + DO i1 = LBOUND(OutData%L_F_DP,1), UBOUND(OutData%L_F_DP,1) + OutData%L_F_DP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_AM 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%L_F_AM)) DEALLOCATE(OutData%L_F_AM) + ALLOCATE(OutData%L_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_AM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_AM,2), UBOUND(OutData%L_F_AM,2) + DO i1 = LBOUND(OutData%L_F_AM,1), UBOUND(OutData%L_F_AM,1) + OutData%L_F_AM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FV 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%L_FV)) DEALLOCATE(OutData%L_FV) + ALLOCATE(OutData%L_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_FV,2), UBOUND(OutData%L_FV,2) + DO i1 = LBOUND(OutData%L_FV,1), UBOUND(OutData%L_FV,1) + OutData%L_FV(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FA 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%L_FA)) DEALLOCATE(OutData%L_FA) + ALLOCATE(OutData%L_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_FA,2), UBOUND(OutData%L_FA,2) + DO i1 = LBOUND(OutData%L_FA,1), UBOUND(OutData%L_FA,1) + OutData%L_FA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FDynP 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%L_FDynP)) DEALLOCATE(OutData%L_FDynP) + ALLOCATE(OutData%L_FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%L_FDynP,1), UBOUND(OutData%L_FDynP,1) + OutData%L_FDynP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_UnPackMisc + + SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%WtrDens = SrcParamData%WtrDens + DstParamData%NNodes = SrcParamData%NNodes +IF (ALLOCATED(SrcParamData%Nodes)) THEN + i1_l = LBOUND(SrcParamData%Nodes,1) + i1_u = UBOUND(SrcParamData%Nodes,1) + IF (.NOT. ALLOCATED(DstParamData%Nodes)) THEN + ALLOCATE(DstParamData%Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%Nodes,1), UBOUND(SrcParamData%Nodes,1) + CALL Morison_Copynodetype( SrcParamData%Nodes(i1), DstParamData%Nodes(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%D_F_I)) THEN + i1_l = LBOUND(SrcParamData%D_F_I,1) + i1_u = UBOUND(SrcParamData%D_F_I,1) + i2_l = LBOUND(SrcParamData%D_F_I,2) + i2_u = UBOUND(SrcParamData%D_F_I,2) + i3_l = LBOUND(SrcParamData%D_F_I,3) + i3_u = UBOUND(SrcParamData%D_F_I,3) + IF (.NOT. ALLOCATED(DstParamData%D_F_I)) THEN + ALLOCATE(DstParamData%D_F_I(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%D_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_F_I = SrcParamData%D_F_I +ENDIF +IF (ALLOCATED(SrcParamData%D_F_DP)) THEN + i1_l = LBOUND(SrcParamData%D_F_DP,1) + i1_u = UBOUND(SrcParamData%D_F_DP,1) + i2_l = LBOUND(SrcParamData%D_F_DP,2) + i2_u = UBOUND(SrcParamData%D_F_DP,2) + i3_l = LBOUND(SrcParamData%D_F_DP,3) + i3_u = UBOUND(SrcParamData%D_F_DP,3) + IF (.NOT. ALLOCATED(DstParamData%D_F_DP)) THEN + ALLOCATE(DstParamData%D_F_DP(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%D_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_F_DP = SrcParamData%D_F_DP +ENDIF +IF (ALLOCATED(SrcParamData%D_dragConst)) THEN + i1_l = LBOUND(SrcParamData%D_dragConst,1) + i1_u = UBOUND(SrcParamData%D_dragConst,1) + IF (.NOT. ALLOCATED(DstParamData%D_dragConst)) THEN + ALLOCATE(DstParamData%D_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_dragConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_dragConst = SrcParamData%D_dragConst +ENDIF +IF (ALLOCATED(SrcParamData%L_An)) THEN + i1_l = LBOUND(SrcParamData%L_An,1) + i1_u = UBOUND(SrcParamData%L_An,1) + i2_l = LBOUND(SrcParamData%L_An,2) + i2_u = UBOUND(SrcParamData%L_An,2) + IF (.NOT. ALLOCATED(DstParamData%L_An)) THEN + ALLOCATE(DstParamData%L_An(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_An.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_An = SrcParamData%L_An +ENDIF +IF (ALLOCATED(SrcParamData%L_F_B)) THEN + i1_l = LBOUND(SrcParamData%L_F_B,1) + i1_u = UBOUND(SrcParamData%L_F_B,1) + i2_l = LBOUND(SrcParamData%L_F_B,2) + i2_u = UBOUND(SrcParamData%L_F_B,2) + IF (.NOT. ALLOCATED(DstParamData%L_F_B)) THEN + ALLOCATE(DstParamData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_F_B = SrcParamData%L_F_B +ENDIF +IF (ALLOCATED(SrcParamData%L_F_I)) THEN + i1_l = LBOUND(SrcParamData%L_F_I,1) + i1_u = UBOUND(SrcParamData%L_F_I,1) + i2_l = LBOUND(SrcParamData%L_F_I,2) + i2_u = UBOUND(SrcParamData%L_F_I,2) + i3_l = LBOUND(SrcParamData%L_F_I,3) + i3_u = UBOUND(SrcParamData%L_F_I,3) + IF (.NOT. ALLOCATED(DstParamData%L_F_I)) THEN + ALLOCATE(DstParamData%L_F_I(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%L_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_F_I = SrcParamData%L_F_I +ENDIF +IF (ALLOCATED(SrcParamData%L_F_DP)) THEN + i1_l = LBOUND(SrcParamData%L_F_DP,1) + i1_u = UBOUND(SrcParamData%L_F_DP,1) + i2_l = LBOUND(SrcParamData%L_F_DP,2) + i2_u = UBOUND(SrcParamData%L_F_DP,2) + i3_l = LBOUND(SrcParamData%L_F_DP,3) + i3_u = UBOUND(SrcParamData%L_F_DP,3) + IF (.NOT. ALLOCATED(DstParamData%L_F_DP)) THEN + ALLOCATE(DstParamData%L_F_DP(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%L_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_F_DP = SrcParamData%L_F_DP +ENDIF +IF (ALLOCATED(SrcParamData%L_F_BF)) THEN + i1_l = LBOUND(SrcParamData%L_F_BF,1) + i1_u = UBOUND(SrcParamData%L_F_BF,1) + i2_l = LBOUND(SrcParamData%L_F_BF,2) + i2_u = UBOUND(SrcParamData%L_F_BF,2) + IF (.NOT. ALLOCATED(DstParamData%L_F_BF)) THEN + ALLOCATE(DstParamData%L_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_F_BF = SrcParamData%L_F_BF +ENDIF +IF (ALLOCATED(SrcParamData%L_AM_M)) THEN + i1_l = LBOUND(SrcParamData%L_AM_M,1) + i1_u = UBOUND(SrcParamData%L_AM_M,1) + i2_l = LBOUND(SrcParamData%L_AM_M,2) + i2_u = UBOUND(SrcParamData%L_AM_M,2) + i3_l = LBOUND(SrcParamData%L_AM_M,3) + i3_u = UBOUND(SrcParamData%L_AM_M,3) + IF (.NOT. ALLOCATED(DstParamData%L_AM_M)) THEN + ALLOCATE(DstParamData%L_AM_M(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%L_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_AM_M = SrcParamData%L_AM_M +ENDIF +IF (ALLOCATED(SrcParamData%L_dragConst)) THEN + i1_l = LBOUND(SrcParamData%L_dragConst,1) + i1_u = UBOUND(SrcParamData%L_dragConst,1) + IF (.NOT. ALLOCATED(DstParamData%L_dragConst)) THEN + ALLOCATE(DstParamData%L_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_dragConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%L_dragConst = SrcParamData%L_dragConst +ENDIF + DstParamData%NDistribMarkers = SrcParamData%NDistribMarkers +IF (ALLOCATED(SrcParamData%distribToNodeIndx)) THEN + i1_l = LBOUND(SrcParamData%distribToNodeIndx,1) + i1_u = UBOUND(SrcParamData%distribToNodeIndx,1) + IF (.NOT. ALLOCATED(DstParamData%distribToNodeIndx)) THEN + ALLOCATE(DstParamData%distribToNodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%distribToNodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%distribToNodeIndx = SrcParamData%distribToNodeIndx +ENDIF + DstParamData%NLumpedMarkers = SrcParamData%NLumpedMarkers +IF (ALLOCATED(SrcParamData%lumpedToNodeIndx)) THEN + i1_l = LBOUND(SrcParamData%lumpedToNodeIndx,1) + i1_u = UBOUND(SrcParamData%lumpedToNodeIndx,1) + IF (.NOT. ALLOCATED(DstParamData%lumpedToNodeIndx)) THEN + ALLOCATE(DstParamData%lumpedToNodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%lumpedToNodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%lumpedToNodeIndx = SrcParamData%lumpedToNodeIndx +ENDIF +IF (ALLOCATED(SrcParamData%WaveVel)) THEN + i1_l = LBOUND(SrcParamData%WaveVel,1) + i1_u = UBOUND(SrcParamData%WaveVel,1) + i2_l = LBOUND(SrcParamData%WaveVel,2) + i2_u = UBOUND(SrcParamData%WaveVel,2) + i3_l = LBOUND(SrcParamData%WaveVel,3) + i3_u = UBOUND(SrcParamData%WaveVel,3) + IF (.NOT. ALLOCATED(DstParamData%WaveVel)) THEN + ALLOCATE(DstParamData%WaveVel(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%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveVel = SrcParamData%WaveVel +ENDIF +IF (ALLOCATED(SrcParamData%WaveAcc)) THEN + i1_l = LBOUND(SrcParamData%WaveAcc,1) + i1_u = UBOUND(SrcParamData%WaveAcc,1) + i2_l = LBOUND(SrcParamData%WaveAcc,2) + i2_u = UBOUND(SrcParamData%WaveAcc,2) + i3_l = LBOUND(SrcParamData%WaveAcc,3) + i3_u = UBOUND(SrcParamData%WaveAcc,3) + IF (.NOT. ALLOCATED(DstParamData%WaveAcc)) THEN + ALLOCATE(DstParamData%WaveAcc(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%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveAcc = SrcParamData%WaveAcc +ENDIF +IF (ALLOCATED(SrcParamData%WaveDynP)) THEN + i1_l = LBOUND(SrcParamData%WaveDynP,1) + i1_u = UBOUND(SrcParamData%WaveDynP,1) + i2_l = LBOUND(SrcParamData%WaveDynP,2) + i2_u = UBOUND(SrcParamData%WaveDynP,2) + IF (.NOT. ALLOCATED(DstParamData%WaveDynP)) THEN + ALLOCATE(DstParamData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveDynP = SrcParamData%WaveDynP +ENDIF +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF +IF (ALLOCATED(SrcParamData%elementWaterState)) THEN + i1_l = LBOUND(SrcParamData%elementWaterState,1) + i1_u = UBOUND(SrcParamData%elementWaterState,1) + i2_l = LBOUND(SrcParamData%elementWaterState,2) + i2_u = UBOUND(SrcParamData%elementWaterState,2) + IF (.NOT. ALLOCATED(DstParamData%elementWaterState)) THEN + ALLOCATE(DstParamData%elementWaterState(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%elementWaterState.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%elementWaterState = SrcParamData%elementWaterState +ENDIF +IF (ALLOCATED(SrcParamData%elementFillState)) THEN + i1_l = LBOUND(SrcParamData%elementFillState,1) + i1_u = UBOUND(SrcParamData%elementFillState,1) + IF (.NOT. ALLOCATED(DstParamData%elementFillState)) THEN + ALLOCATE(DstParamData%elementFillState(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%elementFillState.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%elementFillState = SrcParamData%elementFillState +ENDIF +IF (ALLOCATED(SrcParamData%nodeInWater)) THEN + i1_l = LBOUND(SrcParamData%nodeInWater,1) + i1_u = UBOUND(SrcParamData%nodeInWater,1) + i2_l = LBOUND(SrcParamData%nodeInWater,2) + i2_u = UBOUND(SrcParamData%nodeInWater,2) + IF (.NOT. ALLOCATED(DstParamData%nodeInWater)) THEN + ALLOCATE(DstParamData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%nodeInWater = SrcParamData%nodeInWater +ENDIF +IF (ALLOCATED(SrcParamData%D_F_B)) THEN + i1_l = LBOUND(SrcParamData%D_F_B,1) + i1_u = UBOUND(SrcParamData%D_F_B,1) + i2_l = LBOUND(SrcParamData%D_F_B,2) + i2_u = UBOUND(SrcParamData%D_F_B,2) + IF (.NOT. ALLOCATED(DstParamData%D_F_B)) THEN + ALLOCATE(DstParamData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_F_B = SrcParamData%D_F_B +ENDIF +IF (ALLOCATED(SrcParamData%D_F_BF)) THEN + i1_l = LBOUND(SrcParamData%D_F_BF,1) + i1_u = UBOUND(SrcParamData%D_F_BF,1) + i2_l = LBOUND(SrcParamData%D_F_BF,2) + i2_u = UBOUND(SrcParamData%D_F_BF,2) + IF (.NOT. ALLOCATED(DstParamData%D_F_BF)) THEN + ALLOCATE(DstParamData%D_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_F_BF = SrcParamData%D_F_BF +ENDIF +IF (ALLOCATED(SrcParamData%D_F_MG)) THEN + i1_l = LBOUND(SrcParamData%D_F_MG,1) + i1_u = UBOUND(SrcParamData%D_F_MG,1) + i2_l = LBOUND(SrcParamData%D_F_MG,2) + i2_u = UBOUND(SrcParamData%D_F_MG,2) + IF (.NOT. ALLOCATED(DstParamData%D_F_MG)) THEN + ALLOCATE(DstParamData%D_F_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_F_MG = SrcParamData%D_F_MG +ENDIF +IF (ALLOCATED(SrcParamData%D_AM_M)) THEN + i1_l = LBOUND(SrcParamData%D_AM_M,1) + i1_u = UBOUND(SrcParamData%D_AM_M,1) + i2_l = LBOUND(SrcParamData%D_AM_M,2) + i2_u = UBOUND(SrcParamData%D_AM_M,2) + i3_l = LBOUND(SrcParamData%D_AM_M,3) + i3_u = UBOUND(SrcParamData%D_AM_M,3) + IF (.NOT. ALLOCATED(DstParamData%D_AM_M)) THEN + ALLOCATE(DstParamData%D_AM_M(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%D_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_AM_M = SrcParamData%D_AM_M +ENDIF +IF (ALLOCATED(SrcParamData%D_AM_MG)) THEN + i1_l = LBOUND(SrcParamData%D_AM_MG,1) + i1_u = UBOUND(SrcParamData%D_AM_MG,1) + IF (.NOT. ALLOCATED(DstParamData%D_AM_MG)) THEN + ALLOCATE(DstParamData%D_AM_MG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_AM_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_AM_MG = SrcParamData%D_AM_MG +ENDIF +IF (ALLOCATED(SrcParamData%D_AM_F)) THEN + i1_l = LBOUND(SrcParamData%D_AM_F,1) + i1_u = UBOUND(SrcParamData%D_AM_F,1) + IF (.NOT. ALLOCATED(DstParamData%D_AM_F)) THEN + ALLOCATE(DstParamData%D_AM_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_AM_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D_AM_F = SrcParamData%D_AM_F +ENDIF + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%NMOutputs = SrcParamData%NMOutputs +IF (ALLOCATED(SrcParamData%MOutLst)) THEN + i1_l = LBOUND(SrcParamData%MOutLst,1) + i1_u = UBOUND(SrcParamData%MOutLst,1) + IF (.NOT. ALLOCATED(DstParamData%MOutLst)) THEN + ALLOCATE(DstParamData%MOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MOutLst,1), UBOUND(SrcParamData%MOutLst,1) + CALL Morison_Copymoutput( SrcParamData%MOutLst(i1), DstParamData%MOutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NJOutputs = SrcParamData%NJOutputs +IF (ALLOCATED(SrcParamData%JOutLst)) THEN + i1_l = LBOUND(SrcParamData%JOutLst,1) + i1_u = UBOUND(SrcParamData%JOutLst,1) + IF (.NOT. ALLOCATED(DstParamData%JOutLst)) THEN + ALLOCATE(DstParamData%JOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%JOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%JOutLst,1), UBOUND(SrcParamData%JOutLst,1) + CALL Morison_Copyjoutput( SrcParamData%JOutLst(i1), DstParamData%JOutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOutAll = SrcParamData%NumOutAll + DstParamData%OutSwtch = SrcParamData%OutSwtch + DstParamData%UnOutFile = SrcParamData%UnOutFile + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + END SUBROUTINE Morison_CopyParam + + SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Morison_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%Nodes)) THEN +DO i1 = LBOUND(ParamData%Nodes,1), UBOUND(ParamData%Nodes,1) + CALL Morison_Destroynodetype( ParamData%Nodes(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%Nodes) +ENDIF +IF (ALLOCATED(ParamData%D_F_I)) THEN + DEALLOCATE(ParamData%D_F_I) +ENDIF +IF (ALLOCATED(ParamData%D_F_DP)) THEN + DEALLOCATE(ParamData%D_F_DP) +ENDIF +IF (ALLOCATED(ParamData%D_dragConst)) THEN + DEALLOCATE(ParamData%D_dragConst) +ENDIF +IF (ALLOCATED(ParamData%L_An)) THEN + DEALLOCATE(ParamData%L_An) +ENDIF +IF (ALLOCATED(ParamData%L_F_B)) THEN + DEALLOCATE(ParamData%L_F_B) +ENDIF +IF (ALLOCATED(ParamData%L_F_I)) THEN + DEALLOCATE(ParamData%L_F_I) +ENDIF +IF (ALLOCATED(ParamData%L_F_DP)) THEN + DEALLOCATE(ParamData%L_F_DP) +ENDIF +IF (ALLOCATED(ParamData%L_F_BF)) THEN + DEALLOCATE(ParamData%L_F_BF) +ENDIF +IF (ALLOCATED(ParamData%L_AM_M)) THEN + DEALLOCATE(ParamData%L_AM_M) +ENDIF +IF (ALLOCATED(ParamData%L_dragConst)) THEN + DEALLOCATE(ParamData%L_dragConst) +ENDIF +IF (ALLOCATED(ParamData%distribToNodeIndx)) THEN + DEALLOCATE(ParamData%distribToNodeIndx) +ENDIF +IF (ALLOCATED(ParamData%lumpedToNodeIndx)) THEN + DEALLOCATE(ParamData%lumpedToNodeIndx) +ENDIF +IF (ALLOCATED(ParamData%WaveVel)) THEN + DEALLOCATE(ParamData%WaveVel) +ENDIF +IF (ALLOCATED(ParamData%WaveAcc)) THEN + DEALLOCATE(ParamData%WaveAcc) +ENDIF +IF (ALLOCATED(ParamData%WaveDynP)) THEN + DEALLOCATE(ParamData%WaveDynP) +ENDIF +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF +IF (ALLOCATED(ParamData%elementWaterState)) THEN + DEALLOCATE(ParamData%elementWaterState) +ENDIF +IF (ALLOCATED(ParamData%elementFillState)) THEN + DEALLOCATE(ParamData%elementFillState) +ENDIF +IF (ALLOCATED(ParamData%nodeInWater)) THEN + DEALLOCATE(ParamData%nodeInWater) +ENDIF +IF (ALLOCATED(ParamData%D_F_B)) THEN + DEALLOCATE(ParamData%D_F_B) +ENDIF +IF (ALLOCATED(ParamData%D_F_BF)) THEN + DEALLOCATE(ParamData%D_F_BF) +ENDIF +IF (ALLOCATED(ParamData%D_F_MG)) THEN + DEALLOCATE(ParamData%D_F_MG) +ENDIF +IF (ALLOCATED(ParamData%D_AM_M)) THEN + DEALLOCATE(ParamData%D_AM_M) +ENDIF +IF (ALLOCATED(ParamData%D_AM_MG)) THEN + DEALLOCATE(ParamData%D_AM_MG) +ENDIF +IF (ALLOCATED(ParamData%D_AM_F)) THEN + DEALLOCATE(ParamData%D_AM_F) +ENDIF +IF (ALLOCATED(ParamData%MOutLst)) THEN +DO i1 = LBOUND(ParamData%MOutLst,1), UBOUND(ParamData%MOutLst,1) + CALL Morison_Destroymoutput( ParamData%MOutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MOutLst) +ENDIF +IF (ALLOCATED(ParamData%JOutLst)) THEN +DO i1 = LBOUND(ParamData%JOutLst,1), UBOUND(ParamData%JOutLst,1) + CALL Morison_Destroyjoutput( ParamData%JOutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%JOutLst) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE Morison_DestroyParam + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 + Db_BufSz = Db_BufSz + 1 ! DT + Re_BufSz = Re_BufSz + 1 ! WtrDens + Int_BufSz = Int_BufSz + 1 ! NNodes + Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no + IF ( ALLOCATED(InData%Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Nodes upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + Int_BufSz = Int_BufSz + 3 ! Nodes: size of buffers for each call to pack subtype + CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Nodes + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Nodes + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Nodes + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Nodes + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_I allocated yes/no + IF ( ALLOCATED(InData%D_F_I) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! D_F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_I) ! D_F_I + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_DP allocated yes/no + IF ( ALLOCATED(InData%D_F_DP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! D_F_DP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_DP) ! D_F_DP + END IF + Int_BufSz = Int_BufSz + 1 ! D_dragConst allocated yes/no + IF ( ALLOCATED(InData%D_dragConst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! D_dragConst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_dragConst) ! D_dragConst + END IF + Int_BufSz = Int_BufSz + 1 ! L_An allocated yes/no + IF ( ALLOCATED(InData%L_An) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_An upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_An) ! L_An + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_B allocated yes/no + IF ( ALLOCATED(InData%L_F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_B) ! L_F_B + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_I allocated yes/no + IF ( ALLOCATED(InData%L_F_I) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! L_F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_I) ! L_F_I + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_DP allocated yes/no + IF ( ALLOCATED(InData%L_F_DP) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! L_F_DP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_DP) ! L_F_DP + END IF + Int_BufSz = Int_BufSz + 1 ! L_F_BF allocated yes/no + IF ( ALLOCATED(InData%L_F_BF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! L_F_BF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_F_BF) ! L_F_BF + END IF + Int_BufSz = Int_BufSz + 1 ! L_AM_M allocated yes/no + IF ( ALLOCATED(InData%L_AM_M) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! L_AM_M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_AM_M) ! L_AM_M + END IF + Int_BufSz = Int_BufSz + 1 ! L_dragConst allocated yes/no + IF ( ALLOCATED(InData%L_dragConst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! L_dragConst upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%L_dragConst) ! L_dragConst + END IF + Int_BufSz = Int_BufSz + 1 ! NDistribMarkers + Int_BufSz = Int_BufSz + 1 ! distribToNodeIndx allocated yes/no + IF ( ALLOCATED(InData%distribToNodeIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! distribToNodeIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%distribToNodeIndx) ! distribToNodeIndx + END IF + Int_BufSz = Int_BufSz + 1 ! NLumpedMarkers + Int_BufSz = Int_BufSz + 1 ! lumpedToNodeIndx allocated yes/no + IF ( ALLOCATED(InData%lumpedToNodeIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! lumpedToNodeIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%lumpedToNodeIndx) ! lumpedToNodeIndx + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel allocated yes/no + IF ( ALLOCATED(InData%WaveVel) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel) ! WaveVel + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc allocated yes/no + IF ( ALLOCATED(InData%WaveAcc) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc) ! WaveAcc + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP allocated yes/no + IF ( ALLOCATED(InData%WaveDynP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP) ! WaveDynP + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! elementWaterState allocated yes/no + IF ( ALLOCATED(InData%elementWaterState) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! elementWaterState upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%elementWaterState) ! elementWaterState + END IF + Int_BufSz = Int_BufSz + 1 ! elementFillState allocated yes/no + IF ( ALLOCATED(InData%elementFillState) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! elementFillState upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%elementFillState) ! elementFillState + END IF + Int_BufSz = Int_BufSz + 1 ! nodeInWater allocated yes/no + IF ( ALLOCATED(InData%nodeInWater) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! nodeInWater upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_B allocated yes/no + IF ( ALLOCATED(InData%D_F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_B) ! D_F_B + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_BF allocated yes/no + IF ( ALLOCATED(InData%D_F_BF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_BF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_BF) ! D_F_BF + END IF + Int_BufSz = Int_BufSz + 1 ! D_F_MG allocated yes/no + IF ( ALLOCATED(InData%D_F_MG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D_F_MG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_F_MG) ! D_F_MG + END IF + Int_BufSz = Int_BufSz + 1 ! D_AM_M allocated yes/no + IF ( ALLOCATED(InData%D_AM_M) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! D_AM_M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_AM_M) ! D_AM_M + END IF + Int_BufSz = Int_BufSz + 1 ! D_AM_MG allocated yes/no + IF ( ALLOCATED(InData%D_AM_MG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! D_AM_MG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_AM_MG) ! D_AM_MG + END IF + Int_BufSz = Int_BufSz + 1 ! D_AM_F allocated yes/no + IF ( ALLOCATED(InData%D_AM_F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! D_AM_F upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D_AM_F) ! D_AM_F + END IF + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NMOutputs + Int_BufSz = Int_BufSz + 1 ! MOutLst allocated yes/no + IF ( ALLOCATED(InData%MOutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MOutLst upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MOutLst,1), UBOUND(InData%MOutLst,1) + Int_BufSz = Int_BufSz + 3 ! MOutLst: size of buffers for each call to pack subtype + CALL Morison_Packmoutput( Re_Buf, Db_Buf, Int_Buf, InData%MOutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MOutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MOutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MOutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MOutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NJOutputs + Int_BufSz = Int_BufSz + 1 ! JOutLst allocated yes/no + IF ( ALLOCATED(InData%JOutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! JOutLst upper/lower bounds for each dimension + DO i1 = LBOUND(InData%JOutLst,1), UBOUND(InData%JOutLst,1) + Int_BufSz = Int_BufSz + 3 ! JOutLst: size of buffers for each call to pack subtype + CALL Morison_Packjoutput( Re_Buf, Db_Buf, Int_Buf, InData%JOutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! JOutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! JOutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! JOutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! JOutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1 ! UnOutFile + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nodes) ) 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%Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, OnlySize ) ! Nodes + 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%D_F_I) ) 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%D_F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%D_F_I,3), UBOUND(InData%D_F_I,3) + DO i2 = LBOUND(InData%D_F_I,2), UBOUND(InData%D_F_I,2) + DO i1 = LBOUND(InData%D_F_I,1), UBOUND(InData%D_F_I,1) + ReKiBuf(Re_Xferred) = InData%D_F_I(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_DP) ) 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%D_F_DP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_DP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_DP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%D_F_DP,3), UBOUND(InData%D_F_DP,3) + DO i2 = LBOUND(InData%D_F_DP,2), UBOUND(InData%D_F_DP,2) + DO i1 = LBOUND(InData%D_F_DP,1), UBOUND(InData%D_F_DP,1) + ReKiBuf(Re_Xferred) = InData%D_F_DP(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_dragConst) ) 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%D_dragConst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_dragConst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%D_dragConst,1), UBOUND(InData%D_dragConst,1) + ReKiBuf(Re_Xferred) = InData%D_dragConst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_An) ) 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%L_An,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_An,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_An,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_An,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_An,2), UBOUND(InData%L_An,2) + DO i1 = LBOUND(InData%L_An,1), UBOUND(InData%L_An,1) + ReKiBuf(Re_Xferred) = InData%L_An(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_B) ) 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%L_F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_B,2), UBOUND(InData%L_F_B,2) + DO i1 = LBOUND(InData%L_F_B,1), UBOUND(InData%L_F_B,1) + ReKiBuf(Re_Xferred) = InData%L_F_B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_I) ) 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%L_F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%L_F_I,3), UBOUND(InData%L_F_I,3) + DO i2 = LBOUND(InData%L_F_I,2), UBOUND(InData%L_F_I,2) + DO i1 = LBOUND(InData%L_F_I,1), UBOUND(InData%L_F_I,1) + ReKiBuf(Re_Xferred) = InData%L_F_I(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_DP) ) 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%L_F_DP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%L_F_DP,3), UBOUND(InData%L_F_DP,3) + DO i2 = LBOUND(InData%L_F_DP,2), UBOUND(InData%L_F_DP,2) + DO i1 = LBOUND(InData%L_F_DP,1), UBOUND(InData%L_F_DP,1) + ReKiBuf(Re_Xferred) = InData%L_F_DP(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_F_BF) ) 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%L_F_BF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_BF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%L_F_BF,2), UBOUND(InData%L_F_BF,2) + DO i1 = LBOUND(InData%L_F_BF,1), UBOUND(InData%L_F_BF,1) + ReKiBuf(Re_Xferred) = InData%L_F_BF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_AM_M) ) 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%L_AM_M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%L_AM_M,3), UBOUND(InData%L_AM_M,3) + DO i2 = LBOUND(InData%L_AM_M,2), UBOUND(InData%L_AM_M,2) + DO i1 = LBOUND(InData%L_AM_M,1), UBOUND(InData%L_AM_M,1) + ReKiBuf(Re_Xferred) = InData%L_AM_M(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%L_dragConst) ) 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%L_dragConst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_dragConst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%L_dragConst,1), UBOUND(InData%L_dragConst,1) + ReKiBuf(Re_Xferred) = InData%L_dragConst(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NDistribMarkers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%distribToNodeIndx) ) 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%distribToNodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%distribToNodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%distribToNodeIndx,1), UBOUND(InData%distribToNodeIndx,1) + IntKiBuf(Int_Xferred) = InData%distribToNodeIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NLumpedMarkers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%lumpedToNodeIndx) ) 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%lumpedToNodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lumpedToNodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%lumpedToNodeIndx,1), UBOUND(InData%lumpedToNodeIndx,1) + IntKiBuf(Int_Xferred) = InData%lumpedToNodeIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel) ) 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%WaveVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel,3), UBOUND(InData%WaveVel,3) + DO i2 = LBOUND(InData%WaveVel,2), UBOUND(InData%WaveVel,2) + DO i1 = LBOUND(InData%WaveVel,1), UBOUND(InData%WaveVel,1) + ReKiBuf(Re_Xferred) = InData%WaveVel(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc) ) 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%WaveAcc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc,3), UBOUND(InData%WaveAcc,3) + DO i2 = LBOUND(InData%WaveAcc,2), UBOUND(InData%WaveAcc,2) + DO i1 = LBOUND(InData%WaveAcc,1), UBOUND(InData%WaveAcc,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP) ) 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%WaveDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP,2), UBOUND(InData%WaveDynP,2) + DO i1 = LBOUND(InData%WaveDynP,1), UBOUND(InData%WaveDynP,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elementWaterState) ) 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%elementWaterState,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%elementWaterState,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%elementWaterState,2), UBOUND(InData%elementWaterState,2) + DO i1 = LBOUND(InData%elementWaterState,1), UBOUND(InData%elementWaterState,1) + IntKiBuf(Int_Xferred) = InData%elementWaterState(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%elementFillState) ) 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%elementFillState,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementFillState,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%elementFillState,1), UBOUND(InData%elementFillState,1) + IntKiBuf(Int_Xferred) = InData%elementFillState(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%nodeInWater) ) 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%nodeInWater,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%nodeInWater,2), UBOUND(InData%nodeInWater,2) + DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) + IntKiBuf(Int_Xferred) = InData%nodeInWater(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_B) ) 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%D_F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_B,2), UBOUND(InData%D_F_B,2) + DO i1 = LBOUND(InData%D_F_B,1), UBOUND(InData%D_F_B,1) + ReKiBuf(Re_Xferred) = InData%D_F_B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_BF) ) 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%D_F_BF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_BF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_BF,2), UBOUND(InData%D_F_BF,2) + DO i1 = LBOUND(InData%D_F_BF,1), UBOUND(InData%D_F_BF,1) + ReKiBuf(Re_Xferred) = InData%D_F_BF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_F_MG) ) 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%D_F_MG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_MG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D_F_MG,2), UBOUND(InData%D_F_MG,2) + DO i1 = LBOUND(InData%D_F_MG,1), UBOUND(InData%D_F_MG,1) + ReKiBuf(Re_Xferred) = InData%D_F_MG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_AM_M) ) 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%D_AM_M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%D_AM_M,3), UBOUND(InData%D_AM_M,3) + DO i2 = LBOUND(InData%D_AM_M,2), UBOUND(InData%D_AM_M,2) + DO i1 = LBOUND(InData%D_AM_M,1), UBOUND(InData%D_AM_M,1) + ReKiBuf(Re_Xferred) = InData%D_AM_M(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_AM_MG) ) 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%D_AM_MG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_MG,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%D_AM_MG,1), UBOUND(InData%D_AM_MG,1) + ReKiBuf(Re_Xferred) = InData%D_AM_MG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D_AM_F) ) 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%D_AM_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_F,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%D_AM_F,1), UBOUND(InData%D_AM_F,1) + ReKiBuf(Re_Xferred) = InData%D_AM_F(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NMOutputs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%MOutLst) ) 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%MOutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MOutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MOutLst,1), UBOUND(InData%MOutLst,1) + CALL Morison_Packmoutput( Re_Buf, Db_Buf, Int_Buf, InData%MOutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! MOutLst + 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 + IntKiBuf(Int_Xferred) = InData%NJOutputs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%JOutLst) ) 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%JOutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JOutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%JOutLst,1), UBOUND(InData%JOutLst,1) + CALL Morison_Packjoutput( Re_Buf, Db_Buf, Int_Buf, InData%JOutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! JOutLst + 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%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 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Morison_PackParam + + SUBROUTINE Morison_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(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes 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%Nodes)) DEALLOCATE(OutData%Nodes) + ALLOCATE(OutData%Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Nodes,1), UBOUND(OutData%Nodes,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 Morison_Unpacknodetype( Re_Buf, Db_Buf, Int_Buf, OutData%Nodes(i1), ErrStat2, ErrMsg2 ) ! Nodes + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_I 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%D_F_I)) DEALLOCATE(OutData%D_F_I) + ALLOCATE(OutData%D_F_I(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%D_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%D_F_I,3), UBOUND(OutData%D_F_I,3) + DO i2 = LBOUND(OutData%D_F_I,2), UBOUND(OutData%D_F_I,2) + DO i1 = LBOUND(OutData%D_F_I,1), UBOUND(OutData%D_F_I,1) + OutData%D_F_I(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_DP 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%D_F_DP)) DEALLOCATE(OutData%D_F_DP) + ALLOCATE(OutData%D_F_DP(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%D_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%D_F_DP,3), UBOUND(OutData%D_F_DP,3) + DO i2 = LBOUND(OutData%D_F_DP,2), UBOUND(OutData%D_F_DP,2) + DO i1 = LBOUND(OutData%D_F_DP,1), UBOUND(OutData%D_F_DP,1) + OutData%D_F_DP(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_dragConst 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%D_dragConst)) DEALLOCATE(OutData%D_dragConst) + ALLOCATE(OutData%D_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_dragConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%D_dragConst,1), UBOUND(OutData%D_dragConst,1) + OutData%D_dragConst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_An 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%L_An)) DEALLOCATE(OutData%L_An) + ALLOCATE(OutData%L_An(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_An.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_An,2), UBOUND(OutData%L_An,2) + DO i1 = LBOUND(OutData%L_An,1), UBOUND(OutData%L_An,1) + OutData%L_An(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_B 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%L_F_B)) DEALLOCATE(OutData%L_F_B) + ALLOCATE(OutData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_B,2), UBOUND(OutData%L_F_B,2) + DO i1 = LBOUND(OutData%L_F_B,1), UBOUND(OutData%L_F_B,1) + OutData%L_F_B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_I 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%L_F_I)) DEALLOCATE(OutData%L_F_I) + ALLOCATE(OutData%L_F_I(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%L_F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%L_F_I,3), UBOUND(OutData%L_F_I,3) + DO i2 = LBOUND(OutData%L_F_I,2), UBOUND(OutData%L_F_I,2) + DO i1 = LBOUND(OutData%L_F_I,1), UBOUND(OutData%L_F_I,1) + OutData%L_F_I(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_DP 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%L_F_DP)) DEALLOCATE(OutData%L_F_DP) + ALLOCATE(OutData%L_F_DP(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%L_F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%L_F_DP,3), UBOUND(OutData%L_F_DP,3) + DO i2 = LBOUND(OutData%L_F_DP,2), UBOUND(OutData%L_F_DP,2) + DO i1 = LBOUND(OutData%L_F_DP,1), UBOUND(OutData%L_F_DP,1) + OutData%L_F_DP(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_BF 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%L_F_BF)) DEALLOCATE(OutData%L_F_BF) + ALLOCATE(OutData%L_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%L_F_BF,2), UBOUND(OutData%L_F_BF,2) + DO i1 = LBOUND(OutData%L_F_BF,1), UBOUND(OutData%L_F_BF,1) + OutData%L_F_BF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_AM_M 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%L_AM_M)) DEALLOCATE(OutData%L_AM_M) + ALLOCATE(OutData%L_AM_M(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%L_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%L_AM_M,3), UBOUND(OutData%L_AM_M,3) + DO i2 = LBOUND(OutData%L_AM_M,2), UBOUND(OutData%L_AM_M,2) + DO i1 = LBOUND(OutData%L_AM_M,1), UBOUND(OutData%L_AM_M,1) + OutData%L_AM_M(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_dragConst 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%L_dragConst)) DEALLOCATE(OutData%L_dragConst) + ALLOCATE(OutData%L_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_dragConst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%L_dragConst,1), UBOUND(OutData%L_dragConst,1) + OutData%L_dragConst(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NDistribMarkers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! distribToNodeIndx 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%distribToNodeIndx)) DEALLOCATE(OutData%distribToNodeIndx) + ALLOCATE(OutData%distribToNodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%distribToNodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%distribToNodeIndx,1), UBOUND(OutData%distribToNodeIndx,1) + OutData%distribToNodeIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NLumpedMarkers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lumpedToNodeIndx 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%lumpedToNodeIndx)) DEALLOCATE(OutData%lumpedToNodeIndx) + ALLOCATE(OutData%lumpedToNodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lumpedToNodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%lumpedToNodeIndx,1), UBOUND(OutData%lumpedToNodeIndx,1) + OutData%lumpedToNodeIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel 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%WaveVel)) DEALLOCATE(OutData%WaveVel) + ALLOCATE(OutData%WaveVel(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%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel,3), UBOUND(OutData%WaveVel,3) + DO i2 = LBOUND(OutData%WaveVel,2), UBOUND(OutData%WaveVel,2) + DO i1 = LBOUND(OutData%WaveVel,1), UBOUND(OutData%WaveVel,1) + OutData%WaveVel(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 ! WaveAcc 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%WaveAcc)) DEALLOCATE(OutData%WaveAcc) + ALLOCATE(OutData%WaveAcc(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%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc,3), UBOUND(OutData%WaveAcc,3) + DO i2 = LBOUND(OutData%WaveAcc,2), UBOUND(OutData%WaveAcc,2) + DO i1 = LBOUND(OutData%WaveAcc,1), UBOUND(OutData%WaveAcc,1) + OutData%WaveAcc(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 ! WaveDynP 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%WaveDynP)) DEALLOCATE(OutData%WaveDynP) + ALLOCATE(OutData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP,2), UBOUND(OutData%WaveDynP,2) + DO i1 = LBOUND(OutData%WaveDynP,1), UBOUND(OutData%WaveDynP,1) + OutData%WaveDynP(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementWaterState 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%elementWaterState)) DEALLOCATE(OutData%elementWaterState) + ALLOCATE(OutData%elementWaterState(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementWaterState.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%elementWaterState,2), UBOUND(OutData%elementWaterState,2) + DO i1 = LBOUND(OutData%elementWaterState,1), UBOUND(OutData%elementWaterState,1) + OutData%elementWaterState(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementFillState 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%elementFillState)) DEALLOCATE(OutData%elementFillState) + ALLOCATE(OutData%elementFillState(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementFillState.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%elementFillState,1), UBOUND(OutData%elementFillState,1) + OutData%elementFillState(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! nodeInWater 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%nodeInWater)) DEALLOCATE(OutData%nodeInWater) + ALLOCATE(OutData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%nodeInWater,2), UBOUND(OutData%nodeInWater,2) + DO i1 = LBOUND(OutData%nodeInWater,1), UBOUND(OutData%nodeInWater,1) + OutData%nodeInWater(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_B 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%D_F_B)) DEALLOCATE(OutData%D_F_B) + ALLOCATE(OutData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_B,2), UBOUND(OutData%D_F_B,2) + DO i1 = LBOUND(OutData%D_F_B,1), UBOUND(OutData%D_F_B,1) + OutData%D_F_B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_BF 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%D_F_BF)) DEALLOCATE(OutData%D_F_BF) + ALLOCATE(OutData%D_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_BF,2), UBOUND(OutData%D_F_BF,2) + DO i1 = LBOUND(OutData%D_F_BF,1), UBOUND(OutData%D_F_BF,1) + OutData%D_F_BF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_MG 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%D_F_MG)) DEALLOCATE(OutData%D_F_MG) + ALLOCATE(OutData%D_F_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D_F_MG,2), UBOUND(OutData%D_F_MG,2) + DO i1 = LBOUND(OutData%D_F_MG,1), UBOUND(OutData%D_F_MG,1) + OutData%D_F_MG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_M 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%D_AM_M)) DEALLOCATE(OutData%D_AM_M) + ALLOCATE(OutData%D_AM_M(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%D_AM_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%D_AM_M,3), UBOUND(OutData%D_AM_M,3) + DO i2 = LBOUND(OutData%D_AM_M,2), UBOUND(OutData%D_AM_M,2) + DO i1 = LBOUND(OutData%D_AM_M,1), UBOUND(OutData%D_AM_M,1) + OutData%D_AM_M(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_MG 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%D_AM_MG)) DEALLOCATE(OutData%D_AM_MG) + ALLOCATE(OutData%D_AM_MG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_MG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%D_AM_MG,1), UBOUND(OutData%D_AM_MG,1) + OutData%D_AM_MG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_F 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%D_AM_F)) DEALLOCATE(OutData%D_AM_F) + ALLOCATE(OutData%D_AM_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%D_AM_F,1), UBOUND(OutData%D_AM_F,1) + OutData%D_AM_F(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NMOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MOutLst 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%MOutLst)) DEALLOCATE(OutData%MOutLst) + ALLOCATE(OutData%MOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MOutLst,1), UBOUND(OutData%MOutLst,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 Morison_Unpackmoutput( Re_Buf, Db_Buf, Int_Buf, OutData%MOutLst(i1), ErrStat2, ErrMsg2 ) ! MOutLst + 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 DO + END IF + OutData%NJOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JOutLst 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%JOutLst)) DEALLOCATE(OutData%JOutLst) + ALLOCATE(OutData%JOutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JOutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%JOutLst,1), UBOUND(OutData%JOutLst,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 Morison_Unpackjoutput( Re_Buf, Db_Buf, Int_Buf, OutData%JOutLst(i1), ErrStat2, ErrMsg2 ) ! JOutLst + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Morison_UnPackParam + + SUBROUTINE Morison_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_InputType), INTENT(INOUT) :: SrcInputData + TYPE(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%DistribMesh, DstInputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%LumpedMesh, DstInputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE Morison_CopyInput + + SUBROUTINE Morison_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Morison_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%DistribMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%LumpedMesh, ErrStat, ErrMsg ) + END SUBROUTINE Morison_DestroyInput + + SUBROUTINE Morison_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(Morison_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 = 'Morison_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DistribMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + 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 MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh + 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 MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + 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 Morison_PackInput + + SUBROUTINE Morison_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(Morison_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_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 + 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 MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh + 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 MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + 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 Morison_UnPackInput + + SUBROUTINE Morison_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(Morison_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Morison_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%DistribMesh, DstOutputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%LumpedMesh, DstOutputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE Morison_CopyOutput + + SUBROUTINE Morison_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Morison_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%DistribMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%LumpedMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE Morison_DestroyOutput + + SUBROUTINE Morison_PackOutput( 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(Morison_OutputType), 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 = 'Morison_PackOutput' + ! 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 ! DistribMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh + 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 MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Morison_PackOutput + + SUBROUTINE Morison_UnPackOutput( 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(Morison_OutputType), 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 = 'Morison_UnPackOutput' + ! 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 MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh + 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 MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Morison_UnPackOutput + + + SUBROUTINE Morison_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Morison_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Morison_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Morison_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Morison_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Morison_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Morison_Input_ExtrapInterp + + + SUBROUTINE Morison_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Morison_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Morison_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Morison_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%DistribMesh, u2%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%LumpedMesh, u2%LumpedMesh, tin, u_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE Morison_Input_ExtrapInterp1 + + + SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Morison_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Morison_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Morison_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Morison_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%DistribMesh, u2%DistribMesh, u3%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%LumpedMesh, u2%LumpedMesh, u3%LumpedMesh, tin, u_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE Morison_Input_ExtrapInterp2 + + + SUBROUTINE Morison_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Morison_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Morison_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Morison_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Morison_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Morison_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Morison_Output_ExtrapInterp + + + SUBROUTINE Morison_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Morison_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Morison_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Morison_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%DistribMesh, y2%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%LumpedMesh, y2%LumpedMesh, tin, y_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE Morison_Output_ExtrapInterp1 + + + SUBROUTINE Morison_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Morison_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Morison_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Morison_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Morison_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%DistribMesh, y2%DistribMesh, y3%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%LumpedMesh, y2%LumpedMesh, y3%LumpedMesh, tin, y_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE Morison_Output_ExtrapInterp2 + +END MODULE Morison_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/SS_Excitation.f90 b/OpenFAST/modules/hydrodyn/src/SS_Excitation.f90 new file mode 100644 index 000000000..f2071c1db --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Excitation.f90 @@ -0,0 +1,901 @@ +!********************************************************************************************************************************** +! The SS_Excitation and SS_Excitation_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. SS_Excitations_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012, 2018 National Renewable Energy Laboratory +! +! This file is part of SS_Excitation. +! +! 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 +! +!********************************************************************************************************************************** +MODULE SS_Excitation + + USE SS_Excitation_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: SS_Exc_ProgDesc = ProgDesc( 'SS_Excitation', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: SS_Exc_Init ! Initialization routine + PUBLIC :: SS_Exc_End ! Ending routine (includes clean up) + + PUBLIC :: SS_Exc_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: SS_Exc_CalcOutput ! Routine for computing outputs + + PUBLIC :: SS_Exc_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: SS_Exc_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: SS_Exc_UpdateDiscState ! Tight coupling routine for updating discrete states + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SS_Exc_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(SS_Exc_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SS_Exc_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(SS_Exc_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(SS_Exc_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(SS_Exc_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(SS_Exc_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(SS_Exc_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) SS_Exc_UpdateStates() is called in loose coupling & + !! (2) SS_Exc_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(SS_Exc_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local Variables: + + INTEGER :: I ! Generic index +! INTEGER :: J ! Generic index + INTEGER :: xx (1,6) ! Active DOF's on the input file .ss + INTEGER :: Nlines ! Number of lines in the input file, used to determine N + INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. + INTEGER :: Sttus ! Error in reading .ssexctn file + !CHARACTER :: Line ! Temp line of file + real(ReKi) :: WaveDir ! Temp wave direction angle (deg) + integer :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + u%DummyInput = 0.0_ReKi + + UnSS = -1 + p%N = 0 + + ! Open the .ss input file! + CALL GetNewUnit( UnSS ) + CALL OpenFInpFile ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', ErrStat2, ErrMsg2 ) ! Open file. + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Determine the number of states and size of the matrices + Nlines = 1 + + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Header',ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', WaveDir, 'WaveDir', 'Wave direction (deg)',ErrStat2, ErrMsg2) ! Reads in the second line, containing the wave direction + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + ! Check that excitation state-space file Beta angle (in degrees) matches the HydroDyn input file angle + if ( .not. EqualRealNos(InitInp%WaveDir, WaveDir) ) call SetErrStat(ErrID_FATAL,'HydroDyn Wave direction does not match the wave excitation wave direction',ErrStat,ErrMsg,'SS_Exc_Init') + + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%Tc, 'p%Tc', 'Time offset (s)',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%N, 'p%N', 'Number of states',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%spDOF, 6, 'p%spDOF', 'States per DOF',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + DO !Loop through all the lines of the file + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Header',Sttus,ErrMsg2 )! Reads the first entire line (Title header) + IF ( Sttus == ErrID_None ) THEN ! .TRUE. when data is read in successfully + Nlines=Nlines+1 + ELSE !We must have reached the end of the file + EXIT + END IF + END DO + + ! The input file contains the matrices A [NxN], B [Nx1] and C [6xN], so + !p%N = ( Nlines - 1 ) / 2 ! this is the number of states + + !Verifications on the input file + IF ( ( Nlines - 6 ) / 2 /= p%N) THEN + CALL SetErrStat(ErrID_Severe,'Error in the input file .ssexctn: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Exc_Init') + END IF + + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Now we can allocate the temporary matrices A, B and C + + CALL AllocAry( p%A, p%N, p%N, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( p%B, p%N, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( p%C, 6, p%N, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + REWIND (UNIT=UnSS) ! REWIND the file so we can read it in a second time. + + ! Skip the first 4 lines: (NOTE: no error handling here because we would have caught it the first time through) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Header', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Wave direction (deg)', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Time offset (s)', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Number of Excitation States', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Number of states per dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + + DO I = 1,p%N !Read A MatriX + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%A(I,:), p%N, 'p%A', 'A_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + END DO + + DO I = 1,p%N !Read B Matrix + CALL ReadVar( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', p%B(I), 'p%B', 'B_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + END DO + + DO I = 1,6 !Read C Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', p%C(I,:), p%N, 'p%C', 'C_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + END DO + CLOSE ( UnSS ) !Close .ss input file + UnSS = -1 ! Indicate the file is closed + + + CALL WrScr1 ( 'Using SS_Excitation Module, with '//TRIM( Num2LStr(p%N ))//' excitation states' ) + + ! Define parameters here: + + p%DT = Interval + + ! Allocate Wave-elevation related arrays + p%NStepWave = InitInp%NStepWave + allocate ( p%WaveElev0(0:p%NStepWave) , STAT=ErrStat2 ) + allocate ( p%WaveTime (0:p%NStepWave) , STAT=ErrStat2 ) +!TODO: Error Handling + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + p%WaveTime = InitInp%WaveTime + p%WaveElev0 = InitInp%WaveElev0 + + ! Define initial system states here: + CALL AllocAry( x%x, p%N, 'x%x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + x%x = 0 + + xd%DummyDiscState = 0 !TD: SS doesn't have disc states + z%DummyConstrState = 0 !TD: SS doesn't have constr states + + ! Define other States: + DO I=1,SIZE(OtherState%xdot) + CALL SS_Exc_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + END DO + OtherState%n = -1 + + ! misc vars: + + + ! Inputs + ! no inputs + + ! Define system output initializations (set up mesh) here: + + y%y = 0 + y%WriteOutput = 0 + + + ! Define initialization-routine output here: + + InitOut%WriteOutputHdr = (/ 'Time', 'FX ' , 'FY ' , 'FZ ' , 'MX ' , 'MY ' , 'MZ ' /) + InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + + + CALL CleanUp() ! deallocate local arrays + +CONTAINS + SUBROUTINE CleanUp() + + IF (UnSS > 0 ) CLOSE ( UnSS ) + + END SUBROUTINE CleanUp + +END SUBROUTINE SS_Exc_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE SS_Exc_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(SS_Exc_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(SS_Exc_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(SS_Exc_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + ! Destroy the input data: + + CALL SS_Exc_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL SS_Exc_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL SS_Exc_DestroyContState( x, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + ! Destroy misc vars: + CALL SS_Exc_DestroyMisc( m, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL SS_Exc_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE SS_Exc_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE SS_Exc_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(SS_Exc_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(SS_Exc_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SS_Exc_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER, PARAMETER :: IntegrationMethod = 3 + + + SELECT CASE ( IntegrationMethod ) + + CASE (1) ! RK4 + + CALL SS_Exc_RK4( t, n, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (2) ! AB4 + + CALL SS_Exc_AB4( t, n, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (3) ! ABM4 + + CALL SS_Exc_ABM4( t, n, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE DEFAULT !bjj: we already checked this at initialization, but for completeness: + + ErrStat = ErrID_Fatal + ErrMsg = ' Error in SS_Exc_UpdateStates: method must be 1 (RK4), 2 (AB4), or 3 (ABM4)' + RETURN + + END SELECT + + +END SUBROUTINE SS_Exc_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE SS_Exc_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Exc_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Exc_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None +! REAL(DbKi) :: test(6,1) + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Calc outputs of system, based on system states + ! [y] = [C]*[xr] + + y%y = matmul(p%C,x%x) + + ! Compute outputs here: + + y%WriteOutput(1) = REAL(Time,ReKi) + y%WriteOutput(2:7) = y%y + +END SUBROUTINE SS_Exc_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE SS_Exc_CalcContStateDeriv( Time, waveElev0, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + REAL(SiKi), INTENT(IN ) :: waveElev0 !< Wave elevation at origin at time: Time (m) + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Exc_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(SS_Exc_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL AllocAry( dxdt%x, p%N, 'SS_Exc_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev) RETURN + + ! Compute the first time derivatives of the continuous states here: + + !Calc dxdt of a state space system + ! [dxdt] = [A]*[xr]+B*[q] + + dxdt%x =matmul(p%A,x%x) + p%B * waveElev0 + +END SUBROUTINE SS_Exc_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +SUBROUTINE SS_Exc_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Exc_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Exc_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Update discrete states here: + + ! StateData%DiscState = + +END SUBROUTINE SS_Exc_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE SS_Exc_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Exc_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(SS_Exc_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(SS_Exc_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0 + +END SUBROUTINE SS_Exc_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." �16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +!! +SUBROUTINE SS_Exc_RK4( t, n, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(SS_Exc_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(SS_Exc_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(SS_Exc_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(SS_Exc_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(SS_Exc_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(SS_Exc_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + real(SiKi) :: waveElev0 ! interpolated value of the wave elevation at the origin + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SS_Exc_CopyContState( x, k1, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Exc_CopyContState( x, k2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Exc_CopyContState( x, k3, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Exc_CopyContState( x, k4, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Exc_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find waveElev0 for time, t+p%Tc + + waveElev0 = InterpWrappedStpReal ( REAL(t+p%Tc, SiKi), p%WaveTime(:), p%WaveElev0(:), m%LastIndWave, p%NStepWave + 1 ) + ! find xdot at t + CALL SS_Exc_CalcContStateDeriv( t, waveElev0, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k1%x = p%dt * xdot%x + x_tmp%x = x%x + 0.5 * k1%x + + ! find waveElev0 for time, t + p%Tc + dt/2 + waveElev0 = InterpWrappedStpReal ( REAL(t+p%Tc+p%DT/2.0, SiKi), p%WaveTime(:), p%WaveElev0(:), m%LastIndWave, p%NStepWave + 1 ) + + ! find xdot at t + dt/2 + CALL SS_Exc_CalcContStateDeriv( t + 0.5*p%dt, waveElev0, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k2%x = p%dt * xdot%x + x_tmp%x = x%x + 0.5 * k2%x + + ! find xdot at t + dt/2 + CALL SS_Exc_CalcContStateDeriv( t + 0.5*p%dt, waveElev0, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k3%x = p%dt * xdot%x + x_tmp%x = x%x + k3%x + + ! find waveElev0 for time, (t + p%Tc + dt) + waveElev0 = InterpWrappedStpReal ( REAL(t+p%Tc+p%DT, SiKi), p%WaveTime(:), p%WaveElev0(:), m%LastIndWave, p%NStepWave + 1 ) + + + ! find xdot at t + dt + CALL SS_Exc_CalcContStateDeriv( t + p%dt, waveElev0, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k4%x = p%dt * xdot%x + x%x = x%x + ( k1%x + 2. * k2%x + 2. * k3%x + k4%x ) / 6. + + ! clean up local variables: + CALL ExitThisRoutine( ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SS_Exc_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Exc_RK4:'//TRIM(Msg) + ErrStat = MAX(ErrStat,ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Exc_RK4 +!----------------------------------------------------------------------------- +!! This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +!! +SUBROUTINE SS_Exc_AB4( t, n, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + + real(SiKi) :: waveElev0 + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + if (OtherState%n .lt. n) then + + OtherState%n = n + + CALL SS_Exc_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat2, ErrMsg ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL SS_Exc_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL SS_Exc_CopyContState( OtherState%xdot ( 1 ), OtherState%xdot ( 2 ), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + + elseif (OtherState%n .gt. n) then + + CALL CheckError( ErrID_Fatal, ' Backing up in time is not supported with a multistep method.') + RETURN + + endif + + ! find waveElev at t + Tc + waveElev0 = InterpWrappedStpReal ( REAL(t+p%Tc, SiKi), p%WaveTime(:), p%WaveElev0(:), m%LastIndWave, p%NStepWave + 1 ) + + CALL SS_Exc_CalcContStateDeriv( t, waveElev0, p, x, xd, z, OtherState, m, OtherState%xdot ( 1 ), ErrStat2, ErrMsg2 ) ! initializes OtherState%xdot ( 1 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + if (n .le. 2) then + + CALL SS_Exc_RK4(t, n, utimes, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + else + + x%x = x%x + p%DT/24.0 * ( 55.*OtherState%xdot(1)%x - 59.*OtherState%xdot(2)%x & + + 37.*OtherState%xdot(3)%x - 9.*OtherState%xdot(4)%x ) + + + endif + + +CONTAINS + + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Exc_AB4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Exc_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SS_Exc_ABM4( t, n, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Exc_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Exc_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Exc_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(SS_Exc_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(SS_Exc_ContinuousStateType) :: xdot_pred ! Derivative of continuous states at t + real(SiKi) :: waveElev0 + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SS_Exc_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL SS_Exc_AB4( t, n, utimes, p, x_pred, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + if (n .gt. 2_IntKi) then + + waveElev0 = InterpWrappedStpReal ( REAL(t+p%Tc+p%DT, SiKi), p%WaveTime(:), p%WaveElev0(:), m%LastIndWave, p%NStepWave + 1 ) + CALL SS_Exc_CalcContStateDeriv(t + p%dt, waveElev0, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + x%x = x%x + p%DT/24. * ( 9. * xdot_pred%x + 19. * OtherState%xdot(1)%x & + - 5. * OtherState%xdot(2)%x & + + 1. * OtherState%xdot(3)%x ) + + else + + x%x = x_pred%x + + endif + + + ! clean up local variables: + CALL ExitThisRoutine() + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SS_Exc_DestroyContState( xdot_pred, ErrStat3, ErrMsg3 ) + CALL SS_Exc_DestroyContState( x_pred, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Exc_ABM4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Exc_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE SS_Excitation +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/SS_Excitation.txt b/OpenFAST/modules/hydrodyn/src/SS_Excitation.txt new file mode 100644 index 000000000..1c98d4948 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Excitation.txt @@ -0,0 +1,71 @@ +################## Registry for SS Excitation ############### +# column 1: <keyword> +# column 2: ModuleName/ModName or ^ to use the value from the previous line (ModName is nickname for ModuleName) +# column 3: Derived data type (without "ModName_" prefix) +# column 4: Derived data types's Field type +# column 5: Variable name +# column 6: Dimension of variable {:} for allocatable +# column 7: Variable's initial value (if set in the data type) +# column 8: I think this is a switch for mixed-language programming; it's mostly unused +# column 9: Description +# column 10: Units +################################################################################################################################### +# File last committed: $Date$ +# (File) Revision #: $Rev$ +# URL: $HeadURL$ +################################################################################################################################### + +typedef SS_Excitation/SS_Exc InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ ReKi WaveDir - - - "Wave direction" rad +typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m +typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s + +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {7} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {7} - - "Units of the output" - + +typedef ^ ContinuousStateType R8Ki x {:} - - "Continuous States" - + +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - + +# Define any data that are other states, including integer or logical states here: +typedef ^ OtherStateType IntKi n - - - "Current Time step" - +typedef ^ ^ SS_Exc_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - + + +# ..... 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 INTEGER LastIndWave - 1 - "last used index in the WaveTime 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 DbKi DT - - - "Time step" s +typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - +typedef ^ ^ IntKi spDOF {6} - - "States per DOF" - +typedef ^ ^ ReKi A {:}{:} - - "A matrix" - +typedef ^ ^ ReKi B {:} - - "B matrix" - +typedef ^ ^ ReKi C {:}{:} - - "C matrix" - +typedef ^ ^ INTEGER N - - - "Number of states" - +typedef ^ ^ DbKi Tc - - - "Time shift" s +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m +typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s + +# ..... Inputs ............................. +# Define inputs that are contained on the mesh here: +typedef ^ InputType ReKi DummyInput - - - "Remove this variable if you have input variables" - + + +# ..... Outputs ............................ +typedef ^ OutputType ReKi y {6} - - "Force/Moments" - +typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - + + + + diff --git a/OpenFAST/modules/hydrodyn/src/SS_Excitation_Driver.f90 b/OpenFAST/modules/hydrodyn/src/SS_Excitation_Driver.f90 new file mode 100644 index 000000000..e9170bf77 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Excitation_Driver.f90 @@ -0,0 +1,295 @@ +!********************************************************************************************************************************** +! SS_Excitation_Driver: This code tests the SS_Excitation module +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2018 National Renewable Energy Laboratory +! +! This file is part of SS_Excitation. +! +! 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 +! +!********************************************************************************************************************************** +PROGRAM SS_Excitation_Driver + + USE NWTC_Library + USE SS_Excitation + USE SS_Excitation_Types + + IMPLICIT NONE + + ! Program variables + + REAL(DbKi) :: Time ! Variable for storing time, in seconds + REAL(DbKi) :: waveDT + !REAL(DbKi) :: Time2(145201,1) ! Variable for storing time, in seconds + !REAL(DbKi) :: tdq(145201,7) ! Variable for storing time and body velocities, in m/s or rad/s + !REAL(DbKi) :: dq(145201,6) ! Variable for storing body velocities, in m/s or rad/s + REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds + !INTEGER(B1Ki), ALLOCATABLE :: SaveAry(:) ! Array to store packed data structure + + TYPE(SS_Exc_InitInputType) :: InitInData ! Input data for initialization + TYPE(SS_Exc_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(SS_Exc_ContinuousStateType) :: x ! Continuous states + TYPE(SS_Exc_ContinuousStateType) :: x_new ! Continuous states at updated time + TYPE(SS_Exc_DiscreteStateType) :: xd ! Discrete states + TYPE(SS_Exc_DiscreteStateType) :: xd_new ! Discrete states at updated time + TYPE(SS_Exc_ConstraintStateType) :: z ! Constraint states + TYPE(SS_Exc_ConstraintStateType) :: z_residual ! Residual of the constraint state equations (Z) + TYPE(SS_Exc_OtherStateType) :: OtherState ! Other states + + TYPE(SS_Exc_ParameterType) :: p ! Parameters + TYPE(SS_Exc_InputType) :: u(1) ! System inputs + REAL(DbKi) :: InputTimes(1) ! System input times + TYPE(SS_Exc_OutputType) :: y ! System outputs + TYPE(SS_Exc_MiscVarType) :: m ! misc/optimization variables + + TYPE(SS_Exc_ContinuousStateType) :: dxdt ! First time derivatives of the continuous states + + + + !Local Variables + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: I ! Loop counter (for time step) + INTEGER(IntKi) :: J ! Loop counter (for time step) + REAL(SiKi) :: ElevData + INTEGER(IntKi) :: UnWvEl ! Input file identifier + INTEGER(IntKi) :: Outputy ! Output file identifier + INTEGER(IntKi) :: ErrStat, ErrStat2 ! Status of error message + CHARACTER(1024) :: ErrMsg, ErrMsg2 ! Error message if ErrStat /= ErrID_None + INTEGER :: Sttus ! Error in reading input file + REAL(ReKi) :: Start ! CPU Time at start of the program + REAL(ReKi) :: Finnish ! CPU Time at the end of the program + REAL(ReKi) :: UsrTime + REAL(ReKi) :: Tratio + REAL(ReKi) :: Factor + CHARACTER(8) :: TimePer + INTEGER(4) :: EndTimes (8) ! An array holding the ending clock time of the simulation. + INTEGER(4) :: StrtTime (8) ! An array holding the starting clock time of the simulation. + REAL(ReKi) :: ClckTime + INTEGER :: len ! Number of input arguments + CHARACTER(1024) :: waveFile + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + ErrStat = ErrID_None + ErrMsg = '' + + call NWTC_Init() + + ! Call Time + !call cpu_time(start) + !call DATE_AND_TIME ( Values=StrtTime ) + + + + ! Populate the InitInData data structure + + + ! This file name should be the WAMIT file name without extension! + InitInData%InputFile = 'C:\Dev\Envision\all-changes\Test_Models\5MW_Baseline\HydroData\barge' + InitInData%WaveDir = 0.0_ReKi + InitInData%NStepWave = 14520 + waveDT = 0.25 + allocate ( InitInData%WaveElev0(0:InitInData%NStepWave) , STAT=ErrStat2 ) + allocate ( InitInData%WaveTime (0:InitInData%NStepWave) , STAT=ErrStat2 ) + + ! Construct the wave times array + do i = 0,InitInData%NStepWave + InitInData%WaveTime(i) = waveDT*i + end do + + ! Need to read in the wave elevation data to pass in as initialization data + waveFile = 'C:\Dev\Envision\all-changes\Test_Models\5MW_ITIBarge_DLL_WTurb_WavesIrr\barge.Elev' + call GetNewUnit ( UnWvEl, ErrStat, ErrMsg ) + call OpenFInpFile ( UnWvEl, trim(waveFile), ErrStat, ErrMsg ) ! Open wave elevation file. + if ( ErrStat /= 0 ) then + ErrStat = ErrID_Fatal + ErrMsg = ' Could not open wave elevation file.' + print*, ( ErrMsg ) + end if + + call ReadCom ( UnWvEl, trim(waveFile), 'Header',ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Excitation_Driver') + + do i = 0,InitInData%NStepWave - 1 + call ReadVar( UnWvEl,trim(waveFile), InitInData%WaveElev0(i), 'InitInData%WaveElev0(i)', 'Wave elevation',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Excitation_Driver') + end do + + close ( UnWvEl ) !Close dq input file + + ! Now set the last element of the Wave elevation array to match the initial elevation for wrapping + InitInData%WaveElev0(InitInData%NStepWave) = InitInData%WaveElev0(0) + + + + ! Set the driver's request for time interval here: This should be the Rdtn DT defined in the hydrodyn input file + TimeInterval = 0.005 + + CALL SS_Exc_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + + ! Initialize output file + call GetNewUnit ( Outputy, ErrStat, ErrMsg ) + CALL OpenFOutFile ( Outputy, (TRIM(InitInData%InputFile)//'.out'), ErrStat, ErrMsg) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error opening output file.' + CALL WrScr( ErrMsg ) + END IF + + WRITE(Outputy,*,IOSTAT=Sttus) InitOutData%WriteOutputHdr + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + ENDIF + + WRITE(Outputy,*,IOSTAT=Sttus) InitOutData%WriteOutputUnt + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + ENDIF + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + + CALL WrScr( 'Runnig SS_Excitation in Loose Coupling using a Adams-Bashforth-Moulton Method' ) + + CALL SS_Exc_CopyDiscState( xd, xd_new, MESH_NEWCOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + CALL SS_Exc_CopyContState( x, x_new, MESH_NEWCOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + ! + + DO n = 0,InitInData%NStepWave-1 + + Time = n*TimeInterval + InputTimes(1) = Time + + ! Get state variables at next step: constraint states (z) at step n, continuous and discrete states at step n + 1 + CALL SS_Exc_UpdateStates( Time, n, u, InputTimes, p, x_new, xd_new, z, OtherState, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + !print*, x%x + ! Calculate outputs at n + + CALL SS_Exc_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + ! Update x and xd with continuous and discrete states at n + 1 + ! Note that the constraint state guess at n+1 is the value of the constraint state at n (so it doesn't need updating here) + + CALL SS_Exc_CopyContState( x_new, x, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + CALL SS_Exc_CopyDiscState( xd_new, xd, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + !Write Output to file + WRITE(Outputy,'(7(e16.6))',IOSTAT=Sttus) y%WriteOutput + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + print*, ErrMsg + ENDIF + END DO + + + CALL SS_Exc_DestroyDiscState( xd_new, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + CALL SS_Exc_DestroyContState( x_new, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL SS_Exc_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + + !!!! GREG: This is also to ouput values (dont need it) + !CALL DATE_AND_TIME ( VALUES=EndTimes ) + !CALL cpu_time(finnish) + ! + !ClckTime = 0.001*( EndTimes(8) - StrtTime(8) ) + ( EndTimes(7) - StrtTime(7) ) + 60.0*( EndTimes(6) - StrtTime(6) ) & + ! + 3600.0*( EndTimes(5) - StrtTime(5) ) + 86400.0*( EndTimes(3) - StrtTime(3) ) + ! + !UsrTime = finnish-start + ! + !IF ( UsrTime /= 0.0 ) THEN + ! + !TRatio = Time / UsrTime + ! + !IF ( UsrTime > 86400.0 ) THEN + ! Factor = 1.0/86400.0 + ! TimePer = ' days' + !ELSEIF ( UsrTime > 3600.0 ) THEN + ! Factor = 1.0/3600.0 + ! TimePer = ' hours' + !ELSEIF ( UsrTime > 60.0 ) THEN + ! Factor = 1.0/60.0 + ! TimePer = ' minutes' + !ELSE + ! Factor = 1.0 + ! TimePer = ' seconds' + !ENDIF + ! + !CALL WrScr ( ' Total Real Time: '//TRIM( Flt2LStr( Factor*ClckTime ) )//TRIM( TimePer ) ) + !CALL WrScr ( ' Total CPU Time: '//TRIM( Flt2LStr( Factor*UsrTime ) )//TRIM( TimePer ) ) + !CALL WrScr ( ' Simulated Time: '//TRIM( Flt2LStr( Factor*REAL( Time ) ) )//TRIM( TimePer ) ) + !CALL WrScr ( ' Time Ratio (Sim/CPU): '//TRIM( Flt2LStr( TRatio ) ) ) + ! + !ENDIF + + + !!Write Output to file + ! WRITE(Outputy,'(1(e16.6))',IOSTAT=Sttus) TRatio + ! ! Ending routines + + CLOSE( Outputy ) + + + +END PROGRAM SS_Excitation_Driver + diff --git a/OpenFAST/modules/hydrodyn/src/SS_Excitation_Types.f90 b/OpenFAST/modules/hydrodyn/src/SS_Excitation_Types.f90 new file mode 100644 index 000000000..10966b9c6 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Excitation_Types.f90 @@ -0,0 +1,2331 @@ +!STARTOFREGISTRYGENERATEDFILE 'SS_Excitation_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 +!********************************************************************************************************************************* +! SS_Excitation_Types +!................................................................................................................................. +! This file is part of SS_Excitation. +! +! 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 SS_Excitation. 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 SS_Excitation_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= SS_Exc_InitInputType ======= + TYPE, PUBLIC :: SS_Exc_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + REAL(ReKi) :: WaveDir !< Wave direction [rad] + INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] + END TYPE SS_Exc_InitInputType +! ======================= +! ========= SS_Exc_InitOutputType ======= + TYPE, PUBLIC :: SS_Exc_InitOutputType + CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] + CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + END TYPE SS_Exc_InitOutputType +! ======================= +! ========= SS_Exc_ContinuousStateType ======= + TYPE, PUBLIC :: SS_Exc_ContinuousStateType + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: x !< Continuous States [-] + END TYPE SS_Exc_ContinuousStateType +! ======================= +! ========= SS_Exc_DiscreteStateType ======= + TYPE, PUBLIC :: SS_Exc_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< [-] + END TYPE SS_Exc_DiscreteStateType +! ======================= +! ========= SS_Exc_ConstraintStateType ======= + TYPE, PUBLIC :: SS_Exc_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< [-] + END TYPE SS_Exc_ConstraintStateType +! ======================= +! ========= SS_Exc_OtherStateType ======= + TYPE, PUBLIC :: SS_Exc_OtherStateType + INTEGER(IntKi) :: n !< Current Time step [-] + TYPE(SS_Exc_ContinuousStateType) , DIMENSION(1:4) :: xdot !< Old Values of dxdt to used by the solver (multistep method) [-] + END TYPE SS_Exc_OtherStateType +! ======================= +! ========= SS_Exc_MiscVarType ======= + TYPE, PUBLIC :: SS_Exc_MiscVarType + INTEGER(IntKi) :: LastIndWave = 1 !< last used index in the WaveTime array [-] + END TYPE SS_Exc_MiscVarType +! ======================= +! ========= SS_Exc_ParameterType ======= + TYPE, PUBLIC :: SS_Exc_ParameterType + REAL(DbKi) :: DT !< Time step [s] + INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] + INTEGER(IntKi) , DIMENSION(1:6) :: spDOF !< States per DOF [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: B !< B matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] + INTEGER(IntKi) :: N !< Number of states [-] + REAL(DbKi) :: Tc !< Time shift [s] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] + END TYPE SS_Exc_ParameterType +! ======================= +! ========= SS_Exc_InputType ======= + TYPE, PUBLIC :: SS_Exc_InputType + REAL(ReKi) :: DummyInput !< Remove this variable if you have input variables [-] + END TYPE SS_Exc_InputType +! ======================= +! ========= SS_Exc_OutputType ======= + TYPE, PUBLIC :: SS_Exc_OutputType + REAL(ReKi) , DIMENSION(1:6) :: y !< Force/Moments [-] + REAL(ReKi) , DIMENSION(1:7) :: WriteOutput !< output Data [kN] + END TYPE SS_Exc_OutputType +! ======================= +CONTAINS + SUBROUTINE SS_Exc_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SS_Exc_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 = 'SS_Exc_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%WaveDir = SrcInitInputData%WaveDir + DstInitInputData%NStepWave = SrcInitInputData%NStepWave +IF (ALLOCATED(SrcInitInputData%WaveElev0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElev0,1) + i1_u = UBOUND(SrcInitInputData%WaveElev0,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElev0)) THEN + ALLOCATE(DstInitInputData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElev0 = SrcInitInputData%WaveElev0 +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF + END SUBROUTINE SS_Exc_CopyInitInput + + SUBROUTINE SS_Exc_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SS_Exc_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveElev0)) THEN + DEALLOCATE(InitInputData%WaveElev0) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF + END SUBROUTINE SS_Exc_DestroyInitInput + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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%InputFile) ! InputFile + Re_BufSz = Re_BufSz + 1 ! WaveDir + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no + IF ( ALLOCATED(InData%WaveElev0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev0) ! WaveElev0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%WaveDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElev0) ) 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%WaveElev0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElev0,1), UBOUND(InData%WaveElev0,1) + ReKiBuf(Re_Xferred) = InData%WaveElev0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_PackInitInput + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WaveDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 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%WaveElev0)) DEALLOCATE(OutData%WaveElev0) + ALLOCATE(OutData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElev0,1), UBOUND(OutData%WaveElev0,1) + OutData%WaveElev0(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_UnPackInitInput + + SUBROUTINE SS_Exc_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SS_Exc_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 = 'SS_Exc_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt + END SUBROUTINE SS_Exc_CopyInitOutput + + SUBROUTINE SS_Exc_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SS_Exc_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyInitOutput + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END SUBROUTINE SS_Exc_PackInitOutput + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + i1_l = LBOUND(OutData%WriteOutputHdr,1) + i1_u = UBOUND(OutData%WriteOutputHdr,1) + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + i1_l = LBOUND(OutData%WriteOutputUnt,1) + i1_u = UBOUND(OutData%WriteOutputUnt,1) + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END SUBROUTINE SS_Exc_UnPackInitOutput + + SUBROUTINE SS_Exc_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(SS_Exc_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%x)) THEN + i1_l = LBOUND(SrcContStateData%x,1) + i1_u = UBOUND(SrcContStateData%x,1) + IF (.NOT. ALLOCATED(DstContStateData%x)) THEN + ALLOCATE(DstContStateData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%x = SrcContStateData%x +ENDIF + END SUBROUTINE SS_Exc_CopyContState + + SUBROUTINE SS_Exc_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(SS_Exc_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%x)) THEN + DEALLOCATE(ContStateData%x) +ENDIF + END SUBROUTINE SS_Exc_DestroyContState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + Int_BufSz = Int_BufSz + 1 ! x allocated yes/no + IF ( ALLOCATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + 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%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_PackContState + + SUBROUTINE SS_Exc_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(SS_Exc_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x 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%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_UnPackContState + + SUBROUTINE SS_Exc_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(SS_Exc_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 = 'SS_Exc_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE SS_Exc_CopyDiscState + + SUBROUTINE SS_Exc_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(SS_Exc_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyDiscState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 SS_Exc_PackDiscState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Exc_UnPackDiscState + + SUBROUTINE SS_Exc_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(SS_Exc_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 = 'SS_Exc_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE SS_Exc_CopyConstrState + + SUBROUTINE SS_Exc_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(SS_Exc_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyConstrState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 SS_Exc_PackConstrState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Exc_UnPackConstrState + + SUBROUTINE SS_Exc_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(SS_Exc_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%n = SrcOtherStateData%n + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL SS_Exc_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + END SUBROUTINE SS_Exc_CopyOtherState + + SUBROUTINE SS_Exc_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(SS_Exc_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL SS_Exc_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + END SUBROUTINE SS_Exc_DestroyOtherState + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + Int_BufSz = Int_BufSz + 1 ! n + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL SS_Exc_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%n + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL SS_Exc_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 SUBROUTINE SS_Exc_PackOtherState + + SUBROUTINE SS_Exc_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(SS_Exc_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_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%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%xdot,1) + i1_u = UBOUND(OutData%xdot,1) + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 SS_Exc_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END SUBROUTINE SS_Exc_UnPackOtherState + + SUBROUTINE SS_Exc_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(SS_Exc_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 = 'SS_Exc_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + END SUBROUTINE SS_Exc_CopyMisc + + SUBROUTINE SS_Exc_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyMisc + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 ! LastIndWave + 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%LastIndWave + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SS_Exc_PackMisc + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SS_Exc_UnPackMisc + + SUBROUTINE SS_Exc_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SS_Exc_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%spDOF = SrcParamData%spDOF +IF (ALLOCATED(SrcParamData%A)) THEN + i1_l = LBOUND(SrcParamData%A,1) + i1_u = UBOUND(SrcParamData%A,1) + i2_l = LBOUND(SrcParamData%A,2) + i2_u = UBOUND(SrcParamData%A,2) + IF (.NOT. ALLOCATED(DstParamData%A)) THEN + ALLOCATE(DstParamData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%A = SrcParamData%A +ENDIF +IF (ALLOCATED(SrcParamData%B)) THEN + i1_l = LBOUND(SrcParamData%B,1) + i1_u = UBOUND(SrcParamData%B,1) + IF (.NOT. ALLOCATED(DstParamData%B)) THEN + ALLOCATE(DstParamData%B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%B = SrcParamData%B +ENDIF +IF (ALLOCATED(SrcParamData%C)) THEN + i1_l = LBOUND(SrcParamData%C,1) + i1_u = UBOUND(SrcParamData%C,1) + i2_l = LBOUND(SrcParamData%C,2) + i2_u = UBOUND(SrcParamData%C,2) + IF (.NOT. ALLOCATED(DstParamData%C)) THEN + ALLOCATE(DstParamData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C = SrcParamData%C +ENDIF + DstParamData%N = SrcParamData%N + DstParamData%Tc = SrcParamData%Tc +IF (ALLOCATED(SrcParamData%WaveElev0)) THEN + i1_l = LBOUND(SrcParamData%WaveElev0,1) + i1_u = UBOUND(SrcParamData%WaveElev0,1) + IF (.NOT. ALLOCATED(DstParamData%WaveElev0)) THEN + ALLOCATE(DstParamData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev0 = SrcParamData%WaveElev0 +ENDIF +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF + END SUBROUTINE SS_Exc_CopyParam + + SUBROUTINE SS_Exc_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SS_Exc_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%A)) THEN + DEALLOCATE(ParamData%A) +ENDIF +IF (ALLOCATED(ParamData%B)) THEN + DEALLOCATE(ParamData%B) +ENDIF +IF (ALLOCATED(ParamData%C)) THEN + DEALLOCATE(ParamData%C) +ENDIF +IF (ALLOCATED(ParamData%WaveElev0)) THEN + DEALLOCATE(ParamData%WaveElev0) +ENDIF +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF + END SUBROUTINE SS_Exc_DestroyParam + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + SIZE(InData%spDOF) ! spDOF + Int_BufSz = Int_BufSz + 1 ! A allocated yes/no + IF ( ALLOCATED(InData%A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! A upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%A) ! A + END IF + Int_BufSz = Int_BufSz + 1 ! B allocated yes/no + IF ( ALLOCATED(InData%B) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%B) ! B + END IF + Int_BufSz = Int_BufSz + 1 ! C allocated yes/no + IF ( ALLOCATED(InData%C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C) ! C + END IF + Int_BufSz = Int_BufSz + 1 ! N + Db_BufSz = Db_BufSz + 1 ! Tc + Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no + IF ( ALLOCATED(InData%WaveElev0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev0) ! WaveElev0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%spDOF,1), UBOUND(InData%spDOF,1) + IntKiBuf(Int_Xferred) = InData%spDOF(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%A) ) 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%A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%A,2), UBOUND(InData%A,2) + DO i1 = LBOUND(InData%A,1), UBOUND(InData%A,1) + ReKiBuf(Re_Xferred) = InData%A(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%B) ) 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%B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) + ReKiBuf(Re_Xferred) = InData%B(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C) ) 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%C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C,2), UBOUND(InData%C,2) + DO i1 = LBOUND(InData%C,1), UBOUND(InData%C,1) + ReKiBuf(Re_Xferred) = InData%C(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%N + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Tc + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElev0) ) 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%WaveElev0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElev0,1), UBOUND(InData%WaveElev0,1) + ReKiBuf(Re_Xferred) = InData%WaveElev0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_PackParam + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%spDOF,1) + i1_u = UBOUND(OutData%spDOF,1) + DO i1 = LBOUND(OutData%spDOF,1), UBOUND(OutData%spDOF,1) + OutData%spDOF(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! A 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%A)) DEALLOCATE(OutData%A) + ALLOCATE(OutData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%A,2), UBOUND(OutData%A,2) + DO i1 = LBOUND(OutData%A,1), UBOUND(OutData%A,1) + OutData%A(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! B 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%B)) DEALLOCATE(OutData%B) + ALLOCATE(OutData%B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) + OutData%B(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C 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%C)) DEALLOCATE(OutData%C) + ALLOCATE(OutData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C,2), UBOUND(OutData%C,2) + DO i1 = LBOUND(OutData%C,1), UBOUND(OutData%C,1) + OutData%C(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%N = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Tc = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 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%WaveElev0)) DEALLOCATE(OutData%WaveElev0) + ALLOCATE(OutData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElev0,1), UBOUND(OutData%WaveElev0,1) + OutData%WaveElev0(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Exc_UnPackParam + + SUBROUTINE SS_Exc_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_InputType), INTENT(IN) :: SrcInputData + TYPE(SS_Exc_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%DummyInput = SrcInputData%DummyInput + END SUBROUTINE SS_Exc_CopyInput + + SUBROUTINE SS_Exc_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SS_Exc_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyInput + + SUBROUTINE SS_Exc_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(SS_Exc_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 = 'SS_Exc_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 + Re_BufSz = Re_BufSz + 1 ! DummyInput + 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%DummyInput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Exc_PackInput + + SUBROUTINE SS_Exc_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(SS_Exc_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_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 + OutData%DummyInput = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Exc_UnPackInput + + SUBROUTINE SS_Exc_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Exc_OutputType), INTENT(IN) :: SrcOutputData + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'SS_Exc_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%y = SrcOutputData%y + DstOutputData%WriteOutput = SrcOutputData%WriteOutput + END SUBROUTINE SS_Exc_CopyOutput + + SUBROUTINE SS_Exc_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Exc_DestroyOutput + + SUBROUTINE SS_Exc_PackOutput( 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(SS_Exc_OutputType), 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 = 'SS_Exc_PackOutput' + ! 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%y) ! y + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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%y,1), UBOUND(InData%y,1) + ReKiBuf(Re_Xferred) = InData%y(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Exc_PackOutput + + SUBROUTINE SS_Exc_UnPackOutput( 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(SS_Exc_OutputType), 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 = 'SS_Exc_UnPackOutput' + ! 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%y,1) + i1_u = UBOUND(OutData%y,1) + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%WriteOutput,1) + i1_u = UBOUND(OutData%WriteOutput,1) + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Exc_UnPackOutput + + + SUBROUTINE SS_Exc_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SS_Exc_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SS_Exc_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SS_Exc_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SS_Exc_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SS_Exc_Input_ExtrapInterp + + + SUBROUTINE SS_Exc_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SS_Exc_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(SS_Exc_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%DummyInput - u2%DummyInput) + u_out%DummyInput = u1%DummyInput + b * ScaleFactor + END SUBROUTINE SS_Exc_Input_ExtrapInterp1 + + + SUBROUTINE SS_Exc_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SS_Exc_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(SS_Exc_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(SS_Exc_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%DummyInput - u2%DummyInput) + t(2)**2*(-u1%DummyInput + u3%DummyInput))* scaleFactor + c = ( (t(2)-t(3))*u1%DummyInput + t(3)*u2%DummyInput - t(2)*u3%DummyInput ) * scaleFactor + u_out%DummyInput = u1%DummyInput + b + c * t_out + END SUBROUTINE SS_Exc_Input_ExtrapInterp2 + + + SUBROUTINE SS_Exc_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SS_Exc_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SS_Exc_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SS_Exc_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SS_Exc_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SS_Exc_Output_ExtrapInterp + + + SUBROUTINE SS_Exc_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SS_Exc_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(SS_Exc_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) + b = -(y1%y(i1) - y2%y(i1)) + y_out%y(i1) = y1%y(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) + b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO + END SUBROUTINE SS_Exc_Output_ExtrapInterp1 + + + SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SS_Exc_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(SS_Exc_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(SS_Exc_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Exc_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) + b = (t(3)**2*(y1%y(i1) - y2%y(i1)) + t(2)**2*(-y1%y(i1) + y3%y(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%y(i1) + t(3)*y2%y(i1) - t(2)*y3%y(i1) ) * scaleFactor + y_out%y(i1) = y1%y(i1) + b + c * t_out + END DO + 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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO + END SUBROUTINE SS_Exc_Output_ExtrapInterp2 + +END MODULE SS_Excitation_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/SS_Radiation.f90 b/OpenFAST/modules/hydrodyn/src/SS_Radiation.f90 new file mode 100644 index 000000000..62a9b873d --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Radiation.f90 @@ -0,0 +1,1002 @@ +!********************************************************************************************************************************** +! The SS_Radiation and SS_Radiation_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. SS_Radiations_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012, 2015 National Renewable Energy Laboratory +! +! This file is part of SS_Radiation. +! +! 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 +! +!********************************************************************************************************************************** +MODULE SS_Radiation + + USE SS_Radiation_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: SS_Rad_ProgDesc = ProgDesc( 'SS_Radiation', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: SS_Rad_Init ! Initialization routine + PUBLIC :: SS_Rad_End ! Ending routine (includes clean up) + + PUBLIC :: SS_Rad_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: SS_Rad_CalcOutput ! Routine for computing outputs + + PUBLIC :: SS_Rad_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: SS_Rad_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: SS_Rad_UpdateDiscState ! Tight coupling routine for updating discrete states + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SS_Rad_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(SS_Rad_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SS_Rad_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(SS_Rad_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(SS_Rad_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(SS_Rad_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(SS_Rad_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(SS_Rad_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) SS_Rad_UpdateStates() is called in loose coupling & + !! (2) SS_Rad_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(SS_Rad_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + 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 :: Rad_A (:,:) ! A matrix of the radiation state-space system on the input file ss + REAL(ReKi), ALLOCATABLE :: Rad_B (:,:) ! B matrix of the radiation state-space system on the input file ss + REAL(ReKi), ALLOCATABLE :: Rad_C (:,:) ! C matrix of the radiation state-space system on the input file ss + + INTEGER :: I ! Generic index +! INTEGER :: J ! Generic index + INTEGER :: xx (1,6) ! Active DOF's on the input file .ss + INTEGER :: DOFs ! Number of DOFS + INTEGER :: N ! Number of states + INTEGER :: Nlines ! Number of lines in the input file, used to determine N + INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. + INTEGER :: Sttus ! Error in reading .ss file + !CHARACTER :: Line ! Temp line of file + + integer :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + UnSS = -1 + N = 0 + + ! Open the .ss input file! + CALL GetNewUnit( UnSS ) + CALL OpenFInpFile ( UnSS, TRIM(InitInp%InputFile)//'.ss', ErrStat2, ErrMsg2 ) ! Open file. + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Determine the number of states and size of the matrices + Nlines = 1 + + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Header',ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', xx(1,:), 6, 'xx', 'xx vector containing the enabled dofs',ErrStat2, ErrMsg2) ! Reads in the second line, containing the active dofs vector + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ss', N, 'N', 'Number of Dofs',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', p%spdof, 6, 'spdof', 'spdof vector containing the number of states per dofs',ErrStat2, ErrMsg2) ! Reads in the forth line, containing the state per dofs vector + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + DO !Loop through all the lines of the file + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Header',Sttus,ErrMsg2 )! Reads the first entire line (Title header) + IF ( Sttus == ErrID_None ) THEN ! .TRUE. when data is read in successfully + Nlines=Nlines+1 + ELSE !We must have reach the end of the file + EXIT + END IF + END DO + + ! The input file contains the matrices A [NxN], B [Nx6] and C [6xN], so + !p%N = ( Nlines - 6 ) / 2 ! this is the number of states + + !Verifications on the input file + IF ( ( Nlines - 6 ) / 2 /= N) THEN + CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Rad_Init') + END IF + + IF ( N /= SUM(p%spdof)) THEN + CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Rad_Init') + END IF + + !Verify if the DOFs active in the input file correspond to the ones active by FAST in this run + DO I=1,6 !Loop through all 6 DOFs + IF ( InitInp%DOFs (1,I) == 1) THEN ! True when the current DOF is active in FAST + IF ( xx (1,I) /= 1) THEN ! True if a DOF enabled by FAST is not available in the INPUT File + CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The enabled DOFs in the current FAST Simulation don`t match the ones on the input file .ss!',ErrStat,ErrMsg,'SS_Rad_Init') + END IF + END IF + END DO + + DOFs = SUM (xx) !Number of DOFS in the input file + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Now we can allocate the temporary matrices A, B and C + + CALL AllocAry( Rad_A, N, N, 'Rad_A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_B, N, DOFs, 'Rad_B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_C, DOFs, N, 'Rad_C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + REWIND (UNIT=UnSS) ! REWIND the file so we can read it in a second time. + + ! Skip the first 4 lines: (NOTE: no error handling here because we would have caught it the first time through) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Header', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Enabled dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'N', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'N per dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + + DO I = 1,N !Read A MatriX + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', Rad_A(I,:), N, 'Rad_A', 'A_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + END DO + + DO I = 1,N !Read B Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_B(I,:), 6, 'Rad_B', 'B_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + END DO + + DO I = 1,6 !Read C Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_C(I,:), N, 'Rad_C', 'C_Matrix',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + END DO + + CLOSE ( UnSS ) !Close .ss input file + UnSS = -1 ! Indicate the file is closed + + !Now we are ready to reduce the matrices to the correspondent active dofs in FAST + p%N=0 + DO I=1,6 !For each state + IF ( InitInp%DOFs (1,I) == 1) THEN ! True when the current DOF is active in FAST + p%N = p%N + p%spdof(I) !Add the correspondent number of states to the vector + END IF + END DO + + CALL WrScr1 ( 'Using SS_Radiation Module, with '//TRIM( Num2LStr(p%N ))//' of '//TRIM( Num2LStr(N ))// ' radiation states' ) + + !Now we can allocate the final size of the SS matrices + CALL AllocAry( p%A, p%N, p%N, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( p%B, p%N, 6, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( p%c, 6, p%N, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + + ! if these arrays weren't allocated, return before a seg fault occurs: + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + !Finaly we write the ss matrices, based on the ones on the input file and on the active dofs + + IF ( p%N == N ) THEN !The matrices are the same + + p%A = Rad_A + p%B = Rad_B + p%C = Rad_C + + ELSE !We need to cut some of the lines and columns + + p%A = 0 + p%B = 0 + p%C = 0 + + + N=1 !Use as number of active states introduced + + DO I=1,6 !For each dof... + IF ( InitInp%DOFs (1,I) == 1 .AND. sum(p%spdof(1:I))<size(Rad_A(:,1))) THEN ! That is enabled in FAST + + p%A (N:N+p%spdof(I),N:N+p%spdof(I)) = Rad_A (sum(p%spdof(1:I-1))+1:sum(p%spdof(1:I)),sum(p%spdof(1:I-1))+1:sum(p%spdof(1:I))) + p%B (N:N+p%spdof(I),:)= Rad_B (sum(p%spdof(1:I-1))+1:sum(p%spdof(1:I)),:) + p%C (:,N:N+p%spdof(I))= Rad_C (:,sum(p%spdof(1:I-1))+1:sum(p%spdof(1:I))) + + N = N + p%spdof(I) !Number of lines added to the A and B Matrix and columns to the C Matrix + END IF + END DO + END IF + + ! Define parameters here: + + p%DT = Interval + + ! Define initial system states here: + CALL AllocAry( x%x, p%N, 'x%x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + x%x = 0 + + xd%DummyDiscState = 0 !TD: SS doesn't have disc states + z%DummyConstrState = 0 !TD: SS doesn't have constr states + + ! Define other States: + DO I=1,SIZE(OtherState%xdot) + CALL SS_Rad_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + END DO + OtherState%n = -1 + + ! misc vars: + m%DummyMiscVar = 0 + + !Inputs + u%dq = 0 !6 DoF's velocities + + ! Define system output initializations (set up mesh) here: + + y%y = 0 + y%WriteOutput = 0 + + + ! Define initialization-routine output here: + + InitOut%WriteOutputHdr = (/ 'Time', 'F1 ' , 'F2 ' , 'F3 ' , 'F4 ' , 'F5 ' , 'F6 ' /) + InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + + !p%DT=Interval + + CALL CleanUp() ! deallocate local arrays + +CONTAINS + SUBROUTINE CleanUp() + + IF (UnSS > 0 ) CLOSE ( UnSS ) + + IF ( ALLOCATED( Rad_A ) ) DEALLOCATE( Rad_A ) + IF ( ALLOCATED( Rad_B ) ) DEALLOCATE( Rad_B ) + IF ( ALLOCATED( Rad_C ) ) DEALLOCATE( Rad_C ) + + END SUBROUTINE CleanUp + +END SUBROUTINE SS_Rad_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE SS_Rad_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(SS_Rad_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(SS_Rad_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(SS_Rad_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + ! Destroy the input data: + + CALL SS_Rad_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL SS_Rad_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL SS_Rad_DestroyContState( x, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + ! Destroy misc vars: + CALL SS_Rad_DestroyMisc( m, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL SS_Rad_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE SS_Rad_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE SS_Rad_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(SS_Rad_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(SS_Rad_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SS_Rad_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER, PARAMETER :: IntegrationMethod = 3 + + + SELECT CASE ( IntegrationMethod ) + + CASE (1) ! RK4 + + CALL SS_Rad_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (2) ! AB4 + + CALL SS_Rad_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE (3) ! ABM4 + + CALL SS_Rad_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + CASE DEFAULT !bjj: we already checked this at initialization, but for completeness: + + ErrStat = ErrID_Fatal + ErrMsg = ' Error in SS_Rad_UpdateStates: method must be 1 (RK4), 2 (AB4), or 3 (ABM4)' + RETURN + + END SELECT + + +END SUBROUTINE SS_Rad_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE SS_Rad_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Rad_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Rad_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None +! REAL(DbKi) :: test(6,1) + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Calc outputs of system, based on system states + ! [y] = [C]*[xr] + + y%y = matmul(p%C,x%x) + + ! Compute outputs here: + + y%WriteOutput(1) = REAL(Time,ReKi) + y%WriteOutput(2:7) = y%y + +END SUBROUTINE SS_Rad_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE SS_Rad_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Rad_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Rad_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(SS_Rad_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL AllocAry( dxdt%x, p%N, 'SS_Rad_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev) RETURN + + ! Compute the first time derivatives of the continuous states here: + + !Calc dxdt of a state space system + ! [dxdt] = [A]*[xr]+B*[q] + + dxdt%x =matmul(p%A,x%x) + matmul( p%B, u%dq) + +END SUBROUTINE SS_Rad_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +SUBROUTINE SS_Rad_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Rad_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Rad_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Update discrete states here: + + ! StateData%DiscState = + +END SUBROUTINE SS_Rad_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE SS_Rad_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(SS_Rad_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(SS_Rad_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + TYPE(SS_Rad_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0 + +END SUBROUTINE SS_Rad_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta."Sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +!! +SUBROUTINE SS_Rad_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(SS_Rad_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(SS_Rad_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(SS_Rad_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(SS_Rad_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(SS_Rad_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(SS_Rad_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(SS_Rad_InputType) :: u_interp ! interpolated value of inputs + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SS_Rad_CopyContState( x, k1, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Rad_CopyContState( x, k2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Rad_CopyContState( x, k3, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Rad_CopyContState( x, k4, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL SS_Rad_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + CALL SS_Rad_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! interpolate u to find u_interp = u(t) + CALL SS_Rad_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + CALL SS_Rad_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k1%x = p%dt * xdot%x + x_tmp%x = x%x + 0.5 * k1%x + + ! interpolate u to find u_interp = u(t + dt/2) + CALL SS_Rad_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt/2 + CALL SS_Rad_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k2%x = p%dt * xdot%x + x_tmp%x = x%x + 0.5 * k2%x + + ! find xdot at t + dt/2 + CALL SS_Rad_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k3%x = p%dt * xdot%x + x_tmp%x = x%x + k3%x + + ! interpolate u to find u_interp = u(t + dt) + CALL SS_Rad_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt + CALL SS_Rad_CalcContStateDeriv( t + p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k4%x = p%dt * xdot%x + x%x = x%x + ( k1%x + 2. * k2%x + 2. * k3%x + k4%x ) / 6. + + ! clean up local variables: + CALL ExitThisRoutine( ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SS_Rad_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + + CALL SS_Rad_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Rad_RK4:'//TRIM(Msg) + ErrStat = MAX(ErrStat,ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Rad_RK4 +!----------------------------------------------------------------------------- +!! This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +!! +SUBROUTINE SS_Rad_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + TYPE(SS_Rad_InputType) :: u_interp + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + if (OtherState%n .lt. n) then + + OtherState%n = n + + CALL SS_Rad_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat2, ErrMsg ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL SS_Rad_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL SS_Rad_CopyContState( OtherState%xdot ( 1 ), OtherState%xdot ( 2 ), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + + elseif (OtherState%n .gt. n) then + + CALL CheckError( ErrID_Fatal, ' Backing up in time is not supported with a multistep method.') + RETURN + + endif + + + ! Allocate the input arrays + CALL SS_Rad_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! need xdot at t + CALL SS_Rad_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL SS_Rad_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, OtherState%xdot ( 1 ), ErrStat2, ErrMsg2 ) ! initializes OtherState%xdot ( 1 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + if (n .le. 2) then + + CALL SS_Rad_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + else + + x%x = x%x + p%DT/24.0 * ( 55.*OtherState%xdot(1)%x - 59.*OtherState%xdot(2)%x & + + 37.*OtherState%xdot(3)%x - 9.*OtherState%xdot(4)%x ) + + + endif + + + ! clean up local variables: + CALL ExitThisRoutine() + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SS_Rad_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Rad_AB4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Rad_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SS_Rad_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SS_Rad_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SS_Rad_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SS_Rad_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(SS_Rad_InputType) :: u_interp ! Inputs at t + TYPE(SS_Rad_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(SS_Rad_ContinuousStateType) :: xdot_pred ! Derivative of continuous states at t + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SS_Rad_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL SS_Rad_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + if (n .gt. 2_IntKi) then + ! allocate the arrays in u_interp + CALL SS_Rad_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL SS_Rad_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL SS_Rad_CalcContStateDeriv(t + p%dt, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + x%x = x%x + p%DT/24. * ( 9. * xdot_pred%x + 19. * OtherState%xdot(1)%x & + - 5. * OtherState%xdot(2)%x & + + 1. * OtherState%xdot(3)%x ) + + else + + x%x = x_pred%x + + endif + + + ! clean up local variables: + CALL ExitThisRoutine() + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SS_Rad_DestroyContState( xdot_pred, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyContState( x_pred, ErrStat3, ErrMsg3 ) + CALL SS_Rad_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SS_Rad_ABM4:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE SS_Rad_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE SS_Radiation +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/SS_Radiation.txt b/OpenFAST/modules/hydrodyn/src/SS_Radiation.txt new file mode 100644 index 000000000..1d8866dea --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Radiation.txt @@ -0,0 +1,61 @@ +################## Registry for SS Radiation ############### +# column 1: <keyword> +# column 2: ModuleName/ModName or ^ to use the value from the previous line (ModName is nickname for ModuleName) +# column 3: Derived data type (without "ModName_" prefix) +# column 4: Derived data types's Field type +# column 5: Variable name +# column 6: Dimension of variable {:} for allocatable +# column 7: Variable's initial value (if set in the data type) +# column 8: I think this is a switch for mixed-language programming; it's mostly unused +# column 9: Description +# column 10: Units +################################################################################################################################### + +typedef SS_Radiation/SS_Rad InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ ReKi DOFs {1}{6} - - "Vector with enable platf. DOFs" "m/s or rad/s" + +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {7} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {7} - - "Units of the output" - + +typedef ^ ContinuousStateType R8Ki x {:} - - "Continuous States" - + + +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - + +# Define any data that are other states, including integer or logical states here: +typedef ^ OtherStateType IntKi n - - - "Current Time step" - +typedef ^ ^ SS_Rad_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - + + +# ..... 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 DummyMiscVar - - - "Remove this variable if you have misc/optimization 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 DbKi DT - - - "Time step" seconds +typedef ^ ^ ReKi A {:}{:} - - "A matrix" - +typedef ^ ^ ReKi B {:}{:} - - "B matrix" - +typedef ^ ^ ReKi C {:}{:} - - "C matrix" - +typedef ^ ^ INTEGER N - - - "Number of states" - +typedef ^ ^ INTEGER spdof {6} - - "States per dof" - + +# ..... Inputs ............................. +# Define inputs that are contained on the mesh here: +typedef ^ InputType ReKi dq {6} - - "Body velocities" - + + +# ..... Outputs ............................ +typedef ^ OutputType ReKi y {6} - - "Force" - +typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - + + + + diff --git a/OpenFAST/modules/hydrodyn/src/SS_Radiation_DriverCode.f90 b/OpenFAST/modules/hydrodyn/src/SS_Radiation_DriverCode.f90 new file mode 100644 index 000000000..49f8e464c --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Radiation_DriverCode.f90 @@ -0,0 +1,282 @@ +!********************************************************************************************************************************** +! SS_Radiation_DriverCode: This code tests the template modules +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012 National Renewable Energy Laboratory +! +! This file is part of SS_Radiation. +! +! SS_Radiation is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as +! published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +! of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License along with SS_Radiation. +! If not, see <http://www.gnu.org/licenses/>. +! +!********************************************************************************************************************************** +PROGRAM SS_Radiation_Driver + + USE NWTC_Library + USE SS_Radiation + USE SS_Radiation_Types + + IMPLICIT NONE + + ! Program variables + + REAL(DbKi) :: Time ! Variable for storing time, in seconds + REAL(DbKi) :: Time2(145201,1) ! Variable for storing time, in seconds + REAL(DbKi) :: tdq(145201,7) ! Variable for storing time and body velocities, in m/s or rad/s + REAL(DbKi) :: dq(145201,6) ! Variable for storing body velocities, in m/s or rad/s + REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds + INTEGER(B1Ki), ALLOCATABLE :: SaveAry(:) ! Array to store packed data structure + + TYPE(SS_Rad_InitInputType) :: InitInData ! Input data for initialization + TYPE(SS_Rad_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(SS_Rad_ContinuousStateType) :: x ! Continuous states + TYPE(SS_Rad_ContinuousStateType) :: x_new ! Continuous states at updated time + TYPE(SS_Rad_DiscreteStateType) :: xd ! Discrete states + TYPE(SS_Rad_DiscreteStateType) :: xd_new ! Discrete states at updated time + TYPE(SS_Rad_ConstraintStateType) :: z ! Constraint states + TYPE(SS_Rad_ConstraintStateType) :: z_residual ! Residual of the constraint state equations (Z) + TYPE(SS_Rad_OtherStateType) :: OtherState ! Other states + + TYPE(SS_Rad_ParameterType) :: p ! Parameters + TYPE(SS_Rad_InputType) :: u ! System inputs + TYPE(SS_Rad_OutputType) :: y ! System outputs + TYPE(SS_Rad_MiscVarType) :: m ! misc/optimization variables + + TYPE(SS_Rad_ContinuousStateType) :: dxdt ! First time derivatives of the continuous states + + + + !Local Variables + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: I ! Loop counter (for time step) + INTEGER(IntKi) :: J ! Loop counter (for time step) + INTEGER(IntKi) :: Inputdq ! Input file identifier + INTEGER(IntKi) :: Outputy ! Output file identifier + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER :: Sttus ! Error in reading input file + REAL(ReKi) :: Start ! CPU Time at start of the program + REAL(ReKi) :: Finnish ! CPU Time at the end of the program + REAL(ReKi) :: UsrTime + REAL(ReKi) :: Tratio + REAL(ReKi) :: Factor + CHARACTER(8) :: TimePer + INTEGER(4) :: EndTimes (8) ! An array holding the ending clock time of the simulation. + INTEGER(4) :: StrtTime (8) ! An array holding the starting clock time of the simulation. + REAL(ReKi) :: ClckTime + INTEGER :: len ! Number of input arguments + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + ! Call Time + CALL cpu_time(start) + CALL DATE_AND_TIME ( Values=StrtTime ) + + ! Populate the InitInData data structure here: + + InitInData%InputFile = 'C:\Users\tduarte\Documents\SS_Module\Comparisons\FAST_output_freq\spar_IMP_097' + !!! GREG !!!: This file name should be the WAMIT file name without extension! + + + InitInData%Dofs = 1 + !!! GREG: This is a vector of [1x6] containing 0 and 1 if each of the 6 dofs is enabled or not (as we discussed today in the meeting) + + + ! Set the driver's request for time interval here: + TimeInterval = 0.025 ! Glue code's request for delta time (likely based on information from other modules) + !!! GREG: This should be the Rdtn DT defined in the platform input file@ + + CALL SS_Rad_Init( InitInData, u, p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + !!! GREG: This version reads in the desired file containing the platform velocities. You don't need this in your case. + CALL CheckArgs( InitInData%InputFile ) + + CALL Get_Arg_Num (len ) + + ! Read the time dependent input vector dq + CALL OpenFInpFile ( Inputdq, (TRIM(InitInData%InputFile)//'.txt'), ErrStat ) ! Open motion file. + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating memory for the dq array.' + print*, ( ErrMsg ) + END IF + + + + DO I = 1,145201 !Read dq Matrix + READ (Inputdq,*,IOSTAT=Sttus) (tdq (I,J), J=1,7) + ENDDO + + CLOSE ( Inputdq ) !Close dq input file + + Time2(:,1) = tdq(:,1) + dq = tdq(:,2:7) + + !!!GREG: here the output file is opened, you should not need this + !Initialize output file + CALL OpenFOutFile ( Outputy, (TRIM(InitInData%InputFile)//'.out'), ErrStat) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error opening output file.' + CALL WrScr( ErrMsg ) + END IF + + WRITE(Outputy,*,IOSTAT=Sttus) InitOutData%WriteOutputHdr + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + ENDIF + + WRITE(Outputy,*,IOSTAT=Sttus) InitOutData%WriteOutputUnt + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + ENDIF + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + + CALL WrScr( 'Runnig SS_Radiation in Loose Coupling using a Adams-Bashforth-Moulton Method' ) + + CALL SS_Rad_CopyDiscState( xd, xd_new, MESH_NEWCOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + CALL SS_Rad_CopyContState( x, x_new, MESH_NEWCOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + ! +!CALL cpu_time(T1) + DO n = 0,145200 + + Time = n*TimeInterval + + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + + u%dq(1,1) = dq (n+1,1) + u%dq(2,1) = dq (n+1,2) + u%dq(3,1) = dq (n+1,3) + u%dq(4,1) = dq (n+1,4) + u%dq(5,1) = dq (n+1,5) + u%dq(6,1) = dq (n+1,6) + + ! Get state variables at next step: constraint states (z) at step n, continuous and discrete states at step n + 1 + + CALL SS_Rad_UpdateStates( Time, u, p, x_new, xd_new, z, OtherState, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + !print*, x%x + ! Calculate outputs at n + + CALL SS_Rad_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + ! Update x and xd with continuous and discrete states at n + 1 + ! Note that the constraint state guess at n+1 is the value of the constraint state at n (so it doesn't need updating here) + + CALL SS_Rad_CopyContState( x_new, x, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + CALL SS_Rad_CopyDiscState( xd_new, xd, MESH_UPDATECOPY, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + !Write Output to file + WRITE(Outputy,'(7(e16.6))',IOSTAT=Sttus) y%WriteOutput + IF ( Sttus /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error writing output file.' + CALL WrScr( ErrMsg ) + print*, ErrMsg + ENDIF + END DO + + + CALL SS_Rad_DestroyDiscState( xd_new, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + CALL SS_Rad_DestroyContState( x_new, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL SS_Rad_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + + !!! GREG: This is also to ouput values (dont need it) + CALL DATE_AND_TIME ( VALUES=EndTimes ) + CALL cpu_time(finnish) + + ClckTime = 0.001*( EndTimes(8) - StrtTime(8) ) + ( EndTimes(7) - StrtTime(7) ) + 60.0*( EndTimes(6) - StrtTime(6) ) & + + 3600.0*( EndTimes(5) - StrtTime(5) ) + 86400.0*( EndTimes(3) - StrtTime(3) ) + + UsrTime = finnish-start + + IF ( UsrTime /= 0.0 ) THEN + + TRatio = Time / UsrTime + + IF ( UsrTime > 86400.0 ) THEN + Factor = 1.0/86400.0 + TimePer = ' days' + ELSEIF ( UsrTime > 3600.0 ) THEN + Factor = 1.0/3600.0 + TimePer = ' hours' + ELSEIF ( UsrTime > 60.0 ) THEN + Factor = 1.0/60.0 + TimePer = ' minutes' + ELSE + Factor = 1.0 + TimePer = ' seconds' + ENDIF + + CALL WrScr ( ' Total Real Time: '//TRIM( Flt2LStr( Factor*ClckTime ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Total CPU Time: '//TRIM( Flt2LStr( Factor*UsrTime ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Simulated Time: '//TRIM( Flt2LStr( Factor*REAL( Time ) ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Time Ratio (Sim/CPU): '//TRIM( Flt2LStr( TRatio ) ) ) + + ENDIF + + + !Write Output to file + WRITE(Outputy,'(1(e16.6))',IOSTAT=Sttus) TRatio + ! Ending routines + CLOSE( Outputy ) + + + +END PROGRAM SS_Radiation_Driver + diff --git a/OpenFAST/modules/hydrodyn/src/SS_Radiation_Types.f90 b/OpenFAST/modules/hydrodyn/src/SS_Radiation_Types.f90 new file mode 100644 index 000000000..39cd17870 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/SS_Radiation_Types.f90 @@ -0,0 +1,2134 @@ +!STARTOFREGISTRYGENERATEDFILE 'SS_Radiation_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 +!********************************************************************************************************************************* +! SS_Radiation_Types +!................................................................................................................................. +! This file is part of SS_Radiation. +! +! 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 SS_Radiation. 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 SS_Radiation_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= SS_Rad_InitInputType ======= + TYPE, PUBLIC :: SS_Rad_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + REAL(ReKi) , DIMENSION(1:1,1:6) :: DOFs !< Vector with enable platf. DOFs [m/s or rad/s] + END TYPE SS_Rad_InitInputType +! ======================= +! ========= SS_Rad_InitOutputType ======= + TYPE, PUBLIC :: SS_Rad_InitOutputType + CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] + CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + END TYPE SS_Rad_InitOutputType +! ======================= +! ========= SS_Rad_ContinuousStateType ======= + TYPE, PUBLIC :: SS_Rad_ContinuousStateType + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: x !< Continuous States [-] + END TYPE SS_Rad_ContinuousStateType +! ======================= +! ========= SS_Rad_DiscreteStateType ======= + TYPE, PUBLIC :: SS_Rad_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< [-] + END TYPE SS_Rad_DiscreteStateType +! ======================= +! ========= SS_Rad_ConstraintStateType ======= + TYPE, PUBLIC :: SS_Rad_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< [-] + END TYPE SS_Rad_ConstraintStateType +! ======================= +! ========= SS_Rad_OtherStateType ======= + TYPE, PUBLIC :: SS_Rad_OtherStateType + INTEGER(IntKi) :: n !< Current Time step [-] + TYPE(SS_Rad_ContinuousStateType) , DIMENSION(1:4) :: xdot !< Old Values of dxdt to used by the solver (multistep method) [-] + END TYPE SS_Rad_OtherStateType +! ======================= +! ========= SS_Rad_MiscVarType ======= + TYPE, PUBLIC :: SS_Rad_MiscVarType + REAL(SiKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE SS_Rad_MiscVarType +! ======================= +! ========= SS_Rad_ParameterType ======= + TYPE, PUBLIC :: SS_Rad_ParameterType + REAL(DbKi) :: DT !< Time step [seconds] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< B matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] + INTEGER(IntKi) :: N !< Number of states [-] + INTEGER(IntKi) , DIMENSION(1:6) :: spdof !< States per dof [-] + END TYPE SS_Rad_ParameterType +! ======================= +! ========= SS_Rad_InputType ======= + TYPE, PUBLIC :: SS_Rad_InputType + REAL(ReKi) , DIMENSION(1:6) :: dq !< Body velocities [-] + END TYPE SS_Rad_InputType +! ======================= +! ========= SS_Rad_OutputType ======= + TYPE, PUBLIC :: SS_Rad_OutputType + REAL(ReKi) , DIMENSION(1:6) :: y !< Force [-] + REAL(ReKi) , DIMENSION(1:7) :: WriteOutput !< output Data [kN] + END TYPE SS_Rad_OutputType +! ======================= +CONTAINS + SUBROUTINE SS_Rad_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SS_Rad_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 = 'SS_Rad_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%DOFs = SrcInitInputData%DOFs + END SUBROUTINE SS_Rad_CopyInitInput + + SUBROUTINE SS_Rad_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SS_Rad_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyInitInput + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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%InputFile) ! InputFile + Re_BufSz = Re_BufSz + SIZE(InData%DOFs) ! DOFs + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i2 = LBOUND(InData%DOFs,2), UBOUND(InData%DOFs,2) + DO i1 = LBOUND(InData%DOFs,1), UBOUND(InData%DOFs,1) + ReKiBuf(Re_Xferred) = InData%DOFs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SS_Rad_PackInitInput + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%DOFs,1) + i1_u = UBOUND(OutData%DOFs,1) + i2_l = LBOUND(OutData%DOFs,2) + i2_u = UBOUND(OutData%DOFs,2) + DO i2 = LBOUND(OutData%DOFs,2), UBOUND(OutData%DOFs,2) + DO i1 = LBOUND(OutData%DOFs,1), UBOUND(OutData%DOFs,1) + OutData%DOFs(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SS_Rad_UnPackInitInput + + SUBROUTINE SS_Rad_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SS_Rad_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 = 'SS_Rad_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt + END SUBROUTINE SS_Rad_CopyInitOutput + + SUBROUTINE SS_Rad_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SS_Rad_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyInitOutput + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END SUBROUTINE SS_Rad_PackInitOutput + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + i1_l = LBOUND(OutData%WriteOutputHdr,1) + i1_u = UBOUND(OutData%WriteOutputHdr,1) + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + i1_l = LBOUND(OutData%WriteOutputUnt,1) + i1_u = UBOUND(OutData%WriteOutputUnt,1) + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END SUBROUTINE SS_Rad_UnPackInitOutput + + SUBROUTINE SS_Rad_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(SS_Rad_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%x)) THEN + i1_l = LBOUND(SrcContStateData%x,1) + i1_u = UBOUND(SrcContStateData%x,1) + IF (.NOT. ALLOCATED(DstContStateData%x)) THEN + ALLOCATE(DstContStateData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%x = SrcContStateData%x +ENDIF + END SUBROUTINE SS_Rad_CopyContState + + SUBROUTINE SS_Rad_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(SS_Rad_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%x)) THEN + DEALLOCATE(ContStateData%x) +ENDIF + END SUBROUTINE SS_Rad_DestroyContState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + Int_BufSz = Int_BufSz + 1 ! x allocated yes/no + IF ( ALLOCATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + 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%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Rad_PackContState + + SUBROUTINE SS_Rad_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(SS_Rad_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x 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%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE SS_Rad_UnPackContState + + SUBROUTINE SS_Rad_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(SS_Rad_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 = 'SS_Rad_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE SS_Rad_CopyDiscState + + SUBROUTINE SS_Rad_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(SS_Rad_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyDiscState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 SS_Rad_PackDiscState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Rad_UnPackDiscState + + SUBROUTINE SS_Rad_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(SS_Rad_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 = 'SS_Rad_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE SS_Rad_CopyConstrState + + SUBROUTINE SS_Rad_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(SS_Rad_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyConstrState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 SS_Rad_PackConstrState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Rad_UnPackConstrState + + SUBROUTINE SS_Rad_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(SS_Rad_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%n = SrcOtherStateData%n + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL SS_Rad_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + END SUBROUTINE SS_Rad_CopyOtherState + + SUBROUTINE SS_Rad_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(SS_Rad_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL SS_Rad_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + END SUBROUTINE SS_Rad_DestroyOtherState + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + Int_BufSz = Int_BufSz + 1 ! n + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL SS_Rad_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%n + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL SS_Rad_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 SUBROUTINE SS_Rad_PackOtherState + + SUBROUTINE SS_Rad_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(SS_Rad_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_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%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%xdot,1) + i1_u = UBOUND(OutData%xdot,1) + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 SS_Rad_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END SUBROUTINE SS_Rad_UnPackOtherState + + SUBROUTINE SS_Rad_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(SS_Rad_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 = 'SS_Rad_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE SS_Rad_CopyMisc + + SUBROUTINE SS_Rad_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(SS_Rad_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyMisc + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 SS_Rad_PackMisc + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SS_Rad_UnPackMisc + + SUBROUTINE SS_Rad_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SS_Rad_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT +IF (ALLOCATED(SrcParamData%A)) THEN + i1_l = LBOUND(SrcParamData%A,1) + i1_u = UBOUND(SrcParamData%A,1) + i2_l = LBOUND(SrcParamData%A,2) + i2_u = UBOUND(SrcParamData%A,2) + IF (.NOT. ALLOCATED(DstParamData%A)) THEN + ALLOCATE(DstParamData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%A = SrcParamData%A +ENDIF +IF (ALLOCATED(SrcParamData%B)) THEN + i1_l = LBOUND(SrcParamData%B,1) + i1_u = UBOUND(SrcParamData%B,1) + i2_l = LBOUND(SrcParamData%B,2) + i2_u = UBOUND(SrcParamData%B,2) + IF (.NOT. ALLOCATED(DstParamData%B)) THEN + ALLOCATE(DstParamData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%B = SrcParamData%B +ENDIF +IF (ALLOCATED(SrcParamData%C)) THEN + i1_l = LBOUND(SrcParamData%C,1) + i1_u = UBOUND(SrcParamData%C,1) + i2_l = LBOUND(SrcParamData%C,2) + i2_u = UBOUND(SrcParamData%C,2) + IF (.NOT. ALLOCATED(DstParamData%C)) THEN + ALLOCATE(DstParamData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C = SrcParamData%C +ENDIF + DstParamData%N = SrcParamData%N + DstParamData%spdof = SrcParamData%spdof + END SUBROUTINE SS_Rad_CopyParam + + SUBROUTINE SS_Rad_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SS_Rad_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%A)) THEN + DEALLOCATE(ParamData%A) +ENDIF +IF (ALLOCATED(ParamData%B)) THEN + DEALLOCATE(ParamData%B) +ENDIF +IF (ALLOCATED(ParamData%C)) THEN + DEALLOCATE(ParamData%C) +ENDIF + END SUBROUTINE SS_Rad_DestroyParam + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! A allocated yes/no + IF ( ALLOCATED(InData%A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! A upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%A) ! A + END IF + Int_BufSz = Int_BufSz + 1 ! B allocated yes/no + IF ( ALLOCATED(InData%B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%B) ! B + END IF + Int_BufSz = Int_BufSz + 1 ! C allocated yes/no + IF ( ALLOCATED(InData%C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C) ! C + END IF + Int_BufSz = Int_BufSz + 1 ! N + Int_BufSz = Int_BufSz + SIZE(InData%spdof) ! spdof + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%A) ) 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%A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%A,2), UBOUND(InData%A,2) + DO i1 = LBOUND(InData%A,1), UBOUND(InData%A,1) + ReKiBuf(Re_Xferred) = InData%A(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%B) ) 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%B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%B,2), UBOUND(InData%B,2) + DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) + ReKiBuf(Re_Xferred) = InData%B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C) ) 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%C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C,2), UBOUND(InData%C,2) + DO i1 = LBOUND(InData%C,1), UBOUND(InData%C,1) + ReKiBuf(Re_Xferred) = InData%C(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%N + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%spdof,1), UBOUND(InData%spdof,1) + IntKiBuf(Int_Xferred) = InData%spdof(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_PackParam + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! A 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%A)) DEALLOCATE(OutData%A) + ALLOCATE(OutData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%A,2), UBOUND(OutData%A,2) + DO i1 = LBOUND(OutData%A,1), UBOUND(OutData%A,1) + OutData%A(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! B 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%B)) DEALLOCATE(OutData%B) + ALLOCATE(OutData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%B,2), UBOUND(OutData%B,2) + DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) + OutData%B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C 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%C)) DEALLOCATE(OutData%C) + ALLOCATE(OutData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C,2), UBOUND(OutData%C,2) + DO i1 = LBOUND(OutData%C,1), UBOUND(OutData%C,1) + OutData%C(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%N = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%spdof,1) + i1_u = UBOUND(OutData%spdof,1) + DO i1 = LBOUND(OutData%spdof,1), UBOUND(OutData%spdof,1) + OutData%spdof(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_UnPackParam + + SUBROUTINE SS_Rad_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_InputType), INTENT(IN) :: SrcInputData + TYPE(SS_Rad_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%dq = SrcInputData%dq + END SUBROUTINE SS_Rad_CopyInput + + SUBROUTINE SS_Rad_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SS_Rad_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyInput + + SUBROUTINE SS_Rad_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(SS_Rad_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 = 'SS_Rad_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 + Re_BufSz = Re_BufSz + SIZE(InData%dq) ! dq + 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%dq,1), UBOUND(InData%dq,1) + ReKiBuf(Re_Xferred) = InData%dq(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_PackInput + + SUBROUTINE SS_Rad_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(SS_Rad_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_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 + i1_l = LBOUND(OutData%dq,1) + i1_u = UBOUND(OutData%dq,1) + DO i1 = LBOUND(OutData%dq,1), UBOUND(OutData%dq,1) + OutData%dq(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_UnPackInput + + SUBROUTINE SS_Rad_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SS_Rad_OutputType), INTENT(IN) :: SrcOutputData + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'SS_Rad_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%y = SrcOutputData%y + DstOutputData%WriteOutput = SrcOutputData%WriteOutput + END SUBROUTINE SS_Rad_CopyOutput + + SUBROUTINE SS_Rad_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SS_Rad_DestroyOutput + + SUBROUTINE SS_Rad_PackOutput( 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(SS_Rad_OutputType), 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 = 'SS_Rad_PackOutput' + ! 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%y) ! y + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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%y,1), UBOUND(InData%y,1) + ReKiBuf(Re_Xferred) = InData%y(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_PackOutput + + SUBROUTINE SS_Rad_UnPackOutput( 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(SS_Rad_OutputType), 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 = 'SS_Rad_UnPackOutput' + ! 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%y,1) + i1_u = UBOUND(OutData%y,1) + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%WriteOutput,1) + i1_u = UBOUND(OutData%WriteOutput,1) + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE SS_Rad_UnPackOutput + + + SUBROUTINE SS_Rad_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SS_Rad_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SS_Rad_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SS_Rad_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SS_Rad_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SS_Rad_Input_ExtrapInterp + + + SUBROUTINE SS_Rad_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(u_out%dq,1),UBOUND(u_out%dq,1) + b = -(u1%dq(i1) - u2%dq(i1)) + u_out%dq(i1) = u1%dq(i1) + b * ScaleFactor + END DO + END SUBROUTINE SS_Rad_Input_ExtrapInterp1 + + + SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(u_out%dq,1),UBOUND(u_out%dq,1) + b = (t(3)**2*(u1%dq(i1) - u2%dq(i1)) + t(2)**2*(-u1%dq(i1) + u3%dq(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%dq(i1) + t(3)*u2%dq(i1) - t(2)*u3%dq(i1) ) * scaleFactor + u_out%dq(i1) = u1%dq(i1) + b + c * t_out + END DO + END SUBROUTINE SS_Rad_Input_ExtrapInterp2 + + + SUBROUTINE SS_Rad_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SS_Rad_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SS_Rad_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SS_Rad_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SS_Rad_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SS_Rad_Output_ExtrapInterp + + + SUBROUTINE SS_Rad_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) + b = -(y1%y(i1) - y2%y(i1)) + y_out%y(i1) = y1%y(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) + b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO + END SUBROUTINE SS_Rad_Output_ExtrapInterp1 + + + SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SS_Rad_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) + b = (t(3)**2*(y1%y(i1) - y2%y(i1)) + t(2)**2*(-y1%y(i1) + y3%y(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%y(i1) + t(3)*y2%y(i1) - t(2)*y3%y(i1) ) * scaleFactor + y_out%y(i1) = y1%y(i1) + b + c * t_out + END DO + 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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO + END SUBROUTINE SS_Rad_Output_ExtrapInterp2 + +END MODULE SS_Radiation_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/UserWaves.f90 b/OpenFAST/modules/hydrodyn/src/UserWaves.f90 new file mode 100644 index 000000000..a979b5df9 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/UserWaves.f90 @@ -0,0 +1,984 @@ +MODULE UserWaves + + USE Waves_Types + USE NWTC_Library + USE NWTC_FFTPACK + + IMPLICIT NONE + PRIVATE + + PUBLIC :: UserWaves_Init + PUBLIC :: UserWaveElevations_Init + + + ! Data type for reading in wave elevation data from a file. + TYPE :: WaveElevInputDataFile + REAL(DbKi) :: WaveDT !< time step size + INTEGER(IntKi) :: NStepWave !< Number of wave elevation steps + REAL(SiKi) :: WaveTMax !< Maximum time + REAL(SiKi), ALLOCATABLE :: WaveElev(:) !< Wave elevation at each timestep (m) + REAL(SiKi), ALLOCATABLE :: WaveTime(:) !< Timestamp of each wave elevation (s) + CHARACTER(1024) :: FileName !< Name of the file + END TYPE WaveElevInputDataFile + + + + + CONTAINS + + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reads in the wave elevations from a file and reconstructs the frequency information. +!! +!! FILE Format: +!! Header info: +!! This file may have header lines. These can be any number of lines at the beginning of the file that +!! start with non-numeric data. The Value of WaveDT is calculated using the first and last rows of data, +!! and the number of timesteps. The Number of timesteps is calculated as the number of lines of data, minus 1. +!! +!! column headings --> column 1 = time (s), column 2 = elevation (m) +!! +!! +SUBROUTINE WaveElev_ReadFile ( InitInp, WaveElevData, ErrStat, ErrMsg ) + + IMPLICIT NONE + TYPE(Waves_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WaveElevInputDataFile), INTENT( OUT) :: WaveElevData !< Wave elevation file data, after changing NStepWave + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error Status at return + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Variables for reading in the wave elevation + CHARACTER(1024) :: FileName !< Name of the file we are reading + REAL(SiKi) :: TmpWaveElevRow(2) !< row read in from the wave elevation input file + + + ! Local Variables + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + INTEGER(IntKi) :: I !< Generic counter integer + INTEGER(IntKi) :: NumDataColumns !< Number of columns of data found in the file + INTEGER(IntKi) :: NumHeaderLines !< Number of header lines in the file. + INTEGER(IntKi) :: WaveElevUnit !< Unit number for the ElevFileName + INTEGER(IntKi) :: ErrStatTmp !< Temporarary error status for procesing + CHARACTER(ErrMsgLen) :: ErrMsgTmp !< Temporary error message for processing + CHARACTER(*), PARAMETER :: RoutineName = 'WaveElev_ReadFile' + + + + + ! Initialize the error handling + ErrStat = ErrID_None + ErrMsg = "" + + + ! Get a unit number for reading in the file + CALL GetNewUnit( WaveElevUnit ) + + ! Assemble the filename for the wave elevation data. + WaveElevData%FileName = TRIM(InitInp%WvKinFile)//'.Elev' + + ! Open the file containing the wave elevation timeseries + CALL OpenFInpFile( WaveElevUnit, WaveElevData%FileName, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + + ! Find out how the data is formatted + CALL GetFileLength(WaveElevUnit, TRIM(WaveElevData%Filename), NumDataColumns, WaveElevData%NStepWave, NumHeaderLines, ErrStatTmp, ErrMsgTmp) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + + ! Check that we read in two columns + IF ( NumDataColumns /= 2_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, ' Wave elevation files should contain only two columns of data: Time (s) and Elevation (m). '// & + 'Found '//TRIM(Num2LStr(NumDataColumns))//' of data in '//TRIM(WaveElevData%FileName)//'.', ErrStat, ErrMsg, RoutineName) + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + + ! Adjust the number of steps since we index from zero + WaveElevData%NStepWave = WaveElevData%NStepWave - 1_IntKi + + + + !-------------------------------------------------- + ! Read in the data + !-------------------------------------------------- + + ! Allocate the array to store the time series + ALLOCATE ( WaveElevData%WaveTime(0:WaveElevData%NStepWave), STAT = ErrStatTmp ) + IF ( ErrStatTmp /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for user WaveTime array.', ErrStat, ErrMsg, RoutineName ) + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + ! Allocate the array to store the elevation series + ALLOCATE ( WaveElevData%WaveElev(0:WaveElevData%NStepWave), STAT = ErrStatTmp ) + IF ( ErrStatTmp /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for user WaveElev array.', ErrStat, ErrMsg, RoutineName ) + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + + ! Read and discard the header lines + DO I=1,NumHeaderLines + CALL ReadLine( WaveElevUnit, '', TextLine, LineLen, ErrStatTmp ) + ENDDO + + + ! Read in all the data + DO I=0,WaveElevData%NStepWave + CALL ReadAry( WaveElevUnit, WaveElevData%FileName, TmpWaveElevRow(1:2), 2, 'TmpWaveElevRow','Temporary variable holding the time and wave elevation pair', & + ErrStatTmp,ErrMsgTmp ) + IF ( ErrStatTmp /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error in reading in value from the file: line number '//TRIM(Num2LStr(I))//'. Expecting a total of '// & + TRIM(Num2LStr(WaveElevData%NStepWave))//' rows of data.', ErrStat, ErrMsg, RoutineName ) + CLOSE ( WaveElevUnit ) + CALL CleanUp() + RETURN + END IF + + ! Copy the data to the appropriate places + WaveElevData%WaveTime(I) = TmpWaveElevRow(1) + WaveElevData%WaveElev(I) = TmpWaveElevRow(2) + + ENDDO + + CALL WrScr( ' Read in '//TRIM(Num2LStr(I))//' lines of wave elevation data from '//TRIM(WaveElevData%FileName)//'.' ) + + + CLOSE( WaveElevUnit ) + + + + ! We are going to be a little bit lazy here and blindly assume that the time is correct in the file + ! and that the timesteps are uniform throughout the file (if this isn't true, that isn't the problem + ! of the programmer, rather of the user). + + ! Set the value for WaveTMax using the difference betwee the last value read in and the fist + WaveElevData%WaveTMax = WaveElevData%WaveTime(WaveElevData%NStepWave) - WaveElevData%WaveTime(0) + + ! Set the value for WaveDT using the number of steps read in and the difference from first and last + WaveElevData%WaveDT = REAL( WaveElevData%WaveTMax / WaveElevData%NStepWave, DbKi ) + + + CONTAINS + + SUBROUTINE CleanUp + + IF (ALLOCATED( WaveElevData%WaveElev )) DEALLOCATE( WaveElevData%WaveElev, STAT=ErrStatTmp) + IF (ALLOCATED( WaveElevData%WaveTime )) DEALLOCATE( WaveElevData%WaveTime, STAT=ErrStatTmp) + + END SUBROUTINE CleanUp + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine looks at a file that has been opened and finds out how many header lines there are, how many periods + !! (frequencies) there are (first only if there are paired periods for second order), and how many lines of data there are in + !! the file. + !! + !! A few things are assumed about the file: + !! 1. Any header lines are the first thing in the file. + !! 2. No text appears anyplace other than in the file + !! 3. The datalines only contain numbers that can be read in as reals. + !! + !! Limitations: + !! 1. only handles up to 20 words (columns) on a line + !! 2. empty lines are considered text lines + !! 3. All data rows must contain the same number of columns + !! + !! + SUBROUTINE GetFileLength(UnitDataFile, Filename, NumDataColumns, NumDataLines, NumHeaderLines, ErrStat, ErrMsg) + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: UnitDataFile !< Unit number of the file we are looking at. + CHARACTER(*), INTENT(IN ) :: Filename !< The name of the file we are looking at. + INTEGER(IntKi), INTENT( OUT) :: NumDataColumns !< The number of columns in the data file. + INTEGER(IntKi), INTENT( OUT) :: NumDataLines !< Number of lines containing data + INTEGER(IntKi), INTENT( OUT) :: NumHeaderLines !< Number of header lines at the start of the file + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error Message to return (empty if all good) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Status flag if there were any problems (ErrID_None if all good) + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary message variable. Used in calls. + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status. Used in calls. + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + INTEGER(IntKi) :: TmpIOErrStat !< Temporary error status for the internal read of the first word to a real number + LOGICAL :: IsRealNum !< Flag indicating if the first word on the line was a real number + + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + CHARACTER(1024) :: StrRead !< String containing the first word read in + REAL(SiKi) :: RealRead !< Returns value of the number (if there was one), or NaN (as set by NWTC_Num) if there wasn't + CHARACTER(1024) :: VarName !< Name of the variable we are trying to read from the file + CHARACTER(24) :: Words(20) !< Array of words we extract from a line. We shouldn't have more than 20. + INTEGER(IntKi) :: i,j,k !< simple integer counters + INTEGER(IntKi) :: LineNumber !< the line I am on + LOGICAL :: LineHasText !< Flag indicating if the line I just read has text. If so, it is a header line. + LOGICAL :: HaveReadData !< Flag indicating if I have started reading data. + INTEGER(IntKi) :: NumWords !< Number of words on a line + INTEGER(IntKi) :: FirstDataLineNum !< Line number of the first row of data in the file + CHARACTER(*), PARAMETER :: RoutineName = 'GetFileLength' + + + + ! Initialize the error handling + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + LclErrStat = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + + ! Set some of the flags and counters + HaveReadData = .FALSE. + NumDataColumns = 0 + NumHeaderLines = 0 + NumDataLines = 0 + LineNumber = 0 + + + ! Just in case we were handed a file that we are part way through reading (should never be true), rewind to the start + + REWIND( UnitDataFile ) + + + !------------------------------------ + !> The variable LclErrStat is used to indicate when we have reached the end of the file or had an error from + !! ReadLine. Until that occurs, we read each line, and decide if it contained any non-numeric data. The + !! first group of lines containing non-numeric data is considered the header. The first line of all numeric + !! data is considered the start of the data section. Any non-numeric containing found within the data section + !! will be considered as an invalid file format at which point we will return a fatal error from this routine. + + DO WHILE ( LclErrStat == ErrID_None ) + + !> Reset the indicator flag for the non-numeric content + LineHasText = .FALSE. + + !> Read in a single line from the file + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + + !> If there was an error in reading the file, then exit. + !! Possible causes: reading beyond end of file in which case we are done so don't process it. + IF ( LclErrStat /= ErrID_None ) EXIT + + !> Increment the line counter. + LineNumber = LineNumber + 1 + + !> Read all the words on the line into the array called 'Words'. Only the first words will be encountered + !! will be stored. The others are empty (i.e. only three words on the line, so the remaining 17 are empty). + CALL GetWords( TextLine, Words, 20 ) + + !> Cycle through and count how many are not empty. Once an empty value is encountered, all the rest should + !! be empty if GetWords worked correctly. The index of the last non-empty value is stored. + DO i=1,20 + IF (TRIM(Words(i)) .ne. '') NumWords=i + ENDDO + + + !> Now cycle through the first 'NumWords' of non-empty values stored in 'Words'. Words should contain + !! everything that is one the line. The subroutine ReadRealNumberFromString will set a flag 'IsRealNum' + !! when the value in Words(i) can be read as a real(SiKi). 'StrRead' will contain the string equivalent. + DO i=1,NumWords + CALL ReadRealNumberFromString( Words(i), RealRead, StrRead, IsRealNum, ErrStatTmp, ErrMsgTmp, TmpIOErrStat ) + IF ( .NOT. IsRealNum) THEN + LineHasText = .TRUE. + ENDIF + ENDDO + + !> If all the words on that line had no text in them, then it must have been a line of data. + !! If not, then we have either a header line, which is ok, or a line containing text in the middle of the + !! the data section, which is not good (the flag HaveReadData tells us which case this is). + IF ( LineHasText ) THEN + IF ( HaveReadData ) THEN ! Uh oh, we have already read a line of data before now, so there is a problem + CALL SetErrStat( ErrID_Fatal, ' Found text on line '//TRIM(Num2LStr(LineNumber))//' of '//TRIM(FileName)// & + ' when real numbers were expected. There may be a problem with the file.', ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ELSE + NumHeaderLines = NumHeaderLines + 1 + ENDIF + ELSE ! No text, must be data line + NumDataLines = NumDataLines + 1 + ! If this is the first row of data, then store the number of words that were on the line + IF ( .NOT. HaveReadData ) THEN + ! If this is the first line of data, keep some relevant info about it and the number of columns in it + HaveReadData = .TRUE. + FirstDataLineNum = LineNumber ! Keep the line number of the first row of data (for error reporting) + NumDataColumns = NumWords + ELSE + ! Make sure that the number columns on the row matches the number of columnns on the first row of data. + IF ( NumWords /= NumDataColumns ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error in data file: '//TRIM(Filename)//'.'// & + ' The number of data columns on line '//TRIM(Num2LStr(LineNumber))// & + '('//TRIM(Num2LStr(NumWords))//' columns) is different than the number of columns on first row of data '// & + ' (line: '//TRIM(Num2LStr(FirstDataLineNum))//', '//TRIM(Num2LStr(NumDataColumns))//' columns).', & + ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + ENDIF + ENDIF + + ENDDO + + IF ( NumDataLines < 2 ) THEN + CALL SetErrStat( ErrID_Fatal, ' The file '//TRIM(Filename)//' contains only '//TRIM(Num2LStr(NumDataLines))// & + ' lines of data. This does not appear to be a useful wave elevation file.', ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + REWIND( UnitDataFile ) + + END SUBROUTINE GetFileLength + + + !------------------------------------------------------------------------------- + !> This subroutine takes a line of text that is passed in and reads the first + !! word to see if it is a number. An internal read is used to do this. If + !! it is a number, it is started in ValueRead and returned. The flag IsRealNum + !! is set to true. Otherwise, ValueRead is set to NaN (value from the NWTC_Num) + !! and the flag is set to false. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (IsRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + CHARACTER(*), INTENT(IN ) :: StringToParse !< The string we were handed. + REAL(SiKi), INTENT( OUT) :: ValueRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StringToParse,*,IOSTAT=IOErrStat) StrRead + read(StringToParse,*,IOSTAT=IOErrStat) ValueRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + ValueRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrSTat = ErrID_Severe + endif + + + + RETURN + END SUBROUTINE ReadRealNumberFromString + + + !------------------------------------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + !> This subroutine works with the ReadNum routine from the library. ReadNum is + !! called to read a word from the input file. An internal read is then done to + !! convert the string to a number that is stored in VarRead and returned. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (ISRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumber(UnitNum, FileName, VarName, VarRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + INTEGER(IntKi), INTENT(IN ) :: UnitNum !< The unit number of the file being read + CHARACTER(*), INTENT(IN ) :: FileName !< The name of the file being read. Used in the ErrMsg from ReadNum (Library routine). + CHARACTER(*), INTENT(IN ) :: VarName !< The variable we are reading. Used in the ErrMsg from ReadNum (Library routine)'. + REAL(SiKi), INTENT( OUT) :: VarRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + ! Local vars + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! Now call the ReadNum routine to get the number + ! If it is a word that does not start with T or F, then ReadNum won't give any errors. + CALL ReadNum( UnitNum, FileName, StrRead, VarName, ErrStatTmp, ErrMsgTmp) + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StrRead,*,IOSTAT=IOErrStat) VarRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + VarRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrStat = ErrStatTmp ! The ErrStatTmp returned by the ReadNum routine is an ErrID level. + endif + + + RETURN + END SUBROUTINE ReadRealNumber + + +END SUBROUTINE WaveElev_ReadFile + +!---------------------------------------------------------------------------------------------------------------------------------- + +FUNCTION is_numeric(string, x) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + REAL(SiKi), INTENT(OUT) :: x + LOGICAL :: is_numeric + + INTEGER :: e,n + CHARACTER(len=12) :: fmt + x = 0.0_SiKi + n=LEN_TRIM(string) + WRITE(fmt,'("(F",I0,".0)")') n + READ(string,fmt,IOSTAT=e) x + is_numeric = e == 0 +END FUNCTION is_numeric + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the wave kinematics based a set of user-supplied wave elevations +!! +!! NOTE: WaveDT in file must match given WaveDT in HydroDyn input file +!! Final timestep must match given WaveTMax in HydroDyn input file +!! NOTE: Wave frequency cutoffs can are applied to the read in wave elevation time series +!! +SUBROUTINE UserWaveElevations_Init ( InitInp, InitOut, ErrStat, ErrMsg ) +!---------------------------------------------------------------------------------------------------------------------------------- + TYPE(Waves_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(Waves_InitOutputType), INTENT(INOUT) :: InitOut !< Initialization outputs + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Local Variables + TYPE(WaveElevInputDataFile) :: WaveElevData !< Wave elevation file data after changing NStepWave + REAL(SiKi), ALLOCATABLE :: TmpFFTWaveElev(:) !< Data for the FFT calculation + TYPE(FFT_DataType) :: FFT_Data !< the instance of the FFT module we're using + INTEGER(IntKi) :: I !< Generic counter + + + ! Temporary error handling variables + INTEGER(IntKi) :: ErrStatTmp !< Temporarary error status for procesing + CHARACTER(ErrMsgLen) :: ErrMsgTmp !< Temporary error message for processing + CHARACTER(*), PARAMETER :: RoutineName = 'UserWaveElevations_Init' + + ! Data verification: WaveDT in the HD file and in the .Elev file may be slightly different. We will allow + ! some slight differences due to rounding. If necessary, we could change this to a percentage allowable in the future. + REAL(SiKi), PARAMETER :: WaveDT_Tol = 0.001_SiKi !< Allowable difference in WaveDT values + + ! set error status information + ErrStat = ErrID_None + ErrMsg = '' + + + + ! Statement to user + CALL WrScr1 ( ' Reading in wave elevation data from wave kinematics files with root name "'//TRIM(InitInp%WvKinFile)//'".' ) + + ! Read in the wave elevation data + CALL WaveElev_ReadFile (InitInp, WaveElevData, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Check that the file timestep is the same as the HD file, and check that the WaveTMax value of the file is larger than that of HD. + IF ( InitInp%WaveTMax > WaveElevData%WaveTMax ) THEN + CALL SetErrStat(ErrID_Fatal,' HydroDyn requires a minimum of '//TRIM(Num2LStr(InitInp%WaveTMax))//', but '//TRIM(WaveElevData%FileName)// & + ' only contains a maximum time of '//TRIM(Num2LStr(WaveElevData%WaveTMax))//' (last line).',ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that the values of WaveDT are the same or similar enough + IF ( ABS(InitInp%WaveDT - WaveElevData%WaveDT) > WaveDT_Tol ) THEN + CALL SetErrStat(ErrID_Fatal,' WaveDT from Hydrodyn ('//TRIM(Num2LStr(InitInp%WaveDT))//') and timestep size in wave elevation file '// & + TRIM(WaveElevData%FileName)//' (WaveDT = '//TRIM(Num2LStr(WaveElevData%WaveDT))//') do not match. These need to be within '// & + TRIM(Num2LStr(WaveDT_Tol))//' seconds of each other.',ErrStat,ErrMsg,RoutineName) + ENDIF + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Set new value for NStepWave so that the FFT algorithms are efficient. We will use the values passed in rather than what is read from the file + ! NOTE: This method is what is used in the VariousWaves_Init routine in Waves.f90 + + InitOut%NStepWave = CEILING ( InitInp%WaveTMax/InitInp%WaveDT ) ! Set NStepWave to an even integer + IF ( MOD(InitOut%NStepWave,2) == 1 ) InitOut%NStepWave = InitOut%NStepWave + 1 ! larger or equal to WaveTMax/WaveDT. + InitOut%NStepWave2 = MAX( InitOut%NStepWave/2, 1 ) ! Make sure that NStepWave is an even product of small factors (PSF) that is + InitOut%NStepWave = 2*PSF ( InitOut%NStepWave2, 9 ) ! greater or equal to WaveTMax/WaveDT to ensure that the FFT is efficient. + InitOut%NStepWave2 = InitOut%NStepWave/2 ! Update the value of NStepWave2 based on the value needed for NStepWave. + InitOut%WaveTMax = InitOut%NStepWave*InitInp%WaveDT ! Update the value of WaveTMax based on the value needed for NStepWave. + InitOut%WaveDOmega = TwoPi/InitInp%WaveTMax ! Compute the frequency step for incident wave calculations. + + ! Give warning if the number of timesteps changed + IF ( WaveElevData%NStepWave /= InitOut%NStepWave ) THEN + CALL SetErrStat(ErrID_Warn, ' Changed number of timesteps from '//TRIM(Num2LStr(WaveElevData%NStepWave))//' to '// & + TRIM(Num2LStr(InitOut%NStepWave))//' in order to calculate the frequency information from the wave elevations. '// & + 'Wave elevations during additional time are padded with zero wave elevation.',ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Allocate array to hold the wave elevations for calculation of FFT. + ALLOCATE ( TmpFFTWaveElev( 0:InitOut%NStepWave-1 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpFFTWaveElev.',ErrStat,ErrMsg,RoutineName) + + ! Allocate frequency array for the wave elevation information in frequency space + ALLOCATE ( InitOut%WaveElevC0(2, 0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevC0.',ErrStat,ErrMsg,RoutineName) + + + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Set the values + TmpFFTWaveElev = 0.0_SiKi + InitOut%WaveElevC0(:,:) = 0.0_SiKi + + + ! Copy values over + DO I=0,MIN(WaveElevData%NStepWave,InitOut%NStepWave-1) + TmpFFTWaveElev(I) = WaveElevData%WaveElev(I) + ENDDO + + ! Initialize the FFT + CALL InitFFT ( InitOut%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Apply the forward FFT to get the real and imaginary parts of the frequency information. + CALL ApplyFFT_f ( TmpFFTWaveElev(:), FFT_Data, ErrStatTmp ) ! Note that the TmpFFTWaveElev now contains the real and imaginary bits. + CALL SetErrStat(ErrStatTmp,'Error occured while applying the forwards FFT to TmpFFTWaveElev array.',ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Copy the resulting TmpFFTWaveElev(:) data over to the InitOut%WaveElevC0 array + DO I=1,InitOut%NStepWave2-1 + InitOut%WaveElevC0 (1,I) = TmpFFTWaveElev(2*I-1) + InitOut%WaveElevC0 (2,I) = TmpFFTWaveElev(2*I) + ENDDO + InitOut%WaveElevC0(:,InitOut%NStepWave2) = 0.0_SiKi + + CALL ExitFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + IF (ALLOCATED( WaveElevData%WaveElev )) DEALLOCATE( WaveElevData%WaveElev, STAT=ErrStatTmp) + IF (ALLOCATED( TmpFFTWaveElev )) DEALLOCATE( TmpFFTWaveElev, STAT=ErrStatTmp) + + + + CONTAINS + + SUBROUTINE CleanUp + + IF (ALLOCATED( WaveElevData%WaveElev )) DEALLOCATE( WaveElevData%WaveElev, STAT=ErrStatTmp) + IF (ALLOCATED( WaveElevData%WaveTime )) DEALLOCATE( WaveElevData%WaveTime, STAT=ErrStatTmp) + IF (ALLOCATED( TmpFFTWaveElev )) DEALLOCATE( TmpFFTWaveElev, STAT=ErrStatTmp) + IF (ALLOCATED( InitOut%WaveElevC0 )) DEALLOCATE( InitOut%WaveElevC0, STAT=ErrStatTmp) + + END SUBROUTINE CleanUp + + +END SUBROUTINE UserWaveElevations_Init + + + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE UserWaves_Init ( InitInp, InitOut, ErrStat, ErrMsg ) +! This routine initializes the wave kinematics based on user-supplied data +!---------------------------------------------------------------------------------------------------------------------------------- + TYPE(Waves_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(Waves_InitOutputType), INTENT(INOUT) :: InitOut ! Initialization outputs + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + INTEGER :: UnWv ! file unit for writing the various wave kinematics files + CHARACTER(1024) :: FileName ! complete filename for one of the output files + INTEGER :: I ! Generic index + INTEGER :: J ! Generic index + INTEGER :: iFile ! Generic index + CHARACTER(64) :: Frmt, Sfrmt + CHARACTER(10) :: Delim + CHARACTER(64), ALLOCATABLE :: WaveDataStr(:,:) + REAL(SiKi), ALLOCATABLE :: WaveData(:,:) + + ! Temporary error handling variables + INTEGER(IntKi) :: ErrStatTmp ! Temporarary error status for procesing + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! Temporary error message for processing + LOGICAL :: isNumeric + CHARACTER(*), PARAMETER :: RoutineName = 'UserWaves_Init' + CHARACTER(5) :: extension(7) + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + extension = (/'.Vxi ','.Vyi ','.Vzi ','.Axi ','.Ayi ','.Azi ','.DynP'/) + Delim = '' + + + ! Tell our nice users what is about to happen that may take a while: + + CALL WrScr1 ( ' Reading in wave data from wave kinematics files with root name "'//TRIM(InitInp%WvKinFile)//'".' ) + + + + ! Perform some initialization computations including calculating the + ! total number of time steps in the incident wave and ALLOCATing the + ! arrays; initialize the unneeded values to zero: + InitOut%NStepWave = CEILING ( InitInp%WaveTMax/InitInp%WaveDT ) ! Set NStepWave to an even integer + IF (.NOT. (EqualRealNos( REAL(InitInp%WaveTMax, SiKi) - REAL(InitOut%NStepWave*InitInp%WaveDT, SiKi), 0.0_SiKi ) ) ) THEN + ErrMsg = 'For WaveMod = 5 or 6, WaveTMax must be a multiple of WaveDT' + ErrStat = ErrID_Fatal + RETURN + END IF + + InitOut%NStepWave2 = InitOut%NStepWave/2 + + ALLOCATE ( WaveDataStr (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDataStr.', ErrStat,ErrMsg,RoutineName) + + ALLOCATE ( InitOut%nodeInWater (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array outOfWaterFlag.', ErrStat,ErrMsg,RoutineName) + InitOut%nodeInWater = 1 + + ALLOCATE ( WaveData (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveData.', ErrStat,ErrMsg,RoutineName) + WaveData = 0.0_SiKi + + ALLOCATE ( InitOut%WaveTime (0:InitOut%NStepWave ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveTime.', ErrStat,ErrMsg,RoutineName) + + ALLOCATE ( InitOut%WaveElev (0:InitOut%NStepWave,InitInp%NWaveElev ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElev.', ErrStat,ErrMsg,RoutineName) + InitOut%WaveElev = 0.0_SiKi + + ALLOCATE ( InitOut%WaveDynP (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP.', ErrStat,ErrMsg,RoutineName) + + ALLOCATE ( InitOut%WaveVel (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel.', ErrStat,ErrMsg,RoutineName) + + ALLOCATE ( InitOut%WaveAcc (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc.', ErrStat,ErrMsg,RoutineName) + + + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + + ! Read the first file and set the initial values of the + + CALL GetNewUnit( UnWv ) + + FileName = TRIM(InitInp%WvKinFile) // TRIM(extension(1)) + + CALL OpenFInpFile ( UnWv, FileName, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Failed to open wave kinematics file, ' // TRIM(FileName) + RETURN + END IF + + + + CALL ReadCom( UnWv, FileName, 'HydroDyn wave kinematics file header line 1', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + DO i = 0,InitOut%NStepWave-1 + ! Extract fields from current line + IF (.not. ExtractFields(UnWv, WaveDataStr(i,:), InitInp%NWaveKin)) THEN + call Cleanup() + RETURN + END IF + DO j = 1, InitInp%NWaveKin + + isNumeric = is_numeric(WaveDataStr(i,j), WaveData(i,j)) + IF (.NOT. isNumeric )THEN + InitOut%nodeInWater(i,j) = 0 + WaveData(i,j) = 0.0 + ELSE + InitOut%nodeInWater(i,j) = 1 + END IF + + + END DO + + END DO + + InitOut%WaveVel (:,:,1) = WaveData(:,:) + + ! Now read the remaining files and check that the elements are consistent with the first file + DO iFile = 2,7 + + CALL GetNewUnit( UnWv ) + + FileName = TRIM(InitInp%WvKinFile) // TRIM(extension(iFile)) + + CALL OpenFInpFile ( UnWv, FileName, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Failed to open wave kinematics file, ' // TRIM(FileName) + RETURN + END IF + + + + CALL ReadCom( UnWv, FileName, 'HydroDyn wave kinematics file header line 1', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + DO i = 0,InitOut%NStepWave-1 + ! Extract fields from current line + IF (.not. ExtractFields(UnWv, WaveDataStr(i,:), InitInp%NWaveKin)) THEN + call Cleanup() + RETURN + END IF + DO j = 1, InitInp%NWaveKin + isNumeric = is_numeric(WaveDataStr(i,j), WaveData(i,j)) + IF ( ( isNumeric .AND. (InitOut%nodeInWater(i,j) == 0) ) .OR. ( .NOT. isNumeric .AND. ( InitOut%nodeInWater(i,j) == 1 ) ) ) THEN + ErrStatTmp = ErrID_Fatal + ErrMsgTmp = 'Element of wave kinematics file must be numerical or non-numerical across all files. Problem was found in ' // TRIM(FileName) // ' on row ' // Num2LStr(i+1) // ' and column ' // Num2LStr(j) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + IF (.NOT. isNumeric ) THEN + InitOut%nodeInWater(i,j) = 0 + WaveData(i,j) = 0.0 + ELSE + InitOut%nodeInWater(i,j) = 1 + END IF + END DO + + END DO + SELECT CASE (iFile) + CASE (1) + InitOut%WaveVel (:,:,1) = WaveData(:,:) + CASE (2) + InitOut%WaveVel (:,:,2) = WaveData(:,:) + CASE (3) + InitOut%WaveVel (:,:,3) = WaveData(:,:) + CASE (4) + InitOut%WaveAcc (:,:,1) = WaveData(:,:) + CASE (5) + InitOut%WaveAcc (:,:,2) = WaveData(:,:) + CASE (6) + InitOut%WaveAcc (:,:,3) = WaveData(:,:) + CASE (7) + InitOut%WaveDynP = WaveData + END SELECT + + CLOSE(UnWv) + END DO + + ! WaveTime + DO i = 0,InitOut%NStepWave + InitOut%WaveTime(i) = i*InitInp%WaveDT + END DO + + ! WaveElev + IF ( InitInp%NWaveElev > 0 ) THEN + CALL GetNewUnit( UnWv ) + + FileName = TRIM(InitInp%WvKinFile) // '.Elev' + + CALL OpenFInpFile ( UnWv, FileName, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Failed to open wave elevations file, ' // TRIM(FileName) + RETURN + END IF + + Frmt = '('//TRIM(Int2LStr(InitInp%NWaveElev))//'(:,A,ES11.4e2))' + + CALL ReadCom( UnWv, FileName, 'HydroDyn wave elevations file header line 1', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + DO i = 0,InitOut%NStepWave-1 + Read(UnWv,Frmt) ( Delim, InitOut%WaveElev(i,j) , j=1,InitInp%NWaveElev ) + END DO + CLOSE(UnWv) + END IF + CALL CleanUp( ) + + ! Need to append the first time step record to the end of each array for periodic waves + InitOut%WaveVel (InitOut%NStepWave,:,:) = InitOut%WaveVel (0,:,:) + InitOut%WaveAcc (InitOut%NStepWave,:,:) = InitOut%WaveAcc (0,:,:) + InitOut%WaveDynP(InitOut%NStepWave,:) = InitOut%WaveDynP(0,: ) + InitOut%WaveElev(InitOut%NStepWave,:) = InitOut%WaveElev(0,:) + InitOut%nodeInWater(InitOut%NStepWave,:) = InitOut%nodeInWater(0,:) + + + + ! For creating animations of the sea surface, the WaveElevXY array is passed in with a series of x,y coordinates + ! (index 1). The second index corresponds to the number of points passed in. A two dimensional time series + ! is created with the first index corresponding to the timestep, and second index corresponding to the second + ! index of the WaveElevXY array. + IF ( ALLOCATED(InitInp%WaveElevXY)) THEN + ALLOCATE ( InitOut%WaveElevSeries (0:InitOut%NStepWave, 1:SIZE(InitInp%WaveElevXY, DIM=2)) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevSeries.',ErrStat,ErrMsg,'VariousWaves_Init') + RETURN + END IF + ! Calculate the wave elevation at all points requested in the array WaveElevXY + DO I = 0,InitOut%NStepWave + DO J = 1,SIZE(InitInp%WaveElevXY, DIM=2) + InitOut%WaveElevSeries(I,J) = 0.0_ReKi ! TODO, these values should be interpolated based on inputs + ENDDO + ENDDO + ENDIF + + +CONTAINS + + !> Sub function to extract n fields on the current line of the file unit FU + FUNCTION ExtractFields(FU, s, n) result(OK) + ! Arguments + INTEGER, INTENT(IN) :: FU !< Unit name + INTEGER, INTENT(IN) :: n !< Number of fields + CHARACTER(*), INTENT(OUT) :: s(n) !< Fields + LOGICAL :: OK + ! Local var + CHARACTER(2048) :: TextLine !< One line of text read from the file + OK=.TRUE. + + ! Read line + READ(FU, FMT='(A)', IOSTAT=ErrStat) TextLine + IF (ErrStat/=0) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(A,I0,A,I0,A)') 'Failed to read line ',I+2,' (out of ',InitOut%NStepWave+1,' expected lines) in file '//TRIM(FileName)//& + & '. Check that the number of lines (without header) is equal to WaveTMax/WaveDT. ' + OK=.FALSE. + RETURN + END IF + + ! Extract fields (ReadCAryFromStr is in NWTC_IO) + CALL ReadCAryFromStr ( TextLine, s, n, 'line', 'junk', ErrStat, ErrMsgTmp ) + IF (ErrStat/=0) THEN + ErrStat = ErrID_Fatal + write(ErrMsg,'(A,I0,A,I0,A)') 'Failed to extract fields from line ',I+2,' in file '//TRIM(FileName)//'. '//& + & trim(ErrMsgTmp)//' Check that the number of columns is correct and matches the number of internal HydroDyn nodes.'//& + &' (Typically twice the number of joints).' + OK=.FALSE. + RETURN + END IF + END FUNCTION ExtractFields + + SUBROUTINE CleanUp( ) + + IF (ALLOCATED( WaveDataStr )) DEALLOCATE( WaveDataStr, STAT=ErrStatTmp) + IF (ALLOCATED( WaveData )) DEALLOCATE( WaveData, STAT=ErrStatTmp) + !IF (ALLOCATED( outOfWaterFlag )) DEALLOCATE( outOfWaterFlag, STAT=ErrStatTmp) + !IF (ALLOCATED( GHWvDpth )) DEALLOCATE( GHWvDpth, STAT=ErrStatTmp) + !IF (ALLOCATED( WaveElev0 )) DEALLOCATE( WaveElev0, STAT=ErrStatTmp) + CLOSE(UnWv) + RETURN + END SUBROUTINE CleanUp + + END SUBROUTINE UserWaves_Init +END MODULE UserWaves diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT.f90 new file mode 100644 index 000000000..6081e2f7d --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT.f90 @@ -0,0 +1,1728 @@ +!********************************************************************************************************************************** +! The WAMIT and WAMIT_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. WAMITs_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of WAMIT. +! +! 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 +! +!********************************************************************************************************************************** +MODULE WAMIT + + USE Waves + USE WAMIT_Types + USE WAMIT_Output + USE WAMIT_Interp + USE NWTC_Library + ! USE Waves_Types + USE Conv_Radiation + USE SS_Radiation + USE SS_Excitation + USE NWTC_FFTPACK + + IMPLICIT NONE + + PRIVATE + + REAL(DbKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of DbKi. + + TYPE(ProgDesc), PARAMETER :: WAMIT_ProgDesc = ProgDesc( 'WAMIT', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: WAMIT_Init ! Initialization routine + PUBLIC :: WAMIT_End ! Ending routine (includes clean up) + + PUBLIC :: WAMIT_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: WAMIT_CalcOutput ! Routine for computing outputs + + PUBLIC :: WAMIT_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: WAMIT_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: WAMIT_UpdateDiscState ! Tight coupling routine for updating discrete states + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(WAMIT_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine. NOTE: we need INOUT because we may be moving the allocation of SS_Excitation data + TYPE(WAMIT_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(WAMIT_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(WAMIT_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(WAMIT_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(WAMIT_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(WAMIT_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(WAMIT_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) WAMIT_UpdateStates() is called in loose coupling & + !! (2) WAMIT_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(WAMIT_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + + + ! These are dummy variables to satisfy the framework, but are not used + TYPE(Conv_Rdtn_InitInputType) :: Conv_Rdtn_InitInp ! Local version of the intialization data for the radiation module + TYPE(Conv_Rdtn_InitOutputType) :: Conv_Rdtn_InitOut ! Initialization Outputs from the Conv_Rdtn module initialization + !TYPE(Conv_Rdtn_InitOutputType) :: Conv_RdtnInitOutData + TYPE(SS_Rad_InitInputType) :: SS_Rdtn_InitInp ! Local version of the intialization data for the radiation module + TYPE(SS_Rad_InitOutputType) :: SS_Rdtn_InitOut ! Initialization Outputs from the SS_Rdtn module initialization + TYPE(SS_Exc_InitInputType) :: SS_Exctn_InitInp ! Local version of the intialization data for the SS wave excitation module + TYPE(SS_Exc_InitOutputType) :: SS_Exctn_InitOut ! Initialization Outputs from the SS wave excitation module initialization + + + ! Local Variables + REAL(DbKi) :: Interval_Sub ! Local timestep for the SS_Rad and SS_Exc modules, based on RdtnDT + COMPLEX(SiKi), ALLOCATABLE :: HdroExctn (:,:,:) ! Frequency- and direction-dependent complex hydrodynamic wave excitation force per unit wave amplitude vector (kg/s^2, kg-m/s^2) + COMPLEX(SiKi), ALLOCATABLE :: WaveExctnC(:,:) ! Discrete Fourier transform of the instantaneous value of the total excitation force on the support platfrom from incident waves (N, N-m) + REAL(ReKi) :: DffrctDim (6) ! Matrix used to redimensionalize WAMIT hydrodynamic wave excitation force output (kg/s^2, kg-m/s^2 ) + REAL(SiKi), ALLOCATABLE :: HdroAddMs (:,:) ! The upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic added mass matrix from the radiation problem (kg , kg-m , kg-m^2 ) + REAL(SiKi), ALLOCATABLE :: HdroDmpng (:,:) ! The upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic damping matrix from the radiation problem (kg/s, kg-m/s, kg-m^2/s) + REAL(SiKi), ALLOCATABLE :: HdroFreq (:) ! Frequency components inherent in the hydrodynamic added mass matrix, hydrodynamic daming matrix, and complex wave excitation force per unit wave amplitude vector (rad/s) + REAL(SiKi), ALLOCATABLE :: HdroWvDir (:) ! Incident wave propagation heading direction components inherent in the complex wave excitation force per unit wave amplitude vector (degrees) + REAL(ReKi) :: HighFreq ! The highest frequency component in the WAMIT file, not counting infinity. + REAL(ReKi) :: Omega ! Wave frequency (rad/s) + REAL(ReKi) :: PrvDir ! The value of TmpDir from the previous line (degrees) + REAL(ReKi) :: PrvPer ! The value of TmpPer from the previous line (sec ) + REAL(ReKi) :: SttcDim (6,6) ! Matrix used to redimensionalize WAMIT hydrostatic restoring output (kg/s^2, kg-m/s^2, kg-m^2/s^2) + REAL(ReKi) :: RdtnDim (6,6) ! Matrix used to redimensionalize WAMIT hydrodynamic added mass and damping output (kg , kg-m , kg-m^2 ) + REAL(ReKi) :: TmpData1 ! A temporary value read in from a WAMIT file (- ) + REAL(ReKi) :: TmpData2 ! A temporary value read in from a WAMIT file (- ) + REAL(ReKi) :: TmpDir ! A temporary direction read in from a WAMIT file (degrees) + REAL(ReKi) :: TmpIm ! A temporary imaginary value read in from a WAMIT file (- ) - stored as a REAL value + REAL(ReKi) :: TmpPer ! A temporary period read in from a WAMIT file (sec ) + REAL(ReKi) :: TmpRe ! A temporary real value read in from a WAMIT file (- ) + REAL(SiKi) :: TmpCoord(2) ! A temporary real array to hold the (Omega,WaveDir) pair for interpolation + REAL(ReKi), ALLOCATABLE :: WAMITFreq (:) ! Frequency components as ordered in the WAMIT output files (rad/s ) + REAL(ReKi), ALLOCATABLE :: WAMITPer (:) ! Period components as ordered in the WAMIT output files (sec ) + REAL(ReKi), ALLOCATABLE :: WAMITWvDir(:) ! Wave direction components as ordered in the WAMIT output files (degrees) + + INTEGER :: I ! Generic index + INTEGER :: Indx ! Cycles through the upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic added mass and damping matrices from the radiation problem + INTEGER :: InsertInd ! The lowest sorted index whose associated frequency component is higher than the current frequency component -- this is to sort the frequency components from lowest to highest + INTEGER :: J ! Generic index + INTEGER :: K ! Generic index + INTEGER :: LastInd ! Index into the arrays saved from the last call as a starting point for this call + INTEGER :: LastInd2(2) ! Index into the arrays saved from the last call as a starting point for this call. 2D + INTEGER :: NInpFreq ! Number of input frequency components inherent in the hydrodynamic added mass matrix, hydrodynamic daming matrix, and complex wave excitation force per unit wave amplitude vector (-) + INTEGER :: NInpWvDir ! Number of input incident wave propagation heading direction components inherent in the complex wave excitation force per unit wave amplitude vector (-) + INTEGER, ALLOCATABLE :: SortFreqInd (:) ! The array of indices such that WAMITFreq (SortFreqInd (:)) is sorted from lowest to highest frequency (-) + INTEGER, ALLOCATABLE :: SortWvDirInd(:) ! The array of indices such that WAMITWvDir(SortWvDirInd(:)) is sorted from lowest to highest agnle (-) + INTEGER :: Sttus ! Status returned by an attempted allocation or READ. + INTEGER :: UnW1 ! I/O unit number for the WAMIT output file with the .1 extension; this file contains the linear, nondimensionalized, frequency-dependent solution to the radiation problem. + INTEGER :: UnW3 ! I/O unit number for the WAMIT output file with the .3 extension; this file contains the linear, nondimensionalized, frequency-dependent solution to the diffraction problem. + INTEGER :: UnWh ! I/O unit number for the WAMIT output file with the .hst extension; this file contains the linear, nondimensionalized hydrostatic restoring matrix. + + LOGICAL :: FirstFreq ! When .TRUE., indicates we're still looping through the first frequency component. + LOGICAL :: FirstPass ! When .TRUE., indicates we're on the first pass through a loop. + LOGICAL :: InfFreq ! When .TRUE., indicates that the infinite-frequency limit of added mass is contained within the WAMIT output files. + LOGICAL :: NewPer ! When .TRUE., indicates that the period has just changed. + LOGICAL :: ZeroFreq ! When .TRUE., indicates that the zero -frequency limit of added mass is contained within the WAMIT output files. + + CHARACTER(1024) :: Line ! String to temporarily hold the value of a line within a WAMIT output file. + + TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using + + ! Error handling + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message for calls + INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls + + + + ! Initialize data + + HighFreq = 0.0 + UnW1 = 31 + UnW3 = 32 + UnWh = 33 + LastInd = 1 + LastInd2 = 0 + InfFreq = .FALSE. + ZeroFreq = .FALSE. + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library (set pi constants) + + CALL NWTC_Init( ) + + ! Copy Output Init data from Waves Module Init call + + p%RhoXg = InitInp%RhoXg + p%NStepWave = InitInp%NStepWave + p%NumOuts = InitInp%NumOuts + p%ExctnMod = InitInp%ExctnMod + + ! For now, we are forcing WAMIT to use the glue-code time-step. If the Convolution-based radiation module was requesting a different timestep (RdtnDT) + ! Then HydroDyn will have already thrown an error. + + p%DT = Interval + + !IF ( InitInp%HasWAMIT ) THEN + ! p%NumOuts = InitInp%NumOuts + !ELSE + ! p%NumOuts = 0 ! Need to set this so the when a call uses generic output writing code, there will be no WAMIT outputs + ! + ! RETURN ! We don't need to do any further initialization work because we are not using WAMIT + + ! Need to allocate and copy data and then destroy the original ??? + ALLOCATE ( p%WaveTime (0:p%NStepWave ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + p%WaveTime = InitInp%WaveTime + + ! Copy Input Init data into parameters + + p%PtfmVol0 = InitInp%PtfmVol0 + p%PtfmCOBxt = InitInp%PtfmCOBxt + p%PtfmCOByt = InitInp%PtfmCOByt + + + + + + + + + + + + + + + + + + + + ! Tell our nice users what is about to happen that may take a while: + + CALL WrScr ( ' Reading in WAMIT output with root name "'//TRIM(InitInp%WAMITFile)//'".' ) + + + + ! Let's set up the matrices used to redimensionalize the hydrodynamic data + ! from WAMIT; all these matrices are symmetric and need to be used with + ! element-by-element multiplication, instead of matrix-by-matrix + ! multiplication: + + SttcDim(1,1) = p%RhoXg *InitInp%WAMITULEN**2 ! Force-translation + SttcDim(1,4) = p%RhoXg *InitInp%WAMITULEN**3 ! Force-rotation/Moment-translation - Hydrostatic restoring + SttcDim(4,4) = p%RhoXg *InitInp%WAMITULEN**4 ! Moment-rotation + + RdtnDim(1,1) = InitInp%WtrDens*InitInp%WAMITULEN**3 ! Force-translation + RdtnDim(1,4) = InitInp%WtrDens*InitInp%WAMITULEN**4 ! Force-rotation/Moment-translation - Hydrodynamic added mass and damping + RdtnDim(4,4) = InitInp%WtrDens*InitInp%WAMITULEN**5 ! Moment-rotation + + DffrctDim(1) = p%RhoXg *InitInp%WAMITULEN**2 ! Force-translation - Hydrodynamic wave excitation force + DffrctDim(4) = p%RhoXg *InitInp%WAMITULEN**3 ! Moment-rotation + + DO I = 1,3 ! Loop through all force-translation elements (rows) + + DO J = 1,3 ! Loop through all force-translation elements (columns) + + SttcDim(I,J) = SttcDim(1,1) + + RdtnDim(I,J) = RdtnDim(1,1) + + END DO ! J - All force-translation elements (columns) + + DffrctDim (I ) = DffrctDim(1) + + END DO ! I - All force-translation elements (rows) + + DO I = 1,3 ! Loop through all force-rotation/moment-translation elements (rows/columns) + + DO J = 4,6 ! Loop through all force-rotation/moment-translation elements (columns/rows) + + SttcDim(I,J) = SttcDim(1,4) + SttcDim(J,I) = SttcDim(1,4) + + RdtnDim(I,J) = RdtnDim(1,4) + RdtnDim(J,I) = RdtnDim(1,4) + + END DO ! J - All force-rotation/moment-translation elements (rows/columns) + + END DO ! I - All force-rotation/moment-translation elements (columns/rows) + + DO I = 4,6 ! Loop through all moment-rotation elements (rows) + + DO J = 4,6 ! Loop through all moment-rotation elements (columns) + + SttcDim(I,J) = SttcDim(4,4) + + RdtnDim(I,J) = RdtnDim(4,4) + + END DO ! J - All moment-rotation elements (columns) + + DffrctDim (I ) = DffrctDim(4) + + END DO ! I - All moment-rotation elements (rows) + + + + + ! Let's read in and redimensionalize the hydrodynamic data from the WAMIT + ! output files: + + + + ! Linear restoring from the hydrostatics problem: + + CALL OpenFInpFile ( UnWh, TRIM(InitInp%WAMITFile)//'.hst', ErrStat2, ErrMsg2 ) ! Open file. + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + p%HdroSttc (:,:) = 0.0 ! Initialize to zero + + DO ! Loop through all rows in the file + + + READ (UnWh,*,IOSTAT=Sttus) I, J, TmpData1 ! Read in the row index, column index, and nondimensional data from the WAMIT file + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully +!bjj: TODO verify that I and J are valid values + p%HdroSttc (I,J) = TmpData1*SttcDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array + + ELSE ! We must have reached the end of the file, so stop reading in data + + EXIT + + END IF + + + END DO ! End loop through all rows in the file + + CLOSE ( UnWh ) ! Close file. + + + + ! Linear, frequency-dependent hydrodynamic added mass and damping from the + ! radiation problem: + + CALL OpenFInpFile ( UnW1, TRIM(InitInp%WAMITFile)//'.1', ErrStat2, ErrMsg2 ) ! Open file. + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! First find the number of input frequency components inherent in the + ! hydrodynamic added mass matrix, hydrodynamic daming matrix, and complex + ! wave excitation force per unit wave amplitude vector: + + NInpFreq = 0 ! Initialize to zero + PrvPer = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + DO ! Loop through all rows in the file + + + READ (UnW1,*,IOSTAT=Sttus) TmpPer ! Read in only the period from the WAMIT file + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + IF ( FirstPass .OR. ( TmpPer /= PrvPer ) ) THEN ! .TRUE. if we are on the first pass or if the period currently read in is different than the previous period read in; thus we found a new frequency in the WAMIT file! + NInpFreq = NInpFreq + 1 ! Since we found a new frequency, count it in the total + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + END IF + + ELSE ! We must have reached the end of the file, so stop reading in data !bjj -- this isn't necessarially true.... + + EXIT + + END IF + + + END DO ! End loop through all rows in the file + + + REWIND (UNIT=UnW1) ! REWIND the file so we can read it in a second time. + + + ! Now that we know how many frequencies there are, we can ALLOCATE the arrays + ! to store the frequencies and frequency-dependent hydrodynamic added mass + ! and damping matrices: + + CALL AllocAry( WAMITFreq, NInpFreq, 'WAMITFreq', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( WAMITPer, NInpFreq, 'WAMITPer', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( SortFreqInd, NInpFreq, 'SortFreqInd', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroFreq, NInpFreq, 'HdroFreq', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroAddMs, NInpFreq, 21,'HdroAddMs', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroDmpng, NInpFreq, 21,'HdroDmpng', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! Now find out how the frequencies are ordered in the file. When we read in + ! the added mass and damping matrices, we need to have them sorted by + ! increasing frequency. Thus, find the array of indices, SortFreqInd(), + ! such that WAMITFreq(SortFreqInd(:)) is sorted from lowest to highest + ! frequency: + + K = 0 ! Initialize to zero + PrvPer = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + DO ! Loop through all rows in the file + + + READ (UnW1,*,IOSTAT=Sttus) TmpPer ! Read in only the period from the WAMIT file + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + IF ( FirstPass .OR. ( TmpPer /= PrvPer ) ) THEN ! .TRUE. if we are on the first pass or if the period currently read in is different than the previous period read in; thus we found a new frequency in the WAMIT file! + + K = K + 1 ! This is current count of which frequency component we are on + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + + WAMITPer (K) = TmpPer ! Store the periods in the order they appear in the WAMIT file + IF ( TmpPer < 0.0 ) THEN ! Periods less than zero in WAMIT represent infinite period = zero frequency + WAMITFreq(K) = 0.0 + ZeroFreq = .TRUE. + ELSEIF ( TmpPer == 0.0 ) THEN ! Periods equal to zero in WAMIT represent infinite frequency + WAMITFreq(K) = HUGE(TmpPer) ! Use HUGE() to approximate infinity in the precision of ReKi + InfFreq = .TRUE. + ELSE ! We must have positive, non-infinite frequency + WAMITFreq(K) = TwoPi/TmpPer ! Store the periods as frequencies in rad/s in the order they appear in the WAMIT file + HighFreq = MAX( HighFreq, WAMITFreq(K) ) ! Find the highest frequency (HighFreq) in the WAMIT output file, not counting infinity (even if the infinite frequency limit is in the file). + END IF + + InsertInd = K ! Initialize as the K'th component + DO I = 1,K-1 ! Loop throuh all previous frequencies + IF ( ( WAMITFreq(I) > WAMITFreq(K) ) ) THEN ! .TRUE. if a previous frequency component is higher than the current frequency component + InsertInd = MIN( InsertInd, SortFreqInd(I) ) ! Store the lowest sorted index whose associated frequency component is higher than the current frequency component + SortFreqInd(I) = SortFreqInd(I) + 1 ! Shift all of the sorted indices up by 1 whose associated frequency component is higher than the current frequency component + END IF + END DO ! I - All previous frequencies + SortFreqInd(K) = InsertInd ! Store the index such that WAMITFreq(SortFreqInd(:)) is sorted from lowest to highest frequency + + END IF + + ELSE ! We must have reached the end of the file, so stop reading in data + + EXIT + + END IF + + + END DO ! End loop through all rows in the file + + + REWIND (UNIT=UnW1) ! REWIND the file so we can read it in a third time. (This is getting ridiculous!) + + + ! Now we can finally read in the frequency-dependent added mass and damping + ! matrices; only store the upper-triangular portions (diagonal and above) + ! of these matrices: + + K = 0 ! Initialize to zero + PrvPer = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + HdroAddMs(:,:) = 0.0 ! Initialize to zero + HdroDmpng(:,:) = 0.0 ! Initialize to zero + + DO ! Loop through all rows in the file + + + READ (UnW1,'(A)',IOSTAT=Sttus) Line ! Read in the entire line + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + + READ (Line,*) TmpPer ! Read in only the period from the WAMIT file + + + IF ( FirstPass .OR. ( TmpPer /= PrvPer ) ) THEN ! .TRUE. if we are on the first pass or if the period currently read in is different than the previous period read in; thus we found a new frequency in the WAMIT file! + + K = K + 1 ! This is current count of which frequency component we are on + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + + IF ( TmpPer < 0.0 ) THEN ! Periods less than zero in WAMIT represent infinite period = zero frequency + HdroFreq (SortFreqInd(K)) = 0.0 + ELSEIF ( TmpPer == 0.0 ) THEN ! Periods equal to zero in WAMIT represent infinite frequency; a value slightly larger than HighFreq is returned to approximate infinity while still maintaining an effective interpolation later on. + HdroFreq (SortFreqInd(K)) = HighFreq*OnePlusEps ! Set the infinite frequency to a value slightly larger than HighFreq + ELSE ! We must have positive, non-infinite frequency + HdroFreq (SortFreqInd(K)) = TwoPi/TmpPer ! Convert the period in seconds to a frequency in rad/s and store them sorted from lowest to highest + END IF + + END IF + + + IF ( TmpPer <= 0.0 ) THEN ! .TRUE. if the current period is less than or equal to zero, which in WAMIT represents the zero and infinite frequency limits, respectively; in these cases, only the added mass matrix is computed and output by WAMIT (and based on hydrodynamic theory, the damping matrix is zero as initialized above) + + READ (Line,*,IOSTAT=Sttus) TmpPer, I, J, TmpData1 ! Read in the period, row index, column index, and nondimensional data from the WAMIT file + + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, "Error reading line from WAMIT file", ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF +!bjj: verify that I and J are valid indices for RdtnDim + + + IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal + Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + + HdroAddMs(SortFreqInd(K),Indx) = TmpData1*RdtnDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array + END IF + + ELSE ! We must have a positive, non-infinite frequency. + + READ (Line,*,IOSTAT=Sttus) TmpPer, I, J, TmpData1, TmpData2 ! Read in the period, row index, column index, and nondimensional data from the WAMIT file + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, "Error reading line from WAMIT file", ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF +!bjj: verify that I and J are valid indices for RdtnDim + + IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal + Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + + HdroAddMs(SortFreqInd(K),Indx) = TmpData1*RdtnDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array + HdroDmpng(SortFreqInd(K),Indx) = TmpData2*RdtnDim(I,J)*HdroFreq(SortFreqInd(K)) ! Redimensionalize the data and place it at the appropriate location within the array + END IF + + END IF + + + ELSE ! We must have reached the end of the file, so stop reading in data + + + EXIT + + + END IF + + + END DO ! End loop through all rows in the file + + + CLOSE ( UnW1 ) ! Close file. + + + + ! Linear, frequency- and direction-dependent complex hydrodynamic wave + ! excitation force per unit wave amplitude vector from the diffraction + ! problem: + + CALL OpenFInpFile ( UnW3, TRIM(InitInp%WAMITFile)//'.3', ErrStat2, ErrMsg2 ) ! Open file. + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + ! First find the number of input incident wave propagation heading direction + ! components inherent in the complex wave excitation force per unit wave + ! amplitude vector: + + NInpWvDir = 0 ! Initialize to zero + PrvDir = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + DO ! Loop through all rows in the file + + + READ (UnW3,'(A)',IOSTAT=Sttus) Line ! Read in the entire line + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + + READ (Line,*) TmpPer, TmpDir ! Read in only the period and direction from the WAMIT file !bjj why don't we check IOSTAT here, too???? + + + IF ( FirstPass ) THEN ! .TRUE. if we are on the first pass + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + END IF + + + IF ( TmpPer /= PrvPer ) THEN ! .TRUE. if the period currently read in is different than the previous period read in; thus we found a new period in the WAMIT file, so stop reading in data + EXIT + END IF + + + IF ( FirstPass .OR. ( TmpDir /= PrvDir ) ) THEN ! .TRUE. if we are on the first pass or if the direction currently read in is different than the previous direction read in; thus we found a new direction in the WAMIT file! + NInpWvDir = NInpWvDir + 1 ! Since we found a new direction, count it in the total + PrvDir = TmpDir ! Store the current direction as the previous direction for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + END IF + + + ELSE ! We must have reached the end of the file, so stop reading in data + + + EXIT + + + END IF + + + END DO ! End loop through all rows in the file + + + REWIND (UNIT=UnW3) ! REWIND the file so we can read it in a second time. + + + ! Now that we know how many directions there are, we can ALLOCATE the arrays to + ! to store the directions and frequency- and direction-dependent complex wave + ! excitation force per unit wave amplitude vector: + + CALL AllocAry( WAMITWvDir, NInpWvDir, 'WAMITWvDir', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( SortWvDirInd, NInpWvDir, 'SortWvDirInd', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroWvDir, NInpWvDir, 'HdroWvDir', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ALLOCATE ( HdroExctn (NInpFreq,NInpWvDir,6) , STAT=ErrStat2 ) ! complex so we don't have a reoutine + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for HdroExctn array', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + + ! Now find out how the directions are ordered in the file. When we read in + ! the wave excitation force vector, we need to have them sorted by + ! increasing angle. Thus, find the array of indices, SortWvDirInd(), + ! such that WAMITWvDir(SortWvDirInd(:)) is sorted from lowest to highest + ! angle. At the same time, make sure that the frequencies in the .3 file are + ! ordered in the same way they are in the .1 file and make sure that the + ! directions are the same for each frequency component: + + K = 0 ! Initialize to zero + PrvPer = 0.0 ! Initialize to a don't care + PrvDir = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + DO ! Loop through all rows in the file + + + READ (UnW3,'(A)',IOSTAT=Sttus) Line ! Read in the entire line + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + + READ (Line,*,IOSTAT=Sttus) TmpPer, TmpDir ! Read in only the period and direction from the WAMIT file + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error reading period and direction from WAMIT file.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + + IF ( FirstPass .OR. ( TmpPer /= PrvPer ) ) THEN ! .TRUE. if we are on the first pass or if the period currently read in is different than the previous period read in; thus we found a new period in the WAMIT file! + + J = 0 ! Reset the count of directions to zero + K = K + 1 ! This is current count of which frequency component we are on + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + FirstFreq = FirstPass ! Sorry, you can only loop through the first frequency once + NewPer = .TRUE. ! Reset the new period flag + + DO WHILE ( WAMITPer(K) <= 0.0 ) ! Periods less than or equal to zero in WAMIT represent infinite period = zero frequency and infinite frequency, respectively. However, only the added mass is output by WAMIT at these limits. The damping and wave excitation are left blank, so skip them! + K = K + 1 + END DO + + IF ( TmpPer /= WAMITPer(K) ) THEN ! Abort if the .3 and .1 files do not contain the same frequency components (not counting zero and infinity) + ErrMsg2 = ' Other than zero and infinite frequencies, "' //TRIM(InitInp%WAMITFile)//'.3",' // & + ' contains different frequency components than "'//TRIM(InitInp%WAMITFile)//'.1". '// & + ' Both WAMIT output files must be generated from the same run.' + CALL SetErrStat( ErrID_Fatal, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + END IF + + + IF ( FirstPass .OR. ( TmpDir /= PrvDir ) .OR. NewPer ) THEN ! .TRUE. if we are on the first pass, or if this is new period, or if the direction currently read in is different than the previous direction read in; thus we found a new direction in the WAMIT file! + + J = J + 1 ! This is current count of which direction component we are on + PrvDir = TmpDir ! Store the current direction as the previous direction for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + NewPer = .FALSE. ! Disable the new period flag + + IF ( FirstFreq ) THEN ! .TRUE. while we are still looping through all directions for the first frequency component + WAMITWvDir(J) = TmpDir ! Store the directions in the order they appear in the WAMIT file + + InsertInd = J ! Initialize as the J'th component + DO I = 1,J-1 ! Loop throuh all previous directions + IF ( ( WAMITWvDir(I) > WAMITWvDir(J) ) ) THEN ! .TRUE. if a previous direction component is higher than the current direction component + InsertInd = MIN( InsertInd, SortWvDirInd(I) ) ! Store the lowest sorted index whose associated direction component is higher than the current direction component + SortWvDirInd(I) = SortWvDirInd(I) + 1 ! Shift all of the sorted indices up by 1 whose associated direction component is higher than the current direction component + END IF + END DO ! I - All previous directions + SortWvDirInd(J) = InsertInd ! Store the index such that WAMITWvDir(SortWvDirInd(:)) is sorted from lowest to highest direction + ELSEIF ( TmpDir /= WAMITWvDir(J) ) THEN ! We must have looped through all directions at least once; so check to make sure all subsequent directions are consistent with the directions from the first frequency component, otherwise Abort + ErrMsg2 = ' Not every frequency component in "'//TRIM(InitInp%WAMITFile)//'.3"'// & + ' contains the same listing of direction angles. Check for' // & + ' errors in the WAMIT output file.' + CALL SetErrStat( ErrID_Fatal, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + END IF + + + ELSE ! We must have reached the end of the file, so stop reading in data + + + EXIT + + + END IF + + + END DO ! End loop through all rows in the file + +if (p%ExctnMod == 1 ) then + REWIND (UNIT=UnW3) ! REWIND the file so we can read it in a third time. (This is getting ridiculous!) + + + ! Now we can finally read in the frequency- and direction-dependent complex + ! wave excitation force per unit wave amplitude vector: + + K = 0 ! Initialize to zero + PrvPer = 0.0 ! Initialize to a don't care + PrvDir = 0.0 ! Initialize to a don't care + FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass + + HdroExctn(:,:,:) = 0.0 ! Initialize to zero + + DO ! Loop through all rows in the file + + + READ (UnW3,'(A)',IOSTAT=Sttus) Line ! Read in the entire line + + IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully + + + READ (Line,*,IOSTAT=Sttus) TmpPer, TmpDir, I, TmpData1, TmpData2, TmpRe, TmpIm ! Read in the period, direction, row index, and nondimensional data from the WAMIT file + IF ( Sttus /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error reading period and direction, row index, and nondimensional data from the WAMIT file.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + + IF ( FirstPass .OR. ( TmpPer /= PrvPer ) ) THEN ! .TRUE. if we are on the first pass or if the period currently read in is different than the previous period read in; thus we found a new period in the WAMIT file! + + J = 0 ! Reset the count of directions to zero + K = K + 1 ! This is current count of which frequency component we are on + PrvPer = TmpPer ! Store the current period as the previous period for the next pass + FirstFreq = FirstPass ! Sorry, you can only loop through the first frequency once + NewPer = .TRUE. ! Reset the new period flag + + DO WHILE ( WAMITPer(K) <= 0.0 ) ! Periods less than or equal to zero in WAMIT represent infinite period = zero frequency and infinite frequency, respectively. However, only the added mass is output by WAMIT at these limits. The damping and wave excitation are left blank, so skip them! + K = K + 1 + END DO + + END IF + + + IF ( FirstPass .OR. ( TmpDir /= PrvDir ) .OR. NewPer ) THEN ! .TRUE. if we are on the first pass, or if this is new period, or if the direction currently read in is different than the previous direction read in; thus we found a new direction in the WAMIT file! + + J = J + 1 ! This is current count of which direction component we are on + PrvDir = TmpDir ! Store the current direction as the previous direction for the next pass + FirstPass = .FALSE. ! Sorry, you can only have one first pass + NewPer = .FALSE. ! Disable the new period flag + + IF ( FirstFreq ) THEN ! .TRUE. while we are still looping through all directions for the first frequency component + HdroWvDir(SortWvDirInd(J)) = TmpDir ! Store the directions sorted from lowest to highest + END IF + + END IF + + + HdroExctn(SortFreqInd(K),SortWvDirInd(J),I) = CMPLX( TmpRe, TmpIm )*DffrctDim(I) ! Redimensionalize the data and place it at the appropriate location within the array + + + ELSE ! We must have reached the end of the file, so stop reading in data + + + EXIT + + + END IF + + + END DO ! End loop through all rows in the file + + + CLOSE ( UnW3 ) ! Close file. + +end if + + ! For some reason, WAMIT computes the zero- and infinite- frequency limits for + ! only the added mass. Based on hydrodynamic theory, the damping is zero at + ! these limits (as initialized). Hydrodynamic theory also says that the + ! infinite-frequency limit of the diffraction force is zero (as initialized); + ! however, the zero-frequency limit need not be zero. Thus, if necessary + ! (i.e., if we have read in a WAMIT output file that contains the + ! zero-frequency limit of the added mass), compute the zero-frequency limit + ! of the diffraction problem using the known values at the lowest + ! nonzero-valued frequency available: + + DO I = 1,NInpFreq ! Loop through all input frequency components + + IF ( HdroFreq(I) > 0.0 ) THEN ! .TRUE. at the lowest nonzero-valued frequency component + + DO J = I-1,1,-1 ! Loop through all zero-valued frequency components + HdroExctn(J,:,:) = HdroExctn(I,:,:) ! Set the zero-frequency limits to equal the known values at the lowest nonzero-valued frequency available + END DO ! J - All zero-valued frequency components + + EXIT ! Since HdroFreq(:) is sorted from lowest to highest frequency, there is no reason to continue on once we have found the lowest nonzero-valued frequency component + + END IF + + END DO ! I - All input frequency components + + + + ! Tell our nice users what is about to happen that may take a while: + + CALL WrScr ( ' Computing radiation impulse response functions and wave diffraction forces.' ) + + + + ! Abort if the WAMIT files do not contain both the zero- and and infinite- + ! frequency limits of added mass. + + IF ( .NOT. ( ZeroFreq .AND. InfFreq ) ) THEN ! .TRUE. if both the zero- and infinite-frequency limits of added mass are contained within the WAMIT file + ErrMsg2 = ' "'//TRIM(InitInp%WAMITFile)// & + '.1" must contain both the zero- and infinite-frequency limits of added mass.' + CALL SetErrStat( ErrID_Fatal, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + + + ! Set the infinite-frequency limit of the frequency-dependent hydrodynamic + ! added mass matrix, HdroAdMsI, based on the highest frequency available: + + Indx = 0 + DO J = 1,6 ! Loop through all rows of HdroAdMsI + DO K = J,6 ! Loop through all columns of HdroAdMsI above and including the diagonal + Indx = Indx + 1 + p%HdroAdMsI(J,K) = HdroAddMs(NInpFreq,Indx) + END DO ! K - All columns of HdroAdMsI above and including the diagonal + DO K = J+1,6 ! Loop through all rows of HdroAdMsI below the diagonal + p%HdroAdMsI(K,J) = p%HdroAdMsI(J,K) + END DO ! K - All rows of HdroAdMsI below the diagonal + END DO ! J - All rows of HdroAdMsI + + + if ( ( p%ExctnMod == 0 ) ) then + + ! no need to allocate the p%WaveExctn array because it won't be used + + else + ! Initialize the variables associated with the incident wave: + + SELECT CASE ( InitInp%WaveMod ) ! Which incident wave kinematics model are we using? + CASE ( 0 ) + if ( p%ExctnMod == 1 ) then + ! Initialize everything to zero: + + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + p%WaveExctn = 0.0 + + else if ( p%ExctnMod == 2 ) then + Interval_Sub = InitInp%Conv_Rdtn%RdtnDT + SS_Exctn_InitInp%InputFile = InitInp%WAMITFile + SS_Exctn_InitInp%WaveDir = InitInp%WaveDir + SS_Exctn_InitInp%NStepWave = p%NStepWave + + ! No other modules need this WaveElev0 array so we will simply move the allocation over to the SS_Exctn module + IF (ALLOCATED(InitInp%WaveElev0)) CALL MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) + + ! We need the WaveTime array to stay intact for use in other modules, so we will make a copy instead of moving the allocation + ALLOCATE ( SS_Exctn_InitInp%WaveTime (0:InitInp%NStepWave) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the SS_Exctn_InitInp%WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + SS_Exctn_InitInp%WaveTime = InitInp%WaveTime + + call SS_Exc_Init(SS_Exctn_InitInp, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, & + m%SS_Exctn_y, m%SS_Exctn, Interval_Sub, SS_Exctn_InitOut, ErrStat2, ErrMsg2) + + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + end if + CASE ( 1, 2, 3, 4, 5, 10 ) ! Plane progressive (regular) wave, JONSWAP/Pierson-Moskowitz spectrum (irregular) wave, white-noise wave, or user-defined spectrum (irregular) wave. + + ! Abort if we have chosen a wave heading direction that is outside the range + ! of directions where the complex wave excitation force per unit wave + ! amplitude vector has been defined, else interpolate to find the complex + ! wave excitation force per unit wave amplitude vector at the chosen wave + ! heading direction: + ! NOTE: we may end up inadvertantly aborting if the wave direction crosses + ! the -Pi / Pi boundary (-180/180 degrees). + + IF ( ( InitInp%WaveDirMin < HdroWvDir(1) ) .OR. ( InitInp%WaveDirMax > HdroWvDir(NInpWvDir) ) ) THEN + ErrMsg2 = 'All Wave directions must be within the wave heading angle range available in "' & + //TRIM(InitInp%WAMITFile)//'.3" (inclusive).' + CALL SetErrStat( ErrID_Fatal, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + if ( p%ExctnMod == 1 ) then + + ! Calculate the WaveExctn data from WAMIT data if ExctnMod = 1 + + ! ALLOCATE the arrays: + + ALLOCATE ( WaveExctnC(0:InitInp%NStepWave2 ,6) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctnC array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + + + ! Compute the positive-frequency components (including zero) of the discrete + ! Fourier transform of the wave excitation force: + + DO I = 0,InitInp%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transform + + ! Compute the frequency of this component: + + Omega = I*InitInp%WaveDOmega + + ! Compute the discrete Fourier transform of the instantaneous value of the + ! total excitation force on the support platfrom from incident waves: + + DO J = 1,6 ! Loop through all wave excitation forces and moments + TmpCoord(1) = Omega + TmpCoord(2) = InitInp%WaveDirArr(I) + CALL WAMIT_Interp2D_Cplx( TmpCoord, HdroExctn(:,:,J), HdroFreq, HdroWvDir, LastInd2, WaveExctnC(I,J), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + WaveExctnC(I,J) = WaveExctnC(I,J) * CMPLX(InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I)) + END DO ! J - All wave excitation forces and moments + + + END DO ! I - The positive frequency components (including zero) of the discrete Fourier transform + + + + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Dump the HdroFreq variable to a file for debugging + ! Open and write header info to the HydroDyn Output File + !CALL OpenFOutFile ( 66, 'C:\Dev\NREL_SVN\HydroDyn\branches\HydroDyn_Modularization\Samples\NRELOffshrBsline5MW_OC3Hywind\HdroFreq_HD.txt', ErrStat ) ! Open motion file. + !DO K = 1, NInpFreq + ! WRITE ( 66, '(2(e20.9))', IOSTAT = ErrStat) REAL(K), HdroFreq(K) + !END DO + !CLOSE ( 66 ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Dump the WaveElevCO variable to a file for debugging + ! Open and write header info to the HydroDyn Output File + !CALL OpenFOutFile ( 66, 'C:\Dev\NREL_SVN\HydroDyn\branches\HydroDyn_Modularization\Samples\NRELOffshrBsline5MW_OC3Hywind\WaveElevC0_HD.txt', ErrStat ) ! Open motion file. + !DO K = 0, InitInp%NStepWave2 + ! WRITE ( 66, '(2(e20.9))', IOSTAT = ErrStat) REAL(K), REAL(InitInp%WaveElevC0(K)) + !END DO + !CLOSE ( 66 ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Dump the WaveExctnC variable to a file for debugging + ! Open and write header info to the HydroDyn Output File + !CALL OpenFOutFile ( 66, 'C:\Dev\NREL_SVN\HydroDyn\branches\HydroDyn_Modularization\Samples\NRELOffshrBsline5MW_OC3Hywind\WaveExctnC_HD.txt', ErrStat ) ! Open motion file. + !DO K = 0, InitInp%NStepWave2 + ! WRITE ( 66, '(7(e20.9))', IOSTAT = ErrStat) REAL(K), REAL(WaveExctnC(K,:)) + !END DO + !CLOSE ( 66 ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + ! Compute the inverse discrete Fourier transform to find the time-domain + ! representation of the wave excitation force: + + CALL InitFFT ( InitInp%NStepWave, FFT_Data, .TRUE., ErrStat2 ) + CALL SetErrStat( ErrStat2, 'Error in call to InitFFT.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + DO J = 1,6 ! Loop through all wave excitation forces and moments + CALL ApplyFFT_cx ( p%WaveExctn(0:InitInp%NStepWave-1,J), WaveExctnC(:,J), FFT_Data, ErrStat2 ) + CALL SetErrStat( ErrStat2, ' An error occured while applying an FFT to WaveExctnC.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Append first datpoint as the last as aid for repeated wave data + p%WaveExctn(InitInp%NStepWave,J) = p%WaveExctn(0,J) + END DO ! J - All wave excitation forces and moments + + CALL ExitFFT(FFT_Data, ErrStat2) + CALL SetErrStat( ErrStat2, 'Error in call to ExitFFT.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + else if ( p%ExctnMod == 2 ) then + Interval_Sub = InitInp%Conv_Rdtn%RdtnDT + SS_Exctn_InitInp%InputFile = InitInp%WAMITFile + SS_Exctn_InitInp%WaveDir = InitInp%WaveDir + SS_Exctn_InitInp%NStepWave = p%NStepWave + + ! No other modules need this WaveElev0 array so we will simply move the allocation over to the SS_Exctn module + IF (ALLOCATED(InitInp%WaveElev0)) CALL MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) + + ! We need the WaveTime array to stay intact for use in other modules, so we will make a copy instead of moving the allocation + ALLOCATE ( SS_Exctn_InitInp%WaveTime (0:InitInp%NStepWave) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the SS_Exctn_InitInp%WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + SS_Exctn_InitInp%WaveTime = InitInp%WaveTime + + call SS_Exc_Init(SS_Exctn_InitInp, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, & + m%SS_Exctn_y, m%SS_Exctn, Interval_Sub, SS_Exctn_InitOut, ErrStat2, ErrMsg2) + + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + end if + + CASE ( 6 ) ! User wave data. + + CALL SetErrStat( ErrID_Fatal, 'User input wave data not applicable for floating platforms.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + + ENDSELECT + end if + + IF ( InitInp%RdtnTMax == 0.0 ) THEN ! .TRUE. when we don't want to model wave radiation damping; set RdtnTMax to some minimum value greater than zero to avoid an error in the calculations below. + + p%RdtnMod = 0 + + ELSE ! We will be modeling wave radiation damping. + + p%RdtnMod = InitInp%RdtnMod + + if ( InitInp%RdtnMod == 1 ) THEN + + ! Set Initialization data for the Conv_Rdtn submodule + ! Would be nice if there were a copy InitInput function in the *_Types file + ! BJJ 6/25/2014: There is a copy InitInput function.... ??? + + CALL MOVE_ALLOC( HdroFreq, Conv_Rdtn_InitInp%HdroFreq ) + CALL MOVE_ALLOC( HdroAddMs, Conv_Rdtn_InitInp%HdroAddMs ) + CALL MOVE_ALLOC( HdroDmpng, Conv_Rdtn_InitInp%HdroDmpng ) + + Conv_Rdtn_InitInp%RdtnTMax = InitInp%RdtnTMax + Conv_Rdtn_InitInp%RdtnDT = InitInp%Conv_Rdtn%RdtnDT + Conv_Rdtn_InitInp%HighFreq = HighFreq + Conv_Rdtn_InitInp%WAMITFile = InitInp%WAMITFile + Conv_Rdtn_InitInp%NInpFreq = NInpFreq + Conv_Rdtn_InitInp%UnSum = InitInp%Conv_Rdtn%UnSum + + + CALL Conv_Rdtn_Init(Conv_Rdtn_InitInp, m%Conv_Rdtn_u, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, z%Conv_Rdtn, OtherState%Conv_Rdtn, & + m%Conv_Rdtn_y, m%Conv_Rdtn, Interval, Conv_Rdtn_InitOut, ErrStat2, ErrMsg2) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ELSE IF ( InitInp%RdtnMod == 2 ) THEN + + SS_Rdtn_InitInp%InputFile = InitInp%WAMITFile + SS_Rdtn_InitInp%DOFs = 1 + Interval_Sub = InitInp%Conv_Rdtn%RdtnDT + CALL SS_Rad_Init(SS_Rdtn_InitInp, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, & + m%SS_Rdtn_y, m%SS_Rdtn, Interval_Sub, SS_Rdtn_InitOut, ErrStat2, ErrMsg2) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + END IF + + END IF + + ! create the input and output meshes + ! CALL MeshCreate(u%MeshData, COMPONENT_INPUT, 1, ErrStat2, ErrMsg2, .TRUE.) + ! deallocate arrays + + IF ( ALLOCATED( HdroExctn ) ) DEALLOCATE( HdroExctn ) + IF ( ALLOCATED( WaveExctnC ) ) DEALLOCATE( WaveExctnC ) + IF ( ALLOCATED( HdroAddMs ) ) DEALLOCATE( HdroAddMs ) + IF ( ALLOCATED( HdroDmpng ) ) DEALLOCATE( HdroDmpng ) + IF ( ALLOCATED( HdroFreq ) ) DEALLOCATE( HdroFreq ) + IF ( ALLOCATED( HdroWvDir ) ) DEALLOCATE( HdroWvDir ) + + IF ( ALLOCATED( WAMITFreq ) ) DEALLOCATE( WAMITFreq ) + IF ( ALLOCATED( WAMITPer ) ) DEALLOCATE( WAMITPer ) + IF ( ALLOCATED( WAMITWvDir ) ) DEALLOCATE( WAMITWvDir ) + IF ( ALLOCATED( SortFreqInd ) ) DEALLOCATE( SortFreqInd ) + IF ( ALLOCATED( SortWvDirInd ) ) DEALLOCATE( SortWvDirInd ) + + + + ! Define system output initializations (set up mesh) here: + + + ! Create the input and output meshes associated with lumped loads + + CALL MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Create the node on the mesh + + + + CALL MeshPositionNode (u%Mesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + CALL MeshCommit ( u%Mesh & + , ErrStat2 & + , ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + CALL MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + ! Define initialization-routine output here: + + ! Initialize the outputs + CALL WMTOUT_Init( InitInp, y, p, InitOut, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + + ! initialize misc vars: + m%LastIndWave = 1 + + CALL Cleanup() + +CONTAINS + + + SUBROUTINE Cleanup() + + ! destroy local variables that are types in the framework: + + CALL Conv_Rdtn_DestroyInitInput( Conv_Rdtn_InitInp, ErrStat2, ErrMsg2 ) + CALL Conv_Rdtn_DestroyInitOutput( Conv_Rdtn_InitOut, ErrStat2, ErrMsg2 ) + + CALL SS_Rad_DestroyInitInput( SS_Rdtn_InitInp, ErrStat2, ErrMsg2 ) + CALL SS_Rad_DestroyInitOutput( SS_Rdtn_InitOut, ErrStat2, ErrMsg2 ) + CALL SS_Exc_DestroyInitInput( SS_Exctn_InitInp, ErrStat2, ErrMsg2 ) + CALL SS_Exc_DestroyInitOutput( SS_Exctn_InitOut, ErrStat2, ErrMsg2 ) + + + ! destroy local variables that are allocatable arrays: + + IF ( ALLOCATED( HdroExctn ) ) DEALLOCATE(HdroExctn ) + IF ( ALLOCATED( WaveExctnC ) ) DEALLOCATE(WaveExctnC ) + + IF ( ALLOCATED( HdroAddMs ) ) DEALLOCATE(HdroAddMs ) + IF ( ALLOCATED( HdroDmpng ) ) DEALLOCATE(HdroDmpng ) + IF ( ALLOCATED( HdroFreq ) ) DEALLOCATE(HdroFreq ) + IF ( ALLOCATED( HdroWvDir ) ) DEALLOCATE(HdroWvDir ) + + IF ( ALLOCATED( WAMITFreq ) ) DEALLOCATE(WAMITFreq ) + IF ( ALLOCATED( WAMITPer ) ) DEALLOCATE(WAMITPer ) + IF ( ALLOCATED( WAMITWvDir ) ) DEALLOCATE(WAMITWvDir ) + IF ( ALLOCATED( SortFreqInd ) ) DEALLOCATE(SortFreqInd ) + IF ( ALLOCATED( SortWvDirInd) ) DEALLOCATE(SortWvDirInd) + + + END SUBROUTINE Cleanup + +END SUBROUTINE WAMIT_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE WAMIT_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(WAMIT_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(WAMIT_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(WAMIT_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(WAMIT_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(WAMIT_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(WAMIT_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL WAMIT_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL WAMIT_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL WAMIT_DestroyContState( x, ErrStat, ErrMsg ) + CALL WAMIT_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL WAMIT_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL WAMIT_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + ! Destroy misc vars: + CALL WAMIT_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL WAMIT_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE WAMIT_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE WAMIT_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(WAMIT_InputType), INTENT(IN ) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(WAMIT_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(WAMIT_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(WAMIT_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(WAMIT_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 + + ! Local variables + + INTEGER :: I ! Generic loop counter + INTEGER :: nTime ! Number of inputs +! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (secondary error) +! CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + + ! Create dummy variables required by framework but which are not used by the module + + TYPE(Conv_Rdtn_InputType), ALLOCATABLE :: Conv_Rdtn_u(:) ! Inputs + + TYPE(SS_Rad_InputType), ALLOCATABLE :: SS_Rdtn_u(:) ! Inputs + TYPE(SS_Exc_InputType), ALLOCATABLE :: SS_Exctn_u(:) ! Inputs + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + nTime = size(Inputs) + + + + + + + IF ( p%RdtnMod == 1 ) THEN ! Update the convolution radiation memory effect sub-module's state + + ! Allocate array of Conv_Rdtn inputs + + ALLOCATE( Conv_Rdtn_u(nTime), STAT = ErrStat ) + IF (ErrStat /=0) THEN + ErrMsg = ' Failed to allocate array Conv_Rdtn_u.' + RETURN + END IF + + DO I=1,nTime + Conv_Rdtn_u(I)%Velocity = (/Inputs(I)%Mesh%TranslationVel(:,1), Inputs(I)%Mesh%RotationVel(:,1)/) + END DO + + CALL Conv_Rdtn_UpdateStates( t, n, Conv_Rdtn_u, InputTimes, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, & + z%Conv_Rdtn, OtherState%Conv_Rdtn, m%Conv_Rdtn, ErrStat, ErrMsg ) + + DEALLOCATE(Conv_Rdtn_u) + + ELSE IF ( p%RdtnMod == 2 ) THEN ! Update the state-space radiation memory effect sub-module's state + + ! Allocate array of SS_Rdtn inputs + + ALLOCATE( SS_Rdtn_u(nTime), STAT = ErrStat ) + IF (ErrStat /=0) THEN + ErrMsg = ' Failed to allocate array SS_Rdtn_u.' + RETURN + END IF + + DO I=1,nTime + SS_Rdtn_u(I)%dq(1:3) = Inputs(I)%Mesh%TranslationVel(:,1) + SS_Rdtn_u(I)%dq(4:6) = Inputs(I)%Mesh%RotationVel(:,1) + !SS_Rdtn_u(I)%dq = reshape((/Inputs(I)%Mesh%TranslationVel(:,1), Inputs(I)%Mesh%RotationVel(:,1)/), (/6,1/)) !reshape(u%Velocity, (/6,1/)) ! dq is a 6x1 matrix + END DO + + CALL SS_Rad_UpdateStates( t, n, SS_Rdtn_u, InputTimes, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, ErrStat, ErrMsg ) + + DEALLOCATE(SS_Rdtn_u) + + END IF + + if ( p%ExctnMod == 2 ) then ! Update the state-space wave excitation sub-module's states + + ! Allocate array of dummy SS_Excitation inputs for the framework + + allocate( SS_Exctn_u(nTime), STAT = ErrStat ) + if (ErrStat /=0) then + ErrMsg = ' Failed to allocate array SS_Exctn_u.' + return + end if + + call SS_Exc_UpdateStates( t, n, SS_Exctn_u, InputTimes, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, m%SS_Exctn, ErrStat, ErrMsg ) + + deallocate(SS_Exctn_u) + + end if + +END SUBROUTINE WAMIT_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(WAMIT_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 + + + + ! Local Variables: + !REAL(ReKi) :: F_HS (6) ! Total load contribution from hydrostatics, including the effects of waterplane area and the center of buoyancy (N, N-m) + !REAL(ReKi) :: F_Waves (6) ! Total load contribution from incident waves (i.e., the diffraction problem) (N, N-m) + !REAL(ReKi) :: F_Rdtn (6) ! Total load contribution from wave radiation damping (i.e., the diffraction problem) (N, N-m) + INTEGER(IntKi) :: I ! Generic index + INTEGER(IntKi) :: J ! Generic index +! INTEGER(IntKi) :: K ! Generic index + REAL(ReKi) :: q(6), qdot(6), qdotdot(6) + REAL(ReKi) :: rotdisp(3) ! small angle rotational displacements + REAL(ReKi) :: AllOuts(MaxWAMITOutputs) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute outputs here: + + + + ! Compute the load contribution from incident waves (i.e., the diffraction problem): + if ( p%ExctnMod == 0 ) then + + m%F_Waves1 = 0.0_ReKi + + else if ( p%ExctnMod == 1 ) then + + ! Abort if the wave excitation loads have not been computed yet: + IF ( .NOT. ALLOCATED ( p%WaveExctn ) ) THEN + ErrMsg = ' Routine WAMIT_Init() must be called before routine WAMIT_CalcOutput().' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,6 ! Loop through all wave excitation forces and moments + m%F_Waves1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveExctn(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + END DO ! I - All wave excitation forces and moments + + else if ( p%ExctnMod == 2 ) then + + call SS_Exc_CalcOutput( Time, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, & + z%SS_Exctn, OtherState%SS_Exctn, m%SS_Exctn_y, m%SS_Exctn, ErrStat, ErrMsg ) + m%F_Waves1 (:) = m%SS_Exctn_y%y + + end if + + + + + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,1), ErrStat, ErrMsg ) + + q = reshape((/real(u%Mesh%TranslationDisp(:,1),ReKi),rotdisp(:)/),(/6/)) + qdot = reshape((/u%Mesh%TranslationVel(:,1),u%Mesh%RotationVel(:,1)/),(/6/)) + qdotdot = reshape((/u%Mesh%TranslationAcc(:,1),u%Mesh%RotationAcc(:,1)/),(/6/)) + + + ! Compute the load contirbution from user-supplied added stiffness and damping + ! This is being done by the HydroDyn Module now. GJH 1/6/14 + m%F_PtfmAdd = 0.0 ! p%AddF0 - matmul(p%AddCLin, q) - matmul(p%AddBLin, qdot) - matmul(p%AddBQuad, qdotsq) + + + + + + ! Compute the load contribution from hydrostatics: + + m%F_HS(:) = 0.0 ! Initialize to zero... + m%F_HS(3) = p%RhoXg*p%PtfmVol0 ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position + m%F_HS(4) = p%RhoXg*p%PtfmVol0*p%PtfmCOByt ! and the moment about X due to the COB being offset from the WAMIT reference point + m%F_HS(5) = -p%RhoXg*p%PtfmVol0*p%PtfmCOBxt ! and the moment about Y due to the COB being offset from the WAMIT reference point + + DO I = 1,6 ! Loop through all hydrostatic forces and moments + DO J = 1,6 ! Loop through all platform DOFs + m%F_HS(I) = m%F_HS(I) - p%HdroSttc(I,J)*q(J) + END DO ! J - platform DOFs + + END DO ! I - All hydrostatic forces and moments + + + + + + ! If necessary, compute the load contribution from wave radiation damping + ! (i.e., the radiation problem): + + IF ( p%RdtnMod == 1 ) THEN ! .TRUE. when we will be modeling wave radiation damping. + m%Conv_Rdtn_u%Velocity = qdot + CALL Conv_Rdtn_CalcOutput( Time, m%Conv_Rdtn_u, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, & + z%Conv_Rdtn, OtherState%Conv_Rdtn, m%Conv_Rdtn_y, m%Conv_Rdtn, ErrStat, ErrMsg ) + m%F_Rdtn (:) = m%Conv_Rdtn_y%F_Rdtn + + ELSE IF ( p%RdtnMod == 2 ) THEN + m%SS_Rdtn_u%dq = qdot + CALL SS_Rad_CalcOutput( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, & + z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn_y, m%SS_Rdtn, ErrStat, ErrMsg ) + m%F_Rdtn (:) = m%SS_Rdtn_y%y + ELSE ! We must not be modeling wave radiation damping. + + + ! Set the total load contribution from radiation damping to zero: + + m%F_Rdtn (:) = 0.0 + + + END IF + + + ! Compute Added Mass Forces + + ! Set the platform added mass matrix, PtfmAM, to be the infinite-frequency + ! limit of the frequency-dependent hydrodynamic added mass matrix, + ! HdroAdMsI: + + !added mass: + + m%F_PtfmAM = -matmul(p%HdroAdMsI, qdotdot) + + + + ! Compute outputs here: + DO I=1,3 + y%Mesh%Force(I,1) = m%F_PtfmAM(I) + m%F_Rdtn(I) + m%F_Waves1(I) + m%F_HS(I) + m%F_PtfmAdd(I) + END DO + DO I=1,3 + y%Mesh%Moment(I,1) = m%F_PtfmAM(I+3) + m%F_Rdtn(I+3) + m%F_Waves1(I+3) + m%F_HS(I+3) + m%F_PtfmAdd(I+3) + END DO + + + + + + + + ! Map calculated results into the AllOuts Array + CALL WMTOut_MapOutputs(Time, y, m%F_Waves1, m%F_HS, m%F_Rdtn, m%F_PtfmAM, AllOuts, ErrStat, ErrMsg) + + + ! Put the output data in the OutData array + + DO I = 1,p%NumOuts + + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + + END DO + + +END SUBROUTINE WAMIT_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE WAMIT_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(WAMIT_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(WAMIT_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + if (p%RdtnMod == 2) then + m%SS_Rdtn_u%dq(1:3) = u%Mesh%TranslationVel(:,1) + m%SS_Rdtn_u%dq(4:6) = u%Mesh%RotationVel(:,1) + + CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) + end if + + ! NOTE: The input below (0.0) will only work as part of a linearization Get_OP call! If this routine (WAMIT_CalcContStateDeriv) is called in another context, then the following + ! input needs to be implemented generically. + if (p%ExctnMod == 2) then + CALL SS_Exc_CalcContStateDeriv( Time, 0.0_SiKi, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, m%SS_Exctn, dxdt%SS_Exctn, ErrStat, ErrMsg ) + end if + +END SUBROUTINE WAMIT_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +SUBROUTINE WAMIT_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(WAMIT_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !< Output: Discrete states at Time + Interval + TYPE(WAMIT_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at Time (THIS [intent out] VIOLATES THE FRAMEWORK) + TYPE(WAMIT_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + IF ( p%RdtnMod == 1 ) THEN ! .TRUE. when we will be modeling wave radiation damping. + + m%Conv_Rdtn_u%Velocity = (/u%Mesh%TranslationVel(:,1), u%Mesh%RotationVel(:,1)/) + + CALL Conv_Rdtn_UpdateDiscState( Time, n, m%Conv_Rdtn_u, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, z%Conv_Rdtn, & + OtherState%Conv_Rdtn, m%Conv_Rdtn, ErrStat, ErrMsg ) + + END IF + + +END SUBROUTINE WAMIT_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations +SUBROUTINE WAMIT_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(WAMIT_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(WAMIT_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(WAMIT_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + call SS_Rad_CalcConstrStateResidual( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, z_residual%SS_Rdtn, ErrStat, ErrMsg ) + +END SUBROUTINE WAMIT_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE WAMIT +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT.txt b/OpenFAST/modules/hydrodyn/src/WAMIT.txt new file mode 100644 index 000000000..b4aedf027 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT.txt @@ -0,0 +1,149 @@ +################################################################################################################################### +# Registry for WAMIT in the FAST Modularization Framework +# This Registry file is used to create MODULE WAMIT which contains all of the user-defined types needed in WAMIT. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt +usefrom Conv_Radiation.txt +usefrom SS_Radiation.txt +usefrom SS_Excitation.txt +usefrom Waves.txt +param WAMIT/WAMIT unused INTEGER MaxWAMITOutputs - 18 - "" - +typedef WAMIT/WAMIT InitInputType ReKi PtfmVol0 - - - "" - +typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - +typedef ^ ^ ReKi WAMITULEN - - - "" - +typedef ^ ^ ReKi PtfmCOBxt - - - "" - +typedef ^ ^ ReKi PtfmCOByt - - - "" - +typedef ^ ^ INTEGER RdtnMod - - - "" - +typedef ^ ^ INTEGER ExctnMod - - - "" - +typedef ^ ^ DbKi RdtnTMax - - - "" - +typedef ^ ^ ReKi WaveDir - - - "" - +typedef ^ ^ CHARACTER(1024) WAMITFile - - - "" - +typedef ^ ^ Conv_Rdtn_InitInputType Conv_Rdtn - - - "" - +#typedef ^ ^ SS_Rad_InitInputType SS_Rdtn - - - "" - +#typedef ^ ^ SS_Exc_InitInputType SS_Excn - - - "" - +typedef ^ ^ ReKi Rhoxg - - - "" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ INTEGER NStepWave2 - - - "" - +typedef ^ ^ ReKi WaveDOmega - - - "" - +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin (needed for SS_Excitation module)" m +typedef ^ ^ SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) +typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ INTEGER WaveMod - - - "" - +typedef ^ ^ ReKi WtrDens - - - "" - +typedef ^ ^ SiKi WaveDirArr {:} - - "Array of wave directions (one per frequency) from the Waves module" - +typedef ^ ^ SiKi WaveDirMin - - - "Minimum wave direction from Waves module" - +typedef ^ ^ SiKi WaveDirMax - - - "Maximum wave direction from Waves module" - +typedef ^ ^ CHARACTER(ChanLen) OutList {18} - - "This should really be dimensioned with MaxOutPts" - +typedef ^ ^ LOGICAL OutAll - - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +# +# +# Define outputs from the initialization routine here: +# +#typedef ^ InitOutputType MeshType OutputMesh - - - "" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SS_Rad_ContinuousStateType SS_Rdtn - - - "continuous states from the State Space radiation module" - +typedef ^ ContinuousStateType SS_Exc_ContinuousStateType SS_Exctn - - - "continuous states from the State Space radiation module" - +typedef ^ ^ Conv_Rdtn_ContinuousStateType Conv_Rdtn - - - "placeholder" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType Conv_Rdtn_DiscreteStateType Conv_Rdtn - - - "discrete states from the convolution radiation module" - +typedef ^ DiscreteStateType SS_Rad_DiscreteStateType SS_Rdtn - - - "placeholder" - +typedef ^ DiscreteStateType SS_Exc_DiscreteStateType SS_Exctn - - - "placeholder" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType Conv_Rdtn_ConstraintStateType Conv_Rdtn - - - "placeholder" - +typedef ^ ConstraintStateType SS_Rad_ConstraintStateType SS_Rdtn - - - "placeholder" - +typedef ^ ConstraintStateType SS_Exc_ConstraintStateType SS_Exctn - - - "placeholder" - +# +# + +# Define any data that are integer or logical states here: +typedef ^ OtherStateType SS_Rad_OtherStateType SS_Rdtn - - - "" - +typedef ^ OtherStateType SS_Exc_OtherStateType SS_Exctn - - - "" - +typedef ^ ^ Conv_Rdtn_OtherStateType Conv_Rdtn - - - "" - + + +# ..... 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 INTEGER LastIndWave - - - "" - +typedef ^ ^ ReKi F_HS {6} - - "local variable in CalcOutput:Total load contribution from hydrostatics, including the effects of waterplane area and the center of buoyancy" "(N, N-m)" +typedef ^ ^ ReKi F_Waves1 {6} - - "local variable in CalcOutput:Total load contribution from incident waves (i.e., the diffraction problem)" "(N, N-m)" +typedef ^ ^ ReKi F_Rdtn {6} - - "local variable in CalcOutput:Total load contribution from wave radiation damping (i.e., the diffraction problem)" "(N, N-m)" +typedef ^ ^ ReKi F_PtfmAdd {6} - - "local variable in CalcOutput:set to zero because this is calculated in HydroDyn now" - +typedef ^ ^ ReKi F_PtfmAM {6} - - "local variable in CalcOutput:" - +typedef ^ ^ SS_Rad_MiscVarType SS_Rdtn - - - "" - +typedef ^ ^ SS_Rad_InputType SS_Rdtn_u - - - "" - +typedef ^ ^ SS_Rad_OutputType SS_Rdtn_y - - - "" - +typedef ^ ^ SS_Exc_MiscVarType SS_Exctn - - - "" - +typedef ^ ^ SS_Exc_InputType SS_Exctn_u - - - "" - +typedef ^ ^ SS_Exc_OutputType SS_Exctn_y - - - "" - +typedef ^ ^ Conv_Rdtn_MiscVarType Conv_Rdtn - - - "" - +typedef ^ ^ Conv_Rdtn_InputType Conv_Rdtn_u - - - "" - +typedef ^ ^ Conv_Rdtn_OutputType Conv_Rdtn_y - - - "" - + +# ..... 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 HdroAdMsI {6}{6} - - "" (sec) +typedef ^ ^ ReKi HdroSttc {6}{6} - - "" - +typedef ^ ^ ReKi PtfmVol0 - - - "" - +typedef ^ ^ ReKi PtfmCOBxt - - - "" - +typedef ^ ^ ReKi PtfmCOByt - - - "" - +typedef ^ ^ INTEGER RdtnMod - - - "" - +typedef ^ ^ INTEGER ExctnMod - - - "" - +typedef ^ ^ SiKi WaveExctn {:}{:} - - "" - +typedef ^ ^ ReKi RhoXg - - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ Conv_Rdtn_ParameterType Conv_Rdtn - - - "" - +typedef ^ ^ SS_Rad_ParameterType SS_Rdtn - - - "" - +typedef ^ ^ SS_Exc_ParameterType SS_Exctn - - - "" - +typedef ^ ^ DbKi DT - - - "" - +typedef ^ ^ LOGICAL PtfmSgF - - - "" - +typedef ^ ^ LOGICAL PtfmSwF - - - "" - +typedef ^ ^ LOGICAL PtfmHvF - - - "" - +typedef ^ ^ LOGICAL PtfmRF - - - "" - +typedef ^ ^ LOGICAL PtfmPF - - - "" - +typedef ^ ^ LOGICAL PtfmYF - - - "" - +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - +typedef ^ ^ CHARACTER(ChanLen) Delim - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType MeshType Mesh - - - "Displacements at the WAMIT reference point in the inertial frame" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType Mesh - - - "Loads at the WAMIT reference point in the inertial frame" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT2.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT2.f90 new file mode 100644 index 000000000..af8865192 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT2.f90 @@ -0,0 +1,5771 @@ +!********************************************************************************************************************************** +! NOTE: documentation in this file is written for use with Doxygen 1.8.6 and higher. +! +!> WAMIT2 module +!! +!! This module calculates the second order wave forces on a structure. This module is used with HydroDyn in FAST. +!! +!! This software is written in the FAST modular framework. +!! +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of the WAMIT2 sub-module of HydroDyn. +! +! 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 +! +!********************************************************************************************************************************** +MODULE WAMIT2 + + + + !> Known issues: + !! + !! 1. _Problem:_ + !! In the Read_DataFile3D and Read_DataFile4D routines, if the wave direction information crosses the +/-pi boundary, + !! it will end up sorted incorrectly. This issue has not been fixed or addressed in any way yet. + !! _Effects:_ + !! During checking of the wave directions to see if the data in the WAMIT file spans the full range of the required + !! wave directions when multidirectional waves are used, we will have an issue. This will occur during the error + !! checking within the MnDrift_InitCalc, NewmanApp_InitCalc, DiffQTF_InitCalc, and SumQTF_InitCalc routines. + !! _Solution:_ + !! -- Fix the ordering of the wave direction array in the Read_DataFile3D and Read_DataFile4D arrays. Allow these arrays + !! span from -2pi to 2pi so that the directions are contiguous. Add checks here to make sure the data read in is + !! shifted appropriately (i.e., data crosses the +/-pi boundary with values at 175 and -175 degrees, shift everything + !! so that it lies between 0 and 360 degrees so that it is contiguous). + !! -- In the _InitCalc routines, change the handling of the WaveDirMin and WaveDirMax and shift them when testing + !! across the +/-pi boundary. + !! _Reason not implimented:_ + !! It takes so long for WAMIT to perform the calculations for the QTF that it is unlikely that any data where this is + !! a problem will arise before time is found to fix it. Right now, time is not available. + !! + + + + USE WAMIT2_Types + USE WAMIT_Interp + USE WAMIT2_Output + USE NWTC_Library + USE NWTC_FFTPACK + + IMPLICIT NONE + + PRIVATE + +! INTEGER(IntKi), PARAMETER :: DataFormatID = 1 !< Update this value if the data types change (used in WAMIT_Pack) + TYPE(ProgDesc), PARAMETER :: WAMIT2_ProgDesc = ProgDesc( 'WAMIT2', '', '' ) + !< This holds the name of the program, version info, and date. + + REAL(DbKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of DbKi. + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: WAMIT2_Init !< Initialization routine + PUBLIC :: WAMIT2_End !< Ending routine (includes clean up) + + PUBLIC :: WAMIT2_UpdateStates !< Loose coupling routine for solving for constraint states, integrating + !! continuous states, and updating discrete states + PUBLIC :: WAMIT2_CalcOutput !< Routine for computing outputs + + PUBLIC :: WAMIT2_CalcConstrStateResidual !< Tight coupling routine for returning the constraint state residual + PUBLIC :: WAMIT2_CalcContStateDeriv !< Tight coupling routine for computing derivatives of continuous states + PUBLIC :: WAMIT2_UpdateDiscState !< Tight coupling routine for updating discrete states + + !PUBLIC :: WAMIT2_JacobianPInput !< Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! !! (Xd), and constraint-state (Z) equations all with respect to the inputs (u) + !PUBLIC :: WAMIT2_JacobianPContState !< Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! !! (Xd), and constraint-state (Z) equations all with respect to the continuous + ! !! states (x) + !PUBLIC :: WAMIT2_JacobianPDiscState !< Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! !! (Xd), and constraint-state (Z) equations all with respect to the discrete + ! !! states (xd) + !PUBLIC :: WAMIT2_JacobianPConstrState !< Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + !! (Xd), and constraint-state (Z) equations all with respect to the constraint + !! states (z) + + + + ! Derived types for data storage. + ! There are a couple of good methods that would work for storing the data from the files. We could: + ! 1. Store the data according to which file it came from. Seems redundant + ! 2. Store the data in generic 3D or 4D structures (types). This makes passing data messy. + ! 3. Store the data according to difference or sum method. The difference method data becomes larger as it has to include + ! the 3D and 4D options. But it makes the passing of data much simpler to subroutines. + ! 4. Store the data as QTF and nonQTF method data. The QTF method data would be only 4D, the nonQTF could be either 3D or + ! or 4D. Both the NewmanApp and MnDrift methods could use either the 4D (tossing most of it) or 3D. This option + ! becomes unatractive since we end up mixing the data for the full QTF diff method (DiffQTF) with the sum QTF (SumQTF) + ! + ! In light of the options, it was arbitrarily chosen to use the 3rd method. This is favors keeping the difference methods + ! together, and the sum method as a separate entity. This will streamline calls from the DiffQTF method to the MnDrift method + ! (the first term of the DiffQTF equation is the MnDrift equation). + + + !> This type is only used locally for holding data during the Initialization. It will not be used outside of the WAMIT2_Init + !! routine. The 3D data is of the form F_k( WvFreq1, WvDir1, WvDir2, k ) where k is coordinate index to the load components + !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumWvDir1,NumWvDir2,6). The LoadComponents array + !! contains flags that will indicate which of the LoadComponents were read in from the data file. + !! + !! The DataMask array is of the same size as the DataSet matrix and corresponds to it. Each point in DataMask that is true + !! indicates that the datapoint in DataSet is an actual value. Any missing points are set to 0 in DataSet and marked as + !! FALSE in DataMask. This is used for determining if the matrix is sparse or not. If any points are missing, then DataIsSparse + !! is set to TRUE. This will determine which algorithm we use for interpolation. + TYPE, PRIVATE :: W2_InitData3D_Type + INTEGER(IntKi) :: NumWvFreq1 !< Number of frequencies in first frequency direction set + INTEGER(IntKi) :: NumWvDir1 !< Number of wave directions in first wave direction set + INTEGER(IntKi) :: NumWvDir2 !< Number of wave directions in second wave direction set + LOGICAL :: DataIsSparse(6) !< Flag to indicate if the data is sparse or complete. One per component direction + LOGICAL :: LoadComponents(6) !< Which load components actually exist in the input file + COMPLEX(SiKi), ALLOCATABLE :: DataSet(:,:,:,:) !< Storage for 3D data from the 2nd order WAMIT file + LOGICAL, ALLOCATABLE :: DataMask(:,:,:,:) !< Mask for knowing which data points are complete, which are missing + REAL(SiKi), ALLOCATABLE :: WvFreq1(:) !< (1:NumFreq1) elements -- values correspond to index 1 of DataSet + REAL(SiKi), ALLOCATABLE :: WvDir1(:) !< (1:NumWvDir1) elements -- values correspond to index 2 of DataSet + REAL(SiKi), ALLOCATABLE :: WvDir2(:) !< (1:NumWvDir2) elements -- values correspond to index 3 of DataSet + END TYPE W2_InitData3D_Type + + + !> This type is only used locally for holding data during the Initialization. It will not be used outside of the WAMIT2_Init + !! routine. The 4D data is of the form F_k( WvFreq1, WvFreq2, WvDir1, WvDir2, k ) where k is coordinate index to the load components + !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumFreq2,NumWvDir1,NumWvDir2,6). The LoadComponents + !! array contains flags that will indicate which of the LoadComponents were read in from the data file. + !! + !! The DataMask array is of the same size as the DataSet matrix and corresponds to it. Each point in DataMask that is true + !! indicates that the datapoint in DataSet is an actual value. Any missing points are set to 0 in DataSet and marked as + !! FALSE in DataMask. This is used for determining if the matrix is sparse or not. + TYPE, PRIVATE :: W2_InitData4D_Type + INTEGER(IntKi) :: NumWvFreq1 !< Number of frequencies in first frequency direction set + INTEGER(IntKi) :: NumWvFreq2 !< Number of frequencies in second frequency direction set + INTEGER(IntKi) :: NumWvDir1 !< Number of wave directions in first wave direction set + INTEGER(IntKi) :: NumWvDir2 !< Number of wave directions in second wave direction set + LOGICAL :: DataIsSparse(6) !< Flag to indicate if the data is sparse or complete. One per component direction + LOGICAL :: WvFreqDiagComplete !< Flag to indicate if the diagonal element is complete or not (Omega_m, Omega_m). + LOGICAL :: IsSumForce !< Flag to indicate that this is a sum type array. Used in setting the F_{nm} term from F_{mn} term. + LOGICAL :: LoadComponents(6) !< Which load components actually exist in the input file + COMPLEX(SiKi), ALLOCATABLE :: DataSet(:,:,:,:,:) !< Storage for 4D data from the 2nd order WAMIT file + LOGICAL, ALLOCATABLE :: DataMask(:,:,:,:,:) !< Mask for knowing which data points are complete, which are missing + REAL(SiKi), ALLOCATABLE :: WvFreq1(:) !< (1:NumFreq1) elements -- values correspond to index 1 of DataSet + REAL(SiKi), ALLOCATABLE :: WvFreq2(:) !< (1:NumFreq2) elements -- values correspond to index 2 of DataSet + REAL(SiKi), ALLOCATABLE :: WvDir1(:) !< (1:NumWvDir1) elements -- values correspond to index 3 of DataSet + REAL(SiKi), ALLOCATABLE :: WvDir2(:) !< (1:NumWvDir2) elements -- values correspond to index 4 of DataSet + END TYPE W2_InitData4D_Type + + + !> This type is used to hold the data for difference frequency methods. Only one difference method can be used at a time, + !! but the data could be 3D or 4D depending on the method and input file used. So in order to simplify keeping track of + !! the data, this data structure was created to contain all difference data. Note that since only one method can be used + !! at a time, only one input file can be used at a time, and only one of Data3D or Data4D can be populated. The flags + !! DataIs3D and DataIs4D can be true at a time. + !! + !! | Algorithm | 3D data | 4D data | + !! | :-----------: | :--------: | :-------: | + !! | MnDrift | yes | yes | + !! | NewmanApp | yes | yes | + !! | DiffQTF | NO | yes | + !! + TYPE, PRIVATE :: W2_DiffData_Type + CHARACTER(1024) :: FileName !< The filename the data came from + LOGICAL :: DataIs3D !< Only one of DataIs3D and DataIs4D can be true + LOGICAL :: DataIs4D !< Only one of DataIs3D and DataIs4D can be true + TYPE(W2_InitData3D_Type) :: Data3D !< The 3D type from above + TYPE(W2_InitData4D_Type) :: Data4D !< The 4D type from above + END TYPE W2_DiffData_Type + + + + !> This type is used to hold the data for sum frequency method. Only 4D data can be used for this method, so we + !! will only allow 4D data within the type. The only reason for actually making this type is to maintain consistency + !! with the difference methods (helps with the programming implimentation). + !! + !! The flag DataIs4D is a carryover from the W2_DiffData_Type, and is preserved only for constency in the programming. + !! + !! | Algorithm | 3D data | 4D data | + !! | :-----------: | :--------: | :-------: | + !! | SumQTF | NO | yes | + !! + TYPE, PRIVATE :: W2_SumData_Type + CHARACTER(1024) :: FileName !< The filename the data came from + LOGICAL :: DataIs4D !< Only true if Data4D is populated + TYPE(W2_InitData4D_Type) :: Data4D !< The 4D type from above + END TYPE W2_SumData_Type + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!> @brief +!! This routine is called at the start of the simulation to perform initialization steps. +!! The parameters that are set here are not changed during the simulation. +!! The initial states and initial guess for the input are defined. +SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(WAMIT2_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(WAMIT2_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(WAMIT2_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(WAMIT2_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(WAMIT2_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; only the output mesh is initialized) + TYPE(WAMIT2_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: don't change it from the glue code provided value. + TYPE(WAMIT2_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local Variables +! TYPE(FFT_DataType) :: FFT_Data !< the instance of the FFT module we're using + + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + + ! QTF storage -- from the data files that are read in + TYPE(W2_DiffData_Type) :: MnDriftData !< Data storage for the Mean Drift method + TYPE(W2_DiffData_Type) :: NewmanAppData !< Data storage for the Newman's Approximation method + TYPE(W2_DiffData_Type) :: DiffQTFData !< Data storage for the full difference QTF method + TYPE(W2_SumData_Type) :: SumQTFData !< Data storage for the full sum QTF method + + ! Force arrays + REAL(SiKi) :: MnDriftForce(6) !< MnDrift force array. Constant for all time. First index is force component + REAL(SiKi), ALLOCATABLE :: NewmanAppForce(:,:) !< NewmanApp force array. Index 1: Time, Index 2: force component + REAL(SiKi), ALLOCATABLE :: DiffQTFForce(:,:) !< DiffQTF force array. Index 1: Time, Index 2: force component + REAL(SiKi), ALLOCATABLE :: SumQTFForce(:,:) !< SumQTF force array. Index 1: Time, Index 2: force component + + ! Temporary error trapping variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for holding the error status returned from a CALL statement + CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for holding the error message returned from a CALL statement + + + !> ### Subroutine contents + + !> Initialize Error handling variables + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + + !> Initialize the data storage + MnDriftData%DataIs3D = .FALSE. + MnDriftData%DataIs4D = .FALSE. + MnDriftData%Filename = '' + + NewmanAppData%DataIs3D = .FALSE. + NewmanAppData%DataIs4D = .FALSE. + NewmanAppData%Filename = '' + + DiffQTFData%DataIs3D = .FALSE. + DiffQTFData%DataIs4D = .FALSE. + DiffQTFData%Filename = '' + + SumQTFData%DataIs4D = .FALSE. + SumQTFData%Filename = '' + + + !> Initialize the NWTC Subroutine Library and display the information about this module. + + CALL NWTC_Init() ! WAMIT2_ProgDesc%Name, '('//WAMIT2_ProgDesc%Ver//','//WAMIT2_ProgDesc%Date//')', EchoLibVer = .FALSE. ) + + + + !----------------------------------------------------------------------------- + !> Before attempting to do any real calculations, we first check what was + !! passed in through _InitInp_ to make sure it makes sense. That routine will + !! then copy over the relevant information that should be kept in parameters + !! (_p_). + !! + !! _InitInp_ will also check the flags, existence of files, and set flags + !! accordingly. + !----------------------------------------------------------------------------- + + !------------------------------------------------------------------------------------------------------------- + !> 1. Check the data file related values (_MnDrift_, _MnDriftF_ etc). Also copy over important things from _InitInp_ to _p_ and _InitOut_. + + CALL CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + !------------------------------------------------------------------------------------------------------------- + !> 2. Now read in the data files and store the data and information about it using _Read_DataFile3D_ or + !! _Read_DataFile4D_. Flags should have been set in the _CheckInitInput_ subroutine to indicate + !! what type of data is going to be read in. The consistency of the WAMIT 2nd order data files is checked + !! during the reading in subroutines. + + !> If the MnDrift method will be used, read in the data for it. + IF ( p%MnDriftF ) THEN + IF ( MnDriftData%DataIs3D ) THEN + CALL Read_DataFile3D( TRIM(MnDriftData%Filename), MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSEIF ( MnDriftData%DataIs4D ) THEN + MnDriftData%Data4D%IsSumForce = .FALSE. + CALL Read_DataFile4D( TRIM(MnDriftData%Filename), MnDriftData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift method flags incorrectly set by '// & + 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> If the NewmanApp method will be used, read in the data for it. + IF ( p%NewmanAppF ) THEN + IF ( NewmanAppData%DataIs3D ) THEN + CALL Read_DataFile3D( TRIM(NewmanAppData%Filename), NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSEIF ( NewmanAppData%DataIs4D ) THEN + NewmanAppData%Data4D%IsSumForce = .FALSE. + CALL Read_DataFile4D( TRIM(NewmanAppData%Filename), NewmanAppData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp method flags incorrectly set by '// & + 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> If the DiffQTF method will be used, read in the data for it. This can only be 4D data even though DiffQTF can hold + !! 3D data. This was an intentional choice so that DiffQTFData could be passed to the MnDrift method (the first term + !! of the DiffQTF method equations is the MnDrift term). + IF ( p%DiffQTFF ) THEN + IF ( DiffQTFData%DataIs3D ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF method flags incorrectly set by '// & + 'CheckInitInput subroutine. 3D data cannot be used in the DiffQTF method.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + ELSEIF ( DiffQTFData%DataIs4D ) THEN + DiffQTFData%Data4D%IsSumForce = .FALSE. + CALL Read_DataFile4D( TRIM(DiffQTFData%Filename), DiffQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF method flags incorrectly set by '// & + 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> If the SumQTF method will be used, read in the data for it. This can only be 4D data (SumQTFData only holds 4D). + IF ( p%SumQTFF ) THEN + IF ( SumQTFData%DataIs4D ) THEN + SumQTFData%Data4D%IsSumForce = .TRUE. + CALL Read_DataFile4D( TRIM(SumQTFData%Filename), SumQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF method flags incorrectly set by '// & + 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + + !------------------------------------------------------------------------------------------------------------- + !> 3. Now check the data to ensure that all the dimensions that were requested acually exist in the file. At + !! this point, the MnDriftData and NewmanApp data will be either 3D or 4D, but not both. + !! + + !> Check the MnDrift data: check both in case we have already copied 4D data into the 3D. Will decide later which is used. + IF ( p%MnDriftF ) THEN + IF ( MnDriftData%DataIs3D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data3D%LoadComponents(I) ) ) & + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the MnDrift method.', ErrStat,ErrMsg,'WAMIT2_Init') + ENDDO + ELSE IF ( MnDriftData%DataIs4D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data4D%LoadComponents(I) ) )& + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the MnDrift method.', ErrStat,ErrMsg,'WAMIT2_Init') + ENDDO + ELSE ! We didn't find any data to use... + CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> Check the NewmanApp data: check both in case we have already copied 4D data into the 3D. Will decide later which is used. + IF ( p%NewmanAppF ) THEN + IF ( NewmanAppData%DataIs3D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%NewmanAppDims(I) ) THEN + IF ( .NOT. NewmanAppData%Data3D%LoadComponents(I) ) & + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the NewmanApp method.', ErrStat,ErrMsg,'WAMIT2_Init') + END IF + ENDDO + ELSE IF ( NewmanAppData%DataIs4D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%NewmanAppDims(I) ) THEN + IF ( .NOT. NewmanAppData%Data4D%LoadComponents(I) ) & + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the NewmanApp method.', ErrStat,ErrMsg,'WAMIT2_Init') + END IF + ENDDO + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> Check the DiffQTF data: Don't check the 3D data. We may have copied 4D into it for the MnDrift term. + IF ( p%DiffQTFF ) THEN + IF ( DiffQTFData%DataIs4D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%DiffQTFDims(I) ) THEN + IF ( .NOT. DiffQTFData%Data4D%LoadComponents(I) ) & + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the DiffQTF method.', ErrStat,ErrMsg,'WAMIT2_Init') + END IF + ENDDO + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> Check the SumQTF data + IF ( p%SumQTFF ) THEN + IF ( SumQTFData%DataIs4D ) THEN + ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file + DO I=1,6 + IF ( p%SumQTFDims(I) ) THEN + IF ( .NOT. SumQTFData%Data4D%LoadComponents(I) ) & + CALL SetErrStat( ErrID_Fatal, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the SumQTF method.', ErrStat,ErrMsg,'WAMIT2_Init') + END IF + ENDDO + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !------------------------------------------------------------------------------------------------------------- + !> 4. At this point, all the data from the WAMIT second order output files should be loaded. We can now proceed + !! to perform the calculations for each of the methods. For the call to the method, we pass the dataset + !! corresponding to each method. The calculation methods for MnDrift and NewmanApp can handle both 3D and 4D + !! data, so the entire MnDriftData and NewmanAppData sets are handed to the calculation subroutines. + !! + !! @note The frequency range and wave direction range present in the QTF information that was read in has not + !! been checked. The frequency range needed by the Newman approximation is different than that of the other + !! methods. Therefore the decision has been made to check and apply the frequency check and wave directionality + !! checks at the start of the calculation subroutine for each method. + !! + !! For the DiffQTF and SumQTF methods, only 4D data can be used in the calculations. Again, the entire dataset + !! for each is passed into the respective calculation subroutine. In the case of the DiffQTFData, only the 4D + !! data portion should be populated above. If 3D data is present in it, the subroutine will exit with a + !! warning about a programming error. For the SumQTF method, the data can only be 4D. + !! + !! @note The wamit2:mndrift_initcalc routine will be called from wamit2::diffqtf_initcalc. The first term of the + !! DiffQTF method is the MnDrift method. + !! + !! For the MnDrift and NewmanApp methods, it is possible to convert 4D data where the diagonal is complete but + !! off diagonal values are not. The data in this case will have to be ported over to a 3D storage. This will + !! be handled in the MnDrift_InitCalc and NewmanApp_InitCalc functions. + !! + !! @note The MnDrift and NewmanApp can use the 4D data if the diagonal is not complete, but the full QTF is. + !! This would only occur when the stepsize in \f$ \omega_1 \f$ and \f$ \omega_2 \f$ are not the same + !! resulting in no cases where \f$ \omega_1 == \omega_2 \f$. + + + + !> If the MnDrift method will be used, call the subroutine to calculate the force time series + IF ( p%MnDriftF ) THEN + + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( ' Calculating second order mean drift force.' ) + + CALL MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> If the NewmanApp method will be used, call the subroutine to calculate the force time series + IF ( p%NewmanAppF ) THEN + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( " Calculating second order difference-frequency force using the Newman's approximation." ) + + CALL NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + + !> If the DiffQTF method will be used, call the subroutine to calculate the force time series + !! Note that the MnDrift calculation is included. + IF ( p%DiffQTFF ) THEN + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( ' Calculating second order difference-frequency force using the full quadratic transfer function.' ) + + CALL DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !> If the SumQTF method will be used, call the subroutine to calculate the force time series + IF ( p%SumQTFF ) THEN + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( ' Calculating second order sum-frequency force using the full quadratic transfer function.' ) + + CALL SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + + !---------------------------------------------------------------------- + !> Copy output forces over to parameters as needed. + !---------------------------------------------------------------------- + + ! Initialize the second order force to zero. + p%WaveExctn2 = 0.0_SiKi + + + ! Difference method data. Only one difference method can be calculated at a time. + + IF ( p%MnDriftF ) THEN + + DO I=1,6 ! Loop through load components. Set ones that are calculated. + IF ( p%MnDriftDims(I) ) THEN + p%WaveExctn2(:,I) = MnDriftForce(I) + ENDIF + ENDDO + + ELSE IF ( p%NewmanAppF ) THEN + + DO I=1,6 ! Loop through load components. Set ones that are calculated. + IF ( p%NewmanAppDims(I) ) THEN + p%WaveExctn2(:,I) = NewmanAppForce(:,I) + ENDIF + ENDDO + + ELSE IF ( p%DiffQTFF ) THEN + + DO I=1,6 ! Loop through load components. Set ones that are calculated. + IF ( p%DiffQTFDims(I) ) THEN + p%WaveExctn2(:,I) = DiffQTFForce(:,I) + ENDIF + ENDDO + + ENDIF + + + ! Summation method + IF ( p%SumQTFF ) THEN + + DO I=1,6 ! Loop through load components. Set ones that are calculated. + IF ( p%SumQTFDims(I) ) THEN + ! Add the sum force to the difference force calculated above (if there was one). Loop through all timesteps. + DO J=1,InitInp%NStepWave + p%WaveExctn2(J,I) = p%WaveExctn2(J,I) + SumQTFForce(J,I) + ENDDO + ENDIF + ENDDO + + ENDIF + + + ! Deallocate the force arrays since we are done with them. Note that the MnDrift force array is + ! not deallocated since it is not time dependent. + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce) + IF (ALLOCATED(SumQTFForce)) DEALLOCATE(SumQTFForce) + + + + + !---------------------------------------------------------------------- + !> 5. Create the mesh used for exporting the 2nd order forces from the + !! WAMIT2_CalcOuput routine at each timestep. Also set the outputs + !! for each timestep. + !---------------------------------------------------------------------- + + ! Create the input and output meshes associated with lumped loads + CALL MeshCreate( BlankMesh = u%Mesh , & + IOS = COMPONENT_INPUT , & + Nnodes = 1 , & + ErrStat = ErrStatTmp , & + ErrMess = ErrMsgTmp , & + TranslationDisp = .TRUE. , & + Orientation = .TRUE. , & + TranslationVel = .TRUE. , & + RotationVel = .TRUE. , & + TranslationAcc = .FALSE. , & + RotationAcc = .FALSE.) + + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + ! Create the node on the mesh + CALL MeshPositionNode (u%Mesh, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, 1 ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + + CALL MeshCommit ( u%Mesh, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + CALL MeshCopy( SrcMesh=u%Mesh, DestMesh=y%Mesh, CtrlCode=MESH_SIBLING, IOS=COMPONENT_OUTPUT, & + ErrStat=ErrStatTmp, ErrMess=ErrMsgTmp, Force=.TRUE., Moment=.TRUE. ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + + + ! Initialize the outputs + CALL WMT2OUT_Init( InitInp, y, p, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + + !---------------------------------------------------------------------- + !> 6. Set zero values for unused outputs. This is mostly so that the + !! compiler does not complain. + !---------------------------------------------------------------------- + x%DummyContState = 0.0_SiKi + xd%DummyDiscState = 0.0_SiKi + z%DummyConstrState = 0.0_SiKi + m%LastIndWave = 1_IntKi + + OtherState%DummyOtherState = 0 + + ! Cleanup remaining stuff + CALL CleanUp + + RETURN + + CONTAINS + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine cleans up anything that is still allocated. + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE CleanUp() + + CALL Destroy_InitData3D( MnDriftData%Data3D ) + CALL Destroy_InitData4D( MnDriftData%Data4D ) + CALL Destroy_InitData3D( NewmanAppData%Data3D ) + CALL Destroy_InitData4D( NewmanAppData%Data4D ) + CALL Destroy_InitData3D( DiffQTFData%Data3D ) + CALL Destroy_InitData4D( DiffQTFData%Data4D ) + CALL Destroy_InitData4D( SumQTFData%Data4D ) + + END SUBROUTINE CleanUp + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine calculates the force time series using the MnDrift calculation. + !! The data is stored in either 3D or 4D arrays depending on the file type used. + !! At each step in the summation of the mth term, a call is made to the 3D or 4D interpolation algorithm to find the value of + !! \f$ F^-_k(\omega_m, \omega_n) \f$ corresponding to the \f$ Z(\omega_m) \f$ term in the complex wave amplitude, _WaveElevC_. + !! The limits of \f$ \omega_{lo-d} :math:`\le` \omega_m :math:`\le` \omega_{hi-d} \f$ are imposed during the summation with values + !! outside this range set to zero. + !! + !! For multi-directional waves where the equal energy discretization is used, each frequency has a single wave direction + !! associated with it. Since the mean drift force calculation only involves summing over terms involving only a single frequency + !! at a time, only a single wave direction is involved at each step. So, if all the diagonal elements of the 4D matrix where + !! \f$ \omega_1 = \omega_2 \f$ and \f$ \beta_1 = \beta_2 \f$ were present, it would be possible to simplify the 4D interpolation + !! required to two dimensional interpolation for this particular case. However, since the same interpolation routine is used for + !! all the 4D data handling, it is programatically simpler to use only one interpolation algorithm for the 4D data and incur a + !! slight penalty at the initialization step where this routine is called. Overall it is a small price to pay for maintainable + !! code. + !! + !! The single summation equation used here is given by + !! \f$ {F_{{ex}~k}^{{-}(2)}} = \Re \left( \sum\limits_{m=0}^{N/2} + !! {a_m} {a_m^*} F_k^{-}(\omega_m, \beta_m)\right) \cdot\Delta\omega \f$ + !! for \f$\quad k=1,2,\ldots,6, \f$ + !! + !! where \f$ k \f$ indicates the index to the load component, \f$ {F_{{ex}~k}^{{-}(2)}} \f$ is the resulting time + !! independent mean drift force, and \f$ a_m \f$ and \f$ a_m^* \f$ are the complex wave amplitude and its complex conjugate for + !! the \f$ m^{th} \f$ frequency. Note the lack of time dependence in this equation: the mean drift is the average drift + !! force over the entire simulation. Note also that \f$ F_k^{-} (\omega_m, \beta_m) \f$ is the dimensionalized real valued + !! diagonal of the QTF read from the WAMIT file and interpolated for the \f$ m^{th} \f$ wave frequency. Note that this is + !! is a numerical integral, so the \f$ \Delta\omega \f$ term is necessary. + !! + !! Since the frequency range of the QTF has not yet been checked, we will do that now. + !! + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrStat ) + + IMPLICIT NONE + + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(W2_DiffData_Type), INTENT(INOUT) :: MnDriftData !< Data storage for the MnDrift method. Set to INOUT in case we need to convert 4D to 3D + REAL(SiKi), INTENT( OUT) :: MnDriftForce(6) !< Force data. Index 1 is the force component. Constant for all time. + CHARACTER(*), INTENT( OUT) :: ErrMsg + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + REAL(SiKi) :: TmpReal1 !< Temporary real + REAL(SiKi) :: TmpReal2 !< Temporary real + LOGICAL :: TmpFlag !< Temporary logical flag + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + + ! Wave information and QTF temporary + COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF + COMPLEX(SiKi) :: aWaveElevC !< Wave elevation of current frequency component. NStepWave2 normalization is removed. + REAL(SiKi) :: Omega1 !< Wave frequency of this component + + ! Interpolation routine indices and value to search for, and smaller array to pass + INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms + INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms + REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset + REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset + COMPLEX(SiKi),ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) + COMPLEX(SiKi),ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) + + + ! Initialize a few things + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + MnDriftForce = 0.0_SiKi + + + !> 1. Check the data to see if low cutoff on the difference frequency is 0. If it is above zero, that implies no mean drift + !! term since \f$ \omega_1=\omega_2 \f$ + + IF ( InitInp%WvLowCOffD > 0.0_SiKi ) THEN + CALL SetErrStat( ErrID_Warn, ' WvLowCOffD > 0.0, so no mean drift term is calculated (the mean drift uses only the equal '//& + 'frequency terms of the QTF). Setting the mean drift force to 0.',ErrStat,ErrMsg,'MnDrift_InitCalc') + MnDriftForce = 0.0_SiKi + RETURN + ENDIF + + + + !> 2. Check the data to see if the wave frequencies are present in the QTF data. Since the mean drift term only uses + !! frequencies where \f$ \omega_1=\omega_2 \f$, the data read in from the files must contain the full range of frequencies + !! present in the waves. + + IF ( MnDriftData%DataIs3D ) THEN + + ! Check the low frequency cutoff + IF ( MINVAL( MnDriftData%Data3D%WvFreq1 ) > InitInp%WvLowCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data3D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( (MAXVAL(MnDriftData%Data3D%WvFreq1 ) < InitInp%WvHiCOffD) ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data3D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ELSE IF ( MnDriftData%DataIs4D ) THEN ! only check if not 3D data. If there is 3D data, we default to using it for calculations + + ! Check the low frequency cutoff + IF ( MINVAL( MnDriftData%Data4D%WvFreq1 ) > InitInp%WvLowCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data4D%WvFreq1)))// & + ' rad/s first wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOff.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + IF ( MINVAL( MnDriftData%Data4D%WvFreq2 ) > InitInp%WvLowCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data4D%WvFreq2)))// & + ' rad/s for second wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( (MAXVAL(MnDriftData%Data4D%WvFreq1) < InitInp%WvHiCOffD) ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data4D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + IF ( (MAXVAL(MnDriftData%Data4D%WvFreq2) < InitInp%WvHiCOffD) ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data4D%WvFreq1)))// & + ' rad/s second wave period) data in '//TRIM(MnDriftData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ELSE + ! This is a catastrophic issue. We should not have called this routine without data that is usable for the MnDrift calculation + CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + !> 3. Check the data to see if the wave directions are present. May need to adjust for the boundary at +/- PI + IF ( MnDriftData%DataIs3D ) THEN + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data3D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(MnDriftData%Data3D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'MnDrift_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data3D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(MnDriftData%Data3D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'MnDrift_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (minval(MnDriftData%data3d%WvDir1) > 150.0_SiKi) .OR. (maxval(MnDriftData%data3d%WvDir1) < -150.0_SiKi) .OR. & + (minval(MnDriftData%data3d%WvDir2) > 150.0_SiKi) .OR. (maxval(MnDriftData%data3d%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data3D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data3D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + + ENDIF + + ELSEIF ( MnDriftData%DataIs4D ) THEN + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data4D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(MnDriftData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'MnDrift_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data4D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(MnDriftData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'MnDrift_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (MINVAL(MnDriftData%Data4D%WvDir1) > 150.0_SiKi) .OR. (MAXVAL(MnDriftData%Data4D%WvDir1) < -150.0_SiKi) .OR. & + (MINVAL(MnDriftData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(MnDriftData%Data4D%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + ! --> FIXME: modify to allow shifting values by TwoPi before comparing + IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + + ENDIF + + ELSE + ! No data. This is a catastrophic issue. We should not have called this routine without data that is usable for the MnDrift calculation + CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + !> 4. Check the data to see if we need to convert to 3D arrays before continuing (4D is sparse in any dimension we want and + !! frequency diagonal is complete). Only check if we don't have 3D data. + + IF ( .NOT. MnDriftData%DataIs3D .AND. MnDriftData%Data4D%WvFreqDiagComplete ) THEN + TmpFlag = .FALSE. ! if this goes true, then we need to convert to 3D data + DO I=1,6 + IF ( p%MnDriftDims(I) ) THEN ! Flag indicating which dimension we are calculating for + IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) ) TmpFlag = .TRUE. + ENDIF + ENDDO + + ! If we need to create the 3D data set, then + CALL Copy_InitData4Dto3D( MnDriftData%Data4D, MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'MnDrift_InitCalc') + IF (ErrStat >= AbortErrLev) RETURN + + MnDriftData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. + + ENDIF + + + + !> 5. Now check to make sure we have data that will work. For either 3D or 4D data, it must not be sparse. + !! We simplified the 4D sparse case to 3D above if we could. To check this, we have to check the load + !! components that we will use. So, we will loop through them and set the TmpFlag to true if there is + !! a sparse matrix for one of them. + !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. + TmpFlag = .FALSE. + IF ( MnDriftData%DataIs3D ) THEN + DO I=1,6 + IF ( MnDriftData%Data3D%DataIsSparse(I) .AND. MnDriftData%Data3D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. + ENDDO + ELSE ! must be 4D -- we checked that we had something at the start of this routine. + DO I=1,6 + IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. + ENDDO + ENDIF + IF (TmpFlag) THEN + CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(MnDriftData%Filename)//' is too sparse '// & + 'for the interpolation routine used in the mean drift calculation. At some later point, we will allow for '// & + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'MnDrift_InitCalc') + RETURN + ENDIF + + + !> 5. Calculate the mean drift force + !! The single summation equation used here is given by + !! \f$ {F_{{ex}~k}^{{-}(2)}} = \Re \left( \sum\limits_{m=0}^{N/2} + !! {A_m} {A_m^*} F_k^{-}(\omega_m, \beta_m)\right) \cdot\Delta\omega \f$ + !! for \f$\quad k=1,2,\ldots,6, \f$ + + + ! Setup temporary arrays that we will be passing the data to the interpolation routines in. + IF (MnDriftData%DataIs3D) THEN + ALLOCATE( TmpData3D(MnDriftData%Data3D%NumWvFreq1, MnDriftData%Data3D%NumWvDir1,MnDriftData%Data3D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 3D QTF data.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ELSE + ALLOCATE( TmpData4D(MnDriftData%Data4D%NumWvFreq1,MnDriftData%Data4D%NumWvFreq2,MnDriftData%Data4D%NumWvDir1,MnDriftData%Data4D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & + ErrStat, ErrMsg, 'MnDrift_InitCalc') + ENDIF + + ! If something went wrong during allocation of the temporary arrays... + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Now loop through all the dimensions and perform the calculation + DO I=1,6 + + ! Set the MnDrift force to 0.0 (Even ones we don't calculate) + MnDriftForce(I) = 0.0_SiKi + + ! Only on the dimensions we requested + IF ( p%MnDriftDims(I) ) THEN + + ! Set an initial search index for the 3D and 4D array interpolation + LastIndex3 = (/0,0,0/) + LastIndex4 = (/0,0,0,0/) + + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + IF (MnDriftData%DataIs3D) THEN + TmpData3D = MnDriftData%Data3D%DataSet(:,:,:,I) + ELSE + TmpData4D = MnDriftData%Data4D%DataSet(:,:,:,:,I) + END IF + + + DO J=1,InitInp%NStepWave2 + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + + ! Calculate the frequency + Omega1 = J * InitInp%WaveDOmega + + + ! Only get a QTF value if within the range of frequencies we have wave amplitudes for (first order cutoffs). This + ! is done only for efficiency. + IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN + + ! Now get the QTF value that corresponds to this frequency and wavedirection pair. + IF ( MnDriftData%DataIs3D ) THEN + + ! Set the (omega1,beta1,beta2) point we are looking for. + Coord3 = (/ Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + + ! get the interpolated value for F(omega1,beta1,beta2) + CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, MnDriftData%Data3D%WvFreq1, & + MnDriftData%Data3D%WvDir1, MnDriftData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) + + ELSE + + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + + ! get the interpolated value for F(omega1,omega2,beta1,beta2) + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, MnDriftData%Data4D%WvFreq1, MnDriftData%Data4D%WvFreq2, & + MnDriftData%Data4D%WvDir1, MnDriftData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + + + ENDIF !QTF value find + + + ELSE ! outside the frequency range + + QTF_Value = CMPLX(0.0_SiKi,0.0_SiKi) + + ENDIF ! frequency check + + + ! Check and make sure nothing bombed in the interpolation that we need to be aware of + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'MnDrift_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the mean drift. + ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So + ! we throw the complex part out. + QTF_Value = CMPLX(REAL(QTF_Value),0.0_SiKi) + + + ! Now put it all together... note the frequency stepsize is multiplied after the summation + MnDriftForce(I) = MnDriftForce(I) + REAL(QTF_Value * aWaveElevC * CONJG(aWaveElevC)) !bjj: put QTF_Value first so that if it's zero, the rest gets set to zero (to hopefully avoid overflow issues) + + ENDDO + + + ENDIF ! Load component to calculate + + ENDDO + + + + ! Cleanup + + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + + END SUBROUTINE MnDrift_InitCalc + + + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine calculates the force time series using the NewmanApp calculation. + !! The data is stored in either 3D or 4D arrays depending on the file type used. + !! At each step in the summation of the mth term, a call is made to the 3D or 4D interpolation algorithm to find the value of + !! \f$ F^-_k(\omega_m, \omega_n) \f$ corresponding to the \f$ Z(\omega_m) \f$ term in the complex wave amplitude, _aWaveElevC_. + !! A combination of the limits of \f$ \max(\omega_{lo-d},\omega_{lo}) \le \omega_m \le \min(\omega_{hi-d},\omega_{hi}) \f$ are + !! imposed during the summation before the FFT and values outside this range are set to zero. + !! + !! For multi-directional waves where the equal energy discretization is used, each frequency has a single wave direction + !! associated with it. Since the Newman's approximation calculation only involves summing over terms involving only a single + !! frequency at a time, only a single wave direction is involved at each step. So, if all the diagonal elements of the 4D matrix + !! where \f$ \omega_1 = \omega_2 \f$ and \f$ \beta_1 = \beta_2 \f$ were present, it would be possible to simplify the 4D + !! interpolation required to two dimensional interpolation for this particular case. However, since the same interpolation + !! routine is used for all the 4D data handling, it is programatically simpler to use only one interpolation algorithm for the + !! 4D data and incur a slight penalty at the initialization step where this routine is called. Overall it is a small price to + !! pay for maintainable code. + !! + !! The single summation equation used here is Standing's version of Newman's equation (written in a slightly different form than + !! appears in Standing's paper, but mathematically equivalent). Standing's version differs sligthly from Newman's original + !! equation in that it allows for multidirectional waves, and does not require high frequency filtering afterwards. Our + !! mathematically equivalent equation to Standing's version of Newman's equation is given as, + !! \f$ {F_{{ex}~k}^{- (2)}} \approx + !! \left. \left[ abs \left( \sum\limits_{m=0}^{N/2} + !! {a_m} \sqrt{ F_k^{-}(\omega_m,\omega_m)} + !! \cdot \mathrm{e}^{i \omega_m t} \right) \right]^2 \right|_{F_{k}^{-}(\omega_m,\omega_m) > 0} + !! - \left. \left[ abs \left( \sum\limits_{m=0}^{N/2} + !! {a_m} \sqrt{ - F_k^{-}(\omega_m,\omega_m)} + !! \cdot \mathrm{e}^{i \omega_m t} \right) \right]^2 \right|_{F_{k}^{-}(\omega_m,\omega_m) < 0} \quad \f$ + !! for \f$ \quad k=1,2,\ldots,6, \f$ + !! + !! where \f$ k \f$ indicates the index to the load component, \f$ {F_{{ex}~k}^{{-}(2)}} \f$ is the resulting Newman's + !! approximation of the second order forces, and \f$ a_m \f$ is the complex wave amplitude for the \f$ m^{th} \f$ frequency. Note + !! that the two IFFTs cover different values of \f$ F_k^{-} \f$. Note also that \f$ F_k^{-} (\omega_m, \beta_m) \f$ is the + !! dimensionalized real valued diagonal of the QTF read from the WAMIT file and interpolated for the \f$ m^{th} \f$ wave frequency. + !! Note that this is an IFFT and not a numerical integral. + !! + !! For the Newman approximation, the limits used on the calculations are a little different than with the other methods. For + !! this method, the limits are imposed as the maximum of the low frequency limits, and the minimum of the high frequency limits. + !! + !! @note The inverse Fourier transform in each term is over data that is not conjugate symmetric (where the negative frequencies + !! are the complex conjugate of the positive frequencies). This means we cannot use the IFFTs in FFT_Mod. To get around + !! this, the SlowFT_cx2real routine was written. It evaluates the sum at each timestep. + !! + !! Since the frequency range of the QTF has not yet been checked, we will do that now. + !! + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg, ErrStat ) + + IMPLICIT NONE + + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(W2_DiffData_Type), INTENT(INOUT) :: NewmanAppData !< Data storage for the NewmanApp method. Set to INOUT in case we need to convert 4D to 3D + REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: NewmanAppForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. + CHARACTER(*), INTENT( OUT) :: ErrMsg + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + REAL(SiKi) :: TmpReal1 !< Temporary real + REAL(SiKi) :: TmpReal2 !< Temporary real + LOGICAL :: TmpFlag !< Temporary logical flag + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using + + + ! Wave information and QTF temporary + COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1C(:) !< First term in the newman calculation, complex frequency space. Current load dimension. + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2C(:) !< Second term in the newman calculation, complex frequency space. Current load dimension. + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1t(:) !< First term in the newman calculation, time domain. Current load dimension. + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2t(:) !< Second term in the newman calculation, time domain. Current load dimension. + COMPLEX(SiKi) :: aWaveElevC !< Wave elevation of current frequency component. NStepWave2 factor removed. + REAL(SiKi) :: Omega1 !< Wave frequency of this component + + ! Interpolation routine indices and value to search for, and smaller array to pass + INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms + INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms + REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset + REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset + COMPLEX(SiKi), ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) + COMPLEX(SiKi), ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) + + + ! Initialize a few things + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + + + + !> 1. Check the data to see if the wave frequencies are present in the QTF data. Since Newman's approximation only uses + !! frequencies where \f$ \omega_1=\omega_2 \f$, the data read in from the files must contain the full range of frequencies + !! present in the waves. + + IF ( NewmanAppData%DataIs3D ) THEN + + ! Check the low frequency cutoff + IF ( MINVAL( NewmanAppData%Data3D%WvFreq1 ) > InitInp%WvLowCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data3D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( MAXVAL(NewmanAppData%Data3D%WvFreq1 ) < InitInp%WvHiCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data3D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ELSE IF ( NewmanAppData%DataIs4D ) THEN ! only check if not 3D data. If there is 3D data, we default to using it for calculations + + ! Check the low frequency cutoff + IF ( MINVAL( NewmanAppData%Data4D%WvFreq1 ) > InitInp%WvLowCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data4D%WvFreq1)))// & + ' rad/s first wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + IF ( MINVAL( NewmanAppData%Data4D%WvFreq2 ) > InitInp%WvLowCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data4D%WvFreq2)))// & + ' rad/s for second wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( MAXVAL(NewmanAppData%Data4D%WvFreq1) < InitInp%WvHiCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data4D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + IF ( MAXVAL(NewmanAppData%Data4D%WvFreq2) < InitInp%WvHiCOff ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data4D%WvFreq1)))// & + ' rad/s second wave period) data in '//TRIM(NewmanAppData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOff.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ELSE + ! This is a catastrophic issue. We should not have called this routine without data that is usable for the NewmanApp calculation + CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + !> 2. Check the data to see if the wave directions are present. May need to adjust for the boundary at +/- PI + IF ( NewmanAppData%DataIs3D ) THEN + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data3D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(NewmanAppData%Data3D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data3D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(NewmanAppData%Data3D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (minval(NewmanAppData%data3d%WvDir1) > 150.0_SiKi) .OR. (maxval(NewmanAppData%data3d%WvDir1) < -150.0_SiKi) .OR. & + (minval(NewmanAppData%data3d%WvDir2) > 150.0_SiKi) .OR. (maxval(NewmanAppData%data3d%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data3D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data3D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + + ENDIF + + ELSEIF ( NewmanAppData%DataIs4D ) THEN + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data4D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(NewmanAppData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data4D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(NewmanAppData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'NewmanApp_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (MINVAL(NewmanAppData%Data4D%WvDir1) > 150.0_SiKi) .OR. (MAXVAL(NewmanAppData%Data4D%WvDir1) < -150.0_SiKi) .OR. & + (MINVAL(NewmanAppData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(NewmanAppData%Data4D%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + ! --> FIXME: modify to allow shifting values by TwoPi before comparing + IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + + ENDIF + + ELSE + ! No data. This is a catastrophic issue. We should not have called this routine without data that is usable for the NewmanApp calculation + CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + !> 3. Check the data to see if we need to convert to 3D arrays before continuing (4D is sparse in any dimension we want and + !! frequency diagonal is complete). Only check if we don't have 3D data. + + IF ( .NOT. NewmanAppData%DataIs3D .AND. NewmanAppData%Data4D%WvFreqDiagComplete ) THEN + TmpFlag = .FALSE. ! if this goes true, then we need to convert to 3D data + DO I=1,6 + IF ( p%NewmanAppDims(I) ) THEN ! Flag indicating which dimension we are calculating for + IF ( NewmanAppData%Data4D%DataIsSparse(I) .AND. NewmanAppData%Data4D%LoadComponents(I) ) TmpFlag = .TRUE. + ENDIF + ENDDO + + ! If we need to create the 3D data set, then + CALL Copy_InitData4Dto3D( NewmanAppData%Data4D, NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF (ErrStat >= AbortErrLev) RETURN + + NewmanAppData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. + + ENDIF + + + + !> 4. Now check to make sure we have data that will work. For either 3D or 4D data, it must not be sparse. + !! We simplified the 4D sparse case to 3D above if we could. To check this, we have to check the load + !! components that we will use. So, we will loop through them and set the TmpFlag to true if there is + !! a sparse matrix for one of them. + !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. + TmpFlag = .FALSE. + IF ( NewmanAppData%DataIs3D ) THEN + DO I=1,6 + IF ( NewmanAppData%Data3D%DataIsSparse(I) .AND. NewmanAppData%Data3D%LoadComponents(I) .AND. p%NewmanAppDims(I) ) TmpFlag = .TRUE. + ENDDO + ELSE ! must be 4D -- we checked that we had something at the start of this routine. + DO I=1,6 + IF ( NewmanAppData%Data4D%DataIsSparse(I) .AND. NewmanAppData%Data4D%LoadComponents(I) .AND. p%NewmanAppDims(I) ) TmpFlag = .TRUE. + ENDDO + ENDIF + IF (TmpFlag) THEN + CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(NewmanAppData%Filename)//' is too sparse '// & + 'for the interpolation routine used in the Newman approximation calculation. At some later point, we will allow for '// & + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + RETURN + ENDIF + + + !> 5. Calculate the Newman's approximation for the second order forces + !! The single summation equation used here is given by + !! \f$ {F_{{ex}~k}^{- (2)}} \approx + !! \left. \left| \sum\limits_{m=0}^{N/2} + !! {a_m} \sqrt{ F_k^{-}(\omega_m,\omega_m)} + !! \cdot \mathrm{e}^{i \omega_m t} \right|^2 \right|_{F_{k}^{-}(\omega_m,\omega_m) > 0} + !! - \left. \left| \sum\limits_{m=0}^{N/2} + !! {a_m} \sqrt{ - F_k^{-}(\omega_m,\omega_m)} + !! \cdot \mathrm{e}^{i \omega_m t} \right|^2 \right|_{F_{k}^{-}(\omega_m,\omega_m) < 0} \quad \f$ + !! for \f$ \quad k=1,2,\ldots,6, \f$ + + + ! Setup temporary arrays that we will be passing the data to the interpolation routines in. + IF (NewmanAppData%DataIs3D) THEN + ALLOCATE( TmpData3D(NewmanAppData%Data3D%NumWvFreq1, NewmanAppData%Data3D%NumWvDir1,NewmanAppData%Data3D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 3D QTF data.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ELSE + ALLOCATE( TmpData4D(NewmanAppData%Data4D%NumWvFreq1,NewmanAppData%Data4D%NumWvFreq1,NewmanAppData%Data4D%NumWvDir1,NewmanAppData%Data4D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & + ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ENDIF + + + ! Setup the arrays holding the Newman terms, both the complex frequency domain and real time domain pieces + ALLOCATE( NewmanTerm1t( 0:InitInp%NStepWave ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the first term of the Newmans '// & + 'approximation in the time domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ALLOCATE( NewmanTerm2t( 0:InitInp%NStepWave ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & + 'approximation in the time domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ALLOCATE( NewmanTerm1C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the first term of the Newmans '// & + 'approximation in the frequency domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ALLOCATE( NewmanTerm2C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & + 'approximation in the frequency domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ALLOCATE( NewmanAppForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the resulting Newmans '// & + 'approximation of the 2nd order force.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + + + + ! If something went wrong during allocation of the temporary arrays... + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Set the resulting force to zero. Will calculate for the dimensions requested. + NewmanAppForce = 0.0_SiKi + + + ! Initialize the FFT library + CALL InitCFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) ! Complex result FFT initialize + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + END IF + + + + ! Now loop through all the dimensions and perform the calculation + DO I=1,6 + + ! set zero frequency term to zero + NewmanTerm1C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm2C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) + + ! Only on the dimensions we requested + IF ( p%NewmanAppDims(I) ) THEN + + ! Set an initial search index for the 3D and 4D array interpolation + LastIndex3 = (/0,0,0/) + LastIndex4 = (/0,0,0,0/) + + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + IF (NewmanAppData%DataIs3D) THEN + TmpData3D = NewmanAppData%Data3D%DataSet(:,:,:,I) + ELSE + TmpData4D = NewmanAppData%Data4D%DataSet(:,:,:,:,I) + END IF + + + DO J=1,InitInp%NStepWave2 + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 so that the wave amplitude is of the same form as the paper. + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + ! Calculate the frequency + Omega1 = J * InitInp%WaveDOmega + + + ! Only get a QTF value if within the range of frequencies between the cutoffs for the difference frequency + IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN + + ! Now get the QTF value that corresponds to this frequency and wavedirection pair. + IF ( NewmanAppData%DataIs3D ) THEN + + ! Set the (omega1,beta1,beta2) point we are looking for. + Coord3 = (/ Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + + ! get the interpolated value for F(omega1,beta1,beta2) + CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, NewmanAppData%Data3D%WvFreq1, & + NewmanAppData%Data3D%WvDir1, NewmanAppData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) + + ELSE + + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + + ! get the interpolated value for F(omega1,omega2,beta1,beta2) + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, NewmanAppData%Data4D%WvFreq1, NewmanAppData%Data4D%WvFreq2, & + NewmanAppData%Data4D%WvDir1, NewmanAppData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + + + ENDIF !QTF value find + + + ELSE ! outside the frequency range + + QTF_Value = CMPLX(0.0_SiKi,0.0_SiKi) + + ENDIF ! frequency check + + + + ! Check and make sure nothing bombed in the interpolation that we need to be aware of + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF + + + + ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. + ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So + ! we throw the complex part out. + QTF_Value = CMPLX(REAL(QTF_Value),0.0_SiKi) + + + ! Now we place these results into the arrays + IF (REAL(QTF_Value) > 0.0_SiKi) THEN + + NewmanTerm1C(J) = aWaveElevC * (QTF_Value)**0.5_SiKi + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + + ELSE IF (REAL(QTF_Value) < 0.0_SiKi) THEN + + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm2C(J) = aWaveElevC * (-QTF_Value)**0.5_SiKi + + ELSE ! at 0 + + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + + ENDIF + + + + ENDDO + + ! Now we apply the FFT to the first piece. + CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + END IF + + ! Now we apply the FFT to the second piece. + CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Now square the real part of the resulting time domain pieces and add them together to get the final force time series. + DO J=0,InitInp%NStepWave-1 + NewmanAppForce(J,I) = (abs(NewmanTerm1t(J)))**2 - (abs(NewmanTerm2t(J)))**2 + ENDDO + + ! Copy the last first term to the last so that it is cyclic + NewmanAppForce(InitInp%NStepWave,I) = NewmanAppForce(0,I) + + ENDIF ! Load component to calculate + + ENDDO + + + ! Done with the FFT library routines, so end them. + CALL ExitCFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'NewmanApp_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + END IF + + + ! Cleanup + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + + + + END SUBROUTINE NewmanApp_InitCalc + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine calculates the force time series using the full DiffQTF calculation. + !! The data is stored in a 4D array. A 3D array also exists in the dataset and may be used by the MnDrift calculation when it + !! is called from here. + !! At each step in the summation of the mth term, a call is made to the 4D interpolation algorithm to find the value of + !! \f$ F^-_k(\omega_m, \omega_n, \beta_1, \beta_2) \f$ corresponding to the \f$ Z(\omega_m) \f$ term in the complex wave + !! amplitude, _aWaveElevC_. A combination of the limits of \f$ \omega_{lo-d} \le \omega_\mu \le \omega_{hi-d} \f$ are + !! imposed during the summation before the FFT and values outside this range are set to zero. \f$ \omega_{\mu^-} \f$ is the + !! difference frequency. + !! + !! For multi-directional waves where the equal energy discretization is used, each frequency has a single wave direction + !! associated with it. In the full QTF calculation, the combination of the wave frequencies and their associated wave + !! directions are used. + !! + !! The single summation equation used here is given by + !! \f$ {F_{{ex}~k}^{(-)(2)}} = \Re \left( + !! \sum\limits_{m=0}^{N/2} a_m a_m^* F_k^{-}(\omega_m,\omega_m) + + !! 2 \cdot \sum\limits_{\mu^{-}=1}^{N/2-1} H_{\mu^{-}} \mathrm{e}^{i(\omega_{\mu^{-}})t} \right)\qquad \f$, + !! for \f$ \qquad k=1,2,\ldots,6 \qquad\f$ + !! where \f$ \qquad + !! H_{\mu^{-}} = \frac{1}{2} \sum\limits_{n=0}^{N/2-\mu^{-}} A_{\mu^{-}+n} A_n^* F_k^{-}(\omega_{\mu^{-}+n},\omega_n), \qquad \f$ + !! for \f$ \qquad\quad 1\le\mu^{-}\le N-1 \f$. + !! + !! Note that \f$ k \f$ indicates the index to the load component, \f$ {F_{{ex}~k}^{{-}(2)}} \f$ is the resulting second order + !! force, and \f$ a_m \f$ and \f$ a_m^* \f$ is the complex wave amplitude and its conjugate for the \f$ m^{th} \f$ frequency. + !! Note also that \f$ F_k^{-} (\omega_m, \omega_n, \beta_m, \beta_n) \f$ is the dimensionalized the QTF value read from the + !! WAMIT file and interpolated for the \f$ m^{th} \f$ wave frequency. The value of \f$ \mu^{-}=m-n \f$, the difference index. + !! + !! The first term in this equation is the MnDrift force, so we will call that routine to get it. The second term is an IFFT + !! of the summation of \f$ H_{\mu^{-}} \f$. The limits that are imposed on this equation are the WvLowCOffD and WvHiCOffD + !! values read in from the input file. These limits are placed on \f$ \mu \f$ in the second term of the equation. + !! + !! Since the frequency range of the QTF has not yet been checked, we will do that now as well. + !! + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrStat ) + + IMPLICIT NONE + + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(W2_DiffData_Type), INTENT(INOUT) :: DiffQTFData !< Data storage for the DiffQTF method. Set to INOUT in case we need to convert 4D to 3D + REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: DiffQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. + CHARACTER(*), INTENT( OUT) :: ErrMsg + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + REAL(SiKi) :: TmpReal1 !< Temporary real + REAL(SiKi) :: TmpReal2 !< Temporary real + LOGICAL :: TmpFlag !< Temporary logical flag + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using + + + ! Wave information and QTF temporary + COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF + COMPLEX(SiKi), ALLOCATABLE :: TmpComplexArr(:) !< Temporary complex array for frequency domain of one complete load component + COMPLEX(SiKi) :: TmpHMinusC !< Temporary variable for holding the current value of \f$ H^- \f$ + COMPLEX(SiKi) :: aWaveElevC1 !< Wave elevation of the first frequency component. NStepWave2 factor removed. + COMPLEX(SiKi) :: aWaveElevC2 !< Wave elevation of the second frequency component. NStepWave2 factor removed. + REAL(SiKi) :: OmegaDiff !< Wave difference frequency + REAL(SiKi), ALLOCATABLE :: TmpDiffQTFForce(:) !< The resulting diffQTF force for this load component + REAL(SiKi) :: Omega1 !< First wave frequency + REAL(SiKi) :: Omega2 !< Second wave frequency + REAL(SiKi) :: MnDriftForce(6) !< Mean drift force (first term). MnDrift_InitCalc routine will return this. + + ! Interpolation routine indices and value to search for, and smaller array to pass + INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq + REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset. First wave freq. + COMPLEX(SiKi), ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) + + + ! Initialize a few things + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + + + !> 1. Check the data to see if the wave frequencies are present in the QTF data. + + IF ( DiffQTFData%DataIs4D ) THEN ! We must have a 4D data set + + ! Check the low frequency cutoff + IF ( MINVAL( DiffQTFData%Data4D%WvFreq1 ) > InitInp%WvLowCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(DiffQTFData%Data4D%WvFreq1)))// & + ' rad/s first wave period) data in '//TRIM(DiffQTFData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffD.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + IF ( MINVAL( DiffQTFData%Data4D%WvFreq2 ) > InitInp%WvLowCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(DiffQTFData%Data4D%WvFreq2)))// & + ' rad/s for second wave period) data in '//TRIM(DiffQTFData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffD.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( MAXVAL(DiffQTFData%Data4D%WvFreq1) < InitInp%WvHiCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(DiffQTFData%Data4D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(DiffQTFData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffD.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + IF ( MAXVAL(DiffQTFData%Data4D%WvFreq2) < InitInp%WvHiCOffD ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(DiffQTFData%Data4D%WvFreq1)))// & + ' rad/s second wave period) data in '//TRIM(DiffQTFData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffD.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + + ELSE + ! This is a catastrophic issue. We should not have called this routine without data that is usable for the DiffQTF calculation + CALL SetErrStat( ErrID_Fatal, ' The full Difference QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (DiffQTFData%Data4D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(DiffQTFData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(DiffQTFData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (DiffQTFData%Data4D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(DiffQTFData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(DiffQTFData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (MINVAL(DiffQTFData%Data4D%WvDir1) > 150.0_SiKi) .OR. (MAXVAL(DiffQTFData%Data4D%WvDir1) < -150.0_SiKi) .OR. & + (MINVAL(DiffQTFData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(DiffQTFData%Data4D%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + ! --> FIXME: modify to allow shifting values by TwoPi before comparing + IF ( InitInp%WaveDirMin < MINVAL(DiffQTFData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(DiffQTFData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ENDIF + + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + + !> 4. Now check to make sure we have data that will work. For the 4D data, it must not be sparse. + !! To check this, we have to check the load components that we will use. So, we will loop through them + !! and set the TmpFlag to true if there is a sparse matrix for one of them. + !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implemented. + TmpFlag = .FALSE. + DO I=1,6 + IF ( DiffQTFData%Data4D%DataIsSparse(I) .AND. DiffQTFData%Data4D%LoadComponents(I) .AND. p%DiffQTFDims(I) ) TmpFlag = .TRUE. + ENDDO + IF (TmpFlag) THEN + CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(DiffQTFData%Filename)//' is too sparse '// & + 'for the interpolation routine used in the full Difference QTF calculation. At some later point, we will allow for '// & + 'sparse data when a different interpolation routine is implemented.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + RETURN + ENDIF + + + !> 5. Calculate the second order forces + !! The single summation equation used here is given by + + + ! Setup temporary arrays that we will be passing the data to the interpolation routines in. + ALLOCATE( TmpData4D(DiffQTFData%Data4D%NumWvFreq1,DiffQTFData%Data4D%NumWvFreq1,DiffQTFData%Data4D%NumWvDir1,DiffQTFData%Data4D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & + ErrStat, ErrMsg, 'DiffQTF_InitCalc') + + + ! Setup the arrays holding the DiffQTF terms, both the complex frequency domain and real time domain pieces + ALLOCATE( TmpDiffQTFForce( 0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & + 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ALLOCATE( TmpComplexArr( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ALLOCATE( DiffQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & + 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + + ! If something went wrong during allocation of the temporary arrays... + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Set the resulting force to zero. Will calculate for the dimensions requested. + DiffQTFForce = 0.0_SiKi + + + ! Initialize the FFT library. Do not apply normalization. + CALL InitFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + END IF + + + + + ! Before we continue, we will get the MnDriftForce results. + ! --> Note that we can pass the DiffQTFData directly since we are using the same type for both + CALL MnDrift_InitCalc( InitInp, p, DiffQTFData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'DiffQTF_InitCalc' ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Make sure we have a value for the mean drift for each of the dimensions we were requested to calculate. To + ! find out we will just check the status of the flags for each dimension in the MnDriftDims against the ones + ! for the DiffQTFDims + DO I=1,6 + IF ( p%DiffQTFDims(I) .AND. (.NOT. p%MnDriftDims(I)) ) & + CALL SetErrStat( ErrID_Fatal,' The DiffQTF method requires the use of the MnDrift method for the first term. '// & + 'Something went wrong and the MnDrift method returned a different number of load components.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + ENDDO + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + ENDIF + + + + ! Now loop through all the dimensions and perform the calculation + DO I=1,6 + + ! Only on the dimensions we requested + IF ( p%DiffQTFDims(I) ) THEN + + + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) + + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + TmpData4D = DiffQTFData%Data4D%DataSet(:,:,:,:,I) + + ! Initialize the temporary array to zero. + TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi) + + + ! Outer loop to create the TmpComplexArr + DO J=1,InitInp%NStepWave2-1 + + ! Calculate the frequency -- This is the difference frequency. + OmegaDiff = J * InitInp%WaveDOmega + + + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaDiff >= InitInp%WvLowCOffD) .AND. (OmegaDiff <= InitInp%WvHiCOffD) ) THEN + + ! Set the \f$ H^- \f$ term to zero before we start + TmpHMinusC = CMPLX(0.0_SiKi,0.0_SiKi) + + + ! Do the sum over H^- + DO K=1,InitInp%NStepWave2-J ! note the funny upper limit. This is because we are doing a summation on a triangular area. + + ! set the two frequencies that the difference frequency comes from + Omega1 = (J + K) * InitInp%WaveDOmega ! the mth frequency -- \mu^- + n = m + Omega2 = K * InitInp%WaveDOmega ! the nth frequency + + + ! Find the Wave amplitudes 1 and 2 + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K)) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K)) / InitInp%NStepWave2 + + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ Omega1, Omega2, InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) + + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & + DiffQTFData%Data4D%WvDir1, DiffQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'DiffQTF_InitCalc') + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Calculate this value and add it to what we have so far. + TmpHMinusC = TmpHMinusC + aWaveElevC1 * CONJG(aWaveElevC2) * QTF_Value + + ENDDO + + ! Copy this value difference frequency information over to the array we will take the IFFT. Divide + ! by two for the single sided FFT given in the documentation. + TmpComplexArr(J) = TmpHMinusC / 2.0_SiKi + + ELSE ! outside the frequency range, so + + TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi) + + ENDIF ! frequency check + + + ENDDO + + ! Now we apply the FFT to the result of the sum + CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & + ErrStat,ErrMsg,'DiffQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + END IF + + + ! Now we multiply the result by 2 and save it to the DiffQTFForce array and add the MnDrift term + DO K=0,InitInp%NStepWave-1 ! bjj: added the "-1" here because TmpDiffQTFForce(InitInp%NStepWave) is not set and DiffQTFForce(InitInp%NStepWave,I) gets overwritten next, anyway + DiffQTFForce(K,I) = 2.0_SiKi * TmpDiffQTFForce(K) + MnDriftForce(I) + ENDDO + + ! Copy the last first term to the last so that it is cyclic + DiffQTFForce(InitInp%NStepWave,I) = DiffQTFForce(0,I) + + ENDIF ! Load component to calculate + + ENDDO + + + + ! Done with the FFT library routines, so end them. + CALL ExitFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'DiffQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + END IF + + + ! Cleanup + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + + + END SUBROUTINE DiffQTF_InitCalc + + + + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine calculates the force time series using the full SumQTF calculation. The data is stored in a 4D array. + !! At each step in the summation of the mth term, a call is made to the 4D interpolation algorithm to find the value of + !! \f$ F^-_k(\omega_m, \omega_n, \beta_1, \beta_2) \f$ corresponding to the \f$ Z(\omega_m) \f$ term in the complex wave + !! amplitude, _WaveElevC_. A combination of the limits of \f$ \omega_{lo-s} \le \omega_\mu \le \omega_{hi-s} \f$ are + !! imposed during the summation before the FFT and values outside this range are set to zero. + !! + !! For multi-directional waves where the equal energy discretization is used, each frequency has a single wave direction + !! associated with it. In the full QTF calculation, the combination of the wave frequencies and their associated wave + !! directions are used. + !! + !! The single summation equation used here is given by + !! \f$ {F_{{ex}~k}^{(+)(2)}} = \Re \left( + !! \sum\limits_{m=1}^{\lfloor N/4 \rfloor} A_m A_m F_k^{+}(\omega_m,\omega_m) \mathrm{e}^{2\cdot i\omega_m t} + + !! 2 \sum\limits_{\mu^{+}=2}^{N/2} H_{\mu^{+}}\mathrm{e}^{i (\omega_{\mu^{+}-1})t}\right) ,\quad \f$ + !! for \f$\quad k=1,2,\ldots,6 \qquad\f$ + !! + !! where \f$ + !! H_{\mu^{+}} = \sum\limits_{n=1}^{\left\lfloor\frac{\mu^{+}-n}{2}\right\rfloor} + !! A_n A_{\mu^{+}-n} F_k^{+}(\omega_n,\omega_{\mu^{+}-1}),\f$ + !! for \f$ 2\leq \mu^{+}\leq N/2+1 \f$ + !! + !! and \f$ + !! H_{\mu^{+}} = \displaystyle\sum\limits_{n=\mu^{+}-N}^{\left\lfloor\frac{\mu^{+}-n}{2}\right\rfloor} + !! A_n A_{\mu^{+}-n} F_k^{+}(\omega_n,\omega_{\mu^{+}-1}),\f$ + !! for \f$ N/2+2\leq\mu^{+}\leq N \f$ + !! + !! where \f$ \mu^{+} = m + n \f$, \f$ \lfloor x \rfloor \f$ represents the floor function given by + !! \f$ \lfloor x \rfloor \equiv \max \left\{ m \in \mathbb{Z} \middle| m\leq x \right\}.\f$ + !! + !! Note that \f$ k \f$ indicates the index to the load component, \f$ {F_{{ex}~k}^{{+}(2)}} \f$ is the resulting second order + !! force, and \f$ A_m \f$ is the complex wave amplitude for the \f$ m^{th} \f$ frequency. + !! Note also that \f$ F_k^{+} (\omega_m, \omega_n, \beta_m, \beta_n) \f$ is the dimensionalized QTF value read from the + !! WAMIT file and interpolated for the \f$ m^{th} \f$ wave frequency. + !! + !! The first term in this equation is an IFFT of the diagonal elements where \f$ \omega_m = \omega_n \f$. The second term is + !! an IFFT of the summation of \f$ H_{\mu^{+}} \f$ term. The limits that are imposed on this equation are the WvLowCOffS and + !! WvHiCOffS values read in from the input file. These limits are placed on \f$ \mu^+ \f$ in the both terms of the equation. + !! + !! The second term is an IFFT over \f$ N \f$ terms instead of the usual \f$ N/2 \f$ terms. This results in \f$ 2N \f$ timesteps + !! with a timestep of \f$ \Delta t / 2 \f$. However, since we only report at \f$ \Delta t \f$ timestep intervals, the highest + !! reportable frequency is the Nyquist frequency of \f$ \pi / \Delta t \f$, so anything above that will be lost. Considering + !! this, there is no reason to calculate any summation frequencies above the Nyquist frequency. So we will change the equation + !! to the following form: + !! \f$ {F_{{ex}~k}^{(+)(2)}} = \Re \left( + !! \sum\limits_{m=1}^{\lfloor N/4 \rfloor} A_m A_m F_k^{+}(\omega_m,\omega_m) \mathrm{e}^{2\cdot i\omega_m t} + + !! 2 \sum\limits_{\mu^{+}=2}^{N/2} H_{\mu^{+}}\mathrm{e}^{i (\omega_{\mu^{+}-1})t}\right), \f$ + !! for \f$ k=1,2,\ldots,6 \f$ + !! + !! where \f$ + !! H_{\mu^{+}} = \sum\limits_{n=1}^{\left\lfloor\frac{\mu^{+}-n}{2}\right\rfloor} + !! A_n A_{\mu^{+}-n} F_k^{+}(\omega_n,\omega_{\mu^{+}-1}), \f$ + !! for \f$ 2\le \mu^{+}\le N/2 \f$ + !! + !! + !! + !! + !! Before doing all the calculations, we will first check the frequency range of the QTF and check if we will be truncating data + !! if the cutoff for the highest sum frequency, _WvHiCOffS_ is above the Nyquist frequency. + !! + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ) + + IMPLICIT NONE + + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(W2_SumData_Type), INTENT(INOUT) :: SumQTFData !< Data storage for the SumQTF method. Set to INOUT in case we need to convert 4D to 3D + REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: SumQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. + CHARACTER(*), INTENT( OUT) :: ErrMsg + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + LOGICAL :: TmpFlag !< Temporary logical flag + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using. For the first term in the equation. + + + ! Wave information and QTF temporary + COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF + COMPLEX(SiKi), ALLOCATABLE :: Term1ArrayC(:) !< Temporary complex array for frequency domain of one load component. For first term. + COMPLEX(SiKi), ALLOCATABLE :: Term2ArrayC(:) !< Temporary complex array for frequency domain of one load component. For second term. + REAL(SiKi), ALLOCATABLE :: Term1Array(:) !< Temporary complex array for time domain of one load component. For first term. + REAL(SiKi), ALLOCATABLE :: Term2Array(:) !< Temporary complex array for time domain of one load component. For second term. + COMPLEX(SiKi) :: TmpHPlusC !< Temporary variable for holding the current value of \f$ H^+ \f$ + COMPLEX(SiKi) :: aWaveElevC1 !< Wave elevation of the first frequency component. NStepWave2 factor removed. + COMPLEX(SiKi) :: aWaveElevC2 !< Wave elevation of the second frequency component. NStepWave2 factor removed. + REAL(SiKi) :: OmegaSum !< Wave difference frequency + REAL(SiKi) :: Omega1 !< First wave frequency + REAL(SiKi) :: Omega2 !< Second wave frequency + + ! Interpolation routine indices and value to search for, and smaller array to pass + INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq + REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset. First wave freq. + COMPLEX(SiKi), ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) + + + ! Initialize a few things + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + + + !> 1. Check the data to see if the wave frequencies are present in the QTF data. + + IF ( SumQTFData%DataIs4D ) THEN ! We must have a 4D data set + + ! Check the low frequency cutoff + IF ( MINVAL( SumQTFData%Data4D%WvFreq1 ) > InitInp%WvLowCOffS ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(SumQTFData%Data4D%WvFreq1)))// & + ' rad/s first wave period) data in '//TRIM(SumQTFData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffS.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + IF ( MINVAL( SumQTFData%Data4D%WvFreq2 ) > InitInp%WvLowCOffS ) THEN + CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(SumQTFData%Data4D%WvFreq2)))// & + ' rad/s for second wave period) data in '//TRIM(SumQTFData%Filename)// & + ' is above the low frequency cutoff set by WvLowCOffS.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + + ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency + ! cutoff is typically too high for this in most cases. + IF ( MAXVAL(SumQTFData%Data4D%WvFreq1) < InitInp%WvHiCOffS ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(SumQTFData%Data4D%WvFreq1)))// & + ' rad/s for first wave period) data in '//TRIM(SumQTFData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffS.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + IF ( MAXVAL(SumQTFData%Data4D%WvFreq2) < InitInp%WvHiCOffS ) THEN + CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(SumQTFData%Data4D%WvFreq1)))// & + ' rad/s second wave period) data in '//TRIM(SumQTFData%Filename)// & + ' is below the high frequency cutoff set by WvHiCOffS.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + + ELSE + ! This is a catastrophic issue. We should not have called this routine without data that is usable for the SumQTF calculation + CALL SetErrStat( ErrID_Fatal, ' The full Sum QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + + ! If we are using multidirectional waves, then we should have more than 1 wave direction in the WAMIT file. + IF ( InitInp%WaveMultiDir .AND. (SumQTFData%Data4D%NumWvDir1 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(SumQTFData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(SumQTFData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ELSE IF ( InitInp%WaveMultiDir .AND. (SumQTFData%Data4D%NumWvDir2 == 1) ) THEN + CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(SumQTFData%Filename)//' only contains one wave '// & + 'direction at '//TRIM(Num2LStr(SumQTFData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & + 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + ELSE + + ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For + ! now (since time is limited) we will issue a warning if any of the wave directions for multidirectional waves + ! or data from the WAMIT file for the wavedirections is close to the +/-pi boundary (>150 degrees, <-150 degrees), + ! we will issue a warning. + IF ( (InitInp%WaveDirMin > 150.0_SiKi) .OR. (InitInp%WaveDirMax < -150.0_SiKi) .OR. & + (MINVAL(SumQTFData%Data4D%WvDir1) > 150.0_SiKi) .OR. (MAXVAL(SumQTFData%Data4D%WvDir1) < -150.0_SiKi) .OR. & + (MINVAL(SumQTFData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(SumQTFData%Data4D%WvDir2) < -150.0_SiKi) ) THEN + CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & + 'direction of interest is near the +/- 180 direction. This is a known issue with '// & + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'SumQTF_InitCalc') + ENDIF + + ! Now check the limits for the first wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + ! --> FIXME: modify to allow shifting values by TwoPi before comparing + IF ( InitInp%WaveDirMin < MINVAL(SumQTFData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'SumQTF_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir1) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & + ErrStat, ErrMsg, 'SumQTF_InitCalc') + ENDIF + + + ! Now check the limits for the second wave direction + ! --> FIXME: sometime fix this to handle the above case. See Known Issue #1 at top of file. + IF ( InitInp%WaveDirMin < MINVAL(SumQTFData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& + 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'SumQTF_InitCalc') + ENDIF + IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir2) ) THEN + CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& + 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & + ErrStat, ErrMsg, 'SumQTF_InitCalc') + ENDIF + + ENDIF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + + + !> 4. Now check to make sure we have data that will work. For the 4D data, it must not be sparse. + !! To check this, we have to check the load components that we will use. So, we will loop through them + !! and set the TmpFlag to true if there is a sparse matrix for one of them. + !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. + TmpFlag = .FALSE. + DO I=1,6 + IF ( SumQTFData%Data4D%DataIsSparse(I) .AND. SumQTFData%Data4D%LoadComponents(I) .AND. p%SumQTFDims(I) ) TmpFlag = .TRUE. + ENDDO + IF (TmpFlag) THEN + CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(SumQTFData%Filename)//' is too sparse '// & + 'for the interpolation routine used in the full sum QTF calculation. At some later point, we will allow for '// & + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'SumQTF_InitCalc') + RETURN + ENDIF + + + !> 5. Calculate the second order forces + !! The single summation equation used here is given by + + + ! Setup temporary arrays that we will be passing the data to the interpolation routines in. + ALLOCATE( TmpData4D(SumQTFData%Data4D%NumWvFreq1,SumQTFData%Data4D%NumWvFreq1,SumQTFData%Data4D%NumWvDir1,SumQTFData%Data4D%NumWvDir2),STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & + ErrStat, ErrMsg, 'SumQTF_InitCalc') + + + ! Setup the arrays holding the SumQTF terms, both the complex frequency domain and real time domain pieces + ALLOCATE( Term1ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the first term of one load component of the full sum '// & + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + ALLOCATE( Term2ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + ALLOCATE( Term1Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the first term of one load component of the full sum '// & + 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + ALLOCATE( Term2Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & + 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + ALLOCATE( SumQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & + 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + + ! If something went wrong during allocation of the temporary arrays... + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(Term1ArrayC)) DEALLOCATE(Term1ArrayC,STAT=ErrStatTmp) + IF (ALLOCATED(Term2ArrayC)) DEALLOCATE(Term2ArrayC,STAT=ErrStatTmp) + IF (ALLOCATED(Term1Array)) DEALLOCATE(Term1Array,STAT=ErrStatTmp) + IF (ALLOCATED(Term2Array)) DEALLOCATE(Term2Array,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Set the resulting force to zero. Will calculate for the dimensions requested. + SumQTFForce = 0.0_SiKi + + + ! Initialize the FFT library. Normalization not required in this formulation. + CALL InitFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) ! FIXME: + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'SumQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(SumQTFForce)) DEALLOCATE(SumQTFForce,STAT=ErrStatTmp) + RETURN + END IF + + + + ! Now loop through all the dimensions and perform the calculation + DO I=1,6 + + ! Only on the dimensions we requested + IF ( p%SumQTFDims(I) ) THEN + + + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + TmpData4D = SumQTFData%Data4D%DataSet(:,:,:,:,I) + + + + !--------------------------------------------------------------------------------- + ! Calculate the first term + ! This term is only the FFT over the diagonal elements where omega_1 = omega_2 + ! note that the sum frequency is 2*omega. The index for the sum frequency is + ! therefore 2*J. Since we are placing the calculated value for the A_m * A_m * + ! F_k^+ term in the 2*omega location, we will only run through the first half of + ! the frequencies (the sum frequency will exceed the bounds of the frequencies + ! used in the FFT otherwise). + ! The IFFT will be calculated later. + + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) + + ! Initialize the array to zero + Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi) + + + ! The limits look a little funny. But remember we are placing the value in the 2*J location, + ! so we cannot overun the end of the array, and the highest frequency must be zero. The + ! floor function is just in case (NStepWave2 - 1) is an odd number + DO J=1,FLOOR(REAL(InitInp%NStepWave2-1)/2.0_SiKi) + + ! The frequency + Omega1 = J * InitInp%WaveDOmega + OmegaSum = 2.0_SiKi * Omega1 ! the sum frequency + + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN + + + ! Find the wave amplitude at frequency omega + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & + SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'SumQTF_InitCalc') + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Set the value of the first term in the frequency domain + Term1ArrayC(2*J) = aWaveElevC1 * aWaveElevC1 * QTF_Value + + + ENDIF ! Check on the limits + ENDDO ! First term calculation + + + + !--------------------------------------------------------------------------------- + ! Calculate the second term. + ! In this term, we are are now stepping through the sum frequencies. The inner + ! sum essentially covers all the off diagonal terms (omega_m /= omega_n). The limits + ! on the outer integral that is the FFT run through the full frequency range that + ! we are using + + + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) + + ! Initialize the temporary arrays for each term to zero. + Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi) + + + ! Check the limits for the high frequency cutoff. If WvHiCOffS is less than the + ! maximum frequency possible with the value of WaveDT (omega_max = pi/WaveDT = NStepWave2*WaveDOmega), + ! then we are good. If the WvHiCOff > 1/2 omega_max, then we will be potentially + ! throwing away information. However, remember the following: + ! WaveDT Omega_max wavelength + ! (s) (rad/s) (m) + ! .25 4 Pi < 1 + ! 0.5 2 Pi 1 + ! 1.0 Pi 10 + ! so, we don't need a really small WaveDT + + !This section has been removed since it is kind of annoying. + ! IF ( InitInp%WvHiCOffS > InitInp%NStepWave2*InitInp%WaveDOmega ) THEN + ! CALL SetErrStat( ErrID_Warn,' The high frequency cutoff for second order wave forces, WvHiCOffS, '// & + ! 'is larger than the Nyquist frequency for the given time step of WaveDT. The Nyquist frequency '// & + ! '(highest frequency) that can be computed is OmegaMax = PI/WaveDT = '// & + ! TRIM(Num2LStr(InitInp%NStepWave2*InitInp%WaveDOmega))// & + ! ' radians/second. If you need those frequencies, decrease WaveDT. For reference, 2*PI '// & + ! 'radians/second corresponds to a wavelength of ~1 meter.',& + ! ErrStat,ErrMsg,'SumQTF_InitCalc') + ! ENDIF + + + + ! Outer loop to create the Term2ArrayC. This is stepwise through the sum frequencies. + DO J=1,InitInp%NStepWave2 + + ! Calculate the frequency -- This is the sum frequency. + OmegaSum = J * InitInp%WaveDOmega + + + + ! Set the \f$ H^+ \f$ term to zero before we start + TmpHPlusC = CMPLX(0.0_SiKi,0.0_SiKi) + + + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN + + !> Now do the inner sum. We are going to perform a sum up to the maximum frequency that we + !! can support (Nyquist frequency) for the given WaveDOmega and NStepWave2 (WaveOmegaMax = + !! NStepWave2 * WaveDOmega = Pi / WaveDT rad/second). Note that this means the largest diagonal + !! frequency we use is \f$ \omega = \Delta\omega * \f$ _NStepwave_/4. + !! So, we essentially end up running into the sampling limit. If we want higher frequency + !! terms, we need to use a smaller stepsize. + + DO K=0,FLOOR(Real(J-1)/2.0_SiKi) + + ! Calculate the frequency pair + Omega1 = K * InitInp%WaveDOmega + Omega2 = (J-K) * InitInp%WaveDOmega + + ! Find the wave amplitude at frequency omega. Remove the NStepWave2 normalization built into WaveElevC0 from Waves module + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1, K), InitInp%WaveElevC0(2, K)) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,J-K), InitInp%WaveElevC0(2,J-K)) / InitInp%NStepWave2 + + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ Omega1, Omega2, InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) + + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & + SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'SumQTF_InitCalc') + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Set the value of the first term in the frequency domain. + TmpHPlusC = TmpHPlusC + aWaveElevC1 * aWaveElevC2 * QTF_Value + + ENDDO + + ! Save the value from the summation. + Term2ArrayC(J) = TmpHPlusC + + + ENDIF ! Check on the limits + + ENDDO ! Second term calculation -- frequency step on the sum frequency + + + + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + END IF + + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & + ErrStat,ErrMsg,'SumQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. + DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,I) gets overwritten later, so I'm setting the array bounds to be -1. + SumQTFForce(J,I) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J))) + ENDDO + + ! Copy the last first term to the last so that it is cyclic + SumQTFForce(InitInp%NStepWave,I) = SumQTFForce(0,I) + + ENDIF ! Load component to calculate + + ENDDO + + + + ! Done with the FFT library routines, so end them. + CALL ExitFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'SumQTF_InitCalc') + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + END IF + + + ! Cleanup + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + + END SUBROUTINE SumQTF_InitCalc + + + + + + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine checks the input values present in InitInput. This should in theory have been done in the HydroDyn_Input + !! routine, so it should not be necessary to do this again here. However, we don't necessarily trust that it has been done, + !! particularly if this module gets used without HydroDyn. + !! + !! This subroutine also populates the InitOut and creates the filenames for each of the calculation types. + !! + SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables. + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(WAMIT2_InitOutputType), INTENT(INOUT) :: InitOut !< The output from the init routine + TYPE(WAMIT2_ParameterType), INTENT( OUT) :: p !< The parameters + + ! QTF storage -- from the data files that are read in + TYPE(W2_DiffData_Type) :: MnDriftData !< Data storage for the Mean Drift method + TYPE(W2_DiffData_Type) :: NewmanAppData !< Data storage for the Newman's Approximation method + TYPE(W2_DiffData_Type) :: DiffQTFData !< Data storage for the full difference QTF method + TYPE(W2_SumData_Type) :: SumQTFData !< Data storage for the full sum QTF method + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error value + CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error. + + ! Temporary variables + LOGICAL :: TmpFileExist !< Temporary flag to indicate existence of file + + ! Temporary Error Variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the local error status + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message variable + + !> ## Subroutine contents + + !-------------------------------------------------------------------------------- + !> ### Initialize variables + !-------------------------------------------------------------------------------- + + !> 1. Initialize error variables + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + !> 2. Initialize filenames + MnDriftData%Filename = '' + NewmanAppData%Filename = '' + DiffQTFData%Filename = '' + SumQTFData%Filename = '' + + + !-------------------------------------------------------------------------------- + !> ### Check the algorithm flags and file values: + !! + !! In the following tests, we check to make sure that a good set of values is + !! given for the tests to run. The following chart shows what is allowed. + !! + !! | Algorithm | Flag True | Flag False | Invalid combination | + !! | :-----------: | :------------: | :------------: | :-------------------: | + !! | MnDrift | 7 - 12 | 0 | any other | + !! | NewmanApp | 7 - 12 | 0 | any other | + !! | DiffQTF | 10 - 12 | 0 | any other | + !! | SumQTF | 10 - 12 | 0 | any other | + !! + !! Also, we check that only one of MnDrift, NewmanApp, or DiffQTF are nonzero. + !! Rather than test on the flag value (MnDriftF etc.), we test on the input value + !! then verify the flag matches. It could be done based on the flag, but it isn't + !! for arbitrarily chosen reasons. + !! + !! @note The .8 input files only support dimensions 1,2, and 6 (surge, sway, + !! yaw). This gets checked in this routine, and a set of parameters are set + !! for each method listing which dimensions to use. + !! + !-------------------------------------------------------------------------------- + + + !> 1. Check that we only specified one of MnDrift, NewmanApp, or DiffQTF + !! (compared pairwise -- if any two are both true, we have a problem) + + IF ( ( InitInp%MnDrift /= 0 .AND. InitInp%NewmanApp /= 0 ) .OR. & + ( InitInp%DiffQTF /= 0 .AND. InitInp%NewmanApp /= 0 ) .OR. & + ( InitInp%MnDrift /= 0 .AND. InitInp%DiffQTF /= 0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + !> 2. Check that we have a valid values for MnDrift, check flag status + + IF ( InitInp%MnDrift == 0 ) THEN ! We are not doing anything + IF ( InitInp%MnDriftF ) THEN ! Should be false in this case, so if true there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' MnDriftF flag should be set to false by calling program for MnDrift = 0.'//NewLine// & + ' --> This should have been checked by the calling program.',ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE IF( InitInp%MnDrift >= 7 .AND. InitInp%MnDrift <= 12 ) THEN ! Valid values + IF ( .not. InitInp%MnDriftF ) THEN ! Should be true in this case, so if false there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' MnDriftF flag should be set to true by calling program for MnDrift /= 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' MnDrift can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + !> 3. Check that we have a valid values for NewmanApp, check flag status + + IF ( InitInp%NewmanApp == 0 ) THEN ! We are not doing anything + IF ( InitInp%NewmanAppF ) THEN ! Should be false in this case, so if true there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' NewmanAppF flag should be set to false by calling program for NewmanApp = 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE IF( InitInp%NewmanApp >= 7 .AND. InitInp%NewmanApp <= 12 ) THEN ! Valid values + IF ( InitInp%NewmanAppF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' NewmanAppF flag should be set to true by calling program for NewmanApp /= 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' NewmanApp can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + !> 4. Check that we have a valid values for DiffQTF, check flag status + + IF ( InitInp%DiffQTF == 0 ) THEN ! We are not doing anything + IF ( InitInp%DiffQTFF .eqv. .TRUE. ) THEN ! Should be false in this case, so if true there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' DiffQTFF flag should be set to false by calling program for DiffQTF = 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE IF( InitInp%DiffQTF >= 10 .AND. InitInp%DiffQTF <= 12 ) THEN ! Valid values + IF ( InitInp%DiffQTFF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' DiffQTFF flag should be set to true by calling program for DiffQTF /= 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' DiffQTF can only have values of 0, 10, 11, or 12. '//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + !> 5. Check that we have a valid values for SumQTF, check flag status + + IF ( InitInp%SumQTF == 0 ) THEN ! We are not doing anything + IF ( InitInp%SumQTFF .eqv. .TRUE. ) THEN ! Should be false in this case, so if true there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' SumQTFF flag should be set to false by calling program for SumQTF = 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE IF( InitInp%SumQTF >= 10 .AND. InitInp%SumQTF <= 12 ) THEN ! Valid values + IF ( InitInp%SumQTFF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & + ' SumQTFF flag should be set to true by calling program for SumQTF /= 0.'//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + ELSE + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' SumQTF can only have values of 0, 10, 11, or 12. '//NewLine// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + !-------------------------------------------------------------------------------- + !> ### Check the Min and Max frequencies for the full QTF cases + !! + !! -- these checks are performed based on the DiffQTFF and SumQTFF flags + !-------------------------------------------------------------------------------- + + + !> 1. Check that the min / max diff frequencies make sense if using DiffQTF + + IF ( InitInp%DiffQTFF .eqv. .TRUE. ) THEN + IF ( ( InitInp%WvHiCOffD < InitInp%WvLowCOffD ) .OR. ( InitInp%WvLowCOffD < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' WvHiCOffD must be larger than WvLowCOffD. Both must be positive.'// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + END IF + + + !> 2. Check that the min / max diff frequencies make sense if using SumQTF + + IF ( InitInp%SumQTFF .eqv. .TRUE. ) THEN + IF ( ( InitInp%WvHiCOffS < InitInp%WvLowCOffS ) .OR. ( InitInp%WvLowCOffS < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & + ' WvHiCOffS must be larger than WvLowCOffS. Both must be positive.'// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + END IF + + + + !-------------------------------------------------------------------------------- + !> ### Assemble the names of the WAMIT data files we are using and verify existence + !-------------------------------------------------------------------------------- + + !> 1. Check MnDrift file if we are doing the mean drift calculations. Set flag for data type. + + MnDriftData%DataIs3D = .FALSE. + MnDriftData%DataIs4D = .FALSE. + + IF ( InitInp%MnDrift /= 0) THEN + IF ( InitInp%MnDrift <= 9 ) THEN ! For file types 7, 8, 9 + MnDriftData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%MnDrift)) + INQUIRE( file=TRIM(MnDriftData%Filename), exist=TmpFileExist ) + MnDriftData%DataIs3D = .TRUE. + ELSE ! For full QTF file types 10, 11, 12 + MnDriftData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%MnDrift))//'d' + INQUIRE( file=TRIM(MnDriftData%Filename), exist=TmpFileExist ) + MnDriftData%DataIs4D = .TRUE. + ENDIF + IF ( TmpFileExist .eqv. .FALSE. ) THEN + CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(MnDriftData%Filename)// & + ' required by the MnDrift option.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CLeanup + RETURN + END IF + END IF + + + !> 2. Check NewmanApp file if we are doing the Newman's approximation calculations. Set flag for data type. + + NewmanAppData%DataIs3D = .FALSE. + NewmanAppData%DataIs4D = .FALSE. + + IF ( InitInp%NewmanApp /= 0) THEN + IF ( InitInp%NewmanApp <= 9 ) THEN ! For file types 7, 8, 9 + NewmanAppData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%NewmanApp)) + INQUIRE( file=TRIM(NewmanAppData%Filename), exist=TmpFileExist ) + NewmanAppData%DataIs3D = .TRUE. + ELSE ! For full QTF file types 10, 11, 12 + NewmanAppData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%NewmanApp))//'d' + INQUIRE( file=TRIM(NewmanAppData%Filename), exist=TmpFileExist ) + NewmanAppData%DataIs4D = .TRUE. + ENDIF + IF ( TmpFileExist .eqv. .FALSE. ) THEN + CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(NewmanAppData%Filename)// & + ' required by the NewmanApp option.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + END IF + + + !> 3. Check DiffQTF file if we are doing the Difference QTF calculations + + DiffQTFData%DataIs3D = .FALSE. + DiffQTFData%DataIs4D = .FALSE. + + IF ( InitInp%DiffQTF /= 0) THEN + DiffQTFData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%DiffQTF))//'d' + INQUIRE( file=TRIM(DiffQTFData%Filename), exist=TmpFileExist ) + IF ( TmpFileExist .eqv. .FALSE. ) THEN + CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(DiffQTFData%Filename)// & + ' required by the DiffQTF option.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + DiffQTFData%DataIs4D = .TRUE. + END IF + + + !> 4. Check SumQTF file if we are doing the Sum QTF calculations + + SumQTFData%DataIs4D = .FALSE. + + IF ( InitInp%SumQTF /= 0) THEN + SumQTFData%Filename = TRIM(InitInp%WAMITFile)//'.'//TRIM(Num2LStr(InitInp%SumQTF))//'s' + INQUIRE( file=TRIM(SumQTFData%Filename), exist=TmpFileExist ) + IF ( .not. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(SumQTFData%Filename)// & + ' required by the SumQTF option.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + SumQTFData%DataIs4D = .TRUE. + END IF + + + !-------------------------------------------------------------------------------- + !> ### Check the size of arrays that were passed in containing the wave info + !-------------------------------------------------------------------------------- + + + !> 1. Check that WaveElevC0 is a 2x(NStepWave2+1) sized array (0 index start) + + IF ( SIZE( InitInp%WaveElevC0, 2 ) /= (InitInp%NStepWave2 + 1) ) THEN ! Expect a 2x(0:NStepWave2) array + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init:'//NewLine// & + ' --> Expected array for WaveElevC0 to be of size 2x'//TRIM(Num2LStr(InitInp%NStepWave2 + 1))// & + ' (2x(NStepWave2+1)), but instead received array of size '// & + TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,1)))//'x'//TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,2)))//'.', ErrStat, ErrMsg, 'CheckInitInput') + CALL CleanUp + RETURN + END IF + + + + + !-------------------------------------------------------------------------------- + !> ### Now copy over things to parameters... + !-------------------------------------------------------------------------------- + !> 1. Wave information we need to keep + !-------------------------------------------------------------------------------- + p%NStepWave = InitInp%NStepWave + + + !-------------------------------------------------------------------------------- + !> 2. Time related information + !-------------------------------------------------------------------------------- + + p%DT = Interval ! Timestep from calling program + + ! Allocate array for the WaveTime information -- array of times to generate output for. NOTE: can't use MOVE_ALLOC since InitInp is intent in. + CALL AllocAry( p%WaveTime, SIZE(InitInp%WaveTime,1), 'array to hold WaveTime', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal, ErrMsgTmp, ErrStat, ErrMsg, 'CheckInitInput') + RETURN + ENDIF + p%WaveTime = InitInp%WaveTime + + + + !-------------------------------------------------------------------------------- + !> ### Flags indicating forces to calculate for with each method + !! This information is stored on a method basis since we might use a .8 file + !! in either the NewmanApp or the MnDrift method (it doesn't contain all the + !! dimensions), and use a different file with the SumQTF method. + !! + !! The dimension numbers map as follows: + !! | Index | Name | Axis | + !! | :---: | :------: | :--------: | + !! | 1 | Surge | (X) | + !! | 2 | Sway | (Y) | + !! | 3 | Heave | (Z) | + !! | 4 | Roll | (about X) | + !! | 5 | Pitch | (about Y) | + !! | 6 | Yaw | (about Z) | + !! + !! @note + !! If we had set flags to do calculations of Heave, Roll, or Pitch (3, 4, 5) for + !! either the Mean Drift or Newman's Approximation methods while trying to use + !! the WAMIT .8 output files, we will issue a warning. + !-------------------------------------------------------------------------------- + + !> 1. For the Mean Drift method, + + IF (InitInp%MnDriftF) THEN ! if the flag is true, we are doing this calculation + IF (InitInp%MnDrift == 8) THEN ! the .8 files are not complete + p%MnDriftDims(1) = InitInp%PtfmSgF2 + p%MnDriftDims(2) = InitInp%PtfmSwF2 + p%MnDriftDims(3) = .FALSE. ! the .8 files don't contain this dimension + p%MnDriftDims(4) = .FALSE. ! the .8 files don't contain this dimension + p%MnDriftDims(5) = .FALSE. ! the .8 files don't contain this dimension + p%MnDriftDims(6) = InitInp%PtfmYF2 + !> Now warn me that we changed the calculations in this case... + IF (InitInp%PtfmHvF2) THEN + CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& + 'in the heave direction. No second order heave forces will be calculated within the mean drift calculations.'//NewLine, & + ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + IF (InitInp%PtfmRF2) THEN + CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& + 'for platform roll. No second order roll forces will be calculated within the mean drift calculations.'//NewLine, & + ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + IF (InitInp%PtfmPF2) THEN + CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& + 'for platform pitch. No second order pitching forces will be calculated within the mean drift calculations.'//NewLine, & + ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + ELSE + p%MnDriftDims(1) = InitInp%PtfmSgF2 + p%MnDriftDims(2) = InitInp%PtfmSwF2 + p%MnDriftDims(3) = InitInp%PtfmHvF2 + p%MnDriftDims(4) = InitInp%PtfmRF2 + p%MnDriftDims(5) = InitInp%PtfmPF2 + p%MnDriftDims(6) = InitInp%PtfmYF2 + ENDIF + ELSE + p%MnDriftDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + + !> 2. For the Newman Approximation method + + IF (InitInp%NewmanAppF) THEN ! if the flag is true, we are doing this calculation + IF (InitInp%NewmanApp == 8) THEN ! the .8 files are not complete + p%NewmanAppDims(1) = InitInp%PtfmSgF2 + p%NewmanAppDims(2) = InitInp%PtfmSwF2 + p%NewmanAppDims(3) = .FALSE. ! the .8 files don't contain this dimension + p%NewmanAppDims(4) = .FALSE. ! the .8 files don't contain this dimension + p%NewmanAppDims(5) = .FALSE. ! the .8 files don't contain this dimension + p%NewmanAppDims(6) = InitInp%PtfmYF2 + !> Now warn me that we changed the calculations in this case... + IF (InitInp%PtfmHvF2) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& + 'second order force calculations of platform heave.'//NewLine// & + " No second order heave forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + IF (InitInp%PtfmRF2) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& + 'second order force calculations of platform roll.'//NewLine// & + " No second order roll forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + IF (InitInp%PtfmPF2) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& + 'second order force calculations of platform pitch.'//NewLine// & + " No second order pitching forces will be calculated within the Newman's Approximation calculations.", & + ErrStat, ErrMsg, 'CheckInitInput') + ENDIF + ELSE + p%NewmanAppDims(1) = InitInp%PtfmSgF2 + p%NewmanAppDims(2) = InitInp%PtfmSwF2 + p%NewmanAppDims(3) = InitInp%PtfmHvF2 + p%NewmanAppDims(4) = InitInp%PtfmRF2 + p%NewmanAppDims(5) = InitInp%PtfmPF2 + p%NewmanAppDims(6) = InitInp%PtfmYF2 + ENDIF + ELSE + p%NewmanAppDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something + ENDIF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + + + !> 3. For the Difference QTF method, + + IF (InitInp%DiffQTFF) THEN ! if the flag is true, we are doing this calculation + p%DiffQTFDims(1) = InitInp%PtfmSgF2 + p%DiffQTFDims(2) = InitInp%PtfmSwF2 + p%DiffQTFDims(3) = InitInp%PtfmHvF2 + p%DiffQTFDims(4) = InitInp%PtfmRF2 + p%DiffQTFDims(5) = InitInp%PtfmPF2 + p%DiffQTFDims(6) = InitInp%PtfmYF2 + ! Also set the MnDrift flags. We will be passing data from the DiffQTF method to the MnDrift method for the first term + p%MnDriftDims(1) = InitInp%PtfmSgF2 + p%MnDriftDims(2) = InitInp%PtfmSwF2 + p%MnDriftDims(3) = InitInp%PtfmHvF2 + p%MnDriftDims(4) = InitInp%PtfmRF2 + p%MnDriftDims(5) = InitInp%PtfmPF2 + p%MnDriftDims(6) = InitInp%PtfmYF2 + ELSE + p%DiffQTFDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something + ENDIF + + + !> 4. For the Summation QTF method, + + IF (InitInp%SumQTFF) THEN ! if the flag is true, we are doing this calculation + p%SumQTFDims(1) = InitInp%PtfmSgF2 + p%SumQTFDims(2) = InitInp%PtfmSwF2 + p%SumQTFDims(3) = InitInp%PtfmHvF2 + p%SumQTFDims(4) = InitInp%PtfmRF2 + p%SumQTFDims(5) = InitInp%PtfmPF2 + p%SumQTFDims(6) = InitInp%PtfmYF2 + ELSE + p%SumQTFDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something + ENDIF + + + !-------------------------------------------------------------------------------- + !> Flags to perform method calculations. Info from input file. + !! Flag indicates method use in calculations (ends with F). + !-------------------------------------------------------------------------------- + + ! Mean drift method + p%MnDriftF = InitInp%MnDriftF ! Flag for calculation + + ! Newman approximation method + p%NewmanAppF = InitInp%NewmanAppF ! Flag for calculation + + ! Difference QTF + p%DiffQTFF = InitInp%DiffQTFF ! Flag for calculation + + ! Summation QTF + p%SumQTFF = InitInp%SumQTFF ! Flag for calculation + + + + !-------------------------------------------------------------------------------- + !> Make array for holding the resulting timeseries for the second order force. + !-------------------------------------------------------------------------------- + + ! Allocate array for the WaveExtcn2. + ALLOCATE( p%WaveExctn2(0:InitInp%NStepWave,6), STAT=ErrStatTmp) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array p%WaveExctn2 to store '// & + 'the 2nd order force data.', ErrStat,ErrMsg,'CheckInitInp') + IF (ErrStat >= AbortErrLev ) RETURN + + + !-------------------------------------------------------------------------------- + !> FAST channel output + !-------------------------------------------------------------------------------- + + p%NumOuts = InitInp%NumOuts + p%NumOutAll = InitInp%NumOutAll + + + END SUBROUTINE CheckInitInput + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine reads in the datafile containing 3D data (Omega, WaveDir1, WaveDir2), stores it to Data3D, and sets flags + !! indicating how complete the data is. + !! + !! The datafile is first scanned to make sure it is of the correct form, then read in in its entirety into a temporary matrix. + !! Then we find the number of unique frequencies and unique wave direction pairs that are in it, and create the necessary + !! data structures to hold all of it. Once this is done, we check for the infinite and zero frequency limits and add space + !! for them as needed. + !! + !! This matrix holding the data is read one line at a time and is placed into the correct location within the dataset. The mask + !! array is then marked to indicate valid data is at that coordinate index. + !! + !! Since the data may not contain the zero frequency and infinite frequency, we will create those values. For the zero frequency, + !! the QTF must be zero. For the infinite frequency, we use the value from the highest wave frequency (essentially flat response). + !! + !! At the end of all this, we check the data for completeness and set the flags accordingly. + !! + SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) + + IMPLICIT NONE + + ! Passed variables. + CHARACTER(*), INTENT(IN ) :: Filename3D !< Name of the file containing the 3D data + TYPE(W2_InitData3D_Type), INTENT(INOUT) :: Data3D !< 3D QTF data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error value + CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error. + + ! Local variables + INTEGER(IntKi) :: UnitDataFile !< The unit number for the currently open file + + INTEGER(IntKi) :: NumDataColumns !< Number of data columns in the file + INTEGER(IntKi) :: NumDataLines !< Total number of lines in the file (excluding first text line if there is one) + INTEGER(IntKi) :: NumDataLinesKeep !< Total number of lines in the file that are to be kept (positive force component index) + INTEGER(IntKi) :: NumHeaderLines !< Flag to indicate if the first line of the file is text + + ! Raw file data storage + REAL(SiKi), ALLOCATABLE :: RawData3D(:,:) !< The raw data from the entirety of the input file -- after ignoring negative force components + REAL(SiKi), ALLOCATABLE :: RawData3DTmp(:,:) !< The raw data from the entirety of the input file -- as read in. + REAL(SiKi) :: HighFreq1 !< The highest frequency found. Needed for setting the infinite frequency data. + INTEGER(IntKi) :: WvFreq1HiIdx !< Index to the highest wave 1 frequency + INTEGER(IntKi) :: WvFreq1LoIdx !< Index to the lowest wave 1 frequency + LOGICAL :: HaveZeroFreq1 !< Indicates we have a zer frequency value + + + ! File reading variables + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + REAL(SiKi), ALLOCATABLE :: TmpRealArr(:) !< Temporary real array + REAL(SiKi), ALLOCATABLE :: TmpDataRow(:) !< Single row of data + REAL(SiKi), ALLOCATABLE :: TmpWvFreq1(:) !< Temporary array to hold the wave frequencies read in. + + ! Temporary sparseness checking flag + LOGICAL :: TmpSparseFlag !< Temporary flag for checking sparseness + + ! Generic counters + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + INTEGER(IntKi) :: L !< Generic counter + INTEGER(IntKi) :: TmpCoord(4) !< Temporary index coords to the Data3D matrix (3D + force dimension) + + ! Error handling temporary variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the local error status + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message variable + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + CHARACTER(*), PARAMETER :: RoutineName = 'Read_DataFile3D' + + + !> ## Subroutine Contents + + !-------------------------------------------------------------------------------- + !> Initialize variables + !-------------------------------------------------------------------------------- + + ! Initialize error variables + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + Data3D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. + HaveZeroFreq1 = .FALSE. ! If we find a zero frequency, we will set this to true + + + !-------------------------------------------------------------------------------- + !> ### Check data file for consistency + !-------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------ + !> 3D data files are only used for cases of { MnDrift || NewmanApp } = { 7 || 8 || 9}\n + !! .7 files are available from WAMIT version 7 only --> Not checked at present\n + !! .8 files only contain information for dimensions 1, 2, and 6 (x, y, yaw) -- set in CheckInitInput\n + !! .9 files contain all dimensions + !------------------------------------------------------------------------------ + + ! Find a unit number to use + CALL GetNewUnit(UnitDataFile,ErrStatTmp,ErrMsgTmp) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Open the file + CALL OpenFInpFile( UnitDataFile, TRIM(Filename3D), ErrStat, ErrMsg ) ! Open file containing mean drift information + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + REWIND( UnitDataFile ) + + + ! Do an initial readthrough and find out the length of the file, if there is a header line, and the number of columns in the file. + CALL GetFileLength( UnitDataFile, TRIM(Filename3D), NumDataColumns, NumDataLines, NumHeaderLines, ErrStat, ErrMsg) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + ! Make sure we have 8 columns of data in the data file. + IF ( NumDataColumns /= 8 ) THEN + CALL SetErrStat( ErrID_Fatal, ' The 2nd order WAMIT data file '//TRIM(Filename3D)//' has '//TRIM(Num2LStr(NumDataColumns))// & + ' columns instead of the 8 columns expected.', ErrStat, ErrMsg, RoutineName) + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + !---------------------------------------------------------------------------------- + !> ### Read and store the raw data from the file. Convert all wave periods (s) into + !! frequency (rad/s) + !---------------------------------------------------------------------------------- + + ! Allocate the temporary array for reading in one line + CALL AllocAry( TmpDataRow, NumDataColumns, ' Array for holding one line of 4D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + + ! Allocate an array to hold the entirety of the raw contents of the file + CALL AllocAry( RawData3DTmp, NumDataLines, NumDataColumns, ' Array for holding raw 3D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Read and discard the header lines + DO I=1,NumHeaderLines + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + ENDDO + + ! Read in the data one line at a time and put it in RawData3D + DO I=1,NumDataLines + CALL ReadAry( UnitDataFile, TRIM(Filename3D), TmpDataRow, NumDataColumns, 'RawData3D('//TRIM(Num2LStr(I))//',:)', & + ' Line '//TRIM(Num2LStr(NumHeaderLines+I))//' of '//TRIM(Filename3D), & + ErrStatTmp, ErrMsgTmp ) ! Note, not echoing this to anything. + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + RawData3DTmp(I,:) = TmpDataRow + ENDDO + + CLOSE( UnitDataFile ) + + + !> Before continuing, we need to figure out how many actual lines of data we will + !! be keeping (lines where the force component index is positive). The force component + !! is in column 4 for 3D data read in. First find out if there are negative force + !! components, then count the number of data rows we are keeping. Then copy data over. + IF ( MINVAL(RawData3DTmp(:,4)) < 0_IntKi ) THEN ! check the 4th element (force component) + CALL SetErrStat( ErrID_Warn,' Negative load components found (moving reference frame). Ignoring', & + ErrStat,ErrMsg,RoutineName) + + ! Count how many lines we are keeping. + NumDataLinesKeep = 0_IntKi + DO I=1,NumDataLines + IF ( RawData3DTmp(I,4) > 0 ) THEN + NumDataLinesKeep = NumDataLinesKeep + 1 + ENDIF + ENDDO + + ! Allocate an array to hold the data from the file that we are keeping + CALL AllocAry( RawData3D, NumDataLinesKeep, NumDataColumns, ' Array for holding raw 3D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Now copy over the data that we are keeping. Ignore the rest + NumDataLinesKeep = 0_IntKi + DO I=1,NumDataLines + IF ( RawData3DTmp(I,4) > 0 ) THEN + NumDataLinesKeep = NumDataLinesKeep + 1 + RawData3D( NumDataLinesKeep, : ) = RawData3DTmp(I,:) + ENDIF + ENDDO + + ! We no longer need the raw data from the file. + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + + ! no negative force components, so just move the array. + ELSE + CALL MOVE_ALLOC( RawData3DTmp, RawData3D ) + NumDataLinesKeep = NumDataLines + ENDIF + + + !> Before proceeding further, we are going to change the wave period from measured + !! in seconds to a frequency measurement in _rad/s_. We will step through the data + !! matrix and convert the first column. + !! + !! Note that wave periods that are negative correspond to the \f$ \omega=0 \f$, and + !! wave periods with \f$ \tau=0 \f$ mean \f$ \omega=\infty \f$. Normally these + !! would not be calculated for sum and difference frequencies as there is little + !! information of interest there. + !! + !! In the implimentation here, the infinity frequency covers everything from just above + !! highest frequency given in the file and infinity. This means that everything the + !! the highest frequency is handled exactly the same. + + DO I=1,NumDataLinesKeep + IF ( EqualRealNos(RawData3D(I,1), 0.0_SiKi) ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE IF ( RawData3D(I,1) < 0 ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE + RawData3D(I,1) = TwoPi/RawData3D(I,1) ! First column is Tau1 + ENDIF + ENDDO + + ! Now we can fix the value for the frequency that was negative and set it to sligtly + ! larger than the largest value. First find the highest value. + HighFreq1 = MAXVAL(RawData3D(:,1)) + + ! First change the values given as 0.0 to the infinite frequency and set a flag to indicate we + ! found an infinite frequency in this dimension. We will later copy this value to the infinite + ! frequency. This results in having a flat response from the highest frequency found to the + ! infinite frequency. + DO I=1,NumDataLinesKeep + IF ( EqualRealNos(RawData3D(I,1), 0.0_SiKi) ) THEN + RawData3D(I,1) = HighFreq1 * OnePlusEps + ENDIF + ENDDO + + ! Now change the negative values to be 0.0 (zero frequency) + DO I=1,NumDataLinesKeep + IF ( RawData3D(I,1) < 0.0_SiKi ) THEN + RawData3D(I,1) = 0.0_SiKi + HaveZeroFreq1 = .TRUE. + ENDIF + ENDDO + + + !---------------------------------------------------------------------------------- + !> ### Read through the file and find the number of WvFreq1, WaveDir1, WaveDir2. + !! + !! The 2nd order 3D files are arranged as follows: + !! Tau1, Beta1, Beta2, k, |F|, Phase, Real, Imaginary + !! where: + !! | Column | Variable | Units | Description | + !! | :----: | :-------------: | :-------------: | :-------------------------------- | + !! | 1 |\f$ \omega_1 \f$ | rad/s | Wave period 1 (converted above) | + !! | 2 |\f$ \beta_1 \f$ | degrees | Wave direction 1 | + !! | 3 |\f$ \beta_2 \f$ | degrees | Wave direction 2 | + !! | 4 | k | -- | Force component direction (1-6) | + !! | 5 |\f$ |F| \f$ | Nondimensional | Magnitude of the force QTF | + !! | 6 | Phase | degrees | Phase of the force QTF | + !! | 7 |\f$ \Re(F) \f$ | Nondimensional | Real part of the force QTF | + !! | 8 |\f$ \Im(F) \f$ | Nondimensional | Imaginary part of the force QTF | + !! + !! Only columns 1, 2, 3, 4, 7, 8 are used. Columns 5 & 6 are redundant information. + !! + !! Note that we will be checking for the zero frequency, and adding it if it was not + !! found in the file. + !---------------------------------------------------------------------------------- + + + !---------------------------------------------------------------------------------- + !> Read through the 3D data and figure out how many unique values in each dependent + !! variable (\f$ \omega_1, \beta_1, \beta_2,\f$ Component direction) exist in the file. + !! + !! Allocate the necessary storage arrays when complete. + !---------------------------------------------------------------------------------- + + ! Get the number of first frequencies + CALL UniqueRealValues( RawData3D(:,1), TmpWvFreq1, Data3D%NumWvFreq1, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Get the number of first wave directions + CALL UniqueRealValues( RawData3D(:,2), Data3D%WvDir1, Data3D%NumWvDir1, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Get the number of second wave directions + CALL UniqueRealValues( RawData3D(:,3), Data3D%WvDir2, Data3D%NumWvDir2, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + ! Find out which load components are actually in use + CALL UniqueRealValues( RawData3D(:,4), TmpRealArr, K, ErrStatTmp,ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + + ! If the value of K is more than 6, we have some serious issues + IF ( K > 6 ) CALL SetErrStat( ErrID_Fatal, ' More than 6 load components found in column 4 of '// & + TRIM(Filename3D)//'.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Now check the values we got back and set the LoadComponents flags for those with data. The + ! load component direction must be between 1 and 6 (translational: 1,2,3; rotational: 4,5,6). + Data3D%LoadComponents = .FALSE. + DO I=1,K + IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Load components listed in column 4 of '//TRIM(Filename3D)// & + ' must be between 1 and 6.', ErrStat,ErrMsg,RoutineName) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + Data3D%LoadComponents(NINT(TmpRealArr(I))) = .TRUE. + ENDDO + + + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) ! Done with this, so throw it away. + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + + + + + ! Now we need to figure out if the zero frequency was given in the file. If so, we change NumWvFreq1 to + ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and + ! zero out all values not in the input frequency range. The inifinite frequency value will be set to HUGE + ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step + ! change for zeroing the values outside the input frequency range. + IF (HaveZeroFreq1) THEN + Data3D%NumWvFreq1 = Data3D%NumWvFreq1+2 + WvFreq1LoIdx = 1 + ELSE + Data3D%NumWvFreq1 = Data3D%NumWvFreq1+4 + WvFreq1LoIdx = 3 + ENDIF + + ! Set the index for the highest frequency stored before the cutoff + WvFreq1HiIdx = Data3D%NumWvFreq1-2 + + ! Now allocate the array for holding the WvFreq1 + ALLOCATE( Data3D%WvFreq1( Data3D%NumWvFreq1), STAT=ErrStatTmp) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%WvFreq1 to store '// & + 'the sorted 3D 2nd order WAMIT frequency data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Populate the wave frequencies with what we read in + Data3D%WvFreq1( WvFreq1LoIdx:WvFreq1HiIdx ) = TmpWvFreq1 + + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + IF ( .NOT. HaveZeroFreq1) THEN + Data3D%WvFreq1( 1 ) = 0.0_SiKi + Data3D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing + ENDIF + + ! add the two points for step-change after last entered frequency + Data3D%WvFreq1( Data3D%NumWvFreq1-1 ) = Data3D%WvFreq1(Data3D%NumWvFreq1-2) + 10.0_SiKi*EPSILON(0.0_SiKi) + Data3D%WvFreq1( Data3D%NumWvFreq1 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant + + + + ! Now that we know how many frequencies and wave directions there are, we can allocate the array + ! for saving the sorted data. + ALLOCATE( Data3D%DataSet( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataSet to store '// & + 'the sorted 3D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Allocate the logical array for storing the mask for which points are valid. Set to .FALSE. + ALLOCATE( Data3D%DataMask( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataMask to store '// & + 'the sorted 3D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + Data3D%DataMask = .FALSE. ! Populate this later + + + + !---------------------------------------------------------------------------------- + !> Now step through the raw data and place values in the correct final locations, + !! set the flag mask array, and calculate the conjugate pairs (4D only). + !! + !! The way this works is that the Data3D%WvFreq1, Data3D%WvDir1, and Data3D%WaveDir2 + !! contain the order frequencies and direction from the input file. Therefore, the + !! index numbers of these three arrays corresponds to the location in Data3D%DataSet + !! that holds the complex force QTF value for that frequency and wave direction pair. + !! + !! So, to populate the Data3D%DataSet matrix, we simply have to read one line at a + !! time from the file (stored in RawData3D matrix), and place it in the corresponding + !! coordinate location in Data3D%DataSet. This involves simply searching through + !! the WvFreq1, WvDir1, and WvDir2 arrays for the correct indices. + !! + !! The wave force component direction is stored slightly differently, so it only + !! needs to be read from the raw data and coverted into an integer to use as an + !! index. + !---------------------------------------------------------------------------------- + + + TmpCoord = 1 ! Initialize the search locations. + + DO I=1,NumDataLinesKeep + + ! Error checking: The LocateStp routine will return 0 if the requested value is less than the value + ! of the first element in the array. It will return the index of the last element + ! of the array if the value is larger than the last element. In creating the arrays + ! that are being searched here, the values that we are now trying to find the index + ! to were used. Therefore, if the requested value is not found in the array, then + ! something must have gone horribly wrong while creating it, or between then and now, + ! which is most likely a programming error. + + ! Find the location in the WvFreq1 array that this point corresponds to. We will check only between the + ! cutoffs that were added to the frequency range. This is contained within TmpWvFreq1 from reading in. + CALL LocateStp( RawData3D(I,1), TmpWvFreq1, TmpCoord(1), WvFreq1HiIdx - (WvFreq1LoIdx - 1) ) ! inclusive limits + IF ( TmpCoord(1) == 0 .OR. ( RawData3D(I,1) > Data3D%WvFreq1(Data3D%NumWvFreq1)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data3D%WvFreq1 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + TmpCoord(1) = TmpCoord(1) + ( WvFreq1LoIdx - 1 ) ! shift to the point in the Data3D%WvFreq1 array by adding the zero frequency step function + + ! Find the location in the WvDir1 array that this point corresponds to. + CALL LocateStp( RawData3D(I,2), Data3D%WvDir1, TmpCoord(2), Data3D%NumWvDir1 ) + IF ( TmpCoord(2) == 0 .OR. ( RawData3D(I,2) > Data3D%WvDir1(Data3D%NumWvDir1)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data3D%WvDir1 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Find the location in the WvDir2 array that this point corresponds to. + CALL LocateStp( RawData3D(I,3), Data3D%WvDir2, TmpCoord(3), Data3D%NumWvDir2 ) + IF ( TmpCoord(3) == 0 .OR. ( RawData3D(I,3) > Data3D%WvDir2(Data3D%NumWvDir2)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data3D%WvDir2 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Find which force component this belongs to + TmpCoord(4) = NINT(RawData3D(I,4)) + + + !> The data from the WAMIT file is non-dimensional, so we need to dimensionalize it here. This + !! is a partial dimensionalization since the wave amplitudes are not included (this is done later + !! in each of the calculation methods). To dimensionalize the data, the equation is for the + !! partially dimensionalized force (\f$ F_k \f$) is: + !! + !! \f$ F_k = \rho g \cdot L^\alpha \cdot \bar{F}_k \f$ + !! + !! where \f$ \bar{F}_k \f$ is the force QTF value in the file for the \f$ k \f$ component + !! direction, \f$ L \f$ is the WAMIT unit length _WAMITULEN_, \f$ \rho \f$ is the density of + !! water, and \f$ g \f$ is the gravitational constant (\f$ \rho g \f$ is combined as _RhoXg_). + !! The value of \f$ \alpha \f$ is 1 for \f$ k = 1,2,3 \f$ and 2 for \f$ k = 4,5,6 \f$. + + ! Here K is used for \f$ alpha \f$ in the dimensionalization equation. + IF ( TmpCoord(4) <=3 ) THEN + K = 1 + ELSE + K = 2 + ENDIF + + + ! Check that the current value has not been read in already. If it has, the corresponding + ! flag in the mask array will be set to true. This will indicate that there was redundant + ! data in the file. If the value agrees, we will politely ignore it without warning. If + ! it does not agree, then we will have to stop since it is ambiguous which is correct. + + IF ( Data3D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) ) THEN + IF ( .NOT. EqualRealNos(REAL(Data3D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ),SiKi), & + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K * RawData3D(I,7) ,SiKi)) .AND. & + .NOT. EqualRealNos( AIMAG(Data3D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) ), & + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K * RawData3D(I,8) ,SiKi)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Line '//TRIM(Num2Lstr(NumHeaderLines+I))//' of '//TRIM(Filename3D)// & + ' contains different values for the real and imaginary part (columns 7 and 8) than was '// & + 'given earlier in the file for the same values of wave frequency and wave direction.', & + ErrStat, ErrMsg, RoutineName ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + ELSE + + ! Store the data after dimensionalizing + Data3D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) = & + InitInp%RhoXg * InitInp%WAMITULEN**K * CMPLX(RawData3D(I,7),RawData3D(I,8)) + + ! Set flag indicating that this value has been inserted. + Data3D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) = .TRUE. + + ENDIF + + ENDDO + + + !> Note that in the 3D WAMIT output files (.7, .8, .9 files), only the diagonal terms where + !! \f$ \omega_m = \omega_m \f$ are given. If multidirectional waves are used, both WvDir1 + !! and WvDir2 will need to be populated. According to the WAMIT theory guide (page 4-7), + !! it there is a relationship between the wave direction pairs for this case: + !! \f$ \bar{F}(\omega_n,\omega_m) = \bar{F}^*(\omega_m,\omega_n) \f$. + !! So, we can use this to populate missing values of WvDir2,WvDir1 from the WvDir1,WvDir2 + !! pair. + !! + !! Since only one wave frequency array is present, WvFreq1, this is possible to do. For + !! two wave frequencies, such as in a full QTF, the calculation performed here would need + !! to be performed only when \f$ \omega_1 = \omega_2 \f$. + + ! Loop over the wave components, but only perform calculations on the ones that have values + DO L=1,6 + IF (Data3D%LoadComponents(L)) THEN ! Only do this for the load components that exist + DO I=1,Data3D%NumWvFreq1 ! Frequencies + + ! Now look through the wave direction matrix (all combinations of (beta_1,beta_2) ) + ! and if it is missing, set it equal to the complex conjugate of the + ! (beta_2,beta_1) element if it exists. We don't need to check the beta_1 = beta_2 + ! elements. + DO J=1,Data3D%NumWvDir1 + DO K=J,Data3D%NumWvDir2 + + ! Only non-diagonal elements + IF ( .NOT. EqualRealNos( Data3D%WvDir1(J), Data3D%WvDir2(K) ) ) THEN + + ! See if WvDir1(J) == WvDir2(J) and WvDir1(K) == WvDir2(K), because + ! if they are not, then the discretization along the two wave directions + ! is different and this won't work. + IF ( EqualRealNos( Data3D%WvDir1(J), Data3D%WvDir2(J) ) .AND. & + EqualRealNos( Data3D%WvDir1(K), Data3D%WvDir2(K) ) ) THEN + + ! Check if not filled + IF ( .NOT. Data3D%DataMask( I, J, K, L ) ) THEN + + ! See if the diagonal mirror one (WvDir2,WvDir1) value is not filled, + ! and fill it if empty + IF ( Data3D%DataMask( I, K, J, L ) ) THEN + Data3D%DataSet ( I, K, J, L ) = Data3D%DataSet( I, J, K, L ) + Data3D%DataMask( I, K, J, L ) = .TRUE. + ENDIF + ENDIF + ENDIF ! Check that wave directions will pair. + ENDIF + ENDDO + ENDDO + ENDDO + ENDIF + ENDDO ! Checking the wave directions for completeness. + + + !---------------------------------------------------------------------------------- + !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, + !! and added two frequencies for the infinite frequency term on the end of the array, + !! to create step changes outside the entered frequency ranges. We need to populate + !! the these new terms (set to zero). + !---------------------------------------------------------------------------------- + + IF (.NOT. HaveZeroFreq1) THEN + Data3D%DataSet( 1:2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range + Data3D%DataMask(1:2,:,:,:) = .TRUE. ! Set the mask for these first two frequencies + ENDIF + Data3D%DataSet( Data3D%NumWvFreq1-1:Data3D%NumWvFreq1,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) + Data3D%DataMask(Data3D%NumWvFreq1-1:Data3D%NumWvFreq1,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + + + !---------------------------------------------------------------------------------- + !> Find out if the data is sparse or full. Verification that the requested component + !! directions were found will occur in the calling routine, not here (that information + !! was not passed in). We will check this by sweeping through all three dimensions + !! for only the values of k that have data in them. + !---------------------------------------------------------------------------------- + + DO L=1,6 ! Loop over force component directions + TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found + IF (Data3D%LoadComponents(L)) THEN ! Only if we found data for that component + DO I=1,Data3D%NumWvFreq1 + DO J=1,Data3D%NumWvDir1 + DO K=1,Data3D%NumWvDir2 + IF (.NOT. Data3D%DataMask( I, J, K, L ) ) THEN + TmpSparseFlag = .TRUE. + ENDIF + ENDDO + ENDDO + ENDDO + ENDIF + + ! If any values were missing for this force component direction, TmpSparseFlag will be true. + Data3D%DataIsSparse(L) = TmpSparseFlag + + ENDDO ! Sparseness check + + !> In the MnDrift and NewmanApp calculations used in this module, the wave directions are + !! assigned as one direction per frequency. As a result, we will never have a situation + !! with these methods where we need two wave directions since they involve only a single + !! frequency. So, if multidirectional waves are used, both WvDir1 and WvDir2 will need to + !! be populated. According to the WAMIT theory guide (page 4-7), it is possible to calculate + !! the value of \f$ \bar{F}(\omega_n,\omega_m) = \bar{F}^*(\omega_m,\omega_n) \f$. + + + + ! Clean up + IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + + + END SUBROUTINE Read_DataFile3D + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine reads in the datafile containing 4D data (Omega1, Omega2, WaveDir1, WaveDir2), stores it to Data4D, and sets flags + !! indicating how complete the data is. + !! + !! The datafile is first scanned to make sure it is of the correct form, then read in in its entirety into a temporary matrix. + !! Then we find the number of unique frequencies and unique wave direction pairs that are in it, and create the necessary + !! data structures to hold all of it. Once this is done, we check for the infinite and zero frequency limits and add space + !! for them as needed. + !! + !! This matrix holding the data is read one line at a time and is placed into the correct location within the dataset. The mask + !! array is then marked to indicate valid data is at that coordinate index. + !! + !! Since the data may not contain the zero frequency and infinite frequency, we will create those values. For the zero frequency, + !! the QTF must be zero. For the infinite frequency, we use the value from the highest wave frequency (essentially flat response). + !! + !! At the end of all this, we check the data for completeness and set the flags accordingly. + !! + SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) + + IMPLICIT NONE + + ! Passed variables. + CHARACTER(*), INTENT(IN ) :: Filename4D !< Name of the file containing the 4D data + TYPE(W2_InitData4D_Type), INTENT(INOUT) :: Data4D !< 4D QTF data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error value + CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error. + + ! Local variables + INTEGER(IntKi) :: UnitDataFile !< The unit number for the currently open file + + INTEGER(IntKi) :: NumDataColumns !< Number of data columns in the file + INTEGER(IntKi) :: NumDataLines !< Total number of lines in the file (excluding first text line if there is one) + INTEGER(IntKi) :: NumDataLinesKeep !< Total number of lines in the file that are to be kept (positive force component index) + INTEGER(IntKi) :: NumHeaderLines !< Flag to indicate if the first line of the file is text + + ! Raw file data storage + REAL(SiKi), ALLOCATABLE :: RawData4D(:,:) !< The raw data from the entirety of the input file -- after removing negative force components + REAL(SiKi), ALLOCATABLE :: RawData4DTmp(:,:) !< The raw data from the entirety of the input file -- as read in + REAL(SiKi) :: HighFreq1 !< The highest frequency found. Needed for setting the infinite frequency data. + REAL(SiKi) :: HighFreq2 !< The highest frequency found. Needed for setting the infinite frequency data. + INTEGER(IntKi) :: WvFreq1HiIdx !< Index to the highest wave 1 frequency + INTEGER(IntKi) :: WvFreq1LoIdx !< Index to the lowest wave 1 frequency + INTEGER(IntKi) :: WvFreq2HiIdx !< Index to the highest wave 2 frequency + INTEGER(IntKi) :: WvFreq2LoIdx !< Index to the lowest wave 2 frequency + LOGICAL :: HaveZeroFreq1 !< Indicates we have a zer frequency value + LOGICAL :: HaveZeroFreq2 !< Indicates we have a zer frequency value + + + ! File reading variables + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + REAL(SiKi), ALLOCATABLE :: TmpRealArr(:) !< Temporary real array + REAL(SiKi), ALLOCATABLE :: TmpDataRow(:) !< Single row of data + REAL(SiKi), ALLOCATABLE :: TmpWvFreq1(:) !< Temporary array to hold the wave frequencies read in. + REAL(SiKi), ALLOCATABLE :: TmpWvFreq2(:) !< Temporary array to hold the wave frequencies read in. + + ! Temporary sparseness checking flag + LOGICAL :: TmpSparseFlag !< Temporary flag for checking sparseness + LOGICAL :: TmpDiagComplete !< Temporary flag for checking sparseness + + ! Generic counters + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + INTEGER(IntKi) :: L !< Generic counter + INTEGER(IntKi) :: M !< Generic counter + INTEGER(IntKi) :: TmpCoord(5) !< Temporary index coords to the Data4D matrix (4D + force dimension) + + ! Error handling temporary variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the local error status + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message variable + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + CHARACTER(*), PARAMETER :: RoutineName = 'Read_DataFile4D' + + + !> ## Subroutine Contents + + !-------------------------------------------------------------------------------- + !> Initialize variables + !-------------------------------------------------------------------------------- + + ! Initialize error variables + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + Data4D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. + HaveZeroFreq1 = .FALSE. ! If we find a zero frequency, we will set this to true + HaveZeroFreq2 = .FALSE. ! If we find a zero frequency, we will set this to true + + + !-------------------------------------------------------------------------------- + !> ### Check data file for consistency + !-------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------ + !> 4D data files are only used for cases of { SumQTF || DiffQTF } = { 10 || 11 || 12}\n + !! .10 files can contain all dimensions \n + !! .11 files can contain all dimensions \n + !! .12 files can contain all dimensions + !------------------------------------------------------------------------------ + + ! Find a unit number to use + CALL GetNewUnit(UnitDataFile,ErrStatTmp,ErrMsgTmp) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Open the file + CALL OpenFInpFile( UnitDataFile, TRIM(Filename4D), ErrStat, ErrMsg ) ! Open file containing mean drift information + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Do an initial readthrough and find out the length of the file, if there is a header line, and the number of columns in the file. + CALL GetFileLength( UnitDataFile, TRIM(Filename4D), NumDataColumns, NumDataLines, NumHeaderLines, ErrStat, ErrMsg) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + REWIND( UnitDataFile ) + + + + ! Make sure we have 9 columns of data in the data file. + IF ( NumDataColumns /= 9 ) THEN + CALL SetErrStat( ErrID_Fatal, ' The 2nd order WAMIT data file '//TRIM(Filename4D)//' has '//TRIM(Num2LStr(NumDataColumns))// & + ' columns instead of the 9 columns expected.', ErrStat, ErrMsg, RoutineName) + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + + !---------------------------------------------------------------------------------- + !> ### Read and store the raw data from the file. Convert all wave periods (s) into + !! frequency (rad/s) + !---------------------------------------------------------------------------------- + + ! Allocate the temporary array for reading in one line + CALL AllocAry( TmpDataRow, NumDataColumns, ' Array for holding one line of 4D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + + ! Allocate an array to hold the entirety of the raw contents of the file + CALL AllocAry( RawData4DTmp, NumDataLines, NumDataColumns, ' Array for holding raw 4D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Read and discard the header lines + DO I=1,NumHeaderLines + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + ENDDO + + ! Read in the data one line at a time and put it in RawData4D + DO I=1,NumDataLines + CALL ReadAry( UnitDataFile, TRIM(Filename4D), TmpDataRow, NumDataColumns, 'RawData4DTmp('//TRIM(Num2LStr(I))//',:)', & + ' Line '//TRIM(Num2LStr(NumHeaderLines+I))//' of '//TRIM(Filename4D), & + ErrStatTmp, ErrMsgTmp ) ! Note, not echoing this to anything. + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + RawData4DTmp(I,:) = TmpDataRow + ENDDO + + CLOSE( UnitDataFile ) + + + !> Before continuing, we need to figure out how many actual lines of data we will + !! be keeping (lines where the force component index is positive). The force component + !! is in column 5 for 4D data read in. First find out if there are negative force + !! components, then count the number of data rows we are keeping. Then copy data over. + IF ( MINVAL(RawData4DTmp(:,5)) < 0_IntKi ) THEN ! check the 5th element (force component) + CALL SetErrStat( ErrID_Warn,' Negative load components found (moving reference frame). Ignoring', & + ErrStat,ErrMsg,RoutineName) + + ! Count how many lines we are keeping. + NumDataLinesKeep = 0_IntKi + DO I=1,NumDataLines + IF ( RawData4DTmp(I,5) > 0 ) THEN + NumDataLinesKeep = NumDataLinesKeep + 1 + ENDIF + ENDDO + + ! Allocate an array to hold the data from the file that we are keeping + CALL AllocAry( RawData4D, NumDataLinesKeep, NumDataColumns, ' Array for holding raw 4D data for 2nd order WAMIT files', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnitDataFile ) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Now copy over the data that we are keeping. Ignore the rest + NumDataLinesKeep = 0_IntKi + DO I=1,NumDataLines + IF ( RawData4DTmp(I,5) > 0 ) THEN + NumDataLinesKeep = NumDataLinesKeep + 1 + RawData4D( NumDataLinesKeep, : ) = RawData4DTmp(I,:) + ENDIF + ENDDO + + ! We no longer need the raw data from the file. + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + + ! no negative force components, so just move the array. + ELSE + CALL MOVE_ALLOC( RawData4DTmp, RawData4D ) + NumDataLinesKeep = NumDataLines + ENDIF + + + !> Before proceeding further, we are going to change the wave period from measured + !! in seconds to a frequency measurement in _rad/s_. We will step through the data + !! matrix and convert the first two columns. + !! + !! Note that wave periods that are negative correspond to the \f$ \omega=0 \f$, and + !! wave periods with \f$ \tau=0 \f$ mean \f$ \omega=\infty \f$. Normally these + !! would not be calculated for sum and difference frequencies as there is little + !! information of interest there. + DO I=1,NumDataLinesKeep + IF ( EqualRealNos(RawData4D(I,1), 0.0_SiKi) ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE IF ( RawData4D(I,1) < 0 ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE + RawData4D(I,1) = TwoPi/RawData4D(I,1) ! First column is Tau1 + ENDIF + IF ( EqualRealNos(RawData4D(I,2), 0.0_SiKi) ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE IF ( RawData4D(I,2) < 0 ) THEN + ! Leave it alone. We will have to fix it afterwards. + ELSE + RawData4D(I,2) = TwoPi/RawData4D(I,2) ! First column is Tau2 + ENDIF + ENDDO + + ! Now we can fix the value for the frequency that was negative and set it to sligtly + ! larger than the largest value. First find the highest value. + HighFreq1 = MAXVAL(RawData4D(:,1)) + HighFreq2 = MAXVAL(RawData4D(:,2)) + + ! First change the values given as 0.0 to the infinite frequency and set a flag to indicate we + ! found an infinite frequency in this dimension + DO I=1,NumDataLinesKeep + IF ( EqualRealNos(RawData4D(I,1), 0.0_SiKi) ) THEN + RawData4D(I,1) = HighFreq1 * OnePlusEps + ENDIF + IF ( EqualRealNos(RawData4D(I,1), 0.0_SiKi) ) THEN + RawData4D(I,1) = HighFreq2 * OnePlusEps + ENDIF + ENDDO + + ! Now change the negative values to be 0.0 + DO I=1,NumDataLinesKeep + IF ( RawData4D(I,1) < 0.0_SiKi ) THEN + RawData4D(I,1) = 0.0_SiKi + HaveZeroFreq1 = .TRUE. + ENDIF + IF ( RawData4D(I,2) < 0.0_SiKi ) THEN + RawData4D(I,2) = 0.0_SiKi + HaveZeroFreq2 = .TRUE. + ENDIF + ENDDO + + + + !------------------------------------------------------------------------------------------- + !> ### Read through the file and find the number of WvFreq1, WaveDir1, WaveDir2. + !! + !! The 2nd order 4D files are arranged as follows: + !! Tau1, Beta1, Beta2, k, |F|, Phase, Real, Imaginary + !! where: + !! | Column | Variable | Units | Description | + !! | :----: | :-------------: | :-------------: | :-------------------------------- | + !! | 1 |\f$ \omega_1 \f$ | rad/s | Wave period 1 (converted above) | + !! | 2 |\f$ \omega_2 \f$ | rad/s | Wave period 2 (converted above) | + !! | 3 |\f$ \beta_1 \f$ | degrees | Wave direction 1 | + !! | 4 |\f$ \beta_2 \f$ | degrees | Wave direction 2 | + !! | 5 | k | -- | Force component direction (1-6) | + !! | 6 |\f$ |F| \f$ | Nondimensional | Magnitude of the force QTF | + !! | 7 | Phase | degrees | Phase of the force QTF | + !! | 8 |\f$ \Re(F) \f$ | Nondimensional | Real part of the force QTF | + !! | 9 |\f$ \Im(F) \f$ | Nondimensional | Imaginary part of the force QTF | + !! + !! Only columns 1, 2, 3, 4, 7, 8 are used. Columns 5 & 6 are redundant information. + !! + !---------------------------------------------------------------------------------- + + + !---------------------------------------------------------------------------------- + !> Read through the 4D data and figure out how many unique values in each dependent + !! variable (\f$ \omega_1, \omega_2, \beta_1, \beta_2,\f$ Component direction) exist + !! in the file. + !! + !! Allocate the necessary storage arrays when complete. + !---------------------------------------------------------------------------------- + + ! Get the number of first frequencies + CALL UniqueRealValues( RawData4D(:,1), TmpWvFreq1, Data4D%NumWvFreq1, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Get the number of second frequencies + CALL UniqueRealValues( RawData4D(:,2), TmpWvFreq2, Data4D%NumWvFreq2, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Get the number of first wave directions + CALL UniqueRealValues( RawData4D(:,3), Data4D%WvDir1, Data4D%NumWvDir1, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Get the number of second wave directions + CALL UniqueRealValues( RawData4D(:,4), Data4D%WvDir2, Data4D%NumWvDir2, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + ! Find out which load components are actually in use + CALL UniqueRealValues( RawData4D(:,5), TmpRealArr, K, ErrStatTmp,ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + + ! If the value of K is more than 6, we have some serious issues + IF ( K > 6 ) CALL SetErrStat( ErrID_Fatal, ' More than 6 load components found in column 4 of '// & + TRIM(Filename4D)//'.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Now check the values we got back and set the LoadComponents flags for those with data. The + ! load component direction must be between 1 and 6 (translational: 1,2,3; rotational: 4,5,6). + Data4D%LoadComponents = .FALSE. + DO I=1,K + IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Load components listed in column 4 of '//TRIM(Filename4D)// & + ' must be between 1 and 6.', ErrStat,ErrMsg,RoutineName) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + Data4D%LoadComponents(NINT(TmpRealArr(I))) = .TRUE. + ENDDO + + + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) ! Done with this, so throw it away. + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + + + ! Now we need to figure out if the zero frequency was given in the file. If so, we change NumWvFreq1 to + ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and + ! zero out all values not in the input frequency range. The inifinite frequency value will be set to HUGE + ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step + ! change for zeroing the values outside the input frequency range. + IF (HaveZeroFreq1) THEN + Data4D%NumWvFreq1 = Data4D%NumWvFreq1+2 + WvFreq1LoIdx = 1 + ELSE + Data4D%NumWvFreq1 = Data4D%NumWvFreq1+4 + WvFreq1LoIdx = 3 + ENDIF + + ! Set the index for the highest frequency stored before the cutoff + WvFreq1HiIdx = Data4D%NumWvFreq1-2 + + + ! Do the same for NumWvFreq2 as we did for NumWvFreq2 + IF (HaveZeroFreq2) THEN + Data4D%NumWvFreq2 = Data4D%NumWvFreq2+2 + WvFreq2LoIdx = 1 + ELSE + Data4D%NumWvFreq2 = Data4D%NumWvFreq2+4 + WvFreq2LoIdx = 3 + ENDIF + + ! Set the index for the highest frequency stored before the cutoff + WvFreq2HiIdx = Data4D%NumWvFreq2-2 + + + ! Now allocate the array for holding the WvFreq1 + ALLOCATE( Data4D%WvFreq1( Data4D%NumWvFreq1), STAT=ErrStatTmp) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data4D%WvFreq1 to store '// & + 'the sorted 4D 2nd order WAMIT frequency data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + + ! Now allocate the array for holding the WvFreq2 + ALLOCATE( Data4D%WvFreq2( Data4D%NumWvFreq2), STAT=ErrStatTmp) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data4D%WvFreq2 to store '// & + 'the sorted 4D 2nd order WAMIT frequency data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Populate the wave frequencies with what we read in + Data4D%WvFreq1( WvFreq1LoIdx:WvFreq1HiIdx ) = TmpWvFreq1 + + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + IF ( .NOT. HaveZeroFreq1) THEN + Data4D%WvFreq1( 1 ) = 0.0_SiKi + Data4D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing + ENDIF + + ! add the two points for step-change after last entered frequency + Data4D%WvFreq1( Data4D%NumWvFreq1-1 ) = Data4D%WvFreq1(Data4D%NumWvFreq1-2) + 10.0_SiKi*EPSILON(0.0_SiKi) + Data4D%WvFreq1( Data4D%NumWvFreq1 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant + + + + ! Populate the wave frequencies with what we read in + Data4D%WvFreq2( WvFreq2LoIdx:WvFreq2HiIdx ) = TmpWvFreq2 + + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + IF ( .NOT. HaveZeroFreq2) THEN + Data4D%WvFreq2( 1 ) = 0.0_SiKi + Data4D%WvFreq2( 2 ) = MAX( TmpWvFreq2(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing + ENDIF + + ! add the two points for step-change after last entered frequency + Data4D%WvFreq2( Data4D%NumWvFreq2-1 ) = Data4D%WvFreq2(Data4D%NumWvFreq2-2) + 10.0_SiKi*EPSILON(0.0_SiKi) + Data4D%WvFreq2( Data4D%NumWvFreq2 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant + + + ! Now that we know how many frequencies and wave directions there are, we can allocate the array + ! for saving the sorted data. + ALLOCATE( Data4D%DataSet( Data4D%NumWvFreq1, Data4D%NumWvFreq2, Data4D%NumWvDir1, Data4D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data4D%DataSet to store '// & + 'the sorted 4D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Allocate the logical array for storing the mask for which points are valid. Set to .FALSE. + ALLOCATE( Data4D%DataMask( Data4D%NumWvFreq1, Data4D%NumWvFreq2, Data4D%NumWvDir1, Data4D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data4D%DataMask to store '// & + 'the sorted 4D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + Data4D%DataMask = .FALSE. ! Populate this later + + + + !---------------------------------------------------------------------------------- + !> Now step through the raw data and place values in the correct final locations, + !! set the flag mask array, and calculate the conjugate pairs (4D only). + !! + !! The way this works is that the Data4D%WvFreq1, Data4D%WvFreq2, Data4D%WvDir1, and + !! Data4D%WaveDir2 contain the order frequencies and direction from the input file. + !! Therefore, the index numbers of these three arrays corresponds to the location in + !! Data4D%DataSet that holds the complex force QTF value for that frequency and wave + !! direction pair. + !! + !! So, to populate the Data4D%DataSet matrix, we simply have to read one line at a + !! time from the file (stored in RawData4D matrix), and place it in the corresponding + !! coordinate location in Data4D%DataSet. This involves simply searching through + !! the WvFreq1, WvFreq2, WvDir1, and WvDir2 arrays for the correct indices. + !! + !! The wave force component direction is stored slightly differently, so it only + !! needs to be read from the raw data and coverted into an integer to use as an + !! index. + !---------------------------------------------------------------------------------- + + + TmpCoord = 1 ! Initialize the search locations. + + DO I=1,NumDataLinesKeep + + ! Error checking: The LocateStp routine will return 0 if the requested value is less than the value + ! of the first element in the array. It will return the index of the last element + ! of the array if the value is larger than the last element. In creating the arrays + ! that are being searched here, the values that we are now trying to find the index + ! to were used. Therefore, if the requested value is not found in the array, then + ! something must have gone horribly wrong while creating it, or between then and now, + ! which is most likely a programming error. + + ! Find the location in the WvFreq1 array that this point corresponds to. We will check only between the + ! cutoffs that were added to the frequency range. This is contained within TmpWvFreq1 from reading in. + CALL LocateStp( RawData4D(I,1), TmpWvFreq1, TmpCoord(1), WvFreq1HiIdx - (WvFreq1LoIdx - 1) ) ! inclusive limits + IF ( TmpCoord(1) == 0 .OR. ( RawData4D(I,1) > Data4D%WvFreq1(Data4D%NumWvFreq1)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data4D%WvFreq1 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + TmpCoord(1) = TmpCoord(1) + ( WvFreq1LoIdx - 1 ) ! shift to the point in the Data3D%WvFreq1 array by adding the zero frequency step function + + ! Find the location in the WvFreq2 array that this point corresponds to. We will check only between the + ! cutoffs that were added to the frequency range. This is contained within TmpWvFreq2 from reading in. + CALL LocateStp( RawData4D(I,2), TmpWvFreq2, TmpCoord(2), WvFreq2HiIdx - (WvFreq2LoIdx - 1) ) ! inclusive limits + IF ( TmpCoord(2) == 0 .OR. ( RawData4D(I,2) > Data4D%WvFreq2(Data4D%NumWvFreq2)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data4D%WvFreq2 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + TmpCoord(2) = TmpCoord(2) + ( WvFreq2LoIdx - 1 ) ! shift to the point in the Data3D%WvFreq2 array by adding the zero frequency step function + + ! Find the location in the WvDir1 array that this point corresponds to. + CALL LocateStp( RawData4D(I,3), Data4D%WvDir1, TmpCoord(3), Data4D%NumWvDir1 ) + IF ( TmpCoord(3) == 0 .OR. ( RawData4D(I,3) > Data4D%WvDir1(Data4D%NumWvDir1)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data4D%WvDir1 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Find the location in the WvDir2 array that this point corresponds to. + CALL LocateStp( RawData4D(I,4), Data4D%WvDir2, TmpCoord(4), Data4D%NumWvDir2 ) + IF ( TmpCoord(4) == 0 .OR. ( RawData4D(I,4) > Data4D%WvDir2(Data4D%NumWvDir2)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming error. Array data point not found in Data4D%WvDir2 array.', ErrStat, ErrMsg, RoutineName) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + + ! Find which force component this belongs to + TmpCoord(5) = NINT(RawData4D(I,5)) + + + !> The data from the WAMIT file is non-dimensional, so we need to dimensionalize it here. This + !! is a partial dimensionalization since the wave amplitudes are not included (this is done later + !! in each of the calculation methods). To dimensionalize the data, the equation is for the + !! partially dimensionalized force (\f$ F_k \f$) is: + !! + !! \f$ F_k = \rho g \cdot L^\alpha \cdot \bar{F}_k \f$ + !! + !! where \f$ \bar{F}_k \f$ is the force QTF value in the file for the \f$ k \f$ component + !! direction, \f$ L \f$ is the WAMIT unit length _WAMITULEN_, \f$ \rho \f$ is the density of + !! water, and \f$ g \f$ is the gravitational constant (\f$ \rho g \f$ is combined as _RhoXg_). + !! The value of \f$ \alpha \f$ is 1 for \f$ k = 1,2,3 \f$ and 2 for \f$ k = 4,5,6 \f$. + + ! Here K is used for \f$ alpha \f$ in the dimensionalization equation. + IF ( TmpCoord(5) <=3 ) THEN + K = 1 + ELSE + K = 2 + ENDIF + + + ! Check that the current value has not been read in already. If it has, the corresponding + ! flag in the mask array will be set to true. This will indicate that there was redundant + ! data in the file. If the value agrees, we will politely ignore it without warning. If + ! it does not agree, then we will have to stop since it is ambiguous which is correct. + + IF ( Data4D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) ) THEN + IF ( .NOT. EqualRealNos( REAL(Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ),SiKi), & + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K * RawData4D(I,8) ,SiKi)) .AND. & + .NOT. EqualRealNos(AIMAG(Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) )), & + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K * RawData4D(I,9) ,SiKi))) THEN + CALL SetErrStat( ErrID_Fatal, ' Line '//TRIM(Num2Lstr(NumHeaderLines+I))//' of '//TRIM(Filename4D)// & + ' contains different values for the real and imaginary part (columns 8 and 9) than was '// & + 'given earlier in the file for the same values of wave frequency and wave direction.', & + ErrStat, ErrMsg, RoutineName ) + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + CALL CleanUp + RETURN + ENDIF + ELSE + + ! Store the data after dimensionalizing + Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = & + InitInp%RhoXg * InitInp%WAMITULEN**K * CMPLX(RawData4D(I,8),RawData4D(I,9)) + + ! Set flag indicating that this value has been inserted. + Data4D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = .TRUE. + + ENDIF + + !> There are relationships between F(Omega_m,Omega_n) and F(Omega_n,Omega_m) where F + !! resultant excitation force calculated above and stored in Data4D%DataSet. So, given + !! F(Omega_m,Omega_n), we can calculate F(Omega_n,Omega_m). WAMIT only calculates one + !! of these, so we must generate the other one (we could calculate them later when the + !! value is used, but that adds complexity that can be avoided by calculating it here). + !! + !! The flag Data4D%IsSumForce is set prior to the call to this routine. This dictates + !! which method we use. + !! + !! For sum forces: + !! \f$ \bar{F}^{+}(\omega_m,\omega_n) = \bar{F}^{+}(\omega_n,\omega_m) \f$ + !! + !! For difference forces: + !! \f$ \bar{F}^{-}(\omega_m,\omega_n) = \bar{F}^{- *}(\omega_n,\omega_m) \f$ + !! + !! where \f$ * \f$ indicates the complex conjugate + !! + !! @note For the special case where \f$ \omega_1 = \omega_2 \f$, there is a relationship + !! between the wave directions. Information on this is given in the WAMIT manual, + !! page 4-7: + !! + !! \f$ \bar{F}^{-}(\beta_m,\beta_n) = \bar{F}^{- *}(\beta_n,\beta_m) \f$ + !! + !! Be sure to note that this does not necessarily imply that: + !! \f$ \bar{F}^{-}(\omega_m,\omega_n,\beta_m,\beta_n) = \bar{F}^{-}(\omega_n,\omega_m,\beta_n,\beta_m) \f$ + !! when \f$ \omega_m \neq \omega_n \f$, + + + ! Check if the corresponding value has been filled in already or not. If not, check if + ! the value of the frequencies are compatible with each other (will not be true if the + ! stepsize in the frequencies is different). + IF ( .NOT. Data4D%DataMask( TmpCoord(2), TmpCoord(1), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) ) THEN + + ! Equal stepsize check + IF ( EqualRealNos( Data4D%WvFreq1(TmpCoord(1)), Data4D%WvFreq2(TmpCoord(1)) ) .AND. & + EqualRealNos( Data4D%WvFreq1(TmpCoord(1)), Data4D%WvFreq2(TmpCoord(1)) )) THEN + + ! Value not filled in and the frequencies correspond, so we will now fill it in based + ! on what type of data this is (sum or difference). + IF ( Data4D%IsSumForce ) THEN + Data4D%DataSet( TmpCoord(2), TmpCoord(1), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = & + Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) + ELSE ! Must be difference force, fill with complex conjugate + Data4D%DataSet( TmpCoord(2), TmpCoord(1), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = & + CONJG( Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) ) + ENDIF + + ! We filled in the value, so mark it as filled. + Data4D%DataMask( TmpCoord(2), TmpCoord(1), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = .TRUE. + ENDIF + ENDIF + + ! If we have the special case of being on the diagonal of the frequencies where omega_m=omega_n + ! then there is another rule we can apply to fill in missing values of the wave direction matrix + ! for this (omega_m,omega_m) pair. + IF ( EqualRealNos(Data4D%WvFreq1(TmpCoord(1)), Data4D%WvFreq2(TmpCoord(2))) ) THEN + ! Only wave direction elements not on the wave direction diagonal + IF ( .NOT. EqualRealNos( Data4D%WvDir1(TmpCoord(3)), Data4D%WvDir2(TmpCoord(4)) ) ) THEN + + ! See if WvDir1(J) == WvDir2(J) and WvDir1(K) == WvDir2(K), because + ! if they are not, then the discretization along the two wave directions + ! is different and this won't work. + IF ( EqualRealNos( Data4D%WvDir1(TmpCoord(3)), Data4D%WvDir2(TmpCoord(3)) ) .AND. & + EqualRealNos( Data4D%WvDir1(TmpCoord(4)), Data4D%WvDir2(TmpCoord(4)) ) ) THEN + + ! See if the diagonal mirror one (WvDir2,WvDir1) value is not filled, set it and its flag + IF ( .NOT. Data4D%DataMask(TmpCoord(1), TmpCoord(2), TmpCoord(4), TmpCoord(3), TmpCoord(5)) ) THEN + Data4D%DataSet(TmpCoord(1), TmpCoord(2), TmpCoord(4), TmpCoord(3), TmpCoord(5) ) = & + Data4D%DataSet(TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(3), TmpCoord(5) ) + Data4D%DataMask(TmpCoord(1), TmpCoord(2), TmpCoord(4), TmpCoord(3), TmpCoord(5) ) = .TRUE. + ENDIF + + ENDIF ! Check that wave directions will pair. + + ENDIF + + ENDIF ! WvFreq1(TmpCoord(1)) == WvFreq2(TmpCoord(2)) + + + + ENDDO + + + !---------------------------------------------------------------------------------- + !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, + !! and added two frequencies for the infinite frequency term on the end of the array, + !! to create step changes outside the entered frequency ranges. We need to populate + !! the these new terms (set to zero). + !---------------------------------------------------------------------------------- + + IF (.NOT. HaveZeroFreq1) THEN + Data4D%DataSet( 1:2,:,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range + Data4D%DataMask(1:2,:,:,:,:) = .TRUE. ! Set the mask for these first two frequencies + ENDIF + Data4D%DataSet( Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) + Data4D%DataMask(Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + + IF (.NOT. HaveZeroFreq2) THEN + Data4D%DataSet( :,1:2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range + Data4D%DataMask(:,1:2,:,:,:) = .TRUE. ! Set the mask for these first two frequencies + ENDIF + Data4D%DataSet( :,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) + Data4D%DataMask(:,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + + + !---------------------------------------------------------------------------------- + !> Find out if the data is sparse or full. Verification that the requested component + !! directions were found will occur in the calling routine, not here (that information + !! was not passed in). We will check this by sweeping through all three dimensions + !! for only the values of k that have data in them. + !---------------------------------------------------------------------------------- + + DO M=1,6 ! Loop over force component directions + TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found + IF (Data4D%LoadComponents(M)) THEN ! Only if we found data for that component + DO I=1,Data4D%NumWvFreq1 + DO J=1,Data4D%NumWvFreq2 + DO K=1,Data4D%NumWvDir1 + DO L=1,Data4D%NumWvDir2 + IF (.NOT. Data4D%DataMask( I, J, K, L, M ) ) THEN + TmpSparseFlag = .TRUE. + ENDIF + ENDDO + ENDDO + ENDDO + + ENDDO + ENDIF + + ! If any values were missing for this force component direction, TmpSparseFlag will be true. + Data4D%DataIsSparse(M) = TmpSparseFlag + + ENDDO + + + + !---------------------------------------------------------------------------------- + !> If the data is sparse, it may still have a complete diagonal. This is worth + !! checking in case this data is used for either the MnDrift or NewmanApp methods. + !! + !! Diagonal terms: Elements where the first wave frequency and second wave frequency match. + !! For the diagonal to be complete, we require all the wave direction + !! pairs for \f$ \omega_m = \omega_n \f$ to be complete. + !! + !! NOTE: In the 3D WAMIT files, only the diagonal terms Omega_m = Omega_m are given. In + !! the 4D files, the off diagonal terms are also listed. For calculations that involve the + !! full QTF (such as DiffQTF and SumQTF), the data must be complete to use a normal + !! interpolation routine (may be sparse if a sparse interpolation routine is developed). + !! For the MnDrift and NewmanApp calculations, incomplete 4D QTFs may be used if the + !! diagonal is complete. So, we will do some additional testing on the 4D data to make + !! sure that the diagonal is complete. This will allow the data to be used easily with + !! the MnDrift and NewmanApp. + !! + !! We will only be considering this for the load components requested. Only if all the + !! requested component diagonals are complete will we consider it complete. + !! + !! One consideration worth noting is that the diagonal may not be present in a complete + !! dataset. This would occur if the stepsize in \f$ \omega_1 \f$ and \f$ \omega_2 \f$ are + !! different. + !---------------------------------------------------------------------------------- + + TmpDiagComplete = .TRUE. ! Change this to false if any empty values are found + + ! If the number of frequencies differ, than this won't work. + IF (Data4D%NumWvFreq1 /= Data4D%NumWvFreq2) THEN + TmpDiagComplete = .FALSE. + ELSE ! Same number of frequencies, so we can proceed. + DO M=1,6 ! Loop over force component directions + ! If we have data for this component, and it is sparse, proceed to check it. + IF (Data4D%LoadComponents(M) .AND. Data4D%DataIsSparse(M)) THEN + + ! Step through all the components + DO I=1,Data4D%NumWvFreq1 + ! Make sure the frequencies actually match + IF ( EqualRealNos(Data4D%WvFreq1(I),Data4D%WvFreq2(I)) ) THEN + DO K=1,Data4D%NumWvDir1 + DO L=1,Data4D%NumWvDir2 + IF (.NOT. Data4D%DataMask( I, I, K, L, M ) ) THEN + TmpDiagComplete = .FALSE. ! If any of the elements are missing + ENDIF + ENDDO + ENDDO + ELSE ! Frequencies don't match, so this won't work. + TmpDiagComplete = .FALSE. + ENDIF + ENDDO ! NumWvFreq1 + + ENDIF ! Sparse load component of interest + ENDDO ! Loop over load components + ENDIF + + Data4D%WvFreqDiagComplete = TmpDiagComplete + + + + ! Clean up + IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) + IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) + + END SUBROUTINE Read_DataFile4D + + + + + + + !> This subroutine counts the number of uniqe values in an array and returns a sorted array of them. + !! This is called by the _Read_DataFile3D_ and _Read_DataFile4D_ routines. + SUBROUTINE UniqueRealValues( DataArrayIn, DataArrayOut, NumUnique, ErrStat, ErrMsg ) + IMPLICIT NONE + + REAL(SiKi), INTENT(IN ) :: DataArrayIn(:) !< Array to search + REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: DataArrayOut(:) !< Array to return results in + INTEGER(IntKi), INTENT( OUT) :: NumUnique !< Number of unique values found + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error Status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about the error + + ! Local variables + REAL(SiKi) :: TmpReal !< Temporary real value + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + REAL(SiKi), ALLOCATABLE :: TmpRealArray(:) !< Temporary real array + LOGICAL :: Duplicate !< If there is a duplicate value + + ! Error handling + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + CHARACTER(*), PARAMETER :: RoutineName = 'UniqueRealValues' + + + + ! Initialize things + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + + ! Allocate the temporary array + CALL AllocAry( TmpRealArray, SIZE(DataArrayIn,1), 'Temporary array for data sorting', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + ! Initialize the array with a large negative number. Only positive frequencies and wave directions from + ! +/-180 degrees should ever be sent here. The way this algorithm works, only empty values will have + ! this number. We won't be returning it to the calling routine + TmpRealArray = -9.9e9_SiKi + + + ! The first point is unique since we haven't compared it to anything yet. + TmpRealArray(1) = DataArrayIn(1) + NumUnique = 1 + + ! Step through the DataArrayIn and put unique values into TmpRealArray. Start at second point + DO I=2,SIZE(DataArrayIn,1) + ! Check the current value against the largest stored value (I-1). If the current value is + ! larger than the last stored one, then it should be stored after it. + IF ( DataArrayIn(I) > TmpRealArray(NumUnique) ) THEN + TmpRealArray(NumUnique + 1) = DataArrayIn(I) + NumUnique = NumUnique + 1 + ELSE + ! Otherwise, if the value should not be put last, then we have to find where it goes. Before + ! searching for the location, first make sure this isn't a duplicate value. + Duplicate = .FALSE. + DO J= NumUnique, 1, -1 + IF ( EqualRealNos( DataArrayIn(I), TmpRealArray(J) )) THEN + Duplicate = .TRUE. + EXIT ! Stop searching + ENDIF + ENDDO + + + ! If this is not a duplicate, the location where it goes has to be find. To do this, we will + ! sequentially shift each value one index further as we step backwards through the sorted + ! array. When we find the location between values where this goes, we put the value there. + IF ( .NOT. Duplicate ) THEN + DO J= NumUnique, 1, -1 ! TempRealArray only has NumUnique values. Everything after is junk. + IF ( DataArrayIn(I) < TmpRealArray(J) ) THEN + TmpRealArray(J+1) = TmpRealArray(J) ! Shift this value further along the array + IF ( J == 1 ) THEN ! If we are at the first value, then it goes here. + TmpRealArray(J) = DataArrayIn(I) + NumUnique = NumUnique + 1 + ELSE + IF ( DataArrayIn(I) > TmpRealArray(J-1) ) THEN ! If larger than the preceeding number, it goes here + TmpRealArray(J) = DataArrayIn(I) + NumUnique = NumUnique + 1 + ENDIF + ENDIF + ENDIF + ENDDO + ENDIF + ENDIF + ENDDO + + + ! Now that we have the array sorted into unique values, we need to construct an array to return the values in. + CALL AllocAry( DataArrayOut, NumUnique, 'Return array with sorted values', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + + ! Copy the values over + DataArrayOut = TmpRealArray(1:NumUnique) + + + END SUBROUTINE UniqueRealValues + + + + + + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine looks at a file that has been opened and finds out how many header lines there are, how many periods + !! (frequencies) there are (first only if there are paired periods for second order), and how many lines of data there are in + !! the file. + !! + !! A few things are assumed about the file: + !! 1. Any header lines are the first thing in the file. + !! 2. No text appears anyplace other than in the file + !! 3. The datalines only contain numbers that can be read in as reals. + !! + !! Limitations: + !! 1. only handles up to 20 words (columns) on a line + !! 2. empty lines are considered text lines + !! 3. All data rows must contain the same number of columns + !! + !! + SUBROUTINE GetFileLength(UnitDataFile, Filename, NumDataColumns, NumDataLines, NumHeaderLines, ErrStat, ErrMsg) + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: UnitDataFile !< Unit number of the file we are looking at. + CHARACTER(*), INTENT(IN ) :: Filename !< The name of the file we are looking at. + INTEGER(IntKi), INTENT( OUT) :: NumDataColumns !< The number of columns in the data file. + INTEGER(IntKi), INTENT( OUT) :: NumDataLines !< Number of lines containing data + INTEGER(IntKi), INTENT( OUT) :: NumHeaderLines !< Number of header lines at the start of the file + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error Message to return (empty if all good) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Status flag if there were any problems (ErrID_None if all good) + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary message variable. Used in calls. + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status. Used in calls. + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + INTEGER(IntKi) :: TmpIOErrStat !< Temporary error status for the internal read of the first word to a real number + LOGICAL :: IsRealNum !< Flag indicating if the first word on the line was a real number + + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + CHARACTER(1024) :: StrRead !< String containing the first word read in + REAL(SiKi) :: RealRead !< Returns value of the number (if there was one), or NaN (as set by NWTC_Num) if there wasn't + CHARACTER(1024) :: VarName !< Name of the variable we are trying to read from the file + CHARACTER(24) :: Words(20) !< Array of words we extract from a line. We shouldn't have more than 20. + INTEGER(IntKi) :: i,j,k !< simple integer counters + INTEGER(IntKi) :: LineNumber !< the line I am on + LOGICAL :: LineHasText !< Flag indicating if the line I just read has text. If so, it is a header line. + LOGICAL :: HaveReadData !< Flag indicating if I have started reading data. + INTEGER(IntKi) :: NumWords !< Number of words on a line + INTEGER(IntKi) :: FirstDataLineNum !< Line number of the first row of data in the file + CHARACTER(*), PARAMETER :: RoutineName = 'GetFileLength' + + + + ! Initialize the error handling + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + LclErrStat = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + + ! Set some of the flags and counters + HaveReadData = .FALSE. + NumDataColumns = 0 + NumHeaderLines = 0 + NumDataLines = 0 + LineNumber = 0 + + + ! Just in case we were handed a file that we are part way through reading (should never be true), rewind to the start + + REWIND( UnitDataFile ) + + + !------------------------------------ + !> The variable LclErrStat is used to indicate when we have reached the end of the file or had an error from + !! ReadLine. Until that occurs, we read each line, and decide if it contained any non-numeric data. The + !! first group of lines containing non-numeric data is considered the header. The first line of all numeric + !! data is considered the start of the data section. Any non-numeric containing found within the data section + !! will be considered as an invalid file format at which point we will return a fatal error from this routine. + + DO WHILE ( LclErrStat == ErrID_None ) + + !> Reset the indicator flag for the non-numeric content + LineHasText = .FALSE. + + !> Read in a single line from the file + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + + !> If there was an error in reading the file, then exit. + !! Possible causes: reading beyond end of file in which case we are done so don't process it. + IF ( LclErrStat /= ErrID_None ) EXIT + + !> Increment the line counter. + LineNumber = LineNumber + 1 + + !> Read all the words on the line into the array called 'Words'. Only the first words will be encountered + !! will be stored. The others are empty (i.e. only three words on the line, so the remaining 17 are empty). + CALL GetWords( TextLine, Words, 20 ) + + !> Cycle through and count how many are not empty. Once an empty value is encountered, all the rest should + !! be empty if GetWords worked correctly. The index of the last non-empty value is stored. + DO i=1,20 + IF (TRIM(Words(i)) .ne. '') NumWords=i + ENDDO + + + !> Now cycle through the first 'NumWords' of non-empty values stored in 'Words'. Words should contain + !! everything that is one the line. The subroutine ReadRealNumberFromString will set a flag 'IsRealNum' + !! when the value in Words(i) can be read as a real(SiKi). 'StrRead' will contain the string equivalent. + DO i=1,NumWords + CALL ReadRealNumberFromString( Words(i), RealRead, StrRead, IsRealNum, ErrStatTmp, ErrMsgTmp, TmpIOErrStat ) + IF ( .NOT. IsRealNum) THEN + LineHasText = .TRUE. + ENDIF + ENDDO + + !> If all the words on that line had no text in them, then it must have been a line of data. + !! If not, then we have either a header line, which is ok, or a line containing text in the middle of the + !! the data section, which is not good (the flag HaveReadData tells us which case this is). + IF ( LineHasText ) THEN + IF ( HaveReadData ) THEN ! Uh oh, we have already read a line of data before now, so there is a problem + CALL SetErrStat( ErrID_Fatal, ' Found text on line '//TRIM(Num2LStr(LineNumber))//' of '//TRIM(FileName)// & + ' when real numbers were expected. There may be a problem with the 2nd order WAMIT file: '// & + TRIM(Filename)//'.', ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ELSE + NumHeaderLines = NumHeaderLines + 1 + ENDIF + ELSE ! No text, must be data line + NumDataLines = NumDataLines + 1 + ! If this is the first row of data, then store the number of words that were on the line + IF ( .NOT. HaveReadData ) THEN + ! If this is the first line of data, keep some relevant info about it and the number of columns in it + HaveReadData = .TRUE. + FirstDataLineNum = LineNumber ! Keep the line number of the first row of data (for error reporting) + NumDataColumns = NumWords + ELSE + ! Make sure that the number columns on the row matches the number of columnns on the first row of data. + IF ( NumWords /= NumDataColumns ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error in 2nd order WAMIT file: '//TRIM(Filename)//'.'// & + ' The number of data columns on line '//TRIM(Num2LStr(LineNumber))// & + '('//TRIM(Num2LStr(NumWords))//' columns) is different than the number of columns on first row of data '// & + ' (line: '//TRIM(Num2LStr(FirstDataLineNum))//', '//TRIM(Num2LStr(NumDataColumns))//' columns).', & + ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + ENDIF + ENDIF + + ENDDO + + IF ( NumDataLines < 2 ) THEN + CALL SetErrStat( ErrID_Fatal, ' 2nd order WAMIT file '//TRIM(Filename)//' contains only '//TRIM(Num2LStr(NumDataLines))// & + ' lines of data. This does not appear to be a valid WAMIT file.', ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + ENDIF + ENDIF + + REWIND( UnitDataFile ) + + END SUBROUTINE GetFileLength + + !------------------------------------------------------------------------------- + !> This subroutine takes a line of text that is passed in and reads the first + !! word to see if it is a number. An internal read is used to do this. If + !! it is a number, it is started in ValueRead and returned. The flag IsRealNum + !! is set to true. Otherwise, ValueRead is set to NaN (value from the NWTC_Num) + !! and the flag is set to false. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (IsRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + CHARACTER(*), INTENT(IN ) :: StringToParse !< The string we were handed. + REAL(SiKi), INTENT( OUT) :: ValueRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StringToParse,*,IOSTAT=IOErrStat) StrRead + read(StringToParse,*,IOSTAT=IOErrStat) ValueRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + ValueRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrSTat = ErrID_Severe + endif + + + + RETURN + END SUBROUTINE ReadRealNumberFromString + + + !------------------------------------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + !> This subroutine works with the ReadNum routine from the library. ReadNum is + !! called to read a word from the input file. An internal read is then done to + !! convert the string to a number that is stored in VarRead and returned. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (ISRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumber(UnitNum, FileName, VarName, VarRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + INTEGER(IntKi), INTENT(IN ) :: UnitNum !< The unit number of the file being read + CHARACTER(*), INTENT(IN ) :: FileName !< The name of the file being read. Used in the ErrMsg from ReadNum (Library routine). + CHARACTER(*), INTENT(IN ) :: VarName !< The variable we are reading. Used in the ErrMsg from ReadNum (Library routine)'. + REAL(SiKi), INTENT( OUT) :: VarRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + ! Local vars + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! Now call the ReadNum routine to get the number + ! If it is a word that does not start with T or F, then ReadNum won't give any errors. + CALL ReadNum( UnitNum, FileName, StrRead, VarName, ErrStatTmp, ErrMsgTmp) + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StrRead,*,IOSTAT=IOErrStat) VarRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + VarRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrStat = ErrStatTmp ! The ErrStatTmp returned by the ReadNum routine is an ErrID level. + endif + + + + RETURN + END SUBROUTINE ReadRealNumber + + + + + +END SUBROUTINE WAMIT2_Init + + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. The purpose of this routine is to destroy any data that is leftover. If +!! we don't do this, we may leave memory tied up after the simulation ends. +!! To destroy the data, we call several routines that are generated by the FAST registry, so any issues with the destroy routines +!! should be addressed by the registry.exe which generates the WAMIT2_Types.f90 file. +!! +SUBROUTINE WAMIT2_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(WAMIT2_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(WAMIT2_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(WAMIT2_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(WAMIT2_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(WAMIT2_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 + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Place any last minute operations or calculations here. For WAMIT2, most calculations are performed + !! during the initialization, so there are no final calculations that need to be performed. + + + !> Close files here. The only files that are opened for WAMIT2 take place during the initialization routine. They should + !! have been closed then. + !! @todo Check to make sure nothing is left open by this module. + + + !> Destroy the input data: + + CALL WAMIT2_DestroyInput( u, ErrStat, ErrMsg ) + + + !> Destroy the parameter data: + + CALL WAMIT2_DestroyParam( p, ErrStat, ErrMsg ) + + + !> Destroy the state data: + + CALL WAMIT2_DestroyContState( x, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL WAMIT2_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + !> Destroy the output data: + + CALL WAMIT2_DestroyOutput( y, ErrStat, ErrMsg ) + + +END SUBROUTINE WAMIT2_End + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!> Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE WAMIT2_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(WAMIT2_InputType), INTENT(IN ) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !!Output: Continuous states at t + Interval + TYPE(WAMIT2_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !!Output: Discrete states at t + Interval + TYPE(WAMIT2_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !!Output: Constraint states at t + Interval + TYPE(WAMIT2_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(WAMIT2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + +END SUBROUTINE WAMIT2_UpdateStates + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE WAMIT2_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT2_OtherStateType), INTENT(IN ) :: OtherState !< Other states + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh + !! connectivity information does not have to be recalculated) + TYPE(WAMIT2_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 + + + + ! Local Variables: + INTEGER(IntKi) :: I ! Generic index +! INTEGER(IntKi) :: J ! Generic index +! INTEGER(IntKi) :: K ! Generic index + REAL(ReKi) :: AllOuts(MaxWAMIT2Outputs) + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + + ! Abort if the wave excitation loads have not been computed yet: + + IF ( .NOT. ALLOCATED ( p%WaveExctn2 ) ) THEN + CALL SetErrStat(ErrID_Fatal,' Routine WAMIT2_Init() must be called before routine WAMIT2_CalcOutput().',ErrStat,ErrMsg,'WAMIT2_CalcOutput') + RETURN + END IF + + + + ! Compute the 2nd order load contribution from incident waves: + + DO I = 1,6 ! Loop through all wave excitation forces and moments + m%F_Waves2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveExctn2(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + END DO ! I - All wave excitation forces and moments + + + + ! Copy results to the output point mesh + DO I=1,3 + y%Mesh%Force(I,1) = m%F_Waves2(I) + END DO + DO I=1,3 + y%Mesh%Moment(I,1) = m%F_Waves2(I+3) + END DO + + + + ! Map the calculated results into the AllOuts Array + CALL WMT2Out_MapOutputs(Time, y, m%F_Waves2, AllOuts, ErrStat, ErrMsg) + + + + ! Put the output data in the OutData array + DO I = 1,p%NumOuts + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + END DO + + +END SUBROUTINE WAMIT2_CalcOutput + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this routine calculates the derivative of the continuous states. +!! As this routine is not necessary in the WAMIT2 module, it simply issues a warning and returns. +!! @note A few values will be set so that compilers are happy, but nothing of value is done. +SUBROUTINE WAMIT2_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(WAMIT2_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(WAMIT2_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 + + ErrStat = ErrID_None + ErrMsg = "Warning: No States to take derivative of in WAMIT2 module. *WAMIT2::CalcContStateDeriv was called. It "// & + "is not necessary in the WAMIT2 module, so it does nothing.*" + + + ! Compute the first time derivatives of the continuous states here: None to calculate, so no code here. + + ! Dummy output value for dxdt -- this is only here to prevent the compiler from complaining. + dxdt%DummyContState = 0.0_SiKi + + +END SUBROUTINE WAMIT2_CalcContStateDeriv + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this routine is used to update discrete states, by +!! So, this routine will simply issue a warning and return. +SUBROUTINE WAMIT2_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(WAMIT2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT2_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(WAMIT2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(WAMIT2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(WAMIT2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "Warning: No Discrete States to update in WAMIT2 module. *WAMIT2::UpdateDiscState was called. It is not "// & + "necessary in the WAMIT2 module, so it does nothing.*" + + ! Code to update the discrete states would live here, but there are no discrete states to update, hence no code. + + +END SUBROUTINE WAMIT2_UpdateDiscState + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this is a tight coupling routine for solving for the residual of the constraint state equations +!! So, this routine will simply issue a warning and return. +!! @note A few values will be set so that compilers are happy, but nothing of value is done. +SUBROUTINE WAMIT2_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(WAMIT2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(WAMIT2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(WAMIT2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(WAMIT2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(WAMIT2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(WAMIT2_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(WAMIT2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "Warning: No States in WAMIT2 module. *WAMIT2::CalcConstrStateResidual was called. It is not needed in "//& + "the WAMIT2 module, so it does nothing useful." + + + + ! Solve for the constraint states here: Since there are no constraint states to solve for in WAMIT2, there is no code here. + + z_residual%DummyConstrState = 0.0_SiKi ! This exists just so that we can make the compiler happy. + +END SUBROUTINE WAMIT2_CalcConstrStateResidual + + + +!------------------------------------------------------------------------------- +!> This subroutine copies data stored from a W2_InitData4D_Type to a W2_InitData3D_Type +SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) + IMPLICIT NONE + + TYPE(W2_InitData4D_Type), INTENT(IN ) :: Data4D !< 4D data source + TYPE(W2_InitData3D_Type), INTENT(INOUT) :: Data3D !< 3D data where it will be copied to + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! Local variables + LOGICAL :: TmpSparseFlag !< Flag to indicate if the data is sparse + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: K !< Generic counter + INTEGER(IntKi) :: L !< Generic counter + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + + + ! Initialize the error handling + ErrStat = ErrID_none + ErrStatTmp = ErrID_none + ErrMsg = '' + ErrMsgTmp = '' + + + ! Make sure we aren't trying to copy 4D sum frequency data in to a 3D type that only holds information for difference frequencies + IF ( Data4D%IsSumForce ) THEN + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D sum-frequency data into a 3D difference frequency type.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + RETURN + ENDIF + + ! Make sure the dimensions work + IF ( Data4D%NumWvFreq1 /= Data4D%NumWvFreq2 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when NumFreq1 /= NumFreq2.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + RETURN + ENDIF + + ! Make sure that the frequencies actually match each other + DO I=1,Data4D%NumWvFreq1 + IF ( .NOT. EqualRealNos(Data4D%WvFreq1(I), Data4D%WvFreq2(I)) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when wave frequencies are not the same.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + RETURN + ENDIF + ENDDO + + + ! Make sure that nothing has been allocated already + ErrStatTmp = ErrID_None + IF (ALLOCATED(Data3D%DataSet)) ErrStatTmp = ErrID_Fatal + IF (ALLOCATED(Data3D%DataMask)) ErrStatTmp = ErrID_Fatal + IF (ALLOCATED(Data3D%WvFreq1)) ErrStatTmp = ErrID_Fatal + IF (ALLOCATED(Data3D%WvDir1)) ErrStatTmp = ErrID_Fatal + IF (ALLOCATED(Data3D%WvDir2)) ErrStatTmp = ErrID_Fatal + IF ( ErrStatTmp >= ErrID_Fatal ) THEN + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data into a populated 3D dataset.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + ENDIF + + + + ! Ok. It checks out, so start copying info over + Data3D%NumWvFreq1 = Data4D%NumWvFreq1 + Data3D%NumWvDir1 = Data4D%NumWvDir1 + Data3D%NumWvDir2 = Data4D%NumWvDir2 + Data3D%LoadComponents = Data4D%LoadComponents + + + ! Now allocate the storage arrays + ALLOCATE( Data3D%DataSet( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataSet to store '// & + 'the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,'Copy_InitData4Dto3D') + ALLOCATE( Data3D%DataMask( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataMask to store '// & + 'the information on the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,'Copy_InitData4Dto3D') + CALL AllocAry( Data3D%WvFreq1, Data3D%NumWvFreq1, 'Data3D WvFreq array', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + CALL AllocAry( Data3D%WvDir1, Data3D%NumWvDir1, 'Data3D WvDir1 array', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + CALL AllocAry( Data3D%WvDir2, Data3D%NumWvDir2, 'Data3D WvDir2 array', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL Destroy_InitData3D( Data3D ) + RETURN + ENDIF + + + ! Copy the values over + Data3D%WvFreq1 = Data4D%WvFreq1 + Data3D%WvDir1 = Data4D%WvDir1 + Data3D%WvDir2 = Data4D%WvDir2 + + DO I=1,Data3D%NumWvFreq1 + Data3D%DataSet(I,:,:,:) = Data4D%DataSet(I,I,:,:,:) + Data3D%DataMask(I,:,:,:) = Data4D%DataMask(I,I,:,:,:) + ENDDO + + + !---------------------------------------------------------------------------------- + !> This routine should not have been called unless the data could be copied over, + !! which means that the 4D data is either not sparse in the dimensions of interest, + !! or the diagonal is complete. We won't simply trust that this is true though, so + !! we will run the array and find out if the data we now have is sparse for the + !! load components we have or not. + !! + !! Find out if the data is sparse or full. Verification that the requested component + !! directions were found will occur in the calling routine, not here (that information + !! was not passed in). We will check this by sweeping through all three dimensions + !! for only the values of k that have data in them. + !---------------------------------------------------------------------------------- + + DO L=1,6 ! Loop over force component directions + TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found + IF (Data3D%LoadComponents(L)) THEN ! Only if we found data for that component + DO I=1,Data3D%NumWvFreq1 + DO J=1,Data3D%NumWvDir1 + DO K=1,Data3D%NumWvDir2 + IF (.NOT. Data3D%DataMask( I, J, K, L ) ) THEN + TmpSparseFlag = .TRUE. + ENDIF + ENDDO + ENDDO + ENDDO + ENDIF + + ! If any values were missing for this force component direction, TmpSparseFlag will be true. + Data3D%DataIsSparse(L) = TmpSparseFlag + + ENDDO ! Sparseness check + + + ! Cleanup. Well, nothing here to cleanup. + +END SUBROUTINE Copy_InitData4Dto3D + + + +!> This subroutine destroys data stored in a W2_InitData3D_Type +SUBROUTINE Destroy_InitData3D(Data3D) + IMPLICIT NONE + TYPE(W2_InitData3D_Type), INTENT(INOUT) :: Data3D + INTEGER(IntKi) :: ErrStatTmp + IF (ALLOCATED(Data3D%DataSet)) DEALLOCATE(Data3D%DataSet,STAT=ErrStatTmp) + IF (ALLOCATED(Data3D%DataMask)) DEALLOCATE(Data3D%DataMask,STAT=ErrStatTmp) + IF (ALLOCATED(Data3D%WvFreq1)) DEALLOCATE(Data3D%WvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(Data3D%WvDir1)) DEALLOCATE(Data3D%WvDir1,STAT=ErrStatTmp) + IF (ALLOCATED(Data3D%WvDir2)) DEALLOCATE(Data3D%WvDir2,STAT=ErrStatTmp) +END SUBROUTINE Destroy_InitData3D + + +!> This subroutine destroys data stored in a W2_InitData4D_Type +SUBROUTINE Destroy_InitData4D(Data4D) + IMPLICIT NONE + TYPE(W2_InitData4D_Type), INTENT(INOUT) :: Data4D + INTEGER(IntKi) :: ErrStatTmp + IF (ALLOCATED(Data4D%DataSet)) DEALLOCATE(Data4D%DataSet,STAT=ErrStatTmp) + IF (ALLOCATED(Data4D%DataMask)) DEALLOCATE(Data4D%DataMask,STAT=ErrStatTmp) + IF (ALLOCATED(Data4D%WvFreq1)) DEALLOCATE(Data4D%WvFreq1,STAT=ErrStatTmp) + IF (ALLOCATED(Data4D%WvFreq2)) DEALLOCATE(Data4D%WvFreq2,STAT=ErrStatTmp) + IF (ALLOCATED(Data4D%WvDir1)) DEALLOCATE(Data4D%WvDir1,STAT=ErrStatTmp) + IF (ALLOCATED(Data4D%WvDir2)) DEALLOCATE(Data4D%WvDir2,STAT=ErrStatTmp) +END SUBROUTINE Destroy_InitData4D + + +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE WAMIT2 +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT2.txt b/OpenFAST/modules/hydrodyn/src/WAMIT2.txt new file mode 100644 index 000000000..4226c37ca --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT2.txt @@ -0,0 +1,145 @@ +################################################################################################################################### +# Registry for WAMIT2 in the FAST Modularization Framework +# This Registry file is used to create MODULE WAMIT2 which contains all of the user-defined types needed in WAMIT2. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +param WAMIT2/WAMIT2 unused INTEGER MaxWAMIT2Outputs - 6 - "" - + +#InitInputType -- used for passing stuff into the Init routine. +typedef WAMIT2/WAMIT2 InitInputType LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - +typedef ^ ^ CHARACTER(1024) WAMITFile - - - "Root of the filename for WAMIT2 outputs" - +typedef ^ ^ INTEGER UnSum - - - "The unit number for the HydroDyn summary file" - + +typedef ^ ^ ReKi WAMITULEN - - - "WAMIT unit length scale" - +typedef ^ ^ ReKi RhoXg - - - "Density * Gravity -- from the Waves module." - +typedef ^ ^ INTEGER NStepWave - - - "Total number of frequency components = total number of time steps in the incident wave" - +typedef ^ ^ INTEGER NStepWave2 - - - "NStepWave / 2" - +typedef ^ ^ ReKi WaveDOmega - - - "Frequency step for incident wave calculations" (rad/s) +typedef ^ ^ ReKi WtrDens - - - "Water density" (kg/m^3) + +typedef ^ ^ SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) +typedef ^ ^ SiKi WaveDir - - - "Mean incident wave propagation heading direction" (degrees) +typedef ^ ^ LOGICAL WaveMultiDir - - - "Indicates the waves are multidirectional -- set by HydroDyn_Input" - +typedef ^ ^ SiKi WaveDirArr {:} - - "Wave direction assigned to each frequency" (degrees) +typedef ^ ^ SiKi WaveDirMin - - - "Minimum wave direction from Waves module" - +typedef ^ ^ SiKi WaveDirMax - - - "Maximum wave direction from Waves module" - +typedef ^ ^ SiKi WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec + +typedef ^ ^ CHARACTER(ChanLen) OutList {27} - - "This should really be dimensioned with MaxOutPts" - +typedef ^ ^ LOGICAL OutAll - - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ INTEGER WaveMod - - - "The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here." - + +typedef ^ ^ LOGICAL PtfmSgF2 - - - "Supplied by Driver: Platform horizontal surge translation force (flag)" - +typedef ^ ^ LOGICAL PtfmSwF2 - - - "Supplied by Driver: Platform horizontal sway translation force (flag)" - +typedef ^ ^ LOGICAL PtfmHvF2 - - - "Supplied by Driver: Platform vertical heave translation force (flag)" - +typedef ^ ^ LOGICAL PtfmRF2 - - - "Supplied by Driver: Platform roll tilt rotation force (flag)" - +typedef ^ ^ LOGICAL PtfmPF2 - - - "Supplied by Driver: Platform pitch tilt rotation force (flag)" - +typedef ^ ^ LOGICAL PtfmYF2 - - - "Supplied by Driver: Platform yaw rotation force (flag)" - + + +#[note: only one of MnDriff / NewmanApp / DiffQTF can be non-zero +typedef ^ ^ INTEGER MnDrift - - - "Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use}" - +typedef ^ ^ INTEGER NewmanApp - - - "Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use}" - +typedef ^ ^ INTEGER DiffQTF - - - "Full Difference-Frequency forces computed with full QTF's from WAMIT file: {0: No diff-QTF; [10,11, or 12]: WAMIT file to use}" - +typedef ^ ^ INTEGER SumQTF - - - "Full Sum-Frequency forces computed with full QTF's from WAMIT file: {0: No sum-QTF; [10,11, or 12]: WAMIT file to use}" - +typedef ^ ^ LOGICAL MnDriftF - - - "Flag indicating mean drift force should be calculated" - +typedef ^ ^ LOGICAL NewmanAppF - - - "Flag indicating Newman approximation should be calculated" - +typedef ^ ^ LOGICAL DiffQTFF - - - "Flag indicating the full difference QTF should be calculated" - +typedef ^ ^ LOGICAL SumQTFF - - - "Flag indicating the full sum QTF should be calculated" - +typedef ^ ^ ReKi WvLowCOff - - - "Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4]" (rad/s) +typedef ^ ^ ReKi WvHiCOff - - - "High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4]" (rad/s) +typedef ^ ^ ReKi WvLowCOffD - - - "Minimum frequency used in the difference methods [Ignored if all difference methods = 0]" (rad/s) +typedef ^ ^ ReKi WvHiCOffD - - - "Maximum frequency used in the difference methods [Ignored if all difference methods = 0]" (rad/s) +typedef ^ ^ ReKi WvLowCOffS - - - "Minimum frequency used in the sum-QTF method [Ignored if SumQTF = 0]" (rad/s) +typedef ^ ^ ReKi WvHiCOffS - - - "Maximum frequency used in the sum-QTF method [Ignored if SumQTF = 0]" (rad/s) + + +# Define outputs from the initialization routine here: +# +#typedef ^ InitOutputType MeshType OutputMesh - - - "" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - + + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - + + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - + + +# Define any data that are integer or logical states here: +typedef ^ OtherStateType IntKi 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 INTEGER LastIndWave - - - "Index for last interpolation step of 2nd order forces" - +typedef ^ ^ ReKi F_Waves2 {6} - - "2nd order force from this timestep" - + + + +# ..... 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 WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec +typedef ^ ^ IntKi NStepWave - - - "Number of wave time steps" - +typedef ^ ^ DbKi DT - - - "" - + +#The 2nd order force time series +typedef ^ ^ SiKi WaveExctn2 {:}{:} - - "Time series of the resulting 2nd order force (first index is timestep, second index is load component)" (N) + +#Flags set for dimensions to use with each method (MnDrift, NewmanApp, etc). These are stored by method because .8 files that can be used in MnDrift or NewmanApp don't have some of the dimensions. +typedef ^ ^ LOGICAL MnDriftDims {6} - - "Flags for which dimensions to calculate in MnDrift calculations" - +typedef ^ ^ LOGICAL NewmanAppDims {6} - - "Flags for which dimensions to calculate in NewmanApp calculations" - +typedef ^ ^ LOGICAL DiffQTFDims {6} - - "Flags for which dimensions to calculate in DiffQTF calculations" - +typedef ^ ^ LOGICAL SumQTFDims {6} - - "Flags for which dimensions to calculate in SumQTF calculations" - + +typedef ^ ^ LOGICAL MnDriftF - - - "Flag indicating mean drift force should be calculated" - +typedef ^ ^ LOGICAL NewmanAppF - - - "Flag indicating Newman approximation should be calculated" - +typedef ^ ^ LOGICAL DiffQTFF - - - "Flag indicating the full difference QTF should be calculated" - +typedef ^ ^ LOGICAL SumQTFF - - - "Flag indicating the full sum QTF should be calculated" - + +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - +typedef ^ ^ CHARACTER(ChanLen) Delim - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - + + + + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType MeshType Mesh - - - "Displacements at the platform reference point in the inertial frame" - + + + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType Mesh - - - "Loads at the platform reference point in the inertial frame" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT2_Output.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT2_Output.f90 new file mode 100644 index 000000000..c77b4ebe0 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT2_Output.f90 @@ -0,0 +1,561 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 WAMIT2_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + USE WAMIT2_Types + !USE HydroDyn_Output_Types +! USE Waves + IMPLICIT NONE + + PRIVATE + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen + + ! WAMIT2 Body Forces: + + INTEGER(IntKi), PARAMETER :: WavesF2xi = 1 + INTEGER(IntKi), PARAMETER :: WavesF2yi = 2 + INTEGER(IntKi), PARAMETER :: WavesF2zi = 3 + INTEGER(IntKi), PARAMETER :: WavesM2xi = 4 + INTEGER(IntKi), PARAMETER :: WavesM2yi = 5 + INTEGER(IntKi), PARAMETER :: WavesM2zi = 6 + + + +!End of code generated by Matlab script + + + INTEGER, PARAMETER :: FWaves2(6) = (/WavesF2xi,WavesF2yi,WavesF2zi,WavesM2xi,WavesM2yi,WavesM2zi/) + + + +! This code was generated by hand. + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(6) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "WAVESF2XI ","WAVESF2YI ","WAVESF2ZI ","WAVESM2XI ","WAVESM2YI ","WAVESM2ZI "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(6) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + WavesF2xi , WavesF2yi , WavesF2zi , WavesM2xi , WavesM2yi , WavesM2zi /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(6) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) "/) + + + REAL(ReKi) :: AllOuts(MaxWAMIT2Outputs) ! Array of all possible outputs + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: WMT2OUT_MapOutputs + PUBLIC :: WMT2OUT_WriteOutputNames + PUBLIC :: WMT2OUT_WriteOutputUnits + PUBLIC :: WMT2OUT_WriteOutputs + PUBLIC :: WMT2OUT_Init + PUBLIC :: WMT2OUT_DestroyParam + PUBLIC :: GetWAMIT2Channels + +CONTAINS + + + + +!==================================================================================================== +SUBROUTINE WMT2OUT_MapOutputs( CurrentTime, y, F_Waves2, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by WAMIT2_CalcOutput() at each time step. +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! WAMIT2's output data + REAL(ReKi), INTENT( IN ) :: F_Waves2(6) + REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMIT2Outputs) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + + ErrStat = ErrID_None + ErrMsg = "" + + + ! TODO: use y%mesh for the forces instead of individual parameters + + AllOuts(FWaves2) = F_Waves2 + + + + + +END SUBROUTINE WMT2OUT_MapOutputs + + +!==================================================================================================== + +SUBROUTINE WMT2OUT_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(WAMIT2_ParameterType), INTENT( IN ) :: p ! WAMIT2 module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) + +END SUBROUTINE WMT2OUT_WriteOutputNames + +!==================================================================================================== + + +SUBROUTINE WMT2OUT_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(WAMIT2_ParameterType), INTENT( IN ) :: p ! WAMIT2 module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) + +END SUBROUTINE WMT2OUT_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE WMT2OUT_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in WMT2OUT_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + INTEGER , INTENT( IN ) :: UnOutFile + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! WAMIT2's output data + TYPE(WAMIT2_ParameterType),INTENT( IN ) :: p ! WAMIT2 parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables +! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + + ! Initialize ErrStat and determine if it makes any sense to write output + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN + ErrMsg = ' No WAMIT2 outputs written. The OutParam array must be allocated and there must be a valid output file identifier before we can write outputs.' + ErrStat = ErrID_Warn + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + + + ! Write the output parameters to the file + + Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + + WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) + + + RETURN + + +END SUBROUTINE WMT2OUT_WriteOutputs + + + +!==================================================================================================== +SUBROUTINE WMT2OUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + + TYPE(WAMIT2_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module + TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p + TYPE(WAMIT2_InitOutputType), INTENT( OUT ) :: InitOut + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter +! INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array +! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! CHARACTER(200) :: Frmt ! a string to hold a format statement + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrMsg = "" + + + + + !------------------------------------------------------------------------------------------------- + ! Check that the variables in OutList are valid + !------------------------------------------------------------------------------------------------- + + + CALL WMT2OUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) RETURN + + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + y%WriteOutput = 0.0_ReKi + + ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,p%NumOuts + + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + + END DO + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE WMT2OUT_Init + + +!==================================================================================================== +FUNCTION GetWAMIT2Channels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if they +! below to the list of available WAMIT2 channels. + +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + CHARACTER(ChanLen), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT2 output channels. + LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER GetWAMIT2Channels ! The number of channels found in this module + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. + INTEGER :: count ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. +! LOGICAL :: InvalidOutput(MaxWAMIT2Outputs) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + + LOGICAL :: newFoundMask (NUserOutputs) ! A Mask indicating whether a user requested channel belongs to a modules output channels. + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + GetWAMIT2Channels = 0 + + newFoundMask = .FALSE. + + + DO I = 1,NUserOutputs + IF (.NOT. foundMask(I) ) THEN + OutListTmp = UserOutputs(I) + + CheckOutListAgain = .FALSE. + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + newFoundMask(I) = .TRUE. + foundMask(I) = .TRUE. + GetWAMIT2Channels = GetWAMIT2Channels + 1 + + !ELSE + ! foundMask(I) = .FALSE. + END IF + END IF +END DO + + +IF ( GetWAMIT2Channels > 0 ) THEN + + count = 1 + ! Test that num channels does not exceed max possible channels due to size of OutList + !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutList array in the GetWAMIT2Channels function.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,NUserOutputs + IF ( newFoundMask(I) ) THEN + OutList(count) = UserOutputs(I) + count = count + 1 + END IF + + END DO + +END IF + + +END FUNCTION GetWAMIT2Channels + + +!==================================================================================================== +SUBROUTINE WMT2OUT_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! Note that the Wamit module must be initialized prior to calling this function (if it +! is being used) so that it can correctly determine if the Lines outputs are valid. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT2 platform module + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. +! INTEGER :: J ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + + + ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 09-Jan-2013 14:53:03. + + LOGICAL :: InvalidOutput(MaxWAMIT2Outputs) ! This array determines if the output channel is valid for this configuration + + LOGICAL :: CheckOutListAgain + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + InvalidOutput = .FALSE. + +!End of code generated by Matlab script + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutParam array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' + ErrStat = ErrID_Fatal +! RETURN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + END DO + + + RETURN +END SUBROUTINE WMT2OUT_ChkOutLst + + +!==================================================================================================== +SUBROUTINE WMT2OUT_DestroyParam ( p, ErrStat, ErrMsg ) +! This function cleans up after running the WAMIT2 output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT2 module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + Err = .FALSE. + + + + !------------------------------------------------------------------------------------------------- + ! Deallocate arrays + !------------------------------------------------------------------------------------------------- + IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + !------------------------------------------------------------------------------------------------- + ! Reset number of outputs + !------------------------------------------------------------------------------------------------- + p%NumOuts = 0 + p%UnOutFile = -1 + + !p%WaveKinNd = -1 ! set this array to "invalid" + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE WMT2OUT_DestroyParam +!==================================================================================================== + + +END MODULE WAMIT2_Output diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT2_Types.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT2_Types.f90 new file mode 100644 index 000000000..af1cddd8d --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -0,0 +1,2874 @@ +!STARTOFREGISTRYGENERATEDFILE 'WAMIT2_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 +!********************************************************************************************************************************* +! WAMIT2_Types +!................................................................................................................................. +! This file is part of WAMIT2. +! +! 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 WAMIT2. 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 WAMIT2_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxWAMIT2Outputs = 6 ! [-] +! ========= WAMIT2_InitInputType ======= + TYPE, PUBLIC :: WAMIT2_InitInputType + LOGICAL :: HasWAMIT !< .TRUE. if using WAMIT model, .FALSE. otherwise [-] + CHARACTER(1024) :: WAMITFile !< Root of the filename for WAMIT2 outputs [-] + INTEGER(IntKi) :: UnSum !< The unit number for the HydroDyn summary file [-] + REAL(ReKi) :: WAMITULEN !< WAMIT unit length scale [-] + REAL(ReKi) :: RhoXg !< Density * Gravity -- from the Waves module. [-] + INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] + INTEGER(IntKi) :: NStepWave2 !< NStepWave / 2 [-] + REAL(ReKi) :: WaveDOmega !< Frequency step for incident wave calculations [(rad/s)] + REAL(ReKi) :: WtrDens !< Water density [(kg/m^3)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevC0 !< Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part [(meters)] + REAL(SiKi) :: WaveDir !< Mean incident wave propagation heading direction [(degrees)] + LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveDirArr !< Wave direction assigned to each frequency [(degrees)] + REAL(SiKi) :: WaveDirMin !< Minimum wave direction from Waves module [-] + REAL(SiKi) :: WaveDirMax !< Maximum wave direction from Waves module [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] + CHARACTER(ChanLen) , DIMENSION(1:27) :: OutList !< This should really be dimensioned with MaxOutPts [-] + LOGICAL :: OutAll !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + INTEGER(IntKi) :: WaveMod !< The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here. [-] + LOGICAL :: PtfmSgF2 !< Supplied by Driver: Platform horizontal surge translation force (flag) [-] + LOGICAL :: PtfmSwF2 !< Supplied by Driver: Platform horizontal sway translation force (flag) [-] + LOGICAL :: PtfmHvF2 !< Supplied by Driver: Platform vertical heave translation force (flag) [-] + LOGICAL :: PtfmRF2 !< Supplied by Driver: Platform roll tilt rotation force (flag) [-] + LOGICAL :: PtfmPF2 !< Supplied by Driver: Platform pitch tilt rotation force (flag) [-] + LOGICAL :: PtfmYF2 !< Supplied by Driver: Platform yaw rotation force (flag) [-] + INTEGER(IntKi) :: MnDrift !< Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] + INTEGER(IntKi) :: NewmanApp !< Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] + INTEGER(IntKi) :: DiffQTF !< Full Difference-Frequency forces computed with full QTF's from WAMIT file: {0: No diff-QTF; [10,11, or 12]: WAMIT file to use} [-] + INTEGER(IntKi) :: SumQTF !< Full Sum-Frequency forces computed with full QTF's from WAMIT file: {0: No sum-QTF; [10,11, or 12]: WAMIT file to use} [-] + LOGICAL :: MnDriftF !< Flag indicating mean drift force should be calculated [-] + LOGICAL :: NewmanAppF !< Flag indicating Newman approximation should be calculated [-] + LOGICAL :: DiffQTFF !< Flag indicating the full difference QTF should be calculated [-] + LOGICAL :: SumQTFF !< Flag indicating the full sum QTF should be calculated [-] + REAL(ReKi) :: WvLowCOff !< Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4] [(rad/s)] + REAL(ReKi) :: WvHiCOff !< High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4] [(rad/s)] + REAL(ReKi) :: WvLowCOffD !< Minimum frequency used in the difference methods [Ignored if all difference methods = 0] [(rad/s)] + REAL(ReKi) :: WvHiCOffD !< Maximum frequency used in the difference methods [Ignored if all difference methods = 0] [(rad/s)] + REAL(ReKi) :: WvLowCOffS !< Minimum frequency used in the sum-QTF method [Ignored if SumQTF = 0] [(rad/s)] + REAL(ReKi) :: WvHiCOffS !< Maximum frequency used in the sum-QTF method [Ignored if SumQTF = 0] [(rad/s)] + END TYPE WAMIT2_InitInputType +! ======================= +! ========= WAMIT2_InitOutputType ======= + TYPE, PUBLIC :: WAMIT2_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + END TYPE WAMIT2_InitOutputType +! ======================= +! ========= WAMIT2_ContinuousStateType ======= + TYPE, PUBLIC :: WAMIT2_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE WAMIT2_ContinuousStateType +! ======================= +! ========= WAMIT2_DiscreteStateType ======= + TYPE, PUBLIC :: WAMIT2_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE WAMIT2_DiscreteStateType +! ======================= +! ========= WAMIT2_ConstraintStateType ======= + TYPE, PUBLIC :: WAMIT2_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE WAMIT2_ConstraintStateType +! ======================= +! ========= WAMIT2_OtherStateType ======= + TYPE, PUBLIC :: WAMIT2_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE WAMIT2_OtherStateType +! ======================= +! ========= WAMIT2_MiscVarType ======= + TYPE, PUBLIC :: WAMIT2_MiscVarType + INTEGER(IntKi) :: LastIndWave !< Index for last interpolation step of 2nd order forces [-] + REAL(ReKi) , DIMENSION(1:6) :: F_Waves2 !< 2nd order force from this timestep [-] + END TYPE WAMIT2_MiscVarType +! ======================= +! ========= WAMIT2_ParameterType ======= + TYPE, PUBLIC :: WAMIT2_ParameterType + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] + INTEGER(IntKi) :: NStepWave !< Number of wave time steps [-] + REAL(DbKi) :: DT !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveExctn2 !< Time series of the resulting 2nd order force (first index is timestep, second index is load component) [(N)] + LOGICAL , DIMENSION(1:6) :: MnDriftDims !< Flags for which dimensions to calculate in MnDrift calculations [-] + LOGICAL , DIMENSION(1:6) :: NewmanAppDims !< Flags for which dimensions to calculate in NewmanApp calculations [-] + LOGICAL , DIMENSION(1:6) :: DiffQTFDims !< Flags for which dimensions to calculate in DiffQTF calculations [-] + LOGICAL , DIMENSION(1:6) :: SumQTFDims !< Flags for which dimensions to calculate in SumQTF calculations [-] + LOGICAL :: MnDriftF !< Flag indicating mean drift force should be calculated [-] + LOGICAL :: NewmanAppF !< Flag indicating Newman approximation should be calculated [-] + LOGICAL :: DiffQTFF !< Flag indicating the full difference QTF should be calculated [-] + LOGICAL :: SumQTFF !< Flag indicating the full sum QTF should be calculated [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + CHARACTER(20) :: OutFmt !< [-] + CHARACTER(20) :: OutSFmt !< [-] + CHARACTER(ChanLen) :: Delim !< [-] + INTEGER(IntKi) :: UnOutFile !< [-] + END TYPE WAMIT2_ParameterType +! ======================= +! ========= WAMIT2_InputType ======= + TYPE, PUBLIC :: WAMIT2_InputType + TYPE(MeshType) :: Mesh !< Displacements at the platform reference point in the inertial frame [-] + END TYPE WAMIT2_InputType +! ======================= +! ========= WAMIT2_OutputType ======= + TYPE, PUBLIC :: WAMIT2_OutputType + TYPE(MeshType) :: Mesh !< Loads at the platform reference point in the inertial frame [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + END TYPE WAMIT2_OutputType +! ======================= +CONTAINS + SUBROUTINE WAMIT2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(WAMIT2_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 = 'WAMIT2_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%HasWAMIT = SrcInitInputData%HasWAMIT + DstInitInputData%WAMITFile = SrcInitInputData%WAMITFile + DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%WAMITULEN = SrcInitInputData%WAMITULEN + DstInitInputData%RhoXg = SrcInitInputData%RhoXg + DstInitInputData%NStepWave = SrcInitInputData%NStepWave + DstInitInputData%NStepWave2 = SrcInitInputData%NStepWave2 + DstInitInputData%WaveDOmega = SrcInitInputData%WaveDOmega + DstInitInputData%WtrDens = SrcInitInputData%WtrDens +IF (ALLOCATED(SrcInitInputData%WaveElevC0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevC0,1) + i1_u = UBOUND(SrcInitInputData%WaveElevC0,1) + i2_l = LBOUND(SrcInitInputData%WaveElevC0,2) + i2_u = UBOUND(SrcInitInputData%WaveElevC0,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevC0)) THEN + ALLOCATE(DstInitInputData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevC0 = SrcInitInputData%WaveElevC0 +ENDIF + DstInitInputData%WaveDir = SrcInitInputData%WaveDir + DstInitInputData%WaveMultiDir = SrcInitInputData%WaveMultiDir +IF (ALLOCATED(SrcInitInputData%WaveDirArr)) THEN + i1_l = LBOUND(SrcInitInputData%WaveDirArr,1) + i1_u = UBOUND(SrcInitInputData%WaveDirArr,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveDirArr)) THEN + ALLOCATE(DstInitInputData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveDirArr = SrcInitInputData%WaveDirArr +ENDIF + DstInitInputData%WaveDirMin = SrcInitInputData%WaveDirMin + DstInitInputData%WaveDirMax = SrcInitInputData%WaveDirMax +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF + DstInitInputData%OutList = SrcInitInputData%OutList + DstInitInputData%OutAll = SrcInitInputData%OutAll + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + DstInitInputData%NumOutAll = SrcInitInputData%NumOutAll + DstInitInputData%WaveMod = SrcInitInputData%WaveMod + DstInitInputData%PtfmSgF2 = SrcInitInputData%PtfmSgF2 + DstInitInputData%PtfmSwF2 = SrcInitInputData%PtfmSwF2 + DstInitInputData%PtfmHvF2 = SrcInitInputData%PtfmHvF2 + DstInitInputData%PtfmRF2 = SrcInitInputData%PtfmRF2 + DstInitInputData%PtfmPF2 = SrcInitInputData%PtfmPF2 + DstInitInputData%PtfmYF2 = SrcInitInputData%PtfmYF2 + DstInitInputData%MnDrift = SrcInitInputData%MnDrift + DstInitInputData%NewmanApp = SrcInitInputData%NewmanApp + DstInitInputData%DiffQTF = SrcInitInputData%DiffQTF + DstInitInputData%SumQTF = SrcInitInputData%SumQTF + DstInitInputData%MnDriftF = SrcInitInputData%MnDriftF + DstInitInputData%NewmanAppF = SrcInitInputData%NewmanAppF + DstInitInputData%DiffQTFF = SrcInitInputData%DiffQTFF + DstInitInputData%SumQTFF = SrcInitInputData%SumQTFF + DstInitInputData%WvLowCOff = SrcInitInputData%WvLowCOff + DstInitInputData%WvHiCOff = SrcInitInputData%WvHiCOff + DstInitInputData%WvLowCOffD = SrcInitInputData%WvLowCOffD + DstInitInputData%WvHiCOffD = SrcInitInputData%WvHiCOffD + DstInitInputData%WvLowCOffS = SrcInitInputData%WvLowCOffS + DstInitInputData%WvHiCOffS = SrcInitInputData%WvHiCOffS + END SUBROUTINE WAMIT2_CopyInitInput + + SUBROUTINE WAMIT2_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(WAMIT2_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveElevC0)) THEN + DEALLOCATE(InitInputData%WaveElevC0) +ENDIF +IF (ALLOCATED(InitInputData%WaveDirArr)) THEN + DEALLOCATE(InitInputData%WaveDirArr) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF + END SUBROUTINE WAMIT2_DestroyInitInput + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 ! HasWAMIT + Int_BufSz = Int_BufSz + 1*LEN(InData%WAMITFile) ! WAMITFile + Int_BufSz = Int_BufSz + 1 ! UnSum + Re_BufSz = Re_BufSz + 1 ! WAMITULEN + Re_BufSz = Re_BufSz + 1 ! RhoXg + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NStepWave2 + Re_BufSz = Re_BufSz + 1 ! WaveDOmega + Re_BufSz = Re_BufSz + 1 ! WtrDens + Int_BufSz = Int_BufSz + 1 ! WaveElevC0 allocated yes/no + IF ( ALLOCATED(InData%WaveElevC0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevC0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevC0) ! WaveElevC0 + END IF + Re_BufSz = Re_BufSz + 1 ! WaveDir + Int_BufSz = Int_BufSz + 1 ! WaveMultiDir + Int_BufSz = Int_BufSz + 1 ! WaveDirArr allocated yes/no + IF ( ALLOCATED(InData%WaveDirArr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveDirArr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDirArr) ! WaveDirArr + END IF + Re_BufSz = Re_BufSz + 1 ! WaveDirMin + Re_BufSz = Re_BufSz + 1 ! WaveDirMax + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + Int_BufSz = Int_BufSz + 1 ! WaveMod + Int_BufSz = Int_BufSz + 1 ! PtfmSgF2 + Int_BufSz = Int_BufSz + 1 ! PtfmSwF2 + Int_BufSz = Int_BufSz + 1 ! PtfmHvF2 + Int_BufSz = Int_BufSz + 1 ! PtfmRF2 + Int_BufSz = Int_BufSz + 1 ! PtfmPF2 + Int_BufSz = Int_BufSz + 1 ! PtfmYF2 + Int_BufSz = Int_BufSz + 1 ! MnDrift + Int_BufSz = Int_BufSz + 1 ! NewmanApp + Int_BufSz = Int_BufSz + 1 ! DiffQTF + Int_BufSz = Int_BufSz + 1 ! SumQTF + Int_BufSz = Int_BufSz + 1 ! MnDriftF + Int_BufSz = Int_BufSz + 1 ! NewmanAppF + Int_BufSz = Int_BufSz + 1 ! DiffQTFF + Int_BufSz = Int_BufSz + 1 ! SumQTFF + Re_BufSz = Re_BufSz + 1 ! WvLowCOff + Re_BufSz = Re_BufSz + 1 ! WvHiCOff + Re_BufSz = Re_BufSz + 1 ! WvLowCOffD + Re_BufSz = Re_BufSz + 1 ! WvHiCOffD + Re_BufSz = Re_BufSz + 1 ! WvLowCOffS + Re_BufSz = Re_BufSz + 1 ! WvHiCOffS + 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%HasWAMIT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%WAMITFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%WAMITFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WAMITULEN + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RhoXg + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave2 + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDOmega + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElevC0) ) 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%WaveElevC0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevC0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevC0,2), UBOUND(InData%WaveElevC0,2) + DO i1 = LBOUND(InData%WaveElevC0,1), UBOUND(InData%WaveElevC0,1) + ReKiBuf(Re_Xferred) = InData%WaveElevC0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%WaveDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveMultiDir, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveDirArr) ) 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%WaveDirArr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDirArr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveDirArr,1), UBOUND(InData%WaveDirArr,1) + ReKiBuf(Re_Xferred) = InData%WaveDirArr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%WaveDirMin + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDirMax + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF2, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MnDrift + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NewmanApp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DiffQTF + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SumQTF + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%MnDriftF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%NewmanAppF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DiffQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOffD + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOffD + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOffS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOffS + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE WAMIT2_PackInitInput + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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%HasWAMIT = TRANSFER(IntKiBuf(Int_Xferred), OutData%HasWAMIT) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%WAMITFile) + OutData%WAMITFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WAMITULEN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RhoXg = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDOmega = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 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%WaveElevC0)) DEALLOCATE(OutData%WaveElevC0) + ALLOCATE(OutData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevC0,2), UBOUND(OutData%WaveElevC0,2) + DO i1 = LBOUND(OutData%WaveElevC0,1), UBOUND(OutData%WaveElevC0,1) + OutData%WaveElevC0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%WaveDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveMultiDir = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveMultiDir) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDirArr 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%WaveDirArr)) DEALLOCATE(OutData%WaveDirArr) + ALLOCATE(OutData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveDirArr,1), UBOUND(OutData%WaveDirArr,1) + OutData%WaveDirArr(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WaveDirMin = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDirMax = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%OutList,1) + i1_u = UBOUND(OutData%OutList,1) + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmSgF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmSwF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmHvF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmRF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmPF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF2) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmYF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF2) + Int_Xferred = Int_Xferred + 1 + OutData%MnDrift = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NewmanApp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DiffQTF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SumQTF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%MnDriftF = TRANSFER(IntKiBuf(Int_Xferred), OutData%MnDriftF) + Int_Xferred = Int_Xferred + 1 + OutData%NewmanAppF = TRANSFER(IntKiBuf(Int_Xferred), OutData%NewmanAppF) + Int_Xferred = Int_Xferred + 1 + OutData%DiffQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%DiffQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%SumQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%WvLowCOff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvLowCOffD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOffD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvLowCOffS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOffS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackInitInput + + SUBROUTINE WAMIT2_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(WAMIT2_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 = 'WAMIT2_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE WAMIT2_CopyInitOutput + + SUBROUTINE WAMIT2_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(WAMIT2_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE WAMIT2_DestroyInitOutput + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE WAMIT2_PackInitOutput + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE WAMIT2_UnPackInitOutput + + SUBROUTINE WAMIT2_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(WAMIT2_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 = 'WAMIT2_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE WAMIT2_CopyContState + + SUBROUTINE WAMIT2_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(WAMIT2_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE WAMIT2_DestroyContState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 WAMIT2_PackContState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackContState + + SUBROUTINE WAMIT2_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(WAMIT2_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 = 'WAMIT2_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE WAMIT2_CopyDiscState + + SUBROUTINE WAMIT2_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(WAMIT2_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE WAMIT2_DestroyDiscState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 WAMIT2_PackDiscState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackDiscState + + SUBROUTINE WAMIT2_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(WAMIT2_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 = 'WAMIT2_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE WAMIT2_CopyConstrState + + SUBROUTINE WAMIT2_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(WAMIT2_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE WAMIT2_DestroyConstrState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 WAMIT2_PackConstrState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackConstrState + + SUBROUTINE WAMIT2_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(WAMIT2_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 = 'WAMIT2_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE WAMIT2_CopyOtherState + + SUBROUTINE WAMIT2_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(WAMIT2_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE WAMIT2_DestroyOtherState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT2_PackOtherState + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackOtherState + + SUBROUTINE WAMIT2_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(WAMIT2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + DstMiscData%F_Waves2 = SrcMiscData%F_Waves2 + END SUBROUTINE WAMIT2_CopyMisc + + SUBROUTINE WAMIT2_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(WAMIT2_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE WAMIT2_DestroyMisc + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 ! LastIndWave + Re_BufSz = Re_BufSz + SIZE(InData%F_Waves2) ! F_Waves2 + 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%LastIndWave + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%F_Waves2,1), UBOUND(InData%F_Waves2,1) + ReKiBuf(Re_Xferred) = InData%F_Waves2(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE WAMIT2_PackMisc + + SUBROUTINE WAMIT2_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(WAMIT2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_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%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%F_Waves2,1) + i1_u = UBOUND(OutData%F_Waves2,1) + DO i1 = LBOUND(OutData%F_Waves2,1), UBOUND(OutData%F_Waves2,1) + OutData%F_Waves2(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE WAMIT2_UnPackMisc + + SUBROUTINE WAMIT2_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_ParameterType), INTENT(IN) :: SrcParamData + TYPE(WAMIT2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%DT = SrcParamData%DT +IF (ALLOCATED(SrcParamData%WaveExctn2)) THEN + i1_l = LBOUND(SrcParamData%WaveExctn2,1) + i1_u = UBOUND(SrcParamData%WaveExctn2,1) + i2_l = LBOUND(SrcParamData%WaveExctn2,2) + i2_u = UBOUND(SrcParamData%WaveExctn2,2) + IF (.NOT. ALLOCATED(DstParamData%WaveExctn2)) THEN + ALLOCATE(DstParamData%WaveExctn2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveExctn2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveExctn2 = SrcParamData%WaveExctn2 +ENDIF + DstParamData%MnDriftDims = SrcParamData%MnDriftDims + DstParamData%NewmanAppDims = SrcParamData%NewmanAppDims + DstParamData%DiffQTFDims = SrcParamData%DiffQTFDims + DstParamData%SumQTFDims = SrcParamData%SumQTFDims + DstParamData%MnDriftF = SrcParamData%MnDriftF + DstParamData%NewmanAppF = SrcParamData%NewmanAppF + DstParamData%DiffQTFF = SrcParamData%DiffQTFF + DstParamData%SumQTFF = SrcParamData%SumQTFF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOutAll = SrcParamData%NumOutAll + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + DstParamData%UnOutFile = SrcParamData%UnOutFile + END SUBROUTINE WAMIT2_CopyParam + + SUBROUTINE WAMIT2_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(WAMIT2_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF +IF (ALLOCATED(ParamData%WaveExctn2)) THEN + DEALLOCATE(ParamData%WaveExctn2) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE WAMIT2_DestroyParam + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! NStepWave + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! WaveExctn2 allocated yes/no + IF ( ALLOCATED(InData%WaveExctn2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveExctn2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveExctn2) ! WaveExctn2 + END IF + Int_BufSz = Int_BufSz + SIZE(InData%MnDriftDims) ! MnDriftDims + Int_BufSz = Int_BufSz + SIZE(InData%NewmanAppDims) ! NewmanAppDims + Int_BufSz = Int_BufSz + SIZE(InData%DiffQTFDims) ! DiffQTFDims + Int_BufSz = Int_BufSz + SIZE(InData%SumQTFDims) ! SumQTFDims + Int_BufSz = Int_BufSz + 1 ! MnDriftF + Int_BufSz = Int_BufSz + 1 ! NewmanAppF + Int_BufSz = Int_BufSz + 1 ! DiffQTFF + Int_BufSz = Int_BufSz + 1 ! SumQTFF + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UnOutFile + 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%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveExctn2) ) 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%WaveExctn2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveExctn2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveExctn2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveExctn2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveExctn2,2), UBOUND(InData%WaveExctn2,2) + DO i1 = LBOUND(InData%WaveExctn2,1), UBOUND(InData%WaveExctn2,1) + ReKiBuf(Re_Xferred) = InData%WaveExctn2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%MnDriftDims,1), UBOUND(InData%MnDriftDims,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%MnDriftDims(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%NewmanAppDims,1), UBOUND(InData%NewmanAppDims,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%NewmanAppDims(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%DiffQTFDims,1), UBOUND(InData%DiffQTFDims,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%DiffQTFDims(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SumQTFDims,1), UBOUND(InData%SumQTFDims,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumQTFDims(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%MnDriftF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%NewmanAppF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DiffQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumQTFF, IntKiBuf(1)) + 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 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT2_PackParam + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn2 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%WaveExctn2)) DEALLOCATE(OutData%WaveExctn2) + ALLOCATE(OutData%WaveExctn2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveExctn2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveExctn2,2), UBOUND(OutData%WaveExctn2,2) + DO i1 = LBOUND(OutData%WaveExctn2,1), UBOUND(OutData%WaveExctn2,1) + OutData%WaveExctn2(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%MnDriftDims,1) + i1_u = UBOUND(OutData%MnDriftDims,1) + DO i1 = LBOUND(OutData%MnDriftDims,1), UBOUND(OutData%MnDriftDims,1) + OutData%MnDriftDims(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%MnDriftDims(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%NewmanAppDims,1) + i1_u = UBOUND(OutData%NewmanAppDims,1) + DO i1 = LBOUND(OutData%NewmanAppDims,1), UBOUND(OutData%NewmanAppDims,1) + OutData%NewmanAppDims(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%NewmanAppDims(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%DiffQTFDims,1) + i1_u = UBOUND(OutData%DiffQTFDims,1) + DO i1 = LBOUND(OutData%DiffQTFDims,1), UBOUND(OutData%DiffQTFDims,1) + OutData%DiffQTFDims(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%DiffQTFDims(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SumQTFDims,1) + i1_u = UBOUND(OutData%SumQTFDims,1) + DO i1 = LBOUND(OutData%SumQTFDims,1), UBOUND(OutData%SumQTFDims,1) + OutData%SumQTFDims(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumQTFDims(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%MnDriftF = TRANSFER(IntKiBuf(Int_Xferred), OutData%MnDriftF) + Int_Xferred = Int_Xferred + 1 + OutData%NewmanAppF = TRANSFER(IntKiBuf(Int_Xferred), OutData%NewmanAppF) + Int_Xferred = Int_Xferred + 1 + OutData%DiffQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%DiffQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%SumQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumQTFF) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT2_UnPackParam + + SUBROUTINE WAMIT2_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_InputType), INTENT(INOUT) :: SrcInputData + TYPE(WAMIT2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%Mesh, DstInputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT2_CopyInput + + SUBROUTINE WAMIT2_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(WAMIT2_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%Mesh, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT2_DestroyInput + + SUBROUTINE WAMIT2_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(WAMIT2_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 = 'WAMIT2_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 WAMIT2_PackInput + + SUBROUTINE WAMIT2_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(WAMIT2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_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 + 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 WAMIT2_UnPackInput + + SUBROUTINE WAMIT2_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'WAMIT2_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE WAMIT2_CopyOutput + + SUBROUTINE WAMIT2_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE WAMIT2_DestroyOutput + + SUBROUTINE WAMIT2_PackOutput( 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(WAMIT2_OutputType), 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 = 'WAMIT2_PackOutput' + ! 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 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE WAMIT2_PackOutput + + SUBROUTINE WAMIT2_UnPackOutput( 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(WAMIT2_OutputType), 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 = 'WAMIT2_UnPackOutput' + ! 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE WAMIT2_UnPackOutput + + + SUBROUTINE WAMIT2_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL WAMIT2_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL WAMIT2_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL WAMIT2_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE WAMIT2_Input_ExtrapInterp + + + SUBROUTINE WAMIT2_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE WAMIT2_Input_ExtrapInterp1 + + + SUBROUTINE WAMIT2_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(WAMIT2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE WAMIT2_Input_ExtrapInterp2 + + + SUBROUTINE WAMIT2_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL WAMIT2_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL WAMIT2_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL WAMIT2_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE WAMIT2_Output_ExtrapInterp + + + SUBROUTINE WAMIT2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE WAMIT2_Output_ExtrapInterp1 + + + SUBROUTINE WAMIT2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(WAMIT2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE WAMIT2_Output_ExtrapInterp2 + +END MODULE WAMIT2_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT_Interp.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT_Interp.f90 new file mode 100644 index 000000000..7e7ce8cfa --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT_Interp.f90 @@ -0,0 +1,625 @@ +!********************************************************************************************************************************** +! NOTE: documentation in this file is written for use with Doxygen 1.8.6 and higher. +! +!> WAMIT_Interp module +!! +!! This module is used for interpolating the QTFs used in the WAMIT and WAMIT2 modules of HydroDyn. +!! +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2014-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 WAMIT_Interp + + + USE NWTC_Library + IMPLICIT NONE + + PRIVATE + + ! Public subroutines + PUBLIC :: WAMIT_Interp2D_Cplx + PUBLIC :: WAMIT_Interp3D_Cplx + PUBLIC :: WAMIT_Interp4D_Cplx + + +CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes the complex valued QTF dataset and interpolates for the desired coordinate in (Omega,WaveDir) space. +!! +!! A few important notes concerning this subroutine: +!! 1. It is complex valued. The values represent the second order wave force as calculated by WAMIT. +!! 2. The dimenions of DataSet2D are Frequency1 (positive valued) and Wave Direction (degrees). +!! 3. The wave direction requested might be between end points of wave direction dimension (ie. at 179 degrees when +!! WvDir1(1)=175, WvDir(Dims(3))=-175) +!! 4. The arrays WvFreq1 and WvDir1 will give the values for each dimension that correspond to each index of DataSet2D. +!! 5. The data is not necessarily equally spaced in any direction: ie. WvFreq1 may not have uniform spacing between points. +!! 6. If a point is requested, it can be assumed that it lies within DataSet2D (this is checked before calling this subroutine) +!! 7. LastIndex contains the index numbers for the lowest bound on the indexes used on the last interpolation. If they are 0, +!! then assume this is the first call to this subroutine. +!! 8. DataSet2D is complete and not sparse. There are no missing values. +!! +SUBROUTINE WAMIT_Interp2D_Cplx( InCoord, DataSet2D, WvFreq1, WvDir1, LastIndex, OutForce, ErrStat, ErrMsg ) + + ! I/O variables + + REAL(SiKi), INTENT(IN ) :: InCoord(2) !< Arranged as (Omega1, WaveDir1) + COMPLEX(SiKi), INTENT(IN ) :: DataSet2D(:,:) !< Arranged as Index 1= Omega1, Index 2= WaveDir1. + REAL(SiKi), INTENT(IN ) :: WvFreq1(:) !< Frequencies associated with Index 1 of DataSet2D + REAL(SiKi), INTENT(IN ) :: WvDir1(:) !< Directions associated with Index 2 of DataSet2D + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(2) !< Index for the last (Omega1, WaveDir1) used + COMPLEX(SiKi), INTENT( OUT) :: OutForce !< The interpolated resulting force from DataSet2D + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + REAL(SiKi) :: Coords(2) !< coordinates with wave directions converted to range [-180, 180) + INTEGER(IntKi) :: n(2) !< number of points in WvFreq1 and WvDir1, and WvDir2 + + INTEGER(IntKi) :: Indx_Lo(2) !< index associated with lower bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + INTEGER(IntKi) :: Indx_Hi(2) !< index associated with upper bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + REAL(SiKi) :: Pos_Lo(2) !< coordinate value with lower bound of dimension 1,2 + REAL(SiKi) :: Pos_Hi(2) !< coordinate value with upper bound of dimension 1,2 + + + ErrStat = ErrID_None + ErrMsg = "" + + n(1) = SIZE(WvFreq1) + n(2) = SIZE(WvDir1) + + ! Check sizes of input: + IF ( SIZE( DataSet2D, 1 ) /= n(1) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet2D,1) must be the size(WvFreq1)', ErrStat, ErrMsg, 'WAMIT_Interp2D_Cplx' ) + IF ( SIZE( DataSet2D, 2 ) /= n(2) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet2D,2) must be the size(WvDir1)', ErrStat, ErrMsg, 'WAMIT_Interp2D_Cplx' ) + IF (ErrStat == ErrID_Fatal) RETURN + + + ! find the indices into the arrays representing coordinates of each dimension: + + Coords = InCoord + + ! make sure these requested degrees fall in the range -180 <= Coords(2) < 180 + Coords(2) = MODULO( Coords(2), 360.0_SiKi ) + IF ( Coords(2) >= 180.0_SiKi ) Coords(2) = Coords(2) - 360.0_SiKi + + CALL LocateStp( Coords(1), WvFreq1, LastIndex(1), n(1) ) + CALL LocateStp( Coords(2), WvDir1, LastIndex(2), n(2) ) + + Indx_Lo = LastIndex ! at this point, 0 <= Indx_Lo(i) <= n(i) for all i + + + ! WvFreq1 (indx 1) + IF (Indx_Lo(1) == 0) THEN + Indx_Lo(1) = 1 + ELSEIF (Indx_Lo(1) == n(1) ) THEN + Indx_Lo(1) = max( n(1) - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(1) = min( Indx_Lo(1) + 1 , n(1) ) ! make sure it's a valid index + + + ! WvDir1 (indx 2) [use modular arithmetic] + IF (Indx_Lo(2) == 0) THEN + Indx_Hi(2) = 1 + Indx_Lo(2) = n(2) + ELSEIF (Indx_Lo(2) == n(2) ) THEN + Indx_Hi(2) = 1 + ELSE + Indx_Hi(2) = min( Indx_Lo(2) + 1, n(2) ) ! make sure it's a valid index + END IF + + ! calculate the positions of all dimensions: + + pos_Lo(1) = WvFreq1(Indx_Lo(1)) + pos_Hi(1) = WvFreq1(Indx_Hi(1)) + + pos_Lo(2) = WvDir1(Indx_Lo(2)) + pos_Hi(2) = WvDir1(Indx_Hi(2)) + + + ! angles have to be adjusted so that pos_Lo(2) <= Coords(2) <= pos_Hi(2) + IF ( Indx_Hi(2) == 1 .AND. n(2) > 1 ) THEN ! we're looping around the array [periodic] + IF ( pos_Lo(2) < Coords(2) ) THEN + pos_Hi(2) = pos_Hi(2) + 360.0_SiKi + ELSEIF ( pos_Lo(2) /= Coords(2) ) THEN !bjj: I think it's okay if we don't use equalRealNos here + pos_Lo(2) = pos_Lo(2) - 360.0_SiKi + END IF + END IF + + + CALL Interp2D_withIndx_Cplx( Coords, DataSet2D, Indx_Lo, Indx_Hi, pos_Lo, pos_Hi, OutForce ) + + +END SUBROUTINE WAMIT_Interp2D_Cplx + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes the complex valued QTF dataset and interpolates for the desired coordinate in (Omega,WaveDir,WaveDir) space. +!! +!! A few important notes concerning this subroutine: +!! 1. It is complex valued. The values represent the second order wave force as calculated by WAMIT. +!! 2. The dimenions of DataSet3D are Frequency1 (positive valued), Wave Direction1 (degrees), and Wave Direction2 (degrees). +!! 3. The wave direction requested might be between end points of wave direction dimension (ie. at 179 degrees when +!! WvDir1(1)=175, WvDir(Dims(3))=-175) +!! 4. The arrays WvFreq1, WvDir1, and WvDir2, will give the values for each dimension that correspond to each index of DataSet3D. +!! 5. The data is not necessarily equally spaced in any direction: ie. WvFreq1 may not have uniform spacing between points. +!! 6. If a point is requested, it can be assumed that it lies within DataSet3D (this is checked before calling this subroutine) +!! 7. LastIndex contains the index numbers for the lowest bound on the indexes used on the last interpolation. If they are 0, +!! then assume this is the first call to this subroutine. +!! 8. DataSet4D is complete and not sparse. There are no missing values. +!! +SUBROUTINE WAMIT_Interp3D_Cplx( InCoord, DataSet3D, WvFreq1, WvDir1, WvDir2, LastIndex, OutForce, ErrStat, ErrMsg ) + + ! I/O variables + + REAL(SiKi), INTENT(IN ) :: InCoord(3) !< Arranged as (Omega1, WaveDir1, WaveDir2) + COMPLEX(SiKi), INTENT(IN ) :: DataSet3D(:,:,:) !< Arranged as Index 1= Omega1, Index 2= WaveDir1, Index 3= WaveDir2. + REAL(SiKi), INTENT(IN ) :: WvFreq1(:) !< Frequencies associated with Index 1 of DataSet3D + REAL(SiKi), INTENT(IN ) :: WvDir1(:) !< Directions associated with Index 2 of DataSet3D + REAL(SiKi), INTENT(IN ) :: WvDir2(:) !< Directions associated with Index 3 of DataSet3D + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(3) !< Index for the last (Omega1, WaveDir1, WaveDir2) used + COMPLEX(SiKi), INTENT( OUT) :: OutForce !< The interpolated resulting force from DataSet3D + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + REAL(SiKi) :: Coords(3) !< coordinates with wave directions converted to range [-180, 180) + INTEGER(IntKi) :: i !< generic counter + INTEGER(IntKi) :: n(3) !< number of points in WvFreq1, WvDir1, and WvDir2 + + INTEGER(IntKi) :: Indx_Lo(3) !< index associated with lower bound of dimension 1,2,3 where val(Indx_lo(1,2,3)) <= InCoord(1,2,3) <= val(Indx_hi(1,2,3)) + INTEGER(IntKi) :: Indx_Hi(3) !< index associated with upper bound of dimension 1,2,3 where val(Indx_lo(1,2,3)) <= InCoord(1,2,3) <= val(Indx_hi(1,2,3)) + REAL(SiKi) :: Pos_Lo(3) !< coordinate value with lower bound of dimension 1,2,3 + REAL(SiKi) :: Pos_Hi(3) !< coordinate value with upper bound of dimension 1,2,3 + + + ErrStat = ErrID_None + ErrMsg = "" + + n(1) = SIZE(WvFreq1) + n(2) = SIZE(WvDir1) + n(3) = SIZE(WvDir2) + + ! Check sizes of input: + IF ( SIZE( DataSet3D, 1 ) /= n(1) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet3D,1) must be the size(WvFreq1)', ErrStat, ErrMsg, 'WAMIT_Interp3D_Cplx' ) + IF ( SIZE( DataSet3D, 2 ) /= n(2) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet3D,2) must be the size(WvDir1)', ErrStat, ErrMsg, 'WAMIT_Interp3D_Cplx' ) + IF ( SIZE( DataSet3D, 3 ) /= n(3) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet3D,3) must be the size(WvDir2)', ErrStat, ErrMsg, 'WAMIT_Interp3D_Cplx' ) + IF (ErrStat == ErrID_Fatal) RETURN + + + ! find the indices into the arrays representing coordinates of each dimension: + + Coords = InCoord + + DO i=2,3 ! make sure these requested degrees fall in the range -180 <= Coord(2:3) < 180 + Coords(i) = MODULO( Coords(i), 360.0_SiKi ) + IF ( Coords(i) >= 180.0_SiKi ) Coords(i) = Coords(i) - 360.0_SiKi + END DO + + CALL LocateStp( Coords(1), WvFreq1, LastIndex(1), n(1) ) + CALL LocateStp( Coords(2), WvDir1, LastIndex(2), n(2) ) + CALL LocateStp( Coords(3), WvDir2, LastIndex(3), n(3) ) + + Indx_Lo = LastIndex ! at this point, 0 <= Indx_Lo(i) <= n(i) for all i + + + ! WvFreq1 (indx 1) + IF (Indx_Lo(1) == 0) THEN + Indx_Lo(1) = 1 + ELSEIF (Indx_Lo(1) == n(1) ) THEN + Indx_Lo(1) = max( n(1) - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(1) = min( Indx_Lo(1) + 1 , n(1) ) ! make sure it's a valid index + + + ! WvDir1, WvDir2 (indx 2,3) [use modular arithmetic] + DO i=2,3 + IF (Indx_Lo(i) == 0) THEN + Indx_Hi(i) = 1 + Indx_Lo(i) = n(i) + ELSEIF (Indx_Lo(i) == n(i) ) THEN + Indx_Hi(i) = 1 + ELSE + Indx_Hi(i) = min( Indx_Lo(i) + 1, n(i) ) ! make sure it's a valid index + END IF + END DO + + ! calculate the positions of all dimensions: + + pos_Lo(1) = WvFreq1(Indx_Lo(1)) + pos_Hi(1) = WvFreq1(Indx_Hi(1)) + + pos_Lo(2) = WvDir1(Indx_Lo(2)) + pos_Hi(2) = WvDir1(Indx_Hi(2)) + + pos_Lo(3) = WvDir2(Indx_Lo(3)) + pos_Hi(3) = WvDir2(Indx_Hi(3)) + + ! angles have to be adjusted so that pos_Lo(i) <= Coords(i) <= pos_Hi(i) + DO i=2,3 + IF ( Indx_Hi(i) == 1 .AND. n(i) > 1 ) THEN ! we're looping around the array [periodic] + IF ( pos_Lo(i) < Coords(i) ) THEN + pos_Hi(i) = pos_Hi(i) + 360.0_SiKi + ELSEIF ( pos_Lo(i) /= Coords(i) ) THEN !bjj: I think it's okay if we don't use equalRealNos here + pos_Lo(i) = pos_Lo(i) - 360.0_SiKi + END IF + END IF + END DO + + + + CALL Interp3D_withIndx_Cplx( Coords, DataSet3D, Indx_Lo, Indx_Hi, pos_Lo, pos_Hi, OutForce ) + + +END SUBROUTINE WAMIT_Interp3D_Cplx + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes the complex valued QTF dataset and interpolates for the desired coordinate in (Omega,Omega,WaveDir, +!! WaveDir) space. +!! +!! A few important notes concerning this subroutine: +!! 1. It is complex valued. The values represent the second order wave force as calculated by WAMIT. +!! 2. The dimenions of DataSet4D are Frequency1 (positive valued), Frequency2 (positive valued), Wave Direction 1 (degrees), +!! and Wave Direction 2 (degrees). +!! 3. The wave direction requested might be between end points of wave direction dimension (ie. at 179 degrees when +!! WvDir1(1)=175, WvDir(Dims(3))=-175) +!! 4. The arrays WvFreq1, WvFreq2, WvDir1, and WvDir2 will give the values for each dimension that correspond to +!! each index of DataSet4D. +!! 5. The data is not necessarily equally spaced in any direction: ie. WvFreq1 may not have uniform spacing between points. +!! 6. If a point is requested, it can be assumed that it lies within DataSet4D (this is checked before calling this subroutine) +!! 7. LastIndex contains the index numbers for the lowest bound on the indexes used on the last interpolation. If they are 0, +!! then assume this is the first call to this subroutine. +!! 8. DataSet4D is complete and not sparse. There are no missing values. +!! +!! +SUBROUTINE WAMIT_Interp4D_Cplx( InCoord, DataSet4D, WvFreq1, WvFreq2, WvDir1, WvDir2, LastIndex, OutForce, ErrStat, ErrMsg ) + + ! I/O variables + + REAL(SiKi), INTENT(IN ) :: InCoord(4) !< Arranged as (Omega1, Omega2, WaveDir1) + COMPLEX(SiKi), INTENT(IN ) :: DataSet4D(:,:,:,:) !< Arranged as Index 1= Omega1, Index 2= Omega2, Index 3= WaveDir1, Index 4= Wavedir2. + REAL(SiKi), INTENT(IN ) :: WvFreq1(:) !< Frequencies associated with Index 1 of DataSet4D + REAL(SiKi), INTENT(IN ) :: WvFreq2(:) !< Frequencies associated with Index 2 of DataSet4D + REAL(SiKi), INTENT(IN ) :: WvDir1(:) !< Frequencies associated with Index 3 of DataSet4D + REAL(SiKi), INTENT(IN ) :: WvDir2(:) !< Frequencies associated with Index 3 of DataSet4D + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(4) !< Index for the last (Omega1, Omega2, WaveDir1) used + COMPLEX(SiKi), INTENT( OUT) :: OutForce !< The interpolated resulting force from DataSet4D + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + REAL(SiKi) :: Coords(4) !< coordinates with wave directions converted to range [-180, 180) + INTEGER(IntKi) :: i !< generic counter + INTEGER(IntKi) :: n(4) !< number of points in WvFreq1, WvFreq2, WvDir1, and WvDir2 + + 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) :: Pos_Lo(4) !< coordinate value with lower bound of dimension 1-4 + REAL(SiKi) :: Pos_Hi(4) !< coordinate value with upper bound of dimension 1-4 + + + + + ErrStat = ErrID_None + ErrMsg = "" + + n(1) = SIZE(WvFreq1) + n(2) = SIZE(WvFreq2) + n(3) = SIZE(WvDir1) + n(4) = SIZE(WvDir2) + + ! Check sizes of input: + IF ( SIZE( DataSet4D, 1 ) /= n(1) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet4D,1) must be the size(WvFreq1)', ErrStat, ErrMsg, 'WAMIT_Interp4D_Cplx' ) + IF ( SIZE( DataSet4D, 2 ) /= n(2) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet4D,2) must be the size(WvFreq2)', ErrStat, ErrMsg, 'WAMIT_Interp4D_Cplx' ) + IF ( SIZE( DataSet4D, 3 ) /= n(3) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet4D,3) must be the size(WvDir1)', ErrStat, ErrMsg, 'WAMIT_Interp4D_Cplx' ) + IF ( SIZE( DataSet4D, 4 ) /= n(4) ) CALL SetErrStat( ErrID_Fatal, 'Invalid dimensions: size(DataSet4D,4) must be the size(WvDir2)', ErrStat, ErrMsg, 'WAMIT_Interp4D_Cplx' ) + IF (ErrStat == ErrID_Fatal) RETURN + + + ! find the indices into the arrays representing coordinates of each dimension: + + Coords = InCoord + + DO i=3,4 ! make sure these requested degrees fall in the range -180 <= Coord(3:4) < 180 + Coords(i) = MODULO( Coords(i), 360.0_SiKi ) + IF ( Coords(i) >= 180.0_SiKi ) Coords(i) = Coords(i) - 360.0_SiKi + END DO + + CALL LocateStp( Coords(1), WvFreq1, LastIndex(1), n(1) ) + CALL LocateStp( Coords(2), WvFreq2, LastIndex(2), n(2) ) + CALL LocateStp( Coords(3), WvDir1, LastIndex(3), n(3) ) + CALL LocateStp( Coords(4), WvDir2, LastIndex(4), n(4) ) + + Indx_Lo = LastIndex + + + ! WvFreq1, WvFreq2 (indx 1, 2) + DO i=1,2 + IF (Indx_Lo(i) == 0) THEN + Indx_Lo(i) = 1 + ELSEIF (Indx_Lo(i) == n(i) ) THEN + Indx_Lo(i) = max( n(i) - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(i) = min( Indx_Lo(i) + 1, n(i) ) ! make sure it's a valid index + END DO + + + ! WvDir1, WvDir2 (indx 3,4) [use modular arithmetic] + DO i=3,4 + IF (Indx_Lo(i) == 0) THEN + Indx_Hi(i) = 1 + Indx_Lo(i) = n(i) + ELSEIF (Indx_Lo(i) == n(i) ) THEN + Indx_Hi(i) = 1 + ELSE + Indx_Hi(i) = min( Indx_Lo(i) + 1, n(i) ) ! make sure it's a valid index + END IF + END DO + + + ! calculate the positions of all dimensions: + + pos_Lo(1) = WvFreq1(Indx_Lo(1)) + pos_Hi(1) = WvFreq1(Indx_Hi(1)) + + pos_Lo(2) = WvFreq2(Indx_Lo(2)) + pos_Hi(2) = WvFreq2(Indx_Hi(2)) + + pos_Lo(3) = WvDir1(Indx_Lo(3)) + pos_Hi(3) = WvDir1(Indx_Hi(3)) + + pos_Lo(4) = WvDir2(Indx_Lo(4)) + pos_Hi(4) = WvDir2(Indx_Hi(4)) + + ! angles have to be adjusted so that pos_Lo(i) <= Coords(i) <= pos_Hi(i) + DO i=3,4 + IF ( Indx_Hi(i) == 1 .AND. n(i) > 1 ) THEN ! we're looping around the array [periodic] + IF ( pos_Lo(i) < Coords(i) ) THEN + pos_Hi(i) = pos_Hi(i) + 360.0_SiKi + ELSEIF ( pos_Lo(i) /= Coords(i) ) THEN !bjj: I think it's okay if we don't use equalRealNos here + pos_Lo(i) = pos_Lo(i) - 360.0_SiKi + END IF + END IF + END DO + + + + CALL Interp4D_withIndx_Cplx( Coords, DataSet4D, Indx_Lo, Indx_Hi, pos_Lo, pos_Hi, OutForce ) + + + + +END SUBROUTINE WAMIT_Interp4D_Cplx + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes a complex valued 2D dataset (InData2D) with the positions and indices of the bounding box and +!! performs 3-D linear interpolation to estimate the value of the dataset at InCoord. +!! It does not check that indices are valid or that the bounding box is non-degenerate (i.e., that posHi /= posLo) +!! +!! This method is described here: http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.Ch11.d/AFEM.Ch11.pdf +!! +SUBROUTINE Interp2D_withIndx_Cplx( InCoord, InData2D, Indx_Lo, Indx_Hi, posLo, posHi, InterpVal ) + + REAL(SiKi), INTENT(IN ) :: InCoord(2) !< Arranged as (x, y) + COMPLEX(SiKi), INTENT(IN ) :: InData2D(:,:) !< Arranged as Index 1= x, Index 2= y. + COMPLEX(SiKi), INTENT( OUT) :: InterpVal !< The interpolated value of DataSet2D at InCoord + + REAL(SiKi), INTENT(IN ) :: posLo(2) !< coordinate values associated with Indx_Lo + REAL(SiKi), INTENT(IN ) :: posHi(2) !< coordinate values associated with Indx_Hi + + INTEGER(IntKi), INTENT(IN ) :: Indx_Lo(2) !< index associated with lower bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + INTEGER(IntKi), INTENT(IN ) :: Indx_Hi(2) !< index associated with upper bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + + ! local variables + REAL(SiKi) :: isopc(2) ! isoparametric coordinates + + REAL(SiKi) :: N(4) ! size 2^n + COMPLEX(SiKi) :: u(4) ! size 2^n + + + CALL CalcIsoparCoords( InCoord, posLo, posHi, isopc ) ! Calculate iospc + + + N(1) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi - isopc(2) ) + N(2) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi + isopc(2) ) + N(3) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi + isopc(2) ) + N(4) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi - isopc(2) ) + N = N / REAL( SIZE(N), SiKi ) ! normalize + + u(1) = InData2D( Indx_Hi(1), Indx_Lo(2) ) + u(2) = InData2D( Indx_Hi(1), Indx_Hi(2) ) + u(3) = InData2D( Indx_Lo(1), Indx_Hi(2) ) + u(4) = InData2D( Indx_Lo(1), Indx_Lo(2) ) + + + InterpVal = SUM ( N * u ) + + +END SUBROUTINE Interp2D_withIndx_Cplx + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes a complex valued 3D dataset (InData3D) with the positions and indices of the bounding box and +!! performs 3-D linear interpolation to estimate the value of the dataset at InCoord. +!! It does not check that indices are valid or that the bounding box is non-degenerate (i.e., that posHi /= posLo) +!! +!! This method is described here: http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.Ch11.d/AFEM.Ch11.pdf +!! +SUBROUTINE Interp3D_withIndx_Cplx( InCoord, InData3D, Indx_Lo, Indx_Hi, posLo, posHi, InterpVal ) + + REAL(SiKi), INTENT(IN ) :: InCoord(3) !< Arranged as (x, y, z) + COMPLEX(SiKi), INTENT(IN ) :: InData3D(:,:,:) !< Arranged as Index 1= x, Index 2= y, Index 3= z. + COMPLEX(SiKi), INTENT( OUT) :: InterpVal !< The interpolated value of DataSet3D at InCoord + + REAL(SiKi), INTENT(IN ) :: posLo(3) !< xyz (coordinate) values associated with Indx_Lo + REAL(SiKi), INTENT(IN ) :: posHi(3) !< xyz (coordinate) values associated with Indx_Hi + + INTEGER(IntKi), INTENT(IN ) :: Indx_Lo(3) !< index associated with lower bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + INTEGER(IntKi), INTENT(IN ) :: Indx_Hi(3) !< index associated with upper bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + + ! local variables + REAL(SiKi) :: isopc(3) ! isoparametric hexahedral coordinates (natural coordinates) [ xi, eta, mu ] + + REAL(SiKi) :: N(8) ! size 2^n + COMPLEX(SiKi) :: u(8) ! size 2^n + + + CALL CalcIsoparCoords( InCoord, posLo, posHi, isopc ) ! Calculate iospc + + !eta = ( 2.0_SiKi*InCoord(1) - posLo(1) - posHi(1) ) / ( posHi(1) - posLo(1) ) !< (2*x - x1 - x2 ) / (x2-x1) !note that this is actually negative eta from the referenced paper, but it follows the other 2 dimensions better if we use the negative here and then flip the signs in N(:) (I think there is a bug in that paper) + !xi = ( 2.0_SiKi*InCoord(2) - posLo(2) - posHi(2) ) / ( posHi(2) - posLo(2) ) !< (2*y - y1 - y2 ) / (y2-y1) + !mu = ( 2.0_SiKi*InCoord(3) - posLo(3) - posHi(3) ) / ( posHi(3) - posLo(3) ) !< (2*z - z1 - z2 ) / (z2-z1) + + N(1) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi - isopc(2) )*( 1.0_SiKi - isopc(3) ) + N(2) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi + isopc(2) )*( 1.0_SiKi - isopc(3) ) + N(3) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi + isopc(2) )*( 1.0_SiKi - isopc(3) ) + N(4) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi - isopc(2) )*( 1.0_SiKi - isopc(3) ) + N(5) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi - isopc(2) )*( 1.0_SiKi + isopc(3) ) + N(6) = ( 1.0_SiKi + isopc(1) )*( 1.0_SiKi + isopc(2) )*( 1.0_SiKi + isopc(3) ) + N(7) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi + isopc(2) )*( 1.0_SiKi + isopc(3) ) + N(8) = ( 1.0_SiKi - isopc(1) )*( 1.0_SiKi - isopc(2) )*( 1.0_SiKi + isopc(3) ) + N = N / REAL( SIZE(N), SiKi ) ! normalize + + u(1) = InData3D( Indx_Hi(1), Indx_Lo(2), Indx_Lo(3) ) + u(2) = InData3D( Indx_Hi(1), Indx_Hi(2), Indx_Lo(3) ) + u(3) = InData3D( Indx_Lo(1), Indx_Hi(2), Indx_Lo(3) ) + u(4) = InData3D( Indx_Lo(1), Indx_Lo(2), Indx_Lo(3) ) + u(5) = InData3D( Indx_Hi(1), Indx_Lo(2), Indx_Hi(3) ) + u(6) = InData3D( Indx_Hi(1), Indx_Hi(2), Indx_Hi(3) ) + u(7) = InData3D( Indx_Lo(1), Indx_Hi(2), Indx_Hi(3) ) + u(8) = InData3D( Indx_Lo(1), Indx_Lo(2), Indx_Hi(3) ) + + + InterpVal = SUM ( N * u ) + + +END SUBROUTINE Interp3D_withIndx_Cplx + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes a complex valued 4D dataset (InData4D) with the positions and indices of the bounding box and +!! performs 4-D linear interpolation to estimate the value of the dataset at InCoord. +!! It does not check that indices are valid or that the bounding box is non-degenerate (i.e., that posHi /= posLo) +!! +!! This method is described here: http://rjwagner49.com/Mathematics/Interpolation.pdf +!! +SUBROUTINE Interp4D_withIndx_Cplx( InCoord, InData4D, Indx_Lo, Indx_Hi, posLo, posHi, InterpVal ) + + REAL(SiKi), INTENT(IN ) :: InCoord(4) !< Arranged as (x1, x2, x3, x4 ) + COMPLEX(SiKi), INTENT(IN ) :: InData4D(:,:,:,:) !< Arranged as Index 1= x1, Index 2= x2, Index 3= x3, Index 4= x4. + COMPLEX(SiKi), INTENT( OUT) :: InterpVal !< The interpolated value of InData4D at InCoord + + REAL(SiKi), INTENT(IN ) :: posLo(4) !< coordinate values associated with Indx_Lo + REAL(SiKi), INTENT(IN ) :: posHi(4) !< coordinate values associated with Indx_Hi + + INTEGER(IntKi), INTENT(IN ) :: Indx_Lo(4) !< index associated wtih lower bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + INTEGER(IntKi), INTENT(IN ) :: Indx_Hi(4) !< index associated wtih upper bound of dimension 1 where x(xIndx_lo) <= InCoord(1) <= x(xIndx_hi) + + ! local variables + REAL(SiKi) :: isopc(4) ! isoparametric coordinates + REAL(SiKi) :: N(16) ! size 2^n + COMPLEX(SiKi) :: u(16) ! size 2^n + + + CALL CalcIsoparCoords( InCoord, posLo, posHi, isopc ) ! Calculate iospc + + + 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 + + + u( 1) = InData4D( Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4) ) + u( 2) = InData4D( Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4) ) + u( 3) = InData4D( Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4) ) + u( 4) = InData4D( Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4) ) + u( 5) = InData4D( Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4) ) + u( 6) = InData4D( Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4) ) + u( 7) = InData4D( Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4) ) + u( 8) = InData4D( Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4) ) + u( 9) = InData4D( Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4) ) + u(10) = InData4D( Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4) ) + u(11) = InData4D( Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4) ) + u(12) = InData4D( Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4) ) + u(13) = InData4D( Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4) ) + u(14) = InData4D( Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4) ) + u(15) = InData4D( Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4) ) + u(16) = InData4D( Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4) ) + + + InterpVal = SUM ( N * u ) + + +END SUBROUTINE Interp4D_withIndx_Cplx + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine calculates the iosparametric coordinates, isopc, which is a value between -1 and 1 (for each dimension of a dataset) +!! indicating where InCoord falls between posLo and posHi. +!! +SUBROUTINE CalcIsoparCoords( InCoord, posLo, posHi, isopc ) + + + REAL(SiKi), INTENT(IN ) :: InCoord(:) !< Arranged as (x, y) + REAL(SiKi), INTENT(IN ) :: posLo(:) !< coordinate values associated with Indx_Lo + REAL(SiKi), INTENT(IN ) :: posHi(:) !< coordinate values associated with Indx_Hi + REAL(SiKi), INTENT( OUT) :: isopc(:) ! isoparametric coordinates + + ! local variables + REAL(SiKi) :: dx ! difference between high and low coordinates in the bounding "box" + INTEGER(IntKi) :: i ! loop counter + + + do i=1,size(isopc) + + dx = posHi(i) - posLo(i) + if (EqualRealNos(dx, 0.0_SiKi)) then + isopc(i) = 1.0_SiKi + else + isopc(i) = ( 2.0_SiKi*InCoord(i) - posLo(i) - posHi(i) ) / dx + ! to verify that we don't extrapolate, make sure this is bound between -1 and 1 (effectively nearest neighbor) + isopc(i) = min( 1.0_SiKi, isopc(i) ) + isopc(i) = max(-1.0_SiKi, isopc(i) ) + end if + + end do + +END SUBROUTINE CalcIsoparCoords + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE WAMIT_Interp diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT_Output.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT_Output.f90 new file mode 100644 index 000000000..51fb78d93 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT_Output.f90 @@ -0,0 +1,589 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 WAMIT_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + USE WAMIT_Types + !USE HydroDyn_Output_Types + USE Waves + IMPLICIT NONE + + PRIVATE + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + ! WAMIT Body Forces: + + INTEGER(IntKi), PARAMETER :: WavesF1xi = 1 + INTEGER(IntKi), PARAMETER :: WavesF1yi = 2 + INTEGER(IntKi), PARAMETER :: WavesF1zi = 3 + INTEGER(IntKi), PARAMETER :: WavesM1xi = 4 + INTEGER(IntKi), PARAMETER :: WavesM1yi = 5 + INTEGER(IntKi), PARAMETER :: WavesM1zi = 6 + INTEGER(IntKi), PARAMETER :: HdrStcFxi = 7 + INTEGER(IntKi), PARAMETER :: HdrStcFyi = 8 + INTEGER(IntKi), PARAMETER :: HdrStcFzi = 9 + INTEGER(IntKi), PARAMETER :: HdrStcMxi = 10 + INTEGER(IntKi), PARAMETER :: HdrStcMyi = 11 + INTEGER(IntKi), PARAMETER :: HdrStcMzi = 12 + INTEGER(IntKi), PARAMETER :: RdtnFxi = 13 + INTEGER(IntKi), PARAMETER :: RdtnFyi = 14 + INTEGER(IntKi), PARAMETER :: RdtnFzi = 15 + INTEGER(IntKi), PARAMETER :: RdtnMxi = 16 + INTEGER(IntKi), PARAMETER :: RdtnMyi = 17 + INTEGER(IntKi), PARAMETER :: RdtnMzi = 18 + + + +!End of code generated by Matlab script + + + INTEGER, PARAMETER :: FWaves1(6) = (/WavesF1xi,WavesF1yi,WavesF1zi,WavesM1xi,WavesM1yi,WavesM1zi/) + INTEGER, PARAMETER :: FHdrSttc(6) = (/HdrStcFxi,HdrStcFyi,HdrStcFzi,HdrStcMxi,HdrStcMyi,HdrStcMzi/) + INTEGER, PARAMETER :: FRdtn(6) = (/RdtnFxi,RdtnFyi,RdtnFzi,RdtnMxi,RdtnMyi,RdtnMzi/) + + + + ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 21-Mar-2013 08:13:04. + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(18) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "HDRSTCFXI","HDRSTCFYI","HDRSTCFZI","HDRSTCMXI","HDRSTCMYI","HDRSTCMZI", & + "RDTNFXI ","RDTNFYI ","RDTNFZI ","RDTNMXI ","RDTNMYI ","RDTNMZI ", & + "WAVESF1XI","WAVESF1YI","WAVESF1ZI","WAVESM1XI","WAVESM1YI","WAVESM1ZI"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(18) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + HdrStcFxi , HdrStcFyi , HdrStcFzi , HdrStcMxi , HdrStcMyi , HdrStcMzi , & + RdtnFxi , RdtnFyi , RdtnFzi , RdtnMxi , RdtnMyi , RdtnMzi , & + WavesF1xi, WavesF1yi, WavesF1zi, WavesM1xi, WavesM1yi, WavesM1zi/) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(18) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) "/) + + + REAL(ReKi) :: AllOuts(MaxWAMITOutputs) ! Array of all possible outputs + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: WMTOUT_MapOutputs + PUBLIC :: WMTOUT_WriteOutputNames + PUBLIC :: WMTOUT_WriteOutputUnits + PUBLIC :: WMTOUT_WriteOutputs + PUBLIC :: WMTOUT_Init + PUBLIC :: WMTOUT_DestroyParam + PUBLIC :: GetWAMITChannels + +CONTAINS + + + + +!==================================================================================================== +SUBROUTINE WMTOUT_MapOutputs( CurrentTime, y, F_Waves1, F_HS, F_Rdtn, F_PtfmAM, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by WAMIT_CalcOutput() at each time step. +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data + REAL(ReKi), INTENT( IN ) :: F_Waves1(6) + REAL(ReKi), INTENT( IN ) :: F_HS(6) + REAL(ReKi), INTENT( IN ) :: F_Rdtn(6) + REAL(ReKi), INTENT( IN ) :: F_PtfmAM(6) + REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMITOutputs) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! INTEGER :: I + + ErrStat = ErrID_None + ErrMsg = "" + + + ! TODO: use y%mesh for the forces instead of individual parameters + + !AllOuts(Time) = REAL(CurrentTime,ReKi) + AllOuts(FWaves1) = F_Waves1 + AllOuts(FHdrSttc) = F_HS + AllOuts(FRdtn) = F_Rdtn + F_PtfmAM + + + + + +END SUBROUTINE WMTOUT_MapOutputs + + +!==================================================================================================== + +SUBROUTINE WMTOUT_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) + +END SUBROUTINE WMTOUT_WriteOutputNames + +!==================================================================================================== + + +SUBROUTINE WMTOUT_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) + +END SUBROUTINE WMTOUT_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE WMTOUT_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in WMTOUT_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + INTEGER , INTENT( IN ) :: UnOutFile + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data + TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables +! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + + ! Initialize ErrStat and determine if it makes any sense to write output + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN + ErrMsg = ' No WAMIT outputs written. The OutParam array must be allocated and there must be a valid output file identifier before we can write outputs.' + ErrStat = ErrID_Warn + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + + + ! Write the output parameters to the file + + Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + + WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) + + + RETURN + + +END SUBROUTINE WMTOUT_WriteOutputs + + + +!==================================================================================================== +SUBROUTINE WMTOUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + + TYPE(WAMIT_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module + TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p + TYPE(WAMIT_InitOutputType), INTENT( OUT ) :: InitOut + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter +! INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array +! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! CHARACTER(200) :: Frmt ! a string to hold a format statement + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrMsg = "" + + + + + !------------------------------------------------------------------------------------------------- + ! Check that the variables in OutList are valid + !------------------------------------------------------------------------------------------------- + + + CALL WMTOUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) RETURN + + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + y%WriteOutput = 0.0_ReKi + + ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,p%NumOuts + + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + + END DO + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE WMTOUT_Init + + +!==================================================================================================== +FUNCTION GetWAMITChannels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if they +! below to the list of available WAMIT channels. + +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + CHARACTER(ChanLen), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. + LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER GetWAMITChannels ! The number of channels found in this module + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. + INTEGER :: count ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. +! LOGICAL :: InvalidOutput(MaxWAMITOutputs) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + + LOGICAL :: newFoundMask (NUserOutputs) ! A Mask indicating whether a user requested channel belongs to a modules output channels. + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + GetWAMITChannels = 0 + + newFoundMask = .FALSE. + + + DO I = 1,NUserOutputs + IF (.NOT. foundMask(I) ) THEN + OutListTmp = UserOutputs(I) +! foundMask(I) = .FALSE. + CheckOutListAgain = .FALSE. + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + newfoundMask(I) = .TRUE. + foundMask(I) = .TRUE. + GetWAMITChannels = GetWAMITChannels + 1 + + !ELSE + ! foundMask(I) = .FALSE. + END IF + END IF +END DO + + +IF ( GetWAMITChannels > 0 ) THEN + + count = 1 + ! Test that num channels does not exceed max possible channels due to size of OutList + !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutList array in the GetWAMITChannels function.' + ErrStat = ErrID_Fatal + RETURN + END IF + + DO I = 1,NUserOutputs + IF ( newfoundMask(I) ) THEN + OutList(count) = UserOutputs(I) + count = count + 1 + END IF + + END DO + +END IF + +END FUNCTION GetWAMITChannels + + +!==================================================================================================== +SUBROUTINE WMTOUT_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! Note that the Wamit module must be initialized prior to calling this function (if it +! is being used) so that it can correctly determine if the Lines outputs are valid. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT platform module + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. +! INTEGER :: J ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + + + ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 09-Jan-2013 14:53:03. + + LOGICAL :: InvalidOutput(MaxWAMITOutputs) ! This array determines if the output channel is valid for this configuration + + LOGICAL :: CheckOutListAgain + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + InvalidOutput = .FALSE. + +!End of code generated by Matlab script + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutParam array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' + ErrStat = ErrID_Fatal +! RETURN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + END DO + + + RETURN +END SUBROUTINE WMTOUT_ChkOutLst + + +!==================================================================================================== +SUBROUTINE WMTOUT_DestroyParam ( p, ErrStat, ErrMsg ) +! This function cleans up after running the WAMIT output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + Err = .FALSE. + + + + !------------------------------------------------------------------------------------------------- + ! Deallocate arrays + !------------------------------------------------------------------------------------------------- + IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + !------------------------------------------------------------------------------------------------- + ! Reset number of outputs + !------------------------------------------------------------------------------------------------- + p%NumOuts = 0 + p%UnOutFile = -1 + + !p%WaveKinNd = -1 ! set this array to "invalid" + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE WMTOUT_DestroyParam +!==================================================================================================== + + +END MODULE WAMIT_Output diff --git a/OpenFAST/modules/hydrodyn/src/WAMIT_Types.f90 b/OpenFAST/modules/hydrodyn/src/WAMIT_Types.f90 new file mode 100644 index 000000000..b321d6984 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/WAMIT_Types.f90 @@ -0,0 +1,5135 @@ +!STARTOFREGISTRYGENERATEDFILE 'WAMIT_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 +!********************************************************************************************************************************* +! WAMIT_Types +!................................................................................................................................. +! This file is part of WAMIT. +! +! 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 WAMIT. 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 WAMIT_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE Conv_Radiation_Types +USE SS_Radiation_Types +USE SS_Excitation_Types +USE Waves_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxWAMITOutputs = 18 ! [-] +! ========= WAMIT_InitInputType ======= + TYPE, PUBLIC :: WAMIT_InitInputType + REAL(ReKi) :: PtfmVol0 !< [-] + LOGICAL :: HasWAMIT !< .TRUE. if using WAMIT model, .FALSE. otherwise [-] + REAL(ReKi) :: WAMITULEN !< [-] + REAL(ReKi) :: PtfmCOBxt !< [-] + REAL(ReKi) :: PtfmCOByt !< [-] + INTEGER(IntKi) :: RdtnMod !< [-] + INTEGER(IntKi) :: ExctnMod !< [-] + REAL(DbKi) :: RdtnTMax !< [-] + REAL(ReKi) :: WaveDir !< [-] + CHARACTER(1024) :: WAMITFile !< [-] + TYPE(Conv_Rdtn_InitInputType) :: Conv_Rdtn !< [-] + REAL(ReKi) :: Rhoxg !< [-] + INTEGER(IntKi) :: NStepWave !< [-] + INTEGER(IntKi) :: NStepWave2 !< [-] + REAL(ReKi) :: WaveDOmega !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin (needed for SS_Excitation module) [m] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevC0 !< Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + INTEGER(IntKi) :: WaveMod !< [-] + REAL(ReKi) :: WtrDens !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveDirArr !< Array of wave directions (one per frequency) from the Waves module [-] + REAL(SiKi) :: WaveDirMin !< Minimum wave direction from Waves module [-] + REAL(SiKi) :: WaveDirMax !< Maximum wave direction from Waves module [-] + CHARACTER(ChanLen) , DIMENSION(1:18) :: OutList !< This should really be dimensioned with MaxOutPts [-] + LOGICAL :: OutAll !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + END TYPE WAMIT_InitInputType +! ======================= +! ========= WAMIT_InitOutputType ======= + TYPE, PUBLIC :: WAMIT_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + END TYPE WAMIT_InitOutputType +! ======================= +! ========= WAMIT_ContinuousStateType ======= + TYPE, PUBLIC :: WAMIT_ContinuousStateType + TYPE(SS_Rad_ContinuousStateType) :: SS_Rdtn !< continuous states from the State Space radiation module [-] + TYPE(SS_Exc_ContinuousStateType) :: SS_Exctn !< continuous states from the State Space radiation module [-] + TYPE(Conv_Rdtn_ContinuousStateType) :: Conv_Rdtn !< placeholder [-] + END TYPE WAMIT_ContinuousStateType +! ======================= +! ========= WAMIT_DiscreteStateType ======= + TYPE, PUBLIC :: WAMIT_DiscreteStateType + TYPE(Conv_Rdtn_DiscreteStateType) :: Conv_Rdtn !< discrete states from the convolution radiation module [-] + TYPE(SS_Rad_DiscreteStateType) :: SS_Rdtn !< placeholder [-] + TYPE(SS_Exc_DiscreteStateType) :: SS_Exctn !< placeholder [-] + END TYPE WAMIT_DiscreteStateType +! ======================= +! ========= WAMIT_ConstraintStateType ======= + TYPE, PUBLIC :: WAMIT_ConstraintStateType + TYPE(Conv_Rdtn_ConstraintStateType) :: Conv_Rdtn !< placeholder [-] + TYPE(SS_Rad_ConstraintStateType) :: SS_Rdtn !< placeholder [-] + TYPE(SS_Exc_ConstraintStateType) :: SS_Exctn !< placeholder [-] + END TYPE WAMIT_ConstraintStateType +! ======================= +! ========= WAMIT_OtherStateType ======= + TYPE, PUBLIC :: WAMIT_OtherStateType + TYPE(SS_Rad_OtherStateType) :: SS_Rdtn !< [-] + TYPE(SS_Exc_OtherStateType) :: SS_Exctn !< [-] + TYPE(Conv_Rdtn_OtherStateType) :: Conv_Rdtn !< [-] + END TYPE WAMIT_OtherStateType +! ======================= +! ========= WAMIT_MiscVarType ======= + TYPE, PUBLIC :: WAMIT_MiscVarType + INTEGER(IntKi) :: LastIndWave !< [-] + REAL(ReKi) , DIMENSION(1:6) :: F_HS !< local variable in CalcOutput:Total load contribution from hydrostatics, including the effects of waterplane area and the center of buoyancy [(N, N-m)] + REAL(ReKi) , DIMENSION(1:6) :: F_Waves1 !< local variable in CalcOutput:Total load contribution from incident waves (i.e., the diffraction problem) [(N, N-m)] + REAL(ReKi) , DIMENSION(1:6) :: F_Rdtn !< local variable in CalcOutput:Total load contribution from wave radiation damping (i.e., the diffraction problem) [(N, N-m)] + REAL(ReKi) , DIMENSION(1:6) :: F_PtfmAdd !< local variable in CalcOutput:set to zero because this is calculated in HydroDyn now [-] + REAL(ReKi) , DIMENSION(1:6) :: F_PtfmAM !< local variable in CalcOutput: [-] + TYPE(SS_Rad_MiscVarType) :: SS_Rdtn !< [-] + TYPE(SS_Rad_InputType) :: SS_Rdtn_u !< [-] + TYPE(SS_Rad_OutputType) :: SS_Rdtn_y !< [-] + TYPE(SS_Exc_MiscVarType) :: SS_Exctn !< [-] + TYPE(SS_Exc_InputType) :: SS_Exctn_u !< [-] + TYPE(SS_Exc_OutputType) :: SS_Exctn_y !< [-] + TYPE(Conv_Rdtn_MiscVarType) :: Conv_Rdtn !< [-] + TYPE(Conv_Rdtn_InputType) :: Conv_Rdtn_u !< [-] + TYPE(Conv_Rdtn_OutputType) :: Conv_Rdtn_y !< [-] + END TYPE WAMIT_MiscVarType +! ======================= +! ========= WAMIT_ParameterType ======= + TYPE, PUBLIC :: WAMIT_ParameterType + REAL(ReKi) , DIMENSION(1:6,1:6) :: HdroAdMsI !< [(sec)] + REAL(ReKi) , DIMENSION(1:6,1:6) :: HdroSttc !< [-] + REAL(ReKi) :: PtfmVol0 !< [-] + REAL(ReKi) :: PtfmCOBxt !< [-] + REAL(ReKi) :: PtfmCOByt !< [-] + INTEGER(IntKi) :: RdtnMod !< [-] + INTEGER(IntKi) :: ExctnMod !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveExctn !< [-] + REAL(ReKi) :: RhoXg !< [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< [-] + INTEGER(IntKi) :: NStepWave !< [-] + TYPE(Conv_Rdtn_ParameterType) :: Conv_Rdtn !< [-] + TYPE(SS_Rad_ParameterType) :: SS_Rdtn !< [-] + TYPE(SS_Exc_ParameterType) :: SS_Exctn !< [-] + REAL(DbKi) :: DT !< [-] + LOGICAL :: PtfmSgF !< [-] + LOGICAL :: PtfmSwF !< [-] + LOGICAL :: PtfmHvF !< [-] + LOGICAL :: PtfmRF !< [-] + LOGICAL :: PtfmPF !< [-] + LOGICAL :: PtfmYF !< [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + CHARACTER(20) :: OutFmt !< [-] + CHARACTER(20) :: OutSFmt !< [-] + CHARACTER(ChanLen) :: Delim !< [-] + INTEGER(IntKi) :: UnOutFile !< [-] + END TYPE WAMIT_ParameterType +! ======================= +! ========= WAMIT_InputType ======= + TYPE, PUBLIC :: WAMIT_InputType + TYPE(MeshType) :: Mesh !< Displacements at the WAMIT reference point in the inertial frame [-] + END TYPE WAMIT_InputType +! ======================= +! ========= WAMIT_OutputType ======= + TYPE, PUBLIC :: WAMIT_OutputType + TYPE(MeshType) :: Mesh !< Loads at the WAMIT reference point in the inertial frame [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + END TYPE WAMIT_OutputType +! ======================= +CONTAINS + SUBROUTINE WAMIT_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(WAMIT_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 = 'WAMIT_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%PtfmVol0 = SrcInitInputData%PtfmVol0 + DstInitInputData%HasWAMIT = SrcInitInputData%HasWAMIT + DstInitInputData%WAMITULEN = SrcInitInputData%WAMITULEN + DstInitInputData%PtfmCOBxt = SrcInitInputData%PtfmCOBxt + DstInitInputData%PtfmCOByt = SrcInitInputData%PtfmCOByt + DstInitInputData%RdtnMod = SrcInitInputData%RdtnMod + DstInitInputData%ExctnMod = SrcInitInputData%ExctnMod + DstInitInputData%RdtnTMax = SrcInitInputData%RdtnTMax + DstInitInputData%WaveDir = SrcInitInputData%WaveDir + DstInitInputData%WAMITFile = SrcInitInputData%WAMITFile + CALL Conv_Rdtn_CopyInitInput( SrcInitInputData%Conv_Rdtn, DstInitInputData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%Rhoxg = SrcInitInputData%Rhoxg + DstInitInputData%NStepWave = SrcInitInputData%NStepWave + DstInitInputData%NStepWave2 = SrcInitInputData%NStepWave2 + DstInitInputData%WaveDOmega = SrcInitInputData%WaveDOmega +IF (ALLOCATED(SrcInitInputData%WaveElev0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElev0,1) + i1_u = UBOUND(SrcInitInputData%WaveElev0,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElev0)) THEN + ALLOCATE(DstInitInputData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElev0 = SrcInitInputData%WaveElev0 +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevC0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevC0,1) + i1_u = UBOUND(SrcInitInputData%WaveElevC0,1) + i2_l = LBOUND(SrcInitInputData%WaveElevC0,2) + i2_u = UBOUND(SrcInitInputData%WaveElevC0,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevC0)) THEN + ALLOCATE(DstInitInputData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevC0 = SrcInitInputData%WaveElevC0 +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF + DstInitInputData%WaveMod = SrcInitInputData%WaveMod + DstInitInputData%WtrDens = SrcInitInputData%WtrDens +IF (ALLOCATED(SrcInitInputData%WaveDirArr)) THEN + i1_l = LBOUND(SrcInitInputData%WaveDirArr,1) + i1_u = UBOUND(SrcInitInputData%WaveDirArr,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveDirArr)) THEN + ALLOCATE(DstInitInputData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveDirArr = SrcInitInputData%WaveDirArr +ENDIF + DstInitInputData%WaveDirMin = SrcInitInputData%WaveDirMin + DstInitInputData%WaveDirMax = SrcInitInputData%WaveDirMax + DstInitInputData%OutList = SrcInitInputData%OutList + DstInitInputData%OutAll = SrcInitInputData%OutAll + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + END SUBROUTINE WAMIT_CopyInitInput + + SUBROUTINE WAMIT_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(WAMIT_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Conv_Rdtn_DestroyInitInput( InitInputData%Conv_Rdtn, ErrStat, ErrMsg ) +IF (ALLOCATED(InitInputData%WaveElev0)) THEN + DEALLOCATE(InitInputData%WaveElev0) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevC0)) THEN + DEALLOCATE(InitInputData%WaveElevC0) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF +IF (ALLOCATED(InitInputData%WaveDirArr)) THEN + DEALLOCATE(InitInputData%WaveDirArr) +ENDIF + END SUBROUTINE WAMIT_DestroyInitInput + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + Re_BufSz = Re_BufSz + 1 ! PtfmVol0 + Int_BufSz = Int_BufSz + 1 ! HasWAMIT + Re_BufSz = Re_BufSz + 1 ! WAMITULEN + Re_BufSz = Re_BufSz + 1 ! PtfmCOBxt + Re_BufSz = Re_BufSz + 1 ! PtfmCOByt + Int_BufSz = Int_BufSz + 1 ! RdtnMod + Int_BufSz = Int_BufSz + 1 ! ExctnMod + Db_BufSz = Db_BufSz + 1 ! RdtnTMax + Re_BufSz = Re_BufSz + 1 ! WaveDir + Int_BufSz = Int_BufSz + 1*LEN(InData%WAMITFile) ! WAMITFile + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! Rhoxg + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NStepWave2 + Re_BufSz = Re_BufSz + 1 ! WaveDOmega + Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no + IF ( ALLOCATED(InData%WaveElev0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev0) ! WaveElev0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevC0 allocated yes/no + IF ( ALLOCATED(InData%WaveElevC0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevC0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevC0) ! WaveElevC0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! WaveMod + Re_BufSz = Re_BufSz + 1 ! WtrDens + Int_BufSz = Int_BufSz + 1 ! WaveDirArr allocated yes/no + IF ( ALLOCATED(InData%WaveDirArr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveDirArr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDirArr) ! WaveDirArr + END IF + Re_BufSz = Re_BufSz + 1 ! WaveDirMin + Re_BufSz = Re_BufSz + 1 ! WaveDirMax + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! NumOuts + 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%PtfmVol0 + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%HasWAMIT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WAMITULEN + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCOBxt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCOByt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RdtnMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ExctnMod + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%RdtnTMax + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDir + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%WAMITFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%WAMITFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + CALL Conv_Rdtn_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 + ReKiBuf(Re_Xferred) = InData%Rhoxg + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave2 + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDOmega + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElev0) ) 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%WaveElev0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElev0,1), UBOUND(InData%WaveElev0,1) + ReKiBuf(Re_Xferred) = InData%WaveElev0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevC0) ) 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%WaveElevC0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevC0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevC0,2), UBOUND(InData%WaveElevC0,2) + DO i1 = LBOUND(InData%WaveElevC0,1), UBOUND(InData%WaveElevC0,1) + ReKiBuf(Re_Xferred) = InData%WaveElevC0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%WaveMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveDirArr) ) 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%WaveDirArr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDirArr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveDirArr,1), UBOUND(InData%WaveDirArr,1) + ReKiBuf(Re_Xferred) = InData%WaveDirArr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%WaveDirMin + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDirMax + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT_PackInitInput + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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%PtfmVol0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HasWAMIT = TRANSFER(IntKiBuf(Int_Xferred), OutData%HasWAMIT) + Int_Xferred = Int_Xferred + 1 + OutData%WAMITULEN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCOBxt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCOByt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RdtnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ExctnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RdtnTMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WaveDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%WAMITFile) + OutData%WAMITFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 Conv_Rdtn_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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%Rhoxg = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDOmega = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 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%WaveElev0)) DEALLOCATE(OutData%WaveElev0) + ALLOCATE(OutData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElev0,1), UBOUND(OutData%WaveElev0,1) + OutData%WaveElev0(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 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%WaveElevC0)) DEALLOCATE(OutData%WaveElevC0) + ALLOCATE(OutData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevC0,2), UBOUND(OutData%WaveElevC0,2) + DO i1 = LBOUND(OutData%WaveElevC0,1), UBOUND(OutData%WaveElevC0,1) + OutData%WaveElevC0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WaveMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDirArr 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%WaveDirArr)) DEALLOCATE(OutData%WaveDirArr) + ALLOCATE(OutData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveDirArr,1), UBOUND(OutData%WaveDirArr,1) + OutData%WaveDirArr(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WaveDirMin = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDirMax = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%OutList,1) + i1_u = UBOUND(OutData%OutList,1) + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT_UnPackInitInput + + SUBROUTINE WAMIT_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(WAMIT_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 = 'WAMIT_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE WAMIT_CopyInitOutput + + SUBROUTINE WAMIT_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(WAMIT_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE WAMIT_DestroyInitOutput + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE WAMIT_PackInitOutput + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE WAMIT_UnPackInitOutput + + SUBROUTINE WAMIT_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(WAMIT_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 = 'WAMIT_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SS_Rad_CopyContState( SrcContStateData%SS_Rdtn, DstContStateData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyContState( SrcContStateData%SS_Exctn, DstContStateData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Conv_Rdtn_CopyContState( SrcContStateData%Conv_Rdtn, DstContStateData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyContState + + SUBROUTINE WAMIT_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(WAMIT_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SS_Rad_DestroyContState( ContStateData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyContState( ContStateData%SS_Exctn, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyContState( ContStateData%Conv_Rdtn, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyContState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + 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 SS_Rad_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Exc_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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 Conv_Rdtn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 WAMIT_PackContState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + 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 SS_Rad_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Exc_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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 Conv_Rdtn_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 WAMIT_UnPackContState + + SUBROUTINE WAMIT_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(WAMIT_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 = 'WAMIT_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Conv_Rdtn_CopyDiscState( SrcDiscStateData%Conv_Rdtn, DstDiscStateData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Rad_CopyDiscState( SrcDiscStateData%SS_Rdtn, DstDiscStateData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyDiscState( SrcDiscStateData%SS_Exctn, DstDiscStateData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyDiscState + + SUBROUTINE WAMIT_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(WAMIT_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Conv_Rdtn_DestroyDiscState( DiscStateData%Conv_Rdtn, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyDiscState( DiscStateData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyDiscState( DiscStateData%SS_Exctn, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyDiscState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + 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 Conv_Rdtn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 SS_Rad_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Exc_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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 WAMIT_PackDiscState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + 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 Conv_Rdtn_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 SS_Rad_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Exc_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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 WAMIT_UnPackDiscState + + SUBROUTINE WAMIT_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(WAMIT_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 = 'WAMIT_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Conv_Rdtn_CopyConstrState( SrcConstrStateData%Conv_Rdtn, DstConstrStateData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Rad_CopyConstrState( SrcConstrStateData%SS_Rdtn, DstConstrStateData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyConstrState( SrcConstrStateData%SS_Exctn, DstConstrStateData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyConstrState + + SUBROUTINE WAMIT_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(WAMIT_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL Conv_Rdtn_DestroyConstrState( ConstrStateData%Conv_Rdtn, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyConstrState( ConstrStateData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyConstrState( ConstrStateData%SS_Exctn, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyConstrState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + 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 Conv_Rdtn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 SS_Rad_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Exc_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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 WAMIT_PackConstrState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + 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 Conv_Rdtn_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 SS_Rad_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Exc_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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 WAMIT_UnPackConstrState + + SUBROUTINE WAMIT_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(WAMIT_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 = 'WAMIT_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SS_Rad_CopyOtherState( SrcOtherStateData%SS_Rdtn, DstOtherStateData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyOtherState( SrcOtherStateData%SS_Exctn, DstOtherStateData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Conv_Rdtn_CopyOtherState( SrcOtherStateData%Conv_Rdtn, DstOtherStateData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyOtherState + + SUBROUTINE WAMIT_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(WAMIT_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SS_Rad_DestroyOtherState( OtherStateData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyOtherState( OtherStateData%SS_Exctn, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyOtherState( OtherStateData%Conv_Rdtn, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyOtherState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + 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 SS_Rad_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Exc_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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 Conv_Rdtn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 WAMIT_PackOtherState + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + 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 SS_Rad_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Exc_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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 Conv_Rdtn_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 WAMIT_UnPackOtherState + + SUBROUTINE WAMIT_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(WAMIT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + DstMiscData%F_HS = SrcMiscData%F_HS + DstMiscData%F_Waves1 = SrcMiscData%F_Waves1 + DstMiscData%F_Rdtn = SrcMiscData%F_Rdtn + DstMiscData%F_PtfmAdd = SrcMiscData%F_PtfmAdd + DstMiscData%F_PtfmAM = SrcMiscData%F_PtfmAM + CALL SS_Rad_CopyMisc( SrcMiscData%SS_Rdtn, DstMiscData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Rad_CopyInput( SrcMiscData%SS_Rdtn_u, DstMiscData%SS_Rdtn_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Rad_CopyOutput( SrcMiscData%SS_Rdtn_y, DstMiscData%SS_Rdtn_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyMisc( SrcMiscData%SS_Exctn, DstMiscData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyInput( SrcMiscData%SS_Exctn_u, DstMiscData%SS_Exctn_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyOutput( SrcMiscData%SS_Exctn_y, DstMiscData%SS_Exctn_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Conv_Rdtn_CopyMisc( SrcMiscData%Conv_Rdtn, DstMiscData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Conv_Rdtn_CopyInput( SrcMiscData%Conv_Rdtn_u, DstMiscData%Conv_Rdtn_u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Conv_Rdtn_CopyOutput( SrcMiscData%Conv_Rdtn_y, DstMiscData%Conv_Rdtn_y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyMisc + + SUBROUTINE WAMIT_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(WAMIT_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SS_Rad_DestroyMisc( MiscData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyInput( MiscData%SS_Rdtn_u, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyOutput( MiscData%SS_Rdtn_y, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyMisc( MiscData%SS_Exctn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyInput( MiscData%SS_Exctn_u, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyOutput( MiscData%SS_Exctn_y, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyMisc( MiscData%Conv_Rdtn, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyInput( MiscData%Conv_Rdtn_u, ErrStat, ErrMsg ) + CALL Conv_Rdtn_DestroyOutput( MiscData%Conv_Rdtn_y, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyMisc + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 ! LastIndWave + Re_BufSz = Re_BufSz + SIZE(InData%F_HS) ! F_HS + Re_BufSz = Re_BufSz + SIZE(InData%F_Waves1) ! F_Waves1 + Re_BufSz = Re_BufSz + SIZE(InData%F_Rdtn) ! F_Rdtn + Re_BufSz = Re_BufSz + SIZE(InData%F_PtfmAdd) ! F_PtfmAdd + Re_BufSz = Re_BufSz + SIZE(InData%F_PtfmAM) ! F_PtfmAM + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn_u: size of buffers for each call to pack subtype + CALL SS_Rad_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn_u, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn_y: size of buffers for each call to pack subtype + CALL SS_Rad_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn_y, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn_u: size of buffers for each call to pack subtype + CALL SS_Exc_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn_u, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn_y: size of buffers for each call to pack subtype + CALL SS_Exc_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn_y, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn_y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn_u: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn_u, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn_u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn_u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn_u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn_u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn_y: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn_y, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn_y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn_y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn_y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn_y + 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%LastIndWave + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%F_HS,1), UBOUND(InData%F_HS,1) + ReKiBuf(Re_Xferred) = InData%F_HS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_Waves1,1), UBOUND(InData%F_Waves1,1) + ReKiBuf(Re_Xferred) = InData%F_Waves1(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) + ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_PtfmAdd,1), UBOUND(InData%F_PtfmAdd,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAdd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_PtfmAM,1), UBOUND(InData%F_PtfmAM,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + CALL SS_Rad_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Rad_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn_u, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn_u + 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 SS_Rad_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn_y, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn_y + 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 SS_Exc_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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 SS_Exc_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn_u, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn_u + 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 SS_Exc_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn_y, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn_y + 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 Conv_Rdtn_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 Conv_Rdtn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn_u, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn_u + 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 Conv_Rdtn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn_y, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn_y + 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 WAMIT_PackMisc + + SUBROUTINE WAMIT_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(WAMIT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_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%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%F_HS,1) + i1_u = UBOUND(OutData%F_HS,1) + DO i1 = LBOUND(OutData%F_HS,1), UBOUND(OutData%F_HS,1) + OutData%F_HS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_Waves1,1) + i1_u = UBOUND(OutData%F_Waves1,1) + DO i1 = LBOUND(OutData%F_Waves1,1), UBOUND(OutData%F_Waves1,1) + OutData%F_Waves1(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_Rdtn,1) + i1_u = UBOUND(OutData%F_Rdtn,1) + DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) + OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_PtfmAdd,1) + i1_u = UBOUND(OutData%F_PtfmAdd,1) + DO i1 = LBOUND(OutData%F_PtfmAdd,1), UBOUND(OutData%F_PtfmAdd,1) + OutData%F_PtfmAdd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_PtfmAM,1) + i1_u = UBOUND(OutData%F_PtfmAM,1) + DO i1 = LBOUND(OutData%F_PtfmAM,1), UBOUND(OutData%F_PtfmAM,1) + OutData%F_PtfmAM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 SS_Rad_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Rad_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn_u, ErrStat2, ErrMsg2 ) ! SS_Rdtn_u + 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 SS_Rad_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn_y, ErrStat2, ErrMsg2 ) ! SS_Rdtn_y + 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 SS_Exc_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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 SS_Exc_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn_u, ErrStat2, ErrMsg2 ) ! SS_Exctn_u + 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 SS_Exc_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn_y, ErrStat2, ErrMsg2 ) ! SS_Exctn_y + 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 Conv_Rdtn_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 Conv_Rdtn_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn_u, ErrStat2, ErrMsg2 ) ! Conv_Rdtn_u + 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 Conv_Rdtn_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn_y, ErrStat2, ErrMsg2 ) ! Conv_Rdtn_y + 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 WAMIT_UnPackMisc + + SUBROUTINE WAMIT_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_ParameterType), INTENT(IN) :: SrcParamData + TYPE(WAMIT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%HdroAdMsI = SrcParamData%HdroAdMsI + DstParamData%HdroSttc = SrcParamData%HdroSttc + DstParamData%PtfmVol0 = SrcParamData%PtfmVol0 + DstParamData%PtfmCOBxt = SrcParamData%PtfmCOBxt + DstParamData%PtfmCOByt = SrcParamData%PtfmCOByt + DstParamData%RdtnMod = SrcParamData%RdtnMod + DstParamData%ExctnMod = SrcParamData%ExctnMod +IF (ALLOCATED(SrcParamData%WaveExctn)) THEN + i1_l = LBOUND(SrcParamData%WaveExctn,1) + i1_u = UBOUND(SrcParamData%WaveExctn,1) + i2_l = LBOUND(SrcParamData%WaveExctn,2) + i2_u = UBOUND(SrcParamData%WaveExctn,2) + IF (.NOT. ALLOCATED(DstParamData%WaveExctn)) THEN + ALLOCATE(DstParamData%WaveExctn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveExctn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveExctn = SrcParamData%WaveExctn +ENDIF + DstParamData%RhoXg = SrcParamData%RhoXg +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF + DstParamData%NStepWave = SrcParamData%NStepWave + CALL Conv_Rdtn_CopyParam( SrcParamData%Conv_Rdtn, DstParamData%Conv_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Rad_CopyParam( SrcParamData%SS_Rdtn, DstParamData%SS_Rdtn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SS_Exc_CopyParam( SrcParamData%SS_Exctn, DstParamData%SS_Exctn, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%DT = SrcParamData%DT + DstParamData%PtfmSgF = SrcParamData%PtfmSgF + DstParamData%PtfmSwF = SrcParamData%PtfmSwF + DstParamData%PtfmHvF = SrcParamData%PtfmHvF + DstParamData%PtfmRF = SrcParamData%PtfmRF + DstParamData%PtfmPF = SrcParamData%PtfmPF + DstParamData%PtfmYF = SrcParamData%PtfmYF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOutAll = SrcParamData%NumOutAll + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + DstParamData%UnOutFile = SrcParamData%UnOutFile + END SUBROUTINE WAMIT_CopyParam + + SUBROUTINE WAMIT_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(WAMIT_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%WaveExctn)) THEN + DEALLOCATE(ParamData%WaveExctn) +ENDIF +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF + CALL Conv_Rdtn_DestroyParam( ParamData%Conv_Rdtn, ErrStat, ErrMsg ) + CALL SS_Rad_DestroyParam( ParamData%SS_Rdtn, ErrStat, ErrMsg ) + CALL SS_Exc_DestroyParam( ParamData%SS_Exctn, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE WAMIT_DestroyParam + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + SIZE(InData%HdroAdMsI) ! HdroAdMsI + Re_BufSz = Re_BufSz + SIZE(InData%HdroSttc) ! HdroSttc + Re_BufSz = Re_BufSz + 1 ! PtfmVol0 + Re_BufSz = Re_BufSz + 1 ! PtfmCOBxt + Re_BufSz = Re_BufSz + 1 ! PtfmCOByt + Int_BufSz = Int_BufSz + 1 ! RdtnMod + Int_BufSz = Int_BufSz + 1 ! ExctnMod + Int_BufSz = Int_BufSz + 1 ! WaveExctn allocated yes/no + IF ( ALLOCATED(InData%WaveExctn) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveExctn upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveExctn) ! WaveExctn + END IF + Re_BufSz = Re_BufSz + 1 ! RhoXg + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! NStepWave + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Conv_Rdtn: size of buffers for each call to pack subtype + CALL Conv_Rdtn_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! Conv_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Conv_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Conv_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Conv_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Rdtn: size of buffers for each call to pack subtype + CALL SS_Rad_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Rdtn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Rdtn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Rdtn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Rdtn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SS_Exctn: size of buffers for each call to pack subtype + CALL SS_Exc_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, .TRUE. ) ! SS_Exctn + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SS_Exctn + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SS_Exctn + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SS_Exctn + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! PtfmSgF + Int_BufSz = Int_BufSz + 1 ! PtfmSwF + Int_BufSz = Int_BufSz + 1 ! PtfmHvF + Int_BufSz = Int_BufSz + 1 ! PtfmRF + Int_BufSz = Int_BufSz + 1 ! PtfmPF + Int_BufSz = Int_BufSz + 1 ! PtfmYF + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UnOutFile + 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 i2 = LBOUND(InData%HdroAdMsI,2), UBOUND(InData%HdroAdMsI,2) + DO i1 = LBOUND(InData%HdroAdMsI,1), UBOUND(InData%HdroAdMsI,1) + ReKiBuf(Re_Xferred) = InData%HdroAdMsI(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%HdroSttc,2), UBOUND(InData%HdroSttc,2) + DO i1 = LBOUND(InData%HdroSttc,1), UBOUND(InData%HdroSttc,1) + ReKiBuf(Re_Xferred) = InData%HdroSttc(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + ReKiBuf(Re_Xferred) = InData%PtfmVol0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCOBxt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtfmCOByt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%RdtnMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ExctnMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveExctn) ) 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%WaveExctn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveExctn,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveExctn,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveExctn,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveExctn,2), UBOUND(InData%WaveExctn,2) + DO i1 = LBOUND(InData%WaveExctn,1), UBOUND(InData%WaveExctn,1) + ReKiBuf(Re_Xferred) = InData%WaveExctn(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%RhoXg + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + CALL Conv_Rdtn_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Conv_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! Conv_Rdtn + 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 SS_Rad_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn + 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 SS_Exc_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%SS_Exctn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Exctn + 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%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF, IntKiBuf(1)) + 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 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT_PackParam + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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%HdroAdMsI,1) + i1_u = UBOUND(OutData%HdroAdMsI,1) + i2_l = LBOUND(OutData%HdroAdMsI,2) + i2_u = UBOUND(OutData%HdroAdMsI,2) + DO i2 = LBOUND(OutData%HdroAdMsI,2), UBOUND(OutData%HdroAdMsI,2) + DO i1 = LBOUND(OutData%HdroAdMsI,1), UBOUND(OutData%HdroAdMsI,1) + OutData%HdroAdMsI(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%HdroSttc,1) + i1_u = UBOUND(OutData%HdroSttc,1) + i2_l = LBOUND(OutData%HdroSttc,2) + i2_u = UBOUND(OutData%HdroSttc,2) + DO i2 = LBOUND(OutData%HdroSttc,2), UBOUND(OutData%HdroSttc,2) + DO i1 = LBOUND(OutData%HdroSttc,1), UBOUND(OutData%HdroSttc,1) + OutData%HdroSttc(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + OutData%PtfmVol0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCOBxt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtfmCOByt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RdtnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ExctnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn 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%WaveExctn)) DEALLOCATE(OutData%WaveExctn) + ALLOCATE(OutData%WaveExctn(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveExctn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveExctn,2), UBOUND(OutData%WaveExctn,2) + DO i1 = LBOUND(OutData%WaveExctn,1), UBOUND(OutData%WaveExctn,1) + OutData%WaveExctn(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%RhoXg = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NStepWave = 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 Conv_Rdtn_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%Conv_Rdtn, ErrStat2, ErrMsg2 ) ! Conv_Rdtn + 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 SS_Rad_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Rdtn, ErrStat2, ErrMsg2 ) ! SS_Rdtn + 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 SS_Exc_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%SS_Exctn, ErrStat2, ErrMsg2 ) ! SS_Exctn + 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%PtfmSgF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmSwF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmHvF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmRF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmPF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF) + Int_Xferred = Int_Xferred + 1 + OutData%PtfmYF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE WAMIT_UnPackParam + + SUBROUTINE WAMIT_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_InputType), INTENT(INOUT) :: SrcInputData + TYPE(WAMIT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%Mesh, DstInputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE WAMIT_CopyInput + + SUBROUTINE WAMIT_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(WAMIT_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%Mesh, ErrStat, ErrMsg ) + END SUBROUTINE WAMIT_DestroyInput + + SUBROUTINE WAMIT_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(WAMIT_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 = 'WAMIT_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 WAMIT_PackInput + + SUBROUTINE WAMIT_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(WAMIT_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_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 + 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 WAMIT_UnPackInput + + SUBROUTINE WAMIT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WAMIT_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(WAMIT_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'WAMIT_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE WAMIT_CopyOutput + + SUBROUTINE WAMIT_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(WAMIT_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE WAMIT_DestroyOutput + + SUBROUTINE WAMIT_PackOutput( 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(WAMIT_OutputType), 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 = 'WAMIT_PackOutput' + ! 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 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE WAMIT_PackOutput + + SUBROUTINE WAMIT_UnPackOutput( 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(WAMIT_OutputType), 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 = 'WAMIT_UnPackOutput' + ! 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE WAMIT_UnPackOutput + + + SUBROUTINE WAMIT_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(WAMIT_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(WAMIT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL WAMIT_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL WAMIT_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL WAMIT_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE WAMIT_Input_ExtrapInterp + + + SUBROUTINE WAMIT_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(WAMIT_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(WAMIT_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(WAMIT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE WAMIT_Input_ExtrapInterp1 + + + SUBROUTINE WAMIT_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(WAMIT_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(WAMIT_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(WAMIT_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(WAMIT_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE WAMIT_Input_ExtrapInterp2 + + + SUBROUTINE WAMIT_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL WAMIT_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL WAMIT_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL WAMIT_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE WAMIT_Output_ExtrapInterp + + + SUBROUTINE WAMIT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE WAMIT_Output_ExtrapInterp1 + + + SUBROUTINE WAMIT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(WAMIT_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE WAMIT_Output_ExtrapInterp2 + +END MODULE WAMIT_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/Waves.f90 b/OpenFAST/modules/hydrodyn/src/Waves.f90 new file mode 100644 index 000000000..a521c01d6 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves.f90 @@ -0,0 +1,2440 @@ +!********************************************************************************************************************************** +! The Waves and Waves_Types modules make up a template for creating user-defined calculations in the FAST Modularization +! Framework. Waves_Types will be auto-generated based on a description of the variables for the module. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of Waves. +! +! 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 Waves + + USE Waves_Types + USE UserWaves + USE NWTC_Library + USE NWTC_FFTPACK + USE NWTC_RandomNumber + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: Waves_ProgDesc = ProgDesc( 'Waves', '', '' ) + + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: WavePkShpDefault ! Return the default value of the peak shape parameter of the incident wave spectrum + PUBLIC :: Waves_Init ! Initialization routine + PUBLIC :: Waves_End ! Ending routine (includes clean up) + + + PRIVATE:: WheelerStretching ! This FUNCTION applies the principle of Wheeler stretching to (1-Forward) find the elevation where the wave kinematics are to be applied using Wheeler stretching or (2-Backword) + PRIVATE:: BoxMuller + PRIVATE:: JONSWAP + PUBLIC :: WaveNumber + PRIVATE:: UserWaveSpctrm + PRIVATE:: StillWaterWaves_Init + PRIVATE:: VariousWaves_Init + ! PRIVATE:: WhiteNoiseWaves_Init + +CONTAINS + +!======================================================================= + + FUNCTION WavePkShpDefault ( Hs, Tp ) + + + ! This FUNCTION is used to return the default value of the peak shape + ! parameter of the incident wave spectrum, conditioned on significant + ! wave height and peak spectral period. + ! + ! There are several different versions of the JONSWAP spectrum + ! formula. This version is based on the one documented in the + ! IEC61400-3 wind turbine design standard for offshore wind turbines. + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(IN ) :: Hs ! Significant wave height (meters) + REAL(SiKi), INTENT(IN ) :: Tp ! Peak spectral period (sec) + REAL(SiKi) :: WavePkShpDefault ! This function = default value of the peak shape parameter of the incident wave spectrum conditioned on significant wave height and peak spectral period (-) + + + ! Local Variables: + + REAL(SiKi) :: TpOvrSqrtHs ! = Tp/SQRT(Hs) (s/SQRT(m)) + + + + ! Compute the default peak shape parameter of the incident wave spectrum, + ! conditioned on significant wave height and peak spectral period: + + TpOvrSqrtHs = Tp/SQRT(Hs) + + IF ( TpOvrSqrtHs <= 3.6 ) THEN + WavePkShpDefault = 5.0 + ELSEIF ( TpOvrSqrtHs >= 5.0 ) THEN + WavePkShpDefault = 1.0 + ELSE + WavePkShpDefault = EXP( 5.75 - 1.15*TpOvrSqrtHs ) + END IF + + + + RETURN + END FUNCTION WavePkShpDefault + +!======================================================================= + FUNCTION BoxMuller ( RNGType, NDAmp, Phase ) + + ! This FUNCTION uses the Box-Muller method to turn two uniformly + ! distributed randoms into two unit normal randoms, which are + ! returned as real and imaginary components. + + IMPLICIT NONE + + COMPLEX(SiKi) :: BoxMuller ! This function + + ! Passed Variables: + + INTEGER, INTENT(IN) :: RNGType + LOGICAL, INTENT(IN) :: NDAmp ! Flag for normally-distributed amplitudes + REAL(SiKi), INTENT(IN), OPTIONAL :: Phase ! Optional phase to override random phase (radians) + + ! Local Variables: + + REAL(SiKi) :: C1 ! Intermediate variable + REAL(SiKi) :: C2 ! Intermediate variable + REAL(SiKi) :: U1(1) ! First uniformly distributed random + REAL(SiKi) :: U2(1) ! Second uniformly distributed random + + ! Compute the two uniformly distributed randoms: + ! NOTE: The first random, U1, cannot be zero else the LOG() function + ! below will blow up; there is no restriction on the value of the + ! second random, U2. + + U1 = 0.0 + DO WHILE ( U1(1) == 0.0 ) + CALL UniformRandomNumbers(RNGType, U1) + END DO + CALL UniformRandomNumbers(RNGType, U2) + + ! Compute intermediate variables: + + IF ( NDAmp ) THEN ! Normally-distributed amplitudes + C1 = SQRT( -2.0*LOG(U1(1)) ) + ELSE ! Constant amplitudes (ignore U1); therefore, C1 = SQRT( 2.0 ) = MEAN( SQRT( -2.0*LOG(U1) ) for a uniform distribution of U1 between 0 and 1 + C1 = SQRT( 2.0 ) + END IF + + IF ( PRESENT( Phase ) ) THEN ! Specified phase to replace random phase (ignore U2) + C2 = Phase + ELSE ! Uniformly-distributed phase + C2 = TwoPi*U2(1) + END IF + + ! Compute the unit normal randoms: + + BoxMuller = CMPLX( C1*COS(C2), C1*SIN(C2) ) + + RETURN + END FUNCTION BoxMuller +!======================================================================= + FUNCTION JONSWAP ( Omega, Hs, Tp, Gamma ) + + + ! This FUNCTION computes the JOint North Sea WAve Project + ! (JONSWAP) representation of the one-sided power spectral density + ! or wave spectrum given the frequency, Omega, peak shape + ! parameter, Gamma, significant wave height, Hs, and peak spectral + ! period, Tp, as inputs. If the value of Gamma is 1.0, the + ! Pierson-Moskowitz wave spectrum is returned. + ! + ! There are several different versions of the JONSWAP spectrum + ! formula. This version is based on the one documented in the + ! IEC61400-3 wind turbine design standard for offshore wind + ! turbines. + + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(IN ) :: Gamma ! Peak shape parameter (-) + REAL(SiKi), INTENT(IN ) :: Hs ! Significant wave height (meters) + REAL(SiKi) :: JONSWAP ! This function = JONSWAP wave spectrum, S (m^2/(rad/s)) + REAL(SiKi), INTENT(IN ) :: Omega ! Wave frequency (rad/s) + REAL(SiKi), INTENT(IN ) :: Tp ! Peak spectral period (sec) + + + ! Local Variables: + + REAL(SiKi) :: Alpha ! Exponent on Gamma used in the spectral formulation (-) + REAL(SiKi) :: C ! Normalising factor used in the spectral formulation (-) + REAL(SiKi) :: f ! Wave frequency (Hz) + REAL(SiKi) :: fp ! Peak spectral frequency (Hz) + REAL(SiKi) :: fpOvrf4 ! (fp/f)^4 + REAL(SiKi) :: Sigma ! Scaling factor used in the spectral formulation (-) + + REAL(SiKi) :: Inv2Pi = 0.15915494 + + ! Compute the JONSWAP wave spectrum, unless Omega is zero, in which case, + ! return zero: + + IF ( EqualRealNos(Omega, 0.0_SiKi) ) THEN ! When .TRUE., the formulation below is ill-conditioned; thus, the known value of zero is returned. + + + JONSWAP = 0.0 + + + ELSE ! Omega > 0.0; forumulate the JONSWAP spectrum. + + + ! Compute the wave frequency and peak spectral frequency in Hz: + + f = Inv2Pi*Omega + fp = 1/Tp + fpOvrf4 = (fp/f)**4 + + + ! Compute the normalising factor: + + C = 1.0 - ( 0.287*LOG(GAMMA) ) + + + ! Compute Alpha: + + IF ( f <= fp ) THEN + Sigma = 0.07 + ELSE + Sigma = 0.09 + END IF + +!bjj: Alpha = EXP( ( -0.5*( ( (f/fp) - 1.0 )/Sigma )**2 ) ) + Alpha = EXP( ( -0.5*( ( (f*Tp) - 1.0 )/Sigma )**2 ) ) !this works even if Tp is 0 (but using f/fp doesn't) + + + ! Compute the wave spectrum: + + JONSWAP = Inv2Pi*C*( 0.3125*Hs*Hs*fpOvrf4/f )*EXP( ( -1.25*fpOvrf4 ) )*( GAMMA**Alpha ) + + + END IF + + + + RETURN + END FUNCTION JONSWAP + !======================================================================= +!JASON: MOVE THIS USER-DEFINED ROUTINE (UserWaveSpctrm) TO THE UserSubs.f90 OF HydroDyn WHEN THE PLATFORM LOADING FUNCTIONALITY HAS BEEN DOCUMENTED!!!!! + SUBROUTINE UserWaveSpctrm ( Omega, WaveDir, DirRoot, WaveS1Sdd ) + + + ! This is a dummy routine for holding the place of a user-specified + ! wave spectrum. Modify this code to create your own spectrum. + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(IN ) :: Omega ! Wave frequency, rad/s. + REAL(SiKi), INTENT(IN ) :: WaveDir ! Incident wave propagation heading direction, degrees + REAL(SiKi), INTENT(OUT) :: WaveS1Sdd ! One-sided power spectral density of the wave spectrum per unit time for the current frequency component and heading direction, m^2/(rad/s). + + CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + + WaveS1Sdd = 0.0 + + + + RETURN + END SUBROUTINE UserWaveSpctrm + !======================================================================= + FUNCTION WaveNumber ( Omega, g, h ) + + + ! This FUNCTION solves the finite depth dispersion relationship: + ! + ! k*tanh(k*h)=(Omega^2)/g + ! + ! for k, the wavenumber (WaveNumber) given the frequency, Omega, + ! gravitational constant, g, and water depth, h, as inputs. A + ! high order initial guess is used in conjunction with a quadratic + ! Newton's method for the solution with seven significant digits + ! accuracy using only one iteration pass. The method is due to + ! Professor J.N. Newman of M.I.T. as found in routine EIGVAL of + ! the SWIM-MOTION-LINES (SML) software package in source file + ! Solve.f of the SWIM module. + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(ReKi), INTENT(IN ) :: g ! Gravitational acceleration (m/s^2) + REAL(SiKi), INTENT(IN ) :: h ! Water depth (meters) + REAL(SiKi), INTENT(IN ) :: Omega ! Wave frequency (rad/s) + REAL(SiKi) :: WaveNumber ! This function = wavenumber, k (1/m) + + + ! Local Variables: + + REAL(SiKi) :: A ! A temporary variable used in the solution. + REAL(SiKi) :: B ! A temporary variable used in the solution. + REAL(SiKi) :: C ! A temporary variable used in the solution. + REAL(SiKi) :: C2 ! A temporary variable used in the solution. + REAL(SiKi) :: CC ! A temporary variable used in the solution. + REAL(SiKi) :: E2 ! A temporary variable used in the solution. + REAL(SiKi) :: X0 ! A temporary variable used in the solution. + + + + ! Compute the wavenumber, unless Omega is zero, in which case, return + ! zero: + + IF ( Omega == 0.0 ) THEN ! When .TRUE., the formulation below is ill-conditioned; thus, the known value of zero is returned. + + + WaveNumber = 0.0 + + + ELSE ! Omega > 0.0; solve for the wavenumber as usual. + + + C = Omega*Omega*h/g + CC = C*C + + + ! Find X0: + + IF ( C <= 2.0 ) THEN + + X0 = SQRT(C)*( 1.0 + C*( 0.169 + (0.031*C) ) ) + + ELSE + + E2 = EXP(-2.0*C) + + X0 = C*( 1.0 + ( E2*( 2.0 - (12.0*E2) ) ) ) + + END IF + + + ! Find the WaveNumber: + + IF ( C <= 4.8 ) THEN + + C2 = CC - X0*X0 + A = 1.0/( C - C2 ) + B = A*( ( 0.5*LOG( ( X0 + C )/( X0 - C ) ) ) - X0 ) + + WaveNumber = ( X0 - ( B*C2*( 1.0 + (A*B*C*X0) ) ) )/h + + ELSE + + WaveNumber = X0/h + + END IF + + + END IF + + + + RETURN + END FUNCTION WaveNumber + + !======================================================================= + FUNCTION COSHNumOvrCOSHDen ( k, h, z ) + + + ! This FUNCTION computes the shallow water hyperbolic numerator + ! over denominator term in the wave kinematics expressions: + ! + ! COSH( k*( z + h ) )/COSH( k*h ) + ! + ! given the wave number, k, water depth, h, and elevation z, as + ! inputs. + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi) :: COSHNumOvrCOSHDen ! This function = COSH( k*( z + h ) )/COSH( k*h ) (-) + REAL(SiKi), INTENT(IN ) :: h ! Water depth ( h > 0 ) (meters) + REAL(SiKi), INTENT(IN ) :: k ! Wave number ( k >= 0 ) (1/m) + REAL(SiKi), INTENT(IN ) :: z ! Elevation (-h <= z <= 0 ) (meters) + + + + ! Compute the hyperbolic numerator over denominator: + + IF ( k*h > 89.4_SiKi ) THEN ! When .TRUE., the shallow water formulation will trigger a floating point overflow error; however, COSH( k*( z + h ) )/COSH( k*h ) = EXP( k*z ) + EXP( -k*( z + 2*h ) ) for large k*h. This equals the deep water formulation, EXP( k*z ), except near z = -h, because h > 14.23*wavelength (since k = 2*Pi/wavelength) in this case. + + COSHNumOvrCOSHDen = EXP( k*z ) + EXP( -k*( z + 2.0_SiKi*h ) ) + + ELSE ! 0 < k*h <= 89.4; use the shallow water formulation. + + COSHNumOvrCOSHDen =REAL( COSH( k*( z + h ) ),R8Ki)/COSH( k*h ) + + END IF + + + + RETURN + END FUNCTION COSHNumOvrCOSHDen +!======================================================================= + FUNCTION COSHNumOvrSINHDen ( k, h, z ) + + + ! This FUNCTION computes the shallow water hyperbolic numerator + ! over denominator term in the wave kinematics expressions: + ! + ! COSH( k*( z + h ) )/SINH( k*h ) + ! + ! given the wave number, k, water depth, h, and elevation z, as + ! inputs. + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi) :: COSHNumOvrSINHDen ! This function = COSH( k*( z + h ) )/SINH( k*h ) (-) + REAL(SiKi), INTENT(IN ) :: h ! Water depth ( h > 0 ) (meters) + REAL(SiKi), INTENT(IN ) :: k ! Wave number ( k >= 0 ) (1/m) + REAL(SiKi), INTENT(IN ) :: z ! Elevation (-h <= z <= 0 ) (meters) + + + + ! Compute the hyperbolic numerator over denominator: + + + IF ( k < EPSILON(0.0_SiKi) ) THEN ! When .TRUE., the shallow water formulation is ill-conditioned; thus, HUGE(k) is returned to approximate the known value of infinity. + + COSHNumOvrSINHDen = HUGE( k ) + + ELSEIF ( k*h > 89.4_SiKi ) THEN ! When .TRUE., the shallow water formulation will trigger a floating point overflow error; however, COSH( k*( z + h ) )/SINH( k*h ) = EXP( k*z ) + EXP( -k*( z + 2*h ) ) for large k*h. This equals the deep water formulation, EXP( k*z ), except near z = -h, because h > 14.23*wavelength (since k = 2*Pi/wavelength) in this case. + + COSHNumOvrSINHDen = EXP( k*z ) + EXP( -k*( z + 2*h ) ) + + ELSE ! 0 < k*h <= 89.4; use the shallow water formulation. + + COSHNumOvrSINHDen = COSH( k*( z + h ) )/SINH( k*h ) + + END IF + + + + RETURN + END FUNCTION COSHNumOvrSINHDen +!======================================================================= + FUNCTION COTH ( X ) + + + ! This FUNCTION computes the hyperbolic cotangent, + ! COSH(X)/SINH(X). + + + USE Precision + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi) :: COTH ! This function = COSH( X )/SINH( X ) (-) + REAL(SiKi), INTENT(IN ) :: X ! The argument (-) + + + + ! Compute the hyperbolic cotangent: + + IF ( X == 0.0_SiKi ) THEN ! When .TRUE., the formulation below is ill-conditioned; thus, HUGE(X) is returned to approximate the known value of infinity. + + COTH = HUGE( X ) + + ELSE ! X /= 0.0; use the numerically-stable computation of COTH(X) by means of TANH(X). + + COTH = 1.0_SiKi/TANH( X ) ! = COSH( X )/SINH( X ) + + END IF + + + + RETURN + END FUNCTION COTH + + !======================================================================= + FUNCTION SINHNumOvrSINHDen ( k, h, z ) + + + ! This FUNCTION computes the shallow water hyperbolic numerator + ! over denominator term in the wave kinematics expressions: + ! + ! SINH( k*( z + h ) )/SINH( k*h ) + ! + ! given the wave number, k, water depth, h, and elevation z, as + ! inputs. + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi) :: SINHNumOvrSINHDen ! This function = SINH( k*( z + h ) )/SINH( k*h ) (-) + REAL(SiKi), INTENT(IN ) :: h ! Water depth ( h > 0 ) (meters) + REAL(SiKi), INTENT(IN ) :: k ! Wave number ( k >= 0 ) (1/m) + REAL(SiKi), INTENT(IN ) :: z ! Elevation (-h <= z <= 0 ) (meters) + + + + ! Compute the hyperbolic numerator over denominator: + + IF ( k == 0.0_SiKi ) THEN ! When .TRUE., the shallow water formulation is ill-conditioned; thus, the known value of unity is returned. + + SINHNumOvrSINHDen = 1.0 + + ELSEIF ( k*h > 89.4_SiKi ) THEN ! When .TRUE., the shallow water formulation will trigger a floating point overflow error; however, SINH( k*( z + h ) )/SINH( k*h ) = EXP( k*z ) - EXP( -k*( z + 2*h ) ) for large k*h. This equals the deep water formulation, EXP( k*z ), except near z = -h, because h > 14.23*wavelength (since k = 2*Pi/wavelength) in this case. + + SINHNumOvrSINHDen = EXP( k*z ) - EXP( -k*( z + 2.0_SiKi*h ) ) + + ELSE ! 0 < k*h <= 89.4; use the shallow water formulation. + + SINHNumOvrSINHDen = SINH( k*( z + h ) )/SINH( k*h ) + + END IF + + + + RETURN + END FUNCTION SINHNumOvrSINHDen + + + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE StillWaterWaves_Init ( InitInp, InitOut, ErrStat, ErrMsg ) +! This routine initializes the waves data for WaveMod = 0 , or still water waves option +!---------------------------------------------------------------------------------------------------------------------------------- + + + TYPE(Waves_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(Waves_InitOutputType), INTENT(INOUT) :: InitOut ! Initialization output data + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local Variables + INTEGER :: I, J ! Generic index + INTEGER(IntKi) :: ErrStatTmp ! Temporary error status + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + + + ! Initialize everything to zero: + + InitOut%NStepWave = 2 ! We must have at least two elements in order to interpolate later on + InitOut%NStepWave2 = 1 + + ALLOCATE ( InitOut%WaveTime (0:InitOut%NStepWave ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveTime.', ErrStat,ErrMsg,'StillWaterWaves_Init') + ALLOCATE ( InitOut%WaveElev0 (0:InitOut%NStepWave ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElev0.', ErrStat,ErrMsg,'StillWaterWaves_Init') + ALLOCATE ( InitOut%WaveElevC0 (2, 0:InitOut%NStepWave2 ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevC0.',ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%WaveElev (0:InitOut%NStepWave,InitInp%NWaveElev ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElev.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%WaveDynP (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%WaveVel (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%WaveAcc (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%PWaveDynP0 (0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveDynP0.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%PWaveVel0 (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveVel0.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%PWaveAcc0 (0:InitOut%NStepWave,InitInp%NWaveKin,3) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveAcc0.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%nodeInWater(0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%nodeInWater.', ErrStat,ErrMsg,'StillWaterWaves_Init') + + ALLOCATE ( InitOut%WaveDirArr (0:InitOut%NStepWave2 ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDirArr.',ErrStat,ErrMsg,'StillWaterWaves_Init') + + + IF ( ErrStat >= AbortErrLev ) RETURN + + InitOut%WaveDOmega = 0.0 + InitOut%WaveTime = (/ 0.0_DbKi, 1.0_DbKi, 2.0_DbKi /) ! We must have at least two different time steps in the interpolation + InitOut%WaveElev0 = 0.0 + InitOut%WaveElevC0 = 0.0 + InitOut%WaveElev = 0.0 + InitOut%PWaveDynP0 = 0.0 + InitOut%PWaveVel0 = 0.0 + InitOut%PWaveAcc0 = 0.0 + InitOut%WaveDynP = 0.0 + InitOut%WaveVel = 0.0 + InitOut%WaveAcc = 0.0 + InitOut%WaveDirArr = 0.0 + + ! For creating animations of the sea surface, the WaveElevXY array is passed in with a series of x,y coordinates + ! (index 1). The second index corresponds to the number of points passed in. A two dimensional time series + ! is created with the first index corresponding to the timestep, and second index corresponding to the second + ! index of the WaveElevXY array. + IF ( ALLOCATED(InitInp%WaveElevXY)) THEN + ALLOCATE ( InitOut%WaveElevSeries (0:InitOut%NStepWave, 1:SIZE(InitInp%WaveElevXY, DIM=2)) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevSeries.',ErrStat,ErrMsg,'VariousWaves_Init') + RETURN + END IF + ! Calculate the wave elevation at all points requested in the array WaveElevXY + DO I = 0,InitOut%NStepWave + DO J = 1,SIZE(InitInp%WaveElevXY, DIM=2) + InitOut%WaveElevSeries(I,J) = 0.0_ReKi + ENDDO + ENDDO + ENDIF + + + ! Add the current velocities to the wave velocities: + + DO J = 1,InitInp%NWaveKin ! Loop through all Morison element nodes where the incident wave kinematics will be computed + + InitOut%WaveVel(:,J,1) = InitInp%CurrVxi(J) ! xi-direction + InitOut%WaveVel(:,J,2) = InitInp%CurrVyi(J) ! yi-direction + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + + InitOut%nodeInWater(:, J) = 1 + ELSE + InitOut%nodeInWater(:, J) = 0 + END IF + END DO ! J - All points where the incident wave kinematics will be computed + +END SUBROUTINE StillWaterWaves_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE VariousWaves_Init ( InitInp, InitOut, ErrStat, ErrMsg ) +! Compute the wave kinematics and related information for Plane progressive (regular) wave, JONSWAP/Pierson-Moskowitz spectrum +! (irregular) wave, or user-defined spectrum (irregular) wave. +!---------------------------------------------------------------------------------------------------------------------------------- + + TYPE(Waves_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(Waves_InitOutputType), INTENT(INOUT) :: InitOut ! Output data + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + ! Local Variables + COMPLEX(SiKi), PARAMETER :: ImagNmbr = (0.0,1.0) ! The imaginary number, SQRT(-1.0) + COMPLEX(SiKi) :: ImagOmega ! = ImagNmbr*Omega (rad/s) + ! REAL(SiKi), ALLOCATABLE :: WaveElev0 (:) ! Instantaneous elevation of incident waves at the platform reference point (meters) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveAccC0HxiPz0 (:,:) ! Partial derivative of WaveAccC0Hxi(:) with respect to zi at zi = 0 (1/s^2) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveAccC0HyiPz0 (:,:) ! Partial derivative of WaveAccC0Hyi(:) with respect to zi at zi = 0 (1/s^2) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveAccC0VPz0 (:,:) ! Partial derivative of WaveAccC0V (:) with respect to zi at zi = 0 (1/s^2) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveDynPC0BPz0(:,:) ! Partial derivative of WaveDynPC0B (:) with respect to zi at zi = 0 (N/m ) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveVelC0HxiPz0 (:,:) ! Partial derivative of WaveVelC0Hxi(:) with respect to zi at zi = 0 (1/s ) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveVelC0HyiPz0 (:,:) ! Partial derivative of WaveVelC0Hyi(:) with respect to zi at zi = 0 (1/s ) + !COMPLEX(SiKi), ALLOCATABLE :: PWaveVelC0VPz0 (:,:) ! Partial derivative of WaveVelC0V (:) with respect to zi at zi = 0 (1/s ) + COMPLEX(SiKi), ALLOCATABLE :: WaveAccC0Hxi(:,:) ! Discrete Fourier transform of the instantaneous horizontal acceleration in x-direction of incident waves before applying stretching at the zi-coordinates for points (m/s^2) + COMPLEX(SiKi), ALLOCATABLE :: WaveAccC0Hyi(:,:) ! Discrete Fourier transform of the instantaneous horizontal acceleration in y-direction of incident waves before applying stretching at the zi-coordinates for points (m/s^2) + COMPLEX(SiKi), ALLOCATABLE :: WaveAccC0V(:,:) ! Discrete Fourier transform of the instantaneous vertical acceleration of incident waves before applying stretching at the zi-coordinates for points (m/s^2) + COMPLEX(SiKi), ALLOCATABLE :: WaveDynPC0(:,:) ! Discrete Fourier transform of the instantaneous dynamic pressure of incident waves before applying stretching at the zi-coordinates for points (N/m^2) + COMPLEX(SiKi), ALLOCATABLE :: WaveElevC (:,:) ! Discrete Fourier transform of the instantaneous elevation of incident waves (meters) + COMPLEX(SiKi), ALLOCATABLE :: WaveVelC0Hxi(:,:) ! Discrete Fourier transform of the instantaneous horizontal velocity of incident waves before applying stretching at the zi-coordinates for points (m/s) + COMPLEX(SiKi), ALLOCATABLE :: WaveVelC0Hyi(:,:) ! Discrete Fourier transform of the instantaneous horizontal velocity in x-direction of incident waves before applying stretching at the zi-coordinates for points (m/s) + COMPLEX(SiKi), ALLOCATABLE :: WaveVelC0V(:,:) ! Discrete Fourier transform of the instantaneous vertical velocity in y-direction of incident waves before applying stretching at the zi-coordinates for points (m/s) + COMPLEX(SiKi) :: WGNC ! Discrete Fourier transform of the realization of a White Gaussian Noise (WGN) time series process with unit variance for the current frequency component (-) +! REAL(SiKi) :: CurrVxi ! xi-component of the current velocity at the instantaneous elevation (m/s) +! REAL(SiKi) :: CurrVyi ! yi-component of the current velocity at the instantaneous elevation (m/s) +! REAL(SiKi) :: CurrVxi0 ! xi-component of the current velocity at zi = 0.0 meters (m/s) +! REAL(SiKi) :: CurrVyi0 ! yi-component of the current velocity at zi = 0.0 meters (m/s) +! REAL(SiKi) :: CurrVxiS ! xi-component of the current velocity at zi = -SmllNmbr meters (m/s) +! REAL(SiKi) :: CurrVyiS ! yi-component of the current velocity at zi = -SmllNmbr meters (m/s) + REAL(SiKi), ALLOCATABLE :: CosWaveDir(:) ! COS( WaveDirArr(I) ) -- Each wave frequency has a unique wave direction. + REAL(SiKi), ALLOCATABLE :: GHWaveAcc (:,:) ! Instantaneous acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the GHNWvDpth vertical locations in GH Bladed wave data files (m/s^2) + REAL(SiKi), ALLOCATABLE :: GHWaveDynP(: ) ! Instantaneous dynamic pressure of incident waves at each of the GHNWvDpth vertical locations in GH Bladed wave data files (N/m^2) +! REAL(SiKi) :: GHWaveTime ! Instantaneous simulation times in GH Bladed wave data files (sec) + REAL(SiKi), ALLOCATABLE :: GHWaveVel (:,:) ! Instantaneous velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the GHNWvDpth vertical locations in GH Bladed wave data files (m/s ) + REAL(SiKi), ALLOCATABLE :: GHWvDpth (:) ! Vertical locations in GH Bladed wave data files. +!UNUSED: !REAL(SiKi), PARAMETER :: n_Massel = 3.0 ! Factor used to the scale the peak spectral frequency in order to find the cut-off frequency based on the suggestion in: Massel, S. R., Ocean Surface Waves: Their Physics and Prediction, Advanced Series on Ocean Engineering - Vol. 11, World Scientific Publishing, Singapore - New Jersey - London - Hong Kong, 1996. This reference recommends n_Massel > 3.0 (higher for higher-order wave kinemetics); the ">" designation is accounted for by checking if ( Omega > OmegaCutOff ). + REAL(SiKi) :: Omega ! Wave frequency (rad/s) +!UNUSED: !REAL(SiKi) :: OmegaCutOff ! Cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s) +!UNUSED: ! REAL(SiKi) :: PCurrVxiPz0 ! Partial derivative of CurrVxi with respect to zi at zi = 0 (1/s ) +!UNUSED: ! REAL(SiKi) :: PCurrVyiPz0 ! Partial derivative of CurrVyi with respect to zi at zi = 0 (1/s ) + !REAL(SiKi), ALLOCATABLE :: PWaveAcc0HxiPz0(:,:) ! Partial derivative of WaveAcc0Hxi(:) with respect to zi at zi = 0 (1/s^2) + !REAL(SiKi), ALLOCATABLE :: PWaveAcc0HyiPz0(:,:) ! Partial derivative of WaveAcc0Hyi(:) with respect to zi at zi = 0 (1/s^2) + !REAL(SiKi), ALLOCATABLE :: PWaveAcc0VPz0 (:,:) ! Partial derivative of WaveAcc0V (:) with respect to zi at zi = 0 (1/s^2) + !REAL(SiKi), ALLOCATABLE :: PWaveDynP0BPz0 (:,:) ! Partial derivative of WaveDynP0B (:) with respect to zi at zi = 0 (N/m ) + !REAL(SiKi), ALLOCATABLE :: PWaveVel0HxiPz0(:,:) ! Partial derivative of WaveVel0Hxi(:) with respect to zi at zi = 0 (1/s ) + !REAL(SiKi), ALLOCATABLE :: PWaveVel0HyiPz0(:,:) ! Partial derivative of WaveVel0Hyi(:) with respect to zi at zi = 0 (1/s ) + !REAL(SiKi), ALLOCATABLE :: PWaveVel0VPz0 (:,:) ! Partial derivative of WaveVel0V (:) with respect to zi at zi = 0 (1/s ) +! REAL(SiKi) :: Slope ! Miscellanous slope used in an interpolation (-) + REAL(SiKi), PARAMETER :: SmllNmbr = 9.999E-4 ! A small number representing epsilon for taking numerical derivatives. !bjj: how about using SQRT(EPSILON())? + REAL(SiKi) :: SQRTNStepWave2 ! SQRT( NStepWave/2 ) + REAL(SiKi), ALLOCATABLE :: SinWaveDir (:) ! SIN( WaveDirArr(I) ) + REAL(SiKi), ALLOCATABLE :: WaveAcc0Hxi (:,:) ! Instantaneous horizontal acceleration in x-direction of incident waves before applying stretching at the zi-coordinates for points (m/s^2) + REAL(SiKi), ALLOCATABLE :: WaveAcc0Hyi (:,:) ! Instantaneous horizontal acceleration in y-direction of incident waves before applying stretching at the zi-coordinates for points (m/s^2) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveAcc0HxiExtrap ! Temporary value extrapolated from the WaveAcc0Hxi(:,:) array (m/s^2) +! REAL(SiKi) :: WaveAcc0HxiExtrap ! Temporary value extrapolated from the WaveAcc0Hxi(:,:) array (m/s^2) +! REAL(SiKi) :: WaveAcc0HyiInterp ! Temporary value interpolated from the WaveAcc0Hyi(:,:) array (m/s^2) +! REAL(SiKi) :: WaveAcc0HyiInterp ! Temporary value interpolated from the WaveAcc0Hyi(:,:) array (m/s^2) + REAL(SiKi), ALLOCATABLE :: WaveAcc0V (:,:) ! Instantaneous vertical acceleration of incident waves before applying stretching at the zi-coordinates for points (m/s^2) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveAcc0VExtrap ! Temporary value extrapolated from the WaveAcc0V (:,:) array (m/s^2) +! REAL(SiKi) :: WaveAcc0VInterp ! Temporary value interpolated from the WaveAcc0V (:,:) array (m/s^2) + REAL(SiKi), ALLOCATABLE :: WaveDynP0B(:,:) ! Instantaneous dynamic pressure of incident waves before applying stretching at the zi-coordinates for points (N/m^2) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveDynP0BExtrap ! Temporary value extrapolated from the WaveDynP0B (:,:) array (N/m^2) +! REAL(SiKi) :: WaveDynP0BInterp ! Temporary value interpolated from the WaveDynP0B (:,:) array (N/m^2) +! REAL(SiKi) :: WaveElev_Max ! Maximum expected value of the instantaneous elevation of incident waves (meters) +! REAL(SiKi) :: WaveElev_Min ! Minimum expected value of the instantaneous elevation of incident waves (meters) + COMPLEX(SiKi) :: WaveElevxiPrime0 + REAL(SiKi), ALLOCATABLE :: WaveKinzi0Prime(:) ! zi-coordinates for points where the incident wave kinematics will be computed before applying stretching; these are relative to the mean see level (meters) + INTEGER , ALLOCATABLE :: WaveKinPrimeMap(:) +! REAL(SiKi), ALLOCATABLE :: WaveKinzi0St (:) ! Array of elevations found by stretching the elevations in the WaveKinzi0Prime(:) array using the instantaneous wave elevation; these are relative to the mean see level (meters) + REAL(SiKi) :: WaveNmbr ! Wavenumber of the current frequency component (1/meter) + REAL(SiKi) :: WaveS1Sdd ! One-sided power spectral density of the wave spectrum per unit time for the current frequency component (m^2/(rad/s)) + REAL(SiKi) :: WaveS2Sdd ! Two-sided power spectral density of the wave spectrum per unit time for the current frequency component (m^2/(rad/s)) + REAL(DbKi) :: WaveTMax ! Analysis time for incident wave calculations (sec) + REAL(SiKi), ALLOCATABLE :: WaveVel0Hxi (:,:) ! Instantaneous xi-direction velocity of incident waves before applying stretching at the zi-coordinates for points (m/s ) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveVel0HxiExtrap ! Temporary value extrapolated from the WaveVel0Hxi(:,:) array (m/s ) +! REAL(SiKi) :: WaveVel0HxiInterp ! Temporary value interpolated from the WaveVel0Hxi(:,:) array (m/s ) + REAL(SiKi), ALLOCATABLE :: WaveVel0Hyi (:,:) ! Instantaneous yi-direction velocity of incident waves before applying stretching at the zi-coordinates for points (m/s ) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveVel0HyiExtrap ! Temporary value extrapolated from the WaveVel0Hyi(:,:) array (m/s ) +! REAL(SiKi) :: WaveVel0HyiInterp ! Temporary value interpolated from the WaveVel0Hyi(:,:) array (m/s ) + REAL(SiKi), ALLOCATABLE :: WaveVel0V (:,:) ! Instantaneous vertical velocity of incident waves before applying stretching at the zi-coordinates for points (m/s ) +!UNUSED: for future wave stretching +! REAL(SiKi) :: WaveVel0VExtrap ! Temporary value extrapolated from the WaveVel0V (:,:) array (m/s ) +! REAL(SiKi) :: WaveVel0VInterp ! Temporary value interpolated from the WaveVel0V (:,:) array (m/s ) +! REAL(SiKi) :: zi_Max ! Maximum elevation where the wave kinematics are to be applied using stretching to the instantaneous free surface (meters) +! REAL(SiKi) :: zi_Min ! Minimum elevation where the wave kinematics are to be applied using stretching to the instantaneous free surface (meters) +! REAL(SiKi) :: ziPrime_Max ! Maximum elevation where the wave kinematics are computed before applying stretching to the instantaneous free surface (meters) +! REAL(SiKi) :: ziPrime_Min ! Minimum elevation where the wave kinematics are computed before applying stretching to the instantaneous free surface (meters) + +! REAL(SiKi) :: WGNC_Fact +! INTEGER :: GHNStepWave ! Total number of time steps in the GH Bladed wave data files. +! INTEGER :: GHNWvDpth ! Number of vertical locations in GH Bladed wave data files. + INTEGER :: I ! Generic index +! INTEGER :: I_Orig ! The index of the time step from original (input) part of data + INTEGER :: I_WaveTp ! The index of the frequency component nearest to WaveTp + INTEGER :: J ! Generic index + INTEGER :: J_Min ! The minimum value of index J such that WaveKinzi(J) >= -WtrDpth + INTEGER :: K ! Generic index + INTEGER :: LastInd ! Index into the arrays saved from the last call as a starting point for this call + INTEGER :: nSeeds ! number of seeds required to initialize the intrinsic random number generator + INTEGER :: NWaveKin0Prime ! Number of points where the incident wave kinematics will be computed before applying stretching to the instantaneous free surface (-) + INTEGER, ALLOCATABLE :: TmpWaveSeeds (:) ! A temporary array used for portability. IVF/CVF use a random number generator initialized with 2 seeds; other platforms can use different implementations (e.g. gfortran needs 8 or 12 seeds) + COMPLEX(SiKi) :: tmpComplex ! A temporary varible to hold the complex value of the wave elevation before storing it into a REAL array + COMPLEX(SiKi),ALLOCATABLE :: tmpComplexArr(:) ! A temporary array (0:NStepWave2-1) for FFT use. + TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using + + ! Variables for mult-direction waves + INTEGER(IntKi) :: WaveNDirMax !< Maximum value we can change WaveNDir to (relative to original value passed in). Used in finding new WaveNDir value. + INTEGER(IntKi) :: WvSpreadNDir !< Number of wave spreading directions for intermediate calculations. Set later to be MAX(15*InitOut%WaveNDir,1000) + INTEGER(IntKi) :: WvSpreadFreqPerDir !< Number of wave frequencies per direction + REAL(SiKi), ALLOCATABLE :: WvSpreadCos2SArr(:) !< Wave spreading function results array. Used in equal energy wave spreading function. + REAL(SiKi) :: WvSpreadCos2SConst !< Normalization constant for wave spreading function. + REAL(SiKi), ALLOCATABLE :: WvSpreadIntegral(:) !< Cumulative integral of the wave spreading function. Used in finding equal energy wave directions. + REAL(SiKi) :: WvSpreadDTheta !< Wave direction step size for intermediate calculations. Used in finding equal energy wave directions. + REAL(SiKi), ALLOCATABLE :: WvSpreadThetas(:) !< Wave direction used in calculations and interpolations + REAL(SiKi), ALLOCATABLE :: WvSpreadThetaIdx(:) !< Indices for wave directions + REAL(SiKi), ALLOCATABLE :: WvTheta(:) !< Final set of wave directions (degrees) + REAL(SiKi) :: WvSpreadIntegralTmp !< Temporary variable for the interpolation + + + ! Variables for error handling + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status + CHARACTER(ErrMsgLen) :: ErrMsgTmp !< Temporary error message + CHARACTER(ErrMsgLen) :: ErrMsgTmp2 !< Another temporary error message + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + ! Set the WaveNDir information (number of wave directions). + ! -> Since this must be adjusted later, put it in InitOut first and adjust that later in the code. + InitOut%WaveNDir = InitInp%WaveNDir + InitOut%WaveDir = InitInp%WaveDir ! We may want this value later (I had a nasty surprise when this wasn't set) + WaveNDirMax = CEILING(InitOut%WaveNDir*1.25_SiKi) ! Value we allow WaveNDir to reach before aborting + + + + + + ! Tell our nice users what is about to happen that may take a while: + + CALL WrScr ( ' Generating incident wave kinematics and current time history.' ) + + + + ! Determine the number of, NWaveKin0Prime, and the zi-coordinates for, + ! WaveKinzi0Prime(:), points where the incident wave kinematics will be + ! computed before applying stretching to the instantaneous free surface. + ! The locations are relative to the mean see level. Also determine J_Min, + ! which is the minimum value of index J such that WaveKinzi(J) >= + ! -WtrDpth. These depend on which incident wave kinematics stretching + ! method is being used: + +!JASON: ADD OTHER STRETCHING METHODS HERE, SUCH AS: DELTA STRETCHING (SEE ISO 19901-1) OR CHAKRABARTI STRETCHING (SEE OWTES)??? +!JASON: APPLY STRETCHING TO THE DYNAMIC PRESSURE, IF YOU EVER COMPUTE THAT HERE!!! + +! SELECT CASE ( InitInp%WaveStMod ) ! Which model are we using to extrapolate the incident wave kinematics to the instantaneous free surface? + +! CASE ( 0 ) ! None=no stretching. + + + ! Since we have no stretching, NWaveKin0Prime and WaveKinzi0Prime(:) are + ! equal to the number of, and the zi-coordinates for, the points in the + ! WaveKinzi(:) array between, and including, -WtrDpth and 0.0. + + ! Determine J_Min and NWaveKin0Prime here: + + J_Min = 0 + NWaveKin0Prime = 0 + DO J = 1,InitInp%NWaveKin ! Loop through all mesh points where the incident wave kinematics will be computed + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + NWaveKin0Prime = NWaveKin0Prime + 1 + END IF + END DO ! J - All Morison nodes where the incident wave kinematics will be computed + + + + ! ALLOCATE the WaveKinzi0Prime(:) array and compute its elements here: + + ALLOCATE ( WaveKinzi0Prime(NWaveKin0Prime) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveKinzi0Prime.',ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveKinPrimeMap(NWaveKin0Prime) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveKinPrimeMap.',ErrStat,ErrMsg,'VariousWaves_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + I = 1 + + DO J = 1,InitInp%NWaveKin ! Loop through all points where the incident wave kinematics will be computed without stretching + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + + WaveKinzi0Prime(I) = InitInp%WaveKinzi(J) + WaveKinPrimeMap(I) = J + I = I + 1 + + END IF + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + + +! CASE ( 1, 2 ) ! Vertical stretching or extrapolation stretching. + + + ! Vertical stretching says that the wave kinematics above the mean sea level + ! equal the wave kinematics at the mean sea level. The wave kinematics + ! below the mean sea level are left unchanged. + ! + ! Extrapolation stretching uses a linear Taylor expansion of the wave + ! kinematics (and their partial derivatives with respect to z) at the mean + ! sea level to find the wave kinematics above the mean sea level. The + ! wave kinematics below the mean sea level are left unchanged. + ! + ! Vertical stretching and extrapolation stretching do not effect the wave + ! kinematics below the mean sea level; also, vertical stretching and + ! extrapolation stretching say the wave kinematics above the mean sea + ! level depend only on the mean sea level values. Consequently, + ! NWaveKin0Prime and WaveKinzi0Prime(:) are equal to the number of, and + ! the zi-coordinates for, the points in the WaveKinzi(:) array between, + ! and including, -WtrDpth and 0.0; the WaveKinzi0Prime(:) array must also + ! include 0.0 even if the WaveKinzi(:) array does not. + + + + +! CASE ( 3 ) ! Wheeler stretching. + + + ! Wheeler stretching says that wave kinematics calculated using Airy theory + ! at the mean sea level should actually be applied at the instantaneous + ! free surface and that Airy wave kinematics computed at locations between + ! the seabed and the mean sea level should be shifted vertically to new + ! locations in proportion to their elevation above the seabed. + ! + ! Thus, given a range of zi(:) where we want to know the wave kinematics + ! after applying Wheeler stretching, the required range of ziPrime(:) + ! where the wave kinematics need to be computed before applying + ! stretching, is as follows: + ! + ! ziPrime_Min <= ziPrime(:) <= ziPrime_Max + ! + ! ziPrime_Min = MAX{ ( zi_Min - WaveElev_Max )/( 1 + WaveElev_Max/WtrDpth ), -WtrDpth } + ! ziPrime_Max = MIN{ ( zi_Max - WaveElev_Min )/( 1 + WaveElev_Min/WtrDpth ), 0 } + ! + ! where, + ! zi_Max = maximum elevation where the wave kinematics are to be + ! applied using stretching to the instantaneous free + ! surface + ! zi_Min = minimum elevation where the wave kinematics are to be + ! applied using stretching to the instantaneous free + ! surface + ! ziPrime_Max = maximum elevation where the wave kinematics are computed + ! before applying stretching to the instantaneous free + ! surface + ! ziPrime_Min = minimum elevation where the wave kinematics are computed + ! before applying stretching to the instantaneous free + ! surface + ! WaveElev_Max = maximum expected value of the instantaneous elevation of + ! incident waves + ! WaveElev_Min = minimum expected value of the instantaneous elevation of + ! incident waves + ! + ! Thus, in order to account for Wheeler stretching when computing the wave + ! kinematics at each of the NWaveKin points along a vertical line passing + ! through the platform reference point [defined by the zi-coordinates + ! relative to the mean see level as specified in the WaveKinzi(:) array], + ! we must first compute the wave kinematics without stretching at + ! alternative elevations [indicated here by the NWaveKin0Prime-element + ! array WaveKinzi0Prime(:)]: + + + + + +! ENDSELECT + + + + + ! Perform some initialization computations including initializing the + ! pseudorandom number generator, calculating the total number of frequency + ! components = total number of time steps in the incident wave, + ! calculating the frequency step, calculating the index of the frequency + ! component nearest to WaveTp, and ALLOCATing the arrays: + ! NOTE: WaveDOmega = 2*Pi/WaveTMax since, in the FFT: + ! Omega = (K-1)*WaveDOmega + ! Time = (J-1)*WaveDT + ! and therefore: + ! Omega*Time = (K-1)*(J-1)*WaveDOmega*WaveDT + ! = (K-1)*(J-1)*2*Pi/NStepWave [see NWTC_FFTPACK] + ! or: + ! WaveDOmega = 2*Pi/(NStepWave*WaveDT) + ! = 2*Pi/WaveTMax + + CALL RANDOM_SEED ( SIZE = nSeeds ) + + IF ( nSeeds /= 2 ) THEN + ErrMsgTmp = ' The random number generator in use differs from the original code provided by NREL. This pRNG uses ' & + //TRIM(Int2LStr(nSeeds))//' seeds instead of the 2 in the HydroDyn input file.' + CALL SetErrStat(ErrID_Warn,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + END IF + + ALLOCATE ( TmpWaveSeeds ( nSeeds ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpWaveSeeds.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! We'll just populate this with odd seeds = Seed(1) and even seeds = Seed(2) + DO I = 1,nSeeds,2 + TmpWaveSeeds(I) = InitInp%WaveSeed(1) + END DO + DO I = 2,nSeeds,2 + TmpWaveSeeds(I) = InitInp%WaveSeed(2) + END DO + + + CALL RANDOM_SEED ( PUT=TmpWaveSeeds ) + DEALLOCATE(TmpWaveSeeds, STAT=ErrStatTmp) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot deallocate array TmpWaveSeeds.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Set new value for NStepWave so that the FFT algorithms are efficient. Note that if this method is changed, the method + ! used to calculate the number of multidirectional wave directions (WaveNDir) and the UserWaveElevations_Init subroutine + ! will need to be updated. + + ! NOTE: For WaveMod = 5, NStepWave and several other things were already set in the UserWaveElevations_Init routine + ! using file information (an FFT was performed there, so the information was needed before now). + IF (InitInp%WaveMod /= 5 ) THEN + InitOut%NStepWave = CEILING ( InitInp%WaveTMax/InitInp%WaveDT ) ! Set NStepWave to an even integer + IF ( MOD(InitOut%NStepWave,2) == 1 ) InitOut%NStepWave = InitOut%NStepWave + 1 ! larger or equal to WaveTMax/WaveDT. + InitOut%NStepWave2 = MAX( InitOut%NStepWave/2, 1 ) ! Make sure that NStepWave is an even product of small factors (PSF) that is + InitOut%NStepWave = 2*PSF ( InitOut%NStepWave2, 9 ) ! greater or equal to WaveTMax/WaveDT to ensure that the FFT is efficient. + + InitOut%NStepWave2 = InitOut%NStepWave/2 ! Update the value of NStepWave2 based on the value needed for NStepWave. + WaveTMax = InitOut%NStepWave*InitInp%WaveDT ! Update the value of WaveTMax based on the value needed for NStepWave. + InitOut%WaveTMax = WaveTMax ! Update the value of WaveTMax in the output. Needed by glue code later. + InitOut%WaveDOmega = TwoPi/WaveTMax ! Compute the frequency step for incident wave calculations. + ELSE + WaveTMax = InitOut%WaveTMax + ENDIF + SQRTNStepWave2 = SQRT( REAL( InitOut%NStepWave2, SiKi ) ) ! Compute SQRT( NStepWave/2 ). + I_WaveTp = NINT ( TwoPi/(InitOut%WaveDOmega*InitInp%WaveTp) ) ! Compute the index of the frequency component nearest to WaveTp. + + + ! Allocate all the arrays we need. + + IF ( InitInp%WaveMod /= 5 ) THEN ! For WaveMod == 5, these are allocated and populated in UserWaveElevations_Init + ALLOCATE ( InitOut%WaveElevC0(2, 0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevC0.',ErrStat,ErrMsg,'VariousWaves_Init') + ENDIF + + ALLOCATE ( InitOut%WaveTime (0:InitOut%NStepWave ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveTime.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( tmpComplexArr(0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array tmpComplexArr.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveElevC (0:InitOut%NStepWave2 ,InitInp%NWaveElev), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveElevC.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveDynPC0 (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynPC0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVelC0Hxi (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVelC0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVelC0Hyi (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVelC0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVelC0V (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVelC0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAccC0Hxi (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAccC0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAccC0Hyi (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAccC0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAccC0V (0:InitOut%NStepWave2 ,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAccC0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + !ALLOCATE ( PWaveDynPC0BPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveDynPC0BPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVelC0HxiPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVelC0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVelC0HyiPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVelC0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVelC0VPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVelC0VPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAccC0HxiPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAccC0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAccC0HyiPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAccC0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAccC0VPz0 (0:InitOut%NStepWave2 ,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAccC0VPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%WaveElev0 (0:InitOut%NStepWave ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveElev0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%WaveElev (0:InitOut%NStepWave,InitInp%NWaveElev ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElev.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveDynP0B (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP0B.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVel0Hxi (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVel0Hyi (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveVel0V (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAcc0Hxi (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAcc0Hyi (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( WaveAcc0V (0:InitOut%NStepWave-1,NWaveKin0Prime ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + !ALLOCATE ( PWaveDynP0BPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveDynP0BPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVel0HxiPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVel0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVel0HyiPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVel0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveVel0VPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveVel0Pz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAcc0HxiPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAcc0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAcc0HyiPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAcc0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + !ALLOCATE ( PWaveAcc0VPz0 (0:InitOut%NStepWave-1,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array PWaveAcc0VPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%WaveDynP (0:InitOut%NStepWave,InitInp%NWaveKin ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%WaveVel (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%WaveAcc (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%PWaveDynP0 (0:InitOut%NStepWave,InitInp%NWaveKin ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveDynP0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%PWaveVel0 (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveVel0.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( InitOut%PWaveAcc0 (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%PWaveAcc0.', ErrStat,ErrMsg,'VariousWaves_Init') + + + + ALLOCATE ( InitOut%nodeInWater(0:InitOut%NStepWave,InitInp%NWaveKin ) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%nodeInWater.', ErrStat,ErrMsg,'VariousWaves_Init') + + ! Wave direction associated with each frequency + ALLOCATE ( InitOut%WaveDirArr( 0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDirArr.',ErrStat,ErrMsg,'VariousWaves_Init') + + ! Arrays for the Sin and Cos of the wave direction for each frequency. Used in calculating wave elevation, velocity, acceleration etc. + ALLOCATE ( CosWaveDir( 0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array CosWaveDir.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE ( SinWaveDir( 0:InitOut%NStepWave2 ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array SinWaveDir.', ErrStat,ErrMsg,'VariousWaves_Init') + + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + ! We now need to establish the nodeInWater flag values for all the simulation node for all timesteps, this is an extension which is needed to + ! support user input wave data. TODO: THIS ASSUMES NO WAVE STRETCHING!!!!!!!! GJH 18 Mar 2015 + DO J = 1,InitInp%NWaveKin ! Loop through all points where the incident wave kinematics will be computed without stretching + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + + InitOut%nodeInWater(:, J) = 1 + ELSE + InitOut%nodeInWater(:, J) = 0 + END IF + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + + +!FIXME: Is this piece still needed? If so, why is it commented out? + ! Calculate the factors needed by the discrete time inverse Fourier + ! transform in the calculations of the White Gaussian Noise (WGN) and + ! the two-sided power spectral density of the wave spectrum per unit time: + + ! This factor is needed by the discrete time inverse Fourier transform to ensure that the time series WGN + ! process has unit variance + ! WGNC_Fact = SQRT( Pi/(InitOut%WaveDOmega*InitInp%WaveDT) ) + + + + + + !-------------------------------------------------------------------------------- + !> # Multi Directional Waves + !> ## Adjust WaveNDir + !! + !! If multi-directional waves will be used, the value of WaveNDir may need to be adjusted. The reason is that + !! for the equal energy approach used here, the following condition must be met: + !! + !! CONDITION: (NStepWave2) / WaveNDir must be an integer + !! + !! If this is true, then an equal number of frequencies is assigned to each of the WaveNDir directions which + !! gives the proper wave direction distribution function. Otherwise, the energy distribution by direction + !! will not be correct. + !! + !! _WaveNDir_ could not be adjusted before _NStepWave2_ was finalized above. + !! + !! @note Use the value of WaveNDir stored in InitOut since InitInp cannot be changed. + !! + !! @note Originally, the criteria had been that (NStepWave2 - 1) / WaveNDir is an integer. This criteria + !! was relaxed by setting the direction for Omega = 0 (which has no amplitude) since it was found that + !! (NStepWave2 - 1) is often a prime number due to how NStepWave is calculated above to be a product + !! of smallish numbers. + + IF ( InitInp%WaveMultiDir ) THEN ! Multi-directional waves in use + + ! Check that the number of wave directions is a positive odd number. In theory this has been + ! done before the Waves module was called. We repeat it here in the event that the Waves module + ! gets used in some other code. + ! -> If it is less than 0, error out. + ! -> If it is even, we will increment it by 1. + IF ( InitOut%WaveNDir <= 0_IntKi ) THEN + ErrMsgTmp = 'WaveNDir must be an odd number greater than 0.' + ErrStatTmp = ErrID_Fatal + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + RETURN + END IF + + IF ( MODULO( InitOut%WaveNDir, 2_IntKi) == 0_IntKi ) THEN + InitOut%WaveNDir = InitOut%WaveNDir + 1 + ErrMsgTmp = 'WaveNDir must be odd. Changing the value to '//TRIM(Num2LStr(InitOut%WaveNDir)) + CALL SetErrStat(ErrID_Warn,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + END IF + + ! Now adjust WaveNDir as necessary so that (NStepWave2) / WaveNDir is integer + IF ( .NOT. EqualRealNos(REAL(( InitOut%NStepWave2 )/ InitOut%WaveNDir), & + ((REAL(InitOut%NStepWave2))/REAL(InitOut%WaveNDir)) )) THEN + DO WHILE ( InitOut%WaveNDir <= WaveNDirMax ) + + InitOut%WaveNDir = InitOut%WaveNDir + 2.0_SiKi + IF ( EqualRealNos(REAL(( InitOut%NStepWave2 )/ InitOut%WaveNDir), & + ((REAL(InitOut%NStepWave2))/REAL(InitOut%WaveNDir)) )) THEN + ErrMsgTmp = 'Changed WaveNDir from '//TRIM(Num2LStr(InitInp%WaveNDir))//' to '// & + TRIM(Num2LStr(InitOut%WaveNDir))//' so that an equal number of frequencies are assigned to '// & + 'each direction.' + CALL SetErrStat(ErrID_Warn,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + EXIT + END IF + END DO + END IF + + ! If we exited because we hit a limit (in which case the condition is not satisfied), then we cannot continue. + ! We warn the user that a value for WaveNDir was not found, and that they should try a different value, or try + ! a different value for WaveTMax. The reason for suggesting the latter is that NStepWave is derived from + ! WaveTMax and adjusted until it is a product of smallish numbers (most likely even, but not necessarily so). + ! So, there is a very small possibility then that NStepWave2 is a prime number, in which case we won't find a + ! value for WaveNDir, so we suggest that the user change WaveTMax. To make this a little easier for the user, + ! we will report the first 5 possible values for WaveNDir between their requested value and 1/4 of NStepWave2, + ! if there are any. + IF ( .NOT. EqualRealNos(REAL(( InitOut%NStepWave2 )/ InitOut%WaveNDir), & + ((REAL(InitOut%NStepWave2))/REAL(InitOut%WaveNDir)) )) THEN + ErrMsgTmp = 'Could not find value for WaveNDir between '//TRIM(Num2LStr(InitInp%WaveNDir))//' and '// & + TRIM(Num2LStr(WaveNDirMax))//' such that an equal number of frequencies are assigned to each '// & + 'direction.' + ErrStatTmp = ErrID_Fatal + + ! Now check for the possible values of WaveNDir so that we can tell the user about it. The variable 'I' contains + ! the count of the number of values of WaveNDir found. + I = 0 + ErrMsgTmp2 = 'The next values of WaveNDir that work with the selected values for WaveTMax and WaveDT:' + DO WHILE ( InitOut%WaveNDir <= INT(InitOut%NStepWave2/4.0) ) + IF ( EqualRealNos(REAL(( InitOut%NStepWave2 )/ InitOut%WaveNDir), & + ((REAL(InitOut%NStepWave2))/REAL(InitOut%WaveNDir)) )) THEN + ErrMsgTmp2 = TRIM(ErrMsgTmp2)//" "//TRIM(Num2LStr(InitOut%WaveNDir)) + I = I + 1 + END IF + + InitOut%WaveNDir = InitOut%WaveNDir + 2.0_SiKi + + IF ( I >= 5 ) EXIT + + END DO + + ! If there were no additional values for WaveNDir found, I will be 0, so we rewrite the error message. + IF ( I == 0 ) THEN + ErrMsgTmp2 = 'There are no values for WaveNDir between '//TRIM(Num2LStr(WaveNDirMax))//' and '// & + TRIM(Num2LStr(INT(InitOut%NStepWave2/4.0)))//' (4 frequencies per wave direction)'// & + ' that will work with the selected values for WaveTMax ('//TRIM(Num2Lstr(InitOut%WaveTMax))// & + ') and WaveDT ('//TRIM(Num2LStr(InitInp%WaveDT))//'). Change either'// & + ' WaveTMax or WaveDT.' + ELSE + ErrMsgTmp2 = TRIM(ErrMsgTmp2)//'.' + ENDIF + + ! Append the message about the possible values for WaveNDir (if any were found) and set the error status before + ! returning to the calling program. + ErrMsgTmp = TRIM(ErrMsgTmp)//NewLine//' '//TRIM(ErrMsgTmp2) + + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + RETURN + END IF + + ! Save the number of frequencies per direction so that we can use it later in assigning the directios. + WvSpreadFreqPerDir = (InitOut%NStepWave2)/InitOut%WaveNDir + + + !> ## Calculate the wave directions based on an equal energy approach. + !! + !! All the angles are supplied in degrees and are converted as needed. For the cosine function, + !! we could convert degrees to radians, but the conversion constant cancels out. + !! + !! | Variable | Fortran Name | Location | Units | Description | + !! | :----------------: | :-------------------: | :-------: | :--------: | :----------------------------------------------------- | + !! | \f$\bar\theta\f$ | _WaveDir_ | _InitInp_ | (degrees) | Mean direction heading (_WaveDir_) | + !! | \f$\Theta\f$ | _WaveNDir_ | _InitOut_ | (-) | Number of wave directions | + !! | \f$\delta\theta\f$ | _WaveDirRange_ | _InitInp_ | (degrees) | Full range of spreading function | + !! | \f$S\f$ | _WaveDirSpread_ | _InitInp_ | (-) | The spreading coefficient | + !! | | _WvSpreadNDir_ | local | (-) | Number of angles discretizing the spreading function | + !! | \f$C\f$ | _WvSpreadCos2SConst_ | local | (1/degrees) | The normalization coefficient | + !! | | _WvTheta_ | local | (degrees) | The interpolated wave directions to assign to | + !! | \f$\theta_i\f$ | _WvSpreadThetas_ | local | (degrees) | Array of wave directions associated with _WvSpreadIntegral_ | + !! | | _D2R_ | global | (rad/degree) | Constant from library to convert degrees to radians | + !! + !! The equal energy approach is used to set the wave directions such that each direction has the same + !! number of frequencies. To ensure that direction spreading function (Cosine^2S in this case) has + !! the correct overal energy distribution shape, the wave directions are adjusted. The spacing between + !! directions is closer near the central direction than in the tails of the spreading function. The + !! method distributes the wave directions so that the energy integral between wave directions is kept + !! constant. The following steps are taken: + !! + !! 1. Discretize the spreading function over the range _InitInp%WaveDirRange_ into _WvSpreadNDir_. + !! + !! 2. Calculate the spreading function, _WvSpreadCos2SArr_, in the range.\n + !! \f$ D(\theta) = C \left| \cos\left(\frac{\pi (\theta-\bar\theta)}{\delta\theta}\right)\right|^{2S} \f$\n + !! where\n + !! \f$ C = \frac{\sqrt{\pi} \: \Gamma(S+1)}{\delta\theta \: \Gamma(S+1/2)} \f$, + !! and + !! \f$ \Gamma \f$ is the gamma function. + !! + !! 3. Calculate the integral of WvSpreadCos2SArr up to the current angle, and save it as + !! WvSpreadIntegral. The integral can be written as:\n + !! \f$P(\theta) = \int\limits^{\theta}_{\bar\theta - \delta\theta/2} D(\theta') \: \mathrm{d}\theta'\f$ + !! + !! 4. Do a sanity check on the result of \f$P(\theta)\f$ over the range. + !! + !! 5. Divide the integrated area of _WvSpreadCos2SArr_ into _InitOut%WaveNDir_ directions (the final number + !! of wave directions that was solved for above). To do this, simply find the _1/WaveNDir_ values + !! of the integral and interpolate to find the values of the _WvSpreadThetas_ that match. These are the + !! new wave directions to use. These results are stored in the array _WvTheta_. + !! + !! 6. Cleanup + !! + + !> ### Code Implementation order + !! 1. Discretize the spreading function range and calculate the values of the wave spreading function + + ! Now that we have the value for _WaveNDir_ found above, we set the value of _WvSpreadNDir_ to be 15x as + ! large, or 1000 (whichever is larger). WvSpreadNDir is used only in discretization for later + ! interpolation of actual wave directions. + WvSpreadNDir = MAX(15*InitOut%WaveNDir,1000) + WvSpreadDTheta = InitInp%WaveDirRange/REAL(WvSpreadNDir,SiKi) + + ! Calculate the normalization constant for the wave spreading. + WvSpreadCos2SConst = sqrt(Pi)* (NWTC_GAMMA(InitInp%WaveDirSpread + 1.0_SiKi))/ & + (InitInp%WaveDirRange * NWTC_GAMMA(InitInp%WaveDirSpread + 0.5_SiKi)) + + ! Allocate arrays to use for storing the intermediate values + ALLOCATE( WvSpreadCos2SArr(0:WvSpreadNDir), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WvSpreadCos2SArr.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE( WvSpreadIntegral(0:WvSpreadNDir), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WvSpreadIntegral.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE( WvSpreadThetas(0:WvSpreadNDir), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WvSpreadThetas.', ErrStat,ErrMsg,'VariousWaves_Init') + + ALLOCATE( WvTheta(1:InitOut%WaveNDir), STAT=ErrStatTmp ) ! Dealocate this at very end of routine. + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WvTheta.', ErrStat,ErrMsg,'VariousWaves_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + !> 2. Calculate the spreading function as a function of angle. Step through all _WvSpreadNDir_ steps. + DO I=0,WvSpreadNDir + ! The current angle as we step through the range + WvSpreadThetas(I) = I*WvSpreadDTheta + InitInp%WaveDir - InitInp%WaveDirRange/(2.0_SiKi) + + ! Calculate the wave spreading for the current value of WvSpreadThetas + WvSpreadCos2SArr(I) = WvSpreadCos2SConst*abs( cos(Pi*(WvSpreadThetas(I)-InitInp%WaveDir)/InitInp%WaveDirRange) ) & + **(2*InitInp%WaveDirSpread) + + !> 3. Calculate the integral of the spreading function up to the current angle and save it. + ! Remember that the first element can't refer to one before it. + IF (I == 0) THEN + WvSpreadIntegral(I) = WvSpreadCos2SArr(I) * WvSpreadDTheta + ELSE + WvSpreadIntegral(I) = WvSpreadCos2SArr(I) * WvSpreadDTheta + WvSpreadIntegral(I-1) + END IF + ENDDO + + + !> 4. Perform a quick sanity check. The last value of the integral table should be 1.0 exactly. + !! We will allow for a 1% deviation. If for some reason an error occurs, it may be due to the + !! GAMMA function calculation for the normalization constant, _WvSpreadCos2SConst_. + IF ( WvSpreadIntegral(WvSpreadNDir) < 0.99_SiKi .OR. WvSpreadIntegral(WvSpreadNDir) > 1.01_SiKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Something went wrong in evaluating the multidirectional wave spreading function. '// & + 'Integral is '//TRIM(Num2LStr(WvSpreadIntegral(WvSpreadNDir))),ErrStat,ErrMsg,'VariousWaves_Init') + RETURN + END IF + + + !> 5. Set the wave directions using the results from the integral. + ! We will use the variable LastInd as a simple index for figuring out where in the array we are. First set to 0 + LastInd = 0_IntKi + DO I=1,InitOut%WaveNDir + WvSpreadIntegralTmp = (REAL(I)-0.5_SiKi)/REAL(InitOut%WaveNDir) + WvTheta(I) = InterpStp( WvSpreadIntegralTmp, WvSpreadIntegral, WvSpreadThetas, LastInd, WvSpreadNDir ) + ENDDO ! I=1,InitOut%WaveNDir + + ! Store the minimum and maximum wave directions + InitOut%WaveDirMin = MINVAL(WvTheta) + InitOut%WaveDirMax = MAXVAL(WvTheta) + + !> 6. Done with equal energy wavedirection calculations. Deallocate the arrays used during calculations. + IF(ALLOCATED( WvSpreadCos2SArr )) DEALLOCATE( WvSpreadCos2SArr, STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot deallocate array WvSpreadCos2SArr.', ErrStat,ErrMsg,'VariousWaves_Init') + IF(ALLOCATED( WvSpreadIntegral )) DEALLOCATE( WvSpreadIntegral, STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot deallocate array WvSpreadIntegral.', ErrStat,ErrMsg,'VariousWaves_Init') + IF(ALLOCATED( WvSpreadThetas )) DEALLOCATE( WvSpreadThetas, STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot deallocate array WvSpreadThetas.', ErrStat,ErrMsg,'VariousWaves_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ELSE ! Multi-directional waves not used + + InitOut%WaveDirMin = InitInp%WaveDir + InitOut%WaveDirMax = InitInp%WaveDir + + ENDIF ! Multi-directional waves in use (InitInp%WaveMultiDir == .TRUE.) + + + + ! JASON: IMPLEMENT EQUATIONS (2.12 - 2.13) IN MY DISSERTATION SO THAT ONE CAN READ IN EXTERNAL WAVE + ! DATA?<--BETTER YET, IMPLEMENT WaveElevC0 = DFT(WaveElev) WHERE WaveElev CAN BE READ IN AS + ! GH BLADED WAVE DATA. THAT IS, ADD AN OPTION TO READ IN WAVE DATA FOR FLOATERS! + + ! Compute the positive-frequency components (including zero) of the discrete + ! Fourier transforms of the wave kinematics: + + DO I = 0,InitOut%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transforms + + + ! Compute the frequency of this component and its imaginary value: + + Omega = I* InitOut%WaveDOmega + ImagOmega = ImagNmbr*Omega + + + + ! Compute the discrete Fourier transform of the realization of a White + ! Gaussian Noise (WGN) time series process with unit variance: + ! + ! NOTE: For the time series process to be real with zero mean, the values at + ! Omega == 0.0 and Omega == NStepWave2*WaveDOmega (= WaveOmegaMax) + ! must be zero. + + IF ( ( I == 0 ) .OR. ( I == InitOut%NStepWave2 ) ) THEN ! .TRUE. if ( Omega == 0.0 ) or ( Omega == NStepWave2*WaveDOmega (= WaveOmegaMax) ) + WGNC = (0.0,0.0) + ELSEIF ( InitInp%WaveMod == 10 ) THEN ! .TRUE. for plane progressive (regular) waves with a specified phase + WGNC = BoxMuller ( InitInp%RNG%pRNG, InitInp%WaveNDAmp, InitInp%WavePhase ) + ! This scaling of WGNC is used to ensure that the Box-Muller method is only providing a random phase, + ! not a magnitude change, at the frequency of the plane progressive wave. The SQRT(2.0) is used to + ! ensure that the time series WGN process has unit variance (i.e. sinusoidal with amplitude SQRT(2.0)). + ! + ! NOTE: the denominator here will never equal zero since U1 cannot equal 1.0, and thus, C1 cannot be + ! 0.0 in the Box-Muller method. + IF ( ( I == I_WaveTp ) ) WGNC = WGNC*( SQRT(2.0)/ABS(WGNC) ) + ELSE ! All other Omega + WGNC = BoxMuller ( InitInp%RNG%pRNG, InitInp%WaveNDAmp ) + ! This scaling of WGNC is used to ensure that the Box-Muller method is only providing a random phase, + ! not a magnitude change, at the frequency of the plane progressive wave. The SQRT(2.0) is used to + ! ensure that the time series WGN process has unit variance (i.e. sinusoidal with amplitude SQRT(2.0)). + ! + ! NOTE: the denominator here will never equal zero since U1 cannot equal 1.0, and thus, C1 cannot be + ! 0.0 in the Box-Muller method. + IF ( ( InitInp%WaveMod == 1 ) .AND. ( I == I_WaveTp ) ) WGNC = WGNC*( SQRT(2.0)/ABS(WGNC) ) + END IF + + + ! Compute the one-sided power spectral density of the wave spectrum per unit + ! time; zero-out the wave spectrum above the cut-off frequency: + + SELECT CASE ( InitInp%WaveMod ) ! Which incident wave kinematics model are we using? + + CASE ( 1, 10 ) ! Plane progressive (regular) wave; the wave spectrum is an impulse function centered on frequency component closest to WaveTp. + IF ( I == I_WaveTp ) THEN ! .TRUE. if we are at the Omega closest to WaveTp. + WaveS1Sdd = 0.5*(InitInp%WaveHs/2.0)*(InitInp%WaveHs/2.0)/InitOut%WaveDOmega + ELSE ! All other Omega + WaveS1Sdd = 0.0 + END IF + + CASE ( 2 ) ! JONSWAP/Pierson-Moskowitz spectrum (irregular) wave. + ! Zero-out the wave spectrum above the cut-off frequency. We must cut-off the frequency in order to + ! void nonphysical wave forces. Waves that have wavelengths much smaller than the platform diameter + ! (high frequency) do not contribute to the net force because regions of positive and negative + ! velocity/acceleration are experienced by the platform at the same time and cancel out. + ! + ! JASON: OTHER FREQUENCY CUT-OFF CONDITIONS ARE USED THROUGHOUT THE INDUSTRY. SHOULD YOU USE ONE OF + ! THEM INSTEAD? SEE, FOR EXAMPLE, MY E-MAIL EXCHANGES WITH PAUL SCLAVOUNOS DATED 5/26/2006 OR: + ! "GH Bladed Thoery Manual" OR: Trumars, Jenny M. V.; Tarp-Johansen, Niels Jacob; Krogh, Thomas; + ! "The Effect of Wave Modelling on Offshore Wind Turbine Fatigue Loads," 2005 Copenhagen Offshore + ! Wind Conference and Exhibition, 26-28 October 2005, Copenhagen, Denmark [CD-ROM]. + IF ( Omega < InitInp%WvLowCOff .OR. Omega > InitInp%WvHiCOff ) THEN ! .TRUE. if Omega is above or below the cut-off frequency + WaveS1Sdd = 0.0 + ELSE ! All other Omega + WaveS1Sdd = JONSWAP ( Omega, InitInp%WaveHs, InitInp%WaveTp, InitInp%WavePkShp ) + END IF + CASE ( 3 ) ! White-noise + IF ( Omega < InitInp%WvLowCOff .OR. Omega > InitInp%WvHiCOff ) THEN ! .TRUE. if Omega is above or below the cut-off frequency + WaveS1Sdd = 0.0 + ELSE + WaveS1Sdd = InitInp%WaveHs * InitInp%WaveHs / ( 8.0 * (InitInp%WvHiCOff - InitInp%WvLowCOff) ) + END IF + CASE ( 4 ) ! User-defined spectrum (irregular) wave. + IF ( Omega < InitInp%WvLowCOff .OR. Omega > InitInp%WvHiCOff ) THEN ! .TRUE. if Omega is above or below the cut-off frequency + WaveS1Sdd = 0.0 + ELSE + CALL UserWaveSpctrm ( Omega, InitInp%WaveDir, InitInp%DirRoot, WaveS1Sdd ) + END IF + + ENDSELECT + + + IF ( InitInp%WaveMod == 5 ) THEN ! Wave Elevation data read in + + ! Apply limits to the existing WaveElevC0 arrays if outside frequency range + IF ( Omega < InitInp%WvLowCOff .OR. Omega > InitInp%WvHiCOff ) THEN + InitOut%WaveElevC0(:,I) = 0.0_SiKi + ENDIF + + ELSE ! All other wave cases + + ! Compute the two-sided power spectral density of the wave spectrum per unit + ! time: + + WaveS2Sdd = 0.5*WaveS1Sdd + + + ! Compute the discrete Fourier transform of the instantaneous elevation of + ! incident waves at the WAMIT reference point: + tmpComplex = SQRTNStepWave2*WGNC*SQRT( TwoPi*WaveS2Sdd/REAL(InitInp%WaveDT,SiKi) ) + InitOut%WaveElevC0 (1,I) = REAL( tmpComplex) + InitOut%WaveElevC0 (2,I) = AIMAG(tmpComplex) + + ENDIF + + END DO ! I - The positive frequency components (including zero) of the discrete Fourier transforms + + !-------------------------------------------------------------------------------- + !=== Multi-Directional Waves === + !> ## Assign Wave directions + !! For the equal energy approach to the multi-directional waves, we need to use the random number generator to + !! select which direction each wave frequency is assigned to. We also require that the phase and amplitudes + !! assigned to each frequency are the same regardless of whether or not multiple directions are used, we must + !! first finish assigning all the amplitudes and phases before using the random number generator again. For this + !! reason, the above do loop is completed, the multiple wave directions are computed, and then we run through the + !! all wave frequencies again to set up the remaining pieces. If we did not do this, we would change the seed + !! used by the random number generator before selecting the next amplitude and phase pair. + !! + !! The wave directions are assigned in groups of _WaveNDir_ frequencies such that each frequency is assigned to + !! one of the _WaveNDir_ unique wave directions. Each wave direction is used only once within each group of + !! frequencies. + !! + !! When complete, we deallocate the _WvSpreadThetas_ array that was used to store the assigned directions. + + IF ( InitInp%WaveMultiDir .AND. InitInp%WaveNDir > 1 ) THEN ! Multi-directional waves in use + + + ! Allocate the index array for each group of frequencies. This array is used to randomize the directions + ! within each WaveNDir sized group of frequencies. This is a REAL array used to hold the random numbers. + ALLOCATE( WvSpreadThetaIdx(1:InitOut%WaveNDir), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WvSpreadThetaIdx while assigning '// & + 'wave directions.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Reset the K so that we can use it to count the frequency index. + ! It should be exactly NStepWave2 when done assigning directions. The the Omega = 0 has + ! no amplitude, but gets a direction anyhow (to simplify the calculation of WaveNDir). + K = 0 + + + ! Work through the frequencies in groups of directions. + DO I = 1,WvSpreadFreqPerDir + + ! Populate the array with random numbers + CALL UniformRandomNumbers(InitInp%RNG%pRNG, WvSpreadThetaIdx) + + DO J = 1, InitOut%WaveNDir + + ! Find the index lowest value in the WvSpreadThetaIdx array. This is the index to + ! use for this wave direction. + LastInd = MINLOC( WvSpreadThetaIdx, DIM=1 ) + + ! Assign the direction for this frequency piece to the LastInd value. + InitOut%WaveDirArr(K) = WvTheta( LastInd ) + + ! Now make that element in the WvSpreadThetaIdx really big so we don't pick it again + WvSpreadThetaIdx( LastInd ) = HUGE(1.0_SiKi) + + K = K + 1 ! Increment the frequency index + + ENDDO + ENDDO + ! Filling last value since it is not reached by the loop above + CALL UniformRandomNumbers(InitInp%RNG%pRNG, WvSpreadThetaIdx) + LastInd = MINLOC( WvSpreadThetaIdx, DIM=1 ) + InitOut%WaveDirArr(K) = WvTheta( LastInd ) + + ! Perform a quick sanity check. We should have assigned all wave frequencies a direction, so K should be + ! K = NStepWave2 (K is incrimented afterwards). + IF ( K /= (InitOut%NStepWave2 ) ) CALL SetErrStat(ErrID_Fatal, & + 'Something went wrong while assigning wave directions.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! We are done with the indexing array, so deallocate it + IF(ALLOCATED( WvSpreadThetaIdx )) DEALLOCATE( WvSpreadThetaIdx ) + + ! This had been allocated above (calculation section of equal energy portion of multidirectional waves). + ! Deallocate it here after we have completed all the calculations involving it. + IF(ALLOCATED( WvTheta )) DEALLOCATE( WvTheta ) + + ELSE ! Not really multi-directional waves + + ! Since we do not have multi-directional waves, we must set the wave direction array to the single wave heading. + InitOut%WaveDirArr = InitInp%WaveDir + ENDIF ! Multi-directional waves in use. + + + ! Set the CosWaveDir and SinWaveDir arrays + CosWaveDir=COS(D2R*InitOut%WaveDirArr) + SinWaveDir=SIN(D2R*InitOut%WaveDirArr) + + + !-------------------------------------------------------------------------------- + !> ## Compute IFFTs + !> Compute the discrete Fourier transform of the instantaneous elevation of + !! incident waves at each desired point on the still water level plane + !! where it can be output: + + DO I = 0,InitOut%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transforms + + + ! Set tmpComplex to the Ith element of the WAveElevC0 array + + tmpComplex = CMPLX( InitOut%WaveElevC0(1,I), InitOut%WaveElevC0(2,I)) + + + ! Compute the frequency of this component and its imaginary value: + + Omega = I* InitOut%WaveDOmega + ImagOmega = ImagNmbr*Omega + + ! Compute the wavenumber: + + WaveNmbr = WaveNumber ( Omega, InitInp%Gravity, InitInp%WtrDpth ) + + + ! Compute the discrete Fourier transform of the incident wave kinematics + ! before applying stretching at the zi-coordinates for the WAMIT reference point, and all + ! points where are Morison loads will be calculated. + + DO J = 1,NWaveKin0Prime ! Loop through all points where the incident wave kinematics will be computed without stretching + + WaveElevxiPrime0 = EXP( -ImagNmbr*WaveNmbr*( InitInp%WaveKinxi(WaveKinPrimeMap(J))*CosWaveDir(I) + & + InitInp%WaveKinyi(WaveKinPrimeMap(J))*SinWaveDir(I) )) + + WaveDynPC0 (I,J) = InitOut%RhoXg*tmpComplex*WaveElevxiPrime0 * COSHNumOvrCOSHDen ( WaveNmbr, InitInp%WtrDpth, WaveKinzi0Prime(J) ) + + WaveVelC0Hxi (I,J) = CosWaveDir(I)*Omega*tmpComplex* WaveElevxiPrime0 * COSHNumOvrSINHDen ( WaveNmbr, InitInp%WtrDpth, WaveKinzi0Prime(J) ) + WaveVelC0Hyi (I,J) = SinWaveDir(I)*Omega*tmpComplex* WaveElevxiPrime0 * COSHNumOvrSINHDen ( WaveNmbr, InitInp%WtrDpth, WaveKinzi0Prime(J) ) + + WaveVelC0V (I,J) = ImagOmega*tmpComplex* WaveElevxiPrime0 * SINHNumOvrSINHDen ( WaveNmbr, InitInp%WtrDpth, WaveKinzi0Prime(J) ) + WaveAccC0Hxi (I,J) = ImagOmega* WaveVelC0Hxi (I,J) + + WaveAccC0Hyi (I,J) = ImagOmega* WaveVelC0Hyi (I,J) + WaveAccC0V (I,J) = ImagOmega* WaveVelC0V (I,J) + + + + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + +!=================================== +! Wave stretching + ! DO J = 1,InitInp%NWaveKin + ! WaveElevxiPrime0 = EXP( -ImagNmbr*WaveNmbr*( InitInp%WaveKinxi(J)*CosWaveDir(I) + & + ! InitInp%WaveKinyi(J)*SinWaveDir(I) )) + !! Partial derivatives at zi = 0 + ! PWaveDynPC0BPz0 (I,J) = InitOut%RhoXg* tmpComplex*WaveElevxiPrime0*WaveNmbr*TANH ( WaveNmbr*InitInp%WtrDpth ) + ! PWaveVelC0HxiPz0(I,J) = CosWaveDir(I)*Omega*tmpComplex*WaveElevxiPrime0*WaveNmbr + ! PWaveVelC0HyiPz0(I,J) = SinWaveDir(I)*Omega*tmpComplex*WaveElevxiPrime0*WaveNmbr + ! PWaveVelC0VPz0 (I,J) = ImagOmega*tmpComplex*WaveElevxiPrime0*WaveNmbr*COTH ( WaveNmbr*InitInp%WtrDpth ) + ! PWaveAccC0HxiPz0(I,J) = ImagOmega*PWaveVelC0HxiPz0(I,J) + ! PWaveAccC0HyiPz0(I,J) = ImagOmega*PWaveVelC0HyiPz0(I,J) + ! PWaveAccC0VPz0 (I,J) = ImagOmega*PWaveVelC0VPz0 (I,J) + ! + ! + ! END DO ! J - All points where the incident wave kinematics will be computed without stretching +!=================================== + + END DO ! I - The positive frequency components (including zero) of the discrete Fourier transforms + + + + ! Calculate the array of simulation times at which the instantaneous + ! elevation of, velocity of, acceleration of, and loads associated with + ! the incident waves are to be determined: + + DO I = 0,InitOut%NStepWave ! Loop through all time steps + InitOut%WaveTime(I) = I*REAL(InitInp%WaveDT,SiKi) + END DO ! I - All time steps + + DO I = 0,InitOut%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transform + tmpComplexArr(I) = CMPLX(InitOut%WaveElevC0(1,I), InitOut%WaveElevC0(2,I)) + END DO + + ! Compute the inverse discrete Fourier transforms to find the time-domain + ! representations of the wave kinematics without stretcing: + + CALL InitFFT ( InitOut%NStepWave, FFT_Data, .TRUE., ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! We'll need the following for wave stretching once we implement it. + CALL ApplyFFT_cx ( InitOut%WaveElev0 (0:InitOut%NStepWave-1), tmpComplexArr (: ), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveElev0.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + DO J = 1,InitInp%NWaveElev ! Loop through all points where the incident wave elevations can be output + ! This subroutine call applies the FFT at the correct location. + CALL WaveElevTimeSeriesAtXY( InitInp%WaveElevxi(J), InitInp%WaveElevyi(J), InitOut%WaveElev(:,J), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to InitOut%WaveElev.',ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END DO ! J - All points where the incident wave elevations can be output + + + ! For creating animations of the sea surface, the WaveElevXY array is passed in with a series of x,y coordinates + ! (index 1). The second index corresponds to the number of points passed in. A two dimensional time series + ! is created with the first index corresponding to the timestep, and second index corresponding to the second + ! index of the WaveElevXY array. + IF ( ALLOCATED(InitInp%WaveElevXY)) THEN + ALLOCATE ( InitOut%WaveElevSeries (0:InitOut%NStepWave, 1:SIZE(InitInp%WaveElevXY, DIM=2)) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevSeries.',ErrStat,ErrMsg,'VariousWaves_Init') + CALL CleanUp() + RETURN + END IF + ! Calculate the wave elevation at all points requested in the array WaveElevXY + DO J = 1,SIZE(InitInp%WaveElevXY, DIM=2) + ! This subroutine call applies the FFT at the correct location. + CALL WaveElevTimeSeriesAtXY( InitInp%WaveElevXY(1,J), InitInp%WaveElevXY(2,J), InitOut%WaveElevSeries(0:InitOut%NStepWave,J), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + ENDDO + ENDIF + + + ! User requested data points -- Do all the FFT calls first, then return if something failed. + DO J = 1,NWaveKin0Prime ! Loop through all points where the incident wave kinematics will be computed without stretching + CALL ApplyFFT_cx ( WaveDynP0B (:,J), WaveDynPC0 (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveDynP0B.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveVel0Hxi (:,J), WaveVelC0Hxi (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveVel0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveVel0Hyi (:,J), WaveVelC0Hyi (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveVel0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveVel0V (:,J), WaveVelC0V (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveVel0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveAcc0Hxi (:,J), WaveAccC0Hxi (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveAcc0Hxi.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveAcc0Hyi (:,J), WaveAccC0Hyi (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveAcc0Hyi.', ErrStat,ErrMsg,'VariousWaves_Init') + + CALL ApplyFFT_cx ( WaveAcc0V (:,J), WaveAccC0V (:,J), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to WaveAcc0V.', ErrStat,ErrMsg,'VariousWaves_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + +!=================================== + !DO J = 1,InitInp%NWaveKin ! Loop through all points where the incident wave kinematics will be computed without stretching + ! ! FFT's of the partial derivatives + ! CALL ApplyFFT_cx ( PWaveDynP0BPz0(:,J ), PWaveDynPC0BPz0(:,J ), FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveDynP0BPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveVel0HxiPz0 (:,J ), PWaveVelC0HxiPz0( :,J ),FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveVel0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveVel0HyiPz0 (:,J ), PWaveVelC0HyiPz0( :,J ),FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveVel0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveVel0VPz0 (:,J ), PWaveVelC0VPz0 (:,J ), FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveVel0VPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveAcc0HxiPz0 (:,J ), PWaveAccC0HxiPz0(:,J ),FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveAcc0HxiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveAcc0HyiPz0 (:,J ), PWaveAccC0HyiPz0(:,J ),FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveAcc0HyiPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! CALL ApplyFFT_cx ( PWaveAcc0VPz0 (:,J ), PWaveAccC0VPz0( :,J ), FFT_Data, ErrStatTmp ) + ! CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to PWaveAcc0VPz0.', ErrStat,ErrMsg,'VariousWaves_Init') + ! + ! IF ( ErrStat >= AbortErrLev ) THEN + ! CALL CleanUp() + ! RETURN + ! END IF + ! + !END DO ! J - All points where the incident wave kinematics will be computed without stretching +!=================================== + + + CALL ExitFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'VariousWaves_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + ! Add the current velocities to the wave velocities: + ! NOTE: Both the horizontal velocities and the partial derivative of the + ! horizontal velocities with respect to zi at zi = 0 are found here. + ! + ! NOTE: The current module must be called prior to the waves module. If that was not done, then we + ! don't have a current to add to the wave velocity. So, check if the current velocity components + ! exist. + + + ! If there is a current, we need to add that (the current module was called prior to calling this module + + IF(ALLOCATED(InitInp%CurrVxi)) THEN + + DO J = 1,NWaveKin0Prime ! Loop through all points where the incident wave kinematics will be computed without stretching + + WaveVel0Hxi (:,J) = WaveVel0Hxi (:,J) + InitInp%CurrVxi(WaveKinPrimeMap(J)) ! xi-direction + WaveVel0Hyi (:,J) = WaveVel0Hyi (:,J) + InitInp%CurrVyi(WaveKinPrimeMap(J)) ! yi-direction + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + + !PWaveVel0HxiPz0(: ) = PWaveVel0HxiPz0(: ) + InitInp%PCurrVxiPz0 ! xi-direction + !PWaveVel0HyiPz0(: ) = PWaveVel0HyiPz0(: ) + InitInp%PCurrVyiPz0 ! yi-direction + + ENDIF + + + ! Apply stretching to obtain the wave kinematics, WaveDynP0, WaveVel0, and + ! WaveAcc0, at the desired locations from the wave kinematics at + ! alternative locations, WaveDynP0B, WaveVel0Hxi, WaveVel0Hyi, WaveVel0V, + ! WaveAcc0Hxi, WaveAcc0Hyi, WaveAcc0V, if the elevation of the point defined by + ! WaveKinzi(J) lies between the seabed and the instantaneous free + ! surface, else set WaveDynP0, WaveVel0, and WaveAcc0 to zero. This + ! depends on which incident wave kinematics stretching method is being + ! used: + + ! SELECT CASE ( InitInp%WaveStMod ) ! Which model are we using to extrapolate the incident wave kinematics to the instantaneous free surface? + + ! CASE ( 0 ) ! None=no stretching. + + + ! Since we have no stretching, the wave kinematics between the seabed and + ! the mean sea level are left unchanged; below the seabed or above the + ! mean sea level, the wave kinematics are zero: + + InitOut%PWaveDynP0(:,:) = 0.0 + InitOut%PWaveVel0 (:,:,:) = 0.0 + InitOut%PWaveAcc0 (:,:,:) = 0.0 + K = 1 + DO J = 1,InitInp%NWaveKin ! Loop through all points where the incident wave kinematics will be computed + + IF ( ( InitInp%WaveKinzi(J) < -InitInp%WtrDpth ) .OR. ( InitInp%WaveKinzi(J) > 0.0 ) ) THEN + ! .TRUE. if the elevation of the point defined by WaveKinzi(J) lies below the seabed or above mean sea level (exclusive) + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + + InitOut%WaveDynP(:,J ) = 0.0 + InitOut%WaveVel (:,J,:) = 0.0 + InitOut%WaveAcc (:,J,:) = 0.0 + + ELSE + ! The elevation of the point defined by WaveKinzi(J) must lie between the seabed and the mean sea level (inclusive) + + InitOut%WaveDynP(0:InitOut%NStepWave-1,J ) = WaveDynP0B( 0:InitOut%NStepWave-1,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,1) = WaveVel0Hxi(0:InitOut%NStepWave-1,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,2) = WaveVel0Hyi(0:InitOut%NStepWave-1,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,3) = WaveVel0V( 0:InitOut%NStepWave-1,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,1) = WaveAcc0Hxi(0:InitOut%NStepWave-1,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,2) = WaveAcc0Hyi(0:InitOut%NStepWave-1,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,3) = WaveAcc0V( 0:InitOut%NStepWave-1,K) + K = K + 1 + END IF + + END DO ! J - All points where the incident wave kinematics will be computed + + ! CASE ( 1 ) ! Vertical stretching. + + + ! Vertical stretching says that the wave kinematics above the mean sea level + ! equal the wave kinematics at the mean sea level. The wave kinematics + ! below the mean sea level are left unchanged: + + + + + + ! CASE ( 2 ) ! Extrapolation stretching. + + + ! Extrapolation stretching uses a linear Taylor expansion of the wave + ! kinematics (and their partial derivatives with respect to z) at the mean + ! sea level to find the wave kinematics above the mean sea level. The + ! wave kinematics below the mean sea level are left unchanged: + + + + + + ! CASE ( 3 ) ! Wheeler stretching. + + + ! Wheeler stretching says that wave kinematics calculated using Airy theory + ! at the mean sea level should actually be applied at the instantaneous + ! free surface and that Airy wave kinematics computed at locations between + ! the seabed and the mean sea level should be shifted vertically to new + ! locations in proportion to their elevation above the seabed. + ! + ! Computing the wave kinematics with Wheeler stretching requires that first + ! say that the wave kinematics we computed at the elevations defined by + ! the WaveKinzi0Prime(:) array are actual applied at the elevations found + ! by stretching the elevations in the WaveKinzi0Prime(:) array using the + ! instantaneous wave elevation--these new elevations are stored in the + ! WaveKinzi0St(:) array. Next, we interpolate the wave kinematics + ! computed without stretching to the desired elevations (defined in the + ! WaveKinzi(:) array) using the WaveKinzi0St(:) array: + + + + + ! ENDSELECT + + ! Set the ending timestep to the same as the first timestep + InitOut%WaveDynP(InitOut%NStepWave,: ) = InitOut%WaveDynP(0,: ) + InitOut%WaveVel (InitOut%NStepWave,:,:) = InitOut%WaveVel (0,:,:) + InitOut%WaveAcc (InitOut%NStepWave,:,:) = InitOut%WaveAcc (0,:,:) + InitOut%PWaveDynP0(InitOut%NStepWave,: ) = InitOut%PWaveDynP0(0,: ) + InitOut%PWaveVel0 (InitOut%NStepWave,:,:) = InitOut%PWaveVel0 (0,:,:) + InitOut%PWaveAcc0 (InitOut%NStepWave,:,:) = InitOut%PWaveAcc0 (0,:,:) + InitOut%WaveElev0 (InitOut%NStepWave) = InitOut%WaveElev0 (0 ) + + + + CALL CleanUp ( ) + + +CONTAINS + + + SUBROUTINE WaveElevTimeSeriesAtXY(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStatLcl, ErrMsgLcl ) + + REAL(SiKi), INTENT(IN ) :: Xcoord + REAL(SiKi), INTENT(IN ) :: Ycoord + REAL(SiKi), INTENT( OUT) :: WaveElevSeriesAtXY(0:InitOut%NStepWave) + INTEGER(IntKi), INTENT( OUT) :: ErrStatLcl + INTEGER(IntKi) :: ErrStatLcl2 + CHARACTER(*), INTENT( OUT) :: ErrMsgLcl + + ! This is probably poor programming practice, but we will use I, Omega, WaveNmbr, and tmpComplexArr from the calling routine here. + + ErrStatLcl = ErrID_None + + ! Zero out the temporary array. + tmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi) + + ! Loop through the positive frequency components (including zero). + DO I = 0,InitOut%NStepWave2 + + Omega = I* InitOut%WaveDOmega + WaveNmbr = WaveNumber ( Omega, InitInp%Gravity, InitInp%WtrDpth ) + tmpComplexArr(I) = CMPLX( InitOut%WaveElevC0(1,I), InitOut%WaveElevC0(2,I)) * & + EXP( -ImagNmbr*WaveNmbr*( Xcoord*CosWaveDir(I)+ & + Ycoord*SinWaveDir(I) ) ) + ENDDO + + CALL ApplyFFT_cx ( WaveElevSeriesAtXY(0:InitOut%NStepWave-1), tmpComplexArr, FFT_Data, ErrStatLcl2 ) + CALL SetErrStat(ErrStatLcl2,'Error occured while applying the FFT to InitOut%WaveElevSeries.',ErrStatLcl,ErrMsgLcl,'WaveElevTimeSeriesAtXY') + + ! Append first datpoint as the last as aid for repeated wave data + WaveElevSeriesAtXY(InitOut%NStepWave) = WaveElevSeriesAtXY(0) + + END SUBROUTINE WaveElevTimeSeriesAtXY + + + + SUBROUTINE CleanUp( ) + + IF (ALLOCATED( WaveKinPrimeMap )) DEALLOCATE( WaveKinPrimeMap, STAT=ErrStatTmp) + IF (ALLOCATED( WaveKinzi0Prime )) DEALLOCATE( WaveKinzi0Prime, STAT=ErrStatTmp) + IF (ALLOCATED( WvSpreadCos2SArr )) DEALLOCATE( WvSpreadCos2SArr, STAT=ErrStatTmp) + IF (ALLOCATED( WvSpreadIntegral )) DEALLOCATE( WvSpreadIntegral, STAT=ErrStatTmp) + IF (ALLOCATED( WvSpreadThetas )) DEALLOCATE( WvSpreadThetas, STAT=ErrStatTmp) + IF (ALLOCATED( TmpWaveSeeds )) DEALLOCATE( TmpWaveSeeds, STAT=ErrStatTmp) + IF (ALLOCATED( GHWaveAcc )) DEALLOCATE( GHWaveAcc, STAT=ErrStatTmp) + IF (ALLOCATED( GHWaveDynP )) DEALLOCATE( GHWaveDynP, STAT=ErrStatTmp) + IF (ALLOCATED( GHWaveVel )) DEALLOCATE( GHWaveVel, STAT=ErrStatTmp) + IF (ALLOCATED( GHWvDpth )) DEALLOCATE( GHWvDpth, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAcc0HxiPz0 )) DEALLOCATE( PWaveAcc0HxiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAcc0HyiPz0 )) DEALLOCATE( PWaveAcc0HyiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAcc0VPz0 )) DEALLOCATE( PWaveAcc0VPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAccC0HxiPz0 )) DEALLOCATE( PWaveAccC0HxiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAccC0HyiPz0 )) DEALLOCATE( PWaveAccC0HyiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveAccC0VPz0 )) DEALLOCATE( PWaveAccC0VPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveDynP0BPz0 )) DEALLOCATE( PWaveDynP0BPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveDynPC0BPz0 )) DEALLOCATE( PWaveDynPC0BPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVel0HxiPz0 )) DEALLOCATE( PWaveVel0HxiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVel0HyiPz0 )) DEALLOCATE( PWaveVel0HyiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVel0VPz0 )) DEALLOCATE( PWaveVel0VPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVelC0HxiPz0 )) DEALLOCATE( PWaveVelC0HxiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVelC0HyiPz0 )) DEALLOCATE( PWaveVelC0HyiPz0, STAT=ErrStatTmp) + !IF (ALLOCATED( PWaveVelC0VPz0 )) DEALLOCATE( PWaveVelC0VPz0, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAcc0Hxi )) DEALLOCATE( WaveAcc0Hxi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAcc0Hyi )) DEALLOCATE( WaveAcc0Hyi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAcc0V )) DEALLOCATE( WaveAcc0V, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAccC0Hxi )) DEALLOCATE( WaveAccC0Hxi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAccC0Hyi )) DEALLOCATE( WaveAccC0Hyi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveAccC0V )) DEALLOCATE( WaveAccC0V, STAT=ErrStatTmp) + IF (ALLOCATED( WaveDynP0B )) DEALLOCATE( WaveDynP0B, STAT=ErrStatTmp) + IF (ALLOCATED( WaveDynPC0 )) DEALLOCATE( WaveDynPC0, STAT=ErrStatTmp) + ! IF (ALLOCATED( WaveElev0 )) DEALLOCATE( WaveElev0, STAT=ErrStatTmp) + IF (ALLOCATED( WaveElevC )) DEALLOCATE( WaveElevC, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVel0Hxi )) DEALLOCATE( WaveVel0Hxi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVel0Hyi )) DEALLOCATE( WaveVel0Hyi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVel0V )) DEALLOCATE( WaveVel0V, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVelC0Hxi )) DEALLOCATE( WaveVelC0Hxi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVelC0Hyi )) DEALLOCATE( WaveVelC0Hyi, STAT=ErrStatTmp) + IF (ALLOCATED( WaveVelC0V )) DEALLOCATE( WaveVelC0V, STAT=ErrStatTmp) + IF (ALLOCATED( WvSpreadThetaIdx )) DEALLOCATE( WvSpreadThetaIdx, STAT=ErrStatTmp) + IF (ALLOCATED( tmpComplexArr )) DEALLOCATE( tmpComplexArr, STAT=ErrStatTmp) + RETURN + + END SUBROUTINE CleanUp + + +END SUBROUTINE VariousWaves_Init + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Waves_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Waves_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine !NOTE: We are making this INOUT so that we can overwrite the WaveKinzi with zeros for wave stretching calculations + TYPE(Waves_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Waves_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Waves_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Waves_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Waves_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Waves_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Waves_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Waves_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Waves_UpdateStates() is called in loose coupling & + !! (2) Waves_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Waves_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Local Variables: + INTEGER(IntKi) :: ErrStatTmp ! Temporary error status for processing + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! Temporary error message for procesing +! REAL(ReKi), ALLOCATABLE :: tmpWaveKinzi(:) + +! TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + ! Initialize the pRNG + CALL RandNum_Init(InitInp%RNG, ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Define initialization-routine output here: + + !InitOut%WriteOutputHdr = (/ 'Time', 'Column2' /) + !InitOut%WriteOutputUnt = (/ '(s)', '(-)' /) + + InitOut%RhoXg = InitInp%WtrDens*InitInp%Gravity + + + ! Set the minimum and maximum wave directions to WaveDir. These are reset in the + ! subroutine calls as necessary. + InitOut%WaveDirMin = InitInp%WaveDir + InitOut%WaveDirMax = InitInp%WaveDir + InitOut%WaveDir = InitInp%WaveDir ! Not sure why there are so many copies of this variable, but InitOut%WaveDir must be set, and isn't in all cases otherwise. + + + ! Initialize the variables associated with the incident wave: + + SELECT CASE ( InitInp%WaveMod ) ! Which incident wave kinematics model are we using? + + + CASE ( 0 ) ! None=still water. + + CALL StillWaterWaves_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + IF ( ErrStat >= AbortErrLev ) RETURN + + + + CASE ( 1, 2, 3, 4, 10 ) ! 1, 10: Plane progressive (regular) wave, 2: JONSWAP/Pierson-Moskowitz spectrum (irregular) wave, 3: white-noise, or 4: user-defined spectrum (irregular) wave. + + ! To correctly perform stretching we need wave kinematics at (xi,yi,0) for all nodes where kinematics are computed. + ! This could all be done with the same call to VariousWaves_Init, but then we would have to allocate double the number of temporary data + ! structures for this extra set of locations. + ! INSTEAD, to save memory (at the expense of time) we are going to call VariousWaves_Init, twice! Once for the (xi,yi,zi) locations + ! and then again for the (xi,yi,0) locations. + ! To accomplish this, we need to schuffle some of our data structures or create temporary copies + + ! ! Allocate the temporary storage array for the WvKinxi + !ALLOCATE ( tmpWaveKinzi(InitInp%NWaveKin), STAT = ErrStatTmp ) + !IF ( ErrStatTmp /= ErrID_None ) THEN + ! CALL SetErrStat( ErrID_Fatal,'Error allocating space for tmpWaveKinzi array.',ErrStat,ErrMsg,'Waves_Init') + ! RETURN + !END IF + !!DO I = 1,InitInp%NWaveKin + !! tmpWaveKinzi(I) = InitInp%WaveKinzi(I) + !! InitInp%WaveKinzi(I) = 0.0_ReKi ! Force all zi coordinates to 0.0 for this version of the Waves initialization + !! END DO + ! tmpWaveKinzi = InitInp%WaveKinzi + ! InitInp%WaveKinzi = 0.0_ReKi ! Force all zi coordinates to 0.0 for this version of the Waves initialization + ! + !CALL VariousWaves_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + ! CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + ! IF ( ErrStat >= AbortErrLev ) RETURN + ! + !ALLOCATE ( InitOut%WaveDynP0 (0:InitOut%NStepWave,InitInp%NWaveKin ), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP0.', ErrStat,ErrMsg,'Waves_Init') + ! + !ALLOCATE ( InitOut%WaveVel0 (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel0.', ErrStat,ErrMsg,'Waves_Init') + ! + !ALLOCATE ( InitOut%WaveAcc0 (0:InitOut%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + !IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc0.', ErrStat,ErrMsg,'Waves_Init') + ! + !IF ( ErrStat >= AbortErrLev ) RETURN + ! + ! ! Copy the init output arrays into the MSL versions + !InitOut%WaveDynP0 = InitOut%WaveDynP + !InitOut%WaveAcc0 = InitOut%WaveAcc + !InitOut%WaveVel0 = InitOut%WaveVel + ! + ! ! Reset the zi locations + !InitInp%WaveKinzi = tmpWaveKinzi + ! + ! ! Deallocate data which will be allocated again within the Init routine + !DEALLOCATE( InitOut%WaveDynP ) + !DEALLOCATE( InitOut%WaveAcc ) + !DEALLOCATE( InitOut%WaveVel ) + !DEALLOCATE( InitOut%WaveElevC0) + !DEALLOCATE( InitOut%WaveDirArr) + !DEALLOCATE( InitOut%WaveElev ) + !DEALLOCATE( InitOut%WaveTime ) + !DEALLOCATE( InitOut%NodeInWater ) + + ! Now call the init with all the zi locations for the Morrison member nodes + CALL VariousWaves_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + IF ( ErrStat >= AbortErrLev ) RETURN + + + CASE ( 5 ) ! User-supplied wave elevation time history; HD derives full wave kinematics from this elevation time series data. + + ! Get the wave frequency information from the file (by FFT of the elevation) + CALL UserWaveElevations_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Now call VariousWaves to continue using the wave elevation and derived frequency information from the file + CALL VariousWaves_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + IF ( ErrStat >= AbortErrLev ) RETURN + + + CASE ( 6 ) ! User-supplied wave kinematics data. + + CALL UserWaves_Init( InitInp, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves_Init') + IF ( ErrStat >= AbortErrLev ) RETURN + ENDSELECT + + + u%DummyInput = 0.0 + p%DT = Interval + p%WaveMultiDir = InitOut%WaveMultiDir ! Flag to indicate multidirectional waves + x%DummyContState = 0.0 + xd%DummyDiscState = 0.0 + z%DummyConstrState = 0.0 + OtherState%DummyOtherState = 0 + m%DummyMiscVar = 0 + y%DummyOutput = 0.0 + + + +END SUBROUTINE Waves_Init + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Waves_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Waves_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Waves_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Waves_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Waves_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Waves_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Waves_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(Waves_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Waves_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 + + ! Local error handling variables + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(ErrMsgLen) :: ErrMsgTmp + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_End' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + ! Close files here: + + + + ! Destroy the input data: + + CALL Waves_DestroyInput( u, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + ! Destroy the parameter data: + + CALL Waves_DestroyParam( p, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + ! Destroy the state data: + + CALL Waves_DestroyContState( x, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyDiscState( xd, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyConstrState( z, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL Waves_DestroyOtherState( OtherState, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + CALL Waves_DestroyMisc( m, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + ! Destroy the output data: + + CALL Waves_DestroyOutput( y, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + + +END SUBROUTINE Waves_End +!---------------------------------------------------------------------------------------------------------------------------------- + +!======================================================================= +FUNCTION WheelerStretching ( zOrzPrime, Zeta, h, ForwardOrBackward, ErrStat, ErrMsg ) + + + ! This FUNCTION applies the principle of Wheeler stretching to + ! (1-Forward) find the elevation where the wave kinematics are to + ! be applied using Wheeler stretching or (2-Backword) find the + ! elevation where the wave kinematics are computed before applying + ! Wheeler stretching. Wheeler stretching says that wave + ! kinematics calculated using Airy theory at the mean sea level + ! should actually be applied at the instantaneous free surface and + ! that Airy wave kinematics computed at locations between the + ! seabed and the mean sea level should be shifted vertically to + ! new locations in proportion to their elevation above the seabed + ! as follows: + ! + ! Forward: z(zPrime,Zeta,h) = ( 1 + Zeta/h )*zPrime + Zeta + ! + ! or equivalently: + ! + ! Backword: zPrime(z,Zeta,h) = ( z - Zeta )/( 1 + Zeta/h ) + ! + ! where, + ! Zeta = instantaneous elevation of incident waves + ! h = water depth + ! z = elevations where the wave kinematics are to be + ! applied using Wheeler stretching + ! zPrime = elevations where the wave kinematics are computed + ! before applying Wheeler stretching + + + + IMPLICIT NONE + + + ! Passed Variables: + + REAL(SiKi), INTENT(IN ) :: h ! Water depth (meters) + REAL(SiKi) :: WheelerStretching ! This function = zPrime [forward] or z [backward] (meters) + REAL(SiKi), INTENT(IN ) :: Zeta ! Instantaneous elevation of incident waves (meters) + REAL(SiKi), INTENT(IN ) :: zOrzPrime ! Elevations where the wave kinematics are to be applied using Wheeler stretching, z, [forward] or elevations where the wave kinematics are computed before applying Wheeler stretching, zPrime, [backward] (meters) + CHARACTER(1), INTENT(IN ) :: ForwardOrBackWard ! A string holding the direction ('F'=Forward, 'B'=Backward) for applying Wheeler stretching. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Apply Wheeler stretching, depending on the direction: + + SELECT CASE ( ForwardOrBackWard ) + + CASE ( 'F' ) ! Forward + + WheelerStretching = ( 1.0 + Zeta/h )*zOrzPrime + Zeta + + + CASE ( 'B' ) ! Backward + + WheelerStretching = ( zOrzPrime - Zeta )/( 1.0 + Zeta/h ) + + + CASE DEFAULT + + WheelerStretching = 0.0_SiKi + + ErrMsg = 'The last argument in routine WheelerStretching() must be ''F'' or ''B''.' + ErrStat = ErrID_Fatal + RETURN + + + END SELECT + + + + RETURN +END FUNCTION WheelerStretching + +END MODULE Waves +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/Waves.txt b/OpenFAST/modules/hydrodyn/src/Waves.txt new file mode 100644 index 000000000..366067469 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves.txt @@ -0,0 +1,137 @@ +################################################################################################################################### +# Registry for Waves in the FAST Modularization Framework +# This Registry file is used to create MODULE Waves_Types which contains all of the user-defined types needed in Waves. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Waves/Waves InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ CHARACTER(1024) DirRoot - - - "The name of the root file including the full path. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot." - +typedef ^ ^ CHARACTER(1024) WvKinFile - - - "The root name of user input wave kinematics files" - +typedef ^ ^ LOGICAL WriteWvKin - - - "Flag indicating whether we are going to write out kinematics files. [Must be FALSE if WaveMod = 5 or 6, if TRUE then WvKinFile must have a string value and this is the rootname for all the output files]" - +typedef ^ ^ INTEGER UnSum - - - "The unit number for the HydroDyn summary file" - +typedef ^ ^ ReKi Gravity - - - "Gravitational acceleration" (m/s^2) +typedef ^ ^ ReKi MSL2SWL - - - "Offset between still-water level and mean sea level [positive upward; must be zero if using WAMIT]" (meters) +typedef ^ ^ SiKi WvLowCOff - - - "Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4]" (rad/s) +typedef ^ ^ SiKi WvHiCOff - - - "High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4]" (rad/s) +typedef ^ ^ SiKi WaveDir - - - "Mean incident wave propagation heading direction" (degrees) +typedef ^ ^ INTEGER WaveNDir - - - "Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module]" (-) +typedef ^ ^ LOGICAL WaveMultiDir - - - "Indicates the waves are multidirectional -- set by HydroDyn_Input" - +typedef ^ ^ INTEGER WaveDirMod - - - "Directional wave spreading function {0: none, 1: COS2S} [only used if WaveMod=6]" - +typedef ^ ^ SiKi WaveDirSpread - - - "Spreading coefficient [WaveMod=2,3,4 and WaveDirMod=1]" - +typedef ^ ^ SiKi WaveDirRange - - - "Range of wave directions (full range: WaveDir +/- WaveDirRange/2) [only used if WaveMod=6]" (degrees) +typedef ^ ^ DbKi WaveDT - - - "Time step for incident wave calculations" (sec) +typedef ^ ^ SiKi WaveHs - - - "Significant wave height of incident waves" (meters) +typedef ^ ^ INTEGER WaveMod - - - "Incident wave kinematics model {0: none=still water, 1: plane progressive (regular), 2: JONSWAP/Pierson-Moskowitz spectrum (irregular), 3: white-noise spectrum, 4: user-defind spectrum from routine UserWaveSpctrm (irregular), 5: GH BLADED }" - +typedef ^ ^ CHARACTER(80) WaveModChr - - - "String to temporarially hold the value of the wave kinematics input line" +typedef ^ ^ LOGICAL WaveNDAmp - - - "Flag for normally-distributed amplitudes in incident waves spectrum [flag]" - +typedef ^ ^ SiKi WavePhase - - - "Specified phase for regular waves" (radians) +typedef ^ ^ SiKi WavePkShp - - - "Peak shape parameter of incident wave spectrum [1.0 for Pierson-Moskowitz]" - +typedef ^ ^ CHARACTER(80) WavePkShpChr - - - "String to temporarially hold value of peak shape parameter input line" - +typedef ^ ^ INTEGER WaveSeed {2} - - "Random seeds of incident waves [-2147483648 to 2147483647]" - +typedef ^ ^ INTEGER WaveStMod - - - "Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching}" - +typedef ^ ^ DbKi WaveTMax - - - "Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT" (sec) +typedef ^ ^ SiKi WaveTp - - - "Peak spectral period of incident waves" (sec) +typedef ^ ^ SiKi WtrDens - - - "Water density" (kg/m^3) +typedef ^ ^ SiKi WtrDpth - - - "Water depth" (meters) +typedef ^ ^ INTEGER NWaveElev - - - "Number of points where the incident wave elevations can be output" - +typedef ^ ^ SiKi WaveElevxi {:} - - "xi-coordinates for points where the incident wave elevations can be output" (meters) +typedef ^ ^ SiKi WaveElevyi {:} - - "yi-coordinates for points where the incident wave elevations can be output" (meters) +typedef ^ ^ SiKi WaveElevXY {:}{:} - - "Supplied by Driver: X-Y locations for WaveElevation output (for visualization). Index 1 corresponds to X or Y coordinate. Index 2 corresponds to point number." - +typedef ^ ^ INTEGER NWaveKin - - - "Number of points where the incident wave kinematics will be computed" - +typedef ^ ^ SiKi WaveKinxi {:} - - "xi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) +typedef ^ ^ SiKi WaveKinyi {:} - - "yi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) +typedef ^ ^ SiKi WaveKinzi {:} - - "zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) +typedef ^ ^ SiKi CurrVxi {:} - - "xi-component of the current velocity at elevation i" (m/s) +typedef ^ ^ SiKi CurrVyi {:} - - "yi-component of the current velocity at elevation i" (m/s) +typedef ^ ^ SiKi PCurrVxiPz0 - - - "xi-component of the partial derivative of the current velocity at elevation near mean sea level" (m/s) +typedef ^ ^ SiKi PCurrVyiPz0 - - - "yi-component of the partial derivative of the current velocity at elevation near mean sea level" (m/s) +typedef ^ ^ NWTC_RandomNumber_ParameterType RNG - - - "Parameters for the pseudo random number generator" - + + +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) +typedef ^ ^ SiKi WaveDirArr {:} - - "Wave direction array. Each frequency has a unique direction of WaveNDir > 1" (degrees) +typedef ^ ^ SiKi WaveDirMin - - - "Minimum wave direction." (degrees) +typedef ^ ^ SiKi WaveDirMax - - - "Maximum wave direction." (degrees) +typedef ^ ^ SiKi WaveDir - - - "Incident wave propagation heading direction" (degrees) +typedef ^ ^ INTEGER WaveNDir - - - "Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module]" (-) +typedef ^ ^ LOGICAL WaveMultiDir - - - "Indicates the waves are multidirectional -- set by HydroDyn_Input" - +typedef ^ ^ SiKi WaveDOmega - - - "Frequency step for incident wave calculations" (rad/s) +typedef ^ ^ SiKi WaveKinzi {:} - - "zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean see level" (meters) +typedef ^ ^ SiKi PWaveDynP0 {:}{:} - - "Instantaneous dynamic pressure of incident waves , at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveDynP {:}{:} - - "Instantaneous dynamic pressure of incident waves , accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "Instantaneous acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi PWaveAcc0 {:}{:}{:} - - "Instantaneous acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "Instantaneous velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) +typedef ^ ^ SiKi PWaveVel0 {:}{:}{:} - - "Instantaneous velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) +typedef ^ ^ SiKi WaveElev {:}{:} - - "Instantaneous elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output" (meters) +typedef ^ ^ SiKi WaveElev0 {:} - - "Instantaneous elevation time-series of incident waves at the platform reference point" (meters) + +typedef ^ ^ SiKi WaveElevSeries {:}{:} - - "Instantaneous elevation time-series at each of the points given by WaveElevXY. Used for making movies of the waves. First index is the timestep. Second index is XY point number corresponding to second index of WaveElevXY." (m) + +typedef ^ ^ SiKi WaveTime {:} - - "Simulation times at which the instantaneous elevation of, velocity of, acceleration of, and loads associated with the incident waves are determined" (sec) +typedef ^ ^ DbKi WaveTMax - - - "Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT" (sec) +typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +typedef ^ ^ SiKi RhoXg - - - "= WtrDens*Gravity" - +typedef ^ ^ INTEGER NStepWave - - - "Total number of frequency components = total number of time steps in the incident wave" - +typedef ^ ^ INTEGER NStepWave2 - - - "NStepWave / 2" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - + + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - + + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - + + +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType INTEGER 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 INTEGER DummyMiscVar - - - "Remove this variable if you have misc/optimization 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ^ DbKi WaveTMax - - - "Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT" (sec) +typedef ^ ^ INTEGER NStepWave - - - "Total number of frequency components = total number of time steps in the incident wave" - +typedef ^ ^ INTEGER WaveNDir - - - "Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module]" (-) +typedef ^ ^ LOGICAL WaveMultiDir - - - "Indicates the waves are multidirectional -- set by HydroDyn_Input" - + + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +#typedef ^ InputType MeshType MeshedInput - - - "Meshed input data" - + +# Define inputs that are not on this mesh here: +typedef ^ InputType SiKi DummyInput - - - "Remove this variable if you have input data" - + + +# ..... Outputs ................................................................................................................... +# Define outputs that are not on this mesh here: +typedef ^ OutputType SiKi DummyOutput - - - "Remove this variable if you have output data" - diff --git a/OpenFAST/modules/hydrodyn/src/Waves2.f90 b/OpenFAST/modules/hydrodyn/src/Waves2.f90 new file mode 100644 index 000000000..97ea03a20 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves2.f90 @@ -0,0 +1,2433 @@ +!********************************************************************************************************************************** +! NOTE: documentation in this file is written for use with Doxygen 1.8.6 and higher. +! +!> Waves2 module +!! +!! This module calculates the second order wave forces on a structure. This module is used with HydroDyn in FAST. +!! +!! This software is written in the FAST modular framework. +!! +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2012-2015 National Renewable Energy Laboratory +! +! This file is part of the Waves2 sub-module of HydroDyn. +! +! 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 +! +!********************************************************************************************************************************** +MODULE Waves2 + + + + !> Known issues: + !! + + USE Waves2_Types +! USE WAMIT_Interp + USE Waves2_Output + USE NWTC_Library + USE NWTC_FFTPACK + USE Waves, ONLY : WaveNumber + + IMPLICIT NONE + + PRIVATE + +! INTEGER(IntKi), PARAMETER :: DataFormatID = 1 !< Update this value if the data types change (used in Waves2_Pack) + TYPE(ProgDesc), PARAMETER :: Waves2_ProgDesc = ProgDesc( 'Waves2', '', '' ) + !< This holds the name of the program, version info, and date. + + REAL(DbKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of DbKi. + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Waves2_Init !< Initialization routine + PUBLIC :: Waves2_End !< Ending routine (includes clean up) + + PUBLIC :: Waves2_UpdateStates !< Loose coupling routine for solving for constraint states, integrating + !! continuous states, and updating discrete states + PUBLIC :: Waves2_CalcOutput !< Routine for computing outputs + + PUBLIC :: Waves2_CalcConstrStateResidual !< Tight coupling routine for returning the constraint state residual + PUBLIC :: Waves2_CalcContStateDeriv !< Tight coupling routine for computing derivatives of continuous states + PUBLIC :: Waves2_UpdateDiscState !< Tight coupling routine for updating discrete states + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!> @brief +!! This routine is called at the start of the simulation to perform initialization steps. +!! The parameters that are set here are not changed during the simulation. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Waves2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(Waves2_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Waves2_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Waves2_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Waves2_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Waves2_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Waves2_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; only the output mesh is initialized) + TYPE(Waves2_MiscVarType), INTENT( OUT) :: misc !< Misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: don't change it from the glue code provided value. + TYPE(Waves2_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local Variables + COMPLEX(SiKi) :: ImagNmbr = (0.0,1.0) !< The imaginary number, \f$ \sqrt{-1.0} \f$ + + INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: n !< Generic counter for calculations + INTEGER(IntKi) :: m !< Generic counter for calculations + INTEGER(IntKi) :: mu_minus !< Generic counter for difference kinematics calculations + INTEGER(IntKi) :: mu_plus !< Generic counter for sum kinematics calculations + + REAL(SiKi) :: B_minus !< The value of the \f$ B^-_{nm} \f$ transfer function for the current n,m,z. + REAL(SiKi) :: B_plus !< The value of the \f$ B^+_{nm} \f$ transfer function for the current n,m,z. + + REAL(SiKi) :: Omega_n !< The frequency corresponding to index n + REAL(SiKi) :: Omega_m !< The frequency corresponding to index m + REAL(SiKi) :: Omega_minus !< The difference frequency corresponding to \f$ \omega_{\mu^-} \f$ + REAL(SiKi) :: Omega_plus !< The sum frequency corresponding to \f$ \omega_{\mu^+} \f$ + + REAL(SiKi) :: k_n !< The wavenumber corresponding to \f$ \omega_n \f$ + REAL(SiKi) :: k_m !< The wavenumber corresponding to \f$ \omega_m \f$ + REAL(SiKi) :: k_nm !< Value of \f$ k_{nm}^{-} \f$ + + COMPLEX(SiKi) :: WaveElevxyPrime0 !< The dot product of the wave vector differece and location \f$ \exp[ -i * (\vec{k_n}-\vec{k_m})\cdot\vec{x}] \f$ + + COMPLEX(SiKi) :: WaveElevC_n !< The complex wave elevation for the nth frequency component + COMPLEX(SiKi) :: WaveElevC_m !< The complex wave elevation for the mth frequency component + COMPLEX(SiKi), ALLOCATABLE :: WaveElevC0Norm(:) !< The complex wave amplitude, normalized for these equations. + + ! Velocity calculations + REAL(SiKi) :: Ux_nm_minus !< The value of \f$ _xU^-_{nm} = B_{nm}^- \cdot (|\vec{k_n}|\cos \theta_n - |\vec{k_m}|\cos \theta_m) \f$ used in calculating the x-component of the second order wave velocity + REAL(SiKi) :: Ux_nm_plus !< The value of \f$ _xU^+_{nm} = B_{nm}^+ \cdot (|\vec{k_n}|\cos \theta_n + |\vec{k_m}|\cos \theta_m) \f$ used in calculating the x-component of the second order sum-frequency wave velocity + REAL(SiKi) :: Uy_nm_minus !< The value of \f$ _yU^-_{nm} = B_{nm}^- \cdot (|\vec{k_n}|\sin \theta_n - |\vec{k_m}|\sin \theta_m) \f$ used in calculating the y-component of the second order wave velocity + REAL(SiKi) :: Uy_nm_plus !< The value of \f$ _yU^+_{nm} = B_{nm}^+ \cdot (|\vec{k_n}|\sin \theta_n + |\vec{k_m}|\sin \theta_m) \f$ used in calculating the y-component of the second order sum-frequency wave velocity + COMPLEX(SiKi) :: Uz_nm_minus !< The value of \f$ _z{U}^-_{nm} = (\imath) \cdot {B}_{nm}^- \cdot k^-_{nm} \cdot \tanh[k^-_{nm}(h+z)] \f$ used in calculating the z-component of the second order wave velocity + COMPLEX(SiKi) :: Uz_nm_plus !< The value of \f$ _z{U}^+_{nm} = (\imath) \cdot {B}_{nm}^+ \cdot k^+_{nm} \cdot \tanh[k^+_{nm}(h+z)] \f$ used in calculating the z-component of the second order sum-frequency wave velocity + + ! Acceleration calculations + COMPLEX(SiKi) :: Accx_nm_minus !< The value of \f$ _xAcc^-_{nm} = (\imath) \cdot _xU^-_{nm} \omega_{\mu^-} \f$ + COMPLEX(SiKi) :: Accx_nm_plus !< The value of \f$ _xAcc^+_{nm} = (\imath) \cdot _xU^+_{nm} \omega_{\mu^+} \f$ + COMPLEX(SiKi) :: Accy_nm_minus !< The value of \f$ _yAcc^-_{nm} = (\imath) \cdot _yU^-_{nm} \omega_{\mu^-} \f$ + COMPLEX(SiKi) :: Accy_nm_plus !< The value of \f$ _yAcc^+_{nm} = (\imath) \cdot _yU^+_{nm} \omega_{\mu^+} \f$ + COMPLEX(SiKi) :: Accz_nm_minus !< The value of \f$ _z{Acc}^-_{nm} = (\imath) \cdot _zU^-_{nm} \omega_{\mu^-} \f$ + COMPLEX(SiKi) :: Accz_nm_plus !< The value of \f$ _z{Acc}^+_{nm} = (\imath) \cdot _zU^+_{nm} \omega_{\mu^+} \f$ + + ! Pressure calculations + REAL(SiKi) :: DynP_nm_minus !< The value of \f$ \rho_\mathrm{w} B_{nm}^- \omega_{\mu^-} \f$ + REAL(SiKi) :: DynP_nm_plus !< The value of \f$ \rho_\mathrm{w} B_{nm}^+ \omega_{\mu^+} \f$ + + ! Tracking of joints for which we are doing calculations + REAL(SiKi), ALLOCATABLE :: WaveKinzi0Prime(:) !< zi-coordinates for points where the incident wave kinematics will be computed before applying stretching; these are relative to the mean see level (meters) + INTEGER(IntKi), ALLOCATABLE :: WaveKinPrimeMap(:) !< Mapping function for the wave kinematics to calculate (based on depth) + INTEGER(IntKi) :: NWaveKin0Prime !< Number of points where the incident wave kinematics will be computed before applying stretching to the instantaneous free surface (-) + + + ! Second order wave elevation calculations + REAL(SiKi), ALLOCATABLE :: TmpTimeSeries(:) !< Temporary storage for a wave elevation time series for a single point. + REAL(SiKi), ALLOCATABLE :: TmpTimeSeries2(:) !< Temporary storage for a wave elevation time series for a single point. + COMPLEX(SiKi), ALLOCATABLE :: TmpFreqSeries(:) !< Temporary storage for a wave elevation frequency series for a single point. + COMPLEX(SiKi), ALLOCATABLE :: TmpFreqSeries2(:) !< Temporary storage for a wave elevation frequency series for a single point. + + + ! Calculation of 2nd order particle acceleration, velocity, and pressure terms + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2xCDiff(:) !< Frequency space difference frequency particle velocity term in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2yCDiff(:) !< Frequency space difference frequency particle velocity term in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2zCDiff(:) !< Frequency space difference frequency particle velocity term in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2xCDiff(:) !< Frequency space difference frequency particle acceleration term in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2yCDiff(:) !< Frequency space difference frequency particle acceleration term in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2zCDiff(:) !< Frequency space difference frequency particle acceleration term in the z direction + REAL(SiKi), ALLOCATABLE :: WaveVel2xDiff(:) !< Time domain difference frequency particle velocity term in the x direction + REAL(SiKi), ALLOCATABLE :: WaveVel2yDiff(:) !< Time domain difference frequency particle velocity term in the y direction + REAL(SiKi), ALLOCATABLE :: WaveVel2zDiff(:) !< Time domain difference frequency particle velocity term in the z direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2xDiff(:) !< Time domain difference frequency particle acceleration term in the x direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2yDiff(:) !< Time domain difference frequency particle acceleration term in the y direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2zDiff(:) !< Time domain difference frequency particle acceleration term in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveDynP2CDiff(:) !< Frequency space difference frequency dynamic pressure term + REAL(SiKi), ALLOCATABLE :: WaveDynP2Diff(:) !< Time domain difference frequency dynamic pressure term + + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2xCSumT1(:) !< Frequency space difference frequency particle velocity term 1 in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2yCSumT1(:) !< Frequency space difference frequency particle velocity term 1 in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2zCSumT1(:) !< Frequency space difference frequency particle velocity term 1 in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2xCSumT1(:) !< Frequency space difference frequency particle acceleration term 1 in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2yCSumT1(:) !< Frequency space difference frequency particle acceleration term 1 in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2zCSumT1(:) !< Frequency space difference frequency particle acceleration term 1 in the z direction + REAL(SiKi), ALLOCATABLE :: WaveVel2xSumT1(:) !< Time domain difference frequency particle velocity term 1 in the x direction + REAL(SiKi), ALLOCATABLE :: WaveVel2ySumT1(:) !< Time domain difference frequency particle velocity term 1 in the y direction + REAL(SiKi), ALLOCATABLE :: WaveVel2zSumT1(:) !< Time domain difference frequency particle velocity term 1 in the z direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2xSumT1(:) !< Time domain difference frequency particle acceleration term 1 in the x direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2ySumT1(:) !< Time domain difference frequency particle acceleration term 1 in the y direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2zSumT1(:) !< Time domain difference frequency particle acceleration term 1 in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveDynP2CSumT1(:) !< Frequency space difference frequency dynamic pressure term 1 + REAL(SiKi), ALLOCATABLE :: WaveDynP2SumT1(:) !< Time domain difference frequency dynamic pressure term 1 + + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2xCSumT2(:) !< Frequency space difference frequency particle velocity term 2 in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2yCSumT2(:) !< Frequency space difference frequency particle velocity term 2 in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveVel2zCSumT2(:) !< Frequency space difference frequency particle velocity term 2 in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2xCSumT2(:) !< Frequency space difference frequency particle acceleration term 2 in the x direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2yCSumT2(:) !< Frequency space difference frequency particle acceleration term 2 in the y direction + COMPLEX(SiKi), ALLOCATABLE :: WaveAcc2zCSumT2(:) !< Frequency space difference frequency particle acceleration term 2 in the z direction + REAL(SiKi), ALLOCATABLE :: WaveVel2xSumT2(:) !< Time domain difference frequency particle velocity term 2 in the x direction + REAL(SiKi), ALLOCATABLE :: WaveVel2ySumT2(:) !< Time domain difference frequency particle velocity term 2 in the y direction + REAL(SiKi), ALLOCATABLE :: WaveVel2zSumT2(:) !< Time domain difference frequency particle velocity term 2 in the z direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2xSumT2(:) !< Time domain difference frequency particle acceleration term 2 in the x direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2ySumT2(:) !< Time domain difference frequency particle acceleration term 2 in the y direction + REAL(SiKi), ALLOCATABLE :: WaveAcc2zSumT2(:) !< Time domain difference frequency particle acceleration term 2 in the z direction + COMPLEX(SiKi), ALLOCATABLE :: WaveDynP2CSumT2(:) !< Frequency space difference frequency dynamic pressure term 2 + REAL(SiKi), ALLOCATABLE :: WaveDynP2SumT2(:) !< Time domain difference frequency dynamic pressure term 2 + + ! Stuff for the FFT calculations + TYPE(FFT_DataType) :: FFT_Data !< the instance of the FFT module we're using + + + + + ! Temporary error trapping variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for holding the error status returned from a CALL statement + CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for holding the error message returned from a CALL statement + + + ! Subroutine contents + + ! Initialize Error handling variables + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + ! Initialize the data storage + misc%LastIndWave = 1_IntKi + + ! Initialize the NWTC Subroutine Library and display the information about this module. + + CALL NWTC_Init( ) + + + !----------------------------------------------------------------------------- + !> Before attempting to do any real calculations, we first check what was + !! passed in through _InitInp_ to make sure it makes sense. That routine will + !! then copy over the relevant information that should be kept in parameters + !! (_p_). + !! + !! _InitInp_ will also check the flags, existence of files, and set flags + !! accordingly. + !----------------------------------------------------------------------------- + + + !-------------------------------------------------------------------------------- + ! Check the Min and Max frequencies for the full QTF cases + ! -- these checks are performed based on the DiffQTFF and SumQTFF flags + !-------------------------------------------------------------------------------- + + ! 1. Check that the min / max diff frequencies make sense if using DiffQTF + + IF ( InitInp%WvDiffQTFF .eqv. .TRUE. ) THEN + IF ( ( InitInp%WvHiCOffD < InitInp%WvLowCOffD ) .OR. ( InitInp%WvLowCOffD < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to Waves2_Init: '//NewLine// & + ' WvHiCOffD must be larger than WvLowCOffD. Both must be positive.'// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'Waves2_Init') + CALL CleanUp + RETURN + END IF + END IF + + + ! 2. Check that the min / max diff frequencies make sense if using SumQTF + + IF ( InitInp%WvSumQTFF .eqv. .TRUE. ) THEN + IF ( ( InitInp%WvHiCOffS < InitInp%WvLowCOffS ) .OR. ( InitInp%WvLowCOffS < 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to Waves2_Init: '//NewLine// & + ' WvHiCOffS must be larger than WvLowCOffS. Both must be positive.'// & + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'Waves2_Init') + CALL CleanUp + RETURN + END IF + END IF + + + + !-------------------------------------------------------------------------------- + ! Check the size of arrays that were passed in containing the wave info + !-------------------------------------------------------------------------------- + + + ! Check that WaveElevC0 is a 2x(NStepWave2+1) sized array (0 index start) + + IF ( SIZE( InitInp%WaveElevC0, DIM=2 ) /= (InitInp%NStepWave2 + 1) ) THEN ! Expect a 2x(0:NStepWave2) array + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to Waves2_Init:'//NewLine// & + ' --> Expected array for WaveElevC0 to be of size 2x'//TRIM(Num2LStr(InitInp%NStepWave2 + 1))// & + ' (2x(NStepWave2+1)), but instead received array of size '// & + TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,1)))//'x'//TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,2)))//'.', & + ErrStat, ErrMsg, 'Waves2_Init') + CALL CleanUp + RETURN + END IF + + + ! Check that WaveTime is of size (NStepWave+1) + + IF ( SIZE( InitInp%WaveTime ) /= (InitInp%NStepWave + 1) ) THEN ! Expect a 2x(0:NStepWave2) array + CALL SetErrStat( ErrID_Fatal, ' Programming error in call to Waves2_Init:'//NewLine// & + ' --> Expected array for WaveTime to be of size '//TRIM(Num2LStr(InitInp%NStepWave + 1))// & + ' (NStepWave+1), but instead received array of size '// & + TRIM(Num2LStr(SIZE(InitInp%WaveTime)))//'.', & + ErrStat, ErrMsg, 'Waves2_Init') + CALL CleanUp + RETURN + END IF + + + !-------------------------------------------------------------------------------- + ! Now copy over things to parameters... + !-------------------------------------------------------------------------------- + + ! Wave information we need to keep + + p%NWaveElev = InitInp%NWaveElev + p%NStepWave = InitInp%NStepWave + p%NStepWave2 = InitInp%NStepWave2 + + + ! Time related information + + p%DT = Interval ! Timestep from calling program + + + ! Allocate array for the WaveTime information -- array of times to generate output for. NOTE: can't use MOVE_ALLOC since InitInp is intent in. + CALL AllocAry( p%WaveTime, SIZE(InitInp%WaveTime,DIM=1), 'array to hold WaveTime', ErrStatTmp, ErrMsgTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveTime.',ErrStat,ErrMsg,'Waves2_Init') + p%WaveTime = InitInp%WaveTime + + ! Difference QTF + p%WvDiffQTFF = InitInp%WvDiffQTFF ! Flag for calculation + + ! Summation QTF + p%WvSumQTFF = InitInp%WvSumQTFF ! Flag for calculation + + + ! Initialize the channel outputs + p%NumOuts = InitInp%NumOuts + p%NumOutAll = InitInp%NumOutAll + + CALL Wvs2OUT_Init( InitInp, y, p, InitOut, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + + ! The wave elevation information in frequency space -- we need to normalize this by NStepWave2 + ALLOCATE ( WaveElevC0Norm(0:InitInp%NStepWave2) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveElevC0Norm.',ErrStat,ErrMsg,'Waves2_Init') + + DO I=0,InitInp%NStepWave2 + WaveElevC0Norm(I) = CMPLX( InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I) ) / REAL(InitInp%NStepWave2) + ENDDO + + !-------------------------------------------------------------------------------- + ! Setup WaveKin0Prime -- points from the mesh that are passed in + !-------------------------------------------------------------------------------- + + !> @note Wave stretching will need to be incorporated here when we add it to + !! the waves module. + + ! Determine the number of, NWaveKin0Prime, and the zi-coordinates for, + ! WaveKinzi0Prime(:), points where the incident wave kinematics will be + ! computed before applying stretching to the instantaneous free surface. + ! The locations are relative to the mean see level. These depend on + ! which incident wave kinematics stretching method is being used: + + + ! SELECT CASE ( InitInp%WaveStMod ) ! Which model are we using to extrapolate the incident wave kinematics to the instantaneous free surface? + + ! CASE ( 0 ) ! None=no stretching. + + + ! Since we have no stretching, NWaveKin0Prime and WaveKinzi0Prime(:) are + ! equal to the number of, and the zi-coordinates for, the points in the + ! WaveKinzi(:) array between, and including, -WtrDpth and 0.0. + + ! Determine NWaveKin0Prime here: + + NWaveKin0Prime = 0 + DO J = 1,InitInp%NWaveKin ! Loop through all mesh points where the incident wave kinematics will be computed + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + NWaveKin0Prime = NWaveKin0Prime + 1 + END IF + END DO ! J - All Morison nodes where the incident wave kinematics will be computed + + + + ! ALLOCATE the WaveKinzi0Prime(:) array and compute its elements here: + + ALLOCATE ( WaveKinzi0Prime(NWaveKin0Prime) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveKinzi0Prime.',ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveKinPrimeMap(NWaveKin0Prime) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveKinPrimeMap.',ErrStat,ErrMsg,'Waves2_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + I = 1 + + DO J = 1,InitInp%NWaveKin ! Loop through all points where the incident wave kinematics will be computed without stretching + ! NOTE: We test to 0 instead of MSL2SWL because the locations of WaveKinzi and WtrDpth have already been adjusted using MSL2SWL + IF ( InitInp%WaveKinzi(J) >= -InitInp%WtrDpth .AND. InitInp%WaveKinzi(J) <= 0 ) THEN + + WaveKinzi0Prime(I) = InitInp%WaveKinzi(J) + WaveKinPrimeMap(I) = J + I = I + 1 + + END IF + + END DO ! J - All points where the incident wave kinematics will be computed without stretching + + + + !CASE ( 1, 2 ) ! Vertical stretching or extrapolation stretching. + ! CALL SetErrStat(ErrID_Fatal,' Vertical and extrapolation stretching not supported in second order calculations.',ErrStat,ErrMsg,'Waves2_Init') + ! + ! + !CASE ( 3 ) ! Wheeler stretching. + ! CALL SetErrStat(ErrID_Fatal,' Wheeler stretching not supported in second order calculations.',ErrStat,ErrMsg,'Waves2_Init') + ! + !CASE DEFAULT + ! CALL SetErrStat(ErrID_Fatal,' Stretching is not supported in the second order waves kinematics calculations.',ErrStat,ErrMsg,'Waves2_Init') + ! + ! + !ENDSELECT + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + + !-------------------------------------------------------------------------------- + ! Setup the output arrays + !-------------------------------------------------------------------------------- + + + ALLOCATE ( p%WaveElev2 (0:InitInp%NStepWave,InitInp%NWaveElev ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array p%WaveElev2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveVel2D (0:InitInp%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel2D.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveAcc2D (0:InitInp%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc2D.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveDynP2D (0:InitInp%NStepWave,InitInp%NWaveKin ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP2D.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveVel2S (0:InitInp%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveVel2S.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveAcc2S (0:InitInp%NStepWave,InitInp%NWaveKin,3), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveAcc2S.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( InitOut%WaveDynP2S (0:InitInp%NStepWave,InitInp%NWaveKin ), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveDynP2S.', ErrStat,ErrMsg,'Waves2_Init') + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + !Initialize the output arrays to zero. We will only fill it in for the points we calculate. + p%WaveElev2 = 0.0_SiKi + InitOut%WaveVel2D = 0.0_SiKi + InitOut%WaveAcc2D = 0.0_SiKi + InitOut%WaveDynP2D = 0.0_SiKi + InitOut%WaveVel2S = 0.0_SiKi + InitOut%WaveAcc2S = 0.0_SiKi + InitOut%WaveDynP2S = 0.0_SiKi + + + + ! For creating animations of the sea surface, the WaveElevXY array is passed in with a series of x,y coordinates + ! (index 1). The second index corresponds to the number of points passed in. A two dimensional time series + ! is created with the first index corresponding to the timestep, and second index corresponding to the second + ! index of the WaveElevXY array. + IF ( ALLOCATED(InitInp%WaveElevXY)) THEN + ALLOCATE ( InitOut%WaveElevSeries2 (0:InitInp%NStepWave, 1:SIZE(InitInp%WaveElevXY, DIM=2)) , STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Cannot allocate array InitOut%WaveElevSeries2.',ErrStat,ErrMsg,'Waves2_Init') + CALL CleanUp() + RETURN + END IF + ENDIF + + + ! For calculating the 2nd-order wave elevation corrections, we need a temporary array to hold the information. + ALLOCATE ( TmpTimeSeries(0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpTimeSeries.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( TmpTimeSeries2(0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpTimeSeries2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( TmpFreqSeries(0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpFreqSeries.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( TmpFreqSeries2(0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array TmpFreqSeries2.', ErrStat,ErrMsg,'Waves2_Init') + + + + !-------------------------------------------------------------------------------- + ! Setup the FFT working arrays + !-------------------------------------------------------------------------------- + + CALL InitFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + !-------------------------------------------------------------------------------- + !> # Difference Frequency # + !! The second order difference frequency corrections to the velocity, acceleration, + !! and pressure can be written in generic form as: + !! + !! \f$ + !! V^{(2)-}(t) = 2 \Re \left[ \sum_{\mu^-=1}^{\frac{N}{2}-1} H^-(\omega_{\mu^-}) + !! \exp(\imath \omega_{\mu^-} t) \right] + !! = 2 \operatorname{IFFT}\left[H^-\right] \f$ + !! + !! Notice that in the equations that follow, there is no term analagous to the mean + !! drift term in the WAMIT2 module. Rather, for \f$ \omega_{\mu^-} = 0 \f$, the + !! result is zero. So this term is not included. + !-------------------------------------------------------------------------------- + + + IF(p%WvDiffQTFF) THEN + + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( ' Calculating second order difference frequency wave kinematics.' ) + + + !-------------------------------------------------------------------------------- + ! Setup arrays for the calculations + !-------------------------------------------------------------------------------- + + ! Frequency space arrays: + + ALLOCATE ( WaveVel2xCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xCDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2yCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2yCDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zCDiff.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xCDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2yCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2yCDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zCDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zCDiff.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2CDiff (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2CDiff.', ErrStat,ErrMsg,'Waves2_Init') + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Time domain arrays: + ALLOCATE ( WaveVel2xDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2yDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2yDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zDiff.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2yDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2yDiff.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zDiff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zDiff.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2Diff (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2Diff.', ErrStat,ErrMsg,'Waves2_Init') + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + !-------------------------------------------------------------------------------- + !> ## Calculate the surface elevation corrections ## + !! + !! For each (x,y) coordinate that a wave elevation is requested at (both from the + !! (WaveElevxi,WaveElevyi) pairs, and the WaveElevXY pairs), a call is made to the + !! subroutine waves2::waveelevtimeseriesatxy_diff to calculate the full time series for + !! that point. The results are added to the wave elevation results from the sum + !! frequency calculations later in the code. + !-------------------------------------------------------------------------------- + + ! Step through the requested points + DO I=1,InitInp%NWaveElev + CALL WaveElevTimeSeriesAtXY_Diff(InitInp%WaveElevxi(I), InitInp%WaveElevyi(I), TmpTimeSeries, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to InitOut%WaveElev.',ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + p%WaveElev2(:,I) = TmpTimeSeries(:) + ENDDO ! Wave elevation points requested + + + ! Calculate the wave elevation at all points requested in the array WaveElevXY + IF ( ALLOCATED(InitInp%WaveElevXY) ) THEN + DO I = 1,SIZE(InitInp%WaveElevXY, DIM=2) + ! This subroutine call applies the FFT at the correct location. + CALL WaveElevTimeSeriesAtXY_Diff( InitInp%WaveElevXY(1,I), InitInp%WaveElevXY(2,I), TmpTimeSeries, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + InitOut%WaveElevSeries2(:,I) = TmpTimeSeries(:) + ENDDO + ENDIF + + + + !-------------------------------------------------------------------------------- + !> ## Calculate the second order velocity, acceleration, and pressure corrections for all joints below surface. ## + !-------------------------------------------------------------------------------- + + + ! NWaveKin0Prime loop start + DO I=1,NWaveKin0Prime + + + ! Reset the \f$ H_{\mu^-} \f$ terms to zero before calculating. + WaveVel2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveDynP2CDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + + + ! \f$ \mu^- \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^-} \f$ terms used in the IFFT to find the timeseries. + !> * \f$ \mu^- = n -m \f$ + DO mu_minus=1,InitInp%NStepWave2-1 + + ! The frequency we are dealing with + !> * \f$ \omega^- = \mu^- \Delta \omega \f$ + Omega_minus = mu_minus * InitInp%WaveDOmega + + IF ( Omega_minus >= InitInp%WvLowCOffD .AND. Omega_minus <= InitInp%WvHiCOffD ) THEN + + ! The inner \f$ m \f$ loop for calculating the \f$ H_{\mu^-} \f$ terms at each frequency. + DO m=1,InitInp%NStepWave2-mu_minus + ! Calculate the value of the n index from \f$ \mu^- = n - m \f$. Calculate corresponding wavenumbers and frequencies. + n = mu_minus + m + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + k_m = WaveNumber( Omega_m, InitInp%Gravity, InitInp%WtrDpth ) + k_nm = k_nm_minus( n, m, k_n, k_m ) + + + ! Calculate the terms \f$ n,m \f$ necessary for calculations + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath \left[\vec{k_n} - \vec{k_m} \right] \cdot \vec{x} \right) + !! = \exp \left( -\imath \left[ + !! \left( |\vec{k_n}| \cos \theta_n - |\vec{k_m}| cos \theta_m \right) ~ x + !! + \left( |\vec{k_n}| \sin \theta_n - |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + + + ! Get value for \f$ B^- \f$ for the n,m index pair + B_minus = TransFuncB_minus( n, m, k_n, k_m, WaveKinzi0Prime(I) ) + + + !> Calculate \f$ U^- \f$ terms for the velocity calculations (\f$B^-\f$ provided by waves2::transfuncb_minus) + ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor + !> * \f$ _x{U}_{nm}^- = B_{nm}^- \left(k_n \cos \theta_n - k_m \cos \theta_m \right) \f$ + Ux_nm_minus = B_minus * ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) + + !> * \f$ _y{U}_{nm}^- = B_{nm}^- \left(k_n \sin \theta_n - k_m \sin \theta_m \right) \f$ + Uy_nm_minus = B_minus * ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) + + !> * \f$ _z{U}_{nm}^- = \imath B_{nm}^- k_{nm} \tanh \left( k_{nm} ( h + z ) \right) \f$ + Uz_nm_minus = ImagNmbr * B_minus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) + + + !> Acceleration calculations + Accx_nm_minus = ImagNmbr * Ux_nm_minus * Omega_minus !> * \f$ _x\dot{U}_{nm}^- = \imath * _xU_{nm}^- * \omega_{\mu^-} \f$ + Accy_nm_minus = ImagNmbr * Uy_nm_minus * Omega_minus !> * \f$ _y\dot{U}_{nm}^- = \imath * _yU_{nm}^- * \omega_{\mu^-} \f$ + Accz_nm_minus = ImagNmbr * Uz_nm_minus * Omega_minus !> * \f$ _z\dot{U}_{nm}^- = \imath * _zU_{nm}^- * \omega_{\mu^-} \f$ + + + !> Dynamic pressure + !> * \f$ P_{nm}^- = \rho_\mathrm{w} B_{nm}^- \omega_{\mu^-} \f$ + DynP_nm_minus = InitInp%WtrDens * B_minus * Omega_minus + + + + !> ### Calculate the inner summation \f$ H^-(\omega_{\mu^-}) \f$ terms for the velocity, acceleration, and pressure. ### + + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + WaveElevC_m = WaveElevC0Norm(m) + + !> Velocity terms: + !! * \f$ H^-(\omega_{\mu^-}) = {\sum_{m=1}^{\frac{N}{2}-\mu^{-}}} A_n A^*_m U_{nm}^- + !! \exp\left(-\imath (\vec{k_n} - \vec{k_m})\cdot\vec{x}\right) \f$ + WaveVel2xCDiff(mu_minus) = WaveVel2xCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Ux_nm_minus * WaveElevxyPrime0 + WaveVel2yCDiff(mu_minus) = WaveVel2yCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Uy_nm_minus * WaveElevxyPrime0 + WaveVel2zCDiff(mu_minus) = WaveVel2zCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Uz_nm_minus * WaveElevxyPrime0 + + !> Acceleration terms: + !! * \f$ H^-(\omega_{\mu^-}) = {\sum_{m=1}^{\frac{N}{2}-\mu^{-}}} A_n A^*_m \dot{U}_{nm}^- + !! \exp\left(-\imath (\vec{k_n} - \vec{k_m})\cdot\vec{x}\right) \f$ + WaveAcc2xCDiff(mu_minus) = WaveAcc2xCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Accx_nm_minus * WaveElevxyPrime0 + WaveAcc2yCDiff(mu_minus) = WaveAcc2yCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Accy_nm_minus * WaveElevxyPrime0 + WaveAcc2zCDiff(mu_minus) = WaveAcc2zCDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * Accz_nm_minus * WaveElevxyPrime0 + + !> Pressure term: + !! * \f$ H^-(\omega_{\mu^-}) = {\sum_{m=1}^{\frac{N}{2}-\mu^{-}}} A_n A^*_m P_{nm}^- + !! \exp\left(-\imath (\vec{k_n} - \vec{k_m})\cdot\vec{x}\right) \f$ + WaveDynP2CDiff(mu_minus) = WaveDynP2CDiff(mu_minus) + WaveElevC_n * CONJG( WaveElevC_m ) * DynP_nm_minus * WaveElevxyPrime0 + + + ENDDO ! m loop + + + ENDIF ! Check to see if WvLowCOffD <= mu_minus <= WvHiCOffD + + ENDDO ! mu_minus loop (diff frequency) + + ! Divide by two for the single sided FFT given in the documentation. + WaveVel2xCDiff = WaveVel2xCDiff / 2.0_SiKi + WaveVel2yCDiff = WaveVel2yCDiff / 2.0_SiKi + WaveVel2zCDiff = WaveVel2zCDiff / 2.0_SiKi + WaveAcc2xCDiff = WaveAcc2xCDiff / 2.0_SiKi + WaveAcc2yCDiff = WaveAcc2yCDiff / 2.0_SiKi + WaveAcc2zCDiff = WaveAcc2zCDiff / 2.0_SiKi + WaveDynP2CDiff = WaveDynP2CDiff / 2.0_SiKi + + + + + !> ### Apply the inverse FFT to each of the components to get the time domain result ### + !> * \f$ V(t) = 2 \operatorname{IFFT}\left[H^-\right] \f$ + CALL ApplyFFT_cx( WaveVel2xDiff(:), WaveVel2xCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2yDiff(:), WaveVel2yCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2zDiff(:), WaveVel2zCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveAcc2xDiff(:), WaveAcc2xCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2yDiff(:), WaveAcc2yCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2zDiff(:), WaveAcc2zCDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveDynP2Diff(:), WaveDynP2CDiff(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on DynP2.',ErrStat,ErrMsg,'Waves2_Init') + + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Copy the results to the output + InitOut%WaveVel2D(:,WaveKinPrimeMap(I),1) = 2.0_SiKi * WaveVel2xDiff(:) ! x-component of velocity + InitOut%WaveVel2D(:,WaveKinPrimeMap(I),2) = 2.0_SiKi * WaveVel2yDiff(:) ! y-component of velocity + InitOut%WaveVel2D(:,WaveKinPrimeMap(I),3) = 2.0_SiKi * WaveVel2zDiff(:) ! z-component of velocity + + InitOut%WaveAcc2D(:,WaveKinPrimeMap(I),1) = 2.0_SiKi * WaveAcc2xDiff(:) ! x-component of acceleration + InitOut%WaveAcc2D(:,WaveKinPrimeMap(I),2) = 2.0_SiKi * WaveAcc2yDiff(:) ! y-component of acceleration + InitOut%WaveAcc2D(:,WaveKinPrimeMap(I),3) = 2.0_SiKi * WaveAcc2zDiff(:) ! z-component of acceleration + + InitOut%WaveDynP2D(:,WaveKinPrimeMap(I)) = 2.0_SiKi * WaveDynP2Diff(:) ! Dynamic pressure + + + ! Copy the first point to the last to make it easier. + InitOut%WaveVel2D(InitInp%NStepWave,WaveKinPrimeMap(I),1) = WaveVel2xDiff(0) + InitOut%WaveVel2D(InitInp%NStepWave,WaveKinPrimeMap(I),2) = WaveVel2yDiff(0) + InitOut%WaveVel2D(InitInp%NStepWave,WaveKinPrimeMap(I),3) = WaveVel2zDiff(0) + + InitOut%WaveAcc2D(InitInp%NStepWave,WaveKinPrimeMap(I),1) = WaveAcc2xDiff(0) + InitOut%WaveAcc2D(InitInp%NStepWave,WaveKinPrimeMap(I),2) = WaveAcc2yDiff(0) + InitOut%WaveAcc2D(InitInp%NStepWave,WaveKinPrimeMap(I),3) = WaveAcc2zDiff(0) + + InitOut%WaveDynP2D(InitInp%NStepWave,WaveKinPrimeMap(I)) = WaveDynP2Diff(0) + + + ENDDO ! I=1,NWaveKin0Prime loop end + + + ! Deallocate working arrays. + IF (ALLOCATED(WaveVel2xCDiff)) DEALLOCATE(WaveVel2xCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCDiff)) DEALLOCATE(WaveVel2yCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCDiff)) DEALLOCATE(WaveVel2zCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCDiff)) DEALLOCATE(WaveAcc2xCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCDiff)) DEALLOCATE(WaveAcc2yCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCDiff)) DEALLOCATE(WaveAcc2zCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CDiff)) DEALLOCATE(WaveDynP2CDiff, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xDiff)) DEALLOCATE(WaveVel2xDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yDiff)) DEALLOCATE(WaveVel2yDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zDiff)) DEALLOCATE(WaveVel2zDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xDiff)) DEALLOCATE(WaveAcc2xDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yDiff)) DEALLOCATE(WaveAcc2yDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zDiff)) DEALLOCATE(WaveAcc2zDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2Diff)) DEALLOCATE(WaveDynP2Diff, STAT=ErrStatTmp) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ENDIF ! p%WvDiffQTFF + + + + + + !-------------------------------------------------------------------------------- + !> # Sum Frequency # + !! + !! The sum frequency corrections to the velocity, acceleration, and pressure can + !! be written in generic form as: + !! + !! \f{eqnarray*}{ + !! V^{(2)+}(t) &=& \Re \left[ \sum_{n=1}^{\lfloor \frac{N}{4} \rfloor} K^+(\omega_n) + !! \exp(\imath 2 \omega_n t) \right] + !! + 2 \Re \left[ \sum_{\mu^+=2}^{\frac{N}{2}} H^+(\omega_{\mu^+}) + !! \exp(\imath \omega_{\mu^+} t) \right]\\ + !! &=& \operatorname{IFFT}\left[K(\omega_n)\right] + !! + 2\operatorname{IFFT}\left[H(\omega_{\mu^+})\right] \f} + !! + !! Notice that the first term only contains the \f$ 2 \omega_n \f$ terms; the others + !! are zero. + !-------------------------------------------------------------------------------- + + + IF(p%WvSumQTFF) THEN + + ! Tell our nice users what is about to happen that may take a while: + CALL WrScr ( ' Calculating second order sum frequency wave kinematics.' ) + + + !-------------------------------------------------------------------------------- + ! Setup arrays for the calculations + !-------------------------------------------------------------------------------- + + ! Frequency space arrays: Term 1 (n=m term) + + ALLOCATE ( WaveVel2xCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2yCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2yCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2yCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2yCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zCSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zCSumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2CSumT1 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2CSumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ! Term 2 (n/=m term) + ALLOCATE ( WaveVel2xCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2yCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2yCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2yCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2yCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zCSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zCSumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2CSumT2 (0:InitInp%NStepWave2), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2CSumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Time domain arrays: Term 1 (n=m term) + + ALLOCATE ( WaveVel2xSumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2ySumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2ySumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zSumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zSumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xSumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xSumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2ySumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2ySumT1.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zSumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zSumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2SumT1 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2SumT1.', ErrStat,ErrMsg,'Waves2_Init') + + ! Term 2 (n/=m term) + ALLOCATE ( WaveVel2xSumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2xSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2ySumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2ySumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveVel2zSumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveVel2zSumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveAcc2xSumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2xSumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2ySumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2ySumT2.', ErrStat,ErrMsg,'Waves2_Init') + ALLOCATE ( WaveAcc2zSumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveAcc2zSumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ALLOCATE ( WaveDynP2SumT2 (0:InitInp%NStepWave), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveDynP2SumT2.', ErrStat,ErrMsg,'Waves2_Init') + + ! Now check if all the allocations worked properly + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + + !-------------------------------------------------------------------------------- + !> ## Calculate the surface elevation corrections ## + !! + !! For each (x,y) coordinate that a wave elevation is requested at (both from the + !! (WaveElevxi,WaveElevyi) pairs, and the WaveElevXY pairs), a call is made to the + !! subroutine waves2::waveelevtimeseriesatxy_sum to calculate the full time series for + !! that point. The results are added to the wave elevation results from the diff + !! frequency calculations earlier in the code. + !-------------------------------------------------------------------------------- + + ! Step through the requested points + DO I=1,InitInp%NWaveElev + CALL WaveElevTimeSeriesAtXY_Sum(InitInp%WaveElevxi(I), InitInp%WaveElevyi(I), TmpTimeSeries, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to InitOut%WaveElev.',ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + ! Add to the series since the difference is already included + p%WaveElev2(:,I) = p%WaveElev2(:,I) + TmpTimeSeries(:) + ENDDO ! Wave elevation points requested + + + ! Calculate the wave elevation at all points requested in the array WaveElevXY + IF ( ALLOCATED(InitInp%WaveElevXY) ) THEN + DO I = 1,SIZE(InitInp%WaveElevXY, DIM=2) + ! This subroutine call applies the FFT at the correct location. + CALL WaveElevTimeSeriesAtXY_Sum( InitInp%WaveElevXY(1,I), InitInp%WaveElevXY(2,I), TmpTimeSeries, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + ! Add to the series since the difference is already included + InitOut%WaveElevSeries2(:,I) = InitOut%WaveElevSeries2(:,I) + TmpTimeSeries(:) + ENDDO + ENDIF + + + + !-------------------------------------------------------------------------------- + !> ## Calculate the second order velocity, acceleration, and pressure corrections for all joints below surface. ## + !-------------------------------------------------------------------------------- + ! NWaveKin0Prime loop start + DO I=1,NWaveKin0Prime + + + ! Reset the \f$ H_{\mu^+} \f$ terms to zero before calculating. + WaveVel2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveDynP2CSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) + + WaveVel2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveAcc2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveDynP2CSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + + + !--------------- + !> ### First term ### + !! This term is only the FFT over the diagonal elements where \f$ \omega_n = \omega_m \f$ + !! (note that the sum frequency is \f$ 2 \omega_n \f$). The index for the sum frequency is + !! therefore \f$ 2 n \f$. Since we are placing the calculated value for the \f$ A_n A_n + !! H^+ \f$ term in the \f$ 2 \omega \f$ location, we will only run through the first + !! half of the frequencies (the sum frequency will exceed the bounds of the frequencies + !! used in the FFT otherwise). + !! The IFFT will be calculated later with the IFFT of the second term. + !--------------- + + ! The limits look a little funny. But remember we are placing the value in the 2*J location, + ! so we cannot overun the end of the array. The floor function is just in case NStepWave2 is + ! an odd number + DO n=1,FLOOR( REAL(InitInp%NStepWave2-1) / 2.0_SiKi ) ! Only + + Omega_n = n * InitInp%WaveDOmega + + ! The frequency we are dealing with + !> * \f$ \omega^+ = \mu^+ \Delta \omega = 2 \omega_n \f$ + mu_plus = 2 * n + Omega_plus = 2.0_SiKi * Omega_n + + IF ( Omega_plus >= InitInp%WvLowCOffS .AND. Omega_plus <= InitInp%WvHiCOffS ) THEN + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + k_nm = k_nm_plus( n, n, k_n, k_n ) + + + ! Calculate the terms \f$ n,m \f$ necessary for calculations + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath 2 \vec{k_n} \cdot \vec{x} \right) + !! = \exp \left( -\imath 2 \left[ + !! |\vec{k_n}| \cos \theta_n ~ x + !! + |\vec{k_n}| \sin \theta_n ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + + + ! Get value for \f$ B+ \f$ for the n,m index pair + B_plus = TransFuncB_plus( n, n, k_n, k_n, WaveKinzi0Prime(I) ) + + + !> Calculate \f$ U^+ \f$ terms for the velocity calculations (\f$B^+\f$ provided by waves2::transfuncb_plus) + ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor + !> * \f$ _x{U}_{nn}^+ = B_{nn}^+ 2 k_n \cos \theta_n \f$ + Ux_nm_plus = B_plus * 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) + + !> * \f$ _y{U}_{nn}^+ = B_{nn}^+ 2 k_n \sin \theta_n \f$ + Uy_nm_plus = B_plus * 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + + !> * \f$ _z{U}_{nn}^+ = \imath B_{nn}^+ k_{nn} \tanh \left( k_{nn} ( h + z ) \right) \f$ + Uz_nm_plus = ImagNmbr * B_plus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) + + + !> Acceleration calculations + Accx_nm_plus = ImagNmbr * Ux_nm_plus * Omega_plus !> * \f$ _x\dot{U}_{nn}^+ = \imath * _xU_{nn}^+ * \omega_{\mu^+} \f$ + Accy_nm_plus = ImagNmbr * Uy_nm_plus * Omega_plus !> * \f$ _y\dot{U}_{nn}^+ = \imath * _yU_{nn}^+ * \omega_{\mu^+} \f$ + Accz_nm_plus = ImagNmbr * Uz_nm_plus * Omega_plus !> * \f$ _z\dot{U}_{nn}^+ = \imath * _zU_{nn}^+ * \omega_{\mu^+} \f$ + + + !> Dynamic pressure + !> * \f$ P_{nn}^+ = \rho_\mathrm{w} B_{nn}^+ \omega_{\mu^+} \f$ + DynP_nm_plus = InitInp%WtrDens * B_plus * Omega_plus + + + + !> ### Calculate the array of \f$ K^+(\omega_n) \f$ for the first term of the velocity, acceleration, and pressure. ### + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + + !> Velocity terms: + !! * \f$ K^+(\omega_n) = A_n A_n U_{nn}^+ \exp\left(-\imath 2 \vec{k_n} \cdot\vec{x}\right) \f$ + WaveVel2xCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Ux_nm_plus * WaveElevxyPrime0 + WaveVel2yCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Uy_nm_plus * WaveElevxyPrime0 + WaveVel2zCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Uz_nm_plus * WaveElevxyPrime0 + + !> Acceleration terms: + !! * \f$ K^+(\omega_n) = A_n A_n \dot{U}_{nn}^+ \exp\left(-\imath 2 \vec{k_n} \cdot\vec{x}\right) \f$ + WaveAcc2xCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Accx_nm_plus * WaveElevxyPrime0 + WaveAcc2yCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Accy_nm_plus * WaveElevxyPrime0 + WaveAcc2zCSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * Accz_nm_plus * WaveElevxyPrime0 + + !> Pressure term: + !! * \f$ K^+(\omega_n) = A_n A_n P_{nn}^+ \exp\left(-\imath 2 \vec{k_n} \cdot\vec{x}\right) \f$ + WaveDynP2CSumT1(mu_plus) = WaveElevC_n * WaveElevC_n * DynP_nm_plus * WaveElevxyPrime0 + + + ENDIF ! Check to see if WvLowCOffS <= mu_plus <= WvHiCOffS + + ENDDO ! n loop (sum frequency) + + ! NOTE: The IFFT of the these terms is performed below. + + + !--------------- + !> ### Second term ### + !! In this term, we are are now stepping through the sum frequencies. The inner + !! sum essentially covers all the off diagonal terms (omega_m /= omega_n). The limits + !! on the outer integral that is the FFT run through the full frequency range that + !! we are using. + !--------------- + + ! \f$ \mu^+ \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^+} \f$ terms used in the IFFT to find the timeseries. + !> * \f$ \mu^+ = n + m \f$ + DO mu_plus=2,InitInp%NStepWave2-1 + + ! The frequency we are dealing with + !> * \f$ \omega^+ = \mu^+ \Delta \omega \f$ + Omega_plus = mu_plus * InitInp%WaveDOmega + + IF ( Omega_plus >= InitInp%WvLowCOffS .AND. Omega_plus <= InitInp%WvHiCOffS ) THEN + ! The inner \f$ m \f$ loop for calculating the \f$ H_{\mu^+} \f$ terms at each frequency. + DO m=1,FLOOR( REAL(mu_plus - 1) / 2.0_SiKi ) + ! Calculate the value of the n index from \f$ \mu^+ = n + m \f$. Calculate corresponding wavenumbers and frequencies. + n = mu_plus - m + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + k_m = WaveNumber( Omega_m, InitInp%Gravity, InitInp%WtrDpth ) + k_nm = k_nm_plus( n, m, k_n, k_m ) + + + ! Calculate the terms \f$ n,m \f$ necessary for calculations + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath \left[\vec{k_n} + \vec{k_m} \right] \cdot \vec{x} \right) + !! = \exp \left( -\imath \left[ + !! \left( |\vec{k_n}| \cos \theta_n + |\vec{k_m}| cos \theta_m \right) ~ x + !! + \left( |\vec{k_n}| \sin \theta_n + |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + + + ! Get value for \f$ B+ \f$ for the n,m index pair + B_plus = TransFuncB_plus( n, m, k_n, k_m, WaveKinzi0Prime(I) ) + + + !> Calculate \f$ U^+ \f$ terms for the velocity calculations (\f$B^+\f$ provided by waves2::transfuncb_plus) + ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor + !> * \f$ _x{U}_{nm}^+ = B_{nm}^+ \left(k_n \cos \theta_n + k_m \cos \theta_m \right) \f$ + Ux_nm_plus = B_plus * ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) + + !> * \f$ _y{U}_{nm}^+ = B_{nm}^+ \left(k_n \sin \theta_n + k_m \sin \theta_m \right) \f$ + Uy_nm_plus = B_plus * ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) + + !> * \f$ _z{U}_{nm}^+ = \imath B_{nm}^+ k_{nm} \tanh \left( k_{nm} ( h + z ) \right) \f$ + Uz_nm_plus = ImagNmbr * B_plus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) + + + !> Acceleration calculations + Accx_nm_plus = ImagNmbr * Ux_nm_plus * Omega_plus !> * \f$ _x\dot{U}_{nm}^+ = \imath * _xU_{nm}^+ * \omega_{\mu^+} \f$ + Accy_nm_plus = ImagNmbr * Uy_nm_plus * Omega_plus !> * \f$ _y\dot{U}_{nm}^+ = \imath * _yU_{nm}^+ * \omega_{\mu^+} \f$ + Accz_nm_plus = ImagNmbr * Uz_nm_plus * Omega_plus !> * \f$ _z\dot{U}_{nm}^+ = \imath * _zU_{nm}^+ * \omega_{\mu^+} \f$ + + + !> Dynamic pressure + !> * \f$ P_{nm}^+ = \rho_\mathrm{w} B_{nm}^+ \omega_{\mu^+} \f$ + DynP_nm_plus = InitInp%WtrDens * B_plus * Omega_plus + + + + !> ### Calculate the inner summation \f$ H^+(\omega_{\mu^+}) \f$ terms for the velocity, acceleration, and pressure. ### + + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + WaveElevC_m = WaveElevC0Norm(m) + + + !> Velocity terms: + !! * \f$ H^+(\omega_{\mu^+}) = \sum_{m=1}^{\lfloor \frac{\mu^+-1}{2}\rfloor} A_n A_m U_{nm}^+ + !! \exp\left(-\imath (\vec{k_n} + \vec{k_m})\cdot\vec{x}\right) \f$ + WaveVel2xCSumT2(mu_plus) = WaveVel2xCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Ux_nm_plus * WaveElevxyPrime0 + WaveVel2yCSumT2(mu_plus) = WaveVel2yCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Uy_nm_plus * WaveElevxyPrime0 + WaveVel2zCSumT2(mu_plus) = WaveVel2zCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Uz_nm_plus * WaveElevxyPrime0 + + !> Acceleration terms: + !! * \f$ H^+(\omega_{\mu^+}) = \sum_{m=1}^{\lfloor \frac{\mu^+-1}{2}\rfloor} A_n A_m \dot{U}_{nm}^+ + !! \exp\left(-\imath (\vec{k_n} + \vec{k_m})\cdot\vec{x}\right) \f$ + WaveAcc2xCSumT2(mu_plus) = WaveAcc2xCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Accx_nm_plus * WaveElevxyPrime0 + WaveAcc2yCSumT2(mu_plus) = WaveAcc2yCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Accy_nm_plus * WaveElevxyPrime0 + WaveAcc2zCSumT2(mu_plus) = WaveAcc2zCSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * Accz_nm_plus * WaveElevxyPrime0 + + !> Pressure term: + !! * \f$ H^+(\omega_{\mu^+}) = \sum_{m=1}^{\lfloor \frac{\mu^+-1}{2}\rfloor} A_n A_m P_{nm}^+ + !! \exp\left(-\imath (\vec{k_n} + \vec{k_m})\cdot\vec{x}\right) \f$ + WaveDynP2CSumT2(mu_plus) = WaveDynP2CSumT2(mu_plus) + WaveElevC_n * WaveElevC_m * DynP_nm_plus * WaveElevxyPrime0 + + ENDDO ! m loop + + ENDIF ! Check to see if WvLowCOffS <= mu_plus <= WvHiCOffS + + ENDDO ! mu_plus loop (diff frequency) + + + ! Divide by two for the single sided FFT given in the documentation. + WaveVel2xCSumT1 = WaveVel2xCSumT1 / 2.0_SiKi + WaveVel2yCSumT1 = WaveVel2yCSumT1 / 2.0_SiKi + WaveVel2zCSumT1 = WaveVel2zCSumT1 / 2.0_SiKi + WaveAcc2xCSumT1 = WaveAcc2xCSumT1 / 2.0_SiKi + WaveAcc2yCSumT1 = WaveAcc2yCSumT1 / 2.0_SiKi + WaveAcc2zCSumT1 = WaveAcc2zCSumT1 / 2.0_SiKi + WaveDynP2CSumT1 = WaveDynP2CSumT1 / 2.0_SiKi + WaveVel2xCSumT2 = WaveVel2xCSumT2 / 2.0_SiKi + WaveVel2yCSumT2 = WaveVel2yCSumT2 / 2.0_SiKi + WaveVel2zCSumT2 = WaveVel2zCSumT2 / 2.0_SiKi + WaveAcc2xCSumT2 = WaveAcc2xCSumT2 / 2.0_SiKi + WaveAcc2yCSumT2 = WaveAcc2yCSumT2 / 2.0_SiKi + WaveAcc2zCSumT2 = WaveAcc2zCSumT2 / 2.0_SiKi + WaveDynP2CSumT2 = WaveDynP2CSumT2 / 2.0_SiKi + + + + + !> ### Apply the inverse FFT to the first and second terms of each of the components to get the time domain result ### + !> * \f$ V^{(2)+}(t) = \operatorname{IFFT}\left[K^+\right] + !! + 2\operatorname{IFFT}\left[H^+\right] \f$ + CALL ApplyFFT_cx( WaveVel2xSumT1(:), WaveVel2xCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2ySumT1(:), WaveVel2yCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2zSumT1(:), WaveVel2zCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveAcc2xSumT1(:), WaveAcc2xCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2ySumT1(:), WaveAcc2yCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2zSumT1(:), WaveAcc2zCSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveDynP2SumT1(:), WaveDynP2CSumT1(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on DynP2.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveVel2xSumT2(:), WaveVel2xCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2ySumT2(:), WaveVel2yCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveVel2zSumT2(:), WaveVel2zCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on V_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveAcc2xSumT2(:), WaveAcc2xCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_x.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2ySumT2(:), WaveAcc2yCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_y.',ErrStat,ErrMsg,'Waves2_Init') + CALL ApplyFFT_cx( WaveAcc2zSumT2(:), WaveAcc2zCSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on Acc_z.',ErrStat,ErrMsg,'Waves2_Init') + + CALL ApplyFFT_cx( WaveDynP2SumT2(:), WaveDynP2CSumT2(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT on DynP2.',ErrStat,ErrMsg,'Waves2_Init') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Add the results to the output + InitOut%WaveVel2S(:,WaveKinPrimeMap(I),1) = WaveVel2xSumT1(:) + 2.0_SiKi * WaveVel2xSumT2(:) ! x-component of velocity + InitOut%WaveVel2S(:,WaveKinPrimeMap(I),2) = WaveVel2ySumT1(:) + 2.0_SiKi * WaveVel2ySumT2(:) ! y-component of velocity + InitOut%WaveVel2S(:,WaveKinPrimeMap(I),3) = WaveVel2zSumT1(:) + 2.0_SiKi * WaveVel2zSumT2(:) ! z-component of velocity + + InitOut%WaveAcc2S(:,WaveKinPrimeMap(I),1) = WaveAcc2xSumT1(:) + 2.0_SiKi * WaveAcc2xSumT2(:) ! x-component of acceleration + InitOut%WaveAcc2S(:,WaveKinPrimeMap(I),2) = WaveAcc2ySumT1(:) + 2.0_SiKi * WaveAcc2ySumT2(:) ! y-component of acceleration + InitOut%WaveAcc2S(:,WaveKinPrimeMap(I),3) = WaveAcc2zSumT1(:) + 2.0_SiKi * WaveAcc2zSumT2(:) ! z-component of acceleration + + InitOut%WaveDynP2S(:,WaveKinPrimeMap(I)) = WaveDynP2SumT1(:) + 2.0_SiKi * WaveDynP2SumT2(:) ! Dynamic pressure + + + ! Copy the first point to the last to make it easier. + InitOut%WaveVel2S(InitInp%NStepWave,WaveKinPrimeMap(I),:) = InitOut%WaveVel2S(0,WaveKinPrimeMap(I),:) + InitOut%WaveAcc2S(InitInp%NStepWave,WaveKinPrimeMap(I),:) = InitOut%WaveAcc2S(0,WaveKinPrimeMap(I),:) + InitOut%WaveDynP2S(InitInp%NStepWave,WaveKinPrimeMap(I)) = InitOut%WaveDynP2S(0,WaveKinPrimeMap(I)) + + + ENDDO ! I=1,NWaveKin0Prime loop end + + + ! Deallocate working arrays. + IF (ALLOCATED(WaveVel2xCSumT1)) DEALLOCATE(WaveVel2xCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCSumT1)) DEALLOCATE(WaveVel2yCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCSumT1)) DEALLOCATE(WaveVel2zCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCSumT1)) DEALLOCATE(WaveAcc2xCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCSumT1)) DEALLOCATE(WaveAcc2yCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCSumT1)) DEALLOCATE(WaveAcc2zCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CSumT1)) DEALLOCATE(WaveDynP2CSumT1, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xSumT1)) DEALLOCATE(WaveVel2xSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2ySumT1)) DEALLOCATE(WaveVel2ySumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zSumT1)) DEALLOCATE(WaveVel2zSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xSumT1)) DEALLOCATE(WaveAcc2xSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2ySumT1)) DEALLOCATE(WaveAcc2ySumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zSumT1)) DEALLOCATE(WaveAcc2zSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2SumT1)) DEALLOCATE(WaveDynP2SumT1, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xCSumT2)) DEALLOCATE(WaveVel2xCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCSumT2)) DEALLOCATE(WaveVel2yCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCSumT2)) DEALLOCATE(WaveVel2zCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCSumT2)) DEALLOCATE(WaveAcc2xCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCSumT2)) DEALLOCATE(WaveAcc2yCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCSumT2)) DEALLOCATE(WaveAcc2zCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CSumT2)) DEALLOCATE(WaveDynP2CSumT2, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xSumT2)) DEALLOCATE(WaveVel2xSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2ySumT2)) DEALLOCATE(WaveVel2ySumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zSumT2)) DEALLOCATE(WaveVel2zSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xSumT2)) DEALLOCATE(WaveAcc2xSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2ySumT2)) DEALLOCATE(WaveAcc2ySumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zSumT2)) DEALLOCATE(WaveAcc2zSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2SumT2)) DEALLOCATE(WaveDynP2SumT2, STAT=ErrStatTmp) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + + ENDIF ! p%WvSumQTFF + + + + + + + CALL ExitFFT(FFT_Data, ErrStatTmp) + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'Waves2_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! If we calculated any second order wave elevation corrections, the array TmpTimeSeries was used. Deallocate it. + IF (ALLOCATED(TmpTimeSeries)) DEALLOCATE(TmpTimeSeries, STAT=ErrStatTmp) + IF (ALLOCATED(TmpTimeSeries2)) DEALLOCATE(TmpTimeSeries2, STAT=ErrStatTmp) + IF (ALLOCATED(TmpFreqSeries)) DEALLOCATE(TmpFreqSeries, STAT=ErrStatTmp) + IF (ALLOCATED(TmpFreqSeries2)) DEALLOCATE(TmpFreqSeries2, STAT=ErrStatTmp) + + + ! initialize dummy variables for the framework, so that compilers don't complain that the INTENT(OUT) variables have not been set: + u%DummyInput = 0.0_SiKi + x%DummyContState = 0.0_SiKi + xd%DummyDiscState = 0.0_SiKi + z%DummyConstrState = 0.0_SiKi + OtherState%DummyOtherState = 0_IntKi + + RETURN + + + CONTAINS + + + !> This subroutine calculates the second order difference frequency correction to the wave elevation. The transfer function + !! for the surface elevation is \f$ L^-_{nm} \f$, and is calculated within this subroutine rather than in a separate subroutine. + !! The calculations in this routine follow the same basic structure usind in ::Waves2_Init for the difference frequency + !! calculations. + !! + !! \f$ + !! \eta^{(2)-}(t) = 2 \Re \left[ \sum_{\mu^-=1}^{\frac{N}{2}-1} H^-(\omega_{\mu^-}) + !! \exp(\imath \omega_{\mu^-} t) \right] + !! = \operatorname{IFFT}\left[2 H^-\right] \f$ + !! + !! Notice that in the equations that follow, there is no term analagous to the mean + !! drift term in the WAMIT2 module. Rather, for \f$ \omega_{\mu^-} = 0 \f$, the + !! result is zero. So this term is not included. + !! + !! Also notice that the multiplier 2 is moved inside the IFFT. This was done purely to make the programming simpler. + SUBROUTINE WaveElevTimeSeriesAtXY_Diff(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStatLcl, ErrMsgLcl ) + + REAL(SiKi), INTENT(IN ) :: Xcoord + REAL(SiKi), INTENT(IN ) :: Ycoord + REAL(SiKi), INTENT( OUT) :: WaveElevSeriesAtXY(0:InitInp%NStepWave) + INTEGER(IntKi), INTENT( OUT) :: ErrStatLcl + INTEGER(IntKi) :: ErrStatLcl2 + CHARACTER(*), INTENT( OUT) :: ErrMsgLcl + + ! Local variables + INTEGER(IntKi) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi) :: m !< Index to the second frequency we are dealing with + REAL(SiKi) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi) :: L_minus !< Resulting \f$ L^{-}_{nm} \f$ value. Calculated in this routine. + REAL(SiKi) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: Omega_n !< First frequency of index n + REAL(SiKi) :: Omega_m !< Second frequency of index m + REAL(SiKi) :: D_minus !< Value of \f$ D^-_{nm} \f$ found by ::TransFuncD_minus + + ! Initializations + ErrMsgLcl = '' + ErrStatLcl = ErrID_None + + ! Note that TmpFreqSeries was allocated in the calling routine. Probably bad programming + ! practice, but I didn't want to have to allocate it at each point. + TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveElevSeriesAtXY = 0.0_SiKi + + ! \f$ \mu^- \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^-} \f$ terms used in the IFFT to find the timeseries. + !> * \f$ \mu^- = n -m \f$ + DO mu_minus=1,InitInp%NStepWave2-1 + + ! The frequency we are dealing with + !> * \f$ \omega^- = \mu^- \Delta \omega \f$ + Omega_minus = mu_minus * InitInp%WaveDOmega + + IF ( Omega_minus >= InitInp%WvLowCOffD .AND. Omega_minus <= InitInp%WvHiCOffD ) THEN + + ! The inner \f$ m \f$ loop for calculating the \f$ H_{\mu^-} \f$ terms at each frequency. + DO m=1,InitInp%NStepWave2-mu_minus + ! Calculate the value of the n index from \f$ \mu^- = n - m \f$. Calculate corresponding wavenumbers and frequencies. + n = mu_minus + m + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + k_m = WaveNumber( Omega_m, InitInp%Gravity, InitInp%WtrDpth ) + R_n = k_n * tanh( k_n * InitInp%WtrDpth ) + R_m = k_m * tanh( k_m * InitInp%WtrDpth ) + D_minus = TransFuncD_minus(n,m,k_n,k_m,R_n,R_m) + + !> Calculate the value of + !! \f$ L^-_{nm} = \frac{1}{4} \left[ + !! \frac{D^-_{nm} - |\vec{k}_n| |\vec{k}_m| \cos(\theta_n - \theta_m) - R_n R_m}{\sqrt{R_n R_m}} + !! + (R_n+R_m) \right] \f$ + !! + !! The value of \f$ D^-_{nm} \f$ is found from by the ::TransFuncD_minus routine. + + L_minus = (( D_minus - k_n * k_m * COS(D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m)) - R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi !4.0_SiKi + + + ! Calculate the terms \f$ n,m \f$ necessary for calculations + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath \left[\vec{k_n} - \vec{k_m} \right] \cdot \vec{x} \right) + !! = \exp \left( -\imath \left[ + !! \left( |\vec{k_n}| \cos \theta_n - |\vec{k_m}| cos \theta_m \right) ~ x + !! + \left( |\vec{k_n}| \sin \theta_n - |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * XCoord & + + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * YCoord )) + + + !> ### Calculate the inner summation \f$ H^-(\omega_{\mu^-}) \f$ terms for the velocity, acceleration, and pressure. ### + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + WaveElevC_m = WaveElevC0Norm(m) + + + !> Wave elevation term: + !! * \f$ 2 H^-(\omega_{\mu^-}) = {\sum_{m=1}^{\frac{N}{2}-\mu^{-}}} 2 A_n A^*_m L_{nm}^- + !! \exp\left(-\imath (\vec{k_n} - \vec{k_m})\cdot\vec{x}\right) \f$ + TmpFreqSeries(mu_minus) = TmpFreqSeries(mu_minus) + 2.0_SiKi * WaveElevC_n * CONJG( WaveElevC_m ) * L_minus * WaveElevxyPrime0 + + + ENDDO ! m loop + + ENDIF ! Check to see if WvLowCOffD <= mu_minus <= WvHiCOffD + + ENDDO ! mu_minus loop (diff frequency) + + + ! Divide by two for the single sided FFT given in the documentation. + TmpFreqSeries = TmpFreqSeries / 2.0_SiKi + + + !> ### Apply the inverse FFT to each of the components to get the time domain result ### + !> * \f$ \eta(t) = \operatorname{IFFT}\left[2 H^-\right] \f$ + CALL ApplyFFT_cx( WaveElevSeriesAtXY(:), TmpFreqSeries(:), FFT_Data, ErrStatLcl2 ) + CALL SetErrStat(ErrStatLcl2,'Error occured while applying the FFT on WaveElevSeriesAtXY.',ErrStatLcl,ErrMsgLcl,'WaveElevSeriesAtXY_Diff') + + ! Append first datapoint as the last as aid for repeated wave data + WaveElevSeriesAtXY(InitInp%NStepWave) = WaveElevSeriesAtXY(0) + + + END SUBROUTINE WaveElevTimeSeriesAtXY_Diff + + + + !> This subroutine calculates the second order sum frequency correction to the wave elevation. The transfer function + !! for the surface elevation is \f$ L^+_{nm} \f$, and is calculated within this subroutine rather than in a separate subroutine. + !! The calculations in this routine follow the same basic structure usind in ::Waves2_Init for the sum frequency + !! calculations. + !! + !! \f$ + !! \eta^{(2)+}(t) = \Re \left[ \sum_{n=1}^{\lfloor\frac{N}{4}\rfloor} K^+ \exp(\imath 2\omega_n t) \right] + !! + 2\Re \left[ \sum_{\mu^+=2}^{\frac{N}{2}} H^+(\omega_{\mu^+}) + !! \exp(\imath \omega_{\mu^+} t) \right] + !! = \operatorname{IFFT}\left[K^+\right] + 2\operatorname{IFFT}\left[H^+\right] \f$ + !! + SUBROUTINE WaveElevTimeSeriesAtXY_Sum(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStatLcl, ErrMsgLcl ) + + REAL(SiKi), INTENT(IN ) :: Xcoord + REAL(SiKi), INTENT(IN ) :: Ycoord + REAL(SiKi), INTENT( OUT) :: WaveElevSeriesAtXY(0:InitInp%NStepWave) + INTEGER(IntKi), INTENT( OUT) :: ErrStatLcl + INTEGER(IntKi) :: ErrStatLcl2 + CHARACTER(*), INTENT( OUT) :: ErrMsgLcl + + ! Local variables + INTEGER(IntKi) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi) :: m !< Index to the second frequency we are dealing with + INTEGER(IntKi) :: Ctr !< Generic counter + REAL(SiKi) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi) :: L_plus !< Resulting \f$ L^{+}_{nm} \f$ value. Calculated in this routine. + REAL(SiKi) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: Omega_n !< First frequency of index n + REAL(SiKi) :: Omega_m !< Second frequency of index m + REAL(SiKi) :: D_plus !< Value of \f$ D^+_{nm} \f$ found by ::TransFuncD_plus + + ! Initializations + ErrMsgLcl = '' + ErrStatLcl = ErrID_None + + ! Note that TmpFreqSeries was allocated in the calling routine. Probably bad programming + ! practice, but I didn't want to have to allocate it at each point. + TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi) ! used for first term + TmpFreqSeries2 = CMPLX(0.0_SiKi, 0.0_SiKi) ! used for second term + WaveElevSeriesAtXY = 0.0_SiKi + + + !> ## First term ## + ! First term results are stored in TmpFreqSeries. + + DO n=1,FLOOR( REAL(InitInp%NStepWave2-1) / 2.0_SiKi ) ! Only + + Omega_n = n * InitInp%WaveDOmega + + ! The frequency we are dealing with + !> * \f$ \omega^+ = \mu^+ \Delta \omega = 2 \omega_n \f$ + mu_plus = 2 * n + Omega_plus = 2.0_SiKi * Omega_n + + IF ( Omega_plus >= InitInp%WvLowCOffS .AND. Omega_plus <= InitInp%WvHiCOffS ) THEN + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + R_n = k_n * tanh( k_n * InitInp%WtrDpth ) + D_plus = TransFuncD_plus(n,n,k_n,k_n,R_n,R_n) + + !> Calculate the value of + !! \f$ L^+_{nn} = \frac{1}{4} \left[ + !! \frac{D^+_{nn} - |\vec{k}_n| |\vec{k}_n| \cos(\theta_n - \theta_n) + R_n R_n}{\sqrt{R_n R_n}} + !! + (R_n+R_n) \right] + !! = \frac{1}{4} \left[ \frac{ D^+_{nn} - |\vec{k}_n|^2 + R_n^2 }{ R_n } + 2 R_n \right] \f$ + !! + !! The value of \f$ D^+_{nn} \f$ is found from by the ::TransFuncD_plus routine. + L_plus = (( D_plus - k_n * k_n + R_n * R_n )/R_n + 2.0_SiKi * R_n ) / 4.0_SiKi + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath 2 \vec{k_n} \cdot \vec{x} \right) + !! = \exp \left( -\imath 2 \left[ + !! |\vec{k_n}| \cos \theta_n ~ x + !! + |\vec{k_n}| \sin \theta_n ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) * XCoord & + + 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) * YCoord )) + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + + !> ### Calculate the array of \f$ K^+(\omega_n) \f$ for the first term of the velocity, acceleration, and pressure. ### + !! * \f$ K^+(\omega_n) = A_n A_n L_{nn}^+ \exp\left(-\imath 2 \vec{k_n} \cdot\vec{x}\right) \f$ + TmpFreqSeries(mu_plus) = WaveElevC_n * WaveElevC_n * L_plus * WaveElevxyPrime0 + + ENDIF ! Check to see if WvLowCOffS <= mu_plus <= WvHiCOffS + + ENDDO ! n loop (diff frequency) + + ! NOTE: The IFFT of the these terms is performed below. + + + !--------------- + !> ## Second term ## + !! In this term, we are are now stepping through the sum frequencies. The inner + !! sum essentially covers all the off diagonal terms (omega_m /= omega_n). The limits + !! on the outer integral that is the FFT run through the full frequency range that + !! we are using. + !--------------- + ! The frequency information will be stored in TmpFreqSeries2 + + ! \f$ \mu^+ \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^+} \f$ terms used in the IFFT to find the timeseries. + !> * \f$ \mu^+ = n + m \f$ + DO mu_plus=2,InitInp%NStepWave2-1 + + ! The frequency we are dealing with + !> * \f$ \omega^+ = \mu^+ \Delta \omega \f$ + Omega_plus = mu_plus * InitInp%WaveDOmega + + IF ( Omega_plus >= InitInp%WvLowCOffS .AND. Omega_plus <= InitInp%WvHiCOffS ) THEN + + ! The inner \f$ m \f$ loop for calculating the \f$ H_{\mu^+} \f$ terms at each frequency. + DO m=1,FLOOR( REAL(mu_plus - 1) / 2.0_SiKi ) + ! Calculate the value of the n index from \f$ \mu^+ = n + m \f$. Calculate corresponding wavenumbers and frequencies. + n = mu_plus - m + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + k_n = WaveNumber( Omega_n, InitInp%Gravity, InitInp%WtrDpth ) + k_m = WaveNumber( Omega_m, InitInp%Gravity, InitInp%WtrDpth ) + R_n = k_n * tanh( k_n * InitInp%WtrDpth ) + R_m = k_m * tanh( k_m * InitInp%WtrDpth ) + D_plus = TransFuncD_plus(n,m,k_n,k_m,R_n,R_m) + + !> Calculate the value of + !! \f$ L^+_{nm} = \frac{1}{4} \left[ + !! \frac{D^+_{nm} - |\vec{k}_n| |\vec{k}_m| \cos(\theta_n - \theta_m) + R_n R_m}{\sqrt{R_n R_m}} + !! + (R_n+R_m) \right] \f$ + !! + !! The value of \f$ D^-_{nm} \f$ is found from by the ::TransFuncD_plus routine. + L_plus = (( D_plus - k_n * k_m * COS(D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m)) + R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi + + !> Calculate the dot product of the wavenumbers with the (x,y) location + !! This is given by: + !! + !! * \f$ \exp\left(-\imath \left[\vec{k_n} + \vec{k_m} \right] \cdot \vec{x} \right) + !! = \exp \left( -\imath \left[ + !! \left( |\vec{k_n}| \cos \theta_n + |\vec{k_m}| cos \theta_m \right) ~ x + !! + \left( |\vec{k_n}| \sin \theta_n + |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ + + WaveElevxyPrime0 = exp( - ImagNmbr & + * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * XCoord & + + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * YCoord )) + + + + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase + ! shift associated with the (x,y) location is accounted for by the WaveElevxyPrime0 variable. + WaveElevC_n = WaveElevC0Norm(n) + WaveElevC_m = WaveElevC0Norm(m) + + !> ### Calculate the inner summation \f$ H^+(\omega_{\mu^+}) \f$ term. ### + !! * \f$ H^+(\omega_{\mu^+}) = \sum_{m=1}^{\lfloor \frac{\mu^+-1}{2}\rfloor} A_n A_m L^+_{nm} + !! \exp\left(-\imath (\vec{k_n} + \vec{k_m})\cdot\vec{x}\right) \f$ + TmpFreqSeries2(mu_plus) = TmpFreqSeries2(mu_plus) + WaveElevC_n * WaveElevC_m * L_plus * WaveElevxyPrime0 + + ENDDO ! m loop + + ENDIF ! Check to see if WvLowCOffS <= mu_plus <= WvHiCOffS + + ENDDO ! mu_plus loop (diff frequency) + + + ! Divide by two for the single sided FFT given in the documentation. + TmpFreqSeries = TmpFreqSeries / 2.0_SiKi + TmpFreqSeries2 = TmpFreqSeries2 / 2.0_SiKi + + !> ## Apply the inverse FFT to the first and second terms to get the time domain result ## + !> * \f$ \eta^{(2)+}(t) = \operatorname{IFFT}\left[K^+\right] + !! + 2\operatorname{IFFT}\left[H^+\right] \f$ + CALL ApplyFFT_cx( WaveElevSeriesAtXY(:), TmpFreqSeries(:), FFT_Data, ErrStatLcl2 ) + CALL SetErrStat(ErrStatLcl2,'Error occured while applying the FFT on WaveElevSeriesAtXY.',ErrStatLcl,ErrMsgLcl,'WaveElevSeriesAtXY_Sum') + CALL ApplyFFT_cx( TmpTimeSeries2(:), TmpFreqSeries2(:), FFT_Data, ErrStatLcl2 ) + CALL SetErrStat(ErrStatLcl2,'Error occured while applying the FFT on WaveElevSeriesAtXY.',ErrStatLcl,ErrMsgLcl,'WaveElevSeriesAtXY_Sum') + + ! Add the two terms together + DO Ctr=0,InitInp%NStepWave + WaveElevSeriesAtXY(Ctr) = WaveElevSeriesAtXY(Ctr) + 2.0_SiKi * TmpTimeSeries2(Ctr) + ENDDO + + ! Append first datapoint as the last as aid for repeated wave data + WaveElevSeriesAtXY(InitInp%NStepWave) = WaveElevSeriesAtXY(0) + + + END SUBROUTINE WaveElevTimeSeriesAtXY_Sum + + + + + + + !> This function calculates the term \f$ B^-_{nm} \f$ used in calculating the veloicty, acceleration, and dynamic pressure terms. + !! The equation is given by: + !! + !! \f$ B_{nm}^-(z, \omega_n, \omega_m, \theta_n, \theta_m) =\frac{g^2}{\omega_n \omega_m} + !! \cdot \frac{1}{4} \frac{\cosh\left[k_{nm}^-(h+z)\right]}{\cosh\left[k_{nm}^-(h)\right]} + !! \frac{D_{nm}^-}{\omega_n - \omega_m} \f$ + !! + FUNCTION TransFuncB_minus(n,m,k_n,k_m,z) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: z !< The depth of the point of interest from the surface of the water. + REAL(SiKi) :: TransFuncB_minus !< Resulting \f$ B^{-}_{nm} \f$ value. + + ! Local variables + REAL(SiKi) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: k_nm !< Value of \f$ k_{nm}^{-} \f$ found by ::k_nm_minus + REAL(SiKi) :: Omega_n !< First frequency of index n + REAL(SiKi) :: Omega_m !< Second frequency of index m + REAL(SiKi) :: D_minus !< Value of \f$ D^-_{nm} \f$ found by ::TransFuncD_minus + + ! Check that we are not trying to compute a transfer function with any zero frequencies in it. Those are by definition zero. + IF ( n==0 .or. m==0 ) THEN + + TransFuncB_minus = 0.0_SiKi + + ELSEIF ( n==m ) THEN + + ! If the frequencies are the same, we get a zero in the denominator. These should be defined as zero. + TransFuncB_minus = 0.0_SiKi + + ELSE + + ! Frequencies + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + + ! Wavenumbers + k_nm = k_nm_minus( n,m,k_n,k_m ) + + ! Effect of depth scaling + R_n = k_n * tanh( k_n * InitInp%WtrDpth ) + R_m = k_m * tanh( k_m * InitInp%WtrDpth ) + + ! Transfer function D_minus + D_minus = TransFuncD_minus(n,m,k_n,k_m,R_n,R_m) + + + ! Calculation of B_minus + TransFuncB_minus = InitInp%Gravity*InitInp%Gravity / ( 4.0_SiKi * Omega_n * Omega_m ) & + * COSHNumOvrCOSHDen(k_nm, REAL(InitInp%WtrDpth,SiKi), z) * D_minus / ( Omega_n - Omega_m ) + + + ENDIF + + + + END FUNCTION TransFuncB_minus + + + + + !> This function calculates the term \f$ B^+_{nm} \f$ used in calculating the velocity, acceleration, and dynamic pressure terms. + !! The equation is given by: + !! + !! \f$ B_{nm}^+(z, \omega_n, \omega_m, \theta_n, \theta_m) =\frac{g^2}{\omega_n \omega_m} + !! \cdot \frac{1}{4} \frac{\cosh\left[k_{nm}^-(h+z)\right]}{\cosh\left[k_{nm}^-(h)\right]} + !! \frac{D_{nm}^+}{\omega_n + \omega_m} \f$ + !! + FUNCTION TransFuncB_plus(n,m,k_n,k_m,z) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: z !< The depth of the point of interest from the surface of the water. + REAL(SiKi) :: TransFuncB_plus !< Resulting \f$ B^{-}_{nm} \f$ value. + + ! Local variables + REAL(SiKi) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: k_nm !< Value of \f$ k_{nm}^{+} \f$ found by ::k_nm_plus + REAL(SiKi) :: Omega_n !< First frequency of index n + REAL(SiKi) :: Omega_m !< Second frequency of index m + REAL(SiKi) :: D_plus !< Value of \f$ D^+_{nm} \f$ found by ::TransFuncD_plus + + ! Check that we are not trying to compute a transfer function with any zero frequencies in it. Those are by definition zero. + IF ( n==0 .or. m==0 ) THEN + + TransFuncB_plus = 0.0_SiKi + + + ELSE + + ! Frequencies + Omega_n = n * InitInp%WaveDOmega + Omega_m = m * InitInp%WaveDOmega + + ! Wavenumbers + k_nm = k_nm_plus( n,m,k_n,k_m ) + + ! Effect of depth scaling + R_n = k_n * tanh( k_n * InitInp%WtrDpth ) + R_m = k_m * tanh( k_m * InitInp%WtrDpth ) + + ! Transfer function D_plus + D_plus = TransFuncD_plus(n,m,k_n,k_m,R_n,R_m) + + ! Calculation of B_plus + TransFuncB_plus = InitInp%Gravity*InitInp%Gravity / ( 4.0_SiKi * Omega_n * Omega_m ) & + * COSHNumOvrCOSHDen(k_nm, REAL(InitInp%WtrDpth,SiKi), z) * D_plus / ( Omega_n + Omega_m ) + + + ENDIF + + + + END FUNCTION TransFuncB_plus + + + + + + + !> This function was taken directly from the Waves.f90 file and should be identical to it. + FUNCTION COSHNumOvrCOSHDen ( k, h, z ) + + ! This FUNCTION computes the shallow water hyperbolic numerator + ! over denominator term in the wave kinematics expressions: + ! + ! COSH( k*( z + h ) )/COSH( k*h ) + ! + ! given the wave number, k, water depth, h, and elevation z, as + ! inputs. + + IMPLICIT NONE + + ! Passed Variables: + REAL(SiKi) :: COSHNumOvrCOSHDen ! This function = COSH( k*( z + h ) )/COSH( k*h ) (-) + REAL(SiKi), INTENT(IN ) :: h ! Water depth ( h > 0 ) (meters) + REAL(SiKi), INTENT(IN ) :: k ! Wave number ( k >= 0 ) (1/m) + REAL(SiKi), INTENT(IN ) :: z ! Elevation (-h <= z <= 0 ) (meters) + + + ! Compute the hyperbolic numerator over denominator: + + IF ( k*h > 89.4_SiKi ) THEN ! When .TRUE., the shallow water formulation will trigger a floating point overflow error; + ! however, COSH( k*( z + h ) )/COSH( k*h ) = EXP( k*z ) + EXP( -k*( z + 2*h ) ) for large k*h. + ! This equals the deep water formulation, EXP( k*z ), except near z = -h, because + ! h > 14.23*wavelength (since k = 2*Pi/wavelength) in this case. + + COSHNumOvrCOSHDen = EXP( k*z ) + EXP( -k*( z + 2.0_SiKi*h ) ) + + ELSE ! 0 < k*h <= 89.4; use the shallow water formulation. + + COSHNumOvrCOSHDen = COSH( k*( z + h ) )/COSH( k*h ) + + END IF + + RETURN + END FUNCTION COSHNumOvrCOSHDen + + + !> This function calculates the term \f$ D^-_{nm} \f$ used in finding the transfer functions. + !! The equation is given by: + !! + !! \f$ {D}_{nm}^{-} = + !! \frac { \left(\sqrt{R_n} - \sqrt{R_m}\right) \left[ \sqrt{R_m} \left( k_n^2 - R_n^2 \right) - \sqrt{R_n} \left( k_m^{2} - R_m^2 \right) \right] + !! ~+~ 2 \left(\sqrt{R_n} - \sqrt{R_m}\right)^2 + !! \left[ \left|\vec{k_n}\right| \left|\vec{k_m}\right| \cos \left( \theta_n-\theta_m \right) + R_n R_m \right] } + !! { \left(\sqrt{R_n} - \sqrt{R_m}\right)^2 - k_{nm}^{-} \tanh \left( k_{nm}^{-} h \right) } \f$ + !! + !! where \f$ k_{nm}^{-} \f$ is handled by the function ::k_nm_minus and \f$R_n\f$ is given by + !! \f$ R_n = \left| \overrightarrow{k}_n \right| \tanh\left(\left| \overrightarrow{k}_n \right| h \right) \f$ + !! where \f$ h \f$ is the depth from MSL (or the still water line). + !! + !! To calculate this, we simplify some of the common pieces: + !! + !! \f$ {D}_{nm}^{-} = \frac { R_{nm} \left[ \sqrt{R_m} \left( k_n^2 - R_n^2 \right) - \sqrt{R_n} \left( k_m^2 -R_m^2 \right) \right] + !! ~+~ 2 R_{nm}^2 \left[ \left|\vec{k_n}\right| \left|\vec{k_m}\right| \cos \left( \theta_n-\theta_m \right) + R_n R_m \right] } + !! { R_{nm}^2 - k_{nm}^{-} \tanh \left( k_{nm}^- h \right) } \f$ + !! + !! where \f$ R_{nm} \equiv \sqrt{R_n} - \sqrt{R_m} \f$. + !! + !! The denominator goes to zero when \f$ n = m \f$, as does the numerator. So, using L'Hopital's rule to find the limit, it may be + !! possible to prove that \f$ \stackrel{\lim}{n \to m} D_{nm}^{-} = 0 \f$. It will take more than one derivative + !! to check this, so due to time, this has not been verified. For now we we simply assume this to be true and proceed to set + !! _TransFuncD_minus_ to zero for all \f$ n = m \f$ cases. _This should not be done!_ Plotting this cross sections of this function + !! shows that when \f$ n = m \f$, the result should converge to something non-zero, but close to zero. + !! + !! @note update this function when the limit has been derived. + !! + FUNCTION TransFuncD_minus(n,m,k_n,k_m,R_n,R_m) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi), INTENT(IN ) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: TransFuncD_minus !< Resulting \f$ D^{-}_{nm} \f$ value. + + ! Local variables + REAL(SiKi) :: k_nm !< Value of \f$ k_{nm}^{-} \f$ + REAL(SiKi) :: SqrtRnMinusRm !< Value of \f$ \sqrt{R_n} - \sqrt{R_m} \f$ + + REAL(SiKi) :: Den !< Denominator + REAL(SiKi) :: Num1 !< Numerator first term + REAL(SiKi) :: Num2 !< Numerator second term + + + ! If n == m, D^- is set to zero. It should be set to the limit as n -> m. + IF ( n==m ) THEN + TransFuncD_minus = 0.0_SiKi + ELSE + + k_nm = k_nm_minus(n,m,k_n,k_m) + + ! Calculate R_nm that appears in multiple places + SqrtRnMinusRm = SQRT(R_n) - SQRT(R_m) + + ! Calculate the two pieces of the numerator + Num1 = SqrtRnMinusRm * ( SQRT(R_m) * ( k_n*k_n - R_n*R_n ) - SQRT(R_n) * ( k_m*k_m - R_m*R_m ) ) + + Num2 = 2*SqrtRnMinusRm*SqrtRnMinusRm*( k_n * k_m * COS( D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m) ) + R_n*R_m ) + + ! Calculate the denominator + Den = SqrtRnMinusRm*SqrtRnMinusRm - k_nm * tanh( k_nm * InitInp%WtrDpth ) + + TransFuncD_minus = (Num1+Num2) / Den + + ENDIF + + RETURN + END FUNCTION TransFuncD_minus + + + + !> This function calculates the term \f$ D^+_{nm} \f$ used in finding the transfer functions. + !! The equation is given by: + !! + !! \f$ {D}_{nm}^{+} = + !! \frac { \left(\sqrt{R_n} + \sqrt{R_m}\right) \left[ \sqrt{R_m} \left( k_n^2 - R_n^2 \right) + \sqrt{R_n} \left( k_m^{2} - R_m^2 \right) \right] + !! ~+~ 2 \left(\sqrt{R_n} + \sqrt{R_m}\right)^2 + !! \left[ \left|\vec{k_n}\right| \left|\vec{k_m}\right| \cos \left( \theta_n-\theta_m \right) - R_n R_m \right] } + !! { \left(\sqrt{R_n} + \sqrt{R_m}\right)^2 - k_{nm}^{+} \tanh \left( k_{nm}^{+} h \right) } \f$ + !! + !! where \f$ k_{nm}^{+} \f$ is handled by the function ::k_nm_plus and \f$R_n\f$ is given by + !! \f$ R_n = \left| \overrightarrow{k}_n \right| \tanh\left(\left| \overrightarrow{k}_n \right| h \right) \f$ + !! where \f$ h \f$ is the depth from MSL (or the still water line). + !! + !! To calculate this, we simplify some of the common pieces: + !! + !! \f$ {D}_{nm}^{+} = \frac { R_{nm} \left[ \sqrt{R_m} \left( k_n^2 - R_n^2 \right) - \sqrt{R_n} \left( k_m^2 - R_m^2 \right) \right] + !! ~+~ 2 R_{nm}^2 \left[ \left|\vec{k_n}\right| \left|\vec{k_m}\right| \cos \left( \theta_n-\theta_m \right) + R_n R_m \right] } + !! { R_{nm}^2 - k_{nm}^{+} \tanh \left( k_{nm}^+ h \right) } \f$ + !! + !! where \f$ R_{nm} \equiv \sqrt{R_n} - \sqrt{R_m} \f$. + !! + FUNCTION TransFuncD_plus(n,m,k_n,k_m,R_n,R_m) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for Omega_n -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for Omega_m -- note no direction associated with this + REAL(SiKi), INTENT(IN ) :: R_n !< Effect scaling relationship of depth and wavenumber + REAL(SiKi), INTENT(IN ) :: R_m !< Effect scaling relationship of depth and wavenumber + REAL(SiKi) :: TransFuncD_plus !< Resulting \f$ D^{+}_{nm} \f$ value. + + ! Local variables + REAL(SiKi) :: k_nm !< Value of \f$ k_{nm}^{+} \f$ + REAL(SiKi) :: SqrtRnPlusRm !< Value of \f$ \sqrt{R_n} + \sqrt{R_m} \f$ + + REAL(SiKi) :: Den !< Denominator + REAL(SiKi) :: Num1 !< Numerator first term + REAL(SiKi) :: Num2 !< Numerator second term + + + + k_nm = k_nm_plus(n,m,k_n,k_m) + + ! Calculate R_nm that appears in multiple places + SqrtRnPlusRm = SQRT(R_n) + SQRT(R_m) + + ! Calculate the two pieces of the numerator + Num1 = SqrtRnPlusRm * ( SQRT(R_m) * ( k_n*k_n - R_n*R_n ) + SQRT(R_n) * ( k_m*k_m - R_m*R_m ) ) + + Num2 = 2*SqrtRnPlusRm*SqrtRnPlusRm*( k_n * k_m * COS( D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m) ) - R_n*R_m ) + + ! Calculate the denominator + Den = SqrtRnPlusRm*SqrtRnPlusRm - k_nm * tanh( k_nm * InitInp%WtrDpth ) + + TransFuncD_plus = (Num1+Num2) / Den + + + RETURN + END FUNCTION TransFuncD_plus + + + + + + + !> This function calculates the amplitude of the combined WaveNumber, \f$ k^-_{nm} \f$ of the wave numbers + !! for \f$ k_n \f$ and \f$ k_m \f$ for the difference frequency. The equation is given by + !! \f$ {k}_{nm}^{-} = \sqrt{{k_n}^2 +{k_m}^2 - 2{k_n}{k_m}\cos(\theta_n-\theta_m)} \f$ + !! + !! @note \f$ \theta_n \f$ is given by _InitInp\%WaveDirArr(n)_ + FUNCTION k_nm_minus(n,m,k_n,k_m) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for \f$\omega_n\f$ -- note the direction is found in _InitInp\%WaveDirArr(n)_ + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for \f$\omega_m\f$ -- note the direction is found in _InitInp\%WaveDirArr(m)_ + REAL(SiKi) :: k_nm_minus + + IF (n == m ) THEN + k_nm_minus = 0.0_SiKi ! This is just to eliminate any numerical error + ELSE + !bjj: added abs() because we were getting very small negative numbers here (which should be 0). + k_nm_minus = sqrt( abs( k_n * k_n + k_m * k_m - 2 * k_n * k_m * cos( D2R*InitInp%WaveDirArr(n) - D2R*InitINp%WaveDirArr(m) ) ) ) + ENDIF + + END FUNCTION k_nm_minus + + + + + !> This function calculates the amplitude of the combined WaveNumber, \f$ k^+_{nm} \f$ of the wave numbers + !! for \f$ k_n \f$ and \f$ k_m \f$ for the difference frequency. The equation is given by + !! \f$ {k}_{nm}^{+} = \sqrt{{k_n}^2 +{k_m}^2 + 2{k_n}{k_m}\cos(\theta_n-\theta_m)} \f$ + !! + !! @note \f$ \theta_n \f$ is given by _InitInp\%WaveDirArr(n)_ + FUNCTION k_nm_plus(n,m,k_n,k_m) + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: n !< Index to the first frequency we are dealing with + INTEGER(IntKi), INTENT(IN ) :: m !< Index to the second frequency we are dealing with + REAL(SiKi), INTENT(IN ) :: k_n !< WaveNumber for \f$\omega_n\f$ -- note the direction is found in _InitInp\%WaveDirArr(n)_ + REAL(SiKi), INTENT(IN ) :: k_m !< WaveNumber for \f$\omega_m\f$ -- note the direction is found in _InitInp\%WaveDirArr(m)_ + REAL(SiKi) :: k_nm_plus + + IF (n == m ) THEN + k_nm_plus = 2.0_SiKi * k_n ! This is just to eliminate any numerical error. + ELSE + k_nm_plus = sqrt( k_n * k_n + k_m * k_m + 2 * k_n * k_m * cos( D2R*InitInp%WaveDirArr(n) - D2R*InitINp%WaveDirArr(m) ) ) + ENDIF + + END FUNCTION k_nm_plus + + + + + + + + + + SUBROUTINE CleanUp() + + CALL ExitFFT(FFT_Data, ErrStatTmp) + + IF (ALLOCATED(TmpTimeSeries)) DEALLOCATE(TmpTimeSeries, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xCDiff)) DEALLOCATE(WaveVel2xCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCDiff)) DEALLOCATE(WaveVel2yCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCDiff)) DEALLOCATE(WaveVel2zCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCDiff)) DEALLOCATE(WaveAcc2xCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCDiff)) DEALLOCATE(WaveAcc2yCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCDiff)) DEALLOCATE(WaveAcc2zCDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2xDiff)) DEALLOCATE(WaveVel2xDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yDiff)) DEALLOCATE(WaveVel2yDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zDiff)) DEALLOCATE(WaveVel2zDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xDiff)) DEALLOCATE(WaveAcc2xDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yDiff)) DEALLOCATE(WaveAcc2yDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zDiff)) DEALLOCATE(WaveAcc2zDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CDiff)) DEALLOCATE(WaveDynP2CDiff, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2Diff)) DEALLOCATE(WaveDynP2Diff, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xCSumT1)) DEALLOCATE(WaveVel2xCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCSumT1)) DEALLOCATE(WaveVel2yCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCSumT1)) DEALLOCATE(WaveVel2zCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCSumT1)) DEALLOCATE(WaveAcc2xCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCSumT1)) DEALLOCATE(WaveAcc2yCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCSumT1)) DEALLOCATE(WaveAcc2zCSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2xSumT1)) DEALLOCATE(WaveVel2xSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2ySumT1)) DEALLOCATE(WaveVel2ySumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zSumT1)) DEALLOCATE(WaveVel2zSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xSumT1)) DEALLOCATE(WaveAcc2xSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2ySumT1)) DEALLOCATE(WaveAcc2ySumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zSumT1)) DEALLOCATE(WaveAcc2zSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CSumT1)) DEALLOCATE(WaveDynP2CSumT1, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2SumT1)) DEALLOCATE(WaveDynP2SumT1, STAT=ErrStatTmp) + + IF (ALLOCATED(WaveVel2xCSumT2)) DEALLOCATE(WaveVel2xCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2yCSumT2)) DEALLOCATE(WaveVel2yCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zCSumT2)) DEALLOCATE(WaveVel2zCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xCSumT2)) DEALLOCATE(WaveAcc2xCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2yCSumT2)) DEALLOCATE(WaveAcc2yCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zCSumT2)) DEALLOCATE(WaveAcc2zCSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2xSumT2)) DEALLOCATE(WaveVel2xSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2ySumT2)) DEALLOCATE(WaveVel2ySumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveVel2zSumT2)) DEALLOCATE(WaveVel2zSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2xSumT2)) DEALLOCATE(WaveAcc2xSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2ySumT2)) DEALLOCATE(WaveAcc2ySumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveAcc2zSumT2)) DEALLOCATE(WaveAcc2zSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2CSumT2)) DEALLOCATE(WaveDynP2CSumT2, STAT=ErrStatTmp) + IF (ALLOCATED(WaveDynP2SumT2)) DEALLOCATE(WaveDynP2SumT2, STAT=ErrStatTmp) + + END SUBROUTINE CleanUp + + + + +END SUBROUTINE Waves2_Init + + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. The purpose of this routine is to destroy any data that is leftover. If +!! we don't do this, we may leave memory tied up after the simulation ends. +!! To destroy the data, we call several routines that are generated by the FAST registry, so any issues with the destroy routines +!! should be addressed by the registry.exe which generates the Waves2_Types.f90 file. +!! +SUBROUTINE Waves2_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(Waves2_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Waves2_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Waves2_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Waves2_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Waves2_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(Waves2_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Waves2_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 + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Place any last minute operations or calculations here. For Waves2, most calculations all performed + !! during the initialization, so there are no final calculations that need to be performed. + + + ! Close files here. The Waves2 module does not open any files, so there should be nothing to close. + + + !> Destroy the input data: + + CALL Waves2_DestroyInput( u, ErrStat, ErrMsg ) + + + !> Destroy the parameter data: + + CALL Waves2_DestroyParam( p, ErrStat, ErrMsg ) + + + !> Destroy the state data: + + CALL Waves2_DestroyContState( x, ErrStat, ErrMsg ) + CALL Waves2_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL Waves2_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL Waves2_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + !> Destroy the output data: + + CALL Waves2_DestroyOutput( y, ErrStat, ErrMsg ) + + +END SUBROUTINE Waves2_End + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!> Continuous, constraint, discrete, and other states are updated to values at t + Interval. +SUBROUTINE Waves2_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(Waves2_InputType), INTENT(IN ) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(Waves2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !!Output: Continuous states at t + Interval + TYPE(Waves2_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !!Output: Discrete states at t + Interval + TYPE(Waves2_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !!Output: Constraint states at t + Interval + TYPE(Waves2_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !!Output: Other states at t + Interval + TYPE(Waves2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "Warning: No States to update in Waves2 module. *Waves2_UpdateStates was called*" + + +END SUBROUTINE Waves2_UpdateStates + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! The Waves2 module second order wave kinematic corrections are processed at initialization and passed to other modules (such as +!! Morrison) for processing. As a result, there is nothing that needs to be calculated by the CalcOutput routine other than the +!! WriteOutput values at each timestep. +SUBROUTINE Waves2_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Waves2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Waves2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Waves2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Waves2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Waves2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Waves2_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh + !! connectivity information does not have to be recalculated) + TYPE(Waves2_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 + + + + ! Local Variables: + INTEGER(IntKi) :: I ! Generic index + REAL(SiKi) :: WaveElev2Temp(p%NWaveElev) + REAL(ReKi) :: AllOuts(MaxWaves2Outputs) + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + + + ! Abort if the Waves2 module did not calculate anything + + IF ( .NOT. ALLOCATED ( p%WaveElev2 ) ) RETURN + IF ( p%NumOuts < 1 ) RETURN + + + DO I=1,p%NWaveElev + WaveElev2Temp(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev2(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + ENDDO + + ! Map the calculated results into the AllOuts Array + CALL Wvs2Out_MapOutputs(Time, y, p%NWaveElev, WaveElev2Temp, AllOuts, ErrStat, ErrMsg) + + + + ! Put the output data in the OutData array + DO I = 1,p%NumOuts + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + END DO + + + +END SUBROUTINE Waves2_CalcOutput + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this routine calculates the derivative of the continuous states. +!! As this routine is not necessary in the Waves2 module, it simply issues a warning and returns. +!! @note A few values will be set so that compilers are happy, but nothing of value is done. +SUBROUTINE Waves2_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Waves2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Waves2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Waves2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Waves2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Waves2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Waves2_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(Waves2_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 + + ErrStat = ErrID_None + ErrMsg = "Warning: No States to take derivative of in Waves2 module. *Waves2::CalcContStateDeriv was called. It "// & + "is not necessary in the Waves2 module, so it does nothing.*" + + + ! Compute the first time derivatives of the continuous states here: None to calculate, so no code here. + + ! Dummy output value for dxdt -- this is only here to prevent the compiler from complaining. + dxdt%DummyContState = 0.0_SiKi + + +END SUBROUTINE Waves2_CalcContStateDeriv + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this routine is used to update discrete states, by +!! So, this routine will simply issue a warning and return. +SUBROUTINE Waves2_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(Waves2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Waves2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Waves2_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; + !! Output: Discrete states at Time + Interval + TYPE(Waves2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Waves2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Waves2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "Warning: No Discrete States to update in Waves2 module. *Waves2::UpdateDiscState was called. It is not "// & + "necessary in the Waves2 module, so it does nothing.*" + + ! Code to update the discrete states would live here, but there are no discrete states to update, hence no code. + + +END SUBROUTINE Waves2_UpdateDiscState + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is required for the FAST framework, but is not actually needed for this module. +!! In the framework, this is a tight coupling routine for solving for the residual of the constraint state equations +!! So, this routine will simply issue a warning and return. +!! @note A few values will be set so that compilers are happy, but nothing of value is done. +SUBROUTINE Waves2_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Waves2_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Waves2_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Waves2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Waves2_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Waves2_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(Waves2_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Waves2_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(Waves2_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "Warning: No States in Waves2 module. *Waves2::CalcConstrStateResidual was called. It is not needed in "//& + "the Waves2 module, so it does nothing useful." + + + + ! Solve for the constraint states here: Since there are no constraint states to solve for in Waves2, there is no code here. + + z_residual%DummyConstrState = 0.0_SiKi ! This exists just so that we can make the compiler happy. + +END SUBROUTINE Waves2_CalcConstrStateResidual + + + +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE Waves2 +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/hydrodyn/src/Waves2.txt b/OpenFAST/modules/hydrodyn/src/Waves2.txt new file mode 100644 index 000000000..71aa3c56a --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves2.txt @@ -0,0 +1,154 @@ +################################################################################################################################### +# Registry for Waves2 in the FAST Modularization Framework +# This Registry file is used to create MODULE Waves2_Types which contains all of the user-defined types needed in Waves2. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt + +param Waves2/Waves2 unused INTEGER MaxWaves2Outputs - 9 - "" - +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Waves2/Waves2 InitInputType INTEGER UnSum - - - "The unit number for the HydroDyn summary file" - + +typedef ^ ^ ReKi Gravity - - - "Gravitational acceleration" (m/s^2) +typedef ^ ^ ReKi WtrDens - - - "Water density" (kg/m^3) +typedef ^ ^ SiKi WtrDpth - - - "Water depth" (meters) + +typedef ^ ^ INTEGER NStepWave - - - "Total number of frequency components = total number of time steps in the incident wave" - +typedef ^ ^ INTEGER NStepWave2 - - - "NStepWave / 2" - +typedef ^ ^ SiKi WaveDOmega - - - "Frequency step for incident wave calculations" (rad/s) + +typedef ^ ^ INTEGER WaveStMod - - - "Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching}" - + +typedef ^ ^ LOGICAL WaveMultiDir - - - "Indicates the waves are multidirectional -- set by HydroDyn_Input" - +typedef ^ ^ SiKi WaveDirArr {:} - - "Wave direction array. Each frequency has a unique direction of WaveNDir > 1" (degrees) +typedef ^ ^ SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) +typedef ^ ^ SiKi WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec + +typedef ^ ^ INTEGER NWaveElev - - - "Number of points where the incident wave elevations can be output" - +typedef ^ ^ SiKi WaveElevxi {:} - - "xi-coordinates for points where the incident wave elevations can be output" (meters) +typedef ^ ^ SiKi WaveElevyi {:} - - "yi-coordinates for points where the incident wave elevations can be output" (meters) +typedef ^ ^ SiKi WaveElevXY {:}{:} - - "Supplied by Driver: X-Y locations for WaveElevation output (for visualization). Index 1 corresponds to X or Y coordinate. Index 2 corresponds to point number." - + +typedef ^ ^ INTEGER NWaveKin - - - "Number of points where the incident wave kinematics will be computed" - +typedef ^ ^ SiKi WaveKinxi {:} - - "xi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) +typedef ^ ^ SiKi WaveKinyi {:} - - "yi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) +typedef ^ ^ SiKi WaveKinzi {:} - - "zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level" (meters) + +typedef ^ ^ LOGICAL WvDiffQTFF - - - "Full difference QTF second order forces flag" (-) +typedef ^ ^ LOGICAL WvSumQTFF - - - "Full sum QTF second order forces flag" (-) + +typedef ^ ^ SiKi WvLowCOffD - - - "Minimum frequency used in the difference methods [Ignored if all difference methods = 0]" (rad/s) +typedef ^ ^ SiKi WvHiCOffD - - - "Maximum frequency used in the difference methods [Ignored if all difference methods = 0]" (rad/s) +typedef ^ ^ SiKi WvLowCOffS - - - "Minimum frequency used in the sum-QTF method [Ignored if SumQTF = 0]" (rad/s) +typedef ^ ^ SiKi WvHiCOffS - - - "Maximum frequency used in the sum-QTF method [Ignored if SumQTF = 0]" (rad/s) + +typedef ^ ^ CHARACTER(ChanLen) OutList {18} - - "This should really be dimensioned with MaxOutPts" - +typedef ^ ^ LOGICAL OutAll - - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - + + +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - +typedef ^ ^ SiKi WaveElevSeries2 {:}{:} - - "" (m) +# "Instantaneous elevation time-series at each of the points given by WaveElevXY. Used for making movies of the waves. First index is the timestep. Second index is XY point number corresponding to second index of WaveElevXY." (m) +typedef ^ ^ SiKi WaveAcc2D {:}{:}{:} - - "" (m/s^2) +# "Instantaneous 2nd-order difference frequency correction for the acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi WaveDynP2D {:}{:} - - "" (N/m^2) +# "Instantaneous 2nd-order difference frequency correction for the dynamic pressure of incident waves , at each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveAcc2S {:}{:}{:} - - "" (m/s^2) +# "Instantaneous 2nd-order sum frequency correction for the acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi WaveDynP2S {:}{:} - - "" (N/m^2) +# "Instantaneous 2nd-order sum frequency correction for the dynamic pressure of incident waves , at each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveVel2D {:}{:}{:} - - "" (m/s) +# "Instantaneous 2nd-order difference frequency correction for the velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) +typedef ^ ^ SiKi WaveVel2S {:}{:}{:} - - "" (m/s) +# "Instantaneous 2nd-order sum frequency correction for the velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) +typedef ^ ^ SiKi WaveAcc2D0 {:}{:}{:} - - "" (m/s^2) +# "Instantaneous 2nd-order difference frequency correction for the acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi WaveDynP2D0 {:}{:} - - "" (N/m^2) +# "Instantaneous 2nd-order difference frequency correction for the dynamic pressure of incident waves , at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveAcc2S0 {:}{:}{:} - - "" (m/s^2) +# "Instantaneous 2nd-order sum frequency correction for the acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed" (m/s^2) +typedef ^ ^ SiKi WaveDynP2S0 {:}{:} - - "" (N/m^2) +# "Instantaneous 2nd-order sum frequency correction for the dynamic pressure of incident waves , at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed" (N/m^2) +typedef ^ ^ SiKi WaveVel2D0 {:}{:}{:} - - "" (m/s) +# "Instantaneous 2nd-order difference frequency correction for the velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) +typedef ^ ^ SiKi WaveVel2S0 {:}{:}{:} - - "" (m/s) +# "Instantaneous 2nd-order sum frequency correction for the velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), for each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.)" (m/s) + + + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - + + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - + + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - + + +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType IntKi 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 INTEGER LastIndWave - - - "Index for last interpolation step of 2nd order forces" - + + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ^ LOGICAL WvDiffQTFF - - - "Full difference QTF second order forces flag" (-) +typedef ^ ^ LOGICAL WvSumQTFF - - - "Full sum QTF second order forces flag" (-) +typedef ^ ^ INTEGER NWaveElev - - - "Number of points where the incident wave elevations can be output" - +typedef ^ ^ INTEGER NStepWave - - - "Total number of frequency components = total number of time steps in the incident wave" - +typedef ^ ^ INTEGER NStepWave2 - - - "NStepWave / 2" - +typedef ^ ^ SiKi WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec +typedef ^ ^ SiKi WaveElev2 {:}{:} - - "Instantaneous elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output" (meters) +#typedef ^ ^ SiKi WaveElev2D {:}{:} - - "" (m) +# "Instantaneous 2nd-order difference frequency correction for the elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output" (meters) +#typedef ^ ^ SiKi WaveElev2S {:}{:} - - "" (m) +# "Instantaneous 2nd-order sum frequency correction for the elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output" (meters) +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - +typedef ^ ^ CHARACTER(ChanLen) Delim - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - + + + + + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef ^ InputType SiKi DummyInput - - - "Remove this variable if you have input data" - + + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType ReKi WriteOutput {:} - - "" - diff --git a/OpenFAST/modules/hydrodyn/src/Waves2_Output.f90 b/OpenFAST/modules/hydrodyn/src/Waves2_Output.f90 new file mode 100644 index 000000000..817ebc727 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves2_Output.f90 @@ -0,0 +1,576 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 National Renewable Energy Laboratory +! +! This file is part of HydroDyn. +! +! 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 Waves2_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + USE Waves2_Types + !USE HydroDyn_Output_Types +! USE Waves + IMPLICIT NONE + + PRIVATE + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen + + ! Waves2 Body Forces: + + INTEGER(IntKi), PARAMETER :: Wave1Elv2 = 1 + INTEGER(IntKi), PARAMETER :: Wave2Elv2 = 2 + INTEGER(IntKi), PARAMETER :: Wave3Elv2 = 3 + INTEGER(IntKi), PARAMETER :: Wave4Elv2 = 4 + INTEGER(IntKi), PARAMETER :: Wave5Elv2 = 5 + INTEGER(IntKi), PARAMETER :: Wave6Elv2 = 6 + INTEGER(IntKi), PARAMETER :: Wave7Elv2 = 7 + INTEGER(IntKi), PARAMETER :: Wave8Elv2 = 8 + INTEGER(IntKi), PARAMETER :: Wave9Elv2 = 9 + + + +!End of code generated by Matlab script + + + INTEGER(IntKi), PARAMETER :: WaveElevi2(9) = (/Wave1Elv2,Wave2Elv2,Wave3Elv2,Wave4Elv2,Wave5Elv2,Wave6Elv2,Wave7Elv2,Wave8Elv2,Wave9Elv2/) + + + +! This code was generated by hand. + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(9) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "WAVE1ELV2","WAVE2ELV2","WAVE3ELV2","WAVE4ELV2","WAVE5ELV2","WAVE6ELV2","WAVE7ELV2","WAVE8ELV2","WAVE9ELV2"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(9) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + Wave1Elv2 , Wave2Elv2 , Wave3Elv2 , Wave4Elv2 , Wave5Elv2 , Wave6Elv2 , Wave7Elv2 , Wave8Elv2 , Wave9Elv2 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(9) = (/ & ! This lists the units corresponding to the allowed parameters + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) "/) + + + REAL(ReKi) :: AllOuts(MaxWaves2Outputs) ! Array of all possible outputs + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: Wvs2OUT_MapOutputs + PUBLIC :: Wvs2OUT_WriteOutputNames + PUBLIC :: Wvs2OUT_WriteOutputUnits + PUBLIC :: Wvs2OUT_WriteOutputs + PUBLIC :: Wvs2OUT_Init + PUBLIC :: Wvs2OUT_DestroyParam + PUBLIC :: GetWaves2Channels + +CONTAINS + + + + +!==================================================================================================== +SUBROUTINE Wvs2OUT_MapOutputs( CurrentTime, y, NWaveElev, WaveElev2, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by Waves2_CalcOutput() at each time step. +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(Waves2_OutputType), INTENT( INOUT ) :: y ! Waves2's output data + INTEGER, INTENT( IN ) :: NWaveElev ! Number of wave elevation locations to output + REAL(SiKi), INTENT( IN ) :: WaveElev2(:) ! Instantaneous second order correction to the elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWaves2Outputs) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I + + ErrStat = ErrID_None + ErrMsg = "" + + + ! TODO: use y%mesh for the forces instead of individual parameters + + DO I=1,NWaveElev + AllOuts(WaveElevi2(I)) = WaveElev2(I) + END DO + + + +END SUBROUTINE Wvs2OUT_MapOutputs + + +!==================================================================================================== + +SUBROUTINE Wvs2OUT_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(Waves2_ParameterType), INTENT( IN ) :: p ! Waves2 module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) + +END SUBROUTINE Wvs2OUT_WriteOutputNames + +!==================================================================================================== + + +SUBROUTINE Wvs2OUT_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file + TYPE(Waves2_ParameterType), INTENT( IN ) :: p ! Waves2 module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) + +END SUBROUTINE Wvs2OUT_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE Wvs2OUT_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in Wvs2OUT_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + INTEGER , INTENT( IN ) :: UnOutFile + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + TYPE(Waves2_OutputType), INTENT( INOUT ) :: y ! Waves2's output data + TYPE(Waves2_ParameterType),INTENT( IN ) :: p ! Waves2 parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables +! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + + ! Initialize ErrStat and determine if it makes any sense to write output + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN + ErrMsg = ' No Waves2 outputs written. The OutParam array must be allocated and there must be a valid output file identifier before we can write outputs.' + ErrStat = ErrID_Warn + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + + + ! Write the output parameters to the file + + Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + + WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) + + + RETURN + + +END SUBROUTINE Wvs2OUT_WriteOutputs + + + +!==================================================================================================== +SUBROUTINE Wvs2OUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + + TYPE(Waves2_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module + TYPE(Waves2_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(Waves2_ParameterType), INTENT( INOUT ) :: p + TYPE(Waves2_InitOutputType), INTENT( OUT ) :: InitOut + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter +! INTEGER :: J ! Generic loop counter +! INTEGER :: Indx ! Counts the current index into the WaveKinNd array +! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! CHARACTER(200) :: Frmt ! a string to hold a format statement + + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! Temporary Error status + INTEGER(IntKi) :: ErrStatTmp ! Temporary Error message + + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + + + + !------------------------------------------------------------------------------------------------- + ! Check that the variables in OutList are valid + !------------------------------------------------------------------------------------------------- + + CALL Wvs2OUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStatTmp, ErrMsg ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'Wvs2OUT_Init') + IF (ErrStat >= AbortErrLev ) RETURN + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStatTmp ) + IF ( ErrStattmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,' Error allocating space for WriteOutput array.',ErrStat,ErrMsg,'Wvs2OUT_Init') + IF (ErrStat >= AbortErrLev ) RETURN + RETURN + END IF + y%WriteOutput = 0.0_ReKi + + ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStatTmp ) + IF ( ErrStattmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,' Error allocating space for WriteOutputHdr array.',ErrStat,ErrMsg,'Wvs2OUT_Init') + IF (ErrStat >= AbortErrLev ) RETURN + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStatTmp ) + IF ( ErrStattmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,' Error allocating space for WriteOutputUnt array.',ErrStat,ErrMsg,'Wvs2OUT_Init') + IF (ErrStat >= AbortErrLev ) RETURN + RETURN + END IF + + DO I = 1,p%NumOuts + + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + + END DO + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE Wvs2OUT_Init + + +!==================================================================================================== +FUNCTION GetWaves2Channels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if they +! below to the list of available Waves2 channels. + +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels + CHARACTER(ChanLen), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. + CHARACTER(ChanLen), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched Waves2 output channels. + LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER GetWaves2Channels ! The number of channels found in this module + + ! Local variables. + + INTEGER :: I ! Generic loop-counting index. + INTEGER :: count ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. +! LOGICAL :: InvalidOutput(MaxWaves2Outputs) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + + LOGICAL :: newFoundMask (NUserOutputs) ! A Mask indicating whether a user requested channel belongs to a modules output channels. + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + GetWaves2Channels = 0 + + newFoundMask = .FALSE. + + + DO I = 1,NUserOutputs + IF (.NOT. foundMask(I) ) THEN + OutListTmp = UserOutputs(I) + + CheckOutListAgain = .FALSE. + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + newFoundMask(I) = .TRUE. + foundMask(I) = .TRUE. + GetWaves2Channels = GetWaves2Channels + 1 + + !ELSE + ! foundMask(I) = .FALSE. + END IF + END IF +END DO + + +IF ( GetWaves2Channels > 0 ) THEN + + count = 1 + ! ! Test that num channels does not exceed max possible channels due to size of OutList + ! ALLOCATE ( OutList(GetWaves2Channels) , STAT=ErrStat ) + ! IF ( ErrStat /= 0 ) THEN + ! ErrMsg = ' Error allocating memory for the OutList array in the GetWaves2Channels function.' + ! ErrStat = ErrID_Fatal + ! RETURN + ! END IF + + DO I = 1,NUserOutputs + IF ( newFoundMask(I) ) THEN + OutList(count) = UserOutputs(I) + count = count + 1 + END IF + + END DO + +END IF + + +END FUNCTION GetWaves2Channels + + + + +!==================================================================================================== +SUBROUTINE Wvs2OUT_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! Note that the Wamit module must be initialized prior to calling this function (if it +! is being used) so that it can correctly determine if the Lines outputs are valid. +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(Waves2_OutputType), INTENT( INOUT ) :: y ! This module's internal data + TYPE(Waves2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the Waves2 platform module + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! Temporary error message + INTEGER(IntKi) :: ErrStatTmp ! Temporary error status + + INTEGER :: I ! Generic loop-counting index. +! INTEGER :: J ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + + + ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 09-Jan-2013 14:53:03. + + LOGICAL :: InvalidOutput(MaxWaves2Outputs) ! This array determines if the output channel is valid for this configuration + + LOGICAL :: CheckOutListAgain + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = "" + ErrMsgTmp = "" + + InvalidOutput = .FALSE. + +!End of code generated by Matlab script + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + + + ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStatTmp ) + IF ( ErrStatTmp /= 0 ) CALL SetErrStat(ErrID_Fatal,' Error allocating memory for the OutParam array.',ErrStat,ErrMsg,'Wvs2OUT_ChkOutLst') + IF ( ErrStat >= AbortErrLev ) RETURN + + + + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' + ErrStat = ErrID_Fatal + + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 1 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + END DO + + + RETURN +END SUBROUTINE Wvs2OUT_ChkOutLst + + +!==================================================================================================== +SUBROUTINE Wvs2OUT_DestroyParam ( p, ErrStat, ErrMsg ) +! This function cleans up after running the Waves2 output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(Waves2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the Waves2 module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + Err = .FALSE. + + + + !------------------------------------------------------------------------------------------------- + ! Deallocate arrays + !------------------------------------------------------------------------------------------------- + IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + !------------------------------------------------------------------------------------------------- + ! Reset number of outputs + !------------------------------------------------------------------------------------------------- + p%NumOuts = 0 + p%UnOutFile = -1 + + !p%WaveKinNd = -1 ! set this array to "invalid" + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE Wvs2OUT_DestroyParam +!==================================================================================================== + + +END MODULE Waves2_Output diff --git a/OpenFAST/modules/hydrodyn/src/Waves2_Types.f90 b/OpenFAST/modules/hydrodyn/src/Waves2_Types.f90 new file mode 100644 index 000000000..affe3fdc4 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves2_Types.f90 @@ -0,0 +1,3802 @@ +!STARTOFREGISTRYGENERATEDFILE 'Waves2_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 +!********************************************************************************************************************************* +! Waves2_Types +!................................................................................................................................. +! This file is part of Waves2. +! +! 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 Waves2. 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 Waves2_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxWaves2Outputs = 9 ! [-] +! ========= Waves2_InitInputType ======= + TYPE, PUBLIC :: Waves2_InitInputType + INTEGER(IntKi) :: UnSum !< The unit number for the HydroDyn summary file [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [(m/s^2)] + REAL(ReKi) :: WtrDens !< Water density [(kg/m^3)] + REAL(SiKi) :: WtrDpth !< Water depth [(meters)] + INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] + INTEGER(IntKi) :: NStepWave2 !< NStepWave / 2 [-] + REAL(SiKi) :: WaveDOmega !< Frequency step for incident wave calculations [(rad/s)] + INTEGER(IntKi) :: WaveStMod !< Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching} [-] + LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveDirArr !< Wave direction array. Each frequency has a unique direction of WaveNDir > 1 [(degrees)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevC0 !< Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] + INTEGER(IntKi) :: NWaveElev !< Number of points where the incident wave elevations can be output [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElevxi !< xi-coordinates for points where the incident wave elevations can be output [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElevyi !< yi-coordinates for points where the incident wave elevations can be output [(meters)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< Supplied by Driver: X-Y locations for WaveElevation output (for visualization). Index 1 corresponds to X or Y coordinate. Index 2 corresponds to point number. [-] + INTEGER(IntKi) :: NWaveKin !< Number of points where the incident wave kinematics will be computed [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinxi !< xi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinyi !< yi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinzi !< zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + LOGICAL :: WvDiffQTFF !< Full difference QTF second order forces flag [(-)] + LOGICAL :: WvSumQTFF !< Full sum QTF second order forces flag [(-)] + REAL(SiKi) :: WvLowCOffD !< Minimum frequency used in the difference methods [Ignored if all difference methods = 0] [(rad/s)] + REAL(SiKi) :: WvHiCOffD !< Maximum frequency used in the difference methods [Ignored if all difference methods = 0] [(rad/s)] + REAL(SiKi) :: WvLowCOffS !< Minimum frequency used in the sum-QTF method [Ignored if SumQTF = 0] [(rad/s)] + REAL(SiKi) :: WvHiCOffS !< Maximum frequency used in the sum-QTF method [Ignored if SumQTF = 0] [(rad/s)] + CHARACTER(ChanLen) , DIMENSION(1:18) :: OutList !< This should really be dimensioned with MaxOutPts [-] + LOGICAL :: OutAll !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + END TYPE Waves2_InitInputType +! ======================= +! ========= Waves2_InitOutputType ======= + TYPE, PUBLIC :: Waves2_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevSeries2 !< [(m)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc2D !< [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP2D !< [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc2S !< [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP2S !< [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel2D !< [(m/s)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel2S !< [(m/s)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc2D0 !< [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP2D0 !< [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc2S0 !< [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP2S0 !< [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel2D0 !< [(m/s)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel2S0 !< [(m/s)] + END TYPE Waves2_InitOutputType +! ======================= +! ========= Waves2_ContinuousStateType ======= + TYPE, PUBLIC :: Waves2_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Waves2_ContinuousStateType +! ======================= +! ========= Waves2_DiscreteStateType ======= + TYPE, PUBLIC :: Waves2_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE Waves2_DiscreteStateType +! ======================= +! ========= Waves2_ConstraintStateType ======= + TYPE, PUBLIC :: Waves2_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Waves2_ConstraintStateType +! ======================= +! ========= Waves2_OtherStateType ======= + TYPE, PUBLIC :: Waves2_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE Waves2_OtherStateType +! ======================= +! ========= Waves2_MiscVarType ======= + TYPE, PUBLIC :: Waves2_MiscVarType + INTEGER(IntKi) :: LastIndWave !< Index for last interpolation step of 2nd order forces [-] + END TYPE Waves2_MiscVarType +! ======================= +! ========= Waves2_ParameterType ======= + TYPE, PUBLIC :: Waves2_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + LOGICAL :: WvDiffQTFF !< Full difference QTF second order forces flag [(-)] + LOGICAL :: WvSumQTFF !< Full sum QTF second order forces flag [(-)] + INTEGER(IntKi) :: NWaveElev !< Number of points where the incident wave elevations can be output [-] + INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] + INTEGER(IntKi) :: NStepWave2 !< NStepWave / 2 [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev2 !< Instantaneous elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output [(meters)] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] + INTEGER(IntKi) :: NumOuts !< [-] + INTEGER(IntKi) :: NumOutAll !< [-] + CHARACTER(20) :: OutFmt !< [-] + CHARACTER(20) :: OutSFmt !< [-] + CHARACTER(ChanLen) :: Delim !< [-] + INTEGER(IntKi) :: UnOutFile !< [-] + END TYPE Waves2_ParameterType +! ======================= +! ========= Waves2_InputType ======= + TYPE, PUBLIC :: Waves2_InputType + REAL(SiKi) :: DummyInput !< Remove this variable if you have input data [-] + END TYPE Waves2_InputType +! ======================= +! ========= Waves2_OutputType ======= + TYPE, PUBLIC :: Waves2_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + END TYPE Waves2_OutputType +! ======================= +CONTAINS + SUBROUTINE Waves2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Waves2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%WtrDens = SrcInitInputData%WtrDens + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%NStepWave = SrcInitInputData%NStepWave + DstInitInputData%NStepWave2 = SrcInitInputData%NStepWave2 + DstInitInputData%WaveDOmega = SrcInitInputData%WaveDOmega + DstInitInputData%WaveStMod = SrcInitInputData%WaveStMod + DstInitInputData%WaveMultiDir = SrcInitInputData%WaveMultiDir +IF (ALLOCATED(SrcInitInputData%WaveDirArr)) THEN + i1_l = LBOUND(SrcInitInputData%WaveDirArr,1) + i1_u = UBOUND(SrcInitInputData%WaveDirArr,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveDirArr)) THEN + ALLOCATE(DstInitInputData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveDirArr = SrcInitInputData%WaveDirArr +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevC0)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevC0,1) + i1_u = UBOUND(SrcInitInputData%WaveElevC0,1) + i2_l = LBOUND(SrcInitInputData%WaveElevC0,2) + i2_u = UBOUND(SrcInitInputData%WaveElevC0,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevC0)) THEN + ALLOCATE(DstInitInputData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevC0 = SrcInitInputData%WaveElevC0 +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitInputData%WaveTime,1) + i1_u = UBOUND(SrcInitInputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveTime)) THEN + ALLOCATE(DstInitInputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveTime = SrcInitInputData%WaveTime +ENDIF + DstInitInputData%NWaveElev = SrcInitInputData%NWaveElev +IF (ALLOCATED(SrcInitInputData%WaveElevxi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevxi,1) + i1_u = UBOUND(SrcInitInputData%WaveElevxi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevxi)) THEN + ALLOCATE(DstInitInputData%WaveElevxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevxi = SrcInitInputData%WaveElevxi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevyi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevyi,1) + i1_u = UBOUND(SrcInitInputData%WaveElevyi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevyi)) THEN + ALLOCATE(DstInitInputData%WaveElevyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevyi = SrcInitInputData%WaveElevyi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevXY)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevXY,1) + i1_u = UBOUND(SrcInitInputData%WaveElevXY,1) + i2_l = LBOUND(SrcInitInputData%WaveElevXY,2) + i2_u = UBOUND(SrcInitInputData%WaveElevXY,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevXY)) THEN + ALLOCATE(DstInitInputData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevXY = SrcInitInputData%WaveElevXY +ENDIF + DstInitInputData%NWaveKin = SrcInitInputData%NWaveKin +IF (ALLOCATED(SrcInitInputData%WaveKinxi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinxi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinxi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinxi)) THEN + ALLOCATE(DstInitInputData%WaveKinxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinxi = SrcInitInputData%WaveKinxi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveKinyi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinyi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinyi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinyi)) THEN + ALLOCATE(DstInitInputData%WaveKinyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinyi = SrcInitInputData%WaveKinyi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveKinzi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinzi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinzi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinzi)) THEN + ALLOCATE(DstInitInputData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinzi = SrcInitInputData%WaveKinzi +ENDIF + DstInitInputData%WvDiffQTFF = SrcInitInputData%WvDiffQTFF + DstInitInputData%WvSumQTFF = SrcInitInputData%WvSumQTFF + DstInitInputData%WvLowCOffD = SrcInitInputData%WvLowCOffD + DstInitInputData%WvHiCOffD = SrcInitInputData%WvHiCOffD + DstInitInputData%WvLowCOffS = SrcInitInputData%WvLowCOffS + DstInitInputData%WvHiCOffS = SrcInitInputData%WvHiCOffS + DstInitInputData%OutList = SrcInitInputData%OutList + DstInitInputData%OutAll = SrcInitInputData%OutAll + DstInitInputData%NumOuts = SrcInitInputData%NumOuts + DstInitInputData%NumOutAll = SrcInitInputData%NumOutAll + END SUBROUTINE Waves2_CopyInitInput + + SUBROUTINE Waves2_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Waves2_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveDirArr)) THEN + DEALLOCATE(InitInputData%WaveDirArr) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevC0)) THEN + DEALLOCATE(InitInputData%WaveElevC0) +ENDIF +IF (ALLOCATED(InitInputData%WaveTime)) THEN + DEALLOCATE(InitInputData%WaveTime) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevxi)) THEN + DEALLOCATE(InitInputData%WaveElevxi) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevyi)) THEN + DEALLOCATE(InitInputData%WaveElevyi) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevXY)) THEN + DEALLOCATE(InitInputData%WaveElevXY) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinxi)) THEN + DEALLOCATE(InitInputData%WaveKinxi) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinyi)) THEN + DEALLOCATE(InitInputData%WaveKinyi) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinzi)) THEN + DEALLOCATE(InitInputData%WaveKinzi) +ENDIF + END SUBROUTINE Waves2_DestroyInitInput + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 ! UnSum + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NStepWave2 + Re_BufSz = Re_BufSz + 1 ! WaveDOmega + Int_BufSz = Int_BufSz + 1 ! WaveStMod + Int_BufSz = Int_BufSz + 1 ! WaveMultiDir + Int_BufSz = Int_BufSz + 1 ! WaveDirArr allocated yes/no + IF ( ALLOCATED(InData%WaveDirArr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveDirArr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDirArr) ! WaveDirArr + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevC0 allocated yes/no + IF ( ALLOCATED(InData%WaveElevC0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevC0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevC0) ! WaveElevC0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! NWaveElev + Int_BufSz = Int_BufSz + 1 ! WaveElevxi allocated yes/no + IF ( ALLOCATED(InData%WaveElevxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElevxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevxi) ! WaveElevxi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevyi allocated yes/no + IF ( ALLOCATED(InData%WaveElevyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElevyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevyi) ! WaveElevyi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevXY allocated yes/no + IF ( ALLOCATED(InData%WaveElevXY) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevXY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevXY) ! WaveElevXY + END IF + Int_BufSz = Int_BufSz + 1 ! NWaveKin + Int_BufSz = Int_BufSz + 1 ! WaveKinxi allocated yes/no + IF ( ALLOCATED(InData%WaveKinxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinxi) ! WaveKinxi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveKinyi allocated yes/no + IF ( ALLOCATED(InData%WaveKinyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinyi) ! WaveKinyi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveKinzi allocated yes/no + IF ( ALLOCATED(InData%WaveKinzi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinzi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinzi) ! WaveKinzi + END IF + Int_BufSz = Int_BufSz + 1 ! WvDiffQTFF + Int_BufSz = Int_BufSz + 1 ! WvSumQTFF + Re_BufSz = Re_BufSz + 1 ! WvLowCOffD + Re_BufSz = Re_BufSz + 1 ! WvHiCOffD + Re_BufSz = Re_BufSz + 1 ! WvLowCOffS + Re_BufSz = Re_BufSz + 1 ! WvHiCOffS + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + 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%UnSum + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave2 + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDOmega + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveStMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveMultiDir, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveDirArr) ) 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%WaveDirArr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDirArr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveDirArr,1), UBOUND(InData%WaveDirArr,1) + ReKiBuf(Re_Xferred) = InData%WaveDirArr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevC0) ) 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%WaveElevC0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevC0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevC0,2), UBOUND(InData%WaveElevC0,2) + DO i1 = LBOUND(InData%WaveElevC0,1), UBOUND(InData%WaveElevC0,1) + ReKiBuf(Re_Xferred) = InData%WaveElevC0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NWaveElev + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElevxi) ) 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%WaveElevxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElevxi,1), UBOUND(InData%WaveElevxi,1) + ReKiBuf(Re_Xferred) = InData%WaveElevxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevyi) ) 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%WaveElevyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElevyi,1), UBOUND(InData%WaveElevyi,1) + ReKiBuf(Re_Xferred) = InData%WaveElevyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevXY) ) 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%WaveElevXY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevXY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevXY,2), UBOUND(InData%WaveElevXY,2) + DO i1 = LBOUND(InData%WaveElevXY,1), UBOUND(InData%WaveElevXY,1) + ReKiBuf(Re_Xferred) = InData%WaveElevXY(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NWaveKin + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveKinxi) ) 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%WaveKinxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinxi,1), UBOUND(InData%WaveKinxi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveKinyi) ) 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%WaveKinyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinyi,1), UBOUND(InData%WaveKinyi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveKinzi) ) 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%WaveKinzi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinzi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinzi,1), UBOUND(InData%WaveKinzi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinzi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%WvDiffQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WvSumQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOffD + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOffD + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOffS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOffS + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_PackInitInput + + SUBROUTINE Waves2_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(Waves2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_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%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDOmega = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveStMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveMultiDir = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveMultiDir) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDirArr 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%WaveDirArr)) DEALLOCATE(OutData%WaveDirArr) + ALLOCATE(OutData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveDirArr,1), UBOUND(OutData%WaveDirArr,1) + OutData%WaveDirArr(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 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%WaveElevC0)) DEALLOCATE(OutData%WaveElevC0) + ALLOCATE(OutData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevC0,2), UBOUND(OutData%WaveElevC0,2) + DO i1 = LBOUND(OutData%WaveElevC0,1), UBOUND(OutData%WaveElevC0,1) + OutData%WaveElevC0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NWaveElev = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevxi 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%WaveElevxi)) DEALLOCATE(OutData%WaveElevxi) + ALLOCATE(OutData%WaveElevxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElevxi,1), UBOUND(OutData%WaveElevxi,1) + OutData%WaveElevxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevyi 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%WaveElevyi)) DEALLOCATE(OutData%WaveElevyi) + ALLOCATE(OutData%WaveElevyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElevyi,1), UBOUND(OutData%WaveElevyi,1) + OutData%WaveElevyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevXY 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%WaveElevXY)) DEALLOCATE(OutData%WaveElevXY) + ALLOCATE(OutData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevXY,2), UBOUND(OutData%WaveElevXY,2) + DO i1 = LBOUND(OutData%WaveElevXY,1), UBOUND(OutData%WaveElevXY,1) + OutData%WaveElevXY(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%NWaveKin = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinxi 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%WaveKinxi)) DEALLOCATE(OutData%WaveKinxi) + ALLOCATE(OutData%WaveKinxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinxi,1), UBOUND(OutData%WaveKinxi,1) + OutData%WaveKinxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinyi 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%WaveKinyi)) DEALLOCATE(OutData%WaveKinyi) + ALLOCATE(OutData%WaveKinyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinyi,1), UBOUND(OutData%WaveKinyi,1) + OutData%WaveKinyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinzi 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%WaveKinzi)) DEALLOCATE(OutData%WaveKinzi) + ALLOCATE(OutData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinzi,1), UBOUND(OutData%WaveKinzi,1) + OutData%WaveKinzi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WvDiffQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%WvDiffQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%WvSumQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%WvSumQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%WvLowCOffD = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOffD = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WvLowCOffS = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOffS = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%OutList,1) + i1_u = UBOUND(OutData%OutList,1) + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_UnPackInitInput + + SUBROUTINE Waves2_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Waves2_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveElevSeries2)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElevSeries2,1) + i1_u = UBOUND(SrcInitOutputData%WaveElevSeries2,1) + i2_l = LBOUND(SrcInitOutputData%WaveElevSeries2,2) + i2_u = UBOUND(SrcInitOutputData%WaveElevSeries2,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElevSeries2)) THEN + ALLOCATE(DstInitOutputData%WaveElevSeries2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElevSeries2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElevSeries2 = SrcInitOutputData%WaveElevSeries2 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveAcc2D)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveAcc2D,1) + i1_u = UBOUND(SrcInitOutputData%WaveAcc2D,1) + i2_l = LBOUND(SrcInitOutputData%WaveAcc2D,2) + i2_u = UBOUND(SrcInitOutputData%WaveAcc2D,2) + i3_l = LBOUND(SrcInitOutputData%WaveAcc2D,3) + i3_u = UBOUND(SrcInitOutputData%WaveAcc2D,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveAcc2D)) THEN + ALLOCATE(DstInitOutputData%WaveAcc2D(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveAcc2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveAcc2D = SrcInitOutputData%WaveAcc2D +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDynP2D)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDynP2D,1) + i1_u = UBOUND(SrcInitOutputData%WaveDynP2D,1) + i2_l = LBOUND(SrcInitOutputData%WaveDynP2D,2) + i2_u = UBOUND(SrcInitOutputData%WaveDynP2D,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDynP2D)) THEN + ALLOCATE(DstInitOutputData%WaveDynP2D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDynP2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDynP2D = SrcInitOutputData%WaveDynP2D +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveAcc2S)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveAcc2S,1) + i1_u = UBOUND(SrcInitOutputData%WaveAcc2S,1) + i2_l = LBOUND(SrcInitOutputData%WaveAcc2S,2) + i2_u = UBOUND(SrcInitOutputData%WaveAcc2S,2) + i3_l = LBOUND(SrcInitOutputData%WaveAcc2S,3) + i3_u = UBOUND(SrcInitOutputData%WaveAcc2S,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveAcc2S)) THEN + ALLOCATE(DstInitOutputData%WaveAcc2S(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveAcc2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveAcc2S = SrcInitOutputData%WaveAcc2S +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDynP2S)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDynP2S,1) + i1_u = UBOUND(SrcInitOutputData%WaveDynP2S,1) + i2_l = LBOUND(SrcInitOutputData%WaveDynP2S,2) + i2_u = UBOUND(SrcInitOutputData%WaveDynP2S,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDynP2S)) THEN + ALLOCATE(DstInitOutputData%WaveDynP2S(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDynP2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDynP2S = SrcInitOutputData%WaveDynP2S +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveVel2D)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveVel2D,1) + i1_u = UBOUND(SrcInitOutputData%WaveVel2D,1) + i2_l = LBOUND(SrcInitOutputData%WaveVel2D,2) + i2_u = UBOUND(SrcInitOutputData%WaveVel2D,2) + i3_l = LBOUND(SrcInitOutputData%WaveVel2D,3) + i3_u = UBOUND(SrcInitOutputData%WaveVel2D,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveVel2D)) THEN + ALLOCATE(DstInitOutputData%WaveVel2D(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveVel2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveVel2D = SrcInitOutputData%WaveVel2D +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveVel2S)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveVel2S,1) + i1_u = UBOUND(SrcInitOutputData%WaveVel2S,1) + i2_l = LBOUND(SrcInitOutputData%WaveVel2S,2) + i2_u = UBOUND(SrcInitOutputData%WaveVel2S,2) + i3_l = LBOUND(SrcInitOutputData%WaveVel2S,3) + i3_u = UBOUND(SrcInitOutputData%WaveVel2S,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveVel2S)) THEN + ALLOCATE(DstInitOutputData%WaveVel2S(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveVel2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveVel2S = SrcInitOutputData%WaveVel2S +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveAcc2D0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveAcc2D0,1) + i1_u = UBOUND(SrcInitOutputData%WaveAcc2D0,1) + i2_l = LBOUND(SrcInitOutputData%WaveAcc2D0,2) + i2_u = UBOUND(SrcInitOutputData%WaveAcc2D0,2) + i3_l = LBOUND(SrcInitOutputData%WaveAcc2D0,3) + i3_u = UBOUND(SrcInitOutputData%WaveAcc2D0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveAcc2D0)) THEN + ALLOCATE(DstInitOutputData%WaveAcc2D0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveAcc2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveAcc2D0 = SrcInitOutputData%WaveAcc2D0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDynP2D0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDynP2D0,1) + i1_u = UBOUND(SrcInitOutputData%WaveDynP2D0,1) + i2_l = LBOUND(SrcInitOutputData%WaveDynP2D0,2) + i2_u = UBOUND(SrcInitOutputData%WaveDynP2D0,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDynP2D0)) THEN + ALLOCATE(DstInitOutputData%WaveDynP2D0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDynP2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDynP2D0 = SrcInitOutputData%WaveDynP2D0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveAcc2S0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveAcc2S0,1) + i1_u = UBOUND(SrcInitOutputData%WaveAcc2S0,1) + i2_l = LBOUND(SrcInitOutputData%WaveAcc2S0,2) + i2_u = UBOUND(SrcInitOutputData%WaveAcc2S0,2) + i3_l = LBOUND(SrcInitOutputData%WaveAcc2S0,3) + i3_u = UBOUND(SrcInitOutputData%WaveAcc2S0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveAcc2S0)) THEN + ALLOCATE(DstInitOutputData%WaveAcc2S0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveAcc2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveAcc2S0 = SrcInitOutputData%WaveAcc2S0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDynP2S0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDynP2S0,1) + i1_u = UBOUND(SrcInitOutputData%WaveDynP2S0,1) + i2_l = LBOUND(SrcInitOutputData%WaveDynP2S0,2) + i2_u = UBOUND(SrcInitOutputData%WaveDynP2S0,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDynP2S0)) THEN + ALLOCATE(DstInitOutputData%WaveDynP2S0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDynP2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDynP2S0 = SrcInitOutputData%WaveDynP2S0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveVel2D0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveVel2D0,1) + i1_u = UBOUND(SrcInitOutputData%WaveVel2D0,1) + i2_l = LBOUND(SrcInitOutputData%WaveVel2D0,2) + i2_u = UBOUND(SrcInitOutputData%WaveVel2D0,2) + i3_l = LBOUND(SrcInitOutputData%WaveVel2D0,3) + i3_u = UBOUND(SrcInitOutputData%WaveVel2D0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveVel2D0)) THEN + ALLOCATE(DstInitOutputData%WaveVel2D0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveVel2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveVel2D0 = SrcInitOutputData%WaveVel2D0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveVel2S0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveVel2S0,1) + i1_u = UBOUND(SrcInitOutputData%WaveVel2S0,1) + i2_l = LBOUND(SrcInitOutputData%WaveVel2S0,2) + i2_u = UBOUND(SrcInitOutputData%WaveVel2S0,2) + i3_l = LBOUND(SrcInitOutputData%WaveVel2S0,3) + i3_u = UBOUND(SrcInitOutputData%WaveVel2S0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveVel2S0)) THEN + ALLOCATE(DstInitOutputData%WaveVel2S0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveVel2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveVel2S0 = SrcInitOutputData%WaveVel2S0 +ENDIF + END SUBROUTINE Waves2_CopyInitOutput + + SUBROUTINE Waves2_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Waves2_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF +IF (ALLOCATED(InitOutputData%WaveElevSeries2)) THEN + DEALLOCATE(InitOutputData%WaveElevSeries2) +ENDIF +IF (ALLOCATED(InitOutputData%WaveAcc2D)) THEN + DEALLOCATE(InitOutputData%WaveAcc2D) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDynP2D)) THEN + DEALLOCATE(InitOutputData%WaveDynP2D) +ENDIF +IF (ALLOCATED(InitOutputData%WaveAcc2S)) THEN + DEALLOCATE(InitOutputData%WaveAcc2S) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDynP2S)) THEN + DEALLOCATE(InitOutputData%WaveDynP2S) +ENDIF +IF (ALLOCATED(InitOutputData%WaveVel2D)) THEN + DEALLOCATE(InitOutputData%WaveVel2D) +ENDIF +IF (ALLOCATED(InitOutputData%WaveVel2S)) THEN + DEALLOCATE(InitOutputData%WaveVel2S) +ENDIF +IF (ALLOCATED(InitOutputData%WaveAcc2D0)) THEN + DEALLOCATE(InitOutputData%WaveAcc2D0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDynP2D0)) THEN + DEALLOCATE(InitOutputData%WaveDynP2D0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveAcc2S0)) THEN + DEALLOCATE(InitOutputData%WaveAcc2S0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDynP2S0)) THEN + DEALLOCATE(InitOutputData%WaveDynP2S0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveVel2D0)) THEN + DEALLOCATE(InitOutputData%WaveVel2D0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveVel2S0)) THEN + DEALLOCATE(InitOutputData%WaveVel2S0) +ENDIF + END SUBROUTINE Waves2_DestroyInitOutput + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevSeries2 allocated yes/no + IF ( ALLOCATED(InData%WaveElevSeries2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevSeries2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevSeries2) ! WaveElevSeries2 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc2D allocated yes/no + IF ( ALLOCATED(InData%WaveAcc2D) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc2D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc2D) ! WaveAcc2D + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP2D allocated yes/no + IF ( ALLOCATED(InData%WaveDynP2D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP2D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP2D) ! WaveDynP2D + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc2S allocated yes/no + IF ( ALLOCATED(InData%WaveAcc2S) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc2S upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc2S) ! WaveAcc2S + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP2S allocated yes/no + IF ( ALLOCATED(InData%WaveDynP2S) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP2S upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP2S) ! WaveDynP2S + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel2D allocated yes/no + IF ( ALLOCATED(InData%WaveVel2D) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel2D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel2D) ! WaveVel2D + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel2S allocated yes/no + IF ( ALLOCATED(InData%WaveVel2S) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel2S upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel2S) ! WaveVel2S + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc2D0 allocated yes/no + IF ( ALLOCATED(InData%WaveAcc2D0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc2D0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc2D0) ! WaveAcc2D0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP2D0 allocated yes/no + IF ( ALLOCATED(InData%WaveDynP2D0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP2D0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP2D0) ! WaveDynP2D0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc2S0 allocated yes/no + IF ( ALLOCATED(InData%WaveAcc2S0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc2S0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc2S0) ! WaveAcc2S0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP2S0 allocated yes/no + IF ( ALLOCATED(InData%WaveDynP2S0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP2S0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP2S0) ! WaveDynP2S0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel2D0 allocated yes/no + IF ( ALLOCATED(InData%WaveVel2D0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel2D0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel2D0) ! WaveVel2D0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel2S0 allocated yes/no + IF ( ALLOCATED(InData%WaveVel2S0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel2S0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel2S0) ! WaveVel2S0 + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevSeries2) ) 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%WaveElevSeries2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevSeries2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevSeries2,2), UBOUND(InData%WaveElevSeries2,2) + DO i1 = LBOUND(InData%WaveElevSeries2,1), UBOUND(InData%WaveElevSeries2,1) + ReKiBuf(Re_Xferred) = InData%WaveElevSeries2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc2D) ) 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%WaveAcc2D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2D,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc2D,3), UBOUND(InData%WaveAcc2D,3) + DO i2 = LBOUND(InData%WaveAcc2D,2), UBOUND(InData%WaveAcc2D,2) + DO i1 = LBOUND(InData%WaveAcc2D,1), UBOUND(InData%WaveAcc2D,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc2D(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP2D) ) 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%WaveDynP2D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP2D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2D,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP2D,2), UBOUND(InData%WaveDynP2D,2) + DO i1 = LBOUND(InData%WaveDynP2D,1), UBOUND(InData%WaveDynP2D,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP2D(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc2S) ) 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%WaveAcc2S,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2S,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2S,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc2S,3), UBOUND(InData%WaveAcc2S,3) + DO i2 = LBOUND(InData%WaveAcc2S,2), UBOUND(InData%WaveAcc2S,2) + DO i1 = LBOUND(InData%WaveAcc2S,1), UBOUND(InData%WaveAcc2S,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc2S(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP2S) ) 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%WaveDynP2S,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2S,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP2S,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2S,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP2S,2), UBOUND(InData%WaveDynP2S,2) + DO i1 = LBOUND(InData%WaveDynP2S,1), UBOUND(InData%WaveDynP2S,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP2S(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel2D) ) 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%WaveVel2D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2D,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel2D,3), UBOUND(InData%WaveVel2D,3) + DO i2 = LBOUND(InData%WaveVel2D,2), UBOUND(InData%WaveVel2D,2) + DO i1 = LBOUND(InData%WaveVel2D,1), UBOUND(InData%WaveVel2D,1) + ReKiBuf(Re_Xferred) = InData%WaveVel2D(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel2S) ) 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%WaveVel2S,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2S,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2S,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel2S,3), UBOUND(InData%WaveVel2S,3) + DO i2 = LBOUND(InData%WaveVel2S,2), UBOUND(InData%WaveVel2S,2) + DO i1 = LBOUND(InData%WaveVel2S,1), UBOUND(InData%WaveVel2S,1) + ReKiBuf(Re_Xferred) = InData%WaveVel2S(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc2D0) ) 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%WaveAcc2D0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2D0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2D0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2D0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc2D0,3), UBOUND(InData%WaveAcc2D0,3) + DO i2 = LBOUND(InData%WaveAcc2D0,2), UBOUND(InData%WaveAcc2D0,2) + DO i1 = LBOUND(InData%WaveAcc2D0,1), UBOUND(InData%WaveAcc2D0,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc2D0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP2D0) ) 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%WaveDynP2D0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2D0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP2D0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2D0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP2D0,2), UBOUND(InData%WaveDynP2D0,2) + DO i1 = LBOUND(InData%WaveDynP2D0,1), UBOUND(InData%WaveDynP2D0,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP2D0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc2S0) ) 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%WaveAcc2S0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2S0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc2S0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc2S0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc2S0,3), UBOUND(InData%WaveAcc2S0,3) + DO i2 = LBOUND(InData%WaveAcc2S0,2), UBOUND(InData%WaveAcc2S0,2) + DO i1 = LBOUND(InData%WaveAcc2S0,1), UBOUND(InData%WaveAcc2S0,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc2S0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP2S0) ) 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%WaveDynP2S0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2S0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP2S0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP2S0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP2S0,2), UBOUND(InData%WaveDynP2S0,2) + DO i1 = LBOUND(InData%WaveDynP2S0,1), UBOUND(InData%WaveDynP2S0,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP2S0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel2D0) ) 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%WaveVel2D0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2D0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2D0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2D0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel2D0,3), UBOUND(InData%WaveVel2D0,3) + DO i2 = LBOUND(InData%WaveVel2D0,2), UBOUND(InData%WaveVel2D0,2) + DO i1 = LBOUND(InData%WaveVel2D0,1), UBOUND(InData%WaveVel2D0,1) + ReKiBuf(Re_Xferred) = InData%WaveVel2D0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel2S0) ) 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%WaveVel2S0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2S0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel2S0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel2S0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel2S0,3), UBOUND(InData%WaveVel2S0,3) + DO i2 = LBOUND(InData%WaveVel2S0,2), UBOUND(InData%WaveVel2S0,2) + DO i1 = LBOUND(InData%WaveVel2S0,1), UBOUND(InData%WaveVel2S0,1) + ReKiBuf(Re_Xferred) = InData%WaveVel2S0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE Waves2_PackInitOutput + + SUBROUTINE Waves2_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(Waves2_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevSeries2 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%WaveElevSeries2)) DEALLOCATE(OutData%WaveElevSeries2) + ALLOCATE(OutData%WaveElevSeries2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevSeries2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevSeries2,2), UBOUND(OutData%WaveElevSeries2,2) + DO i1 = LBOUND(OutData%WaveElevSeries2,1), UBOUND(OutData%WaveElevSeries2,1) + OutData%WaveElevSeries2(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc2D 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%WaveAcc2D)) DEALLOCATE(OutData%WaveAcc2D) + ALLOCATE(OutData%WaveAcc2D(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%WaveAcc2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc2D,3), UBOUND(OutData%WaveAcc2D,3) + DO i2 = LBOUND(OutData%WaveAcc2D,2), UBOUND(OutData%WaveAcc2D,2) + DO i1 = LBOUND(OutData%WaveAcc2D,1), UBOUND(OutData%WaveAcc2D,1) + OutData%WaveAcc2D(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 ! WaveDynP2D 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%WaveDynP2D)) DEALLOCATE(OutData%WaveDynP2D) + ALLOCATE(OutData%WaveDynP2D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP2D,2), UBOUND(OutData%WaveDynP2D,2) + DO i1 = LBOUND(OutData%WaveDynP2D,1), UBOUND(OutData%WaveDynP2D,1) + OutData%WaveDynP2D(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc2S 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%WaveAcc2S)) DEALLOCATE(OutData%WaveAcc2S) + ALLOCATE(OutData%WaveAcc2S(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%WaveAcc2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc2S,3), UBOUND(OutData%WaveAcc2S,3) + DO i2 = LBOUND(OutData%WaveAcc2S,2), UBOUND(OutData%WaveAcc2S,2) + DO i1 = LBOUND(OutData%WaveAcc2S,1), UBOUND(OutData%WaveAcc2S,1) + OutData%WaveAcc2S(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 ! WaveDynP2S 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%WaveDynP2S)) DEALLOCATE(OutData%WaveDynP2S) + ALLOCATE(OutData%WaveDynP2S(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP2S,2), UBOUND(OutData%WaveDynP2S,2) + DO i1 = LBOUND(OutData%WaveDynP2S,1), UBOUND(OutData%WaveDynP2S,1) + OutData%WaveDynP2S(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel2D 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%WaveVel2D)) DEALLOCATE(OutData%WaveVel2D) + ALLOCATE(OutData%WaveVel2D(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%WaveVel2D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel2D,3), UBOUND(OutData%WaveVel2D,3) + DO i2 = LBOUND(OutData%WaveVel2D,2), UBOUND(OutData%WaveVel2D,2) + DO i1 = LBOUND(OutData%WaveVel2D,1), UBOUND(OutData%WaveVel2D,1) + OutData%WaveVel2D(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 ! WaveVel2S 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%WaveVel2S)) DEALLOCATE(OutData%WaveVel2S) + ALLOCATE(OutData%WaveVel2S(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%WaveVel2S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel2S,3), UBOUND(OutData%WaveVel2S,3) + DO i2 = LBOUND(OutData%WaveVel2S,2), UBOUND(OutData%WaveVel2S,2) + DO i1 = LBOUND(OutData%WaveVel2S,1), UBOUND(OutData%WaveVel2S,1) + OutData%WaveVel2S(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 ! WaveAcc2D0 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%WaveAcc2D0)) DEALLOCATE(OutData%WaveAcc2D0) + ALLOCATE(OutData%WaveAcc2D0(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%WaveAcc2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc2D0,3), UBOUND(OutData%WaveAcc2D0,3) + DO i2 = LBOUND(OutData%WaveAcc2D0,2), UBOUND(OutData%WaveAcc2D0,2) + DO i1 = LBOUND(OutData%WaveAcc2D0,1), UBOUND(OutData%WaveAcc2D0,1) + OutData%WaveAcc2D0(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 ! WaveDynP2D0 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%WaveDynP2D0)) DEALLOCATE(OutData%WaveDynP2D0) + ALLOCATE(OutData%WaveDynP2D0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP2D0,2), UBOUND(OutData%WaveDynP2D0,2) + DO i1 = LBOUND(OutData%WaveDynP2D0,1), UBOUND(OutData%WaveDynP2D0,1) + OutData%WaveDynP2D0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc2S0 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%WaveAcc2S0)) DEALLOCATE(OutData%WaveAcc2S0) + ALLOCATE(OutData%WaveAcc2S0(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%WaveAcc2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc2S0,3), UBOUND(OutData%WaveAcc2S0,3) + DO i2 = LBOUND(OutData%WaveAcc2S0,2), UBOUND(OutData%WaveAcc2S0,2) + DO i1 = LBOUND(OutData%WaveAcc2S0,1), UBOUND(OutData%WaveAcc2S0,1) + OutData%WaveAcc2S0(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 ! WaveDynP2S0 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%WaveDynP2S0)) DEALLOCATE(OutData%WaveDynP2S0) + ALLOCATE(OutData%WaveDynP2S0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP2S0,2), UBOUND(OutData%WaveDynP2S0,2) + DO i1 = LBOUND(OutData%WaveDynP2S0,1), UBOUND(OutData%WaveDynP2S0,1) + OutData%WaveDynP2S0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel2D0 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%WaveVel2D0)) DEALLOCATE(OutData%WaveVel2D0) + ALLOCATE(OutData%WaveVel2D0(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%WaveVel2D0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel2D0,3), UBOUND(OutData%WaveVel2D0,3) + DO i2 = LBOUND(OutData%WaveVel2D0,2), UBOUND(OutData%WaveVel2D0,2) + DO i1 = LBOUND(OutData%WaveVel2D0,1), UBOUND(OutData%WaveVel2D0,1) + OutData%WaveVel2D0(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 ! WaveVel2S0 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%WaveVel2S0)) DEALLOCATE(OutData%WaveVel2S0) + ALLOCATE(OutData%WaveVel2S0(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%WaveVel2S0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel2S0,3), UBOUND(OutData%WaveVel2S0,3) + DO i2 = LBOUND(OutData%WaveVel2S0,2), UBOUND(OutData%WaveVel2S0,2) + DO i1 = LBOUND(OutData%WaveVel2S0,1), UBOUND(OutData%WaveVel2S0,1) + OutData%WaveVel2S0(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE Waves2_UnPackInitOutput + + SUBROUTINE Waves2_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Waves2_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 = 'Waves2_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Waves2_CopyContState + + SUBROUTINE Waves2_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Waves2_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyContState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 Waves2_PackContState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves2_UnPackContState + + SUBROUTINE Waves2_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Waves2_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 = 'Waves2_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE Waves2_CopyDiscState + + SUBROUTINE Waves2_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Waves2_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyDiscState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 Waves2_PackDiscState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves2_UnPackDiscState + + SUBROUTINE Waves2_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Waves2_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 = 'Waves2_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Waves2_CopyConstrState + + SUBROUTINE Waves2_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Waves2_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyConstrState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 Waves2_PackConstrState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves2_UnPackConstrState + + SUBROUTINE Waves2_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Waves2_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 = 'Waves2_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Waves2_CopyOtherState + + SUBROUTINE Waves2_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Waves2_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyOtherState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_PackOtherState + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_UnPackOtherState + + SUBROUTINE Waves2_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Waves2_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 = 'Waves2_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastIndWave = SrcMiscData%LastIndWave + END SUBROUTINE Waves2_CopyMisc + + SUBROUTINE Waves2_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Waves2_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyMisc + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 ! LastIndWave + 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%LastIndWave + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_PackMisc + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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%LastIndWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_UnPackMisc + + SUBROUTINE Waves2_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Waves2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%WvDiffQTFF = SrcParamData%WvDiffQTFF + DstParamData%WvSumQTFF = SrcParamData%WvSumQTFF + DstParamData%NWaveElev = SrcParamData%NWaveElev + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%NStepWave2 = SrcParamData%NStepWave2 +IF (ALLOCATED(SrcParamData%WaveTime)) THEN + i1_l = LBOUND(SrcParamData%WaveTime,1) + i1_u = UBOUND(SrcParamData%WaveTime,1) + IF (.NOT. ALLOCATED(DstParamData%WaveTime)) THEN + ALLOCATE(DstParamData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveTime = SrcParamData%WaveTime +ENDIF +IF (ALLOCATED(SrcParamData%WaveElev2)) THEN + i1_l = LBOUND(SrcParamData%WaveElev2,1) + i1_u = UBOUND(SrcParamData%WaveElev2,1) + i2_l = LBOUND(SrcParamData%WaveElev2,2) + i2_u = UBOUND(SrcParamData%WaveElev2,2) + IF (.NOT. ALLOCATED(DstParamData%WaveElev2)) THEN + ALLOCATE(DstParamData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev2 = SrcParamData%WaveElev2 +ENDIF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOutAll = SrcParamData%NumOutAll + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt + DstParamData%Delim = SrcParamData%Delim + DstParamData%UnOutFile = SrcParamData%UnOutFile + END SUBROUTINE Waves2_CopyParam + + SUBROUTINE Waves2_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Waves2_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%WaveTime)) THEN + DEALLOCATE(ParamData%WaveTime) +ENDIF +IF (ALLOCATED(ParamData%WaveElev2)) THEN + DEALLOCATE(ParamData%WaveElev2) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE Waves2_DestroyParam + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! WvDiffQTFF + Int_BufSz = Int_BufSz + 1 ! WvSumQTFF + Int_BufSz = Int_BufSz + 1 ! NWaveElev + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NStepWave2 + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev2 allocated yes/no + IF ( ALLOCATED(InData%WaveElev2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev2) ! WaveElev2 + END IF + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOutAll + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UnOutFile + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WvDiffQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WvSumQTFF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NWaveElev + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave2 + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev2) ) 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%WaveElev2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev2,2), UBOUND(InData%WaveElev2,2) + DO i1 = LBOUND(InData%WaveElev2,1), UBOUND(InData%WaveElev2,1) + ReKiBuf(Re_Xferred) = InData%WaveElev2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + 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 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOutAll + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%UnOutFile + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_PackParam + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WvDiffQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%WvDiffQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%WvSumQTFF = TRANSFER(IntKiBuf(Int_Xferred), OutData%WvSumQTFF) + Int_Xferred = Int_Xferred + 1 + OutData%NWaveElev = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev2 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%WaveElev2)) DEALLOCATE(OutData%WaveElev2) + ALLOCATE(OutData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev2,2), UBOUND(OutData%WaveElev2,2) + DO i1 = LBOUND(OutData%WaveElev2,1), UBOUND(OutData%WaveElev2,1) + OutData%WaveElev2(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOutAll = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UnOutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves2_UnPackParam + + SUBROUTINE Waves2_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_InputType), INTENT(IN) :: SrcInputData + TYPE(Waves2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%DummyInput = SrcInputData%DummyInput + END SUBROUTINE Waves2_CopyInput + + SUBROUTINE Waves2_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Waves2_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves2_DestroyInput + + SUBROUTINE Waves2_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(Waves2_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 = 'Waves2_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 + Re_BufSz = Re_BufSz + 1 ! DummyInput + 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%DummyInput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves2_PackInput + + SUBROUTINE Waves2_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(Waves2_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_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 + OutData%DummyInput = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves2_UnPackInput + + SUBROUTINE Waves2_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves2_OutputType), INTENT(IN) :: SrcOutputData + TYPE(Waves2_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Waves2_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE Waves2_CopyOutput + + SUBROUTINE Waves2_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Waves2_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE Waves2_DestroyOutput + + SUBROUTINE Waves2_PackOutput( 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(Waves2_OutputType), 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 = 'Waves2_PackOutput' + ! 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 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Waves2_PackOutput + + SUBROUTINE Waves2_UnPackOutput( 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(Waves2_OutputType), 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 = 'Waves2_UnPackOutput' + ! 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Waves2_UnPackOutput + + + SUBROUTINE Waves2_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Waves2_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Waves2_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Waves2_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Waves2_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Waves2_Input_ExtrapInterp + + + SUBROUTINE Waves2_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%DummyInput - u2%DummyInput) + u_out%DummyInput = u1%DummyInput + b * ScaleFactor + END SUBROUTINE Waves2_Input_ExtrapInterp1 + + + SUBROUTINE Waves2_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Waves2_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%DummyInput - u2%DummyInput) + t(2)**2*(-u1%DummyInput + u3%DummyInput))* scaleFactor + c = ( (t(2)-t(3))*u1%DummyInput + t(3)*u2%DummyInput - t(2)*u3%DummyInput ) * scaleFactor + u_out%DummyInput = u1%DummyInput + b + c * t_out + END SUBROUTINE Waves2_Input_ExtrapInterp2 + + + SUBROUTINE Waves2_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Waves2_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Waves2_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Waves2_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Waves2_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Waves2_Output_ExtrapInterp + + + SUBROUTINE Waves2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE Waves2_Output_ExtrapInterp1 + + + SUBROUTINE Waves2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves2_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE Waves2_Output_ExtrapInterp2 + +END MODULE Waves2_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/hydrodyn/src/Waves_Types.f90 b/OpenFAST/modules/hydrodyn/src/Waves_Types.f90 new file mode 100644 index 000000000..9b98fdc94 --- /dev/null +++ b/OpenFAST/modules/hydrodyn/src/Waves_Types.f90 @@ -0,0 +1,3460 @@ +!STARTOFREGISTRYGENERATEDFILE 'Waves_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 +!********************************************************************************************************************************* +! Waves_Types +!................................................................................................................................. +! This file is part of Waves. +! +! 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 Waves. 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 Waves_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Waves_InitInputType ======= + TYPE, PUBLIC :: Waves_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + CHARACTER(1024) :: DirRoot !< The name of the root file including the full path. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. [-] + CHARACTER(1024) :: WvKinFile !< The root name of user input wave kinematics files [-] + LOGICAL :: WriteWvKin !< Flag indicating whether we are going to write out kinematics files. [Must be FALSE if WaveMod = 5 or 6, if TRUE then WvKinFile must have a string value and this is the rootname for all the output files] [-] + INTEGER(IntKi) :: UnSum !< The unit number for the HydroDyn summary file [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [(m/s^2)] + REAL(ReKi) :: MSL2SWL !< Offset between still-water level and mean sea level [positive upward; must be zero if using WAMIT] [(meters)] + REAL(SiKi) :: WvLowCOff !< Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4] [(rad/s)] + REAL(SiKi) :: WvHiCOff !< High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed. [used only when WaveMod=2,3,4] [(rad/s)] + REAL(SiKi) :: WaveDir !< Mean incident wave propagation heading direction [(degrees)] + INTEGER(IntKi) :: WaveNDir !< Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module] [(-)] + LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] + INTEGER(IntKi) :: WaveDirMod !< Directional wave spreading function {0: none, 1: COS2S} [only used if WaveMod=6] [-] + REAL(SiKi) :: WaveDirSpread !< Spreading coefficient [WaveMod=2,3,4 and WaveDirMod=1] [-] + REAL(SiKi) :: WaveDirRange !< Range of wave directions (full range: WaveDir +/- WaveDirRange/2) [only used if WaveMod=6] [(degrees)] + REAL(DbKi) :: WaveDT !< Time step for incident wave calculations [(sec)] + REAL(SiKi) :: WaveHs !< Significant wave height of incident waves [(meters)] + INTEGER(IntKi) :: WaveMod !< Incident wave kinematics model {0: none=still water, 1: plane progressive (regular), 2: JONSWAP/Pierson-Moskowitz spectrum (irregular), 3: white-noise spectrum, 4: user-defind spectrum from routine UserWaveSpctrm (irregular), 5: GH BLADED } [-] + CHARACTER(80) :: WaveModChr !< String to temporarially hold the value of the wave kinematics input line [-] + LOGICAL :: WaveNDAmp !< Flag for normally-distributed amplitudes in incident waves spectrum [flag] [-] + REAL(SiKi) :: WavePhase !< Specified phase for regular waves [(radians)] + REAL(SiKi) :: WavePkShp !< Peak shape parameter of incident wave spectrum [1.0 for Pierson-Moskowitz] [-] + CHARACTER(80) :: WavePkShpChr !< String to temporarially hold value of peak shape parameter input line [-] + INTEGER(IntKi) , DIMENSION(1:2) :: WaveSeed !< Random seeds of incident waves [-2147483648 to 2147483647] [-] + INTEGER(IntKi) :: WaveStMod !< Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching} [-] + REAL(DbKi) :: WaveTMax !< Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT [(sec)] + REAL(SiKi) :: WaveTp !< Peak spectral period of incident waves [(sec)] + REAL(SiKi) :: WtrDens !< Water density [(kg/m^3)] + REAL(SiKi) :: WtrDpth !< Water depth [(meters)] + INTEGER(IntKi) :: NWaveElev !< Number of points where the incident wave elevations can be output [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElevxi !< xi-coordinates for points where the incident wave elevations can be output [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElevyi !< yi-coordinates for points where the incident wave elevations can be output [(meters)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< Supplied by Driver: X-Y locations for WaveElevation output (for visualization). Index 1 corresponds to X or Y coordinate. Index 2 corresponds to point number. [-] + INTEGER(IntKi) :: NWaveKin !< Number of points where the incident wave kinematics will be computed [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinxi !< xi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinyi !< yi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinzi !< zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean sea level [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: CurrVxi !< xi-component of the current velocity at elevation i [(m/s)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: CurrVyi !< yi-component of the current velocity at elevation i [(m/s)] + REAL(SiKi) :: PCurrVxiPz0 !< xi-component of the partial derivative of the current velocity at elevation near mean sea level [(m/s)] + REAL(SiKi) :: PCurrVyiPz0 !< yi-component of the partial derivative of the current velocity at elevation near mean sea level [(m/s)] + TYPE(NWTC_RandomNumber_ParameterType) :: RNG !< Parameters for the pseudo random number generator [-] + END TYPE Waves_InitInputType +! ======================= +! ========= Waves_InitOutputType ======= + TYPE, PUBLIC :: Waves_InitOutputType + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevC0 !< Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveDirArr !< Wave direction array. Each frequency has a unique direction of WaveNDir > 1 [(degrees)] + REAL(SiKi) :: WaveDirMin !< Minimum wave direction. [(degrees)] + REAL(SiKi) :: WaveDirMax !< Maximum wave direction. [(degrees)] + REAL(SiKi) :: WaveDir !< Incident wave propagation heading direction [(degrees)] + INTEGER(IntKi) :: WaveNDir !< Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module] [(-)] + LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] + REAL(SiKi) :: WaveDOmega !< Frequency step for incident wave calculations [(rad/s)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveKinzi !< zi-coordinates for points where the incident wave kinematics will be computed; these are relative to the mean see level [(meters)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: PWaveDynP0 !< Instantaneous dynamic pressure of incident waves , at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP !< Instantaneous dynamic pressure of incident waves , accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed [(N/m^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc !< Instantaneous acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: PWaveAcc0 !< Instantaneous acceleration of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed [(m/s^2)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< Instantaneous velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, accounting for stretching, at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.) [(m/s)] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: PWaveVel0 !< Instantaneous velocity of incident waves in the xi- (1), yi- (2), and zi- (3) directions, respectively, at the location (xi,yi,0), at each of the NWaveKin points where the incident wave kinematics will be computed (The values include both the velocity of incident waves and the velocity of current.) [(m/s)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< Instantaneous elevation time-series of incident waves at each of the NWaveElev points where the incident wave elevations can be output [(meters)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Instantaneous elevation time-series of incident waves at the platform reference point [(meters)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevSeries !< Instantaneous elevation time-series at each of the points given by WaveElevXY. Used for making movies of the waves. First index is the timestep. Second index is XY point number corresponding to second index of WaveElevXY. [(m)] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous elevation of, velocity of, acceleration of, and loads associated with the incident waves are determined [(sec)] + REAL(DbKi) :: WaveTMax !< Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT [(sec)] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] + REAL(SiKi) :: RhoXg !< = WtrDens*Gravity [-] + INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] + INTEGER(IntKi) :: NStepWave2 !< NStepWave / 2 [-] + END TYPE Waves_InitOutputType +! ======================= +! ========= Waves_ContinuousStateType ======= + TYPE, PUBLIC :: Waves_ContinuousStateType + REAL(SiKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Waves_ContinuousStateType +! ======================= +! ========= Waves_DiscreteStateType ======= + TYPE, PUBLIC :: Waves_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE Waves_DiscreteStateType +! ======================= +! ========= Waves_ConstraintStateType ======= + TYPE, PUBLIC :: Waves_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Waves_ConstraintStateType +! ======================= +! ========= Waves_OtherStateType ======= + TYPE, PUBLIC :: Waves_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE Waves_OtherStateType +! ======================= +! ========= Waves_MiscVarType ======= + TYPE, PUBLIC :: Waves_MiscVarType + INTEGER(IntKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE Waves_MiscVarType +! ======================= +! ========= Waves_ParameterType ======= + TYPE, PUBLIC :: Waves_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + REAL(DbKi) :: WaveTMax !< Analysis time for incident wave calculations; the actual analysis time may be larger than this value in order for the maintain an effecient FFT [(sec)] + INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] + INTEGER(IntKi) :: WaveNDir !< Number of wave directions [only used if WaveDirMod = 1] [Must be an odd number -- will be adjusted within the waves module] [(-)] + LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] + END TYPE Waves_ParameterType +! ======================= +! ========= Waves_InputType ======= + TYPE, PUBLIC :: Waves_InputType + REAL(SiKi) :: DummyInput !< Remove this variable if you have input data [-] + END TYPE Waves_InputType +! ======================= +! ========= Waves_OutputType ======= + TYPE, PUBLIC :: Waves_OutputType + REAL(SiKi) :: DummyOutput !< Remove this variable if you have output data [-] + END TYPE Waves_OutputType +! ======================= +CONTAINS + SUBROUTINE Waves_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Waves_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%DirRoot = SrcInitInputData%DirRoot + DstInitInputData%WvKinFile = SrcInitInputData%WvKinFile + DstInitInputData%WriteWvKin = SrcInitInputData%WriteWvKin + DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL + DstInitInputData%WvLowCOff = SrcInitInputData%WvLowCOff + DstInitInputData%WvHiCOff = SrcInitInputData%WvHiCOff + DstInitInputData%WaveDir = SrcInitInputData%WaveDir + DstInitInputData%WaveNDir = SrcInitInputData%WaveNDir + DstInitInputData%WaveMultiDir = SrcInitInputData%WaveMultiDir + DstInitInputData%WaveDirMod = SrcInitInputData%WaveDirMod + DstInitInputData%WaveDirSpread = SrcInitInputData%WaveDirSpread + DstInitInputData%WaveDirRange = SrcInitInputData%WaveDirRange + DstInitInputData%WaveDT = SrcInitInputData%WaveDT + DstInitInputData%WaveHs = SrcInitInputData%WaveHs + DstInitInputData%WaveMod = SrcInitInputData%WaveMod + DstInitInputData%WaveModChr = SrcInitInputData%WaveModChr + DstInitInputData%WaveNDAmp = SrcInitInputData%WaveNDAmp + DstInitInputData%WavePhase = SrcInitInputData%WavePhase + DstInitInputData%WavePkShp = SrcInitInputData%WavePkShp + DstInitInputData%WavePkShpChr = SrcInitInputData%WavePkShpChr + DstInitInputData%WaveSeed = SrcInitInputData%WaveSeed + DstInitInputData%WaveStMod = SrcInitInputData%WaveStMod + DstInitInputData%WaveTMax = SrcInitInputData%WaveTMax + DstInitInputData%WaveTp = SrcInitInputData%WaveTp + DstInitInputData%WtrDens = SrcInitInputData%WtrDens + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%NWaveElev = SrcInitInputData%NWaveElev +IF (ALLOCATED(SrcInitInputData%WaveElevxi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevxi,1) + i1_u = UBOUND(SrcInitInputData%WaveElevxi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevxi)) THEN + ALLOCATE(DstInitInputData%WaveElevxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevxi = SrcInitInputData%WaveElevxi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevyi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevyi,1) + i1_u = UBOUND(SrcInitInputData%WaveElevyi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevyi)) THEN + ALLOCATE(DstInitInputData%WaveElevyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevyi = SrcInitInputData%WaveElevyi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveElevXY)) THEN + i1_l = LBOUND(SrcInitInputData%WaveElevXY,1) + i1_u = UBOUND(SrcInitInputData%WaveElevXY,1) + i2_l = LBOUND(SrcInitInputData%WaveElevXY,2) + i2_u = UBOUND(SrcInitInputData%WaveElevXY,2) + IF (.NOT. ALLOCATED(DstInitInputData%WaveElevXY)) THEN + ALLOCATE(DstInitInputData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveElevXY = SrcInitInputData%WaveElevXY +ENDIF + DstInitInputData%NWaveKin = SrcInitInputData%NWaveKin +IF (ALLOCATED(SrcInitInputData%WaveKinxi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinxi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinxi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinxi)) THEN + ALLOCATE(DstInitInputData%WaveKinxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinxi = SrcInitInputData%WaveKinxi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveKinyi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinyi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinyi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinyi)) THEN + ALLOCATE(DstInitInputData%WaveKinyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinyi = SrcInitInputData%WaveKinyi +ENDIF +IF (ALLOCATED(SrcInitInputData%WaveKinzi)) THEN + i1_l = LBOUND(SrcInitInputData%WaveKinzi,1) + i1_u = UBOUND(SrcInitInputData%WaveKinzi,1) + IF (.NOT. ALLOCATED(DstInitInputData%WaveKinzi)) THEN + ALLOCATE(DstInitInputData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%WaveKinzi = SrcInitInputData%WaveKinzi +ENDIF +IF (ALLOCATED(SrcInitInputData%CurrVxi)) THEN + i1_l = LBOUND(SrcInitInputData%CurrVxi,1) + i1_u = UBOUND(SrcInitInputData%CurrVxi,1) + IF (.NOT. ALLOCATED(DstInitInputData%CurrVxi)) THEN + ALLOCATE(DstInitInputData%CurrVxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CurrVxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%CurrVxi = SrcInitInputData%CurrVxi +ENDIF +IF (ALLOCATED(SrcInitInputData%CurrVyi)) THEN + i1_l = LBOUND(SrcInitInputData%CurrVyi,1) + i1_u = UBOUND(SrcInitInputData%CurrVyi,1) + IF (.NOT. ALLOCATED(DstInitInputData%CurrVyi)) THEN + ALLOCATE(DstInitInputData%CurrVyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CurrVyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%CurrVyi = SrcInitInputData%CurrVyi +ENDIF + DstInitInputData%PCurrVxiPz0 = SrcInitInputData%PCurrVxiPz0 + DstInitInputData%PCurrVyiPz0 = SrcInitInputData%PCurrVyiPz0 + CALL NWTC_Library_Copynwtc_randomnumber_parametertype( SrcInitInputData%RNG, DstInitInputData%RNG, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE Waves_CopyInitInput + + SUBROUTINE Waves_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Waves_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%WaveElevxi)) THEN + DEALLOCATE(InitInputData%WaveElevxi) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevyi)) THEN + DEALLOCATE(InitInputData%WaveElevyi) +ENDIF +IF (ALLOCATED(InitInputData%WaveElevXY)) THEN + DEALLOCATE(InitInputData%WaveElevXY) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinxi)) THEN + DEALLOCATE(InitInputData%WaveKinxi) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinyi)) THEN + DEALLOCATE(InitInputData%WaveKinyi) +ENDIF +IF (ALLOCATED(InitInputData%WaveKinzi)) THEN + DEALLOCATE(InitInputData%WaveKinzi) +ENDIF +IF (ALLOCATED(InitInputData%CurrVxi)) THEN + DEALLOCATE(InitInputData%CurrVxi) +ENDIF +IF (ALLOCATED(InitInputData%CurrVyi)) THEN + DEALLOCATE(InitInputData%CurrVyi) +ENDIF + CALL NWTC_Library_Destroynwtc_randomnumber_parametertype( InitInputData%RNG, ErrStat, ErrMsg ) + END SUBROUTINE Waves_DestroyInitInput + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%DirRoot) ! DirRoot + Int_BufSz = Int_BufSz + 1*LEN(InData%WvKinFile) ! WvKinFile + Int_BufSz = Int_BufSz + 1 ! WriteWvKin + Int_BufSz = Int_BufSz + 1 ! UnSum + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! MSL2SWL + Re_BufSz = Re_BufSz + 1 ! WvLowCOff + Re_BufSz = Re_BufSz + 1 ! WvHiCOff + Re_BufSz = Re_BufSz + 1 ! WaveDir + Int_BufSz = Int_BufSz + 1 ! WaveNDir + Int_BufSz = Int_BufSz + 1 ! WaveMultiDir + Int_BufSz = Int_BufSz + 1 ! WaveDirMod + Re_BufSz = Re_BufSz + 1 ! WaveDirSpread + Re_BufSz = Re_BufSz + 1 ! WaveDirRange + Db_BufSz = Db_BufSz + 1 ! WaveDT + Re_BufSz = Re_BufSz + 1 ! WaveHs + Int_BufSz = Int_BufSz + 1 ! WaveMod + Int_BufSz = Int_BufSz + 1*LEN(InData%WaveModChr) ! WaveModChr + Int_BufSz = Int_BufSz + 1 ! WaveNDAmp + Re_BufSz = Re_BufSz + 1 ! WavePhase + Re_BufSz = Re_BufSz + 1 ! WavePkShp + Int_BufSz = Int_BufSz + 1*LEN(InData%WavePkShpChr) ! WavePkShpChr + Int_BufSz = Int_BufSz + SIZE(InData%WaveSeed) ! WaveSeed + Int_BufSz = Int_BufSz + 1 ! WaveStMod + Db_BufSz = Db_BufSz + 1 ! WaveTMax + Re_BufSz = Re_BufSz + 1 ! WaveTp + Re_BufSz = Re_BufSz + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Int_BufSz = Int_BufSz + 1 ! NWaveElev + Int_BufSz = Int_BufSz + 1 ! WaveElevxi allocated yes/no + IF ( ALLOCATED(InData%WaveElevxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElevxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevxi) ! WaveElevxi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevyi allocated yes/no + IF ( ALLOCATED(InData%WaveElevyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElevyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevyi) ! WaveElevyi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevXY allocated yes/no + IF ( ALLOCATED(InData%WaveElevXY) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevXY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevXY) ! WaveElevXY + END IF + Int_BufSz = Int_BufSz + 1 ! NWaveKin + Int_BufSz = Int_BufSz + 1 ! WaveKinxi allocated yes/no + IF ( ALLOCATED(InData%WaveKinxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinxi) ! WaveKinxi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveKinyi allocated yes/no + IF ( ALLOCATED(InData%WaveKinyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinyi) ! WaveKinyi + END IF + Int_BufSz = Int_BufSz + 1 ! WaveKinzi allocated yes/no + IF ( ALLOCATED(InData%WaveKinzi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinzi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinzi) ! WaveKinzi + END IF + Int_BufSz = Int_BufSz + 1 ! CurrVxi allocated yes/no + IF ( ALLOCATED(InData%CurrVxi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CurrVxi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CurrVxi) ! CurrVxi + END IF + Int_BufSz = Int_BufSz + 1 ! CurrVyi allocated yes/no + IF ( ALLOCATED(InData%CurrVyi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CurrVyi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CurrVyi) ! CurrVyi + END IF + Re_BufSz = Re_BufSz + 1 ! PCurrVxiPz0 + Re_BufSz = Re_BufSz + 1 ! PCurrVyiPz0 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! RNG: size of buffers for each call to pack subtype + CALL NWTC_Library_Packnwtc_randomnumber_parametertype( Re_Buf, Db_Buf, Int_Buf, InData%RNG, ErrStat2, ErrMsg2, .TRUE. ) ! RNG + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! RNG + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! RNG + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! RNG + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DirRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%DirRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%WvKinFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%WvKinFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%WriteWvKin, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvLowCOff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WvHiCOff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveNDir + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveMultiDir, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveDirMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDirSpread + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDirRange + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%WaveDT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveHs + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveMod + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%WaveModChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WaveModChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveNDAmp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WavePhase + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WavePkShp + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%WavePkShpChr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WavePkShpChr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%WaveSeed,1), UBOUND(InData%WaveSeed,1) + IntKiBuf(Int_Xferred) = InData%WaveSeed(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%WaveStMod + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%WaveTMax + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveTp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NWaveElev + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveElevxi) ) 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%WaveElevxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElevxi,1), UBOUND(InData%WaveElevxi,1) + ReKiBuf(Re_Xferred) = InData%WaveElevxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevyi) ) 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%WaveElevyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElevyi,1), UBOUND(InData%WaveElevyi,1) + ReKiBuf(Re_Xferred) = InData%WaveElevyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevXY) ) 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%WaveElevXY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevXY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevXY,2), UBOUND(InData%WaveElevXY,2) + DO i1 = LBOUND(InData%WaveElevXY,1), UBOUND(InData%WaveElevXY,1) + ReKiBuf(Re_Xferred) = InData%WaveElevXY(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NWaveKin + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveKinxi) ) 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%WaveKinxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinxi,1), UBOUND(InData%WaveKinxi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveKinyi) ) 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%WaveKinyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinyi,1), UBOUND(InData%WaveKinyi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveKinzi) ) 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%WaveKinzi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinzi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinzi,1), UBOUND(InData%WaveKinzi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinzi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CurrVxi) ) 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%CurrVxi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CurrVxi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CurrVxi,1), UBOUND(InData%CurrVxi,1) + ReKiBuf(Re_Xferred) = InData%CurrVxi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CurrVyi) ) 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%CurrVyi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CurrVyi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CurrVyi,1), UBOUND(InData%CurrVyi,1) + ReKiBuf(Re_Xferred) = InData%CurrVyi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%PCurrVxiPz0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PCurrVyiPz0 + Re_Xferred = Re_Xferred + 1 + CALL NWTC_Library_Packnwtc_randomnumber_parametertype( Re_Buf, Db_Buf, Int_Buf, InData%RNG, ErrStat2, ErrMsg2, OnlySize ) ! RNG + 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 Waves_PackInitInput + + SUBROUTINE Waves_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(Waves_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DirRoot) + OutData%DirRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%WvKinFile) + OutData%WvKinFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WriteWvKin = TRANSFER(IntKiBuf(Int_Xferred), OutData%WriteWvKin) + Int_Xferred = Int_Xferred + 1 + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MSL2SWL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WvLowCOff = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WvHiCOff = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveNDir = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveMultiDir = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveMultiDir) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDirMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDirSpread = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDirRange = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WaveHs = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%WaveModChr) + OutData%WaveModChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WaveNDAmp = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveNDAmp) + Int_Xferred = Int_Xferred + 1 + OutData%WavePhase = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WavePkShp = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%WavePkShpChr) + OutData%WavePkShpChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%WaveSeed,1) + i1_u = UBOUND(OutData%WaveSeed,1) + DO i1 = LBOUND(OutData%WaveSeed,1), UBOUND(OutData%WaveSeed,1) + OutData%WaveSeed(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%WaveStMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveTMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WaveTp = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%NWaveElev = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevxi 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%WaveElevxi)) DEALLOCATE(OutData%WaveElevxi) + ALLOCATE(OutData%WaveElevxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElevxi,1), UBOUND(OutData%WaveElevxi,1) + OutData%WaveElevxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevyi 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%WaveElevyi)) DEALLOCATE(OutData%WaveElevyi) + ALLOCATE(OutData%WaveElevyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElevyi,1), UBOUND(OutData%WaveElevyi,1) + OutData%WaveElevyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevXY 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%WaveElevXY)) DEALLOCATE(OutData%WaveElevXY) + ALLOCATE(OutData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevXY,2), UBOUND(OutData%WaveElevXY,2) + DO i1 = LBOUND(OutData%WaveElevXY,1), UBOUND(OutData%WaveElevXY,1) + OutData%WaveElevXY(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%NWaveKin = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinxi 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%WaveKinxi)) DEALLOCATE(OutData%WaveKinxi) + ALLOCATE(OutData%WaveKinxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinxi,1), UBOUND(OutData%WaveKinxi,1) + OutData%WaveKinxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinyi 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%WaveKinyi)) DEALLOCATE(OutData%WaveKinyi) + ALLOCATE(OutData%WaveKinyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinyi,1), UBOUND(OutData%WaveKinyi,1) + OutData%WaveKinyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinzi 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%WaveKinzi)) DEALLOCATE(OutData%WaveKinzi) + ALLOCATE(OutData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinzi,1), UBOUND(OutData%WaveKinzi,1) + OutData%WaveKinzi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CurrVxi 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%CurrVxi)) DEALLOCATE(OutData%CurrVxi) + ALLOCATE(OutData%CurrVxi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CurrVxi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CurrVxi,1), UBOUND(OutData%CurrVxi,1) + OutData%CurrVxi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CurrVyi 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%CurrVyi)) DEALLOCATE(OutData%CurrVyi) + ALLOCATE(OutData%CurrVyi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CurrVyi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CurrVyi,1), UBOUND(OutData%CurrVyi,1) + OutData%CurrVyi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%PCurrVxiPz0 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%PCurrVyiPz0 = REAL(ReKiBuf(Re_Xferred), SiKi) + 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 NWTC_Library_Unpacknwtc_randomnumber_parametertype( Re_Buf, Db_Buf, Int_Buf, OutData%RNG, ErrStat2, ErrMsg2 ) ! RNG + 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 Waves_UnPackInitInput + + SUBROUTINE Waves_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Waves_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WaveElevC0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElevC0,1) + i1_u = UBOUND(SrcInitOutputData%WaveElevC0,1) + i2_l = LBOUND(SrcInitOutputData%WaveElevC0,2) + i2_u = UBOUND(SrcInitOutputData%WaveElevC0,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElevC0)) THEN + ALLOCATE(DstInitOutputData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElevC0 = SrcInitOutputData%WaveElevC0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDirArr)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDirArr,1) + i1_u = UBOUND(SrcInitOutputData%WaveDirArr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDirArr)) THEN + ALLOCATE(DstInitOutputData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDirArr = SrcInitOutputData%WaveDirArr +ENDIF + DstInitOutputData%WaveDirMin = SrcInitOutputData%WaveDirMin + DstInitOutputData%WaveDirMax = SrcInitOutputData%WaveDirMax + DstInitOutputData%WaveDir = SrcInitOutputData%WaveDir + DstInitOutputData%WaveNDir = SrcInitOutputData%WaveNDir + DstInitOutputData%WaveMultiDir = SrcInitOutputData%WaveMultiDir + DstInitOutputData%WaveDOmega = SrcInitOutputData%WaveDOmega +IF (ALLOCATED(SrcInitOutputData%WaveKinzi)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveKinzi,1) + i1_u = UBOUND(SrcInitOutputData%WaveKinzi,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveKinzi)) THEN + ALLOCATE(DstInitOutputData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveKinzi = SrcInitOutputData%WaveKinzi +ENDIF +IF (ALLOCATED(SrcInitOutputData%PWaveDynP0)) THEN + i1_l = LBOUND(SrcInitOutputData%PWaveDynP0,1) + i1_u = UBOUND(SrcInitOutputData%PWaveDynP0,1) + i2_l = LBOUND(SrcInitOutputData%PWaveDynP0,2) + i2_u = UBOUND(SrcInitOutputData%PWaveDynP0,2) + IF (.NOT. ALLOCATED(DstInitOutputData%PWaveDynP0)) THEN + ALLOCATE(DstInitOutputData%PWaveDynP0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%PWaveDynP0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%PWaveDynP0 = SrcInitOutputData%PWaveDynP0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveDynP)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveDynP,1) + i1_u = UBOUND(SrcInitOutputData%WaveDynP,1) + i2_l = LBOUND(SrcInitOutputData%WaveDynP,2) + i2_u = UBOUND(SrcInitOutputData%WaveDynP,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveDynP)) THEN + ALLOCATE(DstInitOutputData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveDynP = SrcInitOutputData%WaveDynP +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveAcc)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveAcc,1) + i1_u = UBOUND(SrcInitOutputData%WaveAcc,1) + i2_l = LBOUND(SrcInitOutputData%WaveAcc,2) + i2_u = UBOUND(SrcInitOutputData%WaveAcc,2) + i3_l = LBOUND(SrcInitOutputData%WaveAcc,3) + i3_u = UBOUND(SrcInitOutputData%WaveAcc,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveAcc)) THEN + ALLOCATE(DstInitOutputData%WaveAcc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveAcc = SrcInitOutputData%WaveAcc +ENDIF +IF (ALLOCATED(SrcInitOutputData%PWaveAcc0)) THEN + i1_l = LBOUND(SrcInitOutputData%PWaveAcc0,1) + i1_u = UBOUND(SrcInitOutputData%PWaveAcc0,1) + i2_l = LBOUND(SrcInitOutputData%PWaveAcc0,2) + i2_u = UBOUND(SrcInitOutputData%PWaveAcc0,2) + i3_l = LBOUND(SrcInitOutputData%PWaveAcc0,3) + i3_u = UBOUND(SrcInitOutputData%PWaveAcc0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%PWaveAcc0)) THEN + ALLOCATE(DstInitOutputData%PWaveAcc0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%PWaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%PWaveAcc0 = SrcInitOutputData%PWaveAcc0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveVel)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveVel,1) + i1_u = UBOUND(SrcInitOutputData%WaveVel,1) + i2_l = LBOUND(SrcInitOutputData%WaveVel,2) + i2_u = UBOUND(SrcInitOutputData%WaveVel,2) + i3_l = LBOUND(SrcInitOutputData%WaveVel,3) + i3_u = UBOUND(SrcInitOutputData%WaveVel,3) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveVel)) THEN + ALLOCATE(DstInitOutputData%WaveVel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveVel = SrcInitOutputData%WaveVel +ENDIF +IF (ALLOCATED(SrcInitOutputData%PWaveVel0)) THEN + i1_l = LBOUND(SrcInitOutputData%PWaveVel0,1) + i1_u = UBOUND(SrcInitOutputData%PWaveVel0,1) + i2_l = LBOUND(SrcInitOutputData%PWaveVel0,2) + i2_u = UBOUND(SrcInitOutputData%PWaveVel0,2) + i3_l = LBOUND(SrcInitOutputData%PWaveVel0,3) + i3_u = UBOUND(SrcInitOutputData%PWaveVel0,3) + IF (.NOT. ALLOCATED(DstInitOutputData%PWaveVel0)) THEN + ALLOCATE(DstInitOutputData%PWaveVel0(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%PWaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%PWaveVel0 = SrcInitOutputData%PWaveVel0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveElev)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElev,1) + i1_u = UBOUND(SrcInitOutputData%WaveElev,1) + i2_l = LBOUND(SrcInitOutputData%WaveElev,2) + i2_u = UBOUND(SrcInitOutputData%WaveElev,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElev)) THEN + ALLOCATE(DstInitOutputData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElev = SrcInitOutputData%WaveElev +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveElev0)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElev0,1) + i1_u = UBOUND(SrcInitOutputData%WaveElev0,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElev0)) THEN + ALLOCATE(DstInitOutputData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElev0 = SrcInitOutputData%WaveElev0 +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveElevSeries)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveElevSeries,1) + i1_u = UBOUND(SrcInitOutputData%WaveElevSeries,1) + i2_l = LBOUND(SrcInitOutputData%WaveElevSeries,2) + i2_u = UBOUND(SrcInitOutputData%WaveElevSeries,2) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveElevSeries)) THEN + ALLOCATE(DstInitOutputData%WaveElevSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveElevSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveElevSeries = SrcInitOutputData%WaveElevSeries +ENDIF +IF (ALLOCATED(SrcInitOutputData%WaveTime)) THEN + i1_l = LBOUND(SrcInitOutputData%WaveTime,1) + i1_u = UBOUND(SrcInitOutputData%WaveTime,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WaveTime)) THEN + ALLOCATE(DstInitOutputData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WaveTime = SrcInitOutputData%WaveTime +ENDIF + DstInitOutputData%WaveTMax = SrcInitOutputData%WaveTMax +IF (ALLOCATED(SrcInitOutputData%nodeInWater)) THEN + i1_l = LBOUND(SrcInitOutputData%nodeInWater,1) + i1_u = UBOUND(SrcInitOutputData%nodeInWater,1) + i2_l = LBOUND(SrcInitOutputData%nodeInWater,2) + i2_u = UBOUND(SrcInitOutputData%nodeInWater,2) + IF (.NOT. ALLOCATED(DstInitOutputData%nodeInWater)) THEN + ALLOCATE(DstInitOutputData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%nodeInWater = SrcInitOutputData%nodeInWater +ENDIF + DstInitOutputData%RhoXg = SrcInitOutputData%RhoXg + DstInitOutputData%NStepWave = SrcInitOutputData%NStepWave + DstInitOutputData%NStepWave2 = SrcInitOutputData%NStepWave2 + END SUBROUTINE Waves_CopyInitOutput + + SUBROUTINE Waves_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Waves_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WaveElevC0)) THEN + DEALLOCATE(InitOutputData%WaveElevC0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDirArr)) THEN + DEALLOCATE(InitOutputData%WaveDirArr) +ENDIF +IF (ALLOCATED(InitOutputData%WaveKinzi)) THEN + DEALLOCATE(InitOutputData%WaveKinzi) +ENDIF +IF (ALLOCATED(InitOutputData%PWaveDynP0)) THEN + DEALLOCATE(InitOutputData%PWaveDynP0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveDynP)) THEN + DEALLOCATE(InitOutputData%WaveDynP) +ENDIF +IF (ALLOCATED(InitOutputData%WaveAcc)) THEN + DEALLOCATE(InitOutputData%WaveAcc) +ENDIF +IF (ALLOCATED(InitOutputData%PWaveAcc0)) THEN + DEALLOCATE(InitOutputData%PWaveAcc0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveVel)) THEN + DEALLOCATE(InitOutputData%WaveVel) +ENDIF +IF (ALLOCATED(InitOutputData%PWaveVel0)) THEN + DEALLOCATE(InitOutputData%PWaveVel0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveElev)) THEN + DEALLOCATE(InitOutputData%WaveElev) +ENDIF +IF (ALLOCATED(InitOutputData%WaveElev0)) THEN + DEALLOCATE(InitOutputData%WaveElev0) +ENDIF +IF (ALLOCATED(InitOutputData%WaveElevSeries)) THEN + DEALLOCATE(InitOutputData%WaveElevSeries) +ENDIF +IF (ALLOCATED(InitOutputData%WaveTime)) THEN + DEALLOCATE(InitOutputData%WaveTime) +ENDIF +IF (ALLOCATED(InitOutputData%nodeInWater)) THEN + DEALLOCATE(InitOutputData%nodeInWater) +ENDIF + END SUBROUTINE Waves_DestroyInitOutput + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 + Int_BufSz = Int_BufSz + 1 ! WaveElevC0 allocated yes/no + IF ( ALLOCATED(InData%WaveElevC0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevC0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevC0) ! WaveElevC0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDirArr allocated yes/no + IF ( ALLOCATED(InData%WaveDirArr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveDirArr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDirArr) ! WaveDirArr + END IF + Re_BufSz = Re_BufSz + 1 ! WaveDirMin + Re_BufSz = Re_BufSz + 1 ! WaveDirMax + Re_BufSz = Re_BufSz + 1 ! WaveDir + Int_BufSz = Int_BufSz + 1 ! WaveNDir + Int_BufSz = Int_BufSz + 1 ! WaveMultiDir + Re_BufSz = Re_BufSz + 1 ! WaveDOmega + Int_BufSz = Int_BufSz + 1 ! WaveKinzi allocated yes/no + IF ( ALLOCATED(InData%WaveKinzi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveKinzi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveKinzi) ! WaveKinzi + END IF + Int_BufSz = Int_BufSz + 1 ! PWaveDynP0 allocated yes/no + IF ( ALLOCATED(InData%PWaveDynP0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PWaveDynP0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PWaveDynP0) ! PWaveDynP0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveDynP allocated yes/no + IF ( ALLOCATED(InData%WaveDynP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveDynP) ! WaveDynP + END IF + Int_BufSz = Int_BufSz + 1 ! WaveAcc allocated yes/no + IF ( ALLOCATED(InData%WaveAcc) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveAcc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveAcc) ! WaveAcc + END IF + Int_BufSz = Int_BufSz + 1 ! PWaveAcc0 allocated yes/no + IF ( ALLOCATED(InData%PWaveAcc0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PWaveAcc0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PWaveAcc0) ! PWaveAcc0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveVel allocated yes/no + IF ( ALLOCATED(InData%WaveVel) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! WaveVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveVel) ! WaveVel + END IF + Int_BufSz = Int_BufSz + 1 ! PWaveVel0 allocated yes/no + IF ( ALLOCATED(InData%PWaveVel0) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! PWaveVel0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PWaveVel0) ! PWaveVel0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev allocated yes/no + IF ( ALLOCATED(InData%WaveElev) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev) ! WaveElev + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no + IF ( ALLOCATED(InData%WaveElev0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev0) ! WaveElev0 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElevSeries allocated yes/no + IF ( ALLOCATED(InData%WaveElevSeries) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevSeries upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevSeries) ! WaveElevSeries + END IF + Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no + IF ( ALLOCATED(InData%WaveTime) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime + END IF + Db_BufSz = Db_BufSz + 1 ! WaveTMax + Int_BufSz = Int_BufSz + 1 ! nodeInWater allocated yes/no + IF ( ALLOCATED(InData%nodeInWater) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! nodeInWater upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater + END IF + Re_BufSz = Re_BufSz + 1 ! RhoXg + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! NStepWave2 + 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%WaveElevC0) ) 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%WaveElevC0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevC0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevC0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevC0,2), UBOUND(InData%WaveElevC0,2) + DO i1 = LBOUND(InData%WaveElevC0,1), UBOUND(InData%WaveElevC0,1) + ReKiBuf(Re_Xferred) = InData%WaveElevC0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDirArr) ) 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%WaveDirArr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDirArr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveDirArr,1), UBOUND(InData%WaveDirArr,1) + ReKiBuf(Re_Xferred) = InData%WaveDirArr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%WaveDirMin + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDirMax + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveNDir + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveMultiDir, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WaveDOmega + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WaveKinzi) ) 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%WaveKinzi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveKinzi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveKinzi,1), UBOUND(InData%WaveKinzi,1) + ReKiBuf(Re_Xferred) = InData%WaveKinzi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PWaveDynP0) ) 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%PWaveDynP0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveDynP0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PWaveDynP0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveDynP0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PWaveDynP0,2), UBOUND(InData%PWaveDynP0,2) + DO i1 = LBOUND(InData%PWaveDynP0,1), UBOUND(InData%PWaveDynP0,1) + ReKiBuf(Re_Xferred) = InData%PWaveDynP0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveDynP) ) 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%WaveDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveDynP,2), UBOUND(InData%WaveDynP,2) + DO i1 = LBOUND(InData%WaveDynP,1), UBOUND(InData%WaveDynP,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveAcc) ) 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%WaveAcc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveAcc,3), UBOUND(InData%WaveAcc,3) + DO i2 = LBOUND(InData%WaveAcc,2), UBOUND(InData%WaveAcc,2) + DO i1 = LBOUND(InData%WaveAcc,1), UBOUND(InData%WaveAcc,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PWaveAcc0) ) 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%PWaveAcc0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveAcc0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PWaveAcc0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveAcc0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PWaveAcc0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveAcc0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PWaveAcc0,3), UBOUND(InData%PWaveAcc0,3) + DO i2 = LBOUND(InData%PWaveAcc0,2), UBOUND(InData%PWaveAcc0,2) + DO i1 = LBOUND(InData%PWaveAcc0,1), UBOUND(InData%PWaveAcc0,1) + ReKiBuf(Re_Xferred) = InData%PWaveAcc0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveVel) ) 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%WaveVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveVel,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveVel,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%WaveVel,3), UBOUND(InData%WaveVel,3) + DO i2 = LBOUND(InData%WaveVel,2), UBOUND(InData%WaveVel,2) + DO i1 = LBOUND(InData%WaveVel,1), UBOUND(InData%WaveVel,1) + ReKiBuf(Re_Xferred) = InData%WaveVel(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PWaveVel0) ) 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%PWaveVel0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveVel0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PWaveVel0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveVel0,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PWaveVel0,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PWaveVel0,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%PWaveVel0,3), UBOUND(InData%PWaveVel0,3) + DO i2 = LBOUND(InData%PWaveVel0,2), UBOUND(InData%PWaveVel0,2) + DO i1 = LBOUND(InData%PWaveVel0,1), UBOUND(InData%PWaveVel0,1) + ReKiBuf(Re_Xferred) = InData%PWaveVel0(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev) ) 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%WaveElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev,2), UBOUND(InData%WaveElev,2) + DO i1 = LBOUND(InData%WaveElev,1), UBOUND(InData%WaveElev,1) + ReKiBuf(Re_Xferred) = InData%WaveElev(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev0) ) 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%WaveElev0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveElev0,1), UBOUND(InData%WaveElev0,1) + ReKiBuf(Re_Xferred) = InData%WaveElev0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElevSeries) ) 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%WaveElevSeries,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevSeries,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevSeries,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevSeries,2), UBOUND(InData%WaveElevSeries,2) + DO i1 = LBOUND(InData%WaveElevSeries,1), UBOUND(InData%WaveElevSeries,1) + ReKiBuf(Re_Xferred) = InData%WaveElevSeries(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveTime) ) 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%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%WaveTMax + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%nodeInWater) ) 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%nodeInWater,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%nodeInWater,2), UBOUND(InData%nodeInWater,2) + DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) + IntKiBuf(Int_Xferred) = InData%nodeInWater(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%RhoXg + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave2 + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_PackInitOutput + + SUBROUTINE Waves_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(Waves_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) :: 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 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%WaveElevC0)) DEALLOCATE(OutData%WaveElevC0) + ALLOCATE(OutData%WaveElevC0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevC0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevC0,2), UBOUND(OutData%WaveElevC0,2) + DO i1 = LBOUND(OutData%WaveElevC0,1), UBOUND(OutData%WaveElevC0,1) + OutData%WaveElevC0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDirArr 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%WaveDirArr)) DEALLOCATE(OutData%WaveDirArr) + ALLOCATE(OutData%WaveDirArr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDirArr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveDirArr,1), UBOUND(OutData%WaveDirArr,1) + OutData%WaveDirArr(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WaveDirMin = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDirMax = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveDir = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%WaveNDir = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveMultiDir = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveMultiDir) + Int_Xferred = Int_Xferred + 1 + OutData%WaveDOmega = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveKinzi 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%WaveKinzi)) DEALLOCATE(OutData%WaveKinzi) + ALLOCATE(OutData%WaveKinzi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveKinzi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveKinzi,1), UBOUND(OutData%WaveKinzi,1) + OutData%WaveKinzi(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PWaveDynP0 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%PWaveDynP0)) DEALLOCATE(OutData%PWaveDynP0) + ALLOCATE(OutData%PWaveDynP0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PWaveDynP0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PWaveDynP0,2), UBOUND(OutData%PWaveDynP0,2) + DO i1 = LBOUND(OutData%PWaveDynP0,1), UBOUND(OutData%PWaveDynP0,1) + OutData%PWaveDynP0(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveDynP 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%WaveDynP)) DEALLOCATE(OutData%WaveDynP) + ALLOCATE(OutData%WaveDynP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveDynP,2), UBOUND(OutData%WaveDynP,2) + DO i1 = LBOUND(OutData%WaveDynP,1), UBOUND(OutData%WaveDynP,1) + OutData%WaveDynP(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveAcc 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%WaveAcc)) DEALLOCATE(OutData%WaveAcc) + ALLOCATE(OutData%WaveAcc(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%WaveAcc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveAcc,3), UBOUND(OutData%WaveAcc,3) + DO i2 = LBOUND(OutData%WaveAcc,2), UBOUND(OutData%WaveAcc,2) + DO i1 = LBOUND(OutData%WaveAcc,1), UBOUND(OutData%WaveAcc,1) + OutData%WaveAcc(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 ! PWaveAcc0 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%PWaveAcc0)) DEALLOCATE(OutData%PWaveAcc0) + ALLOCATE(OutData%PWaveAcc0(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%PWaveAcc0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PWaveAcc0,3), UBOUND(OutData%PWaveAcc0,3) + DO i2 = LBOUND(OutData%PWaveAcc0,2), UBOUND(OutData%PWaveAcc0,2) + DO i1 = LBOUND(OutData%PWaveAcc0,1), UBOUND(OutData%PWaveAcc0,1) + OutData%PWaveAcc0(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 ! WaveVel 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%WaveVel)) DEALLOCATE(OutData%WaveVel) + ALLOCATE(OutData%WaveVel(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%WaveVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%WaveVel,3), UBOUND(OutData%WaveVel,3) + DO i2 = LBOUND(OutData%WaveVel,2), UBOUND(OutData%WaveVel,2) + DO i1 = LBOUND(OutData%WaveVel,1), UBOUND(OutData%WaveVel,1) + OutData%WaveVel(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 ! PWaveVel0 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%PWaveVel0)) DEALLOCATE(OutData%PWaveVel0) + ALLOCATE(OutData%PWaveVel0(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%PWaveVel0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%PWaveVel0,3), UBOUND(OutData%PWaveVel0,3) + DO i2 = LBOUND(OutData%PWaveVel0,2), UBOUND(OutData%PWaveVel0,2) + DO i1 = LBOUND(OutData%PWaveVel0,1), UBOUND(OutData%PWaveVel0,1) + OutData%PWaveVel0(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 ! WaveElev 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%WaveElev)) DEALLOCATE(OutData%WaveElev) + ALLOCATE(OutData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev,2), UBOUND(OutData%WaveElev,2) + DO i1 = LBOUND(OutData%WaveElev,1), UBOUND(OutData%WaveElev,1) + OutData%WaveElev(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 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%WaveElev0)) DEALLOCATE(OutData%WaveElev0) + ALLOCATE(OutData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveElev0,1), UBOUND(OutData%WaveElev0,1) + OutData%WaveElev0(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevSeries 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%WaveElevSeries)) DEALLOCATE(OutData%WaveElevSeries) + ALLOCATE(OutData%WaveElevSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevSeries,2), UBOUND(OutData%WaveElevSeries,2) + DO i1 = LBOUND(OutData%WaveElevSeries,1), UBOUND(OutData%WaveElevSeries,1) + OutData%WaveElevSeries(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime 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%WaveTime)) DEALLOCATE(OutData%WaveTime) + ALLOCATE(OutData%WaveTime(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveTime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) + OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%WaveTMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! nodeInWater 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%nodeInWater)) DEALLOCATE(OutData%nodeInWater) + ALLOCATE(OutData%nodeInWater(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%nodeInWater,2), UBOUND(OutData%nodeInWater,2) + DO i1 = LBOUND(OutData%nodeInWater,1), UBOUND(OutData%nodeInWater,1) + OutData%nodeInWater(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%RhoXg = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NStepWave2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_UnPackInitOutput + + SUBROUTINE Waves_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Waves_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 = 'Waves_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Waves_CopyContState + + SUBROUTINE Waves_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Waves_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyContState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 Waves_PackContState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_UnPackContState + + SUBROUTINE Waves_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Waves_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 = 'Waves_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE Waves_CopyDiscState + + SUBROUTINE Waves_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Waves_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyDiscState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 Waves_PackDiscState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_UnPackDiscState + + SUBROUTINE Waves_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Waves_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 = 'Waves_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Waves_CopyConstrState + + SUBROUTINE Waves_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Waves_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyConstrState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 Waves_PackConstrState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_UnPackConstrState + + SUBROUTINE Waves_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Waves_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 = 'Waves_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Waves_CopyOtherState + + SUBROUTINE Waves_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Waves_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyOtherState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_PackOtherState + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_UnPackOtherState + + SUBROUTINE Waves_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Waves_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 = 'Waves_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE Waves_CopyMisc + + SUBROUTINE Waves_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Waves_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyMisc + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 ! 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 + + IntKiBuf(Int_Xferred) = InData%DummyMiscVar + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_PackMisc + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_UnPackMisc + + SUBROUTINE Waves_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Waves_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 = 'Waves_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%WaveTMax = SrcParamData%WaveTMax + DstParamData%NStepWave = SrcParamData%NStepWave + DstParamData%WaveNDir = SrcParamData%WaveNDir + DstParamData%WaveMultiDir = SrcParamData%WaveMultiDir + END SUBROUTINE Waves_CopyParam + + SUBROUTINE Waves_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Waves_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyParam + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 + Db_BufSz = Db_BufSz + 1 ! DT + Db_BufSz = Db_BufSz + 1 ! WaveTMax + Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! WaveNDir + Int_BufSz = Int_BufSz + 1 ! WaveMultiDir + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%WaveTMax + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NStepWave + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WaveNDir + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WaveMultiDir, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_PackParam + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WaveTMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NStepWave = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveNDir = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WaveMultiDir = TRANSFER(IntKiBuf(Int_Xferred), OutData%WaveMultiDir) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Waves_UnPackParam + + SUBROUTINE Waves_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_InputType), INTENT(IN) :: SrcInputData + TYPE(Waves_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%DummyInput = SrcInputData%DummyInput + END SUBROUTINE Waves_CopyInput + + SUBROUTINE Waves_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Waves_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyInput + + SUBROUTINE Waves_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(Waves_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 = 'Waves_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 + Re_BufSz = Re_BufSz + 1 ! DummyInput + 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%DummyInput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_PackInput + + SUBROUTINE Waves_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(Waves_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_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 + OutData%DummyInput = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_UnPackInput + + SUBROUTINE Waves_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Waves_OutputType), INTENT(IN) :: SrcOutputData + TYPE(Waves_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Waves_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%DummyOutput = SrcOutputData%DummyOutput + END SUBROUTINE Waves_CopyOutput + + SUBROUTINE Waves_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Waves_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Waves_DestroyOutput + + SUBROUTINE Waves_PackOutput( 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(Waves_OutputType), 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 = 'Waves_PackOutput' + ! 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 ! DummyOutput + 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%DummyOutput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_PackOutput + + SUBROUTINE Waves_UnPackOutput( 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(Waves_OutputType), 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 = 'Waves_UnPackOutput' + ! 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%DummyOutput = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Waves_UnPackOutput + + + SUBROUTINE Waves_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Waves_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Waves_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Waves_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Waves_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Waves_Input_ExtrapInterp + + + SUBROUTINE Waves_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(u1%DummyInput - u2%DummyInput) + u_out%DummyInput = u1%DummyInput + b * ScaleFactor + END SUBROUTINE Waves_Input_ExtrapInterp1 + + + SUBROUTINE Waves_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Waves_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(u1%DummyInput - u2%DummyInput) + t(2)**2*(-u1%DummyInput + u3%DummyInput))* scaleFactor + c = ( (t(2)-t(3))*u1%DummyInput + t(3)*u2%DummyInput - t(2)*u3%DummyInput ) * scaleFactor + u_out%DummyInput = u1%DummyInput + b + c * t_out + END SUBROUTINE Waves_Input_ExtrapInterp2 + + + SUBROUTINE Waves_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Waves_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Waves_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Waves_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Waves_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Waves_Output_ExtrapInterp + + + SUBROUTINE Waves_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + b = -(y1%DummyOutput - y2%DummyOutput) + y_out%DummyOutput = y1%DummyOutput + b * ScaleFactor + END SUBROUTINE Waves_Output_ExtrapInterp1 + + + SUBROUTINE Waves_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Waves_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Waves_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + b = (t(3)**2*(y1%DummyOutput - y2%DummyOutput) + t(2)**2*(-y1%DummyOutput + y3%DummyOutput))* scaleFactor + c = ( (t(2)-t(3))*y1%DummyOutput + t(3)*y2%DummyOutput - t(2)*y3%DummyOutput ) * scaleFactor + y_out%DummyOutput = y1%DummyOutput + b + c * t_out + END SUBROUTINE Waves_Output_ExtrapInterp2 + +END MODULE Waves_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/icedyn/CMakeLists.txt b/OpenFAST/modules/icedyn/CMakeLists.txt new file mode 100644 index 000000000..af328a1a2 --- /dev/null +++ b/OpenFAST/modules/icedyn/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/Registry_IceDyn.txt ${CMAKE_CURRENT_LIST_DIR}/src/IceDyn_Types.f90) +endif() + +add_library(icedynlib + src/IceDyn.f90 + src/IceDyn_Types.f90 +) + +target_link_libraries(icedynlib nwtclibs) + +install(TARGETS icedynlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) diff --git a/OpenFAST/modules/icedyn/README.md b/OpenFAST/modules/icedyn/README.md new file mode 100644 index 000000000..2b02a574e --- /dev/null +++ b/OpenFAST/modules/icedyn/README.md @@ -0,0 +1,23 @@ +# IceDyn Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/IceDyn/). + +## Overview +The U.S. Department of Energy (DOE) awarded the University of Michigan a +project to create a model for interaction of bottom-fixed offshore wind +turbines with surface ice for use with common simulation tools. The IceDyn +module, which conforms to the standards of the FAST Modularization Framework, +was created from this project. + +The IceDyn module includes 6 ice mechanics models that incorporate ice floe +forcing, deformation and failure and structure geometry. The six models are +- quasi-static ice loading on vertical structure +- dynamic ice loading on vertical structure +- random ice loading on vertical structure +- non-simultaneous ice loading on vertical structure +- ice loading on sloping structure +- large ice floe impact + +## Manual +IceDyn documentation is available +[here](http://wind.nrel.gov/nwtc/docs/IceDyn_Manual.pdf). diff --git a/OpenFAST/modules/icedyn/src/Driver_IceDyn.f90 b/OpenFAST/modules/icedyn/src/Driver_IceDyn.f90 new file mode 100644 index 000000000..9b1775437 --- /dev/null +++ b/OpenFAST/modules/icedyn/src/Driver_IceDyn.f90 @@ -0,0 +1,473 @@ +! LICENSING +! Copyright (C) 2013-2016 University of Michigan, National Renewable Energy Laboratory +! +! This file is part of module IceDyn. +! +! 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. +!********************************************************************************************************************************** +PROGRAM MAIN + + USE IceDyn + USE IceDyn_Types + + USE NWTC_Library + + IMPLICIT NONE + + ! global glue-code-specific variables + + INTEGER(IntKi) :: ErrStat ! Error status of the operation + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(DbKi) :: dt_global ! fixed/constant global time step + REAL(DbKi) :: t_initial ! time at initialization + REAL(DbKi) :: t_final ! time at simulation end + REAL(DbKi) :: t_global ! global-loop time marker + + INTEGER(IntKi) :: n_t_final ! total number of time steps + INTEGER(IntKi) :: n_t_global ! global-loop time counter + + INTEGER(IntKi) :: pc_max ! 1:explicit loose; 2:pc loose + INTEGER(IntKi) :: pc ! counter for pc iterations + + INTEGER(IntKi) :: IceD_interp_order ! order of interpolation/extrapolation + + ! IceDyn Derived-types variables; see Registry_IceDyn.txt for details + + TYPE(IceD_InitInputType) :: IceD_InitInput + TYPE(IceD_ParameterType) :: IceD_Parameter + TYPE(IceD_ContinuousStateType) :: IceD_ContinuousState + TYPE(IceD_ContinuousStateType) :: IceD_ContinuousStateDeriv + TYPE(IceD_InitOutputType) :: IceD_InitOutput + TYPE(IceD_DiscreteStateType) :: IceD_DiscreteState + TYPE(IceD_ConstraintStateType) :: IceD_ConstraintState + TYPE(IceD_OtherStateType) :: IceD_OtherState + TYPE(IceD_MiscVarType) :: IceD_MiscVar + + TYPE(IceD_InputType), Dimension(:),Allocatable :: IceD_Input + REAL(DbKi) , DIMENSION(:),ALLOCATABLE :: IceD_InputTimes + + TYPE(IceD_OutputType),Dimension(:),Allocatable :: IceD_Output + REAL(DbKi) , DIMENSION(:),ALLOCATABLE :: IceD_OutputTimes + + TYPE(IceD_InputType) :: u1 ! local variable for extrapolated inputs + TYPE(IceD_OutputType) :: y1 ! local variable for extrapolated outputs + + ! IceDyn derived data typed needed in pc-coupling; predicted states + + TYPE(IceD_ContinuousStateType) :: IceD_ContinuousState_pred + TYPE(IceD_DiscreteStateType) :: IceD_DiscreteState_pred + TYPE(IceD_ConstraintStateType) :: IceD_ConstraintState_pred + TYPE(IceD_OtherStateType) :: IceD_OtherState_pred + + ! local variables + Integer(IntKi) :: i ! counter for various loops + Integer(IntKi) :: j ! counter for various loops + + REAL(DbKi) :: exact ! exact solution + REAL(DbKi) :: rms_error ! rms error + REAL(DbKi) :: rms_error_norm ! rms error normalization + + Integer(IntKi) :: num_dof + CHARACTER(1024) :: OutFileName ! Name of the output file + Integer(IntKi) :: Un + CHARACTER(200) :: Frmt + CHARACTER(1) :: Dlim = TAB + + + call NWTC_Init() + + ! ------------------------------------------------------------------------- + ! Initialization of glue-code time-step variables + ! ------------------------------------------------------------------------ + + t_initial = 0.d0 + t_final = 100.0d0 + + pc_max = 1 ! Number of predictor-corrector iterations; 1 corresponds to an explicit calculation where UpdateStates + ! is called only once per time step for each module; inputs and outputs are extrapolated in time and + ! are available to modules that have an implicit dependence on other-module data + + ! specify time increment; currently, all modules will be time integrated with this increment size + dt_global = 0.0125 + + n_t_final = ((t_final - t_initial) / dt_global ) + + t_global = t_initial + + ! initialize rms-error quantities + rms_error = 0. + rms_error_norm = 0. + + ! define polynomial-order for ModName_Input_ExtrapInterp and ModName_Output_ExtrapInterp + ! Must be 0, 1, or 2 + IceD_interp_order = 2 + + !IceDyn: allocate Input and Output arrays; used for interpolation and extrapolation + Allocate(IceD_Input(IceD_interp_order + 1)) + Allocate(IceD_InputTimes(IceD_interp_order + 1)) + + Allocate(IceD_Output(IceD_interp_order + 1)) + Allocate(IceD_OutputTimes(IceD_interp_order + 1)) + + + ! ------------------------------------------------------------------------- + ! Initialization of Modules + ! note that in this example, we are assuming that dt_global is not changed + ! in the modules, i.e., that both modules are called at the same glue-code + ! defined coupling interval. + ! ------------------------------------------------------------------------- + + IceD_InitInput%InputFile = 'IceDyn_Input.txt' + IceD_InitInput%RootName = 'IceDyn_Test' + IceD_InitInput%TMax = t_final + IceD_InitInput%MSL2SWL = 0.0_ReKi + IceD_InitInput%WtrDens = 1000 + IceD_InitInput%gravity = 9.81 + IceD_InitInput%LegNum = 1 + + CALL IceD_Init( IceD_InitInput & + , IceD_Input(1) & + , IceD_Parameter & + , IceD_ContinuousState & + , IceD_DiscreteState & + , IceD_ConstraintState & + , IceD_OtherState & + , IceD_Output(1) & + , IceD_MiscVar & + , dt_global & + , IceD_InitOutput & + , ErrStat & + , ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr('After IceD_Init: ') + call CheckError() + + CALL IceD_CopyInput( IceD_Input(1), u1, MESH_NEWCOPY, ErrStat, ErrMsg ) + call CheckError() + CALL IceD_CopyOutput( IceD_Output(1), y1, MESH_NEWCOPY, ErrStat, ErrMsg ) + call CheckError() + + ! We fill IceD_InputTimes with negative times, but the IceD_Input values are identical for each of those times; this allows + ! us to use, e.g., quadratic interpolation that effectively acts as a zeroth-order extrapolation and first-order extrapolation + ! for the first and second time steps. (The interpolation order in the ExtrapInput routines are determined as + ! order = SIZE(IceD_Input) + do i = 1, IceD_interp_order + 1 + IceD_InputTimes(i) = t_initial - (i - 1) * dt_global + IceD_OutputTimes(i) = t_initial - (i - 1) * dt_global + enddo + + do i = 1, IceD_interp_order + Call IceD_CopyInput (IceD_Input(i), IceD_Input(i+1), MESH_NEWCOPY, Errstat, ErrMsg) + call CheckError() + Call IceD_CopyOutput (IceD_Output(i), IceD_Output(i+1), MESH_NEWCOPY, Errstat, ErrMsg) + call CheckError() + enddo + + + Call IceD_CopyContState (IceD_ContinuousState, IceD_ContinuousState_pred, MESH_NEWCOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyConstrState (IceD_ConstraintState, IceD_ConstraintState_pred, MESH_NEWCOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyDiscState (IceD_DiscreteState, IceD_DiscreteState_pred, MESH_NEWCOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyOtherState (IceD_OtherState, IceD_OtherState_pred, MESH_NEWCOPY, Errstat, ErrMsg); CALL CheckError() + + + ! ------------------------------------------------------------------------- + ! Time-stepping loops + ! ------------------------------------------------------------------------- + + ! write headers for output columns: + + CALL WrScr1( ' Time (t) Numerical q_1(t) Analytical q_1(t)' ) + CALL WrScr( ' --------------- ---------------- -----------------' ) + + ! write initial condition for q1 + !CALL WrScr ( ' '//Num2LStr(t_global)//' '//Num2LStr( IceD_ContinuousState%q)//' '//Num2LStr(IceD_ContinuousState%q)) + + + ! Open output file + OutFileName = Trim(IceD_parameter%RootName)//'.txt' + CALL GetNewUnit (Un) + CALL OpenFOutFile (Un, OutFileName, ErrStat, ErrMsg) + CALL CheckError() + + ! write headers for output columns: + Frmt = '(A8)' + WRITE (Un, Frmt, ADVANCE = 'no') TRIM ('Time') + + Frmt = '(3(:,A,A10))' + WRITE (Un, Frmt, ADVANCE = 'no') Dlim, TRIM('StrDisp'), Dlim, TRIM('IceDisp'), Dlim, TRIM('IceForce') + + Frmt = '(/ F8.3)' + WRITE (Un, Frmt, ADVANCE = 'no') t_global + + Frmt = '(A,F10.4,A,F10.4,A,E10.3E2)' + WRITE (Un, Frmt, ADVANCE = 'no') Dlim, IceD_Input(1)%PointMesh%TranslationDisp(1,1), & + Dlim, IceD_ContinuousState%q, & + Dlim, IceD_Output(1)%PointMesh%Force(1,1) + + + DO n_t_global = 0, n_t_final + !DO n_t_global = 0, 1000 + + + CALL IceD_InputSolve( IceD_Input(1), IceD_Output(1), IceD_Parameter, ErrStat, ErrMsg) + CALL CheckError() + + CALL IceD_CalcOutput( t_global, IceD_Input(1), IceD_Parameter, IceD_ContinuousState, IceD_DiscreteState, & + IceD_ConstraintState, IceD_OtherState, IceD_Output(1), IceD_MiscVar, ErrStat, ErrMsg) + CALL CheckError() + + Frmt = '(/ F8.3)' + WRITE (Un, Frmt, ADVANCE = 'no') t_global + + Frmt = '(A,F10.4,A,F10.4,A,E10.3E2)' + WRITE (Un, Frmt, ADVANCE = 'no') Dlim, IceD_Input(1)%PointMesh%TranslationDisp(1,1), & + Dlim, IceD_ContinuousState%q, & + Dlim, IceD_Output(1)%PointMesh%Force(1,1) + + ! extrapolate inputs and outputs to t + dt; will only be used by modules with an implicit dependence on input data. + + CALL IceD_Input_ExtrapInterp(IceD_Input, IceD_InputTimes, u1, t_global + dt_global, ErrStat, ErrMsg) + CALL CheckError() + + CALL IceD_Output_ExtrapInterp(IceD_Output, IceD_OutputTimes, y1, t_global + dt_global, ErrStat, ErrMsg) + CALL CheckError() + + ! Shift "window" of the IceD_Input and IceD_Output + + do i = IceD_interp_order, 1, -1 + Call IceD_CopyInput (IceD_Input(i), IceD_Input(i+1), MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyOutput (IceD_Output(i), IceD_Output(i+1), MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + IceD_InputTimes(i+1) = IceD_InputTimes(i) + IceD_OutputTimes(i+1) = IceD_OutputTimes(i) + enddo + + Call IceD_CopyInput (u1, IceD_Input(1), MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyOutput (y1, IceD_Output(1), MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + IceD_InputTimes(1) = t_global + dt_global + IceD_OutputTimes(1) = t_global + dt_global + + ! Shift "window" of the IceD_Input and IceD_Output + + do pc = 1, pc_max + + !---------------------------------------------------------------------------------------- + ! IceD + !---------------------------------------------------------------------------------------- + + ! copy ContinuousState to ContinuousState_pred; don't modify ContinuousState until completion of PC iterations + + Call IceD_CopyContState (IceD_ContinuousState, IceD_ContinuousState_pred, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyConstrState (IceD_ConstraintState, IceD_ConstraintState_pred, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyDiscState (IceD_DiscreteState, IceD_DiscreteState_pred, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyOtherState (IceD_OtherState, IceD_OtherState_pred, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + + CALL IceD_UpdateStates( t_global, n_t_global, IceD_Input, IceD_InputTimes, IceD_Parameter, & + IceD_ContinuousState_pred, IceD_DiscreteState_pred, IceD_ConstraintState_pred, & + IceD_OtherState_pred, IceD_MiscVar, ErrStat, ErrMsg ) + CALL CheckError() + + + !----------------------------------------------------------------------------------------- + ! If correction iteration is to be taken, solve intput-output equations; otherwise move on + !----------------------------------------------------------------------------------------- + +! if (pc .lt. pc_max) then +! +! call IceD_IceD_InputOutputSolve( t_global + dt_global, & +! IceD_Input(1), IceD_Parameter, IceD_ContinuousState_pred, IceD_DiscreteState_pred, & +! IceD_ConstraintState_pred, IceD_OtherState, IceD_Output(1), & +! IceD_Input(1), IceD_Parameter, IceD_ContinuousState_pred, IceD_DiscreteState_pred, & +! IceD_ConstraintState_pred, IceD_OtherState, IceD_Output(1), & +! ErrStat, ErrMsg) + +! endif + + enddo + + write(*,*) t_global, IceD_ContinuousState%q + + + !write(*,*) t_global, IceD_ContinuousState%dqdt + + ! Save all final variables + Call IceD_CopyContState (IceD_ContinuousState_pred, IceD_ContinuousState, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyConstrState (IceD_ConstraintState_pred, IceD_ConstraintState, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyDiscState (IceD_DiscreteState_pred, IceD_DiscreteState, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + Call IceD_CopyOtherState (IceD_OtherState_pred, IceD_OtherState, MESH_UPDATECOPY, Errstat, ErrMsg); CALL CheckError() + + + ! update the global time + + t_global = REAL(n_t_global+1,DbKi) * dt_global + t_initial + + + + ! the following is exact solution for q_1(t) for baseline parameters in Gasmi et al. (2013) + + !exact = Cos((SQRT(399.d0)*t_global)/20.d0)*(0.5d0*exp(-t_global/20.d0)) + & + ! Cos((SQRT(7491.d0)*t_global)/50.d0)*(0.5d0*exp(-(3.d0*t_global)/50.d0)) + & + ! Sin((SQRT(399.d0)*t_global)/20.d0)*exp(-t_global/20.d0)/(2.d0*SQRT(399.d0))+ & + ! (SQRT(0.0012014417300760913d0)*Sin((SQRT(7491.d0)*t_global)/50.d0)) & + ! *(0.5d0*exp(-(3.d0*t_global)/50.d0)) + + ! exact = 1. - Cos(3. * t_global) + + ! build rms_error calculation components; see Eq. (56) in Gasmi et al. (2013) + + !rms_error = rms_error + ( IceD_ContinuousState%q - exact )**2 + !rms_error_norm = rms_error_norm + ( exact )**2 + + ! print discrete q_1(t) solution to standard out + + !CALL WrScr ( ' '//Num2LStr(t_global)//' '//Num2LStr( IceD_ContinuousState%q)//' '//Num2LStr(exact) ) + !print *, t_global, IceD_ContinuousState%q, ' ', exact + + END DO + + + ! calculate final time normalized rms error + +! rms_error = sqrt(rms_error / rms_error_norm) + + CALL WrScr1 ( 'IceDyn Method = '//TRIM(Num2LStr(IceD_Parameter%method))) + CALL WrScr ( 'pc_max = '//TRIM(Num2LStr(pc_max))) + + !ALL WrScr1 ( 'normalized rms error of q_1(t) = '//TRIM(Num2LStr( rms_error )) ) + CALL WrScr ( 'time increment = '//TRIM(Num2LStr(dt_global)) ) + +! CALL WrScr1 ( 'log10(dt_global), log10(rms_error): ' ) +! CALL WrScr ( TRIM(Num2LStr( log10(dt_global) ))//' '//TRIM(Num2LStr( log10(rms_error) )) ) + + + ! ------------------------------------------------------------------------- + ! Ending of modules + ! ------------------------------------------------------------------------- + + + CALL IceD_End( IceD_Input(1), IceD_Parameter, IceD_ContinuousState, IceD_DiscreteState, & + IceD_ConstraintState, IceD_OtherState, IceD_Output(1), IceD_MiscVar, ErrStat, ErrMsg ) + CALL CheckError() + + do i = 2, IceD_interp_order+1 + CALL IceD_DestroyInput(IceD_Input(i), ErrStat, ErrMsg ); CALL CheckError() + CALL IceD_DestroyOutput(IceD_Output(i), ErrStat, ErrMsg ); CALL CheckError() + enddo + + DEALLOCATE(IceD_InputTimes) + DEALLOCATE(IceD_OutputTimes) + + Call IceD_DestroyContState (IceD_ContinuousState_pred, Errstat, ErrMsg) + Call IceD_DestroyConstrState (IceD_ConstraintState_pred, Errstat, ErrMsg) + Call IceD_DestroyDiscState (IceD_DiscreteState_pred, Errstat, ErrMsg) + Call IceD_DestroyOtherState (IceD_OtherState_pred, Errstat, ErrMsg) + + +CONTAINS + + SUBROUTINE CheckError() + + ! Local variables + + REAL(ReKi) :: WaitTime ! Time to wait before pausing the program (s) + + WaitTIme = 5.0 + + IF (ErrStat >= AbortErrLev) THEN + CALL ProgAbort( trim(ErrMsg), .FALSE., WaitTIme, ErrStat ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr(trim(ErrMsg)) + END IF + + + END SUBROUTINE CheckError + +END PROGRAM MAIN +!---------------------------------------------------------------------------------------------------------------------------------- +!SUBROUTINE IceD_IceD_InputOutputSolve(time, & +! IceD_Input, IceD_Parameter, IceD_ContinuousState, IceD_DiscreteState, & +! IceD_ConstraintState, IceD_OtherState, IceD_Output, & +! IceD_Input, IceD_Parameter, IceD_ContinuousState, IceD_DiscreteState, & +! IceD_ConstraintState, IceD_OtherState, IceD_Output, & +! ErrStat, ErrMsg) +!! +!! Solve input-output relations for Module 1 coupled to Module 2; this section of code corresponds to Eq. (35) in +!! Gasmi et al. (2013). This code will be specific to the underlying modules +!!................................................................................................................................... +! +! USE IceDyn +! USE IceDyn_Types +! +! +! ! IceDyn Derived-types variables; see Registry_IceDyn.txt for details +! +! TYPE(IceD_InputType), INTENT(INOUT) :: IceD_Input +! TYPE(IceD_ParameterType), INTENT(IN ) :: IceD_Parameter +! TYPE(IceD_ContinuousStateType), INTENT(IN ) :: IceD_ContinuousState +! TYPE(IceD_DiscreteStateType), INTENT(IN ) :: IceD_DiscreteState +! TYPE(IceD_ConstraintStateType), INTENT(INOUT) :: IceD_ConstraintState +! TYPE(IceD_OtherStateType), INTENT(INOUT) :: IceD_OtherState +! TYPE(IceD_OutputType), INTENT(INOUT) :: IceD_Output +! +! +! 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 +! +! ! Solve input-output relations; this section of code corresponds to Eq. (35) in Gasmi et al. (2013) +! ! This code will be specific to the underlying modules; could be placed in a separate routine. +! ! Note that IceDyn has direct feedthrough, but IceDyn does not. Thus, IceDyn should be called first. +! +! CALL IceD_CalcOutput( time, IceD_Input, IceD_Parameter, IceD_ContinuousState, IceD_DiscreteState, & +! IceD_ConstraintState, IceD_OtherState, IceD_Output, ErrStat, ErrMsg ) +! +! call IceD_InputSolve( IceD_Input, IceD_Output, IceD_Input, IceD_Output, ErrStat, ErrMsg) +! +!END SUBROUTINE IceD_IceD_InputOutputSolve +!!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceD_InputSolve( u, y, p, ErrStat, ErrMsg) + + USE IceDyn + USE IceDyn_Types + + ! IceDyn Derived-types variables; see Registry_IceDyn.txt for details + + TYPE(IceD_InputType), INTENT(INOUT) :: u + TYPE(IceD_OutputType), INTENT(IN ) :: y + TYPE(IceD_ParameterType), INTENT(IN ) :: p + + + 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 ! do-loop counter + + REAL(ReKi) :: tmp_vector(3) + + ErrStat = ErrID_None + ErrMsg = '' + + ! gather point forces and line forces + tmp_vector = 0. + + ! Point mesh: displacement and velocity + u%PointMesh%TranslationDisp(:,1) = tmp_vector + u%PointMesh%TranslationVel(:,1) = tmp_vector + + +END SUBROUTINE IceD_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!---------------------------------------------------------------------------------------------------------------------------------- diff --git a/OpenFAST/modules/icedyn/src/IceDyn.f90 b/OpenFAST/modules/icedyn/src/IceDyn.f90 new file mode 100644 index 000000000..64ed3f375 --- /dev/null +++ b/OpenFAST/modules/icedyn/src/IceDyn.f90 @@ -0,0 +1,3244 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 Univeristy of Michigan and National Renewable Energy Laboratory +! +! This file is part of module IceDyn. +! +! 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. +!********************************************************************************************************************************** +!> IceDyn is a module describing ice load on offshore wind turbine supporting structures. +!! +!! The module is given the module name ModuleName = IceDyn and the abbreviated name ModName = IceD. The mathematical +!! formulation of this module is a subset of the most general form permitted by the FAST modularization framework in tight +!! coupling, thus, the module is developed to support both loose and tight coupling (tight coupling for both time marching and +!! linearization). +!! +!! References: +!! +!! Ice Module Manual, by Bingbin Yu, Dale Karr. +!! +!********************************************************************************************************************************** +MODULE IceDyn + + USE IceDyn_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: IceD_Ver = ProgDesc( 'IceDyn', 'v1.02.01', '23-Jul-2016' ) + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: IceD_Init ! Initialization routine + PUBLIC :: IceD_End ! Ending routine (includes clean up) + + PUBLIC :: IceD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: IceD_CalcOutput ! Routine for computing outputs + + PUBLIC :: IceD_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: IceD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: IceD_UpdateDiscState ! Tight coupling routine for updating discrete states + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE IceD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(IceD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(IceD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(IceD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(IceD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(IceD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(IceD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(IceD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(IceD_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !! Coupling interval in seconds: the rate that + !! (1) IceD_UpdateStates() is called in loose coupling & + !! (2) IceD_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(IceD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + TYPE(IceD_InputFile) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + REAL(ReKi) :: TmpPos(3) + + + ! Initialize variables for this routine + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( EchoLibVer=.FALSE. ) + + + ! Display the module information + + IF (InitInp%LegNum == 1) CALL DispNVD( IceD_Ver ) ! We don't need to see the version info more than one time + + !............................................................................................ + ! Read the input file and validate the data + !............................................................................................ + p%RootName = TRIM(InitInp%RootName) ! FAST makes all of the output file names from this module end contain '.IceD' before the file extension + + CALL IceD_ReadInput( InitInp, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL IceD_ValidateInput( InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! make sure the InitInp%LegNum makes sense: + IF ( InputFileData%NumLegs < InitInp%LegNum .OR. InitInp%LegNum < 1 ) THEN + CALL CheckError( ErrID_Fatal, 'IceDyn input file specified '//trim(num2lstr(InputFileData%NumLegs))// & + ' legs. The glue/driver code requested data for leg '//trim(num2lstr(InitInp%LegNum))//'.') + RETURN + END IF + + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + CALL IceD_SetParameters( InputFileData, p, Interval, InitInp%Tmax, InitInp%LegNum, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + + z%DummyConstrState = 0 ! we don't have constraint states + + + ! initialize the continuous states: + ! CALL Init_ContStates( x, p, InputFileData, OtherState, ErrStat2, ErrMsg2 ) ! initialize the continuous states + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF (ErrStat >= AbortErrLev) RETURN + + IF (p%ModNo /= 6) THEN + + x%q = 0 ! we don't have continuous states for ice model 1-5 + x%dqdt = 0 + + ELSE + + x%q = p%InitLoc ! Initial ice floe location + x%dqdt = p%v ! Initial ice velocity + + ENDIF + + ! initialize the discrete states: + !CALL IceD_Init_DiscrtStates( xd, p, InputFileData, ErrStat2, ErrMsg2 ) ! initialize the continuous states + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF (ErrStat >= AbortErrLev) RETURN + + xd%DummyDiscState = 0 + + ! Initialize other states: + CALL IceD_Init_OtherStates( OtherState, p, x, InputFileData, ErrStat2, ErrMsg2 ) ! initialize the other states + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + m%DummyMiscVar = 0 + + !............................................................................................ + ! Define initial guess for the system inputs and output (set up meshes) here: + !............................................................................................ + + ! set up meshes for inputs and outputs: + + ! Define system output initializations (set up mesh) here: + CALL MeshCreate( BlankMesh = u%PointMesh & + ,IOS = COMPONENT_INPUT & + ,NNodes = 1 & + ,TranslationDisp = .TRUE. & + ,TranslationVel = .TRUE. & + ,nScalars = 0 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + + CALL MeshConstructElement ( Mesh = u%PointMesh & + , Xelement = ELEMENT_POINT & + , P1 = 1 & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + ! place single node at water level; position affects mapping/coupling with other modules + TmpPos(1) = InputFileData%LegPosX( InitInp%LegNum ) + TmpPos(2) = InputFileData%LegPosY( InitInp%LegNum ) + TmpPos(3) = InitInp%MSL2SWL + + CALL MeshPositionNode ( Mesh = u%PointMesh & + , INode = 1 & + , Pos = TmpPos & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + CALL MeshCommit ( Mesh = u%PointMesh & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + + CALL MeshCopy ( SrcMesh = u%PointMesh & + , DestMesh = y%PointMesh & + , CtrlCode = MESH_SIBLING & + , Force = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + ! Define initial guess for the system inputs here: + u%PointMesh%TranslationDisp = 0.0_ReKi ! initialize all components of all (1) points + u%PointMesh%TranslationVel = 0.0_ReKi ! initialize all components of all (1) points [bjj: does not appear to be used...] + + y%PointMesh%Force = 0.0_ReKi ! initialize all components of all (1) points + + + + ! set remap flags to true + y%PointMesh%RemapFlag = .True. + u%PointMesh%RemapFlag = .True. + + + + !............................................................................................ + ! Define initialization-routine output here: + !............................................................................................ + CALL AllocAry( InitOut%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + CALL AllocAry( InitOut%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + InitOut%WriteOutputHdr = p%OutName + InitOut%WriteOutputUnt = p%OutUnit + + InitOut%Ver = IceD_Ver + InitOut%numLegs = InputFileData%NumLegs + + !bjj todo: check that water density is the same + + IF ( .NOT. EqualRealNos( InputFileData%rhow, InitInp%WtrDens ) ) THEN + CALL CheckError( ErrID_Warn, 'IceD_Init: water density from IceDyn input file ('//trim(num2Lstr(InputFileData%rhow))//& + ' kg/m^3) differs from water density in glue code ('//trim(num2Lstr(InitInp%WtrDens))//' kg/m^3).') + END IF + + IF ( .NOT. EqualRealNos( 9.81_ReKi, InitInp%gravity ) ) THEN + CALL CheckError( ErrID_Warn, 'IceD_Init: gravity hard-coded in IceDyn ('//trim(num2Lstr(9.81))//& + ' m/s^2) differs from gravity in glue code ('//trim(num2Lstr(InitInp%gravity))//' m/s^2).') + END IF + + + + ! ! Print the summary file if requested: + ! IF (InputFileData%SumPrint) THEN + ! CALL IceD_PrintSum( p, OtherState, GetAdamsVals, ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF (ErrStat >= AbortErrLev) RETURN + ! END IF + + ! Destroy the InputFileData structure (deallocate arrays) + + CALL IceD_DestroyInputFile(InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//' '//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CALL IceD_DestroyInputFile(InputFileData, ErrStat3, ErrMsg3 ) + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE IceD_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE IceD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(IceD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(IceD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(IceD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(IceD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(IceD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(IceD_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 + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Place any last minute operations or calculations here: + + ! Close files here: + + ! Destroy the input data: + + CALL IceD_DestroyInput( u, ErrStat, ErrMsg ) + + ! Destroy the parameter data: + + CALL IceD_DestroyParam( p, ErrStat, ErrMsg ) + + ! Destroy the state data: + + CALL IceD_DestroyContState( x, ErrStat, ErrMsg ) + CALL IceD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL IceD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL IceD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL IceD_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL IceD_DestroyOutput( y, ErrStat, ErrMsg ) + + +END SUBROUTINE IceD_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 IceD_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current simulation time step n = 0,1,... + TYPE(IceD_InputType), INTENT(INOUT) :: u(:) !< Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) !< Times associated with u(:), in seconds + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(IceD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(IceD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t+dt + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t+dt + TYPE(IceD_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 + + ! local variables + + TYPE(IceD_InputType) :: u_interp ! input interpolated from given u at utimes + !TYPE(IceD_ContinuousStateType) :: xdot ! continuous state time derivative + INTEGER(IntKi) :: I ! Loop count + REAL(ReKi) :: Del2 ! Deflection of the current ice tooth, for model 2,3 + REAL(ReKi) :: Del(p%Zn) ! Deflection of ice tooth in each zone, for model 4 +! REAL(ReKi) :: StrRt ! Strain rate (s^-1) +! REAL(ReKi) :: SigCrp ! Creep stress (Pa) + + INTEGER(IntKi) :: nt ! Current time step + INTEGER(IntKi) :: Nc ! Current ice tooth number + REAL(ReKi) :: Psumc ! Current sum of pitch of broken ice teeth (m) + REAL(ReKi) :: Dmc ! Delmax of the current tooth (m) + REAL(ReKi) :: Pc ! Pitch of the current tooth (m) + REAL(ReKi) :: Pnxt ! Pitch of the next ice tooth (m) + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL IceD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, 'IceD_UpdateStates') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! interpolate u to find u_interp = u(t) + CALL IceD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, 'IceD_UpdateStates') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + nt = n+1 !bjj: was this: INT( t / p%dt ) + 1 + + ! Update Other states here for ice model 2 + + IF (p%ModNo == 2) THEN + + Del2 = p%InitLoc + p%v * t - p%Pitch * (OtherState%IceTthNo2 -1) - u_interp%PointMesh%TranslationDisp(1,1) + + IF ( Del2 >= (p%Delmax2 - p%tolerance) ) THEN + + OtherState%IceTthNo2 = OtherState%IceTthNo2 + 1 + !CALL WrScr( 'IceTthNo=' // Num2LStr(xd%IceTthNo2) ) + + ENDIF + + ENDIF + + ! Update Other states here for ice model 3 + + IF (p%ModNo == 3) THEN + Nc = OtherState%Nc (nt) + Psumc = OtherState%Psum (nt) + Pc = p%rdmP (Nc) + + IF (p%SubModNo == 3) THEN + + Del2 = p%InitLoc + p%v * t - OtherState%Psum (nt) - u_interp%PointMesh%TranslationDisp(1,1) ! Deflection of the current ice tooth + Dmc = p%RdmDm ( OtherState%Nc(nt) ) + + IF ( Del2 >= ( p%RdmDm ( OtherState%Nc(nt) ) - p%tolerance) ) THEN ! Current ice tooth breaks + + DO I= nt+1 , p%TmStep + OtherState%Nc (I) = Nc + 1 + OtherState%Psum (I) = Psumc + Pc + Pnxt = OtherState%Psum (I) + ENDDO + + ENDIF + + ENDIF + + ENDIF + + ! Update Other States here for ice model 4 + + IF (p%ModNo == 4) THEN + + DO I = 1, p%Zn + + Del (I) = p%Y0 (I) + p%v * t - p%ZonePitch * (OtherState%IceTthNo (I)-1) - u_interp%PointMesh%TranslationDisp(1,1) + + IF ( Del(I) >= (p%Delmax - p%tolerance) ) THEN + + OtherState%IceTthNo (I) = OtherState%IceTthNo (I)+1 + + ENDIF + + END DO + + END IF + + ! Update Other States here for ice model 5 + + IF (p%ModNo == 5) THEN + + OtherState%Beta = SolveBeta( p%alphaR, p%v, t - OtherState%Tinit, p%Lbr) + + IF (OtherState%Beta >= p%alphaR) THEN + OtherState%Tinit = t + END IF + + ENDIF + + ! Update Continuous states here for ice model 6 + + IF (p%ModNo == 6) THEN + + if (p%method .eq. 1) then + + CALL IceD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + elseif (p%method .eq. 2) then + + CALL IceD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + elseif (p%method .eq. 3) then + + CALL IceD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + else + + ErrStat = ErrID_Fatal + ErrMsg = ' Error in IceD_UpdateStates: p%method must be 1 (RK4), 2 (AB4), or 3 (ABM4)' + RETURN + + endif + + !IF ((x%q - u_interp%PointMesh%TranslationDisp(1,1)) >= OtherState%dxc) THEN + ! OtherState%dxc = x%q - u_interp%PointMesh%TranslationDisp(1,1) + !ENDIF + + ! Determine whether the splitting failure happens + IF (OtherState%Splitf == 0) THEN + CALL Ice_Split (t, u_interp, p, x, OtherState, ErrStat, ErrMsg) + ENDIF + + END IF + + + IF ( ErrStat >= AbortErrLev ) RETURN + + RETURN +CONTAINS + SUBROUTINE Cleanup() + + CALL IceD_DestroyInput( u_interp, ErrStat2, ErrMsg2 ) + + END SUBROUTINE Cleanup + + FUNCTION SolveBeta (alpha, vice, t, l) Result (beta1) + + !SOLVEBETA Solve for ice wedge uprising angle + + IMPLICIT NONE + + ! Input values + REAL(ReKi), intent(in) :: alpha ! Cone angle (rad) + REAL(ReKi), intent(in) :: vice ! Ice velocity (m/s) + REAL(DbKi), intent(in) :: t ! Ice time (s) + REAL(ReKi), intent(in) :: l ! Ice breaking length (m) + + REAL(ReKi) :: beta ! Initial Ice wedge uprising angle + REAL(ReKi) :: beta1 ! Ice wedge uprising angle + + REAL(ReKi) :: Equ + REAL(ReKi) :: Derv + + beta = 0 + DO i = 1,100 + + Equ = sin(beta) - tan(alpha) * cos(beta) + tan(alpha) * (1-vice*t/l); + Derv = cos(beta) + tan(alpha) * sin(beta); + + IF ( abs(Equ) <= p%tolerance) EXIT + + beta = beta - Equ / Derv + + END DO + + beta1 = beta + + END FUNCTION SolveBeta + + SUBROUTINE Ice_Split (t, u, p, x, OtherState, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(IceD_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(IceD_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState ! Other states at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variable + REAL(ReKi) :: IceForce + REAL(ReKi) :: R + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Compute outputs here: + + R = p%StrWd/2 + + IF ( OtherState%Splitf == 0 ) THEN + + IF ((x%q - u%PointMesh%TranslationDisp(1,1)) < OtherState%dxc) THEN + + IceForce = 0 + + ELSE IF ((x%q - u%PointMesh%TranslationDisp(1,1)) >= OtherState%dxc) THEN + + IF (x%q - u%PointMesh%TranslationDisp(1,1) < R) THEN + + IceForce = p%Cpa * ( 2 * p%h * ( R**2 - (R - x%q + u%PointMesh%TranslationDisp(1,1))**2 )**0.5 )**( p%dpa + 1 ) * 1.0e6 + + ELSE + + IceForce = p%Cpa * ( 2 * R * p%h )**( p%dpa + 1 ) * 1.0e6 + + ENDIF + + ENDIF + + ELSE + + IceForce = 0 + + ENDIF + + IF ( IceForce >= p%Fsp ) THEN + OtherState%Splitf = 1 + ENDIF + + END SUBROUTINE Ice_Split + + +END SUBROUTINE IceD_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE IceD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(IceD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(IceD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh + !! connectivity information does not have to be recalculated) + TYPE(IceD_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 + + ! local variables + INTEGER(IntKi) :: I ! Loop count + INTEGER(IntKi) :: nt ! Current time step + REAL(ReKi) :: Del2 ! Deflection of the current ice tooth, for model 2 + REAL(ReKi) :: Del(p%Zn) ! Deflection of each ice tooth, for model 4 + REAL(ReKi) :: ZoneF(p%Zn) ! Ice force of each ice tooth, for model 4 + REAL(ReKi) :: R ! Cone radius + REAL(ReKi) :: Pn1 ! Normal force from cone to ice piece 1, for model 5 + REAL(ReKi) :: Pn2 ! Normal force from cone to ice piece 2, for model 5 + REAL(ReKi) :: Xb ! Moment arm for buoyancy force, for model 5 + REAL(ReKi) :: Fb ! Buoyancy force, for model5 + REAL(ReKi) :: pbeta + REAL(ReKi) :: qbeta + REAL(ReKi) :: Rh ! Horizontal force, for model5 + REAL(ReKi) :: Rv ! Vertical force, for model5 + REAL(ReKi) :: Wr ! Ride-up ice weight, for model5 + REAL(ReKi) :: gamma + REAL(ReKi) :: CrntT0 + REAL(IntKi) :: dummyN + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + nt = INT( t / p%dt ) + 1 + dummyN = 1 + + ! Compute outputs here: + + ! Ice Model 1 -------------------------------- + IF (p%ModNo == 1) THEN + + IF (p%SubModNo == 1) THEN + + IF (t < p%t0 + p%tolerance) THEN + + y%PointMesh%Force(1,1) = 0 + + ELSEIF (t< p%t0 + p%tm1a + p%tolerance) THEN + + y%PointMesh%Force(1,1) = (t-p%t0) / p%tm1a * p%Fmax1a + + ELSE + + y%PointMesh%Force(1,1) = p%Fmax1a + + ENDIF + + ELSEIF (p%SubModNo == 2) THEN + + IF (t < p%t0 + p%tolerance) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (t< p%t0 + p%tm1b + p%tolerance) THEN + + y%PointMesh%Force(1,1) = (t-p%t0) / p%tm1b * p%Fmax1b + + ELSE + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ENDIF + + ELSEIF (p%SubModNo == 3) THEN + + IF (t < p%t0 + p%tolerance) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (t< p%t0 + p%tm1c + p%tolerance) THEN + + y%PointMesh%Force(1,1) = (t-p%t0) / p%tm1c * p%Fmax1c + + ELSE + + y%PointMesh%Force(1,1) = p%Fmax1c + + ENDIF + + ENDIF + + ENDIF + + ! Ice Model 2 -------------------------------- + + IF (p%ModNo == 2) THEN + + Del2 = p%InitLoc + p%v * t - p%Pitch * (OtherState%IceTthNo2 -1) - u%PointMesh%TranslationDisp(1,1) + + IF (p%Delmax2 <= p%Pitch) THEN !Sub-model 1 + + IF ( Del2 <= 0) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (Del2 < p%Delmax2 + p%tolerance) THEN + + y%PointMesh%Force(1,1) = Del2 * p%Kice2 + + ELSE + + !ErrStat = ErrID_Fatal + y%PointMesh%Force(1,1) = Del2 * p%Kice2 + CALL WrScr ( ' Warning in IceDyn Model 2: Ice tooth does not break when Del>Delmax') + + ENDIF + + ELSEIF (p%Delmax2 <= 2*p%Pitch) THEN !Sub-model 2, two ice teeth bending + + IF ( Del2 <= 0) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (Del2 < p%Pitch) THEN + + y%PointMesh%Force(1,1) = Del2 * p%Kice2 + + ELSEIF (Del2 < p%Delmax2 + p%tolerance) THEN + + y%PointMesh%Force(1,1) = Del2 * p%Kice2 + (Del2 - p%Pitch) * p%Kice2 + + ELSE + + !ErrStat = ErrID_Fatal + y%PointMesh%Force(1,1) = Del2 * p%Kice2 + (Del2 - p%Pitch) * p%Kice2 + CALL WrScr ( ' Warning in IceDyn Model 2: Ice tooth does not break when Del>Delmax' ) + + ENDIF + + ELSE + ErrStat = ErrID_Fatal + ErrMsg = ' Error in IceDyn Model 2.2: input delmax > 2*pitch' + ENDIF + + END IF + + IF (p%ModNo == 3) THEN + + IF (p%SubModNo == 1) THEN + + IF ( t <= p%rdmt0 (nt) ) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (t <= p%rdmt0 (nt) + p%rdmtm (nt)) THEN + + y%PointMesh%Force(1,1) = (t-p%rdmt0 (nt)) / p%rdmtm(nt) * p%rdmFm (nt) + + ELSE + + y%PointMesh%Force(1,1) = p%rdmFm (nt) + + ENDIF + + ELSEIF (p%SubModNo == 2) THEN + + CrntT0 = p%rdmt0 (nt) + + IF (t <= p%rdmt0 (nt)) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSEIF (t <= p%rdmt0 (nt) + p%rdmtm (nt)) THEN + + y%PointMesh%Force(1,1) = (t-p%rdmt0 (nt)) / p%rdmtm(nt) * p%rdmFm (nt) + + ELSE + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ENDIF + + ELSEIF (p%SubModNo == 3) THEN + + Del2 = p%InitLoc + p%v * t - OtherState%Psum (nt) - u%PointMesh%TranslationDisp(1,1) ! Determine the contact state between ice sheet and the tower + + !IF (Del2 >= xd%Dmaxn) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = ' Error in IceDyn Model 3c: two ice teeth break at once' + !ENDIF + + IF (Del2 <= 0) THEN + + y%PointMesh%Force(1,1) = 0.0_ReKi + + ELSE IF (Del2 > 0 .AND. Del2 <= p%rdmP (OtherState%Nc(nt)) ) THEN + + y%PointMesh%Force(1,1) = p%rdmKi(OtherState%Nc(nt)) * Del2 + + ELSE + + y%PointMesh%Force(1,1) = p%rdmKi(OtherState%Nc(nt)) * Del2 + p%rdmKi(OtherState%Nc(nt+1)) * (Del2-p%rdmP (OtherState%Nc(nt))) ! Two teeth in contact + + ENDIF + + ENDIF + + ENDIF + + ! Ice Model 4 -------------------------------- + + IF (p%ModNo == 4) THEN + + DO I = 1, p%Zn + + Del (I) = p%Y0 (I) + p%v * t - p%ZonePitch * (OtherState%IceTthNo (I)-1) - u%PointMesh%TranslationDisp(1,1) + + IF ( Del (I) <= 0) THEN + + ZoneF (I) = 0.0 + + ELSEIF (Del (I) < p%Delmax + p%tolerance) THEN + + ZoneF (I) = Del (I) * p%Kice + + ELSE + + !ErrStat = ErrID_Fatal + ZoneF (I) = Del (I) * p%Kice + CALL WrScr (' Warning in IceDyn Model 4: ZoneDel > Delmax') + + ENDIF + + END DO + + IF (sum(ZoneF) <0) THEN + + dummyN = dummyN + 1 + + ENDIF + + y%PointMesh%Force(1,1) = sum(ZoneF) + + END IF + + ! Ice Model 5 -------------------------------- + + IF (p%ModNo == 5) THEN + + IF (t <= OtherState%Tinit) THEN + + y%PointMesh%Force(1,1) = 0 + + ELSE IF (t <= OtherState%Tinit + p%dt) THEN ! Ice load at breakage + + y%PointMesh%Force(1,1) = p%RHbr + + ELSE ! Ice load after breakage + + Wr = p%Wri * ( p%Zr - p%Lbr * sin(OtherState%Beta) ) / p%Zr + Pn1 = Wr * cos(p%alphaR) + gamma = p%rhoi / p%rhow + + IF (OtherState%Beta < gamma * p%h / p%Lbr) THEN + + Xb = p%Lbr /3.0 *( ( 3.0*gamma*p%h - p%Lbr*tan(OtherState%Beta) ) / ( 2.0 *gamma*p%h - p%Lbr*tan(OtherState%Beta) ) ) + Fb = p%rhow * 9.81 * p%Dwl * (0.5 * p%Lbr**2 * tan(OtherState%Beta) + p%Lbr*(gamma*p%h - p%Lbr*tan(OtherState%Beta)) ) + + ELSE + + Xb = 1.0/3.0 * gamma * p%h / sin(OtherState%Beta) + Fb = p%rhow * 9.81 * p%Dwl * (0.5 * (gamma*p%h)**2 / tan(OtherState%Beta) ) + + END IF + + pbeta = sin(OtherState%Beta) * ( sin(p%alphaR) + p%mu*cos(p%alphaR) ) + cos(OtherState%Beta) * ( cos(p%alphaR) - p%mu*sin(p%alphaR) ) + qbeta = ( sin(p%alphaR) + p%mu*cos(p%alphaR) ) * sin( p%alphaR - OtherState%Beta ) + + Pn2 = ( p%WL * p%Lbr /2.0 * cos(OtherState%Beta) + Wr * p%Lbr * qbeta - Fb*Xb) / pbeta / p%Lbr + + Rh = ( Pn1 + Pn2 ) * ( sin(p%alphaR) + p%mu*cos(p%alphaR) ) + Rv = ( Pn1 + Pn2 ) * ( cos(p%alphaR) - p%mu*sin(p%alphaR) ) + + IF (Rh < 0) THEN + y%PointMesh%Force(1,1) = 0 + ELSE + y%PointMesh%Force(1,1) = Rh + ENDIF + + ENDIF + + ENDIF + + ! Ice Model 6 -------------------------------- + IF (p%ModNo == 6) THEN + + R = p%StrWd/2 + + IF ( OtherState%Splitf == 0 ) THEN + + IF ((x%q - u%PointMesh%TranslationDisp(1,1)) < OtherState%dxc) THEN + + y%PointMesh%Force(1,1) = 0 + + ELSE IF ((x%q - u%PointMesh%TranslationDisp(1,1)) >= OtherState%dxc) THEN + + IF (x%q - u%PointMesh%TranslationDisp(1,1) < R) THEN + + y%PointMesh%Force(1,1) = p%Cpa * ( 2 * p%h * ( R**2 - (R - x%q + u%PointMesh%TranslationDisp(1,1))**2 )**0.5 )**( p%dpa + 1 ) * 1.0e6 + + ELSE + + y%PointMesh%Force(1,1) = p%Cpa * ( 2 * R * p%h )**( p%dpa + 1 ) * 1.0e6 + + ENDIF + + ENDIF + + ELSE + + y%PointMesh%Force(1,1) = 0 + + ENDIF + + ENDIF + + !y%PointMesh%Force(1,1) = y%fice + !y%PointMesh%Force(2,1) = 0. + !y%PointMesh%Force(3,1) = 0. + + + ! values to write to a file: + y%WriteOutput(1) = x%q ! IceDisp !bjj: todo: do we need to recalculate this??? + y%WriteOutput(2) = y%PointMesh%Force(1,1) ! IceForce + + +END SUBROUTINE IceD_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing derivatives of continuous states. +SUBROUTINE IceD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(IceD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(IceD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(IceD_ContinuousStateType), INTENT( OUT) :: xdot !< Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + ! REAL(ReKi) :: mass ! Mass of ice feature (kg) + REAL(ReKi) :: force ! Ice force (N) + REAL(ReKi) :: R ! Structure radius + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + IF (p%ModNo == 6) THEN + + ! Compute the first time derivatives of the continuous states here: + + ! When the ice and the structure is in contact, there is ice force. + + R = p%StrWd/2 + + IF ( OtherState%Splitf == 0 ) THEN + + IF ((x%q - u%PointMesh%TranslationDisp(1,1)) < OtherState%dxc) THEN + + force = 0 + p%FdrN + + ELSE IF ((x%q - u%PointMesh%TranslationDisp(1,1)) >= OtherState%dxc) THEN + + IF (x%q - u%PointMesh%TranslationDisp(1,1) < R) THEN + + force = -p%Cpa * ( 2 * p%h * ( R**2 - (R - x%q + u%PointMesh%TranslationDisp(1,1))**2 )**0.5 )**( p%dpa + 1 ) * 1.0e6 + p%FdrN + + ELSE + + force = -p%Cpa * ( 2 * R * p%h )**( p%dpa + 1 ) * 1.0e6 + p%FdrN + + ENDIF + + ENDIF + + ELSE + + force = 0 + + ENDIF + + xdot%q = x%dqdt + + xdot%dqdt = force / p%Mice + + ENDIF + + +END SUBROUTINE IceD_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for updating discrete states +SUBROUTINE IceD_UpdateDiscState( t, n, u, 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(IceD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(IceD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !< Output: Discrete states at t + Interval + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(IceD_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 + + ! local variables + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Update discrete states here: + xd%DummyDiscState = 0.0 + +END SUBROUTINE IceD_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for solving for the residual of the constraint state functions +SUBROUTINE IceD_CalcConstrStateResidual( t, u, p, x, xd, z, OtherState, m, Z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(IceD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(IceD_ConstraintStateType), INTENT( OUT) :: Z_residual !< Residual of the constraint state functions using + !! the input values described above + TYPE(IceD_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + Z_residual%DummyConstrState = 0 + +END SUBROUTINE IceD_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- +!> This public subroutine reads the input required for IceDyn from the file whose name is an +!! input parameter. +SUBROUTINE IceD_ReadInput( InitInp, InputFileData, ErrStat, ErrMsg ) +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(IceD_InitInputType), INTENT( IN ) :: InitInp !< the IceDyn initial input data + TYPE(IceD_InputFile), INTENT( OUT ) :: InputFileData !< Data stored in the IceDyn's input file + INTEGER, INTENT( OUT ) :: ErrStat !< returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + + INTEGER :: UnIn ! Unit number for the input file + CHARACTER(ErrMsgLen) :: FileName ! Name of HydroDyn input file + + INTEGER :: UnEc ! Unit number for the echo file + LOGICAL, PARAMETER :: Echo = .FALSE. ! echo file for debugging +! LOGICAL, PARAMETER :: Echo = .TRUE. ! echo file for debugging (bjj: would like to add this feature to the input file) + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + UnEc = -1 + UnIn = -1 + + !------------------------------------------------------------------------------------------------- + ! Open the file + !------------------------------------------------------------------------------------------------- + IF ( Echo ) THEN + CALL GetNewUnit( UnEc, ErrStat, ErrMsg ) + CALL OpenFOutFile( UnEc, TRIM(InitInp%RootName)//'.IceD.ech', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ' Error opening echo file: "'//TRIM(ErrMsg)//'". Simulation will continue with no IceDyn echo file.' ) + CLOSE( UnEc ) + UnEc = -1 + END IF + END IF + + + + FileName = TRIM(InitInp%InputFile) + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + CALL OpenFInpFile( UnIn, FileName, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + !CALL WrScr( 'Opening IceDyn input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'IceDyn input file header line 1', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + CALL ReadCom( UnIn, FileName, 'IceDyn input file header line 2', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Structure properties + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'IceDyn structure properties header line', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! NumLegs - Number of support-structure legs in contact with ice + + CALL ReadVar ( UnIn, FileName, InputFileData%NumLegs, 'NumLegs', 'Number of support-structure legs in contact with ice', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + IF ( InputFileData%NumLegs < 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'IceD_ReadInput: NumLegs must be a positive number.' + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%LegPosX, InputFileData%NumLegs, 'LegPosX', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%LegPosY, InputFileData%NumLegs, 'LegPosY', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + CALL AllocAry( InputFileData%StrWd, InputFileData%NumLegs, 'StrWd', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! LegPosX - Global X position of legs 1-NumLegs (m) + + CALL ReadAry ( UnIn, FileName, InputFileData%LegPosX, InputFileData%NumLegs, 'LegPosX', 'Global X position of legs, 1-NumLegs (m)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! LegPosY - Global Y position of legs 1-NumLegs (m) + + CALL ReadAry ( UnIn, FileName, InputFileData%LegPosY, InputFileData%NumLegs, 'LegPosY', 'Global Y position of legs, 1-NumLegs (m)', ErrStat, ErrMsg, UnEc ) + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! StWidth - Width of the structure in contact with the ice (m) + + CALL ReadAry ( UnIn, FileName, InputFileData%StrWd, InputFileData%NumLegs, 'StWidth', 'Width of the structure in contact with the ice (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Ice Model Number + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice Models header', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! IceModel - Number that represents different ice models. + + CALL ReadVar ( UnIn, FileName, InputFileData%IceModel, 'IceModel', 'Number that represents different ice models', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! IceSubModel - Number that represents different ice sub models. + + CALL ReadVar ( UnIn, FileName, InputFileData%IceSubModel, 'IceSubModel', 'Number that represents different ice sub-models', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - General + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - General header', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! IceVel - Velocity of ice sheet movement (m/s) + + CALL ReadVar ( UnIn, FileName, InputFileData%v, 'IceVel', 'Velocity of ice sheet movement', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! IceThks - Thickness of the ice sheet (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%h, 'IceThks', 'Thickness of the ice sheet (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! WtDen - Mass density of water (kg/m3) + + CALL ReadVar ( UnIn, FileName, InputFileData%rhow, 'WtDen', 'Mass density of water (kg/m3)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read WtDen parameter.' + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! IceDen - Mass density of ice (kg/m3) + + CALL ReadVar ( UnIn, FileName, InputFileData%rhoi, 'IceDen', 'Mass density of ice (kg/m3)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! InitLoc - Ice sheet initial location (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%InitLoc, 'InitLoc', 'Ice sheet initial location (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! InitTm - Ice load starting time (s) + + CALL ReadVar ( UnIn, FileName, InputFileData%t0, 'InitTm', 'Ice load starting time (s)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Seed1 - Random seed 1 + + CALL ReadVar ( UnIn, FileName, InputFileData%Seed1, 'Seed1', 'Random seed 1', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Seed2 - Random seed 2 + + CALL ReadVar ( UnIn, FileName, InputFileData%Seed2, 'Seed2', 'Random seed 2', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 1 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 1 SubModel 1', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Ikm - Indentation factor + + CALL ReadVar ( UnIn, FileName, InputFileData%Ikm, 'Ikm', 'Indentation factor', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Ag - Constant depends only on ice crystal type, used in calculating uniaxial stress (MPa-3s-1) + + CALL ReadVar ( UnIn, FileName, InputFileData%Ag, 'Ag', 'Constant depends only on ice crystal type, used in calculating uniaxial stress (MPa-3s-1)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Qg - Activation Energy (kJ•mol^-1) + + CALL ReadVar ( UnIn, FileName, InputFileData%Qg, 'Qg', 'Activation Energy (kJ•mol^-1)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Rg - Universal gas constant (J•mol-1K-1) + + CALL ReadVar ( UnIn, FileName, InputFileData%Rg, 'Rg', 'Universal gas constant (J•mol-1K-1)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Tice - Ice temperature (K) + + CALL ReadVar ( UnIn, FileName, InputFileData%Tice, 'Tice', 'Ice temperature (K)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 1 SubModel 2', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Poisson - Poisson's ratio of ice + + CALL ReadVar ( UnIn, FileName, InputFileData%nu, 'Poisson', 'Poisson ratio of ice', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! WgAngle - Wedge Angel, degree. Default 45 Degrees. + + CALL ReadVar ( UnIn, FileName, InputFileData%phi, 'WgAngle', ' Wedge Angel, degree. Default 45 Degrees', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! EIce - Young's modulus of ice (GPa) + + CALL ReadVar ( UnIn, FileName, InputFileData%Eice, 'EIce', 'Youngs modulus of ice (GPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 1 SubModel 3', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! SigN - Nominal ice stress (MPa) + + CALL ReadVar ( UnIn, FileName, InputFileData%SigNm, 'SigNm', 'Nominal ice stress (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 2 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 2 SubModel 1,2', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Pitch - Distance between sequential ice teeth (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Pitch, 'Pitch', 'Distance between sequential ice teeth (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! IceStr2 - Ice failure stress (MPa) + + CALL ReadVar ( UnIn, FileName, InputFileData%IceStr2, 'IceStr2', 'Ice failure stress (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Delmax2 - Ice tooth maximum elastic deformation (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Delmax2, 'Delmax2', 'Ice tooth maximum elastic deformation (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 3 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice PROPERTIES -Ice Model 3, SubModel 1,2', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! ThkMean - Mean value of ice thickness (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%miuh, 'ThkMean', 'Mean value of ice thickness (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! ThkVar - Variance of ice thickness (m^2) + + CALL ReadVar ( UnIn, FileName, InputFileData%varh, 'ThkVar', 'Variance of ice thickness (m^2)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! VelMean - Mean value of ice velocity (m/s) + + CALL ReadVar ( UnIn, FileName, InputFileData%miuv, 'VelMean', 'Mean value of ice velocity (m/s)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! VelVar - Variance of ice velocity (m^2/s^2) + + CALL ReadVar ( UnIn, FileName, InputFileData%varv, 'VelVar', 'Variance of ice velocity (m^2/s^2)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! TeMean - Mean value of ice loading event duration (s) + + CALL ReadVar ( UnIn, FileName, InputFileData%miut, 'TeMean', 'Mean value of ice loading event duration (s)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice PROPERTIES -Ice Model 3, SubModel 2,3', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! StrMean - Mean value of ice thickness (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%miubr, 'StrMean', 'Mean value of ice strength (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! StrVar - Variance of ice thickness (m^2) + + CALL ReadVar ( UnIn, FileName, InputFileData%varbr, 'StrVar', 'Variance of ice strength (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice PROPERTIES -Ice Model 3, SubModel 3', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! DelMean - Mean value of maximum ice tooth tip displacement (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%miuDelm, 'DelMean', 'Mean value of maximum ice tooth tip displacement (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! DelVar - Variance of maximum ice tooth tip displacement (m^2) + + CALL ReadVar ( UnIn, FileName, InputFileData%varDelm, 'DelVar', 'Variance of maximum ice tooth tip displacement (m^2)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! PMean - Mean value of the distance between sequential ice teeth (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%miuP, 'PMean', 'Mean value of the distance between sequential ice teeth (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + ! PVar - Variance of the distance between sequential ice teeth (m^2) + + CALL ReadVar ( UnIn, FileName, InputFileData%varP, 'PVar', 'Variance of the distance between sequential ice teeth (m^2)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CALL Cleanup() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 4 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 4', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! PrflMean - Mean value of ice contact face position (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%PrflMean, 'PrflMean', 'Mean value of ice contact face position (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! PrflSig - Standard deviation of ice contact face position (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%PrflSig, 'PrflSig', 'Standard deviation of ice contact face position (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! ZoneNo1 - Number of failure zones along contact width + + CALL ReadVar ( UnIn, FileName, InputFileData%Zn1, 'ZoneNo1', 'Number of failure zones along contact width', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! ZoneNo2 - Number of failure zones along contact height/thickness + + CALL ReadVar ( UnIn, FileName, InputFileData%Zn2, 'ZoneNo2', 'Number of failure zones along contact height/thickness', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! ZonePitch - Distance between sequential ice teeth (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%ZonePitch, 'ZonePitch', 'Distance between sequential ice teeth (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! IceStr - Ice failure stress within each failure region (MPa) + + CALL ReadVar ( UnIn, FileName, InputFileData%IceStr, 'IceStr', 'Ice failure stress within each failure region (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! Delmax - Ice teeth maximum elastic deformation (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Delmax, 'Delmax', 'Ice teeth maximum elastic deformation (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 5 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 5, Submodel 1,2', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! ConeAgl - Slope angle of the cone (degree) + + CALL ReadVar ( UnIn, FileName, InputFileData%alpha, 'ConeAgl', 'Slope angle of the cone (degree)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! ConeDwl - Cone waterline diameter (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Dwl, 'ConeDwl', 'Cone waterline diameter (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! ConeDtp - Cone top diameter (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Dtp, 'ConeDtp', 'Cone top diameter (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! RdupThk - Ride-up ice thickness (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%hr, 'RdupThk', 'Ride-up ice thickness (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! mu - Friction coefficient between structure and ice (-) + + CALL ReadVar ( UnIn, FileName, InputFileData%mu, 'mu', 'Friction coefficient between structure and ice (-)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! FlxStr - Flexural strength of ice (MPa) + + CALL ReadVar ( UnIn, FileName, InputFileData%sigf, 'FlxStr', 'Flexural strength of ice (MPa)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! StrLim - Limit strain for ice fracture failure (-) + + CALL ReadVar ( UnIn, FileName, InputFileData%StrLim, 'StrLim', 'Limit strain for ice fracture failure (-)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! StrRtLim - Limit strain rate for ice brittle behavior (s^-1) + + CALL ReadVar ( UnIn, FileName, InputFileData%StrRtLim, 'StrRtLim', 'Limit strain rate for ice brittle behavior (s^-1)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! Ice properties - Ice Model 6 + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Ice properties - Ice Model 6', ErrStat, ErrMsg, UnEc) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! FloeLth - Ice floe length (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Ll, 'FloeLth', 'Ice floe length (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! FloeWth - Ice floe width (m) + + CALL ReadVar ( UnIn, FileName, InputFileData%Lw, 'FloeWth', 'Ice floe width (m)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! CPrAr - Ice crushing strength pressure-area relation constant + + CALL ReadVar ( UnIn, FileName, InputFileData%Cpa, 'CPrAr', 'Ice crushing strength pressure-area relation constant', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! dPrAr - Ice crushing strength pressure-area relation order + + CALL ReadVar ( UnIn, FileName, InputFileData%dpa, 'dPrAr', 'Ice crushing strength pressure-area relation order', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! Fdr - Constant external driving force (MN) + + CALL ReadVar ( UnIn, FileName, InputFileData%Fdr, 'Fdr', 'Constant external driving force (MN)', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! Kic - Fracture toughness of ice (kNm^(-3/2)) + + CALL ReadVar ( UnIn, FileName, InputFileData%Kic, 'Kic', 'Fracture toughness of ice (kNm^(-3/2))', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + ! FspN - Non-dimensional splitting load + + CALL ReadVar ( UnIn, FileName, InputFileData%FspN, 'FspN', 'Non-dimensional splitting load', ErrStat, ErrMsg, UnEc ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! This is the end of the input file + !------------------------------------------------------------------------------------------------- + CALL Cleanup() + + + RETURN +CONTAINS + SUBROUTINE Cleanup() + + CLOSE( UnIn ) + IF (UnEc > 0) CLOSE(UnEc) + + END SUBROUTINE + +END SUBROUTINE IceD_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine performs validity checks on data from the input file. +SUBROUTINE IceD_ValidateInput( InputFileData, ErrStat, ErrMsg ) + TYPE(IceD_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( InputFileData%IceModel < 1 .OR. InputFileData%IceModel > 6 ) CALL SetErrStat( ErrID_Fatal, 'IceModel must be a number 1-6.', ErrStat, ErrMsg, 'IceD_ValidateInput') + IF ( InputFileData%IceSubModel < 1 ) CALL SetErrStat( ErrID_Fatal, 'Invalid IceSubModel value', ErrStat, ErrMsg, 'IceD_ValidateInput') + + + +END SUBROUTINE IceD_ValidateInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This takes the primary input file data and sets the corresponding parameters. +SUBROUTINE IceD_SetParameters( InputFileData, p, Interval, Tmax, LegNum, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + + ! Passed variables + + TYPE(IceD_ParameterType), INTENT(INOUT) :: p !< Parameters of the IceDyn module + TYPE(IceD_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + REAL(DbKi), INTENT(IN) :: Interval !< Coupling interval in seconds + REAL(DbKi), INTENT(IN ) :: Tmax !< Total simulation time + INTEGER(IntKi), INTENT(IN ) :: LegNum !< Leg number of this IceDyn instance + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables + INTEGER (IntKi) :: I + ! Ice Model 1 + + REAL(ReKi) :: StrRt ! Strain rate (s^-1) + REAL(ReKi) :: SigCrp ! Creep stress (Pa) + REAL(ReKi) :: Bf ! Flexural rigidity of ice plate (Nm) + REAL(ReKi) :: kappa ! Constants in Ice Model 1b + REAL(ReKi) :: PhiR ! Phi in radius + + ! Ice Model 3 + + REAL(ReKi), allocatable :: rdmh(:) ! Random ice thickness time series (m) + REAL(ReKi), allocatable :: rdmv(:) ! Random ice velocity time series (m/s) + REAL(ReKi), allocatable :: rdmte(:) ! Random ice loading event time (s) + REAL(ReKi), allocatable :: rdmsig(:) ! Random ice strength time series (Pa) +! REAL(ReKi), allocatable :: rdmTstr(:) ! Random ice strength of ice teeth (Pa) + REAL(ReKi) :: t ! Time for generating random parameters time series (s) + REAL(ReKi) :: rdmScrp ! Random ice creeping strength (MPa) + INTEGER(IntKi) :: Nthmax ! Approximate maximum ice teeth number + INTEGER(IntKi) :: nSeeds ! Number of seeds needed to generate random number + INTEGER(IntKi), allocatable :: TmpIceSeeds(:) ! Random seeds needed for initialization random number generater for IceDyn + INTEGER(IntKi) :: J ! Loop count + REAL(ReKi) :: h_dmmy ! Dummy random number for h (m) + REAL(ReKi) :: v_dmmy ! Dummy random number for v (m/s) + REAL(ReKi) :: t_dmmy ! Dummy random number for t (s) + REAL(ReKi) :: s_dmmy ! Dummy random number for sig (Pa) + REAL(ReKi) :: Dm_dmmy ! Dummy random number for Dmax (m) + REAL(ReKi) :: P_dmmy ! Dummy random number for P (m) + REAL(ReKi) :: CrntT0 + + ! Ice Model 4 + REAL(ReKi) :: ZoneWd ! Width of a single failure zone + REAL(ReKi) :: ZoneHt ! Height of a single failuer zone + + ! Ice Model 5 + REAL(ReKi) :: flexStrPa ! Ice flexural strength (Pa) + REAL(ReKi) :: A(6) ! Coefficients when calculating ice breaking force using sub-model 1 + REAL(ReKi) :: Pn1 + REAL(ReKi) :: Pn2 + REAL(ReKi) :: F1 + REAL(ReKi) :: Lxlim1 + REAL(ReKi) :: Lxlim2 + REAL(ReKi) :: Pbr + + + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + + p%verif = 1 + p%method = 1 ! integration method (RK4) + p%dt = Interval + p%tolerance = 1e-6 + + + !............................................................................................................................... + ! Direct copy of variables: + !............................................................................................................................... + p%ModNo = InputFileData%IceModel + p%SubModNo = InputFileData%IceSubModel + p%v = InputFileData%v + p%h = InputFileData%h + p%InitLoc = InputFileData%InitLoc + p%t0 = InputFileData%t0 + p%StrWd = InputFileData%StrWd( LegNum ) + p%Tmax = Tmax + + ! Ice Model 1 + p%Ikm = InputFileData%Ikm + + ! Ice Model 2 + p%Delmax2 = InputFileData%Delmax2 + p%Pitch = InputFileData%Pitch + + IF (p%Delmax2 >= 2*p%Pitch) THEN + + ErrStat = ErrID_Fatal + ErrMsg = ' Error in IceDyn Model 2: Input Delmax2 should not be larger than 2*Pitch' + + ENDIF + + ! Ice Model 4 + p%Delmax = InputFileData%Delmax + p%ZonePitch = InputFileData%ZonePitch + + ! Ice Model 5 + p%rhoi = InputFileData%rhoi + p%rhow = InputFileData%rhow + p%Dwl = InputFileData%Dwl + p%mu = InputFileData%mu + + ! Ice Model 6 + p%Cpa = InputFileData%Cpa + p%dpa = InputFileData%dpa + + + !............................................................................................................................... + ! Calculate some indirect inputs: + !............................................................................................................................... + + StrRt = p%v / 4.0 / p%StrWd + p%EiPa = InputFileData%EIce * 1.0e9 + + ! Ice Model 1a ------------------------------------------------------------------------- + + SigCrp = ( 1.0/InputFileData%Ag * exp( InputFileData%Qg / InputFileData%Rg / InputFileData%Tice ) * StrRt )**(1.0/3.0) * 1e6 + p%Cstr = ( 1.0/InputFileData%Ag * exp( InputFileData%Qg / InputFileData%Rg / InputFileData%Tice ) )**(1.0/3.0) * 1e6 + p%Fmax1a = InputFileData%Ikm * p%StrWd * p%h * SigCrp + p%tm1a = InputFileData%Ikm * SigCrp / p%EiPa / StrRt + + ! Ice Model 1b + + Bf = p%EiPa * p%h**3 / 12.0 / (1.0-InputFileData%nu**2.0) + kappa = ( InputFileData%rhow * 9.81 / 4.0 / Bf ) ** 0.25 !bjj: can you use the gravitational constant defined in FAST? now stored in InitInput%gravity + PhiR = InputFileData%phi / 180.0 * 3.1415927 !bjj todo: you can use "D2R" from NWTC_Library to convert degrees to radians + p%Fmax1b = 5.3 * Bf * kappa * ( kappa * p%StrWd + 2 * tan(PhiR/2.0) ) + p%tm1b = p%Fmax1b / p%StrWd / p%h / p%EiPa / StrRt + + ! Ice Model 1c + + p%Fmax1c = p%StrWd * p%h * InputFileData%SigNm *1e6 + p%tm1c = InputFileData%SigNm *1e6 / p%EiPa / StrRt + + ! Ice Model 2 ------------------------------------------------------------------------- + + p%Kice2 = InputFileData%IceStr2 *1e6 * p%StrWd * p%h / p%Delmax2 + + ! Ice Model 3 ------------------------------------------------------------------------- + + p%TmStep = INT( p%Tmax / p%dt ) + 1 + Nthmax = p%v * p%Tmax / InputFileData%miuP * 2 + + ! Random number initialization + + CALL RANDOM_SEED ( SIZE = nSeeds ) + + IF ( nSeeds /= 2 ) THEN + CALL ProgWarn( ' The random number generator in use differs from the original code provided by NREL. This pRNG uses ' & + //TRIM(Int2LStr(nSeeds))//' seeds instead of the 2 in the IceDyn input file.') + ErrStat = ErrID_Warn + END IF + + ALLOCATE ( TmpIceSeeds ( nSeeds ), STAT=ErrStat ) + IF (ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for TmpIceSeeds array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ! We'll just populate this with odd seeds = Seed(1) and even seeds = Seed(2) + + DO I = 1,nSeeds,2 + TmpIceSeeds(I) = InputFileData%Seed1 + END DO + DO I = 2,nSeeds,2 + TmpIceSeeds(I) = InputFileData%Seed2 + END DO + + CALL RANDOM_SEED ( PUT=TmpIceSeeds ) + DEALLOCATE(TmpIceSeeds, STAT=ErrStat) + IF (ErrStat /= ErrID_None ) THEN + CALL ProgWarn( ' Error deallocating space for TmpIceSeeds array.' ) + ErrStat = ErrID_Warn + END IF + + ! Submodel 1 and 2 + + CALL AllocAry( p%rdmFm, p%TmStep, 'rdmFm', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%rdmt0, p%TmStep, 'rdmt0', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%rdmtm, p%TmStep, 'rdmtm', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( rdmh, p%TmStep, 'rdmh', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( rdmv, p%TmStep, 'rdmv', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( rdmte, p%TmStep, 'rdmte', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( rdmsig, p%TmStep, 'rdmsig', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Submodel 3 + + CALL AllocAry( p%rdmDm, Nthmax, 'rdmDm', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%rdmP, Nthmax, 'rdmP', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%rdmKi, Nthmax, 'rdmKi', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !CALL AllocAry( p%rdmTstr, Nthmax, 'rdmTstr', ErrStat, ErrMsg ) + !IF ( ErrStat >= AbortErrLev ) RETURN + + + + IF (p%SubModNo == 1) THEN + + DO J = 1,p%TmStep + + t = J*Interval + IF( J == 1 ) THEN + p%rdmt0(J) = 0 + CALL IceD_Generate_RandomNum ( rdmh(J), rdmv(J), rdmte(J), s_dmmy, Dm_dmmy, P_dmmy, p, InputFileData, ErrStat, ErrMsg) + rdmScrp = p%Cstr * ( rdmv(J) / 4.0 / p%StrWd )**(1.0/3.0) + p%rdmFm(J) = InputFileData%Ikm * p%StrWd * rdmh(J) * rdmScrp + p%rdmtm(J) = InputFileData%Ikm * rdmScrp / p%EiPa / ( rdmv(J) / 4.0 / p%StrWd ) + ELSEIF ( t < p%rdmt0 (J-1) + rdmte (J-1) ) THEN + rdmh(J) = rdmh(J-1) + rdmv(J) = rdmv(J-1) + rdmte(J) = rdmte(J-1) + rdmsig(J) = rdmsig(J-1) + p%rdmFm(J) = p%rdmFm(J-1) + p%rdmt0(J) = p%rdmt0(J-1) + p%rdmtm(J) = p%rdmtm(J-1) + ELSE + p%rdmt0(J) = p%rdmt0 (J-1) + rdmte (J-1) + CALL IceD_Generate_RandomNum ( rdmh(J), rdmv(J), rdmte(J), s_dmmy, Dm_dmmy, P_dmmy, p, InputFileData, ErrStat, ErrMsg) + rdmScrp = p%Cstr * ( rdmv(J) / 4.0 / p%StrWd )**(1.0/3.0) + p%rdmFm(J) = InputFileData%Ikm * p%StrWd * rdmh(J) * rdmScrp + p%rdmtm(J) = InputFileData%Ikm * rdmScrp / p%EiPa / ( rdmv(J) / 4.0 / p%StrWd ) + ENDIF + + END DO + + ELSEIF (p%SubModNo == 2) THEN + + DO J = 1,p%TmStep + + t = J*Interval + IF( J == 1 ) THEN + p%rdmt0(J) = 0 + CALL IceD_Generate_RandomNum ( rdmh(J), rdmv(J), rdmte(J), rdmsig(J), Dm_dmmy, P_dmmy, p, InputFileData, ErrStat, ErrMsg) + p%rdmFm(J) = p%StrWd * rdmh(J) * rdmsig(J) + p%rdmtm(J) = rdmsig(J) / p%EiPa / ( rdmv(J) / 4.0 / p%StrWd ) + ELSEIF ( t < p%rdmt0 (J-1) + rdmte (J-1) ) THEN + rdmh(J) = rdmh(J-1) + rdmv(J) = rdmv(J-1) + rdmte(J) = rdmte(J-1) + rdmsig(J) = rdmsig(J-1) + p%rdmFm(J) = p%rdmFm(J-1) + p%rdmt0(J) = p%rdmt0(J-1) + p%rdmtm(J) = p%rdmtm(J-1) + ELSE + p%rdmt0(J) = p%rdmt0 (J-1) + rdmte (J-1) + CALL IceD_Generate_RandomNum ( rdmh(J), rdmv(J), rdmte(J), rdmsig(J), Dm_dmmy, P_dmmy, p, InputFileData, ErrStat, ErrMsg) + p%rdmFm(J) = p%StrWd * rdmh(J) * rdmsig(J) + p%rdmtm(J) = rdmsig(J) / p%EiPa / ( rdmv(J) / 4.0 / p%StrWd ) + ENDIF + CrntT0 = p%rdmt0 (J) !bjj: doesn't appear to be used... + END DO + + ELSEIF (p%SubModNo == 3) THEN + + DO J = 1, Nthmax + CALL IceD_Generate_RandomNum ( h_dmmy, v_dmmy, t_dmmy, rdmsig(J), p%rdmDm(J), p%rdmP(J), p, InputFileData, ErrStat, ErrMsg) + p%rdmKi(J) = rdmsig(J) * p%StrWd * p%h / p%rdmDm(J) + END DO + + ENDIF + + ! Ice Model 4 + ZoneWd = p%StrWd / REAL(InputFileData%Zn1) + ZoneHt = InputFileData%h / REAL(InputFileData%Zn2) + p%Kice = InputFileData%IceStr *1e6 * ZoneWd * ZoneHt / InputFileData%Delmax + + p%Zn = InputFileData%Zn1 * InputFileData%Zn2 ! Total number of failure zones + + CALL AllocAry( p%ContPrfl, p%Zn, 'ContPrfl', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( p%Y0, p%Zn, 'ContPrfl', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + DO I = 1,p%Zn + p%ContPrfl (I) = InputFileData%PrflMean + InputFileData%PrflSig * random_normal() + !CALL WrScr ( Num2LStr( p%ContPrfl (I) ) ) + END DO + + p%Y0 = InputFileData%InitLoc + p%ContPrfl - MAXVAL(p%ContPrfl) + + ! Ice Model 5 + flexStrPa = InputFileData%sigf * 1e6 + + p%alphaR = InputFileData%alpha / 180.0 * 3.1415927 + p%Zr = (InputFileData%Dwl - InputFileData%Dtp) / 2 * tan(p%alphaR) + p%Wri = p%rhoi * 9.81 * p%Dwl * p%h * p%Zr / sin(p%alphaR) + + IF (p%SubModNo == 1) THEN + + p%LovR = SolveLambda ( p%rhoi, p%h, p%Dwl, flexStrPa ) + p%Lbr = p%LovR * p%Dwl / 2 + A = BrkLdPar (p%alphaR, p%LovR, InputFileData%mu) + + p%RHbr = ( A(1) * flexStrPa * p%h**2 + A(2) * p%rhoi * 9.81 * p%h * p%Dwl**2 + A(3) * p%rhoi * 9.81 * p%h * (p%Dwl**2 - InputFileData%Dtp**2) ) * A(4) + p%RVbr = A(5) * p%RHbr + A(6) * p%rhoi * 9.81 * p%h * (p%Dwl**2 - InputFileData%Dtp**2) + + + ELSEIF (p%SubModNo == 2) THEN + + Pbr = 8.0 * sqrt(2.0) * ( ( flexStrPa * p%h**2) / 4 ) + Pn1 = p%Wri * cos(p%alphaR) + F1 = p%Wri * ( sin(p%alphaR) + p%mu * cos(p%alphaR) ); + Pn2 = ( Pbr + F1*sin(p%alphaR) ) / ( cos(p%alphaR) - p%mu * sin(p%alphaR) ) + + p%RHbr = (Pn1 + Pn2) * ( sin(p%alphaR) + p%mu * cos(p%alphaR) ) + p%RVbr = (Pn1 + Pn2) * ( cos(p%alphaR) - p%mu * sin(p%alphaR) ) + + Lxlim1 = ( 3.0 * sqrt(6.0) ) / 8.0 * ( p%v * tan(p%alphaR) ) / InputFileData%StrRtLim !Limit strain rate criteria + Lxlim2 = sqrt(6.0) * ( ( flexStrPa * p%h**2) / 4 / (p%rhow * 9.81) / InputFileData%StrLim )**(1.0/3.0) + + IF (Lxlim1 <= Lxlim2) THEN + + p%Lbr = ( 3.0 * sqrt(2.0) ) / 8.0 * ( p%v * tan(p%alphaR) ) / InputFileData%StrRtLim + + ELSE + + p%Lbr = 2.0 * ( ( flexStrPa * p%h**2) / 4 / (p%rhow * 9.81) / InputFileData%StrLim )**(1.0/3.0) + + ENDIF + + ELSE + + ErrMsg = 'Sub-model number for model 5 should be 1 or 2' + ErrStat = ErrID_Fatal + + ENDIF + + p%WL = p%rhoi * 9.81 * p%Dwl * p%h * p%Lbr + + ! Ice Model 6 + p%FdrN = InputFileData%Fdr * 1e6 + p%Mice = InputFileData%rhoi * p%h * InputFileData%Lw * InputFileData%Ll + p%Fsp = InputFileData%FspN * p%h * InputFileData%Kic * 1e3 * sqrt(InputFileData%Ll) + + + ! Deallocate local variables + + IF ( ALLOCATED(TmpIceSeeds) )THEN + DEALLOCATE(TmpIceSeeds, STAT=ErrStat) + IF (ErrStat /= ErrID_None ) THEN + CALL ProgWarn( ' Error deallocating space for TmpIceSeeds array.' ) + ErrStat = ErrID_Warn + END IF + END IF + + + IF ( ALLOCATED(TmpIceSeeds) )THEN + DEALLOCATE(TmpIceSeeds, STAT=ErrStat) + IF (ErrStat /= ErrID_None ) THEN + CALL ProgWarn( ' Error deallocating space for TmpIceSeeds array.' ) + ErrStat = ErrID_Warn + END IF + END IF + + + !............................................................................................................................... + ! Calculate Output variables: + !............................................................................................................................... + + p%NumOuts = 2 + + CALL AllocAry( p%OutName, p%NumOuts, 'OutName', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + !p%OutName (1) = 'Time' + p%OutName (1) = 'IceDisp' + p%OutName (2) = 'IceForce' + + CALL AllocAry( p%OutUnit, p%NumOuts, 'OutUnit', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + !p%OutUnit (1) = '(s)' + p%OutUnit (1) = '(m)' + p%OutUnit (2) = '(N)' + + ! Test parameter assignments + + CONTAINS + + FUNCTION random_normal() RESULT(fn_val) + + ! Adapted from the following Fortran 77 code + ! ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM. + ! THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE, + ! VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435. + + ! The function random_normal() returns a normally distributed pseudo-random + ! number with zero mean and unit variance. + + ! The algorithm uses the ratio of uniforms method of A.J. Kinderman + ! and J.F. Monahan augmented with quadratic bounding curves. + + REAL(ReKi) :: fn_val + + ! Local variables + REAL(ReKi) :: s = 0.449871, t = -0.386595, a = 0.19600, b = 0.25472, & + r1 = 0.27597, r2 = 0.27846, u, v, x, y, q + + ! Generate P = (u,v) uniform in rectangle enclosing acceptance region + + DO + CALL RANDOM_NUMBER(u) + CALL RANDOM_NUMBER(v) + v = 1.7156 * (v - 0.5) + + ! Evaluate the quadratic form + x = u - s + y = ABS(v) - t + q = x**2 + y*(a*y - b*x) + + ! Accept P if inside inner ellipse + IF (q < r1) EXIT + ! Reject P if outside outer ellipse + IF (q > r2) CYCLE + ! Reject P if outside acceptance region + IF (v**2 < -4.0*LOG(u)*u**2) EXIT + END DO + + ! Return ratio of P's coordinates as the normal deviate + fn_val = v/u + RETURN + + END FUNCTION random_normal + + + FUNCTION SolveLambda(rhoi, t, D, sigf) Result (rho) + + ! SOLVERHO Solve for rho according to Ralston model (Ralston 1978) + ! Rho = A/R, A is the first circumferential crack radius, R is the cone + ! structure waterline radius. According to first equation on Ralston + ! paper (P301), calculate rho. + + IMPLICIT NONE + + ! Input values + REAL(ReKi) :: rhoi ! Mass density of ice, (kg/m^3) + REAL(ReKi) :: t ! Ice thickness (m) + REAL(ReKi) :: D ! Cone waterline diameter (m) + REAL(ReKi) :: sigf ! Ice flextural strength (Pa) + + REAL(ReKi) :: rho ! Rho = A/R + REAL(ReKi) :: x = 1.01 ! Initial value of rho + REAL(ReKi) :: Equ + REAL(ReKi) :: Derv + + DO i = 1,100 + + Equ = x - log(x) + 0.0922 * rhoi * 9.81 * t * D**2 / sigf / t**2 * (2*x+1) * (x-1)**2 - 1.369 + Derv = 1 - 1/x + 0.0922 * rhoi * 9.81 * t * D**2 / sigf / t**2 * (2*(x-1)**2 + (2*x+1)*2*(x-1)) + + IF ( abs(Equ) <= 1e-6) THEN + + rho = x + EXIT + + END IF + + x = x - Equ / Derv + + END DO + + END FUNCTION SolveLambda + + + FUNCTION BrkLdPar (alpha, lambda, mu) Result (A) + + !BRKLDPAR Calculates Ralston's horizontal force paramters A1, A2, A3, A4 and B1, B2. + ! Detailed explanation in Ralston's paper: Ice Force Desgin Consideration + ! for Conical Offshore Structure and Ice Module Manual + + IMPLICIT NONE + + ! Input values + REAL(ReKi) :: alpha ! Cone angle, (rad) + REAL(ReKi) :: lambda ! Ratio of breaking length over cone waterline radius + REAL(ReKi) :: mu ! Friction coefficient between structure and ice + + REAL(ReKi) :: A(6) ! Coefficients when calculating ice breaking force + + ! Local variables + REAL(ReKi) :: f + REAL(ReKi) :: g + REAL(ReKi) :: h + REAL(ReKi) :: pi = 3.1415927 + + A(1) = 1.0/3.0 * ( lambda/(lambda-1) + (1-lambda+lambda*log(lambda))/(lambda-1) + 2.422* (lambda*log(lambda))/(lambda-1) ) + + A(2) = ( lambda**2 + lambda -2.0 )/12.0 + + f = pi/2.0 + pi/8.0 * (sin(alpha))**2 / (1-(sin(alpha))**2) - pi/16.0 * (sin(alpha))**4 / (1-(sin(alpha))**4) + g = ( 1.0/2.0 + alpha/sin(2*alpha) ) / ( pi/4.0*sin(alpha) + mu*alpha*cos(alpha)/sin(alpha) ) + A(3) = 1.0/4.0 * ( 1/cos(alpha) + mu*Esina(alpha,10)/sin(alpha) - mu*f*g/tan(alpha) ) + + A(4) = tan(alpha) / ( 1 - mu * g) + + h = cos(alpha) - mu/sin(alpha) * ( Esina(alpha,10) - cos(alpha)**2 * Fsina(alpha) ) + + A(5) = h / ( pi/4.0 * sin(alpha) + mu * alpha / tan(alpha) ) + A(6) = 1.0/4.0 * (pi/2.0*cos(alpha) - mu*alpha - f*h/ ( pi/4.0 * sin(alpha) + mu * alpha / tan(alpha) )) + + !CALL WrScr(Num2LStr(Esina(alpha,10))) + !CALL WrScr(Num2LStr(Fsina(alpha))) + + END FUNCTION BrkLdPar + + + FUNCTION Esina (alpha, n) Result (Esin) + !ESINA calculates E(sin(alpha)). Detailed explanation in Ice Module Manual, Model 5, Submodel 1 + + IMPLICIT NONE + + !Input variable + REAL(ReKi) :: alpha ! Cone angle, (rad) + INTEGER(IntKi) :: n + + !Output + REAL(ReKi) :: Esin + + + !Local variable + INTEGER(IntKi) :: i + REAL(ReKi) :: E = 0 + REAL(ReKi) :: pi = 3.1415927 + + DO i = 1,n + + E = E + pi/2.0*( factorial(2*(i-1)) / 2**(2*(i-1)) / (factorial(i-1))**2 )**2 * (sin(alpha))**(2*(i-1)) / (1-2*(i-1)) + + END DO + + Esin = E + + END FUNCTION Esina + + + FUNCTION Fsina (alpha) Result (F) + !ESINA calculates F(sin(alpha)). Detailed explanation in Ice Module Manual, Model 5, Submodel 1 + + IMPLICIT NONE + + !Input variable + REAL(ReKi) :: alpha ! Cone angle, (rad) + !Output + REAL(ReKi) :: F + !Local variable + REAL(ReKi) :: pi = 3.1415927 + + F = pi/2.0 + pi/8.0 * sin(alpha)**2 / (1-sin(alpha)**2) - pi/16.0 * sin(alpha)**4 / (1-sin(alpha)**4) + + END FUNCTION Fsina + + + FUNCTION factorial (n) Result (fac) + ! FACTORIAL calculates the factorial of n + + IMPLICIT NONE + + !Input variable + INTEGER(IntKi) :: n + + !Output + REAL(ReKi) :: fac + + !Local variables + INTEGER(IntKi) :: i + INTEGER(IntKi) :: M = 1 + + IF (n == 0) THEN + + fac = 1.0 + + ELSE + + DO i = 1,n + + M = M * i + + ENDDO + + ENDIF + + fac = REAL(M) + M = 1 + + END FUNCTION factorial + +END SUBROUTINE IceD_SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the other states of the module. +!! It assumes the parameters are set and that InputFileData contains initial conditions for the other states. +SUBROUTINE IceD_Init_OtherStates( OtherState, p, x, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + IMPLICIT NONE + + TYPE(IceD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(IceD_ParameterType), INTENT(IN) :: p !< Parameters of the IceDyn module + TYPE(IceD_ContinuousStateType), INTENT(IN ) :: x !< Initial continuous states + TYPE(IceD_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: I ! loop counter +! REAL(ReKi) :: StrRt ! Strain rate (s^-1) +! REAL(ReKi) :: SigCrp ! Creep stress (Pa) + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + IF ( p%ModNo == 2 ) THEN + + OtherState%IceTthNo2 = 1 ! Initialize first ice tooth number + + ELSEIF ( p%ModNo == 3 ) THEN + + CALL AllocAry( OtherState%Nc, p%TmStep, 'OtherState%Nc', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( OtherState%Psum, p%TmStep, 'OtherState%Psum', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + DO I = 1,p%TmStep + OtherState%Nc (I) = 1. ! Initialize first ice tooth number + OtherState%Psum (I) = 0. ! Initialize sum of pitches of broken ice teeth + ENDDO + + ELSEIF ( p%ModNo == 4 ) THEN + + CALL AllocAry( OtherState%IceTthNo, p%Zn, 'IceTthNo', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN ! Initialize first ice tooth number for each zone + DO I = 1,p%Zn + OtherState%IceTthNo (I) = 1 + END DO + + ELSEIF ( p%ModNo == 5 ) THEN + + OtherState%beta = 0. ! ice plate lifted angle + OtherState%Tinit = p%t0 + + ELSEIF ( p%ModNo == 6 ) THEN + + OtherState%dxc = 0. ! ice crushed depth + OtherState%Splitf = 0. ! flag to indicate if the ice floe has splitted (0 not splitted, 1 splitted) + + ENDIF + + + if ( p%method .eq. 2) then !integration methods + + Allocate( OtherState%xdot(4), STAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error in IceDyn: could not allocate OtherStat%xdot.' + RETURN + END IF + + elseif ( p%method .eq. 3) then + + Allocate( OtherState%xdot(4), STAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error in IceDyn: could not allocate OtherStat%xdot.' + RETURN + END IF + + endif + + + +END SUBROUTINE IceD_Init_OtherStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine generate random numbers for the module. +!! It assumes the parameters are set and that InputFileData contains input for generating random numbers. +SUBROUTINE IceD_Generate_RandomNum ( h, v, t, s, Dm, Pch, p, InputFileData, ErrStat, ErrMsg) +!.................................................................................................................................. + IMPLICIT NONE + + REAL(ReKi), INTENT(OUT) :: h !< Random ice thickness (m) + REAL(ReKi), INTENT(OUT) :: v !< Random ice velocity (m/s) + REAL(ReKi), INTENT(OUT) :: t !< Random ice loading event time (s) + REAL(ReKi), INTENT(OUT) :: s !< Random ice strength (Pa) + REAL(ReKi), INTENT(OUT) :: Dm !< Random ice tooth maximum displacement (m) + REAL(ReKi), INTENT(OUT) :: Pch !< Random ice tooth spacing (m) + TYPE(IceD_ParameterType), INTENT(IN) :: p !< Parameters of the IceDyn module + TYPE(IceD_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! local variables +! INTEGER(IntKi) :: I ! loop counter + REAL(ReKi) :: SigLogh ! sigma_log(h), standard deviation of log(h) + REAL(ReKi) :: MiuLogh ! miu_log(h), mean value of log(h) + REAL(ReKi) :: VelSig ! parameter for a Rayleigh distribution + REAL(ReKi) :: TeLamb ! parameter for a exponential distribution + !REAL, PARAMETER :: Pi = 3.1415927 !bjj: comes from NWTC_Library + + ! Initialize error data + ErrStat = ErrID_None + ErrMsg = '' + + !Ice thickness has a lognormal distribution + SigLogh = SQRT( LOG ( InputFileData%varh / InputFileData%miuh + 1) ) + MiuLogh = LOG ( InputFileData%miuh ) - 0.5 * SigLogh **2 + h = EXP( random_normal() * SigLogh + MiuLogh ) + + !Ice velocity has a Rayleigh distribution + VelSig = InputFileData%miuv / SQRT(Pi/2) + v = random_rayleigh (VelSig) + + !Iceloading event time has a exponential distribution + TeLamb = 1 / InputFileData%miut + t = random_exponential(TeLamb) + + !Ice strength has a Weibull distribution + s = random_weibull (InputFileData%miubr, InputFileData%varbr) * 1e6 + + !Ice teeth Delmax and pitch have normal distributions + + Dm = InputFileData%miuDelm + InputFileData%varDelm ** 0.5 * random_normal() + Pch = InputFileData%miuP + InputFileData%varP ** 0.5 * random_normal() + + + CONTAINS + +!Functions that generate random number with respect to certain distributions + + FUNCTION random_normal() RESULT(fn_val) + + ! Adapted from the following Fortran 77 code + ! ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM. + ! THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE, + ! VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435. + + ! The function random_normal() returns a normally distributed pseudo-random + ! number with zero mean and unit variance. + + ! The algorithm uses the ratio of uniforms method of A.J. Kinderman + ! and J.F. Monahan augmented with quadratic bounding curves. + + REAL :: fn_val + + ! Local variables + REAL,parameter :: s = 0.449871, t = -0.386595, a = 0.19600, b = 0.25472, & + r1 = 0.27597, r2 = 0.27846 + REAL :: u, v, x, y, q + + ! Generate P = (u,v) uniform in rectangle enclosing acceptance region + + DO + CALL RANDOM_NUMBER(u) + CALL RANDOM_NUMBER(v) + v = 1.7156 * (v - 0.5) + + ! Evaluate the quadratic form + x = u - s + y = ABS(v) - t + q = x**2 + y*(a*y - b*x) + + ! Accept P if inside inner ellipse + IF (q < r1) EXIT + ! Reject P if outside outer ellipse + IF (q > r2) CYCLE + ! Reject P if outside acceptance region + IF (v**2 < -4.0*LOG(u)*u**2) EXIT + END DO + + ! Return ratio of P's coordinates as the normal deviate + fn_val = v/u + RETURN + + END FUNCTION random_normal + + + FUNCTION random_exponential(Lambda) RESULT(fn_val) + + ! Adapted from Fortran 77 code from the book: + ! Dagpunar, J. 'Principles of random variate generation' + ! Clarendon Press, Oxford, 1988. ISBN 0-19-852202-9 + + ! FUNCTION GENERATES A RANDOM VARIATE IN [0,INFINITY) FROM + ! A NEGATIVE EXPONENTIAL DlSTRIBUTION WlTH DENSITY PROPORTIONAL + ! TO EXP(-random_exponential), USING INVERSION. + + REAL(ReKi) :: fn_val + REAL(ReKi) :: Lambda + + ! Local variable + REAL(ReKi) :: r + + DO + CALL RANDOM_NUMBER(r) + IF (r > 0.0) EXIT + END DO + + fn_val = -LOG(1-r)/lambda + RETURN + + END FUNCTION random_exponential + + + FUNCTION random_rayleigh(Sigma) RESULT(fn_val) + + ! Adapted from Fortran 77 code from the book: + ! Dagpunar, J. 'Principles of random variate generation' + ! Clarendon Press, Oxford, 1988. ISBN 0-19-852202-9 + + ! FUNCTION GENERATES A RANDOM VARIATE IN [0,INFINITY) FROM + ! A NEGATIVE EXPONENTIAL DlSTRIBUTION WlTH DENSITY PROPORTIONAL + ! TO EXP(-random_exponential), USING INVERSION. + + REAL(ReKi) :: fn_val + REAL(ReKi) :: Sigma + + ! Local variable + REAL(ReKi) :: r + + DO + CALL RANDOM_NUMBER(r) + IF (r > 0.0) EXIT + END DO + + fn_val = SQRT(-LOG(1-r)*2*sigma**2) + RETURN + + END FUNCTION random_rayleigh + + + FUNCTION random_weibull (mean,var) RESULT(fn_val) + + !Function generates a random variate in (0,infinity) from Weibull + !distribution with input mean value and variance + + IMPLICIT NONE + + REAL(ReKi) :: mean + REAL(ReKi) :: var + REAL(ReKi) :: fn_val + + !Local variables + REAL(ReKi) :: k + REAL(ReKi) :: Lambda + REAL(ReKi) :: u + + k = wbpar (mean, var) + lambda = mean / NWTC_gamma(1+1/k) + ! lambda = mean / gamma(1+1/k) + + CALL RANDOM_NUMBER(u) + fn_val = lambda * (-log(1-u)) ** (1/k) + + END FUNCTION random_weibull + + + FUNCTION wbpar (mean, var) Result (k1) + + !Calculate Weibull distribution parameters due to mean value and variance of the data + IMPLICIT NONE + + REAL(ReKi) :: mean + REAL(ReKi) :: var + REAL(ReKi) :: k + REAL(ReKi) :: k1, F1, dFdk + REAL(ReKi) :: error + + INTEGER :: I + + k = 10 + error = 1e-6 + + DO i = 1,10000 + + F1 = (NWTC_gamma(1+1/k))**2 / NWTC_gamma(1+2/k) - mean**2/(mean**2+var); + !F1 = ( gamma(1+1/k))**2 / gamma(1+2/k) - mean**2/(mean**2+var) + + IF (abs(F1) < error) EXIT + + dFdk = 2* (NWTC_gamma(1+1/k))**2 * (-1/k**2) / NWTC_gamma(1+2/k) * (digamma(1+1/k) -digamma(1+2/k)); + !dFdk = 2* ( gamma(1+1/k))**2 * (-1/k**2) / gamma(1+2/k) * (digamma(1+1/k) -digamma(1+2/k)) + k = k - F1/dFdk + + END DO + + !IF (abs(F1) >= error)THEN + + ! WrScr('Weibull parameters never found') + + !ENDIF + + + k1 = k + + END FUNCTION wbpar + + FUNCTION digamma(z) RESULT(phy) + + !Calculate the value of digamma function of z + REAL(ReKi), INTENT(IN) :: z + REAL(ReKi) :: phy + + phy = log(z) - 1./2./z - 1./12./z**2 + 1./120./z**4 - 1./252./z**6 + 1./240./z**8 - 5./660./z**10; + + END FUNCTION digamma + +END SUBROUTINE IceD_Generate_RandomNum +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." §16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE IceD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(IceD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t + TYPE(IceD_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 + + ! local variables + + TYPE(IceD_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(IceD_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(IceD_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(IceD_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(IceD_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(IceD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(IceD_InputType) :: u_interp ! interpolated value of inputs + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL IceD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! bjj: need to allocate space for u_interp so that IceD_Input_ExtrapInterp works + + ! interpolate u to find u_interp = u(t) + CALL IceD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat, ErrMsg ) + + ! find xdot at t + CALL IceD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k1%q = p%dt * xdot%q + k1%dqdt = p%dt * xdot%dqdt + + x_tmp%q = x%q + 0.5 * k1%q + x_tmp%dqdt = x%dqdt + 0.5 * k1%dqdt + + ! interpolate u to find u_interp = u(t + dt/2) + CALL IceD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%dt, ErrStat, ErrMsg) + + ! find xdot at t + dt/2 + CALL IceD_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k2%q = p%dt * xdot%q + k2%dqdt = p%dt * xdot%dqdt + + x_tmp%q = x%q + 0.5 * k2%q + x_tmp%dqdt = x%dqdt + 0.5 * k2%dqdt + + ! find xdot at t + dt/2 + CALL IceD_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k3%q = p%dt * xdot%q + k3%dqdt = p%dt * xdot%dqdt + + x_tmp%q = x%q + k3%q + x_tmp%dqdt = x%dqdt + k3%dqdt + + ! interpolate u to find u_interp = u(t + dt) + CALL IceD_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat, ErrMsg) + + ! find xdot at t + dt + CALL IceD_CalcContStateDeriv( t + p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + k4%q = p%dt * xdot%q + k4%dqdt = p%dt * xdot%dqdt + + x%q = x%q + ( k1%q + 2. * k2%q + 2. * k3%q + k4%q ) / 6. + x%dqdt = x%dqdt + ( k1%dqdt + 2. * k2%dqdt + 2. * k3%dqdt + k4%dqdt ) / 6. + + CALL Cleanup() + +CONTAINS +SUBROUTINE Cleanup() + + CALL IceD_DestroyInput( u_interp, ErrStat, ErrMsg) + CALL IceD_DestroyContState( xdot , ErrStat, ErrMsg) + CALL IceD_DestroyContState( k1 , ErrStat, ErrMsg) + CALL IceD_DestroyContState( k2 , ErrStat, ErrMsg) + CALL IceD_DestroyContState( k3 , ErrStat, ErrMsg) + CALL IceD_DestroyContState( k4 , ErrStat, ErrMsg) + CALL IceD_DestroyContState( x_tmp, ErrStat, ErrMsg) + +END SUBROUTINE Cleanup +END SUBROUTINE IceD_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE IceD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(IceD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t + TYPE(IceD_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 + + + ! local variables + TYPE(IceD_ContinuousStateType) :: xdot ! Continuous state derivs at t + TYPE(IceD_InputType) :: u_interp + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL IceD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! bjj: need to allocate space for u_interp so that IceD_Input_ExtrapInterp works + + ! need xdot at t + CALL IceD_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat, ErrMsg) + CALL IceD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + + if (n .le. 2) then + + OtherState%n = n + + OtherState%xdot ( 3 - n ) = xdot + + CALL IceD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + else + + if (OtherState%n .lt. n) then + + OtherState%n = n + OtherState%xdot(4) = OtherState%xdot(3) + OtherState%xdot(3) = OtherState%xdot(2) + OtherState%xdot(2) = OtherState%xdot(1) + + elseif (OtherState%n .gt. n) then + + ErrStat = ErrID_Fatal + ErrMsg = ' Backing up in time is not supported with a multistep method ' + RETURN + + endif + + OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date + + x%q = x%q + (p%dt / 24.) * ( 55.*OtherState%xdot(1)%q - 59.*OtherState%xdot(2)%q + 37.*OtherState%xdot(3)%q & + - 9. * OtherState%xdot(4)%q ) + + x%dqdt = x%dqdt + (p%dt / 24.) * ( 55.*OtherState%xdot(1)%dqdt - 59.*OtherState%xdot(2)%dqdt & + + 37.*OtherState%xdot(3)%dqdt - 9.*OtherState%xdot(4)%dqdt ) + + endif + + CALL Cleanup() + +CONTAINS +SUBROUTINE Cleanup() + + CALL IceD_DestroyInput( u_interp, ErrStat, ErrMsg) + CALL IceD_DestroyContState( xdot , ErrStat, ErrMsg) + +END SUBROUTINE Cleanup + + +END SUBROUTINE IceD_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! http://en.wikipedia.org/wiki/Linear_multistep_method +!! +!! or +!! +!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE IceD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(IceD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(IceD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(IceD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(IceD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t + TYPE(IceD_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 + + ! local variables + + TYPE(IceD_InputType) :: u_interp ! Continuous states at t + TYPE(IceD_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(IceD_ContinuousStateType) :: xdot_pred ! Continuous states at t + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL IceD_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) + + CALL IceD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) + + if (n .gt. 2) then + + CALL IceD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! bjj: need to allocate space for u_interp so that IceD_Input_ExtrapInterp works + CALL IceD_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat, ErrMsg) + + CALL IceD_CalcContStateDeriv(t + p%dt, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat, ErrMsg ) + + x%q = x%q + (p%dt / 24.) * ( 9. * xdot_pred%q + 19. * OtherState%xdot(1)%q - 5. * OtherState%xdot(2)%q & + + 1. * OtherState%xdot(3)%q ) + + x%dqdt = x%dqdt + (p%dt / 24.) * ( 9. * xdot_pred%dqdt + 19. * OtherState%xdot(1)%dqdt - 5. * OtherState%xdot(2)%dqdt & + + 1. * OtherState%xdot(3)%dqdt ) + + else + + x%q = x_pred%q + x%dqdt = x_pred%dqdt + + endif + + CALL Cleanup() + +CONTAINS +SUBROUTINE Cleanup() + + CALL IceD_DestroyInput( u_interp, ErrStat, ErrMsg) + CALL IceD_DestroyContState( x_pred , ErrStat, ErrMsg) + CALL IceD_DestroyContState( xdot_pred, ErrStat, ErrMsg) + +END SUBROUTINE Cleanup + +END SUBROUTINE IceD_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE IceDyn +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/icedyn/src/IceDyn_Types.f90 b/OpenFAST/modules/icedyn/src/IceDyn_Types.f90 new file mode 100644 index 000000000..5a676fa8b --- /dev/null +++ b/OpenFAST/modules/icedyn/src/IceDyn_Types.f90 @@ -0,0 +1,4065 @@ +!STARTOFREGISTRYGENERATEDFILE 'IceDyn_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 +!********************************************************************************************************************************* +! IceDyn_Types +!................................................................................................................................. +! This file is part of IceDyn. +! +! 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 IceDyn. 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 IceDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= IceD_InputFile ======= + TYPE, PUBLIC :: IceD_InputFile + INTEGER(IntKi) :: IceModel !< The current ice model number [-] + INTEGER(IntKi) :: IceSubModel !< The current ice sub-model number [-] + REAL(ReKi) :: h !< Ice thickness [m] + REAL(ReKi) :: v !< Ice velocity [m/s] + REAL(ReKi) :: InitLoc !< Ice sheet initial location [m] + REAL(ReKi) :: t0 !< Ice load starting time [s] + REAL(ReKi) :: rhow !< Water mass density [kg/m^3] + REAL(ReKi) :: rhoi !< Ice mass density [kg/m^3] + INTEGER(IntKi) :: Seed1 !< Random seed 1 [-] + INTEGER(IntKi) :: Seed2 !< Random seed 2 [-] + INTEGER(IntKi) :: NumLegs !< Number of support structure legs in ice [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LegPosX !< global X position of legs 1-NumLegs [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LegPosY !< global Y position of legs 1-NumLegs [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: StrWd !< The width of the leg (structure) [m] + REAL(ReKi) :: Ikm !< Indentation factor [-] + REAL(ReKi) :: Ag !< Ice crystal type factor [MPa^-3s^-1] + REAL(ReKi) :: Qg !< Activation energy [kJ] + REAL(ReKi) :: Rg !< Universal gas constant [J] + REAL(ReKi) :: Tice !< Ice temperature [K] + REAL(ReKi) :: nu !< Poison ratio of ice [-] + REAL(ReKi) :: phi !< Ice wedge angle [degree] + REAL(ReKi) :: SigNm !< Nominal ice strength [MPa] + REAL(ReKi) :: Eice !< Elastic modulus of ice [GPa] + REAL(ReKi) :: IceStr2 !< Ice tooth brittle strength [MPa] + REAL(ReKi) :: Delmax2 !< Ice tooth maximum elastic deformation for model 2 [m] + REAL(ReKi) :: Pitch !< Distance between sequential ice teeth for model 2 [m] + REAL(ReKi) :: miuh !< Mean value of random ice thickness [m] + REAL(ReKi) :: varh !< Variance of random ice thicknesss [m^2] + REAL(ReKi) :: miuv !< Mean value of random ice velocity [m/s] + REAL(ReKi) :: varv !< Variance of random ice velocity [m^2/s^2] + REAL(ReKi) :: miut !< Mean value of ice loading event duration time [s] + REAL(ReKi) :: miubr !< Mean value of random ice brittle strength [MPa] + REAL(ReKi) :: varbr !< Variance of random ice brittle strength [MPa^2] + REAL(ReKi) :: miuDelm !< Mean value of random random maximum ice tooth tip displacement [MPa] + REAL(ReKi) :: varDelm !< Variance of random random maximum ice tooth tip displacement [MPa^2] + REAL(ReKi) :: miuP !< Mean value of random distance between sequential ice teeth [m] + REAL(ReKi) :: varP !< Variance of random distance between sequential ice teeth [m^2] + INTEGER(IntKi) :: Zn1 !< Number of failure zones along contact width [-] + INTEGER(IntKi) :: Zn2 !< Number of failure zones along contact height/thickness [-] + REAL(ReKi) :: ZonePitch !< Distance between sequential ice teeth [m] + REAL(ReKi) :: PrflMean !< Ice structure contact profile mean value [m] + REAL(ReKi) :: PrflSig !< Ice structure contact profile standard deviation [m] + REAL(ReKi) :: IceStr !< Ice failure strength [MPa] + REAL(ReKi) :: Delmax !< Ice teeth maximum elastic deformation [m] + REAL(ReKi) :: alpha !< slope angle of the cone [degree] + REAL(ReKi) :: Dwl !< cone waterline diameter [m] + REAL(ReKi) :: Dtp !< cone top diameter [m] + REAL(ReKi) :: hr !< ride-up ice thickness [m] + REAL(ReKi) :: mu !< friction coefficient between structure and ice [-] + REAL(ReKi) :: sigf !< flexural strength of ice [MPa] + REAL(ReKi) :: StrLim !< limit strain [-] + REAL(ReKi) :: StrRtLim !< limit strain rate [s^-1] + INTEGER(IntKi) :: UorD !< flag that indicates upward or downward breaking cone: 0,upward, 1,downward. [-] + REAL(ReKi) :: Ll !< Ice floe length [m] + REAL(ReKi) :: Lw !< Ice floe width [m] + REAL(ReKi) :: Cpa !< ice crushing strength pressure-area relation constant [-] + REAL(ReKi) :: dpa !< ice crushing strength pressure-area relation order [-] + REAL(ReKi) :: Fdr !< Constant external driving force [MN] + REAL(ReKi) :: Kic !< Fracture toughness of ice [kNm^(-3/2)] + REAL(ReKi) :: FspN !< Non-dimensional splitting load [-] + END TYPE IceD_InputFile +! ======================= +! ========= IceD_InitInputType ======= + TYPE, PUBLIC :: IceD_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + CHARACTER(1024) :: RootName !< Root name of the output file [-] + REAL(ReKi) :: MSL2SWL !< Offset between still-water level and mean sea level [m] + REAL(ReKi) :: WtrDens !< Density of water [kg/m^3] + REAL(ReKi) :: gravity !< Gravitational acceleration [m/s^2] + INTEGER(IntKi) :: LegNum !< Which number of legs on the turbine this is being initialized for [m] + REAL(DbKi) :: TMax !< Total simulation time [s] + END TYPE IceD_InitInputType +! ======================= +! ========= IceD_InitOutputType ======= + TYPE, PUBLIC :: IceD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + INTEGER(IntKi) :: numLegs !< Number of legs on the structure [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE IceD_InitOutputType +! ======================= +! ========= IceD_ContinuousStateType ======= + TYPE, PUBLIC :: IceD_ContinuousStateType + REAL(ReKi) :: q !< q - displacement of ice mass [m] + REAL(ReKi) :: dqdt !< dqdt - velocity of ice mass [m/s] + END TYPE IceD_ContinuousStateType +! ======================= +! ========= IceD_DiscreteStateType ======= + TYPE, PUBLIC :: IceD_DiscreteStateType + REAL(SiKi) :: DummyDiscState !< A variable, Replace if you have discrete states [-] + END TYPE IceD_DiscreteStateType +! ======================= +! ========= IceD_ConstraintStateType ======= + TYPE, PUBLIC :: IceD_ConstraintStateType + REAL(SiKi) :: DummyConstrState !< A variable, Replace if you have constraint states [-] + END TYPE IceD_ConstraintStateType +! ======================= +! ========= IceD_OtherStateType ======= + TYPE, PUBLIC :: IceD_OtherStateType + INTEGER(IntKi) :: IceTthNo2 !< Ice tooth number of the current ice tooth, for model 2 (updated in UpdateStates; used in CalcOutput) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Nc !< Number of the current ice tooths number (time series) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Psum !< The sum of pitches of all broken ice teeth (time series) [m] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IceTthNo !< IceTthNo - the current numbers of ice teeth of each zone [-] + REAL(ReKi) :: Beta !< angle between broken ice sheet and level waterline [rad] + REAL(DbKi) :: Tinit !< Initial time of the current load cycle [s] + INTEGER(IntKi) :: Splitf !< flag to indicate if the ice floe has split (0 not splitted, 1 splitted) [-] + REAL(ReKi) :: dxc !< crushed depth of ice [m] + TYPE(IceD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< previous state deriv for multi-step [m] + INTEGER(IntKi) :: n !< tracks time step for which OtherState was updated [-] + END TYPE IceD_OtherStateType +! ======================= +! ========= IceD_MiscVarType ======= + TYPE, PUBLIC :: IceD_MiscVarType + INTEGER(IntKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE IceD_MiscVarType +! ======================= +! ========= IceD_ParameterType ======= + TYPE, PUBLIC :: IceD_ParameterType + REAL(ReKi) :: h !< Ice thickness [m] + REAL(ReKi) :: v !< Ice velocity [m/s] + REAL(ReKi) :: t0 !< Ice load starting time [s] + REAL(ReKi) :: StrWd !< The width of the structure [m] + REAL(ReKi) :: dt !< Time interval for integration within the module [s] + REAL(ReKi) :: InitLoc !< Ice sheet initial location [m] + REAL(ReKi) :: tolerance !< Tolerance when calculating ice breaking force, etc. [-] + REAL(ReKi) :: Tmax !< Total simulation time [s] + INTEGER(IntKi) :: verif !< flag to indicate if verification is being peformed [-] + INTEGER(IntKi) :: ModNo !< The current ice model number [-] + INTEGER(IntKi) :: SubModNo !< The current ice sub-model number [-] + INTEGER(IntKi) :: NumOuts !< The number of output channels [-] + INTEGER(IntKi) :: method !< integration method: 1-RK4, 2-AB4, 3-ABM4 [-] + INTEGER(IntKi) :: TmStep !< Total time step [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutName !< Names of all requested output parameters [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutUnit !< Units of all requested output parameters [-] + CHARACTER(1024) :: RootName !< Rootname [-] + REAL(ReKi) :: tm1a !< Time for the maximum force to be reached for model 1a [s] + REAL(ReKi) :: tm1b !< Time for the maximum force to be reached for model 1b [s] + REAL(ReKi) :: tm1c !< Time for the maximum force to be reached for model 1c [s] + REAL(ReKi) :: Fmax1a !< Maximum ice force of model 1a [N] + REAL(ReKi) :: Fmax1b !< Maximum ice force of model 1b [N] + REAL(ReKi) :: Fmax1c !< Maximum ice force of model 1c [N] + REAL(ReKi) :: Ikm !< Indentation factor [-] + REAL(ReKi) :: Cstr !< Constant when calculating creeping stresss [Pa*s^(-1/3)] + REAL(ReKi) :: EiPa !< Elastic modulus of ice [Pa] + REAL(ReKi) :: Delmax2 !< Ice tooth maximum elastic deformation for model 2 [m] + REAL(ReKi) :: Pitch !< Distance between sequential ice teeth [m] + REAL(ReKi) :: Kice2 !< Stiffness of ice teeth for model 2 [N/m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmFm !< Random maximum ice force time series [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmt0 !< Random ice loading event starting time [s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmtm !< Random time when the maximum force is reached [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmDm !< Random maximum ice tooth tip displacement time series [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmP !< Random distance between sequential ice teeth [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: rdmKi !< Random ice teeth stiffness [N/m] + REAL(ReKi) :: ZonePitch !< Distance between sequential ice teeth [m] + REAL(ReKi) :: Kice !< Stiffness of ice teeth [N/m] + REAL(ReKi) :: Delmax !< Ice teeth maximum elastic deformation [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Y0 !< Ice structure contact profile initial location [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ContPrfl !< Ice structure contact profile [m] + INTEGER(IntKi) :: Zn !< Number of failure zones [-] + REAL(ReKi) :: rhoi !< Ice mass density [kg/m^3] + REAL(ReKi) :: rhow !< Water mass density [kg/m^3] + REAL(ReKi) :: alphaR !< Slope angle of the cone [rad] + REAL(ReKi) :: Dwl !< Cone waterline diameter [m] + REAL(ReKi) :: Zr !< Ice ride-up height [m] + REAL(ReKi) :: RHbr !< Horizontal breaking force [N] + REAL(ReKi) :: RVbr !< Vertical breaking force [N] + REAL(ReKi) :: Lbr !< Ice sheet breaking length [m] + REAL(ReKi) :: LovR !< Ratio of ice breaking length over cone radius [-] + REAL(ReKi) :: mu !< Friction coefficient between structure and ice [-] + REAL(ReKi) :: Wri !< Initial ride-up ice weight [kg] + REAL(ReKi) :: WL !< Broken ice piece weight [kg] + REAL(ReKi) :: Cpa !< ice crushing strength pressure-area relation constant [-] + REAL(ReKi) :: dpa !< ice crushing strength pressure-area relation order [-] + REAL(ReKi) :: FdrN !< Constant external driving force [N] + REAL(ReKi) :: Mice !< Ice floe mass [kg] + REAL(ReKi) :: Fsp !< Ice floe splitting force [N] + END TYPE IceD_ParameterType +! ======================= +! ========= IceD_InputType ======= + TYPE, PUBLIC :: IceD_InputType + TYPE(MeshType) :: PointMesh !< contains displacement and velocity of structure [-] + END TYPE IceD_InputType +! ======================= +! ========= IceD_OutputType ======= + TYPE, PUBLIC :: IceD_OutputType + TYPE(MeshType) :: PointMesh !< contains Ice force [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE IceD_OutputType +! ======================= +CONTAINS + SUBROUTINE IceD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(IceD_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'IceD_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%IceModel = SrcInputFileData%IceModel + DstInputFileData%IceSubModel = SrcInputFileData%IceSubModel + DstInputFileData%h = SrcInputFileData%h + DstInputFileData%v = SrcInputFileData%v + DstInputFileData%InitLoc = SrcInputFileData%InitLoc + DstInputFileData%t0 = SrcInputFileData%t0 + DstInputFileData%rhow = SrcInputFileData%rhow + DstInputFileData%rhoi = SrcInputFileData%rhoi + DstInputFileData%Seed1 = SrcInputFileData%Seed1 + DstInputFileData%Seed2 = SrcInputFileData%Seed2 + DstInputFileData%NumLegs = SrcInputFileData%NumLegs +IF (ALLOCATED(SrcInputFileData%LegPosX)) THEN + i1_l = LBOUND(SrcInputFileData%LegPosX,1) + i1_u = UBOUND(SrcInputFileData%LegPosX,1) + IF (.NOT. ALLOCATED(DstInputFileData%LegPosX)) THEN + ALLOCATE(DstInputFileData%LegPosX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LegPosX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LegPosX = SrcInputFileData%LegPosX +ENDIF +IF (ALLOCATED(SrcInputFileData%LegPosY)) THEN + i1_l = LBOUND(SrcInputFileData%LegPosY,1) + i1_u = UBOUND(SrcInputFileData%LegPosY,1) + IF (.NOT. ALLOCATED(DstInputFileData%LegPosY)) THEN + ALLOCATE(DstInputFileData%LegPosY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%LegPosY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%LegPosY = SrcInputFileData%LegPosY +ENDIF +IF (ALLOCATED(SrcInputFileData%StrWd)) THEN + i1_l = LBOUND(SrcInputFileData%StrWd,1) + i1_u = UBOUND(SrcInputFileData%StrWd,1) + IF (.NOT. ALLOCATED(DstInputFileData%StrWd)) THEN + ALLOCATE(DstInputFileData%StrWd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%StrWd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%StrWd = SrcInputFileData%StrWd +ENDIF + DstInputFileData%Ikm = SrcInputFileData%Ikm + DstInputFileData%Ag = SrcInputFileData%Ag + DstInputFileData%Qg = SrcInputFileData%Qg + DstInputFileData%Rg = SrcInputFileData%Rg + DstInputFileData%Tice = SrcInputFileData%Tice + DstInputFileData%nu = SrcInputFileData%nu + DstInputFileData%phi = SrcInputFileData%phi + DstInputFileData%SigNm = SrcInputFileData%SigNm + DstInputFileData%Eice = SrcInputFileData%Eice + DstInputFileData%IceStr2 = SrcInputFileData%IceStr2 + DstInputFileData%Delmax2 = SrcInputFileData%Delmax2 + DstInputFileData%Pitch = SrcInputFileData%Pitch + DstInputFileData%miuh = SrcInputFileData%miuh + DstInputFileData%varh = SrcInputFileData%varh + DstInputFileData%miuv = SrcInputFileData%miuv + DstInputFileData%varv = SrcInputFileData%varv + DstInputFileData%miut = SrcInputFileData%miut + DstInputFileData%miubr = SrcInputFileData%miubr + DstInputFileData%varbr = SrcInputFileData%varbr + DstInputFileData%miuDelm = SrcInputFileData%miuDelm + DstInputFileData%varDelm = SrcInputFileData%varDelm + DstInputFileData%miuP = SrcInputFileData%miuP + DstInputFileData%varP = SrcInputFileData%varP + DstInputFileData%Zn1 = SrcInputFileData%Zn1 + DstInputFileData%Zn2 = SrcInputFileData%Zn2 + DstInputFileData%ZonePitch = SrcInputFileData%ZonePitch + DstInputFileData%PrflMean = SrcInputFileData%PrflMean + DstInputFileData%PrflSig = SrcInputFileData%PrflSig + DstInputFileData%IceStr = SrcInputFileData%IceStr + DstInputFileData%Delmax = SrcInputFileData%Delmax + DstInputFileData%alpha = SrcInputFileData%alpha + DstInputFileData%Dwl = SrcInputFileData%Dwl + DstInputFileData%Dtp = SrcInputFileData%Dtp + DstInputFileData%hr = SrcInputFileData%hr + DstInputFileData%mu = SrcInputFileData%mu + DstInputFileData%sigf = SrcInputFileData%sigf + DstInputFileData%StrLim = SrcInputFileData%StrLim + DstInputFileData%StrRtLim = SrcInputFileData%StrRtLim + DstInputFileData%UorD = SrcInputFileData%UorD + DstInputFileData%Ll = SrcInputFileData%Ll + DstInputFileData%Lw = SrcInputFileData%Lw + DstInputFileData%Cpa = SrcInputFileData%Cpa + DstInputFileData%dpa = SrcInputFileData%dpa + DstInputFileData%Fdr = SrcInputFileData%Fdr + DstInputFileData%Kic = SrcInputFileData%Kic + DstInputFileData%FspN = SrcInputFileData%FspN + END SUBROUTINE IceD_CopyInputFile + + SUBROUTINE IceD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(IceD_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%LegPosX)) THEN + DEALLOCATE(InputFileData%LegPosX) +ENDIF +IF (ALLOCATED(InputFileData%LegPosY)) THEN + DEALLOCATE(InputFileData%LegPosY) +ENDIF +IF (ALLOCATED(InputFileData%StrWd)) THEN + DEALLOCATE(InputFileData%StrWd) +ENDIF + END SUBROUTINE IceD_DestroyInputFile + + SUBROUTINE IceD_PackInputFile( 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(IceD_InputFile), 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 = 'IceD_PackInputFile' + ! 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 ! IceModel + Int_BufSz = Int_BufSz + 1 ! IceSubModel + Re_BufSz = Re_BufSz + 1 ! h + Re_BufSz = Re_BufSz + 1 ! v + Re_BufSz = Re_BufSz + 1 ! InitLoc + Re_BufSz = Re_BufSz + 1 ! t0 + Re_BufSz = Re_BufSz + 1 ! rhow + Re_BufSz = Re_BufSz + 1 ! rhoi + Int_BufSz = Int_BufSz + 1 ! Seed1 + Int_BufSz = Int_BufSz + 1 ! Seed2 + Int_BufSz = Int_BufSz + 1 ! NumLegs + Int_BufSz = Int_BufSz + 1 ! LegPosX allocated yes/no + IF ( ALLOCATED(InData%LegPosX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LegPosX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LegPosX) ! LegPosX + END IF + Int_BufSz = Int_BufSz + 1 ! LegPosY allocated yes/no + IF ( ALLOCATED(InData%LegPosY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LegPosY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LegPosY) ! LegPosY + END IF + Int_BufSz = Int_BufSz + 1 ! StrWd allocated yes/no + IF ( ALLOCATED(InData%StrWd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StrWd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StrWd) ! StrWd + END IF + Re_BufSz = Re_BufSz + 1 ! Ikm + Re_BufSz = Re_BufSz + 1 ! Ag + Re_BufSz = Re_BufSz + 1 ! Qg + Re_BufSz = Re_BufSz + 1 ! Rg + Re_BufSz = Re_BufSz + 1 ! Tice + Re_BufSz = Re_BufSz + 1 ! nu + Re_BufSz = Re_BufSz + 1 ! phi + Re_BufSz = Re_BufSz + 1 ! SigNm + Re_BufSz = Re_BufSz + 1 ! Eice + Re_BufSz = Re_BufSz + 1 ! IceStr2 + Re_BufSz = Re_BufSz + 1 ! Delmax2 + Re_BufSz = Re_BufSz + 1 ! Pitch + Re_BufSz = Re_BufSz + 1 ! miuh + Re_BufSz = Re_BufSz + 1 ! varh + Re_BufSz = Re_BufSz + 1 ! miuv + Re_BufSz = Re_BufSz + 1 ! varv + Re_BufSz = Re_BufSz + 1 ! miut + Re_BufSz = Re_BufSz + 1 ! miubr + Re_BufSz = Re_BufSz + 1 ! varbr + Re_BufSz = Re_BufSz + 1 ! miuDelm + Re_BufSz = Re_BufSz + 1 ! varDelm + Re_BufSz = Re_BufSz + 1 ! miuP + Re_BufSz = Re_BufSz + 1 ! varP + Int_BufSz = Int_BufSz + 1 ! Zn1 + Int_BufSz = Int_BufSz + 1 ! Zn2 + Re_BufSz = Re_BufSz + 1 ! ZonePitch + Re_BufSz = Re_BufSz + 1 ! PrflMean + Re_BufSz = Re_BufSz + 1 ! PrflSig + Re_BufSz = Re_BufSz + 1 ! IceStr + Re_BufSz = Re_BufSz + 1 ! Delmax + Re_BufSz = Re_BufSz + 1 ! alpha + Re_BufSz = Re_BufSz + 1 ! Dwl + Re_BufSz = Re_BufSz + 1 ! Dtp + Re_BufSz = Re_BufSz + 1 ! hr + Re_BufSz = Re_BufSz + 1 ! mu + Re_BufSz = Re_BufSz + 1 ! sigf + Re_BufSz = Re_BufSz + 1 ! StrLim + Re_BufSz = Re_BufSz + 1 ! StrRtLim + Int_BufSz = Int_BufSz + 1 ! UorD + Re_BufSz = Re_BufSz + 1 ! Ll + Re_BufSz = Re_BufSz + 1 ! Lw + Re_BufSz = Re_BufSz + 1 ! Cpa + Re_BufSz = Re_BufSz + 1 ! dpa + Re_BufSz = Re_BufSz + 1 ! Fdr + Re_BufSz = Re_BufSz + 1 ! Kic + Re_BufSz = Re_BufSz + 1 ! FspN + 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%IceModel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IceSubModel + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%h + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%v + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InitLoc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhow + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhoi + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Seed1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Seed2 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumLegs + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LegPosX) ) 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%LegPosX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LegPosX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LegPosX,1), UBOUND(InData%LegPosX,1) + ReKiBuf(Re_Xferred) = InData%LegPosX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LegPosY) ) 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%LegPosY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LegPosY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LegPosY,1), UBOUND(InData%LegPosY,1) + ReKiBuf(Re_Xferred) = InData%LegPosY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StrWd) ) 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%StrWd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StrWd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StrWd,1), UBOUND(InData%StrWd,1) + ReKiBuf(Re_Xferred) = InData%StrWd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Ikm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ag + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Qg + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rg + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Tice + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%nu + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%phi + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SigNm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Eice + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%IceStr2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Delmax2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Pitch + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miuh + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%varh + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miuv + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%varv + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miut + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miubr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%varbr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miuDelm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%varDelm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%miuP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%varP + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Zn1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Zn2 + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ZonePitch + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PrflMean + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PrflSig + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%IceStr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Delmax + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alpha + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Dwl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Dtp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%hr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%mu + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%sigf + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%StrLim + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%StrRtLim + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UorD + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ll + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Lw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cpa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dpa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Fdr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kic + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FspN + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_PackInputFile + + SUBROUTINE IceD_UnPackInputFile( 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(IceD_InputFile), 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 = 'IceD_UnPackInputFile' + ! 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%IceModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IceSubModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%h = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%v = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InitLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rhow = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rhoi = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Seed1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Seed2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumLegs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LegPosX 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%LegPosX)) DEALLOCATE(OutData%LegPosX) + ALLOCATE(OutData%LegPosX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LegPosX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LegPosX,1), UBOUND(OutData%LegPosX,1) + OutData%LegPosX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LegPosY 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%LegPosY)) DEALLOCATE(OutData%LegPosY) + ALLOCATE(OutData%LegPosY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LegPosY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LegPosY,1), UBOUND(OutData%LegPosY,1) + OutData%LegPosY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StrWd 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%StrWd)) DEALLOCATE(OutData%StrWd) + ALLOCATE(OutData%StrWd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StrWd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%StrWd,1), UBOUND(OutData%StrWd,1) + OutData%StrWd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Ikm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ag = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Qg = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rg = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Tice = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%nu = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%phi = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SigNm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Eice = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%IceStr2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Delmax2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Pitch = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miuh = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%varh = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miuv = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%varv = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miut = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miubr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%varbr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miuDelm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%varDelm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%miuP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%varP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Zn1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Zn2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ZonePitch = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PrflMean = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PrflSig = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%IceStr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Delmax = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Dwl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Dtp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%hr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%mu = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%sigf = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%StrLim = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%StrRtLim = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UorD = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Ll = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Lw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cpa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dpa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Fdr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kic = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FspN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_UnPackInputFile + + SUBROUTINE IceD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(IceD_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 = 'IceD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL + DstInitInputData%WtrDens = SrcInitInputData%WtrDens + DstInitInputData%gravity = SrcInitInputData%gravity + DstInitInputData%LegNum = SrcInitInputData%LegNum + DstInitInputData%TMax = SrcInitInputData%TMax + END SUBROUTINE IceD_CopyInitInput + + SUBROUTINE IceD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(IceD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceD_DestroyInitInput + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! MSL2SWL + Re_BufSz = Re_BufSz + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! gravity + Int_BufSz = Int_BufSz + 1 ! LegNum + Db_BufSz = Db_BufSz + 1 ! TMax + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%gravity + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%LegNum + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TMax + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE IceD_PackInitInput + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%MSL2SWL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LegNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE IceD_UnPackInitInput + + SUBROUTINE IceD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(IceD_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 = 'IceD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + DstInitOutputData%numLegs = SrcInitOutputData%numLegs + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IceD_CopyInitOutput + + SUBROUTINE IceD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(IceD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE IceD_DestroyInitOutput + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + Int_BufSz = Int_BufSz + 1 ! numLegs + ! 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 + + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numLegs + Int_Xferred = 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 IceD_PackInitOutput + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%numLegs = 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 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 IceD_UnPackInitOutput + + SUBROUTINE IceD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(IceD_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 = 'IceD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%q = SrcContStateData%q + DstContStateData%dqdt = SrcContStateData%dqdt + END SUBROUTINE IceD_CopyContState + + SUBROUTINE IceD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(IceD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceD_DestroyContState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 ! q + Re_BufSz = Re_BufSz + 1 ! dqdt + 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%q + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dqdt + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_PackContState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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%q = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dqdt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_UnPackContState + + SUBROUTINE IceD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(IceD_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 = 'IceD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE IceD_CopyDiscState + + SUBROUTINE IceD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(IceD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceD_DestroyDiscState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 IceD_PackDiscState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_UnPackDiscState + + SUBROUTINE IceD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(IceD_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 = 'IceD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE IceD_CopyConstrState + + SUBROUTINE IceD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(IceD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceD_DestroyConstrState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 IceD_PackConstrState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_UnPackConstrState + + SUBROUTINE IceD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(IceD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%IceTthNo2 = SrcOtherStateData%IceTthNo2 +IF (ALLOCATED(SrcOtherStateData%Nc)) THEN + i1_l = LBOUND(SrcOtherStateData%Nc,1) + i1_u = UBOUND(SrcOtherStateData%Nc,1) + IF (.NOT. ALLOCATED(DstOtherStateData%Nc)) THEN + ALLOCATE(DstOtherStateData%Nc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Nc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%Nc = SrcOtherStateData%Nc +ENDIF +IF (ALLOCATED(SrcOtherStateData%Psum)) THEN + i1_l = LBOUND(SrcOtherStateData%Psum,1) + i1_u = UBOUND(SrcOtherStateData%Psum,1) + IF (.NOT. ALLOCATED(DstOtherStateData%Psum)) THEN + ALLOCATE(DstOtherStateData%Psum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Psum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%Psum = SrcOtherStateData%Psum +ENDIF +IF (ALLOCATED(SrcOtherStateData%IceTthNo)) THEN + i1_l = LBOUND(SrcOtherStateData%IceTthNo,1) + i1_u = UBOUND(SrcOtherStateData%IceTthNo,1) + IF (.NOT. ALLOCATED(DstOtherStateData%IceTthNo)) THEN + ALLOCATE(DstOtherStateData%IceTthNo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%IceTthNo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%IceTthNo = SrcOtherStateData%IceTthNo +ENDIF + DstOtherStateData%Beta = SrcOtherStateData%Beta + DstOtherStateData%Tinit = SrcOtherStateData%Tinit + DstOtherStateData%Splitf = SrcOtherStateData%Splitf + DstOtherStateData%dxc = SrcOtherStateData%dxc +IF (ALLOCATED(SrcOtherStateData%xdot)) THEN + i1_l = LBOUND(SrcOtherStateData%xdot,1) + i1_u = UBOUND(SrcOtherStateData%xdot,1) + IF (.NOT. ALLOCATED(DstOtherStateData%xdot)) THEN + ALLOCATE(DstOtherStateData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL IceD_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstOtherStateData%n = SrcOtherStateData%n + END SUBROUTINE IceD_CopyOtherState + + SUBROUTINE IceD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(IceD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%Nc)) THEN + DEALLOCATE(OtherStateData%Nc) +ENDIF +IF (ALLOCATED(OtherStateData%Psum)) THEN + DEALLOCATE(OtherStateData%Psum) +ENDIF +IF (ALLOCATED(OtherStateData%IceTthNo)) THEN + DEALLOCATE(OtherStateData%IceTthNo) +ENDIF +IF (ALLOCATED(OtherStateData%xdot)) THEN +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL IceD_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OtherStateData%xdot) +ENDIF + END SUBROUTINE IceD_DestroyOtherState + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 + Int_BufSz = Int_BufSz + 1 ! IceTthNo2 + Int_BufSz = Int_BufSz + 1 ! Nc allocated yes/no + IF ( ALLOCATED(InData%Nc) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Nc upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nc) ! Nc + END IF + Int_BufSz = Int_BufSz + 1 ! Psum allocated yes/no + IF ( ALLOCATED(InData%Psum) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Psum upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Psum) ! Psum + END IF + Int_BufSz = Int_BufSz + 1 ! IceTthNo allocated yes/no + IF ( ALLOCATED(InData%IceTthNo) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IceTthNo upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IceTthNo) ! IceTthNo + END IF + Re_BufSz = Re_BufSz + 1 ! Beta + Db_BufSz = Db_BufSz + 1 ! Tinit + Int_BufSz = Int_BufSz + 1 ! Splitf + Re_BufSz = Re_BufSz + 1 ! dxc + Int_BufSz = Int_BufSz + 1 ! xdot allocated yes/no + IF ( ALLOCATED(InData%xdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xdot upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! n + 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%IceTthNo2 + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nc) ) 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%Nc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nc,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Nc,1), UBOUND(InData%Nc,1) + IntKiBuf(Int_Xferred) = InData%Nc(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Psum) ) 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%Psum,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Psum,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Psum,1), UBOUND(InData%Psum,1) + ReKiBuf(Re_Xferred) = InData%Psum(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IceTthNo) ) 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%IceTthNo,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IceTthNo,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IceTthNo,1), UBOUND(InData%IceTthNo,1) + IntKiBuf(Int_Xferred) = InData%IceTthNo(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Beta + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Tinit + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Splitf + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dxc + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%xdot) ) 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%xdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 + IntKiBuf(Int_Xferred) = InData%n + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceD_PackOtherState + + SUBROUTINE IceD_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(IceD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_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%IceTthNo2 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nc 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%Nc)) DEALLOCATE(OutData%Nc) + ALLOCATE(OutData%Nc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Nc,1), UBOUND(OutData%Nc,1) + OutData%Nc(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Psum 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%Psum)) DEALLOCATE(OutData%Psum) + ALLOCATE(OutData%Psum(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Psum.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Psum,1), UBOUND(OutData%Psum,1) + OutData%Psum(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IceTthNo 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%IceTthNo)) DEALLOCATE(OutData%IceTthNo) + ALLOCATE(OutData%IceTthNo(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IceTthNo.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IceTthNo,1), UBOUND(OutData%IceTthNo,1) + OutData%IceTthNo(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%Beta = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Tinit = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Splitf = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dxc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdot 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%xdot)) DEALLOCATE(OutData%xdot) + ALLOCATE(OutData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 IceD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END IF + OutData%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceD_UnPackOtherState + + SUBROUTINE IceD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(IceD_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 = 'IceD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE IceD_CopyMisc + + SUBROUTINE IceD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(IceD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceD_DestroyMisc + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 ! 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 + + IntKiBuf(Int_Xferred) = InData%DummyMiscVar + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceD_PackMisc + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceD_UnPackMisc + + SUBROUTINE IceD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(IceD_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 = 'IceD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%h = SrcParamData%h + DstParamData%v = SrcParamData%v + DstParamData%t0 = SrcParamData%t0 + DstParamData%StrWd = SrcParamData%StrWd + DstParamData%dt = SrcParamData%dt + DstParamData%InitLoc = SrcParamData%InitLoc + DstParamData%tolerance = SrcParamData%tolerance + DstParamData%Tmax = SrcParamData%Tmax + DstParamData%verif = SrcParamData%verif + DstParamData%ModNo = SrcParamData%ModNo + DstParamData%SubModNo = SrcParamData%SubModNo + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%method = SrcParamData%method + DstParamData%TmStep = SrcParamData%TmStep +IF (ALLOCATED(SrcParamData%OutName)) THEN + i1_l = LBOUND(SrcParamData%OutName,1) + i1_u = UBOUND(SrcParamData%OutName,1) + IF (.NOT. ALLOCATED(DstParamData%OutName)) THEN + ALLOCATE(DstParamData%OutName(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutName.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%OutName = SrcParamData%OutName +ENDIF +IF (ALLOCATED(SrcParamData%OutUnit)) THEN + i1_l = LBOUND(SrcParamData%OutUnit,1) + i1_u = UBOUND(SrcParamData%OutUnit,1) + IF (.NOT. ALLOCATED(DstParamData%OutUnit)) THEN + ALLOCATE(DstParamData%OutUnit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutUnit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%OutUnit = SrcParamData%OutUnit +ENDIF + DstParamData%RootName = SrcParamData%RootName + DstParamData%tm1a = SrcParamData%tm1a + DstParamData%tm1b = SrcParamData%tm1b + DstParamData%tm1c = SrcParamData%tm1c + DstParamData%Fmax1a = SrcParamData%Fmax1a + DstParamData%Fmax1b = SrcParamData%Fmax1b + DstParamData%Fmax1c = SrcParamData%Fmax1c + DstParamData%Ikm = SrcParamData%Ikm + DstParamData%Cstr = SrcParamData%Cstr + DstParamData%EiPa = SrcParamData%EiPa + DstParamData%Delmax2 = SrcParamData%Delmax2 + DstParamData%Pitch = SrcParamData%Pitch + DstParamData%Kice2 = SrcParamData%Kice2 +IF (ALLOCATED(SrcParamData%rdmFm)) THEN + i1_l = LBOUND(SrcParamData%rdmFm,1) + i1_u = UBOUND(SrcParamData%rdmFm,1) + IF (.NOT. ALLOCATED(DstParamData%rdmFm)) THEN + ALLOCATE(DstParamData%rdmFm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmFm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmFm = SrcParamData%rdmFm +ENDIF +IF (ALLOCATED(SrcParamData%rdmt0)) THEN + i1_l = LBOUND(SrcParamData%rdmt0,1) + i1_u = UBOUND(SrcParamData%rdmt0,1) + IF (.NOT. ALLOCATED(DstParamData%rdmt0)) THEN + ALLOCATE(DstParamData%rdmt0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmt0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmt0 = SrcParamData%rdmt0 +ENDIF +IF (ALLOCATED(SrcParamData%rdmtm)) THEN + i1_l = LBOUND(SrcParamData%rdmtm,1) + i1_u = UBOUND(SrcParamData%rdmtm,1) + IF (.NOT. ALLOCATED(DstParamData%rdmtm)) THEN + ALLOCATE(DstParamData%rdmtm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmtm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmtm = SrcParamData%rdmtm +ENDIF +IF (ALLOCATED(SrcParamData%rdmDm)) THEN + i1_l = LBOUND(SrcParamData%rdmDm,1) + i1_u = UBOUND(SrcParamData%rdmDm,1) + IF (.NOT. ALLOCATED(DstParamData%rdmDm)) THEN + ALLOCATE(DstParamData%rdmDm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmDm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmDm = SrcParamData%rdmDm +ENDIF +IF (ALLOCATED(SrcParamData%rdmP)) THEN + i1_l = LBOUND(SrcParamData%rdmP,1) + i1_u = UBOUND(SrcParamData%rdmP,1) + IF (.NOT. ALLOCATED(DstParamData%rdmP)) THEN + ALLOCATE(DstParamData%rdmP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmP = SrcParamData%rdmP +ENDIF +IF (ALLOCATED(SrcParamData%rdmKi)) THEN + i1_l = LBOUND(SrcParamData%rdmKi,1) + i1_u = UBOUND(SrcParamData%rdmKi,1) + IF (.NOT. ALLOCATED(DstParamData%rdmKi)) THEN + ALLOCATE(DstParamData%rdmKi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rdmKi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%rdmKi = SrcParamData%rdmKi +ENDIF + DstParamData%ZonePitch = SrcParamData%ZonePitch + DstParamData%Kice = SrcParamData%Kice + DstParamData%Delmax = SrcParamData%Delmax +IF (ALLOCATED(SrcParamData%Y0)) THEN + i1_l = LBOUND(SrcParamData%Y0,1) + i1_u = UBOUND(SrcParamData%Y0,1) + IF (.NOT. ALLOCATED(DstParamData%Y0)) THEN + ALLOCATE(DstParamData%Y0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Y0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Y0 = SrcParamData%Y0 +ENDIF +IF (ALLOCATED(SrcParamData%ContPrfl)) THEN + i1_l = LBOUND(SrcParamData%ContPrfl,1) + i1_u = UBOUND(SrcParamData%ContPrfl,1) + IF (.NOT. ALLOCATED(DstParamData%ContPrfl)) THEN + ALLOCATE(DstParamData%ContPrfl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ContPrfl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ContPrfl = SrcParamData%ContPrfl +ENDIF + DstParamData%Zn = SrcParamData%Zn + DstParamData%rhoi = SrcParamData%rhoi + DstParamData%rhow = SrcParamData%rhow + DstParamData%alphaR = SrcParamData%alphaR + DstParamData%Dwl = SrcParamData%Dwl + DstParamData%Zr = SrcParamData%Zr + DstParamData%RHbr = SrcParamData%RHbr + DstParamData%RVbr = SrcParamData%RVbr + DstParamData%Lbr = SrcParamData%Lbr + DstParamData%LovR = SrcParamData%LovR + DstParamData%mu = SrcParamData%mu + DstParamData%Wri = SrcParamData%Wri + DstParamData%WL = SrcParamData%WL + DstParamData%Cpa = SrcParamData%Cpa + DstParamData%dpa = SrcParamData%dpa + DstParamData%FdrN = SrcParamData%FdrN + DstParamData%Mice = SrcParamData%Mice + DstParamData%Fsp = SrcParamData%Fsp + END SUBROUTINE IceD_CopyParam + + SUBROUTINE IceD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(IceD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%OutName)) THEN + DEALLOCATE(ParamData%OutName) +ENDIF +IF (ALLOCATED(ParamData%OutUnit)) THEN + DEALLOCATE(ParamData%OutUnit) +ENDIF +IF (ALLOCATED(ParamData%rdmFm)) THEN + DEALLOCATE(ParamData%rdmFm) +ENDIF +IF (ALLOCATED(ParamData%rdmt0)) THEN + DEALLOCATE(ParamData%rdmt0) +ENDIF +IF (ALLOCATED(ParamData%rdmtm)) THEN + DEALLOCATE(ParamData%rdmtm) +ENDIF +IF (ALLOCATED(ParamData%rdmDm)) THEN + DEALLOCATE(ParamData%rdmDm) +ENDIF +IF (ALLOCATED(ParamData%rdmP)) THEN + DEALLOCATE(ParamData%rdmP) +ENDIF +IF (ALLOCATED(ParamData%rdmKi)) THEN + DEALLOCATE(ParamData%rdmKi) +ENDIF +IF (ALLOCATED(ParamData%Y0)) THEN + DEALLOCATE(ParamData%Y0) +ENDIF +IF (ALLOCATED(ParamData%ContPrfl)) THEN + DEALLOCATE(ParamData%ContPrfl) +ENDIF + END SUBROUTINE IceD_DestroyParam + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 ! h + Re_BufSz = Re_BufSz + 1 ! v + Re_BufSz = Re_BufSz + 1 ! t0 + Re_BufSz = Re_BufSz + 1 ! StrWd + Re_BufSz = Re_BufSz + 1 ! dt + Re_BufSz = Re_BufSz + 1 ! InitLoc + Re_BufSz = Re_BufSz + 1 ! tolerance + Re_BufSz = Re_BufSz + 1 ! Tmax + Int_BufSz = Int_BufSz + 1 ! verif + Int_BufSz = Int_BufSz + 1 ! ModNo + Int_BufSz = Int_BufSz + 1 ! SubModNo + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! method + Int_BufSz = Int_BufSz + 1 ! TmStep + Int_BufSz = Int_BufSz + 1 ! OutName allocated yes/no + IF ( ALLOCATED(InData%OutName) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutName upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutName)*LEN(InData%OutName) ! OutName + END IF + Int_BufSz = Int_BufSz + 1 ! OutUnit allocated yes/no + IF ( ALLOCATED(InData%OutUnit) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutUnit upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutUnit)*LEN(InData%OutUnit) ! OutUnit + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! tm1a + Re_BufSz = Re_BufSz + 1 ! tm1b + Re_BufSz = Re_BufSz + 1 ! tm1c + Re_BufSz = Re_BufSz + 1 ! Fmax1a + Re_BufSz = Re_BufSz + 1 ! Fmax1b + Re_BufSz = Re_BufSz + 1 ! Fmax1c + Re_BufSz = Re_BufSz + 1 ! Ikm + Re_BufSz = Re_BufSz + 1 ! Cstr + Re_BufSz = Re_BufSz + 1 ! EiPa + Re_BufSz = Re_BufSz + 1 ! Delmax2 + Re_BufSz = Re_BufSz + 1 ! Pitch + Re_BufSz = Re_BufSz + 1 ! Kice2 + Int_BufSz = Int_BufSz + 1 ! rdmFm allocated yes/no + IF ( ALLOCATED(InData%rdmFm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmFm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmFm) ! rdmFm + END IF + Int_BufSz = Int_BufSz + 1 ! rdmt0 allocated yes/no + IF ( ALLOCATED(InData%rdmt0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmt0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmt0) ! rdmt0 + END IF + Int_BufSz = Int_BufSz + 1 ! rdmtm allocated yes/no + IF ( ALLOCATED(InData%rdmtm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmtm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmtm) ! rdmtm + END IF + Int_BufSz = Int_BufSz + 1 ! rdmDm allocated yes/no + IF ( ALLOCATED(InData%rdmDm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmDm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmDm) ! rdmDm + END IF + Int_BufSz = Int_BufSz + 1 ! rdmP allocated yes/no + IF ( ALLOCATED(InData%rdmP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmP) ! rdmP + END IF + Int_BufSz = Int_BufSz + 1 ! rdmKi allocated yes/no + IF ( ALLOCATED(InData%rdmKi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! rdmKi upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rdmKi) ! rdmKi + END IF + Re_BufSz = Re_BufSz + 1 ! ZonePitch + Re_BufSz = Re_BufSz + 1 ! Kice + Re_BufSz = Re_BufSz + 1 ! Delmax + Int_BufSz = Int_BufSz + 1 ! Y0 allocated yes/no + IF ( ALLOCATED(InData%Y0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Y0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Y0) ! Y0 + END IF + Int_BufSz = Int_BufSz + 1 ! ContPrfl allocated yes/no + IF ( ALLOCATED(InData%ContPrfl) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ContPrfl upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ContPrfl) ! ContPrfl + END IF + Int_BufSz = Int_BufSz + 1 ! Zn + Re_BufSz = Re_BufSz + 1 ! rhoi + Re_BufSz = Re_BufSz + 1 ! rhow + Re_BufSz = Re_BufSz + 1 ! alphaR + Re_BufSz = Re_BufSz + 1 ! Dwl + Re_BufSz = Re_BufSz + 1 ! Zr + Re_BufSz = Re_BufSz + 1 ! RHbr + Re_BufSz = Re_BufSz + 1 ! RVbr + Re_BufSz = Re_BufSz + 1 ! Lbr + Re_BufSz = Re_BufSz + 1 ! LovR + Re_BufSz = Re_BufSz + 1 ! mu + Re_BufSz = Re_BufSz + 1 ! Wri + Re_BufSz = Re_BufSz + 1 ! WL + Re_BufSz = Re_BufSz + 1 ! Cpa + Re_BufSz = Re_BufSz + 1 ! dpa + Re_BufSz = Re_BufSz + 1 ! FdrN + Re_BufSz = Re_BufSz + 1 ! Mice + Re_BufSz = Re_BufSz + 1 ! Fsp + 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%h + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%v + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%t0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%StrWd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InitLoc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tolerance + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Tmax + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%verif + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ModNo + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SubModNo + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%method + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TmStep + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutName) ) 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%OutName,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutName,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutName,1), UBOUND(InData%OutName,1) + DO I = 1, LEN(InData%OutName) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutName(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OutUnit) ) 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%OutUnit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutUnit,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutUnit,1), UBOUND(InData%OutUnit,1) + DO I = 1, LEN(InData%OutUnit) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutUnit(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%tm1a + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tm1b + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%tm1c + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Fmax1a + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Fmax1b + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Fmax1c + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ikm + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cstr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%EiPa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Delmax2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Pitch + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kice2 + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%rdmFm) ) 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%rdmFm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmFm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmFm,1), UBOUND(InData%rdmFm,1) + ReKiBuf(Re_Xferred) = InData%rdmFm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rdmt0) ) 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%rdmt0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmt0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmt0,1), UBOUND(InData%rdmt0,1) + ReKiBuf(Re_Xferred) = InData%rdmt0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rdmtm) ) 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%rdmtm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmtm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmtm,1), UBOUND(InData%rdmtm,1) + ReKiBuf(Re_Xferred) = InData%rdmtm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rdmDm) ) 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%rdmDm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmDm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmDm,1), UBOUND(InData%rdmDm,1) + ReKiBuf(Re_Xferred) = InData%rdmDm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rdmP) ) 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%rdmP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmP,1), UBOUND(InData%rdmP,1) + ReKiBuf(Re_Xferred) = InData%rdmP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rdmKi) ) 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%rdmKi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rdmKi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%rdmKi,1), UBOUND(InData%rdmKi,1) + ReKiBuf(Re_Xferred) = InData%rdmKi(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%ZonePitch + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kice + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Delmax + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Y0) ) 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%Y0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Y0,1), UBOUND(InData%Y0,1) + ReKiBuf(Re_Xferred) = InData%Y0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ContPrfl) ) 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%ContPrfl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ContPrfl,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ContPrfl,1), UBOUND(InData%ContPrfl,1) + ReKiBuf(Re_Xferred) = InData%ContPrfl(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Zn + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhoi + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhow + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%alphaR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Dwl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Zr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RHbr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RVbr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Lbr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LovR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%mu + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Wri + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cpa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dpa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FdrN + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Mice + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Fsp + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_PackParam + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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%h = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%v = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%t0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%StrWd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InitLoc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tolerance = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Tmax = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%verif = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ModNo = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SubModNo = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%method = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TmStep = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutName 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%OutName)) DEALLOCATE(OutData%OutName) + ALLOCATE(OutData%OutName(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutName.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutName,1), UBOUND(OutData%OutName,1) + DO I = 1, LEN(OutData%OutName) + OutData%OutName(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutUnit 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%OutUnit)) DEALLOCATE(OutData%OutUnit) + ALLOCATE(OutData%OutUnit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutUnit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutUnit,1), UBOUND(OutData%OutUnit,1) + DO I = 1, LEN(OutData%OutUnit) + OutData%OutUnit(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%tm1a = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tm1b = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%tm1c = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Fmax1a = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Fmax1b = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Fmax1c = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ikm = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cstr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%EiPa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Delmax2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Pitch = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kice2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmFm 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%rdmFm)) DEALLOCATE(OutData%rdmFm) + ALLOCATE(OutData%rdmFm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmFm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmFm,1), UBOUND(OutData%rdmFm,1) + OutData%rdmFm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmt0 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%rdmt0)) DEALLOCATE(OutData%rdmt0) + ALLOCATE(OutData%rdmt0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmt0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmt0,1), UBOUND(OutData%rdmt0,1) + OutData%rdmt0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmtm 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%rdmtm)) DEALLOCATE(OutData%rdmtm) + ALLOCATE(OutData%rdmtm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmtm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmtm,1), UBOUND(OutData%rdmtm,1) + OutData%rdmtm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmDm 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%rdmDm)) DEALLOCATE(OutData%rdmDm) + ALLOCATE(OutData%rdmDm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmDm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmDm,1), UBOUND(OutData%rdmDm,1) + OutData%rdmDm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmP 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%rdmP)) DEALLOCATE(OutData%rdmP) + ALLOCATE(OutData%rdmP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmP,1), UBOUND(OutData%rdmP,1) + OutData%rdmP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rdmKi 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%rdmKi)) DEALLOCATE(OutData%rdmKi) + ALLOCATE(OutData%rdmKi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rdmKi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%rdmKi,1), UBOUND(OutData%rdmKi,1) + OutData%rdmKi(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%ZonePitch = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Kice = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Delmax = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Y0 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%Y0)) DEALLOCATE(OutData%Y0) + ALLOCATE(OutData%Y0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Y0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Y0,1), UBOUND(OutData%Y0,1) + OutData%Y0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ContPrfl 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%ContPrfl)) DEALLOCATE(OutData%ContPrfl) + ALLOCATE(OutData%ContPrfl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ContPrfl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ContPrfl,1), UBOUND(OutData%ContPrfl,1) + OutData%ContPrfl(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Zn = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%rhoi = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rhow = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%alphaR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Dwl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Zr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RHbr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RVbr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Lbr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LovR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%mu = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Wri = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cpa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dpa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%FdrN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Mice = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Fsp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceD_UnPackParam + + SUBROUTINE IceD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(IceD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%PointMesh, DstInputData%PointMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IceD_CopyInput + + SUBROUTINE IceD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(IceD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%PointMesh, ErrStat, ErrMsg ) + END SUBROUTINE IceD_DestroyInput + + SUBROUTINE IceD_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(IceD_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 = 'IceD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PointMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PointMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PointMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PointMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PointMesh + 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 MeshPack( InData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PointMesh + 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 IceD_PackInput + + SUBROUTINE IceD_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(IceD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_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 + 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 MeshUnpack( OutData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PointMesh + 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 IceD_UnPackInput + + SUBROUTINE IceD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(IceD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'IceD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%PointMesh, DstOutputData%PointMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE IceD_CopyOutput + + SUBROUTINE IceD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(IceD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%PointMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE IceD_DestroyOutput + + SUBROUTINE IceD_PackOutput( 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(IceD_OutputType), 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 = 'IceD_PackOutput' + ! 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 ! PointMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PointMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PointMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PointMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PointMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PointMesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE IceD_PackOutput + + SUBROUTINE IceD_UnPackOutput( 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(IceD_OutputType), 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 = 'IceD_UnPackOutput' + ! 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 MeshUnpack( OutData%PointMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PointMesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE IceD_UnPackOutput + + + SUBROUTINE IceD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(IceD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(IceD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL IceD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL IceD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL IceD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE IceD_Input_ExtrapInterp + + + SUBROUTINE IceD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(IceD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(IceD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(IceD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%PointMesh, u2%PointMesh, tin, u_out%PointMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE IceD_Input_ExtrapInterp1 + + + SUBROUTINE IceD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(IceD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(IceD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(IceD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(IceD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%PointMesh, u2%PointMesh, u3%PointMesh, tin, u_out%PointMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE IceD_Input_ExtrapInterp2 + + + SUBROUTINE IceD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(IceD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(IceD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL IceD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL IceD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL IceD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE IceD_Output_ExtrapInterp + + + SUBROUTINE IceD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(IceD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(IceD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(IceD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%PointMesh, y2%PointMesh, tin, y_out%PointMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE IceD_Output_ExtrapInterp1 + + + SUBROUTINE IceD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(IceD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(IceD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(IceD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(IceD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%PointMesh, y2%PointMesh, y3%PointMesh, tin, y_out%PointMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE IceD_Output_ExtrapInterp2 + +END MODULE IceDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/icedyn/src/Registry_IceDyn.txt b/OpenFAST/modules/icedyn/src/Registry_IceDyn.txt new file mode 100644 index 000000000..b230ebf9d --- /dev/null +++ b/OpenFAST/modules/icedyn/src/Registry_IceDyn.txt @@ -0,0 +1,234 @@ +################################################################################################################################## +# Registry for IceDyn, creates MODULE IceDyn_Types +# Module IceDyn_Types contains all of the user-defined types needed in Module2. It also contains copy, destroy, pack, and +# unpack routines associated with each defined data types. +################################################################################################################################## +# Entries are of the form +# keyword <modulename/modname> <TypeBeingDefined> <FieldType> <FieldName> <Dims> <InitialValue> <Ctrl> "<DESCRIP>" "<UNITS>" +################################################################################################################################## + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary input file data ........................................................................................................... + +# ..... General input parameters .................................................................................................. +typedef IceDyn/IceD IceD_InputFile IntKi IceModel - - - "The current ice model number" - +typedef ^ ^ IntKi IceSubModel - - - "The current ice sub-model number" - +typedef ^ ^ ReKi h - - - "Ice thickness" m +typedef ^ ^ ReKi v - - - "Ice velocity" m/s +typedef ^ ^ ReKi InitLoc - - - "Ice sheet initial location" m +typedef ^ ^ ReKi t0 - - - "Ice load starting time" s +typedef ^ ^ ReKi rhow - - - "Water mass density" kg/m^3 +typedef ^ ^ ReKi rhoi - - - "Ice mass density" kg/m^3 +typedef ^ ^ IntKi Seed1 - - - "Random seed 1" - +typedef ^ ^ IntKi Seed2 - - - "Random seed 2" - +typedef ^ ^ IntKi NumLegs - - - "Number of support structure legs in ice" - +typedef ^ ^ ReKi LegPosX {:} - - "global X position of legs 1-NumLegs " m +typedef ^ ^ ReKi LegPosY {:} - - "global Y position of legs 1-NumLegs " m +typedef ^ ^ ReKi StrWd {:} - - "The width of the leg (structure)" m + +# ..... Ice Model 1 ............................................................................................................... +typedef IceDyn/IceD ^ ReKi Ikm - - - "Indentation factor" - +typedef ^ ^ ^ Ag - - - "Ice crystal type factor" MPa^-3s^-1 +typedef ^ ^ ^ Qg - - - "Activation energy" kJ mol^-1 +typedef ^ ^ ^ Rg - - - "Universal gas constant" J mol^-1K^-1 +typedef ^ ^ ^ Tice - - - "Ice temperature" K +typedef ^ ^ ^ nu - - - "Poison ratio of ice" - +typedef ^ ^ ^ phi - - - "Ice wedge angle" degree +typedef ^ ^ ^ SigNm - - - "Nominal ice strength" MPa +typedef ^ ^ ^ Eice - - - "Elastic modulus of ice" GPa +# ..... Ice Model 2 ............................................................................................................... +typedef IceDyn/IceD ^ ReKi IceStr2 - - - "Ice tooth brittle strength" MPa +typedef ^ ^ ^ Delmax2 - - - "Ice tooth maximum elastic deformation for model 2" m +typedef ^ ^ ^ Pitch - - - "Distance between sequential ice teeth for model 2" m +# ..... Ice Model 3 ............................................................................................................... +typedef ^ ^ ^ miuh - - - "Mean value of random ice thickness" m +typedef ^ ^ ^ varh - - - "Variance of random ice thicknesss" m^2 +typedef ^ ^ ^ miuv - - - "Mean value of random ice velocity" m/s +typedef ^ ^ ^ varv - - - "Variance of random ice velocity" m^2/s^2 +typedef ^ ^ ^ miut - - - "Mean value of ice loading event duration time" s +typedef ^ ^ ^ miubr - - - "Mean value of random ice brittle strength" MPa +typedef ^ ^ ^ varbr - - - "Variance of random ice brittle strength" MPa^2 +typedef ^ ^ ^ miuDelm - - - "Mean value of random random maximum ice tooth tip displacement" MPa +typedef ^ ^ ^ varDelm - - - "Variance of random random maximum ice tooth tip displacement" MPa^2 +typedef ^ ^ ^ miuP - - - "Mean value of random distance between sequential ice teeth" m +typedef ^ ^ ^ varP - - - "Variance of random distance between sequential ice teeth" m^2 +# ..... Ice Model 4 ............................................................................................................... +typedef IceDyn/IceD ^ IntKi Zn1 - - - "Number of failure zones along contact width" - +typedef ^ ^ ^ Zn2 - - - "Number of failure zones along contact height/thickness" - +typedef ^ ^ ReKi ZonePitch - - - "Distance between sequential ice teeth" m +typedef ^ ^ ^ PrflMean - - - "Ice structure contact profile mean value" m +typedef ^ ^ ^ PrflSig - - - "Ice structure contact profile standard deviation" m +typedef ^ ^ ^ IceStr - - - "Ice failure strength" MPa +typedef ^ ^ ^ Delmax - - - "Ice teeth maximum elastic deformation" m + +# ..... Ice Model 5 ............................................................................................................... +typedef ^ ^ ^ alpha - - - "slope angle of the cone" degree +typedef ^ ^ ^ Dwl - - - "cone waterline diameter" m +typedef ^ ^ ^ Dtp - - - "cone top diameter" m +typedef ^ ^ ^ hr - - - "ride-up ice thickness" m +typedef ^ ^ ^ mu - - - "friction coefficient between structure and ice" - +typedef ^ ^ ^ sigf - - - "flexural strength of ice" MPa +typedef ^ ^ ^ StrLim - - - "limit strain" - +typedef ^ ^ ^ StrRtLim - - - "limit strain rate" s^-1 +typedef ^ ^ IntKi UorD - - - "flag that indicates upward or downward breaking cone: 0,upward, 1,downward." - + +# ..... Ice Model 6 ............................................................................................................... + +typedef ^ ^ ReKi Ll - - - "Ice floe length" m + +typedef ^ ^ ^ Lw - - - "Ice floe width" m + +typedef ^ ^ ^ Cpa - - - "ice crushing strength pressure-area relation constant" - + +typedef ^ ^ ^ dpa - - - "ice crushing strength pressure-area relation order" - + +typedef ^ ^ ^ Fdr - - - "Constant external driving force" MN + +typedef ^ ^ ^ Kic - - - "Fracture toughness of ice" kNm^(-3/2) + +typedef ^ ^ ^ FspN - - - "Non-dimensional splitting load" - + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef IceDyn/IceD InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ ^ ^ RootName - - - "Root name of the output file" - +typedef ^ ^ ReKi MSL2SWL - - - "Offset between still-water level and mean sea level" m +typedef ^ ^ ReKi WtrDens - - - "Density of water" kg/m^3 +typedef ^ ^ ReKi gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ ^ IntKi LegNum - - - "Which number of legs on the turbine this is being initialized for" m +typedef ^ ^ DbKi TMax - - - "Total simulation time" s + + +# Define outputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef IceDyn/IceD InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ ^ ^ WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ ^ IntKi numLegs - - - "Number of legs on the structure" - +typedef ^ ^ ProgDesc Ver - - - "This module's name, version, and date" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# ..... Ice Model 6 ............................................................................................................... +typedef IceDyn/IceD ContinuousStateType ReKi q - - - "q - displacement of ice mass" m +typedef ^ ^ ^ dqdt - - - "dqdt - velocity of ice mass" m/s + +# Define discrete (nondifferentiable) states here: +typedef IceDyn/IceD DiscreteStateType SiKi DummyDiscState - - - "A variable, Replace if you have discrete states" - + +# Define constraint states here: +typedef IceDyn/IceD ConstraintStateType SiKi DummyConstrState - - - "A variable, Replace if you have constraint states" - + +# Define any other states, including integer or logical states here: +# ..... Ice Model 2 ............................................................................................................... +typedef IceDyn/IceD OtherStateType IntKi IceTthNo2 - - - "Ice tooth number of the current ice tooth, for model 2 (updated in UpdateStates; used in CalcOutput)" - +# ..... Ice Model 3 ............................................................................................................... +typedef ^ ^ IntKi Nc {:} - - "Number of the current ice tooths number (time series)" - +typedef ^ ^ ReKi Psum {:} - - "The sum of pitches of all broken ice teeth (time series)" m +# ..... Ice Model 4 ............................................................................................................... +typedef IceDyn/IceD ^ IntKi IceTthNo {:} - - "IceTthNo - the current numbers of ice teeth of each zone" - +# ..... Ice Model 5 ............................................................................................................... +typedef ^ ^ ReKi Beta - - - "angle between broken ice sheet and level waterline" rad +typedef ^ ^ DbKi Tinit - - - "Initial time of the current load cycle" s +# ..... Ice Model 6 ............................................................................................................... +typedef ^ ^ IntKi Splitf - - - "flag to indicate if the ice floe has split (0 not splitted, 1 splitted)" - +typedef ^ ^ ReKi dxc - - - "crushed depth of ice" m +typedef ^ ^ IceD_ContinuousStateType xdot {:} - - "previous state deriv for multi-step" m +typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated" - + + +# ..... 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 DummyMiscVar - - - "Remove this variable if you have misc/optimization variables" - + + +# ..... Parameters ................................................................................................................ +# Define parameters here: +# ..... General parameters ........................................................................................................ +typedef IceDyn/IceD ParameterType ReKi h - - - "Ice thickness" m +typedef ^ ^ ^ v - - - "Ice velocity" m/s +typedef ^ ^ ^ t0 - - - "Ice load starting time" s +typedef ^ ^ ^ StrWd - - - "The width of the structure" m +typedef ^ ^ ^ dt - - - "Time interval for integration within the module" s +typedef ^ ^ ^ InitLoc - - - "Ice sheet initial location" m +typedef ^ ^ ^ tolerance - - - "Tolerance when calculating ice breaking force, etc." - +typedef ^ ^ ^ Tmax - - - "Total simulation time" s +typedef ^ ^ IntKi verif - - - "flag to indicate if verification is being peformed" - +typedef ^ ^ ^ ModNo - - - "The current ice model number" - +typedef ^ ^ ^ SubModNo - - - "The current ice sub-model number" - +typedef ^ ^ ^ NumOuts - - - "The number of output channels" - +typedef ^ ^ ^ method - - - "integration method: 1-RK4, 2-AB4, 3-ABM4" - +typedef ^ ^ ^ TmStep - - - "Total time step" - +typedef ^ ^ CHARACTER(ChanLen) OutName {:} - - "Names of all requested output parameters" - +typedef ^ ^ ^ OutUnit {:} - - "Units of all requested output parameters" - +typedef ^ ^ CHARACTER(1024) RootName - - - "Rootname" - +# ..... Ice Model 1 ............................................................................................................... +typedef IceDyn/IceD ParameterType ReKi tm1a - - - "Time for the maximum force to be reached for model 1a" s +typedef ^ ^ ^ tm1b - - - "Time for the maximum force to be reached for model 1b" s +typedef ^ ^ ^ tm1c - - - "Time for the maximum force to be reached for model 1c" s +typedef ^ ^ ^ Fmax1a - - - "Maximum ice force of model 1a" N +typedef ^ ^ ^ Fmax1b - - - "Maximum ice force of model 1b" N +typedef ^ ^ ^ Fmax1c - - - "Maximum ice force of model 1c" N +typedef ^ ^ ^ Ikm - - - "Indentation factor" - +typedef ^ ^ ^ Cstr - - - "Constant when calculating creeping stresss" Pa*s^(-1/3) +typedef ^ ^ ^ EiPa - - - "Elastic modulus of ice" Pa +# ..... Ice Model 2 ............................................................................................................... +typedef IceDyn/IceD ParameterType ReKi Delmax2 - - - "Ice tooth maximum elastic deformation for model 2" m +typedef ^ ^ ^ Pitch - - - "Distance between sequential ice teeth" m +typedef ^ ^ ^ Kice2 - - - "Stiffness of ice teeth for model 2" N/m +# ..... Ice Model 3 ............................................................................................................... +typedef ^ ^ ^ rdmFm {:} - - "Random maximum ice force time series" m +typedef ^ ^ ^ rdmt0 {:} - - "Random ice loading event starting time" s +typedef ^ ^ ^ rdmtm {:} - - "Random time when the maximum force is reached" m +typedef ^ ^ ^ rdmDm {:} - - "Random maximum ice tooth tip displacement time series" m +typedef ^ ^ ^ rdmP {:} - - "Random distance between sequential ice teeth" m +typedef ^ ^ ^ rdmKi {:} - - "Random ice teeth stiffness" N/m + +# ..... Ice Model 4 ............................................................................................................... +typedef ^ ^ ReKi ZonePitch - - - "Distance between sequential ice teeth" m +typedef ^ ^ ^ Kice - - - "Stiffness of ice teeth" N/m +typedef ^ ^ ^ Delmax - - - "Ice teeth maximum elastic deformation" m +typedef ^ ^ ^ Y0 {:} - - "Ice structure contact profile initial location" m +typedef ^ ^ ^ ContPrfl {:} - - "Ice structure contact profile" m +typedef ^ ^ IntKi Zn - - - "Number of failure zones" - + +# ..... Ice Model 5 ............................................................................................................... +typedef ^ ^ ReKi rhoi - - - "Ice mass density " kg/m^3 +typedef ^ ^ ^ rhow - - - "Water mass density" kg/m^3 +typedef ^ ^ ^ alphaR - - - "Slope angle of the cone" rad +typedef ^ ^ ^ Dwl - - - "Cone waterline diameter " m +typedef ^ ^ ^ Zr - - - "Ice ride-up height" m +typedef ^ ^ ^ RHbr - - - "Horizontal breaking force" N +typedef ^ ^ ^ RVbr - - - "Vertical breaking force" N +typedef ^ ^ ^ Lbr - - - "Ice sheet breaking length" m +typedef ^ ^ ^ LovR - - - "Ratio of ice breaking length over cone radius" - +typedef ^ ^ ^ mu - - - "Friction coefficient between structure and ice" - +typedef ^ ^ ^ Wri - - - "Initial ride-up ice weight " kg +typedef ^ ^ ^ WL - - - "Broken ice piece weight" kg +# ..... Ice Model 6 ............................................................................................................... + +typedef ^ ^ ReKi Cpa - - - "ice crushing strength pressure-area relation constant" - + +typedef ^ ^ ^ dpa - - - "ice crushing strength pressure-area relation order" - + +typedef ^ ^ ^ FdrN - - - "Constant external driving force" N + +typedef ^ ^ ^ Mice - - - "Ice floe mass" kg +typedef ^ ^ ^ Fsp - - - "Ice floe splitting force" N + +# ..... Inputs .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef IceDyn/IceD InputType MeshType PointMesh - - - "contains displacement and velocity of structure" - + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef IceDyn/IceD OutputType MeshType PointMesh - - - "contains Ice force" N +typedef ^ ^ ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" + diff --git a/OpenFAST/modules/icefloe/CMakeLists.txt b/OpenFAST/modules/icefloe/CMakeLists.txt new file mode 100644 index 000000000..67306c750 --- /dev/null +++ b/OpenFAST/modules/icefloe/CMakeLists.txt @@ -0,0 +1,47 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/interfaces/FAST/IceFloe_FASTRegistry.inp ${CMAKE_CURRENT_LIST_DIR}/src/icefloe/IceFloe_Types.f90) +endif() + +set(ICEFLOE_LIBS_SOURCES + src/icefloe/IceFlexBase.F90 + src/icefloe/IceFlexIEC.f90 + src/icefloe/IceFlexISO.f90 + src/icefloe/IceFloeBase.F90 + src/icefloe/coupledCrushing.F90 + src/icefloe/crushingIEC.F90 + src/icefloe/crushingISO.F90 + src/icefloe/iceInput.f90 + src/icefloe/iceLog.F90 + src/icefloe/intermittentCrushing.F90 + src/icefloe/lockInISO.F90 + src/icefloe/randomCrushing.F90 + + src/interfaces/FAST/IceFloe.f90 + + src/icefloe/IceFloe_Types.f90 +) + +add_library(icefloelib ${ICEFLOE_LIBS_SOURCES}) +target_link_libraries(icefloelib nwtclibs) + +install(TARGETS icefloelib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) diff --git a/OpenFAST/modules/icefloe/README.md b/OpenFAST/modules/icefloe/README.md new file mode 100644 index 000000000..ca65c3f58 --- /dev/null +++ b/OpenFAST/modules/icefloe/README.md @@ -0,0 +1,31 @@ +# IceFloe Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/IceFloe/). + +## Overview +The U.S. Department of Energy (DOE) awarded DNV GL a project to create a model +for interaction of bottom-fixed offshore wind turbines with surface ice for use +with common simulation tools. The IceFloe module, which conforms to the +standards of the FAST Modularization Framework, was created from this project. + +The IceFloe module includes the option to apply loads from several models +(listed in table below) to a monopole structure or a multi-leg structure of +either three or four legs of the same diameter. For multi-leg support +structures, the ice loads are calculated independently for each leg; however +factors based on sheltering of one leg by another are also used, which can be +automatically applied or user specified. The project's final technical report +provides more details. + +| Ice Load Model in IceFloe | Source | +| ----------------------------- | ---------------------- | +| Continuous random crushing | ISO 19906, Karna | +| Intermittent crushing per ISO | ISO 19906 | +| Lock-in crushing per ISO | ISO 19906 | +| Lock-in crushing per IEC | IEC 61400-3, Korzhavin | +| Coupled crushing | Määtänen | +| Flexural failure per ISO | ISO 19906, Croasdale | +| Flexural failure per IEC | IEC 61400-3, Ralston | + +## Manual +IceFloe documentation is available +[here](https://nwtc.nrel.gov/system/files/DDRP0133-IceLoadFinalReport2014_10_30.pdf). diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFlexBase.F90 b/OpenFAST/modules/icefloe/src/icefloe/IceFlexBase.F90 new file mode 100644 index 000000000..83261d4c7 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFlexBase.F90 @@ -0,0 +1,90 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!**************************************************************** +! Routines for ice floes that apply loads to the structure +! via flexural failure of the ice sheet +! This module is a base module for flexural failure where a +! time series is precalculated + +module IceFlexBase + + use IceFloeBase + + implicit none + + public + +!-------------------------------------------------- +contains + +! calculate the time series of ice loads using the Croasdale method + subroutine initIceFlex (iceInput, inParams, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams), intent(out) :: inParams ! specific input parameter variable list + real(ReKi) :: frictionLimit + +! initialize the common parmeters + call initIceFloe(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting common flexural failure input parameters ') + + call getIceInput(iceInput, 'flexStrength', inParams%flexStrength, iceLog, 0.0_ReKi, 1.0E9_ReKi) + call logMessage(iceLog, ' flexStrength = '//TRIM(Num2LStr(inParams%flexStrength))//' Pascals') + + call getIceInput(iceInput, 'towerConeAngle', inParams%twr%coneAngle, iceLog, 20.0_ReKi, 70.0_ReKi) + call logMessage(iceLog, ' towerConeAngle = '//TRIM(Num2LStr(inParams%twr%coneAngle))//' degrees') + inParams%twr%coneAngle = D2R*inParams%twr%coneAngle ! convert to radians + +! Check on friction bounds to insure against incorrect zero or negative calculation of static load + if (inParams%twr%coneAngle > 45) then + frictionLimit = cos(inParams%twr%coneAngle)/sin(inParams%twr%coneAngle) - 0.01 + else + frictionLimit = sin(inParams%twr%coneAngle)/cos(inParams%twr%coneAngle) - 0.01 + endif + call getIceInput(iceInput, 'ice2twrFriction', inParams%ice2twrFriction, iceLog, 0.0_ReKi, frictionLimit) + call logMessage(iceLog, ' ice2twrFriction = '//TRIM(Num2LStr(inParams%ice2twrFriction))) + + call getIceInput(iceInput, 'iceDensity', inParams%iceDensity, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' iceDensity = '//TRIM(Num2LStr(inParams%iceDensity))//' kg/m^3') + + call getIceInput(iceInput, 'includeHb', inParams%includeHb, iceLog) + if (inParams%includeHb) call logMessage(iceLog, ' Breaking term, Hb term is included') + if (.not. inParams%includeHb) call logMessage(iceLog, ' Breaking term, Hb term is NOT included') + + call getIceInput(iceInput, 'includeHr', inParams%includeHr, iceLog) + if (inParams%includeHr) call logMessage(iceLog, ' Rubble pushing term, Hr term is included') + if (.not. inParams%includeHr) call logMessage(iceLog, ' Rubble pushing term, term is NOT included') + + end subroutine initIceFlex + +!**************************************************************************** + function outputFlexLoad (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputIceLoads (myIceParams, iceLog, time) + end function outputFlexLoad + +end module IceFlexBase diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFlexIEC.f90 b/OpenFAST/modules/icefloe/src/icefloe/IceFlexIEC.f90 new file mode 100644 index 000000000..6245d38b5 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFlexIEC.f90 @@ -0,0 +1,186 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!***************************************************************************************** +! Special type of loading due to ice sheet flexural failure using the Ralston method +! Ralston, T, "Ice Force Design Considerations for Conical Offshore Structures", POAC, 1977 +! As specified in IEC 61400-3 for offshore turbines +module iceFlexIEC + + use IceFlexBase + + implicit none + + public + +contains + +!============================================================================ +! calculate the time series of ice loads using the Ralston method + + subroutine initFlexIEC (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + +! local variables + real(ReKi) :: maxLoad ! maximum load + real(ReKi) :: freq ! frequency of sinusoidal load + integer(IntKi) :: nL !err, + +! initialize the common parmeters for flexural ice failure + call initIceFlex(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting up flexural failure by Ralston method ') + call logMessage(iceLog, ' Use the IEC 61400-3 suggested equations for max static loads') + + call getIceInput(iceInput, 'rideUpThickness', inParams%rideUpThickness, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' Ride up thickness = '//TRIM(Num2LStr(inParams%rideUpThickness))//' meters') + + call getIceInput(iceInput, 'twrConeTopDiam', inParams%twr%coneTopDiam, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' Tower cone top diameter = '//TRIM(Num2LStr(inParams%twr%coneTopDiam))//' meters') + + call getIceInput(iceInput, 'freqParamK', inParams%freqParamK, iceLog, 4.0_ReKi, 7.0_ReKi) + call logMessage(iceLog, ' Frequency parameter K = '//TRIM(Num2LStr(inParams%freqParamK))//' ') + + ! get leg load phase + if (myIceParams%numLegs>1) then + do nL = 1, myIceParams%numLegs + call getIceInput(iceInput, 'loadPhase'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%phase, iceLog, 0.0_ReKi, 360.0_ReKi) + call logMessage(iceLog, ' Load phase for leg '//TRIM(Num2LStr(nL))//' is ' & + //TRIM(Num2LStr(inParams%twr%leg(nL)%phase))//' degrees') + inParams%twr%leg(nL)%phase = D2R*inParams%twr%leg(nL)%phase + enddo + else + inParams%twr%leg(1)%phase = 0.0 + endif + +! The IEC/Ralston method precalculates a time series of loads based +! as a sinusoid at the fundamental (or a specified) frequency + +! First calculate the absolute maximum load +! Various terms are user optional + maxLoad = 0.0 + if(inParams%includeHr) maxLoad = maxLoad + H_r() + if(inParams%includeHb) maxLoad = (maxLoad + H_b()) + call logMessage(iceLog, '** Maximum static load for flexural failure = '//TRIM(Num2LStr(maxLoad))//'Newtons') + +! Precalculate the random time series +! with sinusoid per IEC + freq = inParams%iceVelocity/inParams%iceThickness/inParams%freqParamK + call IECLoadTimeSeries(myIceParams, inParams, iceLog, maxLoad, freq) + + contains +!================================================================== + +! Complete elliptical integral of the first kind +! Approximation from "Handbook of Mathematical Functions", +! U.S. Dept of Commerce, Nat. Bureau of Standards +! Ed. by Milton Abramovitch, June 1963 + function elliptic_1(alpha) result(K) + real(ReKi), intent(in) :: alpha + real(ReKi) :: m1 + real(ReKi) :: K + + m1 = 1.0 - sin(alpha)**2 + if (m1 == 0.0) then ! not likely, but just in case + K = huge(K) + return + endif + + K = 1.3862944 + 0.1119723*m1 + 0.0725296*m1**2 + K = K + log(1.0/m1)*(0.5 + 0.1213478*m1 + 0.0288729*m1**2) + end function elliptic_1 + +! Complete elliptical integral of the second kind +! Approximation from "Handbook of Mathematical Functions", +! U.S. Dept of Commerce, Nat. Bureau of Standards +! Ed. by Milton Abramovitch, June 1963 + function elliptic_2(alpha) result(E) + real(ReKi), intent(in) :: alpha + real(ReKi) :: m1 + real(ReKi) :: E + + m1 = 1.0 - sin(alpha)**2 + if (m1 == 0.0) then ! not likely, but just in case + E = 1.0 + return + endif + + E = 1.0 + 0.4630151*m1 + 0.1077812*m1**2 + E = E + log(1.0/m1)*(0.2452727*m1 + 0.0412496*m1**2) + end function elliptic_2 + + real(ReKi) function g_r() +! No div by zero for towerConeAngle between 20 and 70 degrees as limited on input + g_r = (sin(inParams%twr%coneAngle) + inParams%twr%coneAngle/cos(inParams%twr%coneAngle)) / & + (2.0*inParams%ice2twrFriction*inParams%twr%coneAngle*cos(inParams%twr%coneAngle) + & + 0.5*pi*sin(inParams%twr%coneAngle)**2) + end function g_r + +!------------------------------------------------------------------------ +! Ice breaking load + real(ReKi) function H_b() + real(ReKi) :: Y, G, x, term1, term2, term3 + + Y = 2.711 ! Based on Tresca yield criteria for the ice sheet + G = inParams%iceDensity*grav*inParams%twr%diam**2 & ! ice weight + / (4.0*inParams%flexStrength*inParams%iceThickness) ! ice strength + + x = 1.0 + 1.0/sqrt(3.0*G+0.5*Y) ! x will always be > 1 so no problems in below equations + + term1 = inParams%flexStrength*inParams%iceThickness**2/3.0 + term2 = tan(inParams%twr%coneAngle)/(1.0-g_r()*inParams%ice2twrFriction) ! 1-g_r*mu can be zero for large angles and friction but input checking should cover this + term3 = G*(x-1.0)*(x+2.0) + (1.0+Y*x*log(x))/(x-1.0) + + H_b = term1*term2*term3 + end function H_b + +! Hr is the load required to push the ice blocks up the slope of the structure and through the rubble pile + real(ReKi) function H_r() + real(ReKi) :: W, f, numer, denom + + W = inParams%iceDensity*grav*inParams%rideUpThickness*(inParams%twr%diam**2 - inParams%twr%coneTopDiam**2) & + /4.0/cos(inParams%twr%coneAngle) + f = inParams%ice2TwrFriction*elliptic_1(inParams%twr%coneAngle)*cos(inParams%twr%coneAngle) & + + sin(inParams%twr%coneAngle) + numer = tan(inParams%twr%coneAngle) + inParams%ice2TwrFriction*(elliptic_2(inParams%twr%coneAngle) & + - f*g_r()*cos(inParams%twr%coneAngle)) + denom = (1.0-g_r()*inParams%ice2TwrFriction) ! 1-g_r*mu can be zero for large angles and friction but input checking should cover this + + H_r = W*numer/denom + end function H_r + + end subroutine initFlexIEC + +!-------------------------------------------------------------------- +! get load for requested time + function outputFlexLoadIEC (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputFlexLoad (myIceParams, iceLog, time) + end function outputFlexLoadIEC + +end module iceFlexIEC + diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFlexISO.f90 b/OpenFAST/modules/icefloe/src/icefloe/IceFlexISO.f90 new file mode 100644 index 000000000..bc1844f3d --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFlexISO.f90 @@ -0,0 +1,351 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!**************************************************************** +! Special type of flexural failure using the Croasdale method +! Croasdale, K.R. and Cammaert A.B. "An Improved Method for the Calculation of Ice Loads on Sloping Structures ..." +! Hydrotechnical Construction Vol. 28 No. 3 ,March, 1994 + +module IceFlexISO + + use IceFlexBase + + implicit none + + public + +contains + + subroutine initFlexISO (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput ! Parameters from input file for initialization + type(iceFloe_ParameterType), intent(inout) :: myIceParams ! saved parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + +! local variables + real(ReKi) :: maxLoad, Hb + +! initialize the common parmeters for flexural ice failure + call initIceFlex(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting up flexural failure by ISO/Croasdale method ') + call logMessage(iceLog, ' Based on the ISO 19906 standard equations for max static loads') + + call getIceInput(iceInput, 'peakLoadCOV', inParams%peakLoadCOV, iceLog, 0.1_ReKi, 0.5_ReKi) + call logMessage(iceLog, ' peakLoadCOV = '//TRIM(Num2LStr(inParams%peakLoadCOV))//' (-)') + + call getIceInput(iceInput, 'coeffLoadPeaks', inParams%coeffLoadPeaks, iceLog, 0.1_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' coeffLoadPeaks = '//TRIM(Num2LStr(inParams%coeffLoadPeaks))) + + call getIceInput(iceInput, 'coeffLoadMin', inParams%coeffLoadMin, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' coeffLoadMin = '//TRIM(Num2LStr(inParams%coeffLoadMin))) + + call getIceInput(iceInput, 'periodCOV', inParams%periodCOV, iceLog, 0.1_ReKi, 0.9_ReKi) + call logMessage(iceLog, ' periodCOV = '//TRIM(Num2LStr(inParams%periodCOV))) + + call getIceInput(iceInput, 'tauMin', inParams%tauMin, iceLog, 0.1_ReKi, 0.8_ReKi) + call logMessage(iceLog, ' tauMin = '//TRIM(Num2LStr(inParams%tauMin))) + + call getIceInput(iceInput, 'tauMax', inParams%tauMax, iceLog, inParams%tauMin, 1.0_ReKi) + call logMessage(iceLog, ' tauMax = '//TRIM(Num2LStr(inParams%tauMax))) + + call getIceInput(iceInput, 'riseTime', inParams%riseTime, iceLog, 0.1_ReKi, 0.9_ReKi) + call logMessage(iceLog, ' riseTime = '//TRIM(Num2LStr(inParams%riseTime))) + inParams%fallTime = 1.0 - inParams%riseTime + + call getIceInput(iceInput, 'coeffBreakLength', inParams%coeffBreakLength, iceLog, 3.0_ReKi, 10.0_ReKi) + call logMessage(iceLog, ' coeffBreakLength = '//TRIM(Num2LStr(inParams%coeffBreakLength))) + + call getIceInput(iceInput, 'rubbleHeight', inParams%rubbleHeight, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' rubbleHeight = '//TRIM(Num2LStr(inParams%rubbleHeight))//' meters') + + call getIceInput(iceInput, 'rubblePorosity', inParams%rubblePorosity, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' rubblePorosity = '//TRIM(Num2LStr(inParams%rubblePorosity))) + + call getIceInput(iceInput, 'rubbleCohesion', inParams%rubbleCohesion, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' rubbleCohesion strength = '//TRIM(Num2LStr(inParams%rubbleCohesion))//' Pascals') + + call getIceInput(iceInput, 'rubbleAngle', inParams%rubbleAngle, iceLog, 0.0_ReKi, inParams%twr%coneAngle/D2R) + call logMessage(iceLog, ' rubbleAngle = '//TRIM(Num2LStr(inParams%rubbleAngle))//' degrees') + inParams%rubbleAngle = D2R*inParams%rubbleAngle ! Convert to radians + + call getIceInput(iceInput, 'frictionAngle', inParams%frictionAngle, iceLog, & + inParams%rubbleAngle/D2R, inParams%twr%coneAngle/D2R) + call logMessage(iceLog, ' frictionAngle = '//TRIM(Num2LStr(inParams%frictionAngle))//' degrees') + inParams%frictionAngle = D2R*inParams%frictionAngle ! Convert to radians + + call getIceInput(iceInput, 'ice2iceFriction', inParams%ice2iceFriction, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' ice2iceFriction = '//TRIM(Num2LStr(inParams%ice2iceFriction))) + + call getIceInput(iceInput, 'waterDensity', inParams%waterDensity, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' waterDensity = '//TRIM(Num2LStr(inParams%waterDensity))//' kg/m^3') + + call getIceInput(iceInput, 'iceModulus', inParams%iceModulus, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' iceModulus = '//TRIM(Num2LStr(inParams%iceModulus))//' Pascals') + + call getIceInput(iceInput, 'poissonRatio', inParams%poissonRatio, iceLog, 0.0_ReKi, 0.5_ReKi) + call logMessage(iceLog, ' poissonRatio = '//TRIM(Num2LStr(inParams%poissonRatio))) + + call getIceInput(iceInput, 'includeHp', inParams%includeHp, iceLog) + if (inParams%includeHp) then + call logMessage(iceLog, ' Including pile up term, Hp') + else + call logMessage(iceLog, ' NOT including pile up term, Hp') + endif + + call getIceInput(iceInput, 'includeHl', inParams%includeHl, iceLog) + if (inParams%includeHl) then + call logMessage(iceLog, ' Including rubble lifting term, Hl') + else + call logMessage(iceLog, ' NOT including rubble lifting term, Hl') + endif + + call getIceInput(iceInput, 'includeHt', inParams%includeHt, iceLog) + if (inParams%includeHt) then + call logMessage(iceLog, ' Including block rotation term, Ht') + else + call logMessage(iceLog, ' NOT including block rotation term, Ht') + endif + + call getIceInput(iceInput, 'includeLc', inParams%includeLc, iceLog) + if (inParams%includeLc) then + call logMessage(iceLog, ' Including crack lenght modification term, Lc') + else + call logMessage(iceLog, ' NOT including crack lenght modification term, Lc') + endif + +! The Croasdale method precalculates a time series of loads based +! on the input parameters and random distributions + +! First calculate the absolute maximum load +! Various terms are user optional + maxLoad = 0.0 + if(inParams%includeHp) then + maxLoad = maxLoad + H_p() + call logMessage(iceLog, '** Pile up term, Hp = '//TRIM(Num2LStr(H_p()))//' Newtons') + endif + if(inParams%includeHl) then + maxLoad = maxLoad + H_l() + call logMessage(iceLog, '** Rubble lifting term, Hl = '//TRIM(Num2LStr(H_l()))//' Newtons') + endif + if(inParams%includeHt) then + maxLoad = maxLoad + H_t() + call logMessage(iceLog, '** Block rotation term, Ht = '//TRIM(Num2LStr(H_t()))//' Newtons') + endif + if(inParams%includeHr) then + maxLoad = maxLoad + H_r() + call logMessage(iceLog, '** Rubble push through term, Hr = '//TRIM(Num2LStr(H_r()))//' Newtons') + endif + if(inParams%includeHb) then + Hb = H_b() + maxLoad = (maxLoad + Hb) / (1.0-Hb/(inParams%flexStrength*l_c()*inParams%iceThickness)) + call logMessage(iceLog, '** Breaking load term, Hb = '//TRIM(Num2LStr(Hb))//' Newtons') + endif + call logMessage(iceLog, '** Maximum static load for flexural failure = '//TRIM(Num2LStr(maxLoad))//' Newtons') + +! Precalculate the random time series + call randomFlexLoadTimeSeries(myIceParams, iceLog, maxLoad) + + contains +!-------------------------------------------------------------------- +! Various load terms for max staic load +! generally DIV by zeros are protected against by input parameter checking +! +! crack width term + real(ReKi) function l_c() + real(ReKi) :: Lc + Lc = sqrt(sqrt((inParams%iceModulus*inParams%iceThickness**3) & + / (12.0*inParams%waterDensity*grav*(1.0-inParams%poissonRatio**2)) )) + l_c = inParams%twr%diam + if (inParams%includeLc) then + l_c = l_c + 0.25*Lc*pi**2 + endif + end function l_c + + real(ReKi) function xi() +! protection against DIV by zero on this function covered by input parameter checking + xi = (sin(inParams%twr%coneAngle) + inParams%ice2twrFriction * cos(inParams%twr%coneAngle)) / & + (cos(inParams%twr%coneAngle) - inParams%ice2twrFriction * sin(inParams%twr%coneAngle)) + end function xi + + real(ReKi) function cot(angle) + real(ReKi), intent(in) :: angle + cot = tan(pi/2.0-angle) + end function cot + +! term with tangents that appears in many of the load terms + real(ReKi) function angleRatio(theta, alpha) + real(ReKi), intent(in) :: theta, alpha + angleRatio = 1.0 - tan(theta)/tan(alpha) + end function angleRatio + +! Ice breaking load + real(ReKi) function H_b() + H_b = 0.68*xi()*inParams%flexStrength*sqrt(sqrt(inParams%waterDensity*grav*inParams%iceThickness**5 & + / inParams%iceModulus))*l_c() + end function H_b + +! Hr is the load required to push the ice blocks up the slope of the structure and through the rubble pile + real(ReKi) function H_r() + real(ReKi) :: P ! effective weight of the rubble pile + + P = 0.5*inParams%ice2iceFriction*(inParams%ice2iceFriction+inParams%ice2twrFriction) & + *inParams%iceDensity*grav*(1.0-inParams%rubblePorosity)*(inParams%rubbleHeight**2) & + *sin(inParams%twr%coneAngle)*(cot(inParams%rubbleAngle)-cot(inParams%twr%coneAngle)) & + *angleRatio(inParams%rubbleAngle,inParams%twr%coneAngle) + + P = P + 0.5*(inParams%ice2iceFriction+inParams%ice2twrFriction)*inParams%iceDensity*grav & + *(1.0-inParams%rubblePorosity)*(inParams%rubbleHeight**2)*cos(inParams%twr%coneAngle) & + /tan(inParams%twr%coneAngle)*angleRatio(inParams%rubbleAngle,inParams%twr%coneAngle) + + P = P + inParams%rubbleHeight*inParams%iceThickness*inParams%iceDensity*grav & + *(sin(inParams%twr%coneAngle)+inParams%ice2twrFriction*cos(inParams%twr%coneAngle)) & + /sin(inParams%twr%coneAngle) + + H_r = inParams%twr%diam*P /(cos(inParams%twr%coneAngle)-inParams%ice2twrFriction*sin(inParams%twr%coneAngle)) + end function H_r + +! Load required to push the ice sheet through the rubble + real(ReKi) function H_p() + H_p = inParams%twr%diam*(inParams%rubbleHeight**2)*inParams%ice2iceFriction*inParams%iceDensity & + *grav*(1.0-inParams%rubblePorosity)*(angleRatio(inParams%rubbleAngle,inParams%twr%coneAngle))**2 & + /(2.0*tan(inParams%rubbleAngle)) + end function H_p + +! Force required to rotate the ice blocks at the cone to cylinder transition of the tower + real(ReKi) function H_t() + H_t = 1.5*inParams%twr%diam*(inParams%iceThickness**2)*inParams%iceDensity*grav*cos(inParams%twr%coneAngle) + H_t = H_t/(sin(inParams%twr%coneAngle)-inParams%ice2twrFriction*cos(inParams%twr%coneAngle)) + end function H_t + +! Fore required to lift the rubble pile that is above the ice sheet + real(ReKi) function H_l() + H_l = cot(inParams%rubbleAngle)-cot(inParams%twr%coneAngle) + H_l = H_l + tan(inParams%frictionAngle)*angleRatio(inParams%rubbleAngle,inParams%twr%coneAngle) + H_l = 0.5*H_l*inParams%rubbleHeight*inParams%iceDensity*grav*(1.0-inParams%rubblePorosity) + inParams%rubbleCohesion + H_l = H_l*xi()*inParams%twr%diam*inParams%rubbleHeight*angleRatio(inParams%rubbleAngle,inParams%twr%coneAngle) + end function H_l + +!**************************************************************************** +! Calculate a sawtooth loading time series with random periods and peaks + subroutine randomFlexLoadTimeSeries (myIceParams, iceLog, maxLoad) + real(ReKi), intent(in) :: maxLoad + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + + integer(IntKi), parameter :: LuxLevel = 3 + integer(IntKi) :: err + integer(IntKi) :: n, ns, nL, nSteps, nRiseSteps, nFallSteps, minLoadSteps + real(ReKi) :: meanLoad ! Mean of the instantaneous peaks of the cycles + real(ReKi) :: peakLoad ! Instantaneous peak for a single cycle + real(ReKi) :: minLoad ! Minimum possible load + real(ReKi) :: meanPeriod ! Mean loading/unloading/dwell cycle period, seconds + real(ReKi) :: period ! randomly distributed period for a single cycle + + real(ReKi) :: tau(1) ! for passing into random number routine + +! Initialize the random number generator + CALL RLuxGo ( LuxLevel, abs(inParams%randomSeed), 0, 0 ) + +! Calc overall number of steps + nSteps = size(myIceParams%loadSeries,1) + +! Calculate the mean period and loads + meanPeriod = inParams%coeffBreakLength*inParams%iceThickness/inParams%iceVelocity + minLoad = inParams%coeffLoadMin*maxLoad + meanLoad = minLoad*(1.0-inParams%coeffLoadPeaks) + inParams%coeffLoadPeaks*maxLoad + +! Loop on all legs + do nL = 1, myIceParams%numLegs + + ! Number of whole periods required not known (since period lenght is random) + ! So iterate until we have enough points in the time series + n = 1 + seriesLoop: do while (n < nSteps+1) + ! Period is time from no load up to peak, down, then dwell at minimum (normal distribution) + CALL RndNorm( period, meanPeriod, inParams%periodCOV*meanPeriod ) + ! Period has to be limited to +/- 50% of the mean period + period = min(1.5*meanPeriod, max(0.5*meanPeriod, period)) + + ! sub period is the fraction of a period: time for load to go up then down (uniform distribution) + CALL RanLux ( tau ) + ! adjust the sub period to be on the requested interval + tau(1) = inParams%tauMin + (inParams%tauMax - inParams%tauMin)*tau(1) + + ! Peak instantaneous load for the period (normal distribution) + CALL RndNorm( peakLoad, meanLoad, inParams%peakLoadCOV*meanLoad ) + ! adjust the peak load to the absolute min and instantaneous max + peakLoad = min(maxLoad, max(minLoad, peakLoad)) + + ! begin to increase the load from the minimum to the instantaneous peak + nRiseSteps = nint( inParams%riseTime * tau(1) * period / myIceParams%dt) + if (nRiseSteps == 0) then ! if dt is too large compared to the rise time then get div by zero below + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Time step too large or period too short in RandomFlexLoadTimeSeries', 1) + return + endif + do ns = 1, nRiseSteps + myIceParams%loadSeries(n,nL) = minLoad + (peakLoad-minLoad)*float(ns-1)/float(nRiseSteps) + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + + ! begin to decrease the load from the peak down to the minimum + nFallSteps = nint( inParams%fallTime * tau(1) * period / myIceParams%dt) + if (nFallSteps == 0) then ! if dt is too large compared to the fall time then get div by zero below + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Time step too large or period too short in RandomFlexLoadTimeSeries', 1) + return + endif + do ns = 1, nFallSteps + myIceParams%loadSeries(n,nL) = peakLoad - (peakLoad-minLoad)*float(ns-1)/float(nFallSteps) + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + + ! Fill the remaining time steps in the period with the minimum load + minLoadSteps = nint( period / myIceParams%dt) - nRiseSteps - nFallSteps + do ns = 1, minLoadSteps + myIceParams%loadSeries(n,nL) = minLoad + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + + enddo seriesLoop + + ! Apply shelter factor to individual legs + myIceParams%loadSeries(:,nL) = myIceParams%ks(nL)*myIceParams%loadSeries(:,nL) + + enddo ! leg loop + + end subroutine randomFlexLoadTimeSeries + + end subroutine initFlexISO ! containing subroutine + +!-------------------------------------------------------------------- +! get load for requested time + function outputFlexLoadISO (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputFlexLoad (myIceParams, iceLog, time) + end function outputFlexLoadISO + +end module IceFlexISO diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFloeBase.F90 b/OpenFAST/modules/icefloe/src/icefloe/IceFloeBase.F90 new file mode 100644 index 000000000..432ed822c --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFloeBase.F90 @@ -0,0 +1,350 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!**************************************************************** +! base type for ice floes, contains generic +! initialization, update, and utility routines + + +module IceFloeBase + + use precision + use IceFloe_Types + use IceInputParams + use Ran_Lux_Mod + use NWTC_IO, only : Num2LStr + + implicit none + + public + +! This is compared to gravity in FAST, warning if different + real(ReKi), parameter :: grav = 9.81 + +! ice type parameters + integer(IntKi), parameter :: randomCrush = 1 + integer(IntKi), parameter :: interCrush = 2 + integer(IntKi), parameter :: lockInISO = 3 + integer(IntKi), parameter :: crushIEC = 4 + integer(IntKi), parameter :: cpldCrush = 5 + integer(IntKi), parameter :: flexFailISO = 6 + integer(IntKi), parameter :: flexFailIEC = 7 + +! for input checking + integer(IntKi), parameter :: lowTypeLimit = min(randomCrush, interCrush, lockInISO, crushIEC, & + cpldCrush, flexFailISO, flexFailIEC) + integer(IntKi), parameter :: hiTypeLimit = max(randomCrush, interCrush, lockInISO, crushIEC, & + cpldCrush, flexFailISO, flexFailIEC) + +! structure to hold some tower data + + + +!---------------------------------------------------------------------------------------------------- +contains + +! Generic initialization of the most common parameters +! Only function is to assign input parameters to convenient variables in module + subroutine initIceFloe (iceInput, inParams, myIceParams, iceLog) + type(iceInputType), intent(in) :: iceInput ! Parameters from input file for initialization + type(iceFloe_ParameterType), intent(inout) :: myIceParams ! saved parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams), intent(out) :: inParams ! specific input parameter variable list + integer(IntKi) :: err + integer(IntKi) :: nL + real(ReKi) :: spacing ! get leg spacing from x,y coords + + call logMessage(iceLog, newLine//' Setting common ice flow input parameters ') + + call getIceInput(iceInput, 'iceType', inParams%iceType, iceLog, lowTypeLimit, hiTypeLimit) + call logMessage(iceLog, ' Ice type = '//TRIM(Num2LStr(inParams%iceType))) + + call getIceInput(iceInput, 'iceThickness', inParams%iceThickness, iceLog, 0.001_ReKi, 100.0_ReKi) + call logMessage(iceLog, ' Ice thickness = '//TRIM(Num2LStr(inParams%iceThickness))//' meters') + + call getIceInput(iceInput, 'iceVelocity', inParams%iceVelocity, iceLog, 0.001_ReKi, 10.0_ReKi) + call logMessage(iceLog, ' Ice velocity = '//TRIM(Num2LStr(inParams%iceVelocity))//' m/s') + + call getIceInput(iceInput, 'iceDirection', inParams%iceDirection, iceLog, -360.0_ReKi, 360.0_ReKi) + call logMessage(iceLog, ' Ice direction = '//TRIM(Num2LStr(inParams%iceDirection))//' degrees') + inParams%iceDirection = D2R*inParams%iceDirection + myIceParams%iceDirection = inParams%iceDirection ! must save this parameter for later output calcs + + call getIceInput(iceInput, 'timeStep', inParams%timeStep, iceLog, 0.0_ReKi) + call logMessage(iceLog, ' Time step = '//TRIM(Num2LStr(inParams%timeStep))//' sec') + + call getIceInput(iceInput, 'towerDiameter', inParams%twr%diam, iceLog, 0.1_ReKi, 100.0_ReKi) + call logMessage(iceLog, ' Tower diameter = '//TRIM(Num2LStr(inParams%twr%diam))//' meters') + + call getIceInput(iceInput, 'randomSeed', inParams%randomSeed, iceLog, 0) + call logMessage(iceLog, ' Random seed = '//TRIM(Num2LStr(inParams%randomSeed))) + + allocate (inParams%twr%leg(myIceParams%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in allocation of support leg array', 1) + return ! error in array allocation + endif + + if (myIceParams%numLegs > 1) then + call logMessage(iceLog, ' Number of legs in support structure = '//TRIM(Num2LStr(myIceParams%numLegs))) + + call getIceInput(iceInput, 'singleLoad', inParams%singleLoad, iceLog) + myIceParams%singleLoad = inParams%singleLoad ! must save this parameter for later use + if (inParams%singleLoad) then + call logMessage(iceLog, ' Apply multitple leg loads as a single equivalent load') + else + call logMessage(iceLog, ' Apply multitple leg loads individually') + endif + + ! get leg locations + do nL = 1, myIceParams%numLegs + call getIceInput(iceInput, 'legX'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%X, iceLog) + call getIceInput(iceInput, 'legY'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%Y, iceLog) + call logMessage(iceLog, ' Leg '//TRIM(Num2LStr(nL))//' position is (' & + //TRIM(Num2LStr(inParams%twr%leg(nL)%X))//', '//TRIM(Num2LStr(inParams%twr%leg(nL)%Y))//') meters') + myIceParams%legX(nL) = inParams%twr%leg(nL)%X + myIceParams%legY(nL) = inParams%twr%leg(nL)%Y + enddo + + ! get minimum leg spacing + spacing = sqrt((inParams%twr%leg(1)%X-inParams%twr%leg(2)%X)**2 + (inParams%twr%leg(1)%Y-inParams%twr%leg(2)%Y)**2) + if (myIceParams%numLegs > 2) spacing = min(spacing, sqrt((inParams%twr%leg(2)%X-inParams%twr%leg(3)%X)**2 + & + (inParams%twr%leg(2)%Y-inParams%twr%leg(3)%Y)**2)) + if (myIceParams%numLegs > 3) spacing = min(spacing, sqrt((inParams%twr%leg(4)%X-inParams%twr%leg(3)%X)**2 + & + (inParams%twr%leg(4)%Y-inParams%twr%leg(3)%Y)**2)) + spacing = min(spacing, sqrt((inParams%twr%leg(1)%X-inParams%twr%leg(myIceParams%numLegs)%X)**2 + & + (inParams%twr%leg(1)%Y-inParams%twr%leg(myIceParams%numLegs)%Y)**2)) + + if (spacing/inParams%twr%diam < 4.0) then + call iceErrorHndlr (iceLog, ErrID_Warn, & + 'Leg spacing/diameter is < 4, high potential for jamming forces which are not considered by this routine', 1) + endif + +! Auto calculate or assign from user input leg load shelter factors + call getIceInput(iceInput, 'legAutoFactor', inParams%legAutoFactor, iceLog) + if (inParams%legAutoFactor) then + call logMessage(iceLog, ' Leg load shelter factors determined automatically') + else + call logMessage(iceLog, ' Leg load shelter factors assigned by user') + endif + do nL = 1, myIceParams%numLegs + myIceParams%ks(nL) = shelterFactor(myIceParams%numLegs, spacing, & + inParams%twr%leg(nL)%X, inParams%twr%leg(nL)%Y, inParams%iceDirection) + call logMessage(iceLog, ' Auto calculated shelter factor for leg #'//TRIM(Num2LStr(nL))// & + ' = '//TRIM(Num2LStr(myIceParams%ks(nL)))) + if (.not. inParams%legAutoFactor) then + call getIceInput(iceInput, 'shelterFactor_ks'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%ks, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' User specified shelter factor for leg #'//TRIM(Num2LStr(nL))// & + ' = '//TRIM(Num2LStr(inParams%twr%leg(nL)%ks))) +! Compare auto generated to user assigned factors, warn if big difference + if (abs(inParams%twr%leg(nL)%ks - myIceParams%ks(nL)) > 0.1) then + call iceErrorHndlr (iceLog, ErrID_Warn, & + 'User assigned shelter factor is more then 0.1 different than auto calculated factor - please check', 1) + endif + myIceParams%ks(nL) = inParams%twr%leg(nL)%ks + endif + enddo + + else + myIceParams%ks(1) = 1.0 + myIceParams%singleLoad = .true. + endif + + end subroutine initIceFloe + + +!======================================================================= +! Use some trigonometry to assign shelter factors to the individual legs +! Based on iceFloe directon and leg coordinates +! This algorithm assumes the legs are spaced evenly around the tower centroid at (0,0) + function shelterFactor (nLegs, spacing, X, Y, iceDir) result(factor) + + integer(IntKi), intent(in) :: nLegs + real(ReKi), intent(in) :: X, Y, spacing, iceDir ! ice floe direction in radians + real(ReKi) :: factor + real(ReKi) :: angle, rotX, rotY, loAngle, hiAngle + +! For large spacing legs are independent and factor = 1 + if (spacing > 5.0) then + factor = 1.0 + return + endif + +! calculate the angle between the ice Floe direction vector and +! the vector from the tower centroid to the specified leg + rotX = X*cos(iceDir) + Y*sin(iceDir) + rotY = -X*sin(iceDir) + Y*cos(iceDir) + angle = mod(R2D*atan2(rotY,rotX)+360.0_ReKi,360.0_ReKi) + +! assign angle limits dependent on number of legs + if (nLegs < 4) then + loAngle = 60.0 + hiAngle = 300.0 + else + loAngle = 67.5 + hiAngle = 292.5 + endif + +! assign the factors + factor = 1.0 + if (angle < loAngle .or. angle >= hiAngle) factor = 0.0 + + end function shelterFactor + +!======================================================================= +! Calculate a sinusoidal load time series per IEC 61400-3 Ed 1 Annex E section E.4.6 + subroutine IECLoadTimeSeries (myIceParams, inParams, iceLog, maxLoad, freq) + real(ReKi), intent(in) :: maxLoad, freq + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(inputParams), intent(in) :: inParams ! specific input parameter variable list + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables +! integer(IntKi) :: err + integer(IntKi) :: ns, nL, nSteps + real(ReKi) :: timeStep + +! Calc overall number of steps + nSteps = size(myIceParams%loadSeries,1) + + do ns = 1, nSteps + timeStep = myIceParams%dt*real(ns,ReKi) + do nL = 1, myIceParams%numLegs + myIceParams%loadSeries(ns,nL) = myIceParams%ks(nL)*maxLoad*(0.75 + & + 0.25*sin(2.0*pi*freq*timeStep+inParams%twr%leg(nL)%phase)) + enddo + enddo + + end subroutine IECLoadTimeSeries + +!======================================================================= +! Generic update function - really just an interpolation +! routine for the precalculated load time series + function outputIceLoads (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + integer(IntKi) :: nStepLow, nStepHigh + real(ReKi) :: iceForceMag ! load in Newtons in direction of ice flow + integer(IntKi) :: nL + + do nL = 1, myIceParams%numLegs + ! find the time steps before and after time + nStepLow = floor(time/myIceParams%dt) + 1 ! +1 so that time = 0 is point #1 + if (nStepLow < 1) then + nStepLow = 1 + call iceErrorHndlr (iceLog, ErrID_Warn, 'Calling program is attempting to obtain an '// & + 'ice load value for time < 0, '// & + 't=0 value will be used', 0 ) + endif + if (nStepLow > size(myIceParams%loadSeries,1)) nStepLow = size(myIceParams%loadSeries,1) + nStepHigh = min(nStepLow+1, size(myIceParams%loadSeries,1)) + + if(nStepLow > size(myIceParams%loadSeries,1)) then + nStepLow = size(myIceParams%loadSeries,1) + nStepHigh = nStepLow + call iceErrorHndlr (iceLog, ErrID_Warn, 'Calling program is attempting to obtain an '// & + 'ice load value past the end time, '// & + 't=endTime value will be used', 0 ) + endif + + ! calculate the magnitude of the load + iceForceMag = (myIceParams%loadSeries(nStepHigh,nL) - myIceParams%loadSeries(nStepLow,nL)) & + * (time/myIceParams%dt - float(nStepLow-1)) + myIceParams%loadSeries(nStepLow,nL) + + ! apply the load in the proper direction via x,y components + iceLoads(:,nL) = iceLoadDirection(iceForceMag, myIceParams) + enddo + + ! If the loads from multiple legs are applied as an "effective" load on one leg at the + ! support center, then compute that effective load vector and put into the first load vector + ! Note that only Fx, Fy, and Mz terms re-calculated. All others remain zero + if (myIceParams%numLegs > 1 .and. myIceParams%singleLoad) & + iceLoads(:,1) = iceLoadEquivalent(iceLoads, myIceParams) + + end function outputIceLoads + +!=================================================================================================== +! Function to handle ice forces from a specified direction relative to ground coordinates (in horizontal plane) + function iceLoadDirection(iceForceMag, myIceParams) result(loadVect) + real(ReKi), intent(in) :: iceForceMag + type(iceFloe_ParameterType), intent(in) :: myIceParams + real(ReKi) :: loadVect(6) + + loadVect(1) = iceForceMag * cos(myIceParams%iceDirection) + loadVect(2) = iceForceMag * sin(myIceParams%iceDirection) + loadVect(3) = 0.0 + loadVect(4) = 0.0 + loadVect(5) = 0.0 + loadVect(6) = 0.0 + + end function iceLoadDirection + +!=================================================================================================== +! Function to calculate a single equivalent load vector from multiple leg locad vectors + function iceLoadEquivalent(inLoads, myIceParams) result(equiv) + type(iceFloe_ParameterType), intent(in) :: myIceParams + real(ReKi) :: inLoads(6,myIceParams%numLegs) + real(ReKi) :: equiv(6) + integer(IntKi) :: nL + + equiv = 0.0 + do nL = 1, myIceParams%numLegs + equiv(6) = equiv(6) + inLoads(2,nL)*myIceParams%legX(nL) - inLoads(1,nL)*myIceParams%legY(nL) + equiv(1) = equiv(1) + inLoads(1,nL) + equiv(2) = equiv(2) + inLoads(2,nL) + enddo + + end function iceLoadEquivalent + +! Some utility routines + +!======================================================================= +! Generate random numbers on a normal distribution +! Borrowed from Turbsim v1.50 + + SUBROUTINE RndNorm( RandNormNum, mu, sigma ) + + IMPLICIT NONE + + REAL(ReKi), INTENT(OUT) :: RandNormNum ! Normally distributed numbers + REAL(ReKi), INTENT(IN), OPTIONAL :: mu ! mean of the distributed numbers - DEFAULT IS 0.0 + REAL(ReKi), INTENT(IN), OPTIONAL :: sigma ! standard deviation of the distributed numbers - DEFAULT IS 1.0 + + ! Internal variable + REAL(ReKi) :: RN(2) ! Pairs of random numbers +! integer(IntKi) :: n + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + CALL RanLux(RN) + + RandNormNum = SQRT(PI/8.0)*LOG((1.0+RN(1))/(1.0-RN(1))) + IF (RN(2) < 0.5) RandNormNum = -RandNormNum + + ! Give the correct mean and standard deviation, if specified + IF ( PRESENT( sigma ) ) THEN + RandNormNum = RandNormNum * sigma + ENDIF + + IF ( PRESENT( mu ) ) THEN + RandNormNum = RandNormNum + mu + ENDIF + + END SUBROUTINE RndNorm + +end module IceFloeBase diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types.f90 b/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types.f90 new file mode 100644 index 000000000..630cf872c --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types.f90 @@ -0,0 +1,2459 @@ +!STARTOFREGISTRYGENERATEDFILE 'IceFloe_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 +!********************************************************************************************************************************* +! IceFloe_Types +!................................................................................................................................. +! This file is part of IceFloe. +! +! 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 IceFloe. 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 IceFloe_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= IceFloe_InitInputType ======= + TYPE, PUBLIC :: IceFloe_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + REAL(ReKi) :: simLength !< Duration of simulation [sec] + REAL(ReKi) :: MSL2SWL !< Offset between still-water level and mean sea level [m] + REAL(ReKi) :: gravity !< Gravitational acceleration [m/s^2] + character(1024) :: RootName !< Output file root name [-] + END TYPE IceFloe_InitInputType +! ======================= +! ========= IceFloe_InitOutputType ======= + TYPE, PUBLIC :: IceFloe_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE IceFloe_InitOutputType +! ======================= +! ========= IceFloe_ContinuousStateType ======= + TYPE, PUBLIC :: IceFloe_ContinuousStateType + REAL(SiKi) :: DummyContStateVar !< None currently used [-] + END TYPE IceFloe_ContinuousStateType +! ======================= +! ========= IceFloe_DiscreteStateType ======= + TYPE, PUBLIC :: IceFloe_DiscreteStateType + REAL(SiKi) :: DummyDiscStateVar !< None currently used [-] + END TYPE IceFloe_DiscreteStateType +! ======================= +! ========= IceFloe_ConstraintStateType ======= + TYPE, PUBLIC :: IceFloe_ConstraintStateType + REAL(SiKi) :: DummyConstrStateVar !< None currently used [-] + END TYPE IceFloe_ConstraintStateType +! ======================= +! ========= IceFloe_OtherStateType ======= + TYPE, PUBLIC :: IceFloe_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE IceFloe_OtherStateType +! ======================= +! ========= IceFloe_MiscVarType ======= + TYPE, PUBLIC :: IceFloe_MiscVarType + INTEGER(IntKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE IceFloe_MiscVarType +! ======================= +! ========= IceFloe_ParameterType ======= + TYPE, PUBLIC :: IceFloe_ParameterType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: loadSeries !< - [precalculated time series of ice loads for each leg] + REAL(ReKi) :: iceVel !< ice floe velocity [m/s] + REAL(ReKi) :: iceDirection !< ice floe direction [degrees] + REAL(ReKi) :: minStrength !< minimum dynamic ice strength [Pa] + REAL(ReKi) :: minStrengthNegVel !< minimum dynamic ice strength for negative velocity [Pa] + REAL(ReKi) :: defaultArea !< structure width to use in cpld crushin [m] + REAL(ReKi) :: crushArea !< cross sectional area of ice against tower [m^2] + REAL(ReKi) :: coeffStressRate !< coefficient to calc stress rate from relative vellocity [Pa/m] + REAL(ReKi) :: C(4) !< coefficient of cubic transition curve for negative stress rates [-] + REAL(ReKi) :: dt !< time step [sec] + REAL(ReKi) :: rampTime !< load ramp up time [sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: legX !< - [x position of each leg relative to structure center] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: legY !< - [y position of each leg relative to structure center] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ks !< - [shelter factor due to upstream leg] + INTEGER(IntKi) :: numLegs !< Number of tower legs (=1 for monopile) [-] + INTEGER(IntKi) :: iceType !< Type of ice Floe: flex, crush, etc. [-] + INTEGER(IntKi) :: logUnitNum !< Unit number for log file [-] + LOGICAL :: singleLoad !< Flag for load application at single point vs multiple legs [-] + LOGICAL :: initFlag !< Flag for successful initialization [-] + END TYPE IceFloe_ParameterType +! ======================= +! ========= IceFloe_InputType ======= + TYPE, PUBLIC :: IceFloe_InputType + TYPE(MeshType) :: iceMesh !< Horizontal velocities on support structure leg(s) at water line [-] + END TYPE IceFloe_InputType +! ======================= +! ========= IceFloe_OutputType ======= + TYPE, PUBLIC :: IceFloe_OutputType + TYPE(MeshType) :: iceMesh !< Horizontal forces and torsional moment(s) on support structure leg(s) at water line [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE IceFloe_OutputType +! ======================= +CONTAINS + SUBROUTINE IceFloe_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(IceFloe_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 = 'IceFloe_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%simLength = SrcInitInputData%simLength + DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL + DstInitInputData%gravity = SrcInitInputData%gravity + DstInitInputData%RootName = SrcInitInputData%RootName + END SUBROUTINE IceFloe_CopyInitInput + + SUBROUTINE IceFloe_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(IceFloe_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyInitInput + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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%InputFile) ! InputFile + Re_BufSz = Re_BufSz + 1 ! simLength + Re_BufSz = Re_BufSz + 1 ! MSL2SWL + Re_BufSz = Re_BufSz + 1 ! gravity + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%simLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%gravity + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE IceFloe_PackInitInput + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%simLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MSL2SWL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE IceFloe_UnPackInitInput + + SUBROUTINE IceFloe_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(IceFloe_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 = 'IceFloe_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IceFloe_CopyInitOutput + + SUBROUTINE IceFloe_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(IceFloe_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE IceFloe_DestroyInitOutput + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 IceFloe_PackInitOutput + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 IceFloe_UnPackInitOutput + + SUBROUTINE IceFloe_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(IceFloe_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 = 'IceFloe_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContStateVar = SrcContStateData%DummyContStateVar + END SUBROUTINE IceFloe_CopyContState + + SUBROUTINE IceFloe_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(IceFloe_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyContState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! DummyContStateVar + 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%DummyContStateVar + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_PackContState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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%DummyContStateVar = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_UnPackContState + + SUBROUTINE IceFloe_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(IceFloe_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 = 'IceFloe_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscStateVar = SrcDiscStateData%DummyDiscStateVar + END SUBROUTINE IceFloe_CopyDiscState + + SUBROUTINE IceFloe_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(IceFloe_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyDiscState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! DummyDiscStateVar + 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%DummyDiscStateVar + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_PackDiscState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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%DummyDiscStateVar = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_UnPackDiscState + + SUBROUTINE IceFloe_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(IceFloe_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 = 'IceFloe_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrStateVar = SrcConstrStateData%DummyConstrStateVar + END SUBROUTINE IceFloe_CopyConstrState + + SUBROUTINE IceFloe_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(IceFloe_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyConstrState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! DummyConstrStateVar + 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%DummyConstrStateVar + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_PackConstrState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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%DummyConstrStateVar = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IceFloe_UnPackConstrState + + SUBROUTINE IceFloe_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(IceFloe_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 = 'IceFloe_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE IceFloe_CopyOtherState + + SUBROUTINE IceFloe_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(IceFloe_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyOtherState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 + Int_BufSz = Int_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 + + IntKiBuf(Int_Xferred) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_PackOtherState + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_UnPackOtherState + + SUBROUTINE IceFloe_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(IceFloe_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 = 'IceFloe_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE IceFloe_CopyMisc + + SUBROUTINE IceFloe_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(IceFloe_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE IceFloe_DestroyMisc + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! 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 + + IntKiBuf(Int_Xferred) = InData%DummyMiscVar + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_PackMisc + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_UnPackMisc + + SUBROUTINE IceFloe_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_ParameterType), INTENT(IN) :: SrcParamData + TYPE(IceFloe_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcParamData%loadSeries)) THEN + i1_l = LBOUND(SrcParamData%loadSeries,1) + i1_u = UBOUND(SrcParamData%loadSeries,1) + i2_l = LBOUND(SrcParamData%loadSeries,2) + i2_u = UBOUND(SrcParamData%loadSeries,2) + IF (.NOT. ALLOCATED(DstParamData%loadSeries)) THEN + ALLOCATE(DstParamData%loadSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%loadSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%loadSeries = SrcParamData%loadSeries +ENDIF + DstParamData%iceVel = SrcParamData%iceVel + DstParamData%iceDirection = SrcParamData%iceDirection + DstParamData%minStrength = SrcParamData%minStrength + DstParamData%minStrengthNegVel = SrcParamData%minStrengthNegVel + DstParamData%defaultArea = SrcParamData%defaultArea + DstParamData%crushArea = SrcParamData%crushArea + DstParamData%coeffStressRate = SrcParamData%coeffStressRate + DstParamData%C(4) = SrcParamData%C(4) + DstParamData%dt = SrcParamData%dt + DstParamData%rampTime = SrcParamData%rampTime +IF (ALLOCATED(SrcParamData%legX)) THEN + i1_l = LBOUND(SrcParamData%legX,1) + i1_u = UBOUND(SrcParamData%legX,1) + IF (.NOT. ALLOCATED(DstParamData%legX)) THEN + ALLOCATE(DstParamData%legX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%legX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%legX = SrcParamData%legX +ENDIF +IF (ALLOCATED(SrcParamData%legY)) THEN + i1_l = LBOUND(SrcParamData%legY,1) + i1_u = UBOUND(SrcParamData%legY,1) + IF (.NOT. ALLOCATED(DstParamData%legY)) THEN + ALLOCATE(DstParamData%legY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%legY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%legY = SrcParamData%legY +ENDIF +IF (ALLOCATED(SrcParamData%ks)) THEN + i1_l = LBOUND(SrcParamData%ks,1) + i1_u = UBOUND(SrcParamData%ks,1) + IF (.NOT. ALLOCATED(DstParamData%ks)) THEN + ALLOCATE(DstParamData%ks(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ks.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ks = SrcParamData%ks +ENDIF + DstParamData%numLegs = SrcParamData%numLegs + DstParamData%iceType = SrcParamData%iceType + DstParamData%logUnitNum = SrcParamData%logUnitNum + DstParamData%singleLoad = SrcParamData%singleLoad + DstParamData%initFlag = SrcParamData%initFlag + END SUBROUTINE IceFloe_CopyParam + + SUBROUTINE IceFloe_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(IceFloe_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%loadSeries)) THEN + DEALLOCATE(ParamData%loadSeries) +ENDIF +IF (ALLOCATED(ParamData%legX)) THEN + DEALLOCATE(ParamData%legX) +ENDIF +IF (ALLOCATED(ParamData%legY)) THEN + DEALLOCATE(ParamData%legY) +ENDIF +IF (ALLOCATED(ParamData%ks)) THEN + DEALLOCATE(ParamData%ks) +ENDIF + END SUBROUTINE IceFloe_DestroyParam + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! loadSeries allocated yes/no + IF ( ALLOCATED(InData%loadSeries) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! loadSeries upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%loadSeries) ! loadSeries + END IF + Re_BufSz = Re_BufSz + 1 ! iceVel + Re_BufSz = Re_BufSz + 1 ! iceDirection + Re_BufSz = Re_BufSz + 1 ! minStrength + Re_BufSz = Re_BufSz + 1 ! minStrengthNegVel + Re_BufSz = Re_BufSz + 1 ! defaultArea + Re_BufSz = Re_BufSz + 1 ! crushArea + Re_BufSz = Re_BufSz + 1 ! coeffStressRate + Re_BufSz = Re_BufSz + 1 ! C(4) + Re_BufSz = Re_BufSz + 1 ! dt + Re_BufSz = Re_BufSz + 1 ! rampTime + Int_BufSz = Int_BufSz + 1 ! legX allocated yes/no + IF ( ALLOCATED(InData%legX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! legX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%legX) ! legX + END IF + Int_BufSz = Int_BufSz + 1 ! legY allocated yes/no + IF ( ALLOCATED(InData%legY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! legY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%legY) ! legY + END IF + Int_BufSz = Int_BufSz + 1 ! ks allocated yes/no + IF ( ALLOCATED(InData%ks) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ks upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ks) ! ks + END IF + Int_BufSz = Int_BufSz + 1 ! numLegs + Int_BufSz = Int_BufSz + 1 ! iceType + Int_BufSz = Int_BufSz + 1 ! logUnitNum + Int_BufSz = Int_BufSz + 1 ! singleLoad + Int_BufSz = Int_BufSz + 1 ! initFlag + 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%loadSeries) ) 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%loadSeries,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%loadSeries,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%loadSeries,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%loadSeries,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%loadSeries,2), UBOUND(InData%loadSeries,2) + DO i1 = LBOUND(InData%loadSeries,1), UBOUND(InData%loadSeries,1) + ReKiBuf(Re_Xferred) = InData%loadSeries(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%iceVel + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%iceDirection + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%minStrength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%minStrengthNegVel + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%defaultArea + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%crushArea + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%coeffStressRate + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C(4) + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rampTime + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%legX) ) 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%legX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%legX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%legX,1), UBOUND(InData%legX,1) + ReKiBuf(Re_Xferred) = InData%legX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%legY) ) 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%legY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%legY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%legY,1), UBOUND(InData%legY,1) + ReKiBuf(Re_Xferred) = InData%legY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ks) ) 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%ks,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ks,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ks,1), UBOUND(InData%ks,1) + ReKiBuf(Re_Xferred) = InData%ks(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%numLegs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%iceType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%logUnitNum + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%singleLoad, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%initFlag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_PackParam + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 ! loadSeries 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%loadSeries)) DEALLOCATE(OutData%loadSeries) + ALLOCATE(OutData%loadSeries(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%loadSeries.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%loadSeries,2), UBOUND(OutData%loadSeries,2) + DO i1 = LBOUND(OutData%loadSeries,1), UBOUND(OutData%loadSeries,1) + OutData%loadSeries(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%iceVel = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%iceDirection = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%minStrength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%minStrengthNegVel = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%defaultArea = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%crushArea = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%coeffStressRate = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C(4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rampTime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! legX 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%legX)) DEALLOCATE(OutData%legX) + ALLOCATE(OutData%legX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%legX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%legX,1), UBOUND(OutData%legX,1) + OutData%legX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! legY 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%legY)) DEALLOCATE(OutData%legY) + ALLOCATE(OutData%legY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%legY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%legY,1), UBOUND(OutData%legY,1) + OutData%legY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ks 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%ks)) DEALLOCATE(OutData%ks) + ALLOCATE(OutData%ks(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ks.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ks,1), UBOUND(OutData%ks,1) + OutData%ks(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%numLegs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%iceType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%logUnitNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%singleLoad = TRANSFER(IntKiBuf(Int_Xferred), OutData%singleLoad) + Int_Xferred = Int_Xferred + 1 + OutData%initFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%initFlag) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IceFloe_UnPackParam + + SUBROUTINE IceFloe_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_InputType), INTENT(INOUT) :: SrcInputData + TYPE(IceFloe_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%iceMesh, DstInputData%iceMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IceFloe_CopyInput + + SUBROUTINE IceFloe_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(IceFloe_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%iceMesh, ErrStat, ErrMsg ) + END SUBROUTINE IceFloe_DestroyInput + + SUBROUTINE IceFloe_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(IceFloe_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 = 'IceFloe_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! iceMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! iceMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! iceMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! iceMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! iceMesh + 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 MeshPack( InData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! iceMesh + 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 IceFloe_PackInput + + SUBROUTINE IceFloe_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(IceFloe_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_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 + 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 MeshUnpack( OutData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! iceMesh + 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 IceFloe_UnPackInput + + SUBROUTINE IceFloe_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(IceFloe_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'IceFloe_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%iceMesh, DstOutputData%iceMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE IceFloe_CopyOutput + + SUBROUTINE IceFloe_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(IceFloe_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%iceMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE IceFloe_DestroyOutput + + SUBROUTINE IceFloe_PackOutput( 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(IceFloe_OutputType), 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 = 'IceFloe_PackOutput' + ! 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 ! iceMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! iceMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! iceMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! iceMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! iceMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! iceMesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE IceFloe_PackOutput + + SUBROUTINE IceFloe_UnPackOutput( 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(IceFloe_OutputType), 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 = 'IceFloe_UnPackOutput' + ! 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 MeshUnpack( OutData%iceMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! iceMesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE IceFloe_UnPackOutput + + + SUBROUTINE IceFloe_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(IceFloe_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(IceFloe_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL IceFloe_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL IceFloe_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL IceFloe_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE IceFloe_Input_ExtrapInterp + + + SUBROUTINE IceFloe_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(IceFloe_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(IceFloe_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(IceFloe_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%iceMesh, u2%iceMesh, tin, u_out%iceMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE IceFloe_Input_ExtrapInterp1 + + + SUBROUTINE IceFloe_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(IceFloe_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(IceFloe_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(IceFloe_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(IceFloe_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%iceMesh, u2%iceMesh, u3%iceMesh, tin, u_out%iceMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE IceFloe_Input_ExtrapInterp2 + + + SUBROUTINE IceFloe_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL IceFloe_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL IceFloe_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL IceFloe_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE IceFloe_Output_ExtrapInterp + + + SUBROUTINE IceFloe_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%iceMesh, y2%iceMesh, tin, y_out%iceMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE IceFloe_Output_ExtrapInterp1 + + + SUBROUTINE IceFloe_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'IceFloe_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%iceMesh, y2%iceMesh, y3%iceMesh, tin, y_out%iceMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE IceFloe_Output_ExtrapInterp2 + +END MODULE IceFloe_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types_notFAST.f90 b/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types_notFAST.f90 new file mode 100644 index 000000000..558676b2e --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/IceFloe_Types_notFAST.f90 @@ -0,0 +1,36 @@ +!********************************************************************************************************************************* +MODULE IceFloe_Types +! this is a simplified version for use with IceFloe with codes other than FAST +!--------------------------------------------------------------------------------------------------------------------------------- +use precision +IMPLICIT NONE +! ========= IceFloe_ParameterType ======= + TYPE, PUBLIC :: IceFloe_ParameterType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: loadSeries ! - [precalculated time series of ice loads for each leg] + REAL(ReKi) :: iceVel ! ice floe velocity [m/s] + REAL(ReKi) :: iceDirection ! ice floe direction [degrees] + REAL(ReKi) :: minStrength ! minimum dynamic ice strength [Pa] + REAL(ReKi) :: minStrengthNegVel ! minimum dynamic ice strength for negative velocity [Pa] + REAL(ReKi) :: defaultArea ! width to use for coupled crushing + REAL(ReKi) :: crushArea ! cross sectional area of ice against tower [m^2] + REAL(ReKi) :: coeffStressRate ! coefficient to calc stress rate from relative vellocity [Pa/m] + REAL(ReKi) :: C(4) ! coefficient of cubic transition curve for negative stress rates [-] + REAL(ReKi) :: dt ! time step [sec] + REAL(ReKi) :: rampTime ! ramp time for forces at beginning of simulation [sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: legX ! - [x position of each leg relative to structure center] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: legY ! - [y position of each leg relative to structure center] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ks ! - [shelter factor due to upstream leg] + INTEGER(IntKi) :: numLegs ! Number of tower legs (=1 for monopile) [-] + INTEGER(IntKi) :: iceType ! Type of ice Floe: flex, crush, etc. [-] + INTEGER(IntKi) :: logUnitNum ! Unit number for log file [-] + LOGICAL :: singleLoad ! Flag for load application at single point vs multiple legs [-] + LOGICAL :: initFlag ! Flag for successful initialization [-] + END TYPE IceFloe_ParameterType +! ======================= + +! Some constants that would otherwise come from NREL code base + real(ReKi), parameter :: Pi = 3.141592654_ReKi + real(ReKi), parameter :: D2R = Pi/180.0_ReKi + real(ReKi), parameter :: R2D = 180.0_ReKi/Pi + +END MODULE IceFloe_Types diff --git a/OpenFAST/modules/icefloe/src/icefloe/coupledCrushing.F90 b/OpenFAST/modules/icefloe/src/icefloe/coupledCrushing.F90 new file mode 100644 index 000000000..22eee68fe --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/coupledCrushing.F90 @@ -0,0 +1,139 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 for calculations of loads induced by ice crushing against vertical surfaces +! Using a coupled model from Maattanen, M. (1998) "Numerical Model for Ice Induced +! vibration load lock-in and Synchronization". Proceedings of the 14th Int. Symp. +! on Ice, Potsdam, NY USA, vol 2, pp 923-930. + +module iceCpldCrushing + + use iceFloeBase + + implicit none + + public + +! local maximum and minima of stress rate to strength curve (fixed since curve is hard coded) + real(ReKi), parameter :: stressRateAtMax = 0.2914592 + real(ReKi), parameter :: stressRateAtMin = 1.3287178 + real(ReKi), parameter :: strengthAtMin = 2.00 + stressRateAtMin*(7.80 + & + stressRateAtMin*(-18.57 + stressRateAtMin*(13.00 - stressRateAtMin*2.91))) + +contains + +! calculate the time series of ice loads using the ISO method + subroutine initCpldCrushing (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput ! Input parameters read from file + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + + real(ReKi) :: defaultWidth +! integer(IntKi) :: err + +! initialize the common parmeters + call initIceFloe(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting coupled ice crushing input parameters ') + + call getIceInput(iceInput, 'refIceStrength', inParams%refIceStrength, iceLog, 0.5E6_ReKi, 5.0E6_ReKi) + call logMessage(iceLog, ' Reference ice strength = '//TRIM(Num2LStr(inParams%refIceStrength))//' Pascals') + + call getIceInput(iceInput, 'minStrength', inParams%minStrength, iceLog, 0.0_ReKi, 1.0E9_ReKi) + call logMessage(iceLog, ' Minimum ice strength from stress rate polynomial = '// & + TRIM(Num2LStr(inParams%minStrength))//' Pascals') + + call getIceInput(iceInput, 'minStrengthNegVel', inParams%minStrengthNegVel, iceLog, 0.0_ReKi, 1.0E9_ReKi) + call logMessage(iceLog, ' Minimum negative velocity ice strength = '// & + TRIM(Num2LStr(inParams%minStrengthNegVel))//' Pascals') + +! Assign some input parameters to saved parameters + myIceParams%iceVel = inParams%iceVelocity + myIceParams%minStrength = inParams%minStrength + myIceParams%minStrengthNegVel = inParams%minStrengthNegVel + +! Precalc some things. + defaultWidth = inParams%twr%diam + if (inParams%twr%diam > 2*inParams%iceThickness) then + call logMessage(iceLog, '*** Tower diameter > 2*ice thickness; width for cpld crushing strength '// & + 'set to latter value. ***') + defaultWidth = 2*inParams%iceThickness + endif + myIceParams%defaultArea = sqrt(1.0/(defaultWidth*inParams%iceThickness)) + +! This is for force from strength, uses actual tower diameter + myIceParams%crushArea = inParams%twr%diam*inParams%iceThickness +! Scale to MPa + myIceParams%coeffStressRate = 8.0E-6*inParams%refIceStrength/PI/defaultWidth + + end subroutine initCpldCrushing + +!**************************************************************************** + function outputCpldCrushLoad (myIceParams, iceLog, inVels, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(ReKi), intent(in) :: inVels(2,myIceParams%numLegs) + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + real(ReKi) :: twrVelAngle ! Angle of tower motion vector + ro x-axis towards y-axis + real(ReKi) :: velProjected ! Velocity component projected onto direction of ice movement + real(ReKi) :: stressRate ! MPa/sec + real(ReKi) :: strength ! Instantaneous ice strength, Pascals + integer(IntKi) :: nL ! loop index for number of legs + + do nL = 1, myIceParams%numLegs + ! get tower velocity in direction of ice floe flow + twrVelAngle = atan2(inVels(2,nL),inVels(1,nL)) + velProjected = sqrt(inVels(1,nL)**2 + inVels(2,nL)**2)*cos(twrVelAngle - myIceParams%iceDirection) + stressRate = (myIceParams%iceVel - velProjected)*myIceParams%coeffStressRate + + ! This polynomial is specific to the Maattanen method and is thus hard coded + ! Only applicable from a stress rate of slightly below zero to +1.3287MPa/sec + ! In this range the failure mode is ductile crushing + strength = 2.00 + stressRate*(7.80 + stressRate*(-18.57 + stressRate*(13.00 - stressRate*2.91))) + strength = 1.0E6*strength*myIceParams%defaultArea + if (stressRate <= stressRateAtMax) then + ! The ice strength is limited to a user specified minimum for negative stress rate (tower moving away from ice forming a gap) + strength = max(strength, myIceParams%minStrengthNegVel) + else + ! For high positive relative velocities (high stress rate) the ice failure mode is brittle and constant + ! The ice strength is limited to the minimum point of the strength vs stress rate curve + if (stressRate > stressRateAtMin) then + strength = 1.0E6*strengthAtMin*myIceParams%defaultArea + endif + ! Unless the user has specified something even higher for the minimum strength + strength = max(strength, myIceParams%minStrength) + endif + + ! apply the load in the proper direction via x,y components + iceLoads(:,nL) = myIceParams%ks(nL)*iceLoadDirection(strength*myIceParams%crushArea, myIceParams) + enddo + + ! If the loads from multiple legs are applied as an "effective" load on one leg at the + ! support center, then compute that effective load vector and put into the first load vector + ! Note that only Fx, Fy, and Mz terms re-calculated. All others remain zero + if (myIceParams%numLegs > 1 .and. myIceParams%singleLoad) & + iceLoads(:,1) = iceLoadEquivalent(iceLoads, myIceParams) + + end function outputCpldCrushLoad + +end module iceCpldCrushing diff --git a/OpenFAST/modules/icefloe/src/icefloe/crushingIEC.F90 b/OpenFAST/modules/icefloe/src/icefloe/crushingIEC.F90 new file mode 100644 index 000000000..933e64b1e --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/crushingIEC.F90 @@ -0,0 +1,116 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 for calculations of loads induced by ice crushing against vertical surfaces +! As suggested in IEC 61400-3, Ed 1 Annex E +! This is effectively a lock in condition where the ice loads are +! sinusoidal at the specified structural frequency +! +module iceCrushingIEC + + use IceFloeBase + + implicit none + + public + +contains + +! calculate the time series of ice loads for continuous crushing +!**************************************************************** + subroutine initCrushingIEC (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput ! Parameter read from input file for initialization + type(iceFloe_ParameterType), intent(inout) :: myIceParams ! saved parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + +! local variables + real(ReKi) :: maxLoad ! Maximum static ice load, Newtons + integer(IntKi) :: nL !err, + +! initialize the common parmeters + call initIceFloe(iceInput, inParams, myIceParams, iceLog) + +! initialize the parmeters for flexural ice failure via IEC + call logMessage(iceLog, newLine//' Setting parameters for crushing on vertical surfaces by IEC/Korzhavin method') + + call getIceInput(iceInput, 'refIceStrength', inParams%refIceStrength, iceLog, 0.5E6_ReKi, 5.0E6_ReKi) + call logMessage(iceLog, ' Reference ice strength = '//TRIM(Num2LStr(inParams%refIceStrength))//' Pascals') + + call getIceInput(iceInput, 'shapeFactor_k1', inParams%shapeFactor_k1, iceLog, 0.1_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Static load shape factor = '//TRIM(Num2LStr(inParams%shapeFactor_k1))) + + call getIceInput(iceInput, 'contactFactor_k2', inParams%contactFactor_k2, iceLog, 0.1_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Static load contact factor = '//TRIM(Num2LStr(inParams%contactFactor_k2))) + + call getIceInput(iceInput, 'towerFrequency', inParams%twr%freq, iceLog, 0.01_ReKi, 10.0_ReKi) + call logMessage(iceLog, ' Tower fundamental frequency = '//TRIM(Num2LStr(inParams%twr%freq))//' Hz') + + ! get leg load phase + if (myIceParams%numLegs>1) then + do nL = 1, myIceParams%numLegs + call getIceInput(iceInput, 'loadPhase'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%phase, iceLog, 0.0_ReKi, 360.0_ReKi) + call logMessage(iceLog, ' Load phase for leg '//TRIM(Num2LStr(nL))//' is ' & + //TRIM(Num2LStr(inParams%twr%leg(nL)%phase))//' degrees') + inParams%twr%leg(nL)%phase = D2R*inParams%twr%leg(nL)%phase + enddo + call getIceInput(iceInput, 'multiLegFactor_kn', inParams%multiLegFactor_kn, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Multi leg factor = '//TRIM(Num2LStr(inParams%multiLegFactor_kn))) + else + inParams%twr%leg(1)%phase = 0.0 + inParams%multiLegFactor_kn = 1.0 + endif + + maxLoad = inParams%multiLegFactor_kn*globalCrushLoadIEC(inParams) + call logMessage(iceLog, '** Global crushing load is: '//TRIM(Num2LStr(maxLoad))//' Newtons.' ) + +! Precalculates a time series of loads based on: +! Sinusoidal per IEC + call IECLoadTimeSeries(myIceParams, inParams, iceLog, maxLoad, inParams%twr%freq) + + end subroutine initCrushingIEC + +!**************************************************************************** +! Per IEC 61400-3 Design Requirements for Offshore Wind Turbines Ed 1, 2009 +! via the Korshavin equation + function globalCrushLoadIEC(inParams) result(load) + type(inputParams), intent(in) :: inParams ! specific input parameter variable list + real(ReKi) :: load + real(ReKi) :: aspectRatio_k3 ! Per IEC + + aspectRatio_k3 = sqrt(1.0+5.0*inParams%iceThickness/inParams%twr%diam) + load = inParams%shapeFactor_k1*inParams%contactFactor_k2*aspectRatio_k3 + load = load*inParams%iceThickness*inParams%twr%diam*inParams%refIceStrength + + end function globalCrushLoadIEC + +!**************************************************************************** +! Continuous crushing uses the standard inerpolation routine +! of the precalculated time series + function outputCrushLoadIEC (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputIceLoads (myIceParams, iceLog, time) + end function outputCrushLoadIEC + +end module iceCrushingIEC \ No newline at end of file diff --git a/OpenFAST/modules/icefloe/src/icefloe/crushingISO.F90 b/OpenFAST/modules/icefloe/src/icefloe/crushingISO.F90 new file mode 100644 index 000000000..f8ffa6dc6 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/crushingISO.F90 @@ -0,0 +1,165 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 for common calculations of loads induced by ice crushing against vertical surfaces +! Using the method in ISO 19906:2010, section A.8.2.4.3.3 +! +module iceCrushingISO + + use iceFloeBase + + implicit none + + public + +contains + +! calculate the time series of ice loads using the ISO method + subroutine initIceCrushISO (iceInput, inParams, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + + type(inputParams), intent(out) :: inParams ! specific input parameter variable list + +! initialize the common parmeters + call initIceFloe(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting common ice crushing input parameters ') + + call getIceInput(iceInput, 'refIceStrength', inParams%refIceStrength, iceLog, 0.1E6_ReKi, 50.0E6_ReKi) + call logMessage(iceLog, ' Reference ice strength = '//TRIM(Num2LStr(inParams%refIceStrength))//' Pascals') + + call getIceInput(iceInput, 'refIceThick', inParams%refIceThick, iceLog, 1.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Reference ice thickness = '//TRIM(Num2LStr(inParams%refIceThick))//' meters ') + + call getIceInput(iceInput, 'staticExponent', inParams%staticExponent, iceLog, -0.16_ReKi, -0.16_ReKi) + call logMessage(iceLog, ' Exponent for static load = '//TRIM(Num2LStr(inParams%staticExponent))) + + end subroutine initIceCrushISO + + +!================================================================== +! Based on ISO 19906, 2010 + function globalCrushLoadISO(inParams) result(load) + type(inputParams), intent(in) :: inParams ! specific input parameter variable list + real(ReKi) :: load ! Newtons + real(ReKi) :: exp_n ! per ISO + + exp_n = min(-0.3_ReKi, 0.2_ReKi*inParams%iceThickness-0.5_ReKi) + + load = inParams%twr%diam*inParams%iceThickness*inParams%refIceStrength + load = load*(inParams%iceThickness/inParams%refIceThick)**exp_n + load = load*(inParams%twr%diam/inParams%iceThickness)**inParams%staticExponent + + end function globalCrushLoadISO + +!============================================================================================ +! Calculate a sawtooth waveform with fixed period, rise, and fall times +! Used by intermittent crushing and lock-in models + subroutine crushLoadTimeSeriesISO (myIceParams, inParams, iceLog, peakLoad, minLoad, period, riseTime, fallTime) + + type(inputParams), intent(in) :: inParams ! specific input parameter variable list + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(ReKi), intent(in) :: peakLoad ! Global maximum load, Newtons + real(ReKi), intent(in) :: minLoad ! Lower limit of dynamic load, Newtons + real(ReKi), intent(in) :: period ! Loading/unloading cycle period, seconds + real(ReKi), intent(in) :: riseTime ! fraction of period for which load is rising + real(ReKi), intent(in) :: fallTime ! fraction of period for which load is falling + +! integer(IntKi) :: err ! error status from memory allocation + integer(IntKi) :: n, ns, nL, nSteps, nRiseSteps, nFallSteps, minLoadSteps ! various counters + integer(IntKi) :: nStart ! where to start in the phase of rising/falling/min load period + +! Number of steps in time series of loads + nSteps = size(myIceParams%loadSeries,1) + +! Loop on all of the legs + do nL = 1, myIceParams%numLegs + n = 1 + nRiseSteps = nint(riseTime * period / myIceParams%dt) + nFallSteps = nint( fallTime * period / myIceParams%dt) + minLoadSteps = nint( period / myIceParams%dt) - nRiseSteps - nFallSteps + if (nRiseSteps == 0 .or. nFallSteps == 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Time step too large or period too short in CrushxLoadTimeSeriesISO', 1) + return + endif + + nStart = nint(period*inParams%twr%leg(nL)%phase/2.0/pi/myIceParams%dt) ! where to start in period + + seriesLoop: do while (n < nSteps+1) + ! begin to increase the load from the minimum to the peak + ! based on phase we may not start on a rise i.e. nStart > nRiseSteps + do ns = nStart, nRiseSteps + myIceParams%loadSeries(n,nL) = minLoad + (peakLoad-minLoad)*float(ns)/float(nRiseSteps) + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + + ! If, dependent on phase, we started during the rise then we don't deal with it any more + if (nStart <= nRiseSteps) then + nStart = 1 + else + nStart = nStart - nRiseSteps + endif + + ! begin to decrease the load from the peak down to the minimum + do ns = nStart, nFallSteps + myIceParams%loadSeries(n,nL) = peakLoad - (peakLoad-minLoad)*float(ns-1)/float(nFallSteps) + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + + ! If, dependent on phase, we started during the fall then we don't deal with it any more + if (nStart <= nRiseSteps+nFallSteps) then + nStart = 1 + else + nStart = nStart - nRiseSteps - nFallSteps + endif + + ! Fill the remaining time steps in the period with the minimum load + do ns = nStart, minLoadSteps + myIceParams%loadSeries(n,nL) = minLoad + n = n + 1 + if (n > nSteps) exit seriesLoop + enddo + nStart = 1 + + enddo seriesLoop + + ! Apply shelter factor to individual legs + myIceParams%loadSeries(:,nL) = myIceParams%ks(nL)*myIceParams%loadSeries(:,nL) + + enddo ! end of leg loop + + end subroutine crushLoadTimeSeriesISO + +!**************************************************************************** + function outputCrushLoadISO (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputIceLoads (myIceParams, iceLog, time) + end function outputCrushLoadISO + +end module iceCrushingISO diff --git a/OpenFAST/modules/icefloe/src/icefloe/iceInput.f90 b/OpenFAST/modules/icefloe/src/icefloe/iceInput.f90 new file mode 100644 index 000000000..8e061eda1 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/iceInput.f90 @@ -0,0 +1,352 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 to handle parameter input from user's file + +module iceInputParams + + use , INTRINSIC :: iso_fortran_env , only : iostat_end ! for end of file detection + use precision + use NWTC_IO, only : GetNewUnit, OpenFInpFile + use iceLog + + implicit none + +! This is used for initial read in of variables by name +! Extraction of values into specific named variables done by getIceInput functions + type paramType + character(132) :: name + real(ReKi) :: value + end type paramType + +! Hold some meta data for the input parameters + type iceInputType + integer(IntKi) :: unitNum + integer(IntKi) :: count + type(paramType), allocatable :: params(:) + end type iceInputType + +! generic functions for retrieving input parameters + interface getIceInput + module procedure getRealInput + module procedure getIntInput + module procedure getLogicalInput + end interface getIceInput + +! data structures for tower - much of this could come from FAST/ElastoDyn/SubDyn +! but need for other codes + type twrLegs + real(ReKi) :: X + real(ReKi) :: Y + real(ReKi) :: phase + real(ReKi) :: ks + end type twrLegs + type towerData + real(ReKi) :: diam ! at water line - this could come from FAST but not other codes + type(twrLegs), allocatable :: leg(:) + real(ReKi) :: freq ! leg or tower fundamental frequency, Hz + real(ReKi) :: coneAngle ! for flexural failure + real(ReKi) :: coneTopDiam ! for flexural failure + end type towerData + +! This is the list of input parameters + type inputParams + integer(IntKi) :: iceType + real(ReKi) :: iceThickness + real(ReKi) :: iceVelocity + real(ReKi) :: iceDirection + real(ReKi) :: timeStep + real(ReKi) :: rampTime + integer(IntKi) :: randomSeed + + type(towerData):: twr + real(ReKi) :: multiLegFactor_kn ! Applied to peak load lock-in for all legs when numLegs>1 + logical :: singleLoad ! true if multiple leg loads will be combined into an equivalent load + logical :: legAutoFactor ! code decides on leg load shelter factors if true + + real(ReKi) :: refIceThick + real(ReKi) :: refIceStrength + real(ReKi) :: staticExponent + + real(ReKi) :: shapeFactor_k1 + real(ReKi) :: contactFactor_k2 + + real(ReKi) :: coeffPSD_b + real(ReKi) :: coeffPSD_ks + real(ReKi) :: crushLoadCOV + real(ReKi) :: stdLoadMult + real(ReKi) :: freqStep + + real(ReKi) :: interPeriod + real(ReKi) :: riseTime + real(ReKi) :: fallTime + + real(ReKi) :: minLoadFraction + + real(ReKi) :: flexStrength + real(ReKi) :: ice2twrFriction + real(ReKi) :: iceDensity + logical :: includeHb + logical :: includeHr + + real(ReKi) :: peakLoadCOV + real(ReKi) :: coeffLoadPeaks + real(ReKi) :: coeffLoadMin + real(ReKi) :: periodCOV + real(ReKi) :: tauMin + real(ReKi) :: tauMax + real(ReKi) :: coeffBreakLength + real(ReKi) :: rubbleHeight + real(ReKi) :: rubblePorosity + real(ReKi) :: rubbleCohesion + real(ReKi) :: rubbleAngle + real(ReKi) :: frictionAngle + real(ReKi) :: ice2iceFriction + real(ReKi) :: waterDensity + real(ReKi) :: iceModulus + real(ReKi) :: poissonRatio + logical :: includeHp + logical :: includeHl + logical :: includeHt + logical :: includeLc + + real(ReKi) :: rideUpThickness + real(ReKi) :: freqParamK + + real(ReKi) :: minStrength + real(ReKi) :: minStrengthNegVel + end type inputParams + +contains + +!======================================================================== + subroutine countIceInputs (fname, iceLog, input) + character(*), intent(in) :: fname ! name of file with input parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(iceInputType), intent(out) :: input + + character(1024) :: lineIn + INTEGER(IntKi) :: ErrStat ! Error status of the operation + CHARACTER(msgLen) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer(IntKi) :: ioStatus + + call GetNewUnit ( input%UnitNum, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) then + call iceErrorHndlr (iceLog, ErrStat, 'CountIceInputs => GetNewUnit: '//newLine//ErrMsg, 1) + return + endif + + call OpenFInpFile ( input%UnitNum, trim(fname), ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) then + call iceErrorHndlr (iceLog, ErrStat, 'CountIceInputs => OpenFInpFile: '//newLine//ErrMsg, 1) + return + endif + + input%count = 0 + readLoop: do while (.true.) + read(input%UnitNum,'(A)',iostat=ioStatus) lineIn + if (ioStatus == iostat_end) exit readLoop + if(lineIn(1:1) == '!' .or. & ! check for a comment + lineIn(1:1) == '#' .or. & + lineIn(1:1) == '$' .or. & + lineIn(1:1) == '%' ) then + cycle readLoop + else + input%count = input%count + 1 + endif + enddo readLoop + + allocate(input%params(input%count), stat=errStat) + if (errStat /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in input parameter array allocation in CountIceInputs', 1) + return ! error in array allocation + endif + +! Go back to the beginning of the file + rewind (unit=input%UnitNum, iostat = ErrStat) + if (ErrStat /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'CountIceInputs => OpenFInpFile: '//newLine// & + ' Error rewinding parameter input file', 1) + return + endif + + end subroutine countIceInputs + +!======================================================================== + subroutine readIceInputs (iceLog, input) + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(iceInputType), intent(inout) :: input + + character(1024) :: lineIn + character(132) :: varName + real(ReKi) :: varValue + integer(IntKi) :: ioStatus, nCount, n + INTEGER(IntKi) :: ErrStat ! Error status of the operation + CHARACTER(msgLen) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + +! read all of the records and put into the proper variable + nCount = 0 + readLoop: do while (nCount < input%count) + read(input%UnitNum,'(A)',iostat=ioStatus) lineIn + if (ioStatus == iostat_end) exit readLoop + if(lineIn(1:1) == '!' .or. & ! check for a comment + lineIn(1:1) == '$' .or. & + lineIn(1:1) == '%' ) cycle readLoop + +! read in the variable name and its value, convert name to upper case + read(lineIn,*) varName, varValue + call Conv2UC (varName) + nCount = nCount + 1 + input%params(nCount)%name = varName + input%params(nCount)%value = varValue + +! loop through the list of possible input variables check for duplication + searchLoop: do n = 1, nCount-1 + if(index(varname, input%params(n)%name) > 0) then + call iceErrorHndlr (iceLog, ErrID_Warn, 'Input parameter '//trim(varName)// & + ' has been specified twice.', 0) + exit searchLoop + endif + enddo searchloop + enddo readLoop + + close (input%UnitNum) + + end subroutine readIceInputs + +!======================================================================== +! extract the input parameter value from the list +! and send back to calling routine + subroutine getRealInput (input, varName, outVal, iceLog, min, max) + type(iceInputType), intent(in) :: input + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + character(*), intent(in) :: varName ! This is the variable requested + real(ReKi), intent(out) :: outVal + real(ReKi), intent(in), optional :: min, max + + integer(IntKi) :: n + character(len_trim(varName)) :: tmpName + logical :: foundParam + + tmpName = varName ! can't change varName since it's an intent(in) + call Conv2UC (tmpName) + + foundParam = .false. + do n = 1, input%count + if(index(input%params(n)%name, tmpName) > 0) then + outVal = input%params(n)%value + foundParam = .true. + exit + endif + enddo + + if (.not. foundParam) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Input parameter '//varName//' was not in the parameter input file.', 1 ) + return + endif + +! If requeseted, check that the value is withing reasonable bounds + if (present(min)) then + if (outVal < min) then + call iceErrorHndlr (iceLog, ErrID_Warn, 'Input parameter '//varName//' is below the minimum bound', 0 ) + endif + endif + if (present(max)) then + if (outVal > max) then + call iceErrorHndlr (iceLog, ErrID_Warn, 'Input parameter '//varName//' is above the maximum bound', 0 ) + endif + endif + + end subroutine getRealInput + +!------------------------------------------------------------------ + subroutine getIntInput (input, varName, outVal, iceLog, min, max) + type(iceInputType), intent(in) :: input + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + character(*), intent(in) :: varName ! This is the variable requested + integer(IntKi), intent(out) :: outVal + integer(IntKi), intent(in), optional :: min, max + + integer(IntKi) :: n + character(len_trim(varName)) :: tmpInName + logical :: foundParam + + tmpInName = varName ! can't use varname since Conv2UC changes it + call Conv2UC (tmpInName) + + foundParam = .false. + do n = 1, input%count + if(index(input%params(n)%name, tmpInName) > 0) then + outVal = input%params(n)%value + foundParam = .true. + exit + endif + enddo + + if (.not. foundParam) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Input parameter '//varName//' was not in the parameter input file.', 1 ) + return + endif + +! If requeseted, check that the value is withing reasonable bounds + if (present(min)) then + if (outVal < min) then + call iceErrorHndlr (iceLog, ErrID_Warn, 'Input parameter '//varName//' is below the minimum bound', 0 ) + endif + endif + if (present(max)) then + if (outVal > max) then + call iceErrorHndlr (iceLog, ErrID_Warn, 'Input parameter '//varName//' is above the maximum bound', 0 ) + endif + endif + + end subroutine getIntInput + +!------------------------------------------------------------------ + subroutine getLogicalInput (input, varName, outVal, iceLog) + type(iceInputType), intent(in) :: input + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + character(*), intent(in) :: varName ! This is the variable requested + logical, intent(out) :: outVal + character(len_trim(varName)) :: tmpName + integer(IntKi) :: n + logical :: foundParam + + tmpName = varName + call Conv2UC (tmpName) + + foundParam = .false. + do n = 1, input%count + if(index(input%params(n)%name, tmpName) > 0) then + !outVal = input%params(n)%value ! warning #6192: Fortran 2003 does not allow this data type conversion. <- real to logical + outVal = ( NINT(input%params(n)%value) /= 0 ) !Intel: The numeric value of .TRUE. and .FALSE. can be -1 and 0 or 1 and 0 depending on compiler option fpscomp + foundParam = .true. + exit + endif + enddo + + if (.not. foundParam) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Input parameter '//varName//' was not in the parameter input file.', 1 ) + return + endif + end subroutine getLogicalInput + +end module iceInputParams diff --git a/OpenFAST/modules/icefloe/src/icefloe/iceLog.F90 b/OpenFAST/modules/icefloe/src/icefloe/iceLog.F90 new file mode 100644 index 000000000..4e82ae1c6 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/iceLog.F90 @@ -0,0 +1,155 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!****************************************************************************************** +! routines for logging progress and errors in the ice +! loading code + +module iceLog + + use NWTC_Base + use NWTC_IO, only : GetNewUnit, OpenFOutFile, conv2uc, progwarn, progabort, NewLine + + implicit none + + public + + integer(IntKi), parameter :: msgLen = 1024 + +! Data structure for message logging and error handling + type iceFloe_LoggingType + ! These are the status codes and error message that will be sent back to the glue code. + ! They are not static and should be reset for every call to IceFloe_init, _update, _calcOutputs, etc. + integer(IntKi) :: UnitNum + INTEGER(IntKi) :: errID + CHARACTER(msgLen) :: errMsg + logical :: warnFlag ! Set if there have been warnings so user can fix even if other fatal error occurs + end type + +contains +!=============================================================================================== +! Error handling routines +!----------------------------------------------------------------------------------------------- +! This routine updates the error ID, appends the message, and writes to screen and log file if requested + subroutine iceErrorHndlr (iceLog, Err, Msg, Scrn) + type (iceFloe_loggingType), intent(inout) :: iceLog + integer(IntKi), intent(in) :: Err ! Error ID + integer(IntKi), intent(in) :: Scrn ! write to screen? + character(*), intent(in) :: Msg + + if ( Err /= ErrID_None ) then +! If we have an existing message, append a new line then the new message + if ( len_trim(iceLog%errMsg) > 0 ) iceLog%errMsg = trim(iceLog%errMsg)//NewLine + iceLog%errMsg = trim(iceLog%errMsg)//trim(Msg) + iceLog%errID = max(iceLog%ErrID, Err) + + if (Err == ErrID_Warn) iceLog%warnFlag = .true. + endif + +! Post the message to the IceFloe log file (this will write to screen as well if requested) + select case (Err) + case (ErrID_Warn) + call logWarn(iceLog, Msg, Scrn) + case (ErrID_Fatal) + call logFatal(iceLog, Msg, Scrn) + end select + + end subroutine iceErrorHndlr + +!----------------------------------------------------------------------------------------------- +! This routine simply appends a message with a new line + subroutine addMessage (iceLog, Msg) + type (iceFloe_loggingType), intent(inout) :: iceLog + character(*), intent(in) :: Msg + iceLog%errMsg = trim(iceLog%errMsg)//newLine//trim(Msg) + end subroutine addMessage + +!=============================================================================================== +! Message logging routines +!----------------------------------------------------------------------------------------------- + subroutine openIceLog (iceLog, logFile) + type (iceFloe_loggingType), intent(inout) :: iceLog + character(*), optional, intent(in) :: logFile + INTEGER(IntKi) :: Err + CHARACTER(msgLen) :: Msg + + call GetNewUnit ( iceLog%UnitNum, Err, Msg ) + if (Err >= ErrID_Severe) then + iceLog%ErrMsg = 'OpenIceLog: '//newLine//trim(Msg) + return + endif + if (present(logFile)) then + call OpenFOutFile ( iceLog%unitNum, logFile, Err, Msg ) + else + call OpenFOutFile ( iceLog%unitNum, 'iceLog.txt', Err, Msg ) + endif + if (Err >= ErrID_Severe) then + iceLog%ErrMsg = 'OpenIceLog: '//newLine//trim(Msg) + return + endif + end subroutine openIceLog + +!-------------------------------------------------------- + subroutine closeIceLog (iceLog) + type (iceFloe_loggingType), intent(in) :: iceLog + close( iceLog%unitNum ) + end subroutine closeIceLog + +!-------------------------------------------------------- + subroutine logMessage (iceLog, msg) + type (iceFloe_loggingType), intent(in) :: iceLog + character(*), intent(in) :: msg + write(iceLog%unitNum,'(A)') trim(msg) + end subroutine logMessage + +!-------------------------------------------------------- + subroutine logWarn (iceLog, msg, Scrn) + type (iceFloe_loggingType), intent(in) :: iceLog + integer(IntKi), intent(in) :: scrn + character(*), intent(in) :: msg + +! Write to log file + write(iceLog%unitNum,*) + write(iceLog%unitNum,'(A)') '************ WARNING ************************************' + write(iceLog%unitNum,'(A)') trim(msg) + write(iceLog%unitNum,'(A)') '*********************************************************' + write(iceLog%unitNum,*) +! Write to screen (may be redundant w/ calling program) + if (scrn==1) call ProgWarn(msg) + + end subroutine logWarn + +!-------------------------------------------------------- + subroutine logFatal (iceLog, msg, scrn) + type (iceFloe_loggingType), intent(in) :: iceLog + integer(IntKi), intent(in) :: scrn + character(*), intent(in) :: msg + +! Write to log file + write(iceLog%unitNum,*) + write(iceLog%unitNum,'(A)') '******** FATAL ERROR, PROGRAM WILL TERMINATE for the following reason ********' + write(iceLog%unitNum,'(A)') trim(msg) + write(iceLog%unitNum,'(A)') '******************************************************************************' + write(iceLog%unitNum,*) +! Write to screen (may be redundant w/ calling program) + if (scrn==1) call ProgAbort('Fatal error, calling program will abort: '//msg, .true.) + + end subroutine logFatal + +end module iceLog \ No newline at end of file diff --git a/OpenFAST/modules/icefloe/src/icefloe/intermittentCrushing.F90 b/OpenFAST/modules/icefloe/src/icefloe/intermittentCrushing.F90 new file mode 100644 index 000000000..e88caf417 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/intermittentCrushing.F90 @@ -0,0 +1,94 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 to initialize and calculate a time series of intermittent +! loads from ice crushing + +module iceIntermittentCrushing + + use iceCrushingISO + + implicit none + + public + +contains + +!======================================================================================== +! calculate the time series of ice loads for intermittent crushing + subroutine initInterCrushing (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput ! Parameters from input file for initialization + type(iceFloe_ParameterType), intent(inout) :: myIceParams ! saved parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + + type(inputParams) :: inParams ! specific input parameter variable list + real(ReKi) :: maxLoad ! Global maximum crushing load + integer(IntKi) :: nL !err, + +! initialize the common parmeters for flexural ice failure + call initIceCrushISO(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting parameters for intermittent crushing loads' ) + + call getIceInput(iceInput, 'interPeriod', inParams%interPeriod, iceLog, 1.0_ReKi) + call logMessage(iceLog, ' Intermittent period = '//TRIM(Num2LStr(inParams%interPeriod))//' seconds') + + call getIceInput(iceInput, 'riseTime', inParams%riseTime, iceLog, 0.1_ReKi, 0.9_ReKi) + call logMessage(iceLog, ' Saw tooth rise time fraction = '//TRIM(Num2LStr(inParams%riseTime))) + + call getIceInput(iceInput, 'fallTime', inParams%fallTime, iceLog, 0.1_ReKi, 1.0_ReKi-inParams%riseTime) + call logMessage(iceLog, ' Saw tooth fall time fraction = '//TRIM(Num2LStr(inParams%fallTime))) + + ! get leg load phase + if (myIceParams%numLegs>1) then + do nL = 1, myIceParams%numLegs + call getIceInput(iceInput, 'loadPhase'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%phase, iceLog, 0.0_ReKi, 360.0_ReKi) + call logMessage(iceLog, ' Load phase for leg '//TRIM(Num2LStr(nL))//' is ' & + //TRIM(Num2LStr(inParams%twr%leg(nL)%phase))//' degrees') + inParams%twr%leg(nL)%phase = D2R*inParams%twr%leg(nL)%phase + enddo + else + inParams%twr%leg(1)%phase = 0.0 + endif + +! The method precalculates a time series of loads based +! on the input parameters and a random distributions of components +! of a spectral model + maxLoad = globalCrushLoadISO(inParams) + call logMessage(iceLog, '** Global crushing load is: '//TRIM(Num2LStr(maxLoad))//' Newtons.' ) + + call crushLoadTimeSeriesISO(myIceParams, inParams, iceLog, maxLoad, 0.0_ReKi, inParams%interPeriod, & + inParams%riseTime, inParams%fallTime) + + end subroutine initInterCrushing + +!**************************************************************************** +! Continuous crushing uses the standard inerpolation routine +! of the precalculated time series + function outputInterCrushLoad (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputCrushLoadISO (myIceParams, iceLog, time) + end function outputInterCrushLoad + +end module iceIntermittentCrushing \ No newline at end of file diff --git a/OpenFAST/modules/icefloe/src/icefloe/lockInISO.F90 b/OpenFAST/modules/icefloe/src/icefloe/lockInISO.F90 new file mode 100644 index 000000000..ebb1e04ec --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/lockInISO.F90 @@ -0,0 +1,93 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ + +!**************************************************************** +! Loads from ice crushing at the specified structural frequency +! per the ISO 19906:2010 with a sawtooth wave form +! +module iceLockInCrushingISO + + use iceCrushingISO + + implicit none + + public + +contains + + subroutine initLockInCrushingISO (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + + real(ReKi) :: fallTime, maxLoad + integer(IntKi) :: nL ! err, + +! initialize the common parmeters + call initIceCrushISO(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting ice crushing loads with frequency lock-in parameteres per ISO') + + call getIceInput(iceInput, 'towerFrequency', inParams%twr%freq, iceLog, 0.01_ReKi, 10.0_ReKi) + call logMessage(iceLog, ' Tower fundamental frequency = '//TRIM(Num2LStr(inParams%twr%freq))//' Hz') + + call getIceInput(iceInput, 'riseTime', inParams%riseTime, iceLog, 0.1_ReKi, 0.9_ReKi) + call logMessage(iceLog, ' Sawtooth rise time fraction = '//TRIM(Num2LStr(inParams%riseTime))) + fallTime = 1.0 - inParams%riseTime + + call getIceInput(iceInput, 'minLoadFraction', inParams%minLoadFraction, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Minimum load fraction (of max) = '//TRIM(Num2LStr(inParams%minLoadFraction))) + + ! get leg load phase + if (myIceParams%numLegs>1) then + do nL = 1, myIceParams%numLegs + call getIceInput(iceInput, 'loadPhase'//TRIM(Num2LStr(nL)), inParams%twr%leg(nL)%phase, iceLog, 0.0_ReKi, 360.0_ReKi) + call logMessage(iceLog, ' Load phase for leg '//TRIM(Num2LStr(nL))//' is ' & + //TRIM(Num2LStr(inParams%twr%leg(nL)%phase))//' degrees') + inParams%twr%leg(nL)%phase = D2R*inParams%twr%leg(nL)%phase + enddo + call getIceInput(iceInput, 'multiLegFactor_kn', inParams%multiLegFactor_kn, iceLog, 0.0_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' Multi leg factor = '//TRIM(Num2LStr(inParams%multiLegFactor_kn))) + else + inParams%twr%leg(1)%phase = 0.0 + inParams%multiLegFactor_kn = 1.0 + endif + +! Pre-calculate sawtooth time series of loads + maxLoad = inParams%multiLegFactor_kn*globalCrushLoadISO(inParams) + call logMessage(iceLog, '** Global crushing load is: '//TRIM(Num2LStr(maxLoad))//' Newtons.' ) + + call crushLoadTimeSeriesISO(myIceParams, inParams, iceLog, maxLoad, inParams%minLoadFraction*maxLoad, & + 1.0_ReKi/inParams%twr%freq, inParams%riseTime, fallTime) + + end subroutine initLockInCrushingISO + +!**************************************************************************** + function outputLockInLoadISO (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputCrushLoadISO (myIceParams, iceLog, time) + end function outputLockInLoadISO + +end module iceLockInCrushingISO diff --git a/OpenFAST/modules/icefloe/src/icefloe/randomCrushing.F90 b/OpenFAST/modules/icefloe/src/icefloe/randomCrushing.F90 new file mode 100644 index 000000000..9996a4032 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/icefloe/randomCrushing.F90 @@ -0,0 +1,177 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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 to calculate a time series of random loads due to continuous ice crushing +! +! Based on a spectral method from: +! Karna, T, et. al., "A Spectral Model for Forces due to Ice Crushing", +! Journal of Offshore Mechanics and Arctic Engineering, May, 2006 +! +module randomCrushing + + use iceCrushingISO + + implicit none + + public + +contains + +!================================================================================ +! Initialize the time series of ice loads for random continuous crushing + subroutine initRandomCrushing (iceInput, myIceParams, iceLog) + + type(iceInputType), intent(in) :: iceInput ! Parameters read from file for initialization + type(iceFloe_ParameterType), intent(inout) :: myIceParams ! saved parameters + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + type(inputParams) :: inParams ! specific input parameter variable list + +! local variables + real(ReKi) :: maxLoad + +! initialize the common parmeters for flexural ice failure + call initIceCrushISO(iceInput, inParams, myIceParams, iceLog) + + call logMessage(iceLog, newLine//' Setting parameters for random crushing loads time series') + + call getIceInput(iceInput, 'coeffPSD_b', inParams%coeffPSD_b, iceLog, 0.1_ReKi, 3.0_ReKi) + call logMessage(iceLog, ' coeffPSD_b = '//TRIM(Num2LStr(inParams%coeffPSD_b))) + + call getIceInput(iceInput, 'coeffPSD_Ks', inParams%coeffPSD_Ks, iceLog, 1.0_ReKi, 5.0_ReKi) + call logMessage(iceLog, ' coeffPSD_Ks = '//TRIM(Num2LStr(inParams%coeffPSD_Ks))) + + call getIceInput(iceInput, 'crushLoadCOV', inParams%crushLoadCOV, iceLog, 0.1_ReKi, 1.0_ReKi) + call logMessage(iceLog, ' crushLoadCOV = '//TRIM(Num2LStr(inParams%crushLoadCOV))) + + call getIceInput(iceInput, 'stdLoadMult', inParams%stdLoadMult, iceLog, 1.0_ReKi, 6.0_ReKi) + call logMessage(iceLog, ' stdLoadMult (number of std devs) = '//TRIM(Num2LStr(inParams%stdLoadMult))) + + call getIceInput(iceInput, 'freqStep', inParams%freqStep, iceLog, .001_ReKi, 0.1_ReKi) + call logMessage(iceLog, ' Frequency step = '//TRIM(Num2LStr(inParams%freqStep))//' Hz') + +! Precalculates a time series of loads + maxLoad = globalCrushLoadISO(inParams) + call logMessage(iceLog, '** Global crushing load is: '//TRIM(Num2LStr(maxLoad))//' Newtons.' ) + call randomCrushLoadTimeSeries(myIceParams, iceLog, maxLoad) + + contains + +!================================================================== +! Generate a random time series by randomizing the phase of sinusoids +! based on a spectrum + subroutine randomCrushLoadTimeSeries (myIceParams, iceLog, maxLoad) + type(iceFloe_ParameterType), intent(inout) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(ReKi), intent(in) :: maxLoad ! global crushing maximum load + + integer(IntKi), parameter :: LuxLevel = 3 ! for ranlux + integer(IntKi) :: err + integer(IntKi) :: nf, ns, nL, nSteps, nfSteps + real(ReKi) :: timeStep, meanLoad, stdLoad + real(ReKi), allocatable :: frequency(:), amplitude(:), randPhase(:) ! temporary variables + real(ReKi) :: nyqFreq, a, stdSum + +! get the mean and standard deviation of the loading +! these will be used to scale the generated time series + meanLoad = maxLoad/(1.0+inParams%stdLoadMult*inParams%crushLoadCOV) + call logMessage(iceLog, '** Mean crushing load is: '//TRIM(Num2LStr(meanLoad))//' Newtons.' ) + stdLoad = meanLoad*inParams%crushLoadCOV + call logMessage(iceLog, '** Stdev of crushing load is: '//TRIM(Num2LStr(stdLoad))//' Newtons.' ) + +! Number of steps in time series of loads + nSteps = size(myIceParams%loadSeries,1) + +! allocate some temporary arrays + nyqFreq = 0.5/myIceParams%dt + nfSteps = floor(nyqFreq/inParams%freqStep) + allocate(randPhase(nfSteps), stat=err) + if (err /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in phase array allocation in RandomCrushLoadTimeSeries', 1) + return ! error in array allocation + endif + allocate(frequency(nfSteps), stat=err) + allocate(amplitude(nfSteps), stat=err) + if (err /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in frequency or amplitude array allocation in '// & + 'RandomCrushLoadTimeSeries', 1) + return ! error in array allocation + endif + +! Initialize the random number generator + call RLuxGo ( LuxLevel, abs(inParams%randomSeed), 0, 0 ) + +! Loop on number of legs + do nL = 1, myIceParams%numLegs + ! get a random phase on the interval +/- pi + call RanLux ( randPhase ) + randPhase = 2.0*pi*randPhase - pi + + ! calculate the amplitude for each frequency from the PSD + a = inParams%coeffPSD_b/(inParams%iceVelocity**0.6) + do nf = 1, nfSteps + frequency(nf) = float(nf)*inParams%freqStep + ! Note PSD is amplitude squared so take square root and mult by freq resolution to get discrete + ! Also times 2 since we are using a single sided PSD + amplitude(nf) = sqrt( (2.0*a*(stdLoad**2)*inParams%freqStep) & + / (1.0+inParams%coeffPSD_Ks*(a**1.5)*frequency(nf)**2) ) + enddo + + ! calculate time series as a sum of frequencies at each time step + ! with amplitudes and random phases at each frequency + ! get the standard deviation for later scaling + stdSum = 0.0 + do ns = 1, nSteps + timeStep = myIceParams%dt*real(ns,ReKi) + myIceParams%loadSeries(ns,nL) = 0.0 + do nf = 1, nfSteps + myIceParams%loadSeries(ns,nL) = myIceParams%loadSeries(ns,nL) + & + amplitude(nf)*cos(2.0*pi*frequency(nf)*timeStep+randPhase(nf)) + enddo +! stdSum = stdSum + myIceParams%loadSeries(ns,nL)**2 + enddo + ! scale the variations to get the desired standard deviation + ! Testing suggests that this doesn't give the desired PSD, so remove +! stdSum = sqrt(stdSum/real(nSteps,ReKi)) +! myIceParams%loadSeries(:,nL) = (stdLoad/stdSum)*myIceParams%loadSeries(:,nL) + ! add in the mean + myIceParams%loadSeries(:,nL) = myIceParams%ks(nL)*(meanLoad + myIceParams%loadSeries(:,nL)) + + enddo ! leg loop + + deallocate(frequency) + deallocate(amplitude) + deallocate(randPhase) + + end subroutine randomCrushLoadTimeSeries + + end subroutine initRandomCrushing ! containing subroutine + +!**************************************************************************** +! Continuous crushing uses the standard inerpolation routine +! of the precalculated time series + function outputRandomCrushLoad (myIceParams, iceLog, time) result(iceLoads) + type(iceFloe_ParameterType), intent(in) :: myIceParams + type(iceFloe_LoggingType), intent(inout) :: iceLog ! structure with message and error logging variables + real(DbKi), intent(in) :: time + real(ReKi) :: iceLoads(6,myIceParams%numLegs) + + iceLoads = outputCrushLoadISO (myIceParams, iceLog, time) + end function outputRandomCrushLoad + +end module randomCrushing \ No newline at end of file diff --git a/OpenFAST/modules/icefloe/src/interfaces/ADAMS/IceADAMS_VFOSUB.f90 b/OpenFAST/modules/icefloe/src/interfaces/ADAMS/IceADAMS_VFOSUB.f90 new file mode 100644 index 000000000..74ef79182 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/ADAMS/IceADAMS_VFOSUB.f90 @@ -0,0 +1,264 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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-01-31 09:14:28 -0800 (Fri, 31 Jan 2014) $ +! (File) Revision #: $Rev: 131 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/HAWC2_DLL/HAWC2_DLL.f90 $ +!********************************************************************************************************************************** + +module IceADAMS + + use IceLog + use IceInputParams + use iceFloeBase + use IceCrushingISO + use IceCrushingIEC + use IceIntermittentCrushing + use IceFlexISO + use IceFlexIEC + use IceLockInCrushingISO + use randomCrushing + use IceCpldCrushing + use NWTC_IO, only : DispNVD, progdesc, curdate, curtime + + type(iceFloe_ParameterType), save :: icep ! Parameters, including precalculated time series + type(iceFloe_LoggingType), save :: theIceLog ! structure with message and error logging variables + +contains +!------------------------------------------------------------------------------------ + subroutine icefloe_init() + + implicit none + + ! locals + Real(ReKi) :: duration + INTEGER(IntKi) :: nSteps + INTEGER(IntKi) :: Err ! Error status of the operation + LOGICAL, SAVE :: bInit = .FALSE. ! Initialization flag + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', 'v1.00.00', 'May-2014' ) + + ! More IceFloe types + type(iceInputType) :: iceInput ! hold list of input names and values from file + character(132) :: logFile ! File name for message logging + + ! Set up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + + ! Display the module information + + CALL DispNVD( IceFloe_Ver ) + + call openIceLog(theIceLog, 'IceFloe.log') + call logMessage(theIceLog, ' Running: '//trim(IceFloe_Ver%Name)//trim(IceFloe_Ver%Ver)//trim(IceFloe_Ver%Date)) + call logMessage(theIceLog, ' This run started on: '//curdate()//' at '//curtime()//newLine) + + call countIceInputs('testIce.inp', theIceLog, iceInput) + call readIceInputs(theIceLog, iceInput) + call logMessage(theIceLog, ' Input file read complete.'//newLine) + + ! call IceFloe initialization routine and get parameters back + ! not all parameters used by all ice floe types + call getIceInput(iceInput, 'iceType',icep%iceType, theIceLog, lowTypeLimit, hiTypeLimit) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + + ! Set the time step as the minimum of the suggested p%dt and the time step from the ice input file + call getIceInput(iceInput, 'timeStep',icep%dt, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + + ! get the duration of the simulation + call getIceInput(iceInput, 'duration', duration, theIceLog, 0.0) + call logMessage(theIceLog, ' Load time series duration = '//TRIM(Num2LStr(duration))//' sec') + + ! get the number of legs on the support structure + call getIceInput(iceInput, 'numLegs', icep%numLegs, theIceLog, 1, 4) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + + ! allocate storage for load series + nSteps = ceiling(duration/icep%dt) + 1 ! + 1 for zero point + allocate(icep%loadSeries(nSteps, icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in time series array allocation in IceFloe_init', 1) + return + endif + ! point internal iceFloe array to the saved load series + ! icep%loadSeries => loadseries + + ! allocate storage for the leg positions + allocate (icep%legX(icep%numLegs), stat=err) + allocate (icep%legY(icep%numLegs), stat=err) + allocate (icep%ks(icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in allocation of leg data in parameters', 1) + return ! error in array allocation + endif + + iceType: select case (icep%iceType) + case (randomCrush) + call initRandomCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Random continuous ice crushing via ISO/Karna initialized'//newLine) + case (interCrush) + call initInterCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Intermittent ice crushing loads initialized'//newLine) + case (crushIEC) + call initCrushingIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Ice crushing loads IEC/Korzhavin initialized'//newLine) + case (flexFailISO) + call initFlexISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' ISO/Croasdale ice flexural failure loads initialized'//newLine) + case (flexFailIEC) + call initFlexIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' IEC/Ralston ice flexural failure loads initialized'//newLine) + case (lockInISO) + call initLockInCrushingISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Frequency lock-in ice crushing loads via ISO initialized'//newLine) + case (cpldCrush) + call initCpldCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Coupled crushing ice loads (Maattanen) initialized'//newLine) + case default + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Invalid ice floe type, ' & + //TRIM(Num2LStr(icep%IceType))//' is not a valid selection', 1) + end select iceType + + end subroutine icefloe_init + +!********************************************************************************************************************************** + SUBROUTINE icefloe_update(Time, Vels, Forces) + + implicit none + ! input + real(DbKi), intent(IN) :: Time + real(ReKi), intent(IN) :: Vels(3) + ! output + real(ReKi), intent(OUT) :: Forces(3) + + real(ReKi) :: loadVect(6,icep%numLegs) + real(ReKi) :: inVels(2,icep%numLegs) + integer(IntKi) :: nL + + ! reset up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + + ! Assign support structure velocities to local variables + ! CURRENTLY only monopile supported so NL should = 1 + inVels = 0.0 + do nL = 1, icep%numLegs + inVels(1,nL) = Vels(1) + inVels(2,nL) = Vels(2) + enddo + + ! get loads from IceFloe + iceType: select case (icep%iceType) + case (randomCrush) + loadVect = outputRandomCrushLoad(icep, theIceLog, time) + case (crushIEC) + loadVect = outputCrushLoadIEC(icep, theIceLog, time) + case (interCrush) + loadVect = outputInterCrushLoad(icep, theIceLog, time) + case (flexFailISO) + loadVect = outputFlexLoadISO(icep, theIceLog, time) + case (flexFailIEC) + loadVect = outputFlexLoadIEC(icep, theIceLog, time) + case (lockInISO) + loadVect = outputLockInLoadISO(icep, theIceLog, time) + case (cpldCrush) + loadVect = outputCpldCrushLoad(icep, theIceLog, inVels, time) + case default + call logFatal (theIceLog, 'Invalid Ice Floe Type Selection', 1) + end select iceType + + !Apply ramp for first 10 seconds + do nL = 1, icep%numLegs + Forces(1) = loadVect(1,nL)*min(1.0, 0.1*time) + Forces(2) = loadVect(2,nL)*min(1.0, 0.1*time) + Forces(3) = 0.0 + enddo + + end SUBROUTINE icefloe_update + +end module IceADAMS + +!********************************************************************************************************************************** + +SUBROUTINE VFOSUB ( ID, ATIME, PAR, NPAR, DFLAG, IFLAG, Forces ) + +! This routine is used to calculate the functional values for a VFORCE statement. +! Specifically to call the IceFloe routines for use in ADAMS + + use IceADAMS + + IMPLICIT NONE + +! Passed variables: + + INTEGER(4), INTENT(IN ) :: ID ! ID of the REQUEST statement calling this routine. + INTEGER(4), INTENT(IN ) :: NPAR ! Number of PARameters passed through PAR. + + REAL(8), INTENT(IN ) :: ATIME ! The current simimulation time. + REAL(8), INTENT(IN ) :: PAR(NPAR) ! The passeed PARameters. + REAL(8), INTENT(OUT) :: Forces(3) ! Values returned to ADAMS. + + LOGICAL, INTENT(IN) :: DFLAG ! Partial Derivative flag. + LOGICAL, INTENT(IN) :: IFLAG ! Initialization pass flag. + +! Local variables + LOGICAL, save :: initFlag = .true. + logical :: errFlg + integer(4) :: IPar3(3), NStates + REAL(4) :: IceForces(3) + REAL(8) :: States(3) + +! get the local velocity at the marker specified in PAR + IPar3(1) = int(PAR(1)) + IPar3(2) = 1 ! ground marker + IPar3(3) = 1 ! ground marker + call SYSARY('TVEL', IPar3, 3, States, NStates, errFlg ) + + IceForces = 0.0 + if (IFLAG .and. initFlag) then + call icefloe_init + initFlag = .false. + endif + + if (.not. initFlag) then +! Get the ice loads + call icefloe_update(atime, real(States, 4), IceForces) + endif + + Forces = real(IceForces, 8)/1000.0 + +END SUBROUTINE VFOSUB + diff --git a/OpenFAST/modules/icefloe/src/interfaces/Bladed/IceFloeBladed.f90 b/OpenFAST/modules/icefloe/src/interfaces/Bladed/IceFloeBladed.f90 new file mode 100644 index 000000000..baa0b0ccb --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/Bladed/IceFloeBladed.f90 @@ -0,0 +1,233 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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-01-07 14:11:45 -0800 (Tue, 07 Jan 2014) $ +! (File) Revision #: $Rev: 120 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/IceFloeConsole/source/IceFloe.f90 $ +!********************************************************************************************************************************** + +!**************************************************************** +! Console program for IceFloe package specific to the Bladed Point load format +! Used to generate time series of ice loads to be read in by Bladed + +program IceFloeBladed + + use IceLog + use IceInputParams + use iceFloeBase + use IceCrushingISO + use IceCrushingIEC + use IceIntermittentCrushing + use IceFlexISO + use IceFlexIEC + use IceLockInCrushingISO + use randomCrushing + use NWTC_IO, only : DispNVD, progdesc, curdate, curtime, nameofile + + implicit none + + TYPE(iceFloe_ParameterType), save :: icep ! Parameters, including precalculated time series + type(iceFloe_LoggingType),save :: theIceLog ! structure with message and error logging variables + type(iceInputType) :: iceInput ! hold list of input names and values from file + + Real(ReKi) :: duration + INTEGER(IntKi) :: nSteps + INTEGER(IntKi) :: Err ! Error status of the operation + LOGICAL, SAVE :: bInit = .FALSE. ! Initialization flag + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', 'v1.00.00', 'May-2014' ) + + CHARACTER(msgLen) :: Msg ! Error message + character(132) :: logFile ! File name for message logging + character(132) :: inputFile + character(132) :: outFile + character(4) :: fileLegNum + integer(IntKi) :: outUnitNum, numArg, n, nL + +! get parameter input file from command line + numArg = COMMAND_ARGUMENT_COUNT() + if (numArg > 0) then + CALL GET_COMMAND_ARGUMENT( 1, inputFile ) + else + write(*,*) ' No input file specified on command line. Exiting program.' + stop + endif + +! Set up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + +! Display the module information + + CALL DispNVD( IceFloe_Ver ) + + call NameOFile ( 1, 'log', logFile ) ! The filename comes from the command line + call openIceLog (theIceLog, logFile) + call logMessage(theIceLog, ' Running: '//trim(IceFloe_Ver%Name)//trim(IceFloe_Ver%Ver)//trim(IceFloe_Ver%Date)) + call logMessage(theIceLog, ' This run started on: '//curdate()//' at '//curtime()//newLine) + +! read the input file twice: once to count the other to read + call countIceInputs(inputFile, theIceLog, iceInput) + call readIceInputs(theIceLog, iceInput) + call logMessage(theIceLog, ' Input file read complete.'//newLine) + +! get some top level input parameters +! the type of ice loading + call getIceInput(iceInput, 'iceType',icep%iceType, theIceLog, lowTypeLimit, hiTypeLimit) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif +! the time step + call getIceInput(iceInput, 'timeStep',icep%dt, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif + call getIceInput(iceInput, 'rampTime',icep%rampTime, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif +! the duration of the simulation + call getIceInput(iceInput, 'duration', duration, theIceLog, 0.0) + call logMessage(theIceLog, ' Load time series duration = '//TRIM(Num2LStr(duration))//' sec') +! the number of legs on the support structure + call getIceInput(iceInput, 'numLegs', icep%numLegs, theIceLog, 1, 4) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif + +! allocate storage for load time series + nSteps = ceiling(duration/icep%dt) + 1 ! + 1 for zero point + allocate(icep%loadSeries(nSteps, icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in time series array allocation in IceFloe_init', 1) + stop + endif + +! allocate storage for the leg positions + allocate (icep%legX(icep%numLegs), stat=err) + allocate (icep%legY(icep%numLegs), stat=err) + allocate (icep%ks(icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in allocation of leg data in parameters', 1) + stop ! error in array allocation + endif + icep%legX = 0.0 + icep%legY = 0.0 + icep%ks = 1.0 + +! initialize and calculate load time series + iceType: select case (icep%iceType) + case (randomCrush) + call initRandomCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Random continuous ice crushing via ISO/Karna initialized'//newLine) + case (interCrush) + call initInterCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Intermittent ice crushing loads initialized'//newLine) + case (crushIEC) + call initCrushingIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Ice crushing loads IEC/Korzhavin initialized'//newLine) + case (flexFailISO) + call initFlexISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' ISO/Croasdale ice flexural failure loads initialized'//newLine) + case (flexFailIEC) + call initFlexIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' IEC/Ralston ice flexural failure loads initialized'//newLine) + case (lockInISO) + call initLockInCrushingISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Frequency lock-in ice crushing loads via ISO initialized'//newLine) + case default + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Invalid ice floe type, ' & + //TRIM(Num2LStr(icep%IceType))//' is not a valid selection', 1) + end select iceType + + if (theIceLog%ErrID >= AbortErrLev) stop + +! Ouput time series of loads to ASCII file +! If only one leg or applying as a single load for multiple legs +! then only writing one file + write(*,*) 'Writing load series to file.' + if (icep%singleLoad .or. icep%numLegs == 1) then + call NameOFile ( 1, 'dat', outFile ) ! The filename comes from the command line + call GetNewUnit ( outUnitNum, Err, Msg ) + call OpenFOutFile ( outUnitNum, outFile, Err, Msg ) + if (Err >= ErrID_Severe) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error opening output file: '//newLine//trim(Msg), 1) + stop + endif + call writeTimeSeries (outUnitNum, nSteps, 1, icep) + close (outUnitNum) + else +! Need one file for each load point, i.e. each leg + do nL = 1, icep%numLegs + write(fileLegNum,'("dat",I1)') nL + call NameOFile ( 1, fileLegNum, outFile ) ! The filename comes from the command line + call GetNewUnit ( outUnitNum, Err, Msg ) + call OpenFOutFile ( outUnitNum, outFile, Err, Msg ) + call writeTimeSeries (outUnitNum, nSteps, nL, icep) + close (outUnitNum) + enddo + endif + + write(*,*) 'Load series write complete.' + +end program IceFloeBladed + + +subroutine writeTimeSeries (outUnitNum, nSteps, nL, icep) + + use iceFloebase + implicit none + + TYPE(iceFloe_ParameterType), intent(IN) :: icep ! Parameters, including precalculated time series + integer(IntKi), intent(IN) :: nSteps, outUnitNum, nL + + real(ReKi) :: loadVect(6,icep%numLegs) ! Forces and moments for a given leg at a given time step + integer(IntKi) :: n, nn + +! Start with header info and zeros for the first time step as suggested in Bladed User Manual + write(outUnitNum,'("NUMPOINTS ", I10)') nSteps + write(outUnitNum,'(7(1pe12.5,1x))') (0.0, nn=1,7) + do n = 1, nSteps-2 + ! If the loads from multiple legs are applied as an "effective" load on one leg at the + ! support center, then compute that effective load vector and put into the first load vector + ! Note that only Fx, Fy, and Mz terms re-calculated. All others remain zero + if (icep%numLegs > 1 .and. icep%singleLoad) then + do nn = 1, icep%numLegs + loadVect(:,nn) = iceLoadDirection(icep%loadSeries(n+1,nn), icep) + enddo + loadVect(:,1) = iceLoadEquivalent(loadVect, icep) + else + loadVect(:,1) = iceLoadDirection(icep%loadSeries(n+1,nL), icep) + endif + loadVect = loadVect*min(1.0, real(n,ReKi)/(icep%rampTime/icep%dt)) ! apply ramp as loads can be large impacts + write(outUnitNum,'(7(1pe12.5,1x))') real(n,ReKi)*icep%dt, (loadVect(nn,1), nn = 1,6) + enddo + +! end with zeros for the last time step + write(outUnitNum,'(7(1pe12.5,1x))') real(nSteps-1,ReKi)*icep%dt, (0.0, nn=1,6) + +end subroutine writeTimeSeries +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/icefloe/src/interfaces/Console/IceFloe.f90 b/OpenFAST/modules/icefloe/src/interfaces/Console/IceFloe.f90 new file mode 100644 index 000000000..6929fd64e --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/Console/IceFloe.f90 @@ -0,0 +1,196 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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-06-18 13:11:28 -0700 (Wed, 18 Jun 2014) $ +! (File) Revision #: $Rev: 149 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/IceFloeConsole/source/IceFloe.f90 $ +!********************************************************************************************************************************** + +!**************************************************************** +! Console program for IceFloe package +! Used to generate time series of ice loads to be read in by other programs +! Note all models supported except coupled crushing which requires feedback of structureal motion + +program IceFloe + + use IceLog + use IceInputParams + use iceFloeBase + use IceCrushingISO + use IceCrushingIEC + use IceIntermittentCrushing + use IceFlexISO + use IceFlexIEC + use IceLockInCrushingISO + use randomCrushing + use NWTC_IO, only : DispNVD, progdesc, curdate, curtime, nameofile + + implicit none + + + TYPE(iceFloe_ParameterType), save :: icep ! Parameters, including precalculated time series + type(iceFloe_LoggingType),save :: theIceLog ! structure with message and error logging variables + type(iceInputType) :: iceInput ! hold list of input names and values from file + + Real(ReKi) :: duration + INTEGER(IntKi) :: nSteps + INTEGER(IntKi) :: Err ! Error status of the operation + LOGICAL, SAVE :: bInit = .FALSE. ! Initialization flag + character(*), parameter :: Progname_ice = 'IceFloeConsole' + character(*), parameter :: Progver_ice = 'v1.00.00' + character(*), parameter :: Progdate_ice = 'December-2013' + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( Progname_ice, Progver_ice, Progdate_ice ) + + CHARACTER(msgLen) :: Msg ! Error message + character(132) :: logFile ! File name for message logging + character(132) :: inputFile + character(132) :: outFile + integer(IntKi) :: outUnitNum, numArg, n, nL + +! get parameter input file from command line + numArg = COMMAND_ARGUMENT_COUNT() + if (numArg > 0) then + CALL GET_COMMAND_ARGUMENT( 1, inputFile ) + else + write(*,*) ' No input file specified on command line. Exiting program.' + stop + endif + +! Set up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + +! Display the module information + + CALL DispNVD( IceFloe_Ver ) + + call NameOFile ( 1, 'log', logFile ) ! The filename comes from the command line + call openIceLog (theIceLog, logFile) + call logMessage(theIceLog, ' Running: '//ProgName_ice//', '//ProgVer_ice//', '//Progdate_ice) + call logMessage(theIceLog, ' This run started on: '//curdate()//' at '//curtime()//newLine) + +! read the input file twice: once to count the other to read + call countIceInputs(inputFile, theIceLog, iceInput) + call readIceInputs(theIceLog, iceInput) + call logMessage(theIceLog, ' Input file read complete.'//newLine) + +! get some top level input parameters +! the type of ice loading + call getIceInput(iceInput, 'iceType',icep%iceType, theIceLog, lowTypeLimit, hiTypeLimit) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif +! the time step + call getIceInput(iceInput, 'timeStep',icep%dt, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif +! the ramp time + call getIceInput(iceInput, 'rampTime',icep%rampTime, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif +! the duration of the simulation + call getIceInput(iceInput, 'duration', duration, theIceLog, 0.0) + call logMessage(theIceLog, ' Load time series duration = '//TRIM(Num2LStr(duration))//' sec') +! the number of legs on the support structure + call getIceInput(iceInput, 'numLegs', icep%numLegs, theIceLog, 1, 4) + if (theIceLog%ErrID >= AbortErrLev) then + stop + endif + +! allocate storage for load time series + nSteps = ceiling(duration/icep%dt) + 1 ! + 1 for zero point + allocate(icep%loadSeries(nSteps, icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in time series array allocation in IceFloe_init', 1) + stop + endif + +! allocate storage for the leg positions + allocate (icep%legX(icep%numLegs), stat=err) + allocate (icep%legY(icep%numLegs), stat=err) + allocate (icep%ks(icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in allocation of leg data in parameters', 1) + stop ! error in array allocation + endif + icep%legX = 0.0 + icep%legY = 0.0 + icep%ks = 1.0 + +! initialize and calculate load time series + iceType: select case (icep%iceType) + case (randomCrush) + call initRandomCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Random continuous ice crushing via ISO/Karna initialized'//newLine) + case (interCrush) + call initInterCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Intermittent ice crushing loads initialized'//newLine) + case (crushIEC) + call initCrushingIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Ice crushing loads IEC/Korzhavin initialized'//newLine) + case (flexFailISO) + call initFlexISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' ISO/Croasdale ice flexural failure loads initialized'//newLine) + case (flexFailIEC) + call initFlexIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' IEC/Ralston ice flexural failure loads initialized'//newLine) + case (lockInISO) + call initLockInCrushingISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Frequency lock-in ice crushing loads via ISO initialized'//newLine) + case default + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Invalid ice floe type, ' & + //TRIM(Num2LStr(icep%IceType))//' is not a valid selection', 1) + end select iceType + + if (theIceLog%ErrID >= AbortErrLev) stop + +! Ouput time series of loads to ASCII file + call NameOFile ( 1, 'dat', outFile ) ! The filename comes from the command line + call GetNewUnit ( outUnitNum, Err, Msg ) + if (Err >= ErrID_Severe) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error obtaining output file handle: '//newLine//trim(Msg), 1) + stop + endif + call OpenFOutFile ( outUnitNum, outFile, Err, Msg ) + if (Err >= ErrID_Severe) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error opening output file: '//newLine//trim(Msg), 1) + stop + endif + + write(*,*) 'Writing load series to file.' + do n = 0, nSteps-1 + icep%loadSeries(n+1,:) = icep%loadSeries(n+1,:)*min(1.0, real(n,ReKi)/(icep%rampTime/icep%dt)) ! apply ramp as loads can be large impacts + write(outUnitNum,'(5(1pe12.5,1x))') real(n,ReKi)*icep%dt, (icep%loadSeries(n+1,nL), nL = 1,icep%numLegs) + enddo + write(*,*) 'Load series write complete.' + + +end program IceFloe + +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/icefloe/src/interfaces/Console/NWTC_Base_reduced.f90 b/OpenFAST/modules/icefloe/src/interfaces/Console/NWTC_Base_reduced.f90 new file mode 100644 index 000000000..5c3b35425 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/Console/NWTC_Base_reduced.f90 @@ -0,0 +1,69 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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. +! +!********************************************************************************************************************************** +! File last committed: $Date: 2013-12-23 14:04:45 -0800 (Mon, 23 Dec 2013) $ +! (File) Revision #: $Rev: 117 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/IceDyn/source/NWTC_Lib/NWTC_Base.f90 $ +!********************************************************************************************************************************** +MODULE NWTC_Base + + + ! This module stores basic constants and routines that are not system-specific, but may be used in the system-specific routines. +! USE, INTRINSIC :: ISO_C_Binding + USE Precision + + IMPLICIT NONE + +!======================================================================= + + ! General constants: + +! INTEGER, PARAMETER :: BITS_IN_ADDR = C_INTPTR_T*8 ! The number of bits in an address (32-bit or 64-bit). + + INTEGER(IntKi), PARAMETER :: ChanLen = 10 ! The allowable length of channel names (i.e., width of output columns) in the FAST framework + + LOGICAL,PARAMETER :: NWTC_VerboseComments = .TRUE. + + ! Global Error-level variables: + + INTEGER(IntKi), PARAMETER :: ErrID_None = 0 + INTEGER(IntKi), PARAMETER :: ErrID_Info = 1 + INTEGER(IntKi), PARAMETER :: ErrID_Warn = 2 + INTEGER(IntKi), PARAMETER :: ErrID_Severe = 3 + INTEGER(IntKi), PARAMETER :: ErrID_Fatal = 4 + + INTEGER(IntKi) :: AbortErrLev = ErrID_Fatal ! Note that this is not a PARAMETER + + + ! Type definition for dynamically loaded libraries: + ! Note that changes here may need to be reflected in DLLTypePack() DLLTypeUnPack(), and the FAST Registry.exe + +! TYPE DLL_Type +! +! INTEGER(C_INTPTR_T) :: FileAddr ! The address of file FileName. (RETURN value from LoadLibrary ) [Windows] +! TYPE(C_PTR) :: FileAddrX ! The address of file FileName. (RETURN value dlopen ) [Linux] +! TYPE(C_FUNPTR) :: ProcAddr ! The address of procedure ProcName. (RETURN value from GetProcAddress or dlsym) +! +! CHARACTER(1024) :: FileName ! The name of the DLL file including the full path to the current working directory. +! CHARACTER(1024) :: ProcName ! The name of the procedure in the DLL that will be called. +! +! END TYPE DLL_Type + + +END MODULE NWTC_Base diff --git a/OpenFAST/modules/icefloe/src/interfaces/Console/SysIVF_reduced.f90 b/OpenFAST/modules/icefloe/src/interfaces/Console/SysIVF_reduced.f90 new file mode 100644 index 000000000..0c31950cc --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/Console/SysIVF_reduced.f90 @@ -0,0 +1,373 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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. +! +!********************************************************************************************************************************** +! File last committed: $Date: 2013-12-23 14:04:45 -0800 (Mon, 23 Dec 2013) $ +! (File) Revision #: $Rev: 117 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/IceDyn/source/NWTC_Lib/SysIVF.f90 $ +!********************************************************************************************************************************** +MODULE SysSubs + + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + + ! SysIVF.f90 is specifically for the Intel Visual Fortran for Windows compiler. + + + ! It contains the following routines: + + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! per MLB, this can be removed, but only if CU is OUTPUT_UNIT: + ! SUBROUTINE OpenCon ! Actually, it can't be removed until we get Intel's FLUSH working. (mlb) + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + + + + USE NWTC_Base + + IMPLICIT NONE + + +!======================================================================= + + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + INTEGER, PARAMETER :: NL_Len = 2 ! The number of characters used for a new line. + + LOGICAL, PARAMETER :: KBInputOK = .TRUE. ! A flag to tell the program that keyboard input is allowed in the environment. + + CHARACTER(10), PARAMETER :: Endian = 'BIG_ENDIAN' ! The internal format of numbers. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Visual Fortran for Windows'! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '\' ! The path separater. + CHARACTER( 1), PARAMETER :: SwChar = '/' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'BINARY' ! The string to specify unformatted I/O files. (used in OpenUOutFile and OpenUInpFile [see TurbSim's .bin files]) + +CONTAINS + +!======================================================================= + FUNCTION FileSize( Unit ) + + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + + USE IFPORT + + + ! Function declaration. + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + + + ! Local declarations: + + INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. + INTEGER :: Status ! The status returned by + + + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + + RETURN + END FUNCTION FileSize ! ( Unit ) +!======================================================================= + SUBROUTINE FlushOut ( Unit ) + + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + + USE IFPORT + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + + + CALL FLUSH ( INT(Unit, B4Ki) ) +!bjj: ADAMS does not compile well with this, so I'll put it back to the subroutine form: +! FLUSH ( Unit ) + + + RETURN + END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= + SUBROUTINE Get_CWD ( DirName, Status ) + + + ! This routine retrieves the path of the current working directory. + + + USE IFPORT + + IMPLICIT NONE + + + ! Passed variables. + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + + Status = GETCWD ( DirName ) + + RETURN + END SUBROUTINE Get_CWD +!======================================================================= + FUNCTION Is_NaN( DblNum ) + + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN in new code, but remains here for + ! backwards compatibility. + + USE IFPORT !remove with use of next line (not implemented in all versions of the IVF compiler) +! USE, INTRINSIC :: ieee_arithmetic + + + ! Argument declarations. + + REAL(DbKi), INTENT(IN) :: DblNum + + + ! Function declaration. + + LOGICAL :: Is_Nan + + + +! Is_NaN = IEEE_IS_NAN( DblNum ) + Is_NaN = IsNaN( DblNum ) + + + RETURN + END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= + SUBROUTINE OpenCon + + + ! This routine opens the console for standard output. + + + USE IFPORT + +!bjj this can be used later: +! INTEGER :: OUTPUT_UNIT +! +! +! OPEN ( OUTPUT_UNIT , FILE='CON' , STATUS='UNKNOWN' , CARRIAGECONTROL='FORTRAN', RECL=ConRecL ) +! +! CALL FlushOut ( OUTPUT_UNIT ) + + + OPEN ( CU , FILE='CON' , STATUS='UNKNOWN' , CARRIAGECONTROL='FORTRAN', RECL=ConRecL ) + + CALL FlushOut ( CU ) + + RETURN + END SUBROUTINE OpenCon +!======================================================================= + SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. +! ACTION='READ' ) ! Use this for UNIX systems. + + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + + RETURN + END SUBROUTINE OpenUnfInpBEFile +!======================================================================= + SUBROUTINE ProgExit ( StatCode ) + + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + + + CALL EXIT ( StatCode ) + +! IF ( StatCode == 0 ) THEN +! STOP 0 +! ELSE +! IF ( StatCode < 0 ) THEN +! CALL WrScr( 'Invalid STOP code.' ) +! END IF +! +! STOP 1 +! END IF + + + END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= + SUBROUTINE UsrAlarm + + + ! This routine generates an alarm to warn the user that something went wrong. + + + + CALL WrNR ( CHAR( 7 ) ) + + + RETURN + END SUBROUTINE UsrAlarm +!======================================================================= + SUBROUTINE WrNR ( Str ) + + + ! This routine writes out a string to the screen without following it with a new line. + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + + + RETURN + END SUBROUTINE WrNR ! ( Str ) +!======================================================================= + SUBROUTINE WrOver ( Str ) + + + ! This routine writes out a string that overwrites the previous line + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + + +!mlb Leave this as it was until FLUSH get fixed. + WRITE (CU,'(''+'',A)') Str +! WRITE (CU,'(A)',ADVANCE='NO') CHAR( 13 )//' '//Str + + + + RETURN + END SUBROUTINE WrOver ! ( Str ) +!======================================================================= + SUBROUTINE WriteScr ( Str, Frm ) + + + ! This routine writes out a string to the screen. + + + IMPLICIT NONE + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + + + END SUBROUTINE WriteScr ! ( Str ) + +!======================================================================= + +!================================================================================================================================== + + +END MODULE SysSubs diff --git a/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe.f90 b/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe.f90 new file mode 100644 index 000000000..5f447efdb --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe.f90 @@ -0,0 +1,643 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ +! modified 8-Jan-2016 by B. Jonkman, NREL to conform to changes in FAST Modularization framework (added MiscVars) + +!********************************************************************************************************************************** +!> IceFloe is a set of routines that calculate ice floe loading on structures and is developed for +!! use with wind turbine aeroelastic simulation codes. +!! +!! User manual: +!! Theory manual: +!! +!! This particular file is the interface between the core IceFloe routines and the FAST Framework +!! +!! References: +!! +!! Gasmi, A., M. A. Sprague, J. M. Jonkman, and W. B. Jones, Numerical stability and accuracy of temporally coupled +!! multi-physics modules in wind turbine CAE tools. In proceedings of the 32nd ASME Wind Energy Symposium, 51st AIAA +!! Aerospace Sciences Meeting including the New Horizons Forum and Aerospace Exposition, Grapevine, TX, January 7-10, +!! 2013. Also published as NREL Report No. CP-2C00-57298. Available in pdf format at: +!! http://www.nrel.gov/docs/fy13osti/57298.pdf +! +!********************************************************************************************************************************** +MODULE IceFloe + + use IceFloe_Types + use IceInputParams + use IceCrushingISO + use IceCrushingIEC + use IceIntermittentCrushing + use IceFlexISO + use IceFlexIEC + use IceLockInCrushingISO + use randomCrushing + use IceCpldCrushing + use NWTC_IO, only : DispNVD + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', 'v1.01.01', '23-Jul-2016' ) + +! ..... Public Subroutines ................................................................................................... + + PUBLIC :: IceFloe_Init ! Initialization routine + PUBLIC :: IceFloe_End ! Ending routine (includes clean up) + + PUBLIC :: IceFloe_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: IceFloe_UpdateDiscState ! Tight coupling routine for updating discrete states + PUBLIC :: IceFloe_CalcOutput ! Routine for computing outputs + +! PUBLIC :: IceFloe_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual +! PUBLIC :: IceFloe_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + +CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceFloe_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +! +! 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. +! The initial states and initial guess for the input are defined. +!.................................................................................................................................. + + TYPE(IceFloe_InitInputType), INTENT( IN ) :: InitInp ! Input data from FAST for initialization routine + TYPE(IceFloe_InputType), INTENT( OUT) :: u ! An initial guess for the input + TYPE(IceFloe_ParameterType), INTENT( OUT) :: p ! Parameters + TYPE(IceFloe_OutputType), INTENT( OUT) :: y ! Initial system outputs (outputs are not calculated; + ! only the output mesh is initialized) + REAL(DbKi), INTENT(INOUT) :: Interval ! Coupling interval in seconds: the rate that + ! (1) IceFloe_UpdateStates() is called in loose coupling & + ! (2) IceFloe_UpdateDiscState() is called in tight coupling. + ! Input is the suggested time from the glue code; + ! Output is the actual coupling interval that will be used + ! by the glue code. + TYPE(IceFloe_InitOutputType), INTENT( OUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! Below are not currently used in IceFloe - dummy variables and stubbed routines are included however + TYPE(IceFloe_ContinuousStateType), INTENT( OUT) :: x ! Initial continuous states + TYPE(IceFloe_DiscreteStateType), INTENT( OUT) :: xd ! Initial discrete states + TYPE(IceFloe_ConstraintStateType), INTENT( OUT) :: z ! Initial guess of the constraint states + TYPE(IceFloe_OtherStateType), INTENT( OUT) :: OtherState ! Initial other states + TYPE(IceFloe_MiscVarType), INTENT( OUT) :: m ! Initial misc/optimization variables + +! More (unregistered) IceFloe types + type(iceInputType) :: iceInput ! hold list of input names and values from file + type(iceFloe_LoggingType) :: iceLog ! structure with message and error logging variables + character(132) :: logFile ! File name for message logging + +! Other local variables + REAL(ReKi) :: duration ! length of simulation in seconds + INTEGER(IntKi) :: nSteps ! number of steps in load time series + INTEGER(IntKi) :: numLdsOut ! number of load output points, could be numlegs or 1 for single load only + INTEGER(IntKi) :: Err ! for array allocation error + INTEGER(IntKi) :: n, numOuts + character(1) :: legNum ! for labeling leg numbers in output headers + + ErrStat = ErrID_None + ErrMsg = '' + + InitOut%Ver = IceFloe_Ver + p%initFlag = .false. + + ! dummy variables for the FAST framework: + ! (initialized to prevent compiler warnings about INTENT(OUT) variables) + x%DummyContStateVar = 0. + m%DummyMiscVar = 0 + OtherState%DummyOtherState = 0 + z%DummyConstrStateVar = 0.0_SiKi + xd%DummyDiscStateVar = 0.0_SiKi + + + ! Display the module information + CALL DispNVD( IceFloe_Ver ) + + logFile = trim(InitInp%RootName)//'.log' !BJJ: we decided output files should have two dots + +! Set up error logging + iceLog%warnFlag = .false. + iceLog%ErrID = ErrID_None + iceLog%ErrMsg = "" + + call openIceLog (iceLog, logFile) + if (iceLog%ErrID >= AbortErrLev) then ! Couldn't open the message logging fle, so this error won't be logged! + ErrStat = iceLog%ErrID + ErrMsg = 'Fatal error in routine: IceFloe_Init => '//trim(iceLog%ErrMsg) + return + endif + p%logUnitNum = iceLog%unitNum ! save for later use by updata routines + + call logMessage(iceLog, ' Running: '//trim(IceFloe_Ver%Name)//trim(IceFloe_Ver%Ver)//trim(IceFloe_Ver%Date)) + call logMessage(iceLog, ' This run started on: '//curdate()//' at '//curtime()//newLine) + +! bjj: check gravity (after log file initialized), and warn if it's different than the internal value: + IF ( .NOT. EqualRealNos(InitInp%Gravity, grav) ) THEN + call iceErrorHndlr (iceLog, ErrID_Warn, 'IceFloe_init: Gravity in FAST is different than gravity in iceFloe by '// & + TRIM(Num2LStr(InitInp%Gravity-grav))//' m/s^2.', 1) + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + if (iceLog%ErrID >= AbortErrLev) return + END IF + + + ! go through the inputs: first count them then read them into a structure + call countIceInputs(InitInp%inputFile, iceLog, iceInput) + call readIceInputs(iceLog, iceInput) + if (iceLog%ErrID >= AbortErrLev) then ! Couldn't open the parameter input fle + ErrStat = iceLog%ErrID + ErrMsg = 'Fatal error in routine: IceFloe_Init=> '//trim(iceLog%ErrMsg) + return + endif + call logMessage(iceLog, ' Parameter input file read finished.'//newLine) + + ! get selected input parameter + call getIceInput(iceInput, 'iceType',p%iceType, iceLog, lowTypeLimit, hiTypeLimit) + if (iceLog%ErrID >= AbortErrLev) then + ErrStat = iceLog%ErrID + ErrMsg = 'Error retrieving ice type from inputs in IceFloe_Init '//newLine//trim(iceLog%ErrMsg) + return + endif + + ! Get the time step from the ice input file + ! Do not use the interval from FAST as it may be too small resulting in large time series generation + ! IceFloe doesn't need fine resolution as frequencies are low. + ! Let FAST call as often as it likes, IceFloe will interpolate. + call getIceInput(iceInput, 'timeStep',p%dt, iceLog, 0.0_ReKi) + if (iceLog%ErrID >= AbortErrLev) then + ErrStat = iceLog%ErrID + ErrMsg = 'Error retrieving time step from inputs in IceFloe_Init '//newLine//trim(iceLog%ErrMsg) + return + endif + + ! get the simulation length from FAST + ! if the the length from FAST is zero read from iceFloe input file + if (InitInp%simLength <= 0) then + duration = InitInp%simLength + else + call getIceInput(iceInput, 'duration', duration, iceLog, 0.0_ReKi) + endif + call logMessage(iceLog, ' Load time series length = '//TRIM(Num2LStr(duration))//' sec') + + ! get the load ramp up time + call getIceInput(iceInput, 'rampTime', p%rampTime, iceLog, 0.1_ReKi) + call logMessage(iceLog, ' Load ramp up time = '//TRIM(Num2LStr(p%rampTime))//' sec') + if (iceLog%ErrID >= AbortErrLev) then + ErrStat = iceLog%ErrID + ErrMsg = 'Error retrieving ramp up time from inputs in IceFloe_Init, set to 10 sec. ' & + //newLine//trim(iceLog%ErrMsg) + p%rampTime = 10.0 + endif + p%rampTime = max(p%rampTime, 0.1_ReKi) + + ! get the number of legs on the support structure + call getIceInput(iceInput, 'numLegs', p%numLegs, iceLog, 1, 4) + if (iceLog%ErrID >= AbortErrLev) then + ErrStat = iceLog%ErrID + ErrMsg = 'Error retrieving simulation length or number of legs from ice input file '//newLine//trim(iceLog%ErrMsg) + return + endif + + ! allocate storage for load series + nSteps = ceiling(duration/p%dt) + 1 ! + 1 for zero point + allocate(p%loadSeries(nSteps, p%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in time series array allocation in IceFloe_init', 1) + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + return + endif + + ! allocate storage for the leg positions + allocate (p%legX(p%numLegs), stat=err) + allocate (p%legY(p%numLegs), stat=err) + allocate (p%ks(p%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Error in allocation of leg data in parameters', 1) + return ! error in array allocation + endif + p%legX = 0; p%legY = 0; ! these will be overwritten for a multi-leg model, otherwise remain zero + + iceType: select case (p%iceType) + case (randomCrush) + call initRandomCrushing(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' Random continuous ice crushing via ISO/Karna initialized'//newLine) + case (interCrush) + call initInterCrushing(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' Intermittent ice crushing loads initialized'//newLine) + case (crushIEC) + call initCrushingIEC(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' Ice crushing loads IEC/Korzhavin initialized'//newLine) + case (flexFailISO) + call initFlexISO(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' ISO/Croasdale ice flexural failure loads initialized'//newLine) + case (flexFailIEC) + call initFlexIEC(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' IEC/Ralston ice flexural failure loads initialized'//newLine) + case (lockInISO) + call initLockInCrushingISO(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' Frequency lock-in ice crushing loads via ISO initialized'//newLine) + case (cpldCrush) + call initCpldCrushing(iceInput, p, iceLog) + if (iceLog%ErrID <= ErrID_Warn) & + call logMessage(iceLog, newLine//' Coupled crushing ice loads (Maattanen) initialized'//newLine) + case default + call iceErrorHndlr(iceLog, ErrID_Fatal, 'Invalid ice type, '//TRIM(Num2LStr(p%IceType))//' is not a valid selection', 1) + end select iceType + + ! initialize mesh for tower/leg load point velocities for input to iceFloe + numLdsOut = p%numLegs + if (p%singleLoad) numLdsOut = 1 + CALL MeshCreate( BlankMesh = u%iceMesh & + ,IOS = COMPONENT_INPUT & + ,NNodes = numLdsOut & + ,TranslationVel = .TRUE. & + ,nScalars = 0 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + call iceErrorHndlr(iceLog, ErrStat, ErrMsg//' in IceFloe_init ', 1) + + do n = 1, numLdsOut + CALL MeshConstructElement ( Mesh = u%iceMesh & + , Xelement = ELEMENT_POINT & + , P1 = n & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + call iceErrorHndlr(iceLog, ErrStat, ErrMsg//' in IceFloe_init ', 1) + + CALL MeshPositionNode ( Mesh = u%iceMesh & + , INode = n & + , Pos = (/p%legX(n), p%legX(n), InitInp%MSL2SWL /) & ! Z is the height at water line + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + call iceErrorHndlr(iceLog, ErrStat, ErrMsg//' in IceFloe_init ', 1) + enddo + + CALL MeshCommit ( Mesh = u%iceMesh & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + call iceErrorHndlr(iceLog, ErrStat, ErrMsg//' in IceFloe_init ', 1) + +! Set up the mesh for load output from iceFloe + CALL MeshCopy ( SrcMesh = u%iceMesh & + , DestMesh = y%iceMesh & + , CtrlCode = MESH_SIBLING & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + call iceErrorHndlr(iceLog, ErrStat, ErrMsg//' in IceFloe_init ', 1) + + ! Assign initial values, all nodes and components at once + u%iceMesh%TranslationVel = 0.0 + y%iceMesh%Force = 0.0 + y%iceMesh%Moment = 0.0 + + + ! set up outputs to write to FAST + ! need to know how many legs and whethter loads applied to all or just one set of effective loads + numOuts = 4*p%numLegs ! 2 velocities and 2 forces + if (p%singleLoad .and. p%numLegs > 1) numOuts = 5 + CALL AllocAry( InitOut%WriteOutputHdr, numOuts, 'WriteOutputHdr', ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, 'Error in allocation of output header memory', 1) + if (ErrStat >= AbortErrLev) return + CALL AllocAry( InitOut%WriteOutputUnt, numOuts, 'WriteOutputUnt', ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, 'Error in allocation of output units memory', 1) + if (ErrStat >= AbortErrLev) return + CALL AllocAry( y%WriteOutput, numOuts, 'WriteOutput', ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, 'Error in allocation of output memory', 1) + if (ErrStat >= AbortErrLev) return + + if (p%numLegs == 1) then + InitOut%WriteOutputHdr = (/"VxTwrIce ", "VyTwrIce ", "IceLoadFx", "IceLoadFy"/) + InitOut%WriteOutputUnt = (/"m/s", "m/s", "kN ", "kN "/) + elseif (p%singleLoad) then + InitOut%WriteOutputHdr = (/"VxTwrIce ", "VyTwrIce ", "IceLoadFx", "IceLoadFy", "IceLoadMz"/) + InitOut%WriteOutputUnt = (/"m/s", "m/s", "kN ", "kN ", "kNm"/) !bjj: note that each string in the array must have the same number of characters so I added a space on the first two + else + do n = 1, p%numLegs + legNum = TRIM(Num2LStr(n)) + InitOut%WriteOutputHdr(4*n-3:4*n) = (/"VxIceLeg"//legNum, "VyIceLeg"//legNum, & + "FxIceLeg"//legNum, "FyIceLeg"//legNum/) + InitOut%WriteOutputUnt(4*n-3:4*n) = (/"m/s", "m/s", "kN ", "kN "/) + enddo + endif + + ! Let the user know if there have been warnings + if (iceLog%WarnFlag) then + call addMessage (iceLog, 'Warning message(s) in routine IceFloe_Init, please see the IceFloe log file') + endif + + ! return message and error logging data + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + + if (ErrStat <= ErrID_Warn) then + p%initFlag = .true. + y%WriteOutput = 0.0 + endif + +END SUBROUTINE IceFloe_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceFloe_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +! +! Routine for computing outputs, used in both loose and tight coupling. +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(IceFloe_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(IceFloe_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y ! Outputs computed at t (Input only so that mesh con- + ! nectivity information does not have to be recalculated) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! Below are not currently used in IceFloe - dummy variables and stubbed routines are included however + TYPE(IceFloe_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(IceFloe_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at t + TYPE(IceFloe_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(IceFloe_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + TYPE(IceFloe_MiscVarType), INTENT(INOUT) :: m ! misc/optimization variables + +! IceFloe specific types and other internal variables + type(iceFloe_LoggingType) :: iceLog ! structure with message and error logging variables + real(ReKi) :: loadVect(6,p%numLegs) + real(ReKi) :: inVels(2,p%numLegs) + integer(IntKi) :: nL, nSteps + + ! point internal iceFloe parameter array to load time series stored by FAST + nSteps = size(p%loadSeries,1) + +! Re-Set up error logging + iceLog%unitNum = p%logUnitNum + iceLog%warnFlag = .false. + iceLog%ErrID = ErrID_None + iceLog%ErrMsg = "" + +! Check for successful initialization + if (.not.p%initFlag) then + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Attempt to calculate ice loads without a successful initialization', 1) + return + endif + +! Map input point velocities to vectors for iceFloe + do nL = 1, p%numLegs + if (p%singleLoad) then + inVels(1,nL) = u%iceMesh%TranslationVel(1,1) + inVels(2,nL) = u%iceMesh%TranslationVel(2,1) + else + inVels(1,nL) = u%iceMesh%TranslationVel(1,nL) + inVels(2,nL) = u%iceMesh%TranslationVel(2,nL) + endif + enddo + +! get loads from IceFloe + iceType: select case (p%iceType) + case (randomCrush) + loadVect = outputRandomCrushLoad(p, iceLog, t) + case (crushIEC) + loadVect = outputCrushLoadIEC(p, iceLog, t) + case (interCrush) + loadVect = outputInterCrushLoad(p, iceLog, t) + case (flexFailISO) + loadVect = outputFlexLoadISO(p, iceLog, t) + case (flexFailIEC) + loadVect = outputFlexLoadIEC(p, iceLog, t) + case (lockInISO) + loadVect = outputLockInLoadISO(p, iceLog, t) + case (cpldCrush) + loadVect = outputCpldCrushLoad(p, iceLog, inVels, t) + case default ! this should have been caught during init but just in case + call iceErrorHndlr (iceLog, ErrID_Fatal, 'Invalid ice floe type, '//TRIM(Num2LStr(p%IceType))// & + ' is not a valid selection', 1) + end select iceType + + ! Apply a time ramp to the loads + loadVect = loadVect*min(1.0_DbKi, t/p%rampTime) + + ! Map the ice load vectors from IceFloe onto the output mesh + if (p%singleLoad) then + y%iceMesh%Force(:,1) = loadVect(1:3,1) + y%iceMesh%Moment(:,1) = loadVect(4:6,1) + y%WriteOutput(1) = inVels(1,1) + y%WriteOutput(2) = inVels(2,1) + y%WriteOutput(3) = 0.001*loadVect(1,1) + y%WriteOutput(4) = 0.001*loadVect(2,1) + if (p%numLegs > 1) y%WriteOutput(5) = 0.001*loadVect(6,1) + else + y%iceMesh%Force = loadVect(1:3,:) + y%iceMesh%Moment = loadVect(4:6,:) + do nL = 1, p%numLegs + y%WriteOutput(4*nL-3) = inVels(1,nL) + y%WriteOutput(4*nL-2) = inVels(2,nL) + y%WriteOutput(4*nL-1) = 0.001*loadVect(1,nL) + y%WriteOutput(4*nL) = 0.001*loadVect(2,nL) + enddo + endif + + ! Let the user know if there have been warnings + if (iceLog%WarnFlag) then + call addMessage (iceLog, 'Warning message(s) in routine IceFloe_Init, please see the IceFloe log file') + endif + + ! return message and error logging data + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + +END SUBROUTINE IceFloe_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceFloe_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +! +! This routine is called at the end of the simulation. +!.................................................................................................................................. + + TYPE(IceFloe_InputType), INTENT(INOUT) :: u ! System inputs + TYPE(IceFloe_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(IceFloe_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states + TYPE(IceFloe_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states + TYPE(IceFloe_ConstraintStateType), INTENT(INOUT) :: z ! Constraint states + TYPE(IceFloe_OtherStateType), INTENT(INOUT) :: OtherState ! Other states + TYPE(IceFloe_OutputType), INTENT(INOUT) :: y ! System outputs + TYPE(IceFloe_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 + + type(iceFloe_LoggingType) :: iceLog ! structure with message and error logging variables + +! Set up error logging + iceLog%unitNum = p%logUnitNum + iceLog%warnFlag = .false. + iceLog%ErrID = ErrID_None + iceLog%ErrMsg = "" + + ! Place any last minute operations or calculations here: + + ! Close files here: + + ! Destroy the input data: + + CALL IceFloe_DestroyInput( u, ErrStat, ErrMsg ) + + ! Destroy the parameter data: + + CALL IceFloe_DestroyParam( p, ErrStat, ErrMsg ) + + ! Destroy the state data: + + CALL IceFloe_DestroyContState( x, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + CALL IceFloe_DestroyDiscState( xd, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + CALL IceFloe_DestroyConstrState( z, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + CALL IceFloe_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + + CALL IceFloe_DestroyMisc( m, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + ! Destroy the output data: + + CALL IceFloe_DestroyOutput( y, ErrStat, ErrMsg ) + call iceErrorHndlr (iceLog, ErrStat, ErrMsg, 1) + + call logMessage(iceLog, newLine//' IceFloe run complete on: '//curdate()//' at '//curtime()) + + ! Let the user know if there have been warnings + if (iceLog%WarnFlag) then + call addMessage (iceLog, 'Warning message(s) in routine IceFloe_Init, please see the IceFloe log file') + endif + + ! return message and error logging data + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + + call closeIceLog(iceLog) + +END SUBROUTINE IceFloe_End + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceFloe_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +! +! Routine for solving for constraint states, integrating continuous states, and updating discrete states +! Constraint states are solved for input t; Continuous and discrete states are updated for t + p%dt +! (stepsize dt assumed to be in ModName parameter) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n ! Current simulation time step n = 0,1,... + TYPE(IceFloe_InputType), INTENT(IN ) :: u(:) ! Inputs at utimes + REAL(DbKi), INTENT(IN ) :: utimes(:) ! Times associated with u(:), in seconds + TYPE(IceFloe_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(IceFloe_ContinuousStateType), INTENT(INOUT) :: x ! Input: Continuous states at t; + ! Output: Continuous states at t + dt + TYPE(IceFloe_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + dt + TYPE(IceFloe_ConstraintStateType), INTENT(INOUT) :: z ! Input: Constraint states at t; + ! Output: Constraint states at t+dt + TYPE(IceFloe_OtherStateType), INTENT(INOUT) :: OtherState ! Input: Other states at t; + ! Output: Other states at t+dt + TYPE(IceFloe_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 + + ! local variables + +! TYPE(IceFloe_InputType) :: u_interp ! input interpolated from given u at utimes +! TYPE(IceFloe_ContinuousStateType) :: xdot ! continuous state time derivative + + type(iceFloe_LoggingType) :: iceLog ! structure with message and error logging variables + +! Set up error logging + iceLog%unitNum = p%logUnitNum + iceLog%warnFlag = .false. + iceLog%ErrID = ErrID_None + iceLog%ErrMsg = "" + + ! Update discrete states here: + +! xd%DummyContStateVar = 0.0 + + ! Let the user know if there have been warnings + if (iceLog%WarnFlag) then + call addMessage (iceLog, 'Warning message(s) in routine IceFloe_Init, please see the IceFloe log file') + endif + + ! return message and error logging data + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + +END SUBROUTINE IceFloe_UpdateStates + +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE IceFloe_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +! +! Routine for updating discrete states +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n ! Current step of the simulation: t = n*Interval + TYPE(IceFloe_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(IceFloe_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(IceFloe_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(IceFloe_DiscreteStateType), INTENT(INOUT) :: xd ! Input: Discrete states at t; + ! Output: Discrete states at t + Interval + TYPE(IceFloe_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(IceFloe_OtherStateType), INTENT(IN ) :: OtherState ! Other states at t + TYPE(IceFloe_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 + + type(iceFloe_LoggingType) :: iceLog ! structure with message and error logging variables + +! Set up error logging + iceLog%unitNum = p%logUnitNum + iceLog%warnFlag = .false. + iceLog%ErrID = ErrID_None + iceLog%ErrMsg = "" + +! Update discrete states here: + + xd%DummyDiscStateVar = 0.0 + + ! Let the user know if there have been warnings + if (iceLog%WarnFlag) then + call addMessage (iceLog, 'Warning message(s) in routine IceFloe_UpdateDiscState, please see the IceFloe log file') + endif + + ! return message and error logging data + ErrStat = iceLog%ErrID + ErrMsg = trim(iceLog%ErrMsg) + +END SUBROUTINE IceFloe_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE IceFloe + +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe_FASTRegistry.inp b/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe_FASTRegistry.inp new file mode 100644 index 000000000..362c9f02b --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/FAST/IceFloe_FASTRegistry.inp @@ -0,0 +1,77 @@ +################################################################################################################################## +# Registry for the DNV KEMA Ice Loading, creates MODULE IceFloe_Types +# Module IceFloe_Types contains all of the user-defined types needed in IceFloe. It also contains copy, destroy, pack, and +# unpack routines associated with each defined data types. +################################################################################################################################## +# Entries are of the form +# keyword <modulename/modname> <TypeBeingDefined> <FieldType> <FieldName> <Dims> <InitialValue> <Ctrl> "<DESCRIP>" "<UNITS>" +################################################################################################################################## + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef IceFloe InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef IceFloe InitInputType ReKi simLength - - - "Duration of simulation" sec +typedef ^ ^ ReKi MSL2SWL - - - "Offset between still-water level and mean sea level" m +typedef ^ ^ ReKi gravity - - - "Gravitational acceleration" "m/s^2" +typedef ^ ^ character(1024) RootName - - - "Output file root name" + +# Define outputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef IceFloe InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef IceFloe InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef IceFloe InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef IceFloe ContinuousStateType SiKi DummyContStateVar - - - "None currently used" - + +# Define discrete (nondifferentiable) states here: +typedef IceFloe DiscreteStateType SiKi DummyDiscStateVar - - - "None currently used" - + +# Define constraint states here: +typedef IceFloe ConstraintStateType SiKi DummyConstrStateVar - - - "None currently used" - + +# Define any other states, including integer or logical states here: +typedef IceFloe OtherStateType IntKi 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 IceFloe MiscVarType IntKi DummyMiscVar - - - "Remove this variable if you have misc/optimization 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 IceFloe ParameterType ReKi loadSeries {:}{:} - - - "precalculated time series of ice loads for each leg" N +typedef ^ ^ ^ iceVel - - - "ice floe velocity" m/s +typedef ^ ^ ^ iceDirection - - - "ice floe direction" degrees +typedef ^ ^ ^ minStrength - - - "minimum dynamic ice strength" Pa +typedef ^ ^ ^ minStrengthNegVel - - - "minimum dynamic ice strength for negative velocity" Pa +typedef ^ ^ ^ defaultArea - - - "structure width to use in cpld crushin" m +typedef ^ ^ ^ crushArea - - - "cross sectional area of ice against tower" m^2 +typedef ^ ^ ^ coeffStressRate - - - "coefficient to calc stress rate from relative vellocity" Pa/m +typedef ^ ^ ^ C(4) - - - "coefficient of cubic transition curve for negative stress rates" - +typedef ^ ^ ^ dt - - - "time step" sec +typedef ^ ^ ^ rampTime - - - "load ramp up time" sec +typedef ^ ^ ^ legX {:} - - - "x position of each leg relative to structure center" m +typedef ^ ^ ^ legY {:} - - - "y position of each leg relative to structure center" m +typedef ^ ^ ^ ks {:} - - - "shelter factor due to upstream leg" - +typedef ^ ^ IntKi numLegs - - - "Number of tower legs (=1 for monopile)" - +typedef ^ ^ IntKi iceType - - - "Type of ice Floe: flex, crush, etc." - +typedef ^ ^ IntKi logUnitNum - - - "Unit number for log file" +typedef ^ ^ Logical singleLoad - - - "Flag for load application at single point vs multiple legs" +typedef ^ ^ Logical initFlag - - - "Flag for successful initialization" + +# ..... Inputs .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef IceFloe InputType MeshType iceMesh - - - "Horizontal velocities on support structure leg(s) at water line" - + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef IceFloe OutputType MeshType iceMesh - - - "Horizontal forces and torsional moment(s) on support structure leg(s) at water line" - +typedef IceFloe OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" diff --git a/OpenFAST/modules/icefloe/src/interfaces/HAWC2/HAWC2_DLL.f90 b/OpenFAST/modules/icefloe/src/interfaces/HAWC2/HAWC2_DLL.f90 new file mode 100644 index 000000000..2389451f2 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/HAWC2/HAWC2_DLL.f90 @@ -0,0 +1,248 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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-06-24 10:28:50 -0700 (Tue, 24 Jun 2014) $ +! (File) Revision #: $Rev: 150 $ +! URL: $HeadURL: http://sel1004.verit.dnv.com:8080/svn/LoadSimCtl_SurfaceIce/trunk/IceDyn_IntelFortran/HAWC2_DLL/HAWC2_DLL.f90 $ +!********************************************************************************************************************************** + +! DLL to be linked with the HAWC2 Aeroelastic wind turbine simulation +! As a type 2 DLL per the user manual +module HAWC2DLL + + use IceLog + use IceInputParams + use iceFloeBase + use IceCrushingISO + use IceCrushingIEC + use IceIntermittentCrushing + use IceFlexISO + use IceFlexIEC + use IceLockInCrushingISO + use randomCrushing + use IceCpldCrushing + use NWTC_IO, only : DispNVD, progdesc, curdate, curtime + + TYPE(iceFloe_ParameterType), save :: icep ! Parameters, including precalculated time series + type(iceFloe_LoggingType),save :: theIceLog ! structure with message and error logging variables + +end module HAWC2DLL + + +subroutine icefloe_init (array1, array2) + +! Expose subroutine DLL to users of this DLL +!DEC$ ATTRIBUTES DLLEXPORT, C, ALIAS:'icefloe_init' :: icefloe_init + + use HAWC2DLL + + implicit none + + ! input + real(8), intent(IN) :: array1(1) + ! output + real(8), intent(OUT) :: array2(1) + + ! locals + Real(ReKi) :: duration + INTEGER(IntKi) :: nSteps + INTEGER(IntKi) :: Err ! Error status of the operation + LOGICAL, SAVE :: bInit = .FALSE. ! Initialization flag + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', 'v1.00.00', 'May-2014' ) + +! More IceFloe types + type(iceInputType) :: iceInput ! hold list of input names and values from file + character(132) :: logFile ! File name for message logging + + ! Initialise on first call + IF (.NOT.bInit) THEN + bInit = .TRUE. + ENDIF + +! Set up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + +! CALL NWTC_Init( ) + + ! Display the module information + + CALL DispNVD( IceFloe_Ver ) + + call openIceLog (theIceLog, 'IceFloe.log') + call logMessage(theIceLog, ' Running: '//trim(IceFloe_Ver%Name)//trim(IceFloe_Ver%Ver)//trim(IceFloe_Ver%Date)) + call logMessage(theIceLog, ' This run started on: '//curdate()//' at '//curtime()//newLine) + + call countIceInputs('testIce.inp', theIceLog, iceInput) + call readIceInputs(theIceLog, iceInput) + call logMessage(theIceLog, ' Input file read complete.'//newLine) + + ! call IceFloe initialization routine and get parameters back + ! not all parameters used by all ice floe types + call getIceInput(iceInput, 'iceType',icep%iceType, theIceLog, lowTypeLimit, hiTypeLimit) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + +! Set the time step as the minimum of the suggested p%dt and the time step from the ice input file + call getIceInput(iceInput, 'timeStep',icep%dt, theIceLog, 0.0) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + + ! get the duration of the simulation + call getIceInput(iceInput, 'duration', duration, theIceLog, 0.0) + call logMessage(theIceLog, ' Load time series duration = '//TRIM(Num2LStr(duration))//' sec') + + ! get the load ramp up time + call getIceInput(iceInput, 'rampTime', icep%rampTime, theIceLog, 0.0) + call logMessage(theIceLog, ' Load ramp up time = '//TRIM(Num2LStr(icep%rampTime))//' sec') + + ! get the number of legs on the support structure + call getIceInput(iceInput, 'numLegs', icep%numLegs, theIceLog, 1, 4) + if (theIceLog%ErrID >= AbortErrLev) then + return + endif + + ! allocate storage for load series + nSteps = ceiling(duration/icep%dt) + 1 ! + 1 for zero point + allocate(icep%loadSeries(nSteps, icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in time series array allocation in IceFloe_init', 1) + return + endif + ! point internal iceFloe array to the saved load series + ! icep%loadSeries => loadseries + + ! allocate storage for the leg positions + allocate (icep%legX(icep%numLegs), stat=err) + allocate (icep%legY(icep%numLegs), stat=err) + allocate (icep%ks(icep%numLegs), stat=err) + if (err /= 0) then + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Error in allocation of leg data in parameters', 1) + return ! error in array allocation + endif + icep%legX = 0.0 + icep%legY = 0.0 + icep%ks = 1.0 + + iceType: select case (icep%iceType) + case (randomCrush) + call initRandomCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Random continuous ice crushing via ISO/Karna initialized'//newLine) + case (interCrush) + call initInterCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Intermittent ice crushing loads initialized'//newLine) + case (crushIEC) + call initCrushingIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Ice crushing loads IEC/Korzhavin initialized'//newLine) + case (flexFailISO) + call initFlexISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' ISO/Croasdale ice flexural failure loads initialized'//newLine) + case (flexFailIEC) + call initFlexIEC(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' IEC/Ralston ice flexural failure loads initialized'//newLine) + case (lockInISO) + call initLockInCrushingISO(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Frequency lock-in ice crushing loads via ISO initialized'//newLine) + case (cpldCrush) + call initCpldCrushing(iceInput, icep, theIceLog) + if (theIceLog%ErrID <= ErrID_Warn) & + call logMessage(theIceLog, newLine//' Coupled crushing ice loads (Maattanen) initialized'//newLine) + case default + call iceErrorHndlr (theIceLog, ErrID_Fatal, 'Invalid ice floe type, ' & + //TRIM(Num2LStr(icep%IceType))//' is not a valid selection', 1) + end select iceType + + array2 = 0.0d0 + +end subroutine icefloe_init + + +SUBROUTINE icefloe_update(array1, array2) + +! Expose subroutine DLL to users of this DLL +!DEC$ ATTRIBUTES DLLEXPORT, C, ALIAS:'icefloe_update' :: icefloe_update + + use HAWC2DLL + + implicit none + ! input + real(8), intent(IN) :: array1(1+3*icep%numLegs) ! 1) Time, 2) Vx, 3) Vy, 4) Vz all in HAWC coords + ! output + real(8), intent(OUT) :: array2(2*icep%numLegs) ! Fx and Fy (in HAWC coords) + + REAL(DbKi) :: t ! Current simulation time in seconds + real(ReKi) :: loadVect(6,icep%numLegs) + real(ReKi) :: inVels(2,icep%numLegs) + integer(IntKi) :: nL + +! reset up error logging + theIceLog%warnFlag = .false. + theIceLog%ErrID = ErrID_None + theIceLog%ErrMsg = "" + + t = array1(1) + inVels = 0.0 +! HAWC has +y axis downwind, x lateral, z + down +! IceFloe has +x axis downwind, y lateral, z + up + do nL = 1, icep%numLegs + inVels(1,nL) = array1(3*nL) + inVels(2,nL) = array1(3*nL-1) + enddo + +! get loads from IceFloe + iceType: select case (icep%iceType) + case (randomCrush) + loadVect = outputRandomCrushLoad(icep, theIceLog, t) + case (crushIEC) + loadVect = outputCrushLoadIEC(icep, theIceLog, t) + case (interCrush) + loadVect = outputInterCrushLoad(icep, theIceLog, t) + case (flexFailISO) + loadVect = outputFlexLoadISO(icep, theIceLog, t) + case (flexFailIEC) + loadVect = outputFlexLoadIEC(icep, theIceLog, t) + case (lockInISO) + loadVect = outputLockInLoadISO(icep, theIceLog, t) + case (cpldCrush) + loadVect = outputCpldCrushLoad(icep, theIceLog, inVels, t) + case default + call logFatal (theIceLog, 'Invalid Ice Floe Type Selection', 1) + end select iceType + +!TODO deal w/ single point application +!Apply ramp for first 10 seconds + loadVect = loadVect*min(1.0, array1(1)/icep%rampTime) + do nL = 1, icep%numLegs + array2(2*nL-1) = dble(loadVect(2,nL))*min(1.0, 0.1*t) + array2(2*nL) = dble(loadVect(1,nL))*min(1.0, 0.1*t) + enddo + +end SUBROUTINE icefloe_update diff --git a/OpenFAST/modules/icefloe/src/interfaces/HAWC2/NWTC_IO_reduced.f90 b/OpenFAST/modules/icefloe/src/interfaces/HAWC2/NWTC_IO_reduced.f90 new file mode 100644 index 000000000..8a86d3212 --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/HAWC2/NWTC_IO_reduced.f90 @@ -0,0 +1,1003 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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 NWTC_IO + + + ! This module contains I/O-related variables and routines with non-system-specific logic. + ! A list of routines follows the data and type definitions. + + USE SysSubs + + IMPLICIT NONE + +!======================================================================= + + CHARACTER(20) :: ProgName = ' ' ! The name of the calling program. DO NOT USE THIS IN NEW PROGRAMS + CHARACTER(99) :: ProgVer ! The version (including date) of the calling program. DO NOT USE THIS IN NEW PROGRAMS + CHARACTER(1), PARAMETER :: Tab = CHAR( 9 ) ! The tab character. + + TYPE, PUBLIC :: ProgDesc + CHARACTER(24) :: Name + CHARACTER(99) :: Ver + CHARACTER(24) :: Date + END TYPE ProgDesc + + TYPE(ProgDesc), PARAMETER :: NWTC_Ver = ProgDesc( 'NWTC Subroutine Library', 'reduced_by_TMcCoy', '3-Dec-2013') ! The name, version, and date of the NWTC Subroutine Library. + + ! Create interface for a generic Num2LStr that actually uses specific routines. + + INTERFACE Num2LStr + MODULE PROCEDURE Int2LStr ! default integers + MODULE PROCEDURE R2LStr4 ! 4-byte reals + MODULE PROCEDURE R2LStr8 ! 8-byte reals + MODULE PROCEDURE R2LStr16 ! 16-byte reals + END INTERFACE + + ! Create interface for DispNVD so that we can pass in the name of the program + + INTERFACE DispNVD + MODULE PROCEDURE DispNVD0 ! No arguments. + MODULE PROCEDURE DispNVD1 ! Single argument of TYPE ProgDesc + MODULE PROCEDURE DispNVD2 ! Two arguments of TYPE character + END INTERFACE + +CONTAINS +!======================================================================= + FUNCTION GetNVD ( ProgInfo ) + + ! This function converts the three strings contained in the ProgDesc + ! data type into a single string listing the program name, + ! version, and release date. + + + ! Argument declarations. + + TYPE( ProgDesc ), INTENT(IN) :: ProgInfo ! Contains the name and version info + + + ! Function delcaration + + CHARACTER(200) :: GetNVD ! A single string containing the name, date, and version info + + + ! Print all the version info into a nice string: + + GetNVD = TRIM( ProgInfo%Name )//' ('//Trim( ProgInfo%Ver )//', '//Trim( ProgInfo%Date )//')' + + END FUNCTION GetNVD ! ( ProgInfo ) + +!======================================================================= + SUBROUTINE DispNVD0 + + + ! This routine displays the name of the program, its version, and its release date. + + + ! Print out program name, version, and date. + + CALL WrScr1 ( ' Running '//TRIM( ProgName )//' '//Trim( ProgVer )//'.' ) + + + RETURN + END SUBROUTINE DispNVD0 +!======================================================================= + SUBROUTINE DispNVD1 ( ProgInfo, DispNWTCVer ) + + + ! This routine displays the name of the program, its version, and its release date. + + + IMPLICIT NONE + TYPE( ProgDesc ), INTENT(IN) :: ProgInfo ! Contains the name and version info + LOGICAL,INTENT(IN),OPTIONAL :: DispNWTCVer ! Option to display what version of the library is linked with the code + + ! Print out program name, version, and date. + + ! As a special case, display the library version with the program version + IF ( PRESENT(DispNWTCVer) ) THEN + IF ( DispNWTCVer .AND. ProgInfo%Name /= NWTC_Ver%Name ) THEN + CALL WrScr1 ( ' Running '//TRIM( GetNVD( ProgInfo ) )//' linked with '//TRIM( GetNVD( NWTC_Ver ) )//'.' ) + RETURN + END IF + END IF + + CALL WrScr1 ( ' Running '//TRIM( GetNVD( ProgInfo ) )//'.' ) + + + RETURN + END SUBROUTINE DispNVD1 ! ( ProgInfo ) +!======================================================================= + SUBROUTINE DispNVD2 ( Name, Ver ) + + + ! This routine displays the name of the program, its version, and its release date passed in as strings + ! This routine is depricated and for legacy purposes only. Please don't use for any new code (Dec-2012) + + IMPLICIT NONE + CHARACTER(*), INTENT(IN) :: Name ! String containing the name of the program using the library + CHARACTER(*), INTENT(IN) :: Ver ! String containing the version and date info + + + ! Print out program name, version, and date. + + CALL WrScr1 ( ' Running '//TRIM( Name )//' ('//Trim( Ver )//').' ) + + + RETURN + END SUBROUTINE DispNVD2 ! ( Name, Ver ) +!======================================================================= + FUNCTION Int2LStr ( Intgr ) + + + ! This function returns a left-adjusted string representing the passed integer. + + + + CHARACTER(11) :: Int2LStr ! This function. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Intgr ! The integer to convert to a left-justified string. + + + + WRITE (Int2LStr,'(I11)') Intgr + + Int2Lstr = ADJUSTL( Int2LStr ) + + + RETURN + END FUNCTION Int2LStr ! ( Intgr ) +!======================================================================= + FUNCTION R2LStr4 ( FltNum ) + + ! This function converts a 4-byte floating point number to + ! a left-aligned string. It eliminates trailing zeroes + ! and even the decimal point if it is not a fraction. + + + ! Function declaration. + + CHARACTER(15) :: R2LStr4 ! This function. + + + ! Argument declarations. + + REAL(SiKi), INTENT(IN) :: FltNum ! The floating-point number to convert. + + + ! Return a 0 if that's what we have. + + IF ( FltNum == 0.0_SiKi ) THEN + R2LStr4 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + + WRITE (R2LStr4,'(1PG15.5)') FltNum + + CALL AdjRealStr( R2LStr4 ) + + + RETURN + END FUNCTION R2LStr4 ! ( FltNum ) +!======================================================================= + FUNCTION R2LStr8 ( FltNum ) + + ! This function converts a 8-byte floating point number to + ! a left-aligned string. It eliminates trailing zeroes + ! and even the decimal point if it is not a fraction. + + + ! Function declaration. + + CHARACTER(15) :: R2LStr8 ! This function. + + + ! Argument declarations. + + REAL(R8Ki), INTENT(IN) :: FltNum ! The floating-point number to convert. + + + ! Return a 0 if that's what we have. + + IF ( FltNum == 0.0_R8Ki ) THEN + R2LStr8 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + + WRITE (R2LStr8,'(1PG15.5)') FltNum + + CALL AdjRealStr( R2LStr8 ) + + + RETURN + END FUNCTION R2LStr8 ! ( FltNum ) +!======================================================================= + FUNCTION R2LStr16 ( FltNum ) + + ! This function converts a 16-byte floating point number to + ! a left-aligned string. It eliminates trailing zeroes + ! and even the decimal point if it is not a fraction. + + + ! Function declaration. + + CHARACTER(15) :: R2LStr16 ! This function. + + + ! Argument declarations. + + REAL(QuKi), INTENT(IN) :: FltNum ! The floating-point number to convert. + + + ! Return a 0 if that's what we have. + + IF ( FltNum == 0.0_QuKi ) THEN + R2LStr16 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + + WRITE (R2LStr16,'(1PG15.5)') FltNum + + CALL AdjRealStr( R2LStr16 ) + + + RETURN + END FUNCTION R2LStr16 ! ( FltNum ) + +!====================================================================== + SUBROUTINE AdjRealStr( NumStr ) + + ! This routine adjusts strings created from real numbers (4, 8, or 16-byte) + ! It removes leading spaces and trailing zeros. It is intended to be called + ! from routines R2LStr4, R2LStr8, and R2LStr16. + + CHARACTER(*), INTENT(INOUT) :: NumStr ! String representing a real number (e.g., from R2LStr4) + + ! Local declarations. + + INTEGER :: IC ! Character index. + + + NumStr = ADJUSTL( NumStr ) + + + ! Replace trailing zeros and possibly the decimal point with blanks. + ! Stop trimming once we find the decimal point or a nonzero. + + + ! Don't remove (important!) trailing zeros if they are in the exponent: + + IF (INDEX( NumStr, "E" ) > 0 ) RETURN + IF (INDEX( NumStr, "e" ) > 0 ) RETURN + + ! These are not in the exponent + + DO IC=LEN_TRIM( NumStr ),1,-1 + + IF ( NumStr(IC:IC) == '.' ) THEN + NumStr(IC:IC) = ' ' + RETURN + ELSE IF ( NumStr(IC:IC) /= '0' ) THEN + RETURN + END IF + + NumStr(IC:IC) = ' ' + + END DO ! IC + + + END SUBROUTINE AdjRealStr +!======================================================================= + RECURSIVE SUBROUTINE WrScr ( InStr ) + + + ! This routine writes out a string to the screen. + + + IMPLICIT NONE + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: InStr ! The input string to write to the screen. + + + ! Local declarations. + + INTEGER :: Beg ! The beginning of the next line of text. + INTEGER :: Indent ! The amunt to be indented. + INTEGER :: LStr ! The length of the remaining portion of the string. + INTEGER :: MaxLen ! Maximum number of columns to be written to the screen. + INTEGER :: NewLineIndx ! The string index where the NewLine character occurs + + CHARACTER(10) :: Frm ! Format specifier for the output. + CHARACTER(LEN(InStr)) :: Str ! The next string to be processed + + + + Str = InStr + + ! Check if we are writing multiple lines: + + NewLineIndx = INDEX( Str, NewLine, BACK=.TRUE. ) + IF ( NewLineIndx > 0 ) THEN ! The user requested a new line + IF ( NewLineIndx == 1 ) THEN ! The first character is a new line, so write a blank line + CALL WrScr( '' ) + ELSE + CALL WrScr( Str(:NewLineIndx-1) ) ! Write everything up to the new line (recursively) + END IF + Str = Str( (NewLineIndx + LEN(NewLine)): ) ! Remove the part we already wrote to the screen (also remove the NewLine character) + END IF + + + ! Find the amount of indent. Create format. + + MaxLen = MaxWrScrLen + Indent = LEN_TRIM( Str ) - LEN_TRIM( ADJUSTL( Str ) ) + Indent = MIN( Indent, MaxLen-2 ) ! at least 2 characters per line + MaxLen = MaxLen - Indent + IF ( Indent > 0 ) THEN + Frm = '(1X, X,A)' + WRITE (Frm(5:6),'(I2)') Indent + ELSE + Frm = '(1X,A)' + END IF + + + ! Break long messages into multiple lines. + + Beg = Indent + 1 + LStr = LEN_TRIM( Str(Beg:) ) + + + + DO WHILE ( Lstr > MaxLen ) + + CALL FindLine ( Str(Beg:) , MaxLen , LStr ) + + CALL WriteScr( TRIM( ADJUSTL( Str(Beg:Beg+LStr-1) ) ), Frm ) + + Beg = Beg + LStr + + + ! If we have a space at the beginning of the string, let's get rid of it + + DO WHILE ( Beg < LEN_TRIM( Str ) .AND. Str(Beg:Beg) == ' ' ) + Beg = Beg + 1 + ENDDO + + LStr = LEN_TRIM( Str(Beg:) ) + + ENDDO + + CALL WriteScr( TRIM( ADJUSTL( Str(Beg:Beg+LStr-1) ) ), Frm ) + + + RETURN + END SUBROUTINE WrScr ! ( Str ) +!======================================================================= + SUBROUTINE WrScr1 ( Str ) + + + ! This routine writes out a string to the screen after a blank line. + ! This routine is DEPRECATED. Call WrScr directly instead. + + + ! Argument declarations. + + CHARACTER(*) :: Str ! The string to print. + + + + !CALL WrScr ( ' ' ) + !CALL WrScr ( TRIM( Str ) ) + + CALL WrScr( NewLine//TRIM( Str ) ) + + + RETURN + END SUBROUTINE WrScr1 ! ( Str ) +!======================================================================= + SUBROUTINE GetNewUnit ( UnIn, ErrStat, ErrMsg ) + + ! This routine returns a unit number not currently in use. + + + ! Argument declarations. + + INTEGER, INTENT(OUT) :: UnIn ! Logical unit for the file. + INTEGER(IntKi), INTENT(OUT), OPTIONAL :: ErrStat ! The error status code; If not present code aborts + CHARACTER(*), INTENT(OUT), OPTIONAL :: ErrMsg ! The error message, if an error occurred + + + ! Local declarations. + + INTEGER :: Un ! Unit number + LOGICAL :: Opened ! Flag indicating whether or not a file is opened. + INTEGER(IntKi), PARAMETER :: StartUnit = 10 ! Starting unit number to check (numbers less than 10 reserved) + INTEGER(IntKi), PARAMETER :: MaxUnit = 99 ! The maximum unit number available (or 10 less than the number of files you want to have open at a time) + CHARACTER(300) :: Msg ! Temporary error message + + + ! Initialize subroutine outputs + + Un = StartUnit + + IF ( PRESENT( ErrStat ) ) ErrStat = ErrID_None + IF ( PRESENT( ErrMsg ) ) ErrMsg = '' + + ! See if unit is connected to an open file. Check the next largest number until it is not opened. + + DO + + INQUIRE ( UNIT=Un , OPENED=Opened ) + + IF ( .NOT. Opened ) EXIT + Un = Un + 1 + + IF ( Un > MaxUnit ) THEN + + Msg = 'GetNewUnit() was unable to find an open file unit specifier between '//TRIM(Num2LStr(StartUnit)) & + //' and '//TRIM(Num2LStr(MaxUnit))//'.' + + IF ( PRESENT( ErrStat ) ) THEN + ErrStat = ErrID_Severe + IF ( PRESENT( ErrMsg) ) ErrMsg = Msg + ELSE + CALL ProgAbort( Msg ) + END IF + + EXIT ! stop searching now + + END IF + + + END DO + + UnIn = Un + + RETURN + END SUBROUTINE GetNewUnit ! ( UnIn [, ErrStat] [, ErrMsg] ) +!======================================================================= + SUBROUTINE Conv2UC ( Str ) + + + ! This routine converts all the text in a string to upper case. + + + ! Argument declarations. + + CHARACTER(*), INTENT(INOUT) :: Str ! The string to be converted to UC. + + + ! Local declarations. + + INTEGER :: IC ! Character index + + + + DO IC=1,LEN_TRIM( Str ) + + IF ( ( Str(IC:IC) >= 'a' ).AND.( Str(IC:IC) <= 'z' ) ) THEN + Str(IC:IC) = CHAR( ICHAR( Str(IC:IC) ) - 32 ) + ELSE + Str(IC:IC) = Str(IC:IC) + END IF + + END DO ! IC + + + RETURN + END SUBROUTINE Conv2UC ! ( Str ) +!======================================================================= + SUBROUTINE OpenFInpFile ( Un, InFile, ErrStat, ErrMsg ) + + + ! This routine opens a formatted input file. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER(IntKi), INTENT(OUT),OPTIONAL:: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT),OPTIONAL:: ErrMsg ! Error message + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + LOGICAL :: Exists ! Flag indicating whether or not a file Exists. + CHARACTER(1024) :: Msg ! Temporary error message + + + ! See if input file Exists. + + INQUIRE ( FILE=TRIM( InFile ) , EXIST=Exists ) + + IF ( .NOT. Exists ) THEN + + Msg = 'The input file, "'//TRIM( InFile )//'", was not found.' + + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + IF ( PRESENT(ErrMsg) ) ErrMsg = Msg + ELSE + CALL ProgAbort ( ' '//TRIM(Msg) ) + END IF + + ELSE + + ! Open input file. Make sure it worked. + + OPEN( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='FORMATTED', IOSTAT=IOS, ACTION='READ' ) + + IF ( IOS /= 0 ) THEN + + Msg = 'Cannot open file "'//TRIM( InFile )//'". Another program like MS Excel may have locked it for writing.' + + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + IF ( PRESENT(ErrMsg) ) ErrMsg = Msg + ELSE + CALL ProgAbort ( ' '//TRIM(Msg) ) + END IF + + ELSE + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + IF ( PRESENT(ErrMsg ) ) ErrMsg = "" + + END IF + + END IF + + + RETURN + END SUBROUTINE OpenFInpFile ! ( Un, InFile [, ErrStat] [, ErrMsg] ) +!======================================================================= + SUBROUTINE OpenFOutFile ( Un, OutFile, ErrStat, ErrMsg ) + + + ! This routine opens a formatted output file. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un ! Logical unit for the output file. + CHARACTER(*), INTENT(IN) :: OutFile ! Name of the output file. + + INTEGER(IntKi), INTENT(OUT), OPTIONAL :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT), OPTIONAL :: ErrMsg ! Error message + + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN + CHARACTER(1024) :: Msg ! Temporary error message + + + ! Open output file. Make sure it worked. + + OPEN( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + + + IF ( IOS /= 0 ) THEN + + Msg = 'Cannot open file "'//TRIM( OutFile )//'". Another program like MS Excel may have locked it for writing.' + + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = Msg + ELSE + CALL ProgAbort( ' '//Msg ) + END IF + + ELSE + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + IF ( PRESENT(ErrMsg) ) ErrMsg = "" + END IF + + + RETURN + END SUBROUTINE OpenFOutFile ! ( Un, OutFile [, ErrStat] [, ErrMsg] ) +!======================================================================= + SUBROUTINE WaitTime ( WaitSecs ) + + + ! This routine pauses program executaion for a specified + ! number of seconds. + + + IMPLICIT NONE + + + ! Argument declarations: + + REAL(ReKi), INTENT(IN) :: WaitSecs ! The number of seconds to wait. + + + ! Local declarations: + + REAL(ReKi) :: EndCounts ! The number of counts when wait time is over. + + INTEGER :: Counts ! Current number of counts on the system clock. + INTEGER :: CountMax ! Maximum number of counts possible on the system clock. + INTEGER :: CountRate ! Number of counts per second on the system clock. + + + + CALL SYSTEM_CLOCK ( Counts, CountRate, CountMax ) + EndCounts = Counts + INT( WaitSecs*CountRate ) + + DO + CALL SYSTEM_CLOCK ( Counts, CountRate, CountMax ) + IF ( Counts > EndCounts ) EXIT + END DO + + + RETURN + END SUBROUTINE WaitTime ! ( Seconds ) +!======================================================================= + SUBROUTINE ProgPause() + + + ! This routine pauses the program. + + + + CALL WrScr ( ' Hit the <Enter> key to continue.' ) + + READ (*,'()') + + + RETURN + END SUBROUTINE ProgPause +!======================================================================= + SUBROUTINE ProgWarn ( Message ) + + + ! This routine outputs non-fatal warning messages and returns to the calling routine. + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Message ! Warning message. + + + + CALL WrScr ( ' WARNING: '//Message ) + + + RETURN + END SUBROUTINE ProgWarn ! ( Message ) +!======================================================================= + SUBROUTINE ProgAbort ( Message, TrapErrors, TimeWait, ErrLevel ) + + + ! This routine outputs fatal error messages and stops the program. + + + ! Argument declarations. + + REAL(ReKi), INTENT(IN), OPTIONAL :: TimeWait ! Tells whether to wait for TimeWait s, or pause if <0. + + INTEGER(IntKi), INTENT(IN), OPTIONAL :: ErrLevel ! The error level to report to the OS. + + LOGICAL, INTENT(IN), OPTIONAL :: TrapErrors ! Determines if the program should abort or return to calling function + + CHARACTER(*), INTENT(IN) :: Message ! Error message. + + + + CALL WrScr ( Message ) + IF ( PRESENT(TrapErrors) ) THEN + IF ( TrapErrors ) RETURN + END IF + + IF ( LEN_TRIM(ProgName) > 0 ) THEN + CALL WrScr1 ( ' Aborting '//TRIM( ProgName )//'.' ) + ELSE + CALL WrScr1 ( ' Aborting program.' ) + END IF + CALL WrScr ( '' ) + + ! Do we pause (<0), proceed (=0), or wait (>0)? + + IF ( PRESENT( TimeWait ) ) THEN + IF ( ( TimeWait < 0.0 ) .AND. KBInputOK ) THEN + CALL ProgPause + ELSE IF ( TimeWait > 0.0 ) THEN + CALL WaitTime( TimeWait ) + END IF + END IF + + + ! Do we report a specific error level to the OS or use the default of 1? + + IF ( PRESENT( ErrLevel ) ) THEN + CALL ProgExit ( ErrLevel ) + ELSE + CALL ProgExit ( 1 ) + END IF + + + END SUBROUTINE ProgAbort ! ( Message [, TrapErrors, TimeWait, ErrLevel] ) +!======================================================================= + FUNCTION CurDate( ) + + + ! This function returns a character string encoded with the date in the form dd-mmm-ccyy. + + + ! Function declaration. + + CHARACTER(11) :: CurDate ! This function + + + ! Local declarations. + + CHARACTER(8) :: CDate ! String to hold the returned value from the DATE_AND_TIME subroutine call. + + + + ! Call the system date function. + + CALL DATE_AND_TIME ( CDate ) + + + ! Parse out the day. + + CurDate(1:3) = CDate(7:8)//'-' + + + ! Parse out the month. + + SELECT CASE ( CDate(5:6) ) + CASE ( '01' ) + CurDate(4:6) = 'Jan' + CASE ( '02' ) + CurDate(4:6) = 'Feb' + CASE ( '03' ) + CurDate(4:6) = 'Mar' + CASE ( '04' ) + CurDate(4:6) = 'Apr' + CASE ( '05' ) + CurDate(4:6) = 'May' + CASE ( '06' ) + CurDate(4:6) = 'Jun' + CASE ( '07' ) + CurDate(4:6) = 'Jul' + CASE ( '08' ) + CurDate(4:6) = 'Aug' + CASE ( '09' ) + CurDate(4:6) = 'Sep' + CASE ( '10' ) + CurDate(4:6) = 'Oct' + CASE ( '11' ) + CurDate(4:6) = 'Nov' + CASE ( '12' ) + CurDate(4:6) = 'Dec' + END SELECT + + + ! Parse out the year. + + CurDate(7:11) = '-'//CDate(1:4) + + + RETURN + END FUNCTION CurDate ! () +!======================================================================= + FUNCTION CurTime( ) + + + ! This function returns a character string encoded with the time in the form "hh:mm:ss". + + + ! Function declaration. + + CHARACTER(8) :: CurTime ! This function. + + + ! Local declarations. + + CHARACTER(10) :: CTime ! String to hold the returned value from the DATE_AND_TIME subroutine call. + + + + CALL DATE_AND_TIME ( TIME=CTime ) + + CurTime = CTime(1:2)//':'//CTime(3:4)//':'//CTime(5:6) + + + RETURN + END FUNCTION CurTime ! () +!======================================================================= + SUBROUTINE FindLine ( Str , MaxLen , StrEnd ) + + + ! This routine finds one line of text with a maximum length of MaxLen from the Str. + ! It tries to break the line at a blank. + + + IMPLICIT NONE + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: MaxLen ! The maximum length of the string. + INTEGER, INTENT(OUT) :: StrEnd ! The location of the end of the string. + + CHARACTER(*), INTENT(IN) :: Str ! The string to search. + + + ! Local declarations: + + INTEGER IC + + + + StrEnd = MaxLen + + IF ( LEN_TRIM( Str ) > MaxLen ) THEN + + IC = INDEX( Str(1:MaxLen), ' ', BACK = .TRUE. ) ! Find the last space in the line + + IF ( IC > 1 ) THEN ! We don't want to return just one character that's a space, or do we? + + StrEnd = IC-1 ! StrEnd > 0 + DO WHILE ( Str(StrEnd:StrEnd) == ' ' ) + StrEnd = StrEnd - 1 + IF ( StrEnd <= 0 ) THEN ! This occurs if everything before IC is a space + StrEnd = IC + EXIT + ENDIF + ENDDO + + ENDIF ! IC > 1 + + ENDIF ! LEN_TRIM( Str ) > MaxLen + + + RETURN + END SUBROUTINE FindLine ! ( Str , MaxLen , StrEnd ) +!======================================================================= + SUBROUTINE NameOFile ( InArg, OutExten, OutFile, ErrStat ) + + + ! Get the name of the input file from the InArgth command-line argument. + ! Remove the extension if there is one, and append OutExten to the end. + + + ! Argument declarations. + + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat ! Error status; if present, program does not abort on error + INTEGER, INTENT(IN) :: InArg ! The number of the command-line argument that should hold the input file name. + + CHARACTER(*), INTENT(IN) :: OutExten ! The requested extension for the output file. + CHARACTER(*), INTENT(OUT) :: OutFile ! The name of the output file. + + + ! Local declarations. + + CHARACTER(100) :: InFile ! The name of the input file. + CHARACTER(100) :: RootName ! The root name of the input file. + + + + ! See if the command line has enough arguments. + + IF ( InArg > COMMAND_ARGUMENT_COUNT() ) THEN + CALL ProgAbort ( 'Insufficient arguments on the command line (at least '//& + TRIM( Int2LStr( InArg ) )//' were expected).', PRESENT(ErrStat) ) + IF ( PRESENT( ErrStat ) ) ErrStat = 1 + RETURN + END IF + + + ! Get the root of the input file name (strip off the extension). + + CALL GET_COMMAND_ARGUMENT( InArg, InFile ) + CALL GetRoot ( TRIM( InFile ), RootName ) + + OutFile = TRIM( RootName )//'.'//OutExten + + IF ( PRESENT( ErrStat ) ) ErrStat = 0 + + RETURN + END SUBROUTINE NameOFile ! ( InArg, OutExten, OutFile [, ErrStat]) +!======================================================================= + SUBROUTINE GetRoot ( GivenFil, RootName ) + + + ! Let's parse the root file name from the name of the given file. + ! We'll count everything after the last period as the extension. + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: GivenFil ! The name of the given file. + CHARACTER(*), INTENT(OUT) :: RootName ! The parsed root name of the given file. + + + ! Local declarations. + + INTEGER :: I ! DO index for character position. + + + + ! Deal with a couple of special cases. + + IF ( ( TRIM( GivenFil ) == "." ) .OR. ( TRIM( GivenFil ) == ".." ) ) THEN + RootName = TRIM( GivenFil ) + RETURN + END IF + + + ! More-normal cases. + + DO I=LEN_TRIM( GivenFil ),1,-1 + + + IF ( GivenFil(I:I) == '.' ) THEN + + + IF ( I < LEN_TRIM( GivenFil ) ) THEN ! Make sure the index I is okay + IF ( INDEX( '\/', GivenFil(I+1:I+1)) == 0 ) THEN ! Make sure we don't have the RootName in a different directory + RootName = GivenFil(:I-1) + ELSE + RootName = GivenFil ! This does not have a file extension + END IF + ELSE + IF ( I == 1 ) THEN + RootName = '' + ELSE + RootName = GivenFil(:I-1) + END IF + END IF + + RETURN + + END IF + END DO ! I + + RootName = GivenFil + + + RETURN + END SUBROUTINE GetRoot ! ( GivenFil, RootName ) + + +END MODULE NWTC_IO diff --git a/OpenFAST/modules/icefloe/src/interfaces/IceFloe_Test.f90 b/OpenFAST/modules/icefloe/src/interfaces/IceFloe_Test.f90 new file mode 100644 index 000000000..540bd0cba --- /dev/null +++ b/OpenFAST/modules/icefloe/src/interfaces/IceFloe_Test.f90 @@ -0,0 +1,168 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014 DNV KEMA Renewables, Inc. +! +! This file is part of the IceFloe suite of subroutines +! +! 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. +!************************************************************************ +! modified 8-Jan-2016 by B. Jonkman, NREL to conform to changes in FAST Modularization framework (added MiscVars) + +!********************************************************************************************************************************** +! File last committed: $Date$ +! (File) Revision #: $Rev$ +! URL: $HeadURL$ +!********************************************************************************************************************************** + +! Test calling program for IceFloe + +program main + +! rename some things to avoid conflicts + use IceFloe_Types, dum1=>errID_none, dum2=>aborterrlev, dum3=>errID_warn, dum4=>errID_fatal, dum5=>newline + use IceFloe + use IceInputParams + implicit none + + TYPE(IceFloe_InitInputType) :: InitInp ! Input data from FAST for initialization routine + TYPE(IceFloe_InputType) :: u(1) ! An initial guess for the input + TYPE(IceFloe_ParameterType) :: p ! Parameters + TYPE(IceFloe_OutputType) :: y ! Initial system outputs (outputs are not calculated; + TYPE(IceFloe_InitOutputType) :: InitOut ! Output for initialization routine + INTEGER(IntKi) :: ErrStat = ErrID_None ! Error status of the operation + CHARACTER(1024) :: ErrMsg = "" ! Error message if ErrStat /= ErrID_None + REAL(DbKi) :: Interval ! Coupling interval in seconds: the rate that + integer(IntKi) :: outUnitNum + +! Below are not currently used in IceFloe - dummy variables and stubbed routines are included however + TYPE(IceFloe_ContinuousStateType) :: x ! Initial continuous states + TYPE(IceFloe_DiscreteStateType) :: xd ! Initial discrete states + TYPE(IceFloe_ConstraintStateType) :: z ! Initial guess of the constraint states + TYPE(IceFloe_OtherStateType) :: OtherState ! Initial other states + TYPE(IceFloe_MiscVarType) :: m ! misc/optimization variables + + character(132) :: outFile + integer(IntKi) :: n, i, numArg, nSteps, nL + real(ReKi) :: pos = 0.0 + real(ReKi) :: lenTime + + numArg = COMMAND_ARGUMENT_COUNT() + if (numArg > 0) then + CALL GET_COMMAND_ARGUMENT( 1, InitInp%InputFile ) + else + InitInp%InputFile = 'testIce.inp' + endif + + write(*,*) ' Initializing IceFloe...' + +! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + + InitInp%rootname = InitInp%InputFile + call IceFloe_Init( InitInp, u(1), p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) then + call progAbort( ErrMsg ) + stop + elseif (ErrStat == ErrID_Warn) then + call progWarn( ErrMsg ) + endif + + call GetRoot( InitInp%InputFile, outFile ) + outFile = trim(outFile)//'.plt' + call OpenFOutFile ( outUnitNum, outFile ) + + pos = 0.0 + + nSteps = size(p%loadSeries,1) + if(p%iceType == 5) nSteps = floor(600.0/p%dt) + write(*,*) ' Now time marching' + + nL = p%numLegs + if (p%singleLoad) nL = 1 + do i = 0, nSteps-1 + call IceFloe_CalcOutput( dble(i)*p%dt, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) then + write(*,*) ErrMsg + stop + endif + write(outUnitNum,'(1x,10(1pe12.5,A))') sngl(i)*p%dt, TAB, pos, TAB, u(1)%iceMesh%TranslationVel(1,1), & + TAB, y%writeoutput(1), TAB, y%writeoutput(2) +! (TAB, y%iceMesh%Force(1,n), TAB, y%iceMesh%Force(2,n), TAB, y%iceMesh%Moment(3,n), n = 1,nL) + if(p%iceType == 5) call sdof(sngl(p%dt), y%iceMesh%Force(1,1), pos, u(1)%iceMesh%TranslationVel(1,1)) + enddo + + write(*,*) ' Wrap up' + + call IceFloe_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + +end program main + +! single degree of system integrated via 4th order RK +subroutine sdof (dt, F, pos, vel) + use precision + implicit none + real(ReKi), intent(in) :: dt, F + real(ReKi), intent(out) :: pos, vel + real(ReKi), save :: x = 0.0 + real(ReKi), save :: xd = 0.0 + real(ReKi), save :: xdd = 0.0 + real(ReKi) :: k11, k12, k13, k14 + real(ReKi) :: k21, k22, k23, k24 + real(ReKi), save :: rampForce = 0.0 + + +! From NREL 5MW monopile in 25m depth (Carbon Trust) + real(ReKi), parameter :: mass = 10.6E6 + real(ReKi), parameter :: stiff = 30.0E6 +! Tom's example +! real(ReKi), parameter :: mass = 166000.0 +! real(ReKi), parameter :: stiff = 1.5E9 + real(ReKi), parameter :: damp = 0.01 + real(ReKi), save :: wn + + wn = sqrt(stiff/mass) + +! Ramp up the force + rampForce = (dt/0.1)*F + (1.0-dt/0.1)*rampForce + +! first integrate xdd (acceleration) + pos = x + vel = xd + + k11 = rampForce/mass - wn*wn*x - 2.0*damp*wn*xd + k21 = xd + x = pos + 0.5*dt*k21 + xd = vel + 0.5*dt*k11 + + k12 = rampForce/mass - wn*wn*x - 2.0*damp*wn*xd + k22 = xd + x = pos + 0.5*dt*k22 + xd = vel + 0.5*dt*k12 + + k13 = rampForce/mass - wn*wn*x - 2.0*damp*wn*xd + k23 = xd + x = pos + 0.5*dt*k23 + xd = vel + 0.5*dt*k13 + + k14 = rampForce/mass - wn*wn*x - 2.0*damp*wn*xd + k24 = xd + + pos = pos + dt*(k21 + 2.0*k22 + 2.0*k23 + k24)/6.0 + vel = vel + dt*(k11 + 2.0*k12 + 2.0*k13 + k14)/6.0 + x = pos + xd = vel + +end subroutine sdof + +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/icefloe/test/GLA_Proto_flex_ISO.inp b/OpenFAST/modules/icefloe/test/GLA_Proto_flex_ISO.inp new file mode 100644 index 000000000..858ebecd0 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_Proto_flex_ISO.inp @@ -0,0 +1,58 @@ +! Ice flexural failure per ISO test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.10 +rampTime 1.0 +duration 600.0 +randomSeed 123 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +numLegs 1.0 +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +singleLoad 1 +shelterFactor_ks 0.0 +! +! Inputs common to loading by ice flexural failure +! +ice2twrFriction 0.15 +includeHb 1 +includeHr 1 +! +! Inputs for ice flexural failure via ISO method (Croasdale) +! +iceType 6 +rubblePorosity 0.30 +rubbleCohesion 0.00 +rubbleAngle 40.0 +frictionAngle 45.0 +ice2iceFriction 0.05 +poissonRatio 0.30 +peakLoadCOV 0.20 +coeffLoadPeaks 0.56 +coeffLoadMin 0.10 +periodCOV 0.50 +tauMin 0.60 +tauMax 0.60 +riseTime 0.80 +coeffBreakLength 4.00 +includeHp 1 +includeHl 1 +includeHt 1 +includeLc 1 diff --git a/OpenFAST/modules/icefloe/test/GLA_Proto_intercrush_ISO.inp b/OpenFAST/modules/icefloe/test/GLA_Proto_intercrush_ISO.inp new file mode 100644 index 000000000..98f67000f --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_Proto_intercrush_ISO.inp @@ -0,0 +1,39 @@ +! Ice intermittent crushing per ISO test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.1 +rampTime 1.0 +duration 600.0 +randomSeed 123 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +numLegs 1.0 +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +singleLoad 1 +shelterFactor_ks 0.0 +! +! Inputs for intermittent crushing +! +iceType 2 +refIceThick 1.0 +staticExponent -0.16 +interPeriod 6.0 +riseTime 0.5 +fallTime 0.15 diff --git a/OpenFAST/modules/icefloe/test/GLA_Proto_lockin_ISO.inp b/OpenFAST/modules/icefloe/test/GLA_Proto_lockin_ISO.inp new file mode 100644 index 000000000..1cf9dc841 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_Proto_lockin_ISO.inp @@ -0,0 +1,41 @@ +! Ice lock-in crushing per ISO test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.1 +rampTime 1.0 +duration 600.0 +randomSeed 123 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +numLegs 1.0 +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +singleLoad 1 +shelterFactor_ks 0.0 +! +! Inputs for lock-in crushing +! +iceType 3 +refIceThick 1.0 +staticExponent -0.16 +riseTime 0.80 +minLoadFraction 0.60 +modalAmpl 1.0 +modalMass 1000000.0 +dampConst 40000000.0 diff --git a/OpenFAST/modules/icefloe/test/GLA_Proto_randomcrush_ISO.inp b/OpenFAST/modules/icefloe/test/GLA_Proto_randomcrush_ISO.inp new file mode 100644 index 000000000..915dc0320 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_Proto_randomcrush_ISO.inp @@ -0,0 +1,41 @@ +! Ice continuous random crushing per ISO test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.1 +duration 600.0 +randomSeed 123 +rampTime 0.01 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +numLegs 1.0 +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +singleLoad 1 +shelterFactor_ks 0.0 +! +! Inputs for random continuous crushing ISO +! +iceType 1 +refIceThick 1.0 +staticExponent -0.16 +coeffPSD_b 1.34 +coeffPSD_ks 3.24 +crushLoadCOV 0.25 +stdLoadMult 4.0 +freqStep 0.001 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.dat b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.dat new file mode 100644 index 000000000..f20ea45f4 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 2.85560E+05 + 2.00000E-01 5.75817E+05 + 3.00000E-01 8.70756E+05 + 4.00000E-01 1.17036E+06 + 5.00000E-01 1.47460E+06 + 6.00000E-01 1.78345E+06 + 7.00000E-01 2.09687E+06 + 8.00000E-01 2.41482E+06 + 9.00000E-01 2.73725E+06 + 1.00000E+00 3.06410E+06 + 1.10000E+00 3.08665E+06 + 1.20000E+00 3.10903E+06 + 1.30000E+00 3.13121E+06 + 1.40000E+00 3.15320E+06 + 1.50000E+00 3.17496E+06 + 1.60000E+00 3.19650E+06 + 1.70000E+00 3.21779E+06 + 1.80000E+00 3.23882E+06 + 1.90000E+00 3.25958E+06 + 2.00000E+00 3.28005E+06 + 2.10000E+00 3.30023E+06 + 2.20000E+00 3.32009E+06 + 2.30000E+00 3.33963E+06 + 2.40000E+00 3.35884E+06 + 2.50000E+00 3.37770E+06 + 2.60000E+00 3.39620E+06 + 2.70000E+00 3.41433E+06 + 2.80000E+00 3.43208E+06 + 2.90000E+00 3.44943E+06 + 3.00000E+00 3.46638E+06 + 3.10000E+00 3.48291E+06 + 3.20000E+00 3.49902E+06 + 3.30000E+00 3.51469E+06 + 3.40000E+00 3.52991E+06 + 3.50000E+00 3.54468E+06 + 3.60000E+00 3.55898E+06 + 3.70000E+00 3.57281E+06 + 3.80000E+00 3.58616E+06 + 3.90000E+00 3.59901E+06 + 4.00000E+00 3.61137E+06 + 4.10000E+00 3.62322E+06 + 4.20000E+00 3.63455E+06 + 4.30000E+00 3.64537E+06 + 4.40000E+00 3.65565E+06 + 4.50000E+00 3.66540E+06 + 4.60000E+00 3.67461E+06 + 4.70000E+00 3.68327E+06 + 4.80000E+00 3.69138E+06 + 4.90000E+00 3.69893E+06 + 5.00000E+00 3.70592E+06 + 5.10000E+00 3.71234E+06 + 5.20000E+00 3.71819E+06 + 5.30000E+00 3.72347E+06 + 5.40000E+00 3.72817E+06 + 5.50000E+00 3.73229E+06 + 5.60000E+00 3.73582E+06 + 5.70000E+00 3.73877E+06 + 5.80000E+00 3.74113E+06 + 5.90000E+00 3.74290E+06 + 6.00000E+00 3.74409E+06 + 6.10000E+00 3.74468E+06 + 6.20000E+00 3.74468E+06 + 6.30000E+00 3.74409E+06 + 6.40000E+00 3.74290E+06 + 6.50000E+00 3.74113E+06 + 6.60000E+00 3.73877E+06 + 6.70000E+00 3.73582E+06 + 6.80000E+00 3.73229E+06 + 6.90000E+00 3.72817E+06 + 7.00000E+00 3.72347E+06 + 7.10000E+00 3.71819E+06 + 7.20000E+00 3.71234E+06 + 7.30000E+00 3.70592E+06 + 7.40000E+00 3.69893E+06 + 7.50000E+00 3.69138E+06 + 7.60000E+00 3.68327E+06 + 7.70000E+00 3.67461E+06 + 7.80000E+00 3.66540E+06 + 7.90000E+00 3.65565E+06 + 8.00000E+00 3.64537E+06 + 8.10000E+00 3.63455E+06 + 8.20000E+00 3.62322E+06 + 8.30000E+00 3.61137E+06 + 8.40000E+00 3.59901E+06 + 8.50000E+00 3.58616E+06 + 8.60000E+00 3.57281E+06 + 8.70000E+00 3.55898E+06 + 8.80000E+00 3.54468E+06 + 8.90000E+00 3.52991E+06 + 9.00000E+00 3.51468E+06 + 9.10000E+00 3.49902E+06 + 9.20000E+00 3.48291E+06 + 9.30000E+00 3.46638E+06 + 9.40000E+00 3.44943E+06 + 9.50000E+00 3.43208E+06 + 9.60000E+00 3.41433E+06 + 9.70000E+00 3.39620E+06 + 9.80000E+00 3.37770E+06 + 9.90000E+00 3.35884E+06 + 1.00000E+01 3.33963E+06 + 1.01000E+01 3.32009E+06 + 1.02000E+01 3.30023E+06 + 1.03000E+01 3.28005E+06 + 1.04000E+01 3.25958E+06 + 1.05000E+01 3.23882E+06 + 1.06000E+01 3.21779E+06 + 1.07000E+01 3.19650E+06 + 1.08000E+01 3.17496E+06 + 1.09000E+01 3.15320E+06 + 1.10000E+01 3.13121E+06 + 1.11000E+01 3.10903E+06 + 1.12000E+01 3.08665E+06 + 1.13000E+01 3.06410E+06 + 1.14000E+01 3.04138E+06 + 1.15000E+01 3.01852E+06 + 1.16000E+01 2.99553E+06 + 1.17000E+01 2.97242E+06 + 1.18000E+01 2.94920E+06 + 1.19000E+01 2.92590E+06 + 1.20000E+01 2.90252E+06 + 1.21000E+01 2.87908E+06 + 1.22000E+01 2.85560E+06 + 1.23000E+01 2.83209E+06 + 1.24000E+01 2.80856E+06 + 1.25000E+01 2.78504E+06 + 1.26000E+01 2.76153E+06 + 1.27000E+01 2.73804E+06 + 1.28000E+01 2.71461E+06 + 1.29000E+01 2.69123E+06 + 1.30000E+01 2.66792E+06 + 1.31000E+01 2.64471E+06 + 1.32000E+01 2.62160E+06 + 1.33000E+01 2.59860E+06 + 1.34000E+01 2.57574E+06 + 1.35000E+01 2.55303E+06 + 1.36000E+01 2.53048E+06 + 1.37000E+01 2.50810E+06 + 1.38000E+01 2.48591E+06 + 1.39000E+01 2.46393E+06 + 1.40000E+01 2.44216E+06 + 1.41000E+01 2.42063E+06 + 1.42000E+01 2.39934E+06 + 1.43000E+01 2.37831E+06 + 1.44000E+01 2.35755E+06 + 1.45000E+01 2.33708E+06 + 1.46000E+01 2.31690E+06 + 1.47000E+01 2.29704E+06 + 1.48000E+01 2.27749E+06 + 1.49000E+01 2.25829E+06 + 1.50000E+01 2.23943E+06 + 1.51000E+01 2.22093E+06 + 1.52000E+01 2.20280E+06 + 1.53000E+01 2.18505E+06 + 1.54000E+01 2.16770E+06 + 1.55000E+01 2.15075E+06 + 1.56000E+01 2.13422E+06 + 1.57000E+01 2.11811E+06 + 1.58000E+01 2.10244E+06 + 1.59000E+01 2.08722E+06 + 1.60000E+01 2.07245E+06 + 1.61000E+01 2.05815E+06 + 1.62000E+01 2.04432E+06 + 1.63000E+01 2.03097E+06 + 1.64000E+01 2.01811E+06 + 1.65000E+01 2.00576E+06 + 1.66000E+01 1.99391E+06 + 1.67000E+01 1.98257E+06 + 1.68000E+01 1.97176E+06 + 1.69000E+01 1.96148E+06 + 1.70000E+01 1.95173E+06 + 1.71000E+01 1.94252E+06 + 1.72000E+01 1.93386E+06 + 1.73000E+01 1.92575E+06 + 1.74000E+01 1.91820E+06 + 1.75000E+01 1.91121E+06 + 1.76000E+01 1.90479E+06 + 1.77000E+01 1.89893E+06 + 1.78000E+01 1.89366E+06 + 1.79000E+01 1.88896E+06 + 1.80000E+01 1.88484E+06 + 1.81000E+01 1.88131E+06 + 1.82000E+01 1.87836E+06 + 1.83000E+01 1.87600E+06 + 1.84000E+01 1.87422E+06 + 1.85000E+01 1.87304E+06 + 1.86000E+01 1.87245E+06 + 1.87000E+01 1.87245E+06 + 1.88000E+01 1.87304E+06 + 1.89000E+01 1.87422E+06 + 1.90000E+01 1.87600E+06 + 1.91000E+01 1.87836E+06 + 1.92000E+01 1.88131E+06 + 1.93000E+01 1.88484E+06 + 1.94000E+01 1.88896E+06 + 1.95000E+01 1.89366E+06 + 1.96000E+01 1.89893E+06 + 1.97000E+01 1.90479E+06 + 1.98000E+01 1.91121E+06 + 1.99000E+01 1.91820E+06 + 2.00000E+01 1.92575E+06 + 2.01000E+01 1.93386E+06 + 2.02000E+01 1.94252E+06 + 2.03000E+01 1.95173E+06 + 2.04000E+01 1.96148E+06 + 2.05000E+01 1.97176E+06 + 2.06000E+01 1.98257E+06 + 2.07000E+01 1.99391E+06 + 2.08000E+01 2.00576E+06 + 2.09000E+01 2.01811E+06 + 2.10000E+01 2.03097E+06 + 2.11000E+01 2.04432E+06 + 2.12000E+01 2.05815E+06 + 2.13000E+01 2.07245E+06 + 2.14000E+01 2.08722E+06 + 2.15000E+01 2.10244E+06 + 2.16000E+01 2.11811E+06 + 2.17000E+01 2.13422E+06 + 2.18000E+01 2.15075E+06 + 2.19000E+01 2.16770E+06 + 2.20000E+01 2.18505E+06 + 2.21000E+01 2.20280E+06 + 2.22000E+01 2.22093E+06 + 2.23000E+01 2.23943E+06 + 2.24000E+01 2.25829E+06 + 2.25000E+01 2.27749E+06 + 2.26000E+01 2.29704E+06 + 2.27000E+01 2.31690E+06 + 2.28000E+01 2.33708E+06 + 2.29000E+01 2.35755E+06 + 2.30000E+01 2.37831E+06 + 2.31000E+01 2.39934E+06 + 2.32000E+01 2.42063E+06 + 2.33000E+01 2.44216E+06 + 2.34000E+01 2.46393E+06 + 2.35000E+01 2.48591E+06 + 2.36000E+01 2.50810E+06 + 2.37000E+01 2.53048E+06 + 2.38000E+01 2.55303E+06 + 2.39000E+01 2.57574E+06 + 2.40000E+01 2.59860E+06 + 2.41000E+01 2.62160E+06 + 2.42000E+01 2.64471E+06 + 2.43000E+01 2.66792E+06 + 2.44000E+01 2.69123E+06 + 2.45000E+01 2.71461E+06 + 2.46000E+01 2.73804E+06 + 2.47000E+01 2.76153E+06 + 2.48000E+01 2.78504E+06 + 2.49000E+01 2.80856E+06 + 2.50000E+01 2.83209E+06 + 2.51000E+01 2.85560E+06 + 2.52000E+01 2.87908E+06 + 2.53000E+01 2.90252E+06 + 2.54000E+01 2.92590E+06 + 2.55000E+01 2.94920E+06 + 2.56000E+01 2.97242E+06 + 2.57000E+01 2.99553E+06 + 2.58000E+01 3.01852E+06 + 2.59000E+01 3.04138E+06 + 2.60000E+01 3.06410E+06 + 2.61000E+01 3.08665E+06 + 2.62000E+01 3.10903E+06 + 2.63000E+01 3.13122E+06 + 2.64000E+01 3.15320E+06 + 2.65000E+01 3.17496E+06 + 2.66000E+01 3.19650E+06 + 2.67000E+01 3.21779E+06 + 2.68000E+01 3.23882E+06 + 2.69000E+01 3.25958E+06 + 2.70000E+01 3.28005E+06 + 2.71000E+01 3.30023E+06 + 2.72000E+01 3.32009E+06 + 2.73000E+01 3.33963E+06 + 2.74000E+01 3.35884E+06 + 2.75000E+01 3.37770E+06 + 2.76000E+01 3.39620E+06 + 2.77000E+01 3.41433E+06 + 2.78000E+01 3.43208E+06 + 2.79000E+01 3.44943E+06 + 2.80000E+01 3.46638E+06 + 2.81000E+01 3.48291E+06 + 2.82000E+01 3.49902E+06 + 2.83000E+01 3.51469E+06 + 2.84000E+01 3.52991E+06 + 2.85000E+01 3.54468E+06 + 2.86000E+01 3.55898E+06 + 2.87000E+01 3.57281E+06 + 2.88000E+01 3.58616E+06 + 2.89000E+01 3.59901E+06 + 2.90000E+01 3.61137E+06 + 2.91000E+01 3.62322E+06 + 2.92000E+01 3.63455E+06 + 2.93000E+01 3.64537E+06 + 2.94000E+01 3.65565E+06 + 2.95000E+01 3.66540E+06 + 2.96000E+01 3.67461E+06 + 2.97000E+01 3.68327E+06 + 2.98000E+01 3.69138E+06 + 2.99000E+01 3.69893E+06 + 3.00000E+01 3.70592E+06 + 3.01000E+01 3.71234E+06 + 3.02000E+01 3.71819E+06 + 3.03000E+01 3.72347E+06 + 3.04000E+01 3.72817E+06 + 3.05000E+01 3.73229E+06 + 3.06000E+01 3.73582E+06 + 3.07000E+01 3.73877E+06 + 3.08000E+01 3.74113E+06 + 3.09000E+01 3.74290E+06 + 3.10000E+01 3.74409E+06 + 3.11000E+01 3.74468E+06 + 3.12000E+01 3.74468E+06 + 3.13000E+01 3.74409E+06 + 3.14000E+01 3.74290E+06 + 3.15000E+01 3.74113E+06 + 3.16000E+01 3.73877E+06 + 3.17000E+01 3.73582E+06 + 3.18000E+01 3.73229E+06 + 3.19000E+01 3.72817E+06 + 3.20000E+01 3.72347E+06 + 3.21000E+01 3.71819E+06 + 3.22000E+01 3.71234E+06 + 3.23000E+01 3.70592E+06 + 3.24000E+01 3.69893E+06 + 3.25000E+01 3.69138E+06 + 3.26000E+01 3.68327E+06 + 3.27000E+01 3.67461E+06 + 3.28000E+01 3.66540E+06 + 3.29000E+01 3.65565E+06 + 3.30000E+01 3.64537E+06 + 3.31000E+01 3.63455E+06 + 3.32000E+01 3.62322E+06 + 3.33000E+01 3.61137E+06 + 3.34000E+01 3.59901E+06 + 3.35000E+01 3.58616E+06 + 3.36000E+01 3.57281E+06 + 3.37000E+01 3.55898E+06 + 3.38000E+01 3.54468E+06 + 3.39000E+01 3.52991E+06 + 3.40000E+01 3.51468E+06 + 3.41000E+01 3.49901E+06 + 3.42000E+01 3.48291E+06 + 3.43000E+01 3.46638E+06 + 3.44000E+01 3.44943E+06 + 3.45000E+01 3.43208E+06 + 3.46000E+01 3.41433E+06 + 3.47000E+01 3.39620E+06 + 3.48000E+01 3.37770E+06 + 3.49000E+01 3.35884E+06 + 3.50000E+01 3.33963E+06 + 3.51000E+01 3.32009E+06 + 3.52000E+01 3.30023E+06 + 3.53000E+01 3.28005E+06 + 3.54000E+01 3.25958E+06 + 3.55000E+01 3.23882E+06 + 3.56000E+01 3.21779E+06 + 3.57000E+01 3.19650E+06 + 3.58000E+01 3.17496E+06 + 3.59000E+01 3.15320E+06 + 3.60000E+01 3.13121E+06 + 3.61000E+01 3.10903E+06 + 3.62000E+01 3.08665E+06 + 3.63000E+01 3.06410E+06 + 3.64000E+01 3.04138E+06 + 3.65000E+01 3.01852E+06 + 3.66000E+01 2.99553E+06 + 3.67000E+01 2.97242E+06 + 3.68000E+01 2.94920E+06 + 3.69000E+01 2.92590E+06 + 3.70000E+01 2.90252E+06 + 3.71000E+01 2.87908E+06 + 3.72000E+01 2.85560E+06 + 3.73000E+01 2.83209E+06 + 3.74000E+01 2.80856E+06 + 3.75000E+01 2.78504E+06 + 3.76000E+01 2.76153E+06 + 3.77000E+01 2.73804E+06 + 3.78000E+01 2.71461E+06 + 3.79000E+01 2.69123E+06 + 3.80000E+01 2.66792E+06 + 3.81000E+01 2.64471E+06 + 3.82000E+01 2.62160E+06 + 3.83000E+01 2.59860E+06 + 3.84000E+01 2.57574E+06 + 3.85000E+01 2.55303E+06 + 3.86000E+01 2.53048E+06 + 3.87000E+01 2.50810E+06 + 3.88000E+01 2.48591E+06 + 3.89000E+01 2.46393E+06 + 3.90000E+01 2.44216E+06 + 3.91000E+01 2.42063E+06 + 3.92000E+01 2.39934E+06 + 3.93000E+01 2.37831E+06 + 3.94000E+01 2.35755E+06 + 3.95000E+01 2.33708E+06 + 3.96000E+01 2.31690E+06 + 3.97000E+01 2.29704E+06 + 3.98000E+01 2.27749E+06 + 3.99000E+01 2.25829E+06 + 4.00000E+01 2.23943E+06 + 4.01000E+01 2.22093E+06 + 4.02000E+01 2.20280E+06 + 4.03000E+01 2.18505E+06 + 4.04000E+01 2.16770E+06 + 4.05000E+01 2.15075E+06 + 4.06000E+01 2.13422E+06 + 4.07000E+01 2.11811E+06 + 4.08000E+01 2.10244E+06 + 4.09000E+01 2.08722E+06 + 4.10000E+01 2.07245E+06 + 4.11000E+01 2.05815E+06 + 4.12000E+01 2.04432E+06 + 4.13000E+01 2.03097E+06 + 4.14000E+01 2.01811E+06 + 4.15000E+01 2.00576E+06 + 4.16000E+01 1.99391E+06 + 4.17000E+01 1.98257E+06 + 4.18000E+01 1.97176E+06 + 4.19000E+01 1.96148E+06 + 4.20000E+01 1.95173E+06 + 4.21000E+01 1.94252E+06 + 4.22000E+01 1.93386E+06 + 4.23000E+01 1.92575E+06 + 4.24000E+01 1.91820E+06 + 4.25000E+01 1.91121E+06 + 4.26000E+01 1.90479E+06 + 4.27000E+01 1.89893E+06 + 4.28000E+01 1.89366E+06 + 4.29000E+01 1.88896E+06 + 4.30000E+01 1.88484E+06 + 4.31000E+01 1.88131E+06 + 4.32000E+01 1.87836E+06 + 4.33000E+01 1.87600E+06 + 4.34000E+01 1.87422E+06 + 4.35000E+01 1.87304E+06 + 4.36000E+01 1.87245E+06 + 4.37000E+01 1.87245E+06 + 4.38000E+01 1.87304E+06 + 4.39000E+01 1.87422E+06 + 4.40000E+01 1.87600E+06 + 4.41000E+01 1.87836E+06 + 4.42000E+01 1.88131E+06 + 4.43000E+01 1.88484E+06 + 4.44000E+01 1.88896E+06 + 4.45000E+01 1.89366E+06 + 4.46000E+01 1.89893E+06 + 4.47000E+01 1.90479E+06 + 4.48000E+01 1.91121E+06 + 4.49000E+01 1.91820E+06 + 4.50000E+01 1.92575E+06 + 4.51000E+01 1.93386E+06 + 4.52000E+01 1.94252E+06 + 4.53000E+01 1.95173E+06 + 4.54000E+01 1.96148E+06 + 4.55000E+01 1.97176E+06 + 4.56000E+01 1.98257E+06 + 4.57000E+01 1.99391E+06 + 4.58000E+01 2.00576E+06 + 4.59000E+01 2.01811E+06 + 4.60000E+01 2.03097E+06 + 4.61000E+01 2.04432E+06 + 4.62000E+01 2.05815E+06 + 4.63000E+01 2.07245E+06 + 4.64000E+01 2.08722E+06 + 4.65000E+01 2.10244E+06 + 4.66000E+01 2.11811E+06 + 4.67000E+01 2.13422E+06 + 4.68000E+01 2.15075E+06 + 4.69000E+01 2.16770E+06 + 4.70000E+01 2.18505E+06 + 4.71000E+01 2.20280E+06 + 4.72000E+01 2.22093E+06 + 4.73000E+01 2.23943E+06 + 4.74000E+01 2.25829E+06 + 4.75000E+01 2.27749E+06 + 4.76000E+01 2.29704E+06 + 4.77000E+01 2.31690E+06 + 4.78000E+01 2.33708E+06 + 4.79000E+01 2.35755E+06 + 4.80000E+01 2.37831E+06 + 4.81000E+01 2.39934E+06 + 4.82000E+01 2.42063E+06 + 4.83000E+01 2.44217E+06 + 4.84000E+01 2.46393E+06 + 4.85000E+01 2.48591E+06 + 4.86000E+01 2.50810E+06 + 4.87000E+01 2.53048E+06 + 4.88000E+01 2.55303E+06 + 4.89000E+01 2.57574E+06 + 4.90000E+01 2.59861E+06 + 4.91000E+01 2.62160E+06 + 4.92000E+01 2.64471E+06 + 4.93000E+01 2.66793E+06 + 4.94000E+01 2.69123E+06 + 4.95000E+01 2.71461E+06 + 4.96000E+01 2.73804E+06 + 4.97000E+01 2.76153E+06 + 4.98000E+01 2.78504E+06 + 4.99000E+01 2.80856E+06 + 5.00000E+01 2.83209E+06 + 5.01000E+01 2.85560E+06 + 5.02000E+01 2.87908E+06 + 5.03000E+01 2.90252E+06 + 5.04000E+01 2.92590E+06 + 5.05000E+01 2.94920E+06 + 5.06000E+01 2.97242E+06 + 5.07000E+01 2.99553E+06 + 5.08000E+01 3.01852E+06 + 5.09000E+01 3.04138E+06 + 5.10000E+01 3.06410E+06 + 5.11000E+01 3.08665E+06 + 5.12000E+01 3.10903E+06 + 5.13000E+01 3.13122E+06 + 5.14000E+01 3.15320E+06 + 5.15000E+01 3.17496E+06 + 5.16000E+01 3.19650E+06 + 5.17000E+01 3.21779E+06 + 5.18000E+01 3.23882E+06 + 5.19000E+01 3.25958E+06 + 5.20000E+01 3.28005E+06 + 5.21000E+01 3.30023E+06 + 5.22000E+01 3.32009E+06 + 5.23000E+01 3.33964E+06 + 5.24000E+01 3.35884E+06 + 5.25000E+01 3.37770E+06 + 5.26000E+01 3.39620E+06 + 5.27000E+01 3.41433E+06 + 5.28000E+01 3.43208E+06 + 5.29000E+01 3.44943E+06 + 5.30000E+01 3.46638E+06 + 5.31000E+01 3.48291E+06 + 5.32000E+01 3.49902E+06 + 5.33000E+01 3.51469E+06 + 5.34000E+01 3.52991E+06 + 5.35000E+01 3.54468E+06 + 5.36000E+01 3.55898E+06 + 5.37000E+01 3.57281E+06 + 5.38000E+01 3.58616E+06 + 5.39000E+01 3.59901E+06 + 5.40000E+01 3.61137E+06 + 5.41000E+01 3.62322E+06 + 5.42000E+01 3.63456E+06 + 5.43000E+01 3.64537E+06 + 5.44000E+01 3.65565E+06 + 5.45000E+01 3.66540E+06 + 5.46000E+01 3.67461E+06 + 5.47000E+01 3.68327E+06 + 5.48000E+01 3.69138E+06 + 5.49000E+01 3.69893E+06 + 5.50000E+01 3.70592E+06 + 5.51000E+01 3.71234E+06 + 5.52000E+01 3.71819E+06 + 5.53000E+01 3.72347E+06 + 5.54000E+01 3.72817E+06 + 5.55000E+01 3.73229E+06 + 5.56000E+01 3.73582E+06 + 5.57000E+01 3.73877E+06 + 5.58000E+01 3.74113E+06 + 5.59000E+01 3.74290E+06 + 5.60000E+01 3.74409E+06 + 5.61000E+01 3.74468E+06 + 5.62000E+01 3.74468E+06 + 5.63000E+01 3.74409E+06 + 5.64000E+01 3.74290E+06 + 5.65000E+01 3.74113E+06 + 5.66000E+01 3.73877E+06 + 5.67000E+01 3.73582E+06 + 5.68000E+01 3.73229E+06 + 5.69000E+01 3.72817E+06 + 5.70000E+01 3.72347E+06 + 5.71000E+01 3.71819E+06 + 5.72000E+01 3.71234E+06 + 5.73000E+01 3.70592E+06 + 5.74000E+01 3.69893E+06 + 5.75000E+01 3.69138E+06 + 5.76000E+01 3.68327E+06 + 5.77000E+01 3.67461E+06 + 5.78000E+01 3.66540E+06 + 5.79000E+01 3.65565E+06 + 5.80000E+01 3.64537E+06 + 5.81000E+01 3.63455E+06 + 5.82000E+01 3.62322E+06 + 5.83000E+01 3.61137E+06 + 5.84000E+01 3.59901E+06 + 5.85000E+01 3.58616E+06 + 5.86000E+01 3.57281E+06 + 5.87000E+01 3.55898E+06 + 5.88000E+01 3.54468E+06 + 5.89000E+01 3.52991E+06 + 5.90000E+01 3.51468E+06 + 5.91000E+01 3.49901E+06 + 5.92000E+01 3.48291E+06 + 5.93000E+01 3.46638E+06 + 5.94000E+01 3.44943E+06 + 5.95000E+01 3.43208E+06 + 5.96000E+01 3.41433E+06 + 5.97000E+01 3.39620E+06 + 5.98000E+01 3.37770E+06 + 5.99000E+01 3.35884E+06 + 6.00000E+01 3.33963E+06 + 6.01000E+01 3.32009E+06 + 6.02000E+01 3.30023E+06 + 6.03000E+01 3.28005E+06 + 6.04000E+01 3.25958E+06 + 6.05000E+01 3.23882E+06 + 6.06000E+01 3.21779E+06 + 6.07000E+01 3.19650E+06 + 6.08000E+01 3.17496E+06 + 6.09000E+01 3.15320E+06 + 6.10000E+01 3.13121E+06 + 6.11000E+01 3.10903E+06 + 6.12000E+01 3.08665E+06 + 6.13000E+01 3.06410E+06 + 6.14000E+01 3.04138E+06 + 6.15000E+01 3.01852E+06 + 6.16000E+01 2.99553E+06 + 6.17000E+01 2.97242E+06 + 6.18000E+01 2.94920E+06 + 6.19000E+01 2.92590E+06 + 6.20000E+01 2.90252E+06 + 6.21000E+01 2.87908E+06 + 6.22000E+01 2.85560E+06 + 6.23000E+01 2.83209E+06 + 6.24000E+01 2.80856E+06 + 6.25000E+01 2.78504E+06 + 6.26000E+01 2.76152E+06 + 6.27000E+01 2.73804E+06 + 6.28000E+01 2.71461E+06 + 6.29000E+01 2.69123E+06 + 6.30000E+01 2.66792E+06 + 6.31000E+01 2.64471E+06 + 6.32000E+01 2.62160E+06 + 6.33000E+01 2.59860E+06 + 6.34000E+01 2.57574E+06 + 6.35000E+01 2.55303E+06 + 6.36000E+01 2.53048E+06 + 6.37000E+01 2.50810E+06 + 6.38000E+01 2.48591E+06 + 6.39000E+01 2.46393E+06 + 6.40000E+01 2.44216E+06 + 6.41000E+01 2.42063E+06 + 6.42000E+01 2.39934E+06 + 6.43000E+01 2.37831E+06 + 6.44000E+01 2.35755E+06 + 6.45000E+01 2.33708E+06 + 6.46000E+01 2.31690E+06 + 6.47000E+01 2.29703E+06 + 6.48000E+01 2.27749E+06 + 6.49000E+01 2.25829E+06 + 6.50000E+01 2.23943E+06 + 6.51000E+01 2.22093E+06 + 6.52000E+01 2.20280E+06 + 6.53000E+01 2.18505E+06 + 6.54000E+01 2.16770E+06 + 6.55000E+01 2.15075E+06 + 6.56000E+01 2.13422E+06 + 6.57000E+01 2.11811E+06 + 6.58000E+01 2.10244E+06 + 6.59000E+01 2.08722E+06 + 6.60000E+01 2.07245E+06 + 6.61000E+01 2.05815E+06 + 6.62000E+01 2.04432E+06 + 6.63000E+01 2.03097E+06 + 6.64000E+01 2.01811E+06 + 6.65000E+01 2.00576E+06 + 6.66000E+01 1.99391E+06 + 6.67000E+01 1.98257E+06 + 6.68000E+01 1.97176E+06 + 6.69000E+01 1.96148E+06 + 6.70000E+01 1.95173E+06 + 6.71000E+01 1.94252E+06 + 6.72000E+01 1.93386E+06 + 6.73000E+01 1.92575E+06 + 6.74000E+01 1.91820E+06 + 6.75000E+01 1.91121E+06 + 6.76000E+01 1.90478E+06 + 6.77000E+01 1.89893E+06 + 6.78000E+01 1.89366E+06 + 6.79000E+01 1.88896E+06 + 6.80000E+01 1.88484E+06 + 6.81000E+01 1.88131E+06 + 6.82000E+01 1.87836E+06 + 6.83000E+01 1.87600E+06 + 6.84000E+01 1.87422E+06 + 6.85000E+01 1.87304E+06 + 6.86000E+01 1.87245E+06 + 6.87000E+01 1.87245E+06 + 6.88000E+01 1.87304E+06 + 6.89000E+01 1.87422E+06 + 6.90000E+01 1.87600E+06 + 6.91000E+01 1.87836E+06 + 6.92000E+01 1.88131E+06 + 6.93000E+01 1.88484E+06 + 6.94000E+01 1.88896E+06 + 6.95000E+01 1.89366E+06 + 6.96000E+01 1.89893E+06 + 6.97000E+01 1.90479E+06 + 6.98000E+01 1.91121E+06 + 6.99000E+01 1.91820E+06 + 7.00000E+01 1.92575E+06 + 7.01000E+01 1.93386E+06 + 7.02000E+01 1.94252E+06 + 7.03000E+01 1.95173E+06 + 7.04000E+01 1.96148E+06 + 7.05000E+01 1.97176E+06 + 7.06000E+01 1.98257E+06 + 7.07000E+01 1.99391E+06 + 7.08000E+01 2.00576E+06 + 7.09000E+01 2.01812E+06 + 7.10000E+01 2.03097E+06 + 7.11000E+01 2.04432E+06 + 7.12000E+01 2.05815E+06 + 7.13000E+01 2.07245E+06 + 7.14000E+01 2.08722E+06 + 7.15000E+01 2.10244E+06 + 7.16000E+01 2.11811E+06 + 7.17000E+01 2.13422E+06 + 7.18000E+01 2.15075E+06 + 7.19000E+01 2.16770E+06 + 7.20000E+01 2.18505E+06 + 7.21000E+01 2.20280E+06 + 7.22000E+01 2.22093E+06 + 7.23000E+01 2.23943E+06 + 7.24000E+01 2.25829E+06 + 7.25000E+01 2.27749E+06 + 7.26000E+01 2.29704E+06 + 7.27000E+01 2.31690E+06 + 7.28000E+01 2.33708E+06 + 7.29000E+01 2.35755E+06 + 7.30000E+01 2.37831E+06 + 7.31000E+01 2.39934E+06 + 7.32000E+01 2.42063E+06 + 7.33000E+01 2.44217E+06 + 7.34000E+01 2.46393E+06 + 7.35000E+01 2.48591E+06 + 7.36000E+01 2.50810E+06 + 7.37000E+01 2.53048E+06 + 7.38000E+01 2.55303E+06 + 7.39000E+01 2.57575E+06 + 7.40000E+01 2.59860E+06 + 7.41000E+01 2.62160E+06 + 7.42000E+01 2.64471E+06 + 7.43000E+01 2.66793E+06 + 7.44000E+01 2.69123E+06 + 7.45000E+01 2.71461E+06 + 7.46000E+01 2.73805E+06 + 7.47000E+01 2.76153E+06 + 7.48000E+01 2.78504E+06 + 7.49000E+01 2.80856E+06 + 7.50000E+01 2.83209E+06 + 7.51000E+01 2.85560E+06 + 7.52000E+01 2.87909E+06 + 7.53000E+01 2.90252E+06 + 7.54000E+01 2.92590E+06 + 7.55000E+01 2.94920E+06 + 7.56000E+01 2.97242E+06 + 7.57000E+01 2.99553E+06 + 7.58000E+01 3.01853E+06 + 7.59000E+01 3.04138E+06 + 7.60000E+01 3.06410E+06 + 7.61000E+01 3.08665E+06 + 7.62000E+01 3.10903E+06 + 7.63000E+01 3.13122E+06 + 7.64000E+01 3.15320E+06 + 7.65000E+01 3.17496E+06 + 7.66000E+01 3.19650E+06 + 7.67000E+01 3.21779E+06 + 7.68000E+01 3.23882E+06 + 7.69000E+01 3.25958E+06 + 7.70000E+01 3.28005E+06 + 7.71000E+01 3.30023E+06 + 7.72000E+01 3.32009E+06 + 7.73000E+01 3.33964E+06 + 7.74000E+01 3.35884E+06 + 7.75000E+01 3.37770E+06 + 7.76000E+01 3.39620E+06 + 7.77000E+01 3.41433E+06 + 7.78000E+01 3.43208E+06 + 7.79000E+01 3.44943E+06 + 7.80000E+01 3.46638E+06 + 7.81000E+01 3.48291E+06 + 7.82000E+01 3.49902E+06 + 7.83000E+01 3.51469E+06 + 7.84000E+01 3.52991E+06 + 7.85000E+01 3.54468E+06 + 7.86000E+01 3.55898E+06 + 7.87000E+01 3.57281E+06 + 7.88000E+01 3.58616E+06 + 7.89000E+01 3.59901E+06 + 7.90000E+01 3.61137E+06 + 7.91000E+01 3.62322E+06 + 7.92000E+01 3.63456E+06 + 7.93000E+01 3.64537E+06 + 7.94000E+01 3.65565E+06 + 7.95000E+01 3.66540E+06 + 7.96000E+01 3.67461E+06 + 7.97000E+01 3.68327E+06 + 7.98000E+01 3.69138E+06 + 7.99000E+01 3.69893E+06 + 8.00000E+01 3.70592E+06 + 8.01000E+01 3.71234E+06 + 8.02000E+01 3.71819E+06 + 8.03000E+01 3.72347E+06 + 8.04000E+01 3.72817E+06 + 8.05000E+01 3.73229E+06 + 8.06000E+01 3.73582E+06 + 8.07000E+01 3.73877E+06 + 8.08000E+01 3.74113E+06 + 8.09000E+01 3.74290E+06 + 8.10000E+01 3.74409E+06 + 8.11000E+01 3.74468E+06 + 8.12000E+01 3.74468E+06 + 8.13000E+01 3.74409E+06 + 8.14000E+01 3.74290E+06 + 8.15000E+01 3.74113E+06 + 8.16000E+01 3.73877E+06 + 8.17000E+01 3.73582E+06 + 8.18000E+01 3.73229E+06 + 8.19000E+01 3.72817E+06 + 8.20000E+01 3.72347E+06 + 8.21000E+01 3.71819E+06 + 8.22000E+01 3.71234E+06 + 8.23000E+01 3.70592E+06 + 8.24000E+01 3.69893E+06 + 8.25000E+01 3.69138E+06 + 8.26000E+01 3.68327E+06 + 8.27000E+01 3.67461E+06 + 8.28000E+01 3.66540E+06 + 8.29000E+01 3.65565E+06 + 8.30000E+01 3.64537E+06 + 8.31000E+01 3.63455E+06 + 8.32000E+01 3.62322E+06 + 8.33000E+01 3.61137E+06 + 8.34000E+01 3.59901E+06 + 8.35000E+01 3.58616E+06 + 8.36000E+01 3.57281E+06 + 8.37000E+01 3.55898E+06 + 8.38000E+01 3.54468E+06 + 8.39000E+01 3.52991E+06 + 8.40000E+01 3.51468E+06 + 8.41000E+01 3.49901E+06 + 8.42000E+01 3.48291E+06 + 8.43000E+01 3.46638E+06 + 8.44000E+01 3.44943E+06 + 8.45000E+01 3.43208E+06 + 8.46000E+01 3.41433E+06 + 8.47000E+01 3.39620E+06 + 8.48000E+01 3.37770E+06 + 8.49000E+01 3.35884E+06 + 8.50000E+01 3.33963E+06 + 8.51000E+01 3.32009E+06 + 8.52000E+01 3.30022E+06 + 8.53000E+01 3.28005E+06 + 8.54000E+01 3.25958E+06 + 8.55000E+01 3.23882E+06 + 8.56000E+01 3.21778E+06 + 8.57000E+01 3.19650E+06 + 8.58000E+01 3.17496E+06 + 8.59000E+01 3.15320E+06 + 8.60000E+01 3.13121E+06 + 8.61000E+01 3.10903E+06 + 8.62000E+01 3.08665E+06 + 8.63000E+01 3.06410E+06 + 8.64000E+01 3.04138E+06 + 8.65000E+01 3.01852E+06 + 8.66000E+01 2.99553E+06 + 8.67000E+01 2.97242E+06 + 8.68000E+01 2.94920E+06 + 8.69000E+01 2.92590E+06 + 8.70000E+01 2.90252E+06 + 8.71000E+01 2.87908E+06 + 8.72000E+01 2.85560E+06 + 8.73000E+01 2.83209E+06 + 8.74000E+01 2.80856E+06 + 8.75000E+01 2.78504E+06 + 8.76000E+01 2.76152E+06 + 8.77000E+01 2.73804E+06 + 8.78000E+01 2.71461E+06 + 8.79000E+01 2.69123E+06 + 8.80000E+01 2.66792E+06 + 8.81000E+01 2.64471E+06 + 8.82000E+01 2.62160E+06 + 8.83000E+01 2.59860E+06 + 8.84000E+01 2.57574E+06 + 8.85000E+01 2.55303E+06 + 8.86000E+01 2.53048E+06 + 8.87000E+01 2.50810E+06 + 8.88000E+01 2.48591E+06 + 8.89000E+01 2.46393E+06 + 8.90000E+01 2.44216E+06 + 8.91000E+01 2.42063E+06 + 8.92000E+01 2.39934E+06 + 8.93000E+01 2.37831E+06 + 8.94000E+01 2.35755E+06 + 8.95000E+01 2.33708E+06 + 8.96000E+01 2.31690E+06 + 8.97000E+01 2.29703E+06 + 8.98000E+01 2.27749E+06 + 8.99000E+01 2.25829E+06 + 9.00000E+01 2.23943E+06 + 9.01000E+01 2.22093E+06 + 9.02000E+01 2.20280E+06 + 9.03000E+01 2.18505E+06 + 9.04000E+01 2.16770E+06 + 9.05000E+01 2.15075E+06 + 9.06000E+01 2.13422E+06 + 9.07000E+01 2.11811E+06 + 9.08000E+01 2.10244E+06 + 9.09000E+01 2.08722E+06 + 9.10000E+01 2.07245E+06 + 9.11000E+01 2.05815E+06 + 9.12000E+01 2.04432E+06 + 9.13000E+01 2.03097E+06 + 9.14000E+01 2.01811E+06 + 9.15000E+01 2.00576E+06 + 9.16000E+01 1.99391E+06 + 9.17000E+01 1.98257E+06 + 9.18000E+01 1.97176E+06 + 9.19000E+01 1.96148E+06 + 9.20000E+01 1.95173E+06 + 9.21000E+01 1.94252E+06 + 9.22000E+01 1.93386E+06 + 9.23000E+01 1.92575E+06 + 9.24000E+01 1.91820E+06 + 9.25000E+01 1.91121E+06 + 9.26000E+01 1.90478E+06 + 9.27000E+01 1.89893E+06 + 9.28000E+01 1.89366E+06 + 9.29000E+01 1.88896E+06 + 9.30000E+01 1.88484E+06 + 9.31000E+01 1.88131E+06 + 9.32000E+01 1.87836E+06 + 9.33000E+01 1.87600E+06 + 9.34000E+01 1.87422E+06 + 9.35000E+01 1.87304E+06 + 9.36000E+01 1.87245E+06 + 9.37000E+01 1.87245E+06 + 9.38000E+01 1.87304E+06 + 9.39000E+01 1.87422E+06 + 9.40000E+01 1.87600E+06 + 9.41000E+01 1.87836E+06 + 9.42000E+01 1.88131E+06 + 9.43000E+01 1.88484E+06 + 9.44000E+01 1.88896E+06 + 9.45000E+01 1.89366E+06 + 9.46000E+01 1.89893E+06 + 9.47000E+01 1.90479E+06 + 9.48000E+01 1.91121E+06 + 9.49000E+01 1.91820E+06 + 9.50000E+01 1.92575E+06 + 9.51000E+01 1.93386E+06 + 9.52000E+01 1.94252E+06 + 9.53000E+01 1.95173E+06 + 9.54000E+01 1.96148E+06 + 9.55000E+01 1.97176E+06 + 9.56000E+01 1.98257E+06 + 9.57000E+01 1.99391E+06 + 9.58000E+01 2.00576E+06 + 9.59000E+01 2.01812E+06 + 9.60000E+01 2.03097E+06 + 9.61000E+01 2.04432E+06 + 9.62000E+01 2.05815E+06 + 9.63000E+01 2.07245E+06 + 9.64000E+01 2.08722E+06 + 9.65000E+01 2.10244E+06 + 9.66000E+01 2.11812E+06 + 9.67000E+01 2.13422E+06 + 9.68000E+01 2.15075E+06 + 9.69000E+01 2.16770E+06 + 9.70000E+01 2.18505E+06 + 9.71000E+01 2.20280E+06 + 9.72000E+01 2.22093E+06 + 9.73000E+01 2.23943E+06 + 9.74000E+01 2.25829E+06 + 9.75000E+01 2.27749E+06 + 9.76000E+01 2.29704E+06 + 9.77000E+01 2.31690E+06 + 9.78000E+01 2.33708E+06 + 9.79000E+01 2.35755E+06 + 9.80000E+01 2.37831E+06 + 9.81000E+01 2.39934E+06 + 9.82000E+01 2.42063E+06 + 9.83000E+01 2.44217E+06 + 9.84000E+01 2.46393E+06 + 9.85000E+01 2.48591E+06 + 9.86000E+01 2.50810E+06 + 9.87000E+01 2.53048E+06 + 9.88000E+01 2.55303E+06 + 9.89000E+01 2.57574E+06 + 9.90000E+01 2.59861E+06 + 9.91000E+01 2.62160E+06 + 9.92000E+01 2.64471E+06 + 9.93000E+01 2.66793E+06 + 9.94000E+01 2.69123E+06 + 9.95000E+01 2.71461E+06 + 9.96000E+01 2.73805E+06 + 9.97000E+01 2.76153E+06 + 9.98000E+01 2.78504E+06 + 9.99000E+01 2.80856E+06 + 1.00000E+02 2.83209E+06 + 1.00100E+02 2.85561E+06 + 1.00200E+02 2.87909E+06 + 1.00300E+02 2.90252E+06 + 1.00400E+02 2.92590E+06 + 1.00500E+02 2.94920E+06 + 1.00600E+02 2.97242E+06 + 1.00700E+02 2.99553E+06 + 1.00800E+02 3.01853E+06 + 1.00900E+02 3.04139E+06 + 1.01000E+02 3.06410E+06 + 1.01100E+02 3.08665E+06 + 1.01200E+02 3.10903E+06 + 1.01300E+02 3.13122E+06 + 1.01400E+02 3.15320E+06 + 1.01500E+02 3.17496E+06 + 1.01600E+02 3.19650E+06 + 1.01700E+02 3.21779E+06 + 1.01800E+02 3.23882E+06 + 1.01900E+02 3.25958E+06 + 1.02000E+02 3.28005E+06 + 1.02100E+02 3.30023E+06 + 1.02200E+02 3.32009E+06 + 1.02300E+02 3.33964E+06 + 1.02400E+02 3.35884E+06 + 1.02500E+02 3.37770E+06 + 1.02600E+02 3.39620E+06 + 1.02700E+02 3.41433E+06 + 1.02800E+02 3.43208E+06 + 1.02900E+02 3.44943E+06 + 1.03000E+02 3.46638E+06 + 1.03100E+02 3.48291E+06 + 1.03200E+02 3.49902E+06 + 1.03300E+02 3.51469E+06 + 1.03400E+02 3.52991E+06 + 1.03500E+02 3.54468E+06 + 1.03600E+02 3.55898E+06 + 1.03700E+02 3.57281E+06 + 1.03800E+02 3.58616E+06 + 1.03900E+02 3.59901E+06 + 1.04000E+02 3.61137E+06 + 1.04100E+02 3.62322E+06 + 1.04200E+02 3.63456E+06 + 1.04300E+02 3.64537E+06 + 1.04400E+02 3.65565E+06 + 1.04500E+02 3.66540E+06 + 1.04600E+02 3.67461E+06 + 1.04700E+02 3.68327E+06 + 1.04800E+02 3.69138E+06 + 1.04900E+02 3.69893E+06 + 1.05000E+02 3.70592E+06 + 1.05100E+02 3.71234E+06 + 1.05200E+02 3.71819E+06 + 1.05300E+02 3.72347E+06 + 1.05400E+02 3.72817E+06 + 1.05500E+02 3.73229E+06 + 1.05600E+02 3.73582E+06 + 1.05700E+02 3.73877E+06 + 1.05800E+02 3.74113E+06 + 1.05900E+02 3.74290E+06 + 1.06000E+02 3.74409E+06 + 1.06100E+02 3.74468E+06 + 1.06200E+02 3.74468E+06 + 1.06300E+02 3.74409E+06 + 1.06400E+02 3.74290E+06 + 1.06500E+02 3.74113E+06 + 1.06600E+02 3.73877E+06 + 1.06700E+02 3.73582E+06 + 1.06800E+02 3.73229E+06 + 1.06900E+02 3.72817E+06 + 1.07000E+02 3.72347E+06 + 1.07100E+02 3.71819E+06 + 1.07200E+02 3.71234E+06 + 1.07300E+02 3.70592E+06 + 1.07400E+02 3.69893E+06 + 1.07500E+02 3.69138E+06 + 1.07600E+02 3.68327E+06 + 1.07700E+02 3.67461E+06 + 1.07800E+02 3.66540E+06 + 1.07900E+02 3.65565E+06 + 1.08000E+02 3.64537E+06 + 1.08100E+02 3.63455E+06 + 1.08200E+02 3.62322E+06 + 1.08300E+02 3.61137E+06 + 1.08400E+02 3.59901E+06 + 1.08500E+02 3.58616E+06 + 1.08600E+02 3.57281E+06 + 1.08700E+02 3.55898E+06 + 1.08800E+02 3.54468E+06 + 1.08900E+02 3.52991E+06 + 1.09000E+02 3.51468E+06 + 1.09100E+02 3.49901E+06 + 1.09200E+02 3.48291E+06 + 1.09300E+02 3.46638E+06 + 1.09400E+02 3.44943E+06 + 1.09500E+02 3.43208E+06 + 1.09600E+02 3.41433E+06 + 1.09700E+02 3.39620E+06 + 1.09800E+02 3.37770E+06 + 1.09900E+02 3.35884E+06 + 1.10000E+02 3.33963E+06 + 1.10100E+02 3.32009E+06 + 1.10200E+02 3.30022E+06 + 1.10300E+02 3.28005E+06 + 1.10400E+02 3.25957E+06 + 1.10500E+02 3.23882E+06 + 1.10600E+02 3.21778E+06 + 1.10700E+02 3.19650E+06 + 1.10800E+02 3.17496E+06 + 1.10900E+02 3.15320E+06 + 1.11000E+02 3.13121E+06 + 1.11100E+02 3.10903E+06 + 1.11200E+02 3.08665E+06 + 1.11300E+02 3.06410E+06 + 1.11400E+02 3.04138E+06 + 1.11500E+02 3.01852E+06 + 1.11600E+02 2.99553E+06 + 1.11700E+02 2.97242E+06 + 1.11800E+02 2.94920E+06 + 1.11900E+02 2.92590E+06 + 1.12000E+02 2.90252E+06 + 1.12100E+02 2.87908E+06 + 1.12200E+02 2.85560E+06 + 1.12300E+02 2.83209E+06 + 1.12400E+02 2.80856E+06 + 1.12500E+02 2.78504E+06 + 1.12600E+02 2.76152E+06 + 1.12700E+02 2.73804E+06 + 1.12800E+02 2.71461E+06 + 1.12900E+02 2.69123E+06 + 1.13000E+02 2.66792E+06 + 1.13100E+02 2.64471E+06 + 1.13200E+02 2.62160E+06 + 1.13300E+02 2.59860E+06 + 1.13400E+02 2.57574E+06 + 1.13500E+02 2.55303E+06 + 1.13600E+02 2.53047E+06 + 1.13700E+02 2.50810E+06 + 1.13800E+02 2.48591E+06 + 1.13900E+02 2.46393E+06 + 1.14000E+02 2.44216E+06 + 1.14100E+02 2.42063E+06 + 1.14200E+02 2.39934E+06 + 1.14300E+02 2.37831E+06 + 1.14400E+02 2.35755E+06 + 1.14500E+02 2.33708E+06 + 1.14600E+02 2.31690E+06 + 1.14700E+02 2.29704E+06 + 1.14800E+02 2.27749E+06 + 1.14900E+02 2.25828E+06 + 1.15000E+02 2.23943E+06 + 1.15100E+02 2.22092E+06 + 1.15200E+02 2.20280E+06 + 1.15300E+02 2.18505E+06 + 1.15400E+02 2.16770E+06 + 1.15500E+02 2.15075E+06 + 1.15600E+02 2.13422E+06 + 1.15700E+02 2.11811E+06 + 1.15800E+02 2.10244E+06 + 1.15900E+02 2.08722E+06 + 1.16000E+02 2.07245E+06 + 1.16100E+02 2.05814E+06 + 1.16200E+02 2.04432E+06 + 1.16300E+02 2.03097E+06 + 1.16400E+02 2.01811E+06 + 1.16500E+02 2.00576E+06 + 1.16600E+02 1.99391E+06 + 1.16700E+02 1.98257E+06 + 1.16800E+02 1.97176E+06 + 1.16900E+02 1.96147E+06 + 1.17000E+02 1.95173E+06 + 1.17100E+02 1.94252E+06 + 1.17200E+02 1.93386E+06 + 1.17300E+02 1.92575E+06 + 1.17400E+02 1.91820E+06 + 1.17500E+02 1.91121E+06 + 1.17600E+02 1.90478E+06 + 1.17700E+02 1.89893E+06 + 1.17800E+02 1.89366E+06 + 1.17900E+02 1.88896E+06 + 1.18000E+02 1.88484E+06 + 1.18100E+02 1.88131E+06 + 1.18200E+02 1.87836E+06 + 1.18300E+02 1.87600E+06 + 1.18400E+02 1.87422E+06 + 1.18500E+02 1.87304E+06 + 1.18600E+02 1.87245E+06 + 1.18700E+02 1.87245E+06 + 1.18800E+02 1.87304E+06 + 1.18900E+02 1.87422E+06 + 1.19000E+02 1.87600E+06 + 1.19100E+02 1.87836E+06 + 1.19200E+02 1.88131E+06 + 1.19300E+02 1.88484E+06 + 1.19400E+02 1.88896E+06 + 1.19500E+02 1.89366E+06 + 1.19600E+02 1.89893E+06 + 1.19700E+02 1.90479E+06 + 1.19800E+02 1.91121E+06 + 1.19900E+02 1.91820E+06 + 1.20000E+02 1.92575E+06 + 1.20100E+02 1.93386E+06 + 1.20200E+02 1.94252E+06 + 1.20300E+02 1.95173E+06 + 1.20400E+02 1.96148E+06 + 1.20500E+02 1.97176E+06 + 1.20600E+02 1.98258E+06 + 1.20700E+02 1.99391E+06 + 1.20800E+02 2.00576E+06 + 1.20900E+02 2.01811E+06 + 1.21000E+02 2.03097E+06 + 1.21100E+02 2.04432E+06 + 1.21200E+02 2.05815E+06 + 1.21300E+02 2.07245E+06 + 1.21400E+02 2.08722E+06 + 1.21500E+02 2.10244E+06 + 1.21600E+02 2.11811E+06 + 1.21700E+02 2.13422E+06 + 1.21800E+02 2.15075E+06 + 1.21900E+02 2.16770E+06 + 1.22000E+02 2.18505E+06 + 1.22100E+02 2.20280E+06 + 1.22200E+02 2.22093E+06 + 1.22300E+02 2.23943E+06 + 1.22400E+02 2.25829E+06 + 1.22500E+02 2.27749E+06 + 1.22600E+02 2.29704E+06 + 1.22700E+02 2.31690E+06 + 1.22800E+02 2.33708E+06 + 1.22900E+02 2.35755E+06 + 1.23000E+02 2.37831E+06 + 1.23100E+02 2.39934E+06 + 1.23200E+02 2.42063E+06 + 1.23300E+02 2.44217E+06 + 1.23400E+02 2.46393E+06 + 1.23500E+02 2.48591E+06 + 1.23600E+02 2.50810E+06 + 1.23700E+02 2.53048E+06 + 1.23800E+02 2.55303E+06 + 1.23900E+02 2.57574E+06 + 1.24000E+02 2.59861E+06 + 1.24100E+02 2.62160E+06 + 1.24200E+02 2.64471E+06 + 1.24300E+02 2.66793E+06 + 1.24400E+02 2.69123E+06 + 1.24500E+02 2.71461E+06 + 1.24600E+02 2.73805E+06 + 1.24700E+02 2.76153E+06 + 1.24800E+02 2.78504E+06 + 1.24900E+02 2.80857E+06 + 1.25000E+02 2.83209E+06 + 1.25100E+02 2.85560E+06 + 1.25200E+02 2.87909E+06 + 1.25300E+02 2.90252E+06 + 1.25400E+02 2.92590E+06 + 1.25500E+02 2.94920E+06 + 1.25600E+02 2.97242E+06 + 1.25700E+02 2.99553E+06 + 1.25800E+02 3.01852E+06 + 1.25900E+02 3.04139E+06 + 1.26000E+02 3.06410E+06 + 1.26100E+02 3.08665E+06 + 1.26200E+02 3.10903E+06 + 1.26300E+02 3.13122E+06 + 1.26400E+02 3.15320E+06 + 1.26500E+02 3.17496E+06 + 1.26600E+02 3.19650E+06 + 1.26700E+02 3.21779E+06 + 1.26800E+02 3.23882E+06 + 1.26900E+02 3.25958E+06 + 1.27000E+02 3.28005E+06 + 1.27100E+02 3.30023E+06 + 1.27200E+02 3.32009E+06 + 1.27300E+02 3.33964E+06 + 1.27400E+02 3.35884E+06 + 1.27500E+02 3.37770E+06 + 1.27600E+02 3.39620E+06 + 1.27700E+02 3.41433E+06 + 1.27800E+02 3.43208E+06 + 1.27900E+02 3.44943E+06 + 1.28000E+02 3.46638E+06 + 1.28100E+02 3.48291E+06 + 1.28200E+02 3.49902E+06 + 1.28300E+02 3.51469E+06 + 1.28400E+02 3.52991E+06 + 1.28500E+02 3.54468E+06 + 1.28600E+02 3.55898E+06 + 1.28700E+02 3.57281E+06 + 1.28800E+02 3.58616E+06 + 1.28900E+02 3.59901E+06 + 1.29000E+02 3.61137E+06 + 1.29100E+02 3.62322E+06 + 1.29200E+02 3.63456E+06 + 1.29300E+02 3.64537E+06 + 1.29400E+02 3.65565E+06 + 1.29500E+02 3.66540E+06 + 1.29600E+02 3.67461E+06 + 1.29700E+02 3.68327E+06 + 1.29800E+02 3.69138E+06 + 1.29900E+02 3.69893E+06 + 1.30000E+02 3.70592E+06 + 1.30100E+02 3.71234E+06 + 1.30200E+02 3.71819E+06 + 1.30300E+02 3.72347E+06 + 1.30400E+02 3.72817E+06 + 1.30500E+02 3.73229E+06 + 1.30600E+02 3.73582E+06 + 1.30700E+02 3.73877E+06 + 1.30800E+02 3.74113E+06 + 1.30900E+02 3.74290E+06 + 1.31000E+02 3.74409E+06 + 1.31100E+02 3.74468E+06 + 1.31200E+02 3.74468E+06 + 1.31300E+02 3.74409E+06 + 1.31400E+02 3.74290E+06 + 1.31500E+02 3.74113E+06 + 1.31600E+02 3.73877E+06 + 1.31700E+02 3.73582E+06 + 1.31800E+02 3.73229E+06 + 1.31900E+02 3.72817E+06 + 1.32000E+02 3.72347E+06 + 1.32100E+02 3.71819E+06 + 1.32200E+02 3.71234E+06 + 1.32300E+02 3.70592E+06 + 1.32400E+02 3.69893E+06 + 1.32500E+02 3.69138E+06 + 1.32600E+02 3.68327E+06 + 1.32700E+02 3.67461E+06 + 1.32800E+02 3.66540E+06 + 1.32900E+02 3.65565E+06 + 1.33000E+02 3.64537E+06 + 1.33100E+02 3.63456E+06 + 1.33200E+02 3.62322E+06 + 1.33300E+02 3.61137E+06 + 1.33400E+02 3.59901E+06 + 1.33500E+02 3.58616E+06 + 1.33600E+02 3.57281E+06 + 1.33700E+02 3.55898E+06 + 1.33800E+02 3.54468E+06 + 1.33900E+02 3.52991E+06 + 1.34000E+02 3.51468E+06 + 1.34100E+02 3.49902E+06 + 1.34200E+02 3.48291E+06 + 1.34300E+02 3.46637E+06 + 1.34400E+02 3.44943E+06 + 1.34500E+02 3.43207E+06 + 1.34600E+02 3.41433E+06 + 1.34700E+02 3.39620E+06 + 1.34800E+02 3.37770E+06 + 1.34900E+02 3.35884E+06 + 1.35000E+02 3.33963E+06 + 1.35100E+02 3.32009E+06 + 1.35200E+02 3.30022E+06 + 1.35300E+02 3.28005E+06 + 1.35400E+02 3.25957E+06 + 1.35500E+02 3.23881E+06 + 1.35600E+02 3.21779E+06 + 1.35700E+02 3.19650E+06 + 1.35800E+02 3.17496E+06 + 1.35900E+02 3.15320E+06 + 1.36000E+02 3.13121E+06 + 1.36100E+02 3.10903E+06 + 1.36200E+02 3.08665E+06 + 1.36300E+02 3.06409E+06 + 1.36400E+02 3.04138E+06 + 1.36500E+02 3.01852E+06 + 1.36600E+02 2.99553E+06 + 1.36700E+02 2.97242E+06 + 1.36800E+02 2.94920E+06 + 1.36900E+02 2.92590E+06 + 1.37000E+02 2.90252E+06 + 1.37100E+02 2.87908E+06 + 1.37200E+02 2.85560E+06 + 1.37300E+02 2.83209E+06 + 1.37400E+02 2.80856E+06 + 1.37500E+02 2.78503E+06 + 1.37600E+02 2.76153E+06 + 1.37700E+02 2.73804E+06 + 1.37800E+02 2.71460E+06 + 1.37900E+02 2.69123E+06 + 1.38000E+02 2.66792E+06 + 1.38100E+02 2.64471E+06 + 1.38200E+02 2.62160E+06 + 1.38300E+02 2.59860E+06 + 1.38400E+02 2.57574E+06 + 1.38500E+02 2.55302E+06 + 1.38600E+02 2.53048E+06 + 1.38700E+02 2.50810E+06 + 1.38800E+02 2.48591E+06 + 1.38900E+02 2.46393E+06 + 1.39000E+02 2.44216E+06 + 1.39100E+02 2.42063E+06 + 1.39200E+02 2.39934E+06 + 1.39300E+02 2.37831E+06 + 1.39400E+02 2.35755E+06 + 1.39500E+02 2.33707E+06 + 1.39600E+02 2.31690E+06 + 1.39700E+02 2.29703E+06 + 1.39800E+02 2.27749E+06 + 1.39900E+02 2.25828E+06 + 1.40000E+02 2.23942E+06 + 1.40100E+02 2.22093E+06 + 1.40200E+02 2.20280E+06 + 1.40300E+02 2.18505E+06 + 1.40400E+02 2.16770E+06 + 1.40500E+02 2.15075E+06 + 1.40600E+02 2.13422E+06 + 1.40700E+02 2.11811E+06 + 1.40800E+02 2.10244E+06 + 1.40900E+02 2.08722E+06 + 1.41000E+02 2.07245E+06 + 1.41100E+02 2.05815E+06 + 1.41200E+02 2.04432E+06 + 1.41300E+02 2.03097E+06 + 1.41400E+02 2.01811E+06 + 1.41500E+02 2.00576E+06 + 1.41600E+02 1.99391E+06 + 1.41700E+02 1.98257E+06 + 1.41800E+02 1.97176E+06 + 1.41900E+02 1.96147E+06 + 1.42000E+02 1.95173E+06 + 1.42100E+02 1.94252E+06 + 1.42200E+02 1.93386E+06 + 1.42300E+02 1.92575E+06 + 1.42400E+02 1.91820E+06 + 1.42500E+02 1.91121E+06 + 1.42600E+02 1.90479E+06 + 1.42700E+02 1.89893E+06 + 1.42800E+02 1.89366E+06 + 1.42900E+02 1.88896E+06 + 1.43000E+02 1.88484E+06 + 1.43100E+02 1.88131E+06 + 1.43200E+02 1.87836E+06 + 1.43300E+02 1.87600E+06 + 1.43400E+02 1.87422E+06 + 1.43500E+02 1.87304E+06 + 1.43600E+02 1.87245E+06 + 1.43700E+02 1.87245E+06 + 1.43800E+02 1.87304E+06 + 1.43900E+02 1.87422E+06 + 1.44000E+02 1.87600E+06 + 1.44100E+02 1.87836E+06 + 1.44200E+02 1.88131E+06 + 1.44300E+02 1.88484E+06 + 1.44400E+02 1.88896E+06 + 1.44500E+02 1.89366E+06 + 1.44600E+02 1.89893E+06 + 1.44700E+02 1.90479E+06 + 1.44800E+02 1.91121E+06 + 1.44900E+02 1.91820E+06 + 1.45000E+02 1.92575E+06 + 1.45100E+02 1.93386E+06 + 1.45200E+02 1.94252E+06 + 1.45300E+02 1.95173E+06 + 1.45400E+02 1.96148E+06 + 1.45500E+02 1.97176E+06 + 1.45600E+02 1.98257E+06 + 1.45700E+02 1.99391E+06 + 1.45800E+02 2.00576E+06 + 1.45900E+02 2.01812E+06 + 1.46000E+02 2.03097E+06 + 1.46100E+02 2.04432E+06 + 1.46200E+02 2.05815E+06 + 1.46300E+02 2.07245E+06 + 1.46400E+02 2.08722E+06 + 1.46500E+02 2.10244E+06 + 1.46600E+02 2.11811E+06 + 1.46700E+02 2.13422E+06 + 1.46800E+02 2.15076E+06 + 1.46900E+02 2.16770E+06 + 1.47000E+02 2.18505E+06 + 1.47100E+02 2.20280E+06 + 1.47200E+02 2.22093E+06 + 1.47300E+02 2.23943E+06 + 1.47400E+02 2.25829E+06 + 1.47500E+02 2.27750E+06 + 1.47600E+02 2.29704E+06 + 1.47700E+02 2.31690E+06 + 1.47800E+02 2.33708E+06 + 1.47900E+02 2.35756E+06 + 1.48000E+02 2.37831E+06 + 1.48100E+02 2.39934E+06 + 1.48200E+02 2.42063E+06 + 1.48300E+02 2.44217E+06 + 1.48400E+02 2.46393E+06 + 1.48500E+02 2.48592E+06 + 1.48600E+02 2.50810E+06 + 1.48700E+02 2.53048E+06 + 1.48800E+02 2.55303E+06 + 1.48900E+02 2.57575E+06 + 1.49000E+02 2.59861E+06 + 1.49100E+02 2.62160E+06 + 1.49200E+02 2.64471E+06 + 1.49300E+02 2.66793E+06 + 1.49400E+02 2.69123E+06 + 1.49500E+02 2.71461E+06 + 1.49600E+02 2.73804E+06 + 1.49700E+02 2.76153E+06 + 1.49800E+02 2.78504E+06 + 1.49900E+02 2.80856E+06 + 1.50000E+02 2.83209E+06 + 1.50100E+02 2.85560E+06 + 1.50200E+02 2.87909E+06 + 1.50300E+02 2.90253E+06 + 1.50400E+02 2.92590E+06 + 1.50500E+02 2.94921E+06 + 1.50600E+02 2.97242E+06 + 1.50700E+02 2.99553E+06 + 1.50800E+02 3.01853E+06 + 1.50900E+02 3.04138E+06 + 1.51000E+02 3.06410E+06 + 1.51100E+02 3.08665E+06 + 1.51200E+02 3.10903E+06 + 1.51300E+02 3.13122E+06 + 1.51400E+02 3.15320E+06 + 1.51500E+02 3.17497E+06 + 1.51600E+02 3.19650E+06 + 1.51700E+02 3.21779E+06 + 1.51800E+02 3.23882E+06 + 1.51900E+02 3.25958E+06 + 1.52000E+02 3.28005E+06 + 1.52100E+02 3.30023E+06 + 1.52200E+02 3.32009E+06 + 1.52300E+02 3.33964E+06 + 1.52400E+02 3.35884E+06 + 1.52500E+02 3.37770E+06 + 1.52600E+02 3.39620E+06 + 1.52700E+02 3.41433E+06 + 1.52800E+02 3.43208E+06 + 1.52900E+02 3.44943E+06 + 1.53000E+02 3.46638E+06 + 1.53100E+02 3.48291E+06 + 1.53200E+02 3.49902E+06 + 1.53300E+02 3.51469E+06 + 1.53400E+02 3.52991E+06 + 1.53500E+02 3.54468E+06 + 1.53600E+02 3.55898E+06 + 1.53700E+02 3.57281E+06 + 1.53800E+02 3.58616E+06 + 1.53900E+02 3.59901E+06 + 1.54000E+02 3.61137E+06 + 1.54100E+02 3.62322E+06 + 1.54200E+02 3.63456E+06 + 1.54300E+02 3.64537E+06 + 1.54400E+02 3.65565E+06 + 1.54500E+02 3.66540E+06 + 1.54600E+02 3.67461E+06 + 1.54700E+02 3.68327E+06 + 1.54800E+02 3.69138E+06 + 1.54900E+02 3.69893E+06 + 1.55000E+02 3.70592E+06 + 1.55100E+02 3.71234E+06 + 1.55200E+02 3.71820E+06 + 1.55300E+02 3.72347E+06 + 1.55400E+02 3.72817E+06 + 1.55500E+02 3.73229E+06 + 1.55600E+02 3.73582E+06 + 1.55700E+02 3.73877E+06 + 1.55800E+02 3.74113E+06 + 1.55900E+02 3.74290E+06 + 1.56000E+02 3.74409E+06 + 1.56100E+02 3.74468E+06 + 1.56200E+02 3.74468E+06 + 1.56300E+02 3.74409E+06 + 1.56400E+02 3.74290E+06 + 1.56500E+02 3.74113E+06 + 1.56600E+02 3.73877E+06 + 1.56700E+02 3.73582E+06 + 1.56800E+02 3.73229E+06 + 1.56900E+02 3.72817E+06 + 1.57000E+02 3.72347E+06 + 1.57100E+02 3.71819E+06 + 1.57200E+02 3.71234E+06 + 1.57300E+02 3.70592E+06 + 1.57400E+02 3.69893E+06 + 1.57500E+02 3.69138E+06 + 1.57600E+02 3.68327E+06 + 1.57700E+02 3.67461E+06 + 1.57800E+02 3.66540E+06 + 1.57900E+02 3.65565E+06 + 1.58000E+02 3.64537E+06 + 1.58100E+02 3.63455E+06 + 1.58200E+02 3.62322E+06 + 1.58300E+02 3.61137E+06 + 1.58400E+02 3.59901E+06 + 1.58500E+02 3.58616E+06 + 1.58600E+02 3.57281E+06 + 1.58700E+02 3.55898E+06 + 1.58800E+02 3.54468E+06 + 1.58900E+02 3.52991E+06 + 1.59000E+02 3.51468E+06 + 1.59100E+02 3.49901E+06 + 1.59200E+02 3.48291E+06 + 1.59300E+02 3.46637E+06 + 1.59400E+02 3.44943E+06 + 1.59500E+02 3.43207E+06 + 1.59600E+02 3.41433E+06 + 1.59700E+02 3.39620E+06 + 1.59800E+02 3.37770E+06 + 1.59900E+02 3.35884E+06 + 1.60000E+02 3.33963E+06 + 1.60100E+02 3.32009E+06 + 1.60200E+02 3.30022E+06 + 1.60300E+02 3.28005E+06 + 1.60400E+02 3.25958E+06 + 1.60500E+02 3.23881E+06 + 1.60600E+02 3.21778E+06 + 1.60700E+02 3.19649E+06 + 1.60800E+02 3.17496E+06 + 1.60900E+02 3.15320E+06 + 1.61000E+02 3.13121E+06 + 1.61100E+02 3.10903E+06 + 1.61200E+02 3.08665E+06 + 1.61300E+02 3.06410E+06 + 1.61400E+02 3.04138E+06 + 1.61500E+02 3.01852E+06 + 1.61600E+02 2.99553E+06 + 1.61700E+02 2.97241E+06 + 1.61800E+02 2.94920E+06 + 1.61900E+02 2.92590E+06 + 1.62000E+02 2.90252E+06 + 1.62100E+02 2.87908E+06 + 1.62200E+02 2.85560E+06 + 1.62300E+02 2.83209E+06 + 1.62400E+02 2.80856E+06 + 1.62500E+02 2.78503E+06 + 1.62600E+02 2.76152E+06 + 1.62700E+02 2.73804E+06 + 1.62800E+02 2.71460E+06 + 1.62900E+02 2.69123E+06 + 1.63000E+02 2.66792E+06 + 1.63100E+02 2.64471E+06 + 1.63200E+02 2.62159E+06 + 1.63300E+02 2.59860E+06 + 1.63400E+02 2.57574E+06 + 1.63500E+02 2.55303E+06 + 1.63600E+02 2.53048E+06 + 1.63700E+02 2.50810E+06 + 1.63800E+02 2.48591E+06 + 1.63900E+02 2.46393E+06 + 1.64000E+02 2.44216E+06 + 1.64100E+02 2.42063E+06 + 1.64200E+02 2.39934E+06 + 1.64300E+02 2.37831E+06 + 1.64400E+02 2.35755E+06 + 1.64500E+02 2.33707E+06 + 1.64600E+02 2.31690E+06 + 1.64700E+02 2.29703E+06 + 1.64800E+02 2.27749E+06 + 1.64900E+02 2.25829E+06 + 1.65000E+02 2.23942E+06 + 1.65100E+02 2.22093E+06 + 1.65200E+02 2.20279E+06 + 1.65300E+02 2.18505E+06 + 1.65400E+02 2.16770E+06 + 1.65500E+02 2.15075E+06 + 1.65600E+02 2.13422E+06 + 1.65700E+02 2.11811E+06 + 1.65800E+02 2.10244E+06 + 1.65900E+02 2.08722E+06 + 1.66000E+02 2.07245E+06 + 1.66100E+02 2.05815E+06 + 1.66200E+02 2.04431E+06 + 1.66300E+02 2.03097E+06 + 1.66400E+02 2.01811E+06 + 1.66500E+02 2.00576E+06 + 1.66600E+02 1.99391E+06 + 1.66700E+02 1.98257E+06 + 1.66800E+02 1.97176E+06 + 1.66900E+02 1.96148E+06 + 1.67000E+02 1.95172E+06 + 1.67100E+02 1.94252E+06 + 1.67200E+02 1.93386E+06 + 1.67300E+02 1.92575E+06 + 1.67400E+02 1.91820E+06 + 1.67500E+02 1.91121E+06 + 1.67600E+02 1.90478E+06 + 1.67700E+02 1.89893E+06 + 1.67800E+02 1.89366E+06 + 1.67900E+02 1.88896E+06 + 1.68000E+02 1.88484E+06 + 1.68100E+02 1.88131E+06 + 1.68200E+02 1.87836E+06 + 1.68300E+02 1.87600E+06 + 1.68400E+02 1.87422E+06 + 1.68500E+02 1.87304E+06 + 1.68600E+02 1.87245E+06 + 1.68700E+02 1.87245E+06 + 1.68800E+02 1.87304E+06 + 1.68900E+02 1.87422E+06 + 1.69000E+02 1.87600E+06 + 1.69100E+02 1.87836E+06 + 1.69200E+02 1.88131E+06 + 1.69300E+02 1.88484E+06 + 1.69400E+02 1.88896E+06 + 1.69500E+02 1.89366E+06 + 1.69600E+02 1.89893E+06 + 1.69700E+02 1.90479E+06 + 1.69800E+02 1.91121E+06 + 1.69900E+02 1.91820E+06 + 1.70000E+02 1.92575E+06 + 1.70100E+02 1.93386E+06 + 1.70200E+02 1.94252E+06 + 1.70300E+02 1.95173E+06 + 1.70400E+02 1.96148E+06 + 1.70500E+02 1.97176E+06 + 1.70600E+02 1.98257E+06 + 1.70700E+02 1.99391E+06 + 1.70800E+02 2.00576E+06 + 1.70900E+02 2.01812E+06 + 1.71000E+02 2.03097E+06 + 1.71100E+02 2.04432E+06 + 1.71200E+02 2.05815E+06 + 1.71300E+02 2.07245E+06 + 1.71400E+02 2.08722E+06 + 1.71500E+02 2.10245E+06 + 1.71600E+02 2.11812E+06 + 1.71700E+02 2.13422E+06 + 1.71800E+02 2.15075E+06 + 1.71900E+02 2.16770E+06 + 1.72000E+02 2.18505E+06 + 1.72100E+02 2.20280E+06 + 1.72200E+02 2.22093E+06 + 1.72300E+02 2.23943E+06 + 1.72400E+02 2.25829E+06 + 1.72500E+02 2.27750E+06 + 1.72600E+02 2.29704E+06 + 1.72700E+02 2.31690E+06 + 1.72800E+02 2.33708E+06 + 1.72900E+02 2.35755E+06 + 1.73000E+02 2.37831E+06 + 1.73100E+02 2.39934E+06 + 1.73200E+02 2.42063E+06 + 1.73300E+02 2.44217E+06 + 1.73400E+02 2.46393E+06 + 1.73500E+02 2.48592E+06 + 1.73600E+02 2.50810E+06 + 1.73700E+02 2.53048E+06 + 1.73800E+02 2.55303E+06 + 1.73900E+02 2.57575E+06 + 1.74000E+02 2.59861E+06 + 1.74100E+02 2.62160E+06 + 1.74200E+02 2.64471E+06 + 1.74300E+02 2.66793E+06 + 1.74400E+02 2.69123E+06 + 1.74500E+02 2.71461E+06 + 1.74600E+02 2.73805E+06 + 1.74700E+02 2.76153E+06 + 1.74800E+02 2.78504E+06 + 1.74900E+02 2.80857E+06 + 1.75000E+02 2.83210E+06 + 1.75100E+02 2.85560E+06 + 1.75200E+02 2.87909E+06 + 1.75300E+02 2.90253E+06 + 1.75400E+02 2.92590E+06 + 1.75500E+02 2.94921E+06 + 1.75600E+02 2.97242E+06 + 1.75700E+02 2.99553E+06 + 1.75800E+02 3.01853E+06 + 1.75900E+02 3.04139E+06 + 1.76000E+02 3.06410E+06 + 1.76100E+02 3.08665E+06 + 1.76200E+02 3.10903E+06 + 1.76300E+02 3.13122E+06 + 1.76400E+02 3.15320E+06 + 1.76500E+02 3.17497E+06 + 1.76600E+02 3.19650E+06 + 1.76700E+02 3.21779E+06 + 1.76800E+02 3.23882E+06 + 1.76900E+02 3.25958E+06 + 1.77000E+02 3.28005E+06 + 1.77100E+02 3.30023E+06 + 1.77200E+02 3.32009E+06 + 1.77300E+02 3.33964E+06 + 1.77400E+02 3.35884E+06 + 1.77500E+02 3.37770E+06 + 1.77600E+02 3.39620E+06 + 1.77700E+02 3.41433E+06 + 1.77800E+02 3.43208E+06 + 1.77900E+02 3.44943E+06 + 1.78000E+02 3.46638E+06 + 1.78100E+02 3.48291E+06 + 1.78200E+02 3.49902E+06 + 1.78300E+02 3.51469E+06 + 1.78400E+02 3.52991E+06 + 1.78500E+02 3.54468E+06 + 1.78600E+02 3.55898E+06 + 1.78700E+02 3.57281E+06 + 1.78800E+02 3.58616E+06 + 1.78900E+02 3.59902E+06 + 1.79000E+02 3.61137E+06 + 1.79100E+02 3.62322E+06 + 1.79200E+02 3.63456E+06 + 1.79300E+02 3.64537E+06 + 1.79400E+02 3.65565E+06 + 1.79500E+02 3.66540E+06 + 1.79600E+02 3.67461E+06 + 1.79700E+02 3.68327E+06 + 1.79800E+02 3.69138E+06 + 1.79900E+02 3.69893E+06 + 1.80000E+02 3.70592E+06 + 1.80100E+02 3.71234E+06 + 1.80200E+02 3.71819E+06 + 1.80300E+02 3.72347E+06 + 1.80400E+02 3.72817E+06 + 1.80500E+02 3.73229E+06 + 1.80600E+02 3.73582E+06 + 1.80700E+02 3.73877E+06 + 1.80800E+02 3.74113E+06 + 1.80900E+02 3.74290E+06 + 1.81000E+02 3.74409E+06 + 1.81100E+02 3.74468E+06 + 1.81200E+02 3.74468E+06 + 1.81300E+02 3.74409E+06 + 1.81400E+02 3.74290E+06 + 1.81500E+02 3.74113E+06 + 1.81600E+02 3.73877E+06 + 1.81700E+02 3.73582E+06 + 1.81800E+02 3.73229E+06 + 1.81900E+02 3.72817E+06 + 1.82000E+02 3.72347E+06 + 1.82100E+02 3.71819E+06 + 1.82200E+02 3.71234E+06 + 1.82300E+02 3.70592E+06 + 1.82400E+02 3.69893E+06 + 1.82500E+02 3.69138E+06 + 1.82600E+02 3.68327E+06 + 1.82700E+02 3.67461E+06 + 1.82800E+02 3.66540E+06 + 1.82900E+02 3.65565E+06 + 1.83000E+02 3.64537E+06 + 1.83100E+02 3.63455E+06 + 1.83200E+02 3.62322E+06 + 1.83300E+02 3.61137E+06 + 1.83400E+02 3.59901E+06 + 1.83500E+02 3.58616E+06 + 1.83600E+02 3.57281E+06 + 1.83700E+02 3.55898E+06 + 1.83800E+02 3.54468E+06 + 1.83900E+02 3.52991E+06 + 1.84000E+02 3.51468E+06 + 1.84100E+02 3.49901E+06 + 1.84200E+02 3.48291E+06 + 1.84300E+02 3.46637E+06 + 1.84400E+02 3.44943E+06 + 1.84500E+02 3.43208E+06 + 1.84600E+02 3.41433E+06 + 1.84700E+02 3.39620E+06 + 1.84800E+02 3.37770E+06 + 1.84900E+02 3.35884E+06 + 1.85000E+02 3.33963E+06 + 1.85100E+02 3.32009E+06 + 1.85200E+02 3.30022E+06 + 1.85300E+02 3.28005E+06 + 1.85400E+02 3.25957E+06 + 1.85500E+02 3.23882E+06 + 1.85600E+02 3.21779E+06 + 1.85700E+02 3.19650E+06 + 1.85800E+02 3.17496E+06 + 1.85900E+02 3.15319E+06 + 1.86000E+02 3.13121E+06 + 1.86100E+02 3.10903E+06 + 1.86200E+02 3.08665E+06 + 1.86300E+02 3.06409E+06 + 1.86400E+02 3.04138E+06 + 1.86500E+02 3.01852E+06 + 1.86600E+02 2.99553E+06 + 1.86700E+02 2.97242E+06 + 1.86800E+02 2.94920E+06 + 1.86900E+02 2.92590E+06 + 1.87000E+02 2.90252E+06 + 1.87100E+02 2.87908E+06 + 1.87200E+02 2.85560E+06 + 1.87300E+02 2.83209E+06 + 1.87400E+02 2.80856E+06 + 1.87500E+02 2.78504E+06 + 1.87600E+02 2.76152E+06 + 1.87700E+02 2.73804E+06 + 1.87800E+02 2.71460E+06 + 1.87900E+02 2.69122E+06 + 1.88000E+02 2.66792E+06 + 1.88100E+02 2.64471E+06 + 1.88200E+02 2.62159E+06 + 1.88300E+02 2.59860E+06 + 1.88400E+02 2.57574E+06 + 1.88500E+02 2.55303E+06 + 1.88600E+02 2.53048E+06 + 1.88700E+02 2.50810E+06 + 1.88800E+02 2.48591E+06 + 1.88900E+02 2.46393E+06 + 1.89000E+02 2.44216E+06 + 1.89100E+02 2.42063E+06 + 1.89200E+02 2.39934E+06 + 1.89300E+02 2.37831E+06 + 1.89400E+02 2.35755E+06 + 1.89500E+02 2.33708E+06 + 1.89600E+02 2.31690E+06 + 1.89700E+02 2.29703E+06 + 1.89800E+02 2.27749E+06 + 1.89900E+02 2.25828E+06 + 1.90000E+02 2.23942E+06 + 1.90100E+02 2.22093E+06 + 1.90200E+02 2.20280E+06 + 1.90300E+02 2.18505E+06 + 1.90400E+02 2.16770E+06 + 1.90500E+02 2.15075E+06 + 1.90600E+02 2.13422E+06 + 1.90700E+02 2.11811E+06 + 1.90800E+02 2.10244E+06 + 1.90900E+02 2.08722E+06 + 1.91000E+02 2.07245E+06 + 1.91100E+02 2.05815E+06 + 1.91200E+02 2.04432E+06 + 1.91300E+02 2.03097E+06 + 1.91400E+02 2.01811E+06 + 1.91500E+02 2.00576E+06 + 1.91600E+02 1.99391E+06 + 1.91700E+02 1.98257E+06 + 1.91800E+02 1.97176E+06 + 1.91900E+02 1.96147E+06 + 1.92000E+02 1.95173E+06 + 1.92100E+02 1.94252E+06 + 1.92200E+02 1.93386E+06 + 1.92300E+02 1.92575E+06 + 1.92400E+02 1.91820E+06 + 1.92500E+02 1.91121E+06 + 1.92600E+02 1.90478E+06 + 1.92700E+02 1.89893E+06 + 1.92800E+02 1.89366E+06 + 1.92900E+02 1.88896E+06 + 1.93000E+02 1.88484E+06 + 1.93100E+02 1.88131E+06 + 1.93200E+02 1.87836E+06 + 1.93300E+02 1.87600E+06 + 1.93400E+02 1.87422E+06 + 1.93500E+02 1.87304E+06 + 1.93600E+02 1.87245E+06 + 1.93700E+02 1.87245E+06 + 1.93800E+02 1.87304E+06 + 1.93900E+02 1.87422E+06 + 1.94000E+02 1.87600E+06 + 1.94100E+02 1.87836E+06 + 1.94200E+02 1.88131E+06 + 1.94300E+02 1.88484E+06 + 1.94400E+02 1.88896E+06 + 1.94500E+02 1.89366E+06 + 1.94600E+02 1.89893E+06 + 1.94700E+02 1.90479E+06 + 1.94800E+02 1.91121E+06 + 1.94900E+02 1.91820E+06 + 1.95000E+02 1.92575E+06 + 1.95100E+02 1.93386E+06 + 1.95200E+02 1.94252E+06 + 1.95300E+02 1.95173E+06 + 1.95400E+02 1.96148E+06 + 1.95500E+02 1.97176E+06 + 1.95600E+02 1.98257E+06 + 1.95700E+02 1.99391E+06 + 1.95800E+02 2.00576E+06 + 1.95900E+02 2.01811E+06 + 1.96000E+02 2.03097E+06 + 1.96100E+02 2.04432E+06 + 1.96200E+02 2.05815E+06 + 1.96300E+02 2.07245E+06 + 1.96400E+02 2.08722E+06 + 1.96500E+02 2.10244E+06 + 1.96600E+02 2.11811E+06 + 1.96700E+02 2.13422E+06 + 1.96800E+02 2.15076E+06 + 1.96900E+02 2.16770E+06 + 1.97000E+02 2.18505E+06 + 1.97100E+02 2.20280E+06 + 1.97200E+02 2.22093E+06 + 1.97300E+02 2.23943E+06 + 1.97400E+02 2.25829E+06 + 1.97500E+02 2.27750E+06 + 1.97600E+02 2.29704E+06 + 1.97700E+02 2.31691E+06 + 1.97800E+02 2.33708E+06 + 1.97900E+02 2.35755E+06 + 1.98000E+02 2.37831E+06 + 1.98100E+02 2.39934E+06 + 1.98200E+02 2.42063E+06 + 1.98300E+02 2.44217E+06 + 1.98400E+02 2.46393E+06 + 1.98500E+02 2.48592E+06 + 1.98600E+02 2.50810E+06 + 1.98700E+02 2.53048E+06 + 1.98800E+02 2.55304E+06 + 1.98900E+02 2.57574E+06 + 1.99000E+02 2.59861E+06 + 1.99100E+02 2.62160E+06 + 1.99200E+02 2.64471E+06 + 1.99300E+02 2.66793E+06 + 1.99400E+02 2.69123E+06 + 1.99500E+02 2.71461E+06 + 1.99600E+02 2.73805E+06 + 1.99700E+02 2.76153E+06 + 1.99800E+02 2.78504E+06 + 1.99900E+02 2.80857E+06 + 2.00000E+02 2.83209E+06 + 2.00100E+02 2.85560E+06 + 2.00200E+02 2.87909E+06 + 2.00300E+02 2.90253E+06 + 2.00400E+02 2.92590E+06 + 2.00500E+02 2.94921E+06 + 2.00600E+02 2.97242E+06 + 2.00700E+02 2.99553E+06 + 2.00800E+02 3.01853E+06 + 2.00900E+02 3.04139E+06 + 2.01000E+02 3.06410E+06 + 2.01100E+02 3.08665E+06 + 2.01200E+02 3.10903E+06 + 2.01300E+02 3.13122E+06 + 2.01400E+02 3.15320E+06 + 2.01500E+02 3.17497E+06 + 2.01600E+02 3.19650E+06 + 2.01700E+02 3.21779E+06 + 2.01800E+02 3.23882E+06 + 2.01900E+02 3.25958E+06 + 2.02000E+02 3.28005E+06 + 2.02100E+02 3.30023E+06 + 2.02200E+02 3.32010E+06 + 2.02300E+02 3.33964E+06 + 2.02400E+02 3.35884E+06 + 2.02500E+02 3.37770E+06 + 2.02600E+02 3.39620E+06 + 2.02700E+02 3.41433E+06 + 2.02800E+02 3.43208E+06 + 2.02900E+02 3.44943E+06 + 2.03000E+02 3.46638E+06 + 2.03100E+02 3.48291E+06 + 2.03200E+02 3.49902E+06 + 2.03300E+02 3.51469E+06 + 2.03400E+02 3.52991E+06 + 2.03500E+02 3.54468E+06 + 2.03600E+02 3.55898E+06 + 2.03700E+02 3.57281E+06 + 2.03800E+02 3.58616E+06 + 2.03900E+02 3.59901E+06 + 2.04000E+02 3.61137E+06 + 2.04100E+02 3.62322E+06 + 2.04200E+02 3.63456E+06 + 2.04300E+02 3.64537E+06 + 2.04400E+02 3.65565E+06 + 2.04500E+02 3.66540E+06 + 2.04600E+02 3.67461E+06 + 2.04700E+02 3.68327E+06 + 2.04800E+02 3.69138E+06 + 2.04900E+02 3.69893E+06 + 2.05000E+02 3.70592E+06 + 2.05100E+02 3.71234E+06 + 2.05200E+02 3.71820E+06 + 2.05300E+02 3.72347E+06 + 2.05400E+02 3.72817E+06 + 2.05500E+02 3.73229E+06 + 2.05600E+02 3.73582E+06 + 2.05700E+02 3.73877E+06 + 2.05800E+02 3.74113E+06 + 2.05900E+02 3.74290E+06 + 2.06000E+02 3.74409E+06 + 2.06100E+02 3.74468E+06 + 2.06200E+02 3.74468E+06 + 2.06300E+02 3.74409E+06 + 2.06400E+02 3.74290E+06 + 2.06500E+02 3.74113E+06 + 2.06600E+02 3.73877E+06 + 2.06700E+02 3.73582E+06 + 2.06800E+02 3.73229E+06 + 2.06900E+02 3.72817E+06 + 2.07000E+02 3.72347E+06 + 2.07100E+02 3.71819E+06 + 2.07200E+02 3.71234E+06 + 2.07300E+02 3.70592E+06 + 2.07400E+02 3.69893E+06 + 2.07500E+02 3.69138E+06 + 2.07600E+02 3.68327E+06 + 2.07700E+02 3.67461E+06 + 2.07800E+02 3.66540E+06 + 2.07900E+02 3.65565E+06 + 2.08000E+02 3.64537E+06 + 2.08100E+02 3.63455E+06 + 2.08200E+02 3.62322E+06 + 2.08300E+02 3.61137E+06 + 2.08400E+02 3.59901E+06 + 2.08500E+02 3.58616E+06 + 2.08600E+02 3.57281E+06 + 2.08700E+02 3.55898E+06 + 2.08800E+02 3.54468E+06 + 2.08900E+02 3.52991E+06 + 2.09000E+02 3.51468E+06 + 2.09100E+02 3.49901E+06 + 2.09200E+02 3.48291E+06 + 2.09300E+02 3.46637E+06 + 2.09400E+02 3.44943E+06 + 2.09500E+02 3.43207E+06 + 2.09600E+02 3.41433E+06 + 2.09700E+02 3.39620E+06 + 2.09800E+02 3.37770E+06 + 2.09900E+02 3.35884E+06 + 2.10000E+02 3.33963E+06 + 2.10100E+02 3.32009E+06 + 2.10200E+02 3.30022E+06 + 2.10300E+02 3.28005E+06 + 2.10400E+02 3.25957E+06 + 2.10500E+02 3.23881E+06 + 2.10600E+02 3.21778E+06 + 2.10700E+02 3.19650E+06 + 2.10800E+02 3.17496E+06 + 2.10900E+02 3.15320E+06 + 2.11000E+02 3.13121E+06 + 2.11100E+02 3.10902E+06 + 2.11200E+02 3.08665E+06 + 2.11300E+02 3.06409E+06 + 2.11400E+02 3.04138E+06 + 2.11500E+02 3.01852E+06 + 2.11600E+02 2.99553E+06 + 2.11700E+02 2.97242E+06 + 2.11800E+02 2.94920E+06 + 2.11900E+02 2.92590E+06 + 2.12000E+02 2.90252E+06 + 2.12100E+02 2.87908E+06 + 2.12200E+02 2.85560E+06 + 2.12300E+02 2.83209E+06 + 2.12400E+02 2.80856E+06 + 2.12500E+02 2.78503E+06 + 2.12600E+02 2.76152E+06 + 2.12700E+02 2.73804E+06 + 2.12800E+02 2.71460E+06 + 2.12900E+02 2.69123E+06 + 2.13000E+02 2.66792E+06 + 2.13100E+02 2.64471E+06 + 2.13200E+02 2.62160E+06 + 2.13300E+02 2.59860E+06 + 2.13400E+02 2.57574E+06 + 2.13500E+02 2.55302E+06 + 2.13600E+02 2.53047E+06 + 2.13700E+02 2.50810E+06 + 2.13800E+02 2.48591E+06 + 2.13900E+02 2.46393E+06 + 2.14000E+02 2.44216E+06 + 2.14100E+02 2.42063E+06 + 2.14200E+02 2.39934E+06 + 2.14300E+02 2.37831E+06 + 2.14400E+02 2.35755E+06 + 2.14500E+02 2.33707E+06 + 2.14600E+02 2.31690E+06 + 2.14700E+02 2.29703E+06 + 2.14800E+02 2.27749E+06 + 2.14900E+02 2.25828E+06 + 2.15000E+02 2.23942E+06 + 2.15100E+02 2.22092E+06 + 2.15200E+02 2.20280E+06 + 2.15300E+02 2.18505E+06 + 2.15400E+02 2.16770E+06 + 2.15500E+02 2.15075E+06 + 2.15600E+02 2.13422E+06 + 2.15700E+02 2.11811E+06 + 2.15800E+02 2.10244E+06 + 2.15900E+02 2.08722E+06 + 2.16000E+02 2.07245E+06 + 2.16100E+02 2.05814E+06 + 2.16200E+02 2.04432E+06 + 2.16300E+02 2.03097E+06 + 2.16400E+02 2.01811E+06 + 2.16500E+02 2.00576E+06 + 2.16600E+02 1.99391E+06 + 2.16700E+02 1.98257E+06 + 2.16800E+02 1.97176E+06 + 2.16900E+02 1.96147E+06 + 2.17000E+02 1.95172E+06 + 2.17100E+02 1.94252E+06 + 2.17200E+02 1.93386E+06 + 2.17300E+02 1.92575E+06 + 2.17400E+02 1.91820E+06 + 2.17500E+02 1.91121E+06 + 2.17600E+02 1.90479E+06 + 2.17700E+02 1.89893E+06 + 2.17800E+02 1.89366E+06 + 2.17900E+02 1.88896E+06 + 2.18000E+02 1.88484E+06 + 2.18100E+02 1.88131E+06 + 2.18200E+02 1.87836E+06 + 2.18300E+02 1.87600E+06 + 2.18400E+02 1.87422E+06 + 2.18500E+02 1.87304E+06 + 2.18600E+02 1.87245E+06 + 2.18700E+02 1.87245E+06 + 2.18800E+02 1.87304E+06 + 2.18900E+02 1.87422E+06 + 2.19000E+02 1.87600E+06 + 2.19100E+02 1.87836E+06 + 2.19200E+02 1.88131E+06 + 2.19300E+02 1.88484E+06 + 2.19400E+02 1.88896E+06 + 2.19500E+02 1.89366E+06 + 2.19600E+02 1.89893E+06 + 2.19700E+02 1.90479E+06 + 2.19800E+02 1.91121E+06 + 2.19900E+02 1.91820E+06 + 2.20000E+02 1.92575E+06 + 2.20100E+02 1.93386E+06 + 2.20200E+02 1.94252E+06 + 2.20300E+02 1.95173E+06 + 2.20400E+02 1.96148E+06 + 2.20500E+02 1.97176E+06 + 2.20600E+02 1.98257E+06 + 2.20700E+02 1.99391E+06 + 2.20800E+02 2.00576E+06 + 2.20900E+02 2.01812E+06 + 2.21000E+02 2.03097E+06 + 2.21100E+02 2.04432E+06 + 2.21200E+02 2.05815E+06 + 2.21300E+02 2.07245E+06 + 2.21400E+02 2.08722E+06 + 2.21500E+02 2.10245E+06 + 2.21600E+02 2.11811E+06 + 2.21700E+02 2.13422E+06 + 2.21800E+02 2.15076E+06 + 2.21900E+02 2.16770E+06 + 2.22000E+02 2.18506E+06 + 2.22100E+02 2.20280E+06 + 2.22200E+02 2.22093E+06 + 2.22300E+02 2.23943E+06 + 2.22400E+02 2.25829E+06 + 2.22500E+02 2.27750E+06 + 2.22600E+02 2.29704E+06 + 2.22700E+02 2.31690E+06 + 2.22800E+02 2.33708E+06 + 2.22900E+02 2.35756E+06 + 2.23000E+02 2.37832E+06 + 2.23100E+02 2.39934E+06 + 2.23200E+02 2.42063E+06 + 2.23300E+02 2.44217E+06 + 2.23400E+02 2.46393E+06 + 2.23500E+02 2.48592E+06 + 2.23600E+02 2.50810E+06 + 2.23700E+02 2.53048E+06 + 2.23800E+02 2.55303E+06 + 2.23900E+02 2.57575E+06 + 2.24000E+02 2.59861E+06 + 2.24100E+02 2.62160E+06 + 2.24200E+02 2.64471E+06 + 2.24300E+02 2.66793E+06 + 2.24400E+02 2.69123E+06 + 2.24500E+02 2.71461E+06 + 2.24600E+02 2.73804E+06 + 2.24700E+02 2.76153E+06 + 2.24800E+02 2.78504E+06 + 2.24900E+02 2.80857E+06 + 2.25000E+02 2.83210E+06 + 2.25100E+02 2.85560E+06 + 2.25200E+02 2.87909E+06 + 2.25300E+02 2.90253E+06 + 2.25400E+02 2.92590E+06 + 2.25500E+02 2.94921E+06 + 2.25600E+02 2.97242E+06 + 2.25700E+02 2.99553E+06 + 2.25800E+02 3.01853E+06 + 2.25900E+02 3.04139E+06 + 2.26000E+02 3.06410E+06 + 2.26100E+02 3.08665E+06 + 2.26200E+02 3.10903E+06 + 2.26300E+02 3.13122E+06 + 2.26400E+02 3.15320E+06 + 2.26500E+02 3.17497E+06 + 2.26600E+02 3.19650E+06 + 2.26700E+02 3.21779E+06 + 2.26800E+02 3.23882E+06 + 2.26900E+02 3.25958E+06 + 2.27000E+02 3.28005E+06 + 2.27100E+02 3.30023E+06 + 2.27200E+02 3.32009E+06 + 2.27300E+02 3.33964E+06 + 2.27400E+02 3.35884E+06 + 2.27500E+02 3.37770E+06 + 2.27600E+02 3.39620E+06 + 2.27700E+02 3.41433E+06 + 2.27800E+02 3.43208E+06 + 2.27900E+02 3.44943E+06 + 2.28000E+02 3.46638E+06 + 2.28100E+02 3.48291E+06 + 2.28200E+02 3.49902E+06 + 2.28300E+02 3.51469E+06 + 2.28400E+02 3.52991E+06 + 2.28500E+02 3.54468E+06 + 2.28600E+02 3.55898E+06 + 2.28700E+02 3.57281E+06 + 2.28800E+02 3.58616E+06 + 2.28900E+02 3.59902E+06 + 2.29000E+02 3.61137E+06 + 2.29100E+02 3.62322E+06 + 2.29200E+02 3.63456E+06 + 2.29300E+02 3.64537E+06 + 2.29400E+02 3.65565E+06 + 2.29500E+02 3.66540E+06 + 2.29600E+02 3.67461E+06 + 2.29700E+02 3.68327E+06 + 2.29800E+02 3.69138E+06 + 2.29900E+02 3.69893E+06 + 2.30000E+02 3.70592E+06 + 2.30100E+02 3.71234E+06 + 2.30200E+02 3.71820E+06 + 2.30300E+02 3.72347E+06 + 2.30400E+02 3.72817E+06 + 2.30500E+02 3.73229E+06 + 2.30600E+02 3.73582E+06 + 2.30700E+02 3.73877E+06 + 2.30800E+02 3.74113E+06 + 2.30900E+02 3.74290E+06 + 2.31000E+02 3.74409E+06 + 2.31100E+02 3.74468E+06 + 2.31200E+02 3.74468E+06 + 2.31300E+02 3.74409E+06 + 2.31400E+02 3.74290E+06 + 2.31500E+02 3.74113E+06 + 2.31600E+02 3.73877E+06 + 2.31700E+02 3.73582E+06 + 2.31800E+02 3.73229E+06 + 2.31900E+02 3.72817E+06 + 2.32000E+02 3.72347E+06 + 2.32100E+02 3.71819E+06 + 2.32200E+02 3.71234E+06 + 2.32300E+02 3.70592E+06 + 2.32400E+02 3.69893E+06 + 2.32500E+02 3.69138E+06 + 2.32600E+02 3.68327E+06 + 2.32700E+02 3.67461E+06 + 2.32800E+02 3.66540E+06 + 2.32900E+02 3.65565E+06 + 2.33000E+02 3.64537E+06 + 2.33100E+02 3.63455E+06 + 2.33200E+02 3.62322E+06 + 2.33300E+02 3.61137E+06 + 2.33400E+02 3.59901E+06 + 2.33500E+02 3.58616E+06 + 2.33600E+02 3.57281E+06 + 2.33700E+02 3.55898E+06 + 2.33800E+02 3.54467E+06 + 2.33900E+02 3.52991E+06 + 2.34000E+02 3.51468E+06 + 2.34100E+02 3.49901E+06 + 2.34200E+02 3.48291E+06 + 2.34300E+02 3.46637E+06 + 2.34400E+02 3.44943E+06 + 2.34500E+02 3.43207E+06 + 2.34600E+02 3.41433E+06 + 2.34700E+02 3.39620E+06 + 2.34800E+02 3.37770E+06 + 2.34900E+02 3.35884E+06 + 2.35000E+02 3.33963E+06 + 2.35100E+02 3.32009E+06 + 2.35200E+02 3.30022E+06 + 2.35300E+02 3.28004E+06 + 2.35400E+02 3.25958E+06 + 2.35500E+02 3.23881E+06 + 2.35600E+02 3.21778E+06 + 2.35700E+02 3.19649E+06 + 2.35800E+02 3.17496E+06 + 2.35900E+02 3.15320E+06 + 2.36000E+02 3.13121E+06 + 2.36100E+02 3.10903E+06 + 2.36200E+02 3.08665E+06 + 2.36300E+02 3.06409E+06 + 2.36400E+02 3.04138E+06 + 2.36500E+02 3.01852E+06 + 2.36600E+02 2.99553E+06 + 2.36700E+02 2.97241E+06 + 2.36800E+02 2.94920E+06 + 2.36900E+02 2.92590E+06 + 2.37000E+02 2.90252E+06 + 2.37100E+02 2.87908E+06 + 2.37200E+02 2.85560E+06 + 2.37300E+02 2.83208E+06 + 2.37400E+02 2.80856E+06 + 2.37500E+02 2.78503E+06 + 2.37600E+02 2.76152E+06 + 2.37700E+02 2.73804E+06 + 2.37800E+02 2.71460E+06 + 2.37900E+02 2.69123E+06 + 2.38000E+02 2.66792E+06 + 2.38100E+02 2.64471E+06 + 2.38200E+02 2.62159E+06 + 2.38300E+02 2.59860E+06 + 2.38400E+02 2.57574E+06 + 2.38500E+02 2.55303E+06 + 2.38600E+02 2.53048E+06 + 2.38700E+02 2.50810E+06 + 2.38800E+02 2.48591E+06 + 2.38900E+02 2.46393E+06 + 2.39000E+02 2.44216E+06 + 2.39100E+02 2.42063E+06 + 2.39200E+02 2.39934E+06 + 2.39300E+02 2.37830E+06 + 2.39400E+02 2.35755E+06 + 2.39500E+02 2.33707E+06 + 2.39600E+02 2.31690E+06 + 2.39700E+02 2.29703E+06 + 2.39800E+02 2.27749E+06 + 2.39900E+02 2.25829E+06 + 2.40000E+02 2.23942E+06 + 2.40100E+02 2.22093E+06 + 2.40200E+02 2.20279E+06 + 2.40300E+02 2.18505E+06 + 2.40400E+02 2.16770E+06 + 2.40500E+02 2.15075E+06 + 2.40600E+02 2.13422E+06 + 2.40700E+02 2.11811E+06 + 2.40800E+02 2.10244E+06 + 2.40900E+02 2.08722E+06 + 2.41000E+02 2.07245E+06 + 2.41100E+02 2.05815E+06 + 2.41200E+02 2.04431E+06 + 2.41300E+02 2.03097E+06 + 2.41400E+02 2.01811E+06 + 2.41500E+02 2.00576E+06 + 2.41600E+02 1.99391E+06 + 2.41700E+02 1.98257E+06 + 2.41800E+02 1.97176E+06 + 2.41900E+02 1.96148E+06 + 2.42000E+02 1.95172E+06 + 2.42100E+02 1.94252E+06 + 2.42200E+02 1.93385E+06 + 2.42300E+02 1.92575E+06 + 2.42400E+02 1.91820E+06 + 2.42500E+02 1.91121E+06 + 2.42600E+02 1.90478E+06 + 2.42700E+02 1.89893E+06 + 2.42800E+02 1.89366E+06 + 2.42900E+02 1.88896E+06 + 2.43000E+02 1.88484E+06 + 2.43100E+02 1.88131E+06 + 2.43200E+02 1.87836E+06 + 2.43300E+02 1.87600E+06 + 2.43400E+02 1.87422E+06 + 2.43500E+02 1.87304E+06 + 2.43600E+02 1.87245E+06 + 2.43700E+02 1.87245E+06 + 2.43800E+02 1.87304E+06 + 2.43900E+02 1.87422E+06 + 2.44000E+02 1.87600E+06 + 2.44100E+02 1.87836E+06 + 2.44200E+02 1.88131E+06 + 2.44300E+02 1.88484E+06 + 2.44400E+02 1.88896E+06 + 2.44500E+02 1.89366E+06 + 2.44600E+02 1.89893E+06 + 2.44700E+02 1.90479E+06 + 2.44800E+02 1.91121E+06 + 2.44900E+02 1.91820E+06 + 2.45000E+02 1.92575E+06 + 2.45100E+02 1.93386E+06 + 2.45200E+02 1.94252E+06 + 2.45300E+02 1.95173E+06 + 2.45400E+02 1.96148E+06 + 2.45500E+02 1.97176E+06 + 2.45600E+02 1.98257E+06 + 2.45700E+02 1.99391E+06 + 2.45800E+02 2.00576E+06 + 2.45900E+02 2.01812E+06 + 2.46000E+02 2.03097E+06 + 2.46100E+02 2.04432E+06 + 2.46200E+02 2.05815E+06 + 2.46300E+02 2.07245E+06 + 2.46400E+02 2.08722E+06 + 2.46500E+02 2.10245E+06 + 2.46600E+02 2.11812E+06 + 2.46700E+02 2.13422E+06 + 2.46800E+02 2.15075E+06 + 2.46900E+02 2.16770E+06 + 2.47000E+02 2.18505E+06 + 2.47100E+02 2.20280E+06 + 2.47200E+02 2.22093E+06 + 2.47300E+02 2.23943E+06 + 2.47400E+02 2.25829E+06 + 2.47500E+02 2.27750E+06 + 2.47600E+02 2.29704E+06 + 2.47700E+02 2.31691E+06 + 2.47800E+02 2.33708E+06 + 2.47900E+02 2.35755E+06 + 2.48000E+02 2.37831E+06 + 2.48100E+02 2.39934E+06 + 2.48200E+02 2.42064E+06 + 2.48300E+02 2.44217E+06 + 2.48400E+02 2.46393E+06 + 2.48500E+02 2.48592E+06 + 2.48600E+02 2.50810E+06 + 2.48700E+02 2.53048E+06 + 2.48800E+02 2.55303E+06 + 2.48900E+02 2.57575E+06 + 2.49000E+02 2.59861E+06 + 2.49100E+02 2.62160E+06 + 2.49200E+02 2.64471E+06 + 2.49300E+02 2.66793E+06 + 2.49400E+02 2.69123E+06 + 2.49500E+02 2.71461E+06 + 2.49600E+02 2.73805E+06 + 2.49700E+02 2.76153E+06 + 2.49800E+02 2.78504E+06 + 2.49900E+02 2.80857E+06 + 2.50000E+02 2.83210E+06 + 2.50100E+02 2.85561E+06 + 2.50200E+02 2.87909E+06 + 2.50300E+02 2.90253E+06 + 2.50400E+02 2.92590E+06 + 2.50500E+02 2.94921E+06 + 2.50600E+02 2.97242E+06 + 2.50700E+02 2.99554E+06 + 2.50800E+02 3.01853E+06 + 2.50900E+02 3.04139E+06 + 2.51000E+02 3.06410E+06 + 2.51100E+02 3.08665E+06 + 2.51200E+02 3.10903E+06 + 2.51300E+02 3.13122E+06 + 2.51400E+02 3.15320E+06 + 2.51500E+02 3.17497E+06 + 2.51600E+02 3.19650E+06 + 2.51700E+02 3.21779E+06 + 2.51800E+02 3.23882E+06 + 2.51900E+02 3.25958E+06 + 2.52000E+02 3.28005E+06 + 2.52100E+02 3.30023E+06 + 2.52200E+02 3.32009E+06 + 2.52300E+02 3.33964E+06 + 2.52400E+02 3.35884E+06 + 2.52500E+02 3.37770E+06 + 2.52600E+02 3.39620E+06 + 2.52700E+02 3.41433E+06 + 2.52800E+02 3.43208E+06 + 2.52900E+02 3.44943E+06 + 2.53000E+02 3.46638E+06 + 2.53100E+02 3.48291E+06 + 2.53200E+02 3.49902E+06 + 2.53300E+02 3.51469E+06 + 2.53400E+02 3.52991E+06 + 2.53500E+02 3.54468E+06 + 2.53600E+02 3.55898E+06 + 2.53700E+02 3.57281E+06 + 2.53800E+02 3.58616E+06 + 2.53900E+02 3.59902E+06 + 2.54000E+02 3.61137E+06 + 2.54100E+02 3.62322E+06 + 2.54200E+02 3.63456E+06 + 2.54300E+02 3.64537E+06 + 2.54400E+02 3.65565E+06 + 2.54500E+02 3.66540E+06 + 2.54600E+02 3.67461E+06 + 2.54700E+02 3.68327E+06 + 2.54800E+02 3.69138E+06 + 2.54900E+02 3.69893E+06 + 2.55000E+02 3.70592E+06 + 2.55100E+02 3.71234E+06 + 2.55200E+02 3.71820E+06 + 2.55300E+02 3.72347E+06 + 2.55400E+02 3.72817E+06 + 2.55500E+02 3.73229E+06 + 2.55600E+02 3.73582E+06 + 2.55700E+02 3.73877E+06 + 2.55800E+02 3.74113E+06 + 2.55900E+02 3.74290E+06 + 2.56000E+02 3.74409E+06 + 2.56100E+02 3.74468E+06 + 2.56200E+02 3.74468E+06 + 2.56300E+02 3.74409E+06 + 2.56400E+02 3.74290E+06 + 2.56500E+02 3.74113E+06 + 2.56600E+02 3.73877E+06 + 2.56700E+02 3.73582E+06 + 2.56800E+02 3.73229E+06 + 2.56900E+02 3.72817E+06 + 2.57000E+02 3.72347E+06 + 2.57100E+02 3.71819E+06 + 2.57200E+02 3.71234E+06 + 2.57300E+02 3.70592E+06 + 2.57400E+02 3.69893E+06 + 2.57500E+02 3.69138E+06 + 2.57600E+02 3.68327E+06 + 2.57700E+02 3.67461E+06 + 2.57800E+02 3.66540E+06 + 2.57900E+02 3.65565E+06 + 2.58000E+02 3.64537E+06 + 2.58100E+02 3.63455E+06 + 2.58200E+02 3.62322E+06 + 2.58300E+02 3.61137E+06 + 2.58400E+02 3.59901E+06 + 2.58500E+02 3.58616E+06 + 2.58600E+02 3.57281E+06 + 2.58700E+02 3.55898E+06 + 2.58800E+02 3.54468E+06 + 2.58900E+02 3.52991E+06 + 2.59000E+02 3.51468E+06 + 2.59100E+02 3.49901E+06 + 2.59200E+02 3.48290E+06 + 2.59300E+02 3.46637E+06 + 2.59400E+02 3.44943E+06 + 2.59500E+02 3.43208E+06 + 2.59600E+02 3.41432E+06 + 2.59700E+02 3.39620E+06 + 2.59800E+02 3.37770E+06 + 2.59900E+02 3.35884E+06 + 2.60000E+02 3.33963E+06 + 2.60100E+02 3.32009E+06 + 2.60200E+02 3.30022E+06 + 2.60300E+02 3.28005E+06 + 2.60400E+02 3.25957E+06 + 2.60500E+02 3.23882E+06 + 2.60600E+02 3.21778E+06 + 2.60700E+02 3.19649E+06 + 2.60800E+02 3.17496E+06 + 2.60900E+02 3.15319E+06 + 2.61000E+02 3.13121E+06 + 2.61100E+02 3.10902E+06 + 2.61200E+02 3.08664E+06 + 2.61300E+02 3.06409E+06 + 2.61400E+02 3.04138E+06 + 2.61500E+02 3.01852E+06 + 2.61600E+02 2.99552E+06 + 2.61700E+02 2.97241E+06 + 2.61800E+02 2.94920E+06 + 2.61900E+02 2.92590E+06 + 2.62000E+02 2.90252E+06 + 2.62100E+02 2.87908E+06 + 2.62200E+02 2.85560E+06 + 2.62300E+02 2.83209E+06 + 2.62400E+02 2.80856E+06 + 2.62500E+02 2.78504E+06 + 2.62600E+02 2.76152E+06 + 2.62700E+02 2.73804E+06 + 2.62800E+02 2.71460E+06 + 2.62900E+02 2.69122E+06 + 2.63000E+02 2.66792E+06 + 2.63100E+02 2.64470E+06 + 2.63200E+02 2.62159E+06 + 2.63300E+02 2.59860E+06 + 2.63400E+02 2.57574E+06 + 2.63500E+02 2.55303E+06 + 2.63600E+02 2.53047E+06 + 2.63700E+02 2.50809E+06 + 2.63800E+02 2.48591E+06 + 2.63900E+02 2.46393E+06 + 2.64000E+02 2.44216E+06 + 2.64100E+02 2.42062E+06 + 2.64200E+02 2.39934E+06 + 2.64300E+02 2.37831E+06 + 2.64400E+02 2.35755E+06 + 2.64500E+02 2.33708E+06 + 2.64600E+02 2.31689E+06 + 2.64700E+02 2.29703E+06 + 2.64800E+02 2.27750E+06 + 2.64900E+02 2.25828E+06 + 2.65000E+02 2.23942E+06 + 2.65100E+02 2.22092E+06 + 2.65200E+02 2.20279E+06 + 2.65300E+02 2.18505E+06 + 2.65400E+02 2.16770E+06 + 2.65500E+02 2.15075E+06 + 2.65600E+02 2.13421E+06 + 2.65700E+02 2.11811E+06 + 2.65800E+02 2.10244E+06 + 2.65900E+02 2.08722E+06 + 2.66000E+02 2.07245E+06 + 2.66100E+02 2.05814E+06 + 2.66200E+02 2.04431E+06 + 2.66300E+02 2.03097E+06 + 2.66400E+02 2.01811E+06 + 2.66500E+02 2.00576E+06 + 2.66600E+02 1.99390E+06 + 2.66700E+02 1.98257E+06 + 2.66800E+02 1.97176E+06 + 2.66900E+02 1.96147E+06 + 2.67000E+02 1.95173E+06 + 2.67100E+02 1.94251E+06 + 2.67200E+02 1.93385E+06 + 2.67300E+02 1.92575E+06 + 2.67400E+02 1.91820E+06 + 2.67500E+02 1.91121E+06 + 2.67600E+02 1.90478E+06 + 2.67700E+02 1.89893E+06 + 2.67800E+02 1.89366E+06 + 2.67900E+02 1.88896E+06 + 2.68000E+02 1.88484E+06 + 2.68100E+02 1.88130E+06 + 2.68200E+02 1.87836E+06 + 2.68300E+02 1.87600E+06 + 2.68400E+02 1.87422E+06 + 2.68500E+02 1.87304E+06 + 2.68600E+02 1.87245E+06 + 2.68700E+02 1.87245E+06 + 2.68800E+02 1.87304E+06 + 2.68900E+02 1.87422E+06 + 2.69000E+02 1.87600E+06 + 2.69100E+02 1.87836E+06 + 2.69200E+02 1.88131E+06 + 2.69300E+02 1.88484E+06 + 2.69400E+02 1.88896E+06 + 2.69500E+02 1.89366E+06 + 2.69600E+02 1.89894E+06 + 2.69700E+02 1.90479E+06 + 2.69800E+02 1.91121E+06 + 2.69900E+02 1.91820E+06 + 2.70000E+02 1.92575E+06 + 2.70100E+02 1.93386E+06 + 2.70200E+02 1.94252E+06 + 2.70300E+02 1.95173E+06 + 2.70400E+02 1.96148E+06 + 2.70500E+02 1.97176E+06 + 2.70600E+02 1.98258E+06 + 2.70700E+02 1.99391E+06 + 2.70800E+02 2.00576E+06 + 2.70900E+02 2.01812E+06 + 2.71000E+02 2.03097E+06 + 2.71100E+02 2.04432E+06 + 2.71200E+02 2.05815E+06 + 2.71300E+02 2.07245E+06 + 2.71400E+02 2.08722E+06 + 2.71500E+02 2.10244E+06 + 2.71600E+02 2.11812E+06 + 2.71700E+02 2.13422E+06 + 2.71800E+02 2.15075E+06 + 2.71900E+02 2.16770E+06 + 2.72000E+02 2.18505E+06 + 2.72100E+02 2.20280E+06 + 2.72200E+02 2.22093E+06 + 2.72300E+02 2.23943E+06 + 2.72400E+02 2.25829E+06 + 2.72500E+02 2.27750E+06 + 2.72600E+02 2.29704E+06 + 2.72700E+02 2.31691E+06 + 2.72800E+02 2.33708E+06 + 2.72900E+02 2.35756E+06 + 2.73000E+02 2.37831E+06 + 2.73100E+02 2.39935E+06 + 2.73200E+02 2.42064E+06 + 2.73300E+02 2.44216E+06 + 2.73400E+02 2.46393E+06 + 2.73500E+02 2.48592E+06 + 2.73600E+02 2.50811E+06 + 2.73700E+02 2.53048E+06 + 2.73800E+02 2.55303E+06 + 2.73900E+02 2.57575E+06 + 2.74000E+02 2.59861E+06 + 2.74100E+02 2.62161E+06 + 2.74200E+02 2.64472E+06 + 2.74300E+02 2.66792E+06 + 2.74400E+02 2.69123E+06 + 2.74500E+02 2.71461E+06 + 2.74600E+02 2.73805E+06 + 2.74700E+02 2.76153E+06 + 2.74800E+02 2.78504E+06 + 2.74900E+02 2.80857E+06 + 2.75000E+02 2.83209E+06 + 2.75100E+02 2.85561E+06 + 2.75200E+02 2.87909E+06 + 2.75300E+02 2.90252E+06 + 2.75400E+02 2.92590E+06 + 2.75500E+02 2.94921E+06 + 2.75600E+02 2.97243E+06 + 2.75700E+02 2.99554E+06 + 2.75800E+02 3.01852E+06 + 2.75900E+02 3.04139E+06 + 2.76000E+02 3.06410E+06 + 2.76100E+02 3.08666E+06 + 2.76200E+02 3.10904E+06 + 2.76300E+02 3.13121E+06 + 2.76400E+02 3.15320E+06 + 2.76500E+02 3.17497E+06 + 2.76600E+02 3.19651E+06 + 2.76700E+02 3.21779E+06 + 2.76800E+02 3.23882E+06 + 2.76900E+02 3.25958E+06 + 2.77000E+02 3.28005E+06 + 2.77100E+02 3.30023E+06 + 2.77200E+02 3.32010E+06 + 2.77300E+02 3.33963E+06 + 2.77400E+02 3.35885E+06 + 2.77500E+02 3.37770E+06 + 2.77600E+02 3.39621E+06 + 2.77700E+02 3.41434E+06 + 2.77800E+02 3.43208E+06 + 2.77900E+02 3.44943E+06 + 2.78000E+02 3.46638E+06 + 2.78100E+02 3.48292E+06 + 2.78200E+02 3.49902E+06 + 2.78300E+02 3.51468E+06 + 2.78400E+02 3.52991E+06 + 2.78500E+02 3.54468E+06 + 2.78600E+02 3.55899E+06 + 2.78700E+02 3.57282E+06 + 2.78800E+02 3.58616E+06 + 2.78900E+02 3.59902E+06 + 2.79000E+02 3.61137E+06 + 2.79100E+02 3.62322E+06 + 2.79200E+02 3.63456E+06 + 2.79300E+02 3.64537E+06 + 2.79400E+02 3.65565E+06 + 2.79500E+02 3.66540E+06 + 2.79600E+02 3.67461E+06 + 2.79700E+02 3.68327E+06 + 2.79800E+02 3.69138E+06 + 2.79900E+02 3.69893E+06 + 2.80000E+02 3.70592E+06 + 2.80100E+02 3.71235E+06 + 2.80200E+02 3.71820E+06 + 2.80300E+02 3.72347E+06 + 2.80400E+02 3.72817E+06 + 2.80500E+02 3.73229E+06 + 2.80600E+02 3.73582E+06 + 2.80700E+02 3.73877E+06 + 2.80800E+02 3.74113E+06 + 2.80900E+02 3.74290E+06 + 2.81000E+02 3.74409E+06 + 2.81100E+02 3.74468E+06 + 2.81200E+02 3.74468E+06 + 2.81300E+02 3.74409E+06 + 2.81400E+02 3.74290E+06 + 2.81500E+02 3.74113E+06 + 2.81600E+02 3.73877E+06 + 2.81700E+02 3.73582E+06 + 2.81800E+02 3.73229E+06 + 2.81900E+02 3.72817E+06 + 2.82000E+02 3.72347E+06 + 2.82100E+02 3.71819E+06 + 2.82200E+02 3.71234E+06 + 2.82300E+02 3.70592E+06 + 2.82400E+02 3.69893E+06 + 2.82500E+02 3.69138E+06 + 2.82600E+02 3.68327E+06 + 2.82700E+02 3.67461E+06 + 2.82800E+02 3.66540E+06 + 2.82900E+02 3.65565E+06 + 2.83000E+02 3.64537E+06 + 2.83100E+02 3.63455E+06 + 2.83200E+02 3.62322E+06 + 2.83300E+02 3.61137E+06 + 2.83400E+02 3.59901E+06 + 2.83500E+02 3.58616E+06 + 2.83600E+02 3.57281E+06 + 2.83700E+02 3.55898E+06 + 2.83800E+02 3.54468E+06 + 2.83900E+02 3.52991E+06 + 2.84000E+02 3.51468E+06 + 2.84100E+02 3.49901E+06 + 2.84200E+02 3.48290E+06 + 2.84300E+02 3.46638E+06 + 2.84400E+02 3.44942E+06 + 2.84500E+02 3.43207E+06 + 2.84600E+02 3.41433E+06 + 2.84700E+02 3.39619E+06 + 2.84800E+02 3.37770E+06 + 2.84900E+02 3.35884E+06 + 2.85000E+02 3.33963E+06 + 2.85100E+02 3.32009E+06 + 2.85200E+02 3.30022E+06 + 2.85300E+02 3.28005E+06 + 2.85400E+02 3.25957E+06 + 2.85500E+02 3.23881E+06 + 2.85600E+02 3.21778E+06 + 2.85700E+02 3.19649E+06 + 2.85800E+02 3.17496E+06 + 2.85900E+02 3.15319E+06 + 2.86000E+02 3.13121E+06 + 2.86100E+02 3.10902E+06 + 2.86200E+02 3.08664E+06 + 2.86300E+02 3.06410E+06 + 2.86400E+02 3.04138E+06 + 2.86500E+02 3.01852E+06 + 2.86600E+02 2.99553E+06 + 2.86700E+02 2.97241E+06 + 2.86800E+02 2.94920E+06 + 2.86900E+02 2.92589E+06 + 2.87000E+02 2.90252E+06 + 2.87100E+02 2.87908E+06 + 2.87200E+02 2.85559E+06 + 2.87300E+02 2.83209E+06 + 2.87400E+02 2.80856E+06 + 2.87500E+02 2.78503E+06 + 2.87600E+02 2.76152E+06 + 2.87700E+02 2.73804E+06 + 2.87800E+02 2.71461E+06 + 2.87900E+02 2.69122E+06 + 2.88000E+02 2.66792E+06 + 2.88100E+02 2.64471E+06 + 2.88200E+02 2.62159E+06 + 2.88300E+02 2.59860E+06 + 2.88400E+02 2.57574E+06 + 2.88500E+02 2.55302E+06 + 2.88600E+02 2.53047E+06 + 2.88700E+02 2.50809E+06 + 2.88800E+02 2.48591E+06 + 2.88900E+02 2.46392E+06 + 2.89000E+02 2.44216E+06 + 2.89100E+02 2.42063E+06 + 2.89200E+02 2.39933E+06 + 2.89300E+02 2.37831E+06 + 2.89400E+02 2.35755E+06 + 2.89500E+02 2.33707E+06 + 2.89600E+02 2.31690E+06 + 2.89700E+02 2.29703E+06 + 2.89800E+02 2.27749E+06 + 2.89900E+02 2.25828E+06 + 2.90000E+02 2.23942E+06 + 2.90100E+02 2.22092E+06 + 2.90200E+02 2.20279E+06 + 2.90300E+02 2.18505E+06 + 2.90400E+02 2.16769E+06 + 2.90500E+02 2.15075E+06 + 2.90600E+02 2.13422E+06 + 2.90700E+02 2.11811E+06 + 2.90800E+02 2.10244E+06 + 2.90900E+02 2.08721E+06 + 2.91000E+02 2.07245E+06 + 2.91100E+02 2.05814E+06 + 2.91200E+02 2.04431E+06 + 2.91300E+02 2.03097E+06 + 2.91400E+02 2.01811E+06 + 2.91500E+02 2.00576E+06 + 2.91600E+02 1.99391E+06 + 2.91700E+02 1.98257E+06 + 2.91800E+02 1.97176E+06 + 2.91900E+02 1.96147E+06 + 2.92000E+02 1.95172E+06 + 2.92100E+02 1.94252E+06 + 2.92200E+02 1.93385E+06 + 2.92300E+02 1.92575E+06 + 2.92400E+02 1.91819E+06 + 2.92500E+02 1.91121E+06 + 2.92600E+02 1.90478E+06 + 2.92700E+02 1.89893E+06 + 2.92800E+02 1.89366E+06 + 2.92900E+02 1.88896E+06 + 2.93000E+02 1.88484E+06 + 2.93100E+02 1.88131E+06 + 2.93200E+02 1.87836E+06 + 2.93300E+02 1.87600E+06 + 2.93400E+02 1.87422E+06 + 2.93500E+02 1.87304E+06 + 2.93600E+02 1.87245E+06 + 2.93700E+02 1.87245E+06 + 2.93800E+02 1.87304E+06 + 2.93900E+02 1.87422E+06 + 2.94000E+02 1.87600E+06 + 2.94100E+02 1.87836E+06 + 2.94200E+02 1.88131E+06 + 2.94300E+02 1.88484E+06 + 2.94400E+02 1.88896E+06 + 2.94500E+02 1.89366E+06 + 2.94600E+02 1.89893E+06 + 2.94700E+02 1.90479E+06 + 2.94800E+02 1.91121E+06 + 2.94900E+02 1.91820E+06 + 2.95000E+02 1.92575E+06 + 2.95100E+02 1.93386E+06 + 2.95200E+02 1.94252E+06 + 2.95300E+02 1.95173E+06 + 2.95400E+02 1.96148E+06 + 2.95500E+02 1.97176E+06 + 2.95600E+02 1.98258E+06 + 2.95700E+02 1.99391E+06 + 2.95800E+02 2.00576E+06 + 2.95900E+02 2.01812E+06 + 2.96000E+02 2.03097E+06 + 2.96100E+02 2.04432E+06 + 2.96200E+02 2.05815E+06 + 2.96300E+02 2.07245E+06 + 2.96400E+02 2.08722E+06 + 2.96500E+02 2.10245E+06 + 2.96600E+02 2.11812E+06 + 2.96700E+02 2.13423E+06 + 2.96800E+02 2.15075E+06 + 2.96900E+02 2.16770E+06 + 2.97000E+02 2.18506E+06 + 2.97100E+02 2.20280E+06 + 2.97200E+02 2.22093E+06 + 2.97300E+02 2.23943E+06 + 2.97400E+02 2.25829E+06 + 2.97500E+02 2.27750E+06 + 2.97600E+02 2.29704E+06 + 2.97700E+02 2.31691E+06 + 2.97800E+02 2.33708E+06 + 2.97900E+02 2.35756E+06 + 2.98000E+02 2.37832E+06 + 2.98100E+02 2.39935E+06 + 2.98200E+02 2.42064E+06 + 2.98300E+02 2.44217E+06 + 2.98400E+02 2.46394E+06 + 2.98500E+02 2.48592E+06 + 2.98600E+02 2.50810E+06 + 2.98700E+02 2.53049E+06 + 2.98800E+02 2.55303E+06 + 2.98900E+02 2.57574E+06 + 2.99000E+02 2.59861E+06 + 2.99100E+02 2.62160E+06 + 2.99200E+02 2.64472E+06 + 2.99300E+02 2.66793E+06 + 2.99400E+02 2.69123E+06 + 2.99500E+02 2.71461E+06 + 2.99600E+02 2.73805E+06 + 2.99700E+02 2.76154E+06 + 2.99800E+02 2.78504E+06 + 2.99900E+02 2.80856E+06 + 3.00000E+02 2.83210E+06 + 3.00100E+02 2.85561E+06 + 3.00200E+02 2.87909E+06 + 3.00300E+02 2.90252E+06 + 3.00400E+02 2.92590E+06 + 3.00500E+02 2.94921E+06 + 3.00600E+02 2.97242E+06 + 3.00700E+02 2.99554E+06 + 3.00800E+02 3.01853E+06 + 3.00900E+02 3.04138E+06 + 3.01000E+02 3.06410E+06 + 3.01100E+02 3.08666E+06 + 3.01200E+02 3.10904E+06 + 3.01300E+02 3.13122E+06 + 3.01400E+02 3.15320E+06 + 3.01500E+02 3.17497E+06 + 3.01600E+02 3.19650E+06 + 3.01700E+02 3.21780E+06 + 3.01800E+02 3.23882E+06 + 3.01900E+02 3.25958E+06 + 3.02000E+02 3.28006E+06 + 3.02100E+02 3.30023E+06 + 3.02200E+02 3.32010E+06 + 3.02300E+02 3.33964E+06 + 3.02400E+02 3.35884E+06 + 3.02500E+02 3.37771E+06 + 3.02600E+02 3.39620E+06 + 3.02700E+02 3.41434E+06 + 3.02800E+02 3.43208E+06 + 3.02900E+02 3.44943E+06 + 3.03000E+02 3.46638E+06 + 3.03100E+02 3.48291E+06 + 3.03200E+02 3.49902E+06 + 3.03300E+02 3.51469E+06 + 3.03400E+02 3.52991E+06 + 3.03500E+02 3.54468E+06 + 3.03600E+02 3.55898E+06 + 3.03700E+02 3.57282E+06 + 3.03800E+02 3.58616E+06 + 3.03900E+02 3.59901E+06 + 3.04000E+02 3.61137E+06 + 3.04100E+02 3.62322E+06 + 3.04200E+02 3.63456E+06 + 3.04300E+02 3.64537E+06 + 3.04400E+02 3.65565E+06 + 3.04500E+02 3.66540E+06 + 3.04600E+02 3.67461E+06 + 3.04700E+02 3.68328E+06 + 3.04800E+02 3.69138E+06 + 3.04900E+02 3.69893E+06 + 3.05000E+02 3.70592E+06 + 3.05100E+02 3.71234E+06 + 3.05200E+02 3.71820E+06 + 3.05300E+02 3.72347E+06 + 3.05400E+02 3.72817E+06 + 3.05500E+02 3.73229E+06 + 3.05600E+02 3.73582E+06 + 3.05700E+02 3.73877E+06 + 3.05800E+02 3.74113E+06 + 3.05900E+02 3.74290E+06 + 3.06000E+02 3.74409E+06 + 3.06100E+02 3.74468E+06 + 3.06200E+02 3.74468E+06 + 3.06300E+02 3.74409E+06 + 3.06400E+02 3.74290E+06 + 3.06500E+02 3.74113E+06 + 3.06600E+02 3.73877E+06 + 3.06700E+02 3.73582E+06 + 3.06800E+02 3.73229E+06 + 3.06900E+02 3.72817E+06 + 3.07000E+02 3.72347E+06 + 3.07100E+02 3.71819E+06 + 3.07200E+02 3.71234E+06 + 3.07300E+02 3.70592E+06 + 3.07400E+02 3.69893E+06 + 3.07500E+02 3.69138E+06 + 3.07600E+02 3.68327E+06 + 3.07700E+02 3.67461E+06 + 3.07800E+02 3.66540E+06 + 3.07900E+02 3.65565E+06 + 3.08000E+02 3.64536E+06 + 3.08100E+02 3.63455E+06 + 3.08200E+02 3.62321E+06 + 3.08300E+02 3.61137E+06 + 3.08400E+02 3.59901E+06 + 3.08500E+02 3.58615E+06 + 3.08600E+02 3.57281E+06 + 3.08700E+02 3.55897E+06 + 3.08800E+02 3.54468E+06 + 3.08900E+02 3.52991E+06 + 3.09000E+02 3.51468E+06 + 3.09100E+02 3.49901E+06 + 3.09200E+02 3.48290E+06 + 3.09300E+02 3.46637E+06 + 3.09400E+02 3.44943E+06 + 3.09500E+02 3.43207E+06 + 3.09600E+02 3.41433E+06 + 3.09700E+02 3.39619E+06 + 3.09800E+02 3.37770E+06 + 3.09900E+02 3.35884E+06 + 3.10000E+02 3.33963E+06 + 3.10100E+02 3.32009E+06 + 3.10200E+02 3.30022E+06 + 3.10300E+02 3.28005E+06 + 3.10400E+02 3.25958E+06 + 3.10500E+02 3.23881E+06 + 3.10600E+02 3.21778E+06 + 3.10700E+02 3.19649E+06 + 3.10800E+02 3.17496E+06 + 3.10900E+02 3.15320E+06 + 3.11000E+02 3.13121E+06 + 3.11100E+02 3.10902E+06 + 3.11200E+02 3.08664E+06 + 3.11300E+02 3.06410E+06 + 3.11400E+02 3.04138E+06 + 3.11500E+02 3.01852E+06 + 3.11600E+02 2.99552E+06 + 3.11700E+02 2.97241E+06 + 3.11800E+02 2.94920E+06 + 3.11900E+02 2.92590E+06 + 3.12000E+02 2.90251E+06 + 3.12100E+02 2.87908E+06 + 3.12200E+02 2.85559E+06 + 3.12300E+02 2.83209E+06 + 3.12400E+02 2.80856E+06 + 3.12500E+02 2.78503E+06 + 3.12600E+02 2.76152E+06 + 3.12700E+02 2.73803E+06 + 3.12800E+02 2.71460E+06 + 3.12900E+02 2.69123E+06 + 3.13000E+02 2.66792E+06 + 3.13100E+02 2.64470E+06 + 3.13200E+02 2.62159E+06 + 3.13300E+02 2.59860E+06 + 3.13400E+02 2.57574E+06 + 3.13500E+02 2.55302E+06 + 3.13600E+02 2.53047E+06 + 3.13700E+02 2.50809E+06 + 3.13800E+02 2.48591E+06 + 3.13900E+02 2.46393E+06 + 3.14000E+02 2.44216E+06 + 3.14100E+02 2.42063E+06 + 3.14200E+02 2.39933E+06 + 3.14300E+02 2.37831E+06 + 3.14400E+02 2.35755E+06 + 3.14500E+02 2.33707E+06 + 3.14600E+02 2.31690E+06 + 3.14700E+02 2.29703E+06 + 3.14800E+02 2.27749E+06 + 3.14900E+02 2.25829E+06 + 3.15000E+02 2.23942E+06 + 3.15100E+02 2.22092E+06 + 3.15200E+02 2.20279E+06 + 3.15300E+02 2.18505E+06 + 3.15400E+02 2.16770E+06 + 3.15500E+02 2.15075E+06 + 3.15600E+02 2.13422E+06 + 3.15700E+02 2.11810E+06 + 3.15800E+02 2.10244E+06 + 3.15900E+02 2.08722E+06 + 3.16000E+02 2.07245E+06 + 3.16100E+02 2.05814E+06 + 3.16200E+02 2.04431E+06 + 3.16300E+02 2.03097E+06 + 3.16400E+02 2.01811E+06 + 3.16500E+02 2.00575E+06 + 3.16600E+02 1.99391E+06 + 3.16700E+02 1.98257E+06 + 3.16800E+02 1.97176E+06 + 3.16900E+02 1.96148E+06 + 3.17000E+02 1.95172E+06 + 3.17100E+02 1.94252E+06 + 3.17200E+02 1.93385E+06 + 3.17300E+02 1.92575E+06 + 3.17400E+02 1.91820E+06 + 3.17500E+02 1.91121E+06 + 3.17600E+02 1.90478E+06 + 3.17700E+02 1.89893E+06 + 3.17800E+02 1.89366E+06 + 3.17900E+02 1.88896E+06 + 3.18000E+02 1.88484E+06 + 3.18100E+02 1.88131E+06 + 3.18200E+02 1.87836E+06 + 3.18300E+02 1.87600E+06 + 3.18400E+02 1.87422E+06 + 3.18500E+02 1.87304E+06 + 3.18600E+02 1.87245E+06 + 3.18700E+02 1.87245E+06 + 3.18800E+02 1.87304E+06 + 3.18900E+02 1.87422E+06 + 3.19000E+02 1.87600E+06 + 3.19100E+02 1.87836E+06 + 3.19200E+02 1.88131E+06 + 3.19300E+02 1.88484E+06 + 3.19400E+02 1.88896E+06 + 3.19500E+02 1.89366E+06 + 3.19600E+02 1.89894E+06 + 3.19700E+02 1.90479E+06 + 3.19800E+02 1.91121E+06 + 3.19900E+02 1.91820E+06 + 3.20000E+02 1.92575E+06 + 3.20100E+02 1.93386E+06 + 3.20200E+02 1.94252E+06 + 3.20300E+02 1.95173E+06 + 3.20400E+02 1.96148E+06 + 3.20500E+02 1.97176E+06 + 3.20600E+02 1.98258E+06 + 3.20700E+02 1.99391E+06 + 3.20800E+02 2.00576E+06 + 3.20900E+02 2.01812E+06 + 3.21000E+02 2.03097E+06 + 3.21100E+02 2.04432E+06 + 3.21200E+02 2.05815E+06 + 3.21300E+02 2.07245E+06 + 3.21400E+02 2.08722E+06 + 3.21500E+02 2.10245E+06 + 3.21600E+02 2.11812E+06 + 3.21700E+02 2.13422E+06 + 3.21800E+02 2.15075E+06 + 3.21900E+02 2.16770E+06 + 3.22000E+02 2.18506E+06 + 3.22100E+02 2.20280E+06 + 3.22200E+02 2.22093E+06 + 3.22300E+02 2.23943E+06 + 3.22400E+02 2.25829E+06 + 3.22500E+02 2.27750E+06 + 3.22600E+02 2.29704E+06 + 3.22700E+02 2.31691E+06 + 3.22800E+02 2.33708E+06 + 3.22900E+02 2.35755E+06 + 3.23000E+02 2.37832E+06 + 3.23100E+02 2.39935E+06 + 3.23200E+02 2.42064E+06 + 3.23300E+02 2.44217E+06 + 3.23400E+02 2.46393E+06 + 3.23500E+02 2.48592E+06 + 3.23600E+02 2.50811E+06 + 3.23700E+02 2.53048E+06 + 3.23800E+02 2.55303E+06 + 3.23900E+02 2.57575E+06 + 3.24000E+02 2.59861E+06 + 3.24100E+02 2.62160E+06 + 3.24200E+02 2.64471E+06 + 3.24300E+02 2.66793E+06 + 3.24400E+02 2.69123E+06 + 3.24500E+02 2.71461E+06 + 3.24600E+02 2.73805E+06 + 3.24700E+02 2.76153E+06 + 3.24800E+02 2.78504E+06 + 3.24900E+02 2.80857E+06 + 3.25000E+02 2.83210E+06 + 3.25100E+02 2.85561E+06 + 3.25200E+02 2.87909E+06 + 3.25300E+02 2.90253E+06 + 3.25400E+02 2.92590E+06 + 3.25500E+02 2.94921E+06 + 3.25600E+02 2.97243E+06 + 3.25700E+02 2.99554E+06 + 3.25800E+02 3.01853E+06 + 3.25900E+02 3.04139E+06 + 3.26000E+02 3.06411E+06 + 3.26100E+02 3.08666E+06 + 3.26200E+02 3.10903E+06 + 3.26300E+02 3.13122E+06 + 3.26400E+02 3.15320E+06 + 3.26500E+02 3.17497E+06 + 3.26600E+02 3.19650E+06 + 3.26700E+02 3.21779E+06 + 3.26800E+02 3.23882E+06 + 3.26900E+02 3.25958E+06 + 3.27000E+02 3.28006E+06 + 3.27100E+02 3.30023E+06 + 3.27200E+02 3.32010E+06 + 3.27300E+02 3.33964E+06 + 3.27400E+02 3.35884E+06 + 3.27500E+02 3.37771E+06 + 3.27600E+02 3.39621E+06 + 3.27700E+02 3.41433E+06 + 3.27800E+02 3.43208E+06 + 3.27900E+02 3.44943E+06 + 3.28000E+02 3.46638E+06 + 3.28100E+02 3.48291E+06 + 3.28200E+02 3.49902E+06 + 3.28300E+02 3.51469E+06 + 3.28400E+02 3.52991E+06 + 3.28500E+02 3.54468E+06 + 3.28600E+02 3.55899E+06 + 3.28700E+02 3.57281E+06 + 3.28800E+02 3.58616E+06 + 3.28900E+02 3.59902E+06 + 3.29000E+02 3.61137E+06 + 3.29100E+02 3.62322E+06 + 3.29200E+02 3.63456E+06 + 3.29300E+02 3.64537E+06 + 3.29400E+02 3.65565E+06 + 3.29500E+02 3.66541E+06 + 3.29600E+02 3.67461E+06 + 3.29700E+02 3.68327E+06 + 3.29800E+02 3.69138E+06 + 3.29900E+02 3.69893E+06 + 3.30000E+02 3.70592E+06 + 3.30100E+02 3.71234E+06 + 3.30200E+02 3.71820E+06 + 3.30300E+02 3.72347E+06 + 3.30400E+02 3.72817E+06 + 3.30500E+02 3.73229E+06 + 3.30600E+02 3.73582E+06 + 3.30700E+02 3.73877E+06 + 3.30800E+02 3.74113E+06 + 3.30900E+02 3.74290E+06 + 3.31000E+02 3.74409E+06 + 3.31100E+02 3.74468E+06 + 3.31200E+02 3.74468E+06 + 3.31300E+02 3.74409E+06 + 3.31400E+02 3.74290E+06 + 3.31500E+02 3.74113E+06 + 3.31600E+02 3.73877E+06 + 3.31700E+02 3.73582E+06 + 3.31800E+02 3.73229E+06 + 3.31900E+02 3.72817E+06 + 3.32000E+02 3.72347E+06 + 3.32100E+02 3.71819E+06 + 3.32200E+02 3.71234E+06 + 3.32300E+02 3.70592E+06 + 3.32400E+02 3.69893E+06 + 3.32500E+02 3.69138E+06 + 3.32600E+02 3.68327E+06 + 3.32700E+02 3.67461E+06 + 3.32800E+02 3.66540E+06 + 3.32900E+02 3.65565E+06 + 3.33000E+02 3.64537E+06 + 3.33100E+02 3.63455E+06 + 3.33200E+02 3.62322E+06 + 3.33300E+02 3.61137E+06 + 3.33400E+02 3.59901E+06 + 3.33500E+02 3.58616E+06 + 3.33600E+02 3.57281E+06 + 3.33700E+02 3.55898E+06 + 3.33800E+02 3.54467E+06 + 3.33900E+02 3.52991E+06 + 3.34000E+02 3.51468E+06 + 3.34100E+02 3.49901E+06 + 3.34200E+02 3.48290E+06 + 3.34300E+02 3.46637E+06 + 3.34400E+02 3.44943E+06 + 3.34500E+02 3.43207E+06 + 3.34600E+02 3.41432E+06 + 3.34700E+02 3.39620E+06 + 3.34800E+02 3.37770E+06 + 3.34900E+02 3.35884E+06 + 3.35000E+02 3.33963E+06 + 3.35100E+02 3.32009E+06 + 3.35200E+02 3.30022E+06 + 3.35300E+02 3.28005E+06 + 3.35400E+02 3.25957E+06 + 3.35500E+02 3.23882E+06 + 3.35600E+02 3.21778E+06 + 3.35700E+02 3.19649E+06 + 3.35800E+02 3.17496E+06 + 3.35900E+02 3.15319E+06 + 3.36000E+02 3.13121E+06 + 3.36100E+02 3.10902E+06 + 3.36200E+02 3.08664E+06 + 3.36300E+02 3.06409E+06 + 3.36400E+02 3.04138E+06 + 3.36500E+02 3.01852E+06 + 3.36600E+02 2.99552E+06 + 3.36700E+02 2.97241E+06 + 3.36800E+02 2.94920E+06 + 3.36900E+02 2.92590E+06 + 3.37000E+02 2.90252E+06 + 3.37100E+02 2.87908E+06 + 3.37200E+02 2.85560E+06 + 3.37300E+02 2.83209E+06 + 3.37400E+02 2.80856E+06 + 3.37500E+02 2.78504E+06 + 3.37600E+02 2.76152E+06 + 3.37700E+02 2.73804E+06 + 3.37800E+02 2.71460E+06 + 3.37900E+02 2.69122E+06 + 3.38000E+02 2.66792E+06 + 3.38100E+02 2.64470E+06 + 3.38200E+02 2.62159E+06 + 3.38300E+02 2.59860E+06 + 3.38400E+02 2.57574E+06 + 3.38500E+02 2.55303E+06 + 3.38600E+02 2.53047E+06 + 3.38700E+02 2.50809E+06 + 3.38800E+02 2.48591E+06 + 3.38900E+02 2.46393E+06 + 3.39000E+02 2.44216E+06 + 3.39100E+02 2.42062E+06 + 3.39200E+02 2.39934E+06 + 3.39300E+02 2.37831E+06 + 3.39400E+02 2.35755E+06 + 3.39500E+02 2.33708E+06 + 3.39600E+02 2.31689E+06 + 3.39700E+02 2.29703E+06 + 3.39800E+02 2.27749E+06 + 3.39900E+02 2.25828E+06 + 3.40000E+02 2.23942E+06 + 3.40100E+02 2.22092E+06 + 3.40200E+02 2.20279E+06 + 3.40300E+02 2.18505E+06 + 3.40400E+02 2.16770E+06 + 3.40500E+02 2.15075E+06 + 3.40600E+02 2.13421E+06 + 3.40700E+02 2.11811E+06 + 3.40800E+02 2.10244E+06 + 3.40900E+02 2.08722E+06 + 3.41000E+02 2.07245E+06 + 3.41100E+02 2.05814E+06 + 3.41200E+02 2.04431E+06 + 3.41300E+02 2.03097E+06 + 3.41400E+02 2.01811E+06 + 3.41500E+02 2.00576E+06 + 3.41600E+02 1.99390E+06 + 3.41700E+02 1.98257E+06 + 3.41800E+02 1.97176E+06 + 3.41900E+02 1.96147E+06 + 3.42000E+02 1.95172E+06 + 3.42100E+02 1.94251E+06 + 3.42200E+02 1.93385E+06 + 3.42300E+02 1.92575E+06 + 3.42400E+02 1.91820E+06 + 3.42500E+02 1.91121E+06 + 3.42600E+02 1.90478E+06 + 3.42700E+02 1.89893E+06 + 3.42800E+02 1.89366E+06 + 3.42900E+02 1.88896E+06 + 3.43000E+02 1.88484E+06 + 3.43100E+02 1.88130E+06 + 3.43200E+02 1.87836E+06 + 3.43300E+02 1.87600E+06 + 3.43400E+02 1.87422E+06 + 3.43500E+02 1.87304E+06 + 3.43600E+02 1.87245E+06 + 3.43700E+02 1.87245E+06 + 3.43800E+02 1.87304E+06 + 3.43900E+02 1.87422E+06 + 3.44000E+02 1.87600E+06 + 3.44100E+02 1.87836E+06 + 3.44200E+02 1.88131E+06 + 3.44300E+02 1.88484E+06 + 3.44400E+02 1.88896E+06 + 3.44500E+02 1.89366E+06 + 3.44600E+02 1.89894E+06 + 3.44700E+02 1.90479E+06 + 3.44800E+02 1.91121E+06 + 3.44900E+02 1.91820E+06 + 3.45000E+02 1.92575E+06 + 3.45100E+02 1.93386E+06 + 3.45200E+02 1.94252E+06 + 3.45300E+02 1.95173E+06 + 3.45400E+02 1.96148E+06 + 3.45500E+02 1.97176E+06 + 3.45600E+02 1.98258E+06 + 3.45700E+02 1.99391E+06 + 3.45800E+02 2.00576E+06 + 3.45900E+02 2.01812E+06 + 3.46000E+02 2.03097E+06 + 3.46100E+02 2.04432E+06 + 3.46200E+02 2.05815E+06 + 3.46300E+02 2.07245E+06 + 3.46400E+02 2.08722E+06 + 3.46500E+02 2.10244E+06 + 3.46600E+02 2.11812E+06 + 3.46700E+02 2.13422E+06 + 3.46800E+02 2.15076E+06 + 3.46900E+02 2.16770E+06 + 3.47000E+02 2.18505E+06 + 3.47100E+02 2.20280E+06 + 3.47200E+02 2.22093E+06 + 3.47300E+02 2.23943E+06 + 3.47400E+02 2.25829E+06 + 3.47500E+02 2.27750E+06 + 3.47600E+02 2.29704E+06 + 3.47700E+02 2.31691E+06 + 3.47800E+02 2.33708E+06 + 3.47900E+02 2.35756E+06 + 3.48000E+02 2.37831E+06 + 3.48100E+02 2.39935E+06 + 3.48200E+02 2.42064E+06 + 3.48300E+02 2.44217E+06 + 3.48400E+02 2.46393E+06 + 3.48500E+02 2.48592E+06 + 3.48600E+02 2.50811E+06 + 3.48700E+02 2.53048E+06 + 3.48800E+02 2.55304E+06 + 3.48900E+02 2.57575E+06 + 3.49000E+02 2.59861E+06 + 3.49100E+02 2.62161E+06 + 3.49200E+02 2.64472E+06 + 3.49300E+02 2.66793E+06 + 3.49400E+02 2.69123E+06 + 3.49500E+02 2.71461E+06 + 3.49600E+02 2.73805E+06 + 3.49700E+02 2.76153E+06 + 3.49800E+02 2.78504E+06 + 3.49900E+02 2.80857E+06 + 3.50000E+02 2.83209E+06 + 3.50100E+02 2.85561E+06 + 3.50200E+02 2.87909E+06 + 3.50300E+02 2.90252E+06 + 3.50400E+02 2.92590E+06 + 3.50500E+02 2.94921E+06 + 3.50600E+02 2.97243E+06 + 3.50700E+02 2.99554E+06 + 3.50800E+02 3.01852E+06 + 3.50900E+02 3.04139E+06 + 3.51000E+02 3.06410E+06 + 3.51100E+02 3.08666E+06 + 3.51200E+02 3.10904E+06 + 3.51300E+02 3.13121E+06 + 3.51400E+02 3.15320E+06 + 3.51500E+02 3.17497E+06 + 3.51600E+02 3.19651E+06 + 3.51700E+02 3.21779E+06 + 3.51800E+02 3.23882E+06 + 3.51900E+02 3.25958E+06 + 3.52000E+02 3.28005E+06 + 3.52100E+02 3.30023E+06 + 3.52200E+02 3.32010E+06 + 3.52300E+02 3.33963E+06 + 3.52400E+02 3.35885E+06 + 3.52500E+02 3.37770E+06 + 3.52600E+02 3.39621E+06 + 3.52700E+02 3.41434E+06 + 3.52800E+02 3.43208E+06 + 3.52900E+02 3.44943E+06 + 3.53000E+02 3.46638E+06 + 3.53100E+02 3.48292E+06 + 3.53200E+02 3.49902E+06 + 3.53300E+02 3.51468E+06 + 3.53400E+02 3.52991E+06 + 3.53500E+02 3.54468E+06 + 3.53600E+02 3.55899E+06 + 3.53700E+02 3.57282E+06 + 3.53800E+02 3.58616E+06 + 3.53900E+02 3.59902E+06 + 3.54000E+02 3.61137E+06 + 3.54100E+02 3.62322E+06 + 3.54200E+02 3.63456E+06 + 3.54300E+02 3.64537E+06 + 3.54400E+02 3.65565E+06 + 3.54500E+02 3.66540E+06 + 3.54600E+02 3.67461E+06 + 3.54700E+02 3.68327E+06 + 3.54800E+02 3.69138E+06 + 3.54900E+02 3.69893E+06 + 3.55000E+02 3.70592E+06 + 3.55100E+02 3.71235E+06 + 3.55200E+02 3.71820E+06 + 3.55300E+02 3.72347E+06 + 3.55400E+02 3.72817E+06 + 3.55500E+02 3.73229E+06 + 3.55600E+02 3.73582E+06 + 3.55700E+02 3.73877E+06 + 3.55800E+02 3.74113E+06 + 3.55900E+02 3.74290E+06 + 3.56000E+02 3.74409E+06 + 3.56100E+02 3.74468E+06 + 3.56200E+02 3.74468E+06 + 3.56300E+02 3.74409E+06 + 3.56400E+02 3.74290E+06 + 3.56500E+02 3.74113E+06 + 3.56600E+02 3.73877E+06 + 3.56700E+02 3.73582E+06 + 3.56800E+02 3.73229E+06 + 3.56900E+02 3.72817E+06 + 3.57000E+02 3.72347E+06 + 3.57100E+02 3.71819E+06 + 3.57200E+02 3.71234E+06 + 3.57300E+02 3.70592E+06 + 3.57400E+02 3.69893E+06 + 3.57500E+02 3.69138E+06 + 3.57600E+02 3.68327E+06 + 3.57700E+02 3.67461E+06 + 3.57800E+02 3.66540E+06 + 3.57900E+02 3.65565E+06 + 3.58000E+02 3.64537E+06 + 3.58100E+02 3.63455E+06 + 3.58200E+02 3.62322E+06 + 3.58300E+02 3.61137E+06 + 3.58400E+02 3.59901E+06 + 3.58500E+02 3.58616E+06 + 3.58600E+02 3.57281E+06 + 3.58700E+02 3.55898E+06 + 3.58800E+02 3.54468E+06 + 3.58900E+02 3.52991E+06 + 3.59000E+02 3.51468E+06 + 3.59100E+02 3.49901E+06 + 3.59200E+02 3.48290E+06 + 3.59300E+02 3.46638E+06 + 3.59400E+02 3.44942E+06 + 3.59500E+02 3.43207E+06 + 3.59600E+02 3.41432E+06 + 3.59700E+02 3.39619E+06 + 3.59800E+02 3.37770E+06 + 3.59900E+02 3.35884E+06 + 3.60000E+02 3.33963E+06 + 3.60100E+02 3.32008E+06 + 3.60200E+02 3.30022E+06 + 3.60300E+02 3.28005E+06 + 3.60400E+02 3.25957E+06 + 3.60500E+02 3.23881E+06 + 3.60600E+02 3.21778E+06 + 3.60700E+02 3.19649E+06 + 3.60800E+02 3.17496E+06 + 3.60900E+02 3.15319E+06 + 3.61000E+02 3.13121E+06 + 3.61100E+02 3.10902E+06 + 3.61200E+02 3.08664E+06 + 3.61300E+02 3.06410E+06 + 3.61400E+02 3.04138E+06 + 3.61500E+02 3.01852E+06 + 3.61600E+02 2.99552E+06 + 3.61700E+02 2.97241E+06 + 3.61800E+02 2.94920E+06 + 3.61900E+02 2.92589E+06 + 3.62000E+02 2.90252E+06 + 3.62100E+02 2.87907E+06 + 3.62200E+02 2.85559E+06 + 3.62300E+02 2.83209E+06 + 3.62400E+02 2.80856E+06 + 3.62500E+02 2.78503E+06 + 3.62600E+02 2.76152E+06 + 3.62700E+02 2.73804E+06 + 3.62800E+02 2.71461E+06 + 3.62900E+02 2.69122E+06 + 3.63000E+02 2.66792E+06 + 3.63100E+02 2.64470E+06 + 3.63200E+02 2.62159E+06 + 3.63300E+02 2.59860E+06 + 3.63400E+02 2.57574E+06 + 3.63500E+02 2.55302E+06 + 3.63600E+02 2.53047E+06 + 3.63700E+02 2.50809E+06 + 3.63800E+02 2.48591E+06 + 3.63900E+02 2.46392E+06 + 3.64000E+02 2.44216E+06 + 3.64100E+02 2.42062E+06 + 3.64200E+02 2.39933E+06 + 3.64300E+02 2.37831E+06 + 3.64400E+02 2.35755E+06 + 3.64500E+02 2.33707E+06 + 3.64600E+02 2.31689E+06 + 3.64700E+02 2.29703E+06 + 3.64800E+02 2.27749E+06 + 3.64900E+02 2.25828E+06 + 3.65000E+02 2.23942E+06 + 3.65100E+02 2.22092E+06 + 3.65200E+02 2.20279E+06 + 3.65300E+02 2.18505E+06 + 3.65400E+02 2.16769E+06 + 3.65500E+02 2.15075E+06 + 3.65600E+02 2.13421E+06 + 3.65700E+02 2.11811E+06 + 3.65800E+02 2.10244E+06 + 3.65900E+02 2.08721E+06 + 3.66000E+02 2.07245E+06 + 3.66100E+02 2.05814E+06 + 3.66200E+02 2.04431E+06 + 3.66300E+02 2.03097E+06 + 3.66400E+02 2.01811E+06 + 3.66500E+02 2.00576E+06 + 3.66600E+02 1.99390E+06 + 3.66700E+02 1.98257E+06 + 3.66800E+02 1.97176E+06 + 3.66900E+02 1.96147E+06 + 3.67000E+02 1.95172E+06 + 3.67100E+02 1.94252E+06 + 3.67200E+02 1.93385E+06 + 3.67300E+02 1.92575E+06 + 3.67400E+02 1.91819E+06 + 3.67500E+02 1.91121E+06 + 3.67600E+02 1.90478E+06 + 3.67700E+02 1.89893E+06 + 3.67800E+02 1.89366E+06 + 3.67900E+02 1.88896E+06 + 3.68000E+02 1.88484E+06 + 3.68100E+02 1.88131E+06 + 3.68200E+02 1.87836E+06 + 3.68300E+02 1.87600E+06 + 3.68400E+02 1.87422E+06 + 3.68500E+02 1.87304E+06 + 3.68600E+02 1.87245E+06 + 3.68700E+02 1.87245E+06 + 3.68800E+02 1.87304E+06 + 3.68900E+02 1.87422E+06 + 3.69000E+02 1.87600E+06 + 3.69100E+02 1.87836E+06 + 3.69200E+02 1.88131E+06 + 3.69300E+02 1.88484E+06 + 3.69400E+02 1.88896E+06 + 3.69500E+02 1.89366E+06 + 3.69600E+02 1.89893E+06 + 3.69700E+02 1.90479E+06 + 3.69800E+02 1.91121E+06 + 3.69900E+02 1.91820E+06 + 3.70000E+02 1.92575E+06 + 3.70100E+02 1.93386E+06 + 3.70200E+02 1.94252E+06 + 3.70300E+02 1.95173E+06 + 3.70400E+02 1.96148E+06 + 3.70500E+02 1.97176E+06 + 3.70600E+02 1.98258E+06 + 3.70700E+02 1.99391E+06 + 3.70800E+02 2.00576E+06 + 3.70900E+02 2.01812E+06 + 3.71000E+02 2.03097E+06 + 3.71100E+02 2.04432E+06 + 3.71200E+02 2.05815E+06 + 3.71300E+02 2.07245E+06 + 3.71400E+02 2.08722E+06 + 3.71500E+02 2.10245E+06 + 3.71600E+02 2.11812E+06 + 3.71700E+02 2.13423E+06 + 3.71800E+02 2.15075E+06 + 3.71900E+02 2.16770E+06 + 3.72000E+02 2.18506E+06 + 3.72100E+02 2.20280E+06 + 3.72200E+02 2.22093E+06 + 3.72300E+02 2.23943E+06 + 3.72400E+02 2.25829E+06 + 3.72500E+02 2.27750E+06 + 3.72600E+02 2.29704E+06 + 3.72700E+02 2.31691E+06 + 3.72800E+02 2.33708E+06 + 3.72900E+02 2.35756E+06 + 3.73000E+02 2.37832E+06 + 3.73100E+02 2.39935E+06 + 3.73200E+02 2.42064E+06 + 3.73300E+02 2.44217E+06 + 3.73400E+02 2.46394E+06 + 3.73500E+02 2.48592E+06 + 3.73600E+02 2.50810E+06 + 3.73700E+02 2.53049E+06 + 3.73800E+02 2.55303E+06 + 3.73900E+02 2.57575E+06 + 3.74000E+02 2.59861E+06 + 3.74100E+02 2.62160E+06 + 3.74200E+02 2.64472E+06 + 3.74300E+02 2.66793E+06 + 3.74400E+02 2.69124E+06 + 3.74500E+02 2.71461E+06 + 3.74600E+02 2.73805E+06 + 3.74700E+02 2.76154E+06 + 3.74800E+02 2.78504E+06 + 3.74900E+02 2.80857E+06 + 3.75000E+02 2.83210E+06 + 3.75100E+02 2.85561E+06 + 3.75200E+02 2.87909E+06 + 3.75300E+02 2.90252E+06 + 3.75400E+02 2.92591E+06 + 3.75500E+02 2.94921E+06 + 3.75600E+02 2.97242E+06 + 3.75700E+02 2.99554E+06 + 3.75800E+02 3.01853E+06 + 3.75900E+02 3.04139E+06 + 3.76000E+02 3.06410E+06 + 3.76100E+02 3.08666E+06 + 3.76200E+02 3.10904E+06 + 3.76300E+02 3.13122E+06 + 3.76400E+02 3.15320E+06 + 3.76500E+02 3.17497E+06 + 3.76600E+02 3.19650E+06 + 3.76700E+02 3.21780E+06 + 3.76800E+02 3.23882E+06 + 3.76900E+02 3.25958E+06 + 3.77000E+02 3.28006E+06 + 3.77100E+02 3.30023E+06 + 3.77200E+02 3.32010E+06 + 3.77300E+02 3.33964E+06 + 3.77400E+02 3.35885E+06 + 3.77500E+02 3.37771E+06 + 3.77600E+02 3.39620E+06 + 3.77700E+02 3.41434E+06 + 3.77800E+02 3.43208E+06 + 3.77900E+02 3.44943E+06 + 3.78000E+02 3.46638E+06 + 3.78100E+02 3.48291E+06 + 3.78200E+02 3.49902E+06 + 3.78300E+02 3.51469E+06 + 3.78400E+02 3.52991E+06 + 3.78500E+02 3.54468E+06 + 3.78600E+02 3.55898E+06 + 3.78700E+02 3.57282E+06 + 3.78800E+02 3.58616E+06 + 3.78900E+02 3.59902E+06 + 3.79000E+02 3.61137E+06 + 3.79100E+02 3.62322E+06 + 3.79200E+02 3.63456E+06 + 3.79300E+02 3.64537E+06 + 3.79400E+02 3.65566E+06 + 3.79500E+02 3.66540E+06 + 3.79600E+02 3.67461E+06 + 3.79700E+02 3.68328E+06 + 3.79800E+02 3.69138E+06 + 3.79900E+02 3.69893E+06 + 3.80000E+02 3.70592E+06 + 3.80100E+02 3.71234E+06 + 3.80200E+02 3.71820E+06 + 3.80300E+02 3.72347E+06 + 3.80400E+02 3.72817E+06 + 3.80500E+02 3.73229E+06 + 3.80600E+02 3.73582E+06 + 3.80700E+02 3.73877E+06 + 3.80800E+02 3.74113E+06 + 3.80900E+02 3.74291E+06 + 3.81000E+02 3.74409E+06 + 3.81100E+02 3.74468E+06 + 3.81200E+02 3.74468E+06 + 3.81300E+02 3.74409E+06 + 3.81400E+02 3.74290E+06 + 3.81500E+02 3.74113E+06 + 3.81600E+02 3.73877E+06 + 3.81700E+02 3.73582E+06 + 3.81800E+02 3.73229E+06 + 3.81900E+02 3.72817E+06 + 3.82000E+02 3.72347E+06 + 3.82100E+02 3.71819E+06 + 3.82200E+02 3.71234E+06 + 3.82300E+02 3.70592E+06 + 3.82400E+02 3.69893E+06 + 3.82500E+02 3.69138E+06 + 3.82600E+02 3.68327E+06 + 3.82700E+02 3.67461E+06 + 3.82800E+02 3.66540E+06 + 3.82900E+02 3.65565E+06 + 3.83000E+02 3.64536E+06 + 3.83100E+02 3.63455E+06 + 3.83200E+02 3.62321E+06 + 3.83300E+02 3.61137E+06 + 3.83400E+02 3.59901E+06 + 3.83500E+02 3.58615E+06 + 3.83600E+02 3.57281E+06 + 3.83700E+02 3.55897E+06 + 3.83800E+02 3.54468E+06 + 3.83900E+02 3.52990E+06 + 3.84000E+02 3.51468E+06 + 3.84100E+02 3.49901E+06 + 3.84200E+02 3.48290E+06 + 3.84300E+02 3.46637E+06 + 3.84400E+02 3.44943E+06 + 3.84500E+02 3.43207E+06 + 3.84600E+02 3.41433E+06 + 3.84700E+02 3.39619E+06 + 3.84800E+02 3.37770E+06 + 3.84900E+02 3.35884E+06 + 3.85000E+02 3.33963E+06 + 3.85100E+02 3.32009E+06 + 3.85200E+02 3.30022E+06 + 3.85300E+02 3.28005E+06 + 3.85400E+02 3.25958E+06 + 3.85500E+02 3.23881E+06 + 3.85600E+02 3.21778E+06 + 3.85700E+02 3.19649E+06 + 3.85800E+02 3.17496E+06 + 3.85900E+02 3.15320E+06 + 3.86000E+02 3.13121E+06 + 3.86100E+02 3.10902E+06 + 3.86200E+02 3.08664E+06 + 3.86300E+02 3.06410E+06 + 3.86400E+02 3.04138E+06 + 3.86500E+02 3.01852E+06 + 3.86600E+02 2.99552E+06 + 3.86700E+02 2.97241E+06 + 3.86800E+02 2.94920E+06 + 3.86900E+02 2.92590E+06 + 3.87000E+02 2.90251E+06 + 3.87100E+02 2.87908E+06 + 3.87200E+02 2.85559E+06 + 3.87300E+02 2.83209E+06 + 3.87400E+02 2.80856E+06 + 3.87500E+02 2.78503E+06 + 3.87600E+02 2.76152E+06 + 3.87700E+02 2.73803E+06 + 3.87800E+02 2.71460E+06 + 3.87900E+02 2.69123E+06 + 3.88000E+02 2.66792E+06 + 3.88100E+02 2.64470E+06 + 3.88200E+02 2.62159E+06 + 3.88300E+02 2.59860E+06 + 3.88400E+02 2.57574E+06 + 3.88500E+02 2.55302E+06 + 3.88600E+02 2.53047E+06 + 3.88700E+02 2.50809E+06 + 3.88800E+02 2.48591E+06 + 3.88900E+02 2.46393E+06 + 3.89000E+02 2.44216E+06 + 3.89100E+02 2.42063E+06 + 3.89200E+02 2.39933E+06 + 3.89300E+02 2.37831E+06 + 3.89400E+02 2.35755E+06 + 3.89500E+02 2.33707E+06 + 3.89600E+02 2.31690E+06 + 3.89700E+02 2.29703E+06 + 3.89800E+02 2.27749E+06 + 3.89900E+02 2.25829E+06 + 3.90000E+02 2.23942E+06 + 3.90100E+02 2.22092E+06 + 3.90200E+02 2.20279E+06 + 3.90300E+02 2.18505E+06 + 3.90400E+02 2.16770E+06 + 3.90500E+02 2.15075E+06 + 3.90600E+02 2.13422E+06 + 3.90700E+02 2.11810E+06 + 3.90800E+02 2.10244E+06 + 3.90900E+02 2.08722E+06 + 3.91000E+02 2.07245E+06 + 3.91100E+02 2.05814E+06 + 3.91200E+02 2.04431E+06 + 3.91300E+02 2.03097E+06 + 3.91400E+02 2.01811E+06 + 3.91500E+02 2.00575E+06 + 3.91600E+02 1.99391E+06 + 3.91700E+02 1.98257E+06 + 3.91800E+02 1.97176E+06 + 3.91900E+02 1.96147E+06 + 3.92000E+02 1.95172E+06 + 3.92100E+02 1.94252E+06 + 3.92200E+02 1.93385E+06 + 3.92300E+02 1.92575E+06 + 3.92400E+02 1.91820E+06 + 3.92500E+02 1.91121E+06 + 3.92600E+02 1.90478E+06 + 3.92700E+02 1.89893E+06 + 3.92800E+02 1.89366E+06 + 3.92900E+02 1.88896E+06 + 3.93000E+02 1.88484E+06 + 3.93100E+02 1.88131E+06 + 3.93200E+02 1.87836E+06 + 3.93300E+02 1.87600E+06 + 3.93400E+02 1.87422E+06 + 3.93500E+02 1.87304E+06 + 3.93600E+02 1.87245E+06 + 3.93700E+02 1.87245E+06 + 3.93800E+02 1.87304E+06 + 3.93900E+02 1.87422E+06 + 3.94000E+02 1.87600E+06 + 3.94100E+02 1.87836E+06 + 3.94200E+02 1.88131E+06 + 3.94300E+02 1.88484E+06 + 3.94400E+02 1.88896E+06 + 3.94500E+02 1.89366E+06 + 3.94600E+02 1.89894E+06 + 3.94700E+02 1.90479E+06 + 3.94800E+02 1.91121E+06 + 3.94900E+02 1.91820E+06 + 3.95000E+02 1.92575E+06 + 3.95100E+02 1.93386E+06 + 3.95200E+02 1.94252E+06 + 3.95300E+02 1.95173E+06 + 3.95400E+02 1.96148E+06 + 3.95500E+02 1.97176E+06 + 3.95600E+02 1.98258E+06 + 3.95700E+02 1.99391E+06 + 3.95800E+02 2.00576E+06 + 3.95900E+02 2.01812E+06 + 3.96000E+02 2.03097E+06 + 3.96100E+02 2.04432E+06 + 3.96200E+02 2.05815E+06 + 3.96300E+02 2.07245E+06 + 3.96400E+02 2.08722E+06 + 3.96500E+02 2.10245E+06 + 3.96600E+02 2.11812E+06 + 3.96700E+02 2.13423E+06 + 3.96800E+02 2.15075E+06 + 3.96900E+02 2.16770E+06 + 3.97000E+02 2.18506E+06 + 3.97100E+02 2.20280E+06 + 3.97200E+02 2.22094E+06 + 3.97300E+02 2.23943E+06 + 3.97400E+02 2.25829E+06 + 3.97500E+02 2.27750E+06 + 3.97600E+02 2.29704E+06 + 3.97700E+02 2.31691E+06 + 3.97800E+02 2.33708E+06 + 3.97900E+02 2.35755E+06 + 3.98000E+02 2.37832E+06 + 3.98100E+02 2.39935E+06 + 3.98200E+02 2.42064E+06 + 3.98300E+02 2.44217E+06 + 3.98400E+02 2.46393E+06 + 3.98500E+02 2.48592E+06 + 3.98600E+02 2.50811E+06 + 3.98700E+02 2.53049E+06 + 3.98800E+02 2.55303E+06 + 3.98900E+02 2.57575E+06 + 3.99000E+02 2.59861E+06 + 3.99100E+02 2.62160E+06 + 3.99200E+02 2.64472E+06 + 3.99300E+02 2.66793E+06 + 3.99400E+02 2.69123E+06 + 3.99500E+02 2.71461E+06 + 3.99600E+02 2.73805E+06 + 3.99700E+02 2.76154E+06 + 3.99800E+02 2.78504E+06 + 3.99900E+02 2.80857E+06 + 4.00000E+02 2.83210E+06 + 4.00100E+02 2.85561E+06 + 4.00200E+02 2.87910E+06 + 4.00300E+02 2.90253E+06 + 4.00400E+02 2.92590E+06 + 4.00500E+02 2.94921E+06 + 4.00600E+02 2.97243E+06 + 4.00700E+02 2.99554E+06 + 4.00800E+02 3.01853E+06 + 4.00900E+02 3.04139E+06 + 4.01000E+02 3.06411E+06 + 4.01100E+02 3.08666E+06 + 4.01200E+02 3.10904E+06 + 4.01300E+02 3.13122E+06 + 4.01400E+02 3.15320E+06 + 4.01500E+02 3.17497E+06 + 4.01600E+02 3.19650E+06 + 4.01700E+02 3.21779E+06 + 4.01800E+02 3.23882E+06 + 4.01900E+02 3.25958E+06 + 4.02000E+02 3.28006E+06 + 4.02100E+02 3.30023E+06 + 4.02200E+02 3.32010E+06 + 4.02300E+02 3.33964E+06 + 4.02400E+02 3.35884E+06 + 4.02500E+02 3.37771E+06 + 4.02600E+02 3.39621E+06 + 4.02700E+02 3.41433E+06 + 4.02800E+02 3.43208E+06 + 4.02900E+02 3.44943E+06 + 4.03000E+02 3.46638E+06 + 4.03100E+02 3.48291E+06 + 4.03200E+02 3.49902E+06 + 4.03300E+02 3.51469E+06 + 4.03400E+02 3.52991E+06 + 4.03500E+02 3.54468E+06 + 4.03600E+02 3.55899E+06 + 4.03700E+02 3.57281E+06 + 4.03800E+02 3.58616E+06 + 4.03900E+02 3.59902E+06 + 4.04000E+02 3.61137E+06 + 4.04100E+02 3.62322E+06 + 4.04200E+02 3.63456E+06 + 4.04300E+02 3.64537E+06 + 4.04400E+02 3.65565E+06 + 4.04500E+02 3.66541E+06 + 4.04600E+02 3.67461E+06 + 4.04700E+02 3.68327E+06 + 4.04800E+02 3.69138E+06 + 4.04900E+02 3.69893E+06 + 4.05000E+02 3.70592E+06 + 4.05100E+02 3.71234E+06 + 4.05200E+02 3.71820E+06 + 4.05300E+02 3.72347E+06 + 4.05400E+02 3.72817E+06 + 4.05500E+02 3.73229E+06 + 4.05600E+02 3.73582E+06 + 4.05700E+02 3.73877E+06 + 4.05800E+02 3.74113E+06 + 4.05900E+02 3.74290E+06 + 4.06000E+02 3.74409E+06 + 4.06100E+02 3.74468E+06 + 4.06200E+02 3.74468E+06 + 4.06300E+02 3.74409E+06 + 4.06400E+02 3.74290E+06 + 4.06500E+02 3.74113E+06 + 4.06600E+02 3.73877E+06 + 4.06700E+02 3.73582E+06 + 4.06800E+02 3.73229E+06 + 4.06900E+02 3.72817E+06 + 4.07000E+02 3.72347E+06 + 4.07100E+02 3.71819E+06 + 4.07200E+02 3.71234E+06 + 4.07300E+02 3.70592E+06 + 4.07400E+02 3.69893E+06 + 4.07500E+02 3.69138E+06 + 4.07600E+02 3.68327E+06 + 4.07700E+02 3.67461E+06 + 4.07800E+02 3.66540E+06 + 4.07900E+02 3.65565E+06 + 4.08000E+02 3.64536E+06 + 4.08100E+02 3.63455E+06 + 4.08200E+02 3.62322E+06 + 4.08300E+02 3.61137E+06 + 4.08400E+02 3.59901E+06 + 4.08500E+02 3.58615E+06 + 4.08600E+02 3.57281E+06 + 4.08700E+02 3.55898E+06 + 4.08800E+02 3.54467E+06 + 4.08900E+02 3.52991E+06 + 4.09000E+02 3.51468E+06 + 4.09100E+02 3.49901E+06 + 4.09200E+02 3.48290E+06 + 4.09300E+02 3.46637E+06 + 4.09400E+02 3.44943E+06 + 4.09500E+02 3.43207E+06 + 4.09600E+02 3.41432E+06 + 4.09700E+02 3.39620E+06 + 4.09800E+02 3.37770E+06 + 4.09900E+02 3.35884E+06 + 4.10000E+02 3.33963E+06 + 4.10100E+02 3.32009E+06 + 4.10200E+02 3.30022E+06 + 4.10300E+02 3.28005E+06 + 4.10400E+02 3.25957E+06 + 4.10500E+02 3.23881E+06 + 4.10600E+02 3.21778E+06 + 4.10700E+02 3.19649E+06 + 4.10800E+02 3.17496E+06 + 4.10900E+02 3.15319E+06 + 4.11000E+02 3.13121E+06 + 4.11100E+02 3.10902E+06 + 4.11200E+02 3.08664E+06 + 4.11300E+02 3.06409E+06 + 4.11400E+02 3.04138E+06 + 4.11500E+02 3.01851E+06 + 4.11600E+02 2.99552E+06 + 4.11700E+02 2.97241E+06 + 4.11800E+02 2.94920E+06 + 4.11900E+02 2.92590E+06 + 4.12000E+02 2.90251E+06 + 4.12100E+02 2.87908E+06 + 4.12200E+02 2.85560E+06 + 4.12300E+02 2.83209E+06 + 4.12400E+02 2.80856E+06 + 4.12500E+02 2.78503E+06 + 4.12600E+02 2.76152E+06 + 4.12700E+02 2.73804E+06 + 4.12800E+02 2.71460E+06 + 4.12900E+02 2.69122E+06 + 4.13000E+02 2.66792E+06 + 4.13100E+02 2.64470E+06 + 4.13200E+02 2.62159E+06 + 4.13300E+02 2.59860E+06 + 4.13400E+02 2.57574E+06 + 4.13500E+02 2.55302E+06 + 4.13600E+02 2.53047E+06 + 4.13700E+02 2.50809E+06 + 4.13800E+02 2.48591E+06 + 4.13900E+02 2.46393E+06 + 4.14000E+02 2.44216E+06 + 4.14100E+02 2.42062E+06 + 4.14200E+02 2.39934E+06 + 4.14300E+02 2.37831E+06 + 4.14400E+02 2.35755E+06 + 4.14500E+02 2.33707E+06 + 4.14600E+02 2.31689E+06 + 4.14700E+02 2.29703E+06 + 4.14800E+02 2.27749E+06 + 4.14900E+02 2.25828E+06 + 4.15000E+02 2.23942E+06 + 4.15100E+02 2.22092E+06 + 4.15200E+02 2.20279E+06 + 4.15300E+02 2.18505E+06 + 4.15400E+02 2.16770E+06 + 4.15500E+02 2.15074E+06 + 4.15600E+02 2.13421E+06 + 4.15700E+02 2.11811E+06 + 4.15800E+02 2.10244E+06 + 4.15900E+02 2.08722E+06 + 4.16000E+02 2.07244E+06 + 4.16100E+02 2.05814E+06 + 4.16200E+02 2.04431E+06 + 4.16300E+02 2.03097E+06 + 4.16400E+02 2.01811E+06 + 4.16500E+02 2.00575E+06 + 4.16600E+02 1.99390E+06 + 4.16700E+02 1.98257E+06 + 4.16800E+02 1.97176E+06 + 4.16900E+02 1.96147E+06 + 4.17000E+02 1.95172E+06 + 4.17100E+02 1.94251E+06 + 4.17200E+02 1.93385E+06 + 4.17300E+02 1.92575E+06 + 4.17400E+02 1.91820E+06 + 4.17500E+02 1.91120E+06 + 4.17600E+02 1.90478E+06 + 4.17700E+02 1.89893E+06 + 4.17800E+02 1.89366E+06 + 4.17900E+02 1.88896E+06 + 4.18000E+02 1.88484E+06 + 4.18100E+02 1.88130E+06 + 4.18200E+02 1.87836E+06 + 4.18300E+02 1.87600E+06 + 4.18400E+02 1.87422E+06 + 4.18500E+02 1.87304E+06 + 4.18600E+02 1.87245E+06 + 4.18700E+02 1.87245E+06 + 4.18800E+02 1.87304E+06 + 4.18900E+02 1.87422E+06 + 4.19000E+02 1.87600E+06 + 4.19100E+02 1.87836E+06 + 4.19200E+02 1.88131E+06 + 4.19300E+02 1.88484E+06 + 4.19400E+02 1.88896E+06 + 4.19500E+02 1.89366E+06 + 4.19600E+02 1.89894E+06 + 4.19700E+02 1.90479E+06 + 4.19800E+02 1.91121E+06 + 4.19900E+02 1.91820E+06 + 4.20000E+02 1.92575E+06 + 4.20100E+02 1.93386E+06 + 4.20200E+02 1.94252E+06 + 4.20300E+02 1.95173E+06 + 4.20400E+02 1.96148E+06 + 4.20500E+02 1.97176E+06 + 4.20600E+02 1.98258E+06 + 4.20700E+02 1.99391E+06 + 4.20800E+02 2.00576E+06 + 4.20900E+02 2.01812E+06 + 4.21000E+02 2.03097E+06 + 4.21100E+02 2.04432E+06 + 4.21200E+02 2.05815E+06 + 4.21300E+02 2.07245E+06 + 4.21400E+02 2.08722E+06 + 4.21500E+02 2.10244E+06 + 4.21600E+02 2.11812E+06 + 4.21700E+02 2.13422E+06 + 4.21800E+02 2.15076E+06 + 4.21900E+02 2.16770E+06 + 4.22000E+02 2.18505E+06 + 4.22100E+02 2.20280E+06 + 4.22200E+02 2.22093E+06 + 4.22300E+02 2.23943E+06 + 4.22400E+02 2.25829E+06 + 4.22500E+02 2.27750E+06 + 4.22600E+02 2.29704E+06 + 4.22700E+02 2.31691E+06 + 4.22800E+02 2.33708E+06 + 4.22900E+02 2.35756E+06 + 4.23000E+02 2.37831E+06 + 4.23100E+02 2.39935E+06 + 4.23200E+02 2.42064E+06 + 4.23300E+02 2.44217E+06 + 4.23400E+02 2.46393E+06 + 4.23500E+02 2.48592E+06 + 4.23600E+02 2.50811E+06 + 4.23700E+02 2.53048E+06 + 4.23800E+02 2.55304E+06 + 4.23900E+02 2.57575E+06 + 4.24000E+02 2.59861E+06 + 4.24100E+02 2.62161E+06 + 4.24200E+02 2.64472E+06 + 4.24300E+02 2.66793E+06 + 4.24400E+02 2.69123E+06 + 4.24500E+02 2.71461E+06 + 4.24600E+02 2.73805E+06 + 4.24700E+02 2.76153E+06 + 4.24800E+02 2.78504E+06 + 4.24900E+02 2.80857E+06 + 4.25000E+02 2.83209E+06 + 4.25100E+02 2.85561E+06 + 4.25200E+02 2.87909E+06 + 4.25300E+02 2.90253E+06 + 4.25400E+02 2.92590E+06 + 4.25500E+02 2.94921E+06 + 4.25600E+02 2.97243E+06 + 4.25700E+02 2.99554E+06 + 4.25800E+02 3.01853E+06 + 4.25900E+02 3.04139E+06 + 4.26000E+02 3.06410E+06 + 4.26100E+02 3.08666E+06 + 4.26200E+02 3.10904E+06 + 4.26300E+02 3.13122E+06 + 4.26400E+02 3.15320E+06 + 4.26500E+02 3.17497E+06 + 4.26600E+02 3.19651E+06 + 4.26700E+02 3.21779E+06 + 4.26800E+02 3.23882E+06 + 4.26900E+02 3.25958E+06 + 4.27000E+02 3.28005E+06 + 4.27100E+02 3.30023E+06 + 4.27200E+02 3.32010E+06 + 4.27300E+02 3.33964E+06 + 4.27400E+02 3.35885E+06 + 4.27500E+02 3.37770E+06 + 4.27600E+02 3.39621E+06 + 4.27700E+02 3.41434E+06 + 4.27800E+02 3.43208E+06 + 4.27900E+02 3.44943E+06 + 4.28000E+02 3.46638E+06 + 4.28100E+02 3.48292E+06 + 4.28200E+02 3.49902E+06 + 4.28300E+02 3.51469E+06 + 4.28400E+02 3.52991E+06 + 4.28500E+02 3.54468E+06 + 4.28600E+02 3.55899E+06 + 4.28700E+02 3.57282E+06 + 4.28800E+02 3.58616E+06 + 4.28900E+02 3.59902E+06 + 4.29000E+02 3.61137E+06 + 4.29100E+02 3.62322E+06 + 4.29200E+02 3.63456E+06 + 4.29300E+02 3.64537E+06 + 4.29400E+02 3.65565E+06 + 4.29500E+02 3.66540E+06 + 4.29600E+02 3.67461E+06 + 4.29700E+02 3.68327E+06 + 4.29800E+02 3.69138E+06 + 4.29900E+02 3.69893E+06 + 4.30000E+02 3.70592E+06 + 4.30100E+02 3.71235E+06 + 4.30200E+02 3.71820E+06 + 4.30300E+02 3.72347E+06 + 4.30400E+02 3.72817E+06 + 4.30500E+02 3.73229E+06 + 4.30600E+02 3.73582E+06 + 4.30700E+02 3.73877E+06 + 4.30800E+02 3.74113E+06 + 4.30900E+02 3.74290E+06 + 4.31000E+02 3.74409E+06 + 4.31100E+02 3.74468E+06 + 4.31200E+02 3.74468E+06 + 4.31300E+02 3.74409E+06 + 4.31400E+02 3.74290E+06 + 4.31500E+02 3.74113E+06 + 4.31600E+02 3.73877E+06 + 4.31700E+02 3.73582E+06 + 4.31800E+02 3.73229E+06 + 4.31900E+02 3.72817E+06 + 4.32000E+02 3.72347E+06 + 4.32100E+02 3.71819E+06 + 4.32200E+02 3.71234E+06 + 4.32300E+02 3.70592E+06 + 4.32400E+02 3.69893E+06 + 4.32500E+02 3.69138E+06 + 4.32600E+02 3.68327E+06 + 4.32700E+02 3.67461E+06 + 4.32800E+02 3.66540E+06 + 4.32900E+02 3.65565E+06 + 4.33000E+02 3.64537E+06 + 4.33100E+02 3.63455E+06 + 4.33200E+02 3.62322E+06 + 4.33300E+02 3.61137E+06 + 4.33400E+02 3.59901E+06 + 4.33500E+02 3.58616E+06 + 4.33600E+02 3.57281E+06 + 4.33700E+02 3.55898E+06 + 4.33800E+02 3.54467E+06 + 4.33900E+02 3.52991E+06 + 4.34000E+02 3.51468E+06 + 4.34100E+02 3.49901E+06 + 4.34200E+02 3.48290E+06 + 4.34300E+02 3.46637E+06 + 4.34400E+02 3.44942E+06 + 4.34500E+02 3.43207E+06 + 4.34600E+02 3.41432E+06 + 4.34700E+02 3.39619E+06 + 4.34800E+02 3.37770E+06 + 4.34900E+02 3.35884E+06 + 4.35000E+02 3.33963E+06 + 4.35100E+02 3.32008E+06 + 4.35200E+02 3.30022E+06 + 4.35300E+02 3.28005E+06 + 4.35400E+02 3.25957E+06 + 4.35500E+02 3.23881E+06 + 4.35600E+02 3.21778E+06 + 4.35700E+02 3.19649E+06 + 4.35800E+02 3.17496E+06 + 4.35900E+02 3.15319E+06 + 4.36000E+02 3.13121E+06 + 4.36100E+02 3.10902E+06 + 4.36200E+02 3.08664E+06 + 4.36300E+02 3.06410E+06 + 4.36400E+02 3.04138E+06 + 4.36500E+02 3.01852E+06 + 4.36600E+02 2.99552E+06 + 4.36700E+02 2.97241E+06 + 4.36800E+02 2.94920E+06 + 4.36900E+02 2.92589E+06 + 4.37000E+02 2.90252E+06 + 4.37100E+02 2.87907E+06 + 4.37200E+02 2.85559E+06 + 4.37300E+02 2.83209E+06 + 4.37400E+02 2.80856E+06 + 4.37500E+02 2.78503E+06 + 4.37600E+02 2.76152E+06 + 4.37700E+02 2.73804E+06 + 4.37800E+02 2.71461E+06 + 4.37900E+02 2.69122E+06 + 4.38000E+02 2.66792E+06 + 4.38100E+02 2.64470E+06 + 4.38200E+02 2.62159E+06 + 4.38300E+02 2.59860E+06 + 4.38400E+02 2.57574E+06 + 4.38500E+02 2.55302E+06 + 4.38600E+02 2.53047E+06 + 4.38700E+02 2.50809E+06 + 4.38800E+02 2.48591E+06 + 4.38900E+02 2.46392E+06 + 4.39000E+02 2.44216E+06 + 4.39100E+02 2.42062E+06 + 4.39200E+02 2.39933E+06 + 4.39300E+02 2.37831E+06 + 4.39400E+02 2.35755E+06 + 4.39500E+02 2.33707E+06 + 4.39600E+02 2.31689E+06 + 4.39700E+02 2.29703E+06 + 4.39800E+02 2.27749E+06 + 4.39900E+02 2.25828E+06 + 4.40000E+02 2.23942E+06 + 4.40100E+02 2.22092E+06 + 4.40200E+02 2.20279E+06 + 4.40300E+02 2.18505E+06 + 4.40400E+02 2.16769E+06 + 4.40500E+02 2.15075E+06 + 4.40600E+02 2.13421E+06 + 4.40700E+02 2.11811E+06 + 4.40800E+02 2.10244E+06 + 4.40900E+02 2.08721E+06 + 4.41000E+02 2.07245E+06 + 4.41100E+02 2.05814E+06 + 4.41200E+02 2.04431E+06 + 4.41300E+02 2.03097E+06 + 4.41400E+02 2.01811E+06 + 4.41500E+02 2.00576E+06 + 4.41600E+02 1.99390E+06 + 4.41700E+02 1.98257E+06 + 4.41800E+02 1.97176E+06 + 4.41900E+02 1.96147E+06 + 4.42000E+02 1.95172E+06 + 4.42100E+02 1.94251E+06 + 4.42200E+02 1.93385E+06 + 4.42300E+02 1.92575E+06 + 4.42400E+02 1.91819E+06 + 4.42500E+02 1.91121E+06 + 4.42600E+02 1.90478E+06 + 4.42700E+02 1.89893E+06 + 4.42800E+02 1.89366E+06 + 4.42900E+02 1.88896E+06 + 4.43000E+02 1.88484E+06 + 4.43100E+02 1.88130E+06 + 4.43200E+02 1.87836E+06 + 4.43300E+02 1.87600E+06 + 4.43400E+02 1.87422E+06 + 4.43500E+02 1.87304E+06 + 4.43600E+02 1.87245E+06 + 4.43700E+02 1.87245E+06 + 4.43800E+02 1.87304E+06 + 4.43900E+02 1.87422E+06 + 4.44000E+02 1.87600E+06 + 4.44100E+02 1.87836E+06 + 4.44200E+02 1.88131E+06 + 4.44300E+02 1.88484E+06 + 4.44400E+02 1.88896E+06 + 4.44500E+02 1.89366E+06 + 4.44600E+02 1.89894E+06 + 4.44700E+02 1.90479E+06 + 4.44800E+02 1.91121E+06 + 4.44900E+02 1.91820E+06 + 4.45000E+02 1.92575E+06 + 4.45100E+02 1.93386E+06 + 4.45200E+02 1.94252E+06 + 4.45300E+02 1.95173E+06 + 4.45400E+02 1.96148E+06 + 4.45500E+02 1.97176E+06 + 4.45600E+02 1.98258E+06 + 4.45700E+02 1.99391E+06 + 4.45800E+02 2.00576E+06 + 4.45900E+02 2.01812E+06 + 4.46000E+02 2.03097E+06 + 4.46100E+02 2.04432E+06 + 4.46200E+02 2.05815E+06 + 4.46300E+02 2.07245E+06 + 4.46400E+02 2.08722E+06 + 4.46500E+02 2.10245E+06 + 4.46600E+02 2.11812E+06 + 4.46700E+02 2.13423E+06 + 4.46800E+02 2.15075E+06 + 4.46900E+02 2.16770E+06 + 4.47000E+02 2.18506E+06 + 4.47100E+02 2.20281E+06 + 4.47200E+02 2.22093E+06 + 4.47300E+02 2.23943E+06 + 4.47400E+02 2.25829E+06 + 4.47500E+02 2.27750E+06 + 4.47600E+02 2.29705E+06 + 4.47700E+02 2.31691E+06 + 4.47800E+02 2.33708E+06 + 4.47900E+02 2.35756E+06 + 4.48000E+02 2.37832E+06 + 4.48100E+02 2.39935E+06 + 4.48200E+02 2.42064E+06 + 4.48300E+02 2.44217E+06 + 4.48400E+02 2.46394E+06 + 4.48500E+02 2.48592E+06 + 4.48600E+02 2.50811E+06 + 4.48700E+02 2.53049E+06 + 4.48800E+02 2.55303E+06 + 4.48900E+02 2.57575E+06 + 4.49000E+02 2.59861E+06 + 4.49100E+02 2.62161E+06 + 4.49200E+02 2.64472E+06 + 4.49300E+02 2.66793E+06 + 4.49400E+02 2.69124E+06 + 4.49500E+02 2.71461E+06 + 4.49600E+02 2.73806E+06 + 4.49700E+02 2.76154E+06 + 4.49800E+02 2.78504E+06 + 4.49900E+02 2.80857E+06 + 4.50000E+02 2.83210E+06 + 4.50100E+02 2.85561E+06 + 4.50200E+02 2.87909E+06 + 4.50300E+02 2.90252E+06 + 4.50400E+02 2.92591E+06 + 4.50500E+02 2.94921E+06 + 4.50600E+02 2.97243E+06 + 4.50700E+02 2.99554E+06 + 4.50800E+02 3.01853E+06 + 4.50900E+02 3.04139E+06 + 4.51000E+02 3.06410E+06 + 4.51100E+02 3.08666E+06 + 4.51200E+02 3.10904E+06 + 4.51300E+02 3.13122E+06 + 4.51400E+02 3.15320E+06 + 4.51500E+02 3.17497E+06 + 4.51600E+02 3.19651E+06 + 4.51700E+02 3.21780E+06 + 4.51800E+02 3.23882E+06 + 4.51900E+02 3.25958E+06 + 4.52000E+02 3.28006E+06 + 4.52100E+02 3.30024E+06 + 4.52200E+02 3.32010E+06 + 4.52300E+02 3.33964E+06 + 4.52400E+02 3.35885E+06 + 4.52500E+02 3.37771E+06 + 4.52600E+02 3.39620E+06 + 4.52700E+02 3.41434E+06 + 4.52800E+02 3.43208E+06 + 4.52900E+02 3.44943E+06 + 4.53000E+02 3.46638E+06 + 4.53100E+02 3.48291E+06 + 4.53200E+02 3.49902E+06 + 4.53300E+02 3.51469E+06 + 4.53400E+02 3.52991E+06 + 4.53500E+02 3.54468E+06 + 4.53600E+02 3.55898E+06 + 4.53700E+02 3.57282E+06 + 4.53800E+02 3.58616E+06 + 4.53900E+02 3.59902E+06 + 4.54000E+02 3.61137E+06 + 4.54100E+02 3.62322E+06 + 4.54200E+02 3.63456E+06 + 4.54300E+02 3.64537E+06 + 4.54400E+02 3.65566E+06 + 4.54500E+02 3.66540E+06 + 4.54600E+02 3.67461E+06 + 4.54700E+02 3.68328E+06 + 4.54800E+02 3.69138E+06 + 4.54900E+02 3.69893E+06 + 4.55000E+02 3.70592E+06 + 4.55100E+02 3.71234E+06 + 4.55200E+02 3.71820E+06 + 4.55300E+02 3.72347E+06 + 4.55400E+02 3.72817E+06 + 4.55500E+02 3.73229E+06 + 4.55600E+02 3.73582E+06 + 4.55700E+02 3.73877E+06 + 4.55800E+02 3.74113E+06 + 4.55900E+02 3.74291E+06 + 4.56000E+02 3.74409E+06 + 4.56100E+02 3.74468E+06 + 4.56200E+02 3.74468E+06 + 4.56300E+02 3.74409E+06 + 4.56400E+02 3.74290E+06 + 4.56500E+02 3.74113E+06 + 4.56600E+02 3.73877E+06 + 4.56700E+02 3.73582E+06 + 4.56800E+02 3.73229E+06 + 4.56900E+02 3.72817E+06 + 4.57000E+02 3.72347E+06 + 4.57100E+02 3.71819E+06 + 4.57200E+02 3.71234E+06 + 4.57300E+02 3.70592E+06 + 4.57400E+02 3.69893E+06 + 4.57500E+02 3.69138E+06 + 4.57600E+02 3.68327E+06 + 4.57700E+02 3.67461E+06 + 4.57800E+02 3.66540E+06 + 4.57900E+02 3.65565E+06 + 4.58000E+02 3.64536E+06 + 4.58100E+02 3.63455E+06 + 4.58200E+02 3.62321E+06 + 4.58300E+02 3.61137E+06 + 4.58400E+02 3.59901E+06 + 4.58500E+02 3.58615E+06 + 4.58600E+02 3.57281E+06 + 4.58700E+02 3.55897E+06 + 4.58800E+02 3.54468E+06 + 4.58900E+02 3.52990E+06 + 4.59000E+02 3.51468E+06 + 4.59100E+02 3.49901E+06 + 4.59200E+02 3.48290E+06 + 4.59300E+02 3.46637E+06 + 4.59400E+02 3.44942E+06 + 4.59500E+02 3.43207E+06 + 4.59600E+02 3.41433E+06 + 4.59700E+02 3.39619E+06 + 4.59800E+02 3.37770E+06 + 4.59900E+02 3.35883E+06 + 4.60000E+02 3.33963E+06 + 4.60100E+02 3.32009E+06 + 4.60200E+02 3.30022E+06 + 4.60300E+02 3.28005E+06 + 4.60400E+02 3.25957E+06 + 4.60500E+02 3.23881E+06 + 4.60600E+02 3.21778E+06 + 4.60700E+02 3.19649E+06 + 4.60800E+02 3.17496E+06 + 4.60900E+02 3.15319E+06 + 4.61000E+02 3.13121E+06 + 4.61100E+02 3.10902E+06 + 4.61200E+02 3.08664E+06 + 4.61300E+02 3.06410E+06 + 4.61400E+02 3.04138E+06 + 4.61500E+02 3.01852E+06 + 4.61600E+02 2.99552E+06 + 4.61700E+02 2.97241E+06 + 4.61800E+02 2.94920E+06 + 4.61900E+02 2.92589E+06 + 4.62000E+02 2.90251E+06 + 4.62100E+02 2.87908E+06 + 4.62200E+02 2.85559E+06 + 4.62300E+02 2.83209E+06 + 4.62400E+02 2.80856E+06 + 4.62500E+02 2.78503E+06 + 4.62600E+02 2.76152E+06 + 4.62700E+02 2.73803E+06 + 4.62800E+02 2.71460E+06 + 4.62900E+02 2.69122E+06 + 4.63000E+02 2.66792E+06 + 4.63100E+02 2.64470E+06 + 4.63200E+02 2.62159E+06 + 4.63300E+02 2.59860E+06 + 4.63400E+02 2.57574E+06 + 4.63500E+02 2.55302E+06 + 4.63600E+02 2.53047E+06 + 4.63700E+02 2.50809E+06 + 4.63800E+02 2.48591E+06 + 4.63900E+02 2.46392E+06 + 4.64000E+02 2.44216E+06 + 4.64100E+02 2.42063E+06 + 4.64200E+02 2.39933E+06 + 4.64300E+02 2.37831E+06 + 4.64400E+02 2.35754E+06 + 4.64500E+02 2.33707E+06 + 4.64600E+02 2.31690E+06 + 4.64700E+02 2.29703E+06 + 4.64800E+02 2.27749E+06 + 4.64900E+02 2.25828E+06 + 4.65000E+02 2.23942E+06 + 4.65100E+02 2.22092E+06 + 4.65200E+02 2.20279E+06 + 4.65300E+02 2.18505E+06 + 4.65400E+02 2.16769E+06 + 4.65500E+02 2.15075E+06 + 4.65600E+02 2.13422E+06 + 4.65700E+02 2.11810E+06 + 4.65800E+02 2.10244E+06 + 4.65900E+02 2.08721E+06 + 4.66000E+02 2.07245E+06 + 4.66100E+02 2.05814E+06 + 4.66200E+02 2.04431E+06 + 4.66300E+02 2.03097E+06 + 4.66400E+02 2.01811E+06 + 4.66500E+02 2.00575E+06 + 4.66600E+02 1.99391E+06 + 4.66700E+02 1.98257E+06 + 4.66800E+02 1.97176E+06 + 4.66900E+02 1.96147E+06 + 4.67000E+02 1.95172E+06 + 4.67100E+02 1.94252E+06 + 4.67200E+02 1.93385E+06 + 4.67300E+02 1.92575E+06 + 4.67400E+02 1.91819E+06 + 4.67500E+02 1.91121E+06 + 4.67600E+02 1.90478E+06 + 4.67700E+02 1.89893E+06 + 4.67800E+02 1.89366E+06 + 4.67900E+02 1.88896E+06 + 4.68000E+02 1.88484E+06 + 4.68100E+02 1.88131E+06 + 4.68200E+02 1.87836E+06 + 4.68300E+02 1.87600E+06 + 4.68400E+02 1.87422E+06 + 4.68500E+02 1.87304E+06 + 4.68600E+02 1.87245E+06 + 4.68700E+02 1.87245E+06 + 4.68800E+02 1.87304E+06 + 4.68900E+02 1.87422E+06 + 4.69000E+02 1.87600E+06 + 4.69100E+02 1.87836E+06 + 4.69200E+02 1.88131E+06 + 4.69300E+02 1.88484E+06 + 4.69400E+02 1.88896E+06 + 4.69500E+02 1.89366E+06 + 4.69600E+02 1.89894E+06 + 4.69700E+02 1.90479E+06 + 4.69800E+02 1.91121E+06 + 4.69900E+02 1.91820E+06 + 4.70000E+02 1.92575E+06 + 4.70100E+02 1.93386E+06 + 4.70200E+02 1.94252E+06 + 4.70300E+02 1.95173E+06 + 4.70400E+02 1.96148E+06 + 4.70500E+02 1.97176E+06 + 4.70600E+02 1.98258E+06 + 4.70700E+02 1.99391E+06 + 4.70800E+02 2.00576E+06 + 4.70900E+02 2.01812E+06 + 4.71000E+02 2.03097E+06 + 4.71100E+02 2.04432E+06 + 4.71200E+02 2.05815E+06 + 4.71300E+02 2.07245E+06 + 4.71400E+02 2.08722E+06 + 4.71500E+02 2.10245E+06 + 4.71600E+02 2.11812E+06 + 4.71700E+02 2.13423E+06 + 4.71800E+02 2.15075E+06 + 4.71900E+02 2.16770E+06 + 4.72000E+02 2.18506E+06 + 4.72100E+02 2.20280E+06 + 4.72200E+02 2.22094E+06 + 4.72300E+02 2.23943E+06 + 4.72400E+02 2.25829E+06 + 4.72500E+02 2.27750E+06 + 4.72600E+02 2.29704E+06 + 4.72700E+02 2.31691E+06 + 4.72800E+02 2.33708E+06 + 4.72900E+02 2.35755E+06 + 4.73000E+02 2.37832E+06 + 4.73100E+02 2.39935E+06 + 4.73200E+02 2.42064E+06 + 4.73300E+02 2.44217E+06 + 4.73400E+02 2.46393E+06 + 4.73500E+02 2.48592E+06 + 4.73600E+02 2.50811E+06 + 4.73700E+02 2.53049E+06 + 4.73800E+02 2.55303E+06 + 4.73900E+02 2.57575E+06 + 4.74000E+02 2.59861E+06 + 4.74100E+02 2.62160E+06 + 4.74200E+02 2.64472E+06 + 4.74300E+02 2.66793E+06 + 4.74400E+02 2.69123E+06 + 4.74500E+02 2.71462E+06 + 4.74600E+02 2.73805E+06 + 4.74700E+02 2.76154E+06 + 4.74800E+02 2.78504E+06 + 4.74900E+02 2.80857E+06 + 4.75000E+02 2.83210E+06 + 4.75100E+02 2.85561E+06 + 4.75200E+02 2.87910E+06 + 4.75300E+02 2.90253E+06 + 4.75400E+02 2.92590E+06 + 4.75500E+02 2.94921E+06 + 4.75600E+02 2.97243E+06 + 4.75700E+02 2.99554E+06 + 4.75800E+02 3.01853E+06 + 4.75900E+02 3.04139E+06 + 4.76000E+02 3.06411E+06 + 4.76100E+02 3.08666E+06 + 4.76200E+02 3.10904E+06 + 4.76300E+02 3.13122E+06 + 4.76400E+02 3.15320E+06 + 4.76500E+02 3.17497E+06 + 4.76600E+02 3.19650E+06 + 4.76700E+02 3.21780E+06 + 4.76800E+02 3.23882E+06 + 4.76900E+02 3.25958E+06 + 4.77000E+02 3.28006E+06 + 4.77100E+02 3.30023E+06 + 4.77200E+02 3.32010E+06 + 4.77300E+02 3.33964E+06 + 4.77400E+02 3.35884E+06 + 4.77500E+02 3.37771E+06 + 4.77600E+02 3.39621E+06 + 4.77700E+02 3.41434E+06 + 4.77800E+02 3.43208E+06 + 4.77900E+02 3.44943E+06 + 4.78000E+02 3.46638E+06 + 4.78100E+02 3.48291E+06 + 4.78200E+02 3.49902E+06 + 4.78300E+02 3.51469E+06 + 4.78400E+02 3.52991E+06 + 4.78500E+02 3.54468E+06 + 4.78600E+02 3.55899E+06 + 4.78700E+02 3.57282E+06 + 4.78800E+02 3.58616E+06 + 4.78900E+02 3.59902E+06 + 4.79000E+02 3.61137E+06 + 4.79100E+02 3.62322E+06 + 4.79200E+02 3.63456E+06 + 4.79300E+02 3.64537E+06 + 4.79400E+02 3.65565E+06 + 4.79500E+02 3.66541E+06 + 4.79600E+02 3.67461E+06 + 4.79700E+02 3.68328E+06 + 4.79800E+02 3.69138E+06 + 4.79900E+02 3.69893E+06 + 4.80000E+02 3.70592E+06 + 4.80100E+02 3.71234E+06 + 4.80200E+02 3.71820E+06 + 4.80300E+02 3.72347E+06 + 4.80400E+02 3.72817E+06 + 4.80500E+02 3.73229E+06 + 4.80600E+02 3.73582E+06 + 4.80700E+02 3.73877E+06 + 4.80800E+02 3.74113E+06 + 4.80900E+02 3.74290E+06 + 4.81000E+02 3.74409E+06 + 4.81100E+02 3.74468E+06 + 4.81200E+02 3.74468E+06 + 4.81300E+02 3.74409E+06 + 4.81400E+02 3.74290E+06 + 4.81500E+02 3.74113E+06 + 4.81600E+02 3.73877E+06 + 4.81700E+02 3.73582E+06 + 4.81800E+02 3.73229E+06 + 4.81900E+02 3.72817E+06 + 4.82000E+02 3.72347E+06 + 4.82100E+02 3.71819E+06 + 4.82200E+02 3.71234E+06 + 4.82300E+02 3.70592E+06 + 4.82400E+02 3.69893E+06 + 4.82500E+02 3.69138E+06 + 4.82600E+02 3.68327E+06 + 4.82700E+02 3.67460E+06 + 4.82800E+02 3.66540E+06 + 4.82900E+02 3.65565E+06 + 4.83000E+02 3.64536E+06 + 4.83100E+02 3.63455E+06 + 4.83200E+02 3.62321E+06 + 4.83300E+02 3.61137E+06 + 4.83400E+02 3.59901E+06 + 4.83500E+02 3.58615E+06 + 4.83600E+02 3.57281E+06 + 4.83700E+02 3.55897E+06 + 4.83800E+02 3.54467E+06 + 4.83900E+02 3.52991E+06 + 4.84000E+02 3.51468E+06 + 4.84100E+02 3.49901E+06 + 4.84200E+02 3.48290E+06 + 4.84300E+02 3.46637E+06 + 4.84400E+02 3.44943E+06 + 4.84500E+02 3.43207E+06 + 4.84600E+02 3.41432E+06 + 4.84700E+02 3.39619E+06 + 4.84800E+02 3.37770E+06 + 4.84900E+02 3.35884E+06 + 4.85000E+02 3.33963E+06 + 4.85100E+02 3.32009E+06 + 4.85200E+02 3.30021E+06 + 4.85300E+02 3.28005E+06 + 4.85400E+02 3.25957E+06 + 4.85500E+02 3.23881E+06 + 4.85600E+02 3.21778E+06 + 4.85700E+02 3.19648E+06 + 4.85800E+02 3.17496E+06 + 4.85900E+02 3.15319E+06 + 4.86000E+02 3.13121E+06 + 4.86100E+02 3.10902E+06 + 4.86200E+02 3.08664E+06 + 4.86300E+02 3.06409E+06 + 4.86400E+02 3.04138E+06 + 4.86500E+02 3.01851E+06 + 4.86600E+02 2.99552E+06 + 4.86700E+02 2.97241E+06 + 4.86800E+02 2.94920E+06 + 4.86900E+02 2.92590E+06 + 4.87000E+02 2.90251E+06 + 4.87100E+02 2.87908E+06 + 4.87200E+02 2.85560E+06 + 4.87300E+02 2.83209E+06 + 4.87400E+02 2.80856E+06 + 4.87500E+02 2.78503E+06 + 4.87600E+02 2.76152E+06 + 4.87700E+02 2.73804E+06 + 4.87800E+02 2.71460E+06 + 4.87900E+02 2.69122E+06 + 4.88000E+02 2.66792E+06 + 4.88100E+02 2.64470E+06 + 4.88200E+02 2.62159E+06 + 4.88300E+02 2.59860E+06 + 4.88400E+02 2.57574E+06 + 4.88500E+02 2.55302E+06 + 4.88600E+02 2.53047E+06 + 4.88700E+02 2.50809E+06 + 4.88800E+02 2.48591E+06 + 4.88900E+02 2.46393E+06 + 4.89000E+02 2.44216E+06 + 4.89100E+02 2.42062E+06 + 4.89200E+02 2.39934E+06 + 4.89300E+02 2.37831E+06 + 4.89400E+02 2.35755E+06 + 4.89500E+02 2.33707E+06 + 4.89600E+02 2.31689E+06 + 4.89700E+02 2.29703E+06 + 4.89800E+02 2.27749E+06 + 4.89900E+02 2.25828E+06 + 4.90000E+02 2.23942E+06 + 4.90100E+02 2.22092E+06 + 4.90200E+02 2.20279E+06 + 4.90300E+02 2.18505E+06 + 4.90400E+02 2.16770E+06 + 4.90500E+02 2.15074E+06 + 4.90600E+02 2.13421E+06 + 4.90700E+02 2.11811E+06 + 4.90800E+02 2.10244E+06 + 4.90900E+02 2.08722E+06 + 4.91000E+02 2.07244E+06 + 4.91100E+02 2.05814E+06 + 4.91200E+02 2.04431E+06 + 4.91300E+02 2.03097E+06 + 4.91400E+02 2.01811E+06 + 4.91500E+02 2.00575E+06 + 4.91600E+02 1.99390E+06 + 4.91700E+02 1.98257E+06 + 4.91800E+02 1.97176E+06 + 4.91900E+02 1.96147E+06 + 4.92000E+02 1.95172E+06 + 4.92100E+02 1.94251E+06 + 4.92200E+02 1.93385E+06 + 4.92300E+02 1.92575E+06 + 4.92400E+02 1.91820E+06 + 4.92500E+02 1.91120E+06 + 4.92600E+02 1.90478E+06 + 4.92700E+02 1.89893E+06 + 4.92800E+02 1.89366E+06 + 4.92900E+02 1.88896E+06 + 4.93000E+02 1.88484E+06 + 4.93100E+02 1.88130E+06 + 4.93200E+02 1.87836E+06 + 4.93300E+02 1.87600E+06 + 4.93400E+02 1.87422E+06 + 4.93500E+02 1.87304E+06 + 4.93600E+02 1.87245E+06 + 4.93700E+02 1.87245E+06 + 4.93800E+02 1.87304E+06 + 4.93900E+02 1.87422E+06 + 4.94000E+02 1.87600E+06 + 4.94100E+02 1.87836E+06 + 4.94200E+02 1.88131E+06 + 4.94300E+02 1.88484E+06 + 4.94400E+02 1.88896E+06 + 4.94500E+02 1.89366E+06 + 4.94600E+02 1.89894E+06 + 4.94700E+02 1.90479E+06 + 4.94800E+02 1.91121E+06 + 4.94900E+02 1.91820E+06 + 4.95000E+02 1.92575E+06 + 4.95100E+02 1.93386E+06 + 4.95200E+02 1.94252E+06 + 4.95300E+02 1.95173E+06 + 4.95400E+02 1.96148E+06 + 4.95500E+02 1.97176E+06 + 4.95600E+02 1.98258E+06 + 4.95700E+02 1.99391E+06 + 4.95800E+02 2.00576E+06 + 4.95900E+02 2.01812E+06 + 4.96000E+02 2.03098E+06 + 4.96100E+02 2.04432E+06 + 4.96200E+02 2.05815E+06 + 4.96300E+02 2.07245E+06 + 4.96400E+02 2.08722E+06 + 4.96500E+02 2.10245E+06 + 4.96600E+02 2.11812E+06 + 4.96700E+02 2.13422E+06 + 4.96800E+02 2.15076E+06 + 4.96900E+02 2.16770E+06 + 4.97000E+02 2.18506E+06 + 4.97100E+02 2.20280E+06 + 4.97200E+02 2.22093E+06 + 4.97300E+02 2.23943E+06 + 4.97400E+02 2.25829E+06 + 4.97500E+02 2.27750E+06 + 4.97600E+02 2.29704E+06 + 4.97700E+02 2.31691E+06 + 4.97800E+02 2.33708E+06 + 4.97900E+02 2.35756E+06 + 4.98000E+02 2.37832E+06 + 4.98100E+02 2.39935E+06 + 4.98200E+02 2.42064E+06 + 4.98300E+02 2.44217E+06 + 4.98400E+02 2.46393E+06 + 4.98500E+02 2.48592E+06 + 4.98600E+02 2.50811E+06 + 4.98700E+02 2.53048E+06 + 4.98800E+02 2.55304E+06 + 4.98900E+02 2.57575E+06 + 4.99000E+02 2.59861E+06 + 4.99100E+02 2.62161E+06 + 4.99200E+02 2.64472E+06 + 4.99300E+02 2.66793E+06 + 4.99400E+02 2.69123E+06 + 4.99500E+02 2.71462E+06 + 4.99600E+02 2.73805E+06 + 4.99700E+02 2.76153E+06 + 4.99800E+02 2.78504E+06 + 4.99900E+02 2.80857E+06 + 5.00000E+02 2.83210E+06 + 5.00100E+02 2.85561E+06 + 5.00200E+02 2.87909E+06 + 5.00300E+02 2.90253E+06 + 5.00400E+02 2.92590E+06 + 5.00500E+02 2.94921E+06 + 5.00600E+02 2.97243E+06 + 5.00700E+02 2.99554E+06 + 5.00800E+02 3.01853E+06 + 5.00900E+02 3.04139E+06 + 5.01000E+02 3.06411E+06 + 5.01100E+02 3.08666E+06 + 5.01200E+02 3.10904E+06 + 5.01300E+02 3.13122E+06 + 5.01400E+02 3.15320E+06 + 5.01500E+02 3.17497E+06 + 5.01600E+02 3.19651E+06 + 5.01700E+02 3.21779E+06 + 5.01800E+02 3.23882E+06 + 5.01900E+02 3.25958E+06 + 5.02000E+02 3.28006E+06 + 5.02100E+02 3.30023E+06 + 5.02200E+02 3.32010E+06 + 5.02300E+02 3.33964E+06 + 5.02400E+02 3.35885E+06 + 5.02500E+02 3.37771E+06 + 5.02600E+02 3.39621E+06 + 5.02700E+02 3.41434E+06 + 5.02800E+02 3.43208E+06 + 5.02900E+02 3.44943E+06 + 5.03000E+02 3.46638E+06 + 5.03100E+02 3.48292E+06 + 5.03200E+02 3.49902E+06 + 5.03300E+02 3.51469E+06 + 5.03400E+02 3.52991E+06 + 5.03500E+02 3.54468E+06 + 5.03600E+02 3.55899E+06 + 5.03700E+02 3.57282E+06 + 5.03800E+02 3.58616E+06 + 5.03900E+02 3.59902E+06 + 5.04000E+02 3.61137E+06 + 5.04100E+02 3.62322E+06 + 5.04200E+02 3.63456E+06 + 5.04300E+02 3.64537E+06 + 5.04400E+02 3.65565E+06 + 5.04500E+02 3.66540E+06 + 5.04600E+02 3.67461E+06 + 5.04700E+02 3.68327E+06 + 5.04800E+02 3.69138E+06 + 5.04900E+02 3.69893E+06 + 5.05000E+02 3.70592E+06 + 5.05100E+02 3.71235E+06 + 5.05200E+02 3.71820E+06 + 5.05300E+02 3.72347E+06 + 5.05400E+02 3.72817E+06 + 5.05500E+02 3.73229E+06 + 5.05600E+02 3.73582E+06 + 5.05700E+02 3.73877E+06 + 5.05800E+02 3.74113E+06 + 5.05900E+02 3.74290E+06 + 5.06000E+02 3.74409E+06 + 5.06100E+02 3.74468E+06 + 5.06200E+02 3.74468E+06 + 5.06300E+02 3.74409E+06 + 5.06400E+02 3.74290E+06 + 5.06500E+02 3.74113E+06 + 5.06600E+02 3.73877E+06 + 5.06700E+02 3.73582E+06 + 5.06800E+02 3.73229E+06 + 5.06900E+02 3.72817E+06 + 5.07000E+02 3.72347E+06 + 5.07100E+02 3.71819E+06 + 5.07200E+02 3.71234E+06 + 5.07300E+02 3.70592E+06 + 5.07400E+02 3.69893E+06 + 5.07500E+02 3.69138E+06 + 5.07600E+02 3.68327E+06 + 5.07700E+02 3.67461E+06 + 5.07800E+02 3.66540E+06 + 5.07900E+02 3.65565E+06 + 5.08000E+02 3.64537E+06 + 5.08100E+02 3.63455E+06 + 5.08200E+02 3.62322E+06 + 5.08300E+02 3.61137E+06 + 5.08400E+02 3.59901E+06 + 5.08500E+02 3.58616E+06 + 5.08600E+02 3.57281E+06 + 5.08700E+02 3.55898E+06 + 5.08800E+02 3.54467E+06 + 5.08900E+02 3.52991E+06 + 5.09000E+02 3.51468E+06 + 5.09100E+02 3.49901E+06 + 5.09200E+02 3.48290E+06 + 5.09300E+02 3.46638E+06 + 5.09400E+02 3.44942E+06 + 5.09500E+02 3.43207E+06 + 5.09600E+02 3.41432E+06 + 5.09700E+02 3.39619E+06 + 5.09800E+02 3.37770E+06 + 5.09900E+02 3.35884E+06 + 5.10000E+02 3.33963E+06 + 5.10100E+02 3.32009E+06 + 5.10200E+02 3.30021E+06 + 5.10300E+02 3.28005E+06 + 5.10400E+02 3.25956E+06 + 5.10500E+02 3.23881E+06 + 5.10600E+02 3.21778E+06 + 5.10700E+02 3.19649E+06 + 5.10800E+02 3.17496E+06 + 5.10900E+02 3.15319E+06 + 5.11000E+02 3.13121E+06 + 5.11100E+02 3.10902E+06 + 5.11200E+02 3.08664E+06 + 5.11300E+02 3.06410E+06 + 5.11400E+02 3.04137E+06 + 5.11500E+02 3.01851E+06 + 5.11600E+02 2.99552E+06 + 5.11700E+02 2.97241E+06 + 5.11800E+02 2.94920E+06 + 5.11900E+02 2.92589E+06 + 5.12000E+02 2.90250E+06 + 5.12100E+02 2.87908E+06 + 5.12200E+02 2.85560E+06 + 5.12300E+02 2.83208E+06 + 5.12400E+02 2.80856E+06 + 5.12500E+02 2.78503E+06 + 5.12600E+02 2.76152E+06 + 5.12700E+02 2.73804E+06 + 5.12800E+02 2.71460E+06 + 5.12900E+02 2.69122E+06 + 5.13000E+02 2.66791E+06 + 5.13100E+02 2.64471E+06 + 5.13200E+02 2.62160E+06 + 5.13300E+02 2.59859E+06 + 5.13400E+02 2.57574E+06 + 5.13500E+02 2.55302E+06 + 5.13600E+02 2.53047E+06 + 5.13700E+02 2.50809E+06 + 5.13800E+02 2.48591E+06 + 5.13900E+02 2.46392E+06 + 5.14000E+02 2.44215E+06 + 5.14100E+02 2.42063E+06 + 5.14200E+02 2.39934E+06 + 5.14300E+02 2.37830E+06 + 5.14400E+02 2.35755E+06 + 5.14500E+02 2.33707E+06 + 5.14600E+02 2.31689E+06 + 5.14700E+02 2.29703E+06 + 5.14800E+02 2.27749E+06 + 5.14900E+02 2.25828E+06 + 5.15000E+02 2.23941E+06 + 5.15100E+02 2.22092E+06 + 5.15200E+02 2.20280E+06 + 5.15300E+02 2.18504E+06 + 5.15400E+02 2.16770E+06 + 5.15500E+02 2.15074E+06 + 5.15600E+02 2.13421E+06 + 5.15700E+02 2.11811E+06 + 5.15800E+02 2.10244E+06 + 5.15900E+02 2.08721E+06 + 5.16000E+02 2.07244E+06 + 5.16100E+02 2.05814E+06 + 5.16200E+02 2.04432E+06 + 5.16300E+02 2.03096E+06 + 5.16400E+02 2.01811E+06 + 5.16500E+02 2.00575E+06 + 5.16600E+02 1.99390E+06 + 5.16700E+02 1.98257E+06 + 5.16800E+02 1.97176E+06 + 5.16900E+02 1.96147E+06 + 5.17000E+02 1.95172E+06 + 5.17100E+02 1.94252E+06 + 5.17200E+02 1.93386E+06 + 5.17300E+02 1.92574E+06 + 5.17400E+02 1.91820E+06 + 5.17500E+02 1.91120E+06 + 5.17600E+02 1.90478E+06 + 5.17700E+02 1.89893E+06 + 5.17800E+02 1.89366E+06 + 5.17900E+02 1.88896E+06 + 5.18000E+02 1.88484E+06 + 5.18100E+02 1.88131E+06 + 5.18200E+02 1.87836E+06 + 5.18300E+02 1.87599E+06 + 5.18400E+02 1.87422E+06 + 5.18500E+02 1.87304E+06 + 5.18600E+02 1.87245E+06 + 5.18700E+02 1.87245E+06 + 5.18800E+02 1.87304E+06 + 5.18900E+02 1.87422E+06 + 5.19000E+02 1.87600E+06 + 5.19100E+02 1.87836E+06 + 5.19200E+02 1.88131E+06 + 5.19300E+02 1.88484E+06 + 5.19400E+02 1.88896E+06 + 5.19500E+02 1.89366E+06 + 5.19600E+02 1.89894E+06 + 5.19700E+02 1.90479E+06 + 5.19800E+02 1.91121E+06 + 5.19900E+02 1.91820E+06 + 5.20000E+02 1.92575E+06 + 5.20100E+02 1.93386E+06 + 5.20200E+02 1.94252E+06 + 5.20300E+02 1.95173E+06 + 5.20400E+02 1.96148E+06 + 5.20500E+02 1.97177E+06 + 5.20600E+02 1.98258E+06 + 5.20700E+02 1.99391E+06 + 5.20800E+02 2.00576E+06 + 5.20900E+02 2.01812E+06 + 5.21000E+02 2.03098E+06 + 5.21100E+02 2.04432E+06 + 5.21200E+02 2.05815E+06 + 5.21300E+02 2.07246E+06 + 5.21400E+02 2.08722E+06 + 5.21500E+02 2.10245E+06 + 5.21600E+02 2.11812E+06 + 5.21700E+02 2.13423E+06 + 5.21800E+02 2.15076E+06 + 5.21900E+02 2.16770E+06 + 5.22000E+02 2.18507E+06 + 5.22100E+02 2.20280E+06 + 5.22200E+02 2.22093E+06 + 5.22300E+02 2.23944E+06 + 5.22400E+02 2.25829E+06 + 5.22500E+02 2.27750E+06 + 5.22600E+02 2.29705E+06 + 5.22700E+02 2.31691E+06 + 5.22800E+02 2.33709E+06 + 5.22900E+02 2.35756E+06 + 5.23000E+02 2.37833E+06 + 5.23100E+02 2.39935E+06 + 5.23200E+02 2.42063E+06 + 5.23300E+02 2.44218E+06 + 5.23400E+02 2.46393E+06 + 5.23500E+02 2.48593E+06 + 5.23600E+02 2.50811E+06 + 5.23700E+02 2.53049E+06 + 5.23800E+02 2.55304E+06 + 5.23900E+02 2.57575E+06 + 5.24000E+02 2.59862E+06 + 5.24100E+02 2.62160E+06 + 5.24200E+02 2.64471E+06 + 5.24300E+02 2.66794E+06 + 5.24400E+02 2.69123E+06 + 5.24500E+02 2.71462E+06 + 5.24600E+02 2.73806E+06 + 5.24700E+02 2.76154E+06 + 5.24800E+02 2.78505E+06 + 5.24900E+02 2.80857E+06 + 5.25000E+02 2.83211E+06 + 5.25100E+02 2.85561E+06 + 5.25200E+02 2.87909E+06 + 5.25300E+02 2.90254E+06 + 5.25400E+02 2.92590E+06 + 5.25500E+02 2.94922E+06 + 5.25600E+02 2.97243E+06 + 5.25700E+02 2.99554E+06 + 5.25800E+02 3.01853E+06 + 5.25900E+02 3.04139E+06 + 5.26000E+02 3.06412E+06 + 5.26100E+02 3.08666E+06 + 5.26200E+02 3.10903E+06 + 5.26300E+02 3.13123E+06 + 5.26400E+02 3.15320E+06 + 5.26500E+02 3.17498E+06 + 5.26600E+02 3.19651E+06 + 5.26700E+02 3.21780E+06 + 5.26800E+02 3.23883E+06 + 5.26900E+02 3.25958E+06 + 5.27000E+02 3.28007E+06 + 5.27100E+02 3.30023E+06 + 5.27200E+02 3.32009E+06 + 5.27300E+02 3.33965E+06 + 5.27400E+02 3.35884E+06 + 5.27500E+02 3.37771E+06 + 5.27600E+02 3.39621E+06 + 5.27700E+02 3.41434E+06 + 5.27800E+02 3.43208E+06 + 5.27900E+02 3.44943E+06 + 5.28000E+02 3.46639E+06 + 5.28100E+02 3.48291E+06 + 5.28200E+02 3.49902E+06 + 5.28300E+02 3.51470E+06 + 5.28400E+02 3.52991E+06 + 5.28500E+02 3.54469E+06 + 5.28600E+02 3.55899E+06 + 5.28700E+02 3.57282E+06 + 5.28800E+02 3.58616E+06 + 5.28900E+02 3.59902E+06 + 5.29000E+02 3.61138E+06 + 5.29100E+02 3.62322E+06 + 5.29200E+02 3.63456E+06 + 5.29300E+02 3.64538E+06 + 5.29400E+02 3.65565E+06 + 5.29500E+02 3.66541E+06 + 5.29600E+02 3.67461E+06 + 5.29700E+02 3.68327E+06 + 5.29800E+02 3.69138E+06 + 5.29900E+02 3.69893E+06 + 5.30000E+02 3.70593E+06 + 5.30100E+02 3.71234E+06 + 5.30200E+02 3.71820E+06 + 5.30300E+02 3.72347E+06 + 5.30400E+02 3.72817E+06 + 5.30500E+02 3.73229E+06 + 5.30600E+02 3.73582E+06 + 5.30700E+02 3.73877E+06 + 5.30800E+02 3.74113E+06 + 5.30900E+02 3.74291E+06 + 5.31000E+02 3.74409E+06 + 5.31100E+02 3.74468E+06 + 5.31200E+02 3.74468E+06 + 5.31300E+02 3.74409E+06 + 5.31400E+02 3.74290E+06 + 5.31500E+02 3.74113E+06 + 5.31600E+02 3.73877E+06 + 5.31700E+02 3.73582E+06 + 5.31800E+02 3.73229E+06 + 5.31900E+02 3.72817E+06 + 5.32000E+02 3.72347E+06 + 5.32100E+02 3.71819E+06 + 5.32200E+02 3.71234E+06 + 5.32300E+02 3.70592E+06 + 5.32400E+02 3.69893E+06 + 5.32500E+02 3.69138E+06 + 5.32600E+02 3.68327E+06 + 5.32700E+02 3.67461E+06 + 5.32800E+02 3.66540E+06 + 5.32900E+02 3.65565E+06 + 5.33000E+02 3.64536E+06 + 5.33100E+02 3.63455E+06 + 5.33200E+02 3.62322E+06 + 5.33300E+02 3.61136E+06 + 5.33400E+02 3.59901E+06 + 5.33500E+02 3.58615E+06 + 5.33600E+02 3.57280E+06 + 5.33700E+02 3.55898E+06 + 5.33800E+02 3.54467E+06 + 5.33900E+02 3.52990E+06 + 5.34000E+02 3.51467E+06 + 5.34100E+02 3.49901E+06 + 5.34200E+02 3.48291E+06 + 5.34300E+02 3.46636E+06 + 5.34400E+02 3.44943E+06 + 5.34500E+02 3.43207E+06 + 5.34600E+02 3.41432E+06 + 5.34700E+02 3.39620E+06 + 5.34800E+02 3.37769E+06 + 5.34900E+02 3.35883E+06 + 5.35000E+02 3.33962E+06 + 5.35100E+02 3.32009E+06 + 5.35200E+02 3.30022E+06 + 5.35300E+02 3.28004E+06 + 5.35400E+02 3.25957E+06 + 5.35500E+02 3.23880E+06 + 5.35600E+02 3.21778E+06 + 5.35700E+02 3.19650E+06 + 5.35800E+02 3.17495E+06 + 5.35900E+02 3.15319E+06 + 5.36000E+02 3.13119E+06 + 5.36100E+02 3.10902E+06 + 5.36200E+02 3.08665E+06 + 5.36300E+02 3.06408E+06 + 5.36400E+02 3.04138E+06 + 5.36500E+02 3.01851E+06 + 5.36600E+02 2.99552E+06 + 5.36700E+02 2.97242E+06 + 5.36800E+02 2.94919E+06 + 5.36900E+02 2.92589E+06 + 5.37000E+02 2.90250E+06 + 5.37100E+02 2.87908E+06 + 5.37200E+02 2.85560E+06 + 5.37300E+02 2.83207E+06 + 5.37400E+02 2.80856E+06 + 5.37500E+02 2.78502E+06 + 5.37600E+02 2.76151E+06 + 5.37700E+02 2.73805E+06 + 5.37800E+02 2.71460E+06 + 5.37900E+02 2.69122E+06 + 5.38000E+02 2.66790E+06 + 5.38100E+02 2.64470E+06 + 5.38200E+02 2.62159E+06 + 5.38300E+02 2.59859E+06 + 5.38400E+02 2.57574E+06 + 5.38500E+02 2.55302E+06 + 5.38600E+02 2.53046E+06 + 5.38700E+02 2.50810E+06 + 5.38800E+02 2.48590E+06 + 5.38900E+02 2.46392E+06 + 5.39000E+02 2.44214E+06 + 5.39100E+02 2.42062E+06 + 5.39200E+02 2.39934E+06 + 5.39300E+02 2.37830E+06 + 5.39400E+02 2.35755E+06 + 5.39500E+02 2.33707E+06 + 5.39600E+02 2.31689E+06 + 5.39700E+02 2.29704E+06 + 5.39800E+02 2.27749E+06 + 5.39900E+02 2.25828E+06 + 5.40000E+02 2.23941E+06 + 5.40100E+02 2.22092E+06 + 5.40200E+02 2.20279E+06 + 5.40300E+02 2.18504E+06 + 5.40400E+02 2.16770E+06 + 5.40500E+02 2.15074E+06 + 5.40600E+02 2.13421E+06 + 5.40700E+02 2.11811E+06 + 5.40800E+02 2.10244E+06 + 5.40900E+02 2.08721E+06 + 5.41000E+02 2.07244E+06 + 5.41100E+02 2.05814E+06 + 5.41200E+02 2.04431E+06 + 5.41300E+02 2.03096E+06 + 5.41400E+02 2.01811E+06 + 5.41500E+02 2.00575E+06 + 5.41600E+02 1.99390E+06 + 5.41700E+02 1.98257E+06 + 5.41800E+02 1.97176E+06 + 5.41900E+02 1.96147E+06 + 5.42000E+02 1.95172E+06 + 5.42100E+02 1.94252E+06 + 5.42200E+02 1.93385E+06 + 5.42300E+02 1.92574E+06 + 5.42400E+02 1.91820E+06 + 5.42500E+02 1.91120E+06 + 5.42600E+02 1.90478E+06 + 5.42700E+02 1.89893E+06 + 5.42800E+02 1.89366E+06 + 5.42900E+02 1.88896E+06 + 5.43000E+02 1.88484E+06 + 5.43100E+02 1.88131E+06 + 5.43200E+02 1.87836E+06 + 5.43300E+02 1.87599E+06 + 5.43400E+02 1.87422E+06 + 5.43500E+02 1.87304E+06 + 5.43600E+02 1.87245E+06 + 5.43700E+02 1.87245E+06 + 5.43800E+02 1.87304E+06 + 5.43900E+02 1.87422E+06 + 5.44000E+02 1.87600E+06 + 5.44100E+02 1.87836E+06 + 5.44200E+02 1.88131E+06 + 5.44300E+02 1.88484E+06 + 5.44400E+02 1.88896E+06 + 5.44500E+02 1.89366E+06 + 5.44600E+02 1.89894E+06 + 5.44700E+02 1.90478E+06 + 5.44800E+02 1.91121E+06 + 5.44900E+02 1.91820E+06 + 5.45000E+02 1.92575E+06 + 5.45100E+02 1.93386E+06 + 5.45200E+02 1.94252E+06 + 5.45300E+02 1.95173E+06 + 5.45400E+02 1.96148E+06 + 5.45500E+02 1.97177E+06 + 5.45600E+02 1.98258E+06 + 5.45700E+02 1.99391E+06 + 5.45800E+02 2.00576E+06 + 5.45900E+02 2.01812E+06 + 5.46000E+02 2.03098E+06 + 5.46100E+02 2.04432E+06 + 5.46200E+02 2.05815E+06 + 5.46300E+02 2.07246E+06 + 5.46400E+02 2.08722E+06 + 5.46500E+02 2.10245E+06 + 5.46600E+02 2.11812E+06 + 5.46700E+02 2.13422E+06 + 5.46800E+02 2.15076E+06 + 5.46900E+02 2.16771E+06 + 5.47000E+02 2.18506E+06 + 5.47100E+02 2.20280E+06 + 5.47200E+02 2.22093E+06 + 5.47300E+02 2.23944E+06 + 5.47400E+02 2.25829E+06 + 5.47500E+02 2.27751E+06 + 5.47600E+02 2.29705E+06 + 5.47700E+02 2.31690E+06 + 5.47800E+02 2.33709E+06 + 5.47900E+02 2.35756E+06 + 5.48000E+02 2.37832E+06 + 5.48100E+02 2.39935E+06 + 5.48200E+02 2.42064E+06 + 5.48300E+02 2.44218E+06 + 5.48400E+02 2.46393E+06 + 5.48500E+02 2.48593E+06 + 5.48600E+02 2.50811E+06 + 5.48700E+02 2.53048E+06 + 5.48800E+02 2.55304E+06 + 5.48900E+02 2.57575E+06 + 5.49000E+02 2.59861E+06 + 5.49100E+02 2.62160E+06 + 5.49200E+02 2.64471E+06 + 5.49300E+02 2.66794E+06 + 5.49400E+02 2.69123E+06 + 5.49500E+02 2.71462E+06 + 5.49600E+02 2.73806E+06 + 5.49700E+02 2.76152E+06 + 5.49800E+02 2.78505E+06 + 5.49900E+02 2.80857E+06 + 5.50000E+02 2.83210E+06 + 5.50100E+02 2.85561E+06 + 5.50200E+02 2.87909E+06 + 5.50300E+02 2.90254E+06 + 5.50400E+02 2.92590E+06 + 5.50500E+02 2.94922E+06 + 5.50600E+02 2.97243E+06 + 5.50700E+02 2.99553E+06 + 5.50800E+02 3.01853E+06 + 5.50900E+02 3.04139E+06 + 5.51000E+02 3.06411E+06 + 5.51100E+02 3.08666E+06 + 5.51200E+02 3.10903E+06 + 5.51300E+02 3.13123E+06 + 5.51400E+02 3.15320E+06 + 5.51500E+02 3.17498E+06 + 5.51600E+02 3.19651E+06 + 5.51700E+02 3.21779E+06 + 5.51800E+02 3.23883E+06 + 5.51900E+02 3.25958E+06 + 5.52000E+02 3.28006E+06 + 5.52100E+02 3.30023E+06 + 5.52200E+02 3.32010E+06 + 5.52300E+02 3.33965E+06 + 5.52400E+02 3.35884E+06 + 5.52500E+02 3.37771E+06 + 5.52600E+02 3.39621E+06 + 5.52700E+02 3.41433E+06 + 5.52800E+02 3.43208E+06 + 5.52900E+02 3.44944E+06 + 5.53000E+02 3.46638E+06 + 5.53100E+02 3.48291E+06 + 5.53200E+02 3.49902E+06 + 5.53300E+02 3.51470E+06 + 5.53400E+02 3.52991E+06 + 5.53500E+02 3.54469E+06 + 5.53600E+02 3.55899E+06 + 5.53700E+02 3.57281E+06 + 5.53800E+02 3.58616E+06 + 5.53900E+02 3.59902E+06 + 5.54000E+02 3.61137E+06 + 5.54100E+02 3.62322E+06 + 5.54200E+02 3.63456E+06 + 5.54300E+02 3.64538E+06 + 5.54400E+02 3.65565E+06 + 5.54500E+02 3.66541E+06 + 5.54600E+02 3.67462E+06 + 5.54700E+02 3.68327E+06 + 5.54800E+02 3.69138E+06 + 5.54900E+02 3.69893E+06 + 5.55000E+02 3.70592E+06 + 5.55100E+02 3.71234E+06 + 5.55200E+02 3.71820E+06 + 5.55300E+02 3.72347E+06 + 5.55400E+02 3.72817E+06 + 5.55500E+02 3.73229E+06 + 5.55600E+02 3.73582E+06 + 5.55700E+02 3.73877E+06 + 5.55800E+02 3.74113E+06 + 5.55900E+02 3.74291E+06 + 5.56000E+02 3.74409E+06 + 5.56100E+02 3.74468E+06 + 5.56200E+02 3.74468E+06 + 5.56300E+02 3.74409E+06 + 5.56400E+02 3.74290E+06 + 5.56500E+02 3.74113E+06 + 5.56600E+02 3.73877E+06 + 5.56700E+02 3.73582E+06 + 5.56800E+02 3.73229E+06 + 5.56900E+02 3.72817E+06 + 5.57000E+02 3.72347E+06 + 5.57100E+02 3.71819E+06 + 5.57200E+02 3.71234E+06 + 5.57300E+02 3.70592E+06 + 5.57400E+02 3.69893E+06 + 5.57500E+02 3.69138E+06 + 5.57600E+02 3.68327E+06 + 5.57700E+02 3.67461E+06 + 5.57800E+02 3.66540E+06 + 5.57900E+02 3.65565E+06 + 5.58000E+02 3.64536E+06 + 5.58100E+02 3.63455E+06 + 5.58200E+02 3.62322E+06 + 5.58300E+02 3.61136E+06 + 5.58400E+02 3.59901E+06 + 5.58500E+02 3.58615E+06 + 5.58600E+02 3.57280E+06 + 5.58700E+02 3.55898E+06 + 5.58800E+02 3.54467E+06 + 5.58900E+02 3.52990E+06 + 5.59000E+02 3.51468E+06 + 5.59100E+02 3.49901E+06 + 5.59200E+02 3.48290E+06 + 5.59300E+02 3.46636E+06 + 5.59400E+02 3.44943E+06 + 5.59500E+02 3.43206E+06 + 5.59600E+02 3.41432E+06 + 5.59700E+02 3.39620E+06 + 5.59800E+02 3.37769E+06 + 5.59900E+02 3.35883E+06 + 5.60000E+02 3.33963E+06 + 5.60100E+02 3.32009E+06 + 5.60200E+02 3.30022E+06 + 5.60300E+02 3.28003E+06 + 5.60400E+02 3.25957E+06 + 5.60500E+02 3.23880E+06 + 5.60600E+02 3.21777E+06 + 5.60700E+02 3.19650E+06 + 5.60800E+02 3.17495E+06 + 5.60900E+02 3.15319E+06 + 5.61000E+02 3.13121E+06 + 5.61100E+02 3.10902E+06 + 5.61200E+02 3.08664E+06 + 5.61300E+02 3.06408E+06 + 5.61400E+02 3.04138E+06 + 5.61500E+02 3.01851E+06 + 5.61600E+02 2.99552E+06 + 5.61700E+02 2.97242E+06 + 5.61800E+02 2.94919E+06 + 5.61900E+02 2.92589E+06 + 5.62000E+02 2.90251E+06 + 5.62100E+02 2.87908E+06 + 5.62200E+02 2.85560E+06 + 5.62300E+02 2.83207E+06 + 5.62400E+02 2.80856E+06 + 5.62500E+02 2.78502E+06 + 5.62600E+02 2.76151E+06 + 5.62700E+02 2.73804E+06 + 5.62800E+02 2.71459E+06 + 5.62900E+02 2.69122E+06 + 5.63000E+02 2.66792E+06 + 5.63100E+02 2.64470E+06 + 5.63200E+02 2.62159E+06 + 5.63300E+02 2.59859E+06 + 5.63400E+02 2.57574E+06 + 5.63500E+02 2.55301E+06 + 5.63600E+02 2.53046E+06 + 5.63700E+02 2.50810E+06 + 5.63800E+02 2.48590E+06 + 5.63900E+02 2.46392E+06 + 5.64000E+02 2.44216E+06 + 5.64100E+02 2.42062E+06 + 5.64200E+02 2.39934E+06 + 5.64300E+02 2.37831E+06 + 5.64400E+02 2.35755E+06 + 5.64500E+02 2.33706E+06 + 5.64600E+02 2.31689E+06 + 5.64700E+02 2.29704E+06 + 5.64800E+02 2.27748E+06 + 5.64900E+02 2.25828E+06 + 5.65000E+02 2.23942E+06 + 5.65100E+02 2.22092E+06 + 5.65200E+02 2.20279E+06 + 5.65300E+02 2.18505E+06 + 5.65400E+02 2.16770E+06 + 5.65500E+02 2.15074E+06 + 5.65600E+02 2.13421E+06 + 5.65700E+02 2.11811E+06 + 5.65800E+02 2.10243E+06 + 5.65900E+02 2.08721E+06 + 5.66000E+02 2.07244E+06 + 5.66100E+02 2.05814E+06 + 5.66200E+02 2.04431E+06 + 5.66300E+02 2.03097E+06 + 5.66400E+02 2.01811E+06 + 5.66500E+02 2.00575E+06 + 5.66600E+02 1.99390E+06 + 5.66700E+02 1.98257E+06 + 5.66800E+02 1.97175E+06 + 5.66900E+02 1.96147E+06 + 5.67000E+02 1.95172E+06 + 5.67100E+02 1.94251E+06 + 5.67200E+02 1.93385E+06 + 5.67300E+02 1.92575E+06 + 5.67400E+02 1.91820E+06 + 5.67500E+02 1.91120E+06 + 5.67600E+02 1.90478E+06 + 5.67700E+02 1.89893E+06 + 5.67800E+02 1.89365E+06 + 5.67900E+02 1.88896E+06 + 5.68000E+02 1.88484E+06 + 5.68100E+02 1.88130E+06 + 5.68200E+02 1.87836E+06 + 5.68300E+02 1.87600E+06 + 5.68400E+02 1.87422E+06 + 5.68500E+02 1.87304E+06 + 5.68600E+02 1.87245E+06 + 5.68700E+02 1.87245E+06 + 5.68800E+02 1.87304E+06 + 5.68900E+02 1.87422E+06 + 5.69000E+02 1.87600E+06 + 5.69100E+02 1.87836E+06 + 5.69200E+02 1.88131E+06 + 5.69300E+02 1.88484E+06 + 5.69400E+02 1.88896E+06 + 5.69500E+02 1.89366E+06 + 5.69600E+02 1.89894E+06 + 5.69700E+02 1.90479E+06 + 5.69800E+02 1.91121E+06 + 5.69900E+02 1.91820E+06 + 5.70000E+02 1.92575E+06 + 5.70100E+02 1.93386E+06 + 5.70200E+02 1.94252E+06 + 5.70300E+02 1.95173E+06 + 5.70400E+02 1.96148E+06 + 5.70500E+02 1.97177E+06 + 5.70600E+02 1.98258E+06 + 5.70700E+02 1.99391E+06 + 5.70800E+02 2.00576E+06 + 5.70900E+02 2.01812E+06 + 5.71000E+02 2.03098E+06 + 5.71100E+02 2.04432E+06 + 5.71200E+02 2.05815E+06 + 5.71300E+02 2.07245E+06 + 5.71400E+02 2.08722E+06 + 5.71500E+02 2.10245E+06 + 5.71600E+02 2.11812E+06 + 5.71700E+02 2.13422E+06 + 5.71800E+02 2.15076E+06 + 5.71900E+02 2.16771E+06 + 5.72000E+02 2.18506E+06 + 5.72100E+02 2.20280E+06 + 5.72200E+02 2.22093E+06 + 5.72300E+02 2.23943E+06 + 5.72400E+02 2.25829E+06 + 5.72500E+02 2.27751E+06 + 5.72600E+02 2.29705E+06 + 5.72700E+02 2.31690E+06 + 5.72800E+02 2.33709E+06 + 5.72900E+02 2.35756E+06 + 5.73000E+02 2.37832E+06 + 5.73100E+02 2.39935E+06 + 5.73200E+02 2.42064E+06 + 5.73300E+02 2.44217E+06 + 5.73400E+02 2.46393E+06 + 5.73500E+02 2.48593E+06 + 5.73600E+02 2.50812E+06 + 5.73700E+02 2.53048E+06 + 5.73800E+02 2.55304E+06 + 5.73900E+02 2.57576E+06 + 5.74000E+02 2.59861E+06 + 5.74100E+02 2.62161E+06 + 5.74200E+02 2.64472E+06 + 5.74300E+02 2.66793E+06 + 5.74400E+02 2.69123E+06 + 5.74500E+02 2.71462E+06 + 5.74600E+02 2.73806E+06 + 5.74700E+02 2.76153E+06 + 5.74800E+02 2.78505E+06 + 5.74900E+02 2.80858E+06 + 5.75000E+02 2.83210E+06 + 5.75100E+02 2.85561E+06 + 5.75200E+02 2.87909E+06 + 5.75300E+02 2.90253E+06 + 5.75400E+02 2.92590E+06 + 5.75500E+02 2.94922E+06 + 5.75600E+02 2.97243E+06 + 5.75700E+02 2.99553E+06 + 5.75800E+02 3.01854E+06 + 5.75900E+02 3.04140E+06 + 5.76000E+02 3.06411E+06 + 5.76100E+02 3.08666E+06 + 5.76200E+02 3.10904E+06 + 5.76300E+02 3.13122E+06 + 5.76400E+02 3.15320E+06 + 5.76500E+02 3.17498E+06 + 5.76600E+02 3.19651E+06 + 5.76700E+02 3.21779E+06 + 5.76800E+02 3.23883E+06 + 5.76900E+02 3.25959E+06 + 5.77000E+02 3.28006E+06 + 5.77100E+02 3.30023E+06 + 5.77200E+02 3.32010E+06 + 5.77300E+02 3.33964E+06 + 5.77400E+02 3.35885E+06 + 5.77500E+02 3.37772E+06 + 5.77600E+02 3.39621E+06 + 5.77700E+02 3.41433E+06 + 5.77800E+02 3.43209E+06 + 5.77900E+02 3.44944E+06 + 5.78000E+02 3.46638E+06 + 5.78100E+02 3.48292E+06 + 5.78200E+02 3.49902E+06 + 5.78300E+02 3.51469E+06 + 5.78400E+02 3.52991E+06 + 5.78500E+02 3.54469E+06 + 5.78600E+02 3.55899E+06 + 5.78700E+02 3.57281E+06 + 5.78800E+02 3.58617E+06 + 5.78900E+02 3.59902E+06 + 5.79000E+02 3.61138E+06 + 5.79100E+02 3.62322E+06 + 5.79200E+02 3.63456E+06 + 5.79300E+02 3.64537E+06 + 5.79400E+02 3.65565E+06 + 5.79500E+02 3.66541E+06 + 5.79600E+02 3.67462E+06 + 5.79700E+02 3.68327E+06 + 5.79800E+02 3.69138E+06 + 5.79900E+02 3.69894E+06 + 5.80000E+02 3.70592E+06 + 5.80100E+02 3.71235E+06 + 5.80200E+02 3.71820E+06 + 5.80300E+02 3.72347E+06 + 5.80400E+02 3.72817E+06 + 5.80500E+02 3.73229E+06 + 5.80600E+02 3.73582E+06 + 5.80700E+02 3.73877E+06 + 5.80800E+02 3.74113E+06 + 5.80900E+02 3.74291E+06 + 5.81000E+02 3.74409E+06 + 5.81100E+02 3.74468E+06 + 5.81200E+02 3.74468E+06 + 5.81300E+02 3.74409E+06 + 5.81400E+02 3.74290E+06 + 5.81500E+02 3.74113E+06 + 5.81600E+02 3.73877E+06 + 5.81700E+02 3.73582E+06 + 5.81800E+02 3.73229E+06 + 5.81900E+02 3.72817E+06 + 5.82000E+02 3.72347E+06 + 5.82100E+02 3.71819E+06 + 5.82200E+02 3.71234E+06 + 5.82300E+02 3.70592E+06 + 5.82400E+02 3.69893E+06 + 5.82500E+02 3.69137E+06 + 5.82600E+02 3.68327E+06 + 5.82700E+02 3.67461E+06 + 5.82800E+02 3.66540E+06 + 5.82900E+02 3.65565E+06 + 5.83000E+02 3.64536E+06 + 5.83100E+02 3.63455E+06 + 5.83200E+02 3.62322E+06 + 5.83300E+02 3.61137E+06 + 5.83400E+02 3.59901E+06 + 5.83500E+02 3.58615E+06 + 5.83600E+02 3.57281E+06 + 5.83700E+02 3.55898E+06 + 5.83800E+02 3.54467E+06 + 5.83900E+02 3.52990E+06 + 5.84000E+02 3.51468E+06 + 5.84100E+02 3.49901E+06 + 5.84200E+02 3.48290E+06 + 5.84300E+02 3.46637E+06 + 5.84400E+02 3.44942E+06 + 5.84500E+02 3.43206E+06 + 5.84600E+02 3.41433E+06 + 5.84700E+02 3.39620E+06 + 5.84800E+02 3.37769E+06 + 5.84900E+02 3.35883E+06 + 5.85000E+02 3.33962E+06 + 5.85100E+02 3.32008E+06 + 5.85200E+02 3.30022E+06 + 5.85300E+02 3.28004E+06 + 5.85400E+02 3.25957E+06 + 5.85500E+02 3.23880E+06 + 5.85600E+02 3.21778E+06 + 5.85700E+02 3.19650E+06 + 5.85800E+02 3.17495E+06 + 5.85900E+02 3.15319E+06 + 5.86000E+02 3.13120E+06 + 5.86100E+02 3.10902E+06 + 5.86200E+02 3.08664E+06 + 5.86300E+02 3.06409E+06 + 5.86400E+02 3.04138E+06 + 5.86500E+02 3.01850E+06 + 5.86600E+02 2.99553E+06 + 5.86700E+02 2.97242E+06 + 5.86800E+02 2.94919E+06 + 5.86900E+02 2.92589E+06 + 5.87000E+02 2.90251E+06 + 5.87100E+02 2.87907E+06 + 5.87200E+02 2.85559E+06 + 5.87300E+02 2.83208E+06 + 5.87400E+02 2.80856E+06 + 5.87500E+02 2.78502E+06 + 5.87600E+02 2.76152E+06 + 5.87700E+02 2.73804E+06 + 5.87800E+02 2.71459E+06 + 5.87900E+02 2.69122E+06 + 5.88000E+02 2.66791E+06 + 5.88100E+02 2.64470E+06 + 5.88200E+02 2.62159E+06 + 5.88300E+02 2.59860E+06 + 5.88400E+02 2.57574E+06 + 5.88500E+02 2.55301E+06 + 5.88600E+02 2.53047E+06 + 5.88700E+02 2.50810E+06 + 5.88800E+02 2.48590E+06 + 5.88900E+02 2.46392E+06 + 5.89000E+02 2.44215E+06 + 5.89100E+02 2.42062E+06 + 5.89200E+02 2.39933E+06 + 5.89300E+02 2.37830E+06 + 5.89400E+02 2.35755E+06 + 5.89500E+02 2.33706E+06 + 5.89600E+02 2.31690E+06 + 5.89700E+02 2.29703E+06 + 5.89800E+02 2.27748E+06 + 5.89900E+02 2.25828E+06 + 5.90000E+02 2.23942E+06 + 5.90100E+02 2.22092E+06 + 5.90200E+02 2.20279E+06 + 5.90300E+02 2.18505E+06 + 5.90400E+02 2.16769E+06 + 5.90500E+02 2.15074E+06 + 5.90600E+02 2.13422E+06 + 5.90700E+02 2.11811E+06 + 5.90800E+02 2.10243E+06 + 5.90900E+02 2.08721E+06 + 5.91000E+02 2.07244E+06 + 5.91100E+02 2.05814E+06 + 5.91200E+02 2.04431E+06 + 5.91300E+02 2.03097E+06 + 5.91400E+02 2.01811E+06 + 5.91500E+02 2.00575E+06 + 5.91600E+02 1.99391E+06 + 5.91700E+02 1.98257E+06 + 5.91800E+02 1.97175E+06 + 5.91900E+02 1.96147E+06 + 5.92000E+02 1.95172E+06 + 5.92100E+02 1.94251E+06 + 5.92200E+02 1.93385E+06 + 5.92300E+02 1.92574E+06 + 5.92400E+02 1.91819E+06 + 5.92500E+02 1.91120E+06 + 5.92600E+02 1.90478E+06 + 5.92700E+02 1.89893E+06 + 5.92800E+02 1.89365E+06 + 5.92900E+02 1.88896E+06 + 5.93000E+02 1.88484E+06 + 5.93100E+02 1.88130E+06 + 5.93200E+02 1.87836E+06 + 5.93300E+02 1.87600E+06 + 5.93400E+02 1.87422E+06 + 5.93500E+02 1.87304E+06 + 5.93600E+02 1.87245E+06 + 5.93700E+02 1.87245E+06 + 5.93800E+02 1.87304E+06 + 5.93900E+02 1.87422E+06 + 5.94000E+02 1.87600E+06 + 5.94100E+02 1.87836E+06 + 5.94200E+02 1.88131E+06 + 5.94300E+02 1.88484E+06 + 5.94400E+02 1.88896E+06 + 5.94500E+02 1.89366E+06 + 5.94600E+02 1.89894E+06 + 5.94700E+02 1.90479E+06 + 5.94800E+02 1.91121E+06 + 5.94900E+02 1.91820E+06 + 5.95000E+02 1.92575E+06 + 5.95100E+02 1.93386E+06 + 5.95200E+02 1.94252E+06 + 5.95300E+02 1.95173E+06 + 5.95400E+02 1.96148E+06 + 5.95500E+02 1.97177E+06 + 5.95600E+02 1.98258E+06 + 5.95700E+02 1.99391E+06 + 5.95800E+02 2.00577E+06 + 5.95900E+02 2.01812E+06 + 5.96000E+02 2.03098E+06 + 5.96100E+02 2.04432E+06 + 5.96200E+02 2.05815E+06 + 5.96300E+02 2.07246E+06 + 5.96400E+02 2.08722E+06 + 5.96500E+02 2.10246E+06 + 5.96600E+02 2.11812E+06 + 5.96700E+02 2.13422E+06 + 5.96800E+02 2.15076E+06 + 5.96900E+02 2.16771E+06 + 5.97000E+02 2.18506E+06 + 5.97100E+02 2.20281E+06 + 5.97200E+02 2.22093E+06 + 5.97300E+02 2.23943E+06 + 5.97400E+02 2.25829E+06 + 5.97500E+02 2.27751E+06 + 5.97600E+02 2.29704E+06 + 5.97700E+02 2.31690E+06 + 5.97800E+02 2.33709E+06 + 5.97900E+02 2.35755E+06 + 5.98000E+02 2.37832E+06 + 5.98100E+02 2.39935E+06 + 5.98200E+02 2.42064E+06 + 5.98300E+02 2.44217E+06 + 5.98400E+02 2.46394E+06 + 5.98500E+02 2.48593E+06 + 5.98600E+02 2.50810E+06 + 5.98700E+02 2.53048E+06 + 5.98800E+02 2.55304E+06 + 5.98900E+02 2.57574E+06 + 5.99000E+02 2.59862E+06 + 5.99100E+02 2.62161E+06 + 5.99200E+02 2.64472E+06 + 5.99300E+02 2.66793E+06 + 5.99400E+02 2.69124E+06 + 5.99500E+02 2.71463E+06 + 5.99600E+02 2.73805E+06 + 5.99700E+02 2.76153E+06 + 5.99800E+02 2.78505E+06 + 5.99900E+02 2.80856E+06 + 6.00000E+02 2.83210E+06 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.inp b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.inp new file mode 100644 index 000000000..68fe04c82 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.inp @@ -0,0 +1,40 @@ +! Ice flexural failure per IEC test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.10 +rampTime 1.0 +duration 600.0 +randomSeed 123 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +! +! Inputs common to loading by ice flexural failure +! +ice2twrFriction 0.15 +includeHb 1 +includeHr 1 +! +! Inputs for ice flexural failure via IEC method (Ralston) +! +iceType 7 +rideUpThickness 2.5 +freqParamK 5.0 +numLegs 1.0 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.log b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.log new file mode 100644 index 000000000..42bda84fb --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_flex_IEC.log @@ -0,0 +1,33 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:25:22 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 7 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting common flexural failure input parameters + flexStrength = 7.00000E+05 Pascals + towerConeAngle = 60 degrees + ice2twrFriction = 0.15 + iceDensity = 916.2 kg/m^3 + Breaking term, Hb term is included + Rubble pushing term, Hr term is included + + Setting up flexural failure by Ralston method + Use the IEC 61400-3 suggested equations for max static loads + Ride up thickness = 2.5 meters + Tower cone top diameter = 1.5 meters + Frequency parameter K = 5 +** Maximum static load for flexural failure = 3.74475E+06Newtons + + IEC/Ralston ice flexural failure loads initialized + diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.dat b/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.dat new file mode 100644 index 000000000..dded56c8d --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 2.77158E+04 + 2.00000E-01 5.76637E+04 + 3.00000E-01 8.98439E+04 + 4.00000E-01 1.24256E+05 + 5.00000E-01 1.60901E+05 + 6.00000E-01 1.99777E+05 + 7.00000E-01 2.40886E+05 + 8.00000E-01 2.84227E+05 + 9.00000E-01 3.29801E+05 + 1.00000E+00 3.77606E+05 + 1.10000E+00 3.88767E+05 + 1.20000E+00 3.99928E+05 + 1.30000E+00 4.11089E+05 + 1.40000E+00 4.22250E+05 + 1.50000E+00 4.33411E+05 + 1.60000E+00 4.44572E+05 + 1.70000E+00 4.55733E+05 + 1.80000E+00 4.66894E+05 + 1.90000E+00 4.78055E+05 + 2.00000E+00 4.89215E+05 + 2.10000E+00 5.00376E+05 + 2.20000E+00 5.11537E+05 + 2.30000E+00 5.22698E+05 + 2.40000E+00 5.33859E+05 + 2.50000E+00 5.45020E+05 + 2.60000E+00 5.56181E+05 + 2.70000E+00 5.67342E+05 + 2.80000E+00 5.78503E+05 + 2.90000E+00 5.89664E+05 + 3.00000E+00 6.00825E+05 + 3.10000E+00 6.11986E+05 + 3.20000E+00 6.23147E+05 + 3.30000E+00 6.34308E+05 + 3.40000E+00 6.45468E+05 + 3.50000E+00 6.56629E+05 + 3.60000E+00 6.67790E+05 + 3.70000E+00 6.78951E+05 + 3.80000E+00 6.90112E+05 + 3.90000E+00 7.01273E+05 + 4.00000E+00 7.12434E+05 + 4.10000E+00 7.23595E+05 + 4.20000E+00 7.34756E+05 + 4.30000E+00 7.45917E+05 + 4.40000E+00 7.57078E+05 + 4.50000E+00 7.68239E+05 + 4.60000E+00 7.79400E+05 + 4.70000E+00 7.90561E+05 + 4.80000E+00 8.01722E+05 + 4.90000E+00 8.12882E+05 + 5.00000E+00 8.24043E+05 + 5.10000E+00 8.35204E+05 + 5.20000E+00 8.46365E+05 + 5.30000E+00 8.57526E+05 + 5.40000E+00 8.68687E+05 + 5.50000E+00 8.79848E+05 + 5.60000E+00 8.91009E+05 + 5.70000E+00 9.02170E+05 + 5.80000E+00 9.13331E+05 + 5.90000E+00 9.24492E+05 + 6.00000E+00 9.35653E+05 + 6.10000E+00 9.46814E+05 + 6.20000E+00 9.57975E+05 + 6.30000E+00 9.69136E+05 + 6.40000E+00 9.80296E+05 + 6.50000E+00 9.91457E+05 + 6.60000E+00 1.00262E+06 + 6.70000E+00 1.01378E+06 + 6.80000E+00 1.02494E+06 + 6.90000E+00 1.03610E+06 + 7.00000E+00 1.04726E+06 + 7.10000E+00 1.05842E+06 + 7.20000E+00 1.06958E+06 + 7.30000E+00 1.08074E+06 + 7.40000E+00 1.09191E+06 + 7.50000E+00 1.04844E+06 + 7.60000E+00 1.00497E+06 + 7.70000E+00 9.61499E+05 + 7.80000E+00 9.18030E+05 + 7.90000E+00 8.74561E+05 + 8.00000E+00 8.31092E+05 + 8.10000E+00 7.87624E+05 + 8.20000E+00 7.44155E+05 + 8.30000E+00 7.00686E+05 + 8.40000E+00 6.57217E+05 + 8.50000E+00 6.13748E+05 + 8.60000E+00 5.70279E+05 + 8.70000E+00 5.26810E+05 + 8.80000E+00 4.83341E+05 + 8.90000E+00 4.39872E+05 + 9.00000E+00 3.96404E+05 + 9.10000E+00 3.52935E+05 + 9.20000E+00 3.09466E+05 + 9.30000E+00 2.65997E+05 + 9.40000E+00 2.65997E+05 + 9.50000E+00 2.65997E+05 + 9.60000E+00 2.65997E+05 + 9.70000E+00 2.65997E+05 + 9.80000E+00 2.65997E+05 + 9.90000E+00 2.65997E+05 + 1.00000E+01 2.65997E+05 + 1.01000E+01 2.65997E+05 + 1.02000E+01 2.65997E+05 + 1.03000E+01 2.65997E+05 + 1.04000E+01 2.65997E+05 + 1.05000E+01 2.65997E+05 + 1.06000E+01 2.65997E+05 + 1.07000E+01 2.65997E+05 + 1.08000E+01 2.65997E+05 + 1.09000E+01 2.65997E+05 + 1.10000E+01 2.65997E+05 + 1.11000E+01 2.65997E+05 + 1.12000E+01 2.65997E+05 + 1.13000E+01 2.65997E+05 + 1.14000E+01 2.65997E+05 + 1.15000E+01 2.65997E+05 + 1.16000E+01 2.65997E+05 + 1.17000E+01 2.65997E+05 + 1.18000E+01 2.65997E+05 + 1.19000E+01 2.65997E+05 + 1.20000E+01 2.65997E+05 + 1.21000E+01 2.65997E+05 + 1.22000E+01 2.65997E+05 + 1.23000E+01 2.65997E+05 + 1.24000E+01 2.65997E+05 + 1.25000E+01 2.65997E+05 + 1.26000E+01 2.65997E+05 + 1.27000E+01 2.65997E+05 + 1.28000E+01 2.65997E+05 + 1.29000E+01 2.65997E+05 + 1.30000E+01 2.65997E+05 + 1.31000E+01 2.65997E+05 + 1.32000E+01 2.65997E+05 + 1.33000E+01 2.65997E+05 + 1.34000E+01 2.65997E+05 + 1.35000E+01 2.65997E+05 + 1.36000E+01 2.65997E+05 + 1.37000E+01 2.65997E+05 + 1.38000E+01 2.65997E+05 + 1.39000E+01 2.65997E+05 + 1.40000E+01 2.65997E+05 + 1.41000E+01 2.65997E+05 + 1.42000E+01 2.65997E+05 + 1.43000E+01 2.65997E+05 + 1.44000E+01 2.65997E+05 + 1.45000E+01 2.65997E+05 + 1.46000E+01 2.65997E+05 + 1.47000E+01 2.65997E+05 + 1.48000E+01 2.65997E+05 + 1.49000E+01 2.65997E+05 + 1.50000E+01 2.65997E+05 + 1.51000E+01 2.65997E+05 + 1.52000E+01 2.65997E+05 + 1.53000E+01 2.65997E+05 + 1.54000E+01 2.65997E+05 + 1.55000E+01 2.65997E+05 + 1.56000E+01 2.84218E+05 + 1.57000E+01 3.02440E+05 + 1.58000E+01 3.20661E+05 + 1.59000E+01 3.38882E+05 + 1.60000E+01 3.57104E+05 + 1.61000E+01 3.75325E+05 + 1.62000E+01 3.93546E+05 + 1.63000E+01 4.11768E+05 + 1.64000E+01 4.29989E+05 + 1.65000E+01 4.48211E+05 + 1.66000E+01 4.66432E+05 + 1.67000E+01 4.84653E+05 + 1.68000E+01 5.02875E+05 + 1.69000E+01 5.21096E+05 + 1.70000E+01 5.39318E+05 + 1.71000E+01 5.57539E+05 + 1.72000E+01 5.75760E+05 + 1.73000E+01 5.93982E+05 + 1.74000E+01 6.12203E+05 + 1.75000E+01 6.30424E+05 + 1.76000E+01 6.48646E+05 + 1.77000E+01 6.66867E+05 + 1.78000E+01 6.85089E+05 + 1.79000E+01 7.03310E+05 + 1.80000E+01 7.21531E+05 + 1.81000E+01 7.39753E+05 + 1.82000E+01 7.57974E+05 + 1.83000E+01 7.76196E+05 + 1.84000E+01 7.94417E+05 + 1.85000E+01 8.12638E+05 + 1.86000E+01 8.30860E+05 + 1.87000E+01 8.49081E+05 + 1.88000E+01 8.67302E+05 + 1.89000E+01 8.85524E+05 + 1.90000E+01 9.03745E+05 + 1.91000E+01 9.21967E+05 + 1.92000E+01 9.40188E+05 + 1.93000E+01 9.58409E+05 + 1.94000E+01 9.76631E+05 + 1.95000E+01 9.94852E+05 + 1.96000E+01 1.01307E+06 + 1.97000E+01 1.03129E+06 + 1.98000E+01 1.04952E+06 + 1.99000E+01 1.06774E+06 + 2.00000E+01 1.08596E+06 + 2.01000E+01 1.10418E+06 + 2.02000E+01 1.12240E+06 + 2.03000E+01 1.14062E+06 + 2.04000E+01 1.15884E+06 + 2.05000E+01 1.17707E+06 + 2.06000E+01 1.19529E+06 + 2.07000E+01 1.21351E+06 + 2.08000E+01 1.23173E+06 + 2.09000E+01 1.24995E+06 + 2.10000E+01 1.26817E+06 + 2.11000E+01 1.28639E+06 + 2.12000E+01 1.30462E+06 + 2.13000E+01 1.32284E+06 + 2.14000E+01 1.34106E+06 + 2.15000E+01 1.35928E+06 + 2.16000E+01 1.37750E+06 + 2.17000E+01 1.39572E+06 + 2.18000E+01 1.41394E+06 + 2.19000E+01 1.43217E+06 + 2.20000E+01 1.45039E+06 + 2.21000E+01 1.46861E+06 + 2.22000E+01 1.48683E+06 + 2.23000E+01 1.50505E+06 + 2.24000E+01 1.52327E+06 + 2.25000E+01 1.54149E+06 + 2.26000E+01 1.55972E+06 + 2.27000E+01 1.57794E+06 + 2.28000E+01 1.59616E+06 + 2.29000E+01 1.61438E+06 + 2.30000E+01 1.63260E+06 + 2.31000E+01 1.65082E+06 + 2.32000E+01 1.66904E+06 + 2.33000E+01 1.68726E+06 + 2.34000E+01 1.70549E+06 + 2.35000E+01 1.72371E+06 + 2.36000E+01 1.74193E+06 + 2.37000E+01 1.76015E+06 + 2.38000E+01 1.77837E+06 + 2.39000E+01 1.79659E+06 + 2.40000E+01 1.81481E+06 + 2.41000E+01 1.83304E+06 + 2.42000E+01 1.85126E+06 + 2.43000E+01 1.86948E+06 + 2.44000E+01 1.79659E+06 + 2.45000E+01 1.72371E+06 + 2.46000E+01 1.65082E+06 + 2.47000E+01 1.57794E+06 + 2.48000E+01 1.50505E+06 + 2.49000E+01 1.43217E+06 + 2.50000E+01 1.35928E+06 + 2.51000E+01 1.28639E+06 + 2.52000E+01 1.21351E+06 + 2.53000E+01 1.14062E+06 + 2.54000E+01 1.06774E+06 + 2.55000E+01 9.94852E+05 + 2.56000E+01 9.21967E+05 + 2.57000E+01 8.49081E+05 + 2.58000E+01 7.76196E+05 + 2.59000E+01 7.03310E+05 + 2.60000E+01 6.30424E+05 + 2.61000E+01 5.57539E+05 + 2.62000E+01 4.84654E+05 + 2.63000E+01 4.11768E+05 + 2.64000E+01 3.38882E+05 + 2.65000E+01 2.65997E+05 + 2.66000E+01 2.65997E+05 + 2.67000E+01 2.65997E+05 + 2.68000E+01 2.65997E+05 + 2.69000E+01 2.65997E+05 + 2.70000E+01 2.65997E+05 + 2.71000E+01 2.65997E+05 + 2.72000E+01 2.65997E+05 + 2.73000E+01 2.65997E+05 + 2.74000E+01 2.65997E+05 + 2.75000E+01 2.65997E+05 + 2.76000E+01 2.65997E+05 + 2.77000E+01 2.65997E+05 + 2.78000E+01 2.65997E+05 + 2.79000E+01 2.65997E+05 + 2.80000E+01 2.65997E+05 + 2.81000E+01 2.65997E+05 + 2.82000E+01 2.65997E+05 + 2.83000E+01 2.65997E+05 + 2.84000E+01 2.65997E+05 + 2.85000E+01 2.65997E+05 + 2.86000E+01 2.65997E+05 + 2.87000E+01 2.65997E+05 + 2.88000E+01 2.65997E+05 + 2.89000E+01 2.65997E+05 + 2.90000E+01 2.65997E+05 + 2.91000E+01 2.65997E+05 + 2.92000E+01 2.65997E+05 + 2.93000E+01 2.65997E+05 + 2.94000E+01 2.65997E+05 + 2.95000E+01 2.65997E+05 + 2.96000E+01 2.65997E+05 + 2.97000E+01 2.65997E+05 + 2.98000E+01 2.65997E+05 + 2.99000E+01 2.65997E+05 + 3.00000E+01 2.65997E+05 + 3.01000E+01 2.65997E+05 + 3.02000E+01 2.65997E+05 + 3.03000E+01 2.65997E+05 + 3.04000E+01 2.65997E+05 + 3.05000E+01 2.65997E+05 + 3.06000E+01 2.65997E+05 + 3.07000E+01 2.65997E+05 + 3.08000E+01 2.65997E+05 + 3.09000E+01 2.65997E+05 + 3.10000E+01 2.65997E+05 + 3.11000E+01 2.65997E+05 + 3.12000E+01 2.65997E+05 + 3.13000E+01 2.65997E+05 + 3.14000E+01 2.65997E+05 + 3.15000E+01 2.65997E+05 + 3.16000E+01 2.65997E+05 + 3.17000E+01 2.65997E+05 + 3.18000E+01 2.65997E+05 + 3.19000E+01 2.65997E+05 + 3.20000E+01 2.65997E+05 + 3.21000E+01 2.65997E+05 + 3.22000E+01 2.65997E+05 + 3.23000E+01 2.65997E+05 + 3.24000E+01 2.65997E+05 + 3.25000E+01 2.65997E+05 + 3.26000E+01 2.65997E+05 + 3.27000E+01 2.65997E+05 + 3.28000E+01 2.65997E+05 + 3.29000E+01 2.65997E+05 + 3.30000E+01 2.65997E+05 + 3.31000E+01 2.65997E+05 + 3.32000E+01 2.65997E+05 + 3.33000E+01 2.65997E+05 + 3.34000E+01 2.65997E+05 + 3.35000E+01 2.65997E+05 + 3.36000E+01 2.65997E+05 + 3.37000E+01 2.65997E+05 + 3.38000E+01 2.65997E+05 + 3.39000E+01 2.89680E+05 + 3.40000E+01 3.13363E+05 + 3.41000E+01 3.37046E+05 + 3.42000E+01 3.60729E+05 + 3.43000E+01 3.84412E+05 + 3.44000E+01 4.08095E+05 + 3.45000E+01 4.31778E+05 + 3.46000E+01 4.55461E+05 + 3.47000E+01 4.79144E+05 + 3.48000E+01 5.02827E+05 + 3.49000E+01 5.26510E+05 + 3.50000E+01 5.50192E+05 + 3.51000E+01 5.73876E+05 + 3.52000E+01 5.97558E+05 + 3.53000E+01 6.21241E+05 + 3.54000E+01 6.44924E+05 + 3.55000E+01 6.68607E+05 + 3.56000E+01 6.92290E+05 + 3.57000E+01 7.15973E+05 + 3.58000E+01 7.39656E+05 + 3.59000E+01 7.63339E+05 + 3.60000E+01 7.87022E+05 + 3.61000E+01 8.10705E+05 + 3.62000E+01 8.34388E+05 + 3.63000E+01 8.58071E+05 + 3.64000E+01 8.81754E+05 + 3.65000E+01 9.05437E+05 + 3.66000E+01 9.29120E+05 + 3.67000E+01 9.52803E+05 + 3.68000E+01 9.76486E+05 + 3.69000E+01 1.00017E+06 + 3.70000E+01 1.02385E+06 + 3.71000E+01 1.04753E+06 + 3.72000E+01 1.07122E+06 + 3.73000E+01 1.09490E+06 + 3.74000E+01 1.11858E+06 + 3.75000E+01 1.14227E+06 + 3.76000E+01 1.16595E+06 + 3.77000E+01 1.18963E+06 + 3.78000E+01 1.21332E+06 + 3.79000E+01 1.23700E+06 + 3.80000E+01 1.26068E+06 + 3.81000E+01 1.28436E+06 + 3.82000E+01 1.30805E+06 + 3.83000E+01 1.33173E+06 + 3.84000E+01 1.35541E+06 + 3.85000E+01 1.37910E+06 + 3.86000E+01 1.40278E+06 + 3.87000E+01 1.42646E+06 + 3.88000E+01 1.45015E+06 + 3.89000E+01 1.47383E+06 + 3.90000E+01 1.49751E+06 + 3.91000E+01 1.52119E+06 + 3.92000E+01 1.54488E+06 + 3.93000E+01 1.56856E+06 + 3.94000E+01 1.59224E+06 + 3.95000E+01 1.61593E+06 + 3.96000E+01 1.63961E+06 + 3.97000E+01 1.66329E+06 + 3.98000E+01 1.68698E+06 + 3.99000E+01 1.71066E+06 + 4.00000E+01 1.73434E+06 + 4.01000E+01 1.75802E+06 + 4.02000E+01 1.78171E+06 + 4.03000E+01 1.80539E+06 + 4.04000E+01 1.82907E+06 + 4.05000E+01 1.85276E+06 + 4.06000E+01 1.87644E+06 + 4.07000E+01 1.90012E+06 + 4.08000E+01 1.92380E+06 + 4.09000E+01 1.94749E+06 + 4.10000E+01 1.85407E+06 + 4.11000E+01 1.76066E+06 + 4.12000E+01 1.66724E+06 + 4.13000E+01 1.57382E+06 + 4.14000E+01 1.48041E+06 + 4.15000E+01 1.38699E+06 + 4.16000E+01 1.29357E+06 + 4.17000E+01 1.20016E+06 + 4.18000E+01 1.10674E+06 + 4.19000E+01 1.01333E+06 + 4.20000E+01 9.19910E+05 + 4.21000E+01 8.26494E+05 + 4.22000E+01 7.33078E+05 + 4.23000E+01 6.39662E+05 + 4.24000E+01 5.46245E+05 + 4.25000E+01 4.52829E+05 + 4.26000E+01 3.59413E+05 + 4.27000E+01 2.65997E+05 + 4.28000E+01 2.65997E+05 + 4.29000E+01 2.65997E+05 + 4.30000E+01 2.65997E+05 + 4.31000E+01 2.65997E+05 + 4.32000E+01 2.65997E+05 + 4.33000E+01 2.65997E+05 + 4.34000E+01 2.65997E+05 + 4.35000E+01 2.65997E+05 + 4.36000E+01 2.65997E+05 + 4.37000E+01 2.65997E+05 + 4.38000E+01 2.65997E+05 + 4.39000E+01 2.65997E+05 + 4.40000E+01 2.65997E+05 + 4.41000E+01 2.65997E+05 + 4.42000E+01 2.65997E+05 + 4.43000E+01 2.65997E+05 + 4.44000E+01 2.65997E+05 + 4.45000E+01 2.65997E+05 + 4.46000E+01 2.65997E+05 + 4.47000E+01 2.65997E+05 + 4.48000E+01 2.65997E+05 + 4.49000E+01 2.65997E+05 + 4.50000E+01 2.65997E+05 + 4.51000E+01 2.65997E+05 + 4.52000E+01 2.65997E+05 + 4.53000E+01 2.65997E+05 + 4.54000E+01 2.65997E+05 + 4.55000E+01 2.65997E+05 + 4.56000E+01 2.65997E+05 + 4.57000E+01 2.65997E+05 + 4.58000E+01 2.65997E+05 + 4.59000E+01 2.65997E+05 + 4.60000E+01 2.65997E+05 + 4.61000E+01 2.65997E+05 + 4.62000E+01 2.65997E+05 + 4.63000E+01 2.65997E+05 + 4.64000E+01 2.65997E+05 + 4.65000E+01 2.65997E+05 + 4.66000E+01 2.65997E+05 + 4.67000E+01 2.65997E+05 + 4.68000E+01 2.65997E+05 + 4.69000E+01 2.65997E+05 + 4.70000E+01 2.65997E+05 + 4.71000E+01 2.65997E+05 + 4.72000E+01 2.65997E+05 + 4.73000E+01 2.65997E+05 + 4.74000E+01 2.65997E+05 + 4.75000E+01 2.65997E+05 + 4.76000E+01 2.65997E+05 + 4.77000E+01 2.65997E+05 + 4.78000E+01 2.65997E+05 + 4.79000E+01 2.65997E+05 + 4.80000E+01 2.65997E+05 + 4.81000E+01 2.65997E+05 + 4.82000E+01 2.65997E+05 + 4.83000E+01 2.65997E+05 + 4.84000E+01 2.65997E+05 + 4.85000E+01 2.65997E+05 + 4.86000E+01 2.65997E+05 + 4.87000E+01 2.65997E+05 + 4.88000E+01 2.78276E+05 + 4.89000E+01 2.90555E+05 + 4.90000E+01 3.02834E+05 + 4.91000E+01 3.15113E+05 + 4.92000E+01 3.27392E+05 + 4.93000E+01 3.39671E+05 + 4.94000E+01 3.51950E+05 + 4.95000E+01 3.64229E+05 + 4.96000E+01 3.76508E+05 + 4.97000E+01 3.88786E+05 + 4.98000E+01 4.01065E+05 + 4.99000E+01 4.13344E+05 + 5.00000E+01 4.25623E+05 + 5.01000E+01 4.37902E+05 + 5.02000E+01 4.50181E+05 + 5.03000E+01 4.62460E+05 + 5.04000E+01 4.74739E+05 + 5.05000E+01 4.87018E+05 + 5.06000E+01 4.99297E+05 + 5.07000E+01 5.11576E+05 + 5.08000E+01 5.23855E+05 + 5.09000E+01 5.36134E+05 + 5.10000E+01 5.48413E+05 + 5.11000E+01 5.60692E+05 + 5.12000E+01 5.72971E+05 + 5.13000E+01 5.85250E+05 + 5.14000E+01 5.97529E+05 + 5.15000E+01 6.09808E+05 + 5.16000E+01 6.22087E+05 + 5.17000E+01 6.34366E+05 + 5.18000E+01 6.46645E+05 + 5.19000E+01 6.58924E+05 + 5.20000E+01 6.71203E+05 + 5.21000E+01 6.83482E+05 + 5.22000E+01 6.95760E+05 + 5.23000E+01 7.08040E+05 + 5.24000E+01 7.20318E+05 + 5.25000E+01 7.32597E+05 + 5.26000E+01 7.44876E+05 + 5.27000E+01 7.57155E+05 + 5.28000E+01 7.69434E+05 + 5.29000E+01 7.81713E+05 + 5.30000E+01 7.93992E+05 + 5.31000E+01 8.06271E+05 + 5.32000E+01 8.18550E+05 + 5.33000E+01 8.30829E+05 + 5.34000E+01 8.43108E+05 + 5.35000E+01 8.55387E+05 + 5.36000E+01 8.67666E+05 + 5.37000E+01 8.79945E+05 + 5.38000E+01 8.92224E+05 + 5.39000E+01 9.04503E+05 + 5.40000E+01 9.16782E+05 + 5.41000E+01 9.29061E+05 + 5.42000E+01 9.41340E+05 + 5.43000E+01 9.53619E+05 + 5.44000E+01 9.65898E+05 + 5.45000E+01 9.78177E+05 + 5.46000E+01 9.90456E+05 + 5.47000E+01 1.00273E+06 + 5.48000E+01 1.01501E+06 + 5.49000E+01 1.02729E+06 + 5.50000E+01 1.03957E+06 + 5.51000E+01 1.05185E+06 + 5.52000E+01 1.06413E+06 + 5.53000E+01 1.07641E+06 + 5.54000E+01 1.08869E+06 + 5.55000E+01 1.10097E+06 + 5.56000E+01 1.11325E+06 + 5.57000E+01 1.12552E+06 + 5.58000E+01 1.13780E+06 + 5.59000E+01 1.15008E+06 + 5.60000E+01 1.16236E+06 + 5.61000E+01 1.17464E+06 + 5.62000E+01 1.18692E+06 + 5.63000E+01 1.19920E+06 + 5.64000E+01 1.21148E+06 + 5.65000E+01 1.22376E+06 + 5.66000E+01 1.23603E+06 + 5.67000E+01 1.24831E+06 + 5.68000E+01 1.26059E+06 + 5.69000E+01 1.27287E+06 + 5.70000E+01 1.28515E+06 + 5.71000E+01 1.29743E+06 + 5.72000E+01 1.30971E+06 + 5.73000E+01 1.32199E+06 + 5.74000E+01 1.33427E+06 + 5.75000E+01 1.34655E+06 + 5.76000E+01 1.35882E+06 + 5.77000E+01 1.37110E+06 + 5.78000E+01 1.38338E+06 + 5.79000E+01 1.39566E+06 + 5.80000E+01 1.40794E+06 + 5.81000E+01 1.42022E+06 + 5.82000E+01 1.43250E+06 + 5.83000E+01 1.44478E+06 + 5.84000E+01 1.45706E+06 + 5.85000E+01 1.46934E+06 + 5.86000E+01 1.48161E+06 + 5.87000E+01 1.49389E+06 + 5.88000E+01 1.50617E+06 + 5.89000E+01 1.51845E+06 + 5.90000E+01 1.53073E+06 + 5.91000E+01 1.54301E+06 + 5.92000E+01 1.55529E+06 + 5.93000E+01 1.56757E+06 + 5.94000E+01 1.57985E+06 + 5.95000E+01 1.59212E+06 + 5.96000E+01 1.60440E+06 + 5.97000E+01 1.61668E+06 + 5.98000E+01 1.62896E+06 + 5.99000E+01 1.64124E+06 + 6.00000E+01 1.65352E+06 + 6.01000E+01 1.66580E+06 + 6.02000E+01 1.67808E+06 + 6.03000E+01 1.69036E+06 + 6.04000E+01 1.70264E+06 + 6.05000E+01 1.71491E+06 + 6.06000E+01 1.72719E+06 + 6.07000E+01 1.73947E+06 + 6.08000E+01 1.75175E+06 + 6.09000E+01 1.76403E+06 + 6.10000E+01 1.77631E+06 + 6.11000E+01 1.78859E+06 + 6.12000E+01 1.80087E+06 + 6.13000E+01 1.81315E+06 + 6.14000E+01 1.82542E+06 + 6.15000E+01 1.83770E+06 + 6.16000E+01 1.84998E+06 + 6.17000E+01 1.86226E+06 + 6.18000E+01 1.87454E+06 + 6.19000E+01 1.82580E+06 + 6.20000E+01 1.77705E+06 + 6.21000E+01 1.72831E+06 + 6.22000E+01 1.67957E+06 + 6.23000E+01 1.63082E+06 + 6.24000E+01 1.58208E+06 + 6.25000E+01 1.53333E+06 + 6.26000E+01 1.48459E+06 + 6.27000E+01 1.43585E+06 + 6.28000E+01 1.38710E+06 + 6.29000E+01 1.33836E+06 + 6.30000E+01 1.28962E+06 + 6.31000E+01 1.24087E+06 + 6.32000E+01 1.19213E+06 + 6.33000E+01 1.14338E+06 + 6.34000E+01 1.09464E+06 + 6.35000E+01 1.04590E+06 + 6.36000E+01 9.97153E+05 + 6.37000E+01 9.48410E+05 + 6.38000E+01 8.99666E+05 + 6.39000E+01 8.50922E+05 + 6.40000E+01 8.02178E+05 + 6.41000E+01 7.53434E+05 + 6.42000E+01 7.04691E+05 + 6.43000E+01 6.55947E+05 + 6.44000E+01 6.07203E+05 + 6.45000E+01 5.58459E+05 + 6.46000E+01 5.09716E+05 + 6.47000E+01 4.60972E+05 + 6.48000E+01 4.12228E+05 + 6.49000E+01 3.63484E+05 + 6.50000E+01 3.14741E+05 + 6.51000E+01 2.65997E+05 + 6.52000E+01 2.65997E+05 + 6.53000E+01 2.65997E+05 + 6.54000E+01 2.65997E+05 + 6.55000E+01 2.65997E+05 + 6.56000E+01 2.65997E+05 + 6.57000E+01 2.65997E+05 + 6.58000E+01 2.65997E+05 + 6.59000E+01 2.65997E+05 + 6.60000E+01 2.65997E+05 + 6.61000E+01 2.65997E+05 + 6.62000E+01 2.65997E+05 + 6.63000E+01 2.65997E+05 + 6.64000E+01 2.65997E+05 + 6.65000E+01 2.65997E+05 + 6.66000E+01 2.65997E+05 + 6.67000E+01 2.65997E+05 + 6.68000E+01 2.65997E+05 + 6.69000E+01 2.65997E+05 + 6.70000E+01 2.65997E+05 + 6.71000E+01 2.65997E+05 + 6.72000E+01 2.65997E+05 + 6.73000E+01 2.65997E+05 + 6.74000E+01 2.65997E+05 + 6.75000E+01 2.65997E+05 + 6.76000E+01 2.65997E+05 + 6.77000E+01 2.65997E+05 + 6.78000E+01 2.65997E+05 + 6.79000E+01 2.65997E+05 + 6.80000E+01 2.65997E+05 + 6.81000E+01 2.65997E+05 + 6.82000E+01 2.65997E+05 + 6.83000E+01 2.65997E+05 + 6.84000E+01 2.65997E+05 + 6.85000E+01 2.65997E+05 + 6.86000E+01 2.65997E+05 + 6.87000E+01 2.65997E+05 + 6.88000E+01 2.65997E+05 + 6.89000E+01 2.65997E+05 + 6.90000E+01 2.65997E+05 + 6.91000E+01 2.65997E+05 + 6.92000E+01 2.65997E+05 + 6.93000E+01 2.65997E+05 + 6.94000E+01 2.65997E+05 + 6.95000E+01 2.65997E+05 + 6.96000E+01 2.65997E+05 + 6.97000E+01 2.65997E+05 + 6.98000E+01 2.65997E+05 + 6.99000E+01 2.65997E+05 + 7.00000E+01 2.65997E+05 + 7.01000E+01 2.65997E+05 + 7.02000E+01 2.65997E+05 + 7.03000E+01 2.65997E+05 + 7.04000E+01 2.65997E+05 + 7.05000E+01 2.65997E+05 + 7.06000E+01 2.65997E+05 + 7.07000E+01 2.65997E+05 + 7.08000E+01 2.65997E+05 + 7.09000E+01 2.65997E+05 + 7.10000E+01 2.65997E+05 + 7.11000E+01 2.65997E+05 + 7.12000E+01 2.65997E+05 + 7.13000E+01 2.65997E+05 + 7.14000E+01 2.65997E+05 + 7.15000E+01 2.65997E+05 + 7.16000E+01 2.65997E+05 + 7.17000E+01 2.65997E+05 + 7.18000E+01 2.65997E+05 + 7.19000E+01 2.65997E+05 + 7.20000E+01 2.65997E+05 + 7.21000E+01 2.65997E+05 + 7.22000E+01 2.65997E+05 + 7.23000E+01 2.65997E+05 + 7.24000E+01 2.65997E+05 + 7.25000E+01 2.65997E+05 + 7.26000E+01 2.65997E+05 + 7.27000E+01 2.65997E+05 + 7.28000E+01 2.65997E+05 + 7.29000E+01 2.65997E+05 + 7.30000E+01 2.65997E+05 + 7.31000E+01 2.65997E+05 + 7.32000E+01 2.65997E+05 + 7.33000E+01 2.65997E+05 + 7.34000E+01 2.65997E+05 + 7.35000E+01 2.65997E+05 + 7.36000E+01 2.65997E+05 + 7.37000E+01 2.65997E+05 + 7.38000E+01 2.65997E+05 + 7.39000E+01 2.65997E+05 + 7.40000E+01 2.65997E+05 + 7.41000E+01 2.65997E+05 + 7.42000E+01 2.65997E+05 + 7.43000E+01 2.65997E+05 + 7.44000E+01 2.65997E+05 + 7.45000E+01 2.65997E+05 + 7.46000E+01 2.65997E+05 + 7.47000E+01 2.65997E+05 + 7.48000E+01 2.65997E+05 + 7.49000E+01 2.65997E+05 + 7.50000E+01 2.65997E+05 + 7.51000E+01 2.65997E+05 + 7.52000E+01 2.65997E+05 + 7.53000E+01 2.65997E+05 + 7.54000E+01 2.65997E+05 + 7.55000E+01 2.65997E+05 + 7.56000E+01 2.65997E+05 + 7.57000E+01 2.65997E+05 + 7.58000E+01 2.65997E+05 + 7.59000E+01 2.65997E+05 + 7.60000E+01 2.65997E+05 + 7.61000E+01 2.88192E+05 + 7.62000E+01 3.10386E+05 + 7.63000E+01 3.32581E+05 + 7.64000E+01 3.54776E+05 + 7.65000E+01 3.76970E+05 + 7.66000E+01 3.99165E+05 + 7.67000E+01 4.21360E+05 + 7.68000E+01 4.43555E+05 + 7.69000E+01 4.65749E+05 + 7.70000E+01 4.87944E+05 + 7.71000E+01 5.10139E+05 + 7.72000E+01 5.32334E+05 + 7.73000E+01 5.54528E+05 + 7.74000E+01 5.76723E+05 + 7.75000E+01 5.98918E+05 + 7.76000E+01 6.21113E+05 + 7.77000E+01 6.43307E+05 + 7.78000E+01 6.65502E+05 + 7.79000E+01 6.87697E+05 + 7.80000E+01 7.09892E+05 + 7.81000E+01 7.32086E+05 + 7.82000E+01 7.54281E+05 + 7.83000E+01 7.76476E+05 + 7.84000E+01 7.98670E+05 + 7.85000E+01 8.20865E+05 + 7.86000E+01 8.43060E+05 + 7.87000E+01 8.65255E+05 + 7.88000E+01 8.87449E+05 + 7.89000E+01 9.09644E+05 + 7.90000E+01 9.31839E+05 + 7.91000E+01 9.54034E+05 + 7.92000E+01 9.76228E+05 + 7.93000E+01 9.98423E+05 + 7.94000E+01 1.02062E+06 + 7.95000E+01 1.04281E+06 + 7.96000E+01 1.06501E+06 + 7.97000E+01 1.08720E+06 + 7.98000E+01 1.10940E+06 + 7.99000E+01 1.13159E+06 + 8.00000E+01 1.15379E+06 + 8.01000E+01 1.17598E+06 + 8.02000E+01 1.19818E+06 + 8.03000E+01 1.22037E+06 + 8.04000E+01 1.24257E+06 + 8.05000E+01 1.26476E+06 + 8.06000E+01 1.28695E+06 + 8.07000E+01 1.30915E+06 + 8.08000E+01 1.33134E+06 + 8.09000E+01 1.35354E+06 + 8.10000E+01 1.37573E+06 + 8.11000E+01 1.39793E+06 + 8.12000E+01 1.42012E+06 + 8.13000E+01 1.44232E+06 + 8.14000E+01 1.46451E+06 + 8.15000E+01 1.48671E+06 + 8.16000E+01 1.50890E+06 + 8.17000E+01 1.53110E+06 + 8.18000E+01 1.55329E+06 + 8.19000E+01 1.57549E+06 + 8.20000E+01 1.59768E+06 + 8.21000E+01 1.61988E+06 + 8.22000E+01 1.64207E+06 + 8.23000E+01 1.66427E+06 + 8.24000E+01 1.68646E+06 + 8.25000E+01 1.70865E+06 + 8.26000E+01 1.73085E+06 + 8.27000E+01 1.75304E+06 + 8.28000E+01 1.77524E+06 + 8.29000E+01 1.68646E+06 + 8.30000E+01 1.59768E+06 + 8.31000E+01 1.50890E+06 + 8.32000E+01 1.42012E+06 + 8.33000E+01 1.33134E+06 + 8.34000E+01 1.24257E+06 + 8.35000E+01 1.15379E+06 + 8.36000E+01 1.06501E+06 + 8.37000E+01 9.76228E+05 + 8.38000E+01 8.87449E+05 + 8.39000E+01 7.98670E+05 + 8.40000E+01 7.09892E+05 + 8.41000E+01 6.21113E+05 + 8.42000E+01 5.32334E+05 + 8.43000E+01 4.43555E+05 + 8.44000E+01 3.54776E+05 + 8.45000E+01 2.65997E+05 + 8.46000E+01 2.65997E+05 + 8.47000E+01 2.65997E+05 + 8.48000E+01 2.65997E+05 + 8.49000E+01 2.65997E+05 + 8.50000E+01 2.65997E+05 + 8.51000E+01 2.65997E+05 + 8.52000E+01 2.65997E+05 + 8.53000E+01 2.65997E+05 + 8.54000E+01 2.65997E+05 + 8.55000E+01 2.65997E+05 + 8.56000E+01 2.65997E+05 + 8.57000E+01 2.65997E+05 + 8.58000E+01 2.65997E+05 + 8.59000E+01 2.65997E+05 + 8.60000E+01 2.65997E+05 + 8.61000E+01 2.65997E+05 + 8.62000E+01 2.65997E+05 + 8.63000E+01 2.65997E+05 + 8.64000E+01 2.65997E+05 + 8.65000E+01 2.65997E+05 + 8.66000E+01 2.65997E+05 + 8.67000E+01 2.65997E+05 + 8.68000E+01 2.65997E+05 + 8.69000E+01 2.65997E+05 + 8.70000E+01 2.65997E+05 + 8.71000E+01 2.65997E+05 + 8.72000E+01 2.65997E+05 + 8.73000E+01 2.65997E+05 + 8.74000E+01 2.65997E+05 + 8.75000E+01 2.65997E+05 + 8.76000E+01 2.65997E+05 + 8.77000E+01 2.65997E+05 + 8.78000E+01 2.65997E+05 + 8.79000E+01 2.65997E+05 + 8.80000E+01 2.65997E+05 + 8.81000E+01 2.65997E+05 + 8.82000E+01 2.65997E+05 + 8.83000E+01 2.65997E+05 + 8.84000E+01 2.65997E+05 + 8.85000E+01 2.65997E+05 + 8.86000E+01 2.65997E+05 + 8.87000E+01 2.65997E+05 + 8.88000E+01 2.65997E+05 + 8.89000E+01 2.65997E+05 + 8.90000E+01 2.65997E+05 + 8.91000E+01 2.65997E+05 + 8.92000E+01 2.65997E+05 + 8.93000E+01 2.65997E+05 + 8.94000E+01 2.65997E+05 + 8.95000E+01 2.65997E+05 + 8.96000E+01 2.65997E+05 + 8.97000E+01 2.65997E+05 + 8.98000E+01 2.65997E+05 + 8.99000E+01 2.65997E+05 + 9.00000E+01 2.65997E+05 + 9.01000E+01 2.65997E+05 + 9.02000E+01 2.79544E+05 + 9.03000E+01 2.93092E+05 + 9.04000E+01 3.06640E+05 + 9.05000E+01 3.20187E+05 + 9.06000E+01 3.33735E+05 + 9.07000E+01 3.47283E+05 + 9.08000E+01 3.60830E+05 + 9.09000E+01 3.74378E+05 + 9.10000E+01 3.87926E+05 + 9.11000E+01 4.01473E+05 + 9.12000E+01 4.15021E+05 + 9.13000E+01 4.28569E+05 + 9.14000E+01 4.42116E+05 + 9.15000E+01 4.55664E+05 + 9.16000E+01 4.69212E+05 + 9.17000E+01 4.82759E+05 + 9.18000E+01 4.96307E+05 + 9.19000E+01 5.09854E+05 + 9.20000E+01 5.23402E+05 + 9.21000E+01 5.36950E+05 + 9.22000E+01 5.50497E+05 + 9.23000E+01 5.64045E+05 + 9.24000E+01 5.77593E+05 + 9.25000E+01 5.91140E+05 + 9.26000E+01 6.04688E+05 + 9.27000E+01 6.18236E+05 + 9.28000E+01 6.31783E+05 + 9.29000E+01 6.45331E+05 + 9.30000E+01 6.58878E+05 + 9.31000E+01 6.72426E+05 + 9.32000E+01 6.85974E+05 + 9.33000E+01 6.99521E+05 + 9.34000E+01 7.13069E+05 + 9.35000E+01 7.26617E+05 + 9.36000E+01 7.40164E+05 + 9.37000E+01 7.53712E+05 + 9.38000E+01 7.67260E+05 + 9.39000E+01 7.80807E+05 + 9.40000E+01 7.94355E+05 + 9.41000E+01 8.07902E+05 + 9.42000E+01 8.21450E+05 + 9.43000E+01 8.34998E+05 + 9.44000E+01 8.48546E+05 + 9.45000E+01 8.62093E+05 + 9.46000E+01 8.75641E+05 + 9.47000E+01 8.89188E+05 + 9.48000E+01 9.02736E+05 + 9.49000E+01 9.16284E+05 + 9.50000E+01 9.29831E+05 + 9.51000E+01 9.43379E+05 + 9.52000E+01 9.56927E+05 + 9.53000E+01 9.70474E+05 + 9.54000E+01 9.84022E+05 + 9.55000E+01 9.97570E+05 + 9.56000E+01 1.01112E+06 + 9.57000E+01 1.02466E+06 + 9.58000E+01 1.03821E+06 + 9.59000E+01 1.05176E+06 + 9.60000E+01 1.06531E+06 + 9.61000E+01 1.07886E+06 + 9.62000E+01 1.09240E+06 + 9.63000E+01 1.10595E+06 + 9.64000E+01 1.11950E+06 + 9.65000E+01 1.13305E+06 + 9.66000E+01 1.14659E+06 + 9.67000E+01 1.16014E+06 + 9.68000E+01 1.17369E+06 + 9.69000E+01 1.18724E+06 + 9.70000E+01 1.20078E+06 + 9.71000E+01 1.21433E+06 + 9.72000E+01 1.22788E+06 + 9.73000E+01 1.24143E+06 + 9.74000E+01 1.25497E+06 + 9.75000E+01 1.26852E+06 + 9.76000E+01 1.28207E+06 + 9.77000E+01 1.29562E+06 + 9.78000E+01 1.30917E+06 + 9.79000E+01 1.32271E+06 + 9.80000E+01 1.33626E+06 + 9.81000E+01 1.34981E+06 + 9.82000E+01 1.36336E+06 + 9.83000E+01 1.37690E+06 + 9.84000E+01 1.39045E+06 + 9.85000E+01 1.40400E+06 + 9.86000E+01 1.41755E+06 + 9.87000E+01 1.43109E+06 + 9.88000E+01 1.44464E+06 + 9.89000E+01 1.45819E+06 + 9.90000E+01 1.47174E+06 + 9.91000E+01 1.48528E+06 + 9.92000E+01 1.49883E+06 + 9.93000E+01 1.51238E+06 + 9.94000E+01 1.52593E+06 + 9.95000E+01 1.53948E+06 + 9.96000E+01 1.55302E+06 + 9.97000E+01 1.56657E+06 + 9.98000E+01 1.58012E+06 + 9.99000E+01 1.59367E+06 + 1.00000E+02 1.60721E+06 + 1.00100E+02 1.62076E+06 + 1.00200E+02 1.63431E+06 + 1.00300E+02 1.64786E+06 + 1.00400E+02 1.66140E+06 + 1.00500E+02 1.60773E+06 + 1.00600E+02 1.55407E+06 + 1.00700E+02 1.50040E+06 + 1.00800E+02 1.44673E+06 + 1.00900E+02 1.39306E+06 + 1.01000E+02 1.33939E+06 + 1.01100E+02 1.28572E+06 + 1.01200E+02 1.23205E+06 + 1.01300E+02 1.17838E+06 + 1.01400E+02 1.12471E+06 + 1.01500E+02 1.07104E+06 + 1.01600E+02 1.01737E+06 + 1.01700E+02 9.63700E+05 + 1.01800E+02 9.10031E+05 + 1.01900E+02 8.56362E+05 + 1.02000E+02 8.02692E+05 + 1.02100E+02 7.49022E+05 + 1.02200E+02 6.95353E+05 + 1.02300E+02 6.41683E+05 + 1.02400E+02 5.88014E+05 + 1.02500E+02 5.34344E+05 + 1.02600E+02 4.80675E+05 + 1.02700E+02 4.27005E+05 + 1.02800E+02 3.73336E+05 + 1.02900E+02 3.19666E+05 + 1.03000E+02 2.65997E+05 + 1.03100E+02 2.65997E+05 + 1.03200E+02 2.65997E+05 + 1.03300E+02 2.65997E+05 + 1.03400E+02 2.65997E+05 + 1.03500E+02 2.65997E+05 + 1.03600E+02 2.65997E+05 + 1.03700E+02 2.65997E+05 + 1.03800E+02 2.65997E+05 + 1.03900E+02 2.65997E+05 + 1.04000E+02 2.65997E+05 + 1.04100E+02 2.65997E+05 + 1.04200E+02 2.65997E+05 + 1.04300E+02 2.65997E+05 + 1.04400E+02 2.65997E+05 + 1.04500E+02 2.65997E+05 + 1.04600E+02 2.65997E+05 + 1.04700E+02 2.65997E+05 + 1.04800E+02 2.65997E+05 + 1.04900E+02 2.65997E+05 + 1.05000E+02 2.65997E+05 + 1.05100E+02 2.65997E+05 + 1.05200E+02 2.65997E+05 + 1.05300E+02 2.65997E+05 + 1.05400E+02 2.65997E+05 + 1.05500E+02 2.65997E+05 + 1.05600E+02 2.65997E+05 + 1.05700E+02 2.65997E+05 + 1.05800E+02 2.65997E+05 + 1.05900E+02 2.65997E+05 + 1.06000E+02 2.65997E+05 + 1.06100E+02 2.65997E+05 + 1.06200E+02 2.65997E+05 + 1.06300E+02 2.65997E+05 + 1.06400E+02 2.65997E+05 + 1.06500E+02 2.65997E+05 + 1.06600E+02 2.65997E+05 + 1.06700E+02 2.65997E+05 + 1.06800E+02 2.65997E+05 + 1.06900E+02 2.65997E+05 + 1.07000E+02 2.65997E+05 + 1.07100E+02 2.65997E+05 + 1.07200E+02 2.65997E+05 + 1.07300E+02 2.65997E+05 + 1.07400E+02 2.65997E+05 + 1.07500E+02 2.65997E+05 + 1.07600E+02 2.65997E+05 + 1.07700E+02 2.65997E+05 + 1.07800E+02 2.65997E+05 + 1.07900E+02 2.65997E+05 + 1.08000E+02 2.65997E+05 + 1.08100E+02 2.65997E+05 + 1.08200E+02 2.65997E+05 + 1.08300E+02 2.65997E+05 + 1.08400E+02 2.65997E+05 + 1.08500E+02 2.65997E+05 + 1.08600E+02 2.65997E+05 + 1.08700E+02 2.65997E+05 + 1.08800E+02 2.65997E+05 + 1.08900E+02 2.65997E+05 + 1.09000E+02 2.65997E+05 + 1.09100E+02 2.65997E+05 + 1.09200E+02 2.65997E+05 + 1.09300E+02 2.65997E+05 + 1.09400E+02 2.65997E+05 + 1.09500E+02 2.65997E+05 + 1.09600E+02 2.65997E+05 + 1.09700E+02 2.65997E+05 + 1.09800E+02 2.65997E+05 + 1.09900E+02 2.65997E+05 + 1.10000E+02 2.65997E+05 + 1.10100E+02 2.65997E+05 + 1.10200E+02 2.65997E+05 + 1.10300E+02 2.65997E+05 + 1.10400E+02 2.65997E+05 + 1.10500E+02 2.65997E+05 + 1.10600E+02 2.65997E+05 + 1.10700E+02 2.65997E+05 + 1.10800E+02 2.65997E+05 + 1.10900E+02 2.65997E+05 + 1.11000E+02 2.65997E+05 + 1.11100E+02 2.65997E+05 + 1.11200E+02 2.65997E+05 + 1.11300E+02 2.65997E+05 + 1.11400E+02 2.65997E+05 + 1.11500E+02 2.65997E+05 + 1.11600E+02 2.65997E+05 + 1.11700E+02 2.75375E+05 + 1.11800E+02 2.84753E+05 + 1.11900E+02 2.94132E+05 + 1.12000E+02 3.03510E+05 + 1.12100E+02 3.12888E+05 + 1.12200E+02 3.22266E+05 + 1.12300E+02 3.31644E+05 + 1.12400E+02 3.41023E+05 + 1.12500E+02 3.50401E+05 + 1.12600E+02 3.59779E+05 + 1.12700E+02 3.69157E+05 + 1.12800E+02 3.78536E+05 + 1.12900E+02 3.87914E+05 + 1.13000E+02 3.97292E+05 + 1.13100E+02 4.06670E+05 + 1.13200E+02 4.16049E+05 + 1.13300E+02 4.25427E+05 + 1.13400E+02 4.34805E+05 + 1.13500E+02 4.44183E+05 + 1.13600E+02 4.53561E+05 + 1.13700E+02 4.62940E+05 + 1.13800E+02 4.72318E+05 + 1.13900E+02 4.81696E+05 + 1.14000E+02 4.91074E+05 + 1.14100E+02 5.00453E+05 + 1.14200E+02 5.09831E+05 + 1.14300E+02 5.19209E+05 + 1.14400E+02 5.28587E+05 + 1.14500E+02 5.37966E+05 + 1.14600E+02 5.47344E+05 + 1.14700E+02 5.56722E+05 + 1.14800E+02 5.66100E+05 + 1.14900E+02 5.75478E+05 + 1.15000E+02 5.84857E+05 + 1.15100E+02 5.94235E+05 + 1.15200E+02 6.03613E+05 + 1.15300E+02 6.12991E+05 + 1.15400E+02 6.22370E+05 + 1.15500E+02 6.31748E+05 + 1.15600E+02 6.41126E+05 + 1.15700E+02 6.50504E+05 + 1.15800E+02 6.59882E+05 + 1.15900E+02 6.69261E+05 + 1.16000E+02 6.78639E+05 + 1.16100E+02 6.88017E+05 + 1.16200E+02 6.97395E+05 + 1.16300E+02 7.06774E+05 + 1.16400E+02 7.16152E+05 + 1.16500E+02 7.25530E+05 + 1.16600E+02 7.34908E+05 + 1.16700E+02 7.44287E+05 + 1.16800E+02 7.53665E+05 + 1.16900E+02 7.63043E+05 + 1.17000E+02 7.72421E+05 + 1.17100E+02 7.81800E+05 + 1.17200E+02 7.91178E+05 + 1.17300E+02 8.00556E+05 + 1.17400E+02 8.09934E+05 + 1.17500E+02 8.19312E+05 + 1.17600E+02 8.28691E+05 + 1.17700E+02 8.38069E+05 + 1.17800E+02 8.47447E+05 + 1.17900E+02 8.56825E+05 + 1.18000E+02 8.66204E+05 + 1.18100E+02 8.75582E+05 + 1.18200E+02 8.84960E+05 + 1.18300E+02 8.94338E+05 + 1.18400E+02 9.03716E+05 + 1.18500E+02 9.13095E+05 + 1.18600E+02 9.22473E+05 + 1.18700E+02 9.31851E+05 + 1.18800E+02 9.41229E+05 + 1.18900E+02 9.50608E+05 + 1.19000E+02 9.59986E+05 + 1.19100E+02 9.69364E+05 + 1.19200E+02 9.78742E+05 + 1.19300E+02 9.88120E+05 + 1.19400E+02 9.97499E+05 + 1.19500E+02 1.00688E+06 + 1.19600E+02 1.01626E+06 + 1.19700E+02 1.02563E+06 + 1.19800E+02 1.03501E+06 + 1.19900E+02 1.04439E+06 + 1.20000E+02 1.05377E+06 + 1.20100E+02 1.06315E+06 + 1.20200E+02 1.07252E+06 + 1.20300E+02 1.08190E+06 + 1.20400E+02 1.09128E+06 + 1.20500E+02 1.10066E+06 + 1.20600E+02 1.11004E+06 + 1.20700E+02 1.11942E+06 + 1.20800E+02 1.12879E+06 + 1.20900E+02 1.13817E+06 + 1.21000E+02 1.14755E+06 + 1.21100E+02 1.15693E+06 + 1.21200E+02 1.16631E+06 + 1.21300E+02 1.17569E+06 + 1.21400E+02 1.18506E+06 + 1.21500E+02 1.19444E+06 + 1.21600E+02 1.20382E+06 + 1.21700E+02 1.21320E+06 + 1.21800E+02 1.22258E+06 + 1.21900E+02 1.23195E+06 + 1.22000E+02 1.24133E+06 + 1.22100E+02 1.25071E+06 + 1.22200E+02 1.26009E+06 + 1.22300E+02 1.26947E+06 + 1.22400E+02 1.27885E+06 + 1.22500E+02 1.28822E+06 + 1.22600E+02 1.29760E+06 + 1.22700E+02 1.30698E+06 + 1.22800E+02 1.31636E+06 + 1.22900E+02 1.32574E+06 + 1.23000E+02 1.33512E+06 + 1.23100E+02 1.34449E+06 + 1.23200E+02 1.35387E+06 + 1.23300E+02 1.36325E+06 + 1.23400E+02 1.37263E+06 + 1.23500E+02 1.38201E+06 + 1.23600E+02 1.39138E+06 + 1.23700E+02 1.40076E+06 + 1.23800E+02 1.41014E+06 + 1.23900E+02 1.41952E+06 + 1.24000E+02 1.42890E+06 + 1.24100E+02 1.43828E+06 + 1.24200E+02 1.44765E+06 + 1.24300E+02 1.45703E+06 + 1.24400E+02 1.46641E+06 + 1.24500E+02 1.47579E+06 + 1.24600E+02 1.48517E+06 + 1.24700E+02 1.49454E+06 + 1.24800E+02 1.50392E+06 + 1.24900E+02 1.46641E+06 + 1.25000E+02 1.42890E+06 + 1.25100E+02 1.39138E+06 + 1.25200E+02 1.35387E+06 + 1.25300E+02 1.31636E+06 + 1.25400E+02 1.27885E+06 + 1.25500E+02 1.24133E+06 + 1.25600E+02 1.20382E+06 + 1.25700E+02 1.16631E+06 + 1.25800E+02 1.12879E+06 + 1.25900E+02 1.09128E+06 + 1.26000E+02 1.05377E+06 + 1.26100E+02 1.01626E+06 + 1.26200E+02 9.78742E+05 + 1.26300E+02 9.41229E+05 + 1.26400E+02 9.03716E+05 + 1.26500E+02 8.66204E+05 + 1.26600E+02 8.28691E+05 + 1.26700E+02 7.91178E+05 + 1.26800E+02 7.53665E+05 + 1.26900E+02 7.16152E+05 + 1.27000E+02 6.78639E+05 + 1.27100E+02 6.41126E+05 + 1.27200E+02 6.03613E+05 + 1.27300E+02 5.66100E+05 + 1.27400E+02 5.28587E+05 + 1.27500E+02 4.91074E+05 + 1.27600E+02 4.53561E+05 + 1.27700E+02 4.16049E+05 + 1.27800E+02 3.78536E+05 + 1.27900E+02 3.41023E+05 + 1.28000E+02 3.03510E+05 + 1.28100E+02 2.65997E+05 + 1.28200E+02 2.65997E+05 + 1.28300E+02 2.65997E+05 + 1.28400E+02 2.65997E+05 + 1.28500E+02 2.65997E+05 + 1.28600E+02 2.65997E+05 + 1.28700E+02 2.65997E+05 + 1.28800E+02 2.65997E+05 + 1.28900E+02 2.65997E+05 + 1.29000E+02 2.65997E+05 + 1.29100E+02 2.65997E+05 + 1.29200E+02 2.65997E+05 + 1.29300E+02 2.65997E+05 + 1.29400E+02 2.65997E+05 + 1.29500E+02 2.65997E+05 + 1.29600E+02 2.65997E+05 + 1.29700E+02 2.65997E+05 + 1.29800E+02 2.65997E+05 + 1.29900E+02 2.65997E+05 + 1.30000E+02 2.65997E+05 + 1.30100E+02 2.65997E+05 + 1.30200E+02 2.65997E+05 + 1.30300E+02 2.65997E+05 + 1.30400E+02 2.65997E+05 + 1.30500E+02 2.65997E+05 + 1.30600E+02 2.65997E+05 + 1.30700E+02 2.65997E+05 + 1.30800E+02 2.65997E+05 + 1.30900E+02 2.65997E+05 + 1.31000E+02 2.65997E+05 + 1.31100E+02 2.65997E+05 + 1.31200E+02 2.65997E+05 + 1.31300E+02 2.65997E+05 + 1.31400E+02 2.65997E+05 + 1.31500E+02 2.65997E+05 + 1.31600E+02 2.65997E+05 + 1.31700E+02 2.65997E+05 + 1.31800E+02 2.65997E+05 + 1.31900E+02 2.65997E+05 + 1.32000E+02 2.65997E+05 + 1.32100E+02 2.65997E+05 + 1.32200E+02 2.65997E+05 + 1.32300E+02 2.65997E+05 + 1.32400E+02 2.65997E+05 + 1.32500E+02 2.65997E+05 + 1.32600E+02 2.65997E+05 + 1.32700E+02 2.65997E+05 + 1.32800E+02 2.65997E+05 + 1.32900E+02 2.65997E+05 + 1.33000E+02 2.65997E+05 + 1.33100E+02 2.65997E+05 + 1.33200E+02 2.65997E+05 + 1.33300E+02 2.65997E+05 + 1.33400E+02 2.65997E+05 + 1.33500E+02 2.65997E+05 + 1.33600E+02 2.65997E+05 + 1.33700E+02 2.65997E+05 + 1.33800E+02 2.65997E+05 + 1.33900E+02 2.65997E+05 + 1.34000E+02 2.65997E+05 + 1.34100E+02 2.65997E+05 + 1.34200E+02 2.65997E+05 + 1.34300E+02 2.65997E+05 + 1.34400E+02 2.65997E+05 + 1.34500E+02 2.65997E+05 + 1.34600E+02 2.65997E+05 + 1.34700E+02 2.65997E+05 + 1.34800E+02 2.65997E+05 + 1.34900E+02 2.65997E+05 + 1.35000E+02 2.65997E+05 + 1.35100E+02 2.65997E+05 + 1.35200E+02 2.65997E+05 + 1.35300E+02 2.65997E+05 + 1.35400E+02 2.65997E+05 + 1.35500E+02 2.65997E+05 + 1.35600E+02 2.65997E+05 + 1.35700E+02 2.65997E+05 + 1.35800E+02 2.65997E+05 + 1.35900E+02 2.65997E+05 + 1.36000E+02 2.65997E+05 + 1.36100E+02 2.65997E+05 + 1.36200E+02 2.65997E+05 + 1.36300E+02 2.65997E+05 + 1.36400E+02 2.65997E+05 + 1.36500E+02 2.65997E+05 + 1.36600E+02 2.65997E+05 + 1.36700E+02 2.65997E+05 + 1.36800E+02 2.65997E+05 + 1.36900E+02 2.65997E+05 + 1.37000E+02 2.65997E+05 + 1.37100E+02 2.65997E+05 + 1.37200E+02 2.65997E+05 + 1.37300E+02 2.65997E+05 + 1.37400E+02 2.65997E+05 + 1.37500E+02 2.65997E+05 + 1.37600E+02 2.65997E+05 + 1.37700E+02 2.65997E+05 + 1.37800E+02 2.65997E+05 + 1.37900E+02 2.65997E+05 + 1.38000E+02 2.65997E+05 + 1.38100E+02 2.65997E+05 + 1.38200E+02 2.65997E+05 + 1.38300E+02 2.65997E+05 + 1.38400E+02 2.65997E+05 + 1.38500E+02 2.65997E+05 + 1.38600E+02 2.65997E+05 + 1.38700E+02 2.65997E+05 + 1.38800E+02 2.65997E+05 + 1.38900E+02 2.65997E+05 + 1.39000E+02 2.65997E+05 + 1.39100E+02 2.65997E+05 + 1.39200E+02 2.80889E+05 + 1.39300E+02 2.95782E+05 + 1.39400E+02 3.10674E+05 + 1.39500E+02 3.25566E+05 + 1.39600E+02 3.40458E+05 + 1.39700E+02 3.55351E+05 + 1.39800E+02 3.70243E+05 + 1.39900E+02 3.85135E+05 + 1.40000E+02 4.00028E+05 + 1.40100E+02 4.14920E+05 + 1.40200E+02 4.29812E+05 + 1.40300E+02 4.44705E+05 + 1.40400E+02 4.59597E+05 + 1.40500E+02 4.74489E+05 + 1.40600E+02 4.89382E+05 + 1.40700E+02 5.04274E+05 + 1.40800E+02 5.19166E+05 + 1.40900E+02 5.34059E+05 + 1.41000E+02 5.48951E+05 + 1.41100E+02 5.63843E+05 + 1.41200E+02 5.78736E+05 + 1.41300E+02 5.93628E+05 + 1.41400E+02 6.08520E+05 + 1.41500E+02 6.23413E+05 + 1.41600E+02 6.38305E+05 + 1.41700E+02 6.53197E+05 + 1.41800E+02 6.68090E+05 + 1.41900E+02 6.82982E+05 + 1.42000E+02 6.97874E+05 + 1.42100E+02 7.12767E+05 + 1.42200E+02 7.27659E+05 + 1.42300E+02 7.42551E+05 + 1.42400E+02 7.57444E+05 + 1.42500E+02 7.72336E+05 + 1.42600E+02 7.87228E+05 + 1.42700E+02 8.02120E+05 + 1.42800E+02 8.17013E+05 + 1.42900E+02 8.31905E+05 + 1.43000E+02 8.46798E+05 + 1.43100E+02 8.61690E+05 + 1.43200E+02 8.76582E+05 + 1.43300E+02 8.91474E+05 + 1.43400E+02 9.06367E+05 + 1.43500E+02 9.21259E+05 + 1.43600E+02 9.36152E+05 + 1.43700E+02 9.51044E+05 + 1.43800E+02 9.65936E+05 + 1.43900E+02 9.80828E+05 + 1.44000E+02 9.95721E+05 + 1.44100E+02 1.01061E+06 + 1.44200E+02 1.02551E+06 + 1.44300E+02 1.04040E+06 + 1.44400E+02 1.05529E+06 + 1.44500E+02 1.07018E+06 + 1.44600E+02 1.08507E+06 + 1.44700E+02 1.09997E+06 + 1.44800E+02 1.11486E+06 + 1.44900E+02 1.12975E+06 + 1.45000E+02 1.14464E+06 + 1.45100E+02 1.15954E+06 + 1.45200E+02 1.17443E+06 + 1.45300E+02 1.18932E+06 + 1.45400E+02 1.20421E+06 + 1.45500E+02 1.21911E+06 + 1.45600E+02 1.23400E+06 + 1.45700E+02 1.24889E+06 + 1.45800E+02 1.26378E+06 + 1.45900E+02 1.27867E+06 + 1.46000E+02 1.29357E+06 + 1.46100E+02 1.30846E+06 + 1.46200E+02 1.25054E+06 + 1.46300E+02 1.19263E+06 + 1.46400E+02 1.13472E+06 + 1.46500E+02 1.07680E+06 + 1.46600E+02 1.01889E+06 + 1.46700E+02 9.60972E+05 + 1.46800E+02 9.03058E+05 + 1.46900E+02 8.45143E+05 + 1.47000E+02 7.87228E+05 + 1.47100E+02 7.29314E+05 + 1.47200E+02 6.71399E+05 + 1.47300E+02 6.13484E+05 + 1.47400E+02 5.55570E+05 + 1.47500E+02 4.97655E+05 + 1.47600E+02 4.39741E+05 + 1.47700E+02 3.81826E+05 + 1.47800E+02 3.23912E+05 + 1.47900E+02 2.65997E+05 + 1.48000E+02 2.65997E+05 + 1.48100E+02 2.65997E+05 + 1.48200E+02 2.65997E+05 + 1.48300E+02 2.65997E+05 + 1.48400E+02 2.65997E+05 + 1.48500E+02 2.65997E+05 + 1.48600E+02 2.65997E+05 + 1.48700E+02 2.65997E+05 + 1.48800E+02 2.65997E+05 + 1.48900E+02 2.65997E+05 + 1.49000E+02 2.65997E+05 + 1.49100E+02 2.65997E+05 + 1.49200E+02 2.65997E+05 + 1.49300E+02 2.65997E+05 + 1.49400E+02 2.65997E+05 + 1.49500E+02 2.65997E+05 + 1.49600E+02 2.65997E+05 + 1.49700E+02 2.65997E+05 + 1.49800E+02 2.65997E+05 + 1.49900E+02 2.65997E+05 + 1.50000E+02 2.65997E+05 + 1.50100E+02 2.65997E+05 + 1.50200E+02 2.65997E+05 + 1.50300E+02 2.65997E+05 + 1.50400E+02 2.65997E+05 + 1.50500E+02 2.65997E+05 + 1.50600E+02 2.65997E+05 + 1.50700E+02 2.65997E+05 + 1.50800E+02 2.65997E+05 + 1.50900E+02 2.65997E+05 + 1.51000E+02 2.65997E+05 + 1.51100E+02 2.65997E+05 + 1.51200E+02 2.65997E+05 + 1.51300E+02 2.65997E+05 + 1.51400E+02 2.65997E+05 + 1.51500E+02 2.65997E+05 + 1.51600E+02 2.65997E+05 + 1.51700E+02 2.65997E+05 + 1.51800E+02 2.65997E+05 + 1.51900E+02 2.65997E+05 + 1.52000E+02 2.65997E+05 + 1.52100E+02 2.65997E+05 + 1.52200E+02 2.65997E+05 + 1.52300E+02 2.65997E+05 + 1.52400E+02 2.65997E+05 + 1.52500E+02 2.65997E+05 + 1.52600E+02 2.65997E+05 + 1.52700E+02 2.65997E+05 + 1.52800E+02 2.65997E+05 + 1.52900E+02 2.65997E+05 + 1.53000E+02 2.65997E+05 + 1.53100E+02 2.65997E+05 + 1.53200E+02 2.65997E+05 + 1.53300E+02 2.65997E+05 + 1.53400E+02 2.65997E+05 + 1.53500E+02 2.65997E+05 + 1.53600E+02 2.65997E+05 + 1.53700E+02 2.65997E+05 + 1.53800E+02 2.65997E+05 + 1.53900E+02 2.88163E+05 + 1.54000E+02 3.10329E+05 + 1.54100E+02 3.32495E+05 + 1.54200E+02 3.54661E+05 + 1.54300E+02 3.76827E+05 + 1.54400E+02 3.98994E+05 + 1.54500E+02 4.21160E+05 + 1.54600E+02 4.43326E+05 + 1.54700E+02 4.65492E+05 + 1.54800E+02 4.87658E+05 + 1.54900E+02 5.09824E+05 + 1.55000E+02 5.31990E+05 + 1.55100E+02 5.54156E+05 + 1.55200E+02 5.76322E+05 + 1.55300E+02 5.98488E+05 + 1.55400E+02 6.20655E+05 + 1.55500E+02 6.42821E+05 + 1.55600E+02 6.64987E+05 + 1.55700E+02 6.87153E+05 + 1.55800E+02 7.09319E+05 + 1.55900E+02 7.31485E+05 + 1.56000E+02 7.53651E+05 + 1.56100E+02 7.75817E+05 + 1.56200E+02 7.97984E+05 + 1.56300E+02 8.20150E+05 + 1.56400E+02 8.42316E+05 + 1.56500E+02 8.64482E+05 + 1.56600E+02 8.86648E+05 + 1.56700E+02 9.08814E+05 + 1.56800E+02 9.30980E+05 + 1.56900E+02 9.53146E+05 + 1.57000E+02 9.75312E+05 + 1.57100E+02 9.97478E+05 + 1.57200E+02 1.01964E+06 + 1.57300E+02 1.04181E+06 + 1.57400E+02 1.06398E+06 + 1.57500E+02 1.08614E+06 + 1.57600E+02 1.10831E+06 + 1.57700E+02 1.13048E+06 + 1.57800E+02 1.15264E+06 + 1.57900E+02 1.17481E+06 + 1.58000E+02 1.19697E+06 + 1.58100E+02 1.21914E+06 + 1.58200E+02 1.24131E+06 + 1.58300E+02 1.26347E+06 + 1.58400E+02 1.28564E+06 + 1.58500E+02 1.30780E+06 + 1.58600E+02 1.32997E+06 + 1.58700E+02 1.35214E+06 + 1.58800E+02 1.37430E+06 + 1.58900E+02 1.39647E+06 + 1.59000E+02 1.41863E+06 + 1.59100E+02 1.44080E+06 + 1.59200E+02 1.46297E+06 + 1.59300E+02 1.48513E+06 + 1.59400E+02 1.50730E+06 + 1.59500E+02 1.52946E+06 + 1.59600E+02 1.43922E+06 + 1.59700E+02 1.34897E+06 + 1.59800E+02 1.25872E+06 + 1.59900E+02 1.16847E+06 + 1.60000E+02 1.07823E+06 + 1.60100E+02 9.87979E+05 + 1.60200E+02 8.97731E+05 + 1.60300E+02 8.07483E+05 + 1.60400E+02 7.17236E+05 + 1.60500E+02 6.26988E+05 + 1.60600E+02 5.36740E+05 + 1.60700E+02 4.46492E+05 + 1.60800E+02 3.56245E+05 + 1.60900E+02 2.65997E+05 + 1.61000E+02 2.65997E+05 + 1.61100E+02 2.65997E+05 + 1.61200E+02 2.65997E+05 + 1.61300E+02 2.65997E+05 + 1.61400E+02 2.65997E+05 + 1.61500E+02 2.65997E+05 + 1.61600E+02 2.65997E+05 + 1.61700E+02 2.65997E+05 + 1.61800E+02 2.65997E+05 + 1.61900E+02 2.65997E+05 + 1.62000E+02 2.65997E+05 + 1.62100E+02 2.65997E+05 + 1.62200E+02 2.65997E+05 + 1.62300E+02 2.65997E+05 + 1.62400E+02 2.65997E+05 + 1.62500E+02 2.65997E+05 + 1.62600E+02 2.65997E+05 + 1.62700E+02 2.65997E+05 + 1.62800E+02 2.65997E+05 + 1.62900E+02 2.65997E+05 + 1.63000E+02 2.65997E+05 + 1.63100E+02 2.65997E+05 + 1.63200E+02 2.65997E+05 + 1.63300E+02 2.65997E+05 + 1.63400E+02 2.65997E+05 + 1.63500E+02 2.65997E+05 + 1.63600E+02 2.65997E+05 + 1.63700E+02 2.65997E+05 + 1.63800E+02 2.65997E+05 + 1.63900E+02 2.65997E+05 + 1.64000E+02 2.65997E+05 + 1.64100E+02 2.65997E+05 + 1.64200E+02 2.65997E+05 + 1.64300E+02 2.65997E+05 + 1.64400E+02 2.65997E+05 + 1.64500E+02 2.65997E+05 + 1.64600E+02 2.65997E+05 + 1.64700E+02 2.65997E+05 + 1.64800E+02 2.65997E+05 + 1.64900E+02 2.65997E+05 + 1.65000E+02 2.65997E+05 + 1.65100E+02 2.65997E+05 + 1.65200E+02 2.65997E+05 + 1.65300E+02 2.65997E+05 + 1.65400E+02 2.65997E+05 + 1.65500E+02 2.65997E+05 + 1.65600E+02 2.65997E+05 + 1.65700E+02 2.65997E+05 + 1.65800E+02 2.65997E+05 + 1.65900E+02 2.73249E+05 + 1.66000E+02 2.80502E+05 + 1.66100E+02 2.87755E+05 + 1.66200E+02 2.95007E+05 + 1.66300E+02 3.02260E+05 + 1.66400E+02 3.09512E+05 + 1.66500E+02 3.16765E+05 + 1.66600E+02 3.24018E+05 + 1.66700E+02 3.31270E+05 + 1.66800E+02 3.38523E+05 + 1.66900E+02 3.45775E+05 + 1.67000E+02 3.53028E+05 + 1.67100E+02 3.60281E+05 + 1.67200E+02 3.67533E+05 + 1.67300E+02 3.74786E+05 + 1.67400E+02 3.82038E+05 + 1.67500E+02 3.89291E+05 + 1.67600E+02 3.96544E+05 + 1.67700E+02 4.03796E+05 + 1.67800E+02 4.11049E+05 + 1.67900E+02 4.18301E+05 + 1.68000E+02 4.25554E+05 + 1.68100E+02 4.32806E+05 + 1.68200E+02 4.40059E+05 + 1.68300E+02 4.47312E+05 + 1.68400E+02 4.54564E+05 + 1.68500E+02 4.61817E+05 + 1.68600E+02 4.69069E+05 + 1.68700E+02 4.76322E+05 + 1.68800E+02 4.83575E+05 + 1.68900E+02 4.90827E+05 + 1.69000E+02 4.98080E+05 + 1.69100E+02 5.05332E+05 + 1.69200E+02 5.12585E+05 + 1.69300E+02 5.19838E+05 + 1.69400E+02 5.27090E+05 + 1.69500E+02 5.34343E+05 + 1.69600E+02 5.41595E+05 + 1.69700E+02 5.48848E+05 + 1.69800E+02 5.56101E+05 + 1.69900E+02 5.63353E+05 + 1.70000E+02 5.70606E+05 + 1.70100E+02 5.77858E+05 + 1.70200E+02 5.85111E+05 + 1.70300E+02 5.92364E+05 + 1.70400E+02 5.99616E+05 + 1.70500E+02 6.06869E+05 + 1.70600E+02 6.14121E+05 + 1.70700E+02 6.21374E+05 + 1.70800E+02 6.28626E+05 + 1.70900E+02 6.35879E+05 + 1.71000E+02 6.43132E+05 + 1.71100E+02 6.50384E+05 + 1.71200E+02 6.57637E+05 + 1.71300E+02 6.64890E+05 + 1.71400E+02 6.72142E+05 + 1.71500E+02 6.79395E+05 + 1.71600E+02 6.86647E+05 + 1.71700E+02 6.93900E+05 + 1.71800E+02 7.01152E+05 + 1.71900E+02 7.08405E+05 + 1.72000E+02 7.15658E+05 + 1.72100E+02 7.22910E+05 + 1.72200E+02 7.30163E+05 + 1.72300E+02 7.37416E+05 + 1.72400E+02 7.44668E+05 + 1.72500E+02 7.51921E+05 + 1.72600E+02 7.59173E+05 + 1.72700E+02 7.66426E+05 + 1.72800E+02 7.73678E+05 + 1.72900E+02 7.80931E+05 + 1.73000E+02 7.88184E+05 + 1.73100E+02 7.95436E+05 + 1.73200E+02 8.02689E+05 + 1.73300E+02 8.09941E+05 + 1.73400E+02 8.17194E+05 + 1.73500E+02 8.24447E+05 + 1.73600E+02 8.31699E+05 + 1.73700E+02 8.38952E+05 + 1.73800E+02 8.46204E+05 + 1.73900E+02 8.53457E+05 + 1.74000E+02 8.60710E+05 + 1.74100E+02 8.67962E+05 + 1.74200E+02 8.75215E+05 + 1.74300E+02 8.82467E+05 + 1.74400E+02 8.89720E+05 + 1.74500E+02 8.96972E+05 + 1.74600E+02 9.04225E+05 + 1.74700E+02 9.11478E+05 + 1.74800E+02 9.18730E+05 + 1.74900E+02 9.25983E+05 + 1.75000E+02 9.33236E+05 + 1.75100E+02 9.40488E+05 + 1.75200E+02 9.47741E+05 + 1.75300E+02 9.54993E+05 + 1.75400E+02 9.62246E+05 + 1.75500E+02 9.69498E+05 + 1.75600E+02 9.76751E+05 + 1.75700E+02 9.84004E+05 + 1.75800E+02 9.91256E+05 + 1.75900E+02 9.98509E+05 + 1.76000E+02 1.00576E+06 + 1.76100E+02 1.01301E+06 + 1.76200E+02 1.02027E+06 + 1.76300E+02 1.02752E+06 + 1.76400E+02 1.03477E+06 + 1.76500E+02 1.04202E+06 + 1.76600E+02 1.04928E+06 + 1.76700E+02 1.05653E+06 + 1.76800E+02 1.06378E+06 + 1.76900E+02 1.07103E+06 + 1.77000E+02 1.07829E+06 + 1.77100E+02 1.08554E+06 + 1.77200E+02 1.09279E+06 + 1.77300E+02 1.10005E+06 + 1.77400E+02 1.10730E+06 + 1.77500E+02 1.11455E+06 + 1.77600E+02 1.12180E+06 + 1.77700E+02 1.12906E+06 + 1.77800E+02 1.13631E+06 + 1.77900E+02 1.14356E+06 + 1.78000E+02 1.15081E+06 + 1.78100E+02 1.15807E+06 + 1.78200E+02 1.16532E+06 + 1.78300E+02 1.17257E+06 + 1.78400E+02 1.17982E+06 + 1.78500E+02 1.18708E+06 + 1.78600E+02 1.19433E+06 + 1.78700E+02 1.20158E+06 + 1.78800E+02 1.20883E+06 + 1.78900E+02 1.21609E+06 + 1.79000E+02 1.22334E+06 + 1.79100E+02 1.23059E+06 + 1.79200E+02 1.23784E+06 + 1.79300E+02 1.24510E+06 + 1.79400E+02 1.25235E+06 + 1.79500E+02 1.25960E+06 + 1.79600E+02 1.26685E+06 + 1.79700E+02 1.27411E+06 + 1.79800E+02 1.28136E+06 + 1.79900E+02 1.28861E+06 + 1.80000E+02 1.29587E+06 + 1.80100E+02 1.30312E+06 + 1.80200E+02 1.31037E+06 + 1.80300E+02 1.28136E+06 + 1.80400E+02 1.25235E+06 + 1.80500E+02 1.22334E+06 + 1.80600E+02 1.19433E+06 + 1.80700E+02 1.16532E+06 + 1.80800E+02 1.13631E+06 + 1.80900E+02 1.10730E+06 + 1.81000E+02 1.07829E+06 + 1.81100E+02 1.04928E+06 + 1.81200E+02 1.02027E+06 + 1.81300E+02 9.91256E+05 + 1.81400E+02 9.62246E+05 + 1.81500E+02 9.33236E+05 + 1.81600E+02 9.04225E+05 + 1.81700E+02 8.75215E+05 + 1.81800E+02 8.46204E+05 + 1.81900E+02 8.17194E+05 + 1.82000E+02 7.88184E+05 + 1.82100E+02 7.59173E+05 + 1.82200E+02 7.30163E+05 + 1.82300E+02 7.01152E+05 + 1.82400E+02 6.72142E+05 + 1.82500E+02 6.43132E+05 + 1.82600E+02 6.14121E+05 + 1.82700E+02 5.85111E+05 + 1.82800E+02 5.56101E+05 + 1.82900E+02 5.27090E+05 + 1.83000E+02 4.98080E+05 + 1.83100E+02 4.69070E+05 + 1.83200E+02 4.40059E+05 + 1.83300E+02 4.11049E+05 + 1.83400E+02 3.82038E+05 + 1.83500E+02 3.53028E+05 + 1.83600E+02 3.24018E+05 + 1.83700E+02 2.95007E+05 + 1.83800E+02 2.65997E+05 + 1.83900E+02 2.65997E+05 + 1.84000E+02 2.65997E+05 + 1.84100E+02 2.65997E+05 + 1.84200E+02 2.65997E+05 + 1.84300E+02 2.65997E+05 + 1.84400E+02 2.65997E+05 + 1.84500E+02 2.65997E+05 + 1.84600E+02 2.65997E+05 + 1.84700E+02 2.65997E+05 + 1.84800E+02 2.65997E+05 + 1.84900E+02 2.65997E+05 + 1.85000E+02 2.65997E+05 + 1.85100E+02 2.65997E+05 + 1.85200E+02 2.65997E+05 + 1.85300E+02 2.65997E+05 + 1.85400E+02 2.65997E+05 + 1.85500E+02 2.65997E+05 + 1.85600E+02 2.65997E+05 + 1.85700E+02 2.65997E+05 + 1.85800E+02 2.65997E+05 + 1.85900E+02 2.65997E+05 + 1.86000E+02 2.65997E+05 + 1.86100E+02 2.65997E+05 + 1.86200E+02 2.65997E+05 + 1.86300E+02 2.65997E+05 + 1.86400E+02 2.65997E+05 + 1.86500E+02 2.65997E+05 + 1.86600E+02 2.65997E+05 + 1.86700E+02 2.65997E+05 + 1.86800E+02 2.65997E+05 + 1.86900E+02 2.65997E+05 + 1.87000E+02 2.65997E+05 + 1.87100E+02 2.65997E+05 + 1.87200E+02 2.65997E+05 + 1.87300E+02 2.65997E+05 + 1.87400E+02 2.65997E+05 + 1.87500E+02 2.65997E+05 + 1.87600E+02 2.65997E+05 + 1.87700E+02 2.65997E+05 + 1.87800E+02 2.65997E+05 + 1.87900E+02 2.65997E+05 + 1.88000E+02 2.65997E+05 + 1.88100E+02 2.65997E+05 + 1.88200E+02 2.65997E+05 + 1.88300E+02 2.65997E+05 + 1.88400E+02 2.65997E+05 + 1.88500E+02 2.65997E+05 + 1.88600E+02 2.65997E+05 + 1.88700E+02 2.65997E+05 + 1.88800E+02 2.65997E+05 + 1.88900E+02 2.65997E+05 + 1.89000E+02 2.65997E+05 + 1.89100E+02 2.65997E+05 + 1.89200E+02 2.65997E+05 + 1.89300E+02 2.65997E+05 + 1.89400E+02 2.65997E+05 + 1.89500E+02 2.65997E+05 + 1.89600E+02 2.65997E+05 + 1.89700E+02 2.65997E+05 + 1.89800E+02 2.65997E+05 + 1.89900E+02 2.65997E+05 + 1.90000E+02 2.65997E+05 + 1.90100E+02 2.65997E+05 + 1.90200E+02 2.65997E+05 + 1.90300E+02 2.65997E+05 + 1.90400E+02 2.65997E+05 + 1.90500E+02 2.65997E+05 + 1.90600E+02 2.65997E+05 + 1.90700E+02 2.65997E+05 + 1.90800E+02 2.65997E+05 + 1.90900E+02 2.65997E+05 + 1.91000E+02 2.65997E+05 + 1.91100E+02 2.65997E+05 + 1.91200E+02 2.65997E+05 + 1.91300E+02 2.65997E+05 + 1.91400E+02 2.65997E+05 + 1.91500E+02 2.65997E+05 + 1.91600E+02 2.65997E+05 + 1.91700E+02 2.65997E+05 + 1.91800E+02 2.65997E+05 + 1.91900E+02 2.65997E+05 + 1.92000E+02 2.65997E+05 + 1.92100E+02 2.65997E+05 + 1.92200E+02 2.65997E+05 + 1.92300E+02 2.65997E+05 + 1.92400E+02 2.65997E+05 + 1.92500E+02 2.65997E+05 + 1.92600E+02 2.65997E+05 + 1.92700E+02 2.65997E+05 + 1.92800E+02 2.65997E+05 + 1.92900E+02 2.65997E+05 + 1.93000E+02 2.65997E+05 + 1.93100E+02 2.65997E+05 + 1.93200E+02 2.65997E+05 + 1.93300E+02 2.65997E+05 + 1.93400E+02 2.65997E+05 + 1.93500E+02 2.65997E+05 + 1.93600E+02 2.65997E+05 + 1.93700E+02 2.65997E+05 + 1.93800E+02 2.65997E+05 + 1.93900E+02 2.65997E+05 + 1.94000E+02 2.65997E+05 + 1.94100E+02 2.65997E+05 + 1.94200E+02 2.65997E+05 + 1.94300E+02 2.65997E+05 + 1.94400E+02 2.65997E+05 + 1.94500E+02 2.65997E+05 + 1.94600E+02 2.65997E+05 + 1.94700E+02 2.65997E+05 + 1.94800E+02 2.65997E+05 + 1.94900E+02 2.65997E+05 + 1.95000E+02 2.65997E+05 + 1.95100E+02 2.65997E+05 + 1.95200E+02 2.65997E+05 + 1.95300E+02 2.65997E+05 + 1.95400E+02 2.65997E+05 + 1.95500E+02 2.65997E+05 + 1.95600E+02 2.65997E+05 + 1.95700E+02 2.65997E+05 + 1.95800E+02 2.65997E+05 + 1.95900E+02 2.78354E+05 + 1.96000E+02 2.90712E+05 + 1.96100E+02 3.03069E+05 + 1.96200E+02 3.15426E+05 + 1.96300E+02 3.27784E+05 + 1.96400E+02 3.40141E+05 + 1.96500E+02 3.52498E+05 + 1.96600E+02 3.64856E+05 + 1.96700E+02 3.77213E+05 + 1.96800E+02 3.89570E+05 + 1.96900E+02 4.01928E+05 + 1.97000E+02 4.14285E+05 + 1.97100E+02 4.26642E+05 + 1.97200E+02 4.39000E+05 + 1.97300E+02 4.51357E+05 + 1.97400E+02 4.63714E+05 + 1.97500E+02 4.76072E+05 + 1.97600E+02 4.88429E+05 + 1.97700E+02 5.00786E+05 + 1.97800E+02 5.13144E+05 + 1.97900E+02 5.25501E+05 + 1.98000E+02 5.37858E+05 + 1.98100E+02 5.50216E+05 + 1.98200E+02 5.62573E+05 + 1.98300E+02 5.74930E+05 + 1.98400E+02 5.87288E+05 + 1.98500E+02 5.99645E+05 + 1.98600E+02 6.12002E+05 + 1.98700E+02 6.24360E+05 + 1.98800E+02 6.36717E+05 + 1.98900E+02 6.49074E+05 + 1.99000E+02 6.61432E+05 + 1.99100E+02 6.73789E+05 + 1.99200E+02 6.86146E+05 + 1.99300E+02 6.98504E+05 + 1.99400E+02 7.10861E+05 + 1.99500E+02 7.23218E+05 + 1.99600E+02 7.35576E+05 + 1.99700E+02 7.47933E+05 + 1.99800E+02 7.60290E+05 + 1.99900E+02 7.72648E+05 + 2.00000E+02 7.85005E+05 + 2.00100E+02 7.97362E+05 + 2.00200E+02 8.09720E+05 + 2.00300E+02 8.22077E+05 + 2.00400E+02 8.34434E+05 + 2.00500E+02 8.46792E+05 + 2.00600E+02 8.59149E+05 + 2.00700E+02 8.71506E+05 + 2.00800E+02 8.83863E+05 + 2.00900E+02 8.96221E+05 + 2.01000E+02 9.08578E+05 + 2.01100E+02 9.20935E+05 + 2.01200E+02 9.33293E+05 + 2.01300E+02 9.45650E+05 + 2.01400E+02 9.58007E+05 + 2.01500E+02 9.70365E+05 + 2.01600E+02 9.82722E+05 + 2.01700E+02 9.95079E+05 + 2.01800E+02 1.00744E+06 + 2.01900E+02 1.01979E+06 + 2.02000E+02 1.03215E+06 + 2.02100E+02 1.04451E+06 + 2.02200E+02 1.05687E+06 + 2.02300E+02 1.06922E+06 + 2.02400E+02 1.08158E+06 + 2.02500E+02 1.09394E+06 + 2.02600E+02 1.10630E+06 + 2.02700E+02 1.11865E+06 + 2.02800E+02 1.13101E+06 + 2.02900E+02 1.14337E+06 + 2.03000E+02 1.15572E+06 + 2.03100E+02 1.16808E+06 + 2.03200E+02 1.18044E+06 + 2.03300E+02 1.19280E+06 + 2.03400E+02 1.20515E+06 + 2.03500E+02 1.21751E+06 + 2.03600E+02 1.22987E+06 + 2.03700E+02 1.24223E+06 + 2.03800E+02 1.25458E+06 + 2.03900E+02 1.26694E+06 + 2.04000E+02 1.27930E+06 + 2.04100E+02 1.29166E+06 + 2.04200E+02 1.30401E+06 + 2.04300E+02 1.31637E+06 + 2.04400E+02 1.32873E+06 + 2.04500E+02 1.34108E+06 + 2.04600E+02 1.35344E+06 + 2.04700E+02 1.36580E+06 + 2.04800E+02 1.37816E+06 + 2.04900E+02 1.39051E+06 + 2.05000E+02 1.40287E+06 + 2.05100E+02 1.41523E+06 + 2.05200E+02 1.42759E+06 + 2.05300E+02 1.43994E+06 + 2.05400E+02 1.45230E+06 + 2.05500E+02 1.46466E+06 + 2.05600E+02 1.47702E+06 + 2.05700E+02 1.48937E+06 + 2.05800E+02 1.50173E+06 + 2.05900E+02 1.51409E+06 + 2.06000E+02 1.52644E+06 + 2.06100E+02 1.47797E+06 + 2.06200E+02 1.42949E+06 + 2.06300E+02 1.38101E+06 + 2.06400E+02 1.33253E+06 + 2.06500E+02 1.28405E+06 + 2.06600E+02 1.23557E+06 + 2.06700E+02 1.18709E+06 + 2.06800E+02 1.13861E+06 + 2.06900E+02 1.09014E+06 + 2.07000E+02 1.04166E+06 + 2.07100E+02 9.93178E+05 + 2.07200E+02 9.44700E+05 + 2.07300E+02 8.96221E+05 + 2.07400E+02 8.47742E+05 + 2.07500E+02 7.99263E+05 + 2.07600E+02 7.50784E+05 + 2.07700E+02 7.02306E+05 + 2.07800E+02 6.53827E+05 + 2.07900E+02 6.05348E+05 + 2.08000E+02 5.56869E+05 + 2.08100E+02 5.08391E+05 + 2.08200E+02 4.59912E+05 + 2.08300E+02 4.11433E+05 + 2.08400E+02 3.62954E+05 + 2.08500E+02 3.14476E+05 + 2.08600E+02 2.65997E+05 + 2.08700E+02 2.65997E+05 + 2.08800E+02 2.65997E+05 + 2.08900E+02 2.65997E+05 + 2.09000E+02 2.65997E+05 + 2.09100E+02 2.65997E+05 + 2.09200E+02 2.65997E+05 + 2.09300E+02 2.65997E+05 + 2.09400E+02 2.65997E+05 + 2.09500E+02 2.65997E+05 + 2.09600E+02 2.65997E+05 + 2.09700E+02 2.65997E+05 + 2.09800E+02 2.65997E+05 + 2.09900E+02 2.65997E+05 + 2.10000E+02 2.65997E+05 + 2.10100E+02 2.65997E+05 + 2.10200E+02 2.65997E+05 + 2.10300E+02 2.65997E+05 + 2.10400E+02 2.65997E+05 + 2.10500E+02 2.65997E+05 + 2.10600E+02 2.65997E+05 + 2.10700E+02 2.65997E+05 + 2.10800E+02 2.65997E+05 + 2.10900E+02 2.65997E+05 + 2.11000E+02 2.65997E+05 + 2.11100E+02 2.65997E+05 + 2.11200E+02 2.65997E+05 + 2.11300E+02 2.65997E+05 + 2.11400E+02 2.65997E+05 + 2.11500E+02 2.65997E+05 + 2.11600E+02 2.65997E+05 + 2.11700E+02 2.65997E+05 + 2.11800E+02 2.65997E+05 + 2.11900E+02 2.65997E+05 + 2.12000E+02 2.65997E+05 + 2.12100E+02 2.65997E+05 + 2.12200E+02 2.65997E+05 + 2.12300E+02 2.65997E+05 + 2.12400E+02 2.65997E+05 + 2.12500E+02 2.65997E+05 + 2.12600E+02 2.65997E+05 + 2.12700E+02 2.65997E+05 + 2.12800E+02 2.65997E+05 + 2.12900E+02 2.65997E+05 + 2.13000E+02 2.65997E+05 + 2.13100E+02 2.65997E+05 + 2.13200E+02 2.65997E+05 + 2.13300E+02 2.65997E+05 + 2.13400E+02 2.65997E+05 + 2.13500E+02 2.65997E+05 + 2.13600E+02 2.65997E+05 + 2.13700E+02 2.65997E+05 + 2.13800E+02 2.65997E+05 + 2.13900E+02 2.65997E+05 + 2.14000E+02 2.65997E+05 + 2.14100E+02 2.65997E+05 + 2.14200E+02 2.65997E+05 + 2.14300E+02 2.65997E+05 + 2.14400E+02 2.65997E+05 + 2.14500E+02 2.65997E+05 + 2.14600E+02 2.65997E+05 + 2.14700E+02 2.65997E+05 + 2.14800E+02 2.65997E+05 + 2.14900E+02 2.65997E+05 + 2.15000E+02 2.65997E+05 + 2.15100E+02 2.65997E+05 + 2.15200E+02 2.65997E+05 + 2.15300E+02 2.65997E+05 + 2.15400E+02 2.65997E+05 + 2.15500E+02 2.65997E+05 + 2.15600E+02 2.65997E+05 + 2.15700E+02 2.65997E+05 + 2.15800E+02 2.65997E+05 + 2.15900E+02 2.65997E+05 + 2.16000E+02 2.65997E+05 + 2.16100E+02 2.65997E+05 + 2.16200E+02 2.65997E+05 + 2.16300E+02 2.65997E+05 + 2.16400E+02 2.65997E+05 + 2.16500E+02 2.65997E+05 + 2.16600E+02 2.65997E+05 + 2.16700E+02 2.65997E+05 + 2.16800E+02 2.65997E+05 + 2.16900E+02 2.65997E+05 + 2.17000E+02 2.65997E+05 + 2.17100E+02 2.65997E+05 + 2.17200E+02 2.82467E+05 + 2.17300E+02 2.98936E+05 + 2.17400E+02 3.15406E+05 + 2.17500E+02 3.31876E+05 + 2.17600E+02 3.48346E+05 + 2.17700E+02 3.64815E+05 + 2.17800E+02 3.81285E+05 + 2.17900E+02 3.97755E+05 + 2.18000E+02 4.14224E+05 + 2.18100E+02 4.30694E+05 + 2.18200E+02 4.47164E+05 + 2.18300E+02 4.63634E+05 + 2.18400E+02 4.80103E+05 + 2.18500E+02 4.96573E+05 + 2.18600E+02 5.13043E+05 + 2.18700E+02 5.29513E+05 + 2.18800E+02 5.45982E+05 + 2.18900E+02 5.62452E+05 + 2.19000E+02 5.78922E+05 + 2.19100E+02 5.95392E+05 + 2.19200E+02 6.11861E+05 + 2.19300E+02 6.28331E+05 + 2.19400E+02 6.44801E+05 + 2.19500E+02 6.61270E+05 + 2.19600E+02 6.77740E+05 + 2.19700E+02 6.94210E+05 + 2.19800E+02 7.10680E+05 + 2.19900E+02 7.27149E+05 + 2.20000E+02 7.43619E+05 + 2.20100E+02 7.60089E+05 + 2.20200E+02 7.76559E+05 + 2.20300E+02 7.93028E+05 + 2.20400E+02 8.09498E+05 + 2.20500E+02 8.25968E+05 + 2.20600E+02 8.42438E+05 + 2.20700E+02 8.58907E+05 + 2.20800E+02 8.75377E+05 + 2.20900E+02 8.91847E+05 + 2.21000E+02 9.08316E+05 + 2.21100E+02 9.24786E+05 + 2.21200E+02 9.41256E+05 + 2.21300E+02 9.57726E+05 + 2.21400E+02 9.74195E+05 + 2.21500E+02 9.90665E+05 + 2.21600E+02 1.00713E+06 + 2.21700E+02 1.02360E+06 + 2.21800E+02 1.04007E+06 + 2.21900E+02 1.05654E+06 + 2.22000E+02 1.07301E+06 + 2.22100E+02 1.08948E+06 + 2.22200E+02 1.10595E+06 + 2.22300E+02 1.12242E+06 + 2.22400E+02 1.13889E+06 + 2.22500E+02 1.15536E+06 + 2.22600E+02 1.17183E+06 + 2.22700E+02 1.18830E+06 + 2.22800E+02 1.20477E+06 + 2.22900E+02 1.22124E+06 + 2.23000E+02 1.23771E+06 + 2.23100E+02 1.25418E+06 + 2.23200E+02 1.27065E+06 + 2.23300E+02 1.28712E+06 + 2.23400E+02 1.30359E+06 + 2.23500E+02 1.32006E+06 + 2.23600E+02 1.25418E+06 + 2.23700E+02 1.18830E+06 + 2.23800E+02 1.12242E+06 + 2.23900E+02 1.05654E+06 + 2.24000E+02 9.90665E+05 + 2.24100E+02 9.24786E+05 + 2.24200E+02 8.58907E+05 + 2.24300E+02 7.93028E+05 + 2.24400E+02 7.27149E+05 + 2.24500E+02 6.61270E+05 + 2.24600E+02 5.95392E+05 + 2.24700E+02 5.29513E+05 + 2.24800E+02 4.63634E+05 + 2.24900E+02 3.97755E+05 + 2.25000E+02 3.31876E+05 + 2.25100E+02 2.65997E+05 + 2.25200E+02 2.65997E+05 + 2.25300E+02 2.65997E+05 + 2.25400E+02 2.65997E+05 + 2.25500E+02 2.65997E+05 + 2.25600E+02 2.65997E+05 + 2.25700E+02 2.65997E+05 + 2.25800E+02 2.65997E+05 + 2.25900E+02 2.65997E+05 + 2.26000E+02 2.65997E+05 + 2.26100E+02 2.65997E+05 + 2.26200E+02 2.65997E+05 + 2.26300E+02 2.65997E+05 + 2.26400E+02 2.65997E+05 + 2.26500E+02 2.65997E+05 + 2.26600E+02 2.65997E+05 + 2.26700E+02 2.65997E+05 + 2.26800E+02 2.65997E+05 + 2.26900E+02 2.65997E+05 + 2.27000E+02 2.65997E+05 + 2.27100E+02 2.65997E+05 + 2.27200E+02 2.65997E+05 + 2.27300E+02 2.65997E+05 + 2.27400E+02 2.65997E+05 + 2.27500E+02 2.65997E+05 + 2.27600E+02 2.65997E+05 + 2.27700E+02 2.65997E+05 + 2.27800E+02 2.65997E+05 + 2.27900E+02 2.65997E+05 + 2.28000E+02 2.65997E+05 + 2.28100E+02 2.65997E+05 + 2.28200E+02 2.65997E+05 + 2.28300E+02 2.65997E+05 + 2.28400E+02 2.65997E+05 + 2.28500E+02 2.65997E+05 + 2.28600E+02 2.65997E+05 + 2.28700E+02 2.65997E+05 + 2.28800E+02 2.65997E+05 + 2.28900E+02 2.65997E+05 + 2.29000E+02 2.65997E+05 + 2.29100E+02 2.65997E+05 + 2.29200E+02 2.65997E+05 + 2.29300E+02 2.65997E+05 + 2.29400E+02 2.65997E+05 + 2.29500E+02 2.65997E+05 + 2.29600E+02 2.65997E+05 + 2.29700E+02 2.65997E+05 + 2.29800E+02 2.65997E+05 + 2.29900E+02 2.65997E+05 + 2.30000E+02 2.65997E+05 + 2.30100E+02 2.65997E+05 + 2.30200E+02 2.65997E+05 + 2.30300E+02 2.65997E+05 + 2.30400E+02 2.65997E+05 + 2.30500E+02 2.72804E+05 + 2.30600E+02 2.79610E+05 + 2.30700E+02 2.86417E+05 + 2.30800E+02 2.93224E+05 + 2.30900E+02 3.00031E+05 + 2.31000E+02 3.06837E+05 + 2.31100E+02 3.13644E+05 + 2.31200E+02 3.20451E+05 + 2.31300E+02 3.27258E+05 + 2.31400E+02 3.34064E+05 + 2.31500E+02 3.40871E+05 + 2.31600E+02 3.47678E+05 + 2.31700E+02 3.54484E+05 + 2.31800E+02 3.61291E+05 + 2.31900E+02 3.68098E+05 + 2.32000E+02 3.74905E+05 + 2.32100E+02 3.81711E+05 + 2.32200E+02 3.88518E+05 + 2.32300E+02 3.95325E+05 + 2.32400E+02 4.02132E+05 + 2.32500E+02 4.08938E+05 + 2.32600E+02 4.15745E+05 + 2.32700E+02 4.22552E+05 + 2.32800E+02 4.29359E+05 + 2.32900E+02 4.36165E+05 + 2.33000E+02 4.42972E+05 + 2.33100E+02 4.49779E+05 + 2.33200E+02 4.56586E+05 + 2.33300E+02 4.63392E+05 + 2.33400E+02 4.70199E+05 + 2.33500E+02 4.77006E+05 + 2.33600E+02 4.83812E+05 + 2.33700E+02 4.90619E+05 + 2.33800E+02 4.97426E+05 + 2.33900E+02 5.04233E+05 + 2.34000E+02 5.11039E+05 + 2.34100E+02 5.17846E+05 + 2.34200E+02 5.24653E+05 + 2.34300E+02 5.31460E+05 + 2.34400E+02 5.38266E+05 + 2.34500E+02 5.45073E+05 + 2.34600E+02 5.51880E+05 + 2.34700E+02 5.58687E+05 + 2.34800E+02 5.65493E+05 + 2.34900E+02 5.72300E+05 + 2.35000E+02 5.79107E+05 + 2.35100E+02 5.85914E+05 + 2.35200E+02 5.92720E+05 + 2.35300E+02 5.99527E+05 + 2.35400E+02 6.06334E+05 + 2.35500E+02 6.13140E+05 + 2.35600E+02 6.19947E+05 + 2.35700E+02 6.26754E+05 + 2.35800E+02 6.33561E+05 + 2.35900E+02 6.40368E+05 + 2.36000E+02 6.47174E+05 + 2.36100E+02 6.53981E+05 + 2.36200E+02 6.60788E+05 + 2.36300E+02 6.67594E+05 + 2.36400E+02 6.74401E+05 + 2.36500E+02 6.81208E+05 + 2.36600E+02 6.88015E+05 + 2.36700E+02 6.94821E+05 + 2.36800E+02 7.01628E+05 + 2.36900E+02 7.08435E+05 + 2.37000E+02 7.15242E+05 + 2.37100E+02 7.22048E+05 + 2.37200E+02 7.28855E+05 + 2.37300E+02 7.35662E+05 + 2.37400E+02 7.42469E+05 + 2.37500E+02 7.49275E+05 + 2.37600E+02 7.56082E+05 + 2.37700E+02 7.62889E+05 + 2.37800E+02 7.69696E+05 + 2.37900E+02 7.76502E+05 + 2.38000E+02 7.83309E+05 + 2.38100E+02 7.90116E+05 + 2.38200E+02 7.96922E+05 + 2.38300E+02 8.03729E+05 + 2.38400E+02 8.10536E+05 + 2.38500E+02 8.17343E+05 + 2.38600E+02 8.24149E+05 + 2.38700E+02 8.30956E+05 + 2.38800E+02 8.37763E+05 + 2.38900E+02 8.44570E+05 + 2.39000E+02 8.51376E+05 + 2.39100E+02 8.58183E+05 + 2.39200E+02 8.64990E+05 + 2.39300E+02 8.71797E+05 + 2.39400E+02 8.78603E+05 + 2.39500E+02 8.85410E+05 + 2.39600E+02 8.92217E+05 + 2.39700E+02 8.99024E+05 + 2.39800E+02 9.05830E+05 + 2.39900E+02 9.12637E+05 + 2.40000E+02 9.19444E+05 + 2.40100E+02 9.26250E+05 + 2.40200E+02 9.33057E+05 + 2.40300E+02 9.39864E+05 + 2.40400E+02 9.46671E+05 + 2.40500E+02 9.53478E+05 + 2.40600E+02 9.60284E+05 + 2.40700E+02 9.67091E+05 + 2.40800E+02 9.73898E+05 + 2.40900E+02 9.80704E+05 + 2.41000E+02 9.87511E+05 + 2.41100E+02 9.94318E+05 + 2.41200E+02 1.00112E+06 + 2.41300E+02 1.00793E+06 + 2.41400E+02 1.01474E+06 + 2.41500E+02 1.02154E+06 + 2.41600E+02 1.02835E+06 + 2.41700E+02 1.03516E+06 + 2.41800E+02 1.04197E+06 + 2.41900E+02 1.04877E+06 + 2.42000E+02 1.05558E+06 + 2.42100E+02 1.06239E+06 + 2.42200E+02 1.06919E+06 + 2.42300E+02 1.07600E+06 + 2.42400E+02 1.08281E+06 + 2.42500E+02 1.08961E+06 + 2.42600E+02 1.09642E+06 + 2.42700E+02 1.10323E+06 + 2.42800E+02 1.11003E+06 + 2.42900E+02 1.11684E+06 + 2.43000E+02 1.12365E+06 + 2.43100E+02 1.13045E+06 + 2.43200E+02 1.13726E+06 + 2.43300E+02 1.14407E+06 + 2.43400E+02 1.15087E+06 + 2.43500E+02 1.15768E+06 + 2.43600E+02 1.16449E+06 + 2.43700E+02 1.17129E+06 + 2.43800E+02 1.17810E+06 + 2.43900E+02 1.18491E+06 + 2.44000E+02 1.19171E+06 + 2.44100E+02 1.19852E+06 + 2.44200E+02 1.20533E+06 + 2.44300E+02 1.21213E+06 + 2.44400E+02 1.21894E+06 + 2.44500E+02 1.22575E+06 + 2.44600E+02 1.23255E+06 + 2.44700E+02 1.23936E+06 + 2.44800E+02 1.24617E+06 + 2.44900E+02 1.21894E+06 + 2.45000E+02 1.19171E+06 + 2.45100E+02 1.16449E+06 + 2.45200E+02 1.13726E+06 + 2.45300E+02 1.11003E+06 + 2.45400E+02 1.08281E+06 + 2.45500E+02 1.05558E+06 + 2.45600E+02 1.02835E+06 + 2.45700E+02 1.00112E+06 + 2.45800E+02 9.73898E+05 + 2.45900E+02 9.46671E+05 + 2.46000E+02 9.19444E+05 + 2.46100E+02 8.92217E+05 + 2.46200E+02 8.64990E+05 + 2.46300E+02 8.37763E+05 + 2.46400E+02 8.10536E+05 + 2.46500E+02 7.83309E+05 + 2.46600E+02 7.56082E+05 + 2.46700E+02 7.28855E+05 + 2.46800E+02 7.01628E+05 + 2.46900E+02 6.74401E+05 + 2.47000E+02 6.47174E+05 + 2.47100E+02 6.19947E+05 + 2.47200E+02 5.92720E+05 + 2.47300E+02 5.65493E+05 + 2.47400E+02 5.38266E+05 + 2.47500E+02 5.11040E+05 + 2.47600E+02 4.83812E+05 + 2.47700E+02 4.56586E+05 + 2.47800E+02 4.29359E+05 + 2.47900E+02 4.02132E+05 + 2.48000E+02 3.74905E+05 + 2.48100E+02 3.47678E+05 + 2.48200E+02 3.20451E+05 + 2.48300E+02 2.93224E+05 + 2.48400E+02 2.65997E+05 + 2.48500E+02 2.65997E+05 + 2.48600E+02 2.65997E+05 + 2.48700E+02 2.65997E+05 + 2.48800E+02 2.65997E+05 + 2.48900E+02 2.65997E+05 + 2.49000E+02 2.65997E+05 + 2.49100E+02 2.65997E+05 + 2.49200E+02 2.65997E+05 + 2.49300E+02 2.65997E+05 + 2.49400E+02 2.65997E+05 + 2.49500E+02 2.65997E+05 + 2.49600E+02 2.65997E+05 + 2.49700E+02 2.65997E+05 + 2.49800E+02 2.65997E+05 + 2.49900E+02 2.65997E+05 + 2.50000E+02 2.65997E+05 + 2.50100E+02 2.65997E+05 + 2.50200E+02 2.65997E+05 + 2.50300E+02 2.65997E+05 + 2.50400E+02 2.65997E+05 + 2.50500E+02 2.65997E+05 + 2.50600E+02 2.65997E+05 + 2.50700E+02 2.65997E+05 + 2.50800E+02 2.65997E+05 + 2.50900E+02 2.65997E+05 + 2.51000E+02 2.65997E+05 + 2.51100E+02 2.65997E+05 + 2.51200E+02 2.65997E+05 + 2.51300E+02 2.65997E+05 + 2.51400E+02 2.65997E+05 + 2.51500E+02 2.65997E+05 + 2.51600E+02 2.65997E+05 + 2.51700E+02 2.65997E+05 + 2.51800E+02 2.65997E+05 + 2.51900E+02 2.65997E+05 + 2.52000E+02 2.65997E+05 + 2.52100E+02 2.65997E+05 + 2.52200E+02 2.65997E+05 + 2.52300E+02 2.65997E+05 + 2.52400E+02 2.65997E+05 + 2.52500E+02 2.65997E+05 + 2.52600E+02 2.65997E+05 + 2.52700E+02 2.65997E+05 + 2.52800E+02 2.65997E+05 + 2.52900E+02 2.65997E+05 + 2.53000E+02 2.65997E+05 + 2.53100E+02 2.65997E+05 + 2.53200E+02 2.65997E+05 + 2.53300E+02 2.65997E+05 + 2.53400E+02 2.65997E+05 + 2.53500E+02 2.65997E+05 + 2.53600E+02 2.65997E+05 + 2.53700E+02 2.65997E+05 + 2.53800E+02 2.65997E+05 + 2.53900E+02 2.65997E+05 + 2.54000E+02 2.65997E+05 + 2.54100E+02 2.65997E+05 + 2.54200E+02 2.65997E+05 + 2.54300E+02 2.65997E+05 + 2.54400E+02 2.65997E+05 + 2.54500E+02 2.65997E+05 + 2.54600E+02 2.65997E+05 + 2.54700E+02 2.65997E+05 + 2.54800E+02 2.65997E+05 + 2.54900E+02 2.65997E+05 + 2.55000E+02 2.65997E+05 + 2.55100E+02 2.65997E+05 + 2.55200E+02 2.65997E+05 + 2.55300E+02 2.65997E+05 + 2.55400E+02 2.65997E+05 + 2.55500E+02 2.65997E+05 + 2.55600E+02 2.65997E+05 + 2.55700E+02 2.65997E+05 + 2.55800E+02 2.65997E+05 + 2.55900E+02 2.65997E+05 + 2.56000E+02 2.65997E+05 + 2.56100E+02 2.65997E+05 + 2.56200E+02 2.65997E+05 + 2.56300E+02 2.65997E+05 + 2.56400E+02 2.65997E+05 + 2.56500E+02 2.65997E+05 + 2.56600E+02 2.65997E+05 + 2.56700E+02 2.65997E+05 + 2.56800E+02 2.65997E+05 + 2.56900E+02 2.65997E+05 + 2.57000E+02 2.65997E+05 + 2.57100E+02 2.65997E+05 + 2.57200E+02 2.65997E+05 + 2.57300E+02 2.65997E+05 + 2.57400E+02 2.65997E+05 + 2.57500E+02 2.65997E+05 + 2.57600E+02 2.65997E+05 + 2.57700E+02 2.65997E+05 + 2.57800E+02 2.65997E+05 + 2.57900E+02 2.65997E+05 + 2.58000E+02 2.65997E+05 + 2.58100E+02 2.65997E+05 + 2.58200E+02 2.65997E+05 + 2.58300E+02 2.65997E+05 + 2.58400E+02 2.65997E+05 + 2.58500E+02 2.65997E+05 + 2.58600E+02 2.65997E+05 + 2.58700E+02 2.65997E+05 + 2.58800E+02 2.65997E+05 + 2.58900E+02 2.65997E+05 + 2.59000E+02 2.65997E+05 + 2.59100E+02 2.65997E+05 + 2.59200E+02 2.65997E+05 + 2.59300E+02 2.65997E+05 + 2.59400E+02 2.65997E+05 + 2.59500E+02 2.65997E+05 + 2.59600E+02 2.65997E+05 + 2.59700E+02 2.65997E+05 + 2.59800E+02 2.65997E+05 + 2.59900E+02 2.65997E+05 + 2.60000E+02 2.65997E+05 + 2.60100E+02 2.65997E+05 + 2.60200E+02 2.65997E+05 + 2.60300E+02 2.65997E+05 + 2.60400E+02 2.65997E+05 + 2.60500E+02 2.88556E+05 + 2.60600E+02 3.11114E+05 + 2.60700E+02 3.33673E+05 + 2.60800E+02 3.56232E+05 + 2.60900E+02 3.78790E+05 + 2.61000E+02 4.01349E+05 + 2.61100E+02 4.23908E+05 + 2.61200E+02 4.46466E+05 + 2.61300E+02 4.69025E+05 + 2.61400E+02 4.91584E+05 + 2.61500E+02 5.14142E+05 + 2.61600E+02 5.36701E+05 + 2.61700E+02 5.59260E+05 + 2.61800E+02 5.81819E+05 + 2.61900E+02 6.04377E+05 + 2.62000E+02 6.26936E+05 + 2.62100E+02 6.49495E+05 + 2.62200E+02 6.72053E+05 + 2.62300E+02 6.94612E+05 + 2.62400E+02 7.17171E+05 + 2.62500E+02 7.39730E+05 + 2.62600E+02 7.62288E+05 + 2.62700E+02 7.84847E+05 + 2.62800E+02 8.07406E+05 + 2.62900E+02 8.29964E+05 + 2.63000E+02 8.52523E+05 + 2.63100E+02 8.75082E+05 + 2.63200E+02 8.97640E+05 + 2.63300E+02 9.20199E+05 + 2.63400E+02 9.42758E+05 + 2.63500E+02 9.65316E+05 + 2.63600E+02 9.87875E+05 + 2.63700E+02 1.01043E+06 + 2.63800E+02 1.03299E+06 + 2.63900E+02 1.05555E+06 + 2.64000E+02 1.07811E+06 + 2.64100E+02 1.10067E+06 + 2.64200E+02 1.12323E+06 + 2.64300E+02 1.14579E+06 + 2.64400E+02 1.16834E+06 + 2.64500E+02 1.19090E+06 + 2.64600E+02 1.21346E+06 + 2.64700E+02 1.23602E+06 + 2.64800E+02 1.25858E+06 + 2.64900E+02 1.28114E+06 + 2.65000E+02 1.30370E+06 + 2.65100E+02 1.32626E+06 + 2.65200E+02 1.34881E+06 + 2.65300E+02 1.37137E+06 + 2.65400E+02 1.39393E+06 + 2.65500E+02 1.41649E+06 + 2.65600E+02 1.43905E+06 + 2.65700E+02 1.46161E+06 + 2.65800E+02 1.48417E+06 + 2.65900E+02 1.50673E+06 + 2.66000E+02 1.52928E+06 + 2.66100E+02 1.55184E+06 + 2.66200E+02 1.57440E+06 + 2.66300E+02 1.59696E+06 + 2.66400E+02 1.61952E+06 + 2.66500E+02 1.64208E+06 + 2.66600E+02 1.66464E+06 + 2.66700E+02 1.68719E+06 + 2.66800E+02 1.70975E+06 + 2.66900E+02 1.73231E+06 + 2.67000E+02 1.75487E+06 + 2.67100E+02 1.77743E+06 + 2.67200E+02 1.79999E+06 + 2.67300E+02 1.82255E+06 + 2.67400E+02 1.84511E+06 + 2.67500E+02 1.86766E+06 + 2.67600E+02 1.89022E+06 + 2.67700E+02 1.91278E+06 + 2.67800E+02 1.93534E+06 + 2.67900E+02 1.95790E+06 + 2.68000E+02 1.98046E+06 + 2.68100E+02 2.00302E+06 + 2.68200E+02 2.02558E+06 + 2.68300E+02 2.04813E+06 + 2.68400E+02 2.07069E+06 + 2.68500E+02 2.09325E+06 + 2.68600E+02 2.11581E+06 + 2.68700E+02 2.13837E+06 + 2.68800E+02 2.16093E+06 + 2.68900E+02 2.18349E+06 + 2.69000E+02 2.20604E+06 + 2.69100E+02 2.22860E+06 + 2.69200E+02 2.25116E+06 + 2.69300E+02 2.27372E+06 + 2.69400E+02 2.29628E+06 + 2.69500E+02 2.31884E+06 + 2.69600E+02 2.34140E+06 + 2.69700E+02 2.36396E+06 + 2.69800E+02 2.38651E+06 + 2.69900E+02 2.40907E+06 + 2.70000E+02 2.31978E+06 + 2.70100E+02 2.23048E+06 + 2.70200E+02 2.14119E+06 + 2.70300E+02 2.05189E+06 + 2.70400E+02 1.96260E+06 + 2.70500E+02 1.87330E+06 + 2.70600E+02 1.78401E+06 + 2.70700E+02 1.69471E+06 + 2.70800E+02 1.60542E+06 + 2.70900E+02 1.51612E+06 + 2.71000E+02 1.42683E+06 + 2.71100E+02 1.33753E+06 + 2.71200E+02 1.24824E+06 + 2.71300E+02 1.15895E+06 + 2.71400E+02 1.06965E+06 + 2.71500E+02 9.80356E+05 + 2.71600E+02 8.91061E+05 + 2.71700E+02 8.01766E+05 + 2.71800E+02 7.12471E+05 + 2.71900E+02 6.23176E+05 + 2.72000E+02 5.33881E+05 + 2.72100E+02 4.44586E+05 + 2.72200E+02 3.55292E+05 + 2.72300E+02 2.65997E+05 + 2.72400E+02 2.65997E+05 + 2.72500E+02 2.65997E+05 + 2.72600E+02 2.65997E+05 + 2.72700E+02 2.65997E+05 + 2.72800E+02 2.65997E+05 + 2.72900E+02 2.65997E+05 + 2.73000E+02 2.65997E+05 + 2.73100E+02 2.65997E+05 + 2.73200E+02 2.65997E+05 + 2.73300E+02 2.65997E+05 + 2.73400E+02 2.65997E+05 + 2.73500E+02 2.65997E+05 + 2.73600E+02 2.65997E+05 + 2.73700E+02 2.65997E+05 + 2.73800E+02 2.65997E+05 + 2.73900E+02 2.65997E+05 + 2.74000E+02 2.65997E+05 + 2.74100E+02 2.65997E+05 + 2.74200E+02 2.65997E+05 + 2.74300E+02 2.65997E+05 + 2.74400E+02 2.65997E+05 + 2.74500E+02 2.65997E+05 + 2.74600E+02 2.65997E+05 + 2.74700E+02 2.65997E+05 + 2.74800E+02 2.65997E+05 + 2.74900E+02 2.65997E+05 + 2.75000E+02 2.65997E+05 + 2.75100E+02 2.65997E+05 + 2.75200E+02 2.65997E+05 + 2.75300E+02 2.65997E+05 + 2.75400E+02 2.65997E+05 + 2.75500E+02 2.65997E+05 + 2.75600E+02 2.65997E+05 + 2.75700E+02 2.65997E+05 + 2.75800E+02 2.65997E+05 + 2.75900E+02 2.65997E+05 + 2.76000E+02 2.65997E+05 + 2.76100E+02 2.65997E+05 + 2.76200E+02 2.65997E+05 + 2.76300E+02 2.65997E+05 + 2.76400E+02 2.65997E+05 + 2.76500E+02 2.65997E+05 + 2.76600E+02 2.65997E+05 + 2.76700E+02 2.65997E+05 + 2.76800E+02 2.65997E+05 + 2.76900E+02 2.65997E+05 + 2.77000E+02 2.65997E+05 + 2.77100E+02 2.65997E+05 + 2.77200E+02 2.65997E+05 + 2.77300E+02 2.65997E+05 + 2.77400E+02 2.65997E+05 + 2.77500E+02 2.65997E+05 + 2.77600E+02 2.65997E+05 + 2.77700E+02 2.65997E+05 + 2.77800E+02 2.65997E+05 + 2.77900E+02 2.65997E+05 + 2.78000E+02 2.65997E+05 + 2.78100E+02 2.65997E+05 + 2.78200E+02 2.65997E+05 + 2.78300E+02 2.65997E+05 + 2.78400E+02 2.65997E+05 + 2.78500E+02 2.65997E+05 + 2.78600E+02 2.65997E+05 + 2.78700E+02 2.65997E+05 + 2.78800E+02 2.65997E+05 + 2.78900E+02 2.65997E+05 + 2.79000E+02 2.65997E+05 + 2.79100E+02 2.65997E+05 + 2.79200E+02 2.65997E+05 + 2.79300E+02 2.65997E+05 + 2.79400E+02 2.65997E+05 + 2.79500E+02 2.65997E+05 + 2.79600E+02 2.65997E+05 + 2.79700E+02 2.65997E+05 + 2.79800E+02 2.65997E+05 + 2.79900E+02 2.65997E+05 + 2.80000E+02 2.65997E+05 + 2.80100E+02 2.65997E+05 + 2.80200E+02 2.65997E+05 + 2.80300E+02 2.75821E+05 + 2.80400E+02 2.85645E+05 + 2.80500E+02 2.95469E+05 + 2.80600E+02 3.05293E+05 + 2.80700E+02 3.15117E+05 + 2.80800E+02 3.24941E+05 + 2.80900E+02 3.34765E+05 + 2.81000E+02 3.44589E+05 + 2.81100E+02 3.54413E+05 + 2.81200E+02 3.64237E+05 + 2.81300E+02 3.74061E+05 + 2.81400E+02 3.83885E+05 + 2.81500E+02 3.93709E+05 + 2.81600E+02 4.03533E+05 + 2.81700E+02 4.13357E+05 + 2.81800E+02 4.23181E+05 + 2.81900E+02 4.33005E+05 + 2.82000E+02 4.42829E+05 + 2.82100E+02 4.52653E+05 + 2.82200E+02 4.62477E+05 + 2.82300E+02 4.72301E+05 + 2.82400E+02 4.82125E+05 + 2.82500E+02 4.91949E+05 + 2.82600E+02 5.01773E+05 + 2.82700E+02 5.11597E+05 + 2.82800E+02 5.21421E+05 + 2.82900E+02 5.31245E+05 + 2.83000E+02 5.41069E+05 + 2.83100E+02 5.50893E+05 + 2.83200E+02 5.60717E+05 + 2.83300E+02 5.70541E+05 + 2.83400E+02 5.80365E+05 + 2.83500E+02 5.90189E+05 + 2.83600E+02 6.00013E+05 + 2.83700E+02 6.09837E+05 + 2.83800E+02 6.19661E+05 + 2.83900E+02 6.29485E+05 + 2.84000E+02 6.39309E+05 + 2.84100E+02 6.49133E+05 + 2.84200E+02 6.58957E+05 + 2.84300E+02 6.68781E+05 + 2.84400E+02 6.78605E+05 + 2.84500E+02 6.88429E+05 + 2.84600E+02 6.98253E+05 + 2.84700E+02 7.08077E+05 + 2.84800E+02 7.17901E+05 + 2.84900E+02 7.27725E+05 + 2.85000E+02 7.37549E+05 + 2.85100E+02 7.47373E+05 + 2.85200E+02 7.57197E+05 + 2.85300E+02 7.67021E+05 + 2.85400E+02 7.76845E+05 + 2.85500E+02 7.86669E+05 + 2.85600E+02 7.96493E+05 + 2.85700E+02 8.06317E+05 + 2.85800E+02 8.16141E+05 + 2.85900E+02 8.25965E+05 + 2.86000E+02 8.35789E+05 + 2.86100E+02 8.45613E+05 + 2.86200E+02 8.55437E+05 + 2.86300E+02 8.65261E+05 + 2.86400E+02 8.75085E+05 + 2.86500E+02 8.84909E+05 + 2.86600E+02 8.94733E+05 + 2.86700E+02 9.04557E+05 + 2.86800E+02 9.14381E+05 + 2.86900E+02 9.24205E+05 + 2.87000E+02 9.34029E+05 + 2.87100E+02 9.43853E+05 + 2.87200E+02 9.53677E+05 + 2.87300E+02 9.63500E+05 + 2.87400E+02 9.73324E+05 + 2.87500E+02 9.83148E+05 + 2.87600E+02 9.92972E+05 + 2.87700E+02 1.00280E+06 + 2.87800E+02 1.01262E+06 + 2.87900E+02 1.02244E+06 + 2.88000E+02 1.03227E+06 + 2.88100E+02 1.04209E+06 + 2.88200E+02 1.05192E+06 + 2.88300E+02 1.06174E+06 + 2.88400E+02 1.07156E+06 + 2.88500E+02 1.08139E+06 + 2.88600E+02 1.09121E+06 + 2.88700E+02 1.10104E+06 + 2.88800E+02 1.11086E+06 + 2.88900E+02 1.12068E+06 + 2.89000E+02 1.13051E+06 + 2.89100E+02 1.14033E+06 + 2.89200E+02 1.15016E+06 + 2.89300E+02 1.15998E+06 + 2.89400E+02 1.16980E+06 + 2.89500E+02 1.17963E+06 + 2.89600E+02 1.18945E+06 + 2.89700E+02 1.19928E+06 + 2.89800E+02 1.20910E+06 + 2.89900E+02 1.21892E+06 + 2.90000E+02 1.22875E+06 + 2.90100E+02 1.23857E+06 + 2.90200E+02 1.24840E+06 + 2.90300E+02 1.25822E+06 + 2.90400E+02 1.26804E+06 + 2.90500E+02 1.27787E+06 + 2.90600E+02 1.28769E+06 + 2.90700E+02 1.29752E+06 + 2.90800E+02 1.30734E+06 + 2.90900E+02 1.31716E+06 + 2.91000E+02 1.32699E+06 + 2.91100E+02 1.33681E+06 + 2.91200E+02 1.34664E+06 + 2.91300E+02 1.35646E+06 + 2.91400E+02 1.36628E+06 + 2.91500E+02 1.37611E+06 + 2.91600E+02 1.38593E+06 + 2.91700E+02 1.39576E+06 + 2.91800E+02 1.40558E+06 + 2.91900E+02 1.41540E+06 + 2.92000E+02 1.42523E+06 + 2.92100E+02 1.43505E+06 + 2.92200E+02 1.44488E+06 + 2.92300E+02 1.45470E+06 + 2.92400E+02 1.46452E+06 + 2.92500E+02 1.47435E+06 + 2.92600E+02 1.48417E+06 + 2.92700E+02 1.49400E+06 + 2.92800E+02 1.50382E+06 + 2.92900E+02 1.51364E+06 + 2.93000E+02 1.52347E+06 + 2.93100E+02 1.53329E+06 + 2.93200E+02 1.54312E+06 + 2.93300E+02 1.55294E+06 + 2.93400E+02 1.56276E+06 + 2.93500E+02 1.57259E+06 + 2.93600E+02 1.58241E+06 + 2.93700E+02 1.59224E+06 + 2.93800E+02 1.60206E+06 + 2.93900E+02 1.61188E+06 + 2.94000E+02 1.62171E+06 + 2.94100E+02 1.63153E+06 + 2.94200E+02 1.64136E+06 + 2.94300E+02 1.65118E+06 + 2.94400E+02 1.66100E+06 + 2.94500E+02 1.67083E+06 + 2.94600E+02 1.68065E+06 + 2.94700E+02 1.64136E+06 + 2.94800E+02 1.60206E+06 + 2.94900E+02 1.56276E+06 + 2.95000E+02 1.52347E+06 + 2.95100E+02 1.48417E+06 + 2.95200E+02 1.44488E+06 + 2.95300E+02 1.40558E+06 + 2.95400E+02 1.36628E+06 + 2.95500E+02 1.32699E+06 + 2.95600E+02 1.28769E+06 + 2.95700E+02 1.24840E+06 + 2.95800E+02 1.20910E+06 + 2.95900E+02 1.16980E+06 + 2.96000E+02 1.13051E+06 + 2.96100E+02 1.09121E+06 + 2.96200E+02 1.05192E+06 + 2.96300E+02 1.01262E+06 + 2.96400E+02 9.73325E+05 + 2.96500E+02 9.34029E+05 + 2.96600E+02 8.94733E+05 + 2.96700E+02 8.55437E+05 + 2.96800E+02 8.16141E+05 + 2.96900E+02 7.76845E+05 + 2.97000E+02 7.37549E+05 + 2.97100E+02 6.98253E+05 + 2.97200E+02 6.58957E+05 + 2.97300E+02 6.19661E+05 + 2.97400E+02 5.80365E+05 + 2.97500E+02 5.41069E+05 + 2.97600E+02 5.01773E+05 + 2.97700E+02 4.62477E+05 + 2.97800E+02 4.23181E+05 + 2.97900E+02 3.83885E+05 + 2.98000E+02 3.44589E+05 + 2.98100E+02 3.05293E+05 + 2.98200E+02 2.65997E+05 + 2.98300E+02 2.65997E+05 + 2.98400E+02 2.65997E+05 + 2.98500E+02 2.65997E+05 + 2.98600E+02 2.65997E+05 + 2.98700E+02 2.65997E+05 + 2.98800E+02 2.65997E+05 + 2.98900E+02 2.65997E+05 + 2.99000E+02 2.65997E+05 + 2.99100E+02 2.65997E+05 + 2.99200E+02 2.65997E+05 + 2.99300E+02 2.65997E+05 + 2.99400E+02 2.65997E+05 + 2.99500E+02 2.65997E+05 + 2.99600E+02 2.65997E+05 + 2.99700E+02 2.65997E+05 + 2.99800E+02 2.65997E+05 + 2.99900E+02 2.65997E+05 + 3.00000E+02 2.65997E+05 + 3.00100E+02 2.65997E+05 + 3.00200E+02 2.65997E+05 + 3.00300E+02 2.65997E+05 + 3.00400E+02 2.65997E+05 + 3.00500E+02 2.65997E+05 + 3.00600E+02 2.65997E+05 + 3.00700E+02 2.65997E+05 + 3.00800E+02 2.65997E+05 + 3.00900E+02 2.65997E+05 + 3.01000E+02 2.65997E+05 + 3.01100E+02 2.65997E+05 + 3.01200E+02 2.65997E+05 + 3.01300E+02 2.65997E+05 + 3.01400E+02 2.65997E+05 + 3.01500E+02 2.65997E+05 + 3.01600E+02 2.65997E+05 + 3.01700E+02 2.65997E+05 + 3.01800E+02 2.65997E+05 + 3.01900E+02 2.65997E+05 + 3.02000E+02 2.65997E+05 + 3.02100E+02 2.65997E+05 + 3.02200E+02 2.65997E+05 + 3.02300E+02 2.65997E+05 + 3.02400E+02 2.65997E+05 + 3.02500E+02 2.65997E+05 + 3.02600E+02 2.65997E+05 + 3.02700E+02 2.65997E+05 + 3.02800E+02 2.65997E+05 + 3.02900E+02 2.65997E+05 + 3.03000E+02 2.65997E+05 + 3.03100E+02 2.65997E+05 + 3.03200E+02 2.65997E+05 + 3.03300E+02 2.65997E+05 + 3.03400E+02 2.65997E+05 + 3.03500E+02 2.65997E+05 + 3.03600E+02 2.65997E+05 + 3.03700E+02 2.65997E+05 + 3.03800E+02 2.65997E+05 + 3.03900E+02 2.65997E+05 + 3.04000E+02 2.65997E+05 + 3.04100E+02 2.65997E+05 + 3.04200E+02 2.65997E+05 + 3.04300E+02 2.65997E+05 + 3.04400E+02 2.65997E+05 + 3.04500E+02 2.65997E+05 + 3.04600E+02 2.65997E+05 + 3.04700E+02 2.65997E+05 + 3.04800E+02 2.65997E+05 + 3.04900E+02 2.65997E+05 + 3.05000E+02 2.65997E+05 + 3.05100E+02 2.65997E+05 + 3.05200E+02 2.65997E+05 + 3.05300E+02 2.65997E+05 + 3.05400E+02 2.65997E+05 + 3.05500E+02 2.65997E+05 + 3.05600E+02 2.65997E+05 + 3.05700E+02 2.65997E+05 + 3.05800E+02 2.65997E+05 + 3.05900E+02 2.65997E+05 + 3.06000E+02 2.65997E+05 + 3.06100E+02 2.65997E+05 + 3.06200E+02 2.65997E+05 + 3.06300E+02 2.65997E+05 + 3.06400E+02 2.65997E+05 + 3.06500E+02 2.65997E+05 + 3.06600E+02 2.65997E+05 + 3.06700E+02 2.65997E+05 + 3.06800E+02 2.65997E+05 + 3.06900E+02 2.65997E+05 + 3.07000E+02 2.65997E+05 + 3.07100E+02 2.65997E+05 + 3.07200E+02 2.65997E+05 + 3.07300E+02 2.65997E+05 + 3.07400E+02 2.65997E+05 + 3.07500E+02 2.65997E+05 + 3.07600E+02 2.65997E+05 + 3.07700E+02 2.65997E+05 + 3.07800E+02 2.65997E+05 + 3.07900E+02 2.65997E+05 + 3.08000E+02 2.65997E+05 + 3.08100E+02 2.65997E+05 + 3.08200E+02 2.65997E+05 + 3.08300E+02 2.65997E+05 + 3.08400E+02 2.65997E+05 + 3.08500E+02 2.65997E+05 + 3.08600E+02 2.65997E+05 + 3.08700E+02 2.65997E+05 + 3.08800E+02 2.65997E+05 + 3.08900E+02 2.65997E+05 + 3.09000E+02 2.65997E+05 + 3.09100E+02 2.65997E+05 + 3.09200E+02 2.65997E+05 + 3.09300E+02 2.65997E+05 + 3.09400E+02 2.65997E+05 + 3.09500E+02 2.65997E+05 + 3.09600E+02 2.65997E+05 + 3.09700E+02 2.65997E+05 + 3.09800E+02 2.65997E+05 + 3.09900E+02 2.65997E+05 + 3.10000E+02 2.65997E+05 + 3.10100E+02 2.65997E+05 + 3.10200E+02 2.65997E+05 + 3.10300E+02 2.76893E+05 + 3.10400E+02 2.87789E+05 + 3.10500E+02 2.98685E+05 + 3.10600E+02 3.09581E+05 + 3.10700E+02 3.20477E+05 + 3.10800E+02 3.31373E+05 + 3.10900E+02 3.42269E+05 + 3.11000E+02 3.53165E+05 + 3.11100E+02 3.64061E+05 + 3.11200E+02 3.74957E+05 + 3.11300E+02 3.85853E+05 + 3.11400E+02 3.96749E+05 + 3.11500E+02 4.07645E+05 + 3.11600E+02 4.18541E+05 + 3.11700E+02 4.29437E+05 + 3.11800E+02 4.40333E+05 + 3.11900E+02 4.51229E+05 + 3.12000E+02 4.62125E+05 + 3.12100E+02 4.73021E+05 + 3.12200E+02 4.83918E+05 + 3.12300E+02 4.94814E+05 + 3.12400E+02 5.05710E+05 + 3.12500E+02 5.16606E+05 + 3.12600E+02 5.27502E+05 + 3.12700E+02 5.38398E+05 + 3.12800E+02 5.49294E+05 + 3.12900E+02 5.60190E+05 + 3.13000E+02 5.71086E+05 + 3.13100E+02 5.81982E+05 + 3.13200E+02 5.92878E+05 + 3.13300E+02 6.03774E+05 + 3.13400E+02 6.14670E+05 + 3.13500E+02 6.25566E+05 + 3.13600E+02 6.36462E+05 + 3.13700E+02 6.47358E+05 + 3.13800E+02 6.58254E+05 + 3.13900E+02 6.69150E+05 + 3.14000E+02 6.80046E+05 + 3.14100E+02 6.90942E+05 + 3.14200E+02 7.01838E+05 + 3.14300E+02 7.12734E+05 + 3.14400E+02 7.23630E+05 + 3.14500E+02 7.34526E+05 + 3.14600E+02 7.45422E+05 + 3.14700E+02 7.56318E+05 + 3.14800E+02 7.67214E+05 + 3.14900E+02 7.78110E+05 + 3.15000E+02 7.89006E+05 + 3.15100E+02 7.99902E+05 + 3.15200E+02 8.10798E+05 + 3.15300E+02 8.21694E+05 + 3.15400E+02 8.32591E+05 + 3.15500E+02 8.43487E+05 + 3.15600E+02 8.54383E+05 + 3.15700E+02 8.65279E+05 + 3.15800E+02 8.76175E+05 + 3.15900E+02 8.87071E+05 + 3.16000E+02 8.97967E+05 + 3.16100E+02 9.08863E+05 + 3.16200E+02 9.19759E+05 + 3.16300E+02 9.30655E+05 + 3.16400E+02 9.41551E+05 + 3.16500E+02 9.52447E+05 + 3.16600E+02 9.63343E+05 + 3.16700E+02 9.74239E+05 + 3.16800E+02 9.85135E+05 + 3.16900E+02 9.96031E+05 + 3.17000E+02 1.00693E+06 + 3.17100E+02 1.01782E+06 + 3.17200E+02 1.02872E+06 + 3.17300E+02 1.03962E+06 + 3.17400E+02 1.05051E+06 + 3.17500E+02 1.06141E+06 + 3.17600E+02 1.07230E+06 + 3.17700E+02 1.08320E+06 + 3.17800E+02 1.09410E+06 + 3.17900E+02 1.10499E+06 + 3.18000E+02 1.11589E+06 + 3.18100E+02 1.12678E+06 + 3.18200E+02 1.13768E+06 + 3.18300E+02 1.14858E+06 + 3.18400E+02 1.15947E+06 + 3.18500E+02 1.17037E+06 + 3.18600E+02 1.18126E+06 + 3.18700E+02 1.19216E+06 + 3.18800E+02 1.20306E+06 + 3.18900E+02 1.21395E+06 + 3.19000E+02 1.22485E+06 + 3.19100E+02 1.23574E+06 + 3.19200E+02 1.24664E+06 + 3.19300E+02 1.25754E+06 + 3.19400E+02 1.26843E+06 + 3.19500E+02 1.27933E+06 + 3.19600E+02 1.29022E+06 + 3.19700E+02 1.30112E+06 + 3.19800E+02 1.31202E+06 + 3.19900E+02 1.32291E+06 + 3.20000E+02 1.33381E+06 + 3.20100E+02 1.34470E+06 + 3.20200E+02 1.35560E+06 + 3.20300E+02 1.36650E+06 + 3.20400E+02 1.37739E+06 + 3.20500E+02 1.38829E+06 + 3.20600E+02 1.39918E+06 + 3.20700E+02 1.41008E+06 + 3.20800E+02 1.42098E+06 + 3.20900E+02 1.37820E+06 + 3.21000E+02 1.33542E+06 + 3.21100E+02 1.29265E+06 + 3.21200E+02 1.24987E+06 + 3.21300E+02 1.20709E+06 + 3.21400E+02 1.16431E+06 + 3.21500E+02 1.12154E+06 + 3.21600E+02 1.07876E+06 + 3.21700E+02 1.03598E+06 + 3.21800E+02 9.93206E+05 + 3.21900E+02 9.50429E+05 + 3.22000E+02 9.07652E+05 + 3.22100E+02 8.64875E+05 + 3.22200E+02 8.22098E+05 + 3.22300E+02 7.79321E+05 + 3.22400E+02 7.36544E+05 + 3.22500E+02 6.93767E+05 + 3.22600E+02 6.50990E+05 + 3.22700E+02 6.08213E+05 + 3.22800E+02 5.65436E+05 + 3.22900E+02 5.22659E+05 + 3.23000E+02 4.79882E+05 + 3.23100E+02 4.37105E+05 + 3.23200E+02 3.94328E+05 + 3.23300E+02 3.51551E+05 + 3.23400E+02 3.08774E+05 + 3.23500E+02 2.65997E+05 + 3.23600E+02 2.65997E+05 + 3.23700E+02 2.65997E+05 + 3.23800E+02 2.65997E+05 + 3.23900E+02 2.65997E+05 + 3.24000E+02 2.65997E+05 + 3.24100E+02 2.65997E+05 + 3.24200E+02 2.65997E+05 + 3.24300E+02 2.65997E+05 + 3.24400E+02 2.65997E+05 + 3.24500E+02 2.65997E+05 + 3.24600E+02 2.65997E+05 + 3.24700E+02 2.65997E+05 + 3.24800E+02 2.65997E+05 + 3.24900E+02 2.65997E+05 + 3.25000E+02 2.65997E+05 + 3.25100E+02 2.65997E+05 + 3.25200E+02 2.65997E+05 + 3.25300E+02 2.65997E+05 + 3.25400E+02 2.65997E+05 + 3.25500E+02 2.65997E+05 + 3.25600E+02 2.65997E+05 + 3.25700E+02 2.65997E+05 + 3.25800E+02 2.65997E+05 + 3.25900E+02 2.65997E+05 + 3.26000E+02 2.65997E+05 + 3.26100E+02 2.65997E+05 + 3.26200E+02 2.65997E+05 + 3.26300E+02 2.65997E+05 + 3.26400E+02 2.65997E+05 + 3.26500E+02 2.65997E+05 + 3.26600E+02 2.65997E+05 + 3.26700E+02 2.65997E+05 + 3.26800E+02 2.65997E+05 + 3.26900E+02 2.65997E+05 + 3.27000E+02 2.65997E+05 + 3.27100E+02 2.65997E+05 + 3.27200E+02 2.65997E+05 + 3.27300E+02 2.65997E+05 + 3.27400E+02 2.65997E+05 + 3.27500E+02 2.65997E+05 + 3.27600E+02 2.65997E+05 + 3.27700E+02 2.65997E+05 + 3.27800E+02 2.65997E+05 + 3.27900E+02 2.65997E+05 + 3.28000E+02 2.65997E+05 + 3.28100E+02 2.65997E+05 + 3.28200E+02 2.65997E+05 + 3.28300E+02 2.65997E+05 + 3.28400E+02 2.65997E+05 + 3.28500E+02 2.65997E+05 + 3.28600E+02 2.65997E+05 + 3.28700E+02 2.65997E+05 + 3.28800E+02 2.65997E+05 + 3.28900E+02 2.65997E+05 + 3.29000E+02 2.65997E+05 + 3.29100E+02 2.65997E+05 + 3.29200E+02 2.65997E+05 + 3.29300E+02 2.65997E+05 + 3.29400E+02 2.65997E+05 + 3.29500E+02 2.65997E+05 + 3.29600E+02 2.65997E+05 + 3.29700E+02 2.65997E+05 + 3.29800E+02 2.65997E+05 + 3.29900E+02 2.65997E+05 + 3.30000E+02 2.65997E+05 + 3.30100E+02 2.65997E+05 + 3.30200E+02 2.65997E+05 + 3.30300E+02 2.65997E+05 + 3.30400E+02 2.65997E+05 + 3.30500E+02 2.65997E+05 + 3.30600E+02 2.65997E+05 + 3.30700E+02 2.65997E+05 + 3.30800E+02 2.65997E+05 + 3.30900E+02 2.65997E+05 + 3.31000E+02 2.65997E+05 + 3.31100E+02 2.65997E+05 + 3.31200E+02 2.65997E+05 + 3.31300E+02 2.65997E+05 + 3.31400E+02 2.65997E+05 + 3.31500E+02 2.65997E+05 + 3.31600E+02 2.65997E+05 + 3.31700E+02 2.65997E+05 + 3.31800E+02 2.65997E+05 + 3.31900E+02 2.65997E+05 + 3.32000E+02 2.65997E+05 + 3.32100E+02 2.65997E+05 + 3.32200E+02 2.65997E+05 + 3.32300E+02 2.65997E+05 + 3.32400E+02 2.65997E+05 + 3.32500E+02 2.78890E+05 + 3.32600E+02 2.91783E+05 + 3.32700E+02 3.04676E+05 + 3.32800E+02 3.17570E+05 + 3.32900E+02 3.30463E+05 + 3.33000E+02 3.43356E+05 + 3.33100E+02 3.56249E+05 + 3.33200E+02 3.69142E+05 + 3.33300E+02 3.82035E+05 + 3.33400E+02 3.94929E+05 + 3.33500E+02 4.07822E+05 + 3.33600E+02 4.20715E+05 + 3.33700E+02 4.33608E+05 + 3.33800E+02 4.46501E+05 + 3.33900E+02 4.59394E+05 + 3.34000E+02 4.72288E+05 + 3.34100E+02 4.85181E+05 + 3.34200E+02 4.98074E+05 + 3.34300E+02 5.10967E+05 + 3.34400E+02 5.23860E+05 + 3.34500E+02 5.36753E+05 + 3.34600E+02 5.49647E+05 + 3.34700E+02 5.62540E+05 + 3.34800E+02 5.75433E+05 + 3.34900E+02 5.88326E+05 + 3.35000E+02 6.01219E+05 + 3.35100E+02 6.14112E+05 + 3.35200E+02 6.27006E+05 + 3.35300E+02 6.39899E+05 + 3.35400E+02 6.52792E+05 + 3.35500E+02 6.65685E+05 + 3.35600E+02 6.78578E+05 + 3.35700E+02 6.91471E+05 + 3.35800E+02 7.04365E+05 + 3.35900E+02 7.17258E+05 + 3.36000E+02 7.30151E+05 + 3.36100E+02 7.43044E+05 + 3.36200E+02 7.55937E+05 + 3.36300E+02 7.68830E+05 + 3.36400E+02 7.81724E+05 + 3.36500E+02 7.94617E+05 + 3.36600E+02 8.07510E+05 + 3.36700E+02 8.20403E+05 + 3.36800E+02 8.33296E+05 + 3.36900E+02 8.46190E+05 + 3.37000E+02 8.59083E+05 + 3.37100E+02 8.71976E+05 + 3.37200E+02 8.84869E+05 + 3.37300E+02 8.97762E+05 + 3.37400E+02 9.10655E+05 + 3.37500E+02 9.23548E+05 + 3.37600E+02 9.36442E+05 + 3.37700E+02 9.49335E+05 + 3.37800E+02 9.62228E+05 + 3.37900E+02 9.75121E+05 + 3.38000E+02 9.88014E+05 + 3.38100E+02 1.00091E+06 + 3.38200E+02 1.01380E+06 + 3.38300E+02 1.02669E+06 + 3.38400E+02 1.03959E+06 + 3.38500E+02 1.05248E+06 + 3.38600E+02 1.06537E+06 + 3.38700E+02 1.07827E+06 + 3.38800E+02 1.09116E+06 + 3.38900E+02 1.10405E+06 + 3.39000E+02 1.11695E+06 + 3.39100E+02 1.12984E+06 + 3.39200E+02 1.14273E+06 + 3.39300E+02 1.15563E+06 + 3.39400E+02 1.16852E+06 + 3.39500E+02 1.18141E+06 + 3.39600E+02 1.19430E+06 + 3.39700E+02 1.20720E+06 + 3.39800E+02 1.22009E+06 + 3.39900E+02 1.23298E+06 + 3.40000E+02 1.24588E+06 + 3.40100E+02 1.25877E+06 + 3.40200E+02 1.27166E+06 + 3.40300E+02 1.28456E+06 + 3.40400E+02 1.29745E+06 + 3.40500E+02 1.31034E+06 + 3.40600E+02 1.32324E+06 + 3.40700E+02 1.33613E+06 + 3.40800E+02 1.34902E+06 + 3.40900E+02 1.36192E+06 + 3.41000E+02 1.37481E+06 + 3.41100E+02 1.38770E+06 + 3.41200E+02 1.40060E+06 + 3.41300E+02 1.41349E+06 + 3.41400E+02 1.42638E+06 + 3.41500E+02 1.43928E+06 + 3.41600E+02 1.45217E+06 + 3.41700E+02 1.46506E+06 + 3.41800E+02 1.47795E+06 + 3.41900E+02 1.49085E+06 + 3.42000E+02 1.50374E+06 + 3.42100E+02 1.51663E+06 + 3.42200E+02 1.52953E+06 + 3.42300E+02 1.54242E+06 + 3.42400E+02 1.55531E+06 + 3.42500E+02 1.56821E+06 + 3.42600E+02 1.58110E+06 + 3.42700E+02 1.59399E+06 + 3.42800E+02 1.60689E+06 + 3.42900E+02 1.61978E+06 + 3.43000E+02 1.63267E+06 + 3.43100E+02 1.64557E+06 + 3.43200E+02 1.65846E+06 + 3.43300E+02 1.67135E+06 + 3.43400E+02 1.68425E+06 + 3.43500E+02 1.69714E+06 + 3.43600E+02 1.71003E+06 + 3.43700E+02 1.72292E+06 + 3.43800E+02 1.73582E+06 + 3.43900E+02 1.74871E+06 + 3.44000E+02 1.76160E+06 + 3.44100E+02 1.77450E+06 + 3.44200E+02 1.78739E+06 + 3.44300E+02 1.80028E+06 + 3.44400E+02 1.81318E+06 + 3.44500E+02 1.82607E+06 + 3.44600E+02 1.83896E+06 + 3.44700E+02 1.85186E+06 + 3.44800E+02 1.86475E+06 + 3.44900E+02 1.87764E+06 + 3.45000E+02 1.89054E+06 + 3.45100E+02 1.90343E+06 + 3.45200E+02 1.91632E+06 + 3.45300E+02 1.92922E+06 + 3.45400E+02 1.94211E+06 + 3.45500E+02 1.95500E+06 + 3.45600E+02 1.96790E+06 + 3.45700E+02 1.98079E+06 + 3.45800E+02 1.99368E+06 + 3.45900E+02 2.00657E+06 + 3.46000E+02 2.01947E+06 + 3.46100E+02 2.03236E+06 + 3.46200E+02 2.04525E+06 + 3.46300E+02 2.05815E+06 + 3.46400E+02 2.07104E+06 + 3.46500E+02 2.08393E+06 + 3.46600E+02 2.09683E+06 + 3.46700E+02 2.10972E+06 + 3.46800E+02 2.12261E+06 + 3.46900E+02 2.07104E+06 + 3.47000E+02 2.01947E+06 + 3.47100E+02 1.96790E+06 + 3.47200E+02 1.91632E+06 + 3.47300E+02 1.86475E+06 + 3.47400E+02 1.81318E+06 + 3.47500E+02 1.76160E+06 + 3.47600E+02 1.71003E+06 + 3.47700E+02 1.65846E+06 + 3.47800E+02 1.60689E+06 + 3.47900E+02 1.55531E+06 + 3.48000E+02 1.50374E+06 + 3.48100E+02 1.45217E+06 + 3.48200E+02 1.40060E+06 + 3.48300E+02 1.34902E+06 + 3.48400E+02 1.29745E+06 + 3.48500E+02 1.24588E+06 + 3.48600E+02 1.19430E+06 + 3.48700E+02 1.14273E+06 + 3.48800E+02 1.09116E+06 + 3.48900E+02 1.03959E+06 + 3.49000E+02 9.88014E+05 + 3.49100E+02 9.36442E+05 + 3.49200E+02 8.84869E+05 + 3.49300E+02 8.33296E+05 + 3.49400E+02 7.81724E+05 + 3.49500E+02 7.30151E+05 + 3.49600E+02 6.78578E+05 + 3.49700E+02 6.27006E+05 + 3.49800E+02 5.75433E+05 + 3.49900E+02 5.23860E+05 + 3.50000E+02 4.72288E+05 + 3.50100E+02 4.20715E+05 + 3.50200E+02 3.69142E+05 + 3.50300E+02 3.17570E+05 + 3.50400E+02 2.65997E+05 + 3.50500E+02 2.65997E+05 + 3.50600E+02 2.65997E+05 + 3.50700E+02 2.65997E+05 + 3.50800E+02 2.65997E+05 + 3.50900E+02 2.65997E+05 + 3.51000E+02 2.65997E+05 + 3.51100E+02 2.65997E+05 + 3.51200E+02 2.65997E+05 + 3.51300E+02 2.65997E+05 + 3.51400E+02 2.65997E+05 + 3.51500E+02 2.65997E+05 + 3.51600E+02 2.65997E+05 + 3.51700E+02 2.65997E+05 + 3.51800E+02 2.65997E+05 + 3.51900E+02 2.65997E+05 + 3.52000E+02 2.65997E+05 + 3.52100E+02 2.65997E+05 + 3.52200E+02 2.65997E+05 + 3.52300E+02 2.65997E+05 + 3.52400E+02 2.65997E+05 + 3.52500E+02 2.65997E+05 + 3.52600E+02 2.65997E+05 + 3.52700E+02 2.65997E+05 + 3.52800E+02 2.65997E+05 + 3.52900E+02 2.65997E+05 + 3.53000E+02 2.65997E+05 + 3.53100E+02 2.65997E+05 + 3.53200E+02 2.65997E+05 + 3.53300E+02 2.65997E+05 + 3.53400E+02 2.65997E+05 + 3.53500E+02 2.65997E+05 + 3.53600E+02 2.65997E+05 + 3.53700E+02 2.65997E+05 + 3.53800E+02 2.65997E+05 + 3.53900E+02 2.65997E+05 + 3.54000E+02 2.65997E+05 + 3.54100E+02 2.65997E+05 + 3.54200E+02 2.65997E+05 + 3.54300E+02 2.65997E+05 + 3.54400E+02 2.65997E+05 + 3.54500E+02 2.65997E+05 + 3.54600E+02 2.65997E+05 + 3.54700E+02 2.65997E+05 + 3.54800E+02 2.65997E+05 + 3.54900E+02 2.65997E+05 + 3.55000E+02 2.65997E+05 + 3.55100E+02 2.65997E+05 + 3.55200E+02 2.65997E+05 + 3.55300E+02 2.65997E+05 + 3.55400E+02 2.65997E+05 + 3.55500E+02 2.65997E+05 + 3.55600E+02 2.65997E+05 + 3.55700E+02 2.65997E+05 + 3.55800E+02 2.65997E+05 + 3.55900E+02 2.65997E+05 + 3.56000E+02 2.65997E+05 + 3.56100E+02 2.65997E+05 + 3.56200E+02 2.65997E+05 + 3.56300E+02 2.65997E+05 + 3.56400E+02 2.65997E+05 + 3.56500E+02 2.65997E+05 + 3.56600E+02 2.65997E+05 + 3.56700E+02 2.65997E+05 + 3.56800E+02 2.65997E+05 + 3.56900E+02 2.65997E+05 + 3.57000E+02 2.65997E+05 + 3.57100E+02 2.65997E+05 + 3.57200E+02 2.65997E+05 + 3.57300E+02 2.65997E+05 + 3.57400E+02 2.65997E+05 + 3.57500E+02 2.65997E+05 + 3.57600E+02 2.65997E+05 + 3.57700E+02 2.65997E+05 + 3.57800E+02 2.65997E+05 + 3.57900E+02 2.65997E+05 + 3.58000E+02 2.65997E+05 + 3.58100E+02 2.65997E+05 + 3.58200E+02 2.65997E+05 + 3.58300E+02 2.65997E+05 + 3.58400E+02 2.65997E+05 + 3.58500E+02 2.65997E+05 + 3.58600E+02 2.65997E+05 + 3.58700E+02 2.65997E+05 + 3.58800E+02 2.65997E+05 + 3.58900E+02 2.65997E+05 + 3.59000E+02 2.65997E+05 + 3.59100E+02 2.65997E+05 + 3.59200E+02 2.65997E+05 + 3.59300E+02 2.65997E+05 + 3.59400E+02 2.65997E+05 + 3.59500E+02 2.65997E+05 + 3.59600E+02 2.65997E+05 + 3.59700E+02 2.65997E+05 + 3.59800E+02 2.65997E+05 + 3.59900E+02 2.65997E+05 + 3.60000E+02 2.65997E+05 + 3.60100E+02 2.65997E+05 + 3.60200E+02 2.65997E+05 + 3.60300E+02 2.65997E+05 + 3.60400E+02 2.65997E+05 + 3.60500E+02 2.65997E+05 + 3.60600E+02 2.65997E+05 + 3.60700E+02 2.65997E+05 + 3.60800E+02 2.65997E+05 + 3.60900E+02 2.65997E+05 + 3.61000E+02 2.65997E+05 + 3.61100E+02 2.65997E+05 + 3.61200E+02 2.65997E+05 + 3.61300E+02 2.65997E+05 + 3.61400E+02 2.65997E+05 + 3.61500E+02 2.65997E+05 + 3.61600E+02 2.65997E+05 + 3.61700E+02 2.65997E+05 + 3.61800E+02 2.65997E+05 + 3.61900E+02 2.65997E+05 + 3.62000E+02 2.65997E+05 + 3.62100E+02 2.65997E+05 + 3.62200E+02 2.65997E+05 + 3.62300E+02 2.65997E+05 + 3.62400E+02 2.65997E+05 + 3.62500E+02 2.74453E+05 + 3.62600E+02 2.82909E+05 + 3.62700E+02 2.91365E+05 + 3.62800E+02 2.99822E+05 + 3.62900E+02 3.08278E+05 + 3.63000E+02 3.16734E+05 + 3.63100E+02 3.25190E+05 + 3.63200E+02 3.33646E+05 + 3.63300E+02 3.42103E+05 + 3.63400E+02 3.50559E+05 + 3.63500E+02 3.59015E+05 + 3.63600E+02 3.67471E+05 + 3.63700E+02 3.75927E+05 + 3.63800E+02 3.84383E+05 + 3.63900E+02 3.92840E+05 + 3.64000E+02 4.01296E+05 + 3.64100E+02 4.09752E+05 + 3.64200E+02 4.18208E+05 + 3.64300E+02 4.26664E+05 + 3.64400E+02 4.35121E+05 + 3.64500E+02 4.43577E+05 + 3.64600E+02 4.52033E+05 + 3.64700E+02 4.60489E+05 + 3.64800E+02 4.68945E+05 + 3.64900E+02 4.77402E+05 + 3.65000E+02 4.85858E+05 + 3.65100E+02 4.94314E+05 + 3.65200E+02 5.02770E+05 + 3.65300E+02 5.11226E+05 + 3.65400E+02 5.19682E+05 + 3.65500E+02 5.28139E+05 + 3.65600E+02 5.36595E+05 + 3.65700E+02 5.45051E+05 + 3.65800E+02 5.53507E+05 + 3.65900E+02 5.61963E+05 + 3.66000E+02 5.70420E+05 + 3.66100E+02 5.78876E+05 + 3.66200E+02 5.87332E+05 + 3.66300E+02 5.95788E+05 + 3.66400E+02 6.04244E+05 + 3.66500E+02 6.12700E+05 + 3.66600E+02 6.21157E+05 + 3.66700E+02 6.29613E+05 + 3.66800E+02 6.38069E+05 + 3.66900E+02 6.46525E+05 + 3.67000E+02 6.54982E+05 + 3.67100E+02 6.63438E+05 + 3.67200E+02 6.71894E+05 + 3.67300E+02 6.80350E+05 + 3.67400E+02 6.88806E+05 + 3.67500E+02 6.97262E+05 + 3.67600E+02 7.05719E+05 + 3.67700E+02 7.14175E+05 + 3.67800E+02 7.22631E+05 + 3.67900E+02 7.31087E+05 + 3.68000E+02 7.39543E+05 + 3.68100E+02 7.48000E+05 + 3.68200E+02 7.56456E+05 + 3.68300E+02 7.64912E+05 + 3.68400E+02 7.73368E+05 + 3.68500E+02 7.81824E+05 + 3.68600E+02 7.90280E+05 + 3.68700E+02 7.98737E+05 + 3.68800E+02 8.07193E+05 + 3.68900E+02 8.15649E+05 + 3.69000E+02 8.24105E+05 + 3.69100E+02 8.32561E+05 + 3.69200E+02 8.41018E+05 + 3.69300E+02 8.49474E+05 + 3.69400E+02 8.57930E+05 + 3.69500E+02 8.66386E+05 + 3.69600E+02 8.74842E+05 + 3.69700E+02 8.83298E+05 + 3.69800E+02 8.91755E+05 + 3.69900E+02 9.00211E+05 + 3.70000E+02 9.08667E+05 + 3.70100E+02 9.17123E+05 + 3.70200E+02 9.25580E+05 + 3.70300E+02 9.34036E+05 + 3.70400E+02 9.42492E+05 + 3.70500E+02 9.50948E+05 + 3.70600E+02 9.59404E+05 + 3.70700E+02 9.67860E+05 + 3.70800E+02 9.76317E+05 + 3.70900E+02 9.84773E+05 + 3.71000E+02 9.93229E+05 + 3.71100E+02 1.00169E+06 + 3.71200E+02 1.01014E+06 + 3.71300E+02 1.01860E+06 + 3.71400E+02 1.02705E+06 + 3.71500E+02 1.03551E+06 + 3.71600E+02 1.04397E+06 + 3.71700E+02 1.05242E+06 + 3.71800E+02 1.06088E+06 + 3.71900E+02 1.06933E+06 + 3.72000E+02 1.07779E+06 + 3.72100E+02 1.08625E+06 + 3.72200E+02 1.09470E+06 + 3.72300E+02 1.10316E+06 + 3.72400E+02 1.11162E+06 + 3.72500E+02 1.12007E+06 + 3.72600E+02 1.12853E+06 + 3.72700E+02 1.13698E+06 + 3.72800E+02 1.14544E+06 + 3.72900E+02 1.15390E+06 + 3.73000E+02 1.16235E+06 + 3.73100E+02 1.17081E+06 + 3.73200E+02 1.17927E+06 + 3.73300E+02 1.18772E+06 + 3.73400E+02 1.19618E+06 + 3.73500E+02 1.20463E+06 + 3.73600E+02 1.21309E+06 + 3.73700E+02 1.22155E+06 + 3.73800E+02 1.23000E+06 + 3.73900E+02 1.23846E+06 + 3.74000E+02 1.24691E+06 + 3.74100E+02 1.25537E+06 + 3.74200E+02 1.26383E+06 + 3.74300E+02 1.27228E+06 + 3.74400E+02 1.28074E+06 + 3.74500E+02 1.28920E+06 + 3.74600E+02 1.29765E+06 + 3.74700E+02 1.30611E+06 + 3.74800E+02 1.31456E+06 + 3.74900E+02 1.32302E+06 + 3.75000E+02 1.33148E+06 + 3.75100E+02 1.33993E+06 + 3.75200E+02 1.34839E+06 + 3.75300E+02 1.35685E+06 + 3.75400E+02 1.36530E+06 + 3.75500E+02 1.37376E+06 + 3.75600E+02 1.38221E+06 + 3.75700E+02 1.39067E+06 + 3.75800E+02 1.39913E+06 + 3.75900E+02 1.40758E+06 + 3.76000E+02 1.41604E+06 + 3.76100E+02 1.42449E+06 + 3.76200E+02 1.43295E+06 + 3.76300E+02 1.44141E+06 + 3.76400E+02 1.44986E+06 + 3.76500E+02 1.45832E+06 + 3.76600E+02 1.46678E+06 + 3.76700E+02 1.47523E+06 + 3.76800E+02 1.48369E+06 + 3.76900E+02 1.44986E+06 + 3.77000E+02 1.41604E+06 + 3.77100E+02 1.38221E+06 + 3.77200E+02 1.34839E+06 + 3.77300E+02 1.31456E+06 + 3.77400E+02 1.28074E+06 + 3.77500E+02 1.24691E+06 + 3.77600E+02 1.21309E+06 + 3.77700E+02 1.17927E+06 + 3.77800E+02 1.14544E+06 + 3.77900E+02 1.11162E+06 + 3.78000E+02 1.07779E+06 + 3.78100E+02 1.04397E+06 + 3.78200E+02 1.01014E+06 + 3.78300E+02 9.76317E+05 + 3.78400E+02 9.42492E+05 + 3.78500E+02 9.08667E+05 + 3.78600E+02 8.74842E+05 + 3.78700E+02 8.41018E+05 + 3.78800E+02 8.07193E+05 + 3.78900E+02 7.73368E+05 + 3.79000E+02 7.39543E+05 + 3.79100E+02 7.05719E+05 + 3.79200E+02 6.71894E+05 + 3.79300E+02 6.38069E+05 + 3.79400E+02 6.04244E+05 + 3.79500E+02 5.70420E+05 + 3.79600E+02 5.36595E+05 + 3.79700E+02 5.02770E+05 + 3.79800E+02 4.68945E+05 + 3.79900E+02 4.35121E+05 + 3.80000E+02 4.01296E+05 + 3.80100E+02 3.67471E+05 + 3.80200E+02 3.33646E+05 + 3.80300E+02 2.99822E+05 + 3.80400E+02 2.65997E+05 + 3.80500E+02 2.65997E+05 + 3.80600E+02 2.65997E+05 + 3.80700E+02 2.65997E+05 + 3.80800E+02 2.65997E+05 + 3.80900E+02 2.65997E+05 + 3.81000E+02 2.65997E+05 + 3.81100E+02 2.65997E+05 + 3.81200E+02 2.65997E+05 + 3.81300E+02 2.65997E+05 + 3.81400E+02 2.65997E+05 + 3.81500E+02 2.65997E+05 + 3.81600E+02 2.65997E+05 + 3.81700E+02 2.65997E+05 + 3.81800E+02 2.65997E+05 + 3.81900E+02 2.65997E+05 + 3.82000E+02 2.65997E+05 + 3.82100E+02 2.65997E+05 + 3.82200E+02 2.65997E+05 + 3.82300E+02 2.65997E+05 + 3.82400E+02 2.65997E+05 + 3.82500E+02 2.65997E+05 + 3.82600E+02 2.65997E+05 + 3.82700E+02 2.65997E+05 + 3.82800E+02 2.65997E+05 + 3.82900E+02 2.65997E+05 + 3.83000E+02 2.65997E+05 + 3.83100E+02 2.65997E+05 + 3.83200E+02 2.65997E+05 + 3.83300E+02 2.65997E+05 + 3.83400E+02 2.65997E+05 + 3.83500E+02 2.65997E+05 + 3.83600E+02 2.65997E+05 + 3.83700E+02 2.65997E+05 + 3.83800E+02 2.65997E+05 + 3.83900E+02 2.65997E+05 + 3.84000E+02 2.65997E+05 + 3.84100E+02 2.65997E+05 + 3.84200E+02 2.65997E+05 + 3.84300E+02 2.65997E+05 + 3.84400E+02 2.65997E+05 + 3.84500E+02 2.65997E+05 + 3.84600E+02 2.65997E+05 + 3.84700E+02 2.65997E+05 + 3.84800E+02 2.65997E+05 + 3.84900E+02 2.65997E+05 + 3.85000E+02 2.65997E+05 + 3.85100E+02 2.65997E+05 + 3.85200E+02 2.65997E+05 + 3.85300E+02 2.65997E+05 + 3.85400E+02 2.65997E+05 + 3.85500E+02 2.65997E+05 + 3.85600E+02 2.65997E+05 + 3.85700E+02 2.65997E+05 + 3.85800E+02 2.65997E+05 + 3.85900E+02 2.65997E+05 + 3.86000E+02 2.65997E+05 + 3.86100E+02 2.65997E+05 + 3.86200E+02 2.65997E+05 + 3.86300E+02 2.65997E+05 + 3.86400E+02 2.65997E+05 + 3.86500E+02 2.65997E+05 + 3.86600E+02 2.65997E+05 + 3.86700E+02 2.65997E+05 + 3.86800E+02 2.65997E+05 + 3.86900E+02 2.65997E+05 + 3.87000E+02 2.65997E+05 + 3.87100E+02 2.65997E+05 + 3.87200E+02 2.65997E+05 + 3.87300E+02 2.65997E+05 + 3.87400E+02 2.65997E+05 + 3.87500E+02 2.65997E+05 + 3.87600E+02 2.65997E+05 + 3.87700E+02 2.65997E+05 + 3.87800E+02 2.65997E+05 + 3.87900E+02 2.65997E+05 + 3.88000E+02 2.65997E+05 + 3.88100E+02 2.65997E+05 + 3.88200E+02 2.65997E+05 + 3.88300E+02 2.65997E+05 + 3.88400E+02 2.65997E+05 + 3.88500E+02 2.65997E+05 + 3.88600E+02 2.65997E+05 + 3.88700E+02 2.65997E+05 + 3.88800E+02 2.65997E+05 + 3.88900E+02 2.65997E+05 + 3.89000E+02 2.65997E+05 + 3.89100E+02 2.65997E+05 + 3.89200E+02 2.65997E+05 + 3.89300E+02 2.65997E+05 + 3.89400E+02 2.65997E+05 + 3.89500E+02 2.65997E+05 + 3.89600E+02 2.65997E+05 + 3.89700E+02 2.65997E+05 + 3.89800E+02 2.65997E+05 + 3.89900E+02 2.65997E+05 + 3.90000E+02 2.65997E+05 + 3.90100E+02 2.65997E+05 + 3.90200E+02 2.65997E+05 + 3.90300E+02 2.65997E+05 + 3.90400E+02 2.65997E+05 + 3.90500E+02 2.65997E+05 + 3.90600E+02 2.65997E+05 + 3.90700E+02 2.65997E+05 + 3.90800E+02 2.65997E+05 + 3.90900E+02 2.65997E+05 + 3.91000E+02 2.65997E+05 + 3.91100E+02 2.65997E+05 + 3.91200E+02 2.65997E+05 + 3.91300E+02 2.65997E+05 + 3.91400E+02 2.65997E+05 + 3.91500E+02 2.65997E+05 + 3.91600E+02 2.65997E+05 + 3.91700E+02 2.65997E+05 + 3.91800E+02 2.65997E+05 + 3.91900E+02 2.65997E+05 + 3.92000E+02 2.65997E+05 + 3.92100E+02 2.65997E+05 + 3.92200E+02 2.65997E+05 + 3.92300E+02 2.65997E+05 + 3.92400E+02 2.65997E+05 + 3.92500E+02 2.81842E+05 + 3.92600E+02 2.97687E+05 + 3.92700E+02 3.13532E+05 + 3.92800E+02 3.29377E+05 + 3.92900E+02 3.45222E+05 + 3.93000E+02 3.61067E+05 + 3.93100E+02 3.76912E+05 + 3.93200E+02 3.92757E+05 + 3.93300E+02 4.08602E+05 + 3.93400E+02 4.24447E+05 + 3.93500E+02 4.40292E+05 + 3.93600E+02 4.56137E+05 + 3.93700E+02 4.71982E+05 + 3.93800E+02 4.87827E+05 + 3.93900E+02 5.03672E+05 + 3.94000E+02 5.19517E+05 + 3.94100E+02 5.35362E+05 + 3.94200E+02 5.51207E+05 + 3.94300E+02 5.67052E+05 + 3.94400E+02 5.82897E+05 + 3.94500E+02 5.98742E+05 + 3.94600E+02 6.14588E+05 + 3.94700E+02 6.30432E+05 + 3.94800E+02 6.46278E+05 + 3.94900E+02 6.62123E+05 + 3.95000E+02 6.77968E+05 + 3.95100E+02 6.93813E+05 + 3.95200E+02 7.09658E+05 + 3.95300E+02 7.25503E+05 + 3.95400E+02 7.41348E+05 + 3.95500E+02 7.57193E+05 + 3.95600E+02 7.73038E+05 + 3.95700E+02 7.88883E+05 + 3.95800E+02 8.04728E+05 + 3.95900E+02 8.20573E+05 + 3.96000E+02 8.36418E+05 + 3.96100E+02 8.52263E+05 + 3.96200E+02 8.68108E+05 + 3.96300E+02 8.83953E+05 + 3.96400E+02 8.99798E+05 + 3.96500E+02 9.15643E+05 + 3.96600E+02 9.31488E+05 + 3.96700E+02 9.47333E+05 + 3.96800E+02 9.63178E+05 + 3.96900E+02 9.79023E+05 + 3.97000E+02 9.94868E+05 + 3.97100E+02 1.01071E+06 + 3.97200E+02 1.02656E+06 + 3.97300E+02 1.04240E+06 + 3.97400E+02 1.05825E+06 + 3.97500E+02 1.07409E+06 + 3.97600E+02 1.08994E+06 + 3.97700E+02 1.10578E+06 + 3.97800E+02 1.12163E+06 + 3.97900E+02 1.13747E+06 + 3.98000E+02 1.15332E+06 + 3.98100E+02 1.16916E+06 + 3.98200E+02 1.18501E+06 + 3.98300E+02 1.20085E+06 + 3.98400E+02 1.21670E+06 + 3.98500E+02 1.23254E+06 + 3.98600E+02 1.24839E+06 + 3.98700E+02 1.26423E+06 + 3.98800E+02 1.28008E+06 + 3.98900E+02 1.29592E+06 + 3.99000E+02 1.31177E+06 + 3.99100E+02 1.32761E+06 + 3.99200E+02 1.34346E+06 + 3.99300E+02 1.35930E+06 + 3.99400E+02 1.37515E+06 + 3.99500E+02 1.39099E+06 + 3.99600E+02 1.40684E+06 + 3.99700E+02 1.42268E+06 + 3.99800E+02 1.43853E+06 + 3.99900E+02 1.45437E+06 + 4.00000E+02 1.47022E+06 + 4.00100E+02 1.48606E+06 + 4.00200E+02 1.50191E+06 + 4.00300E+02 1.51775E+06 + 4.00400E+02 1.53360E+06 + 4.00500E+02 1.54944E+06 + 4.00600E+02 1.56529E+06 + 4.00700E+02 1.58113E+06 + 4.00800E+02 1.59698E+06 + 4.00900E+02 1.53360E+06 + 4.01000E+02 1.47022E+06 + 4.01100E+02 1.40684E+06 + 4.01200E+02 1.34346E+06 + 4.01300E+02 1.28008E+06 + 4.01400E+02 1.21670E+06 + 4.01500E+02 1.15332E+06 + 4.01600E+02 1.08994E+06 + 4.01700E+02 1.02656E+06 + 4.01800E+02 9.63178E+05 + 4.01900E+02 8.99798E+05 + 4.02000E+02 8.36418E+05 + 4.02100E+02 7.73038E+05 + 4.02200E+02 7.09658E+05 + 4.02300E+02 6.46278E+05 + 4.02400E+02 5.82897E+05 + 4.02500E+02 5.19517E+05 + 4.02600E+02 4.56137E+05 + 4.02700E+02 3.92757E+05 + 4.02800E+02 3.29377E+05 + 4.02900E+02 2.65997E+05 + 4.03000E+02 2.65997E+05 + 4.03100E+02 2.65997E+05 + 4.03200E+02 2.65997E+05 + 4.03300E+02 2.65997E+05 + 4.03400E+02 2.65997E+05 + 4.03500E+02 2.65997E+05 + 4.03600E+02 2.65997E+05 + 4.03700E+02 2.65997E+05 + 4.03800E+02 2.65997E+05 + 4.03900E+02 2.65997E+05 + 4.04000E+02 2.65997E+05 + 4.04100E+02 2.65997E+05 + 4.04200E+02 2.65997E+05 + 4.04300E+02 2.65997E+05 + 4.04400E+02 2.65997E+05 + 4.04500E+02 2.65997E+05 + 4.04600E+02 2.65997E+05 + 4.04700E+02 2.65997E+05 + 4.04800E+02 2.65997E+05 + 4.04900E+02 2.65997E+05 + 4.05000E+02 2.65997E+05 + 4.05100E+02 2.65997E+05 + 4.05200E+02 2.65997E+05 + 4.05300E+02 2.65997E+05 + 4.05400E+02 2.65997E+05 + 4.05500E+02 2.65997E+05 + 4.05600E+02 2.65997E+05 + 4.05700E+02 2.65997E+05 + 4.05800E+02 2.65997E+05 + 4.05900E+02 2.65997E+05 + 4.06000E+02 2.65997E+05 + 4.06100E+02 2.65997E+05 + 4.06200E+02 2.65997E+05 + 4.06300E+02 2.65997E+05 + 4.06400E+02 2.65997E+05 + 4.06500E+02 2.65997E+05 + 4.06600E+02 2.65997E+05 + 4.06700E+02 2.65997E+05 + 4.06800E+02 2.65997E+05 + 4.06900E+02 2.65997E+05 + 4.07000E+02 2.65997E+05 + 4.07100E+02 2.65997E+05 + 4.07200E+02 2.65997E+05 + 4.07300E+02 2.65997E+05 + 4.07400E+02 2.65997E+05 + 4.07500E+02 2.65997E+05 + 4.07600E+02 2.65997E+05 + 4.07700E+02 2.65997E+05 + 4.07800E+02 2.65997E+05 + 4.07900E+02 2.65997E+05 + 4.08000E+02 2.65997E+05 + 4.08100E+02 2.65997E+05 + 4.08200E+02 2.65997E+05 + 4.08300E+02 2.65997E+05 + 4.08400E+02 2.65997E+05 + 4.08500E+02 2.65997E+05 + 4.08600E+02 2.65997E+05 + 4.08700E+02 2.65997E+05 + 4.08800E+02 2.65997E+05 + 4.08900E+02 2.65997E+05 + 4.09000E+02 2.65997E+05 + 4.09100E+02 2.65997E+05 + 4.09200E+02 2.65997E+05 + 4.09300E+02 2.65997E+05 + 4.09400E+02 2.65997E+05 + 4.09500E+02 2.65997E+05 + 4.09600E+02 2.65997E+05 + 4.09700E+02 2.65997E+05 + 4.09800E+02 2.65997E+05 + 4.09900E+02 2.74022E+05 + 4.10000E+02 2.82047E+05 + 4.10100E+02 2.90072E+05 + 4.10200E+02 2.98097E+05 + 4.10300E+02 3.06122E+05 + 4.10400E+02 3.14147E+05 + 4.10500E+02 3.22172E+05 + 4.10600E+02 3.30197E+05 + 4.10700E+02 3.38222E+05 + 4.10800E+02 3.46247E+05 + 4.10900E+02 3.54272E+05 + 4.11000E+02 3.62297E+05 + 4.11100E+02 3.70322E+05 + 4.11200E+02 3.78347E+05 + 4.11300E+02 3.86372E+05 + 4.11400E+02 3.94397E+05 + 4.11500E+02 4.02422E+05 + 4.11600E+02 4.10446E+05 + 4.11700E+02 4.18471E+05 + 4.11800E+02 4.26496E+05 + 4.11900E+02 4.34521E+05 + 4.12000E+02 4.42546E+05 + 4.12100E+02 4.50571E+05 + 4.12200E+02 4.58596E+05 + 4.12300E+02 4.66621E+05 + 4.12400E+02 4.74646E+05 + 4.12500E+02 4.82671E+05 + 4.12600E+02 4.90696E+05 + 4.12700E+02 4.98721E+05 + 4.12800E+02 5.06746E+05 + 4.12900E+02 5.14771E+05 + 4.13000E+02 5.22796E+05 + 4.13100E+02 5.30821E+05 + 4.13200E+02 5.38846E+05 + 4.13300E+02 5.46871E+05 + 4.13400E+02 5.54896E+05 + 4.13500E+02 5.62921E+05 + 4.13600E+02 5.70946E+05 + 4.13700E+02 5.78971E+05 + 4.13800E+02 5.86996E+05 + 4.13900E+02 5.95021E+05 + 4.14000E+02 6.03046E+05 + 4.14100E+02 6.11071E+05 + 4.14200E+02 6.19096E+05 + 4.14300E+02 6.27121E+05 + 4.14400E+02 6.35146E+05 + 4.14500E+02 6.43171E+05 + 4.14600E+02 6.51196E+05 + 4.14700E+02 6.59221E+05 + 4.14800E+02 6.67246E+05 + 4.14900E+02 6.75271E+05 + 4.15000E+02 6.83296E+05 + 4.15100E+02 6.91321E+05 + 4.15200E+02 6.99346E+05 + 4.15300E+02 7.07371E+05 + 4.15400E+02 7.15396E+05 + 4.15500E+02 7.23421E+05 + 4.15600E+02 7.31446E+05 + 4.15700E+02 7.39471E+05 + 4.15800E+02 7.47496E+05 + 4.15900E+02 7.55521E+05 + 4.16000E+02 7.63546E+05 + 4.16100E+02 7.71571E+05 + 4.16200E+02 7.79596E+05 + 4.16300E+02 7.87621E+05 + 4.16400E+02 7.95646E+05 + 4.16500E+02 8.03670E+05 + 4.16600E+02 8.11696E+05 + 4.16700E+02 8.19720E+05 + 4.16800E+02 8.27746E+05 + 4.16900E+02 8.35770E+05 + 4.17000E+02 8.43795E+05 + 4.17100E+02 8.51820E+05 + 4.17200E+02 8.59845E+05 + 4.17300E+02 8.67870E+05 + 4.17400E+02 8.75895E+05 + 4.17500E+02 8.83920E+05 + 4.17600E+02 8.91945E+05 + 4.17700E+02 8.99970E+05 + 4.17800E+02 9.07995E+05 + 4.17900E+02 9.16020E+05 + 4.18000E+02 9.24045E+05 + 4.18100E+02 9.32070E+05 + 4.18200E+02 9.40095E+05 + 4.18300E+02 9.48120E+05 + 4.18400E+02 9.56145E+05 + 4.18500E+02 9.64170E+05 + 4.18600E+02 9.72195E+05 + 4.18700E+02 9.80220E+05 + 4.18800E+02 9.88245E+05 + 4.18900E+02 9.96270E+05 + 4.19000E+02 1.00430E+06 + 4.19100E+02 1.01232E+06 + 4.19200E+02 1.02034E+06 + 4.19300E+02 1.02837E+06 + 4.19400E+02 1.03640E+06 + 4.19500E+02 1.04442E+06 + 4.19600E+02 1.05244E+06 + 4.19700E+02 1.06047E+06 + 4.19800E+02 1.06849E+06 + 4.19900E+02 1.07652E+06 + 4.20000E+02 1.08454E+06 + 4.20100E+02 1.09257E+06 + 4.20200E+02 1.10059E+06 + 4.20300E+02 1.10862E+06 + 4.20400E+02 1.11664E+06 + 4.20500E+02 1.12467E+06 + 4.20600E+02 1.13269E+06 + 4.20700E+02 1.14072E+06 + 4.20800E+02 1.14874E+06 + 4.20900E+02 1.15677E+06 + 4.21000E+02 1.16479E+06 + 4.21100E+02 1.17282E+06 + 4.21200E+02 1.18084E+06 + 4.21300E+02 1.18887E+06 + 4.21400E+02 1.19689E+06 + 4.21500E+02 1.20492E+06 + 4.21600E+02 1.21294E+06 + 4.21700E+02 1.22097E+06 + 4.21800E+02 1.22899E+06 + 4.21900E+02 1.23702E+06 + 4.22000E+02 1.24504E+06 + 4.22100E+02 1.25307E+06 + 4.22200E+02 1.26109E+06 + 4.22300E+02 1.26912E+06 + 4.22400E+02 1.27714E+06 + 4.22500E+02 1.28517E+06 + 4.22600E+02 1.29319E+06 + 4.22700E+02 1.30122E+06 + 4.22800E+02 1.30924E+06 + 4.22900E+02 1.31727E+06 + 4.23000E+02 1.32529E+06 + 4.23100E+02 1.33332E+06 + 4.23200E+02 1.34134E+06 + 4.23300E+02 1.34937E+06 + 4.23400E+02 1.35739E+06 + 4.23500E+02 1.36542E+06 + 4.23600E+02 1.37344E+06 + 4.23700E+02 1.38147E+06 + 4.23800E+02 1.38949E+06 + 4.23900E+02 1.39752E+06 + 4.24000E+02 1.40554E+06 + 4.24100E+02 1.41357E+06 + 4.24200E+02 1.42159E+06 + 4.24300E+02 1.38949E+06 + 4.24400E+02 1.35739E+06 + 4.24500E+02 1.32529E+06 + 4.24600E+02 1.29319E+06 + 4.24700E+02 1.26109E+06 + 4.24800E+02 1.22899E+06 + 4.24900E+02 1.19689E+06 + 4.25000E+02 1.16479E+06 + 4.25100E+02 1.13269E+06 + 4.25200E+02 1.10059E+06 + 4.25300E+02 1.06849E+06 + 4.25400E+02 1.03639E+06 + 4.25500E+02 1.00430E+06 + 4.25600E+02 9.72195E+05 + 4.25700E+02 9.40095E+05 + 4.25800E+02 9.07995E+05 + 4.25900E+02 8.75895E+05 + 4.26000E+02 8.43795E+05 + 4.26100E+02 8.11696E+05 + 4.26200E+02 7.79596E+05 + 4.26300E+02 7.47496E+05 + 4.26400E+02 7.15396E+05 + 4.26500E+02 6.83296E+05 + 4.26600E+02 6.51196E+05 + 4.26700E+02 6.19096E+05 + 4.26800E+02 5.86996E+05 + 4.26900E+02 5.54896E+05 + 4.27000E+02 5.22796E+05 + 4.27100E+02 4.90696E+05 + 4.27200E+02 4.58596E+05 + 4.27300E+02 4.26496E+05 + 4.27400E+02 3.94397E+05 + 4.27500E+02 3.62297E+05 + 4.27600E+02 3.30197E+05 + 4.27700E+02 2.98097E+05 + 4.27800E+02 2.65997E+05 + 4.27900E+02 2.65997E+05 + 4.28000E+02 2.65997E+05 + 4.28100E+02 2.65997E+05 + 4.28200E+02 2.65997E+05 + 4.28300E+02 2.65997E+05 + 4.28400E+02 2.65997E+05 + 4.28500E+02 2.65997E+05 + 4.28600E+02 2.65997E+05 + 4.28700E+02 2.65997E+05 + 4.28800E+02 2.65997E+05 + 4.28900E+02 2.65997E+05 + 4.29000E+02 2.65997E+05 + 4.29100E+02 2.65997E+05 + 4.29200E+02 2.65997E+05 + 4.29300E+02 2.65997E+05 + 4.29400E+02 2.65997E+05 + 4.29500E+02 2.65997E+05 + 4.29600E+02 2.65997E+05 + 4.29700E+02 2.65997E+05 + 4.29800E+02 2.65997E+05 + 4.29900E+02 2.65997E+05 + 4.30000E+02 2.65997E+05 + 4.30100E+02 2.65997E+05 + 4.30200E+02 2.65997E+05 + 4.30300E+02 2.65997E+05 + 4.30400E+02 2.65997E+05 + 4.30500E+02 2.65997E+05 + 4.30600E+02 2.65997E+05 + 4.30700E+02 2.65997E+05 + 4.30800E+02 2.65997E+05 + 4.30900E+02 2.65997E+05 + 4.31000E+02 2.65997E+05 + 4.31100E+02 2.65997E+05 + 4.31200E+02 2.65997E+05 + 4.31300E+02 2.65997E+05 + 4.31400E+02 2.65997E+05 + 4.31500E+02 2.65997E+05 + 4.31600E+02 2.65997E+05 + 4.31700E+02 2.65997E+05 + 4.31800E+02 2.65997E+05 + 4.31900E+02 2.65997E+05 + 4.32000E+02 2.65997E+05 + 4.32100E+02 2.65997E+05 + 4.32200E+02 2.65997E+05 + 4.32300E+02 2.65997E+05 + 4.32400E+02 2.65997E+05 + 4.32500E+02 2.65997E+05 + 4.32600E+02 2.65997E+05 + 4.32700E+02 2.65997E+05 + 4.32800E+02 2.65997E+05 + 4.32900E+02 2.65997E+05 + 4.33000E+02 2.65997E+05 + 4.33100E+02 2.65997E+05 + 4.33200E+02 2.65997E+05 + 4.33300E+02 2.65997E+05 + 4.33400E+02 2.65997E+05 + 4.33500E+02 2.65997E+05 + 4.33600E+02 2.65997E+05 + 4.33700E+02 2.65997E+05 + 4.33800E+02 2.65997E+05 + 4.33900E+02 2.65997E+05 + 4.34000E+02 2.65997E+05 + 4.34100E+02 2.65997E+05 + 4.34200E+02 2.65997E+05 + 4.34300E+02 2.65997E+05 + 4.34400E+02 2.65997E+05 + 4.34500E+02 2.65997E+05 + 4.34600E+02 2.65997E+05 + 4.34700E+02 2.65997E+05 + 4.34800E+02 2.65997E+05 + 4.34900E+02 2.65997E+05 + 4.35000E+02 2.65997E+05 + 4.35100E+02 2.65997E+05 + 4.35200E+02 2.65997E+05 + 4.35300E+02 2.65997E+05 + 4.35400E+02 2.65997E+05 + 4.35500E+02 2.65997E+05 + 4.35600E+02 2.65997E+05 + 4.35700E+02 2.65997E+05 + 4.35800E+02 2.65997E+05 + 4.35900E+02 2.65997E+05 + 4.36000E+02 2.65997E+05 + 4.36100E+02 2.65997E+05 + 4.36200E+02 2.65997E+05 + 4.36300E+02 2.65997E+05 + 4.36400E+02 2.65997E+05 + 4.36500E+02 2.65997E+05 + 4.36600E+02 2.65997E+05 + 4.36700E+02 2.65997E+05 + 4.36800E+02 2.65997E+05 + 4.36900E+02 2.65997E+05 + 4.37000E+02 2.65997E+05 + 4.37100E+02 2.65997E+05 + 4.37200E+02 2.65997E+05 + 4.37300E+02 2.65997E+05 + 4.37400E+02 2.65997E+05 + 4.37500E+02 2.65997E+05 + 4.37600E+02 2.65997E+05 + 4.37700E+02 2.65997E+05 + 4.37800E+02 2.65997E+05 + 4.37900E+02 2.65997E+05 + 4.38000E+02 2.65997E+05 + 4.38100E+02 2.65997E+05 + 4.38200E+02 2.65997E+05 + 4.38300E+02 2.65997E+05 + 4.38400E+02 2.65997E+05 + 4.38500E+02 2.65997E+05 + 4.38600E+02 2.65997E+05 + 4.38700E+02 2.65997E+05 + 4.38800E+02 2.65997E+05 + 4.38900E+02 2.65997E+05 + 4.39000E+02 2.65997E+05 + 4.39100E+02 2.65997E+05 + 4.39200E+02 2.65997E+05 + 4.39300E+02 2.65997E+05 + 4.39400E+02 2.65997E+05 + 4.39500E+02 2.65997E+05 + 4.39600E+02 2.65997E+05 + 4.39700E+02 2.65997E+05 + 4.39800E+02 2.65997E+05 + 4.39900E+02 2.77681E+05 + 4.40000E+02 2.89365E+05 + 4.40100E+02 3.01050E+05 + 4.40200E+02 3.12734E+05 + 4.40300E+02 3.24418E+05 + 4.40400E+02 3.36102E+05 + 4.40500E+02 3.47786E+05 + 4.40600E+02 3.59471E+05 + 4.40700E+02 3.71155E+05 + 4.40800E+02 3.82839E+05 + 4.40900E+02 3.94524E+05 + 4.41000E+02 4.06208E+05 + 4.41100E+02 4.17892E+05 + 4.41200E+02 4.29576E+05 + 4.41300E+02 4.41260E+05 + 4.41400E+02 4.52945E+05 + 4.41500E+02 4.64629E+05 + 4.41600E+02 4.76313E+05 + 4.41700E+02 4.87997E+05 + 4.41800E+02 4.99682E+05 + 4.41900E+02 5.11366E+05 + 4.42000E+02 5.23050E+05 + 4.42100E+02 5.34734E+05 + 4.42200E+02 5.46419E+05 + 4.42300E+02 5.58103E+05 + 4.42400E+02 5.69787E+05 + 4.42500E+02 5.81471E+05 + 4.42600E+02 5.93156E+05 + 4.42700E+02 6.04840E+05 + 4.42800E+02 6.16524E+05 + 4.42900E+02 6.28208E+05 + 4.43000E+02 6.39892E+05 + 4.43100E+02 6.51577E+05 + 4.43200E+02 6.63261E+05 + 4.43300E+02 6.74945E+05 + 4.43400E+02 6.86630E+05 + 4.43500E+02 6.98314E+05 + 4.43600E+02 7.09998E+05 + 4.43700E+02 7.21682E+05 + 4.43800E+02 7.33366E+05 + 4.43900E+02 7.45051E+05 + 4.44000E+02 7.56735E+05 + 4.44100E+02 7.68419E+05 + 4.44200E+02 7.80103E+05 + 4.44300E+02 7.91788E+05 + 4.44400E+02 8.03472E+05 + 4.44500E+02 8.15156E+05 + 4.44600E+02 8.26840E+05 + 4.44700E+02 8.38525E+05 + 4.44800E+02 8.50209E+05 + 4.44900E+02 8.61893E+05 + 4.45000E+02 8.73577E+05 + 4.45100E+02 8.85262E+05 + 4.45200E+02 8.96946E+05 + 4.45300E+02 9.08630E+05 + 4.45400E+02 9.20314E+05 + 4.45500E+02 9.31998E+05 + 4.45600E+02 9.43683E+05 + 4.45700E+02 9.55367E+05 + 4.45800E+02 9.67051E+05 + 4.45900E+02 9.78736E+05 + 4.46000E+02 9.90420E+05 + 4.46100E+02 1.00210E+06 + 4.46200E+02 1.01379E+06 + 4.46300E+02 1.02547E+06 + 4.46400E+02 1.03716E+06 + 4.46500E+02 1.04884E+06 + 4.46600E+02 1.06053E+06 + 4.46700E+02 1.07221E+06 + 4.46800E+02 1.08389E+06 + 4.46900E+02 1.09558E+06 + 4.47000E+02 1.10726E+06 + 4.47100E+02 1.11895E+06 + 4.47200E+02 1.13063E+06 + 4.47300E+02 1.14231E+06 + 4.47400E+02 1.15400E+06 + 4.47500E+02 1.16568E+06 + 4.47600E+02 1.17737E+06 + 4.47700E+02 1.18905E+06 + 4.47800E+02 1.20074E+06 + 4.47900E+02 1.21242E+06 + 4.48000E+02 1.22410E+06 + 4.48100E+02 1.23579E+06 + 4.48200E+02 1.24747E+06 + 4.48300E+02 1.25916E+06 + 4.48400E+02 1.27084E+06 + 4.48500E+02 1.28253E+06 + 4.48600E+02 1.29421E+06 + 4.48700E+02 1.30589E+06 + 4.48800E+02 1.31758E+06 + 4.48900E+02 1.32926E+06 + 4.49000E+02 1.34095E+06 + 4.49100E+02 1.35263E+06 + 4.49200E+02 1.36432E+06 + 4.49300E+02 1.37600E+06 + 4.49400E+02 1.38768E+06 + 4.49500E+02 1.39937E+06 + 4.49600E+02 1.41105E+06 + 4.49700E+02 1.42274E+06 + 4.49800E+02 1.43442E+06 + 4.49900E+02 1.44611E+06 + 4.50000E+02 1.45779E+06 + 4.50100E+02 1.46947E+06 + 4.50200E+02 1.48116E+06 + 4.50300E+02 1.49284E+06 + 4.50400E+02 1.50453E+06 + 4.50500E+02 1.51621E+06 + 4.50600E+02 1.52789E+06 + 4.50700E+02 1.53958E+06 + 4.50800E+02 1.55126E+06 + 4.50900E+02 1.56295E+06 + 4.51000E+02 1.51663E+06 + 4.51100E+02 1.47031E+06 + 4.51200E+02 1.42399E+06 + 4.51300E+02 1.37767E+06 + 4.51400E+02 1.33135E+06 + 4.51500E+02 1.28503E+06 + 4.51600E+02 1.23871E+06 + 4.51700E+02 1.19239E+06 + 4.51800E+02 1.14607E+06 + 4.51900E+02 1.09975E+06 + 4.52000E+02 1.05343E+06 + 4.52100E+02 1.00711E+06 + 4.52200E+02 9.60792E+05 + 4.52300E+02 9.14472E+05 + 4.52400E+02 8.68152E+05 + 4.52500E+02 8.21833E+05 + 4.52600E+02 7.75513E+05 + 4.52700E+02 7.29194E+05 + 4.52800E+02 6.82874E+05 + 4.52900E+02 6.36554E+05 + 4.53000E+02 5.90234E+05 + 4.53100E+02 5.43915E+05 + 4.53200E+02 4.97595E+05 + 4.53300E+02 4.51276E+05 + 4.53400E+02 4.04956E+05 + 4.53500E+02 3.58636E+05 + 4.53600E+02 3.12316E+05 + 4.53700E+02 2.65997E+05 + 4.53800E+02 2.65997E+05 + 4.53900E+02 2.65997E+05 + 4.54000E+02 2.65997E+05 + 4.54100E+02 2.65997E+05 + 4.54200E+02 2.65997E+05 + 4.54300E+02 2.65997E+05 + 4.54400E+02 2.65997E+05 + 4.54500E+02 2.65997E+05 + 4.54600E+02 2.65997E+05 + 4.54700E+02 2.65997E+05 + 4.54800E+02 2.65997E+05 + 4.54900E+02 2.65997E+05 + 4.55000E+02 2.65997E+05 + 4.55100E+02 2.65997E+05 + 4.55200E+02 2.65997E+05 + 4.55300E+02 2.65997E+05 + 4.55400E+02 2.65997E+05 + 4.55500E+02 2.65997E+05 + 4.55600E+02 2.65997E+05 + 4.55700E+02 2.65997E+05 + 4.55800E+02 2.65997E+05 + 4.55900E+02 2.65997E+05 + 4.56000E+02 2.65997E+05 + 4.56100E+02 2.65997E+05 + 4.56200E+02 2.65997E+05 + 4.56300E+02 2.65997E+05 + 4.56400E+02 2.65997E+05 + 4.56500E+02 2.65997E+05 + 4.56600E+02 2.65997E+05 + 4.56700E+02 2.65997E+05 + 4.56800E+02 2.65997E+05 + 4.56900E+02 2.65997E+05 + 4.57000E+02 2.65997E+05 + 4.57100E+02 2.65997E+05 + 4.57200E+02 2.65997E+05 + 4.57300E+02 2.65997E+05 + 4.57400E+02 2.65997E+05 + 4.57500E+02 2.65997E+05 + 4.57600E+02 2.65997E+05 + 4.57700E+02 2.65997E+05 + 4.57800E+02 2.65997E+05 + 4.57900E+02 2.65997E+05 + 4.58000E+02 2.65997E+05 + 4.58100E+02 2.65997E+05 + 4.58200E+02 2.65997E+05 + 4.58300E+02 2.65997E+05 + 4.58400E+02 2.65997E+05 + 4.58500E+02 2.65997E+05 + 4.58600E+02 2.65997E+05 + 4.58700E+02 2.65997E+05 + 4.58800E+02 2.65997E+05 + 4.58900E+02 2.65997E+05 + 4.59000E+02 2.65997E+05 + 4.59100E+02 2.65997E+05 + 4.59200E+02 2.65997E+05 + 4.59300E+02 2.65997E+05 + 4.59400E+02 2.65997E+05 + 4.59500E+02 2.65997E+05 + 4.59600E+02 2.65997E+05 + 4.59700E+02 2.65997E+05 + 4.59800E+02 2.65997E+05 + 4.59900E+02 2.65997E+05 + 4.60000E+02 2.65997E+05 + 4.60100E+02 2.65997E+05 + 4.60200E+02 2.65997E+05 + 4.60300E+02 2.65997E+05 + 4.60400E+02 2.65997E+05 + 4.60500E+02 2.65997E+05 + 4.60600E+02 2.65997E+05 + 4.60700E+02 2.65997E+05 + 4.60800E+02 2.65997E+05 + 4.60900E+02 2.65997E+05 + 4.61000E+02 2.65997E+05 + 4.61100E+02 2.65997E+05 + 4.61200E+02 2.65997E+05 + 4.61300E+02 2.65997E+05 + 4.61400E+02 2.65997E+05 + 4.61500E+02 2.65997E+05 + 4.61600E+02 2.65997E+05 + 4.61700E+02 2.65997E+05 + 4.61800E+02 2.65997E+05 + 4.61900E+02 2.65997E+05 + 4.62000E+02 2.65997E+05 + 4.62100E+02 2.65997E+05 + 4.62200E+02 2.65997E+05 + 4.62300E+02 2.65997E+05 + 4.62400E+02 2.65997E+05 + 4.62500E+02 2.65997E+05 + 4.62600E+02 2.65997E+05 + 4.62700E+02 2.65997E+05 + 4.62800E+02 2.65997E+05 + 4.62900E+02 2.84312E+05 + 4.63000E+02 3.02628E+05 + 4.63100E+02 3.20943E+05 + 4.63200E+02 3.39258E+05 + 4.63300E+02 3.57574E+05 + 4.63400E+02 3.75889E+05 + 4.63500E+02 3.94204E+05 + 4.63600E+02 4.12520E+05 + 4.63700E+02 4.30835E+05 + 4.63800E+02 4.49150E+05 + 4.63900E+02 4.67466E+05 + 4.64000E+02 4.85781E+05 + 4.64100E+02 5.04097E+05 + 4.64200E+02 5.22412E+05 + 4.64300E+02 5.40727E+05 + 4.64400E+02 5.59043E+05 + 4.64500E+02 5.77358E+05 + 4.64600E+02 5.95673E+05 + 4.64700E+02 6.13989E+05 + 4.64800E+02 6.32304E+05 + 4.64900E+02 6.50620E+05 + 4.65000E+02 6.68935E+05 + 4.65100E+02 6.87250E+05 + 4.65200E+02 7.05566E+05 + 4.65300E+02 7.23881E+05 + 4.65400E+02 7.42196E+05 + 4.65500E+02 7.60512E+05 + 4.65600E+02 7.78827E+05 + 4.65700E+02 7.97142E+05 + 4.65800E+02 8.15458E+05 + 4.65900E+02 8.33773E+05 + 4.66000E+02 8.52088E+05 + 4.66100E+02 8.70404E+05 + 4.66200E+02 8.88719E+05 + 4.66300E+02 9.07034E+05 + 4.66400E+02 9.25350E+05 + 4.66500E+02 9.43665E+05 + 4.66600E+02 9.61981E+05 + 4.66700E+02 9.80296E+05 + 4.66800E+02 9.98611E+05 + 4.66900E+02 1.01693E+06 + 4.67000E+02 1.03524E+06 + 4.67100E+02 1.05356E+06 + 4.67200E+02 1.07187E+06 + 4.67300E+02 1.09019E+06 + 4.67400E+02 1.10850E+06 + 4.67500E+02 1.12682E+06 + 4.67600E+02 1.14513E+06 + 4.67700E+02 1.16345E+06 + 4.67800E+02 1.18176E+06 + 4.67900E+02 1.20008E+06 + 4.68000E+02 1.21840E+06 + 4.68100E+02 1.23671E+06 + 4.68200E+02 1.25503E+06 + 4.68300E+02 1.27334E+06 + 4.68400E+02 1.29166E+06 + 4.68500E+02 1.30997E+06 + 4.68600E+02 1.32829E+06 + 4.68700E+02 1.34660E+06 + 4.68800E+02 1.36492E+06 + 4.68900E+02 1.38323E+06 + 4.69000E+02 1.40155E+06 + 4.69100E+02 1.41986E+06 + 4.69200E+02 1.43818E+06 + 4.69300E+02 1.45650E+06 + 4.69400E+02 1.47481E+06 + 4.69500E+02 1.49313E+06 + 4.69600E+02 1.51144E+06 + 4.69700E+02 1.52976E+06 + 4.69800E+02 1.54807E+06 + 4.69900E+02 1.56639E+06 + 4.70000E+02 1.58470E+06 + 4.70100E+02 1.60302E+06 + 4.70200E+02 1.62133E+06 + 4.70300E+02 1.63965E+06 + 4.70400E+02 1.56735E+06 + 4.70500E+02 1.49505E+06 + 4.70600E+02 1.42276E+06 + 4.70700E+02 1.35046E+06 + 4.70800E+02 1.27816E+06 + 4.70900E+02 1.20586E+06 + 4.71000E+02 1.13357E+06 + 4.71100E+02 1.06127E+06 + 4.71200E+02 9.88972E+05 + 4.71300E+02 9.16674E+05 + 4.71400E+02 8.44377E+05 + 4.71500E+02 7.72079E+05 + 4.71600E+02 6.99782E+05 + 4.71700E+02 6.27484E+05 + 4.71800E+02 5.55187E+05 + 4.71900E+02 4.82889E+05 + 4.72000E+02 4.10592E+05 + 4.72100E+02 3.38294E+05 + 4.72200E+02 2.65997E+05 + 4.72300E+02 2.65997E+05 + 4.72400E+02 2.65997E+05 + 4.72500E+02 2.65997E+05 + 4.72600E+02 2.65997E+05 + 4.72700E+02 2.65997E+05 + 4.72800E+02 2.65997E+05 + 4.72900E+02 2.65997E+05 + 4.73000E+02 2.65997E+05 + 4.73100E+02 2.65997E+05 + 4.73200E+02 2.65997E+05 + 4.73300E+02 2.65997E+05 + 4.73400E+02 2.65997E+05 + 4.73500E+02 2.65997E+05 + 4.73600E+02 2.65997E+05 + 4.73700E+02 2.65997E+05 + 4.73800E+02 2.65997E+05 + 4.73900E+02 2.65997E+05 + 4.74000E+02 2.65997E+05 + 4.74100E+02 2.65997E+05 + 4.74200E+02 2.65997E+05 + 4.74300E+02 2.65997E+05 + 4.74400E+02 2.65997E+05 + 4.74500E+02 2.65997E+05 + 4.74600E+02 2.65997E+05 + 4.74700E+02 2.65997E+05 + 4.74800E+02 2.65997E+05 + 4.74900E+02 2.65997E+05 + 4.75000E+02 2.65997E+05 + 4.75100E+02 2.65997E+05 + 4.75200E+02 2.65997E+05 + 4.75300E+02 2.65997E+05 + 4.75400E+02 2.65997E+05 + 4.75500E+02 2.65997E+05 + 4.75600E+02 2.65997E+05 + 4.75700E+02 2.65997E+05 + 4.75800E+02 2.65997E+05 + 4.75900E+02 2.65997E+05 + 4.76000E+02 2.65997E+05 + 4.76100E+02 2.65997E+05 + 4.76200E+02 2.65997E+05 + 4.76300E+02 2.65997E+05 + 4.76400E+02 2.65997E+05 + 4.76500E+02 2.65997E+05 + 4.76600E+02 2.65997E+05 + 4.76700E+02 2.65997E+05 + 4.76800E+02 2.65997E+05 + 4.76900E+02 2.65997E+05 + 4.77000E+02 2.65997E+05 + 4.77100E+02 2.65997E+05 + 4.77200E+02 2.65997E+05 + 4.77300E+02 2.65997E+05 + 4.77400E+02 2.65997E+05 + 4.77500E+02 2.65997E+05 + 4.77600E+02 2.65997E+05 + 4.77700E+02 2.65997E+05 + 4.77800E+02 2.65997E+05 + 4.77900E+02 2.65997E+05 + 4.78000E+02 2.65997E+05 + 4.78100E+02 2.65997E+05 + 4.78200E+02 2.65997E+05 + 4.78300E+02 2.65997E+05 + 4.78400E+02 2.65997E+05 + 4.78500E+02 2.76141E+05 + 4.78600E+02 2.86286E+05 + 4.78700E+02 2.96431E+05 + 4.78800E+02 3.06575E+05 + 4.78900E+02 3.16720E+05 + 4.79000E+02 3.26865E+05 + 4.79100E+02 3.37009E+05 + 4.79200E+02 3.47154E+05 + 4.79300E+02 3.57298E+05 + 4.79400E+02 3.67443E+05 + 4.79500E+02 3.77588E+05 + 4.79600E+02 3.87732E+05 + 4.79700E+02 3.97877E+05 + 4.79800E+02 4.08022E+05 + 4.79900E+02 4.18166E+05 + 4.80000E+02 4.28311E+05 + 4.80100E+02 4.38455E+05 + 4.80200E+02 4.48600E+05 + 4.80300E+02 4.58745E+05 + 4.80400E+02 4.68889E+05 + 4.80500E+02 4.79034E+05 + 4.80600E+02 4.89178E+05 + 4.80700E+02 4.99323E+05 + 4.80800E+02 5.09468E+05 + 4.80900E+02 5.19612E+05 + 4.81000E+02 5.29757E+05 + 4.81100E+02 5.39902E+05 + 4.81200E+02 5.50046E+05 + 4.81300E+02 5.60191E+05 + 4.81400E+02 5.70336E+05 + 4.81500E+02 5.80480E+05 + 4.81600E+02 5.90625E+05 + 4.81700E+02 6.00769E+05 + 4.81800E+02 6.10914E+05 + 4.81900E+02 6.21059E+05 + 4.82000E+02 6.31203E+05 + 4.82100E+02 6.41348E+05 + 4.82200E+02 6.51492E+05 + 4.82300E+02 6.61637E+05 + 4.82400E+02 6.71782E+05 + 4.82500E+02 6.81926E+05 + 4.82600E+02 6.92071E+05 + 4.82700E+02 7.02216E+05 + 4.82800E+02 7.12360E+05 + 4.82900E+02 7.22505E+05 + 4.83000E+02 7.32649E+05 + 4.83100E+02 7.42794E+05 + 4.83200E+02 7.52939E+05 + 4.83300E+02 7.63083E+05 + 4.83400E+02 7.73228E+05 + 4.83500E+02 7.83373E+05 + 4.83600E+02 7.93517E+05 + 4.83700E+02 8.03662E+05 + 4.83800E+02 8.13806E+05 + 4.83900E+02 8.23951E+05 + 4.84000E+02 8.34096E+05 + 4.84100E+02 8.44240E+05 + 4.84200E+02 8.54385E+05 + 4.84300E+02 8.64530E+05 + 4.84400E+02 8.74674E+05 + 4.84500E+02 8.84819E+05 + 4.84600E+02 8.94963E+05 + 4.84700E+02 9.05108E+05 + 4.84800E+02 9.15253E+05 + 4.84900E+02 9.25397E+05 + 4.85000E+02 9.35542E+05 + 4.85100E+02 9.45686E+05 + 4.85200E+02 9.55831E+05 + 4.85300E+02 9.65976E+05 + 4.85400E+02 9.76120E+05 + 4.85500E+02 9.86265E+05 + 4.85600E+02 9.96410E+05 + 4.85700E+02 1.00655E+06 + 4.85800E+02 1.01670E+06 + 4.85900E+02 1.02684E+06 + 4.86000E+02 1.03699E+06 + 4.86100E+02 1.04713E+06 + 4.86200E+02 1.05728E+06 + 4.86300E+02 1.06742E+06 + 4.86400E+02 1.07757E+06 + 4.86500E+02 1.08771E+06 + 4.86600E+02 1.09786E+06 + 4.86700E+02 1.10800E+06 + 4.86800E+02 1.11814E+06 + 4.86900E+02 1.12829E+06 + 4.87000E+02 1.13843E+06 + 4.87100E+02 1.14858E+06 + 4.87200E+02 1.15872E+06 + 4.87300E+02 1.16887E+06 + 4.87400E+02 1.17901E+06 + 4.87500E+02 1.18916E+06 + 4.87600E+02 1.19930E+06 + 4.87700E+02 1.20945E+06 + 4.87800E+02 1.21959E+06 + 4.87900E+02 1.22974E+06 + 4.88000E+02 1.23988E+06 + 4.88100E+02 1.25003E+06 + 4.88200E+02 1.26017E+06 + 4.88300E+02 1.27031E+06 + 4.88400E+02 1.28046E+06 + 4.88500E+02 1.29060E+06 + 4.88600E+02 1.30075E+06 + 4.88700E+02 1.31089E+06 + 4.88800E+02 1.32104E+06 + 4.88900E+02 1.33118E+06 + 4.89000E+02 1.34133E+06 + 4.89100E+02 1.35147E+06 + 4.89200E+02 1.36162E+06 + 4.89300E+02 1.37176E+06 + 4.89400E+02 1.38191E+06 + 4.89500E+02 1.39205E+06 + 4.89600E+02 1.40219E+06 + 4.89700E+02 1.41234E+06 + 4.89800E+02 1.42248E+06 + 4.89900E+02 1.43263E+06 + 4.90000E+02 1.44277E+06 + 4.90100E+02 1.40219E+06 + 4.90200E+02 1.36162E+06 + 4.90300E+02 1.32104E+06 + 4.90400E+02 1.28046E+06 + 4.90500E+02 1.23988E+06 + 4.90600E+02 1.19930E+06 + 4.90700E+02 1.15872E+06 + 4.90800E+02 1.11815E+06 + 4.90900E+02 1.07757E+06 + 4.91000E+02 1.03699E+06 + 4.91100E+02 9.96410E+05 + 4.91200E+02 9.55831E+05 + 4.91300E+02 9.15253E+05 + 4.91400E+02 8.74674E+05 + 4.91500E+02 8.34096E+05 + 4.91600E+02 7.93517E+05 + 4.91700E+02 7.52939E+05 + 4.91800E+02 7.12360E+05 + 4.91900E+02 6.71782E+05 + 4.92000E+02 6.31203E+05 + 4.92100E+02 5.90625E+05 + 4.92200E+02 5.50046E+05 + 4.92300E+02 5.09468E+05 + 4.92400E+02 4.68889E+05 + 4.92500E+02 4.28311E+05 + 4.92600E+02 3.87732E+05 + 4.92700E+02 3.47154E+05 + 4.92800E+02 3.06575E+05 + 4.92900E+02 2.65997E+05 + 4.93000E+02 2.65997E+05 + 4.93100E+02 2.65997E+05 + 4.93200E+02 2.65997E+05 + 4.93300E+02 2.65997E+05 + 4.93400E+02 2.65997E+05 + 4.93500E+02 2.65997E+05 + 4.93600E+02 2.65997E+05 + 4.93700E+02 2.65997E+05 + 4.93800E+02 2.65997E+05 + 4.93900E+02 2.65997E+05 + 4.94000E+02 2.65997E+05 + 4.94100E+02 2.65997E+05 + 4.94200E+02 2.65997E+05 + 4.94300E+02 2.65997E+05 + 4.94400E+02 2.65997E+05 + 4.94500E+02 2.65997E+05 + 4.94600E+02 2.65997E+05 + 4.94700E+02 2.65997E+05 + 4.94800E+02 2.65997E+05 + 4.94900E+02 2.65997E+05 + 4.95000E+02 2.65997E+05 + 4.95100E+02 2.65997E+05 + 4.95200E+02 2.65997E+05 + 4.95300E+02 2.65997E+05 + 4.95400E+02 2.65997E+05 + 4.95500E+02 2.65997E+05 + 4.95600E+02 2.65997E+05 + 4.95700E+02 2.65997E+05 + 4.95800E+02 2.65997E+05 + 4.95900E+02 2.65997E+05 + 4.96000E+02 2.65997E+05 + 4.96100E+02 2.65997E+05 + 4.96200E+02 2.65997E+05 + 4.96300E+02 2.65997E+05 + 4.96400E+02 2.65997E+05 + 4.96500E+02 2.65997E+05 + 4.96600E+02 2.65997E+05 + 4.96700E+02 2.65997E+05 + 4.96800E+02 2.65997E+05 + 4.96900E+02 2.65997E+05 + 4.97000E+02 2.65997E+05 + 4.97100E+02 2.65997E+05 + 4.97200E+02 2.65997E+05 + 4.97300E+02 2.65997E+05 + 4.97400E+02 2.65997E+05 + 4.97500E+02 2.65997E+05 + 4.97600E+02 2.65997E+05 + 4.97700E+02 2.65997E+05 + 4.97800E+02 2.65997E+05 + 4.97900E+02 2.65997E+05 + 4.98000E+02 2.65997E+05 + 4.98100E+02 2.65997E+05 + 4.98200E+02 2.65997E+05 + 4.98300E+02 2.65997E+05 + 4.98400E+02 2.65997E+05 + 4.98500E+02 2.65997E+05 + 4.98600E+02 2.65997E+05 + 4.98700E+02 2.65997E+05 + 4.98800E+02 2.65997E+05 + 4.98900E+02 2.65997E+05 + 4.99000E+02 2.65997E+05 + 4.99100E+02 2.65997E+05 + 4.99200E+02 2.65997E+05 + 4.99300E+02 2.65997E+05 + 4.99400E+02 2.65997E+05 + 4.99500E+02 2.65997E+05 + 4.99600E+02 2.65997E+05 + 4.99700E+02 2.65997E+05 + 4.99800E+02 2.65997E+05 + 4.99900E+02 2.65997E+05 + 5.00000E+02 2.65997E+05 + 5.00100E+02 2.65997E+05 + 5.00200E+02 2.65997E+05 + 5.00300E+02 2.65997E+05 + 5.00400E+02 2.65997E+05 + 5.00500E+02 2.65997E+05 + 5.00600E+02 2.65997E+05 + 5.00700E+02 2.65997E+05 + 5.00800E+02 2.65997E+05 + 5.00900E+02 2.65997E+05 + 5.01000E+02 2.65997E+05 + 5.01100E+02 2.65997E+05 + 5.01200E+02 2.65997E+05 + 5.01300E+02 2.65997E+05 + 5.01400E+02 2.65997E+05 + 5.01500E+02 2.65997E+05 + 5.01600E+02 2.65997E+05 + 5.01700E+02 2.65997E+05 + 5.01800E+02 2.65997E+05 + 5.01900E+02 2.65997E+05 + 5.02000E+02 2.65997E+05 + 5.02100E+02 2.65997E+05 + 5.02200E+02 2.65997E+05 + 5.02300E+02 2.65997E+05 + 5.02400E+02 2.65997E+05 + 5.02500E+02 2.65997E+05 + 5.02600E+02 2.65997E+05 + 5.02700E+02 2.69496E+05 + 5.02800E+02 2.72994E+05 + 5.02900E+02 2.76493E+05 + 5.03000E+02 2.79992E+05 + 5.03100E+02 2.83491E+05 + 5.03200E+02 2.86989E+05 + 5.03300E+02 2.90488E+05 + 5.03400E+02 2.93987E+05 + 5.03500E+02 2.97486E+05 + 5.03600E+02 3.00984E+05 + 5.03700E+02 3.04483E+05 + 5.03800E+02 3.07982E+05 + 5.03900E+02 3.11481E+05 + 5.04000E+02 3.14979E+05 + 5.04100E+02 3.18478E+05 + 5.04200E+02 3.21977E+05 + 5.04300E+02 3.25476E+05 + 5.04400E+02 3.28974E+05 + 5.04500E+02 3.32473E+05 + 5.04600E+02 3.35972E+05 + 5.04700E+02 3.39471E+05 + 5.04800E+02 3.42969E+05 + 5.04900E+02 3.46468E+05 + 5.05000E+02 3.49967E+05 + 5.05100E+02 3.53466E+05 + 5.05200E+02 3.56964E+05 + 5.05300E+02 3.60463E+05 + 5.05400E+02 3.63962E+05 + 5.05500E+02 3.67461E+05 + 5.05600E+02 3.70959E+05 + 5.05700E+02 3.74458E+05 + 5.05800E+02 3.77957E+05 + 5.05900E+02 3.81456E+05 + 5.06000E+02 3.84954E+05 + 5.06100E+02 3.88453E+05 + 5.06200E+02 3.91952E+05 + 5.06300E+02 3.95451E+05 + 5.06400E+02 3.98949E+05 + 5.06500E+02 4.02448E+05 + 5.06600E+02 4.05947E+05 + 5.06700E+02 4.09446E+05 + 5.06800E+02 4.12944E+05 + 5.06900E+02 4.16443E+05 + 5.07000E+02 4.19942E+05 + 5.07100E+02 4.23441E+05 + 5.07200E+02 4.26939E+05 + 5.07300E+02 4.30438E+05 + 5.07400E+02 4.33937E+05 + 5.07500E+02 4.37436E+05 + 5.07600E+02 4.40934E+05 + 5.07700E+02 4.44433E+05 + 5.07800E+02 4.47932E+05 + 5.07900E+02 4.51431E+05 + 5.08000E+02 4.54929E+05 + 5.08100E+02 4.58428E+05 + 5.08200E+02 4.61927E+05 + 5.08300E+02 4.65426E+05 + 5.08400E+02 4.68924E+05 + 5.08500E+02 4.72423E+05 + 5.08600E+02 4.75922E+05 + 5.08700E+02 4.79421E+05 + 5.08800E+02 4.82919E+05 + 5.08900E+02 4.86418E+05 + 5.09000E+02 4.89917E+05 + 5.09100E+02 4.93416E+05 + 5.09200E+02 4.96914E+05 + 5.09300E+02 5.00413E+05 + 5.09400E+02 5.03912E+05 + 5.09500E+02 5.07411E+05 + 5.09600E+02 5.10909E+05 + 5.09700E+02 5.14408E+05 + 5.09800E+02 5.17907E+05 + 5.09900E+02 5.21406E+05 + 5.10000E+02 5.24904E+05 + 5.10100E+02 5.28403E+05 + 5.10200E+02 5.31902E+05 + 5.10300E+02 5.35401E+05 + 5.10400E+02 5.38899E+05 + 5.10500E+02 5.42398E+05 + 5.10600E+02 5.45897E+05 + 5.10700E+02 5.49396E+05 + 5.10800E+02 5.52894E+05 + 5.10900E+02 5.56393E+05 + 5.11000E+02 5.59892E+05 + 5.11100E+02 5.63391E+05 + 5.11200E+02 5.66890E+05 + 5.11300E+02 5.70388E+05 + 5.11400E+02 5.73887E+05 + 5.11500E+02 5.77386E+05 + 5.11600E+02 5.80884E+05 + 5.11700E+02 5.84383E+05 + 5.11800E+02 5.87882E+05 + 5.11900E+02 5.91381E+05 + 5.12000E+02 5.94880E+05 + 5.12100E+02 5.98378E+05 + 5.12200E+02 6.01877E+05 + 5.12300E+02 6.05376E+05 + 5.12400E+02 6.08874E+05 + 5.12500E+02 6.12373E+05 + 5.12600E+02 6.15872E+05 + 5.12700E+02 6.19371E+05 + 5.12800E+02 6.22870E+05 + 5.12900E+02 6.26368E+05 + 5.13000E+02 6.29867E+05 + 5.13100E+02 6.33366E+05 + 5.13200E+02 6.36864E+05 + 5.13300E+02 6.40363E+05 + 5.13400E+02 6.43862E+05 + 5.13500E+02 6.47361E+05 + 5.13600E+02 6.33236E+05 + 5.13700E+02 6.19112E+05 + 5.13800E+02 6.04987E+05 + 5.13900E+02 5.90862E+05 + 5.14000E+02 5.76738E+05 + 5.14100E+02 5.62613E+05 + 5.14200E+02 5.48489E+05 + 5.14300E+02 5.34364E+05 + 5.14400E+02 5.20239E+05 + 5.14500E+02 5.06115E+05 + 5.14600E+02 4.91990E+05 + 5.14700E+02 4.77866E+05 + 5.14800E+02 4.63741E+05 + 5.14900E+02 4.49616E+05 + 5.15000E+02 4.35492E+05 + 5.15100E+02 4.21367E+05 + 5.15200E+02 4.07243E+05 + 5.15300E+02 3.93118E+05 + 5.15400E+02 3.78994E+05 + 5.15500E+02 3.64869E+05 + 5.15600E+02 3.50744E+05 + 5.15700E+02 3.36620E+05 + 5.15800E+02 3.22495E+05 + 5.15900E+02 3.08371E+05 + 5.16000E+02 2.94246E+05 + 5.16100E+02 2.80121E+05 + 5.16200E+02 2.65997E+05 + 5.16300E+02 2.65997E+05 + 5.16400E+02 2.65997E+05 + 5.16500E+02 2.65997E+05 + 5.16600E+02 2.65997E+05 + 5.16700E+02 2.65997E+05 + 5.16800E+02 2.65997E+05 + 5.16900E+02 2.65997E+05 + 5.17000E+02 2.65997E+05 + 5.17100E+02 2.65997E+05 + 5.17200E+02 2.65997E+05 + 5.17300E+02 2.65997E+05 + 5.17400E+02 2.65997E+05 + 5.17500E+02 2.65997E+05 + 5.17600E+02 2.65997E+05 + 5.17700E+02 2.65997E+05 + 5.17800E+02 2.65997E+05 + 5.17900E+02 2.65997E+05 + 5.18000E+02 2.65997E+05 + 5.18100E+02 2.65997E+05 + 5.18200E+02 2.65997E+05 + 5.18300E+02 2.65997E+05 + 5.18400E+02 2.65997E+05 + 5.18500E+02 2.65997E+05 + 5.18600E+02 2.65997E+05 + 5.18700E+02 2.65997E+05 + 5.18800E+02 2.65997E+05 + 5.18900E+02 2.65997E+05 + 5.19000E+02 2.65997E+05 + 5.19100E+02 2.65997E+05 + 5.19200E+02 2.65997E+05 + 5.19300E+02 2.65997E+05 + 5.19400E+02 2.65997E+05 + 5.19500E+02 2.65997E+05 + 5.19600E+02 2.65997E+05 + 5.19700E+02 2.65997E+05 + 5.19800E+02 2.65997E+05 + 5.19900E+02 2.65997E+05 + 5.20000E+02 2.65997E+05 + 5.20100E+02 2.65997E+05 + 5.20200E+02 2.65997E+05 + 5.20300E+02 2.65997E+05 + 5.20400E+02 2.65997E+05 + 5.20500E+02 2.65997E+05 + 5.20600E+02 2.65997E+05 + 5.20700E+02 2.65997E+05 + 5.20800E+02 2.65997E+05 + 5.20900E+02 2.65997E+05 + 5.21000E+02 2.65997E+05 + 5.21100E+02 2.65997E+05 + 5.21200E+02 2.65997E+05 + 5.21300E+02 2.65997E+05 + 5.21400E+02 2.65997E+05 + 5.21500E+02 2.65997E+05 + 5.21600E+02 2.65997E+05 + 5.21700E+02 2.65997E+05 + 5.21800E+02 2.65997E+05 + 5.21900E+02 2.65997E+05 + 5.22000E+02 2.65997E+05 + 5.22100E+02 2.65997E+05 + 5.22200E+02 2.65997E+05 + 5.22300E+02 2.65997E+05 + 5.22400E+02 2.65997E+05 + 5.22500E+02 2.65997E+05 + 5.22600E+02 2.65997E+05 + 5.22700E+02 2.65997E+05 + 5.22800E+02 2.65997E+05 + 5.22900E+02 2.65997E+05 + 5.23000E+02 2.65997E+05 + 5.23100E+02 2.65997E+05 + 5.23200E+02 2.65997E+05 + 5.23300E+02 2.65997E+05 + 5.23400E+02 2.65997E+05 + 5.23500E+02 2.65997E+05 + 5.23600E+02 2.65997E+05 + 5.23700E+02 2.65997E+05 + 5.23800E+02 2.65997E+05 + 5.23900E+02 2.65997E+05 + 5.24000E+02 2.65997E+05 + 5.24100E+02 2.65997E+05 + 5.24200E+02 2.65997E+05 + 5.24300E+02 2.65997E+05 + 5.24400E+02 2.65997E+05 + 5.24500E+02 2.65997E+05 + 5.24600E+02 2.65997E+05 + 5.24700E+02 2.65997E+05 + 5.24800E+02 2.65997E+05 + 5.24900E+02 2.65997E+05 + 5.25000E+02 2.65997E+05 + 5.25100E+02 2.65997E+05 + 5.25200E+02 2.65997E+05 + 5.25300E+02 2.65997E+05 + 5.25400E+02 2.86997E+05 + 5.25500E+02 3.07996E+05 + 5.25600E+02 3.28996E+05 + 5.25700E+02 3.49996E+05 + 5.25800E+02 3.70996E+05 + 5.25900E+02 3.91995E+05 + 5.26000E+02 4.12995E+05 + 5.26100E+02 4.33995E+05 + 5.26200E+02 4.54995E+05 + 5.26300E+02 4.75994E+05 + 5.26400E+02 4.96994E+05 + 5.26500E+02 5.17994E+05 + 5.26600E+02 5.38994E+05 + 5.26700E+02 5.59993E+05 + 5.26800E+02 5.80993E+05 + 5.26900E+02 6.01993E+05 + 5.27000E+02 6.22993E+05 + 5.27100E+02 6.43992E+05 + 5.27200E+02 6.64992E+05 + 5.27300E+02 6.85992E+05 + 5.27400E+02 7.06992E+05 + 5.27500E+02 7.27991E+05 + 5.27600E+02 7.48991E+05 + 5.27700E+02 7.69991E+05 + 5.27800E+02 7.90991E+05 + 5.27900E+02 8.11990E+05 + 5.28000E+02 8.32990E+05 + 5.28100E+02 8.53990E+05 + 5.28200E+02 8.74990E+05 + 5.28300E+02 8.95989E+05 + 5.28400E+02 9.16989E+05 + 5.28500E+02 9.37989E+05 + 5.28600E+02 9.58989E+05 + 5.28700E+02 9.79988E+05 + 5.28800E+02 1.00099E+06 + 5.28900E+02 1.02199E+06 + 5.29000E+02 1.04299E+06 + 5.29100E+02 1.06399E+06 + 5.29200E+02 1.08499E+06 + 5.29300E+02 1.10599E+06 + 5.29400E+02 1.12699E+06 + 5.29500E+02 1.14799E+06 + 5.29600E+02 1.16899E+06 + 5.29700E+02 1.18999E+06 + 5.29800E+02 1.21099E+06 + 5.29900E+02 1.23199E+06 + 5.30000E+02 1.25299E+06 + 5.30100E+02 1.27398E+06 + 5.30200E+02 1.29498E+06 + 5.30300E+02 1.31598E+06 + 5.30400E+02 1.33698E+06 + 5.30500E+02 1.35798E+06 + 5.30600E+02 1.37898E+06 + 5.30700E+02 1.39998E+06 + 5.30800E+02 1.42098E+06 + 5.30900E+02 1.44198E+06 + 5.31000E+02 1.46298E+06 + 5.31100E+02 1.48398E+06 + 5.31200E+02 1.50498E+06 + 5.31300E+02 1.52598E+06 + 5.31400E+02 1.54698E+06 + 5.31500E+02 1.56798E+06 + 5.31600E+02 1.58898E+06 + 5.31700E+02 1.60998E+06 + 5.31800E+02 1.63098E+06 + 5.31900E+02 1.65198E+06 + 5.32000E+02 1.67298E+06 + 5.32100E+02 1.69398E+06 + 5.32200E+02 1.71498E+06 + 5.32300E+02 1.73598E+06 + 5.32400E+02 1.75698E+06 + 5.32500E+02 1.77798E+06 + 5.32600E+02 1.79898E+06 + 5.32700E+02 1.81998E+06 + 5.32800E+02 1.84098E+06 + 5.32900E+02 1.86198E+06 + 5.33000E+02 1.88298E+06 + 5.33100E+02 1.90398E+06 + 5.33200E+02 1.92498E+06 + 5.33300E+02 1.94598E+06 + 5.33400E+02 1.96698E+06 + 5.33500E+02 1.98798E+06 + 5.33600E+02 2.00898E+06 + 5.33700E+02 2.02998E+06 + 5.33800E+02 2.05098E+06 + 5.33900E+02 2.07198E+06 + 5.34000E+02 2.09298E+06 + 5.34100E+02 2.11397E+06 + 5.34200E+02 2.13497E+06 + 5.34300E+02 2.15597E+06 + 5.34400E+02 2.17697E+06 + 5.34500E+02 2.19797E+06 + 5.34600E+02 2.21897E+06 + 5.34700E+02 2.23997E+06 + 5.34800E+02 2.26097E+06 + 5.34900E+02 2.28197E+06 + 5.35000E+02 2.30297E+06 + 5.35100E+02 2.32397E+06 + 5.35200E+02 2.34497E+06 + 5.35300E+02 2.36597E+06 + 5.35400E+02 2.38697E+06 + 5.35500E+02 2.40797E+06 + 5.35600E+02 2.42897E+06 + 5.35700E+02 2.44997E+06 + 5.35800E+02 2.47097E+06 + 5.35900E+02 2.49197E+06 + 5.36000E+02 2.51297E+06 + 5.36100E+02 2.53397E+06 + 5.36200E+02 2.55497E+06 + 5.36300E+02 2.57597E+06 + 5.36400E+02 2.59697E+06 + 5.36500E+02 2.61797E+06 + 5.36600E+02 2.63897E+06 + 5.36700E+02 2.65997E+06 + 5.36800E+02 2.57447E+06 + 5.36900E+02 2.48897E+06 + 5.37000E+02 2.40347E+06 + 5.37100E+02 2.31797E+06 + 5.37200E+02 2.23247E+06 + 5.37300E+02 2.14697E+06 + 5.37400E+02 2.06148E+06 + 5.37500E+02 1.97598E+06 + 5.37600E+02 1.89048E+06 + 5.37700E+02 1.80498E+06 + 5.37800E+02 1.71948E+06 + 5.37900E+02 1.63398E+06 + 5.38000E+02 1.54848E+06 + 5.38100E+02 1.46298E+06 + 5.38200E+02 1.37748E+06 + 5.38300E+02 1.29198E+06 + 5.38400E+02 1.20649E+06 + 5.38500E+02 1.12099E+06 + 5.38600E+02 1.03549E+06 + 5.38700E+02 9.49988E+05 + 5.38800E+02 8.64490E+05 + 5.38900E+02 7.78991E+05 + 5.39000E+02 6.93492E+05 + 5.39100E+02 6.07993E+05 + 5.39200E+02 5.22494E+05 + 5.39300E+02 4.36995E+05 + 5.39400E+02 3.51496E+05 + 5.39500E+02 2.65997E+05 + 5.39600E+02 2.65997E+05 + 5.39700E+02 2.65997E+05 + 5.39800E+02 2.65997E+05 + 5.39900E+02 2.65997E+05 + 5.40000E+02 2.65997E+05 + 5.40100E+02 2.65997E+05 + 5.40200E+02 2.65997E+05 + 5.40300E+02 2.65997E+05 + 5.40400E+02 2.65997E+05 + 5.40500E+02 2.65997E+05 + 5.40600E+02 2.65997E+05 + 5.40700E+02 2.65997E+05 + 5.40800E+02 2.65997E+05 + 5.40900E+02 2.65997E+05 + 5.41000E+02 2.65997E+05 + 5.41100E+02 2.65997E+05 + 5.41200E+02 2.65997E+05 + 5.41300E+02 2.65997E+05 + 5.41400E+02 2.65997E+05 + 5.41500E+02 2.65997E+05 + 5.41600E+02 2.65997E+05 + 5.41700E+02 2.65997E+05 + 5.41800E+02 2.65997E+05 + 5.41900E+02 2.65997E+05 + 5.42000E+02 2.65997E+05 + 5.42100E+02 2.65997E+05 + 5.42200E+02 2.65997E+05 + 5.42300E+02 2.65997E+05 + 5.42400E+02 2.65997E+05 + 5.42500E+02 2.65997E+05 + 5.42600E+02 2.65997E+05 + 5.42700E+02 2.65997E+05 + 5.42800E+02 2.65997E+05 + 5.42900E+02 2.65997E+05 + 5.43000E+02 2.65997E+05 + 5.43100E+02 2.65997E+05 + 5.43200E+02 2.65997E+05 + 5.43300E+02 2.65997E+05 + 5.43400E+02 2.65997E+05 + 5.43500E+02 2.65997E+05 + 5.43600E+02 2.65997E+05 + 5.43700E+02 2.65997E+05 + 5.43800E+02 2.65997E+05 + 5.43900E+02 2.65997E+05 + 5.44000E+02 2.65997E+05 + 5.44100E+02 2.65997E+05 + 5.44200E+02 2.65997E+05 + 5.44300E+02 2.65997E+05 + 5.44400E+02 2.65997E+05 + 5.44500E+02 2.65997E+05 + 5.44600E+02 2.65997E+05 + 5.44700E+02 2.65997E+05 + 5.44800E+02 2.65997E+05 + 5.44900E+02 2.65997E+05 + 5.45000E+02 2.65997E+05 + 5.45100E+02 2.65997E+05 + 5.45200E+02 2.65997E+05 + 5.45300E+02 2.65997E+05 + 5.45400E+02 2.65997E+05 + 5.45500E+02 2.65997E+05 + 5.45600E+02 2.65997E+05 + 5.45700E+02 2.65997E+05 + 5.45800E+02 2.65997E+05 + 5.45900E+02 2.65997E+05 + 5.46000E+02 2.65997E+05 + 5.46100E+02 2.65997E+05 + 5.46200E+02 2.65997E+05 + 5.46300E+02 2.65997E+05 + 5.46400E+02 2.65997E+05 + 5.46500E+02 2.65997E+05 + 5.46600E+02 2.65997E+05 + 5.46700E+02 2.65997E+05 + 5.46800E+02 2.65997E+05 + 5.46900E+02 2.65997E+05 + 5.47000E+02 2.65997E+05 + 5.47100E+02 2.65997E+05 + 5.47200E+02 2.65997E+05 + 5.47300E+02 2.65997E+05 + 5.47400E+02 2.65997E+05 + 5.47500E+02 2.65997E+05 + 5.47600E+02 2.65997E+05 + 5.47700E+02 2.65997E+05 + 5.47800E+02 2.65997E+05 + 5.47900E+02 2.65997E+05 + 5.48000E+02 2.65997E+05 + 5.48100E+02 2.65997E+05 + 5.48200E+02 2.65997E+05 + 5.48300E+02 2.65997E+05 + 5.48400E+02 2.65997E+05 + 5.48500E+02 2.65997E+05 + 5.48600E+02 2.65997E+05 + 5.48700E+02 2.65997E+05 + 5.48800E+02 2.65997E+05 + 5.48900E+02 2.65997E+05 + 5.49000E+02 2.65997E+05 + 5.49100E+02 2.80281E+05 + 5.49200E+02 2.94565E+05 + 5.49300E+02 3.08850E+05 + 5.49400E+02 3.23134E+05 + 5.49500E+02 3.37418E+05 + 5.49600E+02 3.51703E+05 + 5.49700E+02 3.65987E+05 + 5.49800E+02 3.80271E+05 + 5.49900E+02 3.94555E+05 + 5.50000E+02 4.08840E+05 + 5.50100E+02 4.23124E+05 + 5.50200E+02 4.37408E+05 + 5.50300E+02 4.51693E+05 + 5.50400E+02 4.65977E+05 + 5.50500E+02 4.80261E+05 + 5.50600E+02 4.94545E+05 + 5.50700E+02 5.08830E+05 + 5.50800E+02 5.23114E+05 + 5.50900E+02 5.37398E+05 + 5.51000E+02 5.51683E+05 + 5.51100E+02 5.65967E+05 + 5.51200E+02 5.80251E+05 + 5.51300E+02 5.94536E+05 + 5.51400E+02 6.08820E+05 + 5.51500E+02 6.23104E+05 + 5.51600E+02 6.37388E+05 + 5.51700E+02 6.51673E+05 + 5.51800E+02 6.65957E+05 + 5.51900E+02 6.80241E+05 + 5.52000E+02 6.94526E+05 + 5.52100E+02 7.08810E+05 + 5.52200E+02 7.23094E+05 + 5.52300E+02 7.37378E+05 + 5.52400E+02 7.51663E+05 + 5.52500E+02 7.65947E+05 + 5.52600E+02 7.80231E+05 + 5.52700E+02 7.94516E+05 + 5.52800E+02 8.08800E+05 + 5.52900E+02 8.23084E+05 + 5.53000E+02 8.37368E+05 + 5.53100E+02 8.51653E+05 + 5.53200E+02 8.65937E+05 + 5.53300E+02 8.80221E+05 + 5.53400E+02 8.94506E+05 + 5.53500E+02 9.08790E+05 + 5.53600E+02 9.23074E+05 + 5.53700E+02 9.37358E+05 + 5.53800E+02 9.51643E+05 + 5.53900E+02 9.65927E+05 + 5.54000E+02 9.80211E+05 + 5.54100E+02 9.94496E+05 + 5.54200E+02 1.00878E+06 + 5.54300E+02 1.02306E+06 + 5.54400E+02 1.03735E+06 + 5.54500E+02 1.05163E+06 + 5.54600E+02 1.06592E+06 + 5.54700E+02 1.08020E+06 + 5.54800E+02 1.09449E+06 + 5.54900E+02 1.10877E+06 + 5.55000E+02 1.12305E+06 + 5.55100E+02 1.13734E+06 + 5.55200E+02 1.15162E+06 + 5.55300E+02 1.16591E+06 + 5.55400E+02 1.18019E+06 + 5.55500E+02 1.19448E+06 + 5.55600E+02 1.20876E+06 + 5.55700E+02 1.22304E+06 + 5.55800E+02 1.23733E+06 + 5.55900E+02 1.25161E+06 + 5.56000E+02 1.26590E+06 + 5.56100E+02 1.28018E+06 + 5.56200E+02 1.29447E+06 + 5.56300E+02 1.30875E+06 + 5.56400E+02 1.32303E+06 + 5.56500E+02 1.33732E+06 + 5.56600E+02 1.35160E+06 + 5.56700E+02 1.36589E+06 + 5.56800E+02 1.38017E+06 + 5.56900E+02 1.39446E+06 + 5.57000E+02 1.40874E+06 + 5.57100E+02 1.42302E+06 + 5.57200E+02 1.43731E+06 + 5.57300E+02 1.45159E+06 + 5.57400E+02 1.46588E+06 + 5.57500E+02 1.48016E+06 + 5.57600E+02 1.49445E+06 + 5.57700E+02 1.50873E+06 + 5.57800E+02 1.52301E+06 + 5.57900E+02 1.53730E+06 + 5.58000E+02 1.55158E+06 + 5.58100E+02 1.56587E+06 + 5.58200E+02 1.58015E+06 + 5.58300E+02 1.59444E+06 + 5.58400E+02 1.60872E+06 + 5.58500E+02 1.62300E+06 + 5.58600E+02 1.63729E+06 + 5.58700E+02 1.65157E+06 + 5.58800E+02 1.66586E+06 + 5.58900E+02 1.68014E+06 + 5.59000E+02 1.69443E+06 + 5.59100E+02 1.70871E+06 + 5.59200E+02 1.72299E+06 + 5.59300E+02 1.73728E+06 + 5.59400E+02 1.75156E+06 + 5.59500E+02 1.76585E+06 + 5.59600E+02 1.78013E+06 + 5.59700E+02 1.79442E+06 + 5.59800E+02 1.73781E+06 + 5.59900E+02 1.68120E+06 + 5.60000E+02 1.62459E+06 + 5.60100E+02 1.56798E+06 + 5.60200E+02 1.51138E+06 + 5.60300E+02 1.45477E+06 + 5.60400E+02 1.39816E+06 + 5.60500E+02 1.34155E+06 + 5.60600E+02 1.28494E+06 + 5.60700E+02 1.22833E+06 + 5.60800E+02 1.17173E+06 + 5.60900E+02 1.11512E+06 + 5.61000E+02 1.05851E+06 + 5.61100E+02 1.00190E+06 + 5.61200E+02 9.45294E+05 + 5.61300E+02 8.88686E+05 + 5.61400E+02 8.32078E+05 + 5.61500E+02 7.75470E+05 + 5.61600E+02 7.18862E+05 + 5.61700E+02 6.62254E+05 + 5.61800E+02 6.05646E+05 + 5.61900E+02 5.49037E+05 + 5.62000E+02 4.92429E+05 + 5.62100E+02 4.35821E+05 + 5.62200E+02 3.79213E+05 + 5.62300E+02 3.22605E+05 + 5.62400E+02 2.65997E+05 + 5.62500E+02 2.65997E+05 + 5.62600E+02 2.65997E+05 + 5.62700E+02 2.65997E+05 + 5.62800E+02 2.65997E+05 + 5.62900E+02 2.65997E+05 + 5.63000E+02 2.65997E+05 + 5.63100E+02 2.65997E+05 + 5.63200E+02 2.65997E+05 + 5.63300E+02 2.65997E+05 + 5.63400E+02 2.65997E+05 + 5.63500E+02 2.65997E+05 + 5.63600E+02 2.65997E+05 + 5.63700E+02 2.65997E+05 + 5.63800E+02 2.65997E+05 + 5.63900E+02 2.65997E+05 + 5.64000E+02 2.65997E+05 + 5.64100E+02 2.65997E+05 + 5.64200E+02 2.65997E+05 + 5.64300E+02 2.65997E+05 + 5.64400E+02 2.65997E+05 + 5.64500E+02 2.65997E+05 + 5.64600E+02 2.65997E+05 + 5.64700E+02 2.65997E+05 + 5.64800E+02 2.65997E+05 + 5.64900E+02 2.65997E+05 + 5.65000E+02 2.65997E+05 + 5.65100E+02 2.65997E+05 + 5.65200E+02 2.65997E+05 + 5.65300E+02 2.65997E+05 + 5.65400E+02 2.65997E+05 + 5.65500E+02 2.65997E+05 + 5.65600E+02 2.65997E+05 + 5.65700E+02 2.65997E+05 + 5.65800E+02 2.65997E+05 + 5.65900E+02 2.65997E+05 + 5.66000E+02 2.65997E+05 + 5.66100E+02 2.65997E+05 + 5.66200E+02 2.65997E+05 + 5.66300E+02 2.65997E+05 + 5.66400E+02 2.65997E+05 + 5.66500E+02 2.65997E+05 + 5.66600E+02 2.65997E+05 + 5.66700E+02 2.65997E+05 + 5.66800E+02 2.65997E+05 + 5.66900E+02 2.65997E+05 + 5.67000E+02 2.65997E+05 + 5.67100E+02 2.65997E+05 + 5.67200E+02 2.65997E+05 + 5.67300E+02 2.65997E+05 + 5.67400E+02 2.65997E+05 + 5.67500E+02 2.65997E+05 + 5.67600E+02 2.65997E+05 + 5.67700E+02 2.65997E+05 + 5.67800E+02 2.65997E+05 + 5.67900E+02 2.65997E+05 + 5.68000E+02 2.65997E+05 + 5.68100E+02 2.65997E+05 + 5.68200E+02 2.65997E+05 + 5.68300E+02 2.65997E+05 + 5.68400E+02 2.65997E+05 + 5.68500E+02 2.65997E+05 + 5.68600E+02 2.65997E+05 + 5.68700E+02 2.65997E+05 + 5.68800E+02 2.65997E+05 + 5.68900E+02 2.65997E+05 + 5.69000E+02 2.65997E+05 + 5.69100E+02 2.65997E+05 + 5.69200E+02 2.65997E+05 + 5.69300E+02 2.65997E+05 + 5.69400E+02 2.65997E+05 + 5.69500E+02 2.65997E+05 + 5.69600E+02 2.65997E+05 + 5.69700E+02 2.65997E+05 + 5.69800E+02 2.65997E+05 + 5.69900E+02 2.65997E+05 + 5.70000E+02 2.65997E+05 + 5.70100E+02 2.65997E+05 + 5.70200E+02 2.65997E+05 + 5.70300E+02 2.65997E+05 + 5.70400E+02 2.65997E+05 + 5.70500E+02 2.65997E+05 + 5.70600E+02 2.65997E+05 + 5.70700E+02 2.65997E+05 + 5.70800E+02 2.65997E+05 + 5.70900E+02 2.65997E+05 + 5.71000E+02 2.65997E+05 + 5.71100E+02 2.65997E+05 + 5.71200E+02 2.65997E+05 + 5.71300E+02 2.65997E+05 + 5.71400E+02 2.78027E+05 + 5.71500E+02 2.90056E+05 + 5.71600E+02 3.02086E+05 + 5.71700E+02 3.14116E+05 + 5.71800E+02 3.26145E+05 + 5.71900E+02 3.38175E+05 + 5.72000E+02 3.50205E+05 + 5.72100E+02 3.62235E+05 + 5.72200E+02 3.74264E+05 + 5.72300E+02 3.86294E+05 + 5.72400E+02 3.98324E+05 + 5.72500E+02 4.10354E+05 + 5.72600E+02 4.22383E+05 + 5.72700E+02 4.34413E+05 + 5.72800E+02 4.46443E+05 + 5.72900E+02 4.58472E+05 + 5.73000E+02 4.70502E+05 + 5.73100E+02 4.82532E+05 + 5.73200E+02 4.94562E+05 + 5.73300E+02 5.06591E+05 + 5.73400E+02 5.18621E+05 + 5.73500E+02 5.30651E+05 + 5.73600E+02 5.42680E+05 + 5.73700E+02 5.54710E+05 + 5.73800E+02 5.66740E+05 + 5.73900E+02 5.78770E+05 + 5.74000E+02 5.90799E+05 + 5.74100E+02 6.02829E+05 + 5.74200E+02 6.14859E+05 + 5.74300E+02 6.26889E+05 + 5.74400E+02 6.38918E+05 + 5.74500E+02 6.50948E+05 + 5.74600E+02 6.62978E+05 + 5.74700E+02 6.75008E+05 + 5.74800E+02 6.87037E+05 + 5.74900E+02 6.99067E+05 + 5.75000E+02 7.11097E+05 + 5.75100E+02 7.23126E+05 + 5.75200E+02 7.35156E+05 + 5.75300E+02 7.47186E+05 + 5.75400E+02 7.59216E+05 + 5.75500E+02 7.71245E+05 + 5.75600E+02 7.83275E+05 + 5.75700E+02 7.95305E+05 + 5.75800E+02 8.07334E+05 + 5.75900E+02 8.19364E+05 + 5.76000E+02 8.31394E+05 + 5.76100E+02 8.43424E+05 + 5.76200E+02 8.55453E+05 + 5.76300E+02 8.67483E+05 + 5.76400E+02 8.79513E+05 + 5.76500E+02 8.91543E+05 + 5.76600E+02 9.03572E+05 + 5.76700E+02 9.15602E+05 + 5.76800E+02 9.27632E+05 + 5.76900E+02 9.39662E+05 + 5.77000E+02 9.51691E+05 + 5.77100E+02 9.63721E+05 + 5.77200E+02 9.75751E+05 + 5.77300E+02 9.87780E+05 + 5.77400E+02 9.99810E+05 + 5.77500E+02 1.01184E+06 + 5.77600E+02 1.02387E+06 + 5.77700E+02 1.03590E+06 + 5.77800E+02 1.04793E+06 + 5.77900E+02 1.05996E+06 + 5.78000E+02 1.07199E+06 + 5.78100E+02 1.08402E+06 + 5.78200E+02 1.09605E+06 + 5.78300E+02 1.10808E+06 + 5.78400E+02 1.12011E+06 + 5.78500E+02 1.13214E+06 + 5.78600E+02 1.14417E+06 + 5.78700E+02 1.15620E+06 + 5.78800E+02 1.16823E+06 + 5.78900E+02 1.18026E+06 + 5.79000E+02 1.19229E+06 + 5.79100E+02 1.20432E+06 + 5.79200E+02 1.21635E+06 + 5.79300E+02 1.22837E+06 + 5.79400E+02 1.24040E+06 + 5.79500E+02 1.25243E+06 + 5.79600E+02 1.26446E+06 + 5.79700E+02 1.27649E+06 + 5.79800E+02 1.28852E+06 + 5.79900E+02 1.30055E+06 + 5.80000E+02 1.31258E+06 + 5.80100E+02 1.32461E+06 + 5.80200E+02 1.33664E+06 + 5.80300E+02 1.34867E+06 + 5.80400E+02 1.36070E+06 + 5.80500E+02 1.37273E+06 + 5.80600E+02 1.38476E+06 + 5.80700E+02 1.39679E+06 + 5.80800E+02 1.40882E+06 + 5.80900E+02 1.42085E+06 + 5.81000E+02 1.43288E+06 + 5.81100E+02 1.38426E+06 + 5.81200E+02 1.33564E+06 + 5.81300E+02 1.28702E+06 + 5.81400E+02 1.23840E+06 + 5.81500E+02 1.18978E+06 + 5.81600E+02 1.14116E+06 + 5.81700E+02 1.09254E+06 + 5.81800E+02 1.04392E+06 + 5.81900E+02 9.95299E+05 + 5.82000E+02 9.46679E+05 + 5.82100E+02 8.98059E+05 + 5.82200E+02 8.49439E+05 + 5.82300E+02 8.00818E+05 + 5.82400E+02 7.52198E+05 + 5.82500E+02 7.03578E+05 + 5.82600E+02 6.54958E+05 + 5.82700E+02 6.06338E+05 + 5.82800E+02 5.57718E+05 + 5.82900E+02 5.09098E+05 + 5.83000E+02 4.60477E+05 + 5.83100E+02 4.11857E+05 + 5.83200E+02 3.63237E+05 + 5.83300E+02 3.14617E+05 + 5.83400E+02 2.65997E+05 + 5.83500E+02 2.65997E+05 + 5.83600E+02 2.65997E+05 + 5.83700E+02 2.65997E+05 + 5.83800E+02 2.65997E+05 + 5.83900E+02 2.65997E+05 + 5.84000E+02 2.65997E+05 + 5.84100E+02 2.65997E+05 + 5.84200E+02 2.65997E+05 + 5.84300E+02 2.65997E+05 + 5.84400E+02 2.65997E+05 + 5.84500E+02 2.65997E+05 + 5.84600E+02 2.65997E+05 + 5.84700E+02 2.65997E+05 + 5.84800E+02 2.65997E+05 + 5.84900E+02 2.65997E+05 + 5.85000E+02 2.65997E+05 + 5.85100E+02 2.65997E+05 + 5.85200E+02 2.65997E+05 + 5.85300E+02 2.65997E+05 + 5.85400E+02 2.65997E+05 + 5.85500E+02 2.65997E+05 + 5.85600E+02 2.65997E+05 + 5.85700E+02 2.65997E+05 + 5.85800E+02 2.65997E+05 + 5.85900E+02 2.65997E+05 + 5.86000E+02 2.65997E+05 + 5.86100E+02 2.65997E+05 + 5.86200E+02 2.65997E+05 + 5.86300E+02 2.65997E+05 + 5.86400E+02 2.65997E+05 + 5.86500E+02 2.65997E+05 + 5.86600E+02 2.65997E+05 + 5.86700E+02 2.65997E+05 + 5.86800E+02 2.65997E+05 + 5.86900E+02 2.65997E+05 + 5.87000E+02 2.65997E+05 + 5.87100E+02 2.65997E+05 + 5.87200E+02 2.65997E+05 + 5.87300E+02 2.65997E+05 + 5.87400E+02 2.65997E+05 + 5.87500E+02 2.65997E+05 + 5.87600E+02 2.65997E+05 + 5.87700E+02 2.65997E+05 + 5.87800E+02 2.65997E+05 + 5.87900E+02 2.65997E+05 + 5.88000E+02 2.65997E+05 + 5.88100E+02 2.65997E+05 + 5.88200E+02 2.65997E+05 + 5.88300E+02 2.65997E+05 + 5.88400E+02 2.65997E+05 + 5.88500E+02 2.65997E+05 + 5.88600E+02 2.65997E+05 + 5.88700E+02 2.65997E+05 + 5.88800E+02 2.65997E+05 + 5.88900E+02 2.65997E+05 + 5.89000E+02 2.65997E+05 + 5.89100E+02 2.65997E+05 + 5.89200E+02 2.65997E+05 + 5.89300E+02 2.65997E+05 + 5.89400E+02 2.65997E+05 + 5.89500E+02 2.65997E+05 + 5.89600E+02 2.65997E+05 + 5.89700E+02 2.65997E+05 + 5.89800E+02 2.65997E+05 + 5.89900E+02 2.65997E+05 + 5.90000E+02 2.65997E+05 + 5.90100E+02 2.65997E+05 + 5.90200E+02 2.65997E+05 + 5.90300E+02 2.65997E+05 + 5.90400E+02 2.65997E+05 + 5.90500E+02 2.65997E+05 + 5.90600E+02 2.65997E+05 + 5.90700E+02 2.65997E+05 + 5.90800E+02 2.65997E+05 + 5.90900E+02 2.65997E+05 + 5.91000E+02 2.65997E+05 + 5.91100E+02 2.65997E+05 + 5.91200E+02 2.65997E+05 + 5.91300E+02 2.65997E+05 + 5.91400E+02 2.65997E+05 + 5.91500E+02 2.86530E+05 + 5.91600E+02 3.07062E+05 + 5.91700E+02 3.27595E+05 + 5.91800E+02 3.48128E+05 + 5.91900E+02 3.68660E+05 + 5.92000E+02 3.89193E+05 + 5.92100E+02 4.09726E+05 + 5.92200E+02 4.30258E+05 + 5.92300E+02 4.50791E+05 + 5.92400E+02 4.71324E+05 + 5.92500E+02 4.91856E+05 + 5.92600E+02 5.12389E+05 + 5.92700E+02 5.32922E+05 + 5.92800E+02 5.53454E+05 + 5.92900E+02 5.73987E+05 + 5.93000E+02 5.94520E+05 + 5.93100E+02 6.15052E+05 + 5.93200E+02 6.35585E+05 + 5.93300E+02 6.56118E+05 + 5.93400E+02 6.76650E+05 + 5.93500E+02 6.97183E+05 + 5.93600E+02 7.17716E+05 + 5.93700E+02 7.38248E+05 + 5.93800E+02 7.58781E+05 + 5.93900E+02 7.79314E+05 + 5.94000E+02 7.99846E+05 + 5.94100E+02 8.20379E+05 + 5.94200E+02 8.40912E+05 + 5.94300E+02 8.61444E+05 + 5.94400E+02 8.81977E+05 + 5.94500E+02 9.02510E+05 + 5.94600E+02 9.23042E+05 + 5.94700E+02 9.43575E+05 + 5.94800E+02 9.64108E+05 + 5.94900E+02 9.84640E+05 + 5.95000E+02 1.00517E+06 + 5.95100E+02 1.02571E+06 + 5.95200E+02 1.04624E+06 + 5.95300E+02 1.06677E+06 + 5.95400E+02 1.08730E+06 + 5.95500E+02 1.10784E+06 + 5.95600E+02 1.12837E+06 + 5.95700E+02 1.14890E+06 + 5.95800E+02 1.16943E+06 + 5.95900E+02 1.18997E+06 + 5.96000E+02 1.21050E+06 + 5.96100E+02 1.23103E+06 + 5.96200E+02 1.25156E+06 + 5.96300E+02 1.27210E+06 + 5.96400E+02 1.29263E+06 + 5.96500E+02 1.31316E+06 + 5.96600E+02 1.33370E+06 + 5.96700E+02 1.35423E+06 + 5.96800E+02 1.37476E+06 + 5.96900E+02 1.39529E+06 + 5.97000E+02 1.41583E+06 + 5.97100E+02 1.43636E+06 + 5.97200E+02 1.45689E+06 + 5.97300E+02 1.47742E+06 + 5.97400E+02 1.49796E+06 + 5.97500E+02 1.51849E+06 + 5.97600E+02 1.53902E+06 + 5.97700E+02 1.55956E+06 + 5.97800E+02 1.58009E+06 + 5.97900E+02 1.60062E+06 + 5.98000E+02 1.62115E+06 + 5.98100E+02 1.64169E+06 + 5.98200E+02 1.66222E+06 + 5.98300E+02 1.68275E+06 + 5.98400E+02 1.70328E+06 + 5.98500E+02 1.72382E+06 + 5.98600E+02 1.74435E+06 + 5.98700E+02 1.76488E+06 + 5.98800E+02 1.78541E+06 + 5.98900E+02 1.80595E+06 + 5.99000E+02 1.72490E+06 + 5.99100E+02 1.64385E+06 + 5.99200E+02 1.56280E+06 + 5.99300E+02 1.48175E+06 + 5.99400E+02 1.40070E+06 + 5.99500E+02 1.31965E+06 + 5.99600E+02 1.23860E+06 + 5.99700E+02 1.15755E+06 + 5.99800E+02 1.07650E+06 + 5.99900E+02 9.95447E+05 + 6.00000E+02 9.14397E+05 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.log b/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.log new file mode 100644 index 000000000..88efb643e --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_flex_ISO.log @@ -0,0 +1,56 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:25:25 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 6 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting common flexural failure input parameters + flexStrength = 7.00000E+05 Pascals + towerConeAngle = 60 degrees + ice2twrFriction = 0.15 + iceDensity = 916.2 kg/m^3 + Breaking term, Hb term is included + Rubble pushing term, Hr term is included + + Setting up flexural failure by ISO/Croasdale method + Based on the ISO 19906 standard equations for max static loads + peakLoadCOV = 0.2 (-) + coeffLoadPeaks = 0.56 + coeffLoadMin = 0.1 + periodCOV = 0.5 + tauMin = 0.6 + tauMax = 0.6 + riseTime = 0.8 + coeffBreakLength = 4 + rubbleHeight = 3 meters + rubblePorosity = 0.3 + rubbleCohesion strength = 0 Pascals + rubbleAngle = 40 degrees + frictionAngle = 45 degrees + ice2iceFriction = 5.00000E-02 + waterDensity = 999.8 kg/m^3 + iceModulus = 8.00000E+09 Pascals + poissonRatio = 0.3 + Including pile up term, Hp + Including rubble lifting term, Hl + Including block rotation term, Ht + Including crack lenght modification term, Lc +** Pile up term, Hp = 2242 Newtons +** Rubble lifting term, Hl = 2.09678E+05 Newtons +** Block rotation term, Ht = 42609 Newtons +** Rubble push through term, Hr = 4.08262E+05 Newtons +** Breaking load term, Hb = 1.84414E+06 Newtons +** Maximum static load for flexural failure = 2.65997E+06 Newtons + + ISO/Croasdale ice flexural failure loads initialized + diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.dat b/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.dat new file mode 100644 index 000000000..b99c50b64 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 2.83424E+04 + 2.00000E-01 1.13369E+05 + 3.00000E-01 2.55081E+05 + 4.00000E-01 4.53478E+05 + 5.00000E-01 7.08559E+05 + 6.00000E-01 1.02033E+06 + 7.00000E-01 1.38878E+06 + 8.00000E-01 1.81391E+06 + 9.00000E-01 2.29573E+06 + 1.00000E+00 2.83424E+06 + 1.10000E+00 3.11766E+06 + 1.20000E+00 3.40108E+06 + 1.30000E+00 3.68451E+06 + 1.40000E+00 3.96793E+06 + 1.50000E+00 4.25136E+06 + 1.60000E+00 4.53478E+06 + 1.70000E+00 4.81820E+06 + 1.80000E+00 5.10163E+06 + 1.90000E+00 5.38505E+06 + 2.00000E+00 5.66847E+06 + 2.10000E+00 5.95190E+06 + 2.20000E+00 6.23532E+06 + 2.30000E+00 6.51875E+06 + 2.40000E+00 6.80217E+06 + 2.50000E+00 7.08559E+06 + 2.60000E+00 7.36902E+06 + 2.70000E+00 7.65244E+06 + 2.80000E+00 7.93586E+06 + 2.90000E+00 8.21929E+06 + 3.00000E+00 8.50271E+06 + 3.10000E+00 8.50271E+06 + 3.20000E+00 7.55797E+06 + 3.30000E+00 6.61322E+06 + 3.40000E+00 5.66848E+06 + 3.50000E+00 4.72373E+06 + 3.60000E+00 3.77898E+06 + 3.70000E+00 2.83424E+06 + 3.80000E+00 1.88949E+06 + 3.90000E+00 9.44746E+05 + 4.00000E+00 0.00000E+00 + 4.10000E+00 0.00000E+00 + 4.20000E+00 0.00000E+00 + 4.30000E+00 0.00000E+00 + 4.40000E+00 0.00000E+00 + 4.50000E+00 0.00000E+00 + 4.60000E+00 0.00000E+00 + 4.70000E+00 0.00000E+00 + 4.80000E+00 0.00000E+00 + 4.90000E+00 0.00000E+00 + 5.00000E+00 0.00000E+00 + 5.10000E+00 0.00000E+00 + 5.20000E+00 0.00000E+00 + 5.30000E+00 0.00000E+00 + 5.40000E+00 0.00000E+00 + 5.50000E+00 0.00000E+00 + 5.60000E+00 0.00000E+00 + 5.70000E+00 0.00000E+00 + 5.80000E+00 0.00000E+00 + 5.90000E+00 0.00000E+00 + 6.00000E+00 0.00000E+00 + 6.10000E+00 2.83424E+05 + 6.20000E+00 5.66847E+05 + 6.30000E+00 8.50271E+05 + 6.40000E+00 1.13369E+06 + 6.50000E+00 1.41712E+06 + 6.60000E+00 1.70054E+06 + 6.70000E+00 1.98397E+06 + 6.80000E+00 2.26739E+06 + 6.90000E+00 2.55081E+06 + 7.00000E+00 2.83424E+06 + 7.10000E+00 3.11766E+06 + 7.20000E+00 3.40108E+06 + 7.30000E+00 3.68451E+06 + 7.40000E+00 3.96793E+06 + 7.50000E+00 4.25136E+06 + 7.60000E+00 4.53478E+06 + 7.70000E+00 4.81820E+06 + 7.80000E+00 5.10163E+06 + 7.90000E+00 5.38505E+06 + 8.00000E+00 5.66847E+06 + 8.10000E+00 5.95190E+06 + 8.20000E+00 6.23532E+06 + 8.30000E+00 6.51875E+06 + 8.40000E+00 6.80217E+06 + 8.50000E+00 7.08559E+06 + 8.60000E+00 7.36902E+06 + 8.70000E+00 7.65244E+06 + 8.80000E+00 7.93586E+06 + 8.90000E+00 8.21929E+06 + 9.00000E+00 8.50271E+06 + 9.10000E+00 8.50271E+06 + 9.20000E+00 7.55797E+06 + 9.30000E+00 6.61322E+06 + 9.40000E+00 5.66848E+06 + 9.50000E+00 4.72373E+06 + 9.60000E+00 3.77898E+06 + 9.70000E+00 2.83424E+06 + 9.80000E+00 1.88949E+06 + 9.90000E+00 9.44746E+05 + 1.00000E+01 0.00000E+00 + 1.01000E+01 0.00000E+00 + 1.02000E+01 0.00000E+00 + 1.03000E+01 0.00000E+00 + 1.04000E+01 0.00000E+00 + 1.05000E+01 0.00000E+00 + 1.06000E+01 0.00000E+00 + 1.07000E+01 0.00000E+00 + 1.08000E+01 0.00000E+00 + 1.09000E+01 0.00000E+00 + 1.10000E+01 0.00000E+00 + 1.11000E+01 0.00000E+00 + 1.12000E+01 0.00000E+00 + 1.13000E+01 0.00000E+00 + 1.14000E+01 0.00000E+00 + 1.15000E+01 0.00000E+00 + 1.16000E+01 0.00000E+00 + 1.17000E+01 0.00000E+00 + 1.18000E+01 0.00000E+00 + 1.19000E+01 0.00000E+00 + 1.20000E+01 0.00000E+00 + 1.21000E+01 2.83424E+05 + 1.22000E+01 5.66847E+05 + 1.23000E+01 8.50271E+05 + 1.24000E+01 1.13369E+06 + 1.25000E+01 1.41712E+06 + 1.26000E+01 1.70054E+06 + 1.27000E+01 1.98397E+06 + 1.28000E+01 2.26739E+06 + 1.29000E+01 2.55081E+06 + 1.30000E+01 2.83424E+06 + 1.31000E+01 3.11766E+06 + 1.32000E+01 3.40108E+06 + 1.33000E+01 3.68451E+06 + 1.34000E+01 3.96793E+06 + 1.35000E+01 4.25136E+06 + 1.36000E+01 4.53478E+06 + 1.37000E+01 4.81820E+06 + 1.38000E+01 5.10163E+06 + 1.39000E+01 5.38505E+06 + 1.40000E+01 5.66847E+06 + 1.41000E+01 5.95190E+06 + 1.42000E+01 6.23532E+06 + 1.43000E+01 6.51875E+06 + 1.44000E+01 6.80217E+06 + 1.45000E+01 7.08559E+06 + 1.46000E+01 7.36902E+06 + 1.47000E+01 7.65244E+06 + 1.48000E+01 7.93586E+06 + 1.49000E+01 8.21929E+06 + 1.50000E+01 8.50271E+06 + 1.51000E+01 8.50271E+06 + 1.52000E+01 7.55797E+06 + 1.53000E+01 6.61322E+06 + 1.54000E+01 5.66848E+06 + 1.55000E+01 4.72373E+06 + 1.56000E+01 3.77898E+06 + 1.57000E+01 2.83424E+06 + 1.58000E+01 1.88949E+06 + 1.59000E+01 9.44746E+05 + 1.60000E+01 0.00000E+00 + 1.61000E+01 0.00000E+00 + 1.62000E+01 0.00000E+00 + 1.63000E+01 0.00000E+00 + 1.64000E+01 0.00000E+00 + 1.65000E+01 0.00000E+00 + 1.66000E+01 0.00000E+00 + 1.67000E+01 0.00000E+00 + 1.68000E+01 0.00000E+00 + 1.69000E+01 0.00000E+00 + 1.70000E+01 0.00000E+00 + 1.71000E+01 0.00000E+00 + 1.72000E+01 0.00000E+00 + 1.73000E+01 0.00000E+00 + 1.74000E+01 0.00000E+00 + 1.75000E+01 0.00000E+00 + 1.76000E+01 0.00000E+00 + 1.77000E+01 0.00000E+00 + 1.78000E+01 0.00000E+00 + 1.79000E+01 0.00000E+00 + 1.80000E+01 0.00000E+00 + 1.81000E+01 2.83424E+05 + 1.82000E+01 5.66847E+05 + 1.83000E+01 8.50271E+05 + 1.84000E+01 1.13369E+06 + 1.85000E+01 1.41712E+06 + 1.86000E+01 1.70054E+06 + 1.87000E+01 1.98397E+06 + 1.88000E+01 2.26739E+06 + 1.89000E+01 2.55081E+06 + 1.90000E+01 2.83424E+06 + 1.91000E+01 3.11766E+06 + 1.92000E+01 3.40108E+06 + 1.93000E+01 3.68451E+06 + 1.94000E+01 3.96793E+06 + 1.95000E+01 4.25136E+06 + 1.96000E+01 4.53478E+06 + 1.97000E+01 4.81820E+06 + 1.98000E+01 5.10163E+06 + 1.99000E+01 5.38505E+06 + 2.00000E+01 5.66847E+06 + 2.01000E+01 5.95190E+06 + 2.02000E+01 6.23532E+06 + 2.03000E+01 6.51875E+06 + 2.04000E+01 6.80217E+06 + 2.05000E+01 7.08559E+06 + 2.06000E+01 7.36902E+06 + 2.07000E+01 7.65244E+06 + 2.08000E+01 7.93586E+06 + 2.09000E+01 8.21929E+06 + 2.10000E+01 8.50271E+06 + 2.11000E+01 8.50271E+06 + 2.12000E+01 7.55797E+06 + 2.13000E+01 6.61322E+06 + 2.14000E+01 5.66848E+06 + 2.15000E+01 4.72373E+06 + 2.16000E+01 3.77898E+06 + 2.17000E+01 2.83424E+06 + 2.18000E+01 1.88949E+06 + 2.19000E+01 9.44746E+05 + 2.20000E+01 0.00000E+00 + 2.21000E+01 0.00000E+00 + 2.22000E+01 0.00000E+00 + 2.23000E+01 0.00000E+00 + 2.24000E+01 0.00000E+00 + 2.25000E+01 0.00000E+00 + 2.26000E+01 0.00000E+00 + 2.27000E+01 0.00000E+00 + 2.28000E+01 0.00000E+00 + 2.29000E+01 0.00000E+00 + 2.30000E+01 0.00000E+00 + 2.31000E+01 0.00000E+00 + 2.32000E+01 0.00000E+00 + 2.33000E+01 0.00000E+00 + 2.34000E+01 0.00000E+00 + 2.35000E+01 0.00000E+00 + 2.36000E+01 0.00000E+00 + 2.37000E+01 0.00000E+00 + 2.38000E+01 0.00000E+00 + 2.39000E+01 0.00000E+00 + 2.40000E+01 0.00000E+00 + 2.41000E+01 2.83424E+05 + 2.42000E+01 5.66847E+05 + 2.43000E+01 8.50271E+05 + 2.44000E+01 1.13369E+06 + 2.45000E+01 1.41712E+06 + 2.46000E+01 1.70054E+06 + 2.47000E+01 1.98397E+06 + 2.48000E+01 2.26739E+06 + 2.49000E+01 2.55081E+06 + 2.50000E+01 2.83424E+06 + 2.51000E+01 3.11766E+06 + 2.52000E+01 3.40108E+06 + 2.53000E+01 3.68451E+06 + 2.54000E+01 3.96793E+06 + 2.55000E+01 4.25136E+06 + 2.56000E+01 4.53478E+06 + 2.57000E+01 4.81820E+06 + 2.58000E+01 5.10163E+06 + 2.59000E+01 5.38505E+06 + 2.60000E+01 5.66847E+06 + 2.61000E+01 5.95190E+06 + 2.62000E+01 6.23532E+06 + 2.63000E+01 6.51875E+06 + 2.64000E+01 6.80217E+06 + 2.65000E+01 7.08559E+06 + 2.66000E+01 7.36902E+06 + 2.67000E+01 7.65244E+06 + 2.68000E+01 7.93586E+06 + 2.69000E+01 8.21929E+06 + 2.70000E+01 8.50271E+06 + 2.71000E+01 8.50271E+06 + 2.72000E+01 7.55797E+06 + 2.73000E+01 6.61322E+06 + 2.74000E+01 5.66848E+06 + 2.75000E+01 4.72373E+06 + 2.76000E+01 3.77898E+06 + 2.77000E+01 2.83424E+06 + 2.78000E+01 1.88949E+06 + 2.79000E+01 9.44746E+05 + 2.80000E+01 0.00000E+00 + 2.81000E+01 0.00000E+00 + 2.82000E+01 0.00000E+00 + 2.83000E+01 0.00000E+00 + 2.84000E+01 0.00000E+00 + 2.85000E+01 0.00000E+00 + 2.86000E+01 0.00000E+00 + 2.87000E+01 0.00000E+00 + 2.88000E+01 0.00000E+00 + 2.89000E+01 0.00000E+00 + 2.90000E+01 0.00000E+00 + 2.91000E+01 0.00000E+00 + 2.92000E+01 0.00000E+00 + 2.93000E+01 0.00000E+00 + 2.94000E+01 0.00000E+00 + 2.95000E+01 0.00000E+00 + 2.96000E+01 0.00000E+00 + 2.97000E+01 0.00000E+00 + 2.98000E+01 0.00000E+00 + 2.99000E+01 0.00000E+00 + 3.00000E+01 0.00000E+00 + 3.01000E+01 2.83424E+05 + 3.02000E+01 5.66847E+05 + 3.03000E+01 8.50271E+05 + 3.04000E+01 1.13369E+06 + 3.05000E+01 1.41712E+06 + 3.06000E+01 1.70054E+06 + 3.07000E+01 1.98397E+06 + 3.08000E+01 2.26739E+06 + 3.09000E+01 2.55081E+06 + 3.10000E+01 2.83424E+06 + 3.11000E+01 3.11766E+06 + 3.12000E+01 3.40108E+06 + 3.13000E+01 3.68451E+06 + 3.14000E+01 3.96793E+06 + 3.15000E+01 4.25136E+06 + 3.16000E+01 4.53478E+06 + 3.17000E+01 4.81820E+06 + 3.18000E+01 5.10163E+06 + 3.19000E+01 5.38505E+06 + 3.20000E+01 5.66847E+06 + 3.21000E+01 5.95190E+06 + 3.22000E+01 6.23532E+06 + 3.23000E+01 6.51875E+06 + 3.24000E+01 6.80217E+06 + 3.25000E+01 7.08559E+06 + 3.26000E+01 7.36902E+06 + 3.27000E+01 7.65244E+06 + 3.28000E+01 7.93586E+06 + 3.29000E+01 8.21929E+06 + 3.30000E+01 8.50271E+06 + 3.31000E+01 8.50271E+06 + 3.32000E+01 7.55797E+06 + 3.33000E+01 6.61322E+06 + 3.34000E+01 5.66848E+06 + 3.35000E+01 4.72373E+06 + 3.36000E+01 3.77898E+06 + 3.37000E+01 2.83424E+06 + 3.38000E+01 1.88949E+06 + 3.39000E+01 9.44746E+05 + 3.40000E+01 0.00000E+00 + 3.41000E+01 0.00000E+00 + 3.42000E+01 0.00000E+00 + 3.43000E+01 0.00000E+00 + 3.44000E+01 0.00000E+00 + 3.45000E+01 0.00000E+00 + 3.46000E+01 0.00000E+00 + 3.47000E+01 0.00000E+00 + 3.48000E+01 0.00000E+00 + 3.49000E+01 0.00000E+00 + 3.50000E+01 0.00000E+00 + 3.51000E+01 0.00000E+00 + 3.52000E+01 0.00000E+00 + 3.53000E+01 0.00000E+00 + 3.54000E+01 0.00000E+00 + 3.55000E+01 0.00000E+00 + 3.56000E+01 0.00000E+00 + 3.57000E+01 0.00000E+00 + 3.58000E+01 0.00000E+00 + 3.59000E+01 0.00000E+00 + 3.60000E+01 0.00000E+00 + 3.61000E+01 2.83424E+05 + 3.62000E+01 5.66847E+05 + 3.63000E+01 8.50271E+05 + 3.64000E+01 1.13369E+06 + 3.65000E+01 1.41712E+06 + 3.66000E+01 1.70054E+06 + 3.67000E+01 1.98397E+06 + 3.68000E+01 2.26739E+06 + 3.69000E+01 2.55081E+06 + 3.70000E+01 2.83424E+06 + 3.71000E+01 3.11766E+06 + 3.72000E+01 3.40108E+06 + 3.73000E+01 3.68451E+06 + 3.74000E+01 3.96793E+06 + 3.75000E+01 4.25136E+06 + 3.76000E+01 4.53478E+06 + 3.77000E+01 4.81820E+06 + 3.78000E+01 5.10163E+06 + 3.79000E+01 5.38505E+06 + 3.80000E+01 5.66847E+06 + 3.81000E+01 5.95190E+06 + 3.82000E+01 6.23532E+06 + 3.83000E+01 6.51875E+06 + 3.84000E+01 6.80217E+06 + 3.85000E+01 7.08559E+06 + 3.86000E+01 7.36902E+06 + 3.87000E+01 7.65244E+06 + 3.88000E+01 7.93586E+06 + 3.89000E+01 8.21929E+06 + 3.90000E+01 8.50271E+06 + 3.91000E+01 8.50271E+06 + 3.92000E+01 7.55797E+06 + 3.93000E+01 6.61322E+06 + 3.94000E+01 5.66848E+06 + 3.95000E+01 4.72373E+06 + 3.96000E+01 3.77898E+06 + 3.97000E+01 2.83424E+06 + 3.98000E+01 1.88949E+06 + 3.99000E+01 9.44746E+05 + 4.00000E+01 0.00000E+00 + 4.01000E+01 0.00000E+00 + 4.02000E+01 0.00000E+00 + 4.03000E+01 0.00000E+00 + 4.04000E+01 0.00000E+00 + 4.05000E+01 0.00000E+00 + 4.06000E+01 0.00000E+00 + 4.07000E+01 0.00000E+00 + 4.08000E+01 0.00000E+00 + 4.09000E+01 0.00000E+00 + 4.10000E+01 0.00000E+00 + 4.11000E+01 0.00000E+00 + 4.12000E+01 0.00000E+00 + 4.13000E+01 0.00000E+00 + 4.14000E+01 0.00000E+00 + 4.15000E+01 0.00000E+00 + 4.16000E+01 0.00000E+00 + 4.17000E+01 0.00000E+00 + 4.18000E+01 0.00000E+00 + 4.19000E+01 0.00000E+00 + 4.20000E+01 0.00000E+00 + 4.21000E+01 2.83424E+05 + 4.22000E+01 5.66847E+05 + 4.23000E+01 8.50271E+05 + 4.24000E+01 1.13369E+06 + 4.25000E+01 1.41712E+06 + 4.26000E+01 1.70054E+06 + 4.27000E+01 1.98397E+06 + 4.28000E+01 2.26739E+06 + 4.29000E+01 2.55081E+06 + 4.30000E+01 2.83424E+06 + 4.31000E+01 3.11766E+06 + 4.32000E+01 3.40108E+06 + 4.33000E+01 3.68451E+06 + 4.34000E+01 3.96793E+06 + 4.35000E+01 4.25136E+06 + 4.36000E+01 4.53478E+06 + 4.37000E+01 4.81820E+06 + 4.38000E+01 5.10163E+06 + 4.39000E+01 5.38505E+06 + 4.40000E+01 5.66847E+06 + 4.41000E+01 5.95190E+06 + 4.42000E+01 6.23532E+06 + 4.43000E+01 6.51875E+06 + 4.44000E+01 6.80217E+06 + 4.45000E+01 7.08559E+06 + 4.46000E+01 7.36902E+06 + 4.47000E+01 7.65244E+06 + 4.48000E+01 7.93586E+06 + 4.49000E+01 8.21929E+06 + 4.50000E+01 8.50271E+06 + 4.51000E+01 8.50271E+06 + 4.52000E+01 7.55797E+06 + 4.53000E+01 6.61322E+06 + 4.54000E+01 5.66848E+06 + 4.55000E+01 4.72373E+06 + 4.56000E+01 3.77898E+06 + 4.57000E+01 2.83424E+06 + 4.58000E+01 1.88949E+06 + 4.59000E+01 9.44746E+05 + 4.60000E+01 0.00000E+00 + 4.61000E+01 0.00000E+00 + 4.62000E+01 0.00000E+00 + 4.63000E+01 0.00000E+00 + 4.64000E+01 0.00000E+00 + 4.65000E+01 0.00000E+00 + 4.66000E+01 0.00000E+00 + 4.67000E+01 0.00000E+00 + 4.68000E+01 0.00000E+00 + 4.69000E+01 0.00000E+00 + 4.70000E+01 0.00000E+00 + 4.71000E+01 0.00000E+00 + 4.72000E+01 0.00000E+00 + 4.73000E+01 0.00000E+00 + 4.74000E+01 0.00000E+00 + 4.75000E+01 0.00000E+00 + 4.76000E+01 0.00000E+00 + 4.77000E+01 0.00000E+00 + 4.78000E+01 0.00000E+00 + 4.79000E+01 0.00000E+00 + 4.80000E+01 0.00000E+00 + 4.81000E+01 2.83424E+05 + 4.82000E+01 5.66847E+05 + 4.83000E+01 8.50271E+05 + 4.84000E+01 1.13369E+06 + 4.85000E+01 1.41712E+06 + 4.86000E+01 1.70054E+06 + 4.87000E+01 1.98397E+06 + 4.88000E+01 2.26739E+06 + 4.89000E+01 2.55081E+06 + 4.90000E+01 2.83424E+06 + 4.91000E+01 3.11766E+06 + 4.92000E+01 3.40108E+06 + 4.93000E+01 3.68451E+06 + 4.94000E+01 3.96793E+06 + 4.95000E+01 4.25136E+06 + 4.96000E+01 4.53478E+06 + 4.97000E+01 4.81820E+06 + 4.98000E+01 5.10163E+06 + 4.99000E+01 5.38505E+06 + 5.00000E+01 5.66847E+06 + 5.01000E+01 5.95190E+06 + 5.02000E+01 6.23532E+06 + 5.03000E+01 6.51875E+06 + 5.04000E+01 6.80217E+06 + 5.05000E+01 7.08559E+06 + 5.06000E+01 7.36902E+06 + 5.07000E+01 7.65244E+06 + 5.08000E+01 7.93586E+06 + 5.09000E+01 8.21929E+06 + 5.10000E+01 8.50271E+06 + 5.11000E+01 8.50271E+06 + 5.12000E+01 7.55797E+06 + 5.13000E+01 6.61322E+06 + 5.14000E+01 5.66848E+06 + 5.15000E+01 4.72373E+06 + 5.16000E+01 3.77898E+06 + 5.17000E+01 2.83424E+06 + 5.18000E+01 1.88949E+06 + 5.19000E+01 9.44746E+05 + 5.20000E+01 0.00000E+00 + 5.21000E+01 0.00000E+00 + 5.22000E+01 0.00000E+00 + 5.23000E+01 0.00000E+00 + 5.24000E+01 0.00000E+00 + 5.25000E+01 0.00000E+00 + 5.26000E+01 0.00000E+00 + 5.27000E+01 0.00000E+00 + 5.28000E+01 0.00000E+00 + 5.29000E+01 0.00000E+00 + 5.30000E+01 0.00000E+00 + 5.31000E+01 0.00000E+00 + 5.32000E+01 0.00000E+00 + 5.33000E+01 0.00000E+00 + 5.34000E+01 0.00000E+00 + 5.35000E+01 0.00000E+00 + 5.36000E+01 0.00000E+00 + 5.37000E+01 0.00000E+00 + 5.38000E+01 0.00000E+00 + 5.39000E+01 0.00000E+00 + 5.40000E+01 0.00000E+00 + 5.41000E+01 2.83424E+05 + 5.42000E+01 5.66847E+05 + 5.43000E+01 8.50271E+05 + 5.44000E+01 1.13369E+06 + 5.45000E+01 1.41712E+06 + 5.46000E+01 1.70054E+06 + 5.47000E+01 1.98397E+06 + 5.48000E+01 2.26739E+06 + 5.49000E+01 2.55081E+06 + 5.50000E+01 2.83424E+06 + 5.51000E+01 3.11766E+06 + 5.52000E+01 3.40108E+06 + 5.53000E+01 3.68451E+06 + 5.54000E+01 3.96793E+06 + 5.55000E+01 4.25136E+06 + 5.56000E+01 4.53478E+06 + 5.57000E+01 4.81820E+06 + 5.58000E+01 5.10163E+06 + 5.59000E+01 5.38505E+06 + 5.60000E+01 5.66847E+06 + 5.61000E+01 5.95190E+06 + 5.62000E+01 6.23532E+06 + 5.63000E+01 6.51875E+06 + 5.64000E+01 6.80217E+06 + 5.65000E+01 7.08559E+06 + 5.66000E+01 7.36902E+06 + 5.67000E+01 7.65244E+06 + 5.68000E+01 7.93586E+06 + 5.69000E+01 8.21929E+06 + 5.70000E+01 8.50271E+06 + 5.71000E+01 8.50271E+06 + 5.72000E+01 7.55797E+06 + 5.73000E+01 6.61322E+06 + 5.74000E+01 5.66848E+06 + 5.75000E+01 4.72373E+06 + 5.76000E+01 3.77898E+06 + 5.77000E+01 2.83424E+06 + 5.78000E+01 1.88949E+06 + 5.79000E+01 9.44746E+05 + 5.80000E+01 0.00000E+00 + 5.81000E+01 0.00000E+00 + 5.82000E+01 0.00000E+00 + 5.83000E+01 0.00000E+00 + 5.84000E+01 0.00000E+00 + 5.85000E+01 0.00000E+00 + 5.86000E+01 0.00000E+00 + 5.87000E+01 0.00000E+00 + 5.88000E+01 0.00000E+00 + 5.89000E+01 0.00000E+00 + 5.90000E+01 0.00000E+00 + 5.91000E+01 0.00000E+00 + 5.92000E+01 0.00000E+00 + 5.93000E+01 0.00000E+00 + 5.94000E+01 0.00000E+00 + 5.95000E+01 0.00000E+00 + 5.96000E+01 0.00000E+00 + 5.97000E+01 0.00000E+00 + 5.98000E+01 0.00000E+00 + 5.99000E+01 0.00000E+00 + 6.00000E+01 0.00000E+00 + 6.01000E+01 2.83424E+05 + 6.02000E+01 5.66847E+05 + 6.03000E+01 8.50271E+05 + 6.04000E+01 1.13369E+06 + 6.05000E+01 1.41712E+06 + 6.06000E+01 1.70054E+06 + 6.07000E+01 1.98397E+06 + 6.08000E+01 2.26739E+06 + 6.09000E+01 2.55081E+06 + 6.10000E+01 2.83424E+06 + 6.11000E+01 3.11766E+06 + 6.12000E+01 3.40108E+06 + 6.13000E+01 3.68451E+06 + 6.14000E+01 3.96793E+06 + 6.15000E+01 4.25136E+06 + 6.16000E+01 4.53478E+06 + 6.17000E+01 4.81820E+06 + 6.18000E+01 5.10163E+06 + 6.19000E+01 5.38505E+06 + 6.20000E+01 5.66847E+06 + 6.21000E+01 5.95190E+06 + 6.22000E+01 6.23532E+06 + 6.23000E+01 6.51875E+06 + 6.24000E+01 6.80217E+06 + 6.25000E+01 7.08559E+06 + 6.26000E+01 7.36902E+06 + 6.27000E+01 7.65244E+06 + 6.28000E+01 7.93586E+06 + 6.29000E+01 8.21929E+06 + 6.30000E+01 8.50271E+06 + 6.31000E+01 8.50271E+06 + 6.32000E+01 7.55797E+06 + 6.33000E+01 6.61322E+06 + 6.34000E+01 5.66848E+06 + 6.35000E+01 4.72373E+06 + 6.36000E+01 3.77898E+06 + 6.37000E+01 2.83424E+06 + 6.38000E+01 1.88949E+06 + 6.39000E+01 9.44746E+05 + 6.40000E+01 0.00000E+00 + 6.41000E+01 0.00000E+00 + 6.42000E+01 0.00000E+00 + 6.43000E+01 0.00000E+00 + 6.44000E+01 0.00000E+00 + 6.45000E+01 0.00000E+00 + 6.46000E+01 0.00000E+00 + 6.47000E+01 0.00000E+00 + 6.48000E+01 0.00000E+00 + 6.49000E+01 0.00000E+00 + 6.50000E+01 0.00000E+00 + 6.51000E+01 0.00000E+00 + 6.52000E+01 0.00000E+00 + 6.53000E+01 0.00000E+00 + 6.54000E+01 0.00000E+00 + 6.55000E+01 0.00000E+00 + 6.56000E+01 0.00000E+00 + 6.57000E+01 0.00000E+00 + 6.58000E+01 0.00000E+00 + 6.59000E+01 0.00000E+00 + 6.60000E+01 0.00000E+00 + 6.61000E+01 2.83424E+05 + 6.62000E+01 5.66847E+05 + 6.63000E+01 8.50271E+05 + 6.64000E+01 1.13369E+06 + 6.65000E+01 1.41712E+06 + 6.66000E+01 1.70054E+06 + 6.67000E+01 1.98397E+06 + 6.68000E+01 2.26739E+06 + 6.69000E+01 2.55081E+06 + 6.70000E+01 2.83424E+06 + 6.71000E+01 3.11766E+06 + 6.72000E+01 3.40108E+06 + 6.73000E+01 3.68451E+06 + 6.74000E+01 3.96793E+06 + 6.75000E+01 4.25136E+06 + 6.76000E+01 4.53478E+06 + 6.77000E+01 4.81820E+06 + 6.78000E+01 5.10163E+06 + 6.79000E+01 5.38505E+06 + 6.80000E+01 5.66847E+06 + 6.81000E+01 5.95190E+06 + 6.82000E+01 6.23532E+06 + 6.83000E+01 6.51875E+06 + 6.84000E+01 6.80217E+06 + 6.85000E+01 7.08559E+06 + 6.86000E+01 7.36902E+06 + 6.87000E+01 7.65244E+06 + 6.88000E+01 7.93586E+06 + 6.89000E+01 8.21929E+06 + 6.90000E+01 8.50271E+06 + 6.91000E+01 8.50271E+06 + 6.92000E+01 7.55797E+06 + 6.93000E+01 6.61322E+06 + 6.94000E+01 5.66848E+06 + 6.95000E+01 4.72373E+06 + 6.96000E+01 3.77898E+06 + 6.97000E+01 2.83424E+06 + 6.98000E+01 1.88949E+06 + 6.99000E+01 9.44746E+05 + 7.00000E+01 0.00000E+00 + 7.01000E+01 0.00000E+00 + 7.02000E+01 0.00000E+00 + 7.03000E+01 0.00000E+00 + 7.04000E+01 0.00000E+00 + 7.05000E+01 0.00000E+00 + 7.06000E+01 0.00000E+00 + 7.07000E+01 0.00000E+00 + 7.08000E+01 0.00000E+00 + 7.09000E+01 0.00000E+00 + 7.10000E+01 0.00000E+00 + 7.11000E+01 0.00000E+00 + 7.12000E+01 0.00000E+00 + 7.13000E+01 0.00000E+00 + 7.14000E+01 0.00000E+00 + 7.15000E+01 0.00000E+00 + 7.16000E+01 0.00000E+00 + 7.17000E+01 0.00000E+00 + 7.18000E+01 0.00000E+00 + 7.19000E+01 0.00000E+00 + 7.20000E+01 0.00000E+00 + 7.21000E+01 2.83424E+05 + 7.22000E+01 5.66847E+05 + 7.23000E+01 8.50271E+05 + 7.24000E+01 1.13369E+06 + 7.25000E+01 1.41712E+06 + 7.26000E+01 1.70054E+06 + 7.27000E+01 1.98397E+06 + 7.28000E+01 2.26739E+06 + 7.29000E+01 2.55081E+06 + 7.30000E+01 2.83424E+06 + 7.31000E+01 3.11766E+06 + 7.32000E+01 3.40108E+06 + 7.33000E+01 3.68451E+06 + 7.34000E+01 3.96793E+06 + 7.35000E+01 4.25136E+06 + 7.36000E+01 4.53478E+06 + 7.37000E+01 4.81820E+06 + 7.38000E+01 5.10163E+06 + 7.39000E+01 5.38505E+06 + 7.40000E+01 5.66847E+06 + 7.41000E+01 5.95190E+06 + 7.42000E+01 6.23532E+06 + 7.43000E+01 6.51875E+06 + 7.44000E+01 6.80217E+06 + 7.45000E+01 7.08559E+06 + 7.46000E+01 7.36902E+06 + 7.47000E+01 7.65244E+06 + 7.48000E+01 7.93586E+06 + 7.49000E+01 8.21929E+06 + 7.50000E+01 8.50271E+06 + 7.51000E+01 8.50271E+06 + 7.52000E+01 7.55797E+06 + 7.53000E+01 6.61322E+06 + 7.54000E+01 5.66848E+06 + 7.55000E+01 4.72373E+06 + 7.56000E+01 3.77898E+06 + 7.57000E+01 2.83424E+06 + 7.58000E+01 1.88949E+06 + 7.59000E+01 9.44746E+05 + 7.60000E+01 0.00000E+00 + 7.61000E+01 0.00000E+00 + 7.62000E+01 0.00000E+00 + 7.63000E+01 0.00000E+00 + 7.64000E+01 0.00000E+00 + 7.65000E+01 0.00000E+00 + 7.66000E+01 0.00000E+00 + 7.67000E+01 0.00000E+00 + 7.68000E+01 0.00000E+00 + 7.69000E+01 0.00000E+00 + 7.70000E+01 0.00000E+00 + 7.71000E+01 0.00000E+00 + 7.72000E+01 0.00000E+00 + 7.73000E+01 0.00000E+00 + 7.74000E+01 0.00000E+00 + 7.75000E+01 0.00000E+00 + 7.76000E+01 0.00000E+00 + 7.77000E+01 0.00000E+00 + 7.78000E+01 0.00000E+00 + 7.79000E+01 0.00000E+00 + 7.80000E+01 0.00000E+00 + 7.81000E+01 2.83424E+05 + 7.82000E+01 5.66847E+05 + 7.83000E+01 8.50271E+05 + 7.84000E+01 1.13369E+06 + 7.85000E+01 1.41712E+06 + 7.86000E+01 1.70054E+06 + 7.87000E+01 1.98397E+06 + 7.88000E+01 2.26739E+06 + 7.89000E+01 2.55081E+06 + 7.90000E+01 2.83424E+06 + 7.91000E+01 3.11766E+06 + 7.92000E+01 3.40108E+06 + 7.93000E+01 3.68451E+06 + 7.94000E+01 3.96793E+06 + 7.95000E+01 4.25136E+06 + 7.96000E+01 4.53478E+06 + 7.97000E+01 4.81820E+06 + 7.98000E+01 5.10163E+06 + 7.99000E+01 5.38505E+06 + 8.00000E+01 5.66847E+06 + 8.01000E+01 5.95190E+06 + 8.02000E+01 6.23532E+06 + 8.03000E+01 6.51875E+06 + 8.04000E+01 6.80217E+06 + 8.05000E+01 7.08559E+06 + 8.06000E+01 7.36902E+06 + 8.07000E+01 7.65244E+06 + 8.08000E+01 7.93586E+06 + 8.09000E+01 8.21929E+06 + 8.10000E+01 8.50271E+06 + 8.11000E+01 8.50271E+06 + 8.12000E+01 7.55797E+06 + 8.13000E+01 6.61322E+06 + 8.14000E+01 5.66848E+06 + 8.15000E+01 4.72373E+06 + 8.16000E+01 3.77898E+06 + 8.17000E+01 2.83424E+06 + 8.18000E+01 1.88949E+06 + 8.19000E+01 9.44746E+05 + 8.20000E+01 0.00000E+00 + 8.21000E+01 0.00000E+00 + 8.22000E+01 0.00000E+00 + 8.23000E+01 0.00000E+00 + 8.24000E+01 0.00000E+00 + 8.25000E+01 0.00000E+00 + 8.26000E+01 0.00000E+00 + 8.27000E+01 0.00000E+00 + 8.28000E+01 0.00000E+00 + 8.29000E+01 0.00000E+00 + 8.30000E+01 0.00000E+00 + 8.31000E+01 0.00000E+00 + 8.32000E+01 0.00000E+00 + 8.33000E+01 0.00000E+00 + 8.34000E+01 0.00000E+00 + 8.35000E+01 0.00000E+00 + 8.36000E+01 0.00000E+00 + 8.37000E+01 0.00000E+00 + 8.38000E+01 0.00000E+00 + 8.39000E+01 0.00000E+00 + 8.40000E+01 0.00000E+00 + 8.41000E+01 2.83424E+05 + 8.42000E+01 5.66847E+05 + 8.43000E+01 8.50271E+05 + 8.44000E+01 1.13369E+06 + 8.45000E+01 1.41712E+06 + 8.46000E+01 1.70054E+06 + 8.47000E+01 1.98397E+06 + 8.48000E+01 2.26739E+06 + 8.49000E+01 2.55081E+06 + 8.50000E+01 2.83424E+06 + 8.51000E+01 3.11766E+06 + 8.52000E+01 3.40108E+06 + 8.53000E+01 3.68451E+06 + 8.54000E+01 3.96793E+06 + 8.55000E+01 4.25136E+06 + 8.56000E+01 4.53478E+06 + 8.57000E+01 4.81820E+06 + 8.58000E+01 5.10163E+06 + 8.59000E+01 5.38505E+06 + 8.60000E+01 5.66847E+06 + 8.61000E+01 5.95190E+06 + 8.62000E+01 6.23532E+06 + 8.63000E+01 6.51875E+06 + 8.64000E+01 6.80217E+06 + 8.65000E+01 7.08559E+06 + 8.66000E+01 7.36902E+06 + 8.67000E+01 7.65244E+06 + 8.68000E+01 7.93586E+06 + 8.69000E+01 8.21929E+06 + 8.70000E+01 8.50271E+06 + 8.71000E+01 8.50271E+06 + 8.72000E+01 7.55797E+06 + 8.73000E+01 6.61322E+06 + 8.74000E+01 5.66848E+06 + 8.75000E+01 4.72373E+06 + 8.76000E+01 3.77898E+06 + 8.77000E+01 2.83424E+06 + 8.78000E+01 1.88949E+06 + 8.79000E+01 9.44746E+05 + 8.80000E+01 0.00000E+00 + 8.81000E+01 0.00000E+00 + 8.82000E+01 0.00000E+00 + 8.83000E+01 0.00000E+00 + 8.84000E+01 0.00000E+00 + 8.85000E+01 0.00000E+00 + 8.86000E+01 0.00000E+00 + 8.87000E+01 0.00000E+00 + 8.88000E+01 0.00000E+00 + 8.89000E+01 0.00000E+00 + 8.90000E+01 0.00000E+00 + 8.91000E+01 0.00000E+00 + 8.92000E+01 0.00000E+00 + 8.93000E+01 0.00000E+00 + 8.94000E+01 0.00000E+00 + 8.95000E+01 0.00000E+00 + 8.96000E+01 0.00000E+00 + 8.97000E+01 0.00000E+00 + 8.98000E+01 0.00000E+00 + 8.99000E+01 0.00000E+00 + 9.00000E+01 0.00000E+00 + 9.01000E+01 2.83424E+05 + 9.02000E+01 5.66847E+05 + 9.03000E+01 8.50271E+05 + 9.04000E+01 1.13369E+06 + 9.05000E+01 1.41712E+06 + 9.06000E+01 1.70054E+06 + 9.07000E+01 1.98397E+06 + 9.08000E+01 2.26739E+06 + 9.09000E+01 2.55081E+06 + 9.10000E+01 2.83424E+06 + 9.11000E+01 3.11766E+06 + 9.12000E+01 3.40108E+06 + 9.13000E+01 3.68451E+06 + 9.14000E+01 3.96793E+06 + 9.15000E+01 4.25136E+06 + 9.16000E+01 4.53478E+06 + 9.17000E+01 4.81820E+06 + 9.18000E+01 5.10163E+06 + 9.19000E+01 5.38505E+06 + 9.20000E+01 5.66847E+06 + 9.21000E+01 5.95190E+06 + 9.22000E+01 6.23532E+06 + 9.23000E+01 6.51875E+06 + 9.24000E+01 6.80217E+06 + 9.25000E+01 7.08559E+06 + 9.26000E+01 7.36902E+06 + 9.27000E+01 7.65244E+06 + 9.28000E+01 7.93586E+06 + 9.29000E+01 8.21929E+06 + 9.30000E+01 8.50271E+06 + 9.31000E+01 8.50271E+06 + 9.32000E+01 7.55797E+06 + 9.33000E+01 6.61322E+06 + 9.34000E+01 5.66848E+06 + 9.35000E+01 4.72373E+06 + 9.36000E+01 3.77898E+06 + 9.37000E+01 2.83424E+06 + 9.38000E+01 1.88949E+06 + 9.39000E+01 9.44746E+05 + 9.40000E+01 0.00000E+00 + 9.41000E+01 0.00000E+00 + 9.42000E+01 0.00000E+00 + 9.43000E+01 0.00000E+00 + 9.44000E+01 0.00000E+00 + 9.45000E+01 0.00000E+00 + 9.46000E+01 0.00000E+00 + 9.47000E+01 0.00000E+00 + 9.48000E+01 0.00000E+00 + 9.49000E+01 0.00000E+00 + 9.50000E+01 0.00000E+00 + 9.51000E+01 0.00000E+00 + 9.52000E+01 0.00000E+00 + 9.53000E+01 0.00000E+00 + 9.54000E+01 0.00000E+00 + 9.55000E+01 0.00000E+00 + 9.56000E+01 0.00000E+00 + 9.57000E+01 0.00000E+00 + 9.58000E+01 0.00000E+00 + 9.59000E+01 0.00000E+00 + 9.60000E+01 0.00000E+00 + 9.61000E+01 2.83424E+05 + 9.62000E+01 5.66847E+05 + 9.63000E+01 8.50271E+05 + 9.64000E+01 1.13369E+06 + 9.65000E+01 1.41712E+06 + 9.66000E+01 1.70054E+06 + 9.67000E+01 1.98397E+06 + 9.68000E+01 2.26739E+06 + 9.69000E+01 2.55081E+06 + 9.70000E+01 2.83424E+06 + 9.71000E+01 3.11766E+06 + 9.72000E+01 3.40108E+06 + 9.73000E+01 3.68451E+06 + 9.74000E+01 3.96793E+06 + 9.75000E+01 4.25136E+06 + 9.76000E+01 4.53478E+06 + 9.77000E+01 4.81820E+06 + 9.78000E+01 5.10163E+06 + 9.79000E+01 5.38505E+06 + 9.80000E+01 5.66847E+06 + 9.81000E+01 5.95190E+06 + 9.82000E+01 6.23532E+06 + 9.83000E+01 6.51875E+06 + 9.84000E+01 6.80217E+06 + 9.85000E+01 7.08559E+06 + 9.86000E+01 7.36902E+06 + 9.87000E+01 7.65244E+06 + 9.88000E+01 7.93586E+06 + 9.89000E+01 8.21929E+06 + 9.90000E+01 8.50271E+06 + 9.91000E+01 8.50271E+06 + 9.92000E+01 7.55797E+06 + 9.93000E+01 6.61322E+06 + 9.94000E+01 5.66848E+06 + 9.95000E+01 4.72373E+06 + 9.96000E+01 3.77898E+06 + 9.97000E+01 2.83424E+06 + 9.98000E+01 1.88949E+06 + 9.99000E+01 9.44746E+05 + 1.00000E+02 0.00000E+00 + 1.00100E+02 0.00000E+00 + 1.00200E+02 0.00000E+00 + 1.00300E+02 0.00000E+00 + 1.00400E+02 0.00000E+00 + 1.00500E+02 0.00000E+00 + 1.00600E+02 0.00000E+00 + 1.00700E+02 0.00000E+00 + 1.00800E+02 0.00000E+00 + 1.00900E+02 0.00000E+00 + 1.01000E+02 0.00000E+00 + 1.01100E+02 0.00000E+00 + 1.01200E+02 0.00000E+00 + 1.01300E+02 0.00000E+00 + 1.01400E+02 0.00000E+00 + 1.01500E+02 0.00000E+00 + 1.01600E+02 0.00000E+00 + 1.01700E+02 0.00000E+00 + 1.01800E+02 0.00000E+00 + 1.01900E+02 0.00000E+00 + 1.02000E+02 0.00000E+00 + 1.02100E+02 2.83424E+05 + 1.02200E+02 5.66847E+05 + 1.02300E+02 8.50271E+05 + 1.02400E+02 1.13369E+06 + 1.02500E+02 1.41712E+06 + 1.02600E+02 1.70054E+06 + 1.02700E+02 1.98397E+06 + 1.02800E+02 2.26739E+06 + 1.02900E+02 2.55081E+06 + 1.03000E+02 2.83424E+06 + 1.03100E+02 3.11766E+06 + 1.03200E+02 3.40108E+06 + 1.03300E+02 3.68451E+06 + 1.03400E+02 3.96793E+06 + 1.03500E+02 4.25136E+06 + 1.03600E+02 4.53478E+06 + 1.03700E+02 4.81820E+06 + 1.03800E+02 5.10163E+06 + 1.03900E+02 5.38505E+06 + 1.04000E+02 5.66847E+06 + 1.04100E+02 5.95190E+06 + 1.04200E+02 6.23532E+06 + 1.04300E+02 6.51875E+06 + 1.04400E+02 6.80217E+06 + 1.04500E+02 7.08559E+06 + 1.04600E+02 7.36902E+06 + 1.04700E+02 7.65244E+06 + 1.04800E+02 7.93586E+06 + 1.04900E+02 8.21929E+06 + 1.05000E+02 8.50271E+06 + 1.05100E+02 8.50271E+06 + 1.05200E+02 7.55797E+06 + 1.05300E+02 6.61322E+06 + 1.05400E+02 5.66848E+06 + 1.05500E+02 4.72373E+06 + 1.05600E+02 3.77898E+06 + 1.05700E+02 2.83424E+06 + 1.05800E+02 1.88949E+06 + 1.05900E+02 9.44746E+05 + 1.06000E+02 0.00000E+00 + 1.06100E+02 0.00000E+00 + 1.06200E+02 0.00000E+00 + 1.06300E+02 0.00000E+00 + 1.06400E+02 0.00000E+00 + 1.06500E+02 0.00000E+00 + 1.06600E+02 0.00000E+00 + 1.06700E+02 0.00000E+00 + 1.06800E+02 0.00000E+00 + 1.06900E+02 0.00000E+00 + 1.07000E+02 0.00000E+00 + 1.07100E+02 0.00000E+00 + 1.07200E+02 0.00000E+00 + 1.07300E+02 0.00000E+00 + 1.07400E+02 0.00000E+00 + 1.07500E+02 0.00000E+00 + 1.07600E+02 0.00000E+00 + 1.07700E+02 0.00000E+00 + 1.07800E+02 0.00000E+00 + 1.07900E+02 0.00000E+00 + 1.08000E+02 0.00000E+00 + 1.08100E+02 2.83424E+05 + 1.08200E+02 5.66847E+05 + 1.08300E+02 8.50271E+05 + 1.08400E+02 1.13369E+06 + 1.08500E+02 1.41712E+06 + 1.08600E+02 1.70054E+06 + 1.08700E+02 1.98397E+06 + 1.08800E+02 2.26739E+06 + 1.08900E+02 2.55081E+06 + 1.09000E+02 2.83424E+06 + 1.09100E+02 3.11766E+06 + 1.09200E+02 3.40108E+06 + 1.09300E+02 3.68451E+06 + 1.09400E+02 3.96793E+06 + 1.09500E+02 4.25136E+06 + 1.09600E+02 4.53478E+06 + 1.09700E+02 4.81820E+06 + 1.09800E+02 5.10163E+06 + 1.09900E+02 5.38505E+06 + 1.10000E+02 5.66847E+06 + 1.10100E+02 5.95190E+06 + 1.10200E+02 6.23532E+06 + 1.10300E+02 6.51875E+06 + 1.10400E+02 6.80217E+06 + 1.10500E+02 7.08559E+06 + 1.10600E+02 7.36902E+06 + 1.10700E+02 7.65244E+06 + 1.10800E+02 7.93586E+06 + 1.10900E+02 8.21929E+06 + 1.11000E+02 8.50271E+06 + 1.11100E+02 8.50271E+06 + 1.11200E+02 7.55797E+06 + 1.11300E+02 6.61322E+06 + 1.11400E+02 5.66848E+06 + 1.11500E+02 4.72373E+06 + 1.11600E+02 3.77898E+06 + 1.11700E+02 2.83424E+06 + 1.11800E+02 1.88949E+06 + 1.11900E+02 9.44746E+05 + 1.12000E+02 0.00000E+00 + 1.12100E+02 0.00000E+00 + 1.12200E+02 0.00000E+00 + 1.12300E+02 0.00000E+00 + 1.12400E+02 0.00000E+00 + 1.12500E+02 0.00000E+00 + 1.12600E+02 0.00000E+00 + 1.12700E+02 0.00000E+00 + 1.12800E+02 0.00000E+00 + 1.12900E+02 0.00000E+00 + 1.13000E+02 0.00000E+00 + 1.13100E+02 0.00000E+00 + 1.13200E+02 0.00000E+00 + 1.13300E+02 0.00000E+00 + 1.13400E+02 0.00000E+00 + 1.13500E+02 0.00000E+00 + 1.13600E+02 0.00000E+00 + 1.13700E+02 0.00000E+00 + 1.13800E+02 0.00000E+00 + 1.13900E+02 0.00000E+00 + 1.14000E+02 0.00000E+00 + 1.14100E+02 2.83424E+05 + 1.14200E+02 5.66847E+05 + 1.14300E+02 8.50271E+05 + 1.14400E+02 1.13369E+06 + 1.14500E+02 1.41712E+06 + 1.14600E+02 1.70054E+06 + 1.14700E+02 1.98397E+06 + 1.14800E+02 2.26739E+06 + 1.14900E+02 2.55081E+06 + 1.15000E+02 2.83424E+06 + 1.15100E+02 3.11766E+06 + 1.15200E+02 3.40108E+06 + 1.15300E+02 3.68451E+06 + 1.15400E+02 3.96793E+06 + 1.15500E+02 4.25136E+06 + 1.15600E+02 4.53478E+06 + 1.15700E+02 4.81820E+06 + 1.15800E+02 5.10163E+06 + 1.15900E+02 5.38505E+06 + 1.16000E+02 5.66847E+06 + 1.16100E+02 5.95190E+06 + 1.16200E+02 6.23532E+06 + 1.16300E+02 6.51875E+06 + 1.16400E+02 6.80217E+06 + 1.16500E+02 7.08559E+06 + 1.16600E+02 7.36902E+06 + 1.16700E+02 7.65244E+06 + 1.16800E+02 7.93586E+06 + 1.16900E+02 8.21929E+06 + 1.17000E+02 8.50271E+06 + 1.17100E+02 8.50271E+06 + 1.17200E+02 7.55797E+06 + 1.17300E+02 6.61322E+06 + 1.17400E+02 5.66848E+06 + 1.17500E+02 4.72373E+06 + 1.17600E+02 3.77898E+06 + 1.17700E+02 2.83424E+06 + 1.17800E+02 1.88949E+06 + 1.17900E+02 9.44746E+05 + 1.18000E+02 0.00000E+00 + 1.18100E+02 0.00000E+00 + 1.18200E+02 0.00000E+00 + 1.18300E+02 0.00000E+00 + 1.18400E+02 0.00000E+00 + 1.18500E+02 0.00000E+00 + 1.18600E+02 0.00000E+00 + 1.18700E+02 0.00000E+00 + 1.18800E+02 0.00000E+00 + 1.18900E+02 0.00000E+00 + 1.19000E+02 0.00000E+00 + 1.19100E+02 0.00000E+00 + 1.19200E+02 0.00000E+00 + 1.19300E+02 0.00000E+00 + 1.19400E+02 0.00000E+00 + 1.19500E+02 0.00000E+00 + 1.19600E+02 0.00000E+00 + 1.19700E+02 0.00000E+00 + 1.19800E+02 0.00000E+00 + 1.19900E+02 0.00000E+00 + 1.20000E+02 0.00000E+00 + 1.20100E+02 2.83424E+05 + 1.20200E+02 5.66847E+05 + 1.20300E+02 8.50271E+05 + 1.20400E+02 1.13369E+06 + 1.20500E+02 1.41712E+06 + 1.20600E+02 1.70054E+06 + 1.20700E+02 1.98397E+06 + 1.20800E+02 2.26739E+06 + 1.20900E+02 2.55081E+06 + 1.21000E+02 2.83424E+06 + 1.21100E+02 3.11766E+06 + 1.21200E+02 3.40108E+06 + 1.21300E+02 3.68451E+06 + 1.21400E+02 3.96793E+06 + 1.21500E+02 4.25136E+06 + 1.21600E+02 4.53478E+06 + 1.21700E+02 4.81820E+06 + 1.21800E+02 5.10163E+06 + 1.21900E+02 5.38505E+06 + 1.22000E+02 5.66847E+06 + 1.22100E+02 5.95190E+06 + 1.22200E+02 6.23532E+06 + 1.22300E+02 6.51875E+06 + 1.22400E+02 6.80217E+06 + 1.22500E+02 7.08559E+06 + 1.22600E+02 7.36902E+06 + 1.22700E+02 7.65244E+06 + 1.22800E+02 7.93586E+06 + 1.22900E+02 8.21929E+06 + 1.23000E+02 8.50271E+06 + 1.23100E+02 8.50271E+06 + 1.23200E+02 7.55797E+06 + 1.23300E+02 6.61322E+06 + 1.23400E+02 5.66848E+06 + 1.23500E+02 4.72373E+06 + 1.23600E+02 3.77898E+06 + 1.23700E+02 2.83424E+06 + 1.23800E+02 1.88949E+06 + 1.23900E+02 9.44746E+05 + 1.24000E+02 0.00000E+00 + 1.24100E+02 0.00000E+00 + 1.24200E+02 0.00000E+00 + 1.24300E+02 0.00000E+00 + 1.24400E+02 0.00000E+00 + 1.24500E+02 0.00000E+00 + 1.24600E+02 0.00000E+00 + 1.24700E+02 0.00000E+00 + 1.24800E+02 0.00000E+00 + 1.24900E+02 0.00000E+00 + 1.25000E+02 0.00000E+00 + 1.25100E+02 0.00000E+00 + 1.25200E+02 0.00000E+00 + 1.25300E+02 0.00000E+00 + 1.25400E+02 0.00000E+00 + 1.25500E+02 0.00000E+00 + 1.25600E+02 0.00000E+00 + 1.25700E+02 0.00000E+00 + 1.25800E+02 0.00000E+00 + 1.25900E+02 0.00000E+00 + 1.26000E+02 0.00000E+00 + 1.26100E+02 2.83424E+05 + 1.26200E+02 5.66847E+05 + 1.26300E+02 8.50271E+05 + 1.26400E+02 1.13369E+06 + 1.26500E+02 1.41712E+06 + 1.26600E+02 1.70054E+06 + 1.26700E+02 1.98397E+06 + 1.26800E+02 2.26739E+06 + 1.26900E+02 2.55081E+06 + 1.27000E+02 2.83424E+06 + 1.27100E+02 3.11766E+06 + 1.27200E+02 3.40108E+06 + 1.27300E+02 3.68451E+06 + 1.27400E+02 3.96793E+06 + 1.27500E+02 4.25136E+06 + 1.27600E+02 4.53478E+06 + 1.27700E+02 4.81820E+06 + 1.27800E+02 5.10163E+06 + 1.27900E+02 5.38505E+06 + 1.28000E+02 5.66847E+06 + 1.28100E+02 5.95190E+06 + 1.28200E+02 6.23532E+06 + 1.28300E+02 6.51875E+06 + 1.28400E+02 6.80217E+06 + 1.28500E+02 7.08559E+06 + 1.28600E+02 7.36902E+06 + 1.28700E+02 7.65244E+06 + 1.28800E+02 7.93586E+06 + 1.28900E+02 8.21929E+06 + 1.29000E+02 8.50271E+06 + 1.29100E+02 8.50271E+06 + 1.29200E+02 7.55797E+06 + 1.29300E+02 6.61322E+06 + 1.29400E+02 5.66848E+06 + 1.29500E+02 4.72373E+06 + 1.29600E+02 3.77898E+06 + 1.29700E+02 2.83424E+06 + 1.29800E+02 1.88949E+06 + 1.29900E+02 9.44746E+05 + 1.30000E+02 0.00000E+00 + 1.30100E+02 0.00000E+00 + 1.30200E+02 0.00000E+00 + 1.30300E+02 0.00000E+00 + 1.30400E+02 0.00000E+00 + 1.30500E+02 0.00000E+00 + 1.30600E+02 0.00000E+00 + 1.30700E+02 0.00000E+00 + 1.30800E+02 0.00000E+00 + 1.30900E+02 0.00000E+00 + 1.31000E+02 0.00000E+00 + 1.31100E+02 0.00000E+00 + 1.31200E+02 0.00000E+00 + 1.31300E+02 0.00000E+00 + 1.31400E+02 0.00000E+00 + 1.31500E+02 0.00000E+00 + 1.31600E+02 0.00000E+00 + 1.31700E+02 0.00000E+00 + 1.31800E+02 0.00000E+00 + 1.31900E+02 0.00000E+00 + 1.32000E+02 0.00000E+00 + 1.32100E+02 2.83424E+05 + 1.32200E+02 5.66847E+05 + 1.32300E+02 8.50271E+05 + 1.32400E+02 1.13369E+06 + 1.32500E+02 1.41712E+06 + 1.32600E+02 1.70054E+06 + 1.32700E+02 1.98397E+06 + 1.32800E+02 2.26739E+06 + 1.32900E+02 2.55081E+06 + 1.33000E+02 2.83424E+06 + 1.33100E+02 3.11766E+06 + 1.33200E+02 3.40108E+06 + 1.33300E+02 3.68451E+06 + 1.33400E+02 3.96793E+06 + 1.33500E+02 4.25136E+06 + 1.33600E+02 4.53478E+06 + 1.33700E+02 4.81820E+06 + 1.33800E+02 5.10163E+06 + 1.33900E+02 5.38505E+06 + 1.34000E+02 5.66847E+06 + 1.34100E+02 5.95190E+06 + 1.34200E+02 6.23532E+06 + 1.34300E+02 6.51875E+06 + 1.34400E+02 6.80217E+06 + 1.34500E+02 7.08559E+06 + 1.34600E+02 7.36902E+06 + 1.34700E+02 7.65244E+06 + 1.34800E+02 7.93586E+06 + 1.34900E+02 8.21929E+06 + 1.35000E+02 8.50271E+06 + 1.35100E+02 8.50271E+06 + 1.35200E+02 7.55797E+06 + 1.35300E+02 6.61322E+06 + 1.35400E+02 5.66848E+06 + 1.35500E+02 4.72373E+06 + 1.35600E+02 3.77898E+06 + 1.35700E+02 2.83424E+06 + 1.35800E+02 1.88949E+06 + 1.35900E+02 9.44746E+05 + 1.36000E+02 0.00000E+00 + 1.36100E+02 0.00000E+00 + 1.36200E+02 0.00000E+00 + 1.36300E+02 0.00000E+00 + 1.36400E+02 0.00000E+00 + 1.36500E+02 0.00000E+00 + 1.36600E+02 0.00000E+00 + 1.36700E+02 0.00000E+00 + 1.36800E+02 0.00000E+00 + 1.36900E+02 0.00000E+00 + 1.37000E+02 0.00000E+00 + 1.37100E+02 0.00000E+00 + 1.37200E+02 0.00000E+00 + 1.37300E+02 0.00000E+00 + 1.37400E+02 0.00000E+00 + 1.37500E+02 0.00000E+00 + 1.37600E+02 0.00000E+00 + 1.37700E+02 0.00000E+00 + 1.37800E+02 0.00000E+00 + 1.37900E+02 0.00000E+00 + 1.38000E+02 0.00000E+00 + 1.38100E+02 2.83424E+05 + 1.38200E+02 5.66847E+05 + 1.38300E+02 8.50271E+05 + 1.38400E+02 1.13369E+06 + 1.38500E+02 1.41712E+06 + 1.38600E+02 1.70054E+06 + 1.38700E+02 1.98397E+06 + 1.38800E+02 2.26739E+06 + 1.38900E+02 2.55081E+06 + 1.39000E+02 2.83424E+06 + 1.39100E+02 3.11766E+06 + 1.39200E+02 3.40108E+06 + 1.39300E+02 3.68451E+06 + 1.39400E+02 3.96793E+06 + 1.39500E+02 4.25136E+06 + 1.39600E+02 4.53478E+06 + 1.39700E+02 4.81820E+06 + 1.39800E+02 5.10163E+06 + 1.39900E+02 5.38505E+06 + 1.40000E+02 5.66847E+06 + 1.40100E+02 5.95190E+06 + 1.40200E+02 6.23532E+06 + 1.40300E+02 6.51875E+06 + 1.40400E+02 6.80217E+06 + 1.40500E+02 7.08559E+06 + 1.40600E+02 7.36902E+06 + 1.40700E+02 7.65244E+06 + 1.40800E+02 7.93586E+06 + 1.40900E+02 8.21929E+06 + 1.41000E+02 8.50271E+06 + 1.41100E+02 8.50271E+06 + 1.41200E+02 7.55797E+06 + 1.41300E+02 6.61322E+06 + 1.41400E+02 5.66848E+06 + 1.41500E+02 4.72373E+06 + 1.41600E+02 3.77898E+06 + 1.41700E+02 2.83424E+06 + 1.41800E+02 1.88949E+06 + 1.41900E+02 9.44746E+05 + 1.42000E+02 0.00000E+00 + 1.42100E+02 0.00000E+00 + 1.42200E+02 0.00000E+00 + 1.42300E+02 0.00000E+00 + 1.42400E+02 0.00000E+00 + 1.42500E+02 0.00000E+00 + 1.42600E+02 0.00000E+00 + 1.42700E+02 0.00000E+00 + 1.42800E+02 0.00000E+00 + 1.42900E+02 0.00000E+00 + 1.43000E+02 0.00000E+00 + 1.43100E+02 0.00000E+00 + 1.43200E+02 0.00000E+00 + 1.43300E+02 0.00000E+00 + 1.43400E+02 0.00000E+00 + 1.43500E+02 0.00000E+00 + 1.43600E+02 0.00000E+00 + 1.43700E+02 0.00000E+00 + 1.43800E+02 0.00000E+00 + 1.43900E+02 0.00000E+00 + 1.44000E+02 0.00000E+00 + 1.44100E+02 2.83424E+05 + 1.44200E+02 5.66847E+05 + 1.44300E+02 8.50271E+05 + 1.44400E+02 1.13369E+06 + 1.44500E+02 1.41712E+06 + 1.44600E+02 1.70054E+06 + 1.44700E+02 1.98397E+06 + 1.44800E+02 2.26739E+06 + 1.44900E+02 2.55081E+06 + 1.45000E+02 2.83424E+06 + 1.45100E+02 3.11766E+06 + 1.45200E+02 3.40108E+06 + 1.45300E+02 3.68451E+06 + 1.45400E+02 3.96793E+06 + 1.45500E+02 4.25136E+06 + 1.45600E+02 4.53478E+06 + 1.45700E+02 4.81820E+06 + 1.45800E+02 5.10163E+06 + 1.45900E+02 5.38505E+06 + 1.46000E+02 5.66847E+06 + 1.46100E+02 5.95190E+06 + 1.46200E+02 6.23532E+06 + 1.46300E+02 6.51875E+06 + 1.46400E+02 6.80217E+06 + 1.46500E+02 7.08559E+06 + 1.46600E+02 7.36902E+06 + 1.46700E+02 7.65244E+06 + 1.46800E+02 7.93586E+06 + 1.46900E+02 8.21929E+06 + 1.47000E+02 8.50271E+06 + 1.47100E+02 8.50271E+06 + 1.47200E+02 7.55797E+06 + 1.47300E+02 6.61322E+06 + 1.47400E+02 5.66848E+06 + 1.47500E+02 4.72373E+06 + 1.47600E+02 3.77898E+06 + 1.47700E+02 2.83424E+06 + 1.47800E+02 1.88949E+06 + 1.47900E+02 9.44746E+05 + 1.48000E+02 0.00000E+00 + 1.48100E+02 0.00000E+00 + 1.48200E+02 0.00000E+00 + 1.48300E+02 0.00000E+00 + 1.48400E+02 0.00000E+00 + 1.48500E+02 0.00000E+00 + 1.48600E+02 0.00000E+00 + 1.48700E+02 0.00000E+00 + 1.48800E+02 0.00000E+00 + 1.48900E+02 0.00000E+00 + 1.49000E+02 0.00000E+00 + 1.49100E+02 0.00000E+00 + 1.49200E+02 0.00000E+00 + 1.49300E+02 0.00000E+00 + 1.49400E+02 0.00000E+00 + 1.49500E+02 0.00000E+00 + 1.49600E+02 0.00000E+00 + 1.49700E+02 0.00000E+00 + 1.49800E+02 0.00000E+00 + 1.49900E+02 0.00000E+00 + 1.50000E+02 0.00000E+00 + 1.50100E+02 2.83424E+05 + 1.50200E+02 5.66847E+05 + 1.50300E+02 8.50271E+05 + 1.50400E+02 1.13369E+06 + 1.50500E+02 1.41712E+06 + 1.50600E+02 1.70054E+06 + 1.50700E+02 1.98397E+06 + 1.50800E+02 2.26739E+06 + 1.50900E+02 2.55081E+06 + 1.51000E+02 2.83424E+06 + 1.51100E+02 3.11766E+06 + 1.51200E+02 3.40108E+06 + 1.51300E+02 3.68451E+06 + 1.51400E+02 3.96793E+06 + 1.51500E+02 4.25136E+06 + 1.51600E+02 4.53478E+06 + 1.51700E+02 4.81820E+06 + 1.51800E+02 5.10163E+06 + 1.51900E+02 5.38505E+06 + 1.52000E+02 5.66847E+06 + 1.52100E+02 5.95190E+06 + 1.52200E+02 6.23532E+06 + 1.52300E+02 6.51875E+06 + 1.52400E+02 6.80217E+06 + 1.52500E+02 7.08559E+06 + 1.52600E+02 7.36902E+06 + 1.52700E+02 7.65244E+06 + 1.52800E+02 7.93586E+06 + 1.52900E+02 8.21929E+06 + 1.53000E+02 8.50271E+06 + 1.53100E+02 8.50271E+06 + 1.53200E+02 7.55797E+06 + 1.53300E+02 6.61322E+06 + 1.53400E+02 5.66848E+06 + 1.53500E+02 4.72373E+06 + 1.53600E+02 3.77898E+06 + 1.53700E+02 2.83424E+06 + 1.53800E+02 1.88949E+06 + 1.53900E+02 9.44746E+05 + 1.54000E+02 0.00000E+00 + 1.54100E+02 0.00000E+00 + 1.54200E+02 0.00000E+00 + 1.54300E+02 0.00000E+00 + 1.54400E+02 0.00000E+00 + 1.54500E+02 0.00000E+00 + 1.54600E+02 0.00000E+00 + 1.54700E+02 0.00000E+00 + 1.54800E+02 0.00000E+00 + 1.54900E+02 0.00000E+00 + 1.55000E+02 0.00000E+00 + 1.55100E+02 0.00000E+00 + 1.55200E+02 0.00000E+00 + 1.55300E+02 0.00000E+00 + 1.55400E+02 0.00000E+00 + 1.55500E+02 0.00000E+00 + 1.55600E+02 0.00000E+00 + 1.55700E+02 0.00000E+00 + 1.55800E+02 0.00000E+00 + 1.55900E+02 0.00000E+00 + 1.56000E+02 0.00000E+00 + 1.56100E+02 2.83424E+05 + 1.56200E+02 5.66847E+05 + 1.56300E+02 8.50271E+05 + 1.56400E+02 1.13369E+06 + 1.56500E+02 1.41712E+06 + 1.56600E+02 1.70054E+06 + 1.56700E+02 1.98397E+06 + 1.56800E+02 2.26739E+06 + 1.56900E+02 2.55081E+06 + 1.57000E+02 2.83424E+06 + 1.57100E+02 3.11766E+06 + 1.57200E+02 3.40108E+06 + 1.57300E+02 3.68451E+06 + 1.57400E+02 3.96793E+06 + 1.57500E+02 4.25136E+06 + 1.57600E+02 4.53478E+06 + 1.57700E+02 4.81820E+06 + 1.57800E+02 5.10163E+06 + 1.57900E+02 5.38505E+06 + 1.58000E+02 5.66847E+06 + 1.58100E+02 5.95190E+06 + 1.58200E+02 6.23532E+06 + 1.58300E+02 6.51875E+06 + 1.58400E+02 6.80217E+06 + 1.58500E+02 7.08559E+06 + 1.58600E+02 7.36902E+06 + 1.58700E+02 7.65244E+06 + 1.58800E+02 7.93586E+06 + 1.58900E+02 8.21929E+06 + 1.59000E+02 8.50271E+06 + 1.59100E+02 8.50271E+06 + 1.59200E+02 7.55797E+06 + 1.59300E+02 6.61322E+06 + 1.59400E+02 5.66848E+06 + 1.59500E+02 4.72373E+06 + 1.59600E+02 3.77898E+06 + 1.59700E+02 2.83424E+06 + 1.59800E+02 1.88949E+06 + 1.59900E+02 9.44746E+05 + 1.60000E+02 0.00000E+00 + 1.60100E+02 0.00000E+00 + 1.60200E+02 0.00000E+00 + 1.60300E+02 0.00000E+00 + 1.60400E+02 0.00000E+00 + 1.60500E+02 0.00000E+00 + 1.60600E+02 0.00000E+00 + 1.60700E+02 0.00000E+00 + 1.60800E+02 0.00000E+00 + 1.60900E+02 0.00000E+00 + 1.61000E+02 0.00000E+00 + 1.61100E+02 0.00000E+00 + 1.61200E+02 0.00000E+00 + 1.61300E+02 0.00000E+00 + 1.61400E+02 0.00000E+00 + 1.61500E+02 0.00000E+00 + 1.61600E+02 0.00000E+00 + 1.61700E+02 0.00000E+00 + 1.61800E+02 0.00000E+00 + 1.61900E+02 0.00000E+00 + 1.62000E+02 0.00000E+00 + 1.62100E+02 2.83424E+05 + 1.62200E+02 5.66847E+05 + 1.62300E+02 8.50271E+05 + 1.62400E+02 1.13369E+06 + 1.62500E+02 1.41712E+06 + 1.62600E+02 1.70054E+06 + 1.62700E+02 1.98397E+06 + 1.62800E+02 2.26739E+06 + 1.62900E+02 2.55081E+06 + 1.63000E+02 2.83424E+06 + 1.63100E+02 3.11766E+06 + 1.63200E+02 3.40108E+06 + 1.63300E+02 3.68451E+06 + 1.63400E+02 3.96793E+06 + 1.63500E+02 4.25136E+06 + 1.63600E+02 4.53478E+06 + 1.63700E+02 4.81820E+06 + 1.63800E+02 5.10163E+06 + 1.63900E+02 5.38505E+06 + 1.64000E+02 5.66847E+06 + 1.64100E+02 5.95190E+06 + 1.64200E+02 6.23532E+06 + 1.64300E+02 6.51875E+06 + 1.64400E+02 6.80217E+06 + 1.64500E+02 7.08559E+06 + 1.64600E+02 7.36902E+06 + 1.64700E+02 7.65244E+06 + 1.64800E+02 7.93586E+06 + 1.64900E+02 8.21929E+06 + 1.65000E+02 8.50271E+06 + 1.65100E+02 8.50271E+06 + 1.65200E+02 7.55797E+06 + 1.65300E+02 6.61322E+06 + 1.65400E+02 5.66848E+06 + 1.65500E+02 4.72373E+06 + 1.65600E+02 3.77898E+06 + 1.65700E+02 2.83424E+06 + 1.65800E+02 1.88949E+06 + 1.65900E+02 9.44746E+05 + 1.66000E+02 0.00000E+00 + 1.66100E+02 0.00000E+00 + 1.66200E+02 0.00000E+00 + 1.66300E+02 0.00000E+00 + 1.66400E+02 0.00000E+00 + 1.66500E+02 0.00000E+00 + 1.66600E+02 0.00000E+00 + 1.66700E+02 0.00000E+00 + 1.66800E+02 0.00000E+00 + 1.66900E+02 0.00000E+00 + 1.67000E+02 0.00000E+00 + 1.67100E+02 0.00000E+00 + 1.67200E+02 0.00000E+00 + 1.67300E+02 0.00000E+00 + 1.67400E+02 0.00000E+00 + 1.67500E+02 0.00000E+00 + 1.67600E+02 0.00000E+00 + 1.67700E+02 0.00000E+00 + 1.67800E+02 0.00000E+00 + 1.67900E+02 0.00000E+00 + 1.68000E+02 0.00000E+00 + 1.68100E+02 2.83424E+05 + 1.68200E+02 5.66847E+05 + 1.68300E+02 8.50271E+05 + 1.68400E+02 1.13369E+06 + 1.68500E+02 1.41712E+06 + 1.68600E+02 1.70054E+06 + 1.68700E+02 1.98397E+06 + 1.68800E+02 2.26739E+06 + 1.68900E+02 2.55081E+06 + 1.69000E+02 2.83424E+06 + 1.69100E+02 3.11766E+06 + 1.69200E+02 3.40108E+06 + 1.69300E+02 3.68451E+06 + 1.69400E+02 3.96793E+06 + 1.69500E+02 4.25136E+06 + 1.69600E+02 4.53478E+06 + 1.69700E+02 4.81820E+06 + 1.69800E+02 5.10163E+06 + 1.69900E+02 5.38505E+06 + 1.70000E+02 5.66847E+06 + 1.70100E+02 5.95190E+06 + 1.70200E+02 6.23532E+06 + 1.70300E+02 6.51875E+06 + 1.70400E+02 6.80217E+06 + 1.70500E+02 7.08559E+06 + 1.70600E+02 7.36902E+06 + 1.70700E+02 7.65244E+06 + 1.70800E+02 7.93586E+06 + 1.70900E+02 8.21929E+06 + 1.71000E+02 8.50271E+06 + 1.71100E+02 8.50271E+06 + 1.71200E+02 7.55797E+06 + 1.71300E+02 6.61322E+06 + 1.71400E+02 5.66848E+06 + 1.71500E+02 4.72373E+06 + 1.71600E+02 3.77898E+06 + 1.71700E+02 2.83424E+06 + 1.71800E+02 1.88949E+06 + 1.71900E+02 9.44746E+05 + 1.72000E+02 0.00000E+00 + 1.72100E+02 0.00000E+00 + 1.72200E+02 0.00000E+00 + 1.72300E+02 0.00000E+00 + 1.72400E+02 0.00000E+00 + 1.72500E+02 0.00000E+00 + 1.72600E+02 0.00000E+00 + 1.72700E+02 0.00000E+00 + 1.72800E+02 0.00000E+00 + 1.72900E+02 0.00000E+00 + 1.73000E+02 0.00000E+00 + 1.73100E+02 0.00000E+00 + 1.73200E+02 0.00000E+00 + 1.73300E+02 0.00000E+00 + 1.73400E+02 0.00000E+00 + 1.73500E+02 0.00000E+00 + 1.73600E+02 0.00000E+00 + 1.73700E+02 0.00000E+00 + 1.73800E+02 0.00000E+00 + 1.73900E+02 0.00000E+00 + 1.74000E+02 0.00000E+00 + 1.74100E+02 2.83424E+05 + 1.74200E+02 5.66847E+05 + 1.74300E+02 8.50271E+05 + 1.74400E+02 1.13369E+06 + 1.74500E+02 1.41712E+06 + 1.74600E+02 1.70054E+06 + 1.74700E+02 1.98397E+06 + 1.74800E+02 2.26739E+06 + 1.74900E+02 2.55081E+06 + 1.75000E+02 2.83424E+06 + 1.75100E+02 3.11766E+06 + 1.75200E+02 3.40108E+06 + 1.75300E+02 3.68451E+06 + 1.75400E+02 3.96793E+06 + 1.75500E+02 4.25136E+06 + 1.75600E+02 4.53478E+06 + 1.75700E+02 4.81820E+06 + 1.75800E+02 5.10163E+06 + 1.75900E+02 5.38505E+06 + 1.76000E+02 5.66847E+06 + 1.76100E+02 5.95190E+06 + 1.76200E+02 6.23532E+06 + 1.76300E+02 6.51875E+06 + 1.76400E+02 6.80217E+06 + 1.76500E+02 7.08559E+06 + 1.76600E+02 7.36902E+06 + 1.76700E+02 7.65244E+06 + 1.76800E+02 7.93586E+06 + 1.76900E+02 8.21929E+06 + 1.77000E+02 8.50271E+06 + 1.77100E+02 8.50271E+06 + 1.77200E+02 7.55797E+06 + 1.77300E+02 6.61322E+06 + 1.77400E+02 5.66848E+06 + 1.77500E+02 4.72373E+06 + 1.77600E+02 3.77898E+06 + 1.77700E+02 2.83424E+06 + 1.77800E+02 1.88949E+06 + 1.77900E+02 9.44746E+05 + 1.78000E+02 0.00000E+00 + 1.78100E+02 0.00000E+00 + 1.78200E+02 0.00000E+00 + 1.78300E+02 0.00000E+00 + 1.78400E+02 0.00000E+00 + 1.78500E+02 0.00000E+00 + 1.78600E+02 0.00000E+00 + 1.78700E+02 0.00000E+00 + 1.78800E+02 0.00000E+00 + 1.78900E+02 0.00000E+00 + 1.79000E+02 0.00000E+00 + 1.79100E+02 0.00000E+00 + 1.79200E+02 0.00000E+00 + 1.79300E+02 0.00000E+00 + 1.79400E+02 0.00000E+00 + 1.79500E+02 0.00000E+00 + 1.79600E+02 0.00000E+00 + 1.79700E+02 0.00000E+00 + 1.79800E+02 0.00000E+00 + 1.79900E+02 0.00000E+00 + 1.80000E+02 0.00000E+00 + 1.80100E+02 2.83424E+05 + 1.80200E+02 5.66847E+05 + 1.80300E+02 8.50271E+05 + 1.80400E+02 1.13369E+06 + 1.80500E+02 1.41712E+06 + 1.80600E+02 1.70054E+06 + 1.80700E+02 1.98397E+06 + 1.80800E+02 2.26739E+06 + 1.80900E+02 2.55081E+06 + 1.81000E+02 2.83424E+06 + 1.81100E+02 3.11766E+06 + 1.81200E+02 3.40108E+06 + 1.81300E+02 3.68451E+06 + 1.81400E+02 3.96793E+06 + 1.81500E+02 4.25136E+06 + 1.81600E+02 4.53478E+06 + 1.81700E+02 4.81820E+06 + 1.81800E+02 5.10163E+06 + 1.81900E+02 5.38505E+06 + 1.82000E+02 5.66847E+06 + 1.82100E+02 5.95190E+06 + 1.82200E+02 6.23532E+06 + 1.82300E+02 6.51875E+06 + 1.82400E+02 6.80217E+06 + 1.82500E+02 7.08559E+06 + 1.82600E+02 7.36902E+06 + 1.82700E+02 7.65244E+06 + 1.82800E+02 7.93586E+06 + 1.82900E+02 8.21929E+06 + 1.83000E+02 8.50271E+06 + 1.83100E+02 8.50271E+06 + 1.83200E+02 7.55797E+06 + 1.83300E+02 6.61322E+06 + 1.83400E+02 5.66848E+06 + 1.83500E+02 4.72373E+06 + 1.83600E+02 3.77898E+06 + 1.83700E+02 2.83424E+06 + 1.83800E+02 1.88949E+06 + 1.83900E+02 9.44746E+05 + 1.84000E+02 0.00000E+00 + 1.84100E+02 0.00000E+00 + 1.84200E+02 0.00000E+00 + 1.84300E+02 0.00000E+00 + 1.84400E+02 0.00000E+00 + 1.84500E+02 0.00000E+00 + 1.84600E+02 0.00000E+00 + 1.84700E+02 0.00000E+00 + 1.84800E+02 0.00000E+00 + 1.84900E+02 0.00000E+00 + 1.85000E+02 0.00000E+00 + 1.85100E+02 0.00000E+00 + 1.85200E+02 0.00000E+00 + 1.85300E+02 0.00000E+00 + 1.85400E+02 0.00000E+00 + 1.85500E+02 0.00000E+00 + 1.85600E+02 0.00000E+00 + 1.85700E+02 0.00000E+00 + 1.85800E+02 0.00000E+00 + 1.85900E+02 0.00000E+00 + 1.86000E+02 0.00000E+00 + 1.86100E+02 2.83424E+05 + 1.86200E+02 5.66847E+05 + 1.86300E+02 8.50271E+05 + 1.86400E+02 1.13369E+06 + 1.86500E+02 1.41712E+06 + 1.86600E+02 1.70054E+06 + 1.86700E+02 1.98397E+06 + 1.86800E+02 2.26739E+06 + 1.86900E+02 2.55081E+06 + 1.87000E+02 2.83424E+06 + 1.87100E+02 3.11766E+06 + 1.87200E+02 3.40108E+06 + 1.87300E+02 3.68451E+06 + 1.87400E+02 3.96793E+06 + 1.87500E+02 4.25136E+06 + 1.87600E+02 4.53478E+06 + 1.87700E+02 4.81820E+06 + 1.87800E+02 5.10163E+06 + 1.87900E+02 5.38505E+06 + 1.88000E+02 5.66847E+06 + 1.88100E+02 5.95190E+06 + 1.88200E+02 6.23532E+06 + 1.88300E+02 6.51875E+06 + 1.88400E+02 6.80217E+06 + 1.88500E+02 7.08559E+06 + 1.88600E+02 7.36902E+06 + 1.88700E+02 7.65244E+06 + 1.88800E+02 7.93586E+06 + 1.88900E+02 8.21929E+06 + 1.89000E+02 8.50271E+06 + 1.89100E+02 8.50271E+06 + 1.89200E+02 7.55797E+06 + 1.89300E+02 6.61322E+06 + 1.89400E+02 5.66848E+06 + 1.89500E+02 4.72373E+06 + 1.89600E+02 3.77898E+06 + 1.89700E+02 2.83424E+06 + 1.89800E+02 1.88949E+06 + 1.89900E+02 9.44746E+05 + 1.90000E+02 0.00000E+00 + 1.90100E+02 0.00000E+00 + 1.90200E+02 0.00000E+00 + 1.90300E+02 0.00000E+00 + 1.90400E+02 0.00000E+00 + 1.90500E+02 0.00000E+00 + 1.90600E+02 0.00000E+00 + 1.90700E+02 0.00000E+00 + 1.90800E+02 0.00000E+00 + 1.90900E+02 0.00000E+00 + 1.91000E+02 0.00000E+00 + 1.91100E+02 0.00000E+00 + 1.91200E+02 0.00000E+00 + 1.91300E+02 0.00000E+00 + 1.91400E+02 0.00000E+00 + 1.91500E+02 0.00000E+00 + 1.91600E+02 0.00000E+00 + 1.91700E+02 0.00000E+00 + 1.91800E+02 0.00000E+00 + 1.91900E+02 0.00000E+00 + 1.92000E+02 0.00000E+00 + 1.92100E+02 2.83424E+05 + 1.92200E+02 5.66847E+05 + 1.92300E+02 8.50271E+05 + 1.92400E+02 1.13369E+06 + 1.92500E+02 1.41712E+06 + 1.92600E+02 1.70054E+06 + 1.92700E+02 1.98397E+06 + 1.92800E+02 2.26739E+06 + 1.92900E+02 2.55081E+06 + 1.93000E+02 2.83424E+06 + 1.93100E+02 3.11766E+06 + 1.93200E+02 3.40108E+06 + 1.93300E+02 3.68451E+06 + 1.93400E+02 3.96793E+06 + 1.93500E+02 4.25136E+06 + 1.93600E+02 4.53478E+06 + 1.93700E+02 4.81820E+06 + 1.93800E+02 5.10163E+06 + 1.93900E+02 5.38505E+06 + 1.94000E+02 5.66847E+06 + 1.94100E+02 5.95190E+06 + 1.94200E+02 6.23532E+06 + 1.94300E+02 6.51875E+06 + 1.94400E+02 6.80217E+06 + 1.94500E+02 7.08559E+06 + 1.94600E+02 7.36902E+06 + 1.94700E+02 7.65244E+06 + 1.94800E+02 7.93586E+06 + 1.94900E+02 8.21929E+06 + 1.95000E+02 8.50271E+06 + 1.95100E+02 8.50271E+06 + 1.95200E+02 7.55797E+06 + 1.95300E+02 6.61322E+06 + 1.95400E+02 5.66848E+06 + 1.95500E+02 4.72373E+06 + 1.95600E+02 3.77898E+06 + 1.95700E+02 2.83424E+06 + 1.95800E+02 1.88949E+06 + 1.95900E+02 9.44746E+05 + 1.96000E+02 0.00000E+00 + 1.96100E+02 0.00000E+00 + 1.96200E+02 0.00000E+00 + 1.96300E+02 0.00000E+00 + 1.96400E+02 0.00000E+00 + 1.96500E+02 0.00000E+00 + 1.96600E+02 0.00000E+00 + 1.96700E+02 0.00000E+00 + 1.96800E+02 0.00000E+00 + 1.96900E+02 0.00000E+00 + 1.97000E+02 0.00000E+00 + 1.97100E+02 0.00000E+00 + 1.97200E+02 0.00000E+00 + 1.97300E+02 0.00000E+00 + 1.97400E+02 0.00000E+00 + 1.97500E+02 0.00000E+00 + 1.97600E+02 0.00000E+00 + 1.97700E+02 0.00000E+00 + 1.97800E+02 0.00000E+00 + 1.97900E+02 0.00000E+00 + 1.98000E+02 0.00000E+00 + 1.98100E+02 2.83424E+05 + 1.98200E+02 5.66847E+05 + 1.98300E+02 8.50271E+05 + 1.98400E+02 1.13369E+06 + 1.98500E+02 1.41712E+06 + 1.98600E+02 1.70054E+06 + 1.98700E+02 1.98397E+06 + 1.98800E+02 2.26739E+06 + 1.98900E+02 2.55081E+06 + 1.99000E+02 2.83424E+06 + 1.99100E+02 3.11766E+06 + 1.99200E+02 3.40108E+06 + 1.99300E+02 3.68451E+06 + 1.99400E+02 3.96793E+06 + 1.99500E+02 4.25136E+06 + 1.99600E+02 4.53478E+06 + 1.99700E+02 4.81820E+06 + 1.99800E+02 5.10163E+06 + 1.99900E+02 5.38505E+06 + 2.00000E+02 5.66847E+06 + 2.00100E+02 5.95190E+06 + 2.00200E+02 6.23532E+06 + 2.00300E+02 6.51875E+06 + 2.00400E+02 6.80217E+06 + 2.00500E+02 7.08559E+06 + 2.00600E+02 7.36902E+06 + 2.00700E+02 7.65244E+06 + 2.00800E+02 7.93586E+06 + 2.00900E+02 8.21929E+06 + 2.01000E+02 8.50271E+06 + 2.01100E+02 8.50271E+06 + 2.01200E+02 7.55797E+06 + 2.01300E+02 6.61322E+06 + 2.01400E+02 5.66848E+06 + 2.01500E+02 4.72373E+06 + 2.01600E+02 3.77898E+06 + 2.01700E+02 2.83424E+06 + 2.01800E+02 1.88949E+06 + 2.01900E+02 9.44746E+05 + 2.02000E+02 0.00000E+00 + 2.02100E+02 0.00000E+00 + 2.02200E+02 0.00000E+00 + 2.02300E+02 0.00000E+00 + 2.02400E+02 0.00000E+00 + 2.02500E+02 0.00000E+00 + 2.02600E+02 0.00000E+00 + 2.02700E+02 0.00000E+00 + 2.02800E+02 0.00000E+00 + 2.02900E+02 0.00000E+00 + 2.03000E+02 0.00000E+00 + 2.03100E+02 0.00000E+00 + 2.03200E+02 0.00000E+00 + 2.03300E+02 0.00000E+00 + 2.03400E+02 0.00000E+00 + 2.03500E+02 0.00000E+00 + 2.03600E+02 0.00000E+00 + 2.03700E+02 0.00000E+00 + 2.03800E+02 0.00000E+00 + 2.03900E+02 0.00000E+00 + 2.04000E+02 0.00000E+00 + 2.04100E+02 2.83424E+05 + 2.04200E+02 5.66847E+05 + 2.04300E+02 8.50271E+05 + 2.04400E+02 1.13369E+06 + 2.04500E+02 1.41712E+06 + 2.04600E+02 1.70054E+06 + 2.04700E+02 1.98397E+06 + 2.04800E+02 2.26739E+06 + 2.04900E+02 2.55081E+06 + 2.05000E+02 2.83424E+06 + 2.05100E+02 3.11766E+06 + 2.05200E+02 3.40108E+06 + 2.05300E+02 3.68451E+06 + 2.05400E+02 3.96793E+06 + 2.05500E+02 4.25136E+06 + 2.05600E+02 4.53478E+06 + 2.05700E+02 4.81820E+06 + 2.05800E+02 5.10163E+06 + 2.05900E+02 5.38505E+06 + 2.06000E+02 5.66847E+06 + 2.06100E+02 5.95190E+06 + 2.06200E+02 6.23532E+06 + 2.06300E+02 6.51875E+06 + 2.06400E+02 6.80217E+06 + 2.06500E+02 7.08559E+06 + 2.06600E+02 7.36902E+06 + 2.06700E+02 7.65244E+06 + 2.06800E+02 7.93586E+06 + 2.06900E+02 8.21929E+06 + 2.07000E+02 8.50271E+06 + 2.07100E+02 8.50271E+06 + 2.07200E+02 7.55797E+06 + 2.07300E+02 6.61322E+06 + 2.07400E+02 5.66848E+06 + 2.07500E+02 4.72373E+06 + 2.07600E+02 3.77898E+06 + 2.07700E+02 2.83424E+06 + 2.07800E+02 1.88949E+06 + 2.07900E+02 9.44746E+05 + 2.08000E+02 0.00000E+00 + 2.08100E+02 0.00000E+00 + 2.08200E+02 0.00000E+00 + 2.08300E+02 0.00000E+00 + 2.08400E+02 0.00000E+00 + 2.08500E+02 0.00000E+00 + 2.08600E+02 0.00000E+00 + 2.08700E+02 0.00000E+00 + 2.08800E+02 0.00000E+00 + 2.08900E+02 0.00000E+00 + 2.09000E+02 0.00000E+00 + 2.09100E+02 0.00000E+00 + 2.09200E+02 0.00000E+00 + 2.09300E+02 0.00000E+00 + 2.09400E+02 0.00000E+00 + 2.09500E+02 0.00000E+00 + 2.09600E+02 0.00000E+00 + 2.09700E+02 0.00000E+00 + 2.09800E+02 0.00000E+00 + 2.09900E+02 0.00000E+00 + 2.10000E+02 0.00000E+00 + 2.10100E+02 2.83424E+05 + 2.10200E+02 5.66847E+05 + 2.10300E+02 8.50271E+05 + 2.10400E+02 1.13369E+06 + 2.10500E+02 1.41712E+06 + 2.10600E+02 1.70054E+06 + 2.10700E+02 1.98397E+06 + 2.10800E+02 2.26739E+06 + 2.10900E+02 2.55081E+06 + 2.11000E+02 2.83424E+06 + 2.11100E+02 3.11766E+06 + 2.11200E+02 3.40108E+06 + 2.11300E+02 3.68451E+06 + 2.11400E+02 3.96793E+06 + 2.11500E+02 4.25136E+06 + 2.11600E+02 4.53478E+06 + 2.11700E+02 4.81820E+06 + 2.11800E+02 5.10163E+06 + 2.11900E+02 5.38505E+06 + 2.12000E+02 5.66847E+06 + 2.12100E+02 5.95190E+06 + 2.12200E+02 6.23532E+06 + 2.12300E+02 6.51875E+06 + 2.12400E+02 6.80217E+06 + 2.12500E+02 7.08559E+06 + 2.12600E+02 7.36902E+06 + 2.12700E+02 7.65244E+06 + 2.12800E+02 7.93586E+06 + 2.12900E+02 8.21929E+06 + 2.13000E+02 8.50271E+06 + 2.13100E+02 8.50271E+06 + 2.13200E+02 7.55797E+06 + 2.13300E+02 6.61322E+06 + 2.13400E+02 5.66848E+06 + 2.13500E+02 4.72373E+06 + 2.13600E+02 3.77898E+06 + 2.13700E+02 2.83424E+06 + 2.13800E+02 1.88949E+06 + 2.13900E+02 9.44746E+05 + 2.14000E+02 0.00000E+00 + 2.14100E+02 0.00000E+00 + 2.14200E+02 0.00000E+00 + 2.14300E+02 0.00000E+00 + 2.14400E+02 0.00000E+00 + 2.14500E+02 0.00000E+00 + 2.14600E+02 0.00000E+00 + 2.14700E+02 0.00000E+00 + 2.14800E+02 0.00000E+00 + 2.14900E+02 0.00000E+00 + 2.15000E+02 0.00000E+00 + 2.15100E+02 0.00000E+00 + 2.15200E+02 0.00000E+00 + 2.15300E+02 0.00000E+00 + 2.15400E+02 0.00000E+00 + 2.15500E+02 0.00000E+00 + 2.15600E+02 0.00000E+00 + 2.15700E+02 0.00000E+00 + 2.15800E+02 0.00000E+00 + 2.15900E+02 0.00000E+00 + 2.16000E+02 0.00000E+00 + 2.16100E+02 2.83424E+05 + 2.16200E+02 5.66847E+05 + 2.16300E+02 8.50271E+05 + 2.16400E+02 1.13369E+06 + 2.16500E+02 1.41712E+06 + 2.16600E+02 1.70054E+06 + 2.16700E+02 1.98397E+06 + 2.16800E+02 2.26739E+06 + 2.16900E+02 2.55081E+06 + 2.17000E+02 2.83424E+06 + 2.17100E+02 3.11766E+06 + 2.17200E+02 3.40108E+06 + 2.17300E+02 3.68451E+06 + 2.17400E+02 3.96793E+06 + 2.17500E+02 4.25136E+06 + 2.17600E+02 4.53478E+06 + 2.17700E+02 4.81820E+06 + 2.17800E+02 5.10163E+06 + 2.17900E+02 5.38505E+06 + 2.18000E+02 5.66847E+06 + 2.18100E+02 5.95190E+06 + 2.18200E+02 6.23532E+06 + 2.18300E+02 6.51875E+06 + 2.18400E+02 6.80217E+06 + 2.18500E+02 7.08559E+06 + 2.18600E+02 7.36902E+06 + 2.18700E+02 7.65244E+06 + 2.18800E+02 7.93586E+06 + 2.18900E+02 8.21929E+06 + 2.19000E+02 8.50271E+06 + 2.19100E+02 8.50271E+06 + 2.19200E+02 7.55797E+06 + 2.19300E+02 6.61322E+06 + 2.19400E+02 5.66848E+06 + 2.19500E+02 4.72373E+06 + 2.19600E+02 3.77898E+06 + 2.19700E+02 2.83424E+06 + 2.19800E+02 1.88949E+06 + 2.19900E+02 9.44746E+05 + 2.20000E+02 0.00000E+00 + 2.20100E+02 0.00000E+00 + 2.20200E+02 0.00000E+00 + 2.20300E+02 0.00000E+00 + 2.20400E+02 0.00000E+00 + 2.20500E+02 0.00000E+00 + 2.20600E+02 0.00000E+00 + 2.20700E+02 0.00000E+00 + 2.20800E+02 0.00000E+00 + 2.20900E+02 0.00000E+00 + 2.21000E+02 0.00000E+00 + 2.21100E+02 0.00000E+00 + 2.21200E+02 0.00000E+00 + 2.21300E+02 0.00000E+00 + 2.21400E+02 0.00000E+00 + 2.21500E+02 0.00000E+00 + 2.21600E+02 0.00000E+00 + 2.21700E+02 0.00000E+00 + 2.21800E+02 0.00000E+00 + 2.21900E+02 0.00000E+00 + 2.22000E+02 0.00000E+00 + 2.22100E+02 2.83424E+05 + 2.22200E+02 5.66847E+05 + 2.22300E+02 8.50271E+05 + 2.22400E+02 1.13369E+06 + 2.22500E+02 1.41712E+06 + 2.22600E+02 1.70054E+06 + 2.22700E+02 1.98397E+06 + 2.22800E+02 2.26739E+06 + 2.22900E+02 2.55081E+06 + 2.23000E+02 2.83424E+06 + 2.23100E+02 3.11766E+06 + 2.23200E+02 3.40108E+06 + 2.23300E+02 3.68451E+06 + 2.23400E+02 3.96793E+06 + 2.23500E+02 4.25136E+06 + 2.23600E+02 4.53478E+06 + 2.23700E+02 4.81820E+06 + 2.23800E+02 5.10163E+06 + 2.23900E+02 5.38505E+06 + 2.24000E+02 5.66847E+06 + 2.24100E+02 5.95190E+06 + 2.24200E+02 6.23532E+06 + 2.24300E+02 6.51875E+06 + 2.24400E+02 6.80217E+06 + 2.24500E+02 7.08559E+06 + 2.24600E+02 7.36902E+06 + 2.24700E+02 7.65244E+06 + 2.24800E+02 7.93586E+06 + 2.24900E+02 8.21929E+06 + 2.25000E+02 8.50271E+06 + 2.25100E+02 8.50271E+06 + 2.25200E+02 7.55797E+06 + 2.25300E+02 6.61322E+06 + 2.25400E+02 5.66848E+06 + 2.25500E+02 4.72373E+06 + 2.25600E+02 3.77898E+06 + 2.25700E+02 2.83424E+06 + 2.25800E+02 1.88949E+06 + 2.25900E+02 9.44746E+05 + 2.26000E+02 0.00000E+00 + 2.26100E+02 0.00000E+00 + 2.26200E+02 0.00000E+00 + 2.26300E+02 0.00000E+00 + 2.26400E+02 0.00000E+00 + 2.26500E+02 0.00000E+00 + 2.26600E+02 0.00000E+00 + 2.26700E+02 0.00000E+00 + 2.26800E+02 0.00000E+00 + 2.26900E+02 0.00000E+00 + 2.27000E+02 0.00000E+00 + 2.27100E+02 0.00000E+00 + 2.27200E+02 0.00000E+00 + 2.27300E+02 0.00000E+00 + 2.27400E+02 0.00000E+00 + 2.27500E+02 0.00000E+00 + 2.27600E+02 0.00000E+00 + 2.27700E+02 0.00000E+00 + 2.27800E+02 0.00000E+00 + 2.27900E+02 0.00000E+00 + 2.28000E+02 0.00000E+00 + 2.28100E+02 2.83424E+05 + 2.28200E+02 5.66847E+05 + 2.28300E+02 8.50271E+05 + 2.28400E+02 1.13369E+06 + 2.28500E+02 1.41712E+06 + 2.28600E+02 1.70054E+06 + 2.28700E+02 1.98397E+06 + 2.28800E+02 2.26739E+06 + 2.28900E+02 2.55081E+06 + 2.29000E+02 2.83424E+06 + 2.29100E+02 3.11766E+06 + 2.29200E+02 3.40108E+06 + 2.29300E+02 3.68451E+06 + 2.29400E+02 3.96793E+06 + 2.29500E+02 4.25136E+06 + 2.29600E+02 4.53478E+06 + 2.29700E+02 4.81820E+06 + 2.29800E+02 5.10163E+06 + 2.29900E+02 5.38505E+06 + 2.30000E+02 5.66847E+06 + 2.30100E+02 5.95190E+06 + 2.30200E+02 6.23532E+06 + 2.30300E+02 6.51875E+06 + 2.30400E+02 6.80217E+06 + 2.30500E+02 7.08559E+06 + 2.30600E+02 7.36902E+06 + 2.30700E+02 7.65244E+06 + 2.30800E+02 7.93586E+06 + 2.30900E+02 8.21929E+06 + 2.31000E+02 8.50271E+06 + 2.31100E+02 8.50271E+06 + 2.31200E+02 7.55797E+06 + 2.31300E+02 6.61322E+06 + 2.31400E+02 5.66848E+06 + 2.31500E+02 4.72373E+06 + 2.31600E+02 3.77898E+06 + 2.31700E+02 2.83424E+06 + 2.31800E+02 1.88949E+06 + 2.31900E+02 9.44746E+05 + 2.32000E+02 0.00000E+00 + 2.32100E+02 0.00000E+00 + 2.32200E+02 0.00000E+00 + 2.32300E+02 0.00000E+00 + 2.32400E+02 0.00000E+00 + 2.32500E+02 0.00000E+00 + 2.32600E+02 0.00000E+00 + 2.32700E+02 0.00000E+00 + 2.32800E+02 0.00000E+00 + 2.32900E+02 0.00000E+00 + 2.33000E+02 0.00000E+00 + 2.33100E+02 0.00000E+00 + 2.33200E+02 0.00000E+00 + 2.33300E+02 0.00000E+00 + 2.33400E+02 0.00000E+00 + 2.33500E+02 0.00000E+00 + 2.33600E+02 0.00000E+00 + 2.33700E+02 0.00000E+00 + 2.33800E+02 0.00000E+00 + 2.33900E+02 0.00000E+00 + 2.34000E+02 0.00000E+00 + 2.34100E+02 2.83424E+05 + 2.34200E+02 5.66847E+05 + 2.34300E+02 8.50271E+05 + 2.34400E+02 1.13369E+06 + 2.34500E+02 1.41712E+06 + 2.34600E+02 1.70054E+06 + 2.34700E+02 1.98397E+06 + 2.34800E+02 2.26739E+06 + 2.34900E+02 2.55081E+06 + 2.35000E+02 2.83424E+06 + 2.35100E+02 3.11766E+06 + 2.35200E+02 3.40108E+06 + 2.35300E+02 3.68451E+06 + 2.35400E+02 3.96793E+06 + 2.35500E+02 4.25136E+06 + 2.35600E+02 4.53478E+06 + 2.35700E+02 4.81820E+06 + 2.35800E+02 5.10163E+06 + 2.35900E+02 5.38505E+06 + 2.36000E+02 5.66847E+06 + 2.36100E+02 5.95190E+06 + 2.36200E+02 6.23532E+06 + 2.36300E+02 6.51875E+06 + 2.36400E+02 6.80217E+06 + 2.36500E+02 7.08559E+06 + 2.36600E+02 7.36902E+06 + 2.36700E+02 7.65244E+06 + 2.36800E+02 7.93586E+06 + 2.36900E+02 8.21929E+06 + 2.37000E+02 8.50271E+06 + 2.37100E+02 8.50271E+06 + 2.37200E+02 7.55797E+06 + 2.37300E+02 6.61322E+06 + 2.37400E+02 5.66848E+06 + 2.37500E+02 4.72373E+06 + 2.37600E+02 3.77898E+06 + 2.37700E+02 2.83424E+06 + 2.37800E+02 1.88949E+06 + 2.37900E+02 9.44746E+05 + 2.38000E+02 0.00000E+00 + 2.38100E+02 0.00000E+00 + 2.38200E+02 0.00000E+00 + 2.38300E+02 0.00000E+00 + 2.38400E+02 0.00000E+00 + 2.38500E+02 0.00000E+00 + 2.38600E+02 0.00000E+00 + 2.38700E+02 0.00000E+00 + 2.38800E+02 0.00000E+00 + 2.38900E+02 0.00000E+00 + 2.39000E+02 0.00000E+00 + 2.39100E+02 0.00000E+00 + 2.39200E+02 0.00000E+00 + 2.39300E+02 0.00000E+00 + 2.39400E+02 0.00000E+00 + 2.39500E+02 0.00000E+00 + 2.39600E+02 0.00000E+00 + 2.39700E+02 0.00000E+00 + 2.39800E+02 0.00000E+00 + 2.39900E+02 0.00000E+00 + 2.40000E+02 0.00000E+00 + 2.40100E+02 2.83424E+05 + 2.40200E+02 5.66847E+05 + 2.40300E+02 8.50271E+05 + 2.40400E+02 1.13369E+06 + 2.40500E+02 1.41712E+06 + 2.40600E+02 1.70054E+06 + 2.40700E+02 1.98397E+06 + 2.40800E+02 2.26739E+06 + 2.40900E+02 2.55081E+06 + 2.41000E+02 2.83424E+06 + 2.41100E+02 3.11766E+06 + 2.41200E+02 3.40108E+06 + 2.41300E+02 3.68451E+06 + 2.41400E+02 3.96793E+06 + 2.41500E+02 4.25136E+06 + 2.41600E+02 4.53478E+06 + 2.41700E+02 4.81820E+06 + 2.41800E+02 5.10163E+06 + 2.41900E+02 5.38505E+06 + 2.42000E+02 5.66847E+06 + 2.42100E+02 5.95190E+06 + 2.42200E+02 6.23532E+06 + 2.42300E+02 6.51875E+06 + 2.42400E+02 6.80217E+06 + 2.42500E+02 7.08559E+06 + 2.42600E+02 7.36902E+06 + 2.42700E+02 7.65244E+06 + 2.42800E+02 7.93586E+06 + 2.42900E+02 8.21929E+06 + 2.43000E+02 8.50271E+06 + 2.43100E+02 8.50271E+06 + 2.43200E+02 7.55797E+06 + 2.43300E+02 6.61322E+06 + 2.43400E+02 5.66848E+06 + 2.43500E+02 4.72373E+06 + 2.43600E+02 3.77898E+06 + 2.43700E+02 2.83424E+06 + 2.43800E+02 1.88949E+06 + 2.43900E+02 9.44746E+05 + 2.44000E+02 0.00000E+00 + 2.44100E+02 0.00000E+00 + 2.44200E+02 0.00000E+00 + 2.44300E+02 0.00000E+00 + 2.44400E+02 0.00000E+00 + 2.44500E+02 0.00000E+00 + 2.44600E+02 0.00000E+00 + 2.44700E+02 0.00000E+00 + 2.44800E+02 0.00000E+00 + 2.44900E+02 0.00000E+00 + 2.45000E+02 0.00000E+00 + 2.45100E+02 0.00000E+00 + 2.45200E+02 0.00000E+00 + 2.45300E+02 0.00000E+00 + 2.45400E+02 0.00000E+00 + 2.45500E+02 0.00000E+00 + 2.45600E+02 0.00000E+00 + 2.45700E+02 0.00000E+00 + 2.45800E+02 0.00000E+00 + 2.45900E+02 0.00000E+00 + 2.46000E+02 0.00000E+00 + 2.46100E+02 2.83424E+05 + 2.46200E+02 5.66847E+05 + 2.46300E+02 8.50271E+05 + 2.46400E+02 1.13369E+06 + 2.46500E+02 1.41712E+06 + 2.46600E+02 1.70054E+06 + 2.46700E+02 1.98397E+06 + 2.46800E+02 2.26739E+06 + 2.46900E+02 2.55081E+06 + 2.47000E+02 2.83424E+06 + 2.47100E+02 3.11766E+06 + 2.47200E+02 3.40108E+06 + 2.47300E+02 3.68451E+06 + 2.47400E+02 3.96793E+06 + 2.47500E+02 4.25136E+06 + 2.47600E+02 4.53478E+06 + 2.47700E+02 4.81820E+06 + 2.47800E+02 5.10163E+06 + 2.47900E+02 5.38505E+06 + 2.48000E+02 5.66847E+06 + 2.48100E+02 5.95190E+06 + 2.48200E+02 6.23532E+06 + 2.48300E+02 6.51875E+06 + 2.48400E+02 6.80217E+06 + 2.48500E+02 7.08559E+06 + 2.48600E+02 7.36902E+06 + 2.48700E+02 7.65244E+06 + 2.48800E+02 7.93586E+06 + 2.48900E+02 8.21929E+06 + 2.49000E+02 8.50271E+06 + 2.49100E+02 8.50271E+06 + 2.49200E+02 7.55797E+06 + 2.49300E+02 6.61322E+06 + 2.49400E+02 5.66848E+06 + 2.49500E+02 4.72373E+06 + 2.49600E+02 3.77898E+06 + 2.49700E+02 2.83424E+06 + 2.49800E+02 1.88949E+06 + 2.49900E+02 9.44746E+05 + 2.50000E+02 0.00000E+00 + 2.50100E+02 0.00000E+00 + 2.50200E+02 0.00000E+00 + 2.50300E+02 0.00000E+00 + 2.50400E+02 0.00000E+00 + 2.50500E+02 0.00000E+00 + 2.50600E+02 0.00000E+00 + 2.50700E+02 0.00000E+00 + 2.50800E+02 0.00000E+00 + 2.50900E+02 0.00000E+00 + 2.51000E+02 0.00000E+00 + 2.51100E+02 0.00000E+00 + 2.51200E+02 0.00000E+00 + 2.51300E+02 0.00000E+00 + 2.51400E+02 0.00000E+00 + 2.51500E+02 0.00000E+00 + 2.51600E+02 0.00000E+00 + 2.51700E+02 0.00000E+00 + 2.51800E+02 0.00000E+00 + 2.51900E+02 0.00000E+00 + 2.52000E+02 0.00000E+00 + 2.52100E+02 2.83424E+05 + 2.52200E+02 5.66847E+05 + 2.52300E+02 8.50271E+05 + 2.52400E+02 1.13369E+06 + 2.52500E+02 1.41712E+06 + 2.52600E+02 1.70054E+06 + 2.52700E+02 1.98397E+06 + 2.52800E+02 2.26739E+06 + 2.52900E+02 2.55081E+06 + 2.53000E+02 2.83424E+06 + 2.53100E+02 3.11766E+06 + 2.53200E+02 3.40108E+06 + 2.53300E+02 3.68451E+06 + 2.53400E+02 3.96793E+06 + 2.53500E+02 4.25136E+06 + 2.53600E+02 4.53478E+06 + 2.53700E+02 4.81820E+06 + 2.53800E+02 5.10163E+06 + 2.53900E+02 5.38505E+06 + 2.54000E+02 5.66847E+06 + 2.54100E+02 5.95190E+06 + 2.54200E+02 6.23532E+06 + 2.54300E+02 6.51875E+06 + 2.54400E+02 6.80217E+06 + 2.54500E+02 7.08559E+06 + 2.54600E+02 7.36902E+06 + 2.54700E+02 7.65244E+06 + 2.54800E+02 7.93586E+06 + 2.54900E+02 8.21929E+06 + 2.55000E+02 8.50271E+06 + 2.55100E+02 8.50271E+06 + 2.55200E+02 7.55797E+06 + 2.55300E+02 6.61322E+06 + 2.55400E+02 5.66848E+06 + 2.55500E+02 4.72373E+06 + 2.55600E+02 3.77898E+06 + 2.55700E+02 2.83424E+06 + 2.55800E+02 1.88949E+06 + 2.55900E+02 9.44746E+05 + 2.56000E+02 0.00000E+00 + 2.56100E+02 0.00000E+00 + 2.56200E+02 0.00000E+00 + 2.56300E+02 0.00000E+00 + 2.56400E+02 0.00000E+00 + 2.56500E+02 0.00000E+00 + 2.56600E+02 0.00000E+00 + 2.56700E+02 0.00000E+00 + 2.56800E+02 0.00000E+00 + 2.56900E+02 0.00000E+00 + 2.57000E+02 0.00000E+00 + 2.57100E+02 0.00000E+00 + 2.57200E+02 0.00000E+00 + 2.57300E+02 0.00000E+00 + 2.57400E+02 0.00000E+00 + 2.57500E+02 0.00000E+00 + 2.57600E+02 0.00000E+00 + 2.57700E+02 0.00000E+00 + 2.57800E+02 0.00000E+00 + 2.57900E+02 0.00000E+00 + 2.58000E+02 0.00000E+00 + 2.58100E+02 2.83424E+05 + 2.58200E+02 5.66847E+05 + 2.58300E+02 8.50271E+05 + 2.58400E+02 1.13369E+06 + 2.58500E+02 1.41712E+06 + 2.58600E+02 1.70054E+06 + 2.58700E+02 1.98397E+06 + 2.58800E+02 2.26739E+06 + 2.58900E+02 2.55081E+06 + 2.59000E+02 2.83424E+06 + 2.59100E+02 3.11766E+06 + 2.59200E+02 3.40108E+06 + 2.59300E+02 3.68451E+06 + 2.59400E+02 3.96793E+06 + 2.59500E+02 4.25136E+06 + 2.59600E+02 4.53478E+06 + 2.59700E+02 4.81820E+06 + 2.59800E+02 5.10163E+06 + 2.59900E+02 5.38505E+06 + 2.60000E+02 5.66847E+06 + 2.60100E+02 5.95190E+06 + 2.60200E+02 6.23532E+06 + 2.60300E+02 6.51875E+06 + 2.60400E+02 6.80217E+06 + 2.60500E+02 7.08559E+06 + 2.60600E+02 7.36902E+06 + 2.60700E+02 7.65244E+06 + 2.60800E+02 7.93586E+06 + 2.60900E+02 8.21929E+06 + 2.61000E+02 8.50271E+06 + 2.61100E+02 8.50271E+06 + 2.61200E+02 7.55797E+06 + 2.61300E+02 6.61322E+06 + 2.61400E+02 5.66848E+06 + 2.61500E+02 4.72373E+06 + 2.61600E+02 3.77898E+06 + 2.61700E+02 2.83424E+06 + 2.61800E+02 1.88949E+06 + 2.61900E+02 9.44746E+05 + 2.62000E+02 0.00000E+00 + 2.62100E+02 0.00000E+00 + 2.62200E+02 0.00000E+00 + 2.62300E+02 0.00000E+00 + 2.62400E+02 0.00000E+00 + 2.62500E+02 0.00000E+00 + 2.62600E+02 0.00000E+00 + 2.62700E+02 0.00000E+00 + 2.62800E+02 0.00000E+00 + 2.62900E+02 0.00000E+00 + 2.63000E+02 0.00000E+00 + 2.63100E+02 0.00000E+00 + 2.63200E+02 0.00000E+00 + 2.63300E+02 0.00000E+00 + 2.63400E+02 0.00000E+00 + 2.63500E+02 0.00000E+00 + 2.63600E+02 0.00000E+00 + 2.63700E+02 0.00000E+00 + 2.63800E+02 0.00000E+00 + 2.63900E+02 0.00000E+00 + 2.64000E+02 0.00000E+00 + 2.64100E+02 2.83424E+05 + 2.64200E+02 5.66847E+05 + 2.64300E+02 8.50271E+05 + 2.64400E+02 1.13369E+06 + 2.64500E+02 1.41712E+06 + 2.64600E+02 1.70054E+06 + 2.64700E+02 1.98397E+06 + 2.64800E+02 2.26739E+06 + 2.64900E+02 2.55081E+06 + 2.65000E+02 2.83424E+06 + 2.65100E+02 3.11766E+06 + 2.65200E+02 3.40108E+06 + 2.65300E+02 3.68451E+06 + 2.65400E+02 3.96793E+06 + 2.65500E+02 4.25136E+06 + 2.65600E+02 4.53478E+06 + 2.65700E+02 4.81820E+06 + 2.65800E+02 5.10163E+06 + 2.65900E+02 5.38505E+06 + 2.66000E+02 5.66847E+06 + 2.66100E+02 5.95190E+06 + 2.66200E+02 6.23532E+06 + 2.66300E+02 6.51875E+06 + 2.66400E+02 6.80217E+06 + 2.66500E+02 7.08559E+06 + 2.66600E+02 7.36902E+06 + 2.66700E+02 7.65244E+06 + 2.66800E+02 7.93586E+06 + 2.66900E+02 8.21929E+06 + 2.67000E+02 8.50271E+06 + 2.67100E+02 8.50271E+06 + 2.67200E+02 7.55797E+06 + 2.67300E+02 6.61322E+06 + 2.67400E+02 5.66848E+06 + 2.67500E+02 4.72373E+06 + 2.67600E+02 3.77898E+06 + 2.67700E+02 2.83424E+06 + 2.67800E+02 1.88949E+06 + 2.67900E+02 9.44746E+05 + 2.68000E+02 0.00000E+00 + 2.68100E+02 0.00000E+00 + 2.68200E+02 0.00000E+00 + 2.68300E+02 0.00000E+00 + 2.68400E+02 0.00000E+00 + 2.68500E+02 0.00000E+00 + 2.68600E+02 0.00000E+00 + 2.68700E+02 0.00000E+00 + 2.68800E+02 0.00000E+00 + 2.68900E+02 0.00000E+00 + 2.69000E+02 0.00000E+00 + 2.69100E+02 0.00000E+00 + 2.69200E+02 0.00000E+00 + 2.69300E+02 0.00000E+00 + 2.69400E+02 0.00000E+00 + 2.69500E+02 0.00000E+00 + 2.69600E+02 0.00000E+00 + 2.69700E+02 0.00000E+00 + 2.69800E+02 0.00000E+00 + 2.69900E+02 0.00000E+00 + 2.70000E+02 0.00000E+00 + 2.70100E+02 2.83424E+05 + 2.70200E+02 5.66847E+05 + 2.70300E+02 8.50271E+05 + 2.70400E+02 1.13369E+06 + 2.70500E+02 1.41712E+06 + 2.70600E+02 1.70054E+06 + 2.70700E+02 1.98397E+06 + 2.70800E+02 2.26739E+06 + 2.70900E+02 2.55081E+06 + 2.71000E+02 2.83424E+06 + 2.71100E+02 3.11766E+06 + 2.71200E+02 3.40108E+06 + 2.71300E+02 3.68451E+06 + 2.71400E+02 3.96793E+06 + 2.71500E+02 4.25136E+06 + 2.71600E+02 4.53478E+06 + 2.71700E+02 4.81820E+06 + 2.71800E+02 5.10163E+06 + 2.71900E+02 5.38505E+06 + 2.72000E+02 5.66847E+06 + 2.72100E+02 5.95190E+06 + 2.72200E+02 6.23532E+06 + 2.72300E+02 6.51875E+06 + 2.72400E+02 6.80217E+06 + 2.72500E+02 7.08559E+06 + 2.72600E+02 7.36902E+06 + 2.72700E+02 7.65244E+06 + 2.72800E+02 7.93586E+06 + 2.72900E+02 8.21929E+06 + 2.73000E+02 8.50271E+06 + 2.73100E+02 8.50271E+06 + 2.73200E+02 7.55797E+06 + 2.73300E+02 6.61322E+06 + 2.73400E+02 5.66848E+06 + 2.73500E+02 4.72373E+06 + 2.73600E+02 3.77898E+06 + 2.73700E+02 2.83424E+06 + 2.73800E+02 1.88949E+06 + 2.73900E+02 9.44746E+05 + 2.74000E+02 0.00000E+00 + 2.74100E+02 0.00000E+00 + 2.74200E+02 0.00000E+00 + 2.74300E+02 0.00000E+00 + 2.74400E+02 0.00000E+00 + 2.74500E+02 0.00000E+00 + 2.74600E+02 0.00000E+00 + 2.74700E+02 0.00000E+00 + 2.74800E+02 0.00000E+00 + 2.74900E+02 0.00000E+00 + 2.75000E+02 0.00000E+00 + 2.75100E+02 0.00000E+00 + 2.75200E+02 0.00000E+00 + 2.75300E+02 0.00000E+00 + 2.75400E+02 0.00000E+00 + 2.75500E+02 0.00000E+00 + 2.75600E+02 0.00000E+00 + 2.75700E+02 0.00000E+00 + 2.75800E+02 0.00000E+00 + 2.75900E+02 0.00000E+00 + 2.76000E+02 0.00000E+00 + 2.76100E+02 2.83424E+05 + 2.76200E+02 5.66847E+05 + 2.76300E+02 8.50271E+05 + 2.76400E+02 1.13369E+06 + 2.76500E+02 1.41712E+06 + 2.76600E+02 1.70054E+06 + 2.76700E+02 1.98397E+06 + 2.76800E+02 2.26739E+06 + 2.76900E+02 2.55081E+06 + 2.77000E+02 2.83424E+06 + 2.77100E+02 3.11766E+06 + 2.77200E+02 3.40108E+06 + 2.77300E+02 3.68451E+06 + 2.77400E+02 3.96793E+06 + 2.77500E+02 4.25136E+06 + 2.77600E+02 4.53478E+06 + 2.77700E+02 4.81820E+06 + 2.77800E+02 5.10163E+06 + 2.77900E+02 5.38505E+06 + 2.78000E+02 5.66847E+06 + 2.78100E+02 5.95190E+06 + 2.78200E+02 6.23532E+06 + 2.78300E+02 6.51875E+06 + 2.78400E+02 6.80217E+06 + 2.78500E+02 7.08559E+06 + 2.78600E+02 7.36902E+06 + 2.78700E+02 7.65244E+06 + 2.78800E+02 7.93586E+06 + 2.78900E+02 8.21929E+06 + 2.79000E+02 8.50271E+06 + 2.79100E+02 8.50271E+06 + 2.79200E+02 7.55797E+06 + 2.79300E+02 6.61322E+06 + 2.79400E+02 5.66848E+06 + 2.79500E+02 4.72373E+06 + 2.79600E+02 3.77898E+06 + 2.79700E+02 2.83424E+06 + 2.79800E+02 1.88949E+06 + 2.79900E+02 9.44746E+05 + 2.80000E+02 0.00000E+00 + 2.80100E+02 0.00000E+00 + 2.80200E+02 0.00000E+00 + 2.80300E+02 0.00000E+00 + 2.80400E+02 0.00000E+00 + 2.80500E+02 0.00000E+00 + 2.80600E+02 0.00000E+00 + 2.80700E+02 0.00000E+00 + 2.80800E+02 0.00000E+00 + 2.80900E+02 0.00000E+00 + 2.81000E+02 0.00000E+00 + 2.81100E+02 0.00000E+00 + 2.81200E+02 0.00000E+00 + 2.81300E+02 0.00000E+00 + 2.81400E+02 0.00000E+00 + 2.81500E+02 0.00000E+00 + 2.81600E+02 0.00000E+00 + 2.81700E+02 0.00000E+00 + 2.81800E+02 0.00000E+00 + 2.81900E+02 0.00000E+00 + 2.82000E+02 0.00000E+00 + 2.82100E+02 2.83424E+05 + 2.82200E+02 5.66847E+05 + 2.82300E+02 8.50271E+05 + 2.82400E+02 1.13369E+06 + 2.82500E+02 1.41712E+06 + 2.82600E+02 1.70054E+06 + 2.82700E+02 1.98397E+06 + 2.82800E+02 2.26739E+06 + 2.82900E+02 2.55081E+06 + 2.83000E+02 2.83424E+06 + 2.83100E+02 3.11766E+06 + 2.83200E+02 3.40108E+06 + 2.83300E+02 3.68451E+06 + 2.83400E+02 3.96793E+06 + 2.83500E+02 4.25136E+06 + 2.83600E+02 4.53478E+06 + 2.83700E+02 4.81820E+06 + 2.83800E+02 5.10163E+06 + 2.83900E+02 5.38505E+06 + 2.84000E+02 5.66847E+06 + 2.84100E+02 5.95190E+06 + 2.84200E+02 6.23532E+06 + 2.84300E+02 6.51875E+06 + 2.84400E+02 6.80217E+06 + 2.84500E+02 7.08559E+06 + 2.84600E+02 7.36902E+06 + 2.84700E+02 7.65244E+06 + 2.84800E+02 7.93586E+06 + 2.84900E+02 8.21929E+06 + 2.85000E+02 8.50271E+06 + 2.85100E+02 8.50271E+06 + 2.85200E+02 7.55797E+06 + 2.85300E+02 6.61322E+06 + 2.85400E+02 5.66848E+06 + 2.85500E+02 4.72373E+06 + 2.85600E+02 3.77898E+06 + 2.85700E+02 2.83424E+06 + 2.85800E+02 1.88949E+06 + 2.85900E+02 9.44746E+05 + 2.86000E+02 0.00000E+00 + 2.86100E+02 0.00000E+00 + 2.86200E+02 0.00000E+00 + 2.86300E+02 0.00000E+00 + 2.86400E+02 0.00000E+00 + 2.86500E+02 0.00000E+00 + 2.86600E+02 0.00000E+00 + 2.86700E+02 0.00000E+00 + 2.86800E+02 0.00000E+00 + 2.86900E+02 0.00000E+00 + 2.87000E+02 0.00000E+00 + 2.87100E+02 0.00000E+00 + 2.87200E+02 0.00000E+00 + 2.87300E+02 0.00000E+00 + 2.87400E+02 0.00000E+00 + 2.87500E+02 0.00000E+00 + 2.87600E+02 0.00000E+00 + 2.87700E+02 0.00000E+00 + 2.87800E+02 0.00000E+00 + 2.87900E+02 0.00000E+00 + 2.88000E+02 0.00000E+00 + 2.88100E+02 2.83424E+05 + 2.88200E+02 5.66847E+05 + 2.88300E+02 8.50271E+05 + 2.88400E+02 1.13369E+06 + 2.88500E+02 1.41712E+06 + 2.88600E+02 1.70054E+06 + 2.88700E+02 1.98397E+06 + 2.88800E+02 2.26739E+06 + 2.88900E+02 2.55081E+06 + 2.89000E+02 2.83424E+06 + 2.89100E+02 3.11766E+06 + 2.89200E+02 3.40108E+06 + 2.89300E+02 3.68451E+06 + 2.89400E+02 3.96793E+06 + 2.89500E+02 4.25136E+06 + 2.89600E+02 4.53478E+06 + 2.89700E+02 4.81820E+06 + 2.89800E+02 5.10163E+06 + 2.89900E+02 5.38505E+06 + 2.90000E+02 5.66847E+06 + 2.90100E+02 5.95190E+06 + 2.90200E+02 6.23532E+06 + 2.90300E+02 6.51875E+06 + 2.90400E+02 6.80217E+06 + 2.90500E+02 7.08559E+06 + 2.90600E+02 7.36902E+06 + 2.90700E+02 7.65244E+06 + 2.90800E+02 7.93586E+06 + 2.90900E+02 8.21929E+06 + 2.91000E+02 8.50271E+06 + 2.91100E+02 8.50271E+06 + 2.91200E+02 7.55797E+06 + 2.91300E+02 6.61322E+06 + 2.91400E+02 5.66848E+06 + 2.91500E+02 4.72373E+06 + 2.91600E+02 3.77898E+06 + 2.91700E+02 2.83424E+06 + 2.91800E+02 1.88949E+06 + 2.91900E+02 9.44746E+05 + 2.92000E+02 0.00000E+00 + 2.92100E+02 0.00000E+00 + 2.92200E+02 0.00000E+00 + 2.92300E+02 0.00000E+00 + 2.92400E+02 0.00000E+00 + 2.92500E+02 0.00000E+00 + 2.92600E+02 0.00000E+00 + 2.92700E+02 0.00000E+00 + 2.92800E+02 0.00000E+00 + 2.92900E+02 0.00000E+00 + 2.93000E+02 0.00000E+00 + 2.93100E+02 0.00000E+00 + 2.93200E+02 0.00000E+00 + 2.93300E+02 0.00000E+00 + 2.93400E+02 0.00000E+00 + 2.93500E+02 0.00000E+00 + 2.93600E+02 0.00000E+00 + 2.93700E+02 0.00000E+00 + 2.93800E+02 0.00000E+00 + 2.93900E+02 0.00000E+00 + 2.94000E+02 0.00000E+00 + 2.94100E+02 2.83424E+05 + 2.94200E+02 5.66847E+05 + 2.94300E+02 8.50271E+05 + 2.94400E+02 1.13369E+06 + 2.94500E+02 1.41712E+06 + 2.94600E+02 1.70054E+06 + 2.94700E+02 1.98397E+06 + 2.94800E+02 2.26739E+06 + 2.94900E+02 2.55081E+06 + 2.95000E+02 2.83424E+06 + 2.95100E+02 3.11766E+06 + 2.95200E+02 3.40108E+06 + 2.95300E+02 3.68451E+06 + 2.95400E+02 3.96793E+06 + 2.95500E+02 4.25136E+06 + 2.95600E+02 4.53478E+06 + 2.95700E+02 4.81820E+06 + 2.95800E+02 5.10163E+06 + 2.95900E+02 5.38505E+06 + 2.96000E+02 5.66847E+06 + 2.96100E+02 5.95190E+06 + 2.96200E+02 6.23532E+06 + 2.96300E+02 6.51875E+06 + 2.96400E+02 6.80217E+06 + 2.96500E+02 7.08559E+06 + 2.96600E+02 7.36902E+06 + 2.96700E+02 7.65244E+06 + 2.96800E+02 7.93586E+06 + 2.96900E+02 8.21929E+06 + 2.97000E+02 8.50271E+06 + 2.97100E+02 8.50271E+06 + 2.97200E+02 7.55797E+06 + 2.97300E+02 6.61322E+06 + 2.97400E+02 5.66848E+06 + 2.97500E+02 4.72373E+06 + 2.97600E+02 3.77898E+06 + 2.97700E+02 2.83424E+06 + 2.97800E+02 1.88949E+06 + 2.97900E+02 9.44746E+05 + 2.98000E+02 0.00000E+00 + 2.98100E+02 0.00000E+00 + 2.98200E+02 0.00000E+00 + 2.98300E+02 0.00000E+00 + 2.98400E+02 0.00000E+00 + 2.98500E+02 0.00000E+00 + 2.98600E+02 0.00000E+00 + 2.98700E+02 0.00000E+00 + 2.98800E+02 0.00000E+00 + 2.98900E+02 0.00000E+00 + 2.99000E+02 0.00000E+00 + 2.99100E+02 0.00000E+00 + 2.99200E+02 0.00000E+00 + 2.99300E+02 0.00000E+00 + 2.99400E+02 0.00000E+00 + 2.99500E+02 0.00000E+00 + 2.99600E+02 0.00000E+00 + 2.99700E+02 0.00000E+00 + 2.99800E+02 0.00000E+00 + 2.99900E+02 0.00000E+00 + 3.00000E+02 0.00000E+00 + 3.00100E+02 2.83424E+05 + 3.00200E+02 5.66847E+05 + 3.00300E+02 8.50271E+05 + 3.00400E+02 1.13369E+06 + 3.00500E+02 1.41712E+06 + 3.00600E+02 1.70054E+06 + 3.00700E+02 1.98397E+06 + 3.00800E+02 2.26739E+06 + 3.00900E+02 2.55081E+06 + 3.01000E+02 2.83424E+06 + 3.01100E+02 3.11766E+06 + 3.01200E+02 3.40108E+06 + 3.01300E+02 3.68451E+06 + 3.01400E+02 3.96793E+06 + 3.01500E+02 4.25136E+06 + 3.01600E+02 4.53478E+06 + 3.01700E+02 4.81820E+06 + 3.01800E+02 5.10163E+06 + 3.01900E+02 5.38505E+06 + 3.02000E+02 5.66847E+06 + 3.02100E+02 5.95190E+06 + 3.02200E+02 6.23532E+06 + 3.02300E+02 6.51875E+06 + 3.02400E+02 6.80217E+06 + 3.02500E+02 7.08559E+06 + 3.02600E+02 7.36902E+06 + 3.02700E+02 7.65244E+06 + 3.02800E+02 7.93586E+06 + 3.02900E+02 8.21929E+06 + 3.03000E+02 8.50271E+06 + 3.03100E+02 8.50271E+06 + 3.03200E+02 7.55797E+06 + 3.03300E+02 6.61322E+06 + 3.03400E+02 5.66848E+06 + 3.03500E+02 4.72373E+06 + 3.03600E+02 3.77898E+06 + 3.03700E+02 2.83424E+06 + 3.03800E+02 1.88949E+06 + 3.03900E+02 9.44746E+05 + 3.04000E+02 0.00000E+00 + 3.04100E+02 0.00000E+00 + 3.04200E+02 0.00000E+00 + 3.04300E+02 0.00000E+00 + 3.04400E+02 0.00000E+00 + 3.04500E+02 0.00000E+00 + 3.04600E+02 0.00000E+00 + 3.04700E+02 0.00000E+00 + 3.04800E+02 0.00000E+00 + 3.04900E+02 0.00000E+00 + 3.05000E+02 0.00000E+00 + 3.05100E+02 0.00000E+00 + 3.05200E+02 0.00000E+00 + 3.05300E+02 0.00000E+00 + 3.05400E+02 0.00000E+00 + 3.05500E+02 0.00000E+00 + 3.05600E+02 0.00000E+00 + 3.05700E+02 0.00000E+00 + 3.05800E+02 0.00000E+00 + 3.05900E+02 0.00000E+00 + 3.06000E+02 0.00000E+00 + 3.06100E+02 2.83424E+05 + 3.06200E+02 5.66847E+05 + 3.06300E+02 8.50271E+05 + 3.06400E+02 1.13369E+06 + 3.06500E+02 1.41712E+06 + 3.06600E+02 1.70054E+06 + 3.06700E+02 1.98397E+06 + 3.06800E+02 2.26739E+06 + 3.06900E+02 2.55081E+06 + 3.07000E+02 2.83424E+06 + 3.07100E+02 3.11766E+06 + 3.07200E+02 3.40108E+06 + 3.07300E+02 3.68451E+06 + 3.07400E+02 3.96793E+06 + 3.07500E+02 4.25136E+06 + 3.07600E+02 4.53478E+06 + 3.07700E+02 4.81820E+06 + 3.07800E+02 5.10163E+06 + 3.07900E+02 5.38505E+06 + 3.08000E+02 5.66847E+06 + 3.08100E+02 5.95190E+06 + 3.08200E+02 6.23532E+06 + 3.08300E+02 6.51875E+06 + 3.08400E+02 6.80217E+06 + 3.08500E+02 7.08559E+06 + 3.08600E+02 7.36902E+06 + 3.08700E+02 7.65244E+06 + 3.08800E+02 7.93586E+06 + 3.08900E+02 8.21929E+06 + 3.09000E+02 8.50271E+06 + 3.09100E+02 8.50271E+06 + 3.09200E+02 7.55797E+06 + 3.09300E+02 6.61322E+06 + 3.09400E+02 5.66848E+06 + 3.09500E+02 4.72373E+06 + 3.09600E+02 3.77898E+06 + 3.09700E+02 2.83424E+06 + 3.09800E+02 1.88949E+06 + 3.09900E+02 9.44746E+05 + 3.10000E+02 0.00000E+00 + 3.10100E+02 0.00000E+00 + 3.10200E+02 0.00000E+00 + 3.10300E+02 0.00000E+00 + 3.10400E+02 0.00000E+00 + 3.10500E+02 0.00000E+00 + 3.10600E+02 0.00000E+00 + 3.10700E+02 0.00000E+00 + 3.10800E+02 0.00000E+00 + 3.10900E+02 0.00000E+00 + 3.11000E+02 0.00000E+00 + 3.11100E+02 0.00000E+00 + 3.11200E+02 0.00000E+00 + 3.11300E+02 0.00000E+00 + 3.11400E+02 0.00000E+00 + 3.11500E+02 0.00000E+00 + 3.11600E+02 0.00000E+00 + 3.11700E+02 0.00000E+00 + 3.11800E+02 0.00000E+00 + 3.11900E+02 0.00000E+00 + 3.12000E+02 0.00000E+00 + 3.12100E+02 2.83424E+05 + 3.12200E+02 5.66847E+05 + 3.12300E+02 8.50271E+05 + 3.12400E+02 1.13369E+06 + 3.12500E+02 1.41712E+06 + 3.12600E+02 1.70054E+06 + 3.12700E+02 1.98397E+06 + 3.12800E+02 2.26739E+06 + 3.12900E+02 2.55081E+06 + 3.13000E+02 2.83424E+06 + 3.13100E+02 3.11766E+06 + 3.13200E+02 3.40108E+06 + 3.13300E+02 3.68451E+06 + 3.13400E+02 3.96793E+06 + 3.13500E+02 4.25136E+06 + 3.13600E+02 4.53478E+06 + 3.13700E+02 4.81820E+06 + 3.13800E+02 5.10163E+06 + 3.13900E+02 5.38505E+06 + 3.14000E+02 5.66847E+06 + 3.14100E+02 5.95190E+06 + 3.14200E+02 6.23532E+06 + 3.14300E+02 6.51875E+06 + 3.14400E+02 6.80217E+06 + 3.14500E+02 7.08559E+06 + 3.14600E+02 7.36902E+06 + 3.14700E+02 7.65244E+06 + 3.14800E+02 7.93586E+06 + 3.14900E+02 8.21929E+06 + 3.15000E+02 8.50271E+06 + 3.15100E+02 8.50271E+06 + 3.15200E+02 7.55797E+06 + 3.15300E+02 6.61322E+06 + 3.15400E+02 5.66848E+06 + 3.15500E+02 4.72373E+06 + 3.15600E+02 3.77898E+06 + 3.15700E+02 2.83424E+06 + 3.15800E+02 1.88949E+06 + 3.15900E+02 9.44746E+05 + 3.16000E+02 0.00000E+00 + 3.16100E+02 0.00000E+00 + 3.16200E+02 0.00000E+00 + 3.16300E+02 0.00000E+00 + 3.16400E+02 0.00000E+00 + 3.16500E+02 0.00000E+00 + 3.16600E+02 0.00000E+00 + 3.16700E+02 0.00000E+00 + 3.16800E+02 0.00000E+00 + 3.16900E+02 0.00000E+00 + 3.17000E+02 0.00000E+00 + 3.17100E+02 0.00000E+00 + 3.17200E+02 0.00000E+00 + 3.17300E+02 0.00000E+00 + 3.17400E+02 0.00000E+00 + 3.17500E+02 0.00000E+00 + 3.17600E+02 0.00000E+00 + 3.17700E+02 0.00000E+00 + 3.17800E+02 0.00000E+00 + 3.17900E+02 0.00000E+00 + 3.18000E+02 0.00000E+00 + 3.18100E+02 2.83424E+05 + 3.18200E+02 5.66847E+05 + 3.18300E+02 8.50271E+05 + 3.18400E+02 1.13369E+06 + 3.18500E+02 1.41712E+06 + 3.18600E+02 1.70054E+06 + 3.18700E+02 1.98397E+06 + 3.18800E+02 2.26739E+06 + 3.18900E+02 2.55081E+06 + 3.19000E+02 2.83424E+06 + 3.19100E+02 3.11766E+06 + 3.19200E+02 3.40108E+06 + 3.19300E+02 3.68451E+06 + 3.19400E+02 3.96793E+06 + 3.19500E+02 4.25136E+06 + 3.19600E+02 4.53478E+06 + 3.19700E+02 4.81820E+06 + 3.19800E+02 5.10163E+06 + 3.19900E+02 5.38505E+06 + 3.20000E+02 5.66847E+06 + 3.20100E+02 5.95190E+06 + 3.20200E+02 6.23532E+06 + 3.20300E+02 6.51875E+06 + 3.20400E+02 6.80217E+06 + 3.20500E+02 7.08559E+06 + 3.20600E+02 7.36902E+06 + 3.20700E+02 7.65244E+06 + 3.20800E+02 7.93586E+06 + 3.20900E+02 8.21929E+06 + 3.21000E+02 8.50271E+06 + 3.21100E+02 8.50271E+06 + 3.21200E+02 7.55797E+06 + 3.21300E+02 6.61322E+06 + 3.21400E+02 5.66848E+06 + 3.21500E+02 4.72373E+06 + 3.21600E+02 3.77898E+06 + 3.21700E+02 2.83424E+06 + 3.21800E+02 1.88949E+06 + 3.21900E+02 9.44746E+05 + 3.22000E+02 0.00000E+00 + 3.22100E+02 0.00000E+00 + 3.22200E+02 0.00000E+00 + 3.22300E+02 0.00000E+00 + 3.22400E+02 0.00000E+00 + 3.22500E+02 0.00000E+00 + 3.22600E+02 0.00000E+00 + 3.22700E+02 0.00000E+00 + 3.22800E+02 0.00000E+00 + 3.22900E+02 0.00000E+00 + 3.23000E+02 0.00000E+00 + 3.23100E+02 0.00000E+00 + 3.23200E+02 0.00000E+00 + 3.23300E+02 0.00000E+00 + 3.23400E+02 0.00000E+00 + 3.23500E+02 0.00000E+00 + 3.23600E+02 0.00000E+00 + 3.23700E+02 0.00000E+00 + 3.23800E+02 0.00000E+00 + 3.23900E+02 0.00000E+00 + 3.24000E+02 0.00000E+00 + 3.24100E+02 2.83424E+05 + 3.24200E+02 5.66847E+05 + 3.24300E+02 8.50271E+05 + 3.24400E+02 1.13369E+06 + 3.24500E+02 1.41712E+06 + 3.24600E+02 1.70054E+06 + 3.24700E+02 1.98397E+06 + 3.24800E+02 2.26739E+06 + 3.24900E+02 2.55081E+06 + 3.25000E+02 2.83424E+06 + 3.25100E+02 3.11766E+06 + 3.25200E+02 3.40108E+06 + 3.25300E+02 3.68451E+06 + 3.25400E+02 3.96793E+06 + 3.25500E+02 4.25136E+06 + 3.25600E+02 4.53478E+06 + 3.25700E+02 4.81820E+06 + 3.25800E+02 5.10163E+06 + 3.25900E+02 5.38505E+06 + 3.26000E+02 5.66847E+06 + 3.26100E+02 5.95190E+06 + 3.26200E+02 6.23532E+06 + 3.26300E+02 6.51875E+06 + 3.26400E+02 6.80217E+06 + 3.26500E+02 7.08559E+06 + 3.26600E+02 7.36902E+06 + 3.26700E+02 7.65244E+06 + 3.26800E+02 7.93586E+06 + 3.26900E+02 8.21929E+06 + 3.27000E+02 8.50271E+06 + 3.27100E+02 8.50271E+06 + 3.27200E+02 7.55797E+06 + 3.27300E+02 6.61322E+06 + 3.27400E+02 5.66848E+06 + 3.27500E+02 4.72373E+06 + 3.27600E+02 3.77898E+06 + 3.27700E+02 2.83424E+06 + 3.27800E+02 1.88949E+06 + 3.27900E+02 9.44746E+05 + 3.28000E+02 0.00000E+00 + 3.28100E+02 0.00000E+00 + 3.28200E+02 0.00000E+00 + 3.28300E+02 0.00000E+00 + 3.28400E+02 0.00000E+00 + 3.28500E+02 0.00000E+00 + 3.28600E+02 0.00000E+00 + 3.28700E+02 0.00000E+00 + 3.28800E+02 0.00000E+00 + 3.28900E+02 0.00000E+00 + 3.29000E+02 0.00000E+00 + 3.29100E+02 0.00000E+00 + 3.29200E+02 0.00000E+00 + 3.29300E+02 0.00000E+00 + 3.29400E+02 0.00000E+00 + 3.29500E+02 0.00000E+00 + 3.29600E+02 0.00000E+00 + 3.29700E+02 0.00000E+00 + 3.29800E+02 0.00000E+00 + 3.29900E+02 0.00000E+00 + 3.30000E+02 0.00000E+00 + 3.30100E+02 2.83424E+05 + 3.30200E+02 5.66847E+05 + 3.30300E+02 8.50271E+05 + 3.30400E+02 1.13369E+06 + 3.30500E+02 1.41712E+06 + 3.30600E+02 1.70054E+06 + 3.30700E+02 1.98397E+06 + 3.30800E+02 2.26739E+06 + 3.30900E+02 2.55081E+06 + 3.31000E+02 2.83424E+06 + 3.31100E+02 3.11766E+06 + 3.31200E+02 3.40108E+06 + 3.31300E+02 3.68451E+06 + 3.31400E+02 3.96793E+06 + 3.31500E+02 4.25136E+06 + 3.31600E+02 4.53478E+06 + 3.31700E+02 4.81820E+06 + 3.31800E+02 5.10163E+06 + 3.31900E+02 5.38505E+06 + 3.32000E+02 5.66847E+06 + 3.32100E+02 5.95190E+06 + 3.32200E+02 6.23532E+06 + 3.32300E+02 6.51875E+06 + 3.32400E+02 6.80217E+06 + 3.32500E+02 7.08559E+06 + 3.32600E+02 7.36902E+06 + 3.32700E+02 7.65244E+06 + 3.32800E+02 7.93586E+06 + 3.32900E+02 8.21929E+06 + 3.33000E+02 8.50271E+06 + 3.33100E+02 8.50271E+06 + 3.33200E+02 7.55797E+06 + 3.33300E+02 6.61322E+06 + 3.33400E+02 5.66848E+06 + 3.33500E+02 4.72373E+06 + 3.33600E+02 3.77898E+06 + 3.33700E+02 2.83424E+06 + 3.33800E+02 1.88949E+06 + 3.33900E+02 9.44746E+05 + 3.34000E+02 0.00000E+00 + 3.34100E+02 0.00000E+00 + 3.34200E+02 0.00000E+00 + 3.34300E+02 0.00000E+00 + 3.34400E+02 0.00000E+00 + 3.34500E+02 0.00000E+00 + 3.34600E+02 0.00000E+00 + 3.34700E+02 0.00000E+00 + 3.34800E+02 0.00000E+00 + 3.34900E+02 0.00000E+00 + 3.35000E+02 0.00000E+00 + 3.35100E+02 0.00000E+00 + 3.35200E+02 0.00000E+00 + 3.35300E+02 0.00000E+00 + 3.35400E+02 0.00000E+00 + 3.35500E+02 0.00000E+00 + 3.35600E+02 0.00000E+00 + 3.35700E+02 0.00000E+00 + 3.35800E+02 0.00000E+00 + 3.35900E+02 0.00000E+00 + 3.36000E+02 0.00000E+00 + 3.36100E+02 2.83424E+05 + 3.36200E+02 5.66847E+05 + 3.36300E+02 8.50271E+05 + 3.36400E+02 1.13369E+06 + 3.36500E+02 1.41712E+06 + 3.36600E+02 1.70054E+06 + 3.36700E+02 1.98397E+06 + 3.36800E+02 2.26739E+06 + 3.36900E+02 2.55081E+06 + 3.37000E+02 2.83424E+06 + 3.37100E+02 3.11766E+06 + 3.37200E+02 3.40108E+06 + 3.37300E+02 3.68451E+06 + 3.37400E+02 3.96793E+06 + 3.37500E+02 4.25136E+06 + 3.37600E+02 4.53478E+06 + 3.37700E+02 4.81820E+06 + 3.37800E+02 5.10163E+06 + 3.37900E+02 5.38505E+06 + 3.38000E+02 5.66847E+06 + 3.38100E+02 5.95190E+06 + 3.38200E+02 6.23532E+06 + 3.38300E+02 6.51875E+06 + 3.38400E+02 6.80217E+06 + 3.38500E+02 7.08559E+06 + 3.38600E+02 7.36902E+06 + 3.38700E+02 7.65244E+06 + 3.38800E+02 7.93586E+06 + 3.38900E+02 8.21929E+06 + 3.39000E+02 8.50271E+06 + 3.39100E+02 8.50271E+06 + 3.39200E+02 7.55797E+06 + 3.39300E+02 6.61322E+06 + 3.39400E+02 5.66848E+06 + 3.39500E+02 4.72373E+06 + 3.39600E+02 3.77898E+06 + 3.39700E+02 2.83424E+06 + 3.39800E+02 1.88949E+06 + 3.39900E+02 9.44746E+05 + 3.40000E+02 0.00000E+00 + 3.40100E+02 0.00000E+00 + 3.40200E+02 0.00000E+00 + 3.40300E+02 0.00000E+00 + 3.40400E+02 0.00000E+00 + 3.40500E+02 0.00000E+00 + 3.40600E+02 0.00000E+00 + 3.40700E+02 0.00000E+00 + 3.40800E+02 0.00000E+00 + 3.40900E+02 0.00000E+00 + 3.41000E+02 0.00000E+00 + 3.41100E+02 0.00000E+00 + 3.41200E+02 0.00000E+00 + 3.41300E+02 0.00000E+00 + 3.41400E+02 0.00000E+00 + 3.41500E+02 0.00000E+00 + 3.41600E+02 0.00000E+00 + 3.41700E+02 0.00000E+00 + 3.41800E+02 0.00000E+00 + 3.41900E+02 0.00000E+00 + 3.42000E+02 0.00000E+00 + 3.42100E+02 2.83424E+05 + 3.42200E+02 5.66847E+05 + 3.42300E+02 8.50271E+05 + 3.42400E+02 1.13369E+06 + 3.42500E+02 1.41712E+06 + 3.42600E+02 1.70054E+06 + 3.42700E+02 1.98397E+06 + 3.42800E+02 2.26739E+06 + 3.42900E+02 2.55081E+06 + 3.43000E+02 2.83424E+06 + 3.43100E+02 3.11766E+06 + 3.43200E+02 3.40108E+06 + 3.43300E+02 3.68451E+06 + 3.43400E+02 3.96793E+06 + 3.43500E+02 4.25136E+06 + 3.43600E+02 4.53478E+06 + 3.43700E+02 4.81820E+06 + 3.43800E+02 5.10163E+06 + 3.43900E+02 5.38505E+06 + 3.44000E+02 5.66847E+06 + 3.44100E+02 5.95190E+06 + 3.44200E+02 6.23532E+06 + 3.44300E+02 6.51875E+06 + 3.44400E+02 6.80217E+06 + 3.44500E+02 7.08559E+06 + 3.44600E+02 7.36902E+06 + 3.44700E+02 7.65244E+06 + 3.44800E+02 7.93586E+06 + 3.44900E+02 8.21929E+06 + 3.45000E+02 8.50271E+06 + 3.45100E+02 8.50271E+06 + 3.45200E+02 7.55797E+06 + 3.45300E+02 6.61322E+06 + 3.45400E+02 5.66848E+06 + 3.45500E+02 4.72373E+06 + 3.45600E+02 3.77898E+06 + 3.45700E+02 2.83424E+06 + 3.45800E+02 1.88949E+06 + 3.45900E+02 9.44746E+05 + 3.46000E+02 0.00000E+00 + 3.46100E+02 0.00000E+00 + 3.46200E+02 0.00000E+00 + 3.46300E+02 0.00000E+00 + 3.46400E+02 0.00000E+00 + 3.46500E+02 0.00000E+00 + 3.46600E+02 0.00000E+00 + 3.46700E+02 0.00000E+00 + 3.46800E+02 0.00000E+00 + 3.46900E+02 0.00000E+00 + 3.47000E+02 0.00000E+00 + 3.47100E+02 0.00000E+00 + 3.47200E+02 0.00000E+00 + 3.47300E+02 0.00000E+00 + 3.47400E+02 0.00000E+00 + 3.47500E+02 0.00000E+00 + 3.47600E+02 0.00000E+00 + 3.47700E+02 0.00000E+00 + 3.47800E+02 0.00000E+00 + 3.47900E+02 0.00000E+00 + 3.48000E+02 0.00000E+00 + 3.48100E+02 2.83424E+05 + 3.48200E+02 5.66847E+05 + 3.48300E+02 8.50271E+05 + 3.48400E+02 1.13369E+06 + 3.48500E+02 1.41712E+06 + 3.48600E+02 1.70054E+06 + 3.48700E+02 1.98397E+06 + 3.48800E+02 2.26739E+06 + 3.48900E+02 2.55081E+06 + 3.49000E+02 2.83424E+06 + 3.49100E+02 3.11766E+06 + 3.49200E+02 3.40108E+06 + 3.49300E+02 3.68451E+06 + 3.49400E+02 3.96793E+06 + 3.49500E+02 4.25136E+06 + 3.49600E+02 4.53478E+06 + 3.49700E+02 4.81820E+06 + 3.49800E+02 5.10163E+06 + 3.49900E+02 5.38505E+06 + 3.50000E+02 5.66847E+06 + 3.50100E+02 5.95190E+06 + 3.50200E+02 6.23532E+06 + 3.50300E+02 6.51875E+06 + 3.50400E+02 6.80217E+06 + 3.50500E+02 7.08559E+06 + 3.50600E+02 7.36902E+06 + 3.50700E+02 7.65244E+06 + 3.50800E+02 7.93586E+06 + 3.50900E+02 8.21929E+06 + 3.51000E+02 8.50271E+06 + 3.51100E+02 8.50271E+06 + 3.51200E+02 7.55797E+06 + 3.51300E+02 6.61322E+06 + 3.51400E+02 5.66848E+06 + 3.51500E+02 4.72373E+06 + 3.51600E+02 3.77898E+06 + 3.51700E+02 2.83424E+06 + 3.51800E+02 1.88949E+06 + 3.51900E+02 9.44746E+05 + 3.52000E+02 0.00000E+00 + 3.52100E+02 0.00000E+00 + 3.52200E+02 0.00000E+00 + 3.52300E+02 0.00000E+00 + 3.52400E+02 0.00000E+00 + 3.52500E+02 0.00000E+00 + 3.52600E+02 0.00000E+00 + 3.52700E+02 0.00000E+00 + 3.52800E+02 0.00000E+00 + 3.52900E+02 0.00000E+00 + 3.53000E+02 0.00000E+00 + 3.53100E+02 0.00000E+00 + 3.53200E+02 0.00000E+00 + 3.53300E+02 0.00000E+00 + 3.53400E+02 0.00000E+00 + 3.53500E+02 0.00000E+00 + 3.53600E+02 0.00000E+00 + 3.53700E+02 0.00000E+00 + 3.53800E+02 0.00000E+00 + 3.53900E+02 0.00000E+00 + 3.54000E+02 0.00000E+00 + 3.54100E+02 2.83424E+05 + 3.54200E+02 5.66847E+05 + 3.54300E+02 8.50271E+05 + 3.54400E+02 1.13369E+06 + 3.54500E+02 1.41712E+06 + 3.54600E+02 1.70054E+06 + 3.54700E+02 1.98397E+06 + 3.54800E+02 2.26739E+06 + 3.54900E+02 2.55081E+06 + 3.55000E+02 2.83424E+06 + 3.55100E+02 3.11766E+06 + 3.55200E+02 3.40108E+06 + 3.55300E+02 3.68451E+06 + 3.55400E+02 3.96793E+06 + 3.55500E+02 4.25136E+06 + 3.55600E+02 4.53478E+06 + 3.55700E+02 4.81820E+06 + 3.55800E+02 5.10163E+06 + 3.55900E+02 5.38505E+06 + 3.56000E+02 5.66847E+06 + 3.56100E+02 5.95190E+06 + 3.56200E+02 6.23532E+06 + 3.56300E+02 6.51875E+06 + 3.56400E+02 6.80217E+06 + 3.56500E+02 7.08559E+06 + 3.56600E+02 7.36902E+06 + 3.56700E+02 7.65244E+06 + 3.56800E+02 7.93586E+06 + 3.56900E+02 8.21929E+06 + 3.57000E+02 8.50271E+06 + 3.57100E+02 8.50271E+06 + 3.57200E+02 7.55797E+06 + 3.57300E+02 6.61322E+06 + 3.57400E+02 5.66848E+06 + 3.57500E+02 4.72373E+06 + 3.57600E+02 3.77898E+06 + 3.57700E+02 2.83424E+06 + 3.57800E+02 1.88949E+06 + 3.57900E+02 9.44746E+05 + 3.58000E+02 0.00000E+00 + 3.58100E+02 0.00000E+00 + 3.58200E+02 0.00000E+00 + 3.58300E+02 0.00000E+00 + 3.58400E+02 0.00000E+00 + 3.58500E+02 0.00000E+00 + 3.58600E+02 0.00000E+00 + 3.58700E+02 0.00000E+00 + 3.58800E+02 0.00000E+00 + 3.58900E+02 0.00000E+00 + 3.59000E+02 0.00000E+00 + 3.59100E+02 0.00000E+00 + 3.59200E+02 0.00000E+00 + 3.59300E+02 0.00000E+00 + 3.59400E+02 0.00000E+00 + 3.59500E+02 0.00000E+00 + 3.59600E+02 0.00000E+00 + 3.59700E+02 0.00000E+00 + 3.59800E+02 0.00000E+00 + 3.59900E+02 0.00000E+00 + 3.60000E+02 0.00000E+00 + 3.60100E+02 2.83424E+05 + 3.60200E+02 5.66847E+05 + 3.60300E+02 8.50271E+05 + 3.60400E+02 1.13369E+06 + 3.60500E+02 1.41712E+06 + 3.60600E+02 1.70054E+06 + 3.60700E+02 1.98397E+06 + 3.60800E+02 2.26739E+06 + 3.60900E+02 2.55081E+06 + 3.61000E+02 2.83424E+06 + 3.61100E+02 3.11766E+06 + 3.61200E+02 3.40108E+06 + 3.61300E+02 3.68451E+06 + 3.61400E+02 3.96793E+06 + 3.61500E+02 4.25136E+06 + 3.61600E+02 4.53478E+06 + 3.61700E+02 4.81820E+06 + 3.61800E+02 5.10163E+06 + 3.61900E+02 5.38505E+06 + 3.62000E+02 5.66847E+06 + 3.62100E+02 5.95190E+06 + 3.62200E+02 6.23532E+06 + 3.62300E+02 6.51875E+06 + 3.62400E+02 6.80217E+06 + 3.62500E+02 7.08559E+06 + 3.62600E+02 7.36902E+06 + 3.62700E+02 7.65244E+06 + 3.62800E+02 7.93586E+06 + 3.62900E+02 8.21929E+06 + 3.63000E+02 8.50271E+06 + 3.63100E+02 8.50271E+06 + 3.63200E+02 7.55797E+06 + 3.63300E+02 6.61322E+06 + 3.63400E+02 5.66848E+06 + 3.63500E+02 4.72373E+06 + 3.63600E+02 3.77898E+06 + 3.63700E+02 2.83424E+06 + 3.63800E+02 1.88949E+06 + 3.63900E+02 9.44746E+05 + 3.64000E+02 0.00000E+00 + 3.64100E+02 0.00000E+00 + 3.64200E+02 0.00000E+00 + 3.64300E+02 0.00000E+00 + 3.64400E+02 0.00000E+00 + 3.64500E+02 0.00000E+00 + 3.64600E+02 0.00000E+00 + 3.64700E+02 0.00000E+00 + 3.64800E+02 0.00000E+00 + 3.64900E+02 0.00000E+00 + 3.65000E+02 0.00000E+00 + 3.65100E+02 0.00000E+00 + 3.65200E+02 0.00000E+00 + 3.65300E+02 0.00000E+00 + 3.65400E+02 0.00000E+00 + 3.65500E+02 0.00000E+00 + 3.65600E+02 0.00000E+00 + 3.65700E+02 0.00000E+00 + 3.65800E+02 0.00000E+00 + 3.65900E+02 0.00000E+00 + 3.66000E+02 0.00000E+00 + 3.66100E+02 2.83424E+05 + 3.66200E+02 5.66847E+05 + 3.66300E+02 8.50271E+05 + 3.66400E+02 1.13369E+06 + 3.66500E+02 1.41712E+06 + 3.66600E+02 1.70054E+06 + 3.66700E+02 1.98397E+06 + 3.66800E+02 2.26739E+06 + 3.66900E+02 2.55081E+06 + 3.67000E+02 2.83424E+06 + 3.67100E+02 3.11766E+06 + 3.67200E+02 3.40108E+06 + 3.67300E+02 3.68451E+06 + 3.67400E+02 3.96793E+06 + 3.67500E+02 4.25136E+06 + 3.67600E+02 4.53478E+06 + 3.67700E+02 4.81820E+06 + 3.67800E+02 5.10163E+06 + 3.67900E+02 5.38505E+06 + 3.68000E+02 5.66847E+06 + 3.68100E+02 5.95190E+06 + 3.68200E+02 6.23532E+06 + 3.68300E+02 6.51875E+06 + 3.68400E+02 6.80217E+06 + 3.68500E+02 7.08559E+06 + 3.68600E+02 7.36902E+06 + 3.68700E+02 7.65244E+06 + 3.68800E+02 7.93586E+06 + 3.68900E+02 8.21929E+06 + 3.69000E+02 8.50271E+06 + 3.69100E+02 8.50271E+06 + 3.69200E+02 7.55797E+06 + 3.69300E+02 6.61322E+06 + 3.69400E+02 5.66848E+06 + 3.69500E+02 4.72373E+06 + 3.69600E+02 3.77898E+06 + 3.69700E+02 2.83424E+06 + 3.69800E+02 1.88949E+06 + 3.69900E+02 9.44746E+05 + 3.70000E+02 0.00000E+00 + 3.70100E+02 0.00000E+00 + 3.70200E+02 0.00000E+00 + 3.70300E+02 0.00000E+00 + 3.70400E+02 0.00000E+00 + 3.70500E+02 0.00000E+00 + 3.70600E+02 0.00000E+00 + 3.70700E+02 0.00000E+00 + 3.70800E+02 0.00000E+00 + 3.70900E+02 0.00000E+00 + 3.71000E+02 0.00000E+00 + 3.71100E+02 0.00000E+00 + 3.71200E+02 0.00000E+00 + 3.71300E+02 0.00000E+00 + 3.71400E+02 0.00000E+00 + 3.71500E+02 0.00000E+00 + 3.71600E+02 0.00000E+00 + 3.71700E+02 0.00000E+00 + 3.71800E+02 0.00000E+00 + 3.71900E+02 0.00000E+00 + 3.72000E+02 0.00000E+00 + 3.72100E+02 2.83424E+05 + 3.72200E+02 5.66847E+05 + 3.72300E+02 8.50271E+05 + 3.72400E+02 1.13369E+06 + 3.72500E+02 1.41712E+06 + 3.72600E+02 1.70054E+06 + 3.72700E+02 1.98397E+06 + 3.72800E+02 2.26739E+06 + 3.72900E+02 2.55081E+06 + 3.73000E+02 2.83424E+06 + 3.73100E+02 3.11766E+06 + 3.73200E+02 3.40108E+06 + 3.73300E+02 3.68451E+06 + 3.73400E+02 3.96793E+06 + 3.73500E+02 4.25136E+06 + 3.73600E+02 4.53478E+06 + 3.73700E+02 4.81820E+06 + 3.73800E+02 5.10163E+06 + 3.73900E+02 5.38505E+06 + 3.74000E+02 5.66847E+06 + 3.74100E+02 5.95190E+06 + 3.74200E+02 6.23532E+06 + 3.74300E+02 6.51875E+06 + 3.74400E+02 6.80217E+06 + 3.74500E+02 7.08559E+06 + 3.74600E+02 7.36902E+06 + 3.74700E+02 7.65244E+06 + 3.74800E+02 7.93586E+06 + 3.74900E+02 8.21929E+06 + 3.75000E+02 8.50271E+06 + 3.75100E+02 8.50271E+06 + 3.75200E+02 7.55797E+06 + 3.75300E+02 6.61322E+06 + 3.75400E+02 5.66848E+06 + 3.75500E+02 4.72373E+06 + 3.75600E+02 3.77898E+06 + 3.75700E+02 2.83424E+06 + 3.75800E+02 1.88949E+06 + 3.75900E+02 9.44746E+05 + 3.76000E+02 0.00000E+00 + 3.76100E+02 0.00000E+00 + 3.76200E+02 0.00000E+00 + 3.76300E+02 0.00000E+00 + 3.76400E+02 0.00000E+00 + 3.76500E+02 0.00000E+00 + 3.76600E+02 0.00000E+00 + 3.76700E+02 0.00000E+00 + 3.76800E+02 0.00000E+00 + 3.76900E+02 0.00000E+00 + 3.77000E+02 0.00000E+00 + 3.77100E+02 0.00000E+00 + 3.77200E+02 0.00000E+00 + 3.77300E+02 0.00000E+00 + 3.77400E+02 0.00000E+00 + 3.77500E+02 0.00000E+00 + 3.77600E+02 0.00000E+00 + 3.77700E+02 0.00000E+00 + 3.77800E+02 0.00000E+00 + 3.77900E+02 0.00000E+00 + 3.78000E+02 0.00000E+00 + 3.78100E+02 2.83424E+05 + 3.78200E+02 5.66847E+05 + 3.78300E+02 8.50271E+05 + 3.78400E+02 1.13369E+06 + 3.78500E+02 1.41712E+06 + 3.78600E+02 1.70054E+06 + 3.78700E+02 1.98397E+06 + 3.78800E+02 2.26739E+06 + 3.78900E+02 2.55081E+06 + 3.79000E+02 2.83424E+06 + 3.79100E+02 3.11766E+06 + 3.79200E+02 3.40108E+06 + 3.79300E+02 3.68451E+06 + 3.79400E+02 3.96793E+06 + 3.79500E+02 4.25136E+06 + 3.79600E+02 4.53478E+06 + 3.79700E+02 4.81820E+06 + 3.79800E+02 5.10163E+06 + 3.79900E+02 5.38505E+06 + 3.80000E+02 5.66847E+06 + 3.80100E+02 5.95190E+06 + 3.80200E+02 6.23532E+06 + 3.80300E+02 6.51875E+06 + 3.80400E+02 6.80217E+06 + 3.80500E+02 7.08559E+06 + 3.80600E+02 7.36902E+06 + 3.80700E+02 7.65244E+06 + 3.80800E+02 7.93586E+06 + 3.80900E+02 8.21929E+06 + 3.81000E+02 8.50271E+06 + 3.81100E+02 8.50271E+06 + 3.81200E+02 7.55797E+06 + 3.81300E+02 6.61322E+06 + 3.81400E+02 5.66848E+06 + 3.81500E+02 4.72373E+06 + 3.81600E+02 3.77898E+06 + 3.81700E+02 2.83424E+06 + 3.81800E+02 1.88949E+06 + 3.81900E+02 9.44746E+05 + 3.82000E+02 0.00000E+00 + 3.82100E+02 0.00000E+00 + 3.82200E+02 0.00000E+00 + 3.82300E+02 0.00000E+00 + 3.82400E+02 0.00000E+00 + 3.82500E+02 0.00000E+00 + 3.82600E+02 0.00000E+00 + 3.82700E+02 0.00000E+00 + 3.82800E+02 0.00000E+00 + 3.82900E+02 0.00000E+00 + 3.83000E+02 0.00000E+00 + 3.83100E+02 0.00000E+00 + 3.83200E+02 0.00000E+00 + 3.83300E+02 0.00000E+00 + 3.83400E+02 0.00000E+00 + 3.83500E+02 0.00000E+00 + 3.83600E+02 0.00000E+00 + 3.83700E+02 0.00000E+00 + 3.83800E+02 0.00000E+00 + 3.83900E+02 0.00000E+00 + 3.84000E+02 0.00000E+00 + 3.84100E+02 2.83424E+05 + 3.84200E+02 5.66847E+05 + 3.84300E+02 8.50271E+05 + 3.84400E+02 1.13369E+06 + 3.84500E+02 1.41712E+06 + 3.84600E+02 1.70054E+06 + 3.84700E+02 1.98397E+06 + 3.84800E+02 2.26739E+06 + 3.84900E+02 2.55081E+06 + 3.85000E+02 2.83424E+06 + 3.85100E+02 3.11766E+06 + 3.85200E+02 3.40108E+06 + 3.85300E+02 3.68451E+06 + 3.85400E+02 3.96793E+06 + 3.85500E+02 4.25136E+06 + 3.85600E+02 4.53478E+06 + 3.85700E+02 4.81820E+06 + 3.85800E+02 5.10163E+06 + 3.85900E+02 5.38505E+06 + 3.86000E+02 5.66847E+06 + 3.86100E+02 5.95190E+06 + 3.86200E+02 6.23532E+06 + 3.86300E+02 6.51875E+06 + 3.86400E+02 6.80217E+06 + 3.86500E+02 7.08559E+06 + 3.86600E+02 7.36902E+06 + 3.86700E+02 7.65244E+06 + 3.86800E+02 7.93586E+06 + 3.86900E+02 8.21929E+06 + 3.87000E+02 8.50271E+06 + 3.87100E+02 8.50271E+06 + 3.87200E+02 7.55797E+06 + 3.87300E+02 6.61322E+06 + 3.87400E+02 5.66848E+06 + 3.87500E+02 4.72373E+06 + 3.87600E+02 3.77898E+06 + 3.87700E+02 2.83424E+06 + 3.87800E+02 1.88949E+06 + 3.87900E+02 9.44746E+05 + 3.88000E+02 0.00000E+00 + 3.88100E+02 0.00000E+00 + 3.88200E+02 0.00000E+00 + 3.88300E+02 0.00000E+00 + 3.88400E+02 0.00000E+00 + 3.88500E+02 0.00000E+00 + 3.88600E+02 0.00000E+00 + 3.88700E+02 0.00000E+00 + 3.88800E+02 0.00000E+00 + 3.88900E+02 0.00000E+00 + 3.89000E+02 0.00000E+00 + 3.89100E+02 0.00000E+00 + 3.89200E+02 0.00000E+00 + 3.89300E+02 0.00000E+00 + 3.89400E+02 0.00000E+00 + 3.89500E+02 0.00000E+00 + 3.89600E+02 0.00000E+00 + 3.89700E+02 0.00000E+00 + 3.89800E+02 0.00000E+00 + 3.89900E+02 0.00000E+00 + 3.90000E+02 0.00000E+00 + 3.90100E+02 2.83424E+05 + 3.90200E+02 5.66847E+05 + 3.90300E+02 8.50271E+05 + 3.90400E+02 1.13369E+06 + 3.90500E+02 1.41712E+06 + 3.90600E+02 1.70054E+06 + 3.90700E+02 1.98397E+06 + 3.90800E+02 2.26739E+06 + 3.90900E+02 2.55081E+06 + 3.91000E+02 2.83424E+06 + 3.91100E+02 3.11766E+06 + 3.91200E+02 3.40108E+06 + 3.91300E+02 3.68451E+06 + 3.91400E+02 3.96793E+06 + 3.91500E+02 4.25136E+06 + 3.91600E+02 4.53478E+06 + 3.91700E+02 4.81820E+06 + 3.91800E+02 5.10163E+06 + 3.91900E+02 5.38505E+06 + 3.92000E+02 5.66847E+06 + 3.92100E+02 5.95190E+06 + 3.92200E+02 6.23532E+06 + 3.92300E+02 6.51875E+06 + 3.92400E+02 6.80217E+06 + 3.92500E+02 7.08559E+06 + 3.92600E+02 7.36902E+06 + 3.92700E+02 7.65244E+06 + 3.92800E+02 7.93586E+06 + 3.92900E+02 8.21929E+06 + 3.93000E+02 8.50271E+06 + 3.93100E+02 8.50271E+06 + 3.93200E+02 7.55797E+06 + 3.93300E+02 6.61322E+06 + 3.93400E+02 5.66848E+06 + 3.93500E+02 4.72373E+06 + 3.93600E+02 3.77898E+06 + 3.93700E+02 2.83424E+06 + 3.93800E+02 1.88949E+06 + 3.93900E+02 9.44746E+05 + 3.94000E+02 0.00000E+00 + 3.94100E+02 0.00000E+00 + 3.94200E+02 0.00000E+00 + 3.94300E+02 0.00000E+00 + 3.94400E+02 0.00000E+00 + 3.94500E+02 0.00000E+00 + 3.94600E+02 0.00000E+00 + 3.94700E+02 0.00000E+00 + 3.94800E+02 0.00000E+00 + 3.94900E+02 0.00000E+00 + 3.95000E+02 0.00000E+00 + 3.95100E+02 0.00000E+00 + 3.95200E+02 0.00000E+00 + 3.95300E+02 0.00000E+00 + 3.95400E+02 0.00000E+00 + 3.95500E+02 0.00000E+00 + 3.95600E+02 0.00000E+00 + 3.95700E+02 0.00000E+00 + 3.95800E+02 0.00000E+00 + 3.95900E+02 0.00000E+00 + 3.96000E+02 0.00000E+00 + 3.96100E+02 2.83424E+05 + 3.96200E+02 5.66847E+05 + 3.96300E+02 8.50271E+05 + 3.96400E+02 1.13369E+06 + 3.96500E+02 1.41712E+06 + 3.96600E+02 1.70054E+06 + 3.96700E+02 1.98397E+06 + 3.96800E+02 2.26739E+06 + 3.96900E+02 2.55081E+06 + 3.97000E+02 2.83424E+06 + 3.97100E+02 3.11766E+06 + 3.97200E+02 3.40108E+06 + 3.97300E+02 3.68451E+06 + 3.97400E+02 3.96793E+06 + 3.97500E+02 4.25136E+06 + 3.97600E+02 4.53478E+06 + 3.97700E+02 4.81820E+06 + 3.97800E+02 5.10163E+06 + 3.97900E+02 5.38505E+06 + 3.98000E+02 5.66847E+06 + 3.98100E+02 5.95190E+06 + 3.98200E+02 6.23532E+06 + 3.98300E+02 6.51875E+06 + 3.98400E+02 6.80217E+06 + 3.98500E+02 7.08559E+06 + 3.98600E+02 7.36902E+06 + 3.98700E+02 7.65244E+06 + 3.98800E+02 7.93586E+06 + 3.98900E+02 8.21929E+06 + 3.99000E+02 8.50271E+06 + 3.99100E+02 8.50271E+06 + 3.99200E+02 7.55797E+06 + 3.99300E+02 6.61322E+06 + 3.99400E+02 5.66848E+06 + 3.99500E+02 4.72373E+06 + 3.99600E+02 3.77898E+06 + 3.99700E+02 2.83424E+06 + 3.99800E+02 1.88949E+06 + 3.99900E+02 9.44746E+05 + 4.00000E+02 0.00000E+00 + 4.00100E+02 0.00000E+00 + 4.00200E+02 0.00000E+00 + 4.00300E+02 0.00000E+00 + 4.00400E+02 0.00000E+00 + 4.00500E+02 0.00000E+00 + 4.00600E+02 0.00000E+00 + 4.00700E+02 0.00000E+00 + 4.00800E+02 0.00000E+00 + 4.00900E+02 0.00000E+00 + 4.01000E+02 0.00000E+00 + 4.01100E+02 0.00000E+00 + 4.01200E+02 0.00000E+00 + 4.01300E+02 0.00000E+00 + 4.01400E+02 0.00000E+00 + 4.01500E+02 0.00000E+00 + 4.01600E+02 0.00000E+00 + 4.01700E+02 0.00000E+00 + 4.01800E+02 0.00000E+00 + 4.01900E+02 0.00000E+00 + 4.02000E+02 0.00000E+00 + 4.02100E+02 2.83424E+05 + 4.02200E+02 5.66847E+05 + 4.02300E+02 8.50271E+05 + 4.02400E+02 1.13369E+06 + 4.02500E+02 1.41712E+06 + 4.02600E+02 1.70054E+06 + 4.02700E+02 1.98397E+06 + 4.02800E+02 2.26739E+06 + 4.02900E+02 2.55081E+06 + 4.03000E+02 2.83424E+06 + 4.03100E+02 3.11766E+06 + 4.03200E+02 3.40108E+06 + 4.03300E+02 3.68451E+06 + 4.03400E+02 3.96793E+06 + 4.03500E+02 4.25136E+06 + 4.03600E+02 4.53478E+06 + 4.03700E+02 4.81820E+06 + 4.03800E+02 5.10163E+06 + 4.03900E+02 5.38505E+06 + 4.04000E+02 5.66847E+06 + 4.04100E+02 5.95190E+06 + 4.04200E+02 6.23532E+06 + 4.04300E+02 6.51875E+06 + 4.04400E+02 6.80217E+06 + 4.04500E+02 7.08559E+06 + 4.04600E+02 7.36902E+06 + 4.04700E+02 7.65244E+06 + 4.04800E+02 7.93586E+06 + 4.04900E+02 8.21929E+06 + 4.05000E+02 8.50271E+06 + 4.05100E+02 8.50271E+06 + 4.05200E+02 7.55797E+06 + 4.05300E+02 6.61322E+06 + 4.05400E+02 5.66848E+06 + 4.05500E+02 4.72373E+06 + 4.05600E+02 3.77898E+06 + 4.05700E+02 2.83424E+06 + 4.05800E+02 1.88949E+06 + 4.05900E+02 9.44746E+05 + 4.06000E+02 0.00000E+00 + 4.06100E+02 0.00000E+00 + 4.06200E+02 0.00000E+00 + 4.06300E+02 0.00000E+00 + 4.06400E+02 0.00000E+00 + 4.06500E+02 0.00000E+00 + 4.06600E+02 0.00000E+00 + 4.06700E+02 0.00000E+00 + 4.06800E+02 0.00000E+00 + 4.06900E+02 0.00000E+00 + 4.07000E+02 0.00000E+00 + 4.07100E+02 0.00000E+00 + 4.07200E+02 0.00000E+00 + 4.07300E+02 0.00000E+00 + 4.07400E+02 0.00000E+00 + 4.07500E+02 0.00000E+00 + 4.07600E+02 0.00000E+00 + 4.07700E+02 0.00000E+00 + 4.07800E+02 0.00000E+00 + 4.07900E+02 0.00000E+00 + 4.08000E+02 0.00000E+00 + 4.08100E+02 2.83424E+05 + 4.08200E+02 5.66847E+05 + 4.08300E+02 8.50271E+05 + 4.08400E+02 1.13369E+06 + 4.08500E+02 1.41712E+06 + 4.08600E+02 1.70054E+06 + 4.08700E+02 1.98397E+06 + 4.08800E+02 2.26739E+06 + 4.08900E+02 2.55081E+06 + 4.09000E+02 2.83424E+06 + 4.09100E+02 3.11766E+06 + 4.09200E+02 3.40108E+06 + 4.09300E+02 3.68451E+06 + 4.09400E+02 3.96793E+06 + 4.09500E+02 4.25136E+06 + 4.09600E+02 4.53478E+06 + 4.09700E+02 4.81820E+06 + 4.09800E+02 5.10163E+06 + 4.09900E+02 5.38505E+06 + 4.10000E+02 5.66847E+06 + 4.10100E+02 5.95190E+06 + 4.10200E+02 6.23532E+06 + 4.10300E+02 6.51875E+06 + 4.10400E+02 6.80217E+06 + 4.10500E+02 7.08559E+06 + 4.10600E+02 7.36902E+06 + 4.10700E+02 7.65244E+06 + 4.10800E+02 7.93586E+06 + 4.10900E+02 8.21929E+06 + 4.11000E+02 8.50271E+06 + 4.11100E+02 8.50271E+06 + 4.11200E+02 7.55797E+06 + 4.11300E+02 6.61322E+06 + 4.11400E+02 5.66848E+06 + 4.11500E+02 4.72373E+06 + 4.11600E+02 3.77898E+06 + 4.11700E+02 2.83424E+06 + 4.11800E+02 1.88949E+06 + 4.11900E+02 9.44746E+05 + 4.12000E+02 0.00000E+00 + 4.12100E+02 0.00000E+00 + 4.12200E+02 0.00000E+00 + 4.12300E+02 0.00000E+00 + 4.12400E+02 0.00000E+00 + 4.12500E+02 0.00000E+00 + 4.12600E+02 0.00000E+00 + 4.12700E+02 0.00000E+00 + 4.12800E+02 0.00000E+00 + 4.12900E+02 0.00000E+00 + 4.13000E+02 0.00000E+00 + 4.13100E+02 0.00000E+00 + 4.13200E+02 0.00000E+00 + 4.13300E+02 0.00000E+00 + 4.13400E+02 0.00000E+00 + 4.13500E+02 0.00000E+00 + 4.13600E+02 0.00000E+00 + 4.13700E+02 0.00000E+00 + 4.13800E+02 0.00000E+00 + 4.13900E+02 0.00000E+00 + 4.14000E+02 0.00000E+00 + 4.14100E+02 2.83424E+05 + 4.14200E+02 5.66847E+05 + 4.14300E+02 8.50271E+05 + 4.14400E+02 1.13369E+06 + 4.14500E+02 1.41712E+06 + 4.14600E+02 1.70054E+06 + 4.14700E+02 1.98397E+06 + 4.14800E+02 2.26739E+06 + 4.14900E+02 2.55081E+06 + 4.15000E+02 2.83424E+06 + 4.15100E+02 3.11766E+06 + 4.15200E+02 3.40108E+06 + 4.15300E+02 3.68451E+06 + 4.15400E+02 3.96793E+06 + 4.15500E+02 4.25136E+06 + 4.15600E+02 4.53478E+06 + 4.15700E+02 4.81820E+06 + 4.15800E+02 5.10163E+06 + 4.15900E+02 5.38505E+06 + 4.16000E+02 5.66847E+06 + 4.16100E+02 5.95190E+06 + 4.16200E+02 6.23532E+06 + 4.16300E+02 6.51875E+06 + 4.16400E+02 6.80217E+06 + 4.16500E+02 7.08559E+06 + 4.16600E+02 7.36902E+06 + 4.16700E+02 7.65244E+06 + 4.16800E+02 7.93586E+06 + 4.16900E+02 8.21929E+06 + 4.17000E+02 8.50271E+06 + 4.17100E+02 8.50271E+06 + 4.17200E+02 7.55797E+06 + 4.17300E+02 6.61322E+06 + 4.17400E+02 5.66848E+06 + 4.17500E+02 4.72373E+06 + 4.17600E+02 3.77898E+06 + 4.17700E+02 2.83424E+06 + 4.17800E+02 1.88949E+06 + 4.17900E+02 9.44746E+05 + 4.18000E+02 0.00000E+00 + 4.18100E+02 0.00000E+00 + 4.18200E+02 0.00000E+00 + 4.18300E+02 0.00000E+00 + 4.18400E+02 0.00000E+00 + 4.18500E+02 0.00000E+00 + 4.18600E+02 0.00000E+00 + 4.18700E+02 0.00000E+00 + 4.18800E+02 0.00000E+00 + 4.18900E+02 0.00000E+00 + 4.19000E+02 0.00000E+00 + 4.19100E+02 0.00000E+00 + 4.19200E+02 0.00000E+00 + 4.19300E+02 0.00000E+00 + 4.19400E+02 0.00000E+00 + 4.19500E+02 0.00000E+00 + 4.19600E+02 0.00000E+00 + 4.19700E+02 0.00000E+00 + 4.19800E+02 0.00000E+00 + 4.19900E+02 0.00000E+00 + 4.20000E+02 0.00000E+00 + 4.20100E+02 2.83424E+05 + 4.20200E+02 5.66847E+05 + 4.20300E+02 8.50271E+05 + 4.20400E+02 1.13369E+06 + 4.20500E+02 1.41712E+06 + 4.20600E+02 1.70054E+06 + 4.20700E+02 1.98397E+06 + 4.20800E+02 2.26739E+06 + 4.20900E+02 2.55081E+06 + 4.21000E+02 2.83424E+06 + 4.21100E+02 3.11766E+06 + 4.21200E+02 3.40108E+06 + 4.21300E+02 3.68451E+06 + 4.21400E+02 3.96793E+06 + 4.21500E+02 4.25136E+06 + 4.21600E+02 4.53478E+06 + 4.21700E+02 4.81820E+06 + 4.21800E+02 5.10163E+06 + 4.21900E+02 5.38505E+06 + 4.22000E+02 5.66847E+06 + 4.22100E+02 5.95190E+06 + 4.22200E+02 6.23532E+06 + 4.22300E+02 6.51875E+06 + 4.22400E+02 6.80217E+06 + 4.22500E+02 7.08559E+06 + 4.22600E+02 7.36902E+06 + 4.22700E+02 7.65244E+06 + 4.22800E+02 7.93586E+06 + 4.22900E+02 8.21929E+06 + 4.23000E+02 8.50271E+06 + 4.23100E+02 8.50271E+06 + 4.23200E+02 7.55797E+06 + 4.23300E+02 6.61322E+06 + 4.23400E+02 5.66848E+06 + 4.23500E+02 4.72373E+06 + 4.23600E+02 3.77898E+06 + 4.23700E+02 2.83424E+06 + 4.23800E+02 1.88949E+06 + 4.23900E+02 9.44746E+05 + 4.24000E+02 0.00000E+00 + 4.24100E+02 0.00000E+00 + 4.24200E+02 0.00000E+00 + 4.24300E+02 0.00000E+00 + 4.24400E+02 0.00000E+00 + 4.24500E+02 0.00000E+00 + 4.24600E+02 0.00000E+00 + 4.24700E+02 0.00000E+00 + 4.24800E+02 0.00000E+00 + 4.24900E+02 0.00000E+00 + 4.25000E+02 0.00000E+00 + 4.25100E+02 0.00000E+00 + 4.25200E+02 0.00000E+00 + 4.25300E+02 0.00000E+00 + 4.25400E+02 0.00000E+00 + 4.25500E+02 0.00000E+00 + 4.25600E+02 0.00000E+00 + 4.25700E+02 0.00000E+00 + 4.25800E+02 0.00000E+00 + 4.25900E+02 0.00000E+00 + 4.26000E+02 0.00000E+00 + 4.26100E+02 2.83424E+05 + 4.26200E+02 5.66847E+05 + 4.26300E+02 8.50271E+05 + 4.26400E+02 1.13369E+06 + 4.26500E+02 1.41712E+06 + 4.26600E+02 1.70054E+06 + 4.26700E+02 1.98397E+06 + 4.26800E+02 2.26739E+06 + 4.26900E+02 2.55081E+06 + 4.27000E+02 2.83424E+06 + 4.27100E+02 3.11766E+06 + 4.27200E+02 3.40108E+06 + 4.27300E+02 3.68451E+06 + 4.27400E+02 3.96793E+06 + 4.27500E+02 4.25136E+06 + 4.27600E+02 4.53478E+06 + 4.27700E+02 4.81820E+06 + 4.27800E+02 5.10163E+06 + 4.27900E+02 5.38505E+06 + 4.28000E+02 5.66847E+06 + 4.28100E+02 5.95190E+06 + 4.28200E+02 6.23532E+06 + 4.28300E+02 6.51875E+06 + 4.28400E+02 6.80217E+06 + 4.28500E+02 7.08559E+06 + 4.28600E+02 7.36902E+06 + 4.28700E+02 7.65244E+06 + 4.28800E+02 7.93586E+06 + 4.28900E+02 8.21929E+06 + 4.29000E+02 8.50271E+06 + 4.29100E+02 8.50271E+06 + 4.29200E+02 7.55797E+06 + 4.29300E+02 6.61322E+06 + 4.29400E+02 5.66848E+06 + 4.29500E+02 4.72373E+06 + 4.29600E+02 3.77898E+06 + 4.29700E+02 2.83424E+06 + 4.29800E+02 1.88949E+06 + 4.29900E+02 9.44746E+05 + 4.30000E+02 0.00000E+00 + 4.30100E+02 0.00000E+00 + 4.30200E+02 0.00000E+00 + 4.30300E+02 0.00000E+00 + 4.30400E+02 0.00000E+00 + 4.30500E+02 0.00000E+00 + 4.30600E+02 0.00000E+00 + 4.30700E+02 0.00000E+00 + 4.30800E+02 0.00000E+00 + 4.30900E+02 0.00000E+00 + 4.31000E+02 0.00000E+00 + 4.31100E+02 0.00000E+00 + 4.31200E+02 0.00000E+00 + 4.31300E+02 0.00000E+00 + 4.31400E+02 0.00000E+00 + 4.31500E+02 0.00000E+00 + 4.31600E+02 0.00000E+00 + 4.31700E+02 0.00000E+00 + 4.31800E+02 0.00000E+00 + 4.31900E+02 0.00000E+00 + 4.32000E+02 0.00000E+00 + 4.32100E+02 2.83424E+05 + 4.32200E+02 5.66847E+05 + 4.32300E+02 8.50271E+05 + 4.32400E+02 1.13369E+06 + 4.32500E+02 1.41712E+06 + 4.32600E+02 1.70054E+06 + 4.32700E+02 1.98397E+06 + 4.32800E+02 2.26739E+06 + 4.32900E+02 2.55081E+06 + 4.33000E+02 2.83424E+06 + 4.33100E+02 3.11766E+06 + 4.33200E+02 3.40108E+06 + 4.33300E+02 3.68451E+06 + 4.33400E+02 3.96793E+06 + 4.33500E+02 4.25136E+06 + 4.33600E+02 4.53478E+06 + 4.33700E+02 4.81820E+06 + 4.33800E+02 5.10163E+06 + 4.33900E+02 5.38505E+06 + 4.34000E+02 5.66847E+06 + 4.34100E+02 5.95190E+06 + 4.34200E+02 6.23532E+06 + 4.34300E+02 6.51875E+06 + 4.34400E+02 6.80217E+06 + 4.34500E+02 7.08559E+06 + 4.34600E+02 7.36902E+06 + 4.34700E+02 7.65244E+06 + 4.34800E+02 7.93586E+06 + 4.34900E+02 8.21929E+06 + 4.35000E+02 8.50271E+06 + 4.35100E+02 8.50271E+06 + 4.35200E+02 7.55797E+06 + 4.35300E+02 6.61322E+06 + 4.35400E+02 5.66848E+06 + 4.35500E+02 4.72373E+06 + 4.35600E+02 3.77898E+06 + 4.35700E+02 2.83424E+06 + 4.35800E+02 1.88949E+06 + 4.35900E+02 9.44746E+05 + 4.36000E+02 0.00000E+00 + 4.36100E+02 0.00000E+00 + 4.36200E+02 0.00000E+00 + 4.36300E+02 0.00000E+00 + 4.36400E+02 0.00000E+00 + 4.36500E+02 0.00000E+00 + 4.36600E+02 0.00000E+00 + 4.36700E+02 0.00000E+00 + 4.36800E+02 0.00000E+00 + 4.36900E+02 0.00000E+00 + 4.37000E+02 0.00000E+00 + 4.37100E+02 0.00000E+00 + 4.37200E+02 0.00000E+00 + 4.37300E+02 0.00000E+00 + 4.37400E+02 0.00000E+00 + 4.37500E+02 0.00000E+00 + 4.37600E+02 0.00000E+00 + 4.37700E+02 0.00000E+00 + 4.37800E+02 0.00000E+00 + 4.37900E+02 0.00000E+00 + 4.38000E+02 0.00000E+00 + 4.38100E+02 2.83424E+05 + 4.38200E+02 5.66847E+05 + 4.38300E+02 8.50271E+05 + 4.38400E+02 1.13369E+06 + 4.38500E+02 1.41712E+06 + 4.38600E+02 1.70054E+06 + 4.38700E+02 1.98397E+06 + 4.38800E+02 2.26739E+06 + 4.38900E+02 2.55081E+06 + 4.39000E+02 2.83424E+06 + 4.39100E+02 3.11766E+06 + 4.39200E+02 3.40108E+06 + 4.39300E+02 3.68451E+06 + 4.39400E+02 3.96793E+06 + 4.39500E+02 4.25136E+06 + 4.39600E+02 4.53478E+06 + 4.39700E+02 4.81820E+06 + 4.39800E+02 5.10163E+06 + 4.39900E+02 5.38505E+06 + 4.40000E+02 5.66847E+06 + 4.40100E+02 5.95190E+06 + 4.40200E+02 6.23532E+06 + 4.40300E+02 6.51875E+06 + 4.40400E+02 6.80217E+06 + 4.40500E+02 7.08559E+06 + 4.40600E+02 7.36902E+06 + 4.40700E+02 7.65244E+06 + 4.40800E+02 7.93586E+06 + 4.40900E+02 8.21929E+06 + 4.41000E+02 8.50271E+06 + 4.41100E+02 8.50271E+06 + 4.41200E+02 7.55797E+06 + 4.41300E+02 6.61322E+06 + 4.41400E+02 5.66848E+06 + 4.41500E+02 4.72373E+06 + 4.41600E+02 3.77898E+06 + 4.41700E+02 2.83424E+06 + 4.41800E+02 1.88949E+06 + 4.41900E+02 9.44746E+05 + 4.42000E+02 0.00000E+00 + 4.42100E+02 0.00000E+00 + 4.42200E+02 0.00000E+00 + 4.42300E+02 0.00000E+00 + 4.42400E+02 0.00000E+00 + 4.42500E+02 0.00000E+00 + 4.42600E+02 0.00000E+00 + 4.42700E+02 0.00000E+00 + 4.42800E+02 0.00000E+00 + 4.42900E+02 0.00000E+00 + 4.43000E+02 0.00000E+00 + 4.43100E+02 0.00000E+00 + 4.43200E+02 0.00000E+00 + 4.43300E+02 0.00000E+00 + 4.43400E+02 0.00000E+00 + 4.43500E+02 0.00000E+00 + 4.43600E+02 0.00000E+00 + 4.43700E+02 0.00000E+00 + 4.43800E+02 0.00000E+00 + 4.43900E+02 0.00000E+00 + 4.44000E+02 0.00000E+00 + 4.44100E+02 2.83424E+05 + 4.44200E+02 5.66847E+05 + 4.44300E+02 8.50271E+05 + 4.44400E+02 1.13369E+06 + 4.44500E+02 1.41712E+06 + 4.44600E+02 1.70054E+06 + 4.44700E+02 1.98397E+06 + 4.44800E+02 2.26739E+06 + 4.44900E+02 2.55081E+06 + 4.45000E+02 2.83424E+06 + 4.45100E+02 3.11766E+06 + 4.45200E+02 3.40108E+06 + 4.45300E+02 3.68451E+06 + 4.45400E+02 3.96793E+06 + 4.45500E+02 4.25136E+06 + 4.45600E+02 4.53478E+06 + 4.45700E+02 4.81820E+06 + 4.45800E+02 5.10163E+06 + 4.45900E+02 5.38505E+06 + 4.46000E+02 5.66847E+06 + 4.46100E+02 5.95190E+06 + 4.46200E+02 6.23532E+06 + 4.46300E+02 6.51875E+06 + 4.46400E+02 6.80217E+06 + 4.46500E+02 7.08559E+06 + 4.46600E+02 7.36902E+06 + 4.46700E+02 7.65244E+06 + 4.46800E+02 7.93586E+06 + 4.46900E+02 8.21929E+06 + 4.47000E+02 8.50271E+06 + 4.47100E+02 8.50271E+06 + 4.47200E+02 7.55797E+06 + 4.47300E+02 6.61322E+06 + 4.47400E+02 5.66848E+06 + 4.47500E+02 4.72373E+06 + 4.47600E+02 3.77898E+06 + 4.47700E+02 2.83424E+06 + 4.47800E+02 1.88949E+06 + 4.47900E+02 9.44746E+05 + 4.48000E+02 0.00000E+00 + 4.48100E+02 0.00000E+00 + 4.48200E+02 0.00000E+00 + 4.48300E+02 0.00000E+00 + 4.48400E+02 0.00000E+00 + 4.48500E+02 0.00000E+00 + 4.48600E+02 0.00000E+00 + 4.48700E+02 0.00000E+00 + 4.48800E+02 0.00000E+00 + 4.48900E+02 0.00000E+00 + 4.49000E+02 0.00000E+00 + 4.49100E+02 0.00000E+00 + 4.49200E+02 0.00000E+00 + 4.49300E+02 0.00000E+00 + 4.49400E+02 0.00000E+00 + 4.49500E+02 0.00000E+00 + 4.49600E+02 0.00000E+00 + 4.49700E+02 0.00000E+00 + 4.49800E+02 0.00000E+00 + 4.49900E+02 0.00000E+00 + 4.50000E+02 0.00000E+00 + 4.50100E+02 2.83424E+05 + 4.50200E+02 5.66847E+05 + 4.50300E+02 8.50271E+05 + 4.50400E+02 1.13369E+06 + 4.50500E+02 1.41712E+06 + 4.50600E+02 1.70054E+06 + 4.50700E+02 1.98397E+06 + 4.50800E+02 2.26739E+06 + 4.50900E+02 2.55081E+06 + 4.51000E+02 2.83424E+06 + 4.51100E+02 3.11766E+06 + 4.51200E+02 3.40108E+06 + 4.51300E+02 3.68451E+06 + 4.51400E+02 3.96793E+06 + 4.51500E+02 4.25136E+06 + 4.51600E+02 4.53478E+06 + 4.51700E+02 4.81820E+06 + 4.51800E+02 5.10163E+06 + 4.51900E+02 5.38505E+06 + 4.52000E+02 5.66847E+06 + 4.52100E+02 5.95190E+06 + 4.52200E+02 6.23532E+06 + 4.52300E+02 6.51875E+06 + 4.52400E+02 6.80217E+06 + 4.52500E+02 7.08559E+06 + 4.52600E+02 7.36902E+06 + 4.52700E+02 7.65244E+06 + 4.52800E+02 7.93586E+06 + 4.52900E+02 8.21929E+06 + 4.53000E+02 8.50271E+06 + 4.53100E+02 8.50271E+06 + 4.53200E+02 7.55797E+06 + 4.53300E+02 6.61322E+06 + 4.53400E+02 5.66848E+06 + 4.53500E+02 4.72373E+06 + 4.53600E+02 3.77898E+06 + 4.53700E+02 2.83424E+06 + 4.53800E+02 1.88949E+06 + 4.53900E+02 9.44746E+05 + 4.54000E+02 0.00000E+00 + 4.54100E+02 0.00000E+00 + 4.54200E+02 0.00000E+00 + 4.54300E+02 0.00000E+00 + 4.54400E+02 0.00000E+00 + 4.54500E+02 0.00000E+00 + 4.54600E+02 0.00000E+00 + 4.54700E+02 0.00000E+00 + 4.54800E+02 0.00000E+00 + 4.54900E+02 0.00000E+00 + 4.55000E+02 0.00000E+00 + 4.55100E+02 0.00000E+00 + 4.55200E+02 0.00000E+00 + 4.55300E+02 0.00000E+00 + 4.55400E+02 0.00000E+00 + 4.55500E+02 0.00000E+00 + 4.55600E+02 0.00000E+00 + 4.55700E+02 0.00000E+00 + 4.55800E+02 0.00000E+00 + 4.55900E+02 0.00000E+00 + 4.56000E+02 0.00000E+00 + 4.56100E+02 2.83424E+05 + 4.56200E+02 5.66847E+05 + 4.56300E+02 8.50271E+05 + 4.56400E+02 1.13369E+06 + 4.56500E+02 1.41712E+06 + 4.56600E+02 1.70054E+06 + 4.56700E+02 1.98397E+06 + 4.56800E+02 2.26739E+06 + 4.56900E+02 2.55081E+06 + 4.57000E+02 2.83424E+06 + 4.57100E+02 3.11766E+06 + 4.57200E+02 3.40108E+06 + 4.57300E+02 3.68451E+06 + 4.57400E+02 3.96793E+06 + 4.57500E+02 4.25136E+06 + 4.57600E+02 4.53478E+06 + 4.57700E+02 4.81820E+06 + 4.57800E+02 5.10163E+06 + 4.57900E+02 5.38505E+06 + 4.58000E+02 5.66847E+06 + 4.58100E+02 5.95190E+06 + 4.58200E+02 6.23532E+06 + 4.58300E+02 6.51875E+06 + 4.58400E+02 6.80217E+06 + 4.58500E+02 7.08559E+06 + 4.58600E+02 7.36902E+06 + 4.58700E+02 7.65244E+06 + 4.58800E+02 7.93586E+06 + 4.58900E+02 8.21929E+06 + 4.59000E+02 8.50271E+06 + 4.59100E+02 8.50271E+06 + 4.59200E+02 7.55797E+06 + 4.59300E+02 6.61322E+06 + 4.59400E+02 5.66848E+06 + 4.59500E+02 4.72373E+06 + 4.59600E+02 3.77898E+06 + 4.59700E+02 2.83424E+06 + 4.59800E+02 1.88949E+06 + 4.59900E+02 9.44746E+05 + 4.60000E+02 0.00000E+00 + 4.60100E+02 0.00000E+00 + 4.60200E+02 0.00000E+00 + 4.60300E+02 0.00000E+00 + 4.60400E+02 0.00000E+00 + 4.60500E+02 0.00000E+00 + 4.60600E+02 0.00000E+00 + 4.60700E+02 0.00000E+00 + 4.60800E+02 0.00000E+00 + 4.60900E+02 0.00000E+00 + 4.61000E+02 0.00000E+00 + 4.61100E+02 0.00000E+00 + 4.61200E+02 0.00000E+00 + 4.61300E+02 0.00000E+00 + 4.61400E+02 0.00000E+00 + 4.61500E+02 0.00000E+00 + 4.61600E+02 0.00000E+00 + 4.61700E+02 0.00000E+00 + 4.61800E+02 0.00000E+00 + 4.61900E+02 0.00000E+00 + 4.62000E+02 0.00000E+00 + 4.62100E+02 2.83424E+05 + 4.62200E+02 5.66847E+05 + 4.62300E+02 8.50271E+05 + 4.62400E+02 1.13369E+06 + 4.62500E+02 1.41712E+06 + 4.62600E+02 1.70054E+06 + 4.62700E+02 1.98397E+06 + 4.62800E+02 2.26739E+06 + 4.62900E+02 2.55081E+06 + 4.63000E+02 2.83424E+06 + 4.63100E+02 3.11766E+06 + 4.63200E+02 3.40108E+06 + 4.63300E+02 3.68451E+06 + 4.63400E+02 3.96793E+06 + 4.63500E+02 4.25136E+06 + 4.63600E+02 4.53478E+06 + 4.63700E+02 4.81820E+06 + 4.63800E+02 5.10163E+06 + 4.63900E+02 5.38505E+06 + 4.64000E+02 5.66847E+06 + 4.64100E+02 5.95190E+06 + 4.64200E+02 6.23532E+06 + 4.64300E+02 6.51875E+06 + 4.64400E+02 6.80217E+06 + 4.64500E+02 7.08559E+06 + 4.64600E+02 7.36902E+06 + 4.64700E+02 7.65244E+06 + 4.64800E+02 7.93586E+06 + 4.64900E+02 8.21929E+06 + 4.65000E+02 8.50271E+06 + 4.65100E+02 8.50271E+06 + 4.65200E+02 7.55797E+06 + 4.65300E+02 6.61322E+06 + 4.65400E+02 5.66848E+06 + 4.65500E+02 4.72373E+06 + 4.65600E+02 3.77898E+06 + 4.65700E+02 2.83424E+06 + 4.65800E+02 1.88949E+06 + 4.65900E+02 9.44746E+05 + 4.66000E+02 0.00000E+00 + 4.66100E+02 0.00000E+00 + 4.66200E+02 0.00000E+00 + 4.66300E+02 0.00000E+00 + 4.66400E+02 0.00000E+00 + 4.66500E+02 0.00000E+00 + 4.66600E+02 0.00000E+00 + 4.66700E+02 0.00000E+00 + 4.66800E+02 0.00000E+00 + 4.66900E+02 0.00000E+00 + 4.67000E+02 0.00000E+00 + 4.67100E+02 0.00000E+00 + 4.67200E+02 0.00000E+00 + 4.67300E+02 0.00000E+00 + 4.67400E+02 0.00000E+00 + 4.67500E+02 0.00000E+00 + 4.67600E+02 0.00000E+00 + 4.67700E+02 0.00000E+00 + 4.67800E+02 0.00000E+00 + 4.67900E+02 0.00000E+00 + 4.68000E+02 0.00000E+00 + 4.68100E+02 2.83424E+05 + 4.68200E+02 5.66847E+05 + 4.68300E+02 8.50271E+05 + 4.68400E+02 1.13369E+06 + 4.68500E+02 1.41712E+06 + 4.68600E+02 1.70054E+06 + 4.68700E+02 1.98397E+06 + 4.68800E+02 2.26739E+06 + 4.68900E+02 2.55081E+06 + 4.69000E+02 2.83424E+06 + 4.69100E+02 3.11766E+06 + 4.69200E+02 3.40108E+06 + 4.69300E+02 3.68451E+06 + 4.69400E+02 3.96793E+06 + 4.69500E+02 4.25136E+06 + 4.69600E+02 4.53478E+06 + 4.69700E+02 4.81820E+06 + 4.69800E+02 5.10163E+06 + 4.69900E+02 5.38505E+06 + 4.70000E+02 5.66847E+06 + 4.70100E+02 5.95190E+06 + 4.70200E+02 6.23532E+06 + 4.70300E+02 6.51875E+06 + 4.70400E+02 6.80217E+06 + 4.70500E+02 7.08559E+06 + 4.70600E+02 7.36902E+06 + 4.70700E+02 7.65244E+06 + 4.70800E+02 7.93586E+06 + 4.70900E+02 8.21929E+06 + 4.71000E+02 8.50271E+06 + 4.71100E+02 8.50271E+06 + 4.71200E+02 7.55797E+06 + 4.71300E+02 6.61322E+06 + 4.71400E+02 5.66848E+06 + 4.71500E+02 4.72373E+06 + 4.71600E+02 3.77898E+06 + 4.71700E+02 2.83424E+06 + 4.71800E+02 1.88949E+06 + 4.71900E+02 9.44746E+05 + 4.72000E+02 0.00000E+00 + 4.72100E+02 0.00000E+00 + 4.72200E+02 0.00000E+00 + 4.72300E+02 0.00000E+00 + 4.72400E+02 0.00000E+00 + 4.72500E+02 0.00000E+00 + 4.72600E+02 0.00000E+00 + 4.72700E+02 0.00000E+00 + 4.72800E+02 0.00000E+00 + 4.72900E+02 0.00000E+00 + 4.73000E+02 0.00000E+00 + 4.73100E+02 0.00000E+00 + 4.73200E+02 0.00000E+00 + 4.73300E+02 0.00000E+00 + 4.73400E+02 0.00000E+00 + 4.73500E+02 0.00000E+00 + 4.73600E+02 0.00000E+00 + 4.73700E+02 0.00000E+00 + 4.73800E+02 0.00000E+00 + 4.73900E+02 0.00000E+00 + 4.74000E+02 0.00000E+00 + 4.74100E+02 2.83424E+05 + 4.74200E+02 5.66847E+05 + 4.74300E+02 8.50271E+05 + 4.74400E+02 1.13369E+06 + 4.74500E+02 1.41712E+06 + 4.74600E+02 1.70054E+06 + 4.74700E+02 1.98397E+06 + 4.74800E+02 2.26739E+06 + 4.74900E+02 2.55081E+06 + 4.75000E+02 2.83424E+06 + 4.75100E+02 3.11766E+06 + 4.75200E+02 3.40108E+06 + 4.75300E+02 3.68451E+06 + 4.75400E+02 3.96793E+06 + 4.75500E+02 4.25136E+06 + 4.75600E+02 4.53478E+06 + 4.75700E+02 4.81820E+06 + 4.75800E+02 5.10163E+06 + 4.75900E+02 5.38505E+06 + 4.76000E+02 5.66847E+06 + 4.76100E+02 5.95190E+06 + 4.76200E+02 6.23532E+06 + 4.76300E+02 6.51875E+06 + 4.76400E+02 6.80217E+06 + 4.76500E+02 7.08559E+06 + 4.76600E+02 7.36902E+06 + 4.76700E+02 7.65244E+06 + 4.76800E+02 7.93586E+06 + 4.76900E+02 8.21929E+06 + 4.77000E+02 8.50271E+06 + 4.77100E+02 8.50271E+06 + 4.77200E+02 7.55797E+06 + 4.77300E+02 6.61322E+06 + 4.77400E+02 5.66848E+06 + 4.77500E+02 4.72373E+06 + 4.77600E+02 3.77898E+06 + 4.77700E+02 2.83424E+06 + 4.77800E+02 1.88949E+06 + 4.77900E+02 9.44746E+05 + 4.78000E+02 0.00000E+00 + 4.78100E+02 0.00000E+00 + 4.78200E+02 0.00000E+00 + 4.78300E+02 0.00000E+00 + 4.78400E+02 0.00000E+00 + 4.78500E+02 0.00000E+00 + 4.78600E+02 0.00000E+00 + 4.78700E+02 0.00000E+00 + 4.78800E+02 0.00000E+00 + 4.78900E+02 0.00000E+00 + 4.79000E+02 0.00000E+00 + 4.79100E+02 0.00000E+00 + 4.79200E+02 0.00000E+00 + 4.79300E+02 0.00000E+00 + 4.79400E+02 0.00000E+00 + 4.79500E+02 0.00000E+00 + 4.79600E+02 0.00000E+00 + 4.79700E+02 0.00000E+00 + 4.79800E+02 0.00000E+00 + 4.79900E+02 0.00000E+00 + 4.80000E+02 0.00000E+00 + 4.80100E+02 2.83424E+05 + 4.80200E+02 5.66847E+05 + 4.80300E+02 8.50271E+05 + 4.80400E+02 1.13369E+06 + 4.80500E+02 1.41712E+06 + 4.80600E+02 1.70054E+06 + 4.80700E+02 1.98397E+06 + 4.80800E+02 2.26739E+06 + 4.80900E+02 2.55081E+06 + 4.81000E+02 2.83424E+06 + 4.81100E+02 3.11766E+06 + 4.81200E+02 3.40108E+06 + 4.81300E+02 3.68451E+06 + 4.81400E+02 3.96793E+06 + 4.81500E+02 4.25136E+06 + 4.81600E+02 4.53478E+06 + 4.81700E+02 4.81820E+06 + 4.81800E+02 5.10163E+06 + 4.81900E+02 5.38505E+06 + 4.82000E+02 5.66847E+06 + 4.82100E+02 5.95190E+06 + 4.82200E+02 6.23532E+06 + 4.82300E+02 6.51875E+06 + 4.82400E+02 6.80217E+06 + 4.82500E+02 7.08559E+06 + 4.82600E+02 7.36902E+06 + 4.82700E+02 7.65244E+06 + 4.82800E+02 7.93586E+06 + 4.82900E+02 8.21929E+06 + 4.83000E+02 8.50271E+06 + 4.83100E+02 8.50271E+06 + 4.83200E+02 7.55797E+06 + 4.83300E+02 6.61322E+06 + 4.83400E+02 5.66848E+06 + 4.83500E+02 4.72373E+06 + 4.83600E+02 3.77898E+06 + 4.83700E+02 2.83424E+06 + 4.83800E+02 1.88949E+06 + 4.83900E+02 9.44746E+05 + 4.84000E+02 0.00000E+00 + 4.84100E+02 0.00000E+00 + 4.84200E+02 0.00000E+00 + 4.84300E+02 0.00000E+00 + 4.84400E+02 0.00000E+00 + 4.84500E+02 0.00000E+00 + 4.84600E+02 0.00000E+00 + 4.84700E+02 0.00000E+00 + 4.84800E+02 0.00000E+00 + 4.84900E+02 0.00000E+00 + 4.85000E+02 0.00000E+00 + 4.85100E+02 0.00000E+00 + 4.85200E+02 0.00000E+00 + 4.85300E+02 0.00000E+00 + 4.85400E+02 0.00000E+00 + 4.85500E+02 0.00000E+00 + 4.85600E+02 0.00000E+00 + 4.85700E+02 0.00000E+00 + 4.85800E+02 0.00000E+00 + 4.85900E+02 0.00000E+00 + 4.86000E+02 0.00000E+00 + 4.86100E+02 2.83424E+05 + 4.86200E+02 5.66847E+05 + 4.86300E+02 8.50271E+05 + 4.86400E+02 1.13369E+06 + 4.86500E+02 1.41712E+06 + 4.86600E+02 1.70054E+06 + 4.86700E+02 1.98397E+06 + 4.86800E+02 2.26739E+06 + 4.86900E+02 2.55081E+06 + 4.87000E+02 2.83424E+06 + 4.87100E+02 3.11766E+06 + 4.87200E+02 3.40108E+06 + 4.87300E+02 3.68451E+06 + 4.87400E+02 3.96793E+06 + 4.87500E+02 4.25136E+06 + 4.87600E+02 4.53478E+06 + 4.87700E+02 4.81820E+06 + 4.87800E+02 5.10163E+06 + 4.87900E+02 5.38505E+06 + 4.88000E+02 5.66847E+06 + 4.88100E+02 5.95190E+06 + 4.88200E+02 6.23532E+06 + 4.88300E+02 6.51875E+06 + 4.88400E+02 6.80217E+06 + 4.88500E+02 7.08559E+06 + 4.88600E+02 7.36902E+06 + 4.88700E+02 7.65244E+06 + 4.88800E+02 7.93586E+06 + 4.88900E+02 8.21929E+06 + 4.89000E+02 8.50271E+06 + 4.89100E+02 8.50271E+06 + 4.89200E+02 7.55797E+06 + 4.89300E+02 6.61322E+06 + 4.89400E+02 5.66848E+06 + 4.89500E+02 4.72373E+06 + 4.89600E+02 3.77898E+06 + 4.89700E+02 2.83424E+06 + 4.89800E+02 1.88949E+06 + 4.89900E+02 9.44746E+05 + 4.90000E+02 0.00000E+00 + 4.90100E+02 0.00000E+00 + 4.90200E+02 0.00000E+00 + 4.90300E+02 0.00000E+00 + 4.90400E+02 0.00000E+00 + 4.90500E+02 0.00000E+00 + 4.90600E+02 0.00000E+00 + 4.90700E+02 0.00000E+00 + 4.90800E+02 0.00000E+00 + 4.90900E+02 0.00000E+00 + 4.91000E+02 0.00000E+00 + 4.91100E+02 0.00000E+00 + 4.91200E+02 0.00000E+00 + 4.91300E+02 0.00000E+00 + 4.91400E+02 0.00000E+00 + 4.91500E+02 0.00000E+00 + 4.91600E+02 0.00000E+00 + 4.91700E+02 0.00000E+00 + 4.91800E+02 0.00000E+00 + 4.91900E+02 0.00000E+00 + 4.92000E+02 0.00000E+00 + 4.92100E+02 2.83424E+05 + 4.92200E+02 5.66847E+05 + 4.92300E+02 8.50271E+05 + 4.92400E+02 1.13369E+06 + 4.92500E+02 1.41712E+06 + 4.92600E+02 1.70054E+06 + 4.92700E+02 1.98397E+06 + 4.92800E+02 2.26739E+06 + 4.92900E+02 2.55081E+06 + 4.93000E+02 2.83424E+06 + 4.93100E+02 3.11766E+06 + 4.93200E+02 3.40108E+06 + 4.93300E+02 3.68451E+06 + 4.93400E+02 3.96793E+06 + 4.93500E+02 4.25136E+06 + 4.93600E+02 4.53478E+06 + 4.93700E+02 4.81820E+06 + 4.93800E+02 5.10163E+06 + 4.93900E+02 5.38505E+06 + 4.94000E+02 5.66847E+06 + 4.94100E+02 5.95190E+06 + 4.94200E+02 6.23532E+06 + 4.94300E+02 6.51875E+06 + 4.94400E+02 6.80217E+06 + 4.94500E+02 7.08559E+06 + 4.94600E+02 7.36902E+06 + 4.94700E+02 7.65244E+06 + 4.94800E+02 7.93586E+06 + 4.94900E+02 8.21929E+06 + 4.95000E+02 8.50271E+06 + 4.95100E+02 8.50271E+06 + 4.95200E+02 7.55797E+06 + 4.95300E+02 6.61322E+06 + 4.95400E+02 5.66848E+06 + 4.95500E+02 4.72373E+06 + 4.95600E+02 3.77898E+06 + 4.95700E+02 2.83424E+06 + 4.95800E+02 1.88949E+06 + 4.95900E+02 9.44746E+05 + 4.96000E+02 0.00000E+00 + 4.96100E+02 0.00000E+00 + 4.96200E+02 0.00000E+00 + 4.96300E+02 0.00000E+00 + 4.96400E+02 0.00000E+00 + 4.96500E+02 0.00000E+00 + 4.96600E+02 0.00000E+00 + 4.96700E+02 0.00000E+00 + 4.96800E+02 0.00000E+00 + 4.96900E+02 0.00000E+00 + 4.97000E+02 0.00000E+00 + 4.97100E+02 0.00000E+00 + 4.97200E+02 0.00000E+00 + 4.97300E+02 0.00000E+00 + 4.97400E+02 0.00000E+00 + 4.97500E+02 0.00000E+00 + 4.97600E+02 0.00000E+00 + 4.97700E+02 0.00000E+00 + 4.97800E+02 0.00000E+00 + 4.97900E+02 0.00000E+00 + 4.98000E+02 0.00000E+00 + 4.98100E+02 2.83424E+05 + 4.98200E+02 5.66847E+05 + 4.98300E+02 8.50271E+05 + 4.98400E+02 1.13369E+06 + 4.98500E+02 1.41712E+06 + 4.98600E+02 1.70054E+06 + 4.98700E+02 1.98397E+06 + 4.98800E+02 2.26739E+06 + 4.98900E+02 2.55081E+06 + 4.99000E+02 2.83424E+06 + 4.99100E+02 3.11766E+06 + 4.99200E+02 3.40108E+06 + 4.99300E+02 3.68451E+06 + 4.99400E+02 3.96793E+06 + 4.99500E+02 4.25136E+06 + 4.99600E+02 4.53478E+06 + 4.99700E+02 4.81820E+06 + 4.99800E+02 5.10163E+06 + 4.99900E+02 5.38505E+06 + 5.00000E+02 5.66847E+06 + 5.00100E+02 5.95190E+06 + 5.00200E+02 6.23532E+06 + 5.00300E+02 6.51875E+06 + 5.00400E+02 6.80217E+06 + 5.00500E+02 7.08559E+06 + 5.00600E+02 7.36902E+06 + 5.00700E+02 7.65244E+06 + 5.00800E+02 7.93586E+06 + 5.00900E+02 8.21929E+06 + 5.01000E+02 8.50271E+06 + 5.01100E+02 8.50271E+06 + 5.01200E+02 7.55797E+06 + 5.01300E+02 6.61322E+06 + 5.01400E+02 5.66848E+06 + 5.01500E+02 4.72373E+06 + 5.01600E+02 3.77898E+06 + 5.01700E+02 2.83424E+06 + 5.01800E+02 1.88949E+06 + 5.01900E+02 9.44746E+05 + 5.02000E+02 0.00000E+00 + 5.02100E+02 0.00000E+00 + 5.02200E+02 0.00000E+00 + 5.02300E+02 0.00000E+00 + 5.02400E+02 0.00000E+00 + 5.02500E+02 0.00000E+00 + 5.02600E+02 0.00000E+00 + 5.02700E+02 0.00000E+00 + 5.02800E+02 0.00000E+00 + 5.02900E+02 0.00000E+00 + 5.03000E+02 0.00000E+00 + 5.03100E+02 0.00000E+00 + 5.03200E+02 0.00000E+00 + 5.03300E+02 0.00000E+00 + 5.03400E+02 0.00000E+00 + 5.03500E+02 0.00000E+00 + 5.03600E+02 0.00000E+00 + 5.03700E+02 0.00000E+00 + 5.03800E+02 0.00000E+00 + 5.03900E+02 0.00000E+00 + 5.04000E+02 0.00000E+00 + 5.04100E+02 2.83424E+05 + 5.04200E+02 5.66847E+05 + 5.04300E+02 8.50271E+05 + 5.04400E+02 1.13369E+06 + 5.04500E+02 1.41712E+06 + 5.04600E+02 1.70054E+06 + 5.04700E+02 1.98397E+06 + 5.04800E+02 2.26739E+06 + 5.04900E+02 2.55081E+06 + 5.05000E+02 2.83424E+06 + 5.05100E+02 3.11766E+06 + 5.05200E+02 3.40108E+06 + 5.05300E+02 3.68451E+06 + 5.05400E+02 3.96793E+06 + 5.05500E+02 4.25136E+06 + 5.05600E+02 4.53478E+06 + 5.05700E+02 4.81820E+06 + 5.05800E+02 5.10163E+06 + 5.05900E+02 5.38505E+06 + 5.06000E+02 5.66847E+06 + 5.06100E+02 5.95190E+06 + 5.06200E+02 6.23532E+06 + 5.06300E+02 6.51875E+06 + 5.06400E+02 6.80217E+06 + 5.06500E+02 7.08559E+06 + 5.06600E+02 7.36902E+06 + 5.06700E+02 7.65244E+06 + 5.06800E+02 7.93586E+06 + 5.06900E+02 8.21929E+06 + 5.07000E+02 8.50271E+06 + 5.07100E+02 8.50271E+06 + 5.07200E+02 7.55797E+06 + 5.07300E+02 6.61322E+06 + 5.07400E+02 5.66848E+06 + 5.07500E+02 4.72373E+06 + 5.07600E+02 3.77898E+06 + 5.07700E+02 2.83424E+06 + 5.07800E+02 1.88949E+06 + 5.07900E+02 9.44746E+05 + 5.08000E+02 0.00000E+00 + 5.08100E+02 0.00000E+00 + 5.08200E+02 0.00000E+00 + 5.08300E+02 0.00000E+00 + 5.08400E+02 0.00000E+00 + 5.08500E+02 0.00000E+00 + 5.08600E+02 0.00000E+00 + 5.08700E+02 0.00000E+00 + 5.08800E+02 0.00000E+00 + 5.08900E+02 0.00000E+00 + 5.09000E+02 0.00000E+00 + 5.09100E+02 0.00000E+00 + 5.09200E+02 0.00000E+00 + 5.09300E+02 0.00000E+00 + 5.09400E+02 0.00000E+00 + 5.09500E+02 0.00000E+00 + 5.09600E+02 0.00000E+00 + 5.09700E+02 0.00000E+00 + 5.09800E+02 0.00000E+00 + 5.09900E+02 0.00000E+00 + 5.10000E+02 0.00000E+00 + 5.10100E+02 2.83424E+05 + 5.10200E+02 5.66847E+05 + 5.10300E+02 8.50271E+05 + 5.10400E+02 1.13369E+06 + 5.10500E+02 1.41712E+06 + 5.10600E+02 1.70054E+06 + 5.10700E+02 1.98397E+06 + 5.10800E+02 2.26739E+06 + 5.10900E+02 2.55081E+06 + 5.11000E+02 2.83424E+06 + 5.11100E+02 3.11766E+06 + 5.11200E+02 3.40108E+06 + 5.11300E+02 3.68451E+06 + 5.11400E+02 3.96793E+06 + 5.11500E+02 4.25136E+06 + 5.11600E+02 4.53478E+06 + 5.11700E+02 4.81820E+06 + 5.11800E+02 5.10163E+06 + 5.11900E+02 5.38505E+06 + 5.12000E+02 5.66847E+06 + 5.12100E+02 5.95190E+06 + 5.12200E+02 6.23532E+06 + 5.12300E+02 6.51875E+06 + 5.12400E+02 6.80217E+06 + 5.12500E+02 7.08559E+06 + 5.12600E+02 7.36902E+06 + 5.12700E+02 7.65244E+06 + 5.12800E+02 7.93586E+06 + 5.12900E+02 8.21929E+06 + 5.13000E+02 8.50271E+06 + 5.13100E+02 8.50271E+06 + 5.13200E+02 7.55797E+06 + 5.13300E+02 6.61322E+06 + 5.13400E+02 5.66848E+06 + 5.13500E+02 4.72373E+06 + 5.13600E+02 3.77898E+06 + 5.13700E+02 2.83424E+06 + 5.13800E+02 1.88949E+06 + 5.13900E+02 9.44746E+05 + 5.14000E+02 0.00000E+00 + 5.14100E+02 0.00000E+00 + 5.14200E+02 0.00000E+00 + 5.14300E+02 0.00000E+00 + 5.14400E+02 0.00000E+00 + 5.14500E+02 0.00000E+00 + 5.14600E+02 0.00000E+00 + 5.14700E+02 0.00000E+00 + 5.14800E+02 0.00000E+00 + 5.14900E+02 0.00000E+00 + 5.15000E+02 0.00000E+00 + 5.15100E+02 0.00000E+00 + 5.15200E+02 0.00000E+00 + 5.15300E+02 0.00000E+00 + 5.15400E+02 0.00000E+00 + 5.15500E+02 0.00000E+00 + 5.15600E+02 0.00000E+00 + 5.15700E+02 0.00000E+00 + 5.15800E+02 0.00000E+00 + 5.15900E+02 0.00000E+00 + 5.16000E+02 0.00000E+00 + 5.16100E+02 2.83424E+05 + 5.16200E+02 5.66847E+05 + 5.16300E+02 8.50271E+05 + 5.16400E+02 1.13369E+06 + 5.16500E+02 1.41712E+06 + 5.16600E+02 1.70054E+06 + 5.16700E+02 1.98397E+06 + 5.16800E+02 2.26739E+06 + 5.16900E+02 2.55081E+06 + 5.17000E+02 2.83424E+06 + 5.17100E+02 3.11766E+06 + 5.17200E+02 3.40108E+06 + 5.17300E+02 3.68451E+06 + 5.17400E+02 3.96793E+06 + 5.17500E+02 4.25136E+06 + 5.17600E+02 4.53478E+06 + 5.17700E+02 4.81820E+06 + 5.17800E+02 5.10163E+06 + 5.17900E+02 5.38505E+06 + 5.18000E+02 5.66847E+06 + 5.18100E+02 5.95190E+06 + 5.18200E+02 6.23532E+06 + 5.18300E+02 6.51875E+06 + 5.18400E+02 6.80217E+06 + 5.18500E+02 7.08559E+06 + 5.18600E+02 7.36902E+06 + 5.18700E+02 7.65244E+06 + 5.18800E+02 7.93586E+06 + 5.18900E+02 8.21929E+06 + 5.19000E+02 8.50271E+06 + 5.19100E+02 8.50271E+06 + 5.19200E+02 7.55797E+06 + 5.19300E+02 6.61322E+06 + 5.19400E+02 5.66848E+06 + 5.19500E+02 4.72373E+06 + 5.19600E+02 3.77898E+06 + 5.19700E+02 2.83424E+06 + 5.19800E+02 1.88949E+06 + 5.19900E+02 9.44746E+05 + 5.20000E+02 0.00000E+00 + 5.20100E+02 0.00000E+00 + 5.20200E+02 0.00000E+00 + 5.20300E+02 0.00000E+00 + 5.20400E+02 0.00000E+00 + 5.20500E+02 0.00000E+00 + 5.20600E+02 0.00000E+00 + 5.20700E+02 0.00000E+00 + 5.20800E+02 0.00000E+00 + 5.20900E+02 0.00000E+00 + 5.21000E+02 0.00000E+00 + 5.21100E+02 0.00000E+00 + 5.21200E+02 0.00000E+00 + 5.21300E+02 0.00000E+00 + 5.21400E+02 0.00000E+00 + 5.21500E+02 0.00000E+00 + 5.21600E+02 0.00000E+00 + 5.21700E+02 0.00000E+00 + 5.21800E+02 0.00000E+00 + 5.21900E+02 0.00000E+00 + 5.22000E+02 0.00000E+00 + 5.22100E+02 2.83424E+05 + 5.22200E+02 5.66847E+05 + 5.22300E+02 8.50271E+05 + 5.22400E+02 1.13369E+06 + 5.22500E+02 1.41712E+06 + 5.22600E+02 1.70054E+06 + 5.22700E+02 1.98397E+06 + 5.22800E+02 2.26739E+06 + 5.22900E+02 2.55081E+06 + 5.23000E+02 2.83424E+06 + 5.23100E+02 3.11766E+06 + 5.23200E+02 3.40108E+06 + 5.23300E+02 3.68451E+06 + 5.23400E+02 3.96793E+06 + 5.23500E+02 4.25136E+06 + 5.23600E+02 4.53478E+06 + 5.23700E+02 4.81820E+06 + 5.23800E+02 5.10163E+06 + 5.23900E+02 5.38505E+06 + 5.24000E+02 5.66847E+06 + 5.24100E+02 5.95190E+06 + 5.24200E+02 6.23532E+06 + 5.24300E+02 6.51875E+06 + 5.24400E+02 6.80217E+06 + 5.24500E+02 7.08559E+06 + 5.24600E+02 7.36902E+06 + 5.24700E+02 7.65244E+06 + 5.24800E+02 7.93586E+06 + 5.24900E+02 8.21929E+06 + 5.25000E+02 8.50271E+06 + 5.25100E+02 8.50271E+06 + 5.25200E+02 7.55797E+06 + 5.25300E+02 6.61322E+06 + 5.25400E+02 5.66848E+06 + 5.25500E+02 4.72373E+06 + 5.25600E+02 3.77898E+06 + 5.25700E+02 2.83424E+06 + 5.25800E+02 1.88949E+06 + 5.25900E+02 9.44746E+05 + 5.26000E+02 0.00000E+00 + 5.26100E+02 0.00000E+00 + 5.26200E+02 0.00000E+00 + 5.26300E+02 0.00000E+00 + 5.26400E+02 0.00000E+00 + 5.26500E+02 0.00000E+00 + 5.26600E+02 0.00000E+00 + 5.26700E+02 0.00000E+00 + 5.26800E+02 0.00000E+00 + 5.26900E+02 0.00000E+00 + 5.27000E+02 0.00000E+00 + 5.27100E+02 0.00000E+00 + 5.27200E+02 0.00000E+00 + 5.27300E+02 0.00000E+00 + 5.27400E+02 0.00000E+00 + 5.27500E+02 0.00000E+00 + 5.27600E+02 0.00000E+00 + 5.27700E+02 0.00000E+00 + 5.27800E+02 0.00000E+00 + 5.27900E+02 0.00000E+00 + 5.28000E+02 0.00000E+00 + 5.28100E+02 2.83424E+05 + 5.28200E+02 5.66847E+05 + 5.28300E+02 8.50271E+05 + 5.28400E+02 1.13369E+06 + 5.28500E+02 1.41712E+06 + 5.28600E+02 1.70054E+06 + 5.28700E+02 1.98397E+06 + 5.28800E+02 2.26739E+06 + 5.28900E+02 2.55081E+06 + 5.29000E+02 2.83424E+06 + 5.29100E+02 3.11766E+06 + 5.29200E+02 3.40108E+06 + 5.29300E+02 3.68451E+06 + 5.29400E+02 3.96793E+06 + 5.29500E+02 4.25136E+06 + 5.29600E+02 4.53478E+06 + 5.29700E+02 4.81820E+06 + 5.29800E+02 5.10163E+06 + 5.29900E+02 5.38505E+06 + 5.30000E+02 5.66847E+06 + 5.30100E+02 5.95190E+06 + 5.30200E+02 6.23532E+06 + 5.30300E+02 6.51875E+06 + 5.30400E+02 6.80217E+06 + 5.30500E+02 7.08559E+06 + 5.30600E+02 7.36902E+06 + 5.30700E+02 7.65244E+06 + 5.30800E+02 7.93586E+06 + 5.30900E+02 8.21929E+06 + 5.31000E+02 8.50271E+06 + 5.31100E+02 8.50271E+06 + 5.31200E+02 7.55797E+06 + 5.31300E+02 6.61322E+06 + 5.31400E+02 5.66848E+06 + 5.31500E+02 4.72373E+06 + 5.31600E+02 3.77898E+06 + 5.31700E+02 2.83424E+06 + 5.31800E+02 1.88949E+06 + 5.31900E+02 9.44746E+05 + 5.32000E+02 0.00000E+00 + 5.32100E+02 0.00000E+00 + 5.32200E+02 0.00000E+00 + 5.32300E+02 0.00000E+00 + 5.32400E+02 0.00000E+00 + 5.32500E+02 0.00000E+00 + 5.32600E+02 0.00000E+00 + 5.32700E+02 0.00000E+00 + 5.32800E+02 0.00000E+00 + 5.32900E+02 0.00000E+00 + 5.33000E+02 0.00000E+00 + 5.33100E+02 0.00000E+00 + 5.33200E+02 0.00000E+00 + 5.33300E+02 0.00000E+00 + 5.33400E+02 0.00000E+00 + 5.33500E+02 0.00000E+00 + 5.33600E+02 0.00000E+00 + 5.33700E+02 0.00000E+00 + 5.33800E+02 0.00000E+00 + 5.33900E+02 0.00000E+00 + 5.34000E+02 0.00000E+00 + 5.34100E+02 2.83424E+05 + 5.34200E+02 5.66847E+05 + 5.34300E+02 8.50271E+05 + 5.34400E+02 1.13369E+06 + 5.34500E+02 1.41712E+06 + 5.34600E+02 1.70054E+06 + 5.34700E+02 1.98397E+06 + 5.34800E+02 2.26739E+06 + 5.34900E+02 2.55081E+06 + 5.35000E+02 2.83424E+06 + 5.35100E+02 3.11766E+06 + 5.35200E+02 3.40108E+06 + 5.35300E+02 3.68451E+06 + 5.35400E+02 3.96793E+06 + 5.35500E+02 4.25136E+06 + 5.35600E+02 4.53478E+06 + 5.35700E+02 4.81820E+06 + 5.35800E+02 5.10163E+06 + 5.35900E+02 5.38505E+06 + 5.36000E+02 5.66847E+06 + 5.36100E+02 5.95190E+06 + 5.36200E+02 6.23532E+06 + 5.36300E+02 6.51875E+06 + 5.36400E+02 6.80217E+06 + 5.36500E+02 7.08559E+06 + 5.36600E+02 7.36902E+06 + 5.36700E+02 7.65244E+06 + 5.36800E+02 7.93586E+06 + 5.36900E+02 8.21929E+06 + 5.37000E+02 8.50271E+06 + 5.37100E+02 8.50271E+06 + 5.37200E+02 7.55797E+06 + 5.37300E+02 6.61322E+06 + 5.37400E+02 5.66848E+06 + 5.37500E+02 4.72373E+06 + 5.37600E+02 3.77898E+06 + 5.37700E+02 2.83424E+06 + 5.37800E+02 1.88949E+06 + 5.37900E+02 9.44746E+05 + 5.38000E+02 0.00000E+00 + 5.38100E+02 0.00000E+00 + 5.38200E+02 0.00000E+00 + 5.38300E+02 0.00000E+00 + 5.38400E+02 0.00000E+00 + 5.38500E+02 0.00000E+00 + 5.38600E+02 0.00000E+00 + 5.38700E+02 0.00000E+00 + 5.38800E+02 0.00000E+00 + 5.38900E+02 0.00000E+00 + 5.39000E+02 0.00000E+00 + 5.39100E+02 0.00000E+00 + 5.39200E+02 0.00000E+00 + 5.39300E+02 0.00000E+00 + 5.39400E+02 0.00000E+00 + 5.39500E+02 0.00000E+00 + 5.39600E+02 0.00000E+00 + 5.39700E+02 0.00000E+00 + 5.39800E+02 0.00000E+00 + 5.39900E+02 0.00000E+00 + 5.40000E+02 0.00000E+00 + 5.40100E+02 2.83424E+05 + 5.40200E+02 5.66847E+05 + 5.40300E+02 8.50271E+05 + 5.40400E+02 1.13369E+06 + 5.40500E+02 1.41712E+06 + 5.40600E+02 1.70054E+06 + 5.40700E+02 1.98397E+06 + 5.40800E+02 2.26739E+06 + 5.40900E+02 2.55081E+06 + 5.41000E+02 2.83424E+06 + 5.41100E+02 3.11766E+06 + 5.41200E+02 3.40108E+06 + 5.41300E+02 3.68451E+06 + 5.41400E+02 3.96793E+06 + 5.41500E+02 4.25136E+06 + 5.41600E+02 4.53478E+06 + 5.41700E+02 4.81820E+06 + 5.41800E+02 5.10163E+06 + 5.41900E+02 5.38505E+06 + 5.42000E+02 5.66847E+06 + 5.42100E+02 5.95190E+06 + 5.42200E+02 6.23532E+06 + 5.42300E+02 6.51875E+06 + 5.42400E+02 6.80217E+06 + 5.42500E+02 7.08559E+06 + 5.42600E+02 7.36902E+06 + 5.42700E+02 7.65244E+06 + 5.42800E+02 7.93586E+06 + 5.42900E+02 8.21929E+06 + 5.43000E+02 8.50271E+06 + 5.43100E+02 8.50271E+06 + 5.43200E+02 7.55797E+06 + 5.43300E+02 6.61322E+06 + 5.43400E+02 5.66848E+06 + 5.43500E+02 4.72373E+06 + 5.43600E+02 3.77898E+06 + 5.43700E+02 2.83424E+06 + 5.43800E+02 1.88949E+06 + 5.43900E+02 9.44746E+05 + 5.44000E+02 0.00000E+00 + 5.44100E+02 0.00000E+00 + 5.44200E+02 0.00000E+00 + 5.44300E+02 0.00000E+00 + 5.44400E+02 0.00000E+00 + 5.44500E+02 0.00000E+00 + 5.44600E+02 0.00000E+00 + 5.44700E+02 0.00000E+00 + 5.44800E+02 0.00000E+00 + 5.44900E+02 0.00000E+00 + 5.45000E+02 0.00000E+00 + 5.45100E+02 0.00000E+00 + 5.45200E+02 0.00000E+00 + 5.45300E+02 0.00000E+00 + 5.45400E+02 0.00000E+00 + 5.45500E+02 0.00000E+00 + 5.45600E+02 0.00000E+00 + 5.45700E+02 0.00000E+00 + 5.45800E+02 0.00000E+00 + 5.45900E+02 0.00000E+00 + 5.46000E+02 0.00000E+00 + 5.46100E+02 2.83424E+05 + 5.46200E+02 5.66847E+05 + 5.46300E+02 8.50271E+05 + 5.46400E+02 1.13369E+06 + 5.46500E+02 1.41712E+06 + 5.46600E+02 1.70054E+06 + 5.46700E+02 1.98397E+06 + 5.46800E+02 2.26739E+06 + 5.46900E+02 2.55081E+06 + 5.47000E+02 2.83424E+06 + 5.47100E+02 3.11766E+06 + 5.47200E+02 3.40108E+06 + 5.47300E+02 3.68451E+06 + 5.47400E+02 3.96793E+06 + 5.47500E+02 4.25136E+06 + 5.47600E+02 4.53478E+06 + 5.47700E+02 4.81820E+06 + 5.47800E+02 5.10163E+06 + 5.47900E+02 5.38505E+06 + 5.48000E+02 5.66847E+06 + 5.48100E+02 5.95190E+06 + 5.48200E+02 6.23532E+06 + 5.48300E+02 6.51875E+06 + 5.48400E+02 6.80217E+06 + 5.48500E+02 7.08559E+06 + 5.48600E+02 7.36902E+06 + 5.48700E+02 7.65244E+06 + 5.48800E+02 7.93586E+06 + 5.48900E+02 8.21929E+06 + 5.49000E+02 8.50271E+06 + 5.49100E+02 8.50271E+06 + 5.49200E+02 7.55797E+06 + 5.49300E+02 6.61322E+06 + 5.49400E+02 5.66848E+06 + 5.49500E+02 4.72373E+06 + 5.49600E+02 3.77898E+06 + 5.49700E+02 2.83424E+06 + 5.49800E+02 1.88949E+06 + 5.49900E+02 9.44746E+05 + 5.50000E+02 0.00000E+00 + 5.50100E+02 0.00000E+00 + 5.50200E+02 0.00000E+00 + 5.50300E+02 0.00000E+00 + 5.50400E+02 0.00000E+00 + 5.50500E+02 0.00000E+00 + 5.50600E+02 0.00000E+00 + 5.50700E+02 0.00000E+00 + 5.50800E+02 0.00000E+00 + 5.50900E+02 0.00000E+00 + 5.51000E+02 0.00000E+00 + 5.51100E+02 0.00000E+00 + 5.51200E+02 0.00000E+00 + 5.51300E+02 0.00000E+00 + 5.51400E+02 0.00000E+00 + 5.51500E+02 0.00000E+00 + 5.51600E+02 0.00000E+00 + 5.51700E+02 0.00000E+00 + 5.51800E+02 0.00000E+00 + 5.51900E+02 0.00000E+00 + 5.52000E+02 0.00000E+00 + 5.52100E+02 2.83424E+05 + 5.52200E+02 5.66847E+05 + 5.52300E+02 8.50271E+05 + 5.52400E+02 1.13369E+06 + 5.52500E+02 1.41712E+06 + 5.52600E+02 1.70054E+06 + 5.52700E+02 1.98397E+06 + 5.52800E+02 2.26739E+06 + 5.52900E+02 2.55081E+06 + 5.53000E+02 2.83424E+06 + 5.53100E+02 3.11766E+06 + 5.53200E+02 3.40108E+06 + 5.53300E+02 3.68451E+06 + 5.53400E+02 3.96793E+06 + 5.53500E+02 4.25136E+06 + 5.53600E+02 4.53478E+06 + 5.53700E+02 4.81820E+06 + 5.53800E+02 5.10163E+06 + 5.53900E+02 5.38505E+06 + 5.54000E+02 5.66847E+06 + 5.54100E+02 5.95190E+06 + 5.54200E+02 6.23532E+06 + 5.54300E+02 6.51875E+06 + 5.54400E+02 6.80217E+06 + 5.54500E+02 7.08559E+06 + 5.54600E+02 7.36902E+06 + 5.54700E+02 7.65244E+06 + 5.54800E+02 7.93586E+06 + 5.54900E+02 8.21929E+06 + 5.55000E+02 8.50271E+06 + 5.55100E+02 8.50271E+06 + 5.55200E+02 7.55797E+06 + 5.55300E+02 6.61322E+06 + 5.55400E+02 5.66848E+06 + 5.55500E+02 4.72373E+06 + 5.55600E+02 3.77898E+06 + 5.55700E+02 2.83424E+06 + 5.55800E+02 1.88949E+06 + 5.55900E+02 9.44746E+05 + 5.56000E+02 0.00000E+00 + 5.56100E+02 0.00000E+00 + 5.56200E+02 0.00000E+00 + 5.56300E+02 0.00000E+00 + 5.56400E+02 0.00000E+00 + 5.56500E+02 0.00000E+00 + 5.56600E+02 0.00000E+00 + 5.56700E+02 0.00000E+00 + 5.56800E+02 0.00000E+00 + 5.56900E+02 0.00000E+00 + 5.57000E+02 0.00000E+00 + 5.57100E+02 0.00000E+00 + 5.57200E+02 0.00000E+00 + 5.57300E+02 0.00000E+00 + 5.57400E+02 0.00000E+00 + 5.57500E+02 0.00000E+00 + 5.57600E+02 0.00000E+00 + 5.57700E+02 0.00000E+00 + 5.57800E+02 0.00000E+00 + 5.57900E+02 0.00000E+00 + 5.58000E+02 0.00000E+00 + 5.58100E+02 2.83424E+05 + 5.58200E+02 5.66847E+05 + 5.58300E+02 8.50271E+05 + 5.58400E+02 1.13369E+06 + 5.58500E+02 1.41712E+06 + 5.58600E+02 1.70054E+06 + 5.58700E+02 1.98397E+06 + 5.58800E+02 2.26739E+06 + 5.58900E+02 2.55081E+06 + 5.59000E+02 2.83424E+06 + 5.59100E+02 3.11766E+06 + 5.59200E+02 3.40108E+06 + 5.59300E+02 3.68451E+06 + 5.59400E+02 3.96793E+06 + 5.59500E+02 4.25136E+06 + 5.59600E+02 4.53478E+06 + 5.59700E+02 4.81820E+06 + 5.59800E+02 5.10163E+06 + 5.59900E+02 5.38505E+06 + 5.60000E+02 5.66847E+06 + 5.60100E+02 5.95190E+06 + 5.60200E+02 6.23532E+06 + 5.60300E+02 6.51875E+06 + 5.60400E+02 6.80217E+06 + 5.60500E+02 7.08559E+06 + 5.60600E+02 7.36902E+06 + 5.60700E+02 7.65244E+06 + 5.60800E+02 7.93586E+06 + 5.60900E+02 8.21929E+06 + 5.61000E+02 8.50271E+06 + 5.61100E+02 8.50271E+06 + 5.61200E+02 7.55797E+06 + 5.61300E+02 6.61322E+06 + 5.61400E+02 5.66848E+06 + 5.61500E+02 4.72373E+06 + 5.61600E+02 3.77898E+06 + 5.61700E+02 2.83424E+06 + 5.61800E+02 1.88949E+06 + 5.61900E+02 9.44746E+05 + 5.62000E+02 0.00000E+00 + 5.62100E+02 0.00000E+00 + 5.62200E+02 0.00000E+00 + 5.62300E+02 0.00000E+00 + 5.62400E+02 0.00000E+00 + 5.62500E+02 0.00000E+00 + 5.62600E+02 0.00000E+00 + 5.62700E+02 0.00000E+00 + 5.62800E+02 0.00000E+00 + 5.62900E+02 0.00000E+00 + 5.63000E+02 0.00000E+00 + 5.63100E+02 0.00000E+00 + 5.63200E+02 0.00000E+00 + 5.63300E+02 0.00000E+00 + 5.63400E+02 0.00000E+00 + 5.63500E+02 0.00000E+00 + 5.63600E+02 0.00000E+00 + 5.63700E+02 0.00000E+00 + 5.63800E+02 0.00000E+00 + 5.63900E+02 0.00000E+00 + 5.64000E+02 0.00000E+00 + 5.64100E+02 2.83424E+05 + 5.64200E+02 5.66847E+05 + 5.64300E+02 8.50271E+05 + 5.64400E+02 1.13369E+06 + 5.64500E+02 1.41712E+06 + 5.64600E+02 1.70054E+06 + 5.64700E+02 1.98397E+06 + 5.64800E+02 2.26739E+06 + 5.64900E+02 2.55081E+06 + 5.65000E+02 2.83424E+06 + 5.65100E+02 3.11766E+06 + 5.65200E+02 3.40108E+06 + 5.65300E+02 3.68451E+06 + 5.65400E+02 3.96793E+06 + 5.65500E+02 4.25136E+06 + 5.65600E+02 4.53478E+06 + 5.65700E+02 4.81820E+06 + 5.65800E+02 5.10163E+06 + 5.65900E+02 5.38505E+06 + 5.66000E+02 5.66847E+06 + 5.66100E+02 5.95190E+06 + 5.66200E+02 6.23532E+06 + 5.66300E+02 6.51875E+06 + 5.66400E+02 6.80217E+06 + 5.66500E+02 7.08559E+06 + 5.66600E+02 7.36902E+06 + 5.66700E+02 7.65244E+06 + 5.66800E+02 7.93586E+06 + 5.66900E+02 8.21929E+06 + 5.67000E+02 8.50271E+06 + 5.67100E+02 8.50271E+06 + 5.67200E+02 7.55797E+06 + 5.67300E+02 6.61322E+06 + 5.67400E+02 5.66848E+06 + 5.67500E+02 4.72373E+06 + 5.67600E+02 3.77898E+06 + 5.67700E+02 2.83424E+06 + 5.67800E+02 1.88949E+06 + 5.67900E+02 9.44746E+05 + 5.68000E+02 0.00000E+00 + 5.68100E+02 0.00000E+00 + 5.68200E+02 0.00000E+00 + 5.68300E+02 0.00000E+00 + 5.68400E+02 0.00000E+00 + 5.68500E+02 0.00000E+00 + 5.68600E+02 0.00000E+00 + 5.68700E+02 0.00000E+00 + 5.68800E+02 0.00000E+00 + 5.68900E+02 0.00000E+00 + 5.69000E+02 0.00000E+00 + 5.69100E+02 0.00000E+00 + 5.69200E+02 0.00000E+00 + 5.69300E+02 0.00000E+00 + 5.69400E+02 0.00000E+00 + 5.69500E+02 0.00000E+00 + 5.69600E+02 0.00000E+00 + 5.69700E+02 0.00000E+00 + 5.69800E+02 0.00000E+00 + 5.69900E+02 0.00000E+00 + 5.70000E+02 0.00000E+00 + 5.70100E+02 2.83424E+05 + 5.70200E+02 5.66847E+05 + 5.70300E+02 8.50271E+05 + 5.70400E+02 1.13369E+06 + 5.70500E+02 1.41712E+06 + 5.70600E+02 1.70054E+06 + 5.70700E+02 1.98397E+06 + 5.70800E+02 2.26739E+06 + 5.70900E+02 2.55081E+06 + 5.71000E+02 2.83424E+06 + 5.71100E+02 3.11766E+06 + 5.71200E+02 3.40108E+06 + 5.71300E+02 3.68451E+06 + 5.71400E+02 3.96793E+06 + 5.71500E+02 4.25136E+06 + 5.71600E+02 4.53478E+06 + 5.71700E+02 4.81820E+06 + 5.71800E+02 5.10163E+06 + 5.71900E+02 5.38505E+06 + 5.72000E+02 5.66847E+06 + 5.72100E+02 5.95190E+06 + 5.72200E+02 6.23532E+06 + 5.72300E+02 6.51875E+06 + 5.72400E+02 6.80217E+06 + 5.72500E+02 7.08559E+06 + 5.72600E+02 7.36902E+06 + 5.72700E+02 7.65244E+06 + 5.72800E+02 7.93586E+06 + 5.72900E+02 8.21929E+06 + 5.73000E+02 8.50271E+06 + 5.73100E+02 8.50271E+06 + 5.73200E+02 7.55797E+06 + 5.73300E+02 6.61322E+06 + 5.73400E+02 5.66848E+06 + 5.73500E+02 4.72373E+06 + 5.73600E+02 3.77898E+06 + 5.73700E+02 2.83424E+06 + 5.73800E+02 1.88949E+06 + 5.73900E+02 9.44746E+05 + 5.74000E+02 0.00000E+00 + 5.74100E+02 0.00000E+00 + 5.74200E+02 0.00000E+00 + 5.74300E+02 0.00000E+00 + 5.74400E+02 0.00000E+00 + 5.74500E+02 0.00000E+00 + 5.74600E+02 0.00000E+00 + 5.74700E+02 0.00000E+00 + 5.74800E+02 0.00000E+00 + 5.74900E+02 0.00000E+00 + 5.75000E+02 0.00000E+00 + 5.75100E+02 0.00000E+00 + 5.75200E+02 0.00000E+00 + 5.75300E+02 0.00000E+00 + 5.75400E+02 0.00000E+00 + 5.75500E+02 0.00000E+00 + 5.75600E+02 0.00000E+00 + 5.75700E+02 0.00000E+00 + 5.75800E+02 0.00000E+00 + 5.75900E+02 0.00000E+00 + 5.76000E+02 0.00000E+00 + 5.76100E+02 2.83424E+05 + 5.76200E+02 5.66847E+05 + 5.76300E+02 8.50271E+05 + 5.76400E+02 1.13369E+06 + 5.76500E+02 1.41712E+06 + 5.76600E+02 1.70054E+06 + 5.76700E+02 1.98397E+06 + 5.76800E+02 2.26739E+06 + 5.76900E+02 2.55081E+06 + 5.77000E+02 2.83424E+06 + 5.77100E+02 3.11766E+06 + 5.77200E+02 3.40108E+06 + 5.77300E+02 3.68451E+06 + 5.77400E+02 3.96793E+06 + 5.77500E+02 4.25136E+06 + 5.77600E+02 4.53478E+06 + 5.77700E+02 4.81820E+06 + 5.77800E+02 5.10163E+06 + 5.77900E+02 5.38505E+06 + 5.78000E+02 5.66847E+06 + 5.78100E+02 5.95190E+06 + 5.78200E+02 6.23532E+06 + 5.78300E+02 6.51875E+06 + 5.78400E+02 6.80217E+06 + 5.78500E+02 7.08559E+06 + 5.78600E+02 7.36902E+06 + 5.78700E+02 7.65244E+06 + 5.78800E+02 7.93586E+06 + 5.78900E+02 8.21929E+06 + 5.79000E+02 8.50271E+06 + 5.79100E+02 8.50271E+06 + 5.79200E+02 7.55797E+06 + 5.79300E+02 6.61322E+06 + 5.79400E+02 5.66848E+06 + 5.79500E+02 4.72373E+06 + 5.79600E+02 3.77898E+06 + 5.79700E+02 2.83424E+06 + 5.79800E+02 1.88949E+06 + 5.79900E+02 9.44746E+05 + 5.80000E+02 0.00000E+00 + 5.80100E+02 0.00000E+00 + 5.80200E+02 0.00000E+00 + 5.80300E+02 0.00000E+00 + 5.80400E+02 0.00000E+00 + 5.80500E+02 0.00000E+00 + 5.80600E+02 0.00000E+00 + 5.80700E+02 0.00000E+00 + 5.80800E+02 0.00000E+00 + 5.80900E+02 0.00000E+00 + 5.81000E+02 0.00000E+00 + 5.81100E+02 0.00000E+00 + 5.81200E+02 0.00000E+00 + 5.81300E+02 0.00000E+00 + 5.81400E+02 0.00000E+00 + 5.81500E+02 0.00000E+00 + 5.81600E+02 0.00000E+00 + 5.81700E+02 0.00000E+00 + 5.81800E+02 0.00000E+00 + 5.81900E+02 0.00000E+00 + 5.82000E+02 0.00000E+00 + 5.82100E+02 2.83424E+05 + 5.82200E+02 5.66847E+05 + 5.82300E+02 8.50271E+05 + 5.82400E+02 1.13369E+06 + 5.82500E+02 1.41712E+06 + 5.82600E+02 1.70054E+06 + 5.82700E+02 1.98397E+06 + 5.82800E+02 2.26739E+06 + 5.82900E+02 2.55081E+06 + 5.83000E+02 2.83424E+06 + 5.83100E+02 3.11766E+06 + 5.83200E+02 3.40108E+06 + 5.83300E+02 3.68451E+06 + 5.83400E+02 3.96793E+06 + 5.83500E+02 4.25136E+06 + 5.83600E+02 4.53478E+06 + 5.83700E+02 4.81820E+06 + 5.83800E+02 5.10163E+06 + 5.83900E+02 5.38505E+06 + 5.84000E+02 5.66847E+06 + 5.84100E+02 5.95190E+06 + 5.84200E+02 6.23532E+06 + 5.84300E+02 6.51875E+06 + 5.84400E+02 6.80217E+06 + 5.84500E+02 7.08559E+06 + 5.84600E+02 7.36902E+06 + 5.84700E+02 7.65244E+06 + 5.84800E+02 7.93586E+06 + 5.84900E+02 8.21929E+06 + 5.85000E+02 8.50271E+06 + 5.85100E+02 8.50271E+06 + 5.85200E+02 7.55797E+06 + 5.85300E+02 6.61322E+06 + 5.85400E+02 5.66848E+06 + 5.85500E+02 4.72373E+06 + 5.85600E+02 3.77898E+06 + 5.85700E+02 2.83424E+06 + 5.85800E+02 1.88949E+06 + 5.85900E+02 9.44746E+05 + 5.86000E+02 0.00000E+00 + 5.86100E+02 0.00000E+00 + 5.86200E+02 0.00000E+00 + 5.86300E+02 0.00000E+00 + 5.86400E+02 0.00000E+00 + 5.86500E+02 0.00000E+00 + 5.86600E+02 0.00000E+00 + 5.86700E+02 0.00000E+00 + 5.86800E+02 0.00000E+00 + 5.86900E+02 0.00000E+00 + 5.87000E+02 0.00000E+00 + 5.87100E+02 0.00000E+00 + 5.87200E+02 0.00000E+00 + 5.87300E+02 0.00000E+00 + 5.87400E+02 0.00000E+00 + 5.87500E+02 0.00000E+00 + 5.87600E+02 0.00000E+00 + 5.87700E+02 0.00000E+00 + 5.87800E+02 0.00000E+00 + 5.87900E+02 0.00000E+00 + 5.88000E+02 0.00000E+00 + 5.88100E+02 2.83424E+05 + 5.88200E+02 5.66847E+05 + 5.88300E+02 8.50271E+05 + 5.88400E+02 1.13369E+06 + 5.88500E+02 1.41712E+06 + 5.88600E+02 1.70054E+06 + 5.88700E+02 1.98397E+06 + 5.88800E+02 2.26739E+06 + 5.88900E+02 2.55081E+06 + 5.89000E+02 2.83424E+06 + 5.89100E+02 3.11766E+06 + 5.89200E+02 3.40108E+06 + 5.89300E+02 3.68451E+06 + 5.89400E+02 3.96793E+06 + 5.89500E+02 4.25136E+06 + 5.89600E+02 4.53478E+06 + 5.89700E+02 4.81820E+06 + 5.89800E+02 5.10163E+06 + 5.89900E+02 5.38505E+06 + 5.90000E+02 5.66847E+06 + 5.90100E+02 5.95190E+06 + 5.90200E+02 6.23532E+06 + 5.90300E+02 6.51875E+06 + 5.90400E+02 6.80217E+06 + 5.90500E+02 7.08559E+06 + 5.90600E+02 7.36902E+06 + 5.90700E+02 7.65244E+06 + 5.90800E+02 7.93586E+06 + 5.90900E+02 8.21929E+06 + 5.91000E+02 8.50271E+06 + 5.91100E+02 8.50271E+06 + 5.91200E+02 7.55797E+06 + 5.91300E+02 6.61322E+06 + 5.91400E+02 5.66848E+06 + 5.91500E+02 4.72373E+06 + 5.91600E+02 3.77898E+06 + 5.91700E+02 2.83424E+06 + 5.91800E+02 1.88949E+06 + 5.91900E+02 9.44746E+05 + 5.92000E+02 0.00000E+00 + 5.92100E+02 0.00000E+00 + 5.92200E+02 0.00000E+00 + 5.92300E+02 0.00000E+00 + 5.92400E+02 0.00000E+00 + 5.92500E+02 0.00000E+00 + 5.92600E+02 0.00000E+00 + 5.92700E+02 0.00000E+00 + 5.92800E+02 0.00000E+00 + 5.92900E+02 0.00000E+00 + 5.93000E+02 0.00000E+00 + 5.93100E+02 0.00000E+00 + 5.93200E+02 0.00000E+00 + 5.93300E+02 0.00000E+00 + 5.93400E+02 0.00000E+00 + 5.93500E+02 0.00000E+00 + 5.93600E+02 0.00000E+00 + 5.93700E+02 0.00000E+00 + 5.93800E+02 0.00000E+00 + 5.93900E+02 0.00000E+00 + 5.94000E+02 0.00000E+00 + 5.94100E+02 2.83424E+05 + 5.94200E+02 5.66847E+05 + 5.94300E+02 8.50271E+05 + 5.94400E+02 1.13369E+06 + 5.94500E+02 1.41712E+06 + 5.94600E+02 1.70054E+06 + 5.94700E+02 1.98397E+06 + 5.94800E+02 2.26739E+06 + 5.94900E+02 2.55081E+06 + 5.95000E+02 2.83424E+06 + 5.95100E+02 3.11766E+06 + 5.95200E+02 3.40108E+06 + 5.95300E+02 3.68451E+06 + 5.95400E+02 3.96793E+06 + 5.95500E+02 4.25136E+06 + 5.95600E+02 4.53478E+06 + 5.95700E+02 4.81820E+06 + 5.95800E+02 5.10163E+06 + 5.95900E+02 5.38505E+06 + 5.96000E+02 5.66847E+06 + 5.96100E+02 5.95190E+06 + 5.96200E+02 6.23532E+06 + 5.96300E+02 6.51875E+06 + 5.96400E+02 6.80217E+06 + 5.96500E+02 7.08559E+06 + 5.96600E+02 7.36902E+06 + 5.96700E+02 7.65244E+06 + 5.96800E+02 7.93586E+06 + 5.96900E+02 8.21929E+06 + 5.97000E+02 8.50271E+06 + 5.97100E+02 8.50271E+06 + 5.97200E+02 7.55797E+06 + 5.97300E+02 6.61322E+06 + 5.97400E+02 5.66848E+06 + 5.97500E+02 4.72373E+06 + 5.97600E+02 3.77898E+06 + 5.97700E+02 2.83424E+06 + 5.97800E+02 1.88949E+06 + 5.97900E+02 9.44746E+05 + 5.98000E+02 0.00000E+00 + 5.98100E+02 0.00000E+00 + 5.98200E+02 0.00000E+00 + 5.98300E+02 0.00000E+00 + 5.98400E+02 0.00000E+00 + 5.98500E+02 0.00000E+00 + 5.98600E+02 0.00000E+00 + 5.98700E+02 0.00000E+00 + 5.98800E+02 0.00000E+00 + 5.98900E+02 0.00000E+00 + 5.99000E+02 0.00000E+00 + 5.99100E+02 0.00000E+00 + 5.99200E+02 0.00000E+00 + 5.99300E+02 0.00000E+00 + 5.99400E+02 0.00000E+00 + 5.99500E+02 0.00000E+00 + 5.99600E+02 0.00000E+00 + 5.99700E+02 0.00000E+00 + 5.99800E+02 0.00000E+00 + 5.99900E+02 0.00000E+00 + 6.00000E+02 0.00000E+00 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.log b/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.log new file mode 100644 index 000000000..aac9d06f3 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_interCrush_ISO.log @@ -0,0 +1,29 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:25:30 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 2 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting common ice crushing input parameters + Reference ice strength = 2.20000E+06 Pascals + Reference ice thickness = 1 meters + Exponent for static load = -0.16 + + Setting parameters for intermittent crushing loads + Intermittent period = 6 seconds + Saw tooth rise time fraction = 0.5 + Saw tooth fall time fraction = 0.15 +** Global crushing load is: 8.50271E+06 Newtons. + + Intermittent ice crushing loads initialized + diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.dat b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.dat new file mode 100644 index 000000000..7631f8122 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 5.95539E+05 + 2.00000E-01 1.25401E+06 + 3.00000E-01 1.96229E+06 + 4.00000E-01 2.70266E+06 + 5.00000E-01 3.45389E+06 + 6.00000E-01 4.19274E+06 + 7.00000E-01 4.89551E+06 + 8.00000E-01 5.53968E+06 + 9.00000E-01 6.10549E+06 + 1.00000E+00 6.57747E+06 + 1.10000E+00 6.31420E+06 + 1.20000E+00 6.00535E+06 + 1.30000E+00 5.66416E+06 + 1.40000E+00 5.30524E+06 + 1.50000E+00 4.94396E+06 + 1.60000E+00 4.59580E+06 + 1.70000E+00 4.27568E+06 + 1.80000E+00 3.99731E+06 + 1.90000E+00 3.77262E+06 + 2.00000E+00 3.61122E+06 + 2.10000E+00 3.52004E+06 + 2.20000E+00 3.50298E+06 + 2.30000E+00 3.56076E+06 + 2.40000E+00 3.69093E+06 + 2.50000E+00 3.88789E+06 + 2.60000E+00 4.14321E+06 + 2.70000E+00 4.44596E+06 + 2.80000E+00 4.78317E+06 + 2.90000E+00 5.14038E+06 + 3.00000E+00 5.50230E+06 + 3.10000E+00 5.85342E+06 + 3.20000E+00 6.17871E+06 + 3.30000E+00 6.46422E+06 + 3.40000E+00 6.69773E+06 + 3.50000E+00 6.86924E+06 + 3.60000E+00 6.97138E+06 + 3.70000E+00 6.99980E+06 + 3.80000E+00 6.95328E+06 + 3.90000E+00 6.83380E+06 + 4.00000E+00 6.64648E+06 + 4.10000E+00 6.39935E+06 + 4.20000E+00 6.10300E+06 + 4.30000E+00 5.77012E+06 + 4.40000E+00 5.41496E+06 + 4.50000E+00 5.05276E+06 + 4.60000E+00 4.69901E+06 + 4.70000E+00 4.36888E+06 + 4.80000E+00 4.07651E+06 + 4.90000E+00 3.83442E+06 + 5.00000E+00 3.65298E+06 + 5.10000E+00 3.53996E+06 + 5.20000E+00 3.50021E+06 + 5.30000E+00 3.53543E+06 + 5.40000E+00 3.64412E+06 + 5.50000E+00 3.82160E+06 + 5.60000E+00 4.06029E+06 + 5.70000E+00 4.34996E+06 + 5.80000E+00 4.67819E+06 + 5.90000E+00 5.03093E+06 + 6.00000E+00 5.39306E+06 + 6.10000E+00 5.74908E+06 + 6.20000E+00 6.08373E+06 + 6.30000E+00 6.38267E+06 + 6.40000E+00 6.63311E+06 + 6.50000E+00 6.82431E+06 + 6.60000E+00 6.94808E+06 + 6.70000E+00 6.99911E+06 + 6.80000E+00 6.97523E+06 + 6.90000E+00 6.87746E+06 + 7.00000E+00 6.70998E+06 + 7.10000E+00 6.47997E+06 + 7.20000E+00 6.19728E+06 + 7.30000E+00 5.87402E+06 + 7.40000E+00 5.52404E+06 + 7.50000E+00 5.16234E+06 + 7.60000E+00 4.80439E+06 + 7.70000E+00 4.46556E+06 + 7.80000E+00 4.16033E+06 + 7.90000E+00 3.90180E+06 + 8.00000E+00 3.70103E+06 + 8.10000E+00 3.56663E+06 + 8.20000E+00 3.50436E+06 + 8.30000E+00 3.51687E+06 + 8.40000E+00 3.60364E+06 + 8.50000E+00 3.76095E+06 + 8.60000E+00 3.98206E+06 + 8.70000E+00 4.25750E+06 + 8.80000E+00 4.57547E+06 + 8.90000E+00 4.92234E+06 + 9.00000E+00 5.28326E+06 + 9.10000E+00 5.64276E+06 + 9.20000E+00 5.98546E+06 + 9.30000E+00 6.29666E+06 + 9.40000E+00 6.56303E+06 + 9.50000E+00 6.77317E+06 + 9.60000E+00 6.91807E+06 + 9.70000E+00 6.99152E+06 + 9.80000E+00 6.99038E+06 + 9.90000E+00 6.91470E+06 + 1.00000E+01 6.76772E+06 + 1.01000E+01 6.55573E+06 + 1.02000E+01 6.28782E+06 + 1.03000E+01 5.97546E+06 + 1.04000E+01 5.63204E+06 + 1.05000E+01 5.27226E+06 + 1.06000E+01 4.91154E+06 + 1.07000E+01 4.56533E+06 + 1.08000E+01 4.24846E+06 + 1.09000E+01 3.97451E+06 + 1.10000E+01 3.75520E+06 + 1.11000E+01 3.59995E+06 + 1.12000E+01 3.51539E+06 + 1.13000E+01 3.50515E+06 + 1.14000E+01 3.56967E+06 + 1.15000E+01 3.70618E+06 + 1.16000E+01 3.90884E+06 + 1.17000E+01 4.16896E+06 + 1.18000E+01 4.47541E+06 + 1.19000E+01 4.81504E+06 + 1.20000E+01 5.17332E+06 + 1.21000E+01 5.53490E+06 + 1.22000E+01 5.88428E+06 + 1.23000E+01 6.20651E+06 + 1.24000E+01 6.48777E+06 + 1.25000E+01 6.71602E+06 + 1.26000E+01 6.88148E+06 + 1.27000E+01 6.97706E+06 + 1.28000E+01 6.99866E+06 + 1.29000E+01 6.94537E+06 + 1.30000E+01 6.81947E+06 + 1.31000E+01 6.62634E+06 + 1.32000E+01 6.37426E+06 + 1.33000E+01 6.07404E+06 + 1.34000E+01 5.73852E+06 + 1.35000E+01 5.38209E+06 + 1.36000E+01 5.02002E+06 + 1.37000E+01 4.66780E+06 + 1.38000E+01 4.34054E+06 + 1.39000E+01 4.05225E+06 + 1.40000E+01 3.81528E+06 + 1.41000E+01 3.63978E+06 + 1.42000E+01 3.53327E+06 + 1.43000E+01 3.50032E+06 + 1.44000E+01 3.54233E+06 + 1.45000E+01 3.65750E+06 + 1.46000E+01 3.84091E+06 + 1.47000E+01 4.08469E+06 + 1.48000E+01 4.37840E+06 + 1.49000E+01 4.70946E+06 + 1.50000E+01 5.06369E+06 + 1.51000E+01 5.42591E+06 + 1.52000E+01 5.78061E+06 + 1.53000E+01 6.11259E+06 + 1.54000E+01 6.40763E+06 + 1.55000E+01 6.65308E+06 + 1.56000E+01 6.83845E+06 + 1.57000E+01 6.95578E+06 + 1.58000E+01 7.00005E+06 + 1.59000E+01 6.96936E+06 + 1.60000E+01 6.86503E+06 + 1.61000E+01 6.69152E+06 + 1.62000E+01 6.45628E+06 + 1.63000E+01 6.16937E+06 + 1.64000E+01 5.84309E+06 + 1.65000E+01 5.49141E+06 + 1.66000E+01 5.12940E+06 + 1.67000E+01 4.77257E+06 + 1.68000E+01 4.43621E+06 + 1.69000E+01 4.13471E+06 + 1.70000E+01 3.88101E+06 + 1.71000E+01 3.68596E+06 + 1.72000E+01 3.55793E+06 + 1.73000E+01 3.50239E+06 + 1.74000E+01 3.52173E+06 + 1.75000E+01 3.61511E+06 + 1.76000E+01 3.77854E+06 + 1.77000E+01 4.00502E+06 + 1.78000E+01 4.28484E+06 + 1.79000E+01 4.60602E+06 + 1.80000E+01 4.95480E+06 + 1.81000E+01 5.31624E+06 + 1.82000E+01 5.67485E+06 + 1.83000E+01 6.01526E+06 + 1.84000E+01 6.32291E+06 + 1.85000E+01 6.58462E+06 + 1.86000E+01 6.78915E+06 + 1.87000E+01 6.92777E+06 + 1.88000E+01 6.99452E+06 + 1.89000E+01 6.98656E+06 + 1.90000E+01 6.90421E+06 + 1.91000E+01 6.75101E+06 + 1.92000E+01 6.53352E+06 + 1.93000E+01 6.26107E+06 + 1.94000E+01 5.94531E+06 + 1.95000E+01 5.59977E+06 + 1.96000E+01 5.23926E+06 + 1.97000E+01 4.87923E+06 + 1.98000E+01 4.53509E+06 + 1.99000E+01 4.22159E+06 + 2.00000E+01 3.95215E+06 + 2.01000E+01 3.73832E+06 + 2.02000E+01 3.58926E+06 + 2.03000E+01 3.51136E+06 + 2.04000E+01 3.50795E+06 + 2.05000E+01 3.57917E+06 + 2.06000E+01 3.72199E+06 + 2.07000E+01 3.93027E+06 + 2.08000E+01 4.19509E+06 + 2.09000E+01 4.50512E+06 + 2.10000E+01 4.84707E+06 + 2.11000E+01 5.20630E+06 + 2.12000E+01 5.56741E+06 + 2.13000E+01 5.91492E+06 + 2.14000E+01 6.23397E+06 + 2.15000E+01 6.51088E+06 + 2.16000E+01 6.73378E+06 + 2.17000E+01 6.89314E+06 + 2.18000E+01 6.98211E+06 + 2.19000E+01 6.99690E+06 + 2.20000E+01 6.93687E+06 + 2.21000E+01 6.80458E+06 + 2.22000E+01 6.60571E+06 + 2.23000E+01 6.34878E+06 + 2.24000E+01 6.04479E+06 + 2.25000E+01 5.70676E+06 + 2.26000E+01 5.34917E+06 + 2.27000E+01 4.98735E+06 + 2.28000E+01 4.63680E+06 + 2.29000E+01 4.31252E+06 + 2.30000E+01 4.02841E+06 + 2.31000E+01 3.79664E+06 + 2.32000E+01 3.62715E+06 + 2.33000E+01 3.52719E+06 + 2.34000E+01 3.50104E+06 + 2.35000E+01 3.54983E+06 + 2.36000E+01 3.67146E+06 + 2.37000E+01 3.86072E+06 + 2.38000E+01 4.10950E+06 + 2.39000E+01 4.40716E+06 + 2.40000E+01 4.74094E+06 + 2.41000E+01 5.09652E+06 + 2.42000E+01 5.45871E+06 + 2.43000E+01 5.81195E+06 + 2.44000E+01 6.14114E+06 + 2.45000E+01 6.43216E+06 + 2.46000E+01 6.67256E+06 + 2.47000E+01 6.85202E+06 + 2.48000E+01 6.96287E+06 + 2.49000E+01 7.00036E+06 + 2.50000E+01 6.96287E+06 + 2.51000E+01 6.85202E+06 + 2.52000E+01 6.67255E+06 + 2.53000E+01 6.43216E+06 + 2.54000E+01 6.14113E+06 + 2.55000E+01 5.81194E+06 + 2.56000E+01 5.45869E+06 + 2.57000E+01 5.09651E+06 + 2.58000E+01 4.74092E+06 + 2.59000E+01 4.40715E+06 + 2.60000E+01 4.10949E+06 + 2.61000E+01 3.86071E+06 + 2.62000E+01 3.67145E+06 + 2.63000E+01 3.54982E+06 + 2.64000E+01 3.50104E+06 + 2.65000E+01 3.52719E+06 + 2.66000E+01 3.62716E+06 + 2.67000E+01 3.79666E+06 + 2.68000E+01 4.02842E+06 + 2.69000E+01 4.31253E+06 + 2.70000E+01 4.63681E+06 + 2.71000E+01 4.98737E+06 + 2.72000E+01 5.34919E+06 + 2.73000E+01 5.70677E+06 + 2.74000E+01 6.04480E+06 + 2.75000E+01 6.34879E+06 + 2.76000E+01 6.60572E+06 + 2.77000E+01 6.80459E+06 + 2.78000E+01 6.93687E+06 + 2.79000E+01 6.99690E+06 + 2.80000E+01 6.98211E+06 + 2.81000E+01 6.89313E+06 + 2.82000E+01 6.73378E+06 + 2.83000E+01 6.51087E+06 + 2.84000E+01 6.23396E+06 + 2.85000E+01 5.91491E+06 + 2.86000E+01 5.56739E+06 + 2.87000E+01 5.20627E+06 + 2.88000E+01 4.84706E+06 + 2.89000E+01 4.50511E+06 + 2.90000E+01 4.19508E+06 + 2.91000E+01 3.93025E+06 + 2.92000E+01 3.72198E+06 + 2.93000E+01 3.57917E+06 + 2.94000E+01 3.50794E+06 + 2.95000E+01 3.51136E+06 + 2.96000E+01 3.58927E+06 + 2.97000E+01 3.73833E+06 + 2.98000E+01 3.95216E+06 + 2.99000E+01 4.22159E+06 + 3.00000E+01 4.53510E+06 + 3.01000E+01 4.87924E+06 + 3.02000E+01 5.23928E+06 + 3.03000E+01 5.59978E+06 + 3.04000E+01 5.94532E+06 + 3.05000E+01 6.26108E+06 + 3.06000E+01 6.53354E+06 + 3.07000E+01 6.75102E+06 + 3.08000E+01 6.90421E+06 + 3.09000E+01 6.98656E+06 + 3.10000E+01 6.99452E+06 + 3.11000E+01 6.92776E+06 + 3.12000E+01 6.78915E+06 + 3.13000E+01 6.58461E+06 + 3.14000E+01 6.32291E+06 + 3.15000E+01 6.01525E+06 + 3.16000E+01 5.67483E+06 + 3.17000E+01 5.31622E+06 + 3.18000E+01 4.95479E+06 + 3.19000E+01 4.60601E+06 + 3.20000E+01 4.28482E+06 + 3.21000E+01 4.00501E+06 + 3.22000E+01 3.77854E+06 + 3.23000E+01 3.61510E+06 + 3.24000E+01 3.52172E+06 + 3.25000E+01 3.50239E+06 + 3.26000E+01 3.55793E+06 + 3.27000E+01 3.68597E+06 + 3.28000E+01 3.88102E+06 + 3.29000E+01 4.13472E+06 + 3.30000E+01 4.43622E+06 + 3.31000E+01 4.77259E+06 + 3.32000E+01 5.12942E+06 + 3.33000E+01 5.49142E+06 + 3.34000E+01 5.84310E+06 + 3.35000E+01 6.16938E+06 + 3.36000E+01 6.45629E+06 + 3.37000E+01 6.69152E+06 + 3.38000E+01 6.86503E+06 + 3.39000E+01 6.96936E+06 + 3.40000E+01 7.00005E+06 + 3.41000E+01 6.95578E+06 + 3.42000E+01 6.83844E+06 + 3.43000E+01 6.65307E+06 + 3.44000E+01 6.40761E+06 + 3.45000E+01 6.11257E+06 + 3.46000E+01 5.78060E+06 + 3.47000E+01 5.42590E+06 + 3.48000E+01 5.06368E+06 + 3.49000E+01 4.70946E+06 + 3.50000E+01 4.37838E+06 + 3.51000E+01 4.08468E+06 + 3.52000E+01 3.84091E+06 + 3.53000E+01 3.65750E+06 + 3.54000E+01 3.54232E+06 + 3.55000E+01 3.50032E+06 + 3.56000E+01 3.53327E+06 + 3.57000E+01 3.63978E+06 + 3.58000E+01 3.81529E+06 + 3.59000E+01 4.05226E+06 + 3.60000E+01 4.34055E+06 + 3.61000E+01 4.66781E+06 + 3.62000E+01 5.02003E+06 + 3.63000E+01 5.38212E+06 + 3.64000E+01 5.73853E+06 + 3.65000E+01 6.07406E+06 + 3.66000E+01 6.37428E+06 + 3.67000E+01 6.62635E+06 + 3.68000E+01 6.81947E+06 + 3.69000E+01 6.94538E+06 + 3.70000E+01 6.99867E+06 + 3.71000E+01 6.97705E+06 + 3.72000E+01 6.88147E+06 + 3.73000E+01 6.71601E+06 + 3.74000E+01 6.48776E+06 + 3.75000E+01 6.20650E+06 + 3.76000E+01 5.88427E+06 + 3.77000E+01 5.53489E+06 + 3.78000E+01 5.17330E+06 + 3.79000E+01 4.81504E+06 + 3.80000E+01 4.47539E+06 + 3.81000E+01 4.16895E+06 + 3.82000E+01 3.90883E+06 + 3.83000E+01 3.70618E+06 + 3.84000E+01 3.56967E+06 + 3.85000E+01 3.50515E+06 + 3.86000E+01 3.51539E+06 + 3.87000E+01 3.59995E+06 + 3.88000E+01 3.75521E+06 + 3.89000E+01 3.97452E+06 + 3.90000E+01 4.24848E+06 + 3.91000E+01 4.56534E+06 + 3.92000E+01 4.91154E+06 + 3.93000E+01 5.27228E+06 + 3.94000E+01 5.63205E+06 + 3.95000E+01 5.97547E+06 + 3.96000E+01 6.28783E+06 + 3.97000E+01 6.55574E+06 + 3.98000E+01 6.76773E+06 + 3.99000E+01 6.91470E+06 + 4.00000E+01 6.99038E+06 + 4.01000E+01 6.99152E+06 + 4.02000E+01 6.91807E+06 + 4.03000E+01 6.77316E+06 + 4.04000E+01 6.56302E+06 + 4.05000E+01 6.29664E+06 + 4.06000E+01 5.98545E+06 + 4.07000E+01 5.64276E+06 + 4.08000E+01 5.28324E+06 + 4.09000E+01 4.92232E+06 + 4.10000E+01 4.57545E+06 + 4.11000E+01 4.25749E+06 + 4.12000E+01 3.98205E+06 + 4.13000E+01 3.76094E+06 + 4.14000E+01 3.60364E+06 + 4.15000E+01 3.51687E+06 + 4.16000E+01 3.50436E+06 + 4.17000E+01 3.56664E+06 + 4.18000E+01 3.70104E+06 + 4.19000E+01 3.90181E+06 + 4.20000E+01 4.16035E+06 + 4.21000E+01 4.46557E+06 + 4.22000E+01 4.80440E+06 + 4.23000E+01 5.16235E+06 + 4.24000E+01 5.52405E+06 + 4.25000E+01 5.87404E+06 + 4.26000E+01 6.19729E+06 + 4.27000E+01 6.47997E+06 + 4.28000E+01 6.70999E+06 + 4.29000E+01 6.87746E+06 + 4.30000E+01 6.97524E+06 + 4.31000E+01 6.99911E+06 + 4.32000E+01 6.94807E+06 + 4.33000E+01 6.82430E+06 + 4.34000E+01 6.63310E+06 + 4.35000E+01 6.38266E+06 + 4.36000E+01 6.08371E+06 + 4.37000E+01 5.74908E+06 + 4.38000E+01 5.39305E+06 + 4.39000E+01 5.03091E+06 + 4.40000E+01 4.67816E+06 + 4.41000E+01 4.34995E+06 + 4.42000E+01 4.06028E+06 + 4.43000E+01 3.82159E+06 + 4.44000E+01 3.64411E+06 + 4.45000E+01 3.53543E+06 + 4.46000E+01 3.50021E+06 + 4.47000E+01 3.53996E+06 + 4.48000E+01 3.65298E+06 + 4.49000E+01 3.83442E+06 + 4.50000E+01 4.07652E+06 + 4.51000E+01 4.36890E+06 + 4.52000E+01 4.69901E+06 + 4.53000E+01 5.05277E+06 + 4.54000E+01 5.41498E+06 + 4.55000E+01 5.77014E+06 + 4.56000E+01 6.10300E+06 + 4.57000E+01 6.39936E+06 + 4.58000E+01 6.64649E+06 + 4.59000E+01 6.83380E+06 + 4.60000E+01 6.95328E+06 + 4.61000E+01 6.99980E+06 + 4.62000E+01 6.97138E+06 + 4.63000E+01 6.86923E+06 + 4.64000E+01 6.69773E+06 + 4.65000E+01 6.46421E+06 + 4.66000E+01 6.17870E+06 + 4.67000E+01 5.85341E+06 + 4.68000E+01 5.50229E+06 + 4.69000E+01 5.14037E+06 + 4.70000E+01 4.78315E+06 + 4.71000E+01 4.44594E+06 + 4.72000E+01 4.14321E+06 + 4.73000E+01 3.88788E+06 + 4.74000E+01 3.69092E+06 + 4.75000E+01 3.56076E+06 + 4.76000E+01 3.50298E+06 + 4.77000E+01 3.52004E+06 + 4.78000E+01 3.61123E+06 + 4.79000E+01 3.77263E+06 + 4.80000E+01 3.99733E+06 + 4.81000E+01 4.27570E+06 + 4.82000E+01 4.59582E+06 + 4.83000E+01 4.94397E+06 + 4.84000E+01 5.30525E+06 + 4.85000E+01 5.66418E+06 + 4.86000E+01 6.00537E+06 + 4.87000E+01 6.31420E+06 + 4.88000E+01 6.57748E+06 + 4.89000E+01 6.78389E+06 + 4.90000E+01 6.92461E+06 + 4.91000E+01 6.99359E+06 + 4.92000E+01 6.98790E+06 + 4.93000E+01 6.90777E+06 + 4.94000E+01 6.75664E+06 + 4.95000E+01 6.54097E+06 + 4.96000E+01 6.27002E+06 + 4.97000E+01 5.95538E+06 + 4.98000E+01 5.61052E+06 + 4.99000E+01 5.25026E+06 + 5.00000E+01 4.88997E+06 + 5.01000E+01 4.54513E+06 + 5.02000E+01 4.23050E+06 + 5.03000E+01 3.95955E+06 + 5.04000E+01 3.74389E+06 + 5.05000E+01 3.59275E+06 + 5.06000E+01 3.51263E+06 + 5.07000E+01 3.50695E+06 + 5.08000E+01 3.57594E+06 + 5.09000E+01 3.71666E+06 + 5.10000E+01 3.92308E+06 + 5.11000E+01 4.18634E+06 + 5.12000E+01 4.49519E+06 + 5.13000E+01 4.83639E+06 + 5.14000E+01 5.19530E+06 + 5.15000E+01 5.55659E+06 + 5.16000E+01 5.90474E+06 + 5.17000E+01 6.22486E+06 + 5.18000E+01 6.50323E+06 + 5.19000E+01 6.72792E+06 + 5.20000E+01 6.88932E+06 + 5.21000E+01 6.98050E+06 + 5.22000E+01 6.99756E+06 + 5.23000E+01 6.93977E+06 + 5.24000E+01 6.80960E+06 + 5.25000E+01 6.61263E+06 + 5.26000E+01 6.35731E+06 + 5.27000E+01 6.05457E+06 + 5.28000E+01 5.71735E+06 + 5.29000E+01 5.36014E+06 + 5.30000E+01 4.99822E+06 + 5.31000E+01 4.64710E+06 + 5.32000E+01 4.32182E+06 + 5.33000E+01 4.03630E+06 + 5.34000E+01 3.80280E+06 + 5.35000E+01 3.63129E+06 + 5.36000E+01 3.52915E+06 + 5.37000E+01 3.50073E+06 + 5.38000E+01 3.54726E+06 + 5.39000E+01 3.66675E+06 + 5.40000E+01 3.85407E+06 + 5.41000E+01 4.10119E+06 + 5.42000E+01 4.39754E+06 + 5.43000E+01 4.73044E+06 + 5.44000E+01 5.08559E+06 + 5.45000E+01 5.44779E+06 + 5.46000E+01 5.80154E+06 + 5.47000E+01 6.13166E+06 + 5.48000E+01 6.42404E+06 + 5.49000E+01 6.66612E+06 + 5.50000E+01 6.84757E+06 + 5.51000E+01 6.96058E+06 + 5.52000E+01 7.00032E+06 + 5.53000E+01 6.96510E+06 + 5.54000E+01 6.85642E+06 + 5.55000E+01 6.67892E+06 + 5.56000E+01 6.44023E+06 + 5.57000E+01 6.15058E+06 + 5.58000E+01 5.82233E+06 + 5.59000E+01 5.46960E+06 + 5.60000E+01 5.10745E+06 + 5.61000E+01 4.75145E+06 + 5.62000E+01 4.41680E+06 + 5.63000E+01 4.11785E+06 + 5.64000E+01 3.86742E+06 + 5.65000E+01 3.67622E+06 + 5.66000E+01 3.55246E+06 + 5.67000E+01 3.50142E+06 + 5.68000E+01 3.52530E+06 + 5.69000E+01 3.62308E+06 + 5.70000E+01 3.79057E+06 + 5.71000E+01 4.02058E+06 + 5.72000E+01 4.30326E+06 + 5.73000E+01 4.62653E+06 + 5.74000E+01 4.97651E+06 + 5.75000E+01 5.33823E+06 + 5.76000E+01 5.69615E+06 + 5.77000E+01 6.03499E+06 + 5.78000E+01 6.34022E+06 + 5.79000E+01 6.59875E+06 + 5.80000E+01 6.79951E+06 + 5.81000E+01 6.93391E+06 + 5.82000E+01 6.99618E+06 + 5.83000E+01 6.98366E+06 + 5.84000E+01 6.89689E+06 + 5.85000E+01 6.73957E+06 + 5.86000E+01 6.51846E+06 + 5.87000E+01 6.24304E+06 + 5.88000E+01 5.92506E+06 + 5.89000E+01 5.57819E+06 + 5.90000E+01 5.21726E+06 + 5.91000E+01 4.85776E+06 + 5.92000E+01 4.51507E+06 + 5.93000E+01 4.20386E+06 + 5.94000E+01 3.93749E+06 + 5.95000E+01 3.72736E+06 + 5.96000E+01 3.58246E+06 + 5.97000E+01 3.50901E+06 + 5.98000E+01 3.51016E+06 + 5.99000E+01 3.58584E+06 + 6.00000E+01 3.73283E+06 + 6.01000E+01 3.94482E+06 + 6.02000E+01 4.21273E+06 + 6.03000E+01 4.52509E+06 + 6.04000E+01 4.86851E+06 + 6.05000E+01 5.22830E+06 + 6.06000E+01 5.58902E+06 + 6.07000E+01 5.93521E+06 + 6.08000E+01 6.25209E+06 + 6.09000E+01 6.52604E+06 + 6.10000E+01 6.74534E+06 + 6.11000E+01 6.90059E+06 + 6.12000E+01 6.98515E+06 + 6.13000E+01 6.99538E+06 + 6.14000E+01 6.93087E+06 + 6.15000E+01 6.79435E+06 + 6.16000E+01 6.59169E+06 + 6.17000E+01 6.33158E+06 + 6.18000E+01 6.02512E+06 + 6.19000E+01 5.68547E+06 + 6.20000E+01 5.32721E+06 + 6.21000E+01 4.96562E+06 + 6.22000E+01 4.61625E+06 + 6.23000E+01 4.29401E+06 + 6.24000E+01 4.01277E+06 + 6.25000E+01 3.78451E+06 + 6.26000E+01 3.61905E+06 + 6.27000E+01 3.52348E+06 + 6.28000E+01 3.50187E+06 + 6.29000E+01 3.55516E+06 + 6.30000E+01 3.68107E+06 + 6.31000E+01 3.87421E+06 + 6.32000E+01 4.12628E+06 + 6.33000E+01 4.42652E+06 + 6.34000E+01 4.76202E+06 + 6.35000E+01 5.11846E+06 + 6.36000E+01 5.48052E+06 + 6.37000E+01 5.83275E+06 + 6.38000E+01 6.16002E+06 + 6.39000E+01 6.44830E+06 + 6.40000E+01 6.68526E+06 + 6.41000E+01 6.86077E+06 + 6.42000E+01 6.96727E+06 + 6.43000E+01 7.00022E+06 + 6.44000E+01 6.95820E+06 + 6.45000E+01 6.84303E+06 + 6.46000E+01 6.65960E+06 + 6.47000E+01 6.41583E+06 + 6.48000E+01 6.12213E+06 + 6.49000E+01 5.79105E+06 + 6.50000E+01 5.43684E+06 + 6.51000E+01 5.07461E+06 + 6.52000E+01 4.71990E+06 + 6.53000E+01 4.38794E+06 + 6.54000E+01 4.09289E+06 + 6.55000E+01 3.84745E+06 + 6.56000E+01 3.66208E+06 + 6.57000E+01 3.54475E+06 + 6.58000E+01 3.50049E+06 + 6.59000E+01 3.53118E+06 + 6.60000E+01 3.63551E+06 + 6.61000E+01 3.80903E+06 + 6.62000E+01 4.04428E+06 + 6.63000E+01 4.33119E+06 + 6.64000E+01 4.65745E+06 + 6.65000E+01 5.00914E+06 + 6.66000E+01 5.37116E+06 + 6.67000E+01 5.72797E+06 + 6.68000E+01 6.06435E+06 + 6.69000E+01 6.36583E+06 + 6.70000E+01 6.61952E+06 + 6.71000E+01 6.81459E+06 + 6.72000E+01 6.94261E+06 + 6.73000E+01 6.99815E+06 + 6.74000E+01 6.97881E+06 + 6.75000E+01 6.88543E+06 + 6.76000E+01 6.72197E+06 + 6.77000E+01 6.49550E+06 + 6.78000E+01 6.21569E+06 + 6.79000E+01 5.89450E+06 + 6.80000E+01 5.54574E+06 + 6.81000E+01 5.18426E+06 + 6.82000E+01 4.82567E+06 + 6.83000E+01 4.48526E+06 + 6.84000E+01 4.17761E+06 + 6.85000E+01 3.91592E+06 + 6.86000E+01 3.71138E+06 + 6.87000E+01 3.57276E+06 + 6.88000E+01 3.50601E+06 + 6.89000E+01 3.51398E+06 + 6.90000E+01 3.59633E+06 + 6.91000E+01 3.74953E+06 + 6.92000E+01 3.96703E+06 + 6.93000E+01 4.23948E+06 + 6.94000E+01 4.55523E+06 + 6.95000E+01 4.90077E+06 + 6.96000E+01 5.26129E+06 + 6.97000E+01 5.62131E+06 + 6.98000E+01 5.96546E+06 + 6.99000E+01 6.27895E+06 + 7.00000E+01 6.54840E+06 + 7.01000E+01 6.76223E+06 + 7.02000E+01 6.91128E+06 + 7.03000E+01 6.98918E+06 + 7.04000E+01 6.99259E+06 + 7.05000E+01 6.92137E+06 + 7.06000E+01 6.77854E+06 + 7.07000E+01 6.57026E+06 + 7.08000E+01 6.30542E+06 + 7.09000E+01 5.99540E+06 + 7.10000E+01 5.65347E+06 + 7.11000E+01 5.29421E+06 + 7.12000E+01 4.93312E+06 + 7.13000E+01 4.58561E+06 + 7.14000E+01 4.26655E+06 + 7.15000E+01 3.98966E+06 + 7.16000E+01 3.76673E+06 + 7.17000E+01 3.60739E+06 + 7.18000E+01 3.51842E+06 + 7.19000E+01 3.50363E+06 + 7.20000E+01 3.56367E+06 + 7.21000E+01 3.69596E+06 + 7.22000E+01 3.89484E+06 + 7.23000E+01 4.15177E+06 + 7.24000E+01 4.45575E+06 + 7.25000E+01 4.79379E+06 + 7.26000E+01 5.15138E+06 + 7.27000E+01 5.51321E+06 + 7.28000E+01 5.86376E+06 + 7.29000E+01 6.18802E+06 + 7.30000E+01 6.47213E+06 + 7.31000E+01 6.70390E+06 + 7.32000E+01 6.87339E+06 + 7.33000E+01 6.97335E+06 + 7.34000E+01 6.99949E+06 + 7.35000E+01 6.95070E+06 + 7.36000E+01 6.82907E+06 + 7.37000E+01 6.63981E+06 + 7.38000E+01 6.39101E+06 + 7.39000E+01 6.09337E+06 + 7.40000E+01 5.75961E+06 + 7.41000E+01 5.40398E+06 + 7.42000E+01 5.04181E+06 + 7.43000E+01 4.68855E+06 + 7.44000E+01 4.35938E+06 + 7.45000E+01 4.06837E+06 + 7.46000E+01 3.82796E+06 + 7.47000E+01 3.64850E+06 + 7.48000E+01 3.53766E+06 + 7.49000E+01 3.50018E+06 + 7.50000E+01 3.53767E+06 + 7.51000E+01 3.64852E+06 + 7.52000E+01 3.82800E+06 + 7.53000E+01 4.06839E+06 + 7.54000E+01 4.35942E+06 + 7.55000E+01 4.68860E+06 + 7.56000E+01 5.04186E+06 + 7.57000E+01 5.40405E+06 + 7.58000E+01 5.75963E+06 + 7.59000E+01 6.09338E+06 + 7.60000E+01 6.39105E+06 + 7.61000E+01 6.63984E+06 + 7.62000E+01 6.82910E+06 + 7.63000E+01 6.95072E+06 + 7.64000E+01 6.99949E+06 + 7.65000E+01 6.97334E+06 + 7.66000E+01 6.87337E+06 + 7.67000E+01 6.70388E+06 + 7.68000E+01 6.47210E+06 + 7.69000E+01 6.18800E+06 + 7.70000E+01 5.86371E+06 + 7.71000E+01 5.51314E+06 + 7.72000E+01 5.15133E+06 + 7.73000E+01 4.79374E+06 + 7.74000E+01 4.45573E+06 + 7.75000E+01 4.15175E+06 + 7.76000E+01 3.89479E+06 + 7.77000E+01 3.69594E+06 + 7.78000E+01 3.56366E+06 + 7.79000E+01 3.50363E+06 + 7.80000E+01 3.51842E+06 + 7.81000E+01 3.60742E+06 + 7.82000E+01 3.76677E+06 + 7.83000E+01 3.98967E+06 + 7.84000E+01 4.26659E+06 + 7.85000E+01 4.58563E+06 + 7.86000E+01 4.93316E+06 + 7.87000E+01 5.29428E+06 + 7.88000E+01 5.65349E+06 + 7.89000E+01 5.99545E+06 + 7.90000E+01 6.30546E+06 + 7.91000E+01 6.57029E+06 + 7.92000E+01 6.77857E+06 + 7.93000E+01 6.92137E+06 + 7.94000E+01 6.99259E+06 + 7.95000E+01 6.98917E+06 + 7.96000E+01 6.91126E+06 + 7.97000E+01 6.76219E+06 + 7.98000E+01 6.54836E+06 + 7.99000E+01 6.27894E+06 + 8.00000E+01 5.96542E+06 + 8.01000E+01 5.62127E+06 + 8.02000E+01 5.26124E+06 + 8.03000E+01 4.90073E+06 + 8.04000E+01 4.55521E+06 + 8.05000E+01 4.23946E+06 + 8.06000E+01 3.96698E+06 + 8.07000E+01 3.74951E+06 + 8.08000E+01 3.59631E+06 + 8.09000E+01 3.51398E+06 + 8.10000E+01 3.50601E+06 + 8.11000E+01 3.57278E+06 + 8.12000E+01 3.71140E+06 + 8.13000E+01 3.91593E+06 + 8.14000E+01 4.17764E+06 + 8.15000E+01 4.48528E+06 + 8.16000E+01 4.82574E+06 + 8.17000E+01 5.18434E+06 + 8.18000E+01 5.54576E+06 + 8.19000E+01 5.89454E+06 + 8.20000E+01 6.21571E+06 + 8.21000E+01 6.49554E+06 + 8.22000E+01 6.72202E+06 + 8.23000E+01 6.88543E+06 + 8.24000E+01 6.97882E+06 + 8.25000E+01 6.99815E+06 + 8.26000E+01 6.94260E+06 + 8.27000E+01 6.81455E+06 + 8.28000E+01 6.61951E+06 + 8.29000E+01 6.36581E+06 + 8.30000E+01 6.06431E+06 + 8.31000E+01 5.72793E+06 + 8.32000E+01 5.37111E+06 + 8.33000E+01 5.00909E+06 + 8.34000E+01 4.65743E+06 + 8.35000E+01 4.33114E+06 + 8.36000E+01 4.04423E+06 + 8.37000E+01 3.80900E+06 + 8.38000E+01 3.63550E+06 + 8.39000E+01 3.53117E+06 + 8.40000E+01 3.50049E+06 + 8.41000E+01 3.54477E+06 + 8.42000E+01 3.66210E+06 + 8.43000E+01 3.84748E+06 + 8.44000E+01 4.09293E+06 + 8.45000E+01 4.38796E+06 + 8.46000E+01 4.71997E+06 + 8.47000E+01 5.07466E+06 + 8.48000E+01 5.43686E+06 + 8.49000E+01 5.79110E+06 + 8.50000E+01 6.12214E+06 + 8.51000E+01 6.41588E+06 + 8.52000E+01 6.65965E+06 + 8.53000E+01 6.84304E+06 + 8.54000E+01 6.95822E+06 + 8.55000E+01 7.00022E+06 + 8.56000E+01 6.96726E+06 + 8.57000E+01 6.86074E+06 + 8.58000E+01 6.68524E+06 + 8.59000E+01 6.44828E+06 + 8.60000E+01 6.15998E+06 + 8.61000E+01 5.83270E+06 + 8.62000E+01 5.48048E+06 + 8.63000E+01 5.11841E+06 + 8.64000E+01 4.76200E+06 + 8.65000E+01 4.42647E+06 + 8.66000E+01 4.12624E+06 + 8.67000E+01 3.87418E+06 + 8.68000E+01 3.68105E+06 + 8.69000E+01 3.55516E+06 + 8.70000E+01 3.50187E+06 + 8.71000E+01 3.52349E+06 + 8.72000E+01 3.61907E+06 + 8.73000E+01 3.78454E+06 + 8.74000E+01 4.01278E+06 + 8.75000E+01 4.29403E+06 + 8.76000E+01 4.61629E+06 + 8.77000E+01 4.96566E+06 + 8.78000E+01 5.32725E+06 + 8.79000E+01 5.68552E+06 + 8.80000E+01 6.02514E+06 + 8.81000E+01 6.33161E+06 + 8.82000E+01 6.59172E+06 + 8.83000E+01 6.79436E+06 + 8.84000E+01 6.93088E+06 + 8.85000E+01 6.99539E+06 + 8.86000E+01 6.98514E+06 + 8.87000E+01 6.90057E+06 + 8.88000E+01 6.74532E+06 + 8.89000E+01 6.52601E+06 + 8.90000E+01 6.25206E+06 + 8.91000E+01 5.93518E+06 + 8.92000E+01 5.58896E+06 + 8.93000E+01 5.22825E+06 + 8.94000E+01 4.86849E+06 + 8.95000E+01 4.52506E+06 + 8.96000E+01 4.21269E+06 + 8.97000E+01 3.94478E+06 + 8.98000E+01 3.73280E+06 + 8.99000E+01 3.58583E+06 + 9.00000E+01 3.51015E+06 + 9.01000E+01 3.50902E+06 + 9.02000E+01 3.58248E+06 + 9.03000E+01 3.72738E+06 + 9.04000E+01 3.93752E+06 + 9.05000E+01 4.20388E+06 + 9.06000E+01 4.51512E+06 + 9.07000E+01 4.85780E+06 + 9.08000E+01 5.21732E+06 + 9.09000E+01 5.57822E+06 + 9.10000E+01 5.92508E+06 + 9.11000E+01 6.24308E+06 + 9.12000E+01 6.51850E+06 + 9.13000E+01 6.73959E+06 + 9.14000E+01 6.89690E+06 + 9.15000E+01 6.98366E+06 + 9.16000E+01 6.99618E+06 + 9.17000E+01 6.93389E+06 + 9.18000E+01 6.79949E+06 + 9.19000E+01 6.59872E+06 + 9.20000E+01 6.34019E+06 + 9.21000E+01 6.03496E+06 + 9.22000E+01 5.69610E+06 + 9.23000E+01 5.33818E+06 + 9.24000E+01 4.97646E+06 + 9.25000E+01 4.62650E+06 + 9.26000E+01 4.30323E+06 + 9.27000E+01 4.02054E+06 + 9.28000E+01 3.79054E+06 + 9.29000E+01 3.62307E+06 + 9.30000E+01 3.52530E+06 + 9.31000E+01 3.50142E+06 + 9.32000E+01 3.55247E+06 + 9.33000E+01 3.67624E+06 + 9.34000E+01 3.86743E+06 + 9.35000E+01 4.11788E+06 + 9.36000E+01 4.41684E+06 + 9.37000E+01 4.75148E+06 + 9.38000E+01 5.10751E+06 + 9.39000E+01 5.46963E+06 + 9.40000E+01 5.82235E+06 + 9.41000E+01 6.15062E+06 + 9.42000E+01 6.44027E+06 + 9.43000E+01 6.67896E+06 + 9.44000E+01 6.85643E+06 + 9.45000E+01 6.96510E+06 + 9.46000E+01 7.00032E+06 + 9.47000E+01 6.96057E+06 + 9.48000E+01 6.84755E+06 + 9.49000E+01 6.66610E+06 + 9.50000E+01 6.42402E+06 + 9.51000E+01 6.13161E+06 + 9.52000E+01 5.80149E+06 + 9.53000E+01 5.44776E+06 + 9.54000E+01 5.08554E+06 + 9.55000E+01 4.73040E+06 + 9.56000E+01 4.39751E+06 + 9.57000E+01 4.10116E+06 + 9.58000E+01 3.85404E+06 + 9.59000E+01 3.66672E+06 + 9.60000E+01 3.54725E+06 + 9.61000E+01 3.50073E+06 + 9.62000E+01 3.52916E+06 + 9.63000E+01 3.63131E+06 + 9.64000E+01 3.80281E+06 + 9.65000E+01 4.03633E+06 + 9.66000E+01 4.32186E+06 + 9.67000E+01 4.64713E+06 + 9.68000E+01 4.99827E+06 + 9.69000E+01 5.36017E+06 + 9.70000E+01 5.71740E+06 + 9.71000E+01 6.05461E+06 + 9.72000E+01 6.35734E+06 + 9.73000E+01 6.61267E+06 + 9.74000E+01 6.80962E+06 + 9.75000E+01 6.93977E+06 + 9.76000E+01 6.99756E+06 + 9.77000E+01 6.98049E+06 + 9.78000E+01 6.88930E+06 + 9.79000E+01 6.72790E+06 + 9.80000E+01 6.50321E+06 + 9.81000E+01 6.22481E+06 + 9.82000E+01 5.90470E+06 + 9.83000E+01 5.55656E+06 + 9.84000E+01 5.19527E+06 + 9.85000E+01 4.83636E+06 + 9.86000E+01 4.49513E+06 + 9.87000E+01 4.18631E+06 + 9.88000E+01 3.92305E+06 + 9.89000E+01 3.71664E+06 + 9.90000E+01 3.57593E+06 + 9.91000E+01 3.50694E+06 + 9.92000E+01 3.51264E+06 + 9.93000E+01 3.59277E+06 + 9.94000E+01 3.74390E+06 + 9.95000E+01 3.95957E+06 + 9.96000E+01 4.23053E+06 + 9.97000E+01 4.54519E+06 + 9.98000E+01 4.89002E+06 + 9.99000E+01 5.25028E+06 + 1.00000E+02 5.61057E+06 + 1.00100E+02 5.95542E+06 + 1.00200E+02 6.27005E+06 + 1.00300E+02 6.54100E+06 + 1.00400E+02 6.75665E+06 + 1.00500E+02 6.90778E+06 + 1.00600E+02 6.98791E+06 + 1.00700E+02 6.99359E+06 + 1.00800E+02 6.92459E+06 + 1.00900E+02 6.78387E+06 + 1.01000E+02 6.57746E+06 + 1.01100E+02 6.31416E+06 + 1.01200E+02 6.00533E+06 + 1.01300E+02 5.66412E+06 + 1.01400E+02 5.30521E+06 + 1.01500E+02 4.94395E+06 + 1.01600E+02 4.59576E+06 + 1.01700E+02 4.27566E+06 + 1.01800E+02 3.99730E+06 + 1.01900E+02 3.77260E+06 + 1.02000E+02 3.61122E+06 + 1.02100E+02 3.52003E+06 + 1.02200E+02 3.50298E+06 + 1.02300E+02 3.56077E+06 + 1.02400E+02 3.69094E+06 + 1.02500E+02 3.88790E+06 + 1.02600E+02 4.14324E+06 + 1.02700E+02 4.44600E+06 + 1.02800E+02 4.78319E+06 + 1.02900E+02 5.14039E+06 + 1.03000E+02 5.50232E+06 + 1.03100E+02 5.85346E+06 + 1.03200E+02 6.17875E+06 + 1.03300E+02 6.46425E+06 + 1.03400E+02 6.69774E+06 + 1.03500E+02 6.86925E+06 + 1.03600E+02 6.97139E+06 + 1.03700E+02 6.99980E+06 + 1.03800E+02 6.95327E+06 + 1.03900E+02 6.83379E+06 + 1.04000E+02 6.64648E+06 + 1.04100E+02 6.39932E+06 + 1.04200E+02 6.10297E+06 + 1.04300E+02 5.77008E+06 + 1.04400E+02 5.41494E+06 + 1.04500E+02 5.05275E+06 + 1.04600E+02 4.69897E+06 + 1.04700E+02 4.36885E+06 + 1.04800E+02 4.07650E+06 + 1.04900E+02 3.83440E+06 + 1.05000E+02 3.65297E+06 + 1.05100E+02 3.53995E+06 + 1.05200E+02 3.50021E+06 + 1.05300E+02 3.53544E+06 + 1.05400E+02 3.64413E+06 + 1.05500E+02 3.82161E+06 + 1.05600E+02 4.06031E+06 + 1.05700E+02 4.34999E+06 + 1.05800E+02 4.67821E+06 + 1.05900E+02 5.03096E+06 + 1.06000E+02 5.39308E+06 + 1.06100E+02 5.74911E+06 + 1.06200E+02 6.08377E+06 + 1.06300E+02 6.38270E+06 + 1.06400E+02 6.63312E+06 + 1.06500E+02 6.82432E+06 + 1.06600E+02 6.94808E+06 + 1.06700E+02 6.99912E+06 + 1.06800E+02 6.97523E+06 + 1.06900E+02 6.87745E+06 + 1.07000E+02 6.70996E+06 + 1.07100E+02 6.47994E+06 + 1.07200E+02 6.19726E+06 + 1.07300E+02 5.87399E+06 + 1.07400E+02 5.52402E+06 + 1.07500E+02 5.16233E+06 + 1.07600E+02 4.80435E+06 + 1.07700E+02 4.46553E+06 + 1.07800E+02 4.16030E+06 + 1.07900E+02 3.90178E+06 + 1.08000E+02 3.70103E+06 + 1.08100E+02 3.56662E+06 + 1.08200E+02 3.50435E+06 + 1.08300E+02 3.51687E+06 + 1.08400E+02 3.60365E+06 + 1.08500E+02 3.76096E+06 + 1.08600E+02 3.98210E+06 + 1.08700E+02 4.25753E+06 + 1.08800E+02 4.57548E+06 + 1.08900E+02 4.92237E+06 + 1.09000E+02 5.28327E+06 + 1.09100E+02 5.64279E+06 + 1.09200E+02 5.98549E+06 + 1.09300E+02 6.29668E+06 + 1.09400E+02 6.56304E+06 + 1.09500E+02 6.77318E+06 + 1.09600E+02 6.91808E+06 + 1.09700E+02 6.99153E+06 + 1.09800E+02 6.99038E+06 + 1.09900E+02 6.91470E+06 + 1.10000E+02 6.76771E+06 + 1.10100E+02 6.55571E+06 + 1.10200E+02 6.28780E+06 + 1.10300E+02 5.97543E+06 + 1.10400E+02 5.63202E+06 + 1.10500E+02 5.27223E+06 + 1.10600E+02 4.91150E+06 + 1.10700E+02 4.56530E+06 + 1.10800E+02 4.24843E+06 + 1.10900E+02 3.97449E+06 + 1.11000E+02 3.75520E+06 + 1.11100E+02 3.59993E+06 + 1.11200E+02 3.51539E+06 + 1.11300E+02 3.50515E+06 + 1.11400E+02 3.56968E+06 + 1.11500E+02 3.70619E+06 + 1.11600E+02 3.90887E+06 + 1.11700E+02 4.16899E+06 + 1.11800E+02 4.47542E+06 + 1.11900E+02 4.81507E+06 + 1.12000E+02 5.17334E+06 + 1.12100E+02 5.53495E+06 + 1.12200E+02 5.88432E+06 + 1.12300E+02 6.20653E+06 + 1.12400E+02 6.48779E+06 + 1.12500E+02 6.71603E+06 + 1.12600E+02 6.88149E+06 + 1.12700E+02 6.97706E+06 + 1.12800E+02 6.99866E+06 + 1.12900E+02 6.94537E+06 + 1.13000E+02 6.81946E+06 + 1.13100E+02 6.62632E+06 + 1.13200E+02 6.37423E+06 + 1.13300E+02 6.07401E+06 + 1.13400E+02 5.73851E+06 + 1.13500E+02 5.38207E+06 + 1.13600E+02 5.01998E+06 + 1.13700E+02 4.66778E+06 + 1.13800E+02 4.34051E+06 + 1.13900E+02 4.05223E+06 + 1.14000E+02 3.81526E+06 + 1.14100E+02 3.63976E+06 + 1.14200E+02 3.53327E+06 + 1.14300E+02 3.50032E+06 + 1.14400E+02 3.54233E+06 + 1.14500E+02 3.65751E+06 + 1.14600E+02 3.84094E+06 + 1.14700E+02 4.08471E+06 + 1.14800E+02 4.37842E+06 + 1.14900E+02 4.70949E+06 + 1.15000E+02 5.06370E+06 + 1.15100E+02 5.42596E+06 + 1.15200E+02 5.78064E+06 + 1.15300E+02 6.11260E+06 + 1.15400E+02 6.40765E+06 + 1.15500E+02 6.65309E+06 + 1.15600E+02 6.83846E+06 + 1.15700E+02 6.95579E+06 + 1.15800E+02 7.00005E+06 + 1.15900E+02 6.96935E+06 + 1.16000E+02 6.86502E+06 + 1.16100E+02 6.69150E+06 + 1.16200E+02 6.45625E+06 + 1.16300E+02 6.16934E+06 + 1.16400E+02 5.84308E+06 + 1.16500E+02 5.49139E+06 + 1.16600E+02 5.12937E+06 + 1.16700E+02 4.77253E+06 + 1.16800E+02 4.43618E+06 + 1.16900E+02 4.13470E+06 + 1.17000E+02 3.88099E+06 + 1.17100E+02 3.68595E+06 + 1.17200E+02 3.55792E+06 + 1.17300E+02 3.50239E+06 + 1.17400E+02 3.52173E+06 + 1.17500E+02 3.61511E+06 + 1.17600E+02 3.77856E+06 + 1.17700E+02 4.00504E+06 + 1.17800E+02 4.28487E+06 + 1.17900E+02 4.60604E+06 + 1.18000E+02 4.95481E+06 + 1.18100E+02 5.31628E+06 + 1.18200E+02 5.67487E+06 + 1.18300E+02 6.01528E+06 + 1.18400E+02 6.32293E+06 + 1.18500E+02 6.58462E+06 + 1.18600E+02 6.78918E+06 + 1.18700E+02 6.92778E+06 + 1.18800E+02 6.99452E+06 + 1.18900E+02 6.98655E+06 + 1.19000E+02 6.90421E+06 + 1.19100E+02 6.75100E+06 + 1.19200E+02 6.53350E+06 + 1.19300E+02 6.26105E+06 + 1.19400E+02 5.94528E+06 + 1.19500E+02 5.59975E+06 + 1.19600E+02 5.23924E+06 + 1.19700E+02 4.87919E+06 + 1.19800E+02 4.53507E+06 + 1.19900E+02 4.22158E+06 + 1.20000E+02 3.95213E+06 + 1.20100E+02 3.73830E+06 + 1.20200E+02 3.58925E+06 + 1.20300E+02 3.51136E+06 + 1.20400E+02 3.50795E+06 + 1.20500E+02 3.57918E+06 + 1.20600E+02 3.72200E+06 + 1.20700E+02 3.93028E+06 + 1.20800E+02 4.19512E+06 + 1.20900E+02 4.50514E+06 + 1.21000E+02 4.84708E+06 + 1.21100E+02 5.20634E+06 + 1.21200E+02 5.56743E+06 + 1.21300E+02 5.91496E+06 + 1.21400E+02 6.23399E+06 + 1.21500E+02 6.51088E+06 + 1.21600E+02 6.73381E+06 + 1.21700E+02 6.89315E+06 + 1.21800E+02 6.98212E+06 + 1.21900E+02 6.99690E+06 + 1.22000E+02 6.93686E+06 + 1.22100E+02 6.80456E+06 + 1.22200E+02 6.60569E+06 + 1.22300E+02 6.34876E+06 + 1.22400E+02 6.04476E+06 + 1.22500E+02 5.70674E+06 + 1.22600E+02 5.34915E+06 + 1.22700E+02 4.98732E+06 + 1.22800E+02 4.63677E+06 + 1.22900E+02 4.31251E+06 + 1.23000E+02 4.02840E+06 + 1.23100E+02 3.79663E+06 + 1.23200E+02 3.62714E+06 + 1.23300E+02 3.52719E+06 + 1.23400E+02 3.50104E+06 + 1.23500E+02 3.54983E+06 + 1.23600E+02 3.67147E+06 + 1.23700E+02 3.86073E+06 + 1.23800E+02 4.10951E+06 + 1.23900E+02 4.40720E+06 + 1.24000E+02 4.74096E+06 + 1.24100E+02 5.09654E+06 + 1.24200E+02 5.45876E+06 + 1.24300E+02 5.81199E+06 + 1.24400E+02 6.14116E+06 + 1.24500E+02 6.43217E+06 + 1.24600E+02 6.67258E+06 + 1.24700E+02 6.85204E+06 + 1.24800E+02 6.96288E+06 + 1.24900E+02 7.00036E+06 + 1.25000E+02 6.96286E+06 + 1.25100E+02 6.85201E+06 + 1.25200E+02 6.67252E+06 + 1.25300E+02 6.43212E+06 + 1.25400E+02 6.14111E+06 + 1.25500E+02 5.81193E+06 + 1.25600E+02 5.45864E+06 + 1.25700E+02 5.09648E+06 + 1.25800E+02 4.74090E+06 + 1.25900E+02 4.40714E+06 + 1.26000E+02 4.10950E+06 + 1.26100E+02 3.86069E+06 + 1.26200E+02 3.67144E+06 + 1.26300E+02 3.54981E+06 + 1.26400E+02 3.50104E+06 + 1.26500E+02 3.52720E+06 + 1.26600E+02 3.62718E+06 + 1.26700E+02 3.79668E+06 + 1.26800E+02 4.02844E+06 + 1.26900E+02 4.31254E+06 + 1.27000E+02 4.63681E+06 + 1.27100E+02 4.98740E+06 + 1.27200E+02 5.34921E+06 + 1.27300E+02 5.70678E+06 + 1.27400E+02 6.04484E+06 + 1.27500E+02 6.34881E+06 + 1.27600E+02 6.60573E+06 + 1.27700E+02 6.80461E+06 + 1.27800E+02 6.93688E+06 + 1.27900E+02 6.99691E+06 + 1.28000E+02 6.98210E+06 + 1.28100E+02 6.89314E+06 + 1.28200E+02 6.73376E+06 + 1.28300E+02 6.51082E+06 + 1.28400E+02 6.23396E+06 + 1.28500E+02 5.91487E+06 + 1.28600E+02 5.56736E+06 + 1.28700E+02 5.20627E+06 + 1.28800E+02 4.84702E+06 + 1.28900E+02 4.50508E+06 + 1.29000E+02 4.19503E+06 + 1.29100E+02 3.93026E+06 + 1.29200E+02 3.72196E+06 + 1.29300E+02 3.57914E+06 + 1.29400E+02 3.50794E+06 + 1.29500E+02 3.51136E+06 + 1.29600E+02 3.58928E+06 + 1.29700E+02 3.73834E+06 + 1.29800E+02 3.95219E+06 + 1.29900E+02 4.22163E+06 + 1.30000E+02 4.53512E+06 + 1.30100E+02 4.87925E+06 + 1.30200E+02 5.23932E+06 + 1.30300E+02 5.59982E+06 + 1.30400E+02 5.94533E+06 + 1.30500E+02 6.26112E+06 + 1.30600E+02 6.53352E+06 + 1.30700E+02 6.75103E+06 + 1.30800E+02 6.90424E+06 + 1.30900E+02 6.98656E+06 + 1.31000E+02 6.99452E+06 + 1.31100E+02 6.92776E+06 + 1.31200E+02 6.78912E+06 + 1.31300E+02 6.58458E+06 + 1.31400E+02 6.32289E+06 + 1.31500E+02 6.01520E+06 + 1.31600E+02 5.67484E+06 + 1.31700E+02 5.31619E+06 + 1.31800E+02 4.95472E+06 + 1.31900E+02 4.60601E+06 + 1.32000E+02 4.28480E+06 + 1.32100E+02 4.00499E+06 + 1.32200E+02 3.77853E+06 + 1.32300E+02 3.61509E+06 + 1.32400E+02 3.52172E+06 + 1.32500E+02 3.50239E+06 + 1.32600E+02 3.55793E+06 + 1.32700E+02 3.68599E+06 + 1.32800E+02 3.88107E+06 + 1.32900E+02 4.13473E+06 + 1.33000E+02 4.43626E+06 + 1.33100E+02 4.77262E+06 + 1.33200E+02 5.12943E+06 + 1.33300E+02 5.49147E+06 + 1.33400E+02 5.84313E+06 + 1.33500E+02 6.16940E+06 + 1.33600E+02 6.45629E+06 + 1.33700E+02 6.69155E+06 + 1.33800E+02 6.86504E+06 + 1.33900E+02 6.96936E+06 + 1.34000E+02 7.00004E+06 + 1.34100E+02 6.95578E+06 + 1.34200E+02 6.83843E+06 + 1.34300E+02 6.65304E+06 + 1.34400E+02 6.40758E+06 + 1.34500E+02 6.11255E+06 + 1.34600E+02 5.78058E+06 + 1.34700E+02 5.42585E+06 + 1.34800E+02 5.06364E+06 + 1.34900E+02 4.70943E+06 + 1.35000E+02 4.37834E+06 + 1.35100E+02 4.08469E+06 + 1.35200E+02 3.84088E+06 + 1.35300E+02 3.65747E+06 + 1.35400E+02 3.54232E+06 + 1.35500E+02 3.50032E+06 + 1.35600E+02 3.53328E+06 + 1.35700E+02 3.63979E+06 + 1.35800E+02 3.81531E+06 + 1.35900E+02 4.05228E+06 + 1.36000E+02 4.34061E+06 + 1.36100E+02 4.66781E+06 + 1.36200E+02 5.02007E+06 + 1.36300E+02 5.38218E+06 + 1.36400E+02 5.73854E+06 + 1.36500E+02 6.07409E+06 + 1.36600E+02 6.37430E+06 + 1.36700E+02 6.62636E+06 + 1.36800E+02 6.81950E+06 + 1.36900E+02 6.94539E+06 + 1.37000E+02 6.99867E+06 + 1.37100E+02 6.97705E+06 + 1.37200E+02 6.88145E+06 + 1.37300E+02 6.71599E+06 + 1.37400E+02 6.48775E+06 + 1.37500E+02 6.20645E+06 + 1.37600E+02 5.88429E+06 + 1.37700E+02 5.53486E+06 + 1.37800E+02 5.17325E+06 + 1.37900E+02 4.81498E+06 + 1.38000E+02 4.47536E+06 + 1.38100E+02 4.16894E+06 + 1.38200E+02 3.90880E+06 + 1.38300E+02 3.70616E+06 + 1.38400E+02 3.56966E+06 + 1.38500E+02 3.50514E+06 + 1.38600E+02 3.51539E+06 + 1.38700E+02 3.59996E+06 + 1.38800E+02 3.75525E+06 + 1.38900E+02 3.97452E+06 + 1.39000E+02 4.24850E+06 + 1.39100E+02 4.56536E+06 + 1.39200E+02 4.91156E+06 + 1.39300E+02 5.27232E+06 + 1.39400E+02 5.63208E+06 + 1.39500E+02 5.97549E+06 + 1.39600E+02 6.28783E+06 + 1.39700E+02 6.55576E+06 + 1.39800E+02 6.76776E+06 + 1.39900E+02 6.91471E+06 + 1.40000E+02 6.99039E+06 + 1.40100E+02 6.99152E+06 + 1.40200E+02 6.91806E+06 + 1.40300E+02 6.77314E+06 + 1.40400E+02 6.56300E+06 + 1.40500E+02 6.29663E+06 + 1.40600E+02 5.98544E+06 + 1.40700E+02 5.64270E+06 + 1.40800E+02 5.28321E+06 + 1.40900E+02 4.92231E+06 + 1.41000E+02 4.57540E+06 + 1.41100E+02 4.25750E+06 + 1.41200E+02 3.98204E+06 + 1.41300E+02 3.76091E+06 + 1.41400E+02 3.60364E+06 + 1.41500E+02 3.51687E+06 + 1.41600E+02 3.50436E+06 + 1.41700E+02 3.56665E+06 + 1.41800E+02 3.70106E+06 + 1.41900E+02 3.90182E+06 + 1.42000E+02 4.16039E+06 + 1.42100E+02 4.46556E+06 + 1.42200E+02 4.80444E+06 + 1.42300E+02 5.16242E+06 + 1.42400E+02 5.52406E+06 + 1.42500E+02 5.87407E+06 + 1.42600E+02 6.19731E+06 + 1.42700E+02 6.47998E+06 + 1.42800E+02 6.71001E+06 + 1.42900E+02 6.87748E+06 + 1.43000E+02 6.97524E+06 + 1.43100E+02 6.99911E+06 + 1.43200E+02 6.94806E+06 + 1.43300E+02 6.82427E+06 + 1.43400E+02 6.63310E+06 + 1.43500E+02 6.38263E+06 + 1.43600E+02 6.08369E+06 + 1.43700E+02 5.74905E+06 + 1.43800E+02 5.39299E+06 + 1.43900E+02 5.03087E+06 + 1.44000E+02 4.67815E+06 + 1.44100E+02 4.34993E+06 + 1.44200E+02 4.06024E+06 + 1.44300E+02 3.82158E+06 + 1.44400E+02 3.64410E+06 + 1.44500E+02 3.53542E+06 + 1.44600E+02 3.50021E+06 + 1.44700E+02 3.53997E+06 + 1.44800E+02 3.65301E+06 + 1.44900E+02 3.83442E+06 + 1.45000E+02 4.07654E+06 + 1.45100E+02 4.36891E+06 + 1.45200E+02 4.69908E+06 + 1.45300E+02 5.05281E+06 + 1.45400E+02 5.41500E+06 + 1.45500E+02 5.77019E+06 + 1.45600E+02 6.10301E+06 + 1.45700E+02 6.39939E+06 + 1.45800E+02 6.64653E+06 + 1.45900E+02 6.83380E+06 + 1.46000E+02 6.95329E+06 + 1.46100E+02 6.99981E+06 + 1.46200E+02 6.97138E+06 + 1.46300E+02 6.86921E+06 + 1.46400E+02 6.69771E+06 + 1.46500E+02 6.46420E+06 + 1.46600E+02 6.17870E+06 + 1.46700E+02 5.85337E+06 + 1.46800E+02 5.50221E+06 + 1.46900E+02 5.14036E+06 + 1.47000E+02 4.78311E+06 + 1.47100E+02 4.44592E+06 + 1.47200E+02 4.14319E+06 + 1.47300E+02 3.88785E+06 + 1.47400E+02 3.69090E+06 + 1.47500E+02 3.56075E+06 + 1.47600E+02 3.50297E+06 + 1.47700E+02 3.52005E+06 + 1.47800E+02 3.61124E+06 + 1.47900E+02 3.77264E+06 + 1.48000E+02 3.99736E+06 + 1.48100E+02 4.27569E+06 + 1.48200E+02 4.59584E+06 + 1.48300E+02 4.94404E+06 + 1.48400E+02 5.30525E+06 + 1.48500E+02 5.66421E+06 + 1.48600E+02 6.00538E+06 + 1.48700E+02 6.31426E+06 + 1.48800E+02 6.57750E+06 + 1.48900E+02 6.78390E+06 + 1.49000E+02 6.92462E+06 + 1.49100E+02 6.99359E+06 + 1.49200E+02 6.98790E+06 + 1.49300E+02 6.90775E+06 + 1.49400E+02 6.75663E+06 + 1.49500E+02 6.54094E+06 + 1.49600E+02 6.27000E+06 + 1.49700E+02 5.95537E+06 + 1.49800E+02 5.61048E+06 + 1.49900E+02 5.25022E+06 + 1.50000E+02 4.88996E+06 + 1.50100E+02 4.54513E+06 + 1.50200E+02 4.23046E+06 + 1.50300E+02 3.95953E+06 + 1.50400E+02 3.74388E+06 + 1.50500E+02 3.59274E+06 + 1.50600E+02 3.51263E+06 + 1.50700E+02 3.50695E+06 + 1.50800E+02 3.57596E+06 + 1.50900E+02 3.71668E+06 + 1.51000E+02 3.92309E+06 + 1.51100E+02 4.18636E+06 + 1.51200E+02 4.49524E+06 + 1.51300E+02 4.83642E+06 + 1.51400E+02 5.19533E+06 + 1.51500E+02 5.55664E+06 + 1.51600E+02 5.90473E+06 + 1.51700E+02 6.22488E+06 + 1.51800E+02 6.50328E+06 + 1.51900E+02 6.72792E+06 + 1.52000E+02 6.88933E+06 + 1.52100E+02 6.98050E+06 + 1.52200E+02 6.99756E+06 + 1.52300E+02 6.93976E+06 + 1.52400E+02 6.80959E+06 + 1.52500E+02 6.61260E+06 + 1.52600E+02 6.35731E+06 + 1.52700E+02 6.05453E+06 + 1.52800E+02 5.71729E+06 + 1.52900E+02 5.36014E+06 + 1.53000E+02 4.99818E+06 + 1.53100E+02 4.64707E+06 + 1.53200E+02 4.32180E+06 + 1.53300E+02 4.03627E+06 + 1.53400E+02 3.80277E+06 + 1.53500E+02 3.63129E+06 + 1.53600E+02 3.52915E+06 + 1.53700E+02 3.50073E+06 + 1.53800E+02 3.54727E+06 + 1.53900E+02 3.66675E+06 + 1.54000E+02 3.85410E+06 + 1.54100E+02 4.10122E+06 + 1.54200E+02 4.39757E+06 + 1.54300E+02 4.73049E+06 + 1.54400E+02 5.08563E+06 + 1.54500E+02 5.44782E+06 + 1.54600E+02 5.80155E+06 + 1.54700E+02 6.13171E+06 + 1.54800E+02 6.42407E+06 + 1.54900E+02 6.66614E+06 + 1.55000E+02 6.84759E+06 + 1.55100E+02 6.96058E+06 + 1.55200E+02 7.00032E+06 + 1.55300E+02 6.96509E+06 + 1.55400E+02 6.85642E+06 + 1.55500E+02 6.67890E+06 + 1.55600E+02 6.44022E+06 + 1.55700E+02 6.15057E+06 + 1.55800E+02 5.82230E+06 + 1.55900E+02 5.46957E+06 + 1.56000E+02 5.10740E+06 + 1.56100E+02 4.75145E+06 + 1.56200E+02 4.41676E+06 + 1.56300E+02 4.11779E+06 + 1.56400E+02 3.86741E+06 + 1.56500E+02 3.67620E+06 + 1.56600E+02 3.55245E+06 + 1.56700E+02 3.50142E+06 + 1.56800E+02 3.52531E+06 + 1.56900E+02 3.62309E+06 + 1.57000E+02 3.79058E+06 + 1.57100E+02 4.02058E+06 + 1.57200E+02 4.30331E+06 + 1.57300E+02 4.62656E+06 + 1.57400E+02 4.97652E+06 + 1.57500E+02 5.33827E+06 + 1.57600E+02 5.69614E+06 + 1.57700E+02 6.03501E+06 + 1.57800E+02 6.34026E+06 + 1.57900E+02 6.59877E+06 + 1.58000E+02 6.79952E+06 + 1.58100E+02 6.93391E+06 + 1.58200E+02 6.99618E+06 + 1.58300E+02 6.98366E+06 + 1.58400E+02 6.89688E+06 + 1.58500E+02 6.73954E+06 + 1.58600E+02 6.51847E+06 + 1.58700E+02 6.24300E+06 + 1.58800E+02 5.92500E+06 + 1.58900E+02 5.57819E+06 + 1.59000E+02 5.21723E+06 + 1.59100E+02 4.85774E+06 + 1.59200E+02 4.51506E+06 + 1.59300E+02 4.20383E+06 + 1.59400E+02 3.93748E+06 + 1.59500E+02 3.72733E+06 + 1.59600E+02 3.58246E+06 + 1.59700E+02 3.50901E+06 + 1.59800E+02 3.51016E+06 + 1.59900E+02 3.58584E+06 + 1.60000E+02 3.73285E+06 + 1.60100E+02 3.94483E+06 + 1.60200E+02 4.21274E+06 + 1.60300E+02 4.52514E+06 + 1.60400E+02 4.86855E+06 + 1.60500E+02 5.22831E+06 + 1.60600E+02 5.58902E+06 + 1.60700E+02 5.93526E+06 + 1.60800E+02 6.25211E+06 + 1.60900E+02 6.52605E+06 + 1.61000E+02 6.74537E+06 + 1.61100E+02 6.90059E+06 + 1.61200E+02 6.98515E+06 + 1.61300E+02 6.99538E+06 + 1.61400E+02 6.93085E+06 + 1.61500E+02 6.79433E+06 + 1.61600E+02 6.59168E+06 + 1.61700E+02 6.33152E+06 + 1.61800E+02 6.02509E+06 + 1.61900E+02 5.68546E+06 + 1.62000E+02 5.32714E+06 + 1.62100E+02 4.96563E+06 + 1.62200E+02 4.61621E+06 + 1.62300E+02 4.29396E+06 + 1.62400E+02 4.01276E+06 + 1.62500E+02 3.78449E+06 + 1.62600E+02 3.61905E+06 + 1.62700E+02 3.52348E+06 + 1.62800E+02 3.50187E+06 + 1.62900E+02 3.55517E+06 + 1.63000E+02 3.68110E+06 + 1.63100E+02 3.87420E+06 + 1.63200E+02 4.12631E+06 + 1.63300E+02 4.42658E+06 + 1.63400E+02 4.76203E+06 + 1.63500E+02 5.11850E+06 + 1.63600E+02 5.48056E+06 + 1.63700E+02 5.83276E+06 + 1.63800E+02 6.16005E+06 + 1.63900E+02 6.44833E+06 + 1.64000E+02 6.68528E+06 + 1.64100E+02 6.86077E+06 + 1.64200E+02 6.96728E+06 + 1.64300E+02 7.00022E+06 + 1.64400E+02 6.95820E+06 + 1.64500E+02 6.84300E+06 + 1.64600E+02 6.65963E+06 + 1.64700E+02 6.41582E+06 + 1.64800E+02 6.12207E+06 + 1.64900E+02 5.79101E+06 + 1.65000E+02 5.43680E+06 + 1.65100E+02 5.07459E+06 + 1.65200E+02 4.71986E+06 + 1.65300E+02 4.38790E+06 + 1.65400E+02 4.09288E+06 + 1.65500E+02 3.84741E+06 + 1.65600E+02 3.66208E+06 + 1.65700E+02 3.54475E+06 + 1.65800E+02 3.50049E+06 + 1.65900E+02 3.53118E+06 + 1.66000E+02 3.63553E+06 + 1.66100E+02 3.80904E+06 + 1.66200E+02 4.04428E+06 + 1.66300E+02 4.33122E+06 + 1.66400E+02 4.65749E+06 + 1.66500E+02 5.00916E+06 + 1.66600E+02 5.37115E+06 + 1.66700E+02 5.72801E+06 + 1.66800E+02 6.06441E+06 + 1.66900E+02 6.36584E+06 + 1.67000E+02 6.61956E+06 + 1.67100E+02 6.81459E+06 + 1.67200E+02 6.94262E+06 + 1.67300E+02 6.99815E+06 + 1.67400E+02 6.97880E+06 + 1.67500E+02 6.88541E+06 + 1.67600E+02 6.72198E+06 + 1.67700E+02 6.49547E+06 + 1.67800E+02 6.21566E+06 + 1.67900E+02 5.89449E+06 + 1.68000E+02 5.54567E+06 + 1.68100E+02 5.18430E+06 + 1.68200E+02 4.82566E+06 + 1.68300E+02 4.48520E+06 + 1.68400E+02 4.17762E+06 + 1.68500E+02 3.91589E+06 + 1.68600E+02 3.71137E+06 + 1.68700E+02 3.57275E+06 + 1.68800E+02 3.50601E+06 + 1.68900E+02 3.51398E+06 + 1.69000E+02 3.59635E+06 + 1.69100E+02 3.74953E+06 + 1.69200E+02 3.96704E+06 + 1.69300E+02 4.23954E+06 + 1.69400E+02 4.55524E+06 + 1.69500E+02 4.90082E+06 + 1.69600E+02 5.26131E+06 + 1.69700E+02 5.62133E+06 + 1.69800E+02 5.96550E+06 + 1.69900E+02 6.27899E+06 + 1.70000E+02 6.54841E+06 + 1.70100E+02 6.76222E+06 + 1.70200E+02 6.91129E+06 + 1.70300E+02 6.98919E+06 + 1.70400E+02 6.99259E+06 + 1.70500E+02 6.92135E+06 + 1.70600E+02 6.77853E+06 + 1.70700E+02 6.57025E+06 + 1.70800E+02 6.30539E+06 + 1.70900E+02 5.99537E+06 + 1.71000E+02 5.65343E+06 + 1.71100E+02 5.29422E+06 + 1.71200E+02 4.93308E+06 + 1.71300E+02 4.58557E+06 + 1.71400E+02 4.26654E+06 + 1.71500E+02 3.98961E+06 + 1.71600E+02 3.76675E+06 + 1.71700E+02 3.60738E+06 + 1.71800E+02 3.51841E+06 + 1.71900E+02 3.50363E+06 + 1.72000E+02 3.56368E+06 + 1.72100E+02 3.69597E+06 + 1.72200E+02 3.89487E+06 + 1.72300E+02 4.15180E+06 + 1.72400E+02 4.45578E+06 + 1.72500E+02 4.79385E+06 + 1.72600E+02 5.15137E+06 + 1.72700E+02 5.51323E+06 + 1.72800E+02 5.86382E+06 + 1.72900E+02 6.18803E+06 + 1.73000E+02 6.47216E+06 + 1.73100E+02 6.70391E+06 + 1.73200E+02 6.87339E+06 + 1.73300E+02 6.97336E+06 + 1.73400E+02 6.99949E+06 + 1.73500E+02 6.95070E+06 + 1.73600E+02 6.82907E+06 + 1.73700E+02 6.63978E+06 + 1.73800E+02 6.39096E+06 + 1.73900E+02 6.09335E+06 + 1.74000E+02 5.75954E+06 + 1.74100E+02 5.40396E+06 + 1.74200E+02 5.04180E+06 + 1.74300E+02 4.68852E+06 + 1.74400E+02 4.35935E+06 + 1.74500E+02 4.06834E+06 + 1.74600E+02 3.82796E+06 + 1.74700E+02 3.64849E+06 + 1.74800E+02 3.53765E+06 + 1.74900E+02 3.50018E+06 + 1.75000E+02 3.53768E+06 + 1.75100E+02 3.64852E+06 + 1.75200E+02 3.82801E+06 + 1.75300E+02 4.06844E+06 + 1.75400E+02 4.35941E+06 + 1.75500E+02 4.68864E+06 + 1.75600E+02 5.04188E+06 + 1.75700E+02 5.40409E+06 + 1.75800E+02 5.75967E+06 + 1.75900E+02 6.09342E+06 + 1.76000E+02 6.39110E+06 + 1.76100E+02 6.63983E+06 + 1.76200E+02 6.82911E+06 + 1.76300E+02 6.95073E+06 + 1.76400E+02 6.99949E+06 + 1.76500E+02 6.97333E+06 + 1.76600E+02 6.87336E+06 + 1.76700E+02 6.70387E+06 + 1.76800E+02 6.47207E+06 + 1.76900E+02 6.18797E+06 + 1.77000E+02 5.86370E+06 + 1.77100E+02 5.51315E+06 + 1.77200E+02 5.15129E+06 + 1.77300E+02 4.79373E+06 + 1.77400E+02 4.45572E+06 + 1.77500E+02 4.15170E+06 + 1.77600E+02 3.89478E+06 + 1.77700E+02 3.69593E+06 + 1.77800E+02 3.56364E+06 + 1.77900E+02 3.50363E+06 + 1.78000E+02 3.51843E+06 + 1.78100E+02 3.60741E+06 + 1.78200E+02 3.76679E+06 + 1.78300E+02 3.98970E+06 + 1.78400E+02 4.26660E+06 + 1.78500E+02 4.58569E+06 + 1.78600E+02 4.93315E+06 + 1.78700E+02 5.29430E+06 + 1.78800E+02 5.65355E+06 + 1.78900E+02 5.99544E+06 + 1.79000E+02 6.30549E+06 + 1.79100E+02 6.57030E+06 + 1.79200E+02 6.77857E+06 + 1.79300E+02 6.92138E+06 + 1.79400E+02 6.99259E+06 + 1.79500E+02 6.98917E+06 + 1.79600E+02 6.91126E+06 + 1.79700E+02 6.76218E+06 + 1.79800E+02 6.54832E+06 + 1.79900E+02 6.27892E+06 + 1.80000E+02 5.96538E+06 + 1.80100E+02 5.62125E+06 + 1.80200E+02 5.26123E+06 + 1.80300E+02 4.90069E+06 + 1.80400E+02 4.55517E+06 + 1.80500E+02 4.23943E+06 + 1.80600E+02 3.96699E+06 + 1.80700E+02 3.74949E+06 + 1.80800E+02 3.59631E+06 + 1.80900E+02 3.51397E+06 + 1.81000E+02 3.50602E+06 + 1.81100E+02 3.57277E+06 + 1.81200E+02 3.71141E+06 + 1.81300E+02 3.91598E+06 + 1.81400E+02 4.17768E+06 + 1.81500E+02 4.48532E+06 + 1.81600E+02 4.82573E+06 + 1.81700E+02 5.18438E+06 + 1.81800E+02 5.54580E+06 + 1.81900E+02 5.89456E+06 + 1.82000E+02 6.21576E+06 + 1.82100E+02 6.49553E+06 + 1.82200E+02 6.72202E+06 + 1.82300E+02 6.88546E+06 + 1.82400E+02 6.97881E+06 + 1.82500E+02 6.99814E+06 + 1.82600E+02 6.94260E+06 + 1.82700E+02 6.81456E+06 + 1.82800E+02 6.61948E+06 + 1.82900E+02 6.36578E+06 + 1.83000E+02 6.06425E+06 + 1.83100E+02 5.72794E+06 + 1.83200E+02 5.37107E+06 + 1.83300E+02 5.00903E+06 + 1.83400E+02 4.65742E+06 + 1.83500E+02 4.33111E+06 + 1.83600E+02 4.04422E+06 + 1.83700E+02 3.80899E+06 + 1.83800E+02 3.63548E+06 + 1.83900E+02 3.53117E+06 + 1.84000E+02 3.50049E+06 + 1.84100E+02 3.54476E+06 + 1.84200E+02 3.66212E+06 + 1.84300E+02 3.84748E+06 + 1.84400E+02 4.09294E+06 + 1.84500E+02 4.38802E+06 + 1.84600E+02 4.71993E+06 + 1.84700E+02 5.07467E+06 + 1.84800E+02 5.43693E+06 + 1.84900E+02 5.79114E+06 + 1.85000E+02 6.12218E+06 + 1.85100E+02 6.41588E+06 + 1.85200E+02 6.65967E+06 + 1.85300E+02 6.84306E+06 + 1.85400E+02 6.95822E+06 + 1.85500E+02 7.00022E+06 + 1.85600E+02 6.96726E+06 + 1.85700E+02 6.86074E+06 + 1.85800E+02 6.68521E+06 + 1.85900E+02 6.44827E+06 + 1.86000E+02 6.15994E+06 + 1.86100E+02 5.83269E+06 + 1.86200E+02 5.48049E+06 + 1.86300E+02 5.11837E+06 + 1.86400E+02 4.76196E+06 + 1.86500E+02 4.42641E+06 + 1.86600E+02 4.12625E+06 + 1.86700E+02 3.87416E+06 + 1.86800E+02 3.68102E+06 + 1.86900E+02 3.55515E+06 + 1.87000E+02 3.50187E+06 + 1.87100E+02 3.52349E+06 + 1.87200E+02 3.61907E+06 + 1.87300E+02 3.78456E+06 + 1.87400E+02 4.01281E+06 + 1.87500E+02 4.29407E+06 + 1.87600E+02 4.61628E+06 + 1.87700E+02 4.96571E+06 + 1.87800E+02 5.32727E+06 + 1.87900E+02 5.68553E+06 + 1.88000E+02 6.02520E+06 + 1.88100E+02 6.33158E+06 + 1.88200E+02 6.59173E+06 + 1.88300E+02 6.79440E+06 + 1.88400E+02 6.93089E+06 + 1.88500E+02 6.99539E+06 + 1.88600E+02 6.98514E+06 + 1.88700E+02 6.90056E+06 + 1.88800E+02 6.74530E+06 + 1.88900E+02 6.52600E+06 + 1.89000E+02 6.25201E+06 + 1.89100E+02 5.93519E+06 + 1.89200E+02 5.58894E+06 + 1.89300E+02 5.22818E+06 + 1.89400E+02 4.86848E+06 + 1.89500E+02 4.52502E+06 + 1.89600E+02 4.21268E+06 + 1.89700E+02 3.94478E+06 + 1.89800E+02 3.73278E+06 + 1.89900E+02 3.58582E+06 + 1.90000E+02 3.51015E+06 + 1.90100E+02 3.50902E+06 + 1.90200E+02 3.58249E+06 + 1.90300E+02 3.72742E+06 + 1.90400E+02 3.93753E+06 + 1.90500E+02 4.20394E+06 + 1.90600E+02 4.51513E+06 + 1.90700E+02 4.85781E+06 + 1.90800E+02 5.21736E+06 + 1.90900E+02 5.57826E+06 + 1.91000E+02 5.92512E+06 + 1.91100E+02 6.24306E+06 + 1.91200E+02 6.51852E+06 + 1.91300E+02 6.73961E+06 + 1.91400E+02 6.89691E+06 + 1.91500E+02 6.98367E+06 + 1.91600E+02 6.99618E+06 + 1.91700E+02 6.93389E+06 + 1.91800E+02 6.79946E+06 + 1.91900E+02 6.59869E+06 + 1.92000E+02 6.34016E+06 + 1.92100E+02 6.03494E+06 + 1.92200E+02 5.69606E+06 + 1.92300E+02 5.33814E+06 + 1.92400E+02 4.97645E+06 + 1.92500E+02 4.62644E+06 + 1.92600E+02 4.30324E+06 + 1.92700E+02 4.02053E+06 + 1.92800E+02 3.79050E+06 + 1.92900E+02 3.62307E+06 + 1.93000E+02 3.52529E+06 + 1.93100E+02 3.50142E+06 + 1.93200E+02 3.55247E+06 + 1.93300E+02 3.67626E+06 + 1.93400E+02 3.86746E+06 + 1.93500E+02 4.11789E+06 + 1.93600E+02 4.41683E+06 + 1.93700E+02 4.75152E+06 + 1.93800E+02 5.10758E+06 + 1.93900E+02 5.46964E+06 + 1.94000E+02 5.82242E+06 + 1.94100E+02 6.15063E+06 + 1.94200E+02 6.44028E+06 + 1.94300E+02 6.67898E+06 + 1.94400E+02 6.85645E+06 + 1.94500E+02 6.96511E+06 + 1.94600E+02 7.00032E+06 + 1.94700E+02 6.96056E+06 + 1.94800E+02 6.84754E+06 + 1.94900E+02 6.66610E+06 + 1.95000E+02 6.42397E+06 + 1.95100E+02 6.13164E+06 + 1.95200E+02 5.80148E+06 + 1.95300E+02 5.44769E+06 + 1.95400E+02 5.08555E+06 + 1.95500E+02 4.73036E+06 + 1.95600E+02 4.39750E+06 + 1.95700E+02 4.10112E+06 + 1.95800E+02 3.85402E+06 + 1.95900E+02 3.66672E+06 + 1.96000E+02 3.54724E+06 + 1.96100E+02 3.50073E+06 + 1.96200E+02 3.52916E+06 + 1.96300E+02 3.63134E+06 + 1.96400E+02 3.80282E+06 + 1.96500E+02 4.03636E+06 + 1.96600E+02 4.32187E+06 + 1.96700E+02 4.64714E+06 + 1.96800E+02 4.99831E+06 + 1.96900E+02 5.36021E+06 + 1.97000E+02 5.71741E+06 + 1.97100E+02 6.05460E+06 + 1.97200E+02 6.35737E+06 + 1.97300E+02 6.61271E+06 + 1.97400E+02 6.80962E+06 + 1.97500E+02 6.93979E+06 + 1.97600E+02 6.99756E+06 + 1.97700E+02 6.98049E+06 + 1.97800E+02 6.88929E+06 + 1.97900E+02 6.72788E+06 + 1.98000E+02 6.50319E+06 + 1.98100E+02 6.22482E+06 + 1.98200E+02 5.90466E+06 + 1.98300E+02 5.55652E+06 + 1.98400E+02 5.19525E+06 + 1.98500E+02 4.83629E+06 + 1.98600E+02 4.49517E+06 + 1.98700E+02 4.18630E+06 + 1.98800E+02 3.92301E+06 + 1.98900E+02 3.71664E+06 + 1.99000E+02 3.57592E+06 + 1.99100E+02 3.50694E+06 + 1.99200E+02 3.51264E+06 + 1.99300E+02 3.59278E+06 + 1.99400E+02 3.74392E+06 + 1.99500E+02 3.95961E+06 + 1.99600E+02 4.23052E+06 + 1.99700E+02 4.54520E+06 + 1.99800E+02 4.89008E+06 + 1.99900E+02 5.25030E+06 + 2.00000E+02 5.61061E+06 + 2.00100E+02 5.95544E+06 + 2.00200E+02 6.27006E+06 + 2.00300E+02 6.54103E+06 + 2.00400E+02 6.75667E+06 + 2.00500E+02 6.90779E+06 + 2.00600E+02 6.98790E+06 + 2.00700E+02 6.99358E+06 + 2.00800E+02 6.92457E+06 + 2.00900E+02 6.78386E+06 + 2.01000E+02 6.57742E+06 + 2.01100E+02 6.31415E+06 + 2.01200E+02 6.00531E+06 + 2.01300E+02 5.66408E+06 + 2.01400E+02 5.30517E+06 + 2.01500E+02 4.94391E+06 + 2.01600E+02 4.59577E+06 + 2.01700E+02 4.27562E+06 + 2.01800E+02 3.99727E+06 + 2.01900E+02 3.77259E+06 + 2.02000E+02 3.61119E+06 + 2.02100E+02 3.52004E+06 + 2.02200E+02 3.50298E+06 + 2.02300E+02 3.56079E+06 + 2.02400E+02 3.69094E+06 + 2.02500E+02 3.88793E+06 + 2.02600E+02 4.14325E+06 + 2.02700E+02 4.44604E+06 + 2.02800E+02 4.78323E+06 + 2.02900E+02 5.14043E+06 + 2.03000E+02 5.50239E+06 + 2.03100E+02 5.85344E+06 + 2.03200E+02 6.17876E+06 + 2.03300E+02 6.46429E+06 + 2.03400E+02 6.69775E+06 + 2.03500E+02 6.86926E+06 + 2.03600E+02 6.97139E+06 + 2.03700E+02 6.99980E+06 + 2.03800E+02 6.95326E+06 + 2.03900E+02 6.83377E+06 + 2.04000E+02 6.64645E+06 + 2.04100E+02 6.39933E+06 + 2.04200E+02 6.10294E+06 + 2.04300E+02 5.77007E+06 + 2.04400E+02 5.41493E+06 + 2.04500E+02 5.05268E+06 + 2.04600E+02 4.69896E+06 + 2.04700E+02 4.36884E+06 + 2.04800E+02 4.07645E+06 + 2.04900E+02 3.83438E+06 + 2.05000E+02 3.65295E+06 + 2.05100E+02 3.53995E+06 + 2.05200E+02 3.50021E+06 + 2.05300E+02 3.53545E+06 + 2.05400E+02 3.64413E+06 + 2.05500E+02 3.82165E+06 + 2.05600E+02 4.06030E+06 + 2.05700E+02 4.35000E+06 + 2.05800E+02 4.67827E+06 + 2.05900E+02 5.03095E+06 + 2.06000E+02 5.39312E+06 + 2.06100E+02 5.74912E+06 + 2.06200E+02 6.08376E+06 + 2.06300E+02 6.38273E+06 + 2.06400E+02 6.63314E+06 + 2.06500E+02 6.82435E+06 + 2.06600E+02 6.94808E+06 + 2.06700E+02 6.99912E+06 + 2.06800E+02 6.97522E+06 + 2.06900E+02 6.87745E+06 + 2.07000E+02 6.70994E+06 + 2.07100E+02 6.47993E+06 + 2.07200E+02 6.19724E+06 + 2.07300E+02 5.87395E+06 + 2.07400E+02 5.52398E+06 + 2.07500E+02 5.16229E+06 + 2.07600E+02 4.80436E+06 + 2.07700E+02 4.46549E+06 + 2.07800E+02 4.16029E+06 + 2.07900E+02 3.90178E+06 + 2.08000E+02 3.70100E+06 + 2.08100E+02 3.56663E+06 + 2.08200E+02 3.50435E+06 + 2.08300E+02 3.51688E+06 + 2.08400E+02 3.60367E+06 + 2.08500E+02 3.76098E+06 + 2.08600E+02 3.98209E+06 + 2.08700E+02 4.25756E+06 + 2.08800E+02 4.57552E+06 + 2.08900E+02 4.92238E+06 + 2.09000E+02 5.28334E+06 + 2.09100E+02 5.64278E+06 + 2.09200E+02 5.98551E+06 + 2.09300E+02 6.29673E+06 + 2.09400E+02 6.56305E+06 + 2.09500E+02 6.77320E+06 + 2.09600E+02 6.91808E+06 + 2.09700E+02 6.99152E+06 + 2.09800E+02 6.99038E+06 + 2.09900E+02 6.91468E+06 + 2.10000E+02 6.76767E+06 + 2.10100E+02 6.55571E+06 + 2.10200E+02 6.28777E+06 + 2.10300E+02 5.97537E+06 + 2.10400E+02 5.63200E+06 + 2.10500E+02 5.27219E+06 + 2.10600E+02 4.91148E+06 + 2.10700E+02 4.56529E+06 + 2.10800E+02 4.24839E+06 + 2.10900E+02 3.97446E+06 + 2.11000E+02 3.75518E+06 + 2.11100E+02 3.59994E+06 + 2.11200E+02 3.51538E+06 + 2.11300E+02 3.50516E+06 + 2.11400E+02 3.56968E+06 + 2.11500E+02 3.70622E+06 + 2.11600E+02 3.90884E+06 + 2.11700E+02 4.16900E+06 + 2.11800E+02 4.47548E+06 + 2.11900E+02 4.81511E+06 + 2.12000E+02 5.17338E+06 + 2.12100E+02 5.53494E+06 + 2.12200E+02 5.88436E+06 + 2.12300E+02 6.20656E+06 + 2.12400E+02 6.48780E+06 + 2.12500E+02 6.71606E+06 + 2.12600E+02 6.88148E+06 + 2.12700E+02 6.97707E+06 + 2.12800E+02 6.99866E+06 + 2.12900E+02 6.94537E+06 + 2.13000E+02 6.81944E+06 + 2.13100E+02 6.62631E+06 + 2.13200E+02 6.37424E+06 + 2.13300E+02 6.07398E+06 + 2.13400E+02 5.73847E+06 + 2.13500E+02 5.38200E+06 + 2.13600E+02 5.01999E+06 + 2.13700E+02 4.66774E+06 + 2.13800E+02 4.34045E+06 + 2.13900E+02 4.05222E+06 + 2.14000E+02 3.81524E+06 + 2.14100E+02 3.63976E+06 + 2.14200E+02 3.53326E+06 + 2.14300E+02 3.50032E+06 + 2.14400E+02 3.54234E+06 + 2.14500E+02 3.65752E+06 + 2.14600E+02 3.84093E+06 + 2.14700E+02 4.08474E+06 + 2.14800E+02 4.37845E+06 + 2.14900E+02 4.70950E+06 + 2.15000E+02 5.06377E+06 + 2.15100E+02 5.42592E+06 + 2.15200E+02 5.78066E+06 + 2.15300E+02 6.11266E+06 + 2.15400E+02 6.40768E+06 + 2.15500E+02 6.65312E+06 + 2.15600E+02 6.83846E+06 + 2.15700E+02 6.95580E+06 + 2.15800E+02 7.00005E+06 + 2.15900E+02 6.96935E+06 + 2.16000E+02 6.86499E+06 + 2.16100E+02 6.69151E+06 + 2.16200E+02 6.45623E+06 + 2.16300E+02 6.16929E+06 + 2.16400E+02 5.84306E+06 + 2.16500E+02 5.49135E+06 + 2.16600E+02 5.12935E+06 + 2.16700E+02 4.77254E+06 + 2.16800E+02 4.43614E+06 + 2.16900E+02 4.13467E+06 + 2.17000E+02 3.88099E+06 + 2.17100E+02 3.68595E+06 + 2.17200E+02 3.55791E+06 + 2.17300E+02 3.50238E+06 + 2.17400E+02 3.52173E+06 + 2.17500E+02 3.61514E+06 + 2.17600E+02 3.77857E+06 + 2.17700E+02 4.00505E+06 + 2.17800E+02 4.28491E+06 + 2.17900E+02 4.60608E+06 + 2.18000E+02 4.95485E+06 + 2.18100E+02 5.31627E+06 + 2.18200E+02 5.67491E+06 + 2.18300E+02 6.01531E+06 + 2.18400E+02 6.32295E+06 + 2.18500E+02 6.58466E+06 + 2.18600E+02 6.78916E+06 + 2.18700E+02 6.92778E+06 + 2.18800E+02 6.99453E+06 + 2.18900E+02 6.98655E+06 + 2.19000E+02 6.90419E+06 + 2.19100E+02 6.75099E+06 + 2.19200E+02 6.53347E+06 + 2.19300E+02 6.26102E+06 + 2.19400E+02 5.94526E+06 + 2.19500E+02 5.59969E+06 + 2.19600E+02 5.23925E+06 + 2.19700E+02 4.87918E+06 + 2.19800E+02 4.53500E+06 + 2.19900E+02 4.22157E+06 + 2.20000E+02 3.95211E+06 + 2.20100E+02 3.73830E+06 + 2.20200E+02 3.58925E+06 + 2.20300E+02 3.51135E+06 + 2.20400E+02 3.50795E+06 + 2.20500E+02 3.57918E+06 + 2.20600E+02 3.72200E+06 + 2.20700E+02 3.93031E+06 + 2.20800E+02 4.19517E+06 + 2.20900E+02 4.50515E+06 + 2.21000E+02 4.84714E+06 + 2.21100E+02 5.20635E+06 + 2.21200E+02 5.56744E+06 + 2.21300E+02 5.91499E+06 + 2.21400E+02 6.23402E+06 + 2.21500E+02 6.51091E+06 + 2.21600E+02 6.73380E+06 + 2.21700E+02 6.89316E+06 + 2.21800E+02 6.98212E+06 + 2.21900E+02 6.99690E+06 + 2.22000E+02 6.93685E+06 + 2.22100E+02 6.80458E+06 + 2.22200E+02 6.60568E+06 + 2.22300E+02 6.34871E+06 + 2.22400E+02 6.04477E+06 + 2.22500E+02 5.70670E+06 + 2.22600E+02 5.34913E+06 + 2.22700E+02 4.98727E+06 + 2.22800E+02 4.63674E+06 + 2.22900E+02 4.31248E+06 + 2.23000E+02 4.02835E+06 + 2.23100E+02 3.79664E+06 + 2.23200E+02 3.62713E+06 + 2.23300E+02 3.52717E+06 + 2.23400E+02 3.50104E+06 + 2.23500E+02 3.54984E+06 + 2.23600E+02 3.67148E+06 + 2.23700E+02 3.86074E+06 + 2.23800E+02 4.10956E+06 + 2.23900E+02 4.40721E+06 + 2.24000E+02 4.74098E+06 + 2.24100E+02 5.09655E+06 + 2.24200E+02 5.45877E+06 + 2.24300E+02 5.81205E+06 + 2.24400E+02 6.14117E+06 + 2.24500E+02 6.43222E+06 + 2.24600E+02 6.67259E+06 + 2.24700E+02 6.85204E+06 + 2.24800E+02 6.96289E+06 + 2.24900E+02 7.00036E+06 + 2.25000E+02 6.96286E+06 + 2.25100E+02 6.85200E+06 + 2.25200E+02 6.67251E+06 + 2.25300E+02 6.43211E+06 + 2.25400E+02 6.14109E+06 + 2.25500E+02 5.81186E+06 + 2.25600E+02 5.45868E+06 + 2.25700E+02 5.09646E+06 + 2.25800E+02 4.74084E+06 + 2.25900E+02 4.40713E+06 + 2.26000E+02 4.10945E+06 + 2.26100E+02 3.86068E+06 + 2.26200E+02 3.67141E+06 + 2.26300E+02 3.54981E+06 + 2.26400E+02 3.50104E+06 + 2.26500E+02 3.52721E+06 + 2.26600E+02 3.62717E+06 + 2.26700E+02 3.79669E+06 + 2.26800E+02 4.02849E+06 + 2.26900E+02 4.31255E+06 + 2.27000E+02 4.63687E+06 + 2.27100E+02 4.98742E+06 + 2.27200E+02 5.34922E+06 + 2.27300E+02 5.70684E+06 + 2.27400E+02 6.04485E+06 + 2.27500E+02 6.34882E+06 + 2.27600E+02 6.60574E+06 + 2.27700E+02 6.80462E+06 + 2.27800E+02 6.93689E+06 + 2.27900E+02 6.99691E+06 + 2.28000E+02 6.98210E+06 + 2.28100E+02 6.89311E+06 + 2.28200E+02 6.73375E+06 + 2.28300E+02 6.51081E+06 + 2.28400E+02 6.23390E+06 + 2.28500E+02 5.91486E+06 + 2.28600E+02 5.56735E+06 + 2.28700E+02 5.20621E+06 + 2.28800E+02 4.84700E+06 + 2.28900E+02 4.50507E+06 + 2.29000E+02 4.19502E+06 + 2.29100E+02 3.93025E+06 + 2.29200E+02 3.72195E+06 + 2.29300E+02 3.57914E+06 + 2.29400E+02 3.50794E+06 + 2.29500E+02 3.51137E+06 + 2.29600E+02 3.58928E+06 + 2.29700E+02 3.73834E+06 + 2.29800E+02 3.95220E+06 + 2.29900E+02 4.22164E+06 + 2.30000E+02 4.53518E+06 + 2.30100E+02 4.87926E+06 + 2.30200E+02 5.23934E+06 + 2.30300E+02 5.59988E+06 + 2.30400E+02 5.94535E+06 + 2.30500E+02 6.26113E+06 + 2.30600E+02 6.53357E+06 + 2.30700E+02 6.75104E+06 + 2.30800E+02 6.90424E+06 + 2.30900E+02 6.98657E+06 + 2.31000E+02 6.99452E+06 + 2.31100E+02 6.92776E+06 + 2.31200E+02 6.78911E+06 + 2.31300E+02 6.58457E+06 + 2.31400E+02 6.32287E+06 + 2.31500E+02 6.01518E+06 + 2.31600E+02 5.67482E+06 + 2.31700E+02 5.31618E+06 + 2.31800E+02 4.95470E+06 + 2.31900E+02 4.60595E+06 + 2.32000E+02 4.28479E+06 + 2.32100E+02 4.00498E+06 + 2.32200E+02 3.77849E+06 + 2.32300E+02 3.61508E+06 + 2.32400E+02 3.52172E+06 + 2.32500E+02 3.50239E+06 + 2.32600E+02 3.55793E+06 + 2.32700E+02 3.68599E+06 + 2.32800E+02 3.88108E+06 + 2.32900E+02 4.13474E+06 + 2.33000E+02 4.43627E+06 + 2.33100E+02 4.77263E+06 + 2.33200E+02 5.12944E+06 + 2.33300E+02 5.49149E+06 + 2.33400E+02 5.84315E+06 + 2.33500E+02 6.16946E+06 + 2.33600E+02 6.45630E+06 + 2.33700E+02 6.69156E+06 + 2.33800E+02 6.86507E+06 + 2.33900E+02 6.96937E+06 + 2.34000E+02 7.00004E+06 + 2.34100E+02 6.95576E+06 + 2.34200E+02 6.83843E+06 + 2.34300E+02 6.65303E+06 + 2.34400E+02 6.40757E+06 + 2.34500E+02 6.11254E+06 + 2.34600E+02 5.78057E+06 + 2.34700E+02 5.42583E+06 + 2.34800E+02 5.06363E+06 + 2.34900E+02 4.70942E+06 + 2.35000E+02 4.37833E+06 + 2.35100E+02 4.08468E+06 + 2.35200E+02 3.84087E+06 + 2.35300E+02 3.65746E+06 + 2.35400E+02 3.54231E+06 + 2.35500E+02 3.50032E+06 + 2.35600E+02 3.53328E+06 + 2.35700E+02 3.63981E+06 + 2.35800E+02 3.81532E+06 + 2.35900E+02 4.05229E+06 + 2.36000E+02 4.34062E+06 + 2.36100E+02 4.66783E+06 + 2.36200E+02 5.02008E+06 + 2.36300E+02 5.38220E+06 + 2.36400E+02 5.73856E+06 + 2.36500E+02 6.07410E+06 + 2.36600E+02 6.37431E+06 + 2.36700E+02 6.62637E+06 + 2.36800E+02 6.81950E+06 + 2.36900E+02 6.94539E+06 + 2.37000E+02 6.99867E+06 + 2.37100E+02 6.97705E+06 + 2.37200E+02 6.88145E+06 + 2.37300E+02 6.71596E+06 + 2.37400E+02 6.48774E+06 + 2.37500E+02 6.20644E+06 + 2.37600E+02 5.88422E+06 + 2.37700E+02 5.53485E+06 + 2.37800E+02 5.17323E+06 + 2.37900E+02 4.81497E+06 + 2.38000E+02 4.47535E+06 + 2.38100E+02 4.16893E+06 + 2.38200E+02 3.90879E+06 + 2.38300E+02 3.70615E+06 + 2.38400E+02 3.56965E+06 + 2.38500E+02 3.50514E+06 + 2.38600E+02 3.51539E+06 + 2.38700E+02 3.59997E+06 + 2.38800E+02 3.75526E+06 + 2.38900E+02 3.97456E+06 + 2.39000E+02 4.24851E+06 + 2.39100E+02 4.56537E+06 + 2.39200E+02 4.91162E+06 + 2.39300E+02 5.27233E+06 + 2.39400E+02 5.63209E+06 + 2.39500E+02 5.97555E+06 + 2.39600E+02 6.28784E+06 + 2.39700E+02 6.55577E+06 + 2.39800E+02 6.76777E+06 + 2.39900E+02 6.91471E+06 + 2.40000E+02 6.99039E+06 + 2.40100E+02 6.99152E+06 + 2.40200E+02 6.91805E+06 + 2.40300E+02 6.77313E+06 + 2.40400E+02 6.56299E+06 + 2.40500E+02 6.29657E+06 + 2.40600E+02 5.98542E+06 + 2.40700E+02 5.64269E+06 + 2.40800E+02 5.28314E+06 + 2.40900E+02 4.92229E+06 + 2.41000E+02 4.57539E+06 + 2.41100E+02 4.25744E+06 + 2.41200E+02 3.98203E+06 + 2.41300E+02 3.76090E+06 + 2.41400E+02 3.60362E+06 + 2.41500E+02 3.51686E+06 + 2.41600E+02 3.50436E+06 + 2.41700E+02 3.56666E+06 + 2.41800E+02 3.70106E+06 + 2.41900E+02 3.90183E+06 + 2.42000E+02 4.16040E+06 + 2.42100E+02 4.46558E+06 + 2.42200E+02 4.80445E+06 + 2.42300E+02 5.16243E+06 + 2.42400E+02 5.52412E+06 + 2.42500E+02 5.87408E+06 + 2.42600E+02 6.19732E+06 + 2.42700E+02 6.48003E+06 + 2.42800E+02 6.71002E+06 + 2.42900E+02 6.87748E+06 + 2.43000E+02 6.97525E+06 + 2.43100E+02 6.99911E+06 + 2.43200E+02 6.94806E+06 + 2.43300E+02 6.82426E+06 + 2.43400E+02 6.63309E+06 + 2.43500E+02 6.38262E+06 + 2.43600E+02 6.08368E+06 + 2.43700E+02 5.74904E+06 + 2.43800E+02 5.39298E+06 + 2.43900E+02 5.03086E+06 + 2.44000E+02 4.67814E+06 + 2.44100E+02 4.34992E+06 + 2.44200E+02 4.06023E+06 + 2.44300E+02 3.82154E+06 + 2.44400E+02 3.64410E+06 + 2.44500E+02 3.53542E+06 + 2.44600E+02 3.50021E+06 + 2.44700E+02 3.53997E+06 + 2.44800E+02 3.65301E+06 + 2.44900E+02 3.83446E+06 + 2.45000E+02 4.07655E+06 + 2.45100E+02 4.36892E+06 + 2.45200E+02 4.69909E+06 + 2.45300E+02 5.05283E+06 + 2.45400E+02 5.41502E+06 + 2.45500E+02 5.77020E+06 + 2.45600E+02 6.10302E+06 + 2.45700E+02 6.39940E+06 + 2.45800E+02 6.64654E+06 + 2.45900E+02 6.83381E+06 + 2.46000E+02 6.95329E+06 + 2.46100E+02 6.99981E+06 + 2.46200E+02 6.97137E+06 + 2.46300E+02 6.86921E+06 + 2.46400E+02 6.69770E+06 + 2.46500E+02 6.46415E+06 + 2.46600E+02 6.17868E+06 + 2.46700E+02 5.85336E+06 + 2.46800E+02 5.50219E+06 + 2.46900E+02 5.14034E+06 + 2.47000E+02 4.78304E+06 + 2.47100E+02 4.44596E+06 + 2.47200E+02 4.14314E+06 + 2.47300E+02 3.88784E+06 + 2.47400E+02 3.69090E+06 + 2.47500E+02 3.56075E+06 + 2.47600E+02 3.50297E+06 + 2.47700E+02 3.52004E+06 + 2.47800E+02 3.61126E+06 + 2.47900E+02 3.77267E+06 + 2.48000E+02 3.99737E+06 + 2.48100E+02 4.27574E+06 + 2.48200E+02 4.59586E+06 + 2.48300E+02 4.94400E+06 + 2.48400E+02 5.30526E+06 + 2.48500E+02 5.66427E+06 + 2.48600E+02 6.00535E+06 + 2.48700E+02 6.31427E+06 + 2.48800E+02 6.57751E+06 + 2.48900E+02 6.78391E+06 + 2.49000E+02 6.92461E+06 + 2.49100E+02 6.99359E+06 + 2.49200E+02 6.98789E+06 + 2.49300E+02 6.90774E+06 + 2.49400E+02 6.75660E+06 + 2.49500E+02 6.54093E+06 + 2.49600E+02 6.26998E+06 + 2.49700E+02 5.95535E+06 + 2.49800E+02 5.61042E+06 + 2.49900E+02 5.25026E+06 + 2.50000E+02 4.88989E+06 + 2.50100E+02 4.54507E+06 + 2.50200E+02 4.23045E+06 + 2.50300E+02 3.95952E+06 + 2.50400E+02 3.74387E+06 + 2.50500E+02 3.59272E+06 + 2.50600E+02 3.51263E+06 + 2.50700E+02 3.50695E+06 + 2.50800E+02 3.57596E+06 + 2.50900E+02 3.71669E+06 + 2.51000E+02 3.92310E+06 + 2.51100E+02 4.18637E+06 + 2.51200E+02 4.49520E+06 + 2.51300E+02 4.83649E+06 + 2.51400E+02 5.19540E+06 + 2.51500E+02 5.55666E+06 + 2.51600E+02 5.90480E+06 + 2.51700E+02 6.22490E+06 + 2.51800E+02 6.50325E+06 + 2.51900E+02 6.72793E+06 + 2.52000E+02 6.88935E+06 + 2.52100E+02 6.98050E+06 + 2.52200E+02 6.99755E+06 + 2.52300E+02 6.93975E+06 + 2.52400E+02 6.80958E+06 + 2.52500E+02 6.61262E+06 + 2.52600E+02 6.35730E+06 + 2.52700E+02 6.05447E+06 + 2.52800E+02 5.71727E+06 + 2.52900E+02 5.36007E+06 + 2.53000E+02 4.99816E+06 + 2.53100E+02 4.64706E+06 + 2.53200E+02 4.32179E+06 + 2.53300E+02 4.03622E+06 + 2.53400E+02 3.80280E+06 + 2.53500E+02 3.63126E+06 + 2.53600E+02 3.52914E+06 + 2.53700E+02 3.50073E+06 + 2.53800E+02 3.54727E+06 + 2.53900E+02 3.66676E+06 + 2.54000E+02 3.85407E+06 + 2.54100E+02 4.10119E+06 + 2.54200E+02 4.39763E+06 + 2.54300E+02 4.73050E+06 + 2.54400E+02 5.08564E+06 + 2.54500E+02 5.44783E+06 + 2.54600E+02 5.80156E+06 + 2.54700E+02 6.13168E+06 + 2.54800E+02 6.42412E+06 + 2.54900E+02 6.66618E+06 + 2.55000E+02 6.84760E+06 + 2.55100E+02 6.96059E+06 + 2.55200E+02 7.00032E+06 + 2.55300E+02 6.96509E+06 + 2.55400E+02 6.85641E+06 + 2.55500E+02 6.67887E+06 + 2.55600E+02 6.44025E+06 + 2.55700E+02 6.15051E+06 + 2.55800E+02 5.82228E+06 + 2.55900E+02 5.46955E+06 + 2.56000E+02 5.10743E+06 + 2.56100E+02 4.75133E+06 + 2.56200E+02 4.41670E+06 + 2.56300E+02 4.11786E+06 + 2.56400E+02 3.86737E+06 + 2.56500E+02 3.67620E+06 + 2.56600E+02 3.55245E+06 + 2.56700E+02 3.50142E+06 + 2.56800E+02 3.52531E+06 + 2.56900E+02 3.62308E+06 + 2.57000E+02 3.79061E+06 + 2.57100E+02 4.02063E+06 + 2.57200E+02 4.30332E+06 + 2.57300E+02 4.62657E+06 + 2.57400E+02 4.97654E+06 + 2.57500E+02 5.33823E+06 + 2.57600E+02 5.69626E+06 + 2.57700E+02 6.03507E+06 + 2.57800E+02 6.34027E+06 + 2.57900E+02 6.59878E+06 + 2.58000E+02 6.79953E+06 + 2.58100E+02 6.93394E+06 + 2.58200E+02 6.99619E+06 + 2.58300E+02 6.98366E+06 + 2.58400E+02 6.89686E+06 + 2.58500E+02 6.73954E+06 + 2.58600E+02 6.51842E+06 + 2.58700E+02 6.24290E+06 + 2.58800E+02 5.92503E+06 + 2.58900E+02 5.57817E+06 + 2.59000E+02 5.21716E+06 + 2.59100E+02 4.85767E+06 + 2.59200E+02 4.51500E+06 + 2.59300E+02 4.20382E+06 + 2.59400E+02 3.93747E+06 + 2.59500E+02 3.72735E+06 + 2.59600E+02 3.58243E+06 + 2.59700E+02 3.50900E+06 + 2.59800E+02 3.51015E+06 + 2.59900E+02 3.58586E+06 + 2.60000E+02 3.73285E+06 + 2.60100E+02 3.94484E+06 + 2.60200E+02 4.21284E+06 + 2.60300E+02 4.52510E+06 + 2.60400E+02 4.86851E+06 + 2.60500E+02 5.22838E+06 + 2.60600E+02 5.58909E+06 + 2.60700E+02 5.93528E+06 + 2.60800E+02 6.25212E+06 + 2.60900E+02 6.52606E+06 + 2.61000E+02 6.74535E+06 + 2.61100E+02 6.90063E+06 + 2.61200E+02 6.98516E+06 + 2.61300E+02 6.99539E+06 + 2.61400E+02 6.93085E+06 + 2.61500E+02 6.79433E+06 + 2.61600E+02 6.59160E+06 + 2.61700E+02 6.33147E+06 + 2.61800E+02 6.02512E+06 + 2.61900E+02 5.68539E+06 + 2.62000E+02 5.32712E+06 + 2.62100E+02 4.96556E+06 + 2.62200E+02 4.61610E+06 + 2.62300E+02 4.29399E+06 + 2.62400E+02 4.01275E+06 + 2.62500E+02 3.78445E+06 + 2.62600E+02 3.61902E+06 + 2.62700E+02 3.52346E+06 + 2.62800E+02 3.50187E+06 + 2.62900E+02 3.55518E+06 + 2.63000E+02 3.68109E+06 + 2.63100E+02 3.87428E+06 + 2.63200E+02 4.12636E+06 + 2.63300E+02 4.42649E+06 + 2.63400E+02 4.76210E+06 + 2.63500E+02 5.11852E+06 + 2.63600E+02 5.48058E+06 + 2.63700E+02 5.83288E+06 + 2.63800E+02 6.16002E+06 + 2.63900E+02 6.44830E+06 + 2.64000E+02 6.68532E+06 + 2.64100E+02 6.86079E+06 + 2.64200E+02 6.96728E+06 + 2.64300E+02 7.00022E+06 + 2.64400E+02 6.95820E+06 + 2.64500E+02 6.84302E+06 + 2.64600E+02 6.65956E+06 + 2.64700E+02 6.41577E+06 + 2.64800E+02 6.12215E+06 + 2.64900E+02 5.79100E+06 + 2.65000E+02 5.43678E+06 + 2.65100E+02 5.07447E+06 + 2.65200E+02 4.71980E+06 + 2.65300E+02 4.38794E+06 + 2.65400E+02 4.09283E+06 + 2.65500E+02 3.84740E+06 + 2.65600E+02 3.66206E+06 + 2.65700E+02 3.54472E+06 + 2.65800E+02 3.50049E+06 + 2.65900E+02 3.53118E+06 + 2.66000E+02 3.63556E+06 + 2.66100E+02 3.80907E+06 + 2.66200E+02 4.04432E+06 + 2.66300E+02 4.33123E+06 + 2.66400E+02 4.65751E+06 + 2.66500E+02 5.00917E+06 + 2.66600E+02 5.37127E+06 + 2.66700E+02 5.72808E+06 + 2.66800E+02 6.06433E+06 + 2.66900E+02 6.36589E+06 + 2.67000E+02 6.61957E+06 + 2.67100E+02 6.81460E+06 + 2.67200E+02 6.94265E+06 + 2.67300E+02 6.99815E+06 + 2.67400E+02 6.97881E+06 + 2.67500E+02 6.88539E+06 + 2.67600E+02 6.72194E+06 + 2.67700E+02 6.49546E+06 + 2.67800E+02 6.21564E+06 + 2.67900E+02 5.89447E+06 + 2.68000E+02 5.54571E+06 + 2.68100E+02 5.18418E+06 + 2.68200E+02 4.82559E+06 + 2.68300E+02 4.48529E+06 + 2.68400E+02 4.17756E+06 + 2.68500E+02 3.91588E+06 + 2.68600E+02 3.71131E+06 + 2.68700E+02 3.57273E+06 + 2.68800E+02 3.50601E+06 + 2.68900E+02 3.51399E+06 + 2.69000E+02 3.59635E+06 + 2.69100E+02 3.74956E+06 + 2.69200E+02 3.96712E+06 + 2.69300E+02 4.23950E+06 + 2.69400E+02 4.55526E+06 + 2.69500E+02 4.90088E+06 + 2.69600E+02 5.26137E+06 + 2.69700E+02 5.62139E+06 + 2.69800E+02 5.96551E+06 + 2.69900E+02 6.27900E+06 + 2.70000E+02 6.54842E+06 + 2.70100E+02 6.76228E+06 + 2.70200E+02 6.91131E+06 + 2.70300E+02 6.98918E+06 + 2.70400E+02 6.99258E+06 + 2.70500E+02 6.92134E+06 + 2.70600E+02 6.77852E+06 + 2.70700E+02 6.57017E+06 + 2.70800E+02 6.30542E+06 + 2.70900E+02 5.99540E+06 + 2.71000E+02 5.65336E+06 + 2.71100E+02 5.29415E+06 + 2.71200E+02 4.93306E+06 + 2.71300E+02 4.58556E+06 + 2.71400E+02 4.26653E+06 + 2.71500E+02 3.98964E+06 + 2.71600E+02 3.76669E+06 + 2.71700E+02 3.60736E+06 + 2.71800E+02 3.51842E+06 + 2.71900E+02 3.50364E+06 + 2.72000E+02 3.56368E+06 + 2.72100E+02 3.69602E+06 + 2.72200E+02 3.89491E+06 + 2.72300E+02 4.15177E+06 + 2.72400E+02 4.45584E+06 + 2.72500E+02 4.79387E+06 + 2.72600E+02 5.15144E+06 + 2.72700E+02 5.51335E+06 + 2.72800E+02 5.86378E+06 + 2.72900E+02 6.18804E+06 + 2.73000E+02 6.47221E+06 + 2.73100E+02 6.70395E+06 + 2.73200E+02 6.87342E+06 + 2.73300E+02 6.97336E+06 + 2.73400E+02 6.99949E+06 + 2.73500E+02 6.95070E+06 + 2.73600E+02 6.82902E+06 + 2.73700E+02 6.63974E+06 + 2.73800E+02 6.39103E+06 + 2.73900E+02 6.09329E+06 + 2.74000E+02 5.75953E+06 + 2.74100E+02 5.40395E+06 + 2.74200E+02 5.04168E+06 + 2.74300E+02 4.68855E+06 + 2.74400E+02 4.35938E+06 + 2.74500E+02 4.06829E+06 + 2.74600E+02 3.82792E+06 + 2.74700E+02 3.64848E+06 + 2.74800E+02 3.53765E+06 + 2.74900E+02 3.50018E+06 + 2.75000E+02 3.53767E+06 + 2.75100E+02 3.64857E+06 + 2.75200E+02 3.82805E+06 + 2.75300E+02 4.06837E+06 + 2.75400E+02 4.35947E+06 + 2.75500E+02 4.68865E+06 + 2.75600E+02 5.04200E+06 + 2.75700E+02 5.40416E+06 + 2.75800E+02 5.75963E+06 + 2.75900E+02 6.09348E+06 + 2.76000E+02 6.39111E+06 + 2.76100E+02 6.63987E+06 + 2.76200E+02 6.82916E+06 + 2.76300E+02 6.95072E+06 + 2.76400E+02 6.99949E+06 + 2.76500E+02 6.97332E+06 + 2.76600E+02 6.87334E+06 + 2.76700E+02 6.70383E+06 + 2.76800E+02 6.47206E+06 + 2.76900E+02 6.18795E+06 + 2.77000E+02 5.86368E+06 + 2.77100E+02 5.51303E+06 + 2.77200E+02 5.15123E+06 + 2.77300E+02 4.79376E+06 + 2.77400E+02 4.45566E+06 + 2.77500E+02 4.15169E+06 + 2.77600E+02 3.89477E+06 + 2.77700E+02 3.69588E+06 + 2.77800E+02 3.56366E+06 + 2.77900E+02 3.50363E+06 + 2.78000E+02 3.51844E+06 + 2.78100E+02 3.60743E+06 + 2.78200E+02 3.76680E+06 + 2.78300E+02 3.98971E+06 + 2.78400E+02 4.26662E+06 + 2.78500E+02 4.58566E+06 + 2.78600E+02 4.93327E+06 + 2.78700E+02 5.29436E+06 + 2.78800E+02 5.65346E+06 + 2.78900E+02 5.99550E+06 + 2.79000E+02 6.30550E+06 + 2.79100E+02 6.57031E+06 + 2.79200E+02 6.77863E+06 + 2.79300E+02 6.92137E+06 + 2.79400E+02 6.99260E+06 + 2.79500E+02 6.98916E+06 + 2.79600E+02 6.91124E+06 + 2.79700E+02 6.76212E+06 + 2.79800E+02 6.54834E+06 + 2.79900E+02 6.27891E+06 + 2.80000E+02 5.96532E+06 + 2.80100E+02 5.62119E+06 + 2.80200E+02 5.26116E+06 + 2.80300E+02 4.90067E+06 + 2.80400E+02 4.55516E+06 + 2.80500E+02 4.23942E+06 + 2.80600E+02 3.96691E+06 + 2.80700E+02 3.74945E+06 + 2.80800E+02 3.59632E+06 + 2.80900E+02 3.51397E+06 + 2.81000E+02 3.50602E+06 + 2.81100E+02 3.57279E+06 + 2.81200E+02 3.71146E+06 + 2.81300E+02 3.91595E+06 + 2.81400E+02 4.17765E+06 + 2.81500E+02 4.48538E+06 + 2.81600E+02 4.82580E+06 + 2.81700E+02 5.18439E+06 + 2.81800E+02 5.54581E+06 + 2.81900E+02 5.89457E+06 + 2.82000E+02 6.21573E+06 + 2.82100E+02 6.49561E+06 + 2.82200E+02 6.72206E+06 + 2.82300E+02 6.88543E+06 + 2.82400E+02 6.97882E+06 + 2.82500E+02 6.99814E+06 + 2.82600E+02 6.94259E+06 + 2.82700E+02 6.81450E+06 + 2.82800E+02 6.61951E+06 + 2.82900E+02 6.36581E+06 + 2.83000E+02 6.06423E+06 + 2.83100E+02 5.72787E+06 + 2.83200E+02 5.37095E+06 + 2.83300E+02 5.00907E+06 + 2.83400E+02 4.65741E+06 + 2.83500E+02 4.33105E+06 + 2.83600E+02 4.04417E+06 + 2.83700E+02 3.80895E+06 + 2.83800E+02 3.63547E+06 + 2.83900E+02 3.53116E+06 + 2.84000E+02 3.50049E+06 + 2.84100E+02 3.54479E+06 + 2.84200E+02 3.66215E+06 + 2.84300E+02 3.84746E+06 + 2.84400E+02 4.09299E+06 + 2.84500E+02 4.38803E+06 + 2.84600E+02 4.72000E+06 + 2.84700E+02 5.07479E+06 + 2.84800E+02 5.43689E+06 + 2.84900E+02 5.79110E+06 + 2.85000E+02 6.12224E+06 + 2.85100E+02 6.41593E+06 + 2.85200E+02 6.65968E+06 + 2.85300E+02 6.84306E+06 + 2.85400E+02 6.95822E+06 + 2.85500E+02 7.00022E+06 + 2.85600E+02 6.96724E+06 + 2.85700E+02 6.86071E+06 + 2.85800E+02 6.68526E+06 + 2.85900E+02 6.44822E+06 + 2.86000E+02 6.15993E+06 + 2.86100E+02 5.83268E+06 + 2.86200E+02 5.48037E+06 + 2.86300E+02 5.11841E+06 + 2.86400E+02 4.76200E+06 + 2.86500E+02 4.42640E+06 + 2.86600E+02 4.12620E+06 + 2.86700E+02 3.87408E+06 + 2.86800E+02 3.68104E+06 + 2.86900E+02 3.55515E+06 + 2.87000E+02 3.50186E+06 + 2.87100E+02 3.52350E+06 + 2.87200E+02 3.61910E+06 + 2.87300E+02 3.78457E+06 + 2.87400E+02 4.01282E+06 + 2.87500E+02 4.29408E+06 + 2.87600E+02 4.61639E+06 + 2.87700E+02 4.96577E+06 + 2.87800E+02 5.32723E+06 + 2.87900E+02 5.68560E+06 + 2.88000E+02 6.02522E+06 + 2.88100E+02 6.33164E+06 + 2.88200E+02 6.59181E+06 + 2.88300E+02 6.79438E+06 + 2.88400E+02 6.93088E+06 + 2.88500E+02 6.99539E+06 + 2.88600E+02 6.98513E+06 + 2.88700E+02 6.90056E+06 + 2.88800E+02 6.74529E+06 + 2.88900E+02 6.52599E+06 + 2.89000E+02 6.25204E+06 + 2.89100E+02 5.93508E+06 + 2.89200E+02 5.58888E+06 + 2.89300E+02 5.22828E+06 + 2.89400E+02 4.86841E+06 + 2.89500E+02 4.52500E+06 + 2.89600E+02 4.21267E+06 + 2.89700E+02 3.94470E+06 + 2.89800E+02 3.73280E+06 + 2.89900E+02 3.58583E+06 + 2.90000E+02 3.51014E+06 + 2.90100E+02 3.50902E+06 + 2.90200E+02 3.58252E+06 + 2.90300E+02 3.72740E+06 + 2.90400E+02 3.93754E+06 + 2.90500E+02 4.20399E+06 + 2.90600E+02 4.51519E+06 + 2.90700E+02 4.85788E+06 + 2.90800E+02 5.21737E+06 + 2.90900E+02 5.57828E+06 + 2.91000E+02 5.92513E+06 + 2.91100E+02 6.24316E+06 + 2.91200E+02 6.51857E+06 + 2.91300E+02 6.73959E+06 + 2.91400E+02 6.89693E+06 + 2.91500E+02 6.98368E+06 + 2.91600E+02 6.99617E+06 + 2.91700E+02 6.93386E+06 + 2.91800E+02 6.79948E+06 + 2.91900E+02 6.59872E+06 + 2.92000E+02 6.34011E+06 + 2.92100E+02 6.03488E+06 + 2.92200E+02 5.69605E+06 + 2.92300E+02 5.33812E+06 + 2.92400E+02 4.97643E+06 + 2.92500E+02 4.62647E+06 + 2.92600E+02 4.30314E+06 + 2.92700E+02 4.02048E+06 + 2.92800E+02 3.79056E+06 + 2.92900E+02 3.62304E+06 + 2.93000E+02 3.52529E+06 + 2.93100E+02 3.50142E+06 + 2.93200E+02 3.55250E+06 + 2.93300E+02 3.67624E+06 + 2.93400E+02 3.86744E+06 + 2.93500E+02 4.11794E+06 + 2.93600E+02 4.41689E+06 + 2.93700E+02 4.75164E+06 + 2.93800E+02 5.10754E+06 + 2.93900E+02 5.46966E+06 + 2.94000E+02 5.82248E+06 + 2.94100E+02 6.15069E+06 + 2.94200E+02 6.44033E+06 + 2.94300E+02 6.67899E+06 + 2.94400E+02 6.85645E+06 + 2.94500E+02 6.96511E+06 + 2.94600E+02 7.00032E+06 + 2.94700E+02 6.96054E+06 + 2.94800E+02 6.84755E+06 + 2.94900E+02 6.66606E+06 + 2.95000E+02 6.42396E+06 + 2.95100E+02 6.13159E+06 + 2.95200E+02 5.80136E+06 + 2.95300E+02 5.44773E+06 + 2.95400E+02 5.08554E+06 + 2.95500E+02 4.73030E+06 + 2.95600E+02 4.39744E+06 + 2.95700E+02 4.10111E+06 + 2.95800E+02 3.85401E+06 + 2.95900E+02 3.66671E+06 + 2.96000E+02 3.54725E+06 + 2.96100E+02 3.50073E+06 + 2.96200E+02 3.52917E+06 + 2.96300E+02 3.63130E+06 + 2.96400E+02 3.80286E+06 + 2.96500E+02 4.03637E+06 + 2.96600E+02 4.32188E+06 + 2.96700E+02 4.64726E+06 + 2.96800E+02 4.99827E+06 + 2.96900E+02 5.36018E+06 + 2.97000E+02 5.71748E+06 + 2.97100E+02 6.05466E+06 + 2.97200E+02 6.35747E+06 + 2.97300E+02 6.61269E+06 + 2.97400E+02 6.80963E+06 + 2.97500E+02 6.93981E+06 + 2.97600E+02 6.99757E+06 + 2.97700E+02 6.98048E+06 + 2.97800E+02 6.88928E+06 + 2.97900E+02 6.72787E+06 + 2.98000E+02 6.50318E+06 + 2.98100E+02 6.22472E+06 + 2.98200E+02 5.90460E+06 + 2.98300E+02 5.55656E+06 + 2.98400E+02 5.19519E+06 + 2.98500E+02 4.83628E+06 + 2.98600E+02 4.49511E+06 + 2.98700E+02 4.18620E+06 + 2.98800E+02 3.92303E+06 + 2.98900E+02 3.71664E+06 + 2.99000E+02 3.57590E+06 + 2.99100E+02 3.50694E+06 + 2.99200E+02 3.51265E+06 + 2.99300E+02 3.59279E+06 + 2.99400E+02 3.74393E+06 + 2.99500E+02 3.95959E+06 + 2.99600E+02 4.23062E+06 + 2.99700E+02 4.54526E+06 + 2.99800E+02 4.88999E+06 + 2.99900E+02 5.25036E+06 + 3.00000E+02 5.61062E+06 + 3.00100E+02 5.95545E+06 + 3.00200E+02 6.27016E+06 + 3.00300E+02 6.54101E+06 + 3.00400E+02 6.75665E+06 + 3.00500E+02 6.90781E+06 + 3.00600E+02 6.98791E+06 + 3.00700E+02 6.99358E+06 + 3.00800E+02 6.92458E+06 + 3.00900E+02 6.78386E+06 + 3.01000E+02 6.57738E+06 + 3.01100E+02 6.31410E+06 + 3.01200E+02 6.00525E+06 + 3.01300E+02 5.66407E+06 + 3.01400E+02 5.30516E+06 + 3.01500E+02 4.94390E+06 + 3.01600E+02 4.59566E+06 + 3.01700E+02 4.27557E+06 + 3.01800E+02 3.99730E+06 + 3.01900E+02 3.77256E+06 + 3.02000E+02 3.61119E+06 + 3.02100E+02 3.52003E+06 + 3.02200E+02 3.50299E+06 + 3.02300E+02 3.56078E+06 + 3.02400E+02 3.69094E+06 + 3.02500E+02 3.88797E+06 + 3.02600E+02 4.14330E+06 + 3.02700E+02 4.44605E+06 + 3.02800E+02 4.78324E+06 + 3.02900E+02 5.14045E+06 + 3.03000E+02 5.50235E+06 + 3.03100E+02 5.85356E+06 + 3.03200E+02 6.17882E+06 + 3.03300E+02 6.46423E+06 + 3.03400E+02 6.69779E+06 + 3.03500E+02 6.86927E+06 + 3.03600E+02 6.97140E+06 + 3.03700E+02 6.99980E+06 + 3.03800E+02 6.95327E+06 + 3.03900E+02 6.83379E+06 + 3.04000E+02 6.64641E+06 + 3.04100E+02 6.39928E+06 + 3.04200E+02 6.10293E+06 + 3.04300E+02 5.77005E+06 + 3.04400E+02 5.41491E+06 + 3.04500E+02 5.05262E+06 + 3.04600E+02 4.69889E+06 + 3.04700E+02 4.36878E+06 + 3.04800E+02 4.07643E+06 + 3.04900E+02 3.83437E+06 + 3.05000E+02 3.65295E+06 + 3.05100E+02 3.53993E+06 + 3.05200E+02 3.50021E+06 + 3.05300E+02 3.53544E+06 + 3.05400E+02 3.64416E+06 + 3.05500E+02 3.82166E+06 + 3.05600E+02 4.06035E+06 + 3.05700E+02 4.35010E+06 + 3.05800E+02 4.67824E+06 + 3.05900E+02 5.03096E+06 + 3.06000E+02 5.39319E+06 + 3.06100E+02 5.74919E+06 + 3.06200E+02 6.08382E+06 + 3.06300E+02 6.38274E+06 + 3.06400E+02 6.63315E+06 + 3.06500E+02 6.82433E+06 + 3.06600E+02 6.94811E+06 + 3.06700E+02 6.99912E+06 + 3.06800E+02 6.97523E+06 + 3.06900E+02 6.87742E+06 + 3.07000E+02 6.70993E+06 + 3.07100E+02 6.47992E+06 + 3.07200E+02 6.19714E+06 + 3.07300E+02 5.87398E+06 + 3.07400E+02 5.52402E+06 + 3.07500E+02 5.16222E+06 + 3.07600E+02 4.80430E+06 + 3.07700E+02 4.46548E+06 + 3.07800E+02 4.16028E+06 + 3.07900E+02 3.90177E+06 + 3.08000E+02 3.70102E+06 + 3.08100E+02 3.56660E+06 + 3.08200E+02 3.50435E+06 + 3.08300E+02 3.51689E+06 + 3.08400E+02 3.60367E+06 + 3.08500E+02 3.76099E+06 + 3.08600E+02 3.98217E+06 + 3.08700E+02 4.25762E+06 + 3.08800E+02 4.57548E+06 + 3.08900E+02 4.92245E+06 + 3.09000E+02 5.28336E+06 + 3.09100E+02 5.64284E+06 + 3.09200E+02 5.98562E+06 + 3.09300E+02 6.29670E+06 + 3.09400E+02 6.56306E+06 + 3.09500E+02 6.77323E+06 + 3.09600E+02 6.91810E+06 + 3.09700E+02 6.99153E+06 + 3.09800E+02 6.99037E+06 + 3.09900E+02 6.91468E+06 + 3.10000E+02 6.76769E+06 + 3.10100E+02 6.55563E+06 + 3.10200E+02 6.28771E+06 + 3.10300E+02 5.97545E+06 + 3.10400E+02 5.63194E+06 + 3.10500E+02 5.27217E+06 + 3.10600E+02 4.91147E+06 + 3.10700E+02 4.56518E+06 + 3.10800E+02 4.24843E+06 + 3.10900E+02 3.97449E+06 + 3.11000E+02 3.75514E+06 + 3.11100E+02 3.59992E+06 + 3.11200E+02 3.51538E+06 + 3.11300E+02 3.50516E+06 + 3.11400E+02 3.56968E+06 + 3.11500E+02 3.70620E+06 + 3.11600E+02 3.90892E+06 + 3.11700E+02 4.16905E+06 + 3.11800E+02 4.47540E+06 + 3.11900E+02 4.81512E+06 + 3.12000E+02 5.17339E+06 + 3.12100E+02 5.53506E+06 + 3.12200E+02 5.88442E+06 + 3.12300E+02 6.20653E+06 + 3.12400E+02 6.48785E+06 + 3.12500E+02 6.71607E+06 + 3.12600E+02 6.88151E+06 + 3.12700E+02 6.97709E+06 + 3.12800E+02 6.99866E+06 + 3.12900E+02 6.94536E+06 + 3.13000E+02 6.81941E+06 + 3.13100E+02 6.62627E+06 + 3.13200E+02 6.37419E+06 + 3.13300E+02 6.07396E+06 + 3.13400E+02 5.73846E+06 + 3.13500E+02 5.38204E+06 + 3.13600E+02 5.01987E+06 + 3.13700E+02 4.66768E+06 + 3.13800E+02 4.34053E+06 + 3.13900E+02 4.05217E+06 + 3.14000E+02 3.81523E+06 + 3.14100E+02 3.63975E+06 + 3.14200E+02 3.53324E+06 + 3.14300E+02 3.50032E+06 + 3.14400E+02 3.54233E+06 + 3.14500E+02 3.65755E+06 + 3.14600E+02 3.84097E+06 + 3.14700E+02 4.08475E+06 + 3.14800E+02 4.37846E+06 + 3.14900E+02 4.70952E+06 + 3.15000E+02 5.06373E+06 + 3.15100E+02 5.42604E+06 + 3.15200E+02 5.78072E+06 + 3.15300E+02 6.11258E+06 + 3.15400E+02 6.40769E+06 + 3.15500E+02 6.65313E+06 + 3.15600E+02 6.83852E+06 + 3.15700E+02 6.95581E+06 + 3.15800E+02 7.00005E+06 + 3.15900E+02 6.96934E+06 + 3.16000E+02 6.86499E+06 + 3.16100E+02 6.69147E+06 + 3.16200E+02 6.45615E+06 + 3.16300E+02 6.16932E+06 + 3.16400E+02 5.84305E+06 + 3.16500E+02 5.49128E+06 + 3.16600E+02 5.12929E+06 + 3.16700E+02 4.77248E+06 + 3.16800E+02 4.43613E+06 + 3.16900E+02 4.13466E+06 + 3.17000E+02 3.88098E+06 + 3.17100E+02 3.68590E+06 + 3.17200E+02 3.55789E+06 + 3.17300E+02 3.50239E+06 + 3.17400E+02 3.52174E+06 + 3.17500E+02 3.61514E+06 + 3.17600E+02 3.77858E+06 + 3.17700E+02 4.00513E+06 + 3.17800E+02 4.28488E+06 + 3.17900E+02 4.60604E+06 + 3.18000E+02 4.95491E+06 + 3.18100E+02 5.31633E+06 + 3.18200E+02 5.67493E+06 + 3.18300E+02 6.01533E+06 + 3.18400E+02 6.32296E+06 + 3.18500E+02 6.58464E+06 + 3.18600E+02 6.78922E+06 + 3.18700E+02 6.92780E+06 + 3.18800E+02 6.99452E+06 + 3.18900E+02 6.98655E+06 + 3.19000E+02 6.90419E+06 + 3.19100E+02 6.75093E+06 + 3.19200E+02 6.53343E+06 + 3.19300E+02 6.26105E+06 + 3.19400E+02 5.94520E+06 + 3.19500E+02 5.59967E+06 + 3.19600E+02 5.23918E+06 + 3.19700E+02 4.87906E+06 + 3.19800E+02 4.53504E+06 + 3.19900E+02 4.22155E+06 + 3.20000E+02 3.95206E+06 + 3.20100E+02 3.73826E+06 + 3.20200E+02 3.58923E+06 + 3.20300E+02 3.51135E+06 + 3.20400E+02 3.50795E+06 + 3.20500E+02 3.57919E+06 + 3.20600E+02 3.72205E+06 + 3.20700E+02 3.93035E+06 + 3.20800E+02 4.19510E+06 + 3.20900E+02 4.50521E+06 + 3.21000E+02 4.84716E+06 + 3.21100E+02 5.20636E+06 + 3.21200E+02 5.56756E+06 + 3.21300E+02 5.91496E+06 + 3.21400E+02 6.23399E+06 + 3.21500E+02 6.51096E+06 + 3.21600E+02 6.73384E+06 + 3.21700E+02 6.89317E+06 + 3.21800E+02 6.98213E+06 + 3.21900E+02 6.99690E+06 + 3.22000E+02 6.93686E+06 + 3.22100E+02 6.80452E+06 + 3.22200E+02 6.60564E+06 + 3.22300E+02 6.34878E+06 + 3.22400E+02 6.04471E+06 + 3.22500E+02 5.70669E+06 + 3.22600E+02 5.34901E+06 + 3.22700E+02 4.98721E+06 + 3.22800E+02 4.63677E+06 + 3.22900E+02 4.31242E+06 + 3.23000E+02 4.02834E+06 + 3.23100E+02 3.79660E+06 + 3.23200E+02 3.62709E+06 + 3.23300E+02 3.52718E+06 + 3.23400E+02 3.50104E+06 + 3.23500E+02 3.54986E+06 + 3.23600E+02 3.67151E+06 + 3.23700E+02 3.86078E+06 + 3.23800E+02 4.10957E+06 + 3.23900E+02 4.40722E+06 + 3.24000E+02 4.74099E+06 + 3.24100E+02 5.09667E+06 + 3.24200E+02 5.45884E+06 + 3.24300E+02 5.81196E+06 + 3.24400E+02 6.14123E+06 + 3.24500E+02 6.43223E+06 + 3.24600E+02 6.67260E+06 + 3.24700E+02 6.85209E+06 + 3.24800E+02 6.96288E+06 + 3.24900E+02 7.00036E+06 + 3.25000E+02 6.96285E+06 + 3.25100E+02 6.85198E+06 + 3.25200E+02 6.67250E+06 + 3.25300E+02 6.43210E+06 + 3.25400E+02 6.14108E+06 + 3.25500E+02 5.81190E+06 + 3.25600E+02 5.45856E+06 + 3.25700E+02 5.09640E+06 + 3.25800E+02 4.74093E+06 + 3.25900E+02 4.40707E+06 + 3.26000E+02 4.10944E+06 + 3.26100E+02 3.86061E+06 + 3.26200E+02 3.67139E+06 + 3.26300E+02 3.54982E+06 + 3.26400E+02 3.50104E+06 + 3.26500E+02 3.52721E+06 + 3.26600E+02 3.62719E+06 + 3.26700E+02 3.79675E+06 + 3.26800E+02 4.02846E+06 + 3.26900E+02 4.31256E+06 + 3.27000E+02 4.63693E+06 + 3.27100E+02 4.98748E+06 + 3.27200E+02 5.34929E+06 + 3.27300E+02 5.70686E+06 + 3.27400E+02 6.04486E+06 + 3.27500E+02 6.34883E+06 + 3.27600E+02 6.60582E+06 + 3.27700E+02 6.80465E+06 + 3.27800E+02 6.93688E+06 + 3.27900E+02 6.99691E+06 + 3.28000E+02 6.98210E+06 + 3.28100E+02 6.89311E+06 + 3.28200E+02 6.73369E+06 + 3.28300E+02 6.51084E+06 + 3.28400E+02 6.23394E+06 + 3.28500E+02 5.91480E+06 + 3.28600E+02 5.56728E+06 + 3.28700E+02 5.20619E+06 + 3.28800E+02 4.84699E+06 + 3.28900E+02 4.50506E+06 + 3.29000E+02 4.19505E+06 + 3.29100E+02 3.93017E+06 + 3.29200E+02 3.72192E+06 + 3.29300E+02 3.57917E+06 + 3.29400E+02 3.50794E+06 + 3.29500E+02 3.51137E+06 + 3.29600E+02 3.58929E+06 + 3.29700E+02 3.73840E+06 + 3.29800E+02 3.95218E+06 + 3.29900E+02 4.22169E+06 + 3.30000E+02 4.53520E+06 + 3.30100E+02 4.87933E+06 + 3.30200E+02 5.23946E+06 + 3.30300E+02 5.59984E+06 + 3.30400E+02 5.94536E+06 + 3.30500E+02 6.26119E+06 + 3.30600E+02 6.53362E+06 + 3.30700E+02 6.75107E+06 + 3.30800E+02 6.90424E+06 + 3.30900E+02 6.98657E+06 + 3.31000E+02 6.99452E+06 + 3.31100E+02 6.92772E+06 + 3.31200E+02 6.78908E+06 + 3.31300E+02 6.58460E+06 + 3.31400E+02 6.32282E+06 + 3.31500E+02 6.01517E+06 + 3.31600E+02 5.67476E+06 + 3.31700E+02 5.31606E+06 + 3.31800E+02 4.95474E+06 + 3.31900E+02 4.60598E+06 + 3.32000E+02 4.28473E+06 + 3.32100E+02 4.00494E+06 + 3.32200E+02 3.77849E+06 + 3.32300E+02 3.61508E+06 + 3.32400E+02 3.52171E+06 + 3.32500E+02 3.50239E+06 + 3.32600E+02 3.55797E+06 + 3.32700E+02 3.68602E+06 + 3.32800E+02 3.88102E+06 + 3.32900E+02 4.13479E+06 + 3.33000E+02 4.43629E+06 + 3.33100E+02 4.77264E+06 + 3.33200E+02 5.12957E+06 + 3.33300E+02 5.49145E+06 + 3.33400E+02 5.84311E+06 + 3.33500E+02 6.16947E+06 + 3.33600E+02 6.45635E+06 + 3.33700E+02 6.69163E+06 + 3.33800E+02 6.86505E+06 + 3.33900E+02 6.96937E+06 + 3.34000E+02 7.00004E+06 + 3.34100E+02 6.95575E+06 + 3.34200E+02 6.83840E+06 + 3.34300E+02 6.65302E+06 + 3.34400E+02 6.40756E+06 + 3.34500E+02 6.11252E+06 + 3.34600E+02 5.78045E+06 + 3.34700E+02 5.42577E+06 + 3.34800E+02 5.06367E+06 + 3.34900E+02 4.70935E+06 + 3.35000E+02 4.37831E+06 + 3.35100E+02 4.08462E+06 + 3.35200E+02 3.84080E+06 + 3.35300E+02 3.65748E+06 + 3.35400E+02 3.54232E+06 + 3.35500E+02 3.50032E+06 + 3.35600E+02 3.53329E+06 + 3.35700E+02 3.63982E+06 + 3.35800E+02 3.81533E+06 + 3.35900E+02 4.05230E+06 + 3.36000E+02 4.34059E+06 + 3.36100E+02 4.66794E+06 + 3.36200E+02 5.02015E+06 + 3.36300E+02 5.38210E+06 + 3.36400E+02 5.73862E+06 + 3.36500E+02 6.07412E+06 + 3.36600E+02 6.37432E+06 + 3.36700E+02 6.62644E+06 + 3.36800E+02 6.81949E+06 + 3.36900E+02 6.94538E+06 + 3.37000E+02 6.99867E+06 + 3.37100E+02 6.97704E+06 + 3.37200E+02 6.88141E+06 + 3.37300E+02 6.71598E+06 + 3.37400E+02 6.48773E+06 + 3.37500E+02 6.20638E+06 + 3.37600E+02 5.88416E+06 + 3.37700E+02 5.53478E+06 + 3.37800E+02 5.17322E+06 + 3.37900E+02 4.81496E+06 + 3.38000E+02 4.47534E+06 + 3.38100E+02 4.16883E+06 + 3.38200E+02 3.90874E+06 + 3.38300E+02 3.70617E+06 + 3.38400E+02 3.56964E+06 + 3.38500E+02 3.50514E+06 + 3.38600E+02 3.51540E+06 + 3.38700E+02 3.60001E+06 + 3.38800E+02 3.75524E+06 + 3.38900E+02 3.97454E+06 + 3.39000E+02 4.24857E+06 + 3.39100E+02 4.56544E+06 + 3.39200E+02 4.91164E+06 + 3.39300E+02 5.27235E+06 + 3.39400E+02 5.63211E+06 + 3.39500E+02 5.97551E+06 + 3.39600E+02 6.28794E+06 + 3.39700E+02 6.55582E+06 + 3.39800E+02 6.76772E+06 + 3.39900E+02 6.91473E+06 + 3.40000E+02 6.99039E+06 + 3.40100E+02 6.99151E+06 + 3.40200E+02 6.91802E+06 + 3.40300E+02 6.77315E+06 + 3.40400E+02 6.56301E+06 + 3.40500E+02 6.29656E+06 + 3.40600E+02 5.98536E+06 + 3.40700E+02 5.64257E+06 + 3.40800E+02 5.28318E+06 + 3.40900E+02 4.92228E+06 + 3.41000E+02 4.57532E+06 + 3.41100E+02 4.25739E+06 + 3.41200E+02 3.98198E+06 + 3.41300E+02 3.76090E+06 + 3.41400E+02 3.60361E+06 + 3.41500E+02 3.51686E+06 + 3.41600E+02 3.50437E+06 + 3.41700E+02 3.56667E+06 + 3.41800E+02 3.70105E+06 + 3.41900E+02 3.90188E+06 + 3.42000E+02 4.16041E+06 + 3.42100E+02 4.46564E+06 + 3.42200E+02 4.80457E+06 + 3.42300E+02 5.16239E+06 + 3.42400E+02 5.52408E+06 + 3.42500E+02 5.87414E+06 + 3.42600E+02 6.19738E+06 + 3.42700E+02 6.48004E+06 + 3.42800E+02 6.71003E+06 + 3.42900E+02 6.87749E+06 + 3.43000E+02 6.97524E+06 + 3.43100E+02 6.99911E+06 + 3.43200E+02 6.94804E+06 + 3.43300E+02 6.82430E+06 + 3.43400E+02 6.63305E+06 + 3.43500E+02 6.38261E+06 + 3.43600E+02 6.08366E+06 + 3.43700E+02 5.74892E+06 + 3.43800E+02 5.39302E+06 + 3.43900E+02 5.03090E+06 + 3.44000E+02 4.67807E+06 + 3.44100E+02 4.34986E+06 + 3.44200E+02 4.06015E+06 + 3.44300E+02 3.82156E+06 + 3.44400E+02 3.64409E+06 + 3.44500E+02 3.53540E+06 + 3.44600E+02 3.50021E+06 + 3.44700E+02 3.53999E+06 + 3.44800E+02 3.65302E+06 + 3.44900E+02 3.83447E+06 + 3.45000E+02 4.07656E+06 + 3.45100E+02 4.36902E+06 + 3.45200E+02 4.69916E+06 + 3.45300E+02 5.05279E+06 + 3.45400E+02 5.41508E+06 + 3.45500E+02 5.77022E+06 + 3.45600E+02 6.10308E+06 + 3.45700E+02 6.39949E+06 + 3.45800E+02 6.64652E+06 + 3.45900E+02 6.83381E+06 + 3.46000E+02 6.95331E+06 + 3.46100E+02 6.99981E+06 + 3.46200E+02 6.97137E+06 + 3.46300E+02 6.86920E+06 + 3.46400E+02 6.69769E+06 + 3.46500E+02 6.46418E+06 + 3.46600E+02 6.17858E+06 + 3.46700E+02 5.85330E+06 + 3.46800E+02 5.50229E+06 + 3.46900E+02 5.14027E+06 + 3.47000E+02 4.78308E+06 + 3.47100E+02 4.44590E+06 + 3.47200E+02 4.14308E+06 + 3.47300E+02 3.88786E+06 + 3.47400E+02 3.69091E+06 + 3.47500E+02 3.56073E+06 + 3.47600E+02 3.50297E+06 + 3.47700E+02 3.52007E+06 + 3.47800E+02 3.61125E+06 + 3.47900E+02 3.77265E+06 + 3.48000E+02 3.99742E+06 + 3.48100E+02 4.27580E+06 + 3.48200E+02 4.59592E+06 + 3.48300E+02 4.94407E+06 + 3.48400E+02 5.30533E+06 + 3.48500E+02 5.66424E+06 + 3.48600E+02 6.00551E+06 + 3.48700E+02 6.31432E+06 + 3.48800E+02 6.57749E+06 + 3.48900E+02 6.78394E+06 + 3.49000E+02 6.92463E+06 + 3.49100E+02 6.99360E+06 + 3.49200E+02 6.98788E+06 + 3.49300E+02 6.90776E+06 + 3.49400E+02 6.75662E+06 + 3.49500E+02 6.54089E+06 + 3.49600E+02 6.26993E+06 + 3.49700E+02 5.95529E+06 + 3.49800E+02 5.61046E+06 + 3.49900E+02 5.25019E+06 + 3.50000E+02 4.88993E+06 + 3.50100E+02 4.54501E+06 + 3.50200E+02 4.23040E+06 + 3.50300E+02 3.95954E+06 + 3.50400E+02 3.74384E+06 + 3.50500E+02 3.59273E+06 + 3.50600E+02 3.51263E+06 + 3.50700E+02 3.50696E+06 + 3.50800E+02 3.57595E+06 + 3.50900E+02 3.71667E+06 + 3.51000E+02 3.92315E+06 + 3.51100E+02 4.18642E+06 + 3.51200E+02 4.49526E+06 + 3.51300E+02 4.83645E+06 + 3.51400E+02 5.19536E+06 + 3.51500E+02 5.55672E+06 + 3.51600E+02 5.90486E+06 + 3.51700E+02 6.22495E+06 + 3.51800E+02 6.50330E+06 + 3.51900E+02 6.72797E+06 + 3.52000E+02 6.88934E+06 + 3.52100E+02 6.98052E+06 + 3.52200E+02 6.99755E+06 + 3.52300E+02 6.93976E+06 + 3.52400E+02 6.80955E+06 + 3.52500E+02 6.61258E+06 + 3.52600E+02 6.35725E+06 + 3.52700E+02 6.05441E+06 + 3.52800E+02 5.71731E+06 + 3.52900E+02 5.36011E+06 + 3.53000E+02 4.99810E+06 + 3.53100E+02 4.64700E+06 + 3.53200E+02 4.32173E+06 + 3.53300E+02 4.03624E+06 + 3.53400E+02 3.80276E+06 + 3.53500E+02 3.63128E+06 + 3.53600E+02 3.52912E+06 + 3.53700E+02 3.50073E+06 + 3.53800E+02 3.54726E+06 + 3.53900E+02 3.66679E+06 + 3.54000E+02 3.85411E+06 + 3.54100E+02 4.10124E+06 + 3.54200E+02 4.39769E+06 + 3.54300E+02 4.73046E+06 + 3.54400E+02 5.08560E+06 + 3.54500E+02 5.44790E+06 + 3.54600E+02 5.80163E+06 + 3.54700E+02 6.13173E+06 + 3.54800E+02 6.42409E+06 + 3.54900E+02 6.66616E+06 + 3.55000E+02 6.84762E+06 + 3.55100E+02 6.96060E+06 + 3.55200E+02 7.00032E+06 + 3.55300E+02 6.96508E+06 + 3.55400E+02 6.85638E+06 + 3.55500E+02 6.67889E+06 + 3.55600E+02 6.44012E+06 + 3.55700E+02 6.15045E+06 + 3.55800E+02 5.82232E+06 + 3.55900E+02 5.46949E+06 + 3.56000E+02 5.10737E+06 + 3.56100E+02 4.75137E+06 + 3.56200E+02 4.41664E+06 + 3.56300E+02 4.11781E+06 + 3.56400E+02 3.86740E+06 + 3.56500E+02 3.67617E+06 + 3.56600E+02 3.55243E+06 + 3.56700E+02 3.50142E+06 + 3.56800E+02 3.52532E+06 + 3.56900E+02 3.62311E+06 + 3.57000E+02 3.79059E+06 + 3.57100E+02 4.02068E+06 + 3.57200E+02 4.30338E+06 + 3.57300E+02 4.62653E+06 + 3.57400E+02 4.97660E+06 + 3.57500E+02 5.33830E+06 + 3.57600E+02 5.69622E+06 + 3.57700E+02 6.03513E+06 + 3.57800E+02 6.34024E+06 + 3.57900E+02 6.59876E+06 + 3.58000E+02 6.79956E+06 + 3.58100E+02 6.93393E+06 + 3.58200E+02 6.99619E+06 + 3.58300E+02 6.98365E+06 + 3.58400E+02 6.89687E+06 + 3.58500E+02 6.73956E+06 + 3.58600E+02 6.51838E+06 + 3.58700E+02 6.24293E+06 + 3.58800E+02 5.92497E+06 + 3.58900E+02 5.57811E+06 + 3.59000E+02 5.21720E+06 + 3.59100E+02 4.85760E+06 + 3.59200E+02 4.51494E+06 + 3.59300E+02 4.20385E+06 + 3.59400E+02 3.93742E+06 + 3.59500E+02 3.72731E+06 + 3.59600E+02 3.58244E+06 + 3.59700E+02 3.50900E+06 + 3.59800E+02 3.51016E+06 + 3.59900E+02 3.58585E+06 + 3.60000E+02 3.73289E+06 + 3.60100E+02 3.94489E+06 + 3.60200E+02 4.21281E+06 + 3.60300E+02 4.52516E+06 + 3.60400E+02 4.86858E+06 + 3.60500E+02 5.22834E+06 + 3.60600E+02 5.58915E+06 + 3.60700E+02 5.93534E+06 + 3.60800E+02 6.25209E+06 + 3.60900E+02 6.52610E+06 + 3.61000E+02 6.74538E+06 + 3.61100E+02 6.90061E+06 + 3.61200E+02 6.98517E+06 + 3.61300E+02 6.99538E+06 + 3.61400E+02 6.93086E+06 + 3.61500E+02 6.79430E+06 + 3.61600E+02 6.59163E+06 + 3.61700E+02 6.33150E+06 + 3.61800E+02 6.02506E+06 + 3.61900E+02 5.68543E+06 + 3.62000E+02 5.32716E+06 + 3.62100E+02 4.96550E+06 + 3.62200E+02 4.61613E+06 + 3.62300E+02 4.29402E+06 + 3.62400E+02 4.01270E+06 + 3.62500E+02 3.78447E+06 + 3.62600E+02 3.61900E+06 + 3.62700E+02 3.52345E+06 + 3.62800E+02 3.50187E+06 + 3.62900E+02 3.55519E+06 + 3.63000E+02 3.68112E+06 + 3.63100E+02 3.87425E+06 + 3.63200E+02 4.12641E+06 + 3.63300E+02 4.42655E+06 + 3.63400E+02 4.76206E+06 + 3.63500E+02 5.11858E+06 + 3.63600E+02 5.48065E+06 + 3.63700E+02 5.83284E+06 + 3.63800E+02 6.16008E+06 + 3.63900E+02 6.44835E+06 + 3.64000E+02 6.68530E+06 + 3.64100E+02 6.86082E+06 + 3.64200E+02 6.96729E+06 + 3.64300E+02 7.00022E+06 + 3.64400E+02 6.95818E+06 + 3.64500E+02 6.84299E+06 + 3.64600E+02 6.65958E+06 + 3.64700E+02 6.41572E+06 + 3.64800E+02 6.12209E+06 + 3.64900E+02 5.79104E+06 + 3.65000E+02 5.43672E+06 + 3.65100E+02 5.07451E+06 + 3.65200E+02 4.71983E+06 + 3.65300E+02 4.38788E+06 + 3.65400E+02 4.09286E+06 + 3.65500E+02 3.84742E+06 + 3.65600E+02 3.66203E+06 + 3.65700E+02 3.54473E+06 + 3.65800E+02 3.50049E+06 + 3.65900E+02 3.53120E+06 + 3.66000E+02 3.63554E+06 + 3.66100E+02 3.80911E+06 + 3.66200E+02 4.04437E+06 + 3.66300E+02 4.33120E+06 + 3.66400E+02 4.65757E+06 + 3.66500E+02 5.00924E+06 + 3.66600E+02 5.37123E+06 + 3.66700E+02 5.72814E+06 + 3.66800E+02 6.06439E+06 + 3.66900E+02 6.36586E+06 + 3.67000E+02 6.61961E+06 + 3.67100E+02 6.81463E+06 + 3.67200E+02 6.94264E+06 + 3.67300E+02 6.99815E+06 + 3.67400E+02 6.97880E+06 + 3.67500E+02 6.88540E+06 + 3.67600E+02 6.72191E+06 + 3.67700E+02 6.49542E+06 + 3.67800E+02 6.21568E+06 + 3.67900E+02 5.89441E+06 + 3.68000E+02 5.54564E+06 + 3.68100E+02 5.18422E+06 + 3.68200E+02 4.82552E+06 + 3.68300E+02 4.48523E+06 + 3.68400E+02 4.17759E+06 + 3.68500E+02 3.91584E+06 + 3.68600E+02 3.71133E+06 + 3.68700E+02 3.57274E+06 + 3.68800E+02 3.50601E+06 + 3.68900E+02 3.51399E+06 + 3.69000E+02 3.59634E+06 + 3.69100E+02 3.74960E+06 + 3.69200E+02 3.96710E+06 + 3.69300E+02 4.23947E+06 + 3.69400E+02 4.55532E+06 + 3.69500E+02 4.90084E+06 + 3.69600E+02 5.26144E+06 + 3.69700E+02 5.62146E+06 + 3.69800E+02 5.96548E+06 + 3.69900E+02 6.27905E+06 + 3.70000E+02 6.54846E+06 + 3.70100E+02 6.76226E+06 + 3.70200E+02 6.91133E+06 + 3.70300E+02 6.98918E+06 + 3.70400E+02 6.99258E+06 + 3.70500E+02 6.92132E+06 + 3.70600E+02 6.77849E+06 + 3.70700E+02 6.57020E+06 + 3.70800E+02 6.30537E+06 + 3.70900E+02 5.99534E+06 + 3.71000E+02 5.65340E+06 + 3.71100E+02 5.29408E+06 + 3.71200E+02 4.93300E+06 + 3.71300E+02 4.58560E+06 + 3.71400E+02 4.26647E+06 + 3.71500E+02 3.98959E+06 + 3.71600E+02 3.76671E+06 + 3.71700E+02 3.60734E+06 + 3.71800E+02 3.51841E+06 + 3.71900E+02 3.50363E+06 + 3.72000E+02 3.56370E+06 + 3.72100E+02 3.69600E+06 + 3.72200E+02 3.89488E+06 + 3.72300E+02 4.15182E+06 + 3.72400E+02 4.45581E+06 + 3.72500E+02 4.79383E+06 + 3.72600E+02 5.15150E+06 + 3.72700E+02 5.51331E+06 + 3.72800E+02 5.86375E+06 + 3.72900E+02 6.18810E+06 + 3.73000E+02 6.47218E+06 + 3.73100E+02 6.70398E+06 + 3.73200E+02 6.87344E+06 + 3.73300E+02 6.97335E+06 + 3.73400E+02 6.99949E+06 + 3.73500E+02 6.95068E+06 + 3.73600E+02 6.82904E+06 + 3.73700E+02 6.63970E+06 + 3.73800E+02 6.39098E+06 + 3.73900E+02 6.09333E+06 + 3.74000E+02 5.75946E+06 + 3.74100E+02 5.40388E+06 + 3.74200E+02 5.04172E+06 + 3.74300E+02 4.68849E+06 + 3.74400E+02 4.35932E+06 + 3.74500E+02 4.06832E+06 + 3.74600E+02 3.82788E+06 + 3.74700E+02 3.64845E+06 + 3.74800E+02 3.53766E+06 + 3.74900E+02 3.50018E+06 + 3.75000E+02 3.53769E+06 + 3.75100E+02 3.64855E+06 + 3.75200E+02 3.82809E+06 + 3.75300E+02 4.06842E+06 + 3.75400E+02 4.35944E+06 + 3.75500E+02 4.68872E+06 + 3.75600E+02 5.04196E+06 + 3.75700E+02 5.40412E+06 + 3.75800E+02 5.75969E+06 + 3.75900E+02 6.09345E+06 + 3.76000E+02 6.39108E+06 + 3.76100E+02 6.63991E+06 + 3.76200E+02 6.82914E+06 + 3.76300E+02 6.95071E+06 + 3.76400E+02 6.99950E+06 + 3.76500E+02 6.97333E+06 + 3.76600E+02 6.87331E+06 + 3.76700E+02 6.70379E+06 + 3.76800E+02 6.47209E+06 + 3.76900E+02 6.18790E+06 + 3.77000E+02 5.86362E+06 + 3.77100E+02 5.51307E+06 + 3.77200E+02 5.15116E+06 + 3.77300E+02 4.79370E+06 + 3.77400E+02 4.45569E+06 + 3.77500E+02 4.15163E+06 + 3.77600E+02 3.89473E+06 + 3.77700E+02 3.69589E+06 + 3.77800E+02 3.56364E+06 + 3.77900E+02 3.50363E+06 + 3.78000E+02 3.51843E+06 + 3.78100E+02 3.60746E+06 + 3.78200E+02 3.76684E+06 + 3.78300E+02 3.98968E+06 + 3.78400E+02 4.26667E+06 + 3.78500E+02 4.58572E+06 + 3.78600E+02 4.93323E+06 + 3.78700E+02 5.29443E+06 + 3.78800E+02 5.65353E+06 + 3.78900E+02 5.99546E+06 + 3.79000E+02 6.30556E+06 + 3.79100E+02 6.57036E+06 + 3.79200E+02 6.77861E+06 + 3.79300E+02 6.92139E+06 + 3.79400E+02 6.99260E+06 + 3.79500E+02 6.98917E+06 + 3.79600E+02 6.91122E+06 + 3.79700E+02 6.76214E+06 + 3.79800E+02 6.54837E+06 + 3.79900E+02 6.27886E+06 + 3.80000E+02 5.96536E+06 + 3.80100E+02 5.62122E+06 + 3.80200E+02 5.26110E+06 + 3.80300E+02 4.90071E+06 + 3.80400E+02 4.55510E+06 + 3.80500E+02 4.23936E+06 + 3.80600E+02 3.96693E+06 + 3.80700E+02 3.74942E+06 + 3.80800E+02 3.59630E+06 + 3.80900E+02 3.51397E+06 + 3.81000E+02 3.50603E+06 + 3.81100E+02 3.57281E+06 + 3.81200E+02 3.71144E+06 + 3.81300E+02 3.91600E+06 + 3.81400E+02 4.17770E+06 + 3.81500E+02 4.48535E+06 + 3.81600E+02 4.82586E+06 + 3.81700E+02 5.18446E+06 + 3.81800E+02 5.54577E+06 + 3.81900E+02 5.89463E+06 + 3.82000E+02 6.21579E+06 + 3.82100E+02 6.49558E+06 + 3.82200E+02 6.72210E+06 + 3.82300E+02 6.88545E+06 + 3.82400E+02 6.97882E+06 + 3.82500E+02 6.99814E+06 + 3.82600E+02 6.94258E+06 + 3.82700E+02 6.81452E+06 + 3.82800E+02 6.61946E+06 + 3.82900E+02 6.36576E+06 + 3.83000E+02 6.06427E+06 + 3.83100E+02 5.72781E+06 + 3.83200E+02 5.37099E+06 + 3.83300E+02 5.00910E+06 + 3.83400E+02 4.65734E+06 + 3.83500E+02 4.33108E+06 + 3.83600E+02 4.04420E+06 + 3.83700E+02 3.80892E+06 + 3.83800E+02 3.63549E+06 + 3.83900E+02 3.53115E+06 + 3.84000E+02 3.50049E+06 + 3.84100E+02 3.54478E+06 + 3.84200E+02 3.66217E+06 + 3.84300E+02 3.84750E+06 + 3.84400E+02 4.09296E+06 + 3.84500E+02 4.38809E+06 + 3.84600E+02 4.72006E+06 + 3.84700E+02 5.07475E+06 + 3.84800E+02 5.43696E+06 + 3.84900E+02 5.79117E+06 + 3.85000E+02 6.12221E+06 + 3.85100E+02 6.41598E+06 + 3.85200E+02 6.65972E+06 + 3.85300E+02 6.84305E+06 + 3.85400E+02 6.95824E+06 + 3.85500E+02 7.00022E+06 + 3.85600E+02 6.96725E+06 + 3.85700E+02 6.86068E+06 + 3.85800E+02 6.68522E+06 + 3.85900E+02 6.44825E+06 + 3.86000E+02 6.15987E+06 + 3.86100E+02 5.83261E+06 + 3.86200E+02 5.48041E+06 + 3.86300E+02 5.11834E+06 + 3.86400E+02 4.76193E+06 + 3.86500E+02 4.42644E+06 + 3.86600E+02 4.12615E+06 + 3.86700E+02 3.87411E+06 + 3.86800E+02 3.68106E+06 + 3.86900E+02 3.55513E+06 + 3.87000E+02 3.50187E+06 + 3.87100E+02 3.52349E+06 + 3.87200E+02 3.61912E+06 + 3.87300E+02 3.78455E+06 + 3.87400E+02 4.01279E+06 + 3.87500E+02 4.29414E+06 + 3.87600E+02 4.61636E+06 + 3.87700E+02 4.96584E+06 + 3.87800E+02 5.32730E+06 + 3.87900E+02 5.68556E+06 + 3.88000E+02 6.02528E+06 + 3.88100E+02 6.33169E+06 + 3.88200E+02 6.59178E+06 + 3.88300E+02 6.79441E+06 + 3.88400E+02 6.93089E+06 + 3.88500E+02 6.99539E+06 + 3.88600E+02 6.98512E+06 + 3.88700E+02 6.90053E+06 + 3.88800E+02 6.74531E+06 + 3.88900E+02 6.52594E+06 + 3.89000E+02 6.25198E+06 + 3.89100E+02 5.93512E+06 + 3.89200E+02 5.58881E+06 + 3.89300E+02 5.22821E+06 + 3.89400E+02 4.86845E+06 + 3.89500E+02 4.52494E+06 + 3.89600E+02 4.21261E+06 + 3.89700E+02 3.94473E+06 + 3.89800E+02 3.73277E+06 + 3.89900E+02 3.58581E+06 + 3.90000E+02 3.51015E+06 + 3.90100E+02 3.50903E+06 + 3.90200E+02 3.58251E+06 + 3.90300E+02 3.72738E+06 + 3.90400E+02 3.93758E+06 + 3.90500E+02 4.20396E+06 + 3.90600E+02 4.51516E+06 + 3.90700E+02 4.85794E+06 + 3.90800E+02 5.21733E+06 + 3.90900E+02 5.57824E+06 + 3.91000E+02 5.92519E+06 + 3.91100E+02 6.24313E+06 + 3.91200E+02 6.51862E+06 + 3.91300E+02 6.73963E+06 + 3.91400E+02 6.89692E+06 + 3.91500E+02 6.98369E+06 + 3.91600E+02 6.99617E+06 + 3.91700E+02 6.93387E+06 + 3.91800E+02 6.79945E+06 + 3.91900E+02 6.59867E+06 + 3.92000E+02 6.34014E+06 + 3.92100E+02 6.03482E+06 + 3.92200E+02 5.69598E+06 + 3.92300E+02 5.33816E+06 + 3.92400E+02 4.97637E+06 + 3.92500E+02 4.62641E+06 + 3.92600E+02 4.30317E+06 + 3.92700E+02 4.02043E+06 + 3.92800E+02 3.79052E+06 + 3.92900E+02 3.62306E+06 + 3.93000E+02 3.52528E+06 + 3.93100E+02 3.50143E+06 + 3.93200E+02 3.55249E+06 + 3.93300E+02 3.67627E+06 + 3.93400E+02 3.86748E+06 + 3.93500E+02 4.11791E+06 + 3.93600E+02 4.41695E+06 + 3.93700E+02 4.75160E+06 + 3.93800E+02 5.10750E+06 + 3.93900E+02 5.46973E+06 + 3.94000E+02 5.82245E+06 + 3.94100E+02 6.15066E+06 + 3.94200E+02 6.44038E+06 + 3.94300E+02 6.67897E+06 + 3.94400E+02 6.85644E+06 + 3.94500E+02 6.96513E+06 + 3.94600E+02 7.00032E+06 + 3.94700E+02 6.96053E+06 + 3.94800E+02 6.84752E+06 + 3.94900E+02 6.66608E+06 + 3.95000E+02 6.42391E+06 + 3.95100E+02 6.13153E+06 + 3.95200E+02 5.80140E+06 + 3.95300E+02 5.44766E+06 + 3.95400E+02 5.08547E+06 + 3.95500E+02 4.73034E+06 + 3.95600E+02 4.39738E+06 + 3.95700E+02 4.10106E+06 + 3.95800E+02 3.85403E+06 + 3.95900E+02 3.66668E+06 + 3.96000E+02 3.54723E+06 + 3.96100E+02 3.50073E+06 + 3.96200E+02 3.52919E+06 + 3.96300E+02 3.63133E+06 + 3.96400E+02 3.80283E+06 + 3.96500E+02 4.03642E+06 + 3.96600E+02 4.32194E+06 + 3.96700E+02 4.64722E+06 + 3.96800E+02 4.99834E+06 + 3.96900E+02 5.36024E+06 + 3.97000E+02 5.71744E+06 + 3.97100E+02 6.05472E+06 + 3.97200E+02 6.35744E+06 + 3.97300E+02 6.61266E+06 + 3.97400E+02 6.80966E+06 + 3.97500E+02 6.93980E+06 + 3.97600E+02 6.99756E+06 + 3.97700E+02 6.98047E+06 + 3.97800E+02 6.88929E+06 + 3.97900E+02 6.72790E+06 + 3.98000E+02 6.50313E+06 + 3.98100E+02 6.22475E+06 + 3.98200E+02 5.90454E+06 + 3.98300E+02 5.55649E+06 + 3.98400E+02 5.19522E+06 + 3.98500E+02 4.83621E+06 + 3.98600E+02 4.49505E+06 + 3.98700E+02 4.18623E+06 + 3.98800E+02 3.92299E+06 + 3.98900E+02 3.71660E+06 + 3.99000E+02 3.57591E+06 + 3.99100E+02 3.50693E+06 + 3.99200E+02 3.51265E+06 + 3.99300E+02 3.59277E+06 + 3.99400E+02 3.74396E+06 + 3.99500E+02 3.95963E+06 + 3.99600E+02 4.23059E+06 + 3.99700E+02 4.54532E+06 + 3.99800E+02 4.89006E+06 + 3.99900E+02 5.25032E+06 + 4.00000E+02 5.61069E+06 + 4.00100E+02 5.95551E+06 + 4.00200E+02 6.27012E+06 + 4.00300E+02 6.54105E+06 + 4.00400E+02 6.75669E+06 + 4.00500E+02 6.90780E+06 + 4.00600E+02 6.98792E+06 + 4.00700E+02 6.99358E+06 + 4.00800E+02 6.92459E+06 + 4.00900E+02 6.78383E+06 + 4.01000E+02 6.57740E+06 + 4.01100E+02 6.31413E+06 + 4.01200E+02 6.00519E+06 + 4.01300E+02 5.66411E+06 + 4.01400E+02 5.30520E+06 + 4.01500E+02 4.94383E+06 + 4.01600E+02 4.59570E+06 + 4.01700E+02 4.27551E+06 + 4.01800E+02 3.99725E+06 + 4.01900E+02 3.77258E+06 + 4.02000E+02 3.61116E+06 + 4.02100E+02 3.52002E+06 + 4.02200E+02 3.50298E+06 + 4.02300E+02 3.56079E+06 + 4.02400E+02 3.69097E+06 + 4.02500E+02 3.88794E+06 + 4.02600E+02 4.14335E+06 + 4.02700E+02 4.44611E+06 + 4.02800E+02 4.78321E+06 + 4.02900E+02 5.14051E+06 + 4.03000E+02 5.50242E+06 + 4.03100E+02 5.85352E+06 + 4.03200E+02 6.17888E+06 + 4.03300E+02 6.46428E+06 + 4.03400E+02 6.69777E+06 + 4.03500E+02 6.86929E+06 + 4.03600E+02 6.97141E+06 + 4.03700E+02 6.99980E+06 + 4.03800E+02 6.95325E+06 + 4.03900E+02 6.83376E+06 + 4.04000E+02 6.64643E+06 + 4.04100E+02 6.39923E+06 + 4.04200E+02 6.10287E+06 + 4.04300E+02 5.77009E+06 + 4.04400E+02 5.41485E+06 + 4.04500E+02 5.05265E+06 + 4.04600E+02 4.69893E+06 + 4.04700E+02 4.36872E+06 + 4.04800E+02 4.07646E+06 + 4.04900E+02 3.83439E+06 + 4.05000E+02 3.65292E+06 + 4.05100E+02 3.53994E+06 + 4.05200E+02 3.50021E+06 + 4.05300E+02 3.53545E+06 + 4.05400E+02 3.64415E+06 + 4.05500E+02 3.82170E+06 + 4.05600E+02 4.06040E+06 + 4.05700E+02 4.35007E+06 + 4.05800E+02 4.67830E+06 + 4.05900E+02 5.03103E+06 + 4.06000E+02 5.39315E+06 + 4.06100E+02 5.74925E+06 + 4.06200E+02 6.08387E+06 + 4.06300E+02 6.38271E+06 + 4.06400E+02 6.63319E+06 + 4.06500E+02 6.82436E+06 + 4.06600E+02 6.94810E+06 + 4.06700E+02 6.99912E+06 + 4.06800E+02 6.97522E+06 + 4.06900E+02 6.87744E+06 + 4.07000E+02 6.70990E+06 + 4.07100E+02 6.47987E+06 + 4.07200E+02 6.19718E+06 + 4.07300E+02 5.87392E+06 + 4.07400E+02 5.52395E+06 + 4.07500E+02 5.16226E+06 + 4.07600E+02 4.80423E+06 + 4.07700E+02 4.46542E+06 + 4.07800E+02 4.16031E+06 + 4.07900E+02 3.90172E+06 + 4.08000E+02 3.70098E+06 + 4.08100E+02 3.56661E+06 + 4.08200E+02 3.50434E+06 + 4.08300E+02 3.51688E+06 + 4.08400E+02 3.60366E+06 + 4.08500E+02 3.76102E+06 + 4.08600E+02 3.98214E+06 + 4.08700E+02 4.25758E+06 + 4.08800E+02 4.57555E+06 + 4.08900E+02 4.92241E+06 + 4.09000E+02 5.28332E+06 + 4.09100E+02 5.64291E+06 + 4.09200E+02 5.98558E+06 + 4.09300E+02 6.29675E+06 + 4.09400E+02 6.56310E+06 + 4.09500E+02 6.77321E+06 + 4.09600E+02 6.91812E+06 + 4.09700E+02 6.99154E+06 + 4.09800E+02 6.99038E+06 + 4.09900E+02 6.91466E+06 + 4.10000E+02 6.76766E+06 + 4.10100E+02 6.55566E+06 + 4.10200E+02 6.28766E+06 + 4.10300E+02 5.97539E+06 + 4.10400E+02 5.63198E+06 + 4.10500E+02 5.27210E+06 + 4.10600E+02 4.91140E+06 + 4.10700E+02 4.56522E+06 + 4.10800E+02 4.24837E+06 + 4.10900E+02 3.97444E+06 + 4.11000E+02 3.75517E+06 + 4.11100E+02 3.59989E+06 + 4.11200E+02 3.51537E+06 + 4.11300E+02 3.50515E+06 + 4.11400E+02 3.56970E+06 + 4.11500E+02 3.70623E+06 + 4.11600E+02 3.90890E+06 + 4.11700E+02 4.16910E+06 + 4.11800E+02 4.47546E+06 + 4.11900E+02 4.81508E+06 + 4.12000E+02 5.17346E+06 + 4.12100E+02 5.53502E+06 + 4.12200E+02 5.88438E+06 + 4.12300E+02 6.20659E+06 + 4.12400E+02 6.48782E+06 + 4.12500E+02 6.71605E+06 + 4.12600E+02 6.88153E+06 + 4.12700E+02 6.97708E+06 + 4.12800E+02 6.99866E+06 + 4.12900E+02 6.94535E+06 + 4.13000E+02 6.81943E+06 + 4.13100E+02 6.62623E+06 + 4.13200E+02 6.37414E+06 + 4.13300E+02 6.07400E+06 + 4.13400E+02 5.73839E+06 + 4.13500E+02 5.38197E+06 + 4.13600E+02 5.01991E+06 + 4.13700E+02 4.66761E+06 + 4.13800E+02 4.34047E+06 + 4.13900E+02 4.05220E+06 + 4.14000E+02 3.81519E+06 + 4.14100E+02 3.63972E+06 + 4.14200E+02 3.53325E+06 + 4.14300E+02 3.50032E+06 + 4.14400E+02 3.54235E+06 + 4.14500E+02 3.65753E+06 + 4.14600E+02 3.84101E+06 + 4.14700E+02 4.08480E+06 + 4.14800E+02 4.37843E+06 + 4.14900E+02 4.70958E+06 + 4.15000E+02 5.06380E+06 + 4.15100E+02 5.42600E+06 + 4.15200E+02 5.78078E+06 + 4.15300E+02 6.11264E+06 + 4.15400E+02 6.40766E+06 + 4.15500E+02 6.65317E+06 + 4.15600E+02 6.83850E+06 + 4.15700E+02 6.95580E+06 + 4.15800E+02 7.00005E+06 + 4.15900E+02 6.96934E+06 + 4.16000E+02 6.86500E+06 + 4.16100E+02 6.69143E+06 + 4.16200E+02 6.45618E+06 + 4.16300E+02 6.16935E+06 + 4.16400E+02 5.84298E+06 + 4.16500E+02 5.49132E+06 + 4.16600E+02 5.12922E+06 + 4.16700E+02 4.77241E+06 + 4.16800E+02 4.43617E+06 + 4.16900E+02 4.13461E+06 + 4.17000E+02 3.88094E+06 + 4.17100E+02 3.68592E+06 + 4.17200E+02 3.55788E+06 + 4.17300E+02 3.50238E+06 + 4.17400E+02 3.52174E+06 + 4.17500E+02 3.61516E+06 + 4.17600E+02 3.77862E+06 + 4.17700E+02 4.00511E+06 + 4.17800E+02 4.28493E+06 + 4.17900E+02 4.60611E+06 + 4.18000E+02 4.95487E+06 + 4.18100E+02 5.31640E+06 + 4.18200E+02 5.67499E+06 + 4.18300E+02 6.01529E+06 + 4.18400E+02 6.32301E+06 + 4.18500E+02 6.58468E+06 + 4.18600E+02 6.78920E+06 + 4.18700E+02 6.92782E+06 + 4.18800E+02 6.99453E+06 + 4.18900E+02 6.98655E+06 + 4.19000E+02 6.90417E+06 + 4.19100E+02 6.75095E+06 + 4.19200E+02 6.53345E+06 + 4.19300E+02 6.26099E+06 + 4.19400E+02 5.94524E+06 + 4.19500E+02 5.59971E+06 + 4.19600E+02 5.23911E+06 + 4.19700E+02 4.87910E+06 + 4.19800E+02 4.53508E+06 + 4.19900E+02 4.22150E+06 + 4.20000E+02 3.95209E+06 + 4.20100E+02 3.73823E+06 + 4.20200E+02 3.58921E+06 + 4.20300E+02 3.51135E+06 + 4.20400E+02 3.50796E+06 + 4.20500E+02 3.57921E+06 + 4.20600E+02 3.72204E+06 + 4.20700E+02 3.93040E+06 + 4.20800E+02 4.19515E+06 + 4.20900E+02 4.50518E+06 + 4.21000E+02 4.84722E+06 + 4.21100E+02 5.20643E+06 + 4.21200E+02 5.56752E+06 + 4.21300E+02 5.91502E+06 + 4.21400E+02 6.23405E+06 + 4.21500E+02 6.51093E+06 + 4.21600E+02 6.73387E+06 + 4.21700E+02 6.89319E+06 + 4.21800E+02 6.98212E+06 + 4.21900E+02 6.99690E+06 + 4.22000E+02 6.93684E+06 + 4.22100E+02 6.80454E+06 + 4.22200E+02 6.60560E+06 + 4.22300E+02 6.34873E+06 + 4.22400E+02 6.04474E+06 + 4.22500E+02 5.70662E+06 + 4.22600E+02 5.34905E+06 + 4.22700E+02 4.98725E+06 + 4.22800E+02 4.63671E+06 + 4.22900E+02 4.31245E+06 + 4.23000E+02 4.02837E+06 + 4.23100E+02 3.79656E+06 + 4.23200E+02 3.62710E+06 + 4.23300E+02 3.52719E+06 + 4.23400E+02 3.50105E+06 + 4.23500E+02 3.54985E+06 + 4.23600E+02 3.67154E+06 + 4.23700E+02 3.86082E+06 + 4.23800E+02 4.10954E+06 + 4.23900E+02 4.40728E+06 + 4.24000E+02 4.74105E+06 + 4.24100E+02 5.09664E+06 + 4.24200E+02 5.45890E+06 + 4.24300E+02 5.81203E+06 + 4.24400E+02 6.14120E+06 + 4.24500E+02 6.43228E+06 + 4.24600E+02 6.67264E+06 + 4.24700E+02 6.85207E+06 + 4.24800E+02 6.96290E+06 + 4.24900E+02 7.00036E+06 + 4.25000E+02 6.96285E+06 + 4.25100E+02 6.85195E+06 + 4.25200E+02 6.67246E+06 + 4.25300E+02 6.43213E+06 + 4.25400E+02 6.14102E+06 + 4.25500E+02 5.81184E+06 + 4.25600E+02 5.45860E+06 + 4.25700E+02 5.09633E+06 + 4.25800E+02 4.74086E+06 + 4.25900E+02 4.40711E+06 + 4.26000E+02 4.10939E+06 + 4.26100E+02 3.86063E+06 + 4.26200E+02 3.67140E+06 + 4.26300E+02 3.54980E+06 + 4.26400E+02 3.50104E+06 + 4.26500E+02 3.52720E+06 + 4.26600E+02 3.62722E+06 + 4.26700E+02 3.79673E+06 + 4.26800E+02 4.02843E+06 + 4.26900E+02 4.31262E+06 + 4.27000E+02 4.63690E+06 + 4.27100E+02 4.98755E+06 + 4.27200E+02 5.34936E+06 + 4.27300E+02 5.70682E+06 + 4.27400E+02 6.04492E+06 + 4.27500E+02 6.34889E+06 + 4.27600E+02 6.60579E+06 + 4.27700E+02 6.80468E+06 + 4.27800E+02 6.93689E+06 + 4.27900E+02 6.99691E+06 + 4.28000E+02 6.98209E+06 + 4.28100E+02 6.89308E+06 + 4.28200E+02 6.73371E+06 + 4.28300E+02 6.51079E+06 + 4.28400E+02 6.23388E+06 + 4.28500E+02 5.91483E+06 + 4.28600E+02 5.56722E+06 + 4.28700E+02 5.20612E+06 + 4.28800E+02 4.84702E+06 + 4.28900E+02 4.50500E+06 + 4.29000E+02 4.19499E+06 + 4.29100E+02 3.93019E+06 + 4.29200E+02 3.72189E+06 + 4.29300E+02 3.57915E+06 + 4.29400E+02 3.50794E+06 + 4.29500E+02 3.51138E+06 + 4.29600E+02 3.58931E+06 + 4.29700E+02 3.73838E+06 + 4.29800E+02 3.95222E+06 + 4.29900E+02 4.22166E+06 + 4.30000E+02 4.53516E+06 + 4.30100E+02 4.87940E+06 + 4.30200E+02 5.23942E+06 + 4.30300E+02 5.59980E+06 + 4.30400E+02 5.94542E+06 + 4.30500E+02 6.26116E+06 + 4.30600E+02 6.53359E+06 + 4.30700E+02 6.75111E+06 + 4.30800E+02 6.90423E+06 + 4.30900E+02 6.98658E+06 + 4.31000E+02 6.99451E+06 + 4.31100E+02 6.92773E+06 + 4.31200E+02 6.78905E+06 + 4.31300E+02 6.58455E+06 + 4.31400E+02 6.32285E+06 + 4.31500E+02 6.01511E+06 + 4.31600E+02 5.67469E+06 + 4.31700E+02 5.31609E+06 + 4.31800E+02 4.95468E+06 + 4.31900E+02 4.60592E+06 + 4.32000E+02 4.28476E+06 + 4.32100E+02 4.00489E+06 + 4.32200E+02 3.77845E+06 + 4.32300E+02 3.61509E+06 + 4.32400E+02 3.52170E+06 + 4.32500E+02 3.50240E+06 + 4.32600E+02 3.55796E+06 + 4.32700E+02 3.68605E+06 + 4.32800E+02 3.88106E+06 + 4.32900E+02 4.13476E+06 + 4.33000E+02 4.43635E+06 + 4.33100E+02 4.77271E+06 + 4.33200E+02 5.12953E+06 + 4.33300E+02 5.49152E+06 + 4.33400E+02 5.84317E+06 + 4.33500E+02 6.16943E+06 + 4.33600E+02 6.45640E+06 + 4.33700E+02 6.69161E+06 + 4.33800E+02 6.86504E+06 + 4.33900E+02 6.96938E+06 + 4.34000E+02 7.00004E+06 + 4.34100E+02 6.95576E+06 + 4.34200E+02 6.83837E+06 + 4.34300E+02 6.65305E+06 + 4.34400E+02 6.40751E+06 + 4.34500E+02 6.11247E+06 + 4.34600E+02 5.78049E+06 + 4.34700E+02 5.42570E+06 + 4.34800E+02 5.06360E+06 + 4.34900E+02 4.70939E+06 + 4.35000E+02 4.37825E+06 + 4.35100E+02 4.08457E+06 + 4.35200E+02 3.84083E+06 + 4.35300E+02 3.65745E+06 + 4.35400E+02 3.54230E+06 + 4.35500E+02 3.50032E+06 + 4.35600E+02 3.53331E+06 + 4.35700E+02 3.63985E+06 + 4.35800E+02 3.81530E+06 + 4.35900E+02 4.05235E+06 + 4.36000E+02 4.34064E+06 + 4.36100E+02 4.66790E+06 + 4.36200E+02 5.02022E+06 + 4.36300E+02 5.38217E+06 + 4.36400E+02 5.73859E+06 + 4.36500E+02 6.07418E+06 + 4.36600E+02 6.37437E+06 + 4.36700E+02 6.62642E+06 + 4.36800E+02 6.81952E+06 + 4.36900E+02 6.94540E+06 + 4.37000E+02 6.99867E+06 + 4.37100E+02 6.97703E+06 + 4.37200E+02 6.88142E+06 + 4.37300E+02 6.71600E+06 + 4.37400E+02 6.48768E+06 + 4.37500E+02 6.20642E+06 + 4.37600E+02 5.88420E+06 + 4.37700E+02 5.53472E+06 + 4.37800E+02 5.17326E+06 + 4.37900E+02 4.81499E+06 + 4.38000E+02 4.47528E+06 + 4.38100E+02 4.16886E+06 + 4.38200E+02 3.90870E+06 + 4.38300E+02 3.70614E+06 + 4.38400E+02 3.56965E+06 + 4.38500E+02 3.50514E+06 + 4.38600E+02 3.51541E+06 + 4.38700E+02 3.60000E+06 + 4.38800E+02 3.75527E+06 + 4.38900E+02 3.97458E+06 + 4.39000E+02 4.24854E+06 + 4.39100E+02 4.56550E+06 + 4.39200E+02 4.91170E+06 + 4.39300E+02 5.27231E+06 + 4.39400E+02 5.63217E+06 + 4.39500E+02 5.97557E+06 + 4.39600E+02 6.28791E+06 + 4.39700E+02 6.55586E+06 + 4.39800E+02 6.76776E+06 + 4.39900E+02 6.91472E+06 + 4.40000E+02 6.99040E+06 + 4.40100E+02 6.99151E+06 + 4.40200E+02 6.91803E+06 + 4.40300E+02 6.77311E+06 + 4.40400E+02 6.56297E+06 + 4.40500E+02 6.29659E+06 + 4.40600E+02 5.98530E+06 + 4.40700E+02 5.64261E+06 + 4.40800E+02 5.28322E+06 + 4.40900E+02 4.92221E+06 + 4.41000E+02 4.57536E+06 + 4.41100E+02 4.25742E+06 + 4.41200E+02 3.98193E+06 + 4.41300E+02 3.76092E+06 + 4.41400E+02 3.60363E+06 + 4.41500E+02 3.51685E+06 + 4.41600E+02 3.50437E+06 + 4.41700E+02 3.56669E+06 + 4.41800E+02 3.70108E+06 + 4.41900E+02 3.90185E+06 + 4.42000E+02 4.16047E+06 + 4.42100E+02 4.46570E+06 + 4.42200E+02 4.80453E+06 + 4.42300E+02 5.16246E+06 + 4.42400E+02 5.52415E+06 + 4.42500E+02 5.87411E+06 + 4.42600E+02 6.19743E+06 + 4.42700E+02 6.48009E+06 + 4.42800E+02 6.71001E+06 + 4.42900E+02 6.87751E+06 + 4.43000E+02 6.97526E+06 + 4.43100E+02 6.99911E+06 + 4.43200E+02 6.94803E+06 + 4.43300E+02 6.82427E+06 + 4.43400E+02 6.63307E+06 + 4.43500E+02 6.38255E+06 + 4.43600E+02 6.08360E+06 + 4.43700E+02 5.74896E+06 + 4.43800E+02 5.39295E+06 + 4.43900E+02 5.03083E+06 + 4.44000E+02 4.67811E+06 + 4.44100E+02 4.34981E+06 + 4.44200E+02 4.06017E+06 + 4.44300E+02 3.82158E+06 + 4.44400E+02 3.64407E+06 + 4.44500E+02 3.53541E+06 + 4.44600E+02 3.50021E+06 + 4.44700E+02 3.54000E+06 + 4.44800E+02 3.65300E+06 + 4.44900E+02 3.83445E+06 + 4.45000E+02 4.07661E+06 + 4.45100E+02 4.36899E+06 + 4.45200E+02 4.69922E+06 + 4.45300E+02 5.05285E+06 + 4.45400E+02 5.41505E+06 + 4.45500E+02 5.77028E+06 + 4.45600E+02 6.10314E+06 + 4.45700E+02 6.39946E+06 + 4.45800E+02 6.64656E+06 + 4.45900E+02 6.83384E+06 + 4.46000E+02 6.95330E+06 + 4.46100E+02 6.99981E+06 + 4.46200E+02 6.97135E+06 + 4.46300E+02 6.86922E+06 + 4.46400E+02 6.69765E+06 + 4.46500E+02 6.46413E+06 + 4.46600E+02 6.17862E+06 + 4.46700E+02 5.85323E+06 + 4.46800E+02 5.50222E+06 + 4.46900E+02 5.14031E+06 + 4.47000E+02 4.78301E+06 + 4.47100E+02 4.44584E+06 + 4.47200E+02 4.14311E+06 + 4.47300E+02 3.88782E+06 + 4.47400E+02 3.69088E+06 + 4.47500E+02 3.56074E+06 + 4.47600E+02 3.50297E+06 + 4.47700E+02 3.52006E+06 + 4.47800E+02 3.61123E+06 + 4.47900E+02 3.77269E+06 + 4.48000E+02 3.99739E+06 + 4.48100E+02 4.27577E+06 + 4.48200E+02 4.59598E+06 + 4.48300E+02 4.94403E+06 + 4.48400E+02 5.30529E+06 + 4.48500E+02 5.66430E+06 + 4.48600E+02 6.00547E+06 + 4.48700E+02 6.31437E+06 + 4.48800E+02 6.57753E+06 + 4.48900E+02 6.78392E+06 + 4.49000E+02 6.92465E+06 + 4.49100E+02 6.99360E+06 + 4.49200E+02 6.98788E+06 + 4.49300E+02 6.90773E+06 + 4.49400E+02 6.75658E+06 + 4.49500E+02 6.54092E+06 + 4.49600E+02 6.26987E+06 + 4.49700E+02 5.95523E+06 + 4.49800E+02 5.61049E+06 + 4.49900E+02 5.25012E+06 + 4.50000E+02 4.88986E+06 + 4.50100E+02 4.54504E+06 + 4.50200E+02 4.23034E+06 + 4.50300E+02 3.95950E+06 + 4.50400E+02 3.74386E+06 + 4.50500E+02 3.59271E+06 + 4.50600E+02 3.51262E+06 + 4.50700E+02 3.50696E+06 + 4.50800E+02 3.57597E+06 + 4.50900E+02 3.71670E+06 + 4.51000E+02 3.92312E+06 + 4.51100E+02 4.18648E+06 + 4.51200E+02 4.49533E+06 + 4.51300E+02 4.83641E+06 + 4.51400E+02 5.19543E+06 + 4.51500E+02 5.55669E+06 + 4.51600E+02 5.90482E+06 + 4.51700E+02 6.22501E+06 + 4.51800E+02 6.50327E+06 + 4.51900E+02 6.72795E+06 + 4.52000E+02 6.88936E+06 + 4.52100E+02 6.98052E+06 + 4.52200E+02 6.99755E+06 + 4.52300E+02 6.93975E+06 + 4.52400E+02 6.80957E+06 + 4.52500E+02 6.61254E+06 + 4.52600E+02 6.35720E+06 + 4.52700E+02 6.05444E+06 + 4.52800E+02 5.71724E+06 + 4.52900E+02 5.36004E+06 + 4.53000E+02 4.99814E+06 + 4.53100E+02 4.64693E+06 + 4.53200E+02 4.32168E+06 + 4.53300E+02 4.03627E+06 + 4.53400E+02 3.80272E+06 + 4.53500E+02 3.63125E+06 + 4.53600E+02 3.52913E+06 + 4.53700E+02 3.50074E+06 + 4.53800E+02 3.54728E+06 + 4.53900E+02 3.66677E+06 + 4.54000E+02 3.85415E+06 + 4.54100E+02 4.10129E+06 + 4.54200E+02 4.39765E+06 + 4.54300E+02 4.73053E+06 + 4.54400E+02 5.08567E+06 + 4.54500E+02 5.44786E+06 + 4.54600E+02 5.80169E+06 + 4.54700E+02 6.13179E+06 + 4.54800E+02 6.42406E+06 + 4.54900E+02 6.66620E+06 + 4.55000E+02 6.84761E+06 + 4.55100E+02 6.96060E+06 + 4.55200E+02 7.00032E+06 + 4.55300E+02 6.96509E+06 + 4.55400E+02 6.85640E+06 + 4.55500E+02 6.67885E+06 + 4.55600E+02 6.44015E+06 + 4.55700E+02 6.15048E+06 + 4.55800E+02 5.82226E+06 + 4.55900E+02 5.46953E+06 + 4.56000E+02 5.10730E+06 + 4.56100E+02 4.75130E+06 + 4.56200E+02 4.41668E+06 + 4.56300E+02 4.11776E+06 + 4.56400E+02 3.86735E+06 + 4.56500E+02 3.67618E+06 + 4.56600E+02 3.55241E+06 + 4.56700E+02 3.50142E+06 + 4.56800E+02 3.52531E+06 + 4.56900E+02 3.62313E+06 + 4.57000E+02 3.79063E+06 + 4.57100E+02 4.02065E+06 + 4.57200E+02 4.30343E+06 + 4.57300E+02 4.62660E+06 + 4.57400E+02 4.97656E+06 + 4.57500E+02 5.33836E+06 + 4.57600E+02 5.69628E+06 + 4.57700E+02 6.03510E+06 + 4.57800E+02 6.34029E+06 + 4.57900E+02 6.59880E+06 + 4.58000E+02 6.79954E+06 + 4.58100E+02 6.93395E+06 + 4.58200E+02 6.99619E+06 + 4.58300E+02 6.98366E+06 + 4.58400E+02 6.89685E+06 + 4.58500E+02 6.73952E+06 + 4.58600E+02 6.51840E+06 + 4.58700E+02 6.24288E+06 + 4.58800E+02 5.92501E+06 + 4.58900E+02 5.57815E+06 + 4.59000E+02 5.21713E+06 + 4.59100E+02 4.85764E+06 + 4.59200E+02 4.51497E+06 + 4.59300E+02 4.20380E+06 + 4.59400E+02 3.93745E+06 + 4.59500E+02 3.72733E+06 + 4.59600E+02 3.58242E+06 + 4.59700E+02 3.50900E+06 + 4.59800E+02 3.51017E+06 + 4.59900E+02 3.58587E+06 + 4.60000E+02 3.73287E+06 + 4.60100E+02 3.94493E+06 + 4.60200E+02 4.21286E+06 + 4.60300E+02 4.52513E+06 + 4.60400E+02 4.86864E+06 + 4.60500E+02 5.22841E+06 + 4.60600E+02 5.58911E+06 + 4.60700E+02 5.93540E+06 + 4.60800E+02 6.25215E+06 + 4.60900E+02 6.52608E+06 + 4.61000E+02 6.74542E+06 + 4.61100E+02 6.90064E+06 + 4.61200E+02 6.98516E+06 + 4.61300E+02 6.99538E+06 + 4.61400E+02 6.93084E+06 + 4.61500E+02 6.79431E+06 + 4.61600E+02 6.59158E+06 + 4.61700E+02 6.33145E+06 + 4.61800E+02 6.02510E+06 + 4.61900E+02 5.68537E+06 + 4.62000E+02 5.32710E+06 + 4.62100E+02 4.96553E+06 + 4.62200E+02 4.61607E+06 + 4.62300E+02 4.29397E+06 + 4.62400E+02 4.01273E+06 + 4.62500E+02 3.78444E+06 + 4.62600E+02 3.61901E+06 + 4.62700E+02 3.52346E+06 + 4.62800E+02 3.50188E+06 + 4.62900E+02 3.55518E+06 + 4.63000E+02 3.68110E+06 + 4.63100E+02 3.87430E+06 + 4.63200E+02 4.12638E+06 + 4.63300E+02 4.42652E+06 + 4.63400E+02 4.76212E+06 + 4.63500E+02 5.11854E+06 + 4.63600E+02 5.48071E+06 + 4.63700E+02 5.83290E+06 + 4.63800E+02 6.16005E+06 + 4.63900E+02 6.44840E+06 + 4.64000E+02 6.68534E+06 + 4.64100E+02 6.86080E+06 + 4.64200E+02 6.96730E+06 + 4.64300E+02 7.00022E+06 + 4.64400E+02 6.95819E+06 + 4.64500E+02 6.84296E+06 + 4.64600E+02 6.65954E+06 + 4.64700E+02 6.41575E+06 + 4.64800E+02 6.12203E+06 + 4.64900E+02 5.79097E+06 + 4.65000E+02 5.43676E+06 + 4.65100E+02 5.07444E+06 + 4.65200E+02 4.71977E+06 + 4.65300E+02 4.38791E+06 + 4.65400E+02 4.09281E+06 + 4.65500E+02 3.84738E+06 + 4.65600E+02 3.66204E+06 + 4.65700E+02 3.54471E+06 + 4.65800E+02 3.50049E+06 + 4.65900E+02 3.53119E+06 + 4.66000E+02 3.63557E+06 + 4.66100E+02 3.80909E+06 + 4.66200E+02 4.04435E+06 + 4.66300E+02 4.33126E+06 + 4.66400E+02 4.65753E+06 + 4.66500E+02 5.00920E+06 + 4.66600E+02 5.37130E+06 + 4.66700E+02 5.72810E+06 + 4.66800E+02 6.06435E+06 + 4.66900E+02 6.36591E+06 + 4.67000E+02 6.61959E+06 + 4.67100E+02 6.81466E+06 + 4.67200E+02 6.94265E+06 + 4.67300E+02 6.99815E+06 + 4.67400E+02 6.97879E+06 + 4.67500E+02 6.88538E+06 + 4.67600E+02 6.72193E+06 + 4.67700E+02 6.49537E+06 + 4.67800E+02 6.21562E+06 + 4.67900E+02 5.89445E+06 + 4.68000E+02 5.54557E+06 + 4.68100E+02 5.18415E+06 + 4.68200E+02 4.82556E+06 + 4.68300E+02 4.48517E+06 + 4.68400E+02 4.17754E+06 + 4.68500E+02 3.91586E+06 + 4.68600E+02 3.71130E+06 + 4.68700E+02 3.57272E+06 + 4.68800E+02 3.50601E+06 + 4.68900E+02 3.51400E+06 + 4.69000E+02 3.59636E+06 + 4.69100E+02 3.74958E+06 + 4.69200E+02 3.96714E+06 + 4.69300E+02 4.23953E+06 + 4.69400E+02 4.55528E+06 + 4.69500E+02 4.90091E+06 + 4.69600E+02 5.26140E+06 + 4.69700E+02 5.62142E+06 + 4.69800E+02 5.96554E+06 + 4.69900E+02 6.27902E+06 + 4.70000E+02 6.54844E+06 + 4.70100E+02 6.76230E+06 + 4.70200E+02 6.91132E+06 + 4.70300E+02 6.98918E+06 + 4.70400E+02 6.99258E+06 + 4.70500E+02 6.92133E+06 + 4.70600E+02 6.77846E+06 + 4.70700E+02 6.57015E+06 + 4.70800E+02 6.30540E+06 + 4.70900E+02 5.99528E+06 + 4.71000E+02 5.65333E+06 + 4.71100E+02 5.29412E+06 + 4.71200E+02 4.93293E+06 + 4.71300E+02 4.58553E+06 + 4.71400E+02 4.26651E+06 + 4.71500E+02 3.98954E+06 + 4.71600E+02 3.76667E+06 + 4.71700E+02 3.60735E+06 + 4.71800E+02 3.51840E+06 + 4.71900E+02 3.50364E+06 + 4.72000E+02 3.56369E+06 + 4.72100E+02 3.69604E+06 + 4.72200E+02 3.89493E+06 + 4.72300E+02 4.15179E+06 + 4.72400E+02 4.45587E+06 + 4.72500E+02 4.79389E+06 + 4.72600E+02 5.15147E+06 + 4.72700E+02 5.51338E+06 + 4.72800E+02 5.86381E+06 + 4.72900E+02 6.18807E+06 + 4.73000E+02 6.47223E+06 + 4.73100E+02 6.70396E+06 + 4.73200E+02 6.87343E+06 + 4.73300E+02 6.97336E+06 + 4.73400E+02 6.99949E+06 + 4.73500E+02 6.95069E+06 + 4.73600E+02 6.82901E+06 + 4.73700E+02 6.63973E+06 + 4.73800E+02 6.39101E+06 + 4.73900E+02 6.09327E+06 + 4.74000E+02 5.75950E+06 + 4.74100E+02 5.40381E+06 + 4.74200E+02 5.04165E+06 + 4.74300E+02 4.68853E+06 + 4.74400E+02 4.35926E+06 + 4.74500E+02 4.06827E+06 + 4.74600E+02 3.82791E+06 + 4.74700E+02 3.64843E+06 + 4.74800E+02 3.53764E+06 + 4.74900E+02 3.50018E+06 + 4.75000E+02 3.53770E+06 + 4.75100E+02 3.64858E+06 + 4.75200E+02 3.82806E+06 + 4.75300E+02 4.06847E+06 + 4.75400E+02 4.35950E+06 + 4.75500E+02 4.68868E+06 + 4.75600E+02 5.04202E+06 + 4.75700E+02 5.40419E+06 + 4.75800E+02 5.75966E+06 + 4.75900E+02 6.09350E+06 + 4.76000E+02 6.39113E+06 + 4.76100E+02 6.63989E+06 + 4.76200E+02 6.82917E+06 + 4.76300E+02 6.95073E+06 + 4.76400E+02 6.99950E+06 + 4.76500E+02 6.97332E+06 + 4.76600E+02 6.87333E+06 + 4.76700E+02 6.70381E+06 + 4.76800E+02 6.47204E+06 + 4.76900E+02 6.18793E+06 + 4.77000E+02 5.86366E+06 + 4.77100E+02 5.51300E+06 + 4.77200E+02 5.15120E+06 + 4.77300E+02 4.79374E+06 + 4.77400E+02 4.45563E+06 + 4.77500E+02 4.15166E+06 + 4.77600E+02 3.89469E+06 + 4.77700E+02 3.69586E+06 + 4.77800E+02 3.56365E+06 + 4.77900E+02 3.50362E+06 + 4.78000E+02 3.51844E+06 + 4.78100E+02 3.60744E+06 + 4.78200E+02 3.76687E+06 + 4.78300E+02 3.98973E+06 + 4.78400E+02 4.26664E+06 + 4.78500E+02 4.58578E+06 + 4.78600E+02 4.93330E+06 + 4.78700E+02 5.29439E+06 + 4.78800E+02 5.65360E+06 + 4.78900E+02 5.99552E+06 + 4.79000E+02 6.30553E+06 + 4.79100E+02 6.57040E+06 + 4.79200E+02 6.77864E+06 + 4.79300E+02 6.92138E+06 + 4.79400E+02 6.99260E+06 + 4.79500E+02 6.98916E+06 + 4.79600E+02 6.91124E+06 + 4.79700E+02 6.76211E+06 + 4.79800E+02 6.54833E+06 + 4.79900E+02 6.27889E+06 + 4.80000E+02 5.96529E+06 + 4.80100E+02 5.62116E+06 + 4.80200E+02 5.26113E+06 + 4.80300E+02 4.90065E+06 + 4.80400E+02 4.55513E+06 + 4.80500E+02 4.23940E+06 + 4.80600E+02 3.96689E+06 + 4.80700E+02 3.74944E+06 + 4.80800E+02 3.59631E+06 + 4.80900E+02 3.51396E+06 + 4.81000E+02 3.50602E+06 + 4.81100E+02 3.57283E+06 + 4.81200E+02 3.71148E+06 + 4.81300E+02 3.91597E+06 + 4.81400E+02 4.17775E+06 + 4.81500E+02 4.48541E+06 + 4.81600E+02 4.82582E+06 + 4.81700E+02 5.18453E+06 + 4.81800E+02 5.54584E+06 + 4.81900E+02 5.89460E+06 + 4.82000E+02 6.21584E+06 + 4.82100E+02 6.49563E+06 + 4.82200E+02 6.72207E+06 + 4.82300E+02 6.88547E+06 + 4.82400E+02 6.97883E+06 + 4.82500E+02 6.99814E+06 + 4.82600E+02 6.94256E+06 + 4.82700E+02 6.81449E+06 + 4.82800E+02 6.61949E+06 + 4.82900E+02 6.36570E+06 + 4.83000E+02 6.06421E+06 + 4.83100E+02 5.72785E+06 + 4.83200E+02 5.37092E+06 + 4.83300E+02 5.00904E+06 + 4.83400E+02 4.65738E+06 + 4.83500E+02 4.33103E+06 + 4.83600E+02 4.04415E+06 + 4.83700E+02 3.80894E+06 + 4.83800E+02 3.63546E+06 + 4.83900E+02 3.53116E+06 + 4.84000E+02 3.50049E+06 + 4.84100E+02 3.54480E+06 + 4.84200E+02 3.66216E+06 + 4.84300E+02 3.84748E+06 + 4.84400E+02 4.09301E+06 + 4.84500E+02 4.38805E+06 + 4.84600E+02 4.72003E+06 + 4.84700E+02 5.07482E+06 + 4.84800E+02 5.43692E+06 + 4.84900E+02 5.79123E+06 + 4.85000E+02 6.12226E+06 + 4.85100E+02 6.41595E+06 + 4.85200E+02 6.65976E+06 + 4.85300E+02 6.84308E+06 + 4.85400E+02 6.95823E+06 + 4.85500E+02 7.00022E+06 + 4.85600E+02 6.96723E+06 + 4.85700E+02 6.86070E+06 + 4.85800E+02 6.68518E+06 + 4.85900E+02 6.44820E+06 + 4.86000E+02 6.15991E+06 + 4.86100E+02 5.83255E+06 + 4.86200E+02 5.48034E+06 + 4.86300E+02 5.11838E+06 + 4.86400E+02 4.76187E+06 + 4.86500E+02 4.42638E+06 + 4.86600E+02 4.12618E+06 + 4.86700E+02 3.87406E+06 + 4.86800E+02 3.68103E+06 + 4.86900E+02 3.55514E+06 + 4.87000E+02 3.50186E+06 + 4.87100E+02 3.52350E+06 + 4.87200E+02 3.61911E+06 + 4.87300E+02 3.78458E+06 + 4.87400E+02 4.01284E+06 + 4.87500E+02 4.29410E+06 + 4.87600E+02 4.61642E+06 + 4.87700E+02 4.96580E+06 + 4.87800E+02 5.32726E+06 + 4.87900E+02 5.68563E+06 + 4.88000E+02 6.02524E+06 + 4.88100E+02 6.33166E+06 + 4.88200E+02 6.59182E+06 + 4.88300E+02 6.79439E+06 + 4.88400E+02 6.93088E+06 + 4.88500E+02 6.99540E+06 + 4.88600E+02 6.98513E+06 + 4.88700E+02 6.90051E+06 + 4.88800E+02 6.74528E+06 + 4.88900E+02 6.52597E+06 + 4.89000E+02 6.25193E+06 + 4.89100E+02 5.93505E+06 + 4.89200E+02 5.58885E+06 + 4.89300E+02 5.22814E+06 + 4.89400E+02 4.86838E+06 + 4.89500E+02 4.52498E+06 + 4.89600E+02 4.21256E+06 + 4.89700E+02 3.94468E+06 + 4.89800E+02 3.73279E+06 + 4.89900E+02 3.58579E+06 + 4.90000E+02 3.51014E+06 + 4.90100E+02 3.50903E+06 + 4.90200E+02 3.58253E+06 + 4.90300E+02 3.72741E+06 + 4.90400E+02 3.93756E+06 + 4.90500E+02 4.20401E+06 + 4.90600E+02 4.51522E+06 + 4.90700E+02 4.85791E+06 + 4.90800E+02 5.21740E+06 + 4.90900E+02 5.57830E+06 + 4.91000E+02 5.92516E+06 + 4.91100E+02 6.24319E+06 + 4.91200E+02 6.51859E+06 + 4.91300E+02 6.73961E+06 + 4.91400E+02 6.89694E+06 + 4.91500E+02 6.98368E+06 + 4.91600E+02 6.99617E+06 + 4.91700E+02 6.93385E+06 + 4.91800E+02 6.79947E+06 + 4.91900E+02 6.59870E+06 + 4.92000E+02 6.34008E+06 + 4.92100E+02 6.03486E+06 + 4.92200E+02 5.69592E+06 + 4.92300E+02 5.33809E+06 + 4.92400E+02 4.97640E+06 + 4.92500E+02 4.62634E+06 + 4.92600E+02 4.30312E+06 + 4.92700E+02 4.02046E+06 + 4.92800E+02 3.79048E+06 + 4.92900E+02 3.62303E+06 + 4.93000E+02 3.52528E+06 + 4.93100E+02 3.50143E+06 + 4.93200E+02 3.55250E+06 + 4.93300E+02 3.67625E+06 + 4.93400E+02 3.86752E+06 + 4.93500E+02 4.11797E+06 + 4.93600E+02 4.41692E+06 + 4.93700E+02 4.75166E+06 + 4.93800E+02 5.10746E+06 + 4.93900E+02 5.46969E+06 + 4.94000E+02 5.82251E+06 + 4.94100E+02 6.15080E+06 + 4.94200E+02 6.44035E+06 + 4.94300E+02 6.67894E+06 + 4.94400E+02 6.85646E+06 + 4.94500E+02 6.96514E+06 + 4.94600E+02 7.00032E+06 + 4.94700E+02 6.96054E+06 + 4.94800E+02 6.84754E+06 + 4.94900E+02 6.66604E+06 + 4.95000E+02 6.42386E+06 + 4.95100E+02 6.13156E+06 + 4.95200E+02 5.80133E+06 + 4.95300E+02 5.44770E+06 + 4.95400E+02 5.08540E+06 + 4.95500E+02 4.73037E+06 + 4.95600E+02 4.39742E+06 + 4.95700E+02 4.10101E+06 + 4.95800E+02 3.85399E+06 + 4.95900E+02 3.66665E+06 + 4.96000E+02 3.54724E+06 + 4.96100E+02 3.50073E+06 + 4.96200E+02 3.52920E+06 + 4.96300E+02 3.63135E+06 + 4.96400E+02 3.80281E+06 + 4.96500E+02 4.03639E+06 + 4.96600E+02 4.32200E+06 + 4.96700E+02 4.64718E+06 + 4.96800E+02 4.99840E+06 + 4.96900E+02 5.36020E+06 + 4.97000E+02 5.71750E+06 + 4.97100E+02 6.05478E+06 + 4.97200E+02 6.35741E+06 + 4.97300E+02 6.61264E+06 + 4.97400E+02 6.80964E+06 + 4.97500E+02 6.93982E+06 + 4.97600E+02 6.99757E+06 + 4.97700E+02 6.98048E+06 + 4.97800E+02 6.88931E+06 + 4.97900E+02 6.72786E+06 + 4.98000E+02 6.50308E+06 + 4.98100E+02 6.22478E+06 + 4.98200E+02 5.90457E+06 + 4.98300E+02 5.55653E+06 + 4.98400E+02 5.19516E+06 + 4.98500E+02 4.83615E+06 + 4.98600E+02 4.49508E+06 + 4.98700E+02 4.18618E+06 + 4.98800E+02 3.92302E+06 + 4.98900E+02 3.71657E+06 + 4.99000E+02 3.57592E+06 + 4.99100E+02 3.50693E+06 + 4.99200E+02 3.51266E+06 + 4.99300E+02 3.59280E+06 + 4.99400E+02 3.74399E+06 + 4.99500E+02 3.95961E+06 + 4.99600E+02 4.23065E+06 + 4.99700E+02 4.54539E+06 + 4.99800E+02 4.89013E+06 + 4.99900E+02 5.25029E+06 + 5.00000E+02 5.61065E+06 + 5.00100E+02 5.95557E+06 + 5.00200E+02 6.27009E+06 + 5.00300E+02 6.54110E+06 + 5.00400E+02 6.75667E+06 + 5.00500E+02 6.90782E+06 + 5.00600E+02 6.98793E+06 + 5.00700E+02 6.99358E+06 + 5.00800E+02 6.92460E+06 + 5.00900E+02 6.78384E+06 + 5.01000E+02 6.57736E+06 + 5.01100E+02 6.31399E+06 + 5.01200E+02 6.00523E+06 + 5.01300E+02 5.66414E+06 + 5.01400E+02 5.30513E+06 + 5.01500E+02 4.94376E+06 + 5.01600E+02 4.59573E+06 + 5.01700E+02 4.27554E+06 + 5.01800E+02 3.99728E+06 + 5.01900E+02 3.77254E+06 + 5.02000E+02 3.61114E+06 + 5.02100E+02 3.52002E+06 + 5.02200E+02 3.50299E+06 + 5.02300E+02 3.56078E+06 + 5.02400E+02 3.69100E+06 + 5.02500E+02 3.88792E+06 + 5.02600E+02 4.14332E+06 + 5.02700E+02 4.44617E+06 + 5.02800E+02 4.78327E+06 + 5.02900E+02 5.14058E+06 + 5.03000E+02 5.50238E+06 + 5.03100E+02 5.85359E+06 + 5.03200E+02 6.17893E+06 + 5.03300E+02 6.46432E+06 + 5.03400E+02 6.69774E+06 + 5.03500E+02 6.86928E+06 + 5.03600E+02 6.97142E+06 + 5.03700E+02 6.99980E+06 + 5.03800E+02 6.95324E+06 + 5.03900E+02 6.83377E+06 + 5.04000E+02 6.64639E+06 + 5.04100E+02 6.39918E+06 + 5.04200E+02 6.10290E+06 + 5.04300E+02 5.77013E+06 + 5.04400E+02 5.41488E+06 + 5.04500E+02 5.05259E+06 + 5.04600E+02 4.69876E+06 + 5.04700E+02 4.36876E+06 + 5.04800E+02 4.07649E+06 + 5.04900E+02 3.83435E+06 + 5.05000E+02 3.65289E+06 + 5.05100E+02 3.53994E+06 + 5.05200E+02 3.50021E+06 + 5.05300E+02 3.53544E+06 + 5.05400E+02 3.64417E+06 + 5.05500E+02 3.82174E+06 + 5.05600E+02 4.06037E+06 + 5.05700E+02 4.35013E+06 + 5.05800E+02 4.67826E+06 + 5.05900E+02 5.03110E+06 + 5.06000E+02 5.39311E+06 + 5.06100E+02 5.74921E+06 + 5.06200E+02 6.08393E+06 + 5.06300E+02 6.38276E+06 + 5.06400E+02 6.63324E+06 + 5.06500E+02 6.82434E+06 + 5.06600E+02 6.94812E+06 + 5.06700E+02 6.99912E+06 + 5.06800E+02 6.97521E+06 + 5.06900E+02 6.87745E+06 + 5.07000E+02 6.70992E+06 + 5.07100E+02 6.47982E+06 + 5.07200E+02 6.19721E+06 + 5.07300E+02 5.87386E+06 + 5.07400E+02 5.52399E+06 + 5.07500E+02 5.16219E+06 + 5.07600E+02 4.80417E+06 + 5.07700E+02 4.46546E+06 + 5.07800E+02 4.16034E+06 + 5.07900E+02 3.90175E+06 + 5.08000E+02 3.70095E+06 + 5.08100E+02 3.56662E+06 + 5.08200E+02 3.50435E+06 + 5.08300E+02 3.51688E+06 + 5.08400E+02 3.60368E+06 + 5.08500E+02 3.76106E+06 + 5.08600E+02 3.98212E+06 + 5.08700E+02 4.25764E+06 + 5.08800E+02 4.57551E+06 + 5.08900E+02 4.92248E+06 + 5.09000E+02 5.28349E+06 + 5.09100E+02 5.64287E+06 + 5.09200E+02 5.98564E+06 + 5.09300E+02 6.29672E+06 + 5.09400E+02 6.56314E+06 + 5.09500E+02 6.77319E+06 + 5.09600E+02 6.91811E+06 + 5.09700E+02 6.99154E+06 + 5.09800E+02 6.99037E+06 + 5.09900E+02 6.91464E+06 + 5.10000E+02 6.76768E+06 + 5.10100E+02 6.55561E+06 + 5.10200E+02 6.28760E+06 + 5.10300E+02 5.97533E+06 + 5.10400E+02 5.63202E+06 + 5.10500E+02 5.27214E+06 + 5.10600E+02 4.91134E+06 + 5.10700E+02 4.56525E+06 + 5.10800E+02 4.24832E+06 + 5.10900E+02 3.97447E+06 + 5.11000E+02 3.75513E+06 + 5.11100E+02 3.59987E+06 + 5.11200E+02 3.51538E+06 + 5.11300E+02 3.50515E+06 + 5.11400E+02 3.56969E+06 + 5.11500E+02 3.70626E+06 + 5.11600E+02 3.90887E+06 + 5.11700E+02 4.16907E+06 + 5.11800E+02 4.47542E+06 + 5.11900E+02 4.81515E+06 + 5.12000E+02 5.17353E+06 + 5.12100E+02 5.53498E+06 + 5.12200E+02 5.88445E+06 + 5.12300E+02 6.20673E+06 + 5.12400E+02 6.48787E+06 + 5.12500E+02 6.71615E+06 + 5.12600E+02 6.88152E+06 + 5.12700E+02 6.97706E+06 + 5.12800E+02 6.99865E+06 + 5.12900E+02 6.94533E+06 + 5.13000E+02 6.81935E+06 + 5.13100E+02 6.62625E+06 + 5.13200E+02 6.37425E+06 + 5.13300E+02 6.07394E+06 + 5.13400E+02 5.73833E+06 + 5.13500E+02 5.38180E+06 + 5.13600E+02 5.01984E+06 + 5.13700E+02 4.66775E+06 + 5.13800E+02 4.34042E+06 + 5.13900E+02 4.05223E+06 + 5.14000E+02 3.81509E+06 + 5.14100E+02 3.63970E+06 + 5.14200E+02 3.53326E+06 + 5.14300E+02 3.50032E+06 + 5.14400E+02 3.54234E+06 + 5.14500E+02 3.65756E+06 + 5.14600E+02 3.84105E+06 + 5.14700E+02 4.08478E+06 + 5.14800E+02 4.37858E+06 + 5.14900E+02 4.70954E+06 + 5.15000E+02 5.06387E+06 + 5.15100E+02 5.42597E+06 + 5.15200E+02 5.78075E+06 + 5.15300E+02 6.11279E+06 + 5.15400E+02 6.40771E+06 + 5.15500E+02 6.65321E+06 + 5.15600E+02 6.83848E+06 + 5.15700E+02 6.95582E+06 + 5.15800E+02 7.00005E+06 + 5.15900E+02 6.96933E+06 + 5.16000E+02 6.86494E+06 + 5.16100E+02 6.69146E+06 + 5.16200E+02 6.45628E+06 + 5.16300E+02 6.16911E+06 + 5.16400E+02 5.84292E+06 + 5.16500E+02 5.49114E+06 + 5.16600E+02 5.12926E+06 + 5.16700E+02 4.77255E+06 + 5.16800E+02 4.43611E+06 + 5.16900E+02 4.13456E+06 + 5.17000E+02 3.88083E+06 + 5.17100E+02 3.68588E+06 + 5.17200E+02 3.55791E+06 + 5.17300E+02 3.50238E+06 + 5.17400E+02 3.52173E+06 + 5.17500E+02 3.61523E+06 + 5.17600E+02 3.77865E+06 + 5.17700E+02 4.00508E+06 + 5.17800E+02 4.28499E+06 + 5.17900E+02 4.60607E+06 + 5.18000E+02 4.95494E+06 + 5.18100E+02 5.31647E+06 + 5.18200E+02 5.67495E+06 + 5.18300E+02 6.01545E+06 + 5.18400E+02 6.32298E+06 + 5.18500E+02 6.58473E+06 + 5.18600E+02 6.78918E+06 + 5.18700E+02 6.92781E+06 + 5.18800E+02 6.99454E+06 + 5.18900E+02 6.98654E+06 + 5.19000E+02 6.90414E+06 + 5.19100E+02 6.75097E+06 + 5.19200E+02 6.53355E+06 + 5.19300E+02 6.26085E+06 + 5.19400E+02 5.94517E+06 + 5.19500E+02 5.59954E+06 + 5.19600E+02 5.23915E+06 + 5.19700E+02 4.87924E+06 + 5.19800E+02 4.53482E+06 + 5.19900E+02 4.22144E+06 + 5.20000E+02 3.95197E+06 + 5.20100E+02 3.73825E+06 + 5.20200E+02 3.58926E+06 + 5.20300E+02 3.51135E+06 + 5.20400E+02 3.50797E+06 + 5.20500E+02 3.57926E+06 + 5.20600E+02 3.72207E+06 + 5.20700E+02 3.93030E+06 + 5.20800E+02 4.19521E+06 + 5.20900E+02 4.50514E+06 + 5.21000E+02 4.84739E+06 + 5.21100E+02 5.20650E+06 + 5.21200E+02 5.56748E+06 + 5.21300E+02 5.91508E+06 + 5.21400E+02 6.23401E+06 + 5.21500E+02 6.51098E+06 + 5.21600E+02 6.73391E+06 + 5.21700E+02 6.89318E+06 + 5.21800E+02 6.98214E+06 + 5.21900E+02 6.99690E+06 + 5.22000E+02 6.93682E+06 + 5.22100E+02 6.80456E+06 + 5.22200E+02 6.60562E+06 + 5.22300E+02 6.34859E+06 + 5.22400E+02 6.04468E+06 + 5.22500E+02 5.70656E+06 + 5.22600E+02 5.34909E+06 + 5.22700E+02 4.98739E+06 + 5.22800E+02 4.63654E+06 + 5.22900E+02 4.31239E+06 + 5.23000E+02 4.02824E+06 + 5.23100E+02 3.79658E+06 + 5.23200E+02 3.62716E+06 + 5.23300E+02 3.52714E+06 + 5.23400E+02 3.50105E+06 + 5.23500E+02 3.54989E+06 + 5.23600E+02 3.67152E+06 + 5.23700E+02 3.86073E+06 + 5.23800E+02 4.10959E+06 + 5.23900E+02 4.40734E+06 + 5.24000E+02 4.74122E+06 + 5.24100E+02 5.09670E+06 + 5.24200E+02 5.45876E+06 + 5.24300E+02 5.81209E+06 + 5.24400E+02 6.14116E+06 + 5.24500E+02 6.43241E+06 + 5.24600E+02 6.67268E+06 + 5.24700E+02 6.85206E+06 + 5.24800E+02 6.96291E+06 + 5.24900E+02 7.00036E+06 + 5.25000E+02 6.96284E+06 + 5.25100E+02 6.85192E+06 + 5.25200E+02 6.67248E+06 + 5.25300E+02 6.43200E+06 + 5.25400E+02 6.14106E+06 + 5.25500E+02 5.81177E+06 + 5.25600E+02 5.45864E+06 + 5.25700E+02 5.09637E+06 + 5.25800E+02 4.74069E+06 + 5.25900E+02 4.40705E+06 + 5.26000E+02 4.10934E+06 + 5.26100E+02 3.86066E+06 + 5.26200E+02 3.67147E+06 + 5.26300E+02 3.54976E+06 + 5.26400E+02 3.50104E+06 + 5.26500E+02 3.52724E+06 + 5.26600E+02 3.62720E+06 + 5.26700E+02 3.79665E+06 + 5.26800E+02 4.02864E+06 + 5.26900E+02 4.31268E+06 + 5.27000E+02 4.63706E+06 + 5.27100E+02 4.98751E+06 + 5.27200E+02 5.34921E+06 + 5.27300E+02 5.70688E+06 + 5.27400E+02 6.04498E+06 + 5.27500E+02 6.34902E+06 + 5.27600E+02 6.60583E+06 + 5.27700E+02 6.80462E+06 + 5.27800E+02 6.93691E+06 + 5.27900E+02 6.99691E+06 + 5.28000E+02 6.98207E+06 + 5.28100E+02 6.89306E+06 + 5.28200E+02 6.73373E+06 + 5.28300E+02 6.51074E+06 + 5.28400E+02 6.23391E+06 + 5.28500E+02 5.91477E+06 + 5.28600E+02 5.56715E+06 + 5.28700E+02 5.20616E+06 + 5.28800E+02 4.84686E+06 + 5.28900E+02 4.50503E+06 + 5.29000E+02 4.19494E+06 + 5.29100E+02 3.93022E+06 + 5.29200E+02 3.72190E+06 + 5.29300E+02 3.57910E+06 + 5.29400E+02 3.50793E+06 + 5.29500E+02 3.51138E+06 + 5.29600E+02 3.58929E+06 + 5.29700E+02 3.73831E+06 + 5.29800E+02 3.95234E+06 + 5.29900E+02 4.22172E+06 + 5.30000E+02 4.53532E+06 + 5.30100E+02 4.87936E+06 + 5.30200E+02 5.23928E+06 + 5.30300E+02 5.60008E+06 + 5.30400E+02 5.94548E+06 + 5.30500E+02 6.26130E+06 + 5.30600E+02 6.53364E+06 + 5.30700E+02 6.75103E+06 + 5.30800E+02 6.90425E+06 + 5.30900E+02 6.98658E+06 + 5.31000E+02 6.99450E+06 + 5.31100E+02 6.92771E+06 + 5.31200E+02 6.78912E+06 + 5.31300E+02 6.58451E+06 + 5.31400E+02 6.32288E+06 + 5.31500E+02 6.01495E+06 + 5.31600E+02 5.67463E+06 + 5.31700E+02 5.31613E+06 + 5.31800E+02 4.95461E+06 + 5.31900E+02 4.60596E+06 + 5.32000E+02 4.28471E+06 + 5.32100E+02 4.00484E+06 + 5.32200E+02 3.77847E+06 + 5.32300E+02 3.61503E+06 + 5.32400E+02 3.52171E+06 + 5.32500E+02 3.50240E+06 + 5.32600E+02 3.55795E+06 + 5.32700E+02 3.68604E+06 + 5.32800E+02 3.88117E+06 + 5.32900E+02 4.13482E+06 + 5.33000E+02 4.43640E+06 + 5.33100E+02 4.77267E+06 + 5.33200E+02 5.12938E+06 + 5.33300E+02 5.49169E+06 + 5.33400E+02 5.84324E+06 + 5.33500E+02 6.16958E+06 + 5.33600E+02 6.45637E+06 + 5.33700E+02 6.69153E+06 + 5.33800E+02 6.86515E+06 + 5.33900E+02 6.96939E+06 + 5.34000E+02 7.00004E+06 + 5.34100E+02 6.95574E+06 + 5.34200E+02 6.83843E+06 + 5.34300E+02 6.65301E+06 + 5.34400E+02 6.40746E+06 + 5.34500E+02 6.11231E+06 + 5.34600E+02 5.78043E+06 + 5.34700E+02 5.42584E+06 + 5.34800E+02 5.06353E+06 + 5.34900E+02 4.70943E+06 + 5.35000E+02 4.37810E+06 + 5.35100E+02 4.08452E+06 + 5.35200E+02 3.84085E+06 + 5.35300E+02 3.65742E+06 + 5.35400E+02 3.54231E+06 + 5.35500E+02 3.50031E+06 + 5.35600E+02 3.53332E+06 + 5.35700E+02 3.63983E+06 + 5.35800E+02 3.81540E+06 + 5.35900E+02 4.05232E+06 + 5.36000E+02 4.34070E+06 + 5.36100E+02 4.66787E+06 + 5.36200E+02 5.02018E+06 + 5.36300E+02 5.38235E+06 + 5.36400E+02 5.73865E+06 + 5.36500E+02 6.07424E+06 + 5.36600E+02 6.37434E+06 + 5.36700E+02 6.62633E+06 + 5.36800E+02 6.81959E+06 + 5.36900E+02 6.94541E+06 + 5.37000E+02 6.99868E+06 + 5.37100E+02 6.97704E+06 + 5.37200E+02 6.88147E+06 + 5.37300E+02 6.71585E+06 + 5.37400E+02 6.48763E+06 + 5.37500E+02 6.20627E+06 + 5.37600E+02 5.88413E+06 + 5.37700E+02 5.53486E+06 + 5.37800E+02 5.17319E+06 + 5.37900E+02 4.81482E+06 + 5.38000E+02 4.47512E+06 + 5.38100E+02 4.16881E+06 + 5.38200E+02 3.90879E+06 + 5.38300E+02 3.70610E+06 + 5.38400E+02 3.56966E+06 + 5.38500E+02 3.50512E+06 + 5.38600E+02 3.51542E+06 + 5.38700E+02 3.59998E+06 + 5.38800E+02 3.75530E+06 + 5.38900E+02 3.97455E+06 + 5.39000E+02 4.24859E+06 + 5.39100E+02 4.56556E+06 + 5.39200E+02 4.91167E+06 + 5.39300E+02 5.27248E+06 + 5.39400E+02 5.63214E+06 + 5.39500E+02 5.97564E+06 + 5.39600E+02 6.28788E+06 + 5.39700E+02 6.55584E+06 + 5.39800E+02 6.76784E+06 + 5.39900E+02 6.91474E+06 + 5.40000E+02 6.99041E+06 + 5.40100E+02 6.99151E+06 + 5.40200E+02 6.91807E+06 + 5.40300E+02 6.77303E+06 + 5.40400E+02 6.56292E+06 + 5.40500E+02 6.29645E+06 + 5.40600E+02 5.98534E+06 + 5.40700E+02 5.64275E+06 + 5.40800E+02 5.28294E+06 + 5.40900E+02 4.92214E+06 + 5.41000E+02 4.57520E+06 + 5.41100E+02 4.25736E+06 + 5.41200E+02 3.98203E+06 + 5.41300E+02 3.76088E+06 + 5.41400E+02 3.60357E+06 + 5.41500E+02 3.51683E+06 + 5.41600E+02 3.50437E+06 + 5.41700E+02 3.56665E+06 + 5.41800E+02 3.70111E+06 + 5.41900E+02 3.90183E+06 + 5.42000E+02 4.16060E+06 + 5.42100E+02 4.46576E+06 + 5.42200E+02 4.80449E+06 + 5.42300E+02 5.16253E+06 + 5.42400E+02 5.52411E+06 + 5.42500E+02 5.87417E+06 + 5.42600E+02 6.19749E+06 + 5.42700E+02 6.48006E+06 + 5.42800E+02 6.71010E+06 + 5.42900E+02 6.87750E+06 + 5.43000E+02 6.97527E+06 + 5.43100E+02 6.99911E+06 + 5.43200E+02 6.94804E+06 + 5.43300E+02 6.82420E+06 + 5.43400E+02 6.63303E+06 + 5.43500E+02 6.38250E+06 + 5.43600E+02 6.08364E+06 + 5.43700E+02 5.74910E+06 + 5.43800E+02 5.39277E+06 + 5.43900E+02 5.03076E+06 + 5.44000E+02 4.67794E+06 + 5.44100E+02 4.34984E+06 + 5.44200E+02 4.06028E+06 + 5.44300E+02 3.82142E+06 + 5.44400E+02 3.64404E+06 + 5.44500E+02 3.53538E+06 + 5.44600E+02 3.50021E+06 + 5.44700E+02 3.53997E+06 + 5.44800E+02 3.65303E+06 + 5.44900E+02 3.83455E+06 + 5.45000E+02 4.07674E+06 + 5.45100E+02 4.36905E+06 + 5.45200E+02 4.69908E+06 + 5.45300E+02 5.05292E+06 + 5.45400E+02 5.41501E+06 + 5.45500E+02 5.77045E+06 + 5.45600E+02 6.10320E+06 + 5.45700E+02 6.39943E+06 + 5.45800E+02 6.64660E+06 + 5.45900E+02 6.83383E+06 + 5.46000E+02 6.95332E+06 + 5.46100E+02 6.99981E+06 + 5.46200E+02 6.97136E+06 + 5.46300E+02 6.86915E+06 + 5.46400E+02 6.69767E+06 + 5.46500E+02 6.46408E+06 + 5.46600E+02 6.17865E+06 + 5.46700E+02 5.85327E+06 + 5.46800E+02 5.50205E+06 + 5.46900E+02 5.14024E+06 + 5.47000E+02 4.78295E+06 + 5.47100E+02 4.44587E+06 + 5.47200E+02 4.14323E+06 + 5.47300E+02 3.88771E+06 + 5.47400E+02 3.69085E+06 + 5.47500E+02 3.56070E+06 + 5.47600E+02 3.50297E+06 + 5.47700E+02 3.52004E+06 + 5.47800E+02 3.61133E+06 + 5.47900E+02 3.77272E+06 + 5.48000E+02 3.99752E+06 + 5.48100E+02 4.27582E+06 + 5.48200E+02 4.59585E+06 + 5.48300E+02 4.94409E+06 + 5.48400E+02 5.30547E+06 + 5.48500E+02 5.66447E+06 + 5.48600E+02 6.00553E+06 + 5.48700E+02 6.31426E+06 + 5.48800E+02 6.57758E+06 + 5.48900E+02 6.78390E+06 + 5.49000E+02 6.92470E+06 + 5.49100E+02 6.99361E+06 + 5.49200E+02 6.98789E+06 + 5.49300E+02 6.90771E+06 + 5.49400E+02 6.75661E+06 + 5.49500E+02 6.54087E+06 + 5.49600E+02 6.26982E+06 + 5.49700E+02 5.95527E+06 + 5.49800E+02 5.61032E+06 + 5.49900E+02 5.25016E+06 + 5.50000E+02 4.88980E+06 + 5.50100E+02 4.54508E+06 + 5.50200E+02 4.23037E+06 + 5.50300E+02 3.95938E+06 + 5.50400E+02 3.74382E+06 + 5.50500E+02 3.59269E+06 + 5.50600E+02 3.51262E+06 + 5.50700E+02 3.50694E+06 + 5.50800E+02 3.57602E+06 + 5.50900E+02 3.71673E+06 + 5.51000E+02 3.92324E+06 + 5.51100E+02 4.18644E+06 + 5.51200E+02 4.49519E+06 + 5.51300E+02 4.83668E+06 + 5.51400E+02 5.19549E+06 + 5.51500E+02 5.55686E+06 + 5.51600E+02 5.90488E+06 + 5.51700E+02 6.22489E+06 + 5.51800E+02 6.50332E+06 + 5.51900E+02 6.72804E+06 + 5.52000E+02 6.88943E+06 + 5.52100E+02 6.98053E+06 + 5.52200E+02 6.99756E+06 + 5.52300E+02 6.93973E+06 + 5.52400E+02 6.80959E+06 + 5.52500E+02 6.61243E+06 + 5.52600E+02 6.35714E+06 + 5.52700E+02 6.05448E+06 + 5.52800E+02 5.71718E+06 + 5.52900E+02 5.36008E+06 + 5.53000E+02 4.99807E+06 + 5.53100E+02 4.64687E+06 + 5.53200E+02 4.32171E+06 + 5.53300E+02 4.03615E+06 + 5.53400E+02 3.80274E+06 + 5.53500E+02 3.63122E+06 + 5.53600E+02 3.52914E+06 + 5.53700E+02 3.50074E+06 + 5.53800E+02 3.54732E+06 + 5.53900E+02 3.66680E+06 + 5.54000E+02 3.85419E+06 + 5.54100E+02 4.10127E+06 + 5.54200E+02 4.39752E+06 + 5.54300E+02 4.73070E+06 + 5.54400E+02 5.08574E+06 + 5.54500E+02 5.44804E+06 + 5.54600E+02 5.80165E+06 + 5.54700E+02 6.13167E+06 + 5.54800E+02 6.42411E+06 + 5.54900E+02 6.66624E+06 + 5.55000E+02 6.84768E+06 + 5.55100E+02 6.96061E+06 + 5.55200E+02 7.00032E+06 + 5.55300E+02 6.96507E+06 + 5.55400E+02 6.85633E+06 + 5.55500E+02 6.67875E+06 + 5.55600E+02 6.44010E+06 + 5.55700E+02 6.15052E+06 + 5.55800E+02 5.82219E+06 + 5.55900E+02 5.46956E+06 + 5.56000E+02 5.10713E+06 + 5.56100E+02 4.75124E+06 + 5.56200E+02 4.41671E+06 + 5.56300E+02 4.11771E+06 + 5.56400E+02 3.86738E+06 + 5.56500E+02 3.67615E+06 + 5.56600E+02 3.55240E+06 + 5.56700E+02 3.50142E+06 + 5.56800E+02 3.52534E+06 + 5.56900E+02 3.62312E+06 + 5.57000E+02 3.79067E+06 + 5.57100E+02 4.02062E+06 + 5.57200E+02 4.30340E+06 + 5.57300E+02 4.62676E+06 + 5.57400E+02 4.97663E+06 + 5.57500E+02 5.33843E+06 + 5.57600E+02 5.69624E+06 + 5.57700E+02 6.03497E+06 + 5.57800E+02 6.34043E+06 + 5.57900E+02 6.59884E+06 + 5.58000E+02 6.79962E+06 + 5.58100E+02 6.93394E+06 + 5.58200E+02 6.99618E+06 + 5.58300E+02 6.98365E+06 + 5.58400E+02 6.89682E+06 + 5.58500E+02 6.73943E+06 + 5.58600E+02 6.51836E+06 + 5.58700E+02 6.24300E+06 + 5.58800E+02 5.92494E+06 + 5.58900E+02 5.57797E+06 + 5.59000E+02 5.21696E+06 + 5.59100E+02 4.85758E+06 + 5.59200E+02 4.51501E+06 + 5.59300E+02 4.20374E+06 + 5.59400E+02 3.93747E+06 + 5.59500E+02 3.72719E+06 + 5.59600E+02 3.58240E+06 + 5.59700E+02 3.50900E+06 + 5.59800E+02 3.51017E+06 + 5.59900E+02 3.58586E+06 + 5.60000E+02 3.73290E+06 + 5.60100E+02 3.94498E+06 + 5.60200E+02 4.21283E+06 + 5.60300E+02 4.52528E+06 + 5.60400E+02 4.86861E+06 + 5.60500E+02 5.22848E+06 + 5.60600E+02 5.58908E+06 + 5.60700E+02 5.93536E+06 + 5.60800E+02 6.25229E+06 + 5.60900E+02 6.52612E+06 + 5.61000E+02 6.74545E+06 + 5.61100E+02 6.90062E+06 + 5.61200E+02 6.98514E+06 + 5.61300E+02 6.99536E+06 + 5.61400E+02 6.93082E+06 + 5.61500E+02 6.79423E+06 + 5.61600E+02 6.59161E+06 + 5.61700E+02 6.33156E+06 + 5.61800E+02 6.02503E+06 + 5.61900E+02 5.68530E+06 + 5.62000E+02 5.32692E+06 + 5.62100E+02 4.96547E+06 + 5.62200E+02 4.61621E+06 + 5.62300E+02 4.29391E+06 + 5.62400E+02 4.01260E+06 + 5.62500E+02 3.78434E+06 + 5.62600E+02 3.61899E+06 + 5.62700E+02 3.52347E+06 + 5.62800E+02 3.50188E+06 + 5.62900E+02 3.55517E+06 + 5.63000E+02 3.68122E+06 + 5.63100E+02 3.87434E+06 + 5.63200E+02 4.12635E+06 + 5.63300E+02 4.42667E+06 + 5.63400E+02 4.76209E+06 + 5.63500E+02 5.11861E+06 + 5.63600E+02 5.48078E+06 + 5.63700E+02 5.83287E+06 + 5.63800E+02 6.16020E+06 + 5.63900E+02 6.44837E+06 + 5.64000E+02 6.68537E+06 + 5.64100E+02 6.86079E+06 + 5.64200E+02 6.96730E+06 + 5.64300E+02 7.00022E+06 + 5.64400E+02 6.95818E+06 + 5.64500E+02 6.84294E+06 + 5.64600E+02 6.65956E+06 + 5.64700E+02 6.41585E+06 + 5.64800E+02 6.12188E+06 + 5.64900E+02 5.79091E+06 + 5.65000E+02 5.43658E+06 + 5.65100E+02 5.07448E+06 + 5.65200E+02 4.71991E+06 + 5.65300E+02 4.38785E+06 + 5.65400E+02 4.09276E+06 + 5.65500E+02 3.84728E+06 + 5.65600E+02 3.66202E+06 + 5.65700E+02 3.54475E+06 + 5.65800E+02 3.50049E+06 + 5.65900E+02 3.53118E+06 + 5.66000E+02 3.63563E+06 + 5.66100E+02 3.80913E+06 + 5.66200E+02 4.04432E+06 + 5.66300E+02 4.33131E+06 + 5.66400E+02 4.65750E+06 + 5.66500E+02 5.00948E+06 + 5.66600E+02 5.37136E+06 + 5.66700E+02 5.72807E+06 + 5.66800E+02 6.06451E+06 + 5.66900E+02 6.36588E+06 + 5.67000E+02 6.61963E+06 + 5.67100E+02 6.81469E+06 + 5.67200E+02 6.94264E+06 + 5.67300E+02 6.99816E+06 + 5.67400E+02 6.97879E+06 + 5.67500E+02 6.88535E+06 + 5.67600E+02 6.72195E+06 + 5.67700E+02 6.49540E+06 + 5.67800E+02 6.21547E+06 + 5.67900E+02 5.89438E+06 + 5.68000E+02 5.54551E+06 + 5.68100E+02 5.18419E+06 + 5.68200E+02 4.82570E+06 + 5.68300E+02 4.48501E+06 + 5.68400E+02 4.17749E+06 + 5.68500E+02 3.91575E+06 + 5.68600E+02 3.71132E+06 + 5.68700E+02 3.57276E+06 + 5.68800E+02 3.50600E+06 + 5.68900E+02 3.51400E+06 + 5.69000E+02 3.59642E+06 + 5.69100E+02 3.74961E+06 + 5.69200E+02 3.96704E+06 + 5.69300E+02 4.23958E+06 + 5.69400E+02 4.55525E+06 + 5.69500E+02 4.90108E+06 + 5.69600E+02 5.26147E+06 + 5.69700E+02 5.62138E+06 + 5.69800E+02 5.96560E+06 + 5.69900E+02 6.27899E+06 + 5.70000E+02 6.54862E+06 + 5.70100E+02 6.76233E+06 + 5.70200E+02 6.91131E+06 + 5.70300E+02 6.98920E+06 + 5.70400E+02 6.99258E+06 + 5.70500E+02 6.92131E+06 + 5.70600E+02 6.77842E+06 + 5.70700E+02 6.57018E+06 + 5.70800E+02 6.30526E+06 + 5.70900E+02 5.99531E+06 + 5.71000E+02 5.65327E+06 + 5.71100E+02 5.29416E+06 + 5.71200E+02 4.93297E+06 + 5.71300E+02 4.58537E+06 + 5.71400E+02 4.26645E+06 + 5.71500E+02 3.98950E+06 + 5.71600E+02 3.76669E+06 + 5.71700E+02 3.60740E+06 + 5.71800E+02 3.51838E+06 + 5.71900E+02 3.50364E+06 + 5.72000E+02 3.56374E+06 + 5.72100E+02 3.69602E+06 + 5.72200E+02 3.89483E+06 + 5.72300E+02 4.15184E+06 + 5.72400E+02 4.45593E+06 + 5.72500E+02 4.79406E+06 + 5.72600E+02 5.15153E+06 + 5.72700E+02 5.51323E+06 + 5.72800E+02 5.86387E+06 + 5.72900E+02 6.18803E+06 + 5.73000E+02 6.47236E+06 + 5.73100E+02 6.70400E+06 + 5.73200E+02 6.87341E+06 + 5.73300E+02 6.97337E+06 + 5.73400E+02 6.99949E+06 + 5.73500E+02 6.95062E+06 + 5.73600E+02 6.82898E+06 + 5.73700E+02 6.63975E+06 + 5.73800E+02 6.39088E+06 + 5.73900E+02 6.09330E+06 + 5.74000E+02 5.75944E+06 + 5.74100E+02 5.40375E+06 + 5.74200E+02 5.04169E+06 + 5.74300E+02 4.68836E+06 + 5.74400E+02 4.35930E+06 + 5.74500E+02 4.06822E+06 + 5.74600E+02 3.82793E+06 + 5.74700E+02 3.64844E+06 + 5.74800E+02 3.53761E+06 + 5.74900E+02 3.50018E+06 + 5.75000E+02 3.53771E+06 + 5.75100E+02 3.64856E+06 + 5.75200E+02 3.82798E+06 + 5.75300E+02 4.06860E+06 + 5.75400E+02 4.35955E+06 + 5.75500E+02 4.68884E+06 + 5.75600E+02 5.04198E+06 + 5.75700E+02 5.40404E+06 + 5.75800E+02 5.75972E+06 + 5.75900E+02 6.09356E+06 + 5.76000E+02 6.39126E+06 + 5.76100E+02 6.63993E+06 + 5.76200E+02 6.82911E+06 + 5.76300E+02 6.95075E+06 + 5.76400E+02 6.99949E+06 + 5.76500E+02 6.97328E+06 + 5.76600E+02 6.87330E+06 + 5.76700E+02 6.70384E+06 + 5.76800E+02 6.47199E+06 + 5.76900E+02 6.18796E+06 + 5.77000E+02 5.86339E+06 + 5.77100E+02 5.51294E+06 + 5.77200E+02 5.15124E+06 + 5.77300E+02 4.79357E+06 + 5.77400E+02 4.45566E+06 + 5.77500E+02 4.15161E+06 + 5.77600E+02 3.89465E+06 + 5.77700E+02 3.69588E+06 + 5.77800E+02 3.56360E+06 + 5.77900E+02 3.50362E+06 + 5.78000E+02 3.51845E+06 + 5.78100E+02 3.60743E+06 + 5.78200E+02 3.76685E+06 + 5.78300E+02 3.98985E+06 + 5.78400E+02 4.26670E+06 + 5.78500E+02 4.58584E+06 + 5.78600E+02 4.93326E+06 + 5.78700E+02 5.29425E+06 + 5.78800E+02 5.65376E+06 + 5.78900E+02 5.99558E+06 + 5.79000E+02 6.30567E+06 + 5.79100E+02 6.57037E+06 + 5.79200E+02 6.77857E+06 + 5.79300E+02 6.92140E+06 + 5.79400E+02 6.99261E+06 + 5.79500E+02 6.98914E+06 + 5.79600E+02 6.91121E+06 + 5.79700E+02 6.76218E+06 + 5.79800E+02 6.54828E+06 + 5.79900E+02 6.27892E+06 + 5.80000E+02 5.96513E+06 + 5.80100E+02 5.62109E+06 + 5.80200E+02 5.26117E+06 + 5.80300E+02 4.90058E+06 + 5.80400E+02 4.55517E+06 + 5.80500E+02 4.23917E+06 + 5.80600E+02 3.96684E+06 + 5.80700E+02 3.74946E+06 + 5.80800E+02 3.59625E+06 + 5.80900E+02 3.51397E+06 + 5.81000E+02 3.50603E+06 + 5.81100E+02 3.57285E+06 + 5.81200E+02 3.71146E+06 + 5.81300E+02 3.91608E+06 + 5.81400E+02 4.17772E+06 + 5.81500E+02 4.48547E+06 + 5.81600E+02 4.82579E+06 + 5.81700E+02 5.18449E+06 + 5.81800E+02 5.54601E+06 + 5.81900E+02 5.89466E+06 + 5.82000E+02 6.21590E+06 + 5.82100E+02 6.49560E+06 + 5.82200E+02 6.72200E+06 + 5.82300E+02 6.88554E+06 + 5.82400E+02 6.97884E+06 + 5.82500E+02 6.99813E+06 + 5.82600E+02 6.94257E+06 + 5.82700E+02 6.81456E+06 + 5.82800E+02 6.61944E+06 + 5.82900E+02 6.36565E+06 + 5.83000E+02 6.06405E+06 + 5.83100E+02 5.72778E+06 + 5.83200E+02 5.37107E+06 + 5.83300E+02 5.00897E+06 + 5.83400E+02 4.65742E+06 + 5.83500E+02 4.33088E+06 + 5.83600E+02 4.04410E+06 + 5.83700E+02 3.80896E+06 + 5.83800E+02 3.63544E+06 + 5.83900E+02 3.53117E+06 + 5.84000E+02 3.50050E+06 + 5.84100E+02 3.54481E+06 + 5.84200E+02 3.66214E+06 + 5.84300E+02 3.84758E+06 + 5.84400E+02 4.09298E+06 + 5.84500E+02 4.38811E+06 + 5.84600E+02 4.72019E+06 + 5.84700E+02 5.07478E+06 + 5.84800E+02 5.43709E+06 + 5.84900E+02 5.79119E+06 + 5.85000E+02 6.12232E+06 + 5.85100E+02 6.41592E+06 + 5.85200E+02 6.65974E+06 + 5.85300E+02 6.84315E+06 + 5.85400E+02 6.95824E+06 + 5.85500E+02 7.00022E+06 + 5.85600E+02 6.96724E+06 + 5.85700E+02 6.86075E+06 + 5.85800E+02 6.68508E+06 + 5.85900E+02 6.44815E+06 + 5.86000E+02 6.15976E+06 + 5.86100E+02 5.83259E+06 + 5.86200E+02 5.48048E+06 + 5.86300E+02 5.11832E+06 + 5.86400E+02 4.76180E+06 + 5.86500E+02 4.42622E+06 + 5.86600E+02 4.12613E+06 + 5.86700E+02 3.87415E+06 + 5.86800E+02 3.68100E+06 + 5.86900E+02 3.55515E+06 + 5.87000E+02 3.50186E+06 + 5.87100E+02 3.52351E+06 + 5.87200E+02 3.61909E+06 + 5.87300E+02 3.78462E+06 + 5.87400E+02 4.01281E+06 + 5.87500E+02 4.29434E+06 + 5.87600E+02 4.61648E+06 + 5.87700E+02 4.96576E+06 + 5.87800E+02 5.32743E+06 + 5.87900E+02 5.68559E+06 + 5.88000E+02 6.02530E+06 + 5.88100E+02 6.33180E+06 + 5.88200E+02 6.59180E+06 + 5.88300E+02 6.79447E+06 + 5.88400E+02 6.93090E+06 + 5.88500E+02 6.99540E+06 + 5.88600E+02 6.98513E+06 + 5.88700E+02 6.90052E+06 + 5.88800E+02 6.74518E+06 + 5.88900E+02 6.52592E+06 + 5.89000E+02 6.25187E+06 + 5.89100E+02 5.93509E+06 + 5.89200E+02 5.58899E+06 + 5.89300E+02 5.22797E+06 + 5.89400E+02 4.86832E+06 + 5.89500E+02 4.52482E+06 + 5.89600E+02 4.21259E+06 + 5.89700E+02 3.94478E+06 + 5.89800E+02 3.73275E+06 + 5.89900E+02 3.58577E+06 + 5.90000E+02 3.51012E+06 + 5.90100E+02 3.50903E+06 + 5.90200E+02 3.58249E+06 + 5.90300E+02 3.72745E+06 + 5.90400E+02 3.93753E+06 + 5.90500E+02 4.20415E+06 + 5.90600E+02 4.51528E+06 + 5.90700E+02 4.85787E+06 + 5.90800E+02 5.21747E+06 + 5.90900E+02 5.57827E+06 + 5.91000E+02 5.92542E+06 + 5.91100E+02 6.24324E+06 + 5.91200E+02 6.51856E+06 + 5.91300E+02 6.73970E+06 + 5.91400E+02 6.89693E+06 + 5.91500E+02 6.98369E+06 + 5.91600E+02 6.99616E+06 + 5.91700E+02 6.93386E+06 + 5.91800E+02 6.79939E+06 + 5.91900E+02 6.59865E+06 + 5.92000E+02 6.34003E+06 + 5.92100E+02 6.03489E+06 + 5.92200E+02 5.69596E+06 + 5.92300E+02 5.33792E+06 + 5.92400E+02 4.97634E+06 + 5.92500E+02 4.62628E+06 + 5.92600E+02 4.30315E+06 + 5.92700E+02 4.02056E+06 + 5.92800E+02 3.79038E+06 + 5.92900E+02 3.62301E+06 + 5.93000E+02 3.52525E+06 + 5.93100E+02 3.50143E+06 + 5.93200E+02 3.55247E+06 + 5.93300E+02 3.67628E+06 + 5.93400E+02 3.86756E+06 + 5.93500E+02 4.11810E+06 + 5.93600E+02 4.41698E+06 + 5.93700E+02 4.75152E+06 + 5.93800E+02 5.10764E+06 + 5.93900E+02 5.46965E+06 + 5.94000E+02 5.82267E+06 + 5.94100E+02 6.15077E+06 + 5.94200E+02 6.44032E+06 + 5.94300E+02 6.67904E+06 + 5.94400E+02 6.85645E+06 + 5.94500E+02 6.96518E+06 + 5.94600E+02 7.00032E+06 + 5.94700E+02 6.96055E+06 + 5.94800E+02 6.84747E+06 + 5.94900E+02 6.66606E+06 + 5.95000E+02 6.42389E+06 + 5.95100E+02 6.13141E+06 + 5.95200E+02 5.80137E+06 + 5.95300E+02 5.44753E+06 + 5.95400E+02 5.08544E+06 + 5.95500E+02 4.73021E+06 + 5.95600E+02 4.39745E+06 + 5.95700E+02 4.10104E+06 + 5.95800E+02 3.85389E+06 + 5.95900E+02 3.66667E+06 + 5.96000E+02 3.54720E+06 + 5.96100E+02 3.50073E+06 + 5.96200E+02 3.52915E+06 + 5.96300E+02 3.63142E+06 + 5.96400E+02 3.80291E+06 + 5.96500E+02 4.03652E+06 + 5.96600E+02 4.32196E+06 + 5.96700E+02 4.64715E+06 + 5.96800E+02 4.99836E+06 + 5.96900E+02 5.36038E+06 + 5.97000E+02 5.71767E+06 + 5.97100E+02 6.05474E+06 + 5.97200E+02 6.35738E+06 + 5.97300E+02 6.61275E+06 + 5.97400E+02 6.80963E+06 + 5.97500E+02 6.93986E+06 + 5.97600E+02 6.99757E+06 + 5.97700E+02 6.98048E+06 + 5.97800E+02 6.88925E+06 + 5.97900E+02 6.72788E+06 + 5.98000E+02 6.50296E+06 + 5.98100E+02 6.22464E+06 + 5.98200E+02 5.90461E+06 + 5.98300E+02 5.55636E+06 + 5.98400E+02 5.19520E+06 + 5.98500E+02 4.83619E+06 + 5.98600E+02 4.49493E+06 + 5.98700E+02 4.18621E+06 + 5.98800E+02 3.92290E+06 + 5.98900E+02 3.71659E+06 + 5.99000E+02 3.57587E+06 + 5.99100E+02 3.50694E+06 + 5.99200E+02 3.51266E+06 + 5.99300E+02 3.59285E+06 + 5.99400E+02 3.74397E+06 + 5.99500E+02 3.95973E+06 + 5.99600E+02 4.23061E+06 + 5.99700E+02 4.54515E+06 + 5.99800E+02 4.89030E+06 + 5.99900E+02 5.25046E+06 + 6.00000E+02 5.61082E+06 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.inp b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.inp new file mode 100644 index 000000000..defe0cd42 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.inp @@ -0,0 +1,34 @@ +! Ice lock-in crushing per IEC test case for IceFloe +! +! Model selection and general inputs +! +timeStep 0.1 +rampTime 1.0 +duration 600.0 +randomSeed 123 +! +! General ice property inputs +! +iceThickness 1.0 +iceVelocity 0.2 +iceDirection 0.0 +refIceStrength 2200000.0 +flexStrength 700000.0 +iceModulus 8000000000.0 +iceDensity 916.2 +waterDensity 999.8 +! +! Tower configuration inputs +! +numLegs 1.0 +towerDiameter 5.0 +towerFrequency 0.33 +towerConeAngle 60.0 +rubbleHeight 3.0 +twrConeTopDiam 1.5 +! +! Inputs for lock-in crushing +! +iceType 4 +shapeFactor_k1 0.9 +contactFactor_k2 0.5 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.log b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.log new file mode 100644 index 000000000..f0279e358 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_IEC.log @@ -0,0 +1,25 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:26:30 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 4 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting parameters for crushing on vertical surfaces by IEC/Korzhavin method + Reference ice strength = 2.20000E+06 Pascals + Static load shape factor = 0.9 + Static load contact factor = 0.5 + Tower fundamental frequency = 0.33 Hz +** Global crushing load is: 7.00036E+06 Newtons. + + Ice crushing loads IEC/Korzhavin initialized + diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.dat b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.dat new file mode 100644 index 000000000..ed7662298 --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 5.24334E+05 + 2.00000E-01 1.07701E+06 + 3.00000E-01 1.65803E+06 + 4.00000E-01 2.26739E+06 + 5.00000E-01 2.90509E+06 + 6.00000E-01 3.57114E+06 + 7.00000E-01 4.26553E+06 + 8.00000E-01 4.98826E+06 + 9.00000E-01 5.73933E+06 + 1.00000E+00 6.51875E+06 + 1.10000E+00 6.66046E+06 + 1.20000E+00 6.80217E+06 + 1.30000E+00 6.94388E+06 + 1.40000E+00 7.08559E+06 + 1.50000E+00 7.22730E+06 + 1.60000E+00 7.36902E+06 + 1.70000E+00 7.51073E+06 + 1.80000E+00 7.65244E+06 + 1.90000E+00 7.79415E+06 + 2.00000E+00 7.93586E+06 + 2.10000E+00 8.07758E+06 + 2.20000E+00 8.21929E+06 + 2.30000E+00 8.36100E+06 + 2.40000E+00 8.50271E+06 + 2.50000E+00 8.50271E+06 + 2.60000E+00 7.93586E+06 + 2.70000E+00 7.36902E+06 + 2.80000E+00 6.80217E+06 + 2.90000E+00 6.23532E+06 + 3.00000E+00 5.66848E+06 + 3.10000E+00 5.24334E+06 + 3.20000E+00 5.38505E+06 + 3.30000E+00 5.52676E+06 + 3.40000E+00 5.66848E+06 + 3.50000E+00 5.81019E+06 + 3.60000E+00 5.95190E+06 + 3.70000E+00 6.09361E+06 + 3.80000E+00 6.23532E+06 + 3.90000E+00 6.37703E+06 + 4.00000E+00 6.51875E+06 + 4.10000E+00 6.66046E+06 + 4.20000E+00 6.80217E+06 + 4.30000E+00 6.94388E+06 + 4.40000E+00 7.08559E+06 + 4.50000E+00 7.22730E+06 + 4.60000E+00 7.36902E+06 + 4.70000E+00 7.51073E+06 + 4.80000E+00 7.65244E+06 + 4.90000E+00 7.79415E+06 + 5.00000E+00 7.93586E+06 + 5.10000E+00 8.07758E+06 + 5.20000E+00 8.21929E+06 + 5.30000E+00 8.36100E+06 + 5.40000E+00 8.50271E+06 + 5.50000E+00 8.50271E+06 + 5.60000E+00 7.93586E+06 + 5.70000E+00 7.36902E+06 + 5.80000E+00 6.80217E+06 + 5.90000E+00 6.23532E+06 + 6.00000E+00 5.66848E+06 + 6.10000E+00 5.24334E+06 + 6.20000E+00 5.38505E+06 + 6.30000E+00 5.52676E+06 + 6.40000E+00 5.66848E+06 + 6.50000E+00 5.81019E+06 + 6.60000E+00 5.95190E+06 + 6.70000E+00 6.09361E+06 + 6.80000E+00 6.23532E+06 + 6.90000E+00 6.37703E+06 + 7.00000E+00 6.51875E+06 + 7.10000E+00 6.66046E+06 + 7.20000E+00 6.80217E+06 + 7.30000E+00 6.94388E+06 + 7.40000E+00 7.08559E+06 + 7.50000E+00 7.22730E+06 + 7.60000E+00 7.36902E+06 + 7.70000E+00 7.51073E+06 + 7.80000E+00 7.65244E+06 + 7.90000E+00 7.79415E+06 + 8.00000E+00 7.93586E+06 + 8.10000E+00 8.07758E+06 + 8.20000E+00 8.21929E+06 + 8.30000E+00 8.36100E+06 + 8.40000E+00 8.50271E+06 + 8.50000E+00 8.50271E+06 + 8.60000E+00 7.93586E+06 + 8.70000E+00 7.36902E+06 + 8.80000E+00 6.80217E+06 + 8.90000E+00 6.23532E+06 + 9.00000E+00 5.66848E+06 + 9.10000E+00 5.24334E+06 + 9.20000E+00 5.38505E+06 + 9.30000E+00 5.52676E+06 + 9.40000E+00 5.66848E+06 + 9.50000E+00 5.81019E+06 + 9.60000E+00 5.95190E+06 + 9.70000E+00 6.09361E+06 + 9.80000E+00 6.23532E+06 + 9.90000E+00 6.37703E+06 + 1.00000E+01 6.51875E+06 + 1.01000E+01 6.66046E+06 + 1.02000E+01 6.80217E+06 + 1.03000E+01 6.94388E+06 + 1.04000E+01 7.08559E+06 + 1.05000E+01 7.22730E+06 + 1.06000E+01 7.36902E+06 + 1.07000E+01 7.51073E+06 + 1.08000E+01 7.65244E+06 + 1.09000E+01 7.79415E+06 + 1.10000E+01 7.93586E+06 + 1.11000E+01 8.07758E+06 + 1.12000E+01 8.21929E+06 + 1.13000E+01 8.36100E+06 + 1.14000E+01 8.50271E+06 + 1.15000E+01 8.50271E+06 + 1.16000E+01 7.93586E+06 + 1.17000E+01 7.36902E+06 + 1.18000E+01 6.80217E+06 + 1.19000E+01 6.23532E+06 + 1.20000E+01 5.66848E+06 + 1.21000E+01 5.24334E+06 + 1.22000E+01 5.38505E+06 + 1.23000E+01 5.52676E+06 + 1.24000E+01 5.66848E+06 + 1.25000E+01 5.81019E+06 + 1.26000E+01 5.95190E+06 + 1.27000E+01 6.09361E+06 + 1.28000E+01 6.23532E+06 + 1.29000E+01 6.37703E+06 + 1.30000E+01 6.51875E+06 + 1.31000E+01 6.66046E+06 + 1.32000E+01 6.80217E+06 + 1.33000E+01 6.94388E+06 + 1.34000E+01 7.08559E+06 + 1.35000E+01 7.22730E+06 + 1.36000E+01 7.36902E+06 + 1.37000E+01 7.51073E+06 + 1.38000E+01 7.65244E+06 + 1.39000E+01 7.79415E+06 + 1.40000E+01 7.93586E+06 + 1.41000E+01 8.07758E+06 + 1.42000E+01 8.21929E+06 + 1.43000E+01 8.36100E+06 + 1.44000E+01 8.50271E+06 + 1.45000E+01 8.50271E+06 + 1.46000E+01 7.93586E+06 + 1.47000E+01 7.36902E+06 + 1.48000E+01 6.80217E+06 + 1.49000E+01 6.23532E+06 + 1.50000E+01 5.66848E+06 + 1.51000E+01 5.24334E+06 + 1.52000E+01 5.38505E+06 + 1.53000E+01 5.52676E+06 + 1.54000E+01 5.66848E+06 + 1.55000E+01 5.81019E+06 + 1.56000E+01 5.95190E+06 + 1.57000E+01 6.09361E+06 + 1.58000E+01 6.23532E+06 + 1.59000E+01 6.37703E+06 + 1.60000E+01 6.51875E+06 + 1.61000E+01 6.66046E+06 + 1.62000E+01 6.80217E+06 + 1.63000E+01 6.94388E+06 + 1.64000E+01 7.08559E+06 + 1.65000E+01 7.22730E+06 + 1.66000E+01 7.36902E+06 + 1.67000E+01 7.51073E+06 + 1.68000E+01 7.65244E+06 + 1.69000E+01 7.79415E+06 + 1.70000E+01 7.93586E+06 + 1.71000E+01 8.07758E+06 + 1.72000E+01 8.21929E+06 + 1.73000E+01 8.36100E+06 + 1.74000E+01 8.50271E+06 + 1.75000E+01 8.50271E+06 + 1.76000E+01 7.93586E+06 + 1.77000E+01 7.36902E+06 + 1.78000E+01 6.80217E+06 + 1.79000E+01 6.23532E+06 + 1.80000E+01 5.66848E+06 + 1.81000E+01 5.24334E+06 + 1.82000E+01 5.38505E+06 + 1.83000E+01 5.52676E+06 + 1.84000E+01 5.66848E+06 + 1.85000E+01 5.81019E+06 + 1.86000E+01 5.95190E+06 + 1.87000E+01 6.09361E+06 + 1.88000E+01 6.23532E+06 + 1.89000E+01 6.37703E+06 + 1.90000E+01 6.51875E+06 + 1.91000E+01 6.66046E+06 + 1.92000E+01 6.80217E+06 + 1.93000E+01 6.94388E+06 + 1.94000E+01 7.08559E+06 + 1.95000E+01 7.22730E+06 + 1.96000E+01 7.36902E+06 + 1.97000E+01 7.51073E+06 + 1.98000E+01 7.65244E+06 + 1.99000E+01 7.79415E+06 + 2.00000E+01 7.93586E+06 + 2.01000E+01 8.07758E+06 + 2.02000E+01 8.21929E+06 + 2.03000E+01 8.36100E+06 + 2.04000E+01 8.50271E+06 + 2.05000E+01 8.50271E+06 + 2.06000E+01 7.93586E+06 + 2.07000E+01 7.36902E+06 + 2.08000E+01 6.80217E+06 + 2.09000E+01 6.23532E+06 + 2.10000E+01 5.66848E+06 + 2.11000E+01 5.24334E+06 + 2.12000E+01 5.38505E+06 + 2.13000E+01 5.52676E+06 + 2.14000E+01 5.66848E+06 + 2.15000E+01 5.81019E+06 + 2.16000E+01 5.95190E+06 + 2.17000E+01 6.09361E+06 + 2.18000E+01 6.23532E+06 + 2.19000E+01 6.37703E+06 + 2.20000E+01 6.51875E+06 + 2.21000E+01 6.66046E+06 + 2.22000E+01 6.80217E+06 + 2.23000E+01 6.94388E+06 + 2.24000E+01 7.08559E+06 + 2.25000E+01 7.22730E+06 + 2.26000E+01 7.36902E+06 + 2.27000E+01 7.51073E+06 + 2.28000E+01 7.65244E+06 + 2.29000E+01 7.79415E+06 + 2.30000E+01 7.93586E+06 + 2.31000E+01 8.07758E+06 + 2.32000E+01 8.21929E+06 + 2.33000E+01 8.36100E+06 + 2.34000E+01 8.50271E+06 + 2.35000E+01 8.50271E+06 + 2.36000E+01 7.93586E+06 + 2.37000E+01 7.36902E+06 + 2.38000E+01 6.80217E+06 + 2.39000E+01 6.23532E+06 + 2.40000E+01 5.66848E+06 + 2.41000E+01 5.24334E+06 + 2.42000E+01 5.38505E+06 + 2.43000E+01 5.52676E+06 + 2.44000E+01 5.66848E+06 + 2.45000E+01 5.81019E+06 + 2.46000E+01 5.95190E+06 + 2.47000E+01 6.09361E+06 + 2.48000E+01 6.23532E+06 + 2.49000E+01 6.37703E+06 + 2.50000E+01 6.51875E+06 + 2.51000E+01 6.66046E+06 + 2.52000E+01 6.80217E+06 + 2.53000E+01 6.94388E+06 + 2.54000E+01 7.08559E+06 + 2.55000E+01 7.22730E+06 + 2.56000E+01 7.36902E+06 + 2.57000E+01 7.51073E+06 + 2.58000E+01 7.65244E+06 + 2.59000E+01 7.79415E+06 + 2.60000E+01 7.93586E+06 + 2.61000E+01 8.07758E+06 + 2.62000E+01 8.21929E+06 + 2.63000E+01 8.36100E+06 + 2.64000E+01 8.50271E+06 + 2.65000E+01 8.50271E+06 + 2.66000E+01 7.93586E+06 + 2.67000E+01 7.36902E+06 + 2.68000E+01 6.80217E+06 + 2.69000E+01 6.23532E+06 + 2.70000E+01 5.66848E+06 + 2.71000E+01 5.24334E+06 + 2.72000E+01 5.38505E+06 + 2.73000E+01 5.52676E+06 + 2.74000E+01 5.66848E+06 + 2.75000E+01 5.81019E+06 + 2.76000E+01 5.95190E+06 + 2.77000E+01 6.09361E+06 + 2.78000E+01 6.23532E+06 + 2.79000E+01 6.37703E+06 + 2.80000E+01 6.51875E+06 + 2.81000E+01 6.66046E+06 + 2.82000E+01 6.80217E+06 + 2.83000E+01 6.94388E+06 + 2.84000E+01 7.08559E+06 + 2.85000E+01 7.22730E+06 + 2.86000E+01 7.36902E+06 + 2.87000E+01 7.51073E+06 + 2.88000E+01 7.65244E+06 + 2.89000E+01 7.79415E+06 + 2.90000E+01 7.93586E+06 + 2.91000E+01 8.07758E+06 + 2.92000E+01 8.21929E+06 + 2.93000E+01 8.36100E+06 + 2.94000E+01 8.50271E+06 + 2.95000E+01 8.50271E+06 + 2.96000E+01 7.93586E+06 + 2.97000E+01 7.36902E+06 + 2.98000E+01 6.80217E+06 + 2.99000E+01 6.23532E+06 + 3.00000E+01 5.66848E+06 + 3.01000E+01 5.24334E+06 + 3.02000E+01 5.38505E+06 + 3.03000E+01 5.52676E+06 + 3.04000E+01 5.66848E+06 + 3.05000E+01 5.81019E+06 + 3.06000E+01 5.95190E+06 + 3.07000E+01 6.09361E+06 + 3.08000E+01 6.23532E+06 + 3.09000E+01 6.37703E+06 + 3.10000E+01 6.51875E+06 + 3.11000E+01 6.66046E+06 + 3.12000E+01 6.80217E+06 + 3.13000E+01 6.94388E+06 + 3.14000E+01 7.08559E+06 + 3.15000E+01 7.22730E+06 + 3.16000E+01 7.36902E+06 + 3.17000E+01 7.51073E+06 + 3.18000E+01 7.65244E+06 + 3.19000E+01 7.79415E+06 + 3.20000E+01 7.93586E+06 + 3.21000E+01 8.07758E+06 + 3.22000E+01 8.21929E+06 + 3.23000E+01 8.36100E+06 + 3.24000E+01 8.50271E+06 + 3.25000E+01 8.50271E+06 + 3.26000E+01 7.93586E+06 + 3.27000E+01 7.36902E+06 + 3.28000E+01 6.80217E+06 + 3.29000E+01 6.23532E+06 + 3.30000E+01 5.66848E+06 + 3.31000E+01 5.24334E+06 + 3.32000E+01 5.38505E+06 + 3.33000E+01 5.52676E+06 + 3.34000E+01 5.66848E+06 + 3.35000E+01 5.81019E+06 + 3.36000E+01 5.95190E+06 + 3.37000E+01 6.09361E+06 + 3.38000E+01 6.23532E+06 + 3.39000E+01 6.37703E+06 + 3.40000E+01 6.51875E+06 + 3.41000E+01 6.66046E+06 + 3.42000E+01 6.80217E+06 + 3.43000E+01 6.94388E+06 + 3.44000E+01 7.08559E+06 + 3.45000E+01 7.22730E+06 + 3.46000E+01 7.36902E+06 + 3.47000E+01 7.51073E+06 + 3.48000E+01 7.65244E+06 + 3.49000E+01 7.79415E+06 + 3.50000E+01 7.93586E+06 + 3.51000E+01 8.07758E+06 + 3.52000E+01 8.21929E+06 + 3.53000E+01 8.36100E+06 + 3.54000E+01 8.50271E+06 + 3.55000E+01 8.50271E+06 + 3.56000E+01 7.93586E+06 + 3.57000E+01 7.36902E+06 + 3.58000E+01 6.80217E+06 + 3.59000E+01 6.23532E+06 + 3.60000E+01 5.66848E+06 + 3.61000E+01 5.24334E+06 + 3.62000E+01 5.38505E+06 + 3.63000E+01 5.52676E+06 + 3.64000E+01 5.66848E+06 + 3.65000E+01 5.81019E+06 + 3.66000E+01 5.95190E+06 + 3.67000E+01 6.09361E+06 + 3.68000E+01 6.23532E+06 + 3.69000E+01 6.37703E+06 + 3.70000E+01 6.51875E+06 + 3.71000E+01 6.66046E+06 + 3.72000E+01 6.80217E+06 + 3.73000E+01 6.94388E+06 + 3.74000E+01 7.08559E+06 + 3.75000E+01 7.22730E+06 + 3.76000E+01 7.36902E+06 + 3.77000E+01 7.51073E+06 + 3.78000E+01 7.65244E+06 + 3.79000E+01 7.79415E+06 + 3.80000E+01 7.93586E+06 + 3.81000E+01 8.07758E+06 + 3.82000E+01 8.21929E+06 + 3.83000E+01 8.36100E+06 + 3.84000E+01 8.50271E+06 + 3.85000E+01 8.50271E+06 + 3.86000E+01 7.93586E+06 + 3.87000E+01 7.36902E+06 + 3.88000E+01 6.80217E+06 + 3.89000E+01 6.23532E+06 + 3.90000E+01 5.66848E+06 + 3.91000E+01 5.24334E+06 + 3.92000E+01 5.38505E+06 + 3.93000E+01 5.52676E+06 + 3.94000E+01 5.66848E+06 + 3.95000E+01 5.81019E+06 + 3.96000E+01 5.95190E+06 + 3.97000E+01 6.09361E+06 + 3.98000E+01 6.23532E+06 + 3.99000E+01 6.37703E+06 + 4.00000E+01 6.51875E+06 + 4.01000E+01 6.66046E+06 + 4.02000E+01 6.80217E+06 + 4.03000E+01 6.94388E+06 + 4.04000E+01 7.08559E+06 + 4.05000E+01 7.22730E+06 + 4.06000E+01 7.36902E+06 + 4.07000E+01 7.51073E+06 + 4.08000E+01 7.65244E+06 + 4.09000E+01 7.79415E+06 + 4.10000E+01 7.93586E+06 + 4.11000E+01 8.07758E+06 + 4.12000E+01 8.21929E+06 + 4.13000E+01 8.36100E+06 + 4.14000E+01 8.50271E+06 + 4.15000E+01 8.50271E+06 + 4.16000E+01 7.93586E+06 + 4.17000E+01 7.36902E+06 + 4.18000E+01 6.80217E+06 + 4.19000E+01 6.23532E+06 + 4.20000E+01 5.66848E+06 + 4.21000E+01 5.24334E+06 + 4.22000E+01 5.38505E+06 + 4.23000E+01 5.52676E+06 + 4.24000E+01 5.66848E+06 + 4.25000E+01 5.81019E+06 + 4.26000E+01 5.95190E+06 + 4.27000E+01 6.09361E+06 + 4.28000E+01 6.23532E+06 + 4.29000E+01 6.37703E+06 + 4.30000E+01 6.51875E+06 + 4.31000E+01 6.66046E+06 + 4.32000E+01 6.80217E+06 + 4.33000E+01 6.94388E+06 + 4.34000E+01 7.08559E+06 + 4.35000E+01 7.22730E+06 + 4.36000E+01 7.36902E+06 + 4.37000E+01 7.51073E+06 + 4.38000E+01 7.65244E+06 + 4.39000E+01 7.79415E+06 + 4.40000E+01 7.93586E+06 + 4.41000E+01 8.07758E+06 + 4.42000E+01 8.21929E+06 + 4.43000E+01 8.36100E+06 + 4.44000E+01 8.50271E+06 + 4.45000E+01 8.50271E+06 + 4.46000E+01 7.93586E+06 + 4.47000E+01 7.36902E+06 + 4.48000E+01 6.80217E+06 + 4.49000E+01 6.23532E+06 + 4.50000E+01 5.66848E+06 + 4.51000E+01 5.24334E+06 + 4.52000E+01 5.38505E+06 + 4.53000E+01 5.52676E+06 + 4.54000E+01 5.66848E+06 + 4.55000E+01 5.81019E+06 + 4.56000E+01 5.95190E+06 + 4.57000E+01 6.09361E+06 + 4.58000E+01 6.23532E+06 + 4.59000E+01 6.37703E+06 + 4.60000E+01 6.51875E+06 + 4.61000E+01 6.66046E+06 + 4.62000E+01 6.80217E+06 + 4.63000E+01 6.94388E+06 + 4.64000E+01 7.08559E+06 + 4.65000E+01 7.22730E+06 + 4.66000E+01 7.36902E+06 + 4.67000E+01 7.51073E+06 + 4.68000E+01 7.65244E+06 + 4.69000E+01 7.79415E+06 + 4.70000E+01 7.93586E+06 + 4.71000E+01 8.07758E+06 + 4.72000E+01 8.21929E+06 + 4.73000E+01 8.36100E+06 + 4.74000E+01 8.50271E+06 + 4.75000E+01 8.50271E+06 + 4.76000E+01 7.93586E+06 + 4.77000E+01 7.36902E+06 + 4.78000E+01 6.80217E+06 + 4.79000E+01 6.23532E+06 + 4.80000E+01 5.66848E+06 + 4.81000E+01 5.24334E+06 + 4.82000E+01 5.38505E+06 + 4.83000E+01 5.52676E+06 + 4.84000E+01 5.66848E+06 + 4.85000E+01 5.81019E+06 + 4.86000E+01 5.95190E+06 + 4.87000E+01 6.09361E+06 + 4.88000E+01 6.23532E+06 + 4.89000E+01 6.37703E+06 + 4.90000E+01 6.51875E+06 + 4.91000E+01 6.66046E+06 + 4.92000E+01 6.80217E+06 + 4.93000E+01 6.94388E+06 + 4.94000E+01 7.08559E+06 + 4.95000E+01 7.22730E+06 + 4.96000E+01 7.36902E+06 + 4.97000E+01 7.51073E+06 + 4.98000E+01 7.65244E+06 + 4.99000E+01 7.79415E+06 + 5.00000E+01 7.93586E+06 + 5.01000E+01 8.07758E+06 + 5.02000E+01 8.21929E+06 + 5.03000E+01 8.36100E+06 + 5.04000E+01 8.50271E+06 + 5.05000E+01 8.50271E+06 + 5.06000E+01 7.93586E+06 + 5.07000E+01 7.36902E+06 + 5.08000E+01 6.80217E+06 + 5.09000E+01 6.23532E+06 + 5.10000E+01 5.66848E+06 + 5.11000E+01 5.24334E+06 + 5.12000E+01 5.38505E+06 + 5.13000E+01 5.52676E+06 + 5.14000E+01 5.66848E+06 + 5.15000E+01 5.81019E+06 + 5.16000E+01 5.95190E+06 + 5.17000E+01 6.09361E+06 + 5.18000E+01 6.23532E+06 + 5.19000E+01 6.37703E+06 + 5.20000E+01 6.51875E+06 + 5.21000E+01 6.66046E+06 + 5.22000E+01 6.80217E+06 + 5.23000E+01 6.94388E+06 + 5.24000E+01 7.08559E+06 + 5.25000E+01 7.22730E+06 + 5.26000E+01 7.36902E+06 + 5.27000E+01 7.51073E+06 + 5.28000E+01 7.65244E+06 + 5.29000E+01 7.79415E+06 + 5.30000E+01 7.93586E+06 + 5.31000E+01 8.07758E+06 + 5.32000E+01 8.21929E+06 + 5.33000E+01 8.36100E+06 + 5.34000E+01 8.50271E+06 + 5.35000E+01 8.50271E+06 + 5.36000E+01 7.93586E+06 + 5.37000E+01 7.36902E+06 + 5.38000E+01 6.80217E+06 + 5.39000E+01 6.23532E+06 + 5.40000E+01 5.66848E+06 + 5.41000E+01 5.24334E+06 + 5.42000E+01 5.38505E+06 + 5.43000E+01 5.52676E+06 + 5.44000E+01 5.66848E+06 + 5.45000E+01 5.81019E+06 + 5.46000E+01 5.95190E+06 + 5.47000E+01 6.09361E+06 + 5.48000E+01 6.23532E+06 + 5.49000E+01 6.37703E+06 + 5.50000E+01 6.51875E+06 + 5.51000E+01 6.66046E+06 + 5.52000E+01 6.80217E+06 + 5.53000E+01 6.94388E+06 + 5.54000E+01 7.08559E+06 + 5.55000E+01 7.22730E+06 + 5.56000E+01 7.36902E+06 + 5.57000E+01 7.51073E+06 + 5.58000E+01 7.65244E+06 + 5.59000E+01 7.79415E+06 + 5.60000E+01 7.93586E+06 + 5.61000E+01 8.07758E+06 + 5.62000E+01 8.21929E+06 + 5.63000E+01 8.36100E+06 + 5.64000E+01 8.50271E+06 + 5.65000E+01 8.50271E+06 + 5.66000E+01 7.93586E+06 + 5.67000E+01 7.36902E+06 + 5.68000E+01 6.80217E+06 + 5.69000E+01 6.23532E+06 + 5.70000E+01 5.66848E+06 + 5.71000E+01 5.24334E+06 + 5.72000E+01 5.38505E+06 + 5.73000E+01 5.52676E+06 + 5.74000E+01 5.66848E+06 + 5.75000E+01 5.81019E+06 + 5.76000E+01 5.95190E+06 + 5.77000E+01 6.09361E+06 + 5.78000E+01 6.23532E+06 + 5.79000E+01 6.37703E+06 + 5.80000E+01 6.51875E+06 + 5.81000E+01 6.66046E+06 + 5.82000E+01 6.80217E+06 + 5.83000E+01 6.94388E+06 + 5.84000E+01 7.08559E+06 + 5.85000E+01 7.22730E+06 + 5.86000E+01 7.36902E+06 + 5.87000E+01 7.51073E+06 + 5.88000E+01 7.65244E+06 + 5.89000E+01 7.79415E+06 + 5.90000E+01 7.93586E+06 + 5.91000E+01 8.07758E+06 + 5.92000E+01 8.21929E+06 + 5.93000E+01 8.36100E+06 + 5.94000E+01 8.50271E+06 + 5.95000E+01 8.50271E+06 + 5.96000E+01 7.93586E+06 + 5.97000E+01 7.36902E+06 + 5.98000E+01 6.80217E+06 + 5.99000E+01 6.23532E+06 + 6.00000E+01 5.66848E+06 + 6.01000E+01 5.24334E+06 + 6.02000E+01 5.38505E+06 + 6.03000E+01 5.52676E+06 + 6.04000E+01 5.66848E+06 + 6.05000E+01 5.81019E+06 + 6.06000E+01 5.95190E+06 + 6.07000E+01 6.09361E+06 + 6.08000E+01 6.23532E+06 + 6.09000E+01 6.37703E+06 + 6.10000E+01 6.51875E+06 + 6.11000E+01 6.66046E+06 + 6.12000E+01 6.80217E+06 + 6.13000E+01 6.94388E+06 + 6.14000E+01 7.08559E+06 + 6.15000E+01 7.22730E+06 + 6.16000E+01 7.36902E+06 + 6.17000E+01 7.51073E+06 + 6.18000E+01 7.65244E+06 + 6.19000E+01 7.79415E+06 + 6.20000E+01 7.93586E+06 + 6.21000E+01 8.07758E+06 + 6.22000E+01 8.21929E+06 + 6.23000E+01 8.36100E+06 + 6.24000E+01 8.50271E+06 + 6.25000E+01 8.50271E+06 + 6.26000E+01 7.93586E+06 + 6.27000E+01 7.36902E+06 + 6.28000E+01 6.80217E+06 + 6.29000E+01 6.23532E+06 + 6.30000E+01 5.66848E+06 + 6.31000E+01 5.24334E+06 + 6.32000E+01 5.38505E+06 + 6.33000E+01 5.52676E+06 + 6.34000E+01 5.66848E+06 + 6.35000E+01 5.81019E+06 + 6.36000E+01 5.95190E+06 + 6.37000E+01 6.09361E+06 + 6.38000E+01 6.23532E+06 + 6.39000E+01 6.37703E+06 + 6.40000E+01 6.51875E+06 + 6.41000E+01 6.66046E+06 + 6.42000E+01 6.80217E+06 + 6.43000E+01 6.94388E+06 + 6.44000E+01 7.08559E+06 + 6.45000E+01 7.22730E+06 + 6.46000E+01 7.36902E+06 + 6.47000E+01 7.51073E+06 + 6.48000E+01 7.65244E+06 + 6.49000E+01 7.79415E+06 + 6.50000E+01 7.93586E+06 + 6.51000E+01 8.07758E+06 + 6.52000E+01 8.21929E+06 + 6.53000E+01 8.36100E+06 + 6.54000E+01 8.50271E+06 + 6.55000E+01 8.50271E+06 + 6.56000E+01 7.93586E+06 + 6.57000E+01 7.36902E+06 + 6.58000E+01 6.80217E+06 + 6.59000E+01 6.23532E+06 + 6.60000E+01 5.66848E+06 + 6.61000E+01 5.24334E+06 + 6.62000E+01 5.38505E+06 + 6.63000E+01 5.52676E+06 + 6.64000E+01 5.66848E+06 + 6.65000E+01 5.81019E+06 + 6.66000E+01 5.95190E+06 + 6.67000E+01 6.09361E+06 + 6.68000E+01 6.23532E+06 + 6.69000E+01 6.37703E+06 + 6.70000E+01 6.51875E+06 + 6.71000E+01 6.66046E+06 + 6.72000E+01 6.80217E+06 + 6.73000E+01 6.94388E+06 + 6.74000E+01 7.08559E+06 + 6.75000E+01 7.22730E+06 + 6.76000E+01 7.36902E+06 + 6.77000E+01 7.51073E+06 + 6.78000E+01 7.65244E+06 + 6.79000E+01 7.79415E+06 + 6.80000E+01 7.93586E+06 + 6.81000E+01 8.07758E+06 + 6.82000E+01 8.21929E+06 + 6.83000E+01 8.36100E+06 + 6.84000E+01 8.50271E+06 + 6.85000E+01 8.50271E+06 + 6.86000E+01 7.93586E+06 + 6.87000E+01 7.36902E+06 + 6.88000E+01 6.80217E+06 + 6.89000E+01 6.23532E+06 + 6.90000E+01 5.66848E+06 + 6.91000E+01 5.24334E+06 + 6.92000E+01 5.38505E+06 + 6.93000E+01 5.52676E+06 + 6.94000E+01 5.66848E+06 + 6.95000E+01 5.81019E+06 + 6.96000E+01 5.95190E+06 + 6.97000E+01 6.09361E+06 + 6.98000E+01 6.23532E+06 + 6.99000E+01 6.37703E+06 + 7.00000E+01 6.51875E+06 + 7.01000E+01 6.66046E+06 + 7.02000E+01 6.80217E+06 + 7.03000E+01 6.94388E+06 + 7.04000E+01 7.08559E+06 + 7.05000E+01 7.22730E+06 + 7.06000E+01 7.36902E+06 + 7.07000E+01 7.51073E+06 + 7.08000E+01 7.65244E+06 + 7.09000E+01 7.79415E+06 + 7.10000E+01 7.93586E+06 + 7.11000E+01 8.07758E+06 + 7.12000E+01 8.21929E+06 + 7.13000E+01 8.36100E+06 + 7.14000E+01 8.50271E+06 + 7.15000E+01 8.50271E+06 + 7.16000E+01 7.93586E+06 + 7.17000E+01 7.36902E+06 + 7.18000E+01 6.80217E+06 + 7.19000E+01 6.23532E+06 + 7.20000E+01 5.66848E+06 + 7.21000E+01 5.24334E+06 + 7.22000E+01 5.38505E+06 + 7.23000E+01 5.52676E+06 + 7.24000E+01 5.66848E+06 + 7.25000E+01 5.81019E+06 + 7.26000E+01 5.95190E+06 + 7.27000E+01 6.09361E+06 + 7.28000E+01 6.23532E+06 + 7.29000E+01 6.37703E+06 + 7.30000E+01 6.51875E+06 + 7.31000E+01 6.66046E+06 + 7.32000E+01 6.80217E+06 + 7.33000E+01 6.94388E+06 + 7.34000E+01 7.08559E+06 + 7.35000E+01 7.22730E+06 + 7.36000E+01 7.36902E+06 + 7.37000E+01 7.51073E+06 + 7.38000E+01 7.65244E+06 + 7.39000E+01 7.79415E+06 + 7.40000E+01 7.93586E+06 + 7.41000E+01 8.07758E+06 + 7.42000E+01 8.21929E+06 + 7.43000E+01 8.36100E+06 + 7.44000E+01 8.50271E+06 + 7.45000E+01 8.50271E+06 + 7.46000E+01 7.93586E+06 + 7.47000E+01 7.36902E+06 + 7.48000E+01 6.80217E+06 + 7.49000E+01 6.23532E+06 + 7.50000E+01 5.66848E+06 + 7.51000E+01 5.24334E+06 + 7.52000E+01 5.38505E+06 + 7.53000E+01 5.52676E+06 + 7.54000E+01 5.66848E+06 + 7.55000E+01 5.81019E+06 + 7.56000E+01 5.95190E+06 + 7.57000E+01 6.09361E+06 + 7.58000E+01 6.23532E+06 + 7.59000E+01 6.37703E+06 + 7.60000E+01 6.51875E+06 + 7.61000E+01 6.66046E+06 + 7.62000E+01 6.80217E+06 + 7.63000E+01 6.94388E+06 + 7.64000E+01 7.08559E+06 + 7.65000E+01 7.22730E+06 + 7.66000E+01 7.36902E+06 + 7.67000E+01 7.51073E+06 + 7.68000E+01 7.65244E+06 + 7.69000E+01 7.79415E+06 + 7.70000E+01 7.93586E+06 + 7.71000E+01 8.07758E+06 + 7.72000E+01 8.21929E+06 + 7.73000E+01 8.36100E+06 + 7.74000E+01 8.50271E+06 + 7.75000E+01 8.50271E+06 + 7.76000E+01 7.93586E+06 + 7.77000E+01 7.36902E+06 + 7.78000E+01 6.80217E+06 + 7.79000E+01 6.23532E+06 + 7.80000E+01 5.66848E+06 + 7.81000E+01 5.24334E+06 + 7.82000E+01 5.38505E+06 + 7.83000E+01 5.52676E+06 + 7.84000E+01 5.66848E+06 + 7.85000E+01 5.81019E+06 + 7.86000E+01 5.95190E+06 + 7.87000E+01 6.09361E+06 + 7.88000E+01 6.23532E+06 + 7.89000E+01 6.37703E+06 + 7.90000E+01 6.51875E+06 + 7.91000E+01 6.66046E+06 + 7.92000E+01 6.80217E+06 + 7.93000E+01 6.94388E+06 + 7.94000E+01 7.08559E+06 + 7.95000E+01 7.22730E+06 + 7.96000E+01 7.36902E+06 + 7.97000E+01 7.51073E+06 + 7.98000E+01 7.65244E+06 + 7.99000E+01 7.79415E+06 + 8.00000E+01 7.93586E+06 + 8.01000E+01 8.07758E+06 + 8.02000E+01 8.21929E+06 + 8.03000E+01 8.36100E+06 + 8.04000E+01 8.50271E+06 + 8.05000E+01 8.50271E+06 + 8.06000E+01 7.93586E+06 + 8.07000E+01 7.36902E+06 + 8.08000E+01 6.80217E+06 + 8.09000E+01 6.23532E+06 + 8.10000E+01 5.66848E+06 + 8.11000E+01 5.24334E+06 + 8.12000E+01 5.38505E+06 + 8.13000E+01 5.52676E+06 + 8.14000E+01 5.66848E+06 + 8.15000E+01 5.81019E+06 + 8.16000E+01 5.95190E+06 + 8.17000E+01 6.09361E+06 + 8.18000E+01 6.23532E+06 + 8.19000E+01 6.37703E+06 + 8.20000E+01 6.51875E+06 + 8.21000E+01 6.66046E+06 + 8.22000E+01 6.80217E+06 + 8.23000E+01 6.94388E+06 + 8.24000E+01 7.08559E+06 + 8.25000E+01 7.22730E+06 + 8.26000E+01 7.36902E+06 + 8.27000E+01 7.51073E+06 + 8.28000E+01 7.65244E+06 + 8.29000E+01 7.79415E+06 + 8.30000E+01 7.93586E+06 + 8.31000E+01 8.07758E+06 + 8.32000E+01 8.21929E+06 + 8.33000E+01 8.36100E+06 + 8.34000E+01 8.50271E+06 + 8.35000E+01 8.50271E+06 + 8.36000E+01 7.93586E+06 + 8.37000E+01 7.36902E+06 + 8.38000E+01 6.80217E+06 + 8.39000E+01 6.23532E+06 + 8.40000E+01 5.66848E+06 + 8.41000E+01 5.24334E+06 + 8.42000E+01 5.38505E+06 + 8.43000E+01 5.52676E+06 + 8.44000E+01 5.66848E+06 + 8.45000E+01 5.81019E+06 + 8.46000E+01 5.95190E+06 + 8.47000E+01 6.09361E+06 + 8.48000E+01 6.23532E+06 + 8.49000E+01 6.37703E+06 + 8.50000E+01 6.51875E+06 + 8.51000E+01 6.66046E+06 + 8.52000E+01 6.80217E+06 + 8.53000E+01 6.94388E+06 + 8.54000E+01 7.08559E+06 + 8.55000E+01 7.22730E+06 + 8.56000E+01 7.36902E+06 + 8.57000E+01 7.51073E+06 + 8.58000E+01 7.65244E+06 + 8.59000E+01 7.79415E+06 + 8.60000E+01 7.93586E+06 + 8.61000E+01 8.07758E+06 + 8.62000E+01 8.21929E+06 + 8.63000E+01 8.36100E+06 + 8.64000E+01 8.50271E+06 + 8.65000E+01 8.50271E+06 + 8.66000E+01 7.93586E+06 + 8.67000E+01 7.36902E+06 + 8.68000E+01 6.80217E+06 + 8.69000E+01 6.23532E+06 + 8.70000E+01 5.66848E+06 + 8.71000E+01 5.24334E+06 + 8.72000E+01 5.38505E+06 + 8.73000E+01 5.52676E+06 + 8.74000E+01 5.66848E+06 + 8.75000E+01 5.81019E+06 + 8.76000E+01 5.95190E+06 + 8.77000E+01 6.09361E+06 + 8.78000E+01 6.23532E+06 + 8.79000E+01 6.37703E+06 + 8.80000E+01 6.51875E+06 + 8.81000E+01 6.66046E+06 + 8.82000E+01 6.80217E+06 + 8.83000E+01 6.94388E+06 + 8.84000E+01 7.08559E+06 + 8.85000E+01 7.22730E+06 + 8.86000E+01 7.36902E+06 + 8.87000E+01 7.51073E+06 + 8.88000E+01 7.65244E+06 + 8.89000E+01 7.79415E+06 + 8.90000E+01 7.93586E+06 + 8.91000E+01 8.07758E+06 + 8.92000E+01 8.21929E+06 + 8.93000E+01 8.36100E+06 + 8.94000E+01 8.50271E+06 + 8.95000E+01 8.50271E+06 + 8.96000E+01 7.93586E+06 + 8.97000E+01 7.36902E+06 + 8.98000E+01 6.80217E+06 + 8.99000E+01 6.23532E+06 + 9.00000E+01 5.66848E+06 + 9.01000E+01 5.24334E+06 + 9.02000E+01 5.38505E+06 + 9.03000E+01 5.52676E+06 + 9.04000E+01 5.66848E+06 + 9.05000E+01 5.81019E+06 + 9.06000E+01 5.95190E+06 + 9.07000E+01 6.09361E+06 + 9.08000E+01 6.23532E+06 + 9.09000E+01 6.37703E+06 + 9.10000E+01 6.51875E+06 + 9.11000E+01 6.66046E+06 + 9.12000E+01 6.80217E+06 + 9.13000E+01 6.94388E+06 + 9.14000E+01 7.08559E+06 + 9.15000E+01 7.22730E+06 + 9.16000E+01 7.36902E+06 + 9.17000E+01 7.51073E+06 + 9.18000E+01 7.65244E+06 + 9.19000E+01 7.79415E+06 + 9.20000E+01 7.93586E+06 + 9.21000E+01 8.07758E+06 + 9.22000E+01 8.21929E+06 + 9.23000E+01 8.36100E+06 + 9.24000E+01 8.50271E+06 + 9.25000E+01 8.50271E+06 + 9.26000E+01 7.93586E+06 + 9.27000E+01 7.36902E+06 + 9.28000E+01 6.80217E+06 + 9.29000E+01 6.23532E+06 + 9.30000E+01 5.66848E+06 + 9.31000E+01 5.24334E+06 + 9.32000E+01 5.38505E+06 + 9.33000E+01 5.52676E+06 + 9.34000E+01 5.66848E+06 + 9.35000E+01 5.81019E+06 + 9.36000E+01 5.95190E+06 + 9.37000E+01 6.09361E+06 + 9.38000E+01 6.23532E+06 + 9.39000E+01 6.37703E+06 + 9.40000E+01 6.51875E+06 + 9.41000E+01 6.66046E+06 + 9.42000E+01 6.80217E+06 + 9.43000E+01 6.94388E+06 + 9.44000E+01 7.08559E+06 + 9.45000E+01 7.22730E+06 + 9.46000E+01 7.36902E+06 + 9.47000E+01 7.51073E+06 + 9.48000E+01 7.65244E+06 + 9.49000E+01 7.79415E+06 + 9.50000E+01 7.93586E+06 + 9.51000E+01 8.07758E+06 + 9.52000E+01 8.21929E+06 + 9.53000E+01 8.36100E+06 + 9.54000E+01 8.50271E+06 + 9.55000E+01 8.50271E+06 + 9.56000E+01 7.93586E+06 + 9.57000E+01 7.36902E+06 + 9.58000E+01 6.80217E+06 + 9.59000E+01 6.23532E+06 + 9.60000E+01 5.66848E+06 + 9.61000E+01 5.24334E+06 + 9.62000E+01 5.38505E+06 + 9.63000E+01 5.52676E+06 + 9.64000E+01 5.66848E+06 + 9.65000E+01 5.81019E+06 + 9.66000E+01 5.95190E+06 + 9.67000E+01 6.09361E+06 + 9.68000E+01 6.23532E+06 + 9.69000E+01 6.37703E+06 + 9.70000E+01 6.51875E+06 + 9.71000E+01 6.66046E+06 + 9.72000E+01 6.80217E+06 + 9.73000E+01 6.94388E+06 + 9.74000E+01 7.08559E+06 + 9.75000E+01 7.22730E+06 + 9.76000E+01 7.36902E+06 + 9.77000E+01 7.51073E+06 + 9.78000E+01 7.65244E+06 + 9.79000E+01 7.79415E+06 + 9.80000E+01 7.93586E+06 + 9.81000E+01 8.07758E+06 + 9.82000E+01 8.21929E+06 + 9.83000E+01 8.36100E+06 + 9.84000E+01 8.50271E+06 + 9.85000E+01 8.50271E+06 + 9.86000E+01 7.93586E+06 + 9.87000E+01 7.36902E+06 + 9.88000E+01 6.80217E+06 + 9.89000E+01 6.23532E+06 + 9.90000E+01 5.66848E+06 + 9.91000E+01 5.24334E+06 + 9.92000E+01 5.38505E+06 + 9.93000E+01 5.52676E+06 + 9.94000E+01 5.66848E+06 + 9.95000E+01 5.81019E+06 + 9.96000E+01 5.95190E+06 + 9.97000E+01 6.09361E+06 + 9.98000E+01 6.23532E+06 + 9.99000E+01 6.37703E+06 + 1.00000E+02 6.51875E+06 + 1.00100E+02 6.66046E+06 + 1.00200E+02 6.80217E+06 + 1.00300E+02 6.94388E+06 + 1.00400E+02 7.08559E+06 + 1.00500E+02 7.22730E+06 + 1.00600E+02 7.36902E+06 + 1.00700E+02 7.51073E+06 + 1.00800E+02 7.65244E+06 + 1.00900E+02 7.79415E+06 + 1.01000E+02 7.93586E+06 + 1.01100E+02 8.07758E+06 + 1.01200E+02 8.21929E+06 + 1.01300E+02 8.36100E+06 + 1.01400E+02 8.50271E+06 + 1.01500E+02 8.50271E+06 + 1.01600E+02 7.93586E+06 + 1.01700E+02 7.36902E+06 + 1.01800E+02 6.80217E+06 + 1.01900E+02 6.23532E+06 + 1.02000E+02 5.66848E+06 + 1.02100E+02 5.24334E+06 + 1.02200E+02 5.38505E+06 + 1.02300E+02 5.52676E+06 + 1.02400E+02 5.66848E+06 + 1.02500E+02 5.81019E+06 + 1.02600E+02 5.95190E+06 + 1.02700E+02 6.09361E+06 + 1.02800E+02 6.23532E+06 + 1.02900E+02 6.37703E+06 + 1.03000E+02 6.51875E+06 + 1.03100E+02 6.66046E+06 + 1.03200E+02 6.80217E+06 + 1.03300E+02 6.94388E+06 + 1.03400E+02 7.08559E+06 + 1.03500E+02 7.22730E+06 + 1.03600E+02 7.36902E+06 + 1.03700E+02 7.51073E+06 + 1.03800E+02 7.65244E+06 + 1.03900E+02 7.79415E+06 + 1.04000E+02 7.93586E+06 + 1.04100E+02 8.07758E+06 + 1.04200E+02 8.21929E+06 + 1.04300E+02 8.36100E+06 + 1.04400E+02 8.50271E+06 + 1.04500E+02 8.50271E+06 + 1.04600E+02 7.93586E+06 + 1.04700E+02 7.36902E+06 + 1.04800E+02 6.80217E+06 + 1.04900E+02 6.23532E+06 + 1.05000E+02 5.66848E+06 + 1.05100E+02 5.24334E+06 + 1.05200E+02 5.38505E+06 + 1.05300E+02 5.52676E+06 + 1.05400E+02 5.66848E+06 + 1.05500E+02 5.81019E+06 + 1.05600E+02 5.95190E+06 + 1.05700E+02 6.09361E+06 + 1.05800E+02 6.23532E+06 + 1.05900E+02 6.37703E+06 + 1.06000E+02 6.51875E+06 + 1.06100E+02 6.66046E+06 + 1.06200E+02 6.80217E+06 + 1.06300E+02 6.94388E+06 + 1.06400E+02 7.08559E+06 + 1.06500E+02 7.22730E+06 + 1.06600E+02 7.36902E+06 + 1.06700E+02 7.51073E+06 + 1.06800E+02 7.65244E+06 + 1.06900E+02 7.79415E+06 + 1.07000E+02 7.93586E+06 + 1.07100E+02 8.07758E+06 + 1.07200E+02 8.21929E+06 + 1.07300E+02 8.36100E+06 + 1.07400E+02 8.50271E+06 + 1.07500E+02 8.50271E+06 + 1.07600E+02 7.93586E+06 + 1.07700E+02 7.36902E+06 + 1.07800E+02 6.80217E+06 + 1.07900E+02 6.23532E+06 + 1.08000E+02 5.66848E+06 + 1.08100E+02 5.24334E+06 + 1.08200E+02 5.38505E+06 + 1.08300E+02 5.52676E+06 + 1.08400E+02 5.66848E+06 + 1.08500E+02 5.81019E+06 + 1.08600E+02 5.95190E+06 + 1.08700E+02 6.09361E+06 + 1.08800E+02 6.23532E+06 + 1.08900E+02 6.37703E+06 + 1.09000E+02 6.51875E+06 + 1.09100E+02 6.66046E+06 + 1.09200E+02 6.80217E+06 + 1.09300E+02 6.94388E+06 + 1.09400E+02 7.08559E+06 + 1.09500E+02 7.22730E+06 + 1.09600E+02 7.36902E+06 + 1.09700E+02 7.51073E+06 + 1.09800E+02 7.65244E+06 + 1.09900E+02 7.79415E+06 + 1.10000E+02 7.93586E+06 + 1.10100E+02 8.07758E+06 + 1.10200E+02 8.21929E+06 + 1.10300E+02 8.36100E+06 + 1.10400E+02 8.50271E+06 + 1.10500E+02 8.50271E+06 + 1.10600E+02 7.93586E+06 + 1.10700E+02 7.36902E+06 + 1.10800E+02 6.80217E+06 + 1.10900E+02 6.23532E+06 + 1.11000E+02 5.66848E+06 + 1.11100E+02 5.24334E+06 + 1.11200E+02 5.38505E+06 + 1.11300E+02 5.52676E+06 + 1.11400E+02 5.66848E+06 + 1.11500E+02 5.81019E+06 + 1.11600E+02 5.95190E+06 + 1.11700E+02 6.09361E+06 + 1.11800E+02 6.23532E+06 + 1.11900E+02 6.37703E+06 + 1.12000E+02 6.51875E+06 + 1.12100E+02 6.66046E+06 + 1.12200E+02 6.80217E+06 + 1.12300E+02 6.94388E+06 + 1.12400E+02 7.08559E+06 + 1.12500E+02 7.22730E+06 + 1.12600E+02 7.36902E+06 + 1.12700E+02 7.51073E+06 + 1.12800E+02 7.65244E+06 + 1.12900E+02 7.79415E+06 + 1.13000E+02 7.93586E+06 + 1.13100E+02 8.07758E+06 + 1.13200E+02 8.21929E+06 + 1.13300E+02 8.36100E+06 + 1.13400E+02 8.50271E+06 + 1.13500E+02 8.50271E+06 + 1.13600E+02 7.93586E+06 + 1.13700E+02 7.36902E+06 + 1.13800E+02 6.80217E+06 + 1.13900E+02 6.23532E+06 + 1.14000E+02 5.66848E+06 + 1.14100E+02 5.24334E+06 + 1.14200E+02 5.38505E+06 + 1.14300E+02 5.52676E+06 + 1.14400E+02 5.66848E+06 + 1.14500E+02 5.81019E+06 + 1.14600E+02 5.95190E+06 + 1.14700E+02 6.09361E+06 + 1.14800E+02 6.23532E+06 + 1.14900E+02 6.37703E+06 + 1.15000E+02 6.51875E+06 + 1.15100E+02 6.66046E+06 + 1.15200E+02 6.80217E+06 + 1.15300E+02 6.94388E+06 + 1.15400E+02 7.08559E+06 + 1.15500E+02 7.22730E+06 + 1.15600E+02 7.36902E+06 + 1.15700E+02 7.51073E+06 + 1.15800E+02 7.65244E+06 + 1.15900E+02 7.79415E+06 + 1.16000E+02 7.93586E+06 + 1.16100E+02 8.07758E+06 + 1.16200E+02 8.21929E+06 + 1.16300E+02 8.36100E+06 + 1.16400E+02 8.50271E+06 + 1.16500E+02 8.50271E+06 + 1.16600E+02 7.93586E+06 + 1.16700E+02 7.36902E+06 + 1.16800E+02 6.80217E+06 + 1.16900E+02 6.23532E+06 + 1.17000E+02 5.66848E+06 + 1.17100E+02 5.24334E+06 + 1.17200E+02 5.38505E+06 + 1.17300E+02 5.52676E+06 + 1.17400E+02 5.66848E+06 + 1.17500E+02 5.81019E+06 + 1.17600E+02 5.95190E+06 + 1.17700E+02 6.09361E+06 + 1.17800E+02 6.23532E+06 + 1.17900E+02 6.37703E+06 + 1.18000E+02 6.51875E+06 + 1.18100E+02 6.66046E+06 + 1.18200E+02 6.80217E+06 + 1.18300E+02 6.94388E+06 + 1.18400E+02 7.08559E+06 + 1.18500E+02 7.22730E+06 + 1.18600E+02 7.36902E+06 + 1.18700E+02 7.51073E+06 + 1.18800E+02 7.65244E+06 + 1.18900E+02 7.79415E+06 + 1.19000E+02 7.93586E+06 + 1.19100E+02 8.07758E+06 + 1.19200E+02 8.21929E+06 + 1.19300E+02 8.36100E+06 + 1.19400E+02 8.50271E+06 + 1.19500E+02 8.50271E+06 + 1.19600E+02 7.93586E+06 + 1.19700E+02 7.36902E+06 + 1.19800E+02 6.80217E+06 + 1.19900E+02 6.23532E+06 + 1.20000E+02 5.66848E+06 + 1.20100E+02 5.24334E+06 + 1.20200E+02 5.38505E+06 + 1.20300E+02 5.52676E+06 + 1.20400E+02 5.66848E+06 + 1.20500E+02 5.81019E+06 + 1.20600E+02 5.95190E+06 + 1.20700E+02 6.09361E+06 + 1.20800E+02 6.23532E+06 + 1.20900E+02 6.37703E+06 + 1.21000E+02 6.51875E+06 + 1.21100E+02 6.66046E+06 + 1.21200E+02 6.80217E+06 + 1.21300E+02 6.94388E+06 + 1.21400E+02 7.08559E+06 + 1.21500E+02 7.22730E+06 + 1.21600E+02 7.36902E+06 + 1.21700E+02 7.51073E+06 + 1.21800E+02 7.65244E+06 + 1.21900E+02 7.79415E+06 + 1.22000E+02 7.93586E+06 + 1.22100E+02 8.07758E+06 + 1.22200E+02 8.21929E+06 + 1.22300E+02 8.36100E+06 + 1.22400E+02 8.50271E+06 + 1.22500E+02 8.50271E+06 + 1.22600E+02 7.93586E+06 + 1.22700E+02 7.36902E+06 + 1.22800E+02 6.80217E+06 + 1.22900E+02 6.23532E+06 + 1.23000E+02 5.66848E+06 + 1.23100E+02 5.24334E+06 + 1.23200E+02 5.38505E+06 + 1.23300E+02 5.52676E+06 + 1.23400E+02 5.66848E+06 + 1.23500E+02 5.81019E+06 + 1.23600E+02 5.95190E+06 + 1.23700E+02 6.09361E+06 + 1.23800E+02 6.23532E+06 + 1.23900E+02 6.37703E+06 + 1.24000E+02 6.51875E+06 + 1.24100E+02 6.66046E+06 + 1.24200E+02 6.80217E+06 + 1.24300E+02 6.94388E+06 + 1.24400E+02 7.08559E+06 + 1.24500E+02 7.22730E+06 + 1.24600E+02 7.36902E+06 + 1.24700E+02 7.51073E+06 + 1.24800E+02 7.65244E+06 + 1.24900E+02 7.79415E+06 + 1.25000E+02 7.93586E+06 + 1.25100E+02 8.07758E+06 + 1.25200E+02 8.21929E+06 + 1.25300E+02 8.36100E+06 + 1.25400E+02 8.50271E+06 + 1.25500E+02 8.50271E+06 + 1.25600E+02 7.93586E+06 + 1.25700E+02 7.36902E+06 + 1.25800E+02 6.80217E+06 + 1.25900E+02 6.23532E+06 + 1.26000E+02 5.66848E+06 + 1.26100E+02 5.24334E+06 + 1.26200E+02 5.38505E+06 + 1.26300E+02 5.52676E+06 + 1.26400E+02 5.66848E+06 + 1.26500E+02 5.81019E+06 + 1.26600E+02 5.95190E+06 + 1.26700E+02 6.09361E+06 + 1.26800E+02 6.23532E+06 + 1.26900E+02 6.37703E+06 + 1.27000E+02 6.51875E+06 + 1.27100E+02 6.66046E+06 + 1.27200E+02 6.80217E+06 + 1.27300E+02 6.94388E+06 + 1.27400E+02 7.08559E+06 + 1.27500E+02 7.22730E+06 + 1.27600E+02 7.36902E+06 + 1.27700E+02 7.51073E+06 + 1.27800E+02 7.65244E+06 + 1.27900E+02 7.79415E+06 + 1.28000E+02 7.93586E+06 + 1.28100E+02 8.07758E+06 + 1.28200E+02 8.21929E+06 + 1.28300E+02 8.36100E+06 + 1.28400E+02 8.50271E+06 + 1.28500E+02 8.50271E+06 + 1.28600E+02 7.93586E+06 + 1.28700E+02 7.36902E+06 + 1.28800E+02 6.80217E+06 + 1.28900E+02 6.23532E+06 + 1.29000E+02 5.66848E+06 + 1.29100E+02 5.24334E+06 + 1.29200E+02 5.38505E+06 + 1.29300E+02 5.52676E+06 + 1.29400E+02 5.66848E+06 + 1.29500E+02 5.81019E+06 + 1.29600E+02 5.95190E+06 + 1.29700E+02 6.09361E+06 + 1.29800E+02 6.23532E+06 + 1.29900E+02 6.37703E+06 + 1.30000E+02 6.51875E+06 + 1.30100E+02 6.66046E+06 + 1.30200E+02 6.80217E+06 + 1.30300E+02 6.94388E+06 + 1.30400E+02 7.08559E+06 + 1.30500E+02 7.22730E+06 + 1.30600E+02 7.36902E+06 + 1.30700E+02 7.51073E+06 + 1.30800E+02 7.65244E+06 + 1.30900E+02 7.79415E+06 + 1.31000E+02 7.93586E+06 + 1.31100E+02 8.07758E+06 + 1.31200E+02 8.21929E+06 + 1.31300E+02 8.36100E+06 + 1.31400E+02 8.50271E+06 + 1.31500E+02 8.50271E+06 + 1.31600E+02 7.93586E+06 + 1.31700E+02 7.36902E+06 + 1.31800E+02 6.80217E+06 + 1.31900E+02 6.23532E+06 + 1.32000E+02 5.66848E+06 + 1.32100E+02 5.24334E+06 + 1.32200E+02 5.38505E+06 + 1.32300E+02 5.52676E+06 + 1.32400E+02 5.66848E+06 + 1.32500E+02 5.81019E+06 + 1.32600E+02 5.95190E+06 + 1.32700E+02 6.09361E+06 + 1.32800E+02 6.23532E+06 + 1.32900E+02 6.37703E+06 + 1.33000E+02 6.51875E+06 + 1.33100E+02 6.66046E+06 + 1.33200E+02 6.80217E+06 + 1.33300E+02 6.94388E+06 + 1.33400E+02 7.08559E+06 + 1.33500E+02 7.22730E+06 + 1.33600E+02 7.36902E+06 + 1.33700E+02 7.51073E+06 + 1.33800E+02 7.65244E+06 + 1.33900E+02 7.79415E+06 + 1.34000E+02 7.93586E+06 + 1.34100E+02 8.07758E+06 + 1.34200E+02 8.21929E+06 + 1.34300E+02 8.36100E+06 + 1.34400E+02 8.50271E+06 + 1.34500E+02 8.50271E+06 + 1.34600E+02 7.93586E+06 + 1.34700E+02 7.36902E+06 + 1.34800E+02 6.80217E+06 + 1.34900E+02 6.23532E+06 + 1.35000E+02 5.66848E+06 + 1.35100E+02 5.24334E+06 + 1.35200E+02 5.38505E+06 + 1.35300E+02 5.52676E+06 + 1.35400E+02 5.66848E+06 + 1.35500E+02 5.81019E+06 + 1.35600E+02 5.95190E+06 + 1.35700E+02 6.09361E+06 + 1.35800E+02 6.23532E+06 + 1.35900E+02 6.37703E+06 + 1.36000E+02 6.51875E+06 + 1.36100E+02 6.66046E+06 + 1.36200E+02 6.80217E+06 + 1.36300E+02 6.94388E+06 + 1.36400E+02 7.08559E+06 + 1.36500E+02 7.22730E+06 + 1.36600E+02 7.36902E+06 + 1.36700E+02 7.51073E+06 + 1.36800E+02 7.65244E+06 + 1.36900E+02 7.79415E+06 + 1.37000E+02 7.93586E+06 + 1.37100E+02 8.07758E+06 + 1.37200E+02 8.21929E+06 + 1.37300E+02 8.36100E+06 + 1.37400E+02 8.50271E+06 + 1.37500E+02 8.50271E+06 + 1.37600E+02 7.93586E+06 + 1.37700E+02 7.36902E+06 + 1.37800E+02 6.80217E+06 + 1.37900E+02 6.23532E+06 + 1.38000E+02 5.66848E+06 + 1.38100E+02 5.24334E+06 + 1.38200E+02 5.38505E+06 + 1.38300E+02 5.52676E+06 + 1.38400E+02 5.66848E+06 + 1.38500E+02 5.81019E+06 + 1.38600E+02 5.95190E+06 + 1.38700E+02 6.09361E+06 + 1.38800E+02 6.23532E+06 + 1.38900E+02 6.37703E+06 + 1.39000E+02 6.51875E+06 + 1.39100E+02 6.66046E+06 + 1.39200E+02 6.80217E+06 + 1.39300E+02 6.94388E+06 + 1.39400E+02 7.08559E+06 + 1.39500E+02 7.22730E+06 + 1.39600E+02 7.36902E+06 + 1.39700E+02 7.51073E+06 + 1.39800E+02 7.65244E+06 + 1.39900E+02 7.79415E+06 + 1.40000E+02 7.93586E+06 + 1.40100E+02 8.07758E+06 + 1.40200E+02 8.21929E+06 + 1.40300E+02 8.36100E+06 + 1.40400E+02 8.50271E+06 + 1.40500E+02 8.50271E+06 + 1.40600E+02 7.93586E+06 + 1.40700E+02 7.36902E+06 + 1.40800E+02 6.80217E+06 + 1.40900E+02 6.23532E+06 + 1.41000E+02 5.66848E+06 + 1.41100E+02 5.24334E+06 + 1.41200E+02 5.38505E+06 + 1.41300E+02 5.52676E+06 + 1.41400E+02 5.66848E+06 + 1.41500E+02 5.81019E+06 + 1.41600E+02 5.95190E+06 + 1.41700E+02 6.09361E+06 + 1.41800E+02 6.23532E+06 + 1.41900E+02 6.37703E+06 + 1.42000E+02 6.51875E+06 + 1.42100E+02 6.66046E+06 + 1.42200E+02 6.80217E+06 + 1.42300E+02 6.94388E+06 + 1.42400E+02 7.08559E+06 + 1.42500E+02 7.22730E+06 + 1.42600E+02 7.36902E+06 + 1.42700E+02 7.51073E+06 + 1.42800E+02 7.65244E+06 + 1.42900E+02 7.79415E+06 + 1.43000E+02 7.93586E+06 + 1.43100E+02 8.07758E+06 + 1.43200E+02 8.21929E+06 + 1.43300E+02 8.36100E+06 + 1.43400E+02 8.50271E+06 + 1.43500E+02 8.50271E+06 + 1.43600E+02 7.93586E+06 + 1.43700E+02 7.36902E+06 + 1.43800E+02 6.80217E+06 + 1.43900E+02 6.23532E+06 + 1.44000E+02 5.66848E+06 + 1.44100E+02 5.24334E+06 + 1.44200E+02 5.38505E+06 + 1.44300E+02 5.52676E+06 + 1.44400E+02 5.66848E+06 + 1.44500E+02 5.81019E+06 + 1.44600E+02 5.95190E+06 + 1.44700E+02 6.09361E+06 + 1.44800E+02 6.23532E+06 + 1.44900E+02 6.37703E+06 + 1.45000E+02 6.51875E+06 + 1.45100E+02 6.66046E+06 + 1.45200E+02 6.80217E+06 + 1.45300E+02 6.94388E+06 + 1.45400E+02 7.08559E+06 + 1.45500E+02 7.22730E+06 + 1.45600E+02 7.36902E+06 + 1.45700E+02 7.51073E+06 + 1.45800E+02 7.65244E+06 + 1.45900E+02 7.79415E+06 + 1.46000E+02 7.93586E+06 + 1.46100E+02 8.07758E+06 + 1.46200E+02 8.21929E+06 + 1.46300E+02 8.36100E+06 + 1.46400E+02 8.50271E+06 + 1.46500E+02 8.50271E+06 + 1.46600E+02 7.93586E+06 + 1.46700E+02 7.36902E+06 + 1.46800E+02 6.80217E+06 + 1.46900E+02 6.23532E+06 + 1.47000E+02 5.66848E+06 + 1.47100E+02 5.24334E+06 + 1.47200E+02 5.38505E+06 + 1.47300E+02 5.52676E+06 + 1.47400E+02 5.66848E+06 + 1.47500E+02 5.81019E+06 + 1.47600E+02 5.95190E+06 + 1.47700E+02 6.09361E+06 + 1.47800E+02 6.23532E+06 + 1.47900E+02 6.37703E+06 + 1.48000E+02 6.51875E+06 + 1.48100E+02 6.66046E+06 + 1.48200E+02 6.80217E+06 + 1.48300E+02 6.94388E+06 + 1.48400E+02 7.08559E+06 + 1.48500E+02 7.22730E+06 + 1.48600E+02 7.36902E+06 + 1.48700E+02 7.51073E+06 + 1.48800E+02 7.65244E+06 + 1.48900E+02 7.79415E+06 + 1.49000E+02 7.93586E+06 + 1.49100E+02 8.07758E+06 + 1.49200E+02 8.21929E+06 + 1.49300E+02 8.36100E+06 + 1.49400E+02 8.50271E+06 + 1.49500E+02 8.50271E+06 + 1.49600E+02 7.93586E+06 + 1.49700E+02 7.36902E+06 + 1.49800E+02 6.80217E+06 + 1.49900E+02 6.23532E+06 + 1.50000E+02 5.66848E+06 + 1.50100E+02 5.24334E+06 + 1.50200E+02 5.38505E+06 + 1.50300E+02 5.52676E+06 + 1.50400E+02 5.66848E+06 + 1.50500E+02 5.81019E+06 + 1.50600E+02 5.95190E+06 + 1.50700E+02 6.09361E+06 + 1.50800E+02 6.23532E+06 + 1.50900E+02 6.37703E+06 + 1.51000E+02 6.51875E+06 + 1.51100E+02 6.66046E+06 + 1.51200E+02 6.80217E+06 + 1.51300E+02 6.94388E+06 + 1.51400E+02 7.08559E+06 + 1.51500E+02 7.22730E+06 + 1.51600E+02 7.36902E+06 + 1.51700E+02 7.51073E+06 + 1.51800E+02 7.65244E+06 + 1.51900E+02 7.79415E+06 + 1.52000E+02 7.93586E+06 + 1.52100E+02 8.07758E+06 + 1.52200E+02 8.21929E+06 + 1.52300E+02 8.36100E+06 + 1.52400E+02 8.50271E+06 + 1.52500E+02 8.50271E+06 + 1.52600E+02 7.93586E+06 + 1.52700E+02 7.36902E+06 + 1.52800E+02 6.80217E+06 + 1.52900E+02 6.23532E+06 + 1.53000E+02 5.66848E+06 + 1.53100E+02 5.24334E+06 + 1.53200E+02 5.38505E+06 + 1.53300E+02 5.52676E+06 + 1.53400E+02 5.66848E+06 + 1.53500E+02 5.81019E+06 + 1.53600E+02 5.95190E+06 + 1.53700E+02 6.09361E+06 + 1.53800E+02 6.23532E+06 + 1.53900E+02 6.37703E+06 + 1.54000E+02 6.51875E+06 + 1.54100E+02 6.66046E+06 + 1.54200E+02 6.80217E+06 + 1.54300E+02 6.94388E+06 + 1.54400E+02 7.08559E+06 + 1.54500E+02 7.22730E+06 + 1.54600E+02 7.36902E+06 + 1.54700E+02 7.51073E+06 + 1.54800E+02 7.65244E+06 + 1.54900E+02 7.79415E+06 + 1.55000E+02 7.93586E+06 + 1.55100E+02 8.07758E+06 + 1.55200E+02 8.21929E+06 + 1.55300E+02 8.36100E+06 + 1.55400E+02 8.50271E+06 + 1.55500E+02 8.50271E+06 + 1.55600E+02 7.93586E+06 + 1.55700E+02 7.36902E+06 + 1.55800E+02 6.80217E+06 + 1.55900E+02 6.23532E+06 + 1.56000E+02 5.66848E+06 + 1.56100E+02 5.24334E+06 + 1.56200E+02 5.38505E+06 + 1.56300E+02 5.52676E+06 + 1.56400E+02 5.66848E+06 + 1.56500E+02 5.81019E+06 + 1.56600E+02 5.95190E+06 + 1.56700E+02 6.09361E+06 + 1.56800E+02 6.23532E+06 + 1.56900E+02 6.37703E+06 + 1.57000E+02 6.51875E+06 + 1.57100E+02 6.66046E+06 + 1.57200E+02 6.80217E+06 + 1.57300E+02 6.94388E+06 + 1.57400E+02 7.08559E+06 + 1.57500E+02 7.22730E+06 + 1.57600E+02 7.36902E+06 + 1.57700E+02 7.51073E+06 + 1.57800E+02 7.65244E+06 + 1.57900E+02 7.79415E+06 + 1.58000E+02 7.93586E+06 + 1.58100E+02 8.07758E+06 + 1.58200E+02 8.21929E+06 + 1.58300E+02 8.36100E+06 + 1.58400E+02 8.50271E+06 + 1.58500E+02 8.50271E+06 + 1.58600E+02 7.93586E+06 + 1.58700E+02 7.36902E+06 + 1.58800E+02 6.80217E+06 + 1.58900E+02 6.23532E+06 + 1.59000E+02 5.66848E+06 + 1.59100E+02 5.24334E+06 + 1.59200E+02 5.38505E+06 + 1.59300E+02 5.52676E+06 + 1.59400E+02 5.66848E+06 + 1.59500E+02 5.81019E+06 + 1.59600E+02 5.95190E+06 + 1.59700E+02 6.09361E+06 + 1.59800E+02 6.23532E+06 + 1.59900E+02 6.37703E+06 + 1.60000E+02 6.51875E+06 + 1.60100E+02 6.66046E+06 + 1.60200E+02 6.80217E+06 + 1.60300E+02 6.94388E+06 + 1.60400E+02 7.08559E+06 + 1.60500E+02 7.22730E+06 + 1.60600E+02 7.36902E+06 + 1.60700E+02 7.51073E+06 + 1.60800E+02 7.65244E+06 + 1.60900E+02 7.79415E+06 + 1.61000E+02 7.93586E+06 + 1.61100E+02 8.07758E+06 + 1.61200E+02 8.21929E+06 + 1.61300E+02 8.36100E+06 + 1.61400E+02 8.50271E+06 + 1.61500E+02 8.50271E+06 + 1.61600E+02 7.93586E+06 + 1.61700E+02 7.36902E+06 + 1.61800E+02 6.80217E+06 + 1.61900E+02 6.23532E+06 + 1.62000E+02 5.66848E+06 + 1.62100E+02 5.24334E+06 + 1.62200E+02 5.38505E+06 + 1.62300E+02 5.52676E+06 + 1.62400E+02 5.66848E+06 + 1.62500E+02 5.81019E+06 + 1.62600E+02 5.95190E+06 + 1.62700E+02 6.09361E+06 + 1.62800E+02 6.23532E+06 + 1.62900E+02 6.37703E+06 + 1.63000E+02 6.51875E+06 + 1.63100E+02 6.66046E+06 + 1.63200E+02 6.80217E+06 + 1.63300E+02 6.94388E+06 + 1.63400E+02 7.08559E+06 + 1.63500E+02 7.22730E+06 + 1.63600E+02 7.36902E+06 + 1.63700E+02 7.51073E+06 + 1.63800E+02 7.65244E+06 + 1.63900E+02 7.79415E+06 + 1.64000E+02 7.93586E+06 + 1.64100E+02 8.07758E+06 + 1.64200E+02 8.21929E+06 + 1.64300E+02 8.36100E+06 + 1.64400E+02 8.50271E+06 + 1.64500E+02 8.50271E+06 + 1.64600E+02 7.93586E+06 + 1.64700E+02 7.36902E+06 + 1.64800E+02 6.80217E+06 + 1.64900E+02 6.23532E+06 + 1.65000E+02 5.66848E+06 + 1.65100E+02 5.24334E+06 + 1.65200E+02 5.38505E+06 + 1.65300E+02 5.52676E+06 + 1.65400E+02 5.66848E+06 + 1.65500E+02 5.81019E+06 + 1.65600E+02 5.95190E+06 + 1.65700E+02 6.09361E+06 + 1.65800E+02 6.23532E+06 + 1.65900E+02 6.37703E+06 + 1.66000E+02 6.51875E+06 + 1.66100E+02 6.66046E+06 + 1.66200E+02 6.80217E+06 + 1.66300E+02 6.94388E+06 + 1.66400E+02 7.08559E+06 + 1.66500E+02 7.22730E+06 + 1.66600E+02 7.36902E+06 + 1.66700E+02 7.51073E+06 + 1.66800E+02 7.65244E+06 + 1.66900E+02 7.79415E+06 + 1.67000E+02 7.93586E+06 + 1.67100E+02 8.07758E+06 + 1.67200E+02 8.21929E+06 + 1.67300E+02 8.36100E+06 + 1.67400E+02 8.50271E+06 + 1.67500E+02 8.50271E+06 + 1.67600E+02 7.93586E+06 + 1.67700E+02 7.36902E+06 + 1.67800E+02 6.80217E+06 + 1.67900E+02 6.23532E+06 + 1.68000E+02 5.66848E+06 + 1.68100E+02 5.24334E+06 + 1.68200E+02 5.38505E+06 + 1.68300E+02 5.52676E+06 + 1.68400E+02 5.66848E+06 + 1.68500E+02 5.81019E+06 + 1.68600E+02 5.95190E+06 + 1.68700E+02 6.09361E+06 + 1.68800E+02 6.23532E+06 + 1.68900E+02 6.37703E+06 + 1.69000E+02 6.51875E+06 + 1.69100E+02 6.66046E+06 + 1.69200E+02 6.80217E+06 + 1.69300E+02 6.94388E+06 + 1.69400E+02 7.08559E+06 + 1.69500E+02 7.22730E+06 + 1.69600E+02 7.36902E+06 + 1.69700E+02 7.51073E+06 + 1.69800E+02 7.65244E+06 + 1.69900E+02 7.79415E+06 + 1.70000E+02 7.93586E+06 + 1.70100E+02 8.07758E+06 + 1.70200E+02 8.21929E+06 + 1.70300E+02 8.36100E+06 + 1.70400E+02 8.50271E+06 + 1.70500E+02 8.50271E+06 + 1.70600E+02 7.93586E+06 + 1.70700E+02 7.36902E+06 + 1.70800E+02 6.80217E+06 + 1.70900E+02 6.23532E+06 + 1.71000E+02 5.66848E+06 + 1.71100E+02 5.24334E+06 + 1.71200E+02 5.38505E+06 + 1.71300E+02 5.52676E+06 + 1.71400E+02 5.66848E+06 + 1.71500E+02 5.81019E+06 + 1.71600E+02 5.95190E+06 + 1.71700E+02 6.09361E+06 + 1.71800E+02 6.23532E+06 + 1.71900E+02 6.37703E+06 + 1.72000E+02 6.51875E+06 + 1.72100E+02 6.66046E+06 + 1.72200E+02 6.80217E+06 + 1.72300E+02 6.94388E+06 + 1.72400E+02 7.08559E+06 + 1.72500E+02 7.22730E+06 + 1.72600E+02 7.36902E+06 + 1.72700E+02 7.51073E+06 + 1.72800E+02 7.65244E+06 + 1.72900E+02 7.79415E+06 + 1.73000E+02 7.93586E+06 + 1.73100E+02 8.07758E+06 + 1.73200E+02 8.21929E+06 + 1.73300E+02 8.36100E+06 + 1.73400E+02 8.50271E+06 + 1.73500E+02 8.50271E+06 + 1.73600E+02 7.93586E+06 + 1.73700E+02 7.36902E+06 + 1.73800E+02 6.80217E+06 + 1.73900E+02 6.23532E+06 + 1.74000E+02 5.66848E+06 + 1.74100E+02 5.24334E+06 + 1.74200E+02 5.38505E+06 + 1.74300E+02 5.52676E+06 + 1.74400E+02 5.66848E+06 + 1.74500E+02 5.81019E+06 + 1.74600E+02 5.95190E+06 + 1.74700E+02 6.09361E+06 + 1.74800E+02 6.23532E+06 + 1.74900E+02 6.37703E+06 + 1.75000E+02 6.51875E+06 + 1.75100E+02 6.66046E+06 + 1.75200E+02 6.80217E+06 + 1.75300E+02 6.94388E+06 + 1.75400E+02 7.08559E+06 + 1.75500E+02 7.22730E+06 + 1.75600E+02 7.36902E+06 + 1.75700E+02 7.51073E+06 + 1.75800E+02 7.65244E+06 + 1.75900E+02 7.79415E+06 + 1.76000E+02 7.93586E+06 + 1.76100E+02 8.07758E+06 + 1.76200E+02 8.21929E+06 + 1.76300E+02 8.36100E+06 + 1.76400E+02 8.50271E+06 + 1.76500E+02 8.50271E+06 + 1.76600E+02 7.93586E+06 + 1.76700E+02 7.36902E+06 + 1.76800E+02 6.80217E+06 + 1.76900E+02 6.23532E+06 + 1.77000E+02 5.66848E+06 + 1.77100E+02 5.24334E+06 + 1.77200E+02 5.38505E+06 + 1.77300E+02 5.52676E+06 + 1.77400E+02 5.66848E+06 + 1.77500E+02 5.81019E+06 + 1.77600E+02 5.95190E+06 + 1.77700E+02 6.09361E+06 + 1.77800E+02 6.23532E+06 + 1.77900E+02 6.37703E+06 + 1.78000E+02 6.51875E+06 + 1.78100E+02 6.66046E+06 + 1.78200E+02 6.80217E+06 + 1.78300E+02 6.94388E+06 + 1.78400E+02 7.08559E+06 + 1.78500E+02 7.22730E+06 + 1.78600E+02 7.36902E+06 + 1.78700E+02 7.51073E+06 + 1.78800E+02 7.65244E+06 + 1.78900E+02 7.79415E+06 + 1.79000E+02 7.93586E+06 + 1.79100E+02 8.07758E+06 + 1.79200E+02 8.21929E+06 + 1.79300E+02 8.36100E+06 + 1.79400E+02 8.50271E+06 + 1.79500E+02 8.50271E+06 + 1.79600E+02 7.93586E+06 + 1.79700E+02 7.36902E+06 + 1.79800E+02 6.80217E+06 + 1.79900E+02 6.23532E+06 + 1.80000E+02 5.66848E+06 + 1.80100E+02 5.24334E+06 + 1.80200E+02 5.38505E+06 + 1.80300E+02 5.52676E+06 + 1.80400E+02 5.66848E+06 + 1.80500E+02 5.81019E+06 + 1.80600E+02 5.95190E+06 + 1.80700E+02 6.09361E+06 + 1.80800E+02 6.23532E+06 + 1.80900E+02 6.37703E+06 + 1.81000E+02 6.51875E+06 + 1.81100E+02 6.66046E+06 + 1.81200E+02 6.80217E+06 + 1.81300E+02 6.94388E+06 + 1.81400E+02 7.08559E+06 + 1.81500E+02 7.22730E+06 + 1.81600E+02 7.36902E+06 + 1.81700E+02 7.51073E+06 + 1.81800E+02 7.65244E+06 + 1.81900E+02 7.79415E+06 + 1.82000E+02 7.93586E+06 + 1.82100E+02 8.07758E+06 + 1.82200E+02 8.21929E+06 + 1.82300E+02 8.36100E+06 + 1.82400E+02 8.50271E+06 + 1.82500E+02 8.50271E+06 + 1.82600E+02 7.93586E+06 + 1.82700E+02 7.36902E+06 + 1.82800E+02 6.80217E+06 + 1.82900E+02 6.23532E+06 + 1.83000E+02 5.66848E+06 + 1.83100E+02 5.24334E+06 + 1.83200E+02 5.38505E+06 + 1.83300E+02 5.52676E+06 + 1.83400E+02 5.66848E+06 + 1.83500E+02 5.81019E+06 + 1.83600E+02 5.95190E+06 + 1.83700E+02 6.09361E+06 + 1.83800E+02 6.23532E+06 + 1.83900E+02 6.37703E+06 + 1.84000E+02 6.51875E+06 + 1.84100E+02 6.66046E+06 + 1.84200E+02 6.80217E+06 + 1.84300E+02 6.94388E+06 + 1.84400E+02 7.08559E+06 + 1.84500E+02 7.22730E+06 + 1.84600E+02 7.36902E+06 + 1.84700E+02 7.51073E+06 + 1.84800E+02 7.65244E+06 + 1.84900E+02 7.79415E+06 + 1.85000E+02 7.93586E+06 + 1.85100E+02 8.07758E+06 + 1.85200E+02 8.21929E+06 + 1.85300E+02 8.36100E+06 + 1.85400E+02 8.50271E+06 + 1.85500E+02 8.50271E+06 + 1.85600E+02 7.93586E+06 + 1.85700E+02 7.36902E+06 + 1.85800E+02 6.80217E+06 + 1.85900E+02 6.23532E+06 + 1.86000E+02 5.66848E+06 + 1.86100E+02 5.24334E+06 + 1.86200E+02 5.38505E+06 + 1.86300E+02 5.52676E+06 + 1.86400E+02 5.66848E+06 + 1.86500E+02 5.81019E+06 + 1.86600E+02 5.95190E+06 + 1.86700E+02 6.09361E+06 + 1.86800E+02 6.23532E+06 + 1.86900E+02 6.37703E+06 + 1.87000E+02 6.51875E+06 + 1.87100E+02 6.66046E+06 + 1.87200E+02 6.80217E+06 + 1.87300E+02 6.94388E+06 + 1.87400E+02 7.08559E+06 + 1.87500E+02 7.22730E+06 + 1.87600E+02 7.36902E+06 + 1.87700E+02 7.51073E+06 + 1.87800E+02 7.65244E+06 + 1.87900E+02 7.79415E+06 + 1.88000E+02 7.93586E+06 + 1.88100E+02 8.07758E+06 + 1.88200E+02 8.21929E+06 + 1.88300E+02 8.36100E+06 + 1.88400E+02 8.50271E+06 + 1.88500E+02 8.50271E+06 + 1.88600E+02 7.93586E+06 + 1.88700E+02 7.36902E+06 + 1.88800E+02 6.80217E+06 + 1.88900E+02 6.23532E+06 + 1.89000E+02 5.66848E+06 + 1.89100E+02 5.24334E+06 + 1.89200E+02 5.38505E+06 + 1.89300E+02 5.52676E+06 + 1.89400E+02 5.66848E+06 + 1.89500E+02 5.81019E+06 + 1.89600E+02 5.95190E+06 + 1.89700E+02 6.09361E+06 + 1.89800E+02 6.23532E+06 + 1.89900E+02 6.37703E+06 + 1.90000E+02 6.51875E+06 + 1.90100E+02 6.66046E+06 + 1.90200E+02 6.80217E+06 + 1.90300E+02 6.94388E+06 + 1.90400E+02 7.08559E+06 + 1.90500E+02 7.22730E+06 + 1.90600E+02 7.36902E+06 + 1.90700E+02 7.51073E+06 + 1.90800E+02 7.65244E+06 + 1.90900E+02 7.79415E+06 + 1.91000E+02 7.93586E+06 + 1.91100E+02 8.07758E+06 + 1.91200E+02 8.21929E+06 + 1.91300E+02 8.36100E+06 + 1.91400E+02 8.50271E+06 + 1.91500E+02 8.50271E+06 + 1.91600E+02 7.93586E+06 + 1.91700E+02 7.36902E+06 + 1.91800E+02 6.80217E+06 + 1.91900E+02 6.23532E+06 + 1.92000E+02 5.66848E+06 + 1.92100E+02 5.24334E+06 + 1.92200E+02 5.38505E+06 + 1.92300E+02 5.52676E+06 + 1.92400E+02 5.66848E+06 + 1.92500E+02 5.81019E+06 + 1.92600E+02 5.95190E+06 + 1.92700E+02 6.09361E+06 + 1.92800E+02 6.23532E+06 + 1.92900E+02 6.37703E+06 + 1.93000E+02 6.51875E+06 + 1.93100E+02 6.66046E+06 + 1.93200E+02 6.80217E+06 + 1.93300E+02 6.94388E+06 + 1.93400E+02 7.08559E+06 + 1.93500E+02 7.22730E+06 + 1.93600E+02 7.36902E+06 + 1.93700E+02 7.51073E+06 + 1.93800E+02 7.65244E+06 + 1.93900E+02 7.79415E+06 + 1.94000E+02 7.93586E+06 + 1.94100E+02 8.07758E+06 + 1.94200E+02 8.21929E+06 + 1.94300E+02 8.36100E+06 + 1.94400E+02 8.50271E+06 + 1.94500E+02 8.50271E+06 + 1.94600E+02 7.93586E+06 + 1.94700E+02 7.36902E+06 + 1.94800E+02 6.80217E+06 + 1.94900E+02 6.23532E+06 + 1.95000E+02 5.66848E+06 + 1.95100E+02 5.24334E+06 + 1.95200E+02 5.38505E+06 + 1.95300E+02 5.52676E+06 + 1.95400E+02 5.66848E+06 + 1.95500E+02 5.81019E+06 + 1.95600E+02 5.95190E+06 + 1.95700E+02 6.09361E+06 + 1.95800E+02 6.23532E+06 + 1.95900E+02 6.37703E+06 + 1.96000E+02 6.51875E+06 + 1.96100E+02 6.66046E+06 + 1.96200E+02 6.80217E+06 + 1.96300E+02 6.94388E+06 + 1.96400E+02 7.08559E+06 + 1.96500E+02 7.22730E+06 + 1.96600E+02 7.36902E+06 + 1.96700E+02 7.51073E+06 + 1.96800E+02 7.65244E+06 + 1.96900E+02 7.79415E+06 + 1.97000E+02 7.93586E+06 + 1.97100E+02 8.07758E+06 + 1.97200E+02 8.21929E+06 + 1.97300E+02 8.36100E+06 + 1.97400E+02 8.50271E+06 + 1.97500E+02 8.50271E+06 + 1.97600E+02 7.93586E+06 + 1.97700E+02 7.36902E+06 + 1.97800E+02 6.80217E+06 + 1.97900E+02 6.23532E+06 + 1.98000E+02 5.66848E+06 + 1.98100E+02 5.24334E+06 + 1.98200E+02 5.38505E+06 + 1.98300E+02 5.52676E+06 + 1.98400E+02 5.66848E+06 + 1.98500E+02 5.81019E+06 + 1.98600E+02 5.95190E+06 + 1.98700E+02 6.09361E+06 + 1.98800E+02 6.23532E+06 + 1.98900E+02 6.37703E+06 + 1.99000E+02 6.51875E+06 + 1.99100E+02 6.66046E+06 + 1.99200E+02 6.80217E+06 + 1.99300E+02 6.94388E+06 + 1.99400E+02 7.08559E+06 + 1.99500E+02 7.22730E+06 + 1.99600E+02 7.36902E+06 + 1.99700E+02 7.51073E+06 + 1.99800E+02 7.65244E+06 + 1.99900E+02 7.79415E+06 + 2.00000E+02 7.93586E+06 + 2.00100E+02 8.07758E+06 + 2.00200E+02 8.21929E+06 + 2.00300E+02 8.36100E+06 + 2.00400E+02 8.50271E+06 + 2.00500E+02 8.50271E+06 + 2.00600E+02 7.93586E+06 + 2.00700E+02 7.36902E+06 + 2.00800E+02 6.80217E+06 + 2.00900E+02 6.23532E+06 + 2.01000E+02 5.66848E+06 + 2.01100E+02 5.24334E+06 + 2.01200E+02 5.38505E+06 + 2.01300E+02 5.52676E+06 + 2.01400E+02 5.66848E+06 + 2.01500E+02 5.81019E+06 + 2.01600E+02 5.95190E+06 + 2.01700E+02 6.09361E+06 + 2.01800E+02 6.23532E+06 + 2.01900E+02 6.37703E+06 + 2.02000E+02 6.51875E+06 + 2.02100E+02 6.66046E+06 + 2.02200E+02 6.80217E+06 + 2.02300E+02 6.94388E+06 + 2.02400E+02 7.08559E+06 + 2.02500E+02 7.22730E+06 + 2.02600E+02 7.36902E+06 + 2.02700E+02 7.51073E+06 + 2.02800E+02 7.65244E+06 + 2.02900E+02 7.79415E+06 + 2.03000E+02 7.93586E+06 + 2.03100E+02 8.07758E+06 + 2.03200E+02 8.21929E+06 + 2.03300E+02 8.36100E+06 + 2.03400E+02 8.50271E+06 + 2.03500E+02 8.50271E+06 + 2.03600E+02 7.93586E+06 + 2.03700E+02 7.36902E+06 + 2.03800E+02 6.80217E+06 + 2.03900E+02 6.23532E+06 + 2.04000E+02 5.66848E+06 + 2.04100E+02 5.24334E+06 + 2.04200E+02 5.38505E+06 + 2.04300E+02 5.52676E+06 + 2.04400E+02 5.66848E+06 + 2.04500E+02 5.81019E+06 + 2.04600E+02 5.95190E+06 + 2.04700E+02 6.09361E+06 + 2.04800E+02 6.23532E+06 + 2.04900E+02 6.37703E+06 + 2.05000E+02 6.51875E+06 + 2.05100E+02 6.66046E+06 + 2.05200E+02 6.80217E+06 + 2.05300E+02 6.94388E+06 + 2.05400E+02 7.08559E+06 + 2.05500E+02 7.22730E+06 + 2.05600E+02 7.36902E+06 + 2.05700E+02 7.51073E+06 + 2.05800E+02 7.65244E+06 + 2.05900E+02 7.79415E+06 + 2.06000E+02 7.93586E+06 + 2.06100E+02 8.07758E+06 + 2.06200E+02 8.21929E+06 + 2.06300E+02 8.36100E+06 + 2.06400E+02 8.50271E+06 + 2.06500E+02 8.50271E+06 + 2.06600E+02 7.93586E+06 + 2.06700E+02 7.36902E+06 + 2.06800E+02 6.80217E+06 + 2.06900E+02 6.23532E+06 + 2.07000E+02 5.66848E+06 + 2.07100E+02 5.24334E+06 + 2.07200E+02 5.38505E+06 + 2.07300E+02 5.52676E+06 + 2.07400E+02 5.66848E+06 + 2.07500E+02 5.81019E+06 + 2.07600E+02 5.95190E+06 + 2.07700E+02 6.09361E+06 + 2.07800E+02 6.23532E+06 + 2.07900E+02 6.37703E+06 + 2.08000E+02 6.51875E+06 + 2.08100E+02 6.66046E+06 + 2.08200E+02 6.80217E+06 + 2.08300E+02 6.94388E+06 + 2.08400E+02 7.08559E+06 + 2.08500E+02 7.22730E+06 + 2.08600E+02 7.36902E+06 + 2.08700E+02 7.51073E+06 + 2.08800E+02 7.65244E+06 + 2.08900E+02 7.79415E+06 + 2.09000E+02 7.93586E+06 + 2.09100E+02 8.07758E+06 + 2.09200E+02 8.21929E+06 + 2.09300E+02 8.36100E+06 + 2.09400E+02 8.50271E+06 + 2.09500E+02 8.50271E+06 + 2.09600E+02 7.93586E+06 + 2.09700E+02 7.36902E+06 + 2.09800E+02 6.80217E+06 + 2.09900E+02 6.23532E+06 + 2.10000E+02 5.66848E+06 + 2.10100E+02 5.24334E+06 + 2.10200E+02 5.38505E+06 + 2.10300E+02 5.52676E+06 + 2.10400E+02 5.66848E+06 + 2.10500E+02 5.81019E+06 + 2.10600E+02 5.95190E+06 + 2.10700E+02 6.09361E+06 + 2.10800E+02 6.23532E+06 + 2.10900E+02 6.37703E+06 + 2.11000E+02 6.51875E+06 + 2.11100E+02 6.66046E+06 + 2.11200E+02 6.80217E+06 + 2.11300E+02 6.94388E+06 + 2.11400E+02 7.08559E+06 + 2.11500E+02 7.22730E+06 + 2.11600E+02 7.36902E+06 + 2.11700E+02 7.51073E+06 + 2.11800E+02 7.65244E+06 + 2.11900E+02 7.79415E+06 + 2.12000E+02 7.93586E+06 + 2.12100E+02 8.07758E+06 + 2.12200E+02 8.21929E+06 + 2.12300E+02 8.36100E+06 + 2.12400E+02 8.50271E+06 + 2.12500E+02 8.50271E+06 + 2.12600E+02 7.93586E+06 + 2.12700E+02 7.36902E+06 + 2.12800E+02 6.80217E+06 + 2.12900E+02 6.23532E+06 + 2.13000E+02 5.66848E+06 + 2.13100E+02 5.24334E+06 + 2.13200E+02 5.38505E+06 + 2.13300E+02 5.52676E+06 + 2.13400E+02 5.66848E+06 + 2.13500E+02 5.81019E+06 + 2.13600E+02 5.95190E+06 + 2.13700E+02 6.09361E+06 + 2.13800E+02 6.23532E+06 + 2.13900E+02 6.37703E+06 + 2.14000E+02 6.51875E+06 + 2.14100E+02 6.66046E+06 + 2.14200E+02 6.80217E+06 + 2.14300E+02 6.94388E+06 + 2.14400E+02 7.08559E+06 + 2.14500E+02 7.22730E+06 + 2.14600E+02 7.36902E+06 + 2.14700E+02 7.51073E+06 + 2.14800E+02 7.65244E+06 + 2.14900E+02 7.79415E+06 + 2.15000E+02 7.93586E+06 + 2.15100E+02 8.07758E+06 + 2.15200E+02 8.21929E+06 + 2.15300E+02 8.36100E+06 + 2.15400E+02 8.50271E+06 + 2.15500E+02 8.50271E+06 + 2.15600E+02 7.93586E+06 + 2.15700E+02 7.36902E+06 + 2.15800E+02 6.80217E+06 + 2.15900E+02 6.23532E+06 + 2.16000E+02 5.66848E+06 + 2.16100E+02 5.24334E+06 + 2.16200E+02 5.38505E+06 + 2.16300E+02 5.52676E+06 + 2.16400E+02 5.66848E+06 + 2.16500E+02 5.81019E+06 + 2.16600E+02 5.95190E+06 + 2.16700E+02 6.09361E+06 + 2.16800E+02 6.23532E+06 + 2.16900E+02 6.37703E+06 + 2.17000E+02 6.51875E+06 + 2.17100E+02 6.66046E+06 + 2.17200E+02 6.80217E+06 + 2.17300E+02 6.94388E+06 + 2.17400E+02 7.08559E+06 + 2.17500E+02 7.22730E+06 + 2.17600E+02 7.36902E+06 + 2.17700E+02 7.51073E+06 + 2.17800E+02 7.65244E+06 + 2.17900E+02 7.79415E+06 + 2.18000E+02 7.93586E+06 + 2.18100E+02 8.07758E+06 + 2.18200E+02 8.21929E+06 + 2.18300E+02 8.36100E+06 + 2.18400E+02 8.50271E+06 + 2.18500E+02 8.50271E+06 + 2.18600E+02 7.93586E+06 + 2.18700E+02 7.36902E+06 + 2.18800E+02 6.80217E+06 + 2.18900E+02 6.23532E+06 + 2.19000E+02 5.66848E+06 + 2.19100E+02 5.24334E+06 + 2.19200E+02 5.38505E+06 + 2.19300E+02 5.52676E+06 + 2.19400E+02 5.66848E+06 + 2.19500E+02 5.81019E+06 + 2.19600E+02 5.95190E+06 + 2.19700E+02 6.09361E+06 + 2.19800E+02 6.23532E+06 + 2.19900E+02 6.37703E+06 + 2.20000E+02 6.51875E+06 + 2.20100E+02 6.66046E+06 + 2.20200E+02 6.80217E+06 + 2.20300E+02 6.94388E+06 + 2.20400E+02 7.08559E+06 + 2.20500E+02 7.22730E+06 + 2.20600E+02 7.36902E+06 + 2.20700E+02 7.51073E+06 + 2.20800E+02 7.65244E+06 + 2.20900E+02 7.79415E+06 + 2.21000E+02 7.93586E+06 + 2.21100E+02 8.07758E+06 + 2.21200E+02 8.21929E+06 + 2.21300E+02 8.36100E+06 + 2.21400E+02 8.50271E+06 + 2.21500E+02 8.50271E+06 + 2.21600E+02 7.93586E+06 + 2.21700E+02 7.36902E+06 + 2.21800E+02 6.80217E+06 + 2.21900E+02 6.23532E+06 + 2.22000E+02 5.66848E+06 + 2.22100E+02 5.24334E+06 + 2.22200E+02 5.38505E+06 + 2.22300E+02 5.52676E+06 + 2.22400E+02 5.66848E+06 + 2.22500E+02 5.81019E+06 + 2.22600E+02 5.95190E+06 + 2.22700E+02 6.09361E+06 + 2.22800E+02 6.23532E+06 + 2.22900E+02 6.37703E+06 + 2.23000E+02 6.51875E+06 + 2.23100E+02 6.66046E+06 + 2.23200E+02 6.80217E+06 + 2.23300E+02 6.94388E+06 + 2.23400E+02 7.08559E+06 + 2.23500E+02 7.22730E+06 + 2.23600E+02 7.36902E+06 + 2.23700E+02 7.51073E+06 + 2.23800E+02 7.65244E+06 + 2.23900E+02 7.79415E+06 + 2.24000E+02 7.93586E+06 + 2.24100E+02 8.07758E+06 + 2.24200E+02 8.21929E+06 + 2.24300E+02 8.36100E+06 + 2.24400E+02 8.50271E+06 + 2.24500E+02 8.50271E+06 + 2.24600E+02 7.93586E+06 + 2.24700E+02 7.36902E+06 + 2.24800E+02 6.80217E+06 + 2.24900E+02 6.23532E+06 + 2.25000E+02 5.66848E+06 + 2.25100E+02 5.24334E+06 + 2.25200E+02 5.38505E+06 + 2.25300E+02 5.52676E+06 + 2.25400E+02 5.66848E+06 + 2.25500E+02 5.81019E+06 + 2.25600E+02 5.95190E+06 + 2.25700E+02 6.09361E+06 + 2.25800E+02 6.23532E+06 + 2.25900E+02 6.37703E+06 + 2.26000E+02 6.51875E+06 + 2.26100E+02 6.66046E+06 + 2.26200E+02 6.80217E+06 + 2.26300E+02 6.94388E+06 + 2.26400E+02 7.08559E+06 + 2.26500E+02 7.22730E+06 + 2.26600E+02 7.36902E+06 + 2.26700E+02 7.51073E+06 + 2.26800E+02 7.65244E+06 + 2.26900E+02 7.79415E+06 + 2.27000E+02 7.93586E+06 + 2.27100E+02 8.07758E+06 + 2.27200E+02 8.21929E+06 + 2.27300E+02 8.36100E+06 + 2.27400E+02 8.50271E+06 + 2.27500E+02 8.50271E+06 + 2.27600E+02 7.93586E+06 + 2.27700E+02 7.36902E+06 + 2.27800E+02 6.80217E+06 + 2.27900E+02 6.23532E+06 + 2.28000E+02 5.66848E+06 + 2.28100E+02 5.24334E+06 + 2.28200E+02 5.38505E+06 + 2.28300E+02 5.52676E+06 + 2.28400E+02 5.66848E+06 + 2.28500E+02 5.81019E+06 + 2.28600E+02 5.95190E+06 + 2.28700E+02 6.09361E+06 + 2.28800E+02 6.23532E+06 + 2.28900E+02 6.37703E+06 + 2.29000E+02 6.51875E+06 + 2.29100E+02 6.66046E+06 + 2.29200E+02 6.80217E+06 + 2.29300E+02 6.94388E+06 + 2.29400E+02 7.08559E+06 + 2.29500E+02 7.22730E+06 + 2.29600E+02 7.36902E+06 + 2.29700E+02 7.51073E+06 + 2.29800E+02 7.65244E+06 + 2.29900E+02 7.79415E+06 + 2.30000E+02 7.93586E+06 + 2.30100E+02 8.07758E+06 + 2.30200E+02 8.21929E+06 + 2.30300E+02 8.36100E+06 + 2.30400E+02 8.50271E+06 + 2.30500E+02 8.50271E+06 + 2.30600E+02 7.93586E+06 + 2.30700E+02 7.36902E+06 + 2.30800E+02 6.80217E+06 + 2.30900E+02 6.23532E+06 + 2.31000E+02 5.66848E+06 + 2.31100E+02 5.24334E+06 + 2.31200E+02 5.38505E+06 + 2.31300E+02 5.52676E+06 + 2.31400E+02 5.66848E+06 + 2.31500E+02 5.81019E+06 + 2.31600E+02 5.95190E+06 + 2.31700E+02 6.09361E+06 + 2.31800E+02 6.23532E+06 + 2.31900E+02 6.37703E+06 + 2.32000E+02 6.51875E+06 + 2.32100E+02 6.66046E+06 + 2.32200E+02 6.80217E+06 + 2.32300E+02 6.94388E+06 + 2.32400E+02 7.08559E+06 + 2.32500E+02 7.22730E+06 + 2.32600E+02 7.36902E+06 + 2.32700E+02 7.51073E+06 + 2.32800E+02 7.65244E+06 + 2.32900E+02 7.79415E+06 + 2.33000E+02 7.93586E+06 + 2.33100E+02 8.07758E+06 + 2.33200E+02 8.21929E+06 + 2.33300E+02 8.36100E+06 + 2.33400E+02 8.50271E+06 + 2.33500E+02 8.50271E+06 + 2.33600E+02 7.93586E+06 + 2.33700E+02 7.36902E+06 + 2.33800E+02 6.80217E+06 + 2.33900E+02 6.23532E+06 + 2.34000E+02 5.66848E+06 + 2.34100E+02 5.24334E+06 + 2.34200E+02 5.38505E+06 + 2.34300E+02 5.52676E+06 + 2.34400E+02 5.66848E+06 + 2.34500E+02 5.81019E+06 + 2.34600E+02 5.95190E+06 + 2.34700E+02 6.09361E+06 + 2.34800E+02 6.23532E+06 + 2.34900E+02 6.37703E+06 + 2.35000E+02 6.51875E+06 + 2.35100E+02 6.66046E+06 + 2.35200E+02 6.80217E+06 + 2.35300E+02 6.94388E+06 + 2.35400E+02 7.08559E+06 + 2.35500E+02 7.22730E+06 + 2.35600E+02 7.36902E+06 + 2.35700E+02 7.51073E+06 + 2.35800E+02 7.65244E+06 + 2.35900E+02 7.79415E+06 + 2.36000E+02 7.93586E+06 + 2.36100E+02 8.07758E+06 + 2.36200E+02 8.21929E+06 + 2.36300E+02 8.36100E+06 + 2.36400E+02 8.50271E+06 + 2.36500E+02 8.50271E+06 + 2.36600E+02 7.93586E+06 + 2.36700E+02 7.36902E+06 + 2.36800E+02 6.80217E+06 + 2.36900E+02 6.23532E+06 + 2.37000E+02 5.66848E+06 + 2.37100E+02 5.24334E+06 + 2.37200E+02 5.38505E+06 + 2.37300E+02 5.52676E+06 + 2.37400E+02 5.66848E+06 + 2.37500E+02 5.81019E+06 + 2.37600E+02 5.95190E+06 + 2.37700E+02 6.09361E+06 + 2.37800E+02 6.23532E+06 + 2.37900E+02 6.37703E+06 + 2.38000E+02 6.51875E+06 + 2.38100E+02 6.66046E+06 + 2.38200E+02 6.80217E+06 + 2.38300E+02 6.94388E+06 + 2.38400E+02 7.08559E+06 + 2.38500E+02 7.22730E+06 + 2.38600E+02 7.36902E+06 + 2.38700E+02 7.51073E+06 + 2.38800E+02 7.65244E+06 + 2.38900E+02 7.79415E+06 + 2.39000E+02 7.93586E+06 + 2.39100E+02 8.07758E+06 + 2.39200E+02 8.21929E+06 + 2.39300E+02 8.36100E+06 + 2.39400E+02 8.50271E+06 + 2.39500E+02 8.50271E+06 + 2.39600E+02 7.93586E+06 + 2.39700E+02 7.36902E+06 + 2.39800E+02 6.80217E+06 + 2.39900E+02 6.23532E+06 + 2.40000E+02 5.66848E+06 + 2.40100E+02 5.24334E+06 + 2.40200E+02 5.38505E+06 + 2.40300E+02 5.52676E+06 + 2.40400E+02 5.66848E+06 + 2.40500E+02 5.81019E+06 + 2.40600E+02 5.95190E+06 + 2.40700E+02 6.09361E+06 + 2.40800E+02 6.23532E+06 + 2.40900E+02 6.37703E+06 + 2.41000E+02 6.51875E+06 + 2.41100E+02 6.66046E+06 + 2.41200E+02 6.80217E+06 + 2.41300E+02 6.94388E+06 + 2.41400E+02 7.08559E+06 + 2.41500E+02 7.22730E+06 + 2.41600E+02 7.36902E+06 + 2.41700E+02 7.51073E+06 + 2.41800E+02 7.65244E+06 + 2.41900E+02 7.79415E+06 + 2.42000E+02 7.93586E+06 + 2.42100E+02 8.07758E+06 + 2.42200E+02 8.21929E+06 + 2.42300E+02 8.36100E+06 + 2.42400E+02 8.50271E+06 + 2.42500E+02 8.50271E+06 + 2.42600E+02 7.93586E+06 + 2.42700E+02 7.36902E+06 + 2.42800E+02 6.80217E+06 + 2.42900E+02 6.23532E+06 + 2.43000E+02 5.66848E+06 + 2.43100E+02 5.24334E+06 + 2.43200E+02 5.38505E+06 + 2.43300E+02 5.52676E+06 + 2.43400E+02 5.66848E+06 + 2.43500E+02 5.81019E+06 + 2.43600E+02 5.95190E+06 + 2.43700E+02 6.09361E+06 + 2.43800E+02 6.23532E+06 + 2.43900E+02 6.37703E+06 + 2.44000E+02 6.51875E+06 + 2.44100E+02 6.66046E+06 + 2.44200E+02 6.80217E+06 + 2.44300E+02 6.94388E+06 + 2.44400E+02 7.08559E+06 + 2.44500E+02 7.22730E+06 + 2.44600E+02 7.36902E+06 + 2.44700E+02 7.51073E+06 + 2.44800E+02 7.65244E+06 + 2.44900E+02 7.79415E+06 + 2.45000E+02 7.93586E+06 + 2.45100E+02 8.07758E+06 + 2.45200E+02 8.21929E+06 + 2.45300E+02 8.36100E+06 + 2.45400E+02 8.50271E+06 + 2.45500E+02 8.50271E+06 + 2.45600E+02 7.93586E+06 + 2.45700E+02 7.36902E+06 + 2.45800E+02 6.80217E+06 + 2.45900E+02 6.23532E+06 + 2.46000E+02 5.66848E+06 + 2.46100E+02 5.24334E+06 + 2.46200E+02 5.38505E+06 + 2.46300E+02 5.52676E+06 + 2.46400E+02 5.66848E+06 + 2.46500E+02 5.81019E+06 + 2.46600E+02 5.95190E+06 + 2.46700E+02 6.09361E+06 + 2.46800E+02 6.23532E+06 + 2.46900E+02 6.37703E+06 + 2.47000E+02 6.51875E+06 + 2.47100E+02 6.66046E+06 + 2.47200E+02 6.80217E+06 + 2.47300E+02 6.94388E+06 + 2.47400E+02 7.08559E+06 + 2.47500E+02 7.22730E+06 + 2.47600E+02 7.36902E+06 + 2.47700E+02 7.51073E+06 + 2.47800E+02 7.65244E+06 + 2.47900E+02 7.79415E+06 + 2.48000E+02 7.93586E+06 + 2.48100E+02 8.07758E+06 + 2.48200E+02 8.21929E+06 + 2.48300E+02 8.36100E+06 + 2.48400E+02 8.50271E+06 + 2.48500E+02 8.50271E+06 + 2.48600E+02 7.93586E+06 + 2.48700E+02 7.36902E+06 + 2.48800E+02 6.80217E+06 + 2.48900E+02 6.23532E+06 + 2.49000E+02 5.66848E+06 + 2.49100E+02 5.24334E+06 + 2.49200E+02 5.38505E+06 + 2.49300E+02 5.52676E+06 + 2.49400E+02 5.66848E+06 + 2.49500E+02 5.81019E+06 + 2.49600E+02 5.95190E+06 + 2.49700E+02 6.09361E+06 + 2.49800E+02 6.23532E+06 + 2.49900E+02 6.37703E+06 + 2.50000E+02 6.51875E+06 + 2.50100E+02 6.66046E+06 + 2.50200E+02 6.80217E+06 + 2.50300E+02 6.94388E+06 + 2.50400E+02 7.08559E+06 + 2.50500E+02 7.22730E+06 + 2.50600E+02 7.36902E+06 + 2.50700E+02 7.51073E+06 + 2.50800E+02 7.65244E+06 + 2.50900E+02 7.79415E+06 + 2.51000E+02 7.93586E+06 + 2.51100E+02 8.07758E+06 + 2.51200E+02 8.21929E+06 + 2.51300E+02 8.36100E+06 + 2.51400E+02 8.50271E+06 + 2.51500E+02 8.50271E+06 + 2.51600E+02 7.93586E+06 + 2.51700E+02 7.36902E+06 + 2.51800E+02 6.80217E+06 + 2.51900E+02 6.23532E+06 + 2.52000E+02 5.66848E+06 + 2.52100E+02 5.24334E+06 + 2.52200E+02 5.38505E+06 + 2.52300E+02 5.52676E+06 + 2.52400E+02 5.66848E+06 + 2.52500E+02 5.81019E+06 + 2.52600E+02 5.95190E+06 + 2.52700E+02 6.09361E+06 + 2.52800E+02 6.23532E+06 + 2.52900E+02 6.37703E+06 + 2.53000E+02 6.51875E+06 + 2.53100E+02 6.66046E+06 + 2.53200E+02 6.80217E+06 + 2.53300E+02 6.94388E+06 + 2.53400E+02 7.08559E+06 + 2.53500E+02 7.22730E+06 + 2.53600E+02 7.36902E+06 + 2.53700E+02 7.51073E+06 + 2.53800E+02 7.65244E+06 + 2.53900E+02 7.79415E+06 + 2.54000E+02 7.93586E+06 + 2.54100E+02 8.07758E+06 + 2.54200E+02 8.21929E+06 + 2.54300E+02 8.36100E+06 + 2.54400E+02 8.50271E+06 + 2.54500E+02 8.50271E+06 + 2.54600E+02 7.93586E+06 + 2.54700E+02 7.36902E+06 + 2.54800E+02 6.80217E+06 + 2.54900E+02 6.23532E+06 + 2.55000E+02 5.66848E+06 + 2.55100E+02 5.24334E+06 + 2.55200E+02 5.38505E+06 + 2.55300E+02 5.52676E+06 + 2.55400E+02 5.66848E+06 + 2.55500E+02 5.81019E+06 + 2.55600E+02 5.95190E+06 + 2.55700E+02 6.09361E+06 + 2.55800E+02 6.23532E+06 + 2.55900E+02 6.37703E+06 + 2.56000E+02 6.51875E+06 + 2.56100E+02 6.66046E+06 + 2.56200E+02 6.80217E+06 + 2.56300E+02 6.94388E+06 + 2.56400E+02 7.08559E+06 + 2.56500E+02 7.22730E+06 + 2.56600E+02 7.36902E+06 + 2.56700E+02 7.51073E+06 + 2.56800E+02 7.65244E+06 + 2.56900E+02 7.79415E+06 + 2.57000E+02 7.93586E+06 + 2.57100E+02 8.07758E+06 + 2.57200E+02 8.21929E+06 + 2.57300E+02 8.36100E+06 + 2.57400E+02 8.50271E+06 + 2.57500E+02 8.50271E+06 + 2.57600E+02 7.93586E+06 + 2.57700E+02 7.36902E+06 + 2.57800E+02 6.80217E+06 + 2.57900E+02 6.23532E+06 + 2.58000E+02 5.66848E+06 + 2.58100E+02 5.24334E+06 + 2.58200E+02 5.38505E+06 + 2.58300E+02 5.52676E+06 + 2.58400E+02 5.66848E+06 + 2.58500E+02 5.81019E+06 + 2.58600E+02 5.95190E+06 + 2.58700E+02 6.09361E+06 + 2.58800E+02 6.23532E+06 + 2.58900E+02 6.37703E+06 + 2.59000E+02 6.51875E+06 + 2.59100E+02 6.66046E+06 + 2.59200E+02 6.80217E+06 + 2.59300E+02 6.94388E+06 + 2.59400E+02 7.08559E+06 + 2.59500E+02 7.22730E+06 + 2.59600E+02 7.36902E+06 + 2.59700E+02 7.51073E+06 + 2.59800E+02 7.65244E+06 + 2.59900E+02 7.79415E+06 + 2.60000E+02 7.93586E+06 + 2.60100E+02 8.07758E+06 + 2.60200E+02 8.21929E+06 + 2.60300E+02 8.36100E+06 + 2.60400E+02 8.50271E+06 + 2.60500E+02 8.50271E+06 + 2.60600E+02 7.93586E+06 + 2.60700E+02 7.36902E+06 + 2.60800E+02 6.80217E+06 + 2.60900E+02 6.23532E+06 + 2.61000E+02 5.66848E+06 + 2.61100E+02 5.24334E+06 + 2.61200E+02 5.38505E+06 + 2.61300E+02 5.52676E+06 + 2.61400E+02 5.66848E+06 + 2.61500E+02 5.81019E+06 + 2.61600E+02 5.95190E+06 + 2.61700E+02 6.09361E+06 + 2.61800E+02 6.23532E+06 + 2.61900E+02 6.37703E+06 + 2.62000E+02 6.51875E+06 + 2.62100E+02 6.66046E+06 + 2.62200E+02 6.80217E+06 + 2.62300E+02 6.94388E+06 + 2.62400E+02 7.08559E+06 + 2.62500E+02 7.22730E+06 + 2.62600E+02 7.36902E+06 + 2.62700E+02 7.51073E+06 + 2.62800E+02 7.65244E+06 + 2.62900E+02 7.79415E+06 + 2.63000E+02 7.93586E+06 + 2.63100E+02 8.07758E+06 + 2.63200E+02 8.21929E+06 + 2.63300E+02 8.36100E+06 + 2.63400E+02 8.50271E+06 + 2.63500E+02 8.50271E+06 + 2.63600E+02 7.93586E+06 + 2.63700E+02 7.36902E+06 + 2.63800E+02 6.80217E+06 + 2.63900E+02 6.23532E+06 + 2.64000E+02 5.66848E+06 + 2.64100E+02 5.24334E+06 + 2.64200E+02 5.38505E+06 + 2.64300E+02 5.52676E+06 + 2.64400E+02 5.66848E+06 + 2.64500E+02 5.81019E+06 + 2.64600E+02 5.95190E+06 + 2.64700E+02 6.09361E+06 + 2.64800E+02 6.23532E+06 + 2.64900E+02 6.37703E+06 + 2.65000E+02 6.51875E+06 + 2.65100E+02 6.66046E+06 + 2.65200E+02 6.80217E+06 + 2.65300E+02 6.94388E+06 + 2.65400E+02 7.08559E+06 + 2.65500E+02 7.22730E+06 + 2.65600E+02 7.36902E+06 + 2.65700E+02 7.51073E+06 + 2.65800E+02 7.65244E+06 + 2.65900E+02 7.79415E+06 + 2.66000E+02 7.93586E+06 + 2.66100E+02 8.07758E+06 + 2.66200E+02 8.21929E+06 + 2.66300E+02 8.36100E+06 + 2.66400E+02 8.50271E+06 + 2.66500E+02 8.50271E+06 + 2.66600E+02 7.93586E+06 + 2.66700E+02 7.36902E+06 + 2.66800E+02 6.80217E+06 + 2.66900E+02 6.23532E+06 + 2.67000E+02 5.66848E+06 + 2.67100E+02 5.24334E+06 + 2.67200E+02 5.38505E+06 + 2.67300E+02 5.52676E+06 + 2.67400E+02 5.66848E+06 + 2.67500E+02 5.81019E+06 + 2.67600E+02 5.95190E+06 + 2.67700E+02 6.09361E+06 + 2.67800E+02 6.23532E+06 + 2.67900E+02 6.37703E+06 + 2.68000E+02 6.51875E+06 + 2.68100E+02 6.66046E+06 + 2.68200E+02 6.80217E+06 + 2.68300E+02 6.94388E+06 + 2.68400E+02 7.08559E+06 + 2.68500E+02 7.22730E+06 + 2.68600E+02 7.36902E+06 + 2.68700E+02 7.51073E+06 + 2.68800E+02 7.65244E+06 + 2.68900E+02 7.79415E+06 + 2.69000E+02 7.93586E+06 + 2.69100E+02 8.07758E+06 + 2.69200E+02 8.21929E+06 + 2.69300E+02 8.36100E+06 + 2.69400E+02 8.50271E+06 + 2.69500E+02 8.50271E+06 + 2.69600E+02 7.93586E+06 + 2.69700E+02 7.36902E+06 + 2.69800E+02 6.80217E+06 + 2.69900E+02 6.23532E+06 + 2.70000E+02 5.66848E+06 + 2.70100E+02 5.24334E+06 + 2.70200E+02 5.38505E+06 + 2.70300E+02 5.52676E+06 + 2.70400E+02 5.66848E+06 + 2.70500E+02 5.81019E+06 + 2.70600E+02 5.95190E+06 + 2.70700E+02 6.09361E+06 + 2.70800E+02 6.23532E+06 + 2.70900E+02 6.37703E+06 + 2.71000E+02 6.51875E+06 + 2.71100E+02 6.66046E+06 + 2.71200E+02 6.80217E+06 + 2.71300E+02 6.94388E+06 + 2.71400E+02 7.08559E+06 + 2.71500E+02 7.22730E+06 + 2.71600E+02 7.36902E+06 + 2.71700E+02 7.51073E+06 + 2.71800E+02 7.65244E+06 + 2.71900E+02 7.79415E+06 + 2.72000E+02 7.93586E+06 + 2.72100E+02 8.07758E+06 + 2.72200E+02 8.21929E+06 + 2.72300E+02 8.36100E+06 + 2.72400E+02 8.50271E+06 + 2.72500E+02 8.50271E+06 + 2.72600E+02 7.93586E+06 + 2.72700E+02 7.36902E+06 + 2.72800E+02 6.80217E+06 + 2.72900E+02 6.23532E+06 + 2.73000E+02 5.66848E+06 + 2.73100E+02 5.24334E+06 + 2.73200E+02 5.38505E+06 + 2.73300E+02 5.52676E+06 + 2.73400E+02 5.66848E+06 + 2.73500E+02 5.81019E+06 + 2.73600E+02 5.95190E+06 + 2.73700E+02 6.09361E+06 + 2.73800E+02 6.23532E+06 + 2.73900E+02 6.37703E+06 + 2.74000E+02 6.51875E+06 + 2.74100E+02 6.66046E+06 + 2.74200E+02 6.80217E+06 + 2.74300E+02 6.94388E+06 + 2.74400E+02 7.08559E+06 + 2.74500E+02 7.22730E+06 + 2.74600E+02 7.36902E+06 + 2.74700E+02 7.51073E+06 + 2.74800E+02 7.65244E+06 + 2.74900E+02 7.79415E+06 + 2.75000E+02 7.93586E+06 + 2.75100E+02 8.07758E+06 + 2.75200E+02 8.21929E+06 + 2.75300E+02 8.36100E+06 + 2.75400E+02 8.50271E+06 + 2.75500E+02 8.50271E+06 + 2.75600E+02 7.93586E+06 + 2.75700E+02 7.36902E+06 + 2.75800E+02 6.80217E+06 + 2.75900E+02 6.23532E+06 + 2.76000E+02 5.66848E+06 + 2.76100E+02 5.24334E+06 + 2.76200E+02 5.38505E+06 + 2.76300E+02 5.52676E+06 + 2.76400E+02 5.66848E+06 + 2.76500E+02 5.81019E+06 + 2.76600E+02 5.95190E+06 + 2.76700E+02 6.09361E+06 + 2.76800E+02 6.23532E+06 + 2.76900E+02 6.37703E+06 + 2.77000E+02 6.51875E+06 + 2.77100E+02 6.66046E+06 + 2.77200E+02 6.80217E+06 + 2.77300E+02 6.94388E+06 + 2.77400E+02 7.08559E+06 + 2.77500E+02 7.22730E+06 + 2.77600E+02 7.36902E+06 + 2.77700E+02 7.51073E+06 + 2.77800E+02 7.65244E+06 + 2.77900E+02 7.79415E+06 + 2.78000E+02 7.93586E+06 + 2.78100E+02 8.07758E+06 + 2.78200E+02 8.21929E+06 + 2.78300E+02 8.36100E+06 + 2.78400E+02 8.50271E+06 + 2.78500E+02 8.50271E+06 + 2.78600E+02 7.93586E+06 + 2.78700E+02 7.36902E+06 + 2.78800E+02 6.80217E+06 + 2.78900E+02 6.23532E+06 + 2.79000E+02 5.66848E+06 + 2.79100E+02 5.24334E+06 + 2.79200E+02 5.38505E+06 + 2.79300E+02 5.52676E+06 + 2.79400E+02 5.66848E+06 + 2.79500E+02 5.81019E+06 + 2.79600E+02 5.95190E+06 + 2.79700E+02 6.09361E+06 + 2.79800E+02 6.23532E+06 + 2.79900E+02 6.37703E+06 + 2.80000E+02 6.51875E+06 + 2.80100E+02 6.66046E+06 + 2.80200E+02 6.80217E+06 + 2.80300E+02 6.94388E+06 + 2.80400E+02 7.08559E+06 + 2.80500E+02 7.22730E+06 + 2.80600E+02 7.36902E+06 + 2.80700E+02 7.51073E+06 + 2.80800E+02 7.65244E+06 + 2.80900E+02 7.79415E+06 + 2.81000E+02 7.93586E+06 + 2.81100E+02 8.07758E+06 + 2.81200E+02 8.21929E+06 + 2.81300E+02 8.36100E+06 + 2.81400E+02 8.50271E+06 + 2.81500E+02 8.50271E+06 + 2.81600E+02 7.93586E+06 + 2.81700E+02 7.36902E+06 + 2.81800E+02 6.80217E+06 + 2.81900E+02 6.23532E+06 + 2.82000E+02 5.66848E+06 + 2.82100E+02 5.24334E+06 + 2.82200E+02 5.38505E+06 + 2.82300E+02 5.52676E+06 + 2.82400E+02 5.66848E+06 + 2.82500E+02 5.81019E+06 + 2.82600E+02 5.95190E+06 + 2.82700E+02 6.09361E+06 + 2.82800E+02 6.23532E+06 + 2.82900E+02 6.37703E+06 + 2.83000E+02 6.51875E+06 + 2.83100E+02 6.66046E+06 + 2.83200E+02 6.80217E+06 + 2.83300E+02 6.94388E+06 + 2.83400E+02 7.08559E+06 + 2.83500E+02 7.22730E+06 + 2.83600E+02 7.36902E+06 + 2.83700E+02 7.51073E+06 + 2.83800E+02 7.65244E+06 + 2.83900E+02 7.79415E+06 + 2.84000E+02 7.93586E+06 + 2.84100E+02 8.07758E+06 + 2.84200E+02 8.21929E+06 + 2.84300E+02 8.36100E+06 + 2.84400E+02 8.50271E+06 + 2.84500E+02 8.50271E+06 + 2.84600E+02 7.93586E+06 + 2.84700E+02 7.36902E+06 + 2.84800E+02 6.80217E+06 + 2.84900E+02 6.23532E+06 + 2.85000E+02 5.66848E+06 + 2.85100E+02 5.24334E+06 + 2.85200E+02 5.38505E+06 + 2.85300E+02 5.52676E+06 + 2.85400E+02 5.66848E+06 + 2.85500E+02 5.81019E+06 + 2.85600E+02 5.95190E+06 + 2.85700E+02 6.09361E+06 + 2.85800E+02 6.23532E+06 + 2.85900E+02 6.37703E+06 + 2.86000E+02 6.51875E+06 + 2.86100E+02 6.66046E+06 + 2.86200E+02 6.80217E+06 + 2.86300E+02 6.94388E+06 + 2.86400E+02 7.08559E+06 + 2.86500E+02 7.22730E+06 + 2.86600E+02 7.36902E+06 + 2.86700E+02 7.51073E+06 + 2.86800E+02 7.65244E+06 + 2.86900E+02 7.79415E+06 + 2.87000E+02 7.93586E+06 + 2.87100E+02 8.07758E+06 + 2.87200E+02 8.21929E+06 + 2.87300E+02 8.36100E+06 + 2.87400E+02 8.50271E+06 + 2.87500E+02 8.50271E+06 + 2.87600E+02 7.93586E+06 + 2.87700E+02 7.36902E+06 + 2.87800E+02 6.80217E+06 + 2.87900E+02 6.23532E+06 + 2.88000E+02 5.66848E+06 + 2.88100E+02 5.24334E+06 + 2.88200E+02 5.38505E+06 + 2.88300E+02 5.52676E+06 + 2.88400E+02 5.66848E+06 + 2.88500E+02 5.81019E+06 + 2.88600E+02 5.95190E+06 + 2.88700E+02 6.09361E+06 + 2.88800E+02 6.23532E+06 + 2.88900E+02 6.37703E+06 + 2.89000E+02 6.51875E+06 + 2.89100E+02 6.66046E+06 + 2.89200E+02 6.80217E+06 + 2.89300E+02 6.94388E+06 + 2.89400E+02 7.08559E+06 + 2.89500E+02 7.22730E+06 + 2.89600E+02 7.36902E+06 + 2.89700E+02 7.51073E+06 + 2.89800E+02 7.65244E+06 + 2.89900E+02 7.79415E+06 + 2.90000E+02 7.93586E+06 + 2.90100E+02 8.07758E+06 + 2.90200E+02 8.21929E+06 + 2.90300E+02 8.36100E+06 + 2.90400E+02 8.50271E+06 + 2.90500E+02 8.50271E+06 + 2.90600E+02 7.93586E+06 + 2.90700E+02 7.36902E+06 + 2.90800E+02 6.80217E+06 + 2.90900E+02 6.23532E+06 + 2.91000E+02 5.66848E+06 + 2.91100E+02 5.24334E+06 + 2.91200E+02 5.38505E+06 + 2.91300E+02 5.52676E+06 + 2.91400E+02 5.66848E+06 + 2.91500E+02 5.81019E+06 + 2.91600E+02 5.95190E+06 + 2.91700E+02 6.09361E+06 + 2.91800E+02 6.23532E+06 + 2.91900E+02 6.37703E+06 + 2.92000E+02 6.51875E+06 + 2.92100E+02 6.66046E+06 + 2.92200E+02 6.80217E+06 + 2.92300E+02 6.94388E+06 + 2.92400E+02 7.08559E+06 + 2.92500E+02 7.22730E+06 + 2.92600E+02 7.36902E+06 + 2.92700E+02 7.51073E+06 + 2.92800E+02 7.65244E+06 + 2.92900E+02 7.79415E+06 + 2.93000E+02 7.93586E+06 + 2.93100E+02 8.07758E+06 + 2.93200E+02 8.21929E+06 + 2.93300E+02 8.36100E+06 + 2.93400E+02 8.50271E+06 + 2.93500E+02 8.50271E+06 + 2.93600E+02 7.93586E+06 + 2.93700E+02 7.36902E+06 + 2.93800E+02 6.80217E+06 + 2.93900E+02 6.23532E+06 + 2.94000E+02 5.66848E+06 + 2.94100E+02 5.24334E+06 + 2.94200E+02 5.38505E+06 + 2.94300E+02 5.52676E+06 + 2.94400E+02 5.66848E+06 + 2.94500E+02 5.81019E+06 + 2.94600E+02 5.95190E+06 + 2.94700E+02 6.09361E+06 + 2.94800E+02 6.23532E+06 + 2.94900E+02 6.37703E+06 + 2.95000E+02 6.51875E+06 + 2.95100E+02 6.66046E+06 + 2.95200E+02 6.80217E+06 + 2.95300E+02 6.94388E+06 + 2.95400E+02 7.08559E+06 + 2.95500E+02 7.22730E+06 + 2.95600E+02 7.36902E+06 + 2.95700E+02 7.51073E+06 + 2.95800E+02 7.65244E+06 + 2.95900E+02 7.79415E+06 + 2.96000E+02 7.93586E+06 + 2.96100E+02 8.07758E+06 + 2.96200E+02 8.21929E+06 + 2.96300E+02 8.36100E+06 + 2.96400E+02 8.50271E+06 + 2.96500E+02 8.50271E+06 + 2.96600E+02 7.93586E+06 + 2.96700E+02 7.36902E+06 + 2.96800E+02 6.80217E+06 + 2.96900E+02 6.23532E+06 + 2.97000E+02 5.66848E+06 + 2.97100E+02 5.24334E+06 + 2.97200E+02 5.38505E+06 + 2.97300E+02 5.52676E+06 + 2.97400E+02 5.66848E+06 + 2.97500E+02 5.81019E+06 + 2.97600E+02 5.95190E+06 + 2.97700E+02 6.09361E+06 + 2.97800E+02 6.23532E+06 + 2.97900E+02 6.37703E+06 + 2.98000E+02 6.51875E+06 + 2.98100E+02 6.66046E+06 + 2.98200E+02 6.80217E+06 + 2.98300E+02 6.94388E+06 + 2.98400E+02 7.08559E+06 + 2.98500E+02 7.22730E+06 + 2.98600E+02 7.36902E+06 + 2.98700E+02 7.51073E+06 + 2.98800E+02 7.65244E+06 + 2.98900E+02 7.79415E+06 + 2.99000E+02 7.93586E+06 + 2.99100E+02 8.07758E+06 + 2.99200E+02 8.21929E+06 + 2.99300E+02 8.36100E+06 + 2.99400E+02 8.50271E+06 + 2.99500E+02 8.50271E+06 + 2.99600E+02 7.93586E+06 + 2.99700E+02 7.36902E+06 + 2.99800E+02 6.80217E+06 + 2.99900E+02 6.23532E+06 + 3.00000E+02 5.66848E+06 + 3.00100E+02 5.24334E+06 + 3.00200E+02 5.38505E+06 + 3.00300E+02 5.52676E+06 + 3.00400E+02 5.66848E+06 + 3.00500E+02 5.81019E+06 + 3.00600E+02 5.95190E+06 + 3.00700E+02 6.09361E+06 + 3.00800E+02 6.23532E+06 + 3.00900E+02 6.37703E+06 + 3.01000E+02 6.51875E+06 + 3.01100E+02 6.66046E+06 + 3.01200E+02 6.80217E+06 + 3.01300E+02 6.94388E+06 + 3.01400E+02 7.08559E+06 + 3.01500E+02 7.22730E+06 + 3.01600E+02 7.36902E+06 + 3.01700E+02 7.51073E+06 + 3.01800E+02 7.65244E+06 + 3.01900E+02 7.79415E+06 + 3.02000E+02 7.93586E+06 + 3.02100E+02 8.07758E+06 + 3.02200E+02 8.21929E+06 + 3.02300E+02 8.36100E+06 + 3.02400E+02 8.50271E+06 + 3.02500E+02 8.50271E+06 + 3.02600E+02 7.93586E+06 + 3.02700E+02 7.36902E+06 + 3.02800E+02 6.80217E+06 + 3.02900E+02 6.23532E+06 + 3.03000E+02 5.66848E+06 + 3.03100E+02 5.24334E+06 + 3.03200E+02 5.38505E+06 + 3.03300E+02 5.52676E+06 + 3.03400E+02 5.66848E+06 + 3.03500E+02 5.81019E+06 + 3.03600E+02 5.95190E+06 + 3.03700E+02 6.09361E+06 + 3.03800E+02 6.23532E+06 + 3.03900E+02 6.37703E+06 + 3.04000E+02 6.51875E+06 + 3.04100E+02 6.66046E+06 + 3.04200E+02 6.80217E+06 + 3.04300E+02 6.94388E+06 + 3.04400E+02 7.08559E+06 + 3.04500E+02 7.22730E+06 + 3.04600E+02 7.36902E+06 + 3.04700E+02 7.51073E+06 + 3.04800E+02 7.65244E+06 + 3.04900E+02 7.79415E+06 + 3.05000E+02 7.93586E+06 + 3.05100E+02 8.07758E+06 + 3.05200E+02 8.21929E+06 + 3.05300E+02 8.36100E+06 + 3.05400E+02 8.50271E+06 + 3.05500E+02 8.50271E+06 + 3.05600E+02 7.93586E+06 + 3.05700E+02 7.36902E+06 + 3.05800E+02 6.80217E+06 + 3.05900E+02 6.23532E+06 + 3.06000E+02 5.66848E+06 + 3.06100E+02 5.24334E+06 + 3.06200E+02 5.38505E+06 + 3.06300E+02 5.52676E+06 + 3.06400E+02 5.66848E+06 + 3.06500E+02 5.81019E+06 + 3.06600E+02 5.95190E+06 + 3.06700E+02 6.09361E+06 + 3.06800E+02 6.23532E+06 + 3.06900E+02 6.37703E+06 + 3.07000E+02 6.51875E+06 + 3.07100E+02 6.66046E+06 + 3.07200E+02 6.80217E+06 + 3.07300E+02 6.94388E+06 + 3.07400E+02 7.08559E+06 + 3.07500E+02 7.22730E+06 + 3.07600E+02 7.36902E+06 + 3.07700E+02 7.51073E+06 + 3.07800E+02 7.65244E+06 + 3.07900E+02 7.79415E+06 + 3.08000E+02 7.93586E+06 + 3.08100E+02 8.07758E+06 + 3.08200E+02 8.21929E+06 + 3.08300E+02 8.36100E+06 + 3.08400E+02 8.50271E+06 + 3.08500E+02 8.50271E+06 + 3.08600E+02 7.93586E+06 + 3.08700E+02 7.36902E+06 + 3.08800E+02 6.80217E+06 + 3.08900E+02 6.23532E+06 + 3.09000E+02 5.66848E+06 + 3.09100E+02 5.24334E+06 + 3.09200E+02 5.38505E+06 + 3.09300E+02 5.52676E+06 + 3.09400E+02 5.66848E+06 + 3.09500E+02 5.81019E+06 + 3.09600E+02 5.95190E+06 + 3.09700E+02 6.09361E+06 + 3.09800E+02 6.23532E+06 + 3.09900E+02 6.37703E+06 + 3.10000E+02 6.51875E+06 + 3.10100E+02 6.66046E+06 + 3.10200E+02 6.80217E+06 + 3.10300E+02 6.94388E+06 + 3.10400E+02 7.08559E+06 + 3.10500E+02 7.22730E+06 + 3.10600E+02 7.36902E+06 + 3.10700E+02 7.51073E+06 + 3.10800E+02 7.65244E+06 + 3.10900E+02 7.79415E+06 + 3.11000E+02 7.93586E+06 + 3.11100E+02 8.07758E+06 + 3.11200E+02 8.21929E+06 + 3.11300E+02 8.36100E+06 + 3.11400E+02 8.50271E+06 + 3.11500E+02 8.50271E+06 + 3.11600E+02 7.93586E+06 + 3.11700E+02 7.36902E+06 + 3.11800E+02 6.80217E+06 + 3.11900E+02 6.23532E+06 + 3.12000E+02 5.66848E+06 + 3.12100E+02 5.24334E+06 + 3.12200E+02 5.38505E+06 + 3.12300E+02 5.52676E+06 + 3.12400E+02 5.66848E+06 + 3.12500E+02 5.81019E+06 + 3.12600E+02 5.95190E+06 + 3.12700E+02 6.09361E+06 + 3.12800E+02 6.23532E+06 + 3.12900E+02 6.37703E+06 + 3.13000E+02 6.51875E+06 + 3.13100E+02 6.66046E+06 + 3.13200E+02 6.80217E+06 + 3.13300E+02 6.94388E+06 + 3.13400E+02 7.08559E+06 + 3.13500E+02 7.22730E+06 + 3.13600E+02 7.36902E+06 + 3.13700E+02 7.51073E+06 + 3.13800E+02 7.65244E+06 + 3.13900E+02 7.79415E+06 + 3.14000E+02 7.93586E+06 + 3.14100E+02 8.07758E+06 + 3.14200E+02 8.21929E+06 + 3.14300E+02 8.36100E+06 + 3.14400E+02 8.50271E+06 + 3.14500E+02 8.50271E+06 + 3.14600E+02 7.93586E+06 + 3.14700E+02 7.36902E+06 + 3.14800E+02 6.80217E+06 + 3.14900E+02 6.23532E+06 + 3.15000E+02 5.66848E+06 + 3.15100E+02 5.24334E+06 + 3.15200E+02 5.38505E+06 + 3.15300E+02 5.52676E+06 + 3.15400E+02 5.66848E+06 + 3.15500E+02 5.81019E+06 + 3.15600E+02 5.95190E+06 + 3.15700E+02 6.09361E+06 + 3.15800E+02 6.23532E+06 + 3.15900E+02 6.37703E+06 + 3.16000E+02 6.51875E+06 + 3.16100E+02 6.66046E+06 + 3.16200E+02 6.80217E+06 + 3.16300E+02 6.94388E+06 + 3.16400E+02 7.08559E+06 + 3.16500E+02 7.22730E+06 + 3.16600E+02 7.36902E+06 + 3.16700E+02 7.51073E+06 + 3.16800E+02 7.65244E+06 + 3.16900E+02 7.79415E+06 + 3.17000E+02 7.93586E+06 + 3.17100E+02 8.07758E+06 + 3.17200E+02 8.21929E+06 + 3.17300E+02 8.36100E+06 + 3.17400E+02 8.50271E+06 + 3.17500E+02 8.50271E+06 + 3.17600E+02 7.93586E+06 + 3.17700E+02 7.36902E+06 + 3.17800E+02 6.80217E+06 + 3.17900E+02 6.23532E+06 + 3.18000E+02 5.66848E+06 + 3.18100E+02 5.24334E+06 + 3.18200E+02 5.38505E+06 + 3.18300E+02 5.52676E+06 + 3.18400E+02 5.66848E+06 + 3.18500E+02 5.81019E+06 + 3.18600E+02 5.95190E+06 + 3.18700E+02 6.09361E+06 + 3.18800E+02 6.23532E+06 + 3.18900E+02 6.37703E+06 + 3.19000E+02 6.51875E+06 + 3.19100E+02 6.66046E+06 + 3.19200E+02 6.80217E+06 + 3.19300E+02 6.94388E+06 + 3.19400E+02 7.08559E+06 + 3.19500E+02 7.22730E+06 + 3.19600E+02 7.36902E+06 + 3.19700E+02 7.51073E+06 + 3.19800E+02 7.65244E+06 + 3.19900E+02 7.79415E+06 + 3.20000E+02 7.93586E+06 + 3.20100E+02 8.07758E+06 + 3.20200E+02 8.21929E+06 + 3.20300E+02 8.36100E+06 + 3.20400E+02 8.50271E+06 + 3.20500E+02 8.50271E+06 + 3.20600E+02 7.93586E+06 + 3.20700E+02 7.36902E+06 + 3.20800E+02 6.80217E+06 + 3.20900E+02 6.23532E+06 + 3.21000E+02 5.66848E+06 + 3.21100E+02 5.24334E+06 + 3.21200E+02 5.38505E+06 + 3.21300E+02 5.52676E+06 + 3.21400E+02 5.66848E+06 + 3.21500E+02 5.81019E+06 + 3.21600E+02 5.95190E+06 + 3.21700E+02 6.09361E+06 + 3.21800E+02 6.23532E+06 + 3.21900E+02 6.37703E+06 + 3.22000E+02 6.51875E+06 + 3.22100E+02 6.66046E+06 + 3.22200E+02 6.80217E+06 + 3.22300E+02 6.94388E+06 + 3.22400E+02 7.08559E+06 + 3.22500E+02 7.22730E+06 + 3.22600E+02 7.36902E+06 + 3.22700E+02 7.51073E+06 + 3.22800E+02 7.65244E+06 + 3.22900E+02 7.79415E+06 + 3.23000E+02 7.93586E+06 + 3.23100E+02 8.07758E+06 + 3.23200E+02 8.21929E+06 + 3.23300E+02 8.36100E+06 + 3.23400E+02 8.50271E+06 + 3.23500E+02 8.50271E+06 + 3.23600E+02 7.93586E+06 + 3.23700E+02 7.36902E+06 + 3.23800E+02 6.80217E+06 + 3.23900E+02 6.23532E+06 + 3.24000E+02 5.66848E+06 + 3.24100E+02 5.24334E+06 + 3.24200E+02 5.38505E+06 + 3.24300E+02 5.52676E+06 + 3.24400E+02 5.66848E+06 + 3.24500E+02 5.81019E+06 + 3.24600E+02 5.95190E+06 + 3.24700E+02 6.09361E+06 + 3.24800E+02 6.23532E+06 + 3.24900E+02 6.37703E+06 + 3.25000E+02 6.51875E+06 + 3.25100E+02 6.66046E+06 + 3.25200E+02 6.80217E+06 + 3.25300E+02 6.94388E+06 + 3.25400E+02 7.08559E+06 + 3.25500E+02 7.22730E+06 + 3.25600E+02 7.36902E+06 + 3.25700E+02 7.51073E+06 + 3.25800E+02 7.65244E+06 + 3.25900E+02 7.79415E+06 + 3.26000E+02 7.93586E+06 + 3.26100E+02 8.07758E+06 + 3.26200E+02 8.21929E+06 + 3.26300E+02 8.36100E+06 + 3.26400E+02 8.50271E+06 + 3.26500E+02 8.50271E+06 + 3.26600E+02 7.93586E+06 + 3.26700E+02 7.36902E+06 + 3.26800E+02 6.80217E+06 + 3.26900E+02 6.23532E+06 + 3.27000E+02 5.66848E+06 + 3.27100E+02 5.24334E+06 + 3.27200E+02 5.38505E+06 + 3.27300E+02 5.52676E+06 + 3.27400E+02 5.66848E+06 + 3.27500E+02 5.81019E+06 + 3.27600E+02 5.95190E+06 + 3.27700E+02 6.09361E+06 + 3.27800E+02 6.23532E+06 + 3.27900E+02 6.37703E+06 + 3.28000E+02 6.51875E+06 + 3.28100E+02 6.66046E+06 + 3.28200E+02 6.80217E+06 + 3.28300E+02 6.94388E+06 + 3.28400E+02 7.08559E+06 + 3.28500E+02 7.22730E+06 + 3.28600E+02 7.36902E+06 + 3.28700E+02 7.51073E+06 + 3.28800E+02 7.65244E+06 + 3.28900E+02 7.79415E+06 + 3.29000E+02 7.93586E+06 + 3.29100E+02 8.07758E+06 + 3.29200E+02 8.21929E+06 + 3.29300E+02 8.36100E+06 + 3.29400E+02 8.50271E+06 + 3.29500E+02 8.50271E+06 + 3.29600E+02 7.93586E+06 + 3.29700E+02 7.36902E+06 + 3.29800E+02 6.80217E+06 + 3.29900E+02 6.23532E+06 + 3.30000E+02 5.66848E+06 + 3.30100E+02 5.24334E+06 + 3.30200E+02 5.38505E+06 + 3.30300E+02 5.52676E+06 + 3.30400E+02 5.66848E+06 + 3.30500E+02 5.81019E+06 + 3.30600E+02 5.95190E+06 + 3.30700E+02 6.09361E+06 + 3.30800E+02 6.23532E+06 + 3.30900E+02 6.37703E+06 + 3.31000E+02 6.51875E+06 + 3.31100E+02 6.66046E+06 + 3.31200E+02 6.80217E+06 + 3.31300E+02 6.94388E+06 + 3.31400E+02 7.08559E+06 + 3.31500E+02 7.22730E+06 + 3.31600E+02 7.36902E+06 + 3.31700E+02 7.51073E+06 + 3.31800E+02 7.65244E+06 + 3.31900E+02 7.79415E+06 + 3.32000E+02 7.93586E+06 + 3.32100E+02 8.07758E+06 + 3.32200E+02 8.21929E+06 + 3.32300E+02 8.36100E+06 + 3.32400E+02 8.50271E+06 + 3.32500E+02 8.50271E+06 + 3.32600E+02 7.93586E+06 + 3.32700E+02 7.36902E+06 + 3.32800E+02 6.80217E+06 + 3.32900E+02 6.23532E+06 + 3.33000E+02 5.66848E+06 + 3.33100E+02 5.24334E+06 + 3.33200E+02 5.38505E+06 + 3.33300E+02 5.52676E+06 + 3.33400E+02 5.66848E+06 + 3.33500E+02 5.81019E+06 + 3.33600E+02 5.95190E+06 + 3.33700E+02 6.09361E+06 + 3.33800E+02 6.23532E+06 + 3.33900E+02 6.37703E+06 + 3.34000E+02 6.51875E+06 + 3.34100E+02 6.66046E+06 + 3.34200E+02 6.80217E+06 + 3.34300E+02 6.94388E+06 + 3.34400E+02 7.08559E+06 + 3.34500E+02 7.22730E+06 + 3.34600E+02 7.36902E+06 + 3.34700E+02 7.51073E+06 + 3.34800E+02 7.65244E+06 + 3.34900E+02 7.79415E+06 + 3.35000E+02 7.93586E+06 + 3.35100E+02 8.07758E+06 + 3.35200E+02 8.21929E+06 + 3.35300E+02 8.36100E+06 + 3.35400E+02 8.50271E+06 + 3.35500E+02 8.50271E+06 + 3.35600E+02 7.93586E+06 + 3.35700E+02 7.36902E+06 + 3.35800E+02 6.80217E+06 + 3.35900E+02 6.23532E+06 + 3.36000E+02 5.66848E+06 + 3.36100E+02 5.24334E+06 + 3.36200E+02 5.38505E+06 + 3.36300E+02 5.52676E+06 + 3.36400E+02 5.66848E+06 + 3.36500E+02 5.81019E+06 + 3.36600E+02 5.95190E+06 + 3.36700E+02 6.09361E+06 + 3.36800E+02 6.23532E+06 + 3.36900E+02 6.37703E+06 + 3.37000E+02 6.51875E+06 + 3.37100E+02 6.66046E+06 + 3.37200E+02 6.80217E+06 + 3.37300E+02 6.94388E+06 + 3.37400E+02 7.08559E+06 + 3.37500E+02 7.22730E+06 + 3.37600E+02 7.36902E+06 + 3.37700E+02 7.51073E+06 + 3.37800E+02 7.65244E+06 + 3.37900E+02 7.79415E+06 + 3.38000E+02 7.93586E+06 + 3.38100E+02 8.07758E+06 + 3.38200E+02 8.21929E+06 + 3.38300E+02 8.36100E+06 + 3.38400E+02 8.50271E+06 + 3.38500E+02 8.50271E+06 + 3.38600E+02 7.93586E+06 + 3.38700E+02 7.36902E+06 + 3.38800E+02 6.80217E+06 + 3.38900E+02 6.23532E+06 + 3.39000E+02 5.66848E+06 + 3.39100E+02 5.24334E+06 + 3.39200E+02 5.38505E+06 + 3.39300E+02 5.52676E+06 + 3.39400E+02 5.66848E+06 + 3.39500E+02 5.81019E+06 + 3.39600E+02 5.95190E+06 + 3.39700E+02 6.09361E+06 + 3.39800E+02 6.23532E+06 + 3.39900E+02 6.37703E+06 + 3.40000E+02 6.51875E+06 + 3.40100E+02 6.66046E+06 + 3.40200E+02 6.80217E+06 + 3.40300E+02 6.94388E+06 + 3.40400E+02 7.08559E+06 + 3.40500E+02 7.22730E+06 + 3.40600E+02 7.36902E+06 + 3.40700E+02 7.51073E+06 + 3.40800E+02 7.65244E+06 + 3.40900E+02 7.79415E+06 + 3.41000E+02 7.93586E+06 + 3.41100E+02 8.07758E+06 + 3.41200E+02 8.21929E+06 + 3.41300E+02 8.36100E+06 + 3.41400E+02 8.50271E+06 + 3.41500E+02 8.50271E+06 + 3.41600E+02 7.93586E+06 + 3.41700E+02 7.36902E+06 + 3.41800E+02 6.80217E+06 + 3.41900E+02 6.23532E+06 + 3.42000E+02 5.66848E+06 + 3.42100E+02 5.24334E+06 + 3.42200E+02 5.38505E+06 + 3.42300E+02 5.52676E+06 + 3.42400E+02 5.66848E+06 + 3.42500E+02 5.81019E+06 + 3.42600E+02 5.95190E+06 + 3.42700E+02 6.09361E+06 + 3.42800E+02 6.23532E+06 + 3.42900E+02 6.37703E+06 + 3.43000E+02 6.51875E+06 + 3.43100E+02 6.66046E+06 + 3.43200E+02 6.80217E+06 + 3.43300E+02 6.94388E+06 + 3.43400E+02 7.08559E+06 + 3.43500E+02 7.22730E+06 + 3.43600E+02 7.36902E+06 + 3.43700E+02 7.51073E+06 + 3.43800E+02 7.65244E+06 + 3.43900E+02 7.79415E+06 + 3.44000E+02 7.93586E+06 + 3.44100E+02 8.07758E+06 + 3.44200E+02 8.21929E+06 + 3.44300E+02 8.36100E+06 + 3.44400E+02 8.50271E+06 + 3.44500E+02 8.50271E+06 + 3.44600E+02 7.93586E+06 + 3.44700E+02 7.36902E+06 + 3.44800E+02 6.80217E+06 + 3.44900E+02 6.23532E+06 + 3.45000E+02 5.66848E+06 + 3.45100E+02 5.24334E+06 + 3.45200E+02 5.38505E+06 + 3.45300E+02 5.52676E+06 + 3.45400E+02 5.66848E+06 + 3.45500E+02 5.81019E+06 + 3.45600E+02 5.95190E+06 + 3.45700E+02 6.09361E+06 + 3.45800E+02 6.23532E+06 + 3.45900E+02 6.37703E+06 + 3.46000E+02 6.51875E+06 + 3.46100E+02 6.66046E+06 + 3.46200E+02 6.80217E+06 + 3.46300E+02 6.94388E+06 + 3.46400E+02 7.08559E+06 + 3.46500E+02 7.22730E+06 + 3.46600E+02 7.36902E+06 + 3.46700E+02 7.51073E+06 + 3.46800E+02 7.65244E+06 + 3.46900E+02 7.79415E+06 + 3.47000E+02 7.93586E+06 + 3.47100E+02 8.07758E+06 + 3.47200E+02 8.21929E+06 + 3.47300E+02 8.36100E+06 + 3.47400E+02 8.50271E+06 + 3.47500E+02 8.50271E+06 + 3.47600E+02 7.93586E+06 + 3.47700E+02 7.36902E+06 + 3.47800E+02 6.80217E+06 + 3.47900E+02 6.23532E+06 + 3.48000E+02 5.66848E+06 + 3.48100E+02 5.24334E+06 + 3.48200E+02 5.38505E+06 + 3.48300E+02 5.52676E+06 + 3.48400E+02 5.66848E+06 + 3.48500E+02 5.81019E+06 + 3.48600E+02 5.95190E+06 + 3.48700E+02 6.09361E+06 + 3.48800E+02 6.23532E+06 + 3.48900E+02 6.37703E+06 + 3.49000E+02 6.51875E+06 + 3.49100E+02 6.66046E+06 + 3.49200E+02 6.80217E+06 + 3.49300E+02 6.94388E+06 + 3.49400E+02 7.08559E+06 + 3.49500E+02 7.22730E+06 + 3.49600E+02 7.36902E+06 + 3.49700E+02 7.51073E+06 + 3.49800E+02 7.65244E+06 + 3.49900E+02 7.79415E+06 + 3.50000E+02 7.93586E+06 + 3.50100E+02 8.07758E+06 + 3.50200E+02 8.21929E+06 + 3.50300E+02 8.36100E+06 + 3.50400E+02 8.50271E+06 + 3.50500E+02 8.50271E+06 + 3.50600E+02 7.93586E+06 + 3.50700E+02 7.36902E+06 + 3.50800E+02 6.80217E+06 + 3.50900E+02 6.23532E+06 + 3.51000E+02 5.66848E+06 + 3.51100E+02 5.24334E+06 + 3.51200E+02 5.38505E+06 + 3.51300E+02 5.52676E+06 + 3.51400E+02 5.66848E+06 + 3.51500E+02 5.81019E+06 + 3.51600E+02 5.95190E+06 + 3.51700E+02 6.09361E+06 + 3.51800E+02 6.23532E+06 + 3.51900E+02 6.37703E+06 + 3.52000E+02 6.51875E+06 + 3.52100E+02 6.66046E+06 + 3.52200E+02 6.80217E+06 + 3.52300E+02 6.94388E+06 + 3.52400E+02 7.08559E+06 + 3.52500E+02 7.22730E+06 + 3.52600E+02 7.36902E+06 + 3.52700E+02 7.51073E+06 + 3.52800E+02 7.65244E+06 + 3.52900E+02 7.79415E+06 + 3.53000E+02 7.93586E+06 + 3.53100E+02 8.07758E+06 + 3.53200E+02 8.21929E+06 + 3.53300E+02 8.36100E+06 + 3.53400E+02 8.50271E+06 + 3.53500E+02 8.50271E+06 + 3.53600E+02 7.93586E+06 + 3.53700E+02 7.36902E+06 + 3.53800E+02 6.80217E+06 + 3.53900E+02 6.23532E+06 + 3.54000E+02 5.66848E+06 + 3.54100E+02 5.24334E+06 + 3.54200E+02 5.38505E+06 + 3.54300E+02 5.52676E+06 + 3.54400E+02 5.66848E+06 + 3.54500E+02 5.81019E+06 + 3.54600E+02 5.95190E+06 + 3.54700E+02 6.09361E+06 + 3.54800E+02 6.23532E+06 + 3.54900E+02 6.37703E+06 + 3.55000E+02 6.51875E+06 + 3.55100E+02 6.66046E+06 + 3.55200E+02 6.80217E+06 + 3.55300E+02 6.94388E+06 + 3.55400E+02 7.08559E+06 + 3.55500E+02 7.22730E+06 + 3.55600E+02 7.36902E+06 + 3.55700E+02 7.51073E+06 + 3.55800E+02 7.65244E+06 + 3.55900E+02 7.79415E+06 + 3.56000E+02 7.93586E+06 + 3.56100E+02 8.07758E+06 + 3.56200E+02 8.21929E+06 + 3.56300E+02 8.36100E+06 + 3.56400E+02 8.50271E+06 + 3.56500E+02 8.50271E+06 + 3.56600E+02 7.93586E+06 + 3.56700E+02 7.36902E+06 + 3.56800E+02 6.80217E+06 + 3.56900E+02 6.23532E+06 + 3.57000E+02 5.66848E+06 + 3.57100E+02 5.24334E+06 + 3.57200E+02 5.38505E+06 + 3.57300E+02 5.52676E+06 + 3.57400E+02 5.66848E+06 + 3.57500E+02 5.81019E+06 + 3.57600E+02 5.95190E+06 + 3.57700E+02 6.09361E+06 + 3.57800E+02 6.23532E+06 + 3.57900E+02 6.37703E+06 + 3.58000E+02 6.51875E+06 + 3.58100E+02 6.66046E+06 + 3.58200E+02 6.80217E+06 + 3.58300E+02 6.94388E+06 + 3.58400E+02 7.08559E+06 + 3.58500E+02 7.22730E+06 + 3.58600E+02 7.36902E+06 + 3.58700E+02 7.51073E+06 + 3.58800E+02 7.65244E+06 + 3.58900E+02 7.79415E+06 + 3.59000E+02 7.93586E+06 + 3.59100E+02 8.07758E+06 + 3.59200E+02 8.21929E+06 + 3.59300E+02 8.36100E+06 + 3.59400E+02 8.50271E+06 + 3.59500E+02 8.50271E+06 + 3.59600E+02 7.93586E+06 + 3.59700E+02 7.36902E+06 + 3.59800E+02 6.80217E+06 + 3.59900E+02 6.23532E+06 + 3.60000E+02 5.66848E+06 + 3.60100E+02 5.24334E+06 + 3.60200E+02 5.38505E+06 + 3.60300E+02 5.52676E+06 + 3.60400E+02 5.66848E+06 + 3.60500E+02 5.81019E+06 + 3.60600E+02 5.95190E+06 + 3.60700E+02 6.09361E+06 + 3.60800E+02 6.23532E+06 + 3.60900E+02 6.37703E+06 + 3.61000E+02 6.51875E+06 + 3.61100E+02 6.66046E+06 + 3.61200E+02 6.80217E+06 + 3.61300E+02 6.94388E+06 + 3.61400E+02 7.08559E+06 + 3.61500E+02 7.22730E+06 + 3.61600E+02 7.36902E+06 + 3.61700E+02 7.51073E+06 + 3.61800E+02 7.65244E+06 + 3.61900E+02 7.79415E+06 + 3.62000E+02 7.93586E+06 + 3.62100E+02 8.07758E+06 + 3.62200E+02 8.21929E+06 + 3.62300E+02 8.36100E+06 + 3.62400E+02 8.50271E+06 + 3.62500E+02 8.50271E+06 + 3.62600E+02 7.93586E+06 + 3.62700E+02 7.36902E+06 + 3.62800E+02 6.80217E+06 + 3.62900E+02 6.23532E+06 + 3.63000E+02 5.66848E+06 + 3.63100E+02 5.24334E+06 + 3.63200E+02 5.38505E+06 + 3.63300E+02 5.52676E+06 + 3.63400E+02 5.66848E+06 + 3.63500E+02 5.81019E+06 + 3.63600E+02 5.95190E+06 + 3.63700E+02 6.09361E+06 + 3.63800E+02 6.23532E+06 + 3.63900E+02 6.37703E+06 + 3.64000E+02 6.51875E+06 + 3.64100E+02 6.66046E+06 + 3.64200E+02 6.80217E+06 + 3.64300E+02 6.94388E+06 + 3.64400E+02 7.08559E+06 + 3.64500E+02 7.22730E+06 + 3.64600E+02 7.36902E+06 + 3.64700E+02 7.51073E+06 + 3.64800E+02 7.65244E+06 + 3.64900E+02 7.79415E+06 + 3.65000E+02 7.93586E+06 + 3.65100E+02 8.07758E+06 + 3.65200E+02 8.21929E+06 + 3.65300E+02 8.36100E+06 + 3.65400E+02 8.50271E+06 + 3.65500E+02 8.50271E+06 + 3.65600E+02 7.93586E+06 + 3.65700E+02 7.36902E+06 + 3.65800E+02 6.80217E+06 + 3.65900E+02 6.23532E+06 + 3.66000E+02 5.66848E+06 + 3.66100E+02 5.24334E+06 + 3.66200E+02 5.38505E+06 + 3.66300E+02 5.52676E+06 + 3.66400E+02 5.66848E+06 + 3.66500E+02 5.81019E+06 + 3.66600E+02 5.95190E+06 + 3.66700E+02 6.09361E+06 + 3.66800E+02 6.23532E+06 + 3.66900E+02 6.37703E+06 + 3.67000E+02 6.51875E+06 + 3.67100E+02 6.66046E+06 + 3.67200E+02 6.80217E+06 + 3.67300E+02 6.94388E+06 + 3.67400E+02 7.08559E+06 + 3.67500E+02 7.22730E+06 + 3.67600E+02 7.36902E+06 + 3.67700E+02 7.51073E+06 + 3.67800E+02 7.65244E+06 + 3.67900E+02 7.79415E+06 + 3.68000E+02 7.93586E+06 + 3.68100E+02 8.07758E+06 + 3.68200E+02 8.21929E+06 + 3.68300E+02 8.36100E+06 + 3.68400E+02 8.50271E+06 + 3.68500E+02 8.50271E+06 + 3.68600E+02 7.93586E+06 + 3.68700E+02 7.36902E+06 + 3.68800E+02 6.80217E+06 + 3.68900E+02 6.23532E+06 + 3.69000E+02 5.66848E+06 + 3.69100E+02 5.24334E+06 + 3.69200E+02 5.38505E+06 + 3.69300E+02 5.52676E+06 + 3.69400E+02 5.66848E+06 + 3.69500E+02 5.81019E+06 + 3.69600E+02 5.95190E+06 + 3.69700E+02 6.09361E+06 + 3.69800E+02 6.23532E+06 + 3.69900E+02 6.37703E+06 + 3.70000E+02 6.51875E+06 + 3.70100E+02 6.66046E+06 + 3.70200E+02 6.80217E+06 + 3.70300E+02 6.94388E+06 + 3.70400E+02 7.08559E+06 + 3.70500E+02 7.22730E+06 + 3.70600E+02 7.36902E+06 + 3.70700E+02 7.51073E+06 + 3.70800E+02 7.65244E+06 + 3.70900E+02 7.79415E+06 + 3.71000E+02 7.93586E+06 + 3.71100E+02 8.07758E+06 + 3.71200E+02 8.21929E+06 + 3.71300E+02 8.36100E+06 + 3.71400E+02 8.50271E+06 + 3.71500E+02 8.50271E+06 + 3.71600E+02 7.93586E+06 + 3.71700E+02 7.36902E+06 + 3.71800E+02 6.80217E+06 + 3.71900E+02 6.23532E+06 + 3.72000E+02 5.66848E+06 + 3.72100E+02 5.24334E+06 + 3.72200E+02 5.38505E+06 + 3.72300E+02 5.52676E+06 + 3.72400E+02 5.66848E+06 + 3.72500E+02 5.81019E+06 + 3.72600E+02 5.95190E+06 + 3.72700E+02 6.09361E+06 + 3.72800E+02 6.23532E+06 + 3.72900E+02 6.37703E+06 + 3.73000E+02 6.51875E+06 + 3.73100E+02 6.66046E+06 + 3.73200E+02 6.80217E+06 + 3.73300E+02 6.94388E+06 + 3.73400E+02 7.08559E+06 + 3.73500E+02 7.22730E+06 + 3.73600E+02 7.36902E+06 + 3.73700E+02 7.51073E+06 + 3.73800E+02 7.65244E+06 + 3.73900E+02 7.79415E+06 + 3.74000E+02 7.93586E+06 + 3.74100E+02 8.07758E+06 + 3.74200E+02 8.21929E+06 + 3.74300E+02 8.36100E+06 + 3.74400E+02 8.50271E+06 + 3.74500E+02 8.50271E+06 + 3.74600E+02 7.93586E+06 + 3.74700E+02 7.36902E+06 + 3.74800E+02 6.80217E+06 + 3.74900E+02 6.23532E+06 + 3.75000E+02 5.66848E+06 + 3.75100E+02 5.24334E+06 + 3.75200E+02 5.38505E+06 + 3.75300E+02 5.52676E+06 + 3.75400E+02 5.66848E+06 + 3.75500E+02 5.81019E+06 + 3.75600E+02 5.95190E+06 + 3.75700E+02 6.09361E+06 + 3.75800E+02 6.23532E+06 + 3.75900E+02 6.37703E+06 + 3.76000E+02 6.51875E+06 + 3.76100E+02 6.66046E+06 + 3.76200E+02 6.80217E+06 + 3.76300E+02 6.94388E+06 + 3.76400E+02 7.08559E+06 + 3.76500E+02 7.22730E+06 + 3.76600E+02 7.36902E+06 + 3.76700E+02 7.51073E+06 + 3.76800E+02 7.65244E+06 + 3.76900E+02 7.79415E+06 + 3.77000E+02 7.93586E+06 + 3.77100E+02 8.07758E+06 + 3.77200E+02 8.21929E+06 + 3.77300E+02 8.36100E+06 + 3.77400E+02 8.50271E+06 + 3.77500E+02 8.50271E+06 + 3.77600E+02 7.93586E+06 + 3.77700E+02 7.36902E+06 + 3.77800E+02 6.80217E+06 + 3.77900E+02 6.23532E+06 + 3.78000E+02 5.66848E+06 + 3.78100E+02 5.24334E+06 + 3.78200E+02 5.38505E+06 + 3.78300E+02 5.52676E+06 + 3.78400E+02 5.66848E+06 + 3.78500E+02 5.81019E+06 + 3.78600E+02 5.95190E+06 + 3.78700E+02 6.09361E+06 + 3.78800E+02 6.23532E+06 + 3.78900E+02 6.37703E+06 + 3.79000E+02 6.51875E+06 + 3.79100E+02 6.66046E+06 + 3.79200E+02 6.80217E+06 + 3.79300E+02 6.94388E+06 + 3.79400E+02 7.08559E+06 + 3.79500E+02 7.22730E+06 + 3.79600E+02 7.36902E+06 + 3.79700E+02 7.51073E+06 + 3.79800E+02 7.65244E+06 + 3.79900E+02 7.79415E+06 + 3.80000E+02 7.93586E+06 + 3.80100E+02 8.07758E+06 + 3.80200E+02 8.21929E+06 + 3.80300E+02 8.36100E+06 + 3.80400E+02 8.50271E+06 + 3.80500E+02 8.50271E+06 + 3.80600E+02 7.93586E+06 + 3.80700E+02 7.36902E+06 + 3.80800E+02 6.80217E+06 + 3.80900E+02 6.23532E+06 + 3.81000E+02 5.66848E+06 + 3.81100E+02 5.24334E+06 + 3.81200E+02 5.38505E+06 + 3.81300E+02 5.52676E+06 + 3.81400E+02 5.66848E+06 + 3.81500E+02 5.81019E+06 + 3.81600E+02 5.95190E+06 + 3.81700E+02 6.09361E+06 + 3.81800E+02 6.23532E+06 + 3.81900E+02 6.37703E+06 + 3.82000E+02 6.51875E+06 + 3.82100E+02 6.66046E+06 + 3.82200E+02 6.80217E+06 + 3.82300E+02 6.94388E+06 + 3.82400E+02 7.08559E+06 + 3.82500E+02 7.22730E+06 + 3.82600E+02 7.36902E+06 + 3.82700E+02 7.51073E+06 + 3.82800E+02 7.65244E+06 + 3.82900E+02 7.79415E+06 + 3.83000E+02 7.93586E+06 + 3.83100E+02 8.07758E+06 + 3.83200E+02 8.21929E+06 + 3.83300E+02 8.36100E+06 + 3.83400E+02 8.50271E+06 + 3.83500E+02 8.50271E+06 + 3.83600E+02 7.93586E+06 + 3.83700E+02 7.36902E+06 + 3.83800E+02 6.80217E+06 + 3.83900E+02 6.23532E+06 + 3.84000E+02 5.66848E+06 + 3.84100E+02 5.24334E+06 + 3.84200E+02 5.38505E+06 + 3.84300E+02 5.52676E+06 + 3.84400E+02 5.66848E+06 + 3.84500E+02 5.81019E+06 + 3.84600E+02 5.95190E+06 + 3.84700E+02 6.09361E+06 + 3.84800E+02 6.23532E+06 + 3.84900E+02 6.37703E+06 + 3.85000E+02 6.51875E+06 + 3.85100E+02 6.66046E+06 + 3.85200E+02 6.80217E+06 + 3.85300E+02 6.94388E+06 + 3.85400E+02 7.08559E+06 + 3.85500E+02 7.22730E+06 + 3.85600E+02 7.36902E+06 + 3.85700E+02 7.51073E+06 + 3.85800E+02 7.65244E+06 + 3.85900E+02 7.79415E+06 + 3.86000E+02 7.93586E+06 + 3.86100E+02 8.07758E+06 + 3.86200E+02 8.21929E+06 + 3.86300E+02 8.36100E+06 + 3.86400E+02 8.50271E+06 + 3.86500E+02 8.50271E+06 + 3.86600E+02 7.93586E+06 + 3.86700E+02 7.36902E+06 + 3.86800E+02 6.80217E+06 + 3.86900E+02 6.23532E+06 + 3.87000E+02 5.66848E+06 + 3.87100E+02 5.24334E+06 + 3.87200E+02 5.38505E+06 + 3.87300E+02 5.52676E+06 + 3.87400E+02 5.66848E+06 + 3.87500E+02 5.81019E+06 + 3.87600E+02 5.95190E+06 + 3.87700E+02 6.09361E+06 + 3.87800E+02 6.23532E+06 + 3.87900E+02 6.37703E+06 + 3.88000E+02 6.51875E+06 + 3.88100E+02 6.66046E+06 + 3.88200E+02 6.80217E+06 + 3.88300E+02 6.94388E+06 + 3.88400E+02 7.08559E+06 + 3.88500E+02 7.22730E+06 + 3.88600E+02 7.36902E+06 + 3.88700E+02 7.51073E+06 + 3.88800E+02 7.65244E+06 + 3.88900E+02 7.79415E+06 + 3.89000E+02 7.93586E+06 + 3.89100E+02 8.07758E+06 + 3.89200E+02 8.21929E+06 + 3.89300E+02 8.36100E+06 + 3.89400E+02 8.50271E+06 + 3.89500E+02 8.50271E+06 + 3.89600E+02 7.93586E+06 + 3.89700E+02 7.36902E+06 + 3.89800E+02 6.80217E+06 + 3.89900E+02 6.23532E+06 + 3.90000E+02 5.66848E+06 + 3.90100E+02 5.24334E+06 + 3.90200E+02 5.38505E+06 + 3.90300E+02 5.52676E+06 + 3.90400E+02 5.66848E+06 + 3.90500E+02 5.81019E+06 + 3.90600E+02 5.95190E+06 + 3.90700E+02 6.09361E+06 + 3.90800E+02 6.23532E+06 + 3.90900E+02 6.37703E+06 + 3.91000E+02 6.51875E+06 + 3.91100E+02 6.66046E+06 + 3.91200E+02 6.80217E+06 + 3.91300E+02 6.94388E+06 + 3.91400E+02 7.08559E+06 + 3.91500E+02 7.22730E+06 + 3.91600E+02 7.36902E+06 + 3.91700E+02 7.51073E+06 + 3.91800E+02 7.65244E+06 + 3.91900E+02 7.79415E+06 + 3.92000E+02 7.93586E+06 + 3.92100E+02 8.07758E+06 + 3.92200E+02 8.21929E+06 + 3.92300E+02 8.36100E+06 + 3.92400E+02 8.50271E+06 + 3.92500E+02 8.50271E+06 + 3.92600E+02 7.93586E+06 + 3.92700E+02 7.36902E+06 + 3.92800E+02 6.80217E+06 + 3.92900E+02 6.23532E+06 + 3.93000E+02 5.66848E+06 + 3.93100E+02 5.24334E+06 + 3.93200E+02 5.38505E+06 + 3.93300E+02 5.52676E+06 + 3.93400E+02 5.66848E+06 + 3.93500E+02 5.81019E+06 + 3.93600E+02 5.95190E+06 + 3.93700E+02 6.09361E+06 + 3.93800E+02 6.23532E+06 + 3.93900E+02 6.37703E+06 + 3.94000E+02 6.51875E+06 + 3.94100E+02 6.66046E+06 + 3.94200E+02 6.80217E+06 + 3.94300E+02 6.94388E+06 + 3.94400E+02 7.08559E+06 + 3.94500E+02 7.22730E+06 + 3.94600E+02 7.36902E+06 + 3.94700E+02 7.51073E+06 + 3.94800E+02 7.65244E+06 + 3.94900E+02 7.79415E+06 + 3.95000E+02 7.93586E+06 + 3.95100E+02 8.07758E+06 + 3.95200E+02 8.21929E+06 + 3.95300E+02 8.36100E+06 + 3.95400E+02 8.50271E+06 + 3.95500E+02 8.50271E+06 + 3.95600E+02 7.93586E+06 + 3.95700E+02 7.36902E+06 + 3.95800E+02 6.80217E+06 + 3.95900E+02 6.23532E+06 + 3.96000E+02 5.66848E+06 + 3.96100E+02 5.24334E+06 + 3.96200E+02 5.38505E+06 + 3.96300E+02 5.52676E+06 + 3.96400E+02 5.66848E+06 + 3.96500E+02 5.81019E+06 + 3.96600E+02 5.95190E+06 + 3.96700E+02 6.09361E+06 + 3.96800E+02 6.23532E+06 + 3.96900E+02 6.37703E+06 + 3.97000E+02 6.51875E+06 + 3.97100E+02 6.66046E+06 + 3.97200E+02 6.80217E+06 + 3.97300E+02 6.94388E+06 + 3.97400E+02 7.08559E+06 + 3.97500E+02 7.22730E+06 + 3.97600E+02 7.36902E+06 + 3.97700E+02 7.51073E+06 + 3.97800E+02 7.65244E+06 + 3.97900E+02 7.79415E+06 + 3.98000E+02 7.93586E+06 + 3.98100E+02 8.07758E+06 + 3.98200E+02 8.21929E+06 + 3.98300E+02 8.36100E+06 + 3.98400E+02 8.50271E+06 + 3.98500E+02 8.50271E+06 + 3.98600E+02 7.93586E+06 + 3.98700E+02 7.36902E+06 + 3.98800E+02 6.80217E+06 + 3.98900E+02 6.23532E+06 + 3.99000E+02 5.66848E+06 + 3.99100E+02 5.24334E+06 + 3.99200E+02 5.38505E+06 + 3.99300E+02 5.52676E+06 + 3.99400E+02 5.66848E+06 + 3.99500E+02 5.81019E+06 + 3.99600E+02 5.95190E+06 + 3.99700E+02 6.09361E+06 + 3.99800E+02 6.23532E+06 + 3.99900E+02 6.37703E+06 + 4.00000E+02 6.51875E+06 + 4.00100E+02 6.66046E+06 + 4.00200E+02 6.80217E+06 + 4.00300E+02 6.94388E+06 + 4.00400E+02 7.08559E+06 + 4.00500E+02 7.22730E+06 + 4.00600E+02 7.36902E+06 + 4.00700E+02 7.51073E+06 + 4.00800E+02 7.65244E+06 + 4.00900E+02 7.79415E+06 + 4.01000E+02 7.93586E+06 + 4.01100E+02 8.07758E+06 + 4.01200E+02 8.21929E+06 + 4.01300E+02 8.36100E+06 + 4.01400E+02 8.50271E+06 + 4.01500E+02 8.50271E+06 + 4.01600E+02 7.93586E+06 + 4.01700E+02 7.36902E+06 + 4.01800E+02 6.80217E+06 + 4.01900E+02 6.23532E+06 + 4.02000E+02 5.66848E+06 + 4.02100E+02 5.24334E+06 + 4.02200E+02 5.38505E+06 + 4.02300E+02 5.52676E+06 + 4.02400E+02 5.66848E+06 + 4.02500E+02 5.81019E+06 + 4.02600E+02 5.95190E+06 + 4.02700E+02 6.09361E+06 + 4.02800E+02 6.23532E+06 + 4.02900E+02 6.37703E+06 + 4.03000E+02 6.51875E+06 + 4.03100E+02 6.66046E+06 + 4.03200E+02 6.80217E+06 + 4.03300E+02 6.94388E+06 + 4.03400E+02 7.08559E+06 + 4.03500E+02 7.22730E+06 + 4.03600E+02 7.36902E+06 + 4.03700E+02 7.51073E+06 + 4.03800E+02 7.65244E+06 + 4.03900E+02 7.79415E+06 + 4.04000E+02 7.93586E+06 + 4.04100E+02 8.07758E+06 + 4.04200E+02 8.21929E+06 + 4.04300E+02 8.36100E+06 + 4.04400E+02 8.50271E+06 + 4.04500E+02 8.50271E+06 + 4.04600E+02 7.93586E+06 + 4.04700E+02 7.36902E+06 + 4.04800E+02 6.80217E+06 + 4.04900E+02 6.23532E+06 + 4.05000E+02 5.66848E+06 + 4.05100E+02 5.24334E+06 + 4.05200E+02 5.38505E+06 + 4.05300E+02 5.52676E+06 + 4.05400E+02 5.66848E+06 + 4.05500E+02 5.81019E+06 + 4.05600E+02 5.95190E+06 + 4.05700E+02 6.09361E+06 + 4.05800E+02 6.23532E+06 + 4.05900E+02 6.37703E+06 + 4.06000E+02 6.51875E+06 + 4.06100E+02 6.66046E+06 + 4.06200E+02 6.80217E+06 + 4.06300E+02 6.94388E+06 + 4.06400E+02 7.08559E+06 + 4.06500E+02 7.22730E+06 + 4.06600E+02 7.36902E+06 + 4.06700E+02 7.51073E+06 + 4.06800E+02 7.65244E+06 + 4.06900E+02 7.79415E+06 + 4.07000E+02 7.93586E+06 + 4.07100E+02 8.07758E+06 + 4.07200E+02 8.21929E+06 + 4.07300E+02 8.36100E+06 + 4.07400E+02 8.50271E+06 + 4.07500E+02 8.50271E+06 + 4.07600E+02 7.93586E+06 + 4.07700E+02 7.36902E+06 + 4.07800E+02 6.80217E+06 + 4.07900E+02 6.23532E+06 + 4.08000E+02 5.66848E+06 + 4.08100E+02 5.24334E+06 + 4.08200E+02 5.38505E+06 + 4.08300E+02 5.52676E+06 + 4.08400E+02 5.66848E+06 + 4.08500E+02 5.81019E+06 + 4.08600E+02 5.95190E+06 + 4.08700E+02 6.09361E+06 + 4.08800E+02 6.23532E+06 + 4.08900E+02 6.37703E+06 + 4.09000E+02 6.51875E+06 + 4.09100E+02 6.66046E+06 + 4.09200E+02 6.80217E+06 + 4.09300E+02 6.94388E+06 + 4.09400E+02 7.08559E+06 + 4.09500E+02 7.22730E+06 + 4.09600E+02 7.36902E+06 + 4.09700E+02 7.51073E+06 + 4.09800E+02 7.65244E+06 + 4.09900E+02 7.79415E+06 + 4.10000E+02 7.93586E+06 + 4.10100E+02 8.07758E+06 + 4.10200E+02 8.21929E+06 + 4.10300E+02 8.36100E+06 + 4.10400E+02 8.50271E+06 + 4.10500E+02 8.50271E+06 + 4.10600E+02 7.93586E+06 + 4.10700E+02 7.36902E+06 + 4.10800E+02 6.80217E+06 + 4.10900E+02 6.23532E+06 + 4.11000E+02 5.66848E+06 + 4.11100E+02 5.24334E+06 + 4.11200E+02 5.38505E+06 + 4.11300E+02 5.52676E+06 + 4.11400E+02 5.66848E+06 + 4.11500E+02 5.81019E+06 + 4.11600E+02 5.95190E+06 + 4.11700E+02 6.09361E+06 + 4.11800E+02 6.23532E+06 + 4.11900E+02 6.37703E+06 + 4.12000E+02 6.51875E+06 + 4.12100E+02 6.66046E+06 + 4.12200E+02 6.80217E+06 + 4.12300E+02 6.94388E+06 + 4.12400E+02 7.08559E+06 + 4.12500E+02 7.22730E+06 + 4.12600E+02 7.36902E+06 + 4.12700E+02 7.51073E+06 + 4.12800E+02 7.65244E+06 + 4.12900E+02 7.79415E+06 + 4.13000E+02 7.93586E+06 + 4.13100E+02 8.07758E+06 + 4.13200E+02 8.21929E+06 + 4.13300E+02 8.36100E+06 + 4.13400E+02 8.50271E+06 + 4.13500E+02 8.50271E+06 + 4.13600E+02 7.93586E+06 + 4.13700E+02 7.36902E+06 + 4.13800E+02 6.80217E+06 + 4.13900E+02 6.23532E+06 + 4.14000E+02 5.66848E+06 + 4.14100E+02 5.24334E+06 + 4.14200E+02 5.38505E+06 + 4.14300E+02 5.52676E+06 + 4.14400E+02 5.66848E+06 + 4.14500E+02 5.81019E+06 + 4.14600E+02 5.95190E+06 + 4.14700E+02 6.09361E+06 + 4.14800E+02 6.23532E+06 + 4.14900E+02 6.37703E+06 + 4.15000E+02 6.51875E+06 + 4.15100E+02 6.66046E+06 + 4.15200E+02 6.80217E+06 + 4.15300E+02 6.94388E+06 + 4.15400E+02 7.08559E+06 + 4.15500E+02 7.22730E+06 + 4.15600E+02 7.36902E+06 + 4.15700E+02 7.51073E+06 + 4.15800E+02 7.65244E+06 + 4.15900E+02 7.79415E+06 + 4.16000E+02 7.93586E+06 + 4.16100E+02 8.07758E+06 + 4.16200E+02 8.21929E+06 + 4.16300E+02 8.36100E+06 + 4.16400E+02 8.50271E+06 + 4.16500E+02 8.50271E+06 + 4.16600E+02 7.93586E+06 + 4.16700E+02 7.36902E+06 + 4.16800E+02 6.80217E+06 + 4.16900E+02 6.23532E+06 + 4.17000E+02 5.66848E+06 + 4.17100E+02 5.24334E+06 + 4.17200E+02 5.38505E+06 + 4.17300E+02 5.52676E+06 + 4.17400E+02 5.66848E+06 + 4.17500E+02 5.81019E+06 + 4.17600E+02 5.95190E+06 + 4.17700E+02 6.09361E+06 + 4.17800E+02 6.23532E+06 + 4.17900E+02 6.37703E+06 + 4.18000E+02 6.51875E+06 + 4.18100E+02 6.66046E+06 + 4.18200E+02 6.80217E+06 + 4.18300E+02 6.94388E+06 + 4.18400E+02 7.08559E+06 + 4.18500E+02 7.22730E+06 + 4.18600E+02 7.36902E+06 + 4.18700E+02 7.51073E+06 + 4.18800E+02 7.65244E+06 + 4.18900E+02 7.79415E+06 + 4.19000E+02 7.93586E+06 + 4.19100E+02 8.07758E+06 + 4.19200E+02 8.21929E+06 + 4.19300E+02 8.36100E+06 + 4.19400E+02 8.50271E+06 + 4.19500E+02 8.50271E+06 + 4.19600E+02 7.93586E+06 + 4.19700E+02 7.36902E+06 + 4.19800E+02 6.80217E+06 + 4.19900E+02 6.23532E+06 + 4.20000E+02 5.66848E+06 + 4.20100E+02 5.24334E+06 + 4.20200E+02 5.38505E+06 + 4.20300E+02 5.52676E+06 + 4.20400E+02 5.66848E+06 + 4.20500E+02 5.81019E+06 + 4.20600E+02 5.95190E+06 + 4.20700E+02 6.09361E+06 + 4.20800E+02 6.23532E+06 + 4.20900E+02 6.37703E+06 + 4.21000E+02 6.51875E+06 + 4.21100E+02 6.66046E+06 + 4.21200E+02 6.80217E+06 + 4.21300E+02 6.94388E+06 + 4.21400E+02 7.08559E+06 + 4.21500E+02 7.22730E+06 + 4.21600E+02 7.36902E+06 + 4.21700E+02 7.51073E+06 + 4.21800E+02 7.65244E+06 + 4.21900E+02 7.79415E+06 + 4.22000E+02 7.93586E+06 + 4.22100E+02 8.07758E+06 + 4.22200E+02 8.21929E+06 + 4.22300E+02 8.36100E+06 + 4.22400E+02 8.50271E+06 + 4.22500E+02 8.50271E+06 + 4.22600E+02 7.93586E+06 + 4.22700E+02 7.36902E+06 + 4.22800E+02 6.80217E+06 + 4.22900E+02 6.23532E+06 + 4.23000E+02 5.66848E+06 + 4.23100E+02 5.24334E+06 + 4.23200E+02 5.38505E+06 + 4.23300E+02 5.52676E+06 + 4.23400E+02 5.66848E+06 + 4.23500E+02 5.81019E+06 + 4.23600E+02 5.95190E+06 + 4.23700E+02 6.09361E+06 + 4.23800E+02 6.23532E+06 + 4.23900E+02 6.37703E+06 + 4.24000E+02 6.51875E+06 + 4.24100E+02 6.66046E+06 + 4.24200E+02 6.80217E+06 + 4.24300E+02 6.94388E+06 + 4.24400E+02 7.08559E+06 + 4.24500E+02 7.22730E+06 + 4.24600E+02 7.36902E+06 + 4.24700E+02 7.51073E+06 + 4.24800E+02 7.65244E+06 + 4.24900E+02 7.79415E+06 + 4.25000E+02 7.93586E+06 + 4.25100E+02 8.07758E+06 + 4.25200E+02 8.21929E+06 + 4.25300E+02 8.36100E+06 + 4.25400E+02 8.50271E+06 + 4.25500E+02 8.50271E+06 + 4.25600E+02 7.93586E+06 + 4.25700E+02 7.36902E+06 + 4.25800E+02 6.80217E+06 + 4.25900E+02 6.23532E+06 + 4.26000E+02 5.66848E+06 + 4.26100E+02 5.24334E+06 + 4.26200E+02 5.38505E+06 + 4.26300E+02 5.52676E+06 + 4.26400E+02 5.66848E+06 + 4.26500E+02 5.81019E+06 + 4.26600E+02 5.95190E+06 + 4.26700E+02 6.09361E+06 + 4.26800E+02 6.23532E+06 + 4.26900E+02 6.37703E+06 + 4.27000E+02 6.51875E+06 + 4.27100E+02 6.66046E+06 + 4.27200E+02 6.80217E+06 + 4.27300E+02 6.94388E+06 + 4.27400E+02 7.08559E+06 + 4.27500E+02 7.22730E+06 + 4.27600E+02 7.36902E+06 + 4.27700E+02 7.51073E+06 + 4.27800E+02 7.65244E+06 + 4.27900E+02 7.79415E+06 + 4.28000E+02 7.93586E+06 + 4.28100E+02 8.07758E+06 + 4.28200E+02 8.21929E+06 + 4.28300E+02 8.36100E+06 + 4.28400E+02 8.50271E+06 + 4.28500E+02 8.50271E+06 + 4.28600E+02 7.93586E+06 + 4.28700E+02 7.36902E+06 + 4.28800E+02 6.80217E+06 + 4.28900E+02 6.23532E+06 + 4.29000E+02 5.66848E+06 + 4.29100E+02 5.24334E+06 + 4.29200E+02 5.38505E+06 + 4.29300E+02 5.52676E+06 + 4.29400E+02 5.66848E+06 + 4.29500E+02 5.81019E+06 + 4.29600E+02 5.95190E+06 + 4.29700E+02 6.09361E+06 + 4.29800E+02 6.23532E+06 + 4.29900E+02 6.37703E+06 + 4.30000E+02 6.51875E+06 + 4.30100E+02 6.66046E+06 + 4.30200E+02 6.80217E+06 + 4.30300E+02 6.94388E+06 + 4.30400E+02 7.08559E+06 + 4.30500E+02 7.22730E+06 + 4.30600E+02 7.36902E+06 + 4.30700E+02 7.51073E+06 + 4.30800E+02 7.65244E+06 + 4.30900E+02 7.79415E+06 + 4.31000E+02 7.93586E+06 + 4.31100E+02 8.07758E+06 + 4.31200E+02 8.21929E+06 + 4.31300E+02 8.36100E+06 + 4.31400E+02 8.50271E+06 + 4.31500E+02 8.50271E+06 + 4.31600E+02 7.93586E+06 + 4.31700E+02 7.36902E+06 + 4.31800E+02 6.80217E+06 + 4.31900E+02 6.23532E+06 + 4.32000E+02 5.66848E+06 + 4.32100E+02 5.24334E+06 + 4.32200E+02 5.38505E+06 + 4.32300E+02 5.52676E+06 + 4.32400E+02 5.66848E+06 + 4.32500E+02 5.81019E+06 + 4.32600E+02 5.95190E+06 + 4.32700E+02 6.09361E+06 + 4.32800E+02 6.23532E+06 + 4.32900E+02 6.37703E+06 + 4.33000E+02 6.51875E+06 + 4.33100E+02 6.66046E+06 + 4.33200E+02 6.80217E+06 + 4.33300E+02 6.94388E+06 + 4.33400E+02 7.08559E+06 + 4.33500E+02 7.22730E+06 + 4.33600E+02 7.36902E+06 + 4.33700E+02 7.51073E+06 + 4.33800E+02 7.65244E+06 + 4.33900E+02 7.79415E+06 + 4.34000E+02 7.93586E+06 + 4.34100E+02 8.07758E+06 + 4.34200E+02 8.21929E+06 + 4.34300E+02 8.36100E+06 + 4.34400E+02 8.50271E+06 + 4.34500E+02 8.50271E+06 + 4.34600E+02 7.93586E+06 + 4.34700E+02 7.36902E+06 + 4.34800E+02 6.80217E+06 + 4.34900E+02 6.23532E+06 + 4.35000E+02 5.66848E+06 + 4.35100E+02 5.24334E+06 + 4.35200E+02 5.38505E+06 + 4.35300E+02 5.52676E+06 + 4.35400E+02 5.66848E+06 + 4.35500E+02 5.81019E+06 + 4.35600E+02 5.95190E+06 + 4.35700E+02 6.09361E+06 + 4.35800E+02 6.23532E+06 + 4.35900E+02 6.37703E+06 + 4.36000E+02 6.51875E+06 + 4.36100E+02 6.66046E+06 + 4.36200E+02 6.80217E+06 + 4.36300E+02 6.94388E+06 + 4.36400E+02 7.08559E+06 + 4.36500E+02 7.22730E+06 + 4.36600E+02 7.36902E+06 + 4.36700E+02 7.51073E+06 + 4.36800E+02 7.65244E+06 + 4.36900E+02 7.79415E+06 + 4.37000E+02 7.93586E+06 + 4.37100E+02 8.07758E+06 + 4.37200E+02 8.21929E+06 + 4.37300E+02 8.36100E+06 + 4.37400E+02 8.50271E+06 + 4.37500E+02 8.50271E+06 + 4.37600E+02 7.93586E+06 + 4.37700E+02 7.36902E+06 + 4.37800E+02 6.80217E+06 + 4.37900E+02 6.23532E+06 + 4.38000E+02 5.66848E+06 + 4.38100E+02 5.24334E+06 + 4.38200E+02 5.38505E+06 + 4.38300E+02 5.52676E+06 + 4.38400E+02 5.66848E+06 + 4.38500E+02 5.81019E+06 + 4.38600E+02 5.95190E+06 + 4.38700E+02 6.09361E+06 + 4.38800E+02 6.23532E+06 + 4.38900E+02 6.37703E+06 + 4.39000E+02 6.51875E+06 + 4.39100E+02 6.66046E+06 + 4.39200E+02 6.80217E+06 + 4.39300E+02 6.94388E+06 + 4.39400E+02 7.08559E+06 + 4.39500E+02 7.22730E+06 + 4.39600E+02 7.36902E+06 + 4.39700E+02 7.51073E+06 + 4.39800E+02 7.65244E+06 + 4.39900E+02 7.79415E+06 + 4.40000E+02 7.93586E+06 + 4.40100E+02 8.07758E+06 + 4.40200E+02 8.21929E+06 + 4.40300E+02 8.36100E+06 + 4.40400E+02 8.50271E+06 + 4.40500E+02 8.50271E+06 + 4.40600E+02 7.93586E+06 + 4.40700E+02 7.36902E+06 + 4.40800E+02 6.80217E+06 + 4.40900E+02 6.23532E+06 + 4.41000E+02 5.66848E+06 + 4.41100E+02 5.24334E+06 + 4.41200E+02 5.38505E+06 + 4.41300E+02 5.52676E+06 + 4.41400E+02 5.66848E+06 + 4.41500E+02 5.81019E+06 + 4.41600E+02 5.95190E+06 + 4.41700E+02 6.09361E+06 + 4.41800E+02 6.23532E+06 + 4.41900E+02 6.37703E+06 + 4.42000E+02 6.51875E+06 + 4.42100E+02 6.66046E+06 + 4.42200E+02 6.80217E+06 + 4.42300E+02 6.94388E+06 + 4.42400E+02 7.08559E+06 + 4.42500E+02 7.22730E+06 + 4.42600E+02 7.36902E+06 + 4.42700E+02 7.51073E+06 + 4.42800E+02 7.65244E+06 + 4.42900E+02 7.79415E+06 + 4.43000E+02 7.93586E+06 + 4.43100E+02 8.07758E+06 + 4.43200E+02 8.21929E+06 + 4.43300E+02 8.36100E+06 + 4.43400E+02 8.50271E+06 + 4.43500E+02 8.50271E+06 + 4.43600E+02 7.93586E+06 + 4.43700E+02 7.36902E+06 + 4.43800E+02 6.80217E+06 + 4.43900E+02 6.23532E+06 + 4.44000E+02 5.66848E+06 + 4.44100E+02 5.24334E+06 + 4.44200E+02 5.38505E+06 + 4.44300E+02 5.52676E+06 + 4.44400E+02 5.66848E+06 + 4.44500E+02 5.81019E+06 + 4.44600E+02 5.95190E+06 + 4.44700E+02 6.09361E+06 + 4.44800E+02 6.23532E+06 + 4.44900E+02 6.37703E+06 + 4.45000E+02 6.51875E+06 + 4.45100E+02 6.66046E+06 + 4.45200E+02 6.80217E+06 + 4.45300E+02 6.94388E+06 + 4.45400E+02 7.08559E+06 + 4.45500E+02 7.22730E+06 + 4.45600E+02 7.36902E+06 + 4.45700E+02 7.51073E+06 + 4.45800E+02 7.65244E+06 + 4.45900E+02 7.79415E+06 + 4.46000E+02 7.93586E+06 + 4.46100E+02 8.07758E+06 + 4.46200E+02 8.21929E+06 + 4.46300E+02 8.36100E+06 + 4.46400E+02 8.50271E+06 + 4.46500E+02 8.50271E+06 + 4.46600E+02 7.93586E+06 + 4.46700E+02 7.36902E+06 + 4.46800E+02 6.80217E+06 + 4.46900E+02 6.23532E+06 + 4.47000E+02 5.66848E+06 + 4.47100E+02 5.24334E+06 + 4.47200E+02 5.38505E+06 + 4.47300E+02 5.52676E+06 + 4.47400E+02 5.66848E+06 + 4.47500E+02 5.81019E+06 + 4.47600E+02 5.95190E+06 + 4.47700E+02 6.09361E+06 + 4.47800E+02 6.23532E+06 + 4.47900E+02 6.37703E+06 + 4.48000E+02 6.51875E+06 + 4.48100E+02 6.66046E+06 + 4.48200E+02 6.80217E+06 + 4.48300E+02 6.94388E+06 + 4.48400E+02 7.08559E+06 + 4.48500E+02 7.22730E+06 + 4.48600E+02 7.36902E+06 + 4.48700E+02 7.51073E+06 + 4.48800E+02 7.65244E+06 + 4.48900E+02 7.79415E+06 + 4.49000E+02 7.93586E+06 + 4.49100E+02 8.07758E+06 + 4.49200E+02 8.21929E+06 + 4.49300E+02 8.36100E+06 + 4.49400E+02 8.50271E+06 + 4.49500E+02 8.50271E+06 + 4.49600E+02 7.93586E+06 + 4.49700E+02 7.36902E+06 + 4.49800E+02 6.80217E+06 + 4.49900E+02 6.23532E+06 + 4.50000E+02 5.66848E+06 + 4.50100E+02 5.24334E+06 + 4.50200E+02 5.38505E+06 + 4.50300E+02 5.52676E+06 + 4.50400E+02 5.66848E+06 + 4.50500E+02 5.81019E+06 + 4.50600E+02 5.95190E+06 + 4.50700E+02 6.09361E+06 + 4.50800E+02 6.23532E+06 + 4.50900E+02 6.37703E+06 + 4.51000E+02 6.51875E+06 + 4.51100E+02 6.66046E+06 + 4.51200E+02 6.80217E+06 + 4.51300E+02 6.94388E+06 + 4.51400E+02 7.08559E+06 + 4.51500E+02 7.22730E+06 + 4.51600E+02 7.36902E+06 + 4.51700E+02 7.51073E+06 + 4.51800E+02 7.65244E+06 + 4.51900E+02 7.79415E+06 + 4.52000E+02 7.93586E+06 + 4.52100E+02 8.07758E+06 + 4.52200E+02 8.21929E+06 + 4.52300E+02 8.36100E+06 + 4.52400E+02 8.50271E+06 + 4.52500E+02 8.50271E+06 + 4.52600E+02 7.93586E+06 + 4.52700E+02 7.36902E+06 + 4.52800E+02 6.80217E+06 + 4.52900E+02 6.23532E+06 + 4.53000E+02 5.66848E+06 + 4.53100E+02 5.24334E+06 + 4.53200E+02 5.38505E+06 + 4.53300E+02 5.52676E+06 + 4.53400E+02 5.66848E+06 + 4.53500E+02 5.81019E+06 + 4.53600E+02 5.95190E+06 + 4.53700E+02 6.09361E+06 + 4.53800E+02 6.23532E+06 + 4.53900E+02 6.37703E+06 + 4.54000E+02 6.51875E+06 + 4.54100E+02 6.66046E+06 + 4.54200E+02 6.80217E+06 + 4.54300E+02 6.94388E+06 + 4.54400E+02 7.08559E+06 + 4.54500E+02 7.22730E+06 + 4.54600E+02 7.36902E+06 + 4.54700E+02 7.51073E+06 + 4.54800E+02 7.65244E+06 + 4.54900E+02 7.79415E+06 + 4.55000E+02 7.93586E+06 + 4.55100E+02 8.07758E+06 + 4.55200E+02 8.21929E+06 + 4.55300E+02 8.36100E+06 + 4.55400E+02 8.50271E+06 + 4.55500E+02 8.50271E+06 + 4.55600E+02 7.93586E+06 + 4.55700E+02 7.36902E+06 + 4.55800E+02 6.80217E+06 + 4.55900E+02 6.23532E+06 + 4.56000E+02 5.66848E+06 + 4.56100E+02 5.24334E+06 + 4.56200E+02 5.38505E+06 + 4.56300E+02 5.52676E+06 + 4.56400E+02 5.66848E+06 + 4.56500E+02 5.81019E+06 + 4.56600E+02 5.95190E+06 + 4.56700E+02 6.09361E+06 + 4.56800E+02 6.23532E+06 + 4.56900E+02 6.37703E+06 + 4.57000E+02 6.51875E+06 + 4.57100E+02 6.66046E+06 + 4.57200E+02 6.80217E+06 + 4.57300E+02 6.94388E+06 + 4.57400E+02 7.08559E+06 + 4.57500E+02 7.22730E+06 + 4.57600E+02 7.36902E+06 + 4.57700E+02 7.51073E+06 + 4.57800E+02 7.65244E+06 + 4.57900E+02 7.79415E+06 + 4.58000E+02 7.93586E+06 + 4.58100E+02 8.07758E+06 + 4.58200E+02 8.21929E+06 + 4.58300E+02 8.36100E+06 + 4.58400E+02 8.50271E+06 + 4.58500E+02 8.50271E+06 + 4.58600E+02 7.93586E+06 + 4.58700E+02 7.36902E+06 + 4.58800E+02 6.80217E+06 + 4.58900E+02 6.23532E+06 + 4.59000E+02 5.66848E+06 + 4.59100E+02 5.24334E+06 + 4.59200E+02 5.38505E+06 + 4.59300E+02 5.52676E+06 + 4.59400E+02 5.66848E+06 + 4.59500E+02 5.81019E+06 + 4.59600E+02 5.95190E+06 + 4.59700E+02 6.09361E+06 + 4.59800E+02 6.23532E+06 + 4.59900E+02 6.37703E+06 + 4.60000E+02 6.51875E+06 + 4.60100E+02 6.66046E+06 + 4.60200E+02 6.80217E+06 + 4.60300E+02 6.94388E+06 + 4.60400E+02 7.08559E+06 + 4.60500E+02 7.22730E+06 + 4.60600E+02 7.36902E+06 + 4.60700E+02 7.51073E+06 + 4.60800E+02 7.65244E+06 + 4.60900E+02 7.79415E+06 + 4.61000E+02 7.93586E+06 + 4.61100E+02 8.07758E+06 + 4.61200E+02 8.21929E+06 + 4.61300E+02 8.36100E+06 + 4.61400E+02 8.50271E+06 + 4.61500E+02 8.50271E+06 + 4.61600E+02 7.93586E+06 + 4.61700E+02 7.36902E+06 + 4.61800E+02 6.80217E+06 + 4.61900E+02 6.23532E+06 + 4.62000E+02 5.66848E+06 + 4.62100E+02 5.24334E+06 + 4.62200E+02 5.38505E+06 + 4.62300E+02 5.52676E+06 + 4.62400E+02 5.66848E+06 + 4.62500E+02 5.81019E+06 + 4.62600E+02 5.95190E+06 + 4.62700E+02 6.09361E+06 + 4.62800E+02 6.23532E+06 + 4.62900E+02 6.37703E+06 + 4.63000E+02 6.51875E+06 + 4.63100E+02 6.66046E+06 + 4.63200E+02 6.80217E+06 + 4.63300E+02 6.94388E+06 + 4.63400E+02 7.08559E+06 + 4.63500E+02 7.22730E+06 + 4.63600E+02 7.36902E+06 + 4.63700E+02 7.51073E+06 + 4.63800E+02 7.65244E+06 + 4.63900E+02 7.79415E+06 + 4.64000E+02 7.93586E+06 + 4.64100E+02 8.07758E+06 + 4.64200E+02 8.21929E+06 + 4.64300E+02 8.36100E+06 + 4.64400E+02 8.50271E+06 + 4.64500E+02 8.50271E+06 + 4.64600E+02 7.93586E+06 + 4.64700E+02 7.36902E+06 + 4.64800E+02 6.80217E+06 + 4.64900E+02 6.23532E+06 + 4.65000E+02 5.66848E+06 + 4.65100E+02 5.24334E+06 + 4.65200E+02 5.38505E+06 + 4.65300E+02 5.52676E+06 + 4.65400E+02 5.66848E+06 + 4.65500E+02 5.81019E+06 + 4.65600E+02 5.95190E+06 + 4.65700E+02 6.09361E+06 + 4.65800E+02 6.23532E+06 + 4.65900E+02 6.37703E+06 + 4.66000E+02 6.51875E+06 + 4.66100E+02 6.66046E+06 + 4.66200E+02 6.80217E+06 + 4.66300E+02 6.94388E+06 + 4.66400E+02 7.08559E+06 + 4.66500E+02 7.22730E+06 + 4.66600E+02 7.36902E+06 + 4.66700E+02 7.51073E+06 + 4.66800E+02 7.65244E+06 + 4.66900E+02 7.79415E+06 + 4.67000E+02 7.93586E+06 + 4.67100E+02 8.07758E+06 + 4.67200E+02 8.21929E+06 + 4.67300E+02 8.36100E+06 + 4.67400E+02 8.50271E+06 + 4.67500E+02 8.50271E+06 + 4.67600E+02 7.93586E+06 + 4.67700E+02 7.36902E+06 + 4.67800E+02 6.80217E+06 + 4.67900E+02 6.23532E+06 + 4.68000E+02 5.66848E+06 + 4.68100E+02 5.24334E+06 + 4.68200E+02 5.38505E+06 + 4.68300E+02 5.52676E+06 + 4.68400E+02 5.66848E+06 + 4.68500E+02 5.81019E+06 + 4.68600E+02 5.95190E+06 + 4.68700E+02 6.09361E+06 + 4.68800E+02 6.23532E+06 + 4.68900E+02 6.37703E+06 + 4.69000E+02 6.51875E+06 + 4.69100E+02 6.66046E+06 + 4.69200E+02 6.80217E+06 + 4.69300E+02 6.94388E+06 + 4.69400E+02 7.08559E+06 + 4.69500E+02 7.22730E+06 + 4.69600E+02 7.36902E+06 + 4.69700E+02 7.51073E+06 + 4.69800E+02 7.65244E+06 + 4.69900E+02 7.79415E+06 + 4.70000E+02 7.93586E+06 + 4.70100E+02 8.07758E+06 + 4.70200E+02 8.21929E+06 + 4.70300E+02 8.36100E+06 + 4.70400E+02 8.50271E+06 + 4.70500E+02 8.50271E+06 + 4.70600E+02 7.93586E+06 + 4.70700E+02 7.36902E+06 + 4.70800E+02 6.80217E+06 + 4.70900E+02 6.23532E+06 + 4.71000E+02 5.66848E+06 + 4.71100E+02 5.24334E+06 + 4.71200E+02 5.38505E+06 + 4.71300E+02 5.52676E+06 + 4.71400E+02 5.66848E+06 + 4.71500E+02 5.81019E+06 + 4.71600E+02 5.95190E+06 + 4.71700E+02 6.09361E+06 + 4.71800E+02 6.23532E+06 + 4.71900E+02 6.37703E+06 + 4.72000E+02 6.51875E+06 + 4.72100E+02 6.66046E+06 + 4.72200E+02 6.80217E+06 + 4.72300E+02 6.94388E+06 + 4.72400E+02 7.08559E+06 + 4.72500E+02 7.22730E+06 + 4.72600E+02 7.36902E+06 + 4.72700E+02 7.51073E+06 + 4.72800E+02 7.65244E+06 + 4.72900E+02 7.79415E+06 + 4.73000E+02 7.93586E+06 + 4.73100E+02 8.07758E+06 + 4.73200E+02 8.21929E+06 + 4.73300E+02 8.36100E+06 + 4.73400E+02 8.50271E+06 + 4.73500E+02 8.50271E+06 + 4.73600E+02 7.93586E+06 + 4.73700E+02 7.36902E+06 + 4.73800E+02 6.80217E+06 + 4.73900E+02 6.23532E+06 + 4.74000E+02 5.66848E+06 + 4.74100E+02 5.24334E+06 + 4.74200E+02 5.38505E+06 + 4.74300E+02 5.52676E+06 + 4.74400E+02 5.66848E+06 + 4.74500E+02 5.81019E+06 + 4.74600E+02 5.95190E+06 + 4.74700E+02 6.09361E+06 + 4.74800E+02 6.23532E+06 + 4.74900E+02 6.37703E+06 + 4.75000E+02 6.51875E+06 + 4.75100E+02 6.66046E+06 + 4.75200E+02 6.80217E+06 + 4.75300E+02 6.94388E+06 + 4.75400E+02 7.08559E+06 + 4.75500E+02 7.22730E+06 + 4.75600E+02 7.36902E+06 + 4.75700E+02 7.51073E+06 + 4.75800E+02 7.65244E+06 + 4.75900E+02 7.79415E+06 + 4.76000E+02 7.93586E+06 + 4.76100E+02 8.07758E+06 + 4.76200E+02 8.21929E+06 + 4.76300E+02 8.36100E+06 + 4.76400E+02 8.50271E+06 + 4.76500E+02 8.50271E+06 + 4.76600E+02 7.93586E+06 + 4.76700E+02 7.36902E+06 + 4.76800E+02 6.80217E+06 + 4.76900E+02 6.23532E+06 + 4.77000E+02 5.66848E+06 + 4.77100E+02 5.24334E+06 + 4.77200E+02 5.38505E+06 + 4.77300E+02 5.52676E+06 + 4.77400E+02 5.66848E+06 + 4.77500E+02 5.81019E+06 + 4.77600E+02 5.95190E+06 + 4.77700E+02 6.09361E+06 + 4.77800E+02 6.23532E+06 + 4.77900E+02 6.37703E+06 + 4.78000E+02 6.51875E+06 + 4.78100E+02 6.66046E+06 + 4.78200E+02 6.80217E+06 + 4.78300E+02 6.94388E+06 + 4.78400E+02 7.08559E+06 + 4.78500E+02 7.22730E+06 + 4.78600E+02 7.36902E+06 + 4.78700E+02 7.51073E+06 + 4.78800E+02 7.65244E+06 + 4.78900E+02 7.79415E+06 + 4.79000E+02 7.93586E+06 + 4.79100E+02 8.07758E+06 + 4.79200E+02 8.21929E+06 + 4.79300E+02 8.36100E+06 + 4.79400E+02 8.50271E+06 + 4.79500E+02 8.50271E+06 + 4.79600E+02 7.93586E+06 + 4.79700E+02 7.36902E+06 + 4.79800E+02 6.80217E+06 + 4.79900E+02 6.23532E+06 + 4.80000E+02 5.66848E+06 + 4.80100E+02 5.24334E+06 + 4.80200E+02 5.38505E+06 + 4.80300E+02 5.52676E+06 + 4.80400E+02 5.66848E+06 + 4.80500E+02 5.81019E+06 + 4.80600E+02 5.95190E+06 + 4.80700E+02 6.09361E+06 + 4.80800E+02 6.23532E+06 + 4.80900E+02 6.37703E+06 + 4.81000E+02 6.51875E+06 + 4.81100E+02 6.66046E+06 + 4.81200E+02 6.80217E+06 + 4.81300E+02 6.94388E+06 + 4.81400E+02 7.08559E+06 + 4.81500E+02 7.22730E+06 + 4.81600E+02 7.36902E+06 + 4.81700E+02 7.51073E+06 + 4.81800E+02 7.65244E+06 + 4.81900E+02 7.79415E+06 + 4.82000E+02 7.93586E+06 + 4.82100E+02 8.07758E+06 + 4.82200E+02 8.21929E+06 + 4.82300E+02 8.36100E+06 + 4.82400E+02 8.50271E+06 + 4.82500E+02 8.50271E+06 + 4.82600E+02 7.93586E+06 + 4.82700E+02 7.36902E+06 + 4.82800E+02 6.80217E+06 + 4.82900E+02 6.23532E+06 + 4.83000E+02 5.66848E+06 + 4.83100E+02 5.24334E+06 + 4.83200E+02 5.38505E+06 + 4.83300E+02 5.52676E+06 + 4.83400E+02 5.66848E+06 + 4.83500E+02 5.81019E+06 + 4.83600E+02 5.95190E+06 + 4.83700E+02 6.09361E+06 + 4.83800E+02 6.23532E+06 + 4.83900E+02 6.37703E+06 + 4.84000E+02 6.51875E+06 + 4.84100E+02 6.66046E+06 + 4.84200E+02 6.80217E+06 + 4.84300E+02 6.94388E+06 + 4.84400E+02 7.08559E+06 + 4.84500E+02 7.22730E+06 + 4.84600E+02 7.36902E+06 + 4.84700E+02 7.51073E+06 + 4.84800E+02 7.65244E+06 + 4.84900E+02 7.79415E+06 + 4.85000E+02 7.93586E+06 + 4.85100E+02 8.07758E+06 + 4.85200E+02 8.21929E+06 + 4.85300E+02 8.36100E+06 + 4.85400E+02 8.50271E+06 + 4.85500E+02 8.50271E+06 + 4.85600E+02 7.93586E+06 + 4.85700E+02 7.36902E+06 + 4.85800E+02 6.80217E+06 + 4.85900E+02 6.23532E+06 + 4.86000E+02 5.66848E+06 + 4.86100E+02 5.24334E+06 + 4.86200E+02 5.38505E+06 + 4.86300E+02 5.52676E+06 + 4.86400E+02 5.66848E+06 + 4.86500E+02 5.81019E+06 + 4.86600E+02 5.95190E+06 + 4.86700E+02 6.09361E+06 + 4.86800E+02 6.23532E+06 + 4.86900E+02 6.37703E+06 + 4.87000E+02 6.51875E+06 + 4.87100E+02 6.66046E+06 + 4.87200E+02 6.80217E+06 + 4.87300E+02 6.94388E+06 + 4.87400E+02 7.08559E+06 + 4.87500E+02 7.22730E+06 + 4.87600E+02 7.36902E+06 + 4.87700E+02 7.51073E+06 + 4.87800E+02 7.65244E+06 + 4.87900E+02 7.79415E+06 + 4.88000E+02 7.93586E+06 + 4.88100E+02 8.07758E+06 + 4.88200E+02 8.21929E+06 + 4.88300E+02 8.36100E+06 + 4.88400E+02 8.50271E+06 + 4.88500E+02 8.50271E+06 + 4.88600E+02 7.93586E+06 + 4.88700E+02 7.36902E+06 + 4.88800E+02 6.80217E+06 + 4.88900E+02 6.23532E+06 + 4.89000E+02 5.66848E+06 + 4.89100E+02 5.24334E+06 + 4.89200E+02 5.38505E+06 + 4.89300E+02 5.52676E+06 + 4.89400E+02 5.66848E+06 + 4.89500E+02 5.81019E+06 + 4.89600E+02 5.95190E+06 + 4.89700E+02 6.09361E+06 + 4.89800E+02 6.23532E+06 + 4.89900E+02 6.37703E+06 + 4.90000E+02 6.51875E+06 + 4.90100E+02 6.66046E+06 + 4.90200E+02 6.80217E+06 + 4.90300E+02 6.94388E+06 + 4.90400E+02 7.08559E+06 + 4.90500E+02 7.22730E+06 + 4.90600E+02 7.36902E+06 + 4.90700E+02 7.51073E+06 + 4.90800E+02 7.65244E+06 + 4.90900E+02 7.79415E+06 + 4.91000E+02 7.93586E+06 + 4.91100E+02 8.07758E+06 + 4.91200E+02 8.21929E+06 + 4.91300E+02 8.36100E+06 + 4.91400E+02 8.50271E+06 + 4.91500E+02 8.50271E+06 + 4.91600E+02 7.93586E+06 + 4.91700E+02 7.36902E+06 + 4.91800E+02 6.80217E+06 + 4.91900E+02 6.23532E+06 + 4.92000E+02 5.66848E+06 + 4.92100E+02 5.24334E+06 + 4.92200E+02 5.38505E+06 + 4.92300E+02 5.52676E+06 + 4.92400E+02 5.66848E+06 + 4.92500E+02 5.81019E+06 + 4.92600E+02 5.95190E+06 + 4.92700E+02 6.09361E+06 + 4.92800E+02 6.23532E+06 + 4.92900E+02 6.37703E+06 + 4.93000E+02 6.51875E+06 + 4.93100E+02 6.66046E+06 + 4.93200E+02 6.80217E+06 + 4.93300E+02 6.94388E+06 + 4.93400E+02 7.08559E+06 + 4.93500E+02 7.22730E+06 + 4.93600E+02 7.36902E+06 + 4.93700E+02 7.51073E+06 + 4.93800E+02 7.65244E+06 + 4.93900E+02 7.79415E+06 + 4.94000E+02 7.93586E+06 + 4.94100E+02 8.07758E+06 + 4.94200E+02 8.21929E+06 + 4.94300E+02 8.36100E+06 + 4.94400E+02 8.50271E+06 + 4.94500E+02 8.50271E+06 + 4.94600E+02 7.93586E+06 + 4.94700E+02 7.36902E+06 + 4.94800E+02 6.80217E+06 + 4.94900E+02 6.23532E+06 + 4.95000E+02 5.66848E+06 + 4.95100E+02 5.24334E+06 + 4.95200E+02 5.38505E+06 + 4.95300E+02 5.52676E+06 + 4.95400E+02 5.66848E+06 + 4.95500E+02 5.81019E+06 + 4.95600E+02 5.95190E+06 + 4.95700E+02 6.09361E+06 + 4.95800E+02 6.23532E+06 + 4.95900E+02 6.37703E+06 + 4.96000E+02 6.51875E+06 + 4.96100E+02 6.66046E+06 + 4.96200E+02 6.80217E+06 + 4.96300E+02 6.94388E+06 + 4.96400E+02 7.08559E+06 + 4.96500E+02 7.22730E+06 + 4.96600E+02 7.36902E+06 + 4.96700E+02 7.51073E+06 + 4.96800E+02 7.65244E+06 + 4.96900E+02 7.79415E+06 + 4.97000E+02 7.93586E+06 + 4.97100E+02 8.07758E+06 + 4.97200E+02 8.21929E+06 + 4.97300E+02 8.36100E+06 + 4.97400E+02 8.50271E+06 + 4.97500E+02 8.50271E+06 + 4.97600E+02 7.93586E+06 + 4.97700E+02 7.36902E+06 + 4.97800E+02 6.80217E+06 + 4.97900E+02 6.23532E+06 + 4.98000E+02 5.66848E+06 + 4.98100E+02 5.24334E+06 + 4.98200E+02 5.38505E+06 + 4.98300E+02 5.52676E+06 + 4.98400E+02 5.66848E+06 + 4.98500E+02 5.81019E+06 + 4.98600E+02 5.95190E+06 + 4.98700E+02 6.09361E+06 + 4.98800E+02 6.23532E+06 + 4.98900E+02 6.37703E+06 + 4.99000E+02 6.51875E+06 + 4.99100E+02 6.66046E+06 + 4.99200E+02 6.80217E+06 + 4.99300E+02 6.94388E+06 + 4.99400E+02 7.08559E+06 + 4.99500E+02 7.22730E+06 + 4.99600E+02 7.36902E+06 + 4.99700E+02 7.51073E+06 + 4.99800E+02 7.65244E+06 + 4.99900E+02 7.79415E+06 + 5.00000E+02 7.93586E+06 + 5.00100E+02 8.07758E+06 + 5.00200E+02 8.21929E+06 + 5.00300E+02 8.36100E+06 + 5.00400E+02 8.50271E+06 + 5.00500E+02 8.50271E+06 + 5.00600E+02 7.93586E+06 + 5.00700E+02 7.36902E+06 + 5.00800E+02 6.80217E+06 + 5.00900E+02 6.23532E+06 + 5.01000E+02 5.66848E+06 + 5.01100E+02 5.24334E+06 + 5.01200E+02 5.38505E+06 + 5.01300E+02 5.52676E+06 + 5.01400E+02 5.66848E+06 + 5.01500E+02 5.81019E+06 + 5.01600E+02 5.95190E+06 + 5.01700E+02 6.09361E+06 + 5.01800E+02 6.23532E+06 + 5.01900E+02 6.37703E+06 + 5.02000E+02 6.51875E+06 + 5.02100E+02 6.66046E+06 + 5.02200E+02 6.80217E+06 + 5.02300E+02 6.94388E+06 + 5.02400E+02 7.08559E+06 + 5.02500E+02 7.22730E+06 + 5.02600E+02 7.36902E+06 + 5.02700E+02 7.51073E+06 + 5.02800E+02 7.65244E+06 + 5.02900E+02 7.79415E+06 + 5.03000E+02 7.93586E+06 + 5.03100E+02 8.07758E+06 + 5.03200E+02 8.21929E+06 + 5.03300E+02 8.36100E+06 + 5.03400E+02 8.50271E+06 + 5.03500E+02 8.50271E+06 + 5.03600E+02 7.93586E+06 + 5.03700E+02 7.36902E+06 + 5.03800E+02 6.80217E+06 + 5.03900E+02 6.23532E+06 + 5.04000E+02 5.66848E+06 + 5.04100E+02 5.24334E+06 + 5.04200E+02 5.38505E+06 + 5.04300E+02 5.52676E+06 + 5.04400E+02 5.66848E+06 + 5.04500E+02 5.81019E+06 + 5.04600E+02 5.95190E+06 + 5.04700E+02 6.09361E+06 + 5.04800E+02 6.23532E+06 + 5.04900E+02 6.37703E+06 + 5.05000E+02 6.51875E+06 + 5.05100E+02 6.66046E+06 + 5.05200E+02 6.80217E+06 + 5.05300E+02 6.94388E+06 + 5.05400E+02 7.08559E+06 + 5.05500E+02 7.22730E+06 + 5.05600E+02 7.36902E+06 + 5.05700E+02 7.51073E+06 + 5.05800E+02 7.65244E+06 + 5.05900E+02 7.79415E+06 + 5.06000E+02 7.93586E+06 + 5.06100E+02 8.07758E+06 + 5.06200E+02 8.21929E+06 + 5.06300E+02 8.36100E+06 + 5.06400E+02 8.50271E+06 + 5.06500E+02 8.50271E+06 + 5.06600E+02 7.93586E+06 + 5.06700E+02 7.36902E+06 + 5.06800E+02 6.80217E+06 + 5.06900E+02 6.23532E+06 + 5.07000E+02 5.66848E+06 + 5.07100E+02 5.24334E+06 + 5.07200E+02 5.38505E+06 + 5.07300E+02 5.52676E+06 + 5.07400E+02 5.66848E+06 + 5.07500E+02 5.81019E+06 + 5.07600E+02 5.95190E+06 + 5.07700E+02 6.09361E+06 + 5.07800E+02 6.23532E+06 + 5.07900E+02 6.37703E+06 + 5.08000E+02 6.51875E+06 + 5.08100E+02 6.66046E+06 + 5.08200E+02 6.80217E+06 + 5.08300E+02 6.94388E+06 + 5.08400E+02 7.08559E+06 + 5.08500E+02 7.22730E+06 + 5.08600E+02 7.36902E+06 + 5.08700E+02 7.51073E+06 + 5.08800E+02 7.65244E+06 + 5.08900E+02 7.79415E+06 + 5.09000E+02 7.93586E+06 + 5.09100E+02 8.07758E+06 + 5.09200E+02 8.21929E+06 + 5.09300E+02 8.36100E+06 + 5.09400E+02 8.50271E+06 + 5.09500E+02 8.50271E+06 + 5.09600E+02 7.93586E+06 + 5.09700E+02 7.36902E+06 + 5.09800E+02 6.80217E+06 + 5.09900E+02 6.23532E+06 + 5.10000E+02 5.66848E+06 + 5.10100E+02 5.24334E+06 + 5.10200E+02 5.38505E+06 + 5.10300E+02 5.52676E+06 + 5.10400E+02 5.66848E+06 + 5.10500E+02 5.81019E+06 + 5.10600E+02 5.95190E+06 + 5.10700E+02 6.09361E+06 + 5.10800E+02 6.23532E+06 + 5.10900E+02 6.37703E+06 + 5.11000E+02 6.51875E+06 + 5.11100E+02 6.66046E+06 + 5.11200E+02 6.80217E+06 + 5.11300E+02 6.94388E+06 + 5.11400E+02 7.08559E+06 + 5.11500E+02 7.22730E+06 + 5.11600E+02 7.36902E+06 + 5.11700E+02 7.51073E+06 + 5.11800E+02 7.65244E+06 + 5.11900E+02 7.79415E+06 + 5.12000E+02 7.93586E+06 + 5.12100E+02 8.07758E+06 + 5.12200E+02 8.21929E+06 + 5.12300E+02 8.36100E+06 + 5.12400E+02 8.50271E+06 + 5.12500E+02 8.50271E+06 + 5.12600E+02 7.93586E+06 + 5.12700E+02 7.36902E+06 + 5.12800E+02 6.80217E+06 + 5.12900E+02 6.23532E+06 + 5.13000E+02 5.66848E+06 + 5.13100E+02 5.24334E+06 + 5.13200E+02 5.38505E+06 + 5.13300E+02 5.52676E+06 + 5.13400E+02 5.66848E+06 + 5.13500E+02 5.81019E+06 + 5.13600E+02 5.95190E+06 + 5.13700E+02 6.09361E+06 + 5.13800E+02 6.23532E+06 + 5.13900E+02 6.37703E+06 + 5.14000E+02 6.51875E+06 + 5.14100E+02 6.66046E+06 + 5.14200E+02 6.80217E+06 + 5.14300E+02 6.94388E+06 + 5.14400E+02 7.08559E+06 + 5.14500E+02 7.22730E+06 + 5.14600E+02 7.36902E+06 + 5.14700E+02 7.51073E+06 + 5.14800E+02 7.65244E+06 + 5.14900E+02 7.79415E+06 + 5.15000E+02 7.93586E+06 + 5.15100E+02 8.07758E+06 + 5.15200E+02 8.21929E+06 + 5.15300E+02 8.36100E+06 + 5.15400E+02 8.50271E+06 + 5.15500E+02 8.50271E+06 + 5.15600E+02 7.93586E+06 + 5.15700E+02 7.36902E+06 + 5.15800E+02 6.80217E+06 + 5.15900E+02 6.23532E+06 + 5.16000E+02 5.66848E+06 + 5.16100E+02 5.24334E+06 + 5.16200E+02 5.38505E+06 + 5.16300E+02 5.52676E+06 + 5.16400E+02 5.66848E+06 + 5.16500E+02 5.81019E+06 + 5.16600E+02 5.95190E+06 + 5.16700E+02 6.09361E+06 + 5.16800E+02 6.23532E+06 + 5.16900E+02 6.37703E+06 + 5.17000E+02 6.51875E+06 + 5.17100E+02 6.66046E+06 + 5.17200E+02 6.80217E+06 + 5.17300E+02 6.94388E+06 + 5.17400E+02 7.08559E+06 + 5.17500E+02 7.22730E+06 + 5.17600E+02 7.36902E+06 + 5.17700E+02 7.51073E+06 + 5.17800E+02 7.65244E+06 + 5.17900E+02 7.79415E+06 + 5.18000E+02 7.93586E+06 + 5.18100E+02 8.07758E+06 + 5.18200E+02 8.21929E+06 + 5.18300E+02 8.36100E+06 + 5.18400E+02 8.50271E+06 + 5.18500E+02 8.50271E+06 + 5.18600E+02 7.93586E+06 + 5.18700E+02 7.36902E+06 + 5.18800E+02 6.80217E+06 + 5.18900E+02 6.23532E+06 + 5.19000E+02 5.66848E+06 + 5.19100E+02 5.24334E+06 + 5.19200E+02 5.38505E+06 + 5.19300E+02 5.52676E+06 + 5.19400E+02 5.66848E+06 + 5.19500E+02 5.81019E+06 + 5.19600E+02 5.95190E+06 + 5.19700E+02 6.09361E+06 + 5.19800E+02 6.23532E+06 + 5.19900E+02 6.37703E+06 + 5.20000E+02 6.51875E+06 + 5.20100E+02 6.66046E+06 + 5.20200E+02 6.80217E+06 + 5.20300E+02 6.94388E+06 + 5.20400E+02 7.08559E+06 + 5.20500E+02 7.22730E+06 + 5.20600E+02 7.36902E+06 + 5.20700E+02 7.51073E+06 + 5.20800E+02 7.65244E+06 + 5.20900E+02 7.79415E+06 + 5.21000E+02 7.93586E+06 + 5.21100E+02 8.07758E+06 + 5.21200E+02 8.21929E+06 + 5.21300E+02 8.36100E+06 + 5.21400E+02 8.50271E+06 + 5.21500E+02 8.50271E+06 + 5.21600E+02 7.93586E+06 + 5.21700E+02 7.36902E+06 + 5.21800E+02 6.80217E+06 + 5.21900E+02 6.23532E+06 + 5.22000E+02 5.66848E+06 + 5.22100E+02 5.24334E+06 + 5.22200E+02 5.38505E+06 + 5.22300E+02 5.52676E+06 + 5.22400E+02 5.66848E+06 + 5.22500E+02 5.81019E+06 + 5.22600E+02 5.95190E+06 + 5.22700E+02 6.09361E+06 + 5.22800E+02 6.23532E+06 + 5.22900E+02 6.37703E+06 + 5.23000E+02 6.51875E+06 + 5.23100E+02 6.66046E+06 + 5.23200E+02 6.80217E+06 + 5.23300E+02 6.94388E+06 + 5.23400E+02 7.08559E+06 + 5.23500E+02 7.22730E+06 + 5.23600E+02 7.36902E+06 + 5.23700E+02 7.51073E+06 + 5.23800E+02 7.65244E+06 + 5.23900E+02 7.79415E+06 + 5.24000E+02 7.93586E+06 + 5.24100E+02 8.07758E+06 + 5.24200E+02 8.21929E+06 + 5.24300E+02 8.36100E+06 + 5.24400E+02 8.50271E+06 + 5.24500E+02 8.50271E+06 + 5.24600E+02 7.93586E+06 + 5.24700E+02 7.36902E+06 + 5.24800E+02 6.80217E+06 + 5.24900E+02 6.23532E+06 + 5.25000E+02 5.66848E+06 + 5.25100E+02 5.24334E+06 + 5.25200E+02 5.38505E+06 + 5.25300E+02 5.52676E+06 + 5.25400E+02 5.66848E+06 + 5.25500E+02 5.81019E+06 + 5.25600E+02 5.95190E+06 + 5.25700E+02 6.09361E+06 + 5.25800E+02 6.23532E+06 + 5.25900E+02 6.37703E+06 + 5.26000E+02 6.51875E+06 + 5.26100E+02 6.66046E+06 + 5.26200E+02 6.80217E+06 + 5.26300E+02 6.94388E+06 + 5.26400E+02 7.08559E+06 + 5.26500E+02 7.22730E+06 + 5.26600E+02 7.36902E+06 + 5.26700E+02 7.51073E+06 + 5.26800E+02 7.65244E+06 + 5.26900E+02 7.79415E+06 + 5.27000E+02 7.93586E+06 + 5.27100E+02 8.07758E+06 + 5.27200E+02 8.21929E+06 + 5.27300E+02 8.36100E+06 + 5.27400E+02 8.50271E+06 + 5.27500E+02 8.50271E+06 + 5.27600E+02 7.93586E+06 + 5.27700E+02 7.36902E+06 + 5.27800E+02 6.80217E+06 + 5.27900E+02 6.23532E+06 + 5.28000E+02 5.66848E+06 + 5.28100E+02 5.24334E+06 + 5.28200E+02 5.38505E+06 + 5.28300E+02 5.52676E+06 + 5.28400E+02 5.66848E+06 + 5.28500E+02 5.81019E+06 + 5.28600E+02 5.95190E+06 + 5.28700E+02 6.09361E+06 + 5.28800E+02 6.23532E+06 + 5.28900E+02 6.37703E+06 + 5.29000E+02 6.51875E+06 + 5.29100E+02 6.66046E+06 + 5.29200E+02 6.80217E+06 + 5.29300E+02 6.94388E+06 + 5.29400E+02 7.08559E+06 + 5.29500E+02 7.22730E+06 + 5.29600E+02 7.36902E+06 + 5.29700E+02 7.51073E+06 + 5.29800E+02 7.65244E+06 + 5.29900E+02 7.79415E+06 + 5.30000E+02 7.93586E+06 + 5.30100E+02 8.07758E+06 + 5.30200E+02 8.21929E+06 + 5.30300E+02 8.36100E+06 + 5.30400E+02 8.50271E+06 + 5.30500E+02 8.50271E+06 + 5.30600E+02 7.93586E+06 + 5.30700E+02 7.36902E+06 + 5.30800E+02 6.80217E+06 + 5.30900E+02 6.23532E+06 + 5.31000E+02 5.66848E+06 + 5.31100E+02 5.24334E+06 + 5.31200E+02 5.38505E+06 + 5.31300E+02 5.52676E+06 + 5.31400E+02 5.66848E+06 + 5.31500E+02 5.81019E+06 + 5.31600E+02 5.95190E+06 + 5.31700E+02 6.09361E+06 + 5.31800E+02 6.23532E+06 + 5.31900E+02 6.37703E+06 + 5.32000E+02 6.51875E+06 + 5.32100E+02 6.66046E+06 + 5.32200E+02 6.80217E+06 + 5.32300E+02 6.94388E+06 + 5.32400E+02 7.08559E+06 + 5.32500E+02 7.22730E+06 + 5.32600E+02 7.36902E+06 + 5.32700E+02 7.51073E+06 + 5.32800E+02 7.65244E+06 + 5.32900E+02 7.79415E+06 + 5.33000E+02 7.93586E+06 + 5.33100E+02 8.07758E+06 + 5.33200E+02 8.21929E+06 + 5.33300E+02 8.36100E+06 + 5.33400E+02 8.50271E+06 + 5.33500E+02 8.50271E+06 + 5.33600E+02 7.93586E+06 + 5.33700E+02 7.36902E+06 + 5.33800E+02 6.80217E+06 + 5.33900E+02 6.23532E+06 + 5.34000E+02 5.66848E+06 + 5.34100E+02 5.24334E+06 + 5.34200E+02 5.38505E+06 + 5.34300E+02 5.52676E+06 + 5.34400E+02 5.66848E+06 + 5.34500E+02 5.81019E+06 + 5.34600E+02 5.95190E+06 + 5.34700E+02 6.09361E+06 + 5.34800E+02 6.23532E+06 + 5.34900E+02 6.37703E+06 + 5.35000E+02 6.51875E+06 + 5.35100E+02 6.66046E+06 + 5.35200E+02 6.80217E+06 + 5.35300E+02 6.94388E+06 + 5.35400E+02 7.08559E+06 + 5.35500E+02 7.22730E+06 + 5.35600E+02 7.36902E+06 + 5.35700E+02 7.51073E+06 + 5.35800E+02 7.65244E+06 + 5.35900E+02 7.79415E+06 + 5.36000E+02 7.93586E+06 + 5.36100E+02 8.07758E+06 + 5.36200E+02 8.21929E+06 + 5.36300E+02 8.36100E+06 + 5.36400E+02 8.50271E+06 + 5.36500E+02 8.50271E+06 + 5.36600E+02 7.93586E+06 + 5.36700E+02 7.36902E+06 + 5.36800E+02 6.80217E+06 + 5.36900E+02 6.23532E+06 + 5.37000E+02 5.66848E+06 + 5.37100E+02 5.24334E+06 + 5.37200E+02 5.38505E+06 + 5.37300E+02 5.52676E+06 + 5.37400E+02 5.66848E+06 + 5.37500E+02 5.81019E+06 + 5.37600E+02 5.95190E+06 + 5.37700E+02 6.09361E+06 + 5.37800E+02 6.23532E+06 + 5.37900E+02 6.37703E+06 + 5.38000E+02 6.51875E+06 + 5.38100E+02 6.66046E+06 + 5.38200E+02 6.80217E+06 + 5.38300E+02 6.94388E+06 + 5.38400E+02 7.08559E+06 + 5.38500E+02 7.22730E+06 + 5.38600E+02 7.36902E+06 + 5.38700E+02 7.51073E+06 + 5.38800E+02 7.65244E+06 + 5.38900E+02 7.79415E+06 + 5.39000E+02 7.93586E+06 + 5.39100E+02 8.07758E+06 + 5.39200E+02 8.21929E+06 + 5.39300E+02 8.36100E+06 + 5.39400E+02 8.50271E+06 + 5.39500E+02 8.50271E+06 + 5.39600E+02 7.93586E+06 + 5.39700E+02 7.36902E+06 + 5.39800E+02 6.80217E+06 + 5.39900E+02 6.23532E+06 + 5.40000E+02 5.66848E+06 + 5.40100E+02 5.24334E+06 + 5.40200E+02 5.38505E+06 + 5.40300E+02 5.52676E+06 + 5.40400E+02 5.66848E+06 + 5.40500E+02 5.81019E+06 + 5.40600E+02 5.95190E+06 + 5.40700E+02 6.09361E+06 + 5.40800E+02 6.23532E+06 + 5.40900E+02 6.37703E+06 + 5.41000E+02 6.51875E+06 + 5.41100E+02 6.66046E+06 + 5.41200E+02 6.80217E+06 + 5.41300E+02 6.94388E+06 + 5.41400E+02 7.08559E+06 + 5.41500E+02 7.22730E+06 + 5.41600E+02 7.36902E+06 + 5.41700E+02 7.51073E+06 + 5.41800E+02 7.65244E+06 + 5.41900E+02 7.79415E+06 + 5.42000E+02 7.93586E+06 + 5.42100E+02 8.07758E+06 + 5.42200E+02 8.21929E+06 + 5.42300E+02 8.36100E+06 + 5.42400E+02 8.50271E+06 + 5.42500E+02 8.50271E+06 + 5.42600E+02 7.93586E+06 + 5.42700E+02 7.36902E+06 + 5.42800E+02 6.80217E+06 + 5.42900E+02 6.23532E+06 + 5.43000E+02 5.66848E+06 + 5.43100E+02 5.24334E+06 + 5.43200E+02 5.38505E+06 + 5.43300E+02 5.52676E+06 + 5.43400E+02 5.66848E+06 + 5.43500E+02 5.81019E+06 + 5.43600E+02 5.95190E+06 + 5.43700E+02 6.09361E+06 + 5.43800E+02 6.23532E+06 + 5.43900E+02 6.37703E+06 + 5.44000E+02 6.51875E+06 + 5.44100E+02 6.66046E+06 + 5.44200E+02 6.80217E+06 + 5.44300E+02 6.94388E+06 + 5.44400E+02 7.08559E+06 + 5.44500E+02 7.22730E+06 + 5.44600E+02 7.36902E+06 + 5.44700E+02 7.51073E+06 + 5.44800E+02 7.65244E+06 + 5.44900E+02 7.79415E+06 + 5.45000E+02 7.93586E+06 + 5.45100E+02 8.07758E+06 + 5.45200E+02 8.21929E+06 + 5.45300E+02 8.36100E+06 + 5.45400E+02 8.50271E+06 + 5.45500E+02 8.50271E+06 + 5.45600E+02 7.93586E+06 + 5.45700E+02 7.36902E+06 + 5.45800E+02 6.80217E+06 + 5.45900E+02 6.23532E+06 + 5.46000E+02 5.66848E+06 + 5.46100E+02 5.24334E+06 + 5.46200E+02 5.38505E+06 + 5.46300E+02 5.52676E+06 + 5.46400E+02 5.66848E+06 + 5.46500E+02 5.81019E+06 + 5.46600E+02 5.95190E+06 + 5.46700E+02 6.09361E+06 + 5.46800E+02 6.23532E+06 + 5.46900E+02 6.37703E+06 + 5.47000E+02 6.51875E+06 + 5.47100E+02 6.66046E+06 + 5.47200E+02 6.80217E+06 + 5.47300E+02 6.94388E+06 + 5.47400E+02 7.08559E+06 + 5.47500E+02 7.22730E+06 + 5.47600E+02 7.36902E+06 + 5.47700E+02 7.51073E+06 + 5.47800E+02 7.65244E+06 + 5.47900E+02 7.79415E+06 + 5.48000E+02 7.93586E+06 + 5.48100E+02 8.07758E+06 + 5.48200E+02 8.21929E+06 + 5.48300E+02 8.36100E+06 + 5.48400E+02 8.50271E+06 + 5.48500E+02 8.50271E+06 + 5.48600E+02 7.93586E+06 + 5.48700E+02 7.36902E+06 + 5.48800E+02 6.80217E+06 + 5.48900E+02 6.23532E+06 + 5.49000E+02 5.66848E+06 + 5.49100E+02 5.24334E+06 + 5.49200E+02 5.38505E+06 + 5.49300E+02 5.52676E+06 + 5.49400E+02 5.66848E+06 + 5.49500E+02 5.81019E+06 + 5.49600E+02 5.95190E+06 + 5.49700E+02 6.09361E+06 + 5.49800E+02 6.23532E+06 + 5.49900E+02 6.37703E+06 + 5.50000E+02 6.51875E+06 + 5.50100E+02 6.66046E+06 + 5.50200E+02 6.80217E+06 + 5.50300E+02 6.94388E+06 + 5.50400E+02 7.08559E+06 + 5.50500E+02 7.22730E+06 + 5.50600E+02 7.36902E+06 + 5.50700E+02 7.51073E+06 + 5.50800E+02 7.65244E+06 + 5.50900E+02 7.79415E+06 + 5.51000E+02 7.93586E+06 + 5.51100E+02 8.07758E+06 + 5.51200E+02 8.21929E+06 + 5.51300E+02 8.36100E+06 + 5.51400E+02 8.50271E+06 + 5.51500E+02 8.50271E+06 + 5.51600E+02 7.93586E+06 + 5.51700E+02 7.36902E+06 + 5.51800E+02 6.80217E+06 + 5.51900E+02 6.23532E+06 + 5.52000E+02 5.66848E+06 + 5.52100E+02 5.24334E+06 + 5.52200E+02 5.38505E+06 + 5.52300E+02 5.52676E+06 + 5.52400E+02 5.66848E+06 + 5.52500E+02 5.81019E+06 + 5.52600E+02 5.95190E+06 + 5.52700E+02 6.09361E+06 + 5.52800E+02 6.23532E+06 + 5.52900E+02 6.37703E+06 + 5.53000E+02 6.51875E+06 + 5.53100E+02 6.66046E+06 + 5.53200E+02 6.80217E+06 + 5.53300E+02 6.94388E+06 + 5.53400E+02 7.08559E+06 + 5.53500E+02 7.22730E+06 + 5.53600E+02 7.36902E+06 + 5.53700E+02 7.51073E+06 + 5.53800E+02 7.65244E+06 + 5.53900E+02 7.79415E+06 + 5.54000E+02 7.93586E+06 + 5.54100E+02 8.07758E+06 + 5.54200E+02 8.21929E+06 + 5.54300E+02 8.36100E+06 + 5.54400E+02 8.50271E+06 + 5.54500E+02 8.50271E+06 + 5.54600E+02 7.93586E+06 + 5.54700E+02 7.36902E+06 + 5.54800E+02 6.80217E+06 + 5.54900E+02 6.23532E+06 + 5.55000E+02 5.66848E+06 + 5.55100E+02 5.24334E+06 + 5.55200E+02 5.38505E+06 + 5.55300E+02 5.52676E+06 + 5.55400E+02 5.66848E+06 + 5.55500E+02 5.81019E+06 + 5.55600E+02 5.95190E+06 + 5.55700E+02 6.09361E+06 + 5.55800E+02 6.23532E+06 + 5.55900E+02 6.37703E+06 + 5.56000E+02 6.51875E+06 + 5.56100E+02 6.66046E+06 + 5.56200E+02 6.80217E+06 + 5.56300E+02 6.94388E+06 + 5.56400E+02 7.08559E+06 + 5.56500E+02 7.22730E+06 + 5.56600E+02 7.36902E+06 + 5.56700E+02 7.51073E+06 + 5.56800E+02 7.65244E+06 + 5.56900E+02 7.79415E+06 + 5.57000E+02 7.93586E+06 + 5.57100E+02 8.07758E+06 + 5.57200E+02 8.21929E+06 + 5.57300E+02 8.36100E+06 + 5.57400E+02 8.50271E+06 + 5.57500E+02 8.50271E+06 + 5.57600E+02 7.93586E+06 + 5.57700E+02 7.36902E+06 + 5.57800E+02 6.80217E+06 + 5.57900E+02 6.23532E+06 + 5.58000E+02 5.66848E+06 + 5.58100E+02 5.24334E+06 + 5.58200E+02 5.38505E+06 + 5.58300E+02 5.52676E+06 + 5.58400E+02 5.66848E+06 + 5.58500E+02 5.81019E+06 + 5.58600E+02 5.95190E+06 + 5.58700E+02 6.09361E+06 + 5.58800E+02 6.23532E+06 + 5.58900E+02 6.37703E+06 + 5.59000E+02 6.51875E+06 + 5.59100E+02 6.66046E+06 + 5.59200E+02 6.80217E+06 + 5.59300E+02 6.94388E+06 + 5.59400E+02 7.08559E+06 + 5.59500E+02 7.22730E+06 + 5.59600E+02 7.36902E+06 + 5.59700E+02 7.51073E+06 + 5.59800E+02 7.65244E+06 + 5.59900E+02 7.79415E+06 + 5.60000E+02 7.93586E+06 + 5.60100E+02 8.07758E+06 + 5.60200E+02 8.21929E+06 + 5.60300E+02 8.36100E+06 + 5.60400E+02 8.50271E+06 + 5.60500E+02 8.50271E+06 + 5.60600E+02 7.93586E+06 + 5.60700E+02 7.36902E+06 + 5.60800E+02 6.80217E+06 + 5.60900E+02 6.23532E+06 + 5.61000E+02 5.66848E+06 + 5.61100E+02 5.24334E+06 + 5.61200E+02 5.38505E+06 + 5.61300E+02 5.52676E+06 + 5.61400E+02 5.66848E+06 + 5.61500E+02 5.81019E+06 + 5.61600E+02 5.95190E+06 + 5.61700E+02 6.09361E+06 + 5.61800E+02 6.23532E+06 + 5.61900E+02 6.37703E+06 + 5.62000E+02 6.51875E+06 + 5.62100E+02 6.66046E+06 + 5.62200E+02 6.80217E+06 + 5.62300E+02 6.94388E+06 + 5.62400E+02 7.08559E+06 + 5.62500E+02 7.22730E+06 + 5.62600E+02 7.36902E+06 + 5.62700E+02 7.51073E+06 + 5.62800E+02 7.65244E+06 + 5.62900E+02 7.79415E+06 + 5.63000E+02 7.93586E+06 + 5.63100E+02 8.07758E+06 + 5.63200E+02 8.21929E+06 + 5.63300E+02 8.36100E+06 + 5.63400E+02 8.50271E+06 + 5.63500E+02 8.50271E+06 + 5.63600E+02 7.93586E+06 + 5.63700E+02 7.36902E+06 + 5.63800E+02 6.80217E+06 + 5.63900E+02 6.23532E+06 + 5.64000E+02 5.66848E+06 + 5.64100E+02 5.24334E+06 + 5.64200E+02 5.38505E+06 + 5.64300E+02 5.52676E+06 + 5.64400E+02 5.66848E+06 + 5.64500E+02 5.81019E+06 + 5.64600E+02 5.95190E+06 + 5.64700E+02 6.09361E+06 + 5.64800E+02 6.23532E+06 + 5.64900E+02 6.37703E+06 + 5.65000E+02 6.51875E+06 + 5.65100E+02 6.66046E+06 + 5.65200E+02 6.80217E+06 + 5.65300E+02 6.94388E+06 + 5.65400E+02 7.08559E+06 + 5.65500E+02 7.22730E+06 + 5.65600E+02 7.36902E+06 + 5.65700E+02 7.51073E+06 + 5.65800E+02 7.65244E+06 + 5.65900E+02 7.79415E+06 + 5.66000E+02 7.93586E+06 + 5.66100E+02 8.07758E+06 + 5.66200E+02 8.21929E+06 + 5.66300E+02 8.36100E+06 + 5.66400E+02 8.50271E+06 + 5.66500E+02 8.50271E+06 + 5.66600E+02 7.93586E+06 + 5.66700E+02 7.36902E+06 + 5.66800E+02 6.80217E+06 + 5.66900E+02 6.23532E+06 + 5.67000E+02 5.66848E+06 + 5.67100E+02 5.24334E+06 + 5.67200E+02 5.38505E+06 + 5.67300E+02 5.52676E+06 + 5.67400E+02 5.66848E+06 + 5.67500E+02 5.81019E+06 + 5.67600E+02 5.95190E+06 + 5.67700E+02 6.09361E+06 + 5.67800E+02 6.23532E+06 + 5.67900E+02 6.37703E+06 + 5.68000E+02 6.51875E+06 + 5.68100E+02 6.66046E+06 + 5.68200E+02 6.80217E+06 + 5.68300E+02 6.94388E+06 + 5.68400E+02 7.08559E+06 + 5.68500E+02 7.22730E+06 + 5.68600E+02 7.36902E+06 + 5.68700E+02 7.51073E+06 + 5.68800E+02 7.65244E+06 + 5.68900E+02 7.79415E+06 + 5.69000E+02 7.93586E+06 + 5.69100E+02 8.07758E+06 + 5.69200E+02 8.21929E+06 + 5.69300E+02 8.36100E+06 + 5.69400E+02 8.50271E+06 + 5.69500E+02 8.50271E+06 + 5.69600E+02 7.93586E+06 + 5.69700E+02 7.36902E+06 + 5.69800E+02 6.80217E+06 + 5.69900E+02 6.23532E+06 + 5.70000E+02 5.66848E+06 + 5.70100E+02 5.24334E+06 + 5.70200E+02 5.38505E+06 + 5.70300E+02 5.52676E+06 + 5.70400E+02 5.66848E+06 + 5.70500E+02 5.81019E+06 + 5.70600E+02 5.95190E+06 + 5.70700E+02 6.09361E+06 + 5.70800E+02 6.23532E+06 + 5.70900E+02 6.37703E+06 + 5.71000E+02 6.51875E+06 + 5.71100E+02 6.66046E+06 + 5.71200E+02 6.80217E+06 + 5.71300E+02 6.94388E+06 + 5.71400E+02 7.08559E+06 + 5.71500E+02 7.22730E+06 + 5.71600E+02 7.36902E+06 + 5.71700E+02 7.51073E+06 + 5.71800E+02 7.65244E+06 + 5.71900E+02 7.79415E+06 + 5.72000E+02 7.93586E+06 + 5.72100E+02 8.07758E+06 + 5.72200E+02 8.21929E+06 + 5.72300E+02 8.36100E+06 + 5.72400E+02 8.50271E+06 + 5.72500E+02 8.50271E+06 + 5.72600E+02 7.93586E+06 + 5.72700E+02 7.36902E+06 + 5.72800E+02 6.80217E+06 + 5.72900E+02 6.23532E+06 + 5.73000E+02 5.66848E+06 + 5.73100E+02 5.24334E+06 + 5.73200E+02 5.38505E+06 + 5.73300E+02 5.52676E+06 + 5.73400E+02 5.66848E+06 + 5.73500E+02 5.81019E+06 + 5.73600E+02 5.95190E+06 + 5.73700E+02 6.09361E+06 + 5.73800E+02 6.23532E+06 + 5.73900E+02 6.37703E+06 + 5.74000E+02 6.51875E+06 + 5.74100E+02 6.66046E+06 + 5.74200E+02 6.80217E+06 + 5.74300E+02 6.94388E+06 + 5.74400E+02 7.08559E+06 + 5.74500E+02 7.22730E+06 + 5.74600E+02 7.36902E+06 + 5.74700E+02 7.51073E+06 + 5.74800E+02 7.65244E+06 + 5.74900E+02 7.79415E+06 + 5.75000E+02 7.93586E+06 + 5.75100E+02 8.07758E+06 + 5.75200E+02 8.21929E+06 + 5.75300E+02 8.36100E+06 + 5.75400E+02 8.50271E+06 + 5.75500E+02 8.50271E+06 + 5.75600E+02 7.93586E+06 + 5.75700E+02 7.36902E+06 + 5.75800E+02 6.80217E+06 + 5.75900E+02 6.23532E+06 + 5.76000E+02 5.66848E+06 + 5.76100E+02 5.24334E+06 + 5.76200E+02 5.38505E+06 + 5.76300E+02 5.52676E+06 + 5.76400E+02 5.66848E+06 + 5.76500E+02 5.81019E+06 + 5.76600E+02 5.95190E+06 + 5.76700E+02 6.09361E+06 + 5.76800E+02 6.23532E+06 + 5.76900E+02 6.37703E+06 + 5.77000E+02 6.51875E+06 + 5.77100E+02 6.66046E+06 + 5.77200E+02 6.80217E+06 + 5.77300E+02 6.94388E+06 + 5.77400E+02 7.08559E+06 + 5.77500E+02 7.22730E+06 + 5.77600E+02 7.36902E+06 + 5.77700E+02 7.51073E+06 + 5.77800E+02 7.65244E+06 + 5.77900E+02 7.79415E+06 + 5.78000E+02 7.93586E+06 + 5.78100E+02 8.07758E+06 + 5.78200E+02 8.21929E+06 + 5.78300E+02 8.36100E+06 + 5.78400E+02 8.50271E+06 + 5.78500E+02 8.50271E+06 + 5.78600E+02 7.93586E+06 + 5.78700E+02 7.36902E+06 + 5.78800E+02 6.80217E+06 + 5.78900E+02 6.23532E+06 + 5.79000E+02 5.66848E+06 + 5.79100E+02 5.24334E+06 + 5.79200E+02 5.38505E+06 + 5.79300E+02 5.52676E+06 + 5.79400E+02 5.66848E+06 + 5.79500E+02 5.81019E+06 + 5.79600E+02 5.95190E+06 + 5.79700E+02 6.09361E+06 + 5.79800E+02 6.23532E+06 + 5.79900E+02 6.37703E+06 + 5.80000E+02 6.51875E+06 + 5.80100E+02 6.66046E+06 + 5.80200E+02 6.80217E+06 + 5.80300E+02 6.94388E+06 + 5.80400E+02 7.08559E+06 + 5.80500E+02 7.22730E+06 + 5.80600E+02 7.36902E+06 + 5.80700E+02 7.51073E+06 + 5.80800E+02 7.65244E+06 + 5.80900E+02 7.79415E+06 + 5.81000E+02 7.93586E+06 + 5.81100E+02 8.07758E+06 + 5.81200E+02 8.21929E+06 + 5.81300E+02 8.36100E+06 + 5.81400E+02 8.50271E+06 + 5.81500E+02 8.50271E+06 + 5.81600E+02 7.93586E+06 + 5.81700E+02 7.36902E+06 + 5.81800E+02 6.80217E+06 + 5.81900E+02 6.23532E+06 + 5.82000E+02 5.66848E+06 + 5.82100E+02 5.24334E+06 + 5.82200E+02 5.38505E+06 + 5.82300E+02 5.52676E+06 + 5.82400E+02 5.66848E+06 + 5.82500E+02 5.81019E+06 + 5.82600E+02 5.95190E+06 + 5.82700E+02 6.09361E+06 + 5.82800E+02 6.23532E+06 + 5.82900E+02 6.37703E+06 + 5.83000E+02 6.51875E+06 + 5.83100E+02 6.66046E+06 + 5.83200E+02 6.80217E+06 + 5.83300E+02 6.94388E+06 + 5.83400E+02 7.08559E+06 + 5.83500E+02 7.22730E+06 + 5.83600E+02 7.36902E+06 + 5.83700E+02 7.51073E+06 + 5.83800E+02 7.65244E+06 + 5.83900E+02 7.79415E+06 + 5.84000E+02 7.93586E+06 + 5.84100E+02 8.07758E+06 + 5.84200E+02 8.21929E+06 + 5.84300E+02 8.36100E+06 + 5.84400E+02 8.50271E+06 + 5.84500E+02 8.50271E+06 + 5.84600E+02 7.93586E+06 + 5.84700E+02 7.36902E+06 + 5.84800E+02 6.80217E+06 + 5.84900E+02 6.23532E+06 + 5.85000E+02 5.66848E+06 + 5.85100E+02 5.24334E+06 + 5.85200E+02 5.38505E+06 + 5.85300E+02 5.52676E+06 + 5.85400E+02 5.66848E+06 + 5.85500E+02 5.81019E+06 + 5.85600E+02 5.95190E+06 + 5.85700E+02 6.09361E+06 + 5.85800E+02 6.23532E+06 + 5.85900E+02 6.37703E+06 + 5.86000E+02 6.51875E+06 + 5.86100E+02 6.66046E+06 + 5.86200E+02 6.80217E+06 + 5.86300E+02 6.94388E+06 + 5.86400E+02 7.08559E+06 + 5.86500E+02 7.22730E+06 + 5.86600E+02 7.36902E+06 + 5.86700E+02 7.51073E+06 + 5.86800E+02 7.65244E+06 + 5.86900E+02 7.79415E+06 + 5.87000E+02 7.93586E+06 + 5.87100E+02 8.07758E+06 + 5.87200E+02 8.21929E+06 + 5.87300E+02 8.36100E+06 + 5.87400E+02 8.50271E+06 + 5.87500E+02 8.50271E+06 + 5.87600E+02 7.93586E+06 + 5.87700E+02 7.36902E+06 + 5.87800E+02 6.80217E+06 + 5.87900E+02 6.23532E+06 + 5.88000E+02 5.66848E+06 + 5.88100E+02 5.24334E+06 + 5.88200E+02 5.38505E+06 + 5.88300E+02 5.52676E+06 + 5.88400E+02 5.66848E+06 + 5.88500E+02 5.81019E+06 + 5.88600E+02 5.95190E+06 + 5.88700E+02 6.09361E+06 + 5.88800E+02 6.23532E+06 + 5.88900E+02 6.37703E+06 + 5.89000E+02 6.51875E+06 + 5.89100E+02 6.66046E+06 + 5.89200E+02 6.80217E+06 + 5.89300E+02 6.94388E+06 + 5.89400E+02 7.08559E+06 + 5.89500E+02 7.22730E+06 + 5.89600E+02 7.36902E+06 + 5.89700E+02 7.51073E+06 + 5.89800E+02 7.65244E+06 + 5.89900E+02 7.79415E+06 + 5.90000E+02 7.93586E+06 + 5.90100E+02 8.07758E+06 + 5.90200E+02 8.21929E+06 + 5.90300E+02 8.36100E+06 + 5.90400E+02 8.50271E+06 + 5.90500E+02 8.50271E+06 + 5.90600E+02 7.93586E+06 + 5.90700E+02 7.36902E+06 + 5.90800E+02 6.80217E+06 + 5.90900E+02 6.23532E+06 + 5.91000E+02 5.66848E+06 + 5.91100E+02 5.24334E+06 + 5.91200E+02 5.38505E+06 + 5.91300E+02 5.52676E+06 + 5.91400E+02 5.66848E+06 + 5.91500E+02 5.81019E+06 + 5.91600E+02 5.95190E+06 + 5.91700E+02 6.09361E+06 + 5.91800E+02 6.23532E+06 + 5.91900E+02 6.37703E+06 + 5.92000E+02 6.51875E+06 + 5.92100E+02 6.66046E+06 + 5.92200E+02 6.80217E+06 + 5.92300E+02 6.94388E+06 + 5.92400E+02 7.08559E+06 + 5.92500E+02 7.22730E+06 + 5.92600E+02 7.36902E+06 + 5.92700E+02 7.51073E+06 + 5.92800E+02 7.65244E+06 + 5.92900E+02 7.79415E+06 + 5.93000E+02 7.93586E+06 + 5.93100E+02 8.07758E+06 + 5.93200E+02 8.21929E+06 + 5.93300E+02 8.36100E+06 + 5.93400E+02 8.50271E+06 + 5.93500E+02 8.50271E+06 + 5.93600E+02 7.93586E+06 + 5.93700E+02 7.36902E+06 + 5.93800E+02 6.80217E+06 + 5.93900E+02 6.23532E+06 + 5.94000E+02 5.66848E+06 + 5.94100E+02 5.24334E+06 + 5.94200E+02 5.38505E+06 + 5.94300E+02 5.52676E+06 + 5.94400E+02 5.66848E+06 + 5.94500E+02 5.81019E+06 + 5.94600E+02 5.95190E+06 + 5.94700E+02 6.09361E+06 + 5.94800E+02 6.23532E+06 + 5.94900E+02 6.37703E+06 + 5.95000E+02 6.51875E+06 + 5.95100E+02 6.66046E+06 + 5.95200E+02 6.80217E+06 + 5.95300E+02 6.94388E+06 + 5.95400E+02 7.08559E+06 + 5.95500E+02 7.22730E+06 + 5.95600E+02 7.36902E+06 + 5.95700E+02 7.51073E+06 + 5.95800E+02 7.65244E+06 + 5.95900E+02 7.79415E+06 + 5.96000E+02 7.93586E+06 + 5.96100E+02 8.07758E+06 + 5.96200E+02 8.21929E+06 + 5.96300E+02 8.36100E+06 + 5.96400E+02 8.50271E+06 + 5.96500E+02 8.50271E+06 + 5.96600E+02 7.93586E+06 + 5.96700E+02 7.36902E+06 + 5.96800E+02 6.80217E+06 + 5.96900E+02 6.23532E+06 + 5.97000E+02 5.66848E+06 + 5.97100E+02 5.24334E+06 + 5.97200E+02 5.38505E+06 + 5.97300E+02 5.52676E+06 + 5.97400E+02 5.66848E+06 + 5.97500E+02 5.81019E+06 + 5.97600E+02 5.95190E+06 + 5.97700E+02 6.09361E+06 + 5.97800E+02 6.23532E+06 + 5.97900E+02 6.37703E+06 + 5.98000E+02 6.51875E+06 + 5.98100E+02 6.66046E+06 + 5.98200E+02 6.80217E+06 + 5.98300E+02 6.94388E+06 + 5.98400E+02 7.08559E+06 + 5.98500E+02 7.22730E+06 + 5.98600E+02 7.36902E+06 + 5.98700E+02 7.51073E+06 + 5.98800E+02 7.65244E+06 + 5.98900E+02 7.79415E+06 + 5.99000E+02 7.93586E+06 + 5.99100E+02 8.07758E+06 + 5.99200E+02 8.21929E+06 + 5.99300E+02 8.36100E+06 + 5.99400E+02 8.50271E+06 + 5.99500E+02 8.50271E+06 + 5.99600E+02 7.93586E+06 + 5.99700E+02 7.36902E+06 + 5.99800E+02 6.80217E+06 + 5.99900E+02 6.23532E+06 + 6.00000E+02 5.66848E+06 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.log b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.log new file mode 100644 index 000000000..3cf9876ed --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_lockin_ISO.log @@ -0,0 +1,29 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:25:27 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 3 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting common ice crushing input parameters + Reference ice strength = 2.20000E+06 Pascals + Reference ice thickness = 1 meters + Exponent for static load = -0.16 + + Setting ice crushing loads with frequency lock-in parameteres per ISO + Tower fundamental frequency = 0.33 Hz + Sawtooth rise time fraction = 0.8 + Minimum load fraction (of max) = 0.6 +** Global crushing load is: 8.50271E+06 Newtons. + + Frequency lock-in ice crushing loads via ISO initialized + diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.dat b/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.dat new file mode 100644 index 000000000..9bfed4a0b --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.dat @@ -0,0 +1,6001 @@ + 0.00000E+00 0.00000E+00 + 1.00000E-01 2.16908E+06 + 2.00000E-01 2.71268E+06 + 3.00000E-01 3.09827E+06 + 4.00000E-01 2.89487E+06 + 5.00000E-01 3.53846E+06 + 6.00000E-01 4.04579E+06 + 7.00000E-01 5.11012E+06 + 8.00000E-01 5.13213E+06 + 9.00000E-01 4.26328E+06 + 1.00000E+00 4.21832E+06 + 1.10000E+00 5.15250E+06 + 1.20000E+00 4.98229E+06 + 1.30000E+00 5.07310E+06 + 1.40000E+00 5.80230E+06 + 1.50000E+00 5.99791E+06 + 1.60000E+00 5.97596E+06 + 1.70000E+00 6.79672E+06 + 1.80000E+00 7.17578E+06 + 1.90000E+00 6.55505E+06 + 2.00000E+00 6.03822E+06 + 2.10000E+00 5.46922E+06 + 2.20000E+00 5.00568E+06 + 2.30000E+00 4.38853E+06 + 2.40000E+00 4.15129E+06 + 2.50000E+00 4.45344E+06 + 2.60000E+00 3.90623E+06 + 2.70000E+00 3.88859E+06 + 2.80000E+00 3.50972E+06 + 2.90000E+00 3.44717E+06 + 3.00000E+00 3.58786E+06 + 3.10000E+00 3.94774E+06 + 3.20000E+00 4.83163E+06 + 3.30000E+00 5.11484E+06 + 3.40000E+00 5.24329E+06 + 3.50000E+00 6.18589E+06 + 3.60000E+00 6.49790E+06 + 3.70000E+00 5.90627E+06 + 3.80000E+00 5.81017E+06 + 3.90000E+00 6.25614E+06 + 4.00000E+00 6.99470E+06 + 4.10000E+00 7.43549E+06 + 4.20000E+00 7.64717E+06 + 4.30000E+00 6.66544E+06 + 4.40000E+00 5.06361E+06 + 4.50000E+00 5.14691E+06 + 4.60000E+00 5.17413E+06 + 4.70000E+00 5.49490E+06 + 4.80000E+00 5.73471E+06 + 4.90000E+00 5.74614E+06 + 5.00000E+00 5.12022E+06 + 5.10000E+00 4.51761E+06 + 5.20000E+00 4.56750E+06 + 5.30000E+00 5.03621E+06 + 5.40000E+00 4.71460E+06 + 5.50000E+00 4.78829E+06 + 5.60000E+00 4.63959E+06 + 5.70000E+00 3.28688E+06 + 5.80000E+00 2.39200E+06 + 5.90000E+00 2.40403E+06 + 6.00000E+00 2.82944E+06 + 6.10000E+00 3.03030E+06 + 6.20000E+00 4.09029E+06 + 6.30000E+00 4.95069E+06 + 6.40000E+00 4.85694E+06 + 6.50000E+00 5.35778E+06 + 6.60000E+00 5.14128E+06 + 6.70000E+00 5.46370E+06 + 6.80000E+00 5.76758E+06 + 6.90000E+00 5.20383E+06 + 7.00000E+00 5.32598E+06 + 7.10000E+00 5.29408E+06 + 7.20000E+00 5.16377E+06 + 7.30000E+00 5.38162E+06 + 7.40000E+00 4.35128E+06 + 7.50000E+00 4.20938E+06 + 7.60000E+00 4.07080E+06 + 7.70000E+00 4.31364E+06 + 7.80000E+00 4.19933E+06 + 7.90000E+00 3.87439E+06 + 8.00000E+00 2.99480E+06 + 8.10000E+00 3.26284E+06 + 8.20000E+00 3.96364E+06 + 8.30000E+00 3.94839E+06 + 8.40000E+00 4.45030E+06 + 8.50000E+00 4.64593E+06 + 8.60000E+00 4.22761E+06 + 8.70000E+00 3.91623E+06 + 8.80000E+00 3.01109E+06 + 8.90000E+00 3.31515E+06 + 9.00000E+00 3.10271E+06 + 9.10000E+00 3.54621E+06 + 9.20000E+00 4.49592E+06 + 9.30000E+00 5.55601E+06 + 9.40000E+00 5.17371E+06 + 9.50000E+00 4.83232E+06 + 9.60000E+00 4.76087E+06 + 9.70000E+00 5.03342E+06 + 9.80000E+00 5.27819E+06 + 9.90000E+00 5.19382E+06 + 1.00000E+01 4.26873E+06 + 1.01000E+01 4.98547E+06 + 1.02000E+01 5.58591E+06 + 1.03000E+01 5.85491E+06 + 1.04000E+01 5.81020E+06 + 1.05000E+01 5.13621E+06 + 1.06000E+01 4.51803E+06 + 1.07000E+01 4.83900E+06 + 1.08000E+01 6.01924E+06 + 1.09000E+01 5.25391E+06 + 1.10000E+01 5.09059E+06 + 1.11000E+01 4.36360E+06 + 1.12000E+01 3.76147E+06 + 1.13000E+01 4.26817E+06 + 1.14000E+01 3.46926E+06 + 1.15000E+01 3.55107E+06 + 1.16000E+01 3.12709E+06 + 1.17000E+01 3.15665E+06 + 1.18000E+01 3.75528E+06 + 1.19000E+01 3.11781E+06 + 1.20000E+01 3.39747E+06 + 1.21000E+01 3.76543E+06 + 1.22000E+01 4.65897E+06 + 1.23000E+01 4.43240E+06 + 1.24000E+01 5.20310E+06 + 1.25000E+01 5.83845E+06 + 1.26000E+01 5.52323E+06 + 1.27000E+01 5.04745E+06 + 1.28000E+01 4.75343E+06 + 1.29000E+01 5.44051E+06 + 1.30000E+01 5.79316E+06 + 1.31000E+01 5.09515E+06 + 1.32000E+01 3.82011E+06 + 1.33000E+01 3.28761E+06 + 1.34000E+01 2.92792E+06 + 1.35000E+01 2.82581E+06 + 1.36000E+01 2.82335E+06 + 1.37000E+01 1.65934E+06 + 1.38000E+01 1.27458E+06 + 1.39000E+01 2.31980E+06 + 1.40000E+01 2.44713E+06 + 1.41000E+01 2.03502E+06 + 1.42000E+01 2.30729E+06 + 1.43000E+01 2.04732E+06 + 1.44000E+01 2.39311E+06 + 1.45000E+01 2.55261E+06 + 1.46000E+01 2.60589E+06 + 1.47000E+01 2.83975E+06 + 1.48000E+01 2.03324E+06 + 1.49000E+01 2.51818E+06 + 1.50000E+01 2.80668E+06 + 1.51000E+01 3.09396E+06 + 1.52000E+01 3.05570E+06 + 1.53000E+01 2.67651E+06 + 1.54000E+01 2.72845E+06 + 1.55000E+01 3.18920E+06 + 1.56000E+01 3.27693E+06 + 1.57000E+01 2.97656E+06 + 1.58000E+01 3.86389E+06 + 1.59000E+01 4.28470E+06 + 1.60000E+01 3.71945E+06 + 1.61000E+01 4.25266E+06 + 1.62000E+01 5.10097E+06 + 1.63000E+01 4.92964E+06 + 1.64000E+01 4.25074E+06 + 1.65000E+01 4.34412E+06 + 1.66000E+01 4.56242E+06 + 1.67000E+01 4.07210E+06 + 1.68000E+01 4.84202E+06 + 1.69000E+01 5.11961E+06 + 1.70000E+01 4.68665E+06 + 1.71000E+01 4.14410E+06 + 1.72000E+01 2.69599E+06 + 1.73000E+01 2.50709E+06 + 1.74000E+01 3.18656E+06 + 1.75000E+01 4.02043E+06 + 1.76000E+01 3.78593E+06 + 1.77000E+01 3.58911E+06 + 1.78000E+01 3.02154E+06 + 1.79000E+01 3.24120E+06 + 1.80000E+01 2.74304E+06 + 1.81000E+01 3.20602E+06 + 1.82000E+01 3.35053E+06 + 1.83000E+01 3.89161E+06 + 1.84000E+01 3.78351E+06 + 1.85000E+01 3.63847E+06 + 1.86000E+01 3.75691E+06 + 1.87000E+01 3.31381E+06 + 1.88000E+01 3.92574E+06 + 1.89000E+01 3.03412E+06 + 1.90000E+01 3.58430E+06 + 1.91000E+01 4.07894E+06 + 1.92000E+01 3.14166E+06 + 1.93000E+01 2.48761E+06 + 1.94000E+01 3.00097E+06 + 1.95000E+01 3.48083E+06 + 1.96000E+01 3.90119E+06 + 1.97000E+01 4.07213E+06 + 1.98000E+01 4.37878E+06 + 1.99000E+01 3.75340E+06 + 2.00000E+01 3.99349E+06 + 2.01000E+01 3.89327E+06 + 2.02000E+01 3.71318E+06 + 2.03000E+01 3.88391E+06 + 2.04000E+01 3.34540E+06 + 2.05000E+01 3.21968E+06 + 2.06000E+01 3.81520E+06 + 2.07000E+01 4.17915E+06 + 2.08000E+01 4.38323E+06 + 2.09000E+01 5.65566E+06 + 2.10000E+01 5.03679E+06 + 2.11000E+01 4.87324E+06 + 2.12000E+01 4.62610E+06 + 2.13000E+01 4.37443E+06 + 2.14000E+01 4.52818E+06 + 2.15000E+01 4.04777E+06 + 2.16000E+01 3.94551E+06 + 2.17000E+01 4.04424E+06 + 2.18000E+01 4.22946E+06 + 2.19000E+01 4.88892E+06 + 2.20000E+01 5.21704E+06 + 2.21000E+01 3.94874E+06 + 2.22000E+01 2.74339E+06 + 2.23000E+01 3.08180E+06 + 2.24000E+01 3.00711E+06 + 2.25000E+01 3.38799E+06 + 2.26000E+01 3.53457E+06 + 2.27000E+01 3.76873E+06 + 2.28000E+01 2.68761E+06 + 2.29000E+01 2.59174E+06 + 2.30000E+01 2.85518E+06 + 2.31000E+01 2.31628E+06 + 2.32000E+01 2.86148E+06 + 2.33000E+01 2.93932E+06 + 2.34000E+01 3.42543E+06 + 2.35000E+01 3.54056E+06 + 2.36000E+01 3.71559E+06 + 2.37000E+01 2.98942E+06 + 2.38000E+01 3.17260E+06 + 2.39000E+01 3.26034E+06 + 2.40000E+01 3.09307E+06 + 2.41000E+01 3.55784E+06 + 2.42000E+01 4.14987E+06 + 2.43000E+01 4.42290E+06 + 2.44000E+01 4.77029E+06 + 2.45000E+01 5.37015E+06 + 2.46000E+01 4.81654E+06 + 2.47000E+01 4.99566E+06 + 2.48000E+01 5.02336E+06 + 2.49000E+01 5.46690E+06 + 2.50000E+01 5.95605E+06 + 2.51000E+01 5.14307E+06 + 2.52000E+01 6.11223E+06 + 2.53000E+01 5.64081E+06 + 2.54000E+01 4.71092E+06 + 2.55000E+01 3.04656E+06 + 2.56000E+01 3.43724E+06 + 2.57000E+01 3.56671E+06 + 2.58000E+01 3.17436E+06 + 2.59000E+01 3.90432E+06 + 2.60000E+01 3.39608E+06 + 2.61000E+01 2.90020E+06 + 2.62000E+01 3.28180E+06 + 2.63000E+01 2.86256E+06 + 2.64000E+01 2.18106E+06 + 2.65000E+01 1.59665E+06 + 2.66000E+01 1.55898E+06 + 2.67000E+01 1.12684E+06 + 2.68000E+01 1.16040E+06 + 2.69000E+01 2.26656E+06 + 2.70000E+01 2.93042E+06 + 2.71000E+01 3.38823E+06 + 2.72000E+01 3.36659E+06 + 2.73000E+01 2.81589E+06 + 2.74000E+01 4.19106E+06 + 2.75000E+01 4.22857E+06 + 2.76000E+01 4.40023E+06 + 2.77000E+01 4.73163E+06 + 2.78000E+01 5.14778E+06 + 2.79000E+01 5.92209E+06 + 2.80000E+01 5.39679E+06 + 2.81000E+01 4.85020E+06 + 2.82000E+01 4.61223E+06 + 2.83000E+01 4.53528E+06 + 2.84000E+01 3.88930E+06 + 2.85000E+01 3.57137E+06 + 2.86000E+01 3.35138E+06 + 2.87000E+01 3.32217E+06 + 2.88000E+01 3.09683E+06 + 2.89000E+01 4.37841E+06 + 2.90000E+01 4.67956E+06 + 2.91000E+01 4.17429E+06 + 2.92000E+01 4.04233E+06 + 2.93000E+01 3.74030E+06 + 2.94000E+01 4.23568E+06 + 2.95000E+01 4.13425E+06 + 2.96000E+01 4.26400E+06 + 2.97000E+01 4.24325E+06 + 2.98000E+01 4.00443E+06 + 2.99000E+01 4.05195E+06 + 3.00000E+01 4.01406E+06 + 3.01000E+01 4.30592E+06 + 3.02000E+01 4.69453E+06 + 3.03000E+01 4.44901E+06 + 3.04000E+01 3.47640E+06 + 3.05000E+01 3.39693E+06 + 3.06000E+01 3.96300E+06 + 3.07000E+01 4.08087E+06 + 3.08000E+01 3.53042E+06 + 3.09000E+01 3.79363E+06 + 3.10000E+01 3.95526E+06 + 3.11000E+01 3.83974E+06 + 3.12000E+01 4.01922E+06 + 3.13000E+01 4.40837E+06 + 3.14000E+01 4.31896E+06 + 3.15000E+01 4.85234E+06 + 3.16000E+01 5.44432E+06 + 3.17000E+01 5.24882E+06 + 3.18000E+01 5.28564E+06 + 3.19000E+01 5.02298E+06 + 3.20000E+01 5.31318E+06 + 3.21000E+01 4.73914E+06 + 3.22000E+01 4.47186E+06 + 3.23000E+01 4.96335E+06 + 3.24000E+01 5.25483E+06 + 3.25000E+01 5.26077E+06 + 3.26000E+01 5.27715E+06 + 3.27000E+01 4.58498E+06 + 3.28000E+01 5.32305E+06 + 3.29000E+01 4.68791E+06 + 3.30000E+01 3.74992E+06 + 3.31000E+01 3.42666E+06 + 3.32000E+01 4.24083E+06 + 3.33000E+01 4.24350E+06 + 3.34000E+01 4.10547E+06 + 3.35000E+01 4.00819E+06 + 3.36000E+01 4.21810E+06 + 3.37000E+01 4.23122E+06 + 3.38000E+01 4.49898E+06 + 3.39000E+01 4.74513E+06 + 3.40000E+01 4.77205E+06 + 3.41000E+01 4.88514E+06 + 3.42000E+01 4.46995E+06 + 3.43000E+01 4.04559E+06 + 3.44000E+01 3.99425E+06 + 3.45000E+01 3.58070E+06 + 3.46000E+01 3.31195E+06 + 3.47000E+01 4.10434E+06 + 3.48000E+01 4.93129E+06 + 3.49000E+01 6.00766E+06 + 3.50000E+01 6.12949E+06 + 3.51000E+01 5.77760E+06 + 3.52000E+01 6.15216E+06 + 3.53000E+01 6.09400E+06 + 3.54000E+01 5.95234E+06 + 3.55000E+01 6.11172E+06 + 3.56000E+01 6.01158E+06 + 3.57000E+01 5.37315E+06 + 3.58000E+01 5.38650E+06 + 3.59000E+01 5.58778E+06 + 3.60000E+01 5.06232E+06 + 3.61000E+01 5.56274E+06 + 3.62000E+01 5.71232E+06 + 3.63000E+01 5.31578E+06 + 3.64000E+01 5.45639E+06 + 3.65000E+01 4.45569E+06 + 3.66000E+01 4.25447E+06 + 3.67000E+01 5.37213E+06 + 3.68000E+01 4.93198E+06 + 3.69000E+01 5.32468E+06 + 3.70000E+01 5.29718E+06 + 3.71000E+01 5.78310E+06 + 3.72000E+01 5.69707E+06 + 3.73000E+01 5.57014E+06 + 3.74000E+01 5.31072E+06 + 3.75000E+01 5.16407E+06 + 3.76000E+01 5.29860E+06 + 3.77000E+01 4.41584E+06 + 3.78000E+01 4.18019E+06 + 3.79000E+01 3.45100E+06 + 3.80000E+01 2.89386E+06 + 3.81000E+01 3.42166E+06 + 3.82000E+01 3.01987E+06 + 3.83000E+01 3.00513E+06 + 3.84000E+01 3.43929E+06 + 3.85000E+01 3.66475E+06 + 3.86000E+01 3.46056E+06 + 3.87000E+01 3.69446E+06 + 3.88000E+01 4.48464E+06 + 3.89000E+01 4.43500E+06 + 3.90000E+01 3.76241E+06 + 3.91000E+01 4.93085E+06 + 3.92000E+01 5.20378E+06 + 3.93000E+01 4.67042E+06 + 3.94000E+01 4.56882E+06 + 3.95000E+01 4.26641E+06 + 3.96000E+01 3.92607E+06 + 3.97000E+01 3.21208E+06 + 3.98000E+01 3.53851E+06 + 3.99000E+01 3.65964E+06 + 4.00000E+01 3.37063E+06 + 4.01000E+01 2.50708E+06 + 4.02000E+01 3.36113E+06 + 4.03000E+01 3.58011E+06 + 4.04000E+01 3.45564E+06 + 4.05000E+01 3.76128E+06 + 4.06000E+01 4.18231E+06 + 4.07000E+01 3.83884E+06 + 4.08000E+01 4.17967E+06 + 4.09000E+01 3.76475E+06 + 4.10000E+01 3.32848E+06 + 4.11000E+01 3.55375E+06 + 4.12000E+01 3.92195E+06 + 4.13000E+01 3.67705E+06 + 4.14000E+01 3.46441E+06 + 4.15000E+01 3.98905E+06 + 4.16000E+01 3.54913E+06 + 4.17000E+01 3.80016E+06 + 4.18000E+01 4.13698E+06 + 4.19000E+01 4.19359E+06 + 4.20000E+01 3.88627E+06 + 4.21000E+01 2.89609E+06 + 4.22000E+01 2.99559E+06 + 4.23000E+01 3.23265E+06 + 4.24000E+01 3.43572E+06 + 4.25000E+01 4.04606E+06 + 4.26000E+01 3.61956E+06 + 4.27000E+01 3.41258E+06 + 4.28000E+01 3.00590E+06 + 4.29000E+01 3.19242E+06 + 4.30000E+01 3.70011E+06 + 4.31000E+01 3.51092E+06 + 4.32000E+01 3.45993E+06 + 4.33000E+01 3.40810E+06 + 4.34000E+01 4.11040E+06 + 4.35000E+01 3.67209E+06 + 4.36000E+01 3.37962E+06 + 4.37000E+01 3.71391E+06 + 4.38000E+01 3.83198E+06 + 4.39000E+01 4.49565E+06 + 4.40000E+01 3.89953E+06 + 4.41000E+01 4.06339E+06 + 4.42000E+01 4.33109E+06 + 4.43000E+01 3.92758E+06 + 4.44000E+01 4.73286E+06 + 4.45000E+01 4.64339E+06 + 4.46000E+01 4.43781E+06 + 4.47000E+01 4.44684E+06 + 4.48000E+01 5.16368E+06 + 4.49000E+01 5.37047E+06 + 4.50000E+01 5.55575E+06 + 4.51000E+01 5.68638E+06 + 4.52000E+01 5.78576E+06 + 4.53000E+01 6.43246E+06 + 4.54000E+01 6.36064E+06 + 4.55000E+01 5.51321E+06 + 4.56000E+01 5.43753E+06 + 4.57000E+01 5.81968E+06 + 4.58000E+01 5.66267E+06 + 4.59000E+01 5.68508E+06 + 4.60000E+01 4.47924E+06 + 4.61000E+01 4.23166E+06 + 4.62000E+01 4.56279E+06 + 4.63000E+01 4.03842E+06 + 4.64000E+01 4.17480E+06 + 4.65000E+01 4.57681E+06 + 4.66000E+01 3.92033E+06 + 4.67000E+01 4.34409E+06 + 4.68000E+01 4.72783E+06 + 4.69000E+01 5.57014E+06 + 4.70000E+01 4.46287E+06 + 4.71000E+01 4.62761E+06 + 4.72000E+01 3.85169E+06 + 4.73000E+01 3.58661E+06 + 4.74000E+01 2.84042E+06 + 4.75000E+01 3.15095E+06 + 4.76000E+01 4.21563E+06 + 4.77000E+01 3.83249E+06 + 4.78000E+01 3.63145E+06 + 4.79000E+01 3.93414E+06 + 4.80000E+01 3.52119E+06 + 4.81000E+01 3.31257E+06 + 4.82000E+01 3.07536E+06 + 4.83000E+01 3.88262E+06 + 4.84000E+01 2.75471E+06 + 4.85000E+01 2.90759E+06 + 4.86000E+01 3.32537E+06 + 4.87000E+01 3.55763E+06 + 4.88000E+01 3.93472E+06 + 4.89000E+01 3.35684E+06 + 4.90000E+01 3.37995E+06 + 4.91000E+01 3.81184E+06 + 4.92000E+01 4.55025E+06 + 4.93000E+01 4.68338E+06 + 4.94000E+01 4.39077E+06 + 4.95000E+01 4.52406E+06 + 4.96000E+01 4.26200E+06 + 4.97000E+01 4.69242E+06 + 4.98000E+01 5.12795E+06 + 4.99000E+01 4.44629E+06 + 5.00000E+01 4.45330E+06 + 5.01000E+01 3.87823E+06 + 5.02000E+01 3.43897E+06 + 5.03000E+01 3.52103E+06 + 5.04000E+01 3.40217E+06 + 5.05000E+01 3.48488E+06 + 5.06000E+01 3.59933E+06 + 5.07000E+01 3.81539E+06 + 5.08000E+01 4.90732E+06 + 5.09000E+01 5.93164E+06 + 5.10000E+01 6.26959E+06 + 5.11000E+01 6.31517E+06 + 5.12000E+01 5.79316E+06 + 5.13000E+01 6.60192E+06 + 5.14000E+01 7.11947E+06 + 5.15000E+01 7.23399E+06 + 5.16000E+01 6.15124E+06 + 5.17000E+01 5.53732E+06 + 5.18000E+01 5.76032E+06 + 5.19000E+01 6.07304E+06 + 5.20000E+01 5.91917E+06 + 5.21000E+01 6.15663E+06 + 5.22000E+01 6.16957E+06 + 5.23000E+01 7.21247E+06 + 5.24000E+01 7.97890E+06 + 5.25000E+01 7.89177E+06 + 5.26000E+01 6.54133E+06 + 5.27000E+01 6.10284E+06 + 5.28000E+01 5.95799E+06 + 5.29000E+01 5.45396E+06 + 5.30000E+01 4.62182E+06 + 5.31000E+01 4.56043E+06 + 5.32000E+01 4.92980E+06 + 5.33000E+01 5.39000E+06 + 5.34000E+01 5.57090E+06 + 5.35000E+01 5.34833E+06 + 5.36000E+01 5.43529E+06 + 5.37000E+01 4.90684E+06 + 5.38000E+01 4.39460E+06 + 5.39000E+01 4.60465E+06 + 5.40000E+01 5.28854E+06 + 5.41000E+01 5.82139E+06 + 5.42000E+01 6.28212E+06 + 5.43000E+01 5.94758E+06 + 5.44000E+01 5.42052E+06 + 5.45000E+01 5.11026E+06 + 5.46000E+01 4.90720E+06 + 5.47000E+01 4.73353E+06 + 5.48000E+01 4.81418E+06 + 5.49000E+01 4.85938E+06 + 5.50000E+01 5.47668E+06 + 5.51000E+01 4.84231E+06 + 5.52000E+01 5.54603E+06 + 5.53000E+01 5.69226E+06 + 5.54000E+01 5.87792E+06 + 5.55000E+01 6.16053E+06 + 5.56000E+01 6.46833E+06 + 5.57000E+01 5.86315E+06 + 5.58000E+01 5.13560E+06 + 5.59000E+01 5.75877E+06 + 5.60000E+01 5.94689E+06 + 5.61000E+01 5.57725E+06 + 5.62000E+01 5.64995E+06 + 5.63000E+01 5.99072E+06 + 5.64000E+01 6.34798E+06 + 5.65000E+01 7.09159E+06 + 5.66000E+01 7.17436E+06 + 5.67000E+01 7.11878E+06 + 5.68000E+01 7.05282E+06 + 5.69000E+01 6.20451E+06 + 5.70000E+01 6.44388E+06 + 5.71000E+01 5.65862E+06 + 5.72000E+01 5.30156E+06 + 5.73000E+01 5.64415E+06 + 5.74000E+01 5.29275E+06 + 5.75000E+01 4.69660E+06 + 5.76000E+01 5.37068E+06 + 5.77000E+01 5.48422E+06 + 5.78000E+01 4.57795E+06 + 5.79000E+01 4.31153E+06 + 5.80000E+01 3.43066E+06 + 5.81000E+01 3.14308E+06 + 5.82000E+01 4.09576E+06 + 5.83000E+01 4.77598E+06 + 5.84000E+01 5.87747E+06 + 5.85000E+01 5.84988E+06 + 5.86000E+01 6.20162E+06 + 5.87000E+01 5.82591E+06 + 5.88000E+01 6.10030E+06 + 5.89000E+01 4.92854E+06 + 5.90000E+01 5.29175E+06 + 5.91000E+01 5.47428E+06 + 5.92000E+01 5.34090E+06 + 5.93000E+01 5.31746E+06 + 5.94000E+01 4.56272E+06 + 5.95000E+01 4.67449E+06 + 5.96000E+01 4.88715E+06 + 5.97000E+01 5.21010E+06 + 5.98000E+01 5.03474E+06 + 5.99000E+01 5.30874E+06 + 6.00000E+01 4.96927E+06 + 6.01000E+01 4.22716E+06 + 6.02000E+01 3.88172E+06 + 6.03000E+01 3.92463E+06 + 6.04000E+01 4.07790E+06 + 6.05000E+01 3.75259E+06 + 6.06000E+01 4.02473E+06 + 6.07000E+01 4.23336E+06 + 6.08000E+01 4.22660E+06 + 6.09000E+01 3.81470E+06 + 6.10000E+01 4.75772E+06 + 6.11000E+01 5.21880E+06 + 6.12000E+01 4.58918E+06 + 6.13000E+01 4.01833E+06 + 6.14000E+01 3.38780E+06 + 6.15000E+01 2.78314E+06 + 6.16000E+01 3.33481E+06 + 6.17000E+01 4.23637E+06 + 6.18000E+01 4.55469E+06 + 6.19000E+01 4.27113E+06 + 6.20000E+01 5.27410E+06 + 6.21000E+01 5.91095E+06 + 6.22000E+01 5.79895E+06 + 6.23000E+01 5.88302E+06 + 6.24000E+01 5.72885E+06 + 6.25000E+01 5.91985E+06 + 6.26000E+01 5.68730E+06 + 6.27000E+01 5.13603E+06 + 6.28000E+01 4.01191E+06 + 6.29000E+01 3.71508E+06 + 6.30000E+01 3.30765E+06 + 6.31000E+01 2.57193E+06 + 6.32000E+01 2.84821E+06 + 6.33000E+01 3.57587E+06 + 6.34000E+01 3.66771E+06 + 6.35000E+01 3.57067E+06 + 6.36000E+01 3.69618E+06 + 6.37000E+01 3.85120E+06 + 6.38000E+01 3.96140E+06 + 6.39000E+01 5.02263E+06 + 6.40000E+01 5.04413E+06 + 6.41000E+01 5.10641E+06 + 6.42000E+01 5.35418E+06 + 6.43000E+01 4.32356E+06 + 6.44000E+01 3.41367E+06 + 6.45000E+01 3.45654E+06 + 6.46000E+01 2.59754E+06 + 6.47000E+01 2.17732E+06 + 6.48000E+01 1.56258E+06 + 6.49000E+01 1.91915E+06 + 6.50000E+01 3.07884E+06 + 6.51000E+01 2.70251E+06 + 6.52000E+01 2.15451E+06 + 6.53000E+01 2.63633E+06 + 6.54000E+01 2.78041E+06 + 6.55000E+01 2.86886E+06 + 6.56000E+01 2.76453E+06 + 6.57000E+01 3.55523E+06 + 6.58000E+01 3.27472E+06 + 6.59000E+01 3.06531E+06 + 6.60000E+01 3.48230E+06 + 6.61000E+01 3.89342E+06 + 6.62000E+01 3.55989E+06 + 6.63000E+01 4.01508E+06 + 6.64000E+01 3.90820E+06 + 6.65000E+01 3.28085E+06 + 6.66000E+01 2.81109E+06 + 6.67000E+01 2.91393E+06 + 6.68000E+01 4.08586E+06 + 6.69000E+01 4.33366E+06 + 6.70000E+01 4.75883E+06 + 6.71000E+01 4.52670E+06 + 6.72000E+01 5.07798E+06 + 6.73000E+01 4.91990E+06 + 6.74000E+01 4.76436E+06 + 6.75000E+01 4.96852E+06 + 6.76000E+01 5.04857E+06 + 6.77000E+01 5.13778E+06 + 6.78000E+01 6.04639E+06 + 6.79000E+01 6.08716E+06 + 6.80000E+01 6.34712E+06 + 6.81000E+01 5.83200E+06 + 6.82000E+01 5.81269E+06 + 6.83000E+01 5.90746E+06 + 6.84000E+01 5.66916E+06 + 6.85000E+01 5.38325E+06 + 6.86000E+01 5.22115E+06 + 6.87000E+01 5.26326E+06 + 6.88000E+01 4.43710E+06 + 6.89000E+01 4.62977E+06 + 6.90000E+01 5.65075E+06 + 6.91000E+01 7.03518E+06 + 6.92000E+01 7.47327E+06 + 6.93000E+01 6.41271E+06 + 6.94000E+01 5.51983E+06 + 6.95000E+01 4.97815E+06 + 6.96000E+01 5.21783E+06 + 6.97000E+01 5.63307E+06 + 6.98000E+01 5.13355E+06 + 6.99000E+01 5.66736E+06 + 7.00000E+01 5.64664E+06 + 7.01000E+01 5.32267E+06 + 7.02000E+01 4.92323E+06 + 7.03000E+01 3.66106E+06 + 7.04000E+01 4.47824E+06 + 7.05000E+01 4.19509E+06 + 7.06000E+01 4.36841E+06 + 7.07000E+01 4.41092E+06 + 7.08000E+01 3.89158E+06 + 7.09000E+01 3.96619E+06 + 7.10000E+01 3.86995E+06 + 7.11000E+01 2.88162E+06 + 7.12000E+01 2.25732E+06 + 7.13000E+01 1.90967E+06 + 7.14000E+01 2.84833E+06 + 7.15000E+01 3.22676E+06 + 7.16000E+01 3.56426E+06 + 7.17000E+01 3.67215E+06 + 7.18000E+01 4.29534E+06 + 7.19000E+01 4.32692E+06 + 7.20000E+01 4.39557E+06 + 7.21000E+01 4.31236E+06 + 7.22000E+01 3.66551E+06 + 7.23000E+01 3.16328E+06 + 7.24000E+01 2.60398E+06 + 7.25000E+01 2.05849E+06 + 7.26000E+01 1.58067E+06 + 7.27000E+01 2.06917E+06 + 7.28000E+01 1.85601E+06 + 7.29000E+01 2.31738E+06 + 7.30000E+01 2.47478E+06 + 7.31000E+01 2.54859E+06 + 7.32000E+01 2.56202E+06 + 7.33000E+01 3.32653E+06 + 7.34000E+01 3.46989E+06 + 7.35000E+01 3.49184E+06 + 7.36000E+01 4.30476E+06 + 7.37000E+01 3.35621E+06 + 7.38000E+01 3.32999E+06 + 7.39000E+01 4.12979E+06 + 7.40000E+01 4.27026E+06 + 7.41000E+01 4.11396E+06 + 7.42000E+01 3.67815E+06 + 7.43000E+01 2.75682E+06 + 7.44000E+01 2.48473E+06 + 7.45000E+01 3.20531E+06 + 7.46000E+01 3.75656E+06 + 7.47000E+01 4.14901E+06 + 7.48000E+01 4.41953E+06 + 7.49000E+01 4.36912E+06 + 7.50000E+01 3.99118E+06 + 7.51000E+01 3.33786E+06 + 7.52000E+01 3.66382E+06 + 7.53000E+01 4.19771E+06 + 7.54000E+01 5.12942E+06 + 7.55000E+01 5.54730E+06 + 7.56000E+01 4.88978E+06 + 7.57000E+01 4.29022E+06 + 7.58000E+01 3.77011E+06 + 7.59000E+01 3.52687E+06 + 7.60000E+01 4.25812E+06 + 7.61000E+01 3.71174E+06 + 7.62000E+01 3.19210E+06 + 7.63000E+01 2.26691E+06 + 7.64000E+01 2.59144E+06 + 7.65000E+01 3.18473E+06 + 7.66000E+01 3.33187E+06 + 7.67000E+01 3.43099E+06 + 7.68000E+01 3.16907E+06 + 7.69000E+01 3.26501E+06 + 7.70000E+01 3.31196E+06 + 7.71000E+01 3.86912E+06 + 7.72000E+01 3.56039E+06 + 7.73000E+01 4.06083E+06 + 7.74000E+01 4.01212E+06 + 7.75000E+01 4.32877E+06 + 7.76000E+01 3.85305E+06 + 7.77000E+01 3.83193E+06 + 7.78000E+01 3.70047E+06 + 7.79000E+01 3.89943E+06 + 7.80000E+01 4.11555E+06 + 7.81000E+01 4.36304E+06 + 7.82000E+01 5.05238E+06 + 7.83000E+01 4.63009E+06 + 7.84000E+01 4.04998E+06 + 7.85000E+01 3.92604E+06 + 7.86000E+01 3.57419E+06 + 7.87000E+01 3.76955E+06 + 7.88000E+01 3.95645E+06 + 7.89000E+01 3.15466E+06 + 7.90000E+01 4.51078E+06 + 7.91000E+01 5.31259E+06 + 7.92000E+01 5.05380E+06 + 7.93000E+01 5.68200E+06 + 7.94000E+01 6.03758E+06 + 7.95000E+01 5.92476E+06 + 7.96000E+01 5.64473E+06 + 7.97000E+01 5.26123E+06 + 7.98000E+01 5.84726E+06 + 7.99000E+01 5.55847E+06 + 8.00000E+01 5.80215E+06 + 8.01000E+01 6.03674E+06 + 8.02000E+01 5.80984E+06 + 8.03000E+01 5.39224E+06 + 8.04000E+01 4.44750E+06 + 8.05000E+01 4.16306E+06 + 8.06000E+01 5.33386E+06 + 8.07000E+01 5.60679E+06 + 8.08000E+01 6.51706E+06 + 8.09000E+01 6.40508E+06 + 8.10000E+01 5.47776E+06 + 8.11000E+01 6.01933E+06 + 8.12000E+01 4.80309E+06 + 8.13000E+01 4.95354E+06 + 8.14000E+01 4.92668E+06 + 8.15000E+01 4.69768E+06 + 8.16000E+01 4.55048E+06 + 8.17000E+01 4.41168E+06 + 8.18000E+01 5.23861E+06 + 8.19000E+01 4.60286E+06 + 8.20000E+01 4.44802E+06 + 8.21000E+01 3.85933E+06 + 8.22000E+01 2.95455E+06 + 8.23000E+01 2.36186E+06 + 8.24000E+01 2.35148E+06 + 8.25000E+01 1.40524E+06 + 8.26000E+01 2.10423E+06 + 8.27000E+01 2.26774E+06 + 8.28000E+01 2.72513E+06 + 8.29000E+01 2.37714E+06 + 8.30000E+01 2.46216E+06 + 8.31000E+01 2.16286E+06 + 8.32000E+01 2.50602E+06 + 8.33000E+01 3.11246E+06 + 8.34000E+01 2.96411E+06 + 8.35000E+01 2.93665E+06 + 8.36000E+01 3.65976E+06 + 8.37000E+01 3.02752E+06 + 8.38000E+01 3.18071E+06 + 8.39000E+01 3.82542E+06 + 8.40000E+01 3.54290E+06 + 8.41000E+01 2.70098E+06 + 8.42000E+01 2.16282E+06 + 8.43000E+01 2.28177E+06 + 8.44000E+01 2.79386E+06 + 8.45000E+01 3.93697E+06 + 8.46000E+01 4.06684E+06 + 8.47000E+01 3.83886E+06 + 8.48000E+01 3.20487E+06 + 8.49000E+01 3.24463E+06 + 8.50000E+01 3.16765E+06 + 8.51000E+01 2.06732E+06 + 8.52000E+01 1.32365E+06 + 8.53000E+01 9.71798E+05 + 8.54000E+01 1.48878E+06 + 8.55000E+01 2.44105E+06 + 8.56000E+01 3.24885E+06 + 8.57000E+01 3.54017E+06 + 8.58000E+01 3.15594E+06 + 8.59000E+01 3.61060E+06 + 8.60000E+01 4.14337E+06 + 8.61000E+01 3.52737E+06 + 8.62000E+01 3.04032E+06 + 8.63000E+01 3.01966E+06 + 8.64000E+01 3.03138E+06 + 8.65000E+01 2.99440E+06 + 8.66000E+01 3.00494E+06 + 8.67000E+01 2.90698E+06 + 8.68000E+01 2.98699E+06 + 8.69000E+01 3.23532E+06 + 8.70000E+01 2.78964E+06 + 8.71000E+01 3.43327E+06 + 8.72000E+01 2.92879E+06 + 8.73000E+01 2.84851E+06 + 8.74000E+01 2.82264E+06 + 8.75000E+01 3.85484E+06 + 8.76000E+01 4.36296E+06 + 8.77000E+01 4.00322E+06 + 8.78000E+01 4.53325E+06 + 8.79000E+01 4.80874E+06 + 8.80000E+01 4.93811E+06 + 8.81000E+01 4.95805E+06 + 8.82000E+01 4.86648E+06 + 8.83000E+01 5.24697E+06 + 8.84000E+01 5.53341E+06 + 8.85000E+01 5.05433E+06 + 8.86000E+01 5.57420E+06 + 8.87000E+01 5.58604E+06 + 8.88000E+01 5.96851E+06 + 8.89000E+01 6.66920E+06 + 8.90000E+01 6.95361E+06 + 8.91000E+01 6.72515E+06 + 8.92000E+01 7.20438E+06 + 8.93000E+01 6.99596E+06 + 8.94000E+01 6.44281E+06 + 8.95000E+01 6.40160E+06 + 8.96000E+01 6.32326E+06 + 8.97000E+01 6.10931E+06 + 8.98000E+01 5.58337E+06 + 8.99000E+01 4.39156E+06 + 9.00000E+01 4.65670E+06 + 9.01000E+01 4.13859E+06 + 9.02000E+01 3.54164E+06 + 9.03000E+01 4.07219E+06 + 9.04000E+01 4.70167E+06 + 9.05000E+01 4.70839E+06 + 9.06000E+01 4.83943E+06 + 9.07000E+01 4.34646E+06 + 9.08000E+01 4.52632E+06 + 9.09000E+01 4.31167E+06 + 9.10000E+01 4.10239E+06 + 9.11000E+01 3.69762E+06 + 9.12000E+01 3.33869E+06 + 9.13000E+01 3.99553E+06 + 9.14000E+01 4.59034E+06 + 9.15000E+01 5.13676E+06 + 9.16000E+01 4.83979E+06 + 9.17000E+01 5.35900E+06 + 9.18000E+01 5.61971E+06 + 9.19000E+01 5.26821E+06 + 9.20000E+01 5.41467E+06 + 9.21000E+01 5.38137E+06 + 9.22000E+01 5.44670E+06 + 9.23000E+01 5.07643E+06 + 9.24000E+01 4.80071E+06 + 9.25000E+01 4.04129E+06 + 9.26000E+01 4.62217E+06 + 9.27000E+01 5.49979E+06 + 9.28000E+01 5.28436E+06 + 9.29000E+01 4.79224E+06 + 9.30000E+01 5.27535E+06 + 9.31000E+01 6.09509E+06 + 9.32000E+01 6.83631E+06 + 9.33000E+01 6.86972E+06 + 9.34000E+01 6.80046E+06 + 9.35000E+01 6.20398E+06 + 9.36000E+01 5.66670E+06 + 9.37000E+01 5.35055E+06 + 9.38000E+01 4.70904E+06 + 9.39000E+01 4.69678E+06 + 9.40000E+01 5.12041E+06 + 9.41000E+01 4.59438E+06 + 9.42000E+01 4.39901E+06 + 9.43000E+01 4.20533E+06 + 9.44000E+01 3.56417E+06 + 9.45000E+01 4.49649E+06 + 9.46000E+01 4.68770E+06 + 9.47000E+01 4.99467E+06 + 9.48000E+01 4.81455E+06 + 9.49000E+01 5.30551E+06 + 9.50000E+01 6.05930E+06 + 9.51000E+01 6.49132E+06 + 9.52000E+01 6.26996E+06 + 9.53000E+01 5.41136E+06 + 9.54000E+01 4.43857E+06 + 9.55000E+01 4.74170E+06 + 9.56000E+01 3.94422E+06 + 9.57000E+01 4.09480E+06 + 9.58000E+01 4.24352E+06 + 9.59000E+01 4.40023E+06 + 9.60000E+01 3.84641E+06 + 9.61000E+01 3.54973E+06 + 9.62000E+01 3.82619E+06 + 9.63000E+01 3.41297E+06 + 9.64000E+01 3.72068E+06 + 9.65000E+01 4.39507E+06 + 9.66000E+01 4.14026E+06 + 9.67000E+01 3.91034E+06 + 9.68000E+01 4.86259E+06 + 9.69000E+01 5.16234E+06 + 9.70000E+01 6.15954E+06 + 9.71000E+01 6.31384E+06 + 9.72000E+01 5.79068E+06 + 9.73000E+01 5.50441E+06 + 9.74000E+01 5.20224E+06 + 9.75000E+01 4.61702E+06 + 9.76000E+01 4.57638E+06 + 9.77000E+01 4.81078E+06 + 9.78000E+01 4.22266E+06 + 9.79000E+01 4.53137E+06 + 9.80000E+01 5.31488E+06 + 9.81000E+01 5.92450E+06 + 9.82000E+01 5.34357E+06 + 9.83000E+01 4.10778E+06 + 9.84000E+01 2.77563E+06 + 9.85000E+01 3.04226E+06 + 9.86000E+01 3.38242E+06 + 9.87000E+01 3.07234E+06 + 9.88000E+01 3.48760E+06 + 9.89000E+01 3.49473E+06 + 9.90000E+01 4.08729E+06 + 9.91000E+01 3.93764E+06 + 9.92000E+01 3.01986E+06 + 9.93000E+01 3.07322E+06 + 9.94000E+01 3.32842E+06 + 9.95000E+01 3.88541E+06 + 9.96000E+01 3.78451E+06 + 9.97000E+01 3.85126E+06 + 9.98000E+01 4.35181E+06 + 9.99000E+01 5.10211E+06 + 1.00000E+02 5.67325E+06 + 1.00100E+02 6.39017E+06 + 1.00200E+02 6.77130E+06 + 1.00300E+02 6.79478E+06 + 1.00400E+02 6.17959E+06 + 1.00500E+02 6.21477E+06 + 1.00600E+02 6.31963E+06 + 1.00700E+02 5.84239E+06 + 1.00800E+02 5.92341E+06 + 1.00900E+02 6.68198E+06 + 1.01000E+02 5.92314E+06 + 1.01100E+02 5.52210E+06 + 1.01200E+02 5.55081E+06 + 1.01300E+02 6.38118E+06 + 1.01400E+02 6.68466E+06 + 1.01500E+02 6.70606E+06 + 1.01600E+02 6.44311E+06 + 1.01700E+02 6.37538E+06 + 1.01800E+02 5.96414E+06 + 1.01900E+02 4.95392E+06 + 1.02000E+02 5.15671E+06 + 1.02100E+02 5.08704E+06 + 1.02200E+02 5.51012E+06 + 1.02300E+02 4.71811E+06 + 1.02400E+02 4.27137E+06 + 1.02500E+02 3.49042E+06 + 1.02600E+02 4.04412E+06 + 1.02700E+02 4.45899E+06 + 1.02800E+02 5.18981E+06 + 1.02900E+02 6.04416E+06 + 1.03000E+02 6.13459E+06 + 1.03100E+02 5.01826E+06 + 1.03200E+02 5.70470E+06 + 1.03300E+02 5.86455E+06 + 1.03400E+02 5.65110E+06 + 1.03500E+02 4.57396E+06 + 1.03600E+02 5.33202E+06 + 1.03700E+02 4.82640E+06 + 1.03800E+02 5.15408E+06 + 1.03900E+02 4.38599E+06 + 1.04000E+02 4.69997E+06 + 1.04100E+02 4.67230E+06 + 1.04200E+02 4.85949E+06 + 1.04300E+02 5.41838E+06 + 1.04400E+02 5.48211E+06 + 1.04500E+02 5.14530E+06 + 1.04600E+02 5.25607E+06 + 1.04700E+02 4.92940E+06 + 1.04800E+02 4.73786E+06 + 1.04900E+02 4.90468E+06 + 1.05000E+02 4.63485E+06 + 1.05100E+02 5.05756E+06 + 1.05200E+02 5.86996E+06 + 1.05300E+02 5.67996E+06 + 1.05400E+02 5.17497E+06 + 1.05500E+02 5.27342E+06 + 1.05600E+02 6.04120E+06 + 1.05700E+02 4.75777E+06 + 1.05800E+02 4.26135E+06 + 1.05900E+02 4.04004E+06 + 1.06000E+02 3.95752E+06 + 1.06100E+02 4.43446E+06 + 1.06200E+02 4.04551E+06 + 1.06300E+02 4.59174E+06 + 1.06400E+02 4.62542E+06 + 1.06500E+02 4.98596E+06 + 1.06600E+02 5.83106E+06 + 1.06700E+02 6.18353E+06 + 1.06800E+02 5.92543E+06 + 1.06900E+02 5.39178E+06 + 1.07000E+02 5.17794E+06 + 1.07100E+02 5.46643E+06 + 1.07200E+02 5.45582E+06 + 1.07300E+02 5.75843E+06 + 1.07400E+02 5.43224E+06 + 1.07500E+02 4.63559E+06 + 1.07600E+02 4.26371E+06 + 1.07700E+02 3.47619E+06 + 1.07800E+02 3.11087E+06 + 1.07900E+02 2.87808E+06 + 1.08000E+02 3.14903E+06 + 1.08100E+02 3.17642E+06 + 1.08200E+02 3.94079E+06 + 1.08300E+02 4.12756E+06 + 1.08400E+02 4.13422E+06 + 1.08500E+02 4.86174E+06 + 1.08600E+02 5.15292E+06 + 1.08700E+02 4.43355E+06 + 1.08800E+02 4.95242E+06 + 1.08900E+02 4.05497E+06 + 1.09000E+02 3.81067E+06 + 1.09100E+02 4.14346E+06 + 1.09200E+02 4.05566E+06 + 1.09300E+02 4.26677E+06 + 1.09400E+02 3.67515E+06 + 1.09500E+02 3.59233E+06 + 1.09600E+02 3.78388E+06 + 1.09700E+02 3.93174E+06 + 1.09800E+02 3.74610E+06 + 1.09900E+02 4.01858E+06 + 1.10000E+02 3.98303E+06 + 1.10100E+02 3.61836E+06 + 1.10200E+02 2.92099E+06 + 1.10300E+02 3.30354E+06 + 1.10400E+02 3.88817E+06 + 1.10500E+02 4.25430E+06 + 1.10600E+02 3.96702E+06 + 1.10700E+02 4.16058E+06 + 1.10800E+02 3.58442E+06 + 1.10900E+02 3.53934E+06 + 1.11000E+02 3.80359E+06 + 1.11100E+02 4.26186E+06 + 1.11200E+02 4.45664E+06 + 1.11300E+02 4.51060E+06 + 1.11400E+02 4.55357E+06 + 1.11500E+02 5.22037E+06 + 1.11600E+02 4.70562E+06 + 1.11700E+02 3.83403E+06 + 1.11800E+02 3.47410E+06 + 1.11900E+02 3.12892E+06 + 1.12000E+02 3.22915E+06 + 1.12100E+02 3.47949E+06 + 1.12200E+02 4.17074E+06 + 1.12300E+02 5.09280E+06 + 1.12400E+02 5.53100E+06 + 1.12500E+02 5.77804E+06 + 1.12600E+02 6.43698E+06 + 1.12700E+02 6.34439E+06 + 1.12800E+02 6.59815E+06 + 1.12900E+02 5.61349E+06 + 1.13000E+02 5.86216E+06 + 1.13100E+02 6.52072E+06 + 1.13200E+02 6.21445E+06 + 1.13300E+02 6.19954E+06 + 1.13400E+02 6.61088E+06 + 1.13500E+02 5.96472E+06 + 1.13600E+02 5.62653E+06 + 1.13700E+02 5.52676E+06 + 1.13800E+02 4.90874E+06 + 1.13900E+02 4.18880E+06 + 1.14000E+02 4.76455E+06 + 1.14100E+02 5.04744E+06 + 1.14200E+02 4.94467E+06 + 1.14300E+02 4.27670E+06 + 1.14400E+02 4.27798E+06 + 1.14500E+02 4.76068E+06 + 1.14600E+02 5.28381E+06 + 1.14700E+02 4.46756E+06 + 1.14800E+02 4.01709E+06 + 1.14900E+02 4.04068E+06 + 1.15000E+02 4.42341E+06 + 1.15100E+02 4.72814E+06 + 1.15200E+02 5.22770E+06 + 1.15300E+02 5.37225E+06 + 1.15400E+02 5.07959E+06 + 1.15500E+02 5.17116E+06 + 1.15600E+02 4.62084E+06 + 1.15700E+02 4.83519E+06 + 1.15800E+02 4.90702E+06 + 1.15900E+02 4.79733E+06 + 1.16000E+02 4.41049E+06 + 1.16100E+02 4.54295E+06 + 1.16200E+02 3.66946E+06 + 1.16300E+02 3.88546E+06 + 1.16400E+02 4.93838E+06 + 1.16500E+02 4.69946E+06 + 1.16600E+02 3.85546E+06 + 1.16700E+02 3.96564E+06 + 1.16800E+02 3.65023E+06 + 1.16900E+02 3.29050E+06 + 1.17000E+02 2.75104E+06 + 1.17100E+02 2.45442E+06 + 1.17200E+02 2.47062E+06 + 1.17300E+02 3.04526E+06 + 1.17400E+02 3.04896E+06 + 1.17500E+02 3.44222E+06 + 1.17600E+02 3.85079E+06 + 1.17700E+02 4.59516E+06 + 1.17800E+02 5.02407E+06 + 1.17900E+02 4.32425E+06 + 1.18000E+02 4.44186E+06 + 1.18100E+02 4.36698E+06 + 1.18200E+02 3.37080E+06 + 1.18300E+02 3.93258E+06 + 1.18400E+02 3.59921E+06 + 1.18500E+02 3.17946E+06 + 1.18600E+02 2.95517E+06 + 1.18700E+02 3.11960E+06 + 1.18800E+02 3.81799E+06 + 1.18900E+02 4.65300E+06 + 1.19000E+02 5.03074E+06 + 1.19100E+02 4.59236E+06 + 1.19200E+02 5.90916E+06 + 1.19300E+02 6.96501E+06 + 1.19400E+02 6.06422E+06 + 1.19500E+02 5.01421E+06 + 1.19600E+02 5.18829E+06 + 1.19700E+02 5.62554E+06 + 1.19800E+02 4.55850E+06 + 1.19900E+02 4.06301E+06 + 1.20000E+02 4.15620E+06 + 1.20100E+02 4.38514E+06 + 1.20200E+02 5.06460E+06 + 1.20300E+02 5.29735E+06 + 1.20400E+02 5.64766E+06 + 1.20500E+02 5.16251E+06 + 1.20600E+02 5.00510E+06 + 1.20700E+02 4.76111E+06 + 1.20800E+02 4.50103E+06 + 1.20900E+02 3.98199E+06 + 1.21000E+02 4.33536E+06 + 1.21100E+02 4.52236E+06 + 1.21200E+02 4.89727E+06 + 1.21300E+02 6.27407E+06 + 1.21400E+02 6.69158E+06 + 1.21500E+02 6.87727E+06 + 1.21600E+02 6.85148E+06 + 1.21700E+02 6.69723E+06 + 1.21800E+02 7.24239E+06 + 1.21900E+02 7.43614E+06 + 1.22000E+02 7.26362E+06 + 1.22100E+02 7.32048E+06 + 1.22200E+02 7.17451E+06 + 1.22300E+02 6.68785E+06 + 1.22400E+02 6.47673E+06 + 1.22500E+02 7.06884E+06 + 1.22600E+02 7.16471E+06 + 1.22700E+02 7.19159E+06 + 1.22800E+02 7.19817E+06 + 1.22900E+02 6.71477E+06 + 1.23000E+02 6.74278E+06 + 1.23100E+02 6.36950E+06 + 1.23200E+02 5.86172E+06 + 1.23300E+02 6.11131E+06 + 1.23400E+02 6.24521E+06 + 1.23500E+02 5.35597E+06 + 1.23600E+02 4.80663E+06 + 1.23700E+02 5.21548E+06 + 1.23800E+02 4.62696E+06 + 1.23900E+02 4.00844E+06 + 1.24000E+02 4.06361E+06 + 1.24100E+02 5.20106E+06 + 1.24200E+02 5.48775E+06 + 1.24300E+02 6.08466E+06 + 1.24400E+02 6.14896E+06 + 1.24500E+02 7.07204E+06 + 1.24600E+02 6.85982E+06 + 1.24700E+02 6.55797E+06 + 1.24800E+02 6.49263E+06 + 1.24900E+02 5.40581E+06 + 1.25000E+02 5.38805E+06 + 1.25100E+02 5.34536E+06 + 1.25200E+02 6.12930E+06 + 1.25300E+02 6.82369E+06 + 1.25400E+02 6.46236E+06 + 1.25500E+02 6.27468E+06 + 1.25600E+02 5.96002E+06 + 1.25700E+02 6.62990E+06 + 1.25800E+02 5.95759E+06 + 1.25900E+02 5.73461E+06 + 1.26000E+02 5.71970E+06 + 1.26100E+02 6.54588E+06 + 1.26200E+02 6.20845E+06 + 1.26300E+02 5.91141E+06 + 1.26400E+02 4.51512E+06 + 1.26500E+02 4.69697E+06 + 1.26600E+02 5.08780E+06 + 1.26700E+02 4.77013E+06 + 1.26800E+02 5.40880E+06 + 1.26900E+02 5.76489E+06 + 1.27000E+02 5.07803E+06 + 1.27100E+02 5.06013E+06 + 1.27200E+02 4.34115E+06 + 1.27300E+02 5.17898E+06 + 1.27400E+02 5.12873E+06 + 1.27500E+02 5.09583E+06 + 1.27600E+02 4.58530E+06 + 1.27700E+02 4.39695E+06 + 1.27800E+02 3.58979E+06 + 1.27900E+02 3.31351E+06 + 1.28000E+02 2.78793E+06 + 1.28100E+02 1.95844E+06 + 1.28200E+02 1.55034E+06 + 1.28300E+02 2.36443E+06 + 1.28400E+02 2.07653E+06 + 1.28500E+02 2.15486E+06 + 1.28600E+02 1.50680E+06 + 1.28700E+02 1.33766E+06 + 1.28800E+02 7.80360E+05 + 1.28900E+02 1.24821E+06 + 1.29000E+02 1.53505E+06 + 1.29100E+02 1.74712E+06 + 1.29200E+02 2.65793E+06 + 1.29300E+02 2.91002E+06 + 1.29400E+02 3.68358E+06 + 1.29500E+02 4.08285E+06 + 1.29600E+02 4.25705E+06 + 1.29700E+02 4.17341E+06 + 1.29800E+02 3.43451E+06 + 1.29900E+02 3.32392E+06 + 1.30000E+02 2.95966E+06 + 1.30100E+02 2.50573E+06 + 1.30200E+02 2.13035E+06 + 1.30300E+02 1.80302E+06 + 1.30400E+02 1.84009E+06 + 1.30500E+02 2.49794E+06 + 1.30600E+02 2.10944E+06 + 1.30700E+02 1.58301E+06 + 1.30800E+02 1.47179E+06 + 1.30900E+02 1.27047E+06 + 1.31000E+02 1.40691E+06 + 1.31100E+02 2.10503E+06 + 1.31200E+02 2.43491E+06 + 1.31300E+02 2.92937E+06 + 1.31400E+02 4.01156E+06 + 1.31500E+02 3.47746E+06 + 1.31600E+02 3.68250E+06 + 1.31700E+02 3.12403E+06 + 1.31800E+02 3.55361E+06 + 1.31900E+02 2.95327E+06 + 1.32000E+02 3.35056E+06 + 1.32100E+02 4.12717E+06 + 1.32200E+02 4.04694E+06 + 1.32300E+02 3.67820E+06 + 1.32400E+02 3.51416E+06 + 1.32500E+02 3.03194E+06 + 1.32600E+02 2.94415E+06 + 1.32700E+02 2.47270E+06 + 1.32800E+02 1.19447E+06 + 1.32900E+02 1.08277E+06 + 1.33000E+02 1.58282E+06 + 1.33100E+02 2.00086E+06 + 1.33200E+02 1.97007E+06 + 1.33300E+02 1.66972E+06 + 1.33400E+02 2.22547E+06 + 1.33500E+02 3.03791E+06 + 1.33600E+02 2.13697E+06 + 1.33700E+02 2.42429E+06 + 1.33800E+02 2.15612E+06 + 1.33900E+02 2.22811E+06 + 1.34000E+02 2.27240E+06 + 1.34100E+02 2.29151E+06 + 1.34200E+02 2.54822E+06 + 1.34300E+02 2.85323E+06 + 1.34400E+02 3.36695E+06 + 1.34500E+02 3.44879E+06 + 1.34600E+02 2.86902E+06 + 1.34700E+02 2.97196E+06 + 1.34800E+02 3.51667E+06 + 1.34900E+02 2.92569E+06 + 1.35000E+02 3.94409E+06 + 1.35100E+02 4.39292E+06 + 1.35200E+02 3.90403E+06 + 1.35300E+02 4.57417E+06 + 1.35400E+02 4.57687E+06 + 1.35500E+02 3.53962E+06 + 1.35600E+02 4.10711E+06 + 1.35700E+02 4.56708E+06 + 1.35800E+02 3.86070E+06 + 1.35900E+02 4.13938E+06 + 1.36000E+02 4.13806E+06 + 1.36100E+02 4.43149E+06 + 1.36200E+02 4.82543E+06 + 1.36300E+02 4.59629E+06 + 1.36400E+02 5.44548E+06 + 1.36500E+02 5.63924E+06 + 1.36600E+02 5.37600E+06 + 1.36700E+02 6.14511E+06 + 1.36800E+02 5.22496E+06 + 1.36900E+02 4.11157E+06 + 1.37000E+02 4.72640E+06 + 1.37100E+02 5.11847E+06 + 1.37200E+02 5.18694E+06 + 1.37300E+02 4.19181E+06 + 1.37400E+02 3.56387E+06 + 1.37500E+02 4.01088E+06 + 1.37600E+02 3.70272E+06 + 1.37700E+02 4.62091E+06 + 1.37800E+02 5.18082E+06 + 1.37900E+02 4.82958E+06 + 1.38000E+02 5.07865E+06 + 1.38100E+02 4.63519E+06 + 1.38200E+02 4.08916E+06 + 1.38300E+02 3.24176E+06 + 1.38400E+02 3.46509E+06 + 1.38500E+02 2.82809E+06 + 1.38600E+02 3.68210E+06 + 1.38700E+02 4.26188E+06 + 1.38800E+02 4.30582E+06 + 1.38900E+02 4.46853E+06 + 1.39000E+02 4.01160E+06 + 1.39100E+02 4.44985E+06 + 1.39200E+02 4.80047E+06 + 1.39300E+02 5.45214E+06 + 1.39400E+02 5.43251E+06 + 1.39500E+02 5.43374E+06 + 1.39600E+02 5.02528E+06 + 1.39700E+02 4.81262E+06 + 1.39800E+02 4.66400E+06 + 1.39900E+02 4.71777E+06 + 1.40000E+02 4.77281E+06 + 1.40100E+02 5.15011E+06 + 1.40200E+02 5.27228E+06 + 1.40300E+02 5.71346E+06 + 1.40400E+02 5.53554E+06 + 1.40500E+02 5.49928E+06 + 1.40600E+02 4.78671E+06 + 1.40700E+02 4.31405E+06 + 1.40800E+02 4.36542E+06 + 1.40900E+02 5.74666E+06 + 1.41000E+02 6.16327E+06 + 1.41100E+02 5.04192E+06 + 1.41200E+02 4.79949E+06 + 1.41300E+02 5.06403E+06 + 1.41400E+02 5.03119E+06 + 1.41500E+02 4.36722E+06 + 1.41600E+02 4.98609E+06 + 1.41700E+02 5.33320E+06 + 1.41800E+02 5.29570E+06 + 1.41900E+02 5.49254E+06 + 1.42000E+02 4.53059E+06 + 1.42100E+02 3.78303E+06 + 1.42200E+02 3.87108E+06 + 1.42300E+02 4.88386E+06 + 1.42400E+02 5.16682E+06 + 1.42500E+02 5.26173E+06 + 1.42600E+02 5.22249E+06 + 1.42700E+02 5.55031E+06 + 1.42800E+02 5.81463E+06 + 1.42900E+02 5.58739E+06 + 1.43000E+02 6.24743E+06 + 1.43100E+02 6.03588E+06 + 1.43200E+02 5.87834E+06 + 1.43300E+02 6.11194E+06 + 1.43400E+02 6.07753E+06 + 1.43500E+02 5.38146E+06 + 1.43600E+02 5.16188E+06 + 1.43700E+02 5.12579E+06 + 1.43800E+02 4.86647E+06 + 1.43900E+02 4.51607E+06 + 1.44000E+02 4.03717E+06 + 1.44100E+02 4.22247E+06 + 1.44200E+02 4.05821E+06 + 1.44300E+02 4.46295E+06 + 1.44400E+02 3.95658E+06 + 1.44500E+02 4.14891E+06 + 1.44600E+02 4.08687E+06 + 1.44700E+02 4.30586E+06 + 1.44800E+02 5.21423E+06 + 1.44900E+02 5.46622E+06 + 1.45000E+02 4.54893E+06 + 1.45100E+02 3.98073E+06 + 1.45200E+02 3.10151E+06 + 1.45300E+02 2.42901E+06 + 1.45400E+02 2.66660E+06 + 1.45500E+02 2.31141E+06 + 1.45600E+02 3.37144E+06 + 1.45700E+02 3.15625E+06 + 1.45800E+02 3.30125E+06 + 1.45900E+02 3.71496E+06 + 1.46000E+02 3.80677E+06 + 1.46100E+02 4.15955E+06 + 1.46200E+02 4.44960E+06 + 1.46300E+02 3.78621E+06 + 1.46400E+02 2.54486E+06 + 1.46500E+02 2.07283E+06 + 1.46600E+02 3.57428E+06 + 1.46700E+02 4.51106E+06 + 1.46800E+02 4.65470E+06 + 1.46900E+02 4.76424E+06 + 1.47000E+02 4.22102E+06 + 1.47100E+02 4.62715E+06 + 1.47200E+02 4.26847E+06 + 1.47300E+02 4.79842E+06 + 1.47400E+02 5.27427E+06 + 1.47500E+02 5.95766E+06 + 1.47600E+02 6.64387E+06 + 1.47700E+02 6.88962E+06 + 1.47800E+02 6.45773E+06 + 1.47900E+02 6.86306E+06 + 1.48000E+02 6.25241E+06 + 1.48100E+02 5.32137E+06 + 1.48200E+02 4.16934E+06 + 1.48300E+02 4.39962E+06 + 1.48400E+02 4.75070E+06 + 1.48500E+02 5.01009E+06 + 1.48600E+02 4.09343E+06 + 1.48700E+02 3.92455E+06 + 1.48800E+02 3.93029E+06 + 1.48900E+02 3.73873E+06 + 1.49000E+02 3.26628E+06 + 1.49100E+02 3.80311E+06 + 1.49200E+02 4.39185E+06 + 1.49300E+02 4.59023E+06 + 1.49400E+02 4.99853E+06 + 1.49500E+02 5.18626E+06 + 1.49600E+02 4.89244E+06 + 1.49700E+02 5.51589E+06 + 1.49800E+02 5.01541E+06 + 1.49900E+02 4.78734E+06 + 1.50000E+02 4.62490E+06 + 1.50100E+02 4.83809E+06 + 1.50200E+02 4.64335E+06 + 1.50300E+02 5.62304E+06 + 1.50400E+02 6.10195E+06 + 1.50500E+02 5.46411E+06 + 1.50600E+02 4.87950E+06 + 1.50700E+02 4.78626E+06 + 1.50800E+02 4.53736E+06 + 1.50900E+02 3.95402E+06 + 1.51000E+02 4.80587E+06 + 1.51100E+02 4.56646E+06 + 1.51200E+02 4.62260E+06 + 1.51300E+02 3.90982E+06 + 1.51400E+02 4.43977E+06 + 1.51500E+02 4.26691E+06 + 1.51600E+02 4.26497E+06 + 1.51700E+02 4.82282E+06 + 1.51800E+02 4.50458E+06 + 1.51900E+02 4.80121E+06 + 1.52000E+02 4.84933E+06 + 1.52100E+02 4.42006E+06 + 1.52200E+02 4.69349E+06 + 1.52300E+02 4.72420E+06 + 1.52400E+02 4.60748E+06 + 1.52500E+02 5.10589E+06 + 1.52600E+02 5.50301E+06 + 1.52700E+02 5.87361E+06 + 1.52800E+02 5.49354E+06 + 1.52900E+02 4.67982E+06 + 1.53000E+02 4.85225E+06 + 1.53100E+02 4.35119E+06 + 1.53200E+02 4.43933E+06 + 1.53300E+02 4.49397E+06 + 1.53400E+02 4.21017E+06 + 1.53500E+02 3.76629E+06 + 1.53600E+02 4.29659E+06 + 1.53700E+02 5.04223E+06 + 1.53800E+02 5.59620E+06 + 1.53900E+02 4.82724E+06 + 1.54000E+02 4.55317E+06 + 1.54100E+02 4.56214E+06 + 1.54200E+02 4.19434E+06 + 1.54300E+02 4.70696E+06 + 1.54400E+02 5.03185E+06 + 1.54500E+02 3.75477E+06 + 1.54600E+02 3.56990E+06 + 1.54700E+02 3.78884E+06 + 1.54800E+02 4.76173E+06 + 1.54900E+02 4.60451E+06 + 1.55000E+02 4.36641E+06 + 1.55100E+02 3.82395E+06 + 1.55200E+02 3.96510E+06 + 1.55300E+02 4.39698E+06 + 1.55400E+02 3.84490E+06 + 1.55500E+02 3.81073E+06 + 1.55600E+02 3.75650E+06 + 1.55700E+02 3.70006E+06 + 1.55800E+02 3.30373E+06 + 1.55900E+02 2.78514E+06 + 1.56000E+02 2.48574E+06 + 1.56100E+02 3.16124E+06 + 1.56200E+02 2.73379E+06 + 1.56300E+02 2.62467E+06 + 1.56400E+02 2.10988E+06 + 1.56500E+02 2.69706E+06 + 1.56600E+02 2.41528E+06 + 1.56700E+02 2.76368E+06 + 1.56800E+02 3.43042E+06 + 1.56900E+02 3.71019E+06 + 1.57000E+02 3.40675E+06 + 1.57100E+02 3.69737E+06 + 1.57200E+02 3.89054E+06 + 1.57300E+02 4.11215E+06 + 1.57400E+02 4.15798E+06 + 1.57500E+02 4.97625E+06 + 1.57600E+02 4.96808E+06 + 1.57700E+02 3.84941E+06 + 1.57800E+02 3.55759E+06 + 1.57900E+02 3.16285E+06 + 1.58000E+02 3.07334E+06 + 1.58100E+02 3.59696E+06 + 1.58200E+02 3.57818E+06 + 1.58300E+02 3.38212E+06 + 1.58400E+02 3.38666E+06 + 1.58500E+02 3.53839E+06 + 1.58600E+02 3.14500E+06 + 1.58700E+02 2.64757E+06 + 1.58800E+02 2.69037E+06 + 1.58900E+02 2.62919E+06 + 1.59000E+02 3.07336E+06 + 1.59100E+02 3.31136E+06 + 1.59200E+02 3.34824E+06 + 1.59300E+02 2.81310E+06 + 1.59400E+02 2.86994E+06 + 1.59500E+02 3.14107E+06 + 1.59600E+02 2.60864E+06 + 1.59700E+02 1.42567E+06 + 1.59800E+02 1.79309E+06 + 1.59900E+02 2.39302E+06 + 1.60000E+02 2.23125E+06 + 1.60100E+02 1.84484E+06 + 1.60200E+02 3.11334E+06 + 1.60300E+02 3.42888E+06 + 1.60400E+02 3.88103E+06 + 1.60500E+02 4.32408E+06 + 1.60600E+02 3.92179E+06 + 1.60700E+02 4.10387E+06 + 1.60800E+02 3.03412E+06 + 1.60900E+02 2.87373E+06 + 1.61000E+02 3.37206E+06 + 1.61100E+02 3.65356E+06 + 1.61200E+02 3.56246E+06 + 1.61300E+02 3.21780E+06 + 1.61400E+02 4.03951E+06 + 1.61500E+02 4.12233E+06 + 1.61600E+02 3.90041E+06 + 1.61700E+02 4.46326E+06 + 1.61800E+02 4.43961E+06 + 1.61900E+02 3.45667E+06 + 1.62000E+02 3.40619E+06 + 1.62100E+02 3.56913E+06 + 1.62200E+02 3.59686E+06 + 1.62300E+02 3.33202E+06 + 1.62400E+02 4.01997E+06 + 1.62500E+02 4.36157E+06 + 1.62600E+02 3.51700E+06 + 1.62700E+02 3.36006E+06 + 1.62800E+02 3.76101E+06 + 1.62900E+02 4.49224E+06 + 1.63000E+02 5.11207E+06 + 1.63100E+02 5.23001E+06 + 1.63200E+02 5.62792E+06 + 1.63300E+02 6.53093E+06 + 1.63400E+02 6.38544E+06 + 1.63500E+02 6.87989E+06 + 1.63600E+02 6.55697E+06 + 1.63700E+02 6.61644E+06 + 1.63800E+02 5.83038E+06 + 1.63900E+02 6.12986E+06 + 1.64000E+02 5.72976E+06 + 1.64100E+02 4.88426E+06 + 1.64200E+02 4.49798E+06 + 1.64300E+02 4.14904E+06 + 1.64400E+02 4.01025E+06 + 1.64500E+02 4.28958E+06 + 1.64600E+02 4.65323E+06 + 1.64700E+02 5.29624E+06 + 1.64800E+02 4.80758E+06 + 1.64900E+02 4.45461E+06 + 1.65000E+02 4.75740E+06 + 1.65100E+02 4.72644E+06 + 1.65200E+02 4.57142E+06 + 1.65300E+02 4.41228E+06 + 1.65400E+02 4.75138E+06 + 1.65500E+02 5.18214E+06 + 1.65600E+02 5.78004E+06 + 1.65700E+02 5.73057E+06 + 1.65800E+02 5.00242E+06 + 1.65900E+02 4.83870E+06 + 1.66000E+02 5.19999E+06 + 1.66100E+02 4.79079E+06 + 1.66200E+02 3.98847E+06 + 1.66300E+02 4.15082E+06 + 1.66400E+02 3.91392E+06 + 1.66500E+02 3.73433E+06 + 1.66600E+02 3.78341E+06 + 1.66700E+02 3.98471E+06 + 1.66800E+02 4.06187E+06 + 1.66900E+02 4.57554E+06 + 1.67000E+02 4.30994E+06 + 1.67100E+02 4.45507E+06 + 1.67200E+02 4.00974E+06 + 1.67300E+02 4.74393E+06 + 1.67400E+02 4.35954E+06 + 1.67500E+02 4.32055E+06 + 1.67600E+02 4.71132E+06 + 1.67700E+02 4.80171E+06 + 1.67800E+02 3.67988E+06 + 1.67900E+02 3.68932E+06 + 1.68000E+02 3.74157E+06 + 1.68100E+02 3.26106E+06 + 1.68200E+02 3.95246E+06 + 1.68300E+02 4.81158E+06 + 1.68400E+02 5.11283E+06 + 1.68500E+02 4.87346E+06 + 1.68600E+02 4.84513E+06 + 1.68700E+02 4.79493E+06 + 1.68800E+02 4.87319E+06 + 1.68900E+02 4.88180E+06 + 1.69000E+02 5.20995E+06 + 1.69100E+02 5.29298E+06 + 1.69200E+02 4.56372E+06 + 1.69300E+02 4.01052E+06 + 1.69400E+02 4.49123E+06 + 1.69500E+02 4.89713E+06 + 1.69600E+02 5.26565E+06 + 1.69700E+02 4.84631E+06 + 1.69800E+02 4.61311E+06 + 1.69900E+02 5.24372E+06 + 1.70000E+02 4.48523E+06 + 1.70100E+02 4.17512E+06 + 1.70200E+02 4.17149E+06 + 1.70300E+02 3.05046E+06 + 1.70400E+02 2.79672E+06 + 1.70500E+02 3.05584E+06 + 1.70600E+02 3.01250E+06 + 1.70700E+02 3.56326E+06 + 1.70800E+02 3.67713E+06 + 1.70900E+02 3.97598E+06 + 1.71000E+02 3.51779E+06 + 1.71100E+02 3.60783E+06 + 1.71200E+02 4.03006E+06 + 1.71300E+02 4.48505E+06 + 1.71400E+02 4.21734E+06 + 1.71500E+02 4.55664E+06 + 1.71600E+02 4.52679E+06 + 1.71700E+02 4.54926E+06 + 1.71800E+02 4.20229E+06 + 1.71900E+02 4.88340E+06 + 1.72000E+02 5.20393E+06 + 1.72100E+02 4.88420E+06 + 1.72200E+02 4.99142E+06 + 1.72300E+02 4.70232E+06 + 1.72400E+02 4.45666E+06 + 1.72500E+02 3.84123E+06 + 1.72600E+02 4.44666E+06 + 1.72700E+02 4.75982E+06 + 1.72800E+02 5.18447E+06 + 1.72900E+02 4.46804E+06 + 1.73000E+02 3.61756E+06 + 1.73100E+02 3.65497E+06 + 1.73200E+02 4.14608E+06 + 1.73300E+02 4.20599E+06 + 1.73400E+02 3.98856E+06 + 1.73500E+02 3.20451E+06 + 1.73600E+02 3.17514E+06 + 1.73700E+02 2.80290E+06 + 1.73800E+02 2.43863E+06 + 1.73900E+02 2.63174E+06 + 1.74000E+02 2.67991E+06 + 1.74100E+02 3.61559E+06 + 1.74200E+02 3.50853E+06 + 1.74300E+02 3.63038E+06 + 1.74400E+02 3.72026E+06 + 1.74500E+02 3.36515E+06 + 1.74600E+02 3.49197E+06 + 1.74700E+02 3.67751E+06 + 1.74800E+02 4.04504E+06 + 1.74900E+02 3.47277E+06 + 1.75000E+02 3.93495E+06 + 1.75100E+02 5.11887E+06 + 1.75200E+02 5.68737E+06 + 1.75300E+02 3.99148E+06 + 1.75400E+02 3.62851E+06 + 1.75500E+02 3.68463E+06 + 1.75600E+02 4.18096E+06 + 1.75700E+02 3.63245E+06 + 1.75800E+02 3.90079E+06 + 1.75900E+02 4.06029E+06 + 1.76000E+02 4.54927E+06 + 1.76100E+02 4.47507E+06 + 1.76200E+02 4.77587E+06 + 1.76300E+02 3.73273E+06 + 1.76400E+02 2.23846E+06 + 1.76500E+02 2.82690E+06 + 1.76600E+02 3.72632E+06 + 1.76700E+02 4.36349E+06 + 1.76800E+02 4.65084E+06 + 1.76900E+02 3.86933E+06 + 1.77000E+02 4.28116E+06 + 1.77100E+02 4.27521E+06 + 1.77200E+02 4.50481E+06 + 1.77300E+02 5.01004E+06 + 1.77400E+02 5.17369E+06 + 1.77500E+02 4.29843E+06 + 1.77600E+02 4.37112E+06 + 1.77700E+02 5.30630E+06 + 1.77800E+02 4.74120E+06 + 1.77900E+02 4.54849E+06 + 1.78000E+02 5.28566E+06 + 1.78100E+02 6.07731E+06 + 1.78200E+02 5.74564E+06 + 1.78300E+02 5.44191E+06 + 1.78400E+02 5.11434E+06 + 1.78500E+02 4.83995E+06 + 1.78600E+02 4.21825E+06 + 1.78700E+02 4.28882E+06 + 1.78800E+02 3.97992E+06 + 1.78900E+02 3.56980E+06 + 1.79000E+02 4.01049E+06 + 1.79100E+02 3.43617E+06 + 1.79200E+02 3.02690E+06 + 1.79300E+02 3.36700E+06 + 1.79400E+02 3.79848E+06 + 1.79500E+02 5.00299E+06 + 1.79600E+02 5.48562E+06 + 1.79700E+02 4.73216E+06 + 1.79800E+02 4.58952E+06 + 1.79900E+02 4.83245E+06 + 1.80000E+02 4.98246E+06 + 1.80100E+02 4.26830E+06 + 1.80200E+02 4.98405E+06 + 1.80300E+02 4.71532E+06 + 1.80400E+02 5.26171E+06 + 1.80500E+02 5.47625E+06 + 1.80600E+02 4.92541E+06 + 1.80700E+02 4.47592E+06 + 1.80800E+02 4.16172E+06 + 1.80900E+02 4.09442E+06 + 1.81000E+02 4.27575E+06 + 1.81100E+02 4.04325E+06 + 1.81200E+02 4.20696E+06 + 1.81300E+02 4.89234E+06 + 1.81400E+02 5.42754E+06 + 1.81500E+02 6.00736E+06 + 1.81600E+02 6.01967E+06 + 1.81700E+02 5.17817E+06 + 1.81800E+02 4.97976E+06 + 1.81900E+02 5.37076E+06 + 1.82000E+02 4.85075E+06 + 1.82100E+02 4.38735E+06 + 1.82200E+02 4.23682E+06 + 1.82300E+02 4.54659E+06 + 1.82400E+02 4.94253E+06 + 1.82500E+02 4.45418E+06 + 1.82600E+02 4.47509E+06 + 1.82700E+02 5.59596E+06 + 1.82800E+02 6.02573E+06 + 1.82900E+02 6.70665E+06 + 1.83000E+02 5.93161E+06 + 1.83100E+02 5.75026E+06 + 1.83200E+02 6.72112E+06 + 1.83300E+02 7.16469E+06 + 1.83400E+02 7.09835E+06 + 1.83500E+02 6.26547E+06 + 1.83600E+02 5.69804E+06 + 1.83700E+02 5.81319E+06 + 1.83800E+02 6.03331E+06 + 1.83900E+02 6.32166E+06 + 1.84000E+02 5.89232E+06 + 1.84100E+02 5.45296E+06 + 1.84200E+02 5.55122E+06 + 1.84300E+02 4.23233E+06 + 1.84400E+02 4.37181E+06 + 1.84500E+02 4.60264E+06 + 1.84600E+02 4.96175E+06 + 1.84700E+02 4.60287E+06 + 1.84800E+02 4.04055E+06 + 1.84900E+02 4.17833E+06 + 1.85000E+02 4.04317E+06 + 1.85100E+02 3.64668E+06 + 1.85200E+02 4.46929E+06 + 1.85300E+02 5.15375E+06 + 1.85400E+02 4.56995E+06 + 1.85500E+02 4.16613E+06 + 1.85600E+02 4.08919E+06 + 1.85700E+02 4.16882E+06 + 1.85800E+02 3.96942E+06 + 1.85900E+02 5.35262E+06 + 1.86000E+02 5.54618E+06 + 1.86100E+02 5.31533E+06 + 1.86200E+02 5.71482E+06 + 1.86300E+02 6.15709E+06 + 1.86400E+02 5.82336E+06 + 1.86500E+02 5.43922E+06 + 1.86600E+02 5.57739E+06 + 1.86700E+02 5.50287E+06 + 1.86800E+02 5.23004E+06 + 1.86900E+02 4.34493E+06 + 1.87000E+02 3.57850E+06 + 1.87100E+02 3.99374E+06 + 1.87200E+02 4.34497E+06 + 1.87300E+02 5.10079E+06 + 1.87400E+02 4.93281E+06 + 1.87500E+02 4.66722E+06 + 1.87600E+02 4.46924E+06 + 1.87700E+02 3.79145E+06 + 1.87800E+02 3.42212E+06 + 1.87900E+02 4.03723E+06 + 1.88000E+02 4.20787E+06 + 1.88100E+02 3.61103E+06 + 1.88200E+02 3.54951E+06 + 1.88300E+02 3.23095E+06 + 1.88400E+02 3.31577E+06 + 1.88500E+02 2.79737E+06 + 1.88600E+02 2.94218E+06 + 1.88700E+02 2.97798E+06 + 1.88800E+02 3.17290E+06 + 1.88900E+02 3.14494E+06 + 1.89000E+02 3.44957E+06 + 1.89100E+02 3.30861E+06 + 1.89200E+02 2.87492E+06 + 1.89300E+02 3.97323E+06 + 1.89400E+02 4.87967E+06 + 1.89500E+02 4.60844E+06 + 1.89600E+02 5.12194E+06 + 1.89700E+02 5.12424E+06 + 1.89800E+02 5.17409E+06 + 1.89900E+02 5.88311E+06 + 1.90000E+02 5.58740E+06 + 1.90100E+02 4.85158E+06 + 1.90200E+02 4.02015E+06 + 1.90300E+02 3.98329E+06 + 1.90400E+02 4.10008E+06 + 1.90500E+02 4.39233E+06 + 1.90600E+02 4.88785E+06 + 1.90700E+02 5.03360E+06 + 1.90800E+02 5.40807E+06 + 1.90900E+02 5.53692E+06 + 1.91000E+02 5.42779E+06 + 1.91100E+02 5.71748E+06 + 1.91200E+02 5.93888E+06 + 1.91300E+02 5.67305E+06 + 1.91400E+02 4.91584E+06 + 1.91500E+02 5.33988E+06 + 1.91600E+02 4.96928E+06 + 1.91700E+02 4.59978E+06 + 1.91800E+02 4.16483E+06 + 1.91900E+02 4.51678E+06 + 1.92000E+02 5.32676E+06 + 1.92100E+02 5.57306E+06 + 1.92200E+02 4.69563E+06 + 1.92300E+02 4.32694E+06 + 1.92400E+02 4.56591E+06 + 1.92500E+02 4.28984E+06 + 1.92600E+02 3.60238E+06 + 1.92700E+02 3.94427E+06 + 1.92800E+02 4.25908E+06 + 1.92900E+02 4.24558E+06 + 1.93000E+02 4.09353E+06 + 1.93100E+02 4.64634E+06 + 1.93200E+02 5.12981E+06 + 1.93300E+02 5.53994E+06 + 1.93400E+02 6.00228E+06 + 1.93500E+02 5.29562E+06 + 1.93600E+02 4.61657E+06 + 1.93700E+02 4.44961E+06 + 1.93800E+02 4.22900E+06 + 1.93900E+02 3.17944E+06 + 1.94000E+02 3.22092E+06 + 1.94100E+02 3.00708E+06 + 1.94200E+02 2.84411E+06 + 1.94300E+02 3.29382E+06 + 1.94400E+02 3.77686E+06 + 1.94500E+02 4.26234E+06 + 1.94600E+02 4.78369E+06 + 1.94700E+02 5.01992E+06 + 1.94800E+02 5.71529E+06 + 1.94900E+02 6.60491E+06 + 1.95000E+02 6.61525E+06 + 1.95100E+02 6.67894E+06 + 1.95200E+02 5.84352E+06 + 1.95300E+02 5.98748E+06 + 1.95400E+02 5.81790E+06 + 1.95500E+02 5.68852E+06 + 1.95600E+02 5.50393E+06 + 1.95700E+02 5.64030E+06 + 1.95800E+02 4.54099E+06 + 1.95900E+02 4.07804E+06 + 1.96000E+02 4.49677E+06 + 1.96100E+02 3.88860E+06 + 1.96200E+02 4.24373E+06 + 1.96300E+02 4.55071E+06 + 1.96400E+02 4.87965E+06 + 1.96500E+02 4.12909E+06 + 1.96600E+02 4.39615E+06 + 1.96700E+02 4.72993E+06 + 1.96800E+02 4.66599E+06 + 1.96900E+02 5.27034E+06 + 1.97000E+02 4.57767E+06 + 1.97100E+02 3.17403E+06 + 1.97200E+02 3.08391E+06 + 1.97300E+02 2.93024E+06 + 1.97400E+02 3.61139E+06 + 1.97500E+02 3.70076E+06 + 1.97600E+02 3.82710E+06 + 1.97700E+02 3.50857E+06 + 1.97800E+02 3.90421E+06 + 1.97900E+02 4.29608E+06 + 1.98000E+02 4.68150E+06 + 1.98100E+02 5.00952E+06 + 1.98200E+02 4.94447E+06 + 1.98300E+02 5.11151E+06 + 1.98400E+02 4.72303E+06 + 1.98500E+02 5.03364E+06 + 1.98600E+02 5.48883E+06 + 1.98700E+02 6.39933E+06 + 1.98800E+02 6.64901E+06 + 1.98900E+02 6.46530E+06 + 1.99000E+02 5.52031E+06 + 1.99100E+02 5.45252E+06 + 1.99200E+02 5.19850E+06 + 1.99300E+02 5.05844E+06 + 1.99400E+02 5.17069E+06 + 1.99500E+02 4.66793E+06 + 1.99600E+02 4.78175E+06 + 1.99700E+02 4.67585E+06 + 1.99800E+02 4.29962E+06 + 1.99900E+02 5.09034E+06 + 2.00000E+02 4.92428E+06 + 2.00100E+02 3.91800E+06 + 2.00200E+02 4.10379E+06 + 2.00300E+02 4.81247E+06 + 2.00400E+02 4.79337E+06 + 2.00500E+02 4.92571E+06 + 2.00600E+02 5.03987E+06 + 2.00700E+02 5.06057E+06 + 2.00800E+02 5.42979E+06 + 2.00900E+02 5.59688E+06 + 2.01000E+02 5.20309E+06 + 2.01100E+02 5.53646E+06 + 2.01200E+02 5.73560E+06 + 2.01300E+02 6.62010E+06 + 2.01400E+02 6.96088E+06 + 2.01500E+02 6.37752E+06 + 2.01600E+02 6.65493E+06 + 2.01700E+02 6.22123E+06 + 2.01800E+02 6.21967E+06 + 2.01900E+02 5.35349E+06 + 2.02000E+02 5.22176E+06 + 2.02100E+02 5.62738E+06 + 2.02200E+02 6.27133E+06 + 2.02300E+02 6.37703E+06 + 2.02400E+02 6.21399E+06 + 2.02500E+02 6.07156E+06 + 2.02600E+02 6.51624E+06 + 2.02700E+02 5.91966E+06 + 2.02800E+02 6.51178E+06 + 2.02900E+02 6.93542E+06 + 2.03000E+02 6.36129E+06 + 2.03100E+02 6.33606E+06 + 2.03200E+02 6.26218E+06 + 2.03300E+02 6.13412E+06 + 2.03400E+02 5.79534E+06 + 2.03500E+02 6.39262E+06 + 2.03600E+02 5.89037E+06 + 2.03700E+02 5.77361E+06 + 2.03800E+02 5.11486E+06 + 2.03900E+02 4.34781E+06 + 2.04000E+02 3.93919E+06 + 2.04100E+02 3.62605E+06 + 2.04200E+02 3.78901E+06 + 2.04300E+02 2.68613E+06 + 2.04400E+02 3.11856E+06 + 2.04500E+02 2.35253E+06 + 2.04600E+02 2.18125E+06 + 2.04700E+02 2.60965E+06 + 2.04800E+02 2.77096E+06 + 2.04900E+02 3.90083E+06 + 2.05000E+02 3.23492E+06 + 2.05100E+02 3.84637E+06 + 2.05200E+02 4.37410E+06 + 2.05300E+02 4.88758E+06 + 2.05400E+02 4.91695E+06 + 2.05500E+02 4.85335E+06 + 2.05600E+02 4.29847E+06 + 2.05700E+02 4.06219E+06 + 2.05800E+02 4.52966E+06 + 2.05900E+02 4.78268E+06 + 2.06000E+02 5.21652E+06 + 2.06100E+02 5.45840E+06 + 2.06200E+02 5.32170E+06 + 2.06300E+02 6.32565E+06 + 2.06400E+02 5.59231E+06 + 2.06500E+02 5.11323E+06 + 2.06600E+02 4.57300E+06 + 2.06700E+02 5.24540E+06 + 2.06800E+02 5.13382E+06 + 2.06900E+02 4.75200E+06 + 2.07000E+02 5.15085E+06 + 2.07100E+02 5.73139E+06 + 2.07200E+02 5.82521E+06 + 2.07300E+02 5.84426E+06 + 2.07400E+02 5.31259E+06 + 2.07500E+02 4.49285E+06 + 2.07600E+02 4.83250E+06 + 2.07700E+02 5.62398E+06 + 2.07800E+02 5.87637E+06 + 2.07900E+02 5.06122E+06 + 2.08000E+02 4.81187E+06 + 2.08100E+02 5.35464E+06 + 2.08200E+02 5.89089E+06 + 2.08300E+02 6.15540E+06 + 2.08400E+02 6.28823E+06 + 2.08500E+02 6.54927E+06 + 2.08600E+02 6.24398E+06 + 2.08700E+02 6.30412E+06 + 2.08800E+02 4.45846E+06 + 2.08900E+02 3.63012E+06 + 2.09000E+02 4.15689E+06 + 2.09100E+02 4.20694E+06 + 2.09200E+02 3.93143E+06 + 2.09300E+02 3.93250E+06 + 2.09400E+02 3.11174E+06 + 2.09500E+02 3.21288E+06 + 2.09600E+02 3.01603E+06 + 2.09700E+02 3.09053E+06 + 2.09800E+02 3.12322E+06 + 2.09900E+02 3.03850E+06 + 2.10000E+02 3.27865E+06 + 2.10100E+02 4.21124E+06 + 2.10200E+02 4.77051E+06 + 2.10300E+02 4.88387E+06 + 2.10400E+02 3.51587E+06 + 2.10500E+02 3.64562E+06 + 2.10600E+02 4.52275E+06 + 2.10700E+02 5.04868E+06 + 2.10800E+02 5.07035E+06 + 2.10900E+02 6.07721E+06 + 2.11000E+02 5.72405E+06 + 2.11100E+02 5.04530E+06 + 2.11200E+02 5.20288E+06 + 2.11300E+02 5.83294E+06 + 2.11400E+02 6.22631E+06 + 2.11500E+02 6.03956E+06 + 2.11600E+02 5.22354E+06 + 2.11700E+02 4.46241E+06 + 2.11800E+02 4.47140E+06 + 2.11900E+02 3.91808E+06 + 2.12000E+02 4.58177E+06 + 2.12100E+02 4.99278E+06 + 2.12200E+02 4.48190E+06 + 2.12300E+02 3.91915E+06 + 2.12400E+02 3.34613E+06 + 2.12500E+02 2.92556E+06 + 2.12600E+02 2.62776E+06 + 2.12700E+02 2.82577E+06 + 2.12800E+02 2.82777E+06 + 2.12900E+02 3.06223E+06 + 2.13000E+02 2.84799E+06 + 2.13100E+02 3.18338E+06 + 2.13200E+02 3.53271E+06 + 2.13300E+02 3.15521E+06 + 2.13400E+02 3.68223E+06 + 2.13500E+02 3.73265E+06 + 2.13600E+02 3.21020E+06 + 2.13700E+02 3.41906E+06 + 2.13800E+02 2.63883E+06 + 2.13900E+02 2.91570E+06 + 2.14000E+02 3.47885E+06 + 2.14100E+02 3.37766E+06 + 2.14200E+02 3.56223E+06 + 2.14300E+02 4.23208E+06 + 2.14400E+02 3.57272E+06 + 2.14500E+02 3.95488E+06 + 2.14600E+02 4.96247E+06 + 2.14700E+02 4.44543E+06 + 2.14800E+02 4.00778E+06 + 2.14900E+02 4.16756E+06 + 2.15000E+02 4.41302E+06 + 2.15100E+02 4.91164E+06 + 2.15200E+02 4.74466E+06 + 2.15300E+02 4.86771E+06 + 2.15400E+02 3.92265E+06 + 2.15500E+02 3.10059E+06 + 2.15600E+02 3.14250E+06 + 2.15700E+02 3.31736E+06 + 2.15800E+02 4.24798E+06 + 2.15900E+02 5.17099E+06 + 2.16000E+02 5.60806E+06 + 2.16100E+02 5.94315E+06 + 2.16200E+02 5.32531E+06 + 2.16300E+02 4.96409E+06 + 2.16400E+02 4.13076E+06 + 2.16500E+02 5.24929E+06 + 2.16600E+02 5.00193E+06 + 2.16700E+02 4.11407E+06 + 2.16800E+02 4.79534E+06 + 2.16900E+02 5.19908E+06 + 2.17000E+02 4.56960E+06 + 2.17100E+02 3.82613E+06 + 2.17200E+02 3.44514E+06 + 2.17300E+02 2.84354E+06 + 2.17400E+02 4.02786E+06 + 2.17500E+02 4.23361E+06 + 2.17600E+02 4.71044E+06 + 2.17700E+02 4.76509E+06 + 2.17800E+02 4.74658E+06 + 2.17900E+02 5.51151E+06 + 2.18000E+02 6.55299E+06 + 2.18100E+02 6.63805E+06 + 2.18200E+02 5.94984E+06 + 2.18300E+02 6.75357E+06 + 2.18400E+02 7.29096E+06 + 2.18500E+02 7.30003E+06 + 2.18600E+02 6.61620E+06 + 2.18700E+02 6.06789E+06 + 2.18800E+02 5.74799E+06 + 2.18900E+02 5.80208E+06 + 2.19000E+02 5.48327E+06 + 2.19100E+02 4.80114E+06 + 2.19200E+02 4.92457E+06 + 2.19300E+02 4.81096E+06 + 2.19400E+02 4.16769E+06 + 2.19500E+02 3.37987E+06 + 2.19600E+02 4.20817E+06 + 2.19700E+02 4.85622E+06 + 2.19800E+02 5.41873E+06 + 2.19900E+02 4.28722E+06 + 2.20000E+02 4.70955E+06 + 2.20100E+02 4.77566E+06 + 2.20200E+02 5.17292E+06 + 2.20300E+02 4.65323E+06 + 2.20400E+02 4.71757E+06 + 2.20500E+02 4.47824E+06 + 2.20600E+02 4.78128E+06 + 2.20700E+02 5.32071E+06 + 2.20800E+02 5.47979E+06 + 2.20900E+02 5.12449E+06 + 2.21000E+02 5.07574E+06 + 2.21100E+02 5.64594E+06 + 2.21200E+02 6.56042E+06 + 2.21300E+02 6.64292E+06 + 2.21400E+02 6.62956E+06 + 2.21500E+02 6.30624E+06 + 2.21600E+02 6.74847E+06 + 2.21700E+02 6.71187E+06 + 2.21800E+02 6.74263E+06 + 2.21900E+02 6.26275E+06 + 2.22000E+02 6.69221E+06 + 2.22100E+02 6.21467E+06 + 2.22200E+02 6.24310E+06 + 2.22300E+02 6.89892E+06 + 2.22400E+02 6.14542E+06 + 2.22500E+02 5.00634E+06 + 2.22600E+02 5.32098E+06 + 2.22700E+02 4.96295E+06 + 2.22800E+02 4.83170E+06 + 2.22900E+02 5.34311E+06 + 2.23000E+02 5.05515E+06 + 2.23100E+02 5.24560E+06 + 2.23200E+02 4.56925E+06 + 2.23300E+02 4.55217E+06 + 2.23400E+02 5.61799E+06 + 2.23500E+02 4.31949E+06 + 2.23600E+02 3.90405E+06 + 2.23700E+02 3.67126E+06 + 2.23800E+02 3.41130E+06 + 2.23900E+02 4.19160E+06 + 2.24000E+02 4.26023E+06 + 2.24100E+02 2.70905E+06 + 2.24200E+02 1.94025E+06 + 2.24300E+02 2.28512E+06 + 2.24400E+02 2.54782E+06 + 2.24500E+02 2.57186E+06 + 2.24600E+02 2.19217E+06 + 2.24700E+02 1.92921E+06 + 2.24800E+02 2.67393E+06 + 2.24900E+02 2.80785E+06 + 2.25000E+02 3.52352E+06 + 2.25100E+02 4.27890E+06 + 2.25200E+02 4.05728E+06 + 2.25300E+02 3.50142E+06 + 2.25400E+02 3.14275E+06 + 2.25500E+02 2.32208E+06 + 2.25600E+02 2.63389E+06 + 2.25700E+02 2.91225E+06 + 2.25800E+02 3.01596E+06 + 2.25900E+02 3.10698E+06 + 2.26000E+02 3.47391E+06 + 2.26100E+02 4.08929E+06 + 2.26200E+02 4.49903E+06 + 2.26300E+02 4.95948E+06 + 2.26400E+02 5.49281E+06 + 2.26500E+02 5.19719E+06 + 2.26600E+02 5.08206E+06 + 2.26700E+02 4.54206E+06 + 2.26800E+02 4.36955E+06 + 2.26900E+02 4.66528E+06 + 2.27000E+02 4.61418E+06 + 2.27100E+02 4.72499E+06 + 2.27200E+02 3.98526E+06 + 2.27300E+02 4.00523E+06 + 2.27400E+02 4.40820E+06 + 2.27500E+02 3.26376E+06 + 2.27600E+02 3.33017E+06 + 2.27700E+02 3.98176E+06 + 2.27800E+02 4.17031E+06 + 2.27900E+02 4.80098E+06 + 2.28000E+02 3.68243E+06 + 2.28100E+02 4.05243E+06 + 2.28200E+02 3.99807E+06 + 2.28300E+02 3.57507E+06 + 2.28400E+02 3.95715E+06 + 2.28500E+02 4.25032E+06 + 2.28600E+02 4.35905E+06 + 2.28700E+02 3.73860E+06 + 2.28800E+02 3.20658E+06 + 2.28900E+02 2.92634E+06 + 2.29000E+02 3.21726E+06 + 2.29100E+02 3.20152E+06 + 2.29200E+02 4.22165E+06 + 2.29300E+02 4.49862E+06 + 2.29400E+02 3.75296E+06 + 2.29500E+02 4.31070E+06 + 2.29600E+02 4.28057E+06 + 2.29700E+02 4.16746E+06 + 2.29800E+02 3.39254E+06 + 2.29900E+02 3.75472E+06 + 2.30000E+02 3.17098E+06 + 2.30100E+02 3.64997E+06 + 2.30200E+02 3.78255E+06 + 2.30300E+02 3.08366E+06 + 2.30400E+02 2.68066E+06 + 2.30500E+02 3.30591E+06 + 2.30600E+02 3.17417E+06 + 2.30700E+02 3.23463E+06 + 2.30800E+02 3.47585E+06 + 2.30900E+02 3.92705E+06 + 2.31000E+02 4.44518E+06 + 2.31100E+02 4.30630E+06 + 2.31200E+02 3.80668E+06 + 2.31300E+02 4.26274E+06 + 2.31400E+02 4.53915E+06 + 2.31500E+02 4.07874E+06 + 2.31600E+02 3.51392E+06 + 2.31700E+02 4.09524E+06 + 2.31800E+02 4.58213E+06 + 2.31900E+02 3.90788E+06 + 2.32000E+02 3.37294E+06 + 2.32100E+02 3.80702E+06 + 2.32200E+02 4.59422E+06 + 2.32300E+02 4.42582E+06 + 2.32400E+02 4.73195E+06 + 2.32500E+02 5.15897E+06 + 2.32600E+02 5.21004E+06 + 2.32700E+02 5.96119E+06 + 2.32800E+02 6.23291E+06 + 2.32900E+02 5.42362E+06 + 2.33000E+02 4.65640E+06 + 2.33100E+02 3.23833E+06 + 2.33200E+02 3.37628E+06 + 2.33300E+02 2.96294E+06 + 2.33400E+02 2.90523E+06 + 2.33500E+02 3.06107E+06 + 2.33600E+02 2.79606E+06 + 2.33700E+02 3.27010E+06 + 2.33800E+02 3.44346E+06 + 2.33900E+02 3.95796E+06 + 2.34000E+02 4.51829E+06 + 2.34100E+02 4.16105E+06 + 2.34200E+02 3.94398E+06 + 2.34300E+02 4.35296E+06 + 2.34400E+02 4.16467E+06 + 2.34500E+02 4.52579E+06 + 2.34600E+02 5.22345E+06 + 2.34700E+02 4.40506E+06 + 2.34800E+02 4.50722E+06 + 2.34900E+02 4.98752E+06 + 2.35000E+02 4.70886E+06 + 2.35100E+02 4.51161E+06 + 2.35200E+02 4.67890E+06 + 2.35300E+02 4.28329E+06 + 2.35400E+02 4.36199E+06 + 2.35500E+02 4.41920E+06 + 2.35600E+02 3.98985E+06 + 2.35700E+02 4.11333E+06 + 2.35800E+02 3.90802E+06 + 2.35900E+02 3.91580E+06 + 2.36000E+02 3.70880E+06 + 2.36100E+02 4.17894E+06 + 2.36200E+02 3.94116E+06 + 2.36300E+02 3.77246E+06 + 2.36400E+02 3.88333E+06 + 2.36500E+02 3.69802E+06 + 2.36600E+02 3.92681E+06 + 2.36700E+02 3.77299E+06 + 2.36800E+02 3.95359E+06 + 2.36900E+02 3.91658E+06 + 2.37000E+02 4.16820E+06 + 2.37100E+02 3.63093E+06 + 2.37200E+02 3.26812E+06 + 2.37300E+02 3.70785E+06 + 2.37400E+02 3.58997E+06 + 2.37500E+02 4.56282E+06 + 2.37600E+02 4.37696E+06 + 2.37700E+02 4.38724E+06 + 2.37800E+02 4.50468E+06 + 2.37900E+02 4.21730E+06 + 2.38000E+02 3.75993E+06 + 2.38100E+02 3.97055E+06 + 2.38200E+02 4.54135E+06 + 2.38300E+02 3.96235E+06 + 2.38400E+02 3.73564E+06 + 2.38500E+02 4.19194E+06 + 2.38600E+02 3.87161E+06 + 2.38700E+02 3.91698E+06 + 2.38800E+02 4.37015E+06 + 2.38900E+02 4.90492E+06 + 2.39000E+02 5.64525E+06 + 2.39100E+02 5.47743E+06 + 2.39200E+02 4.75036E+06 + 2.39300E+02 4.94885E+06 + 2.39400E+02 5.08916E+06 + 2.39500E+02 4.59556E+06 + 2.39600E+02 4.26719E+06 + 2.39700E+02 4.29158E+06 + 2.39800E+02 4.33601E+06 + 2.39900E+02 4.07575E+06 + 2.40000E+02 3.85024E+06 + 2.40100E+02 3.66911E+06 + 2.40200E+02 4.02466E+06 + 2.40300E+02 3.45525E+06 + 2.40400E+02 3.63005E+06 + 2.40500E+02 3.70941E+06 + 2.40600E+02 3.83959E+06 + 2.40700E+02 4.33474E+06 + 2.40800E+02 3.91035E+06 + 2.40900E+02 4.30216E+06 + 2.41000E+02 3.88635E+06 + 2.41100E+02 4.82955E+06 + 2.41200E+02 5.61538E+06 + 2.41300E+02 5.49376E+06 + 2.41400E+02 6.01366E+06 + 2.41500E+02 5.65792E+06 + 2.41600E+02 5.29814E+06 + 2.41700E+02 5.33156E+06 + 2.41800E+02 5.25844E+06 + 2.41900E+02 5.44557E+06 + 2.42000E+02 5.73252E+06 + 2.42100E+02 5.14719E+06 + 2.42200E+02 5.16055E+06 + 2.42300E+02 4.95799E+06 + 2.42400E+02 4.62943E+06 + 2.42500E+02 4.04951E+06 + 2.42600E+02 3.75115E+06 + 2.42700E+02 3.73171E+06 + 2.42800E+02 3.95257E+06 + 2.42900E+02 3.92990E+06 + 2.43000E+02 4.02999E+06 + 2.43100E+02 4.15852E+06 + 2.43200E+02 3.90834E+06 + 2.43300E+02 4.18442E+06 + 2.43400E+02 3.88896E+06 + 2.43500E+02 3.73919E+06 + 2.43600E+02 3.56704E+06 + 2.43700E+02 3.12628E+06 + 2.43800E+02 3.64540E+06 + 2.43900E+02 3.97101E+06 + 2.44000E+02 3.69083E+06 + 2.44100E+02 3.24946E+06 + 2.44200E+02 3.00781E+06 + 2.44300E+02 2.66228E+06 + 2.44400E+02 3.47060E+06 + 2.44500E+02 4.20876E+06 + 2.44600E+02 4.35551E+06 + 2.44700E+02 4.62451E+06 + 2.44800E+02 4.16016E+06 + 2.44900E+02 4.19156E+06 + 2.45000E+02 4.03207E+06 + 2.45100E+02 3.93063E+06 + 2.45200E+02 4.43168E+06 + 2.45300E+02 4.61723E+06 + 2.45400E+02 4.94116E+06 + 2.45500E+02 4.25572E+06 + 2.45600E+02 4.81635E+06 + 2.45700E+02 5.10291E+06 + 2.45800E+02 4.72324E+06 + 2.45900E+02 3.99712E+06 + 2.46000E+02 4.93130E+06 + 2.46100E+02 5.69846E+06 + 2.46200E+02 5.62121E+06 + 2.46300E+02 5.68388E+06 + 2.46400E+02 5.84387E+06 + 2.46500E+02 5.30842E+06 + 2.46600E+02 5.48549E+06 + 2.46700E+02 5.39439E+06 + 2.46800E+02 5.37919E+06 + 2.46900E+02 5.35042E+06 + 2.47000E+02 6.40847E+06 + 2.47100E+02 6.62366E+06 + 2.47200E+02 5.92012E+06 + 2.47300E+02 6.34671E+06 + 2.47400E+02 6.18164E+06 + 2.47500E+02 5.21778E+06 + 2.47600E+02 4.75502E+06 + 2.47700E+02 5.28472E+06 + 2.47800E+02 5.16484E+06 + 2.47900E+02 6.17252E+06 + 2.48000E+02 5.94012E+06 + 2.48100E+02 5.68260E+06 + 2.48200E+02 5.17224E+06 + 2.48300E+02 5.72449E+06 + 2.48400E+02 5.45781E+06 + 2.48500E+02 5.35629E+06 + 2.48600E+02 6.34852E+06 + 2.48700E+02 6.21906E+06 + 2.48800E+02 5.98556E+06 + 2.48900E+02 5.02005E+06 + 2.49000E+02 3.71539E+06 + 2.49100E+02 3.37599E+06 + 2.49200E+02 3.88340E+06 + 2.49300E+02 3.19585E+06 + 2.49400E+02 2.73267E+06 + 2.49500E+02 2.46061E+06 + 2.49600E+02 2.43334E+06 + 2.49700E+02 2.33284E+06 + 2.49800E+02 2.59501E+06 + 2.49900E+02 1.97714E+06 + 2.50000E+02 2.55119E+06 + 2.50100E+02 3.57310E+06 + 2.50200E+02 3.89011E+06 + 2.50300E+02 4.22915E+06 + 2.50400E+02 4.94982E+06 + 2.50500E+02 5.30229E+06 + 2.50600E+02 4.28874E+06 + 2.50700E+02 3.46932E+06 + 2.50800E+02 3.76836E+06 + 2.50900E+02 3.25831E+06 + 2.51000E+02 2.43569E+06 + 2.51100E+02 2.56986E+06 + 2.51200E+02 3.65503E+06 + 2.51300E+02 4.21756E+06 + 2.51400E+02 4.31210E+06 + 2.51500E+02 4.81083E+06 + 2.51600E+02 4.84023E+06 + 2.51700E+02 4.76250E+06 + 2.51800E+02 4.75223E+06 + 2.51900E+02 5.65509E+06 + 2.52000E+02 4.91588E+06 + 2.52100E+02 5.09052E+06 + 2.52200E+02 4.86483E+06 + 2.52300E+02 5.43752E+06 + 2.52400E+02 4.98193E+06 + 2.52500E+02 4.82776E+06 + 2.52600E+02 4.89502E+06 + 2.52700E+02 5.43873E+06 + 2.52800E+02 5.95063E+06 + 2.52900E+02 6.27917E+06 + 2.53000E+02 6.43065E+06 + 2.53100E+02 5.24870E+06 + 2.53200E+02 4.75372E+06 + 2.53300E+02 5.41008E+06 + 2.53400E+02 5.82186E+06 + 2.53500E+02 5.86941E+06 + 2.53600E+02 6.31229E+06 + 2.53700E+02 6.02808E+06 + 2.53800E+02 6.46100E+06 + 2.53900E+02 6.59716E+06 + 2.54000E+02 6.41237E+06 + 2.54100E+02 6.33593E+06 + 2.54200E+02 6.34139E+06 + 2.54300E+02 6.77241E+06 + 2.54400E+02 6.09276E+06 + 2.54500E+02 5.60004E+06 + 2.54600E+02 5.83368E+06 + 2.54700E+02 5.25553E+06 + 2.54800E+02 5.23283E+06 + 2.54900E+02 5.55893E+06 + 2.55000E+02 5.51591E+06 + 2.55100E+02 5.14674E+06 + 2.55200E+02 5.78416E+06 + 2.55300E+02 5.78771E+06 + 2.55400E+02 5.32873E+06 + 2.55500E+02 5.34224E+06 + 2.55600E+02 5.90366E+06 + 2.55700E+02 6.27324E+06 + 2.55800E+02 5.62427E+06 + 2.55900E+02 5.02412E+06 + 2.56000E+02 5.03900E+06 + 2.56100E+02 5.36726E+06 + 2.56200E+02 5.59350E+06 + 2.56300E+02 5.69770E+06 + 2.56400E+02 5.95149E+06 + 2.56500E+02 6.34114E+06 + 2.56600E+02 5.73760E+06 + 2.56700E+02 5.87884E+06 + 2.56800E+02 5.73112E+06 + 2.56900E+02 5.71679E+06 + 2.57000E+02 5.03875E+06 + 2.57100E+02 5.69306E+06 + 2.57200E+02 4.85154E+06 + 2.57300E+02 4.55017E+06 + 2.57400E+02 4.61131E+06 + 2.57500E+02 4.20122E+06 + 2.57600E+02 3.15457E+06 + 2.57700E+02 3.49071E+06 + 2.57800E+02 3.16078E+06 + 2.57900E+02 3.12345E+06 + 2.58000E+02 4.16960E+06 + 2.58100E+02 4.11710E+06 + 2.58200E+02 3.09071E+06 + 2.58300E+02 2.70863E+06 + 2.58400E+02 2.28273E+06 + 2.58500E+02 2.80805E+06 + 2.58600E+02 2.10529E+06 + 2.58700E+02 1.93775E+06 + 2.58800E+02 1.95372E+06 + 2.58900E+02 2.22830E+06 + 2.59000E+02 2.87140E+06 + 2.59100E+02 2.48574E+06 + 2.59200E+02 3.40532E+06 + 2.59300E+02 4.33993E+06 + 2.59400E+02 4.38713E+06 + 2.59500E+02 4.39589E+06 + 2.59600E+02 4.41730E+06 + 2.59700E+02 4.27750E+06 + 2.59800E+02 4.56562E+06 + 2.59900E+02 5.44371E+06 + 2.60000E+02 3.91452E+06 + 2.60100E+02 3.27068E+06 + 2.60200E+02 2.55899E+06 + 2.60300E+02 2.24000E+06 + 2.60400E+02 2.69831E+06 + 2.60500E+02 3.47432E+06 + 2.60600E+02 3.95645E+06 + 2.60700E+02 4.42384E+06 + 2.60800E+02 4.99938E+06 + 2.60900E+02 5.02219E+06 + 2.61000E+02 5.08711E+06 + 2.61100E+02 5.41339E+06 + 2.61200E+02 5.42896E+06 + 2.61300E+02 5.29489E+06 + 2.61400E+02 6.04957E+06 + 2.61500E+02 5.98068E+06 + 2.61600E+02 6.93527E+06 + 2.61700E+02 7.41977E+06 + 2.61800E+02 6.99709E+06 + 2.61900E+02 5.04817E+06 + 2.62000E+02 4.96611E+06 + 2.62100E+02 4.99614E+06 + 2.62200E+02 5.61458E+06 + 2.62300E+02 5.95746E+06 + 2.62400E+02 5.50413E+06 + 2.62500E+02 5.54095E+06 + 2.62600E+02 4.83560E+06 + 2.62700E+02 4.94085E+06 + 2.62800E+02 4.35619E+06 + 2.62900E+02 3.54663E+06 + 2.63000E+02 3.72080E+06 + 2.63100E+02 2.98070E+06 + 2.63200E+02 3.59296E+06 + 2.63300E+02 3.61039E+06 + 2.63400E+02 3.37267E+06 + 2.63500E+02 3.57042E+06 + 2.63600E+02 3.65510E+06 + 2.63700E+02 4.24673E+06 + 2.63800E+02 4.78696E+06 + 2.63900E+02 5.40554E+06 + 2.64000E+02 5.17574E+06 + 2.64100E+02 4.82490E+06 + 2.64200E+02 5.05250E+06 + 2.64300E+02 5.09663E+06 + 2.64400E+02 5.51482E+06 + 2.64500E+02 5.42059E+06 + 2.64600E+02 4.76448E+06 + 2.64700E+02 4.40077E+06 + 2.64800E+02 4.45989E+06 + 2.64900E+02 4.33519E+06 + 2.65000E+02 4.32974E+06 + 2.65100E+02 4.69550E+06 + 2.65200E+02 5.19480E+06 + 2.65300E+02 5.27169E+06 + 2.65400E+02 5.39405E+06 + 2.65500E+02 4.79898E+06 + 2.65600E+02 5.14789E+06 + 2.65700E+02 5.15214E+06 + 2.65800E+02 5.58538E+06 + 2.65900E+02 5.85337E+06 + 2.66000E+02 6.20881E+06 + 2.66100E+02 6.31547E+06 + 2.66200E+02 6.20322E+06 + 2.66300E+02 5.35279E+06 + 2.66400E+02 4.68600E+06 + 2.66500E+02 3.48351E+06 + 2.66600E+02 2.30795E+06 + 2.66700E+02 2.10669E+06 + 2.66800E+02 2.38800E+06 + 2.66900E+02 2.27444E+06 + 2.67000E+02 2.63397E+06 + 2.67100E+02 3.49998E+06 + 2.67200E+02 3.32869E+06 + 2.67300E+02 3.24760E+06 + 2.67400E+02 2.72389E+06 + 2.67500E+02 2.16525E+06 + 2.67600E+02 1.16551E+06 + 2.67700E+02 7.74461E+05 + 2.67800E+02 8.07800E+05 + 2.67900E+02 -6.93920E+04 + 2.68000E+02 -3.11066E+05 + 2.68100E+02 1.22639E+06 + 2.68200E+02 1.84254E+06 + 2.68300E+02 2.30078E+06 + 2.68400E+02 3.20843E+06 + 2.68500E+02 3.52070E+06 + 2.68600E+02 3.27807E+06 + 2.68700E+02 3.74477E+06 + 2.68800E+02 5.12071E+06 + 2.68900E+02 5.29823E+06 + 2.69000E+02 5.36010E+06 + 2.69100E+02 4.34487E+06 + 2.69200E+02 4.10796E+06 + 2.69300E+02 4.39101E+06 + 2.69400E+02 3.88502E+06 + 2.69500E+02 4.00186E+06 + 2.69600E+02 4.00349E+06 + 2.69700E+02 2.56648E+06 + 2.69800E+02 3.15337E+06 + 2.69900E+02 3.63028E+06 + 2.70000E+02 3.87696E+06 + 2.70100E+02 3.33633E+06 + 2.70200E+02 3.41442E+06 + 2.70300E+02 4.06606E+06 + 2.70400E+02 4.51846E+06 + 2.70500E+02 4.93854E+06 + 2.70600E+02 5.01502E+06 + 2.70700E+02 4.79726E+06 + 2.70800E+02 4.54301E+06 + 2.70900E+02 4.40672E+06 + 2.71000E+02 3.62641E+06 + 2.71100E+02 4.30975E+06 + 2.71200E+02 5.00493E+06 + 2.71300E+02 4.37455E+06 + 2.71400E+02 4.36564E+06 + 2.71500E+02 4.29275E+06 + 2.71600E+02 4.41095E+06 + 2.71700E+02 3.76346E+06 + 2.71800E+02 3.40349E+06 + 2.71900E+02 3.20950E+06 + 2.72000E+02 3.00222E+06 + 2.72100E+02 3.18749E+06 + 2.72200E+02 1.62328E+06 + 2.72300E+02 2.10536E+06 + 2.72400E+02 2.77968E+06 + 2.72500E+02 2.92026E+06 + 2.72600E+02 3.47906E+06 + 2.72700E+02 4.38018E+06 + 2.72800E+02 4.85992E+06 + 2.72900E+02 5.36314E+06 + 2.73000E+02 5.13099E+06 + 2.73100E+02 5.54409E+06 + 2.73200E+02 5.90075E+06 + 2.73300E+02 5.49374E+06 + 2.73400E+02 6.05095E+06 + 2.73500E+02 5.64768E+06 + 2.73600E+02 5.07380E+06 + 2.73700E+02 4.25772E+06 + 2.73800E+02 3.79350E+06 + 2.73900E+02 4.39382E+06 + 2.74000E+02 4.16917E+06 + 2.74100E+02 4.33819E+06 + 2.74200E+02 4.23336E+06 + 2.74300E+02 3.01571E+06 + 2.74400E+02 2.52968E+06 + 2.74500E+02 2.64153E+06 + 2.74600E+02 3.18559E+06 + 2.74700E+02 2.87354E+06 + 2.74800E+02 3.07660E+06 + 2.74900E+02 2.63666E+06 + 2.75000E+02 3.54263E+06 + 2.75100E+02 2.89424E+06 + 2.75200E+02 2.22957E+06 + 2.75300E+02 3.09919E+06 + 2.75400E+02 3.50015E+06 + 2.75500E+02 3.62438E+06 + 2.75600E+02 3.49427E+06 + 2.75700E+02 4.05725E+06 + 2.75800E+02 3.55114E+06 + 2.75900E+02 3.89111E+06 + 2.76000E+02 3.62893E+06 + 2.76100E+02 3.35307E+06 + 2.76200E+02 3.49338E+06 + 2.76300E+02 4.63915E+06 + 2.76400E+02 4.35651E+06 + 2.76500E+02 3.30714E+06 + 2.76600E+02 3.18875E+06 + 2.76700E+02 3.34648E+06 + 2.76800E+02 3.01209E+06 + 2.76900E+02 2.63796E+06 + 2.77000E+02 2.46661E+06 + 2.77100E+02 2.88669E+06 + 2.77200E+02 3.88155E+06 + 2.77300E+02 4.49980E+06 + 2.77400E+02 4.26866E+06 + 2.77500E+02 4.39195E+06 + 2.77600E+02 4.27982E+06 + 2.77700E+02 3.53342E+06 + 2.77800E+02 3.96443E+06 + 2.77900E+02 3.72504E+06 + 2.78000E+02 3.52784E+06 + 2.78100E+02 4.18523E+06 + 2.78200E+02 4.15859E+06 + 2.78300E+02 3.98033E+06 + 2.78400E+02 3.36879E+06 + 2.78500E+02 2.46302E+06 + 2.78600E+02 2.33495E+06 + 2.78700E+02 2.97668E+06 + 2.78800E+02 3.89193E+06 + 2.78900E+02 4.88758E+06 + 2.79000E+02 4.98649E+06 + 2.79100E+02 5.22700E+06 + 2.79200E+02 5.31585E+06 + 2.79300E+02 5.92802E+06 + 2.79400E+02 5.86142E+06 + 2.79500E+02 5.54836E+06 + 2.79600E+02 5.04178E+06 + 2.79700E+02 5.00463E+06 + 2.79800E+02 5.33982E+06 + 2.79900E+02 5.65126E+06 + 2.80000E+02 6.36045E+06 + 2.80100E+02 5.88192E+06 + 2.80200E+02 4.86707E+06 + 2.80300E+02 4.69137E+06 + 2.80400E+02 3.72877E+06 + 2.80500E+02 3.18529E+06 + 2.80600E+02 4.22932E+06 + 2.80700E+02 3.60661E+06 + 2.80800E+02 2.71840E+06 + 2.80900E+02 3.04296E+06 + 2.81000E+02 3.62411E+06 + 2.81100E+02 4.19384E+06 + 2.81200E+02 4.17921E+06 + 2.81300E+02 4.09357E+06 + 2.81400E+02 4.24416E+06 + 2.81500E+02 3.71962E+06 + 2.81600E+02 3.20878E+06 + 2.81700E+02 4.04702E+06 + 2.81800E+02 3.76299E+06 + 2.81900E+02 2.64601E+06 + 2.82000E+02 2.44770E+06 + 2.82100E+02 3.43516E+06 + 2.82200E+02 4.35543E+06 + 2.82300E+02 4.24843E+06 + 2.82400E+02 4.51517E+06 + 2.82500E+02 5.41613E+06 + 2.82600E+02 5.45901E+06 + 2.82700E+02 5.87923E+06 + 2.82800E+02 5.74642E+06 + 2.82900E+02 5.64683E+06 + 2.83000E+02 5.58885E+06 + 2.83100E+02 5.78949E+06 + 2.83200E+02 5.41699E+06 + 2.83300E+02 4.95256E+06 + 2.83400E+02 4.53243E+06 + 2.83500E+02 5.35390E+06 + 2.83600E+02 5.27429E+06 + 2.83700E+02 4.98671E+06 + 2.83800E+02 4.61899E+06 + 2.83900E+02 4.38961E+06 + 2.84000E+02 3.52179E+06 + 2.84100E+02 3.04772E+06 + 2.84200E+02 2.52873E+06 + 2.84300E+02 2.94354E+06 + 2.84400E+02 2.73931E+06 + 2.84500E+02 3.02593E+06 + 2.84600E+02 2.71030E+06 + 2.84700E+02 3.75657E+06 + 2.84800E+02 4.38851E+06 + 2.84900E+02 3.01993E+06 + 2.85000E+02 2.75409E+06 + 2.85100E+02 2.73642E+06 + 2.85200E+02 3.40754E+06 + 2.85300E+02 4.43016E+06 + 2.85400E+02 4.83984E+06 + 2.85500E+02 5.05122E+06 + 2.85600E+02 4.63601E+06 + 2.85700E+02 4.33961E+06 + 2.85800E+02 4.23560E+06 + 2.85900E+02 4.56025E+06 + 2.86000E+02 4.55259E+06 + 2.86100E+02 4.18023E+06 + 2.86200E+02 4.02634E+06 + 2.86300E+02 5.37419E+06 + 2.86400E+02 6.36533E+06 + 2.86500E+02 6.59294E+06 + 2.86600E+02 6.57782E+06 + 2.86700E+02 5.80687E+06 + 2.86800E+02 5.40563E+06 + 2.86900E+02 4.86600E+06 + 2.87000E+02 5.08641E+06 + 2.87100E+02 4.84058E+06 + 2.87200E+02 4.41492E+06 + 2.87300E+02 4.39144E+06 + 2.87400E+02 4.57453E+06 + 2.87500E+02 4.93199E+06 + 2.87600E+02 4.74475E+06 + 2.87700E+02 5.38994E+06 + 2.87800E+02 4.89701E+06 + 2.87900E+02 5.33759E+06 + 2.88000E+02 4.73554E+06 + 2.88100E+02 4.24816E+06 + 2.88200E+02 4.02178E+06 + 2.88300E+02 3.77768E+06 + 2.88400E+02 3.41992E+06 + 2.88500E+02 4.61447E+06 + 2.88600E+02 3.96144E+06 + 2.88700E+02 3.26242E+06 + 2.88800E+02 3.19059E+06 + 2.88900E+02 3.20192E+06 + 2.89000E+02 2.57091E+06 + 2.89100E+02 2.22501E+06 + 2.89200E+02 2.43121E+06 + 2.89300E+02 2.19767E+06 + 2.89400E+02 2.72914E+06 + 2.89500E+02 2.58525E+06 + 2.89600E+02 3.02735E+06 + 2.89700E+02 3.01988E+06 + 2.89800E+02 3.11344E+06 + 2.89900E+02 3.08435E+06 + 2.90000E+02 2.97434E+06 + 2.90100E+02 3.48375E+06 + 2.90200E+02 3.73944E+06 + 2.90300E+02 4.34960E+06 + 2.90400E+02 3.99745E+06 + 2.90500E+02 4.13633E+06 + 2.90600E+02 4.12859E+06 + 2.90700E+02 3.85193E+06 + 2.90800E+02 3.20034E+06 + 2.90900E+02 2.97404E+06 + 2.91000E+02 2.98327E+06 + 2.91100E+02 3.69803E+06 + 2.91200E+02 3.89567E+06 + 2.91300E+02 4.12530E+06 + 2.91400E+02 3.82592E+06 + 2.91500E+02 3.85478E+06 + 2.91600E+02 4.35335E+06 + 2.91700E+02 4.92606E+06 + 2.91800E+02 4.76185E+06 + 2.91900E+02 5.17552E+06 + 2.92000E+02 5.50666E+06 + 2.92100E+02 5.37951E+06 + 2.92200E+02 4.93137E+06 + 2.92300E+02 4.76799E+06 + 2.92400E+02 5.58690E+06 + 2.92500E+02 6.07507E+06 + 2.92600E+02 5.38604E+06 + 2.92700E+02 5.02964E+06 + 2.92800E+02 4.06783E+06 + 2.92900E+02 4.15154E+06 + 2.93000E+02 4.61320E+06 + 2.93100E+02 3.77262E+06 + 2.93200E+02 4.12943E+06 + 2.93300E+02 5.19825E+06 + 2.93400E+02 4.72858E+06 + 2.93500E+02 3.92730E+06 + 2.93600E+02 3.71072E+06 + 2.93700E+02 3.96626E+06 + 2.93800E+02 3.84995E+06 + 2.93900E+02 3.94456E+06 + 2.94000E+02 4.95283E+06 + 2.94100E+02 5.03482E+06 + 2.94200E+02 4.88772E+06 + 2.94300E+02 4.64544E+06 + 2.94400E+02 4.67907E+06 + 2.94500E+02 4.78739E+06 + 2.94600E+02 4.59863E+06 + 2.94700E+02 5.14058E+06 + 2.94800E+02 4.33749E+06 + 2.94900E+02 3.78820E+06 + 2.95000E+02 3.17342E+06 + 2.95100E+02 3.04927E+06 + 2.95200E+02 2.56945E+06 + 2.95300E+02 1.75333E+06 + 2.95400E+02 7.74728E+05 + 2.95500E+02 7.46108E+05 + 2.95600E+02 1.75730E+06 + 2.95700E+02 1.69399E+06 + 2.95800E+02 2.16505E+06 + 2.95900E+02 2.73885E+06 + 2.96000E+02 2.39804E+06 + 2.96100E+02 2.62822E+06 + 2.96200E+02 2.59346E+06 + 2.96300E+02 3.35372E+06 + 2.96400E+02 3.73280E+06 + 2.96500E+02 3.51609E+06 + 2.96600E+02 4.40241E+06 + 2.96700E+02 5.33800E+06 + 2.96800E+02 5.44597E+06 + 2.96900E+02 4.72415E+06 + 2.97000E+02 5.33839E+06 + 2.97100E+02 4.84596E+06 + 2.97200E+02 4.96155E+06 + 2.97300E+02 5.10364E+06 + 2.97400E+02 4.33976E+06 + 2.97500E+02 3.84022E+06 + 2.97600E+02 3.45556E+06 + 2.97700E+02 3.38801E+06 + 2.97800E+02 3.74488E+06 + 2.97900E+02 3.90046E+06 + 2.98000E+02 3.63783E+06 + 2.98100E+02 4.42264E+06 + 2.98200E+02 4.91814E+06 + 2.98300E+02 3.93988E+06 + 2.98400E+02 4.07282E+06 + 2.98500E+02 4.59752E+06 + 2.98600E+02 4.76624E+06 + 2.98700E+02 4.37137E+06 + 2.98800E+02 3.89660E+06 + 2.98900E+02 4.89734E+06 + 2.99000E+02 5.45127E+06 + 2.99100E+02 5.35233E+06 + 2.99200E+02 4.67532E+06 + 2.99300E+02 4.68138E+06 + 2.99400E+02 4.51176E+06 + 2.99500E+02 4.34107E+06 + 2.99600E+02 3.98374E+06 + 2.99700E+02 4.20530E+06 + 2.99800E+02 4.46102E+06 + 2.99900E+02 4.53728E+06 + 3.00000E+02 3.84748E+06 + 3.00100E+02 2.98112E+06 + 3.00200E+02 3.76162E+06 + 3.00300E+02 4.34327E+06 + 3.00400E+02 4.92296E+06 + 3.00500E+02 4.92457E+06 + 3.00600E+02 5.46422E+06 + 3.00700E+02 6.19484E+06 + 3.00800E+02 6.51209E+06 + 3.00900E+02 6.25991E+06 + 3.01000E+02 6.94309E+06 + 3.01100E+02 6.08121E+06 + 3.01200E+02 5.55060E+06 + 3.01300E+02 5.19790E+06 + 3.01400E+02 4.78858E+06 + 3.01500E+02 5.32249E+06 + 3.01600E+02 6.11490E+06 + 3.01700E+02 5.23837E+06 + 3.01800E+02 4.85374E+06 + 3.01900E+02 4.44465E+06 + 3.02000E+02 4.21300E+06 + 3.02100E+02 4.48147E+06 + 3.02200E+02 3.19257E+06 + 3.02300E+02 3.34636E+06 + 3.02400E+02 2.97760E+06 + 3.02500E+02 3.02203E+06 + 3.02600E+02 3.51689E+06 + 3.02700E+02 3.95305E+06 + 3.02800E+02 3.21384E+06 + 3.02900E+02 3.18716E+06 + 3.03000E+02 3.38772E+06 + 3.03100E+02 3.59936E+06 + 3.03200E+02 3.75867E+06 + 3.03300E+02 4.44133E+06 + 3.03400E+02 3.54893E+06 + 3.03500E+02 3.34643E+06 + 3.03600E+02 3.73820E+06 + 3.03700E+02 3.58743E+06 + 3.03800E+02 3.29353E+06 + 3.03900E+02 3.64742E+06 + 3.04000E+02 2.60662E+06 + 3.04100E+02 2.26906E+06 + 3.04200E+02 2.33119E+06 + 3.04300E+02 3.14000E+06 + 3.04400E+02 4.47034E+06 + 3.04500E+02 4.69911E+06 + 3.04600E+02 4.20236E+06 + 3.04700E+02 4.91650E+06 + 3.04800E+02 5.95085E+06 + 3.04900E+02 5.53833E+06 + 3.05000E+02 5.26329E+06 + 3.05100E+02 4.54591E+06 + 3.05200E+02 3.96273E+06 + 3.05300E+02 3.48260E+06 + 3.05400E+02 3.71491E+06 + 3.05500E+02 4.01322E+06 + 3.05600E+02 3.66126E+06 + 3.05700E+02 3.74159E+06 + 3.05800E+02 3.78937E+06 + 3.05900E+02 3.77902E+06 + 3.06000E+02 3.87085E+06 + 3.06100E+02 4.26133E+06 + 3.06200E+02 3.90221E+06 + 3.06300E+02 3.08437E+06 + 3.06400E+02 2.21288E+06 + 3.06500E+02 2.52678E+06 + 3.06600E+02 1.74648E+06 + 3.06700E+02 1.61070E+06 + 3.06800E+02 2.07796E+06 + 3.06900E+02 3.05515E+06 + 3.07000E+02 3.16671E+06 + 3.07100E+02 3.94550E+06 + 3.07200E+02 4.41282E+06 + 3.07300E+02 3.96548E+06 + 3.07400E+02 3.85473E+06 + 3.07500E+02 3.65073E+06 + 3.07600E+02 3.57551E+06 + 3.07700E+02 3.52709E+06 + 3.07800E+02 3.23398E+06 + 3.07900E+02 3.27529E+06 + 3.08000E+02 3.39318E+06 + 3.08100E+02 3.07667E+06 + 3.08200E+02 2.56134E+06 + 3.08300E+02 3.16887E+06 + 3.08400E+02 2.82529E+06 + 3.08500E+02 2.61076E+06 + 3.08600E+02 1.79414E+06 + 3.08700E+02 1.97766E+06 + 3.08800E+02 2.34757E+06 + 3.08900E+02 2.37538E+06 + 3.09000E+02 2.86294E+06 + 3.09100E+02 2.62111E+06 + 3.09200E+02 2.89296E+06 + 3.09300E+02 3.29354E+06 + 3.09400E+02 3.26734E+06 + 3.09500E+02 3.49268E+06 + 3.09600E+02 3.11175E+06 + 3.09700E+02 2.32598E+06 + 3.09800E+02 1.56740E+06 + 3.09900E+02 1.85134E+06 + 3.10000E+02 1.85798E+06 + 3.10100E+02 2.25744E+06 + 3.10200E+02 2.32570E+06 + 3.10300E+02 2.38089E+06 + 3.10400E+02 3.52743E+06 + 3.10500E+02 3.52053E+06 + 3.10600E+02 2.71753E+06 + 3.10700E+02 3.23385E+06 + 3.10800E+02 3.64464E+06 + 3.10900E+02 3.74294E+06 + 3.11000E+02 3.45942E+06 + 3.11100E+02 3.24456E+06 + 3.11200E+02 2.90054E+06 + 3.11300E+02 2.68121E+06 + 3.11400E+02 2.53581E+06 + 3.11500E+02 2.20121E+06 + 3.11600E+02 2.14345E+06 + 3.11700E+02 2.68709E+06 + 3.11800E+02 1.66686E+06 + 3.11900E+02 1.29477E+06 + 3.12000E+02 1.44717E+06 + 3.12100E+02 1.38013E+06 + 3.12200E+02 7.75744E+05 + 3.12300E+02 1.50551E+06 + 3.12400E+02 1.46456E+06 + 3.12500E+02 1.42370E+06 + 3.12600E+02 2.16896E+06 + 3.12700E+02 3.43919E+06 + 3.12800E+02 3.50507E+06 + 3.12900E+02 4.37427E+06 + 3.13000E+02 4.19256E+06 + 3.13100E+02 3.33174E+06 + 3.13200E+02 2.15680E+06 + 3.13300E+02 1.44354E+06 + 3.13400E+02 1.38035E+06 + 3.13500E+02 9.93819E+05 + 3.13600E+02 1.26689E+06 + 3.13700E+02 1.94332E+06 + 3.13800E+02 2.35262E+06 + 3.13900E+02 2.51906E+06 + 3.14000E+02 2.50641E+06 + 3.14100E+02 2.41281E+06 + 3.14200E+02 1.95528E+06 + 3.14300E+02 3.29130E+06 + 3.14400E+02 3.76108E+06 + 3.14500E+02 3.51837E+06 + 3.14600E+02 3.45521E+06 + 3.14700E+02 2.42072E+06 + 3.14800E+02 3.17501E+06 + 3.14900E+02 2.92730E+06 + 3.15000E+02 3.67755E+06 + 3.15100E+02 3.49271E+06 + 3.15200E+02 4.12757E+06 + 3.15300E+02 5.04914E+06 + 3.15400E+02 4.94186E+06 + 3.15500E+02 5.07591E+06 + 3.15600E+02 5.87744E+06 + 3.15700E+02 5.78407E+06 + 3.15800E+02 5.47292E+06 + 3.15900E+02 4.79669E+06 + 3.16000E+02 3.63117E+06 + 3.16100E+02 3.85418E+06 + 3.16200E+02 3.79095E+06 + 3.16300E+02 2.87826E+06 + 3.16400E+02 2.19097E+06 + 3.16500E+02 2.60286E+06 + 3.16600E+02 3.23927E+06 + 3.16700E+02 2.59695E+06 + 3.16800E+02 3.15238E+06 + 3.16900E+02 3.75933E+06 + 3.17000E+02 3.67585E+06 + 3.17100E+02 3.94642E+06 + 3.17200E+02 4.19337E+06 + 3.17300E+02 3.85947E+06 + 3.17400E+02 2.66459E+06 + 3.17500E+02 1.96488E+06 + 3.17600E+02 2.02574E+06 + 3.17700E+02 2.63975E+06 + 3.17800E+02 2.54123E+06 + 3.17900E+02 2.41028E+06 + 3.18000E+02 2.58433E+06 + 3.18100E+02 2.22400E+06 + 3.18200E+02 2.06312E+06 + 3.18300E+02 2.33130E+06 + 3.18400E+02 2.19248E+06 + 3.18500E+02 3.28689E+06 + 3.18600E+02 4.56315E+06 + 3.18700E+02 4.96307E+06 + 3.18800E+02 5.31853E+06 + 3.18900E+02 5.14450E+06 + 3.19000E+02 3.58593E+06 + 3.19100E+02 3.53346E+06 + 3.19200E+02 3.88367E+06 + 3.19300E+02 4.08622E+06 + 3.19400E+02 4.18556E+06 + 3.19500E+02 3.91541E+06 + 3.19600E+02 3.75940E+06 + 3.19700E+02 5.06740E+06 + 3.19800E+02 5.52149E+06 + 3.19900E+02 5.59510E+06 + 3.20000E+02 4.73690E+06 + 3.20100E+02 4.68202E+06 + 3.20200E+02 4.39033E+06 + 3.20300E+02 4.57937E+06 + 3.20400E+02 5.03432E+06 + 3.20500E+02 4.99242E+06 + 3.20600E+02 5.26461E+06 + 3.20700E+02 5.44765E+06 + 3.20800E+02 5.46405E+06 + 3.20900E+02 5.65682E+06 + 3.21000E+02 4.34134E+06 + 3.21100E+02 3.36950E+06 + 3.21200E+02 3.01634E+06 + 3.21300E+02 3.24005E+06 + 3.21400E+02 2.41836E+06 + 3.21500E+02 2.61975E+06 + 3.21600E+02 2.80130E+06 + 3.21700E+02 2.99107E+06 + 3.21800E+02 3.24360E+06 + 3.21900E+02 2.73104E+06 + 3.22000E+02 2.43788E+06 + 3.22100E+02 2.19791E+06 + 3.22200E+02 3.07836E+06 + 3.22300E+02 3.85798E+06 + 3.22400E+02 3.97468E+06 + 3.22500E+02 4.04910E+06 + 3.22600E+02 3.90958E+06 + 3.22700E+02 3.66657E+06 + 3.22800E+02 3.67903E+06 + 3.22900E+02 4.07153E+06 + 3.23000E+02 4.63376E+06 + 3.23100E+02 4.36574E+06 + 3.23200E+02 4.95119E+06 + 3.23300E+02 4.90347E+06 + 3.23400E+02 4.90184E+06 + 3.23500E+02 5.35179E+06 + 3.23600E+02 5.52968E+06 + 3.23700E+02 6.02710E+06 + 3.23800E+02 5.70714E+06 + 3.23900E+02 4.98691E+06 + 3.24000E+02 5.48993E+06 + 3.24100E+02 5.63401E+06 + 3.24200E+02 6.21984E+06 + 3.24300E+02 7.10603E+06 + 3.24400E+02 6.87340E+06 + 3.24500E+02 7.09059E+06 + 3.24600E+02 6.51449E+06 + 3.24700E+02 6.10683E+06 + 3.24800E+02 5.35128E+06 + 3.24900E+02 5.85881E+06 + 3.25000E+02 6.02511E+06 + 3.25100E+02 5.39020E+06 + 3.25200E+02 4.74644E+06 + 3.25300E+02 4.01664E+06 + 3.25400E+02 4.04749E+06 + 3.25500E+02 4.29004E+06 + 3.25600E+02 4.07897E+06 + 3.25700E+02 4.38607E+06 + 3.25800E+02 4.27819E+06 + 3.25900E+02 4.51942E+06 + 3.26000E+02 5.13819E+06 + 3.26100E+02 4.58126E+06 + 3.26200E+02 4.82943E+06 + 3.26300E+02 5.14064E+06 + 3.26400E+02 4.75829E+06 + 3.26500E+02 4.75439E+06 + 3.26600E+02 4.86188E+06 + 3.26700E+02 5.02982E+06 + 3.26800E+02 4.80180E+06 + 3.26900E+02 4.66567E+06 + 3.27000E+02 5.04171E+06 + 3.27100E+02 4.60246E+06 + 3.27200E+02 4.68190E+06 + 3.27300E+02 3.33212E+06 + 3.27400E+02 3.30780E+06 + 3.27500E+02 3.88115E+06 + 3.27600E+02 3.39252E+06 + 3.27700E+02 2.84858E+06 + 3.27800E+02 3.48523E+06 + 3.27900E+02 4.19948E+06 + 3.28000E+02 4.30333E+06 + 3.28100E+02 4.51147E+06 + 3.28200E+02 4.68650E+06 + 3.28300E+02 4.97256E+06 + 3.28400E+02 4.99782E+06 + 3.28500E+02 4.38659E+06 + 3.28600E+02 3.70377E+06 + 3.28700E+02 4.20505E+06 + 3.28800E+02 4.57152E+06 + 3.28900E+02 4.91866E+06 + 3.29000E+02 5.05882E+06 + 3.29100E+02 4.93896E+06 + 3.29200E+02 4.69592E+06 + 3.29300E+02 4.26282E+06 + 3.29400E+02 4.64900E+06 + 3.29500E+02 4.99398E+06 + 3.29600E+02 4.15891E+06 + 3.29700E+02 4.20890E+06 + 3.29800E+02 5.06031E+06 + 3.29900E+02 5.15594E+06 + 3.30000E+02 5.42781E+06 + 3.30100E+02 5.02233E+06 + 3.30200E+02 4.72389E+06 + 3.30300E+02 4.29577E+06 + 3.30400E+02 4.60741E+06 + 3.30500E+02 4.23918E+06 + 3.30600E+02 3.91242E+06 + 3.30700E+02 4.06019E+06 + 3.30800E+02 4.29966E+06 + 3.30900E+02 4.38639E+06 + 3.31000E+02 4.31497E+06 + 3.31100E+02 4.60620E+06 + 3.31200E+02 4.54707E+06 + 3.31300E+02 3.49478E+06 + 3.31400E+02 3.47608E+06 + 3.31500E+02 4.14270E+06 + 3.31600E+02 4.19852E+06 + 3.31700E+02 4.24347E+06 + 3.31800E+02 3.86201E+06 + 3.31900E+02 3.30480E+06 + 3.32000E+02 3.50884E+06 + 3.32100E+02 3.84453E+06 + 3.32200E+02 3.62769E+06 + 3.32300E+02 4.22138E+06 + 3.32400E+02 4.78330E+06 + 3.32500E+02 4.29773E+06 + 3.32600E+02 4.46586E+06 + 3.32700E+02 4.95007E+06 + 3.32800E+02 5.06484E+06 + 3.32900E+02 6.26991E+06 + 3.33000E+02 5.77634E+06 + 3.33100E+02 5.67499E+06 + 3.33200E+02 6.58817E+06 + 3.33300E+02 6.42315E+06 + 3.33400E+02 5.01814E+06 + 3.33500E+02 4.66902E+06 + 3.33600E+02 5.80898E+06 + 3.33700E+02 6.69713E+06 + 3.33800E+02 7.68531E+06 + 3.33900E+02 7.81195E+06 + 3.34000E+02 6.58819E+06 + 3.34100E+02 6.17548E+06 + 3.34200E+02 5.84915E+06 + 3.34300E+02 5.36893E+06 + 3.34400E+02 5.51743E+06 + 3.34500E+02 5.67886E+06 + 3.34600E+02 5.26206E+06 + 3.34700E+02 4.59987E+06 + 3.34800E+02 4.64302E+06 + 3.34900E+02 4.68853E+06 + 3.35000E+02 4.30671E+06 + 3.35100E+02 4.07425E+06 + 3.35200E+02 3.94496E+06 + 3.35300E+02 4.22717E+06 + 3.35400E+02 4.14423E+06 + 3.35500E+02 4.21836E+06 + 3.35600E+02 3.85851E+06 + 3.35700E+02 3.27999E+06 + 3.35800E+02 3.94367E+06 + 3.35900E+02 3.87745E+06 + 3.36000E+02 3.31547E+06 + 3.36100E+02 2.36446E+06 + 3.36200E+02 2.00370E+06 + 3.36300E+02 2.11990E+06 + 3.36400E+02 1.73673E+06 + 3.36500E+02 1.98085E+06 + 3.36600E+02 2.08789E+06 + 3.36700E+02 1.83366E+06 + 3.36800E+02 1.53429E+06 + 3.36900E+02 1.76595E+06 + 3.37000E+02 2.45009E+06 + 3.37100E+02 2.99468E+06 + 3.37200E+02 2.88274E+06 + 3.37300E+02 2.58218E+06 + 3.37400E+02 3.09676E+06 + 3.37500E+02 3.94897E+06 + 3.37600E+02 2.85041E+06 + 3.37700E+02 3.52361E+06 + 3.37800E+02 4.31662E+06 + 3.37900E+02 3.47103E+06 + 3.38000E+02 3.55173E+06 + 3.38100E+02 3.70951E+06 + 3.38200E+02 4.52080E+06 + 3.38300E+02 4.99582E+06 + 3.38400E+02 5.56094E+06 + 3.38500E+02 6.26650E+06 + 3.38600E+02 6.85949E+06 + 3.38700E+02 6.68260E+06 + 3.38800E+02 6.19185E+06 + 3.38900E+02 5.81244E+06 + 3.39000E+02 5.97854E+06 + 3.39100E+02 6.54572E+06 + 3.39200E+02 6.71748E+06 + 3.39300E+02 6.25665E+06 + 3.39400E+02 6.78306E+06 + 3.39500E+02 6.97832E+06 + 3.39600E+02 6.35422E+06 + 3.39700E+02 5.57767E+06 + 3.39800E+02 5.71245E+06 + 3.39900E+02 6.02276E+06 + 3.40000E+02 5.88075E+06 + 3.40100E+02 5.61127E+06 + 3.40200E+02 5.23463E+06 + 3.40300E+02 5.91435E+06 + 3.40400E+02 5.80972E+06 + 3.40500E+02 6.08516E+06 + 3.40600E+02 5.76760E+06 + 3.40700E+02 6.19258E+06 + 3.40800E+02 6.30323E+06 + 3.40900E+02 6.14035E+06 + 3.41000E+02 5.39121E+06 + 3.41100E+02 5.71327E+06 + 3.41200E+02 4.46587E+06 + 3.41300E+02 4.33359E+06 + 3.41400E+02 3.92799E+06 + 3.41500E+02 3.50607E+06 + 3.41600E+02 3.68231E+06 + 3.41700E+02 3.17284E+06 + 3.41800E+02 2.90549E+06 + 3.41900E+02 3.98994E+06 + 3.42000E+02 4.03771E+06 + 3.42100E+02 3.54336E+06 + 3.42200E+02 3.25429E+06 + 3.42300E+02 3.85500E+06 + 3.42400E+02 4.09248E+06 + 3.42500E+02 4.14442E+06 + 3.42600E+02 4.61027E+06 + 3.42700E+02 4.66216E+06 + 3.42800E+02 5.15268E+06 + 3.42900E+02 5.08388E+06 + 3.43000E+02 3.67281E+06 + 3.43100E+02 3.29283E+06 + 3.43200E+02 3.95605E+06 + 3.43300E+02 3.86181E+06 + 3.43400E+02 4.54562E+06 + 3.43500E+02 5.58272E+06 + 3.43600E+02 5.26275E+06 + 3.43700E+02 5.17028E+06 + 3.43800E+02 4.79730E+06 + 3.43900E+02 4.82683E+06 + 3.44000E+02 5.04334E+06 + 3.44100E+02 5.11747E+06 + 3.44200E+02 4.28809E+06 + 3.44300E+02 3.75934E+06 + 3.44400E+02 4.78400E+06 + 3.44500E+02 4.60718E+06 + 3.44600E+02 4.60288E+06 + 3.44700E+02 4.13321E+06 + 3.44800E+02 3.53292E+06 + 3.44900E+02 2.99892E+06 + 3.45000E+02 3.17110E+06 + 3.45100E+02 2.82648E+06 + 3.45200E+02 2.41733E+06 + 3.45300E+02 2.66433E+06 + 3.45400E+02 3.34698E+06 + 3.45500E+02 3.20013E+06 + 3.45600E+02 2.98452E+06 + 3.45700E+02 2.90249E+06 + 3.45800E+02 3.19588E+06 + 3.45900E+02 3.19051E+06 + 3.46000E+02 2.98020E+06 + 3.46100E+02 3.34401E+06 + 3.46200E+02 3.01775E+06 + 3.46300E+02 2.47920E+06 + 3.46400E+02 2.71005E+06 + 3.46500E+02 2.51424E+06 + 3.46600E+02 3.10459E+06 + 3.46700E+02 3.50529E+06 + 3.46800E+02 3.05182E+06 + 3.46900E+02 2.90476E+06 + 3.47000E+02 2.59572E+06 + 3.47100E+02 2.19512E+06 + 3.47200E+02 2.27817E+06 + 3.47300E+02 1.70624E+06 + 3.47400E+02 2.23618E+06 + 3.47500E+02 1.67760E+06 + 3.47600E+02 1.60172E+06 + 3.47700E+02 1.31369E+06 + 3.47800E+02 1.26293E+06 + 3.47900E+02 1.27500E+06 + 3.48000E+02 2.20883E+06 + 3.48100E+02 2.18298E+06 + 3.48200E+02 1.62238E+06 + 3.48300E+02 8.91374E+05 + 3.48400E+02 1.08313E+06 + 3.48500E+02 1.43593E+06 + 3.48600E+02 1.98514E+06 + 3.48700E+02 1.88298E+06 + 3.48800E+02 2.31862E+06 + 3.48900E+02 2.53845E+06 + 3.49000E+02 2.72841E+06 + 3.49100E+02 2.24421E+06 + 3.49200E+02 2.25368E+06 + 3.49300E+02 1.30712E+06 + 3.49400E+02 1.77344E+06 + 3.49500E+02 2.65592E+06 + 3.49600E+02 2.87980E+06 + 3.49700E+02 2.93440E+06 + 3.49800E+02 3.24853E+06 + 3.49900E+02 3.30573E+06 + 3.50000E+02 3.40030E+06 + 3.50100E+02 3.27433E+06 + 3.50200E+02 2.90190E+06 + 3.50300E+02 3.51126E+06 + 3.50400E+02 3.83906E+06 + 3.50500E+02 4.23982E+06 + 3.50600E+02 4.53325E+06 + 3.50700E+02 4.61423E+06 + 3.50800E+02 4.74915E+06 + 3.50900E+02 4.38958E+06 + 3.51000E+02 4.26326E+06 + 3.51100E+02 4.56877E+06 + 3.51200E+02 4.69436E+06 + 3.51300E+02 4.75371E+06 + 3.51400E+02 4.78615E+06 + 3.51500E+02 4.87508E+06 + 3.51600E+02 5.57655E+06 + 3.51700E+02 4.70615E+06 + 3.51800E+02 3.99447E+06 + 3.51900E+02 4.34000E+06 + 3.52000E+02 4.50597E+06 + 3.52100E+02 4.61629E+06 + 3.52200E+02 4.14182E+06 + 3.52300E+02 3.96265E+06 + 3.52400E+02 3.56011E+06 + 3.52500E+02 3.01924E+06 + 3.52600E+02 3.05946E+06 + 3.52700E+02 3.54475E+06 + 3.52800E+02 3.34951E+06 + 3.52900E+02 3.39433E+06 + 3.53000E+02 2.75000E+06 + 3.53100E+02 2.88618E+06 + 3.53200E+02 3.55382E+06 + 3.53300E+02 4.31257E+06 + 3.53400E+02 4.82925E+06 + 3.53500E+02 4.80782E+06 + 3.53600E+02 4.68391E+06 + 3.53700E+02 4.68690E+06 + 3.53800E+02 5.03254E+06 + 3.53900E+02 5.62967E+06 + 3.54000E+02 6.25115E+06 + 3.54100E+02 6.14533E+06 + 3.54200E+02 6.03902E+06 + 3.54300E+02 6.08149E+06 + 3.54400E+02 6.18682E+06 + 3.54500E+02 4.81937E+06 + 3.54600E+02 4.46501E+06 + 3.54700E+02 4.49964E+06 + 3.54800E+02 4.56439E+06 + 3.54900E+02 4.30287E+06 + 3.55000E+02 4.65892E+06 + 3.55100E+02 4.79923E+06 + 3.55200E+02 5.34137E+06 + 3.55300E+02 4.96740E+06 + 3.55400E+02 4.11461E+06 + 3.55500E+02 3.23201E+06 + 3.55600E+02 3.46508E+06 + 3.55700E+02 3.96091E+06 + 3.55800E+02 3.50567E+06 + 3.55900E+02 4.29512E+06 + 3.56000E+02 4.66275E+06 + 3.56100E+02 4.85415E+06 + 3.56200E+02 4.78502E+06 + 3.56300E+02 4.25987E+06 + 3.56400E+02 4.50371E+06 + 3.56500E+02 4.00093E+06 + 3.56600E+02 4.95373E+06 + 3.56700E+02 5.45960E+06 + 3.56800E+02 5.27390E+06 + 3.56900E+02 4.66988E+06 + 3.57000E+02 4.93307E+06 + 3.57100E+02 4.84482E+06 + 3.57200E+02 5.80431E+06 + 3.57300E+02 5.79127E+06 + 3.57400E+02 6.26171E+06 + 3.57500E+02 6.99992E+06 + 3.57600E+02 7.01735E+06 + 3.57700E+02 5.87706E+06 + 3.57800E+02 5.85765E+06 + 3.57900E+02 5.86501E+06 + 3.58000E+02 6.67212E+06 + 3.58100E+02 7.37328E+06 + 3.58200E+02 6.67537E+06 + 3.58300E+02 6.45273E+06 + 3.58400E+02 6.31094E+06 + 3.58500E+02 6.73383E+06 + 3.58600E+02 6.79921E+06 + 3.58700E+02 6.91828E+06 + 3.58800E+02 7.21822E+06 + 3.58900E+02 6.94858E+06 + 3.59000E+02 6.02656E+06 + 3.59100E+02 5.96101E+06 + 3.59200E+02 5.84140E+06 + 3.59300E+02 5.48335E+06 + 3.59400E+02 4.78985E+06 + 3.59500E+02 5.58839E+06 + 3.59600E+02 6.48336E+06 + 3.59700E+02 6.40459E+06 + 3.59800E+02 5.70619E+06 + 3.59900E+02 5.13650E+06 + 3.60000E+02 6.00342E+06 + 3.60100E+02 5.86920E+06 + 3.60200E+02 4.64949E+06 + 3.60300E+02 4.69510E+06 + 3.60400E+02 4.29647E+06 + 3.60500E+02 5.76276E+06 + 3.60600E+02 5.74641E+06 + 3.60700E+02 5.75648E+06 + 3.60800E+02 5.82972E+06 + 3.60900E+02 5.34490E+06 + 3.61000E+02 5.14610E+06 + 3.61100E+02 4.37031E+06 + 3.61200E+02 3.94170E+06 + 3.61300E+02 4.19099E+06 + 3.61400E+02 4.30821E+06 + 3.61500E+02 4.25398E+06 + 3.61600E+02 3.57299E+06 + 3.61700E+02 3.99404E+06 + 3.61800E+02 3.94866E+06 + 3.61900E+02 3.97663E+06 + 3.62000E+02 4.22974E+06 + 3.62100E+02 3.08042E+06 + 3.62200E+02 2.68653E+06 + 3.62300E+02 2.85623E+06 + 3.62400E+02 2.14275E+06 + 3.62500E+02 1.81421E+06 + 3.62600E+02 1.89576E+06 + 3.62700E+02 2.03074E+06 + 3.62800E+02 1.80736E+06 + 3.62900E+02 2.07454E+06 + 3.63000E+02 2.53973E+06 + 3.63100E+02 2.53117E+06 + 3.63200E+02 2.80194E+06 + 3.63300E+02 2.85988E+06 + 3.63400E+02 3.12342E+06 + 3.63500E+02 3.19740E+06 + 3.63600E+02 4.05136E+06 + 3.63700E+02 3.93726E+06 + 3.63800E+02 3.80741E+06 + 3.63900E+02 3.80637E+06 + 3.64000E+02 4.01450E+06 + 3.64100E+02 3.58633E+06 + 3.64200E+02 3.05084E+06 + 3.64300E+02 2.77510E+06 + 3.64400E+02 2.24352E+06 + 3.64500E+02 1.94733E+06 + 3.64600E+02 2.82960E+06 + 3.64700E+02 2.29277E+06 + 3.64800E+02 1.85179E+06 + 3.64900E+02 1.49323E+06 + 3.65000E+02 1.72830E+06 + 3.65100E+02 1.89995E+06 + 3.65200E+02 1.94065E+06 + 3.65300E+02 2.83694E+06 + 3.65400E+02 3.44243E+06 + 3.65500E+02 4.45950E+06 + 3.65600E+02 4.85786E+06 + 3.65700E+02 5.51389E+06 + 3.65800E+02 4.92272E+06 + 3.65900E+02 5.33533E+06 + 3.66000E+02 5.86958E+06 + 3.66100E+02 6.56828E+06 + 3.66200E+02 6.16200E+06 + 3.66300E+02 5.46396E+06 + 3.66400E+02 4.86922E+06 + 3.66500E+02 5.73036E+06 + 3.66600E+02 6.61113E+06 + 3.66700E+02 5.62461E+06 + 3.66800E+02 5.31151E+06 + 3.66900E+02 5.47219E+06 + 3.67000E+02 4.90706E+06 + 3.67100E+02 5.14418E+06 + 3.67200E+02 5.16569E+06 + 3.67300E+02 4.64995E+06 + 3.67400E+02 3.44588E+06 + 3.67500E+02 2.72446E+06 + 3.67600E+02 2.81056E+06 + 3.67700E+02 3.09197E+06 + 3.67800E+02 3.52681E+06 + 3.67900E+02 3.24335E+06 + 3.68000E+02 3.23729E+06 + 3.68100E+02 3.42115E+06 + 3.68200E+02 3.51177E+06 + 3.68300E+02 4.54218E+06 + 3.68400E+02 4.42137E+06 + 3.68500E+02 3.74638E+06 + 3.68600E+02 3.67209E+06 + 3.68700E+02 3.12047E+06 + 3.68800E+02 2.90026E+06 + 3.68900E+02 3.29750E+06 + 3.69000E+02 3.85115E+06 + 3.69100E+02 4.18313E+06 + 3.69200E+02 3.54079E+06 + 3.69300E+02 2.83105E+06 + 3.69400E+02 3.11812E+06 + 3.69500E+02 2.89694E+06 + 3.69600E+02 4.26953E+06 + 3.69700E+02 4.92331E+06 + 3.69800E+02 5.31656E+06 + 3.69900E+02 5.20018E+06 + 3.70000E+02 5.48175E+06 + 3.70100E+02 5.72507E+06 + 3.70200E+02 5.94971E+06 + 3.70300E+02 6.15462E+06 + 3.70400E+02 6.63582E+06 + 3.70500E+02 5.94242E+06 + 3.70600E+02 5.87434E+06 + 3.70700E+02 7.06235E+06 + 3.70800E+02 7.37167E+06 + 3.70900E+02 6.25038E+06 + 3.71000E+02 6.14562E+06 + 3.71100E+02 5.84290E+06 + 3.71200E+02 5.22248E+06 + 3.71300E+02 4.24877E+06 + 3.71400E+02 3.36602E+06 + 3.71500E+02 3.37840E+06 + 3.71600E+02 3.03052E+06 + 3.71700E+02 2.18418E+06 + 3.71800E+02 2.80905E+06 + 3.71900E+02 3.32796E+06 + 3.72000E+02 2.98302E+06 + 3.72100E+02 3.33157E+06 + 3.72200E+02 3.62054E+06 + 3.72300E+02 4.26787E+06 + 3.72400E+02 4.52529E+06 + 3.72500E+02 3.96263E+06 + 3.72600E+02 3.49451E+06 + 3.72700E+02 2.56895E+06 + 3.72800E+02 2.01730E+06 + 3.72900E+02 1.56175E+06 + 3.73000E+02 1.64489E+06 + 3.73100E+02 2.40855E+06 + 3.73200E+02 3.28921E+06 + 3.73300E+02 3.69939E+06 + 3.73400E+02 4.21224E+06 + 3.73500E+02 3.70031E+06 + 3.73600E+02 3.57900E+06 + 3.73700E+02 2.91644E+06 + 3.73800E+02 2.85982E+06 + 3.73900E+02 3.41430E+06 + 3.74000E+02 3.16110E+06 + 3.74100E+02 2.69354E+06 + 3.74200E+02 2.01374E+06 + 3.74300E+02 1.96116E+06 + 3.74400E+02 2.61077E+06 + 3.74500E+02 2.46242E+06 + 3.74600E+02 2.72868E+06 + 3.74700E+02 2.80077E+06 + 3.74800E+02 2.98117E+06 + 3.74900E+02 2.96804E+06 + 3.75000E+02 2.28541E+06 + 3.75100E+02 2.25798E+06 + 3.75200E+02 2.57139E+06 + 3.75300E+02 3.16216E+06 + 3.75400E+02 3.73264E+06 + 3.75500E+02 2.98331E+06 + 3.75600E+02 2.55385E+06 + 3.75700E+02 2.76725E+06 + 3.75800E+02 3.48762E+06 + 3.75900E+02 3.56925E+06 + 3.76000E+02 3.80302E+06 + 3.76100E+02 3.31709E+06 + 3.76200E+02 3.68193E+06 + 3.76300E+02 3.18214E+06 + 3.76400E+02 3.84629E+06 + 3.76500E+02 3.55424E+06 + 3.76600E+02 2.77582E+06 + 3.76700E+02 3.12298E+06 + 3.76800E+02 3.11920E+06 + 3.76900E+02 3.26145E+06 + 3.77000E+02 2.89898E+06 + 3.77100E+02 2.63487E+06 + 3.77200E+02 1.96590E+06 + 3.77300E+02 2.05948E+06 + 3.77400E+02 2.65304E+06 + 3.77500E+02 3.73131E+06 + 3.77600E+02 4.35015E+06 + 3.77700E+02 4.34914E+06 + 3.77800E+02 4.92433E+06 + 3.77900E+02 5.15488E+06 + 3.78000E+02 4.07200E+06 + 3.78100E+02 3.29326E+06 + 3.78200E+02 3.25977E+06 + 3.78300E+02 4.09533E+06 + 3.78400E+02 4.00237E+06 + 3.78500E+02 3.90404E+06 + 3.78600E+02 4.66934E+06 + 3.78700E+02 5.99400E+06 + 3.78800E+02 5.48956E+06 + 3.78900E+02 5.36184E+06 + 3.79000E+02 4.99209E+06 + 3.79100E+02 4.87385E+06 + 3.79200E+02 4.02497E+06 + 3.79300E+02 3.88970E+06 + 3.79400E+02 4.31604E+06 + 3.79500E+02 4.71101E+06 + 3.79600E+02 5.02842E+06 + 3.79700E+02 5.00166E+06 + 3.79800E+02 4.09562E+06 + 3.79900E+02 3.42656E+06 + 3.80000E+02 3.45225E+06 + 3.80100E+02 3.14016E+06 + 3.80200E+02 3.09681E+06 + 3.80300E+02 3.97302E+06 + 3.80400E+02 5.36392E+06 + 3.80500E+02 5.50748E+06 + 3.80600E+02 5.07991E+06 + 3.80700E+02 5.69515E+06 + 3.80800E+02 7.00330E+06 + 3.80900E+02 6.81531E+06 + 3.81000E+02 6.76790E+06 + 3.81100E+02 6.08316E+06 + 3.81200E+02 5.87246E+06 + 3.81300E+02 6.80475E+06 + 3.81400E+02 6.07213E+06 + 3.81500E+02 5.59008E+06 + 3.81600E+02 5.97259E+06 + 3.81700E+02 5.80744E+06 + 3.81800E+02 6.17491E+06 + 3.81900E+02 6.04249E+06 + 3.82000E+02 5.40238E+06 + 3.82100E+02 5.12618E+06 + 3.82200E+02 5.68161E+06 + 3.82300E+02 5.27059E+06 + 3.82400E+02 5.46728E+06 + 3.82500E+02 5.31045E+06 + 3.82600E+02 5.96456E+06 + 3.82700E+02 6.50983E+06 + 3.82800E+02 6.92566E+06 + 3.82900E+02 6.19490E+06 + 3.83000E+02 5.22962E+06 + 3.83100E+02 4.83562E+06 + 3.83200E+02 5.44800E+06 + 3.83300E+02 5.40075E+06 + 3.83400E+02 5.81647E+06 + 3.83500E+02 5.35847E+06 + 3.83600E+02 4.48748E+06 + 3.83700E+02 3.86002E+06 + 3.83800E+02 3.36358E+06 + 3.83900E+02 3.80045E+06 + 3.84000E+02 3.33721E+06 + 3.84100E+02 3.91756E+06 + 3.84200E+02 4.13447E+06 + 3.84300E+02 3.65238E+06 + 3.84400E+02 4.34036E+06 + 3.84500E+02 4.29924E+06 + 3.84600E+02 4.57284E+06 + 3.84700E+02 4.97173E+06 + 3.84800E+02 4.31551E+06 + 3.84900E+02 4.91244E+06 + 3.85000E+02 4.63219E+06 + 3.85100E+02 5.19351E+06 + 3.85200E+02 4.50221E+06 + 3.85300E+02 4.55422E+06 + 3.85400E+02 4.23797E+06 + 3.85500E+02 4.87665E+06 + 3.85600E+02 4.00441E+06 + 3.85700E+02 3.99101E+06 + 3.85800E+02 4.00255E+06 + 3.85900E+02 4.66901E+06 + 3.86000E+02 4.75899E+06 + 3.86100E+02 5.14140E+06 + 3.86200E+02 4.86187E+06 + 3.86300E+02 4.66130E+06 + 3.86400E+02 4.64876E+06 + 3.86500E+02 4.55335E+06 + 3.86600E+02 4.58757E+06 + 3.86700E+02 5.09038E+06 + 3.86800E+02 5.74934E+06 + 3.86900E+02 5.81767E+06 + 3.87000E+02 5.30155E+06 + 3.87100E+02 4.83604E+06 + 3.87200E+02 3.93738E+06 + 3.87300E+02 3.54413E+06 + 3.87400E+02 3.86353E+06 + 3.87500E+02 3.30148E+06 + 3.87600E+02 3.58518E+06 + 3.87700E+02 4.11409E+06 + 3.87800E+02 5.38310E+06 + 3.87900E+02 5.38847E+06 + 3.88000E+02 4.35754E+06 + 3.88100E+02 4.56994E+06 + 3.88200E+02 4.57373E+06 + 3.88300E+02 4.98713E+06 + 3.88400E+02 5.48219E+06 + 3.88500E+02 6.04396E+06 + 3.88600E+02 5.87084E+06 + 3.88700E+02 5.59867E+06 + 3.88800E+02 5.98498E+06 + 3.88900E+02 5.46387E+06 + 3.89000E+02 5.77214E+06 + 3.89100E+02 6.06058E+06 + 3.89200E+02 6.86867E+06 + 3.89300E+02 7.62289E+06 + 3.89400E+02 8.23956E+06 + 3.89500E+02 7.81245E+06 + 3.89600E+02 8.15769E+06 + 3.89700E+02 7.57459E+06 + 3.89800E+02 6.79478E+06 + 3.89900E+02 5.93352E+06 + 3.90000E+02 5.60806E+06 + 3.90100E+02 5.23511E+06 + 3.90200E+02 4.89795E+06 + 3.90300E+02 5.51284E+06 + 3.90400E+02 5.88637E+06 + 3.90500E+02 5.03104E+06 + 3.90600E+02 5.53589E+06 + 3.90700E+02 6.37469E+06 + 3.90800E+02 6.49298E+06 + 3.90900E+02 6.66739E+06 + 3.91000E+02 5.75392E+06 + 3.91100E+02 5.17088E+06 + 3.91200E+02 4.20268E+06 + 3.91300E+02 3.58757E+06 + 3.91400E+02 3.07900E+06 + 3.91500E+02 3.11120E+06 + 3.91600E+02 3.26460E+06 + 3.91700E+02 2.89781E+06 + 3.91800E+02 2.03720E+06 + 3.91900E+02 2.33183E+06 + 3.92000E+02 2.77911E+06 + 3.92100E+02 2.55804E+06 + 3.92200E+02 3.01621E+06 + 3.92300E+02 2.69166E+06 + 3.92400E+02 2.62015E+06 + 3.92500E+02 2.56879E+06 + 3.92600E+02 3.07796E+06 + 3.92700E+02 3.34647E+06 + 3.92800E+02 2.94449E+06 + 3.92900E+02 3.28968E+06 + 3.93000E+02 3.69436E+06 + 3.93100E+02 3.56640E+06 + 3.93200E+02 3.87571E+06 + 3.93300E+02 3.63923E+06 + 3.93400E+02 4.92410E+06 + 3.93500E+02 5.29214E+06 + 3.93600E+02 4.74387E+06 + 3.93700E+02 3.58050E+06 + 3.93800E+02 3.58891E+06 + 3.93900E+02 3.94278E+06 + 3.94000E+02 4.32284E+06 + 3.94100E+02 2.75629E+06 + 3.94200E+02 1.52592E+06 + 3.94300E+02 1.96931E+06 + 3.94400E+02 1.28710E+06 + 3.94500E+02 1.78124E+06 + 3.94600E+02 2.13509E+06 + 3.94700E+02 2.11941E+06 + 3.94800E+02 1.81654E+06 + 3.94900E+02 2.90502E+06 + 3.95000E+02 3.97108E+06 + 3.95100E+02 3.73166E+06 + 3.95200E+02 3.47361E+06 + 3.95300E+02 3.41273E+06 + 3.95400E+02 4.32295E+06 + 3.95500E+02 4.16264E+06 + 3.95600E+02 3.89763E+06 + 3.95700E+02 4.49677E+06 + 3.95800E+02 4.35524E+06 + 3.95900E+02 3.75776E+06 + 3.96000E+02 3.93651E+06 + 3.96100E+02 4.12544E+06 + 3.96200E+02 3.81787E+06 + 3.96300E+02 3.89672E+06 + 3.96400E+02 3.55860E+06 + 3.96500E+02 5.05280E+06 + 3.96600E+02 4.79379E+06 + 3.96700E+02 4.45393E+06 + 3.96800E+02 3.45591E+06 + 3.96900E+02 2.44675E+06 + 3.97000E+02 2.63701E+06 + 3.97100E+02 3.38969E+06 + 3.97200E+02 3.32368E+06 + 3.97300E+02 2.74012E+06 + 3.97400E+02 2.65319E+06 + 3.97500E+02 3.01662E+06 + 3.97600E+02 2.95795E+06 + 3.97700E+02 2.47424E+06 + 3.97800E+02 2.76588E+06 + 3.97900E+02 3.21845E+06 + 3.98000E+02 3.05576E+06 + 3.98100E+02 3.92124E+06 + 3.98200E+02 4.01126E+06 + 3.98300E+02 3.44359E+06 + 3.98400E+02 2.87436E+06 + 3.98500E+02 2.94098E+06 + 3.98600E+02 4.18415E+06 + 3.98700E+02 4.30675E+06 + 3.98800E+02 5.04262E+06 + 3.98900E+02 5.84041E+06 + 3.99000E+02 5.75959E+06 + 3.99100E+02 5.95112E+06 + 3.99200E+02 5.98685E+06 + 3.99300E+02 5.43241E+06 + 3.99400E+02 5.38241E+06 + 3.99500E+02 5.46316E+06 + 3.99600E+02 5.50514E+06 + 3.99700E+02 5.64410E+06 + 3.99800E+02 5.67993E+06 + 3.99900E+02 6.21176E+06 + 4.00000E+02 5.67289E+06 + 4.00100E+02 4.65168E+06 + 4.00200E+02 4.91483E+06 + 4.00300E+02 4.38754E+06 + 4.00400E+02 4.38394E+06 + 4.00500E+02 5.45096E+06 + 4.00600E+02 5.55163E+06 + 4.00700E+02 5.60369E+06 + 4.00800E+02 5.59458E+06 + 4.00900E+02 4.94746E+06 + 4.01000E+02 4.14246E+06 + 4.01100E+02 4.20781E+06 + 4.01200E+02 3.80675E+06 + 4.01300E+02 3.16112E+06 + 4.01400E+02 3.18776E+06 + 4.01500E+02 2.87704E+06 + 4.01600E+02 3.53347E+06 + 4.01700E+02 3.25537E+06 + 4.01800E+02 3.77163E+06 + 4.01900E+02 3.63427E+06 + 4.02000E+02 3.44710E+06 + 4.02100E+02 3.63053E+06 + 4.02200E+02 4.43320E+06 + 4.02300E+02 4.54863E+06 + 4.02400E+02 4.50851E+06 + 4.02500E+02 4.13770E+06 + 4.02600E+02 4.27390E+06 + 4.02700E+02 4.32975E+06 + 4.02800E+02 4.86724E+06 + 4.02900E+02 4.15386E+06 + 4.03000E+02 2.83428E+06 + 4.03100E+02 3.24534E+06 + 4.03200E+02 3.08588E+06 + 4.03300E+02 3.15989E+06 + 4.03400E+02 4.13768E+06 + 4.03500E+02 4.44017E+06 + 4.03600E+02 4.83295E+06 + 4.03700E+02 4.55174E+06 + 4.03800E+02 3.89175E+06 + 4.03900E+02 3.89507E+06 + 4.04000E+02 3.62987E+06 + 4.04100E+02 3.42978E+06 + 4.04200E+02 3.01334E+06 + 4.04300E+02 2.70811E+06 + 4.04400E+02 2.74345E+06 + 4.04500E+02 3.18366E+06 + 4.04600E+02 3.64904E+06 + 4.04700E+02 4.39245E+06 + 4.04800E+02 3.65339E+06 + 4.04900E+02 3.14216E+06 + 4.05000E+02 1.67580E+06 + 4.05100E+02 1.91077E+06 + 4.05200E+02 2.43438E+06 + 4.05300E+02 2.66608E+06 + 4.05400E+02 2.65141E+06 + 4.05500E+02 2.48380E+06 + 4.05600E+02 2.35442E+06 + 4.05700E+02 2.98030E+06 + 4.05800E+02 3.45862E+06 + 4.05900E+02 4.02445E+06 + 4.06000E+02 4.04919E+06 + 4.06100E+02 4.39852E+06 + 4.06200E+02 4.24639E+06 + 4.06300E+02 3.55441E+06 + 4.06400E+02 4.58256E+06 + 4.06500E+02 4.75297E+06 + 4.06600E+02 5.00550E+06 + 4.06700E+02 4.94738E+06 + 4.06800E+02 5.11306E+06 + 4.06900E+02 5.86373E+06 + 4.07000E+02 5.65326E+06 + 4.07100E+02 4.83340E+06 + 4.07200E+02 4.89320E+06 + 4.07300E+02 5.03770E+06 + 4.07400E+02 5.33474E+06 + 4.07500E+02 5.74054E+06 + 4.07600E+02 5.64272E+06 + 4.07700E+02 5.33707E+06 + 4.07800E+02 4.81131E+06 + 4.07900E+02 4.88981E+06 + 4.08000E+02 4.18454E+06 + 4.08100E+02 4.36052E+06 + 4.08200E+02 3.50446E+06 + 4.08300E+02 3.02889E+06 + 4.08400E+02 3.45661E+06 + 4.08500E+02 3.35675E+06 + 4.08600E+02 3.53393E+06 + 4.08700E+02 2.67303E+06 + 4.08800E+02 3.56082E+06 + 4.08900E+02 4.28315E+06 + 4.09000E+02 4.80087E+06 + 4.09100E+02 4.36731E+06 + 4.09200E+02 4.28736E+06 + 4.09300E+02 4.17931E+06 + 4.09400E+02 4.79624E+06 + 4.09500E+02 4.56562E+06 + 4.09600E+02 4.00506E+06 + 4.09700E+02 4.12428E+06 + 4.09800E+02 4.32332E+06 + 4.09900E+02 4.29532E+06 + 4.10000E+02 4.37255E+06 + 4.10100E+02 4.30143E+06 + 4.10200E+02 3.36434E+06 + 4.10300E+02 2.40439E+06 + 4.10400E+02 2.29318E+06 + 4.10500E+02 2.90358E+06 + 4.10600E+02 3.03976E+06 + 4.10700E+02 3.38095E+06 + 4.10800E+02 2.87877E+06 + 4.10900E+02 2.47697E+06 + 4.11000E+02 1.95094E+06 + 4.11100E+02 2.34499E+06 + 4.11200E+02 2.65781E+06 + 4.11300E+02 2.39370E+06 + 4.11400E+02 2.56268E+06 + 4.11500E+02 3.14185E+06 + 4.11600E+02 3.13942E+06 + 4.11700E+02 2.65493E+06 + 4.11800E+02 1.20075E+06 + 4.11900E+02 1.20062E+06 + 4.12000E+02 1.09556E+06 + 4.12100E+02 1.24608E+06 + 4.12200E+02 1.53156E+06 + 4.12300E+02 1.73262E+06 + 4.12400E+02 1.92473E+06 + 4.12500E+02 1.94606E+06 + 4.12600E+02 2.52255E+06 + 4.12700E+02 3.38489E+06 + 4.12800E+02 3.69697E+06 + 4.12900E+02 3.66339E+06 + 4.13000E+02 3.73619E+06 + 4.13100E+02 4.22334E+06 + 4.13200E+02 4.79744E+06 + 4.13300E+02 4.10868E+06 + 4.13400E+02 4.04357E+06 + 4.13500E+02 3.20696E+06 + 4.13600E+02 3.63660E+06 + 4.13700E+02 4.06203E+06 + 4.13800E+02 3.75117E+06 + 4.13900E+02 4.15159E+06 + 4.14000E+02 4.49274E+06 + 4.14100E+02 4.69415E+06 + 4.14200E+02 5.89243E+06 + 4.14300E+02 5.36677E+06 + 4.14400E+02 5.01989E+06 + 4.14500E+02 4.74003E+06 + 4.14600E+02 5.69852E+06 + 4.14700E+02 5.86639E+06 + 4.14800E+02 5.02044E+06 + 4.14900E+02 4.62893E+06 + 4.15000E+02 5.35949E+06 + 4.15100E+02 5.24033E+06 + 4.15200E+02 5.26022E+06 + 4.15300E+02 5.59700E+06 + 4.15400E+02 5.47895E+06 + 4.15500E+02 5.53553E+06 + 4.15600E+02 5.37669E+06 + 4.15700E+02 6.03539E+06 + 4.15800E+02 6.32110E+06 + 4.15900E+02 6.61869E+06 + 4.16000E+02 5.44063E+06 + 4.16100E+02 4.84752E+06 + 4.16200E+02 4.82349E+06 + 4.16300E+02 4.97835E+06 + 4.16400E+02 5.88518E+06 + 4.16500E+02 5.58748E+06 + 4.16600E+02 5.29712E+06 + 4.16700E+02 5.39631E+06 + 4.16800E+02 5.18495E+06 + 4.16900E+02 5.33466E+06 + 4.17000E+02 5.19902E+06 + 4.17100E+02 4.25360E+06 + 4.17200E+02 4.57231E+06 + 4.17300E+02 4.77799E+06 + 4.17400E+02 3.98599E+06 + 4.17500E+02 3.64363E+06 + 4.17600E+02 3.47566E+06 + 4.17700E+02 3.71645E+06 + 4.17800E+02 3.26253E+06 + 4.17900E+02 3.07935E+06 + 4.18000E+02 2.89405E+06 + 4.18100E+02 2.11017E+06 + 4.18200E+02 2.00538E+06 + 4.18300E+02 2.32312E+06 + 4.18400E+02 1.71811E+06 + 4.18500E+02 2.00560E+06 + 4.18600E+02 2.72263E+06 + 4.18700E+02 2.77779E+06 + 4.18800E+02 3.10515E+06 + 4.18900E+02 3.15942E+06 + 4.19000E+02 2.19401E+06 + 4.19100E+02 2.28662E+06 + 4.19200E+02 2.40004E+06 + 4.19300E+02 2.64023E+06 + 4.19400E+02 3.01370E+06 + 4.19500E+02 3.58712E+06 + 4.19600E+02 4.24272E+06 + 4.19700E+02 5.55297E+06 + 4.19800E+02 4.99005E+06 + 4.19900E+02 4.70007E+06 + 4.20000E+02 4.59348E+06 + 4.20100E+02 4.25750E+06 + 4.20200E+02 4.49046E+06 + 4.20300E+02 4.98464E+06 + 4.20400E+02 4.64981E+06 + 4.20500E+02 3.41950E+06 + 4.20600E+02 3.04454E+06 + 4.20700E+02 3.45145E+06 + 4.20800E+02 3.93618E+06 + 4.20900E+02 4.22727E+06 + 4.21000E+02 3.71683E+06 + 4.21100E+02 3.67807E+06 + 4.21200E+02 3.28591E+06 + 4.21300E+02 2.96285E+06 + 4.21400E+02 2.78615E+06 + 4.21500E+02 2.47938E+06 + 4.21600E+02 2.99445E+06 + 4.21700E+02 3.45264E+06 + 4.21800E+02 3.08261E+06 + 4.21900E+02 2.99180E+06 + 4.22000E+02 2.48278E+06 + 4.22100E+02 1.88817E+06 + 4.22200E+02 2.13568E+06 + 4.22300E+02 3.09432E+06 + 4.22400E+02 2.94142E+06 + 4.22500E+02 3.18193E+06 + 4.22600E+02 3.74634E+06 + 4.22700E+02 3.13114E+06 + 4.22800E+02 3.20903E+06 + 4.22900E+02 4.17026E+06 + 4.23000E+02 4.27876E+06 + 4.23100E+02 5.08336E+06 + 4.23200E+02 5.51446E+06 + 4.23300E+02 5.46764E+06 + 4.23400E+02 5.00173E+06 + 4.23500E+02 3.97380E+06 + 4.23600E+02 4.48731E+06 + 4.23700E+02 4.69460E+06 + 4.23800E+02 5.71146E+06 + 4.23900E+02 5.48615E+06 + 4.24000E+02 4.91404E+06 + 4.24100E+02 4.92258E+06 + 4.24200E+02 4.40529E+06 + 4.24300E+02 4.43054E+06 + 4.24400E+02 4.05509E+06 + 4.24500E+02 3.80709E+06 + 4.24600E+02 4.66172E+06 + 4.24700E+02 5.17835E+06 + 4.24800E+02 5.22205E+06 + 4.24900E+02 5.62550E+06 + 4.25000E+02 6.28722E+06 + 4.25100E+02 5.53771E+06 + 4.25200E+02 5.08064E+06 + 4.25300E+02 5.74861E+06 + 4.25400E+02 5.74455E+06 + 4.25500E+02 5.64373E+06 + 4.25600E+02 5.62771E+06 + 4.25700E+02 5.53449E+06 + 4.25800E+02 4.82081E+06 + 4.25900E+02 4.43391E+06 + 4.26000E+02 3.62047E+06 + 4.26100E+02 4.04263E+06 + 4.26200E+02 5.13890E+06 + 4.26300E+02 4.97913E+06 + 4.26400E+02 4.44007E+06 + 4.26500E+02 4.25947E+06 + 4.26600E+02 4.10630E+06 + 4.26700E+02 4.34733E+06 + 4.26800E+02 3.06668E+06 + 4.26900E+02 2.78935E+06 + 4.27000E+02 1.56993E+06 + 4.27100E+02 1.62243E+06 + 4.27200E+02 3.41460E+06 + 4.27300E+02 3.41738E+06 + 4.27400E+02 3.73758E+06 + 4.27500E+02 4.63860E+06 + 4.27600E+02 4.70685E+06 + 4.27700E+02 4.16291E+06 + 4.27800E+02 3.40709E+06 + 4.27900E+02 3.88938E+06 + 4.28000E+02 3.64316E+06 + 4.28100E+02 3.68563E+06 + 4.28200E+02 4.03882E+06 + 4.28300E+02 4.41360E+06 + 4.28400E+02 4.11906E+06 + 4.28500E+02 4.14081E+06 + 4.28600E+02 4.10241E+06 + 4.28700E+02 4.99931E+06 + 4.28800E+02 4.96152E+06 + 4.28900E+02 4.59538E+06 + 4.29000E+02 3.87267E+06 + 4.29100E+02 4.31860E+06 + 4.29200E+02 4.70004E+06 + 4.29300E+02 4.10575E+06 + 4.29400E+02 4.57795E+06 + 4.29500E+02 4.47698E+06 + 4.29600E+02 4.99010E+06 + 4.29700E+02 5.14116E+06 + 4.29800E+02 5.09298E+06 + 4.29900E+02 4.31289E+06 + 4.30000E+02 4.76871E+06 + 4.30100E+02 4.83392E+06 + 4.30200E+02 5.89177E+06 + 4.30300E+02 5.91646E+06 + 4.30400E+02 5.84014E+06 + 4.30500E+02 5.43251E+06 + 4.30600E+02 4.33322E+06 + 4.30700E+02 4.05416E+06 + 4.30800E+02 3.85061E+06 + 4.30900E+02 3.82413E+06 + 4.31000E+02 4.08394E+06 + 4.31100E+02 3.35569E+06 + 4.31200E+02 4.01531E+06 + 4.31300E+02 4.19944E+06 + 4.31400E+02 4.16759E+06 + 4.31500E+02 5.32979E+06 + 4.31600E+02 5.53438E+06 + 4.31700E+02 6.69115E+06 + 4.31800E+02 7.31302E+06 + 4.31900E+02 6.72522E+06 + 4.32000E+02 6.79570E+06 + 4.32100E+02 6.69005E+06 + 4.32200E+02 7.27062E+06 + 4.32300E+02 6.76657E+06 + 4.32400E+02 7.14242E+06 + 4.32500E+02 6.36250E+06 + 4.32600E+02 5.38928E+06 + 4.32700E+02 5.02527E+06 + 4.32800E+02 5.60146E+06 + 4.32900E+02 5.68760E+06 + 4.33000E+02 5.53688E+06 + 4.33100E+02 5.85369E+06 + 4.33200E+02 4.97879E+06 + 4.33300E+02 4.40962E+06 + 4.33400E+02 4.48401E+06 + 4.33500E+02 4.69051E+06 + 4.33600E+02 4.43348E+06 + 4.33700E+02 4.02108E+06 + 4.33800E+02 4.24091E+06 + 4.33900E+02 4.71175E+06 + 4.34000E+02 4.69857E+06 + 4.34100E+02 4.84365E+06 + 4.34200E+02 4.74894E+06 + 4.34300E+02 4.88480E+06 + 4.34400E+02 4.64415E+06 + 4.34500E+02 4.93909E+06 + 4.34600E+02 4.17940E+06 + 4.34700E+02 3.28774E+06 + 4.34800E+02 3.78518E+06 + 4.34900E+02 4.18940E+06 + 4.35000E+02 3.95236E+06 + 4.35100E+02 4.31010E+06 + 4.35200E+02 4.46794E+06 + 4.35300E+02 4.12310E+06 + 4.35400E+02 4.23981E+06 + 4.35500E+02 4.95390E+06 + 4.35600E+02 4.94276E+06 + 4.35700E+02 4.63236E+06 + 4.35800E+02 5.13277E+06 + 4.35900E+02 4.99724E+06 + 4.36000E+02 3.89649E+06 + 4.36100E+02 3.93324E+06 + 4.36200E+02 3.43907E+06 + 4.36300E+02 4.25266E+06 + 4.36400E+02 4.92718E+06 + 4.36500E+02 5.59467E+06 + 4.36600E+02 5.83293E+06 + 4.36700E+02 4.97976E+06 + 4.36800E+02 4.30062E+06 + 4.36900E+02 3.55691E+06 + 4.37000E+02 2.79657E+06 + 4.37100E+02 3.35612E+06 + 4.37200E+02 4.38708E+06 + 4.37300E+02 3.93131E+06 + 4.37400E+02 4.32697E+06 + 4.37500E+02 4.88075E+06 + 4.37600E+02 4.70263E+06 + 4.37700E+02 5.27347E+06 + 4.37800E+02 5.37094E+06 + 4.37900E+02 5.12723E+06 + 4.38000E+02 5.01184E+06 + 4.38100E+02 5.01667E+06 + 4.38200E+02 4.96606E+06 + 4.38300E+02 4.65479E+06 + 4.38400E+02 3.44250E+06 + 4.38500E+02 2.94766E+06 + 4.38600E+02 3.17279E+06 + 4.38700E+02 2.71664E+06 + 4.38800E+02 2.65484E+06 + 4.38900E+02 2.60548E+06 + 4.39000E+02 3.03273E+06 + 4.39100E+02 3.55025E+06 + 4.39200E+02 3.06337E+06 + 4.39300E+02 2.84641E+06 + 4.39400E+02 3.24139E+06 + 4.39500E+02 3.18147E+06 + 4.39600E+02 2.75318E+06 + 4.39700E+02 3.09162E+06 + 4.39800E+02 4.48111E+06 + 4.39900E+02 4.97157E+06 + 4.40000E+02 4.77128E+06 + 4.40100E+02 4.63567E+06 + 4.40200E+02 4.72060E+06 + 4.40300E+02 5.28658E+06 + 4.40400E+02 4.55491E+06 + 4.40500E+02 4.57597E+06 + 4.40600E+02 4.46217E+06 + 4.40700E+02 4.08927E+06 + 4.40800E+02 4.30526E+06 + 4.40900E+02 3.80136E+06 + 4.41000E+02 4.32829E+06 + 4.41100E+02 3.78913E+06 + 4.41200E+02 3.59636E+06 + 4.41300E+02 3.95983E+06 + 4.41400E+02 3.29200E+06 + 4.41500E+02 3.11380E+06 + 4.41600E+02 3.16203E+06 + 4.41700E+02 2.86902E+06 + 4.41800E+02 3.08379E+06 + 4.41900E+02 2.73964E+06 + 4.42000E+02 2.96227E+06 + 4.42100E+02 3.23157E+06 + 4.42200E+02 3.21299E+06 + 4.42300E+02 2.06362E+06 + 4.42400E+02 1.50038E+06 + 4.42500E+02 1.33513E+06 + 4.42600E+02 1.90637E+06 + 4.42700E+02 2.82384E+06 + 4.42800E+02 3.48949E+06 + 4.42900E+02 3.97660E+06 + 4.43000E+02 4.19732E+06 + 4.43100E+02 4.59448E+06 + 4.43200E+02 5.57736E+06 + 4.43300E+02 5.68204E+06 + 4.43400E+02 6.04028E+06 + 4.43500E+02 5.48700E+06 + 4.43600E+02 5.89034E+06 + 4.43700E+02 5.98815E+06 + 4.43800E+02 4.49792E+06 + 4.43900E+02 5.06004E+06 + 4.44000E+02 4.77456E+06 + 4.44100E+02 4.77786E+06 + 4.44200E+02 4.92922E+06 + 4.44300E+02 4.47592E+06 + 4.44400E+02 4.22760E+06 + 4.44500E+02 4.34095E+06 + 4.44600E+02 4.47996E+06 + 4.44700E+02 4.15808E+06 + 4.44800E+02 3.59823E+06 + 4.44900E+02 3.80096E+06 + 4.45000E+02 3.88604E+06 + 4.45100E+02 4.12946E+06 + 4.45200E+02 4.09470E+06 + 4.45300E+02 3.30867E+06 + 4.45400E+02 2.88276E+06 + 4.45500E+02 3.40148E+06 + 4.45600E+02 4.03382E+06 + 4.45700E+02 4.34850E+06 + 4.45800E+02 4.66121E+06 + 4.45900E+02 4.70181E+06 + 4.46000E+02 5.41324E+06 + 4.46100E+02 5.26801E+06 + 4.46200E+02 5.24595E+06 + 4.46300E+02 4.64374E+06 + 4.46400E+02 5.05987E+06 + 4.46500E+02 4.01963E+06 + 4.46600E+02 4.60402E+06 + 4.46700E+02 4.82075E+06 + 4.46800E+02 3.86087E+06 + 4.46900E+02 4.14793E+06 + 4.47000E+02 4.39453E+06 + 4.47100E+02 4.45262E+06 + 4.47200E+02 4.19614E+06 + 4.47300E+02 4.35439E+06 + 4.47400E+02 3.93321E+06 + 4.47500E+02 3.93674E+06 + 4.47600E+02 3.83107E+06 + 4.47700E+02 2.85039E+06 + 4.47800E+02 2.81777E+06 + 4.47900E+02 2.57426E+06 + 4.48000E+02 2.64080E+06 + 4.48100E+02 2.34901E+06 + 4.48200E+02 2.53351E+06 + 4.48300E+02 2.25676E+06 + 4.48400E+02 1.62485E+06 + 4.48500E+02 1.66557E+06 + 4.48600E+02 1.66599E+06 + 4.48700E+02 1.87466E+06 + 4.48800E+02 2.95741E+06 + 4.48900E+02 2.98134E+06 + 4.49000E+02 3.54783E+06 + 4.49100E+02 3.91706E+06 + 4.49200E+02 4.24178E+06 + 4.49300E+02 3.65338E+06 + 4.49400E+02 4.01830E+06 + 4.49500E+02 5.14864E+06 + 4.49600E+02 4.40348E+06 + 4.49700E+02 4.44323E+06 + 4.49800E+02 4.88187E+06 + 4.49900E+02 4.64549E+06 + 4.50000E+02 4.28680E+06 + 4.50100E+02 4.15891E+06 + 4.50200E+02 3.71293E+06 + 4.50300E+02 4.17200E+06 + 4.50400E+02 4.82570E+06 + 4.50500E+02 5.14703E+06 + 4.50600E+02 4.87699E+06 + 4.50700E+02 4.75118E+06 + 4.50800E+02 5.56294E+06 + 4.50900E+02 6.15052E+06 + 4.51000E+02 6.30588E+06 + 4.51100E+02 7.01990E+06 + 4.51200E+02 6.40226E+06 + 4.51300E+02 6.48635E+06 + 4.51400E+02 5.97671E+06 + 4.51500E+02 4.91483E+06 + 4.51600E+02 4.61746E+06 + 4.51700E+02 4.19188E+06 + 4.51800E+02 3.29616E+06 + 4.51900E+02 3.22929E+06 + 4.52000E+02 3.33820E+06 + 4.52100E+02 3.75699E+06 + 4.52200E+02 4.10655E+06 + 4.52300E+02 4.46778E+06 + 4.52400E+02 4.73214E+06 + 4.52500E+02 4.94566E+06 + 4.52600E+02 4.50794E+06 + 4.52700E+02 4.71803E+06 + 4.52800E+02 4.43087E+06 + 4.52900E+02 4.10105E+06 + 4.53000E+02 4.46650E+06 + 4.53100E+02 4.73502E+06 + 4.53200E+02 4.46678E+06 + 4.53300E+02 4.42725E+06 + 4.53400E+02 4.82026E+06 + 4.53500E+02 5.96521E+06 + 4.53600E+02 6.20970E+06 + 4.53700E+02 6.55970E+06 + 4.53800E+02 6.65163E+06 + 4.53900E+02 6.51753E+06 + 4.54000E+02 6.18494E+06 + 4.54100E+02 5.38303E+06 + 4.54200E+02 5.89466E+06 + 4.54300E+02 6.05388E+06 + 4.54400E+02 6.31301E+06 + 4.54500E+02 6.28672E+06 + 4.54600E+02 5.03506E+06 + 4.54700E+02 4.75663E+06 + 4.54800E+02 3.77399E+06 + 4.54900E+02 3.08034E+06 + 4.55000E+02 3.01238E+06 + 4.55100E+02 3.73626E+06 + 4.55200E+02 3.09250E+06 + 4.55300E+02 3.46754E+06 + 4.55400E+02 4.27601E+06 + 4.55500E+02 4.54252E+06 + 4.55600E+02 4.47568E+06 + 4.55700E+02 4.73293E+06 + 4.55800E+02 4.82359E+06 + 4.55900E+02 4.73424E+06 + 4.56000E+02 5.26366E+06 + 4.56100E+02 6.11141E+06 + 4.56200E+02 5.00690E+06 + 4.56300E+02 5.06334E+06 + 4.56400E+02 4.93040E+06 + 4.56500E+02 5.22332E+06 + 4.56600E+02 5.69311E+06 + 4.56700E+02 5.00811E+06 + 4.56800E+02 5.43402E+06 + 4.56900E+02 4.39510E+06 + 4.57000E+02 4.48724E+06 + 4.57100E+02 4.34069E+06 + 4.57200E+02 4.57830E+06 + 4.57300E+02 4.11005E+06 + 4.57400E+02 4.17449E+06 + 4.57500E+02 4.15010E+06 + 4.57600E+02 4.36768E+06 + 4.57700E+02 4.85040E+06 + 4.57800E+02 4.99673E+06 + 4.57900E+02 5.33383E+06 + 4.58000E+02 4.42727E+06 + 4.58100E+02 4.10474E+06 + 4.58200E+02 4.25809E+06 + 4.58300E+02 3.91929E+06 + 4.58400E+02 3.48301E+06 + 4.58500E+02 4.35468E+06 + 4.58600E+02 4.32200E+06 + 4.58700E+02 4.17346E+06 + 4.58800E+02 3.62825E+06 + 4.58900E+02 3.69214E+06 + 4.59000E+02 3.88870E+06 + 4.59100E+02 3.30627E+06 + 4.59200E+02 3.55172E+06 + 4.59300E+02 3.29530E+06 + 4.59400E+02 3.83601E+06 + 4.59500E+02 4.14026E+06 + 4.59600E+02 2.83800E+06 + 4.59700E+02 2.43504E+06 + 4.59800E+02 2.86923E+06 + 4.59900E+02 2.94682E+06 + 4.60000E+02 3.16361E+06 + 4.60100E+02 3.17915E+06 + 4.60200E+02 3.67167E+06 + 4.60300E+02 3.81660E+06 + 4.60400E+02 3.89096E+06 + 4.60500E+02 3.60172E+06 + 4.60600E+02 3.26236E+06 + 4.60700E+02 3.65851E+06 + 4.60800E+02 4.01458E+06 + 4.60900E+02 4.48672E+06 + 4.61000E+02 5.72123E+06 + 4.61100E+02 6.16809E+06 + 4.61200E+02 5.93166E+06 + 4.61300E+02 5.50017E+06 + 4.61400E+02 5.59294E+06 + 4.61500E+02 6.13933E+06 + 4.61600E+02 5.75367E+06 + 4.61700E+02 5.45809E+06 + 4.61800E+02 5.04558E+06 + 4.61900E+02 4.07365E+06 + 4.62000E+02 3.67905E+06 + 4.62100E+02 4.51732E+06 + 4.62200E+02 4.81873E+06 + 4.62300E+02 4.44405E+06 + 4.62400E+02 5.32859E+06 + 4.62500E+02 5.26197E+06 + 4.62600E+02 5.44788E+06 + 4.62700E+02 5.93172E+06 + 4.62800E+02 6.00159E+06 + 4.62900E+02 6.45847E+06 + 4.63000E+02 6.24684E+06 + 4.63100E+02 6.11868E+06 + 4.63200E+02 5.90861E+06 + 4.63300E+02 6.41273E+06 + 4.63400E+02 6.55883E+06 + 4.63500E+02 6.42019E+06 + 4.63600E+02 6.44034E+06 + 4.63700E+02 6.64165E+06 + 4.63800E+02 6.35882E+06 + 4.63900E+02 5.86255E+06 + 4.64000E+02 5.69151E+06 + 4.64100E+02 6.06429E+06 + 4.64200E+02 5.78846E+06 + 4.64300E+02 6.09206E+06 + 4.64400E+02 6.26169E+06 + 4.64500E+02 5.85611E+06 + 4.64600E+02 6.18199E+06 + 4.64700E+02 5.69279E+06 + 4.64800E+02 4.70184E+06 + 4.64900E+02 5.12391E+06 + 4.65000E+02 6.12582E+06 + 4.65100E+02 5.63907E+06 + 4.65200E+02 5.36574E+06 + 4.65300E+02 5.28435E+06 + 4.65400E+02 5.08836E+06 + 4.65500E+02 4.47945E+06 + 4.65600E+02 4.34201E+06 + 4.65700E+02 5.36158E+06 + 4.65800E+02 5.42304E+06 + 4.65900E+02 5.65306E+06 + 4.66000E+02 5.76072E+06 + 4.66100E+02 4.70582E+06 + 4.66200E+02 4.51942E+06 + 4.66300E+02 4.80644E+06 + 4.66400E+02 5.09445E+06 + 4.66500E+02 4.65052E+06 + 4.66600E+02 4.19184E+06 + 4.66700E+02 4.03949E+06 + 4.66800E+02 4.44995E+06 + 4.66900E+02 3.38331E+06 + 4.67000E+02 3.33262E+06 + 4.67100E+02 2.86341E+06 + 4.67200E+02 3.17759E+06 + 4.67300E+02 3.44738E+06 + 4.67400E+02 3.80504E+06 + 4.67500E+02 4.08329E+06 + 4.67600E+02 4.17358E+06 + 4.67700E+02 3.93830E+06 + 4.67800E+02 4.46715E+06 + 4.67900E+02 4.73485E+06 + 4.68000E+02 4.69281E+06 + 4.68100E+02 5.75622E+06 + 4.68200E+02 6.13584E+06 + 4.68300E+02 6.68079E+06 + 4.68400E+02 6.53660E+06 + 4.68500E+02 5.64834E+06 + 4.68600E+02 6.49702E+06 + 4.68700E+02 5.55570E+06 + 4.68800E+02 5.78670E+06 + 4.68900E+02 5.80549E+06 + 4.69000E+02 6.38970E+06 + 4.69100E+02 6.53198E+06 + 4.69200E+02 5.54465E+06 + 4.69300E+02 4.35360E+06 + 4.69400E+02 4.43707E+06 + 4.69500E+02 5.24186E+06 + 4.69600E+02 5.12746E+06 + 4.69700E+02 4.75503E+06 + 4.69800E+02 5.34905E+06 + 4.69900E+02 5.76452E+06 + 4.70000E+02 5.49590E+06 + 4.70100E+02 5.61689E+06 + 4.70200E+02 5.29956E+06 + 4.70300E+02 4.31706E+06 + 4.70400E+02 3.94019E+06 + 4.70500E+02 4.48612E+06 + 4.70600E+02 5.04048E+06 + 4.70700E+02 4.77046E+06 + 4.70800E+02 4.32780E+06 + 4.70900E+02 4.59738E+06 + 4.71000E+02 4.31304E+06 + 4.71100E+02 4.16808E+06 + 4.71200E+02 4.07005E+06 + 4.71300E+02 3.63191E+06 + 4.71400E+02 3.69318E+06 + 4.71500E+02 3.34642E+06 + 4.71600E+02 3.83923E+06 + 4.71700E+02 3.57603E+06 + 4.71800E+02 3.56991E+06 + 4.71900E+02 4.46350E+06 + 4.72000E+02 4.32257E+06 + 4.72100E+02 3.14509E+06 + 4.72200E+02 2.75142E+06 + 4.72300E+02 3.10464E+06 + 4.72400E+02 3.08946E+06 + 4.72500E+02 3.94020E+06 + 4.72600E+02 4.71183E+06 + 4.72700E+02 3.78974E+06 + 4.72800E+02 3.28505E+06 + 4.72900E+02 3.27547E+06 + 4.73000E+02 3.48429E+06 + 4.73100E+02 3.38943E+06 + 4.73200E+02 3.86750E+06 + 4.73300E+02 3.51928E+06 + 4.73400E+02 3.96266E+06 + 4.73500E+02 4.24165E+06 + 4.73600E+02 4.48386E+06 + 4.73700E+02 4.18077E+06 + 4.73800E+02 4.24532E+06 + 4.73900E+02 4.09581E+06 + 4.74000E+02 4.15990E+06 + 4.74100E+02 3.44829E+06 + 4.74200E+02 3.36097E+06 + 4.74300E+02 3.39721E+06 + 4.74400E+02 3.61387E+06 + 4.74500E+02 2.95298E+06 + 4.74600E+02 3.41318E+06 + 4.74700E+02 3.38896E+06 + 4.74800E+02 3.43387E+06 + 4.74900E+02 3.39988E+06 + 4.75000E+02 3.54006E+06 + 4.75100E+02 3.95575E+06 + 4.75200E+02 4.22115E+06 + 4.75300E+02 4.93957E+06 + 4.75400E+02 4.24273E+06 + 4.75500E+02 4.46715E+06 + 4.75600E+02 4.57147E+06 + 4.75700E+02 3.55188E+06 + 4.75800E+02 3.33302E+06 + 4.75900E+02 3.65615E+06 + 4.76000E+02 4.04020E+06 + 4.76100E+02 3.27832E+06 + 4.76200E+02 2.92185E+06 + 4.76300E+02 2.95043E+06 + 4.76400E+02 3.49270E+06 + 4.76500E+02 4.09273E+06 + 4.76600E+02 5.04938E+06 + 4.76700E+02 5.14621E+06 + 4.76800E+02 5.33204E+06 + 4.76900E+02 5.49969E+06 + 4.77000E+02 5.36155E+06 + 4.77100E+02 6.13994E+06 + 4.77200E+02 6.62762E+06 + 4.77300E+02 5.90562E+06 + 4.77400E+02 6.18417E+06 + 4.77500E+02 5.82486E+06 + 4.77600E+02 5.69989E+06 + 4.77700E+02 5.30490E+06 + 4.77800E+02 4.72865E+06 + 4.77900E+02 4.45507E+06 + 4.78000E+02 5.02243E+06 + 4.78100E+02 3.91414E+06 + 4.78200E+02 2.92256E+06 + 4.78300E+02 3.02785E+06 + 4.78400E+02 3.61580E+06 + 4.78500E+02 3.61577E+06 + 4.78600E+02 3.60432E+06 + 4.78700E+02 2.75980E+06 + 4.78800E+02 2.20452E+06 + 4.78900E+02 2.62745E+06 + 4.79000E+02 2.84317E+06 + 4.79100E+02 3.24739E+06 + 4.79200E+02 4.23381E+06 + 4.79300E+02 4.74939E+06 + 4.79400E+02 4.75568E+06 + 4.79500E+02 5.48381E+06 + 4.79600E+02 5.91059E+06 + 4.79700E+02 5.61038E+06 + 4.79800E+02 6.10994E+06 + 4.79900E+02 6.46439E+06 + 4.80000E+02 5.64044E+06 + 4.80100E+02 5.21040E+06 + 4.80200E+02 4.93351E+06 + 4.80300E+02 5.57334E+06 + 4.80400E+02 5.49958E+06 + 4.80500E+02 5.75893E+06 + 4.80600E+02 6.18829E+06 + 4.80700E+02 6.63523E+06 + 4.80800E+02 6.56624E+06 + 4.80900E+02 6.45268E+06 + 4.81000E+02 6.45078E+06 + 4.81100E+02 5.14971E+06 + 4.81200E+02 5.05491E+06 + 4.81300E+02 4.91689E+06 + 4.81400E+02 4.28689E+06 + 4.81500E+02 3.88109E+06 + 4.81600E+02 3.36215E+06 + 4.81700E+02 4.15108E+06 + 4.81800E+02 4.54868E+06 + 4.81900E+02 4.49292E+06 + 4.82000E+02 3.80411E+06 + 4.82100E+02 3.10074E+06 + 4.82200E+02 4.06859E+06 + 4.82300E+02 3.94119E+06 + 4.82400E+02 2.71518E+06 + 4.82500E+02 2.74499E+06 + 4.82600E+02 2.81985E+06 + 4.82700E+02 2.61880E+06 + 4.82800E+02 2.82126E+06 + 4.82900E+02 3.41152E+06 + 4.83000E+02 3.27088E+06 + 4.83100E+02 3.30459E+06 + 4.83200E+02 3.96211E+06 + 4.83300E+02 4.00766E+06 + 4.83400E+02 3.92721E+06 + 4.83500E+02 4.37453E+06 + 4.83600E+02 4.46971E+06 + 4.83700E+02 4.52698E+06 + 4.83800E+02 3.79263E+06 + 4.83900E+02 4.56894E+06 + 4.84000E+02 5.00323E+06 + 4.84100E+02 4.65598E+06 + 4.84200E+02 5.15698E+06 + 4.84300E+02 4.97052E+06 + 4.84400E+02 4.44616E+06 + 4.84500E+02 4.26320E+06 + 4.84600E+02 4.07878E+06 + 4.84700E+02 3.65480E+06 + 4.84800E+02 3.92362E+06 + 4.84900E+02 5.27551E+06 + 4.85000E+02 5.21631E+06 + 4.85100E+02 6.10549E+06 + 4.85200E+02 5.78340E+06 + 4.85300E+02 5.21110E+06 + 4.85400E+02 5.44930E+06 + 4.85500E+02 6.53631E+06 + 4.85600E+02 6.30516E+06 + 4.85700E+02 6.17348E+06 + 4.85800E+02 5.77079E+06 + 4.85900E+02 6.07317E+06 + 4.86000E+02 5.26810E+06 + 4.86100E+02 4.96942E+06 + 4.86200E+02 4.64776E+06 + 4.86300E+02 4.37230E+06 + 4.86400E+02 3.79465E+06 + 4.86500E+02 3.68072E+06 + 4.86600E+02 3.98390E+06 + 4.86700E+02 3.27911E+06 + 4.86800E+02 3.90365E+06 + 4.86900E+02 4.02579E+06 + 4.87000E+02 3.72522E+06 + 4.87100E+02 3.48513E+06 + 4.87200E+02 3.87429E+06 + 4.87300E+02 3.26329E+06 + 4.87400E+02 2.60597E+06 + 4.87500E+02 2.40262E+06 + 4.87600E+02 1.78148E+06 + 4.87700E+02 2.09809E+06 + 4.87800E+02 2.03833E+06 + 4.87900E+02 2.31161E+06 + 4.88000E+02 2.65912E+06 + 4.88100E+02 2.52068E+06 + 4.88200E+02 1.83175E+06 + 4.88300E+02 1.93165E+06 + 4.88400E+02 2.97357E+06 + 4.88500E+02 3.60298E+06 + 4.88600E+02 3.78911E+06 + 4.88700E+02 3.36420E+06 + 4.88800E+02 2.35359E+06 + 4.88900E+02 2.57495E+06 + 4.89000E+02 2.47418E+06 + 4.89100E+02 2.93697E+06 + 4.89200E+02 3.83381E+06 + 4.89300E+02 3.47884E+06 + 4.89400E+02 3.26984E+06 + 4.89500E+02 3.41874E+06 + 4.89600E+02 3.32769E+06 + 4.89700E+02 3.43757E+06 + 4.89800E+02 3.89211E+06 + 4.89900E+02 4.08551E+06 + 4.90000E+02 4.05698E+06 + 4.90100E+02 4.41041E+06 + 4.90200E+02 4.02665E+06 + 4.90300E+02 3.91302E+06 + 4.90400E+02 2.70333E+06 + 4.90500E+02 1.83123E+06 + 4.90600E+02 1.84493E+06 + 4.90700E+02 2.01299E+06 + 4.90800E+02 1.56657E+06 + 4.90900E+02 1.81474E+06 + 4.91000E+02 2.60001E+06 + 4.91100E+02 3.26533E+06 + 4.91200E+02 2.57290E+06 + 4.91300E+02 2.67757E+06 + 4.91400E+02 3.18174E+06 + 4.91500E+02 3.77251E+06 + 4.91600E+02 3.63909E+06 + 4.91700E+02 4.76184E+06 + 4.91800E+02 4.94055E+06 + 4.91900E+02 5.14127E+06 + 4.92000E+02 4.69048E+06 + 4.92100E+02 5.55440E+06 + 4.92200E+02 5.52009E+06 + 4.92300E+02 5.24890E+06 + 4.92400E+02 5.65519E+06 + 4.92500E+02 5.43799E+06 + 4.92600E+02 5.15588E+06 + 4.92700E+02 5.17066E+06 + 4.92800E+02 5.29641E+06 + 4.92900E+02 5.22017E+06 + 4.93000E+02 4.74313E+06 + 4.93100E+02 4.49363E+06 + 4.93200E+02 4.70773E+06 + 4.93300E+02 3.26182E+06 + 4.93400E+02 3.17168E+06 + 4.93500E+02 3.26459E+06 + 4.93600E+02 3.46192E+06 + 4.93700E+02 2.89112E+06 + 4.93800E+02 1.89190E+06 + 4.93900E+02 2.59716E+06 + 4.94000E+02 3.59940E+06 + 4.94100E+02 3.37292E+06 + 4.94200E+02 3.38313E+06 + 4.94300E+02 2.67983E+06 + 4.94400E+02 2.86431E+06 + 4.94500E+02 3.59483E+06 + 4.94600E+02 4.25887E+06 + 4.94700E+02 4.22145E+06 + 4.94800E+02 4.28353E+06 + 4.94900E+02 3.83286E+06 + 4.95000E+02 4.10008E+06 + 4.95100E+02 4.17128E+06 + 4.95200E+02 4.23431E+06 + 4.95300E+02 4.85662E+06 + 4.95400E+02 3.71213E+06 + 4.95500E+02 3.91093E+06 + 4.95600E+02 4.21103E+06 + 4.95700E+02 4.56434E+06 + 4.95800E+02 5.16170E+06 + 4.95900E+02 5.40017E+06 + 4.96000E+02 4.88452E+06 + 4.96100E+02 4.97901E+06 + 4.96200E+02 5.17658E+06 + 4.96300E+02 4.81416E+06 + 4.96400E+02 5.15412E+06 + 4.96500E+02 4.86470E+06 + 4.96600E+02 4.68784E+06 + 4.96700E+02 4.12586E+06 + 4.96800E+02 4.23800E+06 + 4.96900E+02 4.66121E+06 + 4.97000E+02 4.23490E+06 + 4.97100E+02 4.08535E+06 + 4.97200E+02 4.19211E+06 + 4.97300E+02 3.91651E+06 + 4.97400E+02 3.80880E+06 + 4.97500E+02 4.17794E+06 + 4.97600E+02 4.62767E+06 + 4.97700E+02 4.26091E+06 + 4.97800E+02 4.34559E+06 + 4.97900E+02 4.61112E+06 + 4.98000E+02 4.83656E+06 + 4.98100E+02 4.56567E+06 + 4.98200E+02 4.86713E+06 + 4.98300E+02 3.56506E+06 + 4.98400E+02 2.63358E+06 + 4.98500E+02 3.24886E+06 + 4.98600E+02 3.44683E+06 + 4.98700E+02 3.69917E+06 + 4.98800E+02 4.30217E+06 + 4.98900E+02 4.51042E+06 + 4.99000E+02 4.61597E+06 + 4.99100E+02 5.18398E+06 + 4.99200E+02 4.72780E+06 + 4.99300E+02 5.09123E+06 + 4.99400E+02 4.36934E+06 + 4.99500E+02 3.13858E+06 + 4.99600E+02 2.88409E+06 + 4.99700E+02 2.25936E+06 + 4.99800E+02 2.10985E+06 + 4.99900E+02 2.05236E+06 + 5.00000E+02 1.85460E+06 + 5.00100E+02 2.55874E+06 + 5.00200E+02 2.95866E+06 + 5.00300E+02 2.50149E+06 + 5.00400E+02 1.80349E+06 + 5.00500E+02 1.13238E+06 + 5.00600E+02 9.66210E+05 + 5.00700E+02 5.70580E+05 + 5.00800E+02 2.67362E+05 + 5.00900E+02 1.63204E+05 + 5.01000E+02 1.92926E+06 + 5.01100E+02 2.91097E+06 + 5.01200E+02 3.13750E+06 + 5.01300E+02 3.53698E+06 + 5.01400E+02 4.25816E+06 + 5.01500E+02 5.20194E+06 + 5.01600E+02 5.52345E+06 + 5.01700E+02 5.07664E+06 + 5.01800E+02 4.01401E+06 + 5.01900E+02 3.33795E+06 + 5.02000E+02 3.54732E+06 + 5.02100E+02 3.90710E+06 + 5.02200E+02 3.38525E+06 + 5.02300E+02 3.52396E+06 + 5.02400E+02 3.67034E+06 + 5.02500E+02 3.83842E+06 + 5.02600E+02 4.39845E+06 + 5.02700E+02 4.82748E+06 + 5.02800E+02 5.65265E+06 + 5.02900E+02 5.74008E+06 + 5.03000E+02 5.27744E+06 + 5.03100E+02 4.75677E+06 + 5.03200E+02 5.71643E+06 + 5.03300E+02 5.43175E+06 + 5.03400E+02 5.18677E+06 + 5.03500E+02 5.31980E+06 + 5.03600E+02 6.14600E+06 + 5.03700E+02 7.24530E+06 + 5.03800E+02 6.70565E+06 + 5.03900E+02 6.48253E+06 + 5.04000E+02 6.75867E+06 + 5.04100E+02 6.35642E+06 + 5.04200E+02 6.09513E+06 + 5.04300E+02 5.85299E+06 + 5.04400E+02 5.86540E+06 + 5.04500E+02 6.41653E+06 + 5.04600E+02 6.08776E+06 + 5.04700E+02 6.19602E+06 + 5.04800E+02 6.50004E+06 + 5.04900E+02 5.74358E+06 + 5.05000E+02 6.11485E+06 + 5.05100E+02 5.97364E+06 + 5.05200E+02 5.82819E+06 + 5.05300E+02 5.65176E+06 + 5.05400E+02 5.33388E+06 + 5.05500E+02 5.58795E+06 + 5.05600E+02 5.61134E+06 + 5.05700E+02 5.75271E+06 + 5.05800E+02 6.67240E+06 + 5.05900E+02 6.18606E+06 + 5.06000E+02 5.92676E+06 + 5.06100E+02 6.01980E+06 + 5.06200E+02 5.57669E+06 + 5.06300E+02 5.89533E+06 + 5.06400E+02 5.12450E+06 + 5.06500E+02 5.49907E+06 + 5.06600E+02 5.09619E+06 + 5.06700E+02 3.75608E+06 + 5.06800E+02 4.82423E+06 + 5.06900E+02 4.70309E+06 + 5.07000E+02 4.52904E+06 + 5.07100E+02 4.30378E+06 + 5.07200E+02 4.46898E+06 + 5.07300E+02 4.46028E+06 + 5.07400E+02 4.96302E+06 + 5.07500E+02 5.38671E+06 + 5.07600E+02 5.16744E+06 + 5.07700E+02 5.05692E+06 + 5.07800E+02 5.39932E+06 + 5.07900E+02 5.28895E+06 + 5.08000E+02 4.90366E+06 + 5.08100E+02 3.65390E+06 + 5.08200E+02 3.58437E+06 + 5.08300E+02 4.10669E+06 + 5.08400E+02 4.41170E+06 + 5.08500E+02 3.93912E+06 + 5.08600E+02 4.01467E+06 + 5.08700E+02 4.06618E+06 + 5.08800E+02 4.86712E+06 + 5.08900E+02 4.57760E+06 + 5.09000E+02 3.95735E+06 + 5.09100E+02 3.63824E+06 + 5.09200E+02 3.34030E+06 + 5.09300E+02 2.64483E+06 + 5.09400E+02 2.79652E+06 + 5.09500E+02 3.29200E+06 + 5.09600E+02 3.66680E+06 + 5.09700E+02 3.42542E+06 + 5.09800E+02 3.27015E+06 + 5.09900E+02 3.55588E+06 + 5.10000E+02 3.20936E+06 + 5.10100E+02 3.03715E+06 + 5.10200E+02 2.63243E+06 + 5.10300E+02 3.39194E+06 + 5.10400E+02 2.97058E+06 + 5.10500E+02 3.77448E+06 + 5.10600E+02 3.87440E+06 + 5.10700E+02 4.45340E+06 + 5.10800E+02 4.74568E+06 + 5.10900E+02 5.13372E+06 + 5.11000E+02 4.67826E+06 + 5.11100E+02 4.56903E+06 + 5.11200E+02 3.41596E+06 + 5.11300E+02 3.45104E+06 + 5.11400E+02 3.49927E+06 + 5.11500E+02 3.56378E+06 + 5.11600E+02 4.15381E+06 + 5.11700E+02 3.51362E+06 + 5.11800E+02 2.76130E+06 + 5.11900E+02 2.43360E+06 + 5.12000E+02 3.55187E+06 + 5.12100E+02 3.43023E+06 + 5.12200E+02 2.93460E+06 + 5.12300E+02 3.23752E+06 + 5.12400E+02 2.97056E+06 + 5.12500E+02 2.64777E+06 + 5.12600E+02 2.83481E+06 + 5.12700E+02 3.59560E+06 + 5.12800E+02 4.18180E+06 + 5.12900E+02 3.39437E+06 + 5.13000E+02 3.69846E+06 + 5.13100E+02 3.56562E+06 + 5.13200E+02 3.90837E+06 + 5.13300E+02 4.75704E+06 + 5.13400E+02 5.78919E+06 + 5.13500E+02 5.55936E+06 + 5.13600E+02 5.62682E+06 + 5.13700E+02 5.90236E+06 + 5.13800E+02 5.22923E+06 + 5.13900E+02 5.52634E+06 + 5.14000E+02 5.15763E+06 + 5.14100E+02 4.62636E+06 + 5.14200E+02 4.32598E+06 + 5.14300E+02 4.20815E+06 + 5.14400E+02 3.80134E+06 + 5.14500E+02 4.63282E+06 + 5.14600E+02 5.27999E+06 + 5.14700E+02 4.78291E+06 + 5.14800E+02 4.60464E+06 + 5.14900E+02 4.56001E+06 + 5.15000E+02 4.55980E+06 + 5.15100E+02 4.68685E+06 + 5.15200E+02 5.11248E+06 + 5.15300E+02 4.17120E+06 + 5.15400E+02 3.97606E+06 + 5.15500E+02 4.65173E+06 + 5.15600E+02 4.29865E+06 + 5.15700E+02 4.00321E+06 + 5.15800E+02 3.92249E+06 + 5.15900E+02 3.13465E+06 + 5.16000E+02 3.26162E+06 + 5.16100E+02 3.51742E+06 + 5.16200E+02 3.95105E+06 + 5.16300E+02 4.16557E+06 + 5.16400E+02 3.66917E+06 + 5.16500E+02 4.44612E+06 + 5.16600E+02 4.55944E+06 + 5.16700E+02 4.25049E+06 + 5.16800E+02 4.81173E+06 + 5.16900E+02 5.29491E+06 + 5.17000E+02 3.79877E+06 + 5.17100E+02 4.34878E+06 + 5.17200E+02 4.90912E+06 + 5.17300E+02 4.25505E+06 + 5.17400E+02 4.43558E+06 + 5.17500E+02 3.91121E+06 + 5.17600E+02 3.97196E+06 + 5.17700E+02 4.14814E+06 + 5.17800E+02 4.88765E+06 + 5.17900E+02 5.16306E+06 + 5.18000E+02 4.58028E+06 + 5.18100E+02 3.68268E+06 + 5.18200E+02 3.65278E+06 + 5.18300E+02 3.85482E+06 + 5.18400E+02 3.80993E+06 + 5.18500E+02 4.00575E+06 + 5.18600E+02 4.05042E+06 + 5.18700E+02 3.64590E+06 + 5.18800E+02 3.72446E+06 + 5.18900E+02 4.80137E+06 + 5.19000E+02 4.66674E+06 + 5.19100E+02 3.59373E+06 + 5.19200E+02 2.89275E+06 + 5.19300E+02 3.17806E+06 + 5.19400E+02 3.20275E+06 + 5.19500E+02 4.00635E+06 + 5.19600E+02 3.64879E+06 + 5.19700E+02 3.08280E+06 + 5.19800E+02 3.96577E+06 + 5.19900E+02 4.12996E+06 + 5.20000E+02 4.15965E+06 + 5.20100E+02 3.94239E+06 + 5.20200E+02 3.47551E+06 + 5.20300E+02 4.20472E+06 + 5.20400E+02 3.59991E+06 + 5.20500E+02 3.97229E+06 + 5.20600E+02 5.36734E+06 + 5.20700E+02 5.83522E+06 + 5.20800E+02 6.28094E+06 + 5.20900E+02 5.03456E+06 + 5.21000E+02 4.23660E+06 + 5.21100E+02 4.92187E+06 + 5.21200E+02 4.79027E+06 + 5.21300E+02 4.31076E+06 + 5.21400E+02 3.15886E+06 + 5.21500E+02 2.93540E+06 + 5.21600E+02 2.84603E+06 + 5.21700E+02 3.01288E+06 + 5.21800E+02 2.65150E+06 + 5.21900E+02 3.08177E+06 + 5.22000E+02 2.92502E+06 + 5.22100E+02 3.20489E+06 + 5.22200E+02 2.68701E+06 + 5.22300E+02 3.11424E+06 + 5.22400E+02 2.84841E+06 + 5.22500E+02 2.17056E+06 + 5.22600E+02 1.72302E+06 + 5.22700E+02 1.52658E+06 + 5.22800E+02 1.64518E+06 + 5.22900E+02 1.42037E+06 + 5.23000E+02 9.72317E+05 + 5.23100E+02 1.17115E+06 + 5.23200E+02 1.01582E+06 + 5.23300E+02 1.82229E+06 + 5.23400E+02 2.14486E+06 + 5.23500E+02 2.84653E+06 + 5.23600E+02 3.51430E+06 + 5.23700E+02 3.83346E+06 + 5.23800E+02 3.93914E+06 + 5.23900E+02 4.29647E+06 + 5.24000E+02 4.21537E+06 + 5.24100E+02 4.06949E+06 + 5.24200E+02 4.28407E+06 + 5.24300E+02 3.87774E+06 + 5.24400E+02 3.45563E+06 + 5.24500E+02 3.38845E+06 + 5.24600E+02 4.04069E+06 + 5.24700E+02 3.88366E+06 + 5.24800E+02 3.57552E+06 + 5.24900E+02 3.66268E+06 + 5.25000E+02 3.45861E+06 + 5.25100E+02 3.44722E+06 + 5.25200E+02 4.08398E+06 + 5.25300E+02 3.51822E+06 + 5.25400E+02 3.06746E+06 + 5.25500E+02 3.63958E+06 + 5.25600E+02 3.95529E+06 + 5.25700E+02 4.21060E+06 + 5.25800E+02 5.00046E+06 + 5.25900E+02 5.08075E+06 + 5.26000E+02 4.94118E+06 + 5.26100E+02 4.59540E+06 + 5.26200E+02 4.49875E+06 + 5.26300E+02 5.12177E+06 + 5.26400E+02 4.79087E+06 + 5.26500E+02 4.28568E+06 + 5.26600E+02 5.07822E+06 + 5.26700E+02 5.79973E+06 + 5.26800E+02 5.71370E+06 + 5.26900E+02 5.47630E+06 + 5.27000E+02 5.87297E+06 + 5.27100E+02 6.53472E+06 + 5.27200E+02 6.27662E+06 + 5.27300E+02 5.81523E+06 + 5.27400E+02 5.93137E+06 + 5.27500E+02 6.08235E+06 + 5.27600E+02 6.42672E+06 + 5.27700E+02 6.20767E+06 + 5.27800E+02 6.37598E+06 + 5.27900E+02 5.37859E+06 + 5.28000E+02 5.03794E+06 + 5.28100E+02 4.14280E+06 + 5.28200E+02 3.30739E+06 + 5.28300E+02 4.10074E+06 + 5.28400E+02 3.93078E+06 + 5.28500E+02 3.16064E+06 + 5.28600E+02 2.94798E+06 + 5.28700E+02 3.00179E+06 + 5.28800E+02 3.01677E+06 + 5.28900E+02 2.33772E+06 + 5.29000E+02 2.20166E+06 + 5.29100E+02 2.49711E+06 + 5.29200E+02 2.80765E+06 + 5.29300E+02 2.42130E+06 + 5.29400E+02 3.18144E+06 + 5.29500E+02 3.29832E+06 + 5.29600E+02 3.34995E+06 + 5.29700E+02 3.55106E+06 + 5.29800E+02 2.95565E+06 + 5.29900E+02 2.73274E+06 + 5.30000E+02 2.48945E+06 + 5.30100E+02 2.66769E+06 + 5.30200E+02 2.88132E+06 + 5.30300E+02 2.42056E+06 + 5.30400E+02 3.18866E+06 + 5.30500E+02 2.91812E+06 + 5.30600E+02 3.50798E+06 + 5.30700E+02 2.91752E+06 + 5.30800E+02 3.11115E+06 + 5.30900E+02 2.65020E+06 + 5.31000E+02 2.79734E+06 + 5.31100E+02 3.02750E+06 + 5.31200E+02 3.48150E+06 + 5.31300E+02 3.54369E+06 + 5.31400E+02 4.63424E+06 + 5.31500E+02 5.17191E+06 + 5.31600E+02 5.06268E+06 + 5.31700E+02 4.38248E+06 + 5.31800E+02 3.63644E+06 + 5.31900E+02 4.43497E+06 + 5.32000E+02 3.74593E+06 + 5.32100E+02 2.89601E+06 + 5.32200E+02 2.67266E+06 + 5.32300E+02 3.16679E+06 + 5.32400E+02 3.82973E+06 + 5.32500E+02 3.31171E+06 + 5.32600E+02 2.93343E+06 + 5.32700E+02 4.21393E+06 + 5.32800E+02 4.85123E+06 + 5.32900E+02 5.39176E+06 + 5.33000E+02 5.48869E+06 + 5.33100E+02 5.41126E+06 + 5.33200E+02 5.25765E+06 + 5.33300E+02 4.98070E+06 + 5.33400E+02 4.40264E+06 + 5.33500E+02 4.74618E+06 + 5.33600E+02 4.43715E+06 + 5.33700E+02 3.68928E+06 + 5.33800E+02 4.05112E+06 + 5.33900E+02 3.88485E+06 + 5.34000E+02 3.96737E+06 + 5.34100E+02 3.86123E+06 + 5.34200E+02 3.04981E+06 + 5.34300E+02 2.11677E+06 + 5.34400E+02 1.97412E+06 + 5.34500E+02 2.83558E+06 + 5.34600E+02 3.35233E+06 + 5.34700E+02 2.79001E+06 + 5.34800E+02 2.81149E+06 + 5.34900E+02 3.13761E+06 + 5.35000E+02 3.77176E+06 + 5.35100E+02 3.16032E+06 + 5.35200E+02 3.95363E+06 + 5.35300E+02 4.10871E+06 + 5.35400E+02 4.59815E+06 + 5.35500E+02 4.83407E+06 + 5.35600E+02 3.51540E+06 + 5.35700E+02 3.47214E+06 + 5.35800E+02 3.43002E+06 + 5.35900E+02 4.03032E+06 + 5.36000E+02 3.95313E+06 + 5.36100E+02 3.82588E+06 + 5.36200E+02 4.69221E+06 + 5.36300E+02 4.71448E+06 + 5.36400E+02 4.76224E+06 + 5.36500E+02 4.87936E+06 + 5.36600E+02 4.57442E+06 + 5.36700E+02 4.41483E+06 + 5.36800E+02 4.34388E+06 + 5.36900E+02 3.61761E+06 + 5.37000E+02 3.63259E+06 + 5.37100E+02 3.11451E+06 + 5.37200E+02 3.09188E+06 + 5.37300E+02 2.90781E+06 + 5.37400E+02 2.98734E+06 + 5.37500E+02 2.84037E+06 + 5.37600E+02 3.12161E+06 + 5.37700E+02 3.23941E+06 + 5.37800E+02 2.85108E+06 + 5.37900E+02 3.25633E+06 + 5.38000E+02 3.45297E+06 + 5.38100E+02 4.20927E+06 + 5.38200E+02 5.12362E+06 + 5.38300E+02 5.49148E+06 + 5.38400E+02 5.03033E+06 + 5.38500E+02 5.22970E+06 + 5.38600E+02 4.84756E+06 + 5.38700E+02 4.30473E+06 + 5.38800E+02 4.50722E+06 + 5.38900E+02 4.50570E+06 + 5.39000E+02 4.39795E+06 + 5.39100E+02 4.69939E+06 + 5.39200E+02 4.12315E+06 + 5.39300E+02 4.18187E+06 + 5.39400E+02 3.55987E+06 + 5.39500E+02 3.45941E+06 + 5.39600E+02 3.14107E+06 + 5.39700E+02 3.42185E+06 + 5.39800E+02 3.74601E+06 + 5.39900E+02 4.41626E+06 + 5.40000E+02 3.83442E+06 + 5.40100E+02 3.87623E+06 + 5.40200E+02 4.21215E+06 + 5.40300E+02 3.39714E+06 + 5.40400E+02 3.24565E+06 + 5.40500E+02 3.07356E+06 + 5.40600E+02 3.27526E+06 + 5.40700E+02 3.85492E+06 + 5.40800E+02 3.91971E+06 + 5.40900E+02 2.71708E+06 + 5.41000E+02 2.08821E+06 + 5.41100E+02 3.02138E+06 + 5.41200E+02 3.38887E+06 + 5.41300E+02 3.74793E+06 + 5.41400E+02 3.48816E+06 + 5.41500E+02 3.53071E+06 + 5.41600E+02 3.39394E+06 + 5.41700E+02 3.77799E+06 + 5.41800E+02 3.57857E+06 + 5.41900E+02 3.17882E+06 + 5.42000E+02 2.85424E+06 + 5.42100E+02 2.35060E+06 + 5.42200E+02 2.48174E+06 + 5.42300E+02 2.86392E+06 + 5.42400E+02 3.04214E+06 + 5.42500E+02 3.03774E+06 + 5.42600E+02 3.22225E+06 + 5.42700E+02 3.93648E+06 + 5.42800E+02 3.85254E+06 + 5.42900E+02 4.75234E+06 + 5.43000E+02 5.07528E+06 + 5.43100E+02 5.27361E+06 + 5.43200E+02 5.53618E+06 + 5.43300E+02 6.12444E+06 + 5.43400E+02 6.02165E+06 + 5.43500E+02 6.02469E+06 + 5.43600E+02 6.12616E+06 + 5.43700E+02 5.72338E+06 + 5.43800E+02 5.61869E+06 + 5.43900E+02 5.50447E+06 + 5.44000E+02 5.83243E+06 + 5.44100E+02 5.36485E+06 + 5.44200E+02 5.62357E+06 + 5.44300E+02 5.03829E+06 + 5.44400E+02 6.33079E+06 + 5.44500E+02 6.87245E+06 + 5.44600E+02 6.75399E+06 + 5.44700E+02 7.37596E+06 + 5.44800E+02 7.21539E+06 + 5.44900E+02 6.87226E+06 + 5.45000E+02 6.23507E+06 + 5.45100E+02 6.04217E+06 + 5.45200E+02 5.81816E+06 + 5.45300E+02 5.31527E+06 + 5.45400E+02 4.99024E+06 + 5.45500E+02 5.50315E+06 + 5.45600E+02 5.36307E+06 + 5.45700E+02 5.57536E+06 + 5.45800E+02 5.41611E+06 + 5.45900E+02 5.07720E+06 + 5.46000E+02 5.47840E+06 + 5.46100E+02 5.61366E+06 + 5.46200E+02 5.26452E+06 + 5.46300E+02 5.51568E+06 + 5.46400E+02 5.71463E+06 + 5.46500E+02 4.98742E+06 + 5.46600E+02 4.54085E+06 + 5.46700E+02 5.34535E+06 + 5.46800E+02 4.86093E+06 + 5.46900E+02 4.51554E+06 + 5.47000E+02 4.50786E+06 + 5.47100E+02 3.71128E+06 + 5.47200E+02 4.16115E+06 + 5.47300E+02 3.50985E+06 + 5.47400E+02 4.03126E+06 + 5.47500E+02 4.53902E+06 + 5.47600E+02 4.39950E+06 + 5.47700E+02 3.94980E+06 + 5.47800E+02 3.79707E+06 + 5.47900E+02 2.90018E+06 + 5.48000E+02 2.72927E+06 + 5.48100E+02 2.86081E+06 + 5.48200E+02 2.55450E+06 + 5.48300E+02 3.34358E+06 + 5.48400E+02 3.94836E+06 + 5.48500E+02 3.64013E+06 + 5.48600E+02 3.72756E+06 + 5.48700E+02 4.12672E+06 + 5.48800E+02 4.42232E+06 + 5.48900E+02 4.23772E+06 + 5.49000E+02 3.24736E+06 + 5.49100E+02 3.39638E+06 + 5.49200E+02 3.52677E+06 + 5.49300E+02 3.82024E+06 + 5.49400E+02 3.72400E+06 + 5.49500E+02 3.62579E+06 + 5.49600E+02 3.82328E+06 + 5.49700E+02 2.81101E+06 + 5.49800E+02 1.60517E+06 + 5.49900E+02 2.43712E+06 + 5.50000E+02 3.16428E+06 + 5.50100E+02 3.49859E+06 + 5.50200E+02 2.97846E+06 + 5.50300E+02 3.64372E+06 + 5.50400E+02 3.18202E+06 + 5.50500E+02 3.06655E+06 + 5.50600E+02 3.06269E+06 + 5.50700E+02 3.61534E+06 + 5.50800E+02 3.42810E+06 + 5.50900E+02 3.85569E+06 + 5.51000E+02 4.36780E+06 + 5.51100E+02 4.02164E+06 + 5.51200E+02 4.52561E+06 + 5.51300E+02 4.55331E+06 + 5.51400E+02 4.43843E+06 + 5.51500E+02 4.56251E+06 + 5.51600E+02 4.14699E+06 + 5.51700E+02 3.63681E+06 + 5.51800E+02 4.09251E+06 + 5.51900E+02 3.89256E+06 + 5.52000E+02 4.41471E+06 + 5.52100E+02 4.58858E+06 + 5.52200E+02 4.36697E+06 + 5.52300E+02 4.83527E+06 + 5.52400E+02 4.39892E+06 + 5.52500E+02 4.38627E+06 + 5.52600E+02 4.53662E+06 + 5.52700E+02 4.35313E+06 + 5.52800E+02 4.82301E+06 + 5.52900E+02 5.55597E+06 + 5.53000E+02 5.61772E+06 + 5.53100E+02 6.50608E+06 + 5.53200E+02 6.19019E+06 + 5.53300E+02 6.03626E+06 + 5.53400E+02 6.33808E+06 + 5.53500E+02 5.67466E+06 + 5.53600E+02 5.63935E+06 + 5.53700E+02 6.08101E+06 + 5.53800E+02 6.27758E+06 + 5.53900E+02 5.97416E+06 + 5.54000E+02 5.82720E+06 + 5.54100E+02 5.55278E+06 + 5.54200E+02 5.45158E+06 + 5.54300E+02 5.30728E+06 + 5.54400E+02 6.95281E+06 + 5.54500E+02 7.62666E+06 + 5.54600E+02 6.51662E+06 + 5.54700E+02 6.41798E+06 + 5.54800E+02 6.72241E+06 + 5.54900E+02 6.52193E+06 + 5.55000E+02 6.30818E+06 + 5.55100E+02 5.12361E+06 + 5.55200E+02 4.52294E+06 + 5.55300E+02 5.07743E+06 + 5.55400E+02 5.74535E+06 + 5.55500E+02 5.02185E+06 + 5.55600E+02 5.13657E+06 + 5.55700E+02 4.72078E+06 + 5.55800E+02 3.61981E+06 + 5.55900E+02 3.57170E+06 + 5.56000E+02 3.09918E+06 + 5.56100E+02 3.50961E+06 + 5.56200E+02 4.34349E+06 + 5.56300E+02 4.32083E+06 + 5.56400E+02 4.57761E+06 + 5.56500E+02 4.34300E+06 + 5.56600E+02 3.90968E+06 + 5.56700E+02 4.07374E+06 + 5.56800E+02 4.85706E+06 + 5.56900E+02 5.16124E+06 + 5.57000E+02 5.29802E+06 + 5.57100E+02 5.49866E+06 + 5.57200E+02 5.28166E+06 + 5.57300E+02 5.49164E+06 + 5.57400E+02 5.54209E+06 + 5.57500E+02 5.63282E+06 + 5.57600E+02 5.20527E+06 + 5.57700E+02 4.57717E+06 + 5.57800E+02 3.80104E+06 + 5.57900E+02 4.15895E+06 + 5.58000E+02 4.03503E+06 + 5.58100E+02 3.90569E+06 + 5.58200E+02 4.70436E+06 + 5.58300E+02 5.17382E+06 + 5.58400E+02 4.43867E+06 + 5.58500E+02 4.71096E+06 + 5.58600E+02 4.88491E+06 + 5.58700E+02 4.56372E+06 + 5.58800E+02 5.13506E+06 + 5.58900E+02 5.67552E+06 + 5.59000E+02 5.70795E+06 + 5.59100E+02 6.66641E+06 + 5.59200E+02 6.39445E+06 + 5.59300E+02 6.32168E+06 + 5.59400E+02 5.72052E+06 + 5.59500E+02 4.80772E+06 + 5.59600E+02 5.01419E+06 + 5.59700E+02 4.58856E+06 + 5.59800E+02 3.29242E+06 + 5.59900E+02 2.51330E+06 + 5.60000E+02 2.88193E+06 + 5.60100E+02 3.17919E+06 + 5.60200E+02 3.45144E+06 + 5.60300E+02 3.51812E+06 + 5.60400E+02 3.08186E+06 + 5.60500E+02 3.09764E+06 + 5.60600E+02 2.73592E+06 + 5.60700E+02 1.99978E+06 + 5.60800E+02 1.41413E+06 + 5.60900E+02 1.72068E+06 + 5.61000E+02 2.45551E+06 + 5.61100E+02 2.35877E+06 + 5.61200E+02 2.81025E+06 + 5.61300E+02 3.60331E+06 + 5.61400E+02 4.09905E+06 + 5.61500E+02 4.67119E+06 + 5.61600E+02 4.43330E+06 + 5.61700E+02 4.00446E+06 + 5.61800E+02 4.06183E+06 + 5.61900E+02 5.25688E+06 + 5.62000E+02 6.18401E+06 + 5.62100E+02 6.23714E+06 + 5.62200E+02 6.44349E+06 + 5.62300E+02 5.80671E+06 + 5.62400E+02 5.13873E+06 + 5.62500E+02 5.10980E+06 + 5.62600E+02 4.79474E+06 + 5.62700E+02 4.28793E+06 + 5.62800E+02 3.67778E+06 + 5.62900E+02 3.25871E+06 + 5.63000E+02 3.69606E+06 + 5.63100E+02 3.75565E+06 + 5.63200E+02 3.46356E+06 + 5.63300E+02 3.13486E+06 + 5.63400E+02 2.83161E+06 + 5.63500E+02 2.52762E+06 + 5.63600E+02 2.35489E+06 + 5.63700E+02 2.42480E+06 + 5.63800E+02 2.37881E+06 + 5.63900E+02 1.44912E+06 + 5.64000E+02 2.14990E+06 + 5.64100E+02 3.77499E+06 + 5.64200E+02 3.96476E+06 + 5.64300E+02 4.26662E+06 + 5.64400E+02 4.64844E+06 + 5.64500E+02 4.58851E+06 + 5.64600E+02 4.75736E+06 + 5.64700E+02 4.29714E+06 + 5.64800E+02 4.65556E+06 + 5.64900E+02 4.59409E+06 + 5.65000E+02 5.23444E+06 + 5.65100E+02 4.60082E+06 + 5.65200E+02 4.87470E+06 + 5.65300E+02 5.02777E+06 + 5.65400E+02 5.29782E+06 + 5.65500E+02 5.13632E+06 + 5.65600E+02 5.06116E+06 + 5.65700E+02 4.78298E+06 + 5.65800E+02 4.09882E+06 + 5.65900E+02 3.85218E+06 + 5.66000E+02 3.87042E+06 + 5.66100E+02 3.02850E+06 + 5.66200E+02 3.36809E+06 + 5.66300E+02 3.97624E+06 + 5.66400E+02 4.72822E+06 + 5.66500E+02 5.23867E+06 + 5.66600E+02 5.19644E+06 + 5.66700E+02 4.57900E+06 + 5.66800E+02 4.31164E+06 + 5.66900E+02 3.88579E+06 + 5.67000E+02 3.88996E+06 + 5.67100E+02 3.26752E+06 + 5.67200E+02 4.52192E+06 + 5.67300E+02 4.77706E+06 + 5.67400E+02 4.09435E+06 + 5.67500E+02 3.93729E+06 + 5.67600E+02 4.45643E+06 + 5.67700E+02 4.75054E+06 + 5.67800E+02 3.71193E+06 + 5.67900E+02 3.35372E+06 + 5.68000E+02 3.64501E+06 + 5.68100E+02 3.45242E+06 + 5.68200E+02 3.93513E+06 + 5.68300E+02 4.39953E+06 + 5.68400E+02 5.06582E+06 + 5.68500E+02 4.12500E+06 + 5.68600E+02 3.76265E+06 + 5.68700E+02 3.09208E+06 + 5.68800E+02 3.28095E+06 + 5.68900E+02 3.65311E+06 + 5.69000E+02 4.28078E+06 + 5.69100E+02 3.88880E+06 + 5.69200E+02 3.96073E+06 + 5.69300E+02 4.12655E+06 + 5.69400E+02 4.40238E+06 + 5.69500E+02 4.24639E+06 + 5.69600E+02 4.94748E+06 + 5.69700E+02 5.34280E+06 + 5.69800E+02 4.96588E+06 + 5.69900E+02 4.43242E+06 + 5.70000E+02 4.73369E+06 + 5.70100E+02 4.61633E+06 + 5.70200E+02 5.44240E+06 + 5.70300E+02 5.83086E+06 + 5.70400E+02 6.22746E+06 + 5.70500E+02 5.96425E+06 + 5.70600E+02 5.67642E+06 + 5.70700E+02 6.38296E+06 + 5.70800E+02 6.31086E+06 + 5.70900E+02 5.20693E+06 + 5.71000E+02 4.50315E+06 + 5.71100E+02 3.77736E+06 + 5.71200E+02 3.83071E+06 + 5.71300E+02 3.78658E+06 + 5.71400E+02 3.87541E+06 + 5.71500E+02 4.00189E+06 + 5.71600E+02 3.71643E+06 + 5.71700E+02 4.17389E+06 + 5.71800E+02 3.01344E+06 + 5.71900E+02 2.51013E+06 + 5.72000E+02 3.12792E+06 + 5.72100E+02 3.23768E+06 + 5.72200E+02 3.31123E+06 + 5.72300E+02 3.83747E+06 + 5.72400E+02 3.92113E+06 + 5.72500E+02 3.96743E+06 + 5.72600E+02 3.83504E+06 + 5.72700E+02 3.22621E+06 + 5.72800E+02 3.20806E+06 + 5.72900E+02 3.08440E+06 + 5.73000E+02 2.31962E+06 + 5.73100E+02 2.39415E+06 + 5.73200E+02 2.44440E+06 + 5.73300E+02 2.38498E+06 + 5.73400E+02 2.55656E+06 + 5.73500E+02 2.93617E+06 + 5.73600E+02 4.02179E+06 + 5.73700E+02 4.83528E+06 + 5.73800E+02 4.78800E+06 + 5.73900E+02 4.39311E+06 + 5.74000E+02 4.80377E+06 + 5.74100E+02 4.29863E+06 + 5.74200E+02 4.90188E+06 + 5.74300E+02 4.02141E+06 + 5.74400E+02 3.83274E+06 + 5.74500E+02 4.18917E+06 + 5.74600E+02 4.02792E+06 + 5.74700E+02 4.59899E+06 + 5.74800E+02 4.33145E+06 + 5.74900E+02 3.92972E+06 + 5.75000E+02 3.95492E+06 + 5.75100E+02 4.99059E+06 + 5.75200E+02 5.45229E+06 + 5.75300E+02 5.53305E+06 + 5.75400E+02 5.72827E+06 + 5.75500E+02 5.36835E+06 + 5.75600E+02 5.81416E+06 + 5.75700E+02 5.36155E+06 + 5.75800E+02 5.82807E+06 + 5.75900E+02 5.03295E+06 + 5.76000E+02 5.54536E+06 + 5.76100E+02 4.75068E+06 + 5.76200E+02 5.33425E+06 + 5.76300E+02 5.17733E+06 + 5.76400E+02 4.57634E+06 + 5.76500E+02 4.72432E+06 + 5.76600E+02 5.05116E+06 + 5.76700E+02 4.52199E+06 + 5.76800E+02 3.68559E+06 + 5.76900E+02 2.85747E+06 + 5.77000E+02 2.59798E+06 + 5.77100E+02 3.86140E+06 + 5.77200E+02 2.69238E+06 + 5.77300E+02 2.57297E+06 + 5.77400E+02 2.22360E+06 + 5.77500E+02 2.49008E+06 + 5.77600E+02 2.07693E+06 + 5.77700E+02 2.46885E+06 + 5.77800E+02 2.17167E+06 + 5.77900E+02 1.50911E+06 + 5.78000E+02 2.28428E+06 + 5.78100E+02 2.59367E+06 + 5.78200E+02 1.85694E+06 + 5.78300E+02 1.34128E+06 + 5.78400E+02 2.40831E+06 + 5.78500E+02 2.00700E+06 + 5.78600E+02 2.36115E+06 + 5.78700E+02 2.62760E+06 + 5.78800E+02 2.91350E+06 + 5.78900E+02 3.01416E+06 + 5.79000E+02 2.78151E+06 + 5.79100E+02 2.71279E+06 + 5.79200E+02 3.16494E+06 + 5.79300E+02 3.22493E+06 + 5.79400E+02 3.13737E+06 + 5.79500E+02 3.78444E+06 + 5.79600E+02 3.98388E+06 + 5.79700E+02 4.10830E+06 + 5.79800E+02 5.40752E+06 + 5.79900E+02 4.98379E+06 + 5.80000E+02 5.06719E+06 + 5.80100E+02 4.82515E+06 + 5.80200E+02 4.93909E+06 + 5.80300E+02 4.94334E+06 + 5.80400E+02 4.41257E+06 + 5.80500E+02 4.51971E+06 + 5.80600E+02 5.26743E+06 + 5.80700E+02 5.42787E+06 + 5.80800E+02 6.15790E+06 + 5.80900E+02 6.39580E+06 + 5.81000E+02 5.94455E+06 + 5.81100E+02 5.68524E+06 + 5.81200E+02 5.11843E+06 + 5.81300E+02 5.72161E+06 + 5.81400E+02 5.13718E+06 + 5.81500E+02 5.08223E+06 + 5.81600E+02 4.61095E+06 + 5.81700E+02 4.50313E+06 + 5.81800E+02 3.97587E+06 + 5.81900E+02 2.89542E+06 + 5.82000E+02 3.78684E+06 + 5.82100E+02 3.86656E+06 + 5.82200E+02 3.35271E+06 + 5.82300E+02 2.34546E+06 + 5.82400E+02 2.30799E+06 + 5.82500E+02 2.72121E+06 + 5.82600E+02 2.98778E+06 + 5.82700E+02 2.84492E+06 + 5.82800E+02 3.15915E+06 + 5.82900E+02 3.25952E+06 + 5.83000E+02 3.68893E+06 + 5.83100E+02 4.61911E+06 + 5.83200E+02 4.33664E+06 + 5.83300E+02 3.55837E+06 + 5.83400E+02 3.57761E+06 + 5.83500E+02 3.82707E+06 + 5.83600E+02 3.29193E+06 + 5.83700E+02 4.14000E+06 + 5.83800E+02 4.69447E+06 + 5.83900E+02 4.70974E+06 + 5.84000E+02 5.24092E+06 + 5.84100E+02 5.34276E+06 + 5.84200E+02 4.70815E+06 + 5.84300E+02 4.48185E+06 + 5.84400E+02 4.48837E+06 + 5.84500E+02 3.90717E+06 + 5.84600E+02 3.56175E+06 + 5.84700E+02 3.11326E+06 + 5.84800E+02 2.86517E+06 + 5.84900E+02 3.17550E+06 + 5.85000E+02 3.60335E+06 + 5.85100E+02 3.13912E+06 + 5.85200E+02 2.20612E+06 + 5.85300E+02 2.19830E+06 + 5.85400E+02 3.00838E+06 + 5.85500E+02 4.03851E+06 + 5.85600E+02 4.65606E+06 + 5.85700E+02 4.75196E+06 + 5.85800E+02 5.08543E+06 + 5.85900E+02 4.99989E+06 + 5.86000E+02 4.83876E+06 + 5.86100E+02 5.09008E+06 + 5.86200E+02 4.82311E+06 + 5.86300E+02 5.05415E+06 + 5.86400E+02 6.01615E+06 + 5.86500E+02 6.15754E+06 + 5.86600E+02 5.85880E+06 + 5.86700E+02 5.07969E+06 + 5.86800E+02 4.46628E+06 + 5.86900E+02 4.47633E+06 + 5.87000E+02 3.58118E+06 + 5.87100E+02 3.45086E+06 + 5.87200E+02 3.75403E+06 + 5.87300E+02 4.00091E+06 + 5.87400E+02 4.64978E+06 + 5.87500E+02 4.82990E+06 + 5.87600E+02 5.69116E+06 + 5.87700E+02 5.64248E+06 + 5.87800E+02 5.42615E+06 + 5.87900E+02 4.71726E+06 + 5.88000E+02 5.93685E+06 + 5.88100E+02 5.73856E+06 + 5.88200E+02 5.44108E+06 + 5.88300E+02 5.38711E+06 + 5.88400E+02 4.75699E+06 + 5.88500E+02 4.83789E+06 + 5.88600E+02 4.99241E+06 + 5.88700E+02 4.32634E+06 + 5.88800E+02 3.82961E+06 + 5.88900E+02 3.46614E+06 + 5.89000E+02 3.58311E+06 + 5.89100E+02 3.18986E+06 + 5.89200E+02 3.17700E+06 + 5.89300E+02 3.78377E+06 + 5.89400E+02 3.21069E+06 + 5.89500E+02 3.60225E+06 + 5.89600E+02 4.23860E+06 + 5.89700E+02 4.63775E+06 + 5.89800E+02 4.20390E+06 + 5.89900E+02 3.47101E+06 + 5.90000E+02 3.70461E+06 + 5.90100E+02 3.83295E+06 + 5.90200E+02 3.83521E+06 + 5.90300E+02 3.57440E+06 + 5.90400E+02 3.56847E+06 + 5.90500E+02 3.61451E+06 + 5.90600E+02 3.20919E+06 + 5.90700E+02 3.59290E+06 + 5.90800E+02 4.35270E+06 + 5.90900E+02 4.21144E+06 + 5.91000E+02 4.45867E+06 + 5.91100E+02 4.10964E+06 + 5.91200E+02 3.42974E+06 + 5.91300E+02 3.89514E+06 + 5.91400E+02 4.14658E+06 + 5.91500E+02 4.42491E+06 + 5.91600E+02 4.11402E+06 + 5.91700E+02 4.23348E+06 + 5.91800E+02 3.91274E+06 + 5.91900E+02 3.98019E+06 + 5.92000E+02 3.75686E+06 + 5.92100E+02 3.11166E+06 + 5.92200E+02 2.86056E+06 + 5.92300E+02 2.95133E+06 + 5.92400E+02 3.42915E+06 + 5.92500E+02 2.65251E+06 + 5.92600E+02 1.99998E+06 + 5.92700E+02 2.80464E+06 + 5.92800E+02 2.87848E+06 + 5.92900E+02 2.73288E+06 + 5.93000E+02 3.77747E+06 + 5.93100E+02 3.96300E+06 + 5.93200E+02 3.61773E+06 + 5.93300E+02 3.26054E+06 + 5.93400E+02 3.27431E+06 + 5.93500E+02 3.31186E+06 + 5.93600E+02 2.89231E+06 + 5.93700E+02 3.77501E+06 + 5.93800E+02 4.34240E+06 + 5.93900E+02 5.14474E+06 + 5.94000E+02 4.27919E+06 + 5.94100E+02 3.93876E+06 + 5.94200E+02 2.85655E+06 + 5.94300E+02 2.79337E+06 + 5.94400E+02 3.48138E+06 + 5.94500E+02 3.78306E+06 + 5.94600E+02 3.42751E+06 + 5.94700E+02 4.61318E+06 + 5.94800E+02 4.42807E+06 + 5.94900E+02 4.30794E+06 + 5.95000E+02 4.49423E+06 + 5.95100E+02 4.24233E+06 + 5.95200E+02 3.92518E+06 + 5.95300E+02 4.97025E+06 + 5.95400E+02 4.43237E+06 + 5.95500E+02 3.95650E+06 + 5.95600E+02 3.82996E+06 + 5.95700E+02 4.52251E+06 + 5.95800E+02 4.08687E+06 + 5.95900E+02 4.22162E+06 + 5.96000E+02 4.00705E+06 + 5.96100E+02 4.32153E+06 + 5.96200E+02 4.68831E+06 + 5.96300E+02 4.69555E+06 + 5.96400E+02 4.50443E+06 + 5.96500E+02 4.66572E+06 + 5.96600E+02 4.95070E+06 + 5.96700E+02 4.54808E+06 + 5.96800E+02 4.61014E+06 + 5.96900E+02 4.32284E+06 + 5.97000E+02 4.04261E+06 + 5.97100E+02 3.29488E+06 + 5.97200E+02 2.99512E+06 + 5.97300E+02 3.26677E+06 + 5.97400E+02 3.48245E+06 + 5.97500E+02 3.24164E+06 + 5.97600E+02 3.49459E+06 + 5.97700E+02 3.54766E+06 + 5.97800E+02 3.75146E+06 + 5.97900E+02 2.93260E+06 + 5.98000E+02 3.56062E+06 + 5.98100E+02 4.38825E+06 + 5.98200E+02 4.74326E+06 + 5.98300E+02 4.80451E+06 + 5.98400E+02 4.66480E+06 + 5.98500E+02 4.71640E+06 + 5.98600E+02 4.04148E+06 + 5.98700E+02 3.88416E+06 + 5.98800E+02 4.81313E+06 + 5.98900E+02 4.10361E+06 + 5.99000E+02 4.30405E+06 + 5.99100E+02 4.92289E+06 + 5.99200E+02 3.97145E+06 + 5.99300E+02 3.89534E+06 + 5.99400E+02 4.46480E+06 + 5.99500E+02 4.71112E+06 + 5.99600E+02 4.86779E+06 + 5.99700E+02 4.47862E+06 + 5.99800E+02 4.37493E+06 + 5.99900E+02 4.14279E+06 + 6.00000E+02 3.79908E+06 diff --git a/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.log b/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.log new file mode 100644 index 000000000..ba6a09a2d --- /dev/null +++ b/OpenFAST/modules/icefloe/test/GLA_proto_randomCrush_ISO.log @@ -0,0 +1,33 @@ + Running: IceFloeConsole, v1.00.00, December-2013 + This run started on: 28-Oct-2014 at 14:25:32 + + Input file read complete. + + Load time series duration = 600 sec + + Setting common ice flow input parameters + Ice type = 1 + Ice thickness = 1 meters + Ice velocity = 0.2 m/s + Ice direction = 0 degrees + Time step = 0.1 sec + Tower diameter = 5 meters + Random seed = 123 + + Setting common ice crushing input parameters + Reference ice strength = 2.20000E+06 Pascals + Reference ice thickness = 1 meters + Exponent for static load = -0.16 + + Setting parameters for random crushing loads time series + coeffPSD_b = 1.34 + coeffPSD_Ks = 3.24 + crushLoadCOV = 0.25 + stdLoadMult (number of std devs) = 4 + Frequency step = 1.00000E-03 Hz +** Global crushing load is: 8.50271E+06 Newtons. +** Mean crushing load is: 4.25136E+06 Newtons. +** Stdev of crushing load is: 1.06284E+06 Newtons. + + Random continuous ice crushing via ISO/Karna initialized + diff --git a/OpenFAST/modules/icefloe/test/runAll.bat b/OpenFAST/modules/icefloe/test/runAll.bat new file mode 100644 index 000000000..d70ed0f3a --- /dev/null +++ b/OpenFAST/modules/icefloe/test/runAll.bat @@ -0,0 +1,6 @@ +..\bin\IceFloeConsole GLA_proto_flex_IEC.inp +..\bin\IceFloeConsole GLA_proto_lockin_IEC.inp +..\bin\IceFloeConsole GLA_proto_flex_ISO.inp +..\bin\IceFloeConsole GLA_proto_lockin_ISO.inp +..\bin\IceFloeConsole GLA_proto_interCrush_ISO.inp +..\bin\IceFloeConsole GLA_proto_randomCrush_ISO.inp diff --git a/OpenFAST/modules/inflowwind/CMakeLists.txt b/OpenFAST/modules/inflowwind/CMakeLists.txt new file mode 100644 index 000000000..860478519 --- /dev/null +++ b/OpenFAST/modules/inflowwind/CMakeLists.txt @@ -0,0 +1,67 @@ +# +# Copyright 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. +# + +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) +endif() + +set(IFW_SOURCES + 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_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/Lidar_Types.f90 +) + +add_library(ifwlib ${IFW_SOURCES}) +target_link_libraries(ifwlib nwtclibs) + +set(IFW_DRIVER_SOURCES + src/InflowWind_Driver_Types.f90 + src/InflowWind_Driver_Subs.f90 + src/InflowWind_Driver.f90 +) + +add_executable(inflowwind_driver ${IFW_DRIVER_SOURCES}) +target_link_libraries(inflowwind_driver ifwlib ${CMAKE_DL_LIBS}) + +install(TARGETS inflowwind_driver ifwlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/inflowwind/README.md b/OpenFAST/modules/inflowwind/README.md new file mode 100644 index 000000000..d19b47055 --- /dev/null +++ b/OpenFAST/modules/inflowwind/README.md @@ -0,0 +1,9 @@ +# InflowWind Module +The legacy version of this module and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/InflowWind/). + +## Overview +InflowWind is a module for processing wind-inflow data. It has been coupled +into the OpenFAST multi-physics engineering tool to enable aero-elastic +simulation of horizontal-axis wind turbines. InflowWind can also be driven +as a standalone code to process wind-inflow data uncoupled from OpenFAST. diff --git a/OpenFAST/modules/inflowwind/src/CTWind.f90 b/OpenFAST/modules/inflowwind/src/CTWind.f90 new file mode 100644 index 000000000..b0adc411c --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/CTWind.f90 @@ -0,0 +1,1345 @@ +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/OpenFAST/modules/inflowwind/src/FDWind.f90 b/OpenFAST/modules/inflowwind/src/FDWind.f90 new file mode 100644 index 000000000..c8accae52 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/FDWind.f90 @@ -0,0 +1,1300 @@ +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/OpenFAST/modules/inflowwind/src/IfW_4Dext.f90 b/OpenFAST/modules/inflowwind/src/IfW_4Dext.f90 new file mode 100644 index 000000000..a6730ad0f --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_4Dext.f90 @@ -0,0 +1,362 @@ +!> 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 + isopc(i) = -1.0_ReKi ! For consistency, we're not going to interpolate in time; this is because we can't interpolate the last time grid in FAST.Farm anyway + + !------------------------------------------------------------------------------------------------- + ! 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. we should probably throw an error here, but I'm just going to go with the closest grid point. + !------------------------------------------------------------------------------------------------- + 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) !BJJ: check that this isn't too restrictive, especially in time + 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 + 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/OpenFAST/modules/inflowwind/src/IfW_4Dext.txt b/OpenFAST/modules/inflowwind/src/IfW_4Dext.txt new file mode 100644 index 000000000..5a4543981 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_4Dext.txt @@ -0,0 +1,39 @@ +################################################################################################################################### +# 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 <IfW_UserWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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/OpenFAST/modules/inflowwind/src/IfW_4Dext_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_4Dext_Types.f90 new file mode 100644 index 000000000..b87a4e1fe --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_4Dext_Types.f90 @@ -0,0 +1,830 @@ +!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 ) + TYPE(IfW_4Dext_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_4Dext_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_4Dext_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +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 ) + TYPE(IfW_4Dext_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.f90 b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.f90 new file mode 100644 index 000000000..620d38701 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.f90 @@ -0,0 +1,1883 @@ +!> 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%WindProfileType = FF_InitInp%WindProfileType + ParamData%FF%Z0 = FF_InitInp%Z0 + ParamData%FF%PLExp = FF_InitInp%PLExp + + if (InitInp%NativeBladedFmt) then + ParamData%FF%InterpTower = .true. + + ! 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. + call AddMeanVelocity(FF_InitInp, ParamData%FF%GridBase, 1.0_ReKi/ParamData%FF%InvFFZD, ParamData%FF%FFData) + else + ParamData%FF%InterpTower = .false. + 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, 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 + + + ! 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 + 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. + + !---------------------------------------------------------------------------------------------- + ! 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' + ! 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. + IF ( StrNeeded(1) .OR. 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(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 + + ENDIF ! TmpErrStat /= 0 + StrNeeded(1) = .FALSE. + + ENDIF ! INDEX for "CLOCKWISE" + + ELSEIF ( StrNeeded(2) ) THEN + + !------------------------------------------------------------------------------------------- + ! #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, 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) :: 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, '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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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, DiskVel, 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/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.txt b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.txt new file mode 100644 index 000000000..0893b0527 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind.txt @@ -0,0 +1,39 @@ +################################################################################################################################### +# 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 <IfW_BladedFFWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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 ^ ^ 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/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 new file mode 100644 index 000000000..6c38d1b10 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 @@ -0,0 +1,783 @@ +!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 [-] + 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 + END SUBROUTINE IfW_BladedFFWind_CopyInitInput + + SUBROUTINE IfW_BladedFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(IfW_BladedFFWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 + 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 + 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 + 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 ) + TYPE(IfW_BladedFFWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_BladedFFWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat, ErrMsg ) + 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/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.f90 b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.f90 new file mode 100644 index 000000000..feed01fc0 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -0,0 +1,1172 @@ +!> 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 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 + + +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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + + ! 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(PointNum>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)) + ENDDO + END IF + + + !REMOVE THIS for AeroDyn 15 + ! Return the average disk velocity values needed by AeroDyn 14. This is the WindInf_ADhack_diskVel routine. + DiskVel(1) = p%MeanFFWS + DiskVel(2:3) = 0.0_ReKi + + + 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) + + 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() + + !------------------------------------------------------------------------------------------------- + ! 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() + + !------------------------------------------------------------------------------------------------- + ! 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 = "" + + 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: + + nz = size(FFData,1) + ny = size(FFData,2) + nc = size(FFData,3) + nx = size(FFData,4) + + ! 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, 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(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< FF wind-inflow data + + ! Local Variables: + REAL(ReKi) :: Z ! height + REAL(ReKi) :: U ! mean wind speed + INTEGER(IntKi) :: iz ! loop counter + INTEGER(IntKi) :: nz ! number of points in the z 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 ! WindProfileType_None + + U = 0.0_ReKi + + END SELECT + + FFData( iz, :, 1, : ) = FFData( iz, :, 1, : ) + U + + END DO ! iz + + +END SUBROUTINE AddMeanVelocity +!==================================================================================================== +FUNCTION CalculateMeanVelocity(p,z) RESULT(u) + + TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters + REAL(ReKi) , INTENT(IN ) :: Z ! height + REAL(ReKi) :: u ! mean wind speed at height 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 + +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_None .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 ) + + +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 <WindFilePath>/vtk/DisYZ.t<i>.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/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.txt b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.txt new file mode 100644 index 000000000..a1f78d123 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base.txt @@ -0,0 +1,53 @@ +################################################################################################################################### +# 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 <IfW_BladedFFWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + + +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 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)" - + diff --git a/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 new file mode 100644 index 000000000..ffc3ddafd --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 @@ -0,0 +1,711 @@ +!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) :: 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) [-] + 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%Z0 = SrcInitInputData%Z0 + DstInitInputData%XOffset = SrcInitInputData%XOffset + END SUBROUTINE IfW_FFWind_CopyInitInput + + SUBROUTINE IfW_FFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(IfW_FFWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ! 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%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%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 + END SUBROUTINE IfW_FFWind_CopyParam + + SUBROUTINE IfW_FFWind_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +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 + 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 + 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 + END SUBROUTINE IfW_FFWind_UnPackParam + +END MODULE IfW_FFWind_Base_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.f90 b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.f90 new file mode 100644 index 000000000..2ebbcc2b0 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.f90 @@ -0,0 +1,387 @@ +!> 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%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, 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 = 1,p%FF%NFFSteps + 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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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, DiskVel, 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/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.txt b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.txt new file mode 100644 index 000000000..1d4529181 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind.txt @@ -0,0 +1,52 @@ +################################################################################################################################### +# 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 <IfW_HAWCWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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/OpenFAST/modules/inflowwind/src/IfW_HAWCWind_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind_Types.f90 new file mode 100644 index 000000000..8fce841f5 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_HAWCWind_Types.f90 @@ -0,0 +1,1609 @@ +!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 ) + TYPE(IfW_HAWCWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL IfW_FFWind_DestroyInitInput( InitInputData%FF, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_HAWCWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_HAWCWind_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_HAWCWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_HAWCWind_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +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/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.f90 b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.f90 new file mode 100644 index 000000000..6e400323d --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.f90 @@ -0,0 +1,659 @@ +!> 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. + + + ! 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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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, DiskVel, 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/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.txt b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.txt new file mode 100644 index 000000000..71b9e9c75 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind.txt @@ -0,0 +1,33 @@ +################################################################################################################################### +# 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 <IfW_TSFFWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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/OpenFAST/modules/inflowwind/src/IfW_TSFFWind_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind_Types.f90 new file mode 100644 index 000000000..e3fe8d918 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_TSFFWind_Types.f90 @@ -0,0 +1,738 @@ +!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 ) + TYPE(IfW_TSFFWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_TSFFWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_TSFFWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat, ErrMsg ) + 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/OpenFAST/modules/inflowwind/src/IfW_UniformWind.f90 b/OpenFAST/modules/inflowwind/src/IfW_UniformWind.f90 new file mode 100644 index 000000000..1bcc76d27 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UniformWind.f90 @@ -0,0 +1,1121 @@ +!> 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_FF + +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 + 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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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 + + ! DiskVel term -- this represents the average across the disk -- sort of. This changes for AeroDyn 15 + DiskVel = WindInf_ADhack_diskVel(Time, p, m, TmpErrStat, TmpErrMsg) + + 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_FF(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) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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_FF' + + 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, DiskVel, 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_FF +!==================================================================================================== + +!==================================================================================================== +END MODULE IfW_UniformWind diff --git a/OpenFAST/modules/inflowwind/src/IfW_UniformWind.txt b/OpenFAST/modules/inflowwind/src/IfW_UniformWind.txt new file mode 100644 index 000000000..df99ddd79 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UniformWind.txt @@ -0,0 +1,67 @@ +################################################################################################################################### +# 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 <IfW_UniformWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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/OpenFAST/modules/inflowwind/src/IfW_UniformWind_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_UniformWind_Types.f90 new file mode 100644 index 000000000..8c344bd7c --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UniformWind_Types.f90 @@ -0,0 +1,1484 @@ +!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 ) + TYPE(IfW_UniformWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyfileinfotype( InitInputData%PassedFileData, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_UniformWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +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 ) + TYPE(IfW_UniformWind_Intrp), INTENT(INOUT) :: IntrpData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyIntrp' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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/OpenFAST/modules/inflowwind/src/IfW_UserWind.f90 b/OpenFAST/modules/inflowwind/src/IfW_UserWind.f90 new file mode 100644 index 000000000..cf52a3386 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UserWind.f90 @@ -0,0 +1,286 @@ +!> 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, DiskVel, 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) + REAL(ReKi), INTENT( OUT) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + 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 + + ! an average wind speed, required for AD14 + DiskVel = 0.0_ReKi + + ! 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/OpenFAST/modules/inflowwind/src/IfW_UserWind.txt b/OpenFAST/modules/inflowwind/src/IfW_UserWind.txt new file mode 100644 index 000000000..62fa3e3b2 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UserWind.txt @@ -0,0 +1,36 @@ +################################################################################################################################### +# 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 <IfW_UserWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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/OpenFAST/modules/inflowwind/src/IfW_UserWind_Types.f90 b/OpenFAST/modules/inflowwind/src/IfW_UserWind_Types.f90 new file mode 100644 index 000000000..1fa5c484a --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/IfW_UserWind_Types.f90 @@ -0,0 +1,646 @@ +!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 ) + TYPE(IfW_UserWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_UserWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + 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 ) + TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 ) + TYPE(IfW_UserWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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/OpenFAST/modules/inflowwind/src/InflowWind.f90 b/OpenFAST/modules/inflowwind/src/InflowWind.f90 new file mode 100644 index 000000000..555afde4a --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind.f90 @@ -0,0 +1,1746 @@ +!********************************************************************************************************************************** +!! This module is used to read and process the (undisturbed) inflow winds. It must be initialized +!! using InflowWind_Init() with the name of the file, the file type, and possibly reference height and +!! width (depending on the type of wind file being used). This module calls appropriate routines +!! in the wind modules so that the type of wind becomes seamless to the user. InflowWind_End() +!! should be called when the program has finshed. +!! +!! Data are assumed to be in units of meters and seconds. Z is measured from the ground (NOT the hub!). +!! +!! 7 Oct 2009 Initial Release with AeroDyn 13.00.00 B. Jonkman, NREL/NWTC +!! 14 Nov 2011 v1.00.01b-bjj B. Jonkman +!! 1 Aug 2012 v1.01.00a-bjj B. Jonkman +!! 10 Aug 2012 v1.01.00b-bjj B. Jonkman +!! Feb 2013 v2.00.00a-adp conversion to Framework A. Platt +!! Sep 2015 v3.00.00a-adb added separate input file A. Platt +! +!.................................................................................................................................. +! Files with this module: +! InflowWind_Subs.f90 +! InflowWind.txt -- InflowWind_Types will be auto-generated based on the descriptions found in this file. +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2017 Envision Energy +! +! 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 InflowWind + + + USE InflowWind_Types + USE NWTC_Library + USE InflowWind_Subs + + USE Lidar ! module for obtaining sensor data + + IMPLICIT NONE + PRIVATE + + TYPE(ProgDesc), PARAMETER :: IfW_Ver = ProgDesc( 'InflowWind', '', '' ) + + + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: InflowWind_Init !< Initialization routine + 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 + + + ! 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 - + !! (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 - + !! (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 - + !! (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 + + + +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. +!! The initial states and initial guess for the input are defined. +!! 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(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) :: 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, 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 ) + + + ! 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. + 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. + ENDIF + + + ! 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) + + 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 + y%VelocityUVW = 0.0_ReKi + + + !----------------------------------------------------------------- + ! Initialize the submodules based on the WindType + !----------------------------------------------------------------- + + + InitOutData%WindFileInfo%MWS = HUGE(InitOutData%WindFileInfo%MWS) + + 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 + p%UniformWind%RefHt = InputFileData%Steady_RefHt + p%UniformWind%RefLength = 1.0_ReKi ! This is not used since no shear gusts are used. Set to 1.0 so calculations don't bomb. + m%UniformWind%TimeIndex = 1 ! Used in UniformWind as a check if initialization was done. + + + 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 = 1.0_ReKi ! This is done so that 0.0*(some stuff)/RefLength doesn't blow up. + 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 + + + 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 + + + CASE ( BladedFF_WindNumber, BladedFF_Shr_WindNumber ) + + ! Set InitInp information + BladedFF_InitData%SumFileUnit = SumFileUnit + + if (InputFileData%WindType /= BladedFF_Shr_WindNumber) then + 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) + + 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 + + + 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 + + + ! Store wind file metadata + CALL SetFFInitOutData(p%HAWCWind%FF) + InitOutData%WindFileInfo%FileName = InputFileData%HAWC_FileName_u + p%ReferenceHeight = InitOutData%WindFileInfo%RefHt + + + 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()') + + + + + END SELECT + + + !IF ( InputFileData%CTTS_Flag ) THEN + ! ! Initialize the CTTS_Wind module + !ENDIF + + + !............................................ + ! 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 + + + +!!! !---------------------------------------------------------------------------------------------- +!!! ! 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 +!!! + + + + + ! 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) + 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 + + + ! allocate and fill variables for linearization: + if (InitInp%Linearize) then + + CALL AllocAry(InitOutData%LinNames_u, InitInp%NumWindPoints*3 + 3, 'LinNames_u', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%RotFrame_u, InitInp%NumWindPoints*3 + 3, 'RotFrame_u', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%IsLoad_u, InitInp%NumWindPoints*3 + 3, 'IsLoad_u', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%LinNames_y, InitInp%NumWindPoints*3+p%NumOuts, 'LinNames_y', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%RotFrame_y, InitInp%NumWindPoints*3+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 + + InitOutData%LinNames_u(InitInp%NumWindPoints*3 + 1) = 'Extended input: horizontal wind speed (steady/uniform wind), m/s' + InitOutData%LinNames_u(InitInp%NumWindPoints*3 + 2) = 'Extended input: vertical power-law shear exponent, -' + InitOutData%LinNames_u(InitInp%NumWindPoints*3 + 3) = 'Extended input: propagation direction, rad' + + do i=1,p%NumOuts + InitOutData%LinNames_y(i+3*InitInp%NumWindPoints) = 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%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() + + + RETURN + + + !---------------------------------------------------------------------------------------------------- +CONTAINS + + 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) + + ! 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 + + + 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 + + +!==================================================================================================== +!> This routine takes an input dataset of type InputType which contains a position array of dimensions 3*n. It then calculates +!! and returns the output dataset of type OutputType which contains a corresponding velocity array of dimensions 3*n. The input +!! array contains XYZ triplets for each position of interest (first index is X/Y/Z for values 1/2/3, second index is the point +!! number to evaluate). The returned values in the OutputData are similar with U/V/W for the first index of 1/2/3. +!! +!! _Coordinate transformation:_ +!! The coordinates passed in are copied to the PositionXYZPrime array, then rotated by -(p%PropagationDir) (radians) so +!! that the wind direction lies along the X-axis (all wind files are given this way). The submodules are then called with +!! these PositionXYZPrime coordinates. +!! +!! After the calculation by the submodule, the PositionXYZPrime coordinate array is deallocated. The returned VelocityUVW +!! 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 ) + + + 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 + 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 + + + + ! 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), & + "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 and OutputData%DiskVel + !----------------------------- + + + CALL CalculateOutput( Time, InputData, p, & + ContStates, DiscStates, ConstrStates, & + OtherStates, OutputData, m, .TRUE., 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 + + + !----------------------------- + ! Outputs: OutputData%WriteOutput from m%AllOuts and OutputData%lidar%LidSpeed + !----------------------------- + + 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 + + + +!==================================================================================================== +!> 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 + + 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) + + + ! Error Handling + + INTEGER( IntKi ), INTENT( OUT) :: ErrStat !< error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message + + + 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 ) + + + CALL InflowWind_DestroyInput( InputData, ErrStat, ErrMsg ) + CALL InflowWind_DestroyParam( p, ErrStat, ErrMsg ) + 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 + + +!==================================================================================================== +! 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 +!! 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; + !! Output: Continuous states at t + Interval + 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; + !! Output: Constraint states at t + Interval + 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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + x%DummyContState = 0.0_ReKi + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + + RETURN + + +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 ) +!.................................................................................................................................. + + 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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + dxdt%DummyContState = 0.0_ReKi + + +END SUBROUTINE InflowWind_CalcContStateDeriv + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states +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; + !! 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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + + ! StateData%DiscState = + +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 + !! 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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + z_residual%DummyConstrState = 0 + +END SUBROUTINE InflowWind_CalcConstrStateResidual + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in IfW_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ) +!.................................................................................................................................. + + 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) + !! with respect to inputs (u) [intent in to avoid deallocation] + 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) + !! with respect to inputs (u) [intent in to avoid deallocation] + 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,6) + integer :: i, n + integer :: i_start, i_end ! indices for input/output start and end + integer :: node, comp + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + IF ( PRESENT( dYdu ) ) THEN + + ! 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 + ! + if (.not. ALLOCATED(dYdu)) then + CALL AllocAry( dYdu, SIZE(u%PositionXYZ)+p%NumOuts, SIZE(u%PositionXYZ)+3, '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 + ! note that p%RotToWind(1,1) = cos(p%PropagationDir) and p%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 ) + + 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,n*3+1:) = local_dYdu(:,4:6) ! extended inputs + + end do + + ! 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 + + 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 ) + else + local_dYdu = 0.0_R8Ki + end if + + dYdu(3*n+i, 3*n+1:) = p%OutParam(i)%SignM * local_dYdu( comp , 4:6) + end do + + CASE DEFAULT + + END SELECT + + 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( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + +END SUBROUTINE InflowWind_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)+3, '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 + + call IfW_UniformWind_GetOP( t, p%UniformWind, m%UniformWind, u_op(index+1:index+2) ) + u_op(index + 3) = p%PropagationDir + + END IF + + IF ( PRESENT( y_op ) ) THEN + if (.not. allocated(y_op)) then + call AllocAry(y_op, size(u%PositionXYZ)+p%NumOuts, '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 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 + + END IF + + IF ( PRESENT( z_op ) ) THEN + + 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_FF(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_FF(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_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_FF(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/OpenFAST/modules/inflowwind/src/InflowWind.txt b/OpenFAST/modules/inflowwind/src/InflowWind.txt new file mode 100644 index 000000000..98d21cb8d --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind.txt @@ -0,0 +1,191 @@ +################################################################################################################################### +# Registry for InflowWind, creates MODULE InflowWind_Types +# Module InflowWind_Types contains all of the user-defined types needed in InflowWind. It also contains copy, destroy, pack, and +# unpack routines associated with each defined data types. +################################################################################################################################### +# Entries are of the form +# keyword <InflowWind[/ModuleAbvr]> <TypeName> <FieldType> <FieldName> <Dims> <Ctrl> <DNAME> <DESCRIP> <UNITS> +################################################################################################################################### + +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 Lidar.txt + +include Registry_NWTC_Library.txt + + +param InflowWind/InflowWind - IntKi Undef_WindNumber - 0 - "This is the code for an undefined WindFileType" - +param ^ - IntKi Steady_WindNumber - 1 - "Steady wind. Calculated internally." - +param ^ - IntKi Uniform_WindNumber - 2 - "Uniform wind. Formally known as a Hub-Height wind file." - +param ^ - IntKi TSFF_WindNumber - 3 - "TurbSim full-field binary file." - +param ^ - IntKi BladedFF_WindNumber - 4 - "Bladed style binary full-field file. Includes native bladed format" - +param ^ - IntKi HAWC_WindNumber - 5 - "HAWC wind file." - +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." - + + +######################### +# ..... 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) +# ..... Primary Input file data ................................................................................................... +typedef InflowWind/InflowWind InflowWind_InputFile LOGICAL EchoFlag - - - "Echo the input file" - +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 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 +typedef ^ ^ ReKi WindVziList : - - "List of Z coordinates for wind velocity measurements" meters +typedef ^ ^ ReKi Steady_HWindSpeed - - - "Steady wind -- horizontal windspeed" meters/s +typedef ^ ^ ReKi Steady_RefHt - - - "Steady wind -- reference height" meters +typedef ^ ^ ReKi Steady_PLexp - - - "Steady wind -- power law exponent" - +typedef ^ ^ CHARACTER(1024) Uniform_FileName - - - "Uniform wind -- filename" - +typedef ^ ^ ReKi Uniform_RefHt - - - "Uniform wind -- reference height" meters +typedef ^ ^ ReKi Uniform_RefLength - - - "Uniform wind -- reference length" meters +typedef ^ ^ CHARACTER(1024) TSFF_FileName - - - "TurbSim Full-Field -- filename" - +typedef ^ ^ CHARACTER(1024) BladedFF_FileName - - - "Bladed-style Full-Field -- filename" - +typedef ^ ^ LOGICAL BladedFF_TowerFile - - - "Bladed-style Full-Field -- tower file exists" - +typedef ^ ^ LOGICAL CTTS_CoherentTurb - .FALSE. - "Coherent turbulence data exists" - +typedef ^ ^ CHARACTER(1024) CTTS_FileName - - - "Name of coherent turbulence file" - +typedef ^ ^ CHARACTER(1024) CTTS_Path - - - "Path to coherent turbulence binary data files" - +typedef ^ ^ CHARACTER(1024) HAWC_FileName_u - - - "HAWC -- u component binary data file name" - +typedef ^ ^ CHARACTER(1024) HAWC_FileName_v - - - "HAWC -- v component binary data file name" - +typedef ^ ^ CHARACTER(1024) HAWC_FileName_w - - - "HAWC -- w component binary data file name" - +typedef ^ ^ IntKi HAWC_nx - - - "HAWC -- number of grids in x direction" - +typedef ^ ^ IntKi HAWC_ny - - - "HAWC -- number of grids in y direction" - +typedef ^ ^ IntKi HAWC_nz - - - "HAWC -- number of grids in z direction" - +typedef ^ ^ ReKi HAWC_dx - - - "HAWC -- distance between points in x direction" meters +typedef ^ ^ ReKi HAWC_dy - - - "HAWC -- distance between points in y direction" meters +typedef ^ ^ ReKi HAWC_dz - - - "HAWC -- distance between points in z direction" meters +typedef ^ ^ LOGICAL SumPrint - - - "Write summary info to a file <ROOTNAME>.IfW.Sum" - +typedef ^ ^ IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ^ CHARACTER(ChanLen) OutList : - - "List of user-requested output channels" - +typedef ^ ^ IntKi SensorType - SensorType_None - "Sensor type (for lidar/sensor module)" - +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 ^ InitInputType CHARACTER(1024) InputFileName - - - "Name of the InflowWind input file to use" - +typedef ^ ^ LOGICAL Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ ^ LOGICAL Use4Dext - .FALSE. - "Flag that tells this module if an external module will pass it 4-D velocity grids." - +typedef ^ ^ IntKi NumWindPoints - - - "Number of wind velocity points expected" - +typedef ^ ^ LOGICAL UseInputFile - .TRUE. - "Should we read everthing from an input file, or do we get it some other way" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" +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 ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - +typedef ^ ^ IfW_4Dext_InitInputType FDext - - - "InitInput for lidar data" - + + +# Init Output +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 ^ 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" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - + + +# ..... 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 ^ ^ ReKi WindViUVW :: - - "List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" meters/second + + +# ..... 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 ^ ^ 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 ^ ^ IntKi WindType - 0 - "Type of wind -- set to Undef_Wind initially" - +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 ^ ^ 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" - + + +# ..... Inputs .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi PositionXYZ :: - - "Array holding the input positions at a given timestep" meters +typedef ^ ^ lidar_InputType lidar - - - "Lidar data" - + + +# ..... 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 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 ^ ^ 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" - +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" - diff --git a/OpenFAST/modules/inflowwind/src/InflowWind_Driver.f90 b/OpenFAST/modules/inflowwind/src/InflowWind_Driver.f90 new file mode 100644 index 000000000..fedb40334 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind_Driver.f90 @@ -0,0 +1,969 @@ +!**************************************************************************** +! +! PROGRAM: InflowWind_Driver - This program tests the inflow wind module +! +!**************************************************************************** +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 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. +! +!********************************************************************************************************************************** + +PROGRAM InflowWind_Driver + +! USE NWTC_Library !NOTE: Not sure why this doesn't need to be specified + USE InflowWind + 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 + + IMPLICIT NONE + + ! Info on this code + TYPE( ProgDesc ), PARAMETER :: ProgInfo = ProgDesc("InflowWind_Driver","","") + INTEGER(IntKi) :: IfWDriver_Verbose = 5 ! Verbose level. 0 = none, 5 = some, 10 = lots + + ! Types needed here (from InflowWind module) + TYPE(InflowWind_InitInputType) :: InflowWind_InitInp ! Data for initialization -- this is where the input info goes + TYPE(InflowWind_InputType) :: InflowWind_u1 ! input -- contains xyz coords of interest -- set 1 + TYPE(InflowWind_InputType) :: InflowWind_u2 ! input -- contains xyz coords of interest -- set 2 + TYPE(InflowWind_InputType) :: InflowWind_u3 ! input -- contains xyz coords of interest -- set 3 + TYPE(InflowWind_ParameterType) :: InflowWind_p ! Parameters + TYPE(InflowWind_ContinuousStateType) :: InflowWind_x ! Continous State Data (not used here) + TYPE(InflowWind_DiscreteStateType) :: InflowWind_xd ! Discrete State Data (not used here) + TYPE(InflowWind_ConstraintStateType) :: InflowWind_z ! Constraint State Data (not used here) + TYPE(InflowWind_OtherStateType) :: InflowWind_OtherState ! Other State Data (Wind data is stored in here) + TYPE(InflowWind_OutputType) :: InflowWind_y1 ! Output Data -- contains the velocities at xyz -- set 1 + TYPE(InflowWind_OutputType) :: InflowWind_y2 ! Output Data -- contains the velocities at xyz -- set 2 + TYPE(InflowWind_OutputType) :: InflowWind_y3 ! Output Data -- contains the velocities at xyz -- set 3 + TYPE(InflowWind_MiscVarType) :: InflowWind_MiscVars ! misc/optimization data + TYPE(InflowWind_InitOutputType) :: InflowWind_InitOut ! Output Data -- contains the names and units + + + ! Local variables for this code + TYPE(IfWDriver_Flags) :: CLSettingsFlags ! Flags indicating which command line arguments were specified + TYPE(IfWDriver_Settings) :: CLSettings ! Command line arguments passed in + 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) :: 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) + + + + + ! Local variables for storing the arrays + REAL(ReKi),ALLOCATABLE :: PointsXYZ(:,:) !< (X,Y,Z) coordinates read from Points input file. Velocity results stored in y2 + INTEGER(IntKi) :: I,J,K,Counter !< Generic counters/indices + + ! Temporary variables + CHARACTER(1024) :: TmpChar ! Temporary character variable + + ! Local Error Handling + INTEGER(IntKi) :: ErrStat + CHARACTER(1024) :: ErrMsg + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + INTEGER(IntKi) :: LenErrMsgTmp ! Length of ErrMsgTmp + + + + ! Temporary array for testing -- This is contained within a the InflowWind_Subs module. It appears here only for testing purposes + CHARACTER(9), PARAMETER :: ValidParamAry(27) = (/ & + "WIND1VELX","WIND1VELY","WIND1VELZ","WIND2VELX","WIND2VELY","WIND2VELZ","WIND3VELX", & + "WIND3VELY","WIND3VELZ","WIND4VELX","WIND4VELY","WIND4VELZ","WIND5VELX","WIND5VELY", & + "WIND5VELZ","WIND6VELX","WIND6VELY","WIND6VELZ","WIND7VELX","WIND7VELY","WIND7VELZ", & + "WIND8VELX","WIND8VELY","WIND8VELZ","WIND9VELX","WIND9VELY","WIND9VELZ"/) + + + !-------------------------------------------------------------------------- + !-=-=- Initialize the Library -=-=- + !-------------------------------------------------------------------------- + + CALL NWTC_Init + CALL DispNVD(ProgInfo) + +! Beep = .FALSE. + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Setup the program -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + ! 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 + + ! Initialize the driver settings to their default values (same as the CL -- command line -- values) + Settings = CLSettings + SettingsFlags = CLSettingsFlags + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Parse the command line inputs -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + CALL RetrieveArgs( CLSettings, CLSettingsFlags, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= 0 ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ENDIF + + + ! Check if we are doing verbose error reporting + IF ( CLSettingsFlags%VVerbose ) THEN + IfWDriver_Verbose = 10_IntKi + ENDIF + IF ( CLSettingsFlags%Verbose ) THEN + IfWDriver_Verbose = 7_IntKi + ENDIF + + + + ! Verbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr('--- Settings from the command line: ---') + CALL printSettings( CLSettingsFlags, CLSettings ) + CALL WrSCr(NewLine) + ENDIF + + + ! Verbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr('--- Driver settings (before reading driver ipt file): ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + + + ! Copy the input file information from the CLSettings to the Settings. + ! At this point only one input file type can be set. + IF ( CLSettingsFlags%DvrIptFile ) THEN + SettingsFlags%DvrIptFile = CLSettingsFlags%DvrIptFile + Settings%DvrIptFileName = CLSettings%DvrIptFileName + ELSE + SettingsFlags%IfWIptFile = CLSettingsFlags%IfWIptFile + Settings%IfWIptFileName = CLSettings%IfWIptFileName + ENDIF + + + ! If the filename given was not the IfW input file (-ifw option), then it is treated + ! as the driver input file (flag should be set correctly by RetrieveArgs). So, we must + ! open this. + IF ( SettingsFlags%DvrIptFile ) THEN + + ! Read the driver input file + CALL ReadDvrIptFile( CLSettings%DvrIptFileName, SettingsFlags, Settings, ProgInfo, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ENDIF + + + ! VVerbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after reading the driver ipt file: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + ! VVerbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) CALL WrScr('Updating driver settings with command line arguments') + + + ! Now that we have read in the driver input settings, we need to override these with any + ! values from the command line arguments. The .TRUE. indicates that a driver input file + ! was read. + CALL UpdateSettingsWithCL( SettingsFlags, Settings, CLSettingsFlags, CLSettings, .TRUE., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ENDIF + + ! Verbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + CALL WrSCr(NewLine//'--- Driver settings after copying over CL settings: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + ELSE + + SettingsFlags%WrHAWC = .FALSE. + SettingsFlags%WrBladed = .FALSE. + SettingsFlags%WrVTK = .FALSE. + + ! VVerbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) CALL WrScr('No driver input file used. Updating driver settings with command line arguments') + + + ! Since there were no settings picked up from the driver input file, we need to copy over all + ! the CLSettings into the regular Settings. The .FALSE. is a flag indicating that the driver + ! input file was not read. + CALL UpdateSettingsWithCL( SettingsFlags, Settings, CLSettingsFlags, CLSettings, .FALSE., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ENDIF + + ! Verbose error reporting + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after copying over CL settings: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + ENDIF + + + + ! Sanity check: if an input points file is specified, make sure it actually exists. Open it if specified + + IF ( SettingsFlags%PointsFile ) THEN + 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 + CALL ReadPointsFile( Settings%PointsFileName, PointsXYZ, ErrStat,ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= 0 ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ENDIF + + ! Make name for output + CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName ) + Settings%PointsOutputName = TRIM(Settings%PointsOutputName)//'.Velocity.dat' + + CALL WrScr(NewLine//"Read "//TRIM(Num2LStr(SIZE(PointsXYZ,DIM=2)))//" points from '"//TRIM(Settings%PointsFileName)// & + "'. Results output to '"//TRIM(Settings%PointsOutputName)//"'.") + + ! 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)) + + ENDIF + + + ! Setup the FFT output + IF ( SettingsFlags%FFTcalc ) THEN + ! Make name for output + IF ( SettingsFlags%DvrIptFile ) THEN + CALL GetRoot( Settings%DvrIptFileName, Settings%FFTOutputName ) + ELSE + CALL GetRoot( Settings%IfWIptFileName, Settings%FFTOutputName ) + ENDIF + + Settings%FFTOutputName = TRIM(Settings%FFTOutputName)//'_'// & + 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 ( "// & + 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)) + + + ENDIF + + + ! Setup WindGrid output + IF ( SettingsFlags%WindGrid ) THEN + + ! Create WindGrid output name + IF ( SettingsFlags%DvrIptFile ) THEN + CALL GetRoot( Settings%DvrIptFileName, Settings%WindGridOutputName ) + ELSE + CALL GetRoot( Settings%IfWIptFileName, Settings%WindGridOutputName ) + ENDIF + + Settings%WindGridOutputName = TRIM(Settings%WindGridOutputName)//'.WindGrid.out' + + ! Output message if some verbosity. + IF ( IfWDriver_Verbose >= 5_IntKi ) THEN + CALL WindGridMessage( Settings, .FALSE., ErrMsgTmp, LenErrMsgTmp ) ! .FALSE. for no comment characters. ErrMsgTmp holds the message. + + CALL WrScr(NewLine//TRIM(ErrMsgTmp)//NewLine) + ENDIF + + ENDIF + + + ! Summary file output + IF ( SettingsFlags%SummaryFile ) THEN + + ! Create SummaryFile output name + IF ( SettingsFlags%DvrIptFile ) THEN + CALL GetRoot( Settings%DvrIptFileName, Settings%SummaryFileName ) + ELSE + CALL GetRoot( Settings%IfWIptFileName, Settings%SummaryFileName ) + ENDIF + + Settings%SummaryFileName = TRIM(Settings%SummaryFileName)//'.sum' + + IF ( IfWDriver_Verbose >= 10_IntKi ) CALL WrScr('Driver summary output file: '//TRIM(Settings%SummaryFileName)) + + ENDIF + + + ! Give status update of the driver flags, if verbose + IF ( IfWDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after finalizing: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Initialize the Module -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! Initialize the InflowWind module --> it will initialize all its pieces + + !DATA HANDLING: + ! + ! During the initialization call to the IfW_Init, we specify how many points we expect to need. For this, + ! we will ask for the WindGrid data (if that was set), or for a single point at 50 m (random height, not reported). + ! The arrays in the IfW_InputType and IfW_OutputType will be allocated by IfW_Init based on this number. The + ! u1 and y1 are used for this. + ! + ! After initialization, we will create a second set of data corresponding to the Points file data. This set + ! of arrays will be allocated by the driver code and copied over. The number of points will usually be + ! different than the number asked for in the WindGrid data. The u2 and y2 are used for this. + ! + ! During the calculations in the driver code, we will use the MOVE_ALLOC statement to switch between the set + ! of arrays (position and velocity) for the WindGrid data and the Points file data. The reason for doing + ! this is to demonstrate one method for handling AeroDynamic loading wind data (blades etc) and LIDAR requested + ! wind information, which may be on a different timestep basis. + ! + ! The one complication that occurs with this is that if the + + + ! Set the number of points we are expecting to ask for initially + InflowWind_InitInp%NumWindPoints = 1_IntKi ! Default for only asking at a single height + IF ( SettingsFlags%WindGrid ) THEN + ! Just in case the number of gridpoints in a direction is <= 0. + InflowWind_InitInp%NumWindPoints = ( MAX(Settings%GridN(1),1_IntKi) ) * ( MAX(Settings%GridN(2),1_IntKi) ) * & + ( MAX(Settings%GridN(3),1_IntKi) ) + ENDIF + + +! ! Should be able to either allocate InflowWind_u1%PositionXYZ here, or in IfW +! CALL AllocAry( InflowWind_u1%PositionXYZ, 3, InflowWind_InitInp%NumWindPoints, & +! "Array of positions at which to find wind velocities for the WindGrid", ErrStat, ErrMsg ) + + + + ! Some other settings + InflowWind_InitInp%InputFileName = Settings%IfWIptFileName ! For now, IfW cannot work without an input file. + !InflowWind_InitInp%DT = Settings%DT + InflowWind_InitInp%UseInputFile = .TRUE. + IF ( SettingsFlags%DvrIptFile ) THEN + CALL GetRoot( Settings%DvrIptFileName, InflowWind_InitInp%RootName ) + ELSE + CALL GetRoot( InflowWind_InitInp%InputFileName, InflowWind_InitInp%RootName ) + !InflowWind_InitInp%RootName = "" + END IF + InflowWind_InitInp%RootName = trim(InflowWind_InitInp%RootName)//'.IfW' + + IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr('Calling InflowWind_Init...') + + + CALL InflowWind_Init( InflowWind_InitInp, InflowWind_u1, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y1, InflowWind_MiscVars, Settings%DT, InflowWind_InitOut, 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 >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' InflowWind_Init returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ENDIF + + + + ! Let user know we returned from the InflowWind code if verbose + IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Init CALL returned without errors.'//NewLine) + + + ! Convert InflowWind file to HAWC format + IF (SettingsFlags%WrHAWC) THEN + + CALL InflowWind_Convert2HAWC( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, 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))) + END IF + ELSE + IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2HAWC CALL returned without errors.'//NewLine) + END IF + + END IF ! Write HAWC2 files + + + ! Convert InflowWind file to Native Bladed format + IF (SettingsFlags%WrBladed) THEN + CALL InflowWind_Convert2Bladed( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, 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_Convert2Bladed returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) + END IF + ELSE + IF ( IfWDriver_Verbose >= 5_IntKi ) 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 ) + + 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))) + END IF + ELSE + IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2VTK CALL returned without errors.'//NewLine) + END IF + + END IF + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Other Setup -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! Setup any additional things + +if (SettingsFlags%WindGrid .or. SettingsFlags%PointsFile .or. SettingsFlags%FFTcalc) then ! we can skip all of this if we haven't asked for any output + + ! Timestep -- The timestep for the calling InflowWind_CalcOutput may need to be changed to what is in the file if the + ! DT = DEFAULT option was used in the driver input file. This does not need to be changed in the InflowWind_Parameters + ! since IfW doesn't care what the timestep is. + + IF ( SettingsFlags%DTDefault ) THEN + IF ( InflowWind_InitOut%WindFileInfo%ConstantDT ) THEN + Settings%DT = InflowWind_InitOut%WindFileInfo%DT + + IF ( IfWDriver_Verbose >= 5 ) CALL WrScr(' DEFAULT requested for DT. Setting to '//TRIM(Num2LStr(Settings%DT))//' as given in the wind file.') + + ELSE IF ( InflowWind_InitOut%WindFileInfo%NumTSteps <= 1 ) THEN + + Settings%DT = 0.0_ReKi + + IF ( IfWDriver_Verbose >= 5 ) CALL WrScr(' DEFAULT requested for DT. Setting to 0.0 since only one timestep given in the wind file.') + + ELSE + CALL DriverCleanup() + CALL ProgAbort(NewLine//" Cannot use setting of 'DT = DEFAULT'. The timesteps are not uniform within the data file,"// & + " or there are less than 3 timesteps in the file.") + ENDIF + ENDIF + + + ! If the number of timesteps was set to default, set it to the minimum of either number of timesteps in the file, + ! or the largest number of complete timesteps for the given DT and time range of the file. + IF ( SettingsFlags%NumTimeStepsDefault ) THEN + + ! Set the value to the number of timesteps given in the file + Settings%NumTimeSteps = InflowWind_InitOut%WindFileInfo%NumTSteps + + ! Tell user what we set the number of timesteps to + IF ( IfWDriver_Verbose >= 7 ) CALL WrScr(' DEFAULT requested for NumTSteps. Setting to '//TRIM(Num2LStr(Settings%NumTimeSteps))//' as given in the wind file.') + + ! Reduce to an integer number of timesteps for the given DT and time we are giving results for + IF ( (Settings%NumTimeSteps * Settings%DT) > (InflowWind_InitOut%WindFileInfo%TRange(2) - Settings%TStart) ) THEN + + ! Set the value. Add 1 to get the first data point + IF ( Settings%DT > 0.0_DbKi ) THEN + Settings%NumTimeSteps = FLOOR( (InflowWind_InitOut%WindFileInfo%TRange(2) - Settings%TStart)/Settings%DT) + 1_IntKi + ELSE + Settings%NumTimeSteps = 1_IntKi + ENDIF + + ! Tell the user that we reset things again + IF ( IfWDriver_Verbose >= 7 ) CALL WrScr(' Resetting NumTSteps to '//TRIM(Num2LStr(Settings%NumTimeSteps))// & + ' to stay within the time range given in the file (with rounding errors).') + ENDIF + + ! Simple message if not extra verbose. + IF ( IfWDriver_Verbose == 5 ) CALL WrScr(' DEFAULT requested for NumTSteps. Setting to '//TRIM(Num2LStr(Settings%NumTimeSteps))//'.') + + ENDIF + + + + ! WindGrid output file and points array + 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 ) + + + ! Setup the actual grid points -- scan order, Y,Z,X + Counter = 1_IntKi + DO I = 1,Settings%GridN(1) ! Slowest scan over X + DO K = 1,Settings%GridN(3) ! Single Z row + DO J = 1,Settings%GridN(2) ! Step through Y fastest + InflowWind_u1%PositionXYZ(1,Counter) = Settings%XRange(1) + Settings%GridDelta(1)*( I - 1 ) + InflowWind_u1%PositionXYZ(2,Counter) = Settings%YRange(1) + Settings%GridDelta(2)*( J - 1 ) + InflowWind_u1%PositionXYZ(3,Counter) = Settings%ZRange(1) + Settings%GridDelta(3)*( K - 1 ) + Counter = Counter+1 + ENDDO + ENDDO + ENDDO + + ELSE + + ! We are going to set the WindGrid with only a single point at the RefHt so that we can calculate something + InflowWind_u1%PositionXYZ(1,1) = 0.0_ReKi ! X + InflowWind_u1%PositionXYZ(2,1) = 0.0_ReKi ! Y + InflowWind_u1%PositionXYZ(3,1) = InflowWind_InitOut%WindFileInfo%RefHt ! Z + + ENDIF + + + + ! If we read in a list of points from the Points input file, setup the arrays for it. + IF ( SettingsFlags%PointsFile ) THEN + + ! Move the points list + CALL MOVE_ALLOC( PointsXYZ, InflowWind_u2%PositionXYZ ) + + ! Allocate the array for the velocity results -- 3 x Npoints + CALL AllocAry( InflowWind_y2%VelocityUVW, 3, SIZE(InflowWind_u2%PositionXYZ, DIM=2 ), & + "Array of velocities 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 ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( 'Error allocating InflowWind_y2%WriteOutput array.' ) + ENDIF + 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 ) + + ENDIF + + + + + + + + ! FFT setup + IF ( SettingsFlags%FFTcalc ) THEN + + ! Allocate arrays for passing data into and out of IfW -- 3 x 1 size + CALL AllocAry( InflowWind_u3%PositionXYZ, 3, 1, & + "Array for FFT position information", ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ENDIF + + CALL AllocAry( InflowWind_y3%VelocityUVW, 3, 1, & + "Array for FFT position information", ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ENDIF + + ! WriteOutput info + IF ( ALLOCATED(InflowWind_y1%WriteOutput) ) THEN + ALLOCATE( InflowWind_y3%WriteOutput(SIZE(InflowWind_y1%WriteOutput)), STAT=ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( 'Error allocating InflowWind_y2%WriteOutput array.' ) + ENDIF + InflowWind_y3%WriteOutput = InflowWind_y1%WriteOutput + ENDIF + + + + ! Allocate storage for the FFT information +!TODO: allocate space for the FFT data storage at driver level +! FFTDataSetVel(TSteps,3) (TimeIdx,DimIdx) Where DimIdx:= 1=U (velocity in X), 2=V (velocity in Y), 3=W (velocity in Z) +! FFTDataSetFrq(Freqs,3) (FreqIdx,DimIdx) Where DimIdx:= 1=X, 2=Y, 3=Z +! TimeArray(TSteps) (TimeIdx) Array of values for the time -- IS THIS NECESSARY? NOT FOR FFT. +! FreqArray(NumFreqs) (FreqIdx) Array of values for the frequency +!TODO: Use the WindFileTRange and WindFileNumTSteps for the FFT + ENDIF + + + ! Report the rotation of the coordinates. + IF ( IfWDriver_Verbose >= 10_IntKi .AND. InflowWind_p%NWindVel > 0_IntKi ) THEN + CALL WrScr(NewLine//NewLine//' Rotation of coordinates to prime (wind file) coordinates by rotating '// & + TRIM(Num2LStr(R2D*InflowWind_p%PropagationDir))// & + ' degrees (meteorological wind direction change) ...'//NewLine) + CALL WrScr(' ------ WindViXYZ --------- ----- WindViXYZprime -----') + + DO I = 1,InflowWind_p%NWindVel + ErrMsgTmp = '' + ErrMsgTmp = ' '//TRIM(Num2LStr(I))//' ' + ErrMsgTmp = TRIM(ErrMsgTmp)//' ('//TRIM(Num2LStr(InflowWind_p%WindViXYZ(1,I)))// & + ', '//TRIM(Num2LStr(InflowWind_p%WindViXYZ(2,I)))//', '// & + TRIM(Num2LStr(InflowWind_p%WindViXYZ(3,I)))//')' + ErrMsgTmp = ErrMsgTmp(1:40)//'('//TRIM(Num2LStr(InflowWind_p%WindViXYZprime(1,I)))// & + ', '//TRIM(Num2LStr(InflowWind_p%WindViXYZprime(2,I)))//', '// & + TRIM(Num2LStr(InflowWind_p%WindViXYZprime(3,I)))//')' + CALL WrScr(TRIM(ErrMsgTmp)) + ENDDO + CALL WrScr(NewLine) + ENDIF + + + + + + + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Time stepping loop -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + +!TODO: save FFT info +!TODO: output file with data from IfW (on time steps) +!TODO: Summary info + + IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Calling InflowWind_CalcOutput...'//NewLine) + + + DO ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) + + 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) + + + + ! 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 + + + ! 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 ) + + 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 + + ! Get the results from IfW +! CALL InflowWind_CalcOutput() + + ! Copy results over to the array for storage +! FFTdata(ITime,:) = + + + ENDIF + + + ENDDO ! ITime loop + + + + ! output table of results for the outlist comparison and check if very verbose -- print statements are + ! used because we don't want linewrapping. + IF ( IfWDriver_Verbose >= 10_IntKi ) THEN + + write(*,'(A)') NewLine//NewLine//' DiskVel: ( '//TRIM(num2lstr(inflowwind_y1%diskvel(1)))//', '// & + TRIM(num2lstr(inflowwind_y1%diskvel(2)))//', '//TRIM(num2lstr(inflowwind_y1%diskvel(3)))//' )' + write(*,'(A)') NewLine//NewLine//' Requested wind points and writeoutput results at last timestep (t='// & + TRIM(Num2LStr(TimeNow))//'):'//NewLine + write(*,'(A)') ' ------ WindViXYZ --------- ----- WindViUVW --------- -- AllOuts -- '// & + '------------- WriteOutput -------------' + write(*,'(A)') ' Index, coord, name Vector value Value '// & + ' Name Unit OutIndex Value' + DO I = 1,27 + ErrMsgTmp = '' + ErrMsgTmp = ' '//TRIM(Num2LStr(I))//' ' + IF ( InflowWind_p%NWindVel >= (I-1)/3+1 ) THEN + ErrMsgTmp = TRIM(ErrMsgTmp)//' ('//TRIM(Num2LStr(InflowWind_p%WindViXYZ(1,(I-1)/3+1)))// & + ', '//TRIM(Num2LStr(InflowWind_p%WindViXYZ(2,(I-1)/3+1)))//', '// & + TRIM(Num2LStr(InflowWind_p%WindViXYZ(3,(I-1)/3+1)))//')' + ErrMsgTmp = ErrMsgTmp(1:25)//ValidParamAry(I) + ErrMsgTmp = ErrMsgTmp(1:40)//'('//TRIM(Num2LStr(InflowWind_MiscVars%WindViUVW(1,(I-1)/3+1)))// & + ', '//TRIM(Num2LStr(InflowWind_MiscVars%WindViUVW(2,(I-1)/3+1)))//', '// & + TRIM(Num2LStr(InflowWind_MiscVars%WindViUVW(3,(I-1)/3+1)))//')' + + ENDIF + ErrMsgTmp = ErrMsgTmp(1:73)//' '//TRIM(Num2LStr(InflowWind_MiscVars%AllOuts(I))) + DO J = 1, InflowWind_p%NumOuts + IF ( InflowWind_p%OutParam(J)%Indx == I ) THEN + ErrMsgTmp = ErrMsgTmp(1:94)//InflowWind_InitOut%WriteOutputHdr(J)//' '// & + InflowWind_InitOut%WriteOutputUnt(J)//TRIM(Num2LStr(J)) + ErrMsgTmp = ErrMsgTmp(1:126)//TRIM(Num2LStr(InflowWind_y1%WriteOutput(J))) + ENDIF + ENDDO + write(*,'(A)') TRIM(ErrMsgTmp) + ENDDO + ENDIF + + +end if + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Calculate OtherStates -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! Iff we add in some averaging / TI / mean etc, it would be in OtherStates. Right now it doesn't look like we need to do that. + ! -- Test that here. + + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Output results -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + +!FFT calculations occur here. Output to file. + + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- We are done, so close everything down -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + CALL InflowWind_DestroyInitOutput( InflowWind_InitOut, ErrStat, ErrMsg ) + + CALL InflowWind_End( 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 >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' InflowWind_End (1/3) returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(NewLine//' InflowWind_End call 1 of 3: ok') + ENDIF + + + + CALL InflowWind_End( InflowWind_u2, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y2, 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 >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' InflowWind_End (2/3) returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(' InflowWind_End call 2 of 3: ok') + ENDIF + + + + CALL InflowWind_End( InflowWind_u3, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y3, 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 >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' InflowWind_End (3/3) returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(' InflowWind_End call 3 of 3: ok') + ENDIF + + + + CALL DriverCleanup() + +CONTAINS + + SUBROUTINE DriverCleanup() + + + if (Settings%WindGridOutputUnit > -1_IntKi ) CLOSE( Settings%WindGridOutputUnit ) + if (Settings%PointsOutputUnit > -1_IntKi ) CLOSE( Settings%PointsOutputUnit ) + if (Settings%FFTOutputUnit > -1_IntKi ) CLOSE( Settings%FFTOutputUnit ) + + + ! Find out how long this actually took + CALL CPU_TIME( Timer(2) ) + CALL WrScr(NewLine//'Elapsed time: '//TRIM(Num2LStr(Timer(2)-Timer(1)))//' seconds') + + + END SUBROUTINE DriverCleanup + + +END PROGRAM InflowWind_Driver + + + + diff --git a/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Subs.f90 new file mode 100644 index 000000000..c10193ae6 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -0,0 +1,2461 @@ +!********************************************************************************************************************************** +! +! MODULE: InflowWind_Driver_Subs - This module contains subroutines used by the InflowWind Driver program +! +!********************************************************************************************************************************** +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2017 Envision Energy USA +! +! 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 InflowWind_Driver_Subs + + USE NWTC_Library + USE InflowWind_Driver_Types + IMPLICIT NONE + + +CONTAINS +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +SUBROUTINE DispHelpText( ErrStat, ErrMsg ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Print out help information ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + USE NWTC_Library + + IMPLICIT NONE + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Statement about usage + CALL WrScr("") + CALL WrScr(" Syntax: InlowWind_Driver <filename> [options]") + CALL WrScr("") + CALL WrScr(" where: <filename> -- Name of driver input file to use") + CALL WrScr(" options: "//SWChar//"ifw -- treat <filename> as name of InflowWind input file") + 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(" white space delimited FILE") + CALL WrScr(" "//SwChar//"v -- verbose output ") + CALL WrScr(" "//SwChar//"vv -- very verbose output ") + CALL WrScr(" "//SwChar//"HAWC -- convert contents of <filename> to HAWC format ") + CALL WrScr(" "//SwChar//"Bladed -- convert contents of <filename> to Bladed format ") + CALL WrScr(" "//SwChar//"vtk -- convert contents of <filename> to vtk format ") + 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.") + CALL WrScr(" -- If no XRange is specified, assumed to be only at X=0") +! CALL WrScr(" -- Features marked [N/A] have not been implimented in this version.") + CALL WrScr(" -- Options are not case sensitive.") + CALL WrScr("") + + +END SUBROUTINE DispHelpText + + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!> This subroutine retrieves the command line arguments and passes them to the +!! inflowwind_driver_subs::parsearg routine for processing. +SUBROUTINE RetrieveArgs( CLSettings, CLFlags, ErrStat, ErrMsg ) + + USE NWTC_Library + USE InflowWind_Driver_Types + + IMPLICIT NONE + + ! Storing the arguments + TYPE( IfWDriver_Flags ), INTENT( OUT) :: CLFlags !< Flags indicating which command line arguments were specified + TYPE( IfWDriver_Settings ), INTENT( OUT) :: CLSettings !< Command line arguments passed in + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + ! Local variable IF ( CLFlags%Summarys + INTEGER(IntKi) :: i !< Generic counter + CHARACTER(1024) :: Arg !< argument given + CHARACTER(1024) :: ArgUC !< Upper case argument to check + INTEGER(IntKi) :: NumInputArgs !< Number of argements passed in from command line + LOGICAL :: ifwFlag !< The -ifw flag was set + CHARACTER(1024) :: FileName !< Filename from the command line. + LOGICAL :: FileNameGiven !< Flag indicating if a filename was given. + + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status (for calls) + CHARACTER(1024) :: ErrMsgTmp !< Temporary error message (for calls) + + + ! initialize some things + CLFlags%DvrIptFile = .FALSE. + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + ifwFlag = .FALSE. + FileNameGiven = .FALSE. + FileName = '' + + + ! Check how many arguments are passed in + NumInputArgs = COMMAND_ARGUMENT_COUNT() + + ! exit if we don't have enough + IF (NumInputArgs == 0) THEN + CALL SetErrStat(ErrID_Fatal," Insufficient Arguments. Use option "//SwChar//"help for help menu.", & + ErrStat,ErrMsg,'RetrieveArgs') + RETURN + ENDIF + + + ! Loop through all the arguments, and store them + DO i=1,NumInputArgs + ! get the ith argument + CALL get_command_argument(i, Arg) + ArgUC = Arg + + ! convert to uppercase + CALL Conv2UC( ArgUC ) + + + ! Check to see if it is a control parameter or the filename + IF ( INDEX( SwChar, ArgUC(1:1) ) > 0 ) THEN + + ! check to see if we asked for help + IF ( ArgUC(2:5) == "HELP" ) THEN + CALL DispHelpText( ErrStat, ErrMsg ) + CALL ProgExit(0) + ENDIF + + + ! Check the argument and put it where it belongs + ! chop the SwChar off before passing the argument + CALL ParseArg( CLSettings, CLFlags, ArgUC(2:), Arg(2:), ifwFlag, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'RetrieveArgs') + IF (ErrStat>AbortErrLev) RETURN + + ELSE + + ! since there is no switch character, assume it is the filename, unless we already set one + IF ( FileNameGiven ) THEN + CALL SetErrStat(ErrID_Fatal," Multiple driver input filenames given: "//TRIM(FileName)//", "//TRIM(Arg), & + ErrStat,ErrMsg,'RetrieveArgs') + RETURN + ELSE + FileName = TRIM(Arg) + FileNameGiven = .TRUE. + ENDIF + + ENDIF + END DO + + + ! Was a filename given? + IF ( .NOT. FileNameGiven ) THEN + CALL SetErrStat( ErrID_Fatal, " No filename given.", ErrStat, ErrMsg, 'RetrieveArgs' ) + RETURN + ENDIF + + ! Was the -ifw flag set? If so, the filename is the InflowWind input file. Otherwise + ! it is the driver input file. + IF ( ifwFlag ) THEN + CLSettings%IfWIptFileName = TRIM(FileName) + CLFlags%IfWIptFile = .TRUE. + ELSE + CLSettings%DvrIptFileName = TRIM(FileName) + CLFlags%DvrIptFile = .TRUE. + ENDIF + + + + !------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + CONTAINS + + + !------------------------------------------------------------------------------- + FUNCTION StringToReal( StringIn, ErrStat ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Convert a string to a real number ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + IMPLICIT NONE + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Input + CHARACTER(*), INTENT(IN ) :: StringIn + + ! Returned value + REAL(ReKi) :: StringToReal + + ! Local Variables + INTEGER(IntKi) :: ErrStatTmp ! Temporary variable to hold the error status + + read( StringIn, *, iostat=ErrStatTmp) StringToReal + + ! If that isn't a number, only warn since we can continue by skipping this value + IF ( ErrStatTmp .ne. 0 ) ErrStat = ErrID_Warn + + END FUNCTION StringToReal + + + + !------------------------------------------------------------------------------- + SUBROUTINE ParseArg( CLSettings, CLFlags, ThisArgUC, ThisArg, ifwFlagSet, ErrStat, ErrMsg ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Parse and store the input argument ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + USE NWTC_Library + USE InflowWind_Driver_Types + USE InflowWind_Types + + IMPLICIT NONE + + ! Storing the arguments + TYPE( IfWDriver_Flags ), INTENT(INOUT) :: CLFlags ! Flags indicating which arguments were specified + TYPE( IfWDriver_Settings ), INTENT(INOUT) :: CLSettings ! Arguments passed in + + CHARACTER(*), INTENT(IN ) :: ThisArgUC ! The current argument (upper case for testing) + CHARACTER(*), INTENT(IN ) :: ThisArg ! The current argument (as passed in for error messages) + LOGICAL, INTENT(INOUT) :: ifwFlagSet ! Was the -ifw flag given? + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + + ! local variables + INTEGER(IntKi) :: Delim1 ! where the [ is + INTEGER(IntKi) :: Delim2 ! where the ] is + INTEGER(IntKi) :: DelimSep ! where the : is + INTEGER(IntKi) :: DelimSep2 ! where the : is + INTEGER(IntKi) :: DelimSep3 ! where the : is + REAL(ReKi) :: TempReal ! temp variable to hold a real + + INTEGER(IntKi) :: ErrStatTmp ! Temporary error status for calls + + + + ! Initialize some things + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + + ! Get the delimiters -- returns 0 if there isn't one + Delim1 = INDEX(ThisArgUC,'[') + Delim2 = INDEX(ThisArgUC,']') + DelimSep = INDEX(ThisArgUC,':') + + + ! check that if there is an opening bracket, then there is a closing one + IF ( (Delim1 > 0_IntKi ) .and. (Delim2 < Delim1) ) THEN + CALL SetErrStat(ErrID_Warn," Syntax error in option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArg') + RETURN + ENDIF + + ! check that if there is a colon, then there are brackets + IF ( (DelimSep > 0_IntKi) .and. (Delim1 == 0_IntKi) ) THEN + CALL SetErrStat(ErrID_Warn," Syntax error in option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArg') + RETURN + ENDIF + + + ! If no delimeters were given, than this option is simply a flag + IF ( Delim1 == 0_IntKi ) THEN + ! check to see if the filename is the name of the IfW input file + IF ( TRIM(ThisArgUC) == "IFW" ) THEN + ifwFlagSet = .TRUE. ! More logic in the routine that calls this one to set things. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "SUM" ) THEN + CLFlags%Summary = .TRUE. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "VV" ) THEN + CLFlags%VVerbose = .TRUE. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "V" ) THEN + CLFlags%Verbose = .TRUE. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "HAWC" ) THEN + CLFlags%WrHAWC = .TRUE. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "BLADED" ) THEN + CLFlags%WrBladed = .TRUE. + RETURN + ELSEIF ( TRIM(ThisArgUC) == "VTK" ) THEN + CLFlags%WrVTK = .TRUE. + RETURN + ELSE + CALL SetErrStat( ErrID_Warn," Unrecognized option '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options.", & + ErrStat,ErrMsg,'ParseArg') + ENDIF + + ENDIF + + + + ! "FFT[X,Y,Z]" + IF ( ThisArgUC(1:Delim1) == "FFT[" ) THEN + DelimSep = INDEX(ThisArgUC,',') + DelimSep2= INDEX(ThisArgUC(DelimSep+1:),',') + DelimSep + IF ( DelimSep2 <= DelimSep ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArg') + RETURN + ENDIF + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%FFTcalc = .TRUE. + CLSettings%FFTcoord(1) = TempReal + ELSE + CLFlags%FFTcalc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, 'ParseArg') + ELSE + CALL SetErrStat(ErrID_FATAL," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:DelimSep2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%FFTcalc = .TRUE. + CLSettings%FFTcoord(2) = TempReal + ELSE + CLFlags%FFTcalc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, 'ParseArg') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Third Value + TempReal = StringToReal( ThisArgUC(DelimSep2+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%FFTcalc = .TRUE. + CLSettings%FFTcoord(3) = TempReal + ELSE + CLFlags%FFTcalc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, 'ParseArg') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + IF ( CLSettings%FFTcoord(3) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn,' FFT coordinate ['//TRIM(Num2LStr(CLSettings%FFTcoord(1)))//','// & + TRIM(Num2LStr(CLSettings%FFTcoord(1)))//','//TRIM(Num2LStr(CLSettings%FFTcoord(1)))// & + '] is at or below ground level where there is no wind. Ingoring.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL' ) + CLFlags%FFTcalc = .FALSE. + ENDIF + + ! "XRANGE[#:#]" + ELSEIF ( ThisArgUC(1:Delim1) == "XRANGE[" ) THEN + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%XRange = .TRUE. + CLSettings%XRange(1) = TempReal + ELSE + CLFlags%XRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%XRange = .TRUE. + CLSettings%XRange(2) = TempReal + ELSE + CLFlags%XRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Check the order of values + IF ( CLSettings%XRange(1) > CLSettings%Xrange(2) ) THEN + CLSettings%XRange(1) = 0.0 + CLSettings%XRange(2) = 0.0 + CLFlags%XRange = .FALSE. + CALL SetErrStat(ErrID_Warn," Unexpected order of values in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, 'ParseArgs') + ENDIF + + + + ! "YRANGE[#:#]" + ELSEIF ( ThisArgUC(1:Delim1) == "YRANGE[" ) THEN + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%YRange = .TRUE. + CLSettings%YRange(1) = TempReal + ELSE + CLFlags%YRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%YRange = .TRUE. + CLSettings%YRange(2) = TempReal + ELSE + CLFlags%YRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Check the order of values + IF ( CLSettings%YRange(1) > CLSettings%Yrange(2) ) THEN + CLSettings%YRange(1) = 0.0 + CLSettings%YRange(2) = 0.0 + CLFlags%YRange = .FALSE. + CALL SetErrStat(ErrID_Warn," Unexpected order of values in option '"//SwChar//TRIM(ThisArg)//"'. Ingoring.", & + ErrStat, ErrMsg, 'ParseArgs') + ENDIF + + + + ! "ZRANGE[#:#]" + ELSEIF ( ThisArgUC(1:Delim1) == "ZRANGE[" ) THEN + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%ZRange = .TRUE. + CLSettings%ZRange(1) = TempReal + ELSE + CLFlags%ZRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%ZRange = .TRUE. + CLSettings%ZRange(2) = TempReal + ELSE + CLFlags%ZRange = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + ! Check the order of values + IF ( CLSettings%ZRange(1) > CLSettings%Zrange(2) ) THEN + CLSettings%ZRange(1) = 0.0 + CLSettings%ZRange(2) = 0.0 + CLFlags%ZRange = .FALSE. + CALL SetErrStat(ErrID_Warn," Unexpected order of values in option '"//SwChar//TRIM(ThisArg)//"'. Ingoring.", & + ErrStat, ErrMsg, 'ParseArgs') + ENDIF + + + ! "DX[#]" + ELSEIF( ThisArgUC(1:Delim1) == "DX[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%Dx = .TRUE. + CLSettings%GridDelta(1) = abs(TempReal) + ELSE + CLFlags%Dx = .FALSE. + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + ! "DY[#]" + ELSEIF( ThisArgUC(1:Delim1) == "DY[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%Dy = .TRUE. + CLSettings%GridDelta(2) = abs(TempReal) + ELSE + CLFlags%Dy = .FALSE. + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + ! "DZ[#]" + ELSEIF( ThisArgUC(1:Delim1) == "DZ[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%Dz = .TRUE. + CLSettings%GridDelta(3) = abs(TempReal) + ELSE + CLFlags%Dz = .FALSE. + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + ! "DT[#]" + ELSEIF( ThisArgUC(1:Delim1) == "DT[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%Dt = .TRUE. + CLSettings%DT = abs(TempReal) + ELSE + CLFlags%Dt = .FALSE. + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + ! "TSTEPS[#]" + ELSEIF( ThisArgUC(1:Delim1) == "TSTEPS[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%NumTimeSteps = .TRUE. + CLSettings%NumTimeSteps = nint(abs(TempReal)) + ELSE + CLFlags%NumTimeSteps = .FALSE. + CLSettings%NumTimeSteps = 1_IntKi + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + + ! "TSTART[#]" + ELSEIF( ThisArgUC(1:Delim1) == "TSTART[" ) THEN + TempReal = StringToReal( ThisArgUC(Delim1+1:Delim2-1), ErrStat ) + IF ( ErrStat == ErrID_None ) THEN + CLFlags%TStart = .TRUE. + CLSettings%TStart = abs(TempReal) + ELSE + CLFlags%TStart = .FALSE. + IF ( ErrStat == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,'ParseArgs') + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, 'ParseArg') + ENDIF + RETURN + ENDIF + + + + ! "POINTS[FILE]" + ELSEIF( ThisArgUC(1:Delim1) == "POINTS[" ) THEN + CLFlags%PointsFile = .TRUE. + CLSettings%PointsFileName = ThisArg(Delim1+1:Delim2-1) + ELSE + ErrMsg = " Unrecognized option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options." + ErrStat = ErrID_Warn + ENDIF + + END SUBROUTINE ParseArg + !------------------------------------------------------------------------------- + + + +END SUBROUTINE RetrieveArgs + + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!> This subroutine reads the driver input file and sets up the flags and settings +!! for the driver code. Any settings from the command line options will override +!! this. +SUBROUTINE ReadDvrIptFile( DvrFileName, DvrFlags, DvrSettings, ProgInfo, ErrStat, ErrMsg ) + + CHARACTER(1024), INTENT(IN ) :: DvrFileName + TYPE(IfWDriver_Flags), INTENT(INOUT) :: DvrFlags + TYPE(IfWDriver_Settings), INTENT(INOUT) :: DvrSettings + TYPE(ProgDesc), INTENT(IN ) :: ProgInfo + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER(IntKi) :: UnIn ! Unit number for the driver input file + CHARACTER(1024) :: FileName ! Name of InflowWind driver input file + + ! Input file echoing + LOGICAL :: EchoFileContents ! Do we echo the driver file out or not? + INTEGER(IntKi) :: UnEchoLocal ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFileName ! Name of InflowWind driver echo file + + ! Time steps + CHARACTER(1024) :: NumTimeStepsChr ! Character string for number of timesteps (to handle DEFAULT value) + CHARACTER(1024) :: DTChr ! Character string for timesteps size (to handle DEFAULT value) + + ! Gridded data + INTEGER(IntKi) :: TmpIntAr3(3) ! Temporary array for reading in a pair of integer values from the input file + REAL(ReKi) :: TmpRealAr3(3) ! Temporary array for reading in a pair of real values from the input file + REAL(ReKi) :: GridCtrCoord(3) ! Center coordinate of the grid read in + + + ! Local error handling + INTEGER(IntKi) :: ios !< I/O status + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + CHARACTER(1024) :: ErrMsgTmp !< Temporary error messages for calls + CHARACTER(*), PARAMETER :: RoutineName = 'ReadDvrIptFile' + CHARACTER(1024) :: PriPath ! Path name of the primary file + + ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input + UnEchoLocal = -1 + + FileName = TRIM(DvrFileName) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile( UnIn, FileName, ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,' Failed to open InflowWind Driver input file: '//FileName, & + ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL WrScr( 'Opening InflowWind Driver input file: '//FileName ) + + CALL GetPath( FileName, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName,' InflowWind Driver input file header line 1', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL ReadCom( UnIn, FileName, 'InflowWind Driver input file header line 2', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Echo Input Files. + CALL ReadVar ( UnIn, FileName, EchoFileContents, 'Echo', 'Echo Input', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( EchoFileContents ) THEN + + EchoFileName = TRIM(FileName)//'.ech' + CALL GetNewUnit( UnEchoLocal ) + CALL OpenEcho ( UnEchoLocal, EchoFileName, ErrStatTmp, ErrMsgTmp, ProgInfo ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + REWIND(UnIn) + + + ! Reread and echo + CALL ReadCom( UnIn, FileName,' InflowWind Driver input file header line 1', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL ReadCom( UnIn, FileName, 'InflowWind Driver input file header line 2', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Echo Input Files. + CALL ReadVar ( UnIn, FileName, EchoFileContents, 'Echo', 'Echo Input', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Driver setup section + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,' Driver setup section, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Name of InflowWind input file + CALL ReadVar( UnIn, FileName,DvrSettings%IfWIptFileName,'IfWIptFileName',' InflowWind input filename', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ELSE + DvrFlags%IfWIptFile = .TRUE. + ENDIF + + IF ( PathIsRelative( DvrSettings%IfWIptFileName ) ) DvrSettings%IfWIptFileName = TRIM(PriPath)//TRIM(DvrSettings%IfWIptFileName) + + !------------------------------------------------------------------------------------------------- + ! File Conversion Options section + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,'File Conversion Options Section Header', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + CALL SetErrStat(ErrStatTmp, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + ! WrHAWC + CALL ReadVar( UnIn, FileName, DvrFlags%WrHAWC, 'WrHAWC', 'Convert wind data to HAWC2 format?', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + CALL SetErrStat(ErrStatTmp, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + ! WrBladed + CALL ReadVar( UnIn, FileName, DvrFlags%WrBladed, 'WrBladed', 'Convert wind data to Bladed format?', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + CALL SetErrStat(ErrStatTmp, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + ! WrVTK + CALL ReadVar( UnIn, FileName, DvrFlags%WrVTK, 'WrVTK', 'Convert wind data to VTK format?', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + CALL SetErrStat(ErrStatTmp, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! Tests of Interpolation Options section + !------------------------------------------------------------------------------------------------- + CALL ReadCom( UnIn, FileName,'Tests of Interpolation Options Section Header', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + CALL SetErrStat(ErrStatTmp, ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + ! Number of timesteps + CALL ReadVar( UnIn, FileName,NumTimeStepsChr,'NumTimeStepsChr',' Character string for number of timesteps to read.', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Check if we asked for the DEFAULT (use what is in the file) + CALL Conv2UC( NumTimeStepsChr ) + IF ( TRIM(NumTimeStepsChr) == 'DEFAULT' ) THEN ! we asked for the default value + DvrFlags%NumTimeSteps = .TRUE. + DvrFlags%NumTimeStepsDefault = .TRUE. ! This flag tells us to use the inflow wind file values + ELSE + ! We probably have a number if it isn't 'DEFAULT', so do an internal read and check to + ! make sure that it was appropriately interpretted. + READ (NumTimeStepsChr,*,IOSTAT=IOS) DvrSettings%NumTimeSteps + IF ( IOS /= 0 ) THEN ! problem in the read, so parse the error. + CALL CheckIOS ( IOS, '', 'NumTimeSteps',NumType, ErrStatTmp, ErrMsgTmp ) + RETURN + ELSE ! Was ok, so set the flags + DvrFlags%NumTimeSteps = .TRUE. + DvrFlags%NumTimeStepsDefault = .FALSE. + ENDIF + ENDIF + + + ! TStart -- start time + CALL ReadVar( UnIn, FileName,DvrSettings%TStart,'TStart',' Time in wind file to start parsing.', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ELSE + DvrFlags%TStart = .TRUE. + ENDIF + + + ! DT -- Timestep size for the driver to take (or DEFAULT for what the file contains) + CALL ReadVar( UnIn, FileName,DTChr,'DTChr',' Character string for Timestep size for the driver to take (or DEFAULT for what the file contains).', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Check if we asked for the DEFAULT (use what is in the file) + CALL Conv2UC( DTChr ) + IF ( TRIM(DTChr) == 'DEFAULT' ) THEN ! we asked for the default value + DvrFlags%DT = .TRUE. + DvrFlags%DTDefault = .TRUE. ! This flag tells us to use the inflow wind file values + ELSE + ! We probably have a number if it isn't 'DEFAULT', so do an internal read and check to + ! make sure that it was appropriately interpretted. + READ (DTChr,*,IOSTAT=IOS) DvrSettings%DT + IF ( IOS /= 0 ) THEN ! problem in the read, so parse the error. + CALL CheckIOS ( IOS, '', 'DT',NumType, ErrStatTmp, ErrMsgTmp ) + RETURN + ELSE ! Was ok, so set the flags + DvrFlags%DT = .TRUE. + DvrFlags%DTDefault = .FALSE. + ENDIF + ENDIF + + + ! Summarize the extents in the windfile + CALL ReadVar( UnIn, FileName,DvrFlags%Summary,'Summary',' Summarize data extents in the windfile', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN +! ELSE +! DvrFlags%Summary = .TRUE. + ENDIF + + + ! Summarize everything in a summary file/ + CALL ReadVar( UnIn, FileName,DvrFlags%SummaryFile,'SummaryFile',' Summarize the results in a .sum file', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN +! ELSE +! DvrFlags%SummaryFile = .TRUE. + ENDIF + + + +#ifdef UNUSED_INPUTFILE_LINES + !------------------------------------------------------------------------------------------------- + ! FFT calculations + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,' FFT calculations, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! FFTcalc -- FFTcalc of the windfield needed. + CALL ReadVar( UnIn, FileName,DvrFlags%FFTcalc,'FFTcalc',' Perform an FFT?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Read the coordinate for the FFT if the flag is set, otherwise skip the line + IF ( DvrFlags%FFTcalc ) THEN + ! FFTcoord -- The coordinates to perform the FFT at + CALL ReadAry ( UnIn, FileName, DvrSettings%FFTcoord, 3, 'FFTcoord', & + 'FFT coordinate', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ELSE + CALL ReadCom( UnIn, FileName,' Skipping the FFT coordinate since not doint an FFT.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ENDIF + +#endif + + !------------------------------------------------------------------------------------------------- + ! points file input + !------------------------------------------------------------------------------------------------- + + ! Header line + CALL ReadCom( UnIn, FileName,' Points file input, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! PointsFile -- Read a points file + CALL ReadVar( UnIn, FileName,DvrFlags%PointsFile,'PointsFile',' Read a points file?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Points input file (unused if .not. DvrFlags%PointsFile) + CALL ReadVar( UnIn, FileName,DvrSettings%PointsFileName,'PointsFileName',' Points file input filename', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + IF ( PathIsRelative( DvrSettings%PointsFileName ) ) DvrSettings%PointsFileName = TRIM(PriPath)//TRIM(DvrSettings%PointsFileName) + + + + !------------------------------------------------------------------------------------------------- + ! gridded data output + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,' Gridded data output, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! WindGrid -- Gridded data output + CALL ReadVar( UnIn, FileName,DvrFlags%WindGrid,'WindGrid',' Output a grid of data?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Read the coordinate for the FFT if the flag is set, otherwise skip the line + IF ( DvrFlags%WindGrid ) THEN + + ! GridCtrCoord -- The coordinates to center the gridded data at + CALL ReadAry ( UnIn, FileName, GridCtrCoord, 3, 'GridCtrCoord', & + 'Coordinate of the center of the gridded data', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Read the DY and DZ stepsize + CALL ReadAry ( UnIn, FileName, TmpRealAr3, 3, 'GridDX, GridDY, GridDZ', & + 'GridDX, GridDY, GridDZ', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Save the DY and DZ values + DvrSettings%GridDelta(1) = abs(TmpRealAr3(1)) ! X direction + DvrSettings%GridDelta(2) = abs(TmpRealAr3(2)) ! Y direction + DvrSettings%GridDelta(3) = abs(TmpRealAr3(3)) ! Z direction + DvrFlags%Dx = .TRUE. ! read in value for the X direction gridding + DvrFlags%Dy = .TRUE. ! read in value for the Y direction gridding + DvrFlags%Dz = .TRUE. ! read in value for the Z direction gridding + + + ! Read the number of points in the Y and Z directions + CALL ReadAry ( UnIn, FileName, TmpIntAr3, 3, 'GridNx, GridNY, GridNZ', & + 'GridNx, GridNY, GridNZ', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Save the GridNY and GridNZ values + DvrSettings%GridN(1) = TmpIntAr3(1) ! X direction + DvrSettings%GridN(2) = TmpIntAr3(2) ! Y direction + DvrSettings%GridN(3) = TmpIntAr3(3) ! Z direction + DvrFlags%XRange = .TRUE. ! read in value for the X direction gridding + DvrFlags%YRange = .TRUE. ! read in value for the Y direction gridding + DvrFlags%ZRange = .TRUE. ! read in value for the Z direction gridding + + + + ! Check that valid values of Dx, Dy, and Dz were read in. + ! Check GridDx + IF ( EqualRealNos(DvrSettings%GridDelta(1), 0.0_ReKi) ) THEN + DvrFlags%Dx = .FALSE. + DvrFlags%XRange = .FALSE. + DvrSettings%GridDelta(1) = 0.0_ReKi + CALL SetErrStat(ErrID_Warn,' Grid spacing in X direction is 0. Ignoring.',ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check GridDy + IF ( EqualRealNos(DvrSettings%GridDelta(2), 0.0_ReKi) ) THEN + DvrFlags%Dy = .FALSE. + DvrFlags%YRange = .FALSE. + DvrSettings%GridDelta(2) = 0.0_ReKi + CALL SetErrStat(ErrID_Warn,' Grid spacing in Y direction is 0. Ignoring.',ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check GridDz + IF ( EqualRealNos(DvrSettings%GridDelta(3), 0.0_ReKi) ) THEN + DvrFlags%Dz = .FALSE. + DvrFlags%ZRange = .FALSE. + DvrSettings%GridDelta(3) = 0.0_ReKi + CALL SetErrStat(ErrID_Warn,' Grid spacing in Z direction is 0. Ignoring.',ErrStat,ErrMsg,RoutineName) + ENDIF + + + ! Now need to set the XRange, YRange, and ZRange values based on what we read in + ! For XRange, check that we have an actual value for the number of points + IF ( (DvrSettings%GridN(1) <= 0) .OR. (.NOT. DvrFlags%XRange) ) THEN + DvrSettings%XRange = GridCtrCoord(1) + DvrFlags%Dx = .FALSE. + DvrFlags%XRange = .FALSE. + + IF ( DvrSettings%GridN(1) < 0 ) THEN + CALL SetErrStat(ErrID_Warn,' Negative number for number of grid points along X direction. Ignoring.',ErrStat,ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_Warn,' No points along X direction. Ignoring.',ErrStat,ErrMsg, RoutineName) + ENDIF + + DvrSettings%GridN(1) = 1_IntKi ! Set to 1 for easier indexing. + + ELSE + ! Set the XRange values + DvrSettings%XRange(1) = GridCtrCoord(1) - (REAL(DvrSettings%GridN(1) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(1) + DvrSettings%XRange(2) = GridCtrCoord(1) + (REAL(DvrSettings%GridN(1) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(1) + DvrFlags%XRange = .TRUE. + ENDIF + + + ! For YRange, check that we have an actual value for the number of points + IF ( (DvrSettings%GridN(2) <= 0) .OR. (.NOT. DvrFlags%YRange) ) THEN + DvrSettings%YRange = GridCtrCoord(2) + DvrFlags%Dy = .FALSE. + DvrFlags%YRange = .FALSE. + + IF ( DvrSettings%GridN(2) < 0 ) THEN + CALL SetErrStat(ErrID_Warn,' Negative number for number of grid points along Y direction. Ignoring.',ErrStat,ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_Warn,' No points along Y direction. Ignoring.',ErrStat,ErrMsg, RoutineName) + ENDIF + + DvrSettings%GridN(2) = 1_IntKi ! Set to 1 for easier indexing. + + ELSE + ! Set the YRange values + DvrSettings%YRange(1) = GridCtrCoord(2) - (REAL(DvrSettings%GridN(2) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(2) + DvrSettings%YRange(2) = GridCtrCoord(2) + (REAL(DvrSettings%GridN(2) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(2) + DvrFlags%YRange = .TRUE. + ENDIF + + ! For ZRange, check that we have an actual value for the number of points, set to ctr point if negative or zero. + IF ( (DvrSettings%GridN(3) <= 0) .OR. (.NOT. DvrFlags%ZRange) ) THEN + DvrSettings%ZRange = abs(GridCtrCoord(3)) ! shouldn't have a negative value anyhow + DvrFlags%Dz = .FALSE. + DvrFlags%ZRange = .FALSE. + + IF ( DvrSettings%GridN(3) < 0 ) THEN + CALL SetErrStat(ErrID_Warn,' Negative number for number of grid points along Z direction. Ignoring.',ErrStat,ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_Warn,' No points along Z direction. Ignoring.',ErrStat,ErrMsg, 'ReadDvrIptFile') + ENDIF + + DvrSettings%GridN(3) = 1_IntKi ! Set to 1 for easier indexing. + + ELSE + ! Set the ZRange values + DvrSettings%ZRange(1) = GridCtrCoord(3) - (REAL(DvrSettings%GridN(3) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(3) + DvrSettings%ZRange(2) = GridCtrCoord(3) + (REAL(DvrSettings%GridN(3) - 1_IntKi ) / 2.0_ReKi ) * DvrSettings%GridDelta(3) + DvrFlags%ZRange = .TRUE. + ENDIF + + + ELSE ! read these lines as comments (actually, we don't need to read them) + + + DvrSettings%GridDelta = 0.0_ReKi + DvrFlags%Dx = .FALSE. + DvrFlags%Dy = .FALSE. + DvrFlags%Dz = .FALSE. + + DvrSettings%GridN = 0.0_ReKi + DvrFlags%XRange = .FALSE. + DvrFlags%YRange = .FALSE. + DvrFlags%ZRange = .FALSE. + + ! Skip the next three entries of the gridded data section. + CALL ReadCom( UnIn, FileName,' Skipping the gridded data section since not calculating it.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the gridded data section since not calculating it.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the gridded data section since not calculating it.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ENDIF + + + + ! Close the echo and input file + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + + +CONTAINS + + !---------------------------------------------------------------------------------------------------- + !> The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + !! any existing echo information + SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) + LOGICAL, INTENT(IN ) :: EchoFlag ! local version of echo flag + INTEGER(IntKi), INTENT(IN ) :: UnEcho ! echo unit number + + ! Close this module's echo file + IF ( EchoFlag ) THEN + CLOSE(UnEcho) + ENDIF + END SUBROUTINE CleanupEchoFile + + + +END SUBROUTINE ReadDvrIptFile + + +!> This subroutine copies an command line (CL) settings over to the program settings. Warnings are +!! issued if anything is changed from what the driver input file requested. +SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVRIPT, ErrStat, ErrMsg ) + + TYPE(IfWDriver_Flags), INTENT(INOUT) :: DvrFlags + TYPE(IfWDriver_Settings), INTENT(INOUT) :: DvrSettings + TYPE(IfWDriver_Flags), INTENT(IN ) :: CLFlags + TYPE(IfWDriver_Settings), INTENT(IN ) :: CLSettings + LOGICAL, INTENT(IN ) :: DVRIPT + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + + ! Local variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + CHARACTER(1024) :: ErrMsgTmp !< Temporary error status for calls + LOGICAL :: WindGridModify !< Did we modify any of the WindGrid related settings? + + ! Initialization + WindGridModify = .FALSE. + + ! Initialize the error handling + ErrStat = ErrID_None + ErrMsg = '' + ErrStatTmp = ErrID_None + ErrMsgTmp = '' + + + DvrFlags%WrHAWC = DvrFlags%WrHAWC .or. CLFlags%WrHAWC ! create file if specified in either place + 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 + +! ! 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 + + !-------------------------------------------- + ! Did we change any time information? + !-------------------------------------------- + + ! Check TStart + IF ( CLFlags%TStart ) THEN + IF ( DvrFlags%TStart .AND. ( .NOT. EqualRealNos(DvrSettings%TStart, CLSettings%TStart) ) ) THEN + CALL SetErrStat( ErrID_Warn, ' Overriding driver input value for TStart with '//TRIM(Num2LStr(CLSettings%TStart))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ELSE + DvrFlags%TStart = .TRUE. + ENDIF + DvrSettings%TStart = CLSettings%TStart + ENDIF + + ! Check DT + IF ( CLFlags%DT ) THEN + IF ( DvrFlags%DT .AND. ( .NOT. EqualRealNos(DvrSettings%DT, CLSettings%DT) ) ) THEN + CALL SetErrStat( ErrID_Warn, ' Overriding driver input value for DT with '//TRIM(Num2LStr(CLSettings%DT))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ELSE + DvrFlags%DT = .TRUE. + ENDIF + DvrSettings%DT = CLSettings%DT + DvrFlags%DTDefault = .FALSE. + ENDIF + + ! Check NumTimeSteps + IF ( CLFlags%NumTimeSteps ) THEN + IF ( DvrFlags%NumTimeSteps .AND. ( DvrSettings%NumTimeSteps /= CLSettings%NumTimeSteps ) ) THEN + CALL SetErrStat( ErrID_Warn, ' Overriding driver input value for NumTimeSteps with '// & + TRIM(Num2LStr(CLSettings%NumTimeSteps))//'.',& + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ELSE + DvrFlags%NumTimeSteps = .TRUE. + ENDIF + DvrSettings%NumTimeSteps = CLSettings%NumTimeSteps + DvrFlags%NumTimeStepsDefault = .FALSE. + ENDIF + + ! Make sure there is at least one timestep + DvrSettings%NumTimeSteps = MAX(DvrSettings%NumTimeSteps,1_IntKi) + + + !-------------------------------------------- + ! Did we change the ranges for the WindGrid? + !-------------------------------------------- + + ! XRange -- There are three bits of information required for the full specification of the Y + ! data: Dx, XRange, and Ny (the number of steps). In the driver input file, Dx and Ny are + ! given, and XRange is calculated using the specified center point. From the command line, + ! Dx, and XRange are specified. + ! In order for the command line values to be used, we must know which were specified or not + ! as it will change the values we use for calculating. + ! + ! First, check if WindGrid is set. If not, set it. + ! + ! XRange Dx What to change + ! y n Assume Dx good. Calculate new Ny. Increase XRange(2) if necessary and warn. + ! n y Assume XRange good (if Ny == 0, issue warning about no points, set to none) + ! y y Calculate Nx from XRange and Dx, reset XRange(2) after calculating (extend + ! a bit if necessary). Also set WindGrid to true if it is false. + ! n n Nothing. + ! + + IF ( CLFlags%XRange .AND. ( .NOT. CLFlags%Dx ) ) THEN + + DvrFlags%Dx = .TRUE. + DvrFlags%XRange = .TRUE. + WindGridModify = .TRUE. + + ! Calculate new Nx. + DvrSettings%XRange(1) = minval(CLSettings%XRange) ! just in case the order is funky + DvrSettings%XRange(2) = maxval(CLSettings%XRange) + + ! Set number of points in X direction + DvrSettings%GridN(1) = CEILING( abs( ( DvrSettings%XRange(2) - DvrSettings%XRange(1) ) / DvrSettings%GridDelta(1) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%XRange(2)= DvrSettings%XRange(1) + ( DvrSettings%GridN(1) - 1_IntKi ) * DvrSettings%GridDelta(2) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%XRange(2),maxval(CLSettings%XRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of XRange to '//TRIM(Num2LStr(DvrSettings%XRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(1)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(1)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + +! ! Only the XRange was specfied, so throw warning and don't change anything. +! CALL SetErrStat( ErrID_Warn, ' XRange argument given, but no Dx. Ignoring since no points to calculate.', & +! ErrStat,ErrMsg,'UpdateSettingsWithCL') +! DvrFlags%XRange = .FALSE. ! Should already be false, but just in case +! DvrFlags%Dx = .FALSE. ! Should already be false, but just in case + + ELSEIF ( ( .NOT. CLFlags%XRange ) .AND. CLFlags%Dx ) THEN + + ! Only Dx was specfied, so throw warning and don't change anything. + CALL SetErrStat( ErrID_Warn, ' Dx argument given, but no XRange. Ignoring since no points to calculate.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + DvrFlags%XRange = .FALSE. ! Should already be false, but just in case + DvrFlags%Dx = .FALSE. ! Should already be false, but just in case + + ELSEIF ( CLFlags%XRange .AND. CLFlags%Dx ) THEN + + DvrFlags%Dx = .TRUE. + DvrFlags%XRange = .TRUE. + WindGridModify = .TRUE. + + ! Copy over the range and stepsize + DvrSettings%XRange(1) = minval(CLSettings%XRange) ! just in case the order is funky + DvrSettings%XRange(2) = maxval(CLSettings%XRange) + DvrSettings%GridDelta(1) = abs(CLSettings%GridDelta(1)) ! just in case there was a negative number + + ! Set number of points in X direction + DvrSettings%GridN(1) = CEILING( abs( ( DvrSettings%XRange(2) - DvrSettings%XRange(1) ) / DvrSettings%GridDelta(1) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%XRange(2)= DvrSettings%XRange(1) + ( DvrSettings%GridN(1) - 1_IntKi ) * DvrSettings%GridDelta(1) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%XRange(2),maxval(CLSettings%XRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of XRange to '//TRIM(Num2LStr(DvrSettings%XRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(1)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(1)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ELSE + ! Nothing was specified, so we don't do anything + ENDIF + + + + ! YRange -- There are three bits of information required for the full specification of the Y + ! data: Dy, YRange, and Ny (the number of steps). In the driver input file, Dy and Ny are + ! given, and YRange is calculated using the specified center point. From the command line, + ! Dy, and YRange are specified. + ! In order for the command line values to be used, we must know which were specified or not + ! as it will change the values we use for calculating. + ! + ! First, check if WindGrid is set. If not, set it. + ! + ! YRange Dy What to change + ! y n Assume Dy good. Calculate new Ny. Increase YRange(2) if necessary and warn. + ! n y Assume YRange good (if Ny == 0, issue warning about no points, set to none) + ! y y Calculate new Ny. Increase Yrange(2) if necessary and warn. + ! n n Nothing to do. leave alone. + ! + + IF ( CLFlags%YRange .AND. ( .NOT. CLFlags%Dy ) ) THEN + + DvrFlags%Dy = .TRUE. + DvrFlags%YRange = .TRUE. + WindGridModify = .TRUE. + + ! Calculate new Ny. + DvrSettings%YRange(1) = minval(CLSettings%YRange) ! just in case the order is funky + DvrSettings%YRange(2) = maxval(CLSettings%YRange) + + ! Set number of points in Y direction + DvrSettings%GridN(2) = CEILING( abs( ( DvrSettings%YRange(2) - DvrSettings%YRange(1) ) / DvrSettings%GridDelta(2) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%YRange(2)= DvrSettings%YRange(1) + ( DvrSettings%GridN(2) - 1_IntKi ) * DvrSettings%GridDelta(2) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%YRange(2),maxval(CLSettings%YRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of YRange to '//TRIM(Num2LStr(DvrSettings%YRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(2)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(2)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ELSEIF ( ( .NOT. CLFlags%YRange ) .AND. CLFlags%Dy ) THEN + + ! Make sure we have points to calculate + IF ( DvrSettings%GridN(2) == 0 ) THEN + ! We only issue this warning. + CALL SetErrStat( ErrID_Warn,' No points specified in driver input file for Y direction. Ignoring Dy input.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + DvrFlags%Dy = .FALSE. + DvrFlags%YRange = .FALSE. + ELSE + + DvrFlags%Dy = .TRUE. + DvrFlags%YRange = .TRUE. + WindGridModify = .TRUE. + + ! Save the Dy value + DvrSettings%GridDelta(2) = abs(CLSettings%GridDelta(2)) ! just in case there was a negative number + + ! Calculate the new value of Ny + DvrSettings%GridN(2) = CEILING( abs( ( DvrSettings%YRange(2) - DvrSettings%YRange(1) ) / DvrSettings%GridDelta(2) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%YRange(2)= DvrSettings%YRange(1) + ( DvrSettings%GridN(2) - 1_IntKi ) * DvrSettings%GridDelta(2) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%YRange(2),maxval(CLSettings%YRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of YRange to '//TRIM(Num2LStr(DvrSettings%YRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(2)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(2)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ENDIF + + + ELSEIF ( CLFlags%YRange .AND. CLFlags%Dy ) THEN + + ! Set flags if not already set + DvrFlags%Dy = .TRUE. + DvrFlags%YRange = .TRUE. + WindGridModify = .TRUE. + + ! Copy over the range and stepsize + DvrSettings%YRange(1) = minval(CLSettings%YRange) ! just in case the order is funky + DvrSettings%YRange(2) = maxval(CLSettings%YRange) + DvrSettings%GridDelta(2) = abs(CLSettings%GridDelta(2)) ! just in case there was a negative number + + ! Set number of points in Y direction + DvrSettings%GridN(2) = CEILING( abs( ( DvrSettings%YRange(2) - DvrSettings%YRange(1) ) / DvrSettings%GridDelta(2) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%YRange(2)= DvrSettings%YRange(1) + ( DvrSettings%GridN(2) - 1_IntKi ) * DvrSettings%GridDelta(2) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%YRange(2),maxval(CLSettings%YRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of YRange to '//TRIM(Num2LStr(DvrSettings%YRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(2)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(2)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ELSE + ! Nothing was specified, so we don't do anything + ENDIF + + + + + ! ZRange / Dz -- This is processed exactly the same as for YRange. + + IF ( CLFlags%ZRange .AND. ( .NOT. CLFlags%Dz ) ) THEN + + DvrFlags%Dz = .TRUE. + DvrFlags%ZRange = .TRUE. + WindGridModify = .TRUE. + + ! Calculate new Ny. + DvrSettings%ZRange(1) = minval(CLSettings%ZRange) ! just in case the order is funky + DvrSettings%ZRange(2) = maxval(CLSettings%ZRange) + + ! Set number of points in Y direction + DvrSettings%GridN(3) = CEILING( abs( ( DvrSettings%ZRange(2) - DvrSettings%ZRange(1) ) / DvrSettings%GridDelta(3) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%ZRange(2)= DvrSettings%ZRange(1) + ( DvrSettings%GridN(3) - 1_IntKi ) * DvrSettings%GridDelta(3) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%ZRange(2),maxval(CLSettings%ZRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of ZRange to '//TRIM(Num2LStr(DvrSettings%ZRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(3)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(3)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ELSEIF ( ( .NOT. CLFlags%ZRange ) .AND. CLFlags%Dz ) THEN + + ! Make sure we have points to calculate + IF ( DvrSettings%GridN(3) == 0 ) THEN + ! We only issue this warning. + CALL SetErrStat( ErrID_Warn,' No points specified in driver input file for Z direction. Ignoring Dz input.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + DvrFlags%Dz = .FALSE. + DvrFlags%ZRange = .FALSE. + ELSE + + DvrFlags%Dz = .TRUE. + DvrFlags%ZRange = .TRUE. + WindGridModify = .TRUE. + + ! Save the Dz value + DvrSettings%GridDelta(3) = abs(CLSettings%GridDelta(3)) ! just in case there was a negative number + + ! Calculate the new value of Ny + DvrSettings%GridN(3) = CEILING( abs( ( DvrSettings%ZRange(2) - DvrSettings%ZRange(1) ) / DvrSettings%GridDelta(3) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%ZRange(2)= DvrSettings%ZRange(1) + ( DvrSettings%GridN(3) - 1_IntKi ) * DvrSettings%GridDelta(3) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%ZRange(2),maxval(CLSettings%ZRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of ZRange to '//TRIM(Num2LStr(DvrSettings%ZRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(3)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(3)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ENDIF + + + ELSEIF ( CLFlags%ZRange .AND. CLFlags%Dz ) THEN + + ! Set flags if not already set + DvrFlags%Dz = .TRUE. + DvrFlags%ZRange = .TRUE. + WindGridModify = .TRUE. + + ! Copy over the range and stepsize + DvrSettings%ZRange(1) = minval(CLSettings%ZRange) ! just in case the order is funky + DvrSettings%ZRange(2) = maxval(CLSettings%ZRange) + DvrSettings%GridDelta(3) = abs(CLSettings%GridDelta(3)) ! just in case there was a negative number + + ! Set number of points in Y direction + DvrSettings%GridN(3) = CEILING( abs( ( DvrSettings%ZRange(2) - DvrSettings%ZRange(1) ) / DvrSettings%GridDelta(3) ) + 1_IntKi ) + + ! Now adjust the upper limit of the range slightly for the integer number of steps + DvrSettings%ZRange(2)= DvrSettings%ZRange(1) + ( DvrSettings%GridN(3) - 1_IntKi ) * DvrSettings%GridDelta(3) + + ! Now issue a warning if we had to change the upper limit, otherwise silently adopt it. + IF ( .NOT. EqualRealNos(DvrSettings%ZRange(2),maxval(CLSettings%ZRange)) ) THEN + CALL SetErrStat(ErrID_Warn,' Adjusted upper limit of ZRange to '//TRIM(Num2LStr(DvrSettings%ZRange(2)))// & + ' so that there are '//TRIM(Num2LStr(DvrSettings%GridN(3)))//' points with a requested spacing '// & + TRIM(Num2LStr(DvrSettings%GridDelta(3)))//'.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ELSE + ! Nothing was specified, so we don't do anything + ENDIF + + + + !-------------------------------------------- + ! Did we change the FFT info? + !-------------------------------------------- + + IF ( CLFlags%FFTcalc ) THEN + ! + IF ( CLSettings%FFTcoord(3) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn,' FFT coordinate ['//TRIM(Num2LStr(CLSettings%FFTcoord(1)))//','// & + TRIM(Num2LStr(CLSettings%FFTcoord(1)))//','//TRIM(Num2LStr(CLSettings%FFTcoord(1)))// & + '] is at or below ground level where there is no wind. Ingoring.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL' ) + DvrFlags%FFTcalc = .FALSE. + ELSE + ! If we are overriding driver input file settings, tell user + IF ( DvrFlags%FFTcalc ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for FFT calculation.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL' ) + ENDIF + DvrSettings%FFTcoord = CLSettings%FFTcoord + DvrFlags%FFTcalc = .TRUE. + ENDIF + + ENDIF + + !-------------------------------------------- + ! Did we request a summary file? + !-------------------------------------------- + + IF ( CLFlags%Summary ) THEN + DvrFlags%Summary = .TRUE. + ENDIF + + !-------------------------------------------- + ! Did we request a different Points file? + !-------------------------------------------- + + IF ( CLFlags%PointsFile ) THEN + ! If a name was given in the driver input file, then warn the user. + IF ( DvrFlags%PointsFile ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for Points file.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL' ) + ENDIF + DvrFlags%PointsFile = .TRUE. + DvrSettings%PointsFileName = CLSettings%PointsFileName + ENDIF + + + + !-------------------------------------------- + ! If there was no driver input file, we need to set a few things. + !-------------------------------------------- + + IF ( .NOT. DVRIPT ) THEN + + ! Do we need to set the NumTimeStepsDefault flag? + IF ( .NOT. DvrFlags%NumTimeSteps ) THEN + DvrFlags%NumTimeStepsDefault = .TRUE. + CALL SetErrStat( ErrID_Info,' The number of timesteps is not specified. Defaulting to what is in the wind file.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + ! Do we need to set the DTDefault flag? + IF ( .NOT. DvrFlags%DT ) THEN + DvrFlags%DTDefault = .TRUE. + CALL SetErrStat( ErrID_Info,' The timestep size is not specified. Defaulting to what is in the wind file.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + + +!FIXME: Anything else? + IF ( .NOT. DvrFlags%ZRange ) THEN + DvrSettings%ZRange = 50.0 + CALL SetErrStat( ErrID_Info,' ZRange not set. Using value of 50.0.', & + ErrStat,ErrMsg,'UpdateSettingsWithCL') + ENDIF + ENDIF + + + ! If no DT value has been set (DEFAULT requested), we need to set a default to pass into IfW + IF ( .NOT. DvrFlags%DT ) THEN + DvrSettings%DT = 0.025_DbKi ! This value gets passed into the IfW_Init routine, so something must be set. + ENDIF + + + +END SUBROUTINE UpdateSettingsWithCL + + +SUBROUTINE ReadPointsFile( PointsFileName, CoordList, ErrStat, ErrMsg ) + + CHARACTER(1024), INTENT(IN ) :: PointsFileName !< Name of the points file to read + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: CoordList(:,:) !< The coordinates we read in + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< The message for the status + + ! Local variables + CHARACTER(1024) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + INTEGER(IntKi) :: FiUnitPoints !< Unit number for points file to open + + INTEGER(IntKi) :: NumDataColumns !< Number of data columns + INTEGER(IntKi) :: NumDataPoints !< Number of lines of data (one point per line) + INTEGER(IntKi) :: NumHeaderLines !< Number of header lines to ignore + + INTEGER(IntKi) :: I !< Generic counter + + ! Initialization of subroutine + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + + + ! Now open file + CALL GetNewUnit( FiUnitPoints ) + CALL OpenFInpFile( FiUnitPoints, TRIM(PointsFileName), ErrStatTmp, ErrMsgTmp ) ! Unformatted input file + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + ! Find out how long the file is + CALL GetFileLength( FiUnitPoints, PointsFileName, NumDataColumns, NumDataPoints, NumHeaderLines, ErrMsgTmp, ErrStatTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + IF ( NumDataColumns /= 3 ) THEN + CALL SetErrStat( ErrID_Fatal,' Expecting three columns in '//TRIM(PointsFileName)//' corresponding to '// & + 'X, Y, and Z coordinates. Instead found '//TRIM(Num2LStr(NumDataColumns))//'.', & + ErrStat, ErrMsg, 'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Allocate the storage for the data + CALL AllocAry( CoordList, 3, NumDataPoints, "Array of Points data", ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Read in the headers and throw them away + DO I=1,NumHeaderLines + CALL ReadCom( FiUnitPoints, PointsFileName,' Points file header line', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + ENDDO + + ! Read in the datapoints + DO I=1,NumDataPoints + CALL ReadAry ( FiUnitPoints, PointsFileName, CoordList(:,I), 3, 'CoordList', & + 'Coordinate point from Points file', ErrStatTmp, ErrMsgTmp) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,'ReadPointsFile') + CLOSE( FiUnitPoints ) + RETURN + ENDIF + ENDDO + + CLOSE( FiUnitPoints ) + +CONTAINS + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine looks at a file that has been opened and finds out how many header lines there are, how many columns there + !! are, and how many lines of data there are in the file. + !! + !! A few things are assumed about the file: + !! 1. Any header lines are the first thing in the file. + !! 2. No text appears anyplace other than in first part of the file + !! 3. The datalines only contain numbers that can be read in as reals. + !! + !! Limitations: + !! 1. only handles up to 20 words (columns) on a line + !! 2. empty lines are considered text lines + !! 3. All data rows must contain the same number of columns + !! + !! + SUBROUTINE GetFileLength(UnitDataFile, DataFileName, NumDataColumns, NumDataLines, NumHeaderLines, ErrMsg, ErrStat) + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: UnitDataFile !< Unit number of the file we are looking at. + CHARACTER(*), INTENT(IN ) :: DataFileName !< The name of the file we are looking at. + INTEGER(IntKi), INTENT( OUT) :: NumDataColumns !< The number of columns in the data file. + INTEGER(IntKi), INTENT( OUT) :: NumDataLines !< Number of lines containing data + INTEGER(IntKi), INTENT( OUT) :: NumHeaderLines !< Number of header lines at the start of the file + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error Message to return (empty if all good) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Status flag if there were any problems (ErrID_None if all good) + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary message variable. Used in calls. + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status. Used in calls. + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + INTEGER(IntKi) :: TmpIOErrStat !< Temporary error status for the internal read of the first word to a real number + LOGICAL :: IsRealNum !< Flag indicating if the first word on the line was a real number + + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + CHARACTER(1024) :: StrRead !< String containing the first word read in + REAL(ReKi) :: RealRead !< Returns value of the number (if there was one), or NaN (as set by NWTC_Num) if there wasn't + CHARACTER(1024) :: VarName !< Name of the variable we are trying to read from the file + CHARACTER(24) :: Words(20) !< Array of words we extract from a line. We shouldn't have more than 20. + INTEGER(IntKi) :: i,j,k !< simple integer counters + INTEGER(IntKi) :: LineNumber !< the line I am on + LOGICAL :: LineHasText !< Flag indicating if the line I just read has text. If so, it is a header line. + LOGICAL :: HaveReadData !< Flag indicating if I have started reading data. + INTEGER(IntKi) :: NumWords !< Number of words on a line + INTEGER(IntKi) :: FirstDataLineNum !< Line number of the first row of data in the file + + + ! Initialize the error handling + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + LclErrStat = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + + ! Set some of the flags and counters + HaveReadData = .FALSE. + NumDataColumns = 0 + NumHeaderLines = 0 + NumDataLines = 0 + LineNumber = 0 + + + ! Just in case we were handed a file that we are part way through reading (should never be true), rewind to the start + + REWIND( UnitDataFile ) + + + !------------------------------------ + !> The variable LclErrStat is used to indicate when we have reached the end of the file or had an error from + !! ReadLine. Until that occurs, we read each line, and decide if it contained any non-numeric data. The + !! first group of lines containing non-numeric data is considered the header. The first line of all numeric + !! data is considered the start of the data section. Any non-numeric containing found within the data section + !! will be considered as an invalid file format at which point we will return a fatal error from this routine. + + DO WHILE ( LclErrStat == ErrID_None ) + + !> Reset the indicator flag for the non-numeric content + LineHasText = .FALSE. + + !> Read in a single line from the file + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + + !> If there was an error in reading the file, then exit. + !! Possible causes: reading beyond end of file in which case we are done so don't process it. + IF ( LclErrStat /= ErrID_None ) EXIT + + !> Increment the line counter. + LineNumber = LineNumber + 1 + + !> Read all the words on the line into the array called 'Words'. Only the first words will be encountered + !! will be stored. The others are empty (i.e. only three words on the line, so the remaining 17 are empty). + CALL GetWords( TextLine, Words, 20 ) + + !> Cycle through and count how many are not empty. Once an empty value is encountered, all the rest should + !! be empty if GetWords worked correctly. The index of the last non-empty value is stored. + DO i=1,20 + IF (TRIM(Words(i)) .ne. '') NumWords=i + ENDDO + + + !> Now cycle through the first 'NumWords' of non-empty values stored in 'Words'. Words should contain + !! everything that is one the line. The subroutine ReadRealNumberFromString will set a flag 'IsRealNum' + !! when the value in Words(i) can be read as a real(ReKi). 'StrRead' will contain the string equivalent. + DO i=1,NumWords + CALL ReadRealNumberFromString( Words(i), RealRead, StrRead, IsRealNum, ErrStatTmp, ErrMsgTmp, TmpIOErrStat ) + IF ( .NOT. IsRealNum) THEN + LineHasText = .TRUE. + ENDIF + ENDDO + + !> If all the words on that line had no text in them, then it must have been a line of data. + !! If not, then we have either a header line, which is ok, or a line containing text in the middle of the + !! the data section, which is not good (the flag HaveReadData tells us which case this is). + IF ( LineHasText ) THEN + IF ( HaveReadData ) THEN ! Uh oh, we have already read a line of data before now, so there is a problem + CALL SetErrStat( ErrID_Fatal, ' Found text on line '//TRIM(Num2LStr(LineNumber))//' of '//TRIM(DataFileName)// & + ' when real numbers were expected. There may be a problem with format of the file: '// & + TRIM(DataFileName)//'.', ErrStat, ErrMsg, 'GetFileLength') + IF ( ErrStat >= AbortErrLev ) THEN + RETURN + ENDIF + ELSE + NumHeaderLines = NumHeaderLines + 1 + ENDIF + ELSE ! No text, must be data line + NumDataLines = NumDataLines + 1 + ! If this is the first row of data, then store the number of words that were on the line + IF ( .NOT. HaveReadData ) THEN + ! If this is the first line of data, keep some relevant info about it and the number of columns in it + HaveReadData = .TRUE. + FirstDataLineNum = LineNumber ! Keep the line number of the first row of data (for error reporting) + NumDataColumns = NumWords + ELSE + ! Make sure that the number columns on the row matches the number of columnns on the first row of data. + IF ( NumWords /= NumDataColumns ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error in file: '//TRIM(DataFileName)//'.'// & + ' The number of data columns on line '//TRIM(Num2LStr(LineNumber))// & + '('//TRIM(Num2LStr(NumWords))//' columns) is different than the number of columns on first row of data '// & + ' (line: '//TRIM(Num2LStr(FirstDataLineNum))//', '//TRIM(Num2LStr(NumDataColumns))//' columns).', & + ErrStat, ErrMsg, 'GetFileLength') + IF ( ErrStat >= AbortErrLev ) THEN + RETURN + ENDIF + ENDIF + ENDIF + ENDIF + + ENDDO + + + REWIND( UnitDataFile ) + + END SUBROUTINE GetFileLength + + !------------------------------------------------------------------------------- + !> This subroutine takes a line of text that is passed in and reads the first + !! word to see if it is a number. An internal read is used to do this. If + !! it is a number, it is started in ValueRead and returned. The flag IsRealNum + !! is set to true. Otherwise, ValueRead is set to NaN (value from the NWTC_Num) + !! and the flag is set to false. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (IsRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + CHARACTER(*), INTENT(IN ) :: StringToParse !< The string we were handed. + REAL(ReKi), INTENT( OUT) :: ValueRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StringToParse,*,IOSTAT=IOErrStat) StrRead + read(StringToParse,*,IOSTAT=IOErrStat) ValueRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + ValueRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrSTat = ErrID_Severe + endif + + + + RETURN + END SUBROUTINE ReadRealNumberFromString + + + !------------------------------------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + !> This subroutine works with the ReadNum routine from the library. ReadNum is + !! called to read a word from the input file. An internal read is then done to + !! convert the string to a number that is stored in VarRead and returned. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (ISRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumber(UnitNum, FileName, VarName, VarRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + INTEGER(IntKi), INTENT(IN ) :: UnitNum !< The unit number of the file being read + CHARACTER(*), INTENT(IN ) :: FileName !< The name of the file being read. Used in the ErrMsg from ReadNum (Library routine). + CHARACTER(*), INTENT(IN ) :: VarName !< The variable we are reading. Used in the ErrMsg from ReadNum (Library routine)'. + REAL(ReKi), INTENT( OUT) :: VarRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + ! Local vars + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! Now call the ReadNum routine to get the number + ! If it is a word that does not start with T or F, then ReadNum won't give any errors. + CALL ReadNum( UnitNum, FileName, StrRead, VarName, ErrStatTmp, ErrMsgTmp) + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StrRead,*,IOSTAT=IOErrStat) VarRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + VarRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrStat = ErrStatTmp ! The ErrStatTmp returned by the ReadNum routine is an ErrID level. + endif + + + + RETURN + END SUBROUTINE ReadRealNumber + + +END SUBROUTINE ReadPointsFile + + + +SUBROUTINE WindGridMessage( Settings, ToFile, Msg, MsgLen ) + + TYPE(IfWDriver_Settings), INTENT(IN ) :: Settings + LOGICAL, INTENT(IN ) :: ToFile !< Prepend comment character + CHARACTER(2048), INTENT( OUT) :: Msg + INTEGER(IntKi), INTENT( OUT) :: MsgLen + + ! Local Variables + CHARACTER(11) :: TmpNumString + INTEGER(IntKi) :: ErrStatTmp + + Msg = '' + + IF ( ToFile ) THEN + Msg='# ' + ELSE + Msg="Requested wind grid data will be written to "//TRIM(Settings%WindGridOutputName)//'.' + ENDIF + Msg = TRIM(Msg)//" Requested data:"//NewLine + + ! Header info: + Msg = TRIM(Msg) + IF ( ToFile ) Msg=TRIM(Msg)//'#' + Msg = TRIM(Msg)//" Dimension Range Stepsize Num. points"//NewLine + IF ( ToFile ) Msg=TRIM(Msg)//'#' + Msg = TRIM(Msg)//" -------------------------------------------------------------------"//NewLine + ! X direction + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%XRange(1) + IF ( ToFile ) THEN + Msg= TRIM(Msg)//"# X" + ELSE + Msg= TRIM(Msg)//" X" + ENDIF + MsgLen= LEN_TRIM(Msg) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+7+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%XRange(2) + Msg = Msg(1:MsgLen)//" -> "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%GridDelta(1) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(i6)',IOSTAT=ErrStatTmp) Settings%GridN(1) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:6)//NewLine + MsgLen= MsgLen+6+6 + + + ! Y direction + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%YRange(1) + IF ( ToFile ) THEN + Msg= TRIM(Msg)//"# Y" + ELSE + Msg= TRIM(Msg)//" Y" + ENDIF + MsgLen= LEN_TRIM(Msg) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+7+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%YRange(2) + Msg = Msg(1:MsgLen)//" -> "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%GridDelta(2) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(i6)',IOSTAT=ErrStatTmp) Settings%GridN(2) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:6)//NewLine + MsgLen= MsgLen+6+6 + + + ! Z direction + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%ZRange(1) + IF ( ToFile ) THEN + Msg= TRIM(Msg)//"# Z" + ELSE + Msg= TRIM(Msg)//" Z" + ENDIF + MsgLen= LEN_TRIM(Msg) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+7+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%ZRange(2) + Msg = Msg(1:MsgLen)//" -> "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(f7.2)',IOSTAT=ErrStatTmp) Settings%GridDelta(3) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:10) + MsgLen= MsgLen+4+10 + + WRITE(TmpNumString,'(i6)',IOSTAT=ErrStatTmp) Settings%GridN(3) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:6)//NewLine + MsgLen= MsgLen+6+6 + + + ! T direction + WRITE(TmpNumString,'(f10.4)',IOSTAT=ErrStatTmp) Settings%TStart + IF ( ToFile ) THEN + Msg= TRIM(Msg)//"# T" + ELSE + Msg= TRIM(Msg)//" T" + ENDIF + MsgLen= LEN_TRIM(Msg) + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:11) + MsgLen= MsgLen+7+11 + + WRITE(TmpNumString,'(f10.4)',IOSTAT=ErrStatTmp) Settings%TStart+Settings%DT*Settings%NumTimeSteps + Msg = Msg(1:MsgLen)//"->"//TmpNumString(1:11) + MsgLen= MsgLen+4+11 + + WRITE(TmpNumString,'(f10.4)',IOSTAT=ErrStatTmp) Settings%DT + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:11) + MsgLen= MsgLen+4+11 + + WRITE(TmpNumString,'(i8)',IOSTAT=ErrStatTmp) Settings%NumTimeSteps + Msg = Msg(1:MsgLen)//" "//TmpNumString(1:8) !//NewLine + MsgLen= MsgLen+6+8 + +END SUBROUTINE + + +!> 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? + 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 + REAL(DbKi), INTENT(IN ) :: TIME !< The current time + 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) + + CHARACTER(52) :: WindVelFmt !< Format specifier for the output file for wave elevation series + INTEGER(IntKi) :: I !< generic counter + + + WindVelFmt = "(3(F14.7,3x),3(F10.3,3x))" + + ErrMsg = '' + ErrStat = ErrID_None + ErrMsgTmp = '' + ErrStatTmp = ErrID_None + + + ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. + IF ( .NOT. Initialized ) THEN + + CALL GetNewUnit( FileUnit ) + CALL OpenFOutFile( FileUnit, TRIM(FileName), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WindGridVel_OutputWrite' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + Initialized = .TRUE. + + ! Write header section + WRITE( FileUnit,'(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 '// & + '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 ) '# ' + 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 '// & + ' U V W' + WRITE (FileUnit,'(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)) + + 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) + + ENDDO + + ENDIF + +END SUBROUTINE WindGridVel_OutputWrite + + +SUBROUTINE PointsVel_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? + 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(DbKi), INTENT(IN ) :: TIME !< The current time + 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) :: PointsVelFmt !< Format specifier for the output file for wave elevation series + + + PointsVelFmt = "(F14.7,3x,F14.7,3x,F14.7,3x,F14.7,3x,F14.7,3x,F14.7,3x,F14.7)" + + ErrMsg = '' + ErrStat = ErrID_None + ErrMsgTmp = '' + ErrStatTmp = ErrID_None + + + ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. + IF ( .NOT. Initialized ) THEN + + CALL GetNewUnit( FileUnit ) + CALL OpenFOutFile( FileUnit, TRIM(FileName), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'PointsVel_OutputWrite' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + Initialized = .TRUE. + + ! Write header section + WRITE( FileUnit,'(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 ) '# T X Y Z '// & + ' U V W' + WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# (s) (m) (m) (m) '// & + ' (m/s) (m/s) (m/s)' + 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) + + ENDDO + + ENDIF + +END SUBROUTINE PointsVel_OutputWrite + + + + +!> This routine exists only to support the development of the module. It will not be needed after the module is complete. +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 + + CALL WrsCr(TRIM(GetNVD(DvrSettings%ProgInfo))) + 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(' Summary: '//FLAG(DvrFlags%Summary)) + CALL WrScr(' SummaryFile: '//FLAG(DvrFlags%SummaryFile)// ' '//TRIM(DvrSettings%SummaryFileName)) + CALL WrScr(' TStart: '//FLAG(DvrFlags%TStart)// ' '//TRIM(Num2LStr(DvrSettings%TStart))) + IF ( DvrFlags%DTDefault) THEN + CALL WrScr(' DT: '//FLAG(DvrFlags%DT)// ' DEFAULT') + ELSE + CALL WrScr(' DT: '//FLAG(DvrFlags%DT)// ' '//TRIM(Num2LStr(DvrSettings%DT))) + ENDIF + IF ( DvrFlags%NumTimeStepsDefault) THEN + CALL WrScr(' NumTimeSteps: '//FLAG(DvrFlags%NumTimeSteps)// ' DEFAULT') + ELSE + CALL WrScr(' NumTimeSteps: '//FLAG(DvrFlags%NumTimeSteps)// ' '//TRIM(Num2LStr(DvrSettings%NumTimeSteps))) + ENDIF + CALL WrScr(' FFTcalc: '//FLAG(DvrFlags%FFTcalc)// ' ['//TRIM(Num2LStr(DvrSettings%FFTcoord(1)))//', '& + //TRIM(Num2LStr(DvrSettings%FFTcoord(2)))//', '& + //TRIM(Num2LStr(DvrSettings%FFTcoord(3)))//']') + CALL WrScr(' WindGrid: '//FLAG(DvrFlags%WindGrid)) +if (DvrFlags%WindGrid) then + CALL WrScr(' GridN: ' //TRIM(Num2LStr(DvrSettings%GridN(1)))//' x ' & + //TRIM(Num2LStr(DvrSettings%GridN(2)))//' x ' & + //TRIM(Num2LStr(DvrSettings%GridN(3)))) + CALL WrScr(' XRange: '//FLAG(DvrFlags%XRange)// ' '//TRIM(Num2LStr(DvrSettings%XRange(1)))//' -- ' & + //TRIM(Num2LStr(DvrSettings%XRange(2)))) + CALL WrScr(' YRange: '//FLAG(DvrFlags%YRange)// ' '//TRIM(Num2LStr(DvrSettings%YRange(1)))//' -- ' & + //TRIM(Num2LStr(DvrSettings%YRange(2)))) + CALL WrScr(' ZRange: '//FLAG(DvrFlags%ZRange)// ' '//TRIM(Num2LStr(DvrSettings%ZRange(1)))//' -- ' & + //TRIM(Num2LStr(DvrSettings%ZRange(2)))) + 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))) +end if + CALL WrScr(' FFTOutputInit: '//FLAG(DvrFlags%FFTOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%FFTOutputUnit))) + CALL WrScr(' PointsOutputInit: '//FLAG(DvrFlags%PointsOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsOutputUnit))) + RETURN +END SUBROUTINE printSettings + + +!> This routine exists only to support the development of the module. It will not be kept after the module is complete. +!! This routine takes a flag setting (LOGICAL) and exports either 'T' or '-' for T/F (respectively) +FUNCTION FLAG(flagval) + LOGICAL, INTENT(IN ) :: flagval !< Value of the flag + CHARACTER(1) :: FLAG !< character interpretation (for prettiness when printing) + IF ( flagval ) THEN + FLAG = 'T' + ELSE + FLAG = '-' + ENDIF + RETURN +END FUNCTION FLAG + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +END MODULE InflowWind_Driver_Subs diff --git a/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Types.f90 new file mode 100644 index 000000000..26bad3c3d --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -0,0 +1,111 @@ +!********************************************************************************************************************************** +! +! MODULE: IfW_Driver_Types - This module contains types used by the InflowWind Driver program to store arguments passed in +! +! The types listed here are used within the InflowWind Driver program to store the settings. These settings are read in as +! command line arguments, then stored within these types. +! +!********************************************************************************************************************************** +! +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! This file is part of InflowWind. +! +! InflowWind is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as +! published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +! of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License along with InflowWind. +! If not, see <http://www.gnu.org/licenses/>. +! +!********************************************************************************************************************************** + +MODULE InflowWind_Driver_Types + + USE NWTC_Library + USE InflowWind_Types + + IMPLICIT NONE + + !> 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. + !! + !! NOTE: The WindFileType is only set if it is given as a command line option. Otherwise + !! it is handled internally by InflowWInd. + !! + !! NOTE: The wind direction is specified by the InflowWind input file. + 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) + LOGICAL :: SummaryFile = .FALSE. !< create a summary file of the output? + LOGICAL :: TStart = .FALSE. !< specified a start time + LOGICAL :: NumTimeSteps = .FALSE. !< specified a number of timesteps to process + LOGICAL :: NumTimeStepsDefault = .FALSE. !< specified a 'DEFAULT' for number of timesteps to process + LOGICAL :: DT = .FALSE. !< specified a resolution in time + LOGICAL :: DTDefault = .FALSE. !< specified a 'DEFAULT' for the time resolution + + LOGICAL :: FFTcalc = .FALSE. !< do an FFT + + LOGICAL :: WindGrid = .FALSE. !< Requested output of wind data on a grid -- input file option only + LOGICAL :: XRange = .FALSE. !< specified a range of x -- command line option only -- stored as GridCtrCoord and GridDelta + LOGICAL :: YRange = .FALSE. !< specified a range of y -- command line option only -- stored as GridCtrCoord and GridDelta + LOGICAL :: ZRange = .FALSE. !< specified a range of z -- command line option only -- stored as GridCtrCoord and GridDelta + LOGICAL :: Dx = .FALSE. !< specified a resolution in x -- command line option only, 0.0 otherwise + 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 :: WindGridOutputInit = .FALSE. !< Is the WindGridOut file initialized + LOGICAL :: PointsOutputInit = .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 + + LOGICAL :: WrHAWC = .FALSE. !< Requested file conversion to HAWC2 format? + LOGICAL :: WrBladed = .FALSE. !< Requested file conversion to Bladed format? + LOGICAL :: WrVTK = .FALSE. !< Requested file output as VTK? + 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 !< 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) :: 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 + + +END MODULE InflowWind_Driver_Types diff --git a/OpenFAST/modules/inflowwind/src/InflowWind_Subs.f90 b/OpenFAST/modules/inflowwind/src/InflowWind_Subs.f90 new file mode 100644 index 000000000..0cdb22e91 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind_Subs.f90 @@ -0,0 +1,1771 @@ +!********************************************************************************************************************************** +! 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. +! +!********************************************************************************************************************************** +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 + + + IMPLICIT NONE + + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 26-Oct-2020 15:42:27. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + 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 + + + ! Wind Magnitude and Direction: + + INTEGER(IntKi), PARAMETER :: Wind1VelXY = 28 + INTEGER(IntKi), PARAMETER :: Wind2VelXY = 29 + INTEGER(IntKi), PARAMETER :: Wind3VelXY = 30 + INTEGER(IntKi), PARAMETER :: Wind4VelXY = 31 + INTEGER(IntKi), PARAMETER :: Wind5VelXY = 32 + INTEGER(IntKi), PARAMETER :: Wind6VelXY = 33 + INTEGER(IntKi), PARAMETER :: Wind7VelXY = 34 + INTEGER(IntKi), PARAMETER :: Wind8VelXY = 35 + INTEGER(IntKi), PARAMETER :: Wind9VelXY = 36 + INTEGER(IntKi), PARAMETER :: Wind1VelMag = 37 + INTEGER(IntKi), PARAMETER :: Wind2VelMag = 38 + INTEGER(IntKi), PARAMETER :: Wind3VelMag = 39 + INTEGER(IntKi), PARAMETER :: Wind4VelMag = 40 + INTEGER(IntKi), PARAMETER :: Wind5VelMag = 41 + INTEGER(IntKi), PARAMETER :: Wind6VelMag = 42 + INTEGER(IntKi), PARAMETER :: Wind7VelMag = 43 + INTEGER(IntKi), PARAMETER :: Wind8VelMag = 44 + INTEGER(IntKi), PARAMETER :: Wind9VelMag = 45 + INTEGER(IntKi), PARAMETER :: Wind1AngXY = 46 + INTEGER(IntKi), PARAMETER :: Wind2AngXY = 47 + INTEGER(IntKi), PARAMETER :: Wind3AngXY = 48 + INTEGER(IntKi), PARAMETER :: Wind4AngXY = 49 + INTEGER(IntKi), PARAMETER :: Wind5AngXY = 50 + INTEGER(IntKi), PARAMETER :: Wind6AngXY = 51 + INTEGER(IntKi), PARAMETER :: Wind7AngXY = 52 + INTEGER(IntKi), PARAMETER :: Wind8AngXY = 53 + INTEGER(IntKi), PARAMETER :: Wind9AngXY = 54 + + + ! Wind Sensor Measurements: + + INTEGER(IntKi), PARAMETER :: WindMeas1 = 55 + INTEGER(IntKi), PARAMETER :: WindMeas2 = 56 + INTEGER(IntKi), PARAMETER :: WindMeas3 = 57 + INTEGER(IntKi), PARAMETER :: WindMeas4 = 58 + INTEGER(IntKi), PARAMETER :: WindMeas5 = 59 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 59 + +!End of code generated by Matlab script +! =================================================================================================== + + + 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 :: 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 + +! =================================================================================================== + +CONTAINS + +!==================================================================================================== +!> This public subroutine parses the array of strings in InputFileData for the input parameters. +SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, InputFileName, EchoFileName, ErrStat, ErrMsg ) +!---------------------------------------------------------------------------------------------------- + + IMPLICIT NONE + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_ParseInputFileInfo" + + ! Passed variables + TYPE(InflowWind_InputFile), INTENT(INOUT) :: InputFileData !< Data of the InflowWind Input File + TYPE(FileInfoType), INTENT(IN ) :: InFileInfo !< The derived type for holding the file information + CHARACTER(*), INTENT(IN ) :: PriPath !< Path to InflowWind input files + CHARACTER(*), intent(in ) :: InputFileName !< The name of the input file + CHARACTER(*), intent(in ) :: EchoFileName !< The name of the echo file, possibly opened in this routine + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Returned error status from this subroutine + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Returned error message from this subroutine + + ! Local variables + INTEGER(IntKi) :: CurLine !< Current entry in InFileInfo%Lines array + INTEGER(IntKi) :: UnEc !< local echo unit + + ! Temoporary messages + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + ! Initialization + ErrStat = ErrID_None + ErrMsg = "" + InputFileData%EchoFlag = .FALSE. ! initialize for error handling (cleanup() routine) + UnEc = -1 + + ! Allocate the array for the OutList + CALL AllocAry( InputFileData%OutList, MaxOutPts, "InflowWind Input File's OutList", TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !--------------------------------------------------------------------------------------------- + ! General settings with wind type, direction and output point list (applies to all wind types) + !--------------------------------------------------------------------------------------------- + + CurLine = 4 + CALL ParseVar( InFileInfo, CurLine, "Echo", InputFileData%EchoFlag, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + if ( InputFileData%EchoFlag ) then + CALL OpenEcho ( UnEc, TRIM(EchoFileName), TmpErrStat, TmpErrMsg ) + if (Failed()) return; + WRITE(UnEc, '(A)') 'Echo file for InflowWind input file: '//trim(InputFileName) + ! Write the first three lines into the echo file + WRITE(UnEc, '(A)') InFileInfo%Lines(1) + WRITE(UnEc, '(A)') InFileInfo%Lines(2) + WRITE(UnEc, '(A)') InFileInfo%Lines(3) + + CurLine = 4 + CALL ParseVar( InFileInfo, CurLine, "Echo", InputFileData%EchoFlag, TmpErrStat, TmpErrMsg, UnEc ) + if (Failed()) return + endif + + + ! 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) + CALL ParseVar( InFileInfo, CurLine, "WindType", InputFileData%WindType, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! Direction of wind propagation (meteorological direction) (deg) + CALL ParseVar( InFileInfo, CurLine, "PropagationDir", InputFileData%PropagationDir, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! VFlowAngle: Upflow angle (deg) + CALL ParseVarWDefault( InFileInfo, CurLine, "VFlowAng", InputFileData%VFlowAngle, 0.0_ReKi, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! NWindVel: Number of points to output the wind velocity (0 to 9) + CALL ParseVar( InFileInfo, CurLine, "NWindVel", InputFileData%NWindVel, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! Before proceeding, make sure that NWindVel makes sense + IF ( InputFileData%NWindVel < 0 .OR. InputFileData%NwindVel > 9 ) THEN + CALL SetErrStat( ErrID_Fatal, 'NWindVel must be greater than or equal to zero and less than 10.', & + ErrStat, ErrMsg, RoutineName ) + RETURN + ELSE + + ! Allocate space for the output location arrays: + CALL AllocAry( InputFileData%WindVxiList, InputFileData%NWindVel, 'WindVxiList', TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( InputFileData%WindVyiList, InputFileData%NWindVel, 'WindVyiList', TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( InputFileData%WindVziList, InputFileData%NWindVel, 'WindVziList', TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + ENDIF + + CALL ParseAry( InFileInfo, CurLine, 'WindVxiList', InputFileData%WindVxiList, InputFileData%NWindVel, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseAry( InFileInfo, CurLine, 'WindVyiList', InputFileData%WindVyiList, InputFileData%NWindVel, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseAry( InFileInfo, CurLine, 'WindVziList', InputFileData%WindVziList, InputFileData%NWindVel, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for Steady Wind Conditions [used only for WindType = 1]_ section + !------------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "HWindSpeed", InputFileData%Steady_HWindSpeed, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "RefHt", InputFileData%Steady_RefHt, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "PLexp", InputFileData%Steady_PLexp, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for Uniform wind file [used only for WindType = 2]_ section + !------------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "FileName_Uni", InputFileData%Uniform_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%Uniform_FileName ) ) InputFileData%Uniform_FileName = TRIM(PriPath)//TRIM(InputFileData%Uniform_FileName) + + CALL ParseVar( InFileInfo, CurLine, "RefHt_Uni", InputFileData%Uniform_RefHt, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "RefLength", InputFileData%Uniform_RefLength, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for Binary TurbSim Full-Field files [used only for WindType = 3]_ section + !------------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "FileName_BTS", InputFileData%TSFF_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%TSFF_FileName ) ) InputFileData%TSFF_FileName = TRIM(PriPath)//TRIM(InputFileData%TSFF_FileName) + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4]_ section + !------------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "FilenameRoot", InputFileData%BladedFF_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%BladedFF_FileName ) ) InputFileData%BladedFF_FileName = TRIM(PriPath)//TRIM(InputFileData%BladedFF_FileName) + + CALL ParseVar( InFileInfo, CurLine, "TowerFile", InputFileData%BladedFF_TowerFile, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for coherent turbulence [used only for WindType = 3 or 4]_ section + !------------------------------------------------------------------------------------------------- + + ! CurLine = CurLine + 1 ! Skip section break + ! CALL ParseVar( InFileInfo, CurLine, "CTTS_CoherentTurbFlag", InputFileData%CTTS_CoherentTurb, TmpErrStat, TmpErrMsg, UnEc ) + ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! if (Failed()) return + + ! CALL ParseVar( InFileInfo, CurLine, "CTTS_FileName", InputFileData%CTTS_FileName, TmpErrStat, TmpErrMsg, UnEc ) + ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! if (Failed()) return + ! IF ( PathIsRelative( InputFileData%CTTS_FileName ) ) InputFileData%CTTS_FileName = TRIM(PriPath)//TRIM(InputFileData%CTTS_FileName) + + ! CALL ParseVar( InFileInfo, CurLine, "CTTS_Path", InputFileData%CTTS_Path, TmpErrStat, TmpErrMsg, UnEc ) + ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! if (Failed()) return + ! IF ( PathIsRelative( InputFileData%CTTS_Path ) ) InputFileData%CTTS_Path = TRIM(PriPath)//TRIM(InputFileData%CTTS_Path) + + !------------------------------------------------------------------------------------------------- + !> Read the _Parameters for HAWC-formatted binary files [used only for WindType = 5]_ section + !------------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "FileName_u", InputFileData%HAWC_FileName_u, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%HAWC_FileName_u ) ) InputFileData%HAWC_FileName_u = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_u) + + CALL ParseVar( InFileInfo, CurLine, "FileName_v", InputFileData%HAWC_FileName_v, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%HAWC_FileName_v ) ) InputFileData%HAWC_FileName_v = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_v) + + CALL ParseVar( InFileInfo, CurLine, "FileName_w", InputFileData%HAWC_FileName_w, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%HAWC_FileName_w ) ) InputFileData%HAWC_FileName_w = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_w) + + CALL ParseVar( InFileInfo, CurLine, "nx", InputFileData%HAWC_nx, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "ny", InputFileData%HAWC_ny, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "nz", InputFileData%HAWC_nz, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "dx", InputFileData%HAWC_dx, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "dy", InputFileData%HAWC_dy, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "dz", InputFileData%HAWC_dz, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "RefHt_HAWC", InputFileData%FF%RefHt, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !---------------------------------------------------------------------------------------------- + !> Read the _Scaling parameters for turbulence (HAWC-format files) [used only for WindType = 5]_ subsection + !---------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + ! ScaleMethod: Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] + CALL ParseVar( InFileInfo, CurLine, "ScaleMethod", InputFileData%FF%ScaleMethod, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SFx", InputFileData%FF%SF(1), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SFy", InputFileData%FF%SF(2), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SFz", InputFileData%FF%SF(3), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SigmaFx", InputFileData%FF%SigmaF(1), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SigmaFy", InputFileData%FF%SigmaF(2), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "SigmaFz", InputFileData%FF%SigmaF(3), TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! CALL ParseVar( InFileInfo, CurLine, "HAWC_TStart", InputFileData%FF%TStart, TmpErrStat, TmpErrMsg, UnEc ) + ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! IF (ErrStat >= AbortErrLev) THEN + ! RETURN + ! ENDIF + + ! CALL ParseVar( InFileInfo, CurLine, "HAWC_TEnd", InputFileData%FF%TEnd, TmpErrStat, TmpErrMsg, UnEc ) + ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! IF (ErrStat >= AbortErrLev) THEN + ! RETURN + ! ENDIF + + !---------------------------------------------------------------------------------------------- + !> Read the _Mean wind profile paramters (added to HAWC-format files) [used only for WindType = 5]_ subsection + !---------------------------------------------------------------------------------------------- + + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "URef", InputFileData%FF%URef, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + ! WindProfileType: Wind profile type (0=constant;1=logarithmic;2=power law) + CALL ParseVar( InFileInfo, CurLine, "WindProfile", InputFileData%FF%WindProfileType, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "PLExp_HAWC", InputFileData%FF%PLExp, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVar( InFileInfo, CurLine, "Z0", InputFileData%FF%Z0, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + CALL ParseVarWDefault( InFileInfo, CurLine, "XOffset", InputFileData%FF%XOffset, 0.0_ReKi, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !---------------------------------------------------------------------------------------------- + !> Read the _OUTPUT_ subsection + !---------------------------------------------------------------------------------------------- + CurLine = CurLine + 1 ! Skip section break + CALL ParseVar( InFileInfo, CurLine, "SumPrint", InputFileData%SumPrint, TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !---------------------- OUTLIST -------------------------------------------- + CurLine = CurLine + 1 ! Skip comment line + CALL ReadOutputListFromFileInfo( InFileInfo, CurLine, InputFileData%OutList, & + InputFileData%NumOuts, "OutList", "List of user-requested output channels", TmpErrStat, TmpErrMsg, UnEc ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return + + !------------------------------------------------------------------------------------------------- + ! This is the end of the input file + !------------------------------------------------------------------------------------------------- + + RETURN + CONTAINS + !------------------------------------------------------------------------------------------------- + logical function Failed() + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + if (Failed) then + if (UnEc > -1_IntKi) CLOSE( UnEc ) + endif + end function Failed + END SUBROUTINE InflowWind_ParseInputFileInfo + +!==================================================================================================== +!> This private subroutine verifies the input required for InflowWind is correctly specified. This +!! routine checkes all the parameters that are common with all the wind types, then calls subroutines +!! that check the parameters specific to each wind type. Only the parameters corresponding to the +!! desired wind type are evaluated; the rest are ignored. Additional checks will be performed after +!! the respective wind file has been read in, but these checks will be performed within the respective +!! wind module. +! +! The reason for structuring it this way is to allow for relocating the validation routines for the +! wind type into their respective modules. It might also prove useful later if we change languages +! but retain the fortran wind modules. +SUBROUTINE InflowWind_ValidateInput( InitInp, InputFileData, ErrStat, ErrMsg ) + + IMPLICIT NONE + + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_ValidateInput" + + + ! Passed variables + + TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization + TYPE(InflowWind_InputFile), INTENT(INOUT) :: InputFileData !< The data for initialization + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status from this subroutine + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message from this subroutine + + + ! Local variables + INTEGER(IntKi) :: I !< Generic counter + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !----------------------------------------------- + ! Data that applies to all wind types + !----------------------------------------------- + + ! WindType + IF ( InputFileData%WindType <= Undef_WindNumber .OR. InputFileData%WindType > Highest_WindNumber ) THEN + CALL SetErrStat(ErrID_Fatal,' Invalid WindType specified. Only values of '// & + TRIM(Num2LStr( Steady_WindNumber ))//','// & + TRIM(Num2LStr( Uniform_WindNumber ))//','// & + TRIM(Num2LStr( TSFF_WindNumber ))//','// & + TRIM(Num2LStr( BladedFF_WindNumber ))//','// & + TRIM(Num2LStr( BladedFF_Shr_WindNumber ))//','// & + TRIM(Num2LStr( HAWC_WindNumber ))//', or '// & + TRIM(Num2LStr( User_WindNumber ))//' are supported.', & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + + if (InitInp%Linearize) then + + if (InputFileData%WindType /= Steady_WindNumber .and. InputFileData%WindType /= Uniform_WindNumber) then + call SetErrStat(ErrID_Fatal, 'InflowWind can perform linearization on only steady or uniform wind types.', ErrStat, ErrMsg, RoutineName) + return + end if + + if (InitInp%lidar%SensorType /= SensorType_None) then + call SetErrStat(ErrID_Fatal, 'InflowWind can not perform linearization with the lidar module enabled.', ErrStat, ErrMsg, RoutineName) + return + end if + + ! we'd have to redo the math to get this correct, so for now we are disabling upflow for linearization: + if (.not. EqualRealNos(InputFileData%VFlowAngle, 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal, 'VFlowAngle (upflow) must be 0 for linearization analysis in InflowWind.', ErrStat, ErrMsg, RoutineName) + return + end if + + end if + + + + ! make sure that all values for WindVzi are above ground. Set to 0 otherwise. + + DO I = 1, InputFileData%NWindVel + IF ( InputFileData%WindVziList(I) <= 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, ' Requested wind velocity at point ( '// & + TRIM(Num2LStr(InputFileData%WindVxiList(I)))//', '// & + TRIM(Num2LStr(InputFileData%WindVyiList(I)))//', '// & + TRIM(Num2LStr(InputFileData%WindVziList(I)))//') is below ground. Ignoring this point.', & + ErrStat, ErrMsg, RoutineName) + InputFileData%WindVziList(I) = 0.0_ReKi + ENDIF + ENDDO + + + !----------------------------------------------- + ! Data specific to a WindType + !----------------------------------------------- + + SELECT CASE ( InputFileData%WindType ) + + CASE ( Steady_WindNumber ) + CALL Steady_ValidateInput() + + CASE ( Uniform_WindNumber ) + + IF ( InitInp%WindType2UseInputFile ) CALL Uniform_ValidateInput() + + CASE ( TSFF_WindNumber ) + CALL TSFF_ValidateInput() + + CASE ( BladedFF_WindNumber, BladedFF_Shr_WindNumber ) + CALL BladedFF_ValidateInput() + + CASE ( HAWC_WindNumber ) + CALL HAWC_ValidateInput() + + CASE ( User_WindNumber ) + CALL User_ValidateInput() + + CASE ( FDext_WindNumber ) + IF ( .not. InitInp%Use4Dext) call SetErrStat(ErrID_Fatal,'4D external wind file is valid only with FAST.Farm',ErrStat,ErrMsg,RoutineName) + 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 + + ! NOTE: we are not checking the error status yet, but rather will run through the Coherent turbulence section + ! before returning. This way a user will know of errors there as well before having to fix the first + ! section. + + ! Coherent turbulence + IF ( InputFileData%CTTS_CoherentTurb ) THEN + CALL CTTS_ValidateInput() + ENDIF + + + RETURN + +CONTAINS + + !> This subroutine checks that the values for the steady wind make sense. There aren't many to check. + SUBROUTINE Steady_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="Steady_ValidateInput" + + + ! Check that HWindSpeed is positive + IF ( InputFileData%Steady_HWindSpeed <= 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Horizontal wind speed (HWindSpeed) for steady winds must be greater than zero.', & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that RefHt is positive + IF ( InputFileData%Steady_RefHt <= 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Reference height (RefHt) for steady winds must be greater than zero.', & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that PLexp is positive + IF ( InputFileData%Steady_PLexp < 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Power law exponent (PLexp) for steady winds must be positive or zero.', & + ErrStat,ErrMsg,RoutineName) + ENDIF + + RETURN + END SUBROUTINE Steady_ValidateInput + + + + !> This subroutine checks that the values for the uniform wind make sense. There isn't much to check. + SUBROUTINE Uniform_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="Uniform_ValidateInput" + + ! Local variables + LOGICAL :: TmpFileExist + + ! Check that the filename requested actually exists + INQUIRE( file=InputFileData%Uniform_FileName, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find uniform wind input file: '"//TRIM(InputFileData%Uniform_FileName)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that RefHt is positive + IF ( InputFileData%Uniform_RefHt <= 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Reference height (RefHt) for uniform winds must be greater than zero.', & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that RefLength is positive + IF ( InputFileData%Uniform_RefLength <= 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,' Reference length (RefLength) for uniform winds must be greater than zero.', & + ErrStat,ErrMsg,RoutineName) + ENDIF + + RETURN + + END SUBROUTINE Uniform_ValidateInput + + + + !> There isn't much to check for the TurbSim full-field section of the input file. + SUBROUTINE TSFF_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="TSFF_ValidateInput" + + ! Local variables + LOGICAL :: TmpFileExist + + ! Check that the filename requested actually exists + INQUIRE( file=InputFileData%TSFF_FileName, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find TurbSim full-field wind input file: '"//TRIM(InputFileData%TSFF_FileName)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + RETURN + + END SUBROUTINE TSFF_ValidateInput + + + + !> We will only check the main bladed input file here. We will check the existance of the towerfile (if requested) in the SetParameters routine. + SUBROUTINE BladedFF_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="BladedFF_ValidateInput" + + ! Local variables + LOGICAL :: TmpFileExist + + ! ! Check that the filename requested actually exists (this happens in the BladedFF submodule...) + !INQUIRE( file=InputFileData%BladedFF_FileName, exist=TmpFileExist ) + !IF ( .NOT. TmpFileExist ) THEN + ! CALL SetErrStat( ErrID_Fatal," Cannot find Bladed-style full-field wind input file: '"//TRIM(InputFileData%BladedFF_FileName)//"'", & + ! ErrStat,ErrMsg,RoutineName) + !ENDIF + + RETURN + END SUBROUTINE BladedFF_ValidateInput + + + + !> This routine checks to see if coherent turbulence can be used or not. We check the path and file + !! information before proceeding. The coherent turbulence info is loaded after the full-field files have + !! been read, and those can be very slow to load. So we preemptively check the existence of the coherent + !! turbulence file. Further checking that the coherent turbulence can actually be used is check by the + !! CTTS_Wind submodule (after the loading of the other stuff). + SUBROUTINE CTTS_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="CTTS_ValidateInput" + + ! Local variables + LOGICAL :: TmpFileExist + + ! Check if coherent turbulence can be used or not. It is only applicable to the TSFF and BladedFF wind + ! file types. + IF ( InputFileData%CTTS_CoherentTurb .AND. ( .NOT. InputFileData%WindType == TSFF_WindNumber ) & + .AND. ( .NOT. InputFileData%WindType == BladedFF_WindNumber ) ) THEN + CALL SetErrStat(ErrID_Fatal,' Coherent turbulence may only be used with full field wind data (WindType = '// & + TRIM(Num2LStr(TSFF_WindNumber))//' or '//TRIM(Num2LStr(BladedFF_WindNumber))//').', & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! Check that the CT input file exists. + INQUIRE( file=InputFileData%CTTS_FileName, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find the coherent turbulence input file: '"//TRIM(InputFileData%CTTS_FileName)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ! Check that the CT Event path exists. + ! Unfortunately there is no good portable method to do this, so we won't try. +!FIXME: See if we have anything in the library. -- Nothing I found... + + RETURN + + END SUBROUTINE CTTS_ValidateInput + + + + !> This routine checks the HAWC wind file type section of the input file. + SUBROUTINE HAWC_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="HAWC_ValidateInput" + + ! Local variables + LOGICAL :: TmpFileExist + + ! Check that the wind files exist. + INQUIRE( file=InputFileData%HAWC_FileName_u, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find the HAWC u-component wind file: '"//TRIM(InputFileData%HAWC_FileName_u)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + INQUIRE( file=InputFileData%HAWC_FileName_v, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find the HAWC v-component wind file: '"//TRIM(InputFileData%HAWC_FileName_v)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + INQUIRE( file=InputFileData%HAWC_FileName_w, exist=TmpFileExist ) + IF ( .NOT. TmpFileExist ) THEN + CALL SetErrStat( ErrID_Fatal," Cannot find the HAWC w-component wind file: '"//TRIM(InputFileData%HAWC_FileName_w)//"'", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + + ! we'll check the rest of these in the HAWC_Init() routine + + RETURN + + END SUBROUTINE HAWC_ValidateInput + + + + !> This routine is a placeholder for later development by the end user. It should only be used if additional inputs + !! for the user defined routines are added to the input file. Otherwise, this routine may be ignored by the user. + SUBROUTINE User_ValidateInput() + + CHARACTER(*), PARAMETER :: RoutineName="User_ValidateInput" + + + CALL SetErrStat( ErrID_Warn,' This subroutine has not been written yet.',ErrStat,ErrMsg,RoutineName) + + RETURN + END SUBROUTINE User_ValidateInput + + +END SUBROUTINE InflowWind_ValidateInput + + + + + +!==================================================================================================== +!> This private subroutine copies the info from the input file over to the parameters for InflowWind. +SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrMsg ) + + IMPLICIT NONE + + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_SetParameters" + + + ! Passed variables + + TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization + TYPE(InflowWind_InputFile), INTENT(INOUT) :: InputFileData !< The data for initialization + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< The parameters for InflowWind + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< The misc/optimization variables for InflowWind + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status from this subroutine + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message from this subroutine + + + ! Temporary variables + INTEGER(IntKi) :: TmpErrStat !< Temporary error status for subroutine and function calls + CHARACTER(ErrMsgLen) :: TmpErrMsg !< Temporary error message for subroutine and function calls + + ! Local variables + INTEGER(IntKi) :: I !< Generic counter + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !----------------------------------------------------------------- + ! 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%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 + + ! Copy over the list of wind coordinates. Move the arrays to the new one. + p%NWindVel = InputFileData%NWindVel + CALL AllocAry( p%WindViXYZ, 3, p%NWindVel, & + "XYZ coordinates of the requested wind points.", TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + p%WindViXYZ(1,1:p%NWindVel) = InputFileData%WindVxiList(1:p%NWindVel) + p%WindViXYZ(2,1:p%NWindVel) = InputFileData%WindVyiList(1:p%NWindVel) + p%WindViXYZ(3,1:p%NWindVel) = InputFileData%WindVziList(1:p%NWindVel) + + + ! Set the number of OutList names read in from the file + p%NumOuts = InputFileData%NumOuts + + + ! Allocate array used for calculating the AllOuts values. This has a total of nine 3d velocity vectors + ! in it (one for each of the possible WindViXYZ points). This gets passed into CalcOutput at each timestep, + ! although only the first NWindVel velocity vectors gets calculated. + CALL AllocAry( m%WindViUVW, 3, p%NWindVel, & + "Array of wind velocities corresponding to the WindViLists", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + m%WindViUVW = 0.0_ReKi + + + ! Set the OutList + CALL SetOutParam( InputFileData%OutList, p, TmpErrStat, TmpErrmsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + + if (InitInp%Linearize) then + CALL SetOutParamLin( p, TmpErrStat, TmpErrmsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + end if + + ! Allocate array for AllOuts + ALLOCATE( m%AllOuts(0:MaxOutPts), Stat=TmpErrStat ) + IF (TmpErrStat/=0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating memory for m%AllOuts.",ErrStat,ErrMsg,RoutineName) + RETURN + END IF + m%AllOuts = 0.0_ReKi + + + + !------------------------------------------------------------- + ! Setup the coordinate transforms for rotating the wind field. + !------------------------------------------------------------- + + !> Perform coordinate transformation using the PropagationDir value read in from the input file (the value stored in parameters + !! was converted from degrees to radians already). + !! @note The PropagationDir is given in Meteorological \f$\Delta\phi\f$, so this is the negative of the \f$\Delta\phi\f$ + !! for polar coordinates + !! + !! An upflow angle rotation is also included in the direction cosine matrix. + !! + !! The rotation matrix _RotToWind_, (\f$ M \f$), rotates the spatial points (\f$ [ X~ Y~ Z ] \f$) into the coordinate system + !! the wind (\f$ [ X'~ Y'~ Z' ] \f$). This is a rotation about the point \f$ [ 0~ 0~ H ] \f$ (H = hub reference height), first + !! about the \f$ Y\f$-axis (in the negative direction), followed by a rotation about \f$Z\f$-axis (also in the negative direction + !! due to the meteorological convention used). In the implementation, the rotation is about the coordinate \f$ [ 0~ 0~ H ] \f$ + !! where \f$ H \f$ is the reference height of the turbine (hub height). + !! + !! \f$ [X'~ Y'~ Z'] = M \left( [X~ Y~ Z] - [ 0~ 0~ H] \right) + [ 0~ 0~ H ] \f$ + !! + !! where + !! + !! \f{eqnarray*}{ + !! M & = & R(-\theta_y) R(-\theta_z) + !! & = & \begin{bmatrix} \cos(-\theta_y) & 0 & -\sin(-\theta_y) \\ + !! 0 & 1 & 0 \\ + !! \sin(-\theta_y) & 0 & \cos(-\theta_y) \end{bmatrix} + !! \begin{bmatrix} \cos(-\theta_z) & \sin(-\theta_z) & 0 \\ + !! -\sin(-\theta_z) & \cos(-\theta_z) & 0 \\ + !! 0 & 0 & 1 \end{bmatrix} + !! & = & \begin{bmatrix} C_y & 0 & -S_y \\ + !! 0 & 1 & 0 \\ + !! S_y & 0 & C_y \end{bmatrix} + !! \begin{bmatrix} C_z & S_z & 0 \\ + !! -S_z & C_z & 0 \\ + !! 0 & 0 & 1 \end{bmatrix} \\ + !! & & + !! & = & \begin{bmatrix} + !! \cos(-\theta_y) \cos(-\theta_z) & \cos(-\theta_y) \sin(-\theta_z) & - \sin(-\theta_y) \\ + !! - \sin(-\theta_z) & \cos(-\theta_z) & 0 \\ + !! \sin(-\theta_y) \cos(-\theta_z) & \sin(-\theta_y) \sin(-\theta_z) & \cos(-\theta_y) \\ + !! \end{bmatrix} + !! & = & \begin{bmatrix} + !! C_y C_z & C_y S_z & - S_y \\ + !! - S_z & C_z & 0 \\ + !! S_y C_z & S_y S_z & C_y \\ + !! \end{bmatrix} \\ + !! \f} + !! + !! where \f$ \theta_z \f$ is the rotation about the Z direction (_PropagationDir_) and \f$ \theta_y \f$ is + !! the upflow angle (_VFlowAngle_). + + + ! 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) /) + + ! 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] + ! 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) + + ! 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', & + TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + + p%RefPosition = (/ 0.0_ReKi, 0.0_ReKi, p%ReferenceHeight /) + + 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 + ENDDO + + p%RotateWindBox = .not. (EqualRealNos (p%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (p%VFlowAngle, 0.0_ReKi)) + +END SUBROUTINE InflowWind_SetParameters + + + + + + + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!! +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 26-Oct-2020 15:42:27. +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out 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 + + ! Local variables + + 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(59) = (/ & ! 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 ","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 ","WINDMEAS1 ","WINDMEAS2 ", & + "WINDMEAS3 ","WINDMEAS4 ","WINDMEAS5 "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(59) = (/ & ! 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 , 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 , WindMeas1 , WindMeas2 , & + WindMeas3 , WindMeas4 , WindMeas5 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(59) = (/ & ! 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)","(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)", & + "(m/s)","(m/s)","(m/s)"/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + ! NOTE: we are not checking that the coordinates input for the WindVxi, WindVyi, and WindVzi are valid here. We are + ! checking that at the input file validation (they simply get zeroed with a warning if there is an issue). + + ! make sure we don't ask for outputs that don't exist: + DO I = p%NWindVel+1, 9 + InvalidOutput( WindVelX( I) ) = .TRUE. + InvalidOutput( WindVelY( I) ) = .TRUE. + InvalidOutput( WindVelZ( I) ) = .TRUE. + InvalidOutput( WindVelXY( I) ) = .TRUE. + InvalidOutput( WindVelMag(I) ) = .TRUE. + InvalidOutput( WindAngXY( I) ) = .TRUE. + END DO + + DO I=p%lidar%NumPulseGate+1,5 + InvalidOutput( WindMeas(I) ) = .TRUE. + END DO + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the InflowWind OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Indx = ParamIndxAry(Indx) + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +!.................................................................................................................................. +!> This routine checks to see if any requested output channel names are to be output in linearization analysis. +!! note that we output all WriteOutput values and assume that none of them depend on inputs (so I don't need this mapping any more) +SUBROUTINE SetOutParamLin( p, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables + + 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 + + ! Local variables + + INTEGER :: ErrStat2 ! temporary (local) error status + INTEGER :: I ! Generic loop-counting index + INTEGER :: J ! Generic loop-counting index + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParamLin" + + ErrStat = ErrID_None + ErrMsg = "" + + call AllocAry(p%OutParamLinIndx, 2, p%NumOuts, 'OutParamLinIndx', ErrStat2, ErrMsg2) + call setErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + p%OutParamLinIndx = 0 ! initialize to 0 + do i = 1,p%NumOuts + if (p%OutParam(i)%SignM /= 0 ) then + + do j=1,size(WindVelX) + if ( p%OutParam(i)%Indx == WindVelX(j) ) then + p%OutParamLinIndx(1,i) = j + p%OutParamLinIndx(2,i) = 1 + exit !exit j loop; move to next parameter + elseif ( p%OutParam(i)%Indx == WindVelY(j) ) then + p%OutParamLinIndx(1,i) = j + p%OutParamLinIndx(2,i) = 2 + exit !exit j loop; move to next parameter + elseif ( p%OutParam(i)%Indx == WindVelZ(j) ) then + p%OutParamLinIndx(1,i) = j + p%OutParamLinIndx(2,i) = 3 + exit !exit j loop; move to next parameter + end if + end do + + end if + end do + + + +END SUBROUTINE SetOutParamLin +!.................................................................................................................................. +SUBROUTINE SetAllOuts( p, y, m, ErrStat, ErrMsg ) + + IMPLICIT NONE + + CHARACTER(*), PARAMETER :: RoutineName="SetAllOuts" + + + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< The parameters for InflowWind + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Outputs + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status from this subroutine + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message from this subroutine + + + ! Local Variables + INTEGER(IntKi) :: I ! Generic counter + + + ! Initialization + ErrStat = ErrID_None + ErrMsg = '' + + ! We set the unused values to 0 at init, so we don't need to set them again here: + DO I = 1,p%NWindVel + + m%AllOuts( WindVelX(I) ) = m%WindViUVW(1,I) + m%AllOuts( WindVelY(I) ) = m%WindViUVW(2,I) + m%AllOuts( WindVelZ(I) ) = m%WindViUVW(3,I) + + m%AllOuts( WindVelXY(I) ) = SQRT( m%WindViUVW(1,I)**2 + m%WindViUVW(2,I)**2 ) + m%AllOuts( WindVelMag(I) ) = SQRT( m%WindViUVW(1,I)**2 + m%WindViUVW(2,I)**2 + m%WindViUVW(3,I)**2 ) + if ( m%AllOuts( WindVelXY(I) ) == 0.0_ReKi) then + m%AllOuts( WindAngXY(I) ) = 0.0_ReKi + 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 + + !FIXME: Add in Wind1Dir etc. -- although those can be derived outside of FAST. + + DO I = 1,MIN(5, p%lidar%NumPulseGate ) + m%AllOuts( WindMeas(I) ) = y%lidar%lidSpeed(I) + END DO + +END SUBROUTINE SetAllOuts + + + + +!==================================================================================================== +SUBROUTINE InflowWind_OpenSumFile( SumFileUnit, SummaryName, IfW_Prog, WindType, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER(IntKi), INTENT( OUT) :: SumFileUnit !< the unit number for the InflowWindsummary file + CHARACTER(*), INTENT(IN ) :: SummaryName !< the name of the InflowWind summary file + TYPE(ProgDesc), INTENT(IN ) :: IfW_Prog !< the name/version/date of the InflowWind program + INTEGER(IntKi), INTENT(IN ) :: WindType !< type identifying what wind we are using + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + INTEGER(IntKi) :: TmpErrStat !< Temporary error status for checking how the WRITE worked + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + SumFileUnit = -1 + CALL GetNewUnit( SumFileUnit ) + CALL OpenFOutFile ( SumFileUnit, SummaryName, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) RETURN + + + ! Write the summary file header + WRITE(SumFileUnit,'(/,A/)',IOSTAT=TmpErrStat) 'This summary file was generated by '//TRIM( IfW_Prog%Name )//& + ' '//TRIM( IfW_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' + WRITE(SumFileUnit,'(A14,I1)',IOSTAT=TmpErrStat) ' WindType: ',WindType + IF ( TmpErrStat /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Error writing to summary file.',ErrStat,ErrMsg,'') + RETURN + END IF + +END SUBROUTINE InflowWind_OpenSumFile + +!==================================================================================================== +SUBROUTINE InflowWind_CloseSumFile( SumFileUnit, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER(IntKi), INTENT(INOUT) :: SumFileUnit !< the unit number for the InflowWindsummary file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + INTEGER(IntKi) :: TmpErrStat + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Write any closing information in the summary file + IF ( SumFileUnit > 0_IntKi ) THEN + WRITE (SumFileUnit,'(/,A/)', IOSTAT=TmpErrStat) 'This summary file was closed on '//CurDate()//' at '//CurTime()//'.' + IF (TmpErrStat /= 0_IntKi) CALL SetErrStat( ErrID_Fatal, 'Problem writing to the InflowWind summary file.', ErrStat, ErrMsg, '' ) + + ! Close the file + CLOSE( SumFileUnit, IOSTAT=TmpErrStat ) + IF (TmpErrStat /= 0_IntKi) CALL SetErrStat( ErrID_Fatal, 'Problem closing the InflowWind summary file.', ErrStat, ErrMsg, '' ) + END IF + + + +END SUBROUTINE InflowWind_CloseSumFile + +!==================================================================================================== + + + +SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, FillWrOut, ErrStat, ErrMsg ) + + + 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 + REAL(ReKi) :: DiskVel(3) !< HACK for AD14: disk velocity output at Time + + 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 + !----------------------------------------------------------------------- + + + !> 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, & + DiskVel, 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, & + DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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, DiskVel, 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) + DiskVel = 0.0_ReKi ! this is only for AD14, which we frankly don't care about in 4Dext wind + + 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 + + + ! DiskVel values over to the output and apply the coordinate transformation + y%DiskVel = MATMUL( p%RotFromWind, DiskVel ) + + + ! Done with the prime coordinates for the XYZ position information that was passed in. + IF (ALLOCATED(PositionXYZprime)) DEALLOCATE(PositionXYZprime) + + + +END SUBROUTINE CalculateOutput + +!==================================================================================================== +!> this routine calculates the mean wind speed +SUBROUTINE InflowWind_GetMean( StartTime, EndTime, delta_time, InputPosition, MeanVelocity, & + p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!---------------------------------------------------------------------------------------------------- + ! Inputs / Outputs + REAL(DbKi), INTENT(IN ) :: StartTime !< first time in range from which to calculate mean + REAL(DbKi), INTENT(IN ) :: EndTime !< last time in range from which to calculate mean + REAL(DbKi), INTENT(IN ) :: delta_time !< dt in time range from which to calculate mean + REAL(ReKi), INTENT(IN ) :: InputPosition(3) !< X, Y, Z positions + REAL(ReKi), INTENT( OUT) :: MeanVelocity(3) !< at InputPosition + + 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/optimization states at Time + 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 + + + ! local variables + REAL(DbKi) :: Time + REAL(DbKi) :: SumVel(3) + INTEGER(IntKi) :: I + INTEGER(IntKi) :: Nt + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_GetMean' + + TYPE(InflowWind_InputType) :: Input ! position where wind speed should be returned + TYPE(InflowWind_OutputType) :: Output ! velocity at InputPosition + + ! main body: + + IF ( EqualRealNos(delta_time,0.0_DbKi) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":delta time must be non-zero." + RETURN + END IF + + ErrStat = ErrID_None + ErrMsg = "" + + + ! allocate arrays to compute outputs + CALL AllocAry(Input%PositionXYZ, 3,1, 'Input%PositionXYZ',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(Output%VelocityUVW, 3,1, 'Output%VelocityUVW',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + Nt = (EndTime - StartTime) / delta_time + SumVel = 0.0 + Input%PositionXYZ(:,1) = InputPosition + + DO I=1,Nt + + Time = StartTime + (I-1)*delta_time + + CALL CalculateOutput( Time, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( ErrStat >= AbortErrLev ) THEN + MeanVelocity = SumVel / REAL(I-1, ReKi) + CALL Cleanup() + RETURN + ELSE + SumVel = SumVel + Output%VelocityUVW(:,1) + END IF + + END DO + + MeanVelocity = SumVel / REAL(Nt, ReKi) + CALL Cleanup() + RETURN + +CONTAINS +!............................ + SUBROUTINE Cleanup() + + IF (ALLOCATED(Input%PositionXYZ)) DEALLOCATE(Input%PositionXYZ) + IF (ALLOCATED(Output%VelocityUVW)) DEALLOCATE(Output%VelocityUVW) + + END SUBROUTINE Cleanup +!............................ +END SUBROUTINE InflowWind_GetMean +!********************************************************************************************************************************** +END MODULE InflowWind_Subs diff --git a/OpenFAST/modules/inflowwind/src/InflowWind_Types.f90 b/OpenFAST/modules/inflowwind/src/InflowWind_Types.f90 new file mode 100644 index 000000000..a3f726ff6 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/InflowWind_Types.f90 @@ -0,0 +1,5830 @@ +!STARTOFREGISTRYGENERATEDFILE 'InflowWind_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_Types +!................................................................................................................................. +! This file is part of InflowWind. +! +! 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. 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_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE IfW_UniformWind_Types +USE IfW_FFWind_Base_Types +USE IfW_TSFFWind_Types +USE IfW_BladedFFWind_Types +USE IfW_HAWCWind_Types +USE IfW_UserWind_Types +USE IfW_4Dext_Types +USE Lidar_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: Undef_WindNumber = 0 ! This is the code for an undefined WindFileType [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Steady_WindNumber = 1 ! Steady wind. Calculated internally. [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Uniform_WindNumber = 2 ! Uniform wind. Formally known as a Hub-Height wind file. [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: TSFF_WindNumber = 3 ! TurbSim full-field binary file. [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: BladedFF_WindNumber = 4 ! Bladed style binary full-field file. Includes native bladed format [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: HAWC_WindNumber = 5 ! HAWC wind file. [-] + 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. [-] +! ========= 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 [-] + 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) :: 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] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WindVziList !< List of Z coordinates for wind velocity measurements [meters] + REAL(ReKi) :: Steady_HWindSpeed !< Steady wind -- horizontal windspeed [meters/s] + REAL(ReKi) :: Steady_RefHt !< Steady wind -- reference height [meters] + REAL(ReKi) :: Steady_PLexp !< Steady wind -- power law exponent [-] + CHARACTER(1024) :: Uniform_FileName !< Uniform wind -- filename [-] + REAL(ReKi) :: Uniform_RefHt !< Uniform wind -- reference height [meters] + REAL(ReKi) :: Uniform_RefLength !< Uniform wind -- reference length [meters] + CHARACTER(1024) :: TSFF_FileName !< TurbSim Full-Field -- filename [-] + CHARACTER(1024) :: BladedFF_FileName !< Bladed-style Full-Field -- filename [-] + LOGICAL :: BladedFF_TowerFile !< Bladed-style Full-Field -- tower file exists [-] + LOGICAL :: CTTS_CoherentTurb = .FALSE. !< Coherent turbulence data exists [-] + CHARACTER(1024) :: CTTS_FileName !< Name of coherent turbulence file [-] + CHARACTER(1024) :: CTTS_Path !< Path to coherent turbulence binary data files [-] + CHARACTER(1024) :: HAWC_FileName_u !< HAWC -- u component binary data file name [-] + CHARACTER(1024) :: HAWC_FileName_v !< HAWC -- v component binary data file name [-] + CHARACTER(1024) :: HAWC_FileName_w !< HAWC -- w component binary data file name [-] + INTEGER(IntKi) :: HAWC_nx !< HAWC -- number of grids in x direction [-] + INTEGER(IntKi) :: HAWC_ny !< HAWC -- number of grids in y direction [-] + INTEGER(IntKi) :: HAWC_nz !< HAWC -- number of grids in z direction [-] + REAL(ReKi) :: HAWC_dx !< HAWC -- distance between points in x direction [meters] + REAL(ReKi) :: HAWC_dy !< HAWC -- distance between points in y direction [meters] + REAL(ReKi) :: HAWC_dz !< HAWC -- distance between points in z direction [meters] + LOGICAL :: SumPrint !< Write summary info to a file <ROOTNAME>.IfW.Sum [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + INTEGER(IntKi) :: SensorType = SensorType_None !< Sensor type (for lidar/sensor module) [-] + 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 [-] + END TYPE InflowWind_InputFile +! ======================= +! ========= InflowWind_InitInputType ======= + TYPE, PUBLIC :: InflowWind_InitInputType + CHARACTER(1024) :: InputFileName !< Name of the InflowWind input file to use [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + LOGICAL :: Use4Dext = .FALSE. !< Flag that tells this module if an external module will pass it 4-D velocity grids. [-] + INTEGER(IntKi) :: NumWindPoints !< Number of wind velocity points expected [-] + LOGICAL :: UseInputFile = .TRUE. !< Should we read everthing from an input file, or do we get it some other way [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + 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. [-] + TYPE(Lidar_InitInputType) :: lidar !< InitInput for lidar data [-] + TYPE(IfW_4Dext_InitInputType) :: FDext !< InitInput for lidar data [-] + END TYPE InflowWind_InitInputType +! ======================= +! ========= InflowWind_InitOutputType ======= + TYPE, PUBLIC :: InflowWind_InitOutputType + 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 [-] + 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + END TYPE InflowWind_InitOutputType +! ======================= +! ========= 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] + END TYPE InflowWind_MiscVarType +! ======================= +! ========= InflowWind_ParameterType ======= + TYPE, PUBLIC :: InflowWind_ParameterType + 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 [-] + 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) :: 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(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 [-] + END TYPE InflowWind_ParameterType +! ======================= +! ========= InflowWind_InputType ======= + TYPE, PUBLIC :: InflowWind_InputType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PositionXYZ !< Array holding the input positions at a given timestep [meters] + TYPE(Lidar_InputType) :: lidar !< Lidar data [-] + END TYPE InflowWind_InputType +! ======================= +! ========= 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 :: 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] + TYPE(Lidar_OutputType) :: lidar !< Lidar data [-] + END TYPE InflowWind_OutputType +! ======================= +! ========= InflowWind_ContinuousStateType ======= + TYPE, PUBLIC :: InflowWind_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE InflowWind_ContinuousStateType +! ======================= +! ========= InflowWind_DiscreteStateType ======= + TYPE, PUBLIC :: InflowWind_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE InflowWind_DiscreteStateType +! ======================= +! ========= InflowWind_ConstraintStateType ======= + TYPE, PUBLIC :: InflowWind_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE InflowWind_ConstraintStateType +! ======================= +! ========= InflowWind_OtherStateType ======= + TYPE, PUBLIC :: InflowWind_OtherStateType + REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE InflowWind_OtherStateType +! ======================= +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 ) + TYPE(WindFileMetaData), INTENT(INOUT) :: WindFileMetaDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyWindFileMetaData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + 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 + 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_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%EchoFlag = SrcInputFileData%EchoFlag + DstInputFileData%WindType = SrcInputFileData%WindType + DstInputFileData%PropagationDir = SrcInputFileData%PropagationDir + DstInputFileData%VFlowAngle = SrcInputFileData%VFlowAngle + DstInputFileData%NWindVel = SrcInputFileData%NWindVel +IF (ALLOCATED(SrcInputFileData%WindVxiList)) THEN + i1_l = LBOUND(SrcInputFileData%WindVxiList,1) + i1_u = UBOUND(SrcInputFileData%WindVxiList,1) + IF (.NOT. ALLOCATED(DstInputFileData%WindVxiList)) THEN + ALLOCATE(DstInputFileData%WindVxiList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%WindVxiList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%WindVxiList = SrcInputFileData%WindVxiList +ENDIF +IF (ALLOCATED(SrcInputFileData%WindVyiList)) THEN + i1_l = LBOUND(SrcInputFileData%WindVyiList,1) + i1_u = UBOUND(SrcInputFileData%WindVyiList,1) + IF (.NOT. ALLOCATED(DstInputFileData%WindVyiList)) THEN + ALLOCATE(DstInputFileData%WindVyiList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%WindVyiList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%WindVyiList = SrcInputFileData%WindVyiList +ENDIF +IF (ALLOCATED(SrcInputFileData%WindVziList)) THEN + i1_l = LBOUND(SrcInputFileData%WindVziList,1) + i1_u = UBOUND(SrcInputFileData%WindVziList,1) + IF (.NOT. ALLOCATED(DstInputFileData%WindVziList)) THEN + ALLOCATE(DstInputFileData%WindVziList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%WindVziList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%WindVziList = SrcInputFileData%WindVziList +ENDIF + DstInputFileData%Steady_HWindSpeed = SrcInputFileData%Steady_HWindSpeed + DstInputFileData%Steady_RefHt = SrcInputFileData%Steady_RefHt + DstInputFileData%Steady_PLexp = SrcInputFileData%Steady_PLexp + DstInputFileData%Uniform_FileName = SrcInputFileData%Uniform_FileName + DstInputFileData%Uniform_RefHt = SrcInputFileData%Uniform_RefHt + DstInputFileData%Uniform_RefLength = SrcInputFileData%Uniform_RefLength + DstInputFileData%TSFF_FileName = SrcInputFileData%TSFF_FileName + DstInputFileData%BladedFF_FileName = SrcInputFileData%BladedFF_FileName + DstInputFileData%BladedFF_TowerFile = SrcInputFileData%BladedFF_TowerFile + DstInputFileData%CTTS_CoherentTurb = SrcInputFileData%CTTS_CoherentTurb + DstInputFileData%CTTS_FileName = SrcInputFileData%CTTS_FileName + DstInputFileData%CTTS_Path = SrcInputFileData%CTTS_Path + DstInputFileData%HAWC_FileName_u = SrcInputFileData%HAWC_FileName_u + DstInputFileData%HAWC_FileName_v = SrcInputFileData%HAWC_FileName_v + DstInputFileData%HAWC_FileName_w = SrcInputFileData%HAWC_FileName_w + DstInputFileData%HAWC_nx = SrcInputFileData%HAWC_nx + DstInputFileData%HAWC_ny = SrcInputFileData%HAWC_ny + DstInputFileData%HAWC_nz = SrcInputFileData%HAWC_nz + DstInputFileData%HAWC_dx = SrcInputFileData%HAWC_dx + DstInputFileData%HAWC_dy = SrcInputFileData%HAWC_dy + DstInputFileData%HAWC_dz = SrcInputFileData%HAWC_dz + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + DstInputFileData%SensorType = SrcInputFileData%SensorType + DstInputFileData%NumPulseGate = SrcInputFileData%NumPulseGate + DstInputFileData%RotorApexOffsetPos = SrcInputFileData%RotorApexOffsetPos + DstInputFileData%LidRadialVel = SrcInputFileData%LidRadialVel + CALL IfW_FFWind_CopyInitInput( SrcInputFileData%FF, DstInputFileData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_CopyInputFile + + SUBROUTINE InflowWind_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(InflowWind_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%WindVxiList)) THEN + DEALLOCATE(InputFileData%WindVxiList) +ENDIF +IF (ALLOCATED(InputFileData%WindVyiList)) THEN + DEALLOCATE(InputFileData%WindVyiList) +ENDIF +IF (ALLOCATED(InputFileData%WindVziList)) THEN + DEALLOCATE(InputFileData%WindVziList) +ENDIF +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF + CALL IfW_FFWind_DestroyInitInput( InputFileData%FF, ErrStat, ErrMsg ) + END SUBROUTINE InflowWind_DestroyInputFile + + SUBROUTINE InflowWind_PackInputFile( 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_InputFile), 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_PackInputFile' + ! 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 ! EchoFlag + Int_BufSz = Int_BufSz + 1 ! WindType + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! NWindVel + Int_BufSz = Int_BufSz + 1 ! WindVxiList allocated yes/no + IF ( ALLOCATED(InData%WindVxiList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WindVxiList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindVxiList) ! WindVxiList + END IF + Int_BufSz = Int_BufSz + 1 ! WindVyiList allocated yes/no + IF ( ALLOCATED(InData%WindVyiList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WindVyiList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindVyiList) ! WindVyiList + END IF + Int_BufSz = Int_BufSz + 1 ! WindVziList allocated yes/no + IF ( ALLOCATED(InData%WindVziList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WindVziList upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindVziList) ! WindVziList + END IF + Re_BufSz = Re_BufSz + 1 ! Steady_HWindSpeed + Re_BufSz = Re_BufSz + 1 ! Steady_RefHt + Re_BufSz = Re_BufSz + 1 ! Steady_PLexp + Int_BufSz = Int_BufSz + 1*LEN(InData%Uniform_FileName) ! Uniform_FileName + Re_BufSz = Re_BufSz + 1 ! Uniform_RefHt + Re_BufSz = Re_BufSz + 1 ! Uniform_RefLength + Int_BufSz = Int_BufSz + 1*LEN(InData%TSFF_FileName) ! TSFF_FileName + Int_BufSz = Int_BufSz + 1*LEN(InData%BladedFF_FileName) ! BladedFF_FileName + Int_BufSz = Int_BufSz + 1 ! BladedFF_TowerFile + Int_BufSz = Int_BufSz + 1 ! CTTS_CoherentTurb + Int_BufSz = Int_BufSz + 1*LEN(InData%CTTS_FileName) ! CTTS_FileName + Int_BufSz = Int_BufSz + 1*LEN(InData%CTTS_Path) ! CTTS_Path + Int_BufSz = Int_BufSz + 1*LEN(InData%HAWC_FileName_u) ! HAWC_FileName_u + Int_BufSz = Int_BufSz + 1*LEN(InData%HAWC_FileName_v) ! HAWC_FileName_v + Int_BufSz = Int_BufSz + 1*LEN(InData%HAWC_FileName_w) ! HAWC_FileName_w + Int_BufSz = Int_BufSz + 1 ! HAWC_nx + Int_BufSz = Int_BufSz + 1 ! HAWC_ny + Int_BufSz = Int_BufSz + 1 ! HAWC_nz + Re_BufSz = Re_BufSz + 1 ! HAWC_dx + Re_BufSz = Re_BufSz + 1 ! HAWC_dy + Re_BufSz = Re_BufSz + 1 ! HAWC_dz + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + END IF + Int_BufSz = Int_BufSz + 1 ! SensorType + Int_BufSz = Int_BufSz + 1 ! NumPulseGate + Re_BufSz = Re_BufSz + SIZE(InData%RotorApexOffsetPos) ! RotorApexOffsetPos + 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 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 + + IntKiBuf(Int_Xferred) = TRANSFER(InData%EchoFlag, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WindType + 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) = InData%NWindVel + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WindVxiList) ) 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%WindVxiList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindVxiList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WindVxiList,1), UBOUND(InData%WindVxiList,1) + ReKiBuf(Re_Xferred) = InData%WindVxiList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WindVyiList) ) 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%WindVyiList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindVyiList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WindVyiList,1), UBOUND(InData%WindVyiList,1) + ReKiBuf(Re_Xferred) = InData%WindVyiList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WindVziList) ) 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%WindVziList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindVziList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WindVziList,1), UBOUND(InData%WindVziList,1) + ReKiBuf(Re_Xferred) = InData%WindVziList(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Steady_HWindSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Steady_RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Steady_PLexp + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%Uniform_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%Uniform_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%Uniform_RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Uniform_RefLength + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(InData%TSFF_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%TSFF_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%BladedFF_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%BladedFF_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%BladedFF_TowerFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CTTS_CoherentTurb, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%CTTS_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%CTTS_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%CTTS_Path) + IntKiBuf(Int_Xferred) = ICHAR(InData%CTTS_Path(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%HAWC_FileName_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%HAWC_FileName_u(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%HAWC_FileName_v) + IntKiBuf(Int_Xferred) = ICHAR(InData%HAWC_FileName_v(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%HAWC_FileName_w) + IntKiBuf(Int_Xferred) = ICHAR(InData%HAWC_FileName_w(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%HAWC_nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%HAWC_ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%HAWC_nz + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HAWC_dx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HAWC_dy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HAWC_dz + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = InData%SensorType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumPulseGate + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RotorApexOffsetPos,1), UBOUND(InData%RotorApexOffsetPos,1) + ReKiBuf(Re_Xferred) = InData%RotorApexOffsetPos(i1) + Re_Xferred = Re_Xferred + 1 + 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 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_PackInputFile + + SUBROUTINE InflowWind_UnPackInputFile( 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_InputFile), 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_UnPackInputFile' + ! 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%EchoFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%EchoFlag) + Int_Xferred = Int_Xferred + 1 + OutData%WindType = 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%NWindVel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindVxiList 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%WindVxiList)) DEALLOCATE(OutData%WindVxiList) + ALLOCATE(OutData%WindVxiList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindVxiList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WindVxiList,1), UBOUND(OutData%WindVxiList,1) + OutData%WindVxiList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindVyiList 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%WindVyiList)) DEALLOCATE(OutData%WindVyiList) + ALLOCATE(OutData%WindVyiList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindVyiList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WindVyiList,1), UBOUND(OutData%WindVyiList,1) + OutData%WindVyiList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindVziList 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%WindVziList)) DEALLOCATE(OutData%WindVziList) + ALLOCATE(OutData%WindVziList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindVziList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WindVziList,1), UBOUND(OutData%WindVziList,1) + OutData%WindVziList(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Steady_HWindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Steady_RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Steady_PLexp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%Uniform_FileName) + OutData%Uniform_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Uniform_RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Uniform_RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + DO I = 1, LEN(OutData%TSFF_FileName) + OutData%TSFF_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%BladedFF_FileName) + OutData%BladedFF_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%BladedFF_TowerFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%BladedFF_TowerFile) + Int_Xferred = Int_Xferred + 1 + OutData%CTTS_CoherentTurb = TRANSFER(IntKiBuf(Int_Xferred), OutData%CTTS_CoherentTurb) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%CTTS_FileName) + OutData%CTTS_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%CTTS_Path) + OutData%CTTS_Path(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%HAWC_FileName_u) + OutData%HAWC_FileName_u(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%HAWC_FileName_v) + OutData%HAWC_FileName_v(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%HAWC_FileName_w) + OutData%HAWC_FileName_w(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%HAWC_nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HAWC_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HAWC_nz = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HAWC_dx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HAWC_dy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HAWC_dz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%SensorType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumPulseGate = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RotorApexOffsetPos,1) + i1_u = UBOUND(OutData%RotorApexOffsetPos,1) + DO i1 = LBOUND(OutData%RotorApexOffsetPos,1), UBOUND(OutData%RotorApexOffsetPos,1) + OutData%RotorApexOffsetPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%LidRadialVel = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidRadialVel) + 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 InflowWind_UnPackInputFile + + SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(InflowWind_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 = 'InflowWind_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFileName = SrcInitInputData%InputFileName + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%Use4Dext = SrcInitInputData%Use4Dext + DstInitInputData%NumWindPoints = SrcInitInputData%NumWindPoints + DstInitInputData%UseInputFile = SrcInitInputData%UseInputFile + DstInitInputData%RootName = SrcInitInputData%RootName + CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%PassedFileData, DstInitInputData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%WindType2UseInputFile = SrcInitInputData%WindType2UseInputFile + CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%WindType2Data, DstInitInputData%WindType2Data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + 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 SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_CopyInitInput + + SUBROUTINE InflowWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(InflowWind_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyfileinfotype( InitInputData%PassedFileData, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroyfileinfotype( InitInputData%WindType2Data, ErrStat, ErrMsg ) + CALL Lidar_DestroyInitInput( InitInputData%lidar, ErrStat, ErrMsg ) + CALL IfW_4Dext_DestroyInitInput( InitInputData%FDext, ErrStat, ErrMsg ) + END SUBROUTINE InflowWind_DestroyInitInput + + SUBROUTINE InflowWind_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(InflowWind_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_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%InputFileName) ! InputFileName + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1 ! Use4Dext + Int_BufSz = Int_BufSz + 1 ! NumWindPoints + Int_BufSz = Int_BufSz + 1 ! UseInputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + ! 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 + Int_BufSz = Int_BufSz + 1 ! WindType2UseInputFile + Int_BufSz = Int_BufSz + 3 ! WindType2Data: size of buffers for each call to pack subtype + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%WindType2Data, ErrStat2, ErrMsg2, .TRUE. ) ! WindType2Data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WindType2Data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WindType2Data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WindType2Data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + 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) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! lidar + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! lidar + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! lidar + 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_PackInitInput( 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 + 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%InputFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Use4Dext, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumWindPoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WindType2UseInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%WindType2Data, ErrStat2, ErrMsg2, OnlySize ) ! WindType2Data + 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 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 + + 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_PackInitInput( 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 SUBROUTINE InflowWind_PackInitInput + + SUBROUTINE InflowWind_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(InflowWind_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_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%InputFileName) + OutData%InputFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%Use4Dext = TRANSFER(IntKiBuf(Int_Xferred), OutData%Use4Dext) + Int_Xferred = Int_Xferred + 1 + OutData%NumWindPoints = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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) + OutData%WindType2UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%WindType2UseInputFile) + 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%WindType2Data, ErrStat2, ErrMsg2 ) ! WindType2Data + 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 Lidar_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%lidar, ErrStat2, ErrMsg2 ) ! lidar + 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_UnpackInitInput( 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) + END SUBROUTINE InflowWind_UnPackInitInput + + SUBROUTINE InflowWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(InflowWind_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 = 'InflowWind_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + 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 SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF + END SUBROUTINE InflowWind_CopyInitOutput + + SUBROUTINE InflowWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(InflowWind_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + CALL InflowWind_Destroywindfilemetadata( InitOutputData%WindFileInfo, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF + END SUBROUTINE InflowWind_DestroyInitOutput + + SUBROUTINE InflowWind_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(InflowWind_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_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 ! 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 SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! WindFileInfo + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! WindFileInfo + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! WindFileInfo + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 InflowWind_Packwindfilemetadata( Re_Buf, Db_Buf, Int_Buf, InData%WindFileInfo, ErrStat2, ErrMsg2, OnlySize ) ! WindFileInfo + 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%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE InflowWind_PackInitOutput + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 InflowWind_Unpackwindfilemetadata( Re_Buf, Db_Buf, Int_Buf, OutData%WindFileInfo, ErrStat2, ErrMsg2 ) ! WindFileInfo + 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 ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE InflowWind_UnPackInitOutput + + SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(InflowWind_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_CopyMisc' +! + 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) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF +IF (ALLOCATED(SrcMiscData%WindViUVW)) THEN + i1_l = LBOUND(SrcMiscData%WindViUVW,1) + i1_u = UBOUND(SrcMiscData%WindViUVW,1) + i2_l = LBOUND(SrcMiscData%WindViUVW,2) + i2_u = UBOUND(SrcMiscData%WindViUVW,2) + IF (.NOT. ALLOCATED(DstMiscData%WindViUVW)) THEN + ALLOCATE(DstMiscData%WindViUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%WindViUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%WindViUVW = SrcMiscData%WindViUVW +ENDIF + END SUBROUTINE InflowWind_CopyMisc + + SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL IfW_UniformWind_DestroyMisc( MiscData%UniformWind, ErrStat, ErrMsg ) + CALL IfW_TSFFWind_DestroyMisc( MiscData%TSFFWind, ErrStat, ErrMsg ) + CALL IfW_HAWCWind_DestroyMisc( MiscData%HAWCWind, ErrStat, ErrMsg ) + CALL IfW_BladedFFWind_DestroyMisc( MiscData%BladedFFWind, ErrStat, ErrMsg ) + CALL IfW_UserWind_DestroyMisc( MiscData%UserWind, ErrStat, ErrMsg ) + CALL IfW_4Dext_DestroyMisc( MiscData%FDext, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF +IF (ALLOCATED(MiscData%WindViUVW)) THEN + DEALLOCATE(MiscData%WindViUVW) +ENDIF + 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 + + 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 + + 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 ! AllOuts allocated yes/no + IF ( ALLOCATED(InData%AllOuts) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AllOuts upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + END IF + Int_BufSz = Int_BufSz + 1 ! WindViUVW allocated yes/no + 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 + 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 + 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 + IF ( .NOT. ALLOCATED(InData%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WindViUVW) ) 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%WindViUVW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViUVW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindViUVW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViUVW,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WindViUVW,2), UBOUND(InData%WindViUVW,2) + DO i1 = LBOUND(InData%WindViUVW,1), UBOUND(InData%WindViUVW,1) + ReKiBuf(Re_Xferred) = InData%WindViUVW(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE InflowWind_PackMisc + + SUBROUTINE InflowWind_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(InflowWind_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_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 + 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 + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindViUVW 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%WindViUVW)) DEALLOCATE(OutData%WindViUVW) + ALLOCATE(OutData%WindViUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindViUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WindViUVW,2), UBOUND(OutData%WindViUVW,2) + DO i1 = LBOUND(OutData%WindViUVW,1), UBOUND(OutData%WindViUVW,1) + OutData%WindViUVW(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE InflowWind_UnPackMisc + + SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_ParameterType), INTENT(IN) :: SrcParamData + TYPE(InflowWind_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%RootFileName = SrcParamData%RootFileName + DstParamData%CTTS_Flag = SrcParamData%CTTS_Flag + DstParamData%RotateWindBox = SrcParamData%RotateWindBox + 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) + i2_l = LBOUND(SrcParamData%WindViXYZprime,2) + i2_u = UBOUND(SrcParamData%WindViXYZprime,2) + IF (.NOT. ALLOCATED(DstParamData%WindViXYZprime)) THEN + ALLOCATE(DstParamData%WindViXYZprime(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WindViXYZprime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + 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) + i2_l = LBOUND(SrcParamData%WindViXYZ,2) + i2_u = UBOUND(SrcParamData%WindViXYZ,2) + IF (.NOT. ALLOCATED(DstParamData%WindViXYZ)) THEN + ALLOCATE(DstParamData%WindViXYZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WindViXYZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WindViXYZ = SrcParamData%WindViXYZ +ENDIF + 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 + DstParamData%NumOuts = SrcParamData%NumOuts +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%OutParamLinIndx)) THEN + i1_l = LBOUND(SrcParamData%OutParamLinIndx,1) + i1_u = UBOUND(SrcParamData%OutParamLinIndx,1) + i2_l = LBOUND(SrcParamData%OutParamLinIndx,2) + i2_u = UBOUND(SrcParamData%OutParamLinIndx,2) + IF (.NOT. ALLOCATED(DstParamData%OutParamLinIndx)) THEN + ALLOCATE(DstParamData%OutParamLinIndx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParamLinIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%OutParamLinIndx = SrcParamData%OutParamLinIndx +ENDIF + CALL Lidar_CopyParam( SrcParamData%lidar, DstParamData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_CopyParam + + SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%WindViXYZprime)) THEN + DEALLOCATE(ParamData%WindViXYZprime) +ENDIF +IF (ALLOCATED(ParamData%WindViXYZ)) THEN + DEALLOCATE(ParamData%WindViXYZ) +ENDIF + CALL IfW_UniformWind_DestroyParam( ParamData%UniformWind, ErrStat, ErrMsg ) + CALL IfW_TSFFWind_DestroyParam( ParamData%TSFFWind, ErrStat, ErrMsg ) + CALL IfW_BladedFFWind_DestroyParam( ParamData%BladedFFWind, ErrStat, ErrMsg ) + CALL IfW_HAWCWind_DestroyParam( ParamData%HAWCWind, ErrStat, ErrMsg ) + CALL IfW_UserWind_DestroyParam( ParamData%UserWind, ErrStat, ErrMsg ) + CALL IfW_4Dext_DestroyParam( ParamData%FDext, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%OutParamLinIndx)) THEN + DEALLOCATE(ParamData%OutParamLinIndx) +ENDIF + CALL Lidar_DestroyParam( ParamData%lidar, ErrStat, ErrMsg ) + END SUBROUTINE InflowWind_DestroyParam + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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*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 ! 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 ! NumOuts + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OutParamLinIndx allocated yes/no + IF ( ALLOCATED(InData%OutParamLinIndx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OutParamLinIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutParamLinIndx) ! OutParamLinIndx + END IF + Int_BufSz = Int_BufSz + 3 ! lidar: size of buffers for each call to pack subtype + CALL Lidar_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, .TRUE. ) ! lidar + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! lidar + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! lidar + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! lidar + 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%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)) + 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 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindViXYZprime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViXYZprime,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindViXYZprime,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViXYZprime,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WindViXYZprime,2), UBOUND(InData%WindViXYZprime,2) + DO i1 = LBOUND(InData%WindViXYZprime,1), UBOUND(InData%WindViXYZprime,1) + ReKiBuf(Re_Xferred) = InData%WindViXYZprime(i1,i2) + Re_Xferred = Re_Xferred + 1 + 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 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindViXYZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViXYZ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindViXYZ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindViXYZ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WindViXYZ,2), UBOUND(InData%WindViXYZ,2) + DO i1 = LBOUND(InData%WindViXYZ,1), UBOUND(InData%WindViXYZ,1) + ReKiBuf(Re_Xferred) = InData%WindViXYZ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + 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 + + 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_PackParam( 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_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 + 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_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) + 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_UnpackParam( 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) + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParamLinIndx 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%OutParamLinIndx)) DEALLOCATE(OutData%OutParamLinIndx) + ALLOCATE(OutData%OutParamLinIndx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParamLinIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OutParamLinIndx,2), UBOUND(OutData%OutParamLinIndx,2) + DO i1 = LBOUND(OutData%OutParamLinIndx,1), UBOUND(OutData%OutParamLinIndx,1) + OutData%OutParamLinIndx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_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 Lidar_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%lidar, ErrStat2, ErrMsg2 ) ! lidar + 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_UnPackParam + + SUBROUTINE InflowWind_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_InputType), INTENT(IN) :: SrcInputData + TYPE(InflowWind_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 = 'InflowWind_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%PositionXYZ)) THEN + i1_l = LBOUND(SrcInputData%PositionXYZ,1) + i1_u = UBOUND(SrcInputData%PositionXYZ,1) + i2_l = LBOUND(SrcInputData%PositionXYZ,2) + i2_u = UBOUND(SrcInputData%PositionXYZ,2) + IF (.NOT. ALLOCATED(DstInputData%PositionXYZ)) THEN + ALLOCATE(DstInputData%PositionXYZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%PositionXYZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%PositionXYZ = SrcInputData%PositionXYZ +ENDIF + CALL Lidar_CopyInput( SrcInputData%lidar, DstInputData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_CopyInput + + SUBROUTINE InflowWind_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(InflowWind_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%PositionXYZ)) THEN + DEALLOCATE(InputData%PositionXYZ) +ENDIF + CALL Lidar_DestroyInput( InputData%lidar, ErrStat, ErrMsg ) + END SUBROUTINE InflowWind_DestroyInput + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 ! PositionXYZ allocated yes/no + IF ( ALLOCATED(InData%PositionXYZ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PositionXYZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PositionXYZ) ! PositionXYZ + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! lidar: size of buffers for each call to pack subtype + CALL Lidar_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, .TRUE. ) ! lidar + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! lidar + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! lidar + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! lidar + 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 + + IF ( .NOT. ALLOCATED(InData%PositionXYZ) ) 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%PositionXYZ,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionXYZ,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PositionXYZ,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionXYZ,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PositionXYZ,2), UBOUND(InData%PositionXYZ,2) + DO i1 = LBOUND(InData%PositionXYZ,1), UBOUND(InData%PositionXYZ,1) + ReKiBuf(Re_Xferred) = InData%PositionXYZ(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + CALL Lidar_PackInput( 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 + END SUBROUTINE InflowWind_PackInput + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 ! PositionXYZ 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%PositionXYZ)) DEALLOCATE(OutData%PositionXYZ) + ALLOCATE(OutData%PositionXYZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PositionXYZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PositionXYZ,2), UBOUND(OutData%PositionXYZ,2) + DO i1 = LBOUND(OutData%PositionXYZ,1), UBOUND(OutData%PositionXYZ,1) + OutData%PositionXYZ(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 Lidar_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%lidar, ErrStat2, ErrMsg2 ) ! lidar + 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_UnPackInput + + SUBROUTINE InflowWind_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_OutputType), INTENT(IN) :: SrcOutputData + TYPE(InflowWind_OutputType), INTENT(INOUT) :: DstOutputData + 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_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%VelocityUVW)) THEN + i1_l = LBOUND(SrcOutputData%VelocityUVW,1) + i1_u = UBOUND(SrcOutputData%VelocityUVW,1) + i2_l = LBOUND(SrcOutputData%VelocityUVW,2) + i2_u = UBOUND(SrcOutputData%VelocityUVW,2) + IF (.NOT. ALLOCATED(DstOutputData%VelocityUVW)) THEN + ALLOCATE(DstOutputData%VelocityUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%VelocityUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%VelocityUVW = SrcOutputData%VelocityUVW +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + DstOutputData%DiskVel = SrcOutputData%DiskVel + CALL Lidar_CopyOutput( SrcOutputData%lidar, DstOutputData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_CopyOutput + + SUBROUTINE InflowWind_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(InflowWind_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%VelocityUVW)) THEN + DEALLOCATE(OutputData%VelocityUVW) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + CALL Lidar_DestroyOutput( OutputData%lidar, ErrStat, ErrMsg ) + END SUBROUTINE InflowWind_DestroyOutput + + SUBROUTINE InflowWind_PackOutput( 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_OutputType), 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_PackOutput' + ! 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 ! VelocityUVW allocated yes/no + IF ( ALLOCATED(InData%VelocityUVW) ) THEN + 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 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + Re_BufSz = Re_BufSz + SIZE(InData%DiskVel) ! DiskVel + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! lidar: size of buffers for each call to pack subtype + CALL Lidar_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, .TRUE. ) ! lidar + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! lidar + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! lidar + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! lidar + 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 + + IF ( .NOT. ALLOCATED(InData%VelocityUVW) ) 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%VelocityUVW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelocityUVW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelocityUVW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelocityUVW,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%VelocityUVW,2), UBOUND(InData%VelocityUVW,2) + DO i1 = LBOUND(InData%VelocityUVW,1), UBOUND(InData%VelocityUVW,1) + ReKiBuf(Re_Xferred) = InData%VelocityUVW(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 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%DiskVel,1), UBOUND(InData%DiskVel,1) + ReKiBuf(Re_Xferred) = InData%DiskVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + CALL Lidar_PackOutput( 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 + END SUBROUTINE InflowWind_PackOutput + + SUBROUTINE InflowWind_UnPackOutput( 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_OutputType), 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_UnPackOutput' + ! 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 ! VelocityUVW 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%VelocityUVW)) DEALLOCATE(OutData%VelocityUVW) + ALLOCATE(OutData%VelocityUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelocityUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%VelocityUVW,2), UBOUND(OutData%VelocityUVW,2) + DO i1 = LBOUND(OutData%VelocityUVW,1), UBOUND(OutData%VelocityUVW,1) + OutData%VelocityUVW(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 + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%DiskVel,1) + i1_u = UBOUND(OutData%DiskVel,1) + DO i1 = LBOUND(OutData%DiskVel,1), UBOUND(OutData%DiskVel,1) + OutData%DiskVel(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 Lidar_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%lidar, ErrStat2, ErrMsg2 ) ! lidar + 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_UnPackOutput + + SUBROUTINE InflowWind_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(InflowWind_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 = 'InflowWind_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE InflowWind_CopyContState + + SUBROUTINE InflowWind_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE InflowWind_DestroyContState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_PackContState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_UnPackContState + + SUBROUTINE InflowWind_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(InflowWind_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 = 'InflowWind_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE InflowWind_CopyDiscState + + SUBROUTINE InflowWind_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE InflowWind_DestroyDiscState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_PackDiscState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_UnPackDiscState + + SUBROUTINE InflowWind_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(InflowWind_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 = 'InflowWind_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE InflowWind_CopyConstrState + + SUBROUTINE InflowWind_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE InflowWind_DestroyConstrState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_PackConstrState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_UnPackConstrState + + SUBROUTINE InflowWind_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(InflowWind_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 = 'InflowWind_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE InflowWind_CopyOtherState + + SUBROUTINE InflowWind_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE InflowWind_DestroyOtherState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_PackOtherState + + SUBROUTINE InflowWind_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(InflowWind_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 = 'InflowWind_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 InflowWind_UnPackOtherState + + + SUBROUTINE InflowWind_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(InflowWind_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(InflowWind_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL InflowWind_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL InflowWind_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL InflowWind_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE InflowWind_Input_ExtrapInterp + + + SUBROUTINE InflowWind_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(InflowWind_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(InflowWind_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(InflowWind_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%PositionXYZ) .AND. ALLOCATED(u1%PositionXYZ)) THEN + DO i2 = LBOUND(u_out%PositionXYZ,2),UBOUND(u_out%PositionXYZ,2) + DO i1 = LBOUND(u_out%PositionXYZ,1),UBOUND(u_out%PositionXYZ,1) + b = -(u1%PositionXYZ(i1,i2) - u2%PositionXYZ(i1,i2)) + u_out%PositionXYZ(i1,i2) = u1%PositionXYZ(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated + CALL Lidar_Input_ExtrapInterp1( u1%lidar, u2%lidar, tin, u_out%lidar, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE InflowWind_Input_ExtrapInterp1 + + + SUBROUTINE InflowWind_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(InflowWind_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(InflowWind_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(InflowWind_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(InflowWind_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%PositionXYZ) .AND. ALLOCATED(u1%PositionXYZ)) THEN + DO i2 = LBOUND(u_out%PositionXYZ,2),UBOUND(u_out%PositionXYZ,2) + DO i1 = LBOUND(u_out%PositionXYZ,1),UBOUND(u_out%PositionXYZ,1) + b = (t(3)**2*(u1%PositionXYZ(i1,i2) - u2%PositionXYZ(i1,i2)) + t(2)**2*(-u1%PositionXYZ(i1,i2) + u3%PositionXYZ(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*u1%PositionXYZ(i1,i2) + t(3)*u2%PositionXYZ(i1,i2) - t(2)*u3%PositionXYZ(i1,i2) ) * scaleFactor + u_out%PositionXYZ(i1,i2) = u1%PositionXYZ(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated + CALL Lidar_Input_ExtrapInterp2( u1%lidar, u2%lidar, u3%lidar, tin, u_out%lidar, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE InflowWind_Input_ExtrapInterp2 + + + SUBROUTINE InflowWind_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(InflowWind_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL InflowWind_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL InflowWind_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL InflowWind_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE InflowWind_Output_ExtrapInterp + + + SUBROUTINE InflowWind_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(InflowWind_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(InflowWind_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%VelocityUVW) .AND. ALLOCATED(y1%VelocityUVW)) THEN + DO i2 = LBOUND(y_out%VelocityUVW,2),UBOUND(y_out%VelocityUVW,2) + DO i1 = LBOUND(y_out%VelocityUVW,1),UBOUND(y_out%VelocityUVW,1) + b = -(y1%VelocityUVW(i1,i2) - y2%VelocityUVW(i1,i2)) + y_out%VelocityUVW(i1,i2) = y1%VelocityUVW(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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + DO i1 = LBOUND(y_out%DiskVel,1),UBOUND(y_out%DiskVel,1) + b = -(y1%DiskVel(i1) - y2%DiskVel(i1)) + y_out%DiskVel(i1) = y1%DiskVel(i1) + b * ScaleFactor + END DO + CALL Lidar_Output_ExtrapInterp1( y1%lidar, y2%lidar, tin, y_out%lidar, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE InflowWind_Output_ExtrapInterp1 + + + SUBROUTINE InflowWind_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(InflowWind_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(InflowWind_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(InflowWind_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i02 ! dim2 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + INTEGER :: i2 ! dim2 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%VelocityUVW) .AND. ALLOCATED(y1%VelocityUVW)) THEN + DO i2 = LBOUND(y_out%VelocityUVW,2),UBOUND(y_out%VelocityUVW,2) + DO i1 = LBOUND(y_out%VelocityUVW,1),UBOUND(y_out%VelocityUVW,1) + b = (t(3)**2*(y1%VelocityUVW(i1,i2) - y2%VelocityUVW(i1,i2)) + t(2)**2*(-y1%VelocityUVW(i1,i2) + y3%VelocityUVW(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%VelocityUVW(i1,i2) + t(3)*y2%VelocityUVW(i1,i2) - t(2)*y3%VelocityUVW(i1,i2) ) * scaleFactor + y_out%VelocityUVW(i1,i2) = y1%VelocityUVW(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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + DO i1 = LBOUND(y_out%DiskVel,1),UBOUND(y_out%DiskVel,1) + b = (t(3)**2*(y1%DiskVel(i1) - y2%DiskVel(i1)) + t(2)**2*(-y1%DiskVel(i1) + y3%DiskVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%DiskVel(i1) + t(3)*y2%DiskVel(i1) - t(2)*y3%DiskVel(i1) ) * scaleFactor + y_out%DiskVel(i1) = y1%DiskVel(i1) + b + c * t_out + END DO + CALL Lidar_Output_ExtrapInterp2( y1%lidar, y2%lidar, y3%lidar, tin, y_out%lidar, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE InflowWind_Output_ExtrapInterp2 + +END MODULE InflowWind_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/inflowwind/src/Lidar.f90 b/OpenFAST/modules/inflowwind/src/Lidar.f90 new file mode 100644 index 000000000..10d835849 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/Lidar.f90 @@ -0,0 +1,589 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 CU Boulder +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! +! Lidar module, a submodule 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 Lidar + + USE InflowWind_Subs + USE InflowWind_Types + USE Lidar_Types + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: Lidar_Ver = ProgDesc( 'Lidar', '', '' ) + CHARACTER(*), PARAMETER :: Lidar_Nickname = 'Lidar' + + + REAL(ReKi), PARAMETER :: BeamRad = 0.028 + REAL(ReKi), PARAMETER :: LsrWavLen = 0.000001565 ! Laser wavelength + + +! ===================================================================================================" + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Lidar_Init ! Initialization routine + PUBLIC :: Lidar_End ! Ending routine (includes clean up) + PUBLIC :: Lidar_CalcOutput ! Routine for computing outputs + + +!bjj: +!! @todo: add mesh to map nacelle rotor apex position in ElastoDyn to lidar location (possibly an array of lidars) in InflowWind +!! @todo: add input file (part of InflowWind input file) +!! - number of lidars, type, location, number of pulse range gates, etc +!! - initial measurement position(s) +!! - scan pattern & associated values [remove this functionality from Matlab] +!! @todo: add subroutine for scanning patterns +!! future work: +!! @todo: do we want to know if the blade is in front of the lidar so we can return garbage to simulate that scenario, too? + +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. +!! The initial states and initial guess for the input are defined. +!! note that we're calling this with the InflowWind data types, so that data is INOUT instead of OUT +SUBROUTINE Lidar_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + + TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(InflowWind_InputType), INTENT(INOUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: x !< Initial continuous states + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: xd !< Initial discrete states + TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: z !< Initial guess of the constraint states + TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherState !< Initial other states + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + REAL(DbKi), INTENT(IN ) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Lidar_UpdateStates() is called in loose coupling & + !! (2) Lidar_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(InflowWind_InitOutputType), INTENT(INOUT) :: InitOut !< Output for initialization routine + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Init' + + REAL(ReKi) :: TempWindSpeed(3) + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + + p%lidar%RotorApexOffsetPos = InitInp%lidar%RotorApexOffsetPos + + p%lidar%SensorType = InitInp%lidar%SensorType + IF (p%lidar%SensorType == SensorType_None) THEN + p%lidar%NumPulseGate = 0 + ELSEIF (p%lidar%SensorType == SensorType_SinglePoint) THEN + p%lidar%NumPulseGate = 1 + ELSE + + ! variables for both pulsed and continuous-wave lidars + + CALL InflowWind_GetMean(0.0_DbKi, InitInp%lidar%TMax, Interval, InitInp%lidar%HubPosition, TempWindSpeed, & + p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + + p%lidar%SpatialRes = 0.5_ReKi*TempWindSpeed(1)*Interval + p%lidar%RayRangeSq = (Pi*(BeamRad**2)/LsrWavLen)**2 + + p%lidar%LidRadialVel = InitInp%lidar%LidRadialVel !.FALSE. + + + IF (p%lidar%SensorType == SensorType_ContinuousLidar) THEN + + p%lidar%WtFnTrunc = 0.02_ReKi + p%lidar%NumPulseGate = 1 + + ELSEIF (p%lidar%SensorType == SensorType_PulsedLidar) THEN + + p%lidar%WtFnTrunc = 0.01_ReKi + p%lidar%NumPulseGate = InitInp%lidar%NumPulseGate + + ! values for the WindCube + p%lidar%DeltaP = 30.0_ReKi + p%lidar%DeltaR = 30.0_ReKi + p%lidar%PulseRangeOne = 35.0_ReKi + + p%lidar%r_p = p%lidar%DeltaR/(2.0_ReKi*SQRT(LOG(2.0_ReKi))) + + ELSE + + CALL SetErrStat(ErrID_Fatal, "Invalid sensor type.", ErrStat, ErrMsg, RoutineName) + RETURN + + END IF + + END IF + + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + + !x%lidar%DummyContState = 0.0_ReKi + !xdlidar%%DummyDiscState = 0.0_ReKi + !z%lidar%DummyConstrState = 0.0_ReKi + !OtherState%lidar%DummyOtherState = 0.0_ReKi + ! + + !............................................................................................ + ! Define initial guess for the system inputs here: + !............................................................................................ + + u%lidar%LidPosition = InitInp%lidar%HubPosition + u%lidar%MsrPosition = InitInp%lidar%HubPosition + (/ 50.0, 0.0, 0.0 /) !bjj: todo FIXME with initial guess of lidar focus. + u%lidar%PulseLidEl = 0.0_ReKi + u%lidar%PulseLidAz = 0.0_ReKi + + + !............................................................................................ + ! Define system output initializations (set up mesh) here: + !............................................................................................ + !CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', ErrStat2, ErrMsg2 ) + ! CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! IF (ErrStat >= AbortErrLev) RETURN + !y%WriteOutput = 0 + + + CALL AllocAry( y%lidar%LidSpeed, p%lidar%NumPulseGate, 'y%lidar%LidSpeed', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); + + !CALL AllocAry( y%LidErr, p%NumPulseGate, 'y%LidErr', ErrStat2, ErrMsg2 ) + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); + + CALL AllocAry( y%lidar%WtTrunc, p%lidar%NumPulseGate, 'y%lidar%WtTrunc', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); + + + IF (ErrStat >= AbortErrLev) RETURN + y%lidar%LidSpeed = 0.0 + y%lidar%WtTrunc = 0.0 + + !............................................................................................ + ! Define initialization-routine output here: + !............................................................................................ + + + RETURN + +END SUBROUTINE Lidar_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Lidar_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(InflowWind_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherState !< Other/optimization states + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< System outputs + 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 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Close files here: + + + ! Destroy the input data: + + CALL Lidar_DestroyInput( u%lidar, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL Lidar_DestroyParam( p%lidar, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + !CALL Lidar_DestroyContState( x, ErrStat, ErrMsg ) + !CALL Lidar_DestroyDiscState( xd, ErrStat, ErrMsg ) + !CALL Lidar_DestroyConstrState( z, ErrStat, ErrMsg ) + !CALL Lidar_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL Lidar_DestroyOutput( y%lidar, ErrStat, ErrMsg ) + + + + +END SUBROUTINE Lidar_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! @note this breaks the framework because we're passing the IfW types instead of the Lidar types... this is necessary to get +!! appropriate wind speeds for the lidar measurements. +SUBROUTINE Lidar_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + 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 + + REAL(ReKi) :: FocDist ! Focus Distance of the laser + REAL(ReKi) :: FocDistMod ! Focus Distance of the laser? + REAL(ReKi) :: LidPhi ! angle used with LidTheta to describe the direction the lidar is pointed + REAL(ReKi) :: LidTheta ! angle used with LidPhi to describe the direction the lidar is pointed + REAL(ReKi) :: LidRange ! lidar range + + REAL(ReKi) :: WtFuncSum ! sum of weight function, used to normalize summation to 1 + REAL(ReKi) :: LidWt ! The weighting function value + REAL(ReKi) :: LidWtMax ! maximum weighting function value? + REAL(ReKi) :: LidWtRatio ! LidWt/LidWtMax + REAL(ReKi) :: LidDirUnVec(3) ! lidar look direction unit vector + + REAL(ReKi) :: Distance(3) ! distance vector between input measurement and lidar positions + + TYPE(InflowWind_InputType) :: Input ! position where wind speed should be returned + TYPE(InflowWind_OutputType) :: Output ! velocity at Input%Position + + REAL(ReKi) :: OutputVelocity(3) + + + INTEGER(IntKi) :: IRangeGt + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_CalcOutput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + IF (p%lidar%SensorType == SensorType_None) RETURN + + + ! allocate arrays to compute outputs + CALL AllocAry(Input%PositionXYZ, 3,1, 'Input%PositionXYZ',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry(Output%VelocityUVW, 3,1, 'Output%VelocityUVW',ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !............................................................................................................................... + ! Compute the outputs + !............................................................................................................................... + + + IF (p%lidar%SensorType == SensorType_SinglePoint) THEN + + !get lidar speed at the focal point to see if it is out of bounds + Input%PositionXYZ(:,1) = u%lidar%MsrPosition + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + y%lidar%LidSpeed = Output%VelocityUVW(:,1) + y%lidar%WtTrunc = 1.0_ReKi + + ELSEIF (p%lidar%SensorType == SensorType_ContinuousLidar) THEN + !calculate the focal distance of the lidar as well as the modified focal distance so that the peak of the weighting func + !is at the intended focal distance + + Distance = u%lidar%MsrPosition - u%lidar%LidPosition + FocDist = SQRT( DOT_PRODUCT( Distance, Distance ) ) !TwoNorm + + IF(EqualRealNos(FocDist,0.0_ReKi)) THEN ! Avoid division-by-zero + y%lidar%LidSpeed = -99.0 + y%lidar%WtTrunc = 0.0 + CALL SetErrStat(ErrID_Fatal,"Measurement position cannot be the same as the lidar position.", ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + + FocDistMod = (p%lidar%RayRangeSq - SQRT(p%lidar%RayRangeSq**2 - 4*p%lidar%RayRangeSq*(FocDist**2)))/(2*FocDist); + + + !Find angles that the lidar is pointed at + LidPhi = ATAN(Distance(3)/SQRT(Distance(1)**2 + Distance(2)**2)) + !LidTheta = ATAN(Distance(2)/ABS(Distance(1))) + LidTheta = ATAN2(Distance(2),-Distance(1)) + + + !calculate the unit vector of the lidar look direction + LidDirUnVec = Distance / FocDist + LidWt = 1.0/(FocDist**2 + ((1 - FocDist/FocDistMod)**2)*p%lidar%RayRangeSq) + LidWtMax = LidWt + LidWtRatio = 1.0_ReKi !LidWt/LidWtMax + + !get lidar speed at the focal point to see if it is out of bounds + Input%PositionXYZ(:,1) = u%lidar%MsrPosition + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !if out of bounds + IF (ErrStat >= AbortErrLev) THEN + !y%lidar%LidErr = 1 + y%lidar%LidSpeed = -99.0 + CALL Cleanup() + RETURN !escape function + ENDIF + + y%lidar%LidSpeed = LidWt*DOT_PRODUCT(-1*LidDirUnVec,Output%VelocityUVW(:,1)) + + WtFuncSum = LidWt + y%lidar%WtTrunc = p%lidar%WtFnTrunc + + !initialize lidar range + LidRange = 0. + + + + !calculate the weighted lidar returns + DO + + !escape loop if desired truncation point has been reached + IF (LidWtRatio < p%lidar%WtFnTrunc) THEN + EXIT + ENDIF + + + !calculate range of current beam point + LidRange = LidRange + p%lidar%SpatialRes + + LidWt = 1.0/((FocDist + LidRange)**2 + ((1 - (FocDist + LidRange)/FocDistMod)**2)*p%lidar%RayRangeSq) + LidWtRatio = LidWt/LidWtMax + + + !trunc point is behind lidar + IF (LidRange > FocDist) THEN + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Info, "Lidar truncation point is behind the lidar. Truncation ratio is "//trim(num2lstr(LidWtRatio))//'.', ErrStat, ErrMsg, RoutineName) ! set informational message about point being behind lidar + !y%LidErr = 3 + y%lidar%WtTrunc = LidWtRatio + EXIT + ENDIF + + + !calculate points to scan for current beam point + Input%PositionXYZ(3,1) = u%lidar%LidPosition(3) + SIN(LidPhi)*(LidRange + FocDist) + Input%PositionXYZ(1,1) = u%lidar%LidPosition(1) - COS(LidTheta)*COS(LidPhi)*(LidRange + FocDist) + Input%PositionXYZ(2,1) = u%lidar%LidPosition(2) + SIN(LidTheta)*COS(LidPhi)*(LidRange + FocDist) + + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + IF (ErrStat2 >= AbortErrLev ) THEN !out of bounds + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Warn, "Lidar speed truncated. Truncation ratio is "//trim(num2lstr(LidWtRatio))//".", ErrStat, ErrMsg, RoutineName ) + !y%LidErr = 2 + y%lidar%WtTrunc = LidWtRatio + EXIT + ENDIF + + OutputVelocity = Output%VelocityUVW(:,1) + + + !calculate points to scan for current beam point + Input%PositionXYZ(3,1) = u%lidar%LidPosition(3) + SIN(LidPhi)*(FocDist - LidRange) + Input%PositionXYZ(1,1) = u%lidar%LidPosition(1) - COS(LidTheta)*COS(LidPhi)*(FocDist - LidRange) + Input%PositionXYZ(2,1) = u%lidar%LidPosition(2) + SIN(LidTheta)*COS(LidPhi)*(FocDist - LidRange) + + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + IF (ErrStat2 >= AbortErrLev) THEN !out of bounds + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Warn, "Lidar speed truncated. Truncation ratio is "//trim(num2lstr(LidWtRatio))//".", ErrStat, ErrMsg, RoutineName ) + !y%lidar%LidErr = 2 + y%lidar%WtTrunc = LidWtRatio + EXIT + ENDIF + + + y%lidar%LidSpeed = y%lidar%LidSpeed + LidWt*DOT_PRODUCT(-1*LidDirUnVec, OutputVelocity + Output%VelocityUVW(:,1)) + WtFuncSum = WtFuncSum + 2*LidWt + + + END DO + + !Normalize the weighting function summation to 1 + + IF ( p%lidar%LidRadialVel ) THEN + !This detects the radial component + y%lidar%LidSpeed = y%lidar%LidSpeed/WtFuncSum + ELSE + !This returns the 'x' component estimate + y%lidar%LidSpeed = -1*y%lidar%LidSpeed/(WtFuncSum*LidDirUnVec(1)) + ENDIF + + ELSE !p%SensorType == SensorType_PulsedLidar + + + + LidDirUnVec(1) = -1*COS(u%lidar%PulseLidEl) + LidDirUnVec(2) = SIN(u%lidar%PulseLidEl)*SIN(u%lidar%PulseLidAz) + LidDirUnVec(3) = SIN(u%lidar%PulseLidEl)*COS(u%lidar%PulseLidAz) + + + DO IRangeGt = 1,p%lidar%NumPulseGate + + !y%lidar%LidErr(IRangeGt) = 0 + + !get lidar speed at the focal point to see if it is out of bounds + Input%PositionXYZ(:,1) = u%lidar%LidPosition + LidDirUnVec*(p%lidar%PulseRangeOne + (IRangeGt-1)*p%lidar%DeltaP) + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + LidWt = NWTC_ERF((p%lidar%DeltaP/2)/p%lidar%r_p)/p%lidar%DeltaP + LidWtMax = LidWt + LidWtRatio = 1.0_ReKi !LidWt/LidWtMax + + + !if out of bounds + IF (AbortErrLev >= AbortErrLev) THEN + !y%LidErr(IRangeGt) = 1 + y%lidar%LidSpeed(IRangeGt) = -99 + CALL Cleanup() + RETURN !escape function + ENDIF + + y%lidar%LidSpeed(IRangeGt) = LidWt*DOT_PRODUCT(-1*LidDirUnVec,Output%VelocityUVW(:,1)) + + WtFuncSum = LidWt + y%lidar%WtTrunc(IRangeGt) = p%lidar%WtFnTrunc + + !initialize lidar range + LidRange = 0. + + DO + !escape loop if desired truncation point has been reached + IF (LidWtRatio < p%lidar%WtFnTrunc) THEN + EXIT + ENDIF + + !calculate range of current beam point + LidRange = LidRange + p%lidar%SpatialRes + + LidWt = (NWTC_ERF((LidRange + p%lidar%DeltaP/2.)/p%lidar%r_p) - NWTC_ERF((LidRange - p%lidar%DeltaP/2.)/p%lidar%r_p))/(2.*p%lidar%DeltaP) + LidWtRatio = LidWt/LidWtMax + + + !trunc point is behind lidar + IF (LidRange > (p%lidar%PulseRangeOne + (IRangeGt-1)*p%lidar%DeltaP)) THEN + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Info, "Lidar truncation point at gate "//trim(num2lstr(IRangeGt))//" is behind the lidar. Truncation ratio is "& + //trim(num2lstr(LidWtRatio))//'.', ErrStat, ErrMsg, RoutineName) ! set informational message about point being behind lidar + !y%LidErr(IRangeGt) = 3 + y%lidar%WtTrunc(IRangeGt) = LidWtRatio + EXIT + ENDIF + + + !calculate points to scan for current beam point + Input%PositionXYZ(:,1) = u%lidar%LidPosition + LidDirUnVec*(p%lidar%PulseRangeOne + (IRangeGt-1)*p%lidar%DeltaP + LidRange) + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + IF (ErrStat2 >= AbortErrLev) THEN !out of bounds + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Warn, "Lidar speed at gate "//trim(num2lstr(IRangeGt))//" truncated. Truncation ratio is "//trim(num2lstr(LidWtRatio))//".", ErrStat, ErrMsg, RoutineName ) + !y%LidErr(IRangeGt) = 2 + y%lidar%WtTrunc(IRangeGt) = LidWtRatio + EXIT + ENDIF + OutputVelocity = Output%VelocityUVW(:,1) + + !calculate points to scan for current beam point + Input%PositionXYZ(:,1) = u%lidar%LidPosition + LidDirUnVec*(p%lidar%PulseRangeOne + (IRangeGt-1)*p%lidar%DeltaP - LidRange) + CALL CalculateOutput( t, Input, p, x, xd, z, OtherState, Output, m, .FALSE., ErrStat2, ErrMsg2 ) + IF (ErrStat2 >= AbortErrLev) THEN !out of bounds + IF (NWTC_VerboseLevel == NWTC_Verbose) & + CALL SetErrStat( ErrID_Warn, "Lidar speed at gate "//trim(num2lstr(IRangeGt))//" truncated. Truncation ratio is "//trim(num2lstr(LidWtRatio))//".", ErrStat, ErrMsg, RoutineName ) + !y%lidar%LidErr(IRangeGt) = 2 + y%lidar%WtTrunc(IRangeGt) = LidWtRatio + EXIT + ENDIF + + + y%lidar%LidSpeed(IRangeGt) = y%lidar%LidSpeed(IRangeGt) + LidWt*DOT_PRODUCT(-1*LidDirUnVec,Output%VelocityUVW(:,1) + OutputVelocity) + WtFuncSum = WtFuncSum + 2*LidWt + + END DO + + + IF ( p%lidar%LidRadialVel ) THEN + !This detects the radial component + y%lidar%LidSpeed(IRangeGt) = y%lidar%LidSpeed(IRangeGt)/WtFuncSum + ELSE + !This returns the 'x' component estimate + y%lidar%LidSpeed(IRangeGt) = -1*y%lidar%LidSpeed(IRangeGt)/(LidDirUnVec(1)*WtFuncSum) + ENDIF + + END DO + + + END IF !type of lidar measurements + + + CALL Cleanup() + + RETURN +CONTAINS + SUBROUTINE Cleanup() + + IF (ALLOCATED(Input%PositionXYZ)) DEALLOCATE(Input%PositionXYZ) + IF (ALLOCATED(Output%VelocityUVW)) DEALLOCATE(Output%VelocityUVW) + + END SUBROUTINE Cleanup + +END SUBROUTINE Lidar_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE Lidar +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/inflowwind/src/Lidar.txt b/OpenFAST/modules/inflowwind/src/Lidar.txt new file mode 100644 index 000000000..fd54f5575 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/Lidar.txt @@ -0,0 +1,68 @@ +################################################################################################################################### +# Registry for Lidar module in the FAST Modularization Framework +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +#include Registry_NWTC_Library.txt + +# LIDAR Constants +param Lidar - IntKi SensorType_None - -1 - - +param Lidar - IntKi SensorType_SinglePoint - 0 - - +param ^ - IntKi SensorType_ContinuousLidar - 1 - - +param ^ - IntKi SensorType_PulsedLidar - 2 - - + +# ..... LIDAR_InitInputType data ....................................................................................................... +typedef ^ Lidar_InitInputType IntKi SensorType - SensorType_None - "SensorType_* parameter" - +typedef ^ Lidar_InitInputType DbKi Tmax - - - "the length of the simulation" "s" +typedef ^ Lidar_InitInputType ReKi RotorApexOffsetPos {3} - - "position of the lidar unit relative to the rotor apex of rotation" m +typedef ^ Lidar_InitInputType ReKi HubPosition {3} - - "initial position of the hub (lidar mounted on hub) [0,0,HubHeight]" "m" +typedef ^ Lidar_InitInputType IntKi NumPulseGate - - - "the number of range gates to return wind speeds at" - +typedef ^ Lidar_InitInputType LOGICAL LidRadialVel - - - "TRUE => return radial component, FALSE => return 'x' direction estimate" - + +# ..... LIDAR_InitInputType data ....................................................................................................... +typedef ^ Lidar_InitOutputType ReKi DummyInitOut - + +# ..... LIDAR_ParameterType data ....................................................................................................... +typedef ^ Lidar_ParameterType IntKi NumPulseGate - - - "the number of range gates to return wind speeds at; pulsed lidar only" - +typedef ^ Lidar_ParameterType ReKi RotorApexOffsetPos {3} - - "position of the lidar unit relative to the rotor apex of rotation" m +typedef ^ Lidar_ParameterType ReKi RayRangeSq - - - "Rayleigh Range Squared" +typedef ^ Lidar_ParameterType ReKi SpatialRes - - - "spatial sampling distance of weighting function (1/2)*(avg ws)*dt" +typedef ^ Lidar_ParameterType IntKi SensorType - - - "SensorType_* parameter" - +typedef ^ Lidar_ParameterType ReKi WtFnTrunc - - - "Percentage of the peak value at which to truncate weighting function" +typedef ^ Lidar_ParameterType ReKi PulseRangeOne - - - "the range to the closest range gate" +typedef ^ Lidar_ParameterType ReKi DeltaP - - - "the distance between range gates" +typedef ^ Lidar_ParameterType ReKi DeltaR - - - "the FWHM width of the pulse" +typedef ^ Lidar_ParameterType ReKi r_p - - - +typedef ^ Lidar_ParameterType LOGICAL LidRadialVel - - - "TRUE => return radial component, FALSE => return 'x' direction estimate" - + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# Define "other" states (any data that are not considered actual states) here: +typedef ^ OtherStateType ReKi DummyOtherState - - - + +# ..... 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" - + + +# ..... LIDAR_InputType data ....................................................................................................... +typedef ^ Lidar_InputType ReKi LidPosition {3} - - "Position of the Lidar unit (was XLidPt, YLidPt, ZLidPt)" m +typedef ^ Lidar_InputType ReKi MsrPosition {3} - - "Position of the desired wind measurement (was XMsrPt, YMsrPt, ZMsrPt)" m +typedef ^ Lidar_InputType ReKi PulseLidEl - - - "the angle off of the x axis that the lidar is aimed (0 would be staring directly upwind, pi/2 would be staring perpendicular to the x axis)" +typedef ^ Lidar_InputType ReKi PulseLidAz - - - "the angle in the YZ plane that the lidar is staring (if PulseLidEl is set to pi/2, then 0 would be aligned with the positive z axis, pi/2 would be aligned with the positive y axis)" + + +# ..... LIDAR_OutputType data ....................................................................................................... +typedef ^ Lidar_OutputType ReKi LidSpeed {:} - - "Speed detected by Lidar at measurement point (range gates for pulsed lidar)" "m/s" +typedef ^ Lidar_OutputType ReKi WtTrunc {:} - - "Contains the fraction of the peak that the weighting function was truncated at (for when truncated early)." +#typedef ^ Lidar_OutputType IntKi LidErr {:} - - "Error code; THIS NEEDS TO GET FIXED (no integer outputs)" + diff --git a/OpenFAST/modules/inflowwind/src/Lidar_Types.f90 b/OpenFAST/modules/inflowwind/src/Lidar_Types.f90 new file mode 100644 index 000000000..4ec86f6a3 --- /dev/null +++ b/OpenFAST/modules/inflowwind/src/Lidar_Types.f90 @@ -0,0 +1,1969 @@ +!STARTOFREGISTRYGENERATEDFILE 'Lidar_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 +!********************************************************************************************************************************* +! Lidar_Types +!................................................................................................................................. +! This file is part of Lidar. +! +! 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 Lidar. 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 Lidar_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: SensorType_None = -1 + INTEGER(IntKi), PUBLIC, PARAMETER :: SensorType_SinglePoint = 0 + INTEGER(IntKi), PUBLIC, PARAMETER :: SensorType_ContinuousLidar = 1 + INTEGER(IntKi), PUBLIC, PARAMETER :: SensorType_PulsedLidar = 2 +! ========= Lidar_InitInputType ======= + TYPE, PUBLIC :: Lidar_InitInputType + INTEGER(IntKi) :: SensorType = SensorType_None !< SensorType_* parameter [-] + REAL(DbKi) :: Tmax !< the length of the simulation [s] + REAL(ReKi) , DIMENSION(1:3) :: RotorApexOffsetPos !< position of the lidar unit relative to the rotor apex of rotation [m] + REAL(ReKi) , DIMENSION(1:3) :: HubPosition !< initial position of the hub (lidar mounted on hub) [0,0,HubHeight] [m] + INTEGER(IntKi) :: NumPulseGate !< the number of range gates to return wind speeds at [-] + LOGICAL :: LidRadialVel !< TRUE => return radial component, FALSE => return 'x' direction estimate [-] + END TYPE Lidar_InitInputType +! ======================= +! ========= Lidar_InitOutputType ======= + TYPE, PUBLIC :: Lidar_InitOutputType + REAL(ReKi) :: DummyInitOut + END TYPE Lidar_InitOutputType +! ======================= +! ========= Lidar_ParameterType ======= + TYPE, PUBLIC :: Lidar_ParameterType + INTEGER(IntKi) :: NumPulseGate !< the number of range gates to return wind speeds at; pulsed lidar only [-] + REAL(ReKi) , DIMENSION(1:3) :: RotorApexOffsetPos !< position of the lidar unit relative to the rotor apex of rotation [m] + REAL(ReKi) :: RayRangeSq !< Rayleigh Range Squared [-] + REAL(ReKi) :: SpatialRes !< spatial sampling distance of weighting function (1/2)*(avg ws)*dt [-] + INTEGER(IntKi) :: SensorType !< SensorType_* parameter [-] + REAL(ReKi) :: WtFnTrunc !< Percentage of the peak value at which to truncate weighting function [-] + REAL(ReKi) :: PulseRangeOne !< the range to the closest range gate [-] + REAL(ReKi) :: DeltaP !< the distance between range gates [-] + REAL(ReKi) :: DeltaR !< the FWHM width of the pulse [-] + REAL(ReKi) :: r_p + LOGICAL :: LidRadialVel !< TRUE => return radial component, FALSE => return 'x' direction estimate [-] + END TYPE Lidar_ParameterType +! ======================= +! ========= Lidar_ContinuousStateType ======= + TYPE, PUBLIC :: Lidar_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE Lidar_ContinuousStateType +! ======================= +! ========= Lidar_DiscreteStateType ======= + TYPE, PUBLIC :: Lidar_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE Lidar_DiscreteStateType +! ======================= +! ========= Lidar_ConstraintStateType ======= + TYPE, PUBLIC :: Lidar_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE Lidar_ConstraintStateType +! ======================= +! ========= Lidar_OtherStateType ======= + TYPE, PUBLIC :: Lidar_OtherStateType + REAL(ReKi) :: DummyOtherState + END TYPE Lidar_OtherStateType +! ======================= +! ========= Lidar_MiscVarType ======= + TYPE, PUBLIC :: Lidar_MiscVarType + REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] + END TYPE Lidar_MiscVarType +! ======================= +! ========= Lidar_InputType ======= + TYPE, PUBLIC :: Lidar_InputType + REAL(ReKi) , DIMENSION(1:3) :: LidPosition !< Position of the Lidar unit (was XLidPt, YLidPt, ZLidPt) [m] + REAL(ReKi) , DIMENSION(1:3) :: MsrPosition !< Position of the desired wind measurement (was XMsrPt, YMsrPt, ZMsrPt) [m] + REAL(ReKi) :: PulseLidEl !< the angle off of the x axis that the lidar is aimed (0 would be staring directly upwind, pi/2 would be staring perpendicular to the x axis) [-] + REAL(ReKi) :: PulseLidAz !< the angle in the YZ plane that the lidar is staring (if PulseLidEl is set to pi/2, then 0 would be aligned with the positive z axis, pi/2 would be aligned with the positive y axis) [-] + END TYPE Lidar_InputType +! ======================= +! ========= Lidar_OutputType ======= + TYPE, PUBLIC :: Lidar_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LidSpeed !< Speed detected by Lidar at measurement point (range gates for pulsed lidar) [m/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WtTrunc !< Contains the fraction of the peak that the weighting function was truncated at (for when truncated early). [-] + END TYPE Lidar_OutputType +! ======================= +CONTAINS + SUBROUTINE Lidar_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Lidar_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 = 'Lidar_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%SensorType = SrcInitInputData%SensorType + DstInitInputData%Tmax = SrcInitInputData%Tmax + DstInitInputData%RotorApexOffsetPos = SrcInitInputData%RotorApexOffsetPos + DstInitInputData%HubPosition = SrcInitInputData%HubPosition + DstInitInputData%NumPulseGate = SrcInitInputData%NumPulseGate + DstInitInputData%LidRadialVel = SrcInitInputData%LidRadialVel + END SUBROUTINE Lidar_CopyInitInput + + SUBROUTINE Lidar_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Lidar_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyInitInput + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 ! SensorType + Db_BufSz = Db_BufSz + 1 ! Tmax + Re_BufSz = Re_BufSz + SIZE(InData%RotorApexOffsetPos) ! RotorApexOffsetPos + Re_BufSz = Re_BufSz + SIZE(InData%HubPosition) ! HubPosition + Int_BufSz = Int_BufSz + 1 ! NumPulseGate + Int_BufSz = Int_BufSz + 1 ! LidRadialVel + 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%SensorType + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Tmax + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%RotorApexOffsetPos,1), UBOUND(InData%RotorApexOffsetPos,1) + ReKiBuf(Re_Xferred) = InData%RotorApexOffsetPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%HubPosition,1), UBOUND(InData%HubPosition,1) + ReKiBuf(Re_Xferred) = InData%HubPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumPulseGate + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LidRadialVel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Lidar_PackInitInput + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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%SensorType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Tmax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%RotorApexOffsetPos,1) + i1_u = UBOUND(OutData%RotorApexOffsetPos,1) + DO i1 = LBOUND(OutData%RotorApexOffsetPos,1), UBOUND(OutData%RotorApexOffsetPos,1) + OutData%RotorApexOffsetPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%HubPosition,1) + i1_u = UBOUND(OutData%HubPosition,1) + DO i1 = LBOUND(OutData%HubPosition,1), UBOUND(OutData%HubPosition,1) + OutData%HubPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%NumPulseGate = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%LidRadialVel = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidRadialVel) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Lidar_UnPackInitInput + + SUBROUTINE Lidar_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Lidar_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 = 'Lidar_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%DummyInitOut = SrcInitOutputData%DummyInitOut + END SUBROUTINE Lidar_CopyInitOutput + + SUBROUTINE Lidar_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Lidar_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyInitOutput + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 + Re_BufSz = Re_BufSz + 1 ! DummyInitOut + 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%DummyInitOut + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Lidar_PackInitOutput + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 + OutData%DummyInitOut = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Lidar_UnPackInitOutput + + SUBROUTINE Lidar_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Lidar_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 = 'Lidar_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%NumPulseGate = SrcParamData%NumPulseGate + DstParamData%RotorApexOffsetPos = SrcParamData%RotorApexOffsetPos + DstParamData%RayRangeSq = SrcParamData%RayRangeSq + DstParamData%SpatialRes = SrcParamData%SpatialRes + DstParamData%SensorType = SrcParamData%SensorType + DstParamData%WtFnTrunc = SrcParamData%WtFnTrunc + DstParamData%PulseRangeOne = SrcParamData%PulseRangeOne + DstParamData%DeltaP = SrcParamData%DeltaP + DstParamData%DeltaR = SrcParamData%DeltaR + DstParamData%r_p = SrcParamData%r_p + DstParamData%LidRadialVel = SrcParamData%LidRadialVel + END SUBROUTINE Lidar_CopyParam + + SUBROUTINE Lidar_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Lidar_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyParam + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 ! NumPulseGate + Re_BufSz = Re_BufSz + SIZE(InData%RotorApexOffsetPos) ! RotorApexOffsetPos + Re_BufSz = Re_BufSz + 1 ! RayRangeSq + Re_BufSz = Re_BufSz + 1 ! SpatialRes + Int_BufSz = Int_BufSz + 1 ! SensorType + Re_BufSz = Re_BufSz + 1 ! WtFnTrunc + Re_BufSz = Re_BufSz + 1 ! PulseRangeOne + Re_BufSz = Re_BufSz + 1 ! DeltaP + Re_BufSz = Re_BufSz + 1 ! DeltaR + Re_BufSz = Re_BufSz + 1 ! r_p + Int_BufSz = Int_BufSz + 1 ! LidRadialVel + 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%NumPulseGate + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RotorApexOffsetPos,1), UBOUND(InData%RotorApexOffsetPos,1) + ReKiBuf(Re_Xferred) = InData%RotorApexOffsetPos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%RayRangeSq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpatialRes + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SensorType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtFnTrunc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PulseRangeOne + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DeltaP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DeltaR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%r_p + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LidRadialVel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Lidar_PackParam + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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%NumPulseGate = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RotorApexOffsetPos,1) + i1_u = UBOUND(OutData%RotorApexOffsetPos,1) + DO i1 = LBOUND(OutData%RotorApexOffsetPos,1), UBOUND(OutData%RotorApexOffsetPos,1) + OutData%RotorApexOffsetPos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%RayRangeSq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpatialRes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SensorType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WtFnTrunc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PulseRangeOne = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DeltaP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DeltaR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%r_p = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LidRadialVel = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidRadialVel) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Lidar_UnPackParam + + SUBROUTINE Lidar_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Lidar_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 = 'Lidar_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE Lidar_CopyContState + + SUBROUTINE Lidar_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Lidar_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyContState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_PackContState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_UnPackContState + + SUBROUTINE Lidar_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Lidar_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 = 'Lidar_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE Lidar_CopyDiscState + + SUBROUTINE Lidar_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Lidar_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyDiscState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_PackDiscState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_UnPackDiscState + + SUBROUTINE Lidar_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Lidar_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 = 'Lidar_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Lidar_CopyConstrState + + SUBROUTINE Lidar_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Lidar_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyConstrState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_PackConstrState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_UnPackConstrState + + SUBROUTINE Lidar_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Lidar_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 = 'Lidar_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Lidar_CopyOtherState + + SUBROUTINE Lidar_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Lidar_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyOtherState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_PackOtherState + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_UnPackOtherState + + SUBROUTINE Lidar_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Lidar_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 = 'Lidar_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE Lidar_CopyMisc + + SUBROUTINE Lidar_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Lidar_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyMisc + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_PackMisc + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 Lidar_UnPackMisc + + SUBROUTINE Lidar_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_InputType), INTENT(IN) :: SrcInputData + TYPE(Lidar_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%LidPosition = SrcInputData%LidPosition + DstInputData%MsrPosition = SrcInputData%MsrPosition + DstInputData%PulseLidEl = SrcInputData%PulseLidEl + DstInputData%PulseLidAz = SrcInputData%PulseLidAz + END SUBROUTINE Lidar_CopyInput + + SUBROUTINE Lidar_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Lidar_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Lidar_DestroyInput + + SUBROUTINE Lidar_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(Lidar_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 = 'Lidar_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 + Re_BufSz = Re_BufSz + SIZE(InData%LidPosition) ! LidPosition + Re_BufSz = Re_BufSz + SIZE(InData%MsrPosition) ! MsrPosition + Re_BufSz = Re_BufSz + 1 ! PulseLidEl + Re_BufSz = Re_BufSz + 1 ! PulseLidAz + 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%LidPosition,1), UBOUND(InData%LidPosition,1) + ReKiBuf(Re_Xferred) = InData%LidPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%MsrPosition,1), UBOUND(InData%MsrPosition,1) + ReKiBuf(Re_Xferred) = InData%MsrPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%PulseLidEl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PulseLidAz + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Lidar_PackInput + + SUBROUTINE Lidar_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(Lidar_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_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 + i1_l = LBOUND(OutData%LidPosition,1) + i1_u = UBOUND(OutData%LidPosition,1) + DO i1 = LBOUND(OutData%LidPosition,1), UBOUND(OutData%LidPosition,1) + OutData%LidPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%MsrPosition,1) + i1_u = UBOUND(OutData%MsrPosition,1) + DO i1 = LBOUND(OutData%MsrPosition,1), UBOUND(OutData%MsrPosition,1) + OutData%MsrPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%PulseLidEl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PulseLidAz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Lidar_UnPackInput + + SUBROUTINE Lidar_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lidar_OutputType), INTENT(IN) :: SrcOutputData + TYPE(Lidar_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Lidar_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%LidSpeed)) THEN + i1_l = LBOUND(SrcOutputData%LidSpeed,1) + i1_u = UBOUND(SrcOutputData%LidSpeed,1) + IF (.NOT. ALLOCATED(DstOutputData%LidSpeed)) THEN + ALLOCATE(DstOutputData%LidSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%LidSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%LidSpeed = SrcOutputData%LidSpeed +ENDIF +IF (ALLOCATED(SrcOutputData%WtTrunc)) THEN + i1_l = LBOUND(SrcOutputData%WtTrunc,1) + i1_u = UBOUND(SrcOutputData%WtTrunc,1) + IF (.NOT. ALLOCATED(DstOutputData%WtTrunc)) THEN + ALLOCATE(DstOutputData%WtTrunc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WtTrunc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WtTrunc = SrcOutputData%WtTrunc +ENDIF + END SUBROUTINE Lidar_CopyOutput + + SUBROUTINE Lidar_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Lidar_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%LidSpeed)) THEN + DEALLOCATE(OutputData%LidSpeed) +ENDIF +IF (ALLOCATED(OutputData%WtTrunc)) THEN + DEALLOCATE(OutputData%WtTrunc) +ENDIF + END SUBROUTINE Lidar_DestroyOutput + + SUBROUTINE Lidar_PackOutput( 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(Lidar_OutputType), 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 = 'Lidar_PackOutput' + ! 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 ! LidSpeed allocated yes/no + IF ( ALLOCATED(InData%LidSpeed) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LidSpeed upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LidSpeed) ! LidSpeed + END IF + Int_BufSz = Int_BufSz + 1 ! WtTrunc allocated yes/no + IF ( ALLOCATED(InData%WtTrunc) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WtTrunc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WtTrunc) ! WtTrunc + 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%LidSpeed) ) 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%LidSpeed,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LidSpeed,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LidSpeed,1), UBOUND(InData%LidSpeed,1) + ReKiBuf(Re_Xferred) = InData%LidSpeed(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WtTrunc) ) 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%WtTrunc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WtTrunc,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WtTrunc,1), UBOUND(InData%WtTrunc,1) + ReKiBuf(Re_Xferred) = InData%WtTrunc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Lidar_PackOutput + + SUBROUTINE Lidar_UnPackOutput( 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(Lidar_OutputType), 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 = 'Lidar_UnPackOutput' + ! 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 ! LidSpeed 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%LidSpeed)) DEALLOCATE(OutData%LidSpeed) + ALLOCATE(OutData%LidSpeed(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LidSpeed.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LidSpeed,1), UBOUND(OutData%LidSpeed,1) + OutData%LidSpeed(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WtTrunc 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%WtTrunc)) DEALLOCATE(OutData%WtTrunc) + ALLOCATE(OutData%WtTrunc(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WtTrunc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WtTrunc,1), UBOUND(OutData%WtTrunc,1) + OutData%WtTrunc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Lidar_UnPackOutput + + + SUBROUTINE Lidar_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Lidar_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Lidar_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Lidar_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Lidar_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Lidar_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Lidar_Input_ExtrapInterp + + + SUBROUTINE Lidar_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Lidar_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Lidar_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Lidar_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + DO i1 = LBOUND(u_out%LidPosition,1),UBOUND(u_out%LidPosition,1) + b = -(u1%LidPosition(i1) - u2%LidPosition(i1)) + u_out%LidPosition(i1) = u1%LidPosition(i1) + b * ScaleFactor + END DO + DO i1 = LBOUND(u_out%MsrPosition,1),UBOUND(u_out%MsrPosition,1) + b = -(u1%MsrPosition(i1) - u2%MsrPosition(i1)) + u_out%MsrPosition(i1) = u1%MsrPosition(i1) + b * ScaleFactor + END DO + b = -(u1%PulseLidEl - u2%PulseLidEl) + u_out%PulseLidEl = u1%PulseLidEl + b * ScaleFactor + b = -(u1%PulseLidAz - u2%PulseLidAz) + u_out%PulseLidAz = u1%PulseLidAz + b * ScaleFactor + END SUBROUTINE Lidar_Input_ExtrapInterp1 + + + SUBROUTINE Lidar_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Lidar_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Lidar_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Lidar_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Lidar_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + DO i1 = LBOUND(u_out%LidPosition,1),UBOUND(u_out%LidPosition,1) + b = (t(3)**2*(u1%LidPosition(i1) - u2%LidPosition(i1)) + t(2)**2*(-u1%LidPosition(i1) + u3%LidPosition(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%LidPosition(i1) + t(3)*u2%LidPosition(i1) - t(2)*u3%LidPosition(i1) ) * scaleFactor + u_out%LidPosition(i1) = u1%LidPosition(i1) + b + c * t_out + END DO + DO i1 = LBOUND(u_out%MsrPosition,1),UBOUND(u_out%MsrPosition,1) + b = (t(3)**2*(u1%MsrPosition(i1) - u2%MsrPosition(i1)) + t(2)**2*(-u1%MsrPosition(i1) + u3%MsrPosition(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%MsrPosition(i1) + t(3)*u2%MsrPosition(i1) - t(2)*u3%MsrPosition(i1) ) * scaleFactor + u_out%MsrPosition(i1) = u1%MsrPosition(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%PulseLidEl - u2%PulseLidEl) + t(2)**2*(-u1%PulseLidEl + u3%PulseLidEl))* scaleFactor + c = ( (t(2)-t(3))*u1%PulseLidEl + t(3)*u2%PulseLidEl - t(2)*u3%PulseLidEl ) * scaleFactor + u_out%PulseLidEl = u1%PulseLidEl + b + c * t_out + b = (t(3)**2*(u1%PulseLidAz - u2%PulseLidAz) + t(2)**2*(-u1%PulseLidAz + u3%PulseLidAz))* scaleFactor + c = ( (t(2)-t(3))*u1%PulseLidAz + t(3)*u2%PulseLidAz - t(2)*u3%PulseLidAz ) * scaleFactor + u_out%PulseLidAz = u1%PulseLidAz + b + c * t_out + END SUBROUTINE Lidar_Input_ExtrapInterp2 + + + SUBROUTINE Lidar_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Lidar_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Lidar_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Lidar_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Lidar_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Lidar_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Lidar_Output_ExtrapInterp + + + SUBROUTINE Lidar_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Lidar_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Lidar_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Lidar_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%LidSpeed) .AND. ALLOCATED(y1%LidSpeed)) THEN + DO i1 = LBOUND(y_out%LidSpeed,1),UBOUND(y_out%LidSpeed,1) + b = -(y1%LidSpeed(i1) - y2%LidSpeed(i1)) + y_out%LidSpeed(i1) = y1%LidSpeed(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WtTrunc) .AND. ALLOCATED(y1%WtTrunc)) THEN + DO i1 = LBOUND(y_out%WtTrunc,1),UBOUND(y_out%WtTrunc,1) + b = -(y1%WtTrunc(i1) - y2%WtTrunc(i1)) + y_out%WtTrunc(i1) = y1%WtTrunc(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE Lidar_Output_ExtrapInterp1 + + + SUBROUTINE Lidar_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Lidar_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Lidar_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Lidar_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Lidar_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Lidar_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%LidSpeed) .AND. ALLOCATED(y1%LidSpeed)) THEN + DO i1 = LBOUND(y_out%LidSpeed,1),UBOUND(y_out%LidSpeed,1) + b = (t(3)**2*(y1%LidSpeed(i1) - y2%LidSpeed(i1)) + t(2)**2*(-y1%LidSpeed(i1) + y3%LidSpeed(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%LidSpeed(i1) + t(3)*y2%LidSpeed(i1) - t(2)*y3%LidSpeed(i1) ) * scaleFactor + y_out%LidSpeed(i1) = y1%LidSpeed(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WtTrunc) .AND. ALLOCATED(y1%WtTrunc)) THEN + DO i1 = LBOUND(y_out%WtTrunc,1),UBOUND(y_out%WtTrunc,1) + b = (t(3)**2*(y1%WtTrunc(i1) - y2%WtTrunc(i1)) + t(2)**2*(-y1%WtTrunc(i1) + y3%WtTrunc(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%WtTrunc(i1) + t(3)*y2%WtTrunc(i1) - t(2)*y3%WtTrunc(i1) ) * scaleFactor + y_out%WtTrunc(i1) = y1%WtTrunc(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE Lidar_Output_ExtrapInterp2 + +END MODULE Lidar_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/inflowwind/tests/ifw_test_tools.F90 b/OpenFAST/modules/inflowwind/tests/ifw_test_tools.F90 new file mode 100644 index 000000000..bbbabbbdf --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/ifw_test_tools.F90 @@ -0,0 +1,145 @@ +module ifw_test_tools + + use NWTC_IO + use NWTC_Library + use NWTC_Library_Types + + implicit none + +contains + + function getInputFileData() + + INTEGER :: ErrStat + CHARACTER(ErrMsgLen) :: ErrMsg + TYPE(FileInfoType) :: getInputFileData + CHARACTER(1024), DIMENSION(55) :: data = (/ & + '------- InflowWind v3.01.* INPUT FILE ------------------------------------------------------------------------- ', & + 'Steady 8 m/s winds with no shear for FAST CertTests #20 and #25 ', & + '--------------------------------------------------------------------------------------------------------------- ', & + ' false Echo - Echo input data to <RootName>.ech (flag) ', & + ' 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) ', & + ' 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) ', & + ' 90 WindVziList - List of coordinates in the inertial Z direction (m) ', & + '================== Parameters for Steady Wind Conditions [used only for WindType = 1] ========================= ', & + ' 8.0 HWindSpeed - Horizontal windspeed (m/s) ', & + ' 90 RefHt - Reference height for horizontal wind speed (m) ', & + ' 0.1 PLexp - Power law exponent (-) ', & + '================== Parameters for Uniform wind file [used only for WindType = 2] ============================ ', & + '"Wind/08ms.wnd" FileName_Uni - Filename of time series data for uniform wind field. (-) ', & + ' 90 RefHt_Uni - Reference height for horizontal wind speed (m) ', & + ' 125.88 RefLength - Reference length for linear horizontal and vertical sheer (-) ', & + '================== Parameters for Binary TurbSim Full-Field files [used only for WindType = 3] ============== ', & + '"Wind/08ms.wnd" filename_bts - name of the full field wind file to use (.bts) ', & + '================== Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4] ========= ', & + '"unused" FilenameRoot - Rootname of the full-field wind file to use (.wnd, .sum) ', & + 'False TowerFile - Have tower file (.twr) (flag) ', & + '================== Parameters for HAWC-format binary files [Only used with WindType = 5] ===================== ', & + '"wasp\Output\basic_5u.bin" FileName_u - name of the file containing the u-component fluctuating wind (.bin) ', & + '"wasp\Output\basic_5v.bin" FileName_v - name of the file containing the v-component fluctuating wind (.bin) ', & + '"wasp\Output\basic_5w.bin" FileName_w - name of the file containing the w-component fluctuating wind (.bin) ', & + ' 64 nx - number of grids in the x direction (in the 3 files above) (-) ', & + ' 32 ny - number of grids in the y direction (in the 3 files above) (-) ', & + ' 32 nz - number of grids in the z direction (in the 3 files above) (-) ', & + ' 16 dx - distance (in meters) between points in the x direction (m) ', & + ' 3 dy - distance (in meters) between points in the y direction (m) ', & + ' 3 dz - distance (in meters) between points in the z direction (m) ', & + ' 90 RefHt_HAWC - reference height; the height (in meters) of the vertical center of the grid (m) ', & + ' ------------- Scaling parameters for turbulence --------------------------------------------------------- ', & + ' 1 ScaleMethod - Turbulence scaling method [0 = none, 1 = direct scaling, 2 = calculate scaling factor based on a desired standard deviation] ', & + ' 1 SFx - Turbulence scaling factor for the x direction (-) [ScaleMethod=1] ', & + ' 1 SFy - Turbulence scaling factor for the y direction (-) [ScaleMethod=1] ', & + ' 1 SFz - Turbulence scaling factor for the z direction (-) [ScaleMethod=1] ', & + ' 12 SigmaFx - Turbulence standard deviation to calculate scaling from in x direction (m/s) [ScaleMethod=2] ', & + ' 8 SigmaFy - Turbulence standard deviation to calculate scaling from in y direction (m/s) [ScaleMethod=2] ', & + ' 2 SigmaFz - Turbulence standard deviation to calculate scaling from in z direction (m/s) [ScaleMethod=2] ', & + ' ------------- Mean wind profile parameters (added to HAWC-format files) --------------------------------- ', & + ' 5 URef - Mean u-component wind speed at the reference height (m/s) ', & + ' 2 WindProfile - Wind profile type (0=constant;1=logarithmic,2=power law) ', & + ' 0 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) ', & + '====================== OUTPUT ================================================== ', & + 'False SumPrint - Print summary data to <RootName>.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,Wind1VelZ" - Wind velocity at point WindVxiList(1),WindVyiList(1),WindVziList(1). X, Y, and Z direction components. ', & + 'END of input file (the word "END" must appear in the first 3 columns of this last OutList line) ', & + '--------------------------------------------------------------------------------------- ' & + /) + + CALL InitFileInfo(data, getInputFileData, ErrStat, ErrMsg) + + end function + + function getInputFileDataWindType2() + + INTEGER :: ErrStat + CHARACTER(ErrMsgLen) :: ErrMsg + TYPE(FileInfoType) :: getInputFileDataWindType2 + CHARACTER(1024), DIMENSION(55) :: data = (/ & + '------- InflowWind v3.01.* INPUT FILE ------------------------------------------------------------------------- ', & + 'Steady 8 m/s winds with no shear for FAST CertTests #20 and #25 ', & + '--------------------------------------------------------------------------------------------------------------- ', & + ' true Echo - Echo input data to <RootName>.ech (flag) ', & + ' 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) ', & + ' 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) ', & + ' 90 WindVziList - List of coordinates in the inertial Z direction (m) ', & + '================== Parameters for Steady Wind Conditions [used only for WindType = 1] ========================= ', & + ' 8.0 HWindSpeed - Horizontal windspeed (m/s) ', & + ' 90 RefHt - Reference height for horizontal wind speed (m) ', & + ' 0.1 PLexp - Power law exponent (-) ', & + '================== Parameters for Uniform wind file [used only for WindType = 2] ============================ ', & + '"Wind/08ms.wnd" FileName_Uni - Filename of time series data for uniform wind field. (-) ', & + ' 90 RefHt_Uni - Reference height for horizontal wind speed (m) ', & + ' 125.88 RefLength - Reference length for linear horizontal and vertical sheer (-) ', & + '================== Parameters for Binary TurbSim Full-Field files [used only for WindType = 3] ============== ', & + '"Wind/08ms.wnd" FileName_BTS - Filename of time series data for uniform wind field. (-) ', & + '================== Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4] ========= ', & + '"unused" FilenameRoot - Rootname of the full-field wind file to use (.wnd, .sum) ', & + 'False TowerFile - Have tower file (.twr) (flag) ', & + '================== Parameters for HAWC-format binary files [Only used with WindType = 5] ===================== ', & + '"wasp\Output\basic_5u.bin" FileName_u - name of the file containing the u-component fluctuating wind (.bin) ', & + '"wasp\Output\basic_5v.bin" FileName_v - name of the file containing the v-component fluctuating wind (.bin) ', & + '"wasp\Output\basic_5w.bin" FileName_w - name of the file containing the w-component fluctuating wind (.bin) ', & + ' 64 nx - number of grids in the x direction (in the 3 files above) (-) ', & + ' 32 ny - number of grids in the y direction (in the 3 files above) (-) ', & + ' 32 nz - number of grids in the z direction (in the 3 files above) (-) ', & + ' 16 dx - distance (in meters) between points in the x direction (m) ', & + ' 3 dy - distance (in meters) between points in the y direction (m) ', & + ' 3 dz - distance (in meters) between points in the z direction (m) ', & + ' 90 RefHt_HAWC - reference height; the height (in meters) of the vertical center of the grid (m) ', & + ' ------------- Scaling parameters for turbulence --------------------------------------------------------- ', & + ' 1 ScaleMethod - Turbulence scaling method [0 = none, 1 = direct scaling, 2 = calculate scaling factor based on a desired standard deviation] ', & + ' 1 SFx - Turbulence scaling factor for the x direction (-) [ScaleMethod=1] ', & + ' 1 SFy - Turbulence scaling factor for the y direction (-) [ScaleMethod=1] ', & + ' 1 SFz - Turbulence scaling factor for the z direction (-) [ScaleMethod=1] ', & + ' 12 SigmaFx - Turbulence standard deviation to calculate scaling from in x direction (m/s) [ScaleMethod=2] ', & + ' 8 SigmaFy - Turbulence standard deviation to calculate scaling from in y direction (m/s) [ScaleMethod=2] ', & + ' 2 SigmaFz - Turbulence standard deviation to calculate scaling from in z direction (m/s) [ScaleMethod=2] ', & + ' ------------- Mean wind profile parameters (added to HAWC-format files) --------------------------------- ', & + ' 5 URef - Mean u-component wind speed at the reference height (m/s) ', & + ' 2 WindProfile - Wind profile type (0=constant;1=logarithmic,2=power law) ', & + ' 0 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) ', & + '====================== OUTPUT ================================================== ', & + 'False SumPrint - Print summary data to <RootName>.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,Wind1VelZ" - Wind velocity at point WindVxiList(1),WindVyiList(1),WindVziList(1). X, Y, and Z direction components. ', & + 'END of input file (the word "END" must appear in the first 3 columns of this last OutList line) ', & + '--------------------------------------------------------------------------------------- ' & + /) + + CALL InitFileInfo(data, getInputFileDataWindType2, ErrStat, ErrMsg) + + end function + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_bladed_wind.F90 b/OpenFAST/modules/inflowwind/tests/test_bladed_wind.F90 new file mode 100644 index 000000000..fe9755d8a --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_bladed_wind.F90 @@ -0,0 +1,35 @@ +module test_bladed_wind + + use pFUnit_mod + use ifw_test_tools + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_bladed_wind_input() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + CHARACTER(16) :: expected + + expected = "unused" + PriPath = "" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(trim(expected), InputFileData%BladedFF_FileName) + @assertEqual(.FALSE., InputFileData%BladedFF_TowerFile) + + end subroutine + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_hawc_wind.F90 b/OpenFAST/modules/inflowwind/tests/test_hawc_wind.F90 new file mode 100644 index 000000000..158cda1d0 --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_hawc_wind.F90 @@ -0,0 +1,62 @@ +module test_hawc_wind + + use pFUnit_mod + use ifw_test_tools + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_hawc_wind_input() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + CHARACTER(32) :: expected_fnu + CHARACTER(32) :: expected_fnv + CHARACTER(32) :: expected_fnw + + PriPath = "" + expected_fnu = "wasp\Output\basic_5u.bin" + expected_fnv = "wasp\Output\basic_5v.bin" + expected_fnw = "wasp\Output\basic_5w.bin" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + + @assertEqual(trim(expected_fnu), InputFileData%HAWC_FileName_u) + @assertEqual(trim(expected_fnv), InputFileData%HAWC_FileName_v) + @assertEqual(trim(expected_fnw), InputFileData%HAWC_FileName_w) + @assertEqual(64, InputFileData%HAWC_nx) + @assertEqual(32, InputFileData%HAWC_ny) + @assertEqual(32, InputFileData%HAWC_nz) + @assertEqual(16, InputFileData%HAWC_dx) + @assertEqual(3, InputFileData%HAWC_dy) + @assertEqual(3, InputFileData%HAWC_dz) + @assertEqual(90, InputFileData%FF%RefHt) + + @assertEqual(1, InputFileData%FF%ScaleMethod) + @assertEqual(1, InputFileData%FF%SF(1)) + @assertEqual(1, InputFileData%FF%SF(2)) + @assertEqual(1, InputFileData%FF%SF(3)) + @assertEqual(12, InputFileData%FF%SigmaF(1)) + @assertEqual(8, InputFileData%FF%SigmaF(2)) + @assertEqual(2, InputFileData%FF%SigmaF(3)) + + @assertEqual(5, InputFileData%FF%URef) + @assertEqual(2, InputFileData%FF%WindProfileType) + @assertEqual(0, InputFileData%FF%PLExp) + @assertEqual(0.03, InputFileData%FF%Z0) + @assertEqual(0, InputFileData%FF%XOffset) + + end subroutine + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_outputs.F90 b/OpenFAST/modules/inflowwind/tests/test_outputs.F90 new file mode 100644 index 000000000..d2e403dd4 --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_outputs.F90 @@ -0,0 +1,62 @@ +module test_outputs + + use pFUnit_mod + use ifw_test_tools + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_outputs_parsing() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + PriPath = "" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(.FALSE., InputFileData%SumPrint) + @assertEqual("Wind1VelX", InputFileData%OutList(1)) + @assertEqual("Wind1VelY", InputFileData%OutList(2)) + @assertEqual("Wind1VelZ", InputFileData%OutList(3)) + + end subroutine + + + @test + subroutine test_outputs_parsing_alternate() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + PriPath = "" + + InFileInfo = getInputFileData() + InFileInfo%Lines(51:53) = (/ & + 'True SumPrint - Print summary data to <RootName>.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. ' & + /) + + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(.TRUE., InputFileData%SumPrint) + @assertEqual("Wind1VelX", InputFileData%OutList(1)) + @assertEqual("Wind1VelY", InputFileData%OutList(2)) + + end subroutine + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_steady_wind.F90 b/OpenFAST/modules/inflowwind/tests/test_steady_wind.F90 new file mode 100644 index 000000000..1917ae94f --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_steady_wind.F90 @@ -0,0 +1,63 @@ +module test_steady_wind + + use pFUnit_mod + use ifw_test_tools + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_steady_wind_input_single_height() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + PriPath = "" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(1, InputFileData%WindType) + @assertEqual(1, InputFileData%NWindVel) + @assertEqual(90, InputFileData%WindVziList(1)) + + end subroutine + + + @test + subroutine test_steady_wind_input_mult_heights() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + PriPath = "" + + InFileInfo = getInputFileData() + InFileInfo%Lines(8:11) = (/ & + ' 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) ', & + ' 80,100 WindVziList - List of coordinates in the inertial Z direction (m) ' & + /) + + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(1, InputFileData%WindType) + @assertEqual(2, InputFileData%NWindVel) + @assertEqual(80, InputFileData%WindVziList(1)) + @assertEqual(100, InputFileData%WindVziList(2)) + + end subroutine + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_turbsim_wind.F90 b/OpenFAST/modules/inflowwind/tests/test_turbsim_wind.F90 new file mode 100644 index 000000000..e56df74c7 --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_turbsim_wind.F90 @@ -0,0 +1,34 @@ +module test_turbsim_wind + + use pFUnit_mod + use ifw_test_tools + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_steady_wind_input_single_height() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + CHARACTER(16) :: expected + + expected = "Wind/08ms.wnd" + PriPath = "" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(trim(expected), InputFileData%TSFF_FileName) + + end subroutine + +end module diff --git a/OpenFAST/modules/inflowwind/tests/test_uniform_wind.F90 b/OpenFAST/modules/inflowwind/tests/test_uniform_wind.F90 new file mode 100644 index 000000000..ced5f198c --- /dev/null +++ b/OpenFAST/modules/inflowwind/tests/test_uniform_wind.F90 @@ -0,0 +1,103 @@ +module test_uniform_wind + + use pFUnit_mod + use ifw_test_tools + use InflowWind + use InflowWind_Subs + use InflowWind_Types + + implicit none + +contains + + @test + subroutine test_uniform_wind_input() + + TYPE(FileInfoType) :: InFileInfo + TYPE(InflowWind_InputFile) :: InputFileData + CHARACTER(1024) :: PriPath + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg + + CHARACTER(16) :: expected + + expected = "Wind/08ms.wnd" + PriPath = "" + + InFileInfo = getInputFileData() + CALL InflowWind_ParseInputFileInfo(InputFileData , InFileInfo, PriPath, "inputFile.inp", "test.ech", TmpErrStat, TmpErrMsg) + + @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') + @assertEqual(trim(expected), InputFileData%Uniform_FileName) + @assertEqual(90, InputFileData%Uniform_RefHt) + @assertEqual(125.88, InputFileData%Uniform_RefLength) + + end subroutine + + @test + subroutine test_uniform_wind_direct_data() + + ! Types for setting up module + TYPE(InflowWind_InitInputType) :: InitInp !< Input data for initialization + TYPE(InflowWind_InputType) :: InputGuess !< An initial guess for the input; the input mesh must be defined + TYPE(InflowWind_ParameterType) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType) :: ContStates !< Initial continuous states + TYPE(InflowWind_DiscreteStateType) :: DiscStates !< Initial discrete states + TYPE(InflowWind_ConstraintStateType) :: ConstrStateGuess !< Initial guess of the constraint states + TYPE(InflowWind_OtherStateType) :: OtherStates !< Initial other/optimization states + TYPE(InflowWind_OutputType) :: y !< Initial output (outputs are not calculated; only the output mesh is initialized) + TYPE(InflowWind_MiscVarType) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi) :: TimeInterval !< Coupling time interval in seconds: InflowWind does not change this. + TYPE(InflowWind_InitOutputType) :: InitOutData + + ! Variables for testing + INTEGER :: ErrStat + CHARACTER(ErrMsgLen) :: ErrMsg + TYPE(FileInfoType) :: InFileInfo + TYPE(FileInfoType) :: WindType2Data + CHARACTER(1024), DIMENSION(6) :: data = (/ & + '! Wind file for sheared 18 m/s wind with 30 degree direction. ', & + '! Time Wind Wind Vert. Horiz. Vert. LinV Gust ', & + '! Speed Dir Speed Shear Shear Shear Speed ', & + ' 0.0 12.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ', & + ' 0.1 12.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ', & + ' 999.9 12.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ' & + /) + + ! Error handling + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg !< temporary error message + + InFileInfo = getInputFileDataWindType2() + CALL InitFileInfo(data, WindType2Data, ErrStat, ErrMsg) + + ! 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. + + ! Variable definitions + InitInp%InputFileName = "" + InitInp%NumWindPoints = 5 + InitInp%UseInputFile = .FALSE. + InitInp%RootName = "" + InitInp%PassedFileData = InFileInfo + InitInp%WindType2UseInputFile = .FALSE. + InitInp%WindType2Data = WindType2Data + + CALL InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, & + ConstrStateGuess, OtherStates, y, m, TimeInterval, & + InitOutData, TmpErrStat, TmpErrMsg) + + ! 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(12.0, p%UniformWind%V(1)) + @assertEqual(12.0, p%UniformWind%V(2)) + @assertEqual(12.0, p%UniformWind%V(3)) + + end subroutine + +end module diff --git a/OpenFAST/modules/map/CMakeLists.txt b/OpenFAST/modules/map/CMakeLists.txt new file mode 100644 index 000000000..d1d73bfc1 --- /dev/null +++ b/OpenFAST/modules/map/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright 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. +# + +if(WIN32 OR CYGWIN OR MINGW) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMAP_DLL_EXPORTS -DCMINPACK_NO_DLL -DNDEBUG -D_WINDOWS -D_USRDLL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMAP_DLL_EXPORTS -DCMINPACK_NO_DLL -DNDEBUG -D_WINDOWS -D_USRDLL") +endif() + +if (GENERATE_TYPES) + generate_f90_types(src/MAP_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -ccode) + generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Fortran_Types.f90 -noextrap) +endif() + +file(GLOB MAP_CLIB_SOURCES src/*.c src/*.cc src/*/*.c src/*/*.cc) +file(GLOB MAP_C_HEADERS src/*.h src/*/*.h) + +add_library(mapcpplib ${MAP_CLIB_SOURCES} src/MAP_Types.f90 src/MAP_Fortran_Types.f90) + +target_include_directories(mapcpplib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/bstring> + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/cminpack> + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/lapack> + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/simclist> + $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>) +target_link_libraries(mapcpplib nwtclibs) + +add_library(maplib + src/map.f90 + src/MAP_Types.f90 + src/MAP_Fortran_Types.f90 +) +target_link_libraries(maplib mapcpplib) + +install(TARGETS maplib mapcpplib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +install(FILES + src/MAP_Types.h + DESTINATION include) diff --git a/OpenFAST/modules/map/README.md b/OpenFAST/modules/map/README.md new file mode 100644 index 000000000..e5c2b4237 --- /dev/null +++ b/OpenFAST/modules/map/README.md @@ -0,0 +1,25 @@ +# Map++ Module +This is an externally developed module with further information +available on the developer's documentation site: +[map++ readthedocs](https://map-plus-plus.readthedocs.io/en/latest). + +The legacy version of FAST's information regarding this module +are available at the [NWTC Software Portal](https://nwtc.nrel.gov/MAP/). + +## Overview +The Mooring Analysis Program (MAP++) is a library designed to be used in +parallel with other CAE tools to model the steady-state forces on a +Multi-Segmented, Quasi-Static (MSQS) mooring line. The MSQS model is developed +based on an extension of conventional single line static solutions. +Conceptually, MAP++'s MSQS module solves the algebraic equations for all +elements simultaneously with the condition that the total force at connection +points sum to zero. Seabed contact, seabed friction, and externally applied +forces can be modeled with this tool. This allows multi-element mooring lines +with arbitrary connection configurations to be analyzed. + +Because MAP++ is compiled as a library, it can be linked with other programs at +run-time. Alternatively, one may use MAP++'s native Python binding routines to +access the program through Python. These features give users the option to +execute MAP++ as a stand-alone design or simulation tool. The entry points into +MAP++ follow the function calling conventions outlined by the NWTC FAST +modularization framework. diff --git a/OpenFAST/modules/map/src/MAP_Fortran_Registry.txt b/OpenFAST/modules/map/src/MAP_Fortran_Registry.txt new file mode 100644 index 000000000..b1ad941a8 --- /dev/null +++ b/OpenFAST/modules/map/src/MAP_Fortran_Registry.txt @@ -0,0 +1,22 @@ +################## Registry for MAP++ ############### +# column 1 <keyword> +# column 2 ModuleName/ModName or ^ to use the value from the previous line (SD is nickname for ModuleName) +# column 3 Derived data type (without "ModName_" prefix) +# column 4 Derived data types's Field type +# column 5 Variable name +# column 6 Dimension of variable {:} for allocatable +# column 7 Variable's initial value (if set in the data type) +# column 8 I think this is a switch for mixed-language programming; it's mostly unused +# column 9 Description +# column 10 Units +# Keyword ModuleName/ModName Derived data type Field type Variable name variable dimension Initial value for mix language, not used Description Units + +include Registry_NWTC_Library.txt + +typedef MAP_Fortran/MAP_Fortran Lin_InitInputType LOGICAL linearize - .false. - "Flag that tells this module if the glue code wants to linearize. (fortran-only)" - +typedef ^ Lin_InitOutputType CHARACTER(200) LinNames_y {:} "" - "second line of output file contents: units (fortran-only)" - +typedef ^ ^ CHARACTER(200) LinNames_u {:} "" - "Names of the inputs used in linearization (fortran-only)" - +typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) (fortran-only)" - +typedef ^ Lin_ParamType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian (fortran-only)" - +typedef ^ ^ R8Ki du - - - "determines size of the translational displacement perturbation for u (inputs) (fortran-only)" - +typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix (fortran-only)" - diff --git a/OpenFAST/modules/map/src/MAP_Fortran_Types.f90 b/OpenFAST/modules/map/src/MAP_Fortran_Types.f90 new file mode 100644 index 000000000..47c34ab7c --- /dev/null +++ b/OpenFAST/modules/map/src/MAP_Fortran_Types.f90 @@ -0,0 +1,674 @@ +!STARTOFREGISTRYGENERATEDFILE 'MAP_Fortran_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 +!********************************************************************************************************************************* +! MAP_Fortran_Types +!................................................................................................................................. +! This file is part of MAP_Fortran. +! +! 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 MAP_Fortran. 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 MAP_Fortran_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Lin_InitInputType ======= + TYPE, PUBLIC :: Lin_InitInputType + LOGICAL :: linearize = .false. !< Flag that tells this module if the glue code wants to linearize. (fortran-only) [-] + END TYPE Lin_InitInputType +! ======================= +! ========= Lin_InitOutputType ======= + TYPE, PUBLIC :: Lin_InitOutputType + CHARACTER(200) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< second line of output file contents: units (fortran-only) [-] + CHARACTER(200) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization (fortran-only) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) (fortran-only) [-] + END TYPE Lin_InitOutputType +! ======================= +! ========= Lin_ParamType ======= + TYPE, PUBLIC :: Lin_ParamType + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian (fortran-only) [-] + REAL(R8Ki) :: du !< determines size of the translational displacement perturbation for u (inputs) (fortran-only) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix (fortran-only) [-] + END TYPE Lin_ParamType +! ======================= +CONTAINS + SUBROUTINE MAP_Fortran_CopyLin_InitInputType( SrcLin_InitInputTypeData, DstLin_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lin_InitInputType), INTENT(IN) :: SrcLin_InitInputTypeData + TYPE(Lin_InitInputType), INTENT(INOUT) :: DstLin_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) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Fortran_CopyLin_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstLin_InitInputTypeData%linearize = SrcLin_InitInputTypeData%linearize + END SUBROUTINE MAP_Fortran_CopyLin_InitInputType + + SUBROUTINE MAP_Fortran_DestroyLin_InitInputType( Lin_InitInputTypeData, ErrStat, ErrMsg ) + TYPE(Lin_InitInputType), INTENT(INOUT) :: Lin_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Fortran_DestroyLin_InitInputType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MAP_Fortran_DestroyLin_InitInputType + + SUBROUTINE MAP_Fortran_PackLin_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(Lin_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 = 'MAP_Fortran_PackLin_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 ! linearize + 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%linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MAP_Fortran_PackLin_InitInputType + + SUBROUTINE MAP_Fortran_UnPackLin_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(Lin_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 = 'MAP_Fortran_UnPackLin_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%linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%linearize) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MAP_Fortran_UnPackLin_InitInputType + + SUBROUTINE MAP_Fortran_CopyLin_InitOutputType( SrcLin_InitOutputTypeData, DstLin_InitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lin_InitOutputType), INTENT(IN) :: SrcLin_InitOutputTypeData + TYPE(Lin_InitOutputType), INTENT(INOUT) :: DstLin_InitOutputTypeData + 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 = 'MAP_Fortran_CopyLin_InitOutputType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcLin_InitOutputTypeData%LinNames_y)) THEN + i1_l = LBOUND(SrcLin_InitOutputTypeData%LinNames_y,1) + i1_u = UBOUND(SrcLin_InitOutputTypeData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstLin_InitOutputTypeData%LinNames_y)) THEN + ALLOCATE(DstLin_InitOutputTypeData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLin_InitOutputTypeData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLin_InitOutputTypeData%LinNames_y = SrcLin_InitOutputTypeData%LinNames_y +ENDIF +IF (ALLOCATED(SrcLin_InitOutputTypeData%LinNames_u)) THEN + i1_l = LBOUND(SrcLin_InitOutputTypeData%LinNames_u,1) + i1_u = UBOUND(SrcLin_InitOutputTypeData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstLin_InitOutputTypeData%LinNames_u)) THEN + ALLOCATE(DstLin_InitOutputTypeData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLin_InitOutputTypeData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLin_InitOutputTypeData%LinNames_u = SrcLin_InitOutputTypeData%LinNames_u +ENDIF +IF (ALLOCATED(SrcLin_InitOutputTypeData%IsLoad_u)) THEN + i1_l = LBOUND(SrcLin_InitOutputTypeData%IsLoad_u,1) + i1_u = UBOUND(SrcLin_InitOutputTypeData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstLin_InitOutputTypeData%IsLoad_u)) THEN + ALLOCATE(DstLin_InitOutputTypeData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLin_InitOutputTypeData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLin_InitOutputTypeData%IsLoad_u = SrcLin_InitOutputTypeData%IsLoad_u +ENDIF + END SUBROUTINE MAP_Fortran_CopyLin_InitOutputType + + SUBROUTINE MAP_Fortran_DestroyLin_InitOutputType( Lin_InitOutputTypeData, ErrStat, ErrMsg ) + TYPE(Lin_InitOutputType), INTENT(INOUT) :: Lin_InitOutputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Fortran_DestroyLin_InitOutputType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Lin_InitOutputTypeData%LinNames_y)) THEN + DEALLOCATE(Lin_InitOutputTypeData%LinNames_y) +ENDIF +IF (ALLOCATED(Lin_InitOutputTypeData%LinNames_u)) THEN + DEALLOCATE(Lin_InitOutputTypeData%LinNames_u) +ENDIF +IF (ALLOCATED(Lin_InitOutputTypeData%IsLoad_u)) THEN + DEALLOCATE(Lin_InitOutputTypeData%IsLoad_u) +ENDIF + END SUBROUTINE MAP_Fortran_DestroyLin_InitOutputType + + SUBROUTINE MAP_Fortran_PackLin_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(Lin_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 = 'MAP_Fortran_PackLin_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 + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_Fortran_PackLin_InitOutputType + + SUBROUTINE MAP_Fortran_UnPackLin_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(Lin_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 = 'MAP_Fortran_UnPackLin_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_Fortran_UnPackLin_InitOutputType + + SUBROUTINE MAP_Fortran_CopyLin_ParamType( SrcLin_ParamTypeData, DstLin_ParamTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Lin_ParamType), INTENT(IN) :: SrcLin_ParamTypeData + TYPE(Lin_ParamType), INTENT(INOUT) :: DstLin_ParamTypeData + 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 = 'MAP_Fortran_CopyLin_ParamType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcLin_ParamTypeData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcLin_ParamTypeData%Jac_u_indx,1) + i1_u = UBOUND(SrcLin_ParamTypeData%Jac_u_indx,1) + i2_l = LBOUND(SrcLin_ParamTypeData%Jac_u_indx,2) + i2_u = UBOUND(SrcLin_ParamTypeData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstLin_ParamTypeData%Jac_u_indx)) THEN + ALLOCATE(DstLin_ParamTypeData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLin_ParamTypeData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLin_ParamTypeData%Jac_u_indx = SrcLin_ParamTypeData%Jac_u_indx +ENDIF + DstLin_ParamTypeData%du = SrcLin_ParamTypeData%du + DstLin_ParamTypeData%Jac_ny = SrcLin_ParamTypeData%Jac_ny + END SUBROUTINE MAP_Fortran_CopyLin_ParamType + + SUBROUTINE MAP_Fortran_DestroyLin_ParamType( Lin_ParamTypeData, ErrStat, ErrMsg ) + TYPE(Lin_ParamType), INTENT(INOUT) :: Lin_ParamTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Fortran_DestroyLin_ParamType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(Lin_ParamTypeData%Jac_u_indx)) THEN + DEALLOCATE(Lin_ParamTypeData%Jac_u_indx) +ENDIF + END SUBROUTINE MAP_Fortran_DestroyLin_ParamType + + SUBROUTINE MAP_Fortran_PackLin_ParamType( 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(Lin_ParamType), 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 = 'MAP_Fortran_PackLin_ParamType' + ! 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 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Db_BufSz = Db_BufSz + 1 ! du + Int_BufSz = Int_BufSz + 1 ! Jac_ny + 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%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DbKiBuf(Db_Xferred) = InData%du + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MAP_Fortran_PackLin_ParamType + + SUBROUTINE MAP_Fortran_UnPackLin_ParamType( 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(Lin_ParamType), 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 = 'MAP_Fortran_UnPackLin_ParamType' + ! 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 ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%du = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MAP_Fortran_UnPackLin_ParamType + +END MODULE MAP_Fortran_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/map/src/MAP_Registry.txt b/OpenFAST/modules/map/src/MAP_Registry.txt new file mode 100644 index 000000000..705ad34c0 --- /dev/null +++ b/OpenFAST/modules/map/src/MAP_Registry.txt @@ -0,0 +1,157 @@ +################## Registry for MAP++ ############### +# column 1 <keyword> +# column 2 ModuleName/ModName or ^ to use the value from the previous line (SD is nickname for ModuleName) +# column 3 Derived data type (without "ModName_" prefix) +# column 4 Derived data types's Field type +# column 5 Variable name +# column 6 Dimension of variable {:} for allocatable +# column 7 Variable's initial value (if set in the data type) +# column 8 I think this is a switch for mixed-language programming; it's mostly unused +# column 9 Description +# column 10 Units +# Keyword ModuleName/ModName Derived data type Field type Variable name variable dimension Initial value for mix language, not used Description Units + + +include Registry_NWTC_Library.txt +usefrom MAP_Fortran_Registry.txt + +## ============================== Define input types here: ============================================================================================================================================ +typedef MAP InitInputType DbKi gravity - -999.9 - "gravity constant" "[m/s^2]" +typedef ^ ^ DbKi sea_density - -999.9 - "sea density" "[kg/m^3]" +typedef ^ ^ DbKi depth - -999.9 - "depth of water" "[m]" +typedef ^ ^ CHARACTER(255) file_name - "" - "MAP input file" +typedef ^ ^ CHARACTER(255) summary_file_name - "" - "MAP summary file name" +typedef ^ ^ CHARACTER(255) library_input_str - "" - "cable library string information (from input file)" +typedef ^ ^ CHARACTER(255) node_input_str - "" - "node string information (from input file)" +typedef ^ ^ CHARACTER(255) line_input_str - "" - "element library string information (from input file)" +typedef ^ ^ CHARACTER(255) option_input_str - "" - "solver options library string information (from input file)" +typedef ^ ^ Lin_InitInputType LinInitInp - - - " " - +## ============================== Define Initialization outputs here: ================================================================================================================================ +typedef ^ InitOutputType CHARACTER(99) progName - "" - "program name" +typedef ^ ^ CHARACTER(99) version - "" - "version numnber" +typedef ^ ^ CHARACTER(24) compilingData - "" - "compiling data" +typedef ^ ^ CHARACTER(15) writeOutputHdr {:} "" - "first line output file contents: output variable names" +typedef ^ ^ CHARACTER(15) writeOutputUnt {:} "" - "second line of output file contents: units" +typedef ^ ^ ProgDesc Ver - "" - "this module's name, version, and date" +typedef ^ ^ Lin_InitOutputType LinInitOut - - - "Init Output linearization data (fortran-only)" - + +## ============================== Define Continuous states here: ===================================================================================================================================== +typedef ^ ContinuousStateType DbKI dummy - - - "Remove this variable if you have continuous states" - + + +## ============================== Define Discrete states here: ===================================================================================================================================== +typedef ^ DiscreteStateType DbKi dummy - - - "Remove this variable if you have discrete states" - + + +## ============================== Define Other states here: ===================================================================================================================================== +typedef ^ OtherStateType DbKi H {:} - - "horizontal line force" "[N]" +typedef ^ ^ DbKi V {:} - - "Vertical line force" "[N]" +typedef ^ ^ DbKi Ha {:} - - "horizontal line force at anchor" "[N]" +typedef ^ ^ DbKi Va {:} - - "Vertical line force at anchor" "[N]" +typedef ^ ^ DbKi x {:} - - "x fairlead line position" "[m]" +typedef ^ ^ DbKi y {:} - - "y fairlead line position" "[m]" +typedef ^ ^ DbKi z {:} - - "z fairlead line position" "[m]" +typedef ^ ^ DbKi xa {:} - - "x fairlead line position at anchor" "[m]" +typedef ^ ^ DbKi ya {:} - - "y fairlead line position at anchor" "[m]" +typedef ^ ^ DbKi za {:} - - "z fairlead line position at anchor" "[m]" +typedef ^ ^ DbKi Fx_connect {:} - - "horizontal x line force at connect node" "[N]" +typedef ^ ^ DbKi Fy_connect {:} - - "horizontal y line force at connect node" "[N]" +typedef ^ ^ DbKi Fz_connect {:} - - "vertical z line force at connect node" "[N]" +typedef ^ ^ DbKi Fx_anchor {:} - - "horizontal x line force at connect node" "[N]" +typedef ^ ^ DbKi Fy_anchor {:} - - "horizontal y line force at connect node" "[N]" +typedef ^ ^ DbKi Fz_anchor {:} - - "vertical z line force at connect node" "[N]" + + +## ============================== Define constraint states here: ===================================================================================================================================== +typedef ^ ConstraintStateType DbKi H {:} - - "horizontal line force" "[N]" +typedef ^ ^ DbKi V {:} - - "Vertical line force" "[N]" +typedef ^ ^ DbKi x {:} - - "fairlead x displacement" "[m]" +typedef ^ ^ DbKi y {:} - - "fairlead y displacement" "[m]" +typedef ^ ^ DbKi z {:} - - "fairlead z displacement" "[m]" + + +## ============================== Parameters ============================================================================================================================================ +typedef ^ ParameterType DbKi g - - - "gravitational constant" "[kg/m^2]" +typedef ^ ^ DbKi depth - - - "distance to seabed" "[m]" +typedef ^ ^ DbKi rho_sea - - - "density of seawater" "[m]" +typedef ^ ^ DbKi dt - - - "time step coupling interval" "[sec]" +#typedef ^ ^ DbKi Lu - - - "unstretched cable length" "[m]" +#typedef ^ ^ DbKi EA - - - "Axial stiffness" "[N]" +#typedef ^ ^ DbKi diam - - - "cable diameter" "[m]" +#typedef ^ ^ DbKi cb - - - "cable/seabed friction coefficient" +#typedef ^ ^ DbKi mu - - - "cable mass denity" "[kg/m]" +typedef ^ ^ CHARACTER(255) InputLines {500} - - "input file line for restart" +typedef ^ ^ CHARACTER(1) InputLineType {500} - - "input file line type for restart" +typedef ^ ^ INTEGER numOuts - 0 - "Number of write outputs" - +typedef ^ ^ Lin_ParamType LinParams - - - "Parameter linearization data (fortran-only)" - + +# ============================== Inputs ============================================================================================================================================ +typedef ^ InputType DbKi x {:} - - "fairlead x displacement" "[m]" +typedef ^ ^ DbKi y {:} - - "fairlead y displacement" "[m]" +typedef ^ ^ DbKi z {:} - - "fairlead z displacement" "[m]" +typedef ^ ^ MeshType PtFairDisplacement - - - "position of each fairlead in X,Y,Z" "[m]" + + +## ============================== Outputs ============================================================================================================================================ +typedef ^ OutputType DbKi Fx {:} - - "horizontal line force" "[N]" +typedef ^ ^ DbKi Fy {:} - - "Vertical line force" "[N]" +typedef ^ ^ DbKi Fz {:} - - "horizontal line force at anchor" "[N]" +typedef ^ ^ ReKi WriteOutput {:} - - "outpur vector" "" +typedef ^ ^ DbKi wrtOutput {:} - - "outpur vector" "" +typedef ^ ^ MeshType ptFairleadLoad - - - "point mesh for forces in X,Y,Z" "[N]" + + +##################################################################################################################################### +## These are not necessary to define in the Registry, but are here to generate blank types until we do actually implement the +## Jacobians in the FAST framework. In the final implementation, they will probably not contain subtypes, but instead be +## square matrices of type ReKi or DbKi. +e##################################################################################################################################### +## ..... Jacobians ................................................................................................................. +## Define the Jacobian of the output equations (Y) with respect to the inputs (u), dY/du (or Partial Y / Partial u): +#typedef ^ SD_PartialOutputPInputType SD_InputType DummyOutput - - - "If you have output equations and input data, update this variable" - +# +## Define the Jacobian of the output equations (Y) with respect to the inputs (u), dY/du (or Partial Y / Partial u): +#typedef ^ SD_PartialContStatePInputType SD_InputType DummyContState - - - "If you have continuous state equations and input data, update this variable" - +# +##Define the Jacobian of the discrete state equations (Xd) with respect to the inputs (u), dXd/du (or Partial Xd / Partial u): +#typedef ^ SD_PartialDiscStatePInputType SD_InputType DummyDiscState - - - "If you have discrete state equations and input data, update this variable" - +# +## Define the Jacobian of the constraint state equations (Z) with respect to the inputs (u), dZ/du (or Partial Z / Partial u): +#typedef ^ SD_PartialConstrStatePInputType SD_InputType DummyConstrState - - - "If you have constraint state equations and input data, update this variable" - +# +## Define the Jacobian of the output equations (Y) with respect to the continuous states (x), dY/dx (or Partial Y / Partial x): +#typedef ^ SD_PartialOutputPContStateType SD_ContinuousStateType DummyOutput - - - "If you have output equations and continuous states, update this variable" - +# +## Define the Jacobian of the continuous state equations (X) with respect to the continuous states (x), dX/dx (or Partial X / Partial x): +#typedef ^ SD_PartialContStatePContStateType SD_ContinuousStateType DummyContState - - - "If you have continuous state equations and continuous states, update this variable" - +# +## Define the Jacobian of the discrete state equations (Xd) with respect to the continuous states (x), dXd/dx (or Partial Xd / Partial x): +#typedef ^ SD_PartialDiscStatePContStateType SD_ContinuousStateType DummyDiscState - - - "If you have discrete state equations and continuous states, update this variable" - +# +## Define the Jacobian of the constraint state equations (Z) with respect to the continuous states (x), dZ/dx (or Partial Z / Partial x): +#typedef ^ SD_PartialConstrStatePContStateType SD_ContinuousStateType DummyConstrState - - - "If you have constraint state equations and continuous states, update this variable" - +# +## Define the Jacobian of the output equations (Y) with respect to the discrete states (xd), dY/dxd (or Partial Y / Partial xd): +#typedef ^ SD_PartialOutputPDiscStateType SD_DiscreteStateType DummyOutput - - - "If you have output equations and discrete states, update this variable" - +# +## Define the Jacobian of the continuous state equations (X) with respect to the discrete states (xd), dX/dxd (or Partial X / Partial xd): +#typedef ^ SD_PartialContStatePDiscStateType SD_DiscreteStateType DummyContState - - - "If you have continuous state equations and discrete states, update this variable" - +# +## Define the Jacobian of the discrete state equations (Xd) with respect to the discrete states (xd), dXd/dxd (or Partial Xd / Partial xd): +#typedef ^ SD_PartialDiscStatePDiscStateType SD_DiscreteStateType DummyDiscState - - - "If you have discrete state equations and discrete states, update this variable" - +# +## Define the Jacobian of the constraint state equations (Z) with respect to the discrete states (xd), dZ/dxd (or Partial Z / Partial xd): +#typedef ^ SD_PartialConstrStatePDiscStateType SD_DiscreteStateType DummyConstrState - - - "If you have constraint state equations and discrete states, update this variable" - +# +## Define the Jacobian of the output equations (Y) with respect to the constraint states (z), dY/dz (or Partial Y / Partial z): +#typedef ^ SD_PartialOutputPConstrStateType SD_ConstraintStateType DummyOutput - - - "If you have output equations and constraint states, update this variable" - +# +## Define the Jacobian of the continuous state equations (X) with respect to the constraint states (z), dX/dz (or Partial X / Partial z): +#typedef ^ SD_PartialContStatePConstrStateType SD_ConstraintStateType DummyContState - - - "If you have continuous state equations and constraint states, update this variable" - +# +## Define the Jacobian of the discrete state equations (Xd) with respect to the constraint states (z), dXd/dz (or Partial Xd / Partial z): +#typedef ^ SD_PartialDiscStatePConstrStateType SD_ConstraintStateType DummyDiscState - - - "If you have discrete state equations and constraint states, update this variable" - +# +## Define the Jacobian of the constraint state equations (Z) with respect to the constraint states (z), dZ/dz (or Partial Z / Partial z): +#typedef ^ SD_PartialConstrStatePConstrStateType SD_ConstraintStateType DummyConstrState - - - "If you have constraint state equations and constraint states, update this variable" - + diff --git a/OpenFAST/modules/map/src/MAP_Types.f90 b/OpenFAST/modules/map/src/MAP_Types.f90 new file mode 100644 index 000000000..1b15b8f33 --- /dev/null +++ b/OpenFAST/modules/map/src/MAP_Types.f90 @@ -0,0 +1,5368 @@ +!STARTOFREGISTRYGENERATEDFILE 'MAP_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 +!********************************************************************************************************************************* +! MAP_Types +!................................................................................................................................. +! This file is part of MAP. +! +! 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 MAP. 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 MAP_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE MAP_Fortran_Types +!USE, INTRINSIC :: ISO_C_Binding +USE NWTC_Library +IMPLICIT NONE +! ========= MAP_InitInputType_C ======= + TYPE, BIND(C) :: MAP_InitInputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + REAL(KIND=C_DOUBLE) :: gravity + REAL(KIND=C_DOUBLE) :: sea_density + REAL(KIND=C_DOUBLE) :: depth + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: file_name + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: summary_file_name + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: library_input_str + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: node_input_str + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: line_input_str + CHARACTER(KIND=C_CHAR), DIMENSION(255) :: option_input_str + END TYPE MAP_InitInputType_C + TYPE, PUBLIC :: MAP_InitInputType + TYPE( MAP_InitInputType_C ) :: C_obj + REAL(DbKi) :: gravity = -999.9 !< gravity constant [[m/s^2]] + REAL(DbKi) :: sea_density = -999.9 !< sea density [[kg/m^3]] + REAL(DbKi) :: depth = -999.9 !< depth of water [[m]] + CHARACTER(255) :: file_name !< MAP input file [-] + CHARACTER(255) :: summary_file_name !< MAP summary file name [-] + CHARACTER(255) :: library_input_str !< cable library string information (from input file) [-] + CHARACTER(255) :: node_input_str !< node string information (from input file) [-] + CHARACTER(255) :: line_input_str !< element library string information (from input file) [-] + CHARACTER(255) :: option_input_str !< solver options library string information (from input file) [-] + TYPE(Lin_InitInputType) :: LinInitInp !< [-] + END TYPE MAP_InitInputType +! ======================= +! ========= MAP_InitOutputType_C ======= + TYPE, BIND(C) :: MAP_InitOutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + CHARACTER(KIND=C_CHAR), DIMENSION(99) :: progName + CHARACTER(KIND=C_CHAR), DIMENSION(99) :: version + CHARACTER(KIND=C_CHAR), DIMENSION(24) :: compilingData + TYPE(C_ptr) :: writeOutputHdr = C_NULL_PTR + INTEGER(C_int) :: writeOutputHdr_Len = 0 + TYPE(C_ptr) :: writeOutputUnt = C_NULL_PTR + INTEGER(C_int) :: writeOutputUnt_Len = 0 + END TYPE MAP_InitOutputType_C + TYPE, PUBLIC :: MAP_InitOutputType + TYPE( MAP_InitOutputType_C ) :: C_obj + CHARACTER(99) :: progName !< program name [-] + CHARACTER(99) :: version !< version numnber [-] + CHARACTER(24) :: compilingData !< compiling data [-] + CHARACTER(15) , DIMENSION(:), ALLOCATABLE :: writeOutputHdr !< first line output file contents: output variable names [-] + CHARACTER(15) , DIMENSION(:), ALLOCATABLE :: writeOutputUnt !< second line of output file contents: units [-] + TYPE(ProgDesc) :: Ver !< this module's name, version, and date [-] + TYPE(Lin_InitOutputType) :: LinInitOut !< Init Output linearization data (fortran-only) [-] + END TYPE MAP_InitOutputType +! ======================= +! ========= MAP_ContinuousStateType_C ======= + TYPE, BIND(C) :: MAP_ContinuousStateType_C + TYPE(C_PTR) :: object = C_NULL_PTR + REAL(KIND=C_DOUBLE) :: dummy + END TYPE MAP_ContinuousStateType_C + TYPE, PUBLIC :: MAP_ContinuousStateType + TYPE( MAP_ContinuousStateType_C ) :: C_obj + REAL(DbKi) :: dummy !< Remove this variable if you have continuous states [-] + END TYPE MAP_ContinuousStateType +! ======================= +! ========= MAP_DiscreteStateType_C ======= + TYPE, BIND(C) :: MAP_DiscreteStateType_C + TYPE(C_PTR) :: object = C_NULL_PTR + REAL(KIND=C_DOUBLE) :: dummy + END TYPE MAP_DiscreteStateType_C + TYPE, PUBLIC :: MAP_DiscreteStateType + TYPE( MAP_DiscreteStateType_C ) :: C_obj + REAL(DbKi) :: dummy !< Remove this variable if you have discrete states [-] + END TYPE MAP_DiscreteStateType +! ======================= +! ========= MAP_OtherStateType_C ======= + TYPE, BIND(C) :: MAP_OtherStateType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: H = C_NULL_PTR + INTEGER(C_int) :: H_Len = 0 + TYPE(C_ptr) :: V = C_NULL_PTR + INTEGER(C_int) :: V_Len = 0 + TYPE(C_ptr) :: Ha = C_NULL_PTR + INTEGER(C_int) :: Ha_Len = 0 + TYPE(C_ptr) :: Va = C_NULL_PTR + INTEGER(C_int) :: Va_Len = 0 + TYPE(C_ptr) :: x = C_NULL_PTR + INTEGER(C_int) :: x_Len = 0 + TYPE(C_ptr) :: y = C_NULL_PTR + INTEGER(C_int) :: y_Len = 0 + TYPE(C_ptr) :: z = C_NULL_PTR + INTEGER(C_int) :: z_Len = 0 + TYPE(C_ptr) :: xa = C_NULL_PTR + INTEGER(C_int) :: xa_Len = 0 + TYPE(C_ptr) :: ya = C_NULL_PTR + INTEGER(C_int) :: ya_Len = 0 + TYPE(C_ptr) :: za = C_NULL_PTR + INTEGER(C_int) :: za_Len = 0 + TYPE(C_ptr) :: Fx_connect = C_NULL_PTR + INTEGER(C_int) :: Fx_connect_Len = 0 + TYPE(C_ptr) :: Fy_connect = C_NULL_PTR + INTEGER(C_int) :: Fy_connect_Len = 0 + TYPE(C_ptr) :: Fz_connect = C_NULL_PTR + INTEGER(C_int) :: Fz_connect_Len = 0 + TYPE(C_ptr) :: Fx_anchor = C_NULL_PTR + INTEGER(C_int) :: Fx_anchor_Len = 0 + TYPE(C_ptr) :: Fy_anchor = C_NULL_PTR + INTEGER(C_int) :: Fy_anchor_Len = 0 + TYPE(C_ptr) :: Fz_anchor = C_NULL_PTR + INTEGER(C_int) :: Fz_anchor_Len = 0 + END TYPE MAP_OtherStateType_C + TYPE, PUBLIC :: MAP_OtherStateType + TYPE( MAP_OtherStateType_C ) :: C_obj + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: H => NULL() !< horizontal line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: V => NULL() !< Vertical line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Ha => NULL() !< horizontal line force at anchor [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Va => NULL() !< Vertical line force at anchor [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: x => NULL() !< x fairlead line position [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: y => NULL() !< y fairlead line position [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: z => NULL() !< z fairlead line position [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: xa => NULL() !< x fairlead line position at anchor [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: ya => NULL() !< y fairlead line position at anchor [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: za => NULL() !< z fairlead line position at anchor [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fx_connect => NULL() !< horizontal x line force at connect node [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fy_connect => NULL() !< horizontal y line force at connect node [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fz_connect => NULL() !< vertical z line force at connect node [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fx_anchor => NULL() !< horizontal x line force at connect node [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fy_anchor => NULL() !< horizontal y line force at connect node [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fz_anchor => NULL() !< vertical z line force at connect node [[N]] + END TYPE MAP_OtherStateType +! ======================= +! ========= MAP_ConstraintStateType_C ======= + TYPE, BIND(C) :: MAP_ConstraintStateType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: H = C_NULL_PTR + INTEGER(C_int) :: H_Len = 0 + TYPE(C_ptr) :: V = C_NULL_PTR + INTEGER(C_int) :: V_Len = 0 + TYPE(C_ptr) :: x = C_NULL_PTR + INTEGER(C_int) :: x_Len = 0 + TYPE(C_ptr) :: y = C_NULL_PTR + INTEGER(C_int) :: y_Len = 0 + TYPE(C_ptr) :: z = C_NULL_PTR + INTEGER(C_int) :: z_Len = 0 + END TYPE MAP_ConstraintStateType_C + TYPE, PUBLIC :: MAP_ConstraintStateType + TYPE( MAP_ConstraintStateType_C ) :: C_obj + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: H => NULL() !< horizontal line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: V => NULL() !< Vertical line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: x => NULL() !< fairlead x displacement [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: y => NULL() !< fairlead y displacement [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: z => NULL() !< fairlead z displacement [[m]] + END TYPE MAP_ConstraintStateType +! ======================= +! ========= MAP_ParameterType_C ======= + TYPE, BIND(C) :: MAP_ParameterType_C + TYPE(C_PTR) :: object = C_NULL_PTR + REAL(KIND=C_DOUBLE) :: g + REAL(KIND=C_DOUBLE) :: depth + REAL(KIND=C_DOUBLE) :: rho_sea + REAL(KIND=C_DOUBLE) :: dt + INTEGER(KIND=C_INT) :: numOuts + END TYPE MAP_ParameterType_C + TYPE, PUBLIC :: MAP_ParameterType + TYPE( MAP_ParameterType_C ) :: C_obj + REAL(DbKi) :: g !< gravitational constant [[kg/m^2]] + REAL(DbKi) :: depth !< distance to seabed [[m]] + REAL(DbKi) :: rho_sea !< density of seawater [[m]] + REAL(DbKi) :: dt !< time step coupling interval [[sec]] + CHARACTER(255) , DIMENSION(1:500) :: InputLines !< input file line for restart [-] + CHARACTER(1) , DIMENSION(1:500) :: InputLineType !< input file line type for restart [-] + INTEGER(IntKi) :: numOuts = 0 !< Number of write outputs [-] + TYPE(Lin_ParamType) :: LinParams !< Parameter linearization data (fortran-only) [-] + END TYPE MAP_ParameterType +! ======================= +! ========= MAP_InputType_C ======= + TYPE, BIND(C) :: MAP_InputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: x = C_NULL_PTR + INTEGER(C_int) :: x_Len = 0 + TYPE(C_ptr) :: y = C_NULL_PTR + INTEGER(C_int) :: y_Len = 0 + TYPE(C_ptr) :: z = C_NULL_PTR + INTEGER(C_int) :: z_Len = 0 + END TYPE MAP_InputType_C + TYPE, PUBLIC :: MAP_InputType + TYPE( MAP_InputType_C ) :: C_obj + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: x => NULL() !< fairlead x displacement [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: y => NULL() !< fairlead y displacement [[m]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: z => NULL() !< fairlead z displacement [[m]] + TYPE(MeshType) :: PtFairDisplacement !< position of each fairlead in X,Y,Z [[m]] + END TYPE MAP_InputType +! ======================= +! ========= MAP_OutputType_C ======= + TYPE, BIND(C) :: MAP_OutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: Fx = C_NULL_PTR + INTEGER(C_int) :: Fx_Len = 0 + TYPE(C_ptr) :: Fy = C_NULL_PTR + INTEGER(C_int) :: Fy_Len = 0 + TYPE(C_ptr) :: Fz = C_NULL_PTR + INTEGER(C_int) :: Fz_Len = 0 + TYPE(C_ptr) :: WriteOutput = C_NULL_PTR + INTEGER(C_int) :: WriteOutput_Len = 0 + TYPE(C_ptr) :: wrtOutput = C_NULL_PTR + INTEGER(C_int) :: wrtOutput_Len = 0 + END TYPE MAP_OutputType_C + TYPE, PUBLIC :: MAP_OutputType + TYPE( MAP_OutputType_C ) :: C_obj + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fx => NULL() !< horizontal line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fy => NULL() !< Vertical line force [[N]] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: Fz => NULL() !< horizontal line force at anchor [[N]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< outpur vector [] + REAL(KIND=C_DOUBLE) , DIMENSION(:), POINTER :: wrtOutput => NULL() !< outpur vector [] + TYPE(MeshType) :: ptFairleadLoad !< point mesh for forces in X,Y,Z [[N]] + END TYPE MAP_OutputType +! ======================= +CONTAINS + SUBROUTINE MAP_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(MAP_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 = 'MAP_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%gravity = SrcInitInputData%gravity + DstInitInputData%C_obj%gravity = SrcInitInputData%C_obj%gravity + DstInitInputData%sea_density = SrcInitInputData%sea_density + DstInitInputData%C_obj%sea_density = SrcInitInputData%C_obj%sea_density + DstInitInputData%depth = SrcInitInputData%depth + DstInitInputData%C_obj%depth = SrcInitInputData%C_obj%depth + DstInitInputData%file_name = SrcInitInputData%file_name + DstInitInputData%C_obj%file_name = SrcInitInputData%C_obj%file_name + DstInitInputData%summary_file_name = SrcInitInputData%summary_file_name + DstInitInputData%C_obj%summary_file_name = SrcInitInputData%C_obj%summary_file_name + DstInitInputData%library_input_str = SrcInitInputData%library_input_str + DstInitInputData%C_obj%library_input_str = SrcInitInputData%C_obj%library_input_str + DstInitInputData%node_input_str = SrcInitInputData%node_input_str + DstInitInputData%C_obj%node_input_str = SrcInitInputData%C_obj%node_input_str + DstInitInputData%line_input_str = SrcInitInputData%line_input_str + DstInitInputData%C_obj%line_input_str = SrcInitInputData%C_obj%line_input_str + DstInitInputData%option_input_str = SrcInitInputData%option_input_str + DstInitInputData%C_obj%option_input_str = SrcInitInputData%C_obj%option_input_str + CALL MAP_Fortran_Copylin_initinputtype( SrcInitInputData%LinInitInp, DstInitInputData%LinInitInp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MAP_CopyInitInput + + SUBROUTINE MAP_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(MAP_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MAP_Fortran_Destroylin_initinputtype( InitInputData%LinInitInp, ErrStat, ErrMsg ) + END SUBROUTINE MAP_DestroyInitInput + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Db_BufSz = Db_BufSz + 1 ! gravity + Db_BufSz = Db_BufSz + 1 ! sea_density + Db_BufSz = Db_BufSz + 1 ! depth + Int_BufSz = Int_BufSz + 1*LEN(InData%file_name) ! file_name + Int_BufSz = Int_BufSz + 1*LEN(InData%summary_file_name) ! summary_file_name + Int_BufSz = Int_BufSz + 1*LEN(InData%library_input_str) ! library_input_str + Int_BufSz = Int_BufSz + 1*LEN(InData%node_input_str) ! node_input_str + Int_BufSz = Int_BufSz + 1*LEN(InData%line_input_str) ! line_input_str + Int_BufSz = Int_BufSz + 1*LEN(InData%option_input_str) ! option_input_str + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! LinInitInp: size of buffers for each call to pack subtype + CALL MAP_Fortran_Packlin_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%LinInitInp, ErrStat2, ErrMsg2, .TRUE. ) ! LinInitInp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LinInitInp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LinInitInp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LinInitInp + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DbKiBuf(Db_Xferred) = InData%gravity + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%sea_density + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%depth + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(InData%file_name) + IntKiBuf(Int_Xferred) = ICHAR(InData%file_name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%summary_file_name) + IntKiBuf(Int_Xferred) = ICHAR(InData%summary_file_name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%library_input_str) + IntKiBuf(Int_Xferred) = ICHAR(InData%library_input_str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%node_input_str) + IntKiBuf(Int_Xferred) = ICHAR(InData%node_input_str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%line_input_str) + IntKiBuf(Int_Xferred) = ICHAR(InData%line_input_str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%option_input_str) + IntKiBuf(Int_Xferred) = ICHAR(InData%option_input_str(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + CALL MAP_Fortran_Packlin_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%LinInitInp, ErrStat2, ErrMsg2, OnlySize ) ! LinInitInp + 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 MAP_PackInitInput + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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%gravity = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%gravity = OutData%gravity + OutData%sea_density = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%sea_density = OutData%sea_density + OutData%depth = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%depth = OutData%depth + DO I = 1, LEN(OutData%file_name) + OutData%file_name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%file_name = TRANSFER(OutData%file_name, OutData%C_obj%file_name ) + DO I = 1, LEN(OutData%summary_file_name) + OutData%summary_file_name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%summary_file_name = TRANSFER(OutData%summary_file_name, OutData%C_obj%summary_file_name ) + DO I = 1, LEN(OutData%library_input_str) + OutData%library_input_str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%library_input_str = TRANSFER(OutData%library_input_str, OutData%C_obj%library_input_str ) + DO I = 1, LEN(OutData%node_input_str) + OutData%node_input_str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%node_input_str = TRANSFER(OutData%node_input_str, OutData%C_obj%node_input_str ) + DO I = 1, LEN(OutData%line_input_str) + OutData%line_input_str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%line_input_str = TRANSFER(OutData%line_input_str, OutData%C_obj%line_input_str ) + DO I = 1, LEN(OutData%option_input_str) + OutData%option_input_str(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%option_input_str = TRANSFER(OutData%option_input_str, OutData%C_obj%option_input_str ) + 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 MAP_Fortran_Unpacklin_initinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%LinInitInp, ErrStat2, ErrMsg2 ) ! LinInitInp + 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 MAP_UnPackInitInput + + SUBROUTINE MAP_C2Fary_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%gravity = InitInputData%C_obj%gravity + InitInputData%sea_density = InitInputData%C_obj%sea_density + InitInputData%depth = InitInputData%C_obj%depth + InitInputData%file_name = TRANSFER(InitInputData%C_obj%file_name, InitInputData%file_name ) + InitInputData%summary_file_name = TRANSFER(InitInputData%C_obj%summary_file_name, InitInputData%summary_file_name ) + InitInputData%library_input_str = TRANSFER(InitInputData%C_obj%library_input_str, InitInputData%library_input_str ) + InitInputData%node_input_str = TRANSFER(InitInputData%C_obj%node_input_str, InitInputData%node_input_str ) + InitInputData%line_input_str = TRANSFER(InitInputData%C_obj%line_input_str, InitInputData%line_input_str ) + InitInputData%option_input_str = TRANSFER(InitInputData%C_obj%option_input_str, InitInputData%option_input_str ) + END SUBROUTINE MAP_C2Fary_CopyInitInput + + SUBROUTINE MAP_F2C_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%C_obj%gravity = InitInputData%gravity + InitInputData%C_obj%sea_density = InitInputData%sea_density + InitInputData%C_obj%depth = InitInputData%depth + InitInputData%C_obj%file_name = TRANSFER(InitInputData%file_name, InitInputData%C_obj%file_name ) + InitInputData%C_obj%summary_file_name = TRANSFER(InitInputData%summary_file_name, InitInputData%C_obj%summary_file_name ) + InitInputData%C_obj%library_input_str = TRANSFER(InitInputData%library_input_str, InitInputData%C_obj%library_input_str ) + InitInputData%C_obj%node_input_str = TRANSFER(InitInputData%node_input_str, InitInputData%C_obj%node_input_str ) + InitInputData%C_obj%line_input_str = TRANSFER(InitInputData%line_input_str, InitInputData%C_obj%line_input_str ) + InitInputData%C_obj%option_input_str = TRANSFER(InitInputData%option_input_str, InitInputData%C_obj%option_input_str ) + END SUBROUTINE MAP_F2C_CopyInitInput + + SUBROUTINE MAP_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(MAP_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 = 'MAP_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%progName = SrcInitOutputData%progName + DstInitOutputData%C_obj%progName = SrcInitOutputData%C_obj%progName + DstInitOutputData%version = SrcInitOutputData%version + DstInitOutputData%C_obj%version = SrcInitOutputData%C_obj%version + DstInitOutputData%compilingData = SrcInitOutputData%compilingData + DstInitOutputData%C_obj%compilingData = SrcInitOutputData%C_obj%compilingData +IF (ALLOCATED(SrcInitOutputData%writeOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%writeOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%writeOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%writeOutputHdr)) THEN + ALLOCATE(DstInitOutputData%writeOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%writeOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%writeOutputHdr = SrcInitOutputData%writeOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%writeOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%writeOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%writeOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%writeOutputUnt)) THEN + ALLOCATE(DstInitOutputData%writeOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%writeOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%writeOutputUnt = SrcInitOutputData%writeOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_Fortran_Copylin_initoutputtype( SrcInitOutputData%LinInitOut, DstInitOutputData%LinInitOut, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MAP_CopyInitOutput + + SUBROUTINE MAP_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(MAP_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%writeOutputHdr)) THEN + DEALLOCATE(InitOutputData%writeOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%writeOutputUnt)) THEN + DEALLOCATE(InitOutputData%writeOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + CALL MAP_Fortran_Destroylin_initoutputtype( InitOutputData%LinInitOut, ErrStat, ErrMsg ) + END SUBROUTINE MAP_DestroyInitOutput + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Int_BufSz = Int_BufSz + 1*LEN(InData%progName) ! progName + Int_BufSz = Int_BufSz + 1*LEN(InData%version) ! version + Int_BufSz = Int_BufSz + 1*LEN(InData%compilingData) ! compilingData + Int_BufSz = Int_BufSz + 1 ! writeOutputHdr allocated yes/no + IF ( ALLOCATED(InData%writeOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! writeOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%writeOutputHdr)*LEN(InData%writeOutputHdr) ! writeOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! writeOutputUnt allocated yes/no + IF ( ALLOCATED(InData%writeOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! writeOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%writeOutputUnt)*LEN(InData%writeOutputUnt) ! writeOutputUnt + END IF + ! 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 ! LinInitOut: size of buffers for each call to pack subtype + CALL MAP_Fortran_Packlin_initoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%LinInitOut, ErrStat2, ErrMsg2, .TRUE. ) ! LinInitOut + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LinInitOut + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LinInitOut + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LinInitOut + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%progName) + IntKiBuf(Int_Xferred) = ICHAR(InData%progName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%version) + IntKiBuf(Int_Xferred) = ICHAR(InData%version(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%compilingData) + IntKiBuf(Int_Xferred) = ICHAR(InData%compilingData(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%writeOutputHdr) ) 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%writeOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%writeOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%writeOutputHdr,1), UBOUND(InData%writeOutputHdr,1) + DO I = 1, LEN(InData%writeOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%writeOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%writeOutputUnt) ) 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%writeOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%writeOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%writeOutputUnt,1), UBOUND(InData%writeOutputUnt,1) + DO I = 1, LEN(InData%writeOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%writeOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 MAP_Fortran_Packlin_initoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%LinInitOut, ErrStat2, ErrMsg2, OnlySize ) ! LinInitOut + 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 MAP_PackInitOutput + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + DO I = 1, LEN(OutData%progName) + OutData%progName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%progName = TRANSFER(OutData%progName, OutData%C_obj%progName ) + DO I = 1, LEN(OutData%version) + OutData%version(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%version = TRANSFER(OutData%version, OutData%C_obj%version ) + DO I = 1, LEN(OutData%compilingData) + OutData%compilingData(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%C_obj%compilingData = TRANSFER(OutData%compilingData, OutData%C_obj%compilingData ) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! writeOutputHdr 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%writeOutputHdr)) DEALLOCATE(OutData%writeOutputHdr) + ALLOCATE(OutData%writeOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%writeOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%writeOutputHdr,1), UBOUND(OutData%writeOutputHdr,1) + DO I = 1, LEN(OutData%writeOutputHdr) + OutData%writeOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! writeOutputUnt 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%writeOutputUnt)) DEALLOCATE(OutData%writeOutputUnt) + ALLOCATE(OutData%writeOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%writeOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%writeOutputUnt,1), UBOUND(OutData%writeOutputUnt,1) + DO I = 1, LEN(OutData%writeOutputUnt) + OutData%writeOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 MAP_Fortran_Unpacklin_initoutputtype( Re_Buf, Db_Buf, Int_Buf, OutData%LinInitOut, ErrStat2, ErrMsg2 ) ! LinInitOut + 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 MAP_UnPackInitOutput + + SUBROUTINE MAP_C2Fary_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitOutputData%progName = TRANSFER(InitOutputData%C_obj%progName, InitOutputData%progName ) + InitOutputData%version = TRANSFER(InitOutputData%C_obj%version, InitOutputData%version ) + InitOutputData%compilingData = TRANSFER(InitOutputData%C_obj%compilingData, InitOutputData%compilingData ) + END SUBROUTINE MAP_C2Fary_CopyInitOutput + + SUBROUTINE MAP_F2C_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitOutputData%C_obj%progName = TRANSFER(InitOutputData%progName, InitOutputData%C_obj%progName ) + InitOutputData%C_obj%version = TRANSFER(InitOutputData%version, InitOutputData%C_obj%version ) + InitOutputData%C_obj%compilingData = TRANSFER(InitOutputData%compilingData, InitOutputData%C_obj%compilingData ) + END SUBROUTINE MAP_F2C_CopyInitOutput + + SUBROUTINE MAP_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(MAP_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 = 'MAP_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%dummy = SrcContStateData%dummy + DstContStateData%C_obj%dummy = SrcContStateData%C_obj%dummy + END SUBROUTINE MAP_CopyContState + + SUBROUTINE MAP_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(MAP_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MAP_DestroyContState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Db_BufSz = Db_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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DbKiBuf(Db_Xferred) = InData%dummy + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE MAP_PackContState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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%dummy = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%dummy = OutData%dummy + END SUBROUTINE MAP_UnPackContState + + SUBROUTINE MAP_C2Fary_CopyContState( ContStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ContStateData%dummy = ContStateData%C_obj%dummy + END SUBROUTINE MAP_C2Fary_CopyContState + + SUBROUTINE MAP_F2C_CopyContState( ContStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ContStateData%C_obj%dummy = ContStateData%dummy + END SUBROUTINE MAP_F2C_CopyContState + + SUBROUTINE MAP_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(MAP_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 = 'MAP_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%dummy = SrcDiscStateData%dummy + DstDiscStateData%C_obj%dummy = SrcDiscStateData%C_obj%dummy + END SUBROUTINE MAP_CopyDiscState + + SUBROUTINE MAP_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(MAP_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MAP_DestroyDiscState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Db_BufSz = Db_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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DbKiBuf(Db_Xferred) = InData%dummy + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE MAP_PackDiscState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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%dummy = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%dummy = OutData%dummy + END SUBROUTINE MAP_UnPackDiscState + + SUBROUTINE MAP_C2Fary_CopyDiscState( DiscStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + DiscStateData%dummy = DiscStateData%C_obj%dummy + END SUBROUTINE MAP_C2Fary_CopyDiscState + + SUBROUTINE MAP_F2C_CopyDiscState( DiscStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + DiscStateData%C_obj%dummy = DiscStateData%dummy + END SUBROUTINE MAP_F2C_CopyDiscState + + SUBROUTINE MAP_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(MAP_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcOtherStateData%H)) THEN + i1_l = LBOUND(SrcOtherStateData%H,1) + i1_u = UBOUND(SrcOtherStateData%H,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%H)) THEN + ALLOCATE(DstOtherStateData%H(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%H.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%H_Len = SIZE(DstOtherStateData%H) + IF (DstOtherStateData%c_obj%H_Len > 0) & + DstOtherStateData%c_obj%H = C_LOC( DstOtherStateData%H(i1_l) ) + END IF + DstOtherStateData%H = SrcOtherStateData%H +ENDIF +IF (ASSOCIATED(SrcOtherStateData%V)) THEN + i1_l = LBOUND(SrcOtherStateData%V,1) + i1_u = UBOUND(SrcOtherStateData%V,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%V)) THEN + ALLOCATE(DstOtherStateData%V(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%V.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%V_Len = SIZE(DstOtherStateData%V) + IF (DstOtherStateData%c_obj%V_Len > 0) & + DstOtherStateData%c_obj%V = C_LOC( DstOtherStateData%V(i1_l) ) + END IF + DstOtherStateData%V = SrcOtherStateData%V +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Ha)) THEN + i1_l = LBOUND(SrcOtherStateData%Ha,1) + i1_u = UBOUND(SrcOtherStateData%Ha,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Ha)) THEN + ALLOCATE(DstOtherStateData%Ha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Ha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Ha_Len = SIZE(DstOtherStateData%Ha) + IF (DstOtherStateData%c_obj%Ha_Len > 0) & + DstOtherStateData%c_obj%Ha = C_LOC( DstOtherStateData%Ha(i1_l) ) + END IF + DstOtherStateData%Ha = SrcOtherStateData%Ha +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Va)) THEN + i1_l = LBOUND(SrcOtherStateData%Va,1) + i1_u = UBOUND(SrcOtherStateData%Va,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Va)) THEN + ALLOCATE(DstOtherStateData%Va(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Va.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Va_Len = SIZE(DstOtherStateData%Va) + IF (DstOtherStateData%c_obj%Va_Len > 0) & + DstOtherStateData%c_obj%Va = C_LOC( DstOtherStateData%Va(i1_l) ) + END IF + DstOtherStateData%Va = SrcOtherStateData%Va +ENDIF +IF (ASSOCIATED(SrcOtherStateData%x)) THEN + i1_l = LBOUND(SrcOtherStateData%x,1) + i1_u = UBOUND(SrcOtherStateData%x,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%x)) THEN + ALLOCATE(DstOtherStateData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%x_Len = SIZE(DstOtherStateData%x) + IF (DstOtherStateData%c_obj%x_Len > 0) & + DstOtherStateData%c_obj%x = C_LOC( DstOtherStateData%x(i1_l) ) + END IF + DstOtherStateData%x = SrcOtherStateData%x +ENDIF +IF (ASSOCIATED(SrcOtherStateData%y)) THEN + i1_l = LBOUND(SrcOtherStateData%y,1) + i1_u = UBOUND(SrcOtherStateData%y,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%y)) THEN + ALLOCATE(DstOtherStateData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%y_Len = SIZE(DstOtherStateData%y) + IF (DstOtherStateData%c_obj%y_Len > 0) & + DstOtherStateData%c_obj%y = C_LOC( DstOtherStateData%y(i1_l) ) + END IF + DstOtherStateData%y = SrcOtherStateData%y +ENDIF +IF (ASSOCIATED(SrcOtherStateData%z)) THEN + i1_l = LBOUND(SrcOtherStateData%z,1) + i1_u = UBOUND(SrcOtherStateData%z,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%z)) THEN + ALLOCATE(DstOtherStateData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%z_Len = SIZE(DstOtherStateData%z) + IF (DstOtherStateData%c_obj%z_Len > 0) & + DstOtherStateData%c_obj%z = C_LOC( DstOtherStateData%z(i1_l) ) + END IF + DstOtherStateData%z = SrcOtherStateData%z +ENDIF +IF (ASSOCIATED(SrcOtherStateData%xa)) THEN + i1_l = LBOUND(SrcOtherStateData%xa,1) + i1_u = UBOUND(SrcOtherStateData%xa,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%xa)) THEN + ALLOCATE(DstOtherStateData%xa(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%xa_Len = SIZE(DstOtherStateData%xa) + IF (DstOtherStateData%c_obj%xa_Len > 0) & + DstOtherStateData%c_obj%xa = C_LOC( DstOtherStateData%xa(i1_l) ) + END IF + DstOtherStateData%xa = SrcOtherStateData%xa +ENDIF +IF (ASSOCIATED(SrcOtherStateData%ya)) THEN + i1_l = LBOUND(SrcOtherStateData%ya,1) + i1_u = UBOUND(SrcOtherStateData%ya,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%ya)) THEN + ALLOCATE(DstOtherStateData%ya(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%ya.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%ya_Len = SIZE(DstOtherStateData%ya) + IF (DstOtherStateData%c_obj%ya_Len > 0) & + DstOtherStateData%c_obj%ya = C_LOC( DstOtherStateData%ya(i1_l) ) + END IF + DstOtherStateData%ya = SrcOtherStateData%ya +ENDIF +IF (ASSOCIATED(SrcOtherStateData%za)) THEN + i1_l = LBOUND(SrcOtherStateData%za,1) + i1_u = UBOUND(SrcOtherStateData%za,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%za)) THEN + ALLOCATE(DstOtherStateData%za(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%za.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%za_Len = SIZE(DstOtherStateData%za) + IF (DstOtherStateData%c_obj%za_Len > 0) & + DstOtherStateData%c_obj%za = C_LOC( DstOtherStateData%za(i1_l) ) + END IF + DstOtherStateData%za = SrcOtherStateData%za +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fx_connect)) THEN + i1_l = LBOUND(SrcOtherStateData%Fx_connect,1) + i1_u = UBOUND(SrcOtherStateData%Fx_connect,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fx_connect)) THEN + ALLOCATE(DstOtherStateData%Fx_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fx_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fx_connect_Len = SIZE(DstOtherStateData%Fx_connect) + IF (DstOtherStateData%c_obj%Fx_connect_Len > 0) & + DstOtherStateData%c_obj%Fx_connect = C_LOC( DstOtherStateData%Fx_connect(i1_l) ) + END IF + DstOtherStateData%Fx_connect = SrcOtherStateData%Fx_connect +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fy_connect)) THEN + i1_l = LBOUND(SrcOtherStateData%Fy_connect,1) + i1_u = UBOUND(SrcOtherStateData%Fy_connect,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fy_connect)) THEN + ALLOCATE(DstOtherStateData%Fy_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fy_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fy_connect_Len = SIZE(DstOtherStateData%Fy_connect) + IF (DstOtherStateData%c_obj%Fy_connect_Len > 0) & + DstOtherStateData%c_obj%Fy_connect = C_LOC( DstOtherStateData%Fy_connect(i1_l) ) + END IF + DstOtherStateData%Fy_connect = SrcOtherStateData%Fy_connect +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fz_connect)) THEN + i1_l = LBOUND(SrcOtherStateData%Fz_connect,1) + i1_u = UBOUND(SrcOtherStateData%Fz_connect,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fz_connect)) THEN + ALLOCATE(DstOtherStateData%Fz_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fz_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fz_connect_Len = SIZE(DstOtherStateData%Fz_connect) + IF (DstOtherStateData%c_obj%Fz_connect_Len > 0) & + DstOtherStateData%c_obj%Fz_connect = C_LOC( DstOtherStateData%Fz_connect(i1_l) ) + END IF + DstOtherStateData%Fz_connect = SrcOtherStateData%Fz_connect +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fx_anchor)) THEN + i1_l = LBOUND(SrcOtherStateData%Fx_anchor,1) + i1_u = UBOUND(SrcOtherStateData%Fx_anchor,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fx_anchor)) THEN + ALLOCATE(DstOtherStateData%Fx_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fx_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fx_anchor_Len = SIZE(DstOtherStateData%Fx_anchor) + IF (DstOtherStateData%c_obj%Fx_anchor_Len > 0) & + DstOtherStateData%c_obj%Fx_anchor = C_LOC( DstOtherStateData%Fx_anchor(i1_l) ) + END IF + DstOtherStateData%Fx_anchor = SrcOtherStateData%Fx_anchor +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fy_anchor)) THEN + i1_l = LBOUND(SrcOtherStateData%Fy_anchor,1) + i1_u = UBOUND(SrcOtherStateData%Fy_anchor,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fy_anchor)) THEN + ALLOCATE(DstOtherStateData%Fy_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fy_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fy_anchor_Len = SIZE(DstOtherStateData%Fy_anchor) + IF (DstOtherStateData%c_obj%Fy_anchor_Len > 0) & + DstOtherStateData%c_obj%Fy_anchor = C_LOC( DstOtherStateData%Fy_anchor(i1_l) ) + END IF + DstOtherStateData%Fy_anchor = SrcOtherStateData%Fy_anchor +ENDIF +IF (ASSOCIATED(SrcOtherStateData%Fz_anchor)) THEN + i1_l = LBOUND(SrcOtherStateData%Fz_anchor,1) + i1_u = UBOUND(SrcOtherStateData%Fz_anchor,1) + IF (.NOT. ASSOCIATED(DstOtherStateData%Fz_anchor)) THEN + ALLOCATE(DstOtherStateData%Fz_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%Fz_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOtherStateData%c_obj%Fz_anchor_Len = SIZE(DstOtherStateData%Fz_anchor) + IF (DstOtherStateData%c_obj%Fz_anchor_Len > 0) & + DstOtherStateData%c_obj%Fz_anchor = C_LOC( DstOtherStateData%Fz_anchor(i1_l) ) + END IF + DstOtherStateData%Fz_anchor = SrcOtherStateData%Fz_anchor +ENDIF + END SUBROUTINE MAP_CopyOtherState + + SUBROUTINE MAP_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(MAP_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(OtherStateData%H)) THEN + DEALLOCATE(OtherStateData%H) + OtherStateData%H => NULL() + OtherStateData%C_obj%H = C_NULL_PTR + OtherStateData%C_obj%H_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%V)) THEN + DEALLOCATE(OtherStateData%V) + OtherStateData%V => NULL() + OtherStateData%C_obj%V = C_NULL_PTR + OtherStateData%C_obj%V_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Ha)) THEN + DEALLOCATE(OtherStateData%Ha) + OtherStateData%Ha => NULL() + OtherStateData%C_obj%Ha = C_NULL_PTR + OtherStateData%C_obj%Ha_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Va)) THEN + DEALLOCATE(OtherStateData%Va) + OtherStateData%Va => NULL() + OtherStateData%C_obj%Va = C_NULL_PTR + OtherStateData%C_obj%Va_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%x)) THEN + DEALLOCATE(OtherStateData%x) + OtherStateData%x => NULL() + OtherStateData%C_obj%x = C_NULL_PTR + OtherStateData%C_obj%x_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%y)) THEN + DEALLOCATE(OtherStateData%y) + OtherStateData%y => NULL() + OtherStateData%C_obj%y = C_NULL_PTR + OtherStateData%C_obj%y_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%z)) THEN + DEALLOCATE(OtherStateData%z) + OtherStateData%z => NULL() + OtherStateData%C_obj%z = C_NULL_PTR + OtherStateData%C_obj%z_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%xa)) THEN + DEALLOCATE(OtherStateData%xa) + OtherStateData%xa => NULL() + OtherStateData%C_obj%xa = C_NULL_PTR + OtherStateData%C_obj%xa_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%ya)) THEN + DEALLOCATE(OtherStateData%ya) + OtherStateData%ya => NULL() + OtherStateData%C_obj%ya = C_NULL_PTR + OtherStateData%C_obj%ya_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%za)) THEN + DEALLOCATE(OtherStateData%za) + OtherStateData%za => NULL() + OtherStateData%C_obj%za = C_NULL_PTR + OtherStateData%C_obj%za_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fx_connect)) THEN + DEALLOCATE(OtherStateData%Fx_connect) + OtherStateData%Fx_connect => NULL() + OtherStateData%C_obj%Fx_connect = C_NULL_PTR + OtherStateData%C_obj%Fx_connect_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fy_connect)) THEN + DEALLOCATE(OtherStateData%Fy_connect) + OtherStateData%Fy_connect => NULL() + OtherStateData%C_obj%Fy_connect = C_NULL_PTR + OtherStateData%C_obj%Fy_connect_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fz_connect)) THEN + DEALLOCATE(OtherStateData%Fz_connect) + OtherStateData%Fz_connect => NULL() + OtherStateData%C_obj%Fz_connect = C_NULL_PTR + OtherStateData%C_obj%Fz_connect_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fx_anchor)) THEN + DEALLOCATE(OtherStateData%Fx_anchor) + OtherStateData%Fx_anchor => NULL() + OtherStateData%C_obj%Fx_anchor = C_NULL_PTR + OtherStateData%C_obj%Fx_anchor_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fy_anchor)) THEN + DEALLOCATE(OtherStateData%Fy_anchor) + OtherStateData%Fy_anchor => NULL() + OtherStateData%C_obj%Fy_anchor = C_NULL_PTR + OtherStateData%C_obj%Fy_anchor_Len = 0 +ENDIF +IF (ASSOCIATED(OtherStateData%Fz_anchor)) THEN + DEALLOCATE(OtherStateData%Fz_anchor) + OtherStateData%Fz_anchor => NULL() + OtherStateData%C_obj%Fz_anchor = C_NULL_PTR + OtherStateData%C_obj%Fz_anchor_Len = 0 +ENDIF + END SUBROUTINE MAP_DestroyOtherState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Int_BufSz = Int_BufSz + 1 ! H allocated yes/no + IF ( ASSOCIATED(InData%H) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! H upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%H) ! H + END IF + Int_BufSz = Int_BufSz + 1 ! V allocated yes/no + IF ( ASSOCIATED(InData%V) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! V upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%V) ! V + END IF + Int_BufSz = Int_BufSz + 1 ! Ha allocated yes/no + IF ( ASSOCIATED(InData%Ha) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Ha upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Ha) ! Ha + END IF + Int_BufSz = Int_BufSz + 1 ! Va allocated yes/no + IF ( ASSOCIATED(InData%Va) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Va upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Va) ! Va + END IF + Int_BufSz = Int_BufSz + 1 ! x allocated yes/no + IF ( ASSOCIATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + END IF + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ASSOCIATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! z allocated yes/no + IF ( ASSOCIATED(InData%z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%z) ! z + END IF + Int_BufSz = Int_BufSz + 1 ! xa allocated yes/no + IF ( ASSOCIATED(InData%xa) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xa upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%xa) ! xa + END IF + Int_BufSz = Int_BufSz + 1 ! ya allocated yes/no + IF ( ASSOCIATED(InData%ya) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ya upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%ya) ! ya + END IF + Int_BufSz = Int_BufSz + 1 ! za allocated yes/no + IF ( ASSOCIATED(InData%za) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! za upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%za) ! za + END IF + Int_BufSz = Int_BufSz + 1 ! Fx_connect allocated yes/no + IF ( ASSOCIATED(InData%Fx_connect) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fx_connect upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fx_connect) ! Fx_connect + END IF + Int_BufSz = Int_BufSz + 1 ! Fy_connect allocated yes/no + IF ( ASSOCIATED(InData%Fy_connect) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fy_connect upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fy_connect) ! Fy_connect + END IF + Int_BufSz = Int_BufSz + 1 ! Fz_connect allocated yes/no + IF ( ASSOCIATED(InData%Fz_connect) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fz_connect upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fz_connect) ! Fz_connect + END IF + Int_BufSz = Int_BufSz + 1 ! Fx_anchor allocated yes/no + IF ( ASSOCIATED(InData%Fx_anchor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fx_anchor upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fx_anchor) ! Fx_anchor + END IF + Int_BufSz = Int_BufSz + 1 ! Fy_anchor allocated yes/no + IF ( ASSOCIATED(InData%Fy_anchor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fy_anchor upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fy_anchor) ! Fy_anchor + END IF + Int_BufSz = Int_BufSz + 1 ! Fz_anchor allocated yes/no + IF ( ASSOCIATED(InData%Fz_anchor) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fz_anchor upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fz_anchor) ! Fz_anchor + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%H) ) 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%H,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%H,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%H,1), UBOUND(InData%H,1) + DbKiBuf(Db_Xferred) = InData%H(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(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) + DbKiBuf(Db_Xferred) = InData%V(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Ha) ) 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%Ha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ha,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Ha,1), UBOUND(InData%Ha,1) + DbKiBuf(Db_Xferred) = InData%Ha(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Va) ) 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%Va,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Va,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Va,1), UBOUND(InData%Va,1) + DbKiBuf(Db_Xferred) = InData%Va(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%y) ) 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%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + DbKiBuf(Db_Xferred) = InData%y(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%z) ) 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%z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + DbKiBuf(Db_Xferred) = InData%z(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%xa) ) 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%xa,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xa,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xa,1), UBOUND(InData%xa,1) + DbKiBuf(Db_Xferred) = InData%xa(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%ya) ) 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%ya,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ya,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ya,1), UBOUND(InData%ya,1) + DbKiBuf(Db_Xferred) = InData%ya(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%za) ) 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%za,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%za,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%za,1), UBOUND(InData%za,1) + DbKiBuf(Db_Xferred) = InData%za(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fx_connect) ) 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%Fx_connect,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fx_connect,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fx_connect,1), UBOUND(InData%Fx_connect,1) + DbKiBuf(Db_Xferred) = InData%Fx_connect(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fy_connect) ) 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%Fy_connect,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fy_connect,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fy_connect,1), UBOUND(InData%Fy_connect,1) + DbKiBuf(Db_Xferred) = InData%Fy_connect(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fz_connect) ) 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%Fz_connect,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fz_connect,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fz_connect,1), UBOUND(InData%Fz_connect,1) + DbKiBuf(Db_Xferred) = InData%Fz_connect(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fx_anchor) ) 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%Fx_anchor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fx_anchor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fx_anchor,1), UBOUND(InData%Fx_anchor,1) + DbKiBuf(Db_Xferred) = InData%Fx_anchor(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fy_anchor) ) 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%Fy_anchor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fy_anchor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fy_anchor,1), UBOUND(InData%Fy_anchor,1) + DbKiBuf(Db_Xferred) = InData%Fy_anchor(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fz_anchor) ) 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%Fz_anchor,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fz_anchor,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fz_anchor,1), UBOUND(InData%Fz_anchor,1) + DbKiBuf(Db_Xferred) = InData%Fz_anchor(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_PackOtherState + + SUBROUTINE MAP_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(MAP_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! H 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 (ASSOCIATED(OutData%H)) DEALLOCATE(OutData%H) + ALLOCATE(OutData%H(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%H.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%H_Len = SIZE(OutData%H) + IF (OutData%c_obj%H_Len > 0) & + OutData%c_obj%H = C_LOC( OutData%H(i1_l) ) + DO i1 = LBOUND(OutData%H,1), UBOUND(OutData%H,1) + OutData%H(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_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 (ASSOCIATED(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 + OutData%c_obj%V_Len = SIZE(OutData%V) + IF (OutData%c_obj%V_Len > 0) & + OutData%c_obj%V = C_LOC( OutData%V(i1_l) ) + DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) + OutData%V(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ha 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 (ASSOCIATED(OutData%Ha)) DEALLOCATE(OutData%Ha) + ALLOCATE(OutData%Ha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Ha_Len = SIZE(OutData%Ha) + IF (OutData%c_obj%Ha_Len > 0) & + OutData%c_obj%Ha = C_LOC( OutData%Ha(i1_l) ) + DO i1 = LBOUND(OutData%Ha,1), UBOUND(OutData%Ha,1) + OutData%Ha(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Va 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 (ASSOCIATED(OutData%Va)) DEALLOCATE(OutData%Va) + ALLOCATE(OutData%Va(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Va.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Va_Len = SIZE(OutData%Va) + IF (OutData%c_obj%Va_Len > 0) & + OutData%c_obj%Va = C_LOC( OutData%Va(i1_l) ) + DO i1 = LBOUND(OutData%Va,1), UBOUND(OutData%Va,1) + OutData%Va(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x 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 (ASSOCIATED(OutData%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%x_Len = SIZE(OutData%x) + IF (OutData%c_obj%x_Len > 0) & + OutData%c_obj%x = C_LOC( OutData%x(i1_l) ) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y 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 (ASSOCIATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%y_Len = SIZE(OutData%y) + IF (OutData%c_obj%y_Len > 0) & + OutData%c_obj%y = C_LOC( OutData%y(i1_l) ) + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z 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 (ASSOCIATED(OutData%z)) DEALLOCATE(OutData%z) + ALLOCATE(OutData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%z_Len = SIZE(OutData%z) + IF (OutData%c_obj%z_Len > 0) & + OutData%c_obj%z = C_LOC( OutData%z(i1_l) ) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,1) + OutData%z(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xa 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 (ASSOCIATED(OutData%xa)) DEALLOCATE(OutData%xa) + ALLOCATE(OutData%xa(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%xa_Len = SIZE(OutData%xa) + IF (OutData%c_obj%xa_Len > 0) & + OutData%c_obj%xa = C_LOC( OutData%xa(i1_l) ) + DO i1 = LBOUND(OutData%xa,1), UBOUND(OutData%xa,1) + OutData%xa(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ya 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 (ASSOCIATED(OutData%ya)) DEALLOCATE(OutData%ya) + ALLOCATE(OutData%ya(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ya.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%ya_Len = SIZE(OutData%ya) + IF (OutData%c_obj%ya_Len > 0) & + OutData%c_obj%ya = C_LOC( OutData%ya(i1_l) ) + DO i1 = LBOUND(OutData%ya,1), UBOUND(OutData%ya,1) + OutData%ya(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! za 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 (ASSOCIATED(OutData%za)) DEALLOCATE(OutData%za) + ALLOCATE(OutData%za(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%za.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%za_Len = SIZE(OutData%za) + IF (OutData%c_obj%za_Len > 0) & + OutData%c_obj%za = C_LOC( OutData%za(i1_l) ) + DO i1 = LBOUND(OutData%za,1), UBOUND(OutData%za,1) + OutData%za(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fx_connect 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 (ASSOCIATED(OutData%Fx_connect)) DEALLOCATE(OutData%Fx_connect) + ALLOCATE(OutData%Fx_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fx_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fx_connect_Len = SIZE(OutData%Fx_connect) + IF (OutData%c_obj%Fx_connect_Len > 0) & + OutData%c_obj%Fx_connect = C_LOC( OutData%Fx_connect(i1_l) ) + DO i1 = LBOUND(OutData%Fx_connect,1), UBOUND(OutData%Fx_connect,1) + OutData%Fx_connect(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fy_connect 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 (ASSOCIATED(OutData%Fy_connect)) DEALLOCATE(OutData%Fy_connect) + ALLOCATE(OutData%Fy_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fy_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fy_connect_Len = SIZE(OutData%Fy_connect) + IF (OutData%c_obj%Fy_connect_Len > 0) & + OutData%c_obj%Fy_connect = C_LOC( OutData%Fy_connect(i1_l) ) + DO i1 = LBOUND(OutData%Fy_connect,1), UBOUND(OutData%Fy_connect,1) + OutData%Fy_connect(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fz_connect 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 (ASSOCIATED(OutData%Fz_connect)) DEALLOCATE(OutData%Fz_connect) + ALLOCATE(OutData%Fz_connect(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fz_connect.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fz_connect_Len = SIZE(OutData%Fz_connect) + IF (OutData%c_obj%Fz_connect_Len > 0) & + OutData%c_obj%Fz_connect = C_LOC( OutData%Fz_connect(i1_l) ) + DO i1 = LBOUND(OutData%Fz_connect,1), UBOUND(OutData%Fz_connect,1) + OutData%Fz_connect(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fx_anchor 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 (ASSOCIATED(OutData%Fx_anchor)) DEALLOCATE(OutData%Fx_anchor) + ALLOCATE(OutData%Fx_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fx_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fx_anchor_Len = SIZE(OutData%Fx_anchor) + IF (OutData%c_obj%Fx_anchor_Len > 0) & + OutData%c_obj%Fx_anchor = C_LOC( OutData%Fx_anchor(i1_l) ) + DO i1 = LBOUND(OutData%Fx_anchor,1), UBOUND(OutData%Fx_anchor,1) + OutData%Fx_anchor(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fy_anchor 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 (ASSOCIATED(OutData%Fy_anchor)) DEALLOCATE(OutData%Fy_anchor) + ALLOCATE(OutData%Fy_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fy_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fy_anchor_Len = SIZE(OutData%Fy_anchor) + IF (OutData%c_obj%Fy_anchor_Len > 0) & + OutData%c_obj%Fy_anchor = C_LOC( OutData%Fy_anchor(i1_l) ) + DO i1 = LBOUND(OutData%Fy_anchor,1), UBOUND(OutData%Fy_anchor,1) + OutData%Fy_anchor(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fz_anchor 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 (ASSOCIATED(OutData%Fz_anchor)) DEALLOCATE(OutData%Fz_anchor) + ALLOCATE(OutData%Fz_anchor(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fz_anchor.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fz_anchor_Len = SIZE(OutData%Fz_anchor) + IF (OutData%c_obj%Fz_anchor_Len > 0) & + OutData%c_obj%Fz_anchor = C_LOC( OutData%Fz_anchor(i1_l) ) + DO i1 = LBOUND(OutData%Fz_anchor,1), UBOUND(OutData%Fz_anchor,1) + OutData%Fz_anchor(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_UnPackOtherState + + SUBROUTINE MAP_C2Fary_CopyOtherState( OtherStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- H OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%H ) ) THEN + NULLIFY( OtherStateData%H ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%H, OtherStateData%H, (/OtherStateData%C_obj%H_Len/)) + END IF + END IF + + ! -- V OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%V ) ) THEN + NULLIFY( OtherStateData%V ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%V, OtherStateData%V, (/OtherStateData%C_obj%V_Len/)) + END IF + END IF + + ! -- Ha OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Ha ) ) THEN + NULLIFY( OtherStateData%Ha ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Ha, OtherStateData%Ha, (/OtherStateData%C_obj%Ha_Len/)) + END IF + END IF + + ! -- Va OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Va ) ) THEN + NULLIFY( OtherStateData%Va ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Va, OtherStateData%Va, (/OtherStateData%C_obj%Va_Len/)) + END IF + END IF + + ! -- x OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%x ) ) THEN + NULLIFY( OtherStateData%x ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%x, OtherStateData%x, (/OtherStateData%C_obj%x_Len/)) + END IF + END IF + + ! -- y OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%y ) ) THEN + NULLIFY( OtherStateData%y ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%y, OtherStateData%y, (/OtherStateData%C_obj%y_Len/)) + END IF + END IF + + ! -- z OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%z ) ) THEN + NULLIFY( OtherStateData%z ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%z, OtherStateData%z, (/OtherStateData%C_obj%z_Len/)) + END IF + END IF + + ! -- xa OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%xa ) ) THEN + NULLIFY( OtherStateData%xa ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%xa, OtherStateData%xa, (/OtherStateData%C_obj%xa_Len/)) + END IF + END IF + + ! -- ya OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%ya ) ) THEN + NULLIFY( OtherStateData%ya ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%ya, OtherStateData%ya, (/OtherStateData%C_obj%ya_Len/)) + END IF + END IF + + ! -- za OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%za ) ) THEN + NULLIFY( OtherStateData%za ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%za, OtherStateData%za, (/OtherStateData%C_obj%za_Len/)) + END IF + END IF + + ! -- Fx_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fx_connect ) ) THEN + NULLIFY( OtherStateData%Fx_connect ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fx_connect, OtherStateData%Fx_connect, (/OtherStateData%C_obj%Fx_connect_Len/)) + END IF + END IF + + ! -- Fy_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fy_connect ) ) THEN + NULLIFY( OtherStateData%Fy_connect ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fy_connect, OtherStateData%Fy_connect, (/OtherStateData%C_obj%Fy_connect_Len/)) + END IF + END IF + + ! -- Fz_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fz_connect ) ) THEN + NULLIFY( OtherStateData%Fz_connect ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fz_connect, OtherStateData%Fz_connect, (/OtherStateData%C_obj%Fz_connect_Len/)) + END IF + END IF + + ! -- Fx_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fx_anchor ) ) THEN + NULLIFY( OtherStateData%Fx_anchor ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fx_anchor, OtherStateData%Fx_anchor, (/OtherStateData%C_obj%Fx_anchor_Len/)) + END IF + END IF + + ! -- Fy_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fy_anchor ) ) THEN + NULLIFY( OtherStateData%Fy_anchor ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fy_anchor, OtherStateData%Fy_anchor, (/OtherStateData%C_obj%Fy_anchor_Len/)) + END IF + END IF + + ! -- Fz_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OtherStateData%C_obj%Fz_anchor ) ) THEN + NULLIFY( OtherStateData%Fz_anchor ) + ELSE + CALL C_F_POINTER(OtherStateData%C_obj%Fz_anchor, OtherStateData%Fz_anchor, (/OtherStateData%C_obj%Fz_anchor_Len/)) + END IF + END IF + END SUBROUTINE MAP_C2Fary_CopyOtherState + + SUBROUTINE MAP_F2C_CopyOtherState( OtherStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- H OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%H)) THEN + OtherStateData%c_obj%H_Len = 0 + OtherStateData%c_obj%H = C_NULL_PTR + ELSE + OtherStateData%c_obj%H_Len = SIZE(OtherStateData%H) + IF (OtherStateData%c_obj%H_Len > 0) & + OtherStateData%c_obj%H = C_LOC( OtherStateData%H( LBOUND(OtherStateData%H,1) ) ) + END IF + END IF + + ! -- V OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%V)) THEN + OtherStateData%c_obj%V_Len = 0 + OtherStateData%c_obj%V = C_NULL_PTR + ELSE + OtherStateData%c_obj%V_Len = SIZE(OtherStateData%V) + IF (OtherStateData%c_obj%V_Len > 0) & + OtherStateData%c_obj%V = C_LOC( OtherStateData%V( LBOUND(OtherStateData%V,1) ) ) + END IF + END IF + + ! -- Ha OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Ha)) THEN + OtherStateData%c_obj%Ha_Len = 0 + OtherStateData%c_obj%Ha = C_NULL_PTR + ELSE + OtherStateData%c_obj%Ha_Len = SIZE(OtherStateData%Ha) + IF (OtherStateData%c_obj%Ha_Len > 0) & + OtherStateData%c_obj%Ha = C_LOC( OtherStateData%Ha( LBOUND(OtherStateData%Ha,1) ) ) + END IF + END IF + + ! -- Va OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Va)) THEN + OtherStateData%c_obj%Va_Len = 0 + OtherStateData%c_obj%Va = C_NULL_PTR + ELSE + OtherStateData%c_obj%Va_Len = SIZE(OtherStateData%Va) + IF (OtherStateData%c_obj%Va_Len > 0) & + OtherStateData%c_obj%Va = C_LOC( OtherStateData%Va( LBOUND(OtherStateData%Va,1) ) ) + END IF + END IF + + ! -- x OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%x)) THEN + OtherStateData%c_obj%x_Len = 0 + OtherStateData%c_obj%x = C_NULL_PTR + ELSE + OtherStateData%c_obj%x_Len = SIZE(OtherStateData%x) + IF (OtherStateData%c_obj%x_Len > 0) & + OtherStateData%c_obj%x = C_LOC( OtherStateData%x( LBOUND(OtherStateData%x,1) ) ) + END IF + END IF + + ! -- y OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%y)) THEN + OtherStateData%c_obj%y_Len = 0 + OtherStateData%c_obj%y = C_NULL_PTR + ELSE + OtherStateData%c_obj%y_Len = SIZE(OtherStateData%y) + IF (OtherStateData%c_obj%y_Len > 0) & + OtherStateData%c_obj%y = C_LOC( OtherStateData%y( LBOUND(OtherStateData%y,1) ) ) + END IF + END IF + + ! -- z OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%z)) THEN + OtherStateData%c_obj%z_Len = 0 + OtherStateData%c_obj%z = C_NULL_PTR + ELSE + OtherStateData%c_obj%z_Len = SIZE(OtherStateData%z) + IF (OtherStateData%c_obj%z_Len > 0) & + OtherStateData%c_obj%z = C_LOC( OtherStateData%z( LBOUND(OtherStateData%z,1) ) ) + END IF + END IF + + ! -- xa OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%xa)) THEN + OtherStateData%c_obj%xa_Len = 0 + OtherStateData%c_obj%xa = C_NULL_PTR + ELSE + OtherStateData%c_obj%xa_Len = SIZE(OtherStateData%xa) + IF (OtherStateData%c_obj%xa_Len > 0) & + OtherStateData%c_obj%xa = C_LOC( OtherStateData%xa( LBOUND(OtherStateData%xa,1) ) ) + END IF + END IF + + ! -- ya OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%ya)) THEN + OtherStateData%c_obj%ya_Len = 0 + OtherStateData%c_obj%ya = C_NULL_PTR + ELSE + OtherStateData%c_obj%ya_Len = SIZE(OtherStateData%ya) + IF (OtherStateData%c_obj%ya_Len > 0) & + OtherStateData%c_obj%ya = C_LOC( OtherStateData%ya( LBOUND(OtherStateData%ya,1) ) ) + END IF + END IF + + ! -- za OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%za)) THEN + OtherStateData%c_obj%za_Len = 0 + OtherStateData%c_obj%za = C_NULL_PTR + ELSE + OtherStateData%c_obj%za_Len = SIZE(OtherStateData%za) + IF (OtherStateData%c_obj%za_Len > 0) & + OtherStateData%c_obj%za = C_LOC( OtherStateData%za( LBOUND(OtherStateData%za,1) ) ) + END IF + END IF + + ! -- Fx_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fx_connect)) THEN + OtherStateData%c_obj%Fx_connect_Len = 0 + OtherStateData%c_obj%Fx_connect = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fx_connect_Len = SIZE(OtherStateData%Fx_connect) + IF (OtherStateData%c_obj%Fx_connect_Len > 0) & + OtherStateData%c_obj%Fx_connect = C_LOC( OtherStateData%Fx_connect( LBOUND(OtherStateData%Fx_connect,1) ) ) + END IF + END IF + + ! -- Fy_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fy_connect)) THEN + OtherStateData%c_obj%Fy_connect_Len = 0 + OtherStateData%c_obj%Fy_connect = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fy_connect_Len = SIZE(OtherStateData%Fy_connect) + IF (OtherStateData%c_obj%Fy_connect_Len > 0) & + OtherStateData%c_obj%Fy_connect = C_LOC( OtherStateData%Fy_connect( LBOUND(OtherStateData%Fy_connect,1) ) ) + END IF + END IF + + ! -- Fz_connect OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fz_connect)) THEN + OtherStateData%c_obj%Fz_connect_Len = 0 + OtherStateData%c_obj%Fz_connect = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fz_connect_Len = SIZE(OtherStateData%Fz_connect) + IF (OtherStateData%c_obj%Fz_connect_Len > 0) & + OtherStateData%c_obj%Fz_connect = C_LOC( OtherStateData%Fz_connect( LBOUND(OtherStateData%Fz_connect,1) ) ) + END IF + END IF + + ! -- Fx_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fx_anchor)) THEN + OtherStateData%c_obj%Fx_anchor_Len = 0 + OtherStateData%c_obj%Fx_anchor = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fx_anchor_Len = SIZE(OtherStateData%Fx_anchor) + IF (OtherStateData%c_obj%Fx_anchor_Len > 0) & + OtherStateData%c_obj%Fx_anchor = C_LOC( OtherStateData%Fx_anchor( LBOUND(OtherStateData%Fx_anchor,1) ) ) + END IF + END IF + + ! -- Fy_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fy_anchor)) THEN + OtherStateData%c_obj%Fy_anchor_Len = 0 + OtherStateData%c_obj%Fy_anchor = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fy_anchor_Len = SIZE(OtherStateData%Fy_anchor) + IF (OtherStateData%c_obj%Fy_anchor_Len > 0) & + OtherStateData%c_obj%Fy_anchor = C_LOC( OtherStateData%Fy_anchor( LBOUND(OtherStateData%Fy_anchor,1) ) ) + END IF + END IF + + ! -- Fz_anchor OtherState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OtherStateData%Fz_anchor)) THEN + OtherStateData%c_obj%Fz_anchor_Len = 0 + OtherStateData%c_obj%Fz_anchor = C_NULL_PTR + ELSE + OtherStateData%c_obj%Fz_anchor_Len = SIZE(OtherStateData%Fz_anchor) + IF (OtherStateData%c_obj%Fz_anchor_Len > 0) & + OtherStateData%c_obj%Fz_anchor = C_LOC( OtherStateData%Fz_anchor( LBOUND(OtherStateData%Fz_anchor,1) ) ) + END IF + END IF + END SUBROUTINE MAP_F2C_CopyOtherState + + SUBROUTINE MAP_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(MAP_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcConstrStateData%H)) THEN + i1_l = LBOUND(SrcConstrStateData%H,1) + i1_u = UBOUND(SrcConstrStateData%H,1) + IF (.NOT. ASSOCIATED(DstConstrStateData%H)) THEN + ALLOCATE(DstConstrStateData%H(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%H.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstConstrStateData%c_obj%H_Len = SIZE(DstConstrStateData%H) + IF (DstConstrStateData%c_obj%H_Len > 0) & + DstConstrStateData%c_obj%H = C_LOC( DstConstrStateData%H(i1_l) ) + END IF + DstConstrStateData%H = SrcConstrStateData%H +ENDIF +IF (ASSOCIATED(SrcConstrStateData%V)) THEN + i1_l = LBOUND(SrcConstrStateData%V,1) + i1_u = UBOUND(SrcConstrStateData%V,1) + IF (.NOT. ASSOCIATED(DstConstrStateData%V)) THEN + ALLOCATE(DstConstrStateData%V(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%V.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstConstrStateData%c_obj%V_Len = SIZE(DstConstrStateData%V) + IF (DstConstrStateData%c_obj%V_Len > 0) & + DstConstrStateData%c_obj%V = C_LOC( DstConstrStateData%V(i1_l) ) + END IF + DstConstrStateData%V = SrcConstrStateData%V +ENDIF +IF (ASSOCIATED(SrcConstrStateData%x)) THEN + i1_l = LBOUND(SrcConstrStateData%x,1) + i1_u = UBOUND(SrcConstrStateData%x,1) + IF (.NOT. ASSOCIATED(DstConstrStateData%x)) THEN + ALLOCATE(DstConstrStateData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstConstrStateData%c_obj%x_Len = SIZE(DstConstrStateData%x) + IF (DstConstrStateData%c_obj%x_Len > 0) & + DstConstrStateData%c_obj%x = C_LOC( DstConstrStateData%x(i1_l) ) + END IF + DstConstrStateData%x = SrcConstrStateData%x +ENDIF +IF (ASSOCIATED(SrcConstrStateData%y)) THEN + i1_l = LBOUND(SrcConstrStateData%y,1) + i1_u = UBOUND(SrcConstrStateData%y,1) + IF (.NOT. ASSOCIATED(DstConstrStateData%y)) THEN + ALLOCATE(DstConstrStateData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstConstrStateData%c_obj%y_Len = SIZE(DstConstrStateData%y) + IF (DstConstrStateData%c_obj%y_Len > 0) & + DstConstrStateData%c_obj%y = C_LOC( DstConstrStateData%y(i1_l) ) + END IF + DstConstrStateData%y = SrcConstrStateData%y +ENDIF +IF (ASSOCIATED(SrcConstrStateData%z)) THEN + i1_l = LBOUND(SrcConstrStateData%z,1) + i1_u = UBOUND(SrcConstrStateData%z,1) + IF (.NOT. ASSOCIATED(DstConstrStateData%z)) THEN + ALLOCATE(DstConstrStateData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConstrStateData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstConstrStateData%c_obj%z_Len = SIZE(DstConstrStateData%z) + IF (DstConstrStateData%c_obj%z_Len > 0) & + DstConstrStateData%c_obj%z = C_LOC( DstConstrStateData%z(i1_l) ) + END IF + DstConstrStateData%z = SrcConstrStateData%z +ENDIF + END SUBROUTINE MAP_CopyConstrState + + SUBROUTINE MAP_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(MAP_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(ConstrStateData%H)) THEN + DEALLOCATE(ConstrStateData%H) + ConstrStateData%H => NULL() + ConstrStateData%C_obj%H = C_NULL_PTR + ConstrStateData%C_obj%H_Len = 0 +ENDIF +IF (ASSOCIATED(ConstrStateData%V)) THEN + DEALLOCATE(ConstrStateData%V) + ConstrStateData%V => NULL() + ConstrStateData%C_obj%V = C_NULL_PTR + ConstrStateData%C_obj%V_Len = 0 +ENDIF +IF (ASSOCIATED(ConstrStateData%x)) THEN + DEALLOCATE(ConstrStateData%x) + ConstrStateData%x => NULL() + ConstrStateData%C_obj%x = C_NULL_PTR + ConstrStateData%C_obj%x_Len = 0 +ENDIF +IF (ASSOCIATED(ConstrStateData%y)) THEN + DEALLOCATE(ConstrStateData%y) + ConstrStateData%y => NULL() + ConstrStateData%C_obj%y = C_NULL_PTR + ConstrStateData%C_obj%y_Len = 0 +ENDIF +IF (ASSOCIATED(ConstrStateData%z)) THEN + DEALLOCATE(ConstrStateData%z) + ConstrStateData%z => NULL() + ConstrStateData%C_obj%z = C_NULL_PTR + ConstrStateData%C_obj%z_Len = 0 +ENDIF + END SUBROUTINE MAP_DestroyConstrState + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Int_BufSz = Int_BufSz + 1 ! H allocated yes/no + IF ( ASSOCIATED(InData%H) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! H upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%H) ! H + END IF + Int_BufSz = Int_BufSz + 1 ! V allocated yes/no + IF ( ASSOCIATED(InData%V) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! V upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%V) ! V + END IF + Int_BufSz = Int_BufSz + 1 ! x allocated yes/no + IF ( ASSOCIATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + END IF + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ASSOCIATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! z allocated yes/no + IF ( ASSOCIATED(InData%z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%z) ! z + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%H) ) 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%H,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%H,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%H,1), UBOUND(InData%H,1) + DbKiBuf(Db_Xferred) = InData%H(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(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) + DbKiBuf(Db_Xferred) = InData%V(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%y) ) 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%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + DbKiBuf(Db_Xferred) = InData%y(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%z) ) 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%z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + DbKiBuf(Db_Xferred) = InData%z(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_PackConstrState + + SUBROUTINE MAP_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(MAP_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! H 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 (ASSOCIATED(OutData%H)) DEALLOCATE(OutData%H) + ALLOCATE(OutData%H(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%H.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%H_Len = SIZE(OutData%H) + IF (OutData%c_obj%H_Len > 0) & + OutData%c_obj%H = C_LOC( OutData%H(i1_l) ) + DO i1 = LBOUND(OutData%H,1), UBOUND(OutData%H,1) + OutData%H(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_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 (ASSOCIATED(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 + OutData%c_obj%V_Len = SIZE(OutData%V) + IF (OutData%c_obj%V_Len > 0) & + OutData%c_obj%V = C_LOC( OutData%V(i1_l) ) + DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) + OutData%V(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x 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 (ASSOCIATED(OutData%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%x_Len = SIZE(OutData%x) + IF (OutData%c_obj%x_Len > 0) & + OutData%c_obj%x = C_LOC( OutData%x(i1_l) ) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y 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 (ASSOCIATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%y_Len = SIZE(OutData%y) + IF (OutData%c_obj%y_Len > 0) & + OutData%c_obj%y = C_LOC( OutData%y(i1_l) ) + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z 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 (ASSOCIATED(OutData%z)) DEALLOCATE(OutData%z) + ALLOCATE(OutData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%z_Len = SIZE(OutData%z) + IF (OutData%c_obj%z_Len > 0) & + OutData%c_obj%z = C_LOC( OutData%z(i1_l) ) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,1) + OutData%z(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE MAP_UnPackConstrState + + SUBROUTINE MAP_C2Fary_CopyConstrState( ConstrStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- H ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ConstrStateData%C_obj%H ) ) THEN + NULLIFY( ConstrStateData%H ) + ELSE + CALL C_F_POINTER(ConstrStateData%C_obj%H, ConstrStateData%H, (/ConstrStateData%C_obj%H_Len/)) + END IF + END IF + + ! -- V ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ConstrStateData%C_obj%V ) ) THEN + NULLIFY( ConstrStateData%V ) + ELSE + CALL C_F_POINTER(ConstrStateData%C_obj%V, ConstrStateData%V, (/ConstrStateData%C_obj%V_Len/)) + END IF + END IF + + ! -- x ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ConstrStateData%C_obj%x ) ) THEN + NULLIFY( ConstrStateData%x ) + ELSE + CALL C_F_POINTER(ConstrStateData%C_obj%x, ConstrStateData%x, (/ConstrStateData%C_obj%x_Len/)) + END IF + END IF + + ! -- y ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ConstrStateData%C_obj%y ) ) THEN + NULLIFY( ConstrStateData%y ) + ELSE + CALL C_F_POINTER(ConstrStateData%C_obj%y, ConstrStateData%y, (/ConstrStateData%C_obj%y_Len/)) + END IF + END IF + + ! -- z ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ConstrStateData%C_obj%z ) ) THEN + NULLIFY( ConstrStateData%z ) + ELSE + CALL C_F_POINTER(ConstrStateData%C_obj%z, ConstrStateData%z, (/ConstrStateData%C_obj%z_Len/)) + END IF + END IF + END SUBROUTINE MAP_C2Fary_CopyConstrState + + SUBROUTINE MAP_F2C_CopyConstrState( ConstrStateData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- H ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ConstrStateData%H)) THEN + ConstrStateData%c_obj%H_Len = 0 + ConstrStateData%c_obj%H = C_NULL_PTR + ELSE + ConstrStateData%c_obj%H_Len = SIZE(ConstrStateData%H) + IF (ConstrStateData%c_obj%H_Len > 0) & + ConstrStateData%c_obj%H = C_LOC( ConstrStateData%H( LBOUND(ConstrStateData%H,1) ) ) + END IF + END IF + + ! -- V ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ConstrStateData%V)) THEN + ConstrStateData%c_obj%V_Len = 0 + ConstrStateData%c_obj%V = C_NULL_PTR + ELSE + ConstrStateData%c_obj%V_Len = SIZE(ConstrStateData%V) + IF (ConstrStateData%c_obj%V_Len > 0) & + ConstrStateData%c_obj%V = C_LOC( ConstrStateData%V( LBOUND(ConstrStateData%V,1) ) ) + END IF + END IF + + ! -- x ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ConstrStateData%x)) THEN + ConstrStateData%c_obj%x_Len = 0 + ConstrStateData%c_obj%x = C_NULL_PTR + ELSE + ConstrStateData%c_obj%x_Len = SIZE(ConstrStateData%x) + IF (ConstrStateData%c_obj%x_Len > 0) & + ConstrStateData%c_obj%x = C_LOC( ConstrStateData%x( LBOUND(ConstrStateData%x,1) ) ) + END IF + END IF + + ! -- y ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ConstrStateData%y)) THEN + ConstrStateData%c_obj%y_Len = 0 + ConstrStateData%c_obj%y = C_NULL_PTR + ELSE + ConstrStateData%c_obj%y_Len = SIZE(ConstrStateData%y) + IF (ConstrStateData%c_obj%y_Len > 0) & + ConstrStateData%c_obj%y = C_LOC( ConstrStateData%y( LBOUND(ConstrStateData%y,1) ) ) + END IF + END IF + + ! -- z ConstrState Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ConstrStateData%z)) THEN + ConstrStateData%c_obj%z_Len = 0 + ConstrStateData%c_obj%z = C_NULL_PTR + ELSE + ConstrStateData%c_obj%z_Len = SIZE(ConstrStateData%z) + IF (ConstrStateData%c_obj%z_Len > 0) & + ConstrStateData%c_obj%z = C_LOC( ConstrStateData%z( LBOUND(ConstrStateData%z,1) ) ) + END IF + END IF + END SUBROUTINE MAP_F2C_CopyConstrState + + SUBROUTINE MAP_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_ParameterType), INTENT(IN) :: SrcParamData + TYPE(MAP_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 = 'MAP_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%g = SrcParamData%g + DstParamData%C_obj%g = SrcParamData%C_obj%g + DstParamData%depth = SrcParamData%depth + DstParamData%C_obj%depth = SrcParamData%C_obj%depth + DstParamData%rho_sea = SrcParamData%rho_sea + DstParamData%C_obj%rho_sea = SrcParamData%C_obj%rho_sea + DstParamData%dt = SrcParamData%dt + DstParamData%C_obj%dt = SrcParamData%C_obj%dt + DstParamData%InputLines = SrcParamData%InputLines + DstParamData%InputLineType = SrcParamData%InputLineType + DstParamData%numOuts = SrcParamData%numOuts + DstParamData%C_obj%numOuts = SrcParamData%C_obj%numOuts + CALL MAP_Fortran_Copylin_paramtype( SrcParamData%LinParams, DstParamData%LinParams, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MAP_CopyParam + + SUBROUTINE MAP_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(MAP_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MAP_Fortran_Destroylin_paramtype( ParamData%LinParams, ErrStat, ErrMsg ) + END SUBROUTINE MAP_DestroyParam + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 + Db_BufSz = Db_BufSz + 1 ! g + Db_BufSz = Db_BufSz + 1 ! depth + Db_BufSz = Db_BufSz + 1 ! rho_sea + Db_BufSz = Db_BufSz + 1 ! dt + Int_BufSz = Int_BufSz + SIZE(InData%InputLines)*LEN(InData%InputLines) ! InputLines + Int_BufSz = Int_BufSz + SIZE(InData%InputLineType)*LEN(InData%InputLineType) ! InputLineType + Int_BufSz = Int_BufSz + 1 ! numOuts + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! LinParams: size of buffers for each call to pack subtype + CALL MAP_Fortran_Packlin_paramtype( Re_Buf, Db_Buf, Int_Buf, InData%LinParams, ErrStat2, ErrMsg2, .TRUE. ) ! LinParams + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LinParams + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LinParams + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LinParams + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DbKiBuf(Db_Xferred) = InData%g + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%depth + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%rho_sea + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%dt + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%InputLines,1), UBOUND(InData%InputLines,1) + DO I = 1, LEN(InData%InputLines) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputLines(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + DO i1 = LBOUND(InData%InputLineType,1), UBOUND(InData%InputLineType,1) + DO I = 1, LEN(InData%InputLineType) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputLineType(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = InData%numOuts + Int_Xferred = Int_Xferred + 1 + CALL MAP_Fortran_Packlin_paramtype( Re_Buf, Db_Buf, Int_Buf, InData%LinParams, ErrStat2, ErrMsg2, OnlySize ) ! LinParams + 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 MAP_PackParam + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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%g = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%g = OutData%g + OutData%depth = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%depth = OutData%depth + OutData%rho_sea = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%rho_sea = OutData%rho_sea + OutData%dt = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%C_obj%dt = OutData%dt + i1_l = LBOUND(OutData%InputLines,1) + i1_u = UBOUND(OutData%InputLines,1) + DO i1 = LBOUND(OutData%InputLines,1), UBOUND(OutData%InputLines,1) + DO I = 1, LEN(OutData%InputLines) + OutData%InputLines(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + i1_l = LBOUND(OutData%InputLineType,1) + i1_u = UBOUND(OutData%InputLineType,1) + DO i1 = LBOUND(OutData%InputLineType,1), UBOUND(OutData%InputLineType,1) + DO I = 1, LEN(OutData%InputLineType) + OutData%InputLineType(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%numOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%numOuts = OutData%numOuts + 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 MAP_Fortran_Unpacklin_paramtype( Re_Buf, Db_Buf, Int_Buf, OutData%LinParams, ErrStat2, ErrMsg2 ) ! LinParams + 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 MAP_UnPackParam + + SUBROUTINE MAP_C2Fary_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%g = ParamData%C_obj%g + ParamData%depth = ParamData%C_obj%depth + ParamData%rho_sea = ParamData%C_obj%rho_sea + ParamData%dt = ParamData%C_obj%dt + ParamData%numOuts = ParamData%C_obj%numOuts + END SUBROUTINE MAP_C2Fary_CopyParam + + SUBROUTINE MAP_F2C_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%C_obj%g = ParamData%g + ParamData%C_obj%depth = ParamData%depth + ParamData%C_obj%rho_sea = ParamData%rho_sea + ParamData%C_obj%dt = ParamData%dt + ParamData%C_obj%numOuts = ParamData%numOuts + END SUBROUTINE MAP_F2C_CopyParam + + SUBROUTINE MAP_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_InputType), INTENT(INOUT) :: SrcInputData + TYPE(MAP_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcInputData%x)) THEN + i1_l = LBOUND(SrcInputData%x,1) + i1_u = UBOUND(SrcInputData%x,1) + IF (.NOT. ASSOCIATED(DstInputData%x)) THEN + ALLOCATE(DstInputData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%x_Len = SIZE(DstInputData%x) + IF (DstInputData%c_obj%x_Len > 0) & + DstInputData%c_obj%x = C_LOC( DstInputData%x(i1_l) ) + END IF + DstInputData%x = SrcInputData%x +ENDIF +IF (ASSOCIATED(SrcInputData%y)) THEN + i1_l = LBOUND(SrcInputData%y,1) + i1_u = UBOUND(SrcInputData%y,1) + IF (.NOT. ASSOCIATED(DstInputData%y)) THEN + ALLOCATE(DstInputData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%y_Len = SIZE(DstInputData%y) + IF (DstInputData%c_obj%y_Len > 0) & + DstInputData%c_obj%y = C_LOC( DstInputData%y(i1_l) ) + END IF + DstInputData%y = SrcInputData%y +ENDIF +IF (ASSOCIATED(SrcInputData%z)) THEN + i1_l = LBOUND(SrcInputData%z,1) + i1_u = UBOUND(SrcInputData%z,1) + IF (.NOT. ASSOCIATED(DstInputData%z)) THEN + ALLOCATE(DstInputData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%z_Len = SIZE(DstInputData%z) + IF (DstInputData%c_obj%z_Len > 0) & + DstInputData%c_obj%z = C_LOC( DstInputData%z(i1_l) ) + END IF + DstInputData%z = SrcInputData%z +ENDIF + CALL MeshCopy( SrcInputData%PtFairDisplacement, DstInputData%PtFairDisplacement, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MAP_CopyInput + + SUBROUTINE MAP_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(MAP_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(InputData%x)) THEN + DEALLOCATE(InputData%x) + InputData%x => NULL() + InputData%C_obj%x = C_NULL_PTR + InputData%C_obj%x_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%y)) THEN + DEALLOCATE(InputData%y) + InputData%y => NULL() + InputData%C_obj%y = C_NULL_PTR + InputData%C_obj%y_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%z)) THEN + DEALLOCATE(InputData%z) + InputData%z => NULL() + InputData%C_obj%z = C_NULL_PTR + InputData%C_obj%z_Len = 0 +ENDIF + CALL MeshDestroy( InputData%PtFairDisplacement, ErrStat, ErrMsg ) + END SUBROUTINE MAP_DestroyInput + + SUBROUTINE MAP_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(MAP_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 = 'MAP_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 ! x allocated yes/no + IF ( ASSOCIATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x) ! x + END IF + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ASSOCIATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! z allocated yes/no + IF ( ASSOCIATED(InData%z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%z) ! z + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PtFairDisplacement: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtFairDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtFairDisplacement + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtFairDisplacement + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtFairDisplacement + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtFairDisplacement + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + DbKiBuf(Db_Xferred) = InData%x(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%y) ) 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%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + DbKiBuf(Db_Xferred) = InData%y(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%z) ) 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%z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + DbKiBuf(Db_Xferred) = InData%z(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + CALL MeshPack( InData%PtFairDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtFairDisplacement + 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 MAP_PackInput + + SUBROUTINE MAP_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(MAP_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_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 ! x 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 (ASSOCIATED(OutData%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%x_Len = SIZE(OutData%x) + IF (OutData%c_obj%x_Len > 0) & + OutData%c_obj%x = C_LOC( OutData%x(i1_l) ) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,1) + OutData%x(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y 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 (ASSOCIATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%y_Len = SIZE(OutData%y) + IF (OutData%c_obj%y_Len > 0) & + OutData%c_obj%y = C_LOC( OutData%y(i1_l) ) + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z 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 (ASSOCIATED(OutData%z)) DEALLOCATE(OutData%z) + ALLOCATE(OutData%z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%z_Len = SIZE(OutData%z) + IF (OutData%c_obj%z_Len > 0) & + OutData%c_obj%z = C_LOC( OutData%z(i1_l) ) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,1) + OutData%z(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + 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 MeshUnpack( OutData%PtFairDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtFairDisplacement + 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 MAP_UnPackInput + + SUBROUTINE MAP_C2Fary_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- x Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%x ) ) THEN + NULLIFY( InputData%x ) + ELSE + CALL C_F_POINTER(InputData%C_obj%x, InputData%x, (/InputData%C_obj%x_Len/)) + END IF + END IF + + ! -- y Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%y ) ) THEN + NULLIFY( InputData%y ) + ELSE + CALL C_F_POINTER(InputData%C_obj%y, InputData%y, (/InputData%C_obj%y_Len/)) + END IF + END IF + + ! -- z Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%z ) ) THEN + NULLIFY( InputData%z ) + ELSE + CALL C_F_POINTER(InputData%C_obj%z, InputData%z, (/InputData%C_obj%z_Len/)) + END IF + END IF + END SUBROUTINE MAP_C2Fary_CopyInput + + SUBROUTINE MAP_F2C_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- x Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%x)) THEN + InputData%c_obj%x_Len = 0 + InputData%c_obj%x = C_NULL_PTR + ELSE + InputData%c_obj%x_Len = SIZE(InputData%x) + IF (InputData%c_obj%x_Len > 0) & + InputData%c_obj%x = C_LOC( InputData%x( LBOUND(InputData%x,1) ) ) + END IF + END IF + + ! -- y Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%y)) THEN + InputData%c_obj%y_Len = 0 + InputData%c_obj%y = C_NULL_PTR + ELSE + InputData%c_obj%y_Len = SIZE(InputData%y) + IF (InputData%c_obj%y_Len > 0) & + InputData%c_obj%y = C_LOC( InputData%y( LBOUND(InputData%y,1) ) ) + END IF + END IF + + ! -- z Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%z)) THEN + InputData%c_obj%z_Len = 0 + InputData%c_obj%z = C_NULL_PTR + ELSE + InputData%c_obj%z_Len = SIZE(InputData%z) + IF (InputData%c_obj%z_Len > 0) & + InputData%c_obj%z = C_LOC( InputData%z( LBOUND(InputData%z,1) ) ) + END IF + END IF + END SUBROUTINE MAP_F2C_CopyInput + + SUBROUTINE MAP_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(MAP_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'MAP_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcOutputData%Fx)) THEN + i1_l = LBOUND(SrcOutputData%Fx,1) + i1_u = UBOUND(SrcOutputData%Fx,1) + IF (.NOT. ASSOCIATED(DstOutputData%Fx)) THEN + ALLOCATE(DstOutputData%Fx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Fx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%Fx_Len = SIZE(DstOutputData%Fx) + IF (DstOutputData%c_obj%Fx_Len > 0) & + DstOutputData%c_obj%Fx = C_LOC( DstOutputData%Fx(i1_l) ) + END IF + DstOutputData%Fx = SrcOutputData%Fx +ENDIF +IF (ASSOCIATED(SrcOutputData%Fy)) THEN + i1_l = LBOUND(SrcOutputData%Fy,1) + i1_u = UBOUND(SrcOutputData%Fy,1) + IF (.NOT. ASSOCIATED(DstOutputData%Fy)) THEN + ALLOCATE(DstOutputData%Fy(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Fy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%Fy_Len = SIZE(DstOutputData%Fy) + IF (DstOutputData%c_obj%Fy_Len > 0) & + DstOutputData%c_obj%Fy = C_LOC( DstOutputData%Fy(i1_l) ) + END IF + DstOutputData%Fy = SrcOutputData%Fy +ENDIF +IF (ASSOCIATED(SrcOutputData%Fz)) THEN + i1_l = LBOUND(SrcOutputData%Fz,1) + i1_u = UBOUND(SrcOutputData%Fz,1) + IF (.NOT. ASSOCIATED(DstOutputData%Fz)) THEN + ALLOCATE(DstOutputData%Fz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%Fz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%Fz_Len = SIZE(DstOutputData%Fz) + IF (DstOutputData%c_obj%Fz_Len > 0) & + DstOutputData%c_obj%Fz = C_LOC( DstOutputData%Fz(i1_l) ) + END IF + DstOutputData%Fz = SrcOutputData%Fz +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF +IF (ASSOCIATED(SrcOutputData%wrtOutput)) THEN + i1_l = LBOUND(SrcOutputData%wrtOutput,1) + i1_u = UBOUND(SrcOutputData%wrtOutput,1) + IF (.NOT. ASSOCIATED(DstOutputData%wrtOutput)) THEN + ALLOCATE(DstOutputData%wrtOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%wrtOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%wrtOutput_Len = SIZE(DstOutputData%wrtOutput) + IF (DstOutputData%c_obj%wrtOutput_Len > 0) & + DstOutputData%c_obj%wrtOutput = C_LOC( DstOutputData%wrtOutput(i1_l) ) + END IF + DstOutputData%wrtOutput = SrcOutputData%wrtOutput +ENDIF + CALL MeshCopy( SrcOutputData%ptFairleadLoad, DstOutputData%ptFairleadLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MAP_CopyOutput + + SUBROUTINE MAP_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(MAP_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(OutputData%Fx)) THEN + DEALLOCATE(OutputData%Fx) + OutputData%Fx => NULL() + OutputData%C_obj%Fx = C_NULL_PTR + OutputData%C_obj%Fx_Len = 0 +ENDIF +IF (ASSOCIATED(OutputData%Fy)) THEN + DEALLOCATE(OutputData%Fy) + OutputData%Fy => NULL() + OutputData%C_obj%Fy = C_NULL_PTR + OutputData%C_obj%Fy_Len = 0 +ENDIF +IF (ASSOCIATED(OutputData%Fz)) THEN + DEALLOCATE(OutputData%Fz) + OutputData%Fz => NULL() + OutputData%C_obj%Fz = C_NULL_PTR + OutputData%C_obj%Fz_Len = 0 +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF +IF (ASSOCIATED(OutputData%wrtOutput)) THEN + DEALLOCATE(OutputData%wrtOutput) + OutputData%wrtOutput => NULL() + OutputData%C_obj%wrtOutput = C_NULL_PTR + OutputData%C_obj%wrtOutput_Len = 0 +ENDIF + CALL MeshDestroy( OutputData%ptFairleadLoad, ErrStat, ErrMsg ) + END SUBROUTINE MAP_DestroyOutput + + SUBROUTINE MAP_PackOutput( 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(MAP_OutputType), 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 = 'MAP_PackOutput' + ! 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 ! Fx allocated yes/no + IF ( ASSOCIATED(InData%Fx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fx upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fx) ! Fx + END IF + Int_BufSz = Int_BufSz + 1 ! Fy allocated yes/no + IF ( ASSOCIATED(InData%Fy) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fy upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fy) ! Fy + END IF + Int_BufSz = Int_BufSz + 1 ! Fz allocated yes/no + IF ( ASSOCIATED(InData%Fz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fz upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fz) ! Fz + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + Int_BufSz = Int_BufSz + 1 ! wrtOutput allocated yes/no + IF ( ASSOCIATED(InData%wrtOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! wrtOutput upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%wrtOutput) ! wrtOutput + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! ptFairleadLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%ptFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ptFairleadLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ptFairleadLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ptFairleadLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ptFairleadLoad + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%Fx) ) 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%Fx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fx,1), UBOUND(InData%Fx,1) + DbKiBuf(Db_Xferred) = InData%Fx(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fy) ) 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%Fy,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fy,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fy,1), UBOUND(InData%Fy,1) + DbKiBuf(Db_Xferred) = InData%Fy(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%Fz) ) 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%Fz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Fz,1), UBOUND(InData%Fz,1) + DbKiBuf(Db_Xferred) = InData%Fz(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%wrtOutput) ) 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%wrtOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%wrtOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%wrtOutput,1), UBOUND(InData%wrtOutput,1) + DbKiBuf(Db_Xferred) = InData%wrtOutput(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + CALL MeshPack( InData%ptFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ptFairleadLoad + 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 MAP_PackOutput + + SUBROUTINE MAP_UnPackOutput( 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(MAP_OutputType), 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 = 'MAP_UnPackOutput' + ! 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 ! Fx 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 (ASSOCIATED(OutData%Fx)) DEALLOCATE(OutData%Fx) + ALLOCATE(OutData%Fx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fx_Len = SIZE(OutData%Fx) + IF (OutData%c_obj%Fx_Len > 0) & + OutData%c_obj%Fx = C_LOC( OutData%Fx(i1_l) ) + DO i1 = LBOUND(OutData%Fx,1), UBOUND(OutData%Fx,1) + OutData%Fx(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fy 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 (ASSOCIATED(OutData%Fy)) DEALLOCATE(OutData%Fy) + ALLOCATE(OutData%Fy(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fy_Len = SIZE(OutData%Fy) + IF (OutData%c_obj%Fy_Len > 0) & + OutData%c_obj%Fy = C_LOC( OutData%Fy(i1_l) ) + DO i1 = LBOUND(OutData%Fy,1), UBOUND(OutData%Fy,1) + OutData%Fy(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fz 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 (ASSOCIATED(OutData%Fz)) DEALLOCATE(OutData%Fz) + ALLOCATE(OutData%Fz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%Fz_Len = SIZE(OutData%Fz) + IF (OutData%c_obj%Fz_Len > 0) & + OutData%c_obj%Fz = C_LOC( OutData%Fz(i1_l) ) + DO i1 = LBOUND(OutData%Fz,1), UBOUND(OutData%Fz,1) + OutData%Fz(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! wrtOutput 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 (ASSOCIATED(OutData%wrtOutput)) DEALLOCATE(OutData%wrtOutput) + ALLOCATE(OutData%wrtOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%wrtOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%wrtOutput_Len = SIZE(OutData%wrtOutput) + IF (OutData%c_obj%wrtOutput_Len > 0) & + OutData%c_obj%wrtOutput = C_LOC( OutData%wrtOutput(i1_l) ) + DO i1 = LBOUND(OutData%wrtOutput,1), UBOUND(OutData%wrtOutput,1) + OutData%wrtOutput(i1) = REAL(DbKiBuf(Db_Xferred), C_DOUBLE) + Db_Xferred = Db_Xferred + 1 + 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 MeshUnpack( OutData%ptFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ptFairleadLoad + 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 MAP_UnPackOutput + + SUBROUTINE MAP_C2Fary_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- Fx Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%Fx ) ) THEN + NULLIFY( OutputData%Fx ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%Fx, OutputData%Fx, (/OutputData%C_obj%Fx_Len/)) + END IF + END IF + + ! -- Fy Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%Fy ) ) THEN + NULLIFY( OutputData%Fy ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%Fy, OutputData%Fy, (/OutputData%C_obj%Fy_Len/)) + END IF + END IF + + ! -- Fz Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%Fz ) ) THEN + NULLIFY( OutputData%Fz ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%Fz, OutputData%Fz, (/OutputData%C_obj%Fz_Len/)) + END IF + END IF + + ! -- wrtOutput Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%wrtOutput ) ) THEN + NULLIFY( OutputData%wrtOutput ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%wrtOutput, OutputData%wrtOutput, (/OutputData%C_obj%wrtOutput_Len/)) + END IF + END IF + END SUBROUTINE MAP_C2Fary_CopyOutput + + SUBROUTINE MAP_F2C_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(MAP_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- Fx Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%Fx)) THEN + OutputData%c_obj%Fx_Len = 0 + OutputData%c_obj%Fx = C_NULL_PTR + ELSE + OutputData%c_obj%Fx_Len = SIZE(OutputData%Fx) + IF (OutputData%c_obj%Fx_Len > 0) & + OutputData%c_obj%Fx = C_LOC( OutputData%Fx( LBOUND(OutputData%Fx,1) ) ) + END IF + END IF + + ! -- Fy Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%Fy)) THEN + OutputData%c_obj%Fy_Len = 0 + OutputData%c_obj%Fy = C_NULL_PTR + ELSE + OutputData%c_obj%Fy_Len = SIZE(OutputData%Fy) + IF (OutputData%c_obj%Fy_Len > 0) & + OutputData%c_obj%Fy = C_LOC( OutputData%Fy( LBOUND(OutputData%Fy,1) ) ) + END IF + END IF + + ! -- Fz Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%Fz)) THEN + OutputData%c_obj%Fz_Len = 0 + OutputData%c_obj%Fz = C_NULL_PTR + ELSE + OutputData%c_obj%Fz_Len = SIZE(OutputData%Fz) + IF (OutputData%c_obj%Fz_Len > 0) & + OutputData%c_obj%Fz = C_LOC( OutputData%Fz( LBOUND(OutputData%Fz,1) ) ) + END IF + END IF + + ! -- wrtOutput Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%wrtOutput)) THEN + OutputData%c_obj%wrtOutput_Len = 0 + OutputData%c_obj%wrtOutput = C_NULL_PTR + ELSE + OutputData%c_obj%wrtOutput_Len = SIZE(OutputData%wrtOutput) + IF (OutputData%c_obj%wrtOutput_Len > 0) & + OutputData%c_obj%wrtOutput = C_LOC( OutputData%wrtOutput( LBOUND(OutputData%wrtOutput,1) ) ) + END IF + END IF + END SUBROUTINE MAP_F2C_CopyOutput + + + SUBROUTINE MAP_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(MAP_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(MAP_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL MAP_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL MAP_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL MAP_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE MAP_Input_ExtrapInterp + + + SUBROUTINE MAP_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(MAP_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(MAP_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(MAP_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(u_out%x) .AND. ASSOCIATED(u1%x)) THEN + DO i1 = LBOUND(u_out%x,1),UBOUND(u_out%x,1) + b = -(u1%x(i1) - u2%x(i1)) + u_out%x(i1) = u1%x(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%y) .AND. ASSOCIATED(u1%y)) THEN + DO i1 = LBOUND(u_out%y,1),UBOUND(u_out%y,1) + b = -(u1%y(i1) - u2%y(i1)) + u_out%y(i1) = u1%y(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%z) .AND. ASSOCIATED(u1%z)) THEN + DO i1 = LBOUND(u_out%z,1),UBOUND(u_out%z,1) + b = -(u1%z(i1) - u2%z(i1)) + u_out%z(i1) = u1%z(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + CALL MeshExtrapInterp1(u1%PtFairDisplacement, u2%PtFairDisplacement, tin, u_out%PtFairDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE MAP_Input_ExtrapInterp1 + + + SUBROUTINE MAP_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(MAP_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(MAP_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(MAP_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(MAP_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(u_out%x) .AND. ASSOCIATED(u1%x)) THEN + DO i1 = LBOUND(u_out%x,1),UBOUND(u_out%x,1) + b = (t(3)**2*(u1%x(i1) - u2%x(i1)) + t(2)**2*(-u1%x(i1) + u3%x(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%x(i1) + t(3)*u2%x(i1) - t(2)*u3%x(i1) ) * scaleFactor + u_out%x(i1) = u1%x(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%y) .AND. ASSOCIATED(u1%y)) THEN + DO i1 = LBOUND(u_out%y,1),UBOUND(u_out%y,1) + b = (t(3)**2*(u1%y(i1) - u2%y(i1)) + t(2)**2*(-u1%y(i1) + u3%y(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%y(i1) + t(3)*u2%y(i1) - t(2)*u3%y(i1) ) * scaleFactor + u_out%y(i1) = u1%y(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%z) .AND. ASSOCIATED(u1%z)) THEN + DO i1 = LBOUND(u_out%z,1),UBOUND(u_out%z,1) + b = (t(3)**2*(u1%z(i1) - u2%z(i1)) + t(2)**2*(-u1%z(i1) + u3%z(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%z(i1) + t(3)*u2%z(i1) - t(2)*u3%z(i1) ) * scaleFactor + u_out%z(i1) = u1%z(i1) + b + c * t_out + END DO +END IF ! check if allocated + CALL MeshExtrapInterp2(u1%PtFairDisplacement, u2%PtFairDisplacement, u3%PtFairDisplacement, tin, u_out%PtFairDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE MAP_Input_ExtrapInterp2 + + + SUBROUTINE MAP_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(MAP_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(MAP_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL MAP_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL MAP_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL MAP_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE MAP_Output_ExtrapInterp + + + SUBROUTINE MAP_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(MAP_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(MAP_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(MAP_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(y_out%Fx) .AND. ASSOCIATED(y1%Fx)) THEN + DO i1 = LBOUND(y_out%Fx,1),UBOUND(y_out%Fx,1) + b = -(y1%Fx(i1) - y2%Fx(i1)) + y_out%Fx(i1) = y1%Fx(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%Fy) .AND. ASSOCIATED(y1%Fy)) THEN + DO i1 = LBOUND(y_out%Fy,1),UBOUND(y_out%Fy,1) + b = -(y1%Fy(i1) - y2%Fy(i1)) + y_out%Fy(i1) = y1%Fy(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%Fz) .AND. ASSOCIATED(y1%Fz)) THEN + DO i1 = LBOUND(y_out%Fz,1),UBOUND(y_out%Fz,1) + b = -(y1%Fz(i1) - y2%Fz(i1)) + y_out%Fz(i1) = y1%Fz(i1) + b * ScaleFactor + 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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%wrtOutput) .AND. ASSOCIATED(y1%wrtOutput)) THEN + DO i1 = LBOUND(y_out%wrtOutput,1),UBOUND(y_out%wrtOutput,1) + b = -(y1%wrtOutput(i1) - y2%wrtOutput(i1)) + y_out%wrtOutput(i1) = y1%wrtOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + CALL MeshExtrapInterp1(y1%ptFairleadLoad, y2%ptFairleadLoad, tin, y_out%ptFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE MAP_Output_ExtrapInterp1 + + + SUBROUTINE MAP_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(MAP_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(MAP_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(MAP_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(MAP_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(y_out%Fx) .AND. ASSOCIATED(y1%Fx)) THEN + DO i1 = LBOUND(y_out%Fx,1),UBOUND(y_out%Fx,1) + b = (t(3)**2*(y1%Fx(i1) - y2%Fx(i1)) + t(2)**2*(-y1%Fx(i1) + y3%Fx(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%Fx(i1) + t(3)*y2%Fx(i1) - t(2)*y3%Fx(i1) ) * scaleFactor + y_out%Fx(i1) = y1%Fx(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%Fy) .AND. ASSOCIATED(y1%Fy)) THEN + DO i1 = LBOUND(y_out%Fy,1),UBOUND(y_out%Fy,1) + b = (t(3)**2*(y1%Fy(i1) - y2%Fy(i1)) + t(2)**2*(-y1%Fy(i1) + y3%Fy(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%Fy(i1) + t(3)*y2%Fy(i1) - t(2)*y3%Fy(i1) ) * scaleFactor + y_out%Fy(i1) = y1%Fy(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%Fz) .AND. ASSOCIATED(y1%Fz)) THEN + DO i1 = LBOUND(y_out%Fz,1),UBOUND(y_out%Fz,1) + b = (t(3)**2*(y1%Fz(i1) - y2%Fz(i1)) + t(2)**2*(-y1%Fz(i1) + y3%Fz(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%Fz(i1) + t(3)*y2%Fz(i1) - t(2)*y3%Fz(i1) ) * scaleFactor + y_out%Fz(i1) = y1%Fz(i1) + b + c * t_out + 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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%wrtOutput) .AND. ASSOCIATED(y1%wrtOutput)) THEN + DO i1 = LBOUND(y_out%wrtOutput,1),UBOUND(y_out%wrtOutput,1) + b = (t(3)**2*(y1%wrtOutput(i1) - y2%wrtOutput(i1)) + t(2)**2*(-y1%wrtOutput(i1) + y3%wrtOutput(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%wrtOutput(i1) + t(3)*y2%wrtOutput(i1) - t(2)*y3%wrtOutput(i1) ) * scaleFactor + y_out%wrtOutput(i1) = y1%wrtOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + CALL MeshExtrapInterp2(y1%ptFairleadLoad, y2%ptFairleadLoad, y3%ptFairleadLoad, tin, y_out%ptFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE MAP_Output_ExtrapInterp2 + +END MODULE MAP_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/map/src/MAP_Types.h b/OpenFAST/modules/map/src/MAP_Types.h new file mode 100644 index 000000000..737caea11 --- /dev/null +++ b/OpenFAST/modules/map/src/MAP_Types.h @@ -0,0 +1,123 @@ +//!STARTOFREGISTRYGENERATEDFILE 'MAP_Types.h' +//! +//! WARNING This file is generated automatically by the FAST registry. +//! Do not edit. Your changes to this file will be lost. +//! + +#ifndef _MAP_TYPES_H +#define _MAP_TYPES_H + + +#ifdef _WIN32 //define something for Windows (32-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#elif _WIN64 //define something for Windows (64-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#else +# include <stdbool.h> +# define CALL +#endif + + + typedef struct MAP_InitInputType { + void * object ; + double gravity ; + double sea_density ; + double depth ; + char file_name[255] ; + char summary_file_name[255] ; + char library_input_str[255] ; + char node_input_str[255] ; + char line_input_str[255] ; + char option_input_str[255] ; + + } MAP_InitInputType_t ; + typedef struct MAP_InitOutputType { + void * object ; + char progName[99] ; + char version[99] ; + char compilingData[24] ; + char * writeOutputHdr ; int writeOutputHdr_Len ; + char * writeOutputUnt ; int writeOutputUnt_Len ; + + + } MAP_InitOutputType_t ; + typedef struct MAP_ContinuousStateType { + void * object ; + double dummy ; + } MAP_ContinuousStateType_t ; + typedef struct MAP_DiscreteStateType { + void * object ; + double dummy ; + } MAP_DiscreteStateType_t ; + typedef struct MAP_OtherStateType { + void * object ; + double * H ; int H_Len ; + double * V ; int V_Len ; + double * Ha ; int Ha_Len ; + double * Va ; int Va_Len ; + double * x ; int x_Len ; + double * y ; int y_Len ; + double * z ; int z_Len ; + double * xa ; int xa_Len ; + double * ya ; int ya_Len ; + double * za ; int za_Len ; + double * Fx_connect ; int Fx_connect_Len ; + double * Fy_connect ; int Fy_connect_Len ; + double * Fz_connect ; int Fz_connect_Len ; + double * Fx_anchor ; int Fx_anchor_Len ; + double * Fy_anchor ; int Fy_anchor_Len ; + double * Fz_anchor ; int Fz_anchor_Len ; + } MAP_OtherStateType_t ; + typedef struct MAP_ConstraintStateType { + void * object ; + double * H ; int H_Len ; + double * V ; int V_Len ; + double * x ; int x_Len ; + double * y ; int y_Len ; + double * z ; int z_Len ; + } MAP_ConstraintStateType_t ; + typedef struct MAP_ParameterType { + void * object ; + double g ; + double depth ; + double rho_sea ; + double dt ; + + + int numOuts ; + + } MAP_ParameterType_t ; + typedef struct MAP_InputType { + void * object ; + double * x ; int x_Len ; + double * y ; int y_Len ; + double * z ; int z_Len ; + + } MAP_InputType_t ; + typedef struct MAP_OutputType { + void * object ; + double * Fx ; int Fx_Len ; + double * Fy ; int Fy_Len ; + double * Fz ; int Fz_Len ; + float * WriteOutput ; int WriteOutput_Len ; + double * wrtOutput ; int wrtOutput_Len ; + + } MAP_OutputType_t ; + typedef struct MAP_UserData { + MAP_InitInputType_t MAP_InitInput ; + MAP_InitOutputType_t MAP_InitOutput ; + MAP_ContinuousStateType_t MAP_ContState ; + MAP_DiscreteStateType_t MAP_DiscState ; + MAP_OtherStateType_t MAP_OtherState ; + MAP_ConstraintStateType_t MAP_ConstrState ; + MAP_ParameterType_t MAP_Param ; + MAP_InputType_t MAP_Input ; + MAP_OutputType_t MAP_Output ; + } MAP_t ; + +#endif // _MAP_TYPES_H + + +//!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/map/src/bstring/bstraux.c b/OpenFAST/modules/map/src/bstring/bstraux.c new file mode 100644 index 000000000..be75254f7 --- /dev/null +++ b/OpenFAST/modules/map/src/bstring/bstraux.c @@ -0,0 +1,1176 @@ +/* Copyright 2002-2010 Paul Hsieh + * This file is part of Bstrlib. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of bstrlib nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * GNU General Public License Version 2 (the "GPL"). + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include "bstraux.h" + +bstring +bTail(bstring b, int n) +{ + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) { + return NULL; + } + if (n >= b->slen) { + return bstrcpy(b); + } + return bmidstr(b, b->slen - n, n); +} + +bstring +bHead(bstring b, int n) +{ + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) { + return NULL; + } + if (n >= b->slen) { + return bstrcpy(b); + } + return bmidstr(b, 0, n); +} + +int +bFill(bstring b, char c, int len) +{ + if (b == NULL || len < 0 || (b->mlen < b->slen && b->mlen > 0)) { + return -__LINE__; + } + b->slen = 0; + return bsetstr(b, len, NULL, c); +} + +int +bReplicate(bstring b, int n) +{ + return bpattern (b, n * b->slen); +} + +int +bReverse(bstring b) +{ + int i, n, m; + unsigned char t; + if (b == NULL || b->slen < 0 || b->mlen < b->slen) { + return -__LINE__; + } + n = b->slen; + if (2 <= n) { + m = ((unsigned int)n) >> 1; + n--; + for (i = 0; i < m; i++) { + t = b->data[n - i]; + b->data[n - i] = b->data[i]; + b->data[i] = t; + } + } + return 0; +} + +int +bInsertChrs(bstring b, int pos, int len, unsigned char c, unsigned char fill) +{ + if (b == NULL || + b->slen < 0 || + b->mlen < b->slen || + pos < 0 || + len <= 0) { + return -__LINE__; + } + if (pos > b->slen && + 0 > bsetstr(b, pos, NULL, fill)) { + return -__LINE__; + } + if (0 > balloc(b, b->slen + len)) { + return -__LINE__; + } + if (pos < b->slen) { + memmove(b->data + pos + len, b->data + pos, b->slen - pos); + } + memset(b->data + pos, c, len); + b->slen += len; + b->data[b->slen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +bJustifyLeft(bstring b, int space) +{ + int j, i, s, t; + unsigned char c = (unsigned char) space; + if (b == NULL || b->slen < 0 || b->mlen < b->slen) { + return -__LINE__; + } + if (space != (int) c) { + return BSTR_OK; + } + for (s = j = i = 0; i < b->slen; i++) { + t = s; + s = c != (b->data[j] = b->data[i]); + j += (t|s); + } + if (j > 0 && b->data[j-1] == c) { + --j; + } + b->data[j] = (unsigned char)'\0'; + b->slen = j; + return BSTR_OK; +} + +int +bJustifyRight(bstring b, int width, int space) { + int ret; + if (width <= 0) { + return -__LINE__; + } + if (0 > (ret = bJustifyLeft(b, space))) { + return ret; + } + if (b->slen <= width) { + return bInsertChrs(b, 0, width - b->slen, (unsigned char)space, + (unsigned char)space); + } + return BSTR_OK; +} + +int +bJustifyCenter(bstring b, int width, int space) { + int ret; + if (width <= 0) { + return -__LINE__; + } + if (0 > (ret = bJustifyLeft(b, space))) { + return ret; + } + if (b->slen <= width) { + return bInsertChrs(b, 0, (width - b->slen + 1) >> 1, + (unsigned char)space, + (unsigned char)space); + } + return BSTR_OK; +} + +int +bJustifyMargin(bstring b, int width, int space) +{ + struct bstrList * sl; + int i, l, c; + if (b == NULL || b->slen < 0 || b->mlen == 0 || b->mlen < b->slen) { + return -__LINE__; + } + if (NULL == (sl = bsplit (b, (unsigned char)space))) { + return -__LINE__; + } + for (l = c = i = 0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + c ++; + l += sl->entry[i]->slen; + } + } + if (l + c >= width || c < 2) { + bstrListDestroy(sl); + return bJustifyLeft(b, space); + } + b->slen = 0; + for (i = 0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + if (b->slen > 0) { + int s = (width - l + (c / 2)) / c; + bInsertChrs(b, b->slen, s, + (unsigned char)space, + (unsigned char)space); + l += s; + } + bconcat(b, sl->entry[i]); + c--; + if (c <= 0) break; + } + } + bstrListDestroy(sl); + return BSTR_OK; +} + +static size_t +readNothing(BSTR_UNUSED void *buff, + BSTR_UNUSED size_t elsize, + BSTR_UNUSED size_t nelem, + BSTR_UNUSED void *parm) +{ + return 0; /* Immediately indicate EOF. */ +} + +struct bStream * +bsFromBstr(const bstring b) +{ + struct bStream *s = bsopen((bNread) readNothing, NULL); + bsunread(s, b); /* Push the bstring data into the empty bStream. */ + return s; +} + +static size_t +readRef(void *buff, size_t elsize, size_t nelem, void *parm) +{ + struct tagbstring * t = (struct tagbstring *)parm; + size_t tsz = elsize * nelem; + if (tsz > (size_t)t->slen) { + tsz = (size_t)t->slen; + } + if (tsz > 0) { + memcpy (buff, t->data, tsz); + t->slen -= (int)tsz; + t->data += tsz; + return tsz / elsize; + } + return 0; +} + +/** + * The "by reference" version of the above function. + * + * This function puts a number of restrictions on the call site (the passed in + * struct tagbstring *will* be modified by this function, and the source data + * must remain alive and constant for the lifetime of the bStream). Hence it + * is not presented as an extern. + */ +static struct bStream * +bsFromBstrRef(struct tagbstring * t) +{ + if (!t) { + return NULL; + } + return bsopen((bNread) readRef, t); +} + +char * +bStr2NetStr(const bstring b) +{ + char strnum[sizeof(b->slen) * 3 + 1]; + bstring s; + unsigned char * buff; + if (b == NULL || b->data == NULL || b->slen < 0) { + return NULL; + } + sprintf(strnum, "%d:", b->slen); + if (NULL == (s = bfromcstr(strnum)) || + bconcat(s, b) == BSTR_ERR || + bconchar(s, (char) ',') == BSTR_ERR) { + bdestroy(s); + return NULL; + } + buff = s->data; + bcstrfree((char *)s); + return (char *)buff; +} + +bstring +bNetStr2Bstr(const char * buff) +{ + int i, x; + bstring b; + if (buff == NULL) { + return NULL; + } + x = 0; + for (i = 0; buff[i] != ':'; ++i) { + unsigned int v = buff[i] - '0'; + if (v > 9 || x > ((INT_MAX - (signed int)v) / 10)) { + return NULL; + } + x = (x * 10) + v; + } + /* This thing has to be properly terminated */ + if (buff[i + 1 + x] != ',') { + return NULL; + } + if (NULL == (b = bfromcstr(""))) { + return NULL; + } + if (balloc(b, x + 1) != BSTR_OK) { + bdestroy(b); + return NULL; + } + memcpy(b->data, buff + i + 1, x); + b->data[x] = (unsigned char)'\0'; + b->slen = x; + return b; +} + +static char b64ETable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +bstring +bBase64Encode(const bstring b) +{ + int i, c0, c1, c2, c3; + bstring out; + if (b == NULL || b->slen < 0 || b->data == NULL) { + return NULL; + } + out = bfromcstr(""); + for (i = 0; i + 2 < b->slen; i += 3) { + if (i && ((i % 57) == 0)) { + if (bconchar(out, (char)'\015') < 0 || + bconchar(out, (char)'\012') < 0) { + bdestroy(out); + return NULL; + } + } + c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | (b->data[i+1] >> 4)) & 0x3F; + c2 = ((b->data[i+1] << 2) | (b->data[i+2] >> 6)) & 0x3F; + c3 = b->data[i+2] & 0x3F; + if (bconchar(out, b64ETable[c0]) < 0 || + bconchar(out, b64ETable[c1]) < 0 || + bconchar(out, b64ETable[c2]) < 0 || + bconchar(out, b64ETable[c3]) < 0) { + bdestroy(out); + return NULL; + } + } + if (i && ((i % 57) == 0)) { + if (bconchar(out, (char)'\015') < 0 || + bconchar(out, (char)'\012') < 0) { + bdestroy(out); + return NULL; + } + } + switch (i + 2 - b->slen) { + case 0: c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | (b->data[i+1] >> 4)) & 0x3F; + c2 = (b->data[i+1] << 2) & 0x3F; + if (bconchar(out, b64ETable[c0]) < 0 || + bconchar(out, b64ETable[c1]) < 0 || + bconchar(out, b64ETable[c2]) < 0 || + bconchar(out, (char)'=') < 0) { + bdestroy(out); + return NULL; + } + break; + case 1: c0 = b->data[i] >> 2; + c1 = (b->data[i] << 4) & 0x3F; + if (bconchar(out, b64ETable[c0]) < 0 || + bconchar(out, b64ETable[c1]) < 0 || + bconchar(out, (char)'=') < 0 || + bconchar(out, (char)'=') < 0) { + bdestroy(out); + return NULL; + } + break; + case 2: + break; + } + return out; +} + +#define B64_PAD (-2) +#define B64_ERR (-1) + +static int +base64DecodeSymbol(unsigned char alpha) +{ + if ((alpha >= 'A') && (alpha <= 'Z')) { + return (int)(alpha - 'A'); + } else if ((alpha >= 'a') && (alpha <= 'z')) { + return 26 + (int)(alpha - 'a'); + } else if ((alpha >= '0') && (alpha <= '9')) { + return 52 + (int)(alpha - '0'); + } else if (alpha == '+') { + return 62; + } else if (alpha == '/') { + return 63; + } else if (alpha == '=') { + return B64_PAD; + } else { + return B64_ERR; + } +} + +bstring +bBase64DecodeEx(const bstring b, int * boolTruncError) +{ + int i, v; + unsigned char c0, c1, c2; + bstring out; + if (b == NULL || b->slen < 0 || b->data == NULL) { + return NULL; + } + if (boolTruncError) { + *boolTruncError = 0; + } + out = bfromcstr(""); + i = 0; + while (1) { + do { + if (i >= b->slen) { + return out; + } + if (b->data[i] == '=') { + /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy(out); + return NULL; + } + v = base64DecodeSymbol(b->data[i]); + i++; + } while (v < 0); + c0 = (unsigned char)(v << 2); + do { + if (i >= b->slen || b->data[i] == '=') { + /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy(out); + return NULL; + } + v = base64DecodeSymbol(b->data[i]); + i++; + } while (v < 0); + c0 |= (unsigned char)(v >> 4); + c1 = (unsigned char)(v << 4); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy(out); + return NULL; + } + if (b->data[i] == '=') { + i++; + if (i >= b->slen || b->data[i] != '=' || + bconchar(out, c0) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + /* Missing "=" at the end. */ + bdestroy(out); + return NULL; + } + return out; + } + v = base64DecodeSymbol(b->data[i]); + i++; + } while (v < 0); + c1 |= (unsigned char)(v >> 2); + c2 = (unsigned char)(v << 6); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy(out); + return NULL; + } + if (b->data[i] == '=') { + if (bconchar(out, c0) < 0 || + bconchar(out, c1) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy(out); + return NULL; + } + if (boolTruncError) { + *boolTruncError = 0; + } + return out; + } + v = base64DecodeSymbol(b->data[i]); + i++; + } while (v < 0); + c2 |= (unsigned char)(v); + if (bconchar(out, c0) < 0 || + bconchar(out, c1) < 0 || + bconchar(out, c2) < 0) { + if (boolTruncError) { + *boolTruncError = -1; + return out; + } + bdestroy(out); + return NULL; + } + } +} + +#define UU_DECODE_BYTE(b) \ + (((b) == (signed int)'`') ? 0 : (b) - (signed int)' ') + +struct bUuInOut { + bstring src, dst; + int * badlines; +}; + +#define UU_MAX_LINELEN 45 + +static int +bUuDecLine(void *parm, int ofs, int len) +{ + struct bUuInOut *io = (struct bUuInOut *)parm; + bstring s = io->src; + bstring t = io->dst; + int i, llen, otlen, ret, c0, c1, c2, c3, d0, d1, d2, d3; + if (len == 0) { + return 0; + } + llen = UU_DECODE_BYTE (s->data[ofs]); + ret = 0; + otlen = t->slen; + if (((unsigned)llen) > UU_MAX_LINELEN) { + ret = -__LINE__; + goto exit; + } + llen += t->slen; + for (i = 1; i < s->slen && t->slen < llen; i += 4) { + unsigned char outoctet[3]; + c0 = UU_DECODE_BYTE(d0 = (int)bchare(s, i+ofs+0, ' ' - 1)); + c1 = UU_DECODE_BYTE(d1 = (int)bchare(s, i+ofs+1, ' ' - 1)); + c2 = UU_DECODE_BYTE(d2 = (int)bchare(s, i+ofs+2, ' ' - 1)); + c3 = UU_DECODE_BYTE(d3 = (int)bchare(s, i+ofs+3, ' ' - 1)); + if (((unsigned)(c0|c1) >= 0x40)) { + if (!ret)ret = -__LINE__; + if (d0 > 0x60 || (d0 < (' ' - 1)&& !isspace(d0)) || + d1 > 0x60 || (d1 < (' ' - 1)&& !isspace(d1))) { + t->slen = otlen; + goto exit; + } + c0 = c1 = 0; + } + outoctet[0] = (unsigned char)((c0 << 2) | ((unsigned)c1 >> 4)); + if (t->slen+1 >= llen) { + if (0 > bconchar(t, (char)outoctet[0])) { + return -__LINE__; + } + break; + } + if ((unsigned)c2 >= 0x40) { + if (!ret) { + ret = -__LINE__; + } + if (d2 > 0x60 || (d2 < (' ' - 1) && !isspace(d2))) { + t->slen = otlen; + goto exit; + } + c2 = 0; + } + outoctet[1] = (unsigned char) ((c1 << 4) | ((unsigned) c2 >> 2)); + if (t->slen + 2 >= llen) { + if (0 > bcatblk (t, outoctet, 2)) { + return -__LINE__; + } + break; + } + if ((unsigned) c3 >= 0x40) { if (!ret) ret = -__LINE__; + if (d3 > 0x60 || (d3 < (' ' - 1) && !isspace (d3))) { + t->slen = otlen; + goto exit; + } + c3 = 0; + } + outoctet[2] = (unsigned char)((c2 << 6) | ((unsigned)c3)); + if (0 > bcatblk(t, outoctet, 3)) return -__LINE__; + } + if (t->slen < llen) { + if (0 == ret) ret = -__LINE__; + t->slen = otlen; + } +exit: + if (ret && io->badlines) { + (*io->badlines)++; + return 0; + } + return ret; +} + +bstring +bUuDecodeEx(const bstring src, int *badlines) +{ + struct bStream *s, *d; + struct tagbstring t; + bstring b; + + if (!src) { + return NULL; + } + t = *src; /* Short lifetime alias to header of src */ + s = bsFromBstrRef(&t); /* t is undefined after this */ + if (!s) { + return NULL; + } + d = bsUuDecode(s, badlines); + b = bfromcstralloc(256, ""); + if (NULL == b) { + goto error; + } + if (0 > bsread(b, d, INT_MAX)) { + goto error; + } +exit: + bsclose(d); + bsclose(s); + return b; +error: + bdestroy(b); + b = NULL; + goto exit; +} + +struct bsUuCtx { + struct bUuInOut io; + struct bStream * sInp; +}; + +static size_t +bsUuDecodePart(void *buff, size_t elsize, size_t nelem, void *parm) +{ + static struct tagbstring eol = bsStatic ("\r\n"); + struct bsUuCtx * ctx = (struct bsUuCtx *) parm; + size_t tsz; + int l, lret; + if (NULL == buff || NULL == parm) { + return 0; + } + tsz = elsize * nelem; +check: + /* If internal buffer has sufficient data, just output it */ + if (((size_t)ctx->io.dst->slen) > tsz) { + memcpy(buff, ctx->io.dst->data, tsz); + bdelete(ctx->io.dst, 0, (int)tsz); + return nelem; + } +decode: + if (0 <= (l = binchr(ctx->io.src, 0, &eol))) { + int ol = 0; + struct tagbstring t; + bstring s = ctx->io.src; + ctx->io.src = &t; + do { + if (l > ol) { + bmid2tbstr(t, s, ol, l - ol); + lret = bUuDecLine(&ctx->io, 0, t.slen); + if (0 > lret) { + ctx->io.src = s; + goto done; + } + } + ol = l + 1; + if (((size_t)ctx->io.dst->slen) > tsz) { + break; + } + l = binchr(s, ol, &eol); + } while (BSTR_ERR != l); + bdelete(s, 0, ol); + ctx->io.src = s; + goto check; + } + if (BSTR_ERR != bsreada(ctx->io.src, ctx->sInp, bsbufflength(ctx->sInp, BSTR_BS_BUFF_LENGTH_GET))) { + goto decode; + } + bUuDecLine(&ctx->io, 0, ctx->io.src->slen); +done: + /* Output any lingering data that has been translated */ + if (((size_t)ctx->io.dst->slen) > 0) { + if (((size_t)ctx->io.dst->slen) > tsz) { + goto check; + } + memcpy(buff, ctx->io.dst->data, ctx->io.dst->slen); + tsz = ctx->io.dst->slen / elsize; + ctx->io.dst->slen = 0; + if (tsz > 0) { + return tsz; + } + } + /* Deallocate once EOF becomes triggered */ + bdestroy(ctx->io.dst); + bdestroy(ctx->io.src); + free(ctx); + return 0; +} + +struct bStream * +bsUuDecode(struct bStream *sInp, int *badlines) +{ + struct bsUuCtx *ctx = (struct bsUuCtx *)malloc(sizeof(struct bsUuCtx)); + struct bStream *sOut; + if (NULL == ctx) { + return NULL; + } + ctx->io.src = bfromcstr(""); + ctx->io.dst = bfromcstr(""); + if (NULL == ctx->io.dst || NULL == ctx->io.src) { + goto error; + } + ctx->io.badlines = badlines; + if (badlines) { + *badlines = 0; + } + ctx->sInp = sInp; + sOut = bsopen((bNread) bsUuDecodePart, ctx); + if (NULL == sOut) { + goto error; + } + return sOut; +error: + bdestroy(ctx->io.dst); + bdestroy(ctx->io.src); + free(ctx); + return NULL; +} + +#define UU_ENCODE_BYTE(b) \ + ((char)(((b) == 0) ? '`' : ((b) + ' '))) + +bstring +bUuEncode(const bstring src) +{ + bstring out; + int i, j, jm; + unsigned int c0, c1, c2; + if (src == NULL || src->slen < 0 || src->data == NULL) { + return NULL; + } + if ((out = bfromcstr("")) == NULL) { + return NULL; + } + for (i = 0; i < src->slen; i += UU_MAX_LINELEN) { + if ((jm = i + UU_MAX_LINELEN) > src->slen) { + jm = src->slen; + } + if (bconchar(out, UU_ENCODE_BYTE(jm - i)) < 0) { + bstrFree(out); + break; + } + for (j = i; j < jm; j += 3) { + c0 = (unsigned int)bchar(src, j); + c1 = (unsigned int)bchar(src, j + 1); + c2 = (unsigned int)bchar(src, j + 2); + if (bconchar(out, UU_ENCODE_BYTE((c0 & 0xFC) >> 2)) < 0 || + bconchar(out, UU_ENCODE_BYTE(((c0 & 0x03) << 4) | ((c1 & 0xF0) >> 4))) < 0 || + bconchar(out, UU_ENCODE_BYTE(((c1 & 0x0F) << 2) | ((c2 & 0xC0) >> 6))) < 0 || + bconchar(out, UU_ENCODE_BYTE((c2 & 0x3F))) < 0) { + bstrFree (out); + goto exit; + } + } + if (bconchar(out, (char)'\r') < 0 || + bconchar(out, (char)'\n') < 0) { + bstrFree(out); + break; + } + } +exit: + return out; +} + +bstring +bYEncode(const bstring src) +{ + int i; + bstring out; + unsigned char c; + if (src == NULL || src->slen < 0 || src->data == NULL) { + return NULL; + } + if ((out = bfromcstr("")) == NULL) { + return NULL; + } + for (i = 0; i < src->slen; ++i) { + c = (unsigned char)(src->data[i] + 42); + if (c == '=' || c == '\0' || c == '\r' || c == '\n') { + if (0 > bconchar (out, (char) '=')) { + bdestroy (out); + return NULL; + } + c += (unsigned char)64; + } + if (0 > bconchar(out, c)) { + bdestroy(out); + return NULL; + } + } + return out; +} + +#define MAX_OB_LEN (64) + +bstring +bYDecode(const bstring src) +{ + int i, obl; + bstring out; + unsigned char c, octetbuff[MAX_OB_LEN]; + if (src == NULL || src->slen < 0 || src->data == NULL) { + return NULL; + } + if ((out = bfromcstr ("")) == NULL) { + return NULL; + } + obl = 0; + for (i = 0; i < src->slen; i++) { + if ('=' == (c = src->data[i])) { + /* The = escape mode */ + ++i; + if (i >= src->slen) { + bdestroy(out); + return NULL; + } + c = (unsigned char)(src->data[i] - 64); + } else { + if ('\0' == c) { + bdestroy(out); + return NULL; + } + /* Extraneous CR/LFs are to be ignored. */ + if (c == '\r' || c == '\n') { + continue; + } + } + octetbuff[obl] = (unsigned char)((int)c - 42); + obl++; + if (obl >= MAX_OB_LEN) { + if (0 > bcatblk(out, octetbuff, obl)) { + bdestroy(out); + return NULL; + } + obl = 0; + } + } + + if (0 > bcatblk(out, octetbuff, obl)) { + bdestroy(out); + out = NULL; + } + return out; +} + +bstring +bStrfTime(const char * fmt, const struct tm * timeptr) +{ +#if defined(__TURBOC__) && !defined(__BORLANDC__) +static struct tagbstring ns = bsStatic ("bStrfTime Not supported"); + fmt = fmt; + timeptr = timeptr; + return &ns; +#else + bstring buff; + int n; + size_t r; + if (fmt == NULL) { + return NULL; + } + /* Since the length is not determinable beforehand, a search is + * performed using the truncating "strftime" call on increasing + * potential sizes for the output result. + */ + if ((n = (int)(2 * strlen (fmt))) < 16) { + n = 16; + } + buff = bfromcstralloc(n + 2, ""); + while (1) { + if (BSTR_OK != balloc(buff, n + 2)) { + bdestroy (buff); + return NULL; + } + r = strftime((char *)buff->data, n + 1, fmt, timeptr); + if (r > 0) { + buff->slen = (int) r; + break; + } + n += n; + } + return buff; +#endif +} + +int +bSetCstrChar(bstring b, int pos, char c) +{ + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) { + return BSTR_ERR; + } + if (pos < 0 || pos > b->slen) { + return BSTR_ERR; + } + if (pos == b->slen) { + if ('\0' != c) return bconchar(b, c); + return 0; + } + b->data[pos] = (unsigned char) c; + if ('\0' == c) { + b->slen = pos; + } + return 0; +} + +int +bSetChar(bstring b, int pos, char c) +{ + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) { + return BSTR_ERR; + } + if (pos < 0 || pos > b->slen) { + return BSTR_ERR; + } + if (pos == b->slen) { + return bconchar(b, c); + } + b->data[pos] = (unsigned char)c; + return 0; +} + +#define INIT_SECURE_INPUT_LENGTH (256) + +bstring +bSecureInput(int maxlen, int termchar, bNgetc vgetchar, void *vgcCtx) +{ + size_t i, m, c; + bstring b, t; + if (!vgetchar) { + return NULL; + } + b = bfromcstralloc(INIT_SECURE_INPUT_LENGTH, ""); + if ((c = UCHAR_MAX + 1) == (size_t)termchar) { + c++; + } + for (i = 0; ; i++) { + if ((size_t)termchar == c || + (maxlen > 0 && i >= (size_t)maxlen)) { + c = EOF; + } else { + c = vgetchar (vgcCtx); + } + if ((size_t)EOF == c) { + break; + } + if (i + 1 >= (size_t)b->mlen) { + /* Double size, but deal with unusual case of numeric + * overflows + */ + if ((m = b->mlen << 1) <= (size_t)b->mlen && + (m = b->mlen + 1024) <= (size_t)b->mlen && + (m = b->mlen + 16) <= (size_t)b->mlen && + (m = b->mlen + 1) <= (size_t)b->mlen) { + t = NULL; + } else { + t = bfromcstralloc (m, ""); + } + if (t) { + memcpy(t->data, b->data, i); + } + bSecureDestroy(b); /* Cleanse previous buffer */ + b = t; + if (!b) { + return b; + } + } + b->data[i] = (unsigned char)c; + } + b->slen = i; + b->data[i] = (unsigned char)'\0'; + return b; +} + +#define BWS_BUFF_SZ (BUFSIZ) + +struct bwriteStream { + bstring buff; /* Buffer for underwrites */ + void * parm; /* The stream handle for core stream */ + bNwrite writeFn; /* fwrite work-a-like fnptr for core stream */ + int isEOF; /* track stream's EOF state */ + int minBuffSz; +}; + +struct bwriteStream * +bwsOpen(bNwrite writeFn, void *parm) +{ + struct bwriteStream * ws; + if (NULL == writeFn) { + return NULL; + } + ws = (struct bwriteStream *)malloc(sizeof(struct bwriteStream)); + if (ws) { + if (NULL == (ws->buff = bfromcstr(""))) { + free(ws); + ws = NULL; + } else { + ws->parm = parm; + ws->writeFn = writeFn; + ws->isEOF = 0; + ws->minBuffSz = BWS_BUFF_SZ; + } + } + return ws; +} + +#define internal_bwswriteout(ws,b) { \ + if ((b)->slen > 0) { \ + if (1 != (ws->writeFn ((b)->data, (b)->slen, 1, ws->parm))) { \ + ws->isEOF = 1; \ + return BSTR_ERR; \ + } \ + } \ +} + +int +bwsWriteFlush(struct bwriteStream *ws) +{ + if (NULL == ws || + ws->isEOF || + 0 >= ws->minBuffSz || + NULL == ws->writeFn || + NULL == ws->buff) { + return BSTR_ERR; + } + internal_bwswriteout(ws, ws->buff); + ws->buff->slen = 0; + return 0; +} + +int +bwsWriteBstr(struct bwriteStream *ws, const bstring b) +{ + struct tagbstring t; + int l; + if (NULL == ws || + NULL == b || + NULL == ws->buff || + ws->isEOF || + 0 >= ws->minBuffSz || + NULL == ws->writeFn) { + return BSTR_ERR; + } + /* Buffer prepacking optimization */ + if (b->slen > 0 && ws->buff->mlen - ws->buff->slen > b->slen) { + static struct tagbstring empty = bsStatic(""); + if (0 > bconcat (ws->buff, b)) { + return BSTR_ERR; + } + return bwsWriteBstr(ws, &empty); + } + if (0 > (l = ws->minBuffSz - ws->buff->slen)) { + internal_bwswriteout(ws, ws->buff); + ws->buff->slen = 0; + l = ws->minBuffSz; + } + if (b->slen < l) { + return bconcat(ws->buff, b); + } + if (0 > bcatblk (ws->buff, b->data, l)) { + return BSTR_ERR; + } + internal_bwswriteout(ws, ws->buff); + ws->buff->slen = 0; + bmid2tbstr(t, (bstring)b, l, b->slen); + if (t.slen >= ws->minBuffSz) { + internal_bwswriteout(ws, &t); + return 0; + } + return bassign(ws->buff, &t); +} + +int +bwsWriteBlk(struct bwriteStream *ws, void *blk, int len) +{ + struct tagbstring t; + if (NULL == blk || len < 0) { + return BSTR_ERR; + } + blk2tbstr(t, blk, len); + return bwsWriteBstr(ws, &t); +} + +int +bwsIsEOF(const struct bwriteStream * ws) +{ + if (NULL == ws || + NULL == ws->buff || + 0 > ws->minBuffSz || + NULL == ws->writeFn) { + return BSTR_ERR; + } + return ws->isEOF; +} + +int +bwsBuffLength(struct bwriteStream *ws, int sz) +{ + int oldSz; + if (ws == NULL || sz < 0) { + return BSTR_ERR; + } + oldSz = ws->minBuffSz; + if (sz > 0) { + ws->minBuffSz = sz; + } + return oldSz; +} + +void * +bwsClose(struct bwriteStream * ws) +{ + void *parm = NULL; + if (ws) { + if (NULL == ws->buff || + 0 >= ws->minBuffSz || + NULL == ws->writeFn) { + return NULL; + } + bwsWriteFlush(ws); + parm = ws->parm; + ws->parm = NULL; + ws->minBuffSz = -1; + ws->writeFn = NULL; + bstrFree(ws->buff); + free(ws); + } + return parm; +} diff --git a/OpenFAST/modules/map/src/bstring/bstraux.h b/OpenFAST/modules/map/src/bstring/bstraux.h new file mode 100644 index 000000000..ad793b0ba --- /dev/null +++ b/OpenFAST/modules/map/src/bstring/bstraux.h @@ -0,0 +1,417 @@ +/* Copyright 2002-2010 Paul Hsieh + * This file is part of Bstrlib. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of bstrlib nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * GNU General Public License Version 2 (the "GPL"). + */ + +/** + * \file + * \brief C example that implements trivial additional functions + * + * This file is not a necessary part of the core bstring library itself, but is + * just an auxilliary module which includes miscellaneous or trivial functions. + */ + +#ifndef BSTRAUX_H +#define BSTRAUX_H + +#include <time.h> +#include "bstrlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Safety mechanisms */ +#define bstrDeclare(b) \ + bstring(b) = NULL + +#define bstrFree(b) \ +do { \ + if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { \ + bdestroy(b); \ + (b) = NULL; \ + } \ +} while (0) + +/* Backward compatibilty with previous versions of Bstrlib */ +#define bAssign(a, b) \ + ((bassign)((a), (b))) + +#define bSubs(b, pos, len, a, c) \ + ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) + +#define bStrchr(b, c) \ + ((bstrchr)((b), (c))) + +#define bStrchrFast(b, c) \ + ((bstrchr)((b), (c))) + +#define bCatCstr(b, s) \ + ((bcatcstr)((b), (s))) + +#define bCatBlk(b, s, len) \ + ((bcatblk)((b), (s), (len))) + +#define bCatStatic(b, s) \ + bCatBlk((b), ("" s ""), sizeof (s) - 1) + +#define bTrunc(b, n) \ + ((btrunc)((b), (n))) + +#define bReplaceAll(b, find, repl, pos) \ + ((bfindreplace)((b),(find),(repl),(pos))) + +#define bUppercase(b) \ + ((btoupper)(b)) + +#define bLowercase(b) \ + ((btolower)(b)) + +#define bCaselessCmp(a, b) \ + ((bstricmp)((a), (b))) + +#define bCaselessNCmp(a, b, n) \ + ((bstrnicmp)((a), (b), (n))) + +#define bBase64Decode(b) \ + (bBase64DecodeEx((b), NULL)) + +#define bUuDecode(b) \ + (bUuDecodeEx((b), NULL)) + +/* Unusual functions */ + +/** + * Create a bStream whose contents are a copy of the bstring passed in. + * + * This allows the use of all the bStream APIs with bstrings. + */ +BSTR_PUBLIC struct bStream * +bsFromBstr(const bstring b); + +/** + * Return with a string of the last n characters of b. + */ +BSTR_PUBLIC bstring +bTail(bstring b, int n); + +/** + * Return with a string of the first n characters of b. + */ +BSTR_PUBLIC bstring +bHead(bstring b, int n); + +/** + * Sets the character at position pos to the character c in the bstring a. + * + * If the character c is NUL ('\0') then the string is truncated at this point. + * Note: this does not enable any other '\0' character in the bstring as + * terminator indicator for the string. pos must be in the position between 0 + * and b->slen inclusive, otherwise BSTR_ERR will be returned. + */ +BSTR_PUBLIC int +bSetCstrChar(bstring a, int pos, char c); + +/** + * Sets the character at position pos to the character c in the bstring a. + * + * The string is not truncated if the character c is NUL ('\0'). pos must be in + * the position between 0 and b->slen inclusive, otherwise BSTR_ERR will be + * returned. + */ +BSTR_PUBLIC int +bSetChar(bstring b, int pos, char c); + +/** + * Fill a given bstring with the character in parameter c, for a length n. + */ +BSTR_PUBLIC int +bFill(bstring a, char c, int len); + +/** + * Replicate the contents of b end to end n times and replace it in b. + */ +BSTR_PUBLIC int +bReplicate(bstring b, int n); + +/** + * Reverse the contents of b in place. + */ +BSTR_PUBLIC int +bReverse(bstring b); + +/** + * Insert a repeated sequence of a given character into the string at position + * pos for a length len. + */ +BSTR_PUBLIC int +bInsertChrs(bstring b, int pos, int len, unsigned char c, unsigned char fill); + +/** + * Takes a format string that is compatible with strftime and a struct tm + * pointer, formats the time according to the format string and outputs the + * bstring as a result. + * + * Note that if there is an early generation of a '\0' character, the bstring + * will be truncated to this end point. + */ +BSTR_PUBLIC bstring +bStrfTime(const char * fmt, const struct tm * timeptr); + +#define bAscTime(t) (bStrfTime ("%c\n", (t))) + +#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL) + +/* Spacing formatting */ + +/** + * Left justify a string. + */ +BSTR_PUBLIC int +bJustifyLeft(bstring b, int space); + +/** + * Right justify a string to within a given width. + */ +BSTR_PUBLIC int +bJustifyRight(bstring b, int width, int space); + +/** + * Stretch a string to flush against left and right margins by evenly + * distributing additional white space between words. + * + * If the line is too long to be margin justified, it is left justified. + */ +BSTR_PUBLIC int +bJustifyMargin(bstring b, int width, int space); + +/** + * Center a string's non-white space characters to within a given width by + * inserting whitespaces at the beginning. + */ +BSTR_PUBLIC int +bJustifyCenter(bstring b, int width, int space); + +/* Esoteric standards specific functions */ + +/** + * Convert a bstring to a netstring. + * + * See http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * + * Note: 1) The value returned should be freed with a call to bcstrfree() at + * the point when it will no longer be referenced to avoid a memory + * leak. + * 2) If the returned value is non-NULL, then it also '\0' terminated + * in the character position one past the "," terminator. + */ +BSTR_PUBLIC char * +bStr2NetStr(const bstring b); + +/** + * Convert a netstring to a bstring. + * + * See http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * + * Note that the terminating "," *must* be present, however a following '\0' + * is *not* required. + */ +BSTR_PUBLIC bstring +bNetStr2Bstr(const char *buf); + +/** + * Generate a base64 encoding. + * + * See: RFC1341 + */ +BSTR_PUBLIC bstring +bBase64Encode(const bstring b); + +/** + * Decode a base64 block of data. + * + * All MIME headers are assumed to have been removed. + * + * See: RFC1341 + */ +BSTR_PUBLIC bstring +bBase64DecodeEx(const bstring b, int *boolTruncError); + +/** + * Creates a bStream which performs the UUDecode of an an input stream. + * + * If there are errors in the decoding, they are counted up and returned in + * "badlines", if badlines is not NULL. It is assumed that the "begin" and + * "end" lines have already been stripped off. The potential security problem + * of writing the filename in the begin line is something that is beyond the + * scope of a portable library. + */ +BSTR_PUBLIC struct bStream * +bsUuDecode(struct bStream *sInp, int *badlines); + +/** + * Performs a UUDecode of a block of data. + * + * If there are errors in the decoding, they are counted up and returned in + * "badlines", if badlines is not NULL. It is assumed that the "begin" and + * "end" lines have already been stripped off. The potential security problem + * of writing the filename in the begin line is something that is beyond the + * scope of a portable library. + */ + +BSTR_PUBLIC bstring +bUuDecodeEx(const bstring src, int *badlines); + +/** + * Performs a UUEncode of a block of data. + * + * The "begin" and "end" lines are not appended. + */ +BSTR_PUBLIC bstring +bUuEncode(const bstring src); + +/** + * Performs a YEncode of a block of data. + * + * No header or tail info is appended. + * + * See: http://www.yenc.org/whatis.htm, http://www.yenc.org/yenc-draft.1.3.txt + */ +BSTR_PUBLIC bstring +bYEncode(const bstring src); + +/** + * Performs a YDecode of a block of data. + * + * See: http://www.yenc.org/whatis.htm, http://www.yenc.org/yenc-draft.1.3.txt + */ +BSTR_PUBLIC bstring +bYDecode(const bstring src); + +/* Writable stream */ +typedef int +(*bNwrite)(const void *buf, size_t elsize, size_t nelem, void *parm); + +/** + * Wrap a given open stream (described by a fwrite work-a-like function pointer + * and stream handle) into an open bwriteStream suitable for write streaming + * functions. + */ +BSTR_PUBLIC struct bwriteStream * +bwsOpen(bNwrite writeFn, void *parm); + +/** + * Send a bstring to a bwriteStream. + * + * If the stream is at EOF BSTR_ERR is returned. Note that there is no + * deterministic way to determine the exact cut off point where the core stream + * stopped accepting data. + */ +BSTR_PUBLIC int +bwsWriteBstr(struct bwriteStream *stream, const bstring b); + +/** + * Send a block of data a bwriteStream. + * + * If the stream is at EOF BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bwsWriteBlk(struct bwriteStream *stream, void *blk, int len); + +/** + * Force any pending data to be written to the core stream. + */ +BSTR_PUBLIC int +bwsWriteFlush(struct bwriteStream *stream); + +/** + * Returns 0 if the stream is currently writable, 1 if the core stream has + * responded by not accepting the previous attempted write. + */ +BSTR_PUBLIC int +bwsIsEOF(const struct bwriteStream *stream); + +/** + * Set the length of the buffer used by the bwsStream. + * + * If sz is zero, the length is not set. This function returns with the + * previous length. + */ +BSTR_PUBLIC int +bwsBuffLength(struct bwriteStream *stream, int sz); + +/** + * Close the bwriteStream, and return the handle to the stream that was + * originally used to open the given stream. + * + * Note that even if the stream is at EOF it still needs to be closed with a + * call to bwsClose. + */ +BSTR_PUBLIC void * +bwsClose(struct bwriteStream *stream); + +/* Security functions */ +#define bSecureDestroy(b) \ +do { \ + if ((b) && (b)->mlen > 0 && (b)->data) { \ + (void)memset((b)->data, 0, (size_t)(b)->mlen); \ + (void)bdestroy((b)); \ + } \ +} while (0) + +#define bSecureWriteProtect(t) \ +do { \ + if ((t).mlen >= 0) { \ + if ((t).mlen > (t).slen)) { \ + (void)memset((t).data + (t).slen, 0, \ + (size_t)(t).mlen - (t).slen); \ + } \ + (t).mlen = -1; \ + } \ +} while (0) + +/** + * Read input from an abstracted input interface, for a length of at most + * maxlen characters. + * + * If maxlen <= 0, then there is no length limit put on the input. The result + * is terminated early if vgetchar() return EOF or the user specified value + * termchar. + * + */ +BSTR_PUBLIC bstring +bSecureInput(int maxlen, int termchar, bNgetc vgetchar, void *vgcCtx); + +#ifdef __cplusplus +} +#endif + +#endif /* BSTRAUX_H */ diff --git a/OpenFAST/modules/map/src/bstring/bstrlib.c b/OpenFAST/modules/map/src/bstring/bstrlib.c new file mode 100644 index 000000000..3dde95324 --- /dev/null +++ b/OpenFAST/modules/map/src/bstring/bstrlib.c @@ -0,0 +1,2951 @@ +/* Copyright 2002-2010 Paul Hsieh + * This file is part of Bstrlib. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of bstrlib nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * GNU General Public License Version 2 (the "GPL"). + */ + +/* + * This file is the core module for implementing the bstring functions. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined (_MSC_VER) +/* These warnings from MSVC++ are totally pointless. */ +# define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "bstrlib.h" + +/* Just a length safe wrapper for memmove. */ + +#define bBlockCopy(D, S, L) \ +do { \ + if ((L) > 0) { \ + memmove((D), (S), (L)); \ + } \ +} while (0); + +/** + * Compute the snapped size for a given requested size. + * + * By snapping to powers of 2 like this, repeated reallocations are avoided. + * */ +static int +snapUpSize(int i) { + if (i < 8) { + i = 8; + } else { + unsigned int j; + j = (unsigned int)i; + j |= (j >> 1); + j |= (j >> 2); + j |= (j >> 4); + j |= (j >> 8); /* Ok, since int >= 16 bits */ +#if (UINT_MAX != 0xffff) + j |= (j >> 16); /* For 32 bit int systems */ +#if (UINT_MAX > 0xffffffffUL) + j |= (j >> 32); /* For 64 bit int systems */ +#endif +#endif + /* Least power of two greater than i */ + j++; + if ((int)j >= i) { + i = (int)j; + } + } + return i; +} + +int +balloc(bstring b, int olen) +{ + int len; + if (b == NULL || b->data == NULL || + b->slen < 0 || b->mlen <= 0 || + b->mlen < b->slen || olen <= 0) { + return BSTR_ERR; + } + if (olen >= b->mlen) { + unsigned char *x; + if ((len = snapUpSize(olen)) <= b->mlen) { + return BSTR_OK; + } + /* Assume probability of a non-moving realloc is 0.125 */ + if (7 * b->mlen < 8 * b->slen) { + /* If slen is close to mlen in size then use realloc + * to reduce the memory defragmentation + */ +retry: + x = realloc(b->data, len); + if (x == NULL) { + /* Since we failed, try mallocating the tighest + * possible mallocation + */ + len = olen; + x = realloc(b->data, len); + if (!x) { + return BSTR_ERR; + } + } + } else { + /* If slen is not close to mlen then avoid the penalty + * of copying the extra bytes that are mallocated, but + * not considered part of the string + */ + x = malloc(len); + if (!x) { + /* Perhaps there is no available memory for the + * two mallocations to be in memory at once + */ + goto retry; + } else { + if (b->slen) { + memcpy(x, b->data, b->slen); + } + free(b->data); + } + } + b->data = x; + b->mlen = len; + b->data[b->slen] = (unsigned char)'\0'; + } + return BSTR_OK; +} + +int +ballocmin(bstring b, int len) +{ + unsigned char *s; + if (b == NULL || b->data == NULL || + (b->slen + 1) < 0 || b->mlen <= 0 || + b->mlen < b->slen || len <= 0) { + return BSTR_ERR; + } + if (len < b->slen + 1) { + len = b->slen + 1; + } + if (len != b->mlen) { + s = realloc(b->data, (size_t)len); + if (NULL == s) { + return BSTR_ERR; + } + s[b->slen] = (unsigned char)'\0'; + b->data = s; + b->mlen = len; + } + + return BSTR_OK; +} + +bstring +bfromcstr(const char *str) +{ + bstring b; + int i; + size_t j; + if (str == NULL) { + return NULL; + } + j = strlen(str); + i = snapUpSize((int)(j + (2 - (j != 0)))); + if (i <= (int)j) { + return NULL; + } + b = malloc(sizeof(struct tagbstring)); + if (!b) { + return NULL; + } + b->slen = (int)j; + b->mlen = i; + b->data = malloc(b->mlen); + if (!b->data) { + free (b); + return NULL; + } + memcpy(b->data, str, j + 1); + return b; +} + +bstring +bfromcstralloc(int mlen, const char *str) +{ + bstring b; + int i; + size_t j; + if (str == NULL) { + return NULL; + } + j = strlen(str); + i = snapUpSize((int)(j + (2 - (j != 0)))); + if (i <= (int) j) { + return NULL; + } + b = malloc(sizeof(struct tagbstring)); + if (b == NULL) { + return NULL; + } + b->slen = (int)j; + if (i < mlen) { + i = mlen; + } + b->mlen = i; + b->data = malloc(b->mlen); + if (!b->data) { + free(b); + return NULL; + } + memcpy(b->data, str, j + 1); + return b; +} + +bstring +blk2bstr(const void *blk, int len) +{ + bstring b; + int i; + if (blk == NULL || len < 0) { + return NULL; + } + b = malloc(sizeof(struct tagbstring)); + if (b == NULL) { + return NULL; + } + b->slen = len; + i = len + (2 - (len != 0)); + i = snapUpSize(i); + b->mlen = i; + b->data = malloc(b->mlen); + if (!b->data) { + free(b); + return NULL; + } + if (len > 0) { + memcpy(b->data, blk, len); + } + b->data[len] = (unsigned char)'\0'; + return b; +} + +char * +bstr2cstr(const bstring b, char z) +{ + int i, l; + char *r; + if (!b || b->slen < 0 || !b->data) { + return NULL; + } + l = b->slen; + r = malloc((size_t)(l + 1)); + if (r == NULL) { + return r; + } + for (i = 0; i < l; i ++) { + r[i] = (char)((b->data[i] == '\0') ? z : (char)(b->data[i])); + } + r[l] = (unsigned char)'\0'; + return r; +} + +int +bcstrfree(char *s) +{ + free(s); + return BSTR_OK; +} + +int +bconcat(bstring b0, const bstring b1) +{ + int len, d; + bstring aux = b1; + if (!b0 || !b1 || !b0->data || !b1->data) { + return BSTR_ERR; + } + d = b0->slen; + len = b1->slen; + if ((d | (b0->mlen - d) | len | (d + len)) < 0) { + return BSTR_ERR; + } + if (b0->mlen <= d + len + 1) { + ptrdiff_t pd = b1->data - b0->data; + if (0 <= pd && pd < b0->mlen) { + aux = bstrcpy(b1); + if (!aux) { + return BSTR_ERR; + } + } + if (balloc(b0, d + len + 1) != BSTR_OK) { + if (aux != b1) { + bdestroy(aux); + } + return BSTR_ERR; + } + } + bBlockCopy(&b0->data[d], &aux->data[0], len); + b0->data[d + len] = (unsigned char)'\0'; + b0->slen = d + len; + if (aux != b1) { + bdestroy(aux); + } + return BSTR_OK; +} + +int +bconchar(bstring b, char c) +{ + int d; + if (!b) { + return BSTR_ERR; + } + d = b->slen; + if ((d | (b->mlen - d)) < 0 || balloc(b, d + 2) != BSTR_OK) { + return BSTR_ERR; + } + b->data[d] = (unsigned char)c; + b->data[d + 1] = (unsigned char)'\0'; + b->slen++; + return BSTR_OK; +} + +int +bcatcstr(bstring b, const char *s) +{ + char *d; + int i, l; + if (b == NULL || b->data == NULL || + b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL) { + return BSTR_ERR; + } + /* Optimistically concatenate directly */ + l = b->mlen - b->slen; + d = (char *)&b->data[b->slen]; + for (i = 0; i < l; ++i) { + if ((*d++ = *s++) == '\0') { + b->slen += i; + return BSTR_OK; + } + } + b->slen += i; + /* Need to explicitely resize and concatenate tail */ + return bcatblk(b, s, strlen(s)); +} + +int +bcatblk(bstring b, const void *s, int len) +{ + int nl; + if (!b || !b->data || + b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || !s || len < 0) { + return BSTR_ERR; + } + if (0 > (nl = b->slen + len)) { + /* Overflow? */ + return BSTR_ERR; + } + if (b->mlen <= nl && 0 > balloc(b, nl + 1)) { + return BSTR_ERR; + } + bBlockCopy(&b->data[b->slen], s, len); + b->slen = nl; + b->data[nl] = (unsigned char)'\0'; + return BSTR_OK; +} + +bstring +bstrcpy(const bstring b) +{ + bstring b0; + int i, j; + /* Attempted to copy an invalid string? */ + if (!b || b->slen < 0 || !b->data) { + return NULL; + } + b0 = malloc(sizeof(struct tagbstring)); + if (!b0) { + /* Unable to mallocate memory for string header */ + return NULL; + } + i = b->slen; + j = snapUpSize(i + 1); + b0->data = malloc(j); + if (b0->data == NULL) { + j = i + 1; + b0->data = (unsigned char *)malloc(j); + if (b0->data == NULL) { + /* Unable to mallocate memory for string data */ + free(b0); + return NULL; + } + } + b0->mlen = j; + b0->slen = i; + if (i) { + memcpy(b0->data, b->data, i); + } + b0->data[b0->slen] = (unsigned char)'\0'; + return b0; +} + +int +bassign(bstring a, const bstring b) +{ + if (!b || !b->data || b->slen < 0) { + return BSTR_ERR; + } + if (b->slen != 0) { + if (balloc(a, b->slen) != BSTR_OK) { + return BSTR_ERR; + } + memmove(a->data, b->data, b->slen); + } else { + if (!a || !a->data || + a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) { + return BSTR_ERR; + } + } + a->data[b->slen] = (unsigned char)'\0'; + a->slen = b->slen; + return BSTR_OK; +} + +int +bassignmidstr(bstring a, const bstring b, int left, int len) +{ + if (!b || !b->data || b->slen < 0) { + return BSTR_ERR; + } + if (left < 0) { + len += left; + left = 0; + } + if (len > b->slen - left) { + len = b->slen - left; + } + if (!a || !a->data || + a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) { + return BSTR_ERR; + } + if (len > 0) { + if (balloc(a, len) != BSTR_OK) { + return BSTR_ERR; + } + memmove(a->data, b->data + left, len); + a->slen = len; + } else { + a->slen = 0; + } + a->data[a->slen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +bassigncstr(bstring a, const char *str) +{ + int i; + size_t len; + if (!a || !a->data || + a->mlen < a->slen || a->slen < 0 || + a->mlen == 0 || !str) { + return BSTR_ERR; + } + for (i = 0; i < a->mlen; ++i) { + if ('\0' == (a->data[i] = str[i])) { + a->slen = i; + return BSTR_OK; + } + } + a->slen = i; + len = strlen(str + i); + if (len > INT_MAX || i + len + 1 > INT_MAX || + 0 > balloc(a, (int)(i + len + 1))) { + return BSTR_ERR; + } + bBlockCopy(a->data + i, str + i, (size_t)len + 1); + a->slen += (int)len; + return BSTR_OK; +} + +int +bassignblk(bstring a, const void *s, int len) +{ + if (!a || !a->data || + a->mlen < a->slen || a->slen < 0 || + a->mlen == 0 || !s || + len + 1 < 1) { + return BSTR_ERR; + } + if (len + 1 > a->mlen && 0 > balloc(a, len + 1)) { + return BSTR_ERR; + } + bBlockCopy(a->data, s, len); + a->data[len] = (unsigned char)'\0'; + a->slen = len; + return BSTR_OK; +} + +int +btrunc(bstring b, int n) +{ + if (n < 0 || !b || + !b->data || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) { + return BSTR_ERR; + } + if (b->slen > n) { + b->slen = n; + b->data[n] = (unsigned char)'\0'; + } + return BSTR_OK; +} + +#define upcase(c) \ + (toupper((unsigned char)c)) + +#define downcase(c) \ + (tolower((unsigned char)c)) + +#define wspace(c) \ + (isspace((unsigned char)c)) + +int +btoupper(bstring b) +{ + int i, len; + if (b == NULL || b->data == NULL || + b->mlen < b->slen || b->slen < 0 || + b->mlen <= 0) { + return BSTR_ERR; + } + for (i = 0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char)upcase(b->data[i]); + } + return BSTR_OK; +} + +int +btolower(bstring b) +{ + int i, len; + if (b == NULL || b->data == NULL || + b->mlen < b->slen || b->slen < 0 || + b->mlen <= 0) { + return BSTR_ERR; + } + for (i = 0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char)downcase(b->data[i]); + } + return BSTR_OK; +} + +int +bstricmp(const bstring b0, const bstring b1) +{ + int i, v, n; + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) { + return SHRT_MIN; + } + if ((n = b0->slen) > b1->slen) { + n = b1->slen; + } else if (b0->slen == b1->slen && b0->data == b1->data) { + return BSTR_OK; + } + for (i = 0; i < n; i ++) { + v = (char)downcase(b0->data[i]) - (char)downcase(b1->data[i]); + if (0 != v) { + return v; + } + } + if (b0->slen > n) { + v = (char)downcase(b0->data[n]); + if (v) { + return v; + } + return UCHAR_MAX + 1; + } + if (b1->slen > n) { + v = - (char)downcase(b1->data[n]); + if (v) { + return v; + } + return -(int)(UCHAR_MAX + 1); + } + return BSTR_OK; +} + +int +bstrnicmp(const bstring b0, const bstring b1, int n) +{ + int i, v, m; + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0 || + n < 0) { + return SHRT_MIN; + } + m = n; + if (m > b0->slen) { + m = b0->slen; + } + if (m > b1->slen) { + m = b1->slen; + } + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = (char)downcase(b0->data[i]); + v -= (char)downcase(b1->data[i]); + if (v != 0) { + return b0->data[i] - b1->data[i]; + } + } + } + if (n == m || b0->slen == b1->slen) { + return BSTR_OK; + } + if (b0->slen > m) { + v = (char)downcase(b0->data[m]); + if (v) { + return v; + } + return UCHAR_MAX + 1; + } + v = - (char)downcase(b1->data[m]); + if (v) { + return v; + } + return -(int)(UCHAR_MAX + 1); +} + +int +biseqcaseless(const bstring b0, const bstring b1) +{ + int i, n; + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) { + return BSTR_ERR; + } + if (b0->slen != b1->slen) { + return BSTR_OK; + } + if (b0->data == b1->data || b0->slen == 0) { + return 1; + } + for (i = 0, n = b0->slen; i < n; i++) { + if (b0->data[i] != b1->data[i]) { + unsigned char c = (unsigned char)downcase(b0->data[i]); + if (c != (unsigned char)downcase(b1->data[i])) { + return 0; + } + } + } + return 1; +} + +int +bisstemeqcaselessblk(const bstring b0, const void *blk, int len) +{ + int i; + if (bdata(b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) { + return BSTR_ERR; + } + if (b0->slen < len) { + return BSTR_OK; + } + if (b0->data == (const unsigned char *)blk || len == 0) { + return 1; + } + for (i = 0; i < len; i++) { + if (b0->data[i] != ((const unsigned char *)blk)[i]) { + if (downcase(b0->data[i]) != + downcase(((const unsigned char *)blk)[i])) { + return 0; + } + } + } + return 1; +} + +int +bltrimws(bstring b) +{ + int i, len; + if (!b || !b->data || + b->mlen < b->slen || b->slen < 0 || + b->mlen <= 0) { + return BSTR_ERR; + } + for (len = b->slen, i = 0; i < len; i++) { + if (!wspace(b->data[i])) { + return bdelete(b, 0, i); + } + } + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +int +brtrimws(bstring b) +{ + int i; + if (b == NULL || + b->data == NULL || + b->mlen < b->slen || + b->slen < 0 || + b->mlen <= 0) { + return BSTR_ERR; + } + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace(b->data[i])) { + if (b->mlen > i) { + b->data[i + 1] = (unsigned char)'\0'; + } + b->slen = i + 1; + return BSTR_OK; + } + } + b->data[0] = (unsigned char)'\0'; + b->slen = 0; + return BSTR_OK; +} + +int +btrimws(bstring b) +{ + int i, j; + if (b == NULL || + b->data == NULL || + b->mlen < b->slen || + b->slen < 0 || + b->mlen <= 0) { + return BSTR_ERR; + } + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace(b->data[i])) { + if (b->mlen > i) { + b->data[i + 1] = (unsigned char)'\0'; + } + b->slen = i + 1; + for (j = 0; wspace (b->data[j]); j++) + ; + return bdelete(b, 0, j); + } + } + b->data[0] = (unsigned char)'\0'; + b->slen = 0; + return BSTR_OK; +} + +int +biseq(const bstring b0, const bstring b1) +{ + if (!b0 || !b1 || + !b0->data || !b1->data || + b0->slen < 0 || b1->slen < 0) { + return BSTR_ERR; + } + if (b0->slen != b1->slen) { + return BSTR_OK; + } + if (b0->data == b1->data || b0->slen == 0) { + return 1; + } + return !memcmp(b0->data, b1->data, b0->slen); +} + +int +bisstemeqblk(const bstring b0, const void *blk, int len) +{ + int i; + if (!bdata(b0) || b0->slen < 0 || !blk || len < 0) { + return BSTR_ERR; + } + if (b0->slen < len) { + return BSTR_OK; + } + if (b0->data == (const unsigned char *)blk || len == 0) { + return 1; + } + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *)blk)[i]) { + return BSTR_OK; + } + } + return 1; +} + +int +biseqcstr(const bstring b, const char *s) +{ + int i; + if (!b || !s || !b->data || b->slen < 0) { + return BSTR_ERR; + } + for (i = 0; i < b->slen; i++) { + if (s[i] == '\0' || b->data[i] != (unsigned char)s[i]) { + return BSTR_OK; + } + } + return s[i] == '\0'; +} + +int +biseqcstrcaseless(const bstring b, const char *s) +{ + int i; + if (!b || !s || !b->data || b->slen < 0) { + return BSTR_ERR; + } + for (i = 0; i < b->slen; i++) { + if (s[i] == '\0' || (b->data[i] != (unsigned char)s[i] && + downcase(b->data[i]) != (unsigned char)downcase(s[i]))) { + return BSTR_OK; + } + } + return s[i] == '\0'; +} + +int +bstrcmp(const bstring b0, const bstring b1) +{ + int i, v, n; + if (!b0 || !b1 || !b0->data || !b1->data || + b0->slen < 0 || b1->slen < 0) { + return SHRT_MIN; + } + n = b0->slen; + if (n > b1->slen) { + n = b1->slen; + } + if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) { + return BSTR_OK; + } + for (i = 0; i < n; i ++) { + v = ((char)b0->data[i]) - ((char)b1->data[i]); + if (v != 0) { + return v; + } + if (b0->data[i] == (unsigned char)'\0') { + return BSTR_OK; + } + } + if (b0->slen > n) { + return 1; + } + if (b1->slen > n) { + return -1; + } + return BSTR_OK; +} + +int +bstrncmp(const bstring b0, const bstring b1, int n) +{ + int i, v, m; + if (!b0 || !b1 || !b0->data || !b1->data || + b0->slen < 0 || b1->slen < 0) { + return SHRT_MIN; + } + m = n; + if (m > b0->slen) { + m = b0->slen; + } + if (m > b1->slen) { + m = b1->slen; + } + if (b0->data != b1->data) { + for (i = 0; i < m; i++) { + v = ((char)b0->data[i]) - ((char)b1->data[i]); + if (v != 0) { + return v; + } + if (b0->data[i] == (unsigned char)'\0') { + return BSTR_OK; + } + } + } + if (n == m || b0->slen == b1->slen) { + return BSTR_OK; + } + if (b0->slen > m) { + return 1; + } + return -1; +} + +bstring +bmidstr(const bstring b, int left, int len) +{ + if (b == NULL || b->slen < 0 || b->data == NULL) { + return NULL; + } + if (left < 0) { + len += left; + left = 0; + } + if (len > b->slen - left) { + len = b->slen - left; + } + if (len <= 0) { + return bfromcstr(""); + } + return blk2bstr(b->data + left, len); +} + +int +bdelete(bstring b, int pos, int len) +{ + /* Clamp to left side of bstring */ + if (pos < 0) { + len += pos; + pos = 0; + } + if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || + b->mlen < b->slen || b->mlen <= 0) { + return BSTR_ERR; + } + if (len > 0 && pos < b->slen) { + if (pos + len >= b->slen) { + b->slen = pos; + } else { + bBlockCopy((char *)(b->data + pos), + (char *)(b->data + pos + len), + b->slen - (pos+len)); + b->slen -= len; + } + b->data[b->slen] = (unsigned char)'\0'; + } + return BSTR_OK; +} + +int +bdestroy(bstring b) +{ + if (b == NULL || b->slen < 0 || + b->mlen <= 0 || b->mlen < b->slen || + b->data == NULL) { + return BSTR_ERR; + } + free(b->data); + /* In case there is any stale usage, there is one more chance to + * notice this error. + */ + b->slen = -1; + b->mlen = -__LINE__; + b->data = NULL; + free(b); + return BSTR_OK; +} + +int +binstr(const bstring b1, int pos, const bstring b2) +{ + int j, ii, ll, lf; + unsigned char *d0; + unsigned char c0; + register unsigned char *d1; + register unsigned char c1; + register int i; + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) { + return BSTR_ERR; + } + if (b1->slen == pos) { + return (b2->slen == 0) ? pos : BSTR_ERR; + } + if (b1->slen < pos || pos < 0) { + return BSTR_ERR; + } + if (b2->slen == 0) { + return pos; + } + /* No space to find such a string? */ + if ((lf = b1->slen - b2->slen + 1) <= pos) { + return BSTR_ERR; + } + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) { + return 0; + } + i = pos; + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + /* Peel off the b2->slen == 1 case */ + c0 = d0[0]; + if (1 == ll) { + for (; i < lf; i++) { + if (c0 == d1[i]) { + return i; + } + } + return BSTR_ERR; + } + c1 = c0; + j = 0; + lf = b1->slen - 1; + ii = -1; + if (i < lf) { + do { + /* Unrolled current character test */ + if (c1 != d1[i]) { + if (c1 != d1[1+i]) { + i += 2; + continue; + } + i++; + } + /* Take note if this is the start of a potential + * match + */ + if (0 == j) { + ii = i; + } + /* Shift the test character down by one */ + j++; + i++; + /* If this isn't past the last character continue */ + if (j < ll) { + c1 = d0[j]; + continue; + } +N0: + /* If no characters mismatched, then we matched */ + if (i == ii + j) { + return ii; + } + /* Shift back to the beginning */ + i -= j; + j = 0; + c1 = c0; + } while (i < lf); + } + /* Deal with last case if unrolling caused a misalignment */ + if (i == lf && ll == j + 1 && c1 == d1[i]) { + goto N0; + } + return BSTR_ERR; +} + +int +binstrr(const bstring b1, int pos, const bstring b2) +{ + int j, i, l; + unsigned char *d0, *d1; + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) { + return BSTR_ERR; + } + if (b1->slen == pos && b2->slen == 0) { + return pos; + } + if (b1->slen < pos || pos < 0) { + return BSTR_ERR; + } + if (b2->slen == 0) { + return pos; + } + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) { + return 0; + } + i = pos; + if ((l = b1->slen - b2->slen) < 0) { + return BSTR_ERR; + } + /* If no space to find such a string then snap back */ + if (l + 1 <= i) { + i = l; + } + j = 0; + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + while (1) { + if (d0[j] == d1[i + j]) { + j++; + if (j >= l) { + return i; + } + } else { + i--; + if (i < 0) { + break; + } + j = 0; + } + } + return BSTR_ERR; +} + +int +binstrcaseless(const bstring b1, int pos, const bstring b2) +{ + int j, i, l, ll; + unsigned char *d0, *d1; + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) { + return BSTR_ERR; + } + if (b1->slen == pos) { + return (b2->slen == 0) ? pos : BSTR_ERR; + } + if (b1->slen < pos || pos < 0) { + return BSTR_ERR; + } + if (b2->slen == 0) { + return pos; + } + l = b1->slen - b2->slen + 1; + /* No space to find such a string? */ + if (l <= pos) { + return BSTR_ERR; + } + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) { + return BSTR_OK; + } + i = pos; + j = 0; + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + while (1) { + if (d0[j] == d1[i + j] || + downcase(d0[j]) == downcase (d1[i + j])) { + j++; + if (j >= ll) { + return i; + } + } else { + i ++; + if (i >= l) { + break; + } + j = 0; + } + } + return BSTR_ERR; +} + +int +binstrrcaseless(const bstring b1, int pos, const bstring b2) +{ + int j, i, l; + unsigned char *d0, *d1; + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) { + return BSTR_ERR; + } + if (b1->slen == pos && b2->slen == 0) { + return pos; + } + if (b1->slen < pos || pos < 0) { + return BSTR_ERR; + } + if (b2->slen == 0) { + return pos; + } + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) { + return BSTR_OK; + } + i = pos; + if ((l = b1->slen - b2->slen) < 0) { + return BSTR_ERR; + } + /* If no space to find such a string then snap back */ + if (l + 1 <= i) { + i = l; + } + j = 0; + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + while (1) { + if (d0[j] == d1[i + j] || + downcase (d0[j]) == downcase(d1[i + j])){ + j++; + if (j >= l) { + return i; + } + } else { + i--; + if (i < 0) { + break; + } + j = 0; + } + } + return BSTR_ERR; +} + +int +bstrchrp(const bstring b, int c, int pos) +{ + unsigned char *p; + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) { + return BSTR_ERR; + } + p = (unsigned char *)memchr((b->data + pos), (unsigned char)c, + (b->slen - pos)); + if (p) { + return (int)(p - b->data); + } + return BSTR_ERR; +} + +int +bstrrchrp(const bstring b, int c, int pos) +{ + int i; + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) { + return BSTR_ERR; + } + for (i = pos; i >= 0; i--) { + if (b->data[i] == (unsigned char)c) { + return i; + } + } + return BSTR_ERR; +} + +#ifndef BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF +#define LONG_LOG_BITS_QTY (3) +#define LONG_BITS_QTY \ + (1 << LONG_LOG_BITS_QTY) +#define LONG_TYPE unsigned char +#define CFCLEN \ + ((1 << CHAR_BIT) / LONG_BITS_QTY) +struct charField { + LONG_TYPE content[CFCLEN]; +}; +#define testInCharField(cf, c) \ + ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) +#define setInCharField(cf, idx) \ +do { \ + unsigned int c = (unsigned int)(idx); \ + (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE)(1ul << (c & (LONG_BITS_QTY-1))); \ +} while (0) +#else /* BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF */ +#define CFCLEN \ + (1 << CHAR_BIT) +struct charField { + unsigned char content[CFCLEN]; +}; +#define testInCharField(cf, c) \ + ((cf)->content[(unsigned char) (c)]) +#define setInCharField(cf, idx) \ + (cf)->content[(unsigned int) (idx)] = ~0 +#endif /* BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF */ + +/* Convert a bstring to charField */ +static int +buildCharField(struct charField *cf, const bstring b) +{ + int i; + if (b == NULL || b->data == NULL || b->slen <= 0) { + return BSTR_ERR; + } + memset((void *)cf->content, 0, sizeof(struct charField)); + for (i = 0; i < b->slen; i++) { + setInCharField(cf, b->data[i]); + } + return BSTR_OK; +} + +static void +invertCharField (struct charField *cf) +{ + int i; + for (i = 0; i < CFCLEN; i++) { + cf->content[i] = ~cf->content[i]; + } +} + +/* Inner engine for binchr */ +static int +binchrCF(const unsigned char *data, int len, int pos, + const struct charField *cf) +{ + int i; + for (i = pos; i < len; i++) { + unsigned char c = (unsigned char)data[i]; + if (testInCharField(cf, c)) { + return i; + } + } + return BSTR_ERR; +} + +int +binchr(const bstring b0, int pos, const bstring b1) +{ + struct charField chrs; + if (pos < 0 || b0 == NULL || + b0->data == NULL || b0->slen <= pos) { + return BSTR_ERR; + } + if (1 == b1->slen) { + return bstrchrp(b0, b1->data[0], pos); + } + if (0 > buildCharField (&chrs, b1)) { + return BSTR_ERR; + } + return binchrCF(b0->data, b0->slen, pos, &chrs); +} + +/* Inner engine for binchrr */ +static int +binchrrCF(const unsigned char *data, int pos, const struct charField *cf) +{ + int i; + for (i = pos; i >= 0; i--) { + unsigned int c = (unsigned int)data[i]; + if (testInCharField(cf, c)) { + return i; + } + } + return BSTR_ERR; +} + +int +binchrr(const bstring b0, int pos, const bstring b1) +{ + struct charField chrs; + if (pos < 0 || b0 == NULL || + b0->data == NULL || b1 == NULL || + b0->slen < pos) { + return BSTR_ERR; + } + if (pos == b0->slen) { + pos--; + } + if (1 == b1->slen) { + return bstrrchrp(b0, b1->data[0], pos); + } + if (0 > buildCharField(&chrs, b1)) { + return BSTR_ERR; + } + return binchrrCF(b0->data, pos, &chrs); +} + +int +bninchr(const bstring b0, int pos, const bstring b1) +{ + struct charField chrs; + if (pos < 0 || b0 == NULL || + b0->data == NULL || b0->slen <= pos) { + return BSTR_ERR; + } + if (buildCharField(&chrs, b1) < 0) { + return BSTR_ERR; + } + invertCharField(&chrs); + return binchrCF(b0->data, b0->slen, pos, &chrs); +} + +int +bninchrr(const bstring b0, int pos, const bstring b1) +{ + struct charField chrs; + if (pos < 0 || b0 == NULL || + b0->data == NULL || b0->slen < pos) { + return BSTR_ERR; + } + if (pos == b0->slen) { + pos--; + } + if (buildCharField(&chrs, b1) < 0) { + return BSTR_ERR; + } + invertCharField(&chrs); + return binchrrCF(b0->data, pos, &chrs); +} + +int +bsetstr(bstring b0, int pos, const bstring b1, unsigned char fill) +{ + int d, newlen; + ptrdiff_t pd; + bstring aux = (bstring) b1; + if (pos < 0 || b0 == NULL || b0->slen < 0 || + NULL == b0->data || b0->mlen < b0->slen || b0->mlen <= 0) { + return BSTR_ERR; + } + if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) { + return BSTR_ERR; + } + d = pos; + /* Aliasing case */ + if (NULL != aux) { + if ((pd = (ptrdiff_t)(b1->data - b0->data)) >= 0 && + pd < (ptrdiff_t) b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + d += aux->slen; + } + /* Increase memory size if necessary */ + if (balloc(b0, d + 1) != BSTR_OK) { + if (aux != b1) { + bdestroy (aux); + } + return BSTR_ERR; + } + newlen = b0->slen; + /* Fill in "fill" character as necessary */ + if (pos > newlen) { + memset(b0->data + b0->slen, (int)fill, + (size_t)(pos - b0->slen)); + newlen = pos; + } + /* Copy b1 to position pos in b0. */ + if (aux != NULL) { + bBlockCopy((char *)(b0->data + pos), (char *)aux->data, + aux->slen); + if (aux != b1) { + bdestroy(aux); + } + } + /* Indicate the potentially increased size of b0 */ + if (d > newlen) { + newlen = d; + } + b0->slen = newlen; + b0->data[newlen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +binsert(bstring b1, int pos, const bstring b2, unsigned char fill) +{ + int d, l; + ptrdiff_t pd; + bstring aux = (bstring) b2; + if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || + b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) { + return BSTR_ERR; + } + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && + pd < (ptrdiff_t) b1->mlen) { + if (NULL == (aux = bstrcpy (b2))) { + return BSTR_ERR; + } + } + /* Compute the two possible end pointers */ + d = b1->slen + aux->slen; + l = pos + aux->slen; + if ((d|l) < 0) { + return BSTR_ERR; + } + if (l > d) { + /* Inserting past the end of the string */ + if (balloc(b1, l + 1) != BSTR_OK) { + if (aux != b2) { + bdestroy(aux); + } + return BSTR_ERR; + } + memset(b1->data + b1->slen, (int)fill, + (size_t)(pos - b1->slen)); + b1->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc(b1, d + 1) != BSTR_OK) { + if (aux != b2) { + bdestroy(aux); + } + return BSTR_ERR; + } + bBlockCopy(b1->data + l, b1->data + pos, d - l); + b1->slen = d; + } + bBlockCopy(b1->data + pos, aux->data, aux->slen); + b1->data[b1->slen] = (unsigned char)'\0'; + if (aux != b2) { + bdestroy(aux); + } + return BSTR_OK; +} + +int +breplace(bstring b1, int pos, int len, const bstring b2, unsigned char fill) +{ + int pl, ret; + ptrdiff_t pd; + bstring aux = (bstring) b2; + if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || + b2 == NULL || b1->data == NULL || b2->data == NULL || + b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || + b1->mlen <= 0) { + return BSTR_ERR; + } + /* Straddles the end? */ + if (pl >= b1->slen) { + if ((ret = bsetstr (b1, pos, b2, fill)) < 0) { + return ret; + } + if (pos + b2->slen < b1->slen) { + b1->slen = pos + b2->slen; + b1->data[b1->slen] = (unsigned char) '\0'; + } + return ret; + } + /* Aliasing case */ + pd = (ptrdiff_t)(b2->data - b1->data); + if (pd >= 0 && pd < (ptrdiff_t)b1->slen) { + aux = bstrcpy(b2); + if (!aux) { + return BSTR_ERR; + } + } + if (aux->slen > len) { + if (balloc(b1, b1->slen + aux->slen - len) != BSTR_OK) { + if (aux != b2) { + bdestroy(aux); + } + return BSTR_ERR; + } + } + if (aux->slen != len) { + memmove(b1->data + pos + aux->slen, b1->data + pos + len, + b1->slen - (pos + len)); + } + memcpy(b1->data + pos, aux->data, aux->slen); + b1->slen += aux->slen - len; + b1->data[b1->slen] = (unsigned char)'\0'; + if (aux != b2) { + bdestroy(aux); + } + return BSTR_OK; +} + +typedef int (*instr_fnptr)(const bstring s1, int pos, const bstring s2); + +#define INITIAL_STATIC_FIND_INDEX_COUNT 32 + +/* + * findreplaceengine is used to implement bfindreplace and + * bfindreplacecaseless. It works by breaking the three cases of + * expansion, reduction and replacement, and solving each of these + * in the most efficient way possible. + */ +static int +findreplaceengine(bstring b, const bstring find, const bstring repl, + int pos, instr_fnptr instr) +{ + int i, ret, slen, mlen, delta, acc; + int *d; + /* This +1 is unnecessary, but it shuts up LINT. */ + int static_d[INITIAL_STATIC_FIND_INDEX_COUNT + 1]; + ptrdiff_t pd; + bstring auxf = (bstring) find; + bstring auxr = (bstring) repl; + if (!b || !b->data || !find || + !find->data || !repl || !repl->data || + pos < 0 || find->slen <= 0 || b->mlen < 0 || + b->slen > b->mlen || b->mlen <= 0 || b->slen < 0 || + repl->slen < 0) { + return BSTR_ERR; + } + if (pos > b->slen - find->slen) { + return BSTR_OK; + } + /* Alias with find string */ + pd = (ptrdiff_t)(find->data - b->data); + if ((ptrdiff_t)(pos - find->slen) < pd && pd < (ptrdiff_t)b->slen) { + auxf = bstrcpy(find); + if (!auxf) { + return BSTR_ERR; + } + } + /* Alias with repl string */ + pd = (ptrdiff_t)(repl->data - b->data); + if ((ptrdiff_t)(pos - repl->slen) < pd && pd < (ptrdiff_t)b->slen) { + auxr = bstrcpy (repl); + if (!auxr) { + if (auxf != find) { + bdestroy(auxf); + } + return BSTR_ERR; + } + } + delta = auxf->slen - auxr->slen; + /* in-place replacement since find and replace strings are of equal + * length + */ + if (delta == 0) { + while ((pos = instr(b, pos, auxf)) >= 0) { + memcpy(b->data + pos, auxr->data, auxr->slen); + pos += auxf->slen; + } + if (auxf != find) { + bdestroy (auxf); + } + if (auxr != repl) { + bdestroy (auxr); + } + return BSTR_OK; + } + /* shrinking replacement since auxf->slen > auxr->slen */ + if (delta > 0) { + acc = 0; + while ((i = instr (b, pos, auxf)) >= 0) { + if (acc && i > pos) { + memmove(b->data + pos - acc, b->data + pos, + i - pos); + } + if (auxr->slen) { + memcpy(b->data + i - acc, auxr->data, + auxr->slen); + } + acc += delta; + pos = i + auxf->slen; + } + + if (acc) { + i = b->slen; + if (i > pos) { + memmove(b->data + pos - acc, b->data + pos, + i - pos); + } + b->slen -= acc; + b->data[b->slen] = (unsigned char) '\0'; + } + + if (auxf != find) { + bdestroy (auxf); + } + if (auxr != repl) { + bdestroy (auxr); + } + return BSTR_OK; + } + /* expanding replacement since find->slen < repl->slen. Its a lot + * more complicated. This works by first finding all the matches and + * storing them to a growable array, then doing at most one resize of + * the destination bstring and then performing the direct memory + * transfers of the string segment pieces to form the final result. The + * growable array of matches uses a deferred doubling reallocing + * strategy. What this means is that it starts as a reasonably fixed + * sized auto array in the hopes that many if not most cases will never + * need to grow this array. But it switches as soon as the bounds of + * the array will be exceeded. An extra find result is always appended + * to this array that corresponds to the end of the destination string, + * so slen is checked against mlen - 1 rather than mlen before + * resizing. + */ + mlen = INITIAL_STATIC_FIND_INDEX_COUNT; + d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ + acc = slen = 0; + while ((pos = instr(b, pos, auxf)) >= 0) { + if (slen >= mlen - 1) { + int sl, *t; + mlen += mlen; + sl = sizeof(int *) * mlen; + if (static_d == d) { + /* static_d cannot be realloced */ + d = NULL; + } + if (mlen <= 0 || sl < mlen || + NULL == (t = (int *) realloc(d, sl))) { + ret = BSTR_ERR; + goto done; + } + if (NULL == d) { + memcpy(t, static_d, sizeof (static_d)); + } + d = t; + } + d[slen] = pos; + slen++; + acc -= delta; + pos += auxf->slen; + if (pos < 0 || acc < 0) { + ret = BSTR_ERR; + goto done; + } + } + /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ + d[slen] = b->slen; + ret = balloc (b, b->slen + acc + 1); + if (BSTR_OK == ret) { + b->slen += acc; + for (i = slen-1; i >= 0; i--) { + int s, l; + s = d[i] + auxf->slen; + l = d[i+1] - s; /* d[slen] may be accessed here. */ + if (l) { + memmove(b->data + s + acc, b->data + s, l); + } + if (auxr->slen) { + memmove(b->data + s + acc - auxr->slen, + auxr->data, auxr->slen); + } + acc += delta; + } + b->data[b->slen] = (unsigned char)'\0'; + } +done: + if (static_d == d) { + d = NULL; + } + free(d); + if (auxf != find) { + bdestroy(auxf); + } + if (auxr != repl) { + bdestroy(auxr); + } + return ret; +} + +int +bfindreplace(bstring b, const bstring find, const bstring repl, int pos) +{ + return findreplaceengine(b, find, repl, pos, binstr); +} + +int +bfindreplacecaseless(bstring b, const bstring find, const bstring repl, int pos) +{ + return findreplaceengine(b, find, repl, pos, binstrcaseless); +} + +int +binsertch(bstring b, int pos, int len, unsigned char fill) +{ + int d, l, i; + if (pos < 0 || !b || + b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || len < 0) { + return BSTR_ERR; + } + /* Compute the two possible end pointers */ + d = b->slen + len; + l = pos + len; + if ((d|l) < 0) { + return BSTR_ERR; + } + if (l > d) { + /* Inserting past the end of the string */ + if (balloc(b, l + 1) != BSTR_OK) { + return BSTR_ERR; + } + pos = b->slen; + b->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc(b, d + 1) != BSTR_OK) { + return BSTR_ERR; + } + for (i = d - 1; i >= l; i--) { + b->data[i] = b->data[i - len]; + } + b->slen = d; + } + for (i = pos; i < l; i++) { + b->data[i] = fill; + } + b->data[b->slen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +bpattern(bstring b, int len) +{ + int i, d; + d = blength(b); + if (d <= 0 || len < 0 || balloc(b, len + 1) != BSTR_OK) { + return BSTR_ERR; + } + if (len > 0) { + if (d == 1) { + return bsetstr(b, len, NULL, b->data[0]); + } + for (i = d; i < len; i++) { + b->data[i] = b->data[i - d]; + } + } + b->data[len] = (unsigned char)'\0'; + b->slen = len; + return BSTR_OK; +} + +#define BS_BUFF_SZ (1024) + +int +breada(bstring b, bNread readPtr, void *parm) +{ + int i, l, n; + if (b == NULL || b->mlen <= 0 || + b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || readPtr == NULL) { + return BSTR_ERR; + } + i = b->slen; + for (n = i + 16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { + if (BSTR_OK != balloc(b, n + 1)) { + return BSTR_ERR; + } + l = (int)readPtr((void *)(b->data + i), 1, n - i, parm); + i += l; + b->slen = i; + if (i < n) { + break; + } + } + b->data[i] = (unsigned char)'\0'; + return BSTR_OK; +} + +bstring +bread(bNread readPtr, void *parm) +{ + bstring buff; + if (0 > breada(buff = bfromcstr (""), readPtr, parm)) { + bdestroy(buff); + return NULL; + } + return buff; +} + +int +bassigngets(bstring b, bNgetc getcPtr, void *parm, char terminator) +{ + int c, d, e; + if (!b || b->mlen <= 0 || + b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) { + return BSTR_ERR; + } + d = 0; + e = b->mlen - 2; + while ((c = getcPtr(parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) { + return BSTR_ERR; + } + e = b->mlen - 2; + } + b->data[d] = (unsigned char)c; + d++; + if (c == terminator) { + break; + } + } + b->data[d] = (unsigned char)'\0'; + b->slen = d; + return d == 0 && c < 0; +} + +int +bgetsa(bstring b, bNgetc getcPtr, void *parm, char terminator) +{ + int c, d, e; + if (!b || b->mlen <= 0 || + b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || !getcPtr) { + return BSTR_ERR; + } + d = b->slen; + e = b->mlen - 2; + while ((c = getcPtr(parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc(b, d + 2) != BSTR_OK) { + return BSTR_ERR; + } + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) { + break; + } + } + b->data[d] = (unsigned char)'\0'; + b->slen = d; + return d == 0 && c < 0; +} + +bstring +bgets(bNgetc getcPtr, void *parm, char terminator) +{ + bstring buff; + if (0 > bgetsa(buff = bfromcstr (""), getcPtr, parm, terminator) || + 0 >= buff->slen) { + bdestroy(buff); + buff = NULL; + } + return buff; +} + +struct bStream { + bstring buff; /* Buffer for over-reads */ + void *parm; /* The stream handle for core stream */ + bNread readFnPtr; /* fread compatible fnptr for core stream */ + int isEOF; /* track file's EOF state */ + int maxBuffSz; +}; + +struct bStream * +bsopen (bNread readPtr, void *parm) +{ + struct bStream *s; + if (readPtr == NULL) { + return NULL; + } + s = malloc(sizeof (struct bStream)); + if (!s) { + return NULL; + } + s->parm = parm; + s->buff = bfromcstr (""); + s->readFnPtr = readPtr; + s->maxBuffSz = BS_BUFF_SZ; + s->isEOF = 0; + return s; +} + +int bsbufflength(struct bStream *s, int sz) +{ + int oldSz; + if (!s || sz < 0) { + return BSTR_ERR; + } + oldSz = s->maxBuffSz; + if (sz > 0) { + s->maxBuffSz = sz; + } + return oldSz; +} + +int +bseof(const struct bStream *s) +{ + if (!s || !s->readFnPtr) { + return BSTR_ERR; + } + return s->isEOF && (s->buff->slen == 0); +} + +void * +bsclose(struct bStream *s) +{ + void *parm; + if (s == NULL) { + return NULL; + } + s->readFnPtr = NULL; + if (s->buff) { + bdestroy(s->buff); + } + s->buff = NULL; + parm = s->parm; + s->parm = NULL; + s->isEOF = 1; + free(s); + return parm; +} + +int +bsreadlna(bstring r, struct bStream *s, char terminator) +{ + int i, l, ret, rlo; + char *b; + struct tagbstring x; + if (!s || !s->buff || + !r || r->mlen <= 0 || + r->slen < 0 || r->mlen < r->slen) { + return BSTR_ERR; + } + l = s->buff->slen; + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + b = (char *)s->buff->data; + x.data = (unsigned char *)b; + /* First check if the current buffer holds the terminator */ + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat(r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) { + bdelete(s->buff, 0, i + 1); + } + return BSTR_OK; + } + rlo = r->slen; + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat(r, &x)) { + return BSTR_ERR; + } + /* Perform direct in-place reads into the destination to allow for + * the minimum of data-copies + */ + while (1) { + if (BSTR_OK != balloc(r, r->slen + s->maxBuffSz + 1)) { + return BSTR_ERR; + } + b = (char *) (r->data + r->slen); + l = (int) s->readFnPtr(b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char)'\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) + ; + if (i < l) { + break; + } + r->slen += l; + } + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + memcpy(s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +bsreadlnsa(bstring r, struct bStream *s, const bstring term) +{ + int i, l, ret, rlo; + unsigned char *b; + struct tagbstring x; + struct charField cf; + if (!s || !s->buff || !r || !term || + !term->data || r->mlen <= 0 || r->slen < 0 || + r->mlen < r->slen) { + return BSTR_ERR; + } + if (term->slen == 1) { + return bsreadlna(r, s, term->data[0]); + } + if (term->slen < 1 || buildCharField(&cf, term)) { + return BSTR_ERR; + } + l = s->buff->slen; + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + b = (unsigned char *)s->buff->data; + x.data = b; + /* First check if the current buffer holds the terminator */ + b[l] = term->data[0]; /* Set sentinel */ + for (i = 0; !testInCharField(&cf, b[i]); i++) + ; + if (i < l) { + x.slen = i + 1; + ret = bconcat(r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) { + bdelete(s->buff, 0, i + 1); + } + return BSTR_OK; + } + rlo = r->slen; + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat(r, &x)) { + return BSTR_ERR; + } + /* Perform direct in-place reads into the destination to allow for + * the minimum of data-copies + */ + while (1) { + if (BSTR_OK != balloc(r, r->slen + s->maxBuffSz + 1)) { + return BSTR_ERR; + } + b = (unsigned char *)(r->data + r->slen); + l = (int) s->readFnPtr(b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char)'\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + b[l] = term->data[0]; /* Set sentinel */ + for (i = 0; !testInCharField(&cf, b[i]); i++) + ; + if (i < l) { + break; + } + r->slen += l; + } + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + memcpy(s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char)'\0'; + return BSTR_OK; +} + +int +bsreada(bstring r, struct bStream *s, int n) +{ + int l, ret, orslen; + char *b; + struct tagbstring x; + if (!s || !s->buff || !r || r->mlen <= 0 + || r->slen < 0 || r->mlen < r->slen || n <= 0) { + return BSTR_ERR; + } + n += r->slen; + if (n <= 0) { + return BSTR_ERR; + } + l = s->buff->slen; + orslen = r->slen; + if (0 == l) { + if (s->isEOF) { + return BSTR_ERR; + } + if (r->mlen > n) { + l = (int)s->readFnPtr(r->data + r->slen, 1, + n - r->slen, s->parm); + if (0 >= l || l > n - r->slen) { + s->isEOF = 1; + return BSTR_ERR; + } + r->slen += l; + r->data[r->slen] = (unsigned char)'\0'; + return 0; + } + } + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + b = (char *) s->buff->data; + x.data = (unsigned char *)b; + do { + if (l + r->slen >= n) { + x.slen = n - r->slen; + ret = bconcat(r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) { + bdelete(s->buff, 0, x.slen); + } + return BSTR_ERR & -(r->slen == orslen); + } + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) { + break; + } + l = n - r->slen; + if (l > s->maxBuffSz) { + l = s->maxBuffSz; + } + l = (int)s->readFnPtr(b, 1, l, s->parm); + + } while (l > 0); + if (l < 0) { + l = 0; + } + if (l == 0) { + s->isEOF = 1; + } + s->buff->slen = l; + return BSTR_ERR & -(r->slen == orslen); +} + +int +bsreadln(bstring r, struct bStream *s, char terminator) +{ + if (!s || !s->buff || !r || r->mlen <= 0) { + return BSTR_ERR; + } + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + r->slen = 0; + return bsreadlna(r, s, terminator); +} + +int +bsreadlns(bstring r, struct bStream *s, const bstring term) +{ + if (!s || !s->buff || !r || !term || !term->data || r->mlen <= 0) { + return BSTR_ERR; + } + if (term->slen == 1) { + return bsreadln (r, s, term->data[0]); + } + if (term->slen < 1) { + return BSTR_ERR; + } + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + r->slen = 0; + return bsreadlnsa(r, s, term); +} + +int +bsread(bstring r, struct bStream *s, int n) +{ + if (!s || !s->buff || !r || r->mlen <= 0 || n <= 0) { + return BSTR_ERR; + } + if (BSTR_OK != balloc(s->buff, s->maxBuffSz + 1)) { + return BSTR_ERR; + } + r->slen = 0; + return bsreada(r, s, n); +} + +int +bsunread(struct bStream *s, const bstring b) +{ + if (!s || !s->buff) { + return BSTR_ERR; + } + return binsert(s->buff, 0, b, (unsigned char)'?'); +} + +int +bspeek(bstring r, const struct bStream *s) +{ + if (!s || !s->buff) { + return BSTR_ERR; + } + return bassign(r, s->buff); +} + +bstring +bjoin(const struct bstrList *bl, const bstring sep) +{ + bstring b; + int i, c, v; + if (bl == NULL || bl->qty < 0) { + return NULL; + } + if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) { + return NULL; + } + for (i = 0, c = 1; i < bl->qty; i++) { + v = bl->entry[i]->slen; + if (v < 0) { + return NULL; /* Invalid input */ + } + c += v; + if (c < 0) { + return NULL; /* Wrap around ?? */ + } + } + if (sep != NULL) { + c += (bl->qty - 1) * sep->slen; + } + b = (bstring)malloc(sizeof(struct tagbstring)); + if (NULL == b) { + return NULL; /* Out of memory */ + } + b->data = (unsigned char *)malloc(c); + if (b->data == NULL) { + free (b); + return NULL; + } + b->mlen = c; + b->slen = c-1; + for (i = 0, c = 0; i < bl->qty; i++) { + if (i > 0 && sep != NULL) { + memcpy(b->data + c, sep->data, sep->slen); + c += sep->slen; + } + v = bl->entry[i]->slen; + memcpy(b->data + c, bl->entry[i]->data, v); + c += v; + } + b->data[c] = (unsigned char)'\0'; + return b; +} + +#define BSSSC_BUFF_LEN (256) + +int +bssplitscb(struct bStream *s, const bstring splitStr, + int (*cb)(void *parm, int ofs, const bstring entry), + void *parm) +{ + struct charField chrs; + bstring buff; + int i, p, ret; + if (!cb || !s || !s->readFnPtr || + !splitStr || splitStr->slen < 0) { + return BSTR_ERR; + } + buff = bfromcstr (""); + if (!buff) { + return BSTR_ERR; + } + if (splitStr->slen == 0) { + while (bsreada(buff, s, BSSSC_BUFF_LEN) >= 0) + ; + if ((ret = cb(parm, 0, buff)) > 0) { + ret = 0; + } + } else { + buildCharField(&chrs, splitStr); + ret = p = i = 0; + while (1) { + if (i >= buff->slen) { + bsreada(buff, s, BSSSC_BUFF_LEN); + if (i >= buff->slen) { + if (0 < (ret = cb (parm, p, buff))) { + ret = 0; + } + break; + } + } + if (testInCharField(&chrs, buff->data[i])) { + struct tagbstring t; + unsigned char c; + blk2tbstr(t, buff->data + i + 1, + buff->slen - (i + 1)); + if ((ret = bsunread(s, &t)) < 0) { + break; + } + buff->slen = i; + c = buff->data[i]; + buff->data[i] = (unsigned char)'\0'; + if ((ret = cb(parm, p, buff)) < 0) { + break; + } + buff->data[i] = c; + buff->slen = 0; + p += i + 1; + i = -1; + } + i++; + } + } + bdestroy(buff); + return ret; +} + +int +bssplitstrcb(struct bStream *s, const bstring splitStr, + int (*cb)(void *parm, int ofs, const bstring entry), + void *parm) +{ + bstring buff; + int i, p, ret; + if (!cb || !s || !s->readFnPtr || + !splitStr || splitStr->slen < 0) { + return BSTR_ERR; + } + if (splitStr->slen == 1) { + return bssplitscb(s, splitStr, cb, parm); + } + buff = bfromcstr (""); + if (!buff) { + return BSTR_ERR; + } + if (splitStr->slen == 0) { + for (i = 0; bsreada(buff, s, BSSSC_BUFF_LEN) >= 0; i++) { + if ((ret = cb (parm, 0, buff)) < 0) { + bdestroy(buff); + return ret; + } + buff->slen = 0; + } + return BSTR_OK; + } else { + ret = p = i = 0; + for (i = p = 0; ;) { + ret = binstr (buff, 0, splitStr); + if (ret >= 0) { + struct tagbstring t; + blk2tbstr(t, buff->data, ret); + i = ret + splitStr->slen; + ret = cb (parm, p, &t); + if (ret < 0) { + break; + } + p += i; + bdelete(buff, 0, i); + } else { + bsreada(buff, s, BSSSC_BUFF_LEN); + if (bseof(s)) { + ret = cb (parm, p, buff); + if (ret > 0) { + ret = 0; + } + break; + } + } + } + } + bdestroy(buff); + return ret; +} + +struct bstrList * +bstrListCreate(void) +{ + struct bstrList *sl = malloc(sizeof(struct bstrList)); + if (sl) { + sl->entry = (bstring *)malloc(1 * sizeof(bstring)); + if (!sl->entry) { + free(sl); + sl = NULL; + } else { + sl->qty = 0; + sl->mlen = 1; + } + } + return sl; +} + +int +bstrListDestroy(struct bstrList *sl) +{ + int i; + if (!sl || sl->qty < 0) { + return BSTR_ERR; + } + for (i = 0; i < sl->qty; i++) { + if (sl->entry[i]) { + bdestroy(sl->entry[i]); + sl->entry[i] = NULL; + } + } + sl->qty = -1; + sl->mlen = -1; + free(sl->entry); + sl->entry = NULL; + free(sl); + return BSTR_OK; +} + +int +bstrListAlloc(struct bstrList *sl, int msz) +{ + bstring *l; + int smsz; + size_t nsz; + if (!sl || msz <= 0 || + !sl->entry || sl->qty < 0 || + sl->mlen <= 0 || sl->qty > sl->mlen) { + return BSTR_ERR; + } + if (sl->mlen >= msz) { + return BSTR_OK; + } + smsz = snapUpSize(msz); + nsz = ((size_t)smsz) * sizeof(bstring); + if (nsz < (size_t) smsz) { + return BSTR_ERR; + } + l = realloc(sl->entry, nsz); + if (!l) { + smsz = msz; + nsz = ((size_t)smsz) * sizeof(bstring); + l = realloc(sl->entry, nsz); + if (!l) { + return BSTR_ERR; + } + } + sl->mlen = smsz; + sl->entry = l; + return BSTR_OK; +} + +int +bstrListAllocMin(struct bstrList *sl, int msz) +{ + bstring *l; + size_t nsz; + if (!sl || msz <= 0 || + !sl->entry || sl->qty < 0 || + sl->mlen <= 0 || sl->qty > sl->mlen) { + return BSTR_ERR; + } + if (msz < sl->qty) { + msz = sl->qty; + } + if (sl->mlen == msz) { + return BSTR_OK; + } + nsz = ((size_t)msz) * sizeof(bstring); + if (nsz < (size_t)msz) { + return BSTR_ERR; + } + l = realloc(sl->entry, nsz); + if (!l) { + return BSTR_ERR; + } + sl->mlen = msz; + sl->entry = l; + return BSTR_OK; +} + +int +bsplitcb(const bstring str, unsigned char splitChar, int pos, + int (*cb) (void *parm, int ofs, int len), + void *parm) +{ + int i, p, ret; + if (!cb || !str || pos < 0 || pos > str->slen) { + return BSTR_ERR; + } + p = pos; + do { + for (i = p; i < str->slen; i++) { + if (str->data[i] == splitChar) { + break; + } + } + if ((ret = cb(parm, p, i - p)) < 0) { + return ret; + } + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +int +bsplitscb(const bstring str, const bstring splitStr, int pos, + int (*cb)(void *parm, int ofs, int len), + void *parm) +{ + struct charField chrs; + int i, p, ret; + if (!cb || !str || pos < 0 || pos > str->slen || + !splitStr || splitStr->slen < 0) { + return BSTR_ERR; + } + if (splitStr->slen == 0) { + if ((ret = cb (parm, 0, str->slen)) > 0) { + ret = 0; + } + return ret; + } + if (splitStr->slen == 1) { + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + } + buildCharField(&chrs, splitStr); + p = pos; + do { + for (i = p; i < str->slen; i++) { + if (testInCharField(&chrs, str->data[i])) { + break; + } + } + if ((ret = cb(parm, p, i - p)) < 0) { + return ret; + } + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +int +bsplitstrcb(const bstring str, const bstring splitStr, int pos, + int (*cb)(void *parm, int ofs, int len), + void *parm) +{ + int i, p, ret; + if (!cb || !str || pos < 0 || pos > str->slen || + !splitStr || splitStr->slen < 0) { + return BSTR_ERR; + } + if (0 == splitStr->slen) { + for (i = pos; i < str->slen; i++) { + ret = cb (parm, i, 1); + if (ret < 0) { + return ret; + } + } + return BSTR_OK; + } + if (splitStr->slen == 1) { + return bsplitcb(str, splitStr->data[0], pos, cb, parm); + } + for (i = p = pos; i <= str->slen - splitStr->slen; i++) { + ret = memcmp(splitStr->data, str->data + i, splitStr->slen); + if (0 == ret) { + ret = cb (parm, p, i - p); + if (ret < 0) { + return ret; + } + i += splitStr->slen; + p = i; + } + } + ret = cb (parm, p, str->slen - p); + if (ret < 0) { + return ret; + } + return BSTR_OK; +} + +struct genBstrList { + bstring b; + struct bstrList *bl; +}; + +static int +bscb(void *parm, int ofs, int len) +{ + struct genBstrList *g = (struct genBstrList *)parm; + if (g->bl->qty >= g->bl->mlen) { + int mlen = g->bl->mlen * 2; + bstring *tbl; + while (g->bl->qty >= mlen) { + if (mlen < g->bl->mlen) { + return BSTR_ERR; + } + mlen += mlen; + } + tbl = (bstring *)realloc(g->bl->entry, sizeof(bstring) * mlen); + if (tbl == NULL) { + return BSTR_ERR; + } + g->bl->entry = tbl; + g->bl->mlen = mlen; + } + g->bl->entry[g->bl->qty] = bmidstr(g->b, ofs, len); + g->bl->qty++; + return BSTR_OK; +} + +struct bstrList * +bsplit(const bstring str, unsigned char splitChar) +{ + struct genBstrList g; + if (!str || !str->data || str->slen < 0) { + return NULL; + } + g.bl = malloc(sizeof(struct bstrList)); + if (!g.bl) { + return NULL; + } + g.bl->mlen = 4; + g.bl->entry = malloc(g.bl->mlen * sizeof(bstring)); + if (!g.bl->entry) { + free(g.bl); + return NULL; + } + + g.b = (bstring)str; + g.bl->qty = 0; + if (bsplitcb(str, splitChar, 0, bscb, &g) < 0) { + bstrListDestroy(g.bl); + return NULL; + } + return g.bl; +} + +struct bstrList * +bsplitstr(const bstring str, const bstring splitStr) +{ + struct genBstrList g; + if (!str || !str->data || str->slen < 0) { + return NULL; + } + g.bl = malloc(sizeof(struct bstrList)); + if (!g.bl) { + return NULL; + } + g.bl->mlen = 4; + g.bl->entry = malloc(g.bl->mlen * sizeof (bstring)); + if (!g.bl->entry) { + free(g.bl); + return NULL; + } + g.b = (bstring)str; + g.bl->qty = 0; + if (bsplitstrcb(str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy(g.bl); + return NULL; + } + return g.bl; +} + +struct bstrList * +bsplits(const bstring str, const bstring splitStr) +{ + struct genBstrList g; + if (!str || str->slen < 0 || !str->data || + !splitStr || splitStr->slen < 0 || !splitStr->data) { + return NULL; + } + g.bl = malloc(sizeof(struct bstrList)); + if (!g.bl) { + return NULL; + } + g.bl->mlen = 4; + g.bl->entry = malloc (g.bl->mlen * sizeof(bstring)); + if (!g.bl->entry) { + free(g.bl); + return NULL; + } + g.b = (bstring)str; + g.bl->qty = 0; + if (bsplitscb(str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy(g.bl); + return NULL; + } + return g.bl; +} + +#define exvsnprintf(r, b, n, f, a) \ +{ \ + r = vsnprintf(b, n, f, a); \ +} + +#define START_VSNBUFF (16) + +/* On IRIX vsnprintf returns n-1 when the operation would overflow the target + * buffer, WATCOM and MSVC both return -1, while C99 requires that the returned + * value be exactly what the length would be if the buffer would be large + * enough. This leads to the idea that if the return value is larger than n, + * then changing n to the return value will reduce the number of iterations + * required. + */ + +int +bformata(bstring b, const char *fmt, ...) +{ + va_list arglist; + bstring buff; + int n, r; + if (!b || !fmt || !b->data || b->mlen <= 0 || + b->slen < 0 || b->slen > b->mlen) { + return BSTR_ERR; + } + /* Since the length is not determinable beforehand, a search is + * performed using the truncating "vsnprintf" call (to avoid buffer + * overflows) on increasing potential sizes for the output result. + */ + n = (int)(2 * strlen(fmt)); + if (n < START_VSNBUFF) { + n = START_VSNBUFF; + } + buff = bfromcstralloc(n + 2, ""); + if (!buff) { + n = 1; + buff = bfromcstralloc(n + 2, ""); + if (!buff) { + return BSTR_ERR; + } + } + while (1) { + va_start(arglist, fmt); + exvsnprintf(r, (char *) buff->data, n + 1, fmt, arglist); + va_end(arglist); + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) { + break; + } + if (r > n) { + n = r; + } else { + n += n; + } + if (BSTR_OK != balloc(buff, n + 2)) { + bdestroy(buff); + return BSTR_ERR; + } + } + r = bconcat(b, buff); + bdestroy(buff); + return r; +} + +int +bassignformat(bstring b, const char *fmt, ...) +{ + va_list arglist; + bstring buff; + int n, r; + if (!b || !fmt || !b->data || b->mlen <= 0 || + b->slen < 0 || b->slen > b->mlen) { + return BSTR_ERR; + } + /* Since the length is not determinable beforehand, a search is + * performed using the truncating "vsnprintf" call (to avoid buffer + * overflows) on increasing potential sizes for the output result. + */ + n = (int)(2 * strlen(fmt)); + if (n < START_VSNBUFF) { + n = START_VSNBUFF; + } + buff = bfromcstralloc (n + 2, ""); + if (!buff) { + n = 1; + buff = bfromcstralloc (n + 2, ""); + if (!buff) { + return BSTR_ERR; + } + } + while (1) { + va_start(arglist, fmt); + exvsnprintf(r, (char *)buff->data, n + 1, fmt, arglist); + va_end(arglist); + buff->data[n] = (unsigned char)'\0'; + buff->slen = (int)strlen((char *)buff->data); + if (buff->slen < n) { + break; + } + if (r > n) { + n = r; + } else { + n += n; + } + if (BSTR_OK != balloc(buff, n + 2)) { + bdestroy(buff); + return BSTR_ERR; + } + } + + r = bassign(b, buff); + bdestroy(buff); + return r; +} + +bstring +bformat(const char *fmt, ...) +{ + va_list arglist; + bstring buff; + int n, r; + if (!fmt) { + return NULL; + } + /* Since the length is not determinable beforehand, a search is + * performed using the truncating "vsnprintf" call (to avoid buffer + * overflows) on increasing potential sizes for the output result. + */ + n = (int)(2 * strlen(fmt)); + if (n < START_VSNBUFF) { + n = START_VSNBUFF; + } + buff = bfromcstralloc(n + 2, ""); + if (!buff) { + n = 1; + buff = bfromcstralloc(n + 2, ""); + if (!buff) { + return NULL; + } + } + while (1) { + va_start(arglist, fmt); + exvsnprintf(r, (char *)buff->data, n + 1, fmt, arglist); + va_end(arglist); + buff->data[n] = (unsigned char)'\0'; + buff->slen = (int)strlen((char *)buff->data); + if (buff->slen < n) { + break; + } + if (r > n) { + n = r; + } else { + n += n; + } + if (BSTR_OK != balloc(buff, n + 2)) { + bdestroy(buff); + return NULL; + } + } + return buff; +} + +int +bvcformata(bstring b, int count, const char *fmt, va_list arg) +{ + int n, r, l; + if (!b || !fmt || count <= 0 || !b->data || + b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) { + return BSTR_ERR; + } + if (count > (n = b->slen + count) + 2) { + return BSTR_ERR; + } + if (BSTR_OK != balloc(b, n + 2)) { + return BSTR_ERR; + } + exvsnprintf(r, (char *)b->data + b->slen, count + 2, fmt, arg); + /* Did the operation complete successfully within bounds? */ + for (l = b->slen; l <= n; l++) { + if ('\0' == b->data[l]) { + b->slen = l; + return BSTR_OK; + } + } + /* Abort, since the buffer was not large enough. The return value + * tries to help set what the retry length should be. + */ + b->data[b->slen] = '\0'; + if (r > count + 1) { + /* Does r specify a particular target length? */ + n = r; + } else { + /* If not, just double the size of count */ + n = count + count; + if (count > n) { + n = INT_MAX; + } + } + n = -n; + if (n > BSTR_ERR - 1) { + n = BSTR_ERR - 1; + } + return n; +} diff --git a/OpenFAST/modules/map/src/bstring/bstrlib.h b/OpenFAST/modules/map/src/bstring/bstrlib.h new file mode 100644 index 000000000..1292a38cb --- /dev/null +++ b/OpenFAST/modules/map/src/bstring/bstrlib.h @@ -0,0 +1,1765 @@ +/* Copyright 2002-2010 Paul Hsieh + * This file is part of Bstrlib. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of bstrlib nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * GNU General Public License Version 2 (the "GPL"). + */ + +/** + * \file + * \brief C implementaion of bstring functions + * + * This file is the header file for the core module for implementing the + * bstring functions. + */ + +#ifndef BSTRLIB_H +#define BSTRLIB_H + +#if __GNUC__ >= 4 +#define BSTR_PUBLIC \ + __attribute__ ((visibility ("default"))) +#define BSTR_PRIVATE \ + __attribute__ ((visibility ("hidden"))) +#else +#define BSTR_PUBLIC +#define BSTR_PRIVATE +#endif + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define BSTR_PRINTF(format, argument) \ + __attribute__ ((__format__ (__printf__, format, argument))) +#define BSTR_UNUSED \ + __attribute__ ((__unused__)) +#else +#define BSTR_PRINTF(format, argument) +#define BSTR_UNUSED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> + +#define BSTR_ERR (-1) +#define BSTR_OK (0) +#define BSTR_BS_BUFF_LENGTH_GET (0) + +typedef struct tagbstring *bstring; + +struct tagbstring { + int mlen; + int slen; + unsigned char *data; +}; + +/* Copy functions */ +#define cstr2bstr bfromcstr + +/** + * Take a standard C library style '\0' terminated char buffer and generate + * a bstring with the same contents as the char buffer. + * + * If an error occurs #NULL is returned. + * + * \code + * bstring b = bfromcstr("Hello"); + * if(!b) { + * fprintf(stderr, "Out of memory"); + * } else { + * puts((char *)b->data); + * } + * \endcode + */ +BSTR_PUBLIC bstring +bfromcstr(const char *str); + +/** + * Create a bstring which contains the contents of the '\0' terminated + * char *buffer str. + * + * The memory buffer backing the bstring is at least mlen characters in + * length. If an error occurs NULL is returned. + * + * \code + * bstring b = bfromcstralloc(64, someCstr); + * if(b) { + * b->data[63] = 'x'; + * } + * \endcode + * + * The idea is that this will set the 64th character of b to 'x' if it is at + * least 64 characters long otherwise do nothing. And we know this is well + * defined so long as b was successfully created, since it will have been + * allocated with at least 64 characters. + */ +BSTR_PUBLIC bstring +bfromcstralloc(int mlen, const char *str); + +/** + * Create a bstring whose contents are described by the contiguous buffer + * pointing to by blk with a length of len bytes. + * + * Note that this function creates a copy of the data in blk, rather than + * simply referencing it. Compare with the blk2tbstr macro. If an error + * occurs NULL is returned. + */ +BSTR_PUBLIC bstring +blk2bstr(const void *blk, int len); + +/** + * Create a '\0' terminated char buffer which contains the contents of the + * bstring s, except that any contained '\0' characters are converted to the + * character in z. + * + * This returned value should be freed with bcstrfree(), by the caller. If + * an error occurs NULL is returned. + */ +BSTR_PUBLIC char * +bstr2cstr(const bstring s, char z); + +/** + * Frees a C-string generated by bstr2cstr(). + * + * This is normally unnecessary since it just wraps a call to free(), + * however, if malloc() and free() have been redefined as a macros within + * the bstrlib module (via macros in the memdbg.h backdoor) with some + * difference in behaviour from the std library functions, then this allows + * a correct way of freeing the memory that allows higher level code to be + * independent from these macro redefinitions. + */ +BSTR_PUBLIC int +bcstrfree(char *s); + +/** + * Make a copy of the passed in bstring. + * + * The copied bstring is returned if there is no error, otherwise NULL is + * returned. + */ +BSTR_PUBLIC bstring +bstrcpy(const bstring b1); + +/** + * Overwrite the bstring a with the contents of bstring b. + * + * Note that the bstring a must be a well defined and writable bstring. If + * an error occurs BSTR_ERR is returned and a is not overwritten. + */ +BSTR_PUBLIC int +bassign(bstring a, const bstring b); + +/** + * Overwrite the bstring a with the middle of contents of bstring b + * starting from position left and running for a length len. + * + * left and len are clamped to the ends of b as with the function bmidstr. + * Note that the bstring a must be a well defined and writable bstring. If + * an error occurs BSTR_ERR is returned and a is not overwritten. + */ +BSTR_PUBLIC int +bassignmidstr(bstring a, const bstring b, int left, int len); + +/** + * Overwrite the string a with the contents of char * string str. + * + * Note that the bstring a must be a well defined and writable bstring. If + * an error occurs BSTR_ERR is returned and a may be partially overwritten. + */ +BSTR_PUBLIC int +bassigncstr(bstring a, const char *str); + +/** + * Overwrite the bstring a with the middle of contents of bstring b + * starting from position left and running for a length len. + * + * left and len are clamped to the ends of b as with the function bmidstr. + * Note that the bstring a must be a well defined and writable bstring. If + * an error occurs BSTR_ERR is returned and a is not overwritten. + */ +BSTR_PUBLIC int +bassignblk(bstring a, const void *s, int len); + +/* Destroy function */ + +/** + * Deallocate the bstring passed. + * + * Passing NULL in as a parameter will have no effect. Note that both the + * header and the data portion of the bstring will be freed. No other + * bstring function which modifies one of its parameters will free or + * reallocate the header. Because of this, in general, bdestroy cannot be + * called on any declared struct tagbstring even if it is not write + * protected. A bstring which is write protected cannot be destroyed via the + * bdestroy call. Any attempt to do so will result in no action taken, and + * BSTR_ERR will be returned. + */ +BSTR_PUBLIC int +bdestroy(bstring b); + +/* Space allocation hinting functions */ + +/** + * Increase the allocated memory backing the data buffer for the bstring b + * to a length of at least length. + * + * If the memory backing the bstring b is already large enough, not action is + * performed. This has no effect on the bstring b that is visible to the + * bstring API. Usually this function will only be used when a minimum buffer + * size is required coupled with a direct access to the ->data member of the + * bstring structure. + * + * Be warned that like any other bstring function, the bstring must be well + * defined upon entry to this function, i.e., doing something like: + * + * \code + * b->slen *= 2; + * balloc(b, b->slen); + * \endcode + * + * is invalid, and should be implemented as: + * + * \code + * int t; + * if (BSTR_OK == balloc (b, t = (b->slen * 2))) { + * b->slen = t; + * } + * \endcode + * + * This function will return with BSTR_ERR if b is not detected as a valid + * bstring or length is not greater than 0, otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +balloc(bstring s, int len); + +/** + * Change the amount of memory backing the bstring b to at least length. + * + * This operation will never truncate the bstring data including the + * extra terminating '\0' and thus will not decrease the length to less than + * b->slen + 1. Note that repeated use of this function may cause + * performance problems (realloc may be called on the bstring more than + * the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b + * is not detected as a valid bstring or length is not greater than 0, + * otherwise BSTR_OK is returned. + * + * So for example: + * + * \code + * if (BSTR_OK == ballocmin (b, 64)) { + * b->data[63] = 'x'; + * } + * \endcode + * + * The idea is that this will set the 64th character of b to 'x' if it is at + * least 64 characters long otherwise do nothing. And we know this is well + * defined so long as the ballocmin call was successfully, since it will + * ensure that b has been allocated with at least 64 characters. + */ +BSTR_PUBLIC int +ballocmin(bstring b, int len); + +/* Substring extraction */ + +/** + * Create a bstring which is the substring of b starting from position left + * and running for a length len (clamped by the end of the bstring b). + * + * If there was no error, the value of this constructed bstring is returned + * otherwise NULL is returned. + */ +BSTR_PUBLIC bstring +bmidstr(const bstring b, int left, int len); + +/*Various standard manipulations */ + +/** + * Concatenate the bstring b1 to the end of bstring b0. + * + * The value BSTR_OK is returned if the operation is successful, otherwise + * BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bconcat(bstring b0, const bstring b1); + +/** + * Concatenate the character c to the end of bstring b. + * + * The value BSTR_OK is returned if the operation is successful, otherwise + * BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bconchar(bstring b0, char c); + +/** + * Concatenate the char * string s to the end of bstring b. + * + * The value BSTR_OK is returned if the operation is successful, otherwise + * BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bcatcstr(bstring b, const char *s); + +/** + * Concatenate a fixed length buffer (s, len) to the end of bstring b. + * + * The value BSTR_OK is returned if the operation is successful, otherwise + * BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bcatblk(bstring b, const void *s, int len); + +/** + * Inserts the bstring s2 into s1 at position pos. + * + * If the position pos is past the end of s1, then the character "fill" is + * appended as necessary to make up the gap between the end of s1 and pos. The + * value BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR + * is returned. + */ +BSTR_PUBLIC int +binsert(bstring s1, int pos, const bstring s2, unsigned char fill); + +/** + * Inserts the character fill repeatedly into s1 at position pos for a + * length len. + * + * If the position pos is past the end of s1, then the character "fill" is + * appended as necessary to make up the gap between the end of s1 and the + * position pos + len (exclusive). The value BSTR_OK is returned if the + * operation is successful, otherwise BSTR_ERR is returned. + */ +BSTR_PUBLIC int +binsertch(bstring s1, int pos, int len, unsigned char fill); + +/** + * Replace a section of a bstring from pos for a length len with the bstring + * b2. + * + * If the position pos is past the end of b1 then the character "fill" is + * appended as necessary to make up the gap between the end of b1 and pos. + */ +BSTR_PUBLIC int +breplace(bstring b1, int pos, int len, const bstring b2, unsigned char fill); + +/** + * Removes characters from pos to pos+len-1 and shifts the tail of the + * bstring starting from pos+len to pos. + * + * len must be positive for this call to have any effect. The section of the + * bstring described by (pos, len) is clamped to boundaries of the bstring b. + * The value BSTR_OK is returned if the operation is successful, otherwise + * BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bdelete(bstring s1, int pos, int len); + +/** + * Overwrite the bstring b0 starting at position pos with the bstring b1. + * + * If the position pos is past the end of b0, then the character "fill" is + * appended as necessary to make up the gap between the end of b0 and pos. If + * b1 is NULL, it behaves as if it were a 0-length bstring. The value BSTR_OK + * is returned if the operation is successful, otherwise BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bsetstr(bstring b0, int pos, const bstring b1, unsigned char fill); + +/** + * Truncate the bstring to at most n characters. + * + * This function will return with BSTR_ERR if b is not detected as a valid + * bstring or n is less than 0, otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +btrunc(bstring b, int n); + +/*Scan/search functions */ + +/** + * Compare two bstrings without differentiating between case. + * + * The return value is the difference of the values of the characters where the + * two bstrings first differ, otherwise 0 is returned indicating that the + * bstrings are equal. If the lengths are different, then a difference from 0 + * is given, but if the first extra character is '\0', then it is taken to be + * the value UCHAR_MAX + 1. + */ +BSTR_PUBLIC int +bstricmp(const bstring b0, const bstring b1); + +/** + * Compare two bstrings without differentiating between case for at most n + * characters. + * + * If the position where the two bstrings first differ is before the nth + * position, the return value is the difference of the values of the + * characters, otherwise 0 is returned. If the lengths are different and less + * than n characters, then a difference from 0 is given, but if the first extra + * character is '\0', then it is taken to be the value UCHAR_MAX + 1. + */ +BSTR_PUBLIC int +bstrnicmp(const bstring b0, const bstring b1, int n); + +/** + * Compare two bstrings for equality without differentiating between case. + * + * If the bstrings differ other than in case, 0 is returned, if the bstrings + * are the same, 1 is returned, if there is an error, -1 is returned. If + * the length of the bstrings are different, this function is O(1). '\0' + * termination characters are not treated in any special way. + */ +BSTR_PUBLIC int +biseqcaseless(const bstring b0, const bstring b1); + +/** + * Compare beginning of bstring b0 with a block of memory of length len + * without differentiating between case for equality. + * + * If the beginning of b0 differs from the memory block other than in case (or + * if b0 is too short), 0 is returned, if the bstrings are the same, 1 is + * returned, if there is an error, -1 is returned. + */ +BSTR_PUBLIC int +bisstemeqcaselessblk(const bstring b0, const void *blk, int len); + +/** + * Compare the bstring b0 and b1 for equality. + * + * If the bstrings differ, 0 is returned, if the bstrings are the same, 1 is + * returned, if there is an error, -1 is returned. If the length of the + * bstrings are different, this function has O(1) complexity. Contained '\0' + * characters are not treated as a termination character. + * + * Note that the semantics of biseq are not completely compatible with + * bstrcmp because of its different treatment of the '\0' character. + */ +BSTR_PUBLIC int +biseq(const bstring b0, const bstring b1); + +/** + * Compare beginning of bstring b0 with a block of memory of length len for + * equality. + * + * If the beginning of b0 differs from the memory block (or if b0 is too + * short), 0 is returned, if the bstrings are the same, 1 is returned, if there + * is an error, -1 is returned. + */ +BSTR_PUBLIC int +bisstemeqblk(const bstring b0, const void *blk, int len); + +/** + * Compare the bstring b and char * string s. + * + * The C string s must be '\0' terminated at exactly the length of the bstring + * b, and the contents between the two must be identical with the bstring b + * with no '\0' characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal when comparing them in the same format after converting one or the + * other. If they are equal 1 is returned, if they are unequal 0 is returned + * and if there is a detectable error BSTR_ERR is returned. + */ +BSTR_PUBLIC int +biseqcstr(const bstring b, const char *s); + +/** + * Compare the bstring b and char * string s. + * + * The C string s must be '\0' terminated at exactly the length of the bstring + * b, and the contents between the two must be identical except for case with + * the bstring b with no '\0' characters for the two contents to be considered + * equal. This is equivalent to the condition that their current contents will + * be always be equal ignoring case when comparing them in the same format + * after converting one or the other. If they are equal, except for case, 1 is + * returned, if they are unequal regardless of case 0 is returned and if there + * is a detectable error BSTR_ERR is returned. + */ +BSTR_PUBLIC int +biseqcstrcaseless(const bstring b, const char *s); + +/** + * Compare the bstrings b0 and b1 for ordering. + * + * If there is an error, SHRT_MIN is returned, otherwise a value less than or + * greater than zero, indicating that the bstring pointed to by b0 is + * lexicographically less than or greater than the bstring pointed to by b1 is + * returned. If the bstring lengths are unequal but the characters up until the + * length of the shorter are equal then a value less than, or greater than + * zero, indicating that the bstring pointed to by b0 is shorter or longer than + * the bstring pointed to by b1 is returned. 0 is returned if and only if the + * two bstrings are the same. If the length of the bstrings are different, this + * function is O(n). Like its standard C library counter part, the comparison + * does not proceed past any '\0' termination characters encountered. + * + * The seemingly odd error return value, merely provides slightly more + * granularity than the undefined situation given in the C library function + * strcmp. The function otherwise behaves very much like strcmp(). + * + * Note that the semantics of bstrcmp are not completely compatible with + * biseq because of its different treatment of the '\0' termination + * character. + */ +BSTR_PUBLIC int +bstrcmp(const bstring b0, const bstring b1); + +/** + * Compare the bstrings b0 and b1 for ordering for at most n characters. + * + * If there is an error, SHRT_MIN is returned, otherwise a value is returned as + * if b0 and b1 were first truncated to at most n characters then bstrcmp was + * called with these new bstrings are paremeters. If the length of the bstrings + * are different, this function is O(n). Like its standard C library counter + * part, the comparison does not proceed past any '\0' termination characters + * encountered. + * + * The seemingly odd error return value, merely provides slightly more + * granularity than the undefined situation given in the C library function + * strncmp. The function otherwise behaves very much like strncmp(). + */ +BSTR_PUBLIC int +bstrncmp(const bstring b0, const bstring b1, int n); + +/** + * Search for the bstring s2 in s1 starting at position pos and looking in a + * forward (increasing) direction. + * + * If it is found then it returns with the first position after pos where it is + * found, otherwise it returns BSTR_ERR. The algorithm used is brute force; + * O(m*n). + */ +BSTR_PUBLIC int +binstr(const bstring s1, int pos, const bstring s2); + +/** + * Search for the bstring s2 in s1 starting at position pos and looking in a + * backward (decreasing) direction. + * + * If it is found then it returns with the first position after pos where it is + * found, otherwise return BSTR_ERR. Note that the current position at pos is + * tested as well -- so to be disjoint from a previous forward search it is + * recommended that the position be backed up (decremented) by one position. + * The algorithm used is brute force; O(m*n). + */ +BSTR_PUBLIC int +binstrr(const bstring s1, int pos, const bstring s2); + +/** + * Search for the bstring s2 in s1 starting at position pos and looking in a + * forward (increasing) direction but without regard to case. + * + * If it is found then it returns with the first position after pos where it is + * found, otherwise it returns BSTR_ERR. The algorithm used is brute force; + * O(m*n). + */ +BSTR_PUBLIC int +binstrcaseless(const bstring s1, int pos, const bstring s2); + +/** + * Search for the bstring s2 in s1 starting at position pos and looking in a + * backward (decreasing) direction but without regard to case. + * + * If it is found then it returns with the first position after pos where it is + * found, otherwise return BSTR_ERR. Note that the current position at pos is + * tested as well -- so to be disjoint from a previous forward search it is + * recommended that the position be backed up (decremented) by one position. + * The algorithm used is brute force; O(m*n). + */ +BSTR_PUBLIC int +binstrrcaseless(const bstring s1, int pos, const bstring s2); + +/** + * Search for the character c in b forwards from the position pos + * (inclusive). + * + * Returns the position of the found character or BSTR_ERR if it is not found. + */ +BSTR_PUBLIC int +bstrchrp(const bstring b, int c, int pos); + +/** + * Search for the character c in b backwards from the position pos in bstring + * (inclusive). + * + * Returns the position of the found character or BSTR_ERR if it is not found. + */ +BSTR_PUBLIC int +bstrrchrp(const bstring b, int c, int pos); + +/** + * Search for the character c in the bstring b forwards from the start of + * the bstring. + * + * Returns the position of the found character or BSTR_ERR if it is not found. + */ +#define bstrchr(b, c) \ + bstrchrp((b), (c), 0) + +/** + * Search for the character c in the bstring b backwards from the end of the + * bstring. + * + * Returns the position of the found character or BSTR_ERR if it is not found. + */ +#define bstrrchr(b, c) \ + bstrrchrp((b), (c), blength(b) - 1) + +/** + * Search for the first position in b0 starting from pos or after, in which + * one of the characters in b1 is found. + * + * This function has an execution time of O(b0->slen + b1->slen). If such a + * position does not exist in b0, then BSTR_ERR is returned. + */ +BSTR_PUBLIC int +binchr(const bstring b0, int pos, const bstring b1); + +/** + * Search for the last position in b0 no greater than pos, in which one of + * the characters in b1 is found. + * + * This function has an execution time of O(b0->slen + b1->slen). If such a + * position does not exist in b0, then BSTR_ERR is returned. + */ +BSTR_PUBLIC int +binchrr(const bstring b0, int pos, const bstring b1); + +/** + * Search for the first position in b0 starting from pos or after, in which + * none of the characters in b1 is found and return it. + * + * This function has an execution time of O(b0->slen + b1->slen). If such a + * position does not exist in b0, then BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bninchr(const bstring b0, int pos, const bstring b1); + +/** + * Search for the last position in b0 no greater than pos, in which none of + * the characters in b1 is found and return it. + * + * This function has an execution time of O(b0->slen + b1->slen). If such a + * position does not exist in b0, then BSTR_ERR is returned. + */ +BSTR_PUBLIC int +bninchrr(const bstring b0, int pos, const bstring b1); + +/** + * Replace all occurrences of the find substring with a replace bstring + * after a given position in the bstring b. + * + * The find bstring must have a length > 0 otherwise BSTR_ERR is returned. This + * function does not perform recursive per character replacement; that is to + * say successive searches resume at the position after the last replace. + * + * So for example: + * + * \code + * bfindreplace(a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"), + * a2 = bfromcstr("aa"), 0); + * \endcode + * + * Should result in changing a0 to "aaaabaaAb". + * + * This function performs exactly (b->slen - position) bstring comparisons, + * and data movement is bounded above by character volume equivalent to size + * of the output bstring. + */ +BSTR_PUBLIC int +bfindreplace(bstring b, const bstring find, const bstring repl, int pos); + +/** + * Replace all occurrences of the find substring, ignoring case, with a + * replace bstring after a given position in the bstring b. + * + * The find bstring must have a length > 0 otherwise BSTR_ERR is returned. This + * function does not perform recursive per character replacement; that is to + * say successive searches resume at the position after the last replace. + * + * So for example: + * + * \code + * bfindreplacecaseless(a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"), + * a2 = bfromcstr("aa"), 0); + * \endcode + * + * Should result in changing a0 to "aaaabaaaab". + * + * This function performs exactly (b->slen - position) bstring comparisons, + * and data movement is bounded above by character volume equivalent to size + * of the output bstring. + */ +BSTR_PUBLIC int +bfindreplacecaseless(bstring b, const bstring find, const bstring repl, + int pos); + +/* List of string container functions */ +struct bstrList { + int qty, mlen; + bstring *entry; +}; + +/** + * Create an empty struct bstrList. + * + * The struct bstrList output structure is declared as follows: + * + * \code + * struct bstrList { + * int qty, mlen; + * bstring *entry; + * }; + * \endcode + * + * The entry field actually is an array with qty number entries. The mlen + * record counts the maximum number of bstring's for which there is memory + * in the entry record. + * + * The Bstrlib API does *NOT* include a comprehensive set of functions for + * full management of struct bstrList in an abstracted way. The reason for + * this is because aliasing semantics of the list are best left to the user + * of this function, and performance varies wildly depending on the + * assumptions made. + */ +BSTR_PUBLIC struct bstrList * +bstrListCreate(void); + +/** + * Destroy a struct bstrList structure that was returned by the bsplit + * function. Note that this will destroy each bstring in the ->entry array + * as well. See bstrListCreate() above for structure of struct bstrList. + */ +BSTR_PUBLIC int +bstrListDestroy(struct bstrList *sl); + +/** + * Ensure that there is memory for at least msz number of entries for the + * list. + */ +BSTR_PUBLIC int +bstrListAlloc(struct bstrList *sl, int msz); + +/** + * Try to allocate the minimum amount of memory for the list to include at + * least msz entries or sl->qty whichever is greater. + */ +BSTR_PUBLIC int +bstrListAllocMin(struct bstrList *sl, int msz); + +/* String split and join functions */ + +/** + * Create an array of sequential substrings from str divided by the + * character splitChar. + * + * Successive occurrences of the splitChar will be divided by empty bstring + * entries, following the semantics from the Python programming language. To + * reclaim the memory from this output structure, bstrListDestroy() should be + * called. See bstrListCreate() above for structure of struct bstrList. + */ +BSTR_PUBLIC struct bstrList * +bsplit(const bstring str, unsigned char splitChar); + +/** + * Create an array of sequential substrings from str divided by any + * character contained in splitStr. + * + * An empty splitStr causes a single entry bstrList containing a copy of str to + * be returned. See bstrListCreate() above for structure of struct bstrList. + */ +BSTR_PUBLIC struct bstrList * +bsplits(const bstring str, const bstring splitStr); + +/** + * Create an array of sequential substrings from str divided by the entire + * substring splitStr. + * + * An empty splitStr causes a single entry bstrList containing a copy of str to + * be returned. See bstrListCreate() above for structure of struct bstrList. + */ +BSTR_PUBLIC struct bstrList * +bsplitstr(const bstring str, const bstring splitStr); + +/** + * Join the entries of a bstrList into one bstring by sequentially + * concatenating them with the sep bstring in between. + * + * If sep is NULL, it is treated as if it were the empty bstring. Note that: + * + * \code + * bjoin (l = bsplit (b, s->data[0]), s); + * \endcode + * + * should result in a copy of b, if s->slen is 1. If there is an error NULL + * is returned, otherwise a bstring with the correct result is returned. + * See bstrListCreate() above for structure of struct bstrList. + */ +BSTR_PUBLIC bstring +bjoin(const struct bstrList *bl, const bstring sep); + +/** + * Iterate the set of disjoint sequential substrings over str starting at + * position pos divided by the character splitChar. + * + * The parm passed to bsplitcb is passed on to cb. If the function cb returns a + * value < 0, then further iterating is halted and this value is returned by + * bsplitcb. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitcb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitcb will continue in an undefined manner. + * + * This function is provided as an incremental alternative to bsplit that is + * abortable and which does not impose additional memory allocation. + */ +BSTR_PUBLIC int +bsplitcb(const bstring str, + unsigned char splitChar, + int pos, + int(*cb)(void *parm, int ofs, int len), + void *parm); + +/** + * Iterate the set of disjoint sequential substrings over str starting at + * position pos divided by any of the characters in splitStr. + * + * An empty splitStr causes the whole str to be iterated once. The parm passed + * to bsplitcb is passed on to cb. If the function cb returns a value < 0, then + * further iterating is halted and this value is returned by bsplitcb. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitscb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + * + * This function is provided as an incremental alternative to bsplits that + * is abortable and which does not impose additional memory allocation. + */ +BSTR_PUBLIC int +bsplitscb(const bstring str, + const bstring splitStr, + int pos, + int(*cb)(void *parm, int ofs, int len), + void *parm); + +/** + * Iterate the set of disjoint sequential substrings over str starting at + * position pos divided by the entire substring splitStr. + * + * An empty splitStr causes each character of str to be iterated. The parm + * passed to bsplitcb is passed on to cb. If the function cb returns a value < + * 0, then further iterating is halted and this value is returned by bsplitcb. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitstrcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitstrcb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + * + * This function is provided as an incremental alternative to bsplitstr that + * is abortable and which does not impose additional memory allocation. + */ +BSTR_PUBLIC int +bsplitstrcb(const bstring str, + const bstring splitStr, + int pos, + int(*cb)(void *parm, int ofs, int len), void *parm); + +/* Miscellaneous functions */ + +/** + * Replicate the starting bstring, b, end to end repeatedly until it + * surpasses len characters, then chop the result to exactly len characters. + * + * This function operates in-place. This function will return with BSTR_ERR + * if b is NULL or of length 0, otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +bpattern(bstring b, int len); + +/** + * Convert contents of bstring to upper case. + * + * This function will return with BSTR_ERR if b is NULL or of length 0, + * otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +btoupper(bstring b); + +/** + * Convert contents of bstring to lower case. + * + * This function will return with BSTR_ERR if b is NULL or of length 0, + * otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +btolower(bstring b); + +/** + * Delete whitespace contiguous from the left end of the bstring. + * + * This function will return with BSTR_ERR if b is NULL or of length 0, + * otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +bltrimws(bstring b); + +/** + * Delete whitespace contiguous from the right end of the bstring. + * + * This function will return with BSTR_ERR if b is NULL or of length 0, + * otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +brtrimws(bstring b); + +/** + * Delete whitespace contiguous from both ends of the bstring. + * + * This function will return with BSTR_ERR if b is NULL or of length 0, + * otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +btrimws(bstring b); + +/* *printf format functions */ +/** + * Takes the same parameters as printf(), but rather than outputting + * results to stdio, it forms a bstring which contains what would have been + * output. + * + * Note that if there is an early generation of a '\0' character, the bstring + * will be truncated to this end point. + * + * Note that %s format tokens correspond to '\0' terminated char * buffers, + * not bstrings. To print a bstring, first dereference data element of the + * the bstring: + * + * b1->data needs to be '\0' terminated, so tagbstrings generated by + * blk2tbstr() might not be suitable. + * + * \code + * b0 = bformat ("Hello, %s", b1->data); + * \endcode + */ +BSTR_PUBLIC bstring +bformat(const char *fmt, ...); + +/** + * In addition to the initial output buffer b, bformata takes the same + * parameters as printf (), but rather than outputting results to stdio, it + * appends the results to the initial bstring parameter. + * + * Note that if there is an early generation of a '\0' character, the bstring + * will be truncated to this end point. + * + * Note that %s format tokens correspond to '\0' terminated char * buffers, + * not bstrings. To print a bstring, first dereference data element of the + * the bstring: + * + * b1->data needs to be '\0' terminated, so tagbstrings generated by + * blk2tbstr() might not be suitable. + * + * \code + * bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data); + * \endcode + */ +BSTR_PUBLIC int +bformata(bstring b, const char *fmt, ...); + +/** + * After the first parameter, it takes the same parameters as printf(), but + * rather than outputting results to stdio, it outputs the results to + * the bstring parameter b. + * + * Note that if there is an early generation of a '\0' character, the bstring + * will be truncated to this end point. + * + * Note that %s format tokens correspond to '\0' terminated char * buffers, + * not bstrings. To print a bstring, first dereference data element of the + * the bstring: + * + * b1->data needs to be '\0' terminated, so tagbstrings generated by + * blk2tbstr() might not be suitable. + * + * \code + * bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data); + * \endcode + */ +BSTR_PUBLIC int +bassignformat(bstring b, const char *fmt, ...); + +/** + * The bvcformata function formats data under control of the format control + * string fmt and attempts to append the result to b. + * + * The fmt parameter is the same as that of the printf function. The variable + * argument list is replaced with arglist, which has been initialized by the + * va_start macro. The size of the output is upper bounded by count. If the + * required output exceeds count, the string b is not augmented with any + * contents and a value below BSTR_ERR is returned. If a value below -count is + * returned then it is recommended that the negative of this value be used as + * an update to the count in a subsequent pass. On other errors, such as + * running out of memory, parameter errors or numeric wrap around BSTR_ERR is + * returned. BSTR_OK is returned when the output is successfully generated and + * appended to b. + * + * Note: There is no sanity checking of arglist, and this function is + * destructive of the contents of b from the b->slen point onward. If there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + * + * Although this function is part of the external API for Bstrlib, the + * interface and semantics (length limitations, and unusual return codes) + * are fairly atypical. The real purpose for this function is to provide an + * engine for the bvformata macro. + */ +BSTR_PUBLIC int +bvcformata(bstring b, int count, const char *fmt, va_list arglist); + +/** + * Append the bstring b with printf like formatting with the format control + * string, and the arguments taken from the list of arguments after + * lastarg passed to the containing function. + * + * If the containing function does not have extra parameters or lastarg is not + * the last named parameter before the extra parameters then the results are + * undefined. If successful, the results are appended to b and BSTR_OK is + * assigned to ret. Otherwise BSTR_ERR is assigned to ret. + * + * Example: + * + * \code + * void dbgerror (FILE *fp, const char *fmt, ...) + * { + * int ret; + * bstring b; + * bvformata(ret, b = bfromcstr ("DBG: "), fmt, fmt); + * if (BSTR_OK == ret) { + * fputs ((char *) bdata (b), fp); + * } + * bdestroy (b); + * } + * \endcode + */ +#define bvformata(ret, b, fmt, lastarg) \ +do { \ + bstring bstrtmp_b =(b); \ + const char *bstrtmp_fmt = (fmt); \ + int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ + for (;;) { \ + va_list bstrtmp_arglist; \ + va_start(bstrtmp_arglist, lastarg); \ + bstrtmp_r = bvcformata(bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, \ + bstrtmp_arglist); \ + va_end(bstrtmp_arglist); \ + if(bstrtmp_r >= 0) { \ + /* Everything went ok */ \ + bstrtmp_r = BSTR_OK; \ + break; \ + } else if(-bstrtmp_r <= bstrtmp_sz) { \ + /* A real error? */ \ + bstrtmp_r = BSTR_ERR; \ + break; \ + } \ + /* Doubled or target size */ \ + bstrtmp_sz = -bstrtmp_r; \ + } \ + ret = bstrtmp_r; \ +} while (0); + +typedef int (*bNgetc)(void *parm); + +typedef size_t (*bNread)(void *buff, size_t elsize, size_t nelem, void *parm); + +/* Input functions */ + +/** + * Read a bstring from a stream. + * + * As many bytes as is necessary are read until the terminator is consumed or + * no more characters are available from the stream. If read from the stream, + * the terminator character will be appended to the end of the returned + * bstring. The getcPtr function must have the same semantics as the fgetc C + * library function (i.e., returning an integer whose value is negative when + * there are no more characters available, otherwise the value of the next + * available unsigned character from the stream.) The intention is that parm + * would contain the stream data context/state required (similar to the role of + * the FILE* I/O stream parameter of fgets.) If no characters are read, or + * there is some other detectable error, NULL is returned. + * + * bgets will never call the getcPtr function more often than necessary to + * construct its output (including a single call, if required, to determine + * that the stream contains no more characters.) + * + * Abstracting the character stream function and terminator character allows + * for different stream devices and string formats other than '\n' + * terminated lines in a file if desired (consider \032 terminated email + * messages, in a UNIX mailbox for example.) + * + * For files, this function can be used analogously as fgets as follows: + * + * \code + * fp = fopen( ... ); + * if (fp) b = bgets((bNgetc) fgetc, fp, '\n'); + * \endcode + * + * (Note that only one terminator character can be used, and that '\0' is + * not assumed to terminate the stream in addition to the terminator + * character. This is consistent with the semantics of fgets.) + */ +BSTR_PUBLIC bstring +bgets(bNgetc getcPtr, void *parm, char terminator); + +/** + * Read an entire stream into a bstring, verbatum. + * + * The readPtr function pointer is compatible with fread sematics, except that + * it need not obtain the stream data from a file. The intention is that parm + * would contain the stream data context/state required (similar to the role of + * the FILE* I/O stream parameter of fread.) + * + * Abstracting the block read function allows for block devices other than + * file streams to be read if desired. Note that there is an ANSI + * compatibility issue if "fread" is used directly; see the ANSI issues + * section below. + */ +BSTR_PUBLIC bstring +bread(bNread readPtr, void *parm); + +/** + * Read from a stream and concatenate to a bstring. + * + * Behaves like bgets, except that it appends it results to the bstring b. The + * value 1 is returned if no characters are read before a negative result is + * returned from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is + * returned in other normal cases. + */ +BSTR_PUBLIC int +bgetsa(bstring b, bNgetc getcPtr, void *parm, char terminator); + +/** + * Read from a stream and concatenate to a bstring. + * + * Behaves like bgets, except that it assigns the results to the bstring b. The + * value 1 is returned if no characters are read before a negative result is + * returned from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is + * returned in other normal cases. + */ +BSTR_PUBLIC int +bassigngets(bstring b, bNgetc getcPtr, void *parm, char terminator); + +/** + * Read an entire stream and append it to a bstring, verbatim. + * + * Behaves like bread, except that it appends it results to the bstring b. + * BSTR_ERR is returned on error, otherwise 0 is returned. + */ +BSTR_PUBLIC int +breada(bstring b, bNread readPtr, void *parm); + +/* Stream functions */ + +/** + * Wrap a given open stream (described by a fread compatible function + * pointer and stream handle) into an open bStream suitable for the bstring + * library streaming functions. + */ +BSTR_PUBLIC struct bStream * +bsopen(bNread readPtr, void *parm); + +/** + * Close the bStream, and return the handle to the stream that was + * originally used to open the given stream. + * + * If s is NULL or detectably invalid, NULL will be returned. + */ +BSTR_PUBLIC void * +bsclose(struct bStream *s); + +/** + * Set the length of the buffer used by the bStream. + * + * If sz is the macro BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not + * set. If s is NULL or sz is negative, the function will return with BSTR_ERR, + * otherwise this function returns with the previous length. + */ +BSTR_PUBLIC int +bsbufflength(struct bStream *s, int sz); + +/** + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. + * + * The matched terminator, if found, appears at the end of the line read. If + * the stream has been exhausted of all available data, before any can be read, + * BSTR_ERR is returned. This function may read additional characters into the + * stream buffer from the core stream that are not returned, but will be + * retained for subsequent read operations. When reading from high speed + * streams, this function can perform significantly faster than bgets. + */ +BSTR_PUBLIC int +bsreadln(bstring b, struct bStream *s, char terminator); + +/** + * Read a bstring terminated by any character in the terminators bstring or + * the end of the stream from the bStream (s) and return it into the + * parameter r. + * + * This function may read additional characters from the core stream that are + * not returned, but will be retained for subsequent read operations. + */ +BSTR_PUBLIC int +bsreadlns(bstring r, struct bStream *s, const bstring term); + +/** + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. + * + * This function will read the minimum required number of additional characters + * from the core stream. When the stream is at the end of the file BSTR_ERR is + * returned, otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +bsread(bstring b, struct bStream *s, int n); + +/** + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and concatenate it to the parameter r. + * + * The matched terminator, if found, appears at the end of the line read. If + * the stream has been exhausted of all available data, before any can be read, + * BSTR_ERR is returned. This function may read additional characters into the + * stream buffer from the core stream that are not returned, but will be + * retained for subsequent read operations. When reading from high speed + * streams, this function can perform significantly faster than bgets. + */ +BSTR_PUBLIC int +bsreadlna(bstring b, struct bStream *s, char terminator); + +/** + * Read a bstring terminated by any character in the terminators bstring or + * the end of the stream from the bStream (s) and concatenate it to the + * parameter r. + * + * If the stream has been exhausted of all available data, before any can be + * read, BSTR_ERR is returned. This function may read additional characters + * from the core stream that are not returned, but will be retained for + * subsequent read operations. + */ +BSTR_PUBLIC int +bsreadlnsa(bstring r, struct bStream *s, const bstring term); + +/** + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream and concatenate it to the parameter r. + * + * This function will read the minimum required number of additional characters + * from the core stream. When the stream is at the end of the file BSTR_ERR is + * returned, otherwise BSTR_OK is returned. + */ +BSTR_PUBLIC int +bsreada(bstring b, struct bStream *s, int n); + +/** + * Insert a bstring into the bStream at the current position. + * + * These characters will be read prior to those that actually come from the + * core stream. + */ +BSTR_PUBLIC int +bsunread(struct bStream *s, const bstring b); + +/** + * Return the number of currently buffered characters from the bStream that + * will be read prior to reads from the core stream, and append it to the + * the parameter r. + */ +BSTR_PUBLIC int +bspeek(bstring r, const struct bStream *s); + +/** + * Iterate the set of disjoint sequential substrings over the stream s + * divided by any character from the bstring splitStr. + * + * The parm passed to bssplitscb is passed on to cb. If the function cb returns + * a value < 0, then further iterating is halted and this return value is + * returned by bssplitscb. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + * + * This function is provided as way to incrementally parse through a file + * or other generic stream that in total size may otherwise exceed the + * practical or desired memory available. As with the other split callback + * based functions this is abortable and does not impose additional memory + * allocation. + */ +BSTR_PUBLIC int +bssplitscb(struct bStream *s, + const bstring splitStr, + int(*cb)(void *parm, int ofs, const bstring entry), + void *parm); + +/** + * Iterate the set of disjoint sequential substrings over the stream s + * divided by the entire substring splitStr. + * + * The parm passed to bssplitstrcb is passed on to cb. If the function cb + * returns a value < 0, then further iterating is halted and this return value + * is returned by bssplitstrcb. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitstrcb will continue by starting the next + * split at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + * + * This function is provided as way to incrementally parse through a file + * or other generic stream that in total size may otherwise exceed the + * practical or desired memory available. As with the other split callback + * based functions this is abortable and does not impose additional memory + * allocation. + */ +BSTR_PUBLIC int +bssplitstrcb(struct bStream *s, + const bstring splitStr, + int(*cb)(void *parm, int ofs, const bstring entry), + void *parm); + +/** + * Return the defacto "EOF" (end of file) state of a stream (1 if the + * bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or + * detectably erroneous). + * + * When the readPtr callback returns a value <= 0 the stream reaches its "EOF" + * state. Note that bunread with non-empty content will essentially turn off + * this state, and the stream will not be in its "EOF" state so long as its + * possible to read more data out of it. + * + * Also note that the semantics of bseof() are slightly different from + * something like feof(), i.e., reaching the end of the stream does not + * necessarily guarantee that bseof() will return with a value indicating + * that this has happened. bseof() will only return indicating that it has + * reached the "EOF" and an attempt has been made to read past the end of + * the bStream. + */ +BSTR_PUBLIC int +bseof(const struct bStream *s); + +/* Accessor macros */ + +/** + * Returns the length of the bstring. + * + * If the bstring is NULL err is returned. + */ +#define blengthe(b, e) \ + (((b) == (void *)0 || (b)->slen < 0) \ + ? (int)(e) \ + : ((b)->slen)) + +/** + * Returns the length of the bstring. + * + * If the bstring is NULL, the length returned is 0. + */ +#define blength(b) \ + (blengthe((b), 0)) + +/** + * Returns the char * data portion of the bstring b offset by ofs. + * + * If b is NULL, err is returned. + */ +#define bdataofse(b, o, e) \ + (((b) == (void *)0 || (b)->data == (void *)0) \ + ? (char *)(e) \ + : ((char *)(b)->data) + (o)) + +/** + * Returns the char * data portion of the bstring b offset by ofs. + * + * If b is NULL, NULL is returned. + */ +#define bdataofs(b, o) \ + (bdataofse((b),(o),(void *)0)) + +/** + * Returns the char * data portion of the bstring b. + * + * If b is NULL, err is returned. + */ +#define bdatae(b, e) \ + (bdataofse(b, 0, e)) + +/** + * Returns the char * data portion of the bstring b. + * + * If b is NULL, NULL is returned. + */ +#define bdata(b) \ + (bdataofs(b, 0)) + +/** + * Returns the p'th character of the bstring b. + * + * If the position p refers to a position that does not exist in the bstring or + * the bstring is NULL, then c is returned. + */ +#define bchare(b, p, e) \ + ((((unsigned)(p)) < (unsigned)blength(b)) \ + ? ((b)->data[(p)]) \ + : (e)) + +/** + * Returns the p'th character of the bstring b. + * + * If the position p refers to a position that does not exist in the bstring or + * the bstring is NULL, then '\0' is returned. + */ +#define bchar(b, p) \ + bchare((b), (p), '\0') + +/* Static constant string initialization macro */ + +/** + */ +#define bsStaticMlen(q, m) { (m), (int)sizeof(q) - 1, (unsigned char *)("" q "") } + +#if defined (_MSC_VER) +/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ +/** + * The bsStatic macro allows for static declarations of literal string + * constants as struct tagbstring structures. + * + * The resulting tagbstring does not need to be freed or destroyed. Note that + * this macro is only well defined for string literal arguments. For more + * general string pointers, use the btfromcstr macro. + * + * The resulting struct tagbstring is permanently write protected. Attempts + * to write to this struct tagbstring from any bstrlib function will lead to + * BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + * tagbstring has no effect. + */ +#define bsStatic(q) bsStaticMlen(q, -32) +#endif /* defined (_MSC_VER) */ + +#ifndef bsStatic +/** + */ +#define bsStatic(q) bsStaticMlen(q, -__LINE__) +#endif /* bsStatic */ + +/* Static constant block parameter pair */ + +/** + * The bsStaticBlkParms macro emits a pair of comma seperated parameters + * corresponding to the block parameters for the block functions in Bstrlib + * (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk). + * + * Note that this macro is only well defined for string literal arguments. + * + * Examples: + * + * \code + * bstring b = blk2bstr(bsStaticBlkParms("Fast init.")); + * bcatblk(b, bsStaticBlkParms("No frills fast concatenation.")); + * \endcode + * + * These are faster than using bfromcstr() and bcatcstr() respectively + * because the length of the inline string is known as a compile time + * constant. Also note that seperate struct tagbstring declarations for + */ +#define bsStaticBlkParms(q) \ + ((void *)("" q "")), ((int)sizeof(q) -1) + +/* Reference building macros */ + +/** + */ +#define cstr2tbstr btfromcstr + +/** + * Fill in the tagbstring t with the '\0' terminated char buffer s. + * + * This action is purely reference oriented; no memory management is done. The + * data member is just assigned s, and slen is assigned the strlen of s. The s + * parameter is accessed exactly once in this macro. + * + * The resulting struct tagbstring is initially write protected. Attempts + * to write to this struct tagbstring in a write protected state from any + * bstrlib function will lead to BSTR_ERR being returned. Invoke the + * bwriteallow on this struct tagbstring to make it writeable (though this + * requires that s be obtained from a function compatible with malloc.) + */ +#define btfromcstr(t, s) \ +do { \ + (t).data = (unsigned char *)(s); \ + (t).slen = ((t).data) \ + ? ((int)(strlen)((char *)(t).data)) \ + : 0; \ + (t).mlen = -1; \ +} while (0) + +/** + */ +#define blk2tbstr(t, s, l) \ +do { \ + (t).data = (unsigned char *)(s); \ + (t).slen = l; \ + (t).mlen = -1; \ +} while (0) + +/** + * Fill in the tagbstring t with the data buffer s with length len. + * + * This action is purely reference oriented; no memory management is done. The + * data member of t is just assigned s, and slen is assigned len. Note that the + * buffer is not appended with a '\0' character. The s and len parameters are + * accessed exactly once each in this macro. + * + * The resulting struct tagbstring is initially write protected. Attempts + * to write to this struct tagbstring in a write protected state from any + * bstrlib function will lead to BSTR_ERR being returned. Invoke the + * bwriteallow on this struct tagbstring to make it writeable (though this + * requires that s be obtained from a function compatible with malloc.) + */ +#define btfromblk(t, s, l) blk2tbstr(t, s, l) + +/** + * Fill the tagbstring t with the substring from b, starting from position + * pos with a length len. + * + * The segment is clamped by the boundaries of the bstring b. This action is + * purely reference oriented; no memory management is done. Note that the + * buffer is not appended with a '\0' character. Note that the t parameter to + * this macro may be accessed multiple times. Note that the contents of t will + * become undefined if the contents of b change or are destroyed. + * + * The resulting struct tagbstring is permanently write protected. Attempts + * to write to this struct tagbstring in a write protected state from any + * bstrlib function will lead to BSTR_ERR being returned. Invoking the + * bwriteallow macro on this struct tagbstring will have no effect. + */ +#define bmid2tbstr(t, b, p, l) \ +do { \ + const bstring bstrtmp_s =(b); \ + if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ + int bstrtmp_left = (p); \ + int bstrtmp_len = (l); \ + if (bstrtmp_left < 0) { \ + bstrtmp_len += bstrtmp_left; \ + bstrtmp_left = 0; \ + } \ + if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) { \ + bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ + } \ + if(bstrtmp_len <= 0) { \ + (t).data =(unsigned char *)""; \ + (t).slen = 0; \ + } else { \ + (t).data = bstrtmp_s->data + bstrtmp_left; \ + (t).slen = bstrtmp_len; \ + } \ + } else { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } \ + (t).mlen = -__LINE__; \ +} while (0); + +/** + * Fill in the tagbstring t with the data buffer s with length len after it + * has been left trimmed. + * + * This action is purely reference oriented; no memory management is done. The + * data member of t is just assigned to a pointer inside the buffer s. Note + * that the buffer is not appended with a '\0' character. The s and len + * parameters are accessed exactly once each in this macro. + * + * The resulting struct tagbstring is permanently write protected. Attempts + * to write to this struct tagbstring from any bstrlib function will lead to + * BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + * tagbstring has no effect. + */ +#define btfromblkltrimws(t, s, l) \ +do { \ + int bstrtmp_idx = 0, bstrtmp_len =(l); \ + unsigned char *bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace(bstrtmp_s[bstrtmp_idx])) { \ + break; \ + } \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} while (0); + +/** + * Fill in the tagbstring t with the data buffer s with length len after it + * has been right trimmed. + * + * This action is purely reference oriented; no memory management is done. The + * data member of t is just assigned to a pointer inside the buffer s. Note + * that the buffer is not appended with a '\0' character. The s and len + * parameters are accessed exactly once each in this macro. + * + * The resulting struct tagbstring is permanently write protected. Attempts + * to write to this struct tagbstring from any bstrlib function will lead to + * BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + * tagbstring has no effect. + */ +#define btfromblkrtrimws(t, s, l) \ +do { \ + int bstrtmp_len = (l) - 1; \ + unsigned char *bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_len >= 0; bstrtmp_len--) { \ + if (!isspace(bstrtmp_s[bstrtmp_len])) { \ + break; \ + } \ + } \ + } \ + (t).data = bstrtmp_s; \ + (t).slen = bstrtmp_len + 1; \ + (t).mlen = -__LINE__; \ +} while (0); + +/** + * Fill in the tagbstring t with the data buffer s with length len after it + * has been left and right trimmed. + * + * This action is purely reference oriented; no memory management is done. The + * data member of t is just assigned to a pointer inside the buffer s. Note + * that the buffer is not appended with a '\0' character. The s and len + * parameters are accessed exactly once each in this macro. + * + * The resulting struct tagbstring is permanently write protected. Attempts + * to write to this struct tagbstring from any bstrlib function will lead to + * BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + * tagbstring has no effect. + */ +#define btfromblktrimws(t, s, l) \ +do { \ + int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ + unsigned char *bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ + if(!isspace(bstrtmp_s[bstrtmp_idx])) { \ + break; \ + } \ + } \ + for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ + if (!isspace(bstrtmp_s[bstrtmp_len])) { \ + break; \ + } \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} while (0); + +/* Write protection macros */ + +/** + * Disallow bstring from being written to via the bstrlib API. + * + * Attempts to write to the resulting tagbstring from any bstrlib function will + * lead to BSTR_ERR being returned. + * + * Note: bstrings which are write protected cannot be destroyed via bdestroy. + */ +#define bwriteprotect(t) \ +do { \ + if ((t).mlen >= 0) { \ + (t).mlen = -1; \ + } \ +} while (0); + +/** + * Allow bstring to be written to via the bstrlib API. + * + * Note that such an action makes the bstring both writable and destroyable. If + * the bstring is not legitimately writable (as is the case for struct + * tagbstrings initialized with a bsStatic value), the results of this are + * undefined. + * + * Note that invoking the bwriteallow macro may increase the number of + * reallocs by one more than necessary for every call to bwriteallow + * interleaved with any bstring API which writes to this bstring. + */ +#define bwriteallow(t) \ +do { \ + if ((t).mlen == -1) { \ + (t).mlen = (t).slen + ((t).slen == 0); \ + } \ +} while (0); + +/** + * Returns 1 if the bstring is write protected, otherwise 0 is returned. + */ +#define biswriteprotected(t) \ + ((t).mlen <= 0) + +#ifdef __cplusplus +} +#endif + +#endif /* BSTRLIB_H */ diff --git a/OpenFAST/modules/map/src/cminpack/cminpack.h b/OpenFAST/modules/map/src/cminpack/cminpack.h new file mode 100644 index 000000000..6d3f75733 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/cminpack.h @@ -0,0 +1,370 @@ +/* Header file for cminpack, by Frederic Devernay. + The documentation for all functions can be found in the file + minpack-documentation.txt from the distribution, or in the source + code of each function. */ + +#ifndef __CMINPACK_H__ +#define __CMINPACK_H__ + +/* The default floating-point type is "double" for C/C++ and "float" for CUDA, + but you can change this by defining one of the following symbols when + compiling the library, and before including cminpack.h when using it: + __cminpack_double__ for double + __cminpack_float__ for float + __cminpack_half__ for half from the OpenEXR library (in this case, you must + compile cminpack with a C++ compiler) +*/ +#ifdef __cminpack_double__ +#define __cminpack_real__ double +#endif + +#ifdef __cminpack_float__ +#define __cminpack_real__ float +#endif + +#ifdef __cminpack_half__ +#include <OpenEXR/half.h> +#define __cminpack_real__ half +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Cmake will define cminpack_EXPORTS on Windows when it +configures to build a shared library. If you are going to use +another build system on windows or create the visual studio +projects by hand you need to define cminpack_EXPORTS when +building a DLL on windows. +*/ +#if defined (__GNUC__) +#define CMINPACK_DECLSPEC_EXPORT __declspec(__dllexport__) +#define CMINPACK_DECLSPEC_IMPORT __declspec(__dllimport__) +#endif +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define CMINPACK_DECLSPEC_EXPORT __declspec(dllexport) +#define CMINPACK_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define CMINPACK_DECLSPEC_EXPORT __export +#define CMINPACK_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define CMINPACK_DECLSPEC_EXPORT _Export +#define CMINPACK_DECLSPEC_IMPORT _Import +#endif + +#if !defined(CMINPACK_NO_DLL) && (defined(__WIN32__) || defined(WIN32) || defined (_WIN32)) +#if defined(cminpack_EXPORTS) || defined(CMINPACK_EXPORTS) || defined(CMINPACK_DLL_EXPORTS) + #define CMINPACK_EXPORT CMINPACK_DECLSPEC_EXPORT + #else + #define CMINPACK_EXPORT CMINPACK_DECLSPEC_IMPORT + #endif /* cminpack_EXPORTS */ +#else /* defined (_WIN32) */ + #define CMINPACK_EXPORT +#endif + +#if defined(__CUDA_ARCH__) || defined(__CUDACC__) +#define __cminpack_attr__ __device__ +#ifndef __cminpack_real__ +#define __cminpack_float__ +#define __cminpack_real__ float +#endif +#define __cminpack_type_fcn_nn__ __cminpack_attr__ int fcn_nn +#define __cminpack_type_fcnder_nn__ __cminpack_attr__ int fcnder_nn +#define __cminpack_type_fcn_mn__ __cminpack_attr__ int fcn_mn +#define __cminpack_type_fcnder_mn__ __cminpack_attr__ int fcnder_mn +#define __cminpack_type_fcnderstr_mn__ __cminpack_attr__ int fcnderstr_mn +#define __cminpack_decl_fcn_nn__ +#define __cminpack_decl_fcnder_nn__ +#define __cminpack_decl_fcn_mn__ +#define __cminpack_decl_fcnder_mn__ +#define __cminpack_decl_fcnderstr_mn__ +#define __cminpack_param_fcn_nn__ +#define __cminpack_param_fcnder_nn__ +#define __cminpack_param_fcn_mn__ +#define __cminpack_param_fcnder_mn__ +#define __cminpack_param_fcnderstr_mn__ +#else +#define __cminpack_attr__ +#ifndef __cminpack_real__ +#define __cminpack_double__ +#define __cminpack_real__ double +#endif +#define __cminpack_type_fcn_nn__ typedef int (*cminpack_func_nn) +#define __cminpack_type_fcnder_nn__ typedef int (*cminpack_funcder_nn) +#define __cminpack_type_fcn_mn__ typedef int (*cminpack_func_mn) +#define __cminpack_type_fcnder_mn__ typedef int (*cminpack_funcder_mn) +#define __cminpack_type_fcnderstr_mn__ typedef int (*cminpack_funcderstr_mn) +#define __cminpack_decl_fcn_nn__ cminpack_func_nn fcn_nn, +#define __cminpack_decl_fcnder_nn__ cminpack_funcder_nn fcnder_nn, +#define __cminpack_decl_fcn_mn__ cminpack_func_mn fcn_mn, +#define __cminpack_decl_fcnder_mn__ cminpack_funcder_mn fcnder_mn, +#define __cminpack_decl_fcnderstr_mn__ cminpack_funcderstr_mn fcnderstr_mn, +#define __cminpack_param_fcn_nn__ fcn_nn, +#define __cminpack_param_fcnder_nn__ fcnder_nn, +#define __cminpack_param_fcn_mn__ fcn_mn, +#define __cminpack_param_fcnder_mn__ fcnder_mn, +#define __cminpack_param_fcnderstr_mn__ fcnderstr_mn, +#endif + +#ifdef __cminpack_double__ +#define __cminpack_func__(func) func +#endif + +#ifdef __cminpack_float__ +#define __cminpack_func__(func) s ## func +#endif + +#ifdef __cminpack_half__ +#define __cminpack_func__(func) h ## func +#endif + +/* Declarations for minpack */ + +/* Function types: */ +/* The first argument can be used to store extra function parameters, thus */ +/* avoiding the use of global variables. */ +/* the iflag parameter is input-only (with respect to the FORTRAN */ +/* version), the output iflag value is the return value of the function. */ +/* If iflag=0, the function shoulkd just print the current values (see */ +/* the nprint parameters below). */ + +/* for hybrd1 and hybrd: */ +/* calculate the functions at x and */ +/* return this vector in fvec. */ +/* return a negative value to terminate hybrd1/hybrd */ +__cminpack_type_fcn_nn__(void *p, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, int iflag ); + +/* for hybrj1 and hybrj */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. do not alter fjac. */ +/* if iflag = 2 calculate the jacobian at x and */ +/* return this matrix in fjac. do not alter fvec. */ +/* return a negative value to terminate hybrj1/hybrj */ +__cminpack_type_fcnder_nn__(void *p, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, int iflag ); + +/* for lmdif1 and lmdif */ +/* calculate the functions at x and */ +/* return this vector in fvec. */ +/* if iflag = 1 the result is used to compute the residuals. */ +/* if iflag = 2 the result is used to compute the Jacobian by finite differences. */ +/* Jacobian computation requires exactly n function calls with iflag = 2. */ +/* return a negative value to terminate lmdif1/lmdif */ +__cminpack_type_fcn_mn__(void *p, int m, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, + int iflag ); + +/* for lmder1 and lmder */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. do not alter fjac. */ +/* if iflag = 2 calculate the jacobian at x and */ +/* return this matrix in fjac. do not alter fvec. */ +/* return a negative value to terminate lmder1/lmder */ +__cminpack_type_fcnder_mn__(void *p, int m, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, + __cminpack_real__ *fjac, int ldfjac, int iflag ); + +/* for lmstr1 and lmstr */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. */ +/* if iflag = i calculate the (i-1)-st row of the */ +/* jacobian at x and return this vector in fjrow. */ +/* return a negative value to terminate lmstr1/lmstr */ +__cminpack_type_fcnderstr_mn__(void *p, int m, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, + __cminpack_real__ *fjrow, int iflag ); + + + + + + +/* MINPACK functions: */ +/* the info parameter was removed from most functions: the return */ +/* value of the function is used instead. */ +/* The argument 'p' can be used to store extra function parameters, thus */ +/* avoiding the use of global variables. You can also think of it as a */ +/* 'this' pointer a la C++. */ + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (Jacobian calculated by + a forward-difference approximation) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(hybrd1)( __cminpack_decl_fcn_nn__ + void *p, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ tol, + __cminpack_real__ *wa, int lwa ); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (Jacobian calculated by + a forward-difference approximation, more general). */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(hybrd)( __cminpack_decl_fcn_nn__ + void *p, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ xtol, int maxfev, + int ml, int mu, __cminpack_real__ epsfcn, __cminpack_real__ *diag, int mode, + __cminpack_real__ factor, int nprint, int *nfev, + __cminpack_real__ *fjac, int ldfjac, __cminpack_real__ *r, int lr, __cminpack_real__ *qtf, + __cminpack_real__ *wa1, __cminpack_real__ *wa2, __cminpack_real__ *wa3, __cminpack_real__ *wa4); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (user-supplied Jacobian) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(hybrj1)( __cminpack_decl_fcnder_nn__ void *p, int n, __cminpack_real__ *x, + __cminpack_real__ *fvec, __cminpack_real__ *fjac, int ldfjac, __cminpack_real__ tol, + __cminpack_real__ *wa, int lwa ); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (user-supplied Jacobian, + more general) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(hybrj)( __cminpack_decl_fcnder_nn__ void *p, int n, __cminpack_real__ *x, + __cminpack_real__ *fvec, __cminpack_real__ *fjac, int ldfjac, __cminpack_real__ xtol, + int maxfev, __cminpack_real__ *diag, int mode, __cminpack_real__ factor, + int nprint, int *nfev, int *njev, __cminpack_real__ *r, + int lr, __cminpack_real__ *qtf, __cminpack_real__ *wa1, __cminpack_real__ *wa2, + __cminpack_real__ *wa3, __cminpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (Jacobian calculated by a forward-difference approximation) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmdif1)( __cminpack_decl_fcn_mn__ + void *p, int m, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ tol, + int *iwa, __cminpack_real__ *wa, int lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (Jacobian calculated by a forward-difference approximation, more + general) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmdif)( __cminpack_decl_fcn_mn__ + void *p, int m, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ ftol, + __cminpack_real__ xtol, __cminpack_real__ gtol, int maxfev, __cminpack_real__ epsfcn, + __cminpack_real__ *diag, int mode, __cminpack_real__ factor, int nprint, + int *nfev, __cminpack_real__ *fjac, int ldfjac, int *ipvt, + __cminpack_real__ *qtf, __cminpack_real__ *wa1, __cminpack_real__ *wa2, __cminpack_real__ *wa3, + __cminpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmder1)( __cminpack_decl_fcnder_mn__ + void *p, int m, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, __cminpack_real__ tol, int *ipvt, + __cminpack_real__ *wa, int lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, more general) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmder)( __cminpack_decl_fcnder_mn__ + void *p, int m, int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, __cminpack_real__ ftol, __cminpack_real__ xtol, __cminpack_real__ gtol, + int maxfev, __cminpack_real__ *diag, int mode, __cminpack_real__ factor, + int nprint, int *nfev, int *njev, int *ipvt, + __cminpack_real__ *qtf, __cminpack_real__ *wa1, __cminpack_real__ *wa2, __cminpack_real__ *wa3, + __cminpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, minimal storage) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmstr1)( __cminpack_decl_fcnderstr_mn__ void *p, int m, int n, + __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, int ldfjac, + __cminpack_real__ tol, int *ipvt, __cminpack_real__ *wa, int lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, minimal storage, more general) */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(lmstr)( __cminpack_decl_fcnderstr_mn__ void *p, int m, + int n, __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, __cminpack_real__ ftol, __cminpack_real__ xtol, __cminpack_real__ gtol, + int maxfev, __cminpack_real__ *diag, int mode, __cminpack_real__ factor, + int nprint, int *nfev, int *njev, int *ipvt, + __cminpack_real__ *qtf, __cminpack_real__ *wa1, __cminpack_real__ *wa2, __cminpack_real__ *wa3, + __cminpack_real__ *wa4 ); + +__cminpack_attr__ +void CMINPACK_EXPORT __cminpack_func__(chkder)( int m, int n, const __cminpack_real__ *x, __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, __cminpack_real__ *xp, __cminpack_real__ *fvecp, int mode, + __cminpack_real__ *err ); + +__cminpack_attr__ +__cminpack_real__ CMINPACK_EXPORT __cminpack_func__(dpmpar)( int i ); + +__cminpack_attr__ +__cminpack_real__ CMINPACK_EXPORT __cminpack_func__(enorm)( int n, const __cminpack_real__ *x ); + +/* compute a forward-difference approximation to the m by n jacobian + matrix associated with a specified problem of m functions in n + variables. */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(fdjac2)(__cminpack_decl_fcn_mn__ + void *p, int m, int n, __cminpack_real__ *x, const __cminpack_real__ *fvec, __cminpack_real__ *fjac, + int ldfjac, __cminpack_real__ epsfcn, __cminpack_real__ *wa); + +/* compute a forward-difference approximation to the n by n jacobian + matrix associated with a specified problem of n functions in n + variables. if the jacobian has a banded form, then function + evaluations are saved by only approximating the nonzero terms. */ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(fdjac1)(__cminpack_decl_fcn_nn__ + void *p, int n, __cminpack_real__ *x, const __cminpack_real__ *fvec, __cminpack_real__ *fjac, int ldfjac, + int ml, int mu, __cminpack_real__ epsfcn, __cminpack_real__ *wa1, + __cminpack_real__ *wa2); + +/* compute inverse(JtJ) after a run of lmdif or lmder. The covariance matrix is obtained + by scaling the result by enorm(y)**2/(m-n). If JtJ is singular and k = rank(J), the + pseudo-inverse is computed, and the result has to be scaled by enorm(y)**2/(m-k). */ +__cminpack_attr__ +void CMINPACK_EXPORT __cminpack_func__(covar)(int n, __cminpack_real__ *r, int ldr, + const int *ipvt, __cminpack_real__ tol, __cminpack_real__ *wa); + +/* covar1 estimates the variance-covariance matrix: + C = sigma**2 (JtJ)**+ + where (JtJ)**+ is the inverse of JtJ or the pseudo-inverse of JtJ (in case J does not have full rank), + and sigma**2 = fsumsq / (m - k) + where fsumsq is the residual sum of squares and k is the rank of J. + The function returns 0 if J has full rank, else the rank of J. +*/ +__cminpack_attr__ +int CMINPACK_EXPORT __cminpack_func__(covar1)(int m, int n, __cminpack_real__ fsumsq, __cminpack_real__ *r, int ldr, + const int *ipvt, __cminpack_real__ tol, __cminpack_real__ *wa); + +/* internal MINPACK subroutines */ +__cminpack_attr__ +void __cminpack_func__(dogleg)(int n, const __cminpack_real__ *r, int lr, + const __cminpack_real__ *diag, const __cminpack_real__ *qtb, __cminpack_real__ delta, __cminpack_real__ *x, + __cminpack_real__ *wa1, __cminpack_real__ *wa2); +__cminpack_attr__ +void __cminpack_func__(qrfac)(int m, int n, __cminpack_real__ *a, int + lda, int pivot, int *ipvt, int lipvt, __cminpack_real__ *rdiag, + __cminpack_real__ *acnorm, __cminpack_real__ *wa); +__cminpack_attr__ +void __cminpack_func__(qrsolv)(int n, __cminpack_real__ *r, int ldr, + const int *ipvt, const __cminpack_real__ *diag, const __cminpack_real__ *qtb, __cminpack_real__ *x, + __cminpack_real__ *sdiag, __cminpack_real__ *wa); +__cminpack_attr__ +void __cminpack_func__(qform)(int m, int n, __cminpack_real__ *q, int + ldq, __cminpack_real__ *wa); +__cminpack_attr__ +void __cminpack_func__(r1updt)(int m, int n, __cminpack_real__ *s, int + ls, const __cminpack_real__ *u, __cminpack_real__ *v, __cminpack_real__ *w, int *sing); +__cminpack_attr__ +void __cminpack_func__(r1mpyq)(int m, int n, __cminpack_real__ *a, int + lda, const __cminpack_real__ *v, const __cminpack_real__ *w); +__cminpack_attr__ +void __cminpack_func__(lmpar)(int n, __cminpack_real__ *r, int ldr, + const int *ipvt, const __cminpack_real__ *diag, const __cminpack_real__ *qtb, __cminpack_real__ delta, + __cminpack_real__ *par, __cminpack_real__ *x, __cminpack_real__ *sdiag, __cminpack_real__ *wa1, + __cminpack_real__ *wa2); +__cminpack_attr__ +void __cminpack_func__(rwupdt)(int n, __cminpack_real__ *r, int ldr, + const __cminpack_real__ *w, __cminpack_real__ *b, __cminpack_real__ *alpha, __cminpack_real__ *cos, + __cminpack_real__ *sin); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __CMINPACK_H__ */ diff --git a/OpenFAST/modules/map/src/cminpack/cminpackP.h b/OpenFAST/modules/map/src/cminpack/cminpackP.h new file mode 100644 index 000000000..d2aa28f96 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/cminpackP.h @@ -0,0 +1,62 @@ +/* Internal header file for cminpack, by Frederic Devernay. */ +#ifndef __CMINPACKP_H__ +#define __CMINPACKP_H__ + +#ifndef __CMINPACK_H__ +#error "cminpackP.h in an internal cminpack header, and must be included after all other headers (including cminpack.h)" +#endif + +#if (defined (USE_CBLAS) || defined (USE_LAPACK)) && !defined (__cminpack_double__) +#error "cminpack can use cblas and lapack only in double precision mode" +#endif + +#ifdef USE_CBLAS +#ifdef __APPLE__ +#include <Accelerate/Accelerate.h> +#else +#include <cblas.h> +#endif +#define __cminpack_enorm__(n,x) cblas_dnrm2(n,x,1) +#else +#define __cminpack_enorm__(n,x) __cminpack_func__(enorm)(n,x) +#endif + +#ifdef USE_LAPACK +#ifdef __APPLE__ +#include <Accelerate/Accelerate.h> +#else +#if defined(__LP64__) /* In LP64 match sizes with the 32 bit ABI */ +typedef int __CLPK_integer; +typedef int __CLPK_logical; +typedef float __CLPK_real; +typedef double __CLPK_doublereal; +typedef __CLPK_logical (*__CLPK_L_fp)(); +typedef int __CLPK_ftnlen; +#else +typedef long int __CLPK_integer; +typedef long int __CLPK_logical; +typedef float __CLPK_real; +typedef double __CLPK_doublereal; +typedef __CLPK_logical (*__CLPK_L_fp)(); +typedef long int __CLPK_ftnlen; +#endif +//extern void dlartg_(double *f, double *g, double *cs, double *sn, double *r__); +int dlartg_(__CLPK_doublereal *f, __CLPK_doublereal *g, __CLPK_doublereal *cs, + __CLPK_doublereal *sn, __CLPK_doublereal *r__) +//extern void dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info); +int dgeqp3_(__CLPK_integer *m, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer * + lda, __CLPK_integer *jpvt, __CLPK_doublereal *tau, __CLPK_doublereal *work, __CLPK_integer *lwork, + __CLPK_integer *info) +//extern void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info); +int dgeqrf_(__CLPK_integer *m, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer * + lda, __CLPK_doublereal *tau, __CLPK_doublereal *work, __CLPK_integer *lwork, __CLPK_integer *info) +#endif +#endif + +#define real_mp __cminpack_real__ +#define minpack_min(a,b) ((a) <= (b) ? (a) : (b)) +#define minpack_max(a,b) ((a) >= (b) ? (a) : (b)) +#define TRUE_ (1) +#define FALSE_ (0) + +#endif /* !__CMINPACKP_H__ */ diff --git a/OpenFAST/modules/map/src/cminpack/dpmpar.c b/OpenFAST/modules/map/src/cminpack/dpmpar.c new file mode 100644 index 000000000..37308dd13 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/dpmpar.c @@ -0,0 +1,201 @@ +#include "cminpack.h" +#include <float.h> +#include "cminpackP.h" + +#define double_EPSILON DBL_EPSILON +#define double_MIN DBL_MIN +#define double_MAX DBL_MAX +#define float_EPSILON FLT_EPSILON +#define float_MIN FLT_MIN +#define float_MAX FLT_MAX +#define half_EPSILON HALF_EPSILON +#define half_MIN HALF_NRM_MIN +#define half_MAX HALF_MAX + +#define DPMPAR(type,X) _DPMPAR(type,X) +#define _DPMPAR(type,X) type ## _ ## X + +__cminpack_attr__ +real_mp __cminpack_func__(dpmpar)(int i) +{ +/* ********** */ + +/* Function dpmpar */ + +/* This function provides double precision machine parameters */ +/* when the appropriate set of data statements is activated (by */ +/* removing the c from column 1) and all other data statements are */ +/* rendered inactive. Most of the parameter values were obtained */ +/* from the corresponding Bell Laboratories Port Library function. */ + +/* The function statement is */ + +/* double precision function dpmpar(i) */ + +/* where */ + +/* i is an integer input variable set to 1, 2, or 3 which */ +/* selects the desired machine parameter. If the machine has */ +/* t base b digits and its smallest and largest exponents are */ +/* emin and emax, respectively, then these parameters are */ + +/* dpmpar(1) = b**(1 - t), the machine precision, */ + +/* dpmpar(2) = b**(emin - 1), the smallest magnitude, */ + +/* dpmpar(3) = b**emax*(1 - b**(-t)), the largest magnitude. */ + +/* Argonne National Laboratory. MINPACK Project. November 1996. */ +/* Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More' */ + +/* ********** */ + +/* Machine constants for the IBM 360/370 series, */ +/* the Amdahl 470/V6, the ICL 2900, the Itel AS/6, */ +/* the Xerox Sigma 5/7/9 and the Sel systems 85/86. */ + +/* data mcheps(1),mcheps(2) / z34100000, z00000000 / */ +/* data minmag(1),minmag(2) / z00100000, z00000000 / */ +/* data maxmag(1),maxmag(2) / z7fffffff, zffffffff / */ + +/* Machine constants for the Honeywell 600/6000 series. */ + +/* data mcheps(1),mcheps(2) / o606400000000, o000000000000 / */ +/* data minmag(1),minmag(2) / o402400000000, o000000000000 / */ +/* data maxmag(1),maxmag(2) / o376777777777, o777777777777 / */ + +/* Machine constants for the CDC 6000/7000 series. */ + +/* data mcheps(1) / 15614000000000000000b / */ +/* data mcheps(2) / 15010000000000000000b / */ + +/* data minmag(1) / 00604000000000000000b / */ +/* data minmag(2) / 00000000000000000000b / */ + +/* data maxmag(1) / 37767777777777777777b / */ +/* data maxmag(2) / 37167777777777777777b / */ + +/* Machine constants for the PDP-10 (KA processor). */ + +/* data mcheps(1),mcheps(2) / "114400000000, "000000000000 / */ +/* data minmag(1),minmag(2) / "033400000000, "000000000000 / */ +/* data maxmag(1),maxmag(2) / "377777777777, "344777777777 / */ + +/* Machine constants for the PDP-10 (KI processor). */ + +/* data mcheps(1),mcheps(2) / "104400000000, "000000000000 / */ +/* data minmag(1),minmag(2) / "000400000000, "000000000000 / */ +/* data maxmag(1),maxmag(2) / "377777777777, "377777777777 / */ + +/* Machine constants for the PDP-11. */ + +/* data mcheps(1),mcheps(2) / 9472, 0 / */ +/* data mcheps(3),mcheps(4) / 0, 0 / */ + +/* data minmag(1),minmag(2) / 128, 0 / */ +/* data minmag(3),minmag(4) / 0, 0 / */ + +/* data maxmag(1),maxmag(2) / 32767, -1 / */ +/* data maxmag(3),maxmag(4) / -1, -1 / */ + +/* Machine constants for the Burroughs 6700/7700 systems. */ + +/* data mcheps(1) / o1451000000000000 / */ +/* data mcheps(2) / o0000000000000000 / */ + +/* data minmag(1) / o1771000000000000 / */ +/* data minmag(2) / o7770000000000000 / */ + +/* data maxmag(1) / o0777777777777777 / */ +/* data maxmag(2) / o7777777777777777 / */ + +/* Machine constants for the Burroughs 5700 system. */ + +/* data mcheps(1) / o1451000000000000 / */ +/* data mcheps(2) / o0000000000000000 / */ + +/* data minmag(1) / o1771000000000000 / */ +/* data minmag(2) / o0000000000000000 / */ + +/* data maxmag(1) / o0777777777777777 / */ +/* data maxmag(2) / o0007777777777777 / */ + +/* Machine constants for the Burroughs 1700 system. */ + +/* data mcheps(1) / zcc6800000 / */ +/* data mcheps(2) / z000000000 / */ + +/* data minmag(1) / zc00800000 / */ +/* data minmag(2) / z000000000 / */ + +/* data maxmag(1) / zdffffffff / */ +/* data maxmag(2) / zfffffffff / */ + +/* Machine constants for the Univac 1100 series. */ + +/* data mcheps(1),mcheps(2) / o170640000000, o000000000000 / */ +/* data minmag(1),minmag(2) / o000040000000, o000000000000 / */ +/* data maxmag(1),maxmag(2) / o377777777777, o777777777777 / */ + +/* Machine constants for the Data General Eclipse S/200. */ + +/* Note - it may be appropriate to include the following card - */ +/* static dmach(3) */ + +/* data minmag/20k,3*0/,maxmag/77777k,3*177777k/ */ +/* data mcheps/32020k,3*0/ */ + +/* Machine constants for the Harris 220. */ + +/* data mcheps(1),mcheps(2) / '20000000, '00000334 / */ +/* data minmag(1),minmag(2) / '20000000, '00000201 / */ +/* data maxmag(1),maxmag(2) / '37777777, '37777577 / */ + +/* Machine constants for the Cray-1. */ + +/* data mcheps(1) / 0376424000000000000000b / */ +/* data mcheps(2) / 0000000000000000000000b / */ + +/* data minmag(1) / 0200034000000000000000b / */ +/* data minmag(2) / 0000000000000000000000b / */ + +/* data maxmag(1) / 0577777777777777777777b / */ +/* data maxmag(2) / 0000007777777777777776b / */ + +/* Machine constants for the Prime 400. */ + +/* data mcheps(1),mcheps(2) / :10000000000, :00000000123 / */ +/* data minmag(1),minmag(2) / :10000000000, :00000100000 / */ +/* data maxmag(1),maxmag(2) / :17777777777, :37777677776 / */ + +/* Machine constants for the VAX-11. */ + +/* data mcheps(1),mcheps(2) / 9472, 0 / */ +/* data minmag(1),minmag(2) / 128, 0 / */ +/* data maxmag(1),maxmag(2) / -32769, -1 / */ + +/* Machine constants for IEEE machines. */ + +/* data dmach(1) /2.22044604926d-16/ */ +/* data dmach(2) /2.22507385852d-308/ */ +/* data dmach(3) /1.79769313485d+308/ */ + + switch(i) { + case 1: + return DPMPAR(real_mp,EPSILON); /* 2.2204460492503131e-16 | 1.19209290e-07F */ + case 2: + return DPMPAR(real_mp,MIN); /* 2.2250738585072014e-308 | 1.17549435e-38F */ + default: + return DPMPAR(real_mp,MAX); /* 1.7976931348623157e+308 | 3.40282347e+38F */ + } + +/* Last card of function dpmpar. */ + +} /* dpmpar_ */ + +#undef mcheps +#undef maxmag +#undef minmag +#undef dmach + + diff --git a/OpenFAST/modules/map/src/cminpack/enorm.c b/OpenFAST/modules/map/src/cminpack/enorm.c new file mode 100644 index 000000000..a93f099d7 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/enorm.c @@ -0,0 +1,157 @@ +#include "cminpack.h" +#include <math.h> +#include "cminpackP.h" + +/* + About the values for rdwarf and rgiant. + + The original values, both in signe-precision FORTRAN source code and in double-precision code were: +#define rdwarf 3.834e-20 +#define rgiant 1.304e19 + See for example: + http://www.netlib.org/slatec/src/denorm.f + http://www.netlib.org/slatec/src/enorm.f + However, rdwarf is smaller than sqrt(FLT_MIN) = 1.0842021724855044e-19, so that rdwarf**2 will + underflow. This contradicts the constraints expressed in the comments below. + + We changed these constants to be sqrt(dpmpar(2))*0.9 and sqrt(dpmpar(3))*0.9, as proposed by the + implementation found in MPFIT http://cow.physics.wisc.edu/~craigm/idl/fitting.html +*/ + +#define double_dwarf (1.4916681462400413e-154*0.9) +#define double_giant (1.3407807929942596e+154*0.9) +#define float_dwarf (1.0842021724855044e-19f*0.9f) +#define float_giant (1.8446743523953730e+19f*0.9f) +#define half_dwarf (2.4414062505039999e-4f*0.9f) +#define half_giant (255.93749236874225497222f*0.9f) + +#define dwarf(type) _dwarf(type) +#define _dwarf(type) type ## _dwarf +#define giant(type) _giant(type) +#define _giant(type) type ## _giant + +#define rdwarf dwarf(real_mp) +#define rgiant giant(real_mp) + +__cminpack_attr__ +real_mp __cminpack_func__(enorm)(int n, const real_mp *x) +{ +#ifdef USE_CBLAS + return cblas_dnrm2(n, x, 1); +#else /* !USE_CBLAS */ + /* System generated locals */ + real_mp ret_val, d1; + + /* Local variables */ + int i; + real_mp s1, s2, s3, xabs, x1max, x3max, agiant, floatn; + +/* ********** */ + +/* function enorm */ + +/* given an n-vector x, this function calculates the */ +/* euclidean norm of x. */ + +/* the euclidean norm is computed by accumulating the sum of */ +/* squares in three different sums. the sums of squares for the */ +/* small and large components are scaled so that no overflows */ +/* occur. non-destructive underflows are permitted. underflows */ +/* and overflows do not occur in the computation of the unscaled */ +/* sum of squares for the intermediate components. */ +/* the definitions of small, intermediate and large components */ +/* depend on two constants, rdwarf and rgiant. the main */ +/* restrictions on these constants are that rdwarf**2 not */ +/* underflow and rgiant**2 not overflow. the constants */ +/* given here are suitable for every known computer. */ + +/* the function statement is */ + +/* double precision function enorm(n,x) */ + +/* where */ + +/* n is a positive integer input variable. */ + +/* x is an input array of length n. */ + +/* subprograms called */ + +/* fortran-supplied ... dabs,dsqrt */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + + s1 = 0.; + s2 = 0.; + s3 = 0.; + x1max = 0.; + x3max = 0.; + floatn = (real_mp) (n); + agiant = rgiant / floatn; + for (i = 0; i < n; ++i) { + xabs = fabs(x[i]); + if (xabs <= rdwarf || xabs >= agiant) { + if (xabs > rdwarf) { + +/* sum for large components. */ + + if (xabs > x1max) { + /* Computing 2nd power */ + d1 = x1max / xabs; + s1 = 1. + s1 * (d1 * d1); + x1max = xabs; + } else { + /* Computing 2nd power */ + d1 = xabs / x1max; + s1 += d1 * d1; + } + } else { + +/* sum for small components. */ + + if (xabs > x3max) { + /* Computing 2nd power */ + d1 = x3max / xabs; + s3 = 1. + s3 * (d1 * d1); + x3max = xabs; + } else { + if (xabs != 0.) { + /* Computing 2nd power */ + d1 = xabs / x3max; + s3 += d1 * d1; + } + } + } + } else { + +/* sum for intermediate components. */ + + /* Computing 2nd power */ + s2 += xabs * xabs; + } + } + +/* calculation of norm. */ + + if (s1 != 0.) { + ret_val = x1max * sqrt(s1 + (s2 / x1max) / x1max); + } else { + if (s2 != 0.) { + if (s2 >= x3max) { + ret_val = sqrt(s2 * (1. + (x3max / s2) * (x3max * s3))); + } else { + ret_val = sqrt(x3max * ((s2 / x3max) + (x3max * s3))); + } + } else { + ret_val = x3max * sqrt(s3); + } + } + return ret_val; + +/* last card of function enorm. */ +#endif /* !USE_CBLAS */ +} /* enorm_ */ + diff --git a/OpenFAST/modules/map/src/cminpack/enorm_u.c b/OpenFAST/modules/map/src/cminpack/enorm_u.c new file mode 100644 index 000000000..3aaefb1d1 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/enorm_u.c @@ -0,0 +1,186 @@ +/* enorm.f -- translated by f2c (version 20020621). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "minpack.h" +#include <math.h> +#define real_mp __minpack_real__ + +/* + About the values for rdwarf and rgiant. + + The original values, both in single-precision FORTRAN source code and in double-precision code were: +#define rdwarf 3.834e-20 +#define rgiant 1.304e19 + See for example: + http://www.netlib.org/slatec/src/denorm.f + http://www.netlib.org/slatec/src/enorm.f + However, rdwarf is smaller than sqrt(FLT_MIN) = 1.0842021724855044e-19, so that rdwarf**2 will + underflow. This contradicts the constraints expressed in the comments below. + + We changed these constants to be sqrt(TYPE_MIN)*0.9 and sqrt(TYPE_MAX)*0.9, as proposed by the + implementation found in MPFIT: http://cow.physics.wisc.edu/~craigm/idl/fitting.html +*/ + +#define double_dwarf (1.4916681462400413e-154*0.9) +#define double_giant (1.3407807929942596e+154*0.9) +#define float_dwarf (1.0842021724855044e-19f*0.9f) +#define float_giant (1.8446743523953730e+19f*0.9f) +#define half_dwarf (2.4414062505039999e-4f*0.9f) +#define half_giant (255.93749236874225497222f*0.9f) + +#define dwarf(type) _dwarf(type) +#define _dwarf(type) type ## _dwarf +#define giant(type) _giant(type) +#define _giant(type) type ## _giant + +#define rdwarf dwarf(real_mp) +#define rgiant giant(real_mp) + +__minpack_attr__ +real_mp __minpack_func__(enorm)(const int *n, const real_mp *x) +{ + /* System generated locals */ + int i__1; + real_mp ret_val, d__1; + + /* Local variables */ + int i__; + real_mp s1, s2, s3, xabs, x1max, x3max, agiant, floatn; + +/* ********** */ + +/* function enorm */ + +/* given an n-vector x, this function calculates the */ +/* euclidean norm of x. */ + +/* the euclidean norm is computed by accumulating the sum of */ +/* squares in three different sums. the sums of squares for the */ +/* small and large components are scaled so that no overflows */ +/* occur. non-destructive underflows are permitted. underflows */ +/* and overflows do not occur in the computation of the unscaled */ +/* sum of squares for the intermediate components. */ +/* the definitions of small, intermediate and large components */ +/* depend on two constants, rdwarf and rgiant. the main */ +/* restrictions on these constants are that rdwarf**2 not */ +/* underflow and rgiant**2 not overflow. the constants */ +/* given here are suitable for every known computer. */ + +/* the function statement is */ + +/* double precision function enorm(n,x) */ + +/* where */ + +/* n is a positive integer input variable. */ + +/* x is an input array of length n. */ + +/* subprograms called */ + +/* fortran-supplied ... dabs,dsqrt */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + /* Parameter adjustments */ + --x; + + /* Function Body */ + s1 = 0.; + s2 = 0.; + s3 = 0.; + x1max = 0.; + x3max = 0.; + floatn = (real_mp) (*n); + agiant = rgiant / floatn; + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + xabs = fabs(x[i__]); + if (xabs > rdwarf && xabs < agiant) { + goto L70; + } + if (xabs <= rdwarf) { + goto L30; + } + +/* sum for large components. */ + + if (xabs <= x1max) { + goto L10; + } +/* Computing 2nd power */ + d__1 = x1max / xabs; + s1 = 1. + s1 * (d__1 * d__1); + x1max = xabs; + goto L20; +L10: +/* Computing 2nd power */ + d__1 = xabs / x1max; + s1 += d__1 * d__1; +L20: + goto L60; +L30: + +/* sum for small components. */ + + if (xabs <= x3max) { + goto L40; + } +/* Computing 2nd power */ + d__1 = x3max / xabs; + s3 = 1. + s3 * (d__1 * d__1); + x3max = xabs; + goto L50; +L40: + if (xabs != 0.) { +/* Computing 2nd power */ + d__1 = xabs / x3max; + s3 += d__1 * d__1; + } +L50: +L60: + goto L80; +L70: + +/* sum for intermediate components. */ + +/* Computing 2nd power */ + d__1 = xabs; + s2 += d__1 * d__1; +L80: +/* L90: */ + ; + } + +/* calculation of norm. */ + + if (s1 == 0.) { + goto L100; + } + ret_val = x1max * sqrt(s1 + s2 / x1max / x1max); + goto L130; +L100: + if (s2 == 0.) { + goto L110; + } + if (s2 >= x3max) { + ret_val = sqrt(s2 * (1. + x3max / s2 * (x3max * s3))); + } + if (s2 < x3max) { + ret_val = sqrt(x3max * (s2 / x3max + x3max * s3)); + } + goto L120; +L110: + ret_val = x3max * sqrt(s3); +L120: +L130: + return ret_val; + +/* last card of function enorm. */ + +} /* enorm_ */ + diff --git a/OpenFAST/modules/map/src/cminpack/lmder.c b/OpenFAST/modules/map/src/cminpack/lmder.c new file mode 100644 index 000000000..32ee504cc --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/lmder.c @@ -0,0 +1,526 @@ +#include "cminpack.h" +#include <math.h> +#include "cminpackP.h" + +__cminpack_attr__ +int __cminpack_func__(lmder)(__cminpack_decl_fcnder_mn__ void *p, int m, int n, real_mp *x, + real_mp *fvec, real_mp *fjac, int ldfjac, real_mp ftol, + real_mp xtol, real_mp gtol, int maxfev, real_mp * + diag, int mode, real_mp factor, int nprint, + int *nfev, int *njev, int *ipvt, real_mp *qtf, + real_mp *wa1, real_mp *wa2, real_mp *wa3, real_mp *wa4) +{ + /* Initialized data */ + +#define p1 .1 +#define p5 .5 +#define p25 .25 +#define p75 .75 +#define p0001 1e-4 + + /* System generated locals */ + real_mp d1, d2; + + /* Local variables */ + int i, j, l; + real_mp par, sum; + int iter; + real_mp temp, temp1, temp2; + int iflag; + real_mp delta = 0.; + real_mp ratio; + real_mp fnorm, gnorm, pnorm, xnorm = 0., fnorm1, actred, dirder, + epsmch, prered; + int info; + +/* ********** */ + +/* subroutine lmder */ + +/* the purpose of lmder is to minimize the sum of the squares of */ +/* m nonlinear functions in n variables by a modification of */ +/* the levenberg-marquardt algorithm. the user must provide a */ +/* subroutine which calculates the functions and the jacobian. */ + +/* the subroutine statement is */ + +/* subroutine lmder(fcn,m,n,x,fvec,fjac,ldfjac,ftol,xtol,gtol, */ +/* maxfev,diag,mode,factor,nprint,info,nfev, */ +/* njev,ipvt,qtf,wa1,wa2,wa3,wa4) */ + +/* where */ + +/* fcn is the name of the user-supplied subroutine which */ +/* calculates the functions and the jacobian. fcn must */ +/* be declared in an external statement in the user */ +/* calling program, and should be written as follows. */ + +/* subroutine fcn(m,n,x,fvec,fjac,ldfjac,iflag) */ +/* integer m,n,ldfjac,iflag */ +/* double precision x(n),fvec(m),fjac(ldfjac,n) */ +/* ---------- */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. do not alter fjac. */ +/* if iflag = 2 calculate the jacobian at x and */ +/* return this matrix in fjac. do not alter fvec. */ +/* ---------- */ +/* return */ +/* end */ + +/* the value of iflag should not be changed by fcn unless */ +/* the user wants to terminate execution of lmder. */ +/* in this case set iflag to a negative integer. */ + +/* m is a positive integer input variable set to the number */ +/* of functions. */ + +/* n is a positive integer input variable set to the number */ +/* of variables. n must not exceed m. */ + +/* x is an array of length n. on input x must contain */ +/* an initial estimate of the solution vector. on output x */ +/* contains the final estimate of the solution vector. */ + +/* fvec is an output array of length m which contains */ +/* the functions evaluated at the output x. */ + +/* fjac is an output m by n array. the upper n by n submatrix */ +/* of fjac contains an upper triangular matrix r with */ +/* diagonal elements of nonincreasing magnitude such that */ + +/* t t t */ +/* p *(jac *jac)*p = r *r, */ + +/* where p is a permutation matrix and jac is the final */ +/* calculated jacobian. column j of p is column ipvt(j) */ +/* (see below) of the identity matrix. the lower trapezoidal */ +/* part of fjac contains information generated during */ +/* the computation of r. */ + +/* ldfjac is a positive integer input variable not less than m */ +/* which specifies the leading dimension of the array fjac. */ + +/* ftol is a nonnegative input variable. termination */ +/* occurs when both the actual and predicted relative */ +/* reductions in the sum of squares are at most ftol. */ +/* therefore, ftol measures the relative error desired */ +/* in the sum of squares. */ + +/* xtol is a nonnegative input variable. termination */ +/* occurs when the relative error between two consecutive */ +/* iterates is at most xtol. therefore, xtol measures the */ +/* relative error desired in the approximate solution. */ + +/* gtol is a nonnegative input variable. termination */ +/* occurs when the cosine of the angle between fvec and */ +/* any column of the jacobian is at most gtol in absolute */ +/* value. therefore, gtol measures the orthogonality */ +/* desired between the function vector and the columns */ +/* of the jacobian. */ + +/* maxfev is a positive integer input variable. termination */ +/* occurs when the number of calls to fcn with iflag = 1 */ +/* has reached maxfev. */ + +/* diag is an array of length n. if mode = 1 (see */ +/* below), diag is internally set. if mode = 2, diag */ +/* must contain positive entries that serve as */ +/* multiplicative scale factors for the variables. */ + +/* mode is an integer input variable. if mode = 1, the */ +/* variables will be scaled internally. if mode = 2, */ +/* the scaling is specified by the input diag. other */ +/* values of mode are equivalent to mode = 1. */ + +/* factor is a positive input variable used in determining the */ +/* initial step bound. this bound is set to the product of */ +/* factor and the euclidean norm of diag*x if nonzero, or else */ +/* to factor itself. in most cases factor should lie in the */ +/* interval (.1,100.).100. is a generally recommended value. */ + +/* nprint is an integer input variable that enables controlled */ +/* printing of iterates if it is positive. in this case, */ +/* fcn is called with iflag = 0 at the beginning of the first */ +/* iteration and every nprint iterations thereafter and */ +/* immediately prior to return, with x, fvec, and fjac */ +/* available for printing. fvec and fjac should not be */ +/* altered. if nprint is not positive, no special calls */ +/* of fcn with iflag = 0 are made. */ + +/* info is an integer output variable. if the user has */ +/* terminated execution, info is set to the (negative) */ +/* value of iflag. see description of fcn. otherwise, */ +/* info is set as follows. */ + +/* info = 0 improper input parameters. */ + +/* info = 1 both actual and predicted relative reductions */ +/* in the sum of squares are at most ftol. */ + +/* info = 2 relative error between two consecutive iterates */ +/* is at most xtol. */ + +/* info = 3 conditions for info = 1 and info = 2 both hold. */ + +/* info = 4 the cosine of the angle between fvec and any */ +/* column of the jacobian is at most gtol in */ +/* absolute value. */ + +/* info = 5 number of calls to fcn with iflag = 1 has */ +/* reached maxfev. */ + +/* info = 6 ftol is too small. no further reduction in */ +/* the sum of squares is possible. */ + +/* info = 7 xtol is too small. no further improvement in */ +/* the approximate solution x is possible. */ + +/* info = 8 gtol is too small. fvec is orthogonal to the */ +/* columns of the jacobian to machine precision. */ + +/* nfev is an integer output variable set to the number of */ +/* calls to fcn with iflag = 1. */ + +/* njev is an integer output variable set to the number of */ +/* calls to fcn with iflag = 2. */ + +/* ipvt is an integer output array of length n. ipvt */ +/* defines a permutation matrix p such that jac*p = q*r, */ +/* where jac is the final calculated jacobian, q is */ +/* orthogonal (not stored), and r is upper triangular */ +/* with diagonal elements of nonincreasing magnitude. */ +/* column j of p is column ipvt(j) of the identity matrix. */ + +/* qtf is an output array of length n which contains */ +/* the first n elements of the vector (q transpose)*fvec. */ + +/* wa1, wa2, and wa3 are work arrays of length n. */ + +/* wa4 is a work array of length m. */ + +/* subprograms called */ + +/* user-supplied ...... fcn */ + +/* minpack-supplied ... dpmpar,enorm,lmpar,qrfac */ + +/* fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + +/* epsmch is the machine precision. */ + + epsmch = __cminpack_func__(dpmpar)(1); + + info = 0; + iflag = 0; + *nfev = 0; + *njev = 0; + +/* check the input parameters for errors. */ + + if (n <= 0 || m < n || ldfjac < m || ftol < 0. || xtol < 0. || + gtol < 0. || maxfev <= 0 || factor <= 0.) { + goto TERMINATE; + } + if (mode == 2) { + for (j = 0; j < n; ++j) { + if (diag[j] <= 0.) { + goto TERMINATE; + } + } + } + +/* evaluate the function at the starting point */ +/* and calculate its norm. */ + + iflag = fcnder_mn(p, m, n, x, fvec, fjac, ldfjac, 1); + *nfev = 1; + if (iflag < 0) { + goto TERMINATE; + } + fnorm = __cminpack_enorm__(m, fvec); + +/* initialize levenberg-marquardt parameter and iteration counter. */ + + par = 0.; + iter = 1; + +/* beginning of the outer loop. */ + + for (;;) { + +/* calculate the jacobian matrix. */ + + iflag = fcnder_mn(p, m, n, x, fvec, fjac, ldfjac, 2); + ++(*njev); + if (iflag < 0) { + goto TERMINATE; + } + +/* if requested, call fcn to enable printing of iterates. */ + + if (nprint > 0) { + iflag = 0; + if ((iter - 1) % nprint == 0) { + iflag = fcnder_mn(p, m, n, x, fvec, fjac, ldfjac, 0); + } + if (iflag < 0) { + goto TERMINATE; + } + } + +/* compute the qr factorization of the jacobian. */ + + __cminpack_func__(qrfac)(m, n, fjac, ldfjac, TRUE_, ipvt, n, + wa1, wa2, wa3); + +/* on the first iteration and if mode is 1, scale according */ +/* to the norms of the columns of the initial jacobian. */ + + if (iter == 1) { + if (mode != 2) { + for (j = 0; j < n; ++j) { + diag[j] = wa2[j]; + if (wa2[j] == 0.) { + diag[j] = 1.; + } + } + } + +/* on the first iteration, calculate the norm of the scaled x */ +/* and initialize the step bound delta. */ + + for (j = 0; j < n; ++j) { + wa3[j] = diag[j] * x[j]; + } + xnorm = __cminpack_enorm__(n, wa3); + delta = factor * xnorm; + if (delta == 0.) { + delta = factor; + } + } + +/* form (q transpose)*fvec and store the first n components in */ +/* qtf. */ + + for (i = 0; i < m; ++i) { + wa4[i] = fvec[i]; + } + for (j = 0; j < n; ++j) { + if (fjac[j + j * ldfjac] != 0.) { + sum = 0.; + for (i = j; i < m; ++i) { + sum += fjac[i + j * ldfjac] * wa4[i]; + } + temp = -sum / fjac[j + j * ldfjac]; + for (i = j; i < m; ++i) { + wa4[i] += fjac[i + j * ldfjac] * temp; + } + } + fjac[j + j * ldfjac] = wa1[j]; + qtf[j] = wa4[j]; + } + +/* compute the norm of the scaled gradient. */ + + gnorm = 0.; + if (fnorm != 0.) { + for (j = 0; j < n; ++j) { + l = ipvt[j]-1; + if (wa2[l] != 0.) { + sum = 0.; + for (i = 0; i <= j; ++i) { + sum += fjac[i + j * ldfjac] * (qtf[i] / fnorm); + } + /* Computing MAX */ + d1 = fabs(sum / wa2[l]); + gnorm = minpack_max(gnorm,d1); + } + } + } + +/* test for convergence of the gradient norm. */ + + if (gnorm <= gtol) { + info = 4; + } + if (info != 0) { + goto TERMINATE; + } + +/* rescale if necessary. */ + + if (mode != 2) { + for (j = 0; j < n; ++j) { + /* Computing MAX */ + d1 = diag[j], d2 = wa2[j]; + diag[j] = minpack_max(d1,d2); + } + } + +/* beginning of the inner loop. */ + + do { + +/* determine the levenberg-marquardt parameter. */ + + __cminpack_func__(lmpar)(n, fjac, ldfjac, ipvt, diag, qtf, delta, + &par, wa1, wa2, wa3, wa4); + +/* store the direction p and x + p. calculate the norm of p. */ + + for (j = 0; j < n; ++j) { + wa1[j] = -wa1[j]; + wa2[j] = x[j] + wa1[j]; + wa3[j] = diag[j] * wa1[j]; + } + pnorm = __cminpack_enorm__(n, wa3); + +/* on the first iteration, adjust the initial step bound. */ + + if (iter == 1) { + delta = minpack_min(delta,pnorm); + } + +/* evaluate the function at x + p and calculate its norm. */ + + iflag = fcnder_mn(p, m, n, wa2, wa4, fjac, ldfjac, 1); + ++(*nfev); + if (iflag < 0) { + goto TERMINATE; + } + fnorm1 = __cminpack_enorm__(m, wa4); + +/* compute the scaled actual reduction. */ + + actred = -1.; + if (p1 * fnorm1 < fnorm) { + /* Computing 2nd power */ + d1 = fnorm1 / fnorm; + actred = 1. - d1 * d1; + } + +/* compute the scaled predicted reduction and */ +/* the scaled directional derivative. */ + + for (j = 0; j < n; ++j) { + wa3[j] = 0.; + l = ipvt[j]-1; + temp = wa1[l]; + for (i = 0; i <= j; ++i) { + wa3[i] += fjac[i + j * ldfjac] * temp; + } + } + temp1 = __cminpack_enorm__(n, wa3) / fnorm; + temp2 = (sqrt(par) * pnorm) / fnorm; + prered = temp1 * temp1 + temp2 * temp2 / p5; + dirder = -(temp1 * temp1 + temp2 * temp2); + +/* compute the ratio of the actual to the predicted */ +/* reduction. */ + + ratio = 0.; + if (prered != 0.) { + ratio = actred / prered; + } + +/* update the step bound. */ + + if (ratio <= p25) { + if (actred >= 0.) { + temp = p5; + } else { + temp = p5 * dirder / (dirder + p5 * actred); + } + if (p1 * fnorm1 >= fnorm || temp < p1) { + temp = p1; + } + /* Computing MIN */ + d1 = pnorm / p1; + delta = temp * minpack_min(delta,d1); + par /= temp; + } else { + if (par == 0. || ratio >= p75) { + delta = pnorm / p5; + par = p5 * par; + } + } + +/* test for successful iteration. */ + + if (ratio >= p0001) { + +/* successful iteration. update x, fvec, and their norms. */ + + for (j = 0; j < n; ++j) { + x[j] = wa2[j]; + wa2[j] = diag[j] * x[j]; + } + for (i = 0; i < m; ++i) { + fvec[i] = wa4[i]; + } + xnorm = __cminpack_enorm__(n, wa2); + fnorm = fnorm1; + ++iter; + } + +/* tests for convergence. */ + + if (fabs(actred) <= ftol && prered <= ftol && p5 * ratio <= 1.) { + info = 1; + } + if (delta <= xtol * xnorm) { + info = 2; + } + if (fabs(actred) <= ftol && prered <= ftol && p5 * ratio <= 1. && info == 2) { + info = 3; + } + if (info != 0) { + goto TERMINATE; + } + +/* tests for termination and stringent tolerances. */ + + if (*nfev >= maxfev) { + info = 5; + } + if (fabs(actred) <= epsmch && prered <= epsmch && p5 * ratio <= 1.) { + info = 6; + } + if (delta <= epsmch * xnorm) { + info = 7; + } + if (gnorm <= epsmch) { + info = 8; + } + if (info != 0) { + goto TERMINATE; + } + +/* end of the inner loop. repeat if iteration unsuccessful. */ + + } while (ratio < p0001); + +/* end of the outer loop. */ + + } +TERMINATE: + +/* termination, either normal or user imposed. */ + + if (iflag < 0) { + info = iflag; + } + if (nprint > 0) { + fcnder_mn(p, m, n, x, fvec, fjac, ldfjac, 0); + } + return info; + +/* last card of subroutine lmder. */ + +} /* lmder_ */ + diff --git a/OpenFAST/modules/map/src/cminpack/lmpar.c b/OpenFAST/modules/map/src/cminpack/lmpar.c new file mode 100644 index 000000000..4f1fecb08 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/lmpar.c @@ -0,0 +1,338 @@ +/* lmpar.f -- translated by f2c (version 20020621). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "cminpack.h" +#include <math.h> +#include "cminpackP.h" + +__cminpack_attr__ +void __cminpack_func__(lmpar)(int n, real_mp *r, int ldr, + const int *ipvt, const real_mp *diag, const real_mp *qtb, real_mp delta, + real_mp *par, real_mp *x, real_mp *sdiag, real_mp *wa1, + real_mp *wa2) +{ + /* Initialized data */ + +#define p1 .1 +#define p001 .001 + + /* System generated locals */ + real_mp d1, d2; + + /* Local variables */ + int j, l; + real_mp fp; + real_mp parc, parl; + int iter; + real_mp temp, paru, dwarf; + int nsing; + real_mp gnorm; + real_mp dxnorm; + +/* ********** */ + +/* subroutine lmpar */ + +/* given an m by n matrix a, an n by n nonsingular diagonal */ +/* matrix d, an m-vector b, and a positive number delta, */ +/* the problem is to determine a value for the parameter */ +/* par such that if x solves the system */ + +/* a*x = b , sqrt(par)*d*x = 0 , */ + +/* in the least squares sense, and dxnorm is the euclidean */ +/* norm of d*x, then either par is zero and */ + +/* (dxnorm-delta) .le. 0.1*delta , */ + +/* or par is positive and */ + +/* abs(dxnorm-delta) .le. 0.1*delta . */ + +/* this subroutine completes the solution of the problem */ +/* if it is provided with the necessary information from the */ +/* qr factorization, with column pivoting, of a. that is, if */ +/* a*p = q*r, where p is a permutation matrix, q has orthogonal */ +/* columns, and r is an upper triangular matrix with diagonal */ +/* elements of nonincreasing magnitude, then lmpar expects */ +/* the full upper triangle of r, the permutation matrix p, */ +/* and the first n components of (q transpose)*b. on output */ +/* lmpar also provides an upper triangular matrix s such that */ + +/* t t t */ +/* p *(a *a + par*d*d)*p = s *s . */ + +/* s is employed within lmpar and may be of separate interest. */ + +/* only a few iterations are generally needed for convergence */ +/* of the algorithm. if, however, the limit of 10 iterations */ +/* is reached, then the output par will contain the best */ +/* value obtained so far. */ + +/* the subroutine statement is */ + +/* subroutine lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag, */ +/* wa1,wa2) */ + +/* where */ + +/* n is a positive integer input variable set to the order of r. */ + +/* r is an n by n array. on input the full upper triangle */ +/* must contain the full upper triangle of the matrix r. */ +/* on output the full upper triangle is unaltered, and the */ +/* strict lower triangle contains the strict upper triangle */ +/* (transposed) of the upper triangular matrix s. */ + +/* ldr is a positive integer input variable not less than n */ +/* which specifies the leading dimension of the array r. */ + +/* ipvt is an integer input array of length n which defines the */ +/* permutation matrix p such that a*p = q*r. column j of p */ +/* is column ipvt(j) of the identity matrix. */ + +/* diag is an input array of length n which must contain the */ +/* diagonal elements of the matrix d. */ + +/* qtb is an input array of length n which must contain the first */ +/* n elements of the vector (q transpose)*b. */ + +/* delta is a positive input variable which specifies an upper */ +/* bound on the euclidean norm of d*x. */ + +/* par is a nonnegative variable. on input par contains an */ +/* initial estimate of the levenberg-marquardt parameter. */ +/* on output par contains the final estimate. */ + +/* x is an output array of length n which contains the least */ +/* squares solution of the system a*x = b, sqrt(par)*d*x = 0, */ +/* for the output par. */ + +/* sdiag is an output array of length n which contains the */ +/* diagonal elements of the upper triangular matrix s. */ + +/* wa1 and wa2 are work arrays of length n. */ + +/* subprograms called */ + +/* minpack-supplied ... dpmpar,enorm,qrsolv */ + +/* fortran-supplied ... dabs,dmax1,dmin1,dsqrt */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + +/* dwarf is the smallest positive magnitude. */ + + dwarf = __cminpack_func__(dpmpar)(2); + +/* compute and store in x the gauss-newton direction. if the */ +/* jacobian is rank-deficient, obtain a least squares solution. */ + + nsing = n; + for (j = 0; j < n; ++j) { + wa1[j] = qtb[j]; + if (r[j + j * ldr] == 0. && nsing == n) { + nsing = j; + } + if (nsing < n) { + wa1[j] = 0.; + } + } +# ifdef USE_CBLAS + cblas_dtrsv(CblasColMajor, CblasUpper, CblasNoTrans, CblasNonUnit, nsing, r, ldr, wa1, 1); +# else + if (nsing >= 1) { + int k; + for (k = 1; k <= nsing; ++k) { + j = nsing - k; + wa1[j] /= r[j + j * ldr]; + temp = wa1[j]; + if (j >= 1) { + int i; + for (i = 0; i < j; ++i) { + wa1[i] -= r[i + j * ldr] * temp; + } + } + } + } +# endif + for (j = 0; j < n; ++j) { + l = ipvt[j]-1; + x[l] = wa1[j]; + } + +/* initialize the iteration counter. */ +/* evaluate the function at the origin, and test */ +/* for acceptance of the gauss-newton direction. */ + + iter = 0; + for (j = 0; j < n; ++j) { + wa2[j] = diag[j] * x[j]; + } + dxnorm = __cminpack_enorm__(n, wa2); + fp = dxnorm - delta; + if (fp <= p1 * delta) { + goto TERMINATE; + } + +/* if the jacobian is not rank deficient, the newton */ +/* step provides a lower bound, parl, for the zero of */ +/* the function. otherwise set this bound to zero. */ + + parl = 0.; + if (nsing >= n) { + for (j = 0; j < n; ++j) { + l = ipvt[j]-1; + wa1[j] = diag[l] * (wa2[l] / dxnorm); + } +# ifdef USE_CBLAS + cblas_dtrsv(CblasColMajor, CblasUpper, CblasTrans, CblasNonUnit, n, r, ldr, wa1, 1); +# else + for (j = 0; j < n; ++j) { + real_mp sum = 0.; + if (j >= 1) { + int i; + for (i = 0; i < j; ++i) { + sum += r[i + j * ldr] * wa1[i]; + } + } + wa1[j] = (wa1[j] - sum) / r[j + j * ldr]; + } +# endif + temp = __cminpack_enorm__(n, wa1); + parl = fp / delta / temp / temp; + } + +/* calculate an upper bound, paru, for the zero of the function. */ + + for (j = 0; j < n; ++j) { + real_mp sum; +# ifdef USE_CBLAS + sum = cblas_ddot(j+1, &r[j*ldr], 1, qtb, 1); +# else + int i; + sum = 0.; + for (i = 0; i <= j; ++i) { + sum += r[i + j * ldr] * qtb[i]; + } +# endif + l = ipvt[j]-1; + wa1[j] = sum / diag[l]; + } + gnorm = __cminpack_enorm__(n, wa1); + paru = gnorm / delta; + if (paru == 0.) { + paru = dwarf / minpack_min(delta,(real_mp)p1) /* / p001 ??? */; + } + +/* if the input par lies outside of the interval (parl,paru), */ +/* set par to the closer endpoint. */ + + *par = minpack_max(*par,parl); + *par = minpack_min(*par,paru); + if (*par == 0.) { + *par = gnorm / dxnorm; + } + +/* beginning of an iteration. */ + + for (;;) { + ++iter; + +/* evaluate the function at the current value of par. */ + + if (*par == 0.) { + /* Computing MAX */ + d1 = dwarf, d2 = p001 * paru; + *par = minpack_max(d1,d2); + } + temp = sqrt(*par); + for (j = 0; j < n; ++j) { + wa1[j] = temp * diag[j]; + } + __cminpack_func__(qrsolv)(n, r, ldr, ipvt, wa1, qtb, x, sdiag, wa2); + for (j = 0; j < n; ++j) { + wa2[j] = diag[j] * x[j]; + } + dxnorm = __cminpack_enorm__(n, wa2); + temp = fp; + fp = dxnorm - delta; + +/* if the function is small enough, accept the current value */ +/* of par. also test for the exceptional cases where parl */ +/* is zero or the number of iterations has reached 10. */ + + if (fabs(fp) <= p1 * delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10) { + goto TERMINATE; + } + +/* compute the newton correction. */ + +# ifdef USE_CBLAS + for (j = 0; j < nsing; ++j) { + l = ipvt[j]-1; + wa1[j] = diag[l] * (wa2[l] / dxnorm); + } + for (j = nsing; j < n; ++j) { + wa1[j] = 0.; + } + /* exchange the diagonal of r with sdiag */ + cblas_dswap(n, r, ldr+1, sdiag, 1); + /* solve lower(r).x = wa1, result id put in wa1 */ + cblas_dtrsv(CblasColMajor, CblasLower, CblasNoTrans, CblasNonUnit, nsing, r, ldr, wa1, 1); + /* exchange the diagonal of r with sdiag */ + cblas_dswap( n, r, ldr+1, sdiag, 1); +# else /* !USE_CBLAS */ + for (j = 0; j < n; ++j) { + l = ipvt[j]-1; + wa1[j] = diag[l] * (wa2[l] / dxnorm); + } + for (j = 0; j < n; ++j) { + wa1[j] /= sdiag[j]; + temp = wa1[j]; + if (n > j+1) { + int i; + for (i = j+1; i < n; ++i) { + wa1[i] -= r[i + j * ldr] * temp; + } + } + } +# endif /* !USE_CBLAS */ + temp = __cminpack_enorm__(n, wa1); + parc = fp / delta / temp / temp; + +/* depending on the sign of the function, update parl or paru. */ + + if (fp > 0.) { + parl = minpack_max(parl,*par); + } + if (fp < 0.) { + paru = minpack_min(paru,*par); + } + +/* compute an improved estimate for par. */ + + /* Computing MAX */ + d1 = parl, d2 = *par + parc; + *par = minpack_max(d1,d2); + +/* end of an iteration. */ + + } +TERMINATE: + +/* termination. */ + + if (iter == 0) { + *par = 0.; + } + +/* last card of subroutine lmpar. */ + +} /* lmpar_ */ + diff --git a/OpenFAST/modules/map/src/cminpack/minpack.h b/OpenFAST/modules/map/src/cminpack/minpack.h new file mode 100644 index 000000000..90f3c9a84 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/minpack.h @@ -0,0 +1,301 @@ +#ifndef __MINPACK_H__ +#define __MINPACK_H__ + +#include "cminpack.h" + +/* The default floating-point type is "double" for C/C++ and "float" for CUDA, + but you can change this by defining one of the following symbols when + compiling the library, and before including cminpack.h when using it: + __cminpack_double__ for double + __cminpack_float__ for float + __cminpack_half__ for half from the OpenEXR library (in this case, you must + compile cminpack with a C++ compiler) +*/ +#ifdef __cminpack_double__ +#define __minpack_func__(func) func ## _ +#endif + +#ifdef __cminpack_float__ +#define __minpack_func__(func) s ## func ## _ +#endif + +#ifdef __cminpack_half__ +#define __minpack_func__(func) h ## func ## _ +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MINPACK_EXPORT CMINPACK_EXPORT + +#define __minpack_real__ __cminpack_real__ +#define __minpack_attr__ __cminpack_attr__ +#if defined(__CUDA_ARCH__) || defined(__CUDACC__) +#define __minpack_type_fcn_nn__ __minpack_attr__ void fcn_nn +#define __minpack_type_fcnder_nn__ __minpack_attr__ void fcnder_nn +#define __minpack_type_fcn_mn__ __minpack_attr__ void fcn_mn +#define __minpack_type_fcnder_mn__ __minpack_attr__ void fcnder_mn +#define __minpack_type_fcnderstr_mn__ __minpack_attr__ void fcnderstr_mn +#define __minpack_decl_fcn_nn__ +#define __minpack_decl_fcnder_nn__ +#define __minpack_decl_fcn_mn__ +#define __minpack_decl_fcnder_mn__ +#define __minpack_decl_fcnderstr_mn__ +#define __minpack_param_fcn_nn__ +#define __minpack_param_fcnder_nn__ +#define __minpack_param_fcn_mn__ +#define __minpack_param_fcnder_mn__ +#define __minpack_param_fcnderstr_mn__ +#else +#define __minpack_type_fcn_nn__ typedef void (*minpack_func_nn) +#define __minpack_type_fcnder_nn__ typedef void (*minpack_funcder_nn) +#define __minpack_type_fcn_mn__ typedef void (*minpack_func_mn) +#define __minpack_type_fcnder_mn__ typedef void (*minpack_funcder_mn) +#define __minpack_type_fcnderstr_mn__ typedef void (*minpack_funcderstr_mn) +#define __minpack_decl_fcn_nn__ minpack_func_nn fcn_nn, +#define __minpack_decl_fcnder_nn__ minpack_funcder_nn fcnder_nn, +#define __minpack_decl_fcn_mn__ minpack_func_mn fcn_mn, +#define __minpack_decl_fcnder_mn__ minpack_funcder_mn fcnder_mn, +#define __minpack_decl_fcnderstr_mn__ minpack_funcderstr_mn fcnderstr_mn, +#define __minpack_param_fcn_nn__ fcn_nn, +#define __minpack_param_fcnder_nn__ fcnder_nn, +#define __minpack_param_fcn_mn__ fcn_mn, +#define __minpack_param_fcnder_mn__ fcnder_mn, +#define __minpack_param_fcnderstr_mn__ fcnderstr_mn, +#endif +#undef __cminpack_type_fcn_nn__ +#undef __cminpack_type_fcnder_nn__ +#undef __cminpack_type_fcn_mn__ +#undef __cminpack_type_fcnder_mn__ +#undef __cminpack_type_fcnderstr_mn__ +#undef __cminpack_decl_fcn_nn__ +#undef __cminpack_decl_fcnder_nn__ +#undef __cminpack_decl_fcn_mn__ +#undef __cminpack_decl_fcnder_mn__ +#undef __cminpack_decl_fcnderstr_mn__ +#undef __cminpack_param_fcn_nn__ +#undef __cminpack_param_fcnder_nn__ +#undef __cminpack_param_fcn_mn__ +#undef __cminpack_param_fcnder_mn__ +#undef __cminpack_param_fcnderstr_mn__ + +/* Declarations for minpack */ + +/* Function types: */ +/* the iflag parameter is input-only (with respect to the FORTRAN */ +/* version), the output iflag value is the return value of the function. */ +/* If iflag=0, the function shoulkd just print the current values (see */ +/* the nprint parameters below). */ + +/* for hybrd1 and hybrd: */ +/* calculate the functions at x and */ +/* return this vector in fvec. */ +/* return a negative value to terminate hybrd1/hybrd */ +__minpack_type_fcn_nn__(const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, int *iflag ); + +/* for hybrj1 and hybrj */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. do not alter fjac. */ +/* if iflag = 2 calculate the jacobian at x and */ +/* return this matrix in fjac. do not alter fvec. */ +/* return a negative value to terminate hybrj1/hybrj */ +__minpack_type_fcnder_nn__(const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjac, + const int *ldfjac, int *iflag ); + +/* for lmdif1 and lmdif */ +/* calculate the functions at x and */ +/* return this vector in fvec. */ +/* if iflag = 1 the result is used to compute the residuals. */ +/* if iflag = 2 the result is used to compute the Jacobian by finite differences. */ +/* Jacobian computation requires exactly n function calls with iflag = 2. */ +/* return a negative value to terminate lmdif1/lmdif */ +__minpack_type_fcn_mn__(const int *m, const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, + int *iflag ); + +/* for lmder1 and lmder */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. do not alter fjac. */ +/* if iflag = 2 calculate the jacobian at x and */ +/* return this matrix in fjac. do not alter fvec. */ +/* return a negative value to terminate lmder1/lmder */ +__minpack_type_fcnder_mn__(const int *m, const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, + __minpack_real__ *fjac, const int *ldfjac, int *iflag ); + +/* for lmstr1 and lmstr */ +/* if iflag = 1 calculate the functions at x and */ +/* return this vector in fvec. */ +/* if iflag = i calculate the (i-1)-st row of the */ +/* jacobian at x and return this vector in fjrow. */ +/* return a negative value to terminate lmstr1/lmstr */ +__minpack_type_fcnderstr_mn__(const int *m, const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, + __minpack_real__ *fjrow, int *iflag ); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (Jacobian calculated by + a forward-difference approximation) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(hybrd1)( __minpack_decl_fcn_nn__ + const int *n, __minpack_real__ *x, __minpack_real__ *fvec, const __minpack_real__ *tol, int *info, + __minpack_real__ *wa, const int *lwa ); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (Jacobian calculated by + a forward-difference approximation, more general). */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(hybrd)( __minpack_decl_fcn_nn__ + const int *n, __minpack_real__ *x, __minpack_real__ *fvec, const __minpack_real__ *xtol, const int *maxfev, + const int *ml, const int *mu, const __minpack_real__ *epsfcn, __minpack_real__ *diag, const int *mode, + const __minpack_real__ *factor, const int *nprint, int *info, int *nfev, + __minpack_real__ *fjac, const int *ldfjac, __minpack_real__ *r, const int *lr, __minpack_real__ *qtf, + __minpack_real__ *wa1, __minpack_real__ *wa2, __minpack_real__ *wa3, __minpack_real__ *wa4); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (user-supplied Jacobian) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(hybrj1)( __minpack_decl_fcnder_nn__ const int *n, __minpack_real__ *x, + __minpack_real__ *fvec, __minpack_real__ *fjec, const int *ldfjac, const __minpack_real__ *tol, + int *info, __minpack_real__ *wa, const int *lwa ); + +/* find a zero of a system of N nonlinear functions in N variables by + a modification of the Powell hybrid method (user-supplied Jacobian, + more general) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(hybrj)( __minpack_decl_fcnder_nn__ const int *n, __minpack_real__ *x, + __minpack_real__ *fvec, __minpack_real__ *fjec, const int *ldfjac, const __minpack_real__ *xtol, + const int *maxfev, __minpack_real__ *diag, const int *mode, const __minpack_real__ *factor, + const int *nprint, int *info, int *nfev, int *njev, __minpack_real__ *r, + const int *lr, __minpack_real__ *qtf, __minpack_real__ *wa1, __minpack_real__ *wa2, + __minpack_real__ *wa3, __minpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (Jacobian calculated by a forward-difference approximation) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmdif1)( __minpack_decl_fcn_mn__ + const int *m, const int *n, __minpack_real__ *x, __minpack_real__ *fvec, const __minpack_real__ *tol, + int *info, int *iwa, __minpack_real__ *wa, const int *lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (Jacobian calculated by a forward-difference approximation, more + general) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmdif)( __minpack_decl_fcn_mn__ + const int *m, const int *n, __minpack_real__ *x, __minpack_real__ *fvec, const __minpack_real__ *ftol, + const __minpack_real__ *xtol, const __minpack_real__ *gtol, const int *maxfev, const __minpack_real__ *epsfcn, + __minpack_real__ *diag, const int *mode, const __minpack_real__ *factor, const int *nprint, + int *info, int *nfev, __minpack_real__ *fjac, const int *ldfjac, int *ipvt, + __minpack_real__ *qtf, __minpack_real__ *wa1, __minpack_real__ *wa2, __minpack_real__ *wa3, + __minpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmder1)( __minpack_decl_fcnder_mn__ + const int *m, const int *n, __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjac, + const int *ldfjac, const __minpack_real__ *tol, int *info, int *ipvt, + __minpack_real__ *wa, const int *lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, more general) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmder)( __minpack_decl_fcnder_mn__ + const int *m, const int *n, __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjac, + const int *ldfjac, const __minpack_real__ *ftol, const __minpack_real__ *xtol, const __minpack_real__ *gtol, + const int *maxfev, __minpack_real__ *diag, const int *mode, const __minpack_real__ *factor, + const int *nprint, int *info, int *nfev, int *njev, int *ipvt, + __minpack_real__ *qtf, __minpack_real__ *wa1, __minpack_real__ *wa2, __minpack_real__ *wa3, + __minpack_real__ *wa4 ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, minimal storage) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmstr1)( __minpack_decl_fcnderstr_mn__ const int *m, const int *n, + __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjac, const int *ldfjac, + const __minpack_real__ *tol, int *info, int *ipvt, __minpack_real__ *wa, const int *lwa ); + +/* minimize the sum of the squares of nonlinear functions in N + variables by a modification of the Levenberg-Marquardt algorithm + (user-supplied Jacobian, minimal storage, more general) */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(lmstr)( __minpack_decl_fcnderstr_mn__ const int *m, + const int *n, __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjac, + const int *ldfjac, const __minpack_real__ *ftol, const __minpack_real__ *xtol, const __minpack_real__ *gtol, + const int *maxfev, __minpack_real__ *diag, const int *mode, const __minpack_real__ *factor, + const int *nprint, int *info, int *nfev, int *njev, int *ipvt, + __minpack_real__ *qtf, __minpack_real__ *wa1, __minpack_real__ *wa2, __minpack_real__ *wa3, + __minpack_real__ *wa4 ); + +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(chkder)( const int *m, const int *n, const __minpack_real__ *x, __minpack_real__ *fvec, __minpack_real__ *fjec, + const int *ldfjac, __minpack_real__ *xp, __minpack_real__ *fvecp, const int *mode, + __minpack_real__ *err ); + +__minpack_attr__ +__minpack_real__ MINPACK_EXPORT __minpack_func__(dpmpar)( const int *i ); + +__minpack_attr__ +__minpack_real__ MINPACK_EXPORT __minpack_func__(enorm)( const int *n, const __minpack_real__ *x ); + +/* compute a forward-difference approximation to the m by n jacobian + matrix associated with a specified problem of m functions in n + variables. */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(fdjac2)(__minpack_decl_fcn_mn__ + const int *m, const int *n, __minpack_real__ *x, const __minpack_real__ *fvec, __minpack_real__ *fjac, + const int *ldfjac, int *iflag, const __minpack_real__ *epsfcn, __minpack_real__ *wa); + +/* compute a forward-difference approximation to the n by n jacobian + matrix associated with a specified problem of n functions in n + variables. if the jacobian has a banded form, then function + evaluations are saved by only approximating the nonzero terms. */ +__minpack_attr__ +void MINPACK_EXPORT __minpack_func__(fdjac1)(__minpack_decl_fcn_nn__ + const int *n, __minpack_real__ *x, const __minpack_real__ *fvec, __minpack_real__ *fjac, const int *ldfjac, + int *iflag, const int *ml, const int *mu, const __minpack_real__ *epsfcn, __minpack_real__ *wa1, + __minpack_real__ *wa2); + +/* internal MINPACK subroutines */ +__minpack_attr__ +void __minpack_func__(dogleg)(const int *n, const __minpack_real__ *r, const int *lr, + const __minpack_real__ *diag, const __minpack_real__ *qtb, const __minpack_real__ *delta, __minpack_real__ *x, + __minpack_real__ *wa1, __minpack_real__ *wa2); +__minpack_attr__ +void __minpack_func__(qrfac)(const int *m, const int *n, __minpack_real__ *a, const int * + lda, const int *pivot, int *ipvt, const int *lipvt, __minpack_real__ *rdiag, + __minpack_real__ *acnorm, __minpack_real__ *wa); +__minpack_attr__ +void __minpack_func__(qrsolv)(const int *n, __minpack_real__ *r, const int *ldr, + const int *ipvt, const __minpack_real__ *diag, const __minpack_real__ *qtb, __minpack_real__ *x, + __minpack_real__ *sdiag, __minpack_real__ *wa); +__minpack_attr__ +void __minpack_func__(qform)(const int *m, const int *n, __minpack_real__ *q, const int * + ldq, __minpack_real__ *wa); +__minpack_attr__ +void __minpack_func__(r1updt)(const int *m, const int *n, __minpack_real__ *s, const int * + ls, const __minpack_real__ *u, __minpack_real__ *v, __minpack_real__ *w, int *sing); +__minpack_attr__ +void __minpack_func__(r1mpyq)(const int *m, const int *n, __minpack_real__ *a, const int * + lda, const __minpack_real__ *v, const __minpack_real__ *w); +__minpack_attr__ +void __minpack_func__(lmpar)(const int *n, __minpack_real__ *r, const int *ldr, + const int *ipvt, const __minpack_real__ *diag, const __minpack_real__ *qtb, const __minpack_real__ *delta, + __minpack_real__ *par, __minpack_real__ *x, __minpack_real__ *sdiag, __minpack_real__ *wa1, + __minpack_real__ *wa2); +__minpack_attr__ +void __minpack_func__(rwupdt)(const int *n, __minpack_real__ *r, const int *ldr, + const __minpack_real__ *w, __minpack_real__ *b, __minpack_real__ *alpha, __minpack_real__ *cos, + __minpack_real__ *sin); +__minpack_attr__ +void __minpack_func__(covar)(const int *n, __minpack_real__ *r, const int *ldr, + const int *ipvt, const __minpack_real__ *tol, __minpack_real__ *wa); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __MINPACK_H__ */ diff --git a/OpenFAST/modules/map/src/cminpack/qrfac.c b/OpenFAST/modules/map/src/cminpack/qrfac.c new file mode 100644 index 000000000..e24628e6c --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/qrfac.c @@ -0,0 +1,285 @@ +#include "cminpack.h" +#include <math.h> +#ifdef USE_LAPACK +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#endif +#include "cminpackP.h" + +__cminpack_attr__ +void __cminpack_func__(qrfac)(int m, int n, real_mp *a, int + lda, int pivot, int *ipvt, int lipvt, real_mp *rdiag, + real_mp *acnorm, real_mp *wa) +{ +#ifdef USE_LAPACK + __CLPK_integer m_ = m; + __CLPK_integer n_ = n; + __CLPK_integer lda_ = lda; + __CLPK_integer *jpvt; + + int i, j, k; + double t; + double* tau = wa; + const __CLPK_integer ltau = m > n ? n : m; + __CLPK_integer lwork = -1; + __CLPK_integer info = 0; + double* work; + + if (pivot) { + assert( lipvt >= n ); + if (sizeof(__CLPK_integer) != sizeof(ipvt[0])) { + jpvt = malloc(n*sizeof(__CLPK_integer)); + } else { + /* __CLPK_integer is actually an int, just do a cast */ + jpvt = (__CLPK_integer *)ipvt; + } + /* set all columns free */ + memset(jpvt, 0, sizeof(int)*n); + } + + /* query optimal size of work */ + lwork = -1; + if (pivot) { + dgeqp3_(&m_,&n_,a,&lda_,jpvt,tau,tau,&lwork,&info); + lwork = (int)tau[0]; + assert( lwork >= 3*n+1 ); + } else { + dgeqrf_(&m_,&n_,a,&lda_,tau,tau,&lwork,&info); + lwork = (int)tau[0]; + assert( lwork >= 1 && lwork >= n ); + } + + assert( info == 0 ); + + /* alloc work area */ + work = (double *)malloc(sizeof(double)*lwork); + assert(work != NULL); + + /* set acnorm first (from the doc of qrfac, acnorm may point to the same area as rdiag) */ + if (acnorm != rdiag) { + for (j = 0; j < n; ++j) { + acnorm[j] = __cminpack_enorm__(m, &a[j * lda]); + } + } + + /* QR decomposition */ + if (pivot) { + dgeqp3_(&m_,&n_,a,&lda_,jpvt,tau,work,&lwork,&info); + } else { + dgeqrf_(&m_,&n_,a,&lda_,tau,work,&lwork,&info); + } + assert(info == 0); + + /* set rdiag, before the diagonal is replaced */ + memset(rdiag, 0, sizeof(double)*n); + for(i=0 ; i<n ; ++i) { + rdiag[i] = a[i*lda+i]; + } + + /* modify lower trinagular part to look like qrfac's output */ + for(i=0 ; i<ltau ; ++i) { + k = i*lda+i; + t = tau[i]; + a[k] = t; + for(j=i+1 ; j<m ; j++) { + k++; + a[k] *= t; + } + } + + free(work); + if (pivot) { + /* convert back jpvt to ipvt */ + if (sizeof(__CLPK_integer) != sizeof(ipvt[0])) { + for(i=0; i<n; ++i) { + ipvt[i] = jpvt[i]; + } + free(jpvt); + } + } +#else /* !USE_LAPACK */ + /* Initialized data */ + +#define p05 .05 + + /* System generated locals */ + real_mp d1; + + /* Local variables */ + int i, j, k, jp1; + real_mp sum; + real_mp temp; + int minmn; + real_mp epsmch; + real_mp ajnorm; + +/* ********** */ + +/* subroutine qrfac */ + +/* this subroutine uses householder transformations with column */ +/* pivoting (optional) to compute a qr factorization of the */ +/* m by n matrix a. that is, qrfac determines an orthogonal */ +/* matrix q, a permutation matrix p, and an upper trapezoidal */ +/* matrix r with diagonal elements of nonincreasing magnitude, */ +/* such that a*p = q*r. the householder transformation for */ +/* column k, k = 1,2,...,min(m,n), is of the form */ + +/* t */ +/* i - (1/u(k))*u*u */ + +/* where u has zeros in the first k-1 positions. the form of */ +/* this transformation and the method of pivoting first */ +/* appeared in the corresponding linpack subroutine. */ + +/* the subroutine statement is */ + +/* subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) */ + +/* where */ + +/* m is a positive integer input variable set to the number */ +/* of rows of a. */ + +/* n is a positive integer input variable set to the number */ +/* of columns of a. */ + +/* a is an m by n array. on input a contains the matrix for */ +/* which the qr factorization is to be computed. on output */ +/* the strict upper trapezoidal part of a contains the strict */ +/* upper trapezoidal part of r, and the lower trapezoidal */ +/* part of a contains a factored form of q (the non-trivial */ +/* elements of the u vectors described above). */ + +/* lda is a positive integer input variable not less than m */ +/* which specifies the leading dimension of the array a. */ + +/* pivot is a logical input variable. if pivot is set true, */ +/* then column pivoting is enforced. if pivot is set false, */ +/* then no column pivoting is done. */ + +/* ipvt is an integer output array of length lipvt. ipvt */ +/* defines the permutation matrix p such that a*p = q*r. */ +/* column j of p is column ipvt(j) of the identity matrix. */ +/* if pivot is false, ipvt is not referenced. */ + +/* lipvt is a positive integer input variable. if pivot is false, */ +/* then lipvt may be as small as 1. if pivot is true, then */ +/* lipvt must be at least n. */ + +/* rdiag is an output array of length n which contains the */ +/* diagonal elements of r. */ + +/* acnorm is an output array of length n which contains the */ +/* norms of the corresponding columns of the input matrix a. */ +/* if this information is not needed, then acnorm can coincide */ +/* with rdiag. */ + +/* wa is a work array of length n. if pivot is false, then wa */ +/* can coincide with rdiag. */ + +/* subprograms called */ + +/* minpack-supplied ... dpmpar,enorm */ + +/* fortran-supplied ... dmax1,dsqrt,min0 */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + (void)lipvt; + +/* epsmch is the machine precision. */ + + epsmch = __cminpack_func__(dpmpar)(1); + +/* compute the initial column norms and initialize several arrays. */ + + for (j = 0; j < n; ++j) { + acnorm[j] = __cminpack_enorm__(m, &a[j * lda + 0]); + rdiag[j] = acnorm[j]; + wa[j] = rdiag[j]; + if (pivot) { + ipvt[j] = j+1; + } + } + +/* reduce a to r with householder transformations. */ + + minmn = minpack_min(m,n); + for (j = 0; j < minmn; ++j) { + if (pivot) { + +/* bring the column of largest norm into the pivot position. */ + + int kmax = j; + for (k = j; k < n; ++k) { + if (rdiag[k] > rdiag[kmax]) { + kmax = k; + } + } + if (kmax != j) { + for (i = 0; i < m; ++i) { + temp = a[i + j * lda]; + a[i + j * lda] = a[i + kmax * lda]; + a[i + kmax * lda] = temp; + } + rdiag[kmax] = rdiag[j]; + wa[kmax] = wa[j]; + k = ipvt[j]; + ipvt[j] = ipvt[kmax]; + ipvt[kmax] = k; + } + } + +/* compute the householder transformation to reduce the */ +/* j-th column of a to a multiple of the j-th unit vector. */ + + ajnorm = __cminpack_enorm__(m - (j+1) + 1, &a[j + j * lda]); + if (ajnorm != 0.) { + if (a[j + j * lda] < 0.) { + ajnorm = -ajnorm; + } + for (i = j; i < m; ++i) { + a[i + j * lda] /= ajnorm; + } + a[j + j * lda] += 1.; + +/* apply the transformation to the remaining columns */ +/* and update the norms. */ + + jp1 = j + 1; + if (n > jp1) { + for (k = jp1; k < n; ++k) { + sum = 0.; + for (i = j; i < m; ++i) { + sum += a[i + j * lda] * a[i + k * lda]; + } + temp = sum / a[j + j * lda]; + for (i = j; i < m; ++i) { + a[i + k * lda] -= temp * a[i + j * lda]; + } + if (pivot && rdiag[k] != 0.) { + temp = a[j + k * lda] / rdiag[k]; + /* Computing MAX */ + d1 = 1. - temp * temp; + rdiag[k] *= sqrt((minpack_max((real_mp)0.,d1))); + /* Computing 2nd power */ + d1 = rdiag[k] / wa[k]; + if (p05 * (d1 * d1) <= epsmch) { + rdiag[k] = __cminpack_enorm__(m - (j+1), &a[jp1 + k * lda]); + wa[k] = rdiag[k]; + } + } + } + } + } + rdiag[j] = -ajnorm; + } + +/* last card of subroutine qrfac. */ +#endif /* !USE_LAPACK */ +} /* qrfac_ */ + diff --git a/OpenFAST/modules/map/src/cminpack/qrsolv.c b/OpenFAST/modules/map/src/cminpack/qrsolv.c new file mode 100644 index 000000000..8697a10b0 --- /dev/null +++ b/OpenFAST/modules/map/src/cminpack/qrsolv.c @@ -0,0 +1,218 @@ +#include "cminpack.h" +#include <math.h> +#include "cminpackP.h" + +__cminpack_attr__ +void __cminpack_func__(qrsolv)(int n, real_mp *r, int ldr, + const int *ipvt, const real_mp *diag, const real_mp *qtb, real_mp *x, + real_mp *sdiag, real_mp *wa) +{ + /* Initialized data */ + +#define p5 .5 +#define p25 .25 + + /* Local variables */ + int i, j, k, l; + real_mp cos, sin, sum, temp; + int nsing; + real_mp qtbpj; + +/* ********** */ + +/* subroutine qrsolv */ + +/* given an m by n matrix a, an n by n diagonal matrix d, */ +/* and an m-vector b, the problem is to determine an x which */ +/* solves the system */ + +/* a*x = b , d*x = 0 , */ + +/* in the least squares sense. */ + +/* this subroutine completes the solution of the problem */ +/* if it is provided with the necessary information from the */ +/* qr factorization, with column pivoting, of a. that is, if */ +/* a*p = q*r, where p is a permutation matrix, q has orthogonal */ +/* columns, and r is an upper triangular matrix with diagonal */ +/* elements of nonincreasing magnitude, then qrsolv expects */ +/* the full upper triangle of r, the permutation matrix p, */ +/* and the first n components of (q transpose)*b. the system */ +/* a*x = b, d*x = 0, is then equivalent to */ + +/* t t */ +/* r*z = q *b , p *d*p*z = 0 , */ + +/* where x = p*z. if this system does not have full rank, */ +/* then a least squares solution is obtained. on output qrsolv */ +/* also provides an upper triangular matrix s such that */ + +/* t t t */ +/* p *(a *a + d*d)*p = s *s . */ + +/* s is computed within qrsolv and may be of separate interest. */ + +/* the subroutine statement is */ + +/* subroutine qrsolv(n,r,ldr,ipvt,diag,qtb,x,sdiag,wa) */ + +/* where */ + +/* n is a positive integer input variable set to the order of r. */ + +/* r is an n by n array. on input the full upper triangle */ +/* must contain the full upper triangle of the matrix r. */ +/* on output the full upper triangle is unaltered, and the */ +/* strict lower triangle contains the strict upper triangle */ +/* (transposed) of the upper triangular matrix s. */ + +/* ldr is a positive integer input variable not less than n */ +/* which specifies the leading dimension of the array r. */ + +/* ipvt is an integer input array of length n which defines the */ +/* permutation matrix p such that a*p = q*r. column j of p */ +/* is column ipvt(j) of the identity matrix. */ + +/* diag is an input array of length n which must contain the */ +/* diagonal elements of the matrix d. */ + +/* qtb is an input array of length n which must contain the first */ +/* n elements of the vector (q transpose)*b. */ + +/* x is an output array of length n which contains the least */ +/* squares solution of the system a*x = b, d*x = 0. */ + +/* sdiag is an output array of length n which contains the */ +/* diagonal elements of the upper triangular matrix s. */ + +/* wa is a work array of length n. */ + +/* subprograms called */ + +/* fortran-supplied ... dabs,dsqrt */ + +/* argonne national laboratory. minpack project. march 1980. */ +/* burton s. garbow, kenneth e. hillstrom, jorge j. more */ + +/* ********** */ + +/* copy r and (q transpose)*b to preserve input and initialize s. */ +/* in particular, save the diagonal elements of r in x. */ + + for (j = 0; j < n; ++j) { + for (i = j; i < n; ++i) { + r[i + j * ldr] = r[j + i * ldr]; + } + x[j] = r[j + j * ldr]; + wa[j] = qtb[j]; + } + +/* eliminate the diagonal matrix d using a givens rotation. */ + + for (j = 0; j < n; ++j) { + +/* prepare the row of d to be eliminated, locating the */ +/* diagonal element using p from the qr factorization. */ + + l = ipvt[j]-1; + if (diag[l] != 0.) { + for (k = j; k < n; ++k) { + sdiag[k] = 0.; + } + sdiag[j] = diag[l]; + +/* the transformations to eliminate the row of d */ +/* modify only a single element of (q transpose)*b */ +/* beyond the first n, which is initially zero. */ + + qtbpj = 0.; + for (k = j; k < n; ++k) { + +/* determine a givens rotation which eliminates the */ +/* appropriate element in the current row of d. */ + + if (sdiag[k] != 0.) { +# ifdef USE_LAPACK + dlartg_( &r[k + k * ldr], &sdiag[k], &cos, &sin, &temp ); +# else /* !USE_LAPACK */ + if (fabs(r[k + k * ldr]) < fabs(sdiag[k])) { + real_mp cotan; + cotan = r[k + k * ldr] / sdiag[k]; + sin = p5 / sqrt(p25 + p25 * (cotan * cotan)); + cos = sin * cotan; + } else { + real_mp tan; + tan = sdiag[k] / r[k + k * ldr]; + cos = p5 / sqrt(p25 + p25 * (tan * tan)); + sin = cos * tan; + } + +/* compute the modified diagonal element of r and */ +/* the modified element of ((q transpose)*b,0). */ + +# endif /* !USE_LAPACK */ + temp = cos * wa[k] + sin * qtbpj; + qtbpj = -sin * wa[k] + cos * qtbpj; + wa[k] = temp; + +/* accumulate the tranformation in the row of s. */ +# ifdef USE_CBLAS + cblas_drot( n-k, &r[k + k * ldr], 1, &sdiag[k], 1, cos, sin ); +# else /* !USE_CBLAS */ + r[k + k * ldr] = cos * r[k + k * ldr] + sin * sdiag[k]; + if (n > k+1) { + for (i = k+1; i < n; ++i) { + temp = cos * r[i + k * ldr] + sin * sdiag[i]; + sdiag[i] = -sin * r[i + k * ldr] + cos * sdiag[i]; + r[i + k * ldr] = temp; + } + } +# endif /* !USE_CBLAS */ + } + } + } + +/* store the diagonal element of s and restore */ +/* the corresponding diagonal element of r. */ + + sdiag[j] = r[j + j * ldr]; + r[j + j * ldr] = x[j]; + } + +/* solve the triangular system for z. if the system is */ +/* singular, then obtain a least squares solution. */ + + nsing = n; + for (j = 0; j < n; ++j) { + if (sdiag[j] == 0. && nsing == n) { + nsing = j; + } + if (nsing < n) { + wa[j] = 0.; + } + } + if (nsing >= 1) { + for (k = 1; k <= nsing; ++k) { + j = nsing - k; + sum = 0.; + if (nsing > j+1) { + for (i = j+1; i < nsing; ++i) { + sum += r[i + j * ldr] * wa[i]; + } + } + wa[j] = (wa[j] - sum) / sdiag[j]; + } + } + +/* permute the components of z back to components of x. */ + + for (j = 0; j < n; ++j) { + l = ipvt[j]-1; + x[l] = wa[j]; + } + return; + +/* last card of subroutine qrsolv. */ + +} /* qrsolv_ */ + diff --git a/OpenFAST/modules/map/src/freedata.c b/OpenFAST/modules/map/src/freedata.c new file mode 100644 index 000000000..f875db98d --- /dev/null +++ b/OpenFAST/modules/map/src/freedata.c @@ -0,0 +1,328 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 + */ + + +#include "freedata.h" + + + +MAP_EXTERNCALL void MAP_InitInput_Delete(InitializationData* init_data) +{ + MAPFREE(init_data); +}; + + +MAP_EXTERNCALL void MAP_OtherState_Delete(Domain* domain) +{ + MAPFREE(domain); +}; + + +MAP_ERROR_CODE free_outlist(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + VarTypePtr* vartype_ptr = NULL; + + if (domain->y_list) { /* if allocated, then proceed with free'ing */ + list_iterator_start(&domain->y_list->out_list_ptr); + while (list_iterator_hasnext(&domain->y_list->out_list_ptr)) { + vartype_ptr = (VarTypePtr*)list_iterator_next(&domain->y_list->out_list_ptr); + bdestroy(vartype_ptr->name); + bdestroy(vartype_ptr->units); + }; + list_iterator_stop(&domain->y_list->out_list_ptr); + + // @rm y_list->out_list no longer exists/is useful ? + list_destroy(&domain->y_list->out_list); /* destroy output lists for writting information to output file */ + list_destroy(&domain->y_list->out_list_ptr); /* destroy output lists for writting information to output file */ + }; + MAPFREE(domain->y_list); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_cable_library(list_t* restrict library) +{ + CableLibrary* iter_library = NULL; + list_iterator_start(library); /* starting an iteration "session" */ + while (list_iterator_hasnext(library)) { /* tell whether more values available */ + iter_library = (CableLibrary*)list_iterator_next(library); + bdestroy(iter_library->label); + }; + list_iterator_stop(library); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_update_list (list_t* restrict ref_list) +{ + ReferencePoint* point_iter = NULL; + list_iterator_start(ref_list); /* starting an iteration "session" */ + while (list_iterator_hasnext(ref_list)) { /* tell whether more values available */ + point_iter = (ReferencePoint*)list_iterator_next(ref_list); + point_iter->x = NULL; + point_iter->y = NULL; + point_iter->z = NULL; + }; + list_iterator_stop(ref_list); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_line(list_t* restrict line) +{ + Line* line_iter = NULL; + list_iterator_start(line); /* starting an iteration "session" */ + while (list_iterator_hasnext(line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(line); + // @rm bdestroy(line_iter->psi.name); + // @rm bdestroy(line_iter->psi.units); + // @rm bdestroy(line_iter->alpha.name); + // @rm bdestroy(line_iter->alpha.units); + // @rm bdestroy(line_iter->alpha_at_anchor.name); + // @rm bdestroy(line_iter->alpha_at_anchor.units); + // @rm bdestroy(line_iter->l.name); + // @rm bdestroy(line_iter->l.units); + // @rm bdestroy(line_iter->Lb.name); + // @rm bdestroy(line_iter->Lb.units); + bdestroy(line_iter->Lu.name); + bdestroy(line_iter->Lu.units); + // @rm bdestroy(line_iter->h.name); + // @rm bdestroy(line_iter->h.units); + bdestroy(line_iter->H.name); + bdestroy(line_iter->H.units); + bdestroy(line_iter->V.name); + bdestroy(line_iter->V.units); + // @rm bdestroy(line_iter->H_at_anchor.name); + // @rm bdestroy(line_iter->H_at_anchor.units); + // @rm bdestroy(line_iter->V_at_anchor.name); + // @rm bdestroy(line_iter->V_at_anchor.units); + // @rm bdestroy(line_iter->force_at_fairlead.fx.name); + // @rm bdestroy(line_iter->force_at_fairlead.fx.units); + // @rm bdestroy(line_iter->force_at_fairlead.fy.name); + // @rm bdestroy(line_iter->force_at_fairlead.fy.units); + // @rm bdestroy(line_iter->force_at_fairlead.fz.name); + // @rm bdestroy(line_iter->force_at_fairlead.fz.units); + // @rm bdestroy(line_iter->force_at_anchor.fx.name); + // @rm bdestroy(line_iter->force_at_anchor.fx.units); + // @rm bdestroy(line_iter->force_at_anchor.fy.name); + // @rm bdestroy(line_iter->force_at_anchor.fy.units); + // @rm bdestroy(line_iter->force_at_anchor.fz.name); + // @rm bdestroy(line_iter->force_at_anchor.fz.units); + // @rm bdestroy(line_iter->T.name); + // @rm bdestroy(line_iter->T.units); + // @rm bdestroy(line_iter->tension_at_anchor.name); + // @rm bdestroy(line_iter->tension_at_anchor.units); + + /* don't let any pointers dangle */ + line_iter->line_property = NULL; + line_iter->label = NULL; + line_iter->line_tension = NULL; + line_iter->anchor = NULL; + line_iter->fairlead = NULL; + }; + list_iterator_stop(line); /* ending the iteration "session" */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_node(list_t *restrict node) +{ + Node* iterNode = NULL; + MAP_ERROR_CODE success = MAP_SAFE; + list_iterator_start(node); /* starting an iteration "session" */ + while (list_iterator_hasnext(node)) { /* tell whether more values available */ + iterNode = (Node*)list_iterator_next(node); + + success = bdestroy(iterNode->M_applied.name); + success = bdestroy(iterNode->M_applied.units); + success = bdestroy(iterNode->B_applied.name); + success = bdestroy(iterNode->B_applied.units); + + success = bdestroy(iterNode->external_force.fx.name); + success = bdestroy(iterNode->external_force.fx.units); + success = bdestroy(iterNode->external_force.fy.name); + success = bdestroy(iterNode->external_force.fy.units); + success = bdestroy(iterNode->external_force.fz.name); + success = bdestroy(iterNode->external_force.fz.units); + + success = bdestroy(iterNode->position_ptr.x.name); + success = bdestroy(iterNode->position_ptr.x.units); + success = bdestroy(iterNode->position_ptr.y.name); + success = bdestroy(iterNode->position_ptr.y.units); + success = bdestroy(iterNode->position_ptr.z.name); + success = bdestroy(iterNode->position_ptr.z.units); + + success = bdestroy(iterNode->sum_force_ptr.fx.name); + success = bdestroy(iterNode->sum_force_ptr.fx.units); + success = bdestroy(iterNode->sum_force_ptr.fy.name); + success = bdestroy(iterNode->sum_force_ptr.fy.units); + success = bdestroy(iterNode->sum_force_ptr.fz.name); + success = bdestroy(iterNode->sum_force_ptr.fz.units); + }; + list_iterator_stop(node); /* ending the iteration "session" */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_vessel(Vessel* floater) +{ + /* Now delete the vessel information */ + MAPFREE(floater->xi); + MAPFREE(floater->yi); + MAPFREE(floater->zi); + + bdestroy(floater->displacement.x.name); + bdestroy(floater->displacement.x.units); + bdestroy(floater->displacement.y.name); + bdestroy(floater->displacement.y.units); + bdestroy(floater->displacement.z.name); + bdestroy(floater->displacement.z.units); + + bdestroy(floater->ref_origin.x.name); + bdestroy(floater->ref_origin.x.units); + bdestroy(floater->ref_origin.y.name); + bdestroy(floater->ref_origin.y.units); + bdestroy(floater->ref_origin.z.name); + bdestroy(floater->ref_origin.z.units); + + bdestroy(floater->line_sum_force.fx.name); + bdestroy(floater->line_sum_force.fx.units); + bdestroy(floater->line_sum_force.fy.name); + bdestroy(floater->line_sum_force.fy.units); + bdestroy(floater->line_sum_force.fz.name); + bdestroy(floater->line_sum_force.fz.units); + + bdestroy(floater->orientation.phi.name); + bdestroy(floater->orientation.phi.units); + bdestroy(floater->orientation.the.name); + bdestroy(floater->orientation.the.units); + bdestroy(floater->orientation.psi.name); + bdestroy(floater->orientation.psi.units); + return MAP_SAFE; +} + + +MAP_ERROR_CODE map_free_types(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_ContinuousStateType_t* x_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type) +{ + /* inputs */ + MAPFREE(u_type->x); + MAPFREE(u_type->y); + MAPFREE(u_type->z); + + /* parameters are skipped for now; they are set in fortran since depth, gravity and sea density are set by glue code */ + + /* continuous state */ + + /* constraint state */ + MAPFREE(z_type->H); + MAPFREE(z_type->V); + MAPFREE(z_type->x); + MAPFREE(z_type->y); + MAPFREE(z_type->z); + + /* other state */ + MAPFREE(other_type->H); + MAPFREE(other_type->V); + MAPFREE(other_type->Ha); + MAPFREE(other_type->Va); + MAPFREE(other_type->x); + MAPFREE(other_type->y); + MAPFREE(other_type->z); + MAPFREE(other_type->xa); + MAPFREE(other_type->ya); + MAPFREE(other_type->za); + MAPFREE(other_type->Fx_connect); + MAPFREE(other_type->Fy_connect); + MAPFREE(other_type->Fz_connect); + MAPFREE(other_type->Fx_anchor); + MAPFREE(other_type->Fy_anchor); + MAPFREE(other_type->Fz_anchor); + + /* outputs */ + MAPFREE(y_type->Fx); + MAPFREE(y_type->Fy); + MAPFREE(y_type->Fz); + MAPFREE(y_type->wrtOutput); + MAPFREE(y_type->WriteOutput); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE free_outer_solve_data(OuterSolveAttributes* ns, const int size, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // const int N = ns->max_krylov_its + 1; + const int SIZE = 3*size; + int i = 0; + + if (ns->jac) { /* is it allocated? */ + for(i=0 ; i<SIZE ; i++) { + MAPFREE(ns->jac[i]); + }; + }; + + if (ns->l) { /* is it allocated? */ + for(i=0 ; i<SIZE ; i++) { + MAPFREE(ns->l[i]); + }; + }; + + if (ns->u) { /* is it allocated? */ + for(i=0 ; i<SIZE ; i++) { + MAPFREE(ns->u[i]); + }; + }; + + if (ns->V) { /* is it allocated? */ + for(i=0 ; i<SIZE ; i++) { + MAPFREE(ns->V[i]); + }; + }; + + if (ns->AV) { /* is it allocated? */ + for(i=0 ; i<SIZE ; i++) { + MAPFREE(ns->AV[i]); + }; + }; + + + MAPFREE(ns->jac); + MAPFREE(ns->AV); + MAPFREE(ns->av); + MAPFREE(ns->V); + MAPFREE(ns->l); + MAPFREE(ns->u); + MAPFREE(ns->b); + MAPFREE(ns->w); + MAPFREE(ns->q); + MAPFREE(ns->x); + MAPFREE(ns->y); + MAPFREE(ns->C); + return MAP_SAFE; +}; + diff --git a/OpenFAST/modules/map/src/freedata.h b/OpenFAST/modules/map/src/freedata.h new file mode 100644 index 000000000..aad426122 --- /dev/null +++ b/OpenFAST/modules/map/src/freedata.h @@ -0,0 +1,86 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _FREE_DATA_H +#define _FREE_DATA_H + + +#include "map.h" + + +MAP_ERROR_CODE map_free_types(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_ContinuousStateType_t* x_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type); +MAP_EXTERNCALL void MAP_InitInput_Delete(InitializationData* init_data); +MAP_EXTERNCALL void MAP_OtherState_Delete(Domain* domain); +MAP_ERROR_CODE free_outer_solve_data(OuterSolveAttributes* ns, const int size, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE free_vessel(Vessel* floater); + + +/** + * @brief Set the reference in ReferencePoint to NULL + * @details Accessed in {@link map_end()}. The ref_list points to nodes associated + * with u_types, i.e., input types that are interpolated by FAST. + * @param ref_list, reference to 'connect' node positions + */ +MAP_ERROR_CODE free_update_list (list_t* restrict ref_list); + + +/** + * @brief Deallocate the 'label' parameter in the CableLibrary + * @details Accessed in {@link map_end()} + * @param library, library link list + */ +MAP_ERROR_CODE free_cable_library(list_t* restrict library); + + +/** + * Frees internal state data allcoated in the mapcall_msqs_init( ) function + * + * @todo: delete additional dependancies in data->z, data->y_list, data->u + * @acceses: none + * @calledby: mapcall_msqs_end( ) + * @see: allocate_outlist( ) + */ +MAP_ERROR_CODE free_outlist(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Deallocates all lines. Function loops through the elemenet link list and frees allocated data. Pointers + * are nullified. + * @param line the line link list + * @return MAP_SAFE if it completes successfully + * @see {@link Line_t()} + */ +MAP_ERROR_CODE free_line(list_t *restrict line); + + +/** + * @brief Deallocates all nodes. Function loops through the elemenet link list and frees allocated data. Pointers + * are nullified. + * @param node the node link list + * @return MAP_SAFE if it completes successfully + * @see {@link Line_t()} + */ +MAP_ERROR_CODE free_node(list_t *restrict node); + + +#endif // _FREE_DATA_H diff --git a/OpenFAST/modules/map/src/jacobian.c b/OpenFAST/modules/map/src/jacobian.c new file mode 100644 index 000000000..95076859b --- /dev/null +++ b/OpenFAST/modules/map/src/jacobian.c @@ -0,0 +1,391 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "jacobian.h" +#include "lineroutines.h" + + +double jacobian_dxdh_no_contact(const double V, const double H, const double w, const double Lu, const double EA) +{ + return (ARCSINH(V/H) - ARCSINH((V-w*Lu)/H))/w - ((V/H + pow(V/H, 2)/sqrt(1.0 + pow(V/H, 2)))/(V/H + sqrt(1.0 + pow(V/H, 2))) + - ((V-w*Lu)/H + pow((V-w*Lu)/H, 2)/sqrt(1.0 + pow((V-w*Lu)/H, 2))) + /((V-w*Lu)/H + sqrt(1.0 + pow((V-w*Lu)/H, 2))))/w + (Lu/(EA)); +}; + + +double jacobian_dxdv_no_contact(const double V, const double H, const double w, const double Lu, const double EA) +{ + return ((1.0 + V/H /sqrt(1.0 + pow(V/H, 2)))/(V/H + sqrt(1.0 + pow(V/H, 2))) + - (1.0 + (V-w*Lu)/H /sqrt(1.0 + pow( (V-w*Lu)/H , 2))) + /((V-w*Lu)/H + sqrt(1.0 + pow((V-w*Lu)/H, 2))))/w; +}; + + +double jacobian_dzdh_no_contact(const double V, const double H, const double w, const double Lu, const double EA) +{ + return ( sqrt( 1.0 + pow( V/H , 2) ) - sqrt( 1.0 + pow( (V-w*Lu)/H , 2) ) )/w + - ( pow( V/H , 2 )/sqrt( 1.0 + pow( V/H , 2) ) - pow( (V-w*Lu)/H , 2)/sqrt( 1.0 + pow( (V-w*Lu)/H , 2) ) )/w; +}; + + +double jacobian_dzdv_no_contact(const double V, const double H, const double w, const double Lu, const double EA) +{ + return ( V/H/sqrt( 1.0 + pow( V/H , 2) ) - (V-w*Lu)/H /sqrt( 1.0 + pow( (V-w*Lu)/H , 2) ) )/w + (Lu/(EA)); +}; + + +double jacobian_dxdh_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb) +{ + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return log((V/H) + sqrt(1.0 + pow(V/H,2)))/w - (((V/H) + (V/H)*(V/H)/sqrt(1.0 + pow(V/H,2)))/((V/H) + sqrt(1.0 + pow(V/H,2))))/w + (Lu/EA); + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return log((V/H) + sqrt(1.0 + pow(V/H,2)))/w - (((V/H) + (V/H)*(V/H)/sqrt(1.0 + pow(V/H,2)))/((V/H) + sqrt(1.0 + pow(V/H,2))))/w + (Lu/EA) - ((Lu-V/w) - (H/w)/cb)/EA; + }; +}; + + +double jacobian_dxdv_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb) +{ + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return ((1.0 + (V/H)/sqrt(1.0 + pow(V/H,2)))/((V/H) + sqrt(1.0 + pow(V/H,2))))/w + (cb/EA)*(Lu-V/w) - 1.0/w; + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return ((1.0 + (V/H)/sqrt(1.0 + pow(V/H,2)))/((V/H) + sqrt(1.0 + pow(V/H,2))))/w + (H/(w*EA)) - 1.0/w; + }; +}; + + +double jacobian_dzdh_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb) +{ + // @todo remove this conditional statement because the equations are the same regardless of the outcome + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return (sqrt(1.0 + pow(V/H,2)) - 1.0 - (V/H)*(V/H)/sqrt(1.0 + pow(V/H,2)))/w; + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return (sqrt(1.0 + pow(V/H,2)) - 1.0 - (V/H)*(V/H)/sqrt(1.0 + pow(V/H,2)))/w; + }; +}; + + + +double jacobian_dzdv_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb) +{ + // @todo remove this conditional statement because the equations are the same regardless of the outcome + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return ((V/H)/sqrt(1.0 + pow(V/H,2)))/w + (V/(w*EA)); + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return ((V/H)/sqrt(1.0 + pow(V/H,2)))/w + (V/(w*EA)); + }; +}; + + +MAP_ERROR_CODE forward_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + OuterSolveAttributes* ns = &domain->outer_loop; + MAP_ERROR_CODE success = MAP_SAFE; + double original_displacement = 0.0; + const int THREE = 3; + const int z_size = z_type->z_Len; + // const int m = THREE*(other_type->Fz_connect_Len); // rows + const int n = THREE*(z_type->z_Len); // columns + int i = 0; + int j = 0; + + for (i=0 ; i<z_size ; i++) { + ns->b[THREE*i] = other_type->Fx_connect[i]; + ns->b[THREE*i+1] = other_type->Fy_connect[i]; + ns->b[THREE*i+2] = other_type->Fz_connect[i]; + } + + /* First store the connect node force before applying ns->epsilon displacement */ + for (i=0 ; i<n ; i++) { + for (j=0 ; j<z_size ; j++) { + ns->jac[THREE*j][i] = -other_type->Fx_connect[j]; + ns->jac[THREE*j+1][i] = -other_type->Fy_connect[j]; + ns->jac[THREE*j+2][i] = -other_type->Fz_connect[j]; + }; + }; + + for (j=0 ; j<z_size ; j++) { // column + for (i=0 ; i<z_size ; i++) { // rows + original_displacement = z_type->x[j]; + z_type->x[j] += ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Forward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j] += other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j] += other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j] += other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j] /= ns->epsilon; + z_type->x[j] = original_displacement; + + original_displacement = z_type->y[j]; + z_type->y[j] += ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Forward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+1] += other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+1] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j+1] += other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+1] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j+1] += other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+1] /= ns->epsilon; + z_type->y[j] = original_displacement; + + original_displacement = z_type->z[j]; + z_type->z[j] += ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Forward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+2] += other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+2] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j+2] += other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+2] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j+2] += other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+2] /= ns->epsilon; + z_type->z[j] = original_displacement; + }; + }; + + /* read flag to set scaling parameter */ + if (ns->pg) { + for (i=0 ; i<THREE*z_size ; i++) { + ns->jac[i][i] += (ns->ds/pow(ns->iteration_count,1.5)+ns->d); + }; + }; + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE backward_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + OuterSolveAttributes* ns = &domain->outer_loop; + MAP_ERROR_CODE success = MAP_SAFE; + double original_displacement = 0.0; + const int THREE = 3; + const int z_size = z_type->z_Len; // N + // const int m = THREE*(other_type->Fz_connect_Len); // rows + const int n = THREE*(z_type->z_Len); // columns + int i = 0; + int j = 0; + + for (i=0 ; i<z_size ; i++) { + ns->b[THREE*i] = other_type->Fx_connect[i]; + ns->b[THREE*i+1] = other_type->Fy_connect[i]; + ns->b[THREE*i+2] = other_type->Fz_connect[i]; + } + + /* First store the connect node force before applying ns->epsilon displacement */ + for (i=0 ; i<n ; i++) { + for (j=0 ; j<z_size ; j++) { + ns->jac[THREE*j][i] = other_type->Fx_connect[j]; + ns->jac[THREE*j+1][i] = other_type->Fy_connect[j]; + ns->jac[THREE*j+2][i] = other_type->Fz_connect[j]; + }; + }; + + for (j=0 ; j<z_size ; j++) { // column + for (i=0 ; i<z_size ; i++) { // rows + original_displacement = z_type->x[j]; + z_type->x[j] -= ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Backward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j] /= ns->epsilon; + z_type->x[j] = original_displacement; + + original_displacement = z_type->y[j]; + z_type->y[j] -= ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Backward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+1] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+1] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j+1] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+1] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j+1] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+1] /= ns->epsilon; + z_type->y[j] = original_displacement; + + original_displacement = z_type->z[j]; + z_type->z[j] -= ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Backward difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+2] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+2] /= ns->epsilon; + ns->jac[THREE*i+1][THREE*j+2] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+2] /= ns->epsilon; + ns->jac[THREE*i+2][THREE*j+2] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+2] /= ns->epsilon; + z_type->z[j] = original_displacement; + }; + }; + + /* read flag to set scaling parameter */ + if (ns->pg) { + for (i=0 ; i<THREE*z_size ; i++) { + ns->jac[i][i] += (ns->ds/pow(ns->iteration_count,1.5)+ns->d); + }; + }; + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE central_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + OuterSolveAttributes* ns = &domain->outer_loop; + MAP_ERROR_CODE success = MAP_SAFE; + double original_displacement = 0.0; + const int THREE = 3; + const int z_size = z_type->z_Len; //M + // const int m = THREE*(other_type->Fz_connect_Len); // rows + // const int n = THREE*(z_type->z_Len); // columns + int i = 0; + int j = 0; + + for (i=0 ; i<z_size ; i++) { + ns->b[THREE*i] = other_type->Fx_connect[i]; + ns->b[THREE*i+1] = other_type->Fy_connect[i]; + ns->b[THREE*i+2] = other_type->Fz_connect[i]; + } + + /* First store the connect node force before applying ns->epsilon displacement */ + for (j=0 ; j<z_size ; j++) { // column + for (i=0 ; i<z_size ; i++) { // rows + original_displacement = z_type->x[j]; + z_type->x[j] += ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j] = other_type->Fx_connect[i]; + ns->jac[THREE*i+1][THREE*j] = other_type->Fy_connect[i]; + ns->jac[THREE*i+2][THREE*j] = other_type->Fz_connect[i]; + z_type->x[j] = original_displacement; + + original_displacement = z_type->y[j]; + z_type->y[j] += ns->epsilon; + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + ns->jac[THREE*i][THREE*j+1] = other_type->Fx_connect[i]; + ns->jac[THREE*i+1][THREE*j+1] = other_type->Fy_connect[i]; + ns->jac[THREE*i+2][THREE*j+1] = other_type->Fz_connect[i]; + z_type->y[j] = original_displacement; + + original_displacement = z_type->z[j]; + z_type->z[j] += ns->epsilon; + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + ns->jac[THREE*i][THREE*j+2] = other_type->Fx_connect[i]; + ns->jac[THREE*i+1][THREE*j+2] = other_type->Fy_connect[i]; + ns->jac[THREE*i+2][THREE*j+2] = other_type->Fz_connect[i]; + z_type->z[j] = original_displacement; + }; + }; + + for (j=0 ; j<z_size ; j++) { // column + for (i=0 ; i<z_size ; i++) { // rows + original_displacement = z_type->x[j]; + z_type->x[j] -= ns->epsilon; + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + ns->jac[THREE*i][THREE*j] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j] /= (2*ns->epsilon); + ns->jac[THREE*i+1][THREE*j] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j] /= (2*ns->epsilon); + ns->jac[THREE*i+2][THREE*j] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j] /= (2*ns->epsilon); + z_type->x[j] = original_displacement; + + original_displacement = z_type->y[j]; + z_type->y[j] -= ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+1] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+1] /= (2*ns->epsilon); + ns->jac[THREE*i+1][THREE*j+1] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+1] /= (2*ns->epsilon); + ns->jac[THREE*i+2][THREE*j+1] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+1] /= (2*ns->epsilon); + z_type->y[j] = original_displacement; + + original_displacement = z_type->z[j]; + z_type->z[j] -= ns->epsilon; + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_78, "Central difference, x[%d]+delta, row %d, col %d.", j+1, THREE*i, THREE*j); + return MAP_FATAL; + }; + ns->jac[THREE*i][THREE*j+2] -= other_type->Fx_connect[i]; + ns->jac[THREE*i][THREE*j+2] /= (2*ns->epsilon); + ns->jac[THREE*i+1][THREE*j+2] -= other_type->Fy_connect[i]; + ns->jac[THREE*i+1][THREE*j+2] /= (2*ns->epsilon); + ns->jac[THREE*i+2][THREE*j+2] -= other_type->Fz_connect[i]; + ns->jac[THREE*i+2][THREE*j+2] /= (2*ns->epsilon); + z_type->z[j] = original_displacement; + }; + }; + + /* read flag to set scaling parameter */ + if (ns->pg) { + ns->coef = pow(ns->iteration_count,1.5); + for (i=0 ; i<THREE*z_size ; i++) { + ns->jac[i][i] += (ns->ds/ns->coef + ns->d); + }; + }; + + return MAP_SAFE; +}; diff --git a/OpenFAST/modules/map/src/jacobian.h b/OpenFAST/modules/map/src/jacobian.h new file mode 100644 index 000000000..7e1038a22 --- /dev/null +++ b/OpenFAST/modules/map/src/jacobian.h @@ -0,0 +1,43 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _JACOBIAN_H +#define _JACOBIAN_H + + +#include "map.h" + +double jacobian_dxdh_no_contact(const double V, const double H, const double w, const double Lu, const double EA); +double jacobian_dxdv_no_contact(const double V, const double H, const double w, const double Lu, const double EA); +double jacobian_dzdh_no_contact(const double V, const double H, const double w, const double Lu, const double EA); +double jacobian_dzdv_no_contact(const double V, const double H, const double w, const double Lu, const double EA); +double jacobian_dxdh_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb); +double jacobian_dxdv_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb); +double jacobian_dzdh_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb); +double jacobian_dzdv_contact(const double V, const double H, const double w, const double Lu, const double EA, const double cb); + +MAP_ERROR_CODE forward_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE backward_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE central_difference_jacobian(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_ConstraintStateType_t* z_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + +#endif // _JACOBIAN_H diff --git a/OpenFAST/modules/map/src/lapack/lapacke.h b/OpenFAST/modules/map/src/lapack/lapacke.h new file mode 100644 index 000000000..a31c10d6d --- /dev/null +++ b/OpenFAST/modules/map/src/lapack/lapacke.h @@ -0,0 +1,16445 @@ +/***************************************************************************** + Copyright (c) 2010, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +****************************************************************************** +* Contents: Native C interface to LAPACK +* Author: Intel Corporation +* Generated November, 2011 +*****************************************************************************/ + +#ifndef _LAPACKE_H_ +#define _LAPACKE_H_ + +/* +* Turn on HAVE_LAPACK_CONFIG_H to redefine C-LAPACK datatypes +*/ +#ifdef HAVE_LAPACK_CONFIG_H +#include "lapacke_config.h" +#endif + +#include <stdlib.h> + +#ifndef lapack_int +#define lapack_int int +#endif + +#ifndef lapack_logical +#define lapack_logical lapack_int +#endif + +/* Complex types are structures equivalent to the +* Fortran complex types COMPLEX(4) and COMPLEX(8). +* +* One can also redefine the types with his own types +* for example by including in the code definitions like +* +* #define lapack_complex_float std::complex<float> +* #define lapack_complex_double std::complex<double> +* +* or define these types in the command line: +* +* -Dlapack_complex_float="std::complex<float>" +* -Dlapack_complex_double="std::complex<double>" +*/ + +#ifndef LAPACK_COMPLEX_CUSTOM + +/* Complex type (single precision) */ +#ifndef lapack_complex_float +#include <complex.h> +#define lapack_complex_float float _Complex +#endif + +#ifndef lapack_complex_float_real +#define lapack_complex_float_real(z) (creal(z)) +#endif + +#ifndef lapack_complex_float_imag +#define lapack_complex_float_imag(z) (cimag(z)) +#endif + +lapack_complex_float lapack_make_complex_float( float re, float im ); + +/* Complex type (double precision) */ +#ifndef lapack_complex_double +#include <complex.h> +#define lapack_complex_double double _Complex +#endif + +#ifndef lapack_complex_double_real +#define lapack_complex_double_real(z) (creal(z)) +#endif + +#ifndef lapack_complex_double_imag +#define lapack_complex_double_imag(z) (cimag(z)) +#endif + +lapack_complex_double lapack_make_complex_double( double re, double im ); + +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef LAPACKE_malloc +#define LAPACKE_malloc( size ) malloc( size ) +#endif +#ifndef LAPACKE_free +#define LAPACKE_free( p ) free( p ) +#endif + +#define LAPACK_C2INT( x ) (lapack_int)(*((float*)&x )) +#define LAPACK_Z2INT( x ) (lapack_int)(*((double*)&x )) + +#define LAPACK_ROW_MAJOR 101 +#define LAPACK_COL_MAJOR 102 + +#define LAPACK_WORK_MEMORY_ERROR -1010 +#define LAPACK_TRANSPOSE_MEMORY_ERROR -1011 + +/* Callback logical functions of one, two, or three arguments are used +* to select eigenvalues to sort to the top left of the Schur form. +* The value is selected if function returns TRUE (non-zero). */ + +typedef lapack_logical (*LAPACK_S_SELECT2) ( const float*, const float* ); +typedef lapack_logical (*LAPACK_S_SELECT3) + ( const float*, const float*, const float* ); +typedef lapack_logical (*LAPACK_D_SELECT2) ( const double*, const double* ); +typedef lapack_logical (*LAPACK_D_SELECT3) + ( const double*, const double*, const double* ); + +typedef lapack_logical (*LAPACK_C_SELECT1) ( const lapack_complex_float* ); +typedef lapack_logical (*LAPACK_C_SELECT2) + ( const lapack_complex_float*, const lapack_complex_float* ); +typedef lapack_logical (*LAPACK_Z_SELECT1) ( const lapack_complex_double* ); +typedef lapack_logical (*LAPACK_Z_SELECT2) + ( const lapack_complex_double*, const lapack_complex_double* ); + +#include "lapacke_mangling.h" + +#define LAPACK_lsame LAPACK_GLOBAL(lsame,LSAME) +lapack_logical LAPACK_lsame( char* ca, char* cb, + lapack_int lca, lapack_int lcb ); + +/* C-LAPACK function prototypes */ + +lapack_int LAPACKE_sbdsdc( int matrix_order, char uplo, char compq, + lapack_int n, float* d, float* e, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, float* q, + lapack_int* iq ); +lapack_int LAPACKE_dbdsdc( int matrix_order, char uplo, char compq, + lapack_int n, double* d, double* e, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* q, lapack_int* iq ); + +lapack_int LAPACKE_sbdsqr( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, float* vt, lapack_int ldvt, + float* u, lapack_int ldu, float* c, lapack_int ldc ); +lapack_int LAPACKE_dbdsqr( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, double* vt, lapack_int ldvt, + double* u, lapack_int ldu, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cbdsqr( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zbdsqr( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* c, + lapack_int ldc ); + +lapack_int LAPACKE_sdisna( char job, lapack_int m, lapack_int n, const float* d, + float* sep ); +lapack_int LAPACKE_ddisna( char job, lapack_int m, lapack_int n, + const double* d, double* sep ); + +lapack_int LAPACKE_sgbbrd( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, float* ab, lapack_int ldab, float* d, + float* e, float* q, lapack_int ldq, float* pt, + lapack_int ldpt, float* c, lapack_int ldc ); +lapack_int LAPACKE_dgbbrd( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq, + double* pt, lapack_int ldpt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cgbbrd( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* pt, lapack_int ldpt, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zgbbrd( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* pt, lapack_int ldpt, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sgbcon( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, const lapack_int* ipiv, float anorm, + float* rcond ); +lapack_int LAPACKE_dgbcon( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond ); +lapack_int LAPACKE_cgbcon( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zgbcon( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sgbequ( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequ( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequ( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgbequ( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax ); + +lapack_int LAPACKE_sgbequb( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequb( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequb( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgbequb( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbrfs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, const float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dgbrfs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, const double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cgbrfs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, lapack_int ldafb, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgbrfs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* afb, lapack_int ldafb, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgbrfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const float* ab, lapack_int ldab, + const float* afb, lapack_int ldafb, + const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgbrfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgbrfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zgbrfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const lapack_complex_double* ab, + lapack_int ldab, const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_sgbsv( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, float* ab, + lapack_int ldab, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbsv( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, double* ab, + lapack_int ldab, lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbsv( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbsv( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgbsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_dgbsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); +lapack_int LAPACKE_cgbsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* rpivot ); +lapack_int LAPACKE_zgbsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* rpivot ); + +lapack_int LAPACKE_sgbsvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgbsvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_cgbsvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zgbsvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_sgbtrf( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, float* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_dgbtrf( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, double* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_cgbtrf( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv ); +lapack_int LAPACKE_zgbtrf( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgbtrs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgbtrs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgbtrs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbtrs( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgebak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* scale, + lapack_int m, float* v, lapack_int ldv ); +lapack_int LAPACKE_dgebak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* scale, + lapack_int m, double* v, lapack_int ldv ); +lapack_int LAPACKE_cgebak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* scale, + lapack_int m, lapack_complex_float* v, + lapack_int ldv ); +lapack_int LAPACKE_zgebak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* scale, + lapack_int m, lapack_complex_double* v, + lapack_int ldv ); + +lapack_int LAPACKE_sgebal( int matrix_order, char job, lapack_int n, float* a, + lapack_int lda, lapack_int* ilo, lapack_int* ihi, + float* scale ); +lapack_int LAPACKE_dgebal( int matrix_order, char job, lapack_int n, double* a, + lapack_int lda, lapack_int* ilo, lapack_int* ihi, + double* scale ); +lapack_int LAPACKE_cgebal( int matrix_order, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, float* scale ); +lapack_int LAPACKE_zgebal( int matrix_order, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, double* scale ); + +lapack_int LAPACKE_sgebrd( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tauq, float* taup ); +lapack_int LAPACKE_dgebrd( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tauq, double* taup ); +lapack_int LAPACKE_cgebrd( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* d, + float* e, lapack_complex_float* tauq, + lapack_complex_float* taup ); +lapack_int LAPACKE_zgebrd( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* d, + double* e, lapack_complex_double* tauq, + lapack_complex_double* taup ); + +lapack_int LAPACKE_sgecon( int matrix_order, char norm, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond ); +lapack_int LAPACKE_dgecon( int matrix_order, char norm, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond ); +lapack_int LAPACKE_cgecon( int matrix_order, char norm, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond ); +lapack_int LAPACKE_zgecon( int matrix_order, char norm, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond ); + +lapack_int LAPACKE_sgeequ( int matrix_order, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgeequ( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequ( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgeequ( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax ); + +lapack_int LAPACKE_sgeequb( int matrix_order, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgeequb( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequb( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgeequb( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgees( int matrix_order, char jobvs, char sort, + LAPACK_S_SELECT2 select, lapack_int n, float* a, + lapack_int lda, lapack_int* sdim, float* wr, + float* wi, float* vs, lapack_int ldvs ); +lapack_int LAPACKE_dgees( int matrix_order, char jobvs, char sort, + LAPACK_D_SELECT2 select, lapack_int n, double* a, + lapack_int lda, lapack_int* sdim, double* wr, + double* wi, double* vs, lapack_int ldvs ); +lapack_int LAPACKE_cgees( int matrix_order, char jobvs, char sort, + LAPACK_C_SELECT1 select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs ); +lapack_int LAPACKE_zgees( int matrix_order, char jobvs, char sort, + LAPACK_Z_SELECT1 select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs ); + +lapack_int LAPACKE_sgeesx( int matrix_order, char jobvs, char sort, + LAPACK_S_SELECT2 select, char sense, lapack_int n, + float* a, lapack_int lda, lapack_int* sdim, + float* wr, float* wi, float* vs, lapack_int ldvs, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dgeesx( int matrix_order, char jobvs, char sort, + LAPACK_D_SELECT2 select, char sense, lapack_int n, + double* a, lapack_int lda, lapack_int* sdim, + double* wr, double* wi, double* vs, lapack_int ldvs, + double* rconde, double* rcondv ); +lapack_int LAPACKE_cgeesx( int matrix_order, char jobvs, char sort, + LAPACK_C_SELECT1 select, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + float* rconde, float* rcondv ); +lapack_int LAPACKE_zgeesx( int matrix_order, char jobvs, char sort, + LAPACK_Z_SELECT1 select, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sgeev( int matrix_order, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* wr, + float* wi, float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_dgeev( int matrix_order, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, double* wr, + double* wi, double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr ); +lapack_int LAPACKE_cgeev( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_zgeev( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr ); + +lapack_int LAPACKE_sgeevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* wr, float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv ); +lapack_int LAPACKE_dgeevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* wr, double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* scale, + double* abnrm, double* rconde, double* rcondv ); +lapack_int LAPACKE_cgeevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, + float* rcondv ); +lapack_int LAPACKE_zgeevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int ldvl, lapack_complex_double* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv ); + +lapack_int LAPACKE_sgehrd( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + float* tau ); +lapack_int LAPACKE_dgehrd( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + double* tau ); +lapack_int LAPACKE_cgehrd( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* tau ); +lapack_int LAPACKE_zgehrd( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgejsv( int matrix_order, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, float* a, lapack_int lda, float* sva, + float* u, lapack_int ldu, float* v, lapack_int ldv, + float* stat, lapack_int* istat ); +lapack_int LAPACKE_dgejsv( int matrix_order, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, double* a, lapack_int lda, double* sva, + double* u, lapack_int ldu, double* v, lapack_int ldv, + double* stat, lapack_int* istat ); + +lapack_int LAPACKE_sgelq2( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgelq2( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgelq2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgelq2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgelqf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgelqf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgelqf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgelqf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgels( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgels( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgels( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgels( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgelsd( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelsd( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, double rcond, + lapack_int* rank ); +lapack_int LAPACKE_cgelsd( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelsd( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgelss( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelss( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, double rcond, + lapack_int* rank ); +lapack_int LAPACKE_cgelss( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelss( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgelsy( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelsy( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* jpvt, + double rcond, lapack_int* rank ); +lapack_int LAPACKE_cgelsy( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelsy( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* jpvt, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgeqlf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqlf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqlf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqlf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqp3( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau ); +lapack_int LAPACKE_dgeqp3( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau ); +lapack_int LAPACKE_cgeqp3( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqp3( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqpf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau ); +lapack_int LAPACKE_dgeqpf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau ); +lapack_int LAPACKE_cgeqpf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqpf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqr2( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqr2( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqr2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqr2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqrf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqrf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqrf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqrf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqrfp( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqrfp( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqrfp( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqrfp( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgerfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dgerfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_cgerfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgerfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgerfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgerfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgerfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* r, + const float* c, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zgerfsx( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* r, + const double* c, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sgerqf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgerqf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgerqf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgerqf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgesdd( int matrix_order, char jobz, lapack_int m, + lapack_int n, float* a, lapack_int lda, float* s, + float* u, lapack_int ldu, float* vt, + lapack_int ldvt ); +lapack_int LAPACKE_dgesdd( int matrix_order, char jobz, lapack_int m, + lapack_int n, double* a, lapack_int lda, double* s, + double* u, lapack_int ldu, double* vt, + lapack_int ldvt ); +lapack_int LAPACKE_cgesdd( int matrix_order, char jobz, lapack_int m, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt ); +lapack_int LAPACKE_zgesdd( int matrix_order, char jobz, lapack_int m, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt ); + +lapack_int LAPACKE_sgesv( int matrix_order, lapack_int n, lapack_int nrhs, + float* a, lapack_int lda, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgesv( int matrix_order, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgesv( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgesv( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsgesv( int matrix_order, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb, double* x, lapack_int ldx, + lapack_int* iter ); +lapack_int LAPACKE_zcgesv( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_int* iter ); + +lapack_int LAPACKE_sgesvd( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, float* a, lapack_int lda, + float* s, float* u, lapack_int ldu, float* vt, + lapack_int ldvt, float* superb ); +lapack_int LAPACKE_dgesvd( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, double* superb ); +lapack_int LAPACKE_cgesvd( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt, float* superb ); +lapack_int LAPACKE_zgesvd( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt, double* superb ); + +lapack_int LAPACKE_sgesvj( int matrix_order, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, float* a, lapack_int lda, + float* sva, lapack_int mv, float* v, lapack_int ldv, + float* stat ); +lapack_int LAPACKE_dgesvj( int matrix_order, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* sva, lapack_int mv, + double* v, lapack_int ldv, double* stat ); + +lapack_int LAPACKE_sgesvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_dgesvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); +lapack_int LAPACKE_cgesvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_zgesvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); + +lapack_int LAPACKE_sgesvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgesvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgesvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zgesvxx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sgetf2( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetf2( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetf2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetf2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetri( int matrix_order, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dgetri( int matrix_order, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_cgetri( int matrix_order, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zgetri( int matrix_order, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgetrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgetrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgetrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sggbak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* lscale, + const float* rscale, lapack_int m, float* v, + lapack_int ldv ); +lapack_int LAPACKE_dggbak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* lscale, + const double* rscale, lapack_int m, double* v, + lapack_int ldv ); +lapack_int LAPACKE_cggbak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* lscale, + const float* rscale, lapack_int m, + lapack_complex_float* v, lapack_int ldv ); +lapack_int LAPACKE_zggbak( int matrix_order, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* lscale, + const double* rscale, lapack_int m, + lapack_complex_double* v, lapack_int ldv ); + +lapack_int LAPACKE_sggbal( int matrix_order, char job, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale ); +lapack_int LAPACKE_dggbal( int matrix_order, char job, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale ); +lapack_int LAPACKE_cggbal( int matrix_order, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale ); +lapack_int LAPACKE_zggbal( int matrix_order, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale ); + +lapack_int LAPACKE_sgges( int matrix_order, char jobvsl, char jobvsr, char sort, + LAPACK_S_SELECT3 selctg, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + lapack_int* sdim, float* alphar, float* alphai, + float* beta, float* vsl, lapack_int ldvsl, float* vsr, + lapack_int ldvsr ); +lapack_int LAPACKE_dgges( int matrix_order, char jobvsl, char jobvsr, char sort, + LAPACK_D_SELECT3 selctg, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int ldvsl, + double* vsr, lapack_int ldvsr ); +lapack_int LAPACKE_cgges( int matrix_order, char jobvsl, char jobvsr, char sort, + LAPACK_C_SELECT2 selctg, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vsl, + lapack_int ldvsl, lapack_complex_float* vsr, + lapack_int ldvsr ); +lapack_int LAPACKE_zgges( int matrix_order, char jobvsl, char jobvsr, char sort, + LAPACK_Z_SELECT2 selctg, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr ); + +lapack_int LAPACKE_sggesx( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, char sense, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* sdim, float* alphar, + float* alphai, float* beta, float* vsl, + lapack_int ldvsl, float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dggesx( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, char sense, + lapack_int n, double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* sdim, double* alphar, + double* alphai, double* beta, double* vsl, + lapack_int ldvsl, double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv ); +lapack_int LAPACKE_cggesx( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv ); +lapack_int LAPACKE_zggesx( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sggev( int matrix_order, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_dggev( int matrix_order, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, double* b, + lapack_int ldb, double* alphar, double* alphai, + double* beta, double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr ); +lapack_int LAPACKE_cggev( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_zggev( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr ); + +lapack_int LAPACKE_sggevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dggevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv ); +lapack_int LAPACKE_cggevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + float* lscale, float* rscale, float* abnrm, + float* bbnrm, float* rconde, float* rcondv ); +lapack_int LAPACKE_zggevx( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* abnrm, double* bbnrm, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sggglm( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, float* b, + lapack_int ldb, float* d, float* x, float* y ); +lapack_int LAPACKE_dggglm( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, double* b, + lapack_int ldb, double* d, double* x, double* y ); +lapack_int LAPACKE_cggglm( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* d, + lapack_complex_float* x, lapack_complex_float* y ); +lapack_int LAPACKE_zggglm( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* d, + lapack_complex_double* x, lapack_complex_double* y ); + +lapack_int LAPACKE_sgghrd( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, float* b, lapack_int ldb, + float* q, lapack_int ldq, float* z, lapack_int ldz ); +lapack_int LAPACKE_dgghrd( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, double* b, lapack_int ldb, + double* q, lapack_int ldq, double* z, + lapack_int ldz ); +lapack_int LAPACKE_cgghrd( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zgghrd( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_sgglse( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, float* a, lapack_int lda, float* b, + lapack_int ldb, float* c, float* d, float* x ); +lapack_int LAPACKE_dgglse( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, double* a, lapack_int lda, double* b, + lapack_int ldb, double* c, double* d, double* x ); +lapack_int LAPACKE_cgglse( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* c, + lapack_complex_float* d, lapack_complex_float* x ); +lapack_int LAPACKE_zgglse( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* c, + lapack_complex_double* d, lapack_complex_double* x ); + +lapack_int LAPACKE_sggqrf( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, float* taua, + float* b, lapack_int ldb, float* taub ); +lapack_int LAPACKE_dggqrf( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub ); +lapack_int LAPACKE_cggqrf( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub ); +lapack_int LAPACKE_zggqrf( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub ); + +lapack_int LAPACKE_sggrqf( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, float* taua, + float* b, lapack_int ldb, float* taub ); +lapack_int LAPACKE_dggrqf( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub ); +lapack_int LAPACKE_cggrqf( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub ); +lapack_int LAPACKE_zggrqf( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub ); + +lapack_int LAPACKE_sggsvd( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alpha, float* beta, float* u, lapack_int ldu, + float* v, lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork ); +lapack_int LAPACKE_dggsvd( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alpha, double* beta, double* u, + lapack_int ldu, double* v, lapack_int ldv, double* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_cggsvd( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, + lapack_int ldv, lapack_complex_float* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_zggsvd( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork ); + +lapack_int LAPACKE_sggsvp( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, float* u, + lapack_int ldu, float* v, lapack_int ldv, float* q, + lapack_int ldq ); +lapack_int LAPACKE_dggsvp( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq ); +lapack_int LAPACKE_cggsvp( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zggsvp( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, + lapack_int ldv, lapack_complex_double* q, + lapack_int ldq ); + +lapack_int LAPACKE_sgtcon( char norm, lapack_int n, const float* dl, + const float* d, const float* du, const float* du2, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_dgtcon( char norm, lapack_int n, const double* dl, + const double* d, const double* du, const double* du2, + const lapack_int* ipiv, double anorm, + double* rcond ); +lapack_int LAPACKE_cgtcon( char norm, lapack_int n, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zgtcon( char norm, lapack_int n, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sgtrfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* dl, const float* d, + const float* du, const float* dlf, const float* df, + const float* duf, const float* du2, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dgtrfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* dl, const double* d, + const double* du, const double* dlf, + const double* df, const double* duf, + const double* du2, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cgtrfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgtrfs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgtsv( int matrix_order, lapack_int n, lapack_int nrhs, + float* dl, float* d, float* du, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgtsv( int matrix_order, lapack_int n, lapack_int nrhs, + double* dl, double* d, double* du, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgtsv( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_float* dl, lapack_complex_float* d, + lapack_complex_float* du, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgtsv( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* dl, lapack_complex_double* d, + lapack_complex_double* du, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgtsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, const float* dl, + const float* d, const float* du, float* dlf, + float* df, float* duf, float* du2, lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dgtsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, const double* dl, + const double* d, const double* du, double* dlf, + double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cgtsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + lapack_complex_float* dlf, lapack_complex_float* df, + lapack_complex_float* duf, lapack_complex_float* du2, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_zgtsvx( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + lapack_complex_double* dlf, + lapack_complex_double* df, + lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_sgttrf( lapack_int n, float* dl, float* d, float* du, + float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_dgttrf( lapack_int n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv ); +lapack_int LAPACKE_cgttrf( lapack_int n, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_zgttrf( lapack_int n, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv ); + +lapack_int LAPACKE_sgttrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* dl, const float* d, + const float* du, const float* du2, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgttrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* dl, const double* d, + const double* du, const double* du2, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgttrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgttrs( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chbev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhbev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhbevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhbevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* q, lapack_int ldq, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chbgst( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* x, lapack_int ldx ); +lapack_int LAPACKE_zhbgst( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* bb, lapack_int ldbb, + lapack_complex_double* x, lapack_int ldx ); + +lapack_int LAPACKE_chbgv( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhbgv( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chbgvd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhbgvd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbgvx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhbgvx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + lapack_complex_double* q, lapack_int ldq, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chbtrd( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zhbtrd( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq ); + +lapack_int LAPACKE_checon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zhecon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_cheequb( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zheequb( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_cheev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_zheev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_cheevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_zheevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* w ); + +lapack_int LAPACKE_cheevr( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_zheevr( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz ); + +lapack_int LAPACKE_cheevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_zheevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chegst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhegst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chegv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w ); +lapack_int LAPACKE_zhegv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* w ); + +lapack_int LAPACKE_chegvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w ); +lapack_int LAPACKE_zhegvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* w ); + +lapack_int LAPACKE_chegvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhegvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_cherfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zherfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_cherfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zherfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_chesv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhesv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chesvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zhesvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_chesvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zhesvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_chetrd( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* d, + float* e, lapack_complex_float* tau ); +lapack_int LAPACKE_zhetrd( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* d, + double* e, lapack_complex_double* tau ); + +lapack_int LAPACKE_chetrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zhetrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_chetri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zhetri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_chetrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chfrk( int matrix_order, char transr, char uplo, char trans, + lapack_int n, lapack_int k, float alpha, + const lapack_complex_float* a, lapack_int lda, + float beta, lapack_complex_float* c ); +lapack_int LAPACKE_zhfrk( int matrix_order, char transr, char uplo, char trans, + lapack_int n, lapack_int k, double alpha, + const lapack_complex_double* a, lapack_int lda, + double beta, lapack_complex_double* c ); + +lapack_int LAPACKE_shgeqz( int matrix_order, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* h, lapack_int ldh, float* t, lapack_int ldt, + float* alphar, float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz ); +lapack_int LAPACKE_dhgeqz( int matrix_order, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* h, lapack_int ldh, double* t, lapack_int ldt, + double* alphar, double* alphai, double* beta, + double* q, lapack_int ldq, double* z, + lapack_int ldz ); +lapack_int LAPACKE_chgeqz( int matrix_order, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhgeqz( int matrix_order, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zhpcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_chpev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* ap, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhpevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* ap, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chpgst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* ap, + const lapack_complex_float* bp ); +lapack_int LAPACKE_zhpgst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* ap, + const lapack_complex_double* bp ); + +lapack_int LAPACKE_chpgv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpgv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpgvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpgvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpgvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_complex_float* bp, + float vl, float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_zhpgvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_complex_double* bp, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zhprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_chpsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhpsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chpsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zhpsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_chptrd( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, float* d, float* e, + lapack_complex_float* tau ); +lapack_int LAPACKE_zhptrd( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, double* d, double* e, + lapack_complex_double* tau ); + +lapack_int LAPACKE_chptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zhptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_chptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_zhptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, const lapack_int* ipiv ); + +lapack_int LAPACKE_chptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_shsein( int matrix_order, char job, char eigsrc, char initv, + lapack_logical* select, lapack_int n, const float* h, + lapack_int ldh, float* wr, const float* wi, + float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_dhsein( int matrix_order, char job, char eigsrc, char initv, + lapack_logical* select, lapack_int n, + const double* h, lapack_int ldh, double* wr, + const double* wi, double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m, lapack_int* ifaill, + lapack_int* ifailr ); +lapack_int LAPACKE_chsein( int matrix_order, char job, char eigsrc, char initv, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_zhsein( int matrix_order, char job, char eigsrc, char initv, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int ldvl, lapack_complex_double* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); + +lapack_int LAPACKE_shseqr( int matrix_order, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, float* h, + lapack_int ldh, float* wr, float* wi, float* z, + lapack_int ldz ); +lapack_int LAPACKE_dhseqr( int matrix_order, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, double* h, + lapack_int ldh, double* wr, double* wi, double* z, + lapack_int ldz ); +lapack_int LAPACKE_chseqr( int matrix_order, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhseqr( int matrix_order, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_clacgv( lapack_int n, lapack_complex_float* x, + lapack_int incx ); +lapack_int LAPACKE_zlacgv( lapack_int n, lapack_complex_double* x, + lapack_int incx ); + +lapack_int LAPACKE_slacn2( lapack_int n, float* v, float* x, lapack_int* isgn, + float* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_dlacn2( lapack_int n, double* v, double* x, lapack_int* isgn, + double* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_clacn2( lapack_int n, lapack_complex_float* v, + lapack_complex_float* x, + float* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_zlacn2( lapack_int n, lapack_complex_double* v, + lapack_complex_double* x, + double* est, lapack_int* kase, lapack_int* isave ); + +lapack_int LAPACKE_slacpy( int matrix_order, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dlacpy( int matrix_order, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_clacpy( int matrix_order, char uplo, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zlacpy( int matrix_order, char uplo, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_clacp2( int matrix_order, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zlacp2( int matrix_order, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_zlag2c( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_float* sa, lapack_int ldsa ); + +lapack_int LAPACKE_slag2d( int matrix_order, lapack_int m, lapack_int n, + const float* sa, lapack_int ldsa, double* a, + lapack_int lda ); + +lapack_int LAPACKE_dlag2s( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, float* sa, + lapack_int ldsa ); + +lapack_int LAPACKE_clag2z( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* sa, lapack_int ldsa, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slagge( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + float* a, lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_dlagge( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + double* a, lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_clagge( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + lapack_complex_float* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_zlagge( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + lapack_complex_double* a, lapack_int lda, + lapack_int* iseed ); + +float LAPACKE_slamch( char cmach ); +double LAPACKE_dlamch( char cmach ); + +float LAPACKE_slange( int matrix_order, char norm, lapack_int m, + lapack_int n, const float* a, lapack_int lda ); +double LAPACKE_dlange( int matrix_order, char norm, lapack_int m, + lapack_int n, const double* a, lapack_int lda ); +float LAPACKE_clange( int matrix_order, char norm, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda ); +double LAPACKE_zlange( int matrix_order, char norm, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda ); + +float LAPACKE_clanhe( int matrix_order, char norm, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda ); +double LAPACKE_zlanhe( int matrix_order, char norm, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda ); + +float LAPACKE_slansy( int matrix_order, char norm, char uplo, lapack_int n, + const float* a, lapack_int lda ); +double LAPACKE_dlansy( int matrix_order, char norm, char uplo, lapack_int n, + const double* a, lapack_int lda ); +float LAPACKE_clansy( int matrix_order, char norm, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda ); +double LAPACKE_zlansy( int matrix_order, char norm, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda ); + +float LAPACKE_slantr( int matrix_order, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const float* a, + lapack_int lda ); +double LAPACKE_dlantr( int matrix_order, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const double* a, + lapack_int lda ); +float LAPACKE_clantr( int matrix_order, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const lapack_complex_float* a, + lapack_int lda ); +double LAPACKE_zlantr( int matrix_order, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const lapack_complex_double* a, + lapack_int lda ); + + +lapack_int LAPACKE_slarfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dlarfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_clarfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zlarfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc ); + +lapack_int LAPACKE_slarfg( lapack_int n, float* alpha, float* x, + lapack_int incx, float* tau ); +lapack_int LAPACKE_dlarfg( lapack_int n, double* alpha, double* x, + lapack_int incx, double* tau ); +lapack_int LAPACKE_clarfg( lapack_int n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int incx, + lapack_complex_float* tau ); +lapack_int LAPACKE_zlarfg( lapack_int n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int incx, + lapack_complex_double* tau ); + +lapack_int LAPACKE_slarft( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* tau, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dlarft( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* tau, double* t, + lapack_int ldt ); +lapack_int LAPACKE_clarft( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* tau, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zlarft( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* tau, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_slarfx( int matrix_order, char side, lapack_int m, + lapack_int n, const float* v, float tau, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dlarfx( int matrix_order, char side, lapack_int m, + lapack_int n, const double* v, double tau, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_clarfx( int matrix_order, char side, lapack_int m, + lapack_int n, const lapack_complex_float* v, + lapack_complex_float tau, lapack_complex_float* c, + lapack_int ldc, lapack_complex_float* work ); +lapack_int LAPACKE_zlarfx( int matrix_order, char side, lapack_int m, + lapack_int n, const lapack_complex_double* v, + lapack_complex_double tau, lapack_complex_double* c, + lapack_int ldc, lapack_complex_double* work ); + +lapack_int LAPACKE_slarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + float* x ); +lapack_int LAPACKE_dlarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + double* x ); +lapack_int LAPACKE_clarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + lapack_complex_float* x ); +lapack_int LAPACKE_zlarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + lapack_complex_double* x ); + +lapack_int LAPACKE_slaset( int matrix_order, char uplo, lapack_int m, + lapack_int n, float alpha, float beta, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlaset( int matrix_order, char uplo, lapack_int m, + lapack_int n, double alpha, double beta, double* a, + lapack_int lda ); +lapack_int LAPACKE_claset( int matrix_order, char uplo, lapack_int m, + lapack_int n, lapack_complex_float alpha, + lapack_complex_float beta, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zlaset( int matrix_order, char uplo, lapack_int m, + lapack_int n, lapack_complex_double alpha, + lapack_complex_double beta, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_slasrt( char id, lapack_int n, float* d ); +lapack_int LAPACKE_dlasrt( char id, lapack_int n, double* d ); + +lapack_int LAPACKE_slaswp( int matrix_order, lapack_int n, float* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_dlaswp( int matrix_order, lapack_int n, double* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_claswp( int matrix_order, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int k1, lapack_int k2, const lapack_int* ipiv, + lapack_int incx ); +lapack_int LAPACKE_zlaswp( int matrix_order, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int k1, lapack_int k2, const lapack_int* ipiv, + lapack_int incx ); + +lapack_int LAPACKE_slatms( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, float* d, + lapack_int mode, float cond, float dmax, + lapack_int kl, lapack_int ku, char pack, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlatms( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, double* d, + lapack_int mode, double cond, double dmax, + lapack_int kl, lapack_int ku, char pack, double* a, + lapack_int lda ); +lapack_int LAPACKE_clatms( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, float* d, + lapack_int mode, float cond, float dmax, + lapack_int kl, lapack_int ku, char pack, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlatms( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, double* d, + lapack_int mode, double cond, double dmax, + lapack_int kl, lapack_int ku, char pack, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slauum( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlauum( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_clauum( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlauum( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_sopgtr( int matrix_order, char uplo, lapack_int n, + const float* ap, const float* tau, float* q, + lapack_int ldq ); +lapack_int LAPACKE_dopgtr( int matrix_order, char uplo, lapack_int n, + const double* ap, const double* tau, double* q, + lapack_int ldq ); + +lapack_int LAPACKE_sopmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, const float* ap, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dopmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, const double* ap, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sorgbr( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgbr( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, double* a, + lapack_int lda, const double* tau ); + +lapack_int LAPACKE_sorghr( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorghr( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorglq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorglq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgql( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgql( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgqr( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgqr( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgrq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgrq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgtr( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, const float* tau ); +lapack_int LAPACKE_dorgtr( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda, const double* tau ); + +lapack_int LAPACKE_sormbr( int matrix_order, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormbr( int matrix_order, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormhr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dormhr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormlq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormlq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormql( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormql( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormqr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormqr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormrq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormrq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormrz( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dormrz( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* tau, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dormtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* tau, double* c, + lapack_int ldc ); + +lapack_int LAPACKE_spbcon( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float anorm, float* rcond ); +lapack_int LAPACKE_dpbcon( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const double* ab, lapack_int ldab, + double anorm, double* rcond ); +lapack_int LAPACKE_cpbcon( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float anorm, float* rcond ); +lapack_int LAPACKE_zpbcon( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double anorm, double* rcond ); + +lapack_int LAPACKE_spbequ( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_dpbequ( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const double* ab, lapack_int ldab, + double* s, double* scond, double* amax ); +lapack_int LAPACKE_cpbequ( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_zpbequ( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); + +lapack_int LAPACKE_spbrfs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, lapack_int ldafb, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dpbrfs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const double* ab, + lapack_int ldab, const double* afb, lapack_int ldafb, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cpbrfs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, lapack_int ldafb, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zpbrfs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* afb, lapack_int ldafb, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_spbstf( int matrix_order, char uplo, lapack_int n, + lapack_int kb, float* bb, lapack_int ldbb ); +lapack_int LAPACKE_dpbstf( int matrix_order, char uplo, lapack_int n, + lapack_int kb, double* bb, lapack_int ldbb ); +lapack_int LAPACKE_cpbstf( int matrix_order, char uplo, lapack_int n, + lapack_int kb, lapack_complex_float* bb, + lapack_int ldbb ); +lapack_int LAPACKE_zpbstf( int matrix_order, char uplo, lapack_int n, + lapack_int kb, lapack_complex_double* bb, + lapack_int ldbb ); + +lapack_int LAPACKE_spbsv( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbsv( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbsv( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbsv( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spbsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* afb, lapack_int ldafb, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dpbsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* afb, lapack_int ldafb, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cpbsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* afb, lapack_int ldafb, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_zpbsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* afb, lapack_int ldafb, + char* equed, double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr ); + +lapack_int LAPACKE_spbtrf( int matrix_order, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab ); +lapack_int LAPACKE_dpbtrf( int matrix_order, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab ); +lapack_int LAPACKE_cpbtrf( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab ); +lapack_int LAPACKE_zpbtrf( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab ); + +lapack_int LAPACKE_spbtrs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbtrs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbtrs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbtrs( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spftrf( int matrix_order, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftrf( int matrix_order, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftrf( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftrf( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftri( int matrix_order, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftri( int matrix_order, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftri( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftri( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftrs( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpftrs( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpftrs( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpftrs( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spocon( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond ); +lapack_int LAPACKE_dpocon( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond ); +lapack_int LAPACKE_cpocon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond ); +lapack_int LAPACKE_zpocon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond ); + +lapack_int LAPACKE_spoequ( int matrix_order, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequ( int matrix_order, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequ( int matrix_order, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequ( int matrix_order, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_spoequb( int matrix_order, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequb( int matrix_order, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequb( int matrix_order, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequb( int matrix_order, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_sporfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dporfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_cporfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_zporfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr ); + +lapack_int LAPACKE_sporfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const float* s, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dporfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const double* s, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cporfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zporfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const double* s, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* x, lapack_int ldx, + lapack_int* iter ); +lapack_int LAPACKE_zcposv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_int* iter ); + +lapack_int LAPACKE_sposvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* af, + lapack_int ldaf, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_dposvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* af, lapack_int ldaf, char* equed, double* s, + double* b, lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); +lapack_int LAPACKE_cposvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zposvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_sposvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_dposvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cposvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zposvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_spotrf( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dpotrf( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_cpotrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotri( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dpotri( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_cpotri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpotrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpotrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zpotrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sppcon( int matrix_order, char uplo, lapack_int n, + const float* ap, float anorm, float* rcond ); +lapack_int LAPACKE_dppcon( int matrix_order, char uplo, lapack_int n, + const double* ap, double anorm, double* rcond ); +lapack_int LAPACKE_cppcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, float anorm, + float* rcond ); +lapack_int LAPACKE_zppcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, double anorm, + double* rcond ); + +lapack_int LAPACKE_sppequ( int matrix_order, char uplo, lapack_int n, + const float* ap, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dppequ( int matrix_order, char uplo, lapack_int n, + const double* ap, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cppequ( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_zppequ( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, double* s, + double* scond, double* amax ); + +lapack_int LAPACKE_spprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, const float* afp, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dpprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, const double* afp, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cpprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zpprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sppsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dppsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cppsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zppsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sppsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* afp, char* equed, + float* s, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dppsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* afp, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cppsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* afp, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zppsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* afp, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_spptrf( int matrix_order, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptrf( int matrix_order, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptri( int matrix_order, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptri( int matrix_order, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spstrf( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, lapack_int* piv, lapack_int* rank, + float tol ); +lapack_int LAPACKE_dpstrf( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda, lapack_int* piv, lapack_int* rank, + double tol ); +lapack_int LAPACKE_cpstrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, float tol ); +lapack_int LAPACKE_zpstrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, double tol ); + +lapack_int LAPACKE_sptcon( lapack_int n, const float* d, const float* e, + float anorm, float* rcond ); +lapack_int LAPACKE_dptcon( lapack_int n, const double* d, const double* e, + double anorm, double* rcond ); +lapack_int LAPACKE_cptcon( lapack_int n, const float* d, + const lapack_complex_float* e, float anorm, + float* rcond ); +lapack_int LAPACKE_zptcon( lapack_int n, const double* d, + const lapack_complex_double* e, double anorm, + double* rcond ); + +lapack_int LAPACKE_spteqr( int matrix_order, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dpteqr( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_cpteqr( int matrix_order, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zpteqr( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_sptrfs( int matrix_order, lapack_int n, lapack_int nrhs, + const float* d, const float* e, const float* df, + const float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dptrfs( int matrix_order, lapack_int n, lapack_int nrhs, + const double* d, const double* e, const double* df, + const double* ef, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* ferr, + double* berr ); +lapack_int LAPACKE_cptrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zptrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, const double* df, + const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sptsv( int matrix_order, lapack_int n, lapack_int nrhs, + float* d, float* e, float* b, lapack_int ldb ); +lapack_int LAPACKE_dptsv( int matrix_order, lapack_int n, lapack_int nrhs, + double* d, double* e, double* b, lapack_int ldb ); +lapack_int LAPACKE_cptsv( int matrix_order, lapack_int n, lapack_int nrhs, + float* d, lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zptsv( int matrix_order, lapack_int n, lapack_int nrhs, + double* d, lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sptsvx( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const float* d, const float* e, + float* df, float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dptsvx( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const double* d, const double* e, + double* df, double* ef, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); +lapack_int LAPACKE_cptsvx( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zptsvx( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, double* df, + lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_spttrf( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dpttrf( lapack_int n, double* d, double* e ); +lapack_int LAPACKE_cpttrf( lapack_int n, float* d, lapack_complex_float* e ); +lapack_int LAPACKE_zpttrf( lapack_int n, double* d, lapack_complex_double* e ); + +lapack_int LAPACKE_spttrs( int matrix_order, lapack_int n, lapack_int nrhs, + const float* d, const float* e, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpttrs( int matrix_order, lapack_int n, lapack_int nrhs, + const double* d, const double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpttrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpttrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssbev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbev( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, double* w, + double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbevd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsbevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* q, lapack_int ldq, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssbgst( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, const float* bb, lapack_int ldbb, + float* x, lapack_int ldx ); +lapack_int LAPACKE_dsbgst( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, const double* bb, lapack_int ldbb, + double* x, lapack_int ldx ); + +lapack_int LAPACKE_ssbgv( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, float* bb, lapack_int ldbb, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbgv( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, double* bb, lapack_int ldbb, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbgvd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, float* bb, lapack_int ldbb, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbgvd( int matrix_order, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, double* bb, lapack_int ldbb, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbgvx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsbgvx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* q, lapack_int ldq, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssbtrd( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* d, + float* e, float* q, lapack_int ldq ); +lapack_int LAPACKE_dsbtrd( int matrix_order, char vect, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq ); + +lapack_int LAPACKE_ssfrk( int matrix_order, char transr, char uplo, char trans, + lapack_int n, lapack_int k, float alpha, + const float* a, lapack_int lda, float beta, + float* c ); +lapack_int LAPACKE_dsfrk( int matrix_order, char transr, char uplo, char trans, + lapack_int n, lapack_int k, double alpha, + const double* a, lapack_int lda, double beta, + double* c ); + +lapack_int LAPACKE_sspcon( int matrix_order, char uplo, lapack_int n, + const float* ap, const lapack_int* ipiv, float anorm, + float* rcond ); +lapack_int LAPACKE_dspcon( int matrix_order, char uplo, lapack_int n, + const double* ap, const lapack_int* ipiv, + double anorm, double* rcond ); +lapack_int LAPACKE_cspcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zspcon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sspev( int matrix_order, char jobz, char uplo, lapack_int n, + float* ap, float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspev( int matrix_order, char jobz, char uplo, lapack_int n, + double* ap, double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspevd( int matrix_order, char jobz, char uplo, lapack_int n, + float* ap, float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspevd( int matrix_order, char jobz, char uplo, lapack_int n, + double* ap, double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, float* ap, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dspevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, double* ap, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_sspgst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, float* ap, const float* bp ); +lapack_int LAPACKE_dspgst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, double* ap, const double* bp ); + +lapack_int LAPACKE_sspgv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspgv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspgvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspgvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspgvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* ap, + float* bp, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + float* z, lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_dspgvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* ap, + double* bp, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_ssprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, const float* afp, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dsprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, const double* afp, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_csprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zsprfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sspsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* ap, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dspsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* ap, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cspsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zspsv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sspsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* afp, + lapack_int* ipiv, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dspsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* afp, + lapack_int* ipiv, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cspsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zspsvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_ssptrd( int matrix_order, char uplo, lapack_int n, float* ap, + float* d, float* e, float* tau ); +lapack_int LAPACKE_dsptrd( int matrix_order, char uplo, lapack_int n, + double* ap, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssptrf( int matrix_order, char uplo, lapack_int n, float* ap, + lapack_int* ipiv ); +lapack_int LAPACKE_dsptrf( int matrix_order, char uplo, lapack_int n, + double* ap, lapack_int* ipiv ); +lapack_int LAPACKE_csptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zsptrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_ssptri( int matrix_order, char uplo, lapack_int n, float* ap, + const lapack_int* ipiv ); +lapack_int LAPACKE_dsptri( int matrix_order, char uplo, lapack_int n, + double* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_csptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_zsptri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, const lapack_int* ipiv ); + +lapack_int LAPACKE_ssptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zsptrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sstebz( char range, char order, lapack_int n, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + const float* d, const float* e, lapack_int* m, + lapack_int* nsplit, float* w, lapack_int* iblock, + lapack_int* isplit ); +lapack_int LAPACKE_dstebz( char range, char order, lapack_int n, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, const double* d, const double* e, + lapack_int* m, lapack_int* nsplit, double* w, + lapack_int* iblock, lapack_int* isplit ); + +lapack_int LAPACKE_sstedc( int matrix_order, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstedc( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_cstedc( int matrix_order, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zstedc( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_sstegr( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dstegr( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); +lapack_int LAPACKE_cstegr( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* isuppz ); +lapack_int LAPACKE_zstegr( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz ); + +lapack_int LAPACKE_sstein( int matrix_order, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, const lapack_int* isplit, + float* z, lapack_int ldz, lapack_int* ifailv ); +lapack_int LAPACKE_dstein( int matrix_order, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, const lapack_int* isplit, + double* z, lapack_int ldz, lapack_int* ifailv ); +lapack_int LAPACKE_cstein( int matrix_order, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, const lapack_int* isplit, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifailv ); +lapack_int LAPACKE_zstein( int matrix_order, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, const lapack_int* isplit, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifailv ); + +lapack_int LAPACKE_sstemr( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, lapack_int* m, + float* w, float* z, lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac ); +lapack_int LAPACKE_dstemr( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, double* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); +lapack_int LAPACKE_cstemr( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, lapack_int* m, + float* w, lapack_complex_float* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); +lapack_int LAPACKE_zstemr( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int ldz, lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); + +lapack_int LAPACKE_ssteqr( int matrix_order, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dsteqr( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_csteqr( int matrix_order, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zsteqr( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_ssterf( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dsterf( lapack_int n, double* d, double* e ); + +lapack_int LAPACKE_sstev( int matrix_order, char jobz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstev( int matrix_order, char jobz, lapack_int n, double* d, + double* e, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sstevd( int matrix_order, char jobz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstevd( int matrix_order, char jobz, lapack_int n, double* d, + double* e, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sstevr( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dstevr( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); + +lapack_int LAPACKE_sstevx( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dstevx( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssycon( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_dsycon( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); +lapack_int LAPACKE_csycon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zsycon( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_ssyequb( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_dsyequb( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax ); +lapack_int LAPACKE_csyequb( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zsyequb( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_ssyev( int matrix_order, char jobz, char uplo, lapack_int n, + float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_dsyev( int matrix_order, char jobz, char uplo, lapack_int n, + double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_ssyevd( int matrix_order, char jobz, char uplo, lapack_int n, + float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_dsyevd( int matrix_order, char jobz, char uplo, lapack_int n, + double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_ssyevr( int matrix_order, char jobz, char range, char uplo, + lapack_int n, float* a, lapack_int lda, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dsyevr( int matrix_order, char jobz, char range, char uplo, + lapack_int n, double* a, lapack_int lda, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); + +lapack_int LAPACKE_ssyevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, float* a, lapack_int lda, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsyevx( int matrix_order, char jobz, char range, char uplo, + lapack_int n, double* a, lapack_int lda, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssygst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, float* a, lapack_int lda, + const float* b, lapack_int ldb ); +lapack_int LAPACKE_dsygst( int matrix_order, lapack_int itype, char uplo, + lapack_int n, double* a, lapack_int lda, + const double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssygv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float* w ); +lapack_int LAPACKE_dsygv( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* w ); + +lapack_int LAPACKE_ssygvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float* w ); +lapack_int LAPACKE_dsygvd( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* w ); + +lapack_int LAPACKE_ssygvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsygvx( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssyrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dsyrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_csyrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zsyrfs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_ssyrfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dsyrfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_csyrfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zsyrfsx( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_ssysv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsysv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csysv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsysv( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssysvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* af, lapack_int ldaf, lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dsysvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + double* af, lapack_int ldaf, lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr ); +lapack_int LAPACKE_csysvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zsysvx( int matrix_order, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_ssysvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dsysvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_csysvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zsysvxx( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_ssytrd( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, float* d, float* e, float* tau ); +lapack_int LAPACKE_dsytrd( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssytrf( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dsytrf( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_csytrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zsytrf( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_ssytri( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dsytri( int matrix_order, char uplo, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_csytri( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zsytri( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_ssytrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsytrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stbcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, const float* ab, + lapack_int ldab, float* rcond ); +lapack_int LAPACKE_dtbcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, const double* ab, + lapack_int ldab, double* rcond ); +lapack_int LAPACKE_ctbcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_float* ab, lapack_int ldab, + float* rcond ); +lapack_int LAPACKE_ztbcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_double* ab, lapack_int ldab, + double* rcond ); + +lapack_int LAPACKE_stbrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const float* ab, lapack_int ldab, const float* b, + lapack_int ldb, const float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dtbrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_ctbrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztbrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_stbtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const float* ab, lapack_int ldab, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtbtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctbtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztbtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stfsm( int matrix_order, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + float alpha, const float* a, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtfsm( int matrix_order, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + double alpha, const double* a, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctfsm( int matrix_order, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztfsm( int matrix_order, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stftri( int matrix_order, char transr, char uplo, char diag, + lapack_int n, float* a ); +lapack_int LAPACKE_dtftri( int matrix_order, char transr, char uplo, char diag, + lapack_int n, double* a ); +lapack_int LAPACKE_ctftri( int matrix_order, char transr, char uplo, char diag, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_ztftri( int matrix_order, char transr, char uplo, char diag, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_stfttp( int matrix_order, char transr, char uplo, + lapack_int n, const float* arf, float* ap ); +lapack_int LAPACKE_dtfttp( int matrix_order, char transr, char uplo, + lapack_int n, const double* arf, double* ap ); +lapack_int LAPACKE_ctfttp( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztfttp( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stfttr( int matrix_order, char transr, char uplo, + lapack_int n, const float* arf, float* a, + lapack_int lda ); +lapack_int LAPACKE_dtfttr( int matrix_order, char transr, char uplo, + lapack_int n, const double* arf, double* a, + lapack_int lda ); +lapack_int LAPACKE_ctfttr( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztfttr( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_stgevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const float* s, lapack_int lds, const float* p, + lapack_int ldp, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_dtgevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const double* s, lapack_int lds, const double* p, + lapack_int ldp, double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_ctgevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* s, lapack_int lds, + const lapack_complex_float* p, lapack_int ldp, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztgevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* s, lapack_int lds, + const lapack_complex_double* p, lapack_int ldp, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); + +lapack_int LAPACKE_stgexc( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float* q, + lapack_int ldq, float* z, lapack_int ldz, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_dtgexc( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, double* q, + lapack_int ldq, double* z, lapack_int ldz, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_ctgexc( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztgexc( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_stgsen( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz, + lapack_int* m, float* pl, float* pr, float* dif ); +lapack_int LAPACKE_dtgsen( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + double* a, lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* q, lapack_int ldq, double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, double* dif ); +lapack_int LAPACKE_ctgsen( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* z, + lapack_int ldz, lapack_int* m, float* pl, float* pr, + float* dif ); +lapack_int LAPACKE_ztgsen( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, double* dif ); + +lapack_int LAPACKE_stgsja( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, float* a, lapack_int lda, + float* b, lapack_int ldb, float tola, float tolb, + float* alpha, float* beta, float* u, lapack_int ldu, + float* v, lapack_int ldv, float* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_dtgsja( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, double* a, + lapack_int lda, double* b, lapack_int ldb, + double tola, double tolb, double* alpha, + double* beta, double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_ctgsja( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float tola, float tolb, float* alpha, + float* beta, lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_ztgsja( int matrix_order, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double tola, double tolb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* ncycle ); + +lapack_int LAPACKE_stgsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* vl, lapack_int ldvl, + const float* vr, lapack_int ldvr, float* s, + float* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_dtgsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* a, lapack_int lda, const double* b, + lapack_int ldb, const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ctgsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztgsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* vl, lapack_int ldvl, + const lapack_complex_double* vr, lapack_int ldvr, + double* s, double* dif, lapack_int mm, + lapack_int* m ); + +lapack_int LAPACKE_stgsyl( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + float* c, lapack_int ldc, const float* d, + lapack_int ldd, const float* e, lapack_int lde, + float* f, lapack_int ldf, float* scale, float* dif ); +lapack_int LAPACKE_dtgsyl( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + double* c, lapack_int ldc, const double* d, + lapack_int ldd, const double* e, lapack_int lde, + double* f, lapack_int ldf, double* scale, + double* dif ); +lapack_int LAPACKE_ctgsyl( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + const lapack_complex_float* d, lapack_int ldd, + const lapack_complex_float* e, lapack_int lde, + lapack_complex_float* f, lapack_int ldf, + float* scale, float* dif ); +lapack_int LAPACKE_ztgsyl( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + const lapack_complex_double* d, lapack_int ldd, + const lapack_complex_double* e, lapack_int lde, + lapack_complex_double* f, lapack_int ldf, + double* scale, double* dif ); + +lapack_int LAPACKE_stpcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const float* ap, float* rcond ); +lapack_int LAPACKE_dtpcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const double* ap, double* rcond ); +lapack_int LAPACKE_ctpcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_float* ap, + float* rcond ); +lapack_int LAPACKE_ztpcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_double* ap, + double* rcond ); + +lapack_int LAPACKE_stprfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* ap, + const float* b, lapack_int ldb, const float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dtprfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* ap, + const double* b, lapack_int ldb, const double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_ctprfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztprfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_stptri( int matrix_order, char uplo, char diag, lapack_int n, + float* ap ); +lapack_int LAPACKE_dtptri( int matrix_order, char uplo, char diag, lapack_int n, + double* ap ); +lapack_int LAPACKE_ctptri( int matrix_order, char uplo, char diag, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztptri( int matrix_order, char uplo, char diag, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stptrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* ap, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dtptrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* ap, + double* b, lapack_int ldb ); +lapack_int LAPACKE_ctptrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztptrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stpttf( int matrix_order, char transr, char uplo, + lapack_int n, const float* ap, float* arf ); +lapack_int LAPACKE_dtpttf( int matrix_order, char transr, char uplo, + lapack_int n, const double* ap, double* arf ); +lapack_int LAPACKE_ctpttf( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* ap, + lapack_complex_float* arf ); +lapack_int LAPACKE_ztpttf( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* ap, + lapack_complex_double* arf ); + +lapack_int LAPACKE_stpttr( int matrix_order, char uplo, lapack_int n, + const float* ap, float* a, lapack_int lda ); +lapack_int LAPACKE_dtpttr( int matrix_order, char uplo, lapack_int n, + const double* ap, double* a, lapack_int lda ); +lapack_int LAPACKE_ctpttr( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztpttr( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const float* a, lapack_int lda, + float* rcond ); +lapack_int LAPACKE_dtrcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const double* a, lapack_int lda, + double* rcond ); +lapack_int LAPACKE_ctrcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* rcond ); +lapack_int LAPACKE_ztrcon( int matrix_order, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* rcond ); + +lapack_int LAPACKE_strevc( int matrix_order, char side, char howmny, + lapack_logical* select, lapack_int n, const float* t, + lapack_int ldt, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_dtrevc( int matrix_order, char side, char howmny, + lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ctrevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztrevc( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); + +lapack_int LAPACKE_strexc( int matrix_order, char compq, lapack_int n, float* t, + lapack_int ldt, float* q, lapack_int ldq, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_dtrexc( int matrix_order, char compq, lapack_int n, + double* t, lapack_int ldt, double* q, lapack_int ldq, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_ctrexc( int matrix_order, char compq, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztrexc( int matrix_order, char compq, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_strrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_dtrrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + const double* x, lapack_int ldx, double* ferr, + double* berr ); +lapack_int LAPACKE_ctrrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztrrfs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_strsen( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, float* t, + lapack_int ldt, float* q, lapack_int ldq, float* wr, + float* wi, lapack_int* m, float* s, float* sep ); +lapack_int LAPACKE_dtrsen( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + double* t, lapack_int ldt, double* q, lapack_int ldq, + double* wr, double* wi, lapack_int* m, double* s, + double* sep ); +lapack_int LAPACKE_ctrsen( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* w, lapack_int* m, float* s, + float* sep ); +lapack_int LAPACKE_ztrsen( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* w, lapack_int* m, double* s, + double* sep ); + +lapack_int LAPACKE_strsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, const float* vl, + lapack_int ldvl, const float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_dtrsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, const double* vl, + lapack_int ldvl, const double* vr, lapack_int ldvr, + double* s, double* sep, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_ctrsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* t, lapack_int ldt, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztrsna( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* t, lapack_int ldt, + const lapack_complex_double* vl, lapack_int ldvl, + const lapack_complex_double* vr, lapack_int ldvr, + double* s, double* sep, lapack_int mm, + lapack_int* m ); + +lapack_int LAPACKE_strsyl( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_dtrsyl( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const double* a, lapack_int lda, const double* b, + lapack_int ldb, double* c, lapack_int ldc, + double* scale ); +lapack_int LAPACKE_ctrsyl( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_ztrsyl( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + double* scale ); + +lapack_int LAPACKE_strtri( int matrix_order, char uplo, char diag, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dtrtri( int matrix_order, char uplo, char diag, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_ctrtri( int matrix_order, char uplo, char diag, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztrtri( int matrix_order, char uplo, char diag, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtrtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctrtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztrtrs( int matrix_order, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_strttf( int matrix_order, char transr, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* arf ); +lapack_int LAPACKE_dtrttf( int matrix_order, char transr, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* arf ); +lapack_int LAPACKE_ctrttf( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* arf ); +lapack_int LAPACKE_ztrttf( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* arf ); + +lapack_int LAPACKE_strttp( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float* ap ); +lapack_int LAPACKE_dtrttp( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double* ap ); +lapack_int LAPACKE_ctrttp( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztrttp( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stzrzf( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dtzrzf( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_ctzrzf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_ztzrzf( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_cungbr( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungbr( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunghr( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zunghr( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunglq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zunglq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungql( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungql( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungqr( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungqr( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungrq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungrq( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungtr( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau ); +lapack_int LAPACKE_zungtr( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunmbr( int matrix_order, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmbr( int matrix_order, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmhr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmhr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmlq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmlq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmql( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmql( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmqr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmqr( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmrq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmrq( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmrz( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmrz( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cupgtr( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zupgtr( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* q, lapack_int ldq ); + +lapack_int LAPACKE_cupmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zupmtr( int matrix_order, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sbdsdc_work( int matrix_order, char uplo, char compq, + lapack_int n, float* d, float* e, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, + float* q, lapack_int* iq, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dbdsdc_work( int matrix_order, char uplo, char compq, + lapack_int n, double* d, double* e, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* q, lapack_int* iq, double* work, + lapack_int* iwork ); + +lapack_int LAPACKE_sbdsqr_work( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, float* vt, lapack_int ldvt, + float* u, lapack_int ldu, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dbdsqr_work( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, double* vt, + lapack_int ldvt, double* u, lapack_int ldu, + double* c, lapack_int ldc, double* work ); +lapack_int LAPACKE_cbdsqr_work( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_zbdsqr_work( int matrix_order, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* c, + lapack_int ldc, double* work ); + +lapack_int LAPACKE_sdisna_work( char job, lapack_int m, lapack_int n, + const float* d, float* sep ); +lapack_int LAPACKE_ddisna_work( char job, lapack_int m, lapack_int n, + const double* d, double* sep ); + +lapack_int LAPACKE_sgbbrd_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, float* ab, lapack_int ldab, + float* d, float* e, float* q, lapack_int ldq, + float* pt, lapack_int ldpt, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dgbbrd_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq, + double* pt, lapack_int ldpt, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_cgbbrd_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* pt, lapack_int ldpt, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgbbrd_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* pt, lapack_int ldpt, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbcon_work( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbcon_work( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbcon_work( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbcon_work( int matrix_order, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbequ_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequ_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequ_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgbequ_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbequb_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequb_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequb_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_zgbequb_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const float* afb, lapack_int ldafb, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgbrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbrfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbrfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const double* ab, + lapack_int ldab, const double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbrfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, + const lapack_complex_float* ab, + lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbrfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbsv_work( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, float* ab, + lapack_int ldab, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbsv_work( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, double* ab, + lapack_int ldab, lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbsv_work( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbsv_work( int matrix_order, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgbsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgbsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgbsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbsvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbsvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbsvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbsvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbtrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, float* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_dgbtrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, double* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_cgbtrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv ); +lapack_int LAPACKE_zgbtrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgbtrs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbtrs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbtrs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbtrs_work( int matrix_order, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgebak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* scale, lapack_int m, float* v, + lapack_int ldv ); +lapack_int LAPACKE_dgebak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* scale, lapack_int m, double* v, + lapack_int ldv ); +lapack_int LAPACKE_cgebak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* scale, lapack_int m, + lapack_complex_float* v, lapack_int ldv ); +lapack_int LAPACKE_zgebak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* scale, lapack_int m, + lapack_complex_double* v, lapack_int ldv ); + +lapack_int LAPACKE_sgebal_work( int matrix_order, char job, lapack_int n, + float* a, lapack_int lda, lapack_int* ilo, + lapack_int* ihi, float* scale ); +lapack_int LAPACKE_dgebal_work( int matrix_order, char job, lapack_int n, + double* a, lapack_int lda, lapack_int* ilo, + lapack_int* ihi, double* scale ); +lapack_int LAPACKE_cgebal_work( int matrix_order, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, + float* scale ); +lapack_int LAPACKE_zgebal_work( int matrix_order, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, + double* scale ); + +lapack_int LAPACKE_sgebrd_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tauq, float* taup, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgebrd_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tauq, double* taup, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgebrd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* d, float* e, lapack_complex_float* tauq, + lapack_complex_float* taup, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgebrd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* d, double* e, + lapack_complex_double* tauq, + lapack_complex_double* taup, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgecon_work( int matrix_order, char norm, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgecon_work( int matrix_order, char norm, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgecon_work( int matrix_order, char norm, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgecon_work( int matrix_order, char norm, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgeequ_work( int matrix_order, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, + float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_dgeequ_work( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequ_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgeequ_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgeequb_work( int matrix_order, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, + float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_dgeequb_work( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequb_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgeequb_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgees_work( int matrix_order, char jobvs, char sort, + LAPACK_S_SELECT2 select, lapack_int n, float* a, + lapack_int lda, lapack_int* sdim, float* wr, + float* wi, float* vs, lapack_int ldvs, + float* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgees_work( int matrix_order, char jobvs, char sort, + LAPACK_D_SELECT2 select, lapack_int n, double* a, + lapack_int lda, lapack_int* sdim, double* wr, + double* wi, double* vs, lapack_int ldvs, + double* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgees_work( int matrix_order, char jobvs, char sort, + LAPACK_C_SELECT1 select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgees_work( int matrix_order, char jobvs, char sort, + LAPACK_Z_SELECT1 select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sgeesx_work( int matrix_order, char jobvs, char sort, + LAPACK_S_SELECT2 select, char sense, + lapack_int n, float* a, lapack_int lda, + lapack_int* sdim, float* wr, float* wi, + float* vs, lapack_int ldvs, float* rconde, + float* rcondv, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgeesx_work( int matrix_order, char jobvs, char sort, + LAPACK_D_SELECT2 select, char sense, + lapack_int n, double* a, lapack_int lda, + lapack_int* sdim, double* wr, double* wi, + double* vs, lapack_int ldvs, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgeesx_work( int matrix_order, char jobvs, char sort, + LAPACK_C_SELECT1 select, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_int* sdim, + lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgeesx_work( int matrix_order, char jobvs, char sort, + LAPACK_Z_SELECT1 select, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_int* sdim, + lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sgeev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, + float* wr, float* wi, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgeev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, + double* wr, double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgeevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* wr, float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgeevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* wr, double* wi, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, double* scale, double* abnrm, + double* rconde, double* rcondv, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgeevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* scale, + double* abnrm, double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgehrd_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgehrd_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + double* tau, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgehrd_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgehrd_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgejsv_work( int matrix_order, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, float* a, + lapack_int lda, float* sva, float* u, + lapack_int ldu, float* v, lapack_int ldv, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgejsv_work( int matrix_order, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* sva, double* u, + lapack_int ldu, double* v, lapack_int ldv, + double* work, lapack_int lwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sgelq2_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work ); +lapack_int LAPACKE_dgelq2_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work ); +lapack_int LAPACKE_cgelq2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zgelq2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sgelqf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgelqf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgelqf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgelqf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgels_work( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgels_work( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgels_work( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgels_work( int matrix_order, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgelsd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, float* s, float rcond, + lapack_int* rank, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgelsd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, + double rcond, lapack_int* rank, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgelsd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork ); +lapack_int LAPACKE_zgelsd_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sgelss_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, float* s, float rcond, + lapack_int* rank, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgelss_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, + double rcond, lapack_int* rank, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgelss_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgelss_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgelsy_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, lapack_int* jpvt, + float rcond, lapack_int* rank, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgelsy_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* jpvt, + double rcond, lapack_int* rank, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgelsy_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgelsy_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* jpvt, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgeqlf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqlf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqlf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqlf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgeqp3_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqp3_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqp3_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeqp3_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgeqpf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau, float* work ); +lapack_int LAPACKE_dgeqpf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau, double* work ); +lapack_int LAPACKE_cgeqpf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgeqpf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgeqr2_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work ); +lapack_int LAPACKE_dgeqr2_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work ); +lapack_int LAPACKE_cgeqr2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zgeqr2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqrf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgeqrfp_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqrfp_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqrfp_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqrfp_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sgerfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgerfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgerfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgerfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgerfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* r, const float* c, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgerfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* r, const double* c, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgerfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgerfsx_work( int matrix_order, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgerqf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgerqf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgerqf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgerqf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgesdd_work( int matrix_order, char jobz, lapack_int m, + lapack_int n, float* a, lapack_int lda, + float* s, float* u, lapack_int ldu, float* vt, + lapack_int ldvt, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgesdd_work( int matrix_order, char jobz, lapack_int m, + lapack_int n, double* a, lapack_int lda, + double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgesdd_work( int matrix_order, char jobz, lapack_int m, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* vt, lapack_int ldvt, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork ); +lapack_int LAPACKE_zgesdd_work( int matrix_order, char jobz, lapack_int m, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* vt, lapack_int ldvt, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork ); + +lapack_int LAPACKE_sgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + float* a, lapack_int lda, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* work, float* swork, + lapack_int* iter ); +lapack_int LAPACKE_zcgesv_work( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + lapack_complex_float* swork, double* rwork, + lapack_int* iter ); + +lapack_int LAPACKE_sgesvd_work( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, float* a, + lapack_int lda, float* s, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgesvd_work( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* s, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgesvd_work( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgesvd_work( int matrix_order, char jobu, char jobvt, + lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgesvj_work( int matrix_order, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, float* a, + lapack_int lda, float* sva, lapack_int mv, + float* v, lapack_int ldv, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgesvj_work( int matrix_order, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* sva, + lapack_int mv, double* v, lapack_int ldv, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgesvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgesvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgesvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgesvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgesvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgesvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgesvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgesvxx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgetf2_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetf2_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetf2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetf2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetri_work( int matrix_order, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgetri_work( int matrix_order, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgetri_work( int matrix_order, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgetri_work( int matrix_order, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgetrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgetrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgetrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgetrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sggbak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* lscale, const float* rscale, + lapack_int m, float* v, lapack_int ldv ); +lapack_int LAPACKE_dggbak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* lscale, const double* rscale, + lapack_int m, double* v, lapack_int ldv ); +lapack_int LAPACKE_cggbak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* lscale, const float* rscale, + lapack_int m, lapack_complex_float* v, + lapack_int ldv ); +lapack_int LAPACKE_zggbak_work( int matrix_order, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* lscale, const double* rscale, + lapack_int m, lapack_complex_double* v, + lapack_int ldv ); + +lapack_int LAPACKE_sggbal_work( int matrix_order, char job, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, + float* work ); +lapack_int LAPACKE_dggbal_work( int matrix_order, char job, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* work ); +lapack_int LAPACKE_cggbal_work( int matrix_order, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* work ); +lapack_int LAPACKE_zggbal_work( int matrix_order, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* work ); + +lapack_int LAPACKE_sgges_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* sdim, float* alphar, + float* alphai, float* beta, float* vsl, + lapack_int ldvsl, float* vsr, lapack_int ldvsr, + float* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgges_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* sdim, double* alphar, + double* alphai, double* beta, double* vsl, + lapack_int ldvsl, double* vsr, lapack_int ldvsr, + double* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgges_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgges_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sggesx_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, char sense, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, lapack_int* sdim, + float* alphar, float* alphai, float* beta, + float* vsl, lapack_int ldvsl, float* vsr, + lapack_int ldvsr, float* rconde, float* rcondv, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dggesx_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, char sense, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* sdim, + double* alphar, double* alphai, double* beta, + double* vsl, lapack_int ldvsl, double* vsr, + lapack_int ldvsr, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cggesx_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork, + lapack_int liwork, lapack_logical* bwork ); +lapack_int LAPACKE_zggesx_work( int matrix_order, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork, + lapack_int liwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sggev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dggev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* alphar, + double* alphai, double* beta, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cggev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zggev_work( int matrix_order, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sggevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, + float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, + float* abnrm, float* bbnrm, float* rconde, + float* rcondv, float* work, lapack_int lwork, + lapack_int* iwork, lapack_logical* bwork ); +lapack_int LAPACKE_dggevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* abnrm, double* bbnrm, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_logical* bwork ); +lapack_int LAPACKE_cggevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork, + lapack_logical* bwork ); +lapack_int LAPACKE_zggevx_work( int matrix_order, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork, + lapack_logical* bwork ); + +lapack_int LAPACKE_sggglm_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, + float* b, lapack_int ldb, float* d, float* x, + float* y, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggglm_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* b, lapack_int ldb, double* d, double* x, + double* y, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggglm_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* d, + lapack_complex_float* x, + lapack_complex_float* y, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggglm_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* d, + lapack_complex_double* x, + lapack_complex_double* y, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgghrd_work( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* q, lapack_int ldq, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dgghrd_work( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* q, lapack_int ldq, + double* z, lapack_int ldz ); +lapack_int LAPACKE_cgghrd_work( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zgghrd_work( int matrix_order, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_sgglse_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, float* a, lapack_int lda, + float* b, lapack_int ldb, float* c, float* d, + float* x, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgglse_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, double* a, lapack_int lda, + double* b, lapack_int ldb, double* c, double* d, + double* x, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgglse_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* c, + lapack_complex_float* d, + lapack_complex_float* x, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgglse_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* c, + lapack_complex_double* d, + lapack_complex_double* x, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggqrf_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, + float* taua, float* b, lapack_int ldb, + float* taub, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggqrf_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggqrf_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggqrf_work( int matrix_order, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggrqf_work( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, + float* taua, float* b, lapack_int ldb, + float* taub, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggrqf_work( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggrqf_work( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggrqf_work( int matrix_order, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggsvd_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* alpha, float* beta, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dggsvd_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* alpha, double* beta, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cggsvd_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* work, float* rwork, + lapack_int* iwork ); +lapack_int LAPACKE_zggsvd_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* work, double* rwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sggsvp_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork, float* tau, float* work ); +lapack_int LAPACKE_dggsvp_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double tola, + double tolb, lapack_int* k, lapack_int* l, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + lapack_int* iwork, double* tau, double* work ); +lapack_int LAPACKE_cggsvp_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float tola, float tolb, + lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_int* iwork, float* rwork, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zggsvp_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double tola, double tolb, + lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sgtcon_work( char norm, lapack_int n, const float* dl, + const float* d, const float* du, + const float* du2, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgtcon_work( char norm, lapack_int n, const double* dl, + const double* d, const double* du, + const double* du2, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgtcon_work( char norm, lapack_int n, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zgtcon_work( char norm, lapack_int n, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_sgtrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* dl, + const float* d, const float* du, + const float* dlf, const float* df, + const float* duf, const float* du2, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgtrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* dl, + const double* d, const double* du, + const double* dlf, const double* df, + const double* duf, const double* du2, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgtrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgtrfs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgtsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + float* dl, float* d, float* du, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgtsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + double* dl, double* d, double* du, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgtsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_float* dl, + lapack_complex_float* d, + lapack_complex_float* du, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgtsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + lapack_complex_double* dl, + lapack_complex_double* d, + lapack_complex_double* du, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgtsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, const float* dl, + const float* d, const float* du, float* dlf, + float* df, float* duf, float* du2, + lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgtsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, const double* dl, + const double* d, const double* du, double* dlf, + double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgtsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + lapack_complex_float* dlf, + lapack_complex_float* df, + lapack_complex_float* duf, + lapack_complex_float* du2, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgtsvx_work( int matrix_order, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + lapack_complex_double* dlf, + lapack_complex_double* df, + lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgttrf_work( lapack_int n, float* dl, float* d, float* du, + float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_dgttrf_work( lapack_int n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv ); +lapack_int LAPACKE_cgttrf_work( lapack_int n, lapack_complex_float* dl, + lapack_complex_float* d, + lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_zgttrf_work( lapack_int n, lapack_complex_double* dl, + lapack_complex_double* d, + lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv ); + +lapack_int LAPACKE_sgttrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const float* dl, + const float* d, const float* du, + const float* du2, const lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dgttrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const double* dl, + const double* d, const double* du, + const double* du2, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgttrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgttrs_work( int matrix_order, char trans, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chbev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhbev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhbevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chbevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* q, lapack_int ldq, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_zhbevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* q, lapack_int ldq, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_chbgst_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* x, lapack_int ldx, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhbgst_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* bb, + lapack_int ldbb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbgv_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhbgv_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbgvd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhbgvd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chbgvx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* bb, + lapack_int ldbb, lapack_complex_float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhbgvx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* bb, + lapack_int ldbb, lapack_complex_double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chbtrd_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* d, float* e, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* work ); +lapack_int LAPACKE_zhbtrd_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* d, double* e, lapack_complex_double* q, + lapack_int ldq, lapack_complex_double* work ); + +lapack_int LAPACKE_checon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zhecon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_cheequb_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax, + lapack_complex_float* work ); +lapack_int LAPACKE_zheequb_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax, + lapack_complex_double* work ); + +lapack_int LAPACKE_cheev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zheev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* w, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_cheevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zheevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* w, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_cheevr_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* isuppz, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zheevr_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_int* isuppz, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_cheevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zheevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chegst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhegst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chegv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zhegv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* w, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_chegvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* w, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhegvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* w, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chegvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhegvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_cherfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zherfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_cherfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zherfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chesv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhesv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_chesvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zhesvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_chesvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhesvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chetrd_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* d, float* e, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhetrd_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* d, double* e, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_chetrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zhetrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_chetri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zhetri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_chetrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chfrk_work( int matrix_order, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + float alpha, const lapack_complex_float* a, + lapack_int lda, float beta, + lapack_complex_float* c ); +lapack_int LAPACKE_zhfrk_work( int matrix_order, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + double alpha, const lapack_complex_double* a, + lapack_int lda, double beta, + lapack_complex_double* c ); + +lapack_int LAPACKE_shgeqz_work( int matrix_order, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, float* h, lapack_int ldh, + float* t, lapack_int ldt, float* alphar, + float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dhgeqz_work( int matrix_order, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, double* h, lapack_int ldh, + double* t, lapack_int ldt, double* alphar, + double* alphai, double* beta, double* q, + lapack_int ldq, double* z, lapack_int ldz, + double* work, lapack_int lwork ); +lapack_int LAPACKE_chgeqz_work( int matrix_order, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* h, + lapack_int ldh, lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zhgeqz_work( int matrix_order, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* h, + lapack_int ldh, lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_chpcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zhpcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_chpev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_double* ap, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chpevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_float* ap, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhpevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_complex_double* ap, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chpevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* ap, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhpevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* ap, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chpgst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* ap, + const lapack_complex_float* bp ); +lapack_int LAPACKE_zhpgst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* ap, + const lapack_complex_double* bp ); + +lapack_int LAPACKE_chpgv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpgv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chpgvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zhpgvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_chpgvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhpgvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chpsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhpsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chpsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chptrd_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, float* d, float* e, + lapack_complex_float* tau ); +lapack_int LAPACKE_zhptrd_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, double* d, double* e, + lapack_complex_double* tau ); + +lapack_int LAPACKE_chptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zhptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_chptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zhptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_chptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_shsein_work( int matrix_order, char job, char eigsrc, + char initv, lapack_logical* select, + lapack_int n, const float* h, lapack_int ldh, + float* wr, const float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, float* work, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_dhsein_work( int matrix_order, char job, char eigsrc, + char initv, lapack_logical* select, + lapack_int n, const double* h, lapack_int ldh, + double* wr, const double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_chsein_work( int matrix_order, char job, char eigsrc, + char initv, const lapack_logical* select, + lapack_int n, const lapack_complex_float* h, + lapack_int ldh, lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_zhsein_work( int matrix_order, char job, char eigsrc, + char initv, const lapack_logical* select, + lapack_int n, const lapack_complex_double* h, + lapack_int ldh, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int* ifaill, lapack_int* ifailr ); + +lapack_int LAPACKE_shseqr_work( int matrix_order, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* h, lapack_int ldh, float* wr, float* wi, + float* z, lapack_int ldz, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dhseqr_work( int matrix_order, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* h, lapack_int ldh, double* wr, + double* wi, double* z, lapack_int ldz, + double* work, lapack_int lwork ); +lapack_int LAPACKE_chseqr_work( int matrix_order, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhseqr_work( int matrix_order, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_clacgv_work( lapack_int n, lapack_complex_float* x, + lapack_int incx ); +lapack_int LAPACKE_zlacgv_work( lapack_int n, lapack_complex_double* x, + lapack_int incx ); + +lapack_int LAPACKE_slacn2_work( lapack_int n, float* v, float* x, + lapack_int* isgn, float* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_dlacn2_work( lapack_int n, double* v, double* x, + lapack_int* isgn, double* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_clacn2_work( lapack_int n, lapack_complex_float* v, + lapack_complex_float* x, + float* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_zlacn2_work( lapack_int n, lapack_complex_double* v, + lapack_complex_double* x, + double* est, lapack_int* kase, + lapack_int* isave ); + +lapack_int LAPACKE_slacpy_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dlacpy_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_clacpy_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zlacpy_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_clacp2_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zlacp2_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_zlag2c_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_float* sa, lapack_int ldsa ); + +lapack_int LAPACKE_slag2d_work( int matrix_order, lapack_int m, lapack_int n, + const float* sa, lapack_int ldsa, double* a, + lapack_int lda ); + +lapack_int LAPACKE_dlag2s_work( int matrix_order, lapack_int m, lapack_int n, + const double* a, lapack_int lda, float* sa, + lapack_int ldsa ); + +lapack_int LAPACKE_clag2z_work( int matrix_order, lapack_int m, lapack_int n, + const lapack_complex_float* sa, lapack_int ldsa, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slagge_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + float* a, lapack_int lda, lapack_int* iseed, + float* work ); +lapack_int LAPACKE_dlagge_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + double* a, lapack_int lda, lapack_int* iseed, + double* work ); +lapack_int LAPACKE_clagge_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + lapack_complex_float* a, lapack_int lda, + lapack_int* iseed, lapack_complex_float* work ); +lapack_int LAPACKE_zlagge_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + lapack_complex_double* a, lapack_int lda, + lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_claghe_work( int matrix_order, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_float* work ); +lapack_int LAPACKE_zlaghe_work( int matrix_order, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_slagsy_work( int matrix_order, lapack_int n, lapack_int k, + const float* d, float* a, lapack_int lda, + lapack_int* iseed, float* work ); +lapack_int LAPACKE_dlagsy_work( int matrix_order, lapack_int n, lapack_int k, + const double* d, double* a, lapack_int lda, + lapack_int* iseed, double* work ); +lapack_int LAPACKE_clagsy_work( int matrix_order, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_float* work ); +lapack_int LAPACKE_zlagsy_work( int matrix_order, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_slapmr_work( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_dlapmr_work( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmr_work( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_zlapmr_work( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_double* x, lapack_int ldx, + lapack_int* k ); + +lapack_int LAPACKE_slartgp_work( float f, float g, float* cs, float* sn, + float* r ); +lapack_int LAPACKE_dlartgp_work( double f, double g, double* cs, double* sn, + double* r ); + +lapack_int LAPACKE_slartgs_work( float x, float y, float sigma, float* cs, + float* sn ); +lapack_int LAPACKE_dlartgs_work( double x, double y, double sigma, double* cs, + double* sn ); + +float LAPACKE_slapy2_work( float x, float y ); +double LAPACKE_dlapy2_work( double x, double y ); + +float LAPACKE_slapy3_work( float x, float y, float z ); +double LAPACKE_dlapy3_work( double x, double y, double z ); + +float LAPACKE_slamch_work( char cmach ); +double LAPACKE_dlamch_work( char cmach ); + +float LAPACKE_slange_work( int matrix_order, char norm, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + float* work ); +double LAPACKE_dlange_work( int matrix_order, char norm, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + double* work ); +float LAPACKE_clange_work( int matrix_order, char norm, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlange_work( int matrix_order, char norm, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_clanhe_work( int matrix_order, char norm, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlanhe_work( int matrix_order, char norm, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_slansy_work( int matrix_order, char norm, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* work ); +double LAPACKE_dlansy_work( int matrix_order, char norm, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* work ); +float LAPACKE_clansy_work( int matrix_order, char norm, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlansy_work( int matrix_order, char norm, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_slantr_work( int matrix_order, char norm, char uplo, + char diag, lapack_int m, lapack_int n, const float* a, + lapack_int lda, float* work ); +double LAPACKE_dlantr_work( int matrix_order, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* work ); +float LAPACKE_clantr_work( int matrix_order, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* work ); +double LAPACKE_zlantr_work( int matrix_order, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* work ); + +lapack_int LAPACKE_slarfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* c, lapack_int ldc, float* work, + lapack_int ldwork ); +lapack_int LAPACKE_dlarfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* c, lapack_int ldc, double* work, + lapack_int ldwork ); +lapack_int LAPACKE_clarfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int ldwork ); +lapack_int LAPACKE_zlarfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, + lapack_int ldwork ); + +lapack_int LAPACKE_slarfg_work( lapack_int n, float* alpha, float* x, + lapack_int incx, float* tau ); +lapack_int LAPACKE_dlarfg_work( lapack_int n, double* alpha, double* x, + lapack_int incx, double* tau ); +lapack_int LAPACKE_clarfg_work( lapack_int n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int incx, + lapack_complex_float* tau ); +lapack_int LAPACKE_zlarfg_work( lapack_int n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int incx, + lapack_complex_double* tau ); + +lapack_int LAPACKE_slarft_work( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* tau, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dlarft_work( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* tau, double* t, + lapack_int ldt ); +lapack_int LAPACKE_clarft_work( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* tau, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zlarft_work( int matrix_order, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* tau, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_slarfx_work( int matrix_order, char side, lapack_int m, + lapack_int n, const float* v, float tau, + float* c, lapack_int ldc, float* work ); +lapack_int LAPACKE_dlarfx_work( int matrix_order, char side, lapack_int m, + lapack_int n, const double* v, double tau, + double* c, lapack_int ldc, double* work ); +lapack_int LAPACKE_clarfx_work( int matrix_order, char side, lapack_int m, + lapack_int n, const lapack_complex_float* v, + lapack_complex_float tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work ); +lapack_int LAPACKE_zlarfx_work( int matrix_order, char side, lapack_int m, + lapack_int n, const lapack_complex_double* v, + lapack_complex_double tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work ); + +lapack_int LAPACKE_slarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, float* x ); +lapack_int LAPACKE_dlarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, double* x ); +lapack_int LAPACKE_clarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, lapack_complex_float* x ); +lapack_int LAPACKE_zlarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, lapack_complex_double* x ); + +lapack_int LAPACKE_slaset_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, float alpha, float beta, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlaset_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, double alpha, double beta, + double* a, lapack_int lda ); +lapack_int LAPACKE_claset_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, lapack_complex_float alpha, + lapack_complex_float beta, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlaset_work( int matrix_order, char uplo, lapack_int m, + lapack_int n, lapack_complex_double alpha, + lapack_complex_double beta, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slasrt_work( char id, lapack_int n, float* d ); +lapack_int LAPACKE_dlasrt_work( char id, lapack_int n, double* d ); + +lapack_int LAPACKE_slaswp_work( int matrix_order, lapack_int n, float* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_dlaswp_work( int matrix_order, lapack_int n, double* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_claswp_work( int matrix_order, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_zlaswp_work( int matrix_order, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); + +lapack_int LAPACKE_slatms_work( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + float* d, lapack_int mode, float cond, + float dmax, lapack_int kl, lapack_int ku, + char pack, float* a, lapack_int lda, + float* work ); +lapack_int LAPACKE_dlatms_work( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + double* d, lapack_int mode, double cond, + double dmax, lapack_int kl, lapack_int ku, + char pack, double* a, lapack_int lda, + double* work ); +lapack_int LAPACKE_clatms_work( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + float* d, lapack_int mode, float cond, + float dmax, lapack_int kl, lapack_int ku, + char pack, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* work ); +lapack_int LAPACKE_zlatms_work( int matrix_order, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + double* d, lapack_int mode, double cond, + double dmax, lapack_int kl, lapack_int ku, + char pack, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* work ); + +lapack_int LAPACKE_slauum_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dlauum_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_clauum_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlauum_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_sopgtr_work( int matrix_order, char uplo, lapack_int n, + const float* ap, const float* tau, float* q, + lapack_int ldq, float* work ); +lapack_int LAPACKE_dopgtr_work( int matrix_order, char uplo, lapack_int n, + const double* ap, const double* tau, double* q, + lapack_int ldq, double* work ); + +lapack_int LAPACKE_sopmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const float* ap, const float* tau, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dopmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const double* ap, const double* tau, double* c, + lapack_int ldc, double* work ); + +lapack_int LAPACKE_sorgbr_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, float* a, + lapack_int lda, const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgbr_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, double* a, + lapack_int lda, const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorghr_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorghr_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorglq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorglq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgql_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgql_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgqr_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgqr_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgrq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgrq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgtr_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, const float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dorgtr_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, const double* tau, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormbr_work( int matrix_order, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormbr_work( int matrix_order, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormhr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormhr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormlq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormlq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormql_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormql_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormqr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormqr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormrq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormrq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormrz_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormrz_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_spbcon_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpbcon_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const double* ab, + lapack_int ldab, double anorm, double* rcond, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbcon_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpbcon_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbequ_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_dpbequ_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpbequ_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_zpbequ_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); + +lapack_int LAPACKE_spbrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, + lapack_int ldafb, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpbrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpbrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbstf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kb, float* bb, lapack_int ldbb ); +lapack_int LAPACKE_dpbstf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kb, double* bb, lapack_int ldbb ); +lapack_int LAPACKE_cpbstf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kb, lapack_complex_float* bb, + lapack_int ldbb ); +lapack_int LAPACKE_zpbstf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kb, lapack_complex_double* bb, + lapack_int ldbb ); + +lapack_int LAPACKE_spbsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spbsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + float* ab, lapack_int ldab, float* afb, + lapack_int ldafb, char* equed, float* s, + float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dpbsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + double* ab, lapack_int ldab, double* afb, + lapack_int ldafb, char* equed, double* s, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* afb, lapack_int ldafb, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zpbsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* afb, lapack_int ldafb, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbtrf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab ); +lapack_int LAPACKE_dpbtrf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab ); +lapack_int LAPACKE_cpbtrf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab ); +lapack_int LAPACKE_zpbtrf_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab ); + +lapack_int LAPACKE_spbtrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbtrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpbtrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbtrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_spftrf_work( int matrix_order, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftrf_work( int matrix_order, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftrf_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftrf_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftri_work( int matrix_order, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftri_work( int matrix_order, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftri_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftri_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftrs_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpftrs_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpftrs_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpftrs_work( int matrix_order, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spocon_work( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dpocon_work( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cpocon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpocon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spoequ_work( int matrix_order, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequ_work( int matrix_order, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequ_work( int matrix_order, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequ_work( int matrix_order, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_spoequb_work( int matrix_order, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequb_work( int matrix_order, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax ); +lapack_int LAPACKE_cpoequb_work( int matrix_order, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequb_work( int matrix_order, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_sporfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dporfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cporfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zporfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sporfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const float* s, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dporfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const double* s, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cporfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zporfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* work, float* swork, + lapack_int* iter ); +lapack_int LAPACKE_zcposv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + lapack_complex_float* swork, double* rwork, + lapack_int* iter ); + +lapack_int LAPACKE_sposvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dposvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cposvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zposvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sposvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dposvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cposvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zposvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_spotrf_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dpotrf_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_cpotrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotri_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dpotri_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_cpotri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpotrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpotrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zpotrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sppcon_work( int matrix_order, char uplo, lapack_int n, + const float* ap, float anorm, float* rcond, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dppcon_work( int matrix_order, char uplo, lapack_int n, + const double* ap, double anorm, double* rcond, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cppcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, float anorm, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zppcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, double anorm, + double* rcond, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sppequ_work( int matrix_order, char uplo, lapack_int n, + const float* ap, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dppequ_work( int matrix_order, char uplo, lapack_int n, + const double* ap, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cppequ_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_zppequ_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, double* s, + double* scond, double* amax ); + +lapack_int LAPACKE_spprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const float* afp, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const double* afp, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cpprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sppsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dppsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cppsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zppsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sppsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* ap, + float* afp, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dppsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* ap, + double* afp, char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cppsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* ap, + lapack_complex_float* afp, char* equed, + float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zppsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* ap, + lapack_complex_double* afp, char* equed, + double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_spptrf_work( int matrix_order, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptrf_work( int matrix_order, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptri_work( int matrix_order, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptri_work( int matrix_order, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spstrf_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, lapack_int* piv, + lapack_int* rank, float tol, float* work ); +lapack_int LAPACKE_dpstrf_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, lapack_int* piv, + lapack_int* rank, double tol, double* work ); +lapack_int LAPACKE_cpstrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, float tol, + float* work ); +lapack_int LAPACKE_zpstrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, double tol, + double* work ); + +lapack_int LAPACKE_sptcon_work( lapack_int n, const float* d, const float* e, + float anorm, float* rcond, float* work ); +lapack_int LAPACKE_dptcon_work( lapack_int n, const double* d, const double* e, + double anorm, double* rcond, double* work ); +lapack_int LAPACKE_cptcon_work( lapack_int n, const float* d, + const lapack_complex_float* e, float anorm, + float* rcond, float* work ); +lapack_int LAPACKE_zptcon_work( lapack_int n, const double* d, + const lapack_complex_double* e, double anorm, + double* rcond, double* work ); + +lapack_int LAPACKE_spteqr_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dpteqr_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); +lapack_int LAPACKE_cpteqr_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_zpteqr_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_sptrfs_work( int matrix_order, lapack_int n, lapack_int nrhs, + const float* d, const float* e, const float* df, + const float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* ferr, + float* berr, float* work ); +lapack_int LAPACKE_dptrfs_work( int matrix_order, lapack_int n, lapack_int nrhs, + const double* d, const double* e, + const double* df, const double* ef, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work ); +lapack_int LAPACKE_cptrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zptrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + const double* df, + const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sptsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + float* d, float* e, float* b, lapack_int ldb ); +lapack_int LAPACKE_dptsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + double* d, double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cptsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + float* d, lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zptsv_work( int matrix_order, lapack_int n, lapack_int nrhs, + double* d, lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sptsvx_work( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const float* d, const float* e, + float* df, float* ef, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work ); +lapack_int LAPACKE_dptsvx_work( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const double* e, double* df, double* ef, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work ); +lapack_int LAPACKE_cptsvx_work( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zptsvx_work( int matrix_order, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, double* df, + lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spttrf_work( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dpttrf_work( lapack_int n, double* d, double* e ); +lapack_int LAPACKE_cpttrf_work( lapack_int n, float* d, + lapack_complex_float* e ); +lapack_int LAPACKE_zpttrf_work( lapack_int n, double* d, + lapack_complex_double* e ); + +lapack_int LAPACKE_spttrs_work( int matrix_order, lapack_int n, lapack_int nrhs, + const float* d, const float* e, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpttrs_work( int matrix_order, lapack_int n, lapack_int nrhs, + const double* d, const double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpttrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpttrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssbev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dsbev_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssbevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsbevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssbevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + float* ab, lapack_int ldab, float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsbevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + double* ab, lapack_int ldab, double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssbgst_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, const float* bb, + lapack_int ldbb, float* x, lapack_int ldx, + float* work ); +lapack_int LAPACKE_dsbgst_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, const double* bb, + lapack_int ldbb, double* x, lapack_int ldx, + double* work ); + +lapack_int LAPACKE_ssbgv_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dsbgv_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssbgvd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsbgvd_work( int matrix_order, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssbgvx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, float* ab, lapack_int ldab, + float* bb, lapack_int ldbb, float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsbgvx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, double* ab, lapack_int ldab, + double* bb, lapack_int ldbb, double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssbtrd_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* d, float* e, float* q, + lapack_int ldq, float* work ); +lapack_int LAPACKE_dsbtrd_work( int matrix_order, char vect, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* d, double* e, + double* q, lapack_int ldq, double* work ); + +lapack_int LAPACKE_ssfrk_work( int matrix_order, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + float alpha, const float* a, lapack_int lda, + float beta, float* c ); +lapack_int LAPACKE_dsfrk_work( int matrix_order, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + double alpha, const double* a, lapack_int lda, + double beta, double* c ); + +lapack_int LAPACKE_sspcon_work( int matrix_order, char uplo, lapack_int n, + const float* ap, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dspcon_work( int matrix_order, char uplo, lapack_int n, + const double* ap, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cspcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zspcon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_sspev_work( int matrix_order, char jobz, char uplo, + lapack_int n, float* ap, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dspev_work( int matrix_order, char jobz, char uplo, + lapack_int n, double* ap, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_sspevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, float* ap, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dspevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, double* ap, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sspevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, float* ap, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dspevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, double* ap, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, double* work, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_sspgst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, float* ap, const float* bp ); +lapack_int LAPACKE_dspgst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, double* ap, const double* bp ); + +lapack_int LAPACKE_sspgv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dspgv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz, + double* work ); + +lapack_int LAPACKE_sspgvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dspgvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sspgvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* ap, + float* bp, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, float* z, lapack_int ldz, float* work, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_dspgvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* ap, + double* bp, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const float* afp, const lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dsprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const double* afp, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zsprfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sspsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* ap, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dspsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* ap, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cspsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zspsv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sspsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, const float* ap, + float* afp, lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dspsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, const double* ap, + double* afp, lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cspsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zspsvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_ssptrd_work( int matrix_order, char uplo, lapack_int n, + float* ap, float* d, float* e, float* tau ); +lapack_int LAPACKE_dsptrd_work( int matrix_order, char uplo, lapack_int n, + double* ap, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssptrf_work( int matrix_order, char uplo, lapack_int n, + float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_dsptrf_work( int matrix_order, char uplo, lapack_int n, + double* ap, lapack_int* ipiv ); +lapack_int LAPACKE_csptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zsptrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_ssptri_work( int matrix_order, char uplo, lapack_int n, + float* ap, const lapack_int* ipiv, + float* work ); +lapack_int LAPACKE_dsptri_work( int matrix_order, char uplo, lapack_int n, + double* ap, const lapack_int* ipiv, + double* work ); +lapack_int LAPACKE_csptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* ap, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zsptri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dsptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_csptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zsptrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sstebz_work( char range, char order, lapack_int n, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, const float* d, const float* e, + lapack_int* m, lapack_int* nsplit, float* w, + lapack_int* iblock, lapack_int* isplit, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dstebz_work( char range, char order, lapack_int n, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, const double* d, const double* e, + lapack_int* m, lapack_int* nsplit, double* w, + lapack_int* iblock, lapack_int* isplit, + double* work, lapack_int* iwork ); + +lapack_int LAPACKE_sstedc_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstedc_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstedc_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstedc_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_sstegr_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dstegr_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstegr_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstegr_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz, double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_sstein_work( int matrix_order, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, + const lapack_int* isplit, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_dstein_work( int matrix_order, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, + const lapack_int* isplit, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_cstein_work( int matrix_order, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, + const lapack_int* isplit, + lapack_complex_float* z, lapack_int ldz, + float* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_zstein_work( int matrix_order, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, + const lapack_int* isplit, + lapack_complex_double* z, lapack_int ldz, + double* work, lapack_int* iwork, + lapack_int* ifailv ); + +lapack_int LAPACKE_sstemr_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstemr_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstemr_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstemr_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac, double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_ssteqr_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dsteqr_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); +lapack_int LAPACKE_csteqr_work( int matrix_order, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_zsteqr_work( int matrix_order, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssterf_work( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dsterf_work( lapack_int n, double* d, double* e ); + +lapack_int LAPACKE_sstev_work( int matrix_order, char jobz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dstev_work( int matrix_order, char jobz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); + +lapack_int LAPACKE_sstevd_work( int matrix_order, char jobz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstevd_work( int matrix_order, char jobz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sstevr_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dstevr_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sstevx_work( int matrix_order, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dstevx_work( int matrix_order, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, double* work, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssycon_work( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dsycon_work( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_csycon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zsycon_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_ssyequb_work( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float* s, + float* scond, float* amax, float* work ); +lapack_int LAPACKE_dsyequb_work( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax, double* work ); +lapack_int LAPACKE_csyequb_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax, + lapack_complex_float* work ); +lapack_int LAPACKE_zsyequb_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssyev_work( int matrix_order, char jobz, char uplo, + lapack_int n, float* a, lapack_int lda, float* w, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsyev_work( int matrix_order, char jobz, char uplo, + lapack_int n, double* a, lapack_int lda, + double* w, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssyevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, float* a, lapack_int lda, + float* w, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsyevd_work( int matrix_order, char jobz, char uplo, + lapack_int n, double* a, lapack_int lda, + double* w, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssyevr_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, float* a, + lapack_int lda, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dsyevr_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, double* a, + lapack_int lda, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssyevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, float* a, + lapack_int lda, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_dsyevx_work( int matrix_order, char jobz, char range, + char uplo, lapack_int n, double* a, + lapack_int lda, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssygst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, float* a, lapack_int lda, + const float* b, lapack_int ldb ); +lapack_int LAPACKE_dsygst_work( int matrix_order, lapack_int itype, char uplo, + lapack_int n, double* a, lapack_int lda, + const double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssygv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* w, float* work, lapack_int lwork ); +lapack_int LAPACKE_dsygv_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* w, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssygvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* w, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsygvd_work( int matrix_order, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* w, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssygvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, float* z, lapack_int ldz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsygvx_work( int matrix_order, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssyrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsyrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csyrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zsyrfs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_ssyrfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsyrfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_csyrfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zsyrfsx_work( int matrix_order, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_ssysv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsysv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csysv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zsysv_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_ssysvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dsysvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_csysvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zsysvx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_ssysvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsysvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csysvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zsysvxx_work( int matrix_order, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_ssytrd_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dsytrd_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tau, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssytrf_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsytrf_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csytrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsytrf_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_ssytri_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, float* work ); +lapack_int LAPACKE_dsytri_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, double* work ); +lapack_int LAPACKE_csytri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zsytri_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssytrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dsytrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stbcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const float* ab, lapack_int ldab, float* rcond, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtbcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const double* ab, lapack_int ldab, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctbcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const lapack_complex_float* ab, lapack_int ldab, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_ztbcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const lapack_complex_double* ab, + lapack_int ldab, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stbrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const float* ab, + lapack_int ldab, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtbrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const double* ab, + lapack_int ldab, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctbrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, const lapack_complex_float* b, + lapack_int ldb, const lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztbrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_complex_double* b, + lapack_int ldb, const lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stbtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtbtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctbtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_ztbtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_stfsm_work( int matrix_order, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, float alpha, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dtfsm_work( int matrix_order, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, double alpha, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_ctfsm_work( int matrix_order, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, lapack_complex_float alpha, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztfsm_work( int matrix_order, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, lapack_complex_double alpha, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stftri_work( int matrix_order, char transr, char uplo, + char diag, lapack_int n, float* a ); +lapack_int LAPACKE_dtftri_work( int matrix_order, char transr, char uplo, + char diag, lapack_int n, double* a ); +lapack_int LAPACKE_ctftri_work( int matrix_order, char transr, char uplo, + char diag, lapack_int n, + lapack_complex_float* a ); +lapack_int LAPACKE_ztftri_work( int matrix_order, char transr, char uplo, + char diag, lapack_int n, + lapack_complex_double* a ); + +lapack_int LAPACKE_stfttp_work( int matrix_order, char transr, char uplo, + lapack_int n, const float* arf, float* ap ); +lapack_int LAPACKE_dtfttp_work( int matrix_order, char transr, char uplo, + lapack_int n, const double* arf, double* ap ); +lapack_int LAPACKE_ctfttp_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztfttp_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stfttr_work( int matrix_order, char transr, char uplo, + lapack_int n, const float* arf, float* a, + lapack_int lda ); +lapack_int LAPACKE_dtfttr_work( int matrix_order, char transr, char uplo, + lapack_int n, const double* arf, double* a, + lapack_int lda ); +lapack_int LAPACKE_ctfttr_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztfttr_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_stgevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const float* s, lapack_int lds, const float* p, + lapack_int ldp, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m, float* work ); +lapack_int LAPACKE_dtgevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const double* s, lapack_int lds, + const double* p, lapack_int ldp, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work ); +lapack_int LAPACKE_ctgevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* s, lapack_int lds, + const lapack_complex_float* p, lapack_int ldp, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztgevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* s, lapack_int lds, + const lapack_complex_double* p, lapack_int ldp, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stgexc_work( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* q, lapack_int ldq, float* z, + lapack_int ldz, lapack_int* ifst, + lapack_int* ilst, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dtgexc_work( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* q, lapack_int ldq, double* z, + lapack_int ldz, lapack_int* ifst, + lapack_int* ilst, double* work, + lapack_int lwork ); +lapack_int LAPACKE_ctgexc_work( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztgexc_work( int matrix_order, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_stgsen_work( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* q, lapack_int ldq, float* z, + lapack_int ldz, lapack_int* m, float* pl, + float* pr, float* dif, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dtgsen_work( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* alphar, double* alphai, + double* beta, double* q, lapack_int ldq, + double* z, lapack_int ldz, lapack_int* m, + double* pl, double* pr, double* dif, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ctgsen_work( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int* m, float* pl, float* pr, float* dif, + lapack_complex_float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ztgsen_work( int matrix_order, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, + double* dif, lapack_complex_double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_stgsja_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + float* a, lapack_int lda, float* b, + lapack_int ldb, float tola, float tolb, + float* alpha, float* beta, float* u, + lapack_int ldu, float* v, lapack_int ldv, + float* q, lapack_int ldq, float* work, + lapack_int* ncycle ); +lapack_int LAPACKE_dtgsja_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + double* a, lapack_int lda, double* b, + lapack_int ldb, double tola, double tolb, + double* alpha, double* beta, double* u, + lapack_int ldu, double* v, lapack_int ldv, + double* q, lapack_int ldq, double* work, + lapack_int* ncycle ); +lapack_int LAPACKE_ctgsja_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float tola, float tolb, float* alpha, + float* beta, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, + lapack_int ldv, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* work, + lapack_int* ncycle ); +lapack_int LAPACKE_ztgsja_work( int matrix_order, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double tola, double tolb, double* alpha, + double* beta, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, + lapack_int ldv, lapack_complex_double* q, + lapack_int ldq, lapack_complex_double* work, + lapack_int* ncycle ); + +lapack_int LAPACKE_stgsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* vl, + lapack_int ldvl, const float* vr, + lapack_int ldvr, float* s, float* dif, + lapack_int mm, lapack_int* m, float* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_dtgsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, + const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* dif, lapack_int mm, lapack_int* m, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctgsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* dif, lapack_int mm, + lapack_int* m, lapack_complex_float* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_ztgsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* vl, + lapack_int ldvl, + const lapack_complex_double* vr, + lapack_int ldvr, double* s, double* dif, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, lapack_int lwork, + lapack_int* iwork ); + +lapack_int LAPACKE_stgsyl_work( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + float* c, lapack_int ldc, const float* d, + lapack_int ldd, const float* e, lapack_int lde, + float* f, lapack_int ldf, float* scale, + float* dif, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dtgsyl_work( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + double* c, lapack_int ldc, const double* d, + lapack_int ldd, const double* e, lapack_int lde, + double* f, lapack_int ldf, double* scale, + double* dif, double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctgsyl_work( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + const lapack_complex_float* d, lapack_int ldd, + const lapack_complex_float* e, lapack_int lde, + lapack_complex_float* f, lapack_int ldf, + float* scale, float* dif, + lapack_complex_float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ztgsyl_work( int matrix_order, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + const lapack_complex_double* d, lapack_int ldd, + const lapack_complex_double* e, lapack_int lde, + lapack_complex_double* f, lapack_int ldf, + double* scale, double* dif, + lapack_complex_double* work, lapack_int lwork, + lapack_int* iwork ); + +lapack_int LAPACKE_stpcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, const float* ap, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtpcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, const double* ap, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctpcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_float* ap, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztpcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_double* ap, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stprfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* ap, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtprfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* ap, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctprfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztprfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stptri_work( int matrix_order, char uplo, char diag, + lapack_int n, float* ap ); +lapack_int LAPACKE_dtptri_work( int matrix_order, char uplo, char diag, + lapack_int n, double* ap ); +lapack_int LAPACKE_ctptri_work( int matrix_order, char uplo, char diag, + lapack_int n, lapack_complex_float* ap ); +lapack_int LAPACKE_ztptri_work( int matrix_order, char uplo, char diag, + lapack_int n, lapack_complex_double* ap ); + +lapack_int LAPACKE_stptrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* ap, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtptrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* ap, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctptrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztptrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stpttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const float* ap, float* arf ); +lapack_int LAPACKE_dtpttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const double* ap, double* arf ); +lapack_int LAPACKE_ctpttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* ap, + lapack_complex_float* arf ); +lapack_int LAPACKE_ztpttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* ap, + lapack_complex_double* arf ); + +lapack_int LAPACKE_stpttr_work( int matrix_order, char uplo, lapack_int n, + const float* ap, float* a, lapack_int lda ); +lapack_int LAPACKE_dtpttr_work( int matrix_order, char uplo, lapack_int n, + const double* ap, double* a, lapack_int lda ); +lapack_int LAPACKE_ctpttr_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztpttr_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, const float* a, + lapack_int lda, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dtrcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, const double* a, + lapack_int lda, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctrcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_ztrcon_work( int matrix_order, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* rcond, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_strevc_work( int matrix_order, char side, char howmny, + lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, float* work ); +lapack_int LAPACKE_dtrevc_work( int matrix_order, char side, char howmny, + lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work ); +lapack_int LAPACKE_ctrevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztrevc_work( int matrix_order, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_strexc_work( int matrix_order, char compq, lapack_int n, + float* t, lapack_int ldt, float* q, + lapack_int ldq, lapack_int* ifst, + lapack_int* ilst, float* work ); +lapack_int LAPACKE_dtrexc_work( int matrix_order, char compq, lapack_int n, + double* t, lapack_int ldt, double* q, + lapack_int ldq, lapack_int* ifst, + lapack_int* ilst, double* work ); +lapack_int LAPACKE_ctrexc_work( int matrix_order, char compq, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztrexc_work( int matrix_order, char compq, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_strrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dtrrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, + const double* x, lapack_int ldx, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_ctrrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztrrfs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_strsen_work( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + float* t, lapack_int ldt, float* q, + lapack_int ldq, float* wr, float* wi, + lapack_int* m, float* s, float* sep, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dtrsen_work( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + double* t, lapack_int ldt, double* q, + lapack_int ldq, double* wr, double* wi, + lapack_int* m, double* s, double* sep, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ctrsen_work( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* w, lapack_int* m, + float* s, float* sep, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ztrsen_work( int matrix_order, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* w, lapack_int* m, + double* s, double* sep, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_strsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, const float* vl, + lapack_int ldvl, const float* vr, + lapack_int ldvr, float* s, float* sep, + lapack_int mm, lapack_int* m, float* work, + lapack_int ldwork, lapack_int* iwork ); +lapack_int LAPACKE_dtrsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, + const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* sep, lapack_int mm, lapack_int* m, + double* work, lapack_int ldwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctrsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* t, lapack_int ldt, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, + lapack_int* m, lapack_complex_float* work, + lapack_int ldwork, float* rwork ); +lapack_int LAPACKE_ztrsna_work( int matrix_order, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* t, lapack_int ldt, + const lapack_complex_double* vl, + lapack_int ldvl, + const lapack_complex_double* vr, + lapack_int ldvr, double* s, double* sep, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, lapack_int ldwork, + double* rwork ); + +lapack_int LAPACKE_strsyl_work( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_dtrsyl_work( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, double* c, + lapack_int ldc, double* scale ); +lapack_int LAPACKE_ctrsyl_work( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_ztrsyl_work( int matrix_order, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + double* scale ); + +lapack_int LAPACKE_strtri_work( int matrix_order, char uplo, char diag, + lapack_int n, float* a, lapack_int lda ); +lapack_int LAPACKE_dtrtri_work( int matrix_order, char uplo, char diag, + lapack_int n, double* a, lapack_int lda ); +lapack_int LAPACKE_ctrtri_work( int matrix_order, char uplo, char diag, + lapack_int n, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_ztrtri_work( int matrix_order, char uplo, char diag, + lapack_int n, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_strtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtrtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctrtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztrtrs_work( int matrix_order, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_strttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* arf ); +lapack_int LAPACKE_dtrttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* arf ); +lapack_int LAPACKE_ctrttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* arf ); +lapack_int LAPACKE_ztrttf_work( int matrix_order, char transr, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* arf ); + +lapack_int LAPACKE_strttp_work( int matrix_order, char uplo, lapack_int n, + const float* a, lapack_int lda, float* ap ); +lapack_int LAPACKE_dtrttp_work( int matrix_order, char uplo, lapack_int n, + const double* a, lapack_int lda, double* ap ); +lapack_int LAPACKE_ctrttp_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztrttp_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stzrzf_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dtzrzf_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_ctzrzf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ztzrzf_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungbr_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungbr_work( int matrix_order, char vect, lapack_int m, + lapack_int n, lapack_int k, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunghr_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunghr_work( int matrix_order, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunglq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunglq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungql_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungql_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungqr_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungqr_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungrq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungrq_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungtr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungtr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmbr_work( int matrix_order, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmbr_work( int matrix_order, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmhr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmhr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmlq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmlq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmql_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmql_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmqr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmqr_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmrq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmrq_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmrz_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmrz_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cupgtr_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* work ); +lapack_int LAPACKE_zupgtr_work( int matrix_order, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* work ); + +lapack_int LAPACKE_cupmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work ); +lapack_int LAPACKE_zupmtr_work( int matrix_order, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work ); + +lapack_int LAPACKE_claghe( int matrix_order, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_zlaghe( int matrix_order, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed ); + +lapack_int LAPACKE_slagsy( int matrix_order, lapack_int n, lapack_int k, + const float* d, float* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_dlagsy( int matrix_order, lapack_int n, lapack_int k, + const double* d, double* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_clagsy( int matrix_order, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_zlagsy( int matrix_order, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed ); + +lapack_int LAPACKE_slapmr( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_dlapmr( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmr( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_zlapmr( int matrix_order, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_double* x, + lapack_int ldx, lapack_int* k ); + + +float LAPACKE_slapy2( float x, float y ); +double LAPACKE_dlapy2( double x, double y ); + +float LAPACKE_slapy3( float x, float y, float z ); +double LAPACKE_dlapy3( double x, double y, double z ); + +lapack_int LAPACKE_slartgp( float f, float g, float* cs, float* sn, float* r ); +lapack_int LAPACKE_dlartgp( double f, double g, double* cs, double* sn, + double* r ); + +lapack_int LAPACKE_slartgs( float x, float y, float sigma, float* cs, + float* sn ); +lapack_int LAPACKE_dlartgs( double x, double y, double sigma, double* cs, + double* sn ); + + +//LAPACK 3.3.0 +lapack_int LAPACKE_cbbcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, float* theta, float* phi, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + float* b11d, float* b11e, float* b12d, float* b12e, + float* b21d, float* b21e, float* b22d, float* b22e ); +lapack_int LAPACKE_cbbcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + float* theta, float* phi, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + float* b11d, float* b11e, float* b12d, + float* b12e, float* b21d, float* b21e, + float* b22d, float* b22e, float* rwork, + lapack_int lrwork ); +lapack_int LAPACKE_cheswapr( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_cheswapr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_chetri2( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_chetri2_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_chetri2x( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_chetri2x_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int nb ); +lapack_int LAPACKE_chetrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_chetrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_csyconv( int matrix_order, char uplo, char way, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_csyconv_work( int matrix_order, char uplo, char way, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_csyswapr( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_csyswapr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_csytri2( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_csytri2_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_csytri2x( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_csytri2x_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int nb ); +lapack_int LAPACKE_csytrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_cunbdb( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2 ); +lapack_int LAPACKE_cunbdb_work( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_cuncsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, lapack_complex_float* u1, + lapack_int ldu1, lapack_complex_float* u2, + lapack_int ldu2, lapack_complex_float* v1t, + lapack_int ldv1t, lapack_complex_float* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_cuncsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_float* x11, + lapack_int ldx11, lapack_complex_float* x12, + lapack_int ldx12, lapack_complex_float* x21, + lapack_int ldx21, lapack_complex_float* x22, + lapack_int ldx22, float* theta, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork ); +lapack_int LAPACKE_dbbcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, double* theta, + double* phi, double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t, + double* v2t, lapack_int ldv2t, double* b11d, + double* b11e, double* b12d, double* b12e, + double* b21d, double* b21e, double* b22d, + double* b22e ); +lapack_int LAPACKE_dbbcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + double* theta, double* phi, double* u1, + lapack_int ldu1, double* u2, lapack_int ldu2, + double* v1t, lapack_int ldv1t, double* v2t, + lapack_int ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e, + double* work, lapack_int lwork ); +lapack_int LAPACKE_dorbdb( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2 ); +lapack_int LAPACKE_dorbdb_work( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2, double* work, + lapack_int lwork ); +lapack_int LAPACKE_dorcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t, + double* v2t, lapack_int ldv2t ); +lapack_int LAPACKE_dorcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, double* x11, lapack_int ldx11, + double* x12, lapack_int ldx12, double* x21, + lapack_int ldx21, double* x22, lapack_int ldx22, + double* theta, double* u1, lapack_int ldu1, + double* u2, lapack_int ldu2, double* v1t, + lapack_int ldv1t, double* v2t, lapack_int ldv2t, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dsyconv( int matrix_order, char uplo, char way, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dsyconv_work( int matrix_order, char uplo, char way, + lapack_int n, double* a, lapack_int lda, + const lapack_int* ipiv, double* work ); +lapack_int LAPACKE_dsyswapr( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_dsyswapr_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_dsytri2( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dsytri2_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_dsytri2x( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv, + lapack_int nb ); +lapack_int LAPACKE_dsytri2x_work( int matrix_order, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, double* work, + lapack_int nb ); +lapack_int LAPACKE_dsytrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_dsytrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb, double* work ); +lapack_int LAPACKE_sbbcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, float* theta, float* phi, + float* u1, lapack_int ldu1, float* u2, + lapack_int ldu2, float* v1t, lapack_int ldv1t, + float* v2t, lapack_int ldv2t, float* b11d, + float* b11e, float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e ); +lapack_int LAPACKE_sbbcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + float* theta, float* phi, float* u1, + lapack_int ldu1, float* u2, lapack_int ldu2, + float* v1t, lapack_int ldv1t, float* v2t, + lapack_int ldv2t, float* b11d, float* b11e, + float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e, + float* work, lapack_int lwork ); +lapack_int LAPACKE_sorbdb( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, float* x11, + lapack_int ldx11, float* x12, lapack_int ldx12, + float* x21, lapack_int ldx21, float* x22, + lapack_int ldx22, float* theta, float* phi, + float* taup1, float* taup2, float* tauq1, + float* tauq2 ); +lapack_int LAPACKE_sorbdb_work( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + float* x11, lapack_int ldx11, float* x12, + lapack_int ldx12, float* x21, lapack_int ldx21, + float* x22, lapack_int ldx22, float* theta, + float* phi, float* taup1, float* taup2, + float* tauq1, float* tauq2, float* work, + lapack_int lwork ); +lapack_int LAPACKE_sorcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, float* x11, + lapack_int ldx11, float* x12, lapack_int ldx12, + float* x21, lapack_int ldx21, float* x22, + lapack_int ldx22, float* theta, float* u1, + lapack_int ldu1, float* u2, lapack_int ldu2, + float* v1t, lapack_int ldv1t, float* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_sorcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, float* x11, lapack_int ldx11, + float* x12, lapack_int ldx12, float* x21, + lapack_int ldx21, float* x22, lapack_int ldx22, + float* theta, float* u1, lapack_int ldu1, + float* u2, lapack_int ldu2, float* v1t, + lapack_int ldv1t, float* v2t, lapack_int ldv2t, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ssyconv( int matrix_order, char uplo, char way, lapack_int n, + float* a, lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_ssyconv_work( int matrix_order, char uplo, char way, + lapack_int n, float* a, lapack_int lda, + const lapack_int* ipiv, float* work ); +lapack_int LAPACKE_ssyswapr( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_ssyswapr_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_ssytri2( int matrix_order, char uplo, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_ssytri2_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ssytri2x( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, const lapack_int* ipiv, + lapack_int nb ); +lapack_int LAPACKE_ssytri2x_work( int matrix_order, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, float* work, + lapack_int nb ); +lapack_int LAPACKE_ssytrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_ssytrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const float* a, + lapack_int lda, const lapack_int* ipiv, + float* b, lapack_int ldb, float* work ); +lapack_int LAPACKE_zbbcsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, double* theta, + double* phi, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, + lapack_int ldv1t, lapack_complex_double* v2t, + lapack_int ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e ); +lapack_int LAPACKE_zbbcsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + double* theta, double* phi, + lapack_complex_double* u1, lapack_int ldu1, + lapack_complex_double* u2, lapack_int ldu2, + lapack_complex_double* v1t, lapack_int ldv1t, + lapack_complex_double* v2t, lapack_int ldv2t, + double* b11d, double* b11e, double* b12d, + double* b12e, double* b21d, double* b21e, + double* b22d, double* b22e, double* rwork, + lapack_int lrwork ); +lapack_int LAPACKE_zheswapr( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zheswapr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zhetri2( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zhetri2_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zhetri2x( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_zhetri2x_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int nb ); +lapack_int LAPACKE_zhetrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); +lapack_int LAPACKE_zsyconv( int matrix_order, char uplo, char way, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zsyconv_work( int matrix_order, char uplo, char way, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* work ); +lapack_int LAPACKE_zsyswapr( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zsyswapr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zsytri2( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zsytri2_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zsytri2x( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_zsytri2x_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int nb ); +lapack_int LAPACKE_zsytrs2( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs2_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); +lapack_int LAPACKE_zunbdb( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2 ); +lapack_int LAPACKE_zunbdb_work( int matrix_order, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zuncsd( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, + lapack_int ldv1t, lapack_complex_double* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_zuncsd_work( int matrix_order, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_double* x11, + lapack_int ldx11, lapack_complex_double* x12, + lapack_int ldx12, lapack_complex_double* x21, + lapack_int ldx21, lapack_complex_double* x22, + lapack_int ldx22, double* theta, + lapack_complex_double* u1, lapack_int ldu1, + lapack_complex_double* u2, lapack_int ldu2, + lapack_complex_double* v1t, lapack_int ldv1t, + lapack_complex_double* v2t, lapack_int ldv2t, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork ); +//LAPACK 3.4.0 +lapack_int LAPACKE_sgemqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dgemqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cgemqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zgemqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc ); + +lapack_int LAPACKE_sgeqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* t, + lapack_int ldt ); +lapack_int LAPACKE_zgeqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* t, + lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt2( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt2( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt2( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt3( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt3( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt3( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt3( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpmqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtpmqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctpmqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztpmqrt( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_dtpqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, double* a, + lapack_int lda, double* b, lapack_int ldb, double* t, + lapack_int ldt ); +lapack_int LAPACKE_ctpqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpqrt2( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* t, lapack_int ldt ); +lapack_int LAPACKE_dtpqrt2( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* t, lapack_int ldt ); +lapack_int LAPACKE_ctpqrt2( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt2( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stprfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtprfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* a, lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctprfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztprfb( int matrix_order, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgemqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dgemqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_cgemqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc, lapack_complex_float* work ); +lapack_int LAPACKE_zgemqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc, lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, float* a, lapack_int lda, + float* t, lapack_int ldt, float* work ); +lapack_int LAPACKE_dgeqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, double* a, lapack_int lda, + double* t, lapack_int ldt, double* work ); +lapack_int LAPACKE_cgeqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* work ); +lapack_int LAPACKE_zgeqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrt2_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt2_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt2_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt3_work( int matrix_order, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt3_work( int matrix_order, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt3_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt3_work( int matrix_order, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpmqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* work ); +lapack_int LAPACKE_dtpmqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const double* v, + lapack_int ldv, const double* t, + lapack_int ldt, double* a, lapack_int lda, + double* b, lapack_int ldb, double* work ); +lapack_int LAPACKE_ctpmqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_ztpmqrt_work( int matrix_order, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); + +lapack_int LAPACKE_dtpqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* t, lapack_int ldt, double* work ); +lapack_int LAPACKE_ctpqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* work ); +lapack_int LAPACKE_ztpqrt_work( int matrix_order, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* work ); + +lapack_int LAPACKE_stpqrt2_work( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* t, lapack_int ldt ); +lapack_int LAPACKE_dtpqrt2_work( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* t, lapack_int ldt ); +lapack_int LAPACKE_ctpqrt2_work( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt2_work( int matrix_order, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stprfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const float* v, lapack_int ldv, const float* t, + lapack_int ldt, float* a, lapack_int lda, + float* b, lapack_int ldb, const float* work, + lapack_int ldwork ); +lapack_int LAPACKE_dtprfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* a, + lapack_int lda, double* b, lapack_int ldb, + const double* work, lapack_int ldwork ); +lapack_int LAPACKE_ctprfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + const float* work, lapack_int ldwork ); +lapack_int LAPACKE_ztprfb_work( int matrix_order, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + const double* work, lapack_int ldwork ); +//LAPACK 3.X.X +lapack_int LAPACKE_ssysv_rook( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsysv_rook( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csysv_rook( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsysv_rook( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); +lapack_int LAPACKE_csyr( int matrix_order, char uplo, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* x, lapack_int incx, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zsyr( int matrix_order, char uplo, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* x, lapack_int incx, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_ssysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsysv_rook_work( int matrix_order, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, + lapack_int lwork ); +lapack_int LAPACKE_csyr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* x, + lapack_int incx, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zsyr_work( int matrix_order, char uplo, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* x, + lapack_int incx, lapack_complex_double* a, + lapack_int lda ); +void LAPACKE_ilaver( const lapack_int* vers_major, + const lapack_int* vers_minor, + const lapack_int* vers_patch ); + + +#define LAPACK_sgetrf LAPACK_GLOBAL(sgetrf,SGETRF) +#define LAPACK_dgetrf LAPACK_GLOBAL(dgetrf,DGETRF) +#define LAPACK_cgetrf LAPACK_GLOBAL(cgetrf,CGETRF) +#define LAPACK_zgetrf LAPACK_GLOBAL(zgetrf,ZGETRF) +#define LAPACK_sgbtrf LAPACK_GLOBAL(sgbtrf,SGBTRF) +#define LAPACK_dgbtrf LAPACK_GLOBAL(dgbtrf,DGBTRF) +#define LAPACK_cgbtrf LAPACK_GLOBAL(cgbtrf,CGBTRF) +#define LAPACK_zgbtrf LAPACK_GLOBAL(zgbtrf,ZGBTRF) +#define LAPACK_sgttrf LAPACK_GLOBAL(sgttrf,SGTTRF) +#define LAPACK_dgttrf LAPACK_GLOBAL(dgttrf,DGTTRF) +#define LAPACK_cgttrf LAPACK_GLOBAL(cgttrf,CGTTRF) +#define LAPACK_zgttrf LAPACK_GLOBAL(zgttrf,ZGTTRF) +#define LAPACK_spotrf LAPACK_GLOBAL(spotrf,SPOTRF) +#define LAPACK_dpotrf LAPACK_GLOBAL(dpotrf,DPOTRF) +#define LAPACK_cpotrf LAPACK_GLOBAL(cpotrf,CPOTRF) +#define LAPACK_zpotrf LAPACK_GLOBAL(zpotrf,ZPOTRF) +#define LAPACK_dpstrf LAPACK_GLOBAL(dpstrf,DPSTRF) +#define LAPACK_spstrf LAPACK_GLOBAL(spstrf,SPSTRF) +#define LAPACK_zpstrf LAPACK_GLOBAL(zpstrf,ZPSTRF) +#define LAPACK_cpstrf LAPACK_GLOBAL(cpstrf,CPSTRF) +#define LAPACK_dpftrf LAPACK_GLOBAL(dpftrf,DPFTRF) +#define LAPACK_spftrf LAPACK_GLOBAL(spftrf,SPFTRF) +#define LAPACK_zpftrf LAPACK_GLOBAL(zpftrf,ZPFTRF) +#define LAPACK_cpftrf LAPACK_GLOBAL(cpftrf,CPFTRF) +#define LAPACK_spptrf LAPACK_GLOBAL(spptrf,SPPTRF) +#define LAPACK_dpptrf LAPACK_GLOBAL(dpptrf,DPPTRF) +#define LAPACK_cpptrf LAPACK_GLOBAL(cpptrf,CPPTRF) +#define LAPACK_zpptrf LAPACK_GLOBAL(zpptrf,ZPPTRF) +#define LAPACK_spbtrf LAPACK_GLOBAL(spbtrf,SPBTRF) +#define LAPACK_dpbtrf LAPACK_GLOBAL(dpbtrf,DPBTRF) +#define LAPACK_cpbtrf LAPACK_GLOBAL(cpbtrf,CPBTRF) +#define LAPACK_zpbtrf LAPACK_GLOBAL(zpbtrf,ZPBTRF) +#define LAPACK_spttrf LAPACK_GLOBAL(spttrf,SPTTRF) +#define LAPACK_dpttrf LAPACK_GLOBAL(dpttrf,DPTTRF) +#define LAPACK_cpttrf LAPACK_GLOBAL(cpttrf,CPTTRF) +#define LAPACK_zpttrf LAPACK_GLOBAL(zpttrf,ZPTTRF) +#define LAPACK_ssytrf LAPACK_GLOBAL(ssytrf,SSYTRF) +#define LAPACK_dsytrf LAPACK_GLOBAL(dsytrf,DSYTRF) +#define LAPACK_csytrf LAPACK_GLOBAL(csytrf,CSYTRF) +#define LAPACK_zsytrf LAPACK_GLOBAL(zsytrf,ZSYTRF) +#define LAPACK_chetrf LAPACK_GLOBAL(chetrf,CHETRF) +#define LAPACK_zhetrf LAPACK_GLOBAL(zhetrf,ZHETRF) +#define LAPACK_ssptrf LAPACK_GLOBAL(ssptrf,SSPTRF) +#define LAPACK_dsptrf LAPACK_GLOBAL(dsptrf,DSPTRF) +#define LAPACK_csptrf LAPACK_GLOBAL(csptrf,CSPTRF) +#define LAPACK_zsptrf LAPACK_GLOBAL(zsptrf,ZSPTRF) +#define LAPACK_chptrf LAPACK_GLOBAL(chptrf,CHPTRF) +#define LAPACK_zhptrf LAPACK_GLOBAL(zhptrf,ZHPTRF) +#define LAPACK_sgetrs LAPACK_GLOBAL(sgetrs,SGETRS) +#define LAPACK_dgetrs LAPACK_GLOBAL(dgetrs,DGETRS) +#define LAPACK_cgetrs LAPACK_GLOBAL(cgetrs,CGETRS) +#define LAPACK_zgetrs LAPACK_GLOBAL(zgetrs,ZGETRS) +#define LAPACK_sgbtrs LAPACK_GLOBAL(sgbtrs,SGBTRS) +#define LAPACK_dgbtrs LAPACK_GLOBAL(dgbtrs,DGBTRS) +#define LAPACK_cgbtrs LAPACK_GLOBAL(cgbtrs,CGBTRS) +#define LAPACK_zgbtrs LAPACK_GLOBAL(zgbtrs,ZGBTRS) +#define LAPACK_sgttrs LAPACK_GLOBAL(sgttrs,SGTTRS) +#define LAPACK_dgttrs LAPACK_GLOBAL(dgttrs,DGTTRS) +#define LAPACK_cgttrs LAPACK_GLOBAL(cgttrs,CGTTRS) +#define LAPACK_zgttrs LAPACK_GLOBAL(zgttrs,ZGTTRS) +#define LAPACK_spotrs LAPACK_GLOBAL(spotrs,SPOTRS) +#define LAPACK_dpotrs LAPACK_GLOBAL(dpotrs,DPOTRS) +#define LAPACK_cpotrs LAPACK_GLOBAL(cpotrs,CPOTRS) +#define LAPACK_zpotrs LAPACK_GLOBAL(zpotrs,ZPOTRS) +#define LAPACK_dpftrs LAPACK_GLOBAL(dpftrs,DPFTRS) +#define LAPACK_spftrs LAPACK_GLOBAL(spftrs,SPFTRS) +#define LAPACK_zpftrs LAPACK_GLOBAL(zpftrs,ZPFTRS) +#define LAPACK_cpftrs LAPACK_GLOBAL(cpftrs,CPFTRS) +#define LAPACK_spptrs LAPACK_GLOBAL(spptrs,SPPTRS) +#define LAPACK_dpptrs LAPACK_GLOBAL(dpptrs,DPPTRS) +#define LAPACK_cpptrs LAPACK_GLOBAL(cpptrs,CPPTRS) +#define LAPACK_zpptrs LAPACK_GLOBAL(zpptrs,ZPPTRS) +#define LAPACK_spbtrs LAPACK_GLOBAL(spbtrs,SPBTRS) +#define LAPACK_dpbtrs LAPACK_GLOBAL(dpbtrs,DPBTRS) +#define LAPACK_cpbtrs LAPACK_GLOBAL(cpbtrs,CPBTRS) +#define LAPACK_zpbtrs LAPACK_GLOBAL(zpbtrs,ZPBTRS) +#define LAPACK_spttrs LAPACK_GLOBAL(spttrs,SPTTRS) +#define LAPACK_dpttrs LAPACK_GLOBAL(dpttrs,DPTTRS) +#define LAPACK_cpttrs LAPACK_GLOBAL(cpttrs,CPTTRS) +#define LAPACK_zpttrs LAPACK_GLOBAL(zpttrs,ZPTTRS) +#define LAPACK_ssytrs LAPACK_GLOBAL(ssytrs,SSYTRS) +#define LAPACK_dsytrs LAPACK_GLOBAL(dsytrs,DSYTRS) +#define LAPACK_csytrs LAPACK_GLOBAL(csytrs,CSYTRS) +#define LAPACK_zsytrs LAPACK_GLOBAL(zsytrs,ZSYTRS) +#define LAPACK_chetrs LAPACK_GLOBAL(chetrs,CHETRS) +#define LAPACK_zhetrs LAPACK_GLOBAL(zhetrs,ZHETRS) +#define LAPACK_ssptrs LAPACK_GLOBAL(ssptrs,SSPTRS) +#define LAPACK_dsptrs LAPACK_GLOBAL(dsptrs,DSPTRS) +#define LAPACK_csptrs LAPACK_GLOBAL(csptrs,CSPTRS) +#define LAPACK_zsptrs LAPACK_GLOBAL(zsptrs,ZSPTRS) +#define LAPACK_chptrs LAPACK_GLOBAL(chptrs,CHPTRS) +#define LAPACK_zhptrs LAPACK_GLOBAL(zhptrs,ZHPTRS) +#define LAPACK_strtrs LAPACK_GLOBAL(strtrs,STRTRS) +#define LAPACK_dtrtrs LAPACK_GLOBAL(dtrtrs,DTRTRS) +#define LAPACK_ctrtrs LAPACK_GLOBAL(ctrtrs,CTRTRS) +#define LAPACK_ztrtrs LAPACK_GLOBAL(ztrtrs,ZTRTRS) +#define LAPACK_stptrs LAPACK_GLOBAL(stptrs,STPTRS) +#define LAPACK_dtptrs LAPACK_GLOBAL(dtptrs,DTPTRS) +#define LAPACK_ctptrs LAPACK_GLOBAL(ctptrs,CTPTRS) +#define LAPACK_ztptrs LAPACK_GLOBAL(ztptrs,ZTPTRS) +#define LAPACK_stbtrs LAPACK_GLOBAL(stbtrs,STBTRS) +#define LAPACK_dtbtrs LAPACK_GLOBAL(dtbtrs,DTBTRS) +#define LAPACK_ctbtrs LAPACK_GLOBAL(ctbtrs,CTBTRS) +#define LAPACK_ztbtrs LAPACK_GLOBAL(ztbtrs,ZTBTRS) +#define LAPACK_sgecon LAPACK_GLOBAL(sgecon,SGECON) +#define LAPACK_dgecon LAPACK_GLOBAL(dgecon,DGECON) +#define LAPACK_cgecon LAPACK_GLOBAL(cgecon,CGECON) +#define LAPACK_zgecon LAPACK_GLOBAL(zgecon,ZGECON) +#define LAPACK_sgbcon LAPACK_GLOBAL(sgbcon,SGBCON) +#define LAPACK_dgbcon LAPACK_GLOBAL(dgbcon,DGBCON) +#define LAPACK_cgbcon LAPACK_GLOBAL(cgbcon,CGBCON) +#define LAPACK_zgbcon LAPACK_GLOBAL(zgbcon,ZGBCON) +#define LAPACK_sgtcon LAPACK_GLOBAL(sgtcon,SGTCON) +#define LAPACK_dgtcon LAPACK_GLOBAL(dgtcon,DGTCON) +#define LAPACK_cgtcon LAPACK_GLOBAL(cgtcon,CGTCON) +#define LAPACK_zgtcon LAPACK_GLOBAL(zgtcon,ZGTCON) +#define LAPACK_spocon LAPACK_GLOBAL(spocon,SPOCON) +#define LAPACK_dpocon LAPACK_GLOBAL(dpocon,DPOCON) +#define LAPACK_cpocon LAPACK_GLOBAL(cpocon,CPOCON) +#define LAPACK_zpocon LAPACK_GLOBAL(zpocon,ZPOCON) +#define LAPACK_sppcon LAPACK_GLOBAL(sppcon,SPPCON) +#define LAPACK_dppcon LAPACK_GLOBAL(dppcon,DPPCON) +#define LAPACK_cppcon LAPACK_GLOBAL(cppcon,CPPCON) +#define LAPACK_zppcon LAPACK_GLOBAL(zppcon,ZPPCON) +#define LAPACK_spbcon LAPACK_GLOBAL(spbcon,SPBCON) +#define LAPACK_dpbcon LAPACK_GLOBAL(dpbcon,DPBCON) +#define LAPACK_cpbcon LAPACK_GLOBAL(cpbcon,CPBCON) +#define LAPACK_zpbcon LAPACK_GLOBAL(zpbcon,ZPBCON) +#define LAPACK_sptcon LAPACK_GLOBAL(sptcon,SPTCON) +#define LAPACK_dptcon LAPACK_GLOBAL(dptcon,DPTCON) +#define LAPACK_cptcon LAPACK_GLOBAL(cptcon,CPTCON) +#define LAPACK_zptcon LAPACK_GLOBAL(zptcon,ZPTCON) +#define LAPACK_ssycon LAPACK_GLOBAL(ssycon,SSYCON) +#define LAPACK_dsycon LAPACK_GLOBAL(dsycon,DSYCON) +#define LAPACK_csycon LAPACK_GLOBAL(csycon,CSYCON) +#define LAPACK_zsycon LAPACK_GLOBAL(zsycon,ZSYCON) +#define LAPACK_checon LAPACK_GLOBAL(checon,CHECON) +#define LAPACK_zhecon LAPACK_GLOBAL(zhecon,ZHECON) +#define LAPACK_sspcon LAPACK_GLOBAL(sspcon,SSPCON) +#define LAPACK_dspcon LAPACK_GLOBAL(dspcon,DSPCON) +#define LAPACK_cspcon LAPACK_GLOBAL(cspcon,CSPCON) +#define LAPACK_zspcon LAPACK_GLOBAL(zspcon,ZSPCON) +#define LAPACK_chpcon LAPACK_GLOBAL(chpcon,CHPCON) +#define LAPACK_zhpcon LAPACK_GLOBAL(zhpcon,ZHPCON) +#define LAPACK_strcon LAPACK_GLOBAL(strcon,STRCON) +#define LAPACK_dtrcon LAPACK_GLOBAL(dtrcon,DTRCON) +#define LAPACK_ctrcon LAPACK_GLOBAL(ctrcon,CTRCON) +#define LAPACK_ztrcon LAPACK_GLOBAL(ztrcon,ZTRCON) +#define LAPACK_stpcon LAPACK_GLOBAL(stpcon,STPCON) +#define LAPACK_dtpcon LAPACK_GLOBAL(dtpcon,DTPCON) +#define LAPACK_ctpcon LAPACK_GLOBAL(ctpcon,CTPCON) +#define LAPACK_ztpcon LAPACK_GLOBAL(ztpcon,ZTPCON) +#define LAPACK_stbcon LAPACK_GLOBAL(stbcon,STBCON) +#define LAPACK_dtbcon LAPACK_GLOBAL(dtbcon,DTBCON) +#define LAPACK_ctbcon LAPACK_GLOBAL(ctbcon,CTBCON) +#define LAPACK_ztbcon LAPACK_GLOBAL(ztbcon,ZTBCON) +#define LAPACK_sgerfs LAPACK_GLOBAL(sgerfs,SGERFS) +#define LAPACK_dgerfs LAPACK_GLOBAL(dgerfs,DGERFS) +#define LAPACK_cgerfs LAPACK_GLOBAL(cgerfs,CGERFS) +#define LAPACK_zgerfs LAPACK_GLOBAL(zgerfs,ZGERFS) +#define LAPACK_dgerfsx LAPACK_GLOBAL(dgerfsx,DGERFSX) +#define LAPACK_sgerfsx LAPACK_GLOBAL(sgerfsx,SGERFSX) +#define LAPACK_zgerfsx LAPACK_GLOBAL(zgerfsx,ZGERFSX) +#define LAPACK_cgerfsx LAPACK_GLOBAL(cgerfsx,CGERFSX) +#define LAPACK_sgbrfs LAPACK_GLOBAL(sgbrfs,SGBRFS) +#define LAPACK_dgbrfs LAPACK_GLOBAL(dgbrfs,DGBRFS) +#define LAPACK_cgbrfs LAPACK_GLOBAL(cgbrfs,CGBRFS) +#define LAPACK_zgbrfs LAPACK_GLOBAL(zgbrfs,ZGBRFS) +#define LAPACK_dgbrfsx LAPACK_GLOBAL(dgbrfsx,DGBRFSX) +#define LAPACK_sgbrfsx LAPACK_GLOBAL(sgbrfsx,SGBRFSX) +#define LAPACK_zgbrfsx LAPACK_GLOBAL(zgbrfsx,ZGBRFSX) +#define LAPACK_cgbrfsx LAPACK_GLOBAL(cgbrfsx,CGBRFSX) +#define LAPACK_sgtrfs LAPACK_GLOBAL(sgtrfs,SGTRFS) +#define LAPACK_dgtrfs LAPACK_GLOBAL(dgtrfs,DGTRFS) +#define LAPACK_cgtrfs LAPACK_GLOBAL(cgtrfs,CGTRFS) +#define LAPACK_zgtrfs LAPACK_GLOBAL(zgtrfs,ZGTRFS) +#define LAPACK_sporfs LAPACK_GLOBAL(sporfs,SPORFS) +#define LAPACK_dporfs LAPACK_GLOBAL(dporfs,DPORFS) +#define LAPACK_cporfs LAPACK_GLOBAL(cporfs,CPORFS) +#define LAPACK_zporfs LAPACK_GLOBAL(zporfs,ZPORFS) +#define LAPACK_dporfsx LAPACK_GLOBAL(dporfsx,DPORFSX) +#define LAPACK_sporfsx LAPACK_GLOBAL(sporfsx,SPORFSX) +#define LAPACK_zporfsx LAPACK_GLOBAL(zporfsx,ZPORFSX) +#define LAPACK_cporfsx LAPACK_GLOBAL(cporfsx,CPORFSX) +#define LAPACK_spprfs LAPACK_GLOBAL(spprfs,SPPRFS) +#define LAPACK_dpprfs LAPACK_GLOBAL(dpprfs,DPPRFS) +#define LAPACK_cpprfs LAPACK_GLOBAL(cpprfs,CPPRFS) +#define LAPACK_zpprfs LAPACK_GLOBAL(zpprfs,ZPPRFS) +#define LAPACK_spbrfs LAPACK_GLOBAL(spbrfs,SPBRFS) +#define LAPACK_dpbrfs LAPACK_GLOBAL(dpbrfs,DPBRFS) +#define LAPACK_cpbrfs LAPACK_GLOBAL(cpbrfs,CPBRFS) +#define LAPACK_zpbrfs LAPACK_GLOBAL(zpbrfs,ZPBRFS) +#define LAPACK_sptrfs LAPACK_GLOBAL(sptrfs,SPTRFS) +#define LAPACK_dptrfs LAPACK_GLOBAL(dptrfs,DPTRFS) +#define LAPACK_cptrfs LAPACK_GLOBAL(cptrfs,CPTRFS) +#define LAPACK_zptrfs LAPACK_GLOBAL(zptrfs,ZPTRFS) +#define LAPACK_ssyrfs LAPACK_GLOBAL(ssyrfs,SSYRFS) +#define LAPACK_dsyrfs LAPACK_GLOBAL(dsyrfs,DSYRFS) +#define LAPACK_csyrfs LAPACK_GLOBAL(csyrfs,CSYRFS) +#define LAPACK_zsyrfs LAPACK_GLOBAL(zsyrfs,ZSYRFS) +#define LAPACK_dsyrfsx LAPACK_GLOBAL(dsyrfsx,DSYRFSX) +#define LAPACK_ssyrfsx LAPACK_GLOBAL(ssyrfsx,SSYRFSX) +#define LAPACK_zsyrfsx LAPACK_GLOBAL(zsyrfsx,ZSYRFSX) +#define LAPACK_csyrfsx LAPACK_GLOBAL(csyrfsx,CSYRFSX) +#define LAPACK_cherfs LAPACK_GLOBAL(cherfs,CHERFS) +#define LAPACK_zherfs LAPACK_GLOBAL(zherfs,ZHERFS) +#define LAPACK_zherfsx LAPACK_GLOBAL(zherfsx,ZHERFSX) +#define LAPACK_cherfsx LAPACK_GLOBAL(cherfsx,CHERFSX) +#define LAPACK_ssprfs LAPACK_GLOBAL(ssprfs,SSPRFS) +#define LAPACK_dsprfs LAPACK_GLOBAL(dsprfs,DSPRFS) +#define LAPACK_csprfs LAPACK_GLOBAL(csprfs,CSPRFS) +#define LAPACK_zsprfs LAPACK_GLOBAL(zsprfs,ZSPRFS) +#define LAPACK_chprfs LAPACK_GLOBAL(chprfs,CHPRFS) +#define LAPACK_zhprfs LAPACK_GLOBAL(zhprfs,ZHPRFS) +#define LAPACK_strrfs LAPACK_GLOBAL(strrfs,STRRFS) +#define LAPACK_dtrrfs LAPACK_GLOBAL(dtrrfs,DTRRFS) +#define LAPACK_ctrrfs LAPACK_GLOBAL(ctrrfs,CTRRFS) +#define LAPACK_ztrrfs LAPACK_GLOBAL(ztrrfs,ZTRRFS) +#define LAPACK_stprfs LAPACK_GLOBAL(stprfs,STPRFS) +#define LAPACK_dtprfs LAPACK_GLOBAL(dtprfs,DTPRFS) +#define LAPACK_ctprfs LAPACK_GLOBAL(ctprfs,CTPRFS) +#define LAPACK_ztprfs LAPACK_GLOBAL(ztprfs,ZTPRFS) +#define LAPACK_stbrfs LAPACK_GLOBAL(stbrfs,STBRFS) +#define LAPACK_dtbrfs LAPACK_GLOBAL(dtbrfs,DTBRFS) +#define LAPACK_ctbrfs LAPACK_GLOBAL(ctbrfs,CTBRFS) +#define LAPACK_ztbrfs LAPACK_GLOBAL(ztbrfs,ZTBRFS) +#define LAPACK_sgetri LAPACK_GLOBAL(sgetri,SGETRI) +#define LAPACK_dgetri LAPACK_GLOBAL(dgetri,DGETRI) +#define LAPACK_cgetri LAPACK_GLOBAL(cgetri,CGETRI) +#define LAPACK_zgetri LAPACK_GLOBAL(zgetri,ZGETRI) +#define LAPACK_spotri LAPACK_GLOBAL(spotri,SPOTRI) +#define LAPACK_dpotri LAPACK_GLOBAL(dpotri,DPOTRI) +#define LAPACK_cpotri LAPACK_GLOBAL(cpotri,CPOTRI) +#define LAPACK_zpotri LAPACK_GLOBAL(zpotri,ZPOTRI) +#define LAPACK_dpftri LAPACK_GLOBAL(dpftri,DPFTRI) +#define LAPACK_spftri LAPACK_GLOBAL(spftri,SPFTRI) +#define LAPACK_zpftri LAPACK_GLOBAL(zpftri,ZPFTRI) +#define LAPACK_cpftri LAPACK_GLOBAL(cpftri,CPFTRI) +#define LAPACK_spptri LAPACK_GLOBAL(spptri,SPPTRI) +#define LAPACK_dpptri LAPACK_GLOBAL(dpptri,DPPTRI) +#define LAPACK_cpptri LAPACK_GLOBAL(cpptri,CPPTRI) +#define LAPACK_zpptri LAPACK_GLOBAL(zpptri,ZPPTRI) +#define LAPACK_ssytri LAPACK_GLOBAL(ssytri,SSYTRI) +#define LAPACK_dsytri LAPACK_GLOBAL(dsytri,DSYTRI) +#define LAPACK_csytri LAPACK_GLOBAL(csytri,CSYTRI) +#define LAPACK_zsytri LAPACK_GLOBAL(zsytri,ZSYTRI) +#define LAPACK_chetri LAPACK_GLOBAL(chetri,CHETRI) +#define LAPACK_zhetri LAPACK_GLOBAL(zhetri,ZHETRI) +#define LAPACK_ssptri LAPACK_GLOBAL(ssptri,SSPTRI) +#define LAPACK_dsptri LAPACK_GLOBAL(dsptri,DSPTRI) +#define LAPACK_csptri LAPACK_GLOBAL(csptri,CSPTRI) +#define LAPACK_zsptri LAPACK_GLOBAL(zsptri,ZSPTRI) +#define LAPACK_chptri LAPACK_GLOBAL(chptri,CHPTRI) +#define LAPACK_zhptri LAPACK_GLOBAL(zhptri,ZHPTRI) +#define LAPACK_strtri LAPACK_GLOBAL(strtri,STRTRI) +#define LAPACK_dtrtri LAPACK_GLOBAL(dtrtri,DTRTRI) +#define LAPACK_ctrtri LAPACK_GLOBAL(ctrtri,CTRTRI) +#define LAPACK_ztrtri LAPACK_GLOBAL(ztrtri,ZTRTRI) +#define LAPACK_dtftri LAPACK_GLOBAL(dtftri,DTFTRI) +#define LAPACK_stftri LAPACK_GLOBAL(stftri,STFTRI) +#define LAPACK_ztftri LAPACK_GLOBAL(ztftri,ZTFTRI) +#define LAPACK_ctftri LAPACK_GLOBAL(ctftri,CTFTRI) +#define LAPACK_stptri LAPACK_GLOBAL(stptri,STPTRI) +#define LAPACK_dtptri LAPACK_GLOBAL(dtptri,DTPTRI) +#define LAPACK_ctptri LAPACK_GLOBAL(ctptri,CTPTRI) +#define LAPACK_ztptri LAPACK_GLOBAL(ztptri,ZTPTRI) +#define LAPACK_sgeequ LAPACK_GLOBAL(sgeequ,SGEEQU) +#define LAPACK_dgeequ LAPACK_GLOBAL(dgeequ,DGEEQU) +#define LAPACK_cgeequ LAPACK_GLOBAL(cgeequ,CGEEQU) +#define LAPACK_zgeequ LAPACK_GLOBAL(zgeequ,ZGEEQU) +#define LAPACK_dgeequb LAPACK_GLOBAL(dgeequb,DGEEQUB) +#define LAPACK_sgeequb LAPACK_GLOBAL(sgeequb,SGEEQUB) +#define LAPACK_zgeequb LAPACK_GLOBAL(zgeequb,ZGEEQUB) +#define LAPACK_cgeequb LAPACK_GLOBAL(cgeequb,CGEEQUB) +#define LAPACK_sgbequ LAPACK_GLOBAL(sgbequ,SGBEQU) +#define LAPACK_dgbequ LAPACK_GLOBAL(dgbequ,DGBEQU) +#define LAPACK_cgbequ LAPACK_GLOBAL(cgbequ,CGBEQU) +#define LAPACK_zgbequ LAPACK_GLOBAL(zgbequ,ZGBEQU) +#define LAPACK_dgbequb LAPACK_GLOBAL(dgbequb,DGBEQUB) +#define LAPACK_sgbequb LAPACK_GLOBAL(sgbequb,SGBEQUB) +#define LAPACK_zgbequb LAPACK_GLOBAL(zgbequb,ZGBEQUB) +#define LAPACK_cgbequb LAPACK_GLOBAL(cgbequb,CGBEQUB) +#define LAPACK_spoequ LAPACK_GLOBAL(spoequ,SPOEQU) +#define LAPACK_dpoequ LAPACK_GLOBAL(dpoequ,DPOEQU) +#define LAPACK_cpoequ LAPACK_GLOBAL(cpoequ,CPOEQU) +#define LAPACK_zpoequ LAPACK_GLOBAL(zpoequ,ZPOEQU) +#define LAPACK_dpoequb LAPACK_GLOBAL(dpoequb,DPOEQUB) +#define LAPACK_spoequb LAPACK_GLOBAL(spoequb,SPOEQUB) +#define LAPACK_zpoequb LAPACK_GLOBAL(zpoequb,ZPOEQUB) +#define LAPACK_cpoequb LAPACK_GLOBAL(cpoequb,CPOEQUB) +#define LAPACK_sppequ LAPACK_GLOBAL(sppequ,SPPEQU) +#define LAPACK_dppequ LAPACK_GLOBAL(dppequ,DPPEQU) +#define LAPACK_cppequ LAPACK_GLOBAL(cppequ,CPPEQU) +#define LAPACK_zppequ LAPACK_GLOBAL(zppequ,ZPPEQU) +#define LAPACK_spbequ LAPACK_GLOBAL(spbequ,SPBEQU) +#define LAPACK_dpbequ LAPACK_GLOBAL(dpbequ,DPBEQU) +#define LAPACK_cpbequ LAPACK_GLOBAL(cpbequ,CPBEQU) +#define LAPACK_zpbequ LAPACK_GLOBAL(zpbequ,ZPBEQU) +#define LAPACK_dsyequb LAPACK_GLOBAL(dsyequb,DSYEQUB) +#define LAPACK_ssyequb LAPACK_GLOBAL(ssyequb,SSYEQUB) +#define LAPACK_zsyequb LAPACK_GLOBAL(zsyequb,ZSYEQUB) +#define LAPACK_csyequb LAPACK_GLOBAL(csyequb,CSYEQUB) +#define LAPACK_zheequb LAPACK_GLOBAL(zheequb,ZHEEQUB) +#define LAPACK_cheequb LAPACK_GLOBAL(cheequb,CHEEQUB) +#define LAPACK_sgesv LAPACK_GLOBAL(sgesv,SGESV) +#define LAPACK_dgesv LAPACK_GLOBAL(dgesv,DGESV) +#define LAPACK_cgesv LAPACK_GLOBAL(cgesv,CGESV) +#define LAPACK_zgesv LAPACK_GLOBAL(zgesv,ZGESV) +#define LAPACK_dsgesv LAPACK_GLOBAL(dsgesv,DSGESV) +#define LAPACK_zcgesv LAPACK_GLOBAL(zcgesv,ZCGESV) +#define LAPACK_sgesvx LAPACK_GLOBAL(sgesvx,SGESVX) +#define LAPACK_dgesvx LAPACK_GLOBAL(dgesvx,DGESVX) +#define LAPACK_cgesvx LAPACK_GLOBAL(cgesvx,CGESVX) +#define LAPACK_zgesvx LAPACK_GLOBAL(zgesvx,ZGESVX) +#define LAPACK_dgesvxx LAPACK_GLOBAL(dgesvxx,DGESVXX) +#define LAPACK_sgesvxx LAPACK_GLOBAL(sgesvxx,SGESVXX) +#define LAPACK_zgesvxx LAPACK_GLOBAL(zgesvxx,ZGESVXX) +#define LAPACK_cgesvxx LAPACK_GLOBAL(cgesvxx,CGESVXX) +#define LAPACK_sgbsv LAPACK_GLOBAL(sgbsv,SGBSV) +#define LAPACK_dgbsv LAPACK_GLOBAL(dgbsv,DGBSV) +#define LAPACK_cgbsv LAPACK_GLOBAL(cgbsv,CGBSV) +#define LAPACK_zgbsv LAPACK_GLOBAL(zgbsv,ZGBSV) +#define LAPACK_sgbsvx LAPACK_GLOBAL(sgbsvx,SGBSVX) +#define LAPACK_dgbsvx LAPACK_GLOBAL(dgbsvx,DGBSVX) +#define LAPACK_cgbsvx LAPACK_GLOBAL(cgbsvx,CGBSVX) +#define LAPACK_zgbsvx LAPACK_GLOBAL(zgbsvx,ZGBSVX) +#define LAPACK_dgbsvxx LAPACK_GLOBAL(dgbsvxx,DGBSVXX) +#define LAPACK_sgbsvxx LAPACK_GLOBAL(sgbsvxx,SGBSVXX) +#define LAPACK_zgbsvxx LAPACK_GLOBAL(zgbsvxx,ZGBSVXX) +#define LAPACK_cgbsvxx LAPACK_GLOBAL(cgbsvxx,CGBSVXX) +#define LAPACK_sgtsv LAPACK_GLOBAL(sgtsv,SGTSV) +#define LAPACK_dgtsv LAPACK_GLOBAL(dgtsv,DGTSV) +#define LAPACK_cgtsv LAPACK_GLOBAL(cgtsv,CGTSV) +#define LAPACK_zgtsv LAPACK_GLOBAL(zgtsv,ZGTSV) +#define LAPACK_sgtsvx LAPACK_GLOBAL(sgtsvx,SGTSVX) +#define LAPACK_dgtsvx LAPACK_GLOBAL(dgtsvx,DGTSVX) +#define LAPACK_cgtsvx LAPACK_GLOBAL(cgtsvx,CGTSVX) +#define LAPACK_zgtsvx LAPACK_GLOBAL(zgtsvx,ZGTSVX) +#define LAPACK_sposv LAPACK_GLOBAL(sposv,SPOSV) +#define LAPACK_dposv LAPACK_GLOBAL(dposv,DPOSV) +#define LAPACK_cposv LAPACK_GLOBAL(cposv,CPOSV) +#define LAPACK_zposv LAPACK_GLOBAL(zposv,ZPOSV) +#define LAPACK_dsposv LAPACK_GLOBAL(dsposv,DSPOSV) +#define LAPACK_zcposv LAPACK_GLOBAL(zcposv,ZCPOSV) +#define LAPACK_sposvx LAPACK_GLOBAL(sposvx,SPOSVX) +#define LAPACK_dposvx LAPACK_GLOBAL(dposvx,DPOSVX) +#define LAPACK_cposvx LAPACK_GLOBAL(cposvx,CPOSVX) +#define LAPACK_zposvx LAPACK_GLOBAL(zposvx,ZPOSVX) +#define LAPACK_dposvxx LAPACK_GLOBAL(dposvxx,DPOSVXX) +#define LAPACK_sposvxx LAPACK_GLOBAL(sposvxx,SPOSVXX) +#define LAPACK_zposvxx LAPACK_GLOBAL(zposvxx,ZPOSVXX) +#define LAPACK_cposvxx LAPACK_GLOBAL(cposvxx,CPOSVXX) +#define LAPACK_sppsv LAPACK_GLOBAL(sppsv,SPPSV) +#define LAPACK_dppsv LAPACK_GLOBAL(dppsv,DPPSV) +#define LAPACK_cppsv LAPACK_GLOBAL(cppsv,CPPSV) +#define LAPACK_zppsv LAPACK_GLOBAL(zppsv,ZPPSV) +#define LAPACK_sppsvx LAPACK_GLOBAL(sppsvx,SPPSVX) +#define LAPACK_dppsvx LAPACK_GLOBAL(dppsvx,DPPSVX) +#define LAPACK_cppsvx LAPACK_GLOBAL(cppsvx,CPPSVX) +#define LAPACK_zppsvx LAPACK_GLOBAL(zppsvx,ZPPSVX) +#define LAPACK_spbsv LAPACK_GLOBAL(spbsv,SPBSV) +#define LAPACK_dpbsv LAPACK_GLOBAL(dpbsv,DPBSV) +#define LAPACK_cpbsv LAPACK_GLOBAL(cpbsv,CPBSV) +#define LAPACK_zpbsv LAPACK_GLOBAL(zpbsv,ZPBSV) +#define LAPACK_spbsvx LAPACK_GLOBAL(spbsvx,SPBSVX) +#define LAPACK_dpbsvx LAPACK_GLOBAL(dpbsvx,DPBSVX) +#define LAPACK_cpbsvx LAPACK_GLOBAL(cpbsvx,CPBSVX) +#define LAPACK_zpbsvx LAPACK_GLOBAL(zpbsvx,ZPBSVX) +#define LAPACK_sptsv LAPACK_GLOBAL(sptsv,SPTSV) +#define LAPACK_dptsv LAPACK_GLOBAL(dptsv,DPTSV) +#define LAPACK_cptsv LAPACK_GLOBAL(cptsv,CPTSV) +#define LAPACK_zptsv LAPACK_GLOBAL(zptsv,ZPTSV) +#define LAPACK_sptsvx LAPACK_GLOBAL(sptsvx,SPTSVX) +#define LAPACK_dptsvx LAPACK_GLOBAL(dptsvx,DPTSVX) +#define LAPACK_cptsvx LAPACK_GLOBAL(cptsvx,CPTSVX) +#define LAPACK_zptsvx LAPACK_GLOBAL(zptsvx,ZPTSVX) +#define LAPACK_ssysv LAPACK_GLOBAL(ssysv,SSYSV) +#define LAPACK_dsysv LAPACK_GLOBAL(dsysv,DSYSV) +#define LAPACK_csysv LAPACK_GLOBAL(csysv,CSYSV) +#define LAPACK_zsysv LAPACK_GLOBAL(zsysv,ZSYSV) +#define LAPACK_ssysvx LAPACK_GLOBAL(ssysvx,SSYSVX) +#define LAPACK_dsysvx LAPACK_GLOBAL(dsysvx,DSYSVX) +#define LAPACK_csysvx LAPACK_GLOBAL(csysvx,CSYSVX) +#define LAPACK_zsysvx LAPACK_GLOBAL(zsysvx,ZSYSVX) +#define LAPACK_dsysvxx LAPACK_GLOBAL(dsysvxx,DSYSVXX) +#define LAPACK_ssysvxx LAPACK_GLOBAL(ssysvxx,SSYSVXX) +#define LAPACK_zsysvxx LAPACK_GLOBAL(zsysvxx,ZSYSVXX) +#define LAPACK_csysvxx LAPACK_GLOBAL(csysvxx,CSYSVXX) +#define LAPACK_chesv LAPACK_GLOBAL(chesv,CHESV) +#define LAPACK_zhesv LAPACK_GLOBAL(zhesv,ZHESV) +#define LAPACK_chesvx LAPACK_GLOBAL(chesvx,CHESVX) +#define LAPACK_zhesvx LAPACK_GLOBAL(zhesvx,ZHESVX) +#define LAPACK_zhesvxx LAPACK_GLOBAL(zhesvxx,ZHESVXX) +#define LAPACK_chesvxx LAPACK_GLOBAL(chesvxx,CHESVXX) +#define LAPACK_sspsv LAPACK_GLOBAL(sspsv,SSPSV) +#define LAPACK_dspsv LAPACK_GLOBAL(dspsv,DSPSV) +#define LAPACK_cspsv LAPACK_GLOBAL(cspsv,CSPSV) +#define LAPACK_zspsv LAPACK_GLOBAL(zspsv,ZSPSV) +#define LAPACK_sspsvx LAPACK_GLOBAL(sspsvx,SSPSVX) +#define LAPACK_dspsvx LAPACK_GLOBAL(dspsvx,DSPSVX) +#define LAPACK_cspsvx LAPACK_GLOBAL(cspsvx,CSPSVX) +#define LAPACK_zspsvx LAPACK_GLOBAL(zspsvx,ZSPSVX) +#define LAPACK_chpsv LAPACK_GLOBAL(chpsv,CHPSV) +#define LAPACK_zhpsv LAPACK_GLOBAL(zhpsv,ZHPSV) +#define LAPACK_chpsvx LAPACK_GLOBAL(chpsvx,CHPSVX) +#define LAPACK_zhpsvx LAPACK_GLOBAL(zhpsvx,ZHPSVX) +#define LAPACK_sgeqrf LAPACK_GLOBAL(sgeqrf,SGEQRF) +#define LAPACK_dgeqrf LAPACK_GLOBAL(dgeqrf,DGEQRF) +#define LAPACK_cgeqrf LAPACK_GLOBAL(cgeqrf,CGEQRF) +#define LAPACK_zgeqrf LAPACK_GLOBAL(zgeqrf,ZGEQRF) +#define LAPACK_sgeqpf LAPACK_GLOBAL(sgeqpf,SGEQPF) +#define LAPACK_dgeqpf LAPACK_GLOBAL(dgeqpf,DGEQPF) +#define LAPACK_cgeqpf LAPACK_GLOBAL(cgeqpf,CGEQPF) +#define LAPACK_zgeqpf LAPACK_GLOBAL(zgeqpf,ZGEQPF) +#define LAPACK_sgeqp3 LAPACK_GLOBAL(sgeqp3,SGEQP3) +#define LAPACK_dgeqp3 LAPACK_GLOBAL(dgeqp3,DGEQP3) +#define LAPACK_cgeqp3 LAPACK_GLOBAL(cgeqp3,CGEQP3) +#define LAPACK_zgeqp3 LAPACK_GLOBAL(zgeqp3,ZGEQP3) +#define LAPACK_sorgqr LAPACK_GLOBAL(sorgqr,SORGQR) +#define LAPACK_dorgqr LAPACK_GLOBAL(dorgqr,DORGQR) +#define LAPACK_sormqr LAPACK_GLOBAL(sormqr,SORMQR) +#define LAPACK_dormqr LAPACK_GLOBAL(dormqr,DORMQR) +#define LAPACK_cungqr LAPACK_GLOBAL(cungqr,CUNGQR) +#define LAPACK_zungqr LAPACK_GLOBAL(zungqr,ZUNGQR) +#define LAPACK_cunmqr LAPACK_GLOBAL(cunmqr,CUNMQR) +#define LAPACK_zunmqr LAPACK_GLOBAL(zunmqr,ZUNMQR) +#define LAPACK_sgelqf LAPACK_GLOBAL(sgelqf,SGELQF) +#define LAPACK_dgelqf LAPACK_GLOBAL(dgelqf,DGELQF) +#define LAPACK_cgelqf LAPACK_GLOBAL(cgelqf,CGELQF) +#define LAPACK_zgelqf LAPACK_GLOBAL(zgelqf,ZGELQF) +#define LAPACK_sorglq LAPACK_GLOBAL(sorglq,SORGLQ) +#define LAPACK_dorglq LAPACK_GLOBAL(dorglq,DORGLQ) +#define LAPACK_sormlq LAPACK_GLOBAL(sormlq,SORMLQ) +#define LAPACK_dormlq LAPACK_GLOBAL(dormlq,DORMLQ) +#define LAPACK_cunglq LAPACK_GLOBAL(cunglq,CUNGLQ) +#define LAPACK_zunglq LAPACK_GLOBAL(zunglq,ZUNGLQ) +#define LAPACK_cunmlq LAPACK_GLOBAL(cunmlq,CUNMLQ) +#define LAPACK_zunmlq LAPACK_GLOBAL(zunmlq,ZUNMLQ) +#define LAPACK_sgeqlf LAPACK_GLOBAL(sgeqlf,SGEQLF) +#define LAPACK_dgeqlf LAPACK_GLOBAL(dgeqlf,DGEQLF) +#define LAPACK_cgeqlf LAPACK_GLOBAL(cgeqlf,CGEQLF) +#define LAPACK_zgeqlf LAPACK_GLOBAL(zgeqlf,ZGEQLF) +#define LAPACK_sorgql LAPACK_GLOBAL(sorgql,SORGQL) +#define LAPACK_dorgql LAPACK_GLOBAL(dorgql,DORGQL) +#define LAPACK_cungql LAPACK_GLOBAL(cungql,CUNGQL) +#define LAPACK_zungql LAPACK_GLOBAL(zungql,ZUNGQL) +#define LAPACK_sormql LAPACK_GLOBAL(sormql,SORMQL) +#define LAPACK_dormql LAPACK_GLOBAL(dormql,DORMQL) +#define LAPACK_cunmql LAPACK_GLOBAL(cunmql,CUNMQL) +#define LAPACK_zunmql LAPACK_GLOBAL(zunmql,ZUNMQL) +#define LAPACK_sgerqf LAPACK_GLOBAL(sgerqf,SGERQF) +#define LAPACK_dgerqf LAPACK_GLOBAL(dgerqf,DGERQF) +#define LAPACK_cgerqf LAPACK_GLOBAL(cgerqf,CGERQF) +#define LAPACK_zgerqf LAPACK_GLOBAL(zgerqf,ZGERQF) +#define LAPACK_sorgrq LAPACK_GLOBAL(sorgrq,SORGRQ) +#define LAPACK_dorgrq LAPACK_GLOBAL(dorgrq,DORGRQ) +#define LAPACK_cungrq LAPACK_GLOBAL(cungrq,CUNGRQ) +#define LAPACK_zungrq LAPACK_GLOBAL(zungrq,ZUNGRQ) +#define LAPACK_sormrq LAPACK_GLOBAL(sormrq,SORMRQ) +#define LAPACK_dormrq LAPACK_GLOBAL(dormrq,DORMRQ) +#define LAPACK_cunmrq LAPACK_GLOBAL(cunmrq,CUNMRQ) +#define LAPACK_zunmrq LAPACK_GLOBAL(zunmrq,ZUNMRQ) +#define LAPACK_stzrzf LAPACK_GLOBAL(stzrzf,STZRZF) +#define LAPACK_dtzrzf LAPACK_GLOBAL(dtzrzf,DTZRZF) +#define LAPACK_ctzrzf LAPACK_GLOBAL(ctzrzf,CTZRZF) +#define LAPACK_ztzrzf LAPACK_GLOBAL(ztzrzf,ZTZRZF) +#define LAPACK_sormrz LAPACK_GLOBAL(sormrz,SORMRZ) +#define LAPACK_dormrz LAPACK_GLOBAL(dormrz,DORMRZ) +#define LAPACK_cunmrz LAPACK_GLOBAL(cunmrz,CUNMRZ) +#define LAPACK_zunmrz LAPACK_GLOBAL(zunmrz,ZUNMRZ) +#define LAPACK_sggqrf LAPACK_GLOBAL(sggqrf,SGGQRF) +#define LAPACK_dggqrf LAPACK_GLOBAL(dggqrf,DGGQRF) +#define LAPACK_cggqrf LAPACK_GLOBAL(cggqrf,CGGQRF) +#define LAPACK_zggqrf LAPACK_GLOBAL(zggqrf,ZGGQRF) +#define LAPACK_sggrqf LAPACK_GLOBAL(sggrqf,SGGRQF) +#define LAPACK_dggrqf LAPACK_GLOBAL(dggrqf,DGGRQF) +#define LAPACK_cggrqf LAPACK_GLOBAL(cggrqf,CGGRQF) +#define LAPACK_zggrqf LAPACK_GLOBAL(zggrqf,ZGGRQF) +#define LAPACK_sgebrd LAPACK_GLOBAL(sgebrd,SGEBRD) +#define LAPACK_dgebrd LAPACK_GLOBAL(dgebrd,DGEBRD) +#define LAPACK_cgebrd LAPACK_GLOBAL(cgebrd,CGEBRD) +#define LAPACK_zgebrd LAPACK_GLOBAL(zgebrd,ZGEBRD) +#define LAPACK_sgbbrd LAPACK_GLOBAL(sgbbrd,SGBBRD) +#define LAPACK_dgbbrd LAPACK_GLOBAL(dgbbrd,DGBBRD) +#define LAPACK_cgbbrd LAPACK_GLOBAL(cgbbrd,CGBBRD) +#define LAPACK_zgbbrd LAPACK_GLOBAL(zgbbrd,ZGBBRD) +#define LAPACK_sorgbr LAPACK_GLOBAL(sorgbr,SORGBR) +#define LAPACK_dorgbr LAPACK_GLOBAL(dorgbr,DORGBR) +#define LAPACK_sormbr LAPACK_GLOBAL(sormbr,SORMBR) +#define LAPACK_dormbr LAPACK_GLOBAL(dormbr,DORMBR) +#define LAPACK_cungbr LAPACK_GLOBAL(cungbr,CUNGBR) +#define LAPACK_zungbr LAPACK_GLOBAL(zungbr,ZUNGBR) +#define LAPACK_cunmbr LAPACK_GLOBAL(cunmbr,CUNMBR) +#define LAPACK_zunmbr LAPACK_GLOBAL(zunmbr,ZUNMBR) +#define LAPACK_sbdsqr LAPACK_GLOBAL(sbdsqr,SBDSQR) +#define LAPACK_dbdsqr LAPACK_GLOBAL(dbdsqr,DBDSQR) +#define LAPACK_cbdsqr LAPACK_GLOBAL(cbdsqr,CBDSQR) +#define LAPACK_zbdsqr LAPACK_GLOBAL(zbdsqr,ZBDSQR) +#define LAPACK_sbdsdc LAPACK_GLOBAL(sbdsdc,SBDSDC) +#define LAPACK_dbdsdc LAPACK_GLOBAL(dbdsdc,DBDSDC) +#define LAPACK_ssytrd LAPACK_GLOBAL(ssytrd,SSYTRD) +#define LAPACK_dsytrd LAPACK_GLOBAL(dsytrd,DSYTRD) +#define LAPACK_sorgtr LAPACK_GLOBAL(sorgtr,SORGTR) +#define LAPACK_dorgtr LAPACK_GLOBAL(dorgtr,DORGTR) +#define LAPACK_sormtr LAPACK_GLOBAL(sormtr,SORMTR) +#define LAPACK_dormtr LAPACK_GLOBAL(dormtr,DORMTR) +#define LAPACK_chetrd LAPACK_GLOBAL(chetrd,CHETRD) +#define LAPACK_zhetrd LAPACK_GLOBAL(zhetrd,ZHETRD) +#define LAPACK_cungtr LAPACK_GLOBAL(cungtr,CUNGTR) +#define LAPACK_zungtr LAPACK_GLOBAL(zungtr,ZUNGTR) +#define LAPACK_cunmtr LAPACK_GLOBAL(cunmtr,CUNMTR) +#define LAPACK_zunmtr LAPACK_GLOBAL(zunmtr,ZUNMTR) +#define LAPACK_ssptrd LAPACK_GLOBAL(ssptrd,SSPTRD) +#define LAPACK_dsptrd LAPACK_GLOBAL(dsptrd,DSPTRD) +#define LAPACK_sopgtr LAPACK_GLOBAL(sopgtr,SOPGTR) +#define LAPACK_dopgtr LAPACK_GLOBAL(dopgtr,DOPGTR) +#define LAPACK_sopmtr LAPACK_GLOBAL(sopmtr,SOPMTR) +#define LAPACK_dopmtr LAPACK_GLOBAL(dopmtr,DOPMTR) +#define LAPACK_chptrd LAPACK_GLOBAL(chptrd,CHPTRD) +#define LAPACK_zhptrd LAPACK_GLOBAL(zhptrd,ZHPTRD) +#define LAPACK_cupgtr LAPACK_GLOBAL(cupgtr,CUPGTR) +#define LAPACK_zupgtr LAPACK_GLOBAL(zupgtr,ZUPGTR) +#define LAPACK_cupmtr LAPACK_GLOBAL(cupmtr,CUPMTR) +#define LAPACK_zupmtr LAPACK_GLOBAL(zupmtr,ZUPMTR) +#define LAPACK_ssbtrd LAPACK_GLOBAL(ssbtrd,SSBTRD) +#define LAPACK_dsbtrd LAPACK_GLOBAL(dsbtrd,DSBTRD) +#define LAPACK_chbtrd LAPACK_GLOBAL(chbtrd,CHBTRD) +#define LAPACK_zhbtrd LAPACK_GLOBAL(zhbtrd,ZHBTRD) +#define LAPACK_ssterf LAPACK_GLOBAL(ssterf,SSTERF) +#define LAPACK_dsterf LAPACK_GLOBAL(dsterf,DSTERF) +#define LAPACK_ssteqr LAPACK_GLOBAL(ssteqr,SSTEQR) +#define LAPACK_dsteqr LAPACK_GLOBAL(dsteqr,DSTEQR) +#define LAPACK_csteqr LAPACK_GLOBAL(csteqr,CSTEQR) +#define LAPACK_zsteqr LAPACK_GLOBAL(zsteqr,ZSTEQR) +#define LAPACK_sstemr LAPACK_GLOBAL(sstemr,SSTEMR) +#define LAPACK_dstemr LAPACK_GLOBAL(dstemr,DSTEMR) +#define LAPACK_cstemr LAPACK_GLOBAL(cstemr,CSTEMR) +#define LAPACK_zstemr LAPACK_GLOBAL(zstemr,ZSTEMR) +#define LAPACK_sstedc LAPACK_GLOBAL(sstedc,SSTEDC) +#define LAPACK_dstedc LAPACK_GLOBAL(dstedc,DSTEDC) +#define LAPACK_cstedc LAPACK_GLOBAL(cstedc,CSTEDC) +#define LAPACK_zstedc LAPACK_GLOBAL(zstedc,ZSTEDC) +#define LAPACK_sstegr LAPACK_GLOBAL(sstegr,SSTEGR) +#define LAPACK_dstegr LAPACK_GLOBAL(dstegr,DSTEGR) +#define LAPACK_cstegr LAPACK_GLOBAL(cstegr,CSTEGR) +#define LAPACK_zstegr LAPACK_GLOBAL(zstegr,ZSTEGR) +#define LAPACK_spteqr LAPACK_GLOBAL(spteqr,SPTEQR) +#define LAPACK_dpteqr LAPACK_GLOBAL(dpteqr,DPTEQR) +#define LAPACK_cpteqr LAPACK_GLOBAL(cpteqr,CPTEQR) +#define LAPACK_zpteqr LAPACK_GLOBAL(zpteqr,ZPTEQR) +#define LAPACK_sstebz LAPACK_GLOBAL(sstebz,SSTEBZ) +#define LAPACK_dstebz LAPACK_GLOBAL(dstebz,DSTEBZ) +#define LAPACK_sstein LAPACK_GLOBAL(sstein,SSTEIN) +#define LAPACK_dstein LAPACK_GLOBAL(dstein,DSTEIN) +#define LAPACK_cstein LAPACK_GLOBAL(cstein,CSTEIN) +#define LAPACK_zstein LAPACK_GLOBAL(zstein,ZSTEIN) +#define LAPACK_sdisna LAPACK_GLOBAL(sdisna,SDISNA) +#define LAPACK_ddisna LAPACK_GLOBAL(ddisna,DDISNA) +#define LAPACK_ssygst LAPACK_GLOBAL(ssygst,SSYGST) +#define LAPACK_dsygst LAPACK_GLOBAL(dsygst,DSYGST) +#define LAPACK_chegst LAPACK_GLOBAL(chegst,CHEGST) +#define LAPACK_zhegst LAPACK_GLOBAL(zhegst,ZHEGST) +#define LAPACK_sspgst LAPACK_GLOBAL(sspgst,SSPGST) +#define LAPACK_dspgst LAPACK_GLOBAL(dspgst,DSPGST) +#define LAPACK_chpgst LAPACK_GLOBAL(chpgst,CHPGST) +#define LAPACK_zhpgst LAPACK_GLOBAL(zhpgst,ZHPGST) +#define LAPACK_ssbgst LAPACK_GLOBAL(ssbgst,SSBGST) +#define LAPACK_dsbgst LAPACK_GLOBAL(dsbgst,DSBGST) +#define LAPACK_chbgst LAPACK_GLOBAL(chbgst,CHBGST) +#define LAPACK_zhbgst LAPACK_GLOBAL(zhbgst,ZHBGST) +#define LAPACK_spbstf LAPACK_GLOBAL(spbstf,SPBSTF) +#define LAPACK_dpbstf LAPACK_GLOBAL(dpbstf,DPBSTF) +#define LAPACK_cpbstf LAPACK_GLOBAL(cpbstf,CPBSTF) +#define LAPACK_zpbstf LAPACK_GLOBAL(zpbstf,ZPBSTF) +#define LAPACK_sgehrd LAPACK_GLOBAL(sgehrd,SGEHRD) +#define LAPACK_dgehrd LAPACK_GLOBAL(dgehrd,DGEHRD) +#define LAPACK_cgehrd LAPACK_GLOBAL(cgehrd,CGEHRD) +#define LAPACK_zgehrd LAPACK_GLOBAL(zgehrd,ZGEHRD) +#define LAPACK_sorghr LAPACK_GLOBAL(sorghr,SORGHR) +#define LAPACK_dorghr LAPACK_GLOBAL(dorghr,DORGHR) +#define LAPACK_sormhr LAPACK_GLOBAL(sormhr,SORMHR) +#define LAPACK_dormhr LAPACK_GLOBAL(dormhr,DORMHR) +#define LAPACK_cunghr LAPACK_GLOBAL(cunghr,CUNGHR) +#define LAPACK_zunghr LAPACK_GLOBAL(zunghr,ZUNGHR) +#define LAPACK_cunmhr LAPACK_GLOBAL(cunmhr,CUNMHR) +#define LAPACK_zunmhr LAPACK_GLOBAL(zunmhr,ZUNMHR) +#define LAPACK_sgebal LAPACK_GLOBAL(sgebal,SGEBAL) +#define LAPACK_dgebal LAPACK_GLOBAL(dgebal,DGEBAL) +#define LAPACK_cgebal LAPACK_GLOBAL(cgebal,CGEBAL) +#define LAPACK_zgebal LAPACK_GLOBAL(zgebal,ZGEBAL) +#define LAPACK_sgebak LAPACK_GLOBAL(sgebak,SGEBAK) +#define LAPACK_dgebak LAPACK_GLOBAL(dgebak,DGEBAK) +#define LAPACK_cgebak LAPACK_GLOBAL(cgebak,CGEBAK) +#define LAPACK_zgebak LAPACK_GLOBAL(zgebak,ZGEBAK) +#define LAPACK_shseqr LAPACK_GLOBAL(shseqr,SHSEQR) +#define LAPACK_dhseqr LAPACK_GLOBAL(dhseqr,DHSEQR) +#define LAPACK_chseqr LAPACK_GLOBAL(chseqr,CHSEQR) +#define LAPACK_zhseqr LAPACK_GLOBAL(zhseqr,ZHSEQR) +#define LAPACK_shsein LAPACK_GLOBAL(shsein,SHSEIN) +#define LAPACK_dhsein LAPACK_GLOBAL(dhsein,DHSEIN) +#define LAPACK_chsein LAPACK_GLOBAL(chsein,CHSEIN) +#define LAPACK_zhsein LAPACK_GLOBAL(zhsein,ZHSEIN) +#define LAPACK_strevc LAPACK_GLOBAL(strevc,STREVC) +#define LAPACK_dtrevc LAPACK_GLOBAL(dtrevc,DTREVC) +#define LAPACK_ctrevc LAPACK_GLOBAL(ctrevc,CTREVC) +#define LAPACK_ztrevc LAPACK_GLOBAL(ztrevc,ZTREVC) +#define LAPACK_strsna LAPACK_GLOBAL(strsna,STRSNA) +#define LAPACK_dtrsna LAPACK_GLOBAL(dtrsna,DTRSNA) +#define LAPACK_ctrsna LAPACK_GLOBAL(ctrsna,CTRSNA) +#define LAPACK_ztrsna LAPACK_GLOBAL(ztrsna,ZTRSNA) +#define LAPACK_strexc LAPACK_GLOBAL(strexc,STREXC) +#define LAPACK_dtrexc LAPACK_GLOBAL(dtrexc,DTREXC) +#define LAPACK_ctrexc LAPACK_GLOBAL(ctrexc,CTREXC) +#define LAPACK_ztrexc LAPACK_GLOBAL(ztrexc,ZTREXC) +#define LAPACK_strsen LAPACK_GLOBAL(strsen,STRSEN) +#define LAPACK_dtrsen LAPACK_GLOBAL(dtrsen,DTRSEN) +#define LAPACK_ctrsen LAPACK_GLOBAL(ctrsen,CTRSEN) +#define LAPACK_ztrsen LAPACK_GLOBAL(ztrsen,ZTRSEN) +#define LAPACK_strsyl LAPACK_GLOBAL(strsyl,STRSYL) +#define LAPACK_dtrsyl LAPACK_GLOBAL(dtrsyl,DTRSYL) +#define LAPACK_ctrsyl LAPACK_GLOBAL(ctrsyl,CTRSYL) +#define LAPACK_ztrsyl LAPACK_GLOBAL(ztrsyl,ZTRSYL) +#define LAPACK_sgghrd LAPACK_GLOBAL(sgghrd,SGGHRD) +#define LAPACK_dgghrd LAPACK_GLOBAL(dgghrd,DGGHRD) +#define LAPACK_cgghrd LAPACK_GLOBAL(cgghrd,CGGHRD) +#define LAPACK_zgghrd LAPACK_GLOBAL(zgghrd,ZGGHRD) +#define LAPACK_sggbal LAPACK_GLOBAL(sggbal,SGGBAL) +#define LAPACK_dggbal LAPACK_GLOBAL(dggbal,DGGBAL) +#define LAPACK_cggbal LAPACK_GLOBAL(cggbal,CGGBAL) +#define LAPACK_zggbal LAPACK_GLOBAL(zggbal,ZGGBAL) +#define LAPACK_sggbak LAPACK_GLOBAL(sggbak,SGGBAK) +#define LAPACK_dggbak LAPACK_GLOBAL(dggbak,DGGBAK) +#define LAPACK_cggbak LAPACK_GLOBAL(cggbak,CGGBAK) +#define LAPACK_zggbak LAPACK_GLOBAL(zggbak,ZGGBAK) +#define LAPACK_shgeqz LAPACK_GLOBAL(shgeqz,SHGEQZ) +#define LAPACK_dhgeqz LAPACK_GLOBAL(dhgeqz,DHGEQZ) +#define LAPACK_chgeqz LAPACK_GLOBAL(chgeqz,CHGEQZ) +#define LAPACK_zhgeqz LAPACK_GLOBAL(zhgeqz,ZHGEQZ) +#define LAPACK_stgevc LAPACK_GLOBAL(stgevc,STGEVC) +#define LAPACK_dtgevc LAPACK_GLOBAL(dtgevc,DTGEVC) +#define LAPACK_ctgevc LAPACK_GLOBAL(ctgevc,CTGEVC) +#define LAPACK_ztgevc LAPACK_GLOBAL(ztgevc,ZTGEVC) +#define LAPACK_stgexc LAPACK_GLOBAL(stgexc,STGEXC) +#define LAPACK_dtgexc LAPACK_GLOBAL(dtgexc,DTGEXC) +#define LAPACK_ctgexc LAPACK_GLOBAL(ctgexc,CTGEXC) +#define LAPACK_ztgexc LAPACK_GLOBAL(ztgexc,ZTGEXC) +#define LAPACK_stgsen LAPACK_GLOBAL(stgsen,STGSEN) +#define LAPACK_dtgsen LAPACK_GLOBAL(dtgsen,DTGSEN) +#define LAPACK_ctgsen LAPACK_GLOBAL(ctgsen,CTGSEN) +#define LAPACK_ztgsen LAPACK_GLOBAL(ztgsen,ZTGSEN) +#define LAPACK_stgsyl LAPACK_GLOBAL(stgsyl,STGSYL) +#define LAPACK_dtgsyl LAPACK_GLOBAL(dtgsyl,DTGSYL) +#define LAPACK_ctgsyl LAPACK_GLOBAL(ctgsyl,CTGSYL) +#define LAPACK_ztgsyl LAPACK_GLOBAL(ztgsyl,ZTGSYL) +#define LAPACK_stgsna LAPACK_GLOBAL(stgsna,STGSNA) +#define LAPACK_dtgsna LAPACK_GLOBAL(dtgsna,DTGSNA) +#define LAPACK_ctgsna LAPACK_GLOBAL(ctgsna,CTGSNA) +#define LAPACK_ztgsna LAPACK_GLOBAL(ztgsna,ZTGSNA) +#define LAPACK_sggsvp LAPACK_GLOBAL(sggsvp,SGGSVP) +#define LAPACK_dggsvp LAPACK_GLOBAL(dggsvp,DGGSVP) +#define LAPACK_cggsvp LAPACK_GLOBAL(cggsvp,CGGSVP) +#define LAPACK_zggsvp LAPACK_GLOBAL(zggsvp,ZGGSVP) +#define LAPACK_stgsja LAPACK_GLOBAL(stgsja,STGSJA) +#define LAPACK_dtgsja LAPACK_GLOBAL(dtgsja,DTGSJA) +#define LAPACK_ctgsja LAPACK_GLOBAL(ctgsja,CTGSJA) +#define LAPACK_ztgsja LAPACK_GLOBAL(ztgsja,ZTGSJA) +#define LAPACK_sgels LAPACK_GLOBAL(sgels,SGELS) +#define LAPACK_dgels LAPACK_GLOBAL(dgels,DGELS) +#define LAPACK_cgels LAPACK_GLOBAL(cgels,CGELS) +#define LAPACK_zgels LAPACK_GLOBAL(zgels,ZGELS) +#define LAPACK_sgelsy LAPACK_GLOBAL(sgelsy,SGELSY) +#define LAPACK_dgelsy LAPACK_GLOBAL(dgelsy,DGELSY) +#define LAPACK_cgelsy LAPACK_GLOBAL(cgelsy,CGELSY) +#define LAPACK_zgelsy LAPACK_GLOBAL(zgelsy,ZGELSY) +#define LAPACK_sgelss LAPACK_GLOBAL(sgelss,SGELSS) +#define LAPACK_dgelss LAPACK_GLOBAL(dgelss,DGELSS) +#define LAPACK_cgelss LAPACK_GLOBAL(cgelss,CGELSS) +#define LAPACK_zgelss LAPACK_GLOBAL(zgelss,ZGELSS) +#define LAPACK_sgelsd LAPACK_GLOBAL(sgelsd,SGELSD) +#define LAPACK_dgelsd LAPACK_GLOBAL(dgelsd,DGELSD) +#define LAPACK_cgelsd LAPACK_GLOBAL(cgelsd,CGELSD) +#define LAPACK_zgelsd LAPACK_GLOBAL(zgelsd,ZGELSD) +#define LAPACK_sgglse LAPACK_GLOBAL(sgglse,SGGLSE) +#define LAPACK_dgglse LAPACK_GLOBAL(dgglse,DGGLSE) +#define LAPACK_cgglse LAPACK_GLOBAL(cgglse,CGGLSE) +#define LAPACK_zgglse LAPACK_GLOBAL(zgglse,ZGGLSE) +#define LAPACK_sggglm LAPACK_GLOBAL(sggglm,SGGGLM) +#define LAPACK_dggglm LAPACK_GLOBAL(dggglm,DGGGLM) +#define LAPACK_cggglm LAPACK_GLOBAL(cggglm,CGGGLM) +#define LAPACK_zggglm LAPACK_GLOBAL(zggglm,ZGGGLM) +#define LAPACK_ssyev LAPACK_GLOBAL(ssyev,SSYEV) +#define LAPACK_dsyev LAPACK_GLOBAL(dsyev,DSYEV) +#define LAPACK_cheev LAPACK_GLOBAL(cheev,CHEEV) +#define LAPACK_zheev LAPACK_GLOBAL(zheev,ZHEEV) +#define LAPACK_ssyevd LAPACK_GLOBAL(ssyevd,SSYEVD) +#define LAPACK_dsyevd LAPACK_GLOBAL(dsyevd,DSYEVD) +#define LAPACK_cheevd LAPACK_GLOBAL(cheevd,CHEEVD) +#define LAPACK_zheevd LAPACK_GLOBAL(zheevd,ZHEEVD) +#define LAPACK_ssyevx LAPACK_GLOBAL(ssyevx,SSYEVX) +#define LAPACK_dsyevx LAPACK_GLOBAL(dsyevx,DSYEVX) +#define LAPACK_cheevx LAPACK_GLOBAL(cheevx,CHEEVX) +#define LAPACK_zheevx LAPACK_GLOBAL(zheevx,ZHEEVX) +#define LAPACK_ssyevr LAPACK_GLOBAL(ssyevr,SSYEVR) +#define LAPACK_dsyevr LAPACK_GLOBAL(dsyevr,DSYEVR) +#define LAPACK_cheevr LAPACK_GLOBAL(cheevr,CHEEVR) +#define LAPACK_zheevr LAPACK_GLOBAL(zheevr,ZHEEVR) +#define LAPACK_sspev LAPACK_GLOBAL(sspev,SSPEV) +#define LAPACK_dspev LAPACK_GLOBAL(dspev,DSPEV) +#define LAPACK_chpev LAPACK_GLOBAL(chpev,CHPEV) +#define LAPACK_zhpev LAPACK_GLOBAL(zhpev,ZHPEV) +#define LAPACK_sspevd LAPACK_GLOBAL(sspevd,SSPEVD) +#define LAPACK_dspevd LAPACK_GLOBAL(dspevd,DSPEVD) +#define LAPACK_chpevd LAPACK_GLOBAL(chpevd,CHPEVD) +#define LAPACK_zhpevd LAPACK_GLOBAL(zhpevd,ZHPEVD) +#define LAPACK_sspevx LAPACK_GLOBAL(sspevx,SSPEVX) +#define LAPACK_dspevx LAPACK_GLOBAL(dspevx,DSPEVX) +#define LAPACK_chpevx LAPACK_GLOBAL(chpevx,CHPEVX) +#define LAPACK_zhpevx LAPACK_GLOBAL(zhpevx,ZHPEVX) +#define LAPACK_ssbev LAPACK_GLOBAL(ssbev,SSBEV) +#define LAPACK_dsbev LAPACK_GLOBAL(dsbev,DSBEV) +#define LAPACK_chbev LAPACK_GLOBAL(chbev,CHBEV) +#define LAPACK_zhbev LAPACK_GLOBAL(zhbev,ZHBEV) +#define LAPACK_ssbevd LAPACK_GLOBAL(ssbevd,SSBEVD) +#define LAPACK_dsbevd LAPACK_GLOBAL(dsbevd,DSBEVD) +#define LAPACK_chbevd LAPACK_GLOBAL(chbevd,CHBEVD) +#define LAPACK_zhbevd LAPACK_GLOBAL(zhbevd,ZHBEVD) +#define LAPACK_ssbevx LAPACK_GLOBAL(ssbevx,SSBEVX) +#define LAPACK_dsbevx LAPACK_GLOBAL(dsbevx,DSBEVX) +#define LAPACK_chbevx LAPACK_GLOBAL(chbevx,CHBEVX) +#define LAPACK_zhbevx LAPACK_GLOBAL(zhbevx,ZHBEVX) +#define LAPACK_sstev LAPACK_GLOBAL(sstev,SSTEV) +#define LAPACK_dstev LAPACK_GLOBAL(dstev,DSTEV) +#define LAPACK_sstevd LAPACK_GLOBAL(sstevd,SSTEVD) +#define LAPACK_dstevd LAPACK_GLOBAL(dstevd,DSTEVD) +#define LAPACK_sstevx LAPACK_GLOBAL(sstevx,SSTEVX) +#define LAPACK_dstevx LAPACK_GLOBAL(dstevx,DSTEVX) +#define LAPACK_sstevr LAPACK_GLOBAL(sstevr,SSTEVR) +#define LAPACK_dstevr LAPACK_GLOBAL(dstevr,DSTEVR) +#define LAPACK_sgees LAPACK_GLOBAL(sgees,SGEES) +#define LAPACK_dgees LAPACK_GLOBAL(dgees,DGEES) +#define LAPACK_cgees LAPACK_GLOBAL(cgees,CGEES) +#define LAPACK_zgees LAPACK_GLOBAL(zgees,ZGEES) +#define LAPACK_sgeesx LAPACK_GLOBAL(sgeesx,SGEESX) +#define LAPACK_dgeesx LAPACK_GLOBAL(dgeesx,DGEESX) +#define LAPACK_cgeesx LAPACK_GLOBAL(cgeesx,CGEESX) +#define LAPACK_zgeesx LAPACK_GLOBAL(zgeesx,ZGEESX) +#define LAPACK_sgeev LAPACK_GLOBAL(sgeev,SGEEV) +#define LAPACK_dgeev LAPACK_GLOBAL(dgeev,DGEEV) +#define LAPACK_cgeev LAPACK_GLOBAL(cgeev,CGEEV) +#define LAPACK_zgeev LAPACK_GLOBAL(zgeev,ZGEEV) +#define LAPACK_sgeevx LAPACK_GLOBAL(sgeevx,SGEEVX) +#define LAPACK_dgeevx LAPACK_GLOBAL(dgeevx,DGEEVX) +#define LAPACK_cgeevx LAPACK_GLOBAL(cgeevx,CGEEVX) +#define LAPACK_zgeevx LAPACK_GLOBAL(zgeevx,ZGEEVX) +#define LAPACK_sgesvd LAPACK_GLOBAL(sgesvd,SGESVD) +#define LAPACK_dgesvd LAPACK_GLOBAL(dgesvd,DGESVD) +#define LAPACK_cgesvd LAPACK_GLOBAL(cgesvd,CGESVD) +#define LAPACK_zgesvd LAPACK_GLOBAL(zgesvd,ZGESVD) +#define LAPACK_sgesdd LAPACK_GLOBAL(sgesdd,SGESDD) +#define LAPACK_dgesdd LAPACK_GLOBAL(dgesdd,DGESDD) +#define LAPACK_cgesdd LAPACK_GLOBAL(cgesdd,CGESDD) +#define LAPACK_zgesdd LAPACK_GLOBAL(zgesdd,ZGESDD) +#define LAPACK_dgejsv LAPACK_GLOBAL(dgejsv,DGEJSV) +#define LAPACK_sgejsv LAPACK_GLOBAL(sgejsv,SGEJSV) +#define LAPACK_dgesvj LAPACK_GLOBAL(dgesvj,DGESVJ) +#define LAPACK_sgesvj LAPACK_GLOBAL(sgesvj,SGESVJ) +#define LAPACK_sggsvd LAPACK_GLOBAL(sggsvd,SGGSVD) +#define LAPACK_dggsvd LAPACK_GLOBAL(dggsvd,DGGSVD) +#define LAPACK_cggsvd LAPACK_GLOBAL(cggsvd,CGGSVD) +#define LAPACK_zggsvd LAPACK_GLOBAL(zggsvd,ZGGSVD) +#define LAPACK_ssygv LAPACK_GLOBAL(ssygv,SSYGV) +#define LAPACK_dsygv LAPACK_GLOBAL(dsygv,DSYGV) +#define LAPACK_chegv LAPACK_GLOBAL(chegv,CHEGV) +#define LAPACK_zhegv LAPACK_GLOBAL(zhegv,ZHEGV) +#define LAPACK_ssygvd LAPACK_GLOBAL(ssygvd,SSYGVD) +#define LAPACK_dsygvd LAPACK_GLOBAL(dsygvd,DSYGVD) +#define LAPACK_chegvd LAPACK_GLOBAL(chegvd,CHEGVD) +#define LAPACK_zhegvd LAPACK_GLOBAL(zhegvd,ZHEGVD) +#define LAPACK_ssygvx LAPACK_GLOBAL(ssygvx,SSYGVX) +#define LAPACK_dsygvx LAPACK_GLOBAL(dsygvx,DSYGVX) +#define LAPACK_chegvx LAPACK_GLOBAL(chegvx,CHEGVX) +#define LAPACK_zhegvx LAPACK_GLOBAL(zhegvx,ZHEGVX) +#define LAPACK_sspgv LAPACK_GLOBAL(sspgv,SSPGV) +#define LAPACK_dspgv LAPACK_GLOBAL(dspgv,DSPGV) +#define LAPACK_chpgv LAPACK_GLOBAL(chpgv,CHPGV) +#define LAPACK_zhpgv LAPACK_GLOBAL(zhpgv,ZHPGV) +#define LAPACK_sspgvd LAPACK_GLOBAL(sspgvd,SSPGVD) +#define LAPACK_dspgvd LAPACK_GLOBAL(dspgvd,DSPGVD) +#define LAPACK_chpgvd LAPACK_GLOBAL(chpgvd,CHPGVD) +#define LAPACK_zhpgvd LAPACK_GLOBAL(zhpgvd,ZHPGVD) +#define LAPACK_sspgvx LAPACK_GLOBAL(sspgvx,SSPGVX) +#define LAPACK_dspgvx LAPACK_GLOBAL(dspgvx,DSPGVX) +#define LAPACK_chpgvx LAPACK_GLOBAL(chpgvx,CHPGVX) +#define LAPACK_zhpgvx LAPACK_GLOBAL(zhpgvx,ZHPGVX) +#define LAPACK_ssbgv LAPACK_GLOBAL(ssbgv,SSBGV) +#define LAPACK_dsbgv LAPACK_GLOBAL(dsbgv,DSBGV) +#define LAPACK_chbgv LAPACK_GLOBAL(chbgv,CHBGV) +#define LAPACK_zhbgv LAPACK_GLOBAL(zhbgv,ZHBGV) +#define LAPACK_ssbgvd LAPACK_GLOBAL(ssbgvd,SSBGVD) +#define LAPACK_dsbgvd LAPACK_GLOBAL(dsbgvd,DSBGVD) +#define LAPACK_chbgvd LAPACK_GLOBAL(chbgvd,CHBGVD) +#define LAPACK_zhbgvd LAPACK_GLOBAL(zhbgvd,ZHBGVD) +#define LAPACK_ssbgvx LAPACK_GLOBAL(ssbgvx,SSBGVX) +#define LAPACK_dsbgvx LAPACK_GLOBAL(dsbgvx,DSBGVX) +#define LAPACK_chbgvx LAPACK_GLOBAL(chbgvx,CHBGVX) +#define LAPACK_zhbgvx LAPACK_GLOBAL(zhbgvx,ZHBGVX) +#define LAPACK_sgges LAPACK_GLOBAL(sgges,SGGES) +#define LAPACK_dgges LAPACK_GLOBAL(dgges,DGGES) +#define LAPACK_cgges LAPACK_GLOBAL(cgges,CGGES) +#define LAPACK_zgges LAPACK_GLOBAL(zgges,ZGGES) +#define LAPACK_sggesx LAPACK_GLOBAL(sggesx,SGGESX) +#define LAPACK_dggesx LAPACK_GLOBAL(dggesx,DGGESX) +#define LAPACK_cggesx LAPACK_GLOBAL(cggesx,CGGESX) +#define LAPACK_zggesx LAPACK_GLOBAL(zggesx,ZGGESX) +#define LAPACK_sggev LAPACK_GLOBAL(sggev,SGGEV) +#define LAPACK_dggev LAPACK_GLOBAL(dggev,DGGEV) +#define LAPACK_cggev LAPACK_GLOBAL(cggev,CGGEV) +#define LAPACK_zggev LAPACK_GLOBAL(zggev,ZGGEV) +#define LAPACK_sggevx LAPACK_GLOBAL(sggevx,SGGEVX) +#define LAPACK_dggevx LAPACK_GLOBAL(dggevx,DGGEVX) +#define LAPACK_cggevx LAPACK_GLOBAL(cggevx,CGGEVX) +#define LAPACK_zggevx LAPACK_GLOBAL(zggevx,ZGGEVX) +#define LAPACK_dsfrk LAPACK_GLOBAL(dsfrk,DSFRK) +#define LAPACK_ssfrk LAPACK_GLOBAL(ssfrk,SSFRK) +#define LAPACK_zhfrk LAPACK_GLOBAL(zhfrk,ZHFRK) +#define LAPACK_chfrk LAPACK_GLOBAL(chfrk,CHFRK) +#define LAPACK_dtfsm LAPACK_GLOBAL(dtfsm,DTFSM) +#define LAPACK_stfsm LAPACK_GLOBAL(stfsm,STFSM) +#define LAPACK_ztfsm LAPACK_GLOBAL(ztfsm,ZTFSM) +#define LAPACK_ctfsm LAPACK_GLOBAL(ctfsm,CTFSM) +#define LAPACK_dtfttp LAPACK_GLOBAL(dtfttp,DTFTTP) +#define LAPACK_stfttp LAPACK_GLOBAL(stfttp,STFTTP) +#define LAPACK_ztfttp LAPACK_GLOBAL(ztfttp,ZTFTTP) +#define LAPACK_ctfttp LAPACK_GLOBAL(ctfttp,CTFTTP) +#define LAPACK_dtfttr LAPACK_GLOBAL(dtfttr,DTFTTR) +#define LAPACK_stfttr LAPACK_GLOBAL(stfttr,STFTTR) +#define LAPACK_ztfttr LAPACK_GLOBAL(ztfttr,ZTFTTR) +#define LAPACK_ctfttr LAPACK_GLOBAL(ctfttr,CTFTTR) +#define LAPACK_dtpttf LAPACK_GLOBAL(dtpttf,DTPTTF) +#define LAPACK_stpttf LAPACK_GLOBAL(stpttf,STPTTF) +#define LAPACK_ztpttf LAPACK_GLOBAL(ztpttf,ZTPTTF) +#define LAPACK_ctpttf LAPACK_GLOBAL(ctpttf,CTPTTF) +#define LAPACK_dtpttr LAPACK_GLOBAL(dtpttr,DTPTTR) +#define LAPACK_stpttr LAPACK_GLOBAL(stpttr,STPTTR) +#define LAPACK_ztpttr LAPACK_GLOBAL(ztpttr,ZTPTTR) +#define LAPACK_ctpttr LAPACK_GLOBAL(ctpttr,CTPTTR) +#define LAPACK_dtrttf LAPACK_GLOBAL(dtrttf,DTRTTF) +#define LAPACK_strttf LAPACK_GLOBAL(strttf,STRTTF) +#define LAPACK_ztrttf LAPACK_GLOBAL(ztrttf,ZTRTTF) +#define LAPACK_ctrttf LAPACK_GLOBAL(ctrttf,CTRTTF) +#define LAPACK_dtrttp LAPACK_GLOBAL(dtrttp,DTRTTP) +#define LAPACK_strttp LAPACK_GLOBAL(strttp,STRTTP) +#define LAPACK_ztrttp LAPACK_GLOBAL(ztrttp,ZTRTTP) +#define LAPACK_ctrttp LAPACK_GLOBAL(ctrttp,CTRTTP) +#define LAPACK_sgeqrfp LAPACK_GLOBAL(sgeqrfp,SGEQRFP) +#define LAPACK_dgeqrfp LAPACK_GLOBAL(dgeqrfp,DGEQRFP) +#define LAPACK_cgeqrfp LAPACK_GLOBAL(cgeqrfp,CGEQRFP) +#define LAPACK_zgeqrfp LAPACK_GLOBAL(zgeqrfp,ZGEQRFP) +#define LAPACK_clacgv LAPACK_GLOBAL(clacgv,CLACGV) +#define LAPACK_zlacgv LAPACK_GLOBAL(zlacgv,ZLACGV) +#define LAPACK_slarnv LAPACK_GLOBAL(slarnv,SLARNV) +#define LAPACK_dlarnv LAPACK_GLOBAL(dlarnv,DLARNV) +#define LAPACK_clarnv LAPACK_GLOBAL(clarnv,CLARNV) +#define LAPACK_zlarnv LAPACK_GLOBAL(zlarnv,ZLARNV) +#define LAPACK_sgeqr2 LAPACK_GLOBAL(sgeqr2,SGEQR2) +#define LAPACK_dgeqr2 LAPACK_GLOBAL(dgeqr2,DGEQR2) +#define LAPACK_cgeqr2 LAPACK_GLOBAL(cgeqr2,CGEQR2) +#define LAPACK_zgeqr2 LAPACK_GLOBAL(zgeqr2,ZGEQR2) +#define LAPACK_slacn2 LAPACK_GLOBAL(slacn2,SLACN2) +#define LAPACK_dlacn2 LAPACK_GLOBAL(dlacn2,DLACN2) +#define LAPACK_clacn2 LAPACK_GLOBAL(clacn2,CLACN2) +#define LAPACK_zlacn2 LAPACK_GLOBAL(zlacn2,ZLACN2) +#define LAPACK_slacpy LAPACK_GLOBAL(slacpy,SLACPY) +#define LAPACK_dlacpy LAPACK_GLOBAL(dlacpy,DLACPY) +#define LAPACK_clacpy LAPACK_GLOBAL(clacpy,CLACPY) +#define LAPACK_zlacpy LAPACK_GLOBAL(zlacpy,ZLACPY) +#define LAPACK_clacp2 LAPACK_GLOBAL(clacp2,CLACP2) +#define LAPACK_zlacp2 LAPACK_GLOBAL(zlacp2,ZLACP2) +#define LAPACK_sgetf2 LAPACK_GLOBAL(sgetf2,SGETF2) +#define LAPACK_dgetf2 LAPACK_GLOBAL(dgetf2,DGETF2) +#define LAPACK_cgetf2 LAPACK_GLOBAL(cgetf2,CGETF2) +#define LAPACK_zgetf2 LAPACK_GLOBAL(zgetf2,ZGETF2) +#define LAPACK_slaswp LAPACK_GLOBAL(slaswp,SLASWP) +#define LAPACK_dlaswp LAPACK_GLOBAL(dlaswp,DLASWP) +#define LAPACK_claswp LAPACK_GLOBAL(claswp,CLASWP) +#define LAPACK_zlaswp LAPACK_GLOBAL(zlaswp,ZLASWP) +#define LAPACK_slange LAPACK_GLOBAL(slange,SLANGE) +#define LAPACK_dlange LAPACK_GLOBAL(dlange,DLANGE) +#define LAPACK_clange LAPACK_GLOBAL(clange,CLANGE) +#define LAPACK_zlange LAPACK_GLOBAL(zlange,ZLANGE) +#define LAPACK_clanhe LAPACK_GLOBAL(clanhe,CLANHE) +#define LAPACK_zlanhe LAPACK_GLOBAL(zlanhe,ZLANHE) +#define LAPACK_slansy LAPACK_GLOBAL(slansy,SLANSY) +#define LAPACK_dlansy LAPACK_GLOBAL(dlansy,DLANSY) +#define LAPACK_clansy LAPACK_GLOBAL(clansy,CLANSY) +#define LAPACK_zlansy LAPACK_GLOBAL(zlansy,ZLANSY) +#define LAPACK_slantr LAPACK_GLOBAL(slantr,SLANTR) +#define LAPACK_dlantr LAPACK_GLOBAL(dlantr,DLANTR) +#define LAPACK_clantr LAPACK_GLOBAL(clantr,CLANTR) +#define LAPACK_zlantr LAPACK_GLOBAL(zlantr,ZLANTR) +#define LAPACK_slamch LAPACK_GLOBAL(slamch,SLAMCH) +#define LAPACK_dlamch LAPACK_GLOBAL(dlamch,DLAMCH) +#define LAPACK_sgelq2 LAPACK_GLOBAL(sgelq2,SGELQ2) +#define LAPACK_dgelq2 LAPACK_GLOBAL(dgelq2,DGELQ2) +#define LAPACK_cgelq2 LAPACK_GLOBAL(cgelq2,CGELQ2) +#define LAPACK_zgelq2 LAPACK_GLOBAL(zgelq2,ZGELQ2) +#define LAPACK_slarfb LAPACK_GLOBAL(slarfb,SLARFB) +#define LAPACK_dlarfb LAPACK_GLOBAL(dlarfb,DLARFB) +#define LAPACK_clarfb LAPACK_GLOBAL(clarfb,CLARFB) +#define LAPACK_zlarfb LAPACK_GLOBAL(zlarfb,ZLARFB) +#define LAPACK_slarfg LAPACK_GLOBAL(slarfg,SLARFG) +#define LAPACK_dlarfg LAPACK_GLOBAL(dlarfg,DLARFG) +#define LAPACK_clarfg LAPACK_GLOBAL(clarfg,CLARFG) +#define LAPACK_zlarfg LAPACK_GLOBAL(zlarfg,ZLARFG) +#define LAPACK_slarft LAPACK_GLOBAL(slarft,SLARFT) +#define LAPACK_dlarft LAPACK_GLOBAL(dlarft,DLARFT) +#define LAPACK_clarft LAPACK_GLOBAL(clarft,CLARFT) +#define LAPACK_zlarft LAPACK_GLOBAL(zlarft,ZLARFT) +#define LAPACK_slarfx LAPACK_GLOBAL(slarfx,SLARFX) +#define LAPACK_dlarfx LAPACK_GLOBAL(dlarfx,DLARFX) +#define LAPACK_clarfx LAPACK_GLOBAL(clarfx,CLARFX) +#define LAPACK_zlarfx LAPACK_GLOBAL(zlarfx,ZLARFX) +#define LAPACK_slatms LAPACK_GLOBAL(slatms,SLATMS) +#define LAPACK_dlatms LAPACK_GLOBAL(dlatms,DLATMS) +#define LAPACK_clatms LAPACK_GLOBAL(clatms,CLATMS) +#define LAPACK_zlatms LAPACK_GLOBAL(zlatms,ZLATMS) +#define LAPACK_slag2d LAPACK_GLOBAL(slag2d,SLAG2D) +#define LAPACK_dlag2s LAPACK_GLOBAL(dlag2s,DLAG2S) +#define LAPACK_clag2z LAPACK_GLOBAL(clag2z,CLAG2Z) +#define LAPACK_zlag2c LAPACK_GLOBAL(zlag2c,ZLAG2C) +#define LAPACK_slauum LAPACK_GLOBAL(slauum,SLAUUM) +#define LAPACK_dlauum LAPACK_GLOBAL(dlauum,DLAUUM) +#define LAPACK_clauum LAPACK_GLOBAL(clauum,CLAUUM) +#define LAPACK_zlauum LAPACK_GLOBAL(zlauum,ZLAUUM) +#define LAPACK_slagge LAPACK_GLOBAL(slagge,SLAGGE) +#define LAPACK_dlagge LAPACK_GLOBAL(dlagge,DLAGGE) +#define LAPACK_clagge LAPACK_GLOBAL(clagge,CLAGGE) +#define LAPACK_zlagge LAPACK_GLOBAL(zlagge,ZLAGGE) +#define LAPACK_slaset LAPACK_GLOBAL(slaset,SLASET) +#define LAPACK_dlaset LAPACK_GLOBAL(dlaset,DLASET) +#define LAPACK_claset LAPACK_GLOBAL(claset,CLASET) +#define LAPACK_zlaset LAPACK_GLOBAL(zlaset,ZLASET) +#define LAPACK_slasrt LAPACK_GLOBAL(slasrt,SLASRT) +#define LAPACK_dlasrt LAPACK_GLOBAL(dlasrt,DLASRT) +#define LAPACK_slagsy LAPACK_GLOBAL(slagsy,SLAGSY) +#define LAPACK_dlagsy LAPACK_GLOBAL(dlagsy,DLAGSY) +#define LAPACK_clagsy LAPACK_GLOBAL(clagsy,CLAGSY) +#define LAPACK_zlagsy LAPACK_GLOBAL(zlagsy,ZLAGSY) +#define LAPACK_claghe LAPACK_GLOBAL(claghe,CLAGHE) +#define LAPACK_zlaghe LAPACK_GLOBAL(zlaghe,ZLAGHE) +#define LAPACK_slapmr LAPACK_GLOBAL(slapmr,SLAPMR) +#define LAPACK_dlapmr LAPACK_GLOBAL(dlapmr,DLAPMR) +#define LAPACK_clapmr LAPACK_GLOBAL(clapmr,CLAPMR) +#define LAPACK_zlapmr LAPACK_GLOBAL(zlapmr,ZLAPMR) +#define LAPACK_slapy2 LAPACK_GLOBAL(slapy2,SLAPY2) +#define LAPACK_dlapy2 LAPACK_GLOBAL(dlapy2,DLAPY2) +#define LAPACK_slapy3 LAPACK_GLOBAL(slapy3,SLAPY3) +#define LAPACK_dlapy3 LAPACK_GLOBAL(dlapy3,DLAPY3) +#define LAPACK_slartgp LAPACK_GLOBAL(slartgp,SLARTGP) +#define LAPACK_dlartgp LAPACK_GLOBAL(dlartgp,DLARTGP) +#define LAPACK_slartgs LAPACK_GLOBAL(slartgs,SLARTGS) +#define LAPACK_dlartgs LAPACK_GLOBAL(dlartgs,DLARTGS) +// LAPACK 3.3.0 +#define LAPACK_cbbcsd LAPACK_GLOBAL(cbbcsd,CBBCSD) +#define LAPACK_cheswapr LAPACK_GLOBAL(cheswapr,CHESWAPR) +#define LAPACK_chetri2 LAPACK_GLOBAL(chetri2,CHETRI2) +#define LAPACK_chetri2x LAPACK_GLOBAL(chetri2x,CHETRI2X) +#define LAPACK_chetrs2 LAPACK_GLOBAL(chetrs2,CHETRS2) +#define LAPACK_csyconv LAPACK_GLOBAL(csyconv,CSYCONV) +#define LAPACK_csyswapr LAPACK_GLOBAL(csyswapr,CSYSWAPR) +#define LAPACK_csytri2 LAPACK_GLOBAL(csytri2,CSYTRI2) +#define LAPACK_csytri2x LAPACK_GLOBAL(csytri2x,CSYTRI2X) +#define LAPACK_csytrs2 LAPACK_GLOBAL(csytrs2,CSYTRS2) +#define LAPACK_cunbdb LAPACK_GLOBAL(cunbdb,CUNBDB) +#define LAPACK_cuncsd LAPACK_GLOBAL(cuncsd,CUNCSD) +#define LAPACK_dbbcsd LAPACK_GLOBAL(dbbcsd,DBBCSD) +#define LAPACK_dorbdb LAPACK_GLOBAL(dorbdb,DORBDB) +#define LAPACK_dorcsd LAPACK_GLOBAL(dorcsd,DORCSD) +#define LAPACK_dsyconv LAPACK_GLOBAL(dsyconv,DSYCONV) +#define LAPACK_dsyswapr LAPACK_GLOBAL(dsyswapr,DSYSWAPR) +#define LAPACK_dsytri2 LAPACK_GLOBAL(dsytri2,DSYTRI2) +#define LAPACK_dsytri2x LAPACK_GLOBAL(dsytri2x,DSYTRI2X) +#define LAPACK_dsytrs2 LAPACK_GLOBAL(dsytrs2,DSYTRS2) +#define LAPACK_sbbcsd LAPACK_GLOBAL(sbbcsd,SBBCSD) +#define LAPACK_sorbdb LAPACK_GLOBAL(sorbdb,SORBDB) +#define LAPACK_sorcsd LAPACK_GLOBAL(sorcsd,SORCSD) +#define LAPACK_ssyconv LAPACK_GLOBAL(ssyconv,SSYCONV) +#define LAPACK_ssyswapr LAPACK_GLOBAL(ssyswapr,SSYSWAPR) +#define LAPACK_ssytri2 LAPACK_GLOBAL(ssytri2,SSYTRI2) +#define LAPACK_ssytri2x LAPACK_GLOBAL(ssytri2x,SSYTRI2X) +#define LAPACK_ssytrs2 LAPACK_GLOBAL(ssytrs2,SSYTRS2) +#define LAPACK_zbbcsd LAPACK_GLOBAL(zbbcsd,ZBBCSD) +#define LAPACK_zheswapr LAPACK_GLOBAL(zheswapr,ZHESWAPR) +#define LAPACK_zhetri2 LAPACK_GLOBAL(zhetri2,ZHETRI2) +#define LAPACK_zhetri2x LAPACK_GLOBAL(zhetri2x,ZHETRI2X) +#define LAPACK_zhetrs2 LAPACK_GLOBAL(zhetrs2,ZHETRS2) +#define LAPACK_zsyconv LAPACK_GLOBAL(zsyconv,ZSYCONV) +#define LAPACK_zsyswapr LAPACK_GLOBAL(zsyswapr,ZSYSWAPR) +#define LAPACK_zsytri2 LAPACK_GLOBAL(zsytri2,ZSYTRI2) +#define LAPACK_zsytri2x LAPACK_GLOBAL(zsytri2x,ZSYTRI2X) +#define LAPACK_zsytrs2 LAPACK_GLOBAL(zsytrs2,ZSYTRS2) +#define LAPACK_zunbdb LAPACK_GLOBAL(zunbdb,ZUNBDB) +#define LAPACK_zuncsd LAPACK_GLOBAL(zuncsd,ZUNCSD) +// LAPACK 3.4.0 +#define LAPACK_sgemqrt LAPACK_GLOBAL(sgemqrt,SGEMQRT) +#define LAPACK_dgemqrt LAPACK_GLOBAL(dgemqrt,DGEMQRT) +#define LAPACK_cgemqrt LAPACK_GLOBAL(cgemqrt,CGEMQRT) +#define LAPACK_zgemqrt LAPACK_GLOBAL(zgemqrt,ZGEMQRT) +#define LAPACK_sgeqrt LAPACK_GLOBAL(sgeqrt,SGEQRT) +#define LAPACK_dgeqrt LAPACK_GLOBAL(dgeqrt,DGEQRT) +#define LAPACK_cgeqrt LAPACK_GLOBAL(cgeqrt,CGEQRT) +#define LAPACK_zgeqrt LAPACK_GLOBAL(zgeqrt,ZGEQRT) +#define LAPACK_sgeqrt2 LAPACK_GLOBAL(sgeqrt2,SGEQRT2) +#define LAPACK_dgeqrt2 LAPACK_GLOBAL(dgeqrt2,DGEQRT2) +#define LAPACK_cgeqrt2 LAPACK_GLOBAL(cgeqrt2,CGEQRT2) +#define LAPACK_zgeqrt2 LAPACK_GLOBAL(zgeqrt2,ZGEQRT2) +#define LAPACK_sgeqrt3 LAPACK_GLOBAL(sgeqrt3,SGEQRT3) +#define LAPACK_dgeqrt3 LAPACK_GLOBAL(dgeqrt3,DGEQRT3) +#define LAPACK_cgeqrt3 LAPACK_GLOBAL(cgeqrt3,CGEQRT3) +#define LAPACK_zgeqrt3 LAPACK_GLOBAL(zgeqrt3,ZGEQRT3) +#define LAPACK_stpmqrt LAPACK_GLOBAL(stpmqrt,STPMQRT) +#define LAPACK_dtpmqrt LAPACK_GLOBAL(dtpmqrt,DTPMQRT) +#define LAPACK_ctpmqrt LAPACK_GLOBAL(ctpmqrt,CTPMQRT) +#define LAPACK_ztpmqrt LAPACK_GLOBAL(ztpmqrt,ZTPMQRT) +#define LAPACK_dtpqrt LAPACK_GLOBAL(dtpqrt,DTPQRT) +#define LAPACK_ctpqrt LAPACK_GLOBAL(ctpqrt,CTPQRT) +#define LAPACK_ztpqrt LAPACK_GLOBAL(ztpqrt,ZTPQRT) +#define LAPACK_stpqrt2 LAPACK_GLOBAL(stpqrt2,STPQRT2) +#define LAPACK_dtpqrt2 LAPACK_GLOBAL(dtpqrt2,DTPQRT2) +#define LAPACK_ctpqrt2 LAPACK_GLOBAL(ctpqrt2,CTPQRT2) +#define LAPACK_ztpqrt2 LAPACK_GLOBAL(ztpqrt2,ZTPQRT2) +#define LAPACK_stprfb LAPACK_GLOBAL(stprfb,STPRFB) +#define LAPACK_dtprfb LAPACK_GLOBAL(dtprfb,DTPRFB) +#define LAPACK_ctprfb LAPACK_GLOBAL(ctprfb,CTPRFB) +#define LAPACK_ztprfb LAPACK_GLOBAL(ztprfb,ZTPRFB) +// LAPACK 3.X.X +#define LAPACK_ssysv_rook LAPACK_GLOBAL(ssysv_rook,SSYSV_ROOK) +#define LAPACK_dsysv_rook LAPACK_GLOBAL(dsysv_rook,DSYSV_ROOK) +#define LAPACK_csysv_rook LAPACK_GLOBAL(csysv_rook,CSYSV_ROOK) +#define LAPACK_zsysv_rook LAPACK_GLOBAL(zsysv_rook,ZSYSV_ROOK) +#define LAPACK_csyr LAPACK_GLOBAL(csyr,CSYR) +#define LAPACK_zsyr LAPACK_GLOBAL(zsyr,ZSYR) +#define LAPACK_ilaver LAPACK_GLOBAL(ilaver,ILAVER) + +void LAPACK_sgetrf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgetrf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgetrf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgetrf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, double* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_complex_float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_complex_double* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgttrf( lapack_int* n, float* dl, float* d, float* du, float* du2, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgttrf( lapack_int* n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgttrf( lapack_int* n, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_zgttrf( lapack_int* n, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_spotrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dpotrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_cpotrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zpotrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dpstrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int* piv, lapack_int* rank, double* tol, + double* work, lapack_int *info ); +void LAPACK_spstrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int* piv, lapack_int* rank, float* tol, float* work, + lapack_int *info ); +void LAPACK_zpstrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* piv, lapack_int* rank, + double* tol, double* work, lapack_int *info ); +void LAPACK_cpstrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* piv, lapack_int* rank, + float* tol, float* work, lapack_int *info ); +void LAPACK_dpftrf( char* transr, char* uplo, lapack_int* n, double* a, + lapack_int *info ); +void LAPACK_spftrf( char* transr, char* uplo, lapack_int* n, float* a, + lapack_int *info ); +void LAPACK_zpftrf( char* transr, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_cpftrf( char* transr, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_spptrf( char* uplo, lapack_int* n, float* ap, lapack_int *info ); +void LAPACK_dpptrf( char* uplo, lapack_int* n, double* ap, lapack_int *info ); +void LAPACK_cpptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_zpptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_spbtrf( char* uplo, lapack_int* n, lapack_int* kd, float* ab, + lapack_int* ldab, lapack_int *info ); +void LAPACK_dpbtrf( char* uplo, lapack_int* n, lapack_int* kd, double* ab, + lapack_int* ldab, lapack_int *info ); +void LAPACK_cpbtrf( char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, + lapack_int *info ); +void LAPACK_zpbtrf( char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, + lapack_int *info ); +void LAPACK_spttrf( lapack_int* n, float* d, float* e, lapack_int *info ); +void LAPACK_dpttrf( lapack_int* n, double* d, double* e, lapack_int *info ); +void LAPACK_cpttrf( lapack_int* n, float* d, lapack_complex_float* e, + lapack_int *info ); +void LAPACK_zpttrf( lapack_int* n, double* d, lapack_complex_double* e, + lapack_int *info ); +void LAPACK_ssytrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsytrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csytrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zsytrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chetrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zhetrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssptrf( char* uplo, lapack_int* n, float* ap, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_dsptrf( char* uplo, lapack_int* n, double* ap, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_csptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zsptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_chptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zhptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const lapack_int* ipiv, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const float* ab, lapack_int* ldab, + const lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const double* ab, lapack_int* ldab, + const lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_float* ab, + lapack_int* ldab, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_double* ab, + lapack_int* ldab, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + const float* du2, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + const double* du2, const lapack_int* ipiv, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spotrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* a, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_spptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_spbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const float* ab, lapack_int* ldab, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const double* ab, lapack_int* ldab, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spttrs( lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpttrs( lapack_int* n, lapack_int* nrhs, const double* d, + const double* e, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpttrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zpttrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ssytrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_csytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zsytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_chetrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zhetrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_ssptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const lapack_int* ipiv, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_csptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zsptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zhptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_strtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* a, lapack_int* lda, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dtrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* a, lapack_int* lda, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_ctrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_stptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* ap, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dtptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* ap, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_ctptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_stbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const float* ab, + lapack_int* ldab, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dtbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const double* ab, + lapack_int* ldab, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ctbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgecon( char* norm, lapack_int* n, const float* a, lapack_int* lda, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgecon( char* norm, lapack_int* n, const double* a, lapack_int* lda, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgecon( char* norm, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgecon( char* norm, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const float* ab, lapack_int* ldab, const lapack_int* ipiv, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const double* ab, lapack_int* ldab, const lapack_int* ipiv, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgtcon( char* norm, lapack_int* n, const float* dl, const float* d, + const float* du, const float* du2, const lapack_int* ipiv, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgtcon( char* norm, lapack_int* n, const double* dl, + const double* d, const double* du, const double* du2, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgtcon( char* norm, lapack_int* n, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, const lapack_int* ipiv, + float* anorm, float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zgtcon( char* norm, lapack_int* n, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, const lapack_int* ipiv, + double* anorm, double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_spocon( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpocon( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cpocon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpocon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sppcon( char* uplo, lapack_int* n, const float* ap, float* anorm, + float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dppcon( char* uplo, lapack_int* n, const double* ap, double* anorm, + double* rcond, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cppcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + float* anorm, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zppcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + double* anorm, double* rcond, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_spbcon( char* uplo, lapack_int* n, lapack_int* kd, const float* ab, + lapack_int* ldab, float* anorm, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dpbcon( char* uplo, lapack_int* n, lapack_int* kd, const double* ab, + lapack_int* ldab, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cpbcon( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_float* ab, lapack_int* ldab, + float* anorm, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zpbcon( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_double* ab, lapack_int* ldab, + double* anorm, double* rcond, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sptcon( lapack_int* n, const float* d, const float* e, float* anorm, + float* rcond, float* work, lapack_int *info ); +void LAPACK_dptcon( lapack_int* n, const double* d, const double* e, + double* anorm, double* rcond, double* work, + lapack_int *info ); +void LAPACK_cptcon( lapack_int* n, const float* d, + const lapack_complex_float* e, float* anorm, float* rcond, + float* work, lapack_int *info ); +void LAPACK_zptcon( lapack_int* n, const double* d, + const lapack_complex_double* e, double* anorm, + double* rcond, double* work, lapack_int *info ); +void LAPACK_ssycon( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + const lapack_int* ipiv, float* anorm, float* rcond, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dsycon( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_csycon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, float* anorm, + float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zsycon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, double* anorm, + double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_checon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, float* anorm, + float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zhecon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, double* anorm, + double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_sspcon( char* uplo, lapack_int* n, const float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dspcon( char* uplo, lapack_int* n, const double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cspcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zspcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_chpcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhpcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_strcon( char* norm, char* uplo, char* diag, lapack_int* n, + const float* a, lapack_int* lda, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const double* a, lapack_int* lda, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + float* rcond, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + double* rcond, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const float* ap, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const double* ap, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_float* ap, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_double* ap, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const float* ab, lapack_int* ldab, + float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const double* ab, lapack_int* ldab, + double* rcond, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const lapack_complex_float* ab, + lapack_int* ldab, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_ztbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const lapack_complex_double* ab, + lapack_int* ldab, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* r, const double* c, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* r, const float* c, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const float* ab, lapack_int* ldab, + const float* afb, lapack_int* ldafb, const lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const double* ab, lapack_int* ldab, + const double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_float* ab, + lapack_int* ldab, const lapack_complex_float* afb, + lapack_int* ldafb, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_double* ab, + lapack_int* ldab, const lapack_complex_double* afb, + lapack_int* ldafb, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_dgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, const double* ab, + lapack_int* ldab, const double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* r, const double* c, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, const float* ab, + lapack_int* ldab, const float* afb, lapack_int* ldafb, + const lapack_int* ipiv, const float* r, const float* c, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* r, const double* c, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* afb, lapack_int* ldafb, + const lapack_int* ipiv, const float* r, const float* c, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + const float* dlf, const float* df, const float* duf, + const float* du2, const lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + const double* dlf, const double* df, const double* duf, + const double* du2, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sporfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const float* af, lapack_int* ldaf, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_dporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const double* s, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const float* s, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const double* s, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const float* s, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_spprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const float* afp, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const double* afp, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const float* ab, lapack_int* ldab, const float* afb, + lapack_int* ldafb, const float* b, lapack_int* ldb, + float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const double* ab, lapack_int* ldab, const double* afb, + lapack_int* ldafb, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* afb, lapack_int* ldafb, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* afb, lapack_int* ldafb, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sptrfs( lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, const float* df, const float* ef, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int *info ); +void LAPACK_dptrfs( lapack_int* n, lapack_int* nrhs, const double* d, + const double* e, const double* df, const double* ef, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int *info ); +void LAPACK_cptrfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zptrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, + const double* df, const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* b, lapack_int* ldb, + float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dsyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_csyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zsyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dsyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* s, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_ssyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* s, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zsyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_csyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_cherfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zherfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_zherfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cherfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ssprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const float* afp, const lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dsprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const double* afp, const lapack_int* ipiv, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_csprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zsprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_strrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, const float* x, + lapack_int* ldx, float* ferr, float* berr, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, const double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, const lapack_complex_float* x, + lapack_int* ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, const lapack_complex_double* x, + lapack_int* ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* ap, const float* b, + lapack_int* ldb, const float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* ap, const double* b, + lapack_int* ldb, const double* x, lapack_int* ldx, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int* ldb, + const lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int* ldb, + const lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_stbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const float* ab, + lapack_int* ldab, const float* b, lapack_int* ldb, + const float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dtbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const double* ab, + lapack_int* ldab, const double* b, lapack_int* ldb, + const double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* b, lapack_int* ldb, + const lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* b, lapack_int* ldb, + const lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sgetri( lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgetri( lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgetri( lapack_int* n, lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgetri( lapack_int* n, lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_spotri( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dpotri( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_cpotri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zpotri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dpftri( char* transr, char* uplo, lapack_int* n, double* a, + lapack_int *info ); +void LAPACK_spftri( char* transr, char* uplo, lapack_int* n, float* a, + lapack_int *info ); +void LAPACK_zpftri( char* transr, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_cpftri( char* transr, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_spptri( char* uplo, lapack_int* n, float* ap, lapack_int *info ); +void LAPACK_dpptri( char* uplo, lapack_int* n, double* ap, lapack_int *info ); +void LAPACK_cpptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_zpptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ssytri( char* uplo, lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, lapack_int *info ); +void LAPACK_dsytri( char* uplo, lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, lapack_int *info ); +void LAPACK_csytri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zsytri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_chetri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhetri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_ssptri( char* uplo, lapack_int* n, float* ap, + const lapack_int* ipiv, float* work, lapack_int *info ); +void LAPACK_dsptri( char* uplo, lapack_int* n, double* ap, + const lapack_int* ipiv, double* work, lapack_int *info ); +void LAPACK_csptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zsptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_chptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zhptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_strtri( char* uplo, char* diag, lapack_int* n, float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dtrtri( char* uplo, char* diag, lapack_int* n, double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ctrtri( char* uplo, char* diag, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_ztrtri( char* uplo, char* diag, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dtftri( char* transr, char* uplo, char* diag, lapack_int* n, + double* a, lapack_int *info ); +void LAPACK_stftri( char* transr, char* uplo, char* diag, lapack_int* n, + float* a, lapack_int *info ); +void LAPACK_ztftri( char* transr, char* uplo, char* diag, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_ctftri( char* transr, char* uplo, char* diag, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_stptri( char* uplo, char* diag, lapack_int* n, float* ap, + lapack_int *info ); +void LAPACK_dtptri( char* uplo, char* diag, lapack_int* n, double* ap, + lapack_int *info ); +void LAPACK_ctptri( char* uplo, char* diag, lapack_int* n, + lapack_complex_float* ap, lapack_int *info ); +void LAPACK_ztptri( char* uplo, char* diag, lapack_int* n, + lapack_complex_double* ap, lapack_int *info ); +void LAPACK_sgeequ( lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_dgeequ( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_cgeequ( lapack_int* m, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgeequ( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* r, + double* c, double* rowcnd, double* colcnd, double* amax, + lapack_int *info ); +void LAPACK_dgeequb( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_sgeequb( lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgeequb( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* r, + double* c, double* rowcnd, double* colcnd, double* amax, + lapack_int *info ); +void LAPACK_cgeequb( lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* r, + float* c, float* rowcnd, float* colcnd, float* amax, + lapack_int *info ); +void LAPACK_sgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* ab, lapack_int* ldab, float* r, + float* c, float* rowcnd, float* colcnd, float* amax, + lapack_int *info ); +void LAPACK_dgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* ab, lapack_int* ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax, lapack_int *info ); +void LAPACK_cgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_float* ab, + lapack_int* ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_double* ab, + lapack_int* ldab, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_dgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* ab, lapack_int* ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax, lapack_int *info ); +void LAPACK_sgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* ab, lapack_int* ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax, lapack_int *info ); +void LAPACK_zgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_double* ab, + lapack_int* ldab, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_cgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_float* ab, + lapack_int* ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_spoequ( lapack_int* n, const float* a, lapack_int* lda, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_dpoequ( lapack_int* n, const double* a, lapack_int* lda, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_cpoequ( lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_zpoequ( lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_dpoequb( lapack_int* n, const double* a, lapack_int* lda, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_spoequb( lapack_int* n, const float* a, lapack_int* lda, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_zpoequb( lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_cpoequb( lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_sppequ( char* uplo, lapack_int* n, const float* ap, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_dppequ( char* uplo, lapack_int* n, const double* ap, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_cppequ( char* uplo, lapack_int* n, const lapack_complex_float* ap, + float* s, float* scond, float* amax, lapack_int *info ); +void LAPACK_zppequ( char* uplo, lapack_int* n, const lapack_complex_double* ap, + double* s, double* scond, double* amax, lapack_int *info ); +void LAPACK_spbequ( char* uplo, lapack_int* n, lapack_int* kd, const float* ab, + lapack_int* ldab, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_dpbequ( char* uplo, lapack_int* n, lapack_int* kd, const double* ab, + lapack_int* ldab, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_cpbequ( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_float* ab, lapack_int* ldab, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_zpbequ( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_double* ab, lapack_int* ldab, + double* s, double* scond, double* amax, lapack_int *info ); +void LAPACK_dsyequb( char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* s, double* scond, double* amax, + double* work, lapack_int *info ); +void LAPACK_ssyequb( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* s, float* scond, float* amax, float* work, + lapack_int *info ); +void LAPACK_zsyequb( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_csyequb( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zheequb( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_cheequb( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_sgesv( lapack_int* n, lapack_int* nrhs, float* a, lapack_int* lda, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgesv( lapack_int* n, lapack_int* nrhs, double* a, lapack_int* lda, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsgesv( lapack_int* n, lapack_int* nrhs, double* a, lapack_int* lda, + lapack_int* ipiv, double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* work, float* swork, + lapack_int* iter, lapack_int *info ); +void LAPACK_zcgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, lapack_complex_float* swork, + double* rwork, lapack_int* iter, lapack_int *info ); +void LAPACK_sgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, float* ab, lapack_int* ldab, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, double* ab, lapack_int* ldab, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, lapack_complex_float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, float* ab, + lapack_int* ldab, float* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, float* r, float* c, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, double* ab, + lapack_int* ldab, double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, double* ab, + lapack_int* ldab, double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, float* ab, + lapack_int* ldab, float* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgtsv( lapack_int* n, lapack_int* nrhs, float* dl, float* d, + float* du, float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dgtsv( lapack_int* n, lapack_int* nrhs, double* dl, double* d, + double* du, double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cgtsv( lapack_int* n, lapack_int* nrhs, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zgtsv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + float* dlf, float* df, float* duf, float* du2, + lapack_int* ipiv, const float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + double* dlf, double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, lapack_complex_float* dlf, + lapack_complex_float* df, lapack_complex_float* duf, + lapack_complex_float* du2, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, lapack_complex_double* dlf, + lapack_complex_double* df, lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sposv( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dposv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dsposv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* work, float* swork, + lapack_int* iter, lapack_int *info ); +void LAPACK_zcposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, lapack_complex_float* swork, + double* rwork, lapack_int* iter, lapack_int *info ); +void LAPACK_sposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + char* equed, float* s, float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + char* equed, double* s, double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, char* equed, + float* s, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, char* equed, + double* s, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + char* equed, double* s, double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + char* equed, float* s, float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, char* equed, + double* s, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, char* equed, + float* s, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sppsv( char* uplo, lapack_int* n, lapack_int* nrhs, float* ap, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dppsv( char* uplo, lapack_int* n, lapack_int* nrhs, double* ap, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cppsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zppsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* ap, float* afp, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* ap, double* afp, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_complex_float* afp, + char* equed, float* s, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_complex_double* afp, + char* equed, double* s, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + float* ab, lapack_int* ldab, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + double* ab, lapack_int* ldab, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, float* ab, lapack_int* ldab, float* afb, + lapack_int* ldafb, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, double* ab, lapack_int* ldab, double* afb, + lapack_int* ldafb, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* afb, + lapack_int* ldafb, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sptsv( lapack_int* n, lapack_int* nrhs, float* d, float* e, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dptsv( lapack_int* n, lapack_int* nrhs, double* d, double* e, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cptsv( lapack_int* n, lapack_int* nrhs, float* d, + lapack_complex_float* e, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zptsv( lapack_int* n, lapack_int* nrhs, double* d, + lapack_complex_double* e, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sptsvx( char* fact, lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, float* df, float* ef, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int *info ); +void LAPACK_dptsvx( char* fact, lapack_int* n, lapack_int* nrhs, + const double* d, const double* e, double* df, double* ef, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* ferr, double* berr, + double* work, lapack_int *info ); +void LAPACK_cptsvx( char* fact, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zptsvx( char* fact, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, double* df, + lapack_complex_double* ef, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssysv( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, lapack_int* ipiv, float* b, lapack_int* ldb, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dsysv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, lapack_int* ipiv, double* b, + lapack_int* ldb, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csysv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zsysv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, float* af, + lapack_int* ldaf, lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dsysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, double* af, + lapack_int* ldaf, lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_csysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zsysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_dsysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ssysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zsysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_csysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_chesv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zhesv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chesvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhesvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_zhesvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chesvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sspsv( char* uplo, lapack_int* n, lapack_int* nrhs, float* ap, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dspsv( char* uplo, lapack_int* n, lapack_int* nrhs, double* ap, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cspsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zspsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, float* afp, lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, double* afp, lapack_int* ipiv, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* afp, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* afp, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chpsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zhpsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chpsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* afp, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhpsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* afp, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgeqrf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqrf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqrf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqrf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgeqpf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* jpvt, float* tau, float* work, + lapack_int *info ); +void LAPACK_dgeqpf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* jpvt, double* tau, double* work, + lapack_int *info ); +void LAPACK_cgeqpf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_float* tau, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgeqpf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_double* tau, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sgeqp3( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* jpvt, float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgeqp3( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* jpvt, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgeqp3( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgeqp3( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sorgqr( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgqr( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungqr( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungqr( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgelqf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgelqf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgelqf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgelqf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorglq( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorglq( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunglq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunglq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgeqlf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqlf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqlf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqlf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorgql( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgql( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungql( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungql( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunmql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgerqf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgerqf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgerqf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgerqf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorgrq( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgrq( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungrq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungrq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunmrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_stzrzf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dtzrzf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ctzrzf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ztzrzf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sggqrf( lapack_int* n, lapack_int* m, lapack_int* p, float* a, + lapack_int* lda, float* taua, float* b, lapack_int* ldb, + float* taub, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggqrf( lapack_int* n, lapack_int* m, lapack_int* p, double* a, + lapack_int* lda, double* taua, double* b, lapack_int* ldb, + double* taub, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggqrf( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* taua, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* taub, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zggqrf( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* taua, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* taub, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sggrqf( lapack_int* m, lapack_int* p, lapack_int* n, float* a, + lapack_int* lda, float* taua, float* b, lapack_int* ldb, + float* taub, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggrqf( lapack_int* m, lapack_int* p, lapack_int* n, double* a, + lapack_int* lda, double* taua, double* b, lapack_int* ldb, + double* taub, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggrqf( lapack_int* m, lapack_int* p, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* taua, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* taub, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zggrqf( lapack_int* m, lapack_int* p, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* taua, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* taub, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgebrd( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* d, float* e, float* tauq, float* taup, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgebrd( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* d, double* e, double* tauq, double* taup, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgebrd( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, float* d, float* e, + lapack_complex_float* tauq, lapack_complex_float* taup, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgebrd( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, double* d, double* e, + lapack_complex_double* tauq, lapack_complex_double* taup, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, float* ab, lapack_int* ldab, + float* d, float* e, float* q, lapack_int* ldq, float* pt, + lapack_int* ldpt, float* c, lapack_int* ldc, float* work, + lapack_int *info ); +void LAPACK_dgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, double* ab, + lapack_int* ldab, double* d, double* e, double* q, + lapack_int* ldq, double* pt, lapack_int* ldpt, double* c, + lapack_int* ldc, double* work, lapack_int *info ); +void LAPACK_cgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, lapack_complex_float* ab, + lapack_int* ldab, float* d, float* e, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* pt, lapack_int* ldpt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, lapack_complex_double* ab, + lapack_int* ldab, double* d, double* e, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* pt, lapack_int* ldpt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sorgbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + float* a, lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + double* a, lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cungbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, float* d, float* e, + float* vt, lapack_int* ldvt, float* u, lapack_int* ldu, + float* c, lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, double* d, double* e, + double* vt, lapack_int* ldvt, double* u, lapack_int* ldu, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_cbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, float* d, float* e, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* c, lapack_int* ldc, float* work, + lapack_int *info ); +void LAPACK_zbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, double* d, double* e, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_sbdsdc( char* uplo, char* compq, lapack_int* n, float* d, float* e, + float* u, lapack_int* ldu, float* vt, lapack_int* ldvt, + float* q, lapack_int* iq, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dbdsdc( char* uplo, char* compq, lapack_int* n, double* d, + double* e, double* u, lapack_int* ldu, double* vt, + lapack_int* ldvt, double* q, lapack_int* iq, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ssytrd( char* uplo, lapack_int* n, float* a, lapack_int* lda, + float* d, float* e, float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dsytrd( char* uplo, lapack_int* n, double* a, lapack_int* lda, + double* d, double* e, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sorgtr( char* uplo, lapack_int* n, float* a, lapack_int* lda, + const float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dorgtr( char* uplo, lapack_int* n, double* a, lapack_int* lda, + const double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_chetrd( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, float* d, float* e, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zhetrd( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, double* d, double* e, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungtr( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zungtr( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssptrd( char* uplo, lapack_int* n, float* ap, float* d, float* e, + float* tau, lapack_int *info ); +void LAPACK_dsptrd( char* uplo, lapack_int* n, double* ap, double* d, double* e, + double* tau, lapack_int *info ); +void LAPACK_sopgtr( char* uplo, lapack_int* n, const float* ap, + const float* tau, float* q, lapack_int* ldq, float* work, + lapack_int *info ); +void LAPACK_dopgtr( char* uplo, lapack_int* n, const double* ap, + const double* tau, double* q, lapack_int* ldq, double* work, + lapack_int *info ); +void LAPACK_sopmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const float* ap, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dopmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const double* ap, const double* tau, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_chptrd( char* uplo, lapack_int* n, lapack_complex_float* ap, + float* d, float* e, lapack_complex_float* tau, + lapack_int *info ); +void LAPACK_zhptrd( char* uplo, lapack_int* n, lapack_complex_double* ap, + double* d, double* e, lapack_complex_double* tau, + lapack_int *info ); +void LAPACK_cupgtr( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_complex_float* tau, lapack_complex_float* q, + lapack_int* ldq, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zupgtr( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_complex_double* tau, lapack_complex_double* q, + lapack_int* ldq, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_cupmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_float* ap, + const lapack_complex_float* tau, lapack_complex_float* c, + lapack_int* ldc, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zupmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_double* ap, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_ssbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* d, float* e, float* q, + lapack_int* ldq, float* work, lapack_int *info ); +void LAPACK_dsbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* d, double* e, + double* q, lapack_int* ldq, double* work, + lapack_int *info ); +void LAPACK_chbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* d, + float* e, lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* d, + double* e, lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_ssterf( lapack_int* n, float* d, float* e, lapack_int *info ); +void LAPACK_dsterf( lapack_int* n, double* d, double* e, lapack_int *info ); +void LAPACK_ssteqr( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dsteqr( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_csteqr( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, float* work, + lapack_int *info ); +void LAPACK_zsteqr( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, double* work, + lapack_int *info ); +void LAPACK_sstemr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + lapack_int* m, float* w, float* z, lapack_int* ldz, + lapack_int* nzc, lapack_int* isuppz, lapack_logical* tryrac, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dstemr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, lapack_int* m, double* w, double* z, + lapack_int* ldz, lapack_int* nzc, lapack_int* isuppz, + lapack_logical* tryrac, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cstemr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_int* nzc, lapack_int* isuppz, + lapack_logical* tryrac, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zstemr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, lapack_int* nzc, + lapack_int* isuppz, lapack_logical* tryrac, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_sstedc( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dstedc( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cstedc( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zstedc( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sstegr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, lapack_int* isuppz, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_dstegr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, lapack_int* isuppz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_cstegr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_int* isuppz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zstegr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_int* isuppz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_spteqr( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dpteqr( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_cpteqr( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, float* work, + lapack_int *info ); +void LAPACK_zpteqr( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, double* work, + lapack_int *info ); +void LAPACK_sstebz( char* range, char* order, lapack_int* n, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + const float* d, const float* e, lapack_int* m, + lapack_int* nsplit, float* w, lapack_int* iblock, + lapack_int* isplit, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dstebz( char* range, char* order, lapack_int* n, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + const double* d, const double* e, lapack_int* m, + lapack_int* nsplit, double* w, lapack_int* iblock, + lapack_int* isplit, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_sstein( lapack_int* n, const float* d, const float* e, + lapack_int* m, const float* w, const lapack_int* iblock, + const lapack_int* isplit, float* z, lapack_int* ldz, + float* work, lapack_int* iwork, lapack_int* ifailv, + lapack_int *info ); +void LAPACK_dstein( lapack_int* n, const double* d, const double* e, + lapack_int* m, const double* w, const lapack_int* iblock, + const lapack_int* isplit, double* z, lapack_int* ldz, + double* work, lapack_int* iwork, lapack_int* ifailv, + lapack_int *info ); +void LAPACK_cstein( lapack_int* n, const float* d, const float* e, + lapack_int* m, const float* w, const lapack_int* iblock, + const lapack_int* isplit, lapack_complex_float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifailv, lapack_int *info ); +void LAPACK_zstein( lapack_int* n, const double* d, const double* e, + lapack_int* m, const double* w, const lapack_int* iblock, + const lapack_int* isplit, lapack_complex_double* z, + lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifailv, lapack_int *info ); +void LAPACK_sdisna( char* job, lapack_int* m, lapack_int* n, const float* d, + float* sep, lapack_int *info ); +void LAPACK_ddisna( char* job, lapack_int* m, lapack_int* n, const double* d, + double* sep, lapack_int *info ); +void LAPACK_ssygst( lapack_int* itype, char* uplo, lapack_int* n, float* a, + lapack_int* lda, const float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dsygst( lapack_int* itype, char* uplo, lapack_int* n, double* a, + lapack_int* lda, const double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chegst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zhegst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sspgst( lapack_int* itype, char* uplo, lapack_int* n, float* ap, + const float* bp, lapack_int *info ); +void LAPACK_dspgst( lapack_int* itype, char* uplo, lapack_int* n, double* ap, + const double* bp, lapack_int *info ); +void LAPACK_chpgst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_float* ap, const lapack_complex_float* bp, + lapack_int *info ); +void LAPACK_zhpgst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_double* ap, const lapack_complex_double* bp, + lapack_int *info ); +void LAPACK_ssbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, + const float* bb, lapack_int* ldbb, float* x, + lapack_int* ldx, float* work, lapack_int *info ); +void LAPACK_dsbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, + const double* bb, lapack_int* ldbb, double* x, + lapack_int* ldx, double* work, lapack_int *info ); +void LAPACK_chbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* bb, lapack_int* ldbb, + lapack_complex_float* x, lapack_int* ldx, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* bb, lapack_int* ldbb, + lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbstf( char* uplo, lapack_int* n, lapack_int* kb, float* bb, + lapack_int* ldbb, lapack_int *info ); +void LAPACK_dpbstf( char* uplo, lapack_int* n, lapack_int* kb, double* bb, + lapack_int* ldbb, lapack_int *info ); +void LAPACK_cpbstf( char* uplo, lapack_int* n, lapack_int* kb, + lapack_complex_float* bb, lapack_int* ldbb, + lapack_int *info ); +void LAPACK_zpbstf( char* uplo, lapack_int* n, lapack_int* kb, + lapack_complex_double* bb, lapack_int* ldbb, + lapack_int *info ); +void LAPACK_sgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, float* a, + lapack_int* lda, float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, double* a, + lapack_int* lda, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sorghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* c, + lapack_int* ldc, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunmhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sgebal( char* job, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ilo, lapack_int* ihi, float* scale, + lapack_int *info ); +void LAPACK_dgebal( char* job, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ilo, lapack_int* ihi, double* scale, + lapack_int *info ); +void LAPACK_cgebal( char* job, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ilo, lapack_int* ihi, + float* scale, lapack_int *info ); +void LAPACK_zgebal( char* job, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ilo, lapack_int* ihi, + double* scale, lapack_int *info ); +void LAPACK_sgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* scale, lapack_int* m, + float* v, lapack_int* ldv, lapack_int *info ); +void LAPACK_dgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* scale, lapack_int* m, + double* v, lapack_int* ldv, lapack_int *info ); +void LAPACK_cgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* scale, lapack_int* m, + lapack_complex_float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_zgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* scale, lapack_int* m, + lapack_complex_double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_shseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, float* h, lapack_int* ldh, float* wr, + float* wi, float* z, lapack_int* ldz, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dhseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, double* h, lapack_int* ldh, double* wr, + double* wi, double* z, lapack_int* ldz, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_chseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_float* h, lapack_int* ldh, + lapack_complex_float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zhseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_double* h, lapack_int* ldh, + lapack_complex_double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_shsein( char* job, char* eigsrc, char* initv, + lapack_logical* select, lapack_int* n, const float* h, + lapack_int* ldh, float* wr, const float* wi, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_dhsein( char* job, char* eigsrc, char* initv, + lapack_logical* select, lapack_int* n, const double* h, + lapack_int* ldh, double* wr, const double* wi, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_chsein( char* job, char* eigsrc, char* initv, + const lapack_logical* select, lapack_int* n, + const lapack_complex_float* h, lapack_int* ldh, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_float* work, float* rwork, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_zhsein( char* job, char* eigsrc, char* initv, + const lapack_logical* select, lapack_int* n, + const lapack_complex_double* h, lapack_int* ldh, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_strevc( char* side, char* howmny, lapack_logical* select, + lapack_int* n, const float* t, lapack_int* ldt, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int *info ); +void LAPACK_dtrevc( char* side, char* howmny, lapack_logical* select, + lapack_int* n, const double* t, lapack_int* ldt, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int *info ); +void LAPACK_ctrevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_strsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const float* t, lapack_int* ldt, + const float* vl, lapack_int* ldvl, const float* vr, + lapack_int* ldvr, float* s, float* sep, lapack_int* mm, + lapack_int* m, float* work, lapack_int* ldwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const double* t, lapack_int* ldt, + const double* vl, lapack_int* ldvl, const double* vr, + lapack_int* ldvr, double* s, double* sep, lapack_int* mm, + lapack_int* m, double* work, lapack_int* ldwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* t, + lapack_int* ldt, const lapack_complex_float* vl, + lapack_int* ldvl, const lapack_complex_float* vr, + lapack_int* ldvr, float* s, float* sep, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, + lapack_int* ldwork, float* rwork, lapack_int *info ); +void LAPACK_ztrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* t, + lapack_int* ldt, const lapack_complex_double* vl, + lapack_int* ldvl, const lapack_complex_double* vr, + lapack_int* ldvr, double* s, double* sep, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, + lapack_int* ldwork, double* rwork, lapack_int *info ); +void LAPACK_strexc( char* compq, lapack_int* n, float* t, lapack_int* ldt, + float* q, lapack_int* ldq, lapack_int* ifst, + lapack_int* ilst, float* work, lapack_int *info ); +void LAPACK_dtrexc( char* compq, lapack_int* n, double* t, lapack_int* ldt, + double* q, lapack_int* ldq, lapack_int* ifst, + lapack_int* ilst, double* work, lapack_int *info ); +void LAPACK_ctrexc( char* compq, lapack_int* n, lapack_complex_float* t, + lapack_int* ldt, lapack_complex_float* q, lapack_int* ldq, + lapack_int* ifst, lapack_int* ilst, lapack_int *info ); +void LAPACK_ztrexc( char* compq, lapack_int* n, lapack_complex_double* t, + lapack_int* ldt, lapack_complex_double* q, lapack_int* ldq, + lapack_int* ifst, lapack_int* ilst, lapack_int *info ); +void LAPACK_strsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, float* t, lapack_int* ldt, float* q, + lapack_int* ldq, float* wr, float* wi, lapack_int* m, + float* s, float* sep, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dtrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, double* t, lapack_int* ldt, double* q, + lapack_int* ldq, double* wr, double* wi, lapack_int* m, + double* s, double* sep, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ctrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* w, lapack_int* m, float* s, + float* sep, lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ztrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* w, lapack_int* m, double* s, + double* sep, lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_strsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, float* c, lapack_int* ldc, + float* scale, lapack_int *info ); +void LAPACK_dtrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, double* c, + lapack_int* ldc, double* scale, lapack_int *info ); +void LAPACK_ctrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* c, lapack_int* ldc, + float* scale, lapack_int *info ); +void LAPACK_ztrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* c, lapack_int* ldc, + double* scale, lapack_int *info ); +void LAPACK_sgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* q, lapack_int* ldq, float* z, + lapack_int* ldz, lapack_int *info ); +void LAPACK_dgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* q, lapack_int* ldq, double* z, + lapack_int* ldz, lapack_int *info ); +void LAPACK_cgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, + lapack_int *info ); +void LAPACK_zgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, + lapack_int *info ); +void LAPACK_sggbal( char* job, lapack_int* n, float* a, lapack_int* lda, + float* b, lapack_int* ldb, lapack_int* ilo, lapack_int* ihi, + float* lscale, float* rscale, float* work, + lapack_int *info ); +void LAPACK_dggbal( char* job, lapack_int* n, double* a, lapack_int* lda, + double* b, lapack_int* ldb, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* work, lapack_int *info ); +void LAPACK_cggbal( char* job, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* work, lapack_int *info ); +void LAPACK_zggbal( char* job, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* work, lapack_int *info ); +void LAPACK_sggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* lscale, const float* rscale, + lapack_int* m, float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_dggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* lscale, const double* rscale, + lapack_int* m, double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_cggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* lscale, const float* rscale, + lapack_int* m, lapack_complex_float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_zggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* lscale, const double* rscale, + lapack_int* m, lapack_complex_double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_shgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, float* h, lapack_int* ldh, + float* t, lapack_int* ldt, float* alphar, float* alphai, + float* beta, float* q, lapack_int* ldq, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dhgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, double* h, + lapack_int* ldh, double* t, lapack_int* ldt, double* alphar, + double* alphai, double* beta, double* q, lapack_int* ldq, + double* z, lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, lapack_complex_float* h, + lapack_int* ldh, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, lapack_complex_double* h, + lapack_int* ldh, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_stgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const float* s, lapack_int* lds, + const float* p, lapack_int* ldp, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int *info ); +void LAPACK_dtgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const double* s, lapack_int* lds, + const double* p, lapack_int* ldp, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int *info ); +void LAPACK_ctgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* s, + lapack_int* lds, const lapack_complex_float* p, + lapack_int* ldp, lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* s, + lapack_int* lds, const lapack_complex_double* p, + lapack_int* ldp, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* q, lapack_int* ldq, float* z, lapack_int* ldz, + lapack_int* ifst, lapack_int* ilst, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dtgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* q, lapack_int* ldq, double* z, lapack_int* ldz, + lapack_int* ifst, lapack_int* ilst, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_ctgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, lapack_int* ifst, + lapack_int* ilst, lapack_int *info ); +void LAPACK_ztgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, lapack_int* ifst, + lapack_int* ilst, lapack_int *info ); +void LAPACK_stgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* alphar, float* alphai, float* beta, + float* q, lapack_int* ldq, float* z, lapack_int* ldz, + lapack_int* m, float* pl, float* pr, float* dif, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dtgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* alphar, double* alphai, + double* beta, double* q, lapack_int* ldq, double* z, + lapack_int* ldz, lapack_int* m, double* pl, double* pr, + double* dif, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ctgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, lapack_int* m, + float* pl, float* pr, float* dif, + lapack_complex_float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ztgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, lapack_int* m, + double* pl, double* pr, double* dif, + lapack_complex_double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_stgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const float* a, lapack_int* lda, const float* b, + lapack_int* ldb, float* c, lapack_int* ldc, const float* d, + lapack_int* ldd, const float* e, lapack_int* lde, float* f, + lapack_int* ldf, float* scale, float* dif, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dtgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const double* a, lapack_int* lda, const double* b, + lapack_int* ldb, double* c, lapack_int* ldc, + const double* d, lapack_int* ldd, const double* e, + lapack_int* lde, double* f, lapack_int* ldf, double* scale, + double* dif, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* c, lapack_int* ldc, + const lapack_complex_float* d, lapack_int* ldd, + const lapack_complex_float* e, lapack_int* lde, + lapack_complex_float* f, lapack_int* ldf, float* scale, + float* dif, lapack_complex_float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ztgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* c, lapack_int* ldc, + const lapack_complex_double* d, lapack_int* ldd, + const lapack_complex_double* e, lapack_int* lde, + lapack_complex_double* f, lapack_int* ldf, double* scale, + double* dif, lapack_complex_double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_stgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, const float* vl, + lapack_int* ldvl, const float* vr, lapack_int* ldvr, + float* s, float* dif, lapack_int* mm, lapack_int* m, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, const double* vl, + lapack_int* ldvl, const double* vr, lapack_int* ldvr, + double* s, double* dif, lapack_int* mm, lapack_int* m, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, const lapack_complex_float* vl, + lapack_int* ldvl, const lapack_complex_float* vr, + lapack_int* ldvr, float* s, float* dif, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_ztgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, const lapack_complex_double* vl, + lapack_int* ldvl, const lapack_complex_double* vr, + lapack_int* ldvr, double* s, double* dif, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_sggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, float* a, lapack_int* lda, + float* b, lapack_int* ldb, float* tola, float* tolb, + lapack_int* k, lapack_int* l, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + lapack_int* iwork, float* tau, float* work, + lapack_int *info ); +void LAPACK_dggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, double* a, lapack_int* lda, + double* b, lapack_int* ldb, double* tola, double* tolb, + lapack_int* k, lapack_int* l, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + lapack_int* iwork, double* tau, double* work, + lapack_int *info ); +void LAPACK_cggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + float* tola, float* tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, lapack_int* iwork, + float* rwork, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + double* tola, double* tolb, lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_stgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* tola, float* tolb, float* alpha, float* beta, + float* u, lapack_int* ldu, float* v, lapack_int* ldv, + float* q, lapack_int* ldq, float* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_dtgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* tola, double* tolb, double* alpha, double* beta, + double* u, lapack_int* ldu, double* v, lapack_int* ldv, + double* q, lapack_int* ldq, double* work, + lapack_int* ncycle, lapack_int *info ); +void LAPACK_ctgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* tola, + float* tolb, float* alpha, float* beta, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_ztgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* tola, + double* tolb, double* alpha, double* beta, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_sgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int* jpvt, float* rcond, lapack_int* rank, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* jpvt, double* rcond, lapack_int* rank, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* jpvt, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* jpvt, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_zgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgglse( lapack_int* m, lapack_int* n, lapack_int* p, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* c, + float* d, float* x, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgglse( lapack_int* m, lapack_int* n, lapack_int* p, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* c, + double* d, double* x, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgglse( lapack_int* m, lapack_int* n, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* c, lapack_complex_float* d, + lapack_complex_float* x, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgglse( lapack_int* m, lapack_int* n, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* c, lapack_complex_double* d, + lapack_complex_double* x, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sggglm( lapack_int* n, lapack_int* m, lapack_int* p, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* d, + float* x, float* y, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggglm( lapack_int* n, lapack_int* m, lapack_int* p, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* d, + double* x, double* y, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggglm( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* d, lapack_complex_float* x, + lapack_complex_float* y, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zggglm( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* d, lapack_complex_double* x, + lapack_complex_double* y, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_ssyev( char* jobz, char* uplo, lapack_int* n, float* a, + lapack_int* lda, float* w, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsyev( char* jobz, char* uplo, lapack_int* n, double* a, + lapack_int* lda, double* w, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cheev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zheev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_ssyevd( char* jobz, char* uplo, lapack_int* n, float* a, + lapack_int* lda, float* w, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsyevd( char* jobz, char* uplo, lapack_int* n, double* a, + lapack_int* lda, double* w, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cheevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zheevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssyevx( char* jobz, char* range, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsyevx( char* jobz, char* range, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_cheevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zheevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_ssyevr( char* jobz, char* range, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + lapack_int* isuppz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsyevr( char* jobz, char* range, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + lapack_int* isuppz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cheevr( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_int* isuppz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zheevr( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_int* isuppz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspev( char* jobz, char* uplo, lapack_int* n, float* ap, float* w, + float* z, lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dspev( char* jobz, char* uplo, lapack_int* n, double* ap, double* w, + double* z, lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chpev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhpev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sspevd( char* jobz, char* uplo, lapack_int* n, float* ap, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dspevd( char* jobz, char* uplo, lapack_int* n, double* ap, + double* w, double* z, lapack_int* ldz, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_chpevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* lrwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zhpevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspevx( char* jobz, char* range, char* uplo, lapack_int* n, + float* ap, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dspevx( char* jobz, char* range, char* uplo, lapack_int* n, + double* ap, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chpevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhpevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_ssbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* w, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dsbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* w, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* w, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, float* ab, lapack_int* ldab, float* q, + lapack_int* ldq, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, double* ab, lapack_int* ldab, double* q, + lapack_int* ldq, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* q, lapack_int* ldq, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* q, lapack_int* ldq, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_sstev( char* jobz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dstev( char* jobz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_sstevd( char* jobz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dstevd( char* jobz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_sstevx( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dstevx( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_sstevr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, lapack_int* isuppz, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_dstevr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, lapack_int* isuppz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sgees( char* jobvs, char* sort, LAPACK_S_SELECT2 select, + lapack_int* n, float* a, lapack_int* lda, lapack_int* sdim, + float* wr, float* wi, float* vs, lapack_int* ldvs, + float* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dgees( char* jobvs, char* sort, LAPACK_D_SELECT2 select, + lapack_int* n, double* a, lapack_int* lda, lapack_int* sdim, + double* wr, double* wi, double* vs, lapack_int* ldvs, + double* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cgees( char* jobvs, char* sort, LAPACK_C_SELECT1 select, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int* ldvs, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_zgees( char* jobvs, char* sort, LAPACK_Z_SELECT1 select, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int* ldvs, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_logical* bwork, lapack_int *info ); +void LAPACK_sgeesx( char* jobvs, char* sort, LAPACK_S_SELECT2 select, + char* sense, lapack_int* n, float* a, lapack_int* lda, + lapack_int* sdim, float* wr, float* wi, float* vs, + lapack_int* ldvs, float* rconde, float* rcondv, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_dgeesx( char* jobvs, char* sort, LAPACK_D_SELECT2 select, + char* sense, lapack_int* n, double* a, lapack_int* lda, + lapack_int* sdim, double* wr, double* wi, double* vs, + lapack_int* ldvs, double* rconde, double* rcondv, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cgeesx( char* jobvs, char* sort, LAPACK_C_SELECT1 select, + char* sense, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int* ldvs, float* rconde, + float* rcondv, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zgeesx( char* jobvs, char* sort, LAPACK_Z_SELECT1 select, + char* sense, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int* ldvs, double* rconde, + double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_sgeev( char* jobvl, char* jobvr, lapack_int* n, float* a, + lapack_int* lda, float* wr, float* wi, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgeev( char* jobvl, char* jobvr, lapack_int* n, double* a, + lapack_int* lda, double* wr, double* wi, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgeev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, lapack_int* ldvr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgeev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, float* a, lapack_int* lda, float* wr, + float* wi, float* vl, lapack_int* ldvl, float* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, float* rcondv, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, double* a, lapack_int* lda, double* wr, + double* wi, double* vl, lapack_int* ldvl, double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + float* a, lapack_int* lda, float* s, float* u, + lapack_int* ldu, float* vt, lapack_int* ldvt, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + double* a, lapack_int* lda, double* s, double* u, + lapack_int* ldu, double* vt, lapack_int* ldvt, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* s, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* s, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgesdd( char* jobz, lapack_int* m, lapack_int* n, float* a, + lapack_int* lda, float* s, float* u, lapack_int* ldu, + float* vt, lapack_int* ldvt, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dgesdd( char* jobz, lapack_int* m, lapack_int* n, double* a, + lapack_int* lda, double* s, double* u, lapack_int* ldu, + double* vt, lapack_int* ldvt, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgesdd( char* jobz, lapack_int* m, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* s, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zgesdd( char* jobz, lapack_int* m, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* s, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, double* a, + lapack_int* lda, double* sva, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, float* a, + lapack_int* lda, float* sva, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, double* a, lapack_int* lda, double* sva, + lapack_int* mv, double* v, lapack_int* ldv, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, float* a, lapack_int* lda, float* sva, + lapack_int* mv, float* v, lapack_int* ldv, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* alpha, float* beta, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* alpha, double* beta, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* alpha, + float* beta, lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, float* rwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_zggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* alpha, + double* beta, lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ssygv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* w, float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dsygv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* w, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chegv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhegv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_ssygvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* w, float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dsygvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* w, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chegvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhegvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssygvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_dsygvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_chegvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zhegvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_sspgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* ap, float* bp, float* w, float* z, lapack_int* ldz, + float* work, lapack_int *info ); +void LAPACK_dspgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* ap, double* bp, double* w, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chpgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhpgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, lapack_complex_double* bp, + double* w, lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sspgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* ap, float* bp, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dspgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* ap, double* bp, double* w, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chpgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, lapack_complex_float* bp, + float* w, lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhpgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, lapack_complex_double* bp, + double* w, lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, float* ap, float* bp, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* iwork, lapack_int* ifail, + lapack_int *info ); +void LAPACK_dspgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, double* ap, double* bp, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* iwork, lapack_int* ifail, + lapack_int *info ); +void LAPACK_chpgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_float* ap, + lapack_complex_float* bp, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhpgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_double* ap, + lapack_complex_double* bp, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_ssbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, float* bb, + lapack_int* ldbb, float* w, float* z, lapack_int* ldz, + float* work, lapack_int *info ); +void LAPACK_dsbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, double* bb, + lapack_int* ldbb, double* w, double* z, lapack_int* ldz, + double* work, lapack_int *info ); +void LAPACK_chbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* bb, lapack_int* ldbb, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* bb, lapack_int* ldbb, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, float* bb, + lapack_int* ldbb, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dsbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, double* bb, + lapack_int* ldbb, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_chbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* bb, lapack_int* ldbb, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* bb, lapack_int* ldbb, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, float* ab, lapack_int* ldab, + float* bb, lapack_int* ldbb, float* q, lapack_int* ldq, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, double* ab, + lapack_int* ldab, double* bb, lapack_int* ldbb, double* q, + lapack_int* ldq, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* bb, + lapack_int* ldbb, lapack_complex_float* q, lapack_int* ldq, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zhbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* bb, + lapack_int* ldbb, lapack_complex_double* q, lapack_int* ldq, + double* vl, double* vu, lapack_int* il, lapack_int* iu, + double* abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_sgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_S_SELECT3 selctg, lapack_int* n, float* a, + lapack_int* lda, float* b, lapack_int* ldb, lapack_int* sdim, + float* alphar, float* alphai, float* beta, float* vsl, + lapack_int* ldvsl, float* vsr, lapack_int* ldvsr, + float* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_D_SELECT3 selctg, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int* ldvsl, double* vsr, + lapack_int* ldvsr, double* work, lapack_int* lwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_cgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_C_SELECT2 selctg, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int* ldvsl, + lapack_complex_float* vsr, lapack_int* ldvsr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_zgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_Z_SELECT2 selctg, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int* ldvsl, + lapack_complex_double* vsr, lapack_int* ldvsr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_logical* bwork, lapack_int *info ); +void LAPACK_sggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_S_SELECT3 selctg, char* sense, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + lapack_int* sdim, float* alphar, float* alphai, float* beta, + float* vsl, lapack_int* ldvsl, float* vsr, + lapack_int* ldvsr, float* rconde, float* rcondv, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_D_SELECT3 selctg, char* sense, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int* ldvsl, double* vsr, + lapack_int* ldvsr, double* rconde, double* rcondv, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_C_SELECT2 selctg, char* sense, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int* ldvsl, + lapack_complex_float* vsr, lapack_int* ldvsr, float* rconde, + float* rcondv, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_Z_SELECT2 selctg, char* sense, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int* ldvsl, + lapack_complex_double* vsr, lapack_int* ldvsr, + double* rconde, double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_sggev( char* jobvl, char* jobvr, lapack_int* n, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* alphar, + float* alphai, float* beta, float* vl, lapack_int* ldvl, + float* vr, lapack_int* ldvr, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggev( char* jobvl, char* jobvr, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* alphar, + double* alphai, double* beta, double* vl, lapack_int* ldvl, + double* vr, lapack_int* ldvr, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cggev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zggev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* alphar, float* alphai, float* beta, + float* vl, lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, float* rconde, + float* rcondv, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* alphar, double* alphai, + double* beta, double* vl, lapack_int* ldvl, double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, float* abnrm, + float* bbnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* abnrm, double* bbnrm, + double* rconde, double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_dsfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, double* alpha, const double* a, + lapack_int* lda, double* beta, double* c ); +void LAPACK_ssfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, float* alpha, const float* a, lapack_int* lda, + float* beta, float* c ); +void LAPACK_zhfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, double* alpha, const lapack_complex_double* a, + lapack_int* lda, double* beta, lapack_complex_double* c ); +void LAPACK_chfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, float* alpha, const lapack_complex_float* a, + lapack_int* lda, float* beta, lapack_complex_float* c ); +void LAPACK_dtfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, double* alpha, + const double* a, double* b, lapack_int* ldb ); +void LAPACK_stfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, float* alpha, + const float* a, float* b, lapack_int* ldb ); +void LAPACK_ztfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, + lapack_complex_double* alpha, const lapack_complex_double* a, + lapack_complex_double* b, lapack_int* ldb ); +void LAPACK_ctfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, + lapack_complex_float* alpha, const lapack_complex_float* a, + lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_dtfttp( char* transr, char* uplo, lapack_int* n, const double* arf, + double* ap, lapack_int *info ); +void LAPACK_stfttp( char* transr, char* uplo, lapack_int* n, const float* arf, + float* ap, lapack_int *info ); +void LAPACK_ztfttp( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* arf, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ctfttp( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* arf, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_dtfttr( char* transr, char* uplo, lapack_int* n, const double* arf, + double* a, lapack_int* lda, lapack_int *info ); +void LAPACK_stfttr( char* transr, char* uplo, lapack_int* n, const float* arf, + float* a, lapack_int* lda, lapack_int *info ); +void LAPACK_ztfttr( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* arf, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ctfttr( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* arf, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dtpttf( char* transr, char* uplo, lapack_int* n, const double* ap, + double* arf, lapack_int *info ); +void LAPACK_stpttf( char* transr, char* uplo, lapack_int* n, const float* ap, + float* arf, lapack_int *info ); +void LAPACK_ztpttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* ap, lapack_complex_double* arf, + lapack_int *info ); +void LAPACK_ctpttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* ap, lapack_complex_float* arf, + lapack_int *info ); +void LAPACK_dtpttr( char* uplo, lapack_int* n, const double* ap, double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_stpttr( char* uplo, lapack_int* n, const float* ap, float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ztpttr( char* uplo, lapack_int* n, const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_ctpttr( char* uplo, lapack_int* n, const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dtrttf( char* transr, char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* arf, lapack_int *info ); +void LAPACK_strttf( char* transr, char* uplo, lapack_int* n, const float* a, + lapack_int* lda, float* arf, lapack_int *info ); +void LAPACK_ztrttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* arf, lapack_int *info ); +void LAPACK_ctrttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* arf, lapack_int *info ); +void LAPACK_dtrttp( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + double* ap, lapack_int *info ); +void LAPACK_strttp( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* ap, lapack_int *info ); +void LAPACK_ztrttp( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ctrttp( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_sgeqrfp( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqrfp( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqrfp( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqrfp( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_clacgv( lapack_int* n, lapack_complex_float* x, lapack_int* incx ); +void LAPACK_zlacgv( lapack_int* n, lapack_complex_double* x, lapack_int* incx ); +void LAPACK_slarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + float* x ); +void LAPACK_dlarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + double* x ); +void LAPACK_clarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + lapack_complex_float* x ); +void LAPACK_zlarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + lapack_complex_double* x ); +void LAPACK_sgeqr2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int *info ); +void LAPACK_dgeqr2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int *info ); +void LAPACK_cgeqr2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgeqr2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slacn2( lapack_int* n, float* v, float* x, lapack_int* isgn, + float* est, lapack_int* kase, lapack_int* isave ); +void LAPACK_dlacn2( lapack_int* n, double* v, double* x, lapack_int* isgn, + double* est, lapack_int* kase, lapack_int* isave ); +void LAPACK_clacn2( lapack_int* n, lapack_complex_float* v, + lapack_complex_float* x, float* est, + lapack_int* kase, lapack_int* isave ); +void LAPACK_zlacn2( lapack_int* n, lapack_complex_double* v, + lapack_complex_double* x, double* est, + lapack_int* kase, lapack_int* isave ); +void LAPACK_slacpy( char* uplo, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* b, lapack_int* ldb ); +void LAPACK_dlacpy( char* uplo, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* b, lapack_int* ldb ); +void LAPACK_clacpy( char* uplo, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_zlacpy( char* uplo, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb ); + +void LAPACK_clacp2( char* uplo, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_zlacp2( char* uplo, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, lapack_complex_double* b, + lapack_int* ldb ); + +void LAPACK_sgetf2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgetf2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgetf2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgetf2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_slaswp( lapack_int* n, float* a, lapack_int* lda, lapack_int* k1, + lapack_int* k2, const lapack_int* ipiv, lapack_int* incx ); +void LAPACK_dlaswp( lapack_int* n, double* a, lapack_int* lda, lapack_int* k1, + lapack_int* k2, const lapack_int* ipiv, lapack_int* incx ); +void LAPACK_claswp( lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_int* k1, lapack_int* k2, const lapack_int* ipiv, + lapack_int* incx ); +void LAPACK_zlaswp( lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_int* k1, lapack_int* k2, const lapack_int* ipiv, + lapack_int* incx ); +float LAPACK_slange( char* norm, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* work ); +double LAPACK_dlange( char* norm, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* work ); +float LAPACK_clange( char* norm, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlange( char* norm, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_clanhe( char* norm, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlanhe( char* norm, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_slansy( char* norm, char* uplo, lapack_int* n, const float* a, + lapack_int* lda, float* work ); +double LAPACK_dlansy( char* norm, char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* work ); +float LAPACK_clansy( char* norm, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlansy( char* norm, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_slantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, float* work ); +double LAPACK_dlantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, double* work ); +float LAPACK_clantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, lapack_int* lda, + float* work ); +double LAPACK_zlantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, lapack_int* lda, + double* work ); +float LAPACK_slamch( char* cmach ); +double LAPACK_dlamch( char* cmach ); +void LAPACK_sgelq2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int *info ); +void LAPACK_dgelq2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int *info ); +void LAPACK_cgelq2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgelq2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, const float* v, + lapack_int* ldv, const float* t, lapack_int* ldt, float* c, + lapack_int* ldc, float* work, lapack_int* ldwork ); +void LAPACK_dlarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* c, lapack_int* ldc, double* work, + lapack_int* ldwork ); +void LAPACK_clarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* ldwork ); +void LAPACK_zlarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* ldwork ); +void LAPACK_slarfg( lapack_int* n, float* alpha, float* x, lapack_int* incx, + float* tau ); +void LAPACK_dlarfg( lapack_int* n, double* alpha, double* x, lapack_int* incx, + double* tau ); +void LAPACK_clarfg( lapack_int* n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int* incx, + lapack_complex_float* tau ); +void LAPACK_zlarfg( lapack_int* n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int* incx, + lapack_complex_double* tau ); +void LAPACK_slarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const float* v, lapack_int* ldv, const float* tau, float* t, + lapack_int* ldt ); +void LAPACK_dlarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const double* v, lapack_int* ldv, const double* tau, + double* t, lapack_int* ldt ); +void LAPACK_clarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* tau, lapack_complex_float* t, + lapack_int* ldt ); +void LAPACK_zlarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* tau, lapack_complex_double* t, + lapack_int* ldt ); +void LAPACK_slarfx( char* side, lapack_int* m, lapack_int* n, const float* v, + float* tau, float* c, lapack_int* ldc, float* work ); +void LAPACK_dlarfx( char* side, lapack_int* m, lapack_int* n, const double* v, + double* tau, double* c, lapack_int* ldc, double* work ); +void LAPACK_clarfx( char* side, lapack_int* m, lapack_int* n, + const lapack_complex_float* v, lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work ); +void LAPACK_zlarfx( char* side, lapack_int* m, lapack_int* n, + const lapack_complex_double* v, lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work ); +void LAPACK_slatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, float* d, lapack_int* mode, float* cond, + float* dmax, lapack_int* kl, lapack_int* ku, char* pack, + float* a, lapack_int* lda, float* work, lapack_int *info ); +void LAPACK_dlatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, double* d, lapack_int* mode, double* cond, + double* dmax, lapack_int* kl, lapack_int* ku, char* pack, + double* a, lapack_int* lda, double* work, + lapack_int *info ); +void LAPACK_clatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, float* d, lapack_int* mode, float* cond, + float* dmax, lapack_int* kl, lapack_int* ku, char* pack, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, double* d, lapack_int* mode, double* cond, + double* dmax, lapack_int* kl, lapack_int* ku, char* pack, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slag2d( lapack_int* m, lapack_int* n, const float* sa, + lapack_int* ldsa, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dlag2s( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, float* sa, lapack_int* ldsa, + lapack_int *info ); +void LAPACK_clag2z( lapack_int* m, lapack_int* n, + const lapack_complex_float* sa, lapack_int* ldsa, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_zlag2c( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_float* sa, lapack_int* ldsa, + lapack_int *info ); +void LAPACK_slauum( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dlauum( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_clauum( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zlauum( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_slagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* d, float* a, lapack_int* lda, + lapack_int* iseed, float* work, lapack_int *info ); +void LAPACK_dlagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* d, double* a, lapack_int* lda, + lapack_int* iseed, double* work, lapack_int *info ); +void LAPACK_clagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* d, lapack_complex_float* a, + lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* d, lapack_complex_double* a, + lapack_int* lda, lapack_int* iseed, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slaset( char* uplo, lapack_int* m, lapack_int* n, float* alpha, + float* beta, float* a, lapack_int* lda ); +void LAPACK_dlaset( char* uplo, lapack_int* m, lapack_int* n, double* alpha, + double* beta, double* a, lapack_int* lda ); +void LAPACK_claset( char* uplo, lapack_int* m, lapack_int* n, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* a, lapack_int* lda ); +void LAPACK_zlaset( char* uplo, lapack_int* m, lapack_int* n, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* a, lapack_int* lda ); +void LAPACK_slasrt( char* id, lapack_int* n, float* d, lapack_int *info ); +void LAPACK_dlasrt( char* id, lapack_int* n, double* d, lapack_int *info ); +void LAPACK_claghe( lapack_int* n, lapack_int* k, const float* d, + lapack_complex_float* a, lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlaghe( lapack_int* n, lapack_int* k, const double* d, + lapack_complex_double* a, lapack_int* lda, + lapack_int* iseed, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_slagsy( lapack_int* n, lapack_int* k, const float* d, float* a, + lapack_int* lda, lapack_int* iseed, float* work, + lapack_int *info ); +void LAPACK_dlagsy( lapack_int* n, lapack_int* k, const double* d, double* a, + lapack_int* lda, lapack_int* iseed, double* work, + lapack_int *info ); +void LAPACK_clagsy( lapack_int* n, lapack_int* k, const float* d, + lapack_complex_float* a, lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlagsy( lapack_int* n, lapack_int* k, const double* d, + lapack_complex_double* a, lapack_int* lda, + lapack_int* iseed, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_slapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_dlapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + double* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_clapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_zlapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_double* x, lapack_int* ldx, lapack_int* k ); +float LAPACK_slapy2( float* x, float* y ); +double LAPACK_dlapy2( double* x, double* y ); +float LAPACK_slapy3( float* x, float* y, float* z ); +double LAPACK_dlapy3( double* x, double* y, double* z ); +void LAPACK_slartgp( float* f, float* g, float* cs, float* sn, float* r ); +void LAPACK_dlartgp( double* f, double* g, double* cs, double* sn, double* r ); +void LAPACK_slartgs( float* x, float* y, float* sigma, float* cs, float* sn ); +void LAPACK_dlartgs( double* x, double* y, double* sigma, double* cs, + double* sn ); +// LAPACK 3.3.0 +void LAPACK_cbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + float* theta, float* phi, + lapack_complex_float* u1, lapack_int* ldu1, + lapack_complex_float* u2, lapack_int* ldu2, + lapack_complex_float* v1t, lapack_int* ldv1t, + lapack_complex_float* v2t, lapack_int* ldv2t, + float* b11d, float* b11e, float* b12d, + float* b12e, float* b21d, float* b21e, + float* b22d, float* b22e, float* rwork, + lapack_int* lrwork , lapack_int *info ); +void LAPACK_cheswapr( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_chetri2( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_chetri2x( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* nb , lapack_int *info ); +void LAPACK_chetrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_csyconv( char* uplo, char* way, + lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_csyswapr( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_csytri2( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_csytri2x( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* nb , lapack_int *info ); +void LAPACK_csytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_cunbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + lapack_complex_float* x11, lapack_int* ldx11, + lapack_complex_float* x12, lapack_int* ldx12, + lapack_complex_float* x21, lapack_int* ldx21, + lapack_complex_float* x22, lapack_int* ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_cuncsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_float* x11, + lapack_int* ldx11, lapack_complex_float* x12, + lapack_int* ldx12, lapack_complex_float* x21, + lapack_int* ldx21, lapack_complex_float* x22, + lapack_int* ldx22, float* theta, + lapack_complex_float* u1, lapack_int* ldu1, + lapack_complex_float* u2, lapack_int* ldu2, + lapack_complex_float* v1t, lapack_int* ldv1t, + lapack_complex_float* v2t, lapack_int* ldv2t, + lapack_complex_float* work, lapack_int* lwork, + float* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_dbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + double* theta, double* phi, double* u1, + lapack_int* ldu1, double* u2, lapack_int* ldu2, + double* v1t, lapack_int* ldv1t, double* v2t, + lapack_int* ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e, + double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_dorbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + double* x11, lapack_int* ldx11, double* x12, + lapack_int* ldx12, double* x21, lapack_int* ldx21, + double* x22, lapack_int* ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2, double* work, + lapack_int* lwork , lapack_int *info ); +void LAPACK_dorcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, double* x11, lapack_int* ldx11, + double* x12, lapack_int* ldx12, double* x21, + lapack_int* ldx21, double* x22, lapack_int* ldx22, + double* theta, double* u1, lapack_int* ldu1, + double* u2, lapack_int* ldu2, double* v1t, + lapack_int* ldv1t, double* v2t, lapack_int* ldv2t, + double* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_dsyconv( char* uplo, char* way, + lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work , lapack_int *info ); +void LAPACK_dsyswapr( char* uplo, lapack_int* n, + double* a, lapack_int* i1, lapack_int* i2 ); +void LAPACK_dsytri2( char* uplo, lapack_int* n, + double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_dsytri2x( char* uplo, lapack_int* n, + double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, + lapack_int* nb , lapack_int *info ); +void LAPACK_dsytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const double* a, + lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, double* work , lapack_int *info ); +void LAPACK_sbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + float* theta, float* phi, float* u1, + lapack_int* ldu1, float* u2, lapack_int* ldu2, + float* v1t, lapack_int* ldv1t, float* v2t, + lapack_int* ldv2t, float* b11d, float* b11e, + float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e, + float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_sorbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + float* x11, lapack_int* ldx11, float* x12, + lapack_int* ldx12, float* x21, lapack_int* ldx21, + float* x22, lapack_int* ldx22, float* theta, + float* phi, float* taup1, float* taup2, + float* tauq1, float* tauq2, float* work, + lapack_int* lwork , lapack_int *info ); +void LAPACK_sorcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, float* x11, lapack_int* ldx11, + float* x12, lapack_int* ldx12, float* x21, + lapack_int* ldx21, float* x22, lapack_int* ldx22, + float* theta, float* u1, lapack_int* ldu1, + float* u2, lapack_int* ldu2, float* v1t, + lapack_int* ldv1t, float* v2t, lapack_int* ldv2t, + float* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_ssyconv( char* uplo, char* way, + lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work , lapack_int *info ); +void LAPACK_ssyswapr( char* uplo, lapack_int* n, + float* a, lapack_int* i1, lapack_int* i2 ); +void LAPACK_ssytri2( char* uplo, lapack_int* n, + float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_ssytri2x( char* uplo, lapack_int* n, + float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, + lapack_int* nb , lapack_int *info ); +void LAPACK_ssytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const float* a, + lapack_int* lda, const lapack_int* ipiv, + float* b, lapack_int* ldb, float* work , lapack_int *info ); +void LAPACK_zbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + double* theta, double* phi, + lapack_complex_double* u1, lapack_int* ldu1, + lapack_complex_double* u2, lapack_int* ldu2, + lapack_complex_double* v1t, lapack_int* ldv1t, + lapack_complex_double* v2t, lapack_int* ldv2t, + double* b11d, double* b11e, double* b12d, + double* b12e, double* b21d, double* b21e, + double* b22d, double* b22e, double* rwork, + lapack_int* lrwork , lapack_int *info ); +void LAPACK_zheswapr( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_zhetri2( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zhetri2x( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* nb , lapack_int *info ); +void LAPACK_zhetrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zsyconv( char* uplo, char* way, + lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zsyswapr( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_zsytri2( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zsytri2x( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* nb , lapack_int *info ); +void LAPACK_zsytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zunbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + lapack_complex_double* x11, lapack_int* ldx11, + lapack_complex_double* x12, lapack_int* ldx12, + lapack_complex_double* x21, lapack_int* ldx21, + lapack_complex_double* x22, lapack_int* ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zuncsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_double* x11, + lapack_int* ldx11, lapack_complex_double* x12, + lapack_int* ldx12, lapack_complex_double* x21, + lapack_int* ldx21, lapack_complex_double* x22, + lapack_int* ldx22, double* theta, + lapack_complex_double* u1, lapack_int* ldu1, + lapack_complex_double* u2, lapack_int* ldu2, + lapack_complex_double* v1t, lapack_int* ldv1t, + lapack_complex_double* v2t, lapack_int* ldv2t, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +// LAPACK 3.4.0 +void LAPACK_sgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, const float* v, + lapack_int* ldv, const float* t, lapack_int* ldt, float* c, + lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, const double* v, + lapack_int* ldv, const double* t, lapack_int* ldt, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_cgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_sgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, float* a, + lapack_int* lda, float* t, lapack_int* ldt, float* work, + lapack_int *info ); +void LAPACK_dgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, double* a, + lapack_int* lda, double* t, lapack_int* ldt, double* work, + lapack_int *info ); +void LAPACK_cgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_sgeqrt2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_dgeqrt2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_cgeqrt2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_zgeqrt2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_sgeqrt3( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_dgeqrt3( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_cgeqrt3( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_zgeqrt3( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_stpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const float* v, lapack_int* ldv, const float* t, + lapack_int* ldt, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* work, lapack_int *info ); +void LAPACK_dtpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* work, lapack_int *info ); +void LAPACK_ctpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_ztpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_dtpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* t, lapack_int* ldt, double* work, + lapack_int *info ); +void LAPACK_ctpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_ztpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_stpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + float* a, lapack_int* lda, + float* b, lapack_int* ldb, + float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_dtpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + double* a, lapack_int* lda, + double* b, lapack_int* ldb, + double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_ctpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_ztpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_stprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const float* v, lapack_int* ldv, const float* t, + lapack_int* ldt, float* a, lapack_int* lda, float* b, + lapack_int* ldb, const float* work, + lapack_int* ldwork ); +void LAPACK_dtprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* a, lapack_int* lda, double* b, + lapack_int* ldb, const double* work, + lapack_int* ldwork ); +void LAPACK_ctprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + const float* work, lapack_int* ldwork ); +void LAPACK_ztprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + const double* work, lapack_int* ldwork ); +// LAPACK 3.5.0 +void LAPACK_ssysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, lapack_int* ipiv, float* b, + lapack_int* ldb, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, lapack_int* ipiv, double* b, + lapack_int* ldb, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zsysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_csyr( char* uplo, lapack_int* n, lapack_complex_float* alpha, + const lapack_complex_float* x, lapack_int* incx, + lapack_complex_float* a, lapack_int* lda ); +void LAPACK_zsyr( char* uplo, lapack_int* n, lapack_complex_double* alpha, + const lapack_complex_double* x, lapack_int* incx, + lapack_complex_double* a, lapack_int* lda ); +void LAPACK_ilaver( const lapack_int* vers_major, const lapack_int* vers_minor, + const lapack_int* vers_patch ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LAPACKE_H_ */ diff --git a/OpenFAST/modules/map/src/lapack/lapacke_mangling.h b/OpenFAST/modules/map/src/lapack/lapacke_mangling.h new file mode 100644 index 000000000..6211fd144 --- /dev/null +++ b/OpenFAST/modules/map/src/lapack/lapacke_mangling.h @@ -0,0 +1,17 @@ +#ifndef LAPACK_HEADER_INCLUDED +#define LAPACK_HEADER_INCLUDED + +#ifndef LAPACK_GLOBAL +#if defined(LAPACK_GLOBAL_PATTERN_LC) || defined(ADD_) +#define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ +#elif defined(LAPACK_GLOBAL_PATTERN_UC) || defined(UPPER) +#define LAPACK_GLOBAL(lcname,UCNAME) UCNAME +#elif defined(LAPACK_GLOBAL_PATTERN_MC) || defined(NOCHANGE) +#define LAPACK_GLOBAL(lcname,UCNAME) lcname +#else +#define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ +#endif +#endif + +#endif + diff --git a/OpenFAST/modules/map/src/lineroutines.c b/OpenFAST/modules/map/src/lineroutines.c new file mode 100644 index 000000000..7a8ca2098 --- /dev/null +++ b/OpenFAST/modules/map/src/lineroutines.c @@ -0,0 +1,1397 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "lineroutines.h" +#include "numeric.h" +#include "jacobian.h" +#ifdef WITH_LAPACK +# include "lapack/lapacke.h" +#endif + +MAP_ERROR_CODE reset_node_force_to_zero(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Node* node_iter = NULL; + + list_iterator_start(&domain->node); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->node)) { /* tell whether more values available */ + node_iter = (Node*)list_iterator_next(&domain->node); + *(node_iter->sum_force_ptr.fx.value) = 0.0; + *(node_iter->sum_force_ptr.fy.value) = 0.0; + *(node_iter->sum_force_ptr.fz.value) = 0.0; + }; + list_iterator_stop(&domain->node); /* ending the iteration "session" */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE calculate_node_sum_force(Domain* domain, MAP_ParameterType_t* p_type) +{ + Line* line_iter = NULL; + Node* node_iter = NULL; + const double g = p_type->g; + const double rho = p_type->rho_sea; + double psi = 0.0; + double sum_fx = 0.0; + double sum_fy = 0.0; + double sum_fz = 0.0; + double fx = 0.0; + double fy = 0.0; + double fz = 0.0; + double fx_a = 0.0; + double fy_a = 0.0; + double fz_a = 0.0; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + psi = line_iter->psi; + fx = *(line_iter->H.value)*cos(psi); + fx_a = -(line_iter->H_at_anchor)*cos(psi); + + fy = *(line_iter->H.value)*sin(psi); + fy_a = -(line_iter->H_at_anchor)*sin(psi); + + fz = *(line_iter->V.value); + fz_a = -(line_iter->V_at_anchor); + + add_to_sum_fx(line_iter->fairlead, fx); + add_to_sum_fx(line_iter->anchor, fx_a); + + add_to_sum_fy(line_iter->fairlead, fy); + add_to_sum_fy(line_iter->anchor, fy_a); + + add_to_sum_fz(line_iter->fairlead, fz); + add_to_sum_fz(line_iter->anchor, fz_a); + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + + /* This is where we include the externally applied forces on the node. Note that + * \sum F_x= \left \{ \mathbf{f}_\textup{lines} \right \}_x-\left \{ \mathbf{f}_\textup{ext} \right \}_x \\ + * \sum F_y= \left \{ \mathbf{f}_\textup{lines} \right \}_y-\left \{ \mathbf{f}_\textup{ext} \right \}_y \ \ + * \sum F_z= \left \{ \mathbf{f}_\textup{lines} \right \}_z-\left \{ \mathbf{f}_\textup{ext} \right \}_z - gM_{\textup{app}} + \rho gB_{\textup{app}} + * The \mathbf{f}_{\textup{lines}} portion is summed in the line iterator above. + */ + list_iterator_start(&domain->node); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->node)) { /* tell whether more values available */ + node_iter = (Node*)list_iterator_next(&domain->node); + if (node_iter->type==CONNECT) { + sum_fx = -(node_iter->external_force.fx.value); + sum_fy = -(node_iter->external_force.fy.value); + sum_fz = -(node_iter->external_force.fz.value - node_iter->M_applied.value*g + node_iter->B_applied.value*rho*g); + + add_to_sum_fx(node_iter, sum_fx); + add_to_sum_fy(node_iter, sum_fy); + add_to_sum_fz(node_iter, sum_fz); + }; + }; + list_iterator_stop(&domain->node); /* ending the iteration "session" */ + return MAP_SAFE; +} + + +void add_to_sum_fx(Node* node, const double fx) +{ + *(node->sum_force_ptr.fx.value) += fx; +}; + + +void add_to_sum_fy(Node* node, const double fy) +{ + *(node->sum_force_ptr.fy.value) += fy; +}; + + +void add_to_sum_fz(Node* node, const double fz) +{ + *(node->sum_force_ptr.fz.value) += fz; +}; + + +MAP_ERROR_CODE set_line_variables_pre_solve(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Line* line_iter = NULL; + int i = 0; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + + /* no fairlead or anchor was not set. End program gracefully. + * there is likely an error in the input file + */ + if (!line_iter->fairlead || !line_iter->anchor) { + *ierr = MAP_FATAL; + break; + }; + + /* horizontal cable excursion */ + line_iter->l = set_horizontal_excursion(line_iter); + + /* vertical cable excursion */ + line_iter->h = set_vertical_excursion(line_iter); + + /* angle of azimuth */ + success = set_psi(line_iter, map_msg, ierr); + if (success!=MAP_SAFE) { + set_universal_error_with_message(map_msg, ierr, MAP_WARNING_6, "Line number %d", i); + }; + i++; + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE set_line_variables_post_solve(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Line* line_iter = NULL; + double H = 0.0; + double V = 0.0; + double Ha = 0.0; + double Va = 0.0; + double w = 0.0; + double Lu = 0.0; + double Lb = 0.0; + double cb = 0.0; + bool contact_flag = false; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + + /* altitude angle at fairlead */ + H = *(line_iter->H.value); + V = *(line_iter->V.value); + line_iter->alpha = atan2(V, H); + + /* tension at fairlead */ + line_iter->T = sqrt(H*H + V*V); + + if (line_iter->options.linear_spring) { + Ha = H; + Va = V; + } else { + /* line in contact with seabed options */ + w = line_iter->line_property->omega; + cb = line_iter->line_property->cb; + contact_flag = line_iter->options.omit_contact; + Lu = line_iter->Lu.value; + if (contact_flag==true || w<0.0 || (V-w*Lu)>0.0) { + line_iter->Lb = 0.0; + Ha = H; + Va = V - w*Lu; + } else { /* line is touching the seabed */ + Lb = Lu - (V/w); + line_iter->Lb = Lb; + ((H-cb*w*Lb)>0.0) ? (Ha = (H-cb*w*Lb)) : (Ha = 0.0); + Va = 0.0; + }; + }; + + /* tension at anchor */ + line_iter->H_at_anchor = Ha; + line_iter->V_at_anchor = Va; + line_iter->T_at_anchor = sqrt(Ha*Ha + Va*Va); + line_iter->alpha_at_anchor = atan2(Va, Ha); + + /* set global x,y,z force at fairlead and achor */ + line_iter->fx_fairlead = H*cos(line_iter->psi); + line_iter->fy_fairlead = H*sin(line_iter->psi); + line_iter->fz_fairlead = V; + + line_iter->fx_anchor = Ha*cos(line_iter->psi); + line_iter->fy_anchor = Ha*sin(line_iter->psi); + line_iter->fz_anchor = Va; + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_psi(Line* line, char* map_msg, MAP_ERROR_CODE* ierr) +{ + const double x_fair = *(line->fairlead->position_ptr.x.value); + const double y_fair = *(line->fairlead->position_ptr.y.value); + const double z_fair = *(line->fairlead->position_ptr.z.value); + const double x_anch = *(line->anchor->position_ptr.x.value); + const double y_anch = *(line->anchor->position_ptr.y.value); + const double z_anch = *(line->anchor->position_ptr.z.value); + const double overlap_value = sqrt(pow((x_fair-x_anch), 2) + pow((y_fair-y_anch), 2) + pow((z_fair-z_anch), 2)); + double norm = sqrt(pow((x_fair-x_anch), 2) + pow((y_fair-y_anch), 2)); + + /* make sure the demoninator is not zero (or close to it) */ + if (overlap_value<=1e-2) { + // @todo: what happens when this returns prematurely? + return MAP_WARNING; + }; + + if (norm<=1e-2) { + norm = 1e-2; + }; + + /* find the angle psi line simply finds the angle psi between the local and global reference frames simply by + * evaluating trig relationships + */ + if ((y_fair-y_anch)>=0) { + /* this simply finds the angle psi between the local and + * global reference frames simply by evaluation trig relationships + */ + line->psi = acos((x_fair-x_anch)/norm); + } else { + line->psi = -acos((x_fair-x_anch)/norm); + }; + // printf("%2.3f %2.3f\n", line->psi, atan2((y_fair - y_anch), (x_fair - x_anch))); + line->psi = atan2((y_fair-y_anch), (x_fair-x_anch)); + return MAP_SAFE; +}; + + +double set_horizontal_excursion(Line* line) +{ + const double x_fair = *(line->fairlead->position_ptr.x.value); + const double y_fair = *(line->fairlead->position_ptr.y.value); + const double x_anch = *(line->anchor->position_ptr.x.value); + const double y_anch = *(line->anchor->position_ptr.y.value); + const double length = sqrt(pow((x_fair-x_anch),2) + pow((y_fair-y_anch),2)); + + return length > MAP_HORIZONTAL_TOL ? length : MAP_HORIZONTAL_TOL; +}; + + +double set_vertical_excursion(Line* line) +{ + const double z_fair = *(line->fairlead->position_ptr.z.value); + const double z_anch = *(line->anchor->position_ptr.z.value); + + return fabs(z_fair - z_anch); +}; + + +MAP_ERROR_CODE set_line_initial_guess(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Line* line_iter = NULL; + double lambda = 0.0; + double length = 0.0; + double height = 0.0; + double w = 0.0; + double Lu = 0.0; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + w = line_iter->line_property->omega; + length = line_iter->l; + height = line_iter->h; + Lu = line_iter->Lu.value; + + /* set initial guess to user defined value (horizontal fairlead force) + in the MAP input file + */ + if (line_iter->fairlead->external_force.fx.user_initial_guess && line_iter->fairlead->external_force.fy.user_initial_guess) { + *(line_iter->H.value) = sqrt(pow(line_iter->fairlead->external_force.fx.value,2) + + pow(line_iter->fairlead->external_force.fy.value,2)); + } else { + /* note: the line horizontal (l) and vertical (h) excursion are previously initialized in set_line_variables_pre_solve(...) */ + if (length<=1e-2) { + lambda = 1000000; + } else if (sqrt(length*length+height*height)>=Lu) { + lambda = 0.2; + } else { + lambda = sqrt(3*((Lu*Lu - height*height)/(length*length) - 1)); + }; + + /* note: omega is previously initialized in function initialize_cable_library_variables(.. ) in mapinit.c */ + *(line_iter->H.value) = fabs(w*length/(2*lambda)); + }; + + /* set initial guess to user defined value (vertical fairlead force) + in the MAP input file + */ + if (line_iter->fairlead->external_force.fz.user_initial_guess) { + *(line_iter->V.value) = line_iter->fairlead->external_force.fz.value; + } else { + *(line_iter->V.value) = (w/2)*((height/tanh(lambda)) + Lu); + }; + + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE line_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, const float t, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + + MAP_BEGIN_ERROR_LOG; + + success = set_line_variables_pre_solve(domain, map_msg, ierr); + success = reset_node_force_to_zero(domain, map_msg, ierr); + success = solve_line(domain, t, map_msg, ierr); CHECKERRQ(MAP_FATAL_88); + // /* prematurely terminating the the line solve routine to return back to the + // caller function. Do a back tracking on the solution and attempt recovery */ + // if (success==MAP_FATAL) { + // return MAP_FATAL_59; + // }; + // CHECKERRQ(MAP_FATAL_39); /* @todo: this should be called elsewhere to notifiy + // users ofpremature termination. This won't be caught + // when solve_line fails. */ + success = set_line_variables_post_solve(domain, map_msg, ierr); + success = calculate_node_sum_force(domain, p_type); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(success); +}; + + +MAP_ERROR_CODE krylov_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr) +{ + OuterSolveAttributes* ns = &domain->outer_loop; + MAP_ERROR_CODE success = MAP_SAFE; + const int z_size = z_type->z_Len; //N + const int rows = 3*z_size; + double* av_head = NULL; + double* v_head = NULL; + double error = 0.0; + int i = 0; + int j = 0; + int dim = domain->outer_loop.max_krylov_its+1; // artificially inflate 'm' such that l and u are solved the first go-around + int info = 0; /* = 0: successful exit + * < 0: if INFO = -i, the i-th argument had an illegal value + * > 0: if INFO = i, the i-th diagonal element of the + * triangular factor of A is zero, so that A does not have + * full rank; the least squares solution could not be + * computed. + */ + + /* can't use this function (and option 'KRYLOV_ACCELERATOR') + * if MAP is compiled without LAPACK libraries + */ +# ifndef WITH_LAPACK + set_universal_error(map_msg, ierr, MAP_FATAL_96); + return MAP_FATAL; +# endif + + ns->iteration_count = 1; + do { + /* Refresh Jacobian, L and U components of the domain. This is solved only once per Kyrlov iteration + */ + if (dim>domain->outer_loop.max_krylov_its) { + dim = 0; + switch (ns->fd) { + case BACKWARD_DIFFERENCE : + success = backward_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_75); + break; + case CENTRAL_DIFFERENCE : + success = central_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_76); + break; + case FORWARD_DIFFERENCE : + success = forward_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_77); + break; + }; + success = line_solve_sequence(domain, p_type, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_78); + success = lu(ns, rows, map_msg, ierr); CHECKERRQ(MAP_FATAL_74); + }; + + success = lu_back_substitution(ns, rows, map_msg, ierr); + + + for (i=0 ; i<rows ; i++) { + ns->AV[i][dim] = ns->x[i]; /* ns->b = function residual */ + }; + + if (dim>0) { + for (i=0 ; i<rows ; i++) { + av_head = ns->AV[i]; + ns->AV[i][dim-1] -= ns->x[i]; + ns->C[i] = ns->x[i]; + for (j=0 ; j<dim ; j++) { + *(ns->av+j+i*dim) = *av_head++; /* av[col + row*num_cols] = AV[i][j], Row Major format */ + }; + }; + +# ifdef WITH_LAPACK + info = LAPACKE_dgels(LAPACK_ROW_MAJOR, 'N', rows, dim, 1, ns->av, dim, ns->C, 1); +# endif + + for (i=0 ; i<rows ; i++) { + av_head = ns->AV[i]; + v_head = ns->V[i]; + for (j=0 ; j<dim ; j++) { + ns->x[i] += (ns->C[j]*(*v_head++) - ns->C[j]*(*av_head++)); + }; + }; + }; + + for (i=0 ; i<rows ; i++) { + ns->V[i][dim] = ns->x[i]; + }; + + success = update_outer_loop_inputs(ns->x, z_type, z_size, map_msg, ierr); + success = line_solve_sequence(domain, p_type, time, map_msg, ierr); + success = update_outer_loop_residuals(ns->b, other_type, z_size, map_msg, ierr); + + error = 0.0; + for (i=0 ; i<z_size ; i++) { + error += (pow(other_type->Fx_connect[i],2)+ pow(other_type->Fy_connect[i],2) + pow(other_type->Fz_connect[i],2)); + } + // printf("error %f\n",error); + dim++; + + ns->iteration_count++; + if (ns->iteration_count>ns->max_its) { + set_universal_error(map_msg, ierr, MAP_FATAL_80); + break; + }; + } while (sqrt(error)>ns->tol); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE update_outer_loop_residuals(double* residual, MAP_OtherStateType_t* other_type, const int size, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + residual[3*i] = other_type->Fx_connect[i]; + residual[3*i+1] = other_type->Fy_connect[i]; + residual[3*i+2] = other_type->Fz_connect[i]; + } + return MAP_SAFE; +}; + + +MAP_ERROR_CODE update_outer_loop_inputs(double* input, MAP_ConstraintStateType_t* z_type, const int size, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int i = 0; + + for (i=0 ; i<size ; i++) { + z_type->x[i] -= input[3*i]; + z_type->y[i] -= input[3*i+1]; + z_type->z[i] -= input[3*i+2]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE newton_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr) +{ + OuterSolveAttributes* ns = &domain->outer_loop; + MAP_ERROR_CODE success = MAP_SAFE; + const int THREE = 3; + const int z_size = z_type->z_Len; //N + double error = 0.0; + int SIZE = THREE*z_size; + + ns->iteration_count = 1; + do { + error = 0.0; + success = line_solve_sequence(domain, p_type, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_79); + switch (ns->fd) { + case BACKWARD_DIFFERENCE : + success = backward_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_75); + break; + case CENTRAL_DIFFERENCE : + success = central_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_76); + break; + case FORWARD_DIFFERENCE : + success = forward_difference_jacobian(other_type, p_type, z_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_77); + break; + }; + + success = line_solve_sequence(domain, p_type, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_78); + success = root_finding_step(ns, SIZE, z_type, other_type, &error, map_msg, ierr); CHECKERRQ(MAP_FATAL_92); + + ns->iteration_count++; + if (ns->iteration_count>ns->max_its) { + set_universal_error(map_msg, ierr, MAP_FATAL_80); + break; + }; + + /* @todo: end when iterations is exceeded. need some way to indicate that simulation did not suuficiently + * meet termination criteria + */ + } while (sqrt(error)>ns->tol); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE node_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + + MAP_BEGIN_ERROR_LOG; + + if (domain->outer_loop.krylov_accelerator) { + success = krylov_solve_sequence(domain, p_type, u_type, z_type, other_type, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_94); + } else if (domain->outer_loop.powell) { + + } else { + success = newton_solve_sequence(domain, p_type, u_type, z_type, other_type, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_93); + }; + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(success); +}; + + +MAP_ERROR_CODE solve_line(Domain* domain, const float time, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Line* line_iter = NULL; + int n = 1; /* line counter */ + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + + // if (line_iter->l<MAP_HORIZONTAL_TOL && line_iter->l>=0.0) { /* perfectly vertical */ + // /* this should be triggered for perfectly vertical cable */ + // line_iter->l = MAP_HORIZONTAL_TOL; + // } else if (line_iter->l<0.0) { + if (line_iter->l<0.0) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_54, "Line segment %d, l = %d [m].", n, line_iter->l); + break; + } else if (line_iter->h<=-MACHINE_EPSILON) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_55, "Line segment %d, h = %d [m].", n, line_iter->h); + break; + } else if (line_iter->line_property->omega>0.0) { + success = check_maximum_line_length(line_iter, line_iter->options.omit_contact, map_msg, ierr); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_59, "Line segment %d.", n); + break; + }; + }; + + if (line_iter->options.linear_spring) { + success = solve_linear_spring_cable(line_iter, map_msg, ierr); CHECKERRQ(MAP_FATAL_87); + } else { + success = call_minpack_lmder(line_iter, &domain->inner_loop, n, time, map_msg, ierr); CHECKERRQ(MAP_FATAL_79); + }; + + /* + @todo: this should be moved to outside the loop + */ + // /* check if L^2 norm is small. If not, MAP converged prematurely */ + // if (line_iter->residual_norm>1e-3) { + // set_universal_error_with_message(map_msg, ierr, MAP_FATAL_90, "Line segment %d.", n); + // break; + // }; + n++; + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + + if (*ierr==MAP_SAFE) { + return MAP_SAFE; + } else if (*ierr==MAP_WARNING) { + return MAP_SAFE; + } else if (*ierr==MAP_ERROR) { + return MAP_ERROR; + } else { + return MAP_FATAL; + }; +}; + + +MAP_ERROR_CODE solve_linear_spring_cable(Line* line, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // MAP_ERROR_CODE success = MAP_SAFE; + double d_norm = 0.0; + Vector d; /* r1-r2 */ + Vector r1; /* anchor position */ + Vector r2; /* fairlead position */ + Vector force; + Vector d_unit; + const double EA = line->line_property->EA; + const double Lu = line->Lu.value; + + /* line anchor position */ + r1.x = *line->anchor->position_ptr.x.value; + r1.y = *line->anchor->position_ptr.y.value; + r1.z = *line->anchor->position_ptr.z.value; + + /* line fairlead position */ + r2.x = *line->fairlead->position_ptr.x.value; + r2.y = *line->fairlead->position_ptr.y.value; + r2.z = *line->fairlead->position_ptr.z.value; + + /* difference vector */ + d.x = r1.x - r2.x; + d.y = r1.y - r2.y; + d.z = r1.z - r2.z; + + /* calculate norm of \mathbf{d} */ + d_norm = sqrt(d.x*d.x + d.y*d.y + d.z*d.z); + + if (d_norm<MACHINE_EPSILON) { + return MAP_FATAL; + } + + /* \hat{u}_{\mathbf{d}} = \frac{\mathbf{d}} {\left \| \mathbf{d} \right \|} */ + d_unit.x = d.x/d_norm; + d_unit.y = d.y/d_norm; + d_unit.z = d.z/d_norm; + + if (d_norm<=Lu) { /* a cable cannot support a compression; force will be negative */ + force.x = 0.0; + force.y = 0.0; + force.z = 0.0; + } else { + force.x = EA/Lu*(d_norm - Lu)*d_unit.x; + force.y = EA/Lu*(d_norm - Lu)*d_unit.y; + force.z = EA/Lu*(d_norm - Lu)*d_unit.z; + }; + + *(line->H.value) = sqrt(force.x*force.x + force.y*force.y); + *(line->V.value) = fabs(force.z); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_maximum_line_length(Line* line, const bool contact_flag, char *map_msg, MAP_ERROR_CODE *ierr) +{ + // MAP_ERROR_CODE success = MAP_SAFE; + double LMax = 0.0; + const double l = line->l; + const double h = line->h; + const double EA = line->line_property->EA; + const double W = line->line_property->omega; + const double Lu = line->Lu.value; + + LMax = l - EA/W + sqrt(pow((EA/W),2) + 2.0*h*EA/W); + if (Lu>=LMax && contact_flag==false) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_59, "LMax = %f [m].", LMax); + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE increment_dof_by_delta(double* u_type, const double delta, const int size) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + u_type[i] += delta; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE restore_original_displacement(double* u_ype, const double* initial_value, const int size) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + u_ype[i] = initial_value[i]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE reset_force_to_zero(double* fx, double* fy, double* fz, double* mx, double* my, double* mz, const int size) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + fx[i] = 0.0; + fy[i] = 0.0; + fz[i] = 0.0; + mx[i] = 0.0; + my[i] = 0.0; + mz[i] = 0.0; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_force_minus(const double* in_force, double* force, const int size) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + force[i] -= -in_force[i]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_force_plus(const double* in_force, double* force, const int size) +{ + int i = 0; + for (i=0 ; i<size ; i++) { + force[i] += -in_force[i]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE increment_phi_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size) +{ + int i = 0; + double R[3][3]; + double phi = vessel->orientation.phi.value; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + + R[0][0] = 1.0; R[0][1] = 0.0; R[0][2] = 0.0; + R[1][0] = 0.0; R[1][1] = cos(phi+delta); R[1][2] = -sin(phi+delta); + R[2][0] = 0.0; R[2][1] = sin(phi+delta); R[2][2] = cos(phi+delta); + + for (i=0 ; i<size ; i++) { + /* @todo: should also include the reference origin location? */ + rx = vessel->xi[i]; + ry = vessel->yi[i]; + rz = vessel->zi[i]; + // uType->y[i] = ry - rz*delta; + // uType->z[i] = rz + ry*delta; + // printf("%f %f %f\n",uType->x[i],uType->y[i],uType->z[i]); + u_type->x[i] = R[0][0]*rx; + u_type->y[i] = R[1][1]*ry + R[1][2]*rz; + u_type->z[i] = R[2][1]*ry + R[2][2]*rz; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE increment_the_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size) +{ + int i = 0; + double R[3][3]; + double the = vessel->orientation.the.value; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + + R[0][0] = cos(the+delta); R[0][1] = 0.0; R[0][2] = sin(the+delta); + R[1][0] = 0.0; R[1][1] = 1.0; R[1][2] = 0.0; + R[2][0] = -sin(the+delta); R[2][1] = 0.0; R[2][2] = cos(the+delta); + + for (i=0 ; i<size ; i++) { + /* @todo: should also include the reference origin location? */ + rx = vessel->xi[i]; + ry = vessel->yi[i]; + rz = vessel->zi[i]; + // u_type->x[i] = rx + rz*delta; + // u_type->z[i] = rz - rx*delta; + u_type->x[i] = R[0][0]*rx + R[0][2]*rz; + u_type->y[i] = R[1][1]*ry; + u_type->z[i] = R[2][0]*rx + R[2][2]*rz; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE increment_psi_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size) +{ + int i = 0; + double R[3][3]; + double psi = vessel->orientation.psi.value; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + + R[0][0] = cos(psi+delta); R[0][1] = -sin(psi+delta); R[0][2] = 0.0; + R[1][0] = sin(psi+delta); R[1][1] = cos(psi+delta); R[1][2] = 0.0; + R[2][0] = 0.0; R[2][1] = 0.0; R[2][2] = 1.0; + + for (i=0 ; i<size ; i++) { + /* @todo: should also include the reference origin location? */ + rx = vessel->xi[i]; + ry = vessel->yi[i]; + rz = vessel->zi[i]; + // u_type->x[i] = rx - ry*delta; + // u_type->y[i] = ry + rx*delta; + u_type->x[i] = R[0][0]*rx + R[0][1]*ry; + u_type->y[i] = R[1][0]*rx + R[1][1]*ry; + u_type->z[i] = R[2][2]*rz; + }; + return MAP_SAFE; +}; + + + +MAP_ERROR_CODE fd_x_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_dof_by_delta(u_type->x, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + /* plus epsilon sequence */ + success = increment_dof_by_delta(u_type->x, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE fd_y_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_dof_by_delta(u_type->y, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + /* plus epsilon sequence */ + success = increment_dof_by_delta(u_type->y, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE fd_z_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_dof_by_delta(u_type->z, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + /* plus epsilon sequence */ + success = increment_dof_by_delta(u_type->z, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_pos, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE fd_phi_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_phi_dof_by_delta(u_type, vessel, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus_phi(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_z, size); CHECKERRQ(MAP_FATAL_61); + + /* plus epsilon sequence */ + success = increment_phi_dof_by_delta(u_type, vessel, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus_phi(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_y, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE fd_the_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_the_dof_by_delta(u_type, vessel, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus_the(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_z, size); CHECKERRQ(MAP_FATAL_61); + + /* plut epsilon sequence */ + success = increment_the_dof_by_delta(u_type, vessel, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus_the(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_z, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE fd_psi_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Domain* domain = other_type->object; + Vessel* vessel = &domain->vessel; + + MAP_BEGIN_ERROR_LOG; + + /* minus epsilon sequence */ + success = increment_psi_dof_by_delta(u_type, vessel, -epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_plus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_plus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_plus_psi(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_plus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_z, size); CHECKERRQ(MAP_FATAL_61); + + /* plut epsilon sequence */ + success = increment_psi_dof_by_delta(u_type, vessel, epsilon, size); CHECKERRQ(MAP_FATAL_61); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + success = set_force_minus(y_type->Fx, force->fx, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fy, force->fy, size); CHECKERRQ(MAP_FATAL_61); + success = set_force_minus(y_type->Fz, force->fz, size); CHECKERRQ(MAP_FATAL_61); + success = set_moment_minus_psi(u_type, y_type, vessel, force->mx, force->my, force->mz, epsilon, size); CHECKERRQ(MAP_FATAL_61); + // success = set_moment_minus(y_type, vessel, force->mx, force->my, force->mz, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->x, original_x, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->y, original_y, size); CHECKERRQ(MAP_FATAL_61); + success = restore_original_displacement(u_type->z, original_z, size); CHECKERRQ(MAP_FATAL_61); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + + +MAP_ERROR_CODE calculate_stiffness(double* K, Fd* force, const double delta, const int size) +{ + int i = 0; + + for (i=0 ; i<size ; i++) { + K[0] += (force->fx[i]/(2*delta)); + K[1] += (force->fy[i]/(2*delta)); + K[2] += (force->fz[i]/(2*delta)); + K[3] += (force->mx[i]/(2*delta)); + K[4] += (force->my[i]/(2*delta)); + K[5] += (force->mz[i]/(2*delta)); + }; + return MAP_SAFE; +}; + + + + + +MAP_ERROR_CODE set_moment_plus(const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + + for (i=0 ; i<size ; i++) { + rx = (vessel->xi[i]);// - vessel->ref_origin.x.value); + ry = (vessel->yi[i]);// - vessel->ref_origin.y.value); + rz = (vessel->zi[i]);// - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + + /* cross product: + * \mathbf{m}=\mathbf{r} \times \mathbf{F} + */ + mx[i] += ((-Fz*ry) - (-Fy*rz)); + my[i] += ((-Fx*rz) - (-Fz*rx)); + mz[i] += ((-Fy*rx) - (-Fx*ry)); + }; + return MAP_SAFE; +}; + + + + +MAP_ERROR_CODE set_moment_minus(const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + + for (i=0 ; i<size ; i++) { + /* @todo: this is not consistent with set_moment_minus_2... + * ensure moments are in the global frame + */ + rx = (vessel->xi[i]);// - vessel->ref_origin.x.value); + ry = (vessel->yi[i]);// - vessel->ref_origin.y.value); + rz = (vessel->zi[i]);// - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + + /* cross product: + * \mathbf{m}=\mathbf{r} \times \mathbf{F} + */ + mx[i] -= ((-Fz*ry) - (-Fy*rz)); + my[i] -= ((-Fx*rz) - (-Fz*rx)); + mz[i] -= ((-Fy*rx) - (-Fx*ry)); + }; + return MAP_SAFE; +} + + +MAP_ERROR_CODE set_moment_minus_phi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double phi = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] -= m1; + my[i] -= m2*cos(phi+epsilon) - m3*sin(phi+epsilon); + mz[i] -= m2*sin(phi+epsilon) + m3*cos(phi+epsilon); + // mx[i] -= ((-y_type->Fz[i]*ry) - (-y_type->Fy[i]*rz)); + // my[i] -= ((-y_type->Fx[i]*rz) - (-y_type->Fz[i]*rx)); + // mz[i] -= ((-y_type->Fy[i]*rx) - (-y_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_moment_plus_phi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double phi = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + /* @todo: forces are in global frame. Make sure everything is consistent. Should also add + * reference origin. This needs to be converted to the global frame to be consistent with + * uType. + */ + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] += m1; + my[i] += m2*cos(phi+epsilon) - m3*sin(phi+epsilon); + mz[i] += m2*sin(phi+epsilon) + m3*cos(phi+epsilon); + // mx[i] += ((-output_type->Fz[i]*ry) - (-output_type->Fy[i]*rz)); + // my[i] += ((-output_type->Fx[i]*rz) - (-output_type->Fz[i]*rx)); + // mz[i] += ((-output_type->Fy[i]*rx) - (-output_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_moment_minus_the(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double the = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] -= (m1*cos(the+epsilon) + m3*sin(the+epsilon)); + my[i] -= m2; + mz[i] -= (-m1*sin(the+epsilon) + m3*cos(the+epsilon)); + // mx[i] -= ((-y_type->Fz[i]*ry) - (-y_type->Fy[i]*rz)); + // my[i] -= ((-y_type->Fx[i]*rz) - (-y_type->Fz[i]*rx)); + // mz[i] -= ((-y_type->Fy[i]*rx) - (-y_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_moment_plus_the(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double the = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + /* @todo: forces are in global frame. Make sure everything is consistent. Should also add + * reference origin. This need s to be converted to the global frame to be consistent with + * uType. + */ + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] += (m1*cos(the+epsilon) + m3*sin(the+epsilon)); + my[i] += m2; + mz[i] += (-m1*sin(the+epsilon) + m3*cos(the+epsilon)); + // mx[i] += ((-output_type->Fz[i]*ry) - (-output_type->Fy[i]*rz)); + // my[i] += ((-output_type->Fx[i]*rz) - (-output_type->Fz[i]*rx)); + // mz[i] += ((-output_type->Fy[i]*rx) - (-output_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; + + + +MAP_ERROR_CODE set_moment_minus_psi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double psi = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] -= (m1*cos(psi+epsilon) - m2*sin(psi+epsilon)); + my[i] -= (m1*sin(psi+epsilon) + m2*cos(psi+epsilon)); + mz[i] -= m3; + // mx[i] -= ((-y_type->Fz[i]*ry) - (-y_type->Fy[i]*rz)); + // my[i] -= ((-y_type->Fx[i]*rz) - (-y_type->Fz[i]*rx)); + // mz[i] -= ((-y_type->Fy[i]*rx) - (-y_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_moment_plus_psi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size) +{ + int i = 0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + double Fx = 0.0; + double Fy = 0.0; + double Fz = 0.0; + double m1 = 0.0; + double m2 = 0.0; + double m3 = 0.0; + double psi = vessel->orientation.phi.value; + + for (i=0 ; i<size ; i++) { + /* @todo: forces are in global frame. Make sure everything is consistent. Should also add + * reference origin. This need s to be converted to the global frame to be consistent with + * uType. + */ + rx = u_type->x[i];// (vessel->xi[i] - vessel->ref_origin.x.value); + ry = u_type->y[i];// (vessel->yi[i] - vessel->ref_origin.y.value); + rz = u_type->z[i];// (vessel->zi[i] - vessel->ref_origin.z.value); + Fx = y_type->Fx[i]; + Fy = y_type->Fy[i]; + Fz = y_type->Fz[i]; + m1 = ((-Fz*ry) - (-Fy*rz)); + m2 = ((-Fx*rz) - (-Fz*rx)); + m3 = ((-Fy*rx) - (-Fx*ry)); + mx[i] += (m1*cos(psi+epsilon) - m2*sin(psi+epsilon)); + my[i] += (m1*sin(psi+epsilon) + m2*cos(psi+epsilon)); + mz[i] += m3; + // mx[i] += ((-output_type->Fz[i]*ry) - (-output_type->Fy[i]*rz)); + // my[i] += ((-output_type->Fx[i]*rz) - (-output_type->Fz[i]*rx)); + // mz[i] += ((-output_type->Fy[i]*rx) - (-output_type->Fx[i]*ry)); + }; + return MAP_SAFE; +}; diff --git a/OpenFAST/modules/map/src/lineroutines.h b/OpenFAST/modules/map/src/lineroutines.h new file mode 100644 index 000000000..e927af29c --- /dev/null +++ b/OpenFAST/modules/map/src/lineroutines.h @@ -0,0 +1,225 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _LINEROUTINES_H +#define _LINEROUTINES_H + + +#include "map.h" + + +/** + * success = incremenet_x_dof_by_delta(uType, -epsilon); + */ +MAP_ERROR_CODE increment_dof_by_delta(double* u_type, const double delta, const int size); + + +/** + * success = restore_original_displacement(uType->x, xOriginal, N); + */ +MAP_ERROR_CODE restore_original_displacement(double* u_ype, const double* initial_value, const int size); + + +/** + * success = reset_force_to_zero(yType, N); + */ +MAP_ERROR_CODE reset_force_to_zero(double* fx, double* fy, double* fz, double* mx, double* my, double* mz, const int size); + + +/** + * success = set_force_plus(yType->Fx, fx, N); + */ +MAP_ERROR_CODE set_force_minus(const double* in_force, double* force, const int size); + + +/** + * success = set_force_plus(yType->Fx, fx, N); + */ +MAP_ERROR_CODE set_force_plus(const double* in_force, double* force, const int size); + + +/** + * + */ +MAP_ERROR_CODE update_outer_loop_inputs(double* input, MAP_ConstraintStateType_t* z_type, const int size, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * + */ +MAP_ERROR_CODE update_outer_loop_residuals(double* residual, MAP_OtherStateType_t* other_type, const int size, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * success = set_moment_minus(yType, vessel, mx, my, mz, N) + */ +MAP_ERROR_CODE set_moment_minus(const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const int size); + + +MAP_ERROR_CODE set_moment_plus(const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const int size); + + +MAP_ERROR_CODE set_moment_minus_phi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); +MAP_ERROR_CODE set_moment_plus_phi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); +MAP_ERROR_CODE set_moment_minus_the(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); +MAP_ERROR_CODE set_moment_plus_the(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); +MAP_ERROR_CODE set_moment_minus_psi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); +MAP_ERROR_CODE set_moment_plus_psi(const MAP_InputType_t* u_type, const MAP_OutputType_t* y_type, const Vessel* vessel, double* mx, double* my, double* mz, const double epsilon, const int size); + + +MAP_ERROR_CODE increment_phi_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size); + + +MAP_ERROR_CODE increment_the_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size); + + +MAP_ERROR_CODE increment_psi_dof_by_delta(MAP_InputType_t* u_type, const Vessel* vessel, const double delta, const int size); + + +MAP_ERROR_CODE fd_x_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE fd_y_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE fd_z_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_pos, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE fd_phi_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE fd_the_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE fd_psi_sequence(MAP_OtherStateType_t* other_type, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, Fd* force, const double epsilon, const int size, const double* original_x, const double* original_y, const double* original_z, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE calculate_stiffness(double* K, Fd* force, const double delta, const int size); + +/** + * sets cable excursions (l and h) and reference frame psi rotation + */ +MAP_ERROR_CODE set_line_variables_pre_solve(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * set: alpha, alpha at anchor, H, V and T at anchor, T at fairlead + */ +MAP_ERROR_CODE set_line_variables_post_solve(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + +double set_vertical_excursion(Line* line); +double set_horizontal_excursion(Line* line); + + +/** + * 'psi' is the angle between the line x-axis (local frame) and X-axis (global frame). This essentially produces this rotation matrix: + * + * \mathbf{R}(\psi) = \begin{bmatrix} + * \cos\psi & -\sin\psi & 0 \\ + * \sin\psi & \cos\psi & 0 \\ + * 0 & 0 & 1 + * \end{bmatrix} + * + * 1) first find psi - the angle of rotation between the line frame and the global reference frame + * 2) r_j = fairlead displacement + * 3) r_i = anchor displacement + * 4) cos^{-1}( dot( (r_j-r_i) , (u_i) ) / ( norm(r_j-r_i) ) ) + */ +MAP_ERROR_CODE set_psi(Line* line, char* map_msg, MAP_ERROR_CODE* ierr); + + +MAP_ERROR_CODE reset_node_force_to_zero(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * Initialized omega (weight per unit length) and cross-section area of a cable. The formula is + * + * A=\pi*\frac{radius^{2}}{4} + * \omega=g*(\mu-A*\rho_{seawater}) + * + * @acceses: none + * @calledby: mapcall_msqs_init( ) + */ +MAP_ERROR_CODE set_line_initial_guess(Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +MAP_ERROR_CODE solve_linear_spring_cable(Line* line, char* map_msg, MAP_ERROR_CODE* ierr); + +/** + * MAP_InputType_t* uType, + * MAP_ConstraintStateType_t* zType, + * MAP_OtherStateType_t* otherType, + * MAP_OutputType_t* yType, + */ +MAP_ERROR_CODE node_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr); + +MAP_ERROR_CODE newton_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE krylov_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr); + +MAP_ERROR_CODE line_solve_sequence(Domain* domain, MAP_ParameterType_t* p_type, const float time, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE solve_line(Domain* domain, const float time, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Determine maximum line length before double-backing occurs + * @details Called by {@link solve_line} to make sure the line is not double- + * backing on itself. In the extreme case, the cable resembles an + * 'L' shape. When the rule is violated, the upper tipe of the 'L' + * bends to the left. A violation of the algebrais equations happens. + * You can disregard double-backing error checking by raising the + * 'omit_contact' element flag. + * Double backing is present when: + * $L_{u} >= l - \frac{EA}{\omega} + \sqrt{(\frac{EA}{W}^2) + 2*h*\frac{EA}{W}}; + * This is an adaptation from the following Fortran code: + * <pre> + * ELSEIF ( W > 0.0_DbKi ) THEN ! .TRUE. when the line will sink in fluid + * LMax = XF - EA/W + SQRT( (EA/W)*(EA/W) + 2.0_DbKi*ZF*EA/W ) ! Compute the maximum stretched length of the line with seabed interaction beyond which the line would have to double-back on itself; here the line forms an "L" between the anchor and fairlead (i.e. it is horizontal along the seabed from the anchor, then vertical to the fairlead) + * IF ( ( L >= LMax ) .AND. ( CB >= 0.0_DbKi ) ) & ! .TRUE. if the line is as long or longer than its maximum possible value with seabed interaction + * CALL ProgAbort ( ' Unstretched mooring line length too large. '// & + * ' Routine Catenary() cannot solve quasi-static mooring line solution.' ) + * ENDIF + * </pre> + * @param line, the line structure to be checked + * @param contact_flag, flag to ignore the double-backing check + * @param map_msg, error message + * @param ierr, error code + * @see solve_line() + * @return MAP error code + */ +MAP_ERROR_CODE check_maximum_line_length(Line* line, const bool contact_flag, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * call immediately after set_line_variables_post_solve(); this added H and V + */ +MAP_ERROR_CODE calculate_node_sum_force(Domain* domain, MAP_ParameterType_t* p_type); + + + +/** + * increment sum force value by (f) if node is fairlead; (-f) is node is anchor. + */ +void add_to_sum_fx(Node* node, const double fx); + + +/** + * increment sum force value by (f) if node is fairlead; (-f) is node is anchor. + */ +void add_to_sum_fy(Node* node, const double fy); + + +/** + * increment sum force value by (f) if node is fairlead; (-f) is node is anchor. + */ +void add_to_sum_fz(Node* node, const double fz); + + +#endif /* _LINEROUTINES_H */ diff --git a/OpenFAST/modules/map/src/lmroutines.cc b/OpenFAST/modules/map/src/lmroutines.cc new file mode 100644 index 000000000..23f575376 --- /dev/null +++ b/OpenFAST/modules/map/src/lmroutines.cc @@ -0,0 +1,20 @@ +/**************************************************************** + * Copyright (C) 2014 * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ diff --git a/OpenFAST/modules/map/src/lmroutines.hpp b/OpenFAST/modules/map/src/lmroutines.hpp new file mode 100644 index 000000000..fe255c83f --- /dev/null +++ b/OpenFAST/modules/map/src/lmroutines.hpp @@ -0,0 +1,47 @@ +/**************************************************************** + * Copyright (C) 2014 * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _LMCONTAINER_H +#define _LMCONTAINER_H + + +#include "simclist/simclist.h" + +// #include "Line.hpp" +// #include "Connection.hpp" + +// #include <vector> +// #include <string> +// #include <stdlib.h> + + +/* Using a link list for LineList and ConnectList avoids the standard + * library vectors. C and C++ stuff can be completely kept separate + * this way. + */ +struct LMContainer_t { + list_t LineList; // vector<Line> LineList; + list_t ConnectList; // vector<Connection> ConnectList; +}; typedef struct LMContainer_t LMContainer; + + +#endif /* _LMCONTAINER_H */ diff --git a/OpenFAST/modules/map/src/makefile b/OpenFAST/modules/map/src/makefile new file mode 100644 index 000000000..c8d824692 --- /dev/null +++ b/OpenFAST/modules/map/src/makefile @@ -0,0 +1,89 @@ +# Copyright (C) 2014 mdm +# map[dot]plus[dot]plus[dot]help[at]gmail +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +MAP_VER:=1.20.10 + +BITS = -m64 +PLATFORM = $(shell uname -s) +VPATH = cminpack:simclist:bstring:lapack + + +ifeq ($(OS),Windows_NT) + DEL_CMD = del + LIB_EXT = dll + CFLAGS = $(BITS) -g -std=c99 -DMAP_DLL_EXPORTS -DCMINPACK_NO_DLL -DNDEBUG -D_WINDOWS -D_USRDLL -D_MINGW + LDFLAGS = $(BITS) -g -shared -Wl,--export-all-symbols + LIB_FLAGS := +else + PLATFORM = $(shell uname -s) + DEL_CMD = rm -rf + GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always) + + ifeq ($(PLATFORM),Darwin) + LIB_EXT = dylib + CC_TOOLS = clang + CFLAGS = -g -O1 -fno-omit-frame-pointer -fPIC -D DEBUG -Icminpack -Isimclist + LDFLAGS = -g -dynamiclib + LIB_FLAGS := -lm + else ifeq ($(PLATFORM),Linux) + LIB_EXT = so + CC_TOOLS = gcc + #CFLAGS = -g -O1 -fsanitize=address -fno-omit-frame-pointer -fPIC -D DEBUG -DGITVERSION=\"$(GIT_VERSION)\" -Icminpack -Isimclist + #CFLAGS = -g -fPIC -std=c99 -Wuninitialized -Wall -D DEBUG -DGITVERSION=\"$(GIT_VERSION)\" + CFLAGS = $(BITS) -g -fPIC -std=c99 -D DEBUG -DGITVERSION=\"$(GIT_VERSION)\" -D WITH_LAPACK + LDFLAGS = $(BITS) -g -shared -llapacke + LIB_FLAGS := -lm -llapacke + endif +endif + +DEBUG = +OBJ = lmder.o \ + dpmpar.o \ + lmpar.o \ + qrsolv.o \ + enorm.o \ + enorm_u.o \ + qrfac.o \ + simclist.o \ + bstrlib.o \ + bstraux.o \ + freedata.o \ + mapinit.o \ + maperror.o \ + lineroutines.o \ + numeric.o \ + outputstream.o \ + mapapi.o \ + lmroutines.o \ + jacobian.o \ + residual.o \ + + +all : $(OBJ) + $(CC_TOOLS) $(LDFLAGS) -o libmap-$(MAP_VER).$(LIB_EXT) $(DEBUG) $(OBJ) $(LIB_FLAGS) + +.c.o : + $(CC_TOOLS) -c $(CFLAGS) $< + +clean: + $(DEL_CMD) *.$(LIB_EXT) *.o *~ + +memcheck: + valgrind --tool=memcheck --leak-check=yes python -E -tt ./main.py diff --git a/OpenFAST/modules/map/src/map.f90 b/OpenFAST/modules/map/src/map.f90 new file mode 100644 index 000000000..4d4f43de4 --- /dev/null +++ b/OpenFAST/modules/map/src/map.f90 @@ -0,0 +1,1599 @@ +! /**************************************************************** +! * Copyright (C) 2014 mdm * +! * map[dot]plus[dot]plus[dot]help[at]gmail * +! * * +! * Licensed to the Apache Software Foundation (ASF) under one * +! * or more contributor license agreements. See the NOTICE file * +! * distributed with this work for additional information * +! * regarding copyright ownership. The ASF licenses this file * +! * to you 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 MAP + + USE MAP_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + PUBLIC :: MAP_Init + PUBLIC :: MAP_UpdateStates + PUBLIC :: MAP_CalcOutput + PUBLIC :: MAP_JacobianPInput + PUBLIC :: MAP_GetOP + PUBLIC :: MAP_End + PUBLIC :: MAP_Restart + + + INTERFACE ! BEGIN: Interface to external C functions + ! Initalize Initialization Input object + FUNCTION MAP_InitInput_Create(msg,err) RESULT( this ) BIND( C, name="MAP_InitInput_Create" ) + IMPORT + TYPE(C_ptr) :: this + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: msg + INTEGER(KIND=C_INT) :: err + END FUNCTION MAP_InitInput_Create + + FUNCTION MAP_OtherState_Create(msg,err) RESULT( this ) BIND( C, name="MAP_OtherState_Create" ) + IMPORT + TYPE(C_ptr) :: this + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: msg + INTEGER(KIND=C_INT) :: err + END FUNCTION MAP_OtherState_Create + + END INTERFACE + + ! ========== initalize_map_base ====== <----------------------------------------------------------+ + ! Initializes states ! | + INTERFACE ! | + SUBROUTINE MAP_Initialize_Base(FC_u , & ! | + FC_p , & ! | + FC_x , & ! | + FC_z , & ! | + FC_O , & ! | + FC_y , & ! | + FC_InitOut) & ! | + bind(C,name='map_initialize_msqs_base') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_InitOutputType_C) :: FC_InitOut ! | + TYPE(MAP_InputType_C) :: FC_u ! | + TYPE(MAP_ParameterType_C) :: FC_p ! | + TYPE(MAP_ContinuousStateType_C) :: FC_x ! | + TYPE(MAP_DiscreteStateType_C) :: FC_xd ! | + TYPE(MAP_ConstraintStateType_C) :: FC_z ! | + TYPE(MAP_OtherStateType_C) :: FC_O ! | + TYPE(MAP_OutputType_C) :: FC_y ! | + END SUBROUTINE MAP_Initialize_Base ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_GetHdrString ====== <---------------------------------------------------------+ + ! ! | + ! Get the string information (label) of all the outputs MAP is providing the FAST glue code ! | + INTERFACE ! | + SUBROUTINE MAP_Get_Header_String(FC_int, FC_string, FC_other) & ! | + BIND(C,name='map_get_header_string') ! | + IMPORT ! | + IMPLICIT NONE ! | + INTEGER(KIND=C_INT) :: FC_int ! | + TYPE(MAP_OtherStateType_C) :: FC_other ! | + TYPE(C_PTR), DIMENSION(FC_int) :: FC_string ! | + END SUBROUTINE MAP_Get_Header_String ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_ModifyHdrUntString ====== <------------------------------------------------------+ + ! ! | + ! Gets the units of all the outputs MAP is providing to the FAST glue code ! | + INTERFACE ! | + SUBROUTINE MAP_Get_Unit_String(FC_int, FC_string, FC_other) & ! | + BIND(C,name='map_get_unit_string') ! | + IMPORT ! | + IMPLICIT NONE ! | + INTEGER(KIND=C_INT) :: FC_int ! | + TYPE(MAP_OtherStateType_C) :: FC_other ! | + TYPE(C_PTR), DIMENSION(FC_int) :: FC_string ! | + END SUBROUTINE MAP_Get_Unit_String ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetGravity ====== <--------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetGravity(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! The idea is to use the gravity constant as defined by FAST, rather than inputing ! | + ! something indenpendent of it. Numerical errors can generate is g (in units of [Nm/s^2] ! | + ! is not consistent among modules. ! | + INTERFACE ! | + SUBROUTINE MAP_set_gravity(interf, val) bind(C,name='map_set_gravity') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_ParameterType_C) :: interf ! | + REAL(C_DOUBLE), VALUE :: val ! | + END SUBROUTINE MAP_set_gravity ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetDepth ====== <----------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetDepth(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! The idea is to use the gravity constant as defined by FAST, rather than inputing ! | + ! something indenpendent of it. Numerical errors can generate is g (in units of [Nm/s^2] ! | + ! is not consistent among modules. ! | + INTERFACE ! | + SUBROUTINE MAP_set_depth(interf, val) BIND(C,name='map_set_sea_depth') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_ParameterType_C) :: interf ! | + REAL(C_DOUBLE), VALUE :: val ! | + END SUBROUTINE MAP_set_depth ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_set_summary_file_name ====== <---------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetSummaryFilename(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + INTERFACE ! | + SUBROUTINE MAP_set_summary_file_name(interf,msg,err) & ! | + BIND(C,name='map_set_summary_file_name') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE( MAP_InitInputType_C ) interf ! | + CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(INOUT) :: msg ! | + INTEGER(KIND=C_INT) :: err ! | + END SUBROUTINE MAP_set_summary_file_name ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetDensity ====== <--------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetDensity(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! Sets the density of seawater [kg/m^3] according to what is being used in HydroDyn/FAST ! | + INTERFACE ! | + SUBROUTINE MAP_set_density(interf, val) BIND(C,name='map_set_sea_density') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_ParameterType_C) :: interf ! | + REAL(C_DOUBLE), VALUE :: val ! | + END SUBROUTINE MAP_set_density ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetCableLibraryData ====== <-----------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetCableLibaryData(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! Pases strings from the "LINE DICTIONARY" porition of the MPA input file to the C++ ! | + ! data structure. ! | + INTERFACE ! | + SUBROUTINE MAP_SetCableLibraryData(interf) BIND(C,name='map_add_cable_library_input_text') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_InitInputType_C) :: interf ! | + END SUBROUTINE MAP_SetCableLibraryData ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetNodeData ====== <-------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetNodeData(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! Pases strings from the "NOE PROPERTIES" porition of the MPA input file to the C++ ! | + ! data structure. ! | + INTERFACE ! | + SUBROUTINE MAP_SetNodeData(interf) BIND(C,name='map_add_node_input_text') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_InitInputType_C) :: interf ! | + END SUBROUTINE MAP_SetNodeData ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetElementData ====== <----------------------------------------------------------+ + ! ! | + ! Calls C function "MAP_SetElementData(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! Pases strings from the "ELEMENT PROPERTIES" porition of the MPA input file to the C++ ! | + ! data structure. ! | + INTERFACE ! | + SUBROUTINE MAP_SetElementData(interf) BIND(C,name='map_add_line_input_text') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE( MAP_InitInputType_C ) :: interf ! | + END SUBROUTINE MAP_SetElementData ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MAP_SetSolverOption ====== <---------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_SetCableLibaryData(MAP_InitInputType)" in MAP_FortranBinding.cpp. ! | + ! Pases strings from the "SOLVER OPTIONS" porition of the MPA input file to the C++ ! | + ! data structure. ! | + INTERFACE ! | + SUBROUTINE MAP_SetSolverOptions(interf) BIND(C,name='map_add_options_input_text') ! | + IMPORT ! | + IMPLICIT NONE ! | + TYPE(MAP_InitInputType_C) :: interf ! | + END SUBROUTINE MAP_SetSolverOptions ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MSQS_Init ====== <-------------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_MSQS_Init(...)" in MAP_FortranBinding.cpp. ! | + ! Initializes the model ! | + INTERFACE ! | + SUBROUTINE MSQS_Init(FC_InitInp, & ! | + FC_u , & ! | + FC_p , & ! | + FC_x , & ! | + FC_xd , & ! | + FC_z , & ! | + FC_O , & ! | + FC_y , & ! | + FC_InitOut, & ! | + err , & ! | + msg) & ! | + BIND(C,name='map_init') ! | + IMPORT ! | + IMPLICIT NONE ! | + INTEGER(KIND=C_INT) :: err ! | + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: msg ! | + TYPE(MAP_InitInputType_C) :: FC_InitInp ! | + TYPE(MAP_InitOutputType_C) :: FC_InitOut ! | + TYPE(MAP_InputType_C) :: FC_u ! | + TYPE(MAP_ParameterType_C) :: FC_p ! | + TYPE(MAP_ContinuousStateType_C) :: FC_x ! | + TYPE(MAP_DiscreteStateType_C) :: FC_xd ! | + TYPE(MAP_ConstraintStateType_C) :: FC_z ! | + TYPE(MAP_OtherStateType_C) :: FC_O ! | + TYPE(MAP_OutputType_C) :: FC_y ! | + END SUBROUTINE MSQS_Init ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MSQS_UpdateStates ====== <-----------------------------------------------------------+ + ! ! | + ! Calls C function "mapcall_msqs_update_states(...)" in MAP_FortranBinding.cpp. ! | + ! Calculates the new fairlead forces based on an updated fairlead displacement ! | + INTERFACE ! | + SUBROUTINE MSQS_UpdateStates(time , & ! | + n , & ! | + FC_u , & ! | + FC_p , & ! | + FC_x , & ! | + FC_xd, & ! | + FC_z , & ! | + FC_O , & ! | + err , & ! | + msg) & ! | + BIND(C,name='map_update_states') ! | + IMPORT ! | + IMPLICIT NONE ! | + REAL(KIND=C_FLOAT), VALUE :: time ! | + INTEGER(KIND=C_INT), VALUE :: n ! | + INTEGER(KIND=C_INT) :: err ! | + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: msg ! | + TYPE(MAP_InputType_C) :: FC_u ! | + TYPE(MAP_ParameterType_C) :: FC_p ! | + TYPE(MAP_ContinuousStateType_C) :: FC_x ! | + TYPE(MAP_DiscreteStateType_C) :: FC_xd ! | + TYPE(MAP_ConstraintStateType_C) :: FC_z ! | + TYPE(MAP_OtherStateType_C) :: FC_O ! | + END SUBROUTINE MSQS_UpdateStates ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MSQS_CalcOutput ====== <-------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_MSQS_CalcOutput(...)" in MAP_FortranBinding.cpp. ! | + ! Calculates the outputs ! | + INTERFACE ! | + SUBROUTINE MSQS_CalcOutput( time , & ! | + FC_u , & ! | + FC_p , & ! | + FC_x , & ! | + FC_xd , & ! | + FC_z , & ! | + FC_O , & ! | + FC_y , & ! | + err , & ! | + msg ) & ! | + BIND(C,name='map_calc_output') ! | + IMPORT ! | + IMPLICIT NONE ! | + REAL(KIND=C_FLOAT) , VALUE :: time ! | + INTEGER(KIND=C_INT) :: err ! | + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: msg ! | + TYPE(MAP_InputType_C) :: FC_u ! | + TYPE(MAP_ParameterType_C) :: FC_p ! | + TYPE(MAP_ContinuousStateType_C) :: FC_x ! | + TYPE(MAP_DiscreteStateType_C) :: FC_xd ! | + TYPE(MAP_ConstraintStateType_C) :: FC_z ! | + TYPE(MAP_OtherStateType_C) :: FC_O ! | + TYPE(MAP_OutputType_C) :: FC_y ! | + END SUBROUTINE MSQS_CalcOutput !MSQS_CalcOutput ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + ! ========== MSQS_End ====== <--------------------------------------------------------------------+ + ! ! | + ! Calls C function "MAPCALL_MSQS_Init(...)" in MAP_FortranBinding.cpp. ! | + ! Initializes the model ! | + INTERFACE ! | + SUBROUTINE MSQS_End( FC_u , & ! | + FC_p , & ! | + FC_x , & ! | + FC_xd , & ! | + FC_z , & ! | + FC_O , & ! | + FC_y , & ! | + err , & ! | + msg ) & ! | + BIND(C,name='map_end') ! | + IMPORT ! | + IMPLICIT NONE ! | + INTEGER(KIND=C_INT) :: err ! | + CHARACTER(KIND=C_CHAR),DIMENSION(1024) :: msg ! | + TYPE( MAP_InputType_C ) FC_u ! | + TYPE( MAP_ParameterType_C ) FC_p ! | + TYPE( MAP_ContinuousStateType_C ) FC_x ! | + TYPE( MAP_DiscreteStateType_C ) FC_xd ! | + TYPE( MAP_ConstraintStateType_C ) FC_z ! | + TYPE( MAP_OtherStateType_C ) FC_O ! | + TYPE( MAP_OutputType_C ) FC_y ! | + END SUBROUTINE MSQS_End ! | + END INTERFACE ! -------+ + !========================================================================================================== + + + CONTAINS + + !========== MAP_Restart ====== <----------------------------------------------------------------------+ + SUBROUTINE MAP_Restart( u, p, x, xd, z, other, y, ErrStat, ErrMsg ) + ! This routine is used on restart (in place of MAP_Init). It is used to get other%C_obj%object from stored values and to make sure the allocated + ! memory is aligned in a way the MAP DLL is happy with. + + TYPE( MAP_InputType ), INTENT(INOUT) :: u ! INTENT( OUT) : An initial guess for the input; input mesh must be defined + TYPE( MAP_ParameterType ), INTENT(INOUT) :: p ! INTENT( OUT) : Parameters + TYPE( MAP_ContinuousStateType ), INTENT(INOUT) :: x ! INTENT( OUT) : Initial continuous states + TYPE( MAP_DiscreteStateType ), INTENT(INOUT) :: xd ! INTENT( OUT) : Initial discrete states + TYPE( MAP_ConstraintStateType ), INTENT(INOUT) :: z ! INTENT( OUT) : Initial guess of the constraint states + TYPE( MAP_OtherStateType ), INTENT(INOUT) :: other ! INTENT( OUT) : Initial other/optimization states + TYPE( MAP_OutputType ), INTENT(INOUT) :: y ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + TYPE( MAP_InitInputType ) :: InitInp ! INTENT(IN ) : Input data for initialization routine + TYPE( MAP_InitOutputType ) :: InitOut ! Output for initialization routine + TYPE( MAP_InputType ) :: u_tmp ! INTENT( OUT) : An initial guess for the input; input mesh must be defined + TYPE( MAP_ContinuousStateType ) :: x_tmp ! INTENT( OUT) : Initial continuous states + TYPE( MAP_DiscreteStateType ) :: xd_tmp ! INTENT( OUT) : Initial discrete states + TYPE( MAP_ConstraintStateType ) :: z_tmp ! INTENT( OUT) : Initial guess of the constraint states + TYPE( MAP_OtherStateType ) :: other_tmp ! INTENT( OUT) : Initial other/optimization states + TYPE( MAP_OutputType ) :: y_tmp ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + + INTEGER(KIND=C_INT) :: status_from_MAP + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(1024) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Restart' + + + ErrStat = ErrID_None + ErrMsg = "" + + status_from_MAP = 0 + message_from_MAP = " " + + ! copy the data so we can use it later (need to allocate these original types inside the MAP DLL so we don't get errors on deallocation later) + CALL MAP_CopyInput( u, u_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyDiscState( xd, xd_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyConstrState( z, z_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyOtherState(other,other_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyOutput( y, y_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + ! now we'll clear out these types for use in the MAP DLL + CALL MAP_DestroyInput( u, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyContState( x, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyDiscState( xd, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyConstrState( z, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOtherState(other, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOutput( y, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + + InitInp%C_obj%object = MAP_InitInput_Create(message_from_MAP,status_from_MAP) ! routine in MAP dll + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + other%C_obj%object = MAP_OtherState_Create(message_from_MAP,status_from_MAP) ! routine in MAP dll + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + InitInp%C_Obj%summary_file_name = "" + InitInp%C_Obj%summary_file_name(1) = C_NULL_CHAR + CALL MAP_set_summary_file_name(InitInp%C_obj, message_from_map, status_from_MAP); + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2); + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL MAP_Initialize_Base(u%C_obj, p%C_obj, x%C_obj, z%C_obj, other%C_obj, y%C_obj, InitOut%C_obj) ! routine in MAP dll + + CALL map_set_input_file_contents(InitInp, p) + + + ! This binds MSQS_Init function in C++ with Fortran + CALL MSQS_Init(InitInp%C_obj , & + u%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z%C_obj , & + other%C_obj , & + y%C_obj , & + InitOut%C_obj , & + status_from_MAP , & + message_from_MAP ) + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2); + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! make sure the C and Fortran sides are consistent before deleting them on the Fortran side: + CALL MAP_C2Fary_CopyInput(u, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyContState(x, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyDiscState(xd, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyConstrState(z, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOtherState(other, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOutput(y, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! copy the data back so we can use it + CALL MAP_CopyInput( u_tmp, u, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyContState( x_tmp, x, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyDiscState( xd_tmp, xd, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyConstrState( z_tmp, z, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyOtherState(other_tmp,other, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_CopyOutput( y_tmp, y, MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + ! now we'll destroy these temporary types + CALL MAP_DestroyInput( u_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyContState( x_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyDiscState( xd_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyConstrState( z_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOtherState(other_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOutput( y_tmp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + CALL MAP_DestroyInitInput( InitInp, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyInitOutput( InitOut, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + END SUBROUTINE MAP_Restart + + !========== MAP_Init ====== <----------------------------------------------------------------------+ + SUBROUTINE MAP_Init( InitInp, u, p, x, xd, z, other, y, Interval, InitOut, ErrStat, ErrMsg ) + IMPLICIT NONE + TYPE( MAP_InitInputType ), INTENT(INOUT) :: InitInp ! INTENT(IN ) : Input data for initialization routine + TYPE( MAP_InputType ), INTENT( OUT) :: u ! INTENT( OUT) : An initial guess for the input; input mesh must be defined + TYPE( MAP_ParameterType ), INTENT( OUT) :: p ! INTENT( OUT) : Parameters + TYPE( MAP_ContinuousStateType ), INTENT( OUT) :: x ! INTENT( OUT) : Initial continuous states + TYPE( MAP_DiscreteStateType ), INTENT( OUT) :: xd ! INTENT( OUT) : Initial discrete states + TYPE( MAP_ConstraintStateType ), INTENT( OUT) :: z ! INTENT( OUT) : Initial guess of the constraint states + TYPE( MAP_OtherStateType ), INTENT( OUT) :: other ! INTENT( OUT) : Initial other/optimization states + TYPE( MAP_OutputType ), INTENT( OUT) :: y ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + REAL(DbKi), INTENT(INOUT) :: Interval ! Coupling interval in seconds: the rate that Output is the actual coupling interval + TYPE( MAP_InitOutputType ), INTENT(INOUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER(KIND=C_INT) :: status_from_MAP + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(1024) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Init' + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: n + REAL(ReKi) :: Pos(3) + INTEGER(IntKi) :: NumNodes + + ErrStat = ErrID_None + ErrMsg = "" + + status_from_MAP = 0 + message_from_MAP = " " + i = 0 + N = 0 + NumNodes = 0 + p%dt = interval + p%C_obj%dt = p%dt + + CALL NWTC_Init( ) ! Initialize the NWTC Subroutine Library + + InitInp%C_obj%object = MAP_InitInput_Create(message_from_MAP,status_from_MAP) ! routine in MAP dll + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + other%C_obj%object = MAP_OtherState_Create(message_from_MAP,status_from_MAP) ! routine in MAP dll + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_Initialize_Base(u%C_obj, p%C_obj, x%C_obj, z%C_obj, other%C_obj, y%C_obj, InitOut%C_obj) ! routine in MAP dll + +IF (ErrStat >= AbortErrLev) RETURN + + ! Set the environmental properties: + ! depth = water depth [m] + ! gravity = the acceleration due to gravity [N] -or- [kg*m/s^2] + ! sea_density = density of sea water [kg/m^3] + ! coupled_to_FAST = flag letting MAP know it is coupled to FAST. MAP won't create the output file when .TRUE. + InitInp%C_Obj%gravity = InitInp%gravity + InitInp%C_Obj%sea_density = InitInp%sea_density + InitInp%C_Obj%depth = -InitInp%depth !BJJ: Why is this the negative? I have to put a negative in the glue code, too. Let's get rid of both of them + + N = LEN_TRIM(InitInp%summary_file_name) + DO i = 1,N + InitInp%C_Obj%summary_file_name(i) = InitInp%summary_file_name(i:i) + END DO !bjj: add C_NULL_CHAR??? + + ! Set the gravity constant, water depth, and sea density in MAP. + ! This calls functions in MAP_FortranBinding.cpp + CALL MAP_set_gravity(p%C_obj, InitInp%C_Obj%gravity) + CALL MAP_set_depth(p%C_obj, InitInp%C_Obj%depth) + CALL MAP_set_density(p%C_obj, InitInp%C_Obj%sea_density) + CALL MAP_set_summary_file_name(InitInp%C_obj, message_from_map, status_from_MAP); + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2); + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! Read the MAP input file, and pass the arguments to the C++ sructures. + ! @note : this call the following C function in MAP_FortranBinding.cpp + CALL map_read_input_file_contents(InitInp%file_name , InitInp, p, ErrStat2) + CALL SetErrStat(ErrStat2,"Cannot read the MAP input file.", ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ! This binds MSQS_Init function in C++ with Fortran + CALL MSQS_Init(InitInp%C_obj , & + u%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z%C_obj , & + other%C_obj , & + y%C_obj , & + InitOut%C_obj , & + status_from_MAP , & + message_from_MAP ) + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2); + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ! ========== MAP F2C (literally, Fortran to C) conversion =========================================== + ! Now call the C2FC_ routines for the INTENT( OUT) C objects + ! MAP Inputs + ! MAP Constraint State + ! MAP Other State + ! MAP Output State + ! MAP parameters (no arrays, but still want to copy scalars for pack/unpack) [packs only the Fortran side] + ! ======================================================================================================= + + CALL MAP_C2Fary_CopyConstrState(z, ErrStat2, ErrMsg2); + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOutput(y, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOtherState(other, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyInput(u, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyParam(p, ErrStat2, ErrMsg2); ! copy these scalars for pack/unpack reasons + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL MAP_Get_Output_Headers(InitOut, other) + + !========== MAP Mesh initialization ====== <--------------------------+ + ! get header information for the FAST output file ! | + NumNodes = u%C_obj%X_Len ! | + ! Create the input mesh ! | + CALL MeshCreate(BlankMesh=u%PtFairDisplacement ,IOS= COMPONENT_INPUT, NNodes=NumNodes, TranslationDisp=.TRUE.,ErrStat=ErrStat2, ErrMess=ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + ! | + DO i = 1,NumNodes ! | + Pos(1) = u%X(i) ! | + Pos(2) = u%Y(i) ! | + Pos(3) = u%Z(i) ! | + ! | + CALL MeshPositionNode(u%PtFairDisplacement,i,Pos,ErrStat2,ErrMsg2)! | + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + ! | + CALL MeshConstructElement(u%PtFairDisplacement, ELEMENT_POINT, ErrStat2, ErrMsg2, i) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + END DO ! | + ! | + CALL MeshCommit ( u%PtFairDisplacement, ErrStat2, ErrMsg2 ) ! | + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + ! | + ! now, copy the input PtFairDisplacement to output ! | + ! PtFairleadLoad to complete this ! | + CALL MeshCopy ( SrcMesh = u%PtFairDisplacement , & ! | + DestMesh = y%PtFairleadLoad , & ! | + CtrlCode = MESH_SIBLING , & ! | + IOS = COMPONENT_OUTPUT , & ! | + Force = .TRUE. , & ! | + ErrStat = ErrStat2 , & ! | + ErrMess = ErrMsg2 ) ! | + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + ! | + ! End mesh initialization ! -------+ + !============================================================================== + + + + ! Program version + N = LEN(InitOut%version) + DO i=1,N + IF (InitOut%C_obj%version(i).EQ.C_NULL_CHAR) THEN + InitOut%version(i:N) = ' ' + EXIT + ELSE + InitOut%version(i:i) = InitOut%C_obj%version(i) + END IF + END DO + + ! Program compiling data + N = LEN(InitOut%compilingData) + DO i=1,N + IF (InitOut%C_obj%compilingData(i).EQ.C_NULL_CHAR) THEN + InitOut%compilingData(i:N) = ' ' + EXIT + ELSE + InitOut%compilingData(i:i) = InitOut%C_obj%compilingData(i) + END IF + END DO + + InitOut%Ver = ProgDesc('MAP++',TRIM(InitOut%version),TRIM(InitOut%compilingData)) + p%numOuts = 0 + if ( allocated(InitOut%WriteOutputHdr) ) THEN + p%numOuts = size(InitOut%WriteOutputHdr) + allocate( y%WriteOutput(p%numOuts), STAT=N) + if (N/=0) call SetErrStat(ErrID_Fatal, 'Failed to allocate y%WriteOutput',ErrStat, ErrMsg, RoutineName) + end if + + !............................................................................................ + ! Initialize Jacobian information: + !............................................................................................ + if (InitInp%LinInitInp%Linearize) then + call map_Init_Jacobian( p, u, y, InitOut, ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + END SUBROUTINE MAP_Init ! -------+ + !========================================================================================================== + + + !========== MAP_UpdateStates ====== <-------------------------------------------------------------+ + SUBROUTINE MAP_UpdateStates( t, n, u, utimes, p, x, xd, z, O, ErrStat, ErrMsg) + REAL(DbKi) , INTENT(IN ) :: t + INTEGER(IntKi) , INTENT(IN ) :: n + REAL(DbKi) , INTENT(IN ) :: utimes(:) + TYPE( MAP_InputType ) , INTENT(INOUT) :: u(:) ! INTENT(IN ) + TYPE( MAP_ParameterType ) , INTENT(INOUT) :: p ! INTENT(IN ) + TYPE( MAP_ContinuousStateType ) , INTENT(INOUT) :: x ! INTENT(INOUT) + TYPE( MAP_DiscreteStateType ) , INTENT(INOUT) :: xd ! INTENT(INOUT) + TYPE( MAP_ConstraintStateType ) , INTENT(INOUT) :: z ! INTENT(INOUT) + TYPE( MAP_OtherStateType ) , INTENT(INOUT) :: O ! INTENT(INOUT) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER(KIND=C_INT) :: status_from_MAP + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP + REAL(KIND=C_FLOAT) :: time + INTEGER(KIND=C_INT) :: interval + INTEGER(IntKi) :: i + TYPE(MAP_InputType) :: u_interp ! Inputs at t + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(1024) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_UpdateStates' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! create space for arrays/meshes in u_interp + CALL MAP_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + CALL MAP_Input_ExtrapInterp(u, utimes, u_interp, t+p%dt, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + ! set the time and coupling interval to something readable by MAP (using KIND=C_INT/C_FLOAT instead + ! of the native IntKi/DbKi format in FAST) + time = t + interval = n + + status_from_MAP = 0 + message_from_MAP = ' ' + + ! Copy the mesh input to the MAP C types + ! @marco: the Position field is fixed in the initialization routine. TranslationDisp is the displacement from the original position. + ! if you need the absolute position, add them: u_interp%PtFairDisplacement(1)%TranslationDisp(1,i) + u_interp%PtFairleadDisplacement(1)%Pos + ! Copy the mesh input to the MAP C types + DO i = 1,u_interp%PtFairDisplacement%NNodes + u_interp%X(i) = u_interp%PtFairDisplacement%Position(1,i) + u_interp%PtFairDisplacement%TranslationDisp(1,i) + u_interp%Y(i) = u_interp%PtFairDisplacement%Position(2,i) + u_interp%PtFairDisplacement%TranslationDisp(2,i) + u_interp%Z(i) = u_interp%PtFairDisplacement%Position(3,i) + u_interp%PtFairDisplacement%TranslationDisp(3,i) + END DO + + CALL MSQS_UpdateStates( time , & + interval , & + u_interp%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z%C_obj , & + O%C_obj , & + status_from_MAP , & + message_from_MAP ) + + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + CALL MAP_DestroyInput(u_interp, ErrStat2, ErrMsg2) + + + END SUBROUTINE MAP_UpdateStates ! -------+ + !========================================================================================================== + + + !========== MAP_CalcOutput ====== <---------------------------------------------------------------+ + SUBROUTINE MAP_CalcOutput( t, u, p, x, xd, z, O, y, ErrStat, ErrMsg ) + REAL(DbKi) , INTENT(IN ) :: t + TYPE( MAP_InputType ) , INTENT(INOUT) :: u ! INTENT(IN ) + TYPE( MAP_ParameterType ) , INTENT(INOUT) :: p ! INTENT(IN ) + TYPE( MAP_ContinuousStateType ) , INTENT(INOUT) :: x ! INTENT(IN ) + TYPE( MAP_DiscreteStateType ) , INTENT(INOUT) :: xd ! INTENT(IN ) + TYPE( MAP_ConstraintStateType ) , INTENT(INOUT) :: z ! INTENT(IN ) + TYPE( MAP_OtherStateType ) , INTENT(INOUT) :: O ! INTENT(INOUT) + TYPE( MAP_OutputType ) , INTENT(INOUT) :: y ! INTENT(INOUT) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat + CHARACTER(*) , INTENT( OUT) :: ErrMsg + + ! Local variables + INTEGER(KIND=C_INT) :: status_from_MAP + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP + REAL(KIND=C_FLOAT) :: time + integer :: i + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(1024) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_CalcOutput' + + + ErrStat = ErrID_None + ErrMsg = "" + + time = t + message_from_MAP = ' ' + + DO i = 1,u%PtFairDisplacement%NNodes + u%X(i) = u%PtFairDisplacement%Position(1,i) + u%PtFairDisplacement%TranslationDisp(1,i) + u%Y(i) = u%PtFairDisplacement%Position(2,i) + u%PtFairDisplacement%TranslationDisp(2,i) + u%Z(i) = u%PtFairDisplacement%Position(3,i) + u%PtFairDisplacement%TranslationDisp(3,i) + END DO + + CALL MSQS_CalcOutput(time , & + u%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z%C_obj , & + O%C_obj , & + y%C_obj , & + status_from_MAP , & + message_from_MAP ) + + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + + IF (ALLOCATED(y%WriteOutput) .AND. ASSOCIATED(y%WrtOutput) ) y%WriteOutput = REAL( y%WrtOutput, ReKi ) + + ! Copy the MAP C output types to the native Fortran mesh output types + DO i = 1,y%ptFairleadLoad%NNodes + y%ptFairleadLoad%Force(1,i) = -y%FX(i) + y%ptFairleadLoad%Force(2,i) = -y%FY(i) + y%ptFairleadLoad%Force(3,i) = -y%FZ(i) + END DO + + + END SUBROUTINE MAP_CalcOutput ! -------+ + !========================================================================================================== + + + !========== MAP_End ====== <----------------------------------------------------------------------+ + SUBROUTINE MAP_End(u, p, x, xd, z, other, y, ErrStat , ErrMsg) + TYPE( MAP_InputType ) , INTENT(INOUT) :: u + TYPE( MAP_ParameterType ) , INTENT(INOUT) :: p + TYPE( MAP_ContinuousStateType ) , INTENT(INOUT) :: x + TYPE( MAP_DiscreteStateType ) , INTENT(INOUT) :: xd + TYPE( MAP_ConstraintStateType ) , INTENT(INOUT) :: z + TYPE( MAP_OtherStateType ) , INTENT(INOUT) :: other + TYPE( MAP_OutputType ) , INTENT(INOUT) :: y + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + ! Locals + INTEGER(KIND=C_INT) :: status_from_MAP=0 + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP = ' ' +! INTEGER(IntKi) :: i=0 + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(1024) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_End' + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL MSQS_End( u%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z%C_obj , & + other%C_obj , & + y%C_obj , & + status_from_MAP , & + message_from_MAP ) + CALL MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + + ! bjj: we need to nullify Fortran pointers that were associated with C_F_POINTER in the Init routine: + ! + CALL MAP_C2Fary_CopyConstrState(z, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOutput(y, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyOtherState(other, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyInput(u, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_C2Fary_CopyParam(p, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + + ! Destroy Fortran MAP types + ! Anything allocated in C should be destroyed in C. Calling these functions only destroys mesh types. + CALL MAP_DestroyInput(u, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyParam(p , ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyContState(x, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyDiscState(xd, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyConstrState(z, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOtherState(other, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + CALL MAP_DestroyOutput(y, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + END SUBROUTINE MAP_End ! -------+ + !========================================================================================================== + + + ! ========== MAP_ReadInputFileContents ====== <---------------------------------------------------+ + ! ! | + ! Reads the MAP input files. Assumes the MAP input file is formated as demonstrated with the + ! MAP distruction archives. Any changes to the format, and this read function may fail. + SUBROUTINE map_read_input_file_contents(file, InitInp, p, ErrStat) + TYPE(MAP_ParameterType), INTENT(INOUT) :: p + TYPE(MAP_InitInputType), INTENT(INOUT) :: InitInp + CHARACTER(255) , INTENT(IN ) :: file + INTEGER(IntKi), INTENT( OUT) :: ErrStat + INTEGER :: success + INTEGER :: index_begn + INTEGER :: index_cabl + INTEGER :: index_node + INTEGER :: index_elem + INTEGER :: index_optn + INTEGER :: iLine + CHARACTER(255) :: line + + INTEGER :: Un + CHARACTER(1024) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'map_read_input_file_contents' + + ErrStat = ErrID_None + + index_begn=1 + index_cabl=0 + index_node=0 + index_elem=0 + index_optn=0 + + iLine=0 + + p%InputLineType = "" +! p%InputLines = "" + + ! Open the MAP input file + Un = -1 + CALL GetNewUnit( Un, ErrStat, ErrMsg ) + CALL OpenFInpFile ( Un, file, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev )RETURN + + + ! Read the contents of the MAP input file + DO + READ( Un , '(A)' , IOSTAT=success ) line ! read one line of the MAP input file + + ! we are no longer reading the MAP input file if we + ! reached the end + IF ( success.NE.0 ) EXIT + + + ! populate the cable library parameter + IF ( index_begn.EQ.1 ) THEN + index_cabl = index_cabl + 1 + IF ( index_cabl.GE.4 ) THEN + IF ( line(1:1).EQ."-" ) THEN + index_begn=2 + ELSE + iLine = iLine + 1 + if (iLine > SIZE(p%InputLines)) THEN + CALL WrScr("Too many lines in MAP input file.") + CLOSE ( Un ) + ErrStat = ErrID_Fatal + RETURN + end if + + p%InputLines(iLine) = line + p%InputLineType(iLine) = 'C' + END IF + END IF + END IF + + + ! populate the node parameter + IF ( index_begn.EQ.2 ) THEN + index_node = index_node + 1 + IF ( index_node.GE.4 ) THEN + IF ( line(1:1).EQ."-" ) THEN + index_begn=3 + ELSE + + iLine = iLine + 1 + if (iLine > SIZE(p%InputLines)) THEN + CALL WrScr("Too many lines in MAP input file.") + CLOSE ( Un ) + ErrStat = ErrID_Fatal + RETURN + end if + + p%InputLines(iLine) = line + p%InputLineType(iLine) = 'N' + END IF + END IF + END IF + + + ! populate the element parameter + IF ( index_begn.EQ.3 ) THEN + index_elem = index_elem + 1 + IF ( index_elem.GE.4 ) THEN + IF ( line(1:1).EQ."-" ) THEN + index_begn=4 + ELSE + + iLine = iLine + 1 + if (iLine > SIZE(p%InputLines)) THEN + CALL WrScr("Too many lines in MAP input file.") + CLOSE ( Un ) + ErrStat = ErrID_Fatal + RETURN + end if + + p%InputLines(iLine) = line + p%InputLineType(iLine) = 'E' + END IF + END IF + END IF + + + ! populate the solver options + IF ( index_begn.EQ.4 ) THEN + index_optn = index_optn + 1 + IF ( index_optn.GE.4 ) THEN + IF ( line(1:1).NE."!" ) THEN + + iLine = iLine + 1 + if (iLine > SIZE(p%InputLines)) THEN + CALL WrScr("Too many lines in MAP input file.") + ErrStat = ErrID_Fatal + CLOSE ( Un ) + RETURN + end if + + p%InputLines(iLine) = line + p%InputLineType(iLine) = 'S' + END IF + END IF + END IF + END DO + + ! Close the MAP input file ! | + CLOSE( Un ) + + CALL map_set_input_file_contents(InitInp, p) + + END SUBROUTINE map_read_input_file_contents ! -------+ + !========================================================================================================== + SUBROUTINE map_set_input_file_contents(InitInp, p) + TYPE(MAP_InitInputType), INTENT(INOUT) :: InitInp + TYPE(MAP_ParameterType), INTENT(INOUT) :: p + INTEGER :: iLine + + + DO iLine = 1,SIZE(p%InputLines) + IF ( LEN_TRIM(p%InputLineType(1)) == 0 ) EXIT + + IF ( LEN_TRIM(p%InputLines(iLine)) + 2 <= SIZE(InitInp%C_obj%library_input_str) ) THEN ! make sure there is a C_NULL_CHAR on this string + + SELECT CASE( p%InputLineType(iLine) ) + CASE('C') + InitInp%C_obj%library_input_str = TRANSFER(TRIM(p%InputLines(iLine))//" "//C_NULL_CHAR, InitInp%C_obj%library_input_str ) + CALL MAP_SetCableLibraryData(InitInp%C_obj) + CASE ('N') + InitInp%C_obj%node_input_str = TRANSFER(TRIM(p%InputLines(iLine))//" "//C_NULL_CHAR, InitInp%C_obj%node_input_str ) + CALL MAP_SetNodeData(InitInp%C_obj) + CASE ('E') + InitInp%C_obj%line_input_str = TRANSFER(TRIM(p%InputLines(iLine))//" "//C_NULL_CHAR, InitInp%C_obj%line_input_str ) + CALL MAP_SetElementData(InitInp%C_obj) + CASE ('S') + InitInp%C_obj%option_input_str = TRANSFER(TRIM(p%InputLines(iLine))//" "//C_NULL_CHAR, InitInp%C_obj%option_input_str ) + CALL MAP_SetSolverOptions(InitInp%C_obj) + END SELECT + + END IF + END DO + + END SUBROUTINE map_set_input_file_contents +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine map::map_init_jacobian is consistant with this routine! +SUBROUTINE map_Perturb_u( p, n, perturb_sign, u, du ) + + TYPE(map_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(map_InputType) , INTENT(INOUT) :: u !< perturbed map inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + + + ! local variables + integer :: fieldIndx + integer :: node + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + fieldIndx = p%LinParams%Jac_u_indx(n,2) + node = p%LinParams%Jac_u_indx(n,3) + du = p%LinParams%du + u%PtFairDisplacement%TranslationDisp (fieldIndx,node) = u%PtFairDisplacement%TranslationDisp (fieldIndx,node) + du * perturb_sign + +END SUBROUTINE map_Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine map::map_init_jacobian is consistant with this routine! +SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) + + TYPE(map_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(map_OutputType) , INTENT(IN ) :: y_p !< map outputs at \f$ u + \Delta u \f$ or \f$ x + \Delta x \f$ (p=plus) + TYPE(map_OutputType) , INTENT(IN ) :: y_m !< map outputs at \f$ u - \Delta u \f$ or \f$ x - \Delta x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta = \Delta u \f$ or \f$ delta = \Delta x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial x_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + + ! local variables: + + integer(IntKi) :: indx_first ! index indicating next value of dY to be filled + logical :: Mask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + integer(IntKi) :: k + + indx_first = 1 + if ( y_p%ptFairleadLoad%Committed ) then + call PackLoadMesh_dY(y_p%ptFairleadLoad, y_m%ptFairleadLoad, dY, indx_first) + end if + + do k=1,p%numOuts + dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) + end do + + + + dY = dY / (2.0_R8Ki*delta) + +END SUBROUTINE Compute_dY +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing corresponding linearization routines ! +SUBROUTINE MAP_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) + + TYPE(map_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(map_InputType) , INTENT(IN ) :: u !< inputs + TYPE(map_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(map_InitOutputType) , INTENT(INOUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MAP_Init_Jacobian' + + ! local variables: + INTEGER(IntKi) :: i, j, k, index, index_next, index_last, nu, i_meshField, m, meshFieldCount + REAL(R8Ki) :: perturb_t, perturb + REAL(R8Ki) :: ScaleLength + LOGICAL :: FieldMask(FIELDMASK_SIZE) ! flags to determine if this field is part of the packing + + ErrStat = ErrID_None + ErrMsg = "" + + !...................................... + ! init linearization outputs: + !...................................... + + ! determine how many outputs there are in the Jacobians + p%LinParams%Jac_ny = 0 + if ( y%ptFairleadLoad%Committed ) then + p%LinParams%Jac_ny = y%ptFairleadLoad%NNodes * 3 ! 3 Forces, no Moments, at each node on the fairlead loads mesh + end if + + p%LinParams%Jac_ny = p%LinParams%Jac_ny + p%numOuts ! WriteOutput values + + !................. + ! set linearization output names: + !................. + call AllocAry(InitOut%LinInitOut%LinNames_y, p%LinParams%Jac_ny, 'LinNames_y', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + index_next = 1 + if ( y%ptFairleadLoad%Committed ) then + index_last = index_next + call PackLoadMesh_Names(y%ptFairleadLoad, 'FairleadLoads', InitOut%LinInitOut%LinNames_y, index_next) + end if + + index_last = index_next + do i=1,p%numOuts + InitOut%LinInitOut%LinNames_y(i+index_next-1) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) + end do + + + !...................................... + ! init linearization inputs: + !...................................... + + + ! determine how many inputs there are in the Jacobians + nu = 0; + if ( u%PtFairDisplacement%Committed ) then + nu = nu + u%PtFairDisplacement%NNodes * 3 ! 3 TranslationDisp at each node + end if + + ! note: all other inputs are ignored + + !.................... + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! (see hydrodyn::map_perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index of the acceleration/load field + ! column 3 is the node + !.................... + + !............... + ! MAP input mappings stored in p%Jac_u_indx: + !............... + call AllocAry(p%LinParams%Jac_u_indx, nu, 3, 'p%LinParams%Jac_u_indx', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + index = 1 + meshFieldCount = 0 + if ( u%PtFairDisplacement%Committed ) then + !Module/Mesh/Field: u%PtFairDisplacement%TranslationDisp = 1; + i_meshField = 1 + do i=1,u%PtFairDisplacement%NNodes + do j=1,3 + p%LinParams%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%PtFairDisplacement%{TranslationDisp} = m + p%LinParams%Jac_u_indx(index,2) = j !index: j + p%LinParams%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + meshFieldCount = meshFieldCount + 1 + end if + + !................ + ! input perturbations, du: + !................ + + p%LinParams%du = 0.2_R8Ki*D2R * max(p%depth,1.0_R8Ki) ! translation input scaling ! u%PtFairDisplacement%TranslationDisp + + !................ + ! names of the columns, InitOut%LinNames_u: + !................ + call AllocAry(InitOut%LinInitOut%LinNames_u, nu, 'LinNames_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AllocAry(InitOut%LinInitOut%IsLoad_u, nu, 'IsLoad_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + InitOut%LinInitOut%IsLoad_u(:) = .false. ! MAP's inputs are NOT loads + + index = 1 + if ( u%PtFairDisplacement%Committed ) then + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + call PackMotionMesh_Names(u%PtFairDisplacement, 'PtFairDisplacement', InitOut%LinInitOut%LinNames_u, index, FieldMask=FieldMask) + end if + +END SUBROUTINE MAP_Init_Jacobian + +SUBROUTINE MAP_JacobianPInput( t, u, p, x, xd, z, OtherState, y, ErrStat, ErrMsg, dYdu ) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(map_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(map_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(map_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at operating point + TYPE(map_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states at operating point + TYPE(map_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states at operating point + TYPE(map_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at operating point + TYPE(map_OutputType), INTENT(INOUT) :: 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. + 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 the inputs (u) [intent in to avoid deallocation] + + + ! local variables + INTEGER(KIND=C_INT) :: status_from_MAP + CHARACTER(KIND=C_CHAR), DIMENSION(1024) :: message_from_MAP + REAL(KIND=C_FLOAT) :: time + INTEGER(KIND=C_INT) :: interval + + TYPE(map_OutputType) :: y_p + TYPE(map_OutputType) :: y_m + TYPE(map_ConstraintStateType) :: z_perturb + TYPE(map_InputType) :: u_perturb + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, j, NN, offsetI, offsetJ + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'map_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + time = t + interval = t / p%dt + + if ( present( dYdu ) ) then + + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate dYdu if necessary + if (.not. allocated(dYdu)) then + call AllocAry(dYdu, p%LinParams%Jac_ny, size(p%LinParams%Jac_u_indx,1), 'dYdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call cleanup() + return + end if + end if + + + do i=1,size(p%LinParams%Jac_u_indx,1) + + ! get u_op + delta u + call map_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + call map_Perturb_u( p, i, 1, u_perturb, delta ) + + call MAP_CopyConstrState( z, z_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + DO j = 1,u_perturb%PtFairDisplacement%NNodes + u_perturb%X(j) = u_perturb%PtFairDisplacement%Position(1,j) + u_perturb%PtFairDisplacement%TranslationDisp(1,j) + u_perturb%Y(j) = u_perturb%PtFairDisplacement%Position(2,j) + u_perturb%PtFairDisplacement%TranslationDisp(2,j) + u_perturb%Z(j) = u_perturb%PtFairDisplacement%Position(3,j) + u_perturb%PtFairDisplacement%TranslationDisp(3,j) + END DO + + ! compute constraint state for u_op + delta u + call MSQS_UpdateStates( time , & + interval , & + u_perturb%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z_perturb%C_obj , & + OtherState%C_obj , & + status_from_MAP , & + message_from_MAP ) + + call MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + + + ! compute y at u_op + delta u + call map_CalcOutput( t, u_perturb, p, x, xd, z_perturb, OtherState, y, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! We need to do this copy inside the loop because MAP++ (in the c-code) requires that the output data structure be y, which was used when MAP++ was initialized. + call map_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get u_op - delta u + call map_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! Minus perturbation + call map_Perturb_u( p, i, -1, u_perturb, delta ) + + call MAP_CopyConstrState( z, z_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + + DO j = 1,u_perturb%PtFairDisplacement%NNodes + u_perturb%X(j) = u_perturb%PtFairDisplacement%Position(1,j) + u_perturb%PtFairDisplacement%TranslationDisp(1,j) + u_perturb%Y(j) = u_perturb%PtFairDisplacement%Position(2,j) + u_perturb%PtFairDisplacement%TranslationDisp(2,j) + u_perturb%Z(j) = u_perturb%PtFairDisplacement%Position(3,j) + u_perturb%PtFairDisplacement%TranslationDisp(3,j) + END DO + + ! compute constraint state for u_op + delta u + call MSQS_UpdateStates( time , & + interval , & + u_perturb%C_obj , & + p%C_obj , & + x%C_obj , & + xd%C_obj , & + z_perturb%C_obj , & + OtherState%C_obj , & + status_from_MAP , & + message_from_MAP ) + + call MAP_ERROR_CHECKER(message_from_MAP,status_from_MAP,ErrMsg2,ErrStat2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg, RoutineName) + + ! compute y at u_op - delta u + call map_CalcOutput( t, u_perturb, p, x, xd, z_perturb, OtherState, y, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! we shouldn't have any errors about allocating memory here so I'm not going to return-on-error until later + + ! We need to do this copy inside the loop because MAP++ (in the c-code) requires that the output data structure be y, which was used when MAP++ was initialized. + call map_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get central difference: note: assumes delta is equivalent for both perturb_u calls. + call Compute_dY( p, y_p, y_m, delta, dYdu(:,i) ) + + end do + end if + call cleanup() + +contains + subroutine cleanup() + call map_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call map_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call map_DestroyConstrState( z_perturb, ErrStat2, ErrMsg2 ) + call map_DestroyInput( u_perturb, ErrStat2, ErrMsg2 ) + + end subroutine cleanup +END SUBROUTINE MAP_JacobianPInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE MAP_GetOP( t, u, p, x, xd, z, OtherState, y, ErrStat, ErrMsg, u_op, y_op) + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(map_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(map_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(map_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(map_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(map_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(map_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(map_OutputType), INTENT(IN ) :: y !< Output at operating point + 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 + + + + INTEGER(IntKi) :: i, k, index, nu + INTEGER(IntKi) :: ny + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'map_GetOP' + TYPE(map_ContinuousStateType) :: dx !< derivative of continuous states at operating point + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + !LIN-TODO: Need to review and implement this routine per plan. Do not understand how to implement at the moment, GJH. + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + !.................................. + IF ( PRESENT( u_op ) ) THEN + + if (.not. allocated(u_op)) then + + nu = size(p%LinParams%Jac_u_indx,1) + + call AllocAry(u_op, nu,'u_op',ErrStat2,ErrMsg2) ! + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + + end if + + Mask = .false. + Mask(MASKID_TRANSLATIONDISP) = .true. + + index = 1 + if ( u%PtFairDisplacement%Committed ) then + call PackMotionMesh(u%PtFairDisplacement, u_op, index, FieldMask=Mask) + end if + + END IF + + !.................................. + if ( PRESENT( y_op ) ) then + + if (.not. allocated(y_op)) then + call AllocAry(y_op, p%LinParams%Jac_ny, 'y_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + index = 1 + if ( y%ptFairleadLoad%Committed ) then + call PackLoadMesh(y%ptFairleadLoad, y_op, index) + end if + + index = index - 1 + do i=1,p%numOuts + y_op(i+index) = y%WriteOutput(i) + end do + + end if + +END SUBROUTINE MAP_GetOP + + !========================================================================================================== + + ! ========== MAP_ERROR ====== <-------------------------------------------------------------------+ + ! ! | + ! this is different from MAP_ERROR_CHECKER. MAP_ERROR check internal fortran errors, whereas + ! the former checks errors in the MAP DLL. + SUBROUTINE MAP_ERROR(ErrMsg, ErrStat, string) + CHARACTER(1024), INTENT(INOUT) :: ErrMsg + INTEGER(IntKi), INTENT(INOUT) :: ErrStat + CHARACTER(*), INTENT(IN ) :: string + + IF (ErrStat.NE.ErrID_None) THEN + ErrMsg = TRIM(ErrMsg)//string + END IF + END SUBROUTINE MAP_ERROR ! -------+ + !========================================================================================================== + + + ! ========== MAP_ERROR_CHECKER ====== <-----------------------------------------------------------+ + ! ! | + ! A convenient way to convert C-character arrays into a fortran string. The return argustment + ! is a logical: False if program is safe; True if program fails in the MAP DLL + SUBROUTINE MAP_ERROR_CHECKER(msg, stat, ErrMsg, ErrStat) + CHARACTER(KIND=C_CHAR), DIMENSION(1024), INTENT(INOUT) :: msg + INTEGER(KIND=C_INT), INTENT(INOUT) :: stat + CHARACTER(*), INTENT( OUT) :: ErrMsg + INTEGER(IntKi), INTENT( OUT) :: ErrStat + INTEGER :: i + + ErrStat = ErrID_None + ErrMsg = "" + + IF (stat.NE.0) THEN + + DO i = 1,min(1024,len(ErrMsg)) ! convert c-character array to a fortran character array + IF(msg(i).NE.C_NULL_CHAR) THEN + ErrMsg(i:i) = msg(i) + ELSE + EXIT + END IF + END DO + + IF(stat.EQ.1) THEN ! assign warning levels + ErrStat = ErrID_Warn + ELSE ! only the case of a fatal warning returns true; throws a RETURN + ErrStat = ErrID_Fatal + END IF + END IF + + END SUBROUTINE MAP_ERROR_CHECKER ! -------+ + !========================================================================================================== + + + ! ========== MAP_Get_Output_Headers ====== <-----------------------------------------+ + ! ! | + ! Get te output header for the FAST text file so something like this is printed: + ! l[1] h[1] psi[1] alpha[1] alpha_a[1] + ! [m] [m] [m] [m] [m] + SUBROUTINE MAP_Get_Output_Headers(InitOut, Other) + TYPE(MAP_InitOutputType), INTENT(INOUT) :: InitOut ! Output for initialization routine + TYPE(MAP_OtherStateType), INTENT(INOUT) :: Other + + ! Locals + INTEGER :: i + INTEGER(C_INT) :: numHeaderStr + CHARACTER(16),DIMENSION(:), ALLOCATABLE, TARGET :: strHdrArray ! Hopefully none of the headers are more than 16 characters long + TYPE(C_PTR), DIMENSION(:), ALLOCATABLE :: strHdrPtrs + CHARACTER(15),DIMENSION(:), ALLOCATABLE, TARGET :: strUntArray ! Hopefully none of the headers are more than 15 characters long + TYPE(C_PTR), DIMENSION(:), ALLOCATABLE :: strUntPtrs + + !========== MAP_InitInpInputType ====== <--------------------------+ + ! get header information for the FAST output file + + numHeaderStr = InitOut%C_obj%writeOutputHdr_Len + ALLOCATE(strHdrArray(numHeaderStr+1)) + ALLOCATE(strHdrPtrs (numHeaderStr+1)) + ALLOCATE(strUntArray(numHeaderStr)) + ALLOCATE(strUntPtrs (numHeaderStr)) + ALLOCATE(InitOut%WriteOutputHdr(numHeaderStr)) + ALLOCATE(InitOut%WriteOutputUnt(numHeaderStr)) + + DO i = 1, numHeaderStr + strHdrArray(i) = "None"//C_NULL_CHAR + strUntArray(i) = "None"//C_NULL_CHAR + strHdrPtrs(i) = C_LOC(strHdrArray(i)) + strUntPtrs(i) = C_LOC(strUntArray(i)) + END DO + + CALL MAP_Get_Header_String(numHeaderStr, strHdrPtrs, Other%C_obj) + CALL MAP_Get_Unit_String(numHeaderStr, strUntPtrs, Other%C_obj) + + DO i = 1, numHeaderStr + InitOut%WriteOutputHdr(i) = strHdrArray(i) + CALL RemoveNullChar( InitOut%WriteOutputHdr(i) ) + InitOut%WriteOutputUnt(i) = strUntArray(i) + CALL RemoveNullChar( InitOut%WriteOutputUnt(i) ) + END DO + + DEALLOCATE(strHdrArray) + DEALLOCATE(strHdrPtrs) + DEALLOCATE(strUntArray) + DEALLOCATE(strUntPtrs) + END SUBROUTINE MAP_Get_Output_Headers ! -------+ + !========================================================================================================== + +END MODULE MAP diff --git a/OpenFAST/modules/map/src/map.h b/OpenFAST/modules/map/src/map.h new file mode 100644 index 000000000..ebcc6e59d --- /dev/null +++ b/OpenFAST/modules/map/src/map.h @@ -0,0 +1,465 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _MAP_H +#define _MAP_H + + +#include "mapsys.h" + +#include "simclist/simclist.h" + +#include "bstring/bstrlib.h" + +#include "cminpack/cminpack.h" +#include "cminpack/cminpackP.h" +#include "cminpack/minpack.h" + +#include "MAP_Types.h" +#include "maperror.h" +#include "lmroutines.hpp" + +#ifdef WITH_LAPACK +# include "lapack/lapacke.h" +#endif // WITH_LAPACK + +/** + * @brief Associates the node with a particular type. Fix nodes are anchor points + * (ussually) and cannot move with time. Connect nodes are intermediaries + * connecting two lines. When a connect node is defined, the force-balance + * equation is minimized to obtain the cable profile X, Y, and Z node position + * at connect nodes are associated with constraint types. Vessel nodes attach + * to the platform. X, Y, and Z, node positions are associated with input + * types, and the corresponding fx, fy, and fz forces are the outputs. + * Moments are calculated by the calling program. + */ +typedef enum NodeType_enum { + NONE, /**< */ + FIX, /**< */ + CONNECT, /**< */ + VESSEL /**< */ +} NodeType; + + +/** + * @brief Finite different routine when solving the outer-loop iterations. + * This is also used when the linearization routine is called. + */ +typedef enum FdType_enum { + BACKWARD_DIFFERENCE, /**< */ + CENTRAL_DIFFERENCE, /**< */ + FORWARD_DIFFERENCE /**< */ +} FdType; + + +/** + * @struct SolveType + * @brief Set internally. If a connect node is present in the MAP input + * file, then the solve typeis partitioned. Partitioned describes the + * process of breaking the problem into two blocks: an inner-loop solve + * (where the catenary equations are minimized) and an outer-loop solve + * (where the force-balance equations are minimized). Likewise, when no + * connect nodes are present, the solver type is monolithic and only the + * non-linear catenary equations need to be solved. + */ +typedef enum SolveType_enum { + MONOLITHIC, /**< for MSQS, lines only (no connect nodes) */ + PARTITIONED, /**< for MSQS system with connect nodes */ + LUMPED_MASS /**< for lumped-mass model */ +} SolveType; + + +/** + * @brief Finite-difference structure. This is used locally withint FD routines to conveniently store the + * force and moment when vessel is displaced by epsilon. + */ +struct Fd_t { + double* fx; + double* fy; + double* fz; + double* mx; + double* my; + double* mz; +}; typedef struct Fd_t Fd; + + +/** + * @brief Fundamental MAP type. Unless it is used locally, every variable should be darclared as a VarType + * (or VarTypePtr, described below). The VarType provides convenience for printing variable + * information, such as the units, it's name (such as 'FX[1]' for X-direction node 1 force to the + * output file), and counting references. + */ +struct VarType_t { + bstring units; /**< units for printing information to a summary file or output buffer */ + bstring name; /**< name of the variable. This is used for identifying it in the output buffer */ + double value; /**< the value */ + bool is_fixed; /**< if is_fixed = true, then we are not solving for this variable */ + bool user_initial_guess; /**< if user_initial_guess = true, the user has supplied an initial guess */ + int ref_counter; /**< for ensuring the variable is assigned to one of: input, param, or constraint */ + int id; /**< node or line this value is attached to */ +}; typedef struct VarType_t VarType; + + +/** + * @brief Serves the same function as VarType, but treats value as a pointer. This preserves the FAST integration + * to native Fortran derivived types. Instead of the variable residing in C, the value parameter points + * to a variable allocated in Fortran. This feature is also preserved with Python binding. + */ +struct VarTypePtr_t { + bstring units; /**< units for printing information to a summary file or output buffer */ + bstring name; /**< name of the variable. This is used for identifying it in the output buffer */ + double* value; /**< the value */ + bool is_fixed; /**< If is_fixed = true, then we are not solving for this variable */ + int ref_counter; /**< For ensuring the variable is assigned to one of: input, param, or constraint */ + int id; /**< node or line this value is attached to */ +}; typedef struct VarTypePtr_t VarTypePtr; + + +struct Vector_t { + double x; + double y; + double z; +}; typedef struct Vector_t Vector; + + +struct Point_t { + VarType x; + VarType y; + VarType z; +}; typedef struct Point_t Point; + + +struct PointPtr_t { + VarTypePtr x; + VarTypePtr y; + VarTypePtr z; +}; typedef struct PointPtr_t PointPtr; + + +struct EulerAngle_t { + VarType phi; + VarType the; + VarType psi; +}; typedef struct EulerAngle_t EulerAngle; + + +struct Force_t { + VarType fx; + VarType fy; + VarType fz; +}; typedef struct Force_t Force; + + +struct ForcePtr_t { + VarTypePtr fx; + VarTypePtr fy; + VarTypePtr fz; +}; typedef struct ForcePtr_t ForcePtr; + + +struct ReferencePoint_t { + VarTypePtr* x; + VarTypePtr* y; + VarTypePtr* z; +}; typedef struct ReferencePoint_t ReferencePoint; + + +/** + * @brief Central point where all 'VESSEL' nodes can be displaced. Instead of displacing all nodes individually, the vessel can be displaced, + * then helper functions can be called to displacement the nodes. The vessel only reference 'input' nodes. + */ +struct Vessel_t { + EulerAngle orientation; /**< Vessel orientation [deg]*/ + double* xi; /**< initial node connection point in body frame.This is equal to uType->x at initialization [m] */ + double* yi; /**< initial node connection point in body frame This is equal to uType->y at initialization [m] */ + double* zi; /**< initial node connection point in body frame This is equal to uType->z at initialization [m] */ + Point displacement; /**< User-specified vessel displacement. This is the [m]*/ + Point ref_origin; /**< Center of rotation origin. The moments are taken about this is point. The reference point is with respect to the FAST reference origin (equal to the + * SWL at zero vessel dispalcements) [m]*/ + Force line_sum_force; /**< Sum force of all nodes connecting to the vessel [N] */ +}; typedef struct Vessel_t Vessel; + + + +/** + * @brief References a list of VarType's (in the case of out_list) and VarTypePtr's + * (in the case of out_list_ptr) for output file data streaming. The idea is + * to loop through the list and print the 'value' and 'name[id]' members of + * VarType and VarTypePtr. + * @see + * @todo This really should be made polymorphic so only one variable is needed. + */ +struct OutputList_t{ + list_t out_list; /**< Outputs associated with VarType */ + list_t out_list_ptr; /**< Outputs associated with VarTypePtr */ +}; typedef struct OutputList_t OutputList; + + +typedef struct { + bool gx_pos_flag; + bool gy_pos_flag; + bool gz_pos_flag; + bool gx_anchor_pos_flag; + bool gy_anchor_pos_flag; + bool gz_anchor_pos_flag; + bool gx_force_flag; + bool gy_force_flag; + bool gz_force_flag; + bool H_flag; + bool V_flag; + bool V_anchor_flag; + bool H_anchor_flag; + bool fairlead_tension_flag; + bool anchor_tension_flag; + bool horizontal_excursion_flag; + bool vertical_excursion_flag; + bool azimuth_flag; + bool altitude_flag; + bool altitude_anchor_flag; + bool line_tension_flag; + bool omit_contact; + bool lay_length_flag; + bool damage_time_flag; + bool diagnostics_flag; + bool linear_spring; /**< treat the elastic catenary as a uncompressible linear springs when true */ +} LineOptions; + + +/** + * @brief Defines cable properties for a line. These values are fixed with time and connot change. + */ +struct CableLibrary_t { + double diam; /**< Cable diameter, [m] */ + double mass_density; /**< Cable density in air [kg/m] */ + double EA; /**< Line stiffness [N] */ + double omega; /**< cable weight per length in seawater [N/m] */ + double a; /**< cross-sectional area [m^2] */ + double cb; /**< Cable/seabed friction coefficient [non-dimensional] */ + double cd_i; /**< Internal (structural) damping coefficient [non-dimensional] */ + double ca; /**< Added mass coefficient [non-dimensional] */ + double cd_n; /**< Quadtradice drag coefficient in the cable cross-flow direction [non-dimensional] */ + double cd_t; /**< Tangential drag oefficient [non-dimensional] */ + bstring label; /**< Provides the string a recognizable name (such as 'nylon' or 'steel') */ +}; typedef struct CableLibrary_t CableLibrary; + + +struct Node_t { + PointPtr acceleration; /**< Node accelration; integrated quantity [m/s^2]; used for LM model. Associated with continuous type */ + PointPtr velocity; /**< Node velocity [m/s]; used for LM model. Associated with continuous type */ + PointPtr position_ptr; /**< this is a Ptr because it points to a fortran type */ + NodeType type; + ForcePtr sum_force_ptr; /**< this is a Ptr because it points to a fortran type */ + VarType M_applied; + VarType B_applied; + Force external_force; +}; typedef struct Node_t Node; + + +// struct LMAttributes { +// void* lm_container; /**< container struct in lmroutines.hpp */ +// double* FlineS; /**< retains last solution for when this is called with dT = 0 */ // +// double** rFairtS; /**< fairlead locations ON TURBINE */ // <--------- will be mapped to a Node_t list +// double** rFairRel; /**< fairlead locations relative to platform center */ // <--------- will be mapped to a Node_t list +// double** rFairi; /**< inertial Fairlead Locations */ // <--------- will be mapped to a Node_t list +// double** rdFairi; /**< inertial Fairlead Velocities */ // <--------- will be mapped to a Node_t list +// +// // static vectors to hold line and connection objects! +// // vector< LineProps > LinePropList; // to hold line library types <--------- Moved to the Line_t struct +// // vector< Line > LineList; // global and persistent? <--------- Moved to a container struct in lmroutines.hpp to isolate c++ and c +// // vector< Connection > ConnectList; <--------- Moved to a container struct in lmroutines.hpp to isolate c++ and c +// int nConnects; +// int nLines; +// +// // state vector and stuff +// double* states; /**< pointer to array comprising global state vector */ +// double* newstates; +// int Nx; /**< size of state vector array */ +// +// // more state vector things for rk4 integration +// double* f0; +// double* f1; +// double* f2; +// double* f3; +// double* xt; +// +// int* lineStateIs; /** vector of line starting indices in "states" array */ // vector< int > LineStateIs; +// int closed; // initialize to 0 +// double dt; // FAST time step, @rm +// double dts; /**< mooring line time step */ +// }; typedef struct LMAttributes_t LMAttributes; + + +struct Line_t { + CableLibrary* line_property; /**< line properties */ + // LMAttributes* lm_attributes; /**< Preserves information of the LM model from previous time steps */ + LineOptions options; /**< run-time options flag */ + VarTypePtr H; /**< Horizontal fairlead force in the local cable elemenet frame */ + VarTypePtr V; /**< Vertical fairlead force in the local cable elemenet frame */ + VarType Lu; /**< unstretched cable length [m] */ + bstring label; /**< reference a pre-defined property in the line dictionary */ + double* line_tension; /**< array of line tension along 's' [N] */ + double psi; /**< angle of roation between global X and local x axis [deg] */ + double alpha; /**< angle of inclication [deg] */ + double alpha_at_anchor; /**< angle of inclication at anchor [deg] */ + double l; /**< horizontal cable excursion [m] */ + double Lb; /**< length of line touching the seabed [m] */ + double h; /**< vertical cable excursion [m] */ + double H_at_anchor; /**< Horizontal anchor force in the local cable elemenet frame */ + double V_at_anchor; /**< Vertical anchor force in the local cable elemenet frame */ + double T; /**< Tension magnitude [N] */ + double T_at_anchor; /**< Tension magnitude at anchor [N] */ + double damage_time; /**< time to damage this line and return zero force to the glue code */ + double residual_norm; + double fx_fairlead; + double fy_fairlead; + double fz_fairlead; + double fx_anchor; + double fy_anchor; + double fz_anchor; + list_t elements; /**< LM model elements */ + Node* anchor; /**< Anchor node */ + Node* fairlead; /**< Fairlead node */ + int segment_size; + int diagnostic_type; /**< none=0, first iteration only=2, all iterations otherwise */ + int evals; /**< number of function evaluations */ + int njac_evals; /**< number of function evaluations */ + int converge_reason; /* - info=0 : improper input parameters. + * - info=1 : both actual and predicted relative reductions in the sum of squares are at most ftol. + * - info=2 : relative error between two consecutive iterates is at most xtol. + * - info=3 : conditions for info = 1 and info = 2 both hold. + * - info=4 : the cosine of the angle between fvec and any column of the Jacobian is at most gtol in absolute value. + * - info=5 : number of calls to fcn has reached or exceeded maxfev. + * - info=6 : ftol is too small. No further reduction in the sum of squares is possible. + * - info=7 : xtol is too small. No further improvement in the approximate solution x is possible. + * - info=8 : gtol is too small. fvec is orthogonal to the columns of the Jacobian to machine precision. + */ +}; typedef struct Line_t Line; + + +struct Element_t { + double l; /**< \left \| \mathbf{r}_{1}-\mathbf{r}_{2} \right \| */ + Node* r1; /**< upper node */ + Node* r2; /**< lower node */ +}; typedef struct Element_t Element; + + +struct InnerSolveAttributes_t { + double** node_jac; + double f_tol; + double g_tol; + double x_tol; + double x[2]; /**< array of variables the length of n */ + double fvec[2]; /**< function evaluations (residual) */ + double fjac[4]; /**< jacobian. This is a little convoluted because the jacobian is not an array */ + double wa1[2]; /**< work array of length n */ + double wa2[2]; /**< work array of length n */ + double wa3[2]; /**< work array of length n */ + double wa4[2]; /**< work array of length m */ + double diag[2]; + double qtf[2]; + double factor; + int max_its; + int ldfjac; /**< number of columns in fjac */ + int mode; + int nprint; + int info; + int ipvt[2]; + int m; /**< number of functions */ + int n; /**< number of variables */ +}; typedef struct InnerSolveAttributes_t InnerSolveAttributes; + + + +struct OuterSolveAttributes_t { + FdType fd; + double** AV; /**< for the Krylov accelerator */ + double** V; /**< for the Krylov accelerator */ + double* av; /**< for the Krylov accelerator, rown-major storage for AV */ + double** jac; + double** l; /**< lower triangle matrix in LU */ + double** u; /**< upper triangle matrix in LU */ + double* b; /**< this is the force vector used in x += ([J]^-1)*b */ + double* C; /**< for the Krylov accelerator */ + double* w; /**< for the Krylov accelerator */ + double* q; /**< for the Krylov accelerator */ + double* x; + double* y; + double ds; + double d; + double epsilon; + double norm_error; + double tol; + double coef; + bool pg; + bool krylov_accelerator; + bool powell; + int max_krylov_its; + int max_its; + int iteration_count; +}; typedef struct OuterSolveAttributes_t OuterSolveAttributes; + + +struct DomainOptions_t { + double* repeat_angle; + double integration_dt; /**< Integration time step [sec]. LM model specific */ + double kb_lm; /**< Seabed stiffeness coefficient [N/m]. LM model specific */ + double cb_lm; /**< Seabed damping parameter [N-s/m]. LM model specific */ + bool wave_kinematics; /**< Enable wave kinematics o calculated relative flui velcity. LM model specific */ + bool lm_model; /**< use the lumped-mass model when true */ + int repeat_angle_size; +}; typedef struct DomainOptions_t DomainOptions; + + +struct Domain_t { + InnerSolveAttributes inner_loop; /**< Inner-loop (line level) solver options. Default settings in {@link initialize_solver_data_to_null} */ + OuterSolveAttributes outer_loop; /**< Outer-loop (node level) solver options. Default settings in {@link initialize_model_options_to_defaults} */ + DomainOptions model_options; /**< Contains global model options. Default setting in {@link initialize_model_options_to_defaults} */ + OutputList* y_list; /**< Output stream. Set to null at initialization */ + SolveType MAP_SOLVE_TYPE; /**< Identifies the solver type: single line, partitioned (multisegmented), and lumped-mass/FEA. Initialized in {@link initialize_domain_to_null} + * */ + Vessel vessel; /**< Vessel for the mooring instance. Initialized in {@link initialize_vessel_to_null}. Associated VarType's are set in {@link set_vessel} */ + list_t library; /**< Cable library link list; stores cable properties, e.g., @see CableLibrary_t */ + list_t line; /**< Line link list */ + list_t node; /**< Node link list */ + list_t u_update_list; /**< List to update the references in VarType-associated u_type's in UpdateStates. Used when coupled to FAST */ + void* HEAD_U_TYPE; /**< Checks if the reference to MAP_InputType_t changes */ +}; typedef struct Domain_t Domain; + + +/** + * @details MAP options from parsed input file. Note that MAP does not readon the input file. This is done by the calling program. + * The calling program simply sets library_input_string, node_input_string, line_input_string, and solver_options_string. + * MAP then parses this string and expands them if necessary depending on the '{@link DomainOptions_t}' repeat_angle flag. + */ +struct InitializationData_t { + struct bstrList* library_input_string; /**< library property string from input file. MAP does not read contents from input string; must be done by calling program */ + struct bstrList* node_input_string; /**< raw (non-expanded) node input string. MAP does not read contents from input string; must be done by calling program */ + struct bstrList* line_input_string; /**< raw (non-expanded) line input string(MAP does not read contents from input string; must be done by calling program */ + struct bstrList* solver_options_string; /**< model poptions input string */ + struct bstrList* expanded_node_input_string; /**< full node input string duplicating information in node_input_string when the 'repeat' flag is used */ + struct bstrList* expanded_line_input_string; /**< full line input string duplicating information in nodeLineString when the 'repeat' flag is used */ + bstring summary_file_name; /**< summary file name. Can be set through {@link map_set_summary_file_name()} */ +}; typedef struct InitializationData_t InitializationData; + + +#endif /* _MAP_H */ diff --git a/OpenFAST/modules/map/src/map_glue.f90 b/OpenFAST/modules/map/src/map_glue.f90 new file mode 100644 index 000000000..6f151d673 --- /dev/null +++ b/OpenFAST/modules/map/src/map_glue.f90 @@ -0,0 +1,338 @@ +! /**************************************************************** +! * Copyright (C) 2014 mdm * +! * map[dot]plus[dot]plus[dot]help[at]gmail * +! * * +! * Licensed to the Apache Software Foundation (ASF) under one * +! * or more contributor license agreements. See the NOTICE file * +! * distributed with this work for additional information * +! * regarding copyright ownership. The ASF licenses this file * +! * to you 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. * +! ****************************************************************/ + +PROGRAM Main + + USE MAP_Types + USE MAP + USE NWTC_Library + + IMPLICIT NONE + + INTEGER(IntKi) :: i,j, j_ss ! generic loop counter + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(DbKi) :: dt_global ! fixed/constant global time step + REAL(DbKi) :: t_initial ! time at initialization + REAL(DbKi) :: t_final ! time at simulation end + REAL(DbKi) :: t_global ! global-loop time marker + + INTEGER(IntKi) :: n_t_final ! total number of time steps + INTEGER(IntKi) :: n_t_global ! global-loop time counter + + TYPE (MAP_InitInputType) :: InitInData_MAP + TYPE (MAP_InitOutputType) :: InitOutData_MAP + TYPE (MAP_InputType) :: u_MAP + TYPE (MAP_ParameterType) :: p_MAP + TYPE (MAP_ContinuousStateType) :: x_MAP + TYPE (MAP_DiscreteStateType) :: xd_MAP + TYPE (MAP_ConstraintStateType) :: z_MAP + TYPE (MAP_OtherStateType) :: other_MAP + + + TYPE(MAP_ContinuousStateType) :: x_MAP_pred ! Predicted continuous states + TYPE(MAP_DiscreteStateType) :: xd_MAP_pred ! Predicted discrete states + TYPE(MAP_ConstraintStateType) :: z_MAP_pred ! Predicted constraint states + TYPE(MAP_OtherStateType) :: other_MAP_old ! Other/optimization states (copied for the case of subcycling) + + TYPE (MAP_InputType), ALLOCATABLE :: MAP_Input(:) + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: MAP_InputTimes(:) + + TYPE (MAP_OutputType) :: y_MAP +! REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: MAP_OutputTimes + + INTEGER(IntKi) :: MAP_interp_order ! order of interpolation/extrapolation + + + ! ------------------------------------------------------------------------- + ! Initialization of glue-code time-step variables + ! ------------------------------------------------------------------------- + + t_initial = 0. + t_final = 10.0 + + ! specify time increment; currently, all modules will be time integrated with this increment size + dt_global = 0.5 + n_t_final = ((t_final - t_initial) / dt_global ) - 1 + t_global = t_initial + + ! @bonnie : is this right? What's a good interp order? + ! @marco: the interp order is specified in the FAST input file. It can be 0, 1, or 2 + MAP_interp_order = 0 + + ! MAP: allocate Input and Output arrays; used for interpolation and extrapolation +! Allocate(MAP_InputTimes(MAP_interp_order + 1)) + + ! @bonnie : This is in the FAST developers glue code example, but it's probably not needed here. + ALLOCATE(MAP_Input(MAP_interp_order + 1), MAP_InputTimes(MAP_interp_order + 1), STAT=ErrStat ) + IF (ErrStat /= 0) CALL CheckError(ErrID_Fatal,"Error allocating MAP_Input and MAP_InputTimes.") + + + ! set the MAP input file name and other environment terms. + InitInData_MAP%file_name = "baseline.map" + InitInData_MAP%summary_file_name = "baseline.sum.map" + InitInData_MAP%gravity = 9.81 ! @bonnie : This need to be according to g used in FAST. Positive value + InitInData_MAP%sea_density = 1025 ! @bonnie : This needs to be set according to seawater density in FAST. Positive value + InitInData_MAP%depth = -320 ! @bonnie : This need to be set according to the water depth in FAST. Negative value + ! p_MAP%dt = dt_global ! @bonnie : This is for the glue code to set + + ! call the initialization routine + ! CALL MAP_Init( InitInData_MAP, MAP_Input(1), p_MAP, x_MAP, xd_MAP, z_MAP, OtherSt_MAP, y_MAP, p_FAST%dt_module( MODULE_MAP ), InitOutData_MAP, ErrStat, ErrMsg ) + CALL MAP_Init(InitInData_MAP , & + MAP_Input(1) , & + p_MAP , & + x_MAP , & + xd_MAP , & + z_MAP , & + other_MAP , & + y_MAP , & + dt_global , & + InitOutData_MAP, & + ErrStat , & + ErrMsg ) + IF (ErrStat.NE.0) THEN + CALL WrScr(ErrMsg) + END IF + + CALL DispNVD(InitOutData_MAP%Ver) + + + CALL MAP_DestroyInitInput(InitInData_MAP, ErrStat, ErrMsg) + CALL MAP_DestroyInitOutput(InitOutData_MAP, ErrStat, ErrMsg) + + + DO j = 1, MAP_interp_order + 1 + MAP_InputTimes(j) = t_initial - (j - 1) * dt_global + END DO + + DO j = 2, MAP_interp_order + 1 + CALL MAP_CopyInput (MAP_Input(1), MAP_Input(j), MESH_NEWCOPY, Errstat, ErrMsg) + CALL CheckError( ErrStat, 'Message from MAP_CopyInput (MAP_Input): '//NewLine//ErrMsg ) + END DO + CALL MAP_CopyInput (MAP_Input(1), u_MAP, MESH_NEWCOPY, Errstat, ErrMsg) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL CheckError( ErrStat, 'Message from MAP_CopyInput (u_MAP): '//NewLine//ErrMsg ) + + ! Initialize predicted states for j_pc loop: + CALL MAP_CopyContState ( x_MAP, x_MAP_pred, MESH_NEWCOPY, Errstat, ErrMsg) + CALL CheckError( ErrStat, 'Message from MAP_CopyContState (init): '//NewLine//ErrMsg ) + CALL MAP_CopyDiscState (xd_MAP, xd_MAP_pred, MESH_NEWCOPY, Errstat, ErrMsg) + CALL CheckError( ErrStat, 'Message from MAP_CopyDiscState (init): '//NewLine//ErrMsg ) + CALL MAP_CopyConstrState ( z_MAP, z_MAP_pred, MESH_NEWCOPY, Errstat, ErrMsg) + CALL CheckError( ErrStat, 'Message from MAP_CopyConstrState (init): '//NewLine//ErrMsg ) + + ! IF ( p_FAST%n_substeps( MODULE_MAP ) > 1 ) THEN + ! CALL MAP_CopyOtherState( other_MAP, other_MAP_old, MESH_NEWCOPY, Errstat, ErrMsg) + ! CALL CheckError( ErrStat, 'Message from MAP_CopyOtherState (init): '//NewLine//ErrMsg ) + ! END IF + + + ! ------------------------------------------------------------------------- + ! BEGIN time marching + ! ------------------------------------------------------------------------- + DO n_t_global = 0, n_t_final + t_global = t_initial + dt_global*n_t_global + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Step 1.a: Extrapolate Inputs (gives predicted values at t+dt + ! + ! a) Extrapolate inputs (and outputs -- bjj: output extrapolation not necessary, yet) + ! to t + dt (i.e., t_global_next); will only be used by modules with an implicit dependence on input data. + ! b) Shift "window" of the ModName_Input and ModName_Output + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! MAP + CALL MAP_Input_ExtrapInterp(MAP_Input, MAP_InputTimes, u_MAP, t_global, ErrStat, ErrMsg) + CALL CheckError(ErrStat,'Message from MAP_Input_ExtrapInterp (FAST): '//NewLine//ErrMsg ) + DO j = MAP_interp_order, 1, -1 + CALL MAP_CopyInput (MAP_Input(j), MAP_Input(j+1), MESH_UPDATECOPY, Errstat, ErrMsg) + MAP_InputTimes(j+1) = MAP_InputTimes(j) + END DO + + CALL MAP_CopyInput (u_MAP, MAP_Input(1), MESH_UPDATECOPY, Errstat, ErrMsg) + MAP_InputTimes(1) = t_global + + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Step 1.b: Advance states (yield state and constraint values at t_global_next) + ! + ! x, xd, and z contain val0ues at t_global; + ! values at t_global_next are stored in the *_pred variables. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !---------------------------------------------------------------------------------------- + ! copy the states at step t_global and get prediction for step t_global_next + ! (note that we need to copy the states because UpdateStates updates the values + ! and we need to have the old values [at t_global] for the next j_pc step) + !---------------------------------------------------------------------------------------- + ! ElastoDyn: get predicted states + ! AeroDyn: get predicted states + ! ServoDyn: get predicted states + ! HydroDyn: get predicted states + ! SubDyn: get predicted states + ! MAP/FEAM: get predicted states + + CALL MAP_CopyContState ( x_MAP, x_MAP_pred, MESH_UPDATECOPY, Errstat, ErrMsg) + CALL MAP_CopyDiscState (xd_MAP, xd_MAP_pred, MESH_UPDATECOPY, Errstat, ErrMsg) + CALL MAP_CopyConstrState ( z_MAP, z_MAP_pred, MESH_UPDATECOPY, Errstat, ErrMsg) + + ! IF ( p_FAST%n_substeps( Module_MAP ) > 1 ) THEN + ! CALL MAP_CopyOtherState( OtherSt_MAP, OtherSt_MAP_old, MESH_UPDATECOPY, Errstat, ErrMsg) + ! END IF + + DO j_ss = 1, 1 !p_FAST%n_substeps( Module_MAP ) + ! n_t_module = n_t_global*p_FAST%n_substeps( Module_MAP ) + j_ss - 1 + ! t_module = n_t_module*p_FAST%dt_module( Module_MAP ) + CALL MAP_UpdateStates(t_global , & + n_t_global , & + MAP_Input , & + MAP_InputTimes , & + p_MAP , & + x_MAP_pred , & + xd_MAP_pred , & + z_MAP_pred , & + other_MAP , & + ErrStat , & + ErrMsg ) + IF (ErrStat.NE.0) THEN + CALL WrScr(trim(ErrMsg)) + END IF + ! CALL CheckError( ErrStat, 'Message from MAP_UpdateStates: '//NewLine//ErrMsg ) + END DO !j_ss + + + ! !========== NOTE ====== <-----------------------------------------+ + ! ! @bonnie : I am assuming this MAP_InputTimes{:} and MAP_Input{:} + ! ! will be assigned by the glue code + ! + ! MAP_InputTimes(1) = t_global + dt_global + ! ! MAP_InputTimes(2) = MAP_InputTimes(1) - dt_global + ! ! MAP_InputTimes(3) = MAP_InputTimes(2) - dt_global + ! + MAP_Input(1)%PtFairDisplacement%TranslationDisp(1,1) = .05*n_t_global + MAP_Input(1)%PtFairDisplacement%TranslationDisp(1,2) = .05*n_t_global + ! ! MAP_Input(3)%PtFairDisplacement%TranslationDisp(1,1) = 1*n_t_global + ! !=========================================================================== + + ! @bonnie & @jason: the FAST glue code will update the new fairlead position + ! based on the new platform position in the global frame. + ! CALL MAP_CalcOutput( this_time, MAP_Input(1), p_MAP, x_MAP_this, xd_MAP_this, z_MAP_this, OtherSt_MAP, y_MAP, ErrStat, ErrMsg ) + CALL MAP_CalcOutput(t_global , & + MAP_Input(1) , & + p_MAP , & + x_MAP_pred , & + xd_MAP_pred , & + z_MAP_pred , & + other_MAP , & + y_MAP , & + ErrStat , & + ErrMsg ) + IF (ErrStat.NE.0) THEN + CALL WrScr(ErrMsg) + END IF + + + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Step 2: Correct (continue in loop) + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! IF ( j_pc /= p_FAST%NumCrctn) THEN ! Don't copy these on the last loop iteration... + ! IF ( p_FAST%n_substeps( Module_MAP ) > 1 ) THEN + ! CALL MAP_CopyOtherState( OtherSt_MAP_old, OtherSt_MAP, MESH_UPDATECOPY, Errstat, ErrMsg) + ! ELSEIF ( p_FAST%n_substeps( Module_FEAM ) > 1 ) THEN + ! CALL FEAM_CopyOtherState( OtherSt_FEAM_old, OtherSt_FEAM, MESH_UPDATECOPY, Errstat, ErrMsg) + ! END IF + ! END IF + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Predictor-corrector ends here! + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Step 3: Save all final variables (advance to next time) + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! MAP: copy final predictions to actual states + CALL MAP_CopyContState ( x_MAP_pred, x_MAP, MESH_UPDATECOPY, Errstat, ErrMsg) + CALL MAP_CopyDiscState (xd_MAP_pred, xd_MAP, MESH_UPDATECOPY, Errstat, ErrMsg) + CALL MAP_CopyConstrState ( z_MAP_pred, z_MAP, MESH_UPDATECOPY, Errstat, ErrMsg) + END DO + ! ------------------------------------------------------------------------- + ! END time marching + ! ------------------------------------------------------------------------- + + + !========== NOTE ====== <-----------------------------------------+ + ! @bonnie : I am assuming the glue code will do this + IF (MAP_interp_order .EQ. 1) THEN + CALL MeshDestroy(MAP_Input(2)%PtFairDisplacement, ErrStat,ErrMsg) + ELSE IF (MAP_interp_order .EQ. 2) THEN + CALL MeshDestroy(MAP_Input(2)%PtFairDisplacement, ErrStat,ErrMsg) + CALL MeshDestroy(MAP_Input(3)%PtFairDisplacement, ErrStat,ErrMsg) + END IF + !=========================================================================== + + ! Destroy all objects + ! CALL MAP_End( MAP_Input(1), p_MAP, x_MAP, xd_MAP, z_MAP, OtherSt_MAP, y_MAP, ErrStat2, ErrMsg2) + CALL MAP_End(MAP_Input(1), & + p_MAP , & + x_MAP , & + xd_MAP , & + z_MAP , & + other_MAP , & + y_MAP , & + ErrStat , & + ErrMsg ) + IF (ErrStat.NE.0) THEN + WRITE(*,*) ErrMsg + END IF + + CALL MAP_DestroyInput(u_MAP, ErrStat, ErrMsg) + IF (ErrStat/=ErrID_None) CALL WrScr(TRIM(ErrMsg)) + IF (ALLOCATED(MAP_Input)) THEN + DO j = 2,MAP_interp_order+1 !note that SD_Input(1) was destroyed in MAP_End + CALL MAP_DestroyInput(MAP_Input(j), ErrStat, ErrMsg) + IF (ErrStat/=ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + DEALLOCATE(MAP_Input) + END IF + IF (ALLOCATED(MAP_Input)) DEALLOCATE(MAP_Input) + IF (ALLOCATED(MAP_InputTimes)) DEALLOCATE(MAP_InputTimes) + + CALL MAP_DestroyContState(x_MAP_pred, ErrStat, ErrMsg); IF (ErrStat/= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MAP_DestroyDiscState(xd_MAP_pred, ErrStat, ErrMsg); IF (ErrStat/= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MAP_DestroyConstrState(z_MAP_pred, ErrStat, ErrMsg); IF (ErrStat/= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MAP_DestroyOtherState(other_MAP_old, ErrStat, ErrMsg); IF (ErrStat/= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CONTAINS + + SUBROUTINE CheckError(ErrID,Msg) + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + IF ( ErrID /= ErrID_None ) THEN + CALL WrScr( NewLine//TRIM(Msg)//NewLine ) + ! IF ( ErrID >= AbortErrLev ) CALL ExitThisProgram( Error=.TRUE., ErrLev=ErrID ) + END IF + END SUBROUTINE CheckError + +END PROGRAM Main + + diff --git a/OpenFAST/modules/map/src/mapapi.c b/OpenFAST/modules/map/src/mapapi.c new file mode 100644 index 000000000..f43a7720b --- /dev/null +++ b/OpenFAST/modules/map/src/mapapi.c @@ -0,0 +1,1317 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "map.h" +#include "maperror.h" +#include "MAP_Types.h" +#include "mapapi.h" +#include "lineroutines.h" +#include "freedata.h" +#include "mapinit.h" +#include "outputstream.h" +#include "numeric.h" +#include "jacobian.h" +#include "residual.h" + + +MAP_EXTERNCALL void map_initialize_msqs_base(MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_InitOutputType_t* io_type) +{ + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + + /* initialize types; set doubles to -999.9, int=0, pointers=NULL + * @todo: add other variables as neccessary. This needs to be fixed each time the registry + * is run an new varaibles are introduced + */ + success = initialize_fortran_types(u_type, p_type, x_type, z_type, other_type, y_type, io_type); + + /* create a cable library link lists for: + * - nodes + * - lines + * - cable library (properties) + * The following are simclist routines + */ + list_init(&domain->library); + list_init(&domain->node); + list_init(&domain->line); + list_init(&domain->u_update_list); + list_attributes_copy(&domain->library, cable_library_meter, 1); + list_attributes_copy(&domain->node, node_meter, 1); + list_attributes_copy(&domain->line, cable_line_meter, 1); + list_attributes_copy(&domain->u_update_list, u_list_meter, 1); +}; + + +/** + * @file + * NWTC required functions necessary to hook MAP into FAST. These functions provide the binding to + * solve constraints for subsequent time-steps. + */ + + +MAP_EXTERNCALL void map_init(MAP_InitInputType_t* init_type, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_InitOutputType_t* io_type, + MAP_ERROR_CODE *ierr, + char *map_msg) { + InitializationData* init_data = init_type->object; + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + + map_reset_universal_error(map_msg, ierr); + domain->HEAD_U_TYPE = u_type; + + MAP_BEGIN_ERROR_LOG; + + success = map_get_version(io_type); + success = allocate_outlist(domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_47); + list_init(&domain->y_list->out_list); /* simclist routine */ + list_init(&domain->y_list->out_list_ptr); /* simclist routine */ + + /* The follow routines expand the input file contents based on the number of repeat + * angles. If not repeat angles are declared, then expanded_node_input_string=node_input_string + * and expanded_line_input_string=line_input_string. This is just a convenient way + * to duplicate lines if a symetric mooring is employed + */ + + success = set_model_options_list(domain, init_data, map_msg, ierr); CHECKERRQ(MAP_FATAL_33); + success = set_cable_library_list(domain, init_data, map_msg, ierr); CHECKERRQ(MAP_FATAL_16); + + success = repeat_nodes(domain, init_data, map_msg, ierr); + success = repeat_lines(domain, init_data, map_msg, ierr); + + success = set_node_list(p_type, u_type, z_type, other_type, y_type, domain, init_data->expanded_node_input_string, map_msg, ierr); CHECKERRQ(MAP_FATAL_16); + success = set_line_list(z_type, domain, init_data->expanded_line_input_string, map_msg, ierr); CHECKERRQ(MAP_FATAL_16); + + /* now create an output list to print to and output file. */ + list_attributes_copy(&domain->y_list->out_list, vartype_meter, 1); + list_attributes_copy(&domain->y_list->out_list_ptr, vartype_ptr_meter, 1); + success = set_output_list(domain, io_type, map_msg, ierr); + success = set_vessel(&domain->vessel, u_type, map_msg, ierr); CHECKERRQ(MAP_FATAL_69); + + if (domain->model_options.lm_model) { + /* @todo: need to allocate LM-specific data */ + domain->MAP_SOLVE_TYPE = LUMPED_MASS; + } else if (z_type->x_Len!=0) { /* this means there are no connect nodes. This does NOT mean z_type->H_len==0 */ + success = allocate_outer_solve_data(&domain->outer_loop, z_type->x_Len, map_msg, ierr); CHECKERRQ(MAP_FATAL_72); + domain->MAP_SOLVE_TYPE = PARTITIONED; + } else { + domain->MAP_SOLVE_TYPE = MONOLITHIC; + }; + + /* if DEBUG is raised in CCFLAGS, then MAP version number is printed to screen */ +# ifdef DEBUG + print_machine_name_to_screen( ); +# endif + + printf("MAP++ environment properties (set externally)...\n"); + printf(" Gravity constant [m/s^2] : %1.2f\n", p_type->g ); + printf(" Sea density [kg/m^3] : %1.2f\n", p_type->rho_sea ); + printf(" Water depth [m] : %1.2f\n", p_type->depth ); + printf(" Vessel reference position [m] : %1.2f , %1.2f , %1.2f\n", domain->vessel.ref_origin.x.value, domain->vessel.ref_origin.y.value, domain->vessel.ref_origin.z.value); + + success = initialize_cable_library_variables(domain, p_type, map_msg, ierr); CHECKERRQ(MAP_FATAL_41); + success = set_line_variables_pre_solve(domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_86);// @rm, not needed. This is called in line_solve_sequence + success = reset_node_force_to_zero(domain, map_msg, ierr); // @rm, not needed. This is called in line_solve_sequence + success = set_line_initial_guess(domain, map_msg, ierr); + success = first_solve(domain, p_type, u_type, z_type, other_type, y_type, map_msg, ierr); CHECKERRQ(MAP_FATAL_39); + success = set_line_variables_post_solve(domain, map_msg, ierr); // @rm, not needed. This is called in line_solve_sequence + + MAP_END_ERROR_LOG; + + /* the next functions are called in a seperate do-loop to log information to the + * summary file even if a fatal error is encountered. This guarantees the summary + * file is written even if garbage is recorded. + */ + log_initialization_information(init_type, p_type, y_type, other_type, domain, map_msg, ierr); + + free_init_data(init_data, map_msg, ierr); + MAP_InitInput_Delete(init_data); + if (*ierr!=MAP_SAFE) printf("Intialization: %s\n", map_msg); + + // checkpoint(); + // printf("In initialization: %p\n",z_type); + // for (int i=0 ; i<z_type->H_Len ; i++){ + // printf(" H=%2.2f V=%2.2f\n",z_type->H[i],z_type->V[i]); + // } + +}; + + +MAP_EXTERNCALL void map_update_states(float t, + int interval, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_ERROR_CODE* ierr, + char* map_msg ) { + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + ReferencePoint* point_iter = NULL; + int i = 0; + + map_reset_universal_error(map_msg, ierr); + + MAP_BEGIN_ERROR_LOG; + + success = associate_constraint_states(domain, z_type); CHECKERRQ(MAP_FATAL_97); + + /* If the reference to u_type changes, then we have to update the location MAP internal states are pointing + * to. This is accomplished in the following code. The issue here is when this is called in Fortran: + * + * CALL MAP_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) + * + * u_interp is passed into into the argument for map_update_states(); however, the internal states are not + * pointing to data in u_interp. We address this below. Note that the initial reference for point_iter is set + * in set_node_list(...) + */ + //if (u_type!=domain->HEAD_U_TYPE) { /* this is intended to be triggered when couled to FAST */ + list_iterator_start(&domain->u_update_list); + while (list_iterator_hasnext(&domain->u_update_list)) { + point_iter = (ReferencePoint*)list_iterator_next(&domain->u_update_list); + point_iter->x->value = &(u_type->x[i]); + point_iter->y->value = &(u_type->y[i]); + point_iter->z->value = &(u_type->z[i]); + i++; + }; + list_iterator_stop(&domain->u_update_list); + domain->HEAD_U_TYPE = u_type; + + if (i!=u_type->x_Len) { /* raise error if the input array are exceeded */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_89, "u_type range: <%d>. Updated array range: <%d>", u_type->x_Len, i); + break; + }; + //}; + + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { /* if the line has no CONNECT object ... */ + success = line_solve_sequence(domain, p_type, t, map_msg, ierr); + } else { /* the line does have CONNECT object defined ... */ + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, t, map_msg, ierr); // @todo CHECKERRQ() + }; + + MAP_END_ERROR_LOG; + if (*ierr!=MAP_SAFE) printf("interval %d Update_state: %s\n",interval, map_msg); +}; + + +MAP_EXTERNCALL void map_calc_output(float t, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_ERROR_CODE* ierr, + char* map_msg ) { + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + ReferencePoint* point_iter = NULL; + int i = 0; + + + map_reset_universal_error(map_msg, ierr); + + MAP_BEGIN_ERROR_LOG; + + success = associate_constraint_states(domain, z_type); CHECKERRQ(MAP_FATAL_98); + + /* If the reference to u_type changes, then we have to update the location MAP internal states are pointing + * to. This is accomplished in the following code. The issue here is when this is called in Fortran: + * + * CALL MAP_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) + * + * u_interp is passed into into the argument for map_update_states(); however, the internal states are not + * pointing to data in u_interp. We address this below. Note that the initial reference for point_iter is set + * in set_node_list(...) + */ + // if (u_type!=domain->HEAD_U_TYPE) { /* this is intended to be triggered when couled to FAST */ + list_iterator_start(&domain->u_update_list); + while (list_iterator_hasnext(&domain->u_update_list)) { + point_iter = (ReferencePoint*)list_iterator_next(&domain->u_update_list); + point_iter->x->value = &(u_type->x[i]); + point_iter->y->value = &(u_type->y[i]); + point_iter->z->value = &(u_type->z[i]); + i++; + }; + list_iterator_stop(&domain->u_update_list); + domain->HEAD_U_TYPE = u_type; + + if (i != u_type->x_Len) { /* raise error if the input array are exceeded */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_89, "u_type range: <%d>. Updated array range: <%d>", u_type->x_Len, i); + break; + }; + //}; + + if (domain->MAP_SOLVE_TYPE == MONOLITHIC) { /* if the line has no CONNECT object ... */ + success = line_solve_sequence(domain, p_type, t, map_msg, ierr); + } + else { /* the line does have CONNECT object defined ... */ + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, t, map_msg, ierr); // @todo CHECKERRQ() + }; + + success = get_iteration_output_stream(y_type, other_type, map_msg, ierr); // @todo: CHECKERRQ(); + MAP_END_ERROR_LOG; + if (*ierr!=MAP_SAFE) printf("time %f Calc_output: %s\n",t, map_msg); +}; + + +MAP_EXTERNCALL void map_end(MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_ERROR_CODE* ierr, + char* map_msg ) { + // Node* iterNode = NULL; + // CableLibrary* iterCableLibrary = NULL; + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + + map_reset_universal_error(map_msg, ierr); + + MAP_BEGIN_ERROR_LOG; + + success = free_outer_solve_data(&domain->outer_loop, z_type->x_Len, map_msg, ierr); CHECKERRQ(MAP_FATAL_73); + success = map_free_types(u_type, p_type, x_type, z_type, other_type, y_type); + success = free_outlist(domain,map_msg,ierr); CHECKERRQ(MAP_FATAL_47);//@rm, should be replaced with a MAPFREE(data->y_list) + success = free_line(&domain->line); + success = free_node(&domain->node); + success = free_vessel(&domain->vessel); + success = free_cable_library(&domain->library); + success = free_update_list(&domain->u_update_list); + + list_destroy(&domain->line); + list_destroy(&domain->node); + list_destroy(&domain->library); + list_destroy(&domain->u_update_list); + MAPFREE(domain->model_options.repeat_angle); + MAP_OtherState_Delete(domain); + + MAP_END_ERROR_LOG; +}; + + +MAP_EXTERNCALL void map_offset_vessel(MAP_OtherStateType_t* other_type, MAP_InputType_t* u_type, double x, double y, double z, double phi, double the, double psi, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* data = other_type->object; + Vessel* vessel = &data->vessel; + int i = 0; + const int u_size = u_type->x_Len; + double R[3][3]; + double cphi = 0.0; + double sphi = 0.0; + double cthe = 0.0; + double sthe = 0.0; + double cpsi = 0.0; + double spsi = 0.0; + double rx = 0.0; + double ry = 0.0; + double rz = 0.0; + + map_reset_universal_error(map_msg, ierr); + + /* define angles */ + cphi = cos(phi*DEG2RAD); + sphi = sin(phi*DEG2RAD); + cthe = cos(the*DEG2RAD); + sthe = sin(the*DEG2RAD); + cpsi = cos(psi*DEG2RAD); + spsi = sin(psi*DEG2RAD); + + /* define transformation matrix */ + R[0][0] = cpsi*cthe; R[0][1] = cpsi*sthe*sphi - spsi*cphi; R[0][2] = cpsi*sthe*cphi + spsi*sphi; + R[1][0] = spsi*cthe; R[1][1] = sphi*sthe*sphi + cpsi*cphi; R[1][2] = spsi*sthe*cphi - cpsi*sphi; + R[2][0] = -sthe; R[2][1] = cthe*sphi; R[2][2] = cthe*cphi; + + for (i=0 ; i<u_size ; i++) { + /* @todo: need to include the reference position for non-zero reference origins , i.e. r = (xi-ref) + * xi, yi, and zi are the original node position. We are adding the new displacement to it. + */ + rx = vessel->xi[i]; + ry = vessel->yi[i]; + rz = vessel->zi[i]; + + /* matrix-vector product */ + /* r_{u_i} = r + r_{ref} + R*r_i */ + u_type->x[i] = x /* + vessel->ref_origin.x.value*/ + (rx*R[0][0] + ry*R[0][1] + rz*R[0][2]); + u_type->y[i] = y /* + vessel->ref_origin.y.value*/ + (rx*R[1][0] + ry*R[1][1] + rz*R[1][2]); + u_type->z[i] = z /* + vessel->ref_origin.z.value*/ + (rx*R[2][0] + ry*R[2][1] + rz*R[2][2]); + }; +}; + + +MAP_EXTERNCALL double** map_linearize_matrix(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, double epsilon, MAP_ERROR_CODE* ierr, char* map_msg) +{ + double* x_original = NULL; + double* y_original = NULL; + double* z_original = NULL; + Domain* domain = other_type->object; + MAP_ERROR_CODE success = MAP_SAFE; + const int n = u_type->x_Len; + const int SIX = 6; + int i = 0; + // int j = 0; + int k = 0; + Fd force; + double** K; + + map_reset_universal_error(map_msg, ierr); + + K = malloc(SIX*sizeof(double*)); + for (i=0 ; i<SIX ; i++) { + K[i] = malloc(SIX*sizeof(double)); + + /* initialize K(6x6) allocated above to zero, row-by-row */ + K[i][0] = 0.0; + K[i][1] = 0.0; + K[i][2] = 0.0; + K[i][3] = 0.0; + K[i][4] = 0.0; + K[i][5] = 0.0; + }; + + force.fx = malloc(n*sizeof(double)); + force.fy = malloc(n*sizeof(double)); + force.fz = malloc(n*sizeof(double)); + force.mx = malloc(n*sizeof(double)); + force.my = malloc(n*sizeof(double)); + force.mz = malloc(n*sizeof(double)); + x_original = malloc(n*sizeof(double)); + y_original = malloc(n*sizeof(double)); + z_original = malloc(n*sizeof(double)); + + /* initialize stuff allocated above to zero */ + for (i=0 ; i<n ; i++) { + force.fx[i] = 0.0; + force.fy[i] = 0.0; + force.fz[i] = 0.0; + force.mx[i] = 0.0; + force.my[i] = 0.0; + force.mz[i] = 0.0; + x_original[i] = 0.0; + y_original[i] = 0.0; + z_original[i] = 0.0; + }; + + MAP_BEGIN_ERROR_LOG; + + /* first get the original values for the displacements */ + for (k=0 ; k<n ; k++) { + x_original[k] = u_type->x[k]; + y_original[k] = u_type->y[k]; + z_original[k] = u_type->z[k]; + }; + + for (i=0 ; i<SIX ; i++) { /* down, force direction changes */ + success = reset_force_to_zero(force.fx, force.fy, force.fz, force.mx, force.my, force.mz, n); + if (i==0) { + success = fd_x_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, x_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_62); + success = calculate_stiffness(K[0], &force, epsilon, n); CHECKERRQ(MAP_FATAL_62); + } else if (i==1) { + success = fd_y_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, y_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_63); + success = calculate_stiffness(K[1], &force, epsilon, n); CHECKERRQ(MAP_FATAL_63); + } else if (i==2) { + success = fd_z_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, z_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_64); + success = calculate_stiffness(K[2], &force, epsilon, n); CHECKERRQ(MAP_FATAL_64); + } else if (i==3) { + success = fd_phi_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, x_original, y_original, z_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_65); + success = calculate_stiffness(K[3], &force, epsilon, n); CHECKERRQ(MAP_FATAL_65); + } else if (i==4) { + success = fd_the_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, x_original, y_original, z_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_66); + success = calculate_stiffness(K[4], &force, epsilon, n); CHECKERRQ(MAP_FATAL_66); + } else if (i==5) { + success = fd_psi_sequence(other_type, p_type, u_type, y_type, z_type, &force, epsilon, n, x_original, y_original, z_original, map_msg, ierr); CHECKERRQ(MAP_FATAL_67); + success = calculate_stiffness(K[5], &force, epsilon, n); CHECKERRQ(MAP_FATAL_67); + }; + }; + + success = reset_force_to_zero(force.fx, force.fy, force.fz, force.mx, force.my, force.mz, n); + success = restore_original_displacement(u_type->x, x_original, n); + success = restore_original_displacement(u_type->y, y_original, n); + success = restore_original_displacement(u_type->z, z_original, n); + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, (float)-999.9, map_msg, ierr); // @todo CHECKERRQ() + }; + + MAP_END_ERROR_LOG; + + MAPFREE(force.fx); + MAPFREE(force.fy); + MAPFREE(force.fz); + MAPFREE(force.mx); + MAPFREE(force.my); + MAPFREE(force.mz); + MAPFREE(x_original); + MAPFREE(y_original); + MAPFREE(z_original); + + return K; +}; + + +MAP_EXTERNCALL void map_free_linearize_matrix(double** array) +{ + int i = 0; + for(i=0 ; i<6 ; i++) { + MAPFREE(array[i]); + }; + MAPFREE(array); +}; + + +MAP_EXTERNCALL double* map_plot_x_array(MAP_OtherStateType_t* other_type, int i, int num_points, char *map_msg, MAP_ERROR_CODE *ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double H = 0.0; + double V = 0.0; + double EA = 0.0; + double Lu = 0.0; + double Lb = 0.0; + double w = 0.0; + double S = 0.0; + double dS = 0.0; + double fairlead_x = 0.0; + double anchor_x = 0.0; + double cb = 0.0; + double lambda = 0.0; + double* array_x = NULL; + // int ret = 0; + int s = 0; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + } else if (line->options.linear_spring) { + fairlead_x = *(line->fairlead->position_ptr.x.value); + anchor_x = *(line->anchor->position_ptr.x.value); + array_x = malloc(num_points*sizeof(double)); + dS = (fairlead_x-anchor_x)/(double)(num_points-1); + for (s=0 ; s<num_points ; s++) { + array_x[s] = fairlead_x - S; + S += dS; + }; + } else { + fairlead_x = *(line->fairlead->position_ptr.x.value); + anchor_x = *(line->anchor->position_ptr.x.value); + array_x = malloc(num_points*sizeof(double)); + H = *(line->H.value); + V = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + w = line->line_property->omega; + cb = line->line_property->cb; + dS = Lu/(double)(num_points-1) ; + + /* If the cable is not resting on the seabed, we use the classic catenary equation + * for a hanging chain to plot the mooring line profile. Otherwise if it is, we + * the modified version as done in the FAST wind turbine program. + * + * @ref : J. Jonkman, November 2007. "Dynamic Modeling and Loads Analysis of an + * Offshore Floating Wind Turbine." NREL Technical Report NREL/TP-500-41958. + */ + if (line->options.omit_contact==true || w<0.0 || (V-w*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + for (s=0 ; s<num_points ; s++) { + array_x[s] = fairlead_x - ( (H/w)*ARCSINH( V/H ) - (H/w)*ARCSINH( (V-S*w)/H ) + (H*S)/(EA) )*cos(line->psi); + S += dS; + }; + } else { + Lb = Lu - (V/w); + lambda = (Lb-H/(cb*w))>0 ? (Lb-H/(cb*w)) : 0; + for (s=0 ; s<num_points ; s++) { + if (0<=S && S<=(Lb-H/(cb*w))) { /* for 0 <= s <= Lb - H/(Cb*w) */ + array_x[s] = S*cos(line->psi) + anchor_x; + } else if ((Lb-H/(cb/w))<S && S<=Lb) { /* for Lb - H/(Cb*w) < s <= Lb */ + array_x[s] = (S + ((cb*w)/(2*EA)) * (S*S - 2*(Lb-H/(cb*w))*S + (Lb- H/(cb*w))*lambda))*cos(line->psi) + anchor_x; + } else { /* for Lb < s <= L */ + array_x[s] = (Lb + (H/w)*ARCSINH((w*(S-Lb))/H))*cos(line->psi) + - ( ((H*S)/(EA)) + ((cb*w)/(2*EA))*(-Lb*Lb + (Lb-H/(cb*w))*lambda))*cos(line->psi) + anchor_x; + }; + S += dS; + }; + }; + }; + return array_x; +}; + + +MAP_EXTERNCALL double* map_plot_y_array(MAP_OtherStateType_t* other_type, int i, int num_points, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* data = other_type->object; + Line* line = NULL; + double H = 0.0; + double V = 0.0; + double EA = 0.0; + double Lu = 0.0; + double Lb = 0.0; + double w = 0.0; + double S = 0.0; + double dS = 0.0; + double fairlead_y = 0.0; + double anchor_y = 0.0; + double cb = 0.0; + double lambda = 0.0; + double* array_y = NULL; + int s = 0; + // int ret = 0; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&data->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + } else if (line->options.linear_spring) { + fairlead_y = *(line->fairlead->position_ptr.y.value); + anchor_y = *(line->anchor->position_ptr.y.value); + array_y = malloc(num_points*sizeof(double)); + dS = (fairlead_y-anchor_y)/(double)(num_points-1); + for (s=0 ; s<num_points ; s++) { + array_y[s] = fairlead_y - S; + S += dS; + }; + } else { + fairlead_y = *(line->fairlead->position_ptr.y.value); + anchor_y = *(line->anchor->position_ptr.y.value); + array_y = malloc(num_points*sizeof(double)); + H = *(line->H.value); + V = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + w = line->line_property->omega; + cb = line->line_property->cb; + dS = Lu/(double)(num_points-1) ; + + /* If the cable is not resting on the seabed, we use the classic catenary equation + * for a hanging chain to plot the mooring line profile. Otherwise if it is, we + * the modified version as done in the FAST wind turbine program. + * + * @ref : J. Jonkman, November 2007. "Dynamic Modeling and Loads Analysis of an + * Offshore Floating Wind Turbine." NREL Technical Report NREL/TP-500-41958. + */ + if (line->options.omit_contact==true || w<0.0 || (V-w*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + for (s=0 ; s<num_points ; s++) { + array_y[s] = fairlead_y - ( (H/w)*ARCSINH( V/H ) - (H/w)*ARCSINH( (V-S*w)/H ) + (H*S)/(EA) )*sin(line->psi); + S += dS; + }; + } else { + Lb = Lu - (V/w); + lambda = (Lb-H/(cb*w))>0 ? (Lb-H/(cb*w)) : 0; + for (s=0 ; s<num_points ; s++) { + if (0<=S && S<=(Lb-H/(cb*w))) { /* for 0 <= s <= Lb - H/(Cb*w) */ + array_y[s] = S*sin(line->psi) + anchor_y; + } else if ((Lb-H/(cb/w))<S && S<=Lb) { /* for Lb - H/(Cb*w) < s <= Lb */ + array_y[s] = (S + ((cb*w)/(2*EA))*(S*S - 2*(Lb-H/(cb*w))*S + (Lb- H/(cb*w))*lambda))*sin(line->psi) + anchor_y; + } else { /* for Lb < s <= L */ + array_y[s] = (Lb + (H/w)*ARCSINH((w*(S-Lb))/H))*sin(line->psi) + - (((H*S)/(EA)) + ((cb*w)/(2*EA))*(-Lb*Lb + (Lb-H/(cb*w))*lambda))*sin(line->psi) + anchor_y; + }; + S += dS; + }; + }; + }; + return array_y; +}; + + +MAP_EXTERNCALL double* map_plot_z_array(MAP_OtherStateType_t* other_type, int i, int num_points, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* data = other_type->object; + Line* line = NULL; + double H = 0.0; + double V = 0.0; + // double Va = 0.0; + double EA = 0.0; + double Lu = 0.0; + double Lb = 0.0; + double w = 0.0; + double S = 0.0; + double dS = 0.0; + double fairlead_z = 0.0; + double anchor_z = 0.0; + double* array_z = NULL; + // int ret = 0; + int s = 0; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&data->line, i); + + if (line==NULL){ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + } else if (line->options.linear_spring) { + fairlead_z = *(line->fairlead->position_ptr.z.value); + anchor_z = *(line->anchor->position_ptr.z.value); + array_z = malloc(num_points*sizeof(double)); + dS = fabs(fairlead_z-anchor_z)/(double)(num_points-1); + for (s=0 ; s<num_points ; s++) { + array_z[s] = fairlead_z - S; + S += dS; + }; + } else { + fairlead_z = *(line->fairlead->position_ptr.z.value); + anchor_z = *(line->anchor->position_ptr.z.value); + array_z = malloc(num_points*sizeof(double)); + H = *(line->H.value); + V = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + w = line->line_property->omega; + dS = Lu/(double)(num_points-1) ; + + /* If the cable is not resting on the seabed, we use the classic catenary equation + * for a hanging chain to plot the mooring line profile. Otherwise if it is, we + * the modified version as done in the FAST wind turbine program. + * + * @ref : J. Jonkman, November 2007. "Dynamic Modeling and Loads Analysis of an + * Offshore Floating Wind Turbine." NREL Technical Report NREL/TP-500-41958. + */ + if (line->options.omit_contact==true || w<0.0 || (V-w*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + if (fairlead_z<anchor_z) { + V = fabs(V - Lu*w); + }; + for (s=0 ; s<num_points ; s++) { + array_z[s] = fairlead_z - ((H/w)*(sqrt(1+pow(V/H,2)) - sqrt(1+pow((V-w*S)/H,2))) + (1/EA)*(V*S+w*S*S/2)); /* Z position of line in global coordinates */ + S += dS; + }; + } else { + Lb = Lu - (V/w); + for (s=0 ; s<num_points ; s++) { + if (0<=S && S<=Lb) { + array_z[s] = anchor_z; + } else { + /* @todo: verify this equation before someone uses this program to design something that matters */ + array_z[s] = ((H/w)*(sqrt(1 + pow((w*(S-Lb)/H),2)) - 1) + ((w*pow((S-Lb),2))/(2*EA))) + anchor_z; + //array_z[s] = - ((H/w)*(sqrt(1 + pow((w*(S-Lb)/H),2)) - 1) + ((w*pow((S-Lb),2))/(2*EA))) + anchor_z; + }; + S += dS; + }; + }; + }; + return array_z; +}; + + +MAP_EXTERNCALL void map_plot_array_free(double* array) +{ + MAPFREE(array); +}; + + +MAP_EXTERNCALL double map_residual_function_length(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double length = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + length = line->l; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return residual_function_length_no_contact(Fv, Fh, omega, Lu, EA, length); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return residual_function_length_contact(Fv, Fh, omega, Lu, EA, length, cb); + }; +}; + + +MAP_EXTERNCALL double map_residual_function_height(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double height = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + height = line->h; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return residual_function_height_no_contact(Fv, Fh, omega, Lu, EA, height); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return residual_function_height_contact(Fv, Fh, omega, Lu, EA, height, cb); + }; +}; + + +MAP_EXTERNCALL double map_jacobian_dxdh(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return jacobian_dxdh_no_contact(Fv, Fh, omega, Lu, EA); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return jacobian_dxdh_contact(Fv, Fh, omega, Lu, EA, cb); + }; +}; + + +MAP_EXTERNCALL double map_jacobian_dxdv(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return jacobian_dxdv_no_contact(Fv, Fh, omega, Lu, EA); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return jacobian_dxdv_contact(Fv, Fh, omega, Lu, EA, cb); + }; +}; + + +MAP_EXTERNCALL double map_jacobian_dzdh(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return jacobian_dzdh_no_contact(Fv, Fh, omega, Lu, EA); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return jacobian_dzdh_contact(Fv, Fh, omega, Lu, EA, cb); + }; +}; + + +MAP_EXTERNCALL double map_jacobian_dzdv(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* domain = other_type->object; + Line* line = NULL; + double Fh = 0.0; + double Fv = 0.0; + double EA = 0.0; + double Lu = 0.0; + double omega = 0.0; + double cb = 0.0; + bool contact_flag = false; + + map_reset_universal_error(map_msg, ierr); + line = (Line*)list_get_at(&domain->line, i); + + if (line==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: <%d>.", i); + return -999.9; + }; + + Fh = *(line->H.value); + Fv = *(line->V.value); + EA = line->line_property->EA; + Lu = line->Lu.value; + omega = line->line_property->omega; + contact_flag = line->options.omit_contact; + cb = line->line_property->cb; + + if (contact_flag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + return jacobian_dzdv_no_contact(Fv, Fh, omega, Lu, EA); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return jacobian_dzdv_contact(Fv, Fh, omega, Lu, EA, cb); + }; +}; + + +MAP_EXTERNCALL void map_get_fairlead_force_2d(double* H, double* V, MAP_OtherStateType_t* other_type, int index, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Line* iter_line = NULL; + Domain* domain = other_type->object; + const unsigned int i = index; + + map_reset_universal_error(map_msg, ierr); + + if (i<=list_size(&domain->line)-1) { + iter_line = (Line*)list_get_at(&domain->line, i); + *H = *(iter_line->H.value); + *V = *(iter_line->V.value); + } else { + /* throw error: line out of range */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: %d.", index); + }; +} + + +MAP_EXTERNCALL void map_get_fairlead_force_3d(double* fx, double* fy, double* fz, MAP_OtherStateType_t* other_type, int index, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Line* iter_line = NULL; + Domain* domain = other_type->object; + double psi = 0.0; + const unsigned int i = index; + + if (i<=list_size(&domain->line)-1) { + iter_line = (Line*)list_get_at(&domain->line, i); + psi = iter_line->psi; + *fx = *(iter_line->H.value)*cos(psi); + *fy = *(iter_line->H.value)*sin(psi); + *fz = *(iter_line->V.value); + } else { + /* throw error: line out of range */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_42, "Line out of range: %d.", index); + }; +} + + +MAP_EXTERNCALL int map_size_lines(MAP_OtherStateType_t* other_type, MAP_ERROR_CODE* ierr, char* map_msg) +{ + Domain* domain = other_type->object; + map_reset_universal_error(map_msg, ierr); + return list_size(&domain->line); +}; + + +MAP_EXTERNCALL void map_set_summary_file_name(MAP_InitInputType_t* init_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + InitializationData* init_data = init_type->object; + map_reset_universal_error(map_msg, ierr); + init_data->summary_file_name = bformat("%s", init_type->summary_file_name); +}; + + +MAP_EXTERNCALL void map_get_header_string(int* n, char** str_array, MAP_OtherStateType_t* other_type) +{ + int count = 0; + Domain* domain = other_type->object; + VarTypePtr* vartype_ptr = NULL; + VarType* vartype = NULL; + + list_iterator_start(&domain->y_list->out_list_ptr); + while (list_iterator_hasnext(&domain->y_list->out_list_ptr)) { + vartype_ptr = (VarTypePtr*)list_iterator_next(&domain->y_list->out_list_ptr); + MAP_STRCPY(str_array[count], 16, (char *)vartype_ptr->name->data); + count++; + }; + list_iterator_stop(&domain->y_list->out_list_ptr); + + list_iterator_start(&domain->y_list->out_list); + while (list_iterator_hasnext(&domain->y_list->out_list)) { + vartype = (VarType*)list_iterator_next(&domain->y_list->out_list); + MAP_STRCPY(str_array[count], 16, (char *)vartype->name->data); + count++; + }; + list_iterator_stop(&domain->y_list->out_list); + /* @todo this should raise and error when count != n */ +}; + + +MAP_EXTERNCALL void map_get_unit_string(int* n, char** str_array, MAP_OtherStateType_t* other_type) +{ + int count = 0; + Domain* domain = other_type->object; + VarTypePtr* vartype_ptr = NULL; + VarType* vartype = NULL; + + list_iterator_start(&domain->y_list->out_list_ptr); + while (list_iterator_hasnext(&domain->y_list->out_list_ptr)) { + vartype_ptr = (VarTypePtr*)list_iterator_next(&domain->y_list->out_list_ptr ); + MAP_STRCPY(str_array[count], 15, (char *)vartype_ptr->units->data); + count++; + }; + list_iterator_stop(&domain->y_list->out_list_ptr); + + list_iterator_start(&domain->y_list->out_list); + while (list_iterator_hasnext(&domain->y_list->out_list)) { + vartype = (VarType*)list_iterator_next(&domain->y_list->out_list ); + MAP_STRCPY(str_array[count], 15, (char *)vartype->units->data); + count++; + }; + list_iterator_stop(&domain->y_list->out_list); +}; + + + +/** + * Fortran binding routine + * SUBROUTINE MAP_set_initinput_to_null(interf,msg,err) bind(C,name='set_init_to_null') + */ +MAP_EXTERNCALL void set_init_to_null(MAP_InitInputType_t* init_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + InitializationData* init = init_type->object; + + init->summary_file_name = NULL; +}; + +MAP_EXTERNCALL void map_set_sea_depth(MAP_ParameterType_t* p_type, const double depth) +{ + p_type->depth = depth; +}; + + +MAP_EXTERNCALL void map_set_sea_density(MAP_ParameterType_t* p_type, const double rho) +{ + p_type->rho_sea = rho; +}; + + +MAP_EXTERNCALL void map_set_gravity(MAP_ParameterType_t* p_type, const double gravity) +{ + p_type->g = gravity; +}; + + +MAP_EXTERNCALL void map_add_cable_library_input_text(MAP_InitInputType_t* init_type) +{ + InitializationData* init_data = init_type->object; + const int n = init_data->library_input_string->qty; + int ret = 0; + + ret = bstrListAlloc(init_data->library_input_string, n+1); + init_data->library_input_string->entry[n] = bfromcstr(init_type->library_input_str); + init_data->library_input_string->qty++; +}; + + +MAP_EXTERNCALL void map_add_node_input_text(MAP_InitInputType_t* init_type) +{ + InitializationData* init_data = init_type->object; + const int n = init_data->node_input_string->qty; + int ret = 0; + + ret = bstrListAlloc(init_data->node_input_string, n+1); + init_data->node_input_string->entry[n] = bfromcstr(init_type->node_input_str); + init_data->node_input_string->qty++; +}; + + +MAP_EXTERNCALL void map_add_line_input_text(MAP_InitInputType_t* init_type) +{ + InitializationData* init_data = init_type->object; + const int n = init_data->line_input_string->qty; + int ret = 0; + + ret = bstrListAlloc(init_data->line_input_string, n+1); + init_data->line_input_string->entry[n] = bfromcstr(init_type->line_input_str); + init_data->line_input_string->qty++; +}; + + +MAP_EXTERNCALL void map_add_options_input_text(MAP_InitInputType_t* init_type) +{ + InitializationData* init_data = init_type->object; + const int n = init_data->solver_options_string->qty; + int ret = 0; + + ret = bstrListAlloc(init_data->solver_options_string, n+1); + init_data->solver_options_string->entry[n] = bfromcstr(init_type->option_input_str); + init_data->solver_options_string->qty++; +}; + + +MAP_EXTERNCALL InitializationData* MAP_InitInput_Create(char* map_msg, MAP_ERROR_CODE* ierr) +{ + InitializationData* new_data = NULL; + + map_reset_universal_error(map_msg, ierr); + new_data = malloc(sizeof(InitializationData)); + if (new_data == NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_4); + return new_data; + } else { + initialize_init_data_to_null(new_data); + return new_data; + }; +}; + + +MAP_EXTERNCALL MAP_InitInputType_t* map_create_init_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_InitInputType_t* new_data = NULL; + + map_reset_universal_error(map_msg, ierr); + new_data = malloc(sizeof(MAP_InitInputType_t)); + if (new_data==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_4); + } else { + initialize_init_type_to_null(new_data); /* set F2C types to null */ + new_data->object = NULL; + new_data->object = (InitializationData*)(uintptr_t)MAP_InitInput_Create(map_msg, ierr); + }; + return new_data; +}; + + +MAP_EXTERNCALL Domain* MAP_OtherState_Create(char* map_msg, MAP_ERROR_CODE* ierr) +{ + Domain* new_data = NULL; + + map_reset_universal_error(map_msg, ierr); + new_data = malloc(sizeof(Domain)); + if (new_data==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_43); + return new_data; + } else { + initialize_domain_to_null(new_data); + return new_data; + }; +}; + +MAP_EXTERNCALL MAP_OtherStateType_t* map_create_other_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_OtherStateType_t* new_data = NULL; + + map_reset_universal_error(map_msg, ierr); + new_data = malloc(sizeof(MAP_OtherStateType_t)); + if (new_data==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_43); + } else { + new_data->object = NULL; + new_data->object = (Domain*)(uintptr_t)MAP_OtherState_Create(map_msg, ierr); + }; + return new_data; +}; + + +MAP_EXTERNCALL MAP_InitOutputType_t* map_create_initout_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_InitOutputType_t* new_type = NULL; + + map_reset_universal_error(map_msg, ierr); + new_type = malloc(sizeof(MAP_InitOutputType_t)); + if (new_type==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_11); + } else { + new_type->object = NULL; + }; + return new_type; +}; + + +MAP_EXTERNCALL MAP_InputType_t* map_create_input_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_InputType_t* new_type = NULL; + + map_reset_universal_error(map_msg, ierr); + new_type = malloc(sizeof(MAP_InputType_t)); + if (new_type == NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_5); + } else { + new_type->object = NULL; + }; + return new_type; +}; + + +MAP_EXTERNCALL MAP_ParameterType_t* map_create_parameter_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ParameterType_t* new_type = NULL; + + map_reset_universal_error(map_msg, ierr); + new_type = malloc(sizeof(MAP_ParameterType_t)); + if (new_type==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_6); + } else { + new_type->object = NULL; + }; + return new_type; +}; + + +MAP_EXTERNCALL MAP_ConstraintStateType_t* map_create_constraint_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ConstraintStateType_t* new_type = NULL; + + map_reset_universal_error(map_msg, ierr); + new_type = malloc(sizeof(MAP_ConstraintStateType_t)); + if (new_type==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + } else { + new_type->object = NULL; + }; + return new_type; +}; + + +MAP_EXTERNCALL MAP_OutputType_t* map_create_output_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_OutputType_t* new_type = NULL; + + map_reset_universal_error(map_msg, ierr); + new_type = malloc(sizeof(MAP_OutputType_t)); + if (new_type==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_10); + } else { + new_type->object = NULL; + }; + return new_type; +}; + + +MAP_EXTERNCALL MAP_ContinuousStateType_t* map_create_continuous_type(char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ContinuousStateType_t* new_data = NULL; + + map_reset_universal_error(map_msg, ierr); + new_data = malloc(sizeof(MAP_ContinuousStateType_t)); + if (new_data==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_7); + } else { + new_data->object = NULL; + }; + return new_data; +}; + + +MAP_EXTERNCALL int free_init_data(InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int success = MAP_SAFE; + + MAP_BEGIN_ERROR_LOG; + + success = bdestroy(init_data->summary_file_name); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->expanded_node_input_string); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->expanded_line_input_string); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->library_input_string); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->node_input_string); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->line_input_string); CHECKERRK(MAP_WARNING_15); + success = bstrListDestroy(init_data->solver_options_string); CHECKERRK(MAP_WARNING_15); + + MAP_END_ERROR_LOG; + + return MAP_SAFE; +}; diff --git a/OpenFAST/modules/map/src/mapapi.h b/OpenFAST/modules/map/src/mapapi.h new file mode 100644 index 000000000..5ccffbe64 --- /dev/null +++ b/OpenFAST/modules/map/src/mapapi.h @@ -0,0 +1,559 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _MAPAPI_H +#define _MAPAPI_H + + +/** + * @brief Initalizes all MAP base types (including some internal state) + * @details The idea is to set variables to zero and null to prevent seg-faults in the case of + * early program termination before initialization (MAP_Init) is fully complete. + * {@link MAP_Init} + * @param el, opaque object used in simclist + * @see map_init() + * @return Size of CableLibrary structure + */ +MAP_EXTERNCALL void map_initialize_msqs_base(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_ContinuousStateType_t* x_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, MAP_InitOutputType_t* io_type); + + +MAP_EXTERNCALL void set_init_to_null(MAP_InitInputType_t* init_type, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL void map_add_cable_library_input_text(MAP_InitInputType_t* init_type); +MAP_EXTERNCALL void map_add_node_input_text(MAP_InitInputType_t* init_type); +MAP_EXTERNCALL void map_add_line_input_text(MAP_InitInputType_t* init_type); +MAP_EXTERNCALL void map_add_options_input_text(MAP_InitInputType_t* init_type); +MAP_EXTERNCALL double* map_plot_x_array(MAP_OtherStateType_t* other_type, int i, int num_points, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double* map_plot_y_array(MAP_OtherStateType_t* other_type, int i, int num_points, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double* map_plot_z_array(MAP_OtherStateType_t* other_type, int i, int num_points, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL void map_plot_array_free(double* array) ; +MAP_EXTERNCALL double map_residual_function_length(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double map_residual_function_height(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double map_jacobian_dxdh(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double map_jacobian_dxdv(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double map_jacobian_dzdh(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL double map_jacobian_dzdv(MAP_OtherStateType_t* other_type, int i, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_EXTERNCALL int map_size_lines(MAP_OtherStateType_t* other_type, MAP_ERROR_CODE* ierr, char* map_msg); + + +/** + * @brief Deallocates the memory space for the init structure. Should be called immediately after map_init() + * @param init MAP-native initialization data structure. This is distinct from the FAST-framework data structure + * @param map_msg error string + * @param ierr error code + * @return MAP_SAFE if it completes successfully + * @see {@link map_init()} + */ +MAP_EXTERNCALL int free_init_data (InitializationData* init, char* map_msg, MAP_ERROR_CODE* ierr); + +/** + * @brief Set the water depth. Should be called before {@link map_init()} + * @param p_type paramter type, native C struct {@link MAP_ParameterType_t} + * @param depth water depth [m] + * + * Example Fortran usage: + * @code + * INTERFACE + * SUBROUTINE mapextern_set_depth(interf, fc_val) BIND(C,name='map_set_sea_depth') + * IMPORT + * IMPLICIT NONE + * TYPE(MAP_ParameterType_C) interf + * REAL(C_DOUBLE), VALUE :: fc_val + * END SUBROUTINE mapextern_set_depth + * END INTERFACE + * + * ... + * + * ! access the function using this subroutine call: + * CALL mapextern_set_depth(p%C_obj, depth) + * @endcode + */ +MAP_EXTERNCALL void map_set_sea_depth(MAP_ParameterType_t* p_type, const double depth); + + +/** + * @brief Set the water density. Should be called before {@link map_init()} + * @param p_type paramter type, native C struct {@link MAP_ParameterType_t} + * @param rho water density [kg/m^3] + * + * Example Fortran usage: + * @code + * INTERFACE + * SUBROUTINE mapextern_set_density(interf, fc_val) BIND(C,name='map_set_sea_density') + * IMPORT + * IMPLICIT NONE + * TYPE(MAP_ParameterType_C) interf + * REAL(C_DOUBLE), VALUE :: fc_val + * END SUBROUTINE mapextern_set_density + * END INTERFACE + * + * ... + * + * ! access the function using this subroutine call: + * CALL mapextern_set_density(p%C_obj, rho) + * @endcode + */ +MAP_EXTERNCALL void map_set_sea_density(MAP_ParameterType_t* p_type, const double rho); + + +/** + * @brief Set the gravitational constant. Should be called before {@link map_init()} + * @param p_type paramter type, native C struct {@link MAP_ParameterType_t} + * @param grtavity gravitational acceleration [m/s^2] + * + * Example Fortran usage: + * @code + * INTERFACE + * SUBROUTINE MAP_map_set_gravity(interf, fc_val) BIND(C,name='map_set_gravity') + * IMPORT + * IMPLICIT NONE + * TYPE(MAP_ParameterType_C) interf + * REAL(C_DOUBLE), VALUE :: fc_val + * END SUBROUTINE MAP_map_set_gravity + * END INTERFACE + * + * ... + * + * ! access the function using this subroutine call: + * CALL mapextern_map_set_gravity(p%C_obj, g) + * @endcode + */ +MAP_EXTERNCALL void map_set_gravity(MAP_ParameterType_t* p_type, const double gravity); + + +/** + * @brief Returns vertical and horizontal fairlead force along line plane + * @details + * @param H, reference to horizontal fairlead force magnitude + * @param V, reference to vertical fairlead force magnitude + * @param other_type, other state type fortran derived + * @param index, line number we are requesting the data for + * @param map_msg, error message + * @param ierr, error code + * @see + */ +MAP_EXTERNCALL void map_get_fairlead_force_2d(double* H, double* V, MAP_OtherStateType_t* other_type, int index, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Returns X, Y, and Z fairlead force in global reference frame + * @details + * @param fx, reference to horizontal X fairlead force in global frame + * @param fy, reference to horizontal Y fairlead force in global frame + * @param fz, reference to vertical Z fairlead force in global frame + * @param other_type, other state type fortran derived + * @param index, line number we are requesting the data for + * @param map_msg, error message + * @param ierr, error code + * @see + */ +MAP_EXTERNCALL void map_get_fairlead_force_3d(double* fx, double* fy, double* fz, MAP_OtherStateType_t* other_type, int index, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * call this in python: offset_vessel().argtypes = [MapData_Type, MapInput_Type, c_char_p, POINTER(c_int)] + * angles are radians + * + * lib.map_offset_vessel.argtypes = [MapData_Type, MapInput_Type, c_double, c_double, c_double, c_double, c_double, c_double, c_char_p, POINTER(c_int)] + * + * Angles are in degrees. This routine converts angles from deg to rad + * Per Fossen (Fossen, Thor I. Guidance and control of ocean vehicles. Vol. 199. No. 4. New York: Wiley, 1994), this + * matrix converts vector from the body frame to the global reference frame: + * + * R = | cos(ψ)*cos(θ) cos(ψ)*sin(θ)*sin(φ) − sin(ψ)*cos(φ) cos(ψ)*sin(θ)*cos(φ) + sin(ψ)*sin(φ) | + * | sin(ψ)*cos(θ) sin(ψ)*sin(θ)*sin(φ) + cos(ψ)*cos(φ) sin(ψ)*sin(θ)*cos(φ) − cos(ψ)*sin(φ) | + * | −sin(θ) cos(θ)*sin(φ) cos(θ)*cos(φ) | + * + * We need to invoke this procedure to move the vessel nodes with body rotations factored: + * + * u_type = x + [R]*r + * ▲ ▲ ▲ + * | | | + * global | | + * global | + * local + */ +MAP_EXTERNCALL void map_offset_vessel(MAP_OtherStateType_t* other_type, MAP_InputType_t* u_type, double x, double y, double z, double phi, double the, double psi, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * lib.linearize_matrix.argtypes = [MapInput_Type, MapData_Type, MapOutnput_Type, c_double, c_char_p, POINTER(c_int)] + */ +MAP_EXTERNCALL double** map_linearize_matrix(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, MAP_ConstraintStateType_t* z_type, double epsilon, MAP_ERROR_CODE* ierr, char* map_msg); + + +/** + * lib.py_free_linearize_matrix.argtypes = [POINTER(POINTER(c_double))] + */ +MAP_EXTERNCALL void map_free_linearize_matrix(double** array); + + +/** + * @brief Initializes the MAP model and allocates memory. Inconsistencies with the input file is reported here. + * This should only be called once. + * @param init_type initialization type, F2C FAST-native derived type + * @param u_type input type, F2C FAST-native derived type. + * @param p_type parameter type, F2C FAST-native derived type + * @param x_type continuous-state type, F2C FAST-native derived type + * @param none void type. It exists because MAP does not use discrete types (it would fill this place otherwise) + * @param z_type constraint-state type, F2C FAST-native derived tpe + * @param other_type other-state type, F2C FAST-native derived type. This is core structure that houses all internal MAP states that cannot be mapped to Fortran + * @param y_type output type, F2C FAST-native derived type + * @param ioType init-output types, F2C FAST-native derived type + * @param ierr error code + * @param map_msg error string + */ +MAP_EXTERNCALL void map_init(MAP_InitInputType_t* init_type, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_InitOutputType_t* ioType, + MAP_ERROR_CODE* ierr, + char* map_msg); + + +/** + * @brief Solves the statics problem for the MSQS system and should be called at each time step or vessel displacement. + * @details Can be called multiple times, but must be called between {@link map_init()} and {@link map_end()} + * If the reference to u_type changes, then we have to update the location MAP internal states are pointing + * to. This is accomplished in the following code. The issue here is when this is called in Fortran: + * + * CALL MAP_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) + * + * u_interp is passed into into the argument for map_update_states(); however, the internal states are not + * pointing to data in u_interp. We address this below. Note that the initial reference for point_iter is set + * in {@link set_node_list()} + * @param t current (global) time + * @param interval coupling interval + * @param u_type input type, F2C FAST-native derived type. + * @param p_type parameter type, F2C FAST-native derived type + * @param x_type continuous-state type, F2C FAST-native derived type + * @param none void type. It exists because MAP does not use discrete types (it would fill this place otherwise) + * @param z_type constraint-state type, F2C FAST-native derived tpe + * @param other_type other-state type, F2C FAST-native derived type. This is core structure that houses all internal MAP states that cannot be mapped to Fortran + * @param ierr error code + * @param map_msg error string + * @see {@link map_calc_output()} + */ +MAP_EXTERNCALL void map_update_states(float t, + int interval, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_ERROR_CODE* ierr, + char* map_msg); + + +/** + * @brief Retrieves the values after the statics problem is solved. This function should be called immediately after map_update_states. + * Can be called multiple times, but must be called between {@link map_init()} and {@link map_end()} + * @param t current (global) time + * @param u_type input type, F2C FAST-native derived type. + * @param p_type parameter type, F2C FAST-native derived type + * @param x_type continuous-state type, F2C FAST-native derived type + * @param none void type. It exists because MAP does not use discrete types (it would fill this place otherwise) + * @param z_type constraint-state type, F2C FAST-native derived tpe + * @param other_type other-state type, F2C FAST-native derived type. This is core structure that houses all internal MAP states that cannot be mapped to Fortran + * @param y_type output type, F2C FAST-native derived type + * @param ierr error code + * @param map_msg error string + * @see {@link map_update_states()} + */ +MAP_EXTERNCALL void map_calc_output(float t, + MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_ERROR_CODE* ierr, + char* map_msg); + + +/** + * @brief Deallocates all memory. Must be called after {@link map_init()}. This is called once. + * @param u_type input type, F2C FAST-native derived type. + * @param p_type parameter type, F2C FAST-native derived type + * @param x_type continuous-state type, F2C FAST-native derived type + * @param none void type. It exists because MAP does not use discrete types (it would fill this place otherwise) + * @param z_type constraint-state type, F2C FAST-native derived tpe + * @param other_type other-state type, F2C FAST-native derived type. This is core structure that houses all internal MAP states that cannot be mapped to Fortran + * @param y_type output type, F2C FAST-native derived type + * @param ierr error code + * @param map_msg error string + * @see {@link map_update_states()} + */ +MAP_EXTERNCALL void map_end(MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_DiscreteStateType_t* xd_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_ERROR_CODE* ierr, + char* map_msg); + +/** + * @brief Set the name out the MAP summary output file. Does not need to be called; the default + * summary file name is 'outlist.map.sum'. + * @param init_type initalization type, native C struct {@link InitializationData_t} + * @param map_msg MAP error message + * @param ierr MAP error code + * + * Example Fortran usage: + * @code + * ! Interface block declaration: + * INTERFACE + * SUBROUTINE mapextern_map_set_summary_file_name(fc_init, fc_char, fc_int) BIND(C,name='map_set_summary_file_name') + * IMPORT + * IMPLICIT NONE + * TYPE(MAP_InitInputType_C) fc_init + * CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fc_char + * INTEGER(KIND=C_INT) :: fc_int + * END SUBROUTINE mapextern_map_set_summary_file_name + * END INTERFACE + * + * ... + * + * ! access the function using this subroutine call: + * CALL mapextern_map_set_summary_file_name(InitInp%C_obj, ErrMsg, ErrStat) + * @endcode + * @todo: need to free summary_file_name. This is done in delete_all_init_data(...), should be called in Fortran routines + */ +MAP_EXTERNCALL void map_set_summary_file_name(MAP_InitInputType_t* init_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Obtains the variable name array corresponding to the outputs selected in the MAP input file. For example, + * str_array can be: + * <pre> + * X[2] H[1] X[6] H[3] X[10] H[5] X[14] H[7] + * </pre> + * @param n number of header blocks. Should be proportional to the number of itms being output to the FAST output file + * @param str_array the string being output. + * @param other_type Fortran other state derived type + * + * Example Fortran usage: + * @code + * ! Interface block declaration: + * INTERFACE + * SUBROUTINE mapextern_map_get_header_string(fc_int, fc_string, fc_other) BIND(C,name='map_get_header_string') + * IMPORT + * IMPLICIT NONE + * INTEGER(KIND=C_INT) :: fc_int + * TYPE( MAP_OtherStateType_C ) fc_other + * TYPE(C_PTR), DIMENSION(FC_int) :: fc_string + * END SUBROUTINE mapextern_map_get_header_string + * END INTERFACE + * + * ... + * + * ! access the function using this subroutine call: + * CALL mapextern_map_get_header_string(num_header_str, hdr_str_ptrs, other%C_obj) + * @endcode + * @todo this should raise and error when count!=n + */ +MAP_EXTERNCALL void map_get_header_string(int* n, char** str_array, MAP_OtherStateType_t* other_type); + + +/** + * @brief Obtains the units of the outputs passed back to the calling program. str_array can be: + * <pre> + * [m] [N] [m] [N] [m] [N] [m] [N] + * </pre> + * @param n number of header blocks. Should be proportional to the number of itms being output to the FAST output file + * @param str_array the string being output. + * @param other_type Fortran other state derived type + * + * Example Fortran usage: + * @code + * ! Interface block declaration: + * INTERFACE + * SUBROUTINE mapextern_map_get_unit_string(fc_int, fc_string, fc_other) BIND(C,name='map_get_unit_string') + * IMPORT + * IMPLICIT NONE + * INTEGER(KIND=C_INT) :: fc_int + * TYPE(MAP_OtherStateType_C) fc_other + * TYPE(C_PTR), DIMENSION(FC_int) :: fc_string + * END SUBROUTINE mapextern_map_get_unit_string + * END INTERFACE + * + * ... + * ! access the function using this subroutine call: + * CALL mapextern_map_get_header_string(num_header_str, unit_str_ptrs, other%C_obj) + * @endcode + * @todo this should raise and error when count!=n + */ +MAP_EXTERNCALL void map_get_unit_string(int* n, char** str_array ,MAP_OtherStateType_t* other_type); + + +/** + * @brief Allocate InitializationData + * @details Called by {@link map_create_init_type} to allocate memory for the iinitialization + * data type. The reason why a layer is added to the initialization data is due to + * Fortran interactions. It is straighforward to pass 1D character arrays between + * Fortran and C instead of 2D arrays. 2D arrays would make more sense since multiple + * lines from the MAP input file can be packed in one step. {@link MAP_InitInputType_t} + * in responsible for the 1D arrays. which are passed from Fortran to C. MAP then takes + * the 1D aray and packs it into InitializationData. This is used to subsequently + * initialize the model. Structure is free'd by calling {@link MAP_InitInput_Delete}. + * @param map_msg, error message + * @param ierr, error code + * @return instance of the packed initialization strings (different from the FAST-required derived types) + */ +MAP_EXTERNCALL InitializationData* MAP_InitInput_Create(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_InitInputType_t and InitializationData + * @details Called to allocate memory for the initialzation data for both the Fortran + * derived data and internal state data. Following sucessful allocation, + * {@link initialize_init_type_to_null} and {@link initialize_init_data_to_null} + * are both called to nullify data. If not called, memory errors results. This should + * the first function called when interacting with MAP. This is a necessary function for + * interaction with python and C based programs + * @param map_msg, error message + * @param ierr, error code + * @return initialization input type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_InitInputType_t* map_create_init_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate Domain + * @details Called by {@link map_create_other_type} to allocate memory for the internal + * state (model) data type. 'Other States', as FAST calls them, are states not + * fitting a regular role as a parameter, constraint, input, ect. Other states + * contain information on the line connectivity matrix, how reference to poperties + * for each line, buoyancy properties of the nodes, ect. Deallocated using + * interaction with python and C based programs. Structure is free'd by calling + * {@link MAP_OtherState_Delete}. + * @param map_msg, error message + * @param ierr, error code + * @see map_create_other_type() + * @return instance of the interal model struct (different from the FAST-required derived types) + */ +MAP_EXTERNCALL Domain* MAP_OtherState_Create(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_OtherStateType_t and Domain + * @details Called to allocate memory for the other states for both the Fortran + * derived data and internal state data. This is a necessary function for + * interaction with python and C based programs. The + * @param map_msg, error message + * @param ierr, error code + * @return other state type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_OtherStateType_t* map_create_other_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_InitOutputType_t + * @details Called to allocate memory for the initialization output type. The only obligation of + * this struct is to store the program version, necessary for FAST. This function is a + * necessary call for C and python, but can be ignored for Fortran if the MAP template + * is followed (that is, ISO C Binding is followed in the mapping of Fortran type and C + * structures). + * @param map_msg, error message + * @param ierr, error code + * @return initialization output type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_InitOutputType_t* map_create_initout_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_InputType_t + * @details Called to allocate memory for the input type. The program inputs are the fairlead + * displacement due to the motion of the vessel the cable are attached to. This function + * is a necessary call for C and python, but can be ignored for Fortran if the MAP + * template is followed (that is, ISO C Binding is followed in the mapping of Fortran + * type and C structures). + * @param map_msg, error message + * @param ierr, error code + * @return input type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_InputType_t* map_create_input_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_ParameterType_t + * @details Called to allocate memory for the parameter type. Parameters are time-invariant + * constants, such as gravitational constant. This function + * is a necessary call for C and python, but can be ignored for Fortran if the MAP + * template is followed (that is, ISO C Binding is followed in the mapping of Fortran + * type and C structures). + * @param map_msg, error message + * @param ierr, error code + * @return parameter type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_ParameterType_t* map_create_parameter_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_ConstraintType_t + * @details Called to allocate memory for the constraint type. Constraints are variables solved + * through an algebraic equation. This is fairlead end forces (H and V) and node positions. + * This function is a necessary call for C and python, but can be ignored for Fortran if + * the MAP template is followed (that is, ISO C Binding is followed in the mapping of Fortran + * type and C structures). + * @param map_msg, error message + * @param ierr, error code + * @return constraint type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_ConstraintStateType_t* map_create_constraint_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_OutputType_t + * @details Called to allocate memory for the output type. IMPORTANT: this is different from the {@link OutList}. + * Output types are forces at the line fairlead only for lines connecting to the vessel. + * This function is a necessary call for C and python, but can be ignored for Fortran if + * the MAP template is followed (that is, ISO C Binding is followed in the mapping of Fortran + * type and C structures). + * @param map_msg, error message + * @param ierr, error code + * @return output type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_OutputType_t* map_create_output_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Allocate MAP_ContinuousStateType_t + * @details Called to allocate memory for the coninuous type. Not currently used, but it still is + * required to be allocated for FAST consistentcy. + * @param map_msg, error message + * @param ierr, error code + * @return continuous type (equivalent C binding struct) + */ +MAP_EXTERNCALL MAP_ContinuousStateType_t* map_create_continuous_type(char* map_msg, MAP_ERROR_CODE* ierr); + + +#endif /* _MAPAPI_H */ diff --git a/OpenFAST/modules/map/src/maperror.c b/OpenFAST/modules/map/src/maperror.c new file mode 100644 index 000000000..9fcf60f73 --- /dev/null +++ b/OpenFAST/modules/map/src/maperror.c @@ -0,0 +1,291 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "maperror.h" +#include "mapinit.h" + + +const char MAP_ERROR_STRING[][256] = { + /* */ "", + /* */ "", + /* */ "", + /* */ "", + /* MAP_FATAL_4 */ "Failed to allocate memory for 'initializaion data'", + /* MAP_FATAL_5 */ "Failed to allocate memory for 'input data'", + /* MAP_FATAL_6 */ "Failed to allocate memory for 'parameter data'", + /* MAP_FATAL_7 */ "Failed to allocate memory for 'continuous data'", + /* MAP_FATAL_8 */ "Failed to allocate memory for 'model data'", + /* MAP_FATAL_9 */ "Failed to allocate memory for 'constraint data'", + /* MAP_FATAL_10 */ "Failed to allocate memory for 'output data'", + /* MAP_FATAL_11 */ "Failed to allocate memory for 'initialization output data'", + /* MAP_FATAL_12 */ "Failed to convert diameter parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_13 */ "Failed to convert mass density parameter in air in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_14 */ "Failed to convert axial stiffness parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_15 */ "Failed to convert cable/seabed friction parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_16 */ "Could not complete the initialization process in MAP_Init() beause of either syntax errors in the input file or memory allocation problems", + /* MAP_FATAL_17 */ "A Node 'X' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_18 */ "A Node 'Y' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_19 */ "A Node 'Z' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_20 */ "A Node 'M' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_21 */ "A Node 'B' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_22 */ "A Node 'FX' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_23 */ "A Node 'FY' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_24 */ "A Node 'FZ' VarType could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_25 */ "Node is assigned an invalid type", + /* MAP_FATAL_26 */ "Line unstretched length could not be converted to a numeric value. Check the MAP input file", + /* MAP_FATAL_27 */ "Invalid line LineType assignment. Cannot find a LineType in the line dictionary. Check the MAP input file for consistency", + /* MAP_FATAL_28 */ "NodeAnch is assigned an invalid node: can not convert value to a float. Check the MAP input file", + /* MAP_FATAL_29 */ "NodeFair is assigned an invalid node: can not convert value to a float. Check the MAP input file", + /* MAP_FATAL_30 */ "Attempting to assign an invalid anchor node to an line", + /* MAP_FATAL_31 */ "Attempting to assign an invalid fairlead node to an line", + /* MAP_FATAL_32 */ "An line property is set incorrectly in the MAP input file", + /* MAP_FATAL_33 */ "Could not complete the initialization process in MAP_Init() because of syntax errors in the MAP input file. Check the 'MODEL OPTIONS' section of the MAP input file", + /* MAP_FATAL_34 */ "Could convert a 'REPEAT' parameter to a numeric value. Check the MAP input file", + /* MAP_FATAL_35 */ "Failed to allocate memory for the 'REPEAT' array", + /* MAP_FATAL_36 */ "Vessel reference origin 'REF_POSITION' is not set correctly. Correct format is 'REF_POSITION xval yval zval'. Check the MAP input file", + /* MAP_FATAL_37 */ "Failed to write the MAP summary file", + /* MAP_FATAL_38 */ "Could not create the summary file.", + /* MAP_FATAL_39 */ "Could not run the first solve. Solver option (INNER_FTOL, INNER_GTOL, INNER_XTOL, INNER_MAX_ITS) could be inadvertendly set to a negative value or line geometry/line cable library is not properly defined", + /* MAP_FATAL_40 */ "Number of function calls has reached or exceeded INNER_MAX_ITS", + /* MAP_FATAL_41 */ "Cable mass density is zero. Neutrally buoyant cables cannot be solved using quasi-statis model", + /* MAP_FATAL_42 */ "Indexing error", + /* MAP_FATAL_43 */ "Failed to allocate memory for 'other data'", + /* MAP_FATAL_44 */ "Failed to allocate memory for internal state 'z'", + /* MAP_FATAL_45 */ "Failed to allocate memory for internal state 'u'", + /* MAP_FATAL_46 */ "Failed to allocate memory for internal state 'y'", + /* MAP_FATAL_47 */ "Out of memory", + /* MAP_FATAL_48 */ "init internal state does not exist. Memory allocation error", + /* MAP_FATAL_49 */ "Length of internal other state array and fortran derivived type do not match", + /* MAP_FATAL_50 */ "Length of internal input state array and fortran derivived type do not match", + /* MAP_FATAL_51 */ "Length of internal output state array and fortran derivived type do not match", + /* MAP_FATAL_52 */ "Length of internal constraint state array and fortran derivived type do not match", + /* MAP_FATAL_53 */ "Could not allocate memory for H/V constraint state", + /* MAP_FATAL_54 */ "Local cooridinates are computed incorrectly. Line horizontal excusion is negative", + /* MAP_FATAL_55 */ "Local cooridinates are computed incorrectly. Line vertical excusion is negative", + /* MAP_FATAL_56 */ "Line unstretched length cannot be negative", + /* MAP_FATAL_57 */ "Line axial stiffness cannot be negative", + /* MAP_FATAL_58 */ "Unstretched line length is too large for the quasi-static model (double backing). Use the 'OMIT_CONTACT' flag to suppress this error", + /* MAP_FATAL_59 */ "Approached a geometric limitation that the MSQS model is unable to solve", + /* MAP_FATAL_60 */ "Solver failed in updates", + /* MAP_FATAL_61 */ "Failed during linearization process", + /* MAP_FATAL_62 */ "Failed during linearization process: fd on surge direction", + /* MAP_FATAL_63 */ "Failed during linearization process: fd on sway direction", + /* MAP_FATAL_64 */ "Failed during linearization process: fd on heave direction", + /* MAP_FATAL_65 */ "Failed during linearization process: fd on roll direction", + /* MAP_FATAL_66 */ "Failed during linearization process: fd on pitch direction", + /* MAP_FATAL_67 */ "Failed during linearization process: fd on yaw direction", + /* MAP_FATAL_68 */ "Failed in nullifying the vessel properties", + /* MAP_FATAL_69 */ "Failed to allocate memory for the vessel", + /* MAP_FATAL_70 */ "Failed to write node information to the MAP summary file", + /* MAP_FATAL_71 */ "Assigning 'DEPTH' parameter to a node that is not fixed", + /* MAP_FATAL_72 */ "Failed to allocate memory for outer loop solution", + /* MAP_FATAL_73 */ "Failed to free memory for outer loop solution", + /* MAP_FATAL_74 */ "Zero pivot detected in LU factorization. Simulation terminated", + /* MAP_FATAL_75 */ "Backward difference Jacobian failed", + /* MAP_FATAL_76 */ "Central difference Jacobian failed", + /* MAP_FATAL_77 */ "Forward difference Jacobian failed", + /* MAP_FATAL_78 */ "Line line failed to converge durring finite difference operation, Outer-loop Jacbobian failure", + /* MAP_FATAL_79 */ "Solution failed in MinPack LMDER", + /* MAP_FATAL_80 */ "Maximum outer-loop iterations reached", + /* MAP_FATAL_81 */ "Failed to convert CIntDamp internal structural damping parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_82 */ "Failed to convert Ca added mass in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_83 */ "Failed to convert Cdn cross-flow drag coefficient parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_84 */ "Failed to convert Cdt tangent-flow drag coefficient parameter in the cable library to a double. Check the MAP input file", + /* MAP_FATAL_85 */ "Error processing 'HELP' flag in the MAP input file", + /* MAP_FATAL_86 */ "Line out of range. This error was triggered in the initialization. This is likely due to incorrect settings in the MAP input file", + /* MAP_FATAL_87 */ "Line linear spring solver failed", + /* MAP_FATAL_88 */ "Line failed", + /* MAP_FATAL_89 */ "Input index array exceeded during UpdateStates. Inputs were not set correctly by the program", + /* MAP_FATAL_90 */ "L^2 norm is too large. MAP may not have converged", + /* MAP_FATAL_91 */ "Krylov acceleration routine failure", + /* MAP_FATAL_92 */ "Failed inside Newton foot-finding iteration", + /* MAP_FATAL_93 */ "Newton failed to converge inside the node sequece. Try adjusting tolerance levels or change Krylov accelerator: option 'KRYLOV_ACCELERATOR <int>'", + /* MAP_FATAL_94 */ "Krylov accelerator failed to converge inside the node solve sequence. Try adjusting tolerance levels or switch to the unmodified Newton step", + /* MAP_FATAL_95 */ "Could not create the MAP initialization output file", + /* MAP_FATAL_96 */ "Atempting to run option KRYLOV_ACCELERATOR without LAPACK libraries compiled in. This option is not available without the LAPACK library", + /* MAP_FATAL_97 */ "Cannot associate constraint variable in map_update_states", + /* MAP_FATAL_98 */ "Cannot associate constraint variable in map_calc_output", + /* MAP_ERROR_1 */ "Line option 'DAMGE_TIME' does not trail with a valid value. Ignoring this run-time flag. Chek the MAP input file", + /* MAP_ERROR_2 */ "Value for 'INNER_FTOL' is not a valid numeric value. Using the default value <1e-6>", + /* MAP_ERROR_3 */ "Value for 'OUTER_TOL' is not a valid numeric value. Using the default value <1e-6>", + /* MAP_ERROR_4 */ "Value for 'INNER_MAX_ITS' is not a valid numeric value. Using the default value <500>", + /* MAP_ERROR_5 */ "Value for 'OUTER_MAX_ITS' is not a valid numeric value. Using the default value <500>", + /* MAP_ERROR_6 */ "Failed to write cable library information to the MAP summary file", + /* MAP_ERROR_7 */ "Failed to write node information to the MAP summary file", + /* MAP_ERROR_8 */ "Failed to write line information to the MAP summary file", + /* MAP_ERROR_9 */ "Value for 'INNER_GTOL' is not a valid numeric value. Using the default value <1e-6>", + /* MAP_ERROR_10 */ "Value for 'INNER_XTOL' is not a valid numeric value. Using the default value <1e-6>", + /* MAP_ERROR_11 */ "INNER_FTOL is too small. No further reduction in the sum of squares is possible", + /* MAP_ERROR_12 */ "INNER_GTOL is too small. No further reduction in the sum of squares is possible", + /* MAP_ERROR_13 */ "INNER_XTOL is too small. No further reduction in the sum of squares is possible", + /* MAP_ERROR_14 */ "Line option 'DIAGNOSTIC' does not trail with a valid value. Defaulting is to run diagnostic for the first iteration only", + /* MAP_ERROR_15 */ "Value for 'INTEGRATION_DT' is not a valid input. No support for the LM/FEA model at this time", + /* MAP_ERROR_16 */ "Value for 'KB_DEFAULT' is not a valid numeric value. Using the default value <3.0E6 N/m>", + /* MAP_ERROR_17 */ "Value for 'CB_DEFAULT' is not a valid numeric value. Using the default value <3.0E5 Ns/m>", + /* MAP_ERROR_18 */ "Value for 'SEG_SIZE' is not a valid numeric value. Using the default value <10>", + /* MAP_WARNING_1 */ "Extra characters are present in the cable library portion of the MAP input file", + /* MAP_WARNING_2 */ "Extra characters are present in the node library portion of the MAP input file", + /* MAP_WARNING_3 */ "Unrecognized line run-time option", + /* MAP_WARNING_4 */ "Unrecognized run-time option in the MAP input file", + /* MAP_WARNING_5 */ "Cable density is approaching the density of seawater. This may result in the problem becoming poorly conditioned", + /* MAP_WARNING_6 */ "The line's anchor and fairlead point occupy the same point in space", + /* MAP_WARNING_7 */ "Option OUTER_TOL must be greater than machine epsilon. Resetting value back to default (1E-6)", + /* MAP_WARNING_8 */ "Invalid parameters for PG_COOKED option: using default value of ds = 1.0, d = 0.0", + /* MAP_WARNING_9 */ "Attemping to recover from fatal error...", + /* MAP_WARNING_10 */ "Ignoring wave kinematic hydrodynamics. This feature is not available", + /* MAP_WARNING_11 */ "Could not enable the lumped-mass model during initialization", + /* MAP_WARNING_12 */ "Line option 'KRYLOV_ACCELERATOR' does not trail with a valid integer. Defaulting to initialized MMAX value", + /* MAP_WARNING_13 */ "Line options 'KRYLOV_ACCELERATOR' and 'PG_COOKED' are not compatible together. Disabling Krylov acceleration", + /* MAP_WARNING_14 */ "Conflicting options. Cannot use Powell's method in conjuction with KRYLOV_ACCELERATOR or PG_COOKED", + /* MAP_WARNING_15 */ "Failed to free a variable", +}; + + +void set_universal_error(char* map_msg, MAP_ERROR_CODE* ierr, const MAP_ERROR_CODE new_error_code) +{ + int error_number = 0; + int ret = 0; + bstring out_string = NULL; + bstring message = bformat("%s", map_msg); /* first format map_msg to contain previously raised errors */ + + if (new_error_code>=MAP_WARNING_1) { /* MAP did not quite fail. Let users know what the error is */ + error_number = new_error_code-MAP_WARNING_1 + 1; + out_string = bformat("MAP_WARNING[%d] : %s.\n", error_number, MAP_ERROR_STRING[new_error_code]); + if (*ierr<=MAP_WARNING) { + *ierr = MAP_WARNING; + }; + } else if (new_error_code>=MAP_ERROR_1 ) { /* MAP failed but recovered */ + error_number = new_error_code-MAP_ERROR_1+1; + out_string = bformat("MAP_ERROR[%d] : %s.\n", error_number, MAP_ERROR_STRING[new_error_code]); + if (*ierr<=MAP_ERROR) { + *ierr = MAP_ERROR; + }; + } else { /* MAP failed and program must end prematurely */ + error_number = new_error_code; + out_string = bformat("MAP_FATAL[%d] : %s.\n", error_number, MAP_ERROR_STRING[new_error_code]); + *ierr = MAP_FATAL; + }; + + ret = bconcat(message, out_string); + ret = btrunc(message, MAP_ERROR_STRING_LENGTH-1); + copy_target_string(map_msg, message->data); + ret = bdestroy(out_string); + ret = bdestroy(message); +}; + + +void map_reset_universal_error(char* map_msg, MAP_ERROR_CODE* ierr) +{ + *ierr = MAP_SAFE; + map_msg[0] = '\0'; + // strcpy(map_msg, "\0"); +}; + + +void set_universal_error_with_message(char* map_msg, MAP_ERROR_CODE* ierr, const MAP_ERROR_CODE new_error_code, const char* in_string, ...) +{ + va_list arglist; + bstring out_string = NULL; + bstring user_msg = NULL; + bstring message = bformat("%s", map_msg); /* first format map_msg to contain previously raised errors */ + const int START_VSNBUFF = 16; + int error_number = 0; + int ret = 0; + int r = 0; + int n = 0; + + /* This is a re-implementation of the bstring library routines 'bformat(...) + * Take the variable argument list and create a string with it. This lets you + * create a custom message to be rpinted to the terminal. + */ + do { + n = (int)(2*strlen(in_string)); + if (n<START_VSNBUFF) { + n = START_VSNBUFF; + }; + user_msg = bfromcstralloc(n+2, ""); + if (!user_msg) { + n = 1; + user_msg = bfromcstralloc(n+2, ""); + if (!user_msg) { + user_msg = NULL; + break; + }; + }; + while (1) { + va_start(arglist, in_string); +# if !defined(_MSC_VER) + r = vsnprintf((char*)user_msg->data, n+1, in_string, arglist); /* this is a copy of exvsnprintf in bstring library */ +# else + r = vsnprintf_s((char*)user_msg->data, n, _TRUNCATE, in_string, arglist); /* windows way (or ISO C11 Annex K) way of doing things */ + /* This function works, but you need to specify the _CRT_SECURE_NO_WARNINGS compiler flag. Visual Studio hates this: + * r = vsnprintf((char*)user_msg->data, n + 1, in_string, arglist); + */ +# endif + va_end(arglist); + user_msg->data[n] = (unsigned char)'\0'; + user_msg->slen = (int)strlen((char*)user_msg->data); + if (user_msg->slen < n) { + break; + }; + if (r>n) { + n = r; + } else { + n += n; + }; + if (0!=balloc(user_msg, n+2)) { + bdestroy(user_msg); + break; + }; + }; + } while (0); + + if (new_error_code>=MAP_WARNING_1) { + /* MAP did not quite fail. Let users know what the error is */ + error_number = new_error_code - MAP_WARNING_1 + 1; + out_string = bformat("MAP_WARNING[%d] : %s. %s\n", error_number, MAP_ERROR_STRING[new_error_code], user_msg->data); + if (*ierr<=MAP_WARNING) { + *ierr = MAP_WARNING; + }; + } else if (new_error_code>=MAP_ERROR_1 ) { + /* MAP failed but recovered */ + error_number = new_error_code - MAP_ERROR_1+1; + out_string = bformat("MAP_ERROR[%d] : %s. %s\n", error_number, MAP_ERROR_STRING[new_error_code], user_msg->data); + if (*ierr<=MAP_ERROR) { + *ierr = MAP_ERROR; + }; + } else { + /* MAP failed and program must end prematurely */ + error_number = new_error_code; + out_string = bformat("MAP_FATAL[%d] : %s. %s\n", error_number, MAP_ERROR_STRING[new_error_code], user_msg->data); + *ierr = MAP_FATAL; + }; + + ret = bconcat(message, out_string); + ret = btrunc(message, MAP_ERROR_STRING_LENGTH-1); + copy_target_string(map_msg, message->data); + ret = bdestroy(out_string); + ret = bdestroy(message); + ret = bdestroy(user_msg); +}; + diff --git a/OpenFAST/modules/map/src/maperror.h b/OpenFAST/modules/map/src/maperror.h new file mode 100644 index 000000000..bdcd60c11 --- /dev/null +++ b/OpenFAST/modules/map/src/maperror.h @@ -0,0 +1,211 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _MAPERROR_H +#define _MAPERROR_H + + +#include "map.h" +#include <stdarg.h> + + +typedef enum MAP_ERROR_CODE { + MAP_SAFE , // = 0 by default + MAP_WARNING , // = 1 + MAP_ERROR , // = 2 + MAP_FATAL , // = 3 + + // These are used internally to the program and are used to + // map text to the specific error code + MAP_FATAL_4 , // Failed to allocate memory for 'initializaion data' + MAP_FATAL_5 , // Failed to allocate memory for 'input data' + MAP_FATAL_6 , // Failed to allocate memory for 'parameter data' + MAP_FATAL_7 , // Failed to allocate memory for 'continuous data' + MAP_FATAL_8 , // Failed to allocate memory for 'model data' + MAP_FATAL_9 , // Failed to allocate memory for 'constraint data' + MAP_FATAL_10 , // Failed to allocate memory for 'output data' + MAP_FATAL_11 , // Failed to allocate memory for 'initialization output data' + MAP_FATAL_12 , // Failed to convert diameter to double. Check the MAP input file. + MAP_FATAL_13 , // Failed to convert mass density parameter in air in the cable library to a double. Check the MAP input file + MAP_FATAL_14 , // Failed to convert axial stiffness parameter in the cable library to a double. Check the MAP input file + MAP_FATAL_15 , // Failed to convert cable/seabed friction parameter in the cable library to a double. Check the MAP input file + MAP_FATAL_16 , // Could not complete the initialization process in MAP_Init() beause of either syntax errors in the input file or memory allocation problems + MAP_FATAL_17 , // A Node 'X' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_18 , // A Node 'Y' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_19 , // A Node 'Z' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_20 , // A Node 'M' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_21 , // A Node 'B' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_22 , // A Node 'FX' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_23 , // A Node 'FY' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_24 , // A Node 'FZ' VarType could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_25 , // Node is assigned an invalid type + MAP_FATAL_26 , // Line unstretched length could not be converted to a numeric value. Check the MAP input file + MAP_FATAL_27 , // Invalid line LineType assignment. Cannot find a LineType in the line dictionary. Check the MAP input file for consistency + MAP_FATAL_28 , // NodeAnch is an invalid anchor type for an line. can not convert value to a float. Check the MAP input file + MAP_FATAL_29 , // NodeFiar is an invalid anchor type for an line. can not convert value to a float. Check the MAP input file + MAP_FATAL_30 , // Attempting to assign an invalid anchor node to an line + MAP_FATAL_31 , // Attempting to assign an invalid fairlead node to an line + MAP_FATAL_32 , // An line property is set incorrectly in the MAP input file + MAP_FATAL_33 , // Could not complete the initialization process in MAP_Init() beause of syntax errors in the MAP input file. Check the 'MODEL OPTIONS' section of the MAP input file + MAP_FATAL_34 , // Could convert a 'REPEAT' parameter to a numeric value. Check the MAP input file + MAP_FATAL_35 , // Failed to allocate memory for the 'REPEAT' array + MAP_FATAL_36 , // Vessel reference origin is not set correctly. Check the MAP input file + MAP_FATAL_37 , // Failed to write the MAP summary file + MAP_FATAL_38 , // Could not create the summary file + MAP_FATAL_39 , // Could not run the first solve. Solver option (INNER_FTOL, INNER_GTOL, INNER_XTOL, INNER_MAX_ITS) could be inadvertendly set to a negative value + MAP_FATAL_40 , // Number of function calls has reached or exceeded INNER_MAX_ITS + MAP_FATAL_41 , // Cable mass density is zero. Neutrally buoyant cables cannot be solved using quasi-statis model + MAP_FATAL_42 , // Indexing error + MAP_FATAL_43 , // Failed to allocate memory for 'other data' + MAP_FATAL_44 , // Failed to allocate memory for internal state 'z' + MAP_FATAL_45 , // Failed to allocate memory for internal state 'u' + MAP_FATAL_46 , // Failed to allocate memory for internal state 'y' + MAP_FATAL_47 , // Out of memory + MAP_FATAL_48 , // init internal state does not exist. Memory allocation error + MAP_FATAL_49 , // Length of internal other state array and fortran derivived type do not match + MAP_FATAL_50 , // Length of internal input state array and fortran derivived type do not match + MAP_FATAL_51 , // Length of internal output state array and fortran derivived type do not match + MAP_FATAL_52 , // Length of internal constraint state array and fortran derivived type do not match + MAP_FATAL_53 , // Could not allocate memory for H/V constraint state + MAP_FATAL_54 , // Local cooridinates are computed incorrectly. Line horizontal excusion is negative + MAP_FATAL_55 , // Local cooridinates are computed incorrectly. Line vertical excusion is negative + MAP_FATAL_56 , // Line unstretched length cannot be negative + MAP_FATAL_57 , // Line axial stiffness cannot be negative + MAP_FATAL_58 , // Unstretched line length is too large for the quasi-static model (double backing) + MAP_FATAL_59 , // Approached a geometric limitation that the MSQS model is unable to solve + MAP_FATAL_60 , // Solver failed in updates + MAP_FATAL_61 , // Failed during linearization process + MAP_FATAL_62 , // Failed during linearization process: fd on surge direction + MAP_FATAL_63 , // Failed during linearization process: fd on sway direction + MAP_FATAL_64 , // Failed during linearization process: fd on heave direction + MAP_FATAL_65 , // Failed during linearization process: fd on roll direction + MAP_FATAL_66 , // Failed during linearization process: fd on pitch direction + MAP_FATAL_67 , // Failed during linearization process: fd on yaw direction + MAP_FATAL_68 , // Failed in nullifying the vessel properties + MAP_FATAL_69 , // Failed to allocate memory for the vessel + MAP_FATAL_70 , // Failed to write node information to the MAP summary file + MAP_FATAL_71 , // Assigning 'DEPTH' parameter to a node that is not fixed + MAP_FATAL_72 , // Failed to allocate memory for outer loop solution + MAP_FATAL_73 , // Failed to free memory for outer loop solution + MAP_FATAL_74 , // Zero pivot detected in LU factorization. Simulation terminated + MAP_FATAL_75 , // Backward difference Jacobian failed. + MAP_FATAL_76 , // Central difference Jacobian failed. + MAP_FATAL_77 , // Forward difference Jacobian failed. + MAP_FATAL_78 , // Line line failed to converge durring finite difference operation. Outer-loop Jacbobian failure: + MAP_FATAL_79 , // Solution failed in MinPack LMDER + MAP_FATAL_80 , // Maximum outer-loop iterations reached + MAP_FATAL_81 , // Failed to convert CIntDamp internal structural damping parameter in the cable library to a double. Check the MAP input file + MAP_FATAL_82 , // Failed to convert Ca added mass in the cable library to a double. Check the MAP input file + MAP_FATAL_83 , // Failed to convert Cdn cross-flow drag coefficient parameter in the cable library to a double. Check the MAP input file + MAP_FATAL_84 , // Failed to convert Cdt tangent-flow drag coefficient parameter in the cable library to a double. Check the MAP input file + MAP_FATAL_85 , // Error processing 'HELP' flag in the MAP input file + MAP_FATAL_86 , // Line out of range. This error was triggered in the initialization. This is likely due to incorrect settings in the MAP input file + MAP_FATAL_87 , // Line linear spring solver failed. + MAP_FATAL_88 , // Line failed + MAP_FATAL_89 , // Input index array exceeded during UpdateStates. Inputs were not set correctly by the program + MAP_FATAL_90 , // L^2 norm is too large. MAP may not have converged + MAP_FATAL_91 , // Krylov acceleration routine failure + MAP_FATAL_92 , // Failed inside Newton foot-finding iteration + MAP_FATAL_93 , // Newton failed to converge inside the node sequece. Try adjusting tolerance levels or change Krylov accelerator: option 'KRYLOV_ACCELERATOR <int>'", + MAP_FATAL_94 , // Krylov accelerator failed to converge inside the node solve sequence. Try adjusting tolerance levels or switch to the unmodified Newton step", + MAP_FATAL_95 , // Could not create the MAP initialization output file + MAP_FATAL_96 , // Atempting to run option KRYLOV_ACCELERATOR without LAPACK libraries compiled in. This option is not available without the LAPACK library + MAP_FATAL_97 , // Cannot associate constriaint variable in UpdateStates", + MAP_FATAL_98 , // Cannot associate constriaint variable in CalcOutput", + MAP_ERROR_1 , // Line option 'DAMAGE_TIME' does not trail with a valid value. Ignoring this run-time flag. Chek the MAP input file + MAP_ERROR_2 , // Value for 'INNER_FTOL' is not a valid numeric value. Using the default value <1e-6> + MAP_ERROR_3 , // Value for 'OUTER_TOL' is not a valid numeric value. Using the default value <1e-6> + MAP_ERROR_4 , // Value for 'INNER_MAX_ITS' is not a valid numeric value. Using the default value <500> + MAP_ERROR_5 , // Value for 'OUTER_MAX_ITS' is not a valid numeric value. Using the default value <500> + MAP_ERROR_6 , // Failed to write cable library information to the MAP summary file + MAP_ERROR_7 , // Failed to write node information to the MAP summary file + MAP_ERROR_8 , // Failed to write line information to the MAP summary file + MAP_ERROR_9 , // Value for 'INNER_GTOL' is not a valid numeric value. Using the default value <1e-6> + MAP_ERROR_10 , // Value for 'INNER_XTOL' is not a valid numeric value. Using the default value <1e-6> + MAP_ERROR_11 , // INNER_FTOL is too small. No further reduction in the sum of squares is possible + MAP_ERROR_12 , // INNER_GTOL is too small. No further reduction in the sum of squares is possible + MAP_ERROR_13 , // INNER_XTOL is too small. No further reduction in the sum of squares is possible + MAP_ERROR_14 , // Line option 'DIAGNOSTIC' does not trail with a valid value. Defaulting is to run diagnostic for the first iteration only + MAP_ERROR_15 , // Value for 'INTEGRATION_DT' is not a valid input. No support for the LM/FEA model at this time. + MAP_ERROR_16 , // Value for 'KB_DEFAULT' is not a valid numeric value. Using the default value <3.0E6 N/m> + MAP_ERROR_17 , // Value for 'CB_DEFAULT' is not a valid numeric value. Using the default value <3.0E5 Ns/m> + MAP_ERROR_18 , // Value for 'SEG_SIZE' is not a valid numeric value. Using the default value <10> + MAP_WARNING_1 , // Extra characters are present in the cable library portion of the MAP input file + MAP_WARNING_2 , // Extra characters are present in the node library portion of the MAP input file + MAP_WARNING_3 , // Unrecognized line run-time option + MAP_WARNING_4 , // Unrecognized model option + MAP_WARNING_5 , // Cable density is approaching the density of seawater + MAP_WARNING_6 , // The line's anchor and fairlead point occupy the same point in space. + MAP_WARNING_7 , // Option outer_tol must be greater than machine epsilon + MAP_WARNING_8 , // Invalid parameters for PG_COOKED option: using default value of ds = 1.0, d = 0.0 + MAP_WARNING_9 , // Attemping to recover from fatal error by back tracking... + MAP_WARNING_10, // Ignoring wave kinematic hydrodynamics. This feature is not available + MAP_WARNING_11, // Could not enable the lumped-mass model during initialization + MAP_WARNING_12, // Line option 'KRYLOV_ACCELERATOR' does not trail with a valid integer. Defaulting to initialized MMAX value + MAP_WARNING_13, // Line options 'KRYLOV_ACCELERATOR' and 'PG_COOKED' are not compatible together. Disabling Krylov acceleration + MAP_WARNING_14, // Conflicting options. Cannot use Powell's method in conjuction with KRYLOV_ACCELERATOR or PG_COOKED + MAP_WARNING_15, // Failed to free a variable +} MAP_ERROR_CODE ; + + +/** + * @brief Reset error code and message with MAP_SAFE and an empty string + * @details Function should be called at the beinging of each API entry point + * @param map_msg, error message of length no greater than MAP_ERROR_STRING_LENGTH + * @param ierr, ierr status before function is invoked, should be MAP_SAFE, MAP_WARNING, MAP_ERROR, MAP_FATAL + */ +void map_reset_universal_error(char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Set error code with customized message + * @details This function is used to create a customized message printied to the terminal + * Can be called in any routine to set the contents of map_message. The routine + * checks to ensure map_msg is not longer than MAX_ERROR_STRING_LENGTH. If it is, + * then the message is truncated. The error code returned depends on the max + * level reached previously durring program execusion. A MAP_WARNING will not + * override a MAP_FATAL or MAP_ERROR level. + * @param map_msg, error message of length no greater than MAP_ERROR_STRING_LENGTH + * @param ierr, ierr status before function is invoked, should be MAP_SAFE, MAP_WARNING, MAP_ERROR, MAP_FATAL + * @param new_error_code, new MAP warning code; any entry in enum MAP_ERROR_CODE + * @param in_string, input string + * @param ..., variable argument input list + */ +void set_universal_error_with_message(char* map_msg, MAP_ERROR_CODE* ierr, const MAP_ERROR_CODE new_error_code, const char* in_string, ...); + + +/** + * @brief Set error code with customized message + * @details Can be called in any routine to set the contents of map_message. The routine + * checks to ensure map_msg is not longer than MAX_ERROR_STRING_LENGTH. If it is, + * then the message is truncated. The error code returned depends on the max + * level reached previously durring program execusion. A MAP_WARNING will not + * override a MAP_FATAL or MAP_ERROR level. + * @param map_msg, error message of length no greater than MAP_ERROR_STRING_LENGTH + * @param ierr, status before function is invoked, should be MAP_SAFE, MAP_WARNING, MAP_ERROR, MAP_FATAL + * @param new_error_code, new MAP warning code; any entry in enum MAP_ERROR_CODE * + */ +void set_universal_error(char* map_msg, MAP_ERROR_CODE* ierr, const MAP_ERROR_CODE new_error_code); + + +#endif // _MAPERROR_H diff --git a/OpenFAST/modules/map/src/mapinit.c b/OpenFAST/modules/map/src/mapinit.c new file mode 100644 index 000000000..2f9564c5d --- /dev/null +++ b/OpenFAST/modules/map/src/mapinit.c @@ -0,0 +1,2880 @@ +/*--------------------------------------------------------------- + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ---------------------------------------------------------------*/ + + +#include "mapinit.h" +#include "lineroutines.h" +#include "outputstream.h" + + +extern const char MAP_ERROR_STRING[][1024]; + + +MAP_ERROR_CODE initialize_fortran_types(MAP_InputType_t* u_type, + MAP_ParameterType_t* p_type, + MAP_ContinuousStateType_t* x_type, + MAP_ConstraintStateType_t* z_type, + MAP_OtherStateType_t* other_type, + MAP_OutputType_t* y_type, + MAP_InitOutputType_t* initout_type) +{ + /* parameters are skipped for now; they are set in fortran since depth, + * gravity and sea density are set by glue code + */ + + /* inputs */ + u_type->x = NULL; u_type->x_Len = 0; + u_type->y = NULL; u_type->y_Len = 0; + u_type->z = NULL; u_type->z_Len = 0; + + /* continuous state */ + x_type->dummy=-999.9; + + /* constraint state */ + z_type->H = NULL; z_type->H_Len = 0; + z_type->V = NULL; z_type->V_Len = 0; + z_type->x = NULL; z_type->x_Len = 0; + z_type->y = NULL; z_type->y_Len = 0; + z_type->z = NULL; z_type->z_Len = 0; + + /* other state */ + other_type->H = NULL; other_type->H_Len = 0; + other_type->V = NULL; other_type->V_Len = 0; + other_type->Ha = NULL; other_type->Ha_Len = 0; + other_type->Va = NULL; other_type->Va_Len = 0; + other_type->x = NULL; other_type->x_Len = 0; + other_type->y = NULL; other_type->y_Len = 0; + other_type->z = NULL; other_type->z_Len = 0; + other_type->xa = NULL; other_type->xa_Len = 0; + other_type->ya = NULL; other_type->ya_Len = 0; + other_type->za = NULL; other_type->za_Len = 0; + other_type->Fx_connect = NULL; other_type->Fx_connect_Len = 0; + other_type->Fy_connect = NULL; other_type->Fy_connect_Len = 0; + other_type->Fz_connect = NULL; other_type->Fz_connect_Len = 0; + other_type->Fx_anchor = NULL; other_type->Fx_anchor_Len = 0; + other_type->Fy_anchor = NULL; other_type->Fy_anchor_Len = 0; + other_type->Fz_anchor = NULL; other_type->Fz_anchor_Len = 0; + + /* outputs */ + y_type->Fx = NULL; y_type->Fx_Len = 0; + y_type->Fy = NULL; y_type->Fy_Len = 0; + y_type->Fz = NULL; y_type->Fz_Len = 0; + y_type->wrtOutput = NULL; y_type->wrtOutput_Len = 0; + y_type->WriteOutput = NULL; y_type->WriteOutput_Len = 0; + + /* init outputs */ + initout_type->progName[0] = '\0' ; + initout_type->version[0] = '\0'; + initout_type->compilingData[0] = '\0'; + initout_type->writeOutputHdr = NULL; initout_type->writeOutputHdr_Len = 0; + initout_type->writeOutputUnt = NULL; initout_type->writeOutputUnt_Len = 0; + + return MAP_SAFE; +}; + + +void initialize_init_type_to_null(MAP_InitInputType_t* init_type) +{ + /* initialize the native Fortran/C types */ + init_type->gravity = -999.9; + init_type->sea_density = -999.9; + init_type->depth = -999.9; + init_type->file_name[0] = '\0'; + init_type->summary_file_name[0] = '\0'; + init_type->library_input_str[0] = '\0'; + init_type->node_input_str[0] = '\0'; + init_type->line_input_str[0] = '\0'; + init_type->option_input_str[0] = '\0'; +}; + + + +void initialize_init_data_to_null(InitializationData* init_data) +{ + /* initialize the MAP initialization internal data strcture */ + init_data->library_input_string = bstrListCreate(); + init_data->node_input_string = bstrListCreate(); + init_data->line_input_string = bstrListCreate(); + init_data->solver_options_string = bstrListCreate(); + init_data->expanded_node_input_string = bstrListCreate(); + init_data->expanded_line_input_string = bstrListCreate(); +}; + + +void initialize_domain_to_null(Domain* domain) +{ + domain->MAP_SOLVE_TYPE = -999; + domain->y_list = NULL; + initialize_inner_solve_data_defaults(&domain->inner_loop); + initialize_outer_solve_data_defaults(&domain->outer_loop); + initialize_vessel_to_null(&domain->vessel); + initialize_model_option_defaults(&domain->model_options); +}; + + +size_t cable_line_meter(const void *el) +{ + return sizeof(Line); +}; + + +size_t cable_library_meter(const void *el) +{ + return sizeof(CableLibrary); +}; + + +size_t node_meter(const void *el) +{ + return sizeof(Node); +}; + + +size_t u_list_meter(const void *el) +{ + return sizeof(ReferencePoint); +}; + + +size_t vartype_meter(const void* el) +{ + /* every line has the constant size of a rectangle structure */ + return sizeof(VarType); +}; + + +size_t vartype_ptr_meter(const void* el) +{ + /* every line has the constant size of a rectangle structure */ + return sizeof(VarTypePtr); +}; + + +MAP_ERROR_CODE allocate_outlist(Domain* data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + data->y_list = malloc(sizeof(OutputList)); + if (data->y_list==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_46); + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +void initialize_inner_solve_data_defaults(InnerSolveAttributes* inner) +{ + inner->f_tol = 1e-6; + inner->g_tol = 1e-6; + inner->x_tol = 1e-6; + inner->max_its = 500; + inner->m = 2; + inner->n = 2; + inner->factor = 1.0E2; + inner->factor = 1.0E2; + inner->ldfjac = 2; + inner->mode = 1; + inner->nprint = 2; + inner->info = 0; +}; + + +void initialize_model_option_defaults(DomainOptions* options) +{ + options->repeat_angle_size = 0; + options->repeat_angle = NULL; + options->integration_dt = 0.01; + options->kb_lm = 3.0E6; + options->cb_lm = 3.0E5; + options->wave_kinematics = false; + options->lm_model = false; +}; + + +/* + + +*/ + +/* deallocated in free_outer_solve_data() */ +void initialize_outer_solve_data_defaults(OuterSolveAttributes* outer) +{ + outer->fd = BACKWARD_DIFFERENCE; + outer->pg = false; + outer->krylov_accelerator = false; + outer->powell = false; + outer->tol = 1e-6; + outer->epsilon = 1e-3; + outer->max_its = 500; + outer->jac = NULL; + outer->x = NULL; + outer->b = NULL; + outer->l = NULL; + outer->u = NULL; + outer->y = NULL; + + outer->max_krylov_its = 3; + outer->AV = NULL; + outer->V = NULL; + outer->av = NULL; + outer->C = NULL; + outer->q = NULL; + outer->w = NULL; +}; + + +void initialize_vessel_to_null(Vessel* floater) +{ + floater->xi = NULL; + floater->yi = NULL; + floater->zi = NULL; + + floater->displacement.x.name = NULL; + floater->displacement.y.name = NULL; + floater->displacement.z.name = NULL; + floater->ref_origin.x.name = NULL; + floater->ref_origin.y.name = NULL; + floater->ref_origin.z.name = NULL; + floater->line_sum_force.fx.name = NULL; + floater->line_sum_force.fy.name = NULL; + floater->line_sum_force.fz.name = NULL; + floater->orientation.phi.name = NULL; + floater->orientation.the.name = NULL; + floater->orientation.psi.name = NULL; + + floater->displacement.x.units = NULL; + floater->displacement.y.units = NULL; + floater->displacement.z.units = NULL; + floater->ref_origin.x.units = NULL; + floater->ref_origin.y.units = NULL; + floater->ref_origin.z.units = NULL; + floater->line_sum_force.fx.units = NULL; + floater->line_sum_force.fy.units = NULL; + floater->line_sum_force.fz.units = NULL; + floater->orientation.phi.units = NULL; + floater->orientation.the.units = NULL; + floater->orientation.psi.units = NULL; + + floater->ref_origin.x.value = 0.0; + floater->ref_origin.y.value = 0.0; + floater->ref_origin.z.value = 0.0; +}; + + +MAP_ERROR_CODE set_vessel(Vessel* floater, const MAP_InputType_t* u_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int n = u_type->x_Len; + + MAP_BEGIN_ERROR_LOG; + + /* vessel displacement */ + success = set_vartype_float("[m]", "Vessel_X", -999, &floater->displacement.x, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[m]", "Vessel_Y", -999, &floater->displacement.y, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[m]", "Vessel_Z", -999, &floater->displacement.z, 0.0); CHECKERRQ(MAP_FATAL_68); + + /* vessel reference origin. When ==[0.0, 0.0, 0.0], then the reference origin is aligned with the SWL + * Note: this is commented because it over rides the run-time option 'REF_POSITION'. Instead, the ref position is + * initialized to zero in function void initialize_vessel_to_null(Vessel* floater) + */ + //success = set_vartype_float("[m]", "Vessel_Xref", -999, &floater->ref_origin.x, 0.0); CHECKERRQ(MAP_FATAL_68); + //success = set_vartype_float("[m]", "Vessel_Yref", -999, &floater->ref_origin.y, 0.0); CHECKERRQ(MAP_FATAL_68); + //success = set_vartype_float("[m]", "Vessel_Zref", -999, &floater->ref_origin.z, 0.0); CHECKERRQ(MAP_FATAL_68); + + /* sum force of all fairleads connecte to the vessel */ + success = set_vartype_float("[N]", "Vessel_fx", -999, &floater->line_sum_force.fx, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[N]", "Vessel_fy", -999, &floater->line_sum_force.fy, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[N]", "Vessel_fz", -999, &floater->line_sum_force.fz, 0.0); CHECKERRQ(MAP_FATAL_68); + + /* orientation of the vessel. This is used as input from the user */ + success = set_vartype_float("[deg]", "Vessel_phi", -999, &floater->orientation.phi, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[deg]", "Vessel_the", -999, &floater->orientation.the, 0.0); CHECKERRQ(MAP_FATAL_68); + success = set_vartype_float("[deg]", "Vessel_psi", -999, &floater->orientation.psi, 0.0); CHECKERRQ(MAP_FATAL_68); + + MAP_END_ERROR_LOG; + + floater->xi = malloc(n*sizeof(double)); + floater->yi = malloc(n*sizeof(double)); + floater->zi = malloc(n*sizeof(double)); + + if (floater->xi==NULL || floater->yi==NULL || floater->zi==NULL) { + return MAP_FATAL; + }; + + for (i=0 ; i<n ; i++) { + floater->xi[i] = u_type->x[i]; + floater->yi[i] = u_type->y[i]; + floater->zi[i] = u_type->z[i]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE first_solve(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + + if (domain->MAP_SOLVE_TYPE==MONOLITHIC) { + success = line_solve_sequence(domain, p_type, 0.0, map_msg, ierr); /* @todo CHECKERRQ() */ + } else { + success = node_solve_sequence(domain, p_type, u_type, z_type, other_type, 0.0, map_msg, ierr); /* @todo CHECKERRQ() */ + }; + + MAP_RETURN_STATUS(success); +}; + + +MAP_ERROR_CODE allocate_outer_solve_data(OuterSolveAttributes* ns, const int size, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // int ret = 0; + int i = 0; + int j = 0; + const int THREE = 3; + const int N = ns->max_krylov_its + 1; + const int SIZE = THREE*size; + + ns->jac = malloc(SIZE*sizeof(double*)); + ns->l = malloc(SIZE*sizeof(double*)); + ns->u = malloc(SIZE*sizeof(double*)); + ns->x = malloc(SIZE*sizeof(double)); + ns->b = malloc(SIZE*sizeof(double)); + ns->y = malloc(SIZE*sizeof(double)); + + if (ns->jac==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->x==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->b==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->l==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->u==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->y==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + /* final initialization to -999.9 */ + for(i=0 ; i<SIZE ; i++) { + ns->jac[i] = malloc(SIZE*sizeof(double)); + ns->l[i] = malloc(SIZE*sizeof(double)); + ns->u[i] = malloc(SIZE*sizeof(double)); + ns->x[i] = -999.9; + ns->b[i] = -999.9; + ns->y[i] = -999.9; + + if (ns->jac[i]==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + if (ns->l[i]==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + if (ns->u[i]==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + for(j=0 ; j<SIZE ; j++) { + ns->jac[i][j] = -999.9; + ns->l[i][j] = -999.9; + ns->u[i][j] = -999.9; + }; + }; + + if (ns->krylov_accelerator) { /* only allocated if Krylov accelerator algorimth is invoked */ + ns->AV = malloc(SIZE*sizeof(double*)); + ns->V = malloc(SIZE*sizeof(double*)); + ns->av = malloc(SIZE*N*sizeof(double)); + ns->C = malloc(SIZE*sizeof(double)); + ns->q = malloc(SIZE*sizeof(double)); + ns->w = malloc(SIZE*sizeof(double)); + + if (ns->AV==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->V==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->C==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->q==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + if (ns->w==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + + /* final initialization to -999.9 */ + for(i=0 ; i<SIZE ; i++) { + ns->AV[i] = malloc(N*sizeof(double)); + ns->V[i] = malloc(N*sizeof(double)); + if (ns->AV[i]==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + if (ns->V[i]==NULL) { + set_universal_error(map_msg, ierr, MAP_FATAL_8); + return MAP_FATAL; + }; + ns->C[i] = -999.9; + ns->q[i] = -999.9; + ns->w[i] = -999.9; + for(j=0 ; j<N ; j++) { + ns->AV[i][j] = -999.9; + ns->V[i][j] = -999.9; + }; + }; + }; + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_help_flag(bstring list) +{ + MAP_ERROR_CODE success = 0; + + success = biseqcstrcaseless(list,"HELP"); /* string compare */ + if (success) { + print_help_to_screen(); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_inner_f_tol_flag(struct bstrList* list, double* ftol) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"INNER_FTOL"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *ftol = (double)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_inner_g_tol_flag(struct bstrList* list, double* gtol) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"INNER_GTOL"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *gtol = (double)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_inner_x_tol_flag(struct bstrList* list, double* xtol) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"INNER_XTOL"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *xtol = (double)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + + +MAP_ERROR_CODE check_inner_max_its_flag(struct bstrList* list, int* max_its) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"INNER_MAX_ITS"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *max_its = (int)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_max_its_flag(struct bstrList* list, int* max_its) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"OUTER_MAX_ITS"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *max_its = (int)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_tol_flag(struct bstrList* list, double* outer_tol) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"OUTER_TOL"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *outer_tol = (double)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_epsilon_flag(struct bstrList* list, double* epsilon) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"OUTER_EPSILON"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *epsilon = (double)atof(word); + return MAP_SAFE; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_integration_dt_flag(struct bstrList* list, double* dt) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"INTEGRATION_DT"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *dt = (double)atof(word); + return MAP_WARNING; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_kb_default_flag(struct bstrList* list, double* kb) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"KB_DEFAULT"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *kb = (double)atof(word); + return MAP_WARNING; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_krylov_accelerator_flag(struct bstrList* list, OuterSolveAttributes* solver) +{ + int n = 0; + int success = 0; + // int next = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"KRYLOV_ACCELERATOR"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + solver->krylov_accelerator = true; + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + solver->max_krylov_its = (int)atoi(word); + word = NULL; + return MAP_SAFE; + }; + } else { /* no trailing integer in the MAP input file */ + word = NULL; + return MAP_WARNING; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_powell_flag(struct bstrList* list, OuterSolveAttributes* solver) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"POWELL"); /* string compare */ + if (success) { + solver->powell = true; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_cb_default_flag(struct bstrList* list, double* cb) +{ + int success = 0; + int n = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"CB_DEFAULT"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + *cb = (double)atof(word); + return MAP_WARNING; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_bd_flag(struct bstrList* list, FdType* bd) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"OUTER_BD"); /* string compare */ + if (success) { + *bd = BACKWARD_DIFFERENCE; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_cd_flag(struct bstrList* list, FdType* cd) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"OUTER_CD"); /* string compare */ + if (success) { + *cd = CENTRAL_DIFFERENCE; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_outer_fd_flag(struct bstrList* list, FdType* fd) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"OUTER_FD"); /* string compare */ + if (success) { + *fd = FORWARD_DIFFERENCE; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_wave_kinematics_flag(struct bstrList* list, bool* wave) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"WAVE_KINEMATICS"); /* string compare */ + if (success) { + *wave = false; + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_lm_model_flag(struct bstrList* list, bool* lm) +{ + int success = 0; + + success = biseqcstrcaseless(list->entry[0],"LM_MODEL"); /* string compare */ + if (success) { + *lm = true; + return MAP_SAFE; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_pg_cooked_flag(struct bstrList* list, OuterSolveAttributes* solver) +{ + int n = 0; + int success = 0; + int next = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"PG_COOKED"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + if (!next) { + solver->d = (double)atof(word); + next++; + } else { + solver->ds = (double)atof(word); + solver->pg = true; + return MAP_SAFE; + }; + } else { + return MAP_FATAL; + }; + }; + n++; + }; + }; + word = NULL; + if (!next) { + return MAP_SAFE; + } else { + return MAP_WARNING; + }; +}; + + +MAP_ERROR_CODE check_repeat_flag(struct bstrList* list, DomainOptions* options) +{ + double* more_angles = NULL; + char* current = NULL; + int success = 0; + int n = 0; /* word interator in the list */ + int i = 0; /* synonym for repeat_angle_size */ + + success = biseqcstrcaseless(list->entry[0],"REPEAT"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + current = (char*)list->entry[n+1]->data; + i = options->repeat_angle_size; + more_angles = realloc(options->repeat_angle, (i+1)*sizeof(double)); + if (more_angles) { + options->repeat_angle = more_angles; + if (is_numeric(current)) { /* add repeat angle if word is numeric */ + options->repeat_angle[i] = atof(current); + options->repeat_angle_size++; + } else { + MAPFREE(more_angles); + return MAP_FATAL; + }; + } else { + MAPFREE(more_angles); + return MAP_FATAL; + }; + }; + n++; + }; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_ref_position_flag(struct bstrList* list, Point* ref_position) +{ + int n = 0; + int success = 0; + int next = 0; + const char* word = NULL; + + success = biseqcstrcaseless(list->entry[0],"REF_POSITION"); /* string compare */ + if (success==BSTR_ERR) { + return MAP_FATAL; + } else if (success) { + while (n<list->qty-1) { /* iterating through all strings */ + if (list->entry[n+1]->slen) { /* if the string length is not 0 */ + word = (char*)list->entry[n+1]->data; + if (is_numeric(word)) { + if (!next) { + ref_position->x.value = (double)atof(word); + next++; + } else if (next==1) { + ref_position->y.value = (double)atof(word); + next++; + } else { + ref_position->z.value = (double)atof(word); + return MAP_SAFE; + }; + }; + }; + n++; + }; + return MAP_WARNING; + }; + word = NULL; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE check_uncaught_flag(struct bstrList* list) +{ + if (biseqcstrcaseless(list->entry[0],"")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"HELP")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"INNER_FTOL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"INNER_GTOL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"INNER_XTOL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"INNER_MAX_ITS")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_MAX_ITS")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_TOL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_EPSILON")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"INTEGRATION_DT")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"KB_DEFAULT")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"CB_DEFAULT")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_CD")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_BD")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"OUTER_FD")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"WAVE_KINEMATICS")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"LM_MODEL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"POWELL")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"PG_COOKED")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"KRYLOV_ACCELERATOR")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"REPEAT")) { + return MAP_SAFE; + } else if (biseqcstrcaseless(list->entry[0],"REF_POSITION")) { + return MAP_SAFE; + }; + return MAP_WARNING; +}; + + +MAP_ERROR_CODE set_library_diameter(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->diam = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_mass_density(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->mass_density = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_ea(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->EA = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_cb(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->cb = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_internal_damping(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->cd_i = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_added_mass_coefficient(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->ca = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_cross_flow_drag_coefficient(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->cd_n = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_library_tangent_drag_coefficient(bstring word, CableLibrary* library_ptr) +{ + if (is_numeric((char*)word->data)) { + library_ptr->cd_t = (double)atof((char*)word->data); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + + +MAP_ERROR_CODE set_model_options_list(Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + const int n_lines = (init_data->solver_options_string->qty)-1; + struct bstrList* parsed = NULL; + struct tagbstring tokens; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + for (i=0 ; i<=n_lines ; i++) { + parsed = bsplits(init_data->solver_options_string->entry[i], &tokens); + + MAP_BEGIN_ERROR_LOG; + + success = check_help_flag(parsed->entry[0]); CHECKERRQ(MAP_FATAL_85); + success = check_inner_f_tol_flag(parsed, &domain->inner_loop.f_tol); CHECKERRK(MAP_ERROR_2); + success = check_outer_max_its_flag(parsed, &domain->outer_loop.max_its); CHECKERRK(MAP_ERROR_3); + success = check_inner_max_its_flag(parsed, &domain->inner_loop.max_its); CHECKERRK(MAP_ERROR_4); + success = check_inner_g_tol_flag(parsed, &domain->inner_loop.g_tol); CHECKERRK(MAP_ERROR_9); + success = check_inner_x_tol_flag(parsed, &domain->inner_loop.x_tol); CHECKERRK(MAP_ERROR_10); + success = check_outer_tol_flag(parsed, &domain->outer_loop.tol); CHECKERRK(MAP_ERROR_3); + success = check_outer_epsilon_flag(parsed, &domain->outer_loop.epsilon); CHECKERRK(MAP_ERROR_3); + success = check_integration_dt_flag(parsed, &domain->model_options.integration_dt); CHECKERRK(MAP_ERROR_15); + success = check_kb_default_flag(parsed, &domain->model_options.kb_lm); CHECKERRK(MAP_ERROR_16); + success = check_cb_default_flag(parsed, &domain->model_options.cb_lm); CHECKERRK(MAP_ERROR_17); + success = check_outer_bd_flag(parsed, &domain->outer_loop.fd); + success = check_outer_cd_flag(parsed, &domain->outer_loop.fd); + success = check_outer_fd_flag(parsed, &domain->outer_loop.fd); + success = check_wave_kinematics_flag(parsed, &domain->model_options.wave_kinematics); CHECKERRK(MAP_WARNING_10); + success = check_lm_model_flag(parsed, &domain->model_options.lm_model); CHECKERRK(MAP_WARNING_11); + success = check_pg_cooked_flag(parsed, &domain->outer_loop); CHECKERRK(MAP_WARNING_8); + success = check_krylov_accelerator_flag(parsed, &domain->outer_loop); CHECKERRK(MAP_WARNING_12); + success = check_powell_flag(parsed, &domain->outer_loop); CHECKERRK(MAP_WARNING_14); + success = check_repeat_flag(parsed, &domain->model_options); CHECKERRQ(MAP_FATAL_34); + success = check_ref_position_flag(parsed, &domain->vessel.ref_origin); CHECKERRQ(MAP_FATAL_36); + success = check_uncaught_flag(parsed); + if (success) { + set_universal_error_with_message(map_msg, ierr, MAP_WARNING_1, "word: <%s>", parsed->entry[0]->data); + }; + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + + /* throw error if PG_COOKED and KRYLOV_ACCELERATOR are simultaneously set in the input file */ + if (domain->outer_loop.pg && domain->outer_loop.krylov_accelerator) { + set_universal_error(map_msg, ierr, MAP_WARNING_13); + domain->outer_loop.krylov_accelerator = false; + }; + + /* throw error if PG_COOKED and KRYLOV_ACCELERATOR are simultaneously set in the input file */ + if ( (domain->outer_loop.powell && domain->outer_loop.krylov_accelerator) || + (domain->outer_loop.powell && domain->outer_loop.pg)) { + set_universal_error(map_msg, ierr, MAP_WARNING_14); + domain->outer_loop.krylov_accelerator = false; + }; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE reset_cable_library(CableLibrary* library_ptr) +{ + library_ptr->diam = 0.0; + library_ptr->mass_density = 0.0; + library_ptr->EA = 0.0; + library_ptr->omega = 0.0; + library_ptr->a = 0.0; + library_ptr->cb = 0.0; + library_ptr->cd_i = 0.0; + library_ptr->ca = 0.0; + library_ptr->cd_n = 0.0; + library_ptr->cd_t = 0.0; + // if (library_ptr->label) { + // success = bdestroy(library_ptr->label); + // }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_cable_library_list(Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int n = 0; + int next = 0; + const int n_lines = (init_data->library_input_string->qty)-1; + struct bstrList* parsed = NULL; + struct tagbstring tokens; + CableLibrary new_cable_library; + CableLibrary* library_iter = NULL; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + success = reset_cable_library(&new_cable_library); + + for (i=0 ; i<=n_lines ; i++) { + list_append(&domain->library, &new_cable_library); + library_iter = (CableLibrary*)list_get_at(&domain->library, i); + + parsed = bsplits(init_data->library_input_string->entry[i], &tokens); + n = 0; + next = 0; + + MAP_BEGIN_ERROR_LOG; + + while (n<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[n]->slen) { /* if the string length is not 0 */ + if (next==0) { + library_iter->label = bstrcpy(parsed->entry[n]); + next++; + } else if (next==1) { + success = set_library_diameter(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_12); + next++; + } else if (next==2) { + success = set_library_mass_density(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_13); + next++; + } else if (next==3) { + success = set_library_ea(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_14); + next++; + } else if (next==4) { + success = set_library_cb(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_15); + next++; + } else if (next==5) { + success = set_library_internal_damping(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_81); + next++; + } else if (next==6) { + success = set_library_added_mass_coefficient(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_82); + next++; + } else if (next==7) { + success = set_library_cross_flow_drag_coefficient(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_83); + next++; + } else if (next==8) { + success = set_library_tangent_drag_coefficient(parsed->entry[n], library_iter); CHECKERRQ(MAP_FATAL_84); + next++; + }; + }; + n++; + }; + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE initialize_cable_library_variables(Domain* domain, MAP_ParameterType_t* p_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + double radius = 0.0; + double area = 0.0; + double mu = 0.0; + double rho_fluid = 0.0; + const double g = p_type->g; + const double PI = 3.14159264; + CableLibrary* library_iter = NULL; + + list_iterator_start(&domain->library); /* starting an iteration "session" */ + while ( list_iterator_hasnext(&domain->library)) { /* tell whether more values available */ + library_iter = (CableLibrary*)list_iterator_next(&domain->library); + radius = library_iter->diam/2; + area = PI*pow(radius,2); + mu = library_iter->mass_density; + rho_fluid = p_type->rho_sea; + library_iter->omega = g*(mu-area*rho_fluid); + + library_iter->a = area; + if (fabs(library_iter->omega)<=1.0) { + set_universal_error_with_message(map_msg, ierr, MAP_WARNING_5, + "omega = %f <= 1.0", library_iter->omega); + }; + }; + list_iterator_stop(&domain->library); /* ending the iteration "session" */ + + if (fabs(library_iter->omega)<=1.0E-3) { + return MAP_FATAL; + } + /* end read */ + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_number(const int n_line, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + current_entry = bformat("%d ", n_line); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + +MAP_ERROR_CODE expand_node_type(const char* word, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_position_x(double* x, const char* word) +{ + if (is_numeric(word)) { /* if number is numeric */ + *x = (double)atof(word); + } else if (word[0]=='#') { + *x = (double)atof(remove_first_character(word)); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_position_y(double* y, const char* word) +{ + if (is_numeric(word)) { /* if number is numeric */ + *y = (double)atof(word); + } else if (word[0]=='#') { + *y = (double)atof(remove_first_character(word)); + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_position_z(Vector* position, const double angle, const double x, const double y, const char* word, bstring line) +{ + bstring current_entry = NULL; + bstring compared_word = NULL; + int ret = 0; + + position->x = x*cos(angle) + y*sin(angle); + position->y = -x*sin(angle) + y*cos(angle); + compared_word = bformat("%s", word); + if (is_numeric(word)) { /* if number is numeric */ + position->z = (double)atof(word); + current_entry = bformat("%1.4f %1.4f %1.4f ",position->x, position->y, position->z); + } else if (word[0]=='#') { + position->z = (double)atof(remove_first_character(word)); + current_entry = bformat("#%1.4f #%1.4f #%1.4f ",position->x, position->y, position->z); + } else if (biseqcstrcaseless(compared_word,"DEPTH")) { + current_entry = bformat("%1.4f %1.4f depth ",position->x, position->y, position->z); + } else { + bdestroy(compared_word); + return MAP_FATAL; + }; + + bdestroy(compared_word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_mass(const char* word, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_buoyancy(const char* word, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_force_x(double* fx, const char* word) +{ + if (is_numeric(word)) { /* if number is numeric */ + *fx = (double)atof(word); + } else if (word[0]=='#') { /* if the nuymber is iterated */ + if (is_numeric(remove_first_character(word))) { + *fx = (double)atof(remove_first_character(word)); + } else { /* in this case, it is presumed the force is just '#' */ + *fx = -999.9; + }; + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_force_y(double* fy, const char* word) +{ + if (is_numeric(word)) { /* if number is numeric */ + *fy = (double)atof(word); + } else if (word[0]=='#') { /* if the nuymber is iterated */ + if (is_numeric(remove_first_character(word))) { + *fy = (double)atof(remove_first_character(word)); + } else { /* in this case, it is presumed the force is just '#' */ + *fy = -999.9; + }; + } else { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_node_force_z(Vector* force, const double angle, const double fx, const double fy, const char* word, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + force->x = fx*cos(angle) + fy*sin(angle); + force->y = -fx*sin(angle) + fy*cos(angle); + + if (is_numeric(word)) { /* if number is numeric */ + force->z = (double)atof(word); + current_entry = bformat("%1.4f %1.4f %1.4f\n",force->x, force->y, force->z); + } else if (word[0]=='#') { /* if the nuymber is iterated */ + if (is_numeric(remove_first_character(word))) { + force->z = (double)atof(remove_first_character(word)); + current_entry = bformat("#%1.4f #%1.4f #%1.4f\n",force->x, force->y, force->z); + } else { /* in this case, it is presumed the force is just '#' */ + force->z = -999.9; + current_entry = bformat("# # #\n"); + }; + } else { + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_FATAL; + }; + + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE repeat_nodes(Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int j = 0; + int next = 0; + int i_parsed = 0; + int n_line = 0; + const int num_repeat = domain->model_options.repeat_angle_size; + const int num_node = init_data->node_input_string->qty; + const int n = (num_node)*(num_repeat+1); + const char* word = NULL; + double x_position = 0.0; + double y_position = 0.0; + double x_force = 0.0; + double y_force = 0.0; + double current_angle = 0.0; + bstring line = bformat(""); + struct bstrList* parsed = NULL; + struct tagbstring tokens; + Vector force; + Vector position; + Node new_node; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + + force.x = 0.0; + force.y = 0.0; + force.z = 0.0; + position.x = 0.0; + position.y = 0.0; + position.z = 0.0; + + /* allocate space needed to expand the number of node lines */ + success = bstrListAlloc(init_data->expanded_node_input_string, n+1); + init_data->expanded_node_input_string->qty = 0; + + for(i=0 ; i<num_node ; i++) { + init_data->expanded_node_input_string->entry[i] = bfromcstr((char*)init_data->node_input_string->entry[i]->data);// bstrcpy(init_data->node_input_string->entry[i]); + init_data->expanded_node_input_string->qty++; + }; + + for(i=0 ; i<num_repeat ; i++) { /* this is skipped if not repeat angles are declared */ + for(j=0 ; j<num_node ; j++) { + success = reset_node(&new_node); + n_line = (i+1)*num_node + j; + current_angle = domain->model_options.repeat_angle[i]*(DEG2RAD); + parsed = bsplits(init_data->node_input_string->entry[j], &tokens); + next = 0; + i_parsed = 0; + + MAP_BEGIN_ERROR_LOG; + + while (i_parsed<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[i_parsed]->slen) { /* if the string length is not 0 */ + word = (char*)parsed->entry[i_parsed]->data; + if (next==0) { + success = expand_node_number(n_line+1, line);/* @todo: checkerrq */ + next++; + } else if (next==1) { + success = expand_node_type(word, line);/* @todo: checkerrq */ + next++; + } else if (next==2) { + success = expand_node_position_x(&x_position, word);/* @todo: checkerrq */ + next++; + } else if (next==3) { + success = expand_node_position_y(&y_position, word);/* @todo: checkerrq */ + next++; + } else if (next==4) { + success = expand_node_position_z(&position, current_angle, x_position, y_position, word, line);/* @todo: checkerrq */ + next++; + } else if (next==5) { /* node mass */ + success = expand_node_mass(word, line);/* @todo: checkerrq */ + next++; + } else if (next==6) { /* node buoyancy */ + success = expand_node_buoyancy(word, line);/* @todo: checkerrq */ + next++; + } else if (next==7) { + success = expand_node_force_x(&x_force, word);/* @todo: checkerrq */ + next++; + } else if (next==8) { + success = expand_node_force_y(&y_force, word);/* @todo: checkerrq */ + next++; + } else if (next==9) { + success = expand_node_force_z(&force, current_angle, x_force, y_force, word, line);/* @todo: checkerrq */ + next++; + }; + }; + i_parsed++; + }; + init_data->expanded_node_input_string->qty++; + init_data->expanded_node_input_string->entry[n_line] = bstrcpy(line); + success = bassigncstr(line, ""); + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + }; + success = bdestroy(line); + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE expand_line_number(const int n_line, bstring line) +{ + bstring current_entry = NULL; + int ret = 0; + + current_entry = bformat("%d ", n_line); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_line_property_name(const char* word, bstring line) +{ + int ret = 0; + bstring current_entry = NULL; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_line_length(const char* word, bstring line) +{ + int ret = 0; + bstring current_entry = NULL; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_line_anchor_number(const char* word, const int index, const int n, bstring line) +{ + int ret = 0; + bstring current_entry = NULL; + int anchor_num = 0; + + if (is_numeric(word)) { + anchor_num = (int)atoi(word); + } else { + return MAP_SAFE; + }; + current_entry = bformat("%d ", (index+1)*n+anchor_num); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE expand_line_fairlead_number(const char* word, const int index, const int n, bstring line) +{ + int ret = 0; + bstring current_entry = NULL; + int fairlead_num = 0; + + if (is_numeric(word)) { + fairlead_num = (int)atoi(word); + } else { + return MAP_SAFE; + }; + current_entry = bformat("%d ", (index+1)*n+fairlead_num); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + +MAP_ERROR_CODE expand_line_flag(const char* word, bstring line) +{ + int ret = 0; + bstring current_entry = NULL; + + current_entry = bformat("%s ", word); + ret = bconcat(line, current_entry); + ret = bdestroy(current_entry); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE repeat_lines(Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int j = 0; + int next = 0; + int i_parsed = 0; + int n_line = 0; + const int num_repeat = domain->model_options.repeat_angle_size; + const int num_line = init_data->line_input_string->qty; + const int num_node = init_data->node_input_string->qty; + const int n = (num_line)*(num_repeat+1); + const char* word = NULL; + double current_angle = 0.0; + bstring line = bformat(""); + struct bstrList* parsed = NULL; + struct tagbstring tokens; + Line new_line; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + + /* allocate space needed to expand the number of node lines */ + success = bstrListAlloc(init_data->expanded_line_input_string, n+1); + init_data->expanded_line_input_string->qty = 0; + + for(i=0 ; i<num_line ; i++) { + init_data->expanded_line_input_string->entry[i] = bfromcstr((char*)init_data->line_input_string->entry[i]->data); + init_data->expanded_line_input_string->qty++; + }; + + + for(i=0 ; i<num_repeat ; i++) { /* this is skipped if not repeat angles are declared */ + for(j=0 ; j<num_line ; j++) { + success = reset_line(&new_line); + n_line = (i+1)*num_line + j; + current_angle = domain->model_options.repeat_angle[i]*(DEG2RAD); + parsed = bsplits(init_data->line_input_string->entry[j], &tokens); + next = 0; + i_parsed = 0; + + MAP_BEGIN_ERROR_LOG; + + while (i_parsed<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[i_parsed]->slen) { /* if the string length is not 0 */ + word = (char*)parsed->entry[i_parsed]->data; + if (next==0) { + success = expand_line_number(n_line+1, line); + next++; + } else if (next==1) { + success = expand_line_property_name(word, line); + next++; + } else if (next==2) { + success = expand_line_length(word, line); + next++; + } else if (next==3) { + success = expand_line_anchor_number(word, i, num_node, line); + next++; + } else if (next==4) { + success = expand_line_fairlead_number(word, i, num_node, line); + next++; + } else { + success = expand_line_flag(word, line); + next++; + }; + }; + i_parsed++; + }; + init_data->expanded_line_input_string->qty++; + init_data->expanded_line_input_string->entry[n_line] = bstrcpy(line); + success = bassigncstr(line, ""); + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + }; + success = bdestroy(line); + + MAP_RETURN_STATUS(*ierr); +}; + + + +MAP_ERROR_CODE allocate_types_for_nodes(MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, Domain* domain, struct bstrList* node_input_string, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int i = 0; + int i_parsed = 0; + int next = 0; + int fix_num = 0; + int vessel_num = 0; + int connect_num = 0; + MAP_ERROR_CODE success = MAP_SAFE; + const int num_nodes = node_input_string->qty; + struct bstrList* parsed = NULL; + struct tagbstring tokens; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + + /* First need to run loop to find the number of inputs, outputs, constraints. + * Basically we are just counting the number of VESSEL, FIX, and CONNECT nodes + */ + for(i=0 ; i<num_nodes ; i++) { + i_parsed = 0; + next = 0; + parsed = bsplits(node_input_string->entry[i], &tokens); + + MAP_BEGIN_ERROR_LOG; + + while (i_parsed<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[i_parsed]->slen) { /* if the string length is not 0 */ + if (next==1) { + if (biseqcstrcaseless(parsed->entry[i_parsed],"FIX")) { + fix_num++; + break; /* break the while-loop because the agenda is reached */ + } else if (biseqcstrcaseless(parsed->entry[i_parsed],"CONNECT")) { + connect_num++; + break; /* break the while-loop because the agenda is reached */ + } else if (biseqcstrcaseless(parsed->entry[i_parsed],"VESSEL")) { + vessel_num++; + break; /* break the while-loop because the agenda is reached */ + } else { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_25, "Value: <%s>", parsed->entry[i_parsed]->data); + }; + }; + next++; + }; + i_parsed++; + }; + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + + other_type->x_Len = fix_num; + other_type->y_Len = fix_num; + other_type->z_Len = fix_num; + other_type->x = malloc(other_type->x_Len*sizeof(double)); + other_type->y = malloc(other_type->y_Len*sizeof(double)); + other_type->z = malloc(other_type->z_Len*sizeof(double)); + + /* If the node is VESSEL, then the applied force is an output state. Otherwise, + * it has to be an other state because it can't be associated with any other type. + * This is what is done below. + */ + other_type->Fx_connect_Len = connect_num; + other_type->Fy_connect_Len = connect_num; + other_type->Fz_connect_Len = connect_num; + other_type->Fx_connect = malloc(other_type->Fx_connect_Len*sizeof(double)); + other_type->Fy_connect = malloc(other_type->Fy_connect_Len*sizeof(double)); + other_type->Fz_connect = malloc(other_type->Fz_connect_Len*sizeof(double)); + + other_type->Fx_anchor_Len = fix_num; + other_type->Fy_anchor_Len = fix_num; + other_type->Fz_anchor_Len = fix_num; + other_type->Fx_anchor = malloc(other_type->Fx_anchor_Len*sizeof(double)); + other_type->Fy_anchor = malloc(other_type->Fy_anchor_Len*sizeof(double)); + other_type->Fz_anchor = malloc(other_type->Fz_anchor_Len*sizeof(double)); + + z_type->x_Len = connect_num; + z_type->y_Len = connect_num; + z_type->z_Len = connect_num; + z_type->x = malloc(z_type->x_Len*sizeof(double)); + z_type->y = malloc(z_type->y_Len*sizeof(double)); + z_type->z = malloc(z_type->z_Len*sizeof(double)); + + u_type->x_Len = vessel_num; + u_type->y_Len = vessel_num; + u_type->z_Len = vessel_num; + u_type->x = malloc(u_type->x_Len*sizeof(double)); + u_type->y = malloc(u_type->y_Len*sizeof(double)); + u_type->z = malloc(u_type->z_Len*sizeof(double)); + + y_type->Fx_Len = vessel_num; + y_type->Fy_Len = vessel_num; + y_type->Fz_Len = vessel_num; + y_type->Fx = malloc(y_type->Fx_Len*sizeof(double)); + y_type->Fy = malloc(y_type->Fy_Len*sizeof(double)); + y_type->Fz = malloc(y_type->Fz_Len*sizeof(double)); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE compare_integer_length(const int a, const int b) +{ + if (a!=b) { + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_node_list(const MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, Domain* domain, struct bstrList* node_input_string, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int i_parsed = 0; + int next = 0; + const int num_nodes = node_input_string->qty; + int fix_num = 0; + int vessel_num = 0; + int connect_num = 0; + Node new_node; + Node* node_iter = NULL; + struct bstrList* parsed = NULL; + struct tagbstring tokens; + bstring alias = NULL; + bstring value_string = NULL; + const double depth = p_type->depth; + ReferencePoint u_reference_point; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + + success = allocate_types_for_nodes(u_type, z_type, other_type, y_type, domain, node_input_string, map_msg, ierr); + success = reset_node(&new_node); /* create an empty node */ + + for(i=0 ; i<num_nodes ; i++) { + list_append(&domain->node, &new_node); /* append node to list */ + node_iter = (Node*)list_get_at(&domain->node, i); + // success = set_node_vartype(node_iter); + i_parsed = 0; + next = 0; + parsed = bsplits(node_input_string->entry[i], &tokens); + + MAP_BEGIN_ERROR_LOG; + + while (i_parsed<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[i_parsed]->slen) { /* if the string length is not 0 */ + if (next==0) { + next++; + } else if (next==1) { + if (biseqcstrcaseless(parsed->entry[i_parsed],"FIX")) { + node_iter->type = FIX; + fix_num++; /* VarTypePtr FAST derived array index */ + success = associate_vartype_ptr(&node_iter->position_ptr.x, other_type->x, fix_num); + success = associate_vartype_ptr(&node_iter->position_ptr.y, other_type->y, fix_num); + success = associate_vartype_ptr(&node_iter->position_ptr.z, other_type->z, fix_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fx, other_type->Fx_anchor, fix_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fy, other_type->Fy_anchor, fix_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fz, other_type->Fz_anchor, fix_num); + } else if (biseqcstrcaseless(parsed->entry[i_parsed],"CONNECT")) { + node_iter->type = CONNECT; + connect_num++; + success = associate_vartype_ptr(&node_iter->position_ptr.x, z_type->x, connect_num); + success = associate_vartype_ptr(&node_iter->position_ptr.y, z_type->y, connect_num); + success = associate_vartype_ptr(&node_iter->position_ptr.z, z_type->z, connect_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fx, other_type->Fx_connect, connect_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fy, other_type->Fy_connect, connect_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fz, other_type->Fz_connect, connect_num); + } else if (biseqcstrcaseless(parsed->entry[i_parsed],"VESSEL")) { + node_iter->type = VESSEL; + vessel_num++; + u_reference_point.x = NULL; + u_reference_point.y = NULL; + u_reference_point.z = NULL; + success = associate_vartype_ptr(&node_iter->position_ptr.x, u_type->x, vessel_num); + success = associate_vartype_ptr(&node_iter->position_ptr.y, u_type->y, vessel_num); + success = associate_vartype_ptr(&node_iter->position_ptr.z, u_type->z, vessel_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fx, y_type->Fx, vessel_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fy, y_type->Fy, vessel_num); + success = associate_vartype_ptr(&node_iter->sum_force_ptr.fz, y_type->Fz, vessel_num); + u_reference_point.x = &node_iter->position_ptr.x; /* create reference to input type; this is the convenient update point when u is interpolated in FAST */ + u_reference_point.y = &node_iter->position_ptr.y; /* create reference to input type; this is the convenient update point when u is interpolated in FAST */ + u_reference_point.z = &node_iter->position_ptr.z; /* create reference to input type; this is the convenient update point when u is interpolated in FAST */ + list_append(&domain->u_update_list, &u_reference_point); /* push onto the update list */ + } else { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_25, "Value: <%s>", parsed->entry[i_parsed]->data); + }; + next++; + } else if (next==2) { /* set initial X node position values */ + alias = bformat("X[%d]", i+1); + success = set_vartype_ptr("[m]", alias, i, &node_iter->position_ptr.x, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_17); + bdestroy(alias); + next++; + } else if (next==3) { /* set initial Y node position values */ + alias = bformat("Y[%d]", i+1); + success = set_vartype_ptr("[m]", alias, i, &node_iter->position_ptr.y, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_18); + bdestroy(alias); + next++; + } else if (next==4) { /* set initial Z node position values */ + alias = bformat("Z[%d]", i+1); + if (biseqcstrcaseless(parsed->entry[i_parsed],"DEPTH")) { + if (node_iter->type!=FIX) { /* can only use 'DEPTH' flag in input file for FIX (anchor) nodes */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_71, "Value: <%s>", parsed->entry[i_parsed]->data); + } else { + value_string = bformat("%f", -depth); + success = set_vartype_ptr("[m]", alias, i, &node_iter->position_ptr.z, value_string); CHECKERRQ(MAP_FATAL_19); + success = bdestroy(value_string); + }; + } else { /* all other nodes not using the 'DEPTH' flag */ + success = set_vartype_ptr("[m]", alias, i, &node_iter->position_ptr.z, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_19); + }; + bdestroy(alias); + next++; + } else if (next==5) { /* set the node mass */ + alias = bformat("M[%d]", i+1); + success = set_vartype("[kg]", alias, i, &node_iter->M_applied, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_20); + bdestroy(alias); + next++; + } else if (next==6) { /* set the node buoyancy */ + alias = bformat("B[%d]", i+1); + success = set_vartype("[m^3]", alias, i, &node_iter->B_applied, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_21); + bdestroy(alias); + next++; + } else if (next==7) { /* set applied X external force (or user guess) of the node */ + alias = bformat("FX[%d]", i+1); + success = set_vartype("[N]", alias, i, &node_iter->external_force.fx, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_22); + bdestroy(alias); + next++; + } else if (next==8) { /* set applied Y external force (or user guess) of the node */ + alias = bformat("FY[%d]", i+1); + success = set_vartype("[N]", alias, i, &node_iter->external_force.fy, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_23); + bdestroy(alias); + next++; + } else if (next==9) { /* set applied Z external force (or user guess) of the node */ + alias = bformat("FZ[%d]", i+1); + success = set_vartype("[N]", alias, i, &node_iter->external_force.fz, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_24); + bdestroy(alias); + next++; + } else { + next++; + }; + }; + i_parsed++; + }; + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + /* @todo: need to make sure next==9; otherwise not enough inputs and an error should + * be thrown + */ + }; + + /* check to make sure the number of allocated array spaces for fortran derived types matches + * what was actually set in the node initialization front end. + */ + MAP_BEGIN_ERROR_LOG; + + success = compare_integer_length(other_type->Fx_connect_Len, connect_num); CHECKERRQ(MAP_FATAL_49); + success = compare_integer_length(other_type->Fy_connect_Len, connect_num); CHECKERRQ(MAP_FATAL_49); + success = compare_integer_length(other_type->Fz_connect_Len, connect_num); CHECKERRQ(MAP_FATAL_49); + + success = compare_integer_length(other_type->Fx_anchor_Len, fix_num); CHECKERRQ(MAP_FATAL_49); // @todo: change error code + success = compare_integer_length(other_type->Fy_anchor_Len, fix_num); CHECKERRQ(MAP_FATAL_49); // @todo: change error code + success = compare_integer_length(other_type->Fz_anchor_Len, fix_num); CHECKERRQ(MAP_FATAL_49); // @todo: change error code + + success = compare_integer_length(other_type->x_Len, fix_num); CHECKERRQ(MAP_FATAL_49); + success = compare_integer_length(other_type->y_Len, fix_num); CHECKERRQ(MAP_FATAL_49); + success = compare_integer_length(other_type->z_Len, fix_num); CHECKERRQ(MAP_FATAL_49); + + success = compare_integer_length(u_type->x_Len, vessel_num); CHECKERRQ(MAP_FATAL_50); + success = compare_integer_length(u_type->y_Len, vessel_num); CHECKERRQ(MAP_FATAL_50); + success = compare_integer_length(u_type->z_Len, vessel_num); CHECKERRQ(MAP_FATAL_50); + + success = compare_integer_length(y_type->Fx_Len, vessel_num); CHECKERRQ(MAP_FATAL_51); + success = compare_integer_length(y_type->Fy_Len, vessel_num); CHECKERRQ(MAP_FATAL_51); + success = compare_integer_length(y_type->Fz_Len, vessel_num); CHECKERRQ(MAP_FATAL_51); + + success = compare_integer_length(z_type->x_Len, connect_num); CHECKERRQ(MAP_FATAL_52); + success = compare_integer_length(z_type->y_Len, connect_num); CHECKERRQ(MAP_FATAL_52); + success = compare_integer_length(z_type->z_Len, connect_num); CHECKERRQ(MAP_FATAL_52); + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE set_vartype_float(const char* unit, const char* alias, const int num, VarType* type, const double value) +{ + type->name = bfromcstr(alias); + type->units = bfromcstr(unit); + type->ref_counter = 0; + type->id = num; + type->value = value; + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_vartype(const char* unit, bstring alias, const int num, VarType* type, bstring property) +{ + type->name = bstrcpy(alias); + type->units = bfromcstr(unit); + type->ref_counter = 0; + type->id = num; + + if (!property) { /* this option should only be called for setting line vartypes */ + type->value = -999.9; + } else { + if (property->data[0]=='#') { /* this variable is an iterated parameter */ + type->is_fixed = false; + if (property->slen==1) { /* implies that property->data = "#" */ + type->value = -999.9; + } else if (is_numeric(remove_first_character((char*)property->data))) { + type->value = (double)atof(remove_first_character((char*)property->data)); + type->user_initial_guess = true; + } else { + return MAP_FATAL; + }; + } else { /* this variable is constant */ + type->is_fixed = true; + if (is_numeric((char*)property->data)) { + type->value = (double)atof((char*)property->data); + } else { + return MAP_FATAL; + }; + }; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_vartype_ptr(const char* unit, bstring alias, const int num, VarTypePtr* type, bstring property) +{ + type->name = bstrcpy(alias); + type->units = bfromcstr(unit); + type->ref_counter = 0; + type->id = num; + + if (property->data[0]=='#') { /* this variable is an iterated parameter */ + type->is_fixed = false; + if (property->slen==1) { /* implies that property->data = "#" */ + *type->value = -999.9; + } else if (is_numeric(remove_first_character((char*)property->data))) { + *type->value = (double)atof(remove_first_character((char*)property->data)); + } else { + return MAP_FATAL; + }; + } else { /* this variable is constant */ + type->is_fixed = true; + if ((char*)is_numeric((char*)property->data)) { + *type->value = (double)atof((char*)property->data); + } else { + return MAP_FATAL; + }; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_line_option_flags(struct bstrList* words, int* i_parsed, Line* line_ptr, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // MAP_ERROR_CODE success = MAP_SAFE; + int index = *i_parsed; + + if (biseqcstrcaseless(words->entry[index], "GX_POS")) { + line_ptr->options.gx_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GY_POS")) { + line_ptr->options.gy_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GZ_POS")) { + line_ptr->options.gz_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GX_A_POS")) { + line_ptr->options.gx_anchor_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GY_A_POS")) { + line_ptr->options.gy_anchor_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GZ_A_POS")) { + line_ptr->options.gz_anchor_pos_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GX_FORCE")) { + line_ptr->options.gx_force_flag= true; + } else if (biseqcstrcaseless(words->entry[index], "GY_FORCE")) { + line_ptr->options.gy_force_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "GZ_FORCE")) { + line_ptr->options.gz_force_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "H_FAIR")) { + line_ptr->options.H_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "H_ANCH")) { + line_ptr->options.H_anchor_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "V_FAIR")) { + line_ptr->options.V_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "V_ANCH")) { + line_ptr->options.V_anchor_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "TENSION_FAIR")) { + line_ptr->options.fairlead_tension_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "TENSION_ANCH")) { + line_ptr->options.anchor_tension_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "X_EXCURSION")) { + line_ptr->options.horizontal_excursion_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "Z_EXCURSION")) { + line_ptr->options.vertical_excursion_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "AZIMUTH")) { + line_ptr->options.azimuth_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "ALTITUDE")) { + line_ptr->options.altitude_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "ALTITUDE_ANCH")) { + line_ptr->options.altitude_anchor_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "LINE_TENSION")) { + line_ptr->options.line_tension_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "OMIT_CONTACT")) { + line_ptr->options.omit_contact = true; + } else if (biseqcstrcaseless(words->entry[index], "LINEAR_SPRING")) { + line_ptr->options.linear_spring = true; + } else if (biseqcstrcaseless(words->entry[index], "SEG_SIZE")) { + do { + index++; + if (words->qty-1<=index) { + break; + }; + } while (words->entry[index]->slen<1); + if (is_numeric((char*)words->entry[index]->data)) { + line_ptr->segment_size = (int)atoi((char*)words->entry[index]->data); + *i_parsed = index; + } else { /* should not cancel the simulation; simply ignore it */ + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_18, "Option <%s>", words->entry[index]->data); + }; + } else if (biseqcstrcaseless(words->entry[index], "LAY_LENGTH")) { + line_ptr->options.lay_length_flag = true; + } else if (biseqcstrcaseless(words->entry[index], "DAMAGE_TIME")) { + do { + index++; + if (words->qty-1<=index) { + break; + }; + } while (words->entry[index]->slen<1); + if (is_numeric((char*)words->entry[index]->data)) { + line_ptr->options.damage_time_flag = true; + line_ptr->damage_time = (double)atof((char*)words->entry[index]->data); + *i_parsed = index; + } else { /* should not cancel the simulation; simply ignore it */ + set_universal_error_with_message(map_msg, ierr, MAP_ERROR_1, "Option <%s>", words->entry[index]->data); + }; + } else if (biseqcstrcaseless(words->entry[index], "DIAGNOSTIC")) { + do { + index++; + if (words->qty-1<=index) { + break; + }; + } while (words->entry[index]->slen<1); + if (is_numeric((char*)words->entry[index]->data)) { + line_ptr->options.diagnostics_flag = true; + line_ptr->diagnostic_type = (int)atoi((char*)words->entry[index]->data); + *i_parsed = index; + } else { /* should not cancel the simulation; simply ignore it */ + set_universal_error_with_message(map_msg, ierr, MAP_ERROR_14, "Option <%s>", words->entry[index]->data); + }; + } else { + /* should not cancel the simulation; simply ignore it */ + set_universal_error_with_message(map_msg, ierr, MAP_WARNING_3, "Option <%s>", words->entry[index]->data); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_line_list(MAP_ConstraintStateType_t* z_type, Domain* domain, struct bstrList* line_input_string, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + int i = 0; + int i_parsed = 0; + int next = 0; + const int num_lines = line_input_string->qty; + Line new_line; + Line* line_iter = NULL; + struct bstrList* parsed = NULL; + struct tagbstring tokens; + bstring alias = NULL; + + cstr2tbstr(tokens," \t\n\r"); /* token for splitting line into indivdual words is a tab and space */ + success = reset_line(&new_line); + + z_type->H_Len = num_lines; + z_type->V_Len = num_lines; + z_type->H = malloc(z_type->H_Len*sizeof(double)); + z_type->V = malloc(z_type->V_Len*sizeof(double)); + + if (z_type->H==NULL || z_type->V==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_53, "Failed allocation of a z_type"); + return MAP_FATAL; + }; + + for(i=0 ; i<num_lines ; i++) { + list_append(&domain->line, &new_line); + line_iter = (Line*)list_get_at(&domain->line, i); + // success = set_line_vartype(line_iter, i); /* @todo: check error */ @rm + + i_parsed = 0; + next = 0; + parsed = bsplits(line_input_string->entry[i], &tokens); + + MAP_BEGIN_ERROR_LOG; + + while (i_parsed<parsed->qty-1) { /* iterating through all strings */ + if (parsed->entry[i_parsed]->slen) { /* if the string length is not 0 */ + if (next==0) { /* use this first option as an opportunity to set the run-time flags to false */ + success = associate_vartype_ptr(&line_iter->H, z_type->H, i+1); + success = associate_vartype_ptr(&line_iter->V, z_type->V, i+1); + + line_iter->H.is_fixed = false; + alias = bformat("H[%d]", i+1); + success = set_vartype_ptr("[N]", alias, i, &line_iter->H, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_32); + success = bdestroy(alias); + + line_iter->V.is_fixed = false; + alias = bformat("V[%d]", i+1); + success = set_vartype_ptr("[N]", alias, i, &line_iter->V, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_32); + success = bdestroy(alias); + + next++; + } else if (next==1) { + success = associate_line_with_cable_property(line_iter, domain, (char*)parsed->entry[i_parsed]->data, map_msg, ierr); CHECKERRQ(MAP_FATAL_32); + next++; + } else if (next==2) { + alias = bformat("Lu[%d]", i+1); + success = set_vartype("[m]", alias, i, &line_iter->Lu, parsed->entry[i_parsed]); CHECKERRQ(MAP_FATAL_26); + success = bdestroy(alias); + next++; + } else if (next==3) { + success = associate_line_with_anchor_node(line_iter, domain, i+1, (char*)parsed->entry[i_parsed]->data, map_msg, ierr); CHECKERRQ(MAP_FATAL_32); + next++; + } else if (next==4) { + success = associate_line_with_fairlead_node(line_iter, domain, i+1, (char*)parsed->entry[i_parsed]->data, map_msg, ierr); CHECKERRQ(MAP_FATAL_32); + next++; + } else { /* set the node mass */ + success = set_line_option_flags(parsed, &i_parsed, line_iter, map_msg, ierr); + }; + }; + i_parsed++; + }; + + MAP_END_ERROR_LOG; + + success = bstrListDestroy(parsed); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE push_variable_to_output_list(OutputList* y_list, const int i, double* variable_ref, const char* alias, const char* units) { + int size = 0; + + VarTypePtr vartype_ptr; + VarTypePtr* iter_vartype = NULL; + + list_append(&y_list->out_list_ptr, &vartype_ptr); /* @todo: this is not correct. Should point to fairlead->sumForce.fy */ + size = list_size(&y_list->out_list_ptr); + iter_vartype = (VarTypePtr*)list_get_at(&y_list->out_list_ptr, size-1); + iter_vartype->value = variable_ref; + iter_vartype->name = bformat("%s[%d]", alias, i); + iter_vartype->units = bformat("%s", units); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE set_output_list(Domain* domain, MAP_InitOutputType_t* io_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + Line* line_iter = NULL; + OutputList* y_list = domain->y_list; + // int size = 0; + int line_num = 1; + // VarTypePtr* iter_vartype = NULL; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + + if (line_iter->options.gx_anchor_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->anchor->position_ptr.x); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gy_anchor_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->anchor->position_ptr.y); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gz_anchor_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->anchor->position_ptr.z); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gx_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->fairlead->position_ptr.x); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gy_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->fairlead->position_ptr.y); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gz_pos_flag) { + list_append(&y_list->out_list_ptr, &line_iter->fairlead->position_ptr.z); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.H_flag) { + list_append(&y_list->out_list_ptr, &line_iter->H); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.V_flag) { + list_append(&y_list->out_list_ptr, &line_iter->V); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.H_anchor_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->H_at_anchor, "H_a", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.V_anchor_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->V_at_anchor, "V_a", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gx_force_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->fx_fairlead, "Fx", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gy_force_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->fy_fairlead, "Fy", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.gz_force_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->fz_fairlead, "Fz", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.fairlead_tension_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->T, "T", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.anchor_tension_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->T_at_anchor, "T_a", "[N]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.lay_length_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->Lb, "Lb", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.horizontal_excursion_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->l, "l", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.vertical_excursion_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->h, "h", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.azimuth_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->psi, "psi", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.altitude_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->alpha, "alpha", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + if (line_iter->options.altitude_anchor_flag) { + success = push_variable_to_output_list(y_list, line_num, &line_iter->alpha_at_anchor, "alpha_a", "[m]"); + io_type->writeOutputHdr_Len++; + io_type->writeOutputUnt_Len++; + }; + + line_num++; + }; + list_iterator_stop(&domain->line); /* ending the iteration session */ + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE reset_line(Line* line_ptr) +{ + /* run-time flags */ + line_ptr->options.gx_pos_flag = false; + line_ptr->options.gy_pos_flag = false; + line_ptr->options.gz_pos_flag = false; + line_ptr->options.gx_anchor_pos_flag = false; + line_ptr->options.gy_anchor_pos_flag = false; + line_ptr->options.gz_anchor_pos_flag = false; + line_ptr->options.gx_force_flag = false; + line_ptr->options.gy_force_flag = false; + line_ptr->options.gz_force_flag = false; + line_ptr->options.H_flag = false; + line_ptr->options.H_anchor_flag = false; + line_ptr->options.V_flag = false; + line_ptr->options.V_anchor_flag = false; + line_ptr->options.fairlead_tension_flag = false; + line_ptr->options.anchor_tension_flag = false; + line_ptr->options.horizontal_excursion_flag = false; + line_ptr->options.vertical_excursion_flag = false; + line_ptr->options.azimuth_flag = false; + line_ptr->options.altitude_flag = false; + line_ptr->options.altitude_anchor_flag = false; + line_ptr->options.line_tension_flag = false; + line_ptr->options.omit_contact = false; + line_ptr->options.lay_length_flag = false; + line_ptr->options.damage_time_flag = false; + line_ptr->options.diagnostics_flag = false; + line_ptr->options.linear_spring = false; + + line_ptr->line_property = NULL; + line_ptr->label = NULL; + line_ptr->line_tension = NULL; + line_ptr->anchor = NULL; /* Anchor node */ + line_ptr->fairlead = NULL; /* Fairlead node */ + + line_ptr->H.name = NULL; + line_ptr->H.units = NULL; + line_ptr->V.name = NULL; + line_ptr->V.units = NULL; + + line_ptr->psi = -999.9; + line_ptr->alpha = -999.9; + line_ptr->alpha_at_anchor = -999.9; + line_ptr->l = -999.9; + line_ptr->Lb = -999.9; + line_ptr->h = -999.9; + line_ptr->H.value = NULL; + line_ptr->V.value = NULL; + line_ptr->H_at_anchor = -999.9; + line_ptr->V_at_anchor = -999.9; + line_ptr->fx_fairlead = -999.9; + line_ptr->fy_fairlead = -999.9; + line_ptr->fz_fairlead = -999.9; + line_ptr->fx_anchor = -999.9; + line_ptr->fy_anchor = -999.9; + line_ptr->fz_anchor = -999.9; + line_ptr->T = -999.9; + line_ptr->T_at_anchor = -999.9; + + line_ptr->residual_norm = 999.9; + line_ptr->damage_time = -999.9; + line_ptr->diagnostic_type = -9999; + line_ptr->segment_size = 10; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE reset_node(Node* node_ptr) +{ + node_ptr->position_ptr.x.name = NULL; + node_ptr->position_ptr.x.units = NULL; + node_ptr->position_ptr.x.value = NULL; + node_ptr->position_ptr.y.name = NULL; + node_ptr->position_ptr.y.units = NULL; + node_ptr->position_ptr.y.value = NULL; + node_ptr->position_ptr.z.name = NULL; + node_ptr->position_ptr.z.units = NULL; + node_ptr->position_ptr.z.value = NULL; + node_ptr->M_applied.name = NULL; + node_ptr->M_applied.units = NULL; + node_ptr->B_applied.name = NULL; + node_ptr->B_applied.units = NULL; + node_ptr->sum_force_ptr.fx.name = NULL; + node_ptr->sum_force_ptr.fx.units = NULL; + node_ptr->sum_force_ptr.fx.value = NULL; + node_ptr->sum_force_ptr.fy.name = NULL; + node_ptr->sum_force_ptr.fy.units = NULL; + node_ptr->sum_force_ptr.fy.value = NULL; + node_ptr->sum_force_ptr.fz.name = NULL; + node_ptr->sum_force_ptr.fz.units = NULL; + node_ptr->sum_force_ptr.fz.value = NULL; + + node_ptr->external_force.fx.name = NULL; + node_ptr->external_force.fx.units = NULL; + node_ptr->external_force.fy.name = NULL; + node_ptr->external_force.fy.units = NULL; + node_ptr->external_force.fz.name = NULL; + node_ptr->external_force.fz.units = NULL; + + node_ptr->M_applied.value = -999.9; + node_ptr->B_applied.value = -999.9; + node_ptr->external_force.fx.value = -999.9; + node_ptr->external_force.fy.value = -999.9; + node_ptr->external_force.fz.value = -999.9; + node_ptr->external_force.fx.user_initial_guess = false; + node_ptr->external_force.fy.user_initial_guess = false; + node_ptr->external_force.fz.user_initial_guess = false; + + node_ptr->sum_force_ptr.fx.is_fixed = false; + node_ptr->sum_force_ptr.fy.is_fixed = false; + node_ptr->sum_force_ptr.fz.is_fixed = false; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE associate_line_with_cable_property(Line* line_ptr, Domain* domain, const char* word, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // MAP_ERROR_CODE success = MAP_SAFE; + CableLibrary* library_iterator = NULL; + + library_iterator = NULL; + line_ptr->line_property = NULL; + + list_iterator_start(&domain->library); /* starting an iteration session */ + while (list_iterator_hasnext(&domain->library)) { /* tell whether more values available */ + library_iterator = (CableLibrary*)list_iterator_next(&domain->library); + if (biseqcstrcaseless(library_iterator->label, word)) { + line_ptr->line_property = library_iterator; + list_iterator_stop(&domain->library); /* ending the iteration session */ + break; + }; + }; + list_iterator_stop(&domain->library); /* ending the iteration session */ + if (line_ptr->line_property==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_27, "No libraries match <%s>.", word); + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE associate_line_with_anchor_node(Line* line_ptr, Domain* domain, const int line_num, const char* word, char* map_msg, MAP_ERROR_CODE* ierr) +{ + // MAP_ERROR_CODE success = MAP_SAFE; + Node* node_iter = NULL; + int node_num = 0; + + line_ptr->anchor = NULL; + + if (is_numeric(word)) { + node_num = (int)atoi(word); + node_iter = (Node*)list_get_at(&domain->node, node_num-1); + line_ptr->anchor = node_iter; /* create the associate with anchor here */ + if (!node_iter) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_30, "Line %d.", line_num); + return MAP_FATAL; + }; + } else { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_28, "Line %d.", line_num); + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE associate_line_with_fairlead_node(Line* line_ptr, Domain* domain, const int line_num, const char* word, char* map_msg, MAP_ERROR_CODE* ierr) +{ + Node* node_iter = NULL; + int node_num = 0; + // MAP_ERROR_CODE success = MAP_SAFE; + + line_ptr->fairlead = NULL; + + if (is_numeric(word)) { + node_num = (int)atoi(word); + node_iter = (Node*)list_get_at(&domain->node, node_num-1); + line_ptr->fairlead = node_iter; /* create the associate with anchor here */ + if (!node_iter) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_31, "Line %d.", line_num); + return MAP_FATAL; + }; + } else { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_29, "Line %d.", line_num); + return MAP_FATAL; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE is_numeric(const char* string) +{ + char* p = NULL; + if (string==NULL || *string=='\0' || isspace(*string)) { + return MAP_SAFE; + }; + strtod (string, &p); + if (*p=='\0') { + return MAP_FATAL; + } else { + return MAP_SAFE; + }; +}; + + +void log_initialization_information(MAP_InitInputType_t* init_type, MAP_ParameterType_t* p_type, MAP_OutputType_t* y_type, MAP_OtherStateType_t* other_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + InitializationData* init_data = init_type->object; + + MAP_BEGIN_ERROR_LOG; + if ( init_data->summary_file_name->data[0] ) { // don't write this file if the file name isn't specified + success = write_summary_file(init_data, p_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_37); + } + + success = write_summary_file(init_data, p_type, domain, map_msg, ierr); CHECKERRQ(MAP_FATAL_37); + success = get_iteration_output_stream(y_type, other_type, map_msg, ierr); // @todo CHECKERRQ() + MAP_END_ERROR_LOG; +}; + + +MAP_ERROR_CODE associate_vartype_ptr(VarTypePtr* type, double* arr, int index) +{ + type->value = &arr[index-1]; + return MAP_SAFE; +}; + + +void copy_target_string(char* target, unsigned char* source) +{ + while (*source) { + *target = *source; + source++; + target++; + }; + *target = '\0'; +}; + + +MAP_ERROR_CODE map_get_version(MAP_InitOutputType_t* io_type) +{ + bstring out_string = NULL; + int ret = 0; + + /* first set the program version defined in the mapsys.h header file + * @todo: program version should be tied to the gi revision numner + */ + out_string = bformat("<%s>",PROGVERSION); + if (out_string->slen>MAX_INIT_VERSION_STRING_LENGTH) { /* overflow */ + return MAP_FATAL; /* @todo: give proper error code */ + }; + copy_target_string(io_type->version, out_string->data); + ret = bdestroy(out_string); + + /* the set the compiling date. This is #defined in the mapsys.h header */ + out_string = bformat("<%c%c%c-%c%c-%c%c%c%c>",BUILD_MONTH_CH0,BUILD_MONTH_CH1,BUILD_MONTH_CH2,BUILD_DAY_CH0,BUILD_DAY_CH1,BUILD_YEAR_CH0,BUILD_YEAR_CH1,BUILD_YEAR_CH2,BUILD_YEAR_CH3); + if (out_string->slen>MAX_INIT_COMPILING_DATA_STRING_LENGTH) { /* overflow */ + return MAP_FATAL; /* @todo: give proper error code */ + }; + copy_target_string(io_type->compilingData, out_string->data); + ret = bdestroy(out_string); + return MAP_SAFE; +}; + + +void print_machine_name_to_screen( ) { + // __get_machine_name(name); + printf( "%s Ver. %s ", PROGNAME, PROGVERSION); + printf( "%c",BUILD_MONTH_CH0 );// build month + printf( "%c",BUILD_MONTH_CH1 ); + printf( "%c",BUILD_MONTH_CH2 ); + printf( "-" ); + printf( "%c",BUILD_DAY_CH0 );// build day + printf( "%c",BUILD_DAY_CH1 ); + printf( "-" ); + printf( "%c",BUILD_YEAR_CH0 ); // build year + printf( "%c",BUILD_YEAR_CH1 ); + printf( "%c",BUILD_YEAR_CH2 ); + printf( "%c\n",BUILD_YEAR_CH3 ); +} + + +const char* remove_first_character(const char* string) +{ + return string+1; +}; + + +MAP_ERROR_CODE print_help_to_screen() +{ + print_machine_name_to_screen( ); + + printf("MAP Input file section definitions:\n"); + printf(" Line dictionary definitions:\n"); + printf(" -LineType, --User-defined name of line [-] \n"); + printf(" -Diam, --Line diameter, used to calculate area and line displacement per unit length [m] \n"); + printf(" -MassDen, --Mass (in air) per unit length [kg/m] \n"); + printf(" -EA, --Axial stiffness [N] \n"); + printf(" -CB, --Cable/seabed Coulumb friction coefficient [-] \n"); + printf(" -CIntDamp, --Internal structural damping coefficient [Pa-s] \n"); + printf(" -Ca, --Cross-flow added-mass coefficient [-]\n"); + printf(" -Cdn, --Cross-flow drag coefficient [-]\n"); + printf(" -Cdt, --Tangent (skin) drag coefficient[-]\n"); + printf(" Node property definitions:\n"); + printf(" -Node, --Node number; first starts at 1 [-]\n"); + printf(" -Type, --Type of node. Must be one of: VESSEL, FIX, CONNECT [-]\n"); + printf(" -X, --Node X position. '#' must prefix CONNECT nodes; constitutes user initial guess [m]\n"); + printf(" -Y, --Node Y position. '#' must prefix CONNECT nodes; constitutes user initial guess [m]\n"); + printf(" -Z, --Node Z position. '#' must prefix CONNECT nodes; constitutes user initial guess [m]\n"); + printf(" -M, --Applied point mass at node [kg]\n"); + printf(" -B, --Applied point buoyancy module at node [m^3]\n"); + printf(" -FX, --Applied X external force at node. '#' must prefix VESSEL and FIX nodes [N]\n"); + printf(" -FY, --Applied Y external force at node. '#' must prefix VESSEL and FIX nodes [N]\n"); + printf(" -FZ, --Applied Z external force at node. '#' must prefix VESSEL and FIX nodes [N]\n"); + printf(" Line property definitions:\n"); + printf(" -Line, --Line number; first starts at 1 [-]\n"); + printf(" -LineType, --Must match property defined in 'Line Dictions'[-]\n"); + printf(" -UnstrLen, --Unstretched line length [m]\n"); + printf(" -NodeAnch, --Anchor node number corresponding to 'Node Property Definitions' section [-]\n"); + printf(" -NodeFair, --Fairlead node number corresponding to 'Node Property Definitions' section [-]\n"); + printf(" -Flags, --User run-time flag; see below [-]\n"); + printf(" \n"); + printf(" Line run-time options definitions\n"); + printf(" Outputs:\n"); + printf(" -gx_pos, --Fairlead position in global X [m]\n"); + printf(" -gy_pos, --Fairlead position in global Y [m]\n"); + printf(" -gx_pos, --Fairlead position in global Z [m]\n"); + printf(" -gx_a_pos, --Anchor position in global X [m]\n"); + printf(" -gy_a_pos, --Anchor position in global Y [m]\n"); + printf(" -gz_a_pos, --Anchor position in global Z [m]\n"); + printf(" -gx_force, --Fairlead force in global X (include applied forces) [N]\n"); + printf(" -gy_force, --Fairlead force in global Y (include applied forces) [N]\n"); + printf(" -gz_force, --Fairlead force in global Z (include applied forces) [N]\n"); + printf(" -h_fair, --Horizontal force at fairlead (does NOT include applied forces) [N]\n"); + printf(" -v_fair, --Vertical force at fairlead (does NOT include applied forces) [N]\n"); + printf(" -h_anch, --Horizontal force at anchor (does NOT include applied forces) [N]\n"); + printf(" -v_anch, --Vertical force at anchor (does NOT include applied forces) [N]\n"); + printf(" -tension_fair, --Line force-magnitude at fairlead (include applied loads) [N]\n"); + printf(" -tension_anch, --Line force-magnitude at anchor (include applied loads) [N]\n"); + printf(" -azimuth, --Line lateral offset angle global X axis [deg]\n"); + printf(" -altitude, --Line inclination angle relative to global XY plane at fairlead [deg]\n"); + printf(" -lay_length, --Length of line on seabed [m]\n"); + printf(" -line_tension, -- \n"); + printf(" Model features:\n"); + printf(" -omit_contact, --Ignore cable/seabed contact\n"); + printf(" -seg_size <10>, --Number of discrete lines in line\n"); + printf(" -damage_time <NULL>, --Line breakage occurs at specified time [s]\n"); + printf(" -diagnostic <TIME>, --Run line solver diagnostics until specified time [s] is reached\n"); + printf("\n"); + printf(" Model option definitions\n"); + printf(" General model features:\n"); + printf(" -ref_position <0.0> <0.0> <0.0>\n"); + printf(" -repeat <NULL> ... <NULL>\n"); + printf(" MSQS solver options:\n"); + printf(" -inner_ftol <float>,\n"); + printf(" -inner_gtol <float>,\n"); + printf(" -inner_xtol <float>,\n"); + printf(" -inner_max_its <int>,\n"); + printf(" -outer_tol <float>,\n"); + printf(" -outer_max_its <int>,\n"); + printf(" -outer_epsilon <float>,\n"); + printf(" -outer_bd,\n"); + printf(" -outer_cd,\n"); + printf(" -outer_fd,\n"); + printf(" -pg_cooked <1000.0> <1.0>,\n"); + printf(" -krylov_accelerator <3>,\n"); + printf(" -integration_dt <0.01>,\n"); + printf(" LM model feature (not suported yet):\n"); + printf(" -kb_default --Seabed stiffness parameter\n"); + printf(" -cb_default --Seabed damping parameter\n"); + printf(" -wave_kinematics --Enables wave kinematics to drag interaction from surface waves\n"); + printf(" -lm_model --Enable the lumped-mass model\n"); + printf( "\nMAP++ Copyright (C) 2014 and Apache'd by Marco Masciola and others\n" ); + printf( "SimCList Copyright (C) 2010 by Mij <http://mij.oltrelinux.com/devel/simclist/>\n" ); + printf( "MinPack Copyright (C) 1999 by the University of Chicago\n" ); + printf( "Modifications to MinPack by Frederic Devernay <http://devernay.free.fr/hacks/cminpack/>\n" ); + printf( "\nMAP++ is free software; see the source for copying conditions.\n" ); + printf( "This software is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES\n" ); + printf( "OR CONDITIONS OF ANY KIND, either express or implied. See\n" ); + printf( "<http://www.apache.org/licenses/LICENSE-2.0> forr more details.\n" ); + printf(" \n"); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE associate_constraint_states(Domain* domain, MAP_ConstraintStateType_t* z_type) +{ + Node* node_iter = NULL; + Line* line_iter = NULL; + int next = 0; + MAP_ERROR_CODE success = MAP_SAFE; + + MAP_BEGIN_ERROR_LOG; + + list_iterator_start(&domain->line); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->line)) { /* tell whether more values available */ + line_iter = (Line*)list_iterator_next(&domain->line); + success = associate_vartype_ptr(&line_iter->H, z_type->H, next+1); + success = associate_vartype_ptr(&line_iter->V, z_type->V, next+1); + next++; + }; + list_iterator_stop(&domain->line); /* ending the iteration "session" */ + + next = 0; + list_iterator_start(&domain->node); /* starting an iteration "session" */ + while (list_iterator_hasnext(&domain->node)) { /* tell whether more values available */ + node_iter = (Node*)list_iterator_next(&domain->node); + if (node_iter->type==CONNECT) { + success = associate_vartype_ptr(&node_iter->position_ptr.x, z_type->x, next+1); + success = associate_vartype_ptr(&node_iter->position_ptr.y, z_type->y, next+1); + success = associate_vartype_ptr(&node_iter->position_ptr.z, z_type->z, next+1); + next++; + }; + }; + list_iterator_stop(&domain->node); /* ending the iteration "session" */ + + MAP_END_ERROR_LOG; + + return MAP_SAFE; +} diff --git a/OpenFAST/modules/map/src/mapinit.h b/OpenFAST/modules/map/src/mapinit.h new file mode 100644 index 000000000..2693c2617 --- /dev/null +++ b/OpenFAST/modules/map/src/mapinit.h @@ -0,0 +1,881 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _MAPINIT_H +#define _MAPINIT_H + + +#include "map.h" + + +MAP_ERROR_CODE initialize_fortran_types(MAP_InputType_t* u_type, MAP_ParameterType_t* p_type, MAP_ContinuousStateType_t* x_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, MAP_InitOutputType_t* initout_type); +MAP_ERROR_CODE allocate_outlist(Domain* data, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Returns the size of CableLibrary structure for link list creation + * @param el, opaque object used in simclist + * @see map_init() + * @return Size of CableLibrary structure + */ +size_t cable_library_meter(const void* el); + + +/** + * @brief Returns the size of Node structure for link list creation + * @param el, opaque object used in simclist + * @see map_init() + * @return Size of Node structure + */ +size_t node_meter(const void* el); + + +/** + * @brief Returns the size of Line structure for link list creation + * @param el, opaque object used in simclist + * @see map_init() + * @return Size of Line structure + */ +size_t cable_line_meter(const void* el); + + +/** + * @brief Returns the size of ReferencePoint (inputs) structure for link list creation + * @param el, opaque object used in simclist + * @see map_init() + * @return Size of ReferencePoint (inputs) structure + */ +size_t u_list_meter(const void *el); + + +/** + * @brief Initializes the Fortran/C iteroperability types + * @details This is called in the map_create_init_type routine following successful allocation + * of memory. This should not be called directly by the user code. + * @param init_type, Fortran/C interoperable type {@link MAP_InitInputType_t} + * @see map_create_init_type() + */ +void initialize_init_type_to_null(MAP_InitInputType_t* init_type); + + +/** + * @brief Initializes MAP internal initialization data + * @details This is called in the map_create_init_type routine following successful allocation + * of memory. This should not be called directly by the user code. The internal states + * are nullified and set to zero. + * @param init_data, internal MAP initialization data {@link InitializationData} + * @see map_create_init_type() + */ +void initialize_init_data_to_null(InitializationData* init_data); + + +/** + * @brief Initialized all model data parameters to NULL or default values + * @details Calls other functions to nullify and assign model data variables default values. + * @param floater, the vessel strcture + * @see map_create_other_type() + */ +void initialize_domain_to_null(Domain* domain); + + +/** + * @brief Initializes MAP internal initialization data + * @details This is called in the map_create_init_type routine following successful allocation + * of memory. This should not be called directly by the user code. The internal states + * are nullified and set to zero. + * @param options, model variables not related to solver items/options + * @see map_create_init_type() + */ +void initialize_model_option_defaults(DomainOptions* options); + + +/** + * @brief Sets inner-loop solver data + * @details Jacobian is 2x2 and residual vectors are 2x1. Sizes are fixed because only two + * algebraic equations are solved for each lines. + * {@link free_outer_solve_data} + * @param inner, inner-loop solver data + * @see map_create_other_type() + */ +void initialize_inner_solve_data_defaults(InnerSolveAttributes* inner); + + +/** + * @brief Sets vessel parameters to NULL + * @details This function nullifies Vessel-associated pointers. The Vessel structure is a + * convenient way to displace all fairleads connected to a vessel with a single + * function call. Since the number of 'VESSEL' nodes are unknown at compile time, + * vessel arrays are sized at run-time. Deallocation occurs in {@link free_vessel} + * @param floater, the vessel strcture + * @see map_create_other_type() + */ +void initialize_vessel_to_null(Vessel* floater); + + +/** + * @brief Sets outer solver data (Jacobian, residual vector, ect) to NULL + * @details Unlike the inner solver data strcture, Jacobian and residual vectors sizes are not + * declared at compile time. These are resized depending on the number of 'connect' + * node declared in the problem. Outer solve data is deallocated in + * {@link free_outer_solve_data} + * @param outer, outer-loop solver data + * @see map_create_other_type() + */ +void initialize_outer_solve_data_defaults(OuterSolveAttributes* outer); + + +/** + * @brief Sets model solver options corresponding to the MAP input file parameters + * @details Called in {@link map_init} to set the corresponding model (solver) options + * in MAP. This is different from line flags. Note that this function can + * return MAP_WARNING and MAP_ERROR; these errors/warnings do not trip MAP_FATAL_33. + * Function must be modified to account for new options added at a future date. + * Valid solver options input parameter include: + * <pre> + * help + * inner_ftol + * inner_gtol + * inner_xtol + * inner_max_its + * outer_max_its + * outer_tol + * outer_epsilon + * integration_dt (unsupported LM option) + * kb_default (unsupported LM option) + * cb_default (unsupported LM option) + * wave_kinematics (unsupported LM option) + * outer_bd + * outer_cd + * outer_fd + * pg_cooked (not compatible with krylov_accelerator option) + * krylov_accelerator (not compatible ith pg_cooked option) + * repeat + * ref_position + * </pre> + * @param domain, MAP interal data construct + * @param init_data, initialization input strings + * @param map_msg, error message + * @param ierr, error code + * @see map_init() + * @return MAP error code + */ +MAP_ERROR_CODE set_model_options_list(Domain* data, InitializationData* init, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Initializes "HELP" flag model options + * @details Called by {@link set_model_option_list} to set the boolean for printing help + * contents to stdout. Prefixing the line with a space (" ") treats the line + * as a comment. + * MAP input file syntax: + * <pre> + * help + * </pre> + * @param list, a character array structure + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_help_flag(bstring list); + + +/** + * @brief Initializes "INNER_FTOL" tolerance for minpack + * @details Called by {@link set_model_option_list} to set the function tolerance. + * From MinPack documentation: "Termination occurs when both the actual + * and predicted relative reductions in the sum of squares are at most FTOL. + * Therefore, FTOL measures the relative error desired in the sum of squares." + * Prefixing the line with a space (" ") treats the line as a comment. + * MAP input file syntax: + * <pre> + * inner_ftol <float> + * </pre> + * @param list, a character array structure + * @param ftol, pointer to the FTOL paramter for minpack + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_inner_f_tol_flag(struct bstrList* list, double* ftol); + + +/** + * @brief Initializes "INNER_GTOL" tolerance for minpack + * @details Called by {@link set_model_option_list} to set the function tolerance. + * From MinPack documentation: "Termination occurs when the cosine of + * the angle between FVEC and any column of the Jacobian is at most GTOL + * in absolute value. Therefore, GTOL measures the orthogonality desired + * between the function vector and the columns of the Jacobian." Prefixing + * the line with a space (" ") treats the line as a comment. + * MAP input file syntax: + * <pre> + * inner_gtol <float> + * </pre> + * @param list, a character array structure + * @param gtol, pointer to the GTOL paramter for minpack + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_inner_g_tol_flag(struct bstrList* list, double* gtol); + + +/** + * @brief Initializes "INNER_XTOL" tolerance for minpack + * @details Called by {@link set_model_option_list} to set the function tolerance. + * From MinPack documentation: "Termination occurs when the relative + * error between two consecutive iterates is at most XTOL. Therefore, + * XTOL measures the relative error desired in the approximate solution. + * Prefixing the line with a space (" ") treats the line as a comment. + * MAP input file syntax: + * <pre> + * inner_xtol <float> + * </pre> + * @param list, a character array structure + * @param xtol, pointer to the XTOL paramter for minpack + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_inner_x_tol_flag(struct bstrList* list, double* xtol); + + +/** + * @brief Initializes "INNER_MAX_ITS" maximimum iteration count for inner-loop solver + * @details Called by {@link set_model_option_list} to set the maximum number of + * iterations for the MinPack routine. The solver terminate prematurely + * when this number is reached. + * MAP input file syntax: + * <pre> + * inner_max_its <float> + * </pre> + * @param list, a character array structure + * @param max_its, pointer to the maximum iteration count integer + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_inner_max_its_flag(struct bstrList* list, int* max_its); + + +/** + * @brief Initializes "OUTER_MAX_ITS" maximimum iteration count for outer-loop solver + * @details Called by {@link set_model_option_list} to set the maximum number of + * iterations for the MinPack routine. The solver terminate prematurely + * when this number is reaches + * MAP input file syntax: + * <pre> + * outer_max_its <float> + * </pre> + * @param list, a character array structure + * @param max_its, pointer to the maximum iteration count integer + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_max_its_flag(struct bstrList* list, int* max_its); + + +/** + * @brief Initializes "OUTER_TOL" tolerance for custom outer-loopNewton-Raphson + * solver + * @details Called by {@link set_model_option_list} to set the function tolerance. + * The convergence criteria required the norm of the function error to be + * less than OUTER_TOL to Prefixing the line with a space (" ") treats the + * line as a comment. + * MAP input file syntax: + * <pre> + * outer_tol <float> + * </pre> + * @param list, a character array structure + * @param outer_tol, pointer to the tolerance paramter + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_tol_flag(struct bstrList* list, double* outer_tol); + + +/** + * @brief Initializes "OUTER_EPSILON" finite-difference increment + * @details Called by {@link set_model_option_list} to set finite-difference tolerance + * for the outer-loop solver. + * MAP input file syntax: + * <pre> + * outer_epsilon <float> + * </pre> + * @param list, a character array structure + * @param epsilon, value by which the states are displaced + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_epsilon_flag(struct bstrList* list, double* epsilon); + + +/** + * @brief Sets FD type to BACKWARD-DIFFERENCE + * @details Called by {@link set_model_option_list} to set the outer-loop finite- + * difference scheme to backward-difference. + * $\frac{\mathbf{f}(x+\epsilon)-\mathbf{f}(x)}{\epsilon}$ + * MAP input file syntax: + * <pre> + * outer_bd + * </pre> + * @param list, a character array structure + * @param bd, finite difference type + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_bd_flag(struct bstrList* list, FdType* bd); + +/** + * @brief Sets FdType type to CENTRAL-DIFFERENCE + * @details Called by {@link set_model_option_list} to set the outer-loop finite- + * difference scheme to central-difference. + * $\frac{\mathbf{f}(x+\epsilon)-\mathbf{f}(x-\epsilon)}{2\epsilon}$ + * MAP input file syntax: + * <pre> + * outer_bd + * </pre> + * @param list, a character array structure + * @param cd, finite difference type + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_cd_flag(struct bstrList* list, FdType* cd); + + +/** + * @brief Sets FdType type to FORWARD-DIFFERENCE + * @details Called by {@link set_model_option_list} to set the outer-loop finite- + * difference scheme to forward-difference. + * $\frac{\mathbf{f}(x+\epsilon)-\mathbf{f}(x)}{\epsilon}$ + * MAP input file syntax: + * <pre> + * outer_fd + * </pre> + * @param list, a character array structure + * @param fd, finite difference type + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_outer_fd_flag(struct bstrList* list, FdType* fd); + + +/** + * @brief Sets DS and DSM preconditioning coefficients for outer-loop solver + * @details Called by {@link set_model_option_list} to set preconditioner coefficients + * placed on the outer-loop Jacobian. With the cosntriant state update being: + * $\mathbf{D}_{i,i}=\frac{\mathbf{DS}}{n^{3/2}}+\mathbf{DSM}$ + * then the preconditioner is: + * $\mathbf{z}_{n+1}=\mathbf{z}_{n}+\left(\mathbf{J}+\mathbf{D}\right)^{-1}\mathbf{r}$ + * This is essentially a Jacobi preconditioner. + * MAP input file syntax: + * <pre> + * outer_fd + * </pre> + * @article {peyrot1978, + * title={Analysis of flexible transmission lines}, + * author={Peyrot, Alain H and Goulois, Alain M}, + * journal={Journal of the Structural Division}, + * volume={104}, + * number={5}, + * pages={763--779}, + * year={1978}, + * publisher={ASCE} + * } + * @param list, a character array structure + * @param solver, outer solvr attributes + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_pg_cooked_flag(struct bstrList* list, OuterSolveAttributes* solver); + + +/** + * @brief Sets flag to use Powell's method to solve the outer loop nonlinear equations + * MAP input file syntax: + * <pre> + * POWELL + * </pre> + * @param list, a character array structure + * @param solver, outer solvr attributes + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_powell_flag(struct bstrList* list, OuterSolveAttributes* solver); + + +/** + * @brief Sets integration time step for the LM model. Not supported yet! + * @details Called by {@link set_model_option_list} to set the integrationt time step + * MAP input file syntax: + * <pre> + * integration_dt <float> + * </pre> + * @param list, a character array structure + * @param dt, integration time step + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_integration_dt_flag(struct bstrList* list, double* dt); + + +/** + * @brief Sets seabed stiffness factor for the LM model. Not supported yet! + * @details Called by {@link set_model_option_list} to set the seabed stiffness + * MAP input file syntax: + * <pre> + * kb_default <float> + * </pre> + * @param list, a character array structure + * @param kb, seabed stiffness in [N/m] + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_kb_default_flag(struct bstrList* list, double* kb); + + +/** + * @brief Sets the boolean and maximum iterations for kyrlov accelerator + * @details Called by {@link set_model_option_list} to choose the krylov + * accelerator option as the MSQS outer-loop option. Not compatible + * with pg_cooked option. + * MAP input file syntax: + * <pre> + * krylov_accelerator <float> + * </pre> + * @param list, a character array structure + * @param max_its, maximum numnber of krylov iterations + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_krylov_accelerator_flag(struct bstrList* list, OuterSolveAttributes* solver); + + +/** + * @brief Sets seabed damping factor for the LM model. Not supported yet! + * @details Called by {@link set_model_option_list} to set the seabed stiffness + * MAP input file syntax: + * <pre> + * cb_default <float> + * </pre> + * @param list, a character array structure + * @param kb, seabed damping in [N-s/m] + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_cb_default_flag(struct bstrList* list, double* cb); + + +/** + * @brief Compute the wave kinematics in MAP for the LM model. Not supported yet! + * @details Called by {@link set_model_option_list} to enable calculation of the + * local oribital fluid velocity and acceleration. This is fed as input + * to compute the added-mass and fluid-drag force. + * MAP input file syntax: + * <pre> + * wave_kinematics + * </pre> + * @param list, a character array structure + * @param wave, true if wave kinematics are computed in MAP + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_wave_kinematics_flag(struct bstrList* list, bool* wave); + + +/** + * @brief Use the LM model. + * @details Called by {@link set_model_option_list} to set the mooring model to + * the lumped-mass formulation. The MAP input file syntax: + * <pre> + * lm_model + * </pre> + * @param list, a character array structure + * @param lm, true if wave kinematics are computed in MAP + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_lm_model_flag(struct bstrList* list, bool* lm); + + +/** + * @brief Initializes "REPEAT" flag model options + * @details Called by {@link set_model_option_list} to set the number of line and node + * repeats. Prefixing the line with a space (" ") treats the line as a comment. + * MAP input file syntax: + * <pre> + * repeat <float_1> <float_2> ... <float_n> + * </pre> + * @param list, an array of bstring + * @param options, model options + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_repeat_flag(struct bstrList* list, DomainOptions* options); + + +/** + * @brief Set the model reference position + * @details Called by {@link set_model_option_list} to set the reference position. The + * reference position is where the linearized stiffness matrix is comuted. + * <pre> + * re_position <float_1> <float_2> <float_3> + * </pre> + * @param list, an array of bstring + * @param ref_position, 3D reference position point + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_ref_position_flag(struct bstrList* list, Point* ref_position); + + +/** + * @brief Checks to make sure option is valid + * @details Called by {@link set_model_option_list} to let users know if they have an + * invalid option in te MAP input file. + * @param list, an array of bstring + * @see set_model_options_list(), map_init() + * @return MAP error code + */ +MAP_ERROR_CODE check_uncaught_flag(struct bstrList* list); + + +/** + * @brief Sets cable properties + * @details Called in {@link map_init} to set the cable properties. The specific properties + * do not necessarily need to be used. + * <pre> + * label - cable name and identifier + * diam - cable diameter + * mass density (in air) + * EA - axial stiffness + * cb - seabed friction coefficient + * internal structural damping (unsupported LM option) + * cross-flow added mass coefficient (unsupported LM option) + * cross-float damping coefficient (unsupported LM option) + * tangen drag coefficient (unsupported LM option) + * </pre> + * @param domain, MAP interal data construct + * @param init_data, initialization input strings + * @param map_msg, error message + * @param ierr, error code + * @see map_init() + * @return MAP error code + */ +MAP_ERROR_CODE set_cable_library_list( Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr ); + + +/** + * @brief Set line diameter at initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_diameter(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line mass density in air at initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_mass_density(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line axial stiffness at initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_ea(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line/seabed friction coefficient at initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_cb(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line structural damping (internal) coefficient at initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_internal_damping(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line cross-flow added mass coefficient initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_added_mass_coefficient(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line cross-flow drag coefficient coefficient initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_cross_flow_drag_coefficient(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Set line skin drag coefficient initialization + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE set_library_tangent_drag_coefficient(bstring word, CableLibrary* library_ptr); + + +/** + * @brief Reset line properties to null or zero + * @details The only reason this is necessary is to destroy the label parameter + * in the cable library structure. If this parameter is not destroyed, + * then an error occurs when the next cable library entry is read. A + * segfault may occur when the bstrcpy() is called a second time on a + * non-nullified bstring. + * @param word, word to conver to float + * @param library_ptr, pointer to a cable library + * @see set_cable_library_list() + * @return MAP error code + */ +MAP_ERROR_CODE reset_cable_library(CableLibrary* new_cable_library); + + +MAP_ERROR_CODE repeat_nodes(Domain* domain, InitializationData* init_data, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE set_node_list(const MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, Domain* domain, struct bstrList* node_input_string, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE allocate_types_for_nodes(MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, Domain* domain, struct bstrList* node_input_string, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE reset_node(Node* node_ptr); +MAP_ERROR_CODE expand_node_number(const int n_line, bstring line); +MAP_ERROR_CODE expand_node_type(const char* word, bstring line); +MAP_ERROR_CODE expand_node_position_x(double* x, const char* word); +MAP_ERROR_CODE expand_node_position_y(double* y, const char* word); +MAP_ERROR_CODE expand_node_position_z(Vector* position, const double angle, const double x, const double y, const char* word, bstring line); +MAP_ERROR_CODE expand_node_mass(const char* word, bstring line); +MAP_ERROR_CODE expand_node_buoyancy(const char* word, bstring line); +MAP_ERROR_CODE expand_node_force_x(double* fx, const char* word); +MAP_ERROR_CODE expand_node_force_y(double* fy, const char* word); +MAP_ERROR_CODE expand_node_force_z(Vector* force, const double angle, const double fx, const double fy, const char* word, bstring line); + + +MAP_ERROR_CODE repeat_lines(Domain* domain, InitializationData* init, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE set_line_list(MAP_ConstraintStateType_t* z_type, Domain* domain, struct bstrList* line_input_string, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE reset_line(Line* line_ptr); +MAP_ERROR_CODE expand_line_number(const int n_line, bstring line); +MAP_ERROR_CODE expand_line_property_name(const char* word, bstring line); +MAP_ERROR_CODE expand_line_length(const char* word, bstring line); +MAP_ERROR_CODE expand_line_anchor_number(const char* word, const int index, const int n, bstring line); +MAP_ERROR_CODE expand_line_fairlead_number(const char* word, const int index, const int n, bstring line); +MAP_ERROR_CODE expand_line_flag(const char* word, bstring line); + + +MAP_ERROR_CODE set_vartype_ptr(const char* unit, bstring alias, const int num, VarTypePtr* type, bstring property); +MAP_ERROR_CODE set_vartype(const char* unit, bstring alias, const int num, VarType* type, bstring property ); + + +/** + * @brief Compares two integers. + * @details Used in comparing the size of a MAP state against iteration count. + * Used in {@link set_node_list()} + * @param a, an integer + * @param b, an integer + * @return MAP_FATAL if a != b; otherwise safe + */ +MAP_ERROR_CODE compare_integer_length(const int a, const int b); + + +// MAP_ERROR_CODE set_line_vartype(Line* line_ptr, const int i); @rm +MAP_ERROR_CODE associate_line_with_cable_property(Line* line_ptr, Domain* domain, const char* word, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE associate_line_with_anchor_node(Line* line_ptr, Domain* domain, const int line_num, const char* word, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE associate_line_with_fairlead_node(Line* line_ptr, Domain* domain, const int line_num, const char* word, char* map_msg, MAP_ERROR_CODE* ierr); +MAP_ERROR_CODE set_line_option_flags(struct bstrList* word, int* index, Line* line_ptr, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief set the 'unit' and 'name' attributes for the node vartype's + * @details Used in the initialization routine, part of {@link set_node_list()} + * @param node_ptr pointer to a newly allocated node data struct + */ +MAP_ERROR_CODE set_node_vartype(Node* node_ptr); + + +/** + * @brief + * @param domain internal state data {@link Domain} + * @param io_type initialization output type, native C struct {@link MAP_InitOutputType_t} + * @param map_msg error message + * @param ierr error code + */ +MAP_ERROR_CODE set_output_list(Domain* domain, MAP_InitOutputType_t* io_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief This sets the pointers to NULL for the vessel object and gives it default properties. + * @todo: need to associate the node with inputs + * @acceses: set_vartype_float( ) + * @calledby: mapcall_msqs_init( ) + */ +MAP_ERROR_CODE set_vessel(Vessel* floater, const MAP_InputType_t* u_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * This sets the pointers to NULL for the vessel object and gives it default properties. Only + * to be used in the python glue code. + * + * @todo: need to associate the node with inputs + * @acceses: set_vartype_float( ) + * @calledby: mapcall_msqs_init( ) + */ +MAP_ERROR_CODE set_vartype_float(const char* unit, const char* alias, const int num, VarType* type, const double value); + + +/** + * @breif Allocate outer solve data + * @param ns, outer solve attributes; preserves l, jac, and u + * @param size, matrix size + * @param map_msg, error message + * @param ierr, error code + * @see mapcall_msqs_init() + * @see mapcall_msqs_end() + * @see free_outer_solve_data() for data deallocation + * @return MAP error code + */ +MAP_ERROR_CODE allocate_outer_solve_data(OuterSolveAttributes* ns, const int size, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @breif Initialized omega (weight per unit length) and cross-section area of a cable. + * @details Called by {@link map_init} to assign: + * $A=\pi*\frac{radius^{2}}{4}$ + * and + * $\omega=g*(\mu-A*\rho_{seawater})$ + * @param domain, mooring domain + * @param p_type, parameter type + * @param map_msg, error message + * @param ierr, error code + * @see mapcall_msqs_init() + * @see mapcall_msqs_end() + * @see free_outer_solve_data() for data deallocation + * @return MAP error code + */ +MAP_ERROR_CODE initialize_cable_library_variables(Domain* domain, MAP_ParameterType_t* p_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * Sets init data to NULL or -9999 + * + * @acceses: none + * @calledby: mapcall_msqs_init( ) + * + * OBTAINED FROM THE CMINPACK SOURCE. The following defintions of the inputs for lmder(...) are provided in the cminpack docmentation. + * + * info = __cminpack_func__(lmder)( inner_function_evals, lineIter, m, n, x, fvec, fjac, ldfjac, ftol, xtol, gtol, + * maxfev, diag, mode, factor, nprint, &nfev, &njev, ipvt, qtf, wa1, wa2, wa3, wa4); + * + * - ftol : a nonnegative input variable. Termination occurs when both the actual and predicted relative reductions in the sum of squares are at most ftol. Therefore, ftol measures the relative error desired in the sum of squares. + * - xtol : a nonnegative input variable. Termination occurs when the relative error between two consecutive iterates is at most xtol. Therefore, xtol measures the relative error desired in the approximate solution. + * - gtol : a nonnegative input variable. Termination occurs when the cosine of the angle between fvec and any column of the Jacobian is at most gtol in absolute value. Therefore, gtol measures the orthogonality desired between the function vector and the columns of the Jacobian. + * - maxfev : a positive integer input variable. Termination occurs when the number of calls to fcn is at least maxfev by the end of an iteration. + * - diag : an array of length n. If mode = 1 (see below), diag is internally set. If mode = 2, diag must contain positive entries that serve as multiplicative scale factors for the variables. + * - mode : an integer input variable. If mode = 1, the variables will be scaled internally. If mode = 2, the scaling is specified by the input diag. Other values of mode are equivalent to mode = 1. + * - factor : a positive input variable used in determining the initial step bound. This bound is set to the product of factor and the euclidean norm of diag*x if the latter is nonzero, or else to factor itself. In most cases factor should lie in the interval (.1,100.). 100. is a generally recommended value. + * - nprint : an integer input variable that enables controlled printing of iterates if it is positive. In this case, fcn is called with iflag = 0 at the beginning of the first iteration and every nprint iterations thereafter and immediately prior to return, with x and fvec available for printing. If nprint is not positive, no special calls of fcn with iflag = 0 are made. + * - info : an integer output variable. If the user has terminated execution, info is set to the (negative) value of iflag. See description of fcn. Otherwise, info is set as follows. + * - info=0 : improper input parameters. + * - info=1 : both actual and predicted relative reductions in the sum of squares are at most ftol. + * - info=2 : relative error between two consecutive iterates is at most xtol. + * - info=3 : conditions for info = 1 and info = 2 both hold. + * - info=4 : the cosine of the angle between fvec and any column of the Jacobian is at most gtol in absolute value. + * - info=5 : number of calls to fcn has reached or exceeded maxfev. + * - info=6 : ftol is too small. No further reduction in the sum of squares is possible. + * - info=7 : xtol is too small. No further improvement in the approximate solution x is possible. + * - info=8 : gtol is too small. fvec is orthogonal to the columns of the Jacobian to machine precision. + * - nfev : an integer output variable set to the number of calls to fcn with iflag = 1. + * - njev : an integer output variable set to the number of calls to fcn with iflag = 2. + * - ipvt : an integer output array of length n. ipvt defines a permutation matrix p such that jac*p = q*r, where jac is the final calculated Jacobian, q is orthogonal (not stored), and r is upper triangular with diagonal lines of nonincreasing magnitude. Column j of p is column ipvt(j) of the identity matrix. + * - qtf : an output array of length n which contains the first n lines of the vector (q transpose)*fvec. + * - wa1, wa2, wa3 : are work arrays of length n. + * - wa4 : a work array of length m. + */ +MAP_ERROR_CODE first_solve(Domain* domain, MAP_ParameterType_t* p_type, MAP_InputType_t* u_type, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, MAP_OutputType_t* y_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * Check if a string can be converted to a valid numeric value + * + * 0 (MAP_SAFE) is reserved for 'safe' exit out of functions. + * + * @param s must point to a user-provided memory location + * @return 0 for success, 3 for failure + * + * @see MAP_ERROR_CODE + */ +MAP_ERROR_CODE is_numeric(const char* string); + + +/** + * @breif Write the map summary file + * @details Is called once in {@link map_init} to create the summary file post-solve. + * Even if the solution is not solved, the summary file will be written. + * @param init_type, initialization type + * @param p_type, parameter type + * @param y_type, output type + * @param other_type, oter state type + * @param domain, mooring domain + * @param map_msg, error message + * @param ierr, error code + * @see mapcall_msqs_init() + */ +void log_initialization_information(MAP_InitInputType_t* init_type, MAP_ParameterType_t* p_type, MAP_OutputType_t* y_type, MAP_OtherStateType_t* other_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +MAP_ERROR_CODE associate_vartype_ptr(VarTypePtr* type, double* arr, int index); +void copy_target_string(char* target, unsigned char* source); +MAP_ERROR_CODE initialize_external_applied_force(char* unit, char* alias, const int num, VarType* type, char const* property); +MAP_ERROR_CODE initialize_node_sum_force_ptr(char* unit, char* alias, const int num, VarTypePtr* type); +MAP_ERROR_CODE map_get_version(MAP_InitOutputType_t* io_type); +MAP_ERROR_CODE print_help_to_screen(); +size_t vartype_meter(const void* el); +size_t vartype_ptr_meter(const void *el); +const char* remove_first_character(const char* string); +void print_machine_name_to_screen(); + +/** + */ +MAP_ERROR_CODE associate_constraint_states(Domain* domain, MAP_ConstraintStateType_t* z_type); + + +#endif /* _INITIALIZATION_H */ diff --git a/OpenFAST/modules/map/src/mapsys.h b/OpenFAST/modules/map/src/mapsys.h new file mode 100644 index 000000000..9dbf89e53 --- /dev/null +++ b/OpenFAST/modules/map/src/mapsys.h @@ -0,0 +1,162 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _MAPSYS_H +#define _MAPSYS_H + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <math.h> + + +#if defined(_WIN32) || defined(_WIN64) +# include <Windows.h> +# include <tchar.h> +#else +# include <unistd.h> +#endif + + +#if defined(_MSC_VER) + typedef int bool; + #define false 0 + #define true 1 +//# include "stdbool.h" +# define map_snprintf _snprintf +# define map_strcat(a,b,c) strcat_s(a,b,c) +# define MAP_EXTERNCALL __declspec( dllexport ) +# define MAP_STRCPY(a,b,c) strcpy_s(a,b,c) +#else +# include <stdbool.h> +# define map_snprintf snprintf +# define map_strcat(a,b,c) strncat(a,c,b) +# if defined(__MINGW32__) +# define MAP_EXTERNCALL __declspec( dllexport ) +# else +# define MAP_EXTERNCALL +# endif +# define MAP_STRCPY(a,b,c) strcpy(a,c) +#endif + + +#ifndef BUILD_DEFS_H +# define BUILD_DEFS_H +# define BUILD_YEAR_CH0 (__DATE__[ 7]) +# define BUILD_YEAR_CH1 (__DATE__[ 8]) +# define BUILD_YEAR_CH2 (__DATE__[ 9]) +# define BUILD_YEAR_CH3 (__DATE__[10]) +# define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +# define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +# define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +# define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +# define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +# define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +# define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +# define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +# define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +# define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +# define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +# define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') +# define BUILD_MONTH_CH0 (__DATE__[ 0]) +# define BUILD_MONTH_CH1 (__DATE__[ 1]) +# define BUILD_MONTH_CH2 (__DATE__[ 2]) +# define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +# define BUILD_DAY_CH1 (__DATE__[ 5]) +#endif // BUILD_DEFS_H + + +#ifdef DEBUG +# define checkpoint() printf("Checkpoint: Line %d in file %s\n",__LINE__,__FILE__); +#else +# define checkpoint() +#endif // DEBUG + + +#define MAX_INIT_TYPE_STRING_LENGTH 255 +#define TIME_BUFFER_SIZE 64 +#define MAX_INIT_VERSION_STRING_LENGTH 99 +#define MAX_INIT_COMPILING_DATA_STRING_LENGTH 25 +#define MAP_ERROR_STRING_LENGTH 1024 +#define MAP_HORIZONTAL_TOL 1E-2 + +#define PROGNAME "MAP++ (Mooring Analysis Program++)" +#define PROGVERSION "1.20.10" +#define CHECKERRQ(code) if(success!=MAP_SAFE) {set_universal_error(map_msg, ierr, code); break;} +#define CHECKERRK(code) if(success!=MAP_SAFE) {set_universal_error(map_msg, ierr, code);} +#define MAPFREE(obj) if(obj!=NULL) {free(obj); obj=NULL;} +#define DEG2RAD 0.01745329251 /* pi/180 */ +#define RAD2DEG 57.2957795131 /* 180/pi */ +#define ARCSINH(x) log(x+sqrt(1+x*x)) +#define SPACE_LENGTH 12 +#define MACHINE_EPSILON 1e-16 +#define MAP_BEGIN_ERROR_LOG do{ \ + ; +#define MAP_END_ERROR_LOG } while(0); +#define MAP_RETURN_STATUS(x) \ + if (x==MAP_SAFE) { \ + return MAP_SAFE; \ + } else if (x==MAP_ERROR) { \ + return MAP_ERROR; \ + } else { \ + return MAP_FATAL; \ + }; + + +/* Text Coloring (OS dependant) + * + * Not used any longer, but can color text at the terminal. If we are on a non-Unix OS, then: + * -- set the strings to "" (empty) so that garbage is not printed + */ +#ifdef __posix +# define MAP_COLOR_RED "\033[1;31m" +# define MAP_COLOR_YELLOW "\033[1;33m" +# define MAP_COLOR_BLUE "\033[1;34m" +# define MAP_COLOR_END "\033[0m" +#elif __linux +# define MAP_COLOR_RED "\033[1;31m" +# define MAP_COLOR_YELLOW "\033[1;33m" +# define MAP_COLOR_BLUE "\033[1;34m" +# define MAP_COLOR_END "\033[0m" +#elif __unix +# define MAP_COLOR_RED "\033[1;31m" +# define MAP_COLOR_YELLOW "\033[1;33m" +# define MAP_COLOR_BLUE "\033[1;34m" +# define MAP_COLOR_END "\033[0m" +#elif __APPLE__ +# define MAP_COLOR_RED "\033[1;31m" +# define MAP_COLOR_YELLOW "\033[1;33m" +# define MAP_COLOR_BLUE "\033[1;34m" +# define MAP_COLOR_END "\033[0m" +#else +# define MAP_COLOR_RED "" +# define MAP_COLOR_YELLOW "" +# define MAP_COLOR_BLUE "" +# define MAP_COLOR_END "" +#endif + +void __get_machine_name( char* machineName ); + +#endif /* _MAPSYS_H */ diff --git a/OpenFAST/modules/map/src/numeric.c b/OpenFAST/modules/map/src/numeric.c new file mode 100644 index 000000000..fac269c46 --- /dev/null +++ b/OpenFAST/modules/map/src/numeric.c @@ -0,0 +1,270 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "numeric.h" +#include "lineroutines.h" +#include "jacobian.h" +#include "residual.h" + + +MAP_ERROR_CODE root_finding_step(OuterSolveAttributes* ns, const int n, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, double* error, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + const int z_size = z_type->z_Len; + const int THREE = 3; + int i = 0; + + MAP_BEGIN_ERROR_LOG; + + success = lu(ns, n, map_msg, ierr); CHECKERRQ(MAP_FATAL_74); + success = lu_back_substitution(ns, n, map_msg, ierr); CHECKERRQ(MAP_FATAL_74); + + /* Note that: ns->x = J^(-1) * F + * [x,y,z]_i+1 = [x,y,z]_i - J^(-1) * F + */ + for (i=0 ; i<z_size ; i++) { + z_type->x[i] -= ns->x[THREE*i]; + z_type->y[i] -= ns->x[THREE*i+1]; + z_type->z[i] -= ns->x[THREE*i+2]; + *error += (pow(other_type->Fx_connect[i],2)+ pow(other_type->Fy_connect[i],2) + pow(other_type->Fz_connect[i],2)); + }; + + MAP_END_ERROR_LOG; + + return MAP_SAFE; +}; + + +int inner_function_evals(void* line_ptr, int m, int n, const __cminpack_real__* x, __cminpack_real__* fvec, __cminpack_real__* fjac, int ldfjac, int iflag) +{ + Line* line = (Line*)line_ptr; + const double Fh = x[0]; + // const double Fh = fabs(x[0]) > MAP_HORIZONTAL_TOL ? fabs(x[0]) : MAP_HORIZONTAL_TOL; + const double Fv = x[1]; + const double EA = line->line_property->EA; + const double Lu = line->Lu.value; + const double height = line->h; + const double length = line->l; + // const double height = line->h > MAP_HORIZONTAL_TOL ? line->h : MAP_HORIZONTAL_TOL; + // const double length = line->l > MAP_HORIZONTAL_TOL ? line->l : MAP_HORIZONTAL_TOL; + const double omega = line->line_property->omega; + const double cb = line->line_property->cb; + const bool contactFlag = line->options.omit_contact; + + if (iflag==0) { + return 0; + }; + + /* Taken from the preceeding FAST 7 HydroDyn.f90 source (verbatim): + * To avoid an ill - conditioned situation, ensure that the initial guess for HF is not less than or equal to zero.Similarly, avoid the problems + * associated with having exactly vertical(so that HF is zero) or exactly horizontal(so that VF is zero) lines by setting the minimum values + * equal to the tolerance.This prevents us from needing to implement the known limiting solutions for vertical or horizontal lines(and thus + * complicating this routine): + * + * HF = MAX(HF, Tol) + * XF = MAX(XF, Tol) + * ZF = MAX(ZF, TOl) + */ + if (iflag!=2) { + if (contactFlag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + fvec[0] = residual_function_length_no_contact(Fv, Fh, omega, Lu, EA, length); + fvec[1] = residual_function_height_no_contact(Fv, Fh, omega, Lu, EA, height); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + fvec[0] = residual_function_length_contact(Fv, Fh, omega, Lu, EA, length, cb); + fvec[1] = residual_function_height_contact(Fv, Fh, omega, Lu, EA, height, cb); + }; + } else { + if (contactFlag==true || omega<0.0 || (Fv-omega*Lu)>0.0) { /* true when no portion of the line rests on the seabed */ + fjac[0] = jacobian_dxdh_no_contact(Fv, Fh, omega, Lu, EA); + fjac[1] = jacobian_dxdv_no_contact(Fv, Fh, omega, Lu, EA); + fjac[2] = jacobian_dzdh_no_contact(Fv, Fh, omega, Lu, EA); + fjac[3] = jacobian_dzdv_no_contact(Fv, Fh, omega, Lu, EA); + } else { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + fjac[0] = jacobian_dxdh_contact(Fv, Fh, omega, Lu, EA, cb); + fjac[1] = jacobian_dxdv_contact(Fv, Fh, omega, Lu, EA, cb); + fjac[2] = jacobian_dzdh_contact(Fv, Fh, omega, Lu, EA, cb); + fjac[3] = jacobian_dzdv_contact(Fv, Fh, omega, Lu, EA, cb); + }; + }; + return 0; +}; + + +MAP_ERROR_CODE lu(OuterSolveAttributes* ns, const int n, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int i = 0; + int j = 0; + int k = 0; + + for (i=0 ; i<n ; i++) { + ns->l[i][i] = 1.0; + for (j=i+1 ; j<n ; j++) { + if (fabs(ns->jac[i][i])<MACHINE_EPSILON) { + return MAP_FATAL; + }; + ns->l[j][i] = (ns->jac[j][i])/(ns->jac[i][i]); + /* ns->jac[j][j] = ns->l[j][j] */ + for (k=i+1 ; k<n ; k++) { + ns->jac[j][k] = ns->jac[j][k] - (ns->l[j][i])*(ns->jac[i][k]); + }; + }; + + for (k=i ; k<n ; k++) { + ns->u[i][k] = ns->jac[i][k] ; + }; + }; + + return MAP_SAFE; +}; + + +/** + * Ax = b -> LUx = b. Then y is defined to be Ux + */ +MAP_ERROR_CODE lu_back_substitution(OuterSolveAttributes* ns, const int n, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int i = 0; + int j = 0; + + /* Forward solve Ly = b */ + for (i=0 ; i<n ; i++) { + /* @todo: I think y can be eliminated. It is simply a copy of b */ + ns->y[i] = ns->b[i]; + for (j=0 ; j<i ; j++) { + ns->y[i] -= (ns->l[i][j])*(ns->y[j]); + }; + if (fabs(ns->l[i][i])<MACHINE_EPSILON) { + return MAP_FATAL; + }; + ns->y[i] /= ns->l[i][i]; + }; + + /* Backward solve Ux = y */ + for (i=n-1 ; i>=0 ; i--) { + ns->x[i] = ns->y[i]; + for (j=i+1 ; j<n ; j++) { + ns->x[i] -= (ns->u[i][j])*(ns->x[j]); + }; + if (fabs(ns->u[i][i])<MACHINE_EPSILON) { + return MAP_FATAL; + }; + ns->x[i] /= ns->u[i][i]; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE call_minpack_lmder(Line* line, InnerSolveAttributes* inner_opt, const int line_num, const float time, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + + /* initial guess vector is set in set_line_initial_guess(..); otherwise, the previous solution is used as the initial guess */ + inner_opt->x[0] = fabs(*(line->H.value)) > MAP_HORIZONTAL_TOL ? fabs(*(line->H.value)) : MAP_HORIZONTAL_TOL; + // inner_opt->x[0] = *(line->H.value); + inner_opt->x[1] = *(line->V.value); + + line->evals = 0; + line->njac_evals = 0; + + inner_opt->info = __cminpack_func__(lmder)(inner_function_evals, + line, + inner_opt->m, + inner_opt->n, + inner_opt->x, + inner_opt->fvec, + inner_opt->fjac, + inner_opt->ldfjac, + inner_opt->f_tol, + inner_opt->x_tol, + inner_opt->g_tol, + inner_opt->max_its, + inner_opt->diag, + inner_opt->mode, + inner_opt->factor, + inner_opt->nprint, + &line->evals, + &line->njac_evals, + inner_opt->ipvt, + inner_opt->qtf, + inner_opt->wa1 , + inner_opt->wa2 , + inner_opt->wa3 , + inner_opt->wa4); + + line->residual_norm = (double)__minpack_func__(enorm)(&inner_opt->m, inner_opt->fvec); + + if (line->options.diagnostics_flag && (double)line->diagnostic_type>time /* || line->residual_norm>inner_opt->f_tol */ ) { + printf("\n %4.3f [sec] Line %d\n",time, line_num); + printf(" ----------------------------------------------------\n"); + printf(" Residual l2 norm at solution: %15.7g\n", line->residual_norm); + printf(" Function evaluations: %10i\n", line->evals); + printf(" Jacobian evaluations: %10i\n", line->njac_evals); + if (line->residual_norm>inner_opt->f_tol) { + printf(" WARNING: l2 norm is much larger than f_tol. Premature convergence is likely\n"); + } + printf(" Exit parameter %10i\n\n", inner_opt->info); + }; + + *(line->H.value) = inner_opt->x[0]; + *(line->V.value) = inner_opt->x[1]; + line->converge_reason = inner_opt->info; + + switch (inner_opt->info) { + case 0 : + success = MAP_FATAL; + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_39, "Line segment %d.", line_num); + break; + case 1 : + success = MAP_SAFE; + break; + case 2 : + success = MAP_SAFE; + break; + case 3 : + success = MAP_SAFE; + break; + case 4 : + success = MAP_SAFE; + break; + case 5 : + success = MAP_FATAL; + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_40, "Line segment %d.", line_num); + break; + case 6 : + success = MAP_FATAL; + set_universal_error_with_message(map_msg, ierr, MAP_ERROR_11, "Line segment %d.", line_num); + break; + case 7 : + success = MAP_FATAL; + set_universal_error_with_message(map_msg, ierr, MAP_ERROR_13, "Line segment %d.", line_num); + break; + case 8 : + success = MAP_FATAL; + set_universal_error_with_message(map_msg, ierr, MAP_ERROR_12, "Line segment %d.", line_num); + break; + default : + success = MAP_SAFE; + break; + }; + return MAP_SAFE; +}; diff --git a/OpenFAST/modules/map/src/numeric.h b/OpenFAST/modules/map/src/numeric.h new file mode 100644 index 000000000..b22509dad --- /dev/null +++ b/OpenFAST/modules/map/src/numeric.h @@ -0,0 +1,163 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _NUMERIC_H +#define _NUMERIC_H + +#include "map.h" + + +/** + * @brief Forms the LU matrix for inverting the Jacobian - step 1 + * @details Called by {@link node_solve_sequence} to form the + * lower (L) and upper (U) triangular matrices to solve + * the system of equations. This is called in the outer + * (node) solve sequence. Back substitution through the + * function {@link lu_back_substitution} follows this + * function call to complete the newton iteration. + * $\mathbf{A}=\mathbf{LU}$ + * with + * $\begin{bmatrix} + * a_{11} & a_{12} & a_{13} \\ + * a_{21} & a_{22} & a_{23} \\ + * a_{31} & a_{32} & a_{33} \\ + * \end{bmatrix} = + * \begin{bmatrix} + * l_{11} & 0 & 0 \\ + * l_{21} & l_{22} & 0 \\ + * l_{31} & l_{32} & l_{33} \\ + * \end{bmatrix} + * \begin{bmatrix} + * u_{11} & u_{12} & u_{13} \\ + * 0 & u_{22} & u_{23} \\ + * 0 & 0 & u_{33} \\ + * \end{bmatrix} + * $ + * @param ns, outer solve attributes; preserves l, jac, and u + * @param n, matrix size, nxn + * @param map_msg, error message + * @param ierr, error code + * @see node_solve_sequence() + * @return MAP error code + */ +MAP_ERROR_CODE root_finding_step(OuterSolveAttributes* ns, const int n, MAP_ConstraintStateType_t* z_type, MAP_OtherStateType_t* other_type, double* error, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Wrapper for cminpack's lmder function + * @details Called by {@link solve_line} to solve the catenary + * equations. The minpack documentation describes the + * the lmder function as: + * <pre> + * The purpose of LMDER is to minimize the sum of the + * squares of M nonlinear functions in N variables by + * a modification of the Levenberg-Marquardt algorithm. + * The user must provide a subroutine which calculates + * the functions and the Jacobian. + * </pre> + * @param line, the line structure to be checked + * @param inner_opt, + * @param line_num, line number for error logging + * @param time, current time + * @param map_msg, error message + * @param ierr, error code + * @see solve_line() + * @return MAP error code + */ +MAP_ERROR_CODE call_minpack_lmder(Line* line, InnerSolveAttributes* inner_opt, const int line_num, const float time, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Return the residual and Jacobian for each line + * @details Passed as a function pointer to the cminpack lmder routine. + * Used in function {@link call_minpack_lmder} to solve the catenary + * equations. + * @param line_ptr, the line structure + * @param m, + * @param n, + * @param x, current state vector + * @param fvec, residual vector + * @param fjac, jacobian matrix + * @param ldfjac, + * @param iflag, solve status; 0 = error + * @return minpack error code + */ +int inner_function_evals(void* line_ptr, int m, int n, const __cminpack_real__* x, __cminpack_real__* fvec, __cminpack_real__* fjac, int ldfjac, int iflag); + + +/** + * @brief Forms the LU matrix for inverting the Jacobian - step 1 + * @details Called by {@link node_solve_sequence} to form the + * lower (L) and upper (U) triangular matrices to solve + * the system of equations. This is called in the outer + * (node) solve sequence. Back substitution through the + * function {@link lu_back_substitution} follows this + * function call to complete the newton iteration. + * $\mathbf{A}=\mathbf{LU}$ + * with + * $\begin{bmatrix} + * a_{11} & a_{12} & a_{13} \\ + * a_{21} & a_{22} & a_{23} \\ + * a_{31} & a_{32} & a_{33} \\ + * \end{bmatrix} = + * \begin{bmatrix} + * l_{11} & 0 & 0 \\ + * l_{21} & l_{22} & 0 \\ + * l_{31} & l_{32} & l_{33} \\ + * \end{bmatrix} + * \begin{bmatrix} + * u_{11} & u_{12} & u_{13} \\ + * 0 & u_{22} & u_{23} \\ + * 0 & 0 & u_{33} \\ + * \end{bmatrix} + * $ + * @param ns, outer solve attributes; preserves l, jac, and u + * @param n, matrix size, nxn + * @param map_msg, error message + * @param ierr, error code + * @see node_solve_sequence() + * @return MAP error code + */ +MAP_ERROR_CODE lu(OuterSolveAttributes* ns, const int n, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Solves $\mathbf{Ax}=\mathbf{b}$ through forward and backward substitution + * @details Called by {@link node_solve_sequence} to solve: + * $\mathbf{Ly}=\mathbf{b}$ + * then: + * $\mathbf{Ux}=\mathbf{y}$ + * The vector \mathbf{x} is used to increment the Newton step. + * Note that $\mathbf{x} = \mathbf{J}^{-1} (\textup{residual})$ with + * $\mathbf{x}=$ns->x + * @param ns, outer solve attributes; preserves l, u, x, and y + * @param n, matrix size, nxn + * @param map_msg, error message + * @param ierr, error code + * @see node_solve_sequence() + * @return MAP error code + */ +MAP_ERROR_CODE lu_back_substitution(OuterSolveAttributes* ns, const int n, char* map_msg, MAP_ERROR_CODE* ierr); + + +#endif // _NUMERIC_H diff --git a/OpenFAST/modules/map/src/outputstream.c b/OpenFAST/modules/map/src/outputstream.c new file mode 100644 index 000000000..b7aae4e81 --- /dev/null +++ b/OpenFAST/modules/map/src/outputstream.c @@ -0,0 +1,947 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 + */ + + +#include "outputstream.h" + + +// <<<<<<< HEAD +// /** @addtogroup FortranCall */ +// /* @{ */ +// MAP_EXTERNCALL void set_summary_file_name(MAP_InitInputType_t* init_type, char *map_msg, MAP_ERROR_CODE *ierr) { +// int length = 0; +// char *temp = NULL; +// InitializationData* init = init_type->object; +// +// if (init->summaryFileName!=NULL) { +// MAPFREE(init->summaryFileName); +// }; +// temp = strtok(init_type->summaryFileName, " \n&"); +// length = strlen(temp)+1; +// init->summaryFileName = (char*)malloc(sizeof(char)*length); +// strcpy(init->summaryFileName, temp); +// init_type->summaryFileName[0] = 0; +// }; +// +// +// MAP_EXTERNCALL void get_header_string(int* n, char** str_array, MAP_OtherStateType_t* other_type) +// { +// int count = 0; +// ModelData* model_data = other_type->object; +// VarTypePtr* vartype_ptr = NULL; +// VarType* vartype = NULL; +// +// list_iterator_start(&model_data->yList->out_list_ptr); +// while (list_iterator_hasnext(&model_data->yList->out_list_ptr)) { +// vartype_ptr = (VarTypePtr*)list_iterator_next(&model_data->yList->out_list_ptr); +// strcpy(str_array[count],vartype_ptr->name); +// count++; +// }; +// list_iterator_stop(&model_data->yList->out_list_ptr); +// +// list_iterator_start(&model_data->yList->out_list); +// while (list_iterator_hasnext(&model_data->yList->out_list)) { +// vartype = (VarType*)list_iterator_next(&model_data->yList->out_list); +// strcpy(str_array[count],vartype->name); +// count++; +// }; +// list_iterator_stop(&model_data->yList->out_list); +// /* @todo this should raise and error when count != n */ +// }; +// +// +// MAP_EXTERNCALL void get_unit_string(int* n, char** str_array, MAP_OtherStateType_t* other_type) +// { +// int count = 0; +// ModelData* model_data = other_type->object; +// VarTypePtr* vartype_ptr = NULL; +// VarType* vartype = NULL; +// +// list_iterator_start(&model_data->yList->out_list_ptr); +// while (list_iterator_hasnext(&model_data->yList->out_list_ptr)) { +// vartype_ptr = (VarTypePtr*)list_iterator_next(&model_data->yList->out_list_ptr ); +// strcpy(str_array[count],vartype_ptr->units); +// count++; +// }; +// list_iterator_stop(&model_data->yList->out_list_ptr); +// +// list_iterator_start(&model_data->yList->out_list); +// while (list_iterator_hasnext(&model_data->yList->out_list)) { +// vartype = (VarType*)list_iterator_next(&model_data->yList->out_list ); +// strcpy(str_array[count],vartype->units); +// count++; +// }; +// list_iterator_stop(&model_data->yList->out_list); +// }; +// /* @} */ +// +// +// ======= +// >>>>>>> next +MAP_ERROR_CODE get_iteration_output_stream(MAP_OutputType_t *y_type, MAP_OtherStateType_t* other_type, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int count = 0; + int i = 0; + Domain* domain = other_type->object; + VarTypePtr* vartype_ptr = NULL; + VarType* vartype = NULL; + + /* this should only be run once at initialization */ + if (!y_type->wrtOutput) { /* if NULL, then wrtOutput is not initialized */ + /* first set size of out list */ + y_type->wrtOutput_Len = (int)list_size(&domain->y_list->out_list_ptr); + y_type->wrtOutput_Len += (int)list_size(&domain->y_list->out_list); + + /* allocation of the array */ + y_type->wrtOutput = malloc(sizeof(double)*y_type->wrtOutput_Len); + }; + + list_iterator_start(&domain->y_list->out_list_ptr); + while (list_iterator_hasnext(&domain->y_list->out_list_ptr)) { + vartype_ptr = (VarTypePtr*)list_iterator_next(&domain->y_list->out_list_ptr); + y_type->wrtOutput[count] = *vartype_ptr->value; + count++; + }; + list_iterator_stop(&domain->y_list->out_list_ptr); + + list_iterator_start(&domain->y_list->out_list); + while (list_iterator_hasnext(&domain->y_list->out_list)) { + vartype = (VarType*)list_iterator_next(&domain->y_list->out_list); + y_type->wrtOutput[count] = vartype->value; + count++; + }; + list_iterator_stop(&domain->y_list->out_list); + + //printf("C :\n"); + for(i=0 ; i<count ; i++) { + // printf("%f , ",y_type->wrtOutput[i]); + //printf("%d %d\n",y_type->wrtOutput_Len,count); + }//printf("\n"); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_summary_file(InitializationData* init, MAP_ParameterType_t* paramType, Domain* data, char* map_msg, MAP_ERROR_CODE* ierr) +{ + MAP_ERROR_CODE success = MAP_SAFE; + FILE* file; + MAP_ERROR_CODE err = MAP_SAFE; + char time_buffer[TIME_BUFFER_SIZE] = "\0"; + time_t timer; + +# if !defined(_MSC_VER) + struct tm* tm_info; + time(&timer); + tm_info = localtime(&timer); + strftime(time_buffer, TIME_BUFFER_SIZE, "%A %B %d-%Y at %H:%M:%S %p", tm_info); +# else + struct tm tm_info; + time(&timer); + localtime_s(&tm_info, &timer); + strftime(time_buffer, TIME_BUFFER_SIZE, "%A %B %d-%Y at %H:%M:%S %p", &tm_info); +# endif + + err = fopen_s(&file, (char*)init->summary_file_name->data, "w"); + if (err!=MAP_SAFE) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_95, "File name: <%s>", init->summary_file_name->data); + return MAP_FATAL; + }; + + if (file==NULL) { + set_universal_error_with_message(map_msg, ierr, MAP_FATAL_38, "File name: <%s>", init->summary_file_name->data); + return MAP_FATAL; + }; + + //__get_machine_name(name); + + /* May want to retag version number of git between major/minor releases. A trick to include git revision number + * can be found archived here: http://stackoverflow.com/questions/1704907/how-can-i-get-my-c-code-to-automatically-print-out-its-git-version-hash + * + * $ git tag -a v1.00 -m "Release v1.00" + */ + + /* unboubtedly this will be useful on windows. Not sure how to track git version + * on windows with MSVC compiler, or for those who don't use version control? */ +# ifndef GITVERSION +# define GITVERSION PROGVERSION +# endif + + fprintf(file,"Outputs were generated using MAP++ %s.\n\n", GITVERSION); + fprintf(file," %s\n\n", time_buffer); + fprintf(file," Gravity constant [m/s^2] : %1.2f\n", paramType->g); + fprintf(file," Sea density [kg/m^3] : %1.2f\n", paramType->rho_sea); + fprintf(file," Water depth [m] : %1.2f\n", paramType->depth); + fprintf(file," Vessel reference position [m] : %1.2f , %1.2f , %1.2f\n\n", data->vessel.ref_origin.x.value, data->vessel.ref_origin.y.value, data->vessel.ref_origin.z.value); + + success = write_cable_library_information_to_summary_file(file, data); CHECKERRK(MAP_ERROR_6); + success = write_node_information_to_summary_file(file, data, map_msg, ierr); CHECKERRK(MAP_ERROR_7); + success = write_line_information_to_summary_file(file, data); CHECKERRK(MAP_ERROR_8); + success = write_expanded_input_file_to_summary_file(file, init); + fclose(file); + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE write_cable_library_information_to_summary_file(FILE* file, Domain* domain) +{ + CableLibrary* library_iter = NULL; + + list_iterator_start(&domain->library); + while (list_iterator_hasnext(&domain->library)) { + library_iter = (CableLibrary*)list_iterator_next(&domain->library); + fprintf(file, " Cable Type : %s\n", library_iter->label->data); + fprintf(file, " Diameter [m] : %1.4f\n", library_iter->diam); + fprintf(file, " Mass Density [kg/m] : %1.2f\n", library_iter->mass_density); + fprintf(file, " EA [N] : %1.2f\n", library_iter->EA); + fprintf(file, " omega [N/m] : %1.2f\n", library_iter->omega); + fprintf(file, " CB : %1.2f\n\n", library_iter->cb); + }; + list_iterator_stop(&domain->library); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_type_to_summary_file(const int num_col, const int count_to_four, const NodeType node_type, bstring line) +{ + int ret = 0; + int j = 0; + const int size = line->slen - 23*count_to_four; + + if (!num_col) { /* if this is the firs column, then line the right side with information */ + if (node_type==VESSEL) { + ret = bcatcstr(line, "Type | VESSEL"); + } else if (node_type==FIX ) { + ret = bcatcstr(line, "Type | FIX"); + } else if (node_type==CONNECT ) { + ret = bcatcstr(line, "Type | CONNECT"); + } else { + ret = bcatcstr(line, "Type | UNKNOWN"); + }; + } else { /* otherwise, just print the information */ + for (j=0 ; j<SPACE_LENGTH-size ; j++) { /* add white spaces */ + bconchar(line,' '); + }; + + if (node_type==VESSEL) { + ret = bcatcstr(line, " VESSEL"); + } else if (node_type==FIX ) { + ret = bcatcstr(line, " FIX"); + } else if(node_type==CONNECT ) { + ret = bcatcstr(line, " CONNECT"); + } else { + ret = bcatcstr(line, " UNKNOWN"); + }; + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_header_to_summary_file(const int num_col, const int count_to_four, const int node_num, bstring line) +{ + int ret = 0; + int j = 0; + const int size = line->slen - 23*count_to_four; + bstring info = NULL; + + if (!num_col) { + info = bformat(" | Node %d Data", node_num); + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + info = bformat("Node %d Data", node_num); + }; + ret = bconcat(line, info); + ret = bdestroy(info); + + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_x_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* x_pos, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + double x = *x_pos->value; + bstring info = NULL; + + if (!num_col) { + if (!x_pos->is_fixed) { + if (x>=0.0) { + info = bformat("X [m] | ( %1.3f)", x); + } else { + info = bformat("X [m] | (%1.3f)", x); + }; + } else { + if (x>0.0) { + info = bformat("X [m] | %1.3f", x); + } else { + info = bformat("X [m] | %1.3f", x); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!x_pos->is_fixed) { + if (x>=0.0) { + info = bformat("( %1.3f)", x); + } else { + info = bformat("(%1.3f)", x); + }; + } else { + if (x>=0.0) { + info = bformat(" %1.3f", x); + } else { + info = bformat(" %1.3f", x); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_y_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* y_pos, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + double y = *y_pos->value; + bstring info = NULL; + + if (!num_col) { + if (!y_pos->is_fixed) { + if (y>=0.0) { + info = bformat("Y [m] | ( %1.3f)", y); + } else { + info = bformat("Y [m] | (%1.3f)", y); + }; + } else { + if (y>0.0) { + info = bformat("Y [m] | %1.3f", y); + } else { + info = bformat("Y [m] | %1.3f", y); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!y_pos->is_fixed) { + if (y>=0.0) { + info = bformat("( %1.3f)", y); + } else { + info = bformat("(%1.3f)", y); + }; + } else { + if (y>=0.0) { + info = bformat(" %1.3f", y); + } else { + info = bformat(" %1.3f", y); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_z_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* z_pos, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + double z = *z_pos->value; + bstring info = NULL; + + if (!num_col) { + if (!z_pos->is_fixed) { + if (z>=0.0) { + info = bformat("Z [m] | ( %1.3f)", z); + } else { + info = bformat("Z [m] | (%1.3f)", z); + }; + } else { + if (z>0.0) { + info = bformat("Z [m] | %1.3f", z); + } else { + info = bformat("Z [m] | %1.3f", z); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!z_pos->is_fixed) { + if (z>=0.0) { + info = bformat("( %1.3f)", z); + } else { + info = bformat("(%1.3f)", z); + }; + } else { + if (z>=0.0) { + info = bformat(" %1.3f", z); + } else { + info = bformat(" %1.3f", z); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_mass_information_to_summary_file(const int num_col, const int count_to_four, VarType* point_mass, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + const double mass = point_mass->value; + bstring info = NULL; + + if (!num_col) { + if (!point_mass->is_fixed) { + if (mass>=0.0) { + info = bformat("M [kg] | ( %1.3f)", mass); + } else { + info = bformat("M [kg] | (%1.3f)", mass); + }; + } else { + if (mass>0.0) { + info = bformat("M [kg] | %1.3f", mass); + } else { + info = bformat("M [kg] | %1.3f", mass); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!point_mass->is_fixed) { + if (mass>=0.0) { + info = bformat("( %1.3f)", mass); + } else { + info = bformat("(%1.3f)", mass); + }; + } else { + if (mass>=0.0) { + info = bformat(" %1.3f", mass); + } else { + info = bformat(" %1.3f", mass); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_buoyancy_information_to_summary_file(const int num_col, const int count_to_four, VarType* point_buoy, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + const double buoy = point_buoy->value; + bstring info = NULL; + + if (!num_col) { + if (!point_buoy->is_fixed) { + if (buoy>=0.0) { + info = bformat("B [m^3] | ( %1.3f)", buoy); + } else { + info = bformat("B [m^3] | (%1.3f)", buoy); + }; + } else { + if (buoy>0.0) { + info = bformat("B [m^3] | %1.3f", buoy); + } else { + info = bformat("B [m^3] | %1.3f", buoy); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!point_buoy->is_fixed) { + if (buoy>=0.0) { + info = bformat("( %1.3f)", buoy); + } else { + info = bformat("(%1.3f)", buoy); + }; + } else { + if (buoy>=0.0) { + info = bformat(" %1.3f", buoy); + } else { + info = bformat(" %1.3f", buoy); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_x_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* x_sum_force, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + const double fx = *(x_sum_force->value); + bstring info = NULL; + + if (!num_col) { + if (!x_sum_force->is_fixed) { + if (fx>=0.0) { + info = bformat("FX [N] | ( %1.3f)", fx); + } else { + info = bformat("FX [N] | (%1.3f)", fx); + }; + } else { + if (fx>0.0) { + info = bformat("FX [N] | %1.3f", fx); + } else { + info = bformat("FX [N] | %1.3f", fx); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!x_sum_force->is_fixed) { + if (fx>=0.0) { + info = bformat("( %1.3f)", fx); + } else { + info = bformat("(%1.3f)", fx); + }; + } else { + if (fx>=0.0) { + info = bformat(" %1.3f", fx); + } else { + info = bformat(" %1.3f", fx); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_y_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* y_sum_force, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + const double fy = *(y_sum_force->value); + bstring info = NULL; + + if (!num_col) { + if (!y_sum_force->is_fixed) { + if (fy>=0.0) { + info = bformat("FY [N] | ( %1.3f)", fy); + } else { + info = bformat("FY [N] | (%1.3f)", fy); + }; + } else { + if (fy>0.0) { + info = bformat("FY [N] | %1.3f", fy); + } else { + info = bformat("FY [N] | %1.3f", fy); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!y_sum_force->is_fixed) { + if (fy>=0.0) { + info = bformat("( %1.3f)", fy); + } else { + info = bformat("(%1.3f)", fy); + }; + } else { + if (fy>=0.0) { + info = bformat(" %1.3f", fy); + } else { + info = bformat(" %1.3f", fy); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_z_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* z_sum_force, bstring line) +{ + int j = 0; + const int size = line->slen-23*count_to_four; /* each node column is 23 character wide */ + const double fz = *(z_sum_force->value); + bstring info = NULL; + + if (!num_col) { + if (!z_sum_force->is_fixed) { + if (fz>=0.0) { + info = bformat("FZ [N] | ( %1.3f)", fz); + } else { + info = bformat("FZ [N] | (%1.3f)", fz); + }; + } else { + if (fz>0.0) { + info = bformat("FZ [N] | %1.3f", fz); + } else { + info = bformat("FZ [N] | %1.3f", fz); + }; + }; + } else { + for (j=0 ; j<SPACE_LENGTH-size ; j++) { + bconchar(line,' '); + }; + + if (!z_sum_force->is_fixed) { + if (fz>=0.0) { + info = bformat("( %1.3f)", fz); + } else { + info = bformat("(%1.3f)", fz); + }; + } else { + if (fz>=0.0) { + info = bformat(" %1.3f", fz); + } else { + info = bformat(" %1.3f", fz); + }; + }; + }; + + bconcat(line, info); + bdestroy(info); + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_node_information_to_summary_file(FILE* file, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr) +{ + int num = 0; + unsigned int i = 0; + int col_cnt = 0; /* number of columns. The MAP summary file prints 4 columns of node information. After column 4, carriage return */ + + bstring line0 = NULL; + bstring line1 = NULL; + bstring line2 = NULL; + bstring line3 = NULL; + bstring line4 = NULL; + bstring line5 = NULL; + bstring line6 = NULL; + bstring line7 = NULL; + bstring line8 = NULL; + bstring line9 = NULL; + Node* node_iter = NULL; + const int FOUR = 4; + const unsigned int num_nodes = list_size(&domain->node); + unsigned int col = 0; + MAP_ERROR_CODE success = MAP_SAFE; + + MAP_BEGIN_ERROR_LOG; + + for (i=0 ; i<num_nodes ; i+=FOUR) { + if (i+FOUR>num_nodes) { + num = num_nodes-i; + } else { + num = FOUR; + }; + + line0 = bformat(""); + line1 = bformat(""); + line2 = bformat(""); + line3 = bformat(""); + line4 = bformat(""); + line5 = bformat(""); + line6 = bformat(""); + line7 = bformat(""); + line8 = bformat(""); + line9 = bformat(""); + + for (col=i ; col<i+num ; col++) { + node_iter = (Node*)list_get_at(&domain->node, col); + success = write_node_header_to_summary_file(col-i, col_cnt, col+1, line0); CHECKERRQ(MAP_FATAL_70); + success = write_node_type_to_summary_file(col-i, col_cnt, node_iter->type, line1); CHECKERRQ(MAP_FATAL_70); + success = write_node_x_position_to_summary_file(col-i, col_cnt, &node_iter->position_ptr.x, line2); CHECKERRQ(MAP_FATAL_70); + success = write_node_y_position_to_summary_file(col-i, col_cnt, &node_iter->position_ptr.y, line3); CHECKERRQ(MAP_FATAL_70); + success = write_node_z_position_to_summary_file(col-i, col_cnt, &node_iter->position_ptr.z, line4); CHECKERRQ(MAP_FATAL_70); + success = write_node_mass_information_to_summary_file(col-i, col_cnt, &node_iter->M_applied, line5); CHECKERRQ(MAP_FATAL_70); + success = write_node_buoyancy_information_to_summary_file(col-i, col_cnt, &node_iter->B_applied, line6); CHECKERRQ(MAP_FATAL_70); + success = write_node_x_sum_force_to_summary_file(col-i, col_cnt, &node_iter->sum_force_ptr.fx, line7); CHECKERRQ(MAP_FATAL_70); + success = write_node_y_sum_force_to_summary_file(col-i, col_cnt, &node_iter->sum_force_ptr.fy, line8); CHECKERRQ(MAP_FATAL_70); + success = write_node_z_sum_force_to_summary_file(col-i, col_cnt, &node_iter->sum_force_ptr.fz, line9); CHECKERRQ(MAP_FATAL_70); + col_cnt++; + }; + col_cnt = 0; + + fprintf(file, "%s\n",line0->data); + fprintf(file, " | -------------------------------------------------------------------------------------------\n"); + fprintf(file, "%s\n",line1->data); + fprintf(file, "%s\n",line2->data); + fprintf(file, "%s\n",line3->data); + fprintf(file, "%s\n",line4->data); + fprintf(file, "%s\n",line5->data); + fprintf(file, "%s\n",line6->data); + fprintf(file, "%s\n",line7->data); + fprintf(file, "%s\n",line8->data); + fprintf(file, "%s\n\n\n",line9->data); + + bdestroy(line0); + bdestroy(line1); + bdestroy(line2); + bdestroy(line3); + bdestroy(line4); + bdestroy(line5); + bdestroy(line6); + bdestroy(line7); + bdestroy(line8); + bdestroy(line9); + }; + + MAP_END_ERROR_LOG; + + MAP_RETURN_STATUS(*ierr); +}; + + +MAP_ERROR_CODE write_line_information_to_summary_file(FILE* file, Domain* domain) +{ + const unsigned int num_lines = list_size(&domain->line); + Line* line_iter = NULL; + bstring line0 = NULL; + bstring line1 = NULL; + bstring line2 = NULL; + bstring line3 = NULL; + bstring line4 = NULL; + bstring line5 = NULL; + bstring line6 = NULL; + bstring line7 = NULL; + bstring line8 = NULL; + bstring line9 = NULL; + bstring line10 = NULL; + unsigned int i = 0; + + for (i=0 ; i<num_lines ; i++) { + line_iter = (Line*)list_get_at(&domain->line, i); + + line0 = bformat(""); + line1 = bformat(""); + line2 = bformat(""); + line3 = bformat(""); + line4 = bformat(""); + line5 = bformat(""); + line6 = bformat(""); + line7 = bformat(""); + line8 = bformat(""); + line9 = bformat(""); + + if (line_iter->Lu.value>0.0) { + bconchar(line0,' '); + }; + if (line_iter->Lb>0.0) { + bconchar(line1,' '); + }; + if (*(line_iter->H.value)>0.0) { + bconchar(line2,' '); + }; + if (*(line_iter->V.value)>0.0) { + bconchar(line3,' '); + }; + if (line_iter->T>0.0) { + bconchar(line4,' '); + }; + if (line_iter->alpha>0.0) { + bconchar(line5,' '); + }; + if (line_iter->H_at_anchor>0.0) { + bconchar(line6,' '); + }; + if (line_iter->V_at_anchor>0.0) { + bconchar(line7,' '); + }; + if (line_iter->T_at_anchor>0.0) { + bconchar(line8,' '); + }; + if (line_iter->alpha_at_anchor>0.0) { + bconchar(line9,' '); + }; + + switch (line_iter->converge_reason) { + case 0 : + line10 = bformat("Improver input parameter for inner loop solver."); + break; + case 1 : + line10 = bformat("SQRT( H^2 + V^2 ) <= INNER_FTOL."); + break; + case 2 : + line10 = bformat("||x_i - x_{i-1}|| <= INNER_XTOL."); + break; + case 3 : + line10 = bformat("Both SQRT( H^2 + V^2 )<=INNER_FTOL and ||x_i - x_{i-1}|| <= INNER_XTOL."); + break; + case 4 : + line10 = bformat("The cosine of the angle between [H, V] and any column of the Jacobian is at most INNER_GTOL in absolute value."); + break; + case 5 : + line10 = bformat("INNER_MAX_ITS reached. Try increasing the maximum allowable iteration count."); + break; + case 6 : + line10 = bformat("INNER_FTOL si too small. SQRT( H^2 + V^2 ) cannot be reduced further."); + break; + case 7 : + line10 = bformat("INNER_XTOL is too small. No further refinements can be made in [H, V]."); + break; + case 8 : + line10 = bformat("INNER_GTOL is too small. The iterated variable vector [H, V] is orthogonal to the Jacobian columns."); + break; + default : + line10 = bformat("Uncaught error."); + break; + }; + + fprintf(file, " | Line %d\n", i+1); + fprintf(file, " | ---------------------------------------\n"); + fprintf(file, "Material | %s\n", line_iter->line_property->label->data); + fprintf(file, "Lu [m] | %s%1.3f\n", line0->data, line_iter->Lu.value); + fprintf(file, "Lb [m] | %s%1.3f\n", line1->data, line_iter->Lb); + fprintf(file, "H [N] | %s%1.3f\n", line2->data, *(line_iter->H.value)); + fprintf(file, "V [N] | %s%1.3f\n", line3->data, *(line_iter->V.value)); + fprintf(file, "T [N] | %s%1.3f\n", line4->data, line_iter->T); + fprintf(file, "Alpha [deg] | %s%1.3f\n", line5->data, line_iter->alpha*RAD2DEG); + fprintf(file, "HAnch [N] | %s%1.3f\n", line6->data, line_iter->H_at_anchor); + fprintf(file, "VAnch [N] | %s%1.3f\n", line7->data, line_iter->V_at_anchor); + fprintf(file, "TAnch [N] | %s%1.3f\n", line8->data, line_iter->T_at_anchor); + fprintf(file, "AlphaAnch [deg] | %s%1.3f\n", line9->data, line_iter->alpha_at_anchor*RAD2DEG); + fprintf(file, "L^2-Norm | %1.7g\n", line_iter->residual_norm); + fprintf(file, "Function Evals | %d\n", line_iter->evals); + fprintf(file, "Jacobian Evals | %d\n", line_iter->njac_evals); + fprintf(file, "Term. criteria | %d : %s\n", line_iter->converge_reason, line10->data); + fprintf(file, "\n\n"); + + bdestroy(line0); + bdestroy(line1); + bdestroy(line2); + bdestroy(line3); + bdestroy(line4); + bdestroy(line5); + bdestroy(line6); + bdestroy(line7); + bdestroy(line8); + bdestroy(line9); + bdestroy(line10); + }; + return MAP_SAFE; +}; + + +MAP_ERROR_CODE write_expanded_input_file_to_summary_file(FILE* file, InitializationData* init_data) +{ + const char* line = NULL; + int len = 0; + int i = 0; + + fprintf(file, "---------------------- LINE DICTIONARY ---------------------------------------\n"); + fprintf(file, "LineType Diam MassDenInAir EA CB\n"); + fprintf(file, "[-] [m] [kg/m] [N] [-]\n"); + for (i=0 ; i<init_data->library_input_string->qty ; i++) { + line = (char*)init_data->library_input_string->entry[i]->data; + len = init_data->library_input_string->entry[i]->slen; + fprintf(file, "%s", line); + if (line[len-1]!='\n') { + fprintf(file, "\n" ); + }; + }; + + fprintf(file, "---------------------- NODE PROPERTIES ---------------------------------------\n"); + fprintf(file, "Node Type X Y Z M B FX FY FZ\n"); + fprintf(file, "[-] [-] [m] [m] [m] [kg] [mˆ3] [N] [N] [N]\n"); + for (i=0 ; i<init_data->expanded_node_input_string->qty ; i++) { + line = (char*)init_data->expanded_node_input_string->entry[i]->data; + len = init_data->expanded_node_input_string->entry[i]->slen; + fprintf(file, "%s", line); + if (line[len-1]!='\n') { + fprintf(file, "\n" ); + }; + }; + + fprintf(file, "---------------------- LINE PROPERTIES ---------------------------------------\n"); + fprintf(file, "Line LineType UnstrLen NodeAnch NodeFair Flags\n"); + fprintf(file, "[-] [-] [m] [-] [-] [-]\n"); + for (i=0 ; i<init_data->expanded_line_input_string->qty ; i++) { + line = (char*)init_data->expanded_line_input_string->entry[i]->data; + len = init_data->expanded_line_input_string->entry[i]->slen; + fprintf(file, "%s", line); + if (line[len-1]!='\n') { + fprintf(file, "\n" ); + }; + }; + + fprintf(file, "---------------------- SOLVER OPTIONS-----------------------------------------\n"); + fprintf(file, "Option \n"); + fprintf(file, "[-] \n"); + for (i=0 ; i<init_data->solver_options_string->qty ; i++) { + line = (char*)init_data->solver_options_string->entry[i]->data; + len = init_data->solver_options_string->entry[i]->slen; + fprintf(file, "%s", line); + if (line[len-1]!='\n') { + fprintf(file, "\n" ); + }; + }; + return MAP_SAFE; +}; + + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +MAP_ERROR_CODE fopen_s(FILE** f, const char* name, const char* mode) +{ + assert(f); + *f = fopen(name, mode); + if (!*f) { + return MAP_FATAL; + } + return MAP_SAFE; +}; +#endif diff --git a/OpenFAST/modules/map/src/outputstream.h b/OpenFAST/modules/map/src/outputstream.h new file mode 100644 index 000000000..8ef94a846 --- /dev/null +++ b/OpenFAST/modules/map/src/outputstream.h @@ -0,0 +1,264 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _OUTPUT_STREAM_H +#define _OUTPUT_STREAM_H + + +#include <time.h> +#include "mapsys.h" +#include "map.h" +#include "maperror.h" +#include "MAP_Types.h" + + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +MAP_ERROR_CODE fopen_s(FILE** f, const char* name, const char* mode); +#endif + + +/** + * @brief + * @param y_type output type, native C struct {@link MAP_OutputType_t} + * @param other_type other state type, native C struct {@link MAP_OtherStateType_t} + * @param map_msg error message + * @param ierr error code + */ +MAP_ERROR_CODE get_iteration_output_stream(MAP_OutputType_t *y_type, MAP_OtherStateType_t* other_type, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief + * @param init_data MAP internal initialization data structure + * @param param_type parmeter type, native C struct {@link MAP_ParameterType_t} + * @param domain internal state data {@link Domain} + * @param map_msg error message + * @param ierr error code + */ +MAP_ERROR_CODE write_summary_file(InitializationData* init_data, MAP_ParameterType_t* param_type, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + + +/** + * @brief Writes all cable properties defined in the MAP input file: + * <pre> + * Cable Type : {value} + * Diameter [m] : {value} + * Mass Density [kg/m] : {value} + * EA [N] : {value} + * omega [N/m] : {value} + * CB : {value} + * </pre> + * @param file file where string is being dumped to + * @param domain internal state data {@link Domain} + * @todo include new properties for the LM model + */ +MAP_ERROR_CODE write_cable_library_information_to_summary_file(FILE* file, Domain* domain); + + +/** + * @brief writes the node type. Can be VESSEL, CONNECT, or FIX + * <pre> + * Type | {VESSEL} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param node_type identifies the node type as a NONE, CONNECT, FIX, or VESSEL + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_type_to_summary_file(const int num_col, const int count_to_four, const NodeType node_type, bstring line); + + +/** + * @brief header for the node block. Prints the node number. + * <pre> + * | Node {number} Data" + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param node_num + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_header_to_summary_file(const int num_col, const int count_to_four, const int node_num, bstring line); + + +/** + * @brief writes the node x global displacement (position) to the node output block. Units are in [m]: + * <pre> + * X [m] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param x_pos node global x position [m] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_x_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* x_pos, bstring line); + + +/** + * @brief writes the node y global displacement (position) to the node output block. Units are in [m]: + * <pre> + * Y [m] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param y_pos node global y position [m] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_y_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* y_pos, bstring line); + + +/** + * @brief writes the node z global displacement (position) to the node output block. Units are in [m]: + * <pre> + * Z [m] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param z_pos node global z position [m] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_z_position_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* z_pos, bstring line); + +/** + * @brief writes the node point mass value to the output block. Units are in [kg]: + * <pre> + * M [kg] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param point_mass node point mass [kg] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_mass_information_to_summary_file(const int num_col, const int count_to_four, VarType* point_mass, bstring line); + + +/** + * @brief writes the volumetric displacement of the buoyancy module to the node output block. Units are in [m^3]: + * <pre> + * B [m^3] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param point_buoyancy node point buoyancy [m^3] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_buoyancy_information_to_summary_file(const int num_col, const int count_to_four, VarType* point_buoy, bstring line); + + +/** + * @brief writes the x-direction sum force to the node output block. Units are in [N]: + * <pre> + * FX [N] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param x_sum_force node global x sum force (including external forces) [N] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_x_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* x_sum_force, bstring line); + + +/** + * @brief writes the y-direction sum force to the node output block. Units are in [N]: + * <pre> + * FY [N] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param y_sum_force node global y sum force (including external forces) [N] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_y_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* y_sum_force, bstring line); + + +/** + * @brief writes the z-direction sum force to the node output block. Units are in [N]: + * <pre> + * FZ [N] | {value} + * </pre> + * @param num_col column number, can be 1, 2, 3, or 4 + * @param count_to_four number of columns currently printed in the node output block + * @param z_sum_force node global z sum force (including external forces) [N] + * @param line_char output string terminated with '\n' + */ +MAP_ERROR_CODE write_node_z_sum_force_to_summary_file(const int num_col, const int count_to_four, VarTypePtr* z_sum_force, bstring line); + + +/** + * @brief write the complete node block to the summary file + * <pre> + * | Node 1 Data Node 2 Data Node 3 Data Node 4 Data + * | ------------------------------------------------------------------------------------------- + * Type | FIX CONNECT VESSEL FIX + * X [m] | 0.000 0.000 0.000 0.000 + * Y [m] | 0.000 0.000 0.000 0.000 + * Z [m] | 0.000 0.000 0.000 0.000 + * M [kg] | 0.000 0.000 0.000 0.000 + * B [m^3] | 0.000 0.000 0.000 0.000 + * FX [N] | 0.000 0.000 0.000 0.000 + * FY [N] | 0.000 0.000 0.000 0.000 + * FZ [N] | 0.000 0.000 0.000 0.000 + * </pre> + * @param file file where string is being dumped to + * @param domain internal state data {@link Domain} + * @param map_msg error message + * @param ierr error code + */ +MAP_ERROR_CODE write_node_information_to_summary_file(FILE* file, Domain* domain, char* map_msg, MAP_ERROR_CODE* ierr); + +/** + * @brief write the complete line block to the summary file + * <pre> + * | Line 1 + * | --------------------------------------- + * Material | Material + * Lu [m] | 0.000 + * Lb [m] | 0.000 + * H [N] | 0.000 + * V [N] | 0.000 + * T [N] | 0.000 + * Alpha [deg] | 0.000 + * HAnch [N] | 0.000 + * VAnch [N] | 0.000 + * TAnch [N] | 0.000 + * AlphaAnch [deg] | 0.000 + * L^2-Norm | 0.000 + * Function Evals | 0 + * Jacobian Evals | 0 + * Term. criteria | 0 + * </pre> + * @param file file where string is being dumped to + * @param domain internal state data {@link Domain} + */ +MAP_ERROR_CODE write_line_information_to_summary_file(FILE* file, Domain* domain); + +/** + * @brief prints the expanded MAP input file. This can be used as a check to make sure the repeat flags + * are correctly interpreted. + * @param file file where string is being dumped to + * @param init_data initialization output type, native C struct {@link MAP_InitOutputType_t} + */ +MAP_ERROR_CODE write_expanded_input_file_to_summary_file(FILE* file, InitializationData* init_data); + + +#endif // _OUTPUT_STREAM_H diff --git a/OpenFAST/modules/map/src/residual.c b/OpenFAST/modules/map/src/residual.c new file mode 100644 index 000000000..e7d861913 --- /dev/null +++ b/OpenFAST/modules/map/src/residual.c @@ -0,0 +1,58 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#include "residual.h" + + +double residual_function_length_no_contact(const double V, const double H, const double w, const double Lu, const double EA, const double l) +{ + return (H/w)*ARCSINH(V/H) - (H/w)*ARCSINH( (V-w*Lu)/H ) + ((H*Lu)/(EA)) - l; +}; + + +double residual_function_height_no_contact(const double V, const double H, const double w, const double Lu, const double EA, const double h) +{ + return (H/w)* sqrt(1 + pow((V/H), 2)) - (H/w)*sqrt(1 + pow(((V-w*Lu)/H), 2)) + 1/(EA)*(V*Lu - (w*Lu*Lu)/2) - h; +}; + + +double residual_function_length_contact(const double V, const double H, const double w, const double Lu, const double EA, const double l, const double cb) +{ + /* Note that Lb = Lu - V/w */ + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return log((V/H) + sqrt(1.0 + pow(V/H,2)))*(H/w) - 0.5*(cb/EA)*w*(Lu-V/w)*(Lu-V/w) + (Lu/EA)*H + (Lu-V/w) - l; + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return log((V/H) + sqrt(1.0 + pow(V/H,2)))*(H/w) - 0.5*(cb/EA)*w*((Lu-V/w)*(Lu-V/w) - ((Lu-V/w) - (H/w)/cb)*((Lu-V/w) - (H/w)/cb)) + (Lu/EA)*H + (Lu-V/w) - l; + }; +}; + + +double residual_function_height_contact(const double V, const double H, const double w, const double Lu, const double EA, const double h, const double cb) +{ + // @todo remove this conditional statement because the equations are the same regardless of the outcome + if (-cb*(V-w*Lu)<H) { /* true when a portion of the line rests on the seabed and the anchor tension is nonzero */ + return (sqrt(1.0 + pow(V/H,2)) - 1.0)*(H/w) + 0.5*V*(V/(w*EA)) - h; + } else { /* 0.0<H<=-CB*(V-w*Lu), A portion of the line must rest on the seabed and the anchor tension is zero */ + return (sqrt(1.0 + pow(V/H,2)) - 1.0)*(H/w) + 0.5*V*(V/(w*EA)) - h; + }; +}; diff --git a/OpenFAST/modules/map/src/residual.h b/OpenFAST/modules/map/src/residual.h new file mode 100644 index 000000000..7633c3a38 --- /dev/null +++ b/OpenFAST/modules/map/src/residual.h @@ -0,0 +1,36 @@ +/**************************************************************** + * Copyright (C) 2014 mdm * + * map[dot]plus[dot]plus[dot]help[at]gmail * + * * + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + + +#ifndef _RESIDUAL_H +#define _RESIDUAL_H + +#include "map.h" + + +double residual_function_length_no_contact(const double V, const double H, const double w, const double Lu, const double EA, const double l); +double residual_function_height_no_contact(const double V, const double H, const double w, const double Lu, const double EA, const double h); +double residual_function_length_contact(const double V, const double H, const double w, const double Lu, const double EA, const double l, const double cb); +double residual_function_height_contact(const double V, const double H, const double w, const double Lu, const double EA, const double h, const double cb); + + +#endif // _RESIDUAL_H diff --git a/OpenFAST/modules/map/src/simclist/simclist.c b/OpenFAST/modules/map/src/simclist/simclist.c new file mode 100644 index 000000000..8bf1d8d1d --- /dev/null +++ b/OpenFAST/modules/map/src/simclist/simclist.c @@ -0,0 +1,1498 @@ +/* + * Copyright (c) 2007,2008,2009,2010 Mij <mij@bitchx.it> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * SimCList library. See http://mij.oltrelinux.com/devel/simclist + */ + +/* SimCList implementation, version 1.5, with local modifications */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> /* for setting errno */ +#include <sys/types.h> +#if !defined(_WIN32) +#include <arpa/inet.h> /* for htons() */ +#include <unistd.h> +#include <sys/time.h> /* for gettimeofday() */ +#include <stdint.h> +#else +#include <winsock2.h> +#endif +#ifdef SIMCLIST_DUMPRESTORE +#ifndef _WIN32 +#include <sys/uio.h> /* for READ_ERRCHECK() and write() */ +#endif +#include <fcntl.h> /* for open() etc */ +#endif +#include <time.h> /* for time() for random seed */ +#include <sys/stat.h> /* for open()'s access modes S_IRUSR etc */ +#include <limits.h> + + +#ifdef SIMCLIST_DUMPRESTORE +/* convert 64bit integers from host to network format */ +#define hton64(x) (\ + htons(1) == 1 ? \ + (uint64_t)x /* big endian */ \ + : /* little endian */ \ + ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ + (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ + (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ + (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) \ + ) + +/* convert 64bit integers from network to host format */ +#define ntoh64(x) (hton64(x)) +#endif + +/* some OSes don't have EPROTO (eg OpenBSD) */ +#ifndef EPROTO +#define EPROTO EIO +#endif + +/* disable asserts */ +#ifndef SIMCLIST_DEBUG +#ifndef NDEBUG +#define NDEBUG +#endif +#endif + +#include <assert.h> + +#ifdef SIMCLIST_WITH_THREADS +/* limit (approx) to the number of threads running + * for threaded operations. Only meant when + * SIMCLIST_WITH_THREADS is defined */ +#define SIMCLIST_MAXTHREADS 2 +#endif + +/* + * how many elems to keep as spare. During a deletion, an element + * can be saved in a "free-list", not free()d immediately. When + * latter insertions are performed, spare elems can be used instead + * of malloc()ing new elems. + * + * about this param, some values for appending + * 10 million elems into an empty list: + * (#, time[sec], gain[%], gain/no[%]) + * 0 2,164 0,00 0,00 <-- feature disabled + * 1 1,815 34,9 34,9 + * 2 1,446 71,8 35,9 <-- MAX gain/no + * 3 1,347 81,7 27,23 + * 5 1,213 95,1 19,02 + * 8 1,064 110,0 13,75 + * 10 1,015 114,9 11,49 <-- MAX gain w/ likely sol + * 15 1,019 114,5 7,63 + * 25 0,985 117,9 4,72 + * 50 1,088 107,6 2,15 + * 75 1,016 114,8 1,53 + * 100 0,988 117,6 1,18 + * 150 1,022 114,2 0,76 + * 200 0,939 122,5 0,61 <-- MIN time + */ +#ifndef SIMCLIST_MAX_SPARE_ELEMS +#define SIMCLIST_MAX_SPARE_ELEMS 5 +#endif + + +#ifdef SIMCLIST_WITH_THREADS +#include <pthread.h> +#endif + +#include "simclist.h" + + +/* minumum number of elements for sorting with quicksort instead of insertion */ +#define SIMCLIST_MINQUICKSORTELS 24 + + +/* list dump declarations */ +#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */ + +#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */ + +/* header for a list dump */ +struct list_dump_header_s { + uint16_t ver; /* version */ + int64_t timestamp; /* dump timestamp */ + int32_t rndterm; /* random value terminator -- terminates the data sequence */ + + uint32_t totlistlen; /* sum of every element' size, bytes */ + uint32_t numels; /* number of elements */ + uint32_t elemlen; /* bytes length of an element, for constant-size lists, <= 0 otherwise */ + int32_t listhash; /* hash of the list at the time of dumping, or 0 if to be ignored */ +}; + + + +/* deletes tmp from list, with care wrt its position (head, tail, middle) */ +static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos); + +/* set default values for initialized lists */ +static int list_attributes_setdefaults(list_t *restrict l); + +#ifndef NDEBUG +/* check whether the list internal REPresentation is valid -- Costs O(n) */ +static int list_repOk(const list_t *restrict l); + +/* check whether the list attribute set is valid -- Costs O(1) */ +static int list_attrOk(const list_t *restrict l); +#endif + +/* do not inline, this is recursive */ +static void list_sort_quicksort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel); + +static inline void list_sort_selectionsort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel); + +static void *list_get_minmax(const list_t *restrict l, int versus); + +static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart); + +#ifdef SIMCLIST_DUMPRESTORE +/* write() decorated with error checking logic */ +#define WRITE_ERRCHECK(fd, msgbuf, msglen) do { \ + if (write(fd, msgbuf, msglen) < 0) return -1; \ + } while (0); +/* READ_ERRCHECK() decorated with error checking logic */ +#define READ_ERRCHECK(fd, msgbuf, msglen) do { \ + if (read(fd, msgbuf, msglen) != msglen) { \ + /*errno = EPROTO;*/ \ + free(buf); \ + return -1; \ + } \ + } while (0); +#endif + +/* + * Random Number Generator + * + * The user is expected to seed the RNG (ie call srand()) if + * SIMCLIST_SYSTEM_RNG is defined. + * + * Otherwise, a self-contained RNG based on LCG is used; see + * http://en.wikipedia.org/wiki/Linear_congruential_generator . + * + * Facts pro local RNG: + * 1. no need for the user to call srand() on his own + * 2. very fast, possibly faster than OS + * 3. avoid interference with user's RNG + * + * Facts pro system RNG: + * 1. may be more accurate (irrelevant for SimCList randno purposes) + * 2. why reinvent the wheel + * + * Default to local RNG for user's ease of use. + */ + +#ifdef SIMCLIST_SYSTEM_RNG +/* keep track whether we initialized already (non-0) or not (0) */ +static unsigned random_seed = 0; + +/* use local RNG */ +static inline void seed_random() { + if (random_seed == 0) + random_seed = (unsigned)getpid() ^ (unsigned)time(NULL); +} + +static inline long get_random() { + random_seed = (1664525 * random_seed + 1013904223); + return random_seed; +} + +#else +/* use OS's random generator */ +# define seed_random() +# define get_random() (rand()) +#endif + + +/* list initialization */ +int list_init(list_t *restrict l) { + if (l == NULL) return -1; + + seed_random(); + + l->numels = 0; + + /* head/tail sentinels and mid pointer */ + l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL; + l->head_sentinel->data = l->tail_sentinel->data = NULL; + + /* iteration attributes */ + l->iter_active = 0; + l->iter_pos = 0; + l->iter_curentry = NULL; + + /* free-list attributes */ + l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *)); + l->spareelsnum = 0; + +#ifdef SIMCLIST_WITH_THREADS + l->threadcount = 0; +#endif + + list_attributes_setdefaults(l); + + assert(list_repOk(l)); + assert(list_attrOk(l)); + + return 0; +} + +void list_destroy(list_t *restrict l) { + unsigned int i; + + list_clear(l); + for (i = 0; i < l->spareelsnum; i++) { + free(l->spareels[i]); + } + free(l->spareels); + free(l->head_sentinel); + free(l->tail_sentinel); +} + +int list_attributes_setdefaults(list_t *restrict l) { + l->attrs.comparator = NULL; + l->attrs.seeker = NULL; + + /* also free() element data when removing and element from the list */ + l->attrs.meter = NULL; + l->attrs.copy_data = 0; + + l->attrs.hasher = NULL; + + /* serializer/unserializer */ + l->attrs.serializer = NULL; + l->attrs.unserializer = NULL; + + assert(list_attrOk(l)); + + return 0; +} + +/* setting list properties */ +int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun) { + if (l == NULL) return -1; + + l->attrs.comparator = comparator_fun; + + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun) { + if (l == NULL) return -1; + + l->attrs.seeker = seeker_fun; + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data) { + if (l == NULL || (metric_fun == NULL && copy_data != 0)) return -1; + + l->attrs.meter = metric_fun; + l->attrs.copy_data = copy_data; + + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun) { + if (l == NULL) return -1; + + l->attrs.hasher = hash_computer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun) { + if (l == NULL) return -1; + + l->attrs.serializer = serializer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun) { + if (l == NULL) return -1; + + l->attrs.unserializer = unserializer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_append(list_t *restrict l, const void *data) { + return list_insert_at(l, data, l->numels); +} + +int list_prepend(list_t *restrict l, const void *data) { + return list_insert_at(l, data, 0); +} + +void *list_fetch(list_t *restrict l) { + return list_extract_at(l, 0); +} + +void *list_get_at(const list_t *restrict l, unsigned int pos) { + struct list_entry_s *tmp; + + tmp = list_findpos(l, pos); + + return (tmp != NULL ? tmp->data : NULL); +} + +void *list_get_max(const list_t *restrict l) { + return list_get_minmax(l, +1); +} + +void *list_get_min(const list_t *restrict l) { + return list_get_minmax(l, -1); +} + +/* REQUIRES {list->numels >= 1} + * return the min (versus < 0) or max value (v > 0) in l */ +static void *list_get_minmax(const list_t *restrict l, int versus) { + void *curminmax; + struct list_entry_s *s; + + if (l->attrs.comparator == NULL || l->numels == 0) + return NULL; + + curminmax = l->head_sentinel->next->data; + for (s = l->head_sentinel->next->next; s != l->tail_sentinel; s = s->next) { + if (l->attrs.comparator(curminmax, s->data) * versus > 0) + curminmax = s->data; + } + + return curminmax; +} + +/* set tmp to point to element at index posstart in l */ +static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) { + struct list_entry_s *ptr; + float x; + int i; + + /* accept 1 slot overflow for fetching head and tail sentinels */ + if (posstart < -1 || posstart > (int)l->numels) return NULL; + + if (l->numels == 0){ //avoid division-by-zero on first element + ptr = l->head_sentinel; + } + else{ + x = (float)(posstart + 1) / l->numels; + if (x <= 0.25) { + /* first quarter: get to posstart from head */ + for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++); + } + else if (x < 0.5) { + /* second quarter: get to posstart from mid */ + for (i = (l->numels - 1) / 2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--); + } + else if (x <= 0.75) { + /* third quarter: get to posstart from mid */ + for (i = (l->numels - 1) / 2, ptr = l->mid; i < posstart; ptr = ptr->next, i++); + } + else { + /* fourth quarter: get to posstart from tail */ + for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--); + } + } + return ptr; +} + +void *list_extract_at(list_t *restrict l, unsigned int pos) { + struct list_entry_s *tmp; + void *data; + + if (l->iter_active || pos >= l->numels) return NULL; + + tmp = list_findpos(l, pos); + data = tmp->data; + + tmp->data = NULL; /* save data from list_drop_elem() free() */ + list_drop_elem(l, tmp, pos); + l->numels--; + + assert(list_repOk(l)); + + return data; +} + +int list_insert_at(list_t *restrict l, const void *data, unsigned int pos) { + struct list_entry_s *lent, *succ, *prec; + + if (l->iter_active || pos > l->numels) return -1; + + /* this code optimizes malloc() with a free-list */ + if (l->spareelsnum > 0) { + lent = l->spareels[l->spareelsnum-1]; + l->spareelsnum--; + } else { + lent = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + if (lent == NULL) + return -1; + } + + if (l->attrs.copy_data) { + /* make room for user' data (has to be copied) */ + size_t datalen = l->attrs.meter(data); + lent->data = (struct list_entry_s *)malloc(datalen); + memcpy(lent->data, data, datalen); + } else { + lent->data = (void*)data; + } + + /* actually append element */ + prec = list_findpos(l, pos-1); + succ = prec->next; + + prec->next = lent; + lent->prev = prec; + lent->next = succ; + succ->prev = lent; + + l->numels++; + + /* fix mid pointer */ + if (l->numels == 1) { /* first element, set pointer */ + l->mid = lent; + } else if (l->numels % 2) { /* now odd */ + if (pos >= (l->numels-1)/2) l->mid = l->mid->next; + } else { /* now even */ + if (pos <= (l->numels-1)/2) l->mid = l->mid->prev; + } + + assert(list_repOk(l)); + + return 1; +} + +int list_delete(list_t *restrict l, const void *data) { + int pos, r; + + pos = list_locate(l, data); + if (pos < 0) + return -1; + + r = list_delete_at(l, pos); + if (r < 0) + return -1; + + assert(list_repOk(l)); + + return 0; +} + +int list_delete_at(list_t *restrict l, unsigned int pos) { + struct list_entry_s *delendo; + + + if (l->iter_active || pos >= l->numels) return -1; + + delendo = list_findpos(l, pos); + + list_drop_elem(l, delendo, pos); + + l->numels--; + + + assert(list_repOk(l)); + + return 0; +} + +int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend) { + struct list_entry_s *lastvalid, *tmp, *tmp2; + unsigned int i; + int movedx; + unsigned int numdel, midposafter; + + if (l->iter_active || posend < posstart || posend >= l->numels) return -1; + + tmp = list_findpos(l, posstart); /* first el to be deleted */ + lastvalid = tmp->prev; /* last valid element */ + + numdel = posend - posstart + 1; + midposafter = (l->numels-1-numdel)/2; + + midposafter = midposafter < posstart ? midposafter : midposafter+numdel; + movedx = midposafter - (l->numels-1)/2; + + if (movedx > 0) { /* move right */ + for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->next, i++); + } else { /* move left */ + movedx = -movedx; + for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->prev, i++); + } + + assert(posstart == 0 || lastvalid != l->head_sentinel); + i = posstart; + if (l->attrs.copy_data) { + /* also free element data */ + for (; i <= posend; i++) { + tmp2 = tmp; + tmp = tmp->next; + if (tmp2->data != NULL) free(tmp2->data); + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp2; + } else { + free(tmp2); + } + } + } else { + /* only free containers */ + for (; i <= posend; i++) { + tmp2 = tmp; + tmp = tmp->next; + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp2; + } else { + free(tmp2); + } + } + } + assert(i == posend+1 && (posend != l->numels || tmp == l->tail_sentinel)); + + lastvalid->next = tmp; + tmp->prev = lastvalid; + + l->numels -= posend - posstart + 1; + + assert(list_repOk(l)); + + return 0; +} + +int list_clear(list_t *restrict l) { + struct list_entry_s *s; + + if (l->iter_active) return -1; + + if (l->attrs.copy_data) { /* also free user data */ + /* spare a loop conditional with two loops: spareing elems and freeing elems */ + for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { + /* move elements as spares as long as there is room */ + if (s->data != NULL) free(s->data); + l->spareels[l->spareelsnum++] = s; + } + while (s != l->tail_sentinel) { + /* free the remaining elems */ + if (s->data != NULL) free(s->data); + s = s->next; + free(s->prev); + } + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + } else { /* only free element containers */ + /* spare a loop conditional with two loops: spareing elems and freeing elems */ + for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { + /* move elements as spares as long as there is room */ + l->spareels[l->spareelsnum++] = s; + } + while (s != l->tail_sentinel) { + /* free the remaining elems */ + s = s->next; + free(s->prev); + } + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + } + l->numels = 0; + l->mid = NULL; + + assert(list_repOk(l)); + + return 0; +} + +unsigned int list_size(const list_t *restrict l) { + return l->numels; +} + +int list_empty(const list_t *restrict l) { + return (l->numels == 0); +} + +int list_locate(const list_t *restrict l, const void *data) { + struct list_entry_s *el; + int pos = 0; + + if (l->attrs.comparator != NULL) { + /* use comparator */ + for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { + if (l->attrs.comparator(data, el->data) == 0) break; + } + } else { + /* compare references */ + for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { + if (el->data == data) break; + } + } + if (el == l->tail_sentinel) return -1; + + return pos; +} + +void *list_seek(list_t *restrict l, const void *indicator) { + const struct list_entry_s *iter; + + if (l->attrs.seeker == NULL) return NULL; + + for (iter = l->head_sentinel->next; iter != l->tail_sentinel; iter = iter->next) { + if (l->attrs.seeker(iter->data, indicator) != 0) return iter->data; + } + + return NULL; +} + +int list_contains(const list_t *restrict l, const void *data) { + return (list_locate(l, data) >= 0); +} + +int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest) { + struct list_entry_s *el, *srcel; + unsigned int cnt; + int err; + + + if (l1 == NULL || l2 == NULL || dest == NULL || l1 == dest || l2 == dest) + return -1; + + list_init(dest); + + dest->numels = l1->numels + l2->numels; + if (dest->numels == 0) + return 0; + + /* copy list1 */ + srcel = l1->head_sentinel->next; + el = dest->head_sentinel; + while (srcel != l1->tail_sentinel) { + el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + el->next->prev = el; + el = el->next; + el->data = srcel->data; + srcel = srcel->next; + } + dest->mid = el; /* approximate position (adjust later) */ + /* copy list 2 */ + srcel = l2->head_sentinel->next; + while (srcel != l2->tail_sentinel) { + el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + el->next->prev = el; + el = el->next; + el->data = srcel->data; + srcel = srcel->next; + } + el->next = dest->tail_sentinel; + dest->tail_sentinel->prev = el; + + /* fix mid pointer */ + err = l2->numels - l1->numels; + if ((err+1)/2 > 0) { /* correct pos RIGHT (err-1)/2 moves */ + err = (err+1)/2; + for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->next; + } else if (err/2 < 0) { /* correct pos LEFT (err/2)-1 moves */ + err = -err/2; + for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->prev; + } + + assert(!(list_repOk(l1) && list_repOk(l2)) || list_repOk(dest)); + + return 0; +} + +int list_sort(list_t *restrict l, int versus) { + if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */ + return -1; + + if (l->numels <= 1) + return 0; + list_sort_quicksort(l, versus, 0, l->head_sentinel->next, l->numels-1, l->tail_sentinel->prev); + assert(list_repOk(l)); + return 0; +} + +#ifdef SIMCLIST_WITH_THREADS +struct list_sort_wrappedparams { + list_t *restrict l; + int versus; + unsigned int first, last; + struct list_entry_s *fel, *lel; +}; + +static void *list_sort_quicksort_threadwrapper(void *wrapped_params) { + struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)wrapped_params; + list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel); + free(wp); + pthread_exit(NULL); + return NULL; +} +#endif + +static inline void list_sort_selectionsort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel) { + struct list_entry_s *cursor, *toswap, *firstunsorted; + void *tmpdata; + + if (last <= first) /* <= 1-element lists are always sorted */ + return; + + for (firstunsorted = fel; firstunsorted != lel; firstunsorted = firstunsorted->next) { + /* find min or max in the remainder of the list */ + for (toswap = firstunsorted, cursor = firstunsorted->next; cursor != lel->next; cursor = cursor->next) + if (l->attrs.comparator(toswap->data, cursor->data) * -versus > 0) toswap = cursor; + if (toswap != firstunsorted) { /* swap firstunsorted with toswap */ + tmpdata = firstunsorted->data; + firstunsorted->data = toswap->data; + toswap->data = tmpdata; + } + } +} + +static void list_sort_quicksort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel) { + unsigned int pivotid; + unsigned int i; + register struct list_entry_s *pivot; + struct list_entry_s *left, *right; + void *tmpdata; +#ifdef SIMCLIST_WITH_THREADS + pthread_t tid; + int traised; +#endif + + + if (last <= first) /* <= 1-element lists are always sorted */ + return; + + if (last - first+1 <= SIMCLIST_MINQUICKSORTELS) { + list_sort_selectionsort(l, versus, first, fel, last, lel); + return; + } + + /* base of iteration: one element list */ + if (! (last > first)) return; + + pivotid = (get_random() % (last - first + 1)); + /* pivotid = (last - first + 1) / 2; */ + + /* find pivot */ + if (pivotid < (last - first + 1)/2) { + for (i = 0, pivot = fel; i < pivotid; pivot = pivot->next, i++); + } else { + for (i = last - first, pivot = lel; i > pivotid; pivot = pivot->prev, i--); + } + + /* smaller PIVOT bigger */ + left = fel; + right = lel; + /* iterate --- left ---> PIV <--- right --- */ + while (left != pivot && right != pivot) { + for (; left != pivot && (l->attrs.comparator(left->data, pivot->data) * -versus <= 0); left = left->next); + /* left points to a smaller element, or to pivot */ + for (; right != pivot && (l->attrs.comparator(right->data, pivot->data) * -versus >= 0); right = right->prev); + /* right points to a bigger element, or to pivot */ + if (left != pivot && right != pivot) { + /* swap, then move iterators */ + tmpdata = left->data; + left->data = right->data; + right->data = tmpdata; + + left = left->next; + right = right->prev; + } + } + + /* now either left points to pivot (end run), or right */ + if (right == pivot) { /* left part longer */ + while (left != pivot) { + if (l->attrs.comparator(left->data, pivot->data) * -versus > 0) { + tmpdata = left->data; + left->data = pivot->prev->data; + pivot->prev->data = pivot->data; + pivot->data = tmpdata; + pivot = pivot->prev; + pivotid--; + if (pivot == left) break; + } else { + left = left->next; + } + } + } else { /* right part longer */ + while (right != pivot) { + if (l->attrs.comparator(right->data, pivot->data) * -versus < 0) { + /* move current right before pivot */ + tmpdata = right->data; + right->data = pivot->next->data; + pivot->next->data = pivot->data; + pivot->data = tmpdata; + pivot = pivot->next; + pivotid++; + if (pivot == right) break; + } else { + right = right->prev; + } + } + } + + /* sort sublists A and B : |---A---| pivot |---B---| */ + +#ifdef SIMCLIST_WITH_THREADS + traised = 0; + if (pivotid > 0) { + /* prepare wrapped args, then start thread */ + if (l->threadcount < SIMCLIST_MAXTHREADS-1) { + struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)malloc(sizeof(struct list_sort_wrappedparams)); + l->threadcount++; + traised = 1; + wp->l = l; + wp->versus = versus; + wp->first = first; + wp->fel = fel; + wp->last = first+pivotid-1; + wp->lel = pivot->prev; + if (pthread_create(&tid, NULL, list_sort_quicksort_threadwrapper, wp) != 0) { + free(wp); + traised = 0; + list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + } + } else { + list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + } + } + if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); + if (traised) { + pthread_join(tid, (void **)NULL); + l->threadcount--; + } +#else + if (pivotid > 0) list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); +#endif +} + +int list_iterator_start(list_t *restrict l) { + if (l->iter_active) return 0; + l->iter_pos = 0; + l->iter_active = 1; + l->iter_curentry = l->head_sentinel->next; + return 1; +} + +void *list_iterator_next(list_t *restrict l) { + void *toret; + + if (! l->iter_active) return NULL; + + toret = l->iter_curentry->data; + l->iter_curentry = l->iter_curentry->next; + l->iter_pos++; + + return toret; +} + +int list_iterator_hasnext(const list_t *restrict l) { + if (! l->iter_active) return 0; + return (l->iter_pos < l->numels); +} + +int list_iterator_stop(list_t *restrict l) { + if (! l->iter_active) return 0; + l->iter_pos = 0; + l->iter_active = 0; + return 1; +} + +int list_hash(const list_t *restrict l, list_hash_t *restrict hash) { + struct list_entry_s *x; + list_hash_t tmphash; + + assert(hash != NULL); + + tmphash = l->numels * 2 + 100; + if (l->attrs.hasher == NULL) { +#ifdef SIMCLIST_ALLOW_LOCATIONBASED_HASHES + /* ENABLE WITH CARE !! */ +#warning "Memlocation-based hash is consistent only for testing modification in the same program run." + int i; + + /* only use element references */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + for (i = 0; i < sizeof(x->data); i++) { + tmphash += (tmphash ^ (uintptr_t)x->data); + } + tmphash += tmphash % l->numels; + } +#else + return -1; +#endif + } else { + /* hash each element with the user-given function */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + tmphash += tmphash ^ l->attrs.hasher(x->data); + tmphash +=* hash % l->numels; + } + } + + *hash = tmphash; + + return 0; +} + +#ifdef SIMCLIST_DUMPRESTORE +/* Workaround for a missing gettimeofday on Windows */ +#if defined(_MSC_VER) || defined(__MINGW32__) +int gettimeofday(struct timeval* tp, void* tzp) { + DWORD t; + t = timeGetTime(); + tp->tv_sec = t / 1000; + tp->tv_usec = t % 1000; + return 0; +} +#endif +int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) { + int32_t terminator_head, terminator_tail; + uint32_t elemlen; + off_t hop; + + + /* version */ + READ_ERRCHECK(fd, & info->version, sizeof(info->version)); + info->version = ntohs(info->version); + if (info->version > SIMCLIST_DUMPFORMAT_VERSION) { + errno = EILSEQ; + return -1; + } + + /* timestamp */ + READ_ERRCHECK(fd, & info->timestamp, sizeof(info->timestamp)); + info->timestamp = hton64(info->timestamp); + + /* list terminator (to check thereafter) */ + READ_ERRCHECK(fd, & terminator_head, sizeof(terminator_head)); + terminator_head = ntohl(terminator_head); + + /* list size */ + READ_ERRCHECK(fd, & info->list_size, sizeof(info->list_size)); + info->list_size = ntohl(info->list_size); + + /* number of elements */ + READ_ERRCHECK(fd, & info->list_numels, sizeof(info->list_numels)); + info->list_numels = ntohl(info->list_numels); + + /* length of each element (for checking for consistency) */ + READ_ERRCHECK(fd, & elemlen, sizeof(elemlen)); + elemlen = ntohl(elemlen); + + /* list hash */ + READ_ERRCHECK(fd, & info->list_hash, sizeof(info->list_hash)); + info->list_hash = ntohl(info->list_hash); + + /* check consistency */ + if (elemlen > 0) { + /* constant length, hop by size only */ + hop = info->list_size; + } else { + /* non-constant length, hop by size + all element length blocks */ + hop = info->list_size + elemlen*info->list_numels; + } + if (lseek(fd, hop, SEEK_CUR) == -1) { + return -1; + } + + /* read the trailing value and compare with terminator_head */ + READ_ERRCHECK(fd, & terminator_tail, sizeof(terminator_tail)); + terminator_tail = ntohl(terminator_tail); + + if (terminator_head == terminator_tail) + info->consistent = 1; + else + info->consistent = 0; + + return 0; +} + +int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info) { + int fd, ret; + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) return -1; + + ret = list_dump_getinfo_filedescriptor(fd, info); + close(fd); + + return ret; +} + +int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) { + struct list_entry_s *x; + void *ser_buf; + uint32_t bufsize; + struct timeval timeofday; + struct list_dump_header_s header; + + if (l->attrs.meter == NULL && l->attrs.serializer == NULL) { + errno = ENOTTY; + return -1; + } + + /**** DUMP FORMAT **** + + [ ver timestamp | totlen numels elemlen hash | DATA ] + + where DATA can be: + @ for constant-size list (element size is constant; elemlen > 0) + [ elem elem ... elem ] + @ for other lists (element size dictated by element_meter each time; elemlen <= 0) + [ size elem size elem ... size elem ] + + all integers are encoded in NETWORK BYTE FORMAT + *****/ + + + /* prepare HEADER */ + /* version */ + header.ver = htons( SIMCLIST_DUMPFORMAT_VERSION ); + + /* timestamp */ + gettimeofday(&timeofday, NULL); + header.timestamp = (int64_t)timeofday.tv_sec * 1000000 + (int64_t)timeofday.tv_usec; + header.timestamp = hton64(header.timestamp); + + header.rndterm = htonl((int32_t)get_random()); + + /* total list size is postprocessed afterwards */ + + /* number of elements */ + header.numels = htonl(l->numels); + + /* include an hash, if possible */ + if (l->attrs.hasher != NULL) { + if (htonl(list_hash(l, & header.listhash)) != 0) { + /* could not compute list hash! */ + return -1; + } + } else { + header.listhash = htonl(0); + } + + header.totlistlen = header.elemlen = 0; + + /* leave room for the header at the beginning of the file */ + if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { + /* errno set by lseek() */ + return -1; + } + + /* write CONTENT */ + if (l->numels > 0) { + /* SPECULATE that the list has constant element size */ + + if (l->attrs.serializer != NULL) { /* user user-specified serializer */ + /* get preliminary length of serialized element in header.elemlen */ + ser_buf = l->attrs.serializer(l->head_sentinel->next->data, & header.elemlen); + free(ser_buf); + /* request custom serialization of each element */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + ser_buf = l->attrs.serializer(x->data, &bufsize); + header.totlistlen += bufsize; + if (header.elemlen != 0) { /* continue on speculation */ + if (header.elemlen != bufsize) { + free(ser_buf); + /* constant element length speculation broken! */ + header.elemlen = 0; + header.totlistlen = 0; + x = l->head_sentinel; + if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { + /* errno set by lseek() */ + return -1; + } + /* restart from the beginning */ + continue; + } + /* speculation confirmed */ + WRITE_ERRCHECK(fd, ser_buf, bufsize); + } else { /* speculation found broken */ + WRITE_ERRCHECK(fd, & bufsize, sizeof(size_t)); + WRITE_ERRCHECK(fd, ser_buf, bufsize); + } + free(ser_buf); + } + } else if (l->attrs.meter != NULL) { + header.elemlen = (uint32_t)l->attrs.meter(l->head_sentinel->next->data); + + /* serialize the element straight from its data */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + bufsize = l->attrs.meter(x->data); + header.totlistlen += bufsize; + if (header.elemlen != 0) { + if (header.elemlen != bufsize) { + /* constant element length speculation broken! */ + header.elemlen = 0; + header.totlistlen = 0; + x = l->head_sentinel; + /* restart from the beginning */ + continue; + } + WRITE_ERRCHECK(fd, x->data, bufsize); + } else { + WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t)); + WRITE_ERRCHECK(fd, x->data, bufsize); + } + } + } + /* adjust endianness */ + header.elemlen = htonl(header.elemlen); + header.totlistlen = htonl(header.totlistlen); + } + + /* write random terminator */ + WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* list terminator */ + + + /* write header */ + lseek(fd, 0, SEEK_SET); + + WRITE_ERRCHECK(fd, & header.ver, sizeof(header.ver)); /* version */ + WRITE_ERRCHECK(fd, & header.timestamp, sizeof(header.timestamp)); /* timestamp */ + WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* random terminator */ + + WRITE_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); /* total length of elements */ + WRITE_ERRCHECK(fd, & header.numels, sizeof(header.numels)); /* number of elements */ + WRITE_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); /* size of each element, or 0 for independent */ + WRITE_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); /* list hash, or 0 for "ignore" */ + + + /* possibly store total written length in "len" */ + if (len != NULL) { + *len = sizeof(header) + ntohl(header.totlistlen); + } + + return 0; +} + +int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len) { + struct list_dump_header_s header; + unsigned long cnt; + void *buf = NULL; + uint32_t elsize, totreadlen, totmemorylen; + + memset(& header, 0, sizeof(header)); + + /* read header */ + + /* version */ + READ_ERRCHECK(fd, &header.ver, sizeof(header.ver)); + header.ver = ntohs(header.ver); + if (header.ver != SIMCLIST_DUMPFORMAT_VERSION) { + errno = EILSEQ; + return -1; + } + + /* timestamp */ + READ_ERRCHECK(fd, & header.timestamp, sizeof(header.timestamp)); + + /* list terminator */ + READ_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); + + header.rndterm = ntohl(header.rndterm); + + /* total list size */ + READ_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); + header.totlistlen = ntohl(header.totlistlen); + + /* number of elements */ + READ_ERRCHECK(fd, & header.numels, sizeof(header.numels)); + header.numels = ntohl(header.numels); + + /* length of every element, or '0' = variable */ + READ_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); + header.elemlen = ntohl(header.elemlen); + + /* list hash, or 0 = 'ignore' */ + READ_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); + header.listhash = ntohl(header.listhash); + + + /* read content */ + totreadlen = totmemorylen = 0; + if (header.elemlen > 0) { + /* elements have constant size = header.elemlen */ + if (l->attrs.unserializer != NULL) { + /* use unserializer */ + buf = malloc(header.elemlen); + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, buf, header.elemlen); + list_append(l, l->attrs.unserializer(buf, & elsize)); + totmemorylen += elsize; + } + } else { + /* copy verbatim into memory */ + for (cnt = 0; cnt < header.numels; cnt++) { + buf = malloc(header.elemlen); + READ_ERRCHECK(fd, buf, header.elemlen); + list_append(l, buf); + } + totmemorylen = header.numels * header.elemlen; + } + totreadlen = header.numels * header.elemlen; + } else { + /* elements have variable size. Each element is preceded by its size */ + if (l->attrs.unserializer != NULL) { + /* use unserializer */ + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, & elsize, sizeof(elsize)); + buf = malloc((size_t)elsize); + READ_ERRCHECK(fd, buf, elsize); + totreadlen += elsize; + list_append(l, l->attrs.unserializer(buf, & elsize)); + totmemorylen += elsize; + } + } else { + /* copy verbatim into memory */ + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, & elsize, sizeof(elsize)); + buf = malloc(elsize); + READ_ERRCHECK(fd, buf, elsize); + totreadlen += elsize; + list_append(l, buf); + } + totmemorylen = totreadlen; + } + } + + READ_ERRCHECK(fd, &elsize, sizeof(elsize)); /* read list terminator */ + elsize = ntohl(elsize); + + /* possibly verify the list consistency */ + /* wrt hash */ + /* don't do that + if (header.listhash != 0 && header.listhash != list_hash(l)) { + errno = ECANCELED; + return -1; + } + */ + + /* wrt header */ + if (totreadlen != header.totlistlen && (int32_t)elsize == header.rndterm) { + errno = EPROTO; + return -1; + } + + /* wrt file */ + if (lseek(fd, 0, SEEK_CUR) != lseek(fd, 0, SEEK_END)) { + errno = EPROTO; + return -1; + } + + if (len != NULL) { + *len = totmemorylen; + } + + return 0; +} + +int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len) { + int fd, mode; + size_t sizetoret; + mode = O_RDWR | O_CREAT | O_TRUNC; +#ifndef _WIN32 + mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; +#endif + fd = open(filename, mode); + if (fd < 0) return -1; + + sizetoret = list_dump_filedescriptor(l, fd, len); + close(fd); + + return sizetoret; +} + +int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len) { + int fd; + size_t totdata; + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) return -1; + + totdata = list_restore_filedescriptor(l, fd, len); + close(fd); + + return totdata; +} +#endif /* ifdef SIMCLIST_DUMPRESTORE */ + + +static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) { + if (tmp == NULL) return -1; + + /* fix mid pointer. This is wrt the PRE situation */ + if (l->numels % 2) { /* now odd */ + /* sort out the base case by hand */ + if (l->numels == 1) l->mid = NULL; + else if (pos >= l->numels/2) l->mid = l->mid->prev; + } else { /* now even */ + if (pos < l->numels/2) l->mid = l->mid->next; + } + + tmp->prev->next = tmp->next; + tmp->next->prev = tmp->prev; + + /* free what's to be freed */ + if (l->attrs.copy_data && tmp->data != NULL) + free(tmp->data); + + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp; + } else { + free(tmp); + } + + return 0; +} + +/* ready-made comparators and meters */ +#define SIMCLIST_NUMBER_COMPARATOR(type) int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); } + +SIMCLIST_NUMBER_COMPARATOR(int8_t) +SIMCLIST_NUMBER_COMPARATOR(int16_t) +SIMCLIST_NUMBER_COMPARATOR(int32_t) +SIMCLIST_NUMBER_COMPARATOR(int64_t) + +SIMCLIST_NUMBER_COMPARATOR(uint8_t) +SIMCLIST_NUMBER_COMPARATOR(uint16_t) +SIMCLIST_NUMBER_COMPARATOR(uint32_t) +SIMCLIST_NUMBER_COMPARATOR(uint64_t) + +SIMCLIST_NUMBER_COMPARATOR(float) +SIMCLIST_NUMBER_COMPARATOR(double) + +int list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); } + +/* ready-made metric functions */ +#define SIMCLIST_METER(type) size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); } + +SIMCLIST_METER(int8_t) +SIMCLIST_METER(int16_t) +SIMCLIST_METER(int32_t) +SIMCLIST_METER(int64_t) + +SIMCLIST_METER(uint8_t) +SIMCLIST_METER(uint16_t) +SIMCLIST_METER(uint32_t) +SIMCLIST_METER(uint64_t) + +SIMCLIST_METER(float) +SIMCLIST_METER(double) + +size_t list_meter_string(const void *el) { return strlen((const char *)el) + 1; } + +/* ready-made hashing functions */ +#define SIMCLIST_HASHCOMPUTER(type) list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); } + +SIMCLIST_HASHCOMPUTER(int8_t) +SIMCLIST_HASHCOMPUTER(int16_t) +SIMCLIST_HASHCOMPUTER(int32_t) +SIMCLIST_HASHCOMPUTER(int64_t) + +SIMCLIST_HASHCOMPUTER(uint8_t) +SIMCLIST_HASHCOMPUTER(uint16_t) +SIMCLIST_HASHCOMPUTER(uint32_t) +SIMCLIST_HASHCOMPUTER(uint64_t) + +SIMCLIST_HASHCOMPUTER(float) +SIMCLIST_HASHCOMPUTER(double) + +list_hash_t list_hashcomputer_string(const void *el) { + size_t l; + list_hash_t hash = 123; + const char *str = (const char *)el; + char plus; + + for (l = 0; str[l] != '\0'; l++) { + if (l) plus = hash ^ str[l]; + else plus = hash ^ (str[l] - str[0]); + hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t)))); + } + + return hash; +} + + +#ifndef NDEBUG +static int list_repOk(const list_t *restrict l) { + int ok, i; + struct list_entry_s *s; + + ok = (l != NULL) && ( + /* head/tail checks */ + (l->head_sentinel != NULL && l->tail_sentinel != NULL) && + (l->head_sentinel != l->tail_sentinel) && (l->head_sentinel->prev == NULL && l->tail_sentinel->next == NULL) && + /* empty list */ + (l->numels > 0 || (l->mid == NULL && l->head_sentinel->next == l->tail_sentinel && l->tail_sentinel->prev == l->head_sentinel)) && + /* spare elements checks */ + l->spareelsnum <= SIMCLIST_MAX_SPARE_ELEMS + ); + + if (!ok) return 0; + + if (l->numels >= 1) { + /* correct referencing */ + for (i = -1, s = l->head_sentinel; i < (int)(l->numels-1)/2 && s->next != NULL; i++, s = s->next) { + if (s->next->prev != s) break; + } + ok = (i == (int)(l->numels-1)/2 && l->mid == s); + if (!ok) return 0; + for (; s->next != NULL; i++, s = s->next) { + if (s->next->prev != s) break; + } + ok = (i == (int)l->numels && s == l->tail_sentinel); + } + + return ok; +} + +static int list_attrOk(const list_t *restrict l) { + int ok; + + ok = (l->attrs.copy_data == 0 || l->attrs.meter != NULL); + return ok; +} + +#endif + diff --git a/OpenFAST/modules/map/src/simclist/simclist.h b/OpenFAST/modules/map/src/simclist/simclist.h new file mode 100644 index 000000000..c6463a871 --- /dev/null +++ b/OpenFAST/modules/map/src/simclist/simclist.h @@ -0,0 +1,984 @@ +/* + * Copyright (c) 2007,2008 Mij <mij@bitchx.it> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * SimCList library. See http://mij.oltrelinux.com/devel/simclist + */ + + +#ifndef SIMCLIST_H +#define SIMCLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* work around lack of inttypes.h support in broken Microsoft Visual Studio compilers */ +#if defined(_MSC_VER) +#include <basetsd.h> +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef ULONG32 uint32_t; +typedef UINT64 uint64_t; +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef LONG32 int32_t; +typedef INT64 int64_t; +#else +#include <inttypes.h> /* (u)int*_t */ +#endif +#include <errno.h> +#include <sys/types.h> + +/* Be friend of both C90 and C99 compilers */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + /* "inline" and "restrict" are keywords */ +#else +# define inline /* inline */ +# define restrict /* restrict */ +#endif + + +/** + * Type representing list hashes. + * + * This is a signed integer value. + */ +typedef int32_t list_hash_t; + +#ifdef SIMCLIST_DUMPRESTORE +typedef struct { + uint16_t version; /* dump version */ + int64_t timestamp; /* when the list has been dumped, microseconds from UNIX epoch */ + uint32_t list_size; + uint32_t list_numels; + list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */ + uint32_t dumpsize; + int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */ +} list_dump_info_t; +#endif + +/** + * a comparator of elements. + * + * A comparator of elements is a function that: + * -# receives two references to elements a and b + * -# returns {<0, 0, >0} if (a > b), (a == b), (a < b) respectively + * + * It is responsability of the function to handle possible NULL values. + */ +typedef int (*element_comparator)(const void *a, const void *b); + +/** + * a seeker of elements. + * + * An element seeker is a function that: + * -# receives a reference to an element el + * -# receives a reference to some indicator data + * -# returns non-0 if the element matches the indicator, 0 otherwise + * + * It is responsability of the function to handle possible NULL values in any + * argument. + */ +typedef int (*element_seeker)(const void *el, const void *indicator); + +/** + * an element lenght meter. + * + * An element meter is a function that: + * -# receives the reference to an element el + * -# returns its size in bytes + * + * It is responsability of the function to handle possible NULL values. + */ +typedef size_t (*element_meter)(const void *el); + +/** + * a function computing the hash of elements. + * + * An hash computing function is a function that: + * -# receives the reference to an element el + * -# returns a hash value for el + * + * It is responsability of the function to handle possible NULL values. + */ +typedef list_hash_t (*element_hash_computer)(const void *el); + +/** + * a function for serializing an element. + * + * A serializer function is one that gets a reference to an element, + * and returns a reference to a buffer that contains its serialization + * along with the length of this buffer. + * It is responsability of the function to handle possible NULL values, + * returning a NULL buffer and a 0 buffer length. + * + * These functions have 3 goals: + * -# "freeze" and "flatten" the memory representation of the element + * -# provide a portable (wrt byte order, or type size) representation of the element, if the dump can be used on different sw/hw combinations + * -# possibly extract a compressed representation of the element + * + * @param el reference to the element data + * @param serialize_buffer reference to fill with the length of the buffer + * @return reference to the buffer with the serialized data + */ +typedef void *(*element_serializer)(const void *restrict el, uint32_t *restrict serializ_len); + +/** + * a function for un-serializing an element. + * + * An unserializer function accomplishes the inverse operation of the + * serializer function. An unserializer function is one that gets a + * serialized representation of an element and turns it backe to the original + * element. The serialized representation is passed as a reference to a buffer + * with its data, and the function allocates and returns the buffer containing + * the original element, and it sets the length of this buffer into the + * integer passed by reference. + * + * @param data reference to the buffer with the serialized representation of the element + * @param data_len reference to the location where to store the length of the data in the buffer returned + * @return reference to a buffer with the original, unserialized representation of the element + */ +typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len); + +/* [private-use] list entry -- olds actual user datum */ +struct list_entry_s { + void *data; + + /* doubly-linked list service references */ + struct list_entry_s *next; + struct list_entry_s *prev; +}; + +/* [private-use] list attributes */ +struct list_attributes_s { + /* user-set routine for comparing list elements */ + element_comparator comparator; + /* user-set routing for seeking elements */ + element_seeker seeker; + /* user-set routine for determining the length of an element */ + element_meter meter; + int copy_data; + /* user-set routine for computing the hash of an element */ + element_hash_computer hasher; + /* user-set routine for serializing an element */ + element_serializer serializer; + /* user-set routine for unserializing an element */ + element_unserializer unserializer; +}; + +/** list object */ +typedef struct { + struct list_entry_s *head_sentinel; + struct list_entry_s *tail_sentinel; + struct list_entry_s *mid; + + unsigned int numels; + + /* array of spare elements */ + struct list_entry_s **spareels; + unsigned int spareelsnum; + +#ifdef SIMCLIST_WITH_THREADS + /* how many threads are currently running */ + unsigned int threadcount; +#endif + + /* service variables for list iteration */ + int iter_active; + unsigned int iter_pos; + struct list_entry_s *iter_curentry; + + /* list attributes */ + struct list_attributes_s attrs; +} list_t; + +/** + * initialize a list object for use. + * + * @param l must point to a user-provided memory location + * @return 0 for success. -1 for failure + */ +int list_init(list_t *restrict l); + +/** + * completely remove the list from memory. + * + * This function is the inverse of list_init(). It is meant to be called when + * the list is no longer going to be used. Elements and possible memory taken + * for internal use are freed. + * + * @param l list to destroy + */ +void list_destroy(list_t *restrict l); + +/** + * set the comparator function for list elements. + * + * Comparator functions are used for searching and sorting. If NULL is passed + * as reference to the function, the comparator is disabled. + * + * @param l list to operate + * @param comparator_fun pointer to the actual comparator function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_comparator() + */ +int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun); + +/** + * set a seeker function for list elements. + * + * Seeker functions are used for finding elements. If NULL is passed as reference + * to the function, the seeker is disabled. + * + * @param l list to operate + * @param seeker_fun pointer to the actual seeker function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_seeker() + */ +int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun); + +/** + * require to free element data when list entry is removed (default: don't free). + * + * [ advanced preference ] + * + * By default, when an element is removed from the list, it disappears from + * the list by its actual data is not free()d. With this option, every + * deletion causes element data to be freed. + * + * It is responsability of this function to correctly handle NULL values, if + * NULL elements are inserted into the list. + * + * @param l list to operate + * @param metric_fun pointer to the actual metric function + * @param copy_data 0: do not free element data (default); non-0: do free + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_meter() + * @see list_meter_int8_t() + * @see list_meter_int16_t() + * @see list_meter_int32_t() + * @see list_meter_int64_t() + * @see list_meter_uint8_t() + * @see list_meter_uint16_t() + * @see list_meter_uint32_t() + * @see list_meter_uint64_t() + * @see list_meter_float() + * @see list_meter_double() + * @see list_meter_string() + */ +int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data); + +/** + * set the element hash computing function for the list elements. + * + * [ advanced preference ] + * + * An hash can be requested depicting the list status at a given time. An hash + * only depends on the elements and their order. By default, the hash of an + * element is only computed on its reference. With this function, the user can + * set a custom function computing the hash of an element. If such function is + * provided, the list_hash() function automatically computes the list hash using + * the custom function instead of simply referring to element references. + * + * @param l list to operate + * @param hash_computer_fun pointer to the actual hash computing function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_hash_computer() + */ +int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun); + +/** + * set the element serializer function for the list elements. + * + * [ advanced preference ] + * + * Serialize functions are used for dumping the list to some persistent + * storage. The serializer function is called for each element; it is passed + * a reference to the element and a reference to a size_t object. It will + * provide (and return) the buffer with the serialization of the element and + * fill the size_t object with the length of this serialization data. + * + * @param l list to operate + * @param serializer_fun pointer to the actual serializer function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_serializer() + * @see list_dump_filedescriptor() + * @see list_restore_filedescriptor() + */ +int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun); + +/** + * set the element unserializer function for the list elements. + * + * [ advanced preference ] + * + * Unserialize functions are used for restoring the list from some persistent + * storage. The unserializer function is called for each element segment read + * from the storage; it is passed the segment and a reference to an integer. + * It shall allocate and return a buffer compiled with the resumed memory + * representation of the element, and set the integer value to the length of + * this buffer. + * + * @param l list to operate + * @param unserializer_fun pointer to the actual unserializer function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_unserializer() + * @see list_dump_filedescriptor() + * @see list_restore_filedescriptor() + */ +int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun); + +/** + * append data at the end of the list. + * + * This function is useful for adding elements with a FIFO/queue policy. + * + * @param l list to operate + * @param data pointer to user data to append + * + * @return 1 for success. < 0 for failure + */ +int list_append(list_t *restrict l, const void *data); + +/** + * insert data in the head of the list. + * + * This function is useful for adding elements with a LIFO/Stack policy. + * + * @param l list to operate + * @param data pointer to user data to append + * + * @return 1 for success. < 0 for failure + */ +int list_prepend(list_t *restrict l, const void *restrict data); + +/** + * extract the element in the top of the list. + * + * This function is for using a list with a FIFO/queue policy. + * + * @param l list to operate + * @return reference to user datum, or NULL on errors + */ +void *list_fetch(list_t *restrict l); + +/** + * retrieve an element at a given position. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element wanted + * @return reference to user datum, or NULL on errors + */ +void *list_get_at(const list_t *restrict l, unsigned int pos); + +/** + * return the maximum element of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * Returns the maximum element with respect to the comparator function output. + * + * @see list_attributes_comparator() + * + * @param l list to operate + * @return the reference to the element, or NULL + */ +void *list_get_max(const list_t *restrict l); + +/** + * return the minimum element of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * Returns the minimum element with respect to the comparator function output. + * + * @see list_attributes_comparator() + * + * @param l list to operate + * @return the reference to the element, or NULL + */ +void *list_get_min(const list_t *restrict l); + +/** + * retrieve and remove from list an element at a given position. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element wanted + * @return reference to user datum, or NULL on errors + */ +void *list_extract_at(list_t *restrict l, unsigned int pos); + +/** + * insert an element at a given position. + * + * @param l list to operate + * @param data reference to data to be inserted + * @param pos [0,size-1] position index to insert the element at + * @return positive value on success. Negative on failure + */ +int list_insert_at(list_t *restrict l, const void *data, unsigned int pos); + +/** + * expunge the first found given element from the list. + * + * Inspects the given list looking for the given element; if the element + * is found, it is removed. Only the first occurence is removed. + * If a comparator function was not set, elements are compared by reference. + * Otherwise, the comparator is used to match the element. + * + * @param l list to operate + * @param data reference of the element to search for + * @return 0 on success. Negative value on failure + * + * @see list_attributes_comparator() + * @see list_delete_at() + */ +int list_delete(list_t *restrict l, const void *data); + +/** + * expunge an element at a given position from the list. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element to be deleted + * @return 0 on success. Negative value on failure + */ +int list_delete_at(list_t *restrict l, unsigned int pos); + +/** + * expunge an array of elements from the list, given their position range. + * + * @param l list to operate + * @param posstart [0,size-1] position index of the first element to be deleted + * @param posend [posstart,size-1] position of the last element to be deleted + * @return the number of elements successfully removed + */ +int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend); + +/** + * clear all the elements off of the list. + * + * The element datums will not be freed. + * + * @see list_delete_range() + * @see list_size() + * + * @param l list to operate + * @return the number of elements in the list before cleaning + */ +int list_clear(list_t *restrict l); + +/** + * inspect the number of elements in the list. + * + * @param l list to operate + * @return number of elements currently held by the list + */ +unsigned int list_size(const list_t *restrict l); + +/** + * inspect whether the list is empty. + * + * @param l list to operate + * @return 0 iff the list is not empty + * + * @see list_size() + */ +int list_empty(const list_t *restrict l); + +/** + * find the position of an element in a list. + * + * @warning Requires a comparator function to be set for the list. + * + * Inspects the given list looking for the given element; if the element + * is found, its position into the list is returned. + * Elements are inspected comparing references if a comparator has not been + * set. Otherwise, the comparator is used to find the element. + * + * @param l list to operate + * @param data reference of the element to search for + * @return position of element in the list, or <0 if not found + * + * @see list_attributes_comparator() + * @see list_get_at() + */ +int list_locate(const list_t *restrict l, const void *data); + +/** + * returns an element given an indicator. + * + * @warning Requires a seeker function to be set for the list. + * + * Inspect the given list looking with the seeker if an element matches + * an indicator. If such element is found, the reference to the element + * is returned. + * + * @param l list to operate + * @param indicator indicator data to pass to the seeker along with elements + * @return reference to the element accepted by the seeker, or NULL if none found + */ +void *list_seek(list_t *restrict l, const void *indicator); + +/** + * inspect whether some data is member of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * By default, a per-reference comparison is accomplished. That is, + * the data is in list if any element of the list points to the same + * location of data. + * A "semantic" comparison is accomplished, otherwise, if a comparator + * function has been set previously, with list_attributes_comparator(); + * in which case, the given data reference is believed to be in list iff + * comparator_fun(elementdata, userdata) == 0 for any element in the list. + * + * @param l list to operate + * @param data reference to the data to search + * @return 0 iff the list does not contain data as an element + * + * @see list_attributes_comparator() + */ +int list_contains(const list_t *restrict l, const void *data); + +/** + * concatenate two lists + * + * Concatenates one list with another, and stores the result into a + * user-provided list object, which must be different from both the + * lists to concatenate. Attributes from the original lists are not + * cloned. + * The destination list referred is threated as virgin room: if it + * is an existing list containing elements, memory leaks will happen. + * It is OK to specify the same list twice as source, for "doubling" + * it in the destination. + * + * @param l1 base list + * @param l2 list to append to the base + * @param dest reference to the destination list + * @return 0 for success, -1 for errors + */ +int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest); + +/** + * sort list elements. + * + * @warning Requires a comparator function to be set for the list. + * + * Sorts the list in ascending or descending order as specified by the versus + * flag. The algorithm chooses autonomously what algorithm is best suited for + * sorting the list wrt its current status. + * + * @param l list to operate + * @param versus positive: order small to big; negative: order big to small + * @return 0: sorting went OK non-0: errors happened + * + * @see list_attributes_comparator() + */ +int list_sort(list_t *restrict l, int versus); + +/** + * start an iteration session. + * + * This function prepares the list to be iterated. + * + * @param l list to operate + * @return 0 if the list cannot be currently iterated. >0 otherwise + * + * @see list_iterator_stop() + */ +int list_iterator_start(list_t *restrict l); + +/** + * return the next element in the iteration session. + * + * @param l list to operate + * @return element datum, or NULL on errors + */ +void *list_iterator_next(list_t *restrict l); + +/** + * inspect whether more elements are available in the iteration session. + * + * @param l list to operate + * @return 0 iff no more elements are available. + */ +int list_iterator_hasnext(const list_t *restrict l); + +/** + * end an iteration session. + * + * @param l list to operate + * @return 0 iff the iteration session cannot be stopped + */ +int list_iterator_stop(list_t *restrict l); + +/** + * return the hash of the current status of the list. + * + * @param l list to operate + * @param hash where the resulting hash is put + * + * @return 0 for success; <0 for failure + */ +int list_hash(const list_t *restrict l, list_hash_t *restrict hash); + +#ifdef SIMCLIST_DUMPRESTORE +/** + * get meta informations on a list dump on filedescriptor. + * + * [ advanced function ] + * + * Extracts the meta information from a SimCList dump located in a file + * descriptor. The file descriptor must be open and positioned at the + * beginning of the SimCList dump block. + * + * @param fd file descriptor to get metadata from + * @param info reference to a dump metainformation structure to fill + * @return 0 for success; <0 for failure + * + * @see list_dump_filedescriptor() + */ +int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info); + +/** + * get meta informations on a list dump on file. + * + * [ advanced function ] + * + * Extracts the meta information from a SimCList dump located in a file. + * + * @param filename filename of the file to fetch from + * @param info reference to a dump metainformation structure to fill + * @return 0 for success; <0 for failure + * + * @see list_dump_filedescriptor() + */ +int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info); + +/** + * dump the list into an open, writable file descriptor. + * + * This function "dumps" the list to a persistent storage so it can be + * preserved across process terminations. + * When called, the file descriptor must be open for writing and positioned + * where the serialized data must begin. It writes its serialization of the + * list in a form which is portable across different architectures. Dump can + * be safely performed on stream-only (non seekable) descriptors. The file + * descriptor is not closed at the end of the operations. + * + * To use dump functions, either of these conditions must be satisfied: + * -# a metric function has been specified with list_attributes_copy() + * -# a serializer function has been specified with list_attributes_serializer() + * + * If a metric function has been specified, each element of the list is dumped + * as-is from memory, copying it from its pointer for its length down to the + * file descriptor. This might have impacts on portability of the dump to + * different architectures. + * + * If a serializer function has been specified, its result for each element is + * dumped to the file descriptor. + * + * + * @param l list to operate + * @param fd file descriptor to write to + * @param len location to store the resulting length of the dump (bytes), or NULL + * + * @return 0 if successful; -1 otherwise + * + * @see element_serializer() + * @see list_attributes_copy() + * @see list_attributes_serializer() + */ +int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len); + +/** + * dump the list to a file name. + * + * This function creates a filename and dumps the current content of the list + * to it. If the file exists it is overwritten. The number of bytes written to + * the file can be returned in a specified argument. + * + * @param l list to operate + * @param filename filename to write to + * @param len location to store the resulting length of the dump (bytes), or NULL + * + * @return 0 if successful; -1 otherwise + * + * @see list_attributes_copy() + * @see element_serializer() + * @see list_attributes_serializer() + * @see list_dump_filedescriptor() + * @see list_restore_file() + * + * This function stores a representation of the list + */ +int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len); + +/** + * restore the list from an open, readable file descriptor to memory. + * + * This function is the "inverse" of list_dump_filedescriptor(). It restores + * the list content from a (open, read-ready) file descriptor to memory. An + * unserializer might be needed to restore elements from the persistent + * representation back into memory-consistent format. List attributes can not + * be restored and must be set manually. + * + * @see list_dump_filedescriptor() + * @see list_attributes_serializer() + * @see list_attributes_unserializer() + * + * @param l list to restore to + * @param fd file descriptor to read from. + * @param len location to store the length of the dump read (bytes), or NULL + * @return 0 if successful; -1 otherwise + */ +int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len); + +/** + * restore the list from a file name. + * + * This function restores the content of a list from a file into memory. It is + * the inverse of list_dump_file(). + * + * @see element_unserializer() + * @see list_attributes_unserializer() + * @see list_dump_file() + * @see list_restore_filedescriptor() + * + * @param l list to restore to + * @param filename filename to read data from + * @param len location to store the length of the dump read (bytes), or NULL + * @return 0 if successful; -1 otherwise + */ +int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len); +#endif + +/* ready-made comparators, meters and hash computers */ + /* comparator functions */ +/** + * ready-made comparator for int8_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int8_t(const void *a, const void *b); + +/** + * ready-made comparator for int16_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int16_t(const void *a, const void *b); + +/** + * ready-made comparator for int32_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int32_t(const void *a, const void *b); + +/** + * ready-made comparator for int64_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int64_t(const void *a, const void *b); + +/** + * ready-made comparator for uint8_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint8_t(const void *a, const void *b); + +/** + * ready-made comparator for uint16_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint16_t(const void *a, const void *b); + +/** + * ready-made comparator for uint32_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint32_t(const void *a, const void *b); + +/** + * ready-made comparator for uint64_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint64_t(const void *a, const void *b); + +/** + * ready-made comparator for float elements. + * @see list_attributes_comparator() + */ +int list_comparator_float(const void *a, const void *b); + +/** + * ready-made comparator for double elements. + * @see list_attributes_comparator() + */ +int list_comparator_double(const void *a, const void *b); + +/** + * ready-made comparator for string elements. + * @see list_attributes_comparator() + */ +int list_comparator_string(const void *a, const void *b); + + /* metric functions */ +/** + * ready-made metric function for int8_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int8_t(const void *el); + +/** + * ready-made metric function for int16_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int16_t(const void *el); + +/** + * ready-made metric function for int32_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int32_t(const void *el); + +/** + * ready-made metric function for int64_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int64_t(const void *el); + +/** + * ready-made metric function for uint8_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint8_t(const void *el); + +/** + * ready-made metric function for uint16_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint16_t(const void *el); + +/** + * ready-made metric function for uint32_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint32_t(const void *el); + +/** + * ready-made metric function for uint64_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint64_t(const void *el); + +/** + * ready-made metric function for float elements. + * @see list_attributes_copy() + */ +size_t list_meter_float(const void *el); + +/** + * ready-made metric function for double elements. + * @see list_attributes_copy() + */ +size_t list_meter_double(const void *el); + +/** + * ready-made metric function for string elements. + * @see list_attributes_copy() + */ +size_t list_meter_string(const void *el); + + /* hash functions */ +/** + * ready-made hash function for int8_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int8_t(const void *el); + +/** + * ready-made hash function for int16_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int16_t(const void *el); + +/** + * ready-made hash function for int32_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int32_t(const void *el); + +/** + * ready-made hash function for int64_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int64_t(const void *el); + +/** + * ready-made hash function for uint8_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint8_t(const void *el); + +/** + * ready-made hash function for uint16_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint16_t(const void *el); + +/** + * ready-made hash function for uint32_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint32_t(const void *el); + +/** + * ready-made hash function for uint64_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint64_t(const void *el); + +/** + * ready-made hash function for float elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_float(const void *el); + +/** + * ready-made hash function for double elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_double(const void *el); + +/** + * ready-made hash function for string elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_string(const void *el); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/OpenFAST/modules/moordyn/CMakeLists.txt b/OpenFAST/modules/moordyn/CMakeLists.txt new file mode 100644 index 000000000..4bd406ba2 --- /dev/null +++ b/OpenFAST/modules/moordyn/CMakeLists.txt @@ -0,0 +1,43 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/MoorDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MoorDyn_Types.f90) +endif() + +set(MOORDYN_LIBS_SOURCES + src/MoorDyn.f90 + src/MoorDyn_IO.f90 + src/MoorDyn_Types.f90 +) + +add_library(moordynlib ${MOORDYN_LIBS_SOURCES}) +target_link_libraries(moordynlib nwtclibs) + +install(TARGETS moordynlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +set(MD_DRIVER_SOURCES src/MoorDyn_Driver.f90) +add_executable(moordyn_driver ${MD_DRIVER_SOURCES}) +target_link_libraries(moordyn_driver moordynlib nwtclibs versioninfolib ${CMAKE_DL_LIBS}) + +install(TARGETS moordyn_driver + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/moordyn/README.md b/OpenFAST/modules/moordyn/README.md new file mode 100644 index 000000000..af24791e5 --- /dev/null +++ b/OpenFAST/modules/moordyn/README.md @@ -0,0 +1,30 @@ +# MoorDyn Module +This is an externally developed module with further information +available on the developer's documentation site: +[Matt Hall](http://www.matt-hall.ca/moordyn.html). + +The legacy version of FAST's information regarding this module +are available at the [NWTC Software Portal](https://nwtc.nrel.gov/MoorDyn/). + +## Overview +MoorDyn is a lumped-mass mooring line model for simulating the dynamics of +moorings connected to floating offshore structures. It accounts for internal +axial stiffness and damping forces, weight and buoyancy forces, hydrodynamic +forces from Morison's equation (assuming quiescent water so far), and vertical +spring-damper forces from contact with the seabed. MoorDyn's input file format +is based on that of MAP. The model supports arbitrary line interconnections, +clump weights and floats, and different line properties. + +The Fortran implementation of MoorDyn, which has been developed +following the FAST Modularization Framework, is included as a module in +OpenFAST. + +For the C++ implementation of MoorDyn, see http://www.matt-hall.ca/moordyn. +"MoorDyn C" can be compiled as a dynamically-linked library and features +simpler functions for easy coupling with models or scripts coded in C/C++, +Fortran, Matlab/Simulink, etc. It has recently been integrated into WEC-Sim. + +Both forms of MoorDyn feature the same underlying mooring model, use similar +input and output conventions, and are being updated and improved in parallel. +They follow the same version numbering, with a "C" or "F" suffix for +differentiation. diff --git a/OpenFAST/modules/moordyn/src/MoorDyn.f90 b/OpenFAST/modules/moordyn/src/MoorDyn.f90 new file mode 100644 index 000000000..7c012801c --- /dev/null +++ b/OpenFAST/modules/moordyn/src/MoorDyn.f90 @@ -0,0 +1,2210 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 Matthew Hall +! +! This file is part of MoorDyn. +! +! 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 MoorDyn + + USE MoorDyn_Types + USE MoorDyn_IO + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: MD_ProgDesc = ProgDesc( 'MoorDyn', 'v1.01.02F', '8-Apr-2016' ) + + + PUBLIC :: MD_Init + PUBLIC :: MD_UpdateStates + PUBLIC :: MD_CalcOutput + PUBLIC :: MD_CalcContStateDeriv + PUBLIC :: MD_End + +CONTAINS + + !========================================= MD_Init =================================== + SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, ErrStat, ErrMsg) + + IMPLICIT NONE + + TYPE(MD_InitInputType), INTENT(INOUT) :: InitInp ! INTENT(INOUT) : Input data for initialization routine + TYPE(MD_InputType), INTENT( OUT) :: u ! INTENT( OUT) : An initial guess for the input; input mesh must be defined + TYPE(MD_ParameterType), INTENT( OUT) :: p ! INTENT( OUT) : Parameters + TYPE(MD_ContinuousStateType), INTENT( OUT) :: x ! INTENT( OUT) : Initial continuous states + TYPE(MD_DiscreteStateType), INTENT( OUT) :: xd ! INTENT( OUT) : Initial discrete states + TYPE(MD_ConstraintStateType), INTENT( OUT) :: z ! INTENT( OUT) : Initial guess of the constraint states + TYPE(MD_OtherStateType), INTENT( OUT) :: other ! INTENT( OUT) : Initial other states + TYPE(MD_OutputType), INTENT( OUT) :: y ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + TYPE(MD_MiscVarType), INTENT( OUT) :: m ! INTENT( OUT) : Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: DTcoupling ! Coupling interval in seconds: the rate that Output is the actual coupling interval + TYPE(MD_InitOutputType), INTENT(INOUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: t ! instantaneous time, to be used during IC generation + INTEGER(IntKi) :: I ! index + INTEGER(IntKi) :: J ! index + INTEGER(IntKi) :: K ! index + INTEGER(IntKi) :: Converged ! flag indicating whether the dynamic relaxation has converged + INTEGER(IntKi) :: N ! convenience integer for readability: number of segments in the line + REAL(ReKi) :: Pos(3) ! array for setting absolute fairlead positions in mesh + REAL(ReKi) :: TransMat(3,3) ! rotation matrix for setting fairlead positions correctly if there is initial platform rotation + REAL(ReKi), ALLOCATABLE :: FairTensIC(:,:)! array of size Nfairs, 3 to store three latest fairlead tensions of each line + CHARACTER(20) :: TempString ! temporary string for incidental use + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + TYPE(MD_InputType) :: uArray(1) ! a size-one array for u to make call to TimeStep happy + REAL(DbKi) :: utimes(1) ! a size-one array saying time is 0 to make call to TimeStep happy + + CHARACTER(MaxWrScrLen) :: Message + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + ! Display the module information + CALL DispNVD( MD_ProgDesc ) + InitOut%Ver = MD_ProgDesc + + + !--------------------------------------------------------------------------------------------- + ! Get all the inputs taken care of + !--------------------------------------------------------------------------------------------- + + + ! set environmental parameters from input data and error check + ! (should remove these values as options from MoorDyn input file for consistency?) + + p%g = InitInp%g + p%WtrDpth = InitInp%WtrDepth + p%rhoW = InitInp%rhoW + + p%RootName = TRIM(InitInp%RootName)//'.MD' ! all files written from this module will have this root name + + + ! call function that reads input file and creates cross-referenced Connect and Line objects + CALL MDIO_ReadInput(InitInp, p, m, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! process the OutList array and set up the index arrays for the requested output quantities + CALL MDIO_ProcessOutList(InitInp%OutList, p, m, y, InitOut, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !------------------------------------------------------------------------------------------------- + ! Connect mooring system together and make necessary allocations + !------------------------------------------------------------------------------------------------- + + CALL WrNR( ' Creating mooring system. ' ) + + p%NFairs = 0 ! this is the number of "vessel" type Connections. being consistent with MAP terminology + p%NConns = 0 ! this is the number of "connect" type Connections. not to be confused with NConnects, the number of Connections + p%NAnchs = 0 ! this is the number of "fixed" type Connections. + + ! cycle through Connects and identify Connect types + DO I = 1, p%NConnects + + TempString = m%ConnectList(I)%type + CALL Conv2UC(TempString) + if (TempString == 'FIXED') then + m%ConnectList(I)%TypeNum = 0 + p%NAnchs = p%NAnchs + 1 + else if (TempString == 'VESSEL') then + m%ConnectList(I)%TypeNum = 1 + p%NFairs = p%NFairs + 1 ! if a vessel connection, increment fairlead counter + else if (TempString == 'CONNECT') then + m%ConnectList(I)%TypeNum = 2 + p%NConns = p%NConns + 1 + else + CALL CheckError( ErrID_Fatal, 'Error in provided Connect type. Must be fixed, vessel, or connect.' ) + RETURN + END IF + END DO + + CALL WrScr(trim(Num2LStr(p%NFairs))//' fairleads, '//trim(Num2LStr(p%NAnchs))//' anchors, '//trim(Num2LStr(p%NConns))//' connects.') + + + ! allocate fairleads list + ALLOCATE ( m%FairIdList(p%NFairs), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL CheckError( ErrID_Fatal, 'Error allocating space for FairIdList array.') + RETURN + END IF + + ! allocate connect list + ALLOCATE ( m%ConnIdList(p%NConns), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL CheckError( ErrID_Fatal, 'Error allocating space for ConnIdList array.') + RETURN + END IF + + + ! now go back through and record the fairlead Id numbers (this is all the "connecting" that's required) + J = 1 ! counter for fairlead number + K = 1 ! counter for connect number + DO I = 1,p%NConnects + IF (m%ConnectList(I)%TypeNum == 1) THEN + m%FairIdList(J) = I ! if a vessel connection, add ID to list + J = J + 1 + ELSE IF (m%ConnectList(I)%TypeNum == 2) THEN + m%ConnIdList(K) = I ! if a connect connection, add ID to list + K = K + 1 + END IF + END DO + + + ! go through lines and allocate variables + DO I = 1, p%NLines + CALL SetupLine( m%LineList(I), m%LineTypeList(m%LineList(I)%PropsIdNum), p%rhoW , ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + + !------------------------------------------------------------------------------------ + ! prepare state vector + !------------------------------------------------------------------------------------ + + ! allocate list of starting state vector indices for each line - does this belong elsewhere? + ALLOCATE ( m%LineStateIndList(p%NLines), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL CheckError(ErrID_Fatal, ' Error allocating LineStateIndList array.') + RETURN + END IF + + + ! figure out required size of state vector and how it will be apportioned to Connect and Lines (J is keeping track of the growing size of the state vector) + J = p%NConns*6 ! start index of first line's states (added six state variables for each "connect"-type connection) + + DO I = 1, p%NLines + m%LineStateIndList(I) = J+1 ! assign start index of each line + J = J + 6*(m%LineList(I)%N - 1) !add 6 state variables for each internal node + END DO + + + ! allocate state vector for RK2 based on size just calculated + ALLOCATE ( x%states(J), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating state vector.' + !CALL CleanUp() + RETURN + END IF + + + ! get header information for the FAST output file <<< what does this mean? + + + !-------------------------------------------------------------------------- + ! create i/o meshes for fairlead positions and forces + !-------------------------------------------------------------------------- + + ! create input mesh for fairlead kinematics + CALL MeshCreate(BlankMesh=u%PtFairleadDisplacement , & + IOS= COMPONENT_INPUT , & + Nnodes=p%NFairs , & + TranslationDisp=.TRUE. , & + TranslationVel=.TRUE. , & + ErrStat=ErrStat2 , & + ErrMess=ErrMsg2) + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! --------------------------- set up initial condition of each fairlead ------------------------------- + DO i = 1,p%NFairs + + Pos(1) = m%ConnectList(m%FairIdList(i))%conX ! set relative position of each fairlead i (I'm pretty sure this is just relative to ptfm origin) + Pos(2) = m%ConnectList(m%FairIdList(i))%conY + Pos(3) = m%ConnectList(m%FairIdList(i))%conZ + + CALL MeshPositionNode(u%PtFairleadDisplacement,i,Pos,ErrStat2,ErrMsg2)! "assign the coordinates of each node in the global coordinate space" + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! set offset position of each node to according to initial platform position + CALL SmllRotTrans('initial fairlead positions due to platform rotation', InitInp%PtfmInit(4),InitInp%PtfmInit(5),InitInp%PtfmInit(6), TransMat, '', ErrStat2, ErrMsg2) ! account for possible platform rotation + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Apply initial platform rotations and translations (fixed Jun 19, 2015) + u%PtFairleadDisplacement%TranslationDisp(1,i) = InitInp%PtfmInit(1) + Transmat(1,1)*Pos(1) + Transmat(2,1)*Pos(2) + TransMat(3,1)*Pos(3) - Pos(1) + u%PtFairleadDisplacement%TranslationDisp(2,i) = InitInp%PtfmInit(2) + Transmat(1,2)*Pos(1) + Transmat(2,2)*Pos(2) + TransMat(3,2)*Pos(3) - Pos(2) + u%PtFairleadDisplacement%TranslationDisp(3,i) = InitInp%PtfmInit(3) + Transmat(1,3)*Pos(1) + Transmat(2,3)*Pos(2) + TransMat(3,3)*Pos(3) - Pos(3) + + ! set velocity of each node to zero + u%PtFairleadDisplacement%TranslationVel(1,i) = 0.0_ReKi + u%PtFairleadDisplacement%TranslationVel(2,i) = 0.0_ReKi + u%PtFairleadDisplacement%TranslationVel(3,i) = 0.0_ReKi + + !print *, 'Fairlead ', i, ' z TranslationDisp at start is ', u%PtFairleadDisplacement%TranslationDisp(3,i) + !print *, 'Fairlead ', i, ' z Position at start is ', u%PtFairleadDisplacement%Position(3,i) + + + ! set each node as a point element + CALL MeshConstructElement(u%PtFairleadDisplacement, ELEMENT_POINT, ErrStat2, ErrMsg2, i) + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + END DO ! I + + + CALL MeshCommit ( u%PtFairleadDisplacement, ErrStat, ErrMsg ) + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! copy the input fairlead kinematics mesh to make the output mesh for fairlead loads, PtFairleadLoad + CALL MeshCopy ( SrcMesh = u%PtFairleadDisplacement, DestMesh = y%PtFairleadLoad, & + CtrlCode = MESH_SIBLING, IOS = COMPONENT_OUTPUT, & + Force = .TRUE., ErrStat = ErrStat2, ErrMess=ErrMsg2 ) + + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! -------------------------------------------------------------------- + ! go through all Connects and set position based on input file + ! -------------------------------------------------------------------- + + ! first do it for all connections (connect and anchor types will be saved) + DO I = 1, p%NConnects + m%ConnectList(I)%r(1) = m%ConnectList(I)%conX + m%ConnectList(I)%r(2) = m%ConnectList(I)%conY + m%ConnectList(I)%r(3) = m%ConnectList(I)%conZ + m%ConnectList(I)%rd(1) = 0.0_ReKi + m%ConnectList(I)%rd(2) = 0.0_ReKi + m%ConnectList(I)%rd(3) = 0.0_ReKi + END DO + + ! then do it for fairlead types + DO I = 1,p%NFairs + DO J = 1, 3 + m%ConnectList(m%FairIdList(I))%r(J) = u%PtFairleadDisplacement%Position(J,I) + u%PtFairleadDisplacement%TranslationDisp(J,I) + m%ConnectList(m%FairIdList(I))%rd(J) = 0.0_ReKi + END DO + END DO + + ! for connect types, write the coordinates to the state vector + DO I = 1,p%NConns + x%states(6*I-2:6*I) = m%ConnectList(m%ConnIdList(I))%r ! double check order of r vs rd + x%states(6*I-5:6*I-3) = m%ConnectList(m%ConnIdList(I))%rd + END DO + + ! -------------------------------------------------------------------- + ! open output file(s) and write header lines + CALL MDIO_OpenOutput( InitInp%FileName, p, m, InitOut, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + ! -------------------------------------------------------------------- + + + + ! -------------------------------------------------------------------- + ! size active tensioning inputs arrays based on highest channel number read from input file for now <<<<<<< + ! -------------------------------------------------------------------- + + ! find the highest channel number + N = 0 + DO I = 1, p%NLines + IF ( m%LineList(I)%CtrlChan > N ) then + N = m%LineList(I)%CtrlChan + END IF + END DO + + ! allocate the input arrays + ALLOCATE ( u%DeltaL(N), u%DeltaLdot(N), STAT = ErrStat2 ) + + + ! -------------------------------------------------------------------- + ! go through lines and initialize internal node positions using Catenary() + ! -------------------------------------------------------------------- + DO I = 1, p%NLines + + N = m%LineList(I)%N ! for convenience + + !TODO: apply any initial adjustment of line length from active tensioning <<<<<<<<<<<< + ! >>> maybe this should be skipped <<<< + + ! set end node positions and velocities from connect objects + m%LineList(I)%r(:,N) = m%ConnectList(m%LineList(I)%FairConnect)%r + m%LineList(I)%r(:,0) = m%ConnectList(m%LineList(I)%AnchConnect)%r + m%LineList(I)%rd(:,N) = (/ 0.0, 0.0, 0.0 /) ! set anchor end velocities to zero + m%LineList(I)%rd(:,0) = (/ 0.0, 0.0, 0.0 /) ! set fairlead end velocities to zero + + ! set initial line internal node positions using quasi-static model or straight-line interpolation from anchor to fairlead + CALL InitializeLine( m%LineList(I), m%LineTypeList(m%LineList(I)%PropsIdNum), p%rhoW , ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + IF (ErrStat >= ErrId_Warn) CALL WrScr(" Catenary solver failed for one or more lines. Using linear node spacing.") ! make this statement more accurate + + ! assign the resulting internal node positions to the integrator initial state vector! (velocities leave at 0) + DO J = 1, N-1 + DO K = 1, 3 + x%states(m%LineStateIndList(I) + 3*N-3 + 3*J-3 + K-1 ) = m%LineList(I)%r(K,J) ! assign position + x%states(m%LineStateIndList(I) + 3*J-3 + K-1 ) = 0.0_ReKi ! assign velocities (of zero) + END DO + END DO + + END DO !I = 1, p%NLines + + +! ! try writing output for troubleshooting purposes (TEMPORARY) +! CALL MDIO_WriteOutputs(-1.0_DbKi, p, m, y, ErrStat, ErrMsg) +! IF ( ErrStat >= AbortErrLev ) THEN +! ErrMsg = ' Error in MDIO_WriteOutputs: '//TRIM(ErrMsg) +! RETURN +! END IF + + + ! -------------------------------------------------------------------- + ! do dynamic relaxation to get ICs + ! -------------------------------------------------------------------- + + CALL WrScr(" Finalizing ICs using dynamic relaxation."//NewLine) ! newline because next line writes over itself + + ! boost drag coefficient of each line type + DO I = 1, p%NTypes + m%LineTypeList(I)%Cdn = m%LineTypeList(I)%Cdn * InitInp%CdScaleIC + m%LineTypeList(I)%Cdt = m%LineTypeList(I)%Cdt * InitInp%CdScaleIC + END DO + + ! allocate array holding three latest fairlead tensions + ALLOCATE ( FairTensIC(p%NFairs,3), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + CALL CheckError( ErrID_Fatal, ErrMsg2 ) + RETURN + END IF + + ! initialize fairlead tension memory at zero + DO J = 1,p%NFairs + DO I = 1, 3 + FairTensIC(J,I) = 0.0_ReKi + END DO + END DO + + t = 0.0_DbKi ! start time at zero + + ! because TimeStep wants an array... + call MD_CopyInput( u, uArray(1), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + + + DO I = 1, ceiling(InitInp%TMaxIC/InitInp%DTIC) ! loop through IC gen time steps, up to maximum + + ! integrate the EOMs one DTIC s time step + CALL TimeStep ( t, InitInp%DTIC, uArray, utimes, p, x, xd, z, other, m, ErrStat, ErrMsg ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! store new fairlead tension (and previous fairlead tensions for comparison) + DO J = 1, p%NFairs + FairTensIC(J,3) = FairTensIC(J,2) + FairTensIC(J,2) = FairTensIC(J,1) + FairTensIC(J,1) = TwoNorm(m%ConnectList(m%FairIdList(J))%Ftot(:)) + END DO + + ! provide status message + ! bjj: putting this in a string so we get blanks to cover up previous values (if current string is shorter than previous one) + Message = ' t='//trim(Num2LStr(t))//' FairTen 1: '//trim(Num2LStr(FairTensIC(1,1)))// & + ', '//trim(Num2LStr(FairTensIC(1,2)))//', '//trim(Num2LStr(FairTensIC(1,3))) + CALL WrOver( Message ) + + ! check for convergence (compare current tension at each fairlead with previous two values) + IF (I > 2) THEN + Converged = 1 + DO J = 1, p%NFairs ! check for non-convergence + IF (( abs( FairTensIC(J,1)/FairTensIC(J,2) - 1.0 ) > InitInp%threshIC ) .OR. ( abs( FairTensIC(J,1)/FairTensIC(J,3) - 1.0 ) > InitInp%threshIC ) ) THEN + Converged = 0 + EXIT + END IF + END DO + + IF (Converged == 1) THEN ! (J == p%NFairs) THEN ! if we made it with all cases satisfying the threshold + CALL WrScr(' Fairlead tensions converged to '//trim(Num2LStr(100.0*InitInp%threshIC))//'% after '//trim(Num2LStr(t))//' seconds.') + EXIT ! break out of the time stepping loop + END IF + END IF + + IF (I == ceiling(InitInp%TMaxIC/InitInp%DTIC) ) THEN + CALL WrScr(' Fairlead tensions did not converge within TMaxIC='//trim(Num2LStr(InitInp%TMaxIC))//' seconds.') + !ErrStat = ErrID_Warn + !ErrMsg = ' MD_Init: ran dynamic convergence to TMaxIC without convergence' + END IF + + END DO ! I ... looping through time steps + + CALL MD_DestroyInput( uArray(1), ErrStat2, ErrMsg2 ) + + ! UNboost drag coefficient of each line type + DO I = 1, p%NTypes + m%LineTypeList(I)%Cdn = m%LineTypeList(I)%Cdn / InitInp%CdScaleIC + m%LineTypeList(I)%Cdt = m%LineTypeList(I)%Cdt / InitInp%CdScaleIC + END DO + + + p%dtCoupling = DTcoupling ! store coupling time step for use in updatestates + + other%dummy = 0 + xd%dummy = 0 + z%dummy = 0 + + CONTAINS + + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + ! Set error status/message; + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine ! if there's a pre-existing warning/error, retain the message and start a new line + + ErrMsg = TRIM(ErrMsg)//' MD_Init:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + ! Clean up if we're going to return on error: close files, deallocate local arrays + + + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(m%FairIdList )) DEALLOCATE(m%FairIdList ) + IF (ALLOCATED(m%ConnIdList )) DEALLOCATE(m%ConnIdList ) + IF (ALLOCATED(m%LineStateIndList )) DEALLOCATE(m%LineStateIndList ) + IF (ALLOCATED(x%states )) DEALLOCATE(x%states ) + IF (ALLOCATED(FairTensIC )) DEALLOCATE(FairTensIC ) + END IF + END IF + + END SUBROUTINE CheckError + + END SUBROUTINE MD_Init + !============================================================================================== + + + + + !============================================================================================== + SUBROUTINE MD_UpdateStates( t, n, u, utimes, p, x, xd, z, other, m, ErrStat, ErrMsg) + + REAL(DbKi) , INTENT(IN ) :: t + INTEGER(IntKi) , INTENT(IN ) :: n + TYPE(MD_InputType) , INTENT(INOUT) :: u(:) ! INTENT(INOUT) ! had to change this to INOUT + REAL(DbKi) , INTENT(IN ) :: utimes(:) + TYPE(MD_ParameterType) , INTENT(IN ) :: p ! INTENT(IN ) + TYPE(MD_ContinuousStateType) , INTENT(INOUT) :: x ! INTENT(INOUT) + TYPE(MD_DiscreteStateType) , INTENT(INOUT) :: xd ! INTENT(INOUT) + TYPE(MD_ConstraintStateType) , INTENT(INOUT) :: z ! INTENT(INOUT) + TYPE(MD_OtherStateType) , INTENT(INOUT) :: other ! INTENT(INOUT) + TYPE(MD_MiscVarType) , INTENT(INOUT) :: m ! INTENT(INOUT) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + +! moved to TimeStep TYPE(MD_InputType) :: u_interp ! + INTEGER(IntKi) :: nTime + + REAL(DbKi) :: t2 ! copy of time passed to TimeStep + + + nTime = size(u) ! the number of times of input data provided? + + t2 = t + +! >>> removing this section and putting it inside loop of TimeStep (to be done at every time step) <<< +! ! create space for arrays/meshes in u_interp +! CALL MD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) +! CALL CheckError( ErrStat2, ErrMsg2 ) +! IF (ErrStat >= AbortErrLev) RETURN +! +! ! interpolate input mesh to correct time +! CALL MD_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat2, ErrMsg2) +! CALL CheckError( ErrStat2, ErrMsg2 ) +! IF (ErrStat >= AbortErrLev) RETURN +! +! +! ! go through fairleads and apply motions from driver +! DO I = 1, p%NFairs +! DO J = 1,3 +! m%ConnectList(m%FairIdList(I))%r(J) = u_interp%PtFairleadDisplacement%Position(J,I) + u_interp%PtFairleadDisplacement%TranslationDisp(J,I) +! m%ConnectList(m%FairIdList(I))%rd(J) = u_interp%PtFairleadDisplacement%TranslationVel(J,I) ! is this right? <<< +! END DO +! END DO +! + + ! call function that loops through mooring model time steps + CALL TimeStep ( t2, p%dtCoupling, u, utimes, p, x, xd, z, other, m, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + ! clean up input interpolation stuff + ! moved to TimeStep CALL MD_DestroyInput(u_interp, ErrStat, ErrMsg) + + + CONTAINS + + SUBROUTINE CheckError(ErrId, Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine ! keep existing error message if there is one + ErrMsg = TRIM(ErrMsg)//' MD_UpdateStates:'//TRIM(Msg) ! add current error message + ErrStat = MAX(ErrStat, ErrID) + + CALL WrScr( ErrMsg ) ! do this always or only if warning level? + + IF( ErrStat > ErrID_Warn ) THEN + ! CALL MD_DestroyInput( u_interp, ErrStat, ErrMsg ) + RETURN + END IF + END IF + + END SUBROUTINE CheckError + + END SUBROUTINE MD_UpdateStates + !======================================================================================== + + + + !======================================================================================== + SUBROUTINE MD_CalcOutput( t, u, p, x, xd, z, other, y, m, ErrStat, ErrMsg ) + + REAL(DbKi) , INTENT(IN ) :: t + TYPE( MD_InputType ) , INTENT(IN ) :: u ! INTENT(IN ) + TYPE( MD_ParameterType ) , INTENT(IN ) :: p ! INTENT(IN ) + TYPE( MD_ContinuousStateType ) , INTENT(IN ) :: x ! INTENT(IN ) + TYPE( MD_DiscreteStateType ) , INTENT(IN ) :: xd ! INTENT(IN ) + TYPE( MD_ConstraintStateType ) , INTENT(IN ) :: z ! INTENT(IN ) + TYPE( MD_OtherStateType ) , INTENT(IN ) :: other ! INTENT(IN ) + TYPE( MD_OutputType ) , INTENT(INOUT) :: y ! INTENT(INOUT) + TYPE(MD_MiscVarType) , INTENT(INOUT) :: m ! INTENT(INOUT) + INTEGER(IntKi) , INTENT(INOUT) :: ErrStat + CHARACTER(*) , INTENT(INOUT) :: ErrMsg + + TYPE(MD_ContinuousStateType) :: dxdt ! time derivatives of continuous states (initialized in CalcContStateDeriv) + INTEGER(IntKi) :: I ! counter + INTEGER(IntKi) :: J ! counter + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + + ! below updated to make sure outputs are current (based on provided x and u) - similar to what's in UpdateStates + + ! go through fairleads and apply motions from driver + DO I = 1, p%NFairs + DO J = 1,3 + m%ConnectList(m%FairIdList(I))%r(J) = u%PtFairleadDisplacement%Position(J,I) + u%PtFairleadDisplacement%TranslationDisp(J,I) + m%ConnectList(m%FairIdList(I))%rd(J) = u%PtFairleadDisplacement%TranslationVel(J,I) ! is this right? <<< + END DO + END DO + + ! call CalcContStateDeriv in order to run model and calculate dynamics with provided x and u + CALL MD_CalcContStateDeriv( t, u, p, x, xd, z, other, m, dxdt, ErrStat, ErrMsg ) + + + ! assign net force on fairlead Connects to the output mesh + DO i = 1, p%NFairs + DO J=1,3 + y%PtFairleadLoad%Force(J,I) = m%ConnectList(m%FairIdList(I))%Ftot(J) + END DO + END DO + + + ! calculate outputs (y%WriteOutput) for glue code and write any m outputs to MoorDyn output files + CALL MDIO_WriteOutputs(t, p, m, y, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2, 'In MDIO_WriteOutputs: '//trim(ErrMsg2)) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! destroy dxdt + CALL MD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2, 'When destroying dxdt: '//trim(ErrMsg2)) + IF ( ErrStat >= AbortErrLev ) RETURN + + + + CONTAINS + + SUBROUTINE CheckError(ErrId, Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine ! keep existing error message if there is one + ErrMsg = TRIM(ErrMsg)//' MD_CalcOutput:'//TRIM(Msg) ! add current error message + ErrStat = MAX(ErrStat, ErrID) + + CALL WrScr( ErrMsg ) ! do this always or only if warning level? <<<<<<<<<<<<<<<<<<<<<< probably should remove all instances + + IF( ErrStat > ErrID_Warn ) THEN + CALL MD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + END IF + END IF + + END SUBROUTINE CheckError + + END SUBROUTINE MD_CalcOutput + !============================================================================================= + + + !============================================================================================= + SUBROUTINE MD_CalcContStateDeriv( t, u, p, x, xd, z, other, m, dxdt, ErrStat, ErrMsg ) + ! Tight coupling routine for computing derivatives of continuous states + ! this is modelled off what used to be subroutine DoRHSmaster + + REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds + TYPE(MD_InputType), INTENT(IN ) :: u ! Inputs at t + TYPE(MD_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(MD_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at t + TYPE(MD_DiscreteStateType), INTENT(IN ) :: xd ! Discrete states at t + TYPE(MD_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t + TYPE(MD_OtherStateType), INTENT(IN ) :: other ! Other states at t + TYPE(MD_MiscVarType), INTENT(INOUT) :: m ! misc/optimization variables + TYPE(MD_ContinuousStateType), INTENT( OUT) :: dxdt ! Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + INTEGER(IntKi) :: L ! index + INTEGER(IntKi) :: J ! index + INTEGER(IntKi) :: K ! index + INTEGER(IntKi) :: Istart ! start index of line/connect in state vector + INTEGER(IntKi) :: Iend ! end index of line/connect in state vector + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! allocations of dxdt (as in SubDyn. "INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here" is this right/efficient?) + ALLOCATE ( dxdt%states(size(x%states)), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating dxdt%states array.' + RETURN + END IF + + + ! clear connection force and mass values + DO L = 1, p%NConnects + DO J = 1,3 + m%ConnectList(L)%Ftot(J) = 0.0_ReKi + m%ConnectList(L)%Ftot(J) = 0.0_ReKi + DO K = 1,3 + m%ConnectList(L)%Mtot(K,J) = 0.0_ReKi + m%ConnectList(L)%Mtot(K,J) = 0.0_ReKi + END DO + END DO + END DO + + ! update fairlead positions for instantaneous values (fixed 2015-06-22) + DO K = 1, p%NFairs + DO J = 1,3 + m%ConnectList(m%FairIdList(K))%r(J) = u%PtFairleadDisplacement%Position(J,K) + u%PtFairleadDisplacement%TranslationDisp(J,K) + m%ConnectList(m%FairIdList(K))%rd(J) = u%PtFairleadDisplacement%TranslationVel(J,K) ! is this right? <<< + END DO + END DO + + ! apply line length changes from active tensioning if applicable + DO L = 1, p%NLines + IF (m%LineList(L)%CtrlChan > 0) then + + ! do a bounds check to prohibit excessive segment length changes (until a method to add/remove segments is created) + IF ( u%DeltaL(m%LineList(L)%CtrlChan) > m%LineList(L)%UnstrLen / m%LineList(L)%N ) then + ErrStat = ErrID_Fatal + ErrMsg = ' Active tension command will make a segment longer than the limit of twice its original length.' + print *, u%DeltaL(m%LineList(L)%CtrlChan), " is an increase of more than ", (m%LineList(L)%UnstrLen / m%LineList(L)%N) + print *, u%DeltaL + print*, m%LineList(L)%CtrlChan + RETURN + END IF + IF ( u%DeltaL(m%LineList(L)%CtrlChan) < -0.5 * m%LineList(L)%UnstrLen / m%LineList(L)%N ) then + ErrStat = ErrID_Fatal + ErrMsg = ' Active tension command will make a segment shorter than the limit of half its original length.' + print *, u%DeltaL(m%LineList(L)%CtrlChan), " is a reduction of more than half of ", (m%LineList(L)%UnstrLen / m%LineList(L)%N) + print *, u%DeltaL + print*, m%LineList(L)%CtrlChan + RETURN + END IF + + ! for now this approach only acts on the fairlead end segment, and assumes all segment lengths are otherwise equal size + m%LineList(L)%l( m%LineList(L)%N) = m%LineList(L)%UnstrLen/m%LineList(L)%N + u%DeltaL(m%LineList(L)%CtrlChan) + m%LineList(L)%ld(m%LineList(L)%N) = u%DeltaLdot(m%LineList(L)%CtrlChan) + END IF + END DO + + ! do Line force and acceleration calculations, also add end masses/forces to respective Connects + DO L = 1, p%NLines + Istart = m%LineStateIndList(L) + Iend = Istart + 6*(m%LineList(L)%N - 1) - 1 + CALL DoLineRHS(x%states(Istart:Iend), dxdt%states(Istart:Iend), t, m%LineList(L), & + m%LineTypeList(m%LineList(L)%PropsIdNum), & + m%ConnectList(m%LineList(L)%FairConnect)%Ftot, m%ConnectList(m%LineList(L)%FairConnect)%Mtot, & + m%ConnectList(m%LineList(L)%AnchConnect)%Ftot, m%ConnectList(m%LineList(L)%AnchConnect)%Mtot ) + END DO + + + ! perform connection force and mass calculations (done to all connects for sake of calculating fairlead/anchor loads) + DO L = 1, p%NConnects + ! add Connect's own forces including buoyancy and weight + m%ConnectList(L)%Ftot(1) =m%ConnectList(L)%Ftot(1) + m%ConnectList(L)%conFX + m%ConnectList(L)%Ftot(2) =m%ConnectList(L)%Ftot(2) + m%ConnectList(L)%conFY + m%ConnectList(L)%Ftot(3) =m%ConnectList(L)%Ftot(3) + m%ConnectList(L)%conFZ + m%ConnectList(L)%conV*p%rhoW*p%g - m%ConnectList(L)%conM*p%g + + ! add Connect's own mass + DO J = 1,3 + m%ConnectList(L)%Mtot(J,J) = m%ConnectList(L)%Mtot(J,J) + m%ConnectList(L)%conM + END DO + END DO ! L + + + ! do Connect acceleration calculations - changed to do only connect types + DO L = 1, p%NConns + Istart = L*6-5 + Iend = L*6 + CALL DoConnectRHS(x%states(Istart:Iend), dxdt%states(Istart:Iend), t, m%ConnectList(m%ConnIDList(L))) + END DO + + + CONTAINS + + + !====================================================================== + SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, AnchMtot) + + Real(ReKi), INTENT( IN ) :: X(:) ! state vector, provided + Real(ReKi), INTENT( INOUT ) :: Xd(:) ! derivative of state vector, returned ! cahnged to INOUT + Real(DbKi), INTENT (IN) :: t ! instantaneous time + TYPE(MD_Line), INTENT (INOUT) :: Line ! label for the current line, for convenience + TYPE(MD_LineProp), INTENT(IN) :: LineProp ! the single line property set for the line of interest + Real(ReKi), INTENT(INOUT) :: FairFtot(:) ! total force on Connect top of line is attached to + Real(ReKi), INTENT(INOUT) :: FairMtot(:,:) ! total mass of Connect top of line is attached to + Real(ReKi), INTENT(INOUT) :: AnchFtot(:) ! total force on Connect bottom of line is attached to + Real(ReKi), INTENT(INOUT) :: AnchMtot(:,:) ! total mass of Connect bottom of line is attached to + + + INTEGER(IntKi) :: I ! index of segments or nodes along line + INTEGER(IntKi) :: J ! index + INTEGER(IntKi) :: K ! index + INTEGER(IntKi) :: N ! number of segments in line + Real(ReKi) :: d ! line diameter + Real(ReKi) :: rho ! line material density [kg/m^3] + Real(ReKi) :: Sum1 ! for summing squares + Real(ReKi) :: m_i ! node mass + Real(ReKi) :: v_i ! node submerged volume + Real(ReKi) :: Vi(3) ! relative water velocity at a given node + Real(ReKi) :: Vp(3) ! transverse relative water velocity component at a given node + Real(ReKi) :: Vq(3) ! tangential relative water velocity component at a given node + Real(ReKi) :: SumSqVp ! + Real(ReKi) :: SumSqVq ! + Real(ReKi) :: MagVp ! + Real(ReKi) :: MagVq ! + + + N = Line%N ! for convenience + d = LineProp%d ! for convenience + rho = LineProp%w/(Pi/4.0*d*d) + + + + ! set end node positions and velocities from connect objects' states + DO J = 1, 3 + Line%r( J,N) = m%ConnectList(Line%FairConnect)%r(J) + Line%r( J,0) = m%ConnectList(Line%AnchConnect)%r(J) + Line%rd(J,N) = m%ConnectList(Line%FairConnect)%rd(J) + Line%rd(J,0) = m%ConnectList(Line%AnchConnect)%rd(J) + END DO + + ! set interior node positions and velocities + DO I = 1, N-1 + DO J = 1, 3 + Line%r( J,I) = X( 3*N-3 + 3*I-3 + J) ! r(J,I) = X[3*N-3 + 3*i-3 + J]; // get positions .. used to start from m%LineStateIndList(Line%IdNum) in whole state vector + Line%rd(J,I) = X( 3*I-3 + J) ! rd(J,I) = X[ 3*i-3 + J]; // get velocities + END DO + END DO + + ! calculate instantaneous (stretched) segment lengths and rates << should add catch here for if lstr is ever zero + DO I = 1, N + Sum1 = 0.0_ReKi + DO J = 1, 3 + Sum1 = Sum1 + (Line%r(J,I) - Line%r(J,I-1)) * (Line%r(J,I) - Line%r(J,I-1)) + END DO + Line%lstr(I) = sqrt(Sum1) ! stretched segment length + + Sum1 = 0.0_ReKi + DO J = 1, 3 + Sum1 = Sum1 + (Line%r(J,I) - Line%r(J,I-1))*(Line%rd(J,I) - Line%rd(J,I-1)) + END DO + Line%lstrd(I) = Sum1/Line%lstr(I) ! segment stretched length rate of change + + ! Line%V(I) = Pi/4.0 * d*d*Line%l(I) !volume attributed to segment + END DO + + !calculate unit tangent vectors (q) for each node (including ends) note: I think these are pointing toward 0 rather than N! + CALL UnitVector(Line%q(:,0), Line%r(:,1), Line%r(:,0)) ! compute unit vector q + DO I = 1, N-1 + CALL UnitVector(Line%q(:,I), Line%r(:,I+1), Line%r(:,I-1)) ! compute unit vector q ... using adjacent two nodes! + END DO + CALL UnitVector(Line%q(:,N), Line%r(:,N), Line%r(:,N-1)) ! compute unit vector q + + + ! wave kinematics not implemented yet + + + !calculate mass (including added mass) matrix for each node + DO I = 0, N + IF (I==0) THEN + m_i = Pi/8.0 *d*d*Line%l(1)*rho + v_i = 0.5 *Line%V(1) + ELSE IF (I==N) THEN + m_i = pi/8.0 *d*d*Line%l(N)*rho; + v_i = 0.5*Line%V(N) + ELSE + m_i = pi/8.0 * d*d*rho*(Line%l(I) + Line%l(I+1)) + v_i = 0.5 *(Line%V(I) + Line%V(I+1)) + END IF + + DO J=1,3 + DO K=1,3 + IF (J==K) THEN + Line%M(K,J,I) = m_i + p%rhoW*v_i*( LineProp%Can*(1 - Line%q(J,I)*Line%q(K,I)) + LineProp%Cat*Line%q(J,I)*Line%q(K,I) ) + ELSE + Line%M(K,J,I) = p%rhoW*v_i*( LineProp%Can*(-Line%q(J,I)*Line%q(K,I)) + LineProp%Cat*Line%q(J,I)*Line%q(K,I) ) + END IF + END DO + END DO + + CALL Inverse3by3(Line%S(:,:,I), Line%M(:,:,I)) ! invert mass matrix + END DO + + + ! ------------------ CALCULATE FORCES ON EACH NODE ---------------------------- + + ! loop through the segments + DO I = 1, N + + ! line tension, inherently including possibility of dynamic length changes in l term + IF (Line%lstr(I)/Line%l(I) > 1.0) THEN + DO J = 1, 3 + Line%T(J,I) = LineProp%EA *( 1.0/Line%l(I) - 1.0/Line%lstr(I) ) * (Line%r(J,I)-Line%r(J,I-1)) + END DO + ELSE + DO J = 1, 3 + Line%T(J,I) = 0.0_ReKi ! cable can't "push" + END DO + END if + + ! line internal damping force based on line-specific BA value, including possibility of dynamic length changes in l and ld terms + DO J = 1, 3 + Line%Td(J,I) = Line%BA* ( Line%lstrd(I) - Line%lstr(I)*Line%ld(I)/Line%l(I) )/Line%l(I) * (Line%r(J,I)-Line%r(J,I-1)) / Line%lstr(I) + END DO + END DO + + + + ! loop through the nodes + DO I = 0, N + + !submerged weight (including buoyancy) + IF (I==0) THEN + Line%W(3,I) = Pi/8.0*d*d* Line%l(1)*(rho - p%rhoW) *(-p%g) ! assuming g is positive + ELSE IF (i==N) THEN + Line%W(3,I) = pi/8.0*d*d* Line%l(N)*(rho - p%rhoW) *(-p%g) + ELSE + Line%W(3,I) = pi/8.0*d*d* (Line%l(I)*(rho - p%rhoW) + Line%l(I+1)*(rho - p%rhoW) )*(-p%g) ! left in this form for future free surface handling + END IF + + !relative flow velocities + DO J = 1, 3 + Vi(J) = 0.0 - Line%rd(J,I) ! relative flow velocity over node -- this is where wave velicites would be added + END DO + + ! decomponse relative flow into components + SumSqVp = 0.0_ReKi ! start sums of squares at zero + SumSqVq = 0.0_ReKi + DO J = 1, 3 + Vq(J) = DOT_PRODUCT( Vi , Line%q(:,I) ) * Line%q(J,I); ! tangential relative flow component + Vp(J) = Vi(J) - Vq(J) ! transverse relative flow component + SumSqVq = SumSqVq + Vq(J)*Vq(J) + SumSqVp = SumSqVp + Vp(J)*Vp(J) + END DO + MagVp = sqrt(SumSqVp) ! get magnitudes of flow components + MagVq = sqrt(SumSqVq) + + ! transverse and tangenential drag + IF (I==0) THEN + DO J = 1, 3 + Line%Dp(J,I) = 0.25*p%rhoW*LineProp%Cdn* d*Line%l(1) * MagVp * Vp(J) + Line%Dq(J,I) = 0.25*p%rhoW*LineProp%Cdt* Pi*d*Line%l(1) * MagVq * Vq(J) + END DO + ELSE IF (I==N) THEN + DO J = 1, 3 + Line%Dp(J,I) = 0.25*p%rhoW*LineProp%Cdn* d*Line%l(N) * MagVp * Vp(J); + Line%Dq(J,I) = 0.25*p%rhoW*LineProp%Cdt* Pi*d*Line%l(N) * MagVq * Vq(J) + END DO + ELSE + DO J = 1, 3 + Line%Dp(J,I) = 0.25*p%rhoW*LineProp%Cdn* d*(Line%l(I) + Line%l(I+1)) * MagVp * vp(J); + Line%Dq(J,I) = 0.25*p%rhoW*LineProp%Cdt* Pi*d*(Line%l(I) + Line%l(I+1)) * MagVq * vq(J); + END DO + END IF + + ! F-K force from fluid acceleration not implemented yet + + ! bottom contact (stiffness and damping, vertical-only for now) - updated Nov 24 for general case where anchor and fairlead ends may deal with bottom contact forces + + IF (Line%r(3,I) < -p%WtrDpth) THEN + IF (I==0) THEN + Line%B(3,I) = ( (-p%WtrDpth - Line%r(3,I))*p%kBot - Line%rd(3,I)*p%cBot) * 0.5*d*( Line%l(I+1) ) + ELSE IF (I==N) THEN + Line%B(3,I) = ( (-p%WtrDpth - Line%r(3,I))*p%kBot - Line%rd(3,I)*p%cBot) * 0.5*d*(Line%l(I) ) + ELSE + Line%B(3,I) = ( (-p%WtrDpth - Line%r(3,I))*p%kBot - Line%rd(3,I)*p%cBot) * 0.5*d*(Line%l(I) + Line%l(I+1) ) + + + + END IF + ELSE + Line%B(3,I) = 0.0_ReKi + END IF + + ! total forces + IF (I==0) THEN + DO J = 1, 3 + Line%F(J,I) = Line%T(J,1) + Line%Td(J,1) + Line%W(J,I) + Line%Dp(J,I) + Line%Dq(J,I) + Line%B(J,I) + END DO + ELSE IF (I==N) THEN + DO J = 1, 3 + Line%F(J,I) = -Line%T(J,N) - Line%Td(J,N) + Line%W(J,I) + Line%Dp(J,I) + Line%Dq(J,I) + Line%B(J,I) + END DO + ELSE + DO J = 1, 3 + Line%F(J,I) = Line%T(J,I+1) - Line%T(J,I) + Line%Td(J,I+1) - Line%Td(J,I) + Line%W(J,I) + Line%Dp(J,I) + Line%Dq(J,I) + Line%B(J,I) + END DO + END IF + + END DO ! I - done looping through nodes + + + ! loop through internal nodes and update their states + DO I=1, N-1 + DO J=1,3 + + ! calculate RHS constant (premultiplying force vector by inverse of mass matrix ... i.e. rhs = S*Forces) + Sum1 = 0.0_ReKi ! reset temporary accumulator + DO K = 1, 3 + Sum1 = Sum1 + Line%S(K,J,I) * Line%F(K,I) ! matrix-vector multiplication [S i]{Forces i} << double check indices + END DO ! K + + ! update states + Xd(3*N-3 + 3*I-3 + J) = X(3*I-3 + J); ! dxdt = V (velocities) + Xd( 3*I-3 + J) = Sum1 ! dVdt = RHS * A (accelerations) + + END DO ! J + END DO ! I + + + ! add force and mass of end nodes to the Connects they correspond to + DO J = 1,3 + FairFtot(J) = FairFtot(J) + Line%F(J,N) + AnchFtot(J) = AnchFtot(J) + Line%F(J,0) + DO K = 1,3 + FairMtot(K,J) = FairMtot(K,J) + Line%M(K,J,N) + AnchMtot(K,J) = AnchMtot(K,J) + Line%M(K,J,0) + END DO + END DO + + END SUBROUTINE DoLineRHS + !===================================================================== + + + !====================================================================== + SUBROUTINE DoConnectRHS (X, Xd, t, Connect) + + ! This subroutine is for the "Connect" type of Connections only. Other types don't have their own state variables. + + Real(ReKi), INTENT( IN ) :: X(:) ! state vector for this connect, provided + Real(ReKi), INTENT( OUT ) :: Xd(:) ! derivative of state vector for this connect, returned + Real(DbKi), INTENT (IN) :: t ! instantaneous time + Type(MD_Connect), INTENT (INOUT) :: Connect ! Connect number + + + !INTEGER(IntKi) :: I ! index of segments or nodes along line + INTEGER(IntKi) :: J ! index + INTEGER(IntKi) :: K ! index + Real(ReKi) :: Sum1 ! for adding things + + ! When this sub is called, the force and mass contributions from the attached Lines should already have been added to + ! Fto and Mtot by the Line RHS function. Also, any self weight, buoyancy, or external forcing should have already been + ! added by the calling subroutine. The only thing left is any added mass or drag forces from the connection (e.g. float) + ! itself, which will be added below. + + + IF (EqualRealNos(t, 0.0_DbKi)) THEN ! this is old: with current IC gen approach, we skip the first call to the line objects, because they're set AFTER the call to the connects + + DO J = 1,3 + Xd(3+J) = X(J) ! velocities - these are unused in integration + Xd(J) = 0.0_ReKi ! accelerations - these are unused in integration + END DO + ELSE + ! from state values, get r and rdot values + DO J = 1,3 + Connect%r(J) = X(3 + J) ! get positions + Connect%rd(J) = X(J) ! get velocities + END DO + END IF + + + ! add any added mass and drag forces from the Connect body itself + DO J = 1,3 + Connect%Ftot(J) = Connect%Ftot(J) - 0.5 * p%rhoW * Connect%rd(J) * abs(Connect%rd(J)) * Connect%conCdA; ! add drag forces - corrected Nov 24 + Connect%Mtot(J,J) = Connect%Mtot(J,J) + Connect%conV*p%rhoW*Connect%conCa; ! add added mass + END DO + + ! invert node mass matrix + CALL Inverse3by3(Connect%S, Connect%Mtot) + + DO J = 1,3 + ! RHS constant - (premultiplying force vector by inverse of mass matrix ... i.e. rhs = S*Forces + Sum1 = 0.0_ReKi ! reset accumulator + DO K = 1, 3 + Sum1 = Sum1 + Connect%S(K,J) * Connect%Ftot(K) ! matrix multiplication [S i]{Forces i} + END DO + + ! update states + Xd(3 + J) = X(J) ! dxdt = V (velocities) + Xd(J) = Sum1 ! dVdt = RHS * A (accelerations) + END DO + + END SUBROUTINE DoConnectRHS + !===================================================================== + + END SUBROUTINE MD_CalcContStateDeriv + !============================================================================================= + + + !=============================================================================================== + SUBROUTINE MD_End(u, p, x, xd, z, other, y, m, ErrStat , ErrMsg) + TYPE(MD_InputType) , INTENT(INOUT) :: u + TYPE(MD_ParameterType) , INTENT(INOUT) :: p + TYPE(MD_ContinuousStateType) , INTENT(INOUT) :: x + TYPE(MD_DiscreteStateType) , INTENT(INOUT) :: xd + TYPE(MD_ConstraintStateType) , INTENT(INOUT) :: z + TYPE(MD_OtherStateType) , INTENT(INOUT) :: other + TYPE(MD_OutputType) , INTENT(INOUT) :: y + TYPE(MD_MiscVarType), INTENT(INOUT) :: m + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + +! INTEGER(IntKi) :: i=0 + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + ErrStat = ErrID_None + ErrMsg = "" + + + + ! deallocate data associated with file output + CALL MDIO_CloseOutput ( p, m, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + !IF (ErrStat >= AbortErrLev) RETURN + + + ! deallocate FAST data structures + CALL MD_DestroyInput(u, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyParam(p, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyContState(x, ErrStat2, ErrMsg2) ! <--- getting access violation + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyDiscState(xd, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyConstrState(z, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyOtherState(other,ErrStat2,ErrMsg2) ! <--- getting access violation + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyOutput(y, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + CALL MD_DestroyMisc(m, ErrStat2, ErrMsg2) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! IF ( ErrStat==ErrID_None) THEN + ! CALL WrScr('MoorDyn closed without errors') + ! ELSE + ! CALL WrScr('MoorDyn closed with errors') + ! END IF + + + CONTAINS + + SUBROUTINE CheckError(ErrId, Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine ! keep existing error message if there is one + ErrMsg = TRIM(ErrMsg)//' MD_End:'//TRIM(Msg) ! add current error message + ErrStat = MAX(ErrStat, ErrID) + + CALL WrScr( ErrMsg ) ! do this always or only if warning level? + + END IF + + END SUBROUTINE CheckError + + + END SUBROUTINE MD_End ! -------+ + !========================================================================================================== + + +!!========== MD_CheckError ======= <---------------------------------------------------------------+ +! SUBROUTINE MD_CheckError(InMsg,OutMsg) +! ! Passed arguments +!! CHARACTER(*), INTENT(IN ) :: InMsg ! The input string +! CHARACTER(*), INTENT(INOUT) :: OutMsg ! The error message (ErrMsg)! +! + ! OutMsg = InMsg + ! RETURN + !END SUBROUTINE MD_CheckError ! -------+ + !========================================================================================================== + + + + + !======================================================================================================== + SUBROUTINE TimeStep ( t, dtStep, u, utimes, p, x, xd, z, other, m, ErrStat, ErrMsg ) + REAL(DbKi) , INTENT(INOUT) :: t + REAL(ReKi) , INTENT(IN ) :: dtStep ! how long to advance the time for + TYPE( MD_InputType ) , INTENT(INOUT) :: u(:) ! INTENT(IN ) + REAL(DbKi) , INTENT(IN ) :: utimes(:) ! times corresponding to elements of u(:)? + TYPE( MD_ParameterType ) , INTENT(IN ) :: p ! INTENT(IN ) + TYPE( MD_ContinuousStateType ) , INTENT(INOUT) :: x + TYPE( MD_DiscreteStateType ) , INTENT(IN ) :: xd ! INTENT(IN ) + TYPE( MD_ConstraintStateType ) , INTENT(IN ) :: z ! INTENT(IN ) + TYPE( MD_OtherStateType ) , INTENT(IN ) :: other ! INTENT(INOUT) + TYPE(MD_MiscVarType) , INTENT(INOUT) :: m ! INTENT(INOUT) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat + CHARACTER(*) , INTENT( OUT) :: ErrMsg + + + TYPE(MD_ContinuousStateType) :: dxdt ! time derivatives of continuous states (initialized in CalcContStateDeriv) + TYPE(MD_ContinuousStateType) :: x2 ! temporary copy of continuous states used in RK2 calculations + INTEGER(IntKi) :: NdtM ! the number of time steps to make with the mooring model + Real(DbKi) :: dtM ! the actual time step size to use + INTEGER(IntKi) :: Nx ! size of states vector + INTEGER(IntKi) :: I ! counter + INTEGER(IntKi) :: J ! counter + TYPE(MD_InputType) :: u_interp ! interpolated instantaneous input values to be calculated for each mooring time step + + Real(DbKi) :: tDbKi ! double version because that's what MD_Input_ExtrapInterp needs. + + + ! allocate space for x2 + CALL MD_CopyContState( x, x2, 0, ErrStat, ErrMsg) + + ! create space for arrays/meshes in u_interp ... is it efficient to do this every time step??? + CALL MD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) + + + Nx = size(x%states) + + + ! round dt to integer number of time steps + NdtM = ceiling(dtStep/p%dtM0) ! get number of mooring time steps to do based on desired time step size + dtM = dtStep/float(NdtM) ! adjust desired time step to satisfy dt with an integer number of time steps + + + !loop through line integration time steps + DO I = 1, NdtM ! for (double ts=t; ts<=t+ICdt-dts; ts+=dts) + + + !tDbKi = t ! get DbKi version of current time (why does ExtrapInterp except different time type than UpdateStates?) + + + ! ------------------------------------------------------------------------------- + ! RK2 integrator written here, now calling CalcContStateDeriv + !-------------------------------------------------------------------------------- + + ! step 1 + + CALL MD_Input_ExtrapInterp(u, utimes, u_interp, t , ErrStat, ErrMsg) ! interpolate input mesh to correct time (t) + + CALL MD_CalcContStateDeriv( t, u_interp, p, x, xd, z, other, m, dxdt, ErrStat, ErrMsg ) + DO J = 1, Nx + x2%states(J) = x%states(J) + 0.5*dtM*dxdt%states(J) !x1 = x0 + dt*f0/2.0; + END DO + + ! step 2 + + CALL MD_Input_ExtrapInterp(u, utimes, u_interp, t + 0.5_DbKi*dtM, ErrStat, ErrMsg) ! interpolate input mesh to correct time (t+0.5*dtM) + + CALL MD_CalcContStateDeriv( (t + 0.5_ReKi*dtM), u_interp, p, x2, xd, z, other, m, dxdt, ErrStat, ErrMsg ) !called with updated states x2 and time = t + dt/2.0 + DO J = 1, Nx + x%states(J) = x%states(J) + dtM*dxdt%states(J) + END DO + + t = t + dtM ! update time + + !print *, " In TimeStep t=", t, ", L1N8Pz=", M%LineList(1)%r(3,8), ", dL1=", u_interp%DeltaL(1) + + !---------------------------------------------------------------------------------- + + ! >>> below should no longer be necessary thanks to using ExtrapInterp of u(:) within the mooring time stepping loop.. <<< + ! ! update Fairlead positions by integrating velocity and last position (do this AFTER the processing of the time step rather than before) + ! DO J = 1, p%NFairs + ! DO K = 1, 3 + ! m%ConnectList(m%FairIdList(J))%r(K) = m%ConnectList(m%FairIdList(J))%r(K) + m%ConnectList(m%FairIdList(J))%rd(K)*dtM + ! END DO + ! END DO + + + END DO ! I time steps + + + ! destroy dxdt and x2, and u_interp + CALL MD_DestroyContState( dxdt, ErrStat, ErrMsg) + CALL MD_DestroyContState( x2, ErrStat, ErrMsg) + CALL MD_DestroyInput(u_interp, ErrStat, ErrMsg) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error destroying dxdt or x2.' + END IF + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'MD_UpdateStates') + + + ! check for NaNs - is this a good place/way to do it? + DO J = 1, Nx + IF (Is_NaN(REAL(x%states(J),DbKi))) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' NaN state detected.' + END IF + END DO + + + END SUBROUTINE TimeStep + !====================================================================== + + + + !======================================================================= + SUBROUTINE SetupLine (Line, LineProp, rhoW, ErrStat, ErrMsg) + ! allocate arrays in line object + + TYPE(MD_Line), INTENT(INOUT) :: Line ! the single line object of interest + TYPE(MD_LineProp), INTENT(INOUT) :: LineProp ! the single line property set for the line of interest + REAL(ReKi), INTENT(IN) :: rhoW + INTEGER, INTENT( INOUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( INOUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(4) :: J ! Generic index + INTEGER(4) :: K ! Generic index + INTEGER(IntKi) :: N + + N = Line%N ! number of segments in this line (for code readability) + + ! allocate node positions and velocities (NOTE: these arrays start at ZERO) + ALLOCATE ( Line%r(3, 0:N), Line%rd(3, 0:N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating r and rd arrays.' + !CALL CleanUp() + RETURN + END IF + + ! allocate node tangent vectors + ALLOCATE ( Line%q(3, 0:N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating q array.' + !CALL CleanUp() + RETURN + END IF + + ! allocate segment scalar quantities + ALLOCATE ( Line%l(N), Line%ld(N), Line%lstr(N), Line%lstrd(N), Line%V(N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating segment scalar quantity arrays.' + !CALL CleanUp() + RETURN + END IF + + ! assign values for l and V + DO J=1,N + Line%l(J) = Line%UnstrLen/REAL(N, DbKi) + Line%ld(J)= 0.0_DbKi + Line%V(J) = Line%l(J)*0.25*Pi*LineProp%d*LineProp%d + END DO + + ! allocate segment tension and internal damping force vectors + ALLOCATE ( Line%T(3, N), Line%Td(3, N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating T and Td arrays.' + !CALL CleanUp() + RETURN + END IF + + ! allocate node force vectors + ALLOCATE ( Line%W(3, 0:N), Line%Dp(3, 0:N), Line%Dq(3, 0:N), Line%Ap(3, 0:N), & + Line%Aq(3, 0:N), Line%B(3, 0:N), Line%F(3, 0:N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating node force arrays.' + !CALL CleanUp() + RETURN + END IF + + ! set gravity and bottom contact forces to zero initially (because the horizontal components should remain at zero) + DO J = 0,N + DO K = 1,3 + Line%W(K,J) = 0.0_ReKi + Line%B(K,J) = 0.0_ReKi + END DO + END DO + + ! allocate mass and inverse mass matrices for each node (including ends) + ALLOCATE ( Line%S(3, 3, 0:N), Line%M(3, 3, 0:N), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating T and Td arrays.' + !CALL CleanUp() + RETURN + END IF + + ! Specify specific internal damping coefficient (BA) for this line. + ! Will be equal to inputted BA of LineType if input value is positive. + ! If input value is negative, it is considered to be desired damping ratio (zeta) + ! from which the line's BA can be calculated based on the segment natural frequency. + IF (LineProp%BA < 0) THEN + ! - we assume desired damping coefficient is zeta = -LineProp%BA + ! - highest axial vibration mode of a segment is wn = sqrt(k/m) = 2N/UnstrLen*sqrt(EA/w) + Line%BA = -LineProp%BA * Line%UnstrLen / Line%N * SQRT(LineProp%EA * LineProp%w) + ! print *, 'Based on zeta, BA set to ', Line%BA + + ! print *, 'Negative BA input detected, treating as -zeta. For zeta = ', -LineProp%BA, ', setting BA to ', Line%BA + + ELSE + Line%BA = LineProp%BA + ! temp = Line%N * Line%BA / Line%UnstrLen * SQRT(1.0/(LineProp%EA * LineProp%w)) + ! print *, 'BA set as input to ', Line%BA, '. Corresponding zeta is ', temp + END IF + + !temp = 2*Line%N / Line%UnstrLen * sqrt( LineProp%EA / LineProp%w) / TwoPi + !print *, 'Segment natural frequency is ', temp, ' Hz' + + + ! need to add cleanup sub <<< + + + END SUBROUTINE SetupLine + !====================================================================== + + + + + !=============================================================================================== + SUBROUTINE InitializeLine (Line, LineProp, rhoW, ErrStat, ErrMsg) + ! calculate initial profile of the line using quasi-static model + + TYPE(MD_Line), INTENT(INOUT) :: Line ! the single line object of interest + TYPE(MD_LineProp), INTENT(INOUT) :: LineProp ! the single line property set for the line of interest + REAL(ReKi), INTENT(IN) :: rhoW + INTEGER, INTENT( INOUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( INOUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi) :: COSPhi ! Cosine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) + REAL(ReKi) :: SINPhi ! Sine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) + REAL(ReKi) :: XF ! Horizontal distance between anchor and fairlead of the current mooring line (meters) + REAL(ReKi) :: ZF ! Vertical distance between anchor and fairlead of the current mooring line (meters) + INTEGER(4) :: I ! Generic index + INTEGER(4) :: J ! Generic index + + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + REAL(ReKi) :: WetWeight + REAL(ReKi) :: SeabedCD = 0.0_ReKi + REAL(ReKi) :: TenTol = 0.0001_ReKi + REAL(ReKi), ALLOCATABLE :: LSNodes(:) + REAL(ReKi), ALLOCATABLE :: LNodesX(:) + REAL(ReKi), ALLOCATABLE :: LNodesZ(:) + INTEGER(IntKi) :: N + + + N = Line%N ! for convenience + + ! try to calculate initial line profile using catenary routine (from FAST v.7) + ! note: much of this function is adapted from the FAST source code + + ! Transform the fairlead location from the inertial frame coordinate system + ! to the local coordinate system of the current line (this coordinate + ! system lies at the current anchor, Z being vertical, and X directed from + ! current anchor to the current fairlead). Also, compute the orientation + ! of this local coordinate system: + + XF = SQRT( ( Line%r(1,N) - Line%r(1,0) )**2.0 + ( Line%r(2,N) - Line%r(2,0) )**2.0 ) + ZF = Line%r(3,N) - Line%r(3,0) + + IF ( XF == 0.0 ) THEN ! .TRUE. if the current mooring line is exactly vertical; thus, the solution below is ill-conditioned because the orientation is undefined; so set it such that the tensions and nodal positions are only vertical + COSPhi = 0.0_ReKi + SINPhi = 0.0_ReKi + ELSE ! The current mooring line must not be vertical; use simple trigonometry + COSPhi = ( Line%r(1,N) - Line%r(1,0) )/XF + SINPhi = ( Line%r(2,N) - Line%r(2,0) )/XF + ENDIF + + WetWeight = LineProp%w - 0.25*Pi*LineProp%d*LineProp%d*rhoW + + !LineNodes = Line%N + 1 ! number of nodes in line for catenary model to worry about + + ! allocate temporary arrays for catenary routine + ALLOCATE ( LSNodes(N+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating LSNodes array.' + CALL CleanUp() + RETURN + END IF + + ALLOCATE ( LNodesX(N+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating LNodesX array.' + CALL CleanUp() + RETURN + END IF + + ALLOCATE ( LNodesZ(N+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating LNodesZ array.' + CALL CleanUp() + RETURN + END IF + + ! Assign node arc length locations + LSNodes(1) = 0.0_ReKi + DO I=2,N + LSNodes(I) = LSNodes(I-1) + Line%l(I-1) ! note: l index is because line segment indices start at 1 + END DO + LSNodes(N+1) = Line%UnstrLen ! ensure the last node length isn't longer than the line due to numerical error + + ! Solve the analytical, static equilibrium equations for a catenary (or + ! taut) mooring line with seabed interaction in order to find the + ! horizontal and vertical tensions at the fairlead in the local coordinate + ! system of the current line: + ! NOTE: The values for the horizontal and vertical tensions at the fairlead + ! from the previous time step are used as the initial guess values at + ! at this time step (because the LAnchHTe(:) and LAnchVTe(:) arrays + ! are stored in a module and thus their values are saved from CALL to + ! CALL). + + + CALL Catenary ( XF , ZF , Line%UnstrLen, LineProp%EA , & + WetWeight , SeabedCD, TenTol, (N+1) , & + LSNodes, LNodesX, LNodesZ , ErrStat2, ErrMsg2) + + IF (ErrStat2 == ErrID_None) THEN ! if it worked, use it + ! Transform the positions of each node on the current line from the local + ! coordinate system of the current line to the inertial frame coordinate + ! system: + + DO J = 0,Line%N ! Loop through all nodes per line where the line position and tension can be output + Line%r(1,J) = Line%r(1,0) + LNodesX(J+1)*COSPhi + Line%r(2,J) = Line%r(2,0) + LNodesX(J+1)*SINPhi + Line%r(3,J) = Line%r(3,0) + LNodesZ(J+1) + ENDDO ! J - All nodes per line where the line position and tension can be output + + + ELSE ! if there is a problem with the catenary approach, just stretch the nodes linearly between fairlead and anchor + + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'InitializeLine') + + DO J = 0,Line%N ! Loop through all nodes per line where the line position and tension can be output + Line%r(1,J) = Line%r(1,0) + (Line%r(1,N) - Line%r(1,0))*REAL(J, ReKi)/REAL(N, ReKi) + Line%r(2,J) = Line%r(2,0) + (Line%r(2,N) - Line%r(2,0))*REAL(J, ReKi)/REAL(N, ReKi) + Line%r(3,J) = Line%r(3,0) + (Line%r(3,N) - Line%r(3,0))*REAL(J, ReKi)/REAL(N, ReKi) + ENDDO + ENDIF + + + + CALL CleanUp() ! deallocate temporary arrays + + + + CONTAINS + + + !======================================================================= + SUBROUTINE CleanUp() + ! deallocate temporary arrays + + IF (ALLOCATED(LSNodes)) DEALLOCATE(LSNodes) + IF (ALLOCATED(LNodesX)) DEALLOCATE(LNodesX) + IF (ALLOCATED(LNodesZ)) DEALLOCATE(LNodesZ) + + END SUBROUTINE CleanUp + !======================================================================= + + + !======================================================================= + SUBROUTINE Catenary ( XF_In, ZF_In, L_In , EA_In, & + W_In , CB_In, Tol_In, N , & + s_In , X_In , Z_In , ErrStat, ErrMsg ) + + ! This subroutine is copied from FAST v7 with minor modifications + + ! This routine solves the analytical, static equilibrium equations + ! for a catenary (or taut) mooring line with seabed interaction. + ! Stretching of the line is accounted for, but bending stiffness + ! is not. Given the mooring line properties and the fairlead + ! position relative to the anchor, this routine finds the line + ! configuration and tensions. Since the analytical solution + ! involves two nonlinear equations (XF and ZF) in two unknowns + ! (HF and VF), a Newton-Raphson iteration scheme is implemented in + ! order to solve for the solution. The values of HF and VF that + ! are passed into this routine are used as the initial guess in + ! the iteration. The Newton-Raphson iteration is only accurate in + ! double precision, so all of the input/output arguments are + ! converteds to/from double precision from/to default precision. + + + ! USE Precision + + + IMPLICIT NONE + + + ! Passed Variables: + + INTEGER(4), INTENT(IN ) :: N ! Number of nodes where the line position and tension can be output (-) + + REAL(ReKi), INTENT(IN ) :: CB_In ! Coefficient of seabed static friction drag (a negative value indicates no seabed) (-) + REAL(ReKi), INTENT(IN ) :: EA_In ! Extensional stiffness of line (N) + ! REAL(ReKi), INTENT( OUT) :: HA_In ! Effective horizontal tension in line at the anchor (N) + ! REAL(ReKi), INTENT(INOUT) :: HF_In ! Effective horizontal tension in line at the fairlead (N) + REAL(ReKi), INTENT(IN ) :: L_In ! Unstretched length of line (meters) + REAL(ReKi), INTENT(IN ) :: s_In (N) ! Unstretched arc distance along line from anchor to each node where the line position and tension can be output (meters) + ! REAL(ReKi), INTENT( OUT) :: Te_In (N) ! Effective line tensions at each node (N) + REAL(ReKi), INTENT(IN ) :: Tol_In ! Convergence tolerance within Newton-Raphson iteration specified as a fraction of tension (-) + ! REAL(ReKi), INTENT( OUT) :: VA_In ! Effective vertical tension in line at the anchor (N) + ! REAL(ReKi), INTENT(INOUT) :: VF_In ! Effective vertical tension in line at the fairlead (N) + REAL(ReKi), INTENT(IN ) :: W_In ! Weight of line in fluid per unit length (N/m) + REAL(ReKi), INTENT( OUT) :: X_In (N) ! Horizontal locations of each line node relative to the anchor (meters) + REAL(ReKi), INTENT(IN ) :: XF_In ! Horizontal distance between anchor and fairlead (meters) + REAL(ReKi), INTENT( OUT) :: Z_In (N) ! Vertical locations of each line node relative to the anchor (meters) + REAL(ReKi), INTENT(IN ) :: ZF_In ! Vertical distance between anchor and fairlead (meters) + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local Variables: + + REAL(DbKi) :: CB ! Coefficient of seabed static friction (a negative value indicates no seabed) (-) + REAL(DbKi) :: CBOvrEA ! = CB/EA + REAL(DbKi) :: DET ! Determinant of the Jacobian matrix (m^2/N^2) + REAL(DbKi) :: dHF ! Increment in HF predicted by Newton-Raphson (N) + REAL(DbKi) :: dVF ! Increment in VF predicted by Newton-Raphson (N) + REAL(DbKi) :: dXFdHF ! Partial derivative of the calculated horizontal distance with respect to the horizontal fairlead tension (m/N): dXF(HF,VF)/dHF + REAL(DbKi) :: dXFdVF ! Partial derivative of the calculated horizontal distance with respect to the vertical fairlead tension (m/N): dXF(HF,VF)/dVF + REAL(DbKi) :: dZFdHF ! Partial derivative of the calculated vertical distance with respect to the horizontal fairlead tension (m/N): dZF(HF,VF)/dHF + REAL(DbKi) :: dZFdVF ! Partial derivative of the calculated vertical distance with respect to the vertical fairlead tension (m/N): dZF(HF,VF)/dVF + REAL(DbKi) :: EA ! Extensional stiffness of line (N) + REAL(DbKi) :: EXF ! Error function between calculated and known horizontal distance (meters): XF(HF,VF) - XF + REAL(DbKi) :: EZF ! Error function between calculated and known vertical distance (meters): ZF(HF,VF) - ZF + REAL(DbKi) :: HA ! Effective horizontal tension in line at the anchor (N) + REAL(DbKi) :: HF ! Effective horizontal tension in line at the fairlead (N) + REAL(DbKi) :: HFOvrW ! = HF/W + REAL(DbKi) :: HFOvrWEA ! = HF/WEA + REAL(DbKi) :: L ! Unstretched length of line (meters) + REAL(DbKi) :: Lamda0 ! Catenary parameter used to generate the initial guesses of the horizontal and vertical tensions at the fairlead for the Newton-Raphson iteration (-) + REAL(DbKi) :: LMax ! Maximum stretched length of the line with seabed interaction beyond which the line would have to double-back on itself; here the line forms an "L" between the anchor and fairlead (i.e. it is horizontal along the seabed from the anchor, then vertical to the fairlead) (meters) + REAL(DbKi) :: LMinVFOvrW ! = L - VF/W + REAL(DbKi) :: LOvrEA ! = L/EA + REAL(DbKi) :: s (N) ! Unstretched arc distance along line from anchor to each node where the line position and tension can be output (meters) + REAL(DbKi) :: sOvrEA ! = s(I)/EA + REAL(DbKi) :: SQRT1VFOvrHF2 ! = SQRT( 1.0_DbKi + VFOvrHF2 ) + REAL(DbKi) :: SQRT1VFMinWLOvrHF2 ! = SQRT( 1.0_DbKi + VFMinWLOvrHF2 ) + REAL(DbKi) :: SQRT1VFMinWLsOvrHF2 ! = SQRT( 1.0_DbKi + VFMinWLsOvrHF*VFMinWLsOvrHF ) + REAL(DbKi) :: Te (N) ! Effective line tensions at each node (N) + REAL(DbKi) :: Tol ! Convergence tolerance within Newton-Raphson iteration specified as a fraction of tension (-) + REAL(DbKi) :: VA ! Effective vertical tension in line at the anchor (N) + REAL(DbKi) :: VF ! Effective vertical tension in line at the fairlead (N) + REAL(DbKi) :: VFMinWL ! = VF - WL + REAL(DbKi) :: VFMinWLOvrHF ! = VFMinWL/HF + REAL(DbKi) :: VFMinWLOvrHF2 ! = VFMinWLOvrHF*VFMinWLOvrHF + REAL(DbKi) :: VFMinWLs ! = VFMinWL + Ws + REAL(DbKi) :: VFMinWLsOvrHF ! = VFMinWLs/HF + REAL(DbKi) :: VFOvrHF ! = VF/HF + REAL(DbKi) :: VFOvrHF2 ! = VFOvrHF*VFOvrHF + REAL(DbKi) :: VFOvrWEA ! = VF/WEA + REAL(DbKi) :: W ! Weight of line in fluid per unit length (N/m) + REAL(DbKi) :: WEA ! = W*EA + REAL(DbKi) :: WL ! Total weight of line in fluid (N): W*L + REAL(DbKi) :: Ws ! = W*s(I) + REAL(DbKi) :: X (N) ! Horizontal locations of each line node relative to the anchor (meters) + REAL(DbKi) :: XF ! Horizontal distance between anchor and fairlead (meters) + REAL(DbKi) :: XF2 ! = XF*XF + REAL(DbKi) :: Z (N) ! Vertical locations of each line node relative to the anchor (meters) + REAL(DbKi) :: ZF ! Vertical distance between anchor and fairlead (meters) + REAL(DbKi) :: ZF2 ! = ZF*ZF + + INTEGER(4) :: I ! Index for counting iterations or looping through line nodes (-) + INTEGER(4) :: MaxIter ! Maximum number of Newton-Raphson iterations possible before giving up (-) + + LOGICAL :: FirstIter ! Flag to determine whether or not this is the first time through the Newton-Raphson interation (flag) + + + ErrStat = ERrId_None + + + ! The Newton-Raphson iteration is only accurate in double precision, so + ! convert the input arguments into double precision: + + CB = REAL( CB_In , DbKi ) + EA = REAL( EA_In , DbKi ) + HF = 0.0_DbKi ! = REAL( HF_In , DbKi ) + L = REAL( L_In , DbKi ) + s (:) = REAL( s_In (:), DbKi ) + Tol = REAL( Tol_In , DbKi ) + VF = 0.0_DbKi ! keeping this for some error catching functionality? (at first glance) ! VF = REAL( VF_In , DbKi ) + W = REAL( W_In , DbKi ) + XF = REAL( XF_In , DbKi ) + ZF = REAL( ZF_In , DbKi ) + + + + ! HF and VF cannot be initialized to zero when a portion of the line rests on the seabed and the anchor tension is nonzero + + ! Generate the initial guess values for the horizontal and vertical tensions + ! at the fairlead in the Newton-Raphson iteration for the catenary mooring + ! line solution. Use starting values documented in: Peyrot, Alain H. and + ! Goulois, A. M., "Analysis Of Cable Structures," Computers & Structures, + ! Vol. 10, 1979, pp. 805-813: + XF2 = XF*XF + ZF2 = ZF*ZF + + IF ( XF == 0.0_DbKi ) THEN ! .TRUE. if the current mooring line is exactly vertical + Lamda0 = 1.0D+06 + ELSEIF ( L <= SQRT( XF2 + ZF2 ) ) THEN ! .TRUE. if the current mooring line is taut + Lamda0 = 0.2_DbKi + ELSE ! The current mooring line must be slack and not vertical + Lamda0 = SQRT( 3.0_DbKi*( ( L**2 - ZF2 )/XF2 - 1.0_DbKi ) ) + ENDIF + + HF = ABS( 0.5_DbKi*W* XF/ Lamda0 ) + VF = 0.5_DbKi*W*( ZF/TANH(Lamda0) + L ) + + + ! Abort when there is no solution or when the only possible solution is + ! illogical: + + IF ( Tol <= EPSILON(TOL) ) THEN ! .TRUE. when the convergence tolerance is specified incorrectly + ErrStat = ErrID_Warn + ErrMsg = ' Convergence tolerance must be greater than zero in routine Catenary().' + return + ELSEIF ( XF < 0.0_DbKi ) THEN ! .TRUE. only when the local coordinate system is not computed correctly + ErrStat = ErrID_Warn + ErrMsg = ' The horizontal distance between an anchor and its'// & + ' fairlead must not be less than zero in routine Catenary().' + return + + ELSEIF ( ZF < 0.0_DbKi ) THEN ! .TRUE. if the fairlead has passed below its anchor + ErrStat = ErrID_Warn + ErrMsg = ' A fairlead has passed below its anchor.' + return + + ELSEIF ( L <= 0.0_DbKi ) THEN ! .TRUE. when the unstretched line length is specified incorrectly + ErrStat = ErrID_Warn + ErrMsg = ' Unstretched length of line must be greater than zero in routine Catenary().' + return + + ELSEIF ( EA <= 0.0_DbKi ) THEN ! .TRUE. when the unstretched line length is specified incorrectly + ErrStat = ErrID_Warn + ErrMsg = ' Extensional stiffness of line must be greater than zero in routine Catenary().' + return + + ELSEIF ( W == 0.0_DbKi ) THEN ! .TRUE. when the weight of the line in fluid is zero so that catenary solution is ill-conditioned + ErrStat = ErrID_Warn + ErrMsg = ' The weight of the line in fluid must not be zero. '// & + ' Routine Catenary() cannot solve quasi-static mooring line solution.' + return + + + ELSEIF ( W > 0.0_DbKi ) THEN ! .TRUE. when the line will sink in fluid + + LMax = XF - EA/W + SQRT( (EA/W)*(EA/W) + 2.0_DbKi*ZF*EA/W ) ! Compute the maximum stretched length of the line with seabed interaction beyond which the line would have to double-back on itself; here the line forms an "L" between the anchor and fairlead (i.e. it is horizontal along the seabed from the anchor, then vertical to the fairlead) + + IF ( ( L >= LMax ) .AND. ( CB >= 0.0_DbKi ) ) then ! .TRUE. if the line is as long or longer than its maximum possible value with seabed interaction + ErrStat = ErrID_Warn + ErrMsg = ' Unstretched mooring line length too large. '// & + ' Routine Catenary() cannot solve quasi-static mooring line solution.' + return + END IF + + ENDIF + + + ! Initialize some commonly used terms that don't depend on the iteration: + + WL = W *L + WEA = W *EA + LOvrEA = L /EA + CBOvrEA = CB /EA + MaxIter = INT(1.0_DbKi/Tol) ! Smaller tolerances may take more iterations, so choose a maximum inversely proportional to the tolerance + + + + ! To avoid an ill-conditioned situation, ensure that the initial guess for + ! HF is not less than or equal to zero. Similarly, avoid the problems + ! associated with having exactly vertical (so that HF is zero) or exactly + ! horizontal (so that VF is zero) lines by setting the minimum values + ! equal to the tolerance. This prevents us from needing to implement + ! the known limiting solutions for vertical or horizontal lines (and thus + ! complicating this routine): + + HF = MAX( HF, Tol ) + XF = MAX( XF, Tol ) + ZF = MAX( ZF, TOl ) + + + + ! Solve the analytical, static equilibrium equations for a catenary (or + ! taut) mooring line with seabed interaction: + + ! Begin Newton-Raphson iteration: + + I = 1 ! Initialize iteration counter + FirstIter = .TRUE. ! Initialize iteration flag + + DO + + + ! Initialize some commonly used terms that depend on HF and VF: + + VFMinWL = VF - WL + LMinVFOvrW = L - VF/W + HFOvrW = HF/W + HFOvrWEA = HF/WEA + VFOvrWEA = VF/WEA + VFOvrHF = VF/HF + VFMinWLOvrHF = VFMinWL/HF + VFOvrHF2 = VFOvrHF *VFOvrHF + VFMinWLOvrHF2 = VFMinWLOvrHF*VFMinWLOvrHF + SQRT1VFOvrHF2 = SQRT( 1.0_DbKi + VFOvrHF2 ) + SQRT1VFMinWLOvrHF2 = SQRT( 1.0_DbKi + VFMinWLOvrHF2 ) + + + ! Compute the error functions (to be zeroed) and the Jacobian matrix + ! (these depend on the anticipated configuration of the mooring line): + + IF ( ( CB < 0.0_DbKi ) .OR. ( W < 0.0_DbKi ) .OR. ( VFMinWL > 0.0_DbKi ) ) THEN ! .TRUE. when no portion of the line rests on the seabed + + EXF = ( LOG( VFOvrHF + SQRT1VFOvrHF2 ) & + - LOG( VFMinWLOvrHF + SQRT1VFMinWLOvrHF2 ) )*HFOvrW & + + LOvrEA* HF - XF + EZF = ( SQRT1VFOvrHF2 & + - SQRT1VFMinWLOvrHF2 )*HFOvrW & + + LOvrEA*( VF - 0.5_DbKi*WL ) - ZF + + dXFdHF = ( LOG( VFOvrHF + SQRT1VFOvrHF2 ) & + - LOG( VFMinWLOvrHF + SQRT1VFMinWLOvrHF2 ) )/ W & + - ( ( VFOvrHF + VFOvrHF2 /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) & + - ( VFMinWLOvrHF + VFMinWLOvrHF2/SQRT1VFMinWLOvrHF2 )/( VFMinWLOvrHF + SQRT1VFMinWLOvrHF2 ) )/ W & + + LOvrEA + dXFdVF = ( ( 1.0_DbKi + VFOvrHF /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) & + - ( 1.0_DbKi + VFMinWLOvrHF /SQRT1VFMinWLOvrHF2 )/( VFMinWLOvrHF + SQRT1VFMinWLOvrHF2 ) )/ W + dZFdHF = ( SQRT1VFOvrHF2 & + - SQRT1VFMinWLOvrHF2 )/ W & + - ( VFOvrHF2 /SQRT1VFOvrHF2 & + - VFMinWLOvrHF2/SQRT1VFMinWLOvrHF2 )/ W + dZFdVF = ( VFOvrHF /SQRT1VFOvrHF2 & + - VFMinWLOvrHF /SQRT1VFMinWLOvrHF2 )/ W & + + LOvrEA + + + ELSEIF ( -CB*VFMinWL < HF ) THEN ! .TRUE. when a portion of the line rests on the seabed and the anchor tension is nonzero + + EXF = LOG( VFOvrHF + SQRT1VFOvrHF2 ) *HFOvrW & + - 0.5_DbKi*CBOvrEA*W* LMinVFOvrW*LMinVFOvrW & + + LOvrEA* HF + LMinVFOvrW - XF + EZF = ( SQRT1VFOvrHF2 - 1.0_DbKi )*HFOvrW & + + 0.5_DbKi*VF*VFOvrWEA - ZF + + dXFdHF = LOG( VFOvrHF + SQRT1VFOvrHF2 ) / W & + - ( ( VFOvrHF + VFOvrHF2 /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) )/ W & + + LOvrEA + dXFdVF = ( ( 1.0_DbKi + VFOvrHF /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) )/ W & + + CBOvrEA*LMinVFOvrW - 1.0_DbKi/W + dZFdHF = ( SQRT1VFOvrHF2 - 1.0_DbKi & + - VFOvrHF2 /SQRT1VFOvrHF2 )/ W + dZFdVF = ( VFOvrHF /SQRT1VFOvrHF2 )/ W & + + VFOvrWEA + + + ELSE ! 0.0_DbKi < HF <= -CB*VFMinWL ! A portion of the line must rest on the seabed and the anchor tension is zero + + EXF = LOG( VFOvrHF + SQRT1VFOvrHF2 ) *HFOvrW & + - 0.5_DbKi*CBOvrEA*W*( LMinVFOvrW*LMinVFOvrW - ( LMinVFOvrW - HFOvrW/CB )*( LMinVFOvrW - HFOvrW/CB ) ) & + + LOvrEA* HF + LMinVFOvrW - XF + EZF = ( SQRT1VFOvrHF2 - 1.0_DbKi )*HFOvrW & + + 0.5_DbKi*VF*VFOvrWEA - ZF + + dXFdHF = LOG( VFOvrHF + SQRT1VFOvrHF2 ) / W & + - ( ( VFOvrHF + VFOvrHF2 /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) )/ W & + + LOvrEA - ( LMinVFOvrW - HFOvrW/CB )/EA + dXFdVF = ( ( 1.0_DbKi + VFOvrHF /SQRT1VFOvrHF2 )/( VFOvrHF + SQRT1VFOvrHF2 ) )/ W & + + HFOvrWEA - 1.0_DbKi/W + dZFdHF = ( SQRT1VFOvrHF2 - 1.0_DbKi & + - VFOvrHF2 /SQRT1VFOvrHF2 )/ W + dZFdVF = ( VFOvrHF /SQRT1VFOvrHF2 )/ W & + + VFOvrWEA + + + ENDIF + + + ! Compute the determinant of the Jacobian matrix and the incremental + ! tensions predicted by Newton-Raphson: + + + DET = dXFdHF*dZFdVF - dXFdVF*dZFdHF + + if ( EqualRealNos( DET, 0.0_DbKi ) ) then +!bjj: there is a serious problem with the debugger here when DET = 0 + ErrStat = ErrID_Warn + ErrMsg = ' Iteration not convergent (DET is 0). '// & + ' Routine Catenary() cannot solve quasi-static mooring line solution.' + return + endif + + + dHF = ( -dZFdVF*EXF + dXFdVF*EZF )/DET ! This is the incremental change in horizontal tension at the fairlead as predicted by Newton-Raphson + dVF = ( dZFdHF*EXF - dXFdHF*EZF )/DET ! This is the incremental change in vertical tension at the fairlead as predicted by Newton-Raphson + + dHF = dHF*( 1.0_DbKi - Tol*I ) ! Reduce dHF by factor (between 1 at I = 1 and 0 at I = MaxIter) that reduces linearly with iteration count to ensure that we converge on a solution even in the case were we obtain a nonconvergent cycle about the correct solution (this happens, for example, if we jump to quickly between a taut and slack catenary) + dVF = dVF*( 1.0_DbKi - Tol*I ) ! Reduce dHF by factor (between 1 at I = 1 and 0 at I = MaxIter) that reduces linearly with iteration count to ensure that we converge on a solution even in the case were we obtain a nonconvergent cycle about the correct solution (this happens, for example, if we jump to quickly between a taut and slack catenary) + + dHF = MAX( dHF, ( Tol - 1.0_DbKi )*HF ) ! To avoid an ill-conditioned situation, make sure HF does not go less than or equal to zero by having a lower limit of Tol*HF [NOTE: the value of dHF = ( Tol - 1.0_DbKi )*HF comes from: HF = HF + dHF = Tol*HF when dHF = ( Tol - 1.0_DbKi )*HF] + + ! Check if we have converged on a solution, or restart the iteration, or + ! Abort if we cannot find a solution: + + IF ( ( ABS(dHF) <= ABS(Tol*HF) ) .AND. ( ABS(dVF) <= ABS(Tol*VF) ) ) THEN ! .TRUE. if we have converged; stop iterating! [The converge tolerance, Tol, is a fraction of tension] + + EXIT + + + ELSEIF ( ( I == MaxIter ) .AND. ( FirstIter ) ) THEN ! .TRUE. if we've iterated MaxIter-times for the first time; + + ! Perhaps we failed to converge because our initial guess was too far off. + ! (This could happen, for example, while linearizing a model via large + ! pertubations in the DOFs.) Instead, use starting values documented in: + ! Peyrot, Alain H. and Goulois, A. M., "Analysis Of Cable Structures," + ! Computers & Structures, Vol. 10, 1979, pp. 805-813: + ! NOTE: We don't need to check if the current mooring line is exactly + ! vertical (i.e., we don't need to check if XF == 0.0), because XF is + ! limited by the tolerance above. + + XF2 = XF*XF + ZF2 = ZF*ZF + + IF ( L <= SQRT( XF2 + ZF2 ) ) THEN ! .TRUE. if the current mooring line is taut + Lamda0 = 0.2_DbKi + ELSE ! The current mooring line must be slack and not vertical + Lamda0 = SQRT( 3.0_DbKi*( ( L*L - ZF2 )/XF2 - 1.0_DbKi ) ) + ENDIF + + HF = MAX( ABS( 0.5_DbKi*W* XF/ Lamda0 ), Tol ) ! As above, set the lower limit of the guess value of HF to the tolerance + VF = 0.5_DbKi*W*( ZF/TANH(Lamda0) + L ) + + + ! Restart Newton-Raphson iteration: + + I = 0 + FirstIter = .FALSE. + dHF = 0.0_DbKi + dVF = 0.0_DbKi + + + ELSEIF ( ( I == MaxIter ) .AND. ( .NOT. FirstIter ) ) THEN ! .TRUE. if we've iterated as much as we can take without finding a solution; Abort + ErrStat = ErrID_Warn + ErrMsg = ' Iteration not convergent. '// & + ' Routine Catenary() cannot solve quasi-static mooring line solution.' + RETURN + + + ENDIF + + + ! Increment fairlead tensions and iteration counter so we can try again: + + HF = HF + dHF + VF = VF + dVF + + I = I + 1 + + + ENDDO + + + + ! We have found a solution for the tensions at the fairlead! + + ! Now compute the tensions at the anchor and the line position and tension + ! at each node (again, these depend on the configuration of the mooring + ! line): + + IF ( ( CB < 0.0_DbKi ) .OR. ( W < 0.0_DbKi ) .OR. ( VFMinWL > 0.0_DbKi ) ) THEN ! .TRUE. when no portion of the line rests on the seabed + + ! Anchor tensions: + + HA = HF + VA = VFMinWL + + + ! Line position and tension at each node: + + DO I = 1,N ! Loop through all nodes where the line position and tension are to be computed + + IF ( ( s(I) < 0.0_DbKi ) .OR. ( s(I) > L ) ) THEN + ErrStat = ErrID_Warn + ErrMsg = ' All line nodes must be located between the anchor ' & + //'and fairlead (inclusive) in routine Catenary().' + RETURN + END IF + + Ws = W *s(I) ! Initialize + VFMinWLs = VFMinWL + Ws ! some commonly + VFMinWLsOvrHF = VFMinWLs/HF ! used terms + sOvrEA = s(I) /EA ! that depend + SQRT1VFMinWLsOvrHF2 = SQRT( 1.0_DbKi + VFMinWLsOvrHF*VFMinWLsOvrHF ) ! on s(I) + + X (I) = ( LOG( VFMinWLsOvrHF + SQRT1VFMinWLsOvrHF2 ) & + - LOG( VFMinWLOvrHF + SQRT1VFMinWLOvrHF2 ) )*HFOvrW & + + sOvrEA* HF + Z (I) = ( SQRT1VFMinWLsOvrHF2 & + - SQRT1VFMinWLOvrHF2 )*HFOvrW & + + sOvrEA*( VFMinWL + 0.5_DbKi*Ws ) + Te(I) = SQRT( HF*HF + VFMinWLs*VFMinWLs ) + + ENDDO ! I - All nodes where the line position and tension are to be computed + + + ELSEIF ( -CB*VFMinWL < HF ) THEN ! .TRUE. when a portion of the line rests on the seabed and the anchor tension is nonzero + + ! Anchor tensions: + + HA = HF + CB*VFMinWL + VA = 0.0_DbKi + + + ! Line position and tension at each node: + + DO I = 1,N ! Loop through all nodes where the line position and tension are to be computed + + IF ( ( s(I) < 0.0_DbKi ) .OR. ( s(I) > L ) ) THEN + ErrStat = ErrID_Warn + ErrMsg = ' All line nodes must be located between the anchor ' & + //'and fairlead (inclusive) in routine Catenary().' + RETURN + END IF + + Ws = W *s(I) ! Initialize + VFMinWLs = VFMinWL + Ws ! some commonly + VFMinWLsOvrHF = VFMinWLs/HF ! used terms + sOvrEA = s(I) /EA ! that depend + SQRT1VFMinWLsOvrHF2 = SQRT( 1.0_DbKi + VFMinWLsOvrHF*VFMinWLsOvrHF ) ! on s(I) + + IF ( s(I) <= LMinVFOvrW ) THEN ! .TRUE. if this node rests on the seabed and the tension is nonzero + + X (I) = s(I) & + + sOvrEA*( HF + CB*VFMinWL + 0.5_DbKi*Ws*CB ) + Z (I) = 0.0_DbKi + Te(I) = HF + CB*VFMinWLs + + ELSE ! LMinVFOvrW < s <= L ! This node must be above the seabed + + X (I) = LOG( VFMinWLsOvrHF + SQRT1VFMinWLsOvrHF2 ) *HFOvrW & + + sOvrEA* HF + LMinVFOvrW - 0.5_DbKi*CB*VFMinWL*VFMinWL/WEA + Z (I) = ( - 1.0_DbKi + SQRT1VFMinWLsOvrHF2 )*HFOvrW & + + sOvrEA*( VFMinWL + 0.5_DbKi*Ws ) + 0.5_DbKi* VFMinWL*VFMinWL/WEA + Te(I) = SQRT( HF*HF + VFMinWLs*VFMinWLs ) + + ENDIF + + ENDDO ! I - All nodes where the line position and tension are to be computed + + + ELSE ! 0.0_DbKi < HF <= -CB*VFMinWL ! A portion of the line must rest on the seabed and the anchor tension is zero + + ! Anchor tensions: + + HA = 0.0_DbKi + VA = 0.0_DbKi + + + ! Line position and tension at each node: + + DO I = 1,N ! Loop through all nodes where the line position and tension are to be computed + + IF ( ( s(I) < 0.0_DbKi ) .OR. ( s(I) > L ) ) THEN + ErrStat = ErrID_Warn + ErrMsg = ' All line nodes must be located between the anchor ' & + //'and fairlead (inclusive) in routine Catenary().' + RETURN + END IF + + Ws = W *s(I) ! Initialize + VFMinWLs = VFMinWL + Ws ! some commonly + VFMinWLsOvrHF = VFMinWLs/HF ! used terms + sOvrEA = s(I) /EA ! that depend + SQRT1VFMinWLsOvrHF2 = SQRT( 1.0_DbKi + VFMinWLsOvrHF*VFMinWLsOvrHF ) ! on s(I) + + IF ( s(I) <= LMinVFOvrW - HFOvrW/CB ) THEN ! .TRUE. if this node rests on the seabed and the tension is zero + + X (I) = s(I) + Z (I) = 0.0_DbKi + Te(I) = 0.0_DbKi + + ELSEIF ( s(I) <= LMinVFOvrW ) THEN ! .TRUE. if this node rests on the seabed and the tension is nonzero + + X (I) = s(I) - ( LMinVFOvrW - 0.5_DbKi*HFOvrW/CB )*HF/EA & + + sOvrEA*( HF + CB*VFMinWL + 0.5_DbKi*Ws*CB ) + 0.5_DbKi*CB*VFMinWL*VFMinWL/WEA + Z (I) = 0.0_DbKi + Te(I) = HF + CB*VFMinWLs + + ELSE ! LMinVFOvrW < s <= L ! This node must be above the seabed + + X (I) = LOG( VFMinWLsOvrHF + SQRT1VFMinWLsOvrHF2 ) *HFOvrW & + + sOvrEA* HF + LMinVFOvrW - ( LMinVFOvrW - 0.5_DbKi*HFOvrW/CB )*HF/EA + Z (I) = ( - 1.0_DbKi + SQRT1VFMinWLsOvrHF2 )*HFOvrW & + + sOvrEA*( VFMinWL + 0.5_DbKi*Ws ) + 0.5_DbKi* VFMinWL*VFMinWL/WEA + Te(I) = SQRT( HF*HF + VFMinWLs*VFMinWLs ) + + ENDIF + + ENDDO ! I - All nodes where the line position and tension are to be computed + + + ENDIF + + + + ! The Newton-Raphson iteration is only accurate in double precision, so + ! convert the output arguments back into the default precision for real + ! numbers: + + !HA_In = REAL( HA , ReKi ) !mth: for this I only care about returning node positions + !HF_In = REAL( HF , ReKi ) + !Te_In(:) = REAL( Te(:), ReKi ) + !VA_In = REAL( VA , ReKi ) + !VF_In = REAL( VF , ReKi ) + X_In (:) = REAL( X (:), ReKi ) + Z_In (:) = REAL( Z (:), ReKi ) + + END SUBROUTINE Catenary + !======================================================================= + + + END SUBROUTINE InitializeLine + !====================================================================== + + + + ! ============ below are some math convenience functions =============== + ! should add error checking if I keep these, but hopefully there are existing NWTCLib functions to replace them + + + ! return unit vector (u) in direction from r1 to r2 + !======================================================================= + SUBROUTINE UnitVector( u, r1, r2 ) + REAL(ReKi), INTENT(OUT) :: u(:) + REAL(ReKi), INTENT(IN) :: r1(:) + REAL(ReKi), INTENT(IN) :: r2(:) + + REAL(ReKi) :: Length + + u = r2 - r1 + Length = TwoNorm(u) + + if ( .NOT. EqualRealNos(length, 0.0_ReKi ) ) THEN + u = u / Length + END IF + + END SUBROUTINE UnitVector + !======================================================================= + + + !compute the inverse of a 3-by-3 matrix m + !======================================================================= + SUBROUTINE Inverse3by3( Minv, M ) + Real(ReKi), INTENT(OUT) :: Minv(:,:) ! returned inverse matrix + Real(ReKi), INTENT(IN) :: M(:,:) ! inputted matrix + + Real(ReKi) :: det ! the determinant + Real(ReKi) :: invdet ! inverse of the determinant + + det = M(1, 1) * (M(2, 2) * M(3, 3) - M(3, 2) * M(2, 3)) - & + M(1, 2) * (M(2, 1) * M(3, 3) - M(2, 3) * M(3, 1)) + & + M(1, 3) * (M(2, 1) * M(3, 2) - M(2, 2) * M(3, 1)); + + invdet = 1.0 / det ! because multiplying is faster than dividing + + Minv(1, 1) = (M(2, 2) * M(3, 3) - M(3, 2) * M(2, 3)) * invdet + Minv(1, 2) = (M(1, 3) * M(3, 2) - M(1, 2) * M(3, 3)) * invdet + Minv(1, 3) = (M(1, 2) * M(2, 3) - M(1, 3) * M(2, 2)) * invdet + Minv(2, 1) = (M(2, 3) * M(3, 1) - M(2, 1) * M(3, 3)) * invdet + Minv(2, 2) = (M(1, 1) * M(3, 3) - M(1, 3) * M(3, 1)) * invdet + Minv(2, 3) = (M(2, 1) * M(1, 3) - M(1, 1) * M(2, 3)) * invdet + Minv(3, 1) = (M(2, 1) * M(3, 2) - M(3, 1) * M(2, 2)) * invdet + Minv(3, 2) = (M(3, 1) * M(1, 2) - M(1, 1) * M(3, 2)) * invdet + Minv(3, 3) = (M(1, 1) * M(2, 2) - M(2, 1) * M(1, 2)) * invdet + + END SUBROUTINE Inverse3by3 + !======================================================================= + + +END MODULE MoorDyn diff --git a/OpenFAST/modules/moordyn/src/MoorDyn_Driver.f90 b/OpenFAST/modules/moordyn/src/MoorDyn_Driver.f90 new file mode 100644 index 000000000..99ad3b801 --- /dev/null +++ b/OpenFAST/modules/moordyn/src/MoorDyn_Driver.f90 @@ -0,0 +1,416 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2020 National Renewable Energy Laboratory +! Copyright (C) 2020 Matthew Hall +! +! This file is part of MoorDyn. +! +! 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. +! +!********************************************************************************************************************************** +PROGRAM MoorDyn_Driver + + USE MoorDyn_Types + USE MoorDyn + USE NWTC_Library + + IMPLICIT NONE + + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + TYPE (MD_InitInputType) :: MD_InitInput + TYPE (MD_ParameterType) :: MD_Parameter + TYPE (MD_ContinuousStateType) :: MD_ContinuousState + TYPE (MD_InitOutputType) :: MD_InitOutput + TYPE (MD_DiscreteStateType) :: MD_DiscreteState + TYPE (MD_ConstraintStateType) :: MD_ConstraintState + TYPE (MD_OtherStateType) :: MD_OtherState + TYPE (MD_MiscVarType) :: MD_MiscVar + + TYPE (MD_InputType), ALLOCATABLE :: MD_Input(:) + REAL(DbKi), DIMENSION(:), ALLOCATABLE :: MD_InputTimes + + TYPE (MD_OutputType) :: MD_Output ! Output file identifier + + INTEGER(IntKi) :: UnPtfmMotIn ! platform motion input file identifier + CHARACTER(100) :: Line ! String to temporarially hold value of read line + REAL(ReKi), ALLOCATABLE :: PtfmMotIn(:,:) ! Variable for storing time, and DOF time series from driver input file + REAL(ReKi), ALLOCATABLE :: PtfmMot(:,:) ! Variable for storing interpolated DOF time series from driver input file + INTEGER(IntKi) :: ntIn ! number of time steps read from driver input file + INTEGER(IntKi) :: ncIn ! number of channels read from driver input file + INTEGER(IntKi) :: nt ! number of coupling time steps to use in simulation + + REAL(DbKi) :: t ! current time (s) + REAL(DbKi) :: tMax ! sim end time (s) + REAL(DbKi) :: dtC ! fixed/constant global time step + REAL(DbKi) :: frac ! fraction used in interpolation + + INTEGER(IntKi) :: MD_interp_order ! order of interpolation/extrapolation + + ! Local variables + Integer(IntKi) :: i ! counter for various loops + Integer(IntKi) :: j ! counter for various loops + Integer(IntKi) :: k ! counter for various loops + Integer(IntKi) :: iIn + integer(intKi) :: Un + + CHARACTER(20) :: FlagArg ! flag argument from command line + CHARACTER(1024) :: PlatformInitInputFile + CHARACTER(200) :: git_commit ! String containing the current git commit hash + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'MoorDyn Driver', '', '' ) + + CALL NWTC_Init( ProgNameIn=version%Name ) + + MD_InitInput%FileName = "MoorDyn.dat" ! initialize to empty string to make sure it's input from the command line + CALL CheckArgs( MD_InitInput%FileName, Arg2=PlatformInitInputFile, Flag=FlagArg ) + IF ( LEN( TRIM(FlagArg) ) > 0 ) CALL NormStop() + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name, 'Copyright (C) 2020 Matthew Hall' ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + ! ------------------------------------------------------------------------- + ! Initialize MoorDyn + ! ------------------------------------------------------------------------- + + dtC = 0.01 ! desired coupling time step size for communicating with MoorDyn + + MD_interp_order = 0 + + ! MAP: allocate Input and Output arrays; used for interpolation and extrapolation + Allocate(MD_InputTimes(MD_interp_order + 1)) + + ! @bonnie : This is in the FAST developers glue code example, but it's probably not needed here. + Allocate(MD_Input(MD_interp_order + 1)) + + ! set the input file name and other environment terms. + !MD_InitInput%NStepWave = 1 ! an arbitrary number > 0 (to set the size of the wave data, which currently contains all zero values) + MD_InitInput%g = 9.81 ! This need to be according to g used in ElastoDyn + MD_InitInput%rhoW = 1025 ! This needs to be set according to seawater density in HydroDyn + MD_InitInput%PtfmInit = 0.0 + MD_InitInput%RootName = "MoorDyn.MD" + + CALL GetNewUnit( Un ) + OPEN(Unit=Un,FILE='MD.out',STATUS='UNKNOWN') + + ! call the initialization routine + CALL MD_Init( MD_InitInput , & + MD_Input(1) , & + MD_Parameter , & + MD_ContinuousState , & + MD_DiscreteState , & + MD_ConstraintState , & + MD_OtherState , & + MD_Output , & + MD_MiscVar , & + dtC , & + MD_InitOutput , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + CALL MD_DestroyInitInput ( MD_InitInput , ErrStat, ErrMsg ) + CALL MD_DestroyInitOutput ( MD_InitOutput , ErrStat, ErrMsg ) + + CALL DispNVD( MD_InitOutput%Ver ) + + ncIn = 6 + size(MD_Input(1)%DeltaL) ! determine number of input channels expected from driver input file time series (DOFs including active tensioning channels) + + + ! ------------------------------------------------------------------------- + ! Read in prescribed motions from text file if available + ! (single 6DOF platform for now, plus one active tensioning command) + ! (to be updated for versatile coupling in future) + ! ------------------------------------------------------------------------- + IF( LEN( TRIM(PlatformInitInputFile) ) < 1 ) THEN + ntIn = 0 ! flag to indicate no motion input file + print *, "No MoorDyn Driver input file provided, so using zero values." + + ELSE + CALL GetNewUnit( UnPtfmMotIn ) + + CALL OpenFInpFile ( UnPtfmMotIn, PlatformInitInputFile, ErrStat, ErrMsg ) + IF (ErrStat /= 0 ) THEN + print *, ErrStat, ErrMsg + STOP + ENDIF + + print *, "Reading platform motion input data from ", PlatformInitInputFile + + ! Read through length of file to find its length + i = 1 ! start counter + DO + READ(UnPtfmMotIn,'(A)',IOSTAT=ErrStat) Line !read into a line + + + IF (ErrStat /= 0) EXIT + + print *, TRIM(Line) + + i = i+1 + END DO + + ! rewind to start of input file to re-read things now that we know how long it is + REWIND(UnPtfmMotIn) + + ntIn = i-1 ! save number of lines of file + + + ! allocate space for input motion array (including time column) + ALLOCATE ( PtfmMotIn(ntIn, ncIn+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for PtfmMotIn array.' + CALL WrScr( ErrMsg ) + END IF + + ! read the data in from the file + DO i = 1, ntIn + READ (UnPtfmMotIn,*,IOSTAT=ErrStat) (PtfmMotIn (i,J), J=1,ncIn+1) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error reading the input time-series file. Expecting '//TRIM(Int2LStr(ncIn))//' channels plus time.' + CALL WrScr( ErrMsg ) + END IF + END DO + + ! Close the inputs file + CLOSE ( UnPtfmMotIn ) + + print *, "Read ", ntIn, " time steps from input file." + print *, PtfmMotIn + + END IF + + + ! ----------------------- specify stepping details ----------------------- + + IF (ntIn > 0) THEN + tMax = PtfmMotIn(ntIn, 1) ! save last time step as total sim time + ELSE + tMax = 60 + END IF + + + nt = tMax/dtC - 1 ! number of coupling time steps + + CALL WrScr(" ") + print *, "Tmax - ", tMax, " and nt=", nt + CALL WrScr(" ") + + ! allocate space for processed motion array + ALLOCATE ( PtfmMot(nt, ncIn), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for PtfmMot array.' + CALL WrScr( ErrMsg ) + END IF + + + ! go through and interpolate inputs to new regular time steps (if nt=0 this array should be left as zeros) + IF (ntIn > 0) THEN + DO i = 1,nt + + t = dtC*(i-1) + + ! interpolation routine + DO iIn = 1,ntIn-1 + IF (PtfmMotIn(iIn+1, 1) > t) THEN + frac = (t - PtfmMotIn(iIn, 1) )/( PtfmMotIn(iIn+1, 1) - PtfmMotIn(iIn, 1) ) + + ! print *, "t=", t, ", iIn=", iIn, ", frac=", frac + + DO J=1,ncIn + PtfmMot(i, J) = PtfmMotIn(iIn, J+1) + frac*(PtfmMotIn(iIn+1, J+1) - PtfmMotIn(iIn, J+1)) + END DO + + EXIT + END IF + END DO + + ! print *, t, "s", PtfmMot(i,:) + + END DO + + + ELSE + PtfmMot = 0.0_Reki + END IF + + + + + ! --------------------------------------------------------------- + ! Set the initial input values + ! --------------------------------------------------------------- + + ! start with zeros >>> or should this be the initial row of DOFs? <<< + MD_Input(1)%PtFairleadDisplacement%TranslationDisp = 0.0_ReKi + MD_Input(1)%DeltaL = 0.0_ReKi + MD_Input(1)%DeltaLdot = 0.0_ReKi + + DO i = 2, MD_interp_order + 1 + CALL MD_CopyInput( MD_Input(1), MD_Input(i), MESH_NEWCOPY, ErrStat, ErrMsg ) + END DO + + DO i = 1, MD_interp_order + 1 + MD_InputTimes(i) = -(i - 1) * dtC + ENDDO + + + t = 0 + + CALL MD_CalcOutput( t , & + MD_Input(1) , & + MD_Parameter , & + MD_ContinuousState , & + MD_DiscreteState , & + MD_ConstraintState , & + MD_OtherState , & + MD_Output , & + MD_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + + ! ------------------------------------------------------------------------- + ! BEGIN time marching >>> note that 3 rotational platform DOFs are currently neglected <<< + ! ------------------------------------------------------------------------- + + print *,"Doing time marching now..." + + DO i = 1,nt + + ! --------------------------------- update inputs --------------------------------- + + t = dtC*(i-1) + + MD_InputTimes(1) = t + dtC + !MD_InputTimes(2) = MD_InputTimes(1) - dtC + !MD_InputTimes(3) = MD_InputTimes(2) - dtC + + ! apply platform translations (neglecting rotations for now) + MD_Input(1)%PtFairleadDisplacement%TranslationDisp(1,1) = PtfmMot(i, 1) + MD_Input(1)%PtFairleadDisplacement%TranslationDisp(1,2) = PtfmMot(i, 2) + MD_Input(1)%PtFairleadDisplacement%TranslationDisp(1,3) = PtfmMot(i, 3) + + !MD_Input(2)%PtFairleadDisplacement%TranslationDisp(1,1) = .001*n_t_global + !MD_Input(3)%PtFairleadDisplacement%TranslationDisp(1,1) = .001*n_t_global + + ! what about velocities?? + + ! also provide any active tensioning commands (just using delta L, and finite differencing to get derivative) + DO j = 1,ncIn-6 + + MD_Input(1)%DeltaL(j) = PtfmMot(i, 6+j) + + IF (i>1) then + MD_Input(1)%DeltaLdot(j) = (PtfmMot(i, 6+j) - PtfmMot(i-1, 6+j))/dtC + ELSE + MD_Input(1)%DeltaLdot(j) = 0.0_ReKi + END IF + + END DO + + ! --------------------------------- update states --------------------------------- + CALL MD_UpdateStates( t , & + nt , & + MD_Input , & + MD_InputTimes , & + MD_Parameter , & + MD_ContinuousState , & + MD_DiscreteState , & + MD_ConstraintState , & + MD_OtherState , & + MD_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + EXIT + END IF + + ! update the global time step by one delta t <<<< ??? why? + t = t + dtC + + ! --------------------------------- calculate outputs --------------------------------- + CALL MD_CalcOutput( t , & + MD_Input(1) , & + MD_Parameter , & + MD_ContinuousState , & + MD_DiscreteState , & + MD_ConstraintState , & + MD_OtherState , & + MD_Output , & + MD_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + + WRITE(Un,100) t, MD_Input(1)%PtFairleadDisplacement%TranslationDisp(1,1), & + ((MD_Output%PtFairleadLoad%Force(k,j), k=1,3),j=1,3) + !WRITE(*,*) t_global + + END DO + + + ! ------------------------------------------------------------------------- + ! END time marching + ! ------------------------------------------------------------------------- + + ! Destroy all objects + CALL MD_End( MD_Input(1) , & + MD_Parameter , & + MD_ContinuousState , & + MD_DiscreteState , & + MD_ConstraintState , & + MD_OtherState , & + MD_Output , & + MD_MiscVar , & + ErrStat , & + ErrMsg ) + IF ( ErrStat .NE. ErrID_None ) THEN + IF (ErrStat >=AbortErrLev) CALL ProgAbort(ErrMsg) + CALL WrScr( ErrMsg ) + END IF + + do j = 2,MD_interp_order+1 + call MD_DestroyInput( MD_Input(j), ErrStat, ErrMsg) + end do + + DEALLOCATE(MD_Input) + DEALLOCATE(MD_InputTimes) + + IF (ALLOCATED(PtfmMot) ) DEALLOCATE(PtfmMot ) + IF (ALLOCATED(PtfmMotIn)) DEALLOCATE(PtfmMotIn) + + CALL WrScr( "Program has ended" ) + close (un) + +100 FORMAT(2(1X,F8.3),9(1X,E12.5)) + + END PROGRAM \ No newline at end of file diff --git a/OpenFAST/modules/moordyn/src/MoorDyn_IO.f90 b/OpenFAST/modules/moordyn/src/MoorDyn_IO.f90 new file mode 100644 index 000000000..e18d4b0ed --- /dev/null +++ b/OpenFAST/modules/moordyn/src/MoorDyn_IO.f90 @@ -0,0 +1,1347 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 Matthew Hall +! +! This file is part of MoorDyn. +! +! 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 MoorDyn_IO + + ! This MODULE stores variables used for input and output and provides i/o subs + + USE NWTC_Library + USE MoorDyn_Types + IMPLICIT NONE + + + PRIVATE + + ! --------------------------- Output definitions ----------------------------------------- + + ! The following are some definitions for use with the output options in MoorDyn. + ! These are for the global output quantities specified by OutList, not line-specific outputs. + ! Output definitions follow the structure described by the MD_OutParmType . + ! Each output channel is described by the following fields: + ! Name - (string) what appears at the top of the output column + ! Units - (string) selected from UnitList (see below) based on index QType + ! OType - (int) the type of object the output is from. 1=line, 2=connect (0=invalid) + ! ObjID - (int) the ID number of the line or connect + ! QType - (int) the type of quantity to output. 0=tension, 1=x pos, etc. see the parameters below + ! NodeID - (int) the ID number of the node of the output quantity + + ! These are the "OTypes": 0=Connect object, 1=Line Object + ! (will just use 0 and 1 rather than parameter names) + + ! Indices for computing output channels: - customized for the MD_OutParmType approach + ! these are the "QTypes" + INTEGER, PARAMETER :: Time = 0 + INTEGER, PARAMETER :: PosX = 1 + INTEGER, PARAMETER :: PosY = 2 + INTEGER, PARAMETER :: PosZ = 3 + INTEGER, PARAMETER :: VelX = 4 + INTEGER, PARAMETER :: VelY = 5 + INTEGER, PARAMETER :: VelZ = 6 + INTEGER, PARAMETER :: AccX = 7 + INTEGER, PARAMETER :: AccY = 8 + INTEGER, PARAMETER :: AccZ = 9 + INTEGER, PARAMETER :: Ten = 10 + INTEGER, PARAMETER :: FX = 11 + INTEGER, PARAMETER :: FY = 12 + INTEGER, PARAMETER :: FZ = 13 + + ! List of units corresponding to the quantities parameters for QTypes + CHARACTER(ChanLen), PARAMETER :: UnitList(0:13) = (/ & + "(s) ","(m) ","(m) ","(m) ", & + "(m/s) ","(m/s) ","(m/s) ", & + "(m/s2) ","(m/s2) ","(m/s2) ", & + "(N) ","(N) ","(N) ","(N) " /) + + CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + CHARACTER(28), PARAMETER :: OutSFmt = "ES10.3E2" + + + ! output naming scheme is as + ! examples: + ! FairTen1, AnchTen1 + ! Con1pX + ! Con3vY (connection 3, y velocity) + ! L2N4pX (line 2, node 4, x position) + + ! --------------------------------------------------------------------------------------------------------- + + + + + PUBLIC :: MDIO_ReadInput + PUBLIC :: MDIO_OpenOutput + PUBLIC :: MDIO_CloseOutput + PUBLIC :: MDIO_ProcessOutList + PUBLIC :: MDIO_WriteOutputs + + +CONTAINS + + + + + !==================================================================================================== + SUBROUTINE MDIO_ReadInput( InitInp, p, m, ErrStat, ErrMsg ) + + ! This subroutine reads the input required for MoorDyn from the file whose name is an + ! input parameter. It sets the size of p%NTypes, NConnects, and NLines, + ! allocates LineTypeList, ConnectList, and LineList, and puts all the read contents of + ! the input file into the respective slots in those lists of types. + + + ! Passed variables + + TYPE(MD_InitInputType), INTENT( INOUT ) :: InitInp ! the MoorDyn data + TYPE(MD_ParameterType), INTENT(INOUT) :: p ! Parameters + TYPE(MD_MiscVarType), INTENT( OUT) :: m ! INTENT( OUT) : Initial misc/optimization vars + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + + INTEGER :: I ! generic integer for counting + INTEGER :: J ! generic integer for counting + INTEGER :: UnIn ! Unit number for the input file + INTEGER :: UnEc ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFile ! Name of MoorDyn echo file + CHARACTER(1024) :: Line ! String to temporarially hold value of read line + CHARACTER(20) :: LineOutString ! String to temporarially hold characters specifying line output options + CHARACTER(20) :: OptString ! String to temporarially hold name of option variable + CHARACTER(20) :: OptValue ! String to temporarially hold value of options variable input + CHARACTER(1024) :: FileName ! + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MDIO_ReadInput' + + + ! + UnEc = -1 + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! Open the file + !------------------------------------------------------------------------------------------------- + FileName = TRIM(InitInp%FileName) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL WrScr( ' MD_Init: Opening MoorDyn input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'MoorDyn input file header line 1', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'MoorDyn input file header line 2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Echo Input Files. + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( InitInp%Echo ) THEN + + !print *, 'gonna try to open echo file' + + EchoFile = TRIM(p%RootName)//'.ech' ! open an echo file for writing + + !print *, 'name is ', EchoFile + + CALL GetNewUnit( UnEc ) + CALL OpenEcho ( UnEc, EchoFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + REWIND(UnIn) ! rewind to start of input file to re-read the first few lines + + + + + CALL ReadCom( UnIn, FileName, 'MoorDyn input file header line 1', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + CALL ReadCom( UnIn, FileName, 'MoorDyn input file header line 2', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + !print *, 'at end of echo if statement' + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Line Types Properties Section + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'Line types header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL ReadVar ( UnIn, FileName, p%NTypes, 'NTypes', 'Number of line types', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Table header + DO I = 1, 2 + CALL ReadCom( UnIn, FileName, 'Line types table header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END DO + + ! make sure NTypes isn't zero + IF ( p%NTypes < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'NTypes parameter must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + ! Allocate memory for LineTypeList array to hold line type properties + ALLOCATE ( m%LineTypeList(p%NTypes), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for LineTypeList array.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + ! read each line + DO I = 1,p%NTypes + ! read the table entries Name Diam MassDenInAir EA cIntDamp Can Cat Cdn Cdt in the MoorDyn input file + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) m%LineTypeList(I)%name, m%LineTypeList(I)%d, & + m%LineTypeList(I)%w, m%LineTypeList(I)%EA, m%LineTypeList(I)%BA, & + m%LineTypeList(I)%Can, m%LineTypeList(I)%Cat, m%LineTypeList(I)%Cdn, m%LineTypeList(I)%Cdt + END IF + + m%LineTypeList(I)%IdNum = I ! specify IdNum of line type for error checking + + + IF ( ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read line type properties for line '//trim(Num2LStr(I)), ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + IF ( InitInp%Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + + END DO + + + + !------------------------------------------------------------------------------------------------- + ! Connections Section + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'Connections header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL ReadVar ( UnIn, FileName, p%NConnects, 'NConnects', 'Number of Connects', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Table header + DO I = 1, 2 + CALL ReadCom( UnIn, FileName, 'Connects header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END DO + + ! make sure NConnects is at least two + IF ( p%NConnects < 2 ) THEN + ErrMsg = ' NConnects parameter must be at least 2.' + CALL CleanUp() + RETURN + END IF + + ! allocate ConnectList + ALLOCATE ( m%ConnectList(p%NConnects), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for ConnectList array.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + + ! read each line + DO I = 1,p%NConnects + ! read the table entries Node Type X Y Z M V FX FY FZ Cda Ca + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) m%ConnectList(I)%IdNum, m%ConnectList(I)%type, m%ConnectList(I)%conX, & + m%ConnectList(I)%conY, m%ConnectList(I)%conZ, m%ConnectList(I)%conM, & + m%ConnectList(I)%conV, m%ConnectList(I)%conFX, m%ConnectList(I)%conFY, & + m%ConnectList(I)%conFZ, m%ConnectList(I)%conCdA, m%ConnectList(I)%conCa + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL WrScr(' Unable to parse Connection '//trim(Num2LStr(I))//' row in input file.') ! Specific screen output because errors likely + CALL WrScr(' Ensure row has all 12 columns, including CdA and Ca.') ! to be caused by non-updated input file formats. + CALL SetErrStat( ErrID_Fatal, 'Failed to read connects.' , ErrStat, ErrMsg, RoutineName ) ! would be nice to specify which line <<<<<<<<< + CALL CleanUp() + RETURN + END IF + + ! check for sequential IdNums + IF ( m%ConnectList(I)%IdNum .NE. I ) THEN + CALL SetErrStat( ErrID_Fatal, 'Node numbers must be sequential starting from 1.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + + + + IF ( InitInp%Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + + END DO + + + !------------------------------------------------------------------------------------------------- + ! Lines Section + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'Lines header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL ReadVar ( UnIn, FileName, p%NLines, 'NLines', 'Number of Lines', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Table header + DO I = 1, 2 + CALL ReadCom( UnIn, FileName, 'Lines header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END DO + + ! make sure NLines is at least one + IF ( p%NLines < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'NLines parameter must be at least 1.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + ! allocate LineList + ALLOCATE ( m%LineList(p%NLines), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for LineList array.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + ! read each line + DO I = 1,p%NLines + ! read the table entries Line LineType UnstrLen NumSegs NodeAnch NodeFair Flags/Outputs + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) m%LineList(I)%IdNum, m%LineList(I)%type, m%LineList(I)%UnstrLen, & + m%LineList(I)%N, m%LineList(I)%AnchConnect, m%LineList(I)%FairConnect, LineOutString, m%LineList(I)%CtrlChan + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read line data for Line '//trim(Num2LStr(I)), ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + + ! check for sequential IdNums + IF ( m%LineList(I)%IdNum .NE. I ) THEN + CALL SetErrStat( ErrID_Fatal, 'Line numbers must be sequential starting from 1.', ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + END IF + + ! identify index of line type + DO J = 1,p%NTypes + IF (trim(m%LineList(I)%type) == trim(m%LineTypeList(J)%name)) THEN + m%LineList(I)%PropsIdNum = J + EXIT + IF (J == p%NTypes) THEN ! call an error if there is no match + CALL SetErrStat( ErrID_Severe, 'Unable to find matching line type name for Line '//trim(Num2LStr(I)), ErrStat, ErrMsg, RoutineName ) + END IF + END IF + END DO + + ! process output flag characters (LineOutString) and set line output flag array (OutFlagList) + m%LineList(I)%OutFlagList = 0 ! first set array all to zero + IF ( scan( LineOutString, 'p') > 0 ) m%LineList(I)%OutFlagList(2) = 1 + IF ( scan( LineOutString, 'v') > 0 ) m%LineList(I)%OutFlagList(3) = 1 + IF ( scan( LineOutString, 'U') > 0 ) m%LineList(I)%OutFlagList(4) = 1 + IF ( scan( LineOutString, 'D') > 0 ) m%LineList(I)%OutFlagList(5) = 1 + IF ( scan( LineOutString, 't') > 0 ) m%LineList(I)%OutFlagList(6) = 1 + IF ( scan( LineOutString, 'c') > 0 ) m%LineList(I)%OutFlagList(7) = 1 + IF ( scan( LineOutString, 's') > 0 ) m%LineList(I)%OutFlagList(8) = 1 + IF ( scan( LineOutString, 'd') > 0 ) m%LineList(I)%OutFlagList(9) = 1 + IF ( scan( LineOutString, 'l') > 0 ) m%LineList(I)%OutFlagList(10)= 1 + IF (SUM(m%LineList(I)%OutFlagList) > 0) m%LineList(I)%OutFlagList(1) = 1 ! this first entry signals whether to create any output file at all + ! the above letter-index combinations define which OutFlagList entry corresponds to which output type + + + ! check errors + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read line data for Line '//trim(Num2LStr(I)) + CALL CleanUp() + RETURN + END IF + + + IF ( InitInp%Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + + END DO ! I + + + !------------------------------------------------------------------------------------------------- + ! Read any options lines + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'Options header', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! loop through any remaining input lines, and use them to set options (overwriting default values in many cases). + ! doing this manually since I'm not sure that there is a built in subroutine for reading any input value on any line number. + DO + + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + + IF (ErrStat2 == 0) THEN + IF (( Line(1:3) == '---' ) .OR. ( Line(1:3) == 'END' ) .OR. ( Line(1:3) == 'end' )) EXIT ! check if it's the end line + + READ(Line,*,IOSTAT=ErrStat2) OptValue, OptString ! look at first two entries, ignore remaining words in line, which should be comments + END IF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Failed to read options.', ErrStat, ErrMsg, RoutineName ) ! would be nice to specify which line had the error + CALL CleanUp() + RETURN + END IF + + CALL Conv2UC(OptString) + + ! check all possible options types and see if OptString is one of them, in which case set the variable. + if ( OptString == 'DTM') THEN + read (OptValue,*) p%dtM0 ! InitInp%DTmooring + else if ( OptString == 'G') then + read (OptValue,*) p%G + else if ( OptString == 'RHOW') then + read (OptValue,*) p%rhoW + else if ( OptString == 'WTRDPTH') then + read (OptValue,*) p%WtrDpth + else if ( OptString == 'KBOT') then + read (OptValue,*) p%kBot + else if ( OptString == 'CBOT') then + read (OptValue,*) p%cBot + else if ( OptString == 'DTIC') then + read (OptValue,*) InitInp%dtIC + else if ( OptString == 'TMAXIC') then + read (OptValue,*) InitInp%TMaxIC + else if ( OptString == 'CDSCALEIC') then + read (OptValue,*) InitInp%CdScaleIC + else if ( OptString == 'THRESHIC') then + read (OptValue,*) InitInp%threshIC + else + CALL SetErrStat( ErrID_Warn, 'unable to interpret input '//trim(OptString), ErrStat, ErrMsg, RoutineName ) + end if + + IF ( InitInp%Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + + END DO + + + !------------------------------------------------------------------------------------------------- + ! Read the FAST-style outputs list in the final section, if there is one + !------------------------------------------------------------------------------------------------- + ! we don't read in the outputs header line because it's already been read in for detecting the end of the variable-length options section + ! CALL ReadCom( UnIn, FileName, 'Outputs header', ErrStat, ErrMsg, UnEc ) + + ! allocate InitInp%Outliest (to a really big number for now...) + CALL AllocAry( InitInp%OutList, 1000, "MoorDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList ( UnIn, FileName, InitInp%OutList, p%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + !print *, 'NumOuts is ', p%NumOuts + !print *, ' OutList is ', InitInp%OutList(1:p%NumOuts) + + + !------------------------------------------------------------------------------------------------- + ! This is the end of the input file + !------------------------------------------------------------------------------------------------- + + CALL CleanUp() + + CONTAINS + ! subroutine to set ErrState and close the files if an error occurs + SUBROUTINE CleanUp() + + ! ErrStat = ErrID_Fatal + CLOSE( UnIn ) + IF (InitInp%Echo) CLOSE( UnEc ) + + END SUBROUTINE + + END SUBROUTINE MDIO_ReadInput + ! ==================================================================================================== + + + + ! ==================================================================================================== + SUBROUTINE MDIO_ProcessOutList(OutList, p, m, y, InitOut, ErrStat, ErrMsg ) + + ! This routine processes the output channels requested by OutList, checking for validity and setting + ! the p%OutParam structures (of type MD_OutParmType) for each valid output. + ! It assumes the value p%NumOuts has been set beforehand, and sets the values of p%OutParam. + + + IMPLICIT NONE + + ! Passed variables + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) ! The list of user-requested outputs + TYPE(MD_ParameterType), INTENT(INOUT) :: p ! The module parameters + TYPE(MD_MiscVarType), INTENT(INOUT) :: m + TYPE(MD_OutputType), INTENT(INOUT) :: y ! Initial system outputs (outputs are not calculated; only the output mesh is initialized) + TYPE(MD_InitOutputType), INTENT(INOUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! Local variables + INTEGER :: I ! Generic loop-counting index +! INTEGER :: J ! Generic loop-counting index +! INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I), the name of each output channel + CHARACTER(ChanLen) :: qVal ! quantity type string to match to list of valid options + + INTEGER :: oID ! ID number of connect or line object + INTEGER :: nID ! ID number of node object + INTEGER :: i1,i2,i3,i4 ! indices of start of numbers or letters in OutListTmp string, for parsing + + + ! see the top of the module for info on the output labelling types + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + + + ALLOCATE ( p%OutParam(1:p%NumOuts) , STAT=ErrStat ) ! note: I'm skipping the time output entry at index 0 for simplicity + IF ( ErrStat /= 0_IntKi ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "Error allocating memory for the MoorDyn OutParam array." + RETURN + ELSE + ErrStat = ErrID_None + ENDIF + + + ! Set index, name, and units for the time output channel: ! note: I'm skipping the time output entry at index 0 + !p%OutParam(0)%Indx = Time + !p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + !p%OutParam(0)%Units = "(s)" + !p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not valid set ErrStat = ErrID_Warn. + + + ! go through list of requested output names and process (this is a bit of a mess) + + DO I = 1,p%NumOuts + + OutListTmp = OutList(I) ! current requested output name + !p%OutParam(I)%Name = OutListTmp + CALL Conv2UC(OutListTmp) ! convert to all uppercase for string matching purposes + + ! find indicies of changes in number-vs-letter in characters of OutListTmp + i1 = scan( OutListTmp , '1234567890' ) ! first number in the string + i2 = i1+verify( OutListTmp(i1+1:) , '1234567890' ) ! second letter start (assuming first character is a letter, i.e. i1>1) + i3 = i2+scan( OutListTmp(i2+1:) , '1234567890' ) ! second number start + i4 = i3+verify( OutListTmp(i3+1:) , '1234567890' ) ! third letter start + !i5 = scan( OutListTmp(i1:) , '1234567890' ) ! find first letter after first number + + ! error check + IF (i1 <= 1) THEN + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + CALL WrScr('Warning: invalid output specifier '//trim(OutListTmp)//'. Starting character must be C or L.') + CYCLE ! <<<<<<<<<<< check correct usage + END IF + + p%OutParam(I)%Name = OutListTmp ! label channel with whatever name was inputted, for now + + + ! figure out what type of output it is and process accordingly + + ! fairlead tension case (updated) + IF (OutListTmp(1:i1-1) == 'FAIRTEN') THEN + p%OutParam(I)%OType = 2 ! connection object type + p%OutParam(I)%QType = Ten ! tension quantity type + p%OutParam(I)%Units = UnitList(Ten) ! set units according to QType + READ (OutListTmp(i1:),*) oID ! this is the line number + p%OutParam(I)%ObjID = m%LineList(oID)%FairConnect ! get the connection ID of the fairlead + p%OutParam(I)%NodeID = -1 ! not used. m%LineList(oID)%N ! specify node N (fairlead) + + ! achor tension case + ELSE IF (OutListTmp(1:i1-1) == 'ANCHTEN') THEN + p%OutParam(I)%OType = 2 ! connectoin object type + p%OutParam(I)%QType = Ten ! tension quantity type + p%OutParam(I)%Units = UnitList(Ten) ! set units according to QType + READ (OutListTmp(i1:),*) oID ! this is the line number + p%OutParam(I)%ObjID = m%LineList(oID)%AnchConnect ! get the connection ID of the fairlead + p%OutParam(I)%NodeID = -1 ! not used. m%LineList(oID)%0 ! specify node 0 (anchor) + + ! more general case + ELSE + + ! what object type? + ! Line case ... L?N?xxxx + IF (OutListTmp(1:i1-1) == 'L') THEN + p%OutParam(I)%OType = 1 ! Line object type + ! for now we'll just assume the next character(s) are "n" to represent node number: + READ (OutListTmp(i3:i4-1),*) nID + p%OutParam(I)%NodeID = nID + qVal = OutListTmp(i4:) ! isolate quantity type string + ! Connect case ... C?xxx or Con?xxx + ELSE IF (OutListTmp(1:1) == 'C') THEN + p%OutParam(I)%OType = 2 ! Connect object type + qVal = OutListTmp(i2:) ! isolate quantity type string + + ! should do fairlead option also! + + ! error + ELSE + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + CALL WrScr('Warning: invalid output specifier '//trim(OutListTmp)//'. Type must be L or C.') + CYCLE + END IF + + ! object number + READ (OutListTmp(i1:i2-1),*) oID + p%OutParam(I)%ObjID = oID ! line or connect ID number + + ! which kind of quantity? + IF (qVal == 'PX') THEN + p%OutParam(I)%QType = PosX + p%OutParam(I)%Units = UnitList(PosX) + ELSE IF (qVal == 'PY') THEN + p%OutParam(I)%QType = PosY + p%OutParam(I)%Units = UnitList(PosY) + ELSE IF (qVal == 'PZ') THEN + p%OutParam(I)%QType = PosZ + p%OutParam(I)%Units = UnitList(PosZ) + ELSE IF (qVal == 'VX') THEN + p%OutParam(I)%QType = VelX + p%OutParam(I)%Units = UnitList(VelX) + ELSE IF (qVal == 'VY') THEN + p%OutParam(I)%QType = VelY + p%OutParam(I)%Units = UnitList(VelY) + ELSE IF (qVal == 'VZ') THEN + p%OutParam(I)%QType = VelZ + p%OutParam(I)%Units = UnitList(VelZ) + ELSE IF (qVal == 'AX') THEN + p%OutParam(I)%QType = AccX + p%OutParam(I)%Units = UnitList(AccX) + ELSE IF (qVal == 'AY') THEN ! fixed typo Nov 24 + p%OutParam(I)%QType = AccY + p%OutParam(I)%Units = UnitList(AccY) + ELSE IF (qVal == 'AZ') THEN + p%OutParam(I)%QType = AccZ + p%OutParam(I)%Units = UnitList(AccZ) + ELSE IF ((qVal == 'T') .or. (qval == 'Ten')) THEN + p%OutParam(I)%QType = Ten + p%OutParam(I)%Units = UnitList(Ten) + ELSE IF (qVal == 'FX') THEN + p%OutParam(I)%QType = FX + p%OutParam(I)%Units = UnitList(FX) + ELSE IF (qVal == 'FY') THEN + p%OutParam(I)%QType = FY + p%OutParam(I)%Units = UnitList(FY) + ELSE IF (qVal == 'FZ') THEN + p%OutParam(I)%QType = FZ + p%OutParam(I)%Units = UnitList(FZ) + ELSE + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + CALL WrScr('Warning: invalid output specifier '//trim(OutListTmp)//'. Quantity type not recognized.') + CONTINUE + END IF + + END IF + + ! also check whether each object index and node index (if applicable) is in range + IF (p%OutParam(I)%OType==2) THEN + IF (p%OutParam(I)%ObjID > p%NConnects) THEN + CALL WrScr('Warning: output Connect index excedes number of Connects in requested output '//trim(OutListTmp)//'.') + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + END IF + ELSE IF (p%OutParam(I)%OType==1) THEN + IF (p%OutParam(I)%ObjID > p%NLines) THEN + CALL WrScr('Warning: output Line index excedes number of Lines in requested output '//trim(OutListTmp)//'.') + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + END IF + IF (p%OutParam(I)%NodeID > m%LineList(p%OutParam(I)%ObjID)%N) THEN + CALL WrScr('Warning: output node index excedes number of nodes in requested output '//trim(OutListTmp)//'.') + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + ELSE IF (p%OutParam(I)%NodeID < 0) THEN + CALL WrScr('Warning: output node index is less than zero in requested output '//trim(OutListTmp)//'.') + CALL DenoteInvalidOutput(p%OutParam(I)) ! flag as invalid + END IF + + END IF + + ! is the reverse sign functionality necessary? + ! ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + END DO ! I ... looping through OutList + + +!! ! Allocate MDWrOutput which is used to store a time step's worth of output channels, prior to writing to a file. +! ALLOCATE( MDWrOutput( p%NumOuts), STAT = ErrStat ) +! IF ( ErrStat /= ErrID_None ) THEN +! ErrMsg = ' Error allocating space for MDWrOutput array.' +! ErrStat = ErrID_Fatal +! RETURN +! END IF + + + ! Allocate MDWrOuput2 which is used to store a time step's worth of output data for each line, just making it really big for now <<<<<<<<<<<<<< + ! <<<<<<<<<<< should do this for each line instead. + ! ALLOCATE( LineWriteOutputs( 200), STAT = ErrStat ) + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Error allocating space for LineWriteOutputs array.' + ! ErrStat = ErrID_Fatal + ! RETURN + ! END IF + + !Allocate WriteOuput + ALLOCATE( y%WriteOutput( p%NumOuts), & + InitOut%WriteOutputHdr(p%NumOuts), & + InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for y%WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ! allocate output array in each Line + DO I=1,p%NLines + ALLOCATE(m%LineList(I)%LineWrOutput( 1 + 3*(m%LineList(I)%N + 1)*SUM(m%LineList(I)%OutFlagList(2:5)) + m%LineList(I)%N*SUM(m%LineList(I)%OutFlagList(6:10)) ), STAT = ErrStat) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for a LineWrOutput array' + ErrStat = ErrID_Fatal + RETURN + END IF + END DO ! I + + !print *, "y%WriteOutput allocated to size ", size(y%WriteOutput) + + ! These variables are to help follow the framework template, but the data in them is simply a copy of data + ! already available in the OutParam data structure + ! ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) + ! ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) + + DO I = 1,p%NumOuts + InitOut%WriteOutputHdr(I) = p%OutParam(I)%Name + InitOut%WriteOutputUnt(I) = p%OutParam(I)%Units + END DO + + + CONTAINS + + SUBROUTINE DenoteInvalidOutput( OutParm ) + TYPE(MD_OutParmType), INTENT (INOUT) :: OutParm + + OutParm%OType = 0 ! flag as invalid + OutParm%Name = 'Invalid' + OutParm%Units = ' - ' + + END SUBROUTINE DenoteInvalidOutput + + END SUBROUTINE MDIO_ProcessOutList + !==================================================================================================== + + + + + + !==================================================================================================== + SUBROUTINE MDIO_OpenOutput( OutRootName, p, m, InitOut, ErrStat, ErrMsg ) + !---------------------------------------------------------------------------------------------------- + + CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file + TYPE(MD_ParameterType), INTENT( INOUT ) :: p + TYPE(MD_MiscVarType), INTENT( INOUT ) :: m + TYPE(MD_InitOutPutType ), INTENT( IN ) :: InitOut ! + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I ! Generic loop counter + INTEGER :: J ! Generic loop counter + CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. +! INTEGER :: L ! counter for index in LineWrOutput + INTEGER :: LineNumOuts ! number of entries in LineWrOutput for each line + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: ErrStat2 + + + ErrStat = ErrID_None + ErrMsg = "" + + p%Delim = ' ' ! for now + + !------------------------------------------------------------------------------------------------- + ! Open the output file, if necessary, and write the header + !------------------------------------------------------------------------------------------------- + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ! Open the file for output + OutFileName = TRIM(p%RootName)//'.out' + CALL GetNewUnit( p%MDUnOut ) + + CALL OpenFOutFile ( p%MDUnOut, OutFileName, ErrStat, ErrMsg ) + IF ( ErrStat > ErrID_None ) THEN + ErrMsg = ' Error opening MoorDyn-level output file: '//TRIM(ErrMsg) + ErrStat = ErrID_Fatal + RETURN + END IF + + + !Write the names of the output parameters: + + Frmt = '(A10,'//TRIM(Int2LStr(p%NumOuts))//'(A1,A10))' + + WRITE(p%MDUnOut,Frmt, IOSTAT=ErrStat2) TRIM( 'Time' ), ( p%Delim, TRIM( p%OutParam(I)%Name), I=1,p%NumOuts ) + + WRITE(p%MDUnOut,Frmt) TRIM( '(s)' ), ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) + + ! ELSE ! if no outputs requested + + ! call wrscr('note, MDIO_OpenOutput thinks that no outputs have been requested.') + + END IF + + !-------------------------------------------------------------------------- + ! now do the same for line output files + !-------------------------------------------------------------------------- + + !! allocate UnLineOuts + !ALLOCATE(UnLineOuts(p%NLines)) ! should add error checking + + DO I = 1,p%NLines + + + IF (m%LineList(I)%OutFlagList(1) == 1) THEN ! only proceed if the line is flagged to output a file + + ! Open the file for output + OutFileName = TRIM(p%RootName)//'.Line'//TRIM(Int2LStr(I))//'.out' + CALL GetNewUnit( m%LineList(I)%LineUnOut ) + + CALL OpenFOutFile ( m%LineList(I)%LineUnOut, OutFileName, ErrStat, ErrMsg ) + IF ( ErrStat > ErrID_None ) THEN + ErrMsg = ' Error opening Line output file '//TRIM(ErrMsg) + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! calculate number of output entries (including time) to write for this line + LineNumOuts = 1 + 3*(m%LineList(I)%N + 1)*SUM(m%LineList(I)%OutFlagList(2:5)) + m%LineList(I)%N*SUM(m%LineList(I)%OutFlagList(6:10)) + + Frmt = '(A10,'//TRIM(Int2LStr(LineNumOuts))//'(A1,A10))' ! should evenutally use user specified format? + !Frmt = '(A10,'//TRIM(Int2LStr(3+3*m%LineList(I)%N))//'(A1,A10))' + + ! Write the names of the output parameters: (these use "implied DO" loops) + + WRITE(m%LineList(I)%LineUnOut,'(A10)', advance='no', IOSTAT=ErrStat2) TRIM( 'Time' ) + IF (m%LineList(I)%OutFlagList(2) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Node'//TRIM(Int2Lstr(J))//'px', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'py', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'pz', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(3) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Node'//TRIM(Int2Lstr(J))//'vx', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'vy', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'vz', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(4) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Ux', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Uy', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Uz', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(5) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Dx', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Dy', p%Delim, 'Node'//TRIM(Int2Lstr(J))//'Dz', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(6) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Seg'//TRIM(Int2Lstr(J))//'Ten', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(7) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Seg'//TRIM(Int2Lstr(J))//'Dmp', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(8) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Seg'//TRIM(Int2Lstr(J))//'Str', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(9) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Seg'//TRIM(Int2Lstr(J))//'SRt', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(10)== 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, 'Seg'//TRIM(Int2Lstr(J))//'Lst', J=1,(m%LineList(I)%N) ) + END IF + + WRITE(m%LineList(I)%LineUnOut,'(A1)', IOSTAT=ErrStat2) ' ' ! make line break at the end + + ! Now write the units line + + WRITE(m%LineList(I)%LineUnOut,'(A10)', advance='no', IOSTAT=ErrStat2) TRIM( '(s)' ) + IF (m%LineList(I)%OutFlagList(2) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(m)', p%Delim, '(m)', p%Delim, '(m)', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(3) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(m/s)', p%Delim, '(m/s)', p%Delim, '(m/s)', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(4) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(m/s)', p%Delim, '(m/s)', p%Delim, '(m/s)', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(5) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((3+3*m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(N)', p%Delim, '(N)', p%Delim, '(N)', J=0,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(6) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(N)', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(7) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(N)', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(8) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(-)', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(9) == 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(1/s)', J=1,(m%LineList(I)%N) ) + END IF + IF (m%LineList(I)%OutFlagList(10)== 1) THEN + WRITE(m%LineList(I)%LineUnOut,'('//TRIM(Int2LStr((m%LineList(I)%N)))//'(A1,A10))', advance='no', IOSTAT=ErrStat2) & + ( p%Delim, '(m)', J=1,(m%LineList(I)%N) ) + END IF + + WRITE(m%LineList(I)%LineUnOut,'(A1)', IOSTAT=ErrStat2) ' ' ! make line break at the end + + END IF ! if line is flagged for output file + + END DO ! I - line number + + + ! need to fix error handling in this sub + + END SUBROUTINE MDIO_OpenOutput + !==================================================================================================== + + + !==================================================================================================== + SUBROUTINE MDIO_CloseOutput ( p, m, ErrStat, ErrMsg ) + ! This function cleans up after running the MoorDyn output module. + ! It closes the output files and releases memory. + + TYPE(MD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module + TYPE(MD_MiscVarType), INTENT( INOUT ) :: m ! data for this instance of the floating platform module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: I ! generic counter + + + ErrStat = 0 + ErrMsg = "" + + + ! close main MoorDyn output file + CLOSE( p%MDUnOut, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = 'Error closing output file' + END IF + + ! close individual line output files + DO I=1,p%NLines + CLOSE( m%LineList(I)%LineUnOut, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = 'Error closing line output file' + END IF + END DO + + ! deallocate output arrays + IF (ALLOCATED(m%MDWrOutput)) THEN + DEALLOCATE(m%MDWrOutput) + ENDIF + DO I=1,p%NLines + IF (ALLOCATED(m%LineList(I)%LineWrOutput)) THEN + DEALLOCATE(m%LineList(I)%LineWrOutput) ! this may be unnecessary and handled by Line destructor + ENDIF + END DO + + END SUBROUTINE MDIO_CloseOutput + !==================================================================================================== + + + !==================================================================================================== + SUBROUTINE MDIO_WriteOutputs( Time, p, m, y, ErrStat, ErrMsg ) + ! This subroutine gathers the output data defined by the OutParams list and + ! writes it to the output file opened in MDIO_OutInit() + + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + TYPE(MD_ParameterType), INTENT( IN ) :: p ! MoorDyn module's parameter data + TYPE(MD_OutputType), INTENT( INOUT ) :: y ! INTENT( OUT) : Initial system outputs (outputs are not calculated; only the output mesh is initialized) + TYPE(MD_MiscVarType), INTENT( INOUT ) :: m ! MoorDyn module's m data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: I ! Generic loop counter + INTEGER :: J ! Generic loop counter + INTEGER :: K ! Generic loop counter + INTEGER :: L ! counter for index in LineWrOutput + INTEGER :: LineNumOuts ! number of entries in LineWrOutput for each line + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. p%MDUnOut < 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' To write outputs for MoorDyn there must be a valid file ID and OutParam must be allocated.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + ! Return if there are no outputs + if ( p%NumOuts < 1_IntKi ) return + + + ! gather the required output quantities (INCOMPLETE!) + DO I = 1,p%NumOuts + + IF (p%OutParam(I)%OType == 2) THEN ! if dealing with a Connect output + SELECT CASE (p%OutParam(I)%QType) + CASE (PosX) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%r(1) ! x position + CASE (PosY) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%r(2) ! y position + CASE (PosZ) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%r(3) ! z position + CASE (VelX) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%rd(1) ! x velocity + CASE (VelY) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%rd(2) ! y velocity + CASE (VelZ) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%rd(3) ! z velocity + CASE (Ten) + y%WriteOutput(I) = TwoNorm(m%ConnectList(p%OutParam(I)%ObjID)%Ftot) ! total force magnitude on a connect (used eg. for fairlead and anchor tensions) + CASE (FX) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%Ftot(1) ! total force in x - added Nov 24 + CASE (FY) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%Ftot(2) ! total force in y + CASE (FZ) + y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%Ftot(3) ! total force in z + CASE DEFAULT + y%WriteOutput(I) = 0.0_ReKi + ErrStat = ErrID_Warn + ErrMsg = ' Unsupported output quantity '//TRIM(Num2Lstr(p%OutParam(I)%QType))//' requested from Connection '//TRIM(Num2Lstr(p%OutParam(I)%ObjID))//'.' + END SELECT + + ELSE IF (p%OutParam(I)%OType == 1) THEN ! if dealing with a Line output + + SELECT CASE (p%OutParam(I)%QType) + CASE (PosX) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%r(1,p%OutParam(I)%NodeID) ! x position + CASE (PosY) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%r(2,p%OutParam(I)%NodeID) ! y position + CASE (PosZ) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%r(3,p%OutParam(I)%NodeID) ! z position + CASE (VelX) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%rd(1,p%OutParam(I)%NodeID) ! x velocity + CASE (VelY) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%rd(2,p%OutParam(I)%NodeID) ! y velocity + CASE (VelZ) + y%WriteOutput(I) = m%LineList(p%OutParam(I)%ObjID)%rd(3,p%OutParam(I)%NodeID) ! z velocity + CASE (Ten) + y%WriteOutput(I) = TwoNorm(m%LineList(p%OutParam(I)%ObjID)%T(:,p%OutParam(I)%NodeID)) ! this is actually the segment tension ( 1 < NodeID < N ) Should deal with properly! + CASE DEFAULT + y%WriteOutput(I) = 0.0_ReKi + ErrStat = ErrID_Warn + ErrMsg = ' Unsupported output quantity '//TRIM(Num2Lstr(p%OutParam(I)%QType))//' requested from Line '//TRIM(Num2Lstr(p%OutParam(I)%ObjID))//'.' + END SELECT + + ELSE ! it must be an invalid output, so write zero + y%WriteOutput(I) = 0.0_ReKi + + END IF + + END DO ! I, loop through OutParam + + + ! Write the output parameters to the file + + Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts))//'(A1,e10.4))' ! should evenutally use user specified format? + + WRITE(p%MDUnOut,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) + + + + + + !------------------------------------------------------------------------ + ! now do the outputs for each line! + + DO I=1,p%NLines + + IF (m%LineList(I)%OutFlagList(1) == 1) THEN ! only proceed if the line is flagged to output a file + + ! calculate number of output entries to write for this line + LineNumOuts = 3*(m%LineList(I)%N + 1)*SUM(m%LineList(I)%OutFlagList(2:5)) + m%LineList(I)%N*SUM(m%LineList(I)%OutFlagList(6:10)) + + + Frmt = '(F10.4,'//TRIM(Int2LStr(LineNumOuts))//'(A1,e10.4))' ! should evenutally use user specified format? + + L = 1 ! start of index of line output file at first entry + + ! Time + ! m%LineList(I)%LineWrOutput(L) = Time + ! L = L+1 + + ! Node positions + IF (m%LineList(I)%OutFlagList(2) == 1) THEN + DO J = 0,m%LineList(I)%N ! note index starts at zero because these are nodes + DO K = 1,3 + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%r(K,J) + L = L+1 + END DO + END DO + END IF + + ! Node velocities + IF (m%LineList(I)%OutFlagList(3) == 1) THEN + DO J = 0,m%LineList(I)%N ! note index starts at zero because these are nodes + DO K = 1,3 + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%rd(K,J) + L = L+1 + END DO + END DO + END IF + + + ! Node wave velocities (not implemented yet) + IF (m%LineList(I)%OutFlagList(4) == 1) THEN + DO J = 0,m%LineList(I)%N ! note index starts at zero because these are nodes + DO K = 1,3 + m%LineList(I)%LineWrOutput(L) = 0.0 + L = L+1 + END DO + END DO + END IF + + + ! Node total hydrodynamic forces (except added mass - just drag for now) + IF (m%LineList(I)%OutFlagList(5) == 1) THEN + DO J = 0,m%LineList(I)%N ! note index starts at zero because these are nodes + DO K = 1,3 + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%Dp(K,J) + m%LineList(I)%Dq(K,J) + L = L+1 + END DO + END DO + END IF + + + ! Segment tension force (excludes damping term, just EA) + IF (m%LineList(I)%OutFlagList(6) == 1) THEN + DO J = 1,m%LineList(I)%N + m%LineList(I)%LineWrOutput(L) = TwoNorm(m%LineList(I)%T(:,J) ) + L = L+1 + END DO + END IF + + ! Segment internal damping force + IF (m%LineList(I)%OutFlagList(7) == 1) THEN + DO J = 1,m%LineList(I)%N + IF (( m%LineList(I)%Td(3,J)*m%LineList(I)%T(3,J) ) > 0) THEN ! if statement for handling sign (positive = tension) + m%LineList(I)%LineWrOutput(L) = TwoNorm(m%LineList(I)%Td(:,J) ) + ELSE + m%LineList(I)%LineWrOutput(L) = -TwoNorm(m%LineList(I)%Td(:,J) ) + END IF + L = L+1 + END DO + END IF + + ! Segment strain + IF (m%LineList(I)%OutFlagList(8) == 1) THEN + DO J = 1,m%LineList(I)%N + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%lstr(J)/m%LineList(I)%l(J) - 1.0 + L = L+1 + END DO + END IF + + ! Segment strain rate + IF (m%LineList(I)%OutFlagList(9) == 1) THEN + DO J = 1,m%LineList(I)%N + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%lstrd(J)/m%LineList(I)%l(J) + L = L+1 + END DO + END IF + + ! Segment length + IF (m%LineList(I)%OutFlagList(10) == 1) THEN + DO J = 1,m%LineList(I)%N + m%LineList(I)%LineWrOutput(L) = m%LineList(I)%lstr(J) + L = L+1 + END DO + END IF + + + WRITE(m%LineList(I)%LineUnOut,Frmt) Time, ( p%Delim, m%LineList(I)%LineWrOutput(J), J=1,(LineNumOuts) ) + !WRITE(m%LineList(I)%LineUnOut,Frmt) Time, ( p%Delim, m%LineList(I)%LineWrOutput(J), J=1,(3+3*m%LineList(I)%N) ) + + END IF ! if line output file flag is on + + END DO ! I + + END SUBROUTINE MDIO_WriteOutputs + !==================================================================================================== + + +END MODULE MoorDyn_IO diff --git a/OpenFAST/modules/moordyn/src/MoorDyn_Registry.txt b/OpenFAST/modules/moordyn/src/MoorDyn_Registry.txt new file mode 100644 index 000000000..8868e2621 --- /dev/null +++ b/OpenFAST/modules/moordyn/src/MoorDyn_Registry.txt @@ -0,0 +1,174 @@ +################## Registry for MoorDyn (Matthew Hall 2015) ############### +# column 1 <keyword> +# column 2 ModuleName/ModName or ^ to use the value from the previous line (SD is nickname for ModuleName) +# column 3 Derived data type (without "ModName_" prefix) +# column 4 Derived data types's Field type +# column 5 Variable name +# column 6 Dimension of variable {:} for allocatable +# column 7 Variable's initial value (if set in the data type) +# column 8 I think this is a switch for mixed-language programming; it's mostly unused +# column 9 Description +# column 10 Units +# Keyword ModuleName/ModName Derived data type Field type Variable name variable dimension Initial value for mix language, not used Description Units + +include Registry_NWTC_Library.txt + + +## ============================== Define input types here: ============================================================================================================================================ +typedef MoorDyn/MD InitInputType ReKi g - -999.9 - "gravity constant" "[m/s^2]" +typedef ^ ^ ReKi rhoW - -999.9 - "sea density" "[kg/m^3]" +typedef ^ ^ ReKi WtrDepth - -999.9 - "depth of water" "[m]" +typedef ^ ^ ReKi PtfmInit {6} - - "initial position of platform" - +typedef ^ ^ CHARACTER(1024) FileName - "" - "MoorDyn input file" +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ LOGICAL Echo - "" - "echo parameter - do we want to echo the header line describing the input file?" +typedef ^ ^ ReKi DTIC - - - "convergence check time step for IC generation" "[s]" +typedef ^ ^ ReKi TMaxIC - 120 - "maximum time to allow for getting converged ICs" "[s]" +typedef ^ ^ ReKi CdScaleIC - 1 - "factor to scale drag coefficients by during dynamic relaxation" "[]" +typedef ^ ^ ReKi threshIC - 0.01 - "convergence tolerance for ICs (0.01 means 1%)" "[]" +typedef ^ ^ CHARACTER(ChanLen) OutList {:} "" - "string containing list of output channels requested in input file" + + +# ====================================== Internal data types ======================================================================== +# line properties from line dictionary input +typedef ^ MD_LineProp IntKi IdNum - - - "integer identifier of this set of line properties" +typedef ^ ^ CHARACTER(10) name - - - "name/identifier of this set of line properties" +typedef ^ ^ ReKi d - - - "volume-equivalent diameter" "[m]" +typedef ^ ^ ReKi w - - - "per-length weight in air" "[kg/m]" +typedef ^ ^ ReKi EA - - - "stiffness" "[N]" +typedef ^ ^ ReKi BA - - - "internal damping coefficient times area" "[N-s]" +typedef ^ ^ ReKi Can - - - "transverse added mass coefficient" +typedef ^ ^ ReKi Cat - - - "tangential added mass coefficient" +typedef ^ ^ ReKi Cdn - - - "transverse drag coefficient" +typedef ^ ^ ReKi Cdt - - - "tangential drag coefficient" + +# this is the Connection type, which holds data for each connection object +typedef ^ MD_Connect IntKi IdNum - - - "integer identifier of this Connection" +typedef ^ ^ CHARACTER(10) type - - - "type of Connect: fix, vessel, connect" +typedef ^ ^ IntKi TypeNum - - - "integer identifying the type. 0=fixed, 1=vessel, 2=connect" +typedef ^ ^ IntKi AttachedFairs {:} - - "list of IdNums of connected Line tops" +typedef ^ ^ IntKi AttachedAnchs {:} - - "list of IdNums of connected Line bottoms" +typedef ^ ^ ReKi conX - - - "" +typedef ^ ^ ReKi conY - - - "" +typedef ^ ^ ReKi conZ - - - "" +typedef ^ ^ ReKi conM - - - "" +typedef ^ ^ ReKi conV - - - "" +typedef ^ ^ ReKi conFX - - - "" +typedef ^ ^ ReKi conFY - - - "" +typedef ^ ^ ReKi conFZ - - - "" +typedef ^ ^ ReKi conCa - - - "added mass coefficient of connection point" "-" +typedef ^ ^ ReKi conCdA - - - "product of drag force and frontal area of connection point" "[m^2]" +typedef ^ ^ ReKi Ftot {3} - - "total force on node" +typedef ^ ^ ReKi Mtot {3}{3} - - "node mass matrix, from attached lines" +typedef ^ ^ ReKi S {3}{3} - - "inverse mass matrix" "[kg]" +typedef ^ ^ ReKi r {3} - - "position" +typedef ^ ^ ReKi rd {3} - - "velocity" + +# this is the Line type, which holds data for each line object +typedef ^ MD_Line IntKi IdNum - - - "integer identifier of this Line" +typedef ^ ^ CHARACTER(10) type - - - "type of line. should match one of LineProp names" +typedef ^ ^ IntKi OutFlagList {20} - - "array specifying what line quantities should be output (1 vs 0)" - +typedef ^ ^ IntKi CtrlChan - - - "index of control channel that will drive line active tensioning (0 for none)" - +typedef ^ ^ IntKi FairConnect - - - "IdNum of Connection at fairlead" +typedef ^ ^ IntKi AnchConnect - - - "IdNum of Connection at anchor" +typedef ^ ^ IntKi PropsIdNum - - - "the IdNum of the associated line properties" - +typedef ^ ^ IntKi N - - - "The number of elements in the line" - +typedef ^ ^ ReKi UnstrLen - - - "unstretched length of the line" - +typedef ^ ^ ReKi BA - - - "internal damping coefficient times area for this line only" "[N-s]" +typedef ^ ^ ReKi r {:}{:} - - "node positions" - +typedef ^ ^ ReKi rd {:}{:} - - "node velocities" - +typedef ^ ^ ReKi q {:}{:} - - "node tangent vectors" - +typedef ^ ^ ReKi l {:} - - "segment unstretched length" "[m]" +typedef ^ ^ ReKi ld {:} - - "segment unstretched length rate of change (used in active tensioning)" "[m]" +typedef ^ ^ ReKi lstr {:} - - "segment stretched length" "[m]" +typedef ^ ^ ReKi lstrd {:} - - "segment change in stretched length" "[m/s]" +typedef ^ ^ ReKi V {:} - - "segment volume" "[m^3]" +typedef ^ ^ ReKi T {:}{:} - - "segment tension vectors" "[N]" +typedef ^ ^ ReKi Td {:}{:} - - "segment internal damping force vectors" "[N]" +typedef ^ ^ ReKi W {:}{:} - - "weight/buoyancy vectors" "[N]" +typedef ^ ^ ReKi Dp {:}{:} - - "node drag (transverse)" "[N]" +typedef ^ ^ ReKi Dq {:}{:} - - "node drag (axial)" "[N]" +typedef ^ ^ ReKi Ap {:}{:} - - "node added mass forcing (transverse)" "[N]" +typedef ^ ^ ReKi Aq {:}{:} - - "node added mass forcing (axial)" "[N]" +typedef ^ ^ ReKi B {:}{:} - - "node bottom contact force" "[N]" +typedef ^ ^ ReKi F {:}{:} - - "total force on node" "[N]" +typedef ^ ^ ReKi S {:}{:}{:} - - "node inverse mass matrix" "[kg]" +typedef ^ ^ ReKi M {:}{:}{:} - - "node mass matrix" "[kg]" +typedef ^ ^ IntKi LineUnOut - - - "unit number of line output file" +typedef ^ ^ ReKi LineWrOutput {:} - - "one row of output data for this line" + + + +# this is the MDOutParmType - a less literal alternative of the NWTC OutParmType for MoorDyn (to avoid huge lists of possible output channel permutations) +typedef ^ MD_OutParmType CHARACTER(ChanLen) Name - - - "name of output channel" +typedef ^ ^ CHARACTER(ChanLen) Units - - - "units string" +typedef ^ ^ IntKi QType - - - "type of quantity - 0=tension, 1=x, 2=y, 3=z..." +typedef ^ ^ IntKi OType - - - "type of object - 0=line, 1=connect" +typedef ^ ^ IntKi NodeID - - - "node number if OType=0. 0=anchor, -1=N=Fairlead" +typedef ^ ^ IntKi ObjID - - - "number of Connect or Line object" + + +## ============================== Define Initialization outputs here: ================================================================================================================================ +typedef ^ InitOutputType CHARACTER(ChanLen) writeOutputHdr {:} "" - "first line output file contents: output variable names" +typedef ^ ^ CHARACTER(ChanLen) writeOutputUnt {:} "" - "second line of output file contents: units" +typedef ^ ^ ProgDesc Ver - "" - "this module's name, version, and date" + + +## ============================== Define Continuous states here: ===================================================================================================================================== +typedef ^ ContinuousStateType ReKi states {:} "" - "full list of node coordinates and velocities" "[m] or [m/s]" + + +## ============================== Define Discrete states here: ===================================================================================================================================== +typedef ^ DiscreteStateType SiKi dummy - - - "Remove this variable if you have discrete states" - + + +## ============================== Define constraint states here: ===================================================================================================================================== +typedef ^ ConstraintStateType SiKi dummy - - - "Remove this variable if you have constraint states" - + + +## ============================== Define Other states here: ===================================================================================================================================== +typedef ^ OtherStateType SiKi dummy - - - "Remove this variable if you have other states" - + + +## ============================== Define Misc variables here: ===================================================================================================================================== +typedef ^ MiscVarType MD_LineProp LineTypeList {:} - - "array of properties for each line type" - +typedef ^ ^ MD_Connect ConnectList {:} - - "array of connection properties" - +typedef ^ ^ MD_Line LineList {:} - - "array of line properties" - +typedef ^ ^ IntKi FairIdList {:} - - "array of size NFairs listing the ID of each fairlead (index of ConnectList)" "" +typedef ^ ^ IntKi ConnIdList {:} - - "array of size NConnss listing the ID of each connect type connection (index of ConnectList)" "" +typedef ^ ^ IntKi LineStateIndList {:} - - "starting index of each line's states in state vector" "" +typedef ^ ^ ReKi MDWrOutput {:} - - "Data from time step to be written to a MoorDyn output file" + + +## ============================== Parameters ============================================================================================================================================ +typedef ^ ParameterType IntKi NTypes - - - "number of line types" "" +typedef ^ ^ IntKi NConnects - - - "number of Connection objects" "" +typedef ^ ^ IntKi NFairs - - - "number of Fairlead Connections" "" +typedef ^ ^ IntKi NConns - - - "number of Connect type Connections - not to be confused with NConnects" "" +typedef ^ ^ IntKi NAnchs - - - "number of Anchor type Connections" "" +typedef ^ ^ IntKi NLines - - - "number of Line objects" "" +typedef ^ ^ ReKi g - 9.81 - "gravitational constant" "[kg/m^2]" +typedef ^ ^ ReKi rhoW - - - "density of seawater" "[m]" +typedef ^ ^ ReKi WtrDpth - - - "water depth" "[m]" +typedef ^ ^ ReKi kBot - - - "bottom stiffness" "[Pa/m]" +typedef ^ ^ ReKi cBot - - - "bottom damping" "[Pa-s/m]" +typedef ^ ^ ReKi dtM0 - - - "desired mooring model time step" "[s]" +typedef ^ ^ ReKi dtCoupling - - - "coupling time step that MoorDyn should expect" "[s]" +typedef ^ ^ IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ MD_OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ^ CHARACTER(1) Delim - - - "Column delimiter for output text files" - +typedef ^ ^ IntKi MDUnOut - - - "Unit number of main output file" + + +# ============================== Inputs ============================================================================================================================================ +typedef ^ InputType MeshType PtFairleadDisplacement - - - "mesh for position AND VELOCITY of each fairlead in X,Y,Z" "[m, m/s]" +# typedef ^ ^ MeshType HydroForceLineMesh - - - "Meshed input data" - +typedef ^ ^ ReKi DeltaL {:} - - "change in line length command for each channel" "[m]" +typedef ^ ^ ReKi DeltaLdot {:} - - "rate of change of line length command for each channel" "[m]" + + +## ============================== Outputs ============================================================================================================================================ +typedef ^ OutputType MeshType PtFairleadLoad - - - "point mesh for fairlead forces in X,Y,Z" "[N]" +typedef ^ ^ ReKi WriteOutput {:} - - "output vector returned to glue code" "" +# typedef ^ ^ MeshType LineMeshPosition - - - "Meshed output data" - diff --git a/OpenFAST/modules/moordyn/src/MoorDyn_Types.f90 b/OpenFAST/modules/moordyn/src/MoorDyn_Types.f90 new file mode 100644 index 000000000..e7fb3a826 --- /dev/null +++ b/OpenFAST/modules/moordyn/src/MoorDyn_Types.f90 @@ -0,0 +1,5598 @@ +!STARTOFREGISTRYGENERATEDFILE 'MoorDyn_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 +!********************************************************************************************************************************* +! MoorDyn_Types +!................................................................................................................................. +! This file is part of MoorDyn. +! +! 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 MoorDyn. 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 MoorDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= MD_InitInputType ======= + TYPE, PUBLIC :: MD_InitInputType + REAL(ReKi) :: g = -999.9 !< gravity constant [[m/s^2]] + REAL(ReKi) :: rhoW = -999.9 !< sea density [[kg/m^3]] + REAL(ReKi) :: WtrDepth = -999.9 !< depth of water [[m]] + REAL(ReKi) , DIMENSION(1:6) :: PtfmInit !< initial position of platform [-] + CHARACTER(1024) :: FileName !< MoorDyn input file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + LOGICAL :: Echo !< echo parameter - do we want to echo the header line describing the input file? [-] + REAL(ReKi) :: DTIC !< convergence check time step for IC generation [[s]] + REAL(ReKi) :: TMaxIC = 120 !< maximum time to allow for getting converged ICs [[s]] + REAL(ReKi) :: CdScaleIC = 1 !< factor to scale drag coefficients by during dynamic relaxation [[]] + REAL(ReKi) :: threshIC = 0.01 !< convergence tolerance for ICs (0.01 means 1%) [[]] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< string containing list of output channels requested in input file [-] + END TYPE MD_InitInputType +! ======================= +! ========= MD_LineProp ======= + TYPE, PUBLIC :: MD_LineProp + INTEGER(IntKi) :: IdNum !< integer identifier of this set of line properties [-] + CHARACTER(10) :: name !< name/identifier of this set of line properties [-] + REAL(ReKi) :: d !< volume-equivalent diameter [[m]] + REAL(ReKi) :: w !< per-length weight in air [[kg/m]] + REAL(ReKi) :: EA !< stiffness [[N]] + REAL(ReKi) :: BA !< internal damping coefficient times area [[N-s]] + REAL(ReKi) :: Can !< transverse added mass coefficient [-] + REAL(ReKi) :: Cat !< tangential added mass coefficient [-] + REAL(ReKi) :: Cdn !< transverse drag coefficient [-] + REAL(ReKi) :: Cdt !< tangential drag coefficient [-] + END TYPE MD_LineProp +! ======================= +! ========= MD_Connect ======= + TYPE, PUBLIC :: MD_Connect + INTEGER(IntKi) :: IdNum !< integer identifier of this Connection [-] + CHARACTER(10) :: type !< type of Connect: fix, vessel, connect [-] + INTEGER(IntKi) :: TypeNum !< integer identifying the type. 0=fixed, 1=vessel, 2=connect [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AttachedFairs !< list of IdNums of connected Line tops [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AttachedAnchs !< list of IdNums of connected Line bottoms [-] + REAL(ReKi) :: conX !< [-] + REAL(ReKi) :: conY !< [-] + REAL(ReKi) :: conZ !< [-] + REAL(ReKi) :: conM !< [-] + REAL(ReKi) :: conV !< [-] + REAL(ReKi) :: conFX !< [-] + REAL(ReKi) :: conFY !< [-] + REAL(ReKi) :: conFZ !< [-] + REAL(ReKi) :: conCa !< added mass coefficient of connection point [-] + REAL(ReKi) :: conCdA !< product of drag force and frontal area of connection point [[m^2]] + REAL(ReKi) , DIMENSION(1:3) :: Ftot !< total force on node [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: Mtot !< node mass matrix, from attached lines [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: S !< inverse mass matrix [[kg]] + REAL(ReKi) , DIMENSION(1:3) :: r !< position [-] + REAL(ReKi) , DIMENSION(1:3) :: rd !< velocity [-] + END TYPE MD_Connect +! ======================= +! ========= MD_Line ======= + TYPE, PUBLIC :: MD_Line + INTEGER(IntKi) :: IdNum !< integer identifier of this Line [-] + CHARACTER(10) :: type !< type of line. should match one of LineProp names [-] + INTEGER(IntKi) , DIMENSION(1:20) :: OutFlagList !< array specifying what line quantities should be output (1 vs 0) [-] + INTEGER(IntKi) :: CtrlChan !< index of control channel that will drive line active tensioning (0 for none) [-] + INTEGER(IntKi) :: FairConnect !< IdNum of Connection at fairlead [-] + INTEGER(IntKi) :: AnchConnect !< IdNum of Connection at anchor [-] + INTEGER(IntKi) :: PropsIdNum !< the IdNum of the associated line properties [-] + INTEGER(IntKi) :: N !< The number of elements in the line [-] + REAL(ReKi) :: UnstrLen !< unstretched length of the line [-] + REAL(ReKi) :: BA !< internal damping coefficient times area for this line only [[N-s]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: r !< node positions [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rd !< node velocities [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: q !< node tangent vectors [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: l !< segment unstretched length [[m]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ld !< segment unstretched length rate of change (used in active tensioning) [[m]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstr !< segment stretched length [[m]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstrd !< segment change in stretched length [[m/s]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V !< segment volume [[m^3]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T !< segment tension vectors [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Td !< segment internal damping force vectors [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: W !< weight/buoyancy vectors [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dp !< node drag (transverse) [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dq !< node drag (axial) [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Ap !< node added mass forcing (transverse) [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Aq !< node added mass forcing (axial) [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< node bottom contact force [[N]] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F !< total force on node [[N]] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: S !< node inverse mass matrix [[kg]] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: M !< node mass matrix [[kg]] + INTEGER(IntKi) :: LineUnOut !< unit number of line output file [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineWrOutput !< one row of output data for this line [-] + END TYPE MD_Line +! ======================= +! ========= MD_OutParmType ======= + TYPE, PUBLIC :: MD_OutParmType + CHARACTER(ChanLen) :: Name !< name of output channel [-] + CHARACTER(ChanLen) :: Units !< units string [-] + INTEGER(IntKi) :: QType !< type of quantity - 0=tension, 1=x, 2=y, 3=z... [-] + INTEGER(IntKi) :: OType !< type of object - 0=line, 1=connect [-] + INTEGER(IntKi) :: NodeID !< node number if OType=0. 0=anchor, -1=N=Fairlead [-] + INTEGER(IntKi) :: ObjID !< number of Connect or Line object [-] + END TYPE MD_OutParmType +! ======================= +! ========= MD_InitOutputType ======= + TYPE, PUBLIC :: MD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: writeOutputHdr !< first line output file contents: output variable names [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: writeOutputUnt !< second line of output file contents: units [-] + TYPE(ProgDesc) :: Ver !< this module's name, version, and date [-] + END TYPE MD_InitOutputType +! ======================= +! ========= MD_ContinuousStateType ======= + TYPE, PUBLIC :: MD_ContinuousStateType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: states !< full list of node coordinates and velocities [[m] or [m/s]] + END TYPE MD_ContinuousStateType +! ======================= +! ========= MD_DiscreteStateType ======= + TYPE, PUBLIC :: MD_DiscreteStateType + REAL(SiKi) :: dummy !< Remove this variable if you have discrete states [-] + END TYPE MD_DiscreteStateType +! ======================= +! ========= MD_ConstraintStateType ======= + TYPE, PUBLIC :: MD_ConstraintStateType + REAL(SiKi) :: dummy !< Remove this variable if you have constraint states [-] + END TYPE MD_ConstraintStateType +! ======================= +! ========= MD_OtherStateType ======= + TYPE, PUBLIC :: MD_OtherStateType + REAL(SiKi) :: dummy !< Remove this variable if you have other states [-] + END TYPE MD_OtherStateType +! ======================= +! ========= MD_MiscVarType ======= + TYPE, PUBLIC :: MD_MiscVarType + TYPE(MD_LineProp) , DIMENSION(:), ALLOCATABLE :: LineTypeList !< array of properties for each line type [-] + TYPE(MD_Connect) , DIMENSION(:), ALLOCATABLE :: ConnectList !< array of connection properties [-] + TYPE(MD_Line) , DIMENSION(:), ALLOCATABLE :: LineList !< array of line properties [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: FairIdList !< array of size NFairs listing the ID of each fairlead (index of ConnectList) [] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ConnIdList !< array of size NConnss listing the ID of each connect type connection (index of ConnectList) [] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: LineStateIndList !< starting index of each line's states in state vector [] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: MDWrOutput !< Data from time step to be written to a MoorDyn output file [-] + END TYPE MD_MiscVarType +! ======================= +! ========= MD_ParameterType ======= + TYPE, PUBLIC :: MD_ParameterType + INTEGER(IntKi) :: NTypes !< number of line types [] + INTEGER(IntKi) :: NConnects !< number of Connection objects [] + INTEGER(IntKi) :: NFairs !< number of Fairlead Connections [] + INTEGER(IntKi) :: NConns !< number of Connect type Connections - not to be confused with NConnects [] + INTEGER(IntKi) :: NAnchs !< number of Anchor type Connections [] + INTEGER(IntKi) :: NLines !< number of Line objects [] + REAL(ReKi) :: g = 9.81 !< gravitational constant [[kg/m^2]] + REAL(ReKi) :: rhoW !< density of seawater [[m]] + REAL(ReKi) :: WtrDpth !< water depth [[m]] + REAL(ReKi) :: kBot !< bottom stiffness [[Pa/m]] + REAL(ReKi) :: cBot !< bottom damping [[Pa-s/m]] + REAL(ReKi) :: dtM0 !< desired mooring model time step [[s]] + REAL(ReKi) :: dtCoupling !< coupling time step that MoorDyn should expect [[s]] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(MD_OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + INTEGER(IntKi) :: MDUnOut !< Unit number of main output file [-] + END TYPE MD_ParameterType +! ======================= +! ========= MD_InputType ======= + TYPE, PUBLIC :: MD_InputType + TYPE(MeshType) :: PtFairleadDisplacement !< mesh for position AND VELOCITY of each fairlead in X,Y,Z [[m, m/s]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DeltaL !< change in line length command for each channel [[m]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DeltaLdot !< rate of change of line length command for each channel [[m]] + END TYPE MD_InputType +! ======================= +! ========= MD_OutputType ======= + TYPE, PUBLIC :: MD_OutputType + TYPE(MeshType) :: PtFairleadLoad !< point mesh for fairlead forces in X,Y,Z [[N]] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< output vector returned to glue code [] + END TYPE MD_OutputType +! ======================= +CONTAINS + SUBROUTINE MD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%g = SrcInitInputData%g + DstInitInputData%rhoW = SrcInitInputData%rhoW + DstInitInputData%WtrDepth = SrcInitInputData%WtrDepth + DstInitInputData%PtfmInit = SrcInitInputData%PtfmInit + DstInitInputData%FileName = SrcInitInputData%FileName + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%Echo = SrcInitInputData%Echo + DstInitInputData%DTIC = SrcInitInputData%DTIC + DstInitInputData%TMaxIC = SrcInitInputData%TMaxIC + DstInitInputData%CdScaleIC = SrcInitInputData%CdScaleIC + DstInitInputData%threshIC = SrcInitInputData%threshIC +IF (ALLOCATED(SrcInitInputData%OutList)) THEN + i1_l = LBOUND(SrcInitInputData%OutList,1) + i1_u = UBOUND(SrcInitInputData%OutList,1) + IF (.NOT. ALLOCATED(DstInitInputData%OutList)) THEN + ALLOCATE(DstInitInputData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%OutList = SrcInitInputData%OutList +ENDIF + END SUBROUTINE MD_CopyInitInput + + SUBROUTINE MD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(MD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%OutList)) THEN + DEALLOCATE(InitInputData%OutList) +ENDIF + END SUBROUTINE MD_DestroyInitInput + + SUBROUTINE MD_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(MD_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 = 'MD_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 + Re_BufSz = Re_BufSz + 1 ! g + Re_BufSz = Re_BufSz + 1 ! rhoW + Re_BufSz = Re_BufSz + 1 ! WtrDepth + Re_BufSz = Re_BufSz + SIZE(InData%PtfmInit) ! PtfmInit + Int_BufSz = Int_BufSz + 1*LEN(InData%FileName) ! FileName + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! Echo + Re_BufSz = Re_BufSz + 1 ! DTIC + Re_BufSz = Re_BufSz + 1 ! TMaxIC + Re_BufSz = Re_BufSz + 1 ! CdScaleIC + Re_BufSz = Re_BufSz + 1 ! threshIC + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + 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%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhoW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDepth + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%PtfmInit,1), UBOUND(InData%PtfmInit,1) + ReKiBuf(Re_Xferred) = InData%PtfmInit(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(InData%FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DTIC + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMaxIC + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CdScaleIC + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%threshIC + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE MD_PackInitInput + + SUBROUTINE MD_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(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_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%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rhoW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDepth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%PtfmInit,1) + i1_u = UBOUND(OutData%PtfmInit,1) + DO i1 = LBOUND(OutData%PtfmInit,1), UBOUND(OutData%PtfmInit,1) + OutData%PtfmInit(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(OutData%FileName) + OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 + OutData%DTIC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMaxIC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CdScaleIC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%threshIC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE MD_UnPackInitInput + + SUBROUTINE MD_CopyLineProp( SrcLinePropData, DstLinePropData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_LineProp), INTENT(IN) :: SrcLinePropData + TYPE(MD_LineProp), INTENT(INOUT) :: DstLinePropData + 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 = 'MD_CopyLineProp' +! + ErrStat = ErrID_None + ErrMsg = "" + DstLinePropData%IdNum = SrcLinePropData%IdNum + DstLinePropData%name = SrcLinePropData%name + DstLinePropData%d = SrcLinePropData%d + DstLinePropData%w = SrcLinePropData%w + DstLinePropData%EA = SrcLinePropData%EA + DstLinePropData%BA = SrcLinePropData%BA + DstLinePropData%Can = SrcLinePropData%Can + DstLinePropData%Cat = SrcLinePropData%Cat + DstLinePropData%Cdn = SrcLinePropData%Cdn + DstLinePropData%Cdt = SrcLinePropData%Cdt + END SUBROUTINE MD_CopyLineProp + + SUBROUTINE MD_DestroyLineProp( LinePropData, ErrStat, ErrMsg ) + TYPE(MD_LineProp), INTENT(INOUT) :: LinePropData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyLineProp' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MD_DestroyLineProp + + SUBROUTINE MD_PackLineProp( 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(MD_LineProp), 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 = 'MD_PackLineProp' + ! 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 ! IdNum + Int_BufSz = Int_BufSz + 1*LEN(InData%name) ! name + Re_BufSz = Re_BufSz + 1 ! d + Re_BufSz = Re_BufSz + 1 ! w + Re_BufSz = Re_BufSz + 1 ! EA + Re_BufSz = Re_BufSz + 1 ! BA + Re_BufSz = Re_BufSz + 1 ! Can + Re_BufSz = Re_BufSz + 1 ! Cat + Re_BufSz = Re_BufSz + 1 ! Cdn + Re_BufSz = Re_BufSz + 1 ! Cdt + 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%IdNum + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%name) + IntKiBuf(Int_Xferred) = ICHAR(InData%name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%d + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%w + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%EA + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BA + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Can + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cat + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cdn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Cdt + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE MD_PackLineProp + + SUBROUTINE MD_UnPackLineProp( 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(MD_LineProp), 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 = 'MD_UnPackLineProp' + ! 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%IdNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%name) + OutData%name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%d = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%w = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%EA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Can = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cat = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cdn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Cdt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE MD_UnPackLineProp + + SUBROUTINE MD_CopyConnect( SrcConnectData, DstConnectData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_Connect), INTENT(IN) :: SrcConnectData + TYPE(MD_Connect), INTENT(INOUT) :: DstConnectData + 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 = 'MD_CopyConnect' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConnectData%IdNum = SrcConnectData%IdNum + DstConnectData%type = SrcConnectData%type + DstConnectData%TypeNum = SrcConnectData%TypeNum +IF (ALLOCATED(SrcConnectData%AttachedFairs)) THEN + i1_l = LBOUND(SrcConnectData%AttachedFairs,1) + i1_u = UBOUND(SrcConnectData%AttachedFairs,1) + IF (.NOT. ALLOCATED(DstConnectData%AttachedFairs)) THEN + ALLOCATE(DstConnectData%AttachedFairs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConnectData%AttachedFairs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstConnectData%AttachedFairs = SrcConnectData%AttachedFairs +ENDIF +IF (ALLOCATED(SrcConnectData%AttachedAnchs)) THEN + i1_l = LBOUND(SrcConnectData%AttachedAnchs,1) + i1_u = UBOUND(SrcConnectData%AttachedAnchs,1) + IF (.NOT. ALLOCATED(DstConnectData%AttachedAnchs)) THEN + ALLOCATE(DstConnectData%AttachedAnchs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstConnectData%AttachedAnchs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstConnectData%AttachedAnchs = SrcConnectData%AttachedAnchs +ENDIF + DstConnectData%conX = SrcConnectData%conX + DstConnectData%conY = SrcConnectData%conY + DstConnectData%conZ = SrcConnectData%conZ + DstConnectData%conM = SrcConnectData%conM + DstConnectData%conV = SrcConnectData%conV + DstConnectData%conFX = SrcConnectData%conFX + DstConnectData%conFY = SrcConnectData%conFY + DstConnectData%conFZ = SrcConnectData%conFZ + DstConnectData%conCa = SrcConnectData%conCa + DstConnectData%conCdA = SrcConnectData%conCdA + DstConnectData%Ftot = SrcConnectData%Ftot + DstConnectData%Mtot = SrcConnectData%Mtot + DstConnectData%S = SrcConnectData%S + DstConnectData%r = SrcConnectData%r + DstConnectData%rd = SrcConnectData%rd + END SUBROUTINE MD_CopyConnect + + SUBROUTINE MD_DestroyConnect( ConnectData, ErrStat, ErrMsg ) + TYPE(MD_Connect), INTENT(INOUT) :: ConnectData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyConnect' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ConnectData%AttachedFairs)) THEN + DEALLOCATE(ConnectData%AttachedFairs) +ENDIF +IF (ALLOCATED(ConnectData%AttachedAnchs)) THEN + DEALLOCATE(ConnectData%AttachedAnchs) +ENDIF + END SUBROUTINE MD_DestroyConnect + + SUBROUTINE MD_PackConnect( 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(MD_Connect), 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 = 'MD_PackConnect' + ! 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 ! IdNum + Int_BufSz = Int_BufSz + 1*LEN(InData%type) ! type + Int_BufSz = Int_BufSz + 1 ! TypeNum + Int_BufSz = Int_BufSz + 1 ! AttachedFairs allocated yes/no + IF ( ALLOCATED(InData%AttachedFairs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AttachedFairs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AttachedFairs) ! AttachedFairs + END IF + Int_BufSz = Int_BufSz + 1 ! AttachedAnchs allocated yes/no + IF ( ALLOCATED(InData%AttachedAnchs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AttachedAnchs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AttachedAnchs) ! AttachedAnchs + END IF + Re_BufSz = Re_BufSz + 1 ! conX + Re_BufSz = Re_BufSz + 1 ! conY + Re_BufSz = Re_BufSz + 1 ! conZ + Re_BufSz = Re_BufSz + 1 ! conM + Re_BufSz = Re_BufSz + 1 ! conV + Re_BufSz = Re_BufSz + 1 ! conFX + Re_BufSz = Re_BufSz + 1 ! conFY + Re_BufSz = Re_BufSz + 1 ! conFZ + Re_BufSz = Re_BufSz + 1 ! conCa + Re_BufSz = Re_BufSz + 1 ! conCdA + Re_BufSz = Re_BufSz + SIZE(InData%Ftot) ! Ftot + Re_BufSz = Re_BufSz + SIZE(InData%Mtot) ! Mtot + Re_BufSz = Re_BufSz + SIZE(InData%S) ! S + Re_BufSz = Re_BufSz + SIZE(InData%r) ! r + Re_BufSz = Re_BufSz + SIZE(InData%rd) ! rd + 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%IdNum + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%type) + IntKiBuf(Int_Xferred) = ICHAR(InData%type(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%TypeNum + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AttachedFairs) ) 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%AttachedFairs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AttachedFairs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AttachedFairs,1), UBOUND(InData%AttachedFairs,1) + IntKiBuf(Int_Xferred) = InData%AttachedFairs(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AttachedAnchs) ) 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%AttachedAnchs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AttachedAnchs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AttachedAnchs,1), UBOUND(InData%AttachedAnchs,1) + IntKiBuf(Int_Xferred) = InData%AttachedAnchs(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%conX + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conY + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conFX + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conFY + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conFZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conCa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%conCdA + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%Ftot,1), UBOUND(InData%Ftot,1) + ReKiBuf(Re_Xferred) = InData%Ftot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%Mtot,2), UBOUND(InData%Mtot,2) + DO i1 = LBOUND(InData%Mtot,1), UBOUND(InData%Mtot,1) + ReKiBuf(Re_Xferred) = InData%Mtot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%S,2), UBOUND(InData%S,2) + DO i1 = LBOUND(InData%S,1), UBOUND(InData%S,1) + ReKiBuf(Re_Xferred) = InData%S(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%r,1), UBOUND(InData%r,1) + ReKiBuf(Re_Xferred) = InData%r(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%rd,1), UBOUND(InData%rd,1) + ReKiBuf(Re_Xferred) = InData%rd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE MD_PackConnect + + SUBROUTINE MD_UnPackConnect( 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(MD_Connect), 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 = 'MD_UnPackConnect' + ! 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%IdNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%type) + OutData%type(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%TypeNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AttachedFairs 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%AttachedFairs)) DEALLOCATE(OutData%AttachedFairs) + ALLOCATE(OutData%AttachedFairs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AttachedFairs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AttachedFairs,1), UBOUND(OutData%AttachedFairs,1) + OutData%AttachedFairs(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AttachedAnchs 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%AttachedAnchs)) DEALLOCATE(OutData%AttachedAnchs) + ALLOCATE(OutData%AttachedAnchs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AttachedAnchs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AttachedAnchs,1), UBOUND(OutData%AttachedAnchs,1) + OutData%AttachedAnchs(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%conX = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conFX = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conFY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conFZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conCa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%conCdA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%Ftot,1) + i1_u = UBOUND(OutData%Ftot,1) + DO i1 = LBOUND(OutData%Ftot,1), UBOUND(OutData%Ftot,1) + OutData%Ftot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%Mtot,1) + i1_u = UBOUND(OutData%Mtot,1) + i2_l = LBOUND(OutData%Mtot,2) + i2_u = UBOUND(OutData%Mtot,2) + DO i2 = LBOUND(OutData%Mtot,2), UBOUND(OutData%Mtot,2) + DO i1 = LBOUND(OutData%Mtot,1), UBOUND(OutData%Mtot,1) + OutData%Mtot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%S,1) + i1_u = UBOUND(OutData%S,1) + i2_l = LBOUND(OutData%S,2) + i2_u = UBOUND(OutData%S,2) + DO i2 = LBOUND(OutData%S,2), UBOUND(OutData%S,2) + DO i1 = LBOUND(OutData%S,1), UBOUND(OutData%S,1) + OutData%S(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%r,1) + i1_u = UBOUND(OutData%r,1) + DO i1 = LBOUND(OutData%r,1), UBOUND(OutData%r,1) + OutData%r(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%rd,1) + i1_u = UBOUND(OutData%rd,1) + DO i1 = LBOUND(OutData%rd,1), UBOUND(OutData%rd,1) + OutData%rd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE MD_UnPackConnect + + SUBROUTINE MD_CopyLine( SrcLineData, DstLineData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_Line), INTENT(IN) :: SrcLineData + TYPE(MD_Line), INTENT(INOUT) :: DstLineData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyLine' +! + ErrStat = ErrID_None + ErrMsg = "" + DstLineData%IdNum = SrcLineData%IdNum + DstLineData%type = SrcLineData%type + DstLineData%OutFlagList = SrcLineData%OutFlagList + DstLineData%CtrlChan = SrcLineData%CtrlChan + DstLineData%FairConnect = SrcLineData%FairConnect + DstLineData%AnchConnect = SrcLineData%AnchConnect + DstLineData%PropsIdNum = SrcLineData%PropsIdNum + DstLineData%N = SrcLineData%N + DstLineData%UnstrLen = SrcLineData%UnstrLen + DstLineData%BA = SrcLineData%BA +IF (ALLOCATED(SrcLineData%r)) THEN + i1_l = LBOUND(SrcLineData%r,1) + i1_u = UBOUND(SrcLineData%r,1) + i2_l = LBOUND(SrcLineData%r,2) + i2_u = UBOUND(SrcLineData%r,2) + IF (.NOT. ALLOCATED(DstLineData%r)) THEN + ALLOCATE(DstLineData%r(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%r.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%r = SrcLineData%r +ENDIF +IF (ALLOCATED(SrcLineData%rd)) THEN + i1_l = LBOUND(SrcLineData%rd,1) + i1_u = UBOUND(SrcLineData%rd,1) + i2_l = LBOUND(SrcLineData%rd,2) + i2_u = UBOUND(SrcLineData%rd,2) + IF (.NOT. ALLOCATED(DstLineData%rd)) THEN + ALLOCATE(DstLineData%rd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%rd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%rd = SrcLineData%rd +ENDIF +IF (ALLOCATED(SrcLineData%q)) THEN + i1_l = LBOUND(SrcLineData%q,1) + i1_u = UBOUND(SrcLineData%q,1) + i2_l = LBOUND(SrcLineData%q,2) + i2_u = UBOUND(SrcLineData%q,2) + IF (.NOT. ALLOCATED(DstLineData%q)) THEN + ALLOCATE(DstLineData%q(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%q.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%q = SrcLineData%q +ENDIF +IF (ALLOCATED(SrcLineData%l)) THEN + i1_l = LBOUND(SrcLineData%l,1) + i1_u = UBOUND(SrcLineData%l,1) + IF (.NOT. ALLOCATED(DstLineData%l)) THEN + ALLOCATE(DstLineData%l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%l = SrcLineData%l +ENDIF +IF (ALLOCATED(SrcLineData%ld)) THEN + i1_l = LBOUND(SrcLineData%ld,1) + i1_u = UBOUND(SrcLineData%ld,1) + IF (.NOT. ALLOCATED(DstLineData%ld)) THEN + ALLOCATE(DstLineData%ld(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%ld.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%ld = SrcLineData%ld +ENDIF +IF (ALLOCATED(SrcLineData%lstr)) THEN + i1_l = LBOUND(SrcLineData%lstr,1) + i1_u = UBOUND(SrcLineData%lstr,1) + IF (.NOT. ALLOCATED(DstLineData%lstr)) THEN + ALLOCATE(DstLineData%lstr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%lstr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%lstr = SrcLineData%lstr +ENDIF +IF (ALLOCATED(SrcLineData%lstrd)) THEN + i1_l = LBOUND(SrcLineData%lstrd,1) + i1_u = UBOUND(SrcLineData%lstrd,1) + IF (.NOT. ALLOCATED(DstLineData%lstrd)) THEN + ALLOCATE(DstLineData%lstrd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%lstrd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%lstrd = SrcLineData%lstrd +ENDIF +IF (ALLOCATED(SrcLineData%V)) THEN + i1_l = LBOUND(SrcLineData%V,1) + i1_u = UBOUND(SrcLineData%V,1) + IF (.NOT. ALLOCATED(DstLineData%V)) THEN + ALLOCATE(DstLineData%V(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%V.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%V = SrcLineData%V +ENDIF +IF (ALLOCATED(SrcLineData%T)) THEN + i1_l = LBOUND(SrcLineData%T,1) + i1_u = UBOUND(SrcLineData%T,1) + i2_l = LBOUND(SrcLineData%T,2) + i2_u = UBOUND(SrcLineData%T,2) + IF (.NOT. ALLOCATED(DstLineData%T)) THEN + ALLOCATE(DstLineData%T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%T = SrcLineData%T +ENDIF +IF (ALLOCATED(SrcLineData%Td)) THEN + i1_l = LBOUND(SrcLineData%Td,1) + i1_u = UBOUND(SrcLineData%Td,1) + i2_l = LBOUND(SrcLineData%Td,2) + i2_u = UBOUND(SrcLineData%Td,2) + IF (.NOT. ALLOCATED(DstLineData%Td)) THEN + ALLOCATE(DstLineData%Td(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%Td.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%Td = SrcLineData%Td +ENDIF +IF (ALLOCATED(SrcLineData%W)) THEN + i1_l = LBOUND(SrcLineData%W,1) + i1_u = UBOUND(SrcLineData%W,1) + i2_l = LBOUND(SrcLineData%W,2) + i2_u = UBOUND(SrcLineData%W,2) + IF (.NOT. ALLOCATED(DstLineData%W)) THEN + ALLOCATE(DstLineData%W(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%W.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%W = SrcLineData%W +ENDIF +IF (ALLOCATED(SrcLineData%Dp)) THEN + i1_l = LBOUND(SrcLineData%Dp,1) + i1_u = UBOUND(SrcLineData%Dp,1) + i2_l = LBOUND(SrcLineData%Dp,2) + i2_u = UBOUND(SrcLineData%Dp,2) + IF (.NOT. ALLOCATED(DstLineData%Dp)) THEN + ALLOCATE(DstLineData%Dp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%Dp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%Dp = SrcLineData%Dp +ENDIF +IF (ALLOCATED(SrcLineData%Dq)) THEN + i1_l = LBOUND(SrcLineData%Dq,1) + i1_u = UBOUND(SrcLineData%Dq,1) + i2_l = LBOUND(SrcLineData%Dq,2) + i2_u = UBOUND(SrcLineData%Dq,2) + IF (.NOT. ALLOCATED(DstLineData%Dq)) THEN + ALLOCATE(DstLineData%Dq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%Dq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%Dq = SrcLineData%Dq +ENDIF +IF (ALLOCATED(SrcLineData%Ap)) THEN + i1_l = LBOUND(SrcLineData%Ap,1) + i1_u = UBOUND(SrcLineData%Ap,1) + i2_l = LBOUND(SrcLineData%Ap,2) + i2_u = UBOUND(SrcLineData%Ap,2) + IF (.NOT. ALLOCATED(DstLineData%Ap)) THEN + ALLOCATE(DstLineData%Ap(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%Ap.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%Ap = SrcLineData%Ap +ENDIF +IF (ALLOCATED(SrcLineData%Aq)) THEN + i1_l = LBOUND(SrcLineData%Aq,1) + i1_u = UBOUND(SrcLineData%Aq,1) + i2_l = LBOUND(SrcLineData%Aq,2) + i2_u = UBOUND(SrcLineData%Aq,2) + IF (.NOT. ALLOCATED(DstLineData%Aq)) THEN + ALLOCATE(DstLineData%Aq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%Aq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%Aq = SrcLineData%Aq +ENDIF +IF (ALLOCATED(SrcLineData%B)) THEN + i1_l = LBOUND(SrcLineData%B,1) + i1_u = UBOUND(SrcLineData%B,1) + i2_l = LBOUND(SrcLineData%B,2) + i2_u = UBOUND(SrcLineData%B,2) + IF (.NOT. ALLOCATED(DstLineData%B)) THEN + ALLOCATE(DstLineData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%B = SrcLineData%B +ENDIF +IF (ALLOCATED(SrcLineData%F)) THEN + i1_l = LBOUND(SrcLineData%F,1) + i1_u = UBOUND(SrcLineData%F,1) + i2_l = LBOUND(SrcLineData%F,2) + i2_u = UBOUND(SrcLineData%F,2) + IF (.NOT. ALLOCATED(DstLineData%F)) THEN + ALLOCATE(DstLineData%F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%F = SrcLineData%F +ENDIF +IF (ALLOCATED(SrcLineData%S)) THEN + i1_l = LBOUND(SrcLineData%S,1) + i1_u = UBOUND(SrcLineData%S,1) + i2_l = LBOUND(SrcLineData%S,2) + i2_u = UBOUND(SrcLineData%S,2) + i3_l = LBOUND(SrcLineData%S,3) + i3_u = UBOUND(SrcLineData%S,3) + IF (.NOT. ALLOCATED(DstLineData%S)) THEN + ALLOCATE(DstLineData%S(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%S = SrcLineData%S +ENDIF +IF (ALLOCATED(SrcLineData%M)) THEN + i1_l = LBOUND(SrcLineData%M,1) + i1_u = UBOUND(SrcLineData%M,1) + i2_l = LBOUND(SrcLineData%M,2) + i2_u = UBOUND(SrcLineData%M,2) + i3_l = LBOUND(SrcLineData%M,3) + i3_u = UBOUND(SrcLineData%M,3) + IF (.NOT. ALLOCATED(DstLineData%M)) THEN + ALLOCATE(DstLineData%M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%M = SrcLineData%M +ENDIF + DstLineData%LineUnOut = SrcLineData%LineUnOut +IF (ALLOCATED(SrcLineData%LineWrOutput)) THEN + i1_l = LBOUND(SrcLineData%LineWrOutput,1) + i1_u = UBOUND(SrcLineData%LineWrOutput,1) + IF (.NOT. ALLOCATED(DstLineData%LineWrOutput)) THEN + ALLOCATE(DstLineData%LineWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLineData%LineWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLineData%LineWrOutput = SrcLineData%LineWrOutput +ENDIF + END SUBROUTINE MD_CopyLine + + SUBROUTINE MD_DestroyLine( LineData, ErrStat, ErrMsg ) + TYPE(MD_Line), INTENT(INOUT) :: LineData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyLine' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(LineData%r)) THEN + DEALLOCATE(LineData%r) +ENDIF +IF (ALLOCATED(LineData%rd)) THEN + DEALLOCATE(LineData%rd) +ENDIF +IF (ALLOCATED(LineData%q)) THEN + DEALLOCATE(LineData%q) +ENDIF +IF (ALLOCATED(LineData%l)) THEN + DEALLOCATE(LineData%l) +ENDIF +IF (ALLOCATED(LineData%ld)) THEN + DEALLOCATE(LineData%ld) +ENDIF +IF (ALLOCATED(LineData%lstr)) THEN + DEALLOCATE(LineData%lstr) +ENDIF +IF (ALLOCATED(LineData%lstrd)) THEN + DEALLOCATE(LineData%lstrd) +ENDIF +IF (ALLOCATED(LineData%V)) THEN + DEALLOCATE(LineData%V) +ENDIF +IF (ALLOCATED(LineData%T)) THEN + DEALLOCATE(LineData%T) +ENDIF +IF (ALLOCATED(LineData%Td)) THEN + DEALLOCATE(LineData%Td) +ENDIF +IF (ALLOCATED(LineData%W)) THEN + DEALLOCATE(LineData%W) +ENDIF +IF (ALLOCATED(LineData%Dp)) THEN + DEALLOCATE(LineData%Dp) +ENDIF +IF (ALLOCATED(LineData%Dq)) THEN + DEALLOCATE(LineData%Dq) +ENDIF +IF (ALLOCATED(LineData%Ap)) THEN + DEALLOCATE(LineData%Ap) +ENDIF +IF (ALLOCATED(LineData%Aq)) THEN + DEALLOCATE(LineData%Aq) +ENDIF +IF (ALLOCATED(LineData%B)) THEN + DEALLOCATE(LineData%B) +ENDIF +IF (ALLOCATED(LineData%F)) THEN + DEALLOCATE(LineData%F) +ENDIF +IF (ALLOCATED(LineData%S)) THEN + DEALLOCATE(LineData%S) +ENDIF +IF (ALLOCATED(LineData%M)) THEN + DEALLOCATE(LineData%M) +ENDIF +IF (ALLOCATED(LineData%LineWrOutput)) THEN + DEALLOCATE(LineData%LineWrOutput) +ENDIF + END SUBROUTINE MD_DestroyLine + + SUBROUTINE MD_PackLine( 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(MD_Line), 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 = 'MD_PackLine' + ! 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 ! IdNum + Int_BufSz = Int_BufSz + 1*LEN(InData%type) ! type + Int_BufSz = Int_BufSz + SIZE(InData%OutFlagList) ! OutFlagList + Int_BufSz = Int_BufSz + 1 ! CtrlChan + Int_BufSz = Int_BufSz + 1 ! FairConnect + Int_BufSz = Int_BufSz + 1 ! AnchConnect + Int_BufSz = Int_BufSz + 1 ! PropsIdNum + Int_BufSz = Int_BufSz + 1 ! N + Re_BufSz = Re_BufSz + 1 ! UnstrLen + Re_BufSz = Re_BufSz + 1 ! BA + Int_BufSz = Int_BufSz + 1 ! r allocated yes/no + IF ( ALLOCATED(InData%r) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! r upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%r) ! r + END IF + Int_BufSz = Int_BufSz + 1 ! rd allocated yes/no + IF ( ALLOCATED(InData%rd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! rd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%rd) ! rd + END IF + Int_BufSz = Int_BufSz + 1 ! q allocated yes/no + IF ( ALLOCATED(InData%q) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! q upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%q) ! q + END IF + Int_BufSz = Int_BufSz + 1 ! l allocated yes/no + IF ( ALLOCATED(InData%l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%l) ! l + END IF + Int_BufSz = Int_BufSz + 1 ! ld allocated yes/no + IF ( ALLOCATED(InData%ld) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ld upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ld) ! ld + END IF + Int_BufSz = Int_BufSz + 1 ! lstr allocated yes/no + IF ( ALLOCATED(InData%lstr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! lstr upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%lstr) ! lstr + END IF + Int_BufSz = Int_BufSz + 1 ! lstrd allocated yes/no + IF ( ALLOCATED(InData%lstrd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! lstrd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%lstrd) ! lstrd + 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 ! T allocated yes/no + IF ( ALLOCATED(InData%T) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! T upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%T) ! T + END IF + Int_BufSz = Int_BufSz + 1 ! Td allocated yes/no + IF ( ALLOCATED(InData%Td) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Td upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Td) ! Td + END IF + Int_BufSz = Int_BufSz + 1 ! W allocated yes/no + IF ( ALLOCATED(InData%W) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! W upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%W) ! W + END IF + Int_BufSz = Int_BufSz + 1 ! Dp allocated yes/no + IF ( ALLOCATED(InData%Dp) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Dp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Dp) ! Dp + END IF + Int_BufSz = Int_BufSz + 1 ! Dq allocated yes/no + IF ( ALLOCATED(InData%Dq) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Dq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Dq) ! Dq + END IF + Int_BufSz = Int_BufSz + 1 ! Ap allocated yes/no + IF ( ALLOCATED(InData%Ap) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Ap upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Ap) ! Ap + END IF + Int_BufSz = Int_BufSz + 1 ! Aq allocated yes/no + IF ( ALLOCATED(InData%Aq) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Aq upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Aq) ! Aq + END IF + Int_BufSz = Int_BufSz + 1 ! B allocated yes/no + IF ( ALLOCATED(InData%B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%B) ! B + END IF + Int_BufSz = Int_BufSz + 1 ! F allocated yes/no + IF ( ALLOCATED(InData%F) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + END IF + Int_BufSz = Int_BufSz + 1 ! S allocated yes/no + IF ( ALLOCATED(InData%S) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! S upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%S) ! S + END IF + Int_BufSz = Int_BufSz + 1 ! M allocated yes/no + IF ( ALLOCATED(InData%M) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + END IF + Int_BufSz = Int_BufSz + 1 ! LineUnOut + Int_BufSz = Int_BufSz + 1 ! LineWrOutput allocated yes/no + IF ( ALLOCATED(InData%LineWrOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineWrOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LineWrOutput) ! LineWrOutput + 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%IdNum + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%type) + IntKiBuf(Int_Xferred) = ICHAR(InData%type(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%OutFlagList,1), UBOUND(InData%OutFlagList,1) + IntKiBuf(Int_Xferred) = InData%OutFlagList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%CtrlChan + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%FairConnect + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AnchConnect + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PropsIdNum + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%N + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UnstrLen + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BA + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%r) ) 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%r,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%r,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%r,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%r,2), UBOUND(InData%r,2) + DO i1 = LBOUND(InData%r,1), UBOUND(InData%r,1) + ReKiBuf(Re_Xferred) = InData%r(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%rd) ) 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%rd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%rd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%rd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%rd,2), UBOUND(InData%rd,2) + DO i1 = LBOUND(InData%rd,1), UBOUND(InData%rd,1) + ReKiBuf(Re_Xferred) = InData%rd(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%q) ) 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%q,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%q,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%q,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%q,2), UBOUND(InData%q,2) + DO i1 = LBOUND(InData%q,1), UBOUND(InData%q,1) + ReKiBuf(Re_Xferred) = InData%q(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%l) ) 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%l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%l,1), UBOUND(InData%l,1) + ReKiBuf(Re_Xferred) = InData%l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ld) ) 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%ld,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ld,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ld,1), UBOUND(InData%ld,1) + ReKiBuf(Re_Xferred) = InData%ld(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%lstr) ) 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%lstr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lstr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%lstr,1), UBOUND(InData%lstr,1) + ReKiBuf(Re_Xferred) = InData%lstr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%lstrd) ) 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%lstrd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lstrd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%lstrd,1), UBOUND(InData%lstrd,1) + ReKiBuf(Re_Xferred) = InData%lstrd(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%T) ) 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%T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%T,2), UBOUND(InData%T,2) + DO i1 = LBOUND(InData%T,1), UBOUND(InData%T,1) + ReKiBuf(Re_Xferred) = InData%T(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Td) ) 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%Td,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Td,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Td,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Td,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Td,2), UBOUND(InData%Td,2) + DO i1 = LBOUND(InData%Td,1), UBOUND(InData%Td,1) + ReKiBuf(Re_Xferred) = InData%Td(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%W) ) 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%W,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%W,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%W,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%W,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%W,2), UBOUND(InData%W,2) + DO i1 = LBOUND(InData%W,1), UBOUND(InData%W,1) + ReKiBuf(Re_Xferred) = InData%W(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Dp) ) 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%Dp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dp,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Dp,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dp,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Dp,2), UBOUND(InData%Dp,2) + DO i1 = LBOUND(InData%Dp,1), UBOUND(InData%Dp,1) + ReKiBuf(Re_Xferred) = InData%Dp(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Dq) ) 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%Dq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dq,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Dq,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Dq,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Dq,2), UBOUND(InData%Dq,2) + DO i1 = LBOUND(InData%Dq,1), UBOUND(InData%Dq,1) + ReKiBuf(Re_Xferred) = InData%Dq(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Ap) ) 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%Ap,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ap,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ap,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ap,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Ap,2), UBOUND(InData%Ap,2) + DO i1 = LBOUND(InData%Ap,1), UBOUND(InData%Ap,1) + ReKiBuf(Re_Xferred) = InData%Ap(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Aq) ) 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%Aq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Aq,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Aq,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Aq,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Aq,2), UBOUND(InData%Aq,2) + DO i1 = LBOUND(InData%Aq,1), UBOUND(InData%Aq,1) + ReKiBuf(Re_Xferred) = InData%Aq(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%B) ) 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%B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%B,2), UBOUND(InData%B,2) + DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) + ReKiBuf(Re_Xferred) = InData%B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F) ) 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%F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F,2), UBOUND(InData%F,2) + DO i1 = LBOUND(InData%F,1), UBOUND(InData%F,1) + ReKiBuf(Re_Xferred) = InData%F(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%S) ) 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%S,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%S,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%S,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%S,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%S,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%S,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%S,3), UBOUND(InData%S,3) + DO i2 = LBOUND(InData%S,2), UBOUND(InData%S,2) + DO i1 = LBOUND(InData%S,1), UBOUND(InData%S,1) + ReKiBuf(Re_Xferred) = InData%S(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M) ) 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%M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%M,3), UBOUND(InData%M,3) + DO i2 = LBOUND(InData%M,2), UBOUND(InData%M,2) + DO i1 = LBOUND(InData%M,1), UBOUND(InData%M,1) + ReKiBuf(Re_Xferred) = InData%M(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%LineUnOut + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LineWrOutput) ) 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%LineWrOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineWrOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineWrOutput,1), UBOUND(InData%LineWrOutput,1) + ReKiBuf(Re_Xferred) = InData%LineWrOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_PackLine + + SUBROUTINE MD_UnPackLine( 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(MD_Line), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_UnPackLine' + ! 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%IdNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%type) + OutData%type(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%OutFlagList,1) + i1_u = UBOUND(OutData%OutFlagList,1) + DO i1 = LBOUND(OutData%OutFlagList,1), UBOUND(OutData%OutFlagList,1) + OutData%OutFlagList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%CtrlChan = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FairConnect = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AnchConnect = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PropsIdNum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%N = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnstrLen = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%BA = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r 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%r)) DEALLOCATE(OutData%r) + ALLOCATE(OutData%r(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%r.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%r,2), UBOUND(OutData%r,2) + DO i1 = LBOUND(OutData%r,1), UBOUND(OutData%r,1) + OutData%r(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! rd 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%rd)) DEALLOCATE(OutData%rd) + ALLOCATE(OutData%rd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%rd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%rd,2), UBOUND(OutData%rd,2) + DO i1 = LBOUND(OutData%rd,1), UBOUND(OutData%rd,1) + OutData%rd(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! q 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%q)) DEALLOCATE(OutData%q) + ALLOCATE(OutData%q(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%q.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%q,2), UBOUND(OutData%q,2) + DO i1 = LBOUND(OutData%q,1), UBOUND(OutData%q,1) + OutData%q(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! l 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%l)) DEALLOCATE(OutData%l) + ALLOCATE(OutData%l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%l,1), UBOUND(OutData%l,1) + OutData%l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ld 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%ld)) DEALLOCATE(OutData%ld) + ALLOCATE(OutData%ld(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ld.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ld,1), UBOUND(OutData%ld,1) + OutData%ld(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstr 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%lstr)) DEALLOCATE(OutData%lstr) + ALLOCATE(OutData%lstr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lstr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%lstr,1), UBOUND(OutData%lstr,1) + OutData%lstr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstrd 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%lstrd)) DEALLOCATE(OutData%lstrd) + ALLOCATE(OutData%lstrd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lstrd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%lstrd,1), UBOUND(OutData%lstrd,1) + OutData%lstrd(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 ! T 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%T)) DEALLOCATE(OutData%T) + ALLOCATE(OutData%T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%T,2), UBOUND(OutData%T,2) + DO i1 = LBOUND(OutData%T,1), UBOUND(OutData%T,1) + OutData%T(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Td 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%Td)) DEALLOCATE(OutData%Td) + ALLOCATE(OutData%Td(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Td.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Td,2), UBOUND(OutData%Td,2) + DO i1 = LBOUND(OutData%Td,1), UBOUND(OutData%Td,1) + OutData%Td(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! W 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%W)) DEALLOCATE(OutData%W) + ALLOCATE(OutData%W(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%W.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%W,2), UBOUND(OutData%W,2) + DO i1 = LBOUND(OutData%W,1), UBOUND(OutData%W,1) + OutData%W(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Dp 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%Dp)) DEALLOCATE(OutData%Dp) + ALLOCATE(OutData%Dp(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Dp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Dp,2), UBOUND(OutData%Dp,2) + DO i1 = LBOUND(OutData%Dp,1), UBOUND(OutData%Dp,1) + OutData%Dp(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Dq 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%Dq)) DEALLOCATE(OutData%Dq) + ALLOCATE(OutData%Dq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Dq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Dq,2), UBOUND(OutData%Dq,2) + DO i1 = LBOUND(OutData%Dq,1), UBOUND(OutData%Dq,1) + OutData%Dq(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ap 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%Ap)) DEALLOCATE(OutData%Ap) + ALLOCATE(OutData%Ap(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ap.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Ap,2), UBOUND(OutData%Ap,2) + DO i1 = LBOUND(OutData%Ap,1), UBOUND(OutData%Ap,1) + OutData%Ap(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Aq 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%Aq)) DEALLOCATE(OutData%Aq) + ALLOCATE(OutData%Aq(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Aq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Aq,2), UBOUND(OutData%Aq,2) + DO i1 = LBOUND(OutData%Aq,1), UBOUND(OutData%Aq,1) + OutData%Aq(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! B 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%B)) DEALLOCATE(OutData%B) + ALLOCATE(OutData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%B,2), UBOUND(OutData%B,2) + DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) + OutData%B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F 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%F)) DEALLOCATE(OutData%F) + ALLOCATE(OutData%F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F,2), UBOUND(OutData%F,2) + DO i1 = LBOUND(OutData%F,1), UBOUND(OutData%F,1) + OutData%F(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! S 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%S)) DEALLOCATE(OutData%S) + ALLOCATE(OutData%S(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%S.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%S,3), UBOUND(OutData%S,3) + DO i2 = LBOUND(OutData%S,2), UBOUND(OutData%S,2) + DO i1 = LBOUND(OutData%S,1), UBOUND(OutData%S,1) + OutData%S(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M 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%M)) DEALLOCATE(OutData%M) + ALLOCATE(OutData%M(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%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%M,3), UBOUND(OutData%M,3) + DO i2 = LBOUND(OutData%M,2), UBOUND(OutData%M,2) + DO i1 = LBOUND(OutData%M,1), UBOUND(OutData%M,1) + OutData%M(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%LineUnOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineWrOutput 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%LineWrOutput)) DEALLOCATE(OutData%LineWrOutput) + ALLOCATE(OutData%LineWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineWrOutput,1), UBOUND(OutData%LineWrOutput,1) + OutData%LineWrOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_UnPackLine + + SUBROUTINE MD_CopyOutParmType( SrcOutParmTypeData, DstOutParmTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_OutParmType), INTENT(IN) :: SrcOutParmTypeData + TYPE(MD_OutParmType), INTENT(INOUT) :: DstOutParmTypeData + 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 = 'MD_CopyOutParmType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutParmTypeData%Name = SrcOutParmTypeData%Name + DstOutParmTypeData%Units = SrcOutParmTypeData%Units + DstOutParmTypeData%QType = SrcOutParmTypeData%QType + DstOutParmTypeData%OType = SrcOutParmTypeData%OType + DstOutParmTypeData%NodeID = SrcOutParmTypeData%NodeID + DstOutParmTypeData%ObjID = SrcOutParmTypeData%ObjID + END SUBROUTINE MD_CopyOutParmType + + SUBROUTINE MD_DestroyOutParmType( OutParmTypeData, ErrStat, ErrMsg ) + TYPE(MD_OutParmType), INTENT(INOUT) :: OutParmTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyOutParmType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MD_DestroyOutParmType + + SUBROUTINE MD_PackOutParmType( 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(MD_OutParmType), 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 = 'MD_PackOutParmType' + ! 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%Name) ! Name + Int_BufSz = Int_BufSz + 1*LEN(InData%Units) ! Units + Int_BufSz = Int_BufSz + 1 ! QType + Int_BufSz = Int_BufSz + 1 ! OType + Int_BufSz = Int_BufSz + 1 ! NodeID + Int_BufSz = Int_BufSz + 1 ! ObjID + 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%Name) + IntKiBuf(Int_Xferred) = ICHAR(InData%Name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Units) + IntKiBuf(Int_Xferred) = ICHAR(InData%Units(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%QType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NodeID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ObjID + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MD_PackOutParmType + + SUBROUTINE MD_UnPackOutParmType( 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(MD_OutParmType), 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 = 'MD_UnPackOutParmType' + ! 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%Name) + OutData%Name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Units) + OutData%Units(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%QType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NodeID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ObjID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MD_UnPackOutParmType + + SUBROUTINE MD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(MD_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 = 'MD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%writeOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%writeOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%writeOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%writeOutputHdr)) THEN + ALLOCATE(DstInitOutputData%writeOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%writeOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%writeOutputHdr = SrcInitOutputData%writeOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%writeOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%writeOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%writeOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%writeOutputUnt)) THEN + ALLOCATE(DstInitOutputData%writeOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%writeOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%writeOutputUnt = SrcInitOutputData%writeOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE MD_CopyInitOutput + + SUBROUTINE MD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(MD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%writeOutputHdr)) THEN + DEALLOCATE(InitOutputData%writeOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%writeOutputUnt)) THEN + DEALLOCATE(InitOutputData%writeOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE MD_DestroyInitOutput + + SUBROUTINE MD_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(MD_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 = 'MD_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 + Int_BufSz = Int_BufSz + 1 ! writeOutputHdr allocated yes/no + IF ( ALLOCATED(InData%writeOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! writeOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%writeOutputHdr)*LEN(InData%writeOutputHdr) ! writeOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! writeOutputUnt allocated yes/no + IF ( ALLOCATED(InData%writeOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! writeOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%writeOutputUnt)*LEN(InData%writeOutputUnt) ! writeOutputUnt + END IF + ! 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 + + IF ( .NOT. ALLOCATED(InData%writeOutputHdr) ) 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%writeOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%writeOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%writeOutputHdr,1), UBOUND(InData%writeOutputHdr,1) + DO I = 1, LEN(InData%writeOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%writeOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%writeOutputUnt) ) 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%writeOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%writeOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%writeOutputUnt,1), UBOUND(InData%writeOutputUnt,1) + DO I = 1, LEN(InData%writeOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%writeOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 MD_PackInitOutput + + SUBROUTINE MD_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(MD_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 = 'MD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! writeOutputHdr 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%writeOutputHdr)) DEALLOCATE(OutData%writeOutputHdr) + ALLOCATE(OutData%writeOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%writeOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%writeOutputHdr,1), UBOUND(OutData%writeOutputHdr,1) + DO I = 1, LEN(OutData%writeOutputHdr) + OutData%writeOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! writeOutputUnt 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%writeOutputUnt)) DEALLOCATE(OutData%writeOutputUnt) + ALLOCATE(OutData%writeOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%writeOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%writeOutputUnt,1), UBOUND(OutData%writeOutputUnt,1) + DO I = 1, LEN(OutData%writeOutputUnt) + OutData%writeOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 MD_UnPackInitOutput + + SUBROUTINE MD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%states)) THEN + i1_l = LBOUND(SrcContStateData%states,1) + i1_u = UBOUND(SrcContStateData%states,1) + IF (.NOT. ALLOCATED(DstContStateData%states)) THEN + ALLOCATE(DstContStateData%states(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%states.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%states = SrcContStateData%states +ENDIF + END SUBROUTINE MD_CopyContState + + SUBROUTINE MD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(MD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%states)) THEN + DEALLOCATE(ContStateData%states) +ENDIF + END SUBROUTINE MD_DestroyContState + + SUBROUTINE MD_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(MD_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 = 'MD_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 + Int_BufSz = Int_BufSz + 1 ! states allocated yes/no + IF ( ALLOCATED(InData%states) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! states upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%states) ! states + 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%states) ) 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%states,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%states,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%states,1), UBOUND(InData%states,1) + ReKiBuf(Re_Xferred) = InData%states(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_PackContState + + SUBROUTINE MD_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(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! states 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%states)) DEALLOCATE(OutData%states) + ALLOCATE(OutData%states(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%states.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%states,1), UBOUND(OutData%states,1) + OutData%states(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_UnPackContState + + SUBROUTINE MD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(MD_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 = 'MD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%dummy = SrcDiscStateData%dummy + END SUBROUTINE MD_CopyDiscState + + SUBROUTINE MD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(MD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MD_DestroyDiscState + + SUBROUTINE MD_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(MD_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 = 'MD_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 ! 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 MD_PackDiscState + + SUBROUTINE MD_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(MD_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 = 'MD_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%dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE MD_UnPackDiscState + + SUBROUTINE MD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(MD_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 = 'MD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%dummy = SrcConstrStateData%dummy + END SUBROUTINE MD_CopyConstrState + + SUBROUTINE MD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(MD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MD_DestroyConstrState + + SUBROUTINE MD_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(MD_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 = 'MD_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 ! 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 MD_PackConstrState + + SUBROUTINE MD_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(MD_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 = 'MD_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%dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE MD_UnPackConstrState + + SUBROUTINE MD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(MD_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 = 'MD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%dummy = SrcOtherStateData%dummy + END SUBROUTINE MD_CopyOtherState + + SUBROUTINE MD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(MD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE MD_DestroyOtherState + + SUBROUTINE MD_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(MD_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 = 'MD_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 ! 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 MD_PackOtherState + + SUBROUTINE MD_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(MD_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 = 'MD_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%dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE MD_UnPackOtherState + + SUBROUTINE MD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%LineTypeList)) THEN + i1_l = LBOUND(SrcMiscData%LineTypeList,1) + i1_u = UBOUND(SrcMiscData%LineTypeList,1) + IF (.NOT. ALLOCATED(DstMiscData%LineTypeList)) THEN + ALLOCATE(DstMiscData%LineTypeList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LineTypeList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%LineTypeList,1), UBOUND(SrcMiscData%LineTypeList,1) + CALL MD_Copylineprop( SrcMiscData%LineTypeList(i1), DstMiscData%LineTypeList(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%ConnectList)) THEN + i1_l = LBOUND(SrcMiscData%ConnectList,1) + i1_u = UBOUND(SrcMiscData%ConnectList,1) + IF (.NOT. ALLOCATED(DstMiscData%ConnectList)) THEN + ALLOCATE(DstMiscData%ConnectList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ConnectList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%ConnectList,1), UBOUND(SrcMiscData%ConnectList,1) + CALL MD_Copyconnect( SrcMiscData%ConnectList(i1), DstMiscData%ConnectList(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%LineList)) THEN + i1_l = LBOUND(SrcMiscData%LineList,1) + i1_u = UBOUND(SrcMiscData%LineList,1) + IF (.NOT. ALLOCATED(DstMiscData%LineList)) THEN + ALLOCATE(DstMiscData%LineList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LineList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%LineList,1), UBOUND(SrcMiscData%LineList,1) + CALL MD_Copyline( SrcMiscData%LineList(i1), DstMiscData%LineList(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%FairIdList)) THEN + i1_l = LBOUND(SrcMiscData%FairIdList,1) + i1_u = UBOUND(SrcMiscData%FairIdList,1) + IF (.NOT. ALLOCATED(DstMiscData%FairIdList)) THEN + ALLOCATE(DstMiscData%FairIdList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FairIdList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FairIdList = SrcMiscData%FairIdList +ENDIF +IF (ALLOCATED(SrcMiscData%ConnIdList)) THEN + i1_l = LBOUND(SrcMiscData%ConnIdList,1) + i1_u = UBOUND(SrcMiscData%ConnIdList,1) + IF (.NOT. ALLOCATED(DstMiscData%ConnIdList)) THEN + ALLOCATE(DstMiscData%ConnIdList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ConnIdList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%ConnIdList = SrcMiscData%ConnIdList +ENDIF +IF (ALLOCATED(SrcMiscData%LineStateIndList)) THEN + i1_l = LBOUND(SrcMiscData%LineStateIndList,1) + i1_u = UBOUND(SrcMiscData%LineStateIndList,1) + IF (.NOT. ALLOCATED(DstMiscData%LineStateIndList)) THEN + ALLOCATE(DstMiscData%LineStateIndList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LineStateIndList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%LineStateIndList = SrcMiscData%LineStateIndList +ENDIF +IF (ALLOCATED(SrcMiscData%MDWrOutput)) THEN + i1_l = LBOUND(SrcMiscData%MDWrOutput,1) + i1_u = UBOUND(SrcMiscData%MDWrOutput,1) + IF (.NOT. ALLOCATED(DstMiscData%MDWrOutput)) THEN + ALLOCATE(DstMiscData%MDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%MDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%MDWrOutput = SrcMiscData%MDWrOutput +ENDIF + END SUBROUTINE MD_CopyMisc + + SUBROUTINE MD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(MD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%LineTypeList)) THEN +DO i1 = LBOUND(MiscData%LineTypeList,1), UBOUND(MiscData%LineTypeList,1) + CALL MD_Destroylineprop( MiscData%LineTypeList(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%LineTypeList) +ENDIF +IF (ALLOCATED(MiscData%ConnectList)) THEN +DO i1 = LBOUND(MiscData%ConnectList,1), UBOUND(MiscData%ConnectList,1) + CALL MD_Destroyconnect( MiscData%ConnectList(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%ConnectList) +ENDIF +IF (ALLOCATED(MiscData%LineList)) THEN +DO i1 = LBOUND(MiscData%LineList,1), UBOUND(MiscData%LineList,1) + CALL MD_Destroyline( MiscData%LineList(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%LineList) +ENDIF +IF (ALLOCATED(MiscData%FairIdList)) THEN + DEALLOCATE(MiscData%FairIdList) +ENDIF +IF (ALLOCATED(MiscData%ConnIdList)) THEN + DEALLOCATE(MiscData%ConnIdList) +ENDIF +IF (ALLOCATED(MiscData%LineStateIndList)) THEN + DEALLOCATE(MiscData%LineStateIndList) +ENDIF +IF (ALLOCATED(MiscData%MDWrOutput)) THEN + DEALLOCATE(MiscData%MDWrOutput) +ENDIF + END SUBROUTINE MD_DestroyMisc + + SUBROUTINE MD_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(MD_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 = 'MD_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 ! LineTypeList allocated yes/no + IF ( ALLOCATED(InData%LineTypeList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineTypeList upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%LineTypeList,1), UBOUND(InData%LineTypeList,1) + Int_BufSz = Int_BufSz + 3 ! LineTypeList: size of buffers for each call to pack subtype + CALL MD_Packlineprop( Re_Buf, Db_Buf, Int_Buf, InData%LineTypeList(i1), ErrStat2, ErrMsg2, .TRUE. ) ! LineTypeList + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LineTypeList + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LineTypeList + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LineTypeList + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ConnectList allocated yes/no + IF ( ALLOCATED(InData%ConnectList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ConnectList upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ConnectList,1), UBOUND(InData%ConnectList,1) + Int_BufSz = Int_BufSz + 3 ! ConnectList: size of buffers for each call to pack subtype + CALL MD_Packconnect( Re_Buf, Db_Buf, Int_Buf, InData%ConnectList(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ConnectList + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ConnectList + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ConnectList + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ConnectList + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! LineList allocated yes/no + IF ( ALLOCATED(InData%LineList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineList upper/lower bounds for each dimension + DO i1 = LBOUND(InData%LineList,1), UBOUND(InData%LineList,1) + Int_BufSz = Int_BufSz + 3 ! LineList: size of buffers for each call to pack subtype + CALL MD_Packline( Re_Buf, Db_Buf, Int_Buf, InData%LineList(i1), ErrStat2, ErrMsg2, .TRUE. ) ! LineList + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LineList + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LineList + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LineList + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! FairIdList allocated yes/no + IF ( ALLOCATED(InData%FairIdList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FairIdList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FairIdList) ! FairIdList + END IF + Int_BufSz = Int_BufSz + 1 ! ConnIdList allocated yes/no + IF ( ALLOCATED(InData%ConnIdList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ConnIdList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ConnIdList) ! ConnIdList + END IF + Int_BufSz = Int_BufSz + 1 ! LineStateIndList allocated yes/no + IF ( ALLOCATED(InData%LineStateIndList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LineStateIndList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LineStateIndList) ! LineStateIndList + END IF + Int_BufSz = Int_BufSz + 1 ! MDWrOutput allocated yes/no + IF ( ALLOCATED(InData%MDWrOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MDWrOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MDWrOutput) ! MDWrOutput + 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%LineTypeList) ) 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%LineTypeList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineTypeList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineTypeList,1), UBOUND(InData%LineTypeList,1) + CALL MD_Packlineprop( Re_Buf, Db_Buf, Int_Buf, InData%LineTypeList(i1), ErrStat2, ErrMsg2, OnlySize ) ! LineTypeList + 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%ConnectList) ) 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%ConnectList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ConnectList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ConnectList,1), UBOUND(InData%ConnectList,1) + CALL MD_Packconnect( Re_Buf, Db_Buf, Int_Buf, InData%ConnectList(i1), ErrStat2, ErrMsg2, OnlySize ) ! ConnectList + 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%LineList) ) 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%LineList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineList,1), UBOUND(InData%LineList,1) + CALL MD_Packline( Re_Buf, Db_Buf, Int_Buf, InData%LineList(i1), ErrStat2, ErrMsg2, OnlySize ) ! LineList + 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%FairIdList) ) 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%FairIdList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FairIdList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FairIdList,1), UBOUND(InData%FairIdList,1) + IntKiBuf(Int_Xferred) = InData%FairIdList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ConnIdList) ) 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%ConnIdList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ConnIdList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ConnIdList,1), UBOUND(InData%ConnIdList,1) + IntKiBuf(Int_Xferred) = InData%ConnIdList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LineStateIndList) ) 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%LineStateIndList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LineStateIndList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LineStateIndList,1), UBOUND(InData%LineStateIndList,1) + IntKiBuf(Int_Xferred) = InData%LineStateIndList(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MDWrOutput) ) 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%MDWrOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MDWrOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MDWrOutput,1), UBOUND(InData%MDWrOutput,1) + ReKiBuf(Re_Xferred) = InData%MDWrOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_PackMisc + + SUBROUTINE MD_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(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_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 ! LineTypeList 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%LineTypeList)) DEALLOCATE(OutData%LineTypeList) + ALLOCATE(OutData%LineTypeList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineTypeList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineTypeList,1), UBOUND(OutData%LineTypeList,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 MD_Unpacklineprop( Re_Buf, Db_Buf, Int_Buf, OutData%LineTypeList(i1), ErrStat2, ErrMsg2 ) ! LineTypeList + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ConnectList 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%ConnectList)) DEALLOCATE(OutData%ConnectList) + ALLOCATE(OutData%ConnectList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ConnectList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ConnectList,1), UBOUND(OutData%ConnectList,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 MD_Unpackconnect( Re_Buf, Db_Buf, Int_Buf, OutData%ConnectList(i1), ErrStat2, ErrMsg2 ) ! ConnectList + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineList 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%LineList)) DEALLOCATE(OutData%LineList) + ALLOCATE(OutData%LineList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineList,1), UBOUND(OutData%LineList,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 MD_Unpackline( Re_Buf, Db_Buf, Int_Buf, OutData%LineList(i1), ErrStat2, ErrMsg2 ) ! LineList + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FairIdList 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%FairIdList)) DEALLOCATE(OutData%FairIdList) + ALLOCATE(OutData%FairIdList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FairIdList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FairIdList,1), UBOUND(OutData%FairIdList,1) + OutData%FairIdList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ConnIdList 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%ConnIdList)) DEALLOCATE(OutData%ConnIdList) + ALLOCATE(OutData%ConnIdList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ConnIdList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ConnIdList,1), UBOUND(OutData%ConnIdList,1) + OutData%ConnIdList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LineStateIndList 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%LineStateIndList)) DEALLOCATE(OutData%LineStateIndList) + ALLOCATE(OutData%LineStateIndList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LineStateIndList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LineStateIndList,1), UBOUND(OutData%LineStateIndList,1) + OutData%LineStateIndList(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MDWrOutput 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%MDWrOutput)) DEALLOCATE(OutData%MDWrOutput) + ALLOCATE(OutData%MDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MDWrOutput,1), UBOUND(OutData%MDWrOutput,1) + OutData%MDWrOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_UnPackMisc + + SUBROUTINE MD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(MD_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 = 'MD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%NTypes = SrcParamData%NTypes + DstParamData%NConnects = SrcParamData%NConnects + DstParamData%NFairs = SrcParamData%NFairs + DstParamData%NConns = SrcParamData%NConns + DstParamData%NAnchs = SrcParamData%NAnchs + DstParamData%NLines = SrcParamData%NLines + DstParamData%g = SrcParamData%g + DstParamData%rhoW = SrcParamData%rhoW + DstParamData%WtrDpth = SrcParamData%WtrDpth + DstParamData%kBot = SrcParamData%kBot + DstParamData%cBot = SrcParamData%cBot + DstParamData%dtM0 = SrcParamData%dtM0 + DstParamData%dtCoupling = SrcParamData%dtCoupling + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL MD_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%Delim = SrcParamData%Delim + DstParamData%MDUnOut = SrcParamData%MDUnOut + END SUBROUTINE MD_CopyParam + + SUBROUTINE MD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(MD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL MD_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE MD_DestroyParam + + SUBROUTINE MD_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(MD_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 = 'MD_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 ! NTypes + Int_BufSz = Int_BufSz + 1 ! NConnects + Int_BufSz = Int_BufSz + 1 ! NFairs + Int_BufSz = Int_BufSz + 1 ! NConns + Int_BufSz = Int_BufSz + 1 ! NAnchs + Int_BufSz = Int_BufSz + 1 ! NLines + Re_BufSz = Re_BufSz + 1 ! g + Re_BufSz = Re_BufSz + 1 ! rhoW + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + 1 ! kBot + Re_BufSz = Re_BufSz + 1 ! cBot + Re_BufSz = Re_BufSz + 1 ! dtM0 + Re_BufSz = Re_BufSz + 1 ! dtCoupling + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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 MD_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! MDUnOut + 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%NTypes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NConnects + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NFairs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NConns + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NAnchs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NLines + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%rhoW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%kBot + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%cBot + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dtM0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dtCoupling + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 MD_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 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%MDUnOut + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MD_PackParam + + SUBROUTINE MD_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(MD_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 = 'MD_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%NTypes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NConnects = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NFairs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NConns = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NAnchs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NLines = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%rhoW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%kBot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%cBot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dtM0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dtCoupling = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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 MD_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%MDUnOut = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE MD_UnPackParam + + SUBROUTINE MD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%PtFairleadDisplacement, DstInputData%PtFairleadDisplacement, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%DeltaL)) THEN + i1_l = LBOUND(SrcInputData%DeltaL,1) + i1_u = UBOUND(SrcInputData%DeltaL,1) + IF (.NOT. ALLOCATED(DstInputData%DeltaL)) THEN + ALLOCATE(DstInputData%DeltaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%DeltaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%DeltaL = SrcInputData%DeltaL +ENDIF +IF (ALLOCATED(SrcInputData%DeltaLdot)) THEN + i1_l = LBOUND(SrcInputData%DeltaLdot,1) + i1_u = UBOUND(SrcInputData%DeltaLdot,1) + IF (.NOT. ALLOCATED(DstInputData%DeltaLdot)) THEN + ALLOCATE(DstInputData%DeltaLdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%DeltaLdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%DeltaLdot = SrcInputData%DeltaLdot +ENDIF + END SUBROUTINE MD_CopyInput + + SUBROUTINE MD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(MD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%PtFairleadDisplacement, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%DeltaL)) THEN + DEALLOCATE(InputData%DeltaL) +ENDIF +IF (ALLOCATED(InputData%DeltaLdot)) THEN + DEALLOCATE(InputData%DeltaLdot) +ENDIF + END SUBROUTINE MD_DestroyInput + + SUBROUTINE MD_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(MD_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 = 'MD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PtFairleadDisplacement: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtFairleadDisplacement + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtFairleadDisplacement + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtFairleadDisplacement + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtFairleadDisplacement + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! DeltaL allocated yes/no + IF ( ALLOCATED(InData%DeltaL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DeltaL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DeltaL) ! DeltaL + END IF + Int_BufSz = Int_BufSz + 1 ! DeltaLdot allocated yes/no + IF ( ALLOCATED(InData%DeltaLdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DeltaLdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DeltaLdot) ! DeltaLdot + 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 MeshPack( InData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtFairleadDisplacement + 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%DeltaL) ) 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%DeltaL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DeltaL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DeltaL,1), UBOUND(InData%DeltaL,1) + ReKiBuf(Re_Xferred) = InData%DeltaL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DeltaLdot) ) 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%DeltaLdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DeltaLdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DeltaLdot,1), UBOUND(InData%DeltaLdot,1) + ReKiBuf(Re_Xferred) = InData%DeltaLdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_PackInput + + SUBROUTINE MD_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(MD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MD_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 + 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 MeshUnpack( OutData%PtFairleadDisplacement, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtFairleadDisplacement + 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 ! DeltaL 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%DeltaL)) DEALLOCATE(OutData%DeltaL) + ALLOCATE(OutData%DeltaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DeltaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DeltaL,1), UBOUND(OutData%DeltaL,1) + OutData%DeltaL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DeltaLdot 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%DeltaLdot)) DEALLOCATE(OutData%DeltaLdot) + ALLOCATE(OutData%DeltaLdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DeltaLdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DeltaLdot,1), UBOUND(OutData%DeltaLdot,1) + OutData%DeltaLdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_UnPackInput + + SUBROUTINE MD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(MD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'MD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%PtFairleadLoad, DstOutputData%PtFairleadLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE MD_CopyOutput + + SUBROUTINE MD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(MD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%PtFairleadLoad, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE MD_DestroyOutput + + SUBROUTINE MD_PackOutput( 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(MD_OutputType), 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 = 'MD_PackOutput' + ! 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 ! PtFairleadLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtFairleadLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtFairleadLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtFairleadLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtFairleadLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtFairleadLoad + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_PackOutput + + SUBROUTINE MD_UnPackOutput( 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(MD_OutputType), 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 = 'MD_UnPackOutput' + ! 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 MeshUnpack( OutData%PtFairleadLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtFairleadLoad + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE MD_UnPackOutput + + + SUBROUTINE MD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(MD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(MD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL MD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL MD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL MD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE MD_Input_ExtrapInterp + + + SUBROUTINE MD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(MD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(MD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(MD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%PtFairleadDisplacement, u2%PtFairleadDisplacement, tin, u_out%PtFairleadDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%DeltaL) .AND. ALLOCATED(u1%DeltaL)) THEN + DO i1 = LBOUND(u_out%DeltaL,1),UBOUND(u_out%DeltaL,1) + b = -(u1%DeltaL(i1) - u2%DeltaL(i1)) + u_out%DeltaL(i1) = u1%DeltaL(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%DeltaLdot) .AND. ALLOCATED(u1%DeltaLdot)) THEN + DO i1 = LBOUND(u_out%DeltaLdot,1),UBOUND(u_out%DeltaLdot,1) + b = -(u1%DeltaLdot(i1) - u2%DeltaLdot(i1)) + u_out%DeltaLdot(i1) = u1%DeltaLdot(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE MD_Input_ExtrapInterp1 + + + SUBROUTINE MD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(MD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(MD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(MD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(MD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%PtFairleadDisplacement, u2%PtFairleadDisplacement, u3%PtFairleadDisplacement, tin, u_out%PtFairleadDisplacement, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%DeltaL) .AND. ALLOCATED(u1%DeltaL)) THEN + DO i1 = LBOUND(u_out%DeltaL,1),UBOUND(u_out%DeltaL,1) + b = (t(3)**2*(u1%DeltaL(i1) - u2%DeltaL(i1)) + t(2)**2*(-u1%DeltaL(i1) + u3%DeltaL(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%DeltaL(i1) + t(3)*u2%DeltaL(i1) - t(2)*u3%DeltaL(i1) ) * scaleFactor + u_out%DeltaL(i1) = u1%DeltaL(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(u_out%DeltaLdot) .AND. ALLOCATED(u1%DeltaLdot)) THEN + DO i1 = LBOUND(u_out%DeltaLdot,1),UBOUND(u_out%DeltaLdot,1) + b = (t(3)**2*(u1%DeltaLdot(i1) - u2%DeltaLdot(i1)) + t(2)**2*(-u1%DeltaLdot(i1) + u3%DeltaLdot(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%DeltaLdot(i1) + t(3)*u2%DeltaLdot(i1) - t(2)*u3%DeltaLdot(i1) ) * scaleFactor + u_out%DeltaLdot(i1) = u1%DeltaLdot(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE MD_Input_ExtrapInterp2 + + + SUBROUTINE MD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(MD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(MD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL MD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL MD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL MD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE MD_Output_ExtrapInterp + + + SUBROUTINE MD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(MD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(MD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(MD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%PtFairleadLoad, y2%PtFairleadLoad, tin, y_out%PtFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE MD_Output_ExtrapInterp1 + + + SUBROUTINE MD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(MD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(MD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(MD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(MD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'MD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%PtFairleadLoad, y2%PtFairleadLoad, y3%PtFairleadLoad, tin, y_out%PtFairleadLoad, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE MD_Output_ExtrapInterp2 + +END MODULE MoorDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/nwtc-library/CMakeLists.txt b/OpenFAST/modules/nwtc-library/CMakeLists.txt new file mode 100644 index 000000000..4630e604e --- /dev/null +++ b/OpenFAST/modules/nwtc-library/CMakeLists.txt @@ -0,0 +1,136 @@ +# +# Copyright 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. +# + +set(NWTCLIBS_SOURCES + src/ModMesh.f90 + src/ModMesh_Mapping.f90 + src/ModMesh_Types.f90 + src/NWTC_Base.f90 + src/NWTC_IO.f90 + src/NWTC_Library.f90 + src/NWTC_Num.f90 + src/NWTC_RandomNumber.f90 + src/SingPrec.f90 + src/NWTC_Library_Types.f90 + + # RanLux sources + src/ranlux/RANLUX.f90 + + # NetLib sources + src/NetLib/fftpack/fftpack4.1.f + src/NetLib/scalapack/dlasrt2.f + src/NetLib/scalapack/slasrt2.f + src/NetLib/fftpack/NWTC_FFTPACK.f90 + src/NetLib/lapack/NWTC_LAPACK.f90 + src/NetLib/scalapack/NWTC_ScaLAPACK.f90 + + # NetLib SLATEC sources + src/NetLib/slatec/NWTC_SLATEC.f90 + src/NetLib/slatec/dqk61.f + src/NetLib/slatec/qk61.f + src/NetLib/slatec/d1mach.f + src/NetLib/slatec/r1mach.f + src/NetLib/slatec/xercnt.f + src/NetLib/slatec/xerhlt.f + src/NetLib/slatec/xerprn.f + src/NetLib/slatec/xersve.f + src/NetLib/slatec/fdump.f + src/NetLib/slatec/i1mach.f + src/NetLib/slatec/j4save.f + src/NetLib/slatec/xgetua.f + src/NetLib/slatec/xermsg.f ) + +get_filename_component(FCNAME ${CMAKE_Fortran_COMPILER} NAME) + +# Recursive use of routine in qk61/dqk61 will trigger errors in debug +if (CMAKE_BUILD_TYPE MATCHES Debug) + if (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + set_source_files_properties(src/NetLib/slatec/NWTC_SLATEC.f90 PROPERTIES COMPILE_FLAGS -frecursive) + set_source_files_properties(src/NetLib/slatec/dqk61.f PROPERTIES COMPILE_FLAGS -frecursive) + set_source_files_properties(src/NetLib/slatec/qk61.f PROPERTIES COMPILE_FLAGS -frecursive) + elseif (${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + if("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_LESS "19") + if (WIN32) + set_source_files_properties(src/NetLib/slatec/NWTC_SLATEC.f90 PROPERTIES COMPILE_FLAGS "/recursive") + set_source_files_properties(src/NetLib/slatec/dqk61.f PROPERTIES COMPILE_FLAGS "/recursive") + set_source_files_properties(src/NetLib/slatec/qk61.f PROPERTIES COMPILE_FLAGS "/recursive") + else() + set_source_files_properties(src/NetLib/slatec/NWTC_SLATEC.f90 PROPERTIES COMPILE_FLAGS "-recursive") + set_source_files_properties(src/NetLib/slatec/dqk61.f PROPERTIES COMPILE_FLAGS "-recursive") + set_source_files_properties(src/NetLib/slatec/qk61.f PROPERTIES COMPILE_FLAGS "-recursive") + endif() + else() # The above syntax will be deprecated after version 20. This is supported from version 19 onwards + # see: https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/recursive.html + if (WIN32) + set_source_files_properties(src/NetLib/slatec/NWTC_SLATEC.f90 PROPERTIES COMPILE_FLAGS "/assume:recursion") + set_source_files_properties(src/NetLib/slatec/dqk61.f PROPERTIES COMPILE_FLAGS "/assume:recursion") + set_source_files_properties(src/NetLib/slatec/qk61.f PROPERTIES COMPILE_FLAGS "/assume:recursion") + else() + set_source_files_properties(src/NetLib/slatec/NWTC_SLATEC.f90 PROPERTIES COMPILE_FLAGS "-assume recursion") + set_source_files_properties(src/NetLib/slatec/dqk61.f PROPERTIES COMPILE_FLAGS "-assume recursion") + set_source_files_properties(src/NetLib/slatec/qk61.f PROPERTIES COMPILE_FLAGS "-assume recursion") + endif() + endif() + endif() +endif() + + +if(BUILD_OPENFAST_SIMULINK_API) + + if (APPLE OR UNIX) + if (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + set(NWTC_SYS_FILE src/SysMatlabLinuxGnu.f90) + elseif (${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + set(NWTC_SYS_FILE src/SysMatlabLinuxIntel.f90) + endif() + elseif (WIN32) + set(NWTC_SYS_FILE src/SysMatlabWindows.f90) + endif() + +elseif (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + if (WIN32) + set(NWTC_SYS_FILE src/SysGnuWin.f90) + elseif (APPLE OR UNIX OR CYGWIN) + set(NWTC_SYS_FILE src/SysGnuLinux.f90) + endif () +elseif (${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + if (APPLE OR UNIX) + set(NWTC_SYS_FILE src/SysIFL.f90) + elseif (WIN32) + set(NWTC_SYS_FILE src/SysIVF.f90) + endif (APPLE OR UNIX) +endif () + +if (NWTC_SYS_FILE) + message("-- Setting system file as: ${NWTC_SYS_FILE}") + list(APPEND NWTCLIBS_SOURCES ${NWTC_SYS_FILE}) +else (NWTC_SYS_FILE) + message(FATAL_ERROR "Cannot determine system file used with NWTC_Library") +endif (NWTC_SYS_FILE) + +add_library(nwtclibs ${NWTCLIBS_SOURCES}) + +if(BUILD_OPENFAST_SIMULINK_API) + find_package(Matlab REQUIRED) + target_link_libraries(nwtclibs versioninfolib ${LAPACK_LIBRARIES} ${CMAKE_DL_LIBS} ${Matlab_MEX_LIBRARY}) +else() + target_link_libraries(nwtclibs versioninfolib ${LAPACK_LIBRARIES} ${CMAKE_DL_LIBS}) +endif() + +install(TARGETS nwtclibs + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/nwtc-library/README.md b/OpenFAST/modules/nwtc-library/README.md new file mode 100644 index 000000000..9273a9ff8 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/README.md @@ -0,0 +1,22 @@ +# NWTC Library Module +The legacy version of this module and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/NWTC_Library/). + +## Overview +Over the years, the researchers at the NWTC have written many general-purpose +routines that we use in many of our software. In the past, we would copy those +needed for any given program from the source of another code. We decided that +doing it that way was just too much work; especially when we wanted to change +one of the routines and have it affect all the packages. So, we decided to +create a central set of routines and include their source files in our Fortran +projects. Thus, the NWTC Subroutine Library was born. + +The NWTC Subroutine Library consists of several modules, each contained in its +own source file. The library is written in standard Fortran 2003, with the +exception of some of the routines and data in the Sys*.f90 files. We currently +have several compiler-specific files available to choose from, including +- SysIVF.f90 for the Intel Visual Fortran compiler for Windows +- SysGnuLinux.f90 for the GNU Fortran compiler for Linux + +If you want to port our programs to a different compiler, you should only have +to modify one of the Sys*.f90 files to get it to compile. diff --git a/OpenFAST/modules/nwtc-library/src/Generate_NWTC_Library_Types.bat b/OpenFAST/modules/nwtc-library/src/Generate_NWTC_Library_Types.bat new file mode 100644 index 000000000..d6c0ef77f --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/Generate_NWTC_Library_Types.bat @@ -0,0 +1,34 @@ +@ECHO OFF + +SET REG_Loc=..\..\..\build\bin +::SET Registry=%REG_Loc%\Registry_Win32.exe +SET Registry=%REG_Loc%\Registry.exe + +SET ModuleName=%1 + +GOTO %ModuleName% + +REM ---------------------------------------------------------------------------- +REM ---------------- RUN THE REGISTRY TO AUTO-GENERATE FILES ------------------- +REM ---------------------------------------------------------------------------- +ECHO on +:mesh +%REGISTRY% Registry_NWTC_Library_typedef_mesh.txt -noextrap +goto end + +:nomesh +%REGISTRY% Registry_NWTC_Library_typedef_nomesh.txt -noextrap + + +:end +REM ---------------------------------------------------------------------------- +REM ------------------------- CLEAR MEMORY ------------------------------------- +REM ---------------------------------------------------------------------------- +ECHO.  + + +SET REGISTRY= +SET REG_Loc= + +SET ModuleName= +:Done diff --git a/OpenFAST/modules/nwtc-library/src/ModMesh.f90 b/OpenFAST/modules/nwtc-library/src/ModMesh.f90 new file mode 100644 index 000000000..a38dfdd72 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/ModMesh.f90 @@ -0,0 +1,3552 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +!********************************************************************************************************************************** +!> The modules ModMesh and ModMesh_Types provide data structures and subroutines for representing and manipulating meshes +!! and meshed data in the FAST modular framework. +!! +!! A mesh is comprised of a set of "nodes" (simple points in space) together with information specifying how they are connected +!! to form "elements" representing spatial boundaries between components. ModMesh and ModMesh_Types define point, line, surface, +!! and volume elements in a standard isoparametric mapping from finite element analysis. Currently only points and straight line +!! (line2) elements are implemented. +!! +!! Associated with a mesh are one or more "fields" that represent the values of variables or "degrees of freedom" at each node. +!! A mesh always has a named "Position" that specifies the location in three-dimensional space as an Xi,Yi,Zi triplet of each node +!! and a field named "RefOrientation" that specifies the orientation (as a direction cosine matrix) of the node. +!! The ModMesh_Types module predefines a number of other fields of triples representing velocities, forces, and moments as well as +!! a field of nine values representing a direction cosine matrix. +!! +!! The operations on meshes defined in the ModMesh module are creation, spatio-location of nodes, construction, committing the +!! mesh definition, initialization of fields, accessing field data, updating field data, copying, deallocating, and destroying meshes. +!! See https://nwtc.nrel.gov/FAST-Developers and https://nwtc.nrel.gov/system/files/ProgrammingHandbook_Mod20130717.pdf +MODULE ModMesh + + USE ModMesh_Types + IMPLICIT NONE +! INTEGER :: DEBUG_UNIT = 74 + + INTEGER, PARAMETER, PRIVATE :: BUMPUP = 64 !< size element list will be increased when adding an element that does not fit in the currently allocated space; do not set to less than 2 + CHARACTER(*),PARAMETER :: VTK_AryFmt = '(3(F30.5))' !< text format for triplets written to VTK text files + + + INTERFACE MeshConstructElement + MODULE PROCEDURE MeshConstructElement_1PT , & + MeshConstructElement_2PT , MeshConstructElement_3PT , & + MeshConstructElement_4PT , & + MeshConstructElement_6PT , & + MeshConstructElement_8PT , & + MeshConstructElement_10PT, & + MeshConstructElement_15PT, & + MeshConstructElement_20PT + END INTERFACE + +CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes mesh information in binary form. If UnIn is < 0, it gets a new unit number and opens the file, +!! otherwise the file is appended. It is up to the caller of this routine to close the file when it's finished. +SUBROUTINE MeshWrBin ( UnIn, M, ErrStat, ErrMsg, FileName) + + + INTEGER, INTENT(INOUT) :: UnIn !< fortran output unit + TYPE(MeshType), INTENT(IN) :: M !< mesh to be reported on + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Indicates whether an error occurred (see NWTC_Library) + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with the ErrStat + CHARACTER(*), INTENT(IN), OPTIONAL :: FileName !< Name of the file to write the output in + + ! local variables + INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors + INTEGER(IntKi) :: I ! loop counter + CHARACTER(*), PARAMETER :: RoutineName = 'MeshWrBin' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (UnIn < 0) THEN + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + + CALL OpenBOutFile ( UnIn, TRIM(FileName), ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + ! Write information about mesh structure: + WRITE (UnIn, IOSTAT=ErrStat2) INT(ReKi,B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) INT(FIELDMASK_SIZE,B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) M%fieldmask ! BJJ: do we need to verify that this is size B4Ki? + WRITE (UnIn, IOSTAT=ErrStat2) INT(M%Nnodes,B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) INT(M%nelemlist,B4Ki) + if (M%Fieldmask(MASKID_SCALAR)) WRITE (UnIn, IOSTAT=ErrStat2) INT(M%nScalars,B4Ki) + + + !........... + ! Write nodal information: + !........... + + IF (.NOT. M%Initialized) RETURN + + WRITE (UnIn, IOSTAT=ErrStat2) M%Position + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing Position to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) M%RefOrientation + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing RefOrientation to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + ! Write fields: + + IF ( M%fieldmask(MASKID_FORCE) .AND. ALLOCATED(M%Force) ) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%Force + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing Force to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_Moment) .AND. ALLOCATED(M%Moment)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%Moment + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing Force to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_ORIENTATION) .AND. ALLOCATED(M%Orientation)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%Orientation + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing Orientation to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_TRANSLATIONDISP) .AND. ALLOCATED(M%TranslationDisp)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%TranslationDisp + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TranslationDisp to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_TRANSLATIONVEL) .AND. ALLOCATED(M%TranslationVel)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%TranslationVel + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TranslationVel to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_ROTATIONVEL) .AND. ALLOCATED(M%RotationVel)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%RotationVel + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing RotationVel to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_TRANSLATIONACC) .AND. ALLOCATED(M%TranslationAcc)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%TranslationAcc + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TranslationAcc to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_ROTATIONACC) .AND. ALLOCATED(M%RotationAcc)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%RotationAcc + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing RotationAcc to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + IF ( M%fieldmask(MASKID_SCALAR) .AND. ALLOCATED(M%Scalars)) THEN + WRITE (UnIn, IOSTAT=ErrStat2) M%Scalars + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing Scalars to the mesh binary file.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + END IF + + + !........... + ! Write element information: + !........... + + DO i=1,M%nelemlist + WRITE (UnIn, IOSTAT=ErrStat2) INT(M%ElemList(i)%Element%Xelement ,B4Ki) ! what kind of element + WRITE (UnIn, IOSTAT=ErrStat2) INT(SIZE(M%ElemList(i)%Element%ElemNodes),B4Ki) ! how many nodes + WRITE (UnIn, IOSTAT=ErrStat2) INT(M%ElemList(i)%Element%ElemNodes ,B4Ki) ! which nodes + END DO + +END SUBROUTINE MeshWrBin +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes the reference position and orientations of a mesh in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE MeshWrVTKreference (RefPoint, M, FileRootName, ErrStat, ErrMsg ) + + REAL(SiKi), INTENT(IN) :: RefPoint(3) !< reference location, normally (0,0,0) + TYPE(MeshType), INTENT(IN) :: M !< mesh to be written + CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in (excluding extension) + + 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) :: Un ! fortran unit number + INTEGER(IntKi) :: I, J ! loop counters + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'MeshWrVTKreference' + + CHARACTER(*),PARAMETER :: RefOrientation(3) = (/ 'RefOrientationX','RefOrientationY','RefOrientationZ' /) + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) + call WrVTK_header( TRIM(FileRootName)//'_Reference.vtp', M%Nnodes, M%ElemTable(ELEMENT_LINE2)%nelem, 0, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + +! points (i.e., nodes): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + END DO + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + +! point data (orientation vectors): + WRITE(Un,'(A)') ' <PointData>' + DO j=1,3 + WRITE(Un,'(A,A,A)') ' <DataArray type="Float32" Name="', RefOrientation(j), '" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%RefOrientation(j,:,i) + END DO + WRITE(Un,'(A)') ' </DataArray>' + END DO + WRITE(Un,'(A)') ' </PointData>' + +! lines (i.e., elements; for line2 meshes only): + if ( M%ElemTable(ELEMENT_LINE2)%nelem > 0) then + WRITE(Un,'(A)') ' <Lines>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + WRITE(Un,'(2(i7))') M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) - 1, M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) - 1 + END DO + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + WRITE(Un,'(i7)') 2*i + END DO + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Lines>' + end if + + call WrVTK_footer( Un ) + +END SUBROUTINE MeshWrVTKreference +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes mesh information in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE MeshWrVTK ( RefPoint, M, FileRootName, VTKcount, OutputFieldData, ErrStat, ErrMsg, Twidth, Sib ) + + REAL(SiKi), INTENT(IN) :: RefPoint(3) !< reference location, normally (0,0,0) + TYPE(MeshType), INTENT(IN) :: M !< mesh to be written + CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in (excluding extension) + INTEGER(IntKi), INTENT(IN) :: VTKcount !< Indicates number for VTK output file (when 0, the routine will also write reference information) + LOGICAL, INTENT(IN) :: OutputFieldData !< flag to determine if we want to output field data or just the absolute position of this mesh + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Indicates whether an error occurred (see NWTC_Library) + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with the ErrStat + INTEGER(IntKi), INTENT(IN) :: Twidth !< Number of digits in the maximum write-out step (used to pad the VTK write-out in the filename with zeros) + + TYPE(MeshType), INTENT(IN), OPTIONAL :: Sib !< "functional" Sibling of M that contains translational displacement information (used to place forces at displaced positions) + + ! local variables + INTEGER(IntKi) :: Un ! fortran unit number + INTEGER(IntKi) :: i,j ! loop counters + CHARACTER(1024) :: FileName + CHARACTER(Twidth) :: Tstr ! string for current VTK write-out step (padded with zeros) + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'MeshWrVTK' + CHARACTER(*),PARAMETER :: Orientation(3) = (/ 'OrientationX','OrientationY','OrientationZ' /) + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. M%Initialized) RETURN + + !................................................................. + !> We'll write the mesh reference fields on the first timestep only: + !................................................................. + if (VTKcount == 0) then + call MeshWrVTKreference(RefPoint, M, FileRootName, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + !................................................................. + ! write the data that potentially changes each time step: + !................................................................. + + ! construct the string for the zero-padded VTK write-out step + write(Tstr, '(i' // trim(Num2LStr(Twidth)) //'.'// trim(Num2LStr(Twidth)) // ')') VTKcount + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) file + FileName = TRIM(FileRootName)//'.'//Tstr//'.vtp' + + call WrVTK_header( trim(FileName), M%Nnodes, M%ElemTable(ELEMENT_LINE2)%nelem, 0, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + + ! Write a VTP mesh file (Polygonal VTK file) with positions, lines, and field information + ! (note alignment of WRITE statements to make sure spaces are lined up in XML file) + +! points (nodes): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + IF (ALLOCATED(M%TranslationDisp)) THEN + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + END DO + ELSEIF ( PRESENT(Sib) ) THEN + if (allocated(Sib%TranslationDisp)) then + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + Sib%TranslationDisp(:,i) ! @note: M%Position and Sib%Position should be the same! + END DO + else + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + END DO + end if + ELSE + DO i=1,M%Nnodes + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + END DO + END IF + + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + + if (OutputFieldData) then ! point data for any existing mesh fields: + WRITE(Un,'(A)') ' <PointData>' + call MeshWrVTKfields ( Un, M, 1) + + if ( PRESENT(Sib) ) then ! write the sibling fields, too, so we don't have so many output files + if (Sib%Nnodes == M%Nnodes .and. Sib%nelemlist == M%nelemlist ) then + call MeshWrVTKfields ( Un, Sib, 1) + end if + end if + WRITE(Un,'(A)') ' </PointData>' + end if !(OutputFieldData) + + +! lines (i.e., elements; for line2 meshes only): + if ( M%ElemTable(ELEMENT_LINE2)%nelem > 0) then + WRITE(Un,'(A)') ' <Lines>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + WRITE(Un,'(2(i7))') M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) - 1, M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) - 1 + END DO + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + WRITE(Un,'(i7)') 2*i + END DO + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Lines>' + end if + + call WrVTK_footer( Un ) + +END SUBROUTINE MeshWrVTK +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes mesh field information in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE MeshWrVTKfields ( Un, M, n ) + + INTEGER(IntKi), INTENT(IN) :: Un !< unit number of already-open vtk file in which to write the field information + TYPE(MeshType), INTENT(IN) :: M !< mesh to be written + INTEGER(IntKi), INTENT(IN) :: n !< number of times to write field value for each mesh node (> 1 when added to surface) + + + ! local variables + INTEGER(IntKi) :: i,j,k ! loop counters + CHARACTER(1024) :: FileName + + !INTEGER(IntKi) :: ErrStat2 + !CHARACTER(ErrMsgLen) :: ErrMsg2 + !CHARACTER(*),PARAMETER :: RoutineName = 'MeshWrVTKfields' + CHARACTER(*),PARAMETER :: Orientation(3) = (/ 'OrientationX','OrientationY','OrientationZ' /) + + + +! point data for any existing mesh fields: + !WRITE(Un,'(A)') ' <PointData>' + + IF ( M%fieldmask(MASKID_FORCE) .AND. ALLOCATED(M%Force) ) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="Force" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%Force(:,i) + end do !k + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + + IF ( M%fieldmask(MASKID_MOMENT) .AND. ALLOCATED(M%Moment) ) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="Moment" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%Moment(:,i) + end do !k + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + +#ifdef VTK_OUTPUT_TRANSLATIONDISP + IF ( M%fieldmask(MASKID_TRANSLATIONDISP) .AND. ALLOCATED(M%TranslationDisp)) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="TranslationalDisplacement" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%TranslationDisp(:,i) + end do + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF +#endif + + IF ( M%fieldmask(MASKID_TRANSLATIONVEL) .AND. ALLOCATED(M%TranslationVel)) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="TranslationalVelocity" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%TranslationVel(:,i) + end do + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + + IF ( M%fieldmask(MASKID_ROTATIONVEL) .AND. ALLOCATED(M%RotationVel)) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="RotationalVelocity" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%RotationVel(:,i) + end do !k + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + + IF ( M%fieldmask(MASKID_TRANSLATIONACC) .AND. ALLOCATED(M%TranslationAcc)) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="TranslationalAcceleration" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%TranslationAcc(:,i) + end do !k + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + + IF ( M%fieldmask(MASKID_ROTATIONACC) .AND. ALLOCATED(M%RotationAcc)) THEN + WRITE(Un,'(A)') ' <DataArray type="Float32" Name="RotationalAcceleration" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%RotationAcc(:,i) + end do + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + +IF (M%fieldmask(MASKID_ORIENTATION) .AND. ALLOCATED(M%Orientation)) THEN + DO j=1,3 + WRITE(Un,'(A,A,A)') ' <DataArray type="Float32" Name="', Orientation(j), '" NumberOfComponents="3" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,VTK_AryFmt) M%Orientation(j,:,i) + end do + END DO + WRITE(Un,'(A)') ' </DataArray>' + END DO +END IF + + IF ( M%fieldmask(MASKID_SCALAR) .AND. ALLOCATED(M%Scalars) .AND. M%nScalars > 0) THEN + WRITE(Un,'(A,I7,A)') ' <DataArray type="Float32" Name="Scalars" NumberOfComponents="', M%nScalars, '" format="ascii">' + DO i=1,M%Nnodes + do k=1,n + WRITE(Un,'('//trim(num2lstr(M%nScalars))//'(F20.6))') M%Scalars(:,i) ! not very efficient, but it's easy and I'm not sure anyone uses this field + end do + END DO + WRITE(Un,'(A)') ' </DataArray>' + END IF + + !WRITE(Un,'(A)') ' </PointData>' + + + +END SUBROUTINE MeshWrVTKfields +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes line2 mesh surface information in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE MeshWrVTK_Ln2Surface ( RefPoint, M, FileRootName, VTKcount, OutputFieldData, ErrStat, ErrMsg, Twidth, NumSegments, Radius, verts, Sib ) + + REAL(SiKi), INTENT(IN) :: RefPoint(3) !< reference location, normally (0,0,0) + TYPE(MeshType), INTENT(IN) :: M !< mesh to be written + CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in (excluding extension) + INTEGER(IntKi), INTENT(IN) :: VTKcount !< Indicates number for VTK output file (when 0, the routine will also write reference information) + LOGICAL, INTENT(IN) :: OutputFieldData !< flag to determine if we want to output field data or just the absolute position of this mesh + INTEGER(IntKi), INTENT(IN) :: Twidth !< Number of digits in the maximum write-out step (used to pad the VTK write-out in the filename with zeros) + INTEGER(IntKi), INTENT(IN), OPTIONAL :: NumSegments !< Number of segments to split the circle into + REAL(SiKi), INTENT(IN), OPTIONAL :: Radius(:) !< Radius of each node + REAL(SiKi), INTENT(IN), OPTIONAL :: verts(:,:,:) !< X-Y verticies (2x{NumSegs}xNNodes) of points that define a shape around each node + TYPE(MeshType), INTENT(IN), OPTIONAL :: Sib !< Sibling of M that contains more field information (used only if OutputFieldData is true, to minimize number of files being written) + + 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) :: Un ! fortran unit number + INTEGER(IntKi) :: i,j ! loop counters + INTEGER(IntKi) :: offset_cnt ! counter for offsets (corresponding to number of nodes in polygons written) + CHARACTER(1024) :: FileName + REAL(SiKi) :: angle + REAL(SiKi) :: xyz(3) + CHARACTER(Twidth) :: Tstr ! string for current write-out step (padded with zeros) + + INTEGER(IntKi) :: firstPntEnd, firstPntStart, secondPntStart, secondPntEnd ! node indices for forming rectangle + INTEGER(IntKi) :: NumSegments1 + + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'MeshWrVTK_Ln2Surface' + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. M%Initialized) RETURN + IF (.NOT. ALLOCATED(M%TranslationDisp) ) RETURN + IF (.NOT. ALLOCATED(M%Orientation) ) RETURN + + if (present(verts)) then + NumSegments1 = size(verts,2) + elseif (present(Radius) .and. present(NumSegments)) then + NumSegments1 = NumSegments + else + call SetErrStat(ErrID_Fatal,'Incorrect number of arguments.',ErrStat,ErrMsg,RoutineName) + RETURN + end if + + !................................................................. + ! write the data that potentially changes each time step: + !................................................................. + + ! construct the string for the zero-padded VTK write-out step + write(Tstr, '(i' // trim(Num2LStr(Twidth)) //'.'// trim(Num2LStr(Twidth)) // ')') VTKcount + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) file + FileName = TRIM(FileRootName)//'.'//Tstr//'.vtp' + + ! Write a VTP mesh file (Polygonal VTK file) with positions and polygons (surfaces) + ! (note alignment of WRITE statements to make sure spaces are lined up in XML file) + call WrVTK_header( FileName=trim(FileName) & + , NumberOfPoints=M%Nnodes*NumSegments1 & + , NumberOfLines=M%ElemTable(ELEMENT_LINE2)%nelem & + , NumberOfPolys=M%ElemTable(ELEMENT_LINE2)%nelem*(NumSegments1+2)& + , Un=Un & + , ErrStat=ErrStat2 & + , ErrMsg=ErrMsg2 ) + + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + + +! points (nodes, augmented with NumSegments): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + + xyz(3) = 0.0_SiKi + if (present(verts)) then + + DO i=1,M%Nnodes + DO j=1,NumSegments1 + xyz(1:2) = verts(1:2,j,i) + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + matmul(xyz,M%Orientation(:,:,i)) + END DO + END DO + else + DO i=1,M%Nnodes + DO j=1,NumSegments1 + angle = TwoPi*(j-1.0_ReKi)/NumSegments1 + xyz(1) = radius(i)*COS(angle) + xyz(2) = radius(i)*SIN(angle) + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + matmul(xyz,M%Orientation(:,:,i)) + END DO + END DO + end if + + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + + + if (OutputFieldData) then ! point data for any existing mesh fields: + WRITE(Un,'(A)') ' <PointData>' + call MeshWrVTKfields ( Un, M, NumSegments1) + + if ( PRESENT(Sib) ) then ! write the sibling fields, too, so we don't have so many output files + if (Sib%Nnodes == M%Nnodes .and. Sib%nelemlist == M%nelemlist ) then + call MeshWrVTKfields ( Un, Sib, NumSegments1) + end if + end if + WRITE(Un,'(A)') ' </PointData>' + end if !(OutputFieldData) + + if ( M%ElemTable(ELEMENT_LINE2)%nelem > 0) then + ! Using rectangle to render surfaces (for line2 meshes only): + WRITE(Un,'(A)') ' <Polys>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + firstPntStart = (M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1)-1)*NumSegments1 + firstPntEnd = firstPntStart + NumSegments1 - 1 + secondPntStart = (M%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2)-1)*NumSegments1 + secondPntEnd = secondPntStart + NumSegments1 - 1 + DO j=1,NumSegments1-1 + WRITE(Un,'(4(i7))') firstPntStart + (j-1), firstPntStart + j, & + secondPntStart + j, secondPntStart + (j-1) + END DO + WRITE(Un,'(4(i7))') firstPntEnd, firstPntStart, secondPntStart, secondPntEnd + + ! make top and bottom of this element, making sure surface normals point outward + WRITE(Un,'('//trim(num2lstr(NumSegments1))//'(i7))') (j, j=firstPntEnd,firstPntStart,-1) + WRITE(Un,'('//trim(num2lstr(NumSegments1))//'(i7))') (j, j=secondPntStart,secondPntEnd) + + END DO + WRITE(Un,'(A)') ' </DataArray>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + offset_cnt = 0 + DO i=1,M%ElemTable(ELEMENT_LINE2)%nelem + DO j=1,NumSegments1 + offset_cnt = offset_cnt + 4 ! number of nodes in polygon + WRITE(Un,'(i7)') offset_cnt + END DO + DO j=1,2 ! top and bottom + offset_cnt = offset_cnt + NumSegments1 ! number of nodes in this polygon + WRITE(Un,'(i7)') offset_cnt + END DO + END DO + WRITE(Un,'(A)') ' </DataArray>' + + WRITE(Un,'(A)') ' </Polys>' + + end if ! do this only for line2 elements + + call WrVTK_footer( Un ) + + END SUBROUTINE MeshWrVTK_Ln2Surface +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes point mesh surfaces information in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE MeshWrVTK_PointSurface ( RefPoint, M, FileRootName, VTKcount, OutputFieldData, ErrStat, ErrMsg, Twidth, NumSegments, Radius, verts, Sib ) + + REAL(SiKi), INTENT(IN) :: RefPoint(3) !< reference location, normally (0,0,0) + TYPE(MeshType), INTENT(IN) :: M !< mesh to be written + CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in (excluding extension) + INTEGER(IntKi), INTENT(IN) :: VTKcount !< Indicates number for VTK output file (when 0, the routine will also write reference information) + LOGICAL, INTENT(IN) :: OutputFieldData !< flag to determine if we want to output field data or just the absolute position of this mesh + INTEGER(IntKi), INTENT(IN) :: Twidth !< Number of digits in the maximum write-out timestep (used to pad the VTK write-out in the filename with zeros) + INTEGER(IntKi), INTENT(IN), OPTIONAL :: NumSegments !< Number of segments to split the circle into + REAL(SiKi), INTENT(IN), OPTIONAL :: Radius !< Radius of each node + REAL(SiKi), INTENT(IN), OPTIONAL :: verts(:,:) !< X-Y-Z verticies (3xn) of points that define a volume around each node + !bjj: we don't need this to be limited to 8, I guess... + TYPE(MeshType), INTENT(IN), OPTIONAL :: Sib !< Sibling of M that contains more field information (used only if OutputFieldData is true, to minimize number of files being written) + + 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) :: Un ! fortran unit number + INTEGER(IntKi) :: i,j,k ! loop counters + INTEGER(IntKi) :: offset_cnt ! counter for offsets (corresponding to number of nodes in polygons written) + INTEGER(IntKi) :: NumberOfPoints, NumberOfPointsPerNode + INTEGER(IntKi) :: NumberOfPolys + INTEGER(IntKi) :: NumSegments1 + INTEGER(IntKi) :: NumSegments2 + CHARACTER(1024) :: FileName + REAL(SiKi) :: angle, r, ratio + REAL(SiKi) :: xyz(3) + CHARACTER(Twidth) :: Tstr ! string for current VTK write-out step (padded with zeros) + + INTEGER(IntKi) :: firstPntEnd, firstPntStart, secondPntStart, secondPntEnd ! node indices for forming rectangle + + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'MeshWrVTK_PointSurface' + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. M%Initialized) RETURN + IF (.NOT. ALLOCATED(M%TranslationDisp) ) RETURN + IF (.NOT. ALLOCATED(M%Orientation) ) RETURN + + if (present(verts)) then + NumberOfPointsPerNode = size(verts,2) + if (size(verts,2)==8) then + NumberOfPolys = 6 ! per node + elseif (size(verts,2)==4) then + NumberOfPolys = 1 ! per node + else + ! it would be nice if we could add this sometime, but ... + call SetErrStat(ErrID_Fatal,'When verticies are specified, there must be exactly 4 or 8.',ErrStat,ErrMsg,RoutineName) + RETURN + end if + + NumberOfPolys = M%Nnodes * NumberOfPolys + + elseif (present(Radius) ) then + if (present(NumSegments)) then ! a volume + NumSegments1 = max(1,abs(NumSegments)) + NumSegments2 = max(4,NumSegments1) + + NumberOfPolys = M%Nnodes * max(1,(NumSegments2-1))* NumSegments1 + NumberOfPointsPerNode = NumSegments2 * NumSegments1 + + else ! a plane + NumSegments1 = 20 + NumSegments2 = 1 + + NumberOfPolys = M%Nnodes + NumberOfPointsPerNode = NumSegments1 + + end if + + + else + call SetErrStat(ErrID_Fatal,'Incorrect number of arguments.',ErrStat,ErrMsg,RoutineName) + RETURN + end if + + NumberOfPoints = M%Nnodes*NumberOfPointsPerNode + !................................................................. + ! write the data that potentially changes each time step: + !................................................................. + + ! construct the string for the zero-padded VTK write-out step + write(Tstr, '(i' // trim(Num2LStr(Twidth)) //'.'// trim(Num2LStr(Twidth)) // ')') VTKcount + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) file + FileName = TRIM(FileRootName)//'.'//Tstr//'.vtp' + + ! Write a VTP mesh file (Polygonal VTK file) with positions and polygons (surfaces) + ! (note alignment of WRITE statements to make sure spaces are lined up in XML file) + call WrVTK_header( trim(FileName), M%Nnodes*NumberOfPoints, 0, NumberOfPolys, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + +! points (nodes, augmented with NumSegments): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + + if ( present(verts) ) then + do i=1,M%Nnodes + do j=1,NumberOfPointsPerNode + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + MATMUL(verts(:,j),M%Orientation(:,:,i)) + end do + end do + + else + DO i=1,M%Nnodes + DO j=1,NumSegments2 + if (NumSegments2>1) then + ratio = 2.0_SiKi*REAL(j-1,SiKi)/REAL(NumSegments2-1,SiKi) - 1.0_SiKi ! where we are in [-1, 1] + else + ratio = 0.0_SiKi + !WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) ! write center of node + end if + + xyz(3) = radius*ratio + + ! now calculate the radius of the x-y circle we're going to create at this z: + !r = acos( radius / xyz(3) ) or r = sqrt( radius**2 - xyz(3)**2 ) = radius*sqrt(1 - ratio**2) + r = radius*sqrt(abs(1.0_SiKi - ratio**2)) ! note the abs in case ratio**2 gets slightly larger than 1 + + DO k=1,NumSegments1 + angle = TwoPi*(k-1.0_ReKi)/NumSegments1 + xyz(1) = r*COS(angle) + xyz(2) = r*SIN(angle) + WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + MATMUL(xyz,M%Orientation(:,:,i)) + !WRITE(Un,VTK_AryFmt) RefPoint + M%Position(:,i) + M%TranslationDisp(:,i) + xyz + END DO + END DO + END DO + end if + + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + + + if (OutputFieldData) then ! point data for any existing mesh fields: + WRITE(Un,'(A)') ' <PointData>' + call MeshWrVTKfields ( Un, M, NumberOfPointsPerNode) + + if ( PRESENT(Sib) ) then ! write the sibling fields, too, so we don't have so many output files + if (Sib%Nnodes == M%Nnodes .and. Sib%nelemlist == M%nelemlist ) then + call MeshWrVTKfields ( Un, Sib, NumberOfPointsPerNode) + end if + end if + WRITE(Un,'(A)') ' </PointData>' + end if !(OutputFieldData) + + WRITE(Un,'(A)') ' <Polys>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + + offset_cnt = 4 + if ( present(verts) ) then + if (size(verts,2)==8) then + + ! Write points for the 6 corners of the box + + do i=1,M%Nnodes + firstPntStart = (i-1)*size(verts,2) + + WRITE(Un,'(4(i7))') firstPntStart ,firstPntStart+1,firstPntStart+2,firstPntStart+3 ! bottom + WRITE(Un,'(4(i7))') firstPntStart+4,firstPntStart+5,firstPntStart+6,firstPntStart+7 ! top + + WRITE(Un,'(4(i7))') firstPntStart+7,firstPntStart+6,firstPntStart+1,firstPntStart ! sides + WRITE(Un,'(4(i7))') firstPntStart+6,firstPntStart+5,firstPntStart+2,firstPntStart+1 + WRITE(Un,'(4(i7))') firstPntStart+5,firstPntStart+4,firstPntStart+3,firstPntStart+2 + WRITE(Un,'(4(i7))') firstPntStart+4,firstPntStart+7,firstPntStart ,firstPntStart+3 + end do + + elseif (size(verts,2)==4) then + + ! Write points for the 4 corners of the polygon + + do i=1,M%Nnodes + firstPntStart = (i-1)*size(verts,2) + + WRITE(Un,'(4(i7))') firstPntStart ,firstPntStart+1,firstPntStart+2,firstPntStart+3 ! bottom + end do + + end if + else + + if (NumSegments2==1) then + offset_cnt = NumSegments1 ! number of nodes in this polygon + + DO i=1,M%Nnodes + WRITE(Un,'('//trim(num2lstr(NumSegments1))//'(i7))') (k, k=0,NumSegments1-1) + END DO + else + + DO i=1,M%Nnodes + DO j=1,NumSegments2-1 + firstPntStart = (j-1)*NumSegments1 + (i-1)*NumSegments1*NumSegments2 + firstPntEnd = firstPntStart + NumSegments1 - 1 + secondPntStart = j*NumSegments1 + (i-1)*NumSegments1*NumSegments2 + secondPntEnd = secondPntStart + NumSegments1 - 1 + DO k=1,NumSegments1-1 + WRITE(Un,'(4(i7))') firstPntStart + (k-1), firstPntStart + k, & + secondPntStart + k, secondPntStart + (k-1) + END DO + WRITE(Un,'(4(i7))') firstPntEnd, firstPntStart, secondPntStart, secondPntEnd + END DO + END DO + + end if + end if + + WRITE(Un,'(A)') ' </DataArray>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + + do i=1,NumberOfPolys + WRITE(Un,'(i7)') offset_cnt*i + end do + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Polys>' + + + call WrVTK_footer( Un ) + + END SUBROUTINE MeshWrVTK_PointSurface + +!------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes mesh information in text form. It is used for debugging. + SUBROUTINE MeshPrintInfo ( U, M, N) + + INTEGER, INTENT(IN ) :: U !< fortran output unit + TYPE(MeshType),INTENT(IN ) :: M !< mesh to be reported on + INTEGER, OPTIONAL,INTENT(IN ) :: N !< Number to print, default is all nodes + ! Local + INTEGER isz,i,j,nn,Ielement,Xelement + + nn = M%Nnodes !5 + IF (PRESENT(N)) nn = min(nn,N) + + write(U,*)'----------- MeshPrintInfo: -------------' + + write(U,*) 'Initialized: ', M%initialized + write(U,*) 'Committed: ', M%Committed + IF ( ASSOCIATED(M%RemapFlag) ) write(U,*) 'Remap Flag: ', M%RemapFlag + + write(U,*) 'Fieldmask: ', M%FieldMask + IF ( M%FieldMask( MASKID_FORCE ) ) write(U,*) ' Defined : Force' + IF ( M%FieldMask( MASKID_MOMENT ) ) write(U,*) ' Defined : Moment' + IF ( M%FieldMask( MASKID_ORIENTATION ) ) write(U,*) ' Defined : Orientation' + IF ( M%FieldMask( MASKID_TRANSLATIONDISP ) ) write(U,*) ' Defined : TranslationDisp' + IF ( M%FieldMask( MASKID_TRANSLATIONVEL ) ) write(U,*) ' Defined : TranslationVel' + IF ( M%FieldMask( MASKID_ROTATIONVEL ) ) write(U,*) ' Defined : RotationVel' + IF ( M%FieldMask( MASKID_TRANSLATIONACC ) ) write(U,*) ' Defined : TranslationAcc' + IF ( M%FieldMask( MASKID_ROTATIONACC ) ) write(U,*) ' Defined : RotationAcc' + IF ( M%FieldMask( MASKID_SCALAR ) ) write(U,*) ' Defined : Scalar' + write(U,*) 'Ios: ', M%Ios + write(U,*) 'Nnodes: ', M%Nnodes + + + IF (ASSOCIATED(M%ElemTable)) THEN + DO i = 1, NELEMKINDS + IF ( M%ElemTable(i)%nelem .GT. 0 ) THEN + WRITE(U,*)ElemNames(i),' nelem: ',M%ElemTable(i)%nelem,' max: ',M%ElemTable(i)%maxelem + IF(M%initialized.AND.ASSOCIATED(M%ElemTable(i)%Elements))THEN + DO j = 1,min(nn,M%ElemTable(i)%nelem) + write(U,*)' ',j,M%ElemTable(i)%Elements(j)%ElemNodes(:) + ENDDO + ENDIF + ENDIF + END DO + END IF + +! Here are some built in derived data types that can represent values at the nodes +! the last dimension of each of these has range 1:nnodes for the mesh being represented +! and they are indexed by the element arrays above +! only some of these would be allocated, depending on what's being represented +! on the mesh. +! Whether or not these are allocated is indicted in the fieldmask, which can +! be interrogated by a routine using an instance of the type. If you add a field +! here, be sure to change the table of parameters used to size and index fieldmask above. + IF(ASSOCIATED(M%Position))THEN + isz=size(M%Position,2) + write(U,*)'Position: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%Position(:,i) + ENDDO + ENDIF + IF(ASSOCIATED(M%RefOrientation))THEN + isz=size(M%RefOrientation,3) + write(U,*)'RefOrientation: ',isz + DO i=1,min(nn,isz) !bjj: printing this like a matrix: + write(U,'(1X,I3, 3(1X,F10.4))') i, M%RefOrientation(1,:,i) + write(U,'(4X, 3(1X,F10.4))') M%RefOrientation(2,:,i) + write(U,'(4X, 3(1X,F10.4))') M%RefOrientation(3,:,i) + ENDDO + ENDIF + + + IF(ALLOCATED(M%Force))THEN + isz=size(M%Force,2) + write(U,*)'Force: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%Force(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%Moment))THEN + isz=size(M%Moment,2) + write(U,*)'Moment: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%Moment(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%Orientation))THEN + isz=size(M%Orientation,3) + write(U,*)'Orientation: ',isz,' node(s)' + DO i=1,min(nn,isz) !bjj: printing this like a matrix: + write(U,'(1X,I3, 3(1X,F10.4))') i, M%Orientation(1,:,i) + write(U,'(4X, 3(1X,F10.4))') M%Orientation(2,:,i) + write(U,'(4X, 3(1X,F10.4))') M%Orientation(3,:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%TranslationDisp))THEN + isz=size(M%TranslationDisp,2) + write(U,*)'TranslationDisp: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%TranslationDisp(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%RotationVel))THEN + isz=size(M%RotationVel,2) + write(U,*)'RotationVel: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%RotationVel(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%TranslationVel))THEN + isz=size(M%TranslationVel,2) + write(U,*)'TranslationVel: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%TranslationVel(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%RotationAcc))THEN + isz=size(M%RotationAcc,2) + write(U,*)'RotationAcc: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%RotationAcc(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%TranslationAcc))THEN + isz=size(M%TranslationAcc,2) + write(U,*)'TranslationAcc: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%TranslationAcc(:,i) + ENDDO + ENDIF + IF(ALLOCATED(M%Scalars))THEN + isz=size(M%Scalars,1) + write(U,*)'Scalars: ',isz,' node(s)' + DO i=1,min(nn,isz) + write(U,*)' ',i,M%Scalars(:,i) + ENDDO + ENDIF + write(U,*)'--------- Traverse Element List ----------' + + DO Ielement=1,M%nelemlist + Xelement = M%ElemList(Ielement)%Element%Xelement + + WRITE(U,'(" Ielement: ",I10,1x,A," det_jac: ",ES15.7," Nodes:",'//& + Num2LStr( size(M%ElemList(Ielement)%Element%ElemNodes) )//'(1x,I10))') & + Ielement,& + ElemNames(Xelement), & + M%ElemList(Ielement)%Element%det_jac, & + M%ElemList(Ielement)%Element%ElemNodes + END DO + + write(U,*)'--------- End of Element List ----------' + + END SUBROUTINE MeshPrintInfo + +!---------------------------------------------------------------------------------------------------------------------------------- + ! operations to create a mesh + +!> Takes a blank, uninitialized instance of Type(MeshType) and defines the number of nodes in the mesh. Optional +!! arguments indicate the fields that will be allocated and associated with the nodes of the mesh. The fields that may +!! be associated with the mesh nodes are Force, Moment, Orientation, Rotation, TranslationDisp, RotationVel, TranslationVel, +!! RotationAcc, TranslationAcc, and an arbitrary number of Scalars. See the definition of ModMeshType for descriptions of these fields. +! After the first 5 arguments, the others are optional that say whether to allocate fields in the mesh. +! These are always dimensioned npoints + SUBROUTINE MeshCreate ( BlankMesh & + ,IOS & + ,Nnodes & + ,ErrStat & + ,ErrMess & + ,Force & + ,Moment & + ,Orientation & + ,TranslationDisp & + ,TranslationVel & + ,RotationVel & + ,TranslationAcc & + ,RotationAcc & + ,nScalars & + ,IsNewSibling & + ) + + TYPE(MeshType), INTENT(INOUT) :: BlankMesh !< Mesh to be created + INTEGER,INTENT(IN) :: IOS !< input (COMPONENT_INPUT), output(COMPONENT_OUTPUT), or state(COMPONENT_STATE) + INTEGER,INTENT(IN) :: Nnodes !< Number of nodes in mesh + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< error status/level + CHARACTER(*),INTENT(OUT) :: ErrMess !< error message + ! optional arguments from here down + ! optional arguments that say whether to allocate fields + ! in the mesh. These are always dimensioned npoints + LOGICAL,OPTIONAL,INTENT(IN):: Force !< If present and true, allocate Force field + LOGICAL,OPTIONAL,INTENT(IN):: Moment !< If present and true, allocate Moment field + LOGICAL,OPTIONAL,INTENT(IN):: Orientation !< If present and true, allocate Orientation field + LOGICAL,OPTIONAL,INTENT(IN):: TranslationDisp !< If present and true, allocate TranslationDisp field + LOGICAL,OPTIONAL,INTENT(IN):: TranslationVel !< If present and true, allocate TranslationVel field + LOGICAL,OPTIONAL,INTENT(IN):: RotationVel !< If present and true, allocate RotationVel field + LOGICAL,OPTIONAL,INTENT(IN):: TranslationAcc !< If present and true, allocate TranslationAcc field + LOGICAL,OPTIONAL,INTENT(IN):: RotationAcc !< If present and true, allocate RotationAcc field +! + INTEGER,OPTIONAL,INTENT(IN):: nScalars !< If present and > 0, allocate nScalars Scalars + LOGICAL,OPTIONAL,INTENT(IN):: IsNewSibling !< If present and true, this is an new sibling so don't allocate new shared fields (RemapFlag, position, RefOrientation, and ElemTable) + + ! Local + INTEGER i + LOGICAL :: IsNewSib + + LOGICAL :: IsMotion + LOGICAL :: IsLoad + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMess2 + CHARACTER(*),PARAMETER :: RoutineName = 'MeshCreate' + + ! Local initializations: + + ErrStat = ErrID_None + ErrMess = "" + IsMotion = .FALSE. + IsLoad = .FALSE. + + IF ( mesh_debug ) print*,'Called MeshCreate' + + CALL MeshDestroy( BlankMesh, ErrStat2, ErrMess2, .TRUE. ) + ! make sure we're not leaving any pointers dangling + ! and nullify them for good measure + ! See comment on optional IgnoreSibling argument + ! in definition of MeshDestroy + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + BlankMesh%initialized = .TRUE. + BlankMesh%IOS = IOS + +!bjj: check that IOS is valid and Nnodes > 0? + + BlankMesh%Nnodes = Nnodes + BlankMesh%nelemlist = 0 ; BlankMesh%maxelemlist = 0 ; + + + ! These fields are shared between siblings, so we don't want to recreate space for them here. + IsNewSib = .FALSE. + IF ( PRESENT(IsNewSibling) ) IsNewSib = IsNewSibling + + IF ( .NOT. IsNewSib ) THEN + CALL AllocPAry( BlankMesh%Position, 3, Nnodes, 'MeshCreate: Position', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + CALL AllocPAry( BlankMesh%RefOrientation, 3, 3, Nnodes, 'MeshCreate: RefOrientation', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + ! initialize these variables: + BlankMesh%Position = 0.0_ReKi + CALL Eye(BlankMesh%RefOrientation, ErrStat2, ErrMess2) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + + ALLOCATE(BlankMesh%ElemTable(NELEMKINDS),STAT=ErrStat2) + IF (ErrStat2/=0) THEN + CALL SetErrStat(ErrID_Fatal, "Error allocating ElemTable.", ErrStat, ErrMess,RoutineName) + RETURN + END IF + + + DO i = 1, NELEMKINDS + BlankMesh%ElemTable(i)%nelem = 0 ; BlankMesh%ElemTable(i)%maxelem = 0 + NULLIFY(BlankMesh%ElemTable(i)%Elements ) + ENDDO + + ALLOCATE(BlankMesh%RemapFlag, Stat=ErrStat2 ) ! assign some space for this pointer to point to + IF (ErrStat2/=0) THEN + CALL SetErrStat(ErrID_Fatal, "Error allocating RemapFlag.", ErrStat, ErrMess,RoutineName) + RETURN + END IF + BlankMesh%RemapFlag = .true. + + ELSE + NULLIFY( BlankMesh%Position ) + NULLIFY( BlankMesh%RefOrientation ) + NULLIFY( BlankMesh%ElemTable ) + NULLIFY( BlankMesh%ElemList ) + NULLIFY( BlankMesh%RemapFlag ) + END IF + NULLIFY( BlankMesh%SiblingMesh ) + + ! handle optionals + BlankMesh%FieldMask = .FALSE. + + IF ( PRESENT(Force) ) THEN + IF ( Force ) THEN + CALL AllocAry( BlankMesh%Force, 3, Nnodes, 'MeshCreate: Force', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%Force = 0. + BlankMesh%FieldMask(MASKID_FORCE) = .TRUE. + IsLoad = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(Moment) ) THEN + IF ( Moment ) THEN + CALL AllocAry( BlankMesh%Moment, 3, Nnodes, 'MeshCreate: Moment', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%Moment = 0. + BlankMesh%FieldMask(MASKID_MOMENT) = .TRUE. + IsLoad = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(Orientation) ) THEN + IF ( Orientation ) THEN + CALL AllocAry( BlankMesh%Orientation, 3, 3, Nnodes, 'MeshCreate: Orientation', ErrStat2,ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + CALL Eye(BlankMesh%Orientation, ErrStat2, ErrMess2) ! set this orientation to the identity matrix + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + BlankMesh%FieldMask(MASKID_ORIENTATION) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(TranslationDisp) ) THEN + IF ( TranslationDisp ) THEN + CALL AllocAry( BlankMesh%TranslationDisp, 3, Nnodes, 'MeshCreate: TranslationDisp', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationDisp = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONDISP) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(TranslationVel) ) THEN + IF ( TranslationVel ) THEN + CALL AllocAry( BlankMesh%TranslationVel, 3, Nnodes, 'MeshCreate: TranslationVel', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationVel = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONVEL) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(RotationVel) ) THEN + IF ( RotationVel ) THEN + CALL AllocAry( BlankMesh%RotationVel, 3, Nnodes, 'MeshCreate: RotationVel', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%RotationVel = 0. + BlankMesh%FieldMask(MASKID_ROTATIONVEL) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(TranslationAcc) ) THEN + IF ( TranslationAcc ) THEN + CALL AllocAry( BlankMesh%TranslationAcc, 3, Nnodes, 'MeshCreate: TranslationAcc', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationAcc = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONACC) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + IF ( PRESENT(RotationAcc) ) THEN + IF ( RotationAcc ) THEN + CALL AllocAry( BlankMesh%RotationAcc, 3, Nnodes, 'MeshCreate: RotationAcc', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%RotationAcc = 0. + BlankMesh%FieldMask(MASKID_ROTATIONACC) = .TRUE. + IsMotion = .TRUE. + ENDIF + ENDIF + + + BlankMesh%nScalars = 0 + IF ( PRESENT(nScalars) ) THEN + IF ( nScalars .GT. 0 ) THEN + CALL AllocAry( BlankMesh%Scalars, nScalars, Nnodes, 'MeshCreate: Scalars', ErrStat2,ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%Scalars = 0. + BlankMesh%FieldMask(MASKID_Scalar) = .TRUE. + BlankMesh%nScalars = nScalars + !IsMotion = .TRUE. !bjj: do we care about this one? + ENDIF + ENDIF + + + !........................ + ! Let's make sure that we have all the necessary fields: + !........................ + !> This routine will add any required fields that were not explicitly requested. + !! If the mesh has motion fields and it is an input mesh, it must always have the following fields: TranslationDisp, TranslationVel, TranslationAcc + IF ( IsMotion .AND. IOS == COMPONENT_INPUT ) THEN + + IF ( .NOT. BlankMesh%FieldMask(MASKID_TRANSLATIONDISP)) THEN + CALL AllocAry( BlankMesh%TranslationDisp, 3, Nnodes, 'MeshCreate: TranslationDisp', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationDisp = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONDISP) = .TRUE. + !CALL SetErrStat(ErrID_Info, 'Meshes with motion fields must also contain the TranslationDisp field.',ErrStat,ErrMsg,'MeshCreate') + ENDIF + + IF ( .NOT. BlankMesh%FieldMask(MASKID_TRANSLATIONVEL)) THEN + CALL AllocAry( BlankMesh%TranslationVel, 3, Nnodes, 'MeshCreate: TranslationVel', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationVel = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONVEL) = .TRUE. + !CALL SetErrStat(ErrID_Info, 'Meshes with motion fields must also contain the TranslationVel field.',ErrStat,ErrMsg,'MeshCreate') + ENDIF + + IF ( .NOT. BlankMesh%FieldMask(MASKID_TRANSLATIONACC)) THEN + CALL AllocAry( BlankMesh%TranslationAcc, 3, Nnodes, 'MeshCreate: TranslationAcc', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%TranslationAcc = 0. + BlankMesh%FieldMask(MASKID_TRANSLATIONACC) = .TRUE. + !CALL SetErrStat(ErrID_Info, 'Meshes with motion fields must also contain the TranslationAcc field.',ErrStat,ErrMsg,'MeshCreate') + ENDIF + + END IF + + !> If the mesh has load fields and it is an input mesh, it must always have the following fields: Moment + IF ( IsLoad .AND. IOS == COMPONENT_INPUT ) THEN + + IF ( .NOT. BlankMesh%FieldMask(MASKID_MOMENT)) THEN + CALL AllocAry( BlankMesh%Moment, 3, Nnodes, 'MeshCreate: Moment', ErrStat2, ErrMess2 ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + BlankMesh%Moment = 0. + BlankMesh%FieldMask(MASKID_MOMENT) = .TRUE. + !CALL SetErrStat(ErrID_Info, 'Meshes with load fields must also contain the Moment field.',ErrStat,ErrMsg,'MeshCreate') + ENDIF + + END IF + + + RETURN + + END SUBROUTINE MeshCreate + +!> Destroy the given mesh and deallocate all of its data. If the optional IgnoreSibling argument +!! is set to TRUE, destroying a sibling in a set has no effect on the other siblings other than +!! to remove the victim from the list of siblings. If IgnoreSibling is omitted or is set to FALSE, +!! all of the other siblings in the set will be destroyed as well. + RECURSIVE SUBROUTINE MeshDestroy ( Mesh, ErrStat, ErrMess, IgnoreSibling ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh to be vaporized + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status/code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + ! On a brand new mesh, the pointers to siblings may not be nullified and + ! thus undefined (which may cause ASSOCIATED to report .true. erroneously) + ! This despite use of => NULL in declaration of this fields for MeshType. Sigh. (15-dec-2015 bjj: not sure this is true; some fields didn't use => NULL) + ! So ... + LOGICAL, INTENT(IN), OPTIONAL :: IgnoreSibling !< if IgnoreSibling is present and true, don't follow the sibling pointers. + !! Instead just unconditionally nullify these. + !! Use this carefully, since it can leave dangling memory if used for a + !! mesh that already exists and has existing siblings. + + ! Local + LOGICAL IgSib + INTEGER i, j + + ErrStat = ErrID_None + + !IF ( .NOT. Mesh%Initialized ) RETURN + + ! Deallocate/Nullify/Deinitialize values that are not shared between siblings: + + Mesh%initialized = .FALSE. + Mesh%committed = .FALSE. + Mesh%fieldmask = .FALSE. + Mesh%ios = 0 + Mesh%Nnodes = 0 + + IF ( ALLOCATED(Mesh%Force) ) DEALLOCATE(Mesh%Force) + IF ( ALLOCATED(Mesh%Moment) ) DEALLOCATE(Mesh%Moment) + IF ( ALLOCATED(Mesh%Orientation) ) DEALLOCATE(Mesh%Orientation) + IF ( ALLOCATED(Mesh%TranslationDisp)) DEALLOCATE(Mesh%TranslationDisp) + IF ( ALLOCATED(Mesh%RotationVel) ) DEALLOCATE(Mesh%RotationVel) + IF ( ALLOCATED(Mesh%TranslationVel) ) DEALLOCATE(Mesh%TranslationVel) + IF ( ALLOCATED(Mesh%RotationAcc) ) DEALLOCATE(Mesh%RotationAcc) + IF ( ALLOCATED(Mesh%TranslationAcc) ) DEALLOCATE(Mesh%TranslationAcc) + IF ( ALLOCATED(Mesh%Scalars) ) DEALLOCATE(Mesh%Scalars) + + +!bjj: if we keep the sibling, deleting this table is going to be a problem + + IgSib = .FALSE. + IF ( PRESENT( IgnoreSibling ) ) THEN + IgSib = IgnoreSibling + ENDIF + + + IF ( .NOT. ASSOCIATED( Mesh%SiblingMesh ) ) THEN ! There is no sibling mesh so we don't want to keep the data. + + ! Deallocate and Nullify all fields that can be shared between siblings + + IF ( ASSOCIATED(Mesh%RemapFlag) ) THEN + DEALLOCATE(Mesh%RemapFlag) + NULLIFY(Mesh%RemapFlag) + END IF + + IF ( ASSOCIATED(Mesh%ElemTable) ) THEN + DO i = 1, NELEMKINDS + Mesh%ElemTable(i)%nelem = 0 ; Mesh%ElemTable(i)%maxelem = 0 + IF (ASSOCIATED(Mesh%ElemTable(i)%Elements)) THEN + DO j = 1, SIZE(Mesh%ElemTable(i)%Elements) + IF (ALLOCATED(Mesh%ElemTable(i)%Elements(j)%ElemNodes)) THEN + DEALLOCATE(Mesh%ElemTable(i)%Elements(j)%ElemNodes) + ENDIF + !IF (ASSOCIATED(Mesh%ElemTable(i)%Elements(j)%Neighbors)) THEN + ! DEALLOCATE(Mesh%ElemTable(i)%Elements(j)%Neighbors) + ! NULLIFY(Mesh%ElemTable(i)%Elements(j)%Neighbors) + !ENDIF + ENDDO + DEALLOCATE(Mesh%ElemTable(i)%Elements) + NULLIFY(Mesh%ElemTable(i)%Elements) + ENDIF + ENDDO + DEALLOCATE(Mesh%ElemTable) + NULLIFY(Mesh%ElemTable) + ENDIF + + IF (ASSOCIATED(Mesh%ElemList) ) THEN + DEALLOCATE(Mesh%ElemList) ! These elements pointed to the ElemTable data, which we've deallocated already + NULLIFY( Mesh%ElemList ) + END IF + + IF ( ASSOCIATED(Mesh%Position) ) THEN + DEALLOCATE(Mesh%Position) + NULLIFY(Mesh%Position) + END IF + + IF ( ASSOCIATED(Mesh%RefOrientation) ) THEN + DEALLOCATE(Mesh%RefOrientation) + NULLIFY(Mesh%RefOrientation) + END IF + + + ELSE ! Keep the data for an existing sibling mesh (nullify but don't deallocate): + + NULLIFY( Mesh%RemapFlag ) + NULLIFY( Mesh%ElemTable ) + NULLIFY( Mesh%ElemList ) + NULLIFY( Mesh%Position ) + NULLIFY( Mesh%RefOrientation ) + + ! Tell the sibling that this sibling doesn't exist (avoid endless recursion): + IF ( ASSOCIATED( Mesh%SiblingMesh%SiblingMesh ) ) THEN ! the mesh should be associated with Mesh%SiblingMesh%SiblingMesh + NULLIFY( Mesh%SiblingMesh%SiblingMesh ) + ELSE + ! Throw a fault here. The mesh's twin should point back to this mesh. + ErrStat = ErrID_Fatal + ErrMess = 'ModMesh: MeshDestroy: estranged twin mesh.' + CALL ProgAbort ( ErrMess ) !bjj: our handbook says we shouldn't call ProgAbort, except in the Glue code + !jm: but this is framework code, not a contributed module, and this is a fatal error + !bjj: it's called from contributed modules; but, assuming we've done the rest of this correctly, we'd never get an estranged twin mesh, right? + ! If we abort using the FAST-for-Matlab code, Matlab will almost certainly have to restart because files are locked (or it runs out of memory). a pain. + RETURN + ENDIF + + IF ( .not. IgSib ) THEN ! don't Ignore the sibling (i.e., delete it, too) + CALL MeshDestroy( Mesh%SiblingMesh, ErrStat, ErrMess ) + IF (ErrStat >= AbortErrLev) RETURN + ENDIF !IgSib + + END IF + + NULLIFY( Mesh%SiblingMesh ) + + + END SUBROUTINE MeshDestroy + +!---------------------------------------------------------------------------------------------------------------------------------- +! Format of the Int buffer +! word +! 1 Total size of Int buffer in bytes +! 2 Total size of Real buffer in bytes +! 3 Total size of Db buffer in bytes +! 4 IOS +! 5 Number of Nodes +! 6 Number of element records +! 7 FieldMask FIELDMASK_SIZE +! 7+$7 Table Entries $5 * SIZE(ElemRecType) +! +!> Given a mesh and allocatable buffers of type INTEGER(IntKi), REAL(ReKi), and REAL(DbKi), +!! return the mesh information compacted into consecutive elements of the corresponding buffers. +!! This would be done to allow subsequent writing of the buffers to a file for restarting later. +!! The sense of the name is "pack the data from the mesh into buffers". IMPORTANT: MeshPack +!! allocates the three buffers. It is incumbent upon the calling program to deallocate the +!! buffers when they are no longer needed. For sibling meshes, MeshPack should be called +!! separately for each sibling, because the fields allocated with the siblings are separate +!! and unique to each sibling. + SUBROUTINE MeshPack ( Mesh, ReKiBuf, DbKiBuf, IntKiBuf , ErrStat, ErrMess, SizeOnly ) + + TYPE(MeshType), INTENT(IN ) :: Mesh ! Mesh being packed + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) ! Real buffer + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) ! Double buffer + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) ! Int buffer + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + + ! Local + INTEGER(IntKi) :: Re_BufSz ! number of reals in the buffer + INTEGER(IntKi) :: Re_Xferred ! number of reals transferred + INTEGER(IntKi) :: Db_BufSz ! number of doubles in the buffer + INTEGER(IntKi) :: Db_Xferred ! number of doubles transferred + INTEGER(IntKi) :: Int_BufSz ! number of integers in the buffer + INTEGER(IntKi) :: Int_Xferred ! number of integers transferred + + + INTEGER i,j, nelemnodes + LOGICAL OnlySize + INTEGER(IntKi) :: ErrStat2 + !CHARACTER(1024) :: ErrMess2 + CHARACTER(*), PARAMETER :: RoutineName = "MeshPack" + + + ErrStat = ErrID_None + ErrMess = "" + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) OnlySize = SizeOnly + + + ! bjj: figure out what to do about sibling meshes... (for now, I'm going to ignore them) + + !......................................... + ! get number of integer values + !......................................... + IF (.NOT. Mesh%Initialized) THEN ! we don't need to store any data; it's a blank mesh + Int_BufSz = 1 + ELSE ! initialized, may or may not be committed + Int_BufSz = 3 & ! number of logicals in MeshType (initialized, committed, RemapFlag) + + FIELDMASK_SIZE & ! number of logicals in MeshType (fieldmask) + + 5 ! number of non-pointer integers (ios, nnodes, nextelem, nscalars, refNode) + + !...... + ! we'll store the element structure (and call MeshCommit on Unpack if necessary to get the remaining fields like det_jac) + !...... + DO i = 1, NELEMKINDS + + Int_BufSz = Int_BufSz+1 ! Mesh%ElemTable(i)%nelem + if (Mesh%ElemTable(i)%nelem > 0) Int_BufSz = Int_BufSz+1 ! number of nodes in this kind of element + + DO j = 1, Mesh%ElemTable(i)%nelem + !Int_BufSz = Int_BufSz+1 ! which kind of element + !Int_BufSz = Int_BufSz+1 ! skip Nneighbors until that's implemented (as well as neighbor list) + Int_BufSz = Int_BufSz + SIZE( Mesh%ElemTable(i)%Elements(j)%ElemNodes ) ! nodes in this element + END DO + + END DO + + END IF + + !......................................... + ! get number of real values + !......................................... + Re_BufSz = 0 + IF (Mesh%Initialized) THEN + Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 ! Position + !Re_BufSz = Re_BufSz + Mesh%Nnodes * 9 ! RefOrientation + IF ( Mesh%FieldMask(MASKID_FORCE) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%FieldMask(MASKID_MOMENT) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + !IF ( Mesh%FieldMask(MASKID_ORIENTATION) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 9 + !IF ( Mesh%FieldMask(MASKID_TRANSLATIONDISP) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%FieldMask(MASKID_ROTATIONVEL) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%FieldMask(MASKID_TRANSLATIONVEL) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%FieldMask(MASKID_ROTATIONACC) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%FieldMask(MASKID_TRANSLATIONACC) ) Re_BufSz = Re_BufSz + Mesh%Nnodes * 3 + IF ( Mesh%nScalars .GT. 0 ) Re_BufSz = Re_BufSz + Mesh%Nnodes * Mesh%nScalars + END IF + + !......................................... + ! get number of double values (none now) + !......................................... + Db_BufSz = 0 + IF (Mesh%Initialized) THEN + Db_BufSz = Db_BufSz + Mesh%Nnodes * 9 ! RefOrientation + IF ( Mesh%FieldMask(MASKID_ORIENTATION) ) Db_BufSz = Db_BufSz + Mesh%Nnodes * 9 + IF ( Mesh%FieldMask(MASKID_TRANSLATIONDISP) ) Db_BufSz = Db_BufSz + Mesh%Nnodes * 3 + END IF + + !......................................... + ! allocate buffer arrays + !......................................... + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMess,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, ErrMess,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, ErrMess,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + + !......................................... + ! store data in buffer arrays + !......................................... + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ! ..... fill IntKiBuf ..... + + IF (.NOT. Mesh%Initialized) THEN ! we don't need to store any data; it's a blank mesh + IntKiBuf(Int_Xferred) = 0; ; Int_Xferred = Int_Xferred + 1 + ELSE ! initialized, may or may not be committed + ! transfer the logicals + IntKiBuf(Int_Xferred) = 1; Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER( Mesh%committed, IntKiBuf(1) ); Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred:Int_Xferred+FIELDMASK_SIZE-1) = TRANSFER( Mesh%fieldmask, IntKiBuf(Int_Xferred:Int_Xferred+FIELDMASK_SIZE-1) ); Int_Xferred = Int_Xferred + FIELDMASK_SIZE + IntKiBuf(Int_Xferred) = TRANSFER( Mesh%RemapFlag, IntKiBuf(1) ); Int_Xferred = Int_Xferred + 1 + ! integers + IntKiBuf(Int_Xferred) = Mesh%ios; Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = Mesh%nnodes; Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = Mesh%refnode; Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = Mesh%nextelem; Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = Mesh%nscalars; Int_Xferred = Int_Xferred + 1 + + ! element structure + DO i = 1, NELEMKINDS + + IntKiBuf(Int_Xferred) = Mesh%ElemTable(i)%nelem; Int_Xferred = Int_Xferred + 1 ! number of elements + + if (Mesh%ElemTable(i)%nelem > 0) then + nelemnodes = SIZE( Mesh%ElemTable(i)%Elements(1)%ElemNodes ); + IntKiBuf(Int_Xferred) = nelemnodes; Int_Xferred = Int_Xferred + 1 ! nodes per element + + ! nodes in this element + DO j = 1, Mesh%ElemTable(i)%nelem + IntKiBuf(Int_Xferred:Int_Xferred+nelemnodes-1) = Mesh%ElemTable(i)%Elements(j)%ElemNodes; Int_Xferred = Int_Xferred + nelemnodes + END DO + end if + + END DO + + END IF + + ! ..... fill ReKiBuf and DbKiBuf ..... + IF (Mesh%Initialized) THEN + DO i = 1, Mesh%Nnodes ! Position + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%Position(:,i); Re_Xferred = Re_Xferred + 3 + END DO + DO i = 1, Mesh%Nnodes ! RefOrientation + DO j = 1,3 + DbKiBuf(Db_Xferred:Db_Xferred+2) = Mesh%RefOrientation(:,j,i); Db_Xferred = Db_Xferred + 3 + ENDDO + END DO + + IF ( Mesh%FieldMask(MASKID_FORCE) ) THEN ! Force + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%Force(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_MOMENT) ) THEN ! Moment + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%Moment(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_ORIENTATION) ) THEN ! Orientation + DO i = 1, Mesh%Nnodes + DO j = 1,3 + DbKiBuf(Db_Xferred:Db_Xferred+2) = Mesh%Orientation(:,j,i); Db_Xferred = Db_Xferred + 3 + ENDDO + END DO + ENDIF + IF ( Mesh%FieldMask(MASKID_TRANSLATIONDISP) ) THEN ! TranslationDisp + DO i = 1, Mesh%Nnodes + DbKiBuf(Db_Xferred:Db_Xferred+2) = Mesh%TranslationDisp(:,i); Db_Xferred = Db_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_ROTATIONVEL) ) THEN ! RotationVel + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%RotationVel(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_TRANSLATIONVEL) ) THEN ! TranslationVel + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%TranslationVel(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_ROTATIONACC) ) THEN ! RotationAcc + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%RotationAcc(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( Mesh%FieldMask(MASKID_TRANSLATIONACC) ) THEN ! TranslationAcc + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+2) = Mesh%TranslationAcc(:,i); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + + IF ( Mesh%nScalars .GT. 0 ) THEN ! n_re = n_re + Mesh%Nnodes * Mesh%nScalar + DO i = 1, Mesh%Nnodes + ReKiBuf(Re_Xferred:Re_Xferred+Mesh%nScalars-1) = Mesh%Scalars(:,i); Re_Xferred = Re_Xferred + Mesh%nScalars + ENDDO + ENDIF + + END IF + + !bjj: where are we keeping track of which ones are siblings so that we can unpack them (set pointers) properly for restart? + END SUBROUTINE MeshPack + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a blank, uncreated mesh and buffers of type INTEGER(IntKi), REAL(ReKi), and +!! REAL(DbKi), unpack the mesh information from the buffers. This would be done to +!! recreate a mesh after reading in the buffers on a restart of the program. The sense +!! of the name is "unpack the mesh from buffers." The resulting mesh will be returned +!! in the exact state as when the data in the buffers was packed using MeshPack. + SUBROUTINE MeshUnpack( Mesh, ReKiBuf, DbKiBuf, IntKiBuf, ErrStat, ErrMess ) + + ! bjj: not implemented yet: + ! If the mesh has an already recreated sibling mesh from a previous call to MeshUnpack, specify + ! the existing sibling as an optional argument so that the sibling relationship is also recreated. + + TYPE(MeshType), INTENT(INOUT) :: Mesh + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMess + + ! Local + LOGICAL committed, RemapFlag, fieldmask(FIELDMASK_SIZE) + INTEGER nScalars, ios, nnodes, nextelem, nelemnodes, nelem, refnode + INTEGER i,j + + INTEGER(IntKi) :: Re_Xferred ! number of reals transferred + INTEGER(IntKi) :: Db_Xferred ! number of doubles transferred + INTEGER(IntKi) :: Int_Xferred ! number of integers transferred + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMess2 + CHARACTER(*), PARAMETER :: RoutineName = "MeshUnpack" + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ErrStat = ErrID_None + ErrMess = "" + + IF (IntKiBuf(Int_Xferred) == 0 ) THEN ! this is a blank mesh + CALL MeshDestroy( Mesh, ErrStat2, ErrMess2, .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMess2,ErrStat,ErrMess,RoutineName) + RETURN + END IF + + + ! initialized, may or may not be committed + + Mesh%initialized = .true.; Int_Xferred = Int_Xferred + 1 + committed = TRANSFER( IntKiBuf(Int_Xferred), Mesh%committed ); Int_Xferred = Int_Xferred + 1 + fieldmask = TRANSFER( IntKiBuf(Int_Xferred:Int_Xferred+FIELDMASK_SIZE-1), fieldmask ); Int_Xferred = Int_Xferred + FIELDMASK_SIZE + RemapFlag = TRANSFER( IntKiBuf(Int_Xferred), Mesh%RemapFlag ); Int_Xferred = Int_Xferred + 1 + ! integers + ios = IntKiBuf(Int_Xferred) ; Int_Xferred = Int_Xferred + 1 + nnodes = IntKiBuf(Int_Xferred) ; Int_Xferred = Int_Xferred + 1 + refnode = IntKiBuf(Int_Xferred) ; Int_Xferred = Int_Xferred + 1 + nextelem = IntKiBuf(Int_Xferred) ; Int_Xferred = Int_Xferred + 1 + nscalars = IntKiBuf(Int_Xferred) ; Int_Xferred = Int_Xferred + 1 + + + CALL MeshCreate( Mesh, ios, nnodes & + ,ErrStat=ErrStat2, ErrMess=ErrMess2 & + ,Force =fieldmask(MASKID_FORCE) & + ,Moment =fieldmask(MASKID_MOMENT) & + ,Orientation =fieldmask(MASKID_ORIENTATION) & + ,TranslationDisp=fieldmask(MASKID_TRANSLATIONDISP) & + ,TranslationVel =fieldmask(MASKID_TRANSLATIONVEL ) & + ,RotationVel =fieldmask(MASKID_ROTATIONVEL ) & + ,TranslationAcc =fieldmask(MASKID_TRANSLATIONACC ) & + ,RotationAcc =fieldmask(MASKID_ROTATIONACC ) & + ,nScalars = nScalars & + ) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + Mesh%RefNode = refnode + Mesh%RemapFlag = RemapFlag + Mesh%nextelem = nextelem + + ! element structure + DO i = 1, NELEMKINDS + nelem = IntKiBuf(Int_Xferred); Int_Xferred = Int_Xferred + 1 ! number of elements + + if (nelem > 0) then + nelemnodes = IntKiBuf(Int_Xferred); Int_Xferred = Int_Xferred + 1 ! nodes per element + + ! nodes in this element + DO j = 1,nelem + + SELECT CASE (nelemnodes) + CASE (1) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ) & + ) + CASE (2) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1) & + ) + CASE (3) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + ) + CASE (4) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3) & + ) + CASE (6) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3),P5 =IntKiBuf(Int_Xferred+ 4),P6 =IntKiBuf(Int_Xferred+ 5) & + ) + CASE (8) + CALL MeshConstructElement( Mesh, i, ErrStat2, ErrMess2 & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3),P5 =IntKiBuf(Int_Xferred+ 4),P6 =IntKiBuf(Int_Xferred+ 5) & + , P7 =IntKiBuf(Int_Xferred+ 6),P8 =IntKiBuf(Int_Xferred+ 7) & + ) + CASE (10) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3),P5 =IntKiBuf(Int_Xferred+ 4),P6 =IntKiBuf(Int_Xferred+ 5) & + , P7 =IntKiBuf(Int_Xferred+ 6),P8 =IntKiBuf(Int_Xferred+ 7),P9 =IntKiBuf(Int_Xferred+ 8) & + , P10=IntKiBuf(Int_Xferred+ 9) & + ) + CASE (15) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3),P5 =IntKiBuf(Int_Xferred+ 4),P6 =IntKiBuf(Int_Xferred+ 5) & + , P7 =IntKiBuf(Int_Xferred+ 6),P8 =IntKiBuf(Int_Xferred+ 7),P9 =IntKiBuf(Int_Xferred+ 8) & + , P10=IntKiBuf(Int_Xferred+ 9),P11=IntKiBuf(Int_Xferred+10),P12=IntKiBuf(Int_Xferred+11) & + , P13=IntKiBuf(Int_Xferred+12),P14=IntKiBuf(Int_Xferred+13),P15=IntKiBuf(Int_Xferred+14) & + ) + CASE (20) + CALL MeshConstructElement( Mesh, i, ErrStat, ErrMess & + , P1 =IntKiBuf(Int_Xferred ),P2 =IntKiBuf(Int_Xferred+ 1),P3 =IntKiBuf(Int_Xferred+ 2) & + , P4 =IntKiBuf(Int_Xferred+ 3),P5 =IntKiBuf(Int_Xferred+ 4),P6 =IntKiBuf(Int_Xferred+ 5) & + , P7 =IntKiBuf(Int_Xferred+ 6),P8 =IntKiBuf(Int_Xferred+ 7),P9 =IntKiBuf(Int_Xferred+ 8) & + , P10=IntKiBuf(Int_Xferred+ 9),P11=IntKiBuf(Int_Xferred+10),P12=IntKiBuf(Int_Xferred+11) & + , P13=IntKiBuf(Int_Xferred+12),P14=IntKiBuf(Int_Xferred+13),P15=IntKiBuf(Int_Xferred+14) & + , P16=IntKiBuf(Int_Xferred+15),P17=IntKiBuf(Int_Xferred+16),P18=IntKiBuf(Int_Xferred+17) & + , P19=IntKiBuf(Int_Xferred+18),P20=IntKiBuf(Int_Xferred+19) & + ) + CASE DEFAULT + CALL SetErrStat(ErrID_Fatal,"No such element. Probably manged buffer.",ErrStat,ErrMess,RoutineName) + RETURN + END SELECT + Int_Xferred = Int_Xferred + nelemnodes + END DO ! Elements of this kind + end if ! if there are any elements of this kind + + END DO ! kinds of elements + + ! ..... fill ReKiBuf ..... + DO i = 1, Mesh%Nnodes ! Position + Mesh%Position(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + END DO + DO i = 1, Mesh%Nnodes ! RefOrientation + DO j = 1,3 + Mesh%RefOrientation(:,j,i) = DbKiBuf(Db_Xferred:Db_Xferred+2); Db_Xferred = Db_Xferred + 3 + ENDDO + END DO + + IF ( FieldMask(MASKID_FORCE) ) THEN ! Force + DO i = 1, Mesh%Nnodes + Mesh%Force(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_MOMENT) ) THEN ! Moment + DO i = 1, Mesh%Nnodes + Mesh%Moment(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_ORIENTATION) ) THEN ! Orientation + DO i = 1, Mesh%Nnodes + DO j = 1,3 + Mesh%Orientation(:,j,i) = DbKiBuf(Db_Xferred:Db_Xferred+2); Db_Xferred = Db_Xferred + 3 + ENDDO + END DO + ENDIF + IF ( FieldMask(MASKID_TRANSLATIONDISP) ) THEN ! TranslationDisp + DO i = 1, Mesh%Nnodes + Mesh%TranslationDisp(:,i) = DbKiBuf(Db_Xferred:Db_Xferred+2); Db_Xferred = Db_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_ROTATIONVEL) ) THEN ! RotationVel + DO i = 1, Mesh%Nnodes + Mesh%RotationVel(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_TRANSLATIONVEL) ) THEN ! TranslationVel + DO i = 1, Mesh%Nnodes + Mesh%TranslationVel(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_ROTATIONACC) ) THEN ! RotationAcc + DO i = 1, Mesh%Nnodes + Mesh%RotationAcc(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + IF ( FieldMask(MASKID_TRANSLATIONACC) ) THEN ! TranslationAcc + DO i = 1, Mesh%Nnodes + Mesh%TranslationAcc(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+2); Re_Xferred = Re_Xferred + 3 + ENDDO + ENDIF + + IF ( Mesh%nScalars .GT. 0 ) THEN ! n_re = n_re + Mesh%Nnodes * Mesh%nScalar + DO i = 1, Mesh%Nnodes + Mesh%Scalars(:,i) = ReKiBuf(Re_Xferred:Re_Xferred+Mesh%nScalars-1); Re_Xferred = Re_Xferred + Mesh%nScalars + ENDDO + ENDIF + + ! commit the mesh + IF (committed) THEN + CALL MeshCommit(Mesh, ErrStat2, ErrMess2) + CALL SetErrStat(ErrStat2, ErrMess2, ErrStat, ErrMess, RoutineName) + END IF + + RETURN + + END SUBROUTINE MeshUnpack + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given an existing mesh and a destination mesh, create a completely new copy, a sibling, or +!! update the fields of a second existing mesh from the first mesh. When CtrlCode is +!! MESH_NEWCOPY or MESH_SIBLING, the destination mesh must be a blank, uncreated mesh. +!! +!! If CtrlCode is MESH_NEWCOPY, an entirely new copy of the mesh is created, including all fields, +!! with the same data values as the original, but as an entirely separate copy in memory. The new +!! copy is in the same state as the original--if the original has not been committed, neither is +!! the copy; in this case, an all-new copy of the mesh must be committed separately. +!! +!! If CtrlCode is MESH_SIBLING, the destination mesh is created with the same mesh and position/reference +!! orientation information of the source mesh, and this new sibling is added to the end of the list for +!! the set of siblings. Siblings may have different fields (other than Position and RefOrientation). +!! Therefore, for a sibling, it is necessary, as with MeshCreate, to indicate the fields the sibling +!! will have using optional arguments. Sibling meshes should not be created unless the original mesh +!! has been committed first. +!! +!! If CtrlCode is MESH_UPDATECOPY, all of the allocatable fields of the destination mesh are updated +!! with the values of the fields in the source. (The underlying mesh is untouched.) The mesh and field +!! definitions of the source and destination meshes must match and both must have been already committed. +!! The destination mesh may be an entirely different copy or it may be a sibling of the source mesh. + SUBROUTINE MeshCopy( SrcMesh, DestMesh, CtrlCode, ErrStat , ErrMess & + ,IOS, Force, Moment, Orientation, TranslationDisp, TranslationVel & + ,RotationVel, TranslationAcc, RotationAcc, nScalars ) + + + + TYPE(MeshType), TARGET, INTENT(INOUT) :: SrcMesh !< Mesh being copied + TYPE(MeshType), TARGET, INTENT(INOUT) :: DestMesh !< Copy of mesh + INTEGER(IntKi), INTENT(IN) :: CtrlCode !< MESH_NEWCOPY, MESH_SIBLING, or + !! MESH_UPDATECOPY + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + ! Optional arguments (used only if CtrlCode is MESH_SIBLING): + INTEGER(IntKi), OPTIONAL, INTENT(IN) :: IOS !< If present, IOS of new sibling: input (COMPONENT_INPUT), output(COMPONENT_OUTPUT), or state(COMPONENT_STATE) + LOGICAL, OPTIONAL, INTENT(IN) :: Force !< If present and true, allocate Force field + LOGICAL, OPTIONAL, INTENT(IN) :: Moment !< If present and true, allocate Moment field + LOGICAL, OPTIONAL, INTENT(IN) :: Orientation !< If present and true, allocate Orientation field + LOGICAL, OPTIONAL, INTENT(IN) :: TranslationDisp !< If present and true, allocate TranslationDisp field + LOGICAL, OPTIONAL, INTENT(IN) :: TranslationVel !< If present and true, allocate TranslationVel field + LOGICAL, OPTIONAL, INTENT(IN) :: RotationVel !< If present and true, allocate RotationVel field + LOGICAL, OPTIONAL, INTENT(IN) :: TranslationAcc !< If present and true, allocate TranslationAcc field + LOGICAL, OPTIONAL, INTENT(IN) :: RotationAcc !< If present and true, allocate RotationAcc field + INTEGER(IntKi), OPTIONAL, INTENT(IN) :: nScalars !< If present and > 0 , alloc n Scalars + ! Local + INTEGER(IntKi) :: IOS_l ! IOS of new sibling + LOGICAL :: Force_l & ! If true, allocate Force field + , Moment_l & ! If true, allocate Moment field + , Orientation_l & ! If true, allocate Orientation field + , TranslationDisp_l & ! If true, allocate TranslationDisp field + , TranslationVel_l & ! If true, allocate TranslationVel field + , RotationVel_l & ! If true, allocate RotationVel field + , TranslationAcc_l & ! If true, allocate TranslationAcc field + , RotationAcc_l ! If true, allocate RotationAcc field + INTEGER(IntKi) :: nScalars_l ! If > 0, alloc n Scalars + INTEGER i, j, k, ErrStat2 + + + + + ErrStat = ErrID_None + ErrMess = "" + + IF (.NOT. SrcMesh%Initialized) RETURN !bjj: maybe we should first CALL MeshDestroy(DestMesh,ErrStat, ErrMess) + + IF ( CtrlCode .EQ. MESH_NEWCOPY .OR. CtrlCode .EQ. MESH_SIBLING .OR. CtrlCode .EQ. MESH_COUSIN ) THEN + + IF (CtrlCode .EQ. MESH_NEWCOPY) THEN + IOS_l = SrcMesh%IOS + Force_l = SrcMesh%FieldMask(MASKID_FORCE) + Moment_l = SrcMesh%FieldMask(MASKID_MOMENT) + Orientation_l = SrcMesh%FieldMask(MASKID_ORIENTATION) + TranslationDisp_l = SrcMesh%FieldMask(MASKID_TRANSLATIONDISP) + TranslationVel_l = SrcMesh%FieldMask(MASKID_TRANSLATIONVEL) + RotationVel_l = SrcMesh%FieldMask(MASKID_ROTATIONVEL) + TranslationAcc_l = SrcMesh%FieldMask(MASKID_TRANSLATIONACC) + RotationAcc_l = SrcMesh%FieldMask(MASKID_ROTATIONACC) + nScalars_l = SrcMesh%nScalars + ELSE ! Sibling or cousin + IOS_l = SrcMesh%IOS ; IF ( PRESENT(IOS) ) IOS_l = IOS + Force_l = .FALSE. ; IF ( PRESENT(Force) ) Force_l = Force + Moment_l = .FALSE. ; IF ( PRESENT(Moment) ) Moment_l = Moment + Orientation_l = .FALSE. ; IF ( PRESENT(Orientation) ) Orientation_l = Orientation + TranslationDisp_l = .FALSE. ; IF ( PRESENT(TranslationDisp) ) TranslationDisp_l = TranslationDisp + TranslationVel_l = .FALSE. ; IF ( PRESENT(TranslationVel) ) TranslationVel_l = TranslationVel + RotationVel_l = .FALSE. ; IF ( PRESENT(RotationVel) ) RotationVel_l = RotationVel + TranslationAcc_l = .FALSE. ; IF ( PRESENT(TranslationAcc) ) TranslationAcc_l = TranslationAcc + RotationAcc_l = .FALSE. ; IF ( PRESENT(RotationAcc) ) RotationAcc_l = RotationAcc + nScalars_l = 0 ; IF ( PRESENT(nScalars) ) nScalars_l = nScalars + END IF + + IF ( CtrlCode .EQ. MESH_NEWCOPY .OR. CtrlCode .EQ. MESH_COUSIN ) THEN + + CALL MeshCreate( DestMesh, IOS=IOS_l, Nnodes=SrcMesh%Nnodes, ErrStat=ErrStat, ErrMess=ErrMess & + ,Force=Force_l & + ,Moment=Moment_l & + ,Orientation=Orientation_l & + ,TranslationDisp=TranslationDisp_l & + ,TranslationVel=TranslationVel_l & + ,RotationVel=RotationVel_l & + ,TranslationAcc=TranslationAcc_l & + ,RotationAcc=RotationAcc_l & + ,nScalars=nScalars_l ) + + IF (ErrStat >= AbortErrLev) RETURN + + DestMesh%Position = SrcMesh%Position + DestMesh%RefOrientation = SrcMesh%RefOrientation + + DO i = 1, NELEMKINDS + DestMesh%ElemTable(i)%nelem = SrcMesh%ElemTable(i)%nelem + DestMesh%ElemTable(i)%maxelem = SrcMesh%ElemTable(i)%maxelem + DestMesh%ElemTable(i)%XElement = SrcMesh%ElemTable(i)%XElement + + ALLOCATE(DestMesh%ElemTable(i)%Elements(DestMesh%ElemTable(i)%maxelem),STAT=ErrStat2) + IF (ErrStat2 /=0) THEN + ErrStat = ErrID_Fatal + ErrMess='MeshCopy:Error allocating ElemTable%Elements.' + RETURN !Early return + END IF + + DO j = 1,DestMesh%ElemTable(i)%nelem + + ALLOCATE(DestMesh%ElemTable(i)%Elements(j)%ElemNodes(size(SrcMesh%ElemTable(i)%Elements(j)%ElemNodes)),STAT=ErrStat2) + IF (ErrStat2 /=0) THEN + ErrStat = ErrID_Fatal + ErrMess='MeshCopy:Error allocating ElemTable%ElemNodes.' + RETURN !Early return + END IF + DestMesh%ElemTable(i)%Elements(j)%ElemNodes = SrcMesh%ElemTable(i)%Elements(j)%ElemNodes + DestMesh%ElemTable(i)%Elements(j)%det_jac = SrcMesh%ElemTable(i)%Elements(j)%det_jac + DestMesh%ElemTable(i)%Elements(j)%Xelement = SrcMesh%ElemTable(i)%Elements(j)%Xelement + DestMesh%ElemTable(i)%Elements(j)%Nneighbors= SrcMesh%ElemTable(i)%Elements(j)%Nneighbors +!bjj: allocate Neighbors, too: +! IF (DestMesh%ElemTable(i)%Elements(j)%Nneighbors > 0) then + + ENDDO + ENDDO + + + ! Regenerate new list of elements (point to ElemTable) + !bjj: call meshCommit? + DestMesh%nelemlist = SrcMesh%nelemlist + DestMesh%maxelemlist = SrcMesh%maxelemlist + DestMesh%nextelem = SrcMesh%nextelem + + IF ( SrcMesh%Committed ) THEN + + ALLOCATE(DestMesh%ElemList(DestMesh%maxelemlist),Stat=ErrStat2) + IF (ErrStat2 /=0) THEN + ErrStat = ErrID_Fatal + ErrMess=' MeshCopy: Error allocating ElemList.' + RETURN !Early return + END IF + + k = 0 + DO i = 1, NELEMKINDS + DO j = 1, DestMesh%ElemTable(i)%nelem + k = k + 1 + DestMesh%elemlist(k)%Element => DestMesh%ElemTable(i)%Elements(j) + DestMesh%elemlist(k)%Element%Xelement = i + ENDDO + END DO + + END IF ! SrcMesh%Committed + + DestMesh%RemapFlag = SrcMesh%RemapFlag + + ELSE IF ( CtrlCode .EQ. MESH_SIBLING ) THEN +!bjj: we should make sure the mesh has been committed, otherwise the element lists haven't been created, yet (and thus not shared) + IF ( ASSOCIATED(SrcMesh%SiblingMesh) ) THEN + ErrStat = ErrID_Fatal + ErrMess = ' MeshCopy: A mesh can have only one sibling.' + RETURN !early return + END IF + + IF (.NOT. SrcMesh%Committed ) THEN + ErrStat = ErrID_Fatal + ErrMess = ' MeshCopy: An uncommitted mesh cannot have a sibling.' + RETURN !early return + END IF + + CALL MeshCreate( DestMesh, IOS=IOS_l, Nnodes=SrcMesh%Nnodes, ErrStat=ErrStat, ErrMess=ErrMess & + ,Force=Force_l & + ,Moment=Moment_l & + ,Orientation=Orientation_l & + ,TranslationDisp=TranslationDisp_l & + ,TranslationVel=TranslationVel_l & + ,RotationVel=RotationVel_l & + ,TranslationAcc=TranslationAcc_l & + ,RotationAcc=RotationAcc_l & + ,nScalars=nScalars_l & + ,IsNewSibling=.TRUE.) + IF (ErrStat >= AbortErrLev) RETURN + + !bjj: Doesn't this logic mean we can have only one sibling? + ! I added a check that SrcMesh%SiblingMesh isn't already associated so that we don't lose siblings + DestMesh%SiblingMesh => SrcMesh + SrcMesh%SiblingMesh => DestMesh + + DestMesh%Position => SrcMesh%Position + DestMesh%RefOrientation => SrcMesh%RefOrientation + DestMesh%RemapFlag => SrcMesh%RemapFlag + DestMesh%ElemTable => SrcMesh%ElemTable + DestMesh%ElemList => SrcMesh%ElemList + + DestMesh%nelemlist = SrcMesh%nelemlist + DestMesh%maxelemlist = SrcMesh%maxelemlist + DestMesh%nextelem = SrcMesh%nextelem + + + ENDIF + + DO i = 1, NELEMKINDS + IF ( ASSOCIATED(SrcMesh%ElemTable) ) THEN + ENDIF + IF ( ASSOCIATED(DestMesh%ElemTable) ) THEN + ENDIF + ENDDO + + ELSE IF ( CtrlCode .EQ. MESH_UPDATECOPY ) THEN + + IF ( SrcMesh%nNodes .NE. DestMesh%nNodes ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCopy: MESH_UPDATECOPY of meshes with different numbers of nodes." + RETURN + ENDIF + + ELSE IF ( CtrlCode .EQ. MESH_UPDATEREFERENCE ) THEN + + IF ( SrcMesh%nNodes .NE. DestMesh%nNodes ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCopy:MESH_UPDATEREFERENCE of meshes with different numbers of nodes." + RETURN + ENDIF ! if we have a different number of nodes or different element connectivity, we'll have to redo this + + DestMesh%Position = SrcMesh%Position + DestMesh%RefOrientation = SrcMesh%RefOrientation + DestMesh%RemapFlag = SrcMesh%RemapFlag + + ELSE + ErrStat = ErrID_Fatal + ErrMess = 'MeshCopy: Invalid CtrlCode.' + RETURN + ENDIF + + ! These aren't shared between siblings, so they get copied, no matter what the CtrlCode: + + DestMesh%Initialized = SrcMesh%Initialized + DestMesh%Committed = SrcMesh%Committed + DestMesh%refNode = SrcMesh%refNode + IF ( ALLOCATED(SrcMesh%Force ) .AND. ALLOCATED(DestMesh%Force ) ) DestMesh%Force = SrcMesh%Force + IF ( ALLOCATED(SrcMesh%Moment ) .AND. ALLOCATED(DestMesh%Moment ) ) DestMesh%Moment = SrcMesh%Moment + IF ( ALLOCATED(SrcMesh%Orientation ) .AND. ALLOCATED(DestMesh%Orientation ) ) DestMesh%Orientation = SrcMesh%Orientation + IF ( ALLOCATED(SrcMesh%TranslationDisp) .AND. ALLOCATED(DestMesh%TranslationDisp) ) DestMesh%TranslationDisp = SrcMesh%TranslationDisp + IF ( ALLOCATED(SrcMesh%TranslationVel ) .AND. ALLOCATED(DestMesh%TranslationVel ) ) DestMesh%TranslationVel = SrcMesh%TranslationVel + IF ( ALLOCATED(SrcMesh%RotationVel ) .AND. ALLOCATED(DestMesh%RotationVel ) ) DestMesh%RotationVel = SrcMesh%RotationVel + IF ( ALLOCATED(SrcMesh%TranslationAcc ) .AND. ALLOCATED(DestMesh%TranslationAcc ) ) DestMesh%TranslationAcc = SrcMesh%TranslationAcc + IF ( ALLOCATED(SrcMesh%RotationAcc ) .AND. ALLOCATED(DestMesh%RotationAcc ) ) DestMesh%RotationAcc = SrcMesh%RotationAcc + IF ( ALLOCATED(SrcMesh%Scalars ) .AND. ALLOCATED(DestMesh%Scalars ) ) DestMesh%Scalars = SrcMesh%Scalars + + + !DestMesh%spatial = SrcMesh%spatial !bjj: unused? + + END SUBROUTINE MeshCopy + +!---------------------------------------------------------------------------------------------------------------------------------- +!> For a given node in a mesh, assign the coordinates of the node in the global coordinate space. +!! If an Orient argument is included, the node will also be assigned the specified orientation +!! (orientation is assumed to be the identity matrix if omitted). Returns a non-zero value in +!! ErrStat if Inode is outside the range 1..Nnodes. + SUBROUTINE MeshPositionNode( Mesh, Inode, Pos, ErrStat, ErrMess, Orient, Ref ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being spatio-located + INTEGER(IntKi), INTENT(IN ) :: Inode !< Number of node being located + REAL(ReKi), INTENT(IN ) :: Pos(3) !< Xi,Yi,Zi, coordinates of node + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT( OUT) :: ErrMess !< Error message + REAL(R8Ki), OPTIONAL, INTENT(IN ) :: Orient(3,3) !< Orientation (direction cosine matrix) of node; identity by default + LOGICAL, OPTIONAL, INTENT(IN ) :: Ref + + ErrStat = ErrID_None + ErrMess = "" + ! Safety first + IF ( .NOT. Mesh%Initialized ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: attempt to use uncreated mesh." + ENDIF + IF ( Mesh%Nnodes < 0 ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: Invalid number of nodes: "//TRIM(Num2LStr(Mesh%Nnodes)) + ENDIF + IF (Mesh%Committed ) THEN !bjj: perhaps this shouldn't be an error? Maybe it just sets Mesh%RemapFlag = .TRUE. + ErrStat = ErrID_Fatal + ErrMess = " MeshPositionNode: attempt to reposition committed mesh." + END IF + + IF ( .NOT. ( Inode .GE. 1 .AND. Inode .LE. Mesh%Nnodes ) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: not 1 <= Inode("//TRIM(Num2LStr(Inode))//") <= "//TRIM(Num2LStr(Mesh%Nnodes)) + ENDIF + IF ( .NOT. ASSOCIATED(Mesh%Position) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: Position array not associated" + ENDIF + IF ( .NOT. SIZE(Mesh%Position,2) .GE. Mesh%Nnodes ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: Position array not big enough" + ENDIF + IF ( .NOT. ASSOCIATED(Mesh%RefOrientation) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: RefOrientation array not associated" + ENDIF + IF ( .NOT. SIZE(Mesh%RefOrientation,3) .GE. Mesh%Nnodes ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshPositionNode: RefOrientation array not big enough" + ENDIF + + + + IF ( ErrStat .NE. ErrID_None ) RETURN ! early return on error + + ! Business + Mesh%Position(:,Inode) = Pos + + IF ( PRESENT(Orient) ) THEN + Mesh%RefOrientation(:,:,Inode) = Orient + ELSE + Mesh%RefOrientation(:,1,Inode) = (/ 1._R8Ki, 0._R8Ki, 0._R8Ki /) + Mesh%RefOrientation(:,2,Inode) = (/ 0._R8Ki, 1._R8Ki, 0._R8Ki /) + Mesh%RefOrientation(:,3,Inode) = (/ 0._R8Ki, 0._R8Ki, 1._R8Ki /) + END IF + + IF (PRESENT(Ref)) THEN + Mesh%RefNode = Inode + END IF + + RETURN + + END SUBROUTINE MeshPositionNode + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mesh that has been created, spatio-located, and constructed, +!! commit the definition of the mesh, making it ready for initialization +!! and use. Explicitly committing a mesh provides the opportunity to precompute +!! traversal information, neighbor lists and other information about the mesh. +!! Returns non-zero in value of ErrStat on error. + SUBROUTINE MeshCommit( Mesh, ErrStat, ErrMess ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being committed + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + ! Local + REAL(ReKi) :: n1_n2_vector(3) ! vector going from node 1 to node 2 in a Line2 element + INTEGER n0d, n1d, n2d, n3d, nn, i, j, NElem, n1,n2 + LOGICAL :: NodeInElement(Mesh%NNodes) ! determines if each node is part of an element + + !TYPE(ElemListType), POINTER :: tmp(:) + + IF (Mesh%Committed) then + ErrStat = ErrID_Warn + ErrMess = "MeshCommit: mesh was already committed." + RETURN ! Early return + ENDIF + + !> Check for spatial constraints -- can't mix 1D with 2D with 3D + n0d = Mesh%ElemTable(ELEMENT_POINT)%nelem + n1d = Mesh%ElemTable(ELEMENT_LINE2)%nelem+Mesh%ElemTable(ELEMENT_LINE3)%nelem + n2d = Mesh%ElemTable(ELEMENT_TRI3)%nelem+Mesh%ElemTable(ELEMENT_TRI6)%nelem + & + Mesh%ElemTable(ELEMENT_QUAD4)%nelem+Mesh%ElemTable(ELEMENT_QUAD8)%nelem + n3d = Mesh%ElemTable(ELEMENT_TET4)%nelem+Mesh%ElemTable(ELEMENT_TET10)%nelem + & + Mesh%ElemTable(ELEMENT_HEX8)%nelem+Mesh%ElemTable(ELEMENT_HEX20)%nelem + & + Mesh%ElemTable(ELEMENT_WEDGE6)%nelem+Mesh%ElemTable(ELEMENT_WEDGE15)%nelem + nn = n0d + n1d + n2d + n3d + IF ( max(n0d,n1d,n2d,n3d) .LT. nn ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: mixing elements of different spatial dimensionality" + RETURN ! Early return + ENDIF + + IF ( ALL( Mesh%ElemTable(:)%nelem /= SUM(Mesh%ElemTable(:)%nelem ) ) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: a mesh can have only one type of element." + RETURN ! Early return + ENDIF + + !> Check that every node is part of an element. + NodeInElement = .FALSE. + DO i = 1, NELEMKINDS + DO j = 1, Mesh%ElemTable(i)%nelem + DO n1 = 1,NumNodes( Mesh%ElemTable(i)%XElement ) + n2 = Mesh%ElemTable(i)%Elements(j)%ElemNodes(n1) + NodeInElement( n2 ) = .TRUE. + END DO + END DO + END DO + + ! maybe we should check that the RefOrientation is a DCM? (or at least non-zero?) + + IF ( .NOT. ALL(NodeInElement) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: all nodes must be part of an element." + RETURN ! Early return + END IF + + IF ( .NOT. ANY(Mesh%FieldMask) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: Mesh does not contain any fields." + RETURN + END IF + + + ! make sure the arrays are allocated properly... + IF ( SIZE(Mesh%Position,2) < Mesh%Nnodes) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: Position array smaller than number of nodes." + RETURN ! Early return + ELSEIF ( SIZE(Mesh%Position,2) > Mesh%Nnodes ) THEN + + ! bjj: need to get rid of the extra storage so that this doesn't cause errors in MeshCopy.... + + + END IF + + + + + ! Construct list of elements + + + ! first determine how many elements there are + Mesh%Nelemlist = 0 + DO i = 1, NELEMKINDS + DO j = 1, Mesh%ElemTable(i)%nelem + Mesh%Nelemlist = Mesh%Nelemlist + 1 + END DO + END DO + + Mesh%maxelemlist = Mesh%Nelemlist + ALLOCATE( Mesh%elemlist(Mesh%maxelemlist), STAT=ErrStat ) !Allocates the pointer array + + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshCommit: Error allocating element list." + RETURN + END IF + + NElem = 0 + DO i = 1, NELEMKINDS + DO j = 1, Mesh%ElemTable(i)%nelem + NElem = NElem + 1 + Mesh%elemlist(NElem)%Element => Mesh%ElemTable(i)%Elements(j) + Mesh%elemlist(NElem)%Element%Xelement = i + END DO + END DO + + + ! calculate det_jac: + + DO j=1,Mesh%ElemTable(ELEMENT_POINT)%nelem + Mesh%ElemTable(ELEMENT_POINT)%Elements(J)%det_jac = 0.0_ReKi + END DO + + DO j = 1,Mesh%ElemTable(ELEMENT_LINE2)%nelem + + n2 = Mesh%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes(2) + n1 = Mesh%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes(1) + n1_n2_vector = Mesh%Position(:,n2) & + - Mesh%Position(:,n1) + + Mesh%ElemTable(ELEMENT_LINE2)%Elements(J)%det_jac = 0.5_ReKi * TwoNorm( n1_n2_vector ) ! = L / 2 + + IF ( 2.0_ReKi*Mesh%ElemTable(ELEMENT_LINE2)%Elements(J)%det_jac < MIN_LINE2_ELEMENT_LENGTH ) THEN + ErrStat = ErrID_Fatal + ErrMess = trim(ErrMess)//"MeshCommit: Line2 element "//TRIM(Num2Lstr(j))//" has 0 length."//NewLine// & + " n2 = n("//TRIM(Num2Lstr(n2))//") = ("//TRIM(Num2Lstr(Mesh%Position(1,n2)))//','//TRIM(Num2Lstr(mesh%position(2,n2)))//','//TRIM(Num2Lstr(mesh%position(3,n2))) //')'//NewLine// & + " n1 = n("//TRIM(Num2Lstr(n1))//") = ("//TRIM(Num2Lstr(Mesh%Position(1,n1)))//','//TRIM(Num2Lstr(mesh%position(2,n1)))//','//TRIM(Num2Lstr(mesh%position(3,n1))) //')'//NewLine + RETURN + END IF + + END DO + + + ! we're finished: + + Mesh%Committed = .TRUE. + + END SUBROUTINE MeshCommit + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mesh and an element name, construct a point element whose vertex is the +!! node index listed as the remaining argument of the call to MeshConstructElement. +!! Returns a non-zero ErrStat value on error. + SUBROUTINE MeshConstructElement_1PT( Mesh, Xelement, ErrStat, ErrMess, P1 ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement !< See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + INTEGER, INTENT(IN ) :: P1 !< node index for this point element + + IF ( mesh_debug ) print*,'Called MeshConstructElement_1PT' + ErrStat = ErrID_None + ErrMess = '' + ! Safety first + IF ( .NOT. Mesh%Initialized ) THEN + ErrStat = ErrID_Fatal + ErrMess="MeshConstructElement_1PT: attempt to use uncreated mesh." + ELSEIF ( P1 .LT. 1 .OR. P1 .GT. Mesh%Nnodes ) THEN !BJJ moved to ELSE + ErrStat = ErrID_Fatal + ErrMess="MeshConstructElement_1PT: invalid P1 ("//TRIM(Num2LStr(P1))//") for mesh with "//TRIM(Num2LStr(Mesh%Nnodes))//" nodes." + ELSEIF (Mesh%Committed ) THEN + ErrStat = ErrID_Fatal + ErrMess = " MeshConstructElement_1PT: attempt to add element to committed mesh." + ENDIF + IF ( ErrStat .NE. ErrID_None ) THEN + CALL WrScr(TRIM(ErrMess)) + RETURN ! early return on error + ENDIF + ! Business + IF ( Xelement .EQ. ELEMENT_POINT ) THEN + Mesh%ElemTable(ELEMENT_POINT)%nelem = Mesh%ElemTable(ELEMENT_POINT)%nelem + 1 + Mesh%ElemTable(ELEMENT_POINT)%XElement = ELEMENT_POINT + + CALL BumpupElementTable( Mesh, Xelement, ErrStat, ErrMess ) + IF (ErrStat >= AbortErrLev ) RETURN + + ALLOCATE(Mesh%ElemTable(ELEMENT_POINT)%Elements(Mesh%ElemTable(ELEMENT_POINT)%nelem)%ElemNodes(1),sTAT=ErrStat) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshConstructElement_1PT: Couldn't allocate space for element nodes." + RETURN + END IF + Mesh%ElemTable(ELEMENT_POINT)%Elements(Mesh%ElemTable(ELEMENT_POINT)%nelem)%ElemNodes(1) = P1 + Mesh%ElemTable(ELEMENT_POINT)%Elements(Mesh%ElemTable(ELEMENT_POINT)%nelem)%Xelement = ELEMENT_POINT + ELSE + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_1PT called for invalid element type' + ENDIF + + RETURN + + END SUBROUTINE MeshConstructElement_1PT + +!---------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE BumpupElementTable_New( Mesh, Xelement, ErrStat, ErrMess ) + ! bjj: I am getting weird errors with some models using gfortran (ivf is fine), + ! so I am implementing this method which does not just set a pointer, pointing to + ! a local variable. It actually copies the data twice, but allocates the pointer + ! in the dataype. + + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + + ! Local + TYPE(ElemRecType), ALLOCATABLE :: tmp(:) + INTEGER :: i + + ErrStat = ErrID_None + ErrMess = "" + + + IF ( Mesh%ElemTable(Xelement)%nelem .GE. Mesh%ElemTable(Xelement)%maxelem ) THEN +!write(0,*)'>>>>>>>>>> bumping maxpoint',Mesh%ElemTable(Xelement)%maxelem + + IF (Mesh%ElemTable(Xelement)%maxelem .GT. 0 ) THEN + + ! copy data in pointer to temp copy: + ALLOCATE ( tmp(Mesh%ElemTable(Xelement)%maxelem), STAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "BumpupElementTable: Couldn't allocate space for element table copy." + RETURN + END IF + + DO i=1,Mesh%ElemTable(Xelement)%maxelem + CALL Mesh_MoveAlloc_ElemRecType( Mesh%ElemTable(Xelement)%Elements(i), tmp(i) ) + END DO + + END IF + + ! deallocate the pointer, then reallocate to a larger size: + IF ( ASSOCIATED(Mesh%ElemTable(Xelement)%Elements) ) DEALLOCATE(Mesh%ElemTable(Xelement)%Elements) + + ALLOCATE( Mesh%ElemTable(Xelement)%Elements( Mesh%ElemTable(Xelement)%maxelem + BUMPUP ),STAT=ErrStat ) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "BumpupElementTable: Couldn't allocate space for element table." + IF ( ALLOCATED(tmp) ) DEALLOCATE(tmp) + RETURN + END IF + + ! copy old data to the table pointer: + DO i=1,Mesh%ElemTable(Xelement)%maxelem + CALL Mesh_MoveAlloc_ElemRecType( tmp(i), Mesh%ElemTable(Xelement)%Elements(i) ) + END DO + + IF ( ALLOCATED(tmp) ) DEALLOCATE(tmp) + + ! set the new size of the element table: + Mesh%ElemTable(Xelement)%maxelem = Mesh%ElemTable(Xelement)%maxelem + BUMPUP +!write(0,*)'>>>>>>>>>> bumped maxpoint',Mesh%ElemTable(Xelement)%maxelem + END IF + + END SUBROUTINE BumpupElementTable_New + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine increases the allocated space for Mesh%ElemTable(Xelement)%Elements +!! if adding a new element will exceed the pre-allocated space. + SUBROUTINE BumpupElementTable( Mesh, Xelement, ErrStat, ErrMess ) + + ! bjj: this is the old method of increasing the element table size. + ! it was duplicated in MeshConstructElement_1PT and MeshConstructElement_2PT + ! I have made it a subroutine so we don't have to duplicate it anymore. + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement !< type of element (See Element Names) + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + + ! Local + TYPE(ElemRecType), POINTER :: tmp(:) + INTEGER :: i + + ErrStat = ErrID_None + ErrMess = "" + + IF ( Mesh%ElemTable(Xelement)%nelem .GE. Mesh%ElemTable(Xelement)%maxelem ) THEN +!write(0,*)'>>>>>>>>>> bumping maxline2',Mesh%ElemTable(Xelement)%maxelem + ALLOCATE(tmp(Mesh%ElemTable(Xelement)%maxelem+BUMPUP),Stat=ErrStat) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "BumpupElementTableOld: Couldn't allocate space for element table" + RETURN + END IF + + !IF (Mesh%ElemTable(Xelement)%maxelem .GT. 0 ) & + ! tmp(1:Mesh%ElemTable(Xelement)%maxelem) = Mesh%ElemTable(Xelement)%Elements(1:Mesh%ElemTable(Xelement)%maxelem) + DO i=1,Mesh%ElemTable(Xelement)%maxelem + CALL Mesh_MoveAlloc_ElemRecType( Mesh%ElemTable(Xelement)%Elements(i), tmp(i) ) + END DO + + IF ( ASSOCIATED(Mesh%ElemTable(Xelement)%Elements) ) DEALLOCATE(Mesh%ElemTable(Xelement)%Elements) + Mesh%ElemTable(Xelement)%Elements => tmp + Mesh%ElemTable(Xelement)%maxelem = Mesh%ElemTable(Xelement)%maxelem + BUMPUP +!write(0,*)'>>>>>>>>>> bumped maxline2',Mesh%ElemTable(Xelement)%maxelem + ENDIF + + + END SUBROUTINE BumpupElementTable + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mesh and an element name, construct 2-point line (line2) element whose +!! vertices are the node indices listed as the remaining arguments of the call to +!! MeshConstructElement. The adjacency of elements is implied when elements are +!! created that share some of the same nodes. Returns a non-zero value on error. + SUBROUTINE MeshConstructElement_2PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2 ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement !< See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + INTEGER, INTENT(IN ) :: P1 !< 1 of 2 points that make a 2-point line element + INTEGER, INTENT(IN ) :: P2 !< 1 of 2 points that make a 2-point line element + + IF ( mesh_debug ) print*,'Called MeshConstructElement_2PT' + ErrStat = ErrID_None + ErrMess = "" + ! Safety first + IF ( .NOT. Mesh%Initialized ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshConstructElement_2PT: attempt to use uncreated mesh." + ELSEIF ( P1 .LT. 1 .OR. P1 .GT. Mesh%Nnodes .OR. & + P2 .LT. 1 .OR. P2 .GT. Mesh%Nnodes ) THEN + ErrStat = ErrID_Fatal + ErrMess ="MeshConstructElement_2PT: invalid P1 ("//TRIM(Num2LStr(P1))//") or P2 ("//TRIM(Num2LStr(P2))//& + ") for mesh with "//TRIM(Num2LStr(Mesh%Nnodes))//" nodes." + ELSEIF (Mesh%Committed ) THEN + ErrStat = ErrID_Fatal + ErrMess = " MeshConstructElement_2PT: attempt to add element to committed mesh." + ENDIF +! TODO: hook the element into a list of elements stored in this mesh to +! allow traversal over elements + IF ( ErrStat .NE. ErrID_None ) THEN + CALL WrScr( TRIM(ErrMess) ) + RETURN ! early return on error + ENDIF + ! Business + IF ( Xelement .EQ. ELEMENT_LINE2 ) THEN + Mesh%ElemTable(ELEMENT_LINE2)%nelem = Mesh%ElemTable(ELEMENT_LINE2)%nelem + 1 + Mesh%ElemTable(ELEMENT_LINE2)%XElement = ELEMENT_LINE2 + + CALL BumpupElementTable( Mesh, Xelement, ErrStat, ErrMess ) + IF (ErrStat >= AbortErrLev) RETURN + + ALLOCATE(Mesh%ElemTable(ELEMENT_LINE2)%Elements(Mesh%ElemTable(ELEMENT_LINE2)%nelem)%ElemNodes(2),Stat=ErrStat) + IF (ErrStat /= 0) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshConstructElement_2PT: Couldn't allocate space for element nodes." + RETURN + END IF + Mesh%ElemTable(ELEMENT_LINE2)%Elements(Mesh%ElemTable(ELEMENT_LINE2)%nelem)%ElemNodes(1) = P1 + Mesh%ElemTable(ELEMENT_LINE2)%Elements(Mesh%ElemTable(ELEMENT_LINE2)%nelem)%ElemNodes(2) = P2 + Mesh%ElemTable(ELEMENT_LINE2)%Elements(Mesh%ElemTable(ELEMENT_LINE2)%nelem)%Xelement = ELEMENT_LINE2 + + ELSE + ErrMess = 'MeshConstructElement_2PT called for invalid element type' + ErrStat = ErrID_Fatal + ENDIF + RETURN + END SUBROUTINE MeshConstructElement_2PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_3PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3 + IF ( mesh_debug ) print*,'Called MeshConstructElement_3PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_3PT not supported' + END SUBROUTINE MeshConstructElement_3PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_4PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4 + IF ( mesh_debug ) print*,'Called MeshConstructElement_4PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_4PT not supported' + END SUBROUTINE MeshConstructElement_4PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_6PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4, P5, P6 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4, P5, P6 + IF ( mesh_debug ) print*,'Called MeshConstructElement_6PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_6PT not supported' + END SUBROUTINE MeshConstructElement_6PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_8PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4, P5, P6, P7, P8 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4, P5, P6, P7, P8 + IF ( mesh_debug ) print*,'Called MeshConstructElement_8PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_8PT not supported' + END SUBROUTINE MeshConstructElement_8PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_10PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10 + IF ( mesh_debug ) print*,'Called MeshConstructElement_10PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_10PT not supported' + END SUBROUTINE MeshConstructElement_10PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_15PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10, & + P11, P12, P13, P14, P15 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10, & + P11, P12, P13, P14, P15 + IF ( mesh_debug ) print*,'Called MeshConstructElement_15PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_15PT not supported' + END SUBROUTINE MeshConstructElement_15PT + +!---------------------------------------------------------------------------------------------------------------------------------- +!> added 20130102 as stub for AeroDyn work + SUBROUTINE MeshConstructElement_20PT( Mesh, Xelement, ErrStat, ErrMess, P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10, & + P11, P12, P13, P14, P15, & + P16, P17, P18, P19, P20 ) + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement ! See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER, INTENT(IN ) :: P1, P2, P3, P4, P5, & + P6, P7, P8, P9, P10, & + P11, P12, P13, P14, P15, & + P16, P17, P18, P19, P20 + IF ( mesh_debug ) print*,'Called MeshConstructElement_20PT' + ErrStat = ErrID_None + ErrMess = '' + ErrStat = ErrID_Fatal + ErrMess = 'MeshConstructElement_20PT not supported' + END SUBROUTINE MeshConstructElement_20PT + +!................................................................ +!> This routine splits a line2 element into two separate elements, using p1 as +!! the new node connecting the two new elements formed from E1. + SUBROUTINE MeshSplitElement_2PT( Mesh, Xelement, ErrStat, ErrMess, E1, P1 ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh !< Mesh being constructed + INTEGER(IntKi), INTENT(IN) :: Xelement !< See Element Names + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error code + CHARACTER(*), INTENT(OUT) :: ErrMess !< Error message + INTEGER, INTENT(IN ) :: E1 !< number of element in Element Table + INTEGER, INTENT(IN ) :: P1 !< node number + + INTEGER :: p2 ! local copy of P2, in case we end up deallocating the array pointed to in the call to construct a new element + + IF ( mesh_debug ) print*,'Called MeshSplitElement_2PT' + ErrStat = ErrID_None + ErrMess = "" + + ! Safety first + IF ( Xelement .NE. ELEMENT_LINE2 ) THEN + ErrMess = 'MeshSplitElement_2PT called for invalid element type.' + ErrStat = ErrID_Fatal + ELSEIF ( .NOT. Mesh%Initialized ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshSplitElement_2PT: attempt to use uncreated mesh." + ELSEIF ( P1 .LT. 1 .OR. P1 .GT. Mesh%Nnodes ) THEN + ErrStat = ErrID_Fatal + ErrMess ="MeshSplitElement_2PT: invalid P1 ("//TRIM(Num2LStr(P1))//") for mesh with "//TRIM(Num2LStr(Mesh%Nnodes))//" nodes." + ELSEIF ( E1 .LT. 1 .OR. E1 .GT. Mesh%ElemTable(ELEMENT_LINE2)%nelem ) THEN + ErrStat = ErrID_Fatal + ErrMess ="MeshSplitElement_2PT: invalid E1 ("//TRIM(Num2LStr(E1))//") for mesh with "//TRIM(Num2LStr(Mesh%ElemTable(ELEMENT_LINE2)%nelem))//" Line2 elements." + ELSEIF (Mesh%Committed ) THEN + ErrStat = ErrID_Fatal + ErrMess = " MeshSplitElement_2PT: attempt to add element to committed mesh." + ELSEIF ( Mesh%ElemTable(ELEMENT_LINE2)%Elements(E1)%ElemNodes(1) == P1 .OR. & + Mesh%ElemTable(ELEMENT_LINE2)%Elements(E1)%ElemNodes(2) == P1 ) THEN + ErrStat = ErrID_Fatal + ErrMess ="MeshSplitElement_2PT: node P1 ("//TRIM(Num2LStr(P1))//") is already a node of element E1 ("//TRIM(Num2LStr(E1))//")." + ENDIF + + IF ( ErrStat .NE. ErrID_None ) THEN + !CALL WrScr( TRIM(ErrMess) ) + RETURN ! early return on fatal error + ENDIF + + + ! Business + ! E1 currently has nodes (n1,n2): + ! Create a new element with nodes (p1,n2): + p2 = Mesh%ElemTable(ELEMENT_LINE2)%Elements(E1)%ElemNodes(2) + CALL MeshConstructElement( Mesh, Xelement, ErrStat, ErrMess, p1=P1, p2=p2) + + ! Make element E1 now have nodes (n1,p1): + Mesh%ElemTable(ELEMENT_LINE2)%Elements(E1)%ElemNodes(2) = P1 + + RETURN + + END SUBROUTINE MeshSplitElement_2PT +!................................................................ + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a control code and a mesh that has been committed, retrieve the next element in the mesh. +!! Used to traverse mesh element by element. On entry, the CtrlCode argument contains a control code: +!! zero indicates start from the beginning, an integer between 1 and Mesh%Nelemlist returns that element, +!! and MESH_NEXT means return the next element in traversal. On exit, CtrlCode contains the status of the +!! traversal in (zero or MESH_NOMOREELEMS). The routine optionally outputs the index of the element in the +!! mesh's element list, the name of the element (see "Element Names"), and a pointer to the element. + SUBROUTINE MeshNextElement ( Mesh, CtrlCode, ErrStat, ErrMess, Ielement, Xelement, ElemRec ) + + TYPE(MeshType), INTENT(INOUT) :: Mesh ! Mesh being constructed + INTEGER(IntKi), INTENT(INOUT) :: CtrlCode ! CtrlCode + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error code + CHARACTER(*), INTENT(OUT) :: ErrMess ! Error message + INTEGER(IntKi),OPTIONAL, INTENT(OUT) :: Ielement ! Element index + INTEGER(IntKi),OPTIONAL, INTENT(OUT) :: Xelement ! Element identifier + TYPE(ElemRecType),POINTER,OPTIONAL,INTENT(INOUT) :: ElemRec ! Return array of elements of kind Xelement + + + ErrStat = ErrID_None + ErrMess = "" + + IF (.not. Mesh%Committed) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshNextElement: Uncommitted mesh." + RETURN ! Early Return + ENDIF + + IF ( .NOT. CtrlCode .EQ. MESH_NEXT .AND. (CtrlCode .LT. 0 .OR. CtrlCode .GT. Mesh%nelemlist) ) THEN + ErrStat = ErrID_Fatal + ErrMess = "MeshNextElement: Invalid CtrlCode" + RETURN ! Early Return + ENDIF + IF ( CtrlCode .EQ. 0 ) THEN ! 0 means start traversal from beginning + Mesh%nextelem = 1 + ELSE IF ( CtrlCode .NE. MESH_NEXT ) THEN ! Use the index provided in CtrlCode + Mesh%nextelem = CtrlCode + ENDIF + CtrlCode = 0 + IF ( Mesh%nextelem .GT. Mesh%nelemlist ) THEN + CtrlCode = MESH_NOMOREELEMS + RETURN ! Early Return + ENDIF + IF ( PRESENT(Ielement) ) Ielement = Mesh%nextelem + IF ( PRESENT(ElemRec) ) ElemRec => Mesh%elemlist(Mesh%nextelem)%Element + IF ( PRESENT(Xelement) ) Xelement = Mesh%elemlist(Mesh%nextelem)%Element%Xelement + Mesh%nextelem = Mesh%nextelem + 1 !bjj should we put this in a modulo statement? (i.e, if we go past the end, nextelem = 1) + RETURN + + END SUBROUTINE MeshNextElement + +!............................................................................................................................... +!> This subroutine returns the names of the output rows/columns in the Jacobian matrices. It assumes both force and moment +!! fields are allocated. + SUBROUTINE PackLoadMesh_Names(M, MeshName, Names, indx_first) + + TYPE(MeshType) , INTENT(IN ) :: M !< Load mesh + CHARACTER(*) , INTENT(IN ) :: MeshName !< name of mesh + CHARACTER(LinChanLen) , INTENT(INOUT) :: Names(:) !< name of row/column of jacobian + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into Names array; gives location of next array position to fill + + ! local variables: + INTEGER(IntKi) :: i, j + character(1), parameter :: Comp(3) = (/'X','Y','Z'/) + character(2) :: UnitDesc + + + UnitDesc = '' + if (M%Committed) then + if (M%ElemTable(ELEMENT_LINE2)%nelem > 0) UnitDesc = '/m' + end if + + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' force, node '//trim(num2lstr(i))//', N'//UnitDesc + indx_first = indx_first + 1 + end do + end do + ! This is needed for MAP meshes because it only contains the Force field not the Moment field + if ( M%fieldmask(MASKID_Moment) .AND. ALLOCATED(M%Moment)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' moment, node '//trim(num2lstr(i))//', Nm'//UnitDesc + indx_first = indx_first + 1 + end do + end do + end if + + END SUBROUTINE PackLoadMesh_Names +!............................................................................................................................... +!> This subroutine returns the operating point values of the mesh fields. It assumes both force and moment +!! fields are allocated. + SUBROUTINE PackLoadMesh(M, Ary, indx_first) + + TYPE(MeshType) , INTENT(IN ) :: M !< Load mesh + REAL(ReKi) , INTENT(INOUT) :: Ary(:) !< array to pack this mesh into + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into Ary; gives location of next array position to fill + + ! local variables: + INTEGER(IntKi) :: i, j + + + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%Force(j,i) + indx_first = indx_first + 1 + end do + end do + + ! This is needed for MAP meshes because it only contains the Force field not the Moment field + if ( M%fieldmask(MASKID_Moment) .AND. ALLOCATED(M%Moment)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%Moment(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + END SUBROUTINE PackLoadMesh +!............................................................................................................................... +!> This subroutine computes the differences of two meshes and packs that value into appropriate locations in the dY array. +!! Do not change this packing without making sure subroutine aerodyn::init_jacobian is consistant with this routine! + SUBROUTINE PackLoadMesh_dY(M_p, M_m, dY, indx_first) + + TYPE(MeshType) , INTENT(IN ) :: M_p !< AD outputs on given mesh at \f$ u + \Delta u \f$ (p=plus) + TYPE(MeshType) , INTENT(IN ) :: M_m !< AD outputs on given mesh at \f$ u - \Delta u \f$ (m=minus) + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdz \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into dY array; gives location of next array position to fill + + ! local variables: + INTEGER(IntKi) :: i, indx_last + + + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%Force(:,i) - M_m%Force(:,i) + indx_first = indx_last + 1 + end do + + ! This is needed for MAP meshes because it only contains the Force field not the Moment field + if ( M_p%fieldmask(MASKID_Moment) .AND. ALLOCATED(M_p%Moment)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%Moment(:,i) - M_m%Moment(:,i) + indx_first = indx_last + 1 + end do + end if + + END SUBROUTINE PackLoadMesh_dY +!............................................................................................................................... +!> This subroutine returns the names of rows/columns of motion meshes in the Jacobian matrices. It assumes all fields marked +!! by FieldMask are allocated; Some fields may be allocated by the ModMesh module and not used in +!! the linearization procedure, thus I am not using the check if they are allocated to determine if they should be included. +!............................................................................................................................... + SUBROUTINE PackMotionMesh_Names(M, MeshName, Names, indx_first, FieldMask) + + TYPE(MeshType) , INTENT(IN ) :: M !< Motion mesh + CHARACTER(*) , INTENT(IN ) :: MeshName !< name of mesh + CHARACTER(LinChanLen) , INTENT(INOUT) :: Names(:) !< name of row/column of jacobian + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into Names array; gives location of next array position to fill + LOGICAL, OPTIONAL , INTENT(IN ) :: FieldMask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + + ! local variables: + INTEGER(IntKi) :: i, j + character(1), parameter :: Comp(3) = (/'X','Y','Z'/) + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + if (present(FieldMask)) then + Mask = FieldMask + else + Mask = .true. + end if + + + if (Mask(MASKID_TRANSLATIONDISP)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' translation displacement, node '//trim(num2lstr(i))//', m' + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ORIENTATION)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' orientation angle, node '//trim(num2lstr(i))//', rad' + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_TRANSLATIONVEL)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' translation velocity, node '//trim(num2lstr(i))//', m/s' + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ROTATIONVEL)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' rotation velocity, node '//trim(num2lstr(i))//', rad/s' + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_TRANSLATIONACC)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' translation acceleration, node '//trim(num2lstr(i))//', m/s^2' + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ROTATIONACC)) then + do i=1,M%NNodes + do j=1,3 + Names(indx_first) = trim(MeshName)//' '//Comp(j)//' rotation acceleration, node '//trim(num2lstr(i))//', rad/s^2' + indx_first = indx_first + 1 + end do + end do + end if + + + END SUBROUTINE PackMotionMesh_Names +!> This subroutine returns the operating point values of the mesh fields. It assumes all fields marked +!! by FieldMask are allocated; Some fields may be allocated by the ModMesh module and not used in +!! the linearization procedure, thus I am not using the check if they are allocated to determine if they should be included. + SUBROUTINE PackMotionMesh(M, Ary, indx_first, FieldMask, UseLogMaps) + + TYPE(MeshType) , INTENT(IN ) :: M !< Motion mesh + REAL(ReKi) , INTENT(INOUT) :: Ary(:) !< array to pack this mesh into + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into Ary; gives location of next array position to fill + LOGICAL, OPTIONAL , INTENT(IN ) :: FieldMask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + LOGICAL, OPTIONAL , INTENT(IN ) :: UseLogMaps !< flag to determine if the orientation should be packed as a DCM or a log map + + + ! local variables: + INTEGER(IntKi) :: i, j, k + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + LOGICAL :: OutputLogMap + REAL(R8Ki) :: logmap(3) !< array to pack logmaps into + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + if (present(FieldMask)) then + Mask = FieldMask + else + Mask = .true. + end if + + + if (Mask(MASKID_TRANSLATIONDISP)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%TranslationDisp(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ORIENTATION)) then + if (present(UseLogMaps)) then + OutputLogMap = UseLogMaps + else + OutputLogMap = .false. + end if + + if (OutputLogMap) then + do i=1,M%NNodes + call DCM_logMap(M%Orientation(:,:,i), logmap, ErrStat2, ErrMsg2) + do k=1,3 + Ary(indx_first) = logmap(k) + indx_first = indx_first + 1 + end do + end do + else + do i=1,M%NNodes + do j=1,3 + do k=1,3 ! note this gives us 9 values instead of 3 for this "operating point" + Ary(indx_first) = M%Orientation(j,k,i) + indx_first = indx_first + 1 + end do + end do + end do + end if + end if + + if (Mask(MASKID_TRANSLATIONVEL)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%TranslationVel(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ROTATIONVEL)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%RotationVel(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_TRANSLATIONACC)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%TranslationAcc(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + if (Mask(MASKID_ROTATIONACC)) then + do i=1,M%NNodes + do j=1,3 + Ary(indx_first) = M%RotationAcc(j,i) + indx_first = indx_first + 1 + end do + end do + end if + + + END SUBROUTINE PackMotionMesh +!............................................................................................................................... +!> This subroutine computes the differences of two meshes and packs that value into appropriate locations in the dY array. + SUBROUTINE PackMotionMesh_dY(M_p, M_m, dY, indx_first, FieldMask) + + TYPE(MeshType) , INTENT(IN ) :: M_p !< ED outputs on given mesh at \f$ u + \Delta u \f$ (p=plus) + TYPE(MeshType) , INTENT(IN ) :: M_m !< ED outputs on given mesh at \f$ u - \Delta u \f$ (m=minus) + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ + INTEGER(IntKi) , INTENT(INOUT) :: indx_first !< index into dY array; gives location of next array position to fill + LOGICAL, OPTIONAL , INTENT(IN ) :: FieldMask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + ! local variables: + INTEGER(IntKi) :: ErrStat2 ! we're ignoring the errors about small angles + CHARACTER(ErrMsgLen) :: ErrMsg2 + + INTEGER(IntKi) :: i, indx_last + REAL(R8Ki) :: lambda_m(3) + REAL(R8Ki) :: lambda_p(3) + REAL(R8Ki) :: smallAngles(3) + LOGICAL :: Mask(FIELDMASK_SIZE) !< flags to determine if this field is part of the packing + + if (present(FieldMask)) then + Mask = FieldMask + else + Mask = .true. + end if + + + if (Mask(MASKID_TRANSLATIONDISP)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%TranslationDisp(:,i) - M_m%TranslationDisp(:,i) + indx_first = indx_last + 1 + end do + end if + + if (Mask(MASKID_ORIENTATION)) then + do i=1,M_p%NNodes + call DCM_logMap( M_m%Orientation(:,:,i), lambda_m, ErrStat2, ErrMsg2 ) + call DCM_logMap( M_p%Orientation(:,:,i), lambda_p, ErrStat2, ErrMsg2 ) + + smallAngles = lambda_p - lambda_m + + indx_last = indx_first + 2 + dY(indx_first:indx_last) = smallAngles + indx_first = indx_last + 1 + end do + end if + + if (Mask(MASKID_TRANSLATIONVEL)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%TranslationVel(:,i) - M_m%TranslationVel(:,i) + indx_first = indx_last + 1 + end do + end if + + if (Mask(MASKID_ROTATIONVEL)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%RotationVel(:,i) - M_m%RotationVel(:,i) + indx_first = indx_last + 1 + end do + end if + + if (Mask(MASKID_TRANSLATIONACC)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%TranslationAcc(:,i) - M_m%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + end if + + if (Mask(MASKID_ROTATIONACC)) then + do i=1,M_p%NNodes + indx_last = indx_first + 2 + dY(indx_first:indx_last) = M_p%RotationAcc(:,i) - M_m%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + end if + + + END SUBROUTINE PackMotionMesh_dY + +!............................................................................................................................... +!> This subroutine calculates a extrapolated (or interpolated) input u_out at time t_out, from previous/future time +!! values of u (which has values associated with times in t). Order of the interpolation is 1. + SUBROUTINE MeshExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN) :: u1 !< Inputs at t1 > t2 + TYPE(MeshType), INTENT(IN) :: u2 !< Inputs at t2 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + TYPE(MeshType), INTENT(INOUT) :: u_out !< Inputs at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(DbKi) :: tensor(3, order+1) ! for extrapolation of orientations + REAL(DbKi) :: tensor_interp(3) ! for extrapolation of orientations + REAL(DbKi) :: Orient(3,3) ! for extrapolation of orientations + + INTEGER(IntKi) :: node ! node counter + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! some error checking: + + if ( size(t) .ne. order+1) then + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp1: size(t) must equal 2.' + RETURN + end if + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + RETURN + END IF + + ! now let's interpolate/extrapolate the fields: + scaleFactor = t_out / t(2) + + IF ( ALLOCATED(u1%Force) ) THEN + u_out%Force = u1%Force + (u2%Force - u1%Force) * scaleFactor + END IF + + IF ( ALLOCATED(u1%Moment) ) THEN + u_out%Moment = u1%Moment + (u2%Moment - u1%Moment) * scaleFactor + END IF + + IF ( ALLOCATED(u1%TranslationDisp) ) THEN + u_out%TranslationDisp = u1%TranslationDisp + (u2%TranslationDisp - u1%TranslationDisp) * scaleFactor + END IF + + IF ( ALLOCATED(u1%RotationVel) ) THEN + u_out%RotationVel = u1%RotationVel + (u2%RotationVel - u1%RotationVel) * scaleFactor + END IF + + IF ( ALLOCATED(u1%TranslationVel) ) THEN + u_out%TranslationVel = u1%TranslationVel + (u2%TranslationVel - u1%TranslationVel) * scaleFactor + END IF + + IF ( ALLOCATED(u1%RotationAcc) ) THEN + u_out%RotationAcc = u1%RotationAcc + (u2%RotationAcc - u1%RotationAcc) * scaleFactor + END IF + + IF ( ALLOCATED(u1%TranslationAcc) ) THEN + u_out%TranslationAcc = u1%TranslationAcc + (u2%TranslationAcc - u1%TranslationAcc) * scaleFactor + END IF + + IF ( ALLOCATED(u1%Scalars) ) THEN + u_out%Scalars = u1%Scalars + (u2%Scalars - u1%Scalars) * scaleFactor + END IF + + IF ( ALLOCATED(u1%Orientation) ) THEN + + if ( EqualRealNos(t_out, t(1)) ) then + u_out%Orientation = u1%Orientation + elseif ( EqualRealNos(t_out, t(2)) ) then + u_out%Orientation = u2%Orientation + else + + DO node=1,u_out%Nnodes + + Orient = u1%Orientation(:,:,node) + CALL DCM_logmap ( Orient, tensor(:,1), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) THEN + ErrMsg = 'MeshExtrapInterp1:'//TRIM(ErrMsg) + RETURN + END IF + + Orient = u2%Orientation(:,:,node) + CALL DCM_logmap ( Orient, tensor(:,2), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) THEN + ErrMsg = 'MeshExtrapInterp1:'//TRIM(ErrMsg) + RETURN + END IF + + CALL DCM_SetLogMapForInterp( tensor ) + + tensor_interp = tensor(:,1) + (tensor(:,2) - tensor(:,1)) * scaleFactor + + u_out%Orientation(:,:,node) = DCM_exp( tensor_interp ) + + END DO + + end if + + END IF + + END SUBROUTINE MeshExtrapInterp1 + +!............................................................................................................................... +!> This subroutine calculates a extrapolated (or interpolated) input u_out at time t_out, from previous/future time +!! values of u (which has values associated with times in t). Order of the interpolation is 2. + SUBROUTINE MeshExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN) :: u1 !< Inputs at t1 > t2 > t3 + TYPE(MeshType), INTENT(IN) :: u2 !< Inputs at t2 > t3 + TYPE(MeshType), INTENT(IN) :: u3 !< Inputs at t3 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + TYPE(MeshType), INTENT(INOUT) :: u_out !< Inputs at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(DbKi) :: tensor(3, order+1) ! for extrapolation of orientations + REAL(DbKi) :: tensor_interp(3) ! for extrapolation of orientations + REAL(DbKi) :: Orient(3,3) ! for extrapolation of orientations + + INTEGER(IntKi) :: node ! node counter + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + +!bjj: TODO check that we've initialized the mesh + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + + ! Some error checking: + + if ( size(t) .ne. order+1) then + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp2: size(t) must equal 3.' + RETURN + end if + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + RETURN + END IF + IF ( EqualRealNos( t(2), t(3) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + RETURN + END IF + IF ( EqualRealNos( t(1), t(3) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'MeshExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + RETURN + END IF + + ! Now let's interpolate/extrapolate: + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + IF ( ALLOCATED(u1%Force) ) THEN + + u_out%Force = u1%Force & + + ( t(3)**2 * (u1%Force - u2%Force) + t(2)**2*(-u1%Force + u3%Force) ) * scaleFactor & + + ( (t(2)-t(3))*u1%Force + t(3)*u2%Force - t(2)*u3%Force ) *scaleFactor * t_out + + END IF + IF ( ALLOCATED(u1%Moment) ) THEN + u_out%Moment = u1%Moment & + + ( t(3)**2 * (u1%Moment - u2%Moment) + t(2)**2*(-u1%Moment + u3%Moment) ) * scaleFactor & + + ( (t(2)-t(3))*u1%Moment + t(3)*u2%Moment - t(2)*u3%Moment ) *scaleFactor * t_out + END IF + + IF ( ALLOCATED(u1%TranslationDisp) ) THEN + u_out%TranslationDisp = u1%TranslationDisp & + + ( t(3)**2 * ( u1%TranslationDisp - u2%TranslationDisp) & + + t(2)**2 * (-u1%TranslationDisp + u3%TranslationDisp) ) * scaleFactor & + + ( (t(2)-t(3))*u1%TranslationDisp + t(3)*u2%TranslationDisp & + - t(2)*u3%TranslationDisp )*scaleFactor*t_out + END IF + + IF ( ALLOCATED(u1%RotationVel) ) THEN + u_out%RotationVel = u1%RotationVel & + + ( t(3)**2 * ( u1%RotationVel - u2%RotationVel) & + + t(2)**2 * (-u1%RotationVel + u3%RotationVel) ) * scaleFactor & + + ( (t(2)-t(3))*u1%RotationVel + t(3)*u2%RotationVel - t(2)*u3%RotationVel )*scaleFactor*t_out + END IF + + IF ( ALLOCATED(u1%TranslationVel) ) THEN + u_out%TranslationVel = u1%TranslationVel & + +( t(3)**2 * ( u1%TranslationVel - u2%TranslationVel) & + + t(2)**2 * (-u1%TranslationVel + u3%TranslationVel) ) * scaleFactor & + +( (t(2)-t(3))*u1%TranslationVel + t(3)*u2%TranslationVel - t(2)*u3%TranslationVel)*scaleFactor*t_out + END IF + + IF ( ALLOCATED(u1%RotationAcc) ) THEN + u_out%RotationAcc = u1%RotationAcc & + + ( t(3)**2 * ( u1%RotationAcc - u2%RotationAcc) & + + t(2)**2 * (-u1%RotationAcc + u3%RotationAcc) ) * scaleFactor & + + ( (t(2)-t(3))*u1%RotationAcc + t(3)*u2%RotationAcc - t(2)*u3%RotationAcc )*scaleFactor*t_out + END IF + + IF ( ALLOCATED(u1%TranslationAcc) ) THEN + u_out%TranslationAcc = u1%TranslationAcc & + +( t(3)**2 * ( u1%TranslationAcc - u2%TranslationAcc) & + + t(2)**2 * (-u1%TranslationAcc + u3%TranslationAcc) ) * scaleFactor & + +( (t(2)-t(3))*u1%TranslationAcc + t(3)*u2%TranslationAcc - t(2)*u3%TranslationAcc)*scaleFactor*t_out + END IF + + IF ( ALLOCATED(u1%Scalars) ) THEN + u_out%Scalars = u1%Scalars & + + ( t(3)**2 * (u1%Scalars - u2%Scalars) + t(2)**2*(-u1%Scalars + u3%Scalars) )*scaleFactor & + + ( (t(2)-t(3))*u1%Scalars + t(3)*u2%Scalars - t(2)*u3%Scalars )*scaleFactor * t_out + END IF + + IF ( ALLOCATED(u1%Orientation) ) THEN + + if ( EqualRealNos(t_out, t(1)) ) then + u_out%Orientation = u1%Orientation + elseif ( EqualRealNos(t_out, t(2)) ) then + u_out%Orientation = u2%Orientation + elseif ( EqualRealNos(t_out, t(3)) ) then + u_out%Orientation = u3%Orientation + else + DO node=1,u_out%Nnodes + + Orient = u1%Orientation(:,:,node) + CALL DCM_logmap ( Orient, tensor(:,1), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) THEN + ErrMsg = 'MeshExtrapInterp2:'//TRIM(ErrMsg) + RETURN + END IF + + Orient = u2%Orientation(:,:,node) + CALL DCM_logmap ( Orient, tensor(:,2), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) THEN + ErrMsg = 'MeshExtrapInterp2:'//TRIM(ErrMsg) + RETURN + END IF + + Orient = u3%Orientation(:,:,node) + CALL DCM_logmap ( Orient, tensor(:,3), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev ) THEN + ErrMsg = 'MeshExtrapInterp2:'//TRIM(ErrMsg) + RETURN + END IF + + CALL DCM_SetLogMapForInterp( tensor ) + + tensor_interp = tensor(:,1) & + + ( t(3)**2 * (tensor(:,1) - tensor(:,2)) + t(2)**2*(-tensor(:,1) + tensor(:,3)) )*scaleFactor & + + ( (t(2)-t(3))*tensor(:,1) + t(3)*tensor(:,2) - t(2)*tensor(:,3) )*scaleFactor * t_out + u_out%Orientation(:,:,node) = DCM_exp( tensor_interp ) + + END DO + end if + + + END IF + + END SUBROUTINE MeshExtrapInterp2 + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE ModMesh + + diff --git a/OpenFAST/modules/nwtc-library/src/ModMesh_Mapping.f90 b/OpenFAST/modules/nwtc-library/src/ModMesh_Mapping.f90 new file mode 100644 index 000000000..6a56316bc --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/ModMesh_Mapping.f90 @@ -0,0 +1,7920 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +!********************************************************************************************************************************** +!> This code implements the spatial mapping algorithms described in the following papers +!! - Sprague, Michael A.; Jonkman, Jason M.; and Jonkman, Bonnie J., "FAST Modular Framework for Wind Turbine Simulation: New +!! Algorithms and Numerical Examples." Proceedings of the 53rd Aerospace Sciences Meeting, 2015, also published in tech report +!! NREL/CP-2C00-63203, National Renewable Energy Laboratory, Golden, CO. http://www.nrel.gov/docs/fy16osti/63203.pdf +!! - Jonkman, Jason M. and Jonkman, Bonnie J., "FAST Modular Framework for Wind Turbine Simulation: +!! Full-System Linearization.", J. Phys.: Conf. Ser. 753 082010, also published in tech report +!! NREL/CP-5000-67015, National Renewable Energy Laboratory, Golden, CO. http://www.nrel.gov/docs/fy17osti/67015.pdf + +!********************************************************************************************************************************** +MODULE ModMesh_Mapping + + USE ModMesh + USE NWTC_LAPACK + + IMPLICIT NONE + + PRIVATE + + !bjj: these types require the use of ModMesh.f90, thus they cannot be part of NWTC_Library_Types.f90 (though they are auto_generated with that code): + + !> Type that describes characteristics of the mapping between two meshes + TYPE, PUBLIC :: MapType + INTEGER(IntKi) :: OtherMesh_Element !< Node (for point meshes) or Element (for line2 meshes) number on other mesh; for loads, other mesh is Dest, for motions/scalars, other mesh is Src + REAL(R8Ki) :: distance !< magnitude of couple_arm + REAL(R8Ki) :: couple_arm(3) !< Vector between a point and node 1 of an element (p_ODR - p_OSR) + REAL(R8Ki) :: shape_fn(2) !< shape functions: 1-D element-level location [0,1] based on closest-line projection of point + END TYPE MapType + + !> data structures (for linearization) containing jacobians of mapping between fields on different meshes + TYPE, PUBLIC :: MeshMapLinearizationType + ! values for motions: + REAL(R8Ki), ALLOCATABLE :: mi(:,:) !< block matrix of motions that reflects identity (i.e., solely the mapping of one quantity to itself on another mesh) [-] + REAL(R8Ki), ALLOCATABLE :: fx_p(:,:) !< block matrix of motions that reflects skew-symmetric (cross-product) matrix [-] + REAL(R8Ki), ALLOCATABLE :: tv_uD(:,:) !< block matrix of translational velocity that is multiplied by destination translational displacement [-] + REAL(R8Ki), ALLOCATABLE :: tv_uS(:,:) !< block matrix of translational velocity that is multiplied by source translational displacement [-] + REAL(R8Ki), ALLOCATABLE :: ta_uD(:,:) !< block matrix of translational acceleration that is multiplied by destination translational displacement [-] + REAL(R8Ki), ALLOCATABLE :: ta_uS(:,:) !< block matrix of translational acceleration that is multiplied by source translational displacement [-] + REAL(R8Ki), ALLOCATABLE :: ta_rv(:,:) !< block matrix of translational acceleration that is multiplied by omega (RotationVel) [-] + ! values for loads: + REAL(R8Ki), ALLOCATABLE :: li(:,:) !< block matrix of loads that reflects identity (i.e., solely the mapping on one quantity to itself on another mesh) [-] + REAL(R8Ki), ALLOCATABLE :: M_uS(:,:) !< block matrix of moment that is multiplied by Source u (translationDisp) [-] + REAL(R8Ki), ALLOCATABLE :: M_uD(:,:) !< block matrix of moment that is multiplied by Destination u (translationDisp) [-] + REAL(R8Ki), ALLOCATABLE :: M_f(:,:) !< block matrix of moment that is multiplied by force [-] + END TYPE MeshMapLinearizationType + + + !> data structures to determine full mapping between fields on different meshes + TYPE, PUBLIC :: MeshMapType + TYPE(MapType), ALLOCATABLE :: MapLoads(:) !< mapping data structure for loads on the mesh + TYPE(MapType), ALLOCATABLE :: MapMotions(:) !< mapping data structure for motions and/or scalars on the mesh [-] + TYPE(MapType), ALLOCATABLE :: MapSrcToAugmt(:) !< for source line2 loads, we map between source and an augmented source mesh, then between augmented source and destination + TYPE(MeshType) :: Augmented_Ln2_Src !< the augmented source mesh needed for some mapping types + TYPE(MeshType) :: Lumped_Points_Src !< a lumped mesh needed for some mapping types, stored here for efficiency +#ifdef MESH_DEBUG + TYPE(MeshType) :: Lumped_Points_Dest +#endif + INTEGER, ALLOCATABLE :: LoadLn2_A_Mat_Piv(:) !< The pivot values for the factorization of LoadLn2_A_Mat + REAL(R8Ki), ALLOCATABLE :: DisplacedPosition(:,:,:) !< couple_arm +Scr%Disp - Dest%Disp for each mapped node (stored here for efficiency) + REAL(R8Ki), ALLOCATABLE :: LoadLn2_A_Mat(:,:) !< The n-by-n (n=3xNNodes) matrix that makes up the diagonal of the [A 0; B A] matrix in the point-to-line load mapping + REAL(R8Ki), ALLOCATABLE :: LoadLn2_F(:,:) !< The 3-components of the forces for each node of an element in the point-to-line load mapping (for each element) + REAL(R8Ki), ALLOCATABLE :: LoadLn2_M(:,:) !< The 3-components of the moments for each node of an element in the point-to-line load mapping (for each element) + + TYPE(MeshMapLinearizationType) :: dM !< type that contains information for linearization matrices, partial M partial u (or y) + END TYPE MeshMapType + + ! note that these parameters must be negative (positive indicates the node/element it is mapped to) + INTEGER(IntKi), PARAMETER :: NODE_NOT_MAPPED = -1 !< constant that indicates a node is not mapped + + PUBLIC :: MeshMapCreate + PUBLIC :: MeshMapDestroy + PUBLIC :: MeshMapWrBin + PUBLIC :: Transfer_Point_to_Point + PUBLIC :: Transfer_Line2_to_Point + PUBLIC :: Transfer_Point_to_Line2 + PUBLIC :: Transfer_Line2_to_Line2 + + PUBLIC :: Linearize_Point_to_Point + PUBLIC :: Linearize_Line2_to_Point + PUBLIC :: Linearize_Point_to_Line2 + PUBLIC :: Linearize_Line2_to_Line2 + !PUBLIC :: Lump_Line2_to_Point + + PUBLIC :: WriteMappingTransferToFile ! routine for mesh-mapping debugging + + ! auto-generated routines, necessary for the FAST Registry: + PUBLIC :: NWTC_Library_DestroyMeshMapType, NWTC_Library_CopyMeshMapType, NWTC_Library_PackMeshMapType, NWTC_Library_UnpackMeshMapType + PUBLIC :: NWTC_Library_DestroyMapType, NWTC_Library_CopyMapType, NWTC_Library_PackMapType, NWTC_Library_UnpackMapType + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!bjj: maybe the MeshMapCreate routine shouldn't actually allocate arrays; allocate them in +! the "IF (RemapFlag)" sections so that if people add nodes during the simulation, the structures get reallocated to correct +! size? MeshMapCreate should maybe be MeshMapping_Init() and only check that fields are compatible, etc. +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes two meshes, determines the sizes required for the mapping data structure, and then +!! allocates the mappings (different for loads and motions/scalars). +SUBROUTINE MeshMapCreate( Src, Dest, MeshMap, ErrStat, ErrMsg ) + +! note that MeshMap%MapSrcToAugmt is allocated in Create_Augmented_Ln2_Src_Mesh() along with the Augmented_Ln2_Src Mesh + + TYPE(MeshType), INTENT(IN) :: Src !< source mesh + TYPE(MeshType), INTENT(IN) :: Dest !< destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables: + + INTEGER(IntKi) :: PointsInMap, PointsInTmpMap + INTEGER(IntKi) :: ElementNodes + LOGICAL :: MapCreated + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'MeshMapCreate' + + + ErrStat = ErrID_None + ErrMsg = '' + + MapCreated = .FALSE. + + + IF ( .NOT. Dest%Committed .OR. .NOT. Src%Committed ) THEN + ErrStat = ErrID_Fatal + ErrMsg = " Both meshes must be committed before they can be mapped." + RETURN + END IF + + + ElementNodes = 1 + PointsInTmpMap = 0 + + !................................................ + ! Allocate the mapping for Motions and Scalars (if both meshes have some): + !................................................ + IF ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) THEN + + IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN !Line2-to-Point and Line2-to-Line2 motion mapping + ElementNodes = 2 + END IF + + + ! for motion fields, every destination node is mapped to a source element or node + + PointsInMap = Dest%Nnodes + PointsInTmpMap = MAX(PointsInTmpMap,PointsInMap) + + IF ( PointsInMap < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'MeshMap%MapMotions not allocated because no nodes were found to map.', ErrStat, ErrMsg, RoutineName) + ELSE + + ! Allocate the mapping structure: + ALLOCATE( MeshMap%MapMotions(PointsInMap), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error trying to allocate MeshMap%MapMotions.', ErrStat, ErrMsg, RoutineName) + ELSE + MapCreated = .TRUE. + + ! set up the initial mappings so that we don't necessarially have to do this multiple times on the first time step (if calculating Jacobians) + IF ( Dest%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! point-to-Line2 or Line2-to-Line2 + + IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-Line2 + CALL CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-Line2 + CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + ELSEIF ( Dest%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point or Line2-to-point + + IF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point + CALL CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-point + CALL CreateMotionMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + END IF ! create initial mapping based on mesh element type + + END IF ! MapMotions created + + END IF ! Dest has nodes to map + + END IF !HasMotionFields + + + !................................................ + ! Allocate the mapping for Loads: + !................................................ + IF ( HasLoadFields(Src) .AND. HasLoadFields(Dest) ) THEN + + ! check that the appropriate combinations of source/destination force/moments exist: + IF ( Src%FieldMask(MASKID_Force) ) THEN + IF (.NOT. Dest%FieldMask(MASKID_Force) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Destination mesh does not contain force but source mesh does.', ErrStat, ErrMsg, RoutineName) + END IF + IF (.NOT. Dest%FieldMask(MASKID_Moment) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must contain moment when source mesh contains force.', ErrStat, ErrMsg, RoutineName) + END IF + END IF + IF ( Src%FieldMask(MASKID_Moment) ) THEN + IF (.NOT. Dest%FieldMask(MASKID_Moment) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Destination mesh does not contain moment but source mesh does.', ErrStat, ErrMsg, RoutineName) + END IF + END IF + + + ! get size of mapping: + PointsInMap = Src%Nnodes + + IF ( PointsInMap < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'MeshMap%MapLoads not allocated because no nodes were found to map.', ErrStat, ErrMsg, RoutineName) + ELSE + + ! Allocate the mapping structure: + ALLOCATE( MeshMap%MapLoads(PointsInMap), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error trying to allocate MeshMap%MapLoads.', ErrStat, ErrMsg, RoutineName) + ELSE + MapCreated = .TRUE. + + ! set up the initial mappings so that we don't necessarially have to do this multiple times on the first time step (if calculating Jacobians) + IF ( Dest%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! point-to-Line2 or Line2-to-Line2 + + ElementNodes = 2 + + IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-Line2 + CALL CreateLoadMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-Line2 + CALL CreateLoadMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + ELSEIF ( Dest%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point or Line2-to-point + + IF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point + CALL CreateLoadMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-point + CALL CreateLoadMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + END IF ! create initial mapping based on mesh element type + + END IF ! MapLoads allocated + + END IF ! Src has nodes to transfer + + END IF ! HasLoadFields + + IF ( .NOT. MapCreated ) THEN + CALL SetErrStat( ErrID_Fatal, 'Neither MapMotions or MapLoads was allocated. Meshes may not have compatible fields for mapping.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + + !................................................ + ! Allocate the DisplacedPosition field: + !................................................ + + IF (.NOT. ALLOCATED (MeshMap%DisplacedPosition)) THEN + CALL AllocAry( MeshMap%DisplacedPosition, 3, PointsInTmpMap, ElementNodes, 'MeshMap%DisplacedPosition', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + +END SUBROUTINE MeshMapCreate +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine destroys the elements of the MeshMapType +SUBROUTINE MeshMapDestroy( MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL NWTC_Library_DestroyMeshMapType(MeshMap, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'MeshMapDestroy') + +#ifdef MESH_DEBUG + CALL MeshDestroy( MeshMap%Lumped_Points_Dest, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'MeshMapDestroy') +#endif + +END SUBROUTINE MeshMapDestroy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This creates a matrix to write to a binary file (for debugging) +SUBROUTINE MeshMapWrBin( UnIn, Src, Dest, MeshMap, ErrStat, ErrMsg, FileName ) + + INTEGER, INTENT(INOUT) :: UnIn !< fortran output unit + + TYPE(MeshType), INTENT(IN ) :: Src !< source mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< destination mesh + TYPE(MeshMapType), INTENT(IN ) :: MeshMap !< mapping data structure + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + CHARACTER(*), OPTIONAL, INTENT(IN ) :: FileName !< Name of the file to write the output in + + ! local variables + REAL(ReKi), allocatable :: MapMat(:,:) + INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors + INTEGER(IntKi) :: I , j , k, n ! loop counter + INTEGER(B4Ki) :: MeshesInFile(3), MatInFile(2) + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrMsg = "" + ErrStat = ErrID_None + MeshesInFile = 0 + MatInFile= 0 + + IF (UnIn < 0) THEN + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + + CALL OpenBOutFile ( UnIn, TRIM(FileName), ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + IF ( MeshMap%Augmented_Ln2_Src%Committed ) THEN + ALLOCATE( MapMat(MeshMap%Augmented_Ln2_Src%Nnodes, Dest%Nnodes),STAT=ErrStat2) + ELSE + ALLOCATE( MapMat(Src%Nnodes, Dest%Nnodes),STAT=ErrStat2) + END IF + IF ( ErrStat2 /=0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg="Error allocating MapMat." + RETURN + END IF + + MapMat = 0.0_ReKi + IF ( HasMotionFields(Src) ) THEN + WRITE (UnIn, IOSTAT=ErrStat2) INT(1,B4Ki) + + IF ( Src%ElemTable(ELEMENT_POINT)%Nelem > 0 ) THEN + DO i=1,Dest%Nnodes + j=MeshMap%MapMotions(i)%OtherMesh_Element + if ( j < 1 ) CYCLE + MapMat(j,i) = 1 + END DO + ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%Nelem > 0 ) THEN + DO i=1,Dest%Nnodes + j=MeshMap%MapMotions(i)%OtherMesh_Element + if ( j < 1 ) CYCLE + DO k=1,size(Src%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes) + n=Src%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes(k) + MapMat(n,i) = MeshMap%MapMotions(i)%shape_fn(k) + END DO + END DO !i + ENDIF + + WRITE (UnIn, IOSTAT=ErrStat2) INT(SIZE(MapMat,1),B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) INT(SIZE(MapMat,2),B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) MapMat + + else + WRITE (UnIn, IOSTAT=ErrStat2) INT(0,B4Ki) + END IF + + + IF ( HasLoadFields(Src) ) THEN + WRITE (UnIn, IOSTAT=ErrStat2) INT(1,B4Ki) ! contains a load field + MapMat = 0.0_ReKi + IF ( Src%ElemTable(ELEMENT_POINT)%Nelem > 0 ) THEN + DO i=1,Src%Nnodes + j=MeshMap%MapLoads(i)%OtherMesh_Element + if ( j < 1 ) CYCLE + MapMat(i,j) = 1 + END DO + ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%Nelem > 0 ) THEN + + IF ( Dest%ElemTable(ELEMENT_POINT)%Nelem > 0 ) THEN + DO i=1,Src%Nnodes + j=MeshMap%MapLoads(i)%OtherMesh_Element + if ( j < 1 ) CYCLE + DO k=1,size(Dest%ElemTable(ELEMENT_POINT)%Elements(j)%ElemNodes) + n=Dest%ElemTable(ELEMENT_POINT)%Elements(j)%ElemNodes(k) + MapMat(i,n) = 1 !this isn't really "1"... it's a factor of lumping, etc, but we'll leave as is for now. + END DO + END DO !i + ELSEIF (Dest%ElemTable(ELEMENT_LINE2)%Nelem > 0 ) THEN + DO i=1,MeshMap%Augmented_Ln2_Src%Nnodes + j=MeshMap%MapLoads(i)%OtherMesh_Element + if ( j < 1 ) CYCLE + DO k=1,size(Dest%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes) + n=Dest%ElemTable(ELEMENT_LINE2)%Elements(j)%ElemNodes(k) + MapMat(i,n) = MeshMap%MapLoads(i)%shape_fn(k) + END DO + END DO !i + END IF + + ENDIF + WRITE (UnIn, IOSTAT=ErrStat2) INT(SIZE(MapMat,1),B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) INT(SIZE(MapMat,2),B4Ki) + WRITE (UnIn, IOSTAT=ErrStat2) MapMat + else + WRITE (UnIn, IOSTAT=ErrStat2) INT(0,B4Ki) + END IF + + + IF ( ALLOCATED(MapMat) ) DEALLOCATE(MapMat) + + MeshesInFile = 0 +#ifdef MESH_DEBUG + IF (MeshMap%Augmented_Ln2_Src%committed) MeshesInFile(1)=1 + IF (MeshMap%Lumped_Points_Src%committed) MeshesInFile(2)=1 + IF (MeshMap%Lumped_Points_Dest%committed) MeshesInFile(3)=1 + WRITE (UnIn, IOSTAT=ErrStat2) MeshesInFile + + IF (MeshMap%Augmented_Ln2_Src%committed) CALL MeshWrBin(UnIn, MeshMap%Augmented_Ln2_Src, ErrStat2, ErrMsg2) + IF (MeshMap%Lumped_Points_Src%committed) CALL MeshWrBin(UnIn, MeshMap%Lumped_Points_Src, ErrStat2, ErrMsg2) + IF (MeshMap%Lumped_Points_Dest%committed) CALL MeshWrBin(UnIn, MeshMap%Lumped_Points_Dest, ErrStat2, ErrMsg2) +#else + WRITE (UnIn, IOSTAT=ErrStat2) MeshesInFile +#endif + +END SUBROUTINE MeshMapWrBin +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for transfering data from Line2 mesh to Point Mesh +SUBROUTINE Transfer_Line2_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source mesh + TYPE(MeshType), INTENT(INOUT) :: Dest !< destination mesh + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp !< a "functional" sibling of the source mesh required for loads transfer; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: DestDisp !< a "functional" sibling of the destination mesh required for loads transfer; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + REAL(ReKi) :: LoadsScaleFactor ! bjj: added this scaling factor to get loads in a better numerical range + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_Line2_to_Point' + + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + !................. + ! Check to ensure that the source mesh is composed of Line2 elements and destination mesh is composed of Point elements + !................. + + if (Src%ElemTable(ELEMENT_LINE2)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Source mesh must have one or more Line2 elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Dest%ElemTable(ELEMENT_POINT)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must have one or more Point elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + ! This is the same algorithm as Transfer_Line2_to_Line2 (motions) + + !........................ + ! Start: Create Mapping data (if remap is true) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_L2_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !remapping + + + !........................ + ! Start: Transfer data + !........................ + + CALL Transfer_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !algorithm for motions/scalars + + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + ! ------------------------------------------------------------------------------------------------------ + ! Start: If mapping force/moment from Line2 to Point, need to created a temporary + ! PointMesh that has nodes at the same locations as the Line2 mesh; distributed force/moment + ! from the Line2 mesh can then be lumped into the temporary Point mesh and transfered to the Destination + ! Point mesh via the same algorithm as subroutine Transfer_Point_to_Point + ! ------------------------------------------------------------------------------------------------------ + + if ( HasLoadFields(Src) ) then + + !........................ + ! Create mapping (including the temporary src mesh) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + ELSE ! Check that the temporary mesh has been set + + IF ( .NOT. MeshMap%Lumped_Points_Src%Initialized ) THEN + CALL SetErrStat( ErrID_Fatal, 'MeshMap%Lumped_Points_Src not initialized (set RemapFlag = TRUE).', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + END IF + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + LoadsScaleFactor = GetLoadsScaleFactor ( Src ) + + ! first, we take the source fields and transfer them to fields on the augmented source mesh: + ! (we're also taking the SrcDisp field and putting it on our augmented mesh) + CALL Transfer_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat2, ErrMsg2, SrcDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! then we lump the loads from the augmented source mesh: + CALL Lump_Line2_to_Point( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, ErrStat2, ErrMsg2, LoadsScaleFactor=LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + !........................ + ! Transfer data + !........................ + + ! we already checked if SrcDisp is present and transferred the displacements to MeshMap%Augmented_Ln2_Src + CALL Transfer_Loads_Point_to_Point( MeshMap%Lumped_Points_Src, Dest, MeshMap, ErrStat2, ErrMsg2, MeshMap%Augmented_Ln2_Src, DestDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if !algorithm for loads + + +END SUBROUTINE Transfer_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing linearization matrices for data transfer from Line2 mesh to Point Mesh +!! \copydetails modmesh_mapping::linearize_line2_to_line2 +SUBROUTINE Linearize_Line2_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src ! source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! destination mesh + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp ! a "functional" sibling of the source mesh required for loads transfer; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: DestDisp ! a "functional" sibling of the destination mesh required for loads transfer; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap ! mapping data structure + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + real(R8Ki), allocatable :: M_A(:,:) ! linearization matrix for augmented source mesh + real(R8Ki), allocatable :: M_SL_fm(:,:) ! linearization matrix for source-mesh lumped force component of moment + real(R8Ki), allocatable :: M_SL_uSm(:,:) ! linearization matrix for source-mesh lumped translational displacement component of moment + real(R8Ki), allocatable :: M_SL_li(:,:) ! linearization matrix for source-mesh lumped load "identity" component + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linearize_Line2_to_Point' + + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Linearization of Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + ! This is the same algorithm as Transfer_Line2_to_Line2 (motions) + + !........................ + !> * Create Mapping data (if remap is true) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_L2_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !remapping + + + !........................ + !> * Get linearization matrices of data transfer + !........................ + + CALL Linearize_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !algorithm for motions/scalars + + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + ! ------------------------------------------------------------------------------------------------------ + ! Start: If mapping force/moment from Line2 to Point, follow same algorithm as Line2-to-Line2, but skip final "unlumping" step + ! ------------------------------------------------------------------------------------------------------ + + if ( HasLoadFields(Src) ) then + + !........................ + !> * Create mapping (including the temporary src mesh) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + ELSE ! Check that the temporary mesh has been set + + IF ( .NOT. MeshMap%Lumped_Points_Src%Initialized ) THEN + CALL SetErrStat( ErrID_Fatal, 'MeshMap%Lumped_Points_Src not initialized (set RemapFlag = TRUE).', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + END IF + + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer linearization.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + !........................ + !> * Linearize data + !........................ + + !........................ + !> + Get individual transformation matrices + !........................ + + + !> 1. Get the matrix that transfers the source fields to the augmented source mesh. + !! (We're also taking the force field and and translational displacement field and + !! putting them on our [intermediate] augmented mesh.) + CALL Linearize_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat2, ErrMsg2, SrcDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call move_alloc( MeshMap%dM%li, M_A ) +! ^^^ size of M_A is 3*MeshMap%Augmented_Ln2_Src%NNodes X 3*Src%Nnodes + + !> 2. Get the matrices that lump the loads on the augmented source mesh. + !! (We're also taking the force field and putting it on our [intermediate] lumped mesh.) + CALL Linearize_Lump_Line2_to_Point( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, MeshMap%dM, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call move_alloc( MeshMap%dM%m_uD, M_SL_uSm ) + call move_alloc( MeshMap%dM%m_f, M_SL_fm ) + call move_alloc( MeshMap%dM%li, M_SL_li ) + +! ^^^ size of M_SL_i (as well as M_SL_uSm and M_SL_fm) is 3*MeshMap%Augmented_Ln2_Src%NNodes X 3*MeshMap%Augmented_Ln2_Src%NNodes + + !> 3. Get the matrices that transfer point meshes to other point meshes. + ! we already checked if SrcDisp is present and transferred the displacements to MeshMap%Augmented_Ln2_Src + CALL Linearize_Loads_Point_to_Point( MeshMap%Lumped_Points_Src, Dest, MeshMap, ErrStat2, ErrMsg2, MeshMap%Augmented_Ln2_Src, DestDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + +!^^ this creates matrices of size 3*Dest%NNodes x 3*MeshMap%Lumped_Points_Src%NNodes (m_uD is square, of size 3*Dest%NNodes X 3*Dest%NNodes) +! need to return size 3*Dest%NNodes x 3*Src%NNodes + + !........................ + !> + Multiply individual transformation matrices to form full linearization matrices + !........................ + + CALL FormMatrix_FullLinearization( MeshMap%dM, M_A, M_SL_fm, M_SL_uSm, M_SL_li, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call cleanup() + + end if !algorithm for loads + + +contains +subroutine cleanup() + + if (allocated(M_A )) deallocate(M_A ) + if (allocated(M_SL_uSm)) deallocate(M_SL_uSm) + if (allocated(M_SL_fm )) deallocate(M_SL_fm) + if (allocated(M_SL_li )) deallocate(M_SL_li) + +end subroutine cleanup + + +END SUBROUTINE Linearize_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that forms the final linearization matrices for of loads from line2 meshes to either line2 or point matrices +subroutine FormMatrix_FullLinearization( dM, M_A, M_SL_fm, M_SL_uSm, M_SL_li, ErrStat, ErrMsg ) + + type(MeshMapLinearizationType), intent(inout) :: dM !< linearization data type currently filled with values from point-to-point or point-to-line2 linearization + real(R8Ki), allocatable, intent(inout) :: M_A(:,:) !< linearization matrix for augmented source mesh + real(R8Ki), allocatable, intent(inout) :: M_SL_fm(:,:) !< linearization matrix for source-mesh lumped force component of moment + real(R8Ki), allocatable, intent(inout) :: M_SL_uSm(:,:) !< linearization matrix for source-mesh lumped source translational displacement component of moment + real(R8Ki), allocatable, intent(inout) :: M_SL_li(:,:) !< linearization matrix for source-mesh lumped load "identity" component + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + real(R8Ki), allocatable :: M(:,:) ! temporary transfer matrix for linearization (to make sure everything is the correct size) + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FormMatrix_FullLinearization' + + + + ErrStat = ErrID_None + ErrMsg = '' + + + !> Matrix \f$ M_{uSm} = \left[ M_{uSm}^D + M_{li}^D M_{uSm}^{SL} \right] M^A \f$. + if (allocated(dM%m_uS)) then + + dM%m_uS = dM%m_uS + matmul( dM%li, M_SL_uSm) + + deallocate(M_SL_uSm) + + call AllocAry(M, size(dM%m_uS,1), size(M_A,2), 'M', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat>=AbortErrLev) return + + M = matmul( dM%m_uS, M_A ) + call move_alloc( M, dM%m_uS ) + + end if + + !> Matrix \f$ M_{uDm} = M_{uDm}^D \f$ + ! already stored in dM%m_uD + + !> Matrix \f$ M_{fm} = \left[ M_{fm}^D M_{li}^{SL} + M_{li}^D M_{fm}^{SL} \right] M^A \f$ + if (allocated(dM%m_f)) then + + dM%m_f = matmul( dM%m_f, M_SL_li) + dM%m_f = dM%m_f + matmul( dM%li, M_SL_fm) + + deallocate(M_SL_fm) + + call AllocAry(M, size(dM%m_f,1), size(M_A,2), 'M', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat>=AbortErrLev) return + + M = matmul( dM%m_f, M_A ) + call move_alloc( M, dM%m_f ) + + end if + + + !> Matrix \f$ M_{li} = M_{li}^D M_{li}^{SL} M^A \f$ + if (allocated(dM%li)) then + + dM%li = matmul( dM%li, M_SL_li) + + deallocate(M_SL_li) + + call AllocAry(M, size(dM%li,1), size(M_A,2), 'M', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat>=AbortErrLev) return + + M = matmul( dM%li, M_A ) + call move_alloc( M, dM%li ) + + end if + +end subroutine FormMatrix_FullLinearization +!---------------------------------------------------------------------------------------------------------------------------------- +#ifdef __NEW_LINE2_TO_POINT_MOTION_TRANSFER +!!!! 2-Jun-2016: bjj: this new Transfer_Motions_Line2_to_Point routine doesn't seem to give any better results than the old one; +!!!! it's more computationally expensive so we'll keep the old one. +!!! +!!!!> This subroutine returns an interpolated value of the source orientation, computed by +!!!!! \f$\ RotationMatrix = +!!!!! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \left[\theta^{SR}_{eSn_i}\right]^T \right) \phi_i \right) +!!!!! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \theta^S_{eSn_i} \right) \phi_i \right) +!!!!! \f$ +!!!!! where \f$\log()\f$ is nwtc_num::dcm_logmap and \f$\Lambda()\f$ is nwtc_num::dcm_exp +!!!subroutine InterpSrcOrientation(i, Src, MeshMap, RotationMatrixD, ErrStat, ErrMsg) +!!! +!!! INTEGER(IntKi), INTENT(IN ) :: i !< current destination node +!!! TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with motion fields allocated +!!! +!!! TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data +!!! REAL(DbKi), INTENT( OUT) :: RotationMatrixD(3,3) !< interpolated value of MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n) ), Src%Orientation(:,:,n) ) +!!! +!!! INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation +!!! CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None +!!! +!!! +!!! REAL(DbKi) :: FieldValue(3,2) ! Temporary variable to store values for DCM interpolation +!!! REAL(DbKi) :: RotationMatrixDS(3,3) +!!! REAL(DbKi) :: tensor_interp(3) +!!! INTEGER(IntKi) :: n, n1, n2 ! temporary space for node numbers +!!! +!!! ErrStat = ErrID_None +!!! ErrMsg = "" +!!! +!!! n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) +!!! n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) +!!! +!!! +!!! ! bjj: because of numerical issues when the angle of rotation is pi, (where +!!! ! DCM_exp( DCM_logmap (x) ) isn't quite x +!!! if ( EqualRealNos( MeshMap%MapMotions(i)%shape_fn(1), 1.0_ReKi ) ) then +!!! RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n1) ), Src%Orientation(:,:,n1) ) +!!! +!!! elseif ( EqualRealNos( MeshMap%MapMotions(i)%shape_fn(2), 1.0_ReKi ) ) then +!!! RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n2) ), Src%Orientation(:,:,n2) ) +!!! +!!! else +!!! +!!! !......... +!!! ! interpolate reference orientation (bjj: could be optimized to not do this every step!) +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! RotationMatrixD = TRANSPOSE( Src%RefOrientation(:,:,n) ) +!!! CALL DCM_logmap( RotationMatrixD, FieldValue(:,n1), ErrStat, ErrMsg ) +!!! IF (ErrStat >= AbortErrLev) RETURN +!!! end do +!!! +!!! CALL DCM_SetLogMapForInterp( FieldValue ) ! make sure we don't cross a 2pi boundary +!!! +!!! ! interpolate tensors: +!!! tensor_interp = MeshMap%MapMotions(i)%shape_fn(1)*FieldValue(:,1) & +!!! + MeshMap%MapMotions(i)%shape_fn(2)*FieldValue(:,2) +!!! +!!! ! convert back to DCM for transpose (Src%RefOrientation): +!!! RotationMatrixD = DCM_exp( tensor_interp ) +!!! +!!! +!!! !......... +!!! ! interpolate Src%Orientation +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! RotationMatrixDS = Src%Orientation(:,:,n) ! possible change of precision +!!! CALL DCM_logmap( RotationMatrixDS, FieldValue(:,n1), ErrStat, ErrMsg ) +!!! IF (ErrStat >= AbortErrLev) RETURN +!!! end do +!!! +!!! CALL DCM_SetLogMapForInterp( FieldValue ) ! make sure we don't cross a 2pi boundary +!!! +!!! ! interpolate tensors: +!!! tensor_interp = MeshMap%MapMotions(i)%shape_fn(1)*FieldValue(:,1) & +!!! + MeshMap%MapMotions(i)%shape_fn(2)*FieldValue(:,2) +!!! +!!! ! convert back to DCM for transpose (Src%RefOrientation): +!!! RotationMatrixDS = DCM_exp( tensor_interp ) +!!! +!!! ! multiply so we have matmul( transpose(Src%RefOrientation), transpose(Src%Orientation) ) +!!! RotationMatrixD = matmul( RotationMatrixD, RotationMatrixDS ) +!!! +!!! end if +!!! +!!!end subroutine InterpSrcOrientation +!!!!---------------------------------------------------------------------------------------------------------------------------------- +!!!!> Given a mapping, this routine transfers the motions from nodes on Line2 elements to nodes on another mesh. +!!!SUBROUTINE Transfer_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg ) +!!! +!!! TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with motion fields allocated +!!! TYPE(MeshType), INTENT(INOUT) :: Dest !< The destination mesh +!!! +!!! TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data +!!! +!!! 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 , j ! counter over the nodes +!!! INTEGER(IntKi) :: n, n1 ! temporary space for node numbers +!!! REAL(ReKi) :: TmpVec(3), TmpVec2(3) +!!! REAL(R8Ki) :: RotationMatrix(3,3) +!!! +!!! REAL(DbKi) :: FieldValue(3,2) ! Temporary variable to store values for DCM interpolation +!!! REAL(DbKi) :: RotationMatrixD(3,3) +!!! +!!! +!!! ErrStat = ErrID_None +!!! ErrMsg = "" +!!! +!!! !> Define \f$ \phi_1 = 1-\bar{l}^S \f$ and +!!! !! \f$ \phi_2 = \bar{l}^S \f$. +!!! +!!! +!!! +!!! ! ---------------------------- ORIENTATION/Direction Cosine Matrix ---------------------- +!!! !> Orientation: \f$\theta^D = \theta^{DR} +!!! !! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \left[\theta^{SR}_{eSn_i}\right]^T \right) \phi_i \right) +!!! !! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \theta^S_{eSn_i} \right) \phi_i \right) +!!! !! \f$ +!!! !! where \f$\log()\f$ is nwtc_num::dcm_logmap and \f$\Lambda()\f$ is nwtc_num::dcm_exp +!!! +!!! ! transfer direction cosine matrix, aka orientation +!!! if ( Src%FieldMask(MASKID_Orientation) .AND. Dest%FieldMask(MASKID_Orientation) ) then +!!! +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! call InterpSrcOrientation(i, Src, MeshMap, RotationMatrixD, ErrStat, ErrMsg) +!!! if (ErrStat >= AbortErrLev) return +!!! +!!! CALL DCM_logmap( RotationMatrixD, FieldValue(:,1), ErrStat, ErrMsg ) +!!! +!!! RotationMatrix = REAL( RotationMatrixD, R8Ki ) +!!! Dest%Orientation(:,:,i) = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrix ) +!!! +!!! RotationMatrixD = Dest%RefOrientation(:,:,i) +!!! CALL DCM_logmap( RotationMatrixD, FieldValue(:,2), ErrStat, ErrMsg ) +!!! +!!! end do +!!! +!!! endif +!!! +!!! +!!! ! ---------------------------- Translation ------------------------------------------------ +!!! !> Translational Displacement: \f$\vec{u}^D = +!!! !! \sum\limits_{i=1}^{2}\left( \vec{u}^S_{eSn_i} \phi_i \right) + +!!! !! \left[ +!!! !! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \left[\theta^{S}_{eSn_i}\right]^T \right) \phi_i \right) +!!! !! \Lambda\left( \sum\limits_{i=1}^{2} \log\left( \theta^{SR}_{eSn_i} \right) \phi_i \right) +!!! !! - I \right] +!!! !! \left\{ \vec{p}^{ODR}- +!!! !! \sum\limits_{i=1}^{2}\left( \vec{p}^{OSR}_{eSn_i} \phi_i \right) +!!! !! \right\} +!!! !! \f$ +!!! +!!! if ( Src%FieldMask(MASKID_TranslationDisp) .AND. Dest%FieldMask(MASKID_TranslationDisp) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! Dest%TranslationDisp(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%TranslationDisp(:,i) = Dest%TranslationDisp(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%TranslationDisp(:,n) +!!! end do +!!! +!!! +!!! ! if Src mesh has orientation, superpose Dest displacement with translation due to rotation and couple arm +!!! if ( Src%FieldMask(MASKID_Orientation) ) then +!!! +!!! ! Calculate RotationMatrix as O_S^T*O_SR +!!! call InterpSrcOrientation(i, Src, MeshMap, RotationMatrixD, ErrStat, ErrMsg) +!!! if (ErrStat >= AbortErrLev) return +!!! RotationMatrix = transpose( RotationMatrixD ) +!!! +!!! ! subtract I +!!! do j=1,3 +!!! RotationMatrix(j,j)= RotationMatrix(j,j) - 1.0_ReKi +!!! end do +!!! +!!! ! multiply by p_DR - p_SR +!!! +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! FieldValue(:,n1) = MeshMap%MapMotions(i)%shape_fn(n1) * Src%Position(:,n) +!!! end do +!!! TmpVec = Dest%Position(:,i) - sum(FieldValue,2) +!!! Dest%TranslationDisp(:,i) = Dest%TranslationDisp(:,i) + matmul( RotationMatrix, TmpVec ) +!!! +!!! end if +!!! +!!! end do +!!! +!!! end if +!!! +!!! +!!! +!!! ! ---------------------------- Calculated total displaced positions --------------------- +!!! ! these values are used in both the translational velocity and translational acceleration +!!! ! calculations. The calculations rely on the TranslationDisp fields, which are calculated +!!! ! earlier in this routine. +!!! IF ( Src%FieldMask(MASKID_TranslationVel) .OR. Src%FieldMask(MASKID_TranslationAcc) ) THEN +!!! DO i = 1,Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! FieldValue(:,n1) = MeshMap%MapMotions(i)%shape_fn(n1) * ( Src%Position(:,n) + Src%TranslationDisp(:,n) ) +!!! end do +!!! TmpVec = sum(FieldValue,2) +!!! MeshMap%DisplacedPosition(:,i,1) = TmpVec - Dest%Position(:,i) - Dest%TranslationDisp(:,i) +!!! +!!! END DO +!!! END IF +!!! +!!! ! ---------------------------- TranslationVel -------------------------------------------- +!!! !> Translational Velocity: \f$\vec{v}^D = +!!! !! \sum\limits_{i=1}^{2}\left( \vec{v}^S_{eSn_i} \phi_i \right) +!!! !! + \left\{ +!!! !! \sum\limits_{i=1}^{2}\left( \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} \phi_i \right) +!!! !! - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} +!!! !! \right\} \times +!!! !! \sum\limits_{i=1}^{2} \left( \vec{\omega}^S_{eSn_i} \phi_i \right) +!!! !! \f$ +!!! +!!! +!!! if ( Src%FieldMask(MASKID_TranslationVel) .AND. Dest%FieldMask(MASKID_TranslationVel) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! Dest%TranslationVel(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%TranslationVel(:,i) = Dest%TranslationVel(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%TranslationVel(:,n) +!!! end do +!!! +!!! +!!! if ( Src%FieldMask(MASKID_RotationVel) ) then +!!! +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! FieldValue(:,n1) = MeshMap%MapMotions(i)%shape_fn(n1)*Src%RotationVel(:,n) +!!! end do +!!! TmpVec = sum(FieldValue,2) +!!! +!!! Dest%TranslationVel(:,i) = Dest%TranslationVel(:,i) + cross_product( MeshMap%DisplacedPosition(:,i,1) , TmpVec) +!!! +!!! endif +!!! +!!! end do +!!! +!!! endif +!!! +!!! ! ---------------------------- RotationVel ----------------------------------------------- +!!! !> Rotational Velocity: \f$\vec{\omega}^D = \sum\limits_{i=1}^{2} +!!! !! \vec{\omega}^S_{eSn_i} +!!! !! \phi_i\f$ +!!! +!!! +!!! if ( Src%FieldMask(MASKID_RotationVel) .AND. Dest%FieldMask(MASKID_RotationVel) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! Dest%RotationVel(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%RotationVel(:,i) = Dest%RotationVel(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%RotationVel(:,n) +!!! end do +!!! end do +!!! +!!! end if +!!! +!!! ! ---------------------------- TranslationAcc ----------------------------------------------- +!!! !> Translational Acceleration: \f$\vec{a}^D = +!!! !! \sum\limits_{i=1}^{2}\left( \vec{a}^S_{eSn_i} \phi_i \right) +!!! !! + \left\{ +!!! !! \sum\limits_{i=1}^{2}\left( \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} \phi_i \right) +!!! !! - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} +!!! !! \right\} \times +!!! !! \left( \sum\limits_{i=1}^{2}\left( \vec{\alpha}^S_{eSn_i} \phi_i \right) \right) +!!! !! + \left( \sum\limits_{i=1}^{2}\left( \vec{\omega}^S_{eSn_i} \phi_i \right) \right) +!!! !! \times \left\{ \left\{ +!!! !! \sum\limits_{i=1}^{2}\left( \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} \phi_i \right) +!!! !! - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} +!!! !! \right\} \times +!!! !! \left( \sum\limits_{i=1}^{2}\left( \vec{\omega}^S_{eSn_i} \phi_i \right) \right) +!!! !! \right\} +!!! !! \f$ +!!! +!!! +!!! if ( Src%FieldMask(MASKID_TranslationAcc) .AND. Dest%FieldMask(MASKID_TranslationAcc) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! +!!! Dest%TranslationAcc(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%TranslationAcc(:,i) = Dest%TranslationAcc(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%TranslationAcc(:,n) +!!! end do +!!! +!!! if ( Src%FieldMask(MASKID_RotationAcc) ) then +!!! +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! FieldValue(:,n1) = MeshMap%MapMotions(i)%shape_fn(n1)*Src%RotationAcc(:,n) +!!! end do +!!! TmpVec = sum(FieldValue,2) +!!! +!!! Dest%TranslationAcc(:,i) = Dest%TranslationAcc(:,i) + cross_product( MeshMap%DisplacedPosition(:,i,1) , TmpVec) +!!! end if +!!! +!!! if ( Src%FieldMask(MASKID_RotationVel) ) then +!!! +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! FieldValue(:,n1) = MeshMap%MapMotions(i)%shape_fn(n1)*Src%RotationVel(:,n) +!!! end do +!!! TmpVec = sum(FieldValue,2) ! omega +!!! +!!! TmpVec2 = cross_product( MeshMap%DisplacedPosition(:,i,1), TmpVec ) +!!! +!!! Dest%TranslationAcc(:,i) = Dest%TranslationAcc(:,i) + cross_product( TmpVec, TmpVec2) +!!! +!!! endif +!!! +!!! end do +!!! endif +!!! +!!! +!!! ! ---------------------------- RotationAcc ----------------------------------------------- +!!! !> Rotational Acceleration: \f$\vec{\alpha}^D = \sum\limits_{i=1}^{2} +!!! !! \vec{\alpha}^S_{eSn_i} +!!! !! \phi_i\f$ +!!! +!!! if (Src%FieldMask(MASKID_RotationAcc) .AND. Dest%FieldMask(MASKID_RotationAcc) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! Dest%RotationAcc(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%RotationAcc(:,i) = Dest%RotationAcc(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%RotationAcc(:,n) +!!! end do +!!! +!!! end do +!!! end if +!!! +!!! ! ---------------------------- Scalars ----------------------------------------------- +!!! !> Scalar: \f$S^D = \sum\limits_{i=1}^{2} +!!! !! S^S_{eSn_i} +!!! !! \phi_i\f$ +!!! +!!! if (Src%FieldMask(MASKID_SCALAR) .AND. Dest%FieldMask(MASKID_SCALAR) ) then +!!! do i=1, Dest%Nnodes +!!! !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE +!!! +!!! Dest%Scalars(:,i) = 0.0_ReKi +!!! do n1=1,NumNodes(ELEMENT_LINE2) +!!! n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(n1) +!!! +!!! Dest%Scalars(:,i) = Dest%Scalars(:,i) + MeshMap%MapMotions(i)%shape_fn(n1)*Src%Scalars(:,n) +!!! end do +!!! +!!! end do +!!! end if +!!! +!!! +!!!END SUBROUTINE Transfer_Motions_Line2_to_Point +!!!!---------------------------------------------------------------------------------------------------------------------------------- +#else +!> Given a mapping, this routine transfers the motions from nodes on Line2 elements to nodes on another mesh. +SUBROUTINE Transfer_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with motion fields allocated + TYPE(MeshType), INTENT(INOUT) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data + + 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 , j ! counter over the nodes + INTEGER(IntKi) :: k ! counter components + INTEGER(IntKi) :: nScalars ! number of scalars transferred + INTEGER(IntKi) :: n, n1, n2 ! temporary space for node numbers + REAL(R8Ki) :: FieldValueN1(3) ! Temporary variable to store field values on element nodes + REAL(R8Ki) :: FieldValueN2(3) ! Temporary variable to store field values on element nodes + REAL(ReKi) :: TmpVec(3) + REAL(R8Ki) :: RotationMatrix(3,3) + + REAL(DbKi) :: FieldValue(3,2) ! Temporary variable to store values for DCM interpolation + REAL(DbKi) :: RotationMatrixD(3,3) + REAL(DbKi) :: tensor_interp(3) + + + ErrStat = ErrID_None + ErrMsg = "" + + !> Define \f$ \phi_1 = 1-\bar{l}^S \f$ and + !! \f$ \phi_2 = \bar{l}^S \f$. + +!bjj: FieldValueN1 and FieldValueN2 should really be one matrix of DIM (3,2) now that we've modified some of the other data structures.... + + ! ---------------------------- Translation ------------------------------------------------ + !> Translational Displacement: \f$\vec{u}^D = \sum\limits_{i=1}^{2}\left( + !! \vec{u}^S_{eSn_i} + \left[\left[\theta^S_{eSn_i}\right]^T \theta^{SR}_{eSn_i} - I\right]\left\{\vec{p}^{ODR}-\vec{p}^{OSR}_{eSn_i}\right\} + !! \right) \phi_i\f$ + + ! u_Dest1 = u_Src + [Orientation_Src^T * RefOrientation_Src - I] * [p_Dest - p_Src] at Source Node n1 + ! u_Dest2 = u_Src + [Orientation_Src^T * RefOrientation_Src - I] * [p_Dest - p_Src] at Source Node n2 + ! u_Dest = (1.-elem_position)*u_Dest1 + elem_position*u_Dest2 + if ( Src%FieldMask(MASKID_TranslationDisp) .AND. Dest%FieldMask(MASKID_TranslationDisp) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + ! add the translation displacement portion part + do j=1,NumNodes(ELEMENT_LINE2) ! number of nodes per line2 element + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + FieldValue(:,j) = Src%TranslationDisp(:,n) + end do + + + ! if Src mesh has orientation, superpose Dest displacement with translation due to rotation and couple arm + if ( Src%FieldMask(MASKID_Orientation) ) then + + do j=1,NumNodes(ELEMENT_LINE2) ! number of nodes per line2 element + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + !Calculate RotationMatrix as O_S^T*O_SR + RotationMatrix = TRANSPOSE( Src%Orientation(:,:,n ) ) + RotationMatrix = MATMUL( RotationMatrix, Src%RefOrientation(:,:,n) ) + + ! subtract I + do k=1,3 + RotationMatrix(k,k)= RotationMatrix(k,k) - 1.0_R8Ki + end do + + FieldValue(:,j) = FieldValue(:,j) + MATMUL(RotationMatrix,(Dest%Position(:,i)-Src%Position(:,n))) + + end do + + end if + + ! now form a weighted average of the two points: + Dest%TranslationDisp(:,i) = MeshMap%MapMotions(i)%shape_fn(1)*FieldValue(:,1) & + + MeshMap%MapMotions(i)%shape_fn(2)*FieldValue(:,2) + + end do + + end if + + ! ---------------------------- ORIENTATION/Direction Cosine Matrix ---------------------- + !> Orientation: \f$\theta^D = \Lambda\left( \sum\limits_{i=1}^{2} + !! \log\left( \theta^{DR}\left[\theta^{SR}_{eSn_i}\right]^T\theta^S_{eSn_i} \right) + !! \phi_i \right)\f$ + !! where \f$\log()\f$ is nwtc_num::dcm_logmap and \f$\Lambda()\f$ is nwtc_num::dcm_exp + + + + ! transfer direction cosine matrix, aka orientation + + if ( Src%FieldMask(MASKID_Orientation) .AND. Dest%FieldMask(MASKID_Orientation) ) then + + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + ! bjj: added this IF statement because of numerical issues when the angle of rotation is pi, + ! (where DCM_exp( DCM_logmap (x) ) isn't quite x + if ( EqualRealNos( MeshMap%MapMotions(i)%shape_fn(1), 1.0_R8Ki ) ) then + + RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n1) ), Src%Orientation(:,:,n1) ) + RotationMatrixD = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrixD ) + + elseif ( EqualRealNos( MeshMap%MapMotions(i)%shape_fn(2), 1.0_R8Ki ) ) then + + RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n2) ), Src%Orientation(:,:,n2) ) + RotationMatrixD = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrixD ) + + else + + ! calculate Rotation matrix for FieldValueN1 and convert to tensor: + RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n1) ), Src%Orientation(:,:,n1) ) + RotationMatrixD = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrixD ) + + CALL DCM_logmap( RotationMatrixD, FieldValue(:,1), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + ! calculate Rotation matrix for FieldValueN2 and convert to tensor: + RotationMatrixD = MATMUL( TRANSPOSE( Src%RefOrientation(:,:,n2) ), Src%Orientation(:,:,n2) ) + RotationMatrixD = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrixD ) + + CALL DCM_logmap( RotationMatrixD, FieldValue(:,2), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL DCM_SetLogMapForInterp( FieldValue ) ! make sure we don't cross a 2pi boundary + + + ! interpolate tensors: + tensor_interp = MeshMap%MapMotions(i)%shape_fn(1)*FieldValue(:,1) & + + MeshMap%MapMotions(i)%shape_fn(2)*FieldValue(:,2) + + ! convert back to DCM: + RotationMatrixD = DCM_exp( tensor_interp ) + + end if + + Dest%Orientation(:,:,i) = REAL( RotationMatrixD, R8Ki ) + + end do + + endif + + ! ---------------------------- Calculated total displaced positions --------------------- + ! these values are used in both the translational velocity and translational acceleration + ! calculations. The calculations rely on the TranslationDisp fields, which are calculated + ! earlier in this routine. + IF ( Src%FieldMask(MASKID_TranslationVel) .OR. Src%FieldMask(MASKID_TranslationAcc) ) THEN + DO i = 1,Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + DO j=1,NumNodes(ELEMENT_LINE2) ! number of nodes per line2 element + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + MeshMap%DisplacedPosition(:,i,j) = Src%Position(:,n) + Src%TranslationDisp(:,n) & + - Dest%Position(:,i) - Dest%TranslationDisp(:,i) + end do + + END DO + END IF + + ! ---------------------------- TranslationVel -------------------------------------------- + !> Translational Velocity: \f$\vec{v}^D = \sum\limits_{i=1}^{2}\left( + !! \vec{v}^S_{eSn_i} + !! + \left\{ \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\omega}^S_{eSn_i} + !! \right) \phi_i\f$ + + + if ( Src%FieldMask(MASKID_TranslationVel) .AND. Dest%FieldMask(MASKID_TranslationVel) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + FieldValueN1 = Src%TranslationVel(:,n1) + FieldValueN2 = Src%TranslationVel(:,n2) + + if ( Src%FieldMask(MASKID_RotationVel) ) then + FieldValueN1 = FieldValueN1 + cross_product ( MeshMap%DisplacedPosition(:,i,1), Src%RotationVel(:,n1) ) + FieldValueN2 = FieldValueN2 + cross_product ( MeshMap%DisplacedPosition(:,i,2), Src%RotationVel(:,n2) ) + endif + + Dest%TranslationVel(:,i) = MeshMap%MapMotions(i)%shape_fn(1)*FieldValueN1 & + + MeshMap%MapMotions(i)%shape_fn(2)*FieldValueN2 + + + end do + + endif + + ! ---------------------------- RotationVel ----------------------------------------------- + !> Rotational Velocity: \f$\vec{\omega}^D = \sum\limits_{i=1}^{2} + !! \vec{\omega}^S_{eSn_i} + !! \phi_i\f$ + + + if ( Src%FieldMask(MASKID_RotationVel) .AND. Dest%FieldMask(MASKID_RotationVel) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + Dest%RotationVel(:,i) = MeshMap%MapMotions(i)%shape_fn(1)*Src%RotationVel(:,n1) & + + MeshMap%MapMotions(i)%shape_fn(2)*Src%RotationVel(:,n2) + end do + + end if + + ! ---------------------------- TranslationAcc ----------------------------------------------- + !> Translational Acceleration: \f$\vec{a}^D = \sum\limits_{i=1}^{2}\left( + !! \vec{a}^S_{eSn_i} + !! + \left\{ \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\alpha}^S_{eSn_i} + !! + \vec{\omega}^S_{eSn_i} \times \left\{ + !! \left\{ \left\{ \vec{p}^{OSR}_{eSn_i} + \vec{u}^S_{eSn_i} \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\omega}^S_{eSn_i} + !! \right\} + !! \right) \phi_i\f$ + + + + + if ( Src%FieldMask(MASKID_TranslationAcc) .AND. Dest%FieldMask(MASKID_TranslationAcc) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + FieldValueN1 = Src%TranslationAcc(:,n1) + FieldValueN2 = Src%TranslationAcc(:,n2) + + + if ( Src%FieldMask(MASKID_RotationAcc) ) then + FieldValueN1 = FieldValueN1 + cross_product( MeshMap%DisplacedPosition(:,i,1), Src%RotationAcc(:,n1) ) + FieldValueN2 = FieldValueN2 + cross_product( MeshMap%DisplacedPosition(:,i,2), Src%RotationAcc(:,n2) ) + endif + + if ( Src%FieldMask(MASKID_RotationVel) ) then + TmpVec = cross_product( MeshMap%DisplacedPosition(:,i,1), Src%RotationVel(:,n1) ) + FieldValueN1 = FieldValueN1 + cross_product( Src%RotationVel(:,n1), TmpVec ) + + TmpVec = cross_product( MeshMap%DisplacedPosition(:,i,2), Src%RotationVel(:,n2) ) + FieldValueN2 = FieldValueN2 + cross_product( Src%RotationVel(:,n2), TmpVec ) + + endif + + Dest%TranslationAcc(:,i) = MeshMap%MapMotions(i)%shape_fn(1)*FieldValueN1 & + + MeshMap%MapMotions(i)%shape_fn(2)*FieldValueN2 + + end do + endif + + + ! ---------------------------- RotationAcc ----------------------------------------------- + !> Rotational Acceleration: \f$\vec{\alpha}^D = \sum\limits_{i=1}^{2} + !! \vec{\alpha}^S_{eSn_i} + !! \phi_i\f$ + + if (Src%FieldMask(MASKID_RotationAcc) .AND. Dest%FieldMask(MASKID_RotationAcc) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + Dest%RotationAcc(:,i) = MeshMap%MapMotions(i)%shape_fn(1)*Src%RotationAcc(:,n1) & + + MeshMap%MapMotions(i)%shape_fn(2)*Src%RotationAcc(:,n2) + + + end do + end if + + ! ---------------------------- Scalars ----------------------------------------------- + !> Scalar: \f$S^D = \sum\limits_{i=1}^{2} + !! S^S_{eSn_i} + !! \phi_i\f$ + + if (Src%FieldMask(MASKID_SCALAR) .AND. Dest%FieldMask(MASKID_SCALAR) ) then + nScalars = min(Dest%nScalars, Src%nScalars) + + if (Dest%nScalars > nScalars) then + call SetErrStat(ErrID_Severe, "Not all scalars could be computed from source mesh (insufficient data).", ErrStat, ErrMsg, 'Transfer_Motions_Line2_to_Point') + Dest%Scalars(nScalars+1:,:) = 0.0_ReKi + end if + + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + n1 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + Dest%Scalars(1:nScalars,i) = MeshMap%MapMotions(i)%shape_fn(1)*Src%Scalars(1:nScalars,n1) & + + MeshMap%MapMotions(i)%shape_fn(2)*Src%Scalars(1:nScalars,n2) + + end do + end if + + +END SUBROUTINE Transfer_Motions_Line2_to_Point +#endif +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mapping, this routine transfers the motions from nodes on Line2 elements to nodes on another mesh. +SUBROUTINE Linearize_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with motion fields allocated + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data + + 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 + integer(intKi) :: i,j, k, n, d_start, d_end, s_start, s_end + real(R8Ki) :: tmp, tmpVec(3), SSMat(3,3) + real(R8Ki) :: RotVel(3) + + character(*), parameter :: RoutineName = 'Linearize_Motions_Line2_to_Point' + ErrStat = ErrID_None + ErrMsg = "" + + + if (.not. allocated(MeshMap%dM%mi) ) then + call AllocAry(MeshMap%dM%mi, Dest%Nnodes*3, Src%Nnodes*3, 'dM%mi', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%mi = 0.0_R8Ki + do i=1, Dest%Nnodes + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + do k=1,3 + MeshMap%dM%mi( (i-1)*3+k, (n-1)*3+k ) = MeshMap%MapMotions(i)%shape_fn(j) + end do + + end do + + end do + + + if ( (Src%FieldMask(MASKID_TranslationDisp) .AND. Dest%FieldMask(MASKID_TranslationDisp)) & + .or. (Src%FieldMask(MASKID_TranslationVel ) .AND. Dest%FieldMask(MASKID_TranslationVel )) & + .or. (Src%FieldMask(MASKID_TranslationAcc ) .AND. Dest%FieldMask(MASKID_TranslationAcc )) ) then + + + ! calculate displaced positions at operating point: + DO i = 1,Dest%Nnodes + + DO j=1,NumNodes(ELEMENT_LINE2) ! number of nodes per line2 element + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + MeshMap%DisplacedPosition(:,i,j) = Src%Position(:,n) + Src%TranslationDisp(:,n) & + - Dest%Position(:,i) - Dest%TranslationDisp(:,i) + end do + + END DO + + + + ! MeshMap%dM%fx_p required for all three transfers: + if (.not. allocated(MeshMap%dM%fx_p) ) then + call AllocAry(MeshMap%dM%fx_p, Dest%Nnodes*3, Src%Nnodes*3, 'dM%fx_p', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%fx_p = 0.0_R8Ki + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + s_start = (n - 1)*3+1 + s_end = s_start+2 + + tmpVec = MeshMap%DisplacedPosition(:,i,j) * MeshMap%MapMotions(i)%shape_fn(j) + MeshMap%dM%fx_p( d_start:d_end, s_start:s_end ) = SkewSymMat( tmpVec ) + + end do + + end do + + + ! MeshMap%dM%tv_uS and MeshMap%dM%tv_uD required for translational velocity: + if ( Src%FieldMask(MASKID_TranslationVel) .AND. Dest%FieldMask(MASKID_TranslationVel) ) then + + if ( Src%FieldMask(MASKID_RotationVel) ) then + if (.not. allocated(MeshMap%dM%tv_uD) ) then + call AllocAry(MeshMap%dM%tv_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%tv_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + if (.not. allocated(MeshMap%dM%tv_uS) ) then + call AllocAry(MeshMap%dM%tv_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%tv_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%tv_uD = 0.0_R8Ki + MeshMap%dM%tv_uS = 0.0_R8Ki + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + s_start = (n - 1)*3+1 + s_end = s_start+2 + + TmpVec = Src%RotationVel(:,n) * MeshMap%MapMotions(i)%shape_fn(j) + SSMat = SkewSymMat( TmpVec ) + + MeshMap%dM%tv_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%tv_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%tv_uS( d_start:d_end, s_start:s_end ) = -SSMat + end do + + end do + + else + if (allocated(MeshMap%dM%tv_uD)) deallocate(MeshMap%dM%tv_uD) + if (allocated(MeshMap%dM%tv_uS)) deallocate(MeshMap%dM%tv_uS) + end if !MASKID_RotationVel + + else + if (allocated(MeshMap%dM%tv_uD)) deallocate(MeshMap%dM%tv_uD) + if (allocated(MeshMap%dM%tv_uS)) deallocate(MeshMap%dM%tv_uS) + end if !MASKID_TranslationVel + + + if ( Src%FieldMask(MASKID_TranslationAcc ) .AND. Dest%FieldMask(MASKID_TranslationAcc ) ) then + + !-------------- ta_uD and ta_uS ----------------------------- + if (.not. allocated(MeshMap%dM%ta_uD) ) then + call AllocAry(MeshMap%dM%ta_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%ta_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + if (.not. allocated(MeshMap%dM%ta_uS) ) then + call AllocAry(MeshMap%dM%ta_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%ta_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + MeshMap%dM%ta_uD = 0.0_R8Ki + MeshMap%dM%ta_uS = 0.0_R8Ki + if ( Src%FieldMask(MASKID_RotationAcc) ) then + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + s_start = (n - 1)*3+1 + s_end = s_start+2 + + TmpVec = Src%RotationAcc(:,n) * MeshMap%MapMotions(i)%shape_fn(j) + SSMat = SkewSymMat( TmpVec ) + MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) = -SSMat + end do + end do + end if + + if ( Src%FieldMask(MASKID_RotationVel) ) then + + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + s_start = (n - 1)*3+1 + s_end = s_start+2 + + TmpVec = Src%RotationVel(:,n) * MeshMap%MapMotions(i)%shape_fn(j) + RotVel = Src%RotationVel(:,n) + SSMat = OuterProduct( RotVel, TmpVec ) + tmp = dot_product( RotVel, TmpVec ) + do k=1,3 + SSMat(k,k) = SSMat(k,k) - tmp + end do + + MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) = MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) - SSMat + + end do + + end do + end if + + + + + !-------------- ta_rv ----------------------------- + if ( Src%FieldMask(MASKID_RotationVel) ) then + if (.not. allocated(MeshMap%dM%ta_rv) ) then + call AllocAry(MeshMap%dM%ta_rv, Dest%Nnodes*3, Src%Nnodes*3, 'dM%ta_rv', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%ta_rv = 0.0_R8Ki + + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + + n = Src%ElemTable(ELEMENT_LINE2)%Elements(MeshMap%MapMotions(i)%OtherMesh_Element)%ElemNodes(j) + + s_start = (n - 1)*3+1 + s_end = s_start+2 + + RotVel = Src%RotationVel(:,n) + tmpVec = cross_product( RotVel, MeshMap%DisplacedPosition(:,i,j) ) + + SSMat = SkewSymMat( tmpVec ) + OuterProduct( MeshMap%DisplacedPosition(:,i,j), RotVel ) + MeshMap%dM%ta_rv( d_start:d_end, s_start:s_end ) = SSMat * MeshMap%MapMotions(i)%shape_fn(j) + + tmp=dot_product( MeshMap%DisplacedPosition(:,i,1), RotVel ) * MeshMap%MapMotions(i)%shape_fn(j) + do k=0,2 + MeshMap%dM%ta_rv( d_start+k, s_start+k ) = MeshMap%dM%ta_rv( d_start+k, s_start+k ) - tmp + end do + + end do + end do + + else + if (allocated(MeshMap%dM%ta_rv)) deallocate(MeshMap%dM%ta_rv) + end if ! MASKID_RotationVel + else + if (allocated(MeshMap%dM%ta_uD)) deallocate(MeshMap%dM%ta_uD) + if (allocated(MeshMap%dM%ta_uS)) deallocate(MeshMap%dM%ta_uS) + if (allocated(MeshMap%dM%ta_rv)) deallocate(MeshMap%dM%ta_rv) + end if ! MASKID_TranslationAcc + + end if ! MASKID_TranslationDisp, MASKID_RotationVel, or MASKID_TranslationAcc + + +END SUBROUTINE Linearize_Motions_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine projects Mesh1 onto a Line2 mesh (Mesh2) to find the element mappings between the two meshes. +SUBROUTINE CreateMapping_ProjectToLine2(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, ErrStat, ErrMsg) + + TYPE(MeshType), INTENT(IN ) :: Mesh1 !< The mesh in the outer mapping loop (Dest for Motions/Scalars; Src for Loads) + TYPE(MeshType), INTENT(IN ) :: Mesh2 !< The mesh in the inner mapping loop (Src for Motions/Scalars; Dest for Loads) + + TYPE(MapType), INTENT(INOUT) :: NodeMap(:) !< The mapping from Src to Dest + + INTEGER(IntKi), INTENT(IN ) :: Mesh1_TYPE !< Type of Mesh1 elements to map + INTEGER(IntKi), PARAMETER :: Mesh2_TYPE = ELEMENT_LINE2 !< Type of Mesh2 elements on map (MUST BE ELEMENT_LINE2) + + 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 ! Error status of the operation +! CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None +#ifdef DEBUG_MESHMAPPING + CHARACTER(200) :: DebugFileName ! File name for debugging file +#endif + CHARACTER(*), PARAMETER :: RoutineName = 'CreateMapping_ProjectToLine2' + + + REAL(ReKi) :: denom + REAL(ReKi) :: dist + REAL(ReKi) :: min_dist + REAL(ReKi) :: elem_position + REAL(SiKi) :: elem_position_SiKi + + REAL(ReKi) :: Mesh1_xyz(3) + + REAL(ReKi) :: n1_n2_vector(3) ! vector going from node 1 to node 2 in Line2 element + REAL(ReKi) :: n1_Point_vector(3) ! vector going from node 1 in Line 2 element to Destination Point + REAL(ReKi) :: tmp(3) ! temporary vector for cross product calculation + + + INTEGER(IntKi) :: iElem, iNode, i ! do-loop counter for elements on Mesh1, associated node(S) + INTEGER(IntKi) :: jElem ! do-loop counter for elements on Mesh2, associated node + + INTEGER(IntKi) :: n1, n2 ! nodes associated with an element + + LOGICAL :: found + LOGICAL :: on_element + REAL(ReKi) :: closest_elem_position + INTEGER(IntKi) :: closest_elem + REAL(ReKi) :: closest_elem_diff + REAL(ReKi) :: closest_elem_distance + +#ifdef DEBUG_MESHMAPPING + INTEGER(IntKi) :: Un ! unit number for debugging + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 +#endif + + + + ! initialization + ErrStat = ErrID_None + ErrMsg = "" + + + ! Map the source nodes to destination nodes: + do n1=1,size(NodeMap) + NodeMap(n1)%OtherMesh_Element = NODE_NOT_MAPPED ! initialize this so we know if we've mapped this node already (done only because we may have different elements) + end do !n1 + + + + do iElem = 1, Mesh1%ElemTable(Mesh1_TYPE)%nelem ! number of Mesh1_TYPE elements on Mesh1 + do iNode = 1, SIZE( Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes ) + i = Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes(iNode) ! the nodes on element iElem + IF ( NodeMap(i)%OtherMesh_Element > 0 ) CYCLE ! we already mapped this node; let's move on to the next iNode (or iElem) + + ! destination point + Mesh1_xyz = Mesh1%Position(:, i) + + found = .false. + min_dist = HUGE(min_dist) + + ! some values for finding mapping if there are some numerical issues + closest_elem_diff = HUGE(min_dist) + closest_elem = 0 + + do jElem = 1, Mesh2%ElemTable(Mesh2_TYPE)%nelem ! ELEMENT_LINE2 = Mesh2_TYPE + + ! write(*,*) 'i,jElem = ', i,jElem, 'found = ', found + + ! grab node numbers associated with the jElem_th element + n1 = Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(1) + n2 = Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(2) + + ! Calculate vectors used in projection operation + + n1_n2_vector = Mesh2%Position(:,n2) - Mesh2%Position(:,n1) + n1_Point_vector = Mesh1_xyz - Mesh2%Position(:,n1) + + denom = DOT_PRODUCT( n1_n2_vector, n1_n2_vector ) + IF ( EqualRealNos( denom, 0.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Division by zero because Line2 element nodes are in same position.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + ! project point onto line defined by n1 and n2 + + elem_position = DOT_PRODUCT(n1_n2_vector,n1_Point_vector) / denom + + ! note: i forumlated it this way because Fortran doesn't necessarially do shortcutting and I don't want to call EqualRealNos if we don't need it: + if ( elem_position .ge. 0.0_ReKi .and. elem_position .le. 1.0_ReKi ) then !we're ON the element (between the two nodes) + on_element = .true. + else + elem_position_SiKi = REAL( elem_position, SiKi ) + if (EqualRealNos( elem_position_SiKi, 1.0_SiKi )) then !we're ON the element (at a node) + on_element = .true. + elem_position = 1.0_ReKi + elseif (EqualRealNos( elem_position_SiKi, 0.0_SiKi )) then !we're ON the element (at a node) + on_element = .true. + elem_position = 0.0_ReKi + else !we're not on the element + on_element = .false. + + if (.not. found) then ! see if we have are very close to the end of an element (numerical roundoff?) + if ( elem_position_SiKi < 0.0_SiKi ) then + if ( -elem_position_SiKi < closest_elem_diff ) then + closest_elem_diff = -elem_position_SiKi + closest_elem = jElem + closest_elem_position = 0.0_ReKi + closest_elem_distance = sqrt(denom) * closest_elem_diff ! distance from end of element, in meters + end if + else + if ( elem_position_SiKi-1.0_SiKi < closest_elem_diff ) then + closest_elem_diff = elem_position_SiKi-1.0_SiKi + closest_elem = jElem + closest_elem_position = 1.0_ReKi + closest_elem_distance = sqrt(denom) * closest_elem_diff ! distance from end of element, in meters + end if + end if + end if + + end if + end if + + if (on_element) then + + ! calculate distance between point and line (note: this is actually the distance squared); + ! will only store information once we have determined the closest element + tmp = cross_product( n1_n2_vector, n1_Point_vector ) + dist = DOT_PRODUCT(tmp,tmp) / denom + + if (dist .lt. min_dist) then + found = .true. + min_dist = dist + + NodeMap(i)%OtherMesh_Element = jElem + NodeMap(i)%shape_fn(1) = 1.0_ReKi - elem_position + NodeMap(i)%shape_fn(2) = elem_position + + !NodeMap(i)%couple_arm = n1_Point_vector + + end if !the point is closest to this line2 element + + endif + + end do !jElem + + ! if failed to find an element that the Point projected into, throw an error + if (.not. found) then + if ( closest_elem_distance <= 7.5e-3 ) then ! if it is within 7.5mm of the end of an element, we'll accept it + NodeMap(i)%OtherMesh_Element = closest_elem + NodeMap(i)%shape_fn(1) = 1.0_ReKi - closest_elem_position + NodeMap(i)%shape_fn(2) = closest_elem_position + CALL SetErrStat( ErrID_Info, 'Found close value for node '//trim(num2Lstr(i))//'. ('//trim(num2lstr(closest_elem_distance))//' m)', ErrStat, ErrMsg, RoutineName) + end if + + if (NodeMap(i)%OtherMesh_Element .lt. 1 ) then + CALL SetErrStat( ErrID_Fatal, 'Node '//trim(num2Lstr(i))//' does not project onto any line2 element.' & + //' Closest distance is '//trim(num2lstr(closest_elem_distance))//' m.', ErrStat, ErrMsg, RoutineName) + +#ifdef DEBUG_MESHMAPPING + ! output some mesh information for debugging + CALL GetNewUnit(Un,ErrStat2,ErrMsg2) + DebugFileName='FAST_Meshes.'//trim(num2Lstr(Un))//'.dbg' + CALL OpenFOutFile(Un,DebugFileName,ErrStat2,ErrMsg2) + IF (ErrStat2 >= AbortErrLev) RETURN + + CALL SetErrStat( ErrID_Info, 'See '//trim(DebugFileName)//' for mesh debug information.', ErrStat, ErrMsg, RoutineName) + WRITE( Un, '(A,I5,A,I5,A,ES15.5,A)' ) 'Element ', closest_elem, ' is closest to node ', i, & + '. It has a relative position of ', closest_elem_diff, '.' + + WRITE( Un, '(A)') '************************************************** Mesh1 ***************************************************' + WRITE( Un, '(A)') 'Mesh1 is the destination mesh for transfer of motions/scalars; it is the source mesh for transfer of loads.' + WRITE( Un, '(A)') '************************************************************************************************************' + CALL MeshPrintInfo ( Un, Mesh1 ) + WRITE( Un, '(A)') '************************************************** Mesh2 ***************************************************' + WRITE( Un, '(A)') 'Mesh2 is the source mesh for transfer of motions/scalars; it is the destination mesh for transfer of loads.' + WRITE( Un, '(A)') '************************************************************************************************************' + CALL MeshPrintInfo ( Un, Mesh2 ) + ! CLOSE(Un) ! by not closing this, I can ensure unique file names. +#endif + + RETURN + endif + + end if !not found on projection to element + + end do !iNode + end do !iElem + +END SUBROUTINE CreateMapping_ProjectToLine2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine creates a new mesh with the same positions as the Src mesh, except all of the elements are points. It adds fields for +!! forces, moments, and/or TranslationDisp, if they are part of the Src mesh. +SUBROUTINE Create_PointMesh(Src, Temp_Point_Src, ErrStat, ErrMsg) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh + TYPE(MeshType), INTENT(INOUT) :: Temp_Point_Src !< A blank mesh to be created + + 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 !loop over the nodes + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + CALL MeshDestroy( Temp_Point_Src, ErrStat2, ErrMsg2, .TRUE. ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Create_PointMesh') + IF (ErrStat >= AbortErrLev) RETURN + + + CALL MeshCreate( BlankMesh = Temp_Point_Src & + ,IOS = Src%IOS & + ,NNodes = Src%nnodes & + ,Force = Src%FieldMask(maskid_force) & + ,Moment = Src%FieldMask(maskid_moment) & + ,TranslationDisp = Src%FieldMask(maskid_TranslationDisp) & ! ,Orientation = Src%FieldMask(maskid_Orientation) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Create_PointMesh') + IF (ErrStat >= AbortErrLev) RETURN + + do i = 1, src%nnodes + + CALL MeshConstructElement ( Mesh = Temp_Point_Src & + ,Xelement = ELEMENT_POINT & + ,P1 = I & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Create_PointMesh') + IF (ErrStat >= AbortErrLev) RETURN + + CALL MeshPositionNode ( Mesh = Temp_Point_Src & + ,INode = i & + ,Pos = Src%Position(:,i) & + ,Orient = Src%RefOrientation(:,:,i) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Create_PointMesh') + IF (ErrStat >= AbortErrLev) RETURN + + enddo + + CALL MeshCommit ( Temp_Point_Src, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Create_PointMesh') + IF (ErrStat >= AbortErrLev) RETURN + +END SUBROUTINE Create_PointMesh +!---------------------------------------------------------------------------------------------------------------------------------- +!> routine that creats a map of line2 loads to points +SUBROUTINE CreateLoadMap_L2_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping structure + + 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 = "" + + + ! augment the source mesh with nodes formed by projections from the destination mesh nodes + CALL Create_Augmented_Ln2_Src_Mesh(Src, Dest, MeshMap, ELEMENT_POINT, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateLoadMap_L2_to_P') + IF (ErrStat >= AbortErrLev) RETURN + + ! Create a temporary mesh for lumped point elements of the line2 mesh + CALL Create_PointMesh( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateLoadMap_L2_to_P') + IF (ErrStat >= AbortErrLev) RETURN + + ! in following call, Src is mesh to loop over, finding a corresponding point for each point in Dest + CALL CreateMapping_NearestNeighbor( MeshMap%Lumped_Points_Src, Dest, MeshMap%MapLoads, ELEMENT_POINT, ELEMENT_POINT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateLoadMap_L2_to_P') + IF (ErrStat >= AbortErrLev) RETURN + +END SUBROUTINE CreateLoadMap_L2_to_P +!---------------------------------------------------------------------------------------------------------------------------------- +!> routine that creats a map of line2 motions to points +SUBROUTINE CreateMotionMap_L2_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure + + 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 = "" + + CALL CreateMapping_ProjectToLine2(Dest,Src, MeshMap%MapMotions, ELEMENT_POINT, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_L2_to_P') + !IF (ErrStat >= AbortErrLev) RETURN + +END SUBROUTINE CreateMotionMap_L2_to_P +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that transfers data from a point mesh to a line2 mesh. +SUBROUTINE Transfer_Point_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source (point) mesh + TYPE(MeshType), INTENT(INOUT) :: Dest !< destination (line2) mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp !< a "functional" sibling of the source mesh for load mapping; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: DestDisp !< a "functional" sibling of the destination mesh for load mapping; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + ! local variables + + REAL(ReKi) :: LoadsScaleFactor ! bjj: added this scaling factor to get loads in a better numerical range + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName= 'Transfer_Point_to_Line2' + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + !................. + ! Check to ensure that the source mesh is composed of Point elements and destination mesh is composed of Line2 elements + !................. + + if (Src%ElemTable(ELEMENT_POINT)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Source mesh must have one or more Point elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Dest%ElemTable(ELEMENT_LINE2)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must have one or more Line2 elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + ! Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + ! Transfer data + !........................ + + ! This is the same algorithm as Transfer_Point_to_Point + CALL Transfer_Motions_Point_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if ! algorithm for motions/scalars + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasLoadFields(Src) ) then + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + !........................ + ! Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + + !........................ + ! Transfer data + !........................ + LoadsScaleFactor = GetLoadsScaleFactor ( Src ) + + CALL Transfer_Loads_Point_to_Line2( Src, Dest, MeshMap, ErrStat2, ErrMsg2, SrcDisp, DestDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if ! algorithm for loads + + +END SUBROUTINE Transfer_Point_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that creates linearization matricies for data tranfer from a point mesh to a line2 mesh. +!! \copydetails modmesh_mapping::linearize_point_to_point +SUBROUTINE Linearize_Point_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src ! source (point) mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! destination (line2) mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap ! mapping data structure of Src to Dest + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + TYPE(MeshType),OPTIONAL, INTENT(IN ) :: SrcDisp ! a "functional" sibling of the source mesh for load mapping; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL, INTENT(IN ) :: DestDisp ! a "functional" sibling of the destination mesh for load mapping; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + ! local variables + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName= 'Linearize_Point_to_Line2' + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Linearization of Data Transfer for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + !> * Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + !> * Get linearization matrices for data transfer + !........................ + + ! This is the same algorithm as Transfer_Point_to_Point + CALL Linearize_Motions_Point_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if ! algorithm for motions/scalars + + ! ------------------------------------------------------------------------------------------------------------------------------ + !. ### Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasLoadFields(Src) ) then + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer linearization.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + !........................ + !> * Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !> + We need a motion mapping structure from the SrcDisp to DestDisp meshes so that we can form the proper matrices for moment + !! linearizaiton. (This is because we have both the source translational displacement and rotational displacement on the right side + !! of the equation; alternatively we'd have to have the source AND destination translational displacements on the right hand side.) + if ( .not. allocated(MeshMap%MapMotions)) then + + ! Allocate the mapping structure: + ALLOCATE( MeshMap%MapMotions(DestDisp%NNodes), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error trying to allocate MeshMap%MapMotions.', ErrStat, ErrMsg, RoutineName) + return + ELSE + ! set up the initial mappings so that we don't necessarially have to do this multiple times on the first time step (if calculating Jacobians) + !note this is for SrcDisp and DestDisp meshes, but they are "functional siblings" of Src and Dest (i.e., may have different element types than point and line2) + CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + elseif (SrcDisp%RemapFlag .or. DestDisp%RemapFlag ) then + + !note this is for SrcDisp and DestDisp meshes, but they are "functional siblings" of Src and Dest (i.e., may have different element types than line2) + CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + !> * Get linearization matrices for data transfer + !........................ + + CALL Linearize_Loads_Point_to_Line2( Src, Dest, MeshMap, ErrStat2, ErrMsg2, SrcDisp, DestDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if ! algorithm for loads + + +END SUBROUTINE Linearize_Point_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateLoadMap_P_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + + 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 = "" + + !........................ + ! Create matrix used to "unlump" loads later (needs to have element connectivity information to create it) + !........................ + CALL Create_InverseLumping_Matrix( Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateLoadMap_P_to_L2') + + + CALL CreateMapping_ProjectToLine2(Src, Dest, MeshMap%MapLoads, ELEMENT_POINT, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateLoadMap_P_to_L2') + IF (ErrStat >= AbortErrLev) RETURN + + +END SUBROUTINE CreateLoadMap_P_to_L2 +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + + 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 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Each destination node (on a LINE2 mesh) needs a source + ! in following call, Dest is mesh to looped over, finding a corresponding point for each point in Src + CALL CreateMapping_NearestNeighbor( Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ELEMENT_POINT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_P_to_L2') + IF (ErrStat >= AbortErrLev) RETURN + + ! bjj: for consistant definition of couple_arm (i.e. p_ODR-p_OSR), let's multiply by -1 + do i=1,SIZE(MeshMap%MapMotions) + MeshMap%MapMotions(i)%couple_arm = -1._ReKi*MeshMap%MapMotions(i)%couple_arm + end do + + +END SUBROUTINE CreateMotionMap_P_to_L2 + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given two point meshes, this routine transfers the source mesh values to the destination mesh using appropriate math. +SUBROUTINE Transfer_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source point mesh + TYPE(MeshType), INTENT(INOUT) :: Dest !< destination point mesh + TYPE(MeshType), OPTIONAL,INTENT(IN ) :: SrcDisp !< an optional mesh, which contains the displacements associated with the source if the source contains load information + TYPE(MeshType), OPTIONAL,INTENT(IN ) :: DestDisp !< an optional mesh, which contains the displacements associated with the destination if the destination contains load information + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< Mapping(s) between Src and Dest meshes + + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_Point_to_Point' + + REAL(ReKi) :: LoadsScaleFactor ! bjj: added this scaling factor to get loads in a better numerical range + + + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + !................. + ! Check to ensure that both the source and destination meshes are composed of Point elements + !................. + + if (Src%ElemTable(ELEMENT_POINT)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Source mesh must have one or more Point elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Dest%ElemTable(ELEMENT_POINT)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must have one or more Point elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + + !> ------------------------------------------------------------------------------------------------------------------------------ + !! Mapping and Transfer of Data for Mesh Motion and Scalar Fields + !! ------------------------------------------------------------------------------------------------------------------------------ + !! If Src is displacements/velocities then loop over the Destination Mesh; + !! each motion/scalar in the destination mesh needs to be interpolated from the source mesh. + + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + ! Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + ! Transfer data + !........................ + + CALL Transfer_Motions_Point_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if ! algorithm for motions/scalars + + !> ------------------------------------------------------------------------------------------------------------------------------ + !! Mapping and Transfer of Data for Mesh Load Fields + !! ------------------------------------------------------------------------------------------------------------------------------ + !! IF Src is forces and/or moments, loop over Src Mesh; + !! each load in the source mesh needs to be placed somewhere in the destination mesh. + + if ( HasLoadFields(Src) ) then + + !........................ + ! Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Transfer_Point_to_Point:CreateLoadMap_P_to_P') + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + ! Transfer data + !........................ + + IF ( PRESENT( SrcDisp ) .AND. PRESENT( DestDisp ) ) THEN + + LoadsScaleFactor = GetLoadsScaleFactor ( Src ) + + CALL Transfer_Loads_Point_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2, SrcDisp, DestDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ELSE !bjj: we could check if Src also had TranslationDisp fields and call with SrcDisp=Src + CALL SetErrStat( ErrID_Fatal, 'Invalid arguments to Transfer_Point_to_Point for meshes with load fields.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + end if ! algorithm for loads + + + +END SUBROUTINE Transfer_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine creates the node-to-node (nearest neighbor). We map FROM Mesh1 to Mesh2 +SUBROUTINE CreateMapping_NearestNeighbor( Mesh1, Mesh2, NodeMap, Mesh1_TYPE, Mesh2_TYPE, ErrStat, ErrMsg ) +!....................................................................................... + TYPE(MeshType), INTENT(IN ) :: Mesh1 !< The mesh in the outer mapping loop (Dest for Motions/Scalars; Src for Loads) + TYPE(MeshType), INTENT(IN ) :: Mesh2 !< The mesh in the inner mapping loop (Src for Motions/Scalars; Dest for Loads) + + TYPE(MapType), INTENT(INOUT) :: NodeMap(:) !< The mapping from Src to Dest + + INTEGER(IntKi), INTENT(IN ) :: Mesh1_TYPE !< Type of Mesh1 elements to map + INTEGER(IntKi), INTENT(IN ) :: Mesh2_TYPE !< Type of Mesh2 elements on map + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + REAL(ReKi) :: dist + REAL(ReKi) :: min_dist + + REAL(ReKi) :: Mesh1_xyz(3) + REAL(ReKi) :: Mesh2_xyz(3) + + INTEGER(IntKi) :: point_with_min_dist + INTEGER(IntKi) :: iElem, iNode, i ! do-loop counter for elements on Mesh1, associated node(S) + INTEGER(IntKi) :: jElem, jNode, j ! do-loop counter for elements on Mesh2, associated node + + LOGICAL :: UseMesh2Node(Mesh2%NNodes) ! determines if the node on the second mesh is part of the mapping (i.e., contained in an element of the appropriate type) + + + ! initialization + ErrStat = ErrID_None + ErrMsg = "" + + ! Determine which nodes on mesh2 are going to be in the mapping + UseMesh2Node = .FALSE. + do jElem = 1, Mesh2%ElemTable(Mesh2_TYPE)%nelem ! number of point elements on Mesh2 + do jNode = 1, SIZE( Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes ) + UseMesh2Node( Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(jNode) ) = .TRUE. + end do + end do + + ! Map the source nodes to destination nodes: + do i=1,size(NodeMap) + NodeMap(i)%OtherMesh_Element = NODE_NOT_MAPPED ! initialize this so we know if we've mapped this node already (done only because we may have different elements) + end do !n1 + + + do iElem = 1, Mesh1%ElemTable(Mesh1_TYPE)%nelem ! number of Mesh1_TYPE elements on Mesh1 = number of points on Mesh1 + do iNode = 1, SIZE( Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes ) + i = Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes(iNode) ! the nodes on element iElem + IF ( NodeMap(i)%OtherMesh_Element > 0 ) CYCLE ! we already mapped this node; let's move on + + + ! Find the nearest neighbor node for this particular node + + ! initialize minimum distance marker at some huge number + min_dist = HUGE(min_dist) + point_with_min_dist = 0 + + Mesh1_xyz = Mesh1%Position(:, i) + + do j = 1, Mesh2%NNodes + IF ( .NOT. UseMesh2Node(j) ) CYCLE !This node isn't part of the elements we're mapping + + ! destination point + Mesh2_xyz = Mesh2%Position(:, j) + + ! calculate distance between source and desination; will only store information once we have determined + ! the closest point + dist = sqrt( (Mesh1_xyz(1) - Mesh2_xyz(1))**2 & + + (Mesh1_xyz(2) - Mesh2_xyz(2))**2 & + + (Mesh1_xyz(3) - Mesh2_xyz(3))**2 ) + + if (dist .lt. min_dist) then + + min_dist = dist + point_with_min_dist = j + + !if (EqualRealNos(dist), 0.0_ReKi)) EXIT !we have an exact match so let's just stop looking + + endif + + end do !j + + if (point_with_min_dist .lt. 1 ) then + CALL SetErrStat( ErrID_Fatal, 'Failed to find destination point associated with source point.', ErrStat, ErrMsg, 'CreateMapping_NearestNeighbor') + RETURN + endif + + NodeMap(i)%OtherMesh_Element = point_with_min_dist !bjj: For consistency, I really wish we had used element numbers here instead.... + + NodeMap(i)%distance = min_dist + + NodeMap(i)%couple_arm = Mesh2%Position(:, point_with_min_dist) - Mesh1_xyz + !bjj: this is the negative of the case where it's Mesh2=src, so we'll have to multiply by -1 outside this routine if that's the case + + end do !iNode + end do !iElem + + +END SUBROUTINE CreateMapping_NearestNeighbor +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a nearest-neighbor mapping, this routine transfers motions between nodes on the mesh. +SUBROUTINE Transfer_Motions_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh with motion fields allocated + TYPE(MeshType), INTENT(INOUT) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< data for the mesh mapping + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: nScalars + INTEGER(IntKi) :: i, j ! counter over the nodes + REAL(R8Ki) :: RotationMatrix(3,3) + REAL(ReKi) :: TmpVec(3) + + + ErrStat = ErrID_None + ErrMsg = "" + + + + ! ---------------------------- Translation ------------------------------------------------ + !> Translational Displacement: \f$\vec{u}^D = \vec{u}^S + \left[\left[\theta^S\right]^T \theta^{SR} - I\right]\left\{\vec{p}^{ODR}-\vec{p}^{OSR}\right\}\f$ + + ! u_Dest = u_Src + [Orientation_Src^T * RefOrientation_Src - I] * [p_Dest - p_Src] + if ( Src%FieldMask(MASKID_TranslationDisp) .AND. Dest%FieldMask(MASKID_TranslationDisp) ) then + do i=1, Dest%Nnodes + if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%TranslationDisp(:,i) = Src%TranslationDisp(:,MeshMap%MapMotions(i)%OtherMesh_Element) + + ! if Src mesh has orientation, superpose Dest displacement with translation due to rotation and couple arm + if ( Src%FieldMask(MASKID_Orientation) ) then + + !Calculate RotationMatrix as O_S^T*O_SR + RotationMatrix = TRANSPOSE( Src%Orientation(:,:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + RotationMatrix = MATMUL( RotationMatrix, Src%RefOrientation(:,:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + + ! subtract I + do j=1,3 + RotationMatrix(j,j)= RotationMatrix(j,j) - 1.0_R8Ki + end do + + + Dest%TranslationDisp(:,i) = Dest%TranslationDisp(:,i) + MATMUL(RotationMatrix, MeshMap%MapMotions(i)%couple_arm) + + end if + + end do + + end if + + + ! ---------------------------- ORIENTATION/Direction Cosine Matrix ---------------------- + !> Orientation: \f$\theta^D = \theta^{DR}\left[\theta^{SR}\right]^T\theta^S\f$ + + ! transfer direction cosine matrix, aka orientation + + if ( Src%FieldMask(MASKID_Orientation) .AND. Dest%FieldMask(MASKID_Orientation) ) then + + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + RotationMatrix = TRANSPOSE( Src%RefOrientation(:,:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + RotationMatrix = MATMUL( Dest%RefOrientation(:,:,i), RotationMatrix ) + Dest%Orientation(:,:,i) = MATMUL( RotationMatrix, Src%Orientation(:,:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + end do + + endif + + ! ---------------------------- Calculated total displaced positions --------------------- + ! these values are used in both the translational velocity and translational acceleration + ! calculations. The calculations rely on the TranslationDisp fields, which are calculated + ! earlier in this routine. + IF ( Src%FieldMask(MASKID_TranslationVel) .OR. Src%FieldMask(MASKID_TranslationAcc) ) THEN + + DO i = 1,Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + MeshMap%DisplacedPosition(:,i,1) = Src%TranslationDisp(:,MeshMap%MapMotions(i)%OtherMesh_Element) & + - Dest%TranslationDisp(:,i) & + - MeshMap%MapMotions(i)%couple_arm + END DO + + END IF + + ! ---------------------------- TranslationVel -------------------------------------------- + !> Translational Velocity: \f$\vec{v}^D = \vec{v}^S + !! + \left\{ \left\{ \vec{p}^{OSR} + \vec{u}^S \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\omega}^S\f$ + + if ( Src%FieldMask(MASKID_TranslationVel) .AND. Dest%FieldMask(MASKID_TranslationVel) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%TranslationVel(:,i) = Src%TranslationVel(:,MeshMap%MapMotions(i)%OtherMesh_Element) + + if ( Src%FieldMask(MASKID_RotationVel) ) then + Dest%TranslationVel(:,i) = Dest%TranslationVel(:,i) + & + cross_product ( MeshMap%DisplacedPosition(:,i,1), & + Src%RotationVel(:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + endif + end do + + endif + + ! ---------------------------- RotationVel ----------------------------------------------- + !> Rotational Velocity: \f$\vec{\omega}^D = \vec{\omega}^S\f$ + + if ( Src%FieldMask(MASKID_RotationVel) .AND. Dest%FieldMask(MASKID_RotationVel) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%RotationVel(:,i) = Src%RotationVel(:,MeshMap%MapMotions(i)%OtherMesh_Element) + end do + end if + + ! ---------------------------- TranslationAcc ----------------------------------------------- + !> Translational Acceleration: \f$\vec{a}^D = \vec{a}^S + !! + \left\{ \left\{ \vec{p}^{OSR} + \vec{u}^S \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\alpha}^S + !! + \vec{\omega}^S \times \left\{ + !! \left\{ \left\{ \vec{p}^{OSR} + \vec{u}^S \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{\omega}^S + !! \right\} + !!\f$ + + if ( Src%FieldMask(MASKID_TranslationAcc) .AND. Dest%FieldMask(MASKID_TranslationAcc) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%TranslationAcc(:,i) = Src%TranslationAcc(:,MeshMap%MapMotions(i)%OtherMesh_Element) + + if ( Src%FieldMask(MASKID_RotationAcc) ) then + Dest%TranslationAcc(:,i) = Dest%TranslationAcc(:,i) + & + cross_product( MeshMap%DisplacedPosition(:,i,1), & + Src%RotationAcc(:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + endif + + if ( Src%FieldMask(MASKID_RotationVel) ) then + TmpVec = cross_product( MeshMap%DisplacedPosition(:,i,1), Src%RotationVel(:,MeshMap%MapMotions(i)%OtherMesh_Element) ) + + Dest%TranslationAcc(:,i) = Dest%TranslationAcc(:,i) + & + cross_product( Src%RotationVel(:,MeshMap%MapMotions(i)%OtherMesh_Element), TmpVec) + endif + end do + endif + + ! ---------------------------- RotationAcc ----------------------------------------------- + !> Rotational Acceleration: \f$\vec{\alpha}^D = \vec{\alpha}^S\f$ + + if (Src%FieldMask(MASKID_RotationAcc) .AND. Dest%FieldMask(MASKID_RotationAcc) ) then + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%RotationAcc(:,i) = Src%RotationAcc(:,MeshMap%MapMotions(i)%OtherMesh_Element) + end do + end if + + ! ---------------------------- Scalars ----------------------------------------------- + !> Scalars: \f$S^D = S^S\f$ + + if (Src%FieldMask(MASKID_SCALAR) .AND. Dest%FieldMask(MASKID_SCALAR) ) then + nScalars = min(Dest%nScalars, Src%nScalars) + + if (Dest%nScalars > nScalars) then + call SetErrStat(ErrID_Severe, "Not all scalars could be computed from source mesh (insufficient data).", ErrStat, ErrMsg, 'Transfer_Motions_Point_to_Point') + Dest%Scalars(nScalars+1:,:) = 0.0_ReKi + end if + + do i=1, Dest%Nnodes + !if ( MeshMap%MapMotions(i)%OtherMesh_Element < 1 ) CYCLE + + Dest%Scalars(1:nScalars,i) = Src%Scalars(1:nScalars,MeshMap%MapMotions(i)%OtherMesh_Element) + end do + end if + + +END SUBROUTINE Transfer_Motions_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a nearest-neighbor mapping, this routine forms the linearization matrices of motion transfer between nodes on the mesh. +SUBROUTINE Linearize_Motions_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh with motion fields allocated + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< data for the mesh mapping + + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'Linearize_Motions_Point_to_Point' + + integer(intKi) :: i,j,k, n, d_start, d_end, s_start, s_end + real(r8Ki) :: tmp, tmpVec(3), SSMat(3,3) + real(r8Ki) :: RotVel(3), RotAcc(3) + + + + ErrStat = ErrID_None + ErrMsg = "" + + + + if (.not. allocated(MeshMap%dM%mi) ) then + call AllocAry(MeshMap%dM%mi, Dest%Nnodes*3, Src%Nnodes*3, 'dM%mi', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%mi = 0.0_R8Ki + do i=1, Dest%Nnodes + + n = MeshMap%MapMotions(i)%OtherMesh_Element + do j=1,3 + MeshMap%dM%mi( (i-1)*3+j, (n-1)*3+j ) = 1.0_R8Ki + end do + end do + + + if ( (Src%FieldMask(MASKID_TranslationDisp) .AND. Dest%FieldMask(MASKID_TranslationDisp)) & + .or. (Src%FieldMask(MASKID_TranslationVel ) .AND. Dest%FieldMask(MASKID_TranslationVel )) & + .or. (Src%FieldMask(MASKID_TranslationAcc ) .AND. Dest%FieldMask(MASKID_TranslationAcc )) ) then + + + ! calculate displaced positions at operating point: + DO i = 1,Dest%Nnodes + MeshMap%DisplacedPosition(:,i,1) = Src%TranslationDisp(:,MeshMap%MapMotions(i)%OtherMesh_Element) & + - Dest%TranslationDisp(:,i) & + - MeshMap%MapMotions(i)%couple_arm + END DO + + ! MeshMap%dM%fx_p required for all three transfers: + if (.not. allocated(MeshMap%dM%fx_p) ) then + call AllocAry(MeshMap%dM%fx_p, Dest%Nnodes*3, Src%Nnodes*3, 'dM%fx_p', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%fx_p = 0.0_R8Ki + do i=1, Dest%Nnodes + + d_start = (i-1)*3+1 + d_end = d_start+2 + s_start = (MeshMap%MapMotions(i)%OtherMesh_Element - 1)*3+1 + s_end = s_start+2 + MeshMap%dM%fx_p( d_start:d_end, s_start:s_end ) = SkewSymMat( MeshMap%DisplacedPosition(:,i,1) ) + end do + + + ! MeshMap%dM%tv_uS and MeshMap%dM%tv_uD required for translational velocity: + if ( Src%FieldMask(MASKID_TranslationVel) .AND. Dest%FieldMask(MASKID_TranslationVel) ) then + + if ( Src%FieldMask(MASKID_RotationVel) ) then + + if (.not. allocated(MeshMap%dM%tv_uD) ) then + call AllocAry(MeshMap%dM%tv_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%tv_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + if (.not. allocated(MeshMap%dM%tv_uS) ) then + call AllocAry(MeshMap%dM%tv_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%tv_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%tv_uD = 0.0_R8Ki + MeshMap%dM%tv_uS = 0.0_R8Ki + do i=1, Dest%Nnodes + + n = MeshMap%MapMotions(i)%OtherMesh_Element + d_start = (i-1)*3+1 + d_end = d_start+2 + + s_start = (n - 1)*3+1 + s_end = s_start+2 + + RotVel = Src%RotationVel(:,n) + SSMat = SkewSymMat( RotVel ) + MeshMap%dM%tv_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%tv_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%tv_uS( d_start:d_end, s_start:s_end ) = -SSMat + + end do + else + if (allocated(MeshMap%dM%tv_uD)) deallocate(MeshMap%dM%tv_uD) + if (allocated(MeshMap%dM%tv_uS)) deallocate(MeshMap%dM%tv_uS) + end if !MASKID_RotationVel + else + if (allocated(MeshMap%dM%tv_uD)) deallocate(MeshMap%dM%tv_uD) + if (allocated(MeshMap%dM%tv_uS)) deallocate(MeshMap%dM%tv_uS) + end if !MASKID_TranslationVel + + + if ( Src%FieldMask(MASKID_TranslationAcc ) .AND. Dest%FieldMask(MASKID_TranslationAcc ) ) then + + !-------------- ta_uD and ta_uS ----------------------------- + ! these are the matrix that relates destination and source displacements to translational acceleration + + if (.not. allocated(MeshMap%dM%ta_uD) ) then + call AllocAry(MeshMap%dM%ta_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%ta_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + if (.not. allocated(MeshMap%dM%ta_uS) ) then + call AllocAry(MeshMap%dM%ta_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%ta_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%ta_uD = 0.0_R8Ki + MeshMap%dM%ta_uS = 0.0_R8Ki + if ( Src%FieldMask(MASKID_RotationAcc) ) then + do i=1, Dest%Nnodes + + n = MeshMap%MapMotions(i)%OtherMesh_Element + d_start = (i-1)*3+1 + d_end = d_start+2 + s_start = (n-1)*3+1 + s_end = s_start+2 + + RotAcc = Src%RotationAcc(:,n) + SSMat = SkewSymMat( RotAcc ) + MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) = -SSMat + + end do + end if + + if ( Src%FieldMask(MASKID_RotationVel) ) then + + do i=1, Dest%Nnodes + + n = MeshMap%MapMotions(i)%OtherMesh_Element + d_start = (i-1)*3+1 + d_end = d_start+2 + s_start = (n-1)*3+1 + s_end = s_start+2 + + RotVel = Src%RotationVel(:,n) + SSMat = OuterProduct( RotVel, RotVel ) + tmp = dot_product( RotVel, RotVel ) + do k=1,3 + SSMat(k,k) = SSMat(k,k) - tmp + end do + + MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%ta_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) = MeshMap%dM%ta_uS( d_start:d_end, s_start:s_end ) - SSMat + end do + end if + + + !-------------- ta_rv ----------------------------- + ! this is the matrix that relates rotational velocity to translational acceleration + if ( Src%FieldMask(MASKID_RotationVel) ) then + + if (.not. allocated(MeshMap%dM%ta_rv) ) then + call AllocAry(MeshMap%dM%ta_rv, Dest%Nnodes*3, Src%Nnodes*3, 'dM%ta_rv', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%ta_rv = 0.0_R8Ki + do i=1, Dest%Nnodes + + n = MeshMap%MapMotions(i)%OtherMesh_Element + d_start = (i-1)*3+1 + d_end = d_start+2 + s_start = (n - 1)*3+1 + s_end = s_start+2 + + RotVel = Src%RotationVel(:,n) + tmpVec = cross_product( RotVel, MeshMap%DisplacedPosition(:,i,1) ) + + MeshMap%dM%ta_rv( d_start:d_end, s_start:s_end ) = SkewSymMat( tmpVec ) + & + OuterProduct( MeshMap%DisplacedPosition(:,i,1), RotVel ) + + tmp=dot_product( MeshMap%DisplacedPosition(:,i,1), RotVel ) + do j=0,2 + MeshMap%dM%ta_rv( d_start+j, s_start+j ) = MeshMap%dM%ta_rv( d_start+j, s_start+j ) - tmp + end do + + end do + else + if (allocated(MeshMap%dM%ta_rv)) deallocate(MeshMap%dM%ta_rv) + end if ! MASKID_RotationVel + + else + if (allocated(MeshMap%dM%ta_uD)) deallocate(MeshMap%dM%ta_uD) + if (allocated(MeshMap%dM%ta_uS)) deallocate(MeshMap%dM%ta_uS) + if (allocated(MeshMap%dM%ta_rv)) deallocate(MeshMap%dM%ta_rv) + end if ! MASKID_TranslationAcc + + end if ! MASKID_TranslationDisp, MASKID_RotationVel, or MASKID_TranslationAcc + + +END SUBROUTINE Linearize_Motions_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a nearest-neighbor mapping, this routine transfers loads between point nodes on the meshes. +SUBROUTINE Transfer_Loads_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp,LoadsScaleFactor ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh with loads fields allocated + TYPE(MeshType), INTENT(INOUT) :: Dest !< The destination mesh + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< A mesh that contains the displacements associated with the source mesh + TYPE(MeshType), INTENT(IN ) :: DestDisp !< A mesh that contains the displacements associated with the destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data structure (from Dest to Src) + REAL(ReKi), INTENT(IN) :: LoadsScaleFactor !< Scaling factor for loads (to help with numerical issues) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables +! REAL(R8Ki) :: RotationMatrix(3,3) + REAL(ReKi) :: torque(3), DisplacedPosition(3) + INTEGER(IntKi) :: i ! counter over the nodes + + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Force: \f$\vec{F}^D = \sum\limits_{eS} \vec{F}^S \f$ + + !> Moment: \f$\vec{M}^D = \sum\limits_{eS} \left\{ \vec{M}^S + !! + \left\{ \left\{ \vec{p}^{OSR} + \vec{u}^S \right\} - \left\{ \vec{p}^{ODR} + \vec{u}^D \right\} \right\} \times \vec{F}^S \right\}\f$ + + +!bjj note that we already checked that the following two conditions apply in this case: +! if Src%FieldMask(MASKID_FORCE), Dest%FieldMask(MASKID_FORCE) and Dest%FieldMask(MASKID_MOMENT) +! if Src%FieldMask(MASKID_MOMENT), Dest%FieldMask(MASKID_MOMENT) + + if (Dest%FieldMask(MASKID_MOMENT) ) Dest%Moment = 0. ! whole array initialization; required to handle superposition of moments + + if (Src%FieldMask(MASKID_FORCE) ) THEN + Dest%Force = 0. ! whole array initialization; required to handle superposition of forces + do i = 1, Src%NNodes + !if ( MeshMap%MapLoads(i)%OtherMesh_Element < 1 ) CYCLE ! would only happen if we had non-point elements (or nodes not contained in an element) + + ! F_d += F_s + Dest%Force(:,MeshMap%MapLoads(i)%OtherMesh_Element) = Dest%Force(:,MeshMap%MapLoads(i)%OtherMesh_Element) + (Src%Force(:,i) / LoadsScaleFactor) + end do + Dest%Force = Dest%Force * LoadsScaleFactor + + + ! M_d += torque + if ( Dest%FieldMask(MASKID_MOMENT) ) then + + ! if the distance (which can never be less than zero) is greater than "zero" and there is a + ! force in the source mesh, then we need to add a moment to the destination mesh to account + ! for the mismatch between points + + do i = 1, Src%NNodes + DisplacedPosition = SrcDisp%TranslationDisp(:,i) + SrcDisp%Position(:,i) & + - ( DestDisp%TranslationDisp(:,MeshMap%MapLoads(i)%OtherMesh_Element) & + + DestDisp%Position( :,MeshMap%MapLoads(i)%OtherMesh_Element) ) + ! calculation torque vector based on offset force: torque = couple_arm X Force + torque = Src%Force(:,i) / LoadsScaleFactor !not torque yet, but we're doing this cross product in two step to avoid tempoary memory storage + torque = CROSS_PRODUCT( DisplacedPosition, torque ) + Dest%Moment(:,MeshMap%MapLoads(i)%OtherMesh_Element) = Dest%Moment(:,MeshMap%MapLoads(i)%OtherMesh_Element) + torque + enddo + endif + + end if + + + if (Src%FieldMask(MASKID_MOMENT) ) then + + ! M_d += M_s + do i = 1, Src%NNodes + !if ( MeshMap%MapLoads(i)%OtherMesh_Element < 1 ) CYCLE ! would only happen if we had non-point elements (or nodes not contained in an element) + + Dest%Moment(:,MeshMap%MapLoads(i)%OtherMesh_Element) = Dest%Moment(:,MeshMap%MapLoads(i)%OtherMesh_Element) + (Src%Moment(:,i) / LoadsScaleFactor) + end do + + endif + + if (Dest%FieldMask(MASKID_MOMENT) ) Dest%Moment = Dest%Moment * LoadsScaleFactor + +END SUBROUTINE Transfer_Loads_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a nearest-neighbor mapping, this routine generates the linearization matrices for loads transfer between point nodes on the meshes. +SUBROUTINE Linearize_Loads_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh with loads fields allocated + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< A mesh that contains the displacements associated with the source mesh + TYPE(MeshType), INTENT(IN ) :: DestDisp !< A mesh that contains the displacements associated with the destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data structure (from Dest to Src) + + 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,j,n, d_start, d_end, s_start, s_end + real(r8Ki) :: DisplacedPosition(3), SSmat(3,3) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Linearize_Loads_Point_to_Point' + + + ErrStat = ErrID_None + ErrMsg = "" + + !> Matrix \f$ M_{li}^D = M_{li} \f$, stored in modmesh_mapping::meshmaplinearizationtype::li, + !! is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! This is the matrix that maps each field of the source mesh to an augmented mesh. + + ! identity for forces and/or moments: + if (.not. allocated(MeshMap%dM%li) ) then + call AllocAry(MeshMap%dM%li, Dest%Nnodes*3, Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(MeshMap%dM%li,1) /= Dest%Nnodes*3 .or. size(MeshMap%dM%li,2) /= Src%Nnodes*3) then + deallocate(MeshMap%dM%li) + call AllocAry(MeshMap%dM%li, Dest%Nnodes*3, Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%li = 0.0_R8Ki + do i = 1, Src%NNodes + !if ( MeshMap%MapLoads(i)%OtherMesh_Element < 1 ) CYCLE ! would only happen if we had non-point elements (or nodes not contained in an element) + + n = MeshMap%MapLoads(i)%OtherMesh_Element + do j=1,3 + MeshMap%dM%li( (n-1)*3+j, (i-1)*3+j ) = 1.0_R8Ki + end do + end do + + + ! M_uD, M_uS, and m_f for moments: + + if (Dest%FieldMask(MASKID_MOMENT) .AND. Src%FieldMask(MASKID_FORCE) ) then + + !> Matrix \f$ M_{uD}^D \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_ud, + !! is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! This is the block matrix that maps the destination translation displacement field + !! of the source mesh to the moment field of the destination mesh. + + if (.not. allocated(MeshMap%dM%M_uD) ) then + call AllocAry(MeshMap%dM%M_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%M_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(MeshMap%dM%M_uD,1) /= Dest%Nnodes*3 .or. size(MeshMap%dM%M_uD,2) /= Dest%Nnodes*3) then + deallocate(MeshMap%dM%M_uD) + call AllocAry(MeshMap%dM%M_uD, Dest%Nnodes*3, Dest%Nnodes*3, 'dM%M_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + !> Matrix \f$ M_{uS}^D \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_us, + !! is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! This is the block matrix that maps the source translation displacement field + !! of the source mesh to the moment field of the destination mesh. + + if (.not. allocated(MeshMap%dM%M_uS) ) then + call AllocAry(MeshMap%dM%M_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%M_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(MeshMap%dM%M_uS,1) /= Dest%Nnodes*3 .or. size(MeshMap%dM%M_uS,2) /= Src%Nnodes*3) then + deallocate(MeshMap%dM%M_uS) + call AllocAry(MeshMap%dM%M_uS, Dest%Nnodes*3, Src%Nnodes*3, 'dM%M_uS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + MeshMap%dM%M_uD = 0.0_R8Ki + MeshMap%dM%M_uS = 0.0_R8Ki + + do i = 1, Src%NNodes + n = MeshMap%MapLoads(i)%OtherMesh_Element + + s_start = (i-1)*3+1 + s_end = s_start+2 + + d_start = (n-1)*3+1 + d_end = d_start+2 + + SSMat = SkewSymMat( Src%Force(:,i) ) + + MeshMap%dM%M_uD( d_start:d_end, d_start:d_end ) = MeshMap%dM%M_uD( d_start:d_end, d_start:d_end ) + SSMat + MeshMap%dM%M_uS( d_start:d_end, s_start:s_end ) = MeshMap%dM%M_uS( d_start:d_end, s_start:s_end ) - SSMat + + end do + + !> > Matrix \f$ M_{fm}^D \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_f, + !! > is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the block matrix that maps the force field of the source mesh to the moment field of the destination mesh. + + if (.not. allocated(MeshMap%dM%m_f) ) then + call AllocAry(MeshMap%dM%m_f, Dest%Nnodes*3, Src%Nnodes*3, 'dM%m_f', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(MeshMap%dM%m_f,1) /= Dest%Nnodes*3 .or. size(MeshMap%dM%m_f,2) /= Src%Nnodes*3) then + deallocate(MeshMap%dM%m_f) + call AllocAry(MeshMap%dM%m_f, Dest%Nnodes*3, Src%Nnodes*3, 'dM%m_f', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + MeshMap%dM%m_f = 0.0_R8Ki + + do i = 1, Src%NNodes + n = MeshMap%MapLoads(i)%OtherMesh_Element + + s_start = (i-1)*3+1 + s_end = s_start+2 + + d_start = (n-1)*3+1 + d_end = d_start+2 + + DisplacedPosition = SrcDisp%TranslationDisp(:,i) + SrcDisp%Position(:,i) & + - ( DestDisp%TranslationDisp(:,n) + DestDisp%Position(:,n) ) + + MeshMap%dM%m_f( d_start:d_end, s_start:s_end ) = SkewSymMat( DisplacedPosition ) + + end do + + endif + + +END SUBROUTINE Linearize_Loads_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +! This routine computes a scaling factor for loads fields to reduce numerical problems in computions that involve accelerations +! and forces/moments. +FUNCTION GetLoadsScaleFactor( Src ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh with loads fields allocated + REAL(ReKi) :: GetLoadsScaleFactor !< scaling factor for loads fields + + + ! LOCAL: + INTEGER :: I, j + REAL(ReKi) :: MaxLoad + + + GetLoadsScaleFactor = 1.0 + MaxLoad = 0.0 + + IF ( Src%FIELDMASK( MASKID_FORCE ) ) THEN + + DO I=1,Src%Nnodes + DO J=1,3 + MaxLoad = MAX(MaxLoad, ABS(Src%Force(j,I) ) ) + END DO + END DO + + END IF + + + IF ( Src%FIELDMASK( MASKID_MOMENT ) ) THEN + + DO I=1,Src%Nnodes + DO J=1,3 + MaxLoad = MAX(MaxLoad, ABS(Src%Moment(j,I) ) ) + END DO + END DO + + END IF + + IF ( MaxLoad > 10. ) THEN + GetLoadsScaleFactor = 10**MIN( NINT(log10(MaxLoad)), 15 ) ! Let's not get carried away and cause overflow; 10E15 is as far as we'll go + END IF + + +END FUNCTION GetLoadsScaleFactor +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateLoadMap_P_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! in following call, Src is mesh to loop over, finding a corresponding point for each point in Dest + CALL CreateMapping_NearestNeighbor( Src, Dest, MeshMap%MapLoads, ELEMENT_POINT, ELEMENT_POINT, ErrStat, ErrMsg ) + +END SUBROUTINE CreateLoadMap_P_to_P +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + + 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 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! in following call, Dest is mesh to looped over, finding a corresponding point for each point in Src + CALL CreateMapping_NearestNeighbor( Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ELEMENT_POINT, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_P_to_P') + IF (ErrStat >= AbortErrLev) RETURN + + ! bjj: for consistant definition of couple_arm (i.e. p_ODR-p_OSR), let's multiply by -1 + do i=1,SIZE(MeshMap%MapMotions) + MeshMap%MapMotions(i)%couple_arm = -1.0_ReKi*MeshMap%MapMotions(i)%couple_arm + end do + +END SUBROUTINE CreateMotionMap_P_to_P +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that transfers data from a line2 mesh to another line2 mesh. +SUBROUTINE Transfer_Line2_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source Line2 mesh + TYPE(MeshType), INTENT(INOUT) :: Dest !< destination Line2 mesh + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp !< a "functional" sibling of the source mesh; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: DestDisp !< a "functional" sibling of the destination mesh; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping between Src and Dest meshes + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(ReKi) :: LoadsScaleFactor ! Scaling factor for loads (to help with numerical issues) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_Line2_to_Line2' + + ErrStat = ErrID_None + ErrMsg = '' + + !................. + ! Check to ensure that both the source and destination meshes are composed of Line2 elements + !................. + if (Src%ElemTable(ELEMENT_LINE2)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Source mesh must have one or more Line2 elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Dest%ElemTable(ELEMENT_LINE2)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must have one or more Line2 elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + ! Start: Create Mapping data (if remap is true) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !remapping + + !........................ + ! Start: Transfer data + !........................ + + CALL Transfer_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !algorithm for motions/scalars + + + ! ------------------------------------------------------------------------------------------------------------------------------ + ! Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasLoadFields(Src) ) then + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + !................. + ! other checks for available mesh fields (now done in AllocMapping routine) + !................. + + + !........................ + ! Create mapping + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + ! Transfer data + !........................ + + LoadsScaleFactor = GetLoadsScaleFactor ( Src ) + + ! first, we take the source fields and transfer them to fields on the augmented source mesh: + ! (we're also taking the SrcDisp field and putting it on our augmented mesh) + CALL Transfer_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat2, ErrMsg2, SrcDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ! then we lump the loads from the augmented source mesh: + CALL Lump_Line2_to_Point( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, ErrStat2, ErrMsg2, LoadsScaleFactor=LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + CALL Transfer_Loads_Point_to_Line2( MeshMap%Lumped_Points_Src, Dest, MeshMap, ErrStat2, ErrMsg2, MeshMap%Augmented_Ln2_Src, DestDisp, LoadsScaleFactor ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + end if ! algorithm for loads + + +END SUBROUTINE Transfer_Line2_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that computes the linearization matrices for data transfers from a mesh to a line2 mesh. +!! Mapping equations are as follows: +!! +!! Rotational Displacement: \f$ \frac{\partial M_\Lambda}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$ \left\{ \vec{\theta}^S\right\}\f$ +!! +!! Translational Displacement: \f$ \frac{\partial M_u}{\partial x} = \begin{bmatrix} M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^S \\ +!! \vec{\theta}^S +!! \end{matrix} \right\} \f$ +!! +!! Rotational Velocity: \f$ \frac{\partial M_\omega}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{\omega}^S\right\}\f$ +!! +!! Translational Velocity: \f$ \frac{\partial M_v}{\partial x} = \begin{bmatrix} M_{tv\_uD} & M_{tv\_uS} & M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{v}^S \\ +!! \vec{\omega}^S +!! \end{matrix} \right\} \f$ +!! +!! Rotational Acceleration: \f$ \frac{\partial M_\alpha}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{\alpha}^S\right\}\f$ +!! +!! Translational Acceleration: \f$ \frac{\partial M_a}{\partial x} = \begin{bmatrix} M_{ta\_uD} & M_{ta\_uS} & M_{ta\_rv} & M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{\omega}^S \\ +!! \vec{a}^S \\ +!! \vec{\alpha}^S +!! \end{matrix} \right\} \f$ +!! +!! Scalar quantities: \f$ \frac{\partial M_S}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{S}^S\right\}\f$ +!! +!! Forces: \f$ \frac{\partial M_f}{\partial x} = \begin{bmatrix} M_{li} \end{bmatrix} \f$ for source fields \f$\left\{\vec{f}^S\right\}\f$ +!! +!! Moments: \f$ \frac{\partial M_m}{\partial x} = \begin{bmatrix} M_{uDm} & M_{uSm} & M_{fm} & M_{li} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{f}^S \\ +!! \vec{m}^S +!! \end{matrix} \right\} \f$ +!! +!! \f$M_{mi}\f$ is modmesh_mapping::meshmaplinearizationtype::mi \n +!! \f$M_{f_{\times p}}\f$ is modmesh_mapping::meshmaplinearizationtype::fx_p \n +!! \f$M_{tv\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uD \n +!! \f$M_{tv\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uS \n +!! \f$M_{ta\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uD \n +!! \f$M_{ta\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uS \n +!! \f$M_{ta\_rv}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_rv \n +!! \f$M_{li}\f$ is modmesh_mapping::meshmaplinearizationtype::li \n +!! \f$M_{uSm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_us \n +!! \f$M_{uDm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_ud \n +!! \f$M_{fm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_f +SUBROUTINE Linearize_Line2_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source Line2 mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< destination mesh + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp !< a "functional" sibling of the source mesh; Src contains loads and SrcDisp contains TranslationDisp and Orientation + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: DestDisp !< a "functional" sibling of the destination mesh; Dest contains loads and DestDisp contains TranslationDisp and Orientation + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping between Src and Dest meshes + + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'Linearize_Line2_to_Line2' + + real(R8Ki), allocatable :: M_A(:,:) ! linearization matrix for augmented source mesh + real(R8Ki), allocatable :: M_SL_fm(:,:) ! linearization matrix for source-mesh lumped force component of moment + real(R8Ki), allocatable :: M_SL_uSm(:,:) ! linearization matrix for source-mesh lumped translational displacement component of moment + real(R8Ki), allocatable :: M_SL_li(:,:) ! linearization matrix for source-mesh lumped load "identity" component + + ErrStat = ErrID_None + ErrMsg = '' + + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Linearization of Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + !> * Create mapping (if remap is true) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !remapping + + !........................ + !> * Get linearization matrices of data transfer + !........................ + + CALL Linearize_Motions_Line2_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + endif !algorithm for motions/scalars + + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Linearization of Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + if ( HasLoadFields(Src) ) then + + IF (.not. PRESENT(SrcDisp) .OR. .NOT. PRESENT(DestDisp) ) THEN + CALL SetErrStat( ErrID_Fatal, 'SrcDisp and DestDisp arguments are required for load transfer linearization.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + !................. + ! other checks for available mesh fields (now done in AllocMapping routine) + !................. + + + !........................ + !> * Create mapping (if remap is true) + ! Note that we also create a motion mapping for the source and destination displacement meshes (SrcDisp and DestDisp) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + !> * Linearize data + !........................ + + !> + Get individual transformation matrices: + + !> 1. Get the matrix that transfers the source fields to the augmented source mesh. + !! (We're also taking the force field and and (source) translational displacement field and + !! putting them on our [intermediate] augmented mesh.) + CALL Linearize_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat2, ErrMsg2, SrcDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + call move_alloc( MeshMap%dM%li, M_A ) + +! ^^^ size of M_A is 3*MeshMap%Augmented_Ln2_Src%NNodes X 3*Src%Nnodes + + !> 2. Get the matrices that lump the loads on the augmented source mesh. + !! (We're also taking the force field and putting it on our lumped mesh.) + CALL Linearize_Lump_Line2_to_Point( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, MeshMap%dM, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call move_alloc( MeshMap%dM%m_uD, M_SL_uSm ) + call move_alloc( MeshMap%dM%m_f, M_SL_fm ) + call move_alloc( MeshMap%dM%li, M_SL_li ) + +! ^^^ size of M_SL_li (as well as M_SL_uSm and M_SL_fm) is 3*MeshMap%Augmented_Ln2_Src%NNodes X 3*MeshMap%Augmented_Ln2_Src%NNodes + + !> 3. (and 4) Get the matrices transfering the lumped (point) loads to line2 loads. + CALL Linearize_Loads_Point_to_Line2( MeshMap%Lumped_Points_Src, Dest, MeshMap, ErrStat2, ErrMsg2, MeshMap%Augmented_Ln2_Src, DestDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +! ^^^ size of dM%li is 3*Dest%NNodes X 3*MeshMap%Augmented_Ln2_Src%NNodes (m_uD is square, of size 3*Dest%NNodes X 3*Dest%NNodes) +! need to return size of dM%li as 3*Dest%NNodes X 3*Src%NNodes: + + + !> + Multiply individual transformation matrices to get full linearization matrices + CALL FormMatrix_FullLinearization( MeshMap%dM, M_A, M_SL_fm, M_SL_uSm, M_SL_li, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call cleanup() + + end if ! algorithm for loads + + +contains +subroutine cleanup() + + if (allocated(M_A )) deallocate(M_A ) + if (allocated(M_SL_li )) deallocate(M_SL_li) + if (allocated(M_SL_uSm)) deallocate(M_SL_uSm) + if (allocated(M_SL_fm )) deallocate(M_SL_fm) + +end subroutine cleanup + +END SUBROUTINE Linearize_Line2_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mapping, this routine transfers the loads from nodes on a point-element mesh to nodes on another Line2 mesh. +SUBROUTINE Transfer_Loads_Point_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp, LoadsScaleFactor ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with loads fields allocated + TYPE(MeshType), INTENT(INOUT) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< The source mesh's cooresponding position mesh + TYPE(MeshType), INTENT(IN ) :: DestDisp !< The destination mesh's cooresponding position mesh + REAL(ReKi), INTENT(IN) :: LoadsScaleFactor !< Scaling factor for loads (to help with numerical issues) + + ! local variables + REAL(ReKi) :: torque(3), DisplacedPosition(3) + + INTEGER(IntKi) :: i,j ! loop counters + INTEGER(IntKi) :: jElem ! element number + INTEGER(IntKi) :: jNode ! node number + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Transfer_Loads_Point_to_Line2' + + + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Start with transferring the loads like point-to-point (except split between two nodes of the dest element). + ! [because the OtherMesh_Element is line2, we can't just call the routine here] + + if ( Dest%FieldMask(MASKID_MOMENT) ) Dest%Moment = 0._ReKi ! whole array initialization; required to handle superposition of loads + + ! ---------------------------- Force ------------------------------------------------ + ! Transfer this source force (lumped) to destination force and/or moment fields (currently lumped): + + ! split the point source loads across the line2 destination element (note that they are still point loads on line2 elements here) + + if ( Src%FieldMask(MASKID_Force) ) THEN + Dest%Force = 0._ReKi ! whole array initialization; required to handle superposition of loads + ! ( Dest%FieldMask(MASKID_Force) ) is .TRUE. + + DO i = 1, Src%Nnodes ! the source nodes (containing lumped loads) + + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + DO j = 1,2 ! number of nodes on dest + jNode = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + Dest%Force(:,jNode) = Dest%Force(:,jNode) + (Src%Force(:,i)/LoadsScaleFactor)*MeshMap%MapLoads(i)%shape_fn(j) + END DO !j + + END DO !loop through source nodes + + + ! calculate the moment due to force + !if ( Dest%FieldMask(MASKID_MOMENT) ) then (now must always be true) + + ! if the distance (which can never be less than zero) is greater than "zero" and there is a + ! force in the source mesh, then we need to add a moment to the destination mesh to account + ! for the mismatch between points + + ! M_d += torque + + DO i = 1, Src%Nnodes ! the source nodes + + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + DO j = 1,2 ! number of nodes on dest + jNode = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + + DisplacedPosition = Src%Position(:,i) + SrcDisp%TranslationDisp(:,i) & + - Dest%Position(:,jNode) - DestDisp%TranslationDisp(:,jNode) + + torque = Src%Force(:,i) / LoadsScaleFactor !not torque yet, but we're doing this cross product in two steps to avoid tempoary memory storage + torque = CROSS_PRODUCT( DisplacedPosition, torque ) + Dest%Moment(:,jNode) = Dest%Moment(:,jNode) + torque*MeshMap%MapLoads(i)%shape_fn(j) + END DO !j + + + END DO !loop through source elements + + + !end if ! Dest has moment, too + + + end if !source has force + + + ! ---------------------------- Moments ------------------------------------------------ + ! Transfer this source moment to the destination moment field + + if ( Src%FieldMask(MASKID_Moment) ) then ! + + + DO i = 1, Src%Nnodes ! the source nodes + + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + DO j = 1,2 ! number of nodes on dest + jNode = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + Dest%Moment(:,jNode) = Dest%Moment(:,jNode) + (Src%Moment(:,i)/LoadsScaleFactor)*MeshMap%MapLoads(i)%shape_fn(j) + END DO !j + + END DO !loop through source nodes + + + end if !src has moment field + +#ifdef MESH_DEBUG + CALL Create_PointMesh(Dest, MeshMap%Lumped_Points_Dest, ErrStat, ErrMsg) + IF (Dest%FieldMask(maskid_force)) MeshMap%Lumped_Points_Dest%Force = Dest%Force + IF (Dest%FieldMask(maskid_moment)) MeshMap%Lumped_Points_Dest%Moment = Dest%Moment +#endif + + !> now we can convert the lumped loads on the dest (line2) mesh into distributed loads on the same mesh: + CALL Convert_Point_To_Line2_Loads(Dest, MeshMap, ErrStat2, ErrMsg2, DestDisp) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + !IF (ErrStat >= AbortErrLev) RETURN + + if (Dest%FieldMask(MASKID_FORCE) ) Dest%Force = Dest%Force * LoadsScaleFactor ! whole array initialization + if (Dest%FieldMask(MASKID_MOMENT)) Dest%Moment = Dest%Moment * LoadsScaleFactor ! whole array initialization + + +END SUBROUTINE Transfer_Loads_Point_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Given a mapping, this routine contains the linearization matrices of the load transfers from nodes on a point-element mesh to +!! nodes on another Line2 mesh. At the end of this routine, the MeshMap data structure will contain the four matrices for loads +!! transfer from a point to line2 mesh: \f$ M_{um}\f$, \f$ M_{tm}\f$, \f$M_{fm}\f$, and \f$M_{li}\f$, where +!! \f{equation}{ +!! \begin{aligned} +!! \left\{ \begin{matrix} \Delta\vec{u}^D \\ \Delta\vec{\theta}^D \\ \Delta\vec{f}^D \\ \Delta\vec{m}^D \end{matrix} \right\} & = +!! \begin{bmatrix} M_{mi} & M_{f_{\times p}} & 0 & 0 \\ +!! 0 & M_{mi} & 0 & 0 \\ +!! 0 & 0 & M_{li} & 0 \\ +!! M_{um} & M_{tm} & M_{fm} & M_{li} \\ \end{bmatrix} +!! \left\{ \begin{matrix} \Delta\vec{u}^S \\ \Delta\vec{\theta}^S \\ \Delta\vec{F}^S \\ \Delta\vec{M}^S \end{matrix} \right\} \\ & = +!! \begin{bmatrix} I & 0 & 0 & 0 \\ +!! 0 & I & 0 & 0 \\ +!! 0 & 0 & \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} & 0 \\ +!! -\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1}M_{um}^{DL} & 0 & -\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1}M_{fm}^{DL}\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} & \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} \\ \end{bmatrix} +!! \begin{bmatrix} M_{mi} & M_{f_{\times p}} & 0 & 0 \\ +!! 0 & M_{mi} & 0 & 0 \\ +!! 0 & 0 & M_{li}^D & 0 \\ +!! 0 & M_{tm}^D & M_{fm}^D & M_{li}^D \\ \end{bmatrix} +!! \left\{ \begin{matrix} \Delta\vec{u}^S \\ \Delta\vec{\theta}^S \\ \Delta\vec{F}^S \\ \Delta\vec{M}^S \end{matrix} \right\} +!! \end{aligned} +!! \f} +!! "S" refers to the source (point) mesh;"D" refers to the destination (line2) mesh; "DL" refers to the destination mesh with lumped (point) loads. \n +!! \f$M_{li}\f$ is modmesh_mapping::meshmaplinearizationtype::li \n +!! \f$M_{M_u}\f$ is modmesh_mapping::meshmaplinearizationtype::m_us \n +!! \f$M_{M_t}\f$ is modmesh_mapping::meshmaplinearizationtype::m_ud \n +!! \f$M_{M_f}\f$ is modmesh_mapping::meshmaplinearizationtype::m_f +SUBROUTINE Linearize_Loads_Point_to_Line2( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source (Line2) mesh with loads fields allocated + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data from Src to Dest + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< The source mesh's cooresponding position mesh + TYPE(MeshType), INTENT(IN ) :: DestDisp !< The destination mesh's cooresponding position mesh + + ! local variables + REAL(R8Ki) :: DisplacedPosition(3), SSMat(3,3) + + REAL(R8Ki), ALLOCATABLE :: li_D(:,:) + REAL(R8Ki), ALLOCATABLE :: muS_D(:,:) + REAL(R8Ki), ALLOCATABLE :: muD_D(:,:) + REAL(R8Ki), ALLOCATABLE :: mf_D(:,:) + + integer(intKi) :: i, j, jElem, k, n, d_start, d_end, s_start, s_end + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Linearize_Loads_Point_to_Line2' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Start by determining how the point load is split based on its projected location in the mapped destination Line2 element. + !! (This is like Linearize_Loads_Point_to_Point, except we need to loop on elements instead of nodes [because of nearest neighbor mapping routine]) + + !> > Matrix \f$ M_{li}^D \f$, stored in li_D, + !! > is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the matrix that maps each field of the source point mesh to another point mesh. + + ! "identity" (portion of node) for forces and/or moments: + if (.not. allocated(li_D) ) then + call AllocAry(li_D, Dest%Nnodes*3, Src%Nnodes*3, 'li_D', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + end if + + li_D = 0.0_R8Ki + do i = 1, Src%NNodes + + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + do j=1,NumNodes(ELEMENT_LINE2) + n = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + + do k=1,3 + li_D( (n-1)*3+k, (i-1)*3+k ) = MeshMap%MapLoads(i)%shape_fn(j) + end do + end do + + end do + + ! m_uD, m_uS, and m_f for moments: + + if (Dest%FieldMask(MASKID_MOMENT) .AND. Src%FieldMask(MASKID_FORCE) ) then + + !> > Matrix \f$ M_{uD}^D \f$, stored in muD_D, + !! > is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! > This is the block matrix that maps the u (translational displacement) field + !! > of the destination mesh to the moment field of the destination mesh. + + if (.not. allocated(muD_D) ) then + call AllocAry(muD_D, Dest%Nnodes*3, Dest%Nnodes*3, 'muD_D', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + end if + + !> > Matrix \f$ M_{uS}^D \f$, stored in muS_D, + !! > is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the block matrix that maps the u (translational displacement) field + !! > of the source mesh to the moment field of the destination mesh. + + if (.not. allocated(muS_D) ) then + call AllocAry(muS_D, Dest%Nnodes*3, Src%Nnodes*3, 'muS_D', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + end if + + muD_D = 0.0_R8Ki + muS_D = 0.0_R8Ki + do i = 1, Src%NNodes + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + + s_start = (i-1)*3+1 + s_end = s_start+2 + + do j=1,NumNodes(ELEMENT_LINE2) + n = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + + d_start = (n-1)*3+1 + d_end = d_start+2 + + SSmat = SkewSymMat( Src%Force(:,i)*MeshMap%MapLoads(i)%shape_fn(j) ) + + muD_D( d_start:d_end, d_start:d_end ) = muD_D( d_start:d_end, d_start:d_end ) + SSmat + muS_D( d_start:d_end, s_start:s_end ) = muS_D( d_start:d_end, s_start:s_end ) - SSmat + + end do !j + + end do + + + !> > Matrix \f$ M_{fm}^D \f$, stored in mf_D, + !! > is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the block matrix that maps the force field of the source mesh to the moment field of the destination mesh. + + if (.not. allocated(mf_D) ) then + call AllocAry(mf_D, Dest%Nnodes*3, Src%Nnodes*3, 'mf_D', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + end if + + + mf_D = 0.0_R8Ki + do i = 1, Src%NNodes + jElem = MeshMap%MapLoads(i)%OtherMesh_Element + + s_start = (i - 1)*3+1 + s_end = s_start+2 + do j=1,NumNodes(ELEMENT_LINE2) + n = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(j) + + d_start = (n-1)*3+1 + d_end = d_start+2 + + DisplacedPosition = SrcDisp%TranslationDisp(:,i) + SrcDisp%Position(:,i) & + - ( DestDisp%TranslationDisp(:,n) + DestDisp%Position(:,n) ) + + DisplacedPosition = DisplacedPosition*MeshMap%MapLoads(i)%shape_fn(j) ! multiply the fraction here so we don't need to apply to any of the terms below + + mf_D( d_start:d_end, s_start:s_end ) = SkewSymMat( DisplacedPosition ) + + end do !j + + end do + + endif + + !> Then we can obtain the matrices that convert the lumped loads on the dest (line2) mesh into distributed loads on the same mesh: + !! For linearization analysis, we assume this destination mesh already contains the distributed loads (i.e., values at the operating point). + CALL Linearize_Convert_Point_To_Line2_Loads(Dest, MeshMap, ErrStat2, ErrMsg2, DestDisp) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + RETURN + end if + + !> Finally, we multiply the matrices together and return the non-zero block matrices that remain. + + n=Dest%Nnodes*3 + + !> > Matrix \f$ M_{li} = \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{li}^{D} \f$, stored in modmesh_mapping::meshmaplinearizationtype::li, + !! > is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the matrix that maps each field of the source mesh to an augmented mesh. + !! > \n Note that we solve the equation \f$ M_{li}^{DL} M_{li} = M_{li}^{D} \f$ for \f$ M_{li} \f$. + + ! solve this before M_{fm} so that we can use M_{li} in the equation for M_{fm} + + ! solve for M_{li}: + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, B=li_D, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call move_alloc(li_D, MeshMap%dM%li) + + + if (Dest%FieldMask(MASKID_MOMENT) .AND. Src%FieldMask(MASKID_FORCE) ) then + + !> > Matrix \f$ M_{uSm} = -\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{uSm}^{DL} \f$ + !! > stored in modmesh_mapping::meshmaplinearizationtype::m_us, is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the matrix that maps the source u (translational displacement) to the destination moment. + !! > \n Note that we solve the equation \f$ M_{li}^{DL} M_{uSm} = M_{uSm}^{DL} \f$ for \f$ M_{uSm} \f$. + + ! solve for M_{uSm} + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, B=muS_D, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call move_alloc(muS_D, MeshMap%dM%M_uS) + + !> > Matrix \f$ M_{uDm} = -\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{uDm}^{DL} + \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{uDm}^D \f$ + !! > stored in modmesh_mapping::meshmaplinearizationtype::m_ud, is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! > This is the matrix that maps the destination u (translational displacement) to the destination moment. + !! > \n Note that we solve the equation \f$ M_{li}^{DL} M_{uDm} = M_{uDm}^D - M_{uDm}^{DL} \f$ for \f$ M_{uDm} \f$. + + ! get RHS of equation: + muD_D = muD_D - MeshMap%dM%m_uD + + ! solve for M_{uDm} + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, B=muD_D, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call move_alloc(muD_D, MeshMap%dM%M_uD) + + !> > Matrix \f$ M_{fm} \f$ is stored in modmesh_mapping::meshmaplinearizationtype::m_f and is allocated to be size Dest\%NNodes*3, Src\%NNodes*3. + !! > This is the matrix that maps the force to the moment. \n + !! > \f$ \begin{aligned} M_{fm} & = + !! - \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{fm}^{DL}\begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1}M_{li}^D + !! + \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{fm}^D \\ & = + !! \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} \left( - M_{fm}^{DL} M_{li} + M_{fm}^D \right) \end{aligned}\f$, + !! > \n Note that we solve the equation \f$ M_{li}^{DL} M_{fm} = M_{fm}^D - M_{fm}^{DL} M_{li} \f$ for \f$ M_{fm} \f$. + + ! get RHS of equation + mf_D = mf_D - matmul( MeshMap%dM%m_f, MeshMap%dM%li ) + + ! solve for M_{fm} + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, B=mf_D, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call move_alloc(mf_D, MeshMap%dM%m_f) + + end if + + + call cleanup() + +contains + + subroutine cleanup() + if (allocated(li_D)) deallocate(li_D) + if (allocated(muD_D)) deallocate(muD_D) + if (allocated(muS_D)) deallocate(muS_D) + if (allocated(mf_D)) deallocate(mf_D) + end subroutine cleanup + +END SUBROUTINE Linearize_Loads_Point_to_Line2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine takes the lumped loads on nodes of a (line2) mesh and converts them to loads distributed across the line2 elements. +SUBROUTINE Convert_Point_To_Line2_Loads(Dest, MeshMap, ErrStat, ErrMsg, DestDisp) + + TYPE(MeshType), INTENT(INOUT) :: Dest !< The mesh (on input, the nodal loads values are lumped; on output they are distributed along the element) + TYPE(MeshType), INTENT(IN ) :: DestDisp !< The mesh that contains the translation displacement for these loads + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: jElem, n, i,j, n1, n2 + REAL(ReKi) :: a_vec(3), sum_f(3), crossProd(3) + REAL(ReKi) :: c + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Convert_Point_To_Line2_Loads' + + + n=3*Dest%Nnodes !also SIZE(MeshMap%LoadLn2_F,1) and SIZE(MeshMap%LoadLn2_M,1) + ErrStat = ErrID_None + ErrMsg = "" + + + ! Convert the forces on each element + + IF ( Dest%FieldMask(MASKID_Force) ) then + + MeshMap%LoadLn2_F = RESHAPE( Dest%Force, (/ n, 1 /) ) + + ! After following call, LoadLn2_F contains the distributed forces: + + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, & + B=MeshMap%LoadLn2_F, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + + ! Transfer forces to the mesh fields + + Dest%Force = RESHAPE( MeshMap%LoadLn2_F, (/ 3, Dest%Nnodes /) ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + END IF ! Force + + + ! Convert the moments on each element + + IF ( Dest%FieldMask(MASKID_Moment) ) then + + MeshMap%LoadLn2_M = RESHAPE( Dest%Moment, (/ n, 1 /) ) + + IF ( Dest%FieldMask(MASKID_Force) ) then + + DO jElem = 1,Dest%ElemTable(ELEMENT_LINE2)%nelem + + n1=Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(1) + n2=Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%ElemNodes(2) + + c = Dest%ElemTable(ELEMENT_LINE2)%Elements(jElem)%det_jac/6.0_ReKi ! this contains an extra factor of 1/2, which comes from omitting it from the a_vec term + + a_vec = ( DestDisp%Position(:,n2) + DestDisp%TranslationDisp(:,n2) ) & + - ( DestDisp%Position(:,n1) + DestDisp%TranslationDisp(:,n1) ) + + ! We solved LoadLn2_F for the distributed value, so we'll use it here: (the B matrix is just the cross product terms) + sum_f = Dest%Force(:,n1) + Dest%Force(:,n2) + crossProd = c * cross_product( a_vec, sum_f) + + ! subtract the force (using the distributed values) from the lumped moment terms: + i = (n1-1)*3+1; j = i+2 + MeshMap%LoadLn2_M(i:j,1)=MeshMap%LoadLn2_M(i:j,1) - crossProd + + i = (n2-1)*3+1; j = i+2 + MeshMap%LoadLn2_M(i:j,1)=MeshMap%LoadLn2_M(i:j,1) + crossProd + END DO + + END IF ! moment due to force + + ! After following call, LoadLn2_M contains the distributed moments: + + CALL LAPACK_getrs(TRANS='N',N=n,A=MeshMap%LoadLn2_A_Mat,IPIV=MeshMap%LoadLn2_A_Mat_piv, & + B=MeshMap%LoadLn2_M, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + + ! Transfer moments to the mesh fields + + Dest%Moment = RESHAPE( MeshMap%LoadLn2_M, (/ 3, Dest%Nnodes /) ) + + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + END IF ! Moment + + +END SUBROUTINE Convert_Point_To_Line2_Loads +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the linearized matrices that convert the lumped (point) loads on nodes of a (line2) mesh +!! to loads distributed across the line2 elements. (i.e., inverse lumping) +SUBROUTINE Linearize_Convert_Point_To_Line2_Loads(Dest, MeshMap, ErrStat, ErrMsg, DestDisp) + + TYPE(MeshType), INTENT(IN ) :: Dest !< The mesh (on linearization input the loads are distributed along the line2 element) + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< The mapping data + TYPE(MeshType), INTENT(IN ) :: DestDisp !< The mesh that contains the translation displacement for these loads + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Linearize_Convert_Point_To_Line2_Loads' + + + ErrStat = ErrID_None + ErrMsg = "" + + !> Matrix \f$ \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} \f$, stored in modmesh_mapping::meshmaplinearizationtype::li, + !! is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! This is the block matrix that maps the individual load fields of the source mesh to the corresponding field in the destination mesh. + !! This matrix also forms part of the terms of modmesh_mapping::meshmaplinearizationtype::m_uS and modmesh_mapping::meshmaplinearizationtype::m_f. + !! > However, since this is easier done with a solve, we are not actually going to form the matrix here. + + ! Now I need to get the cross-product terms for the moments as well: + ! M_uD and m_f for moments: + + if (Dest%FieldMask(MASKID_MOMENT) .AND. Dest%FieldMask(MASKID_FORCE) ) then + + !> Matrix \f$ M_{uDm}^{DLinv} = - \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{uDm}^{DL} \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_us, + !! is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! This is the block matrix that relates the destination translational displacement field to the moment field. + !! > However, since this is easier done with a solve, we are not actually going to form the matrix here. Instead, I'll return \f$ M_{uDm}^{DL} \f$ + + + !> Matrix \f$ M_{fm}^{DLinv} = - \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1} M_{fm}^{DL} \begin{bmatrix} M_{li}^{DL} \end{bmatrix}^{-1}\f$, + !! stored in modmesh_mapping::meshmaplinearizationtype::m_f, + !! is allocated to be size Dest\%NNodes*3, Dest\%NNodes*3. + !! This is the block matrix that relates the force field to the moment field. + !! > However, since this is easier done with a solve, we are not actually going to form the matrix here. Instead, I'll return \f$ M_{fm}^{DL} \f$ + + + ! this call sets MeshMap%dM%m_uD = M_{uDm}^{DL} and MeshMap%dM%m_f = M_{fm}^{DL} + call FormMatrix_Lump_Line2_to_Point( Dest, Meshmap%dM, ErrStat2, ErrMsg2, DestDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + +END SUBROUTINE Linearize_Convert_Point_To_Line2_Loads +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Create_Augmented_Ln2_Src_Mesh(Src, Dest, MeshMap, Dest_TYPE, ErrStat, ErrMsg) +!This routine creates a new line2 mesh. This augmented line2-element source mesh is formed by splitting the original Line2-element +! source mesh at each location where a destination mesh node (either a point or line2 element) projects orthogonally onto the +! line2-element source mesh. +! It adds fields for forces, moments, and/or TranslationDisp, if they are part of the Src mesh + +! creates MeshMap%Augmented_Ln2_Src and +! MeshMap%MapSrcToAugmt +! and (reallocates) MeshMap%MapLoads if necessary +! +! bjj: maybe this should be in the AllocMapping routine? Or maybe the allocMapping routine shouldn't actually allocate arrays; do +! it in the "IF (RemapFlag)" sections so that if people add nodes during the simulation, the structures get reallocated to correct +! size? allocMapping should maybe be MeshMapping_Init() and only check that fields are compatible, etc. +! +!.................................................................................................................................. + TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap + INTEGER(IntKi), INTENT(IN ) :: Dest_TYPE ! Type of Dest elements to map + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: iElem, i ! do-loop counter for nodes/elements on source + INTEGER(IntKi) :: jElem, jNode, j ! do-loop counter for nodes/elements on destination + + INTEGER(IntKi) :: max_new_nodes, max_nodes, Aug_Nnodes + INTEGER(IntKi) :: Aug_NElem, curr_Aug_NElem + INTEGER(IntKi) :: n1, n2 + REAL(ReKi) :: p_ED(3), p_ES(3), n1S_nD_vector(3), position(3) + REAL(ReKi) :: p_ED_orig(3), denom_orig + REAL(R8Ki) :: RefOrientation(3,3) + REAL(DbKi) :: TmpVec(3), RefOrientationD(3,3), FieldValue(3,2) ! values for interpolating direction cosine matrices + REAL(ReKi) :: denom, elem_position + REAL(ReKi), PARAMETER :: TOL = sqrt(epsilon(elem_position)) ! we're not using EqualRealNos here because we don't want elements of zero length (EqualRealNos produces elements of zero length) + REAL(ReKi) :: L ! length of newly created element(s) + + TYPE(MeshType) :: Temp_Ln2_Src ! A temporary mesh + INTEGER, allocatable :: Original_Src_Element(:) + REAL(ReKi), allocatable :: shape_fn2(:) + + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Create_Augmented_Ln2_Src_Mesh' + + + + ErrStat = ErrID_None + ErrMsg = "" + + ! We're going to find out the maximum number of new nodes that we will add to this mesh and create a new mesh with those nodes. + ! We will likely not actually need all those extra nodes, so we'll have to transfer them to another mesh to commit it later. + + ! first, we need to know how many (additional) nodes we might need: + ! each node of each destination element could potentially split each element of the source mesh + max_new_nodes = (NumNodes( Dest_TYPE ) * dest%ElemTable(Dest_TYPE)%nelem) * src%ElemTable(ELEMENT_LINE2)%nelem ! max number of new nodes + max_nodes = max_new_nodes + Src%nnodes ! max total number of nodes in new mesh + + ! create a temporary mesh that we can work with (add nodes and split elements): + ! note that we don't have any fields, and we will never commit this mesh, either. + + CALL MeshCreate( BlankMesh = Temp_Ln2_Src & + ,IOS = Src%IOS & + ,NNodes = max_nodes & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + CALL AllocAry( Original_Src_Element, src%ElemTable(ELEMENT_LINE2)%nelem+max_new_nodes, 'Original_Src_Element', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + CALL AllocAry( shape_fn2, max_nodes, 'shape_fn2', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! we'll first add the nodes and Line2 elements from the original source mesh + do i = 1, src%nnodes + + CALL MeshPositionNode ( Mesh = Temp_Ln2_Src & + ,INode = i & + ,Pos = Src%Position(:,i) & + ,Orient = Src%RefOrientation(:,:,i) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! Original_Src_Element(i)=-1 !Part of the original mesh + enddo + DO i=1,src%ElemTable(ELEMENT_LINE2)%nelem + CALL MeshConstructElement ( Mesh = Temp_Ln2_Src & + ,Xelement = ELEMENT_LINE2 & + ,P1 = Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) & + ,P2 = Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + Original_Src_Element(i)=i !Part of the original mesh + end do + + ! now we'll augment the mesh: + Aug_Nnodes = Src%nnodes ! number of nodes in the augmented mesh + Aug_NElem = Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%nelem + + ! loop through the destination elements (NOTE: for point elements, this is the same as looping over nodes): + DO jElem = 1,dest%ElemTable(Dest_TYPE)%nelem + + IF ( Dest_TYPE == ELEMENT_LINE2 ) THEN + p_eD = dest%Position(:, dest%ElemTable(Dest_TYPE)%Elements(jElem)%ElemNodes(2)) & + - dest%Position(:, dest%ElemTable(Dest_TYPE)%Elements(jElem)%ElemNodes(1)) + p_eD_orig = p_eD ! save for later calculations (to allow point elements, too) + END IF + + + iElem = 1 + curr_Aug_NElem = Aug_NElem + j = 1 + + Src_Elements: DO WHILE ( iElem <= curr_Aug_NElem ) ! bjj: we're adding elements and nodes to Temp_Ln2_Src, so this must be flexible + + p_eS = Temp_Ln2_Src%Position(:, Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2)) & + - Temp_Ln2_Src%Position(:, Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1)) + + IF ( Dest_TYPE == ELEMENT_POINT ) p_eD = p_eS + denom = DOT_PRODUCT( p_eD , p_eS ) + + + IF ( .NOT. EqualRealNos( denom, 0.0_ReKi) ) THEN ! we ignore source elements that are parallel to the destination element (i.e., denom == 0) + DO jNode = j, NumNodes( Dest_TYPE ) ! check each node of the destination element + n1S_nD_vector = dest%Position(:, dest%ElemTable(Dest_TYPE)%Elements(jElem)%ElemNodes(jNode)) & + - Temp_Ln2_Src%Position(:, Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1)) + + elem_position = DOT_PRODUCT( p_eD, n1S_nD_vector ) / denom ! Eq 37 (AIAA 2015 paper) + +!bjj: todo: we need to set this TOL based on actual distances, not relative values (0,1) on an element.... +! for now, I've calculated the element length inside this tolerance and reserve the right to reject new nodes that create 0-length elements. + + ! if 0 < elem_position < 1, we create a new node and split this element + IF ( elem_position > TOL .AND. elem_position < (1.0_ReKi - TOL) ) THEN + + + ! Add a node (and therefore an element): + Aug_Nnodes = Aug_Nnodes + 1 + + ! calculate the position and orientation relative to the *original* source element: + n1=Src%ElemTable(ELEMENT_LINE2)%Elements(Original_Src_Element(iElem))%ElemNodes(1) + n2=Src%ElemTable(ELEMENT_LINE2)%Elements(Original_Src_Element(iElem))%ElemNodes(2) + + + p_eS = Src%Position(:, n2) - Src%Position(:, n1) + IF ( Dest_TYPE == ELEMENT_POINT ) p_eD_orig = p_eS + denom_orig = DOT_PRODUCT( p_eD_orig , p_eS ) ! we don't need to check that this is zero because it's just a shorter version of the temp Temp_Ln2_Src element + n1S_nD_vector = dest%Position(:, dest%ElemTable(Dest_TYPE)%Elements(jElem)%ElemNodes(jNode)) & + - Src%Position(:, n1 ) + shape_fn2(Aug_Nnodes) = DOT_PRODUCT( p_eD_orig, n1S_nD_vector ) / denom_orig ! save this for later, when we need to map the mesh fields... + + ! interpolate position on the original souce element: + + position = (1.0_ReKi - shape_fn2(Aug_Nnodes)) * Src%Position(:, n1) & + + shape_fn2(Aug_Nnodes) * Src%Position(:, n2) + + ! let's just verify that this new node (n1) doesn't give us zero-length elements: + ! (note we use the NEW (not original) source element, which may have been split) + p_eS = position - Temp_Ln2_Src%Position(:, Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) ) + L = SQRT(dot_product(p_eS,p_eS)) ! length of new element + + IF ( L < MIN_LINE2_ELEMENT_LENGTH ) THEN ! this element is basically zero length + ! for numerical reasons, we really didn't want this node.... + Aug_Nnodes = Aug_Nnodes - 1 + ELSE + + ! let's verify the other node (n2) of this element doesn't give zero-length: + p_eS = position - Temp_Ln2_Src%Position(:, Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2)) + L = SQRT(dot_product(p_eS,p_eS)) ! length of new element + + IF ( L < MIN_LINE2_ELEMENT_LENGTH ) THEN ! this element is basically zero length + ! for numerical reasons, we really didn't want this node.... + Aug_Nnodes = Aug_Nnodes - 1 + ELSE + + ! we can add the node (and an element) + Aug_NElem = Aug_NElem + 1 + CALL MeshSplitElement_2PT( Temp_Ln2_Src, ELEMENT_LINE2, ErrStat2, ErrMsg2, iElem, Aug_Nnodes ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + Original_Src_Element( Aug_NElem ) = Original_Src_Element( iElem ) ! this node can now be mapped to original source mesh element + + + ! get the Reference orientation for this new node + ! convert DCMs to tensors: + + RefOrientationD = Src%RefOrientation(:, :, n1) + CALL DCM_logmap( RefOrientationD, FieldValue(:,1), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + RefOrientationD = Src%RefOrientation(:, :, n2) + CALL DCM_logmap( RefOrientationD, FieldValue(:,2), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL DCM_SetLogMapForInterp( FieldValue ) ! make sure we don't cross a 2pi boundary + + ! interpolate tensors: + TmpVec = (1.0_ReKi - shape_fn2(Aug_Nnodes)) * FieldValue(:, 1) & + + shape_fn2(Aug_Nnodes) * FieldValue(:, 2) + + ! convert back to DCM: + RefOrientationD = DCM_exp( TmpVec ) + RefOrientation = REAL(RefOrientationD, R8Ki) + + + CALL MeshPositionNode ( Mesh = Temp_Ln2_Src & + ,INode = Aug_Nnodes & + ,Pos = position & + ,Orient = RefOrientation & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! if we have to check a second node, we need to first recalculate p_eS and denom on Temp_Ln2_Src: + IF ( jNode < NumNodes( Dest_TYPE )) THEN + j = jNode+1 ! start on the next node + CYCLE Src_Elements + END IF + + END IF ! doesn't cause zero-length element + + + END IF + + END IF ! New node/element + + END DO !jNode + j = 1 + + END IF ! elements aren't parallel + + ! move to the next source element (i.e., CYCLE Src_Elements) + iElem = iElem + 1 + + END DO Src_Elements ! while + + END DO !jElem + + + !.................. + ! Now let's create the actual augmented mesh (should be smaller than the Temp_Ln2_Src mesh): + !................. + + CALL MeshDestroy( MeshMap%Augmented_Ln2_Src, ErrStat2, ErrMsg2, .TRUE. ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + CALL MeshCreate( BlankMesh = MeshMap%Augmented_Ln2_Src & + ,IOS = Src%IOS & + ,NNodes = Aug_Nnodes & + ,Force = Src%FieldMask(maskid_force) & + ,Moment = Src%FieldMask(maskid_moment) & ! ,TranslationDisp = Src%FieldMask(maskid_TranslationDisp) & + ,TranslationDisp = .TRUE. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + do i = 1, Aug_Nnodes + + CALL MeshPositionNode ( Mesh = MeshMap%Augmented_Ln2_Src & + ,INode = i & + ,Pos = Temp_Ln2_Src%Position(:,i) & + ,Orient = Temp_Ln2_Src%RefOrientation(:,:,i) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + enddo + DO i=1,Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%nelem + CALL MeshConstructElement ( Mesh = MeshMap%Augmented_Ln2_Src & + ,Xelement = ELEMENT_LINE2 & + ,P1 = Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) & + ,P2 = Temp_Ln2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + end do + + CALL MeshCommit ( MeshMap%Augmented_Ln2_Src, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! we're going to need the mapping data from source to augmented source: + IF (Aug_Nnodes > Src%Nnodes) THEN + IF (ALLOCATED(MeshMap%MapSrcToAugmt)) THEN + IF (UBOUND(MeshMap%MapSrcToAugmt,1) < Aug_NNodes) THEN + DEALLOCATE (MeshMap%MapSrcToAugmt) + END IF + END IF + + IF (.NOT. ALLOCATED(MeshMap%MapSrcToAugmt)) THEN + ALLOCATE( MeshMap%MapSrcToAugmt((Src%Nnodes+1):Aug_NNodes), STAT=ErrStat2 ) + + IF (ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Could not allocate MeshMap%MapSrcToAugmt.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + END IF + + j=Src%ElemTable(ELEMENT_LINE2)%nelem + do i=LBOUND(MeshMap%MapSrcToAugmt,1),UBOUND(MeshMap%MapSrcToAugmt,1) + j = j+1 + MeshMap%MapSrcToAugmt(i)%OtherMesh_Element = Original_Src_Element( j ) ! we added just as many nodes as elements... + MeshMap%MapSrcToAugmt(i)%shape_fn(2) = shape_fn2( i ) + MeshMap%MapSrcToAugmt(i)%shape_fn(1) = 1.0_ReKi - shape_fn2( i ) + end do + + IF (ALLOCATED(MeshMap%DisplacedPosition)) THEN + IF ( SIZE(MeshMap%DisplacedPosition,2) < Aug_Nnodes ) THEN + + DEALLOCATE (MeshMap%DisplacedPosition) + END IF + END IF + + IF (.NOT. ALLOCATED(MeshMap%DisplacedPosition)) THEN + CALL AllocAry( MeshMap%DisplacedPosition, 3, Aug_Nnodes,2, 'MeshMap%DisplacedPosition', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + END IF + + + IF ( ALLOCATED(MeshMap%MapLoads)) THEN + IF (SIZE(MeshMap%MapLoads) < Aug_NNodes) THEN + DEALLOCATE( MeshMap%MapLoads ) + END IF + END IF + + IF (.NOT. ALLOCATED(MeshMap%MapLoads)) THEN + ALLOCATE( MeshMap%MapLoads(Aug_Nnodes), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Could not allocate MeshMap%MapLoads.', ErrStat, ErrMsg, RoutineName) + CALL CleanUp() + RETURN + END IF + END IF + + + END IF + + + CALL CleanUp() + RETURN + + ! clean up +CONTAINS + SUBROUTINE CleanUp() + + CALL MeshDestroy( Temp_Ln2_Src, ErrStat2, ErrMsg2 ) + IF ( ALLOCATED(Original_Src_Element) ) DEALLOCATE(Original_Src_Element) + IF ( ALLOCATED(shape_fn2) ) DEALLOCATE(shape_fn2) + + END SUBROUTINE CleanUp + +END SUBROUTINE Create_Augmented_Ln2_Src_Mesh +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine takes the loads from a line2 mesh and transfers them to an augmented line2 mesh (the src mesh with extra/augmented nodes). +!! It also transfers the translation displacement field to this augmented mesh so that we have only one mesh to deal with +!! instead of two. The first NNodes values of the two meshes are equal, and the additional, augmented nodes are split between +!! nodes on a line2 element. +SUBROUTINE Transfer_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat, ErrMsg, SrcDisp, LoadsScaleFactor ) +!.................................................................................................................................. + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh containing line2 loads + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mesh mapping data, including the augmented source mesh + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< The displacements associated with the source mesh + REAL(ReKi), INTENT(IN) :: LoadsScaleFactor !< Scaling factor for loads (to help with numerical issues) + + ! local variables + INTEGER(IntKi) :: iElem, i ! do-loop counter for nodes/elements on source + INTEGER(IntKi) :: n1, n2 + + ErrStat = ErrID_None + ErrMsg = "" + + !....................................... + ! TranslationDisp (from external mesh to augmented one) + !....................................... + + IF ( SrcDisp%FIELDMASK(MASKID_TranslationDisp) ) THEN + + DO i = 1,Src%NNodes !in case SrcDisp has more nodes that Src (e.g. ElastoDyn blade and tower meshes), I'm using Src%NNodes here + MeshMap%Augmented_Ln2_Src%TranslationDisp(:,i) = SrcDisp%TranslationDisp(:,i) + END DO + + DO i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + + n1=SrcDisp%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2=SrcDisp%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + MeshMap%Augmented_Ln2_Src%TranslationDisp(:,i) = MeshMap%MapSrcToAugmt(i)%shape_fn(1) * SrcDisp%TranslationDisp(:, n1) & + + MeshMap%MapSrcToAugmt(i)%shape_fn(2) * SrcDisp%TranslationDisp(:, n2) + + END DO + + END IF + + !....................................... + ! Force + !....................................... + + IF ( Src%FIELDMASK(MASKID_Force) ) THEN + + DO i = 1,Src%NNodes + MeshMap%Augmented_Ln2_Src%Force(:,i) = Src%Force(:,i) + END DO + + DO i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + + n1=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + MeshMap%Augmented_Ln2_Src%Force(:,i) = MeshMap%MapSrcToAugmt(i)%shape_fn(1) * (Src%Force(:, n1)/LoadsScaleFactor) & + + MeshMap%MapSrcToAugmt(i)%shape_fn(2) * (Src%Force(:, n2)/LoadsScaleFactor) + + MeshMap%Augmented_Ln2_Src%Force(:,i) = MeshMap%Augmented_Ln2_Src%Force(:,i)*LoadsScaleFactor + + END DO + + END IF + + + !....................................... + ! Moment + !....................................... + + IF ( Src%FIELDMASK(MASKID_Moment) ) THEN + + DO i = 1,Src%NNodes + MeshMap%Augmented_Ln2_Src%Moment(:,i) = Src%Moment(:,i) + END DO + + DO i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + + n1=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + MeshMap%Augmented_Ln2_Src%Moment(:,i) = MeshMap%MapSrcToAugmt(i)%shape_fn(1) * (Src%Moment(:, n1)/LoadsScaleFactor) & + + MeshMap%MapSrcToAugmt(i)%shape_fn(2) * (Src%Moment(:, n2)/LoadsScaleFactor) + + MeshMap%Augmented_Ln2_Src%Moment(:,i) = MeshMap%Augmented_Ln2_Src%Moment(:,i)*LoadsScaleFactor + + + END DO + + END IF + + + +END SUBROUTINE Transfer_Src_To_Augmented_Ln2_Src +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine linearizes Transfer_Src_To_Augmented_Ln2_Src (modmesh_mapping::transfer_src_to_augmented_ln2_src). +SUBROUTINE Linearize_Src_To_Augmented_Ln2_Src( Src, MeshMap, ErrStat, ErrMsg, SrcDisp ) +!.................................................................................................................................. + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh containing line2 loads + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mesh mapping data, including the augmented source mesh + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(MeshType), INTENT(IN ) :: SrcDisp !< The displacements associated with the source mesh + + ! local variables + INTEGER(IntKi) :: iElem, i ! do-loop counter for nodes/elements on source + INTEGER(IntKi) :: n, n1, n2, j + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linearize_Src_To_Augmented_Ln2_Src' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !> Matrix \f$ M_{li}^A = M_{mi}^A = M^A \f$, stored in modmesh_mapping::meshmaplinearizationtype::li, + !! is allocated to be size MeshMap\%Augmented_Ln2_Src\%NNodes*3, Src\%NNodes*3. + !> This is the matrix that maps each field of the source mesh to an augmented mesh. + + if (.not. allocated(MeshMap%dM%li) ) then + call AllocAry(MeshMap%dM%li, MeshMap%Augmented_Ln2_Src%NNodes*3, Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(MeshMap%dM%li,1) /= MeshMap%Augmented_Ln2_Src%NNodes*3 .or. size(MeshMap%dM%li,2) /= Src%Nnodes*3 ) then + ! this would happen if we've called the linearization routine multiple times + deallocate(MeshMap%dM%li) + call AllocAry(MeshMap%dM%li, MeshMap%Augmented_Ln2_Src%NNodes*3, Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + MeshMap%dM%li = 0.0_R8Ki + do i=1, Src%Nnodes + do j=1,3 + MeshMap%dM%li( (i-1)*3+j, (i-1)*3+j ) = 1.0_R8Ki + end do + end do + + do i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + do n1=1,NumNodes(ELEMENT_LINE2) + + n = SrcDisp%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(n1) + + do j=1,3 + MeshMap%dM%li( (i-1)*3+j, (n-1)*3+j ) = MeshMap%MapSrcToAugmt(i)%shape_fn(n1) + end do + + end do + + end do + + + !....................................... + ! TranslationDisp (from external mesh to augmented one) + !....................................... + + IF ( SrcDisp%FIELDMASK(MASKID_TranslationDisp) ) THEN + + DO i = 1,Src%NNodes !in case SrcDisp has more nodes that Src (e.g. ElastoDyn blade and tower meshes), I'm using Src%NNodes here + MeshMap%Augmented_Ln2_Src%TranslationDisp(:,i) = SrcDisp%TranslationDisp(:,i) + END DO + + DO i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + + n1=SrcDisp%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2=SrcDisp%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + MeshMap%Augmented_Ln2_Src%TranslationDisp(:,i) = MeshMap%MapSrcToAugmt(i)%shape_fn(1) * SrcDisp%TranslationDisp(:, n1) & + + MeshMap%MapSrcToAugmt(i)%shape_fn(2) * SrcDisp%TranslationDisp(:, n2) + + END DO + + END IF + + !....................................... + ! Force + !> We need the distributed forces on the augmented mesh, so we transfer them in the linearization, too. + !! Note that this is done without the LoadsScaleFactor. + !....................................... + + IF ( Src%FIELDMASK(MASKID_Force) ) THEN + + DO i = 1,Src%NNodes + MeshMap%Augmented_Ln2_Src%Force(:,i) = Src%Force(:,i) + END DO + + DO i = (Src%NNodes+1),MeshMap%Augmented_Ln2_Src%NNodes + iElem = MeshMap%MapSrcToAugmt(i)%OtherMesh_Element + + n1=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2=Src%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + MeshMap%Augmented_Ln2_Src%Force(:,i) = MeshMap%MapSrcToAugmt(i)%shape_fn(1) * Src%Force(:, n1) & + + MeshMap%MapSrcToAugmt(i)%shape_fn(2) * Src%Force(:, n2) + + END DO + + END IF + +END SUBROUTINE Linearize_Src_To_Augmented_Ln2_Src +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine creates a matrix used to "unlump" loads later (needs to have element connectivity information to create it) +SUBROUTINE Create_InverseLumping_Matrix( Dest, MeshMap, ErrStat, ErrMsg ) + TYPE(MeshType), INTENT(IN ) :: Dest !< destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mesh mapping data + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(ReKi) :: c, TwoC + + INTEGER(IntKi) :: N, n1, n2 ! node numbers + INTEGER(IntKi) :: j,k, iElem, iComp + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Create_InverseLumping_Matrix' + + + ErrStat = ErrID_None + ErrMsg = "" + + n = Dest%Nnodes* 3 + + IF ( ALLOCATED(MeshMap%LoadLn2_A_Mat) ) THEN + IF ( SIZE(MeshMap%LoadLn2_A_Mat,1) < n ) THEN + DEALLOCATE(MeshMap%LoadLn2_A_Mat) + DEALLOCATE(MeshMap%LoadLn2_A_Mat_piv) + DEALLOCATE(MeshMap%LoadLn2_F) + DEALLOCATE(MeshMap%LoadLn2_M) + CALL AllocInvLumpingArrays() + IF (ErrStat >= AbortErrLev) RETURN + END IF + ELSE + CALL AllocInvLumpingArrays() + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + ! factor the "A" matrix for the solve later: + + MeshMap%LoadLn2_A_Mat = 0.0_ReKi + + ! loop over source mesh, integrating over each element + do iElem = 1, Dest%ElemTable(ELEMENT_LINE2)%nelem + + n1 = Dest%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(1) + n2 = Dest%ElemTable(ELEMENT_LINE2)%Elements(iElem)%ElemNodes(2) + + c = Dest%ElemTable(ELEMENT_LINE2)%Elements(iElem)%det_jac / 3.0_ReKi != TwoNorm( p(n2)-p(n1) )/6 + TwoC = 2.0_ReKi * c + + do iComp=1,3 !3 components of force + j = (n1-1)*3 + iComp ! this is the index of the node/component of the lumped value + k = (n2-1)*3 + iComp ! the is the portion of the "lesser" node + + MeshMap%LoadLn2_A_Mat(j,j) = MeshMap%LoadLn2_A_Mat(j,j) + TwoC + MeshMap%LoadLn2_A_Mat(k,k) = MeshMap%LoadLn2_A_Mat(k,k) + TwoC + MeshMap%LoadLn2_A_Mat(j,k) = MeshMap%LoadLn2_A_Mat(j,k) + c + MeshMap%LoadLn2_A_Mat(k,j) = MeshMap%LoadLn2_A_Mat(k,j) + c + enddo !icomp + enddo !i + + CALL LAPACK_getrf(n,n,MeshMap%LoadLn2_A_Mat,MeshMap%LoadLn2_A_Mat_piv, ErrStat, ErrMsg) + +!........................................................................................................ +CONTAINS + SUBROUTINE AllocInvLumpingArrays + + CALL AllocAry( MeshMap%LoadLn2_A_Mat, n, n, 'MeshMap%LoadLn2_A_Mat', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL AllocAry( MeshMap%LoadLn2_A_Mat_piv, n, 'MeshMap%LoadLn2_A_Mat_piv',ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL AllocAry( MeshMap%LoadLn2_F, n, 1, 'MeshMap%LoadLn2_F', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL AllocAry( MeshMap%LoadLn2_M, n, 1, 'MeshMap%LoadLn2_M', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + END SUBROUTINE AllocInvLumpingArrays + +END SUBROUTINE Create_InverseLumping_Matrix +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine creates the mapping from a line2 mesh with loads to another line2 mesh. +SUBROUTINE CreateLoadMap_L2_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data + + 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 + character(*), parameter :: RoutineName = 'CreateLoadMap_L2_to_L2' + + ErrStat = ErrID_None + ErrMsg = "" + + + !........................ + !> + Create a matrix used to "unlump" loads later (needs to have element connectivity information to create it) + !........................ + CALL Create_InverseLumping_Matrix( Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + !........................ + !> + An augmented Line2-element source mesh is formed + !! by splitting the original Line2-element source mesh at each location where a + !! destination-mesh Line2-element node projects orthogonally from the destination mesh + !........................ + + CALL Create_Augmented_Ln2_Src_Mesh(Src, Dest, MeshMap, ELEMENT_LINE2, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + !........................ + !> + For each Line2-element node of the augmented source mesh, + !! a nearest-neighbor Line2 element of the destination mesh is found (else aborted) in the reference configuration, + !! for which the source Line2-element node projects orthogonally onto the destination Line2-element domain. + !! A destination-mesh Line2 element may be associated with multiple source-mesh Line2-element nodes. + !........................ + + CALL CreateMapping_ProjectToLine2(MeshMap%Augmented_Ln2_Src, Dest, MeshMap%MapLoads, ELEMENT_LINE2, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + !........................ + !> + Create a temporary mesh for lumped point elements of the line2 source + !........................ + CALL Create_PointMesh( MeshMap%Augmented_Ln2_Src, MeshMap%Lumped_Points_Src, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + +END SUBROUTINE CreateLoadMap_L2_to_L2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine creates the mapping of motions between two meshes +SUBROUTINE CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< structure that contains data necessary to map these two meshes + + 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 = "" + + + CALL CreateMapping_ProjectToLine2(Dest,Src, MeshMap%MapMotions, ELEMENT_LINE2, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_L2_to_L2') + IF (ErrStat >= AbortErrLev) RETURN + +END SUBROUTINE CreateMotionMap_L2_to_L2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes a Line2 mesh (SRC) with distributed forces and/or moments and lumps those to the concentrated forces +!! and/or moments at the endpoints (nodes) of the Line2 mesh. These are placed in a Point mesh (DEST) where the Points are +!! assumed to be colocated with the nodes of the Line2 Mesh. +!! +!! This routine is expected to be used in the transfer of HydroDyn Output (distributed force/moment) to the SubDyn Input +!! (concentrated force/moment); routine is to be called from the Input_Ouput routine for HydroDyn to SubDyn. +!! +!! Formulation: +!! Distrbuted quantities are integrated over the element with two-point nodal (Gauss-Lobatto) quadrature. +!! +!! F(x_j) = int_{-1}^{1} f(xi) phi_j(xi) J dxi (exact) +!! +!! F(x_1) =~ f(-1) phi_1(-1) J w_1 + f(+1) phi_1(+1) J w_2 (two-point quadrature) +!! F(x_2) =~ f(-1) phi_2(-1) J w_1 + f(+1) phi_2(+1) J w_2 (two-point quadrature) +!! +!! which can be simplified to +!! +!! F(x_1) =~ f(-1) J +!! F(x_2) =~ f(+1) J +!! +!! since w_1 = w_2 = 1, phi_j(xi_i) = Delta_{j,i} (Kronecker Delta) +!! +!! where x_j is the jth node in 3D physical coordinates, xi_i is the ith node in 1D element coordinates, j in {1,2}, +!! xi in [-1,1] is the element natural coordinate, f(xi) is the distributed quantity, phi_j(xi) is the basis function +!! for the jth node, J is the determinant of the Jacobian +!! in the mapping from [X_1,X_2] to [-1,1] (X_j is the 3D location of the jth point) +!! +!! For Line2 elements, J = DIST(X_1,X_2) / 2 +!! +SUBROUTINE Lump_Line2_to_Point( Line2_Src, Point_Dest, ErrStat, ErrMsg, SrcDisp, LoadsScaleFactor ) + + TYPE(MeshType), INTENT(IN ) :: Line2_Src !< line2 source mesh + TYPE(MeshType), INTENT(INOUT) :: Point_Dest !< point destination mesh + TYPE(MeshType),OPTIONAL,INTENT(IN ) :: SrcDisp !< Another mesh that may contain the source's TranslationDisp field + + REAL(ReKi), INTENT(IN) :: LoadsScaleFactor !< Scaling factor for loads (to help with numerical issues) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(ReKi) :: det_jac_Ovr3 +! REAL(ReKi) :: n1_n2_vector(3) ! vector going from node 1 to node 2 in a Line2 element + REAL(ReKi) :: pCrossf(3) ! a temporary vector storing cross product of positions with forces + REAL(ReKi) :: p1(3), p2(3) ! temporary position vectors + REAL(ReKi) :: dp(3) ! a temporary vector storing p2-p1 + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: nnodes + + INTEGER(IntKi) :: n1 + INTEGER(IntKi) :: n2 + character(*), parameter :: RoutineName = 'Lump_Line2_to_Point' + + + ErrStat = ErrID_None + ErrMsg = "" + +#ifdef MESH_DEBUG + ! bjj: we shouldn't have to check this in production mode; this routine is an internal one only. + + if (Line2_Src%ElemTable(ELEMENT_LINE2)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Source mesh must have one or more Line2 Elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Point_Dest%ElemTable(ELEMENT_POINT)%nelem .eq. 0) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh must have one or more Point Elements.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Line2_Src%nnodes .ne. Point_Dest%nnodes) then + CALL SetErrStat( ErrID_Fatal, 'Source and Destination meshes must have same number of Nodes.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + + if (Point_Dest%FieldMask(MASKID_FORCE) ) then + if (.not. Line2_Src%FieldMask(MASKID_FORCE) ) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh contains Force, but Source does not.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + endif +!bjj: this may not be covered... + if (Point_Dest%FieldMask(MASKID_MOMENT) ) then + if (.not. Line2_SRC%FieldMask(MASKID_MOMENT) ) then + CALL SetErrStat( ErrID_Fatal, 'Destination mesh contains Moment, but Source does not.', ErrStat, ErrMsg, RoutineName) + RETURN + endif + endif + +#endif + + ! see equations 40-43 of Spraque, Jonkman, and Jonkman [2014] + + nnodes = Point_Dest%nnodes ! also = Line2_Src%nnodes + + if ( Point_Dest%FieldMask(MASKID_TRANSLATIONDISP) ) then + Point_Dest%TranslationDisp = Line2_Src%TranslationDisp + end if + + + ! initialize force/moment in Dest + if (Point_Dest%FieldMask(MASKID_FORCE) ) Point_Dest%Force = 0. + if (Point_Dest%FieldMask(MASKID_MOMENT) ) Point_Dest%Moment = 0. + + ! loop over source mesh, integrating over each element + do i = 1, Line2_Src%ElemTable(ELEMENT_LINE2)%nelem + + n1 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) + n2 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) + + !n1_n2_vector = Line2_Src%Position(:,n2) - Line2_Src%Position(:,n1) + ! + !det_jac_Ovr3 = SQRT( DOT_PRODUCT(n1_n2_vector,n1_n2_vector) ) / 6._ReKi = L / 6 = det_jac/3. + + det_jac_Ovr3 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%det_jac / 3.0_ReKi + + + if (Point_Dest%FieldMask(MASKID_FORCE) ) then + + Point_Dest%Force(:,n1) = Point_Dest%Force(:,n1) + det_jac_Ovr3 * ( 2.*(Line2_Src%Force(:,n1)/LoadsScaleFactor) + (Line2_Src%Force(:,n2)/LoadsScaleFactor) ) + Point_Dest%Force(:,n2) = Point_Dest%Force(:,n2) + det_jac_Ovr3 * ( (Line2_Src%Force(:,n1)/LoadsScaleFactor) + 2.*(Line2_Src%Force(:,n2)/LoadsScaleFactor) ) + + endif + + if (Point_Dest%FieldMask(MASKID_MOMENT) ) then + + Point_Dest%Moment(:,n1) = Point_Dest%Moment(:,n1) + det_jac_Ovr3 * ( 2.*(Line2_Src%Moment(:,n1)/LoadsScaleFactor) + (Line2_Src%Moment(:,n2)/LoadsScaleFactor) ) + Point_Dest%Moment(:,n2) = Point_Dest%Moment(:,n2) + det_jac_Ovr3 * ( (Line2_Src%Moment(:,n1)/LoadsScaleFactor) + 2.*(Line2_Src%Moment(:,n2)/LoadsScaleFactor) ) + + + if ( Point_Dest%FieldMask(MASKID_FORCE) ) then + + p1 = Line2_Src%Position(:,n1) + p2 = Line2_Src%Position(:,n2) + + IF ( PRESENT(SrcDisp) ) THEN + p1 = p1 + SrcDisp%TranslationDisp(:,n1) + p2 = p2 + SrcDisp%TranslationDisp(:,n2) + ELSEIF (Line2_Src%FieldMask(MASKID_TRANSLATIONDISP)) THEN + p1 = p1 + Line2_Src%TranslationDisp(:,n1) + p2 = p2 + Line2_Src%TranslationDisp(:,n2) + END IF + + dp = p2-p1 + pCrossf = (Line2_Src%Force(:,n1)/LoadsScaleFactor) + (Line2_Src%Force(:,n2)/LoadsScaleFactor) !temp storage of f to avoid array creating in cross_product + pCrossf = 0.5*det_jac_Ovr3 *cross_product( dp, pCrossf) + + Point_Dest%Moment(:,n1) = Point_Dest%Moment(:,n1) + pCrossf + Point_Dest%Moment(:,n2) = Point_Dest%Moment(:,n2) - pCrossf + + end if ! src moment AND force + + endif + + enddo + + if (Point_Dest%FieldMask(MASKID_FORCE) ) Point_Dest%Force = Point_Dest%Force * LoadsScaleFactor + if (Point_Dest%FieldMask(MASKID_MOMENT) ) Point_Dest%Moment = Point_Dest%Moment* LoadsScaleFactor + + +END SUBROUTINE Lump_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine linearizes the lumping of distributed loads to point loads. +SUBROUTINE Linearize_Lump_Line2_to_Point( Line2_Src, Point_Dest, dM, ErrStat, ErrMsg ) + + TYPE(MeshType), INTENT(IN ) :: Line2_Src !< line2 source mesh + TYPE(MeshType), INTENT(INOUT) :: Point_Dest !< point destination mesh + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + type(MeshMapLinearizationType), intent(inout) :: dM !< data structure for linearization + + + ! local variables + REAL(R8Ki) :: c, TwoC + + INTEGER(IntKi) :: n1, n2 ! node numbers + INTEGER(IntKi) :: i, j, k, iComp + Integer(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'Linearize_Lump_Line2_to_Point' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! identity for forces and/or moments: + + !> Matrix \f$ M_{li}^{SL} \f$, stored in modmesh_mapping::meshmaplinearizationtype::li, + !! is allocated to be size Point_Dest\%NNodes*3, Line2_Src\%NNodes*3 (a square matrix). + !! This is the block matrix that maps each field of the distributed source mesh to its identical field on the point (lumped) mesh. + !! (i.e., force component of force; moment component of moment). + + if (.not. allocated(dM%li) ) then + call AllocAry(dM%li, Point_Dest%Nnodes*3, Line2_Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) !Line2_Src%Nnodes should equal Point_Dest%Nnodes + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(dM%li,1) /= Point_Dest%Nnodes*3 .or. size(dM%li,2) /= Line2_Src%Nnodes*3) then + deallocate(dM%li) + call AllocAry(dM%li, Point_Dest%Nnodes*3, Line2_Src%Nnodes*3, 'dM%li', ErrStat2, ErrMsg2 ) !Line2_Src%Nnodes should equal Point_Dest%Nnodes + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + dM%li = 0.0_R8Ki + ! loop over source mesh, integrating over each element + do i = 1, Line2_Src%ElemTable(ELEMENT_LINE2)%nelem + + n1 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) + n2 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) + + c = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%det_jac / 3.0_R8Ki != TwoNorm( p(n2)-p(n1) )/6 = det_jac/3 + TwoC = 2.0_R8Ki * c + + do iComp=1,3 !3 components of force or moment + j = (n1-1)*3 + iComp ! this is the index of the node/component of the lumped value + k = (n2-1)*3 + iComp ! the is the portion of the "lesser" node + + dM%li(j,j) =dM%li(j,j) + TwoC + dM%li(k,k) =dM%li(k,k) + TwoC + dM%li(j,k) =dM%li(j,k) + c + dM%li(k,j) =dM%li(k,j) + c + enddo !icomp + enddo !i = iElem + + + + ! M_uD and m_f for moments: + + if ( Point_Dest%FieldMask(MASKID_MOMENT) .AND. Line2_Src%FieldMask(MASKID_FORCE) ) then + + call FormMatrix_Lump_Line2_to_Point( Line2_Src, dM, ErrStat2, ErrMsg2, Line2_Src ) !Line2_Src is assumed to contain the displaced positions as well as the loads + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + !> Matrix \f$ M_{um}^{SL} \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_ud, + !! is allocated to be size Point_Dest\%NNodes*3, Line2_Src\%NNodes*3 (a square matrix). + !! This is the block matrix that relates the translational displacement (u) to the lumped moment. + !! > Note this could be considered either m_ud or m_us, depending on context. + + !> Matrix \f$ M_{fm}^{SL} \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_f, + !! is allocated to be size Point_Dest\%NNodes*3, Line2_Src\%NNodes*3 (a square matrix). + !> This is the block matrix that relates the force (f) to the lumped moment. + + + !> We also transfer the force to the destination mesh so that we can use these values for creating the appropriate matrices later + if (Point_Dest%FieldMask(MASKID_FORCE) ) then + Point_Dest%Force = 0. + ! loop over source mesh, integrating over each element + do i = 1, Line2_Src%ElemTable(ELEMENT_LINE2)%nelem + + n1 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) + n2 = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) + + c = Line2_Src%ElemTable(ELEMENT_LINE2)%Elements(i)%det_jac / 3.0_ReKi != TwoNorm( p(n2)-p(n1) )/6 = det_jac_Ovr3 + + Point_Dest%Force(:,n1) = Point_Dest%Force(:,n1) + c * ( 2.0_ReKi*Line2_Src%Force(:,n1) + Line2_Src%Force(:,n2) ) + Point_Dest%Force(:,n2) = Point_Dest%Force(:,n2) + c * ( Line2_Src%Force(:,n1) + 2.0_ReKi*Line2_Src%Force(:,n2) ) + + end do + end if + end if + + +END SUBROUTINE Linearize_Lump_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FormMatrix_Lump_Line2_to_Point( Mesh, dM, ErrStat, ErrMsg, DispMesh ) + + TYPE(MeshType), INTENT(IN ) :: Mesh !< mesh that has loads being lumped + TYPE(MeshType), INTENT(IN ) :: DispMesh !< mesh that has displaced position of Mesh + type(MeshMapLinearizationType), intent(inout) :: dM !< data structure for linearization + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + REAL(ReKi) :: c, x(3), SSmat(3,3) + + INTEGER(IntKi) :: n1_start, n1_end ! node numbers + INTEGER(IntKi) :: n2_start, n2_end ! node numbers + + INTEGER(IntKi) :: n1, n2 ! node numbers + INTEGER(IntKi) :: i + Integer(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'FormMatrix_Lump_Line2_to_Point' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! M_uD and m_f for moments: + + !> Matrix \f$ M_{uDm}^{L} \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_ud, + !! is allocated to be size Mesh\%NNodes*3, Mesh\%NNodes*3 (a square matrix). + !> This is the block matrix that relates the destination translational displacement (u) to the lumped moment. + + if (.not. allocated(dM%m_uD) ) then + call AllocAry(dM%m_uD, Mesh%Nnodes*3, Mesh%Nnodes*3, 'dM%m_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(dM%m_uD,1) /= Mesh%Nnodes*3 .or. size(dM%m_uD,2) /= Mesh%Nnodes*3) then + deallocate(dM%m_uD) + call AllocAry(dM%m_uD, Mesh%Nnodes*3, Mesh%Nnodes*3, 'dM%m_uD', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + !> Matrix \f$ M_{fm}^{L} \f$, stored in modmesh_mapping::meshmaplinearizationtype::m_f, + !! is allocated to be size Mesh\%NNodes*3, Mesh\%NNodes*3 (a square matrix). + !> This is the block matrix that relates the force (f) to the lumped moment. + + if (.not. allocated(dM%m_f) ) then + call AllocAry(dM%m_f, Mesh%Nnodes*3, Mesh%Nnodes*3, 'dM%m_f', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + elseif (size(dM%m_f,1) /= Mesh%Nnodes*3 .or. size(dM%m_f,2) /= Mesh%Nnodes*3) then + deallocate(dM%m_f) + call AllocAry(dM%m_f, Mesh%Nnodes*3, Mesh%Nnodes*3, 'dM%m_f', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + dM%m_uD = 0.0_ReKi + dM%m_f = 0.0_ReKi + do i = 1, Mesh%ElemTable(ELEMENT_LINE2)%nelem + + n1 = Mesh%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(1) + n2 = Mesh%ElemTable(ELEMENT_LINE2)%Elements(i)%ElemNodes(2) + + n1_start = (n1-1)*3+1 + n1_end = n1_start+2 + n2_start = (n2 - 1)*3+1 + n2_end = n2_start+2 + + c = Mesh%ElemTable(ELEMENT_LINE2)%Elements(i)%det_jac / 6.0_ReKi != TwoNorm( p(n2)-p(n1) )/12 + + ! dM%m_uS (portion that gets multiplied by u [TranslationDisp]) + + x = Mesh%Force(:,n1) + Mesh%Force(:,n2) + x = x*c + SSmat = SkewSymMat(x) + + dM%m_uD( n1_start:n1_end, n1_start:n1_end ) = dM%m_uD( n1_start:n1_end, n1_start:n1_end ) + SSmat + dM%m_uD( n2_start:n2_end, n1_start:n1_end ) = dM%m_uD( n2_start:n2_end, n1_start:n1_end ) - SSmat + + dM%m_uD( n1_start:n1_end, n2_start:n2_end ) = dM%m_uD( n1_start:n1_end, n2_start:n2_end ) - SSmat + dM%m_uD( n2_start:n2_end, n2_start:n2_end ) = dM%m_uD( n2_start:n2_end, n2_start:n2_end ) + SSmat + + + ! m_f (portion that gets multiplied by f [Force]) + x = Mesh%Position(:,n2) + DispMesh%TranslationDisp(:,n2) - & + (Mesh%Position(:,n1) + DispMesh%TranslationDisp(:,n1)) + x = x*c + SSmat = SkewSymMat(x) + + dM%m_f( n1_start:n1_end, n1_start:n1_end ) = dM%m_f( n1_start:n1_end, n1_start:n1_end ) + SSmat + dM%m_f( n2_start:n2_end, n1_start:n1_end ) = dM%m_f( n2_start:n2_end, n1_start:n1_end ) - SSmat + + dM%m_f( n1_start:n1_end, n2_start:n2_end ) = dM%m_f( n1_start:n1_end, n2_start:n2_end ) + SSmat + dM%m_f( n2_start:n2_end, n2_start:n2_end ) = dM%m_f( n2_start:n2_end, n2_start:n2_end ) - SSmat + enddo !i = iElem + + +END SUBROUTINE FormMatrix_Lump_Line2_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine creates the linearization matrices for transfer of fields between point meshes. +!! Mapping equations are as follows: +!! +!> Rotational Displacement: \f$ \frac{\partial M_\Lambda}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$ \left\{ \vec{\theta}^S\right\}\f$ +!! +!> Translational Displacement: \f$ \frac{\partial M_u}{\partial x} = \begin{bmatrix} M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^S \\ +!! \vec{\theta}^S +!! \end{matrix} \right\} \f$ +!! +!> Rotational Velocity: \f$ \frac{\partial M_\omega}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{\omega}^S\right\}\f$ +!! +!! Translational Velocity: \f$ \frac{\partial M_v}{\partial x} = \begin{bmatrix} M_{tv\_uD} & M_{tv\_uS} & M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{v}^S \\ +!! \vec{\omega}^S +!! \end{matrix} \right\} \f$ +!! +!! Rotational Acceleration: \f$ \frac{\partial M_\alpha}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{\alpha}^S\right\}\f$ +!! +!! Translational Acceleration: \f$ \frac{\partial M_a}{\partial x} = \begin{bmatrix} M_{ta\_uD} & M_{ta\_uS} & M_{ta\_rv} & M_{mi} & M_{f_{\times p}} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{\omega}^S \\ +!! \vec{a}^S \\ +!! \vec{\alpha}^S +!! \end{matrix} \right\} \f$ +!! +!! Scalar quantities: \f$ \frac{\partial M_S}{\partial x} = \begin{bmatrix} M_{mi} \end{bmatrix} \f$ for source fields \f$\left\{\vec{S}^S\right\}\f$ +!! +!! Forces: \f$ \frac{\partial M_F}{\partial x} = \begin{bmatrix} M_{li} \end{bmatrix} \f$ for source fields \f$\left\{\vec{F}^S\right\}\f$ +!! +!! Moments: \f$ \frac{\partial M_M}{\partial x} = \begin{bmatrix} M_{uDm} & M_{uSm} & M_{fm} & M_{li} \end{bmatrix} \f$ for source fields +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^D \\ +!! \vec{u}^S \\ +!! \vec{F}^S \\ +!! \vec{M}^S +!! \end{matrix} \right\} \f$ +!! +!! \f$M_{mi}\f$ is modmesh_mapping::meshmaplinearizationtype::mi \n +!! \f$M_{f_{\times p}}\f$ is modmesh_mapping::meshmaplinearizationtype::fx_p \n +!! \f$M_{tv\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uD \n +!! \f$M_{tv\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uS \n +!! \f$M_{ta\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uD \n +!! \f$M_{ta\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uS \n +!! \f$M_{ta\_rv}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_rv \n +!! \f$M_{li}\f$ is modmesh_mapping::meshmaplinearizationtype::li \n +!! \f$M_{uSm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_us \n +!! \f$M_{uDm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_ud \n +!! \f$M_{fm}\f$ is modmesh_mapping::meshmaplinearizationtype::m_f +!! +SUBROUTINE Linearize_Point_to_Point( Src, Dest, MeshMap, ErrStat, ErrMsg, SrcDisp, DestDisp ) + + TYPE(MeshType), INTENT(IN ) :: Src !< source point mesh + TYPE(MeshType), INTENT(IN ) :: Dest !< destination mesh + TYPE(MeshType), OPTIONAL,INTENT(IN ) :: SrcDisp !< an optional mesh, which contains the displacements associated with the source if the source contains load information + TYPE(MeshType), OPTIONAL,INTENT(IN ) :: DestDisp !< an optional mesh, which contains the displacements associated with the destination if the destination contains load information + + TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< Mapping(s) between Src and Dest meshes; also contains jacobian of this mapping + + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'Linearize_Point_to_Point' + + + ! logic + + ErrStat = ErrID_None + ErrMsg = '' + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Transfer of Data for Mesh Motion and Scalar Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + ! If Src is displacements/velocities then loop over the Destination Mesh; + ! each motion/scalar in the destination mesh needs to be interpolated from the source mesh. + + + if ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) then + + !........................ + !> * Create mapping (if remapFlag) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + !> * Create linearization matrices for motions + !........................ + + call Linearize_Motions_Point_to_Point(Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if ! HasMotionFields: algorithm for motions/scalars + + ! ------------------------------------------------------------------------------------------------------------------------------ + !> ### Mapping and Transfer of Data for Mesh Load Fields + ! ------------------------------------------------------------------------------------------------------------------------------ + + if ( HasLoadFields(Src) ) then + + !........................ + !> * Create mapping (if RemapFlag) + !........................ + + if (Src%RemapFlag .or. Dest%RemapFlag ) then + + CALL CreateLoadMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + end if + + !........................ + !> * Create linearization matrices for loads + !........................ + + IF ( PRESENT( SrcDisp ) .AND. PRESENT( DestDisp ) ) THEN + + call Linearize_Loads_Point_to_Point( Src, Dest, MeshMap, ErrStat2, ErrMsg2, SrcDisp, DestDisp ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ELSE !bjj: we could check if Src also had TranslationDisp fields and call with SrcDisp=Src + CALL SetErrStat( ErrID_Fatal, 'Meshes with load fields must also have sibling meshes with displacment field.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + end if ! algorithm for loads + + + +END SUBROUTINE Linearize_Point_to_Point +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> This routine is used for debugging mesh mappings. It checks to see that the sum of the loads on each mesh is the same as when +!! all the loads from each mesh are lumped to a single point. +SUBROUTINE WriteMappingTransferToFile(Mesh1_I,Mesh1_O,Mesh2_I,Mesh2_O,Map_Mod1_Mod2,Map_Mod2_Mod1,BinOutputName) + + TYPE(meshtype), intent(in) :: mesh1_I !< mesh 1 inputs + TYPE(meshtype), intent(in) :: mesh1_O !< mesh 1 outputs + TYPE(meshtype), intent(in) :: mesh2_I !< mesh 2 inputs + TYPE(meshtype), intent(in) :: mesh2_O !< mesh 2 outputs + + TYPE(MeshMapType), intent(in) :: Map_Mod1_Mod2 !< Data for mapping meshes from mesh 1 (outputs) to mesh 2 (inputs) + TYPE(MeshMapType), intent(in) :: Map_Mod2_Mod1 !< Data for mapping meshes from mesh 2 (outputs) to mesh 1 (inputs) + + CHARACTER(*), INTENT(IN) :: BinOutputName !< name of binary output file + + + ! local variables: + TYPE(meshtype) :: mesh_Motion_1PT, mesh1_I_1PT, mesh2_O_1PT + TYPE(MeshMapType) :: Map_Mod2_O_1PT, Map_Mod1_I_1PT + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: un_out + INTEGER(IntKi) :: ErrStat ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg ! Error message if ErrStat /= ErrID_None + CHARACTER(256) :: PrintWarnF, PrintWarnM, TmpValues + +#ifdef MESH_DEBUG + TYPE(meshtype) :: mesh2_O_1PT_augmented, mesh2_O_1PT_lumped, mesh1_I_1PT_lumped + TYPE(MeshMapType) :: Map_Mod2_O_1PT_augmented, Map_Mod2_O_1PT_lumped, Map_Mod1_I_1PT_lumped +#endif + + + !------------------------------------------------------------------------ + ! Make sure the meshes are committed before checking them: + !------------------------------------------------------------------------ + + IF (.NOT. mesh1_I%Committed .OR. .NOT. mesh1_O%Committed ) RETURN + IF (.NOT. mesh2_I%Committed .OR. .NOT. mesh2_O%Committed ) RETURN + + !------------------------------------------------------------------------ + ! lump the loads to one point and compare: + !------------------------------------------------------------------------ + + ! create one loads mesh with one point: + CALL MeshCreate( BlankMesh = mesh1_I_1PT & + , IOS = COMPONENT_INPUT & + , NNodes = 1 & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + CALL MeshPositionNode ( mesh1_I_1PT, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/), ErrStat, ErrMsg ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshConstructElement ( mesh1_I_1PT, ELEMENT_POINT, ErrStat, ErrMsg, 1 ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshCommit ( mesh1_I_1PT, ErrStat, ErrMsg ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !..... + ! create a corresponding motion mesh with one point: + + CALL MeshCopy( mesh1_I_1PT, mesh_Motion_1PT, MESH_SIBLING, ErrStat, ErrMsg & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + !..... + ! create a second loads mesh with one point: + CALL MeshCopy( mesh1_I_1PT, mesh2_O_1PT, MESH_NEWCOPY, ErrStat, ErrMsg ) ! This thinks it's for input, but really it's for output. I don't think it matters... + + !..... + ! create the mapping data structures: + CALL MeshMapCreate( Mesh1_I, Mesh1_I_1PT, Map_Mod1_I_1PT, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapCreate( Mesh2_O, Mesh2_O_1PT, Map_Mod2_O_1PT, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !..... + ! transfer MESH1_I (loads) to single point: + + IF ( mesh1_I%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN + CALL Transfer_Point_to_Point( Mesh1_I, Mesh1_I_1PT, Map_Mod1_I_1PT,ErrStat,ErrMsg,mesh1_O,mesh_Motion_1PT); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + ELSEIF ( mesh1_I%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN + CALL Transfer_Line2_to_Point( Mesh1_I, Mesh1_I_1PT, Map_Mod1_I_1PT,ErrStat,ErrMsg,mesh1_O,mesh_Motion_1PT); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END IF + + !..... + ! transfer Mesh2_O (loads) to single point: + IF ( Mesh2_O%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN + CALL Transfer_Point_to_Point( Mesh2_O, Mesh2_O_1PT, Map_Mod2_O_1PT,ErrStat,ErrMsg,mesh2_I,mesh_Motion_1PT); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + ELSEIF ( Mesh2_O%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN + CALL Transfer_Line2_to_Point( Mesh2_O, Mesh2_O_1PT, Map_Mod2_O_1PT,ErrStat,ErrMsg,mesh2_I,mesh_Motion_1PT); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END IF + !............ + + ! dsisplay a warning if the point loads are not equal: + PrintWarnF="" + PrintWarnM="" + do i=1,3 + if (.NOT. equalrealnos(mesh1_I_1PT%Force( i,1),mesh2_O_1PT%Force( i,1)) ) PrintWarnF=NewLine//" <----------- WARNING: Forces are not equal -----------> "//NewLine//NewLine + if (.NOT. equalrealnos(mesh1_I_1PT%Moment(i,1),mesh2_O_1PT%Moment(i,1)) ) PrintWarnM=NewLine//" <----------- WARNING: Moments are not equal -----------> "//NewLine//NewLine + end do + + + call wrscr(TRIM(PrintWarnF)//'Total Force:' ) + write(TmpValues,*) mesh1_I_1PT%Force; call wrscr(' Mesh 1: '//TRIM(TmpValues)) + write(TmpValues,*) mesh2_O_1PT%Force; call wrscr(' Mesh 2: '//TRIM(TmpValues)) + call wrscr(TRIM(PrintWarnM)//'Total Moment:' ) + write(TmpValues,*) mesh1_I_1PT%Moment; call wrscr(' Mesh 1: '//TRIM(TmpValues)) + write(TmpValues,*) mesh2_O_1PT%Moment; call wrscr(' Mesh 2: '//TRIM(TmpValues)) + !............ + + !------------------------------------------------------------------------ + ! now we'll write all the mesh info to a file for debugging: + !------------------------------------------------------------------------ + + un_out = -1 + CALL MeshWrBin ( un_out, Mesh1_I, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshWrBin ( un_out, Mesh1_O, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshWrBin ( un_out, Mesh2_I, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshWrBin ( un_out, Mesh2_O, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshWrBin ( un_out, mesh1_I_1PT, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshWrBin ( un_out, mesh2_O_1PT, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshWrBin ( un_out, mesh_Motion_1PT, ErrStat, ErrMsg, BinOutputName); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshMapWrBin( un_out, Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg, BinOutputName ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapWrBin( un_out, Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, BinOutputName ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshMapWrBin( un_out, Mesh1_I, Mesh1_I_1PT, Map_Mod1_I_1PT, ErrStat, ErrMsg, BinOutputName ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapWrBin( un_out, Mesh2_O, Mesh2_O_1PT, Map_Mod2_O_1PT, ErrStat, ErrMsg, BinOutputName ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + close( un_out ) + + + +#ifdef MESH_DEBUG + +if (LEN_TRIM(PrintWarnM)>0 .OR. LEN_TRIM(PrintWarnF)>0 ) THEN + call wrscr(NewLine) + call wrmatrix( mesh1_O%TranslationDisp, CU, 'f10.5') + call wrscr(NewLine) + ! call wrmatrix( mesh2_I%TranslationDisp, CU, 'f10.5') + ! call wrmatrix( mesh_Motion_1PT%TranslationDisp, CU, 'f10.5') + ! call wrmatrix( mesh_Motion_1PT%Position, CU, 'f10.5') + + + if (Map_Mod2_Mod1%Augmented_Ln2_Src%committed) THEN + CALL MeshCopy( Mesh2_O_1PT, mesh2_O_1PT_augmented, MESH_NEWCOPY, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + mesh2_O_1PT_augmented%force = 0.0 + mesh2_O_1PT_augmented%moment = 0.0 + ! Map_Mod2_Mod1%Augmented_Ln2_Src%TranslationDisp=0.0 + CALL MeshMapCreate( Map_Mod2_Mod1%Augmented_Ln2_Src, mesh2_O_1PT_augmented, Map_Mod2_O_1PT_augmented, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL Transfer_Line2_to_Point(Map_Mod2_Mod1%Augmented_Ln2_Src, mesh2_O_1PT_augmented, Map_Mod2_O_1PT_augmented, ErrStat, ErrMsg, Map_Mod2_Mod1%Augmented_Ln2_Src, mesh_Motion_1PT ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !print *, '---------Augmented_Ln2_Src:---------------' + !call meshprintinfo(CU,Map_Mod2_Mod1%Augmented_Ln2_Src) + end if + + if (Map_Mod2_Mod1%Lumped_Points_Src%committed) THEN + CALL MeshCopy( Mesh2_O_1PT, mesh2_O_1PT_lumped, MESH_NEWCOPY, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapCreate( Map_Mod2_Mod1%Lumped_Points_Src, mesh2_O_1PT_lumped, Map_Mod2_O_1PT_lumped, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL Transfer_Point_to_Point(Map_Mod2_Mod1%Lumped_Points_Src, mesh2_O_1PT_lumped, Map_Mod2_O_1PT_lumped, ErrStat, ErrMsg, Map_Mod2_Mod1%Lumped_Points_Src, mesh_Motion_1PT ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !print *, '-------------Lumped_Points_Src:----------------' + !call meshprintinfo(CU,Map_Mod2_Mod1%Lumped_Points_Src) + end if + + if (Map_Mod2_Mod1%Lumped_Points_Dest%committed) THEN + CALL MeshCopy( Mesh1_I_1PT, mesh1_I_1PT_lumped, MESH_NEWCOPY, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapCreate( Map_Mod2_Mod1%Lumped_Points_Dest, mesh1_I_1PT_lumped, Map_Mod1_I_1PT_lumped, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL Transfer_Point_to_Point(Map_Mod2_Mod1%Lumped_Points_Dest, mesh1_I_1PT_lumped, Map_Mod1_I_1PT_lumped, ErrStat, ErrMsg, mesh1_O, mesh_Motion_1PT ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !print *, '-----------Lumped_Points_Dest:---------------' + !call meshprintinfo(CU,Map_Mod2_Mod1%Lumped_Points_Dest) + end if + + + call wrscr('Total Force:' ) + if (mesh2_O_1PT_augmented%committed) then + write(TmpValues,*) mesh2_O_1PT_augmented%Force + call wrscr(' Mesh 2 (augmented):'//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Augmented_Ln2_Src%Nnodes )) ) + end if + + if (mesh2_O_1PT_lumped%committed) then + write(TmpValues,*) mesh2_O_1PT_lumped%Force + call wrscr(' Mesh 2 (lumped): '//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Lumped_Points_Src%Nnodes )) ) + end if + + if (mesh1_I_1PT_lumped%committed) then + write(TmpValues,*) mesh1_I_1PT_lumped%Force + call wrscr(' Mesh 1 (lumped): '//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Lumped_Points_Dest%Nnodes )) ) + end if + + call wrscr('Total Moment:' ) + if (mesh2_O_1PT_augmented%committed) then + write(TmpValues,*) mesh2_O_1PT_augmented%Moment + call wrscr(' Mesh 2 (augmented):'//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Augmented_Ln2_Src%Nnodes )) ) + end if + + if (mesh2_O_1PT_lumped%committed) then + write(TmpValues,*) mesh2_O_1PT_lumped%Moment + call wrscr(' Mesh 2 (lumped): '//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Lumped_Points_Src%Nnodes )) ) + end if + + if (mesh1_I_1PT_lumped%committed) then + write(TmpValues,*) mesh1_I_1PT_lumped%Moment + call wrscr(' Mesh 1 (lumped): '//TRIM(TmpValues)//trim(num2lstr(Map_Mod2_Mod1%Lumped_Points_Dest%Nnodes )) ) + end if + +END IF +#endif + + + !------------------------------------------------------------------------ + ! destroy local copies: + !------------------------------------------------------------------------ + + CALL MeshDestroy( mesh_Motion_1PT, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh1_I_1PT, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_O_1PT, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + call MeshMapDestroy(Map_Mod1_I_1PT, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call MeshMapDestroy(Map_Mod2_O_1PT, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + +#ifdef MESH_DEBUG + CALL MeshDestroy( mesh2_O_1PT_augmented, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_O_1PT_lumped, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh1_I_1PT_lumped, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + call MeshMapDestroy(Map_Mod2_O_1PT_augmented, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call MeshMapDestroy(Map_Mod2_O_1PT_lumped, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call MeshMapDestroy(Map_Mod1_I_1PT_lumped, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) +#endif + + +END SUBROUTINE WriteMappingTransferToFile +!---------------------------------------------------------------------------------------------------------------------------------- + +!================================================================================================================================== +!bjj: these routines require the use of ModMesh.f90, thus they cannot be part of NWTC_Library_Types.f90: +!STARTOFREGISTRYGENERATEDFILE 'NWTC_Library_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 (v3.02.00, 23-Jul-2016) +!********************************************************************************************************************************* + SUBROUTINE NWTC_Library_CopyMapType( SrcMapTypeData, DstMapTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MapType), INTENT(IN) :: SrcMapTypeData + TYPE(MapType), INTENT(INOUT) :: DstMapTypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_CopyMapType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMapTypeData%OtherMesh_Element = SrcMapTypeData%OtherMesh_Element + DstMapTypeData%distance = SrcMapTypeData%distance + DstMapTypeData%couple_arm = SrcMapTypeData%couple_arm + DstMapTypeData%shape_fn = SrcMapTypeData%shape_fn + END SUBROUTINE NWTC_Library_CopyMapType + + SUBROUTINE NWTC_Library_DestroyMapType( MapTypeData, ErrStat, ErrMsg ) + TYPE(MapType), INTENT(INOUT) :: MapTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyMapType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE NWTC_Library_DestroyMapType + + SUBROUTINE NWTC_Library_PackMapType( 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(MapType), 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 = 'NWTC_Library_PackMapType' + ! 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 ! OtherMesh_Element + Db_BufSz = Db_BufSz + 1 ! distance + Db_BufSz = Db_BufSz + SIZE(InData%couple_arm) ! couple_arm + Db_BufSz = Db_BufSz + SIZE(InData%shape_fn) ! shape_fn + 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%OtherMesh_Element + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%distance + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%couple_arm,1), UBOUND(InData%couple_arm,1) + DbKiBuf(Db_Xferred) = InData%couple_arm(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%shape_fn,1), UBOUND(InData%shape_fn,1) + DbKiBuf(Db_Xferred) = InData%shape_fn(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE NWTC_Library_PackMapType + + SUBROUTINE NWTC_Library_UnPackMapType( 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(MapType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_UnPackMapType' + ! 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%OtherMesh_Element = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%distance = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%couple_arm,1) + i1_u = UBOUND(OutData%couple_arm,1) + DO i1 = LBOUND(OutData%couple_arm,1), UBOUND(OutData%couple_arm,1) + OutData%couple_arm(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%shape_fn,1) + i1_u = UBOUND(OutData%shape_fn,1) + DO i1 = LBOUND(OutData%shape_fn,1), UBOUND(OutData%shape_fn,1) + OutData%shape_fn(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END SUBROUTINE NWTC_Library_UnPackMapType + + SUBROUTINE NWTC_Library_CopyMeshMapLinearizationType( SrcMeshMapLinearizationTypeData, DstMeshMapLinearizationTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeshMapLinearizationType), INTENT(IN) :: SrcMeshMapLinearizationTypeData + TYPE(MeshMapLinearizationType), INTENT(INOUT) :: DstMeshMapLinearizationTypeData + 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 = 'NWTC_Library_CopyMeshMapLinearizationType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%mi)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%mi,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%mi,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%mi,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%mi,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%mi)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%mi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%mi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%mi = SrcMeshMapLinearizationTypeData%mi +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%fx_p)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%fx_p,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%fx_p,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%fx_p,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%fx_p,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%fx_p)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%fx_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%fx_p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%fx_p = SrcMeshMapLinearizationTypeData%fx_p +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%tv_uD)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%tv_uD,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%tv_uD,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%tv_uD,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%tv_uD,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%tv_uD)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%tv_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%tv_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%tv_uD = SrcMeshMapLinearizationTypeData%tv_uD +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%tv_uS)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%tv_uS,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%tv_uS,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%tv_uS,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%tv_uS,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%tv_uS)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%tv_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%tv_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%tv_uS = SrcMeshMapLinearizationTypeData%tv_uS +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%ta_uD)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_uD,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_uD,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_uD,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_uD,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%ta_uD)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%ta_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%ta_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%ta_uD = SrcMeshMapLinearizationTypeData%ta_uD +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%ta_uS)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_uS,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_uS,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_uS,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_uS,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%ta_uS)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%ta_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%ta_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%ta_uS = SrcMeshMapLinearizationTypeData%ta_uS +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%ta_rv)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_rv,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_rv,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%ta_rv,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%ta_rv,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%ta_rv)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%ta_rv(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%ta_rv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%ta_rv = SrcMeshMapLinearizationTypeData%ta_rv +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%li)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%li,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%li,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%li,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%li,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%li)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%li(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%li.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%li = SrcMeshMapLinearizationTypeData%li +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%M_uS)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%M_uS,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%M_uS,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%M_uS,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%M_uS,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%M_uS)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%M_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%M_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%M_uS = SrcMeshMapLinearizationTypeData%M_uS +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%M_uD)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%M_uD,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%M_uD,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%M_uD,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%M_uD,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%M_uD)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%M_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%M_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%M_uD = SrcMeshMapLinearizationTypeData%M_uD +ENDIF +IF (ALLOCATED(SrcMeshMapLinearizationTypeData%M_f)) THEN + i1_l = LBOUND(SrcMeshMapLinearizationTypeData%M_f,1) + i1_u = UBOUND(SrcMeshMapLinearizationTypeData%M_f,1) + i2_l = LBOUND(SrcMeshMapLinearizationTypeData%M_f,2) + i2_u = UBOUND(SrcMeshMapLinearizationTypeData%M_f,2) + IF (.NOT. ALLOCATED(DstMeshMapLinearizationTypeData%M_f)) THEN + ALLOCATE(DstMeshMapLinearizationTypeData%M_f(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapLinearizationTypeData%M_f.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapLinearizationTypeData%M_f = SrcMeshMapLinearizationTypeData%M_f +ENDIF + END SUBROUTINE NWTC_Library_CopyMeshMapLinearizationType + + SUBROUTINE NWTC_Library_DestroyMeshMapLinearizationType( MeshMapLinearizationTypeData, ErrStat, ErrMsg ) + TYPE(MeshMapLinearizationType), INTENT(INOUT) :: MeshMapLinearizationTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyMeshMapLinearizationType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MeshMapLinearizationTypeData%mi)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%mi) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%fx_p)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%fx_p) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%tv_uD)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%tv_uD) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%tv_uS)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%tv_uS) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%ta_uD)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%ta_uD) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%ta_uS)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%ta_uS) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%ta_rv)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%ta_rv) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%li)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%li) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%M_uS)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%M_uS) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%M_uD)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%M_uD) +ENDIF +IF (ALLOCATED(MeshMapLinearizationTypeData%M_f)) THEN + DEALLOCATE(MeshMapLinearizationTypeData%M_f) +ENDIF + END SUBROUTINE NWTC_Library_DestroyMeshMapLinearizationType + + SUBROUTINE NWTC_Library_PackMeshMapLinearizationType( 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(MeshMapLinearizationType), 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 = 'NWTC_Library_PackMeshMapLinearizationType' + ! 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 ! mi allocated yes/no + IF ( ALLOCATED(InData%mi) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! mi upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%mi) ! mi + END IF + Int_BufSz = Int_BufSz + 1 ! fx_p allocated yes/no + IF ( ALLOCATED(InData%fx_p) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! fx_p upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%fx_p) ! fx_p + END IF + Int_BufSz = Int_BufSz + 1 ! tv_uD allocated yes/no + IF ( ALLOCATED(InData%tv_uD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tv_uD upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%tv_uD) ! tv_uD + END IF + Int_BufSz = Int_BufSz + 1 ! tv_uS allocated yes/no + IF ( ALLOCATED(InData%tv_uS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! tv_uS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%tv_uS) ! tv_uS + END IF + Int_BufSz = Int_BufSz + 1 ! ta_uD allocated yes/no + IF ( ALLOCATED(InData%ta_uD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ta_uD upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%ta_uD) ! ta_uD + END IF + Int_BufSz = Int_BufSz + 1 ! ta_uS allocated yes/no + IF ( ALLOCATED(InData%ta_uS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ta_uS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%ta_uS) ! ta_uS + END IF + Int_BufSz = Int_BufSz + 1 ! ta_rv allocated yes/no + IF ( ALLOCATED(InData%ta_rv) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ta_rv upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%ta_rv) ! ta_rv + END IF + Int_BufSz = Int_BufSz + 1 ! li allocated yes/no + IF ( ALLOCATED(InData%li) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! li upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%li) ! li + END IF + Int_BufSz = Int_BufSz + 1 ! M_uS allocated yes/no + IF ( ALLOCATED(InData%M_uS) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M_uS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%M_uS) ! M_uS + END IF + Int_BufSz = Int_BufSz + 1 ! M_uD allocated yes/no + IF ( ALLOCATED(InData%M_uD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M_uD upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%M_uD) ! M_uD + END IF + Int_BufSz = Int_BufSz + 1 ! M_f allocated yes/no + IF ( ALLOCATED(InData%M_f) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M_f upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%M_f) ! M_f + 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%mi) ) 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%mi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mi,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%mi,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%mi,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%mi,2), UBOUND(InData%mi,2) + DO i1 = LBOUND(InData%mi,1), UBOUND(InData%mi,1) + DbKiBuf(Db_Xferred) = InData%mi(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%fx_p) ) 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%fx_p,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fx_p,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%fx_p,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fx_p,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%fx_p,2), UBOUND(InData%fx_p,2) + DO i1 = LBOUND(InData%fx_p,1), UBOUND(InData%fx_p,1) + DbKiBuf(Db_Xferred) = InData%fx_p(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tv_uD) ) 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%tv_uD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tv_uD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tv_uD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tv_uD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tv_uD,2), UBOUND(InData%tv_uD,2) + DO i1 = LBOUND(InData%tv_uD,1), UBOUND(InData%tv_uD,1) + DbKiBuf(Db_Xferred) = InData%tv_uD(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tv_uS) ) 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%tv_uS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tv_uS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tv_uS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tv_uS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%tv_uS,2), UBOUND(InData%tv_uS,2) + DO i1 = LBOUND(InData%tv_uS,1), UBOUND(InData%tv_uS,1) + DbKiBuf(Db_Xferred) = InData%tv_uS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ta_uD) ) 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%ta_uD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_uD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ta_uD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_uD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ta_uD,2), UBOUND(InData%ta_uD,2) + DO i1 = LBOUND(InData%ta_uD,1), UBOUND(InData%ta_uD,1) + DbKiBuf(Db_Xferred) = InData%ta_uD(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ta_uS) ) 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%ta_uS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_uS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ta_uS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_uS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ta_uS,2), UBOUND(InData%ta_uS,2) + DO i1 = LBOUND(InData%ta_uS,1), UBOUND(InData%ta_uS,1) + DbKiBuf(Db_Xferred) = InData%ta_uS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ta_rv) ) 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%ta_rv,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_rv,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ta_rv,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ta_rv,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ta_rv,2), UBOUND(InData%ta_rv,2) + DO i1 = LBOUND(InData%ta_rv,1), UBOUND(InData%ta_rv,1) + DbKiBuf(Db_Xferred) = InData%ta_rv(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%li) ) 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%li,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%li,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%li,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%li,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%li,2), UBOUND(InData%li,2) + DO i1 = LBOUND(InData%li,1), UBOUND(InData%li,1) + DbKiBuf(Db_Xferred) = InData%li(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M_uS) ) 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%M_uS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_uS,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M_uS,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_uS,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M_uS,2), UBOUND(InData%M_uS,2) + DO i1 = LBOUND(InData%M_uS,1), UBOUND(InData%M_uS,1) + DbKiBuf(Db_Xferred) = InData%M_uS(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M_uD) ) 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%M_uD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_uD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M_uD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_uD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M_uD,2), UBOUND(InData%M_uD,2) + DO i1 = LBOUND(InData%M_uD,1), UBOUND(InData%M_uD,1) + DbKiBuf(Db_Xferred) = InData%M_uD(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M_f) ) 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%M_f,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_f,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M_f,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M_f,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M_f,2), UBOUND(InData%M_f,2) + DO i1 = LBOUND(InData%M_f,1), UBOUND(InData%M_f,1) + DbKiBuf(Db_Xferred) = InData%M_f(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE NWTC_Library_PackMeshMapLinearizationType + + SUBROUTINE NWTC_Library_UnPackMeshMapLinearizationType( 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(MeshMapLinearizationType), 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 = 'NWTC_Library_UnPackMeshMapLinearizationType' + ! 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 ! mi 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%mi)) DEALLOCATE(OutData%mi) + ALLOCATE(OutData%mi(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%mi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%mi,2), UBOUND(OutData%mi,2) + DO i1 = LBOUND(OutData%mi,1), UBOUND(OutData%mi,1) + OutData%mi(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fx_p 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%fx_p)) DEALLOCATE(OutData%fx_p) + ALLOCATE(OutData%fx_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fx_p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%fx_p,2), UBOUND(OutData%fx_p,2) + DO i1 = LBOUND(OutData%fx_p,1), UBOUND(OutData%fx_p,1) + OutData%fx_p(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tv_uD 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%tv_uD)) DEALLOCATE(OutData%tv_uD) + ALLOCATE(OutData%tv_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tv_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tv_uD,2), UBOUND(OutData%tv_uD,2) + DO i1 = LBOUND(OutData%tv_uD,1), UBOUND(OutData%tv_uD,1) + OutData%tv_uD(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tv_uS 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%tv_uS)) DEALLOCATE(OutData%tv_uS) + ALLOCATE(OutData%tv_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tv_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%tv_uS,2), UBOUND(OutData%tv_uS,2) + DO i1 = LBOUND(OutData%tv_uS,1), UBOUND(OutData%tv_uS,1) + OutData%tv_uS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ta_uD 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%ta_uD)) DEALLOCATE(OutData%ta_uD) + ALLOCATE(OutData%ta_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ta_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ta_uD,2), UBOUND(OutData%ta_uD,2) + DO i1 = LBOUND(OutData%ta_uD,1), UBOUND(OutData%ta_uD,1) + OutData%ta_uD(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ta_uS 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%ta_uS)) DEALLOCATE(OutData%ta_uS) + ALLOCATE(OutData%ta_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ta_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ta_uS,2), UBOUND(OutData%ta_uS,2) + DO i1 = LBOUND(OutData%ta_uS,1), UBOUND(OutData%ta_uS,1) + OutData%ta_uS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ta_rv 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%ta_rv)) DEALLOCATE(OutData%ta_rv) + ALLOCATE(OutData%ta_rv(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ta_rv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ta_rv,2), UBOUND(OutData%ta_rv,2) + DO i1 = LBOUND(OutData%ta_rv,1), UBOUND(OutData%ta_rv,1) + OutData%ta_rv(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! li 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%li)) DEALLOCATE(OutData%li) + ALLOCATE(OutData%li(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%li.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%li,2), UBOUND(OutData%li,2) + DO i1 = LBOUND(OutData%li,1), UBOUND(OutData%li,1) + OutData%li(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M_uS 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%M_uS)) DEALLOCATE(OutData%M_uS) + ALLOCATE(OutData%M_uS(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M_uS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M_uS,2), UBOUND(OutData%M_uS,2) + DO i1 = LBOUND(OutData%M_uS,1), UBOUND(OutData%M_uS,1) + OutData%M_uS(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M_uD 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%M_uD)) DEALLOCATE(OutData%M_uD) + ALLOCATE(OutData%M_uD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M_uD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M_uD,2), UBOUND(OutData%M_uD,2) + DO i1 = LBOUND(OutData%M_uD,1), UBOUND(OutData%M_uD,1) + OutData%M_uD(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M_f 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%M_f)) DEALLOCATE(OutData%M_f) + ALLOCATE(OutData%M_f(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M_f.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M_f,2), UBOUND(OutData%M_f,2) + DO i1 = LBOUND(OutData%M_f,1), UBOUND(OutData%M_f,1) + OutData%M_f(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE NWTC_Library_UnPackMeshMapLinearizationType + + SUBROUTINE NWTC_Library_CopyMeshMapType( SrcMeshMapTypeData, DstMeshMapTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeshMapType), INTENT(INOUT) :: SrcMeshMapTypeData + TYPE(MeshMapType), INTENT(INOUT) :: DstMeshMapTypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_CopyMeshMapType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMeshMapTypeData%MapLoads)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%MapLoads,1) + i1_u = UBOUND(SrcMeshMapTypeData%MapLoads,1) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%MapLoads)) THEN + ALLOCATE(DstMeshMapTypeData%MapLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%MapLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMeshMapTypeData%MapLoads,1), UBOUND(SrcMeshMapTypeData%MapLoads,1) + CALL NWTC_Library_Copymaptype( SrcMeshMapTypeData%MapLoads(i1), DstMeshMapTypeData%MapLoads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%MapMotions)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%MapMotions,1) + i1_u = UBOUND(SrcMeshMapTypeData%MapMotions,1) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%MapMotions)) THEN + ALLOCATE(DstMeshMapTypeData%MapMotions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%MapMotions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMeshMapTypeData%MapMotions,1), UBOUND(SrcMeshMapTypeData%MapMotions,1) + CALL NWTC_Library_Copymaptype( SrcMeshMapTypeData%MapMotions(i1), DstMeshMapTypeData%MapMotions(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%MapSrcToAugmt)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%MapSrcToAugmt,1) + i1_u = UBOUND(SrcMeshMapTypeData%MapSrcToAugmt,1) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%MapSrcToAugmt)) THEN + ALLOCATE(DstMeshMapTypeData%MapSrcToAugmt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%MapSrcToAugmt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMeshMapTypeData%MapSrcToAugmt,1), UBOUND(SrcMeshMapTypeData%MapSrcToAugmt,1) + CALL NWTC_Library_Copymaptype( SrcMeshMapTypeData%MapSrcToAugmt(i1), DstMeshMapTypeData%MapSrcToAugmt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcMeshMapTypeData%Augmented_Ln2_Src, DstMeshMapTypeData%Augmented_Ln2_Src, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcMeshMapTypeData%Lumped_Points_Src, DstMeshMapTypeData%Lumped_Points_Src, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMeshMapTypeData%LoadLn2_A_Mat_Piv)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat_Piv,1) + i1_u = UBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat_Piv,1) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%LoadLn2_A_Mat_Piv)) THEN + ALLOCATE(DstMeshMapTypeData%LoadLn2_A_Mat_Piv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%LoadLn2_A_Mat_Piv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapTypeData%LoadLn2_A_Mat_Piv = SrcMeshMapTypeData%LoadLn2_A_Mat_Piv +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%DisplacedPosition)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%DisplacedPosition,1) + i1_u = UBOUND(SrcMeshMapTypeData%DisplacedPosition,1) + i2_l = LBOUND(SrcMeshMapTypeData%DisplacedPosition,2) + i2_u = UBOUND(SrcMeshMapTypeData%DisplacedPosition,2) + i3_l = LBOUND(SrcMeshMapTypeData%DisplacedPosition,3) + i3_u = UBOUND(SrcMeshMapTypeData%DisplacedPosition,3) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%DisplacedPosition)) THEN + ALLOCATE(DstMeshMapTypeData%DisplacedPosition(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%DisplacedPosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapTypeData%DisplacedPosition = SrcMeshMapTypeData%DisplacedPosition +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%LoadLn2_A_Mat)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat,1) + i1_u = UBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat,1) + i2_l = LBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat,2) + i2_u = UBOUND(SrcMeshMapTypeData%LoadLn2_A_Mat,2) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%LoadLn2_A_Mat)) THEN + ALLOCATE(DstMeshMapTypeData%LoadLn2_A_Mat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%LoadLn2_A_Mat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapTypeData%LoadLn2_A_Mat = SrcMeshMapTypeData%LoadLn2_A_Mat +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%LoadLn2_F)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%LoadLn2_F,1) + i1_u = UBOUND(SrcMeshMapTypeData%LoadLn2_F,1) + i2_l = LBOUND(SrcMeshMapTypeData%LoadLn2_F,2) + i2_u = UBOUND(SrcMeshMapTypeData%LoadLn2_F,2) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%LoadLn2_F)) THEN + ALLOCATE(DstMeshMapTypeData%LoadLn2_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%LoadLn2_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapTypeData%LoadLn2_F = SrcMeshMapTypeData%LoadLn2_F +ENDIF +IF (ALLOCATED(SrcMeshMapTypeData%LoadLn2_M)) THEN + i1_l = LBOUND(SrcMeshMapTypeData%LoadLn2_M,1) + i1_u = UBOUND(SrcMeshMapTypeData%LoadLn2_M,1) + i2_l = LBOUND(SrcMeshMapTypeData%LoadLn2_M,2) + i2_u = UBOUND(SrcMeshMapTypeData%LoadLn2_M,2) + IF (.NOT. ALLOCATED(DstMeshMapTypeData%LoadLn2_M)) THEN + ALLOCATE(DstMeshMapTypeData%LoadLn2_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshMapTypeData%LoadLn2_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshMapTypeData%LoadLn2_M = SrcMeshMapTypeData%LoadLn2_M +ENDIF + CALL NWTC_Library_Copymeshmaplinearizationtype( SrcMeshMapTypeData%dM, DstMeshMapTypeData%dM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE NWTC_Library_CopyMeshMapType + + SUBROUTINE NWTC_Library_DestroyMeshMapType( MeshMapTypeData, ErrStat, ErrMsg ) + TYPE(MeshMapType), INTENT(INOUT) :: MeshMapTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyMeshMapType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MeshMapTypeData%MapLoads)) THEN +DO i1 = LBOUND(MeshMapTypeData%MapLoads,1), UBOUND(MeshMapTypeData%MapLoads,1) + CALL NWTC_Library_Destroymaptype( MeshMapTypeData%MapLoads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MeshMapTypeData%MapLoads) +ENDIF +IF (ALLOCATED(MeshMapTypeData%MapMotions)) THEN +DO i1 = LBOUND(MeshMapTypeData%MapMotions,1), UBOUND(MeshMapTypeData%MapMotions,1) + CALL NWTC_Library_Destroymaptype( MeshMapTypeData%MapMotions(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MeshMapTypeData%MapMotions) +ENDIF +IF (ALLOCATED(MeshMapTypeData%MapSrcToAugmt)) THEN +DO i1 = LBOUND(MeshMapTypeData%MapSrcToAugmt,1), UBOUND(MeshMapTypeData%MapSrcToAugmt,1) + CALL NWTC_Library_Destroymaptype( MeshMapTypeData%MapSrcToAugmt(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MeshMapTypeData%MapSrcToAugmt) +ENDIF + CALL MeshDestroy( MeshMapTypeData%Augmented_Ln2_Src, ErrStat, ErrMsg ) + CALL MeshDestroy( MeshMapTypeData%Lumped_Points_Src, ErrStat, ErrMsg ) +IF (ALLOCATED(MeshMapTypeData%LoadLn2_A_Mat_Piv)) THEN + DEALLOCATE(MeshMapTypeData%LoadLn2_A_Mat_Piv) +ENDIF +IF (ALLOCATED(MeshMapTypeData%DisplacedPosition)) THEN + DEALLOCATE(MeshMapTypeData%DisplacedPosition) +ENDIF +IF (ALLOCATED(MeshMapTypeData%LoadLn2_A_Mat)) THEN + DEALLOCATE(MeshMapTypeData%LoadLn2_A_Mat) +ENDIF +IF (ALLOCATED(MeshMapTypeData%LoadLn2_F)) THEN + DEALLOCATE(MeshMapTypeData%LoadLn2_F) +ENDIF +IF (ALLOCATED(MeshMapTypeData%LoadLn2_M)) THEN + DEALLOCATE(MeshMapTypeData%LoadLn2_M) +ENDIF + CALL NWTC_Library_Destroymeshmaplinearizationtype( MeshMapTypeData%dM, ErrStat, ErrMsg ) + END SUBROUTINE NWTC_Library_DestroyMeshMapType + + SUBROUTINE NWTC_Library_PackMeshMapType( 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(MeshMapType), 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 = 'NWTC_Library_PackMeshMapType' + ! 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 ! MapLoads allocated yes/no + IF ( ALLOCATED(InData%MapLoads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MapLoads upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%MapLoads,1), UBOUND(InData%MapLoads,1) + Int_BufSz = Int_BufSz + 3 ! MapLoads: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapLoads(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MapLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MapLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MapLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MapLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MapMotions allocated yes/no + IF ( ALLOCATED(InData%MapMotions) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MapMotions upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MapMotions,1), UBOUND(InData%MapMotions,1) + Int_BufSz = Int_BufSz + 3 ! MapMotions: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapMotions(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MapMotions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MapMotions + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MapMotions + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MapMotions + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MapSrcToAugmt allocated yes/no + IF ( ALLOCATED(InData%MapSrcToAugmt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MapSrcToAugmt upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MapSrcToAugmt,1), UBOUND(InData%MapSrcToAugmt,1) + Int_BufSz = Int_BufSz + 3 ! MapSrcToAugmt: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapSrcToAugmt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MapSrcToAugmt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MapSrcToAugmt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MapSrcToAugmt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MapSrcToAugmt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! Augmented_Ln2_Src: size of buffers for each call to pack subtype + CALL MeshPack( InData%Augmented_Ln2_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Augmented_Ln2_Src + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Augmented_Ln2_Src + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Augmented_Ln2_Src + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Augmented_Ln2_Src + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Lumped_Points_Src: size of buffers for each call to pack subtype + CALL MeshPack( InData%Lumped_Points_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Lumped_Points_Src + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Lumped_Points_Src + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Lumped_Points_Src + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Lumped_Points_Src + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! LoadLn2_A_Mat_Piv allocated yes/no + IF ( ALLOCATED(InData%LoadLn2_A_Mat_Piv) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LoadLn2_A_Mat_Piv upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LoadLn2_A_Mat_Piv) ! LoadLn2_A_Mat_Piv + END IF + Int_BufSz = Int_BufSz + 1 ! DisplacedPosition allocated yes/no + IF ( ALLOCATED(InData%DisplacedPosition) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! DisplacedPosition upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DisplacedPosition) ! DisplacedPosition + END IF + Int_BufSz = Int_BufSz + 1 ! LoadLn2_A_Mat allocated yes/no + IF ( ALLOCATED(InData%LoadLn2_A_Mat) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LoadLn2_A_Mat upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LoadLn2_A_Mat) ! LoadLn2_A_Mat + END IF + Int_BufSz = Int_BufSz + 1 ! LoadLn2_F allocated yes/no + IF ( ALLOCATED(InData%LoadLn2_F) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LoadLn2_F upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LoadLn2_F) ! LoadLn2_F + END IF + Int_BufSz = Int_BufSz + 1 ! LoadLn2_M allocated yes/no + IF ( ALLOCATED(InData%LoadLn2_M) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! LoadLn2_M upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LoadLn2_M) ! LoadLn2_M + END IF + Int_BufSz = Int_BufSz + 3 ! dM: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaplinearizationtype( Re_Buf, Db_Buf, Int_Buf, InData%dM, ErrStat2, ErrMsg2, .TRUE. ) ! dM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! dM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! dM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! dM + 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 + + IF ( .NOT. ALLOCATED(InData%MapLoads) ) 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%MapLoads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MapLoads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MapLoads,1), UBOUND(InData%MapLoads,1) + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapLoads(i1), ErrStat2, ErrMsg2, OnlySize ) ! MapLoads + 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%MapMotions) ) 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%MapMotions,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MapMotions,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MapMotions,1), UBOUND(InData%MapMotions,1) + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapMotions(i1), ErrStat2, ErrMsg2, OnlySize ) ! MapMotions + 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%MapSrcToAugmt) ) 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%MapSrcToAugmt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MapSrcToAugmt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MapSrcToAugmt,1), UBOUND(InData%MapSrcToAugmt,1) + CALL NWTC_Library_Packmaptype( Re_Buf, Db_Buf, Int_Buf, InData%MapSrcToAugmt(i1), ErrStat2, ErrMsg2, OnlySize ) ! MapSrcToAugmt + 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 + CALL MeshPack( InData%Augmented_Ln2_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Augmented_Ln2_Src + 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 MeshPack( InData%Lumped_Points_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Lumped_Points_Src + 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%LoadLn2_A_Mat_Piv) ) 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%LoadLn2_A_Mat_Piv,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_A_Mat_Piv,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LoadLn2_A_Mat_Piv,1), UBOUND(InData%LoadLn2_A_Mat_Piv,1) + IntKiBuf(Int_Xferred) = InData%LoadLn2_A_Mat_Piv(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DisplacedPosition) ) 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%DisplacedPosition,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisplacedPosition,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DisplacedPosition,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisplacedPosition,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DisplacedPosition,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DisplacedPosition,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%DisplacedPosition,3), UBOUND(InData%DisplacedPosition,3) + DO i2 = LBOUND(InData%DisplacedPosition,2), UBOUND(InData%DisplacedPosition,2) + DO i1 = LBOUND(InData%DisplacedPosition,1), UBOUND(InData%DisplacedPosition,1) + DbKiBuf(Db_Xferred) = InData%DisplacedPosition(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LoadLn2_A_Mat) ) 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%LoadLn2_A_Mat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_A_Mat,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LoadLn2_A_Mat,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_A_Mat,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LoadLn2_A_Mat,2), UBOUND(InData%LoadLn2_A_Mat,2) + DO i1 = LBOUND(InData%LoadLn2_A_Mat,1), UBOUND(InData%LoadLn2_A_Mat,1) + DbKiBuf(Db_Xferred) = InData%LoadLn2_A_Mat(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LoadLn2_F) ) 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%LoadLn2_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_F,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LoadLn2_F,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_F,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LoadLn2_F,2), UBOUND(InData%LoadLn2_F,2) + DO i1 = LBOUND(InData%LoadLn2_F,1), UBOUND(InData%LoadLn2_F,1) + DbKiBuf(Db_Xferred) = InData%LoadLn2_F(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LoadLn2_M) ) 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%LoadLn2_M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LoadLn2_M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LoadLn2_M,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%LoadLn2_M,2), UBOUND(InData%LoadLn2_M,2) + DO i1 = LBOUND(InData%LoadLn2_M,1), UBOUND(InData%LoadLn2_M,1) + DbKiBuf(Db_Xferred) = InData%LoadLn2_M(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + CALL NWTC_Library_Packmeshmaplinearizationtype( Re_Buf, Db_Buf, Int_Buf, InData%dM, ErrStat2, ErrMsg2, OnlySize ) ! dM + 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 NWTC_Library_PackMeshMapType + + SUBROUTINE NWTC_Library_UnPackMeshMapType( 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(MeshMapType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_UnPackMeshMapType' + ! 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 ! MapLoads 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%MapLoads)) DEALLOCATE(OutData%MapLoads) + ALLOCATE(OutData%MapLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MapLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MapLoads,1), UBOUND(OutData%MapLoads,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_Unpackmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%MapLoads(i1), ErrStat2, ErrMsg2 ) ! MapLoads + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MapMotions 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%MapMotions)) DEALLOCATE(OutData%MapMotions) + ALLOCATE(OutData%MapMotions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MapMotions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MapMotions,1), UBOUND(OutData%MapMotions,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_Unpackmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%MapMotions(i1), ErrStat2, ErrMsg2 ) ! MapMotions + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MapSrcToAugmt 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%MapSrcToAugmt)) DEALLOCATE(OutData%MapSrcToAugmt) + ALLOCATE(OutData%MapSrcToAugmt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MapSrcToAugmt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MapSrcToAugmt,1), UBOUND(OutData%MapSrcToAugmt,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_Unpackmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%MapSrcToAugmt(i1), ErrStat2, ErrMsg2 ) ! MapSrcToAugmt + 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 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 MeshUnpack( OutData%Augmented_Ln2_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Augmented_Ln2_Src + 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 MeshUnpack( OutData%Lumped_Points_Src, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Lumped_Points_Src + 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 ! LoadLn2_A_Mat_Piv 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%LoadLn2_A_Mat_Piv)) DEALLOCATE(OutData%LoadLn2_A_Mat_Piv) + ALLOCATE(OutData%LoadLn2_A_Mat_Piv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LoadLn2_A_Mat_Piv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LoadLn2_A_Mat_Piv,1), UBOUND(OutData%LoadLn2_A_Mat_Piv,1) + OutData%LoadLn2_A_Mat_Piv(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DisplacedPosition 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%DisplacedPosition)) DEALLOCATE(OutData%DisplacedPosition) + ALLOCATE(OutData%DisplacedPosition(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%DisplacedPosition.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%DisplacedPosition,3), UBOUND(OutData%DisplacedPosition,3) + DO i2 = LBOUND(OutData%DisplacedPosition,2), UBOUND(OutData%DisplacedPosition,2) + DO i1 = LBOUND(OutData%DisplacedPosition,1), UBOUND(OutData%DisplacedPosition,1) + OutData%DisplacedPosition(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LoadLn2_A_Mat 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%LoadLn2_A_Mat)) DEALLOCATE(OutData%LoadLn2_A_Mat) + ALLOCATE(OutData%LoadLn2_A_Mat(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LoadLn2_A_Mat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LoadLn2_A_Mat,2), UBOUND(OutData%LoadLn2_A_Mat,2) + DO i1 = LBOUND(OutData%LoadLn2_A_Mat,1), UBOUND(OutData%LoadLn2_A_Mat,1) + OutData%LoadLn2_A_Mat(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LoadLn2_F 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%LoadLn2_F)) DEALLOCATE(OutData%LoadLn2_F) + ALLOCATE(OutData%LoadLn2_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LoadLn2_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LoadLn2_F,2), UBOUND(OutData%LoadLn2_F,2) + DO i1 = LBOUND(OutData%LoadLn2_F,1), UBOUND(OutData%LoadLn2_F,1) + OutData%LoadLn2_F(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LoadLn2_M 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%LoadLn2_M)) DEALLOCATE(OutData%LoadLn2_M) + ALLOCATE(OutData%LoadLn2_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LoadLn2_M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%LoadLn2_M,2), UBOUND(OutData%LoadLn2_M,2) + DO i1 = LBOUND(OutData%LoadLn2_M,1), UBOUND(OutData%LoadLn2_M,1) + OutData%LoadLn2_M(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_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 NWTC_Library_Unpackmeshmaplinearizationtype( Re_Buf, Db_Buf, Int_Buf, OutData%dM, ErrStat2, ErrMsg2 ) ! dM + 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 NWTC_Library_UnPackMeshMapType + +!********************************************************************************************************************************* +!ENDOFREGISTRYGENERATEDFILE + + +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE ModMesh_Mapping +!---------------------------------------------------------------------------------------------------------------------------------- diff --git a/OpenFAST/modules/nwtc-library/src/ModMesh_Types.f90 b/OpenFAST/modules/nwtc-library/src/ModMesh_Types.f90 new file mode 100644 index 000000000..1bca2c98a --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/ModMesh_Types.f90 @@ -0,0 +1,240 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +!********************************************************************************************************************************** +!> This module contains the type definition of of ModMesh, the FAST spatial mesh structure. +MODULE ModMesh_Types + USE NWTC_Num + IMPLICIT NONE + + INTEGER, PUBLIC, PARAMETER :: COMPONENT_INPUT = 1 !< parameter for "input mesh" + INTEGER, PUBLIC, PARAMETER :: COMPONENT_OUTPUT = 2 !< parameter for "output mesh" + INTEGER, PUBLIC, PARAMETER :: COMPONENT_STATE = 3 !< parameter for "state mesh" (not recommended to use) + +!WARNING... if you add fields here add them to the buffer size computation MeshPack too + INTEGER, PUBLIC, PARAMETER :: MASKID_FORCE = 1 !< parameter for fields holding force + INTEGER, PUBLIC, PARAMETER :: MASKID_MOMENT = 2 !< parameter for fields holding moment + INTEGER, PUBLIC, PARAMETER :: MASKID_ORIENTATION = 3 !< parameter for fields holding orientation + INTEGER, PUBLIC, PARAMETER :: MASKID_TRANSLATIONDISP = 4 !< parameter for fields holding translational displacement + INTEGER, PUBLIC, PARAMETER :: MASKID_TRANSLATIONVEL = 5 !< parameter for fields holding translational velocity + INTEGER, PUBLIC, PARAMETER :: MASKID_ROTATIONVEL = 6 !< parameter for fields holding rotational velocity + INTEGER, PUBLIC, PARAMETER :: MASKID_TRANSLATIONACC = 7 !< parameter for fields holding translational acceleration + INTEGER, PUBLIC, PARAMETER :: MASKID_ROTATIONACC = 8 !< parameter for fields holding rotational acceleration + INTEGER, PUBLIC, PARAMETER :: MASKID_SCALAR = 9 !< parameter for fields holding scalars + INTEGER, PUBLIC, PARAMETER :: FIELDMASK_SIZE = 9 !< maximum number of fields in a mesh + + INTEGER, PUBLIC, PARAMETER :: ELEMENT_POINT = 1 !< parameter for elements of point + INTEGER, PUBLIC, PARAMETER :: ELEMENT_LINE2 = 2 !< parameter for elements of 2-point lines + INTEGER, PUBLIC, PARAMETER :: ELEMENT_LINE3 = 3 !< parameter for elements of 3-point lines (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_TRI3 = 4 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_TRI6 = 5 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_QUAD4 = 6 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_QUAD8 = 7 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_TET4 = 8 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_TET10 = 9 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_HEX8 = 10 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_HEX20 = 11 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_WEDGE6 = 12 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: ELEMENT_WEDGE15 = 13 !< parameter for elements (currently unused) + INTEGER, PUBLIC, PARAMETER :: NELEMKINDS = 13 !< parameter for maximum number of element kinds + + CHARACTER(*),DIMENSION(NELEMKINDS),PARAMETER:: ElemNames = (/& + "Point ","Line2 ","Line3 ","Tri3 ","Tri6 ",& + "Quad4 ","Quad8 ","Tet4 ","Tet10 ","Hex8 ",& + "Hex20 ","Wedge6 ","Wedge15" /) !< element names + + + INTEGER, PUBLIC, PARAMETER :: MESH_NEWCOPY = 1 !< parameter for type of mesh copy: new mesh instance + INTEGER, PUBLIC, PARAMETER :: MESH_SIBLING = 2 !< parameter for type of mesh copy: new sibling (shares element and reference data; fields separate) + INTEGER, PUBLIC, PARAMETER :: MESH_UPDATECOPY = 3 !< parameter for type of mesh copy: updates fields in existing mesh + INTEGER, PUBLIC, PARAMETER :: MESH_UPDATEREFERENCE = 4 !< parameter for type of mesh copy: updates reference fields in existing mesh + INTEGER, PUBLIC, PARAMETER :: MESH_COUSIN = 5 !< parameter for type of mesh copy: like sibling, but allocates memory for all data + + INTEGER, PUBLIC, PARAMETER :: MESH_NEXT = -2 !< parameter for next element in mesh + INTEGER, PUBLIC, PARAMETER :: MESH_NOMOREELEMS = -3 !< parameter indicating no more elements in mesh + INTEGER, PUBLIC, PARAMETER :: MESH_NOMOREELEMENTS = MESH_NOMOREELEMS !< synonym + INTEGER, PUBLIC, PARAMETER :: MESH_NOMORE = MESH_NOMOREELEMS !< synonym + + LOGICAL, PARAMETER :: mesh_debug = .FALSE. + + +! REAL(ReKi), PARAMETER :: MIN_LINE2_ELEMENT_LENGTH = 0.001 ! 1 millimeter + REAL(ReKi), PARAMETER :: MIN_LINE2_ELEMENT_LENGTH = sqrt(epsilon(1.0_ReKi)) ! old length + + !> element record type: fields for a particular element + TYPE, PUBLIC :: ElemRecType + ! note: any fields added to this type must be copied in Mesh_MoveAlloc_ElemRecType (modmesh_types::mesh_movealloc_elemrectype) + INTEGER :: Xelement !< which kind of element + INTEGER :: Nneighbors !< how many neighbors + REAL(ReKi) :: det_jac !< determinant of the Jacobian (e.g., 1/2 the length of a line-2 element) + INTEGER, ALLOCATABLE :: ElemNodes(:) !< the list of nodes +! TYPE(ElemRecType), POINTER :: Neighbors(:) ! neighbor list (cannot be allocatable because it's a subtype of itself) + END TYPE ElemRecType + + !> table of all elements of a particular type + TYPE, PUBLIC :: ElemTabType + INTEGER :: nelem !< number of elements of this type + INTEGER :: maxelem !< maximum elements currently allocated for this type + INTEGER :: Xelement !< which kind of element + TYPE(ElemRecType), POINTER :: Elements(:) => NULL() !< pointer to list of all elements of this type + END TYPE ElemTabType + + !> table/list of all elements (may be different types, but not spatial dimensions) + TYPE, PUBLIC :: ElemListType + TYPE(ElemRecType), POINTER :: Element => NULL() !< pointer to a particular mesh element + END TYPE ElemListType + + !> mesh data structure + TYPE, PUBLIC :: MeshType + LOGICAL :: initialized = .FALSE. !< Indicate whether this mesh is initialized + LOGICAL :: committed = .FALSE. !< Indicate whether this mesh is committed + LOGICAL :: fieldmask(FIELDMASK_SIZE) = .FALSE. !< Dimension as number of allocatable fields, below + LOGICAL,POINTER :: RemapFlag => NULL() !< false=no action/ignore; true=remap required + INTEGER :: ios !< Mesh type: input (1), output(2), or state(3) + INTEGER :: refNode = 0 !< optional reference node (informational only) + INTEGER :: Nnodes = 0 !< Number of nodes (vertices) in mesh + + ! Mesh elements + TYPE(ElemTabType), POINTER :: ElemTable(:) => NULL() !< A table of all elements in the mesh, by type + + ! Mesh traversal + INTEGER :: nelemlist !< Number of elements in the list (ElemList) + INTEGER :: maxelemlist !< Maximum number of elements in the list + INTEGER :: nextelem !< Next element in the list + TYPE(ElemListType), POINTER :: ElemList(:) => NULL() !< All of the elements in the mesh + + ! Node position and reference orientation, which are always allocated (and shared between siblings): + REAL(ReKi), POINTER :: Position(:,:) => NULL() !< XYZ coordinate of node (3,:) + REAL(R8Ki), POINTER :: RefOrientation(:,:,:) => NULL() !< Original/reference orientation [DCM] (3,3,:) + +! Here are some built in derived data types that can represent values at the nodes +! the last dimension of each of these has range 1:nnodes for the mesh being represented +! and they are indexed by the element arrays above +! only some of these would be allocated, depending on what's being represented +! on the mesh. +! Whether or not these are allocated is indicated in the fieldmask, which can +! be interrogated by a routine using an instance of the type. If you add a field +! here, be sure to change the table of parameters used to size and index fieldmask above. + + REAL(ReKi), ALLOCATABLE :: Force(:,:) !< Field: Force vectors (3,NNodes) + REAL(ReKi), ALLOCATABLE :: Moment(:,:) !< Field: Moment vectors (3,NNodes) + REAL(R8Ki), ALLOCATABLE :: Orientation(:,:,:) !< Field: Direction Cosine Matrix (DCM) (3,3,NNodes) + REAL(R8Ki), ALLOCATABLE :: TranslationDisp(:,:) !< Field: Translational displacements (3,NNodes) + REAL(ReKi), ALLOCATABLE :: RotationVel(:,:) !< Field: Rotational velocities (3,NNodes) + REAL(ReKi), ALLOCATABLE :: TranslationVel(:,:) !< Field: Translational velocities (3,NNodes) + REAL(ReKi), ALLOCATABLE :: RotationAcc(:,:) !< Field: Rotational accelerations (3,NNodes) + REAL(ReKi), ALLOCATABLE :: TranslationAcc(:,:) !< Field: Translational accelerations (3,NNodes) + REAL(ReKi), ALLOCATABLE :: Scalars(:,:) !< Scalars (nScalars,NNodes) + INTEGER :: nScalars !< Stores value of nScalars when created +!bjj: to be added later: REAL(ReKi), ALLOCATABLE :: ElementScalars(nElementScalars,nelemlist) ! Scalars associated with elements +!bjj: to be added later: INTEGER :: nElementScalars ! Stores value of nElementScalars when created + + ! Keeping track of siblings: + TYPE(MeshType),POINTER :: SiblingMesh => NULL() !< Pointer to mesh's (only) sibling + + END TYPE MeshType + +CONTAINS +!> This function returns the number of nodes in a given type of element. + INTEGER FUNCTION NumNodes( Xelement ) + INTEGER, INTENT(IN) :: Xelement !< type of element + + SELECT CASE ( Xelement ) + CASE ( ELEMENT_POINT ) + NumNodes = 1 + CASE ( ELEMENT_LINE2 ) + NumNodes = 2 + CASE ( ELEMENT_LINE3 ) + NumNodes = 3 + CASE ( ELEMENT_TRI3 ) + NumNodes = 3 + CASE ( ELEMENT_TRI6 ) + NumNodes = 6 + CASE ( ELEMENT_QUAD4 ) + NumNodes = 4 + CASE ( ELEMENT_QUAD8 ) + NumNodes = 8 + CASE ( ELEMENT_TET4 ) + NumNodes = 4 + CASE ( ELEMENT_TET10 ) + NumNodes = 10 + CASE ( ELEMENT_HEX8 ) + NumNodes = 8 + CASE ( ELEMENT_HEX20 ) + NumNodes = 20 + CASE ( ELEMENT_WEDGE6 ) + NumNodes = 6 + CASE ( ELEMENT_WEDGE15 ) + NumNodes = 15 + CASE DEFAULT + NumNodes = 0 + CALL ProgAbort(' NumNodes: invalid argument Xelement = '//TRIM(Num2LStr(Xelement))) + END SELECT + END FUNCTION NumNodes + +!> This function determines if a mesh contains any motion field (translational/rotational positions, velocities, accelerations or scalars). + LOGICAL FUNCTION HasMotionFields(Mesh) + + TYPE(MeshType), INTENT(IN) :: Mesh !< mesh to query + + IF ( Mesh%FieldMask(MASKID_TRANSLATIONDISP) & + .or. Mesh%FieldMask(MASKID_ORIENTATION) & + .or. Mesh%FieldMask(MASKID_TRANSLATIONVEL) & + .or. Mesh%FieldMask(MASKID_ROTATIONVEL) & + .or. Mesh%FieldMask(MASKID_TRANSLATIONACC) & + .or. Mesh%FieldMask(MASKID_ROTATIONACC) & + .or. Mesh%FieldMask(MASKID_SCALAR) & + ) THEN + + HasMotionFields = .TRUE. + ELSE + HasMotionFields = .FALSE. + END IF + + END FUNCTION HasMotionFields + +!> This function determines if a mesh contains any load field (force or motion). + LOGICAL FUNCTION HasLoadFields(Mesh) + + TYPE(MeshType), INTENT(IN) :: Mesh !< mesh to query + + IF ( Mesh%FieldMask(MASKID_FORCE) & + .or. Mesh%FieldMask(MASKID_MOMENT) & + ) THEN + + HasLoadFields = .TRUE. + ELSE + HasLoadFields = .FALSE. + END IF + + END FUNCTION HasLoadFields + +!> This subroutine copies the element record data from one ElemRecType data structure to another. It calls the Fortran 2003 +!! intrinsic MOVE_ALLOC routine to move the address of the Src\%ElemNodes array to the Dest\%ElemNodes array without physically +!! copying any of the array. On exist Src\%ElemNodes will be deallocated. + SUBROUTINE Mesh_MoveAlloc_ElemRecType( Src, Dest ) + TYPE(ElemRecType), INTENT(INOUT) :: Src !< mesh containing ElemNodes to be moved + TYPE(ElemRecType), INTENT(INOUT) :: Dest !< mesh that will receive the ElemNodes array from Src + + Dest%Xelement = Src%Xelement + Dest%Nneighbors = Src%Nneighbors + Dest%det_jac = Src%det_jac + if (allocated(Src%ElemNodes)) & ! bjj: 9/12/15 added this because of invalid memory address (harmless?) found with Inspector + CALL Move_Alloc( Src%ElemNodes, Dest%ElemNodes ) + + END SUBROUTINE Mesh_MoveAlloc_ElemRecType +END MODULE ModMesh_Types diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_Base.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_Base.f90 new file mode 100644 index 000000000..66873d24b --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_Base.f90 @@ -0,0 +1,77 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +! +!********************************************************************************************************************************** +!> This module stores basic constants and routines that are not system-specific, but may be used in the system-specific routines. +MODULE NWTC_Base + + + USE, INTRINSIC :: ISO_C_Binding + USE Precision + + IMPLICIT NONE + +!======================================================================= + + !logical :: debug_print = .false. + + ! General constants: + + INTEGER, PARAMETER :: BITS_IN_ADDR = C_INTPTR_T*8 !< The number of bits in an address (32-bit or 64-bit). + INTEGER, PARAMETER :: ErrMsgLen = 1024 !< The maximum number of characters in an error message in the FAST framework + INTEGER, PARAMETER :: CStringLen = 1025 !< Length of strings through the C interface + + INTEGER(IntKi), PARAMETER :: ChanLen = 20 !< The maximum allowable length of channel names (i.e., width of output columns) in the FAST framework + INTEGER(IntKi), PARAMETER :: MinChanLen = 10 !< The min allowable length of channel names (i.e., width of output columns), used because some modules (like Bladed DLL outputs) have excessively long names + INTEGER(IntKi), PARAMETER :: LinChanLen = 200 !< The allowable length of row/column names in linearization files + + + INTEGER(IntKi), PARAMETER :: NWTC_Verbose = 10 !< The maximum level of verbosity + INTEGER(IntKi), PARAMETER :: NWTC_VerboseLevel = 5 !< a number in [0, NWTC_Verbose]: 0 = no output; NWTC_Verbose=verbose; + + ! Global Error-level variables: + + INTEGER(IntKi), PARAMETER :: ErrID_None = 0 !< ErrStat parameter indicating "no error" + INTEGER(IntKi), PARAMETER :: ErrID_Info = 1 !< ErrStat parameter indicating "informational message" + INTEGER(IntKi), PARAMETER :: ErrID_Warn = 2 !< ErrStat parameter indicating "warning" + INTEGER(IntKi), PARAMETER :: ErrID_Severe = 3 !< ErrStat parameter indicating "severe error"; + INTEGER(IntKi), PARAMETER :: ErrID_Fatal = 4 !< ErrStat parameter indicating "fatal error"; simulation should end + + INTEGER(IntKi) :: AbortErrLev = ErrID_Fatal !< ErrStat that indicates the error level when program should end; ErrID_Fatal by default. Note that this is not a PARAMETER + + + INTEGER(IntKi), PARAMETER :: NWTC_MAX_DLL_PROC = 3 !< maximum number of procedures that can be dynamically loaded from a DLL (see DLL_Type nwtc_base::dll_type) + + + !> Type definition for dynamically loaded libraries: + !! Note that changes here may need to be reflected in DLLTypePack() (nwtc_io::dlltypepack) DLLTypeUnPack() (nwtc_io::dlltypeunpack), + !! and the FAST Registry executable. + + TYPE DLL_Type + + INTEGER(C_INTPTR_T) :: FileAddr !< The address of file FileName. (RETURN value from LoadLibrary ) [Windows] + TYPE(C_PTR) :: FileAddrX = C_NULL_PTR !< The address of file FileName. (RETURN value from dlopen ) [Linux] + TYPE(C_FUNPTR) :: ProcAddr(NWTC_MAX_DLL_PROC) = C_NULL_FUNPTR !< The address of procedure ProcName. (RETURN value from GetProcAddress or dlsym) [initialized to Null for pack/unpack] + + CHARACTER(1024) :: FileName !< The name of the DLL file including the full path to the current working directory. + CHARACTER(1024) :: ProcName(NWTC_MAX_DLL_PROC) = "" !< The name of the procedure in the DLL that will be called. + + END TYPE DLL_Type + + +END MODULE NWTC_Base diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_IO.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_IO.f90 new file mode 100644 index 000000000..eeecdb9b9 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_IO.f90 @@ -0,0 +1,8693 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +!********************************************************************************************************************************** + +!> This module contains I/O-related variables and routines with non-system-specific logic. +MODULE NWTC_IO + + USE SysSubs + USE NWTC_Library_Types ! ProgDesc and other types with copy and other routines for those types + USE IEEE_ARITHMETIC + USE VersionInfo + + IMPLICIT NONE + +!======================================================================= + + TYPE(ProgDesc), PARAMETER :: NWTC_Ver = & + ProgDesc( 'NWTC Subroutine Library', '', '') !< The name, version, and date of the NWTC Subroutine Library + + !> This type stores a linked list of file names, used in MLB-style input file parsing (currently used in AirfoilInfo) + TYPE, PUBLIC :: FNlist_Type + CHARACTER(1024) :: FileName !< A file name + TYPE(FNlist_Type), POINTER :: Next => NULL() !< The pointer to the next file name in the list + END TYPE FNlist_Type + + + ! Global coupling scheme variables. + + INTEGER(IntKi), PARAMETER :: ExplicitLoose = 1 !< parameter for global coupling scheme explicit-loose type + !bjj: will add more of these as we work our way + + + ! Global I/O-related variables. + + INTEGER(IntKi), PARAMETER :: FlgType = 1 !< Switch for telling if a variable is a flag (logical). + INTEGER(IntKi), PARAMETER :: NumType = 2 !< Switch for telling if a variable is a number. + INTEGER(IntKi), PARAMETER :: StrType = 3 !< Switch for telling if a variable is a string. + + INTEGER(B2Ki), PARAMETER :: FileFmtID_WithTime = 1 !< ID for FAST Output File Format, specifies that the time channel is included in the output file (use if the output can occur at variable times) + INTEGER(B2Ki), PARAMETER :: FileFmtID_WithoutTime = 2 !< ID for FAST Output File Format, specifies that the time channel is not included in the output file (used only with constant time-step output) + INTEGER(B2Ki), PARAMETER :: FileFmtID_NoCompressWithoutTime = 3 !< ID for FAST Output File Format, specifies that the time channel is not included in the output file (used only with constant time-step output), and data is not compressed, but written as double-precision floats + INTEGER(B2Ki), PARAMETER :: FileFmtID_ChanLen_In = 4 !< ID for FAST Output File Format, specifies that the time channel is not included in the output file, and channel length is included in the file + + + LOGICAL :: Beep = .TRUE. !< Flag that specifies whether or not to beep for error messages and program terminations. + + CHARACTER(20) :: ProgName = ' ' !< The name of the calling program. DO NOT USE THIS IN NEW PROGRAMS (Modules) + CHARACTER(99) :: ProgVer = ' ' !< The version (including date) of the calling program. DO NOT USE THIS IN NEW PROGRAMS + CHARACTER(1), PARAMETER :: Tab = CHAR( 9 ) !< The tab character. + CHARACTER(*), PARAMETER :: CommChars = '!#%' !< Comment characters that mark the end of useful input + INTEGER(IntKi), PARAMETER :: NWTC_SizeOfNumWord = 200 !< maximum length of the words containing numeric input (for ParseVar routines) + + ! Parameters for writing to echo files (in this module only) + + INTEGER(IntKi), PARAMETER :: NWTC_MaxAryLen = 100 !< the maximum length of arrays that can be printed with the array formats below (used to make sure we don't crash when trying to write too many): + ! >>> Note that the following array formats use 100, the value of NWTC_MaxAryLen above. Please keep the two numbers consistant! + CHARACTER(*),PARAMETER :: Ec_StrAryFrmt = "(15X,A,T30,' - ',A,/,2X,100('""',A,'""',:,1X))" !< Output format for array of string parameters. + CHARACTER(*),PARAMETER :: Ec_StrFrmt = "(15X,A,T30,' - ',A,/,2X, A )" !< Output format for string parameters + CHARACTER(*),PARAMETER :: Ec_ReAryFrmt = "(15X,A,T30,' - ',A,/,100(2X,ES11.4e2,:))" !< Output format for array of real parameters. + CHARACTER(*),PARAMETER :: Ec_ReFrmt = "( 2X, ES11.4e2,2X,A,T30,' - ',A )" !< Output format for real parameters + CHARACTER(*),PARAMETER :: Ec_LgAryFrmt = "(15X,A,T30,' - ',A,/,100(2X,L11,:))" !< Output format for array of logical parameters. + CHARACTER(*),PARAMETER :: Ec_LgFrmt = "( 2X, L11,2X,A,T30,' - ',A )" !< Output format for logical parameters + CHARACTER(*),PARAMETER :: Ec_IntAryFrmt = "(15X,A,T30,' - ',A,/,100(2X,I11,:))" !< Output format for array of integer parameters. + CHARACTER(*),PARAMETER :: Ec_IntFrmt = "( 2X, I11,2X,A,T30,' - ',A )" !< Output format for integer parameters + CHARACTER(*),PARAMETER :: Ec_Ch11Frmt = "( 2X, A11,2X,A,T30,' - ',A )" !< Output format for 11-character string parameters + ! <<< End of arrays that use number defined in NWTC_MaxAryLen + +!======================================================================= + + !> \copydoc nwtc_io::allcary1 + INTERFACE AllocAry + MODULE PROCEDURE AllCAry1 + MODULE PROCEDURE AllCAry2 + MODULE PROCEDURE AllCAry3 + ! MODULE PROCEDURE AllCAry4 Not yet coded. + MODULE PROCEDURE AllI1BAry1 ! 1-dimensional array of B1Ki integers + MODULE PROCEDURE AllI2BAry1 ! 1-dimensional array of B2Ki integers + MODULE PROCEDURE AllI4BAry1 ! 1-dimensional array of B4Ki integers + MODULE PROCEDURE AllIAry2 + MODULE PROCEDURE AllIAry3 + ! MODULE PROCEDURE AllIAry4 Not yet coded. + MODULE PROCEDURE AllLAry1 + MODULE PROCEDURE AllLAry2 + MODULE PROCEDURE AllLAry3 + ! MODULE PROCEDURE AllLAry4 Not yet coded. + + MODULE PROCEDURE AllR4Ary1 ! 1-dimensional array of SiKi reals + MODULE PROCEDURE AllR8Ary1 ! 1-dimensional array of R8Ki reals + MODULE PROCEDURE AllR16Ary1 ! 1-dimensional array of QuKi reals + MODULE PROCEDURE AllR4Ary2 ! 2-dimensional array of SiKi reals + MODULE PROCEDURE AllR8Ary2 ! 2-dimensional array of R8Ki reals + MODULE PROCEDURE AllR16Ary2 ! 2-dimensional array of QuKi reals + + MODULE PROCEDURE AllR4Ary3 ! 3-dimensional array of SiKi reals + MODULE PROCEDURE AllR8Ary3 ! 3-dimensional array of R8Ki reals + MODULE PROCEDURE AllR16Ary3 ! 3-dimensional array of QuKi reals + MODULE PROCEDURE AllR4Ary4 ! 4-dimensional array of SiKi reals + MODULE PROCEDURE AllR8Ary4 ! 4-dimensional array of R8Ki reals + MODULE PROCEDURE AllR16Ary4 ! 4-dimensional array of QuKi reals + MODULE PROCEDURE AllR4Ary5 ! 5-dimensional array of SiKi reals + MODULE PROCEDURE AllR8Ary5 ! 5-dimensional array of R8Ki reals + MODULE PROCEDURE AllR16Ary5 ! 5-dimensional array of QuKi reals + END INTERFACE + + !> \copydoc nwtc_io::allipary1 + INTERFACE AllocPAry + MODULE PROCEDURE AllIPAry1 + MODULE PROCEDURE AllIPAry2 + MODULE PROCEDURE AllFPAry1 + MODULE PROCEDURE AllRPAry2 + MODULE PROCEDURE AllR4PAry3 + MODULE PROCEDURE AllR8PAry3 + MODULE PROCEDURE AllR16PAry3 +! MODULE PROCEDURE AllRPAry4 !not yet coded + END INTERFACE + + !> \copydoc nwtc_io::parsechvar + INTERFACE ParseVar ! Parses a character variable name and value from a string. + MODULE PROCEDURE ParseChVar ! Parses a character string from a string. + MODULE PROCEDURE ParseDbVar ! Parses a double-precision REAL from a string. + MODULE PROCEDURE ParseInVar ! Parses an INTEGER from a string. + MODULE PROCEDURE ParseLoVar ! Parses an LOGICAL from a string. + MODULE PROCEDURE ParseSiVar ! Parses a single-precision REAL from a string. + END INTERFACE + + !> \copydoc nwtc_io::parsechvarwdefault + INTERFACE ParseVarWDefault ! Parses a character variable name and value from a string, potentially sets to a default value if "Default" is parsed. + MODULE PROCEDURE ParseChVarWDefault ! Parses a character string from a string, potentially sets to a default value if "Default" is parsed. + MODULE PROCEDURE ParseDbVarWDefault ! Parses a double-precision REAL from a string, potentially sets to a default value if "Default" is parsed. + MODULE PROCEDURE ParseInVarWDefault ! Parses an INTEGER from a string, potentially sets to a default value if "Default" is parsed. + MODULE PROCEDURE ParseLoVarWDefault ! Parses an LOGICAL from a string, potentially sets to a default value if "Default" is parsed. + MODULE PROCEDURE ParseSiVarWDefault ! Parses a single-precision REAL from a string, potentially sets to a default value if "Default" is parsed. + END INTERFACE + + !> \copydoc nwtc_io::parsedbary + INTERFACE ParseAry ! Parse an array of numbers from a string. + MODULE PROCEDURE ParseDbAry ! Parse an array of double-precision REAL values. + MODULE PROCEDURE ParseInAry ! Parse an array of whole numbers. + MODULE PROCEDURE ParseLoAry ! Parse an array of LOGICAL values. + MODULE PROCEDURE ParseSiAry ! Parse an array of single-precision REAL values. + MODULE PROCEDURE ParseChAry + END INTERFACE + + !> \copydoc nwtc_io::checkr4var + INTERFACE CheckRealVar + MODULE PROCEDURE CheckR4Var ! 4-byte real + MODULE PROCEDURE CheckR8Var ! 8-byte real + MODULE PROCEDURE CheckR16Var ! 16-byte real + END INTERFACE + + !> \copydoc nwtc_io::readcvar + INTERFACE ReadVar + MODULE PROCEDURE ReadCVar + MODULE PROCEDURE ReadIVar + MODULE PROCEDURE ReadLVar + MODULE PROCEDURE ReadR4Var ! 4-byte real + MODULE PROCEDURE ReadR8Var ! 8-byte real + MODULE PROCEDURE ReadR16Var ! 16-byte real + END INTERFACE + + !> \copydoc nwtc_io::readivarwdefault + INTERFACE ReadVarWDefault + !MODULE PROCEDURE ReadCVar + MODULE PROCEDURE ReadIVarWDefault + MODULE PROCEDURE ReadLVarWDefault ! Logical + MODULE PROCEDURE ReadR4VarWDefault ! 4-byte real + MODULE PROCEDURE ReadR8VarWDefault ! 8-byte real + MODULE PROCEDURE ReadR16VarWDefault ! 16-byte real + END INTERFACE + + !> \copydoc nwtc_io::readcary + INTERFACE ReadAry + MODULE PROCEDURE ReadCAry + MODULE PROCEDURE ReadCAryFromStr + MODULE PROCEDURE ReadIAry + MODULE PROCEDURE ReadLAry + MODULE PROCEDURE ReadR4Ary ! read array of 4-byte reals + MODULE PROCEDURE ReadR4AryFromStr + MODULE PROCEDURE ReadR8Ary ! read array of 8-byte reals + MODULE PROCEDURE ReadR8AryFromStr + MODULE PROCEDURE ReadR16Ary ! read array of 16-byte reals + MODULE PROCEDURE ReadR16AryFromStr + END INTERFACE + + !> \copydoc nwtc_io::readcarylines + INTERFACE ReadAryLines + MODULE PROCEDURE ReadCAryLines + MODULE PROCEDURE ReadR4AryLines + MODULE PROCEDURE ReadR8AryLines + MODULE PROCEDURE ReadR16AryLines +! MODULE PROCEDURE ReadIAryLines ! Not coded yet +! MODULE PROCEDURE ReadLAryLines ! Not coded yet + END INTERFACE + + !> \copydoc nwtc_io::int2lstr + INTERFACE Num2LStr + MODULE PROCEDURE Int2LStr ! default integers + MODULE PROCEDURE R2LStr4 ! 4-byte reals + MODULE PROCEDURE R2LStr8 ! 8-byte reals + MODULE PROCEDURE R2LStr16 ! 16-byte reals + END INTERFACE + + !> \copydoc nwtc_io::dispnvd0 + INTERFACE DispNVD + MODULE PROCEDURE DispNVD0 ! No arguments. + MODULE PROCEDURE DispNVD1 ! Single argument of TYPE ProgDesc + MODULE PROCEDURE DispNVD2 ! Two arguments of TYPE character + END INTERFACE + + !> \copydoc nwtc_io::wrmatrix1r4 + INTERFACE WrMatrix + MODULE PROCEDURE WrMatrix1R4 ! Single dimension matrix (Ary) of SiKi + MODULE PROCEDURE WrMatrix2R4 ! Two dimension matrix of SiKi + MODULE PROCEDURE WrMatrix1R8 ! Single dimension matrix (Ary) of R8Ki + MODULE PROCEDURE WrMatrix2R8 ! Two dimension matrix of R8Ki + MODULE PROCEDURE WrMatrix1R16 ! Single dimension matrix (Ary) of QuKi + MODULE PROCEDURE WrMatrix2R16 ! Two dimension matrix of QuKi + END INTERFACE + + !> \copydoc nwtc_io::wrpartialmatrix1r8 + INTERFACE WrPartialMatrix + MODULE PROCEDURE WrPartialMatrix1R8 ! Single dimension matrix (array) of R8Ki + MODULE PROCEDURE WrPartialMatrix2R8 ! Two dimension matrix of R8Ki + END INTERFACE + + !> \copydoc nwtc_io::wrr4aryfilenr + INTERFACE WrNumAryFileNR + MODULE PROCEDURE WrIAryFileNR + MODULE PROCEDURE WrR4AryFileNR + MODULE PROCEDURE WrR8AryFileNR + MODULE PROCEDURE WrR16AryFileNR + END INTERFACE + + +CONTAINS + +!> This routine adjusts strings created from real numbers (4, 8, or 16-byte) +! It removes leading spaces and trailing zeros. It is intended to be called +! from routines R2LStr4, R2LStr8, and R2LStr16 (nwtc_io::r2lstr). +!======================================================================= + SUBROUTINE AdjRealStr( NumStr ) + + + CHARACTER(*), INTENT(INOUT) :: NumStr !< String representing a real number (e.g., from R2LStr4) + + ! Local declarations. + + INTEGER :: IC ! Character index. + + + NumStr = ADJUSTL( NumStr ) + + + ! Replace trailing zeros and possibly the decimal point with blanks. + ! Stop trimming once we find the decimal point or a nonzero. + + + ! Don't remove (important!) trailing zeros if they are in the exponent: + + IF (INDEX( NumStr, "E" ) > 0 ) RETURN + IF (INDEX( NumStr, "e" ) > 0 ) RETURN + + ! These are not in the exponent + + DO IC=LEN_TRIM( NumStr ),1,-1 + + IF ( NumStr(IC:IC) == '.' ) THEN + NumStr(IC:IC) = ' ' + RETURN + ELSE IF ( NumStr(IC:IC) /= '0' ) THEN + RETURN + END IF + + NumStr(IC:IC) = ' ' + + END DO ! IC + + + END SUBROUTINE AdjRealStr +!======================================================================= +!> This routine allocates an array to the size specified in the AryDim input arguement(s). +!! Arrays are of type ALLOCATABLE. +!! If the array is already allocated on entry to this routine, an error will be generated. \n +!! Use AllocAry (nwtc_io::allocary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE AllCAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 1-D CHARACTER array. + + ! Argument declarations. + + CHARACTER(*), ALLOCATABLE :: Ary (:) !< Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 !< The size of the first dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr !< Brief array description (for error message). + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1))//' characters in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllCAry1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllCAry2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 2-D CHARACTER array. + + + ! Argument declarations. + + CHARACTER(*), ALLOCATABLE :: Ary (:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1*AryDim2))//' characters in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllCAry2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllCAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D CHARACTER array. + + + ! Argument declarations. + + CHARACTER(*), ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3))//' characters in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + RETURN + END SUBROUTINE AllCAry3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllI1BAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 1-D INTEGER B1Ki array. + + + ! Argument declarations. + + INTEGER(B1Ki), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER(IntKi), INTENT(IN) :: AryDim1 ! The size of the array + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*1))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = ' ' + END IF + + RETURN + END SUBROUTINE AllI1BAry1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllI2BAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 1-D INTEGER B2Ki array. + + + ! Argument declarations. + + INTEGER(B2Ki), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER(IntKi), INTENT(IN) :: AryDim1 ! The size of the array + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*2))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = ' ' + END IF + + RETURN + END SUBROUTINE AllI2BAry1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllI4BAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 1-D INTEGER B1Ki array. + + + ! Argument declarations. + + INTEGER(B4Ki), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER(IntKi), INTENT(IN) :: AryDim1 ! The size of the array + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*4))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = ' ' + END IF + + RETURN + END SUBROUTINE AllI4BAry1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllIAry2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D INTEGER array. + + + ! Argument declarations. + + INTEGER(IntKi), ALLOCATABLE :: Ary (:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*BYTES_IN_INT))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllIAry2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllIAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D INTEGER array. + + + ! Argument declarations. + + INTEGER(IntKi), ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_INT))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllIAry3 +!======================================================================= +!> This routine allocates an array to the size specified in the AryDim input arguement(s). +!! Arrays are of type POINTER. +!! If the array pointer is already associated on entry to this routine, the array it points to +!! will be deallocated first. \n +!! Use AllocPAry (nwtc_io::allocpary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE AllIPAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 1-D INTEGER array. + + ! Argument declarations. + + INTEGER, POINTER :: Ary (:) !< Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 !< The size of the first dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr !< Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllIPAry1: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + + RETURN + END SUBROUTINE AllIPAry1 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllIPAry2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D INTEGER array. + + ! Argument declarations. + + INTEGER, POINTER :: Ary (:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllIPAry2: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllIPAry2 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllFPAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 1-D REAL array. + ! Argument declarations. + + REAL(C_FLOAT), POINTER :: Ary (:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllRPAry2: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllFPAry1 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllRPAry2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + ! This routine allocates a 2-D REAL array. + ! Argument declarations. + + REAL(ReKi), POINTER :: Ary (:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllRPAry2: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllRPAry2 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllR4PAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D REAL array. + + ! Argument declarations. + + REAL(SiKi), POINTER :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllRPAry3: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllR4PAry3 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllR8PAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D REAL array. + + ! Argument declarations. + + REAL(R8Ki), POINTER :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllRPAry3: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllR8PAry3 +!======================================================================= +!> \copydoc nwtc_io::allipary1 + SUBROUTINE AllR16PAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D REAL array. + + ! Argument declarations. + + REAL(QuKi), POINTER :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + + + IF ( ASSOCIATED(Ary) ) THEN + DEALLOCATE(Ary) + !ErrStat = ErrID_Warn + !ErrMsg = " AllRPAry3: Ary already allocated." + END IF + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + Ary = 0 + RETURN + END SUBROUTINE AllR16PAry3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllLAry1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 1-D LOGICAL array. + + + ! Argument declarations. + + LOGICAL, ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1))//& + ' logical values in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllLAry1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllLAry2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D LOGICAL array. + + + ! Argument declarations. + + LOGICAL, ALLOCATABLE :: Ary (:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1*AryDim2))//& + ' logical values in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllLAry2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllLAry3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + ! Argument declarations. + LOGICAL, ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating memory for '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3))//& + ' logical values in the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllLAry3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR4Ary1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + ! Argument declarations. + + REAL(SiKi), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the array. + + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*BYTES_IN_SiKi))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR4Ary1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR8Ary1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 1-D 8-byte REAL array. + + + ! Argument declarations. + + REAL(R8Ki), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the array. + + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*BYTES_IN_R8Ki))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR8Ary1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR16Ary1 ( Ary, AryDim1, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 1-D 16-byte REAL array. + + + ! Argument declarations. + + REAL(QuKi), ALLOCATABLE :: Ary (:) ! Array to be allocated + INTEGER, INTENT(IN) :: AryDim1 ! The size of the array. + + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*BYTES_IN_QuKi))//' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllR16Ary1 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR4Ary2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D 4-Byte REAL array. + + + ! Argument declarations. + + REAL(SiKi), ALLOCATABLE :: Ary (:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*BYTES_IN_SiKi))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllR4Ary2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR8Ary2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D 8-Byte REAL array. + + + ! Argument declarations. + + REAL(R8Ki), ALLOCATABLE :: Ary (:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*BYTES_IN_R8Ki))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE AllR8Ary2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR16Ary2 ( Ary, AryDim1, AryDim2, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 2-D 4-Byte REAL array. + + + ! Argument declarations. + + REAL(QuKi), ALLOCATABLE :: Ary (:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + + ALLOCATE ( Ary(AryDim1,AryDim2) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*BYTES_IN_QuKi))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR16Ary2 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR4Ary3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D 4-byte REAL array. + + + ! Argument declarations. + + REAL(SiKi), ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR4Ary3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR8Ary3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D 8-byte REAL array. + + + ! Argument declarations. + + REAL(R8Ki), ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR8Ary3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR16Ary3 ( Ary, AryDim1, AryDim2, AryDim3, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 3-D 16-byte REAL array. + + + ! Argument declarations. + + REAL(QuKi), ALLOCATABLE :: Ary (:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR16Ary3 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR4Ary4 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 4-D 4-byte REAL array. + + + ! Argument declarations. + + REAL(SiKi), ALLOCATABLE :: Ary (:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR4Ary4 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR8Ary4 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 4-D 8-byte REAL array. + + + ! Argument declarations. + + REAL(R8Ki), ALLOCATABLE :: Ary (:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR8Ary4 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR16Ary4 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 4-D 16-byte REAL array. + + + ! Argument declarations. + + REAL(QuKi), ALLOCATABLE :: Ary (:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + RETURN + END SUBROUTINE AllR16Ary4 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR4Ary5 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, AryDim5, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 5-D 4-byte REAL array. + + + ! Argument declarations. + + REAL(SiKi), ALLOCATABLE :: Ary (:,:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + INTEGER, INTENT(IN) :: AryDim5 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4,AryDim5) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*AryDim5*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + RETURN + END SUBROUTINE AllR4Ary5 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR8Ary5 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, AryDim5, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 5-D 8-byte REAL array. + + + ! Argument declarations. + + REAL(R8Ki), ALLOCATABLE :: Ary (:,:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + INTEGER, INTENT(IN) :: AryDim5 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4,AryDim5) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*AryDim5*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + RETURN + END SUBROUTINE AllR8Ary5 +!======================================================================= +!> \copydoc nwtc_io::allcary1 + SUBROUTINE AllR16Ary5 ( Ary, AryDim1, AryDim2, AryDim3, AryDim4, AryDim5, Descr, ErrStat, ErrMsg ) + + + ! This routine allocates a 5-D 16-byte REAL array. + + + ! Argument declarations. + + REAL(QuKi), ALLOCATABLE :: Ary (:,:,:,:,:) ! Array to be allocated + + INTEGER, INTENT(IN) :: AryDim1 ! The size of the first dimension of the array. + INTEGER, INTENT(IN) :: AryDim2 !< The size of the second dimension of the array. + INTEGER, INTENT(IN) :: AryDim3 !< The size of the third dimension of the array. + INTEGER, INTENT(IN) :: AryDim4 !< The size of the fourth dimension of the array. + INTEGER, INTENT(IN) :: AryDim5 !< The size of the fourth dimension of the array. + CHARACTER(*), INTENT(IN) :: Descr ! Brief array description. + INTEGER, INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message corresponding to ErrStat + + + ALLOCATE ( Ary(AryDim1,AryDim2,AryDim3,AryDim4,AryDim5) , STAT=ErrStat ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + IF ( ALLOCATED(Ary) ) THEN ! or Sttus=151 on IVF + ErrMsg = 'Error allocating memory for the '//TRIM( Descr )//' array; array was already allocated.' + ELSE + ErrMsg = 'Error allocating '//TRIM(Num2LStr(AryDim1*AryDim2*AryDim3*AryDim4*AryDim5*BYTES_IN_REAL))//& + ' bytes of memory for the '//TRIM( Descr )//' array.' + END IF + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + RETURN + END SUBROUTINE AllR16Ary5 +!======================================================================= +!> This subroutine checks for command-line arguments. + SUBROUTINE CheckArgs ( Arg1, ErrStat, Arg2, Flag, InputArgArray ) + + ! Argument declarations: + CHARACTER(*), INTENT(INOUT) :: Arg1 !< The first non-flag argument; generally, the name of the input file. + INTEGER, INTENT( OUT), OPTIONAL :: ErrStat !< An optional argument for catching errors; if present, program does not abort on error. + CHARACTER(*), INTENT( OUT), OPTIONAL :: Arg2 !< An optional 2nd non-flag argument. + CHARACTER(*), INTENT( OUT), OPTIONAL :: Flag !< An optional flag argument; the first argument starting with a switch character. + CHARACTER(*), INTENT(IN ), DIMENSION(:), OPTIONAL :: InputArgArray !< An optional argument containing the arguments to parse; primarily used for unit testing. + + ! Local declarations: + INTEGER :: I, J ! Iterator variables + CHARACTER(1024) :: Arg, FlagIter + CHARACTER(1024), DIMENSION(:), ALLOCATABLE :: ArgArray, TempArray, Flags + LOGICAL :: FirstArgumentSet, SecondArgumentSet + + FirstArgumentSet = .FALSE. + SecondArgumentSet = .FALSE. + + IF ( PRESENT(Arg2) ) Arg2 = "" + IF ( PRESENT(Flag) ) Flag = "" + + ! Save all arguments in a single argument array; this is primarily used to enable unit testing + IF ( PRESENT(InputArgArray) ) THEN + ALLOCATE( ArgArray( SIZE(InputArgArray) ) ) + ArgArray = InputArgArray + ELSE + ALLOCATE( ArgArray( COMMAND_ARGUMENT_COUNT() ) ) + DO I = 1, SIZE(ArgArray) + CALL GET_COMMAND_LINE_ARG( I, ArgArray(I) ) + END DO + END IF + + ! Early return if no arguments and no default input file given + IF ( SIZE(ArgArray) == 0 .AND. LEN( TRIM(Arg1) ) == 0 ) THEN + CALL INVALID_SYNTAX( 'no command-line arguments given.' ) + CALL CLEANUP() + RETURN + END IF + + ! Split arguments into flags and non-flags + ALLOCATE( Flags(0) ) + DO I = 1, SIZE(ArgArray) + Arg = TRIM(ArgArray(I)) + IF ( IsFlag(Arg) ) THEN + ! This is how we can dynamically resize an array in Fortran... + ! Dont do this where performance matters. + ALLOCATE( TempArray( SIZE(Flags) + 1 ) ) + DO J = 1, SIZE(Flags) + TempArray(J) = Flags(J) + END DO + TempArray(SIZE(Flags) + 1) = TRIM(Arg) + DEALLOCATE(Flags) + CALL MOVE_ALLOC(TempArray, Flags) + ELSE IF ( .NOT. FirstArgumentSet ) THEN + Arg1 = TRIM(Arg) + FirstArgumentSet = .TRUE. + ELSE IF ( .NOT. SecondArgumentSet ) THEN + Arg2 = TRIM(Arg) + SecondArgumentSet = .True. + ELSE + CALL INVALID_SYNTAX( 'too many command-line arguments given.' ) + CALL CLEANUP() + RETURN + END IF + END DO + + DO I = 1, SIZE(Flags) + + FlagIter = Flags(I)(2:) ! This results in the flag without the switch character + CALL Conv2UC( FlagIter ) + IF ( PRESENT(Flag) ) Flag = FlagIter + + SELECT CASE ( TRIM(FlagIter) ) + + CASE ('H') + CALL DispCopyrightLicense( ProgName ) + CALL DispCompileRuntimeInfo + CALL NWTC_DisplaySyntax( Arg1, ProgName ) + IF ( PRESENT( ErrStat ) ) ErrStat = ErrID_None + CALL CLEANUP() + RETURN + + CASE ('V', 'VERSION') + CALL DispCopyrightLicense( ProgName ) + CALL DispCompileRuntimeInfo + IF ( PRESENT( ErrStat ) ) ErrStat = ErrID_None + CALL CLEANUP() + RETURN + + CASE ('RESTART') + IF ( FirstArgumentSet .AND. .NOT. SecondArgumentSet ) THEN + Arg2 = Arg1 + Arg1 = "" + END IF + IF ( .NOT. FirstArgumentSet .AND. .NOT. SecondArgumentSet ) THEN + CALL INVALID_SYNTAX( 'the restart capability requires at least one argument: <input_file (OPTIONAL)> -restart <checkpoint_file>' ) + CALL CLEANUP() + RETURN + END IF + + CASE ('VTKLIN') + IF ( FirstArgumentSet .AND. .NOT. SecondArgumentSet ) THEN + Arg2 = Arg1 + Arg1 = "" + END IF + IF ( .NOT. FirstArgumentSet .AND. .NOT. SecondArgumentSet ) THEN + CALL INVALID_SYNTAX( 'the restart capability for vtk mode shapes requires at least one argument: <input_file (OPTIONAL)> -vtklin <visualization_input_file>' ) + CALL CLEANUP() + RETURN + END IF + + CASE DEFAULT + CALL INVALID_SYNTAX( 'unknown command-line argument given: '//TRIM(FlagIter) ) + CALL CLEANUP() + RETURN + + END SELECT + + END DO + + IF ( PRESENT( ErrStat ) ) ErrStat = ErrID_None + CALL CLEANUP() + + RETURN + + CONTAINS + SUBROUTINE CLEANUP() + IF ( ALLOCATED(ArgArray) ) DEALLOCATE(ArgArray) + IF ( ALLOCATED(Flags) ) DEALLOCATE(Flags) + IF ( ALLOCATED(TempArray) ) DEALLOCATE(TempArray) + END SUBROUTINE + + SUBROUTINE INVALID_SYNTAX(ErrorMessage) + + CHARACTER(*), INTENT(IN) :: ErrorMessage + + CALL DispCopyrightLicense( ProgName ) + CALL DispCompileRuntimeInfo + CALL NWTC_DisplaySyntax( Arg1, ProgName ) + CALL ProgAbort( ' Invalid syntax: '//TRIM(ErrorMessage), PRESENT(ErrStat) ) + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_Fatal + + END SUBROUTINE + + SUBROUTINE GET_COMMAND_LINE_ARG(ArgIndex, ArgGiven) + + INTEGER, INTENT(IN) :: ArgIndex !< Index location of the argument to get. + CHARACTER(1024), INTENT(OUT) :: ArgGiven !< The gotten command-line argument. + INTEGER :: Error !< Indicates if there was an error getting an argument. + + CALL GET_COMMAND_ARGUMENT( ArgIndex, ArgGiven, STATUS=Error ) + ArgGiven = TRIM(ArgGiven) + IF ( Error /= 0 ) THEN + CALL ProgAbort ( ' Error getting command-line argument #'//TRIM( Int2LStr( ArgIndex ) )//'.', PRESENT(ErrStat) ) + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_Fatal + END IF + + END SUBROUTINE + + FUNCTION IsFlag(ArgString) + + CHARACTER(*), INTENT(IN) :: ArgString + LOGICAL :: IsFlag + + IF ( ArgString(1:1) == SwChar .OR. ArgString(1:1) == '-' ) THEN + IsFlag = .TRUE. + ELSE + IsFlag = .FALSE. + END IF + + END FUNCTION + + END SUBROUTINE CheckArgs +!======================================================================= +!> This subroutine checks the data to be parsed to make sure it finds +!! the expected variable name and an associated value. + SUBROUTINE ChkParseData ( Words, ExpVarName, FileName, FileLineNum, NameIndx, ErrStat, ErrMsg ) + + ! Arguments declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + INTEGER(IntKi), INTENT(IN) :: FileLineNum !< The number of the line in the file being parsed. + INTEGER(IntKi), INTENT(OUT) :: NameIndx !< The index into the Words array that points to the variable name. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName !< The expected variable name. + CHARACTER(*), INTENT(IN) :: FileName !< The name of the file being parsed. + CHARACTER(*), INTENT(IN) :: Words (2) !< The two words to be parsed from the line. + + + ! Local declarations. + + CHARACTER(20) :: ExpUCVarName ! The uppercase version of ExpVarName. + CHARACTER(20) :: FndUCVarName ! The uppercase version of the word being tested. + + + + ! Convert the found and expected names to uppercase. + + FndUCVarName = Words(1) + ExpUCVarName = ExpVarName + + CALL Conv2UC ( FndUCVarName ) + CALL Conv2UC ( ExpUCVarName ) + + + ! Allow for an empty variable name to be passed. This occurs when we have + ! multiple lines of items that may not have variable keys associated. In + ! this case, we will assume the first word has the value and return that. + ! Otherwise, we will check which is the variable keyname. + IF ( LEN_TRIM(ExpVarName) == 0 ) THEN + ! There isn't actually a variable name passed in, but this satisfies the + ! logic for retrieving the value in the calling routine + NameIndx = 2 + + ELSE + ! See which word is the variable name. Generate an error if it is neither. + ! If it is the first word, check to make sure the second word is not empty. + + IF ( TRIM( FndUCVarName ) == TRIM( ExpUCVarName ) ) THEN + NameIndx = 1 + IF ( LEN_TRIM( Words(2) ) == 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & + //'".'//NewLine//' >> The variable "'//TRIM( Words(1) )//'" was not assigned a value on line #' & + //TRIM( Num2LStr( FileLineNum ) )//'.' ) + RETURN + ENDIF + ELSE + FndUCVarName = Words(2) + CALL Conv2UC ( FndUCVarName ) + IF ( TRIM( FndUCVarName ) == TRIM( ExpUCVarName ) ) THEN + NameIndx = 2 + ELSE + CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & + //'".'//NewLine//' >> The variable "'//TRIM( ExpVarName )//'" was not found on line #' & + //TRIM( Num2LStr( FileLineNum ) )//'.' ) + RETURN + ENDIF + ENDIF + + ENDIF + + + CALL ExitThisRoutine ( ErrID_None, ' ' ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE ChkParseData ! ( Words, ExpVarName, FileName, FileLineNum, NameIndx, ErrStat, ErrMsg ) +!======================================================================= +!> This routine tests to make sure we have a valid format string for real numbers (i.e., it doesn't produce "****"). + SUBROUTINE ChkRealFmtStr ( RealFmt, RealFmtVar, FmtWidth, ErrStat, ErrMsg ) + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< An error level to be returned to the calling routine. + INTEGER(IntKi), INTENT(OUT) :: FmtWidth !< The number of characters that will result from writes. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< An error message to be returned to the calling routine. + + CHARACTER(*), INTENT(IN) :: RealFmt !< The proposed format string. + CHARACTER(*), INTENT(IN) :: RealFmtVar !< The name of the variable storing the format string. + + + ! Local delarations. + + REAL, PARAMETER :: TestVal = -1.0 ! The value to test the format specifier with. + + INTEGER :: IOS ! An integer to store the I/O status of the attempted internal write. + INTEGER, PARAMETER :: TestStrLen = 30 ! A parameter for specifying the length of RealStr. + + CHARACTER(TestStrLen) :: RealStr ! A string to test writing a real number to. + + + + ! Try writing TestVal to RealStr using RealFmt as the format. + ! Determine the format width. + + WRITE (RealStr,'('//RealFmt//')',IOSTAT=IOS) TestVal + + FmtWidth = Len_Trim( RealStr ) + + + ! Check to see if the format is invalid or if it did not have even a reasonable width. + + IF ( IOS /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'The real-format specifier, '//TRIM(RealFmtVar)//', is invalid. You set it to "'//TRIM( RealFmt )//'".' + FmtWidth = 0 + ELSEIF ( INDEX( RealStr, '*' ) > 0 ) THEN + ErrStat = ErrID_Severe + ErrMsg = 'The real-format specifier, '//TRIM(RealFmtVar)//', is too narrow to print even '//TRIM(Num2LStr(TestVal)) & + //'. You set it to "'//TRIM( RealFmt )//'".' + ELSE + ErrStat = ErrID_None + ErrMsg = "" + ENDIF + + + RETURN + END SUBROUTINE ChkRealFmtStr +!======================================================================= +!> This routine checks the I/O status and prints either an end-of-file or +!! an invalid-input message, and then aborts the program or returns an appropriate error level and message. + SUBROUTINE CheckIOS ( IOS, Fil, Variable, VarType, ErrStat, ErrMsg, TrapErrors ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: IOS !< I/O status + CHARACTER(*),INTENT(IN) :: Fil !< Name of input file + CHARACTER(*),INTENT(IN) :: Variable !< Variable name + INTEGER, INTENT(IN) :: VarType !< Type of variable + LOGICAL, INTENT(IN), OPTIONAL :: TrapErrors !< Determines if the program should abort or return to calling function + INTEGER, INTENT(OUT),OPTIONAL :: ErrStat !< Error status + CHARACTER(*),INTENT(OUT),OPTIONAL :: ErrMsg !< Error message (if present, no message is written to the screen) + + ! local variables + LOGICAL :: TrapThisError ! The local version of TrapErrors + CHARACTER(ErrMsgLen) :: Msg ! Temporary error message + + + + IF ( PRESENT( TrapErrors ) ) THEN + TrapThisError = TrapErrors + ELSE + TrapThisError = .FALSE. + END IF + + + IF ( IOS < 0 ) THEN + + Msg = 'Premature EOF for file "'//TRIM( Fil )//'" occurred while trying to read '//TRIM( Variable )//'.' + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_Fatal + IF ( PRESENT(ErrMsg) ) THEN + ErrMsg = Msg + ELSE + CALL WrScr( ' ' ) + CALL ProgAbort( ' '//TRIM(Msg), TrapThisError ) + END IF + + ELSE IF ( IOS > 0 ) THEN + + SELECTCASE ( VarType ) + + CASE ( NumType ) + Msg = 'Invalid numerical input' + CASE ( FlgType ) + Msg = 'Invalid logical input' + CASE ( StrType ) + Msg = 'Invalid character input' + CASE DEFAULT + Msg = 'Invalid input (unknown type)' + ENDSELECT + Msg = TRIM(Msg)//' for file "'//TRIM( Fil )//'" occurred while trying to read '//TRIM( Variable )//'.' + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_Fatal + + IF ( PRESENT(ErrMsg) ) THEN + ErrMsg = Msg + ELSE + CALL WrScr( ' ' ) + CALL ProgAbort( ' '//TRIM(Msg), TrapThisError ) + END IF + + ELSE + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + IF ( PRESENT(ErrMsg) ) ErrMsg = "" + + END IF + + + RETURN + END SUBROUTINE CheckIOS +!======================================================================= +!> This routine checks that real values are finite and not NaNs +SUBROUTINE CheckR4Var( RealVar, RealDesc, ErrStat, ErrMsg ) + + REAL(SiKi), INTENT(IN) :: RealVar !< Real value to check + CHARACTER(*),INTENT(IN) :: RealDesc !< description of RealVar + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*),INTENT(OUT) :: ErrMsg !< Error message + + IF (IEEE_IS_NAN(RealVar) .or. .not. IEEE_IS_FINITE( RealVar) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = trim(RealDesc)//': value is not a finite real number.' + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + +END SUBROUTINE CheckR4Var +!======================================================================= +!> \copydoc nwtc_io::checkr4var +SUBROUTINE CheckR8Var( RealVar, RealDesc, ErrStat, ErrMsg ) + + REAL(R8Ki), INTENT(IN) :: RealVar !< Real value to check + CHARACTER(*),INTENT(IN) :: RealDesc !< description of RealVar + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*),INTENT(OUT) :: ErrMsg !< Error message + + IF (IEEE_IS_NAN(RealVar) .or. .not. IEEE_IS_FINITE( RealVar) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = trim(RealDesc)//': value is not a finite real number.' + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + +END SUBROUTINE CheckR8Var +!======================================================================= +!> \copydoc nwtc_io::checkr4var +SUBROUTINE CheckR16Var( RealVar, RealDesc, ErrStat, ErrMsg ) + + REAL(QuKi), INTENT(IN) :: RealVar !< Real value to check + CHARACTER(*),INTENT(IN) :: RealDesc !< description of RealVar + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*),INTENT(OUT) :: ErrMsg !< Error message + + IF (IEEE_IS_NAN(RealVar) .or. .not. IEEE_IS_FINITE( RealVar) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = trim(RealDesc)//': value is not a finite real number.' + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + +END SUBROUTINE CheckR16Var +!======================================================================= +!> This routine converts all the text in a string to upper case. + SUBROUTINE Conv2UC ( Str ) + + ! Argument declarations. + + CHARACTER(*), INTENT(INOUT) :: Str !< The string to be converted to UC (upper case). + + + ! Local declarations. + + INTEGER :: IC ! Character index + + + + DO IC=1,LEN_TRIM( Str ) + + IF ( ( Str(IC:IC) >= 'a' ).AND.( Str(IC:IC) <= 'z' ) ) THEN + Str(IC:IC) = CHAR( ICHAR( Str(IC:IC) ) - 32 ) + END IF + + END DO ! IC + + + RETURN + END SUBROUTINE Conv2UC +!======================================================================= +!> This subroutine is used to count the number of "words" in a line of text. +!! It uses spaces, tabs, commas, semicolons, single quotes, and double quotes ("whitespace") +!! as word separators. Use GetWords (nwtc_io::getwords) to return the words from the line. + FUNCTION CountWords ( Line ) + + ! Function declaration. + + INTEGER :: CountWords !< Number of "words" in Line + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Line !< Count the words in this text string. + + + ! Local declarations. + + INTEGER :: Ch ! Character position. + INTEGER :: NextWhite ! Position of the next white space. + + + + ! Let's initialize the number of columns and the character pointer. + + CountWords = 0 + + + ! Let's make sure we have text on this line. + + IF ( LEN_TRIM( Line ) == 0 ) RETURN + + + ! Count words separated by any combination of spaces, tabs, commas, + ! semicolons, single quotes, and double quotes ("whitespace"). + + Ch = 0 + + DO + + NextWhite = SCAN( Line(Ch+1:) , ' ,;''"'//Tab ) + Ch = Ch + NextWhite + + IF ( NextWhite > 1 ) THEN + CountWords = CountWords + 1 + ELSE IF ( NextWhite == 1 ) THEN + CYCLE + ELSE + EXIT + END IF + + END DO + + + RETURN + END FUNCTION CountWords +!======================================================================= +!> This function returns a character string encoded with today's date in the form dd-mmm-ccyy. + FUNCTION CurDate( ) + + ! Function declaration. + + CHARACTER(11) :: CurDate !< 'dd-mmm-yyyy' string with the current date + + + ! Local declarations. + + CHARACTER(8) :: CDate ! String to hold the returned value from the DATE_AND_TIME subroutine call. + + + + ! Call the system date function. + + CALL DATE_AND_TIME ( CDate ) + + + ! Parse out the day. + + CurDate(1:3) = CDate(7:8)//'-' + + + ! Parse out the month. + + SELECT CASE ( CDate(5:6) ) + CASE ( '01' ) + CurDate(4:6) = 'Jan' + CASE ( '02' ) + CurDate(4:6) = 'Feb' + CASE ( '03' ) + CurDate(4:6) = 'Mar' + CASE ( '04' ) + CurDate(4:6) = 'Apr' + CASE ( '05' ) + CurDate(4:6) = 'May' + CASE ( '06' ) + CurDate(4:6) = 'Jun' + CASE ( '07' ) + CurDate(4:6) = 'Jul' + CASE ( '08' ) + CurDate(4:6) = 'Aug' + CASE ( '09' ) + CurDate(4:6) = 'Sep' + CASE ( '10' ) + CurDate(4:6) = 'Oct' + CASE ( '11' ) + CurDate(4:6) = 'Nov' + CASE ( '12' ) + CurDate(4:6) = 'Dec' + END SELECT + + + ! Parse out the year. + + CurDate(7:11) = '-'//CDate(1:4) + + + RETURN + END FUNCTION CurDate +!======================================================================= +!> This function returns a character string encoded with the time in the form "hh:mm:ss". + FUNCTION CurTime( ) + + ! Function declaration. + + CHARACTER(8) :: CurTime !< The current time in the form "hh:mm:ss". + + + ! Local declarations. + + CHARACTER(10) :: CTime ! String to hold the returned value from the DATE_AND_TIME subroutine call. + + + + CALL DATE_AND_TIME ( TIME=CTime ) + + CurTime = CTime(1:2)//':'//CTime(3:4)//':'//CTime(5:6) + + + RETURN + END FUNCTION CurTime +!======================================================================= +!> This routine displays some text about copyright and license. + SUBROUTINE DispCopyrightLicense( ProgramName, AdditionalComment ) + + CHARACTER(*), INTENT(IN) :: ProgramName !< The name of the program being run + CHARACTER(*), INTENT(IN), OPTIONAL :: AdditionalComment !< An additional comment displayed in the copyright notice. Typically used to describe alpha versions or one-off versions. + + ! local variable + INTEGER(IntKi) :: I ! generic loop/index + CHARACTER(4) :: Year ! the year, determined from the FPP __DATE__ variable + CHARACTER(MaxWrScrLen) :: Stars ! a line of '*******' characters + + DO I=1,MaxWrScrLen + Stars(I:I)='*' + END DO + + Year = __DATE__(8:11) + + CALL WrScr('') + CALL WrScr(Stars) + CALL WrScr( TRIM(ProgramName) ) + CALL WrScr('') + CALL WrScr( 'Copyright (C) '//TRIM(Year)//' National Renewable Energy Laboratory' ) + CALL WrScr( 'Copyright (C) '//TRIM(Year)//' Envision Energy USA LTD' ) + CALL WrScr('') + IF (PRESENT(AdditionalComment)) THEN + CALL WrScr( AdditionalComment ) + CALL WrScr('') + END IF + CALL WrScr( 'This program is licensed under Apache License Version 2.0 and comes with ABSOLUTELY NO WARRANTY. '//& + 'See the "LICENSE" file distributed with this software for details.') + CALL WrScr(Stars) + CALL WrScr('') + + + END SUBROUTINE DispCopyrightLicense +!======================================================================= +!> This routine packs the DLL_Type (nwtc_base::dll_type) data into an integer buffer. +!! It is required for the FAST Registry. It is the inverse of DLLTypeUnPack (nwtc_io::dlltypeunpack). + SUBROUTINE DLLTypePack( InData, ReKiBuf, DbKiBuf, IntKiBuf, ErrStat, ErrMsg, SizeOnly ) + + + TYPE(DLL_Type), INTENT(IN ) :: InData !< DLL data to pack (store in arrays of type ReKi, DbKi, and/or IntKi) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) !< buffer with real (ReKi) data from InData structure + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) !< buffer with double (DbKi) data from InData structure + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) !< buffer with integer (IntKi) data from InData structure + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message + LOGICAL, OPTIONAL, INTENT(IN ) :: SizeOnly !< flag to determine if we're just looking for the size of the buffers instead of the packed data + + ! Local variable + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: i,buf_start + + ErrStat = ErrID_None + ErrMsg = "" + + ! get size of buffer: + Int_BufSz = LEN(InData%FileName) + LEN(InData%ProcName(1))*NWTC_MAX_DLL_PROC + 1 + + ALLOCATE( IntKiBuf(Int_BufSz), STAT=ErrStat ) + IF (ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' DLLTypePack: Error allocating IntKiBuf.' + RETURN + END IF + + IF ( PRESENT(SizeOnly) ) THEN + IF ( SizeOnly ) RETURN + ENDIF + + !.............. + ! Fill buffer + !.............. + + ! has the DLL procedure been loaded? + IF ( C_ASSOCIATED(InData%ProcAddr(1))) THEN + IntKiBuf(1) = 1 + ELSE + IntKiBuf(1) = 0 + END IF + + ! Put an ascii representation of the strings in the integer array + CALL Str2IntAry( InData%FileName, IntKiBuf(2:), ErrStat, ErrMsg ) + buf_start=LEN(InData%FileName)+2 + DO i=1,NWTC_MAX_DLL_PROC + CALL Str2IntAry( InData%ProcName(i), IntKiBuf(buf_start:), ErrStat, ErrMsg ) + buf_start = buf_start + LEN(InData%ProcName(i)) + END DO + + + END SUBROUTINE DLLTypePack +!======================================================================= +!> This routine unpacks the DLL_Type data from an integer buffer. +!! It is required for the FAST Registry. It is the inverse of DLLTypePack (nwtc_io::dlltypepack). + SUBROUTINE DLLTypeUnPack( OutData, ReKiBuf, DbKiBuf, IntKiBuf, ErrStat, ErrMsg ) + + + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) !< buffer with real (ReKi) data to place in the OutData structure + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) !< buffer with real (DbKi) data to place in the OutData structure + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) !< buffer with integer (IntKi) data to place in the OutData structure + TYPE(DLL_Type), INTENT( OUT) :: OutData !< the reconstituted OutData structure, created from 3 buffers + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status/level + CHARACTER(*), INTENT( OUT) :: ErrMsg !< message corresponding to ErrStat + + ! Local variable + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: i, Int_BufEnd + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. ALLOCATED(IntKiBuf) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' DLLTypeUnPack: invalid buffer.' + END IF + + ! Get an ascii representation of the strings from the integer array + Int_BufSz = LEN(OutData%FileName) + 1 + CALL IntAry2Str( IntKiBuf(2:(Int_BufSz)), OutData%FileName, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + Int_BufSz = Int_BufSz + 1 + do i=1,NWTC_MAX_DLL_PROC + Int_BufEnd=Int_BufSz+LEN(OutData%ProcName(i))-1 + CALL IntAry2Str( IntKiBuf(Int_BufSz:Int_BufEnd), OutData%ProcName(i), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + Int_BufSz = Int_BufSz+LEN(OutData%ProcName(i)) + end do + + + IF ( IntKiBuf(1) == 1 .AND. LEN_TRIM(OutData%FileName) > 0 .AND. LEN_TRIM(OutData%ProcName(1)) > 0 ) THEN + CALL LoadDynamicLib( OutData, ErrStat, ErrMsg ) + END IF + + END SUBROUTINE DLLTypeUnPack +!======================================================================= +!> + SUBROUTINE DispCompileRuntimeInfo() +#ifdef HAS_FORTRAN2008_FEATURES + USE iso_fortran_env, ONLY: compiler_version +#endif + CHARACTER(200) :: compiler_version_str + CHARACTER(200) :: name + CHARACTER(200) :: git_commit, architecture, compiled_precision + CHARACTER(200) :: execution_date, execution_time, execution_zone + + name = ProgName + git_commit = QueryGitVersion() + architecture = TRIM(Num2LStr(BITS_IN_ADDR))//' bit' + IF (ReKi == SiKi) THEN + compiled_precision = 'single' + ELSE IF (ReKi == R8Ki) THEN + compiled_precision = 'double' + ELSE + compiled_precision = 'unknown' + END IF + +#if defined(HAS_FORTRAN2008_FEATURES) + compiler_version_str = compiler_version() +#elif defined(__INTEL_COMPILER) + compiler_version_str = 'Intel(R) Fortran Compiler '//num2lstr(__INTEL_COMPILER) +#else + compiler_version_str = OS_Desc +#endif + + CALL WrScr(trim(name)//'-'//trim(git_commit)) + CALL WrScr('Compile Info:') + call wrscr(' - Compiler: '//trim(compiler_version_str)) + CALL WrScr(' - Architecture: '//trim(architecture)) + CALL WrScr(' - Precision: '//trim(compiled_precision)) + CALL WrScr(' - Date: '//__DATE__) + CALL WrScr(' - Time: '//__TIME__) + ! call wrscr(' - Options: '//trim(compiler_options())) + + CALL DATE_AND_TIME(execution_date, execution_time, execution_zone) + + CALL WrScr('Execution Info:') + CALL WrScr(' - Date: '//TRIM(execution_date(5:6)//'/'//execution_date(7:8)//'/'//execution_date(1:4))) + CALL WrScr(' - Time: '//TRIM(execution_time(1:2)//':'//execution_time(3:4)//':'//execution_time(5:6))//TRIM(execution_zone)) + CALL WrScr('') + + END SUBROUTINE +!======================================================================= +!> This routine displays the name of the program, its version, and its release date. +!! Use DispNVD (nwtc_io::dispnvd) instead of directly calling a specific routine in the generic interface. + SUBROUTINE DispNVD0() + + ! Print out program name, version, and date. + CALL WrScr ( NewLine//' Running '//TRIM( ProgName )//' '//Trim( ProgVer )//'.' ) + + RETURN + END SUBROUTINE DispNVD0 + +!======================================================================= +!> \copydoc nwtc_io::dispnvd0 + SUBROUTINE DispNVD1 ( ProgInfo, DispNWTCVer ) + + IMPLICIT NONE + + TYPE( ProgDesc ), INTENT(IN) :: ProgInfo !< Contains the name and version info + LOGICAL,INTENT(IN),OPTIONAL :: DispNWTCVer !< Option to display what version of the library is linked with the code + + ! Print out program name, version, and date. + + ! As a special case, display the library version with the program version + IF ( PRESENT(DispNWTCVer) ) THEN + IF ( DispNWTCVer .AND. ProgInfo%Name /= NWTC_Ver%Name ) THEN + CALL WrScr ( NewLine//' Running '//TRIM( GetNVD( ProgInfo ) )//' linked with '//TRIM( GetNVD( NWTC_Ver ) )//'.' ) + RETURN + END IF + END IF + + CALL WrScr ( 'Running '//TRIM( GetNVD( ProgInfo ) )//'.' ) + + RETURN + END SUBROUTINE DispNVD1 + +!======================================================================= +!> This routine displays the name of the program, its version, and its release date passed in as strings +!! This routine is depricated and for legacy purposes only. Please don't use for any new code (Dec-2012). + SUBROUTINE DispNVD2 ( Name, Ver ) + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Name !< String containing the name of the program using the library + CHARACTER(*), INTENT(IN) :: Ver !< String containing the version and date info + + ! Print out program name, version, and date. + CALL WrScr ( NewLine//' Running '//TRIM( Name )//' ('//Trim( Ver )//').' ) + + RETURN + END SUBROUTINE DispNVD2 + +!======================================================================= +!> This routine finds one line of text with a maximum length of MaxLen from the Str. +!! It tries to break the line at a blank. + SUBROUTINE FindLine ( Str , MaxLen , StrEnd ) + + IMPLICIT NONE + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: MaxLen !< The maximum length of the string. + INTEGER, INTENT(OUT) :: StrEnd !< The location of the end of the string. + + CHARACTER(*), INTENT(IN) :: Str !< The string to search. + + + ! Local declarations: + + INTEGER IC + + + + StrEnd = MaxLen + + IF ( LEN_TRIM( Str ) > MaxLen ) THEN + + IC = INDEX( Str(1:MaxLen), ' ', BACK = .TRUE. ) ! Find the last space in the line + + IF ( IC > 1 ) THEN ! We don't want to return just one character that's a space, or do we? + + StrEnd = IC-1 ! StrEnd > 0 + DO WHILE ( Str(StrEnd:StrEnd) == ' ' ) + StrEnd = StrEnd - 1 + IF ( StrEnd <= 0 ) THEN ! This occurs if everything before IC is a space + StrEnd = IC + EXIT + ENDIF + ENDDO + + ENDIF ! IC > 1 + + ENDIF ! LEN_TRIM( Str ) > MaxLen + + + RETURN + END SUBROUTINE FindLine +!======================================================================= +!> This routine returns the next unit number greater than 9 that is not currently in use. +!! If it cannot find any unit between 10 and 99 that is available, it either aborts or returns an appropriate error status/message. + SUBROUTINE GetNewUnit ( UnIn, ErrStat, ErrMsg ) + + + + ! Argument declarations. + + INTEGER, INTENT(OUT) :: UnIn !< Logical unit for the file. + INTEGER(IntKi), INTENT(OUT), OPTIONAL :: ErrStat !< The error status code; If not present code aborts + CHARACTER(*), INTENT(OUT), OPTIONAL :: ErrMsg !< The error message, if an error occurred + + + ! Local declarations. + + INTEGER :: Un ! Unit number + LOGICAL :: Opened ! Flag indicating whether or not a file is opened. + INTEGER(IntKi), PARAMETER :: StartUnit = 10 ! Starting unit number to check (numbers less than 10 reserved) + INTEGER(IntKi), PARAMETER :: MaxUnit = 99 ! The maximum unit number available (or 10 less than the number of files you want to have open at a time) + CHARACTER(ErrMsgLen) :: Msg ! Temporary error message + + + ! Initialize subroutine outputs + + Un = StartUnit + + IF ( PRESENT( ErrStat ) ) ErrStat = ErrID_None + IF ( PRESENT( ErrMsg ) ) ErrMsg = '' + + ! See if unit is connected to an open file. Check the next largest number until it is not opened. + + DO + + INQUIRE ( UNIT=Un , OPENED=Opened ) + + IF ( .NOT. Opened ) EXIT + Un = Un + 1 + + IF ( Un > MaxUnit ) THEN + + Msg = 'GetNewUnit() was unable to find an open file unit specifier between '//TRIM(Num2LStr(StartUnit)) & + //' and '//TRIM(Num2LStr(MaxUnit))//'.' + + IF ( PRESENT( ErrStat ) ) THEN + ErrStat = ErrID_Severe + IF ( PRESENT( ErrMsg) ) ErrMsg = Msg + ELSE + CALL ProgAbort( Msg ) + END IF + + EXIT ! stop searching now + + END IF + + + END DO + + UnIn = Un + + RETURN + END SUBROUTINE GetNewUnit +!======================================================================= +!> This function returns a text description of the ErrID (ErrStat) code. + FUNCTION GetErrStr ( ErrID ) + + ! This function returns a description of the ErrID code + + ! Argument declarations. + INTEGER(IntKi), INTENT(IN) :: ErrID !< error status/level + + ! Function delcaration + CHARACTER(13) :: GetErrStr !< description of the ErrID level + + SELECT CASE ( ErrID ) + CASE ( ErrID_None ) + GetErrStr = '' + CASE ( ErrID_Info ) + GetErrStr = 'INFORMATION' + CASE ( ErrID_Warn ) + GetErrStr = 'WARNING' + CASE ( ErrID_Severe ) + GetErrStr = 'SEVERE ERROR' + CASE ( ErrID_Fatal ) + GetErrStr = 'FATAL ERROR' + CASE DEFAULT + GetErrStr = 'Unknown ErrID' + END SELECT + + + END FUNCTION GetErrStr + +!======================================================================= +!> This function extracts the Name field from the ProgDesc data type +! and return it. + FUNCTION GetNVD ( ProgInfo ) + + ! Argument declarations. + TYPE( ProgDesc ), INTENT(IN) :: ProgInfo !< Contains the name, date, and version info + + ! Function delcaration + CHARACTER(200) :: GetNVD !< A single string containing the name, date, and version info + + ! Store all the version info into a single string: + if (len_trim(ProgInfo%Ver) > 0) then + GetNVD = TRIM( ProgInfo%Name )//' ('//Trim( ProgInfo%Ver )//', '//Trim( ProgInfo%Date )//')' + else + GetNVD = TRIM( ProgInfo%Name ) + end if + + END FUNCTION GetNVD +!======================================================================= +!> Let's parse the path name from the name of the given file. +!! We'll count everything before (and including) the last "\" or "/". + SUBROUTINE GetPath ( GivenFil, PathName, FileName ) + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: GivenFil !< The name of the given file. + CHARACTER(*), INTENT(OUT) :: PathName !< The path name of the given file (based solely on the GivenFil text string). + CHARACTER(*), INTENT(OUT), OPTIONAL :: FileName !< The name of the given file without the PathName (based solely on the GivenFil text string). + + + ! Local declarations. + + INTEGER :: I ! DO index for character position. + + + ! Look for path separators + + I = INDEX( GivenFil, '\', BACK=.TRUE. ) + I = MAX( I, INDEX( GivenFil, '/', BACK=.TRUE. ) ) + + IF ( I == 0 ) THEN + ! we don't have a path specified, return '.' + PathName = '.'//PathSep + IF (PRESENT(FileName)) FileName = GivenFil + ELSE + PathName = GivenFil(:I) + IF (PRESENT(FileName)) THEN + IF ( LEN_TRIM(GivenFil) > I ) THEN + FileName = GivenFil(I+1:) + ELSE + FileName = "" + END IF + END IF + END IF + + + RETURN + END SUBROUTINE GetPath +!======================================================================= +!> Let's parse the root file name from the name of the given file. +!! We'll count everything after the last period as the extension. + SUBROUTINE GetRoot ( GivenFil, RootName ) + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: GivenFil !< The name of the given file. + CHARACTER(*), INTENT(OUT) :: RootName !< The parsed root name of the given file. + + + ! Local declarations. + + INTEGER :: I ! DO index for character position. + + + + ! Deal with a couple of special cases. + + IF ( ( TRIM( GivenFil ) == "." ) .OR. ( TRIM( GivenFil ) == ".." ) ) THEN + RootName = TRIM( GivenFil ) + RETURN + END IF + + + ! More-normal cases. + + DO I=LEN_TRIM( GivenFil ),1,-1 + + + IF ( GivenFil(I:I) == '.' ) THEN + + + IF ( I < LEN_TRIM( GivenFil ) ) THEN ! Make sure the index I is okay + IF ( INDEX( '\/', GivenFil(I+1:I+1)) == 0 ) THEN ! Make sure we don't have the RootName in a different directory + RootName = GivenFil(:I-1) + ELSE + RootName = GivenFil ! This does not have a file extension + END IF + ELSE + IF ( I == 1 ) THEN + RootName = '' + ELSE + RootName = GivenFil(:I-1) + END IF + END IF + + RETURN + + END IF + END DO ! I + + RootName = GivenFil + + + RETURN + END SUBROUTINE GetRoot +!======================================================================= +!> This routine will parse Line for NumTok "tokens" and return them in the Tokens array. +!! This routine differs from GetWords() (nwtc_io::getwords) in that it uses only spaces as token separators. + SUBROUTINE GetTokens ( Line, NumTok, Tokens, Error ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: NumTok !< The number of "words" to look for. + + LOGICAL, INTENT(OUT) :: Error !< Error flag to indicate an insuffient number of tokens were found. + + CHARACTER(*), INTENT(INOUT) :: Line !< The string to search. + CHARACTER(*), INTENT(OUT) :: Tokens (:) !< The tokens that were found. + + + ! Local declarations. + + INTEGER :: IT ! Token index + INTEGER :: NextBlank ! The location of the next blank character + + + + NextBlank = 0 + + DO IT=1,NumTok + + Line = ADJUSTL( Line(NextBlank+1:) ) + NextBlank = INDEX ( Line , ' ' ) + + IF ( NextBlank == 0 .OR. IT > SIZE(Tokens) ) THEN + Error = .TRUE. + RETURN + END IF + + Tokens(IT) = Line(1:NextBlank-1) + + END DO ! IT + + Error = .FALSE. + + + RETURN + END SUBROUTINE GetTokens +!======================================================================= +!> This subroutine is used to get the NumWords "words" from a line of text. +!! It uses spaces, tabs, commas, semicolons, single quotes, and double quotes ("whitespace") +!! as word separators. If there aren't NumWords in the line, the remaining array elements will remain empty. +!! Use CountWords (nwtc_io::countwords) to count the number of words in a line. + SUBROUTINE GetWords ( Line, Words, NumWords ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: NumWords !< The number of words to look for. + + CHARACTER(*), INTENT(IN) :: Line !< The string to search. + CHARACTER(*), INTENT(OUT) :: Words(NumWords) !< The array of found words. + + + ! Local declarations. + + INTEGER :: Ch ! Character position within the string. + INTEGER :: IW ! Word index. + INTEGER :: NextWhite ! The location of the next whitespace in the string. + + + + ! Let's prefill the array with blanks. + + DO IW=1,NumWords + Words(IW) = ' ' + END DO ! IW + + + ! Let's make sure we have text on this line. + + IF ( LEN_TRIM( Line ) == 0 ) RETURN + + + ! Parse words separated by any combination of spaces, tabs, commas, + ! semicolons, single quotes, and double quotes ("whitespace"). + + Ch = 0 + IW = 0 + + DO + + NextWhite = SCAN( Line(Ch+1:) , ' ,;''"'//Tab ) + + IF ( NextWhite > 1 ) THEN + + IW = IW + 1 + Words(IW) = Line(Ch+1:Ch+NextWhite-1) + if (NextWhite > len(words(iw)) ) then + call ProgWarn('Error reading field from file. There are too many characters in the input file to store in the field. Value may be truncated.') + end if + + IF ( IW == NumWords ) EXIT + + Ch = Ch + NextWhite + + ELSE IF ( NextWhite == 1 ) THEN + + Ch = Ch + 1 + + CYCLE + + ELSE + + EXIT + + END IF + + END DO + + + RETURN + END SUBROUTINE GetWords +!======================================================================= +!> This routine converts an ASCII array of integers into an equivalent string +!! (character array). This routine is the inverse of the Str2IntAry() (nwtc_io::str2intary) routine. + SUBROUTINE IntAry2Str( IntAry, Str, ErrStat, ErrMsg ) + + ! Argument declarations: + INTEGER(IntKi), INTENT(IN) :: IntAry(:) !< ASCII array to convert to a string + CHARACTER(*), INTENT(OUT) :: Str !< The string representation of IntAry + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with ErrStat + + ! Argument declarations: + INTEGER(IntKi) :: I ! generic loop counter + INTEGER(IntKi) :: LStr ! length of the string + INTEGER(IntKi) :: LAry ! length of the integer array + + + ! Get the size of the arrays: + LStr = LEN(Str) + LAry = SIZE(IntAry) + + + Str = '' + + ! Determine if the string will fit in the integer array: + IF ( LAry > LStr ) THEN + ErrStat = ErrID_Warn + ErrMsg = 'Int2Char:Array exceeds string size.' + LAry = LStr ! we'll only convert the string values up to the array length + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + ! Convert the ASCII array to a string: + DO I=1,LAry + Str(I:I) = CHAR(IntAry(I)) + END DO + + END SUBROUTINE IntAry2Str +!======================================================================= +!> This function returns a left-adjusted string representing the passed numeric value. +!! It eliminates trailing zeroes and even the decimal point if it is not a fraction. \n +!! Use Num2LStr (nwtc_io::num2lstr) instead of directly calling a specific routine in the generic interface. + FUNCTION Int2LStr ( Num ) + + CHARACTER(11) :: Int2LStr !< string representing input number. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Num !< The number to convert to a left-justified string. + + + + WRITE (Int2LStr,'(I11)') Num + + Int2Lstr = ADJUSTL( Int2LStr ) + + + RETURN + END FUNCTION Int2LStr +!======================================================================= +!> This function returns true if and only if the first character of the input StringToCheck matches on the of comment characters +!! nwtc_io::commchars. + FUNCTION IsComment(StringToCheck) + ! Note: only the first character in the word is checked. Otherwise we would falsely grab the units '(%)' + LOGICAL :: IsComment + CHARACTER(*), INTENT(IN ) :: StringToCheck ! String to check + + + if ( LEN_TRIM(StringToCheck) > 0 ) then + ISComment = INDEX( CommChars, StringToCheck(1:1) ) > 0 + else + IsComment = .FALSE. + end if + + END FUNCTION IsComment +!======================================================================= +!> This routine gets the name of the input file from the InArgth command-line argument, +!! removes the extension if there is one, and appends OutExten to the end. + SUBROUTINE NameOFile ( InArg, OutExten, OutFile, ErrStat, ErrMsg ) + + + ! Argument declarations. + + INTEGER, INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + INTEGER, INTENT(IN) :: InArg !< The number of the command-line argument that should hold the input file name. + + CHARACTER(*), INTENT(IN) :: OutExten !< The requested extension for the output file. + CHARACTER(*), INTENT(OUT) :: OutFile !< The name of the output file. + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Description of error + + + ! Local declarations. + + CHARACTER(100) :: InFile ! The name of the input file. + CHARACTER(100) :: RootName ! The root name of the input file. + + + + ! See if the command line has enough arguments. + + IF ( InArg > COMMAND_ARGUMENT_COUNT() ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'NameOFile:Insufficient arguments on the command line (at least '//& + TRIM( Int2LStr( InArg ) )//' were expected).' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + ! Get the root of the input file name (strip off the extension). + + CALL GET_COMMAND_ARGUMENT( InArg, InFile ) + CALL GetRoot ( TRIM( InFile ), RootName ) + + OutFile = TRIM( RootName )//'.'//OutExten + + + RETURN + END SUBROUTINE NameOFile +!======================================================================= +!> This routine performs a normal termination of the program. + SUBROUTINE NormStop() + + IF ( LEN_TRIM(ProgName) > 0 ) THEN + CALL WrScr ( NewLine//' '//TRIM( ProgName )//' terminated normally.' ) + ELSE + CALL WrScr ( NewLine//' Program terminated normally.' ) + END IF + CALL WrScr ( '' ) + CALL ProgExit ( 0 ) + + + END SUBROUTINE NormStop +!======================================================================= +!> This routine displays the expected command-line syntax for +!! most software developed at the NWTC. + SUBROUTINE NWTC_DisplaySyntax( DefaultInputFile, ThisProgName ) + + CHARACTER(*), INTENT(IN) :: DefaultInputFile !< the default name of the input file, if any + CHARACTER(*), INTENT(IN) :: ThisProgName !< the name of the executable to be displayed in the calling syntax + + + CALL WrScr ( NewLine//' Syntax is:' ) + IF ( LEN_TRIM( DefaultInputFile ) == 0 ) THEN + CALL WrScr ( NewLine//' '//TRIM( ThisProgName )//' ['//SwChar//'h] <InputFile>' ) + CALL WrScr ( NewLine//' where:' ) + CALL WrScr ( NewLine//' '//SwChar//'h generates this help message.' ) + CALL WrScr ( ' <InputFile> is the name of the required primary input file.' ) + ELSE + CALL WrScr ( NewLine//' '//TRIM( ThisProgName )//' ['//SwChar//'h] [<InputFile>]' ) + CALL WrScr ( NewLine//' where:' ) + CALL WrScr ( NewLine//' '//SwChar//'h generates this help message.' ) + CALL WrScr ( ' <InputFile> is the name of the primary input file. If omitted, the default file is "' & + //TRIM( DefaultInputFile )//'".' ) + END IF + CALL WrScr ( NewLine//' Note: values enclosed in square brackets [] are optional. Do not enter the brackets.') + CALL WrScr ( ' ') + + END SUBROUTINE NWTC_DisplaySyntax +!======================================================================= +!> This routine opens a binary input file. + SUBROUTINE OpenBInpFile ( Un, InFile, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: Un !< Logical unit for the input file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status: returns "fatal" if the file doesn't exist or can't be opened + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file. + + + ! Local declarations. + + ! NOTE: Do not explicitly declare the precision of this variable [as in + ! LOGICAL(1)] so that the statements using this variable work with + ! any compiler: + LOGICAL :: Exists ! Flag indicating whether or not a file Exists. + + + ErrStat = ErrID_None + ErrMsg = '' + + + ! See if input file Exists. + + INQUIRE ( FILE=TRIM( InFile ) , EXIST=Exists ) + + IF ( .NOT. Exists ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenBInpFile:The input file, "'//TRIM( InFile )//'", was not found.' + RETURN + END IF + + + ! Open input file. Make sure it worked. + OPEN( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='STREAM', IOSTAT=ErrStat, ACTION='READ' ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenBInpFile:Cannot open file "'//TRIM( InFile )//'" for reading. Another program may have locked it.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE OpenBInpFile +!======================================================================= +!> This routine opens a binary output file with stream access, +!! implemented in standrad Fortran 2003. +!! Valid in gfortran 4.6.1 and IVF 10.1 and later + SUBROUTINE OpenBOutFile ( Un, OutFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: Un !< Logical unit for the output file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: OutFile !< Name of the output file + + + + ! Open output file. Make sure it worked. + OPEN( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM='UNFORMATTED' , ACCESS='STREAM', IOSTAT=ErrStat, ACTION='WRITE' ) + + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenBOutFile:Cannot open file "'//TRIM( OutFile )//'". Another program may have locked it for writing.' & + //' (IOSTAT is '//TRIM(Num2LStr(ErrStat))//')' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + + RETURN + END SUBROUTINE OpenBOutFile +!======================================================================= +!> This routine opens a formatted output file for the echo file. + SUBROUTINE OpenEcho ( Un, OutFile, ErrStat, ErrMsg, ProgVer ) + + ! Argument declarations. + + INTEGER, INTENT(INOUT) :: Un !< Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: OutFile !< Name of the input file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + TYPE(ProgDesc), INTENT(IN), OPTIONAL :: ProgVer !< Program version info to display in echo file + + + ! local variables + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(*),PARAMETER :: RoutineName = 'OpenEcho' + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Get a unit number for the echo file: + + IF ( Un < 0 ) THEN + CALL GetNewUnit( Un, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat, ErrMsg, RoutineName ) + END IF + + + ! Open the file for writing: + + CALL OpenFOutFile( Un, OutFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Write a heading line to the file + + IF ( PRESENT( ProgVer ) ) THEN + + WRITE (Un,'(/,A)', IOSTAT=ErrStat2 ) 'This file of echoed input was generated by '//TRIM(GetNVD(ProgVer))// & + ' on '//CurDate()//' at '//CurTime()//'.' + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat(ErrID_Info, 'Could not write header information to the file.', ErrStat, ErrMsg, RoutineName ) + END IF + + END IF + + + RETURN + END SUBROUTINE OpenEcho +!======================================================================= +!> This routine opens a formatted input file. + SUBROUTINE OpenFInpFile ( Un, InFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + LOGICAL :: Exists ! Flag indicating whether or not a file Exists. + CHARACTER(*), PARAMETER :: RoutineName = 'OpenFInpFile' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! See if input file Exists. + + INQUIRE ( FILE=TRIM( InFile ) , EXIST=Exists ) + + IF ( .NOT. Exists ) THEN + CALL SetErrStat( ErrID_Fatal, 'The input file, "'//TRIM( InFile )//'", was not found.', ErrStat, ErrMsg, RoutineName) + ELSE + + ! Open input file. Make sure it worked. + + OPEN( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='FORMATTED', IOSTAT=IOS, ACTION='READ' ) + + IF ( IOS /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Cannot open file "'//TRIM( InFile )//'".', ErrStat,ErrMsg,RoutineName) + END IF + + END IF + + + RETURN + END SUBROUTINE OpenFInpFile +!======================================================================= +!> This routine opens a formatted output file. + SUBROUTINE OpenFOutFile ( Un, OutFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the output file. + CHARACTER(*), INTENT(IN) :: OutFile !< Name of the output file. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN + CHARACTER(*), PARAMETER :: RoutineName = 'OpenFOutFile' + + + ! Open output file. Make sure it worked. + + OPEN( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + + + IF ( IOS /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenFOutFile:Cannot open file "'//TRIM( OutFile )//& + '". Another program like MS Excel may have locked it for writing.' + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + + + RETURN + END SUBROUTINE OpenFOutFile +!======================================================================= +!> This routine opens a formatted output file and returns a flag telling if it already existed. + SUBROUTINE OpenFUnkFile ( Un, OutFile, FailAbt, Failed, Exists, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the output file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status: returns "fatal" if the file doesn't exist or can't be opened + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + LOGICAL, INTENT(OUT) :: Exists !< Flag that indicates if the file already existedo. + LOGICAL, INTENT(IN) :: FailAbt !< Flag that tells this routine to abort if the open fails. + LOGICAL, INTENT(OUT) :: Failed !< Flag that indicates if the open failed. + + CHARACTER(*), INTENT(IN) :: OutFile !< Name of the output file. + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + + + ! Check to see if the file already exists. + + INQUIRE ( FILE=TRIM( OutFile ) , EXIST=Exists ) + + + ! Open output file. Make sure it worked. + + OPEN( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS ) + + + IF ( IOS /= 0 ) THEN + Failed = .TRUE. + ErrStat = ErrID_Fatal + ErrMsg = 'OpenFUnkFile:Cannot open file "'//TRIM( OutFile )//'". Another program like MS Excel may have locked it for writing.' + IF ( FailAbt ) CALL ProgAbort ( TRIM(ErrMsg) ) + ELSE + Failed = .FALSE. + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE OpenFUnkFile +!======================================================================= +!> This routine opens a formatted output file in append mode if it exists, otherwise opens a new file + SUBROUTINE OpenFUnkFileAppend ( Un, OutFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un ! Logical unit for the output file. + CHARACTER(*), INTENT(IN) :: OutFile ! Name of the output file. + + INTEGER(IntKi), INTENT(OUT), OPTIONAL :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT), OPTIONAL :: ErrMsg ! Error message + + + + ! Local declarations. + LOGICAL :: FileExists ! Does the file exist? + INTEGER :: IOS ! I/O status of OPEN + CHARACTER(1024) :: Msg ! Temporary error message + + + ! Open output file. Make sure it worked. + + inquire(file=TRIM( OutFile ), exist=FileExists) + + if (FileExists) then + OPEN( Un, FILE=TRIM( OutFile ), STATUS='OLD', POSITION='APPEND', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + else + OPEN( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + end if + + + IF ( IOS /= 0 ) THEN + + Msg = 'Cannot open file "'//TRIM( OutFile )//'". Another program like MS Excel may have locked it for writing.' + + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = Msg + ELSE + CALL ProgAbort( ' '//Msg ) + END IF + + ELSE + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + IF ( PRESENT(ErrMsg) ) ErrMsg = "" + END IF + + + RETURN + END SUBROUTINE OpenFUnkFileAppend ! ( Un, OutFile [, ErrStat] [, ErrMsg] ) +!======================================================================= +!> This routine opens an unformatted input file of RecLen-byte data records +!! stored in Big Endian format. + SUBROUTINE OpenUInBEFile( Un, InFile, RecLen, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the input file + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file + INTEGER, INTENT(IN) :: RecLen !< The input file's record length in bytes + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status: returns "fatal" if the file doesn't exist or can't be opened + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + LOGICAL :: Exists ! Flag to indicate if a file exists + LOGICAL :: Error ! Flag to indicate the open failed + + + + ! See if input file Exists. + + INQUIRE ( FILE=TRIM( InFile ) , EXIST=Exists ) + + IF ( .NOT. Exists ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenUInBEFile:The input file, "'//TRIM( InFile )//'", was not found.' + RETURN + END IF + + + ! Open the file. + + CALL OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + IF ( Error ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenUInBEFile:Cannot open file "'//TRIM( InFile )//'". Another program may have locked it.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + + END SUBROUTINE OpenUInBEFile +!======================================================================= +!> This routine opens an unformatted input file. + SUBROUTINE OpenUInfile ( Un, InFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status: returns "fatal" if the file doesn't exist or can't be opened + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file + + + ! Local declarations. + + INTEGER :: IOS ! Returned input/output status. + + LOGICAL :: Exists ! Flag indicating whether or not a file Exists. + + + + ! See if input file Exists. + + INQUIRE ( FILE=TRIM( InFile ) , EXIST=Exists ) + + IF ( .NOT. Exists ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenUInfile:The input file, "'//TRIM( InFile )//'", was not found.' + RETURN + END IF + + + ! Open the file. + + OPEN ( Un, FILE=TRIM( InFile ), STATUS='UNKNOWN', FORM=UnfForm, ACCESS='SEQUENTIAL', IOSTAT=IOS, ACTION='READ' ) + + IF ( IOS /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenUInfile:Cannot open file "'//TRIM( InFile )//'". Another program may have locked it.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE OpenUInfile +!======================================================================= +!> This routine opens an unformatted output file. + SUBROUTINE OpenUOutfile ( Un, OutFile, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un !< Logical unit for the output file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status: returns "fatal" if the file doesn't exist or can't be opened + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(IN) :: OutFile !< Name of the output file + + + ! Local declarations. + + INTEGER :: IOS ! Returned input/output status. + + + + ! Open the file. + + OPEN ( Un, FILE=TRIM( OutFile ), STATUS='UNKNOWN', FORM=UnfForm, ACCESS='SEQUENTIAL', IOSTAT=IOS, ACTION='WRITE' ) + + IF ( IOS /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'OpenUOutfile:Cannot open file "'//TRIM( OutFile )//'". Another program may have locked it for writing.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE OpenUOutfile +!======================================================================= +!> This subroutine prints the contents of the FileInfo data structure to the screen +!! This may be useful for diagnostic purposes. this is written to unit U + subroutine Print_FileInfo_Struct( U, FileInfo ) + integer(IntKi), intent(in ) :: U !< Unit number to print to + type(FileInfoType), intent(in ) :: FileInfo !< derived type containing everything read from file + integer(IntKi) :: i !< generic counter + character(20) :: TmpStr20 + character(45) :: TmpStr45 + write(U,*) '-------------- Print_FileInfo_Struct ------------' + write(U,*) ' info stored in the FileInfo data type' + write(U,*) ' %NumLines (integer): ',FileInfo%NumLines + write(U,*) ' %NumFiles (integer): ',FileInfo%NumFiles + write(U,*) ' %FileList (array of strings): ',size(FileInfo%FileList) + write(U,*) ' %FileIndx (array of integer): ',size(FileInfo%FileIndx) + write(U,*) ' %FileLine (array of integer): ',size(FileInfo%FileLine) + write(U,*) ' %Lines (array of strings): ',size(FileInfo%Lines ) + if (allocated(FileInfo%FileList)) then + write(U,*) ' list of files read:' + write(U,*) ' FileIdx FileName' + do i=1,FileInfo%NumFiles + write(TmpStr20,'(7x,I3,10x)') i + write(U,*) TmpStr20//trim(FileInfo%FileList(i)) + enddo + endif + if (allocated(FileInfo%FileLine) .and. allocated(FileInfo%FileIndx) .and. allocated(FileInfo%Lines)) then + write(U,*) ' Non-comment lines stored in memory from files:' + write(U,*) ' i FileIndx FileLine Lines(i)' + do i=1,FileInfo%NumLines + write(TmpStr45, '(5x,I5,10x,I5,10x,I5,5x)') i, FileInfo%FileIndx(i), FileInfo%FileLine(i) + write(U,*) TmpStr45, trim(FileInfo%Lines(i)) + enddo + endif + end subroutine Print_FileInfo_Struct +!======================================================================= +!> This subroutine parses the specified line of text for AryLen CHARACTER values. +!! Generate an error message if the value is the wrong type. +!! Use ParseAry (nwtc_io::parseary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ParseChAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + INTEGER, INTENT(IN) :: AryLen !< The length of the array to parse. + TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + INTEGER(IntKi), INTENT(INOUT) :: LineNum !< The number of the line to parse. + CHARACTER(*), INTENT(IN) :: AryName !< The array name we are trying to fill. + CHARACTER(*), INTENT(OUT) :: Ary(AryLen) !< The array to receive the input values. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc. + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: i ! Error status local to this routine. + + CHARACTER(*), PARAMETER :: RoutineName = 'ParseChAry' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + READ (FileInfo%Lines(LineNum),*,IOSTAT=ErrStatLcl) Ary + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned valid REAL values on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(A)') TRIM( FileInfo%Lines(LineNum) ) + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseChAry +!======================================================================= +!> This subroutine parses the specified line of text for two words. One should be a +!! the name of a variable and the other the value of the variable. +!! Generate an error message if the value is the wrong type or if only one "word" is found. +!! +!! WARNING: This routine assumes the "words" containing the variable name and value are <= 20 characters. \n +!! Use ParseVar (nwtc_io::parsevar) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum !< The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: Var !< The variable to receive the input value. + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName !< The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + + CHARACTER(200) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseChVar' + + + ErrStat=ErrID_None + ErrMsg = "" + + !' >> The text being parsed was :'//NewLine//' "'//TRIM( FileInfo%Lines(LineNum) )//' + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( ExpVarName )//'" variable was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + IF ( Words(2) == '' .and. (LEN_TRIM(ExpVarName) > 0) ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The variable "'//TRIM( ExpVarName )//'" was not assigned valid string value on line #' & + //TRIM( Num2LStr( LineNum ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + CALL ChkParseData ( Words, ExpVarName, FileInfo%FileList(FileInfo%FileIndx(LineNum)) & + , FileInfo%FileLine(LineNum), NameIndx, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + Var = Words(3-NameIndx) + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(1X,A15," = ",A20)') Words + END IF + + LineNum = LineNum + 1 + + RETURN + END SUBROUTINE ParseChVar +!======================================================================= +!> This subroutine parses the specified line of text for two words. One should be a +!! the name of a variable and the other a value for the variable. If the variable is the +!! character string "DEFAULT", a default value will be used to set the variable. +!! Generate an error message if the value is the wrong type or if only one "word" is found. +!! +!! WARNING: This routine assumes the "words" containing the variable name and value are <= 20 characters. +!! Use ParseVarWDefault (nwtc_io::parsevarwdefault) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ParseChVarWDefault ( FileInfo, LineNum, ExpVarName, Var, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum !< The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: Var !< The variable to receive the input value. + CHARACTER(*), INTENT(IN) :: VarDefault !< The default value for the variable. + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName !< The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseChVarDefault' + CHARACTER(20) :: defaultStr + + ErrStat=ErrID_None + ErrMsg = "" + + ! First parse this as a string + CALL ParseVar ( FileInfo, LineNum, ExpVarName, defaultStr, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + CALL Conv2UC( defaultStr ) + IF ( INDEX(defaultStr, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable + Var = defaultStr + ELSE + Var = VarDefault ! "DEFAULT" value + END IF + + RETURN + END SUBROUTINE ParseChVarWDefault +!======================================================================= +!> This subroutine parses the specified line of text for AryLen REAL values. +!! Generate an error message if the value is the wrong type. +!! Use ParseAry (nwtc_io::parseary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ParseDbAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + INTEGER, INTENT(IN) :: AryLen !< The length of the array to parse. + + REAL(DbKi), INTENT(OUT) :: Ary (AryLen) !< The array to receive the input values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum !< The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(In) :: AryName !< The array name we are trying to fill. + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: i ! Error status local to this routine. + + CHARACTER(*), PARAMETER :: RoutineName = 'ParseDbAry' + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + READ (FileInfo%Lines(LineNum),*,IOSTAT=ErrStatLcl) Ary + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned valid REAL values on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + DO i=1,AryLen + call CheckRealVar( Ary(i), AryName, ErrStat, ErrMsg ) + if (ErrStat>= AbortErrLev) return + END DO + + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(A)') TRIM( FileInfo%Lines(LineNum) ) + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseDbAry +!======================================================================= +!> \copydoc nwtc_io::parsechvar + SUBROUTINE ParseDbVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + REAL(DbKi), INTENT(OUT) :: Var ! The double-precision REAL variable to receive the input value. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + + CHARACTER(NWTC_SizeOfNumWord) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseDbVar' + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( ExpVarName )//'" variable was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + + CALL ChkParseData ( Words, ExpVarName, FileInfo%FileList(FileInfo%FileIndx(LineNum)) & + , FileInfo%FileLine(LineNum), NameIndx, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + READ (Words(3-NameIndx),*,IOSTAT=ErrStatLcl) Var + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The variable "'//TRIM( Words(NameIndx) )//'" was not assigned valid REAL value on line #' & + //TRIM( Num2LStr( LineNum ) )//'.'//NewLine//' >> The text being parsed was :'//& + NewLine//' "'//TRIM( FileInfo%Lines(LineNum) )//'"', ErrStat, ErrMsg, RoutineName) + RETURN + ENDIF + CALL CheckRealVar( Var, ExpVarName, ErrStatLcl, ErrMsg2) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(1X,A15," = ",A20)') Words + END IF + + LineNum = LineNum + 1 + + RETURN + END SUBROUTINE ParseDbVar +!======================================================================= +!> \copydoc nwtc_io::parsechvarwdefault + SUBROUTINE ParseDbVarWDefault ( FileInfo, LineNum, ExpVarName, Var, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + REAL(DbKi), INTENT(OUT) :: Var ! The double-precision REAL variable to receive the input value. + REAL(DbKi), INTENT(IN) :: VarDefault ! The double-precision REAL used as the default. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseDbVarDefault' + CHARACTER(20) :: defaultStr + + ErrStat=ErrID_None + ErrMsg = "" + + ! First parse this as a string + CALL ParseVar ( FileInfo, LineNum, ExpVarName, defaultStr, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + CALL Conv2UC( defaultStr ) + IF ( INDEX(defaultStr, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable + LineNum = LineNum - 1 ! back up a line + CALL ParseVar ( FileInfo, LineNum, ExpVarName, Var, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE + Var = VarDefault ! "DEFAULT" value + END IF + + RETURN + END SUBROUTINE ParseDbVarWDefault +!======================================================================= +!> \copydoc nwtc_io::parsedbary + SUBROUTINE ParseInAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + INTEGER, INTENT(IN) :: AryLen ! The length of the array to parse. + + INTEGER, INTENT(OUT) :: Ary (AryLen) ! The INTEGER array to receive the input values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(In) :: AryName ! The array name we are trying to fill. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(*), PARAMETER :: RoutineName = 'ParseInAry' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + READ (FileInfo%Lines(LineNum),*,IOSTAT=ErrStatLcl) Ary + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned valid INTEGER values on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(A)') TRIM( FileInfo%Lines(LineNum) ) + END IF + + LineNum = LineNum + 1 + + + RETURN + + + END SUBROUTINE ParseInAry +!======================================================================= +!> This subroutine parses the include information that occurs after a "@" when processing an input file. + SUBROUTINE ParseInclInfo ( InclInfo, RelativePathFileName, FileName, RangeBeg, RangeEnd, ErrStat, ErrMsg ) + + ! Arguments declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. + + INTEGER, INTENT(OUT) :: RangeBeg !< The beginning of a range of lines to be processed in an included file. + INTEGER, INTENT(OUT) :: RangeEnd !< The end of a range of lines to be processed in an included file. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(OUT) :: FileName !< The file name that was parsed from InclInfo. + CHARACTER(*), INTENT(INOUT) :: InclInfo !< The text following the "@" on an input line being processed. + CHARACTER(*), INTENT(IN) :: RelativePathFileName !< The name of the file that any new file is relative to. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + INTEGER :: DashLoc ! The possible location of the dash in the range text. + + CHARACTER( 20) :: InclInfoUC ! InclInfo converted to upper case. + CHARACTER(512) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(1024) :: PriPath ! path name of primary file (RelativePathFileName) + CHARACTER(*), PARAMETER :: RoutineName = 'ParseInclInfo' + + ErrStat = ErrID_None + ErrMsg = "" + + ! Check for an integer at the beginning of the line. If found, it is where + ! we will start reading the included file. + ! Check to make sure the case-independent string " in " is found between the number and the file name. + + InclInfoUC = InclInfo + + CALL Conv2UC ( InclInfoUC ) + CALL GetWords ( InclInfoUC, Words, 2 ) + + IF ( TRIM( Words(2) ) == 'IN' ) THEN + + DashLoc = INDEX( Words(1), '-' ) + + IF ( DashLoc > 0 ) THEN ! Must be in the form of "<num1>-<num2>". + + READ (Words(1)(:DashLoc-1),*,IOSTAT=ErrStatLcl) RangeBeg ! Parse the first number as the beginning fo the range. + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF ! ( ErrStatLcl /= 0 ) + + READ (Words(1)(DashLoc+1:),*,IOSTAT=ErrStatLcl) RangeEnd + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF ! ( ErrStatLcl /= 0 ) + + + ! Are the line numbers valid? + + IF ( RangeBeg <= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.'//NewLine// & + ' The start of the range must be > 0.',ErrStat,ErrMsg,RoutineName) + RETURN + ELSEIF ( RangeEnd < 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.'//NewLine// & + ' The end of the range must be >= 0.',ErrStat,ErrMsg,RoutineName) + RETURN + ELSEIF ( ( RangeEnd > 0 ) .AND. ( RangeEnd < RangeBeg ) ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.'//NewLine// & + ' The end of the range must be >= '//TRIM( Num2LStr( RangeBeg ) )//' or = 0.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF ! ( ErrStatLcl /= 0 ) + + ELSE + + READ (Words(1),*,IOSTAT=ErrStatLcl) RangeBeg + IF ( ErrStatLcl /= 0 ) THEN ! Was there a number after the "@"? If so, assume it is the line to start reading. + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.'//NewLine// & + ' The end of the range must be >= '//TRIM( Num2LStr( RangeBeg ) )//' or = 0.',ErrStat,ErrMsg,RoutineName) + RETURN + ELSE ! Number found. Assume it is the line to start reading. + RangeEnd = 0 ! TEMP: Read entire file after the start line. + ENDIF ! ( ErrStartLcl /= 0 ) + + ENDIF ! ( DashLoc > 0 ) + + FileName = ADJUSTL( InclInfo(INDEX( InclInfoUC, 'IN' )+3:) ) ! File name must be at least three characters after the "I" in "IN". + + ELSE + ! Line did not have the form "@<int> in <filename>". + FileName = ADJUSTL( InclInfo ) ! Shift the file name to the beginning of Line. + RangeBeg = 1 + RangeEnd = 0 + + ENDIF ! ( Words(2) == 'IN' ) + + + ! Check for quotes and remove them from the file name. + ! If the file name is quote delimited, we should be able to read it as a quoted string. Otherwise, leave it as is. + + IF ( INDEX( FileName, '"' )+INDEX( FileName, "'" ) > 0 ) THEN + READ (FileName,*,IOSTAT=ErrStatLcl) FileName !,IOMSG=ErrMsg2 + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF ! ( ErrStatLcl /= 0 ) + ENDIF ! ( INDEX( InclInfo, '"' )+INDEX( InclInfo, "'" ) > 0 ) + + IF ( PathIsRelative( Filename ) ) then + CALL GetPath( RelativePathFileName, PriPath ) ! Input files will be relative to the path where the primary input file is located. + Filename = TRIM(PriPath)//TRIM(Filename) + END IF + + + RETURN + + END SUBROUTINE ParseInclInfo +!======================================================================= +!> \copydoc nwtc_io::parsechvar + SUBROUTINE ParseInVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + + ! This subroutine parses the specified line of text for two words. One should be a + ! variable name and the other an INTEGER value. + ! Generate an error message if the value is the wrong type. + + + ! Arguments declarations. + + INTEGER, INTENT(OUT) :: Var ! The INTEGER variable to receive the input value. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + + CHARACTER(NWTC_SizeOfNumWord) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseInVar' + + ErrStat = ErrID_None + ErrMsg = "" + + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( ExpVarName )//'" variable was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + + CALL ChkParseData ( Words, ExpVarName, FileInfo%FileList(FileInfo%FileIndx(LineNum)) & + , FileInfo%FileLine(LineNum), NameIndx, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat ( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + READ (Words(3-NameIndx),*,IOSTAT=ErrStatLcl) Var + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The variable "'//TRIM( Words(NameIndx) )//'" was not assigned valid INTEGER value on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//& + ' >> The text being parsed was :'//NewLine//' "'//TRIM( FileInfo%Lines(LineNum) )//'"', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(1X,A15," = ",A20)') Words + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseInVar +!======================================================================= +!> \copydoc nwtc_io::parsechvarwdefault + SUBROUTINE ParseInVarWDefault ( FileInfo, LineNum, ExpVarName, Var, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! This subroutine parses the specified line of text for two words. One should be a + ! the name of a integer variable and the other an integer value. + ! Generate an error message if the value is the wrong type. + + ! WARNING: This routine assumes the "words" containing the variable name and value are <= 20 characters. + + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + INTEGER(IntKi), INTENT(OUT) :: Var ! The INTEGER variable to receive the input value. + INTEGER(IntKi), INTENT(IN) :: VarDefault ! The INTEGER used as the default. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseInVarDefault' + CHARACTER(20) :: defaultStr + + ErrStat=ErrID_None + ErrMsg = "" + + ! First parse this as a string + CALL ParseVar ( FileInfo, LineNum, ExpVarName, defaultStr, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + CALL Conv2UC( defaultStr ) + IF ( INDEX(defaultStr, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable + LineNum = LineNum - 1 ! back up a line + CALL ParseVar ( FileInfo, LineNum, ExpVarName, Var, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE + Var = VarDefault ! "DEFAULT" value + END IF + + RETURN + END SUBROUTINE ParseInVarWDefault +!======================================================================= +!> \copydoc nwtc_io::parsedbary + SUBROUTINE ParseLoAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg, UnEc ) + + ! This subroutine parses the specified line of text for AryLen LOGICAL values. + ! Generate an error message if the value is the wrong type. + + + ! Arguments declarations. + + INTEGER, INTENT(IN) :: AryLen ! The length of the array to parse. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + LOGICAL, INTENT(OUT) :: Ary (AryLen) ! The LOGICAL array to receive the input values. + + CHARACTER(*), INTENT(In) :: AryName ! The array name we are trying to fill. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(*), PARAMETER :: RoutineName = 'ParseLoAry' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + READ (FileInfo%Lines(LineNum),*,IOSTAT=ErrStatLcl) Ary + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned valid LOGICAL values on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(A)') TRIM( FileInfo%Lines(LineNum) ) + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseLoAry +!======================================================================= +!> \copydoc nwtc_io::parsechvar + SUBROUTINE ParseLoVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + + ! This subroutine parses the specified line of text for two words. One should be a + ! variable name and the other a LOGICAL value. + ! Generate an error message if the value is the wrong type. + + + ! Arguments declarations. + + LOGICAL, INTENT(OUT) :: Var ! The LOGICAL variable to receive the input value. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + + CHARACTER(NWTC_SizeOfNumWord) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseLoVar' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( ExpVarName )//'" variable was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + + CALL ChkParseData ( Words, ExpVarName, FileInfo%FileList(FileInfo%FileIndx(LineNum)) & + , FileInfo%FileLine(LineNum), NameIndx, ErrStatLcl, ErrMsg2 ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ (Words(3-NameIndx),*,IOSTAT=ErrStatLcl) Var + + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The variable "'//TRIM( Words(NameIndx) )//'" was not assigned valid LOGICAL value on line #' & + //TRIM( Num2LStr( LineNum ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(1X,A15," = ",A20)') Words + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseLoVar +!======================================================================= +!> \copydoc nwtc_io::parsechvarwdefault + SUBROUTINE ParseLoVarWDefault ( FileInfo, LineNum, ExpVarName, Var, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + LOGICAL, INTENT(OUT) :: Var ! The LOGICAL variable to receive the input value. + LOGICAL, INTENT(IN) :: VarDefault ! The LOGICAL used as the default. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseLoVarDefault' + CHARACTER(20) :: defaultStr + + ErrStat=ErrID_None + ErrMsg = "" + + ! First parse this as a string + CALL ParseVar ( FileInfo, LineNum, ExpVarName, defaultStr, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + CALL Conv2UC( defaultStr ) + IF ( INDEX(defaultStr, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable + LineNum = LineNum - 1 ! back up a line + CALL ParseVar ( FileInfo, LineNum, ExpVarName, Var, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE + Var = VarDefault ! "DEFAULT" value + END IF + + RETURN + END SUBROUTINE ParseLoVarWDefault +!======================================================================= +!> \copydoc nwtc_io::parsedbary + SUBROUTINE ParseSiAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + INTEGER, INTENT(IN) :: AryLen ! The length of the array to parse. + + REAL(ReKi), INTENT(OUT) :: Ary (AryLen) ! The single-precision REAL array to receive the input values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(In) :: AryName ! The array name we are trying to fill. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: i + + CHARACTER(*), PARAMETER :: RoutineName = 'ParseSiAry' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + READ (FileInfo%Lines(LineNum),*,IOSTAT=ErrStatLcl) Ary + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The "'//TRIM( AryName )//'" array was not assigned valid REAL values on line #' & + //TRIM( Num2LStr( FileInfo%FileLine(LineNum) ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine & + //' "'//TRIM( FileInfo%Lines(LineNum) )//'"', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(A)') TRIM( FileInfo%Lines(LineNum) ) + END IF + + DO i=1,AryLen + call CheckRealVar( Ary(i), AryName, ErrStat, ErrMsg ) + if (ErrStat>= AbortErrLev) return + END DO + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseSiAry +!======================================================================= +!> \copydoc nwtc_io::parsechvar + SUBROUTINE ParseSiVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + REAL(ReKi), INTENT(OUT) :: Var ! The single-precision REAL variable to receive the input value. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + + CHARACTER(NWTC_SizeOfNumWord) :: Words (2) ! The two "words" parsed from the line. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseSiVar' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (LineNum > size(FileInfo%Lines) ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The "'//TRIM( ExpVarName )//'" variable was not assigned because the file is too short.' & + , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + + CALL ChkParseData ( Words, ExpVarName, FileInfo%FileList(FileInfo%FileIndx(LineNum)) & + , FileInfo%FileLine(LineNum), NameIndx, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + READ (Words(3-NameIndx),*,IOSTAT=ErrStatLcl) Var + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "' & + //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & + ' >> The variable "'//TRIM( Words(NameIndx) )//'" was not assigned valid REAL value on line #' & + //TRIM( Num2LStr( LineNum ) )//'.'//NewLine//' >> The text being parsed was :'//NewLine// & + ' "'//TRIM( FileInfo%Lines(LineNum) )//'"', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + CALL CheckRealVar( Var, ExpVarName, ErrStat, ErrMsg) + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) WRITE (UnEc,'(1X,A15," = ",A20)') Words !bjj: not sure this is the best way to echo the number being read (in case of truncation, etc) + END IF + + LineNum = LineNum + 1 + + RETURN + + END SUBROUTINE ParseSiVar +!======================================================================= +!> \copydoc nwtc_io::parsechvarwdefault + SUBROUTINE ParseSiVarWDefault ( FileInfo, LineNum, ExpVarName, Var, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Arguments declarations. + + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status. + INTEGER(IntKi), INTENT(INOUT) :: LineNum ! The number of the line to parse. + + INTEGER, INTENT(IN), OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc. + + REAL(ReKi), INTENT(OUT) :: Var ! The single-precision REAL variable to receive the input value. + REAL(ReKi), INTENT(IN) :: VarDefault ! The single-precision REAL used as the default. + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if ErrStat /= 0. + CHARACTER(*), INTENT(IN) :: ExpVarName ! The expected variable name. + + TYPE (FileInfoType), INTENT(IN) :: FileInfo ! The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ParseSiVarDefault' + CHARACTER(20) :: defaultStr + + ErrStat=ErrID_None + ErrMsg = "" + + ! First parse this as a string + CALL ParseVar ( FileInfo, LineNum, ExpVarName, defaultStr, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + CALL Conv2UC( defaultStr ) + IF ( INDEX(defaultStr, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable + LineNum = LineNum - 1 ! back up a line + CALL ParseVar ( FileInfo, LineNum, ExpVarName, Var, ErrStatLcl, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE + Var = VarDefault ! "DEFAULT" value + END IF + + RETURN + END SUBROUTINE ParseSiVarWDefault +!======================================================================= +!> This routine determines if the given file name is absolute or relative. +!! We will consider an absolute path one that satisfies one of the +!! following four criteria: +!! 1. It contains ":/" +!! 2. It contains ":\" +!! 3. It starts with "/" +!! 4. It starts with "\" +!! +!! All others are considered relative. + FUNCTION PathIsRelative ( GivenFil ) + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: GivenFil !< The name of the given file. + LOGICAL :: PathIsRelative !< The function return value + + + + ! Determine if file name begins with an absolute path name or if it is relative + ! note that Doxygen has serious issues if you use the single quote instead of + ! double quote characters in the strings below: + + PathIsRelative = .FALSE. + + IF ( ( INDEX( GivenFil, ":/") == 0 ) .AND. ( INDEX( GivenFil, ":\") == 0 ) ) THEN ! No drive is specified (by ":\" or ":/") + + IF ( INDEX( "/\", GivenFil(1:1) ) == 0 ) THEN ! The file name doesn't start with "\" or "/" + + PathIsRelative = .TRUE. + + END IF + + END IF + + RETURN + END FUNCTION PathIsRelative +!======================================================================= +!> This routine prints out an end-of-file message and aborts the program. + SUBROUTINE PremEOF ( Fil , Variable, TrapErrors, ErrMsg ) + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Fil !< The name of the file that ran out of data. + CHARACTER(*), INTENT(IN) :: Variable !< The name of the variable we were trying to read at the time. + LOGICAL, INTENT(IN), OPTIONAL :: TrapErrors !< Determines if the program should abort or return to calling function + CHARACTER(*), INTENT(OUT),OPTIONAL:: ErrMsg !< The name of the file that ran out of data. + + ! LOCAL variables + LOGICAL :: TrapThisError ! The local version of TrapErrors + CHARACTER(ErrMsgLen) :: Msg ! The local version of ErrMsg + + + IF ( PRESENT( TrapErrors ) ) THEN + TrapThisError = TrapErrors + ELSE + TrapThisError = .FALSE. + END IF + + + Msg = 'Premature EOF for file "'//TRIM( Fil )//'" while trying to read '//TRIM( Variable )//'.' + + IF ( PRESENT(ErrMsg) ) THEN + ErrMsg = Msg + ELSE + CALL WrScr( ' ' ) + CALL ProgAbort( ' '//TRIM(Msg), TrapThisError ) + END IF + + + RETURN + END SUBROUTINE PremEOF +!======================================================================= + SUBROUTINE InitFileInfo( StringArray, FileInfo, ErrStat, ErrMsg ) + + CHARACTER(*), DIMENSION(:), INTENT(IN ) :: StringArray + TYPE(FileInfoType), INTENT( OUT) :: FileInfo + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + character(len=len(StringArray)) :: TmpStringArray(size(StringArray)) + character(len=len(StringArray)) :: Line + integer :: TmpFileLine(size(StringArray)) + + CHARACTER(*), PARAMETER :: RoutineName = 'InitFileInfo' + INTEGER :: i, NumLines, IC, NumCommChars, LineLen, FirstComm, CommLoc + + ErrStat = ErrID_None + ErrMsg = "" + NumLines = 0 ! Initialize counter for non-comment populated lines + TmpFileLine = 0 ! Line number that was passed in + NumCommChars = LEN_TRIM( CommChars ) ! Number of globally specified CommChars + + ! Find how many non-comment lines we have + do i=1,size(StringArray) + Line=StringArray(i) + LineLen = LEN_TRIM( Line ) + IF ( ( NumCommChars == 0 ) .OR. ( LineLen == 0 ) ) CYCLE + + FirstComm = MIN( LEN( Line ), LineLen + 1 ) + + DO IC=1,NumCommChars + CommLoc = INDEX( Line, CommChars(IC:IC) ) + IF ( CommLoc > 0 ) THEN + FirstComm = MIN( CommLoc, FirstComm ) + ENDIF + END DO + + ! Only keep lines with no comments and some sort of length + if ( LEN_TRIM( Line(:FirstComm-1) ) > 0 ) then + NumLines=NumLines+1 + TmpStringArray(NumLines) = Line(:FirstComm-1) ! Store non-comment line + TmpFileLine(NumLines) = i ! Corresponding line number of passed in info + endif + enddo + + ! Now save the FileInfo + FileInfo%NumLines = NumLines ! only lines that contained anything + FileInfo%NumFiles = 1 + ALLOCATE( FileInfo%Lines(FileInfo%NumLines) ) + ALLOCATE( FileInfo%FileLine(FileInfo%NumLines) ) + ALLOCATE( FileInfo%FileIndx(FileInfo%NumLines) ) + ALLOCATE( FileInfo%FileList(FileInfo%NumFiles) ) + + DO i = 1, FileInfo%NumLines + IF ( LEN(TmpStringArray(i)) > LEN(FileInfo%Lines(i)) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Input string exceeds the bounds of FileInfoType.' , ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + FileInfo%Lines(i) = TmpStringArray(i) + FileInfo%FileLine(i) = TmpFileLine(i) + END DO + FileInfo%FileIndx = FileInfo%NumFiles + FileInfo%FileList = (/ "passed file info" /) + + END SUBROUTINE +!======================================================================= +!> This routine calls ScanComFile (nwtc_io::scancomfile) and ReadComFile (nwtc_io::readcomfile) +!! to move non-comments in a set of nested files starting with TopFile into the FileInfo (nwtc_io::fileinfo) structure. + SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Argument declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + CHARACTER(*), INTENT(IN) :: TopFileName !< The name of the top file in the nested structure. + + TYPE (FileInfoType), INTENT(OUT) :: FileInfo !< The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: AryInd = 0 ! The index into the FileInfo arrays. There is no data in the arrays at the start. + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: FileIndx = 1 ! The index into the FileInfo%FileList array. Start with the first file in the list. + INTEGER(IntKi) :: RangeBeg = 1 ! The first line in a range of lines to be included from a file. + INTEGER(IntKi) :: RangeEnd = 0 ! The last line in a range of lines to be included from a file. Zero to read to the end of the file. + + INTEGER :: File = 0 ! Index into the arrays. + + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ProcessComFile' + TYPE (FNlist_Type), POINTER :: CurrFile ! The current file being pointed to in the linked list. + TYPE (FNlist_Type), POINTER :: FirstFile ! The first file in the linked list (TopFile). + TYPE (FNlist_Type), POINTER :: LastFile ! The last file in the linked list. + + + ! Scan the file, and it's included files, to determine how many lines will be kept and generate + ! a linked list of the different files. + ! This MUST be done before calling ReadComFile. + + ErrStat = ErrID_None + ErrMsg = "" + + ALLOCATE ( FirstFile ) !bjj: fix me , IOStat=ErrStatLcl2 + LastFile => FirstFile + NULLIFY ( LastFile%Next ) + LastFile%Filename = TopFileName + CurrFile => LastFile + FileInfo%NumLines = 0 + + CALL ScanComFile ( FirstFile, CurrFile, LastFile, 1, 0, FileInfo%NumLines, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStatLcl >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + + ! Count the number of different files in the linked list and allocate the array for the list of files. + ! This MUST be done before calling ReadComFile. + + CurrFile => FirstFile + FileInfo%NumFiles = 0 + + DO + IF ( .NOT. ASSOCIATED( CurrFile ) ) EXIT + FileInfo%NumFiles = FileInfo%NumFiles + 1 + CurrFile => CurrFile%Next + ENDDO + + ALLOCATE ( FileInfo%FileList( FileInfo%NumFiles ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the FileInfo%FileList array.' , ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + + ! Copy the linked list of file names into the FileList array. + ! This MUST be done before calling ReadComFile. + + CurrFile => FirstFile + File = 0 + DO + IF ( .NOT. ASSOCIATED( CurrFile ) ) EXIT + File = File + 1 + FileInfo%FileList(File) = CurrFile%Filename + CurrFile => CurrFile%Next + ENDDO + + + ! Allocate the arrays to hold the non-comments, the files they occur in, and which lines they were found on. + ! This MUST be done before calling ReadComFile. + + ALLOCATE ( FileInfo%FileLine( FileInfo%NumLines ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the FileInfo%FileLine array.' , ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( FileInfo%FileIndx( FileInfo%NumLines ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the FileInfo%FileIndx array.' , ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( FileInfo%Lines( FileInfo%NumLines ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the FileInfo%Lines array.' , ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + + ! Read the file and save all but the comments. + + AryInd = 0 + CALL ReadComFile ( FileInfo, FileIndx, AryInd, RangeBeg, RangeEnd, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStatLcl >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + CALL Cleanup() + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE Cleanup ( ) + + ! This subroutine cleans up all the allocatable arrays and closes the binary file + + ! Local arguments. + + TYPE (FNlist_Type), POINTER :: NextFile ! The next file being pointed to in the linked list. + + ! Deallocate the linked list of file names. + + CurrFile => FirstFile + NextFile => CurrFile%Next + DO + DEALLOCATE(CurrFile) + IF ( .NOT. ASSOCIATED( NextFile ) ) EXIT + CurrFile => NextFile + NextFile => CurrFile%Next + ENDDO + +!bjj: this needs to happen elsewhere... + + !IF ( ALLOCATED( FileInfo%FileLine ) ) DEALLOCATE( FileInfo%FileLine ) + !IF ( ALLOCATED( FileInfo%Lines ) ) DEALLOCATE( FileInfo%FileIndx ) + !IF ( ALLOCATED( FileInfo%FileLine ) ) DEALLOCATE( FileInfo%FileList ) + !IF ( ALLOCATED( FileInfo%Lines ) ) DEALLOCATE( FileInfo%Lines ) + + END SUBROUTINE Cleanup + + END SUBROUTINE ProcessComFile +!======================================================================= +!> This routine outputs fatal error messages and stops the program. + SUBROUTINE ProgAbort ( Message, TrapErrors, TimeWait, ErrLevel ) + + ! Argument declarations. + + REAL(ReKi), INTENT(IN), OPTIONAL :: TimeWait !< Tells whether to wait for TimeWait s, or pause if < 0. + + INTEGER(IntKi), INTENT(IN), OPTIONAL :: ErrLevel !< The error level to report to the OS. + + LOGICAL, INTENT(IN), OPTIONAL :: TrapErrors !< Determines if the program should abort or return to calling function + + CHARACTER(*), INTENT(IN) :: Message !< Error message. + + + + IF ( Beep ) CALL UsrAlarm + + CALL WrScr ( Message ) + + IF ( PRESENT(TrapErrors) ) THEN + IF ( TrapErrors ) RETURN + END IF + + IF ( LEN_TRIM(ProgName) > 0 ) THEN + CALL WrScr ( NewLine//' Aborting '//TRIM( ProgName )//'.'//NewLine ) + ELSE + CALL WrScr ( NewLine//' Aborting program.'//NewLine ) + END IF + + ! Do we pause (<0), proceed (=0), or wait (>0)? + + IF ( PRESENT( TimeWait ) ) THEN + IF ( ( TimeWait < 0.0 ) .AND. KBInputOK ) THEN + CALL ProgPause + ELSE IF ( TimeWait > 0.0 ) THEN + CALL WaitTime( TimeWait ) + END IF + END IF + + + ! Do we report a specific error level to the OS or use the default of 1? + + IF ( PRESENT( ErrLevel ) ) THEN + CALL ProgExit ( ErrLevel ) + ELSE + CALL ProgExit ( 1 ) + END IF + + + END SUBROUTINE ProgAbort +!======================================================================= +!> This routine pauses the program. + SUBROUTINE ProgPause() + + CALL WrScr ( ' Hit the <Enter> key to continue.' ) + + READ (*,'()') + + + RETURN + END SUBROUTINE ProgPause +!======================================================================= +!> This routine outputs non-fatal warning messages and returns to the calling routine. +!! It beeps if ntwc_io::beep is true. + SUBROUTINE ProgWarn ( Message ) + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Message !< Warning message to print + + + + IF ( Beep ) CALL UsrAlarm + CALL WrScr ( ' WARNING: '//Message ) + + + RETURN + END SUBROUTINE ProgWarn + +!======================================================================= +!> \copydoc nwtc_io::int2lstr + FUNCTION R2LStr4 ( Num, Fmt_in ) + + ! Function declaration. + + CHARACTER(15) :: R2LStr4 ! This function. + CHARACTER(*), OPTIONAL :: Fmt_in + + + ! Argument declarations. + + REAL(SiKi), INTENT(IN) :: Num ! The number to convert. + CHARACTER(15) :: Fmt ! format for output + + + ! Return a 0 if that's what we have. + + IF ( Num == 0.0_SiKi ) THEN + R2LStr4 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + if ( present( Fmt_in ) ) then + Fmt = '('//Fmt_in//')' + else + Fmt = '(1PG15.5)' + end if + + + WRITE (R2LStr4,Fmt) Num + + CALL AdjRealStr( R2LStr4 ) + + + RETURN + END FUNCTION R2LStr4 +!======================================================================= +!> \copydoc nwtc_io::int2lstr + FUNCTION R2LStr8 ( Num, Fmt_in ) + + ! Function declaration. + + CHARACTER(15) :: R2LStr8 ! This function. + CHARACTER(*), OPTIONAL :: Fmt_in + + + ! Argument declarations. + + REAL(R8Ki), INTENT(IN) :: Num ! The floating-point number to convert. + CHARACTER(15) :: Fmt ! format for output + + + ! Return a 0 if that's what we have. + + IF ( Num == 0.0_R8Ki ) THEN + R2LStr8 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + if ( present( Fmt_in ) ) then + Fmt = '('//Fmt_in//')' + else + Fmt = '(1PG15.5)' + end if + + WRITE (R2LStr8,Fmt) Num + + CALL AdjRealStr( R2LStr8 ) + + + RETURN + END FUNCTION R2LStr8 +!======================================================================= +!> \copydoc nwtc_io::int2lstr + FUNCTION R2LStr16 ( Num, Fmt_in ) + + ! This function converts a 16-byte floating point number to + ! a left-aligned string. It eliminates trailing zeroes + ! and even the decimal point if it is not a fraction. + + + ! Function declaration. + + CHARACTER(15) :: R2LStr16 ! This function. + CHARACTER(*), OPTIONAL :: Fmt_in + + + ! Argument declarations. + + REAL(QuKi), INTENT(IN) :: Num ! The floating-point number to convert. + CHARACTER(15) :: Fmt ! format for output + + + ! Return a 0 if that's what we have. + + IF ( Num == 0.0_QuKi ) THEN + R2LStr16 = '0' + RETURN + END IF + + + ! Write the number into the string using G format and left justify it. + if ( present( Fmt_in ) ) then + Fmt = '('//Fmt_in//')' + else + Fmt = '(1PG15.5)' + end if + + WRITE (R2LStr16,Fmt) Num + + CALL AdjRealStr( R2LStr16 ) + + + RETURN + END FUNCTION R2LStr16 +!====================================================================== +!> This routine reads a AryLen values separated by whitespace (or other Fortran record delimiters such as commas) +!! into an array (either on same line or multiple lines). +!! Use ReadAry (nwtc_io::readary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadCAry ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + + CHARACTER(*), INTENT(OUT) :: Ary(AryLen) !< Array being read. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the string array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), StrType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_StrAryFrmt) TRIM( AryName ), AryDescr, ( TRIM( Ary(Ind) ), Ind=1,MIN(AryLen,NWTC_MaxAryLen) ) + END IF + + + RETURN + END SUBROUTINE ReadCAry +!====================================================================== +!> This routine reads a AryLen values separated by whitespace (or other Fortran record delimiters such as commas) +!! into an array (either on same line or multiple lines) from an input string +!! Use ReadAry (nwtc_io::readary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadCAryFromStr ( Str, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + CHARACTER(*), INTENT(IN) :: Str !< String to read from + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + CHARACTER(*), INTENT(OUT) :: Ary(AryLen) !< Array being read. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + ! Local declarations: + INTEGER :: Ind ! Index into the string array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + ! Init of output + do Ind=1,AryLen + Ary(Ind)='' + end do + ! Reading fields from string + READ (Str,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + ! Dedicated "CheckIOS" + IF ( IOS < 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'End of line reached while trying to read ',AryLen,' fields from string.' + ErrStat = ErrID_Fatal + ELSE IF ( IOS > 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'Unexpected error while trying to read ',AryLen,' fields from string.' + ELSE + ErrMsg='' + ErrStat = ErrID_None + END IF + IF (ErrStat >= AbortErrLev) RETURN + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_StrAryFrmt) TRIM( AryName ), AryDescr, ( TRIM( Ary(Ind) ), Ind=1,MIN(AryLen,NWTC_MaxAryLen) ) + END IF + RETURN + END SUBROUTINE ReadCAryFromStr +!======================================================================= +!> This routine reads a AryLen values into a real array from the next AryLen lines of the input file (one value per line). +!! Use ReadAryLines (nwtc_io::readarylines) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadCAryLines ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + + CHARACTER(*), INTENT(OUT) :: Ary(AryLen) !< Array variable being read. + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + ErrStat = ErrID_None + ErrMsg = "" + + DO Ind=1,AryLen + READ (UnIn,*,IOSTAT=IOS) Ary(Ind) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName )//'('//TRIM( Int2LStr( Ind ) )//')', StrType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_StrFrmt) TRIM( AryName )//'('//TRIM( Int2LStr( Ind ) )//')', AryDescr, TRIM(Ary(Ind)) + END IF + END DO + + RETURN + END SUBROUTINE ReadCAryLines +!======================================================================= +!> This routine reads a comment from the next line of the input file. + SUBROUTINE ReadCom ( UnIn, Fil, ComName, ErrStat, ErrMsg, UnEc, Comment ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: ComName !< Text string containing the comment name. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(OUT), OPTIONAL :: Comment !< Text string containing the comment. + + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + + + READ (UnIn,'(A)',IOSTAT=IOS) Comment + + CALL CheckIOS ( IOS, Fil, ComName, StrType, ErrStat, ErrMsg ) + + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,'(A)') TRIM(Comment) + END IF + + + RETURN + END SUBROUTINE ReadCom +!============================================================================= +!> This routine opens and reads the contents of a file with comments and stores the good stuff in the FileInfo structure. +!! You need to call ScanComFile() first to count the number of lines and get the list of files in the recursive tree. +!! This information needs to be stored in the FileInfo structure before calling this routine. + RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLine, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER(IntKi), INTENT(INOUT) :: AryInd !< The current index into the FileInfo arrays. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + INTEGER(IntKi), INTENT(IN) :: FileIndx !< The pointer to file name in the list of files. + INTEGER(IntKi), INTENT(IN) :: LastLine !< The last line to read from this file. Includes blank and comment lines. Zero means read to the end of file. + INTEGER(IntKi), INTENT(IN) :: StartLine !< The line at which to start processing this file. Includes blank and comment lines. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + TYPE (FileInfoType), INTENT(INOUT) :: FileInfo !< The derived type for holding the file information. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + + INTEGER :: File ! The index into the FileList array. + INTEGER :: FileLine ! The current line of the input file. + INTEGER :: LineLen ! The length of the line returned from ReadLine(). + INTEGER :: NewIndx ! The index into the FileList array that applied to the next file to be processed. + INTEGER :: RangeBeg ! The first line in a range of lines to be included from a file. + INTEGER :: RangeEnd ! The last line in a range of lines to be included from a file. + INTEGER :: UnIn ! The unit number used for the input file. + ! Should the comment characters be passed to this routine instead of being hard coded? -mlb + CHARACTER(1024) :: IncFileName ! The name of a file that this one includes. + CHARACTER(512) :: Line ! The contents of a line returned from ReadLine() with comment removed. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ReadComFile' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Open the input file. + + CALL GetNewUnit ( UnIn, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL OpenFInpFile ( UnIn, FileInfo%FileList(FileIndx), ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + + ! Skip the beginning of the file, if requested. + + IF ( StartLine > 1 ) THEN + DO FileLine=1,StartLine-1 + READ(UnIn,'()',IOStat=ErrStatLcl) + IF (ErrStatLcl /= 0) THEN + CALL SetErrStat( ErrID_Fatal, "Error reading file beginning.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + ENDDO ! FileLine + ENDIF ! ( StartLine > 1 ) + + FileLine = StartLine - 1 + + + ! Read the data. + + ErrStatLcl = 0 + + DO WHILE ( ErrStatLcl == 0 ) + + + ! Stop processing when CurrLine > LastLine. If LastLine is zero, read to the end of file. + + FileLine = FileLine + 1 + + IF ( ( LastLine > 0 ) .AND. ( FileLine > LastLine ) ) EXIT + + + ! Process the next line. + + CALL ReadLine ( UnIn, CommChars, Line, LineLen, ErrStatLcl ) ! Reads a line. Returns what is before the first comment character. + + IF ( ( ErrStatLcl == 0 ) .AND. ( LineLen > 0 ) ) THEN ! ErrStatLcl is IOStat from Read statement + + Line = ADJUSTL( Line ) + + + ! Is this line trying to include another file? If so, recursively process it. + + IF ( Line(1:1) == '@' ) THEN + + + ! Parse the contents of everything after the "@" to determine the name of the include file and the optional line range. + + CALL ParseInclInfo ( Line(2:), FileInfo%FileList(FileIndx), IncFileName, RangeBeg, RangeEnd, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, TRIM( FileInfo%FileList(FileIndx) )//':Line#'//TRIM( Num2LStr( FileLine ) ) & + //':'//TRIM(ErrMsg2), ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + ErrStatLcl = 0 + + ! Which file in the prestored list is the new one? + + DO File=1,FileInfo%NumFiles + IF ( TRIM( FileInfo%FileList(File) ) == TRIM( IncFileName ) ) THEN + NewIndx = File + EXIT + ENDIF ! ( TRIM( FileInfo%FileList(File) ) == TRIM( Line(2:) ) ) + ENDDO ! File + + + ! Let's recursively process this new file. + + CALL ReadComFile ( FileInfo, NewIndx, AryInd, RangeBeg, RangeEnd, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + ErrStatLcl = 0 + + ELSE + + + ! Not a file name. Add this line to stack. + + AryInd = AryInd + 1 + FileInfo%FileLine(AryInd) = FileLine + FileInfo%FileIndx(AryInd) = FileIndx + FileInfo%Lines (AryInd) = Line + + ENDIF ! ( Line(1:1) == '@' ) + + ENDIF ! ( ( ErrStatLcl == 0 ) .AND. ( LineLen > 0 ) ) + + ENDDO ! WHILE ( ErrStatLcl == 0 ) + + CALL Cleanup( ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE Cleanup ( ) + + ! This subroutine cleans up all the allocatable arrays, sets the error status/message and closes the binary file + + ! Close the input file. + + CLOSE ( UnIn ) + + END SUBROUTINE Cleanup + + END SUBROUTINE ReadComFile +!======================================================================= +!> This routine reads a variable from the next line of the input file. +!! Use ReadVar (nwtc_io::readvar) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadCVar ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(OUT) :: Var !< Variable being read + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) Var + + + CALL CheckIOS ( IOS, Fil, VarName, StrType, ErrStat, ErrMsg ) + + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_StrFrmt) VarName, VarDescr, '"'//TRIM( Var )//'"' + END IF + + + RETURN + END SUBROUTINE ReadCVar +!======================================================================= +!> This routine reads the contents of a FAST binary output file (FASTbinFile) and stores it in FASTdata. +!! It is assumed that the name of the binary file is preloaded into FASTdata%File by the calling procedure. + SUBROUTINE ReadFASTbin ( UnIn, Init, FASTdata, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< An optional error level to be returned to the calling routine. + INTEGER(IntKi), INTENT(INOUT) :: UnIn !< The IO unit for the FAST binary file. + + LOGICAL, INTENT(IN) :: Init !< A flag to tell the routine to read only the file header for initialization purposes. + + CHARACTER(*), INTENT( OUT) :: ErrMsg !< An optional error message to be returned to the calling routine. + + TYPE (FASTdataType), INTENT(INOUT) :: FASTdata !< The derived type for holding FAST output data. + + + ! Local declarations. + + REAL(R8Ki) :: TimeIncr ! The increment for the time data when a time channel is not included. + REAL(R8Ki) :: TimeOff ! The offset for the time data when a time channel is included. + REAL(R8Ki) :: TimeOut1 ! The first output data when a time channel is not included. + REAL(R8Ki) :: TimeScl ! The slope for the time data when a time channel is included. + + REAL(ReKi), ALLOCATABLE :: ColMax(:) ! The maximum value of the column data. + REAL(ReKi), ALLOCATABLE :: ColMin(:) ! The minimum value of the column data. + + REAL(SiKi), ALLOCATABLE :: ColOff(:) ! The offset for the column data. + REAL(SiKi), ALLOCATABLE :: ColScl(:) ! The slope for the column data. + + INTEGER(IntKi) :: IChan ! The channel index used for DO loops. + INTEGER(IntKi) :: IChr ! The character index used for DO loops. + INTEGER(IntKi) :: IRow ! The row index used for DO loops. + INTEGER(IntKi) :: LenDesc ! The length of the description string, DescStr. + INTEGER(IntKi), PARAMETER :: MaxLenDesc = 1024 ! The maximum allowed length of the description string, DescStr. + INTEGER(IntKi) :: ChanLen2 ! The lengths of channel names in the file + + INTEGER(B4Ki), ALLOCATABLE :: TmpTimeArray(:) ! This array holds the normalized time channel that was read from the binary file. + INTEGER(B4Ki) :: Tmp4BInt ! This scalar temporarially holds a 4-byte integer that was stored in the binary file + + INTEGER(B2Ki) :: FileType ! The type of FAST data file (1: Time channel included in file; 2: Time stored as start time and step). + INTEGER(B2Ki) :: Tmp2BInt ! This scalar temporarially holds a 2-byte integer that was stored in the binary file. + INTEGER(B2Ki), ALLOCATABLE :: TmpInArray(:,:) ! This array holds the normalized channels that were read from the binary file. + INTEGER(R8Ki), ALLOCATABLE :: TmpR8InArray(:,:) ! This array holds the uncompressed channels that were read from the binary file. + + INTEGER(B1Ki), ALLOCATABLE :: DescStrASCII(:) ! The ASCII equivalent of DescStr. + INTEGER(B1Ki), ALLOCATABLE :: TmpStrASCII(:) ! The temporary ASCII equivalent of a channel name or units. + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ReadFASTbin' + + + ErrStat = ErrID_None + ErrMsg = "" + + + + ! Open data file. + + CALL OpenBInpFile ( UnIn, FASTdata%File, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + + ! Process the requested data records of this file. + + CALL WrScr ( NewLine//' =======================================================' ) + CALL WrScr ( ' Reading in data from file "'//TRIM( FASTdata%File )//'".'//NewLine ) + + + ! Read some of the header information. + + READ (UnIn, IOSTAT=ErrStat2) FileType + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading FileType from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + + IF (FileType == FileFmtID_ChanLen_In) THEN + READ (UnIn, IOSTAT=ErrStat2) Tmp2BInt + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading ChanLen from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + ChanLen2 = Tmp2BInt + ELSE + ChanLen2 = 10 + END IF + + READ (UnIn, IOSTAT=ErrStat2) Tmp4BInt + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the number of channels from file "' & + //TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + FASTdata%NumChans = Tmp4BInt ! possible type conversion + + READ (UnIn, IOSTAT=ErrStat2) Tmp4BInt + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the number of records from file "' & + //TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + FASTdata%NumRecs = Tmp4BInt ! possible type conversion + + + ! Time is done differently for the two file types. + + IF ( FileType == FileFmtID_WithTime ) THEN + + READ (UnIn, IOSTAT=ErrStat2) TimeScl + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading TimeScl from file "'//TRIM( FASTdata%File ) & + //'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) TimeOff + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading TimeOff from file "'//TRIM( FASTdata%File ) & + //'".', ErrStat, ErrMsg, RoutineName ) + RETURN + CALL Cleanup() + ENDIF + + ELSE + + READ (UnIn, IOSTAT=ErrStat2) TimeOut1 + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading TimeOut1 from file "'//TRIM( FASTdata%File ) & + //'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) TimeIncr + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading TimeIncr from file "'//TRIM( FASTdata%File ) & + //'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + END IF ! IF ( FileType == FileFmtID_WithTime ) + + + ! Allocate the necessary arrays. + + ALLOCATE ( FASTdata%ChanNames( FASTdata%NumChans+1 ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for FASTdata%ChanNames array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( FASTdata%ChanUnits( FASTdata%NumChans+1 ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Fatal error allocating memory for FASTdata%ChanUnits array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( FASTdata%Data( FASTdata%NumRecs, FASTdata%NumChans+1 ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the FASTdata%Data array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + IF ( FileType == FileFmtID_NoCompressWithoutTime ) THEN + ALLOCATE ( TmpR8InArray( FASTdata%NumRecs, FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the TmpR8InArray array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ELSE + + ALLOCATE ( ColMax( FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for ColMax array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( ColMin( FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for ColMin array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( ColOff( FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for ColOff array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( ColScl( FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for ColScl array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ALLOCATE ( TmpInArray( FASTdata%NumRecs, FASTdata%NumChans ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the TmpInArray array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + IF ( FileType == FileFmtID_WithTime ) THEN + ALLOCATE ( TmpTimeArray( FASTdata%NumRecs ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the TmpTimeArray array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + END IF + + END IF + + + + + ! Read more of the header information. + + IF ( FileType /= FileFmtID_NoCompressWithoutTime ) THEN + + READ (UnIn, IOSTAT=ErrStat2) ColScl + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the ColScl array from file "' & + //TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) ColOff + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the ColOff array from file "' & + //TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) LenDesc + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading LenDesc from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + LenDesc = MIN( LenDesc, MaxLenDesc ) + + ALLOCATE ( DescStrASCII( LenDesc ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the DescStrASCII array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) DescStrASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the DescStrASCII array from file "' & + //TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + FASTdata%Descr = '' + + DO IChr=1,LenDesc + FASTdata%Descr(IChr:IChr) = CHAR( DescStrASCII(IChr) ) + END DO + + + ALLOCATE ( TmpStrASCII( ChanLen2 ) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error allocating memory for the DescStrASCII array.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + TmpStrASCII(:) = ICHAR( ' ' ) + DO IChan=1,FASTdata%NumChans+1 + READ (UnIn, IOSTAT=ErrStat2) TmpStrASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the title of Channel #'//Int2LStr( IChan )// & + ' from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + FASTdata%ChanNames(IChan) = '' + DO IChr=1,ChanLen2 + FASTdata%ChanNames(IChan)(IChr:IChr) = CHAR( TmpStrASCII(IChr) ) + END DO + END DO + + TmpStrASCII(:) = ICHAR( ' ' ) + DO IChan=1,FASTdata%NumChans+1 + READ (UnIn, IOSTAT=ErrStat2) TmpStrASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading the units of Channel #'//Int2LStr( IChan )// & + ' from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + FASTdata%ChanUnits(IChan) = '' + DO IChr=1,ChanLen2 + FASTdata%ChanUnits(IChan)(IChr:IChr) = CHAR( TmpStrASCII(IChr) ) + END DO + END DO + + + ! Return if we only wanted to read the header. + + IF ( Init ) THEN + CALL Cleanup() + RETURN + ENDIF + + + ! If the file contains a time channel (as opposed to just initial time and time step), read it. + ! There are four bytes per time value. + + IF ( FileType == FileFmtID_WithTime ) THEN + + READ (UnIn, IOSTAT=ErrStat2) TmpTimeArray ! Time data stored in normalized 32-bit integers + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading time data from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + + END IF ! FileType + + + ! Put time data in the data array. + + IF ( FileType == FileFmtID_WithTime ) THEN + FASTdata%Data(:,1) = ( TmpTimeArray(:) - TimeOff )/TimeScl; + FASTdata%TimeStep = FASTdata%Data(2,1) - FASTdata%Data(1,1) + ELSE + FASTdata%Data(:,1) = REAL( TimeOut1, DbKi ) + REAL( TimeIncr, DbKi )*[ (IRow, IRow=0,FASTdata%NumRecs-1 ) ]; + FASTdata%TimeStep = TimeIncr + END IF + + + ! Read the FAST channel data. + + DO IRow=1,FASTdata%NumRecs + IF ( FileType == FileFmtID_NoCompressWithoutTime ) THEN + READ (UnIn, IOSTAT=ErrStat2) TmpR8InArray(IRow,:) + ELSE + READ (UnIn, IOSTAT=ErrStat2) TmpInArray(IRow,:) + ENDIF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading channel data from file "'//TRIM( FASTdata%File )//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF + END DO ! IRow=1,FASTdata%NumRecs + + + IF ( FileType == FileFmtID_NoCompressWithoutTime ) THEN + DO IRow=1,FASTdata%NumRecs + FASTdata%Data(IRow,2:) = REAL(TmpR8InArray(IRow,:), ReKi) + END DO ! IRow=1,FASTdata%NumRecs + ELSE + DO IRow=1,FASTdata%NumRecs + ! Denormalize the data one row at a time and store it in the FASTdata%Data array. + FASTdata%Data(IRow,2:) = ( TmpInArray(IRow,:) - ColOff(:) )/ColScl(:) + END DO ! IRow=1,FASTdata%NumRecs + END IF + + + + CALL Cleanup( ) + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE Cleanup ( ) + + ! This subroutine cleans up all the allocatable arrays, sets the error status/message and closes the binary file + + + ! Deallocate arrays created in this routine. + + IF ( ALLOCATED( ColMax ) ) DEALLOCATE( ColMax ) + IF ( ALLOCATED( ColMin ) ) DEALLOCATE( ColMin ) + IF ( ALLOCATED( ColOff ) ) DEALLOCATE( ColOff ) + IF ( ALLOCATED( ColScl ) ) DEALLOCATE( ColScl ) + IF ( ALLOCATED( DescStrASCII ) ) DEALLOCATE( DescStrASCII ) + IF ( ALLOCATED( TmpStrASCII ) ) DEALLOCATE( TmpStrASCII ) + IF ( ALLOCATED( TmpInArray ) ) DEALLOCATE( TmpInArray ) + IF ( ALLOCATED( TmpR8InArray ) ) DEALLOCATE( TmpR8InArray ) + IF ( ALLOCATED( TmpTimeArray ) ) DEALLOCATE( TmpTimeArray ) + + + ! Close file + + CLOSE ( UnIn ) + + END SUBROUTINE Cleanup + + END SUBROUTINE ReadFASTbin +!======================================================================= +!> \copydoc nwtc_io::readcary + SUBROUTINE ReadIAry ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(OUT) :: Ary(AryLen) ! Integer array being read. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the integer array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_IntAryFrmt ) TRIM( AryName ), AryDescr, Ary(1:MIN(AryLen,NWTC_MaxAryLen)) + END IF + END IF !present(unec) + + + + + RETURN + END SUBROUTINE ReadIAry +!======================================================================= +!> \copydoc nwtc_io::readcvar +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadIVar ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a single integer variable from the next line of the input file. + + + ! Argument declarations: + + INTEGER, INTENT(OUT) :: Var ! Integer variable being read. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + READ (Word,*,IOSTAT=IOS) Var + + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_IntFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadIVar +!======================================================================= +!> This routine reads a scalar variable from the next line of the input file. +!! Use ReadVarWDefault (nwtc_io::readvarwdefault) instead of directly calling a specific routine in the generic interface. +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadIVarWDefault ( UnIn, Fil, Var, VarName, VarDescr, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(OUT) :: Var !< variable being read + INTEGER, INTENT(IN) :: VarDefault !< default value of variable being read + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + CALL Conv2UC( Word ) + IF ( INDEX(Word, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the DEFAULT value + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + ELSE + Var = VarDefault + END IF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_IntFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadIVarWDefault +!======================================================================= +!> This routine reads a logical variable from the next line of the input file. +!! Use ReadVarWDefault (nwtc_io::readvarwdefault) instead of directly calling a specific routine in the generic interface. +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadLVarWDefault ( UnIn, Fil, Var, VarName, VarDescr, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + LOGICAL, INTENT(OUT) :: Var !< variable being read + LOGICAL, INTENT(IN) :: VarDefault !< default value of variable being read + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + CALL Conv2UC( Word ) + IF ( INDEX(Word, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the DEFAULT value + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + ELSE + Var = VarDefault + END IF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_IntFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadLVarWDefault +!======================================================================= + +!> \copydoc nwtc_io::readcary + SUBROUTINE ReadLAry ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into an logical array from the next AryLen lines of the input file. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + LOGICAL, INTENT(OUT) :: Ary(AryLen) ! Logical array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the integer array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), FlgType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_LgAryFrmt ) TRIM( AryName ), AryDescr, Ary(1:MIN(AryLen,NWTC_MaxAryLen)) + END IF + END IF !present(unec) + + RETURN + END SUBROUTINE ReadLAry +!============================================================================= +!> This routine reads a line from the specified input file and returns the non-comment +!! portion of the line. + SUBROUTINE ReadLine ( UnIn, CommentChars, Line, LineLen, IOStat ) + + ! Argument declarations. + + INTEGER(IntKi), INTENT(OUT) :: IOStat !< IOS error status from file read. + + INTEGER, INTENT(IN) :: UnIn !< The unit number for the file being read. + INTEGER, INTENT(OUT) :: LineLen !< The length of the line returned from ReadLine(). + + CHARACTER(*), INTENT(IN) :: CommentChars !< The list of possible comment characters. + CHARACTER(*), INTENT(OUT) :: Line !< The decommented line being returned to the calling routine. + + ! Local declarations. + + INTEGER :: CommLoc ! The left-most location of a given comment character in the Line. + INTEGER :: FirstComm ! The location of first comment character in the Line. + INTEGER :: IC ! The index for the character location in the string. + INTEGER :: NumCommChars ! The number of comment characters in the CommentChars array. + + + READ (UnIn,'(A)',IOSTAT=IOStat) Line + + IF ( IOStat /= 0 ) THEN + Line = '' + LineLen = 0 + RETURN + ENDIF + + LineLen = LEN_TRIM( Line ) + NumCommChars = LEN_TRIM( CommentChars ) + + IF ( ( NumCommChars == 0 ) .OR. ( LineLen == 0 ) ) RETURN + + FirstComm = MIN( LEN( Line ), LineLen + 1 ) + + DO IC=1,NumCommChars + CommLoc = INDEX( Line, CommentChars(IC:IC) ) + IF ( CommLoc > 0 ) THEN + FirstComm = MIN( CommLoc, FirstComm ) + ENDIF + END DO + + Line = Line(:FirstComm-1) + LineLen = LEN_TRIM( Line ) + + + RETURN + END SUBROUTINE ReadLine +!======================================================================= +!> \copydoc nwtc_io::readcvar + SUBROUTINE ReadLVar ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a single logical variable from the next line of the input file. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + LOGICAL, INTENT(OUT) :: Var ! Logical variable being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + READ (UnIn,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, FlgType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_LgFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadLVar +!======================================================================= +!> This routine reads a single word from a file and tests to see if it's a pure number (no true or false). + SUBROUTINE ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: VarName !< Text string containing the variable name. + CHARACTER(*), INTENT(Out) :: Word !< Text string containing the first word from the input line. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + + ! Read in the first word of the input line. Check I/O status. + + READ (UnIn,*,IOSTAT=IOS) Word + + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + + + IF (ErrStat >= AbortErrLev) RETURN + + + ! See if the word starts with a T or F. If so, flag it as an invalid number. + + IF ( INDEX( 'FTft', Word(:1) ) > 0 ) THEN + + ErrStat = ErrID_Severe + ErrMsg = 'ReadNum:Invalid numeric input for file "'//TRIM( Fil )//'". "'//TRIM( Word )// & + '" found when trying to read the number, '//TRIM( VarName )//'.' + + END IF + + + + RETURN + END SUBROUTINE ReadNum +!======================================================================= +!> This routine reads up to MaxAryLen values from an input file and store them in CharAry(:). +!! These values represent the names of output channels, and they are specified in the format +!! required for OutList(:) in FAST input files. +!! The end of this list is specified with the line beginning with the 3 characters "END". + SUBROUTINE ReadOutputList ( UnIn, Fil, CharAry, AryLenRead, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(OUT) :: AryLenRead !< Length of the array that was actually read. + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN) :: UnEc !< I/O unit for echo file (if > 0). + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(OUT) :: CharAry(:) !< Character array being read (calling routine dimensions it to max allowable size). + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: MaxAryLen ! Maximum length of the array being read + INTEGER :: NumWords ! Number of words contained on a line + + + CHARACTER(1000) :: OutLine ! Character string read from file, containing output list + CHARACTER(3) :: EndOfFile + + + ! Initialize some values + + ErrStat = ErrID_None + ErrMsg = '' + MaxAryLen = SIZE(CharAry) + AryLenRead = 0 + + CharAry = '' + + + ! Read in all of the lines containing output parameters and store them in CharAry(:). + ! The end of this list is specified with the line beginning with END. + + DO + + CALL ReadVar ( UnIn, Fil, OutLine, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + IF ( ErrStat >= AbortErrLev ) RETURN + + EndOfFile = OutLine(1:3) ! EndOfFile is the 1st 3 characters of OutLine + CALL Conv2UC( EndOfFile ) ! Convert EndOfFile to upper case + IF ( EndOfFile == 'END' ) EXIT ! End of OutList has been reached; therefore, exit this DO + + NumWords = CountWords( OutLine ) ! The number of words in OutLine. + + AryLenRead = AryLenRead + NumWords ! The total number of output channels read in so far. + + ! Check to see if the maximum # allowable in the array has been reached. + + IF ( AryLenRead > MaxAryLen ) THEN + + ErrStat = ErrID_Fatal + ErrMsg = 'ReadOutputList:The maximum number of output channels allowed is '//TRIM( Int2LStr(MaxAryLen) )//'.' + RETURN + + ELSE + + CALL GetWords ( OutLine, CharAry((AryLenRead - NumWords + 1):AryLenRead), NumWords ) + + END IF + + END DO + + + RETURN + END SUBROUTINE ReadOutputList +!======================================================================= +!> This routine reads up to MaxAryLen values from an input file and store them in CharAry(:). +!! These values represent the names of output channels, and they are specified in the format +!! required for OutList(:) in FAST input files. +!! The end of this list is specified with the line beginning with the 3 characters "END". + SUBROUTINE ReadOutputListFromFileInfo ( FileInfo, LineNum, CharAry, AryLenRead, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + INTEGER(IntKi), INTENT(INOUT):: LineNum !< The number of the line to parse. + INTEGER, INTENT(OUT) :: AryLenRead !< Length of the array that was actually read. + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file (if > 0). + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(OUT) :: CharAry(:) !< Character array being read (calling routine dimensions it to max allowable size). + + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: MaxAryLen ! Maximum length of the array being read + INTEGER :: NumWords ! Number of words contained on a line + + INTEGER :: QuoteCh ! Character position. + + CHARACTER(1000) :: OutLine ! Character string read from file, containing output list + CHARACTER(3) :: EndOfFile + + + ! Initialize some values + + ErrStat = ErrID_None + ErrMsg = '' + MaxAryLen = SIZE(CharAry) + AryLenRead = 0 + + CharAry = '' + + + ! Read in all of the lines containing output parameters and store them in CharAry(:). + ! The end of this list is specified with the line beginning with END. + + DO + + IF ( PRESENT(UnEc) ) THEN + if (UnEc > 0) WRITE(UnEc, '(A)') FileInfo%Lines(LineNum) + ENDIF + OutLine = adjustl(trim(FileInfo%Lines(LineNum))) ! remove leading whitespace + + EndOfFile = OutLine(1:3) ! EndOfFile is the 1st 3 characters of OutLine + CALL Conv2UC( EndOfFile ) ! Convert EndOfFile to upper case + IF ( EndOfFile == 'END' ) THEN + LineNum = LineNum + 1 + EXIT ! End of OutList has been reached; therefore, exit this DO + ENDIF + + ! Check if we have a quoted string at the begining. Ignore anything outside the quotes if so (this is the ReadVar behaviour for quoted strings). + if (SCAN(OutLine(1:1), '''"' ) == 1_IntKi ) then + QuoteCh = SCAN( OutLine(2:), '''"' ) ! last quote + if (QuoteCh < 1) QuoteCh = LEN_TRIM(OutLine) ! in case no end quote + OutLine(QuoteCh+2:) = ' ' ! blank out everything after last quote + endif + + NumWords = CountWords( OutLine ) ! The number of words in OutLine. + + AryLenRead = AryLenRead + NumWords ! The total number of output channels read in so far. + + ! Check to see if the maximum # allowable in the array has been reached. + + IF ( AryLenRead > MaxAryLen ) THEN + + ErrStat = ErrID_Fatal + ErrMsg = 'ReadOutputList:The maximum number of output channels allowed is '//TRIM( Int2LStr(MaxAryLen) )//'.' + RETURN + + ELSE + + CALL GetWords ( OutLine, CharAry((AryLenRead - NumWords + 1):AryLenRead), NumWords ) + + END IF + + LineNum = LineNum+1 + + END DO + + + RETURN + END SUBROUTINE ReadOutputListFromFileInfo + +!======================================================================= +!> \copydoc nwtc_io::readcary + SUBROUTINE ReadR4Ary ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into a 4-byte real array separated by white space + ! (possibly on the same line of the input file). + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN),OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + + REAL(SiKi), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + DO Ind=1,AryLen + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_ReAryFrmt ) TRIM( AryName ), AryDescr, Ary(1:MIN(AryLen,NWTC_MaxAryLen)) + END IF + END IF + + + RETURN + END SUBROUTINE ReadR4Ary +!====================================================================== +!> This routine reads a AryLen values separated by whitespace (or other Fortran record delimiters such as commas) +!! into an array (either on same line or multiple lines) from an input string +!! Use ReadAry (nwtc_io::readary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadR4AryFromStr ( Str, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + CHARACTER(*), INTENT(IN) :: Str !< String to read from + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + REAL(SiKi), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + ! Local declarations: + INTEGER :: Ind ! Index into the string array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + ! Init of output + do Ind=1,AryLen + Ary(Ind)=0.0 + end do + ! Reading fields from string + READ (Str,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + ! Dedicated "CheckIOS" + IF ( IOS < 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'End of line reached while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ErrStat = ErrID_Fatal + ELSE IF ( IOS > 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'Unexpected error while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ELSE + ErrMsg='' + ErrStat = ErrID_None + END IF + IF (ErrStat >= AbortErrLev) RETURN + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReAryFrmt) TRIM( AryName ), AryDescr, ( Ary(Ind), Ind=1,MIN(AryLen,NWTC_MaxAryLen) ) + END IF + RETURN + END SUBROUTINE ReadR4AryFromStr +!======================================================================= +!> \copydoc nwtc_io::readcary + SUBROUTINE ReadR8Ary ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into a 8-byte real array separated by white space + ! (possibly on the same line of the input file). + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN),OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + + REAL(R8Ki), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + DO Ind=1,AryLen + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_ReAryFrmt ) TRIM( AryName ), AryDescr, Ary(1:MIN(AryLen,NWTC_MaxAryLen)) + END IF + END IF + + RETURN + END SUBROUTINE ReadR8Ary +!====================================================================== +!> This routine reads a AryLen values separated by whitespace (or other Fortran record delimiters such as commas) +!! into an array (either on same line or multiple lines) from an input string +!! Use ReadAry (nwtc_io::readary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadR8AryFromStr ( Str, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + CHARACTER(*), INTENT(IN) :: Str !< String to read from + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + REAL(R8Ki), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + ! Local declarations: + INTEGER :: Ind ! Index into the string array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + ! Init of output + do Ind=1,AryLen + Ary(Ind)=0.0 + end do + ! Reading fields from string + READ (Str,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + ! Dedicated "CheckIOS" + IF ( IOS < 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'End of line reached while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ErrStat = ErrID_Fatal + ELSE IF ( IOS > 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'Unexpected error while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ELSE + ErrMsg='' + ErrStat = ErrID_None + END IF + IF (ErrStat >= AbortErrLev) RETURN + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReAryFrmt) TRIM( AryName ), AryDescr, ( Ary(Ind), Ind=1,MIN(AryLen,NWTC_MaxAryLen) ) + END IF + RETURN + END SUBROUTINE ReadR8AryFromStr +!======================================================================= +!> \copydoc nwtc_io::readcary + SUBROUTINE ReadR16Ary ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into a 16-byte real array separated by white space + ! (possibly on the same line of the input file). + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN),OPTIONAL :: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + + REAL(QuKi), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName ), NumType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + DO Ind=1,AryLen + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) THEN + WRITE( UnEc, Ec_ReAryFrmt ) TRIM( AryName ), AryDescr, Ary(1:MIN(AryLen,NWTC_MaxAryLen)) + END IF + END IF + + + RETURN + END SUBROUTINE ReadR16Ary +!====================================================================== +!> This routine reads a AryLen values separated by whitespace (or other Fortran record delimiters such as commas) +!! into an array (either on same line or multiple lines) from an input string +!! Use ReadAry (nwtc_io::readary) instead of directly calling a specific routine in the generic interface. + SUBROUTINE ReadR16AryFromStr ( Str, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + CHARACTER(*), INTENT(IN) :: Str !< String to read from + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message describing ErrStat + REAL(QuKi), INTENT(INOUT) :: Ary(AryLen) ! Real array being read. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + ! Local declarations: + INTEGER :: Ind ! Index into the string array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + ! Init of output + do Ind=1,AryLen + Ary(Ind)=0.0 + end do + ! Reading fields from string + READ (Str,*,IOSTAT=IOS) ( Ary(Ind), Ind=1,AryLen ) + + ! Dedicated "CheckIOS" + IF ( IOS < 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'End of line reached while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ErrStat = ErrID_Fatal + ELSE IF ( IOS > 0 ) THEN + write(ErrMsg,'(A,I0,A)') 'Unexpected error while trying to read ',AryLen,' value from string:`'//trim(Str)//'`' + ELSE + ErrMsg='' + ErrStat = ErrID_None + END IF + IF (ErrStat >= AbortErrLev) RETURN + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReAryFrmt) TRIM( AryName ), AryDescr, ( Ary(Ind), Ind=1,MIN(AryLen,NWTC_MaxAryLen) ) + END IF + RETURN + END SUBROUTINE ReadR16AryFromStr +!======================================================================= +!> \copydoc nwtc_io::readcarylines + SUBROUTINE ReadR4AryLines ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + REAL(SiKi), INTENT(OUT) :: Ary(AryLen) ! Real (4-byte) array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + ErrStat = ErrID_None + ErrMsg = "" + + DO Ind=1,AryLen + READ (UnIn,*,IOSTAT=IOS) Ary(Ind) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName )//'('//TRIM( Num2LStr( Ind ) )//')', NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Ary(Ind), TRIM( AryName )//'('//TRIM( Int2LStr( Ind ) )//')', AryDescr + END IF + END DO + + RETURN + END SUBROUTINE ReadR4AryLines +!======================================================================= +!> \copydoc nwtc_io::readcarylines + SUBROUTINE ReadR8AryLines ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into a real array from the next AryLen lines of the input file. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + REAL(R8Ki), INTENT(OUT) :: Ary(AryLen) ! Real (8-byte) array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + ErrStat = ErrID_None + ErrMsg = "" + + DO Ind=1,AryLen + READ (UnIn,*,IOSTAT=IOS) Ary(Ind) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName )//'('//TRIM( Num2LStr( Ind ) )//')', NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Ary(Ind), TRIM( AryName )//'('//TRIM( Int2LStr( Ind ) )//')', AryDescr + END IF + END DO + + RETURN + END SUBROUTINE ReadR8AryLines +!======================================================================= +!> \copydoc nwtc_io::readcarylines + SUBROUTINE ReadR16AryLines ( UnIn, Fil, Ary, AryLen, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a AryLen values into a real array from the next AryLen lines of the input file. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + INTEGER, INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + REAL(QuKi), INTENT(OUT) :: Ary(AryLen) ! Real (16-byte) array being read. + + CHARACTER(*), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr ! Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: Ind ! Index into the real array. Assumed to be one digit. + INTEGER :: IOS ! I/O status returned from the read statement. + + + + ErrStat = ErrID_None + ErrMsg = "" + + DO Ind=1,AryLen + READ (UnIn,*,IOSTAT=IOS) Ary(Ind) + + CALL CheckIOS ( IOS, Fil, TRIM( AryName )//'('//TRIM( Num2LStr( Ind ) )//')', NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Ary(Ind), AryName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Ary(Ind), TRIM( AryName )//'('//TRIM( Int2LStr( Ind ) )//')', AryDescr + END IF + END DO + + RETURN + END SUBROUTINE ReadR16AryLines +!======================================================================= +!> \copydoc nwtc_io::readcvar +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadR4Var ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a single double (real) variable from the next line of the input file. + ! New code should call ReadVar instead of directly calling this routine. + + + ! Argument declarations: + + REAL(SiKi), INTENT(OUT) :: Var ! Real (4-byte) variable being read. + INTEGER(IntKi),INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + RETURN + END SUBROUTINE ReadR4Var +!======================================================================= +!> \copydoc nwtc_io::readivarwdefault + SUBROUTINE ReadR4VarWDefault ( UnIn, Fil, Var, VarName, VarDescr, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + REAL(SiKi), INTENT(OUT) :: Var ! Variable being read + REAL(SiKi), INTENT(IN ) :: VarDefault ! Default value for variable being read + + INTEGER(IntKi),INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + CALL Conv2UC( Word ) + IF ( INDEX(Word, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the DEFAULT value + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + ELSE + Var = VarDefault + END IF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + RETURN + END SUBROUTINE ReadR4VarWDefault +!======================================================================= +!> \copydoc nwtc_io::readcvar +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadR8Var ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + REAL(R8Ki), INTENT(OUT) :: Var ! Real (8-byte) variable being read. + INTEGER(IntKi),INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadR8Var +!======================================================================= +!> \copydoc nwtc_io::readr4varwdefault + SUBROUTINE ReadR8VarWDefault ( UnIn, Fil, Var, VarName, VarDescr, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + REAL(R8Ki), INTENT(OUT) :: Var !< Variable being read + REAL(R8Ki), INTENT(IN ) :: VarDefault !< Default value for variable being read + + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + CALL Conv2UC( Word ) + IF ( INDEX(Word, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the DEFAULT value + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + ELSE + Var = VarDefault + END IF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + RETURN + END SUBROUTINE ReadR8VarWDefault +!======================================================================= +!> \copydoc nwtc_io::readcvar +!! WARNING: this routine limits the size of the number being read to 30 characters + SUBROUTINE ReadR16Var ( UnIn, Fil, Var, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + + ! This routine reads a single double (real) variable from the next line of the input file. + ! New code should call ReadVar instead of directly calling this routine. + + + ! Argument declarations: + + REAL(QuKi), INTENT(OUT) :: Var ! Real (16-byte) variable being read. + INTEGER(IntKi),INTENT(OUT),OPTIONAL:: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT),OPTIONAL:: ErrMsg ! Error message + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc ! I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + + RETURN + END SUBROUTINE ReadR16Var +!======================================================================= +!> \copydoc nwtc_io::readr4varwdefault + SUBROUTINE ReadR16VarWDefault ( UnIn, Fil, Var, VarName, VarDescr, VarDefault, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + REAL(QuKi), INTENT(OUT) :: Var !< Variable being read + REAL(QuKi), INTENT(IN ) :: VarDefault !< Default value for variable being read + + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + + CHARACTER( *), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + CHARACTER(30) :: Word ! String to hold the first word on the line. + + + CALL ReadNum ( UnIn, Fil, Word, VarName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev) RETURN ! If we're about to read a T/F and treat it as a number, we have a less severe ErrStat + + + CALL Conv2UC( Word ) + IF ( INDEX(Word, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the DEFAULT value + READ (Word,*,IOSTAT=IOS) Var + + CALL CheckIOS ( IOS, Fil, VarName, NumType, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + CALL CheckRealVar( Var, VarName, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + ELSE + Var = VarDefault + END IF + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_ReFrmt) Var, VarName, VarDescr + END IF + + RETURN + END SUBROUTINE ReadR16VarWDefault +!======================================================================= +!> This routine reads a string from the next line of the input file. + SUBROUTINE ReadStr ( UnIn, Fil, CharVar, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN), OPTIONAL:: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(OUT) :: CharVar !< Integer variable being read. + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: VarDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: VarName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + + READ (UnIn,'(A)',IOSTAT=IOS) CharVar + + CALL CheckIOS ( IOS, Fil, VarName, StrType, ErrStat, ErrMsg ) + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc > 0 ) & + WRITE (UnEc,Ec_StrFrmt) VarName, VarDescr, '"'//TRIM( CharVar )//'"' + END IF + + + + RETURN + END SUBROUTINE ReadStr +!======================================================================= +!> This routine removes trailing C_NULL characters, which can be present when +!! passing strings between C and Fortran. + SUBROUTINE RemoveNullChar( Str ) + + CHARACTER(*), INTENT(INOUT) :: Str !< string that will be truncated before the null character + + INTEGER(IntKi) :: I + + I = INDEX( Str, C_NULL_CHAR ) - 1 + IF ( I > 0 ) Str = Str(1:I) + + END SUBROUTINE RemoveNullChar +!============================================================================= +!> This routine opens and scans the contents of a file with comments counting non-comment lines. +!! If a line has "@Filename" on a line, it recursively scans that file to add the non-comment lines +!! to the total. +!! This routine is typically called before ReadComFile() (nwtc_io::readcomfile) to count the number on non-comment lines +!! that will need to be stored. +!! It also adds to a linked list of unique file names that are in the call chain. + RECURSIVE SUBROUTINE ScanComFile ( FirstFile, ThisFile, LastFile, StartLine, LastLine, NumLines, ErrStat, ErrMsg ) + + IMPLICIT NONE + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + INTEGER(IntKi), INTENT(IN) :: LastLine !< The last line to read from this file. Includes blank and comment lines. Zero means read to the end of file. + INTEGER(IntKi), INTENT(INOUT) :: NumLines !< The total number of non-comment lines scanned so far. + INTEGER(IntKi), INTENT(IN) :: StartLine !< The line at which to start processing this file. Includes blank and comment lines. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + TYPE (FNlist_Type), POINTER, INTENT(IN) :: FirstFile !< The first file in the linked list. + TYPE (FNlist_Type), POINTER, INTENT(INOUT) :: LastFile !< The last file in the linked list. + TYPE (FNlist_Type), POINTER, INTENT(IN) :: ThisFile !< The last file in the linked list. + + + ! Local declarations. + + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine and/or IOStatus. + + INTEGER :: CurrLine ! The current line in the file. + INTEGER :: RangeBeg ! The first line in a range of lines to be included from a file. + INTEGER :: RangeEnd ! The last line in a range of lines to be included from a file. + INTEGER :: LineLen ! The length of the line returned from ReadLine(). + INTEGER :: UnIn ! The unit number used for the input file. + + LOGICAL :: FileFound ! A flag that is set to TRUE if this file has already been read. + LOGICAL :: IsOpen ! A flag that is set to TRUE if this file is already open. + + CHARACTER(1024) :: FileName ! The name of this file being processed. + CHARACTER(1024) :: IncFileName ! The name of a file that this one includes. + CHARACTER(512) :: Line ! The contents of a line returned from ReadLine() with comment removed. + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ScanComFile' + + TYPE (FNlist_Type), POINTER :: CurrFile ! The current file being pointed to in the linked list. + TYPE (FNlist_Type), POINTER :: NewFile ! The file being pointed to in the linked list is is to be included by ThisFile. + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Is this file already open from earlier in the recursion. That would be bad. + + FileName = ThisFile%Filename + INQUIRE ( FILE=Filename, OPENED=IsOpen ) + IF ( IsOpen ) THEN + CALL SetErrStat( ErrID_Fatal, 'Fatal error scanning "'//TRIM( Filename ) & + //'". A file cannot directly or indirectly include itself.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + ! Open the input file. + UnIn = -1 + CALL GetNewUnit ( UnIn, ErrStatLcl, ErrMsg2 ) + + CALL OpenFInpFile ( UnIn, Filename, ErrStatLcl, ErrMsg2 ) + IF ( ErrStatLcl /= 0 ) THEN + CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF ! ( ErrStatLcl /= 0 ) + + + ! Skip the beginning of the file, if requested. + + IF ( StartLine > 1 ) THEN + DO CurrLine=1,StartLine-1 + READ(UnIn,'()', IOStat=ErrStatLcl) + IF (ErrStatLcl /= 0) THEN + CALL SetErrStat( ErrID_Fatal, "Error reading file beginning.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + ENDDO ! CurrLine + ENDIF ! ( StartLine > 1 ) + + CurrLine = StartLine - 1 + + + ! Make sure LastLine >= FirstLine unless it is zero. + + IF ( LastLine > 0 ) THEN + IF ( StartLine > LastLine ) THEN + CALL SetErrStat( ErrID_Fatal, 'Fatal error: LastLine must be >= StartLine unless it is zero.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ENDIF ! ( StartLine > LastLine ) + ENDIF ! ( LastLine > 0 ) + + + ! Scan the file to learn the number of non-comment lines and total number of files, including included files. + + ErrStatLcl = 0 + + DO WHILE ( ErrStatLcl == 0 ) + + + ! Stop processing when CurrLine > LastLine. If LastLine is zero, read to the end of file. + + CurrLine = CurrLine + 1 + + IF ( ( LastLine > 0 ) .AND. ( CurrLine > LastLine ) ) EXIT + + + ! Process the next line. + + CALL ReadLine ( UnIn, CommChars, Line, LineLen, ErrStatLcl ) ! Reads a line. Returns what is before the first comment character. + + IF ( ( ErrStatLcl == 0 ) .AND. ( LineLen > 0 ) ) THEN ! ErrStatLcl is IOStatus from read statement + + Line = ADJUSTL( Line ) + + + ! Is this line trying to include another file? + + IF ( Line(1:1) == '@' ) THEN + + + ! Parse the contents of everything after the "@" to determine the name of the include file and the optional line range. + + CALL ParseInclInfo ( Line(2:), Filename, IncFileName, RangeBeg, RangeEnd, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, TRIM( FileName )//':Line#'//TRIM( Num2LStr( CurrLine ) )//':'//TRIM(ErrMsg2), ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ErrStatLcl = 0 + + + ! Check to see if this file has been opened before. + + CurrFile => FirstFile + FileFound = .FALSE. + + DO + IF ( .NOT. ASSOCIATED( CurrFile ) ) EXIT + IF ( TRIM( IncFileName ) == TRIM( CurrFile%FileName ) ) THEN + FileFound = .TRUE. + NewFile => CurrFile + EXIT + ENDIF + CurrFile => CurrFile%Next + ENDDO + + + ! We have not seen this file before. Add it to the list. + + IF ( .NOT. FileFound ) THEN + ALLOCATE ( LastFile%Next ) + LastFile => LastFile%Next + NULLIFY ( LastFile%Next ) + LastFile%FileName = TRIM( IncFileName ) + NewFile => LastFile + ENDIF ! ( .NOT. FileFound ) + + CALL ScanComFile ( FirstFile, NewFile, LastFile, RangeBeg, RangeEnd, NumLines, ErrStatLcl, ErrMsg2 ) + CALL SetErrStat( ErrStatLcl, TRIM( FileName )//':Line#'//TRIM( Num2LStr( CurrLine ) )//':'//TRIM(ErrMsg2), ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ErrStatLcl = 0 + + ELSE + + NumLines = NumLines + 1 + + ENDIF ! ( Line(1:1) == '@' ) + + ENDIF ! IF ( ( ErrStatLcl == 0 ) .AND. ( LineLen > 0 ) ) + + ENDDO ! WHILE ( ErrStatLcl == 0 ) + + CALL Cleanup() + + + RETURN + +!======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE Cleanup ( ) + + ! This subroutine cleans up the parent routine before exiting. + + ! Local declarations. + + LOGICAL :: IsOpen ! A flage that indicates if the input unit is still open. + + + ! Close the file if it it open.. + + INQUIRE ( UnIn, OPENED=IsOpen ) + IF ( IsOpen ) CLOSE ( UnIn ) + + RETURN + + END SUBROUTINE Cleanup + + END SUBROUTINE ScanComFile +!======================================================================= +!> This routine converts a string (character array) into an +!! equivalent ASCII array of integers. +!! This routine is the inverse of the IntAry2Str() routine. + SUBROUTINE Str2IntAry( Str, IntAry, ErrStat, ErrMsg ) + + + ! Argument declarations: + CHARACTER(*), INTENT(IN) :: Str !< The string to convert + INTEGER(IntKi), INTENT(OUT) :: IntAry(:) !< ASCII representation of Str + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with ErrStat + + ! Local variables: + INTEGER(IntKi) :: I ! generic loop counter + INTEGER(IntKi) :: LStr ! length of the string + INTEGER(IntKi) :: LAry ! length of the integer array + + + ! Get the size of the arrays: + LStr = LEN(Str) + LAry = SIZE(IntAry) + + + ! Determine if the string will fit in the integer array: + IF ( LStr > LAry ) THEN + ErrStat = ErrID_Warn + ErrMsg = 'Char2Int:String exceeds array size.' + LStr = LAry ! we'll only convert the string values up to the array length + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + ! Convert the string to an ASCII array: + DO I=1,LStr + IntAry(I) = ICHAR(Str(I:I), IntKi) + END DO + + END SUBROUTINE Str2IntAry +!======================================================================= +!> This routine pauses program executaion for a specified +!! number of seconds. + SUBROUTINE WaitTime ( WaitSecs ) + + IMPLICIT NONE + + + ! Argument declarations: + + REAL(ReKi), INTENT(IN) :: WaitSecs !< The number of seconds to wait. + + + ! Local declarations: + + REAL(ReKi) :: EndCounts ! The number of counts when wait time is over. + + INTEGER :: Counts ! Current number of counts on the system clock. + INTEGER :: CountMax ! Maximum number of counts possible on the system clock. + INTEGER :: CountRate ! Number of counts per second on the system clock. + + + + CALL SYSTEM_CLOCK ( Counts, CountRate, CountMax ) + EndCounts = Counts + INT( WaitSecs*CountRate ) + + DO + CALL SYSTEM_CLOCK ( Counts, CountRate, CountMax ) + IF ( Counts > EndCounts ) EXIT + END DO + + + RETURN + END SUBROUTINE WaitTime +!======================================================================= +!> This subroutine opens a binary file named FileName, and writes a the AllOutData Matrix to a 16-bit packed +!! binary file. A text DescStr is written to the file as well as the text in the ChanName and ChanUnit arrays. +!! The file is closed at the end of this subroutine call (and on error). \n +!! NOTE: Developers may wish to inquire if the file can be opened at the start of a simulation to ensure that +!! it's available before running the simulation (i.e., don't run a code for a long time only to find out +!! that the file cannot be opened for writing). + SUBROUTINE WrBinFAST(FileName, FileID, DescStr, ChanName, ChanUnit, TimeData, AllOutData, ErrStat, ErrMsg) + + + IMPLICIT NONE + + ! Passed data (sorted by element size, then alphabetical) + + REAL(DbKi), INTENT(IN) :: TimeData(:) !< The time being output to the file (if using FileFmtID_WithoutTime: element 1 is the first output time, element 2 is the delta t) + REAL(ReKi), INTENT(IN) :: AllOutData(:,:) !< All of the data being written to the file (except time; note that the channels are the rows and time is the column--this is done for speed of saving the array) + INTEGER(IntKi), INTENT(OUT):: ErrStat !< Indicates whether an error occurred (see NWTC_Library) + INTEGER(B2Ki), INTENT(IN) :: FileID !< File ID, used to determine format of output file (use FileFmtID_WithTime or FileFmtID_WithoutTime) + + CHARACTER(ChanLen),INTENT(IN) :: ChanName(:) !< The output channel names (including Time) + CHARACTER(ChanLen),INTENT(IN) :: ChanUnit(:) !< The output channel units (including Time) + CHARACTER(*), INTENT(IN) :: DescStr !< Description to write to the binary file (e.g., program version, date, & time) + CHARACTER(*), INTENT(OUT):: ErrMsg !< Error message associated with the ErrStat + CHARACTER(*), INTENT(IN) :: FileName !< Name of the file to write the output in + + + ! Parameters required for scaling Real data to 16-bit integers + + REAL(R8Ki), PARAMETER :: Int32Max = 65535.0 ! Largest integer represented in 4 bytes + REAL(R8Ki), PARAMETER :: Int32Min = -65536.0 ! Smallest integer represented in 4 bytes + REAL(R8Ki), PARAMETER :: Int32Rng = Int32Max - Int32Min ! Max Range of 4-byte integer + + REAL(SiKi), PARAMETER :: IntMax = 32767.0 ! Largest integer represented in 2 bytes + REAL(SiKi), PARAMETER :: IntMin = -32768.0 ! Smallest integer represented in 2 bytes + REAL(SiKi), PARAMETER :: IntRng = IntMax - IntMin ! Max Range of 2 byte integer + + + ! Local variables + + REAL(DbKi) :: TimeMax ! Maximum value of the time data + REAL(DbKi) :: TimeMin ! Minimum value of the time data + REAL(R8Ki) :: TimeOff ! Offset for the time data + REAL(R8Ki) :: TimeScl ! Slope for the time data + REAL(R8Ki) :: TimeOut1 ! The first output time + REAL(R8Ki) :: TimeIncrement ! The delta t + + REAL(ReKi), ALLOCATABLE :: ColMax(:) ! Maximum value of the column data + REAL(ReKi), ALLOCATABLE :: ColMin(:) ! Minimum value of the column data + REAL(SiKi), ALLOCATABLE :: ColOff(:) ! Offset for the column data + REAL(SiKi), ALLOCATABLE :: ColScl(:) ! Slope for the column data + + + INTEGER(IntKi) :: ErrStat2 ! temporary error status + INTEGER(IntKi) :: I ! Generic loop counter + INTEGER(IntKi) :: IC ! Loop counter for the output channel + INTEGER(IntKi) :: IT ! Loop counter for the timestep + INTEGER(IntKi) :: J ! Generic counter + INTEGER(IntKi) :: LenDesc ! Length of the description string, DescStr + INTEGER(IntKi) :: NT ! Number of time steps + INTEGER(IntKi) :: NumOutChans ! Number of output channels + INTEGER(IntKi) :: UnIn ! Unit number for the binary file + REAL(R8Ki), ALLOCATABLE :: TmpR8OutArray(:) ! This array holds the uncompressed output channels before being written to the binary file + INTEGER(B2Ki), ALLOCATABLE :: TmpOutArray(:) ! This array holds the normalized output channels before being written to the binary file + INTEGER(B4Ki), ALLOCATABLE :: TmpTimeArray(:) ! This array holds the normalized output time channel before being written to the binary file + INTEGER(B1Ki), ALLOCATABLE :: DescStrASCII(:) ! The ASCII equivalent of DescStr + INTEGER(B1Ki), ALLOCATABLE :: ChanNameASCII(:) ! The ASCII equivalent of ChanName + INTEGER(B1Ki), ALLOCATABLE :: ChanUnitASCII(:) ! The ASCII equivalent of ChanUnit + + INTEGER(IntKi) :: LenName ! Max number of characters in a channel name + + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message + CHARACTER(*), PARAMETER :: RoutineName = 'WrBinFAST' + + !............................................................................................................................... + ! Initialize some values + !............................................................................................................................... + + ErrStat = ErrID_None ! No error has yet occurred + ErrMsg = '' ! No error has yet occurred + NumOutChans = SIZE(AllOutData,1) ! The number of output channels + NT = SIZE(AllOutData,2) ! The number of time steps to be written + LenDesc = LEN_TRIM( DescStr ) ! Length of the string that contains program name, version, date, and time + + ! Generate the unit number for the binary file + UnIn = 0 + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !............................................................................................................................... + ! Open the binary file for output + !............................................................................................................................... + + CALL OpenBOutFile ( UnIn, TRIM(FileName), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + !............................................................................................................................... + ! Allocate arrays + !............................................................................................................................... + IF (FileID==FileFmtID_ChanLen_In) THEN + LenName = 1 + DO IC = 1,NumOutChans+1 + LenName = MAX(LenName,LEN_TRIM(ChanName(IC))) + LenName = MAX(LenName,LEN_TRIM(ChanUnit(IC))) + END DO + ELSE + LenName = 10 + END IF + + CALL AllocAry( ChanNameASCII, (1+NumOutChans)*LenName , 'temporary channel name array (ChanNameASCII)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( ChanUnitASCII, (1+NumOutChans)*LenName, 'temporary channel unit names (ChanUnitASCII)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( DescStrASCII, LenDesc, 'temporary file description (DescStrASCII)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( FileID == FileFmtID_NoCompressWithoutTime ) THEN + CALL AllocAry( TmpR8OutArray, NumOutChans*NT, 'temporary output array (TmpR8OutArray)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE + + CALL AllocAry( ColMax, NumOutChans, 'column maxima (ColMax)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( ColMin, NumOutChans, 'column minima (ColMin)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( ColOff, NumOutChans, 'column offsets (ColOff)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( ColScl, NumOutChans, 'column scales (ColScl)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AllocAry( TmpOutArray, NumOutChans*NT, 'temporary output array (TmpOutArray)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( FileID == FileFmtID_WithTime ) THEN + CALL AllocAry( TmpTimeArray, NT, 'temporary output time array (TmpTimeArray)', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ENDIF + + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup( ) + RETURN + END IF + + + !............................................................................................................................... + ! Convert character strings to ASCII + !............................................................................................................................... + + ! Description string (DescStr) + + DO I=1,LenDesc + DescStrASCII(I) = IACHAR( DescStr(I:I) ) + END DO + + ! Channel names (ChanName) + J = 1 + DO IC = 1,SIZE(ChanName) + DO I=1,LenName + ChanNameASCII(J) = IACHAR( ChanName(IC)(I:I) ) + J = J + 1 + END DO + END DO + + ! Channel units (ChanUnit) + J = 1 + DO IC = 1,SIZE(ChanUnit) + DO I=1,LenName + ChanUnitASCII(J) = IACHAR( ChanUnit(IC)(I:I) ) + J = J + 1 + END DO + END DO + + !............................................................................................................................... + ! Find the range of our output channels + !............................................................................................................................... +!BJJ: This scaling has issues if the channel contains NaN. + + + + IF ( FileID == FileFmtID_WithTime ) THEN + TimeMin = TimeData(1) ! Initialize the Min time value + TimeMax = MAX(TimeData(1),TimeData(NT)) ! Initialize the Max time value + + DO IT=2,NT ! Loop through the remaining time steps + IF ( TimeData(IT) > TimeMax ) THEN + TimeMax = TimeData(IT) + ELSEIF ( TimeData(IT) < TimeMin ) THEN + TimeMin = TimeData(IT) + ENDIF + ENDDO !IT + + IF ( TimeMax == TimeMin ) THEN + TimeScl = 1 + ELSE + TimeScl = Int32Rng/REAL( TimeMax - TimeMin, R8Ki ) + ENDIF + + TimeOff = Int32Min - TimeScl*REAL( TimeMin, R8Ki ) + + ! Pack the time into 32-bit integers + DO IT=1,NT ! Loop through the time steps + TmpTimeArray(IT) = NINT( Max( Min( REAL( TimeScl*TimeData(IT) + TimeOff, R8Ki), Int32Max ), Int32Min) , B4Ki ) + ENDDO !IT + + + ELSE ! FileFmtID_WithoutTime and FileFmtID_NoCompressWithoutTime + ! Convert DbKi to R8Ki, if necessary + TimeOut1 = TimeData(1) ! The first output time + TimeIncrement = TimeData(2) ! The time increment + END IF ! FileID + + IF ( FileID /= FileFmtID_NoCompressWithoutTime ) THEN + + ColMin(:) = AllOutData(:,1_IntKi) ! Initialize the Min values for each channel + ColMax(:) = AllOutData(:,1_IntKi) ! Initialize the Max values for each channel + + DO IT=2,NT ! Loop through the remaining time steps + DO IC=1,NumOutChans ! Loop through the output channels + IF ( AllOutData(IC,IT) > ColMax(IC) ) THEN + ColMax(IC) = AllOutData(IC,IT) + ELSEIF ( AllOutData(IC,IT) < ColMin(IC) ) THEN + ColMin(IC) = AllOutData(IC,IT) + ENDIF + ENDDO !IC + ENDDO !IT + + !............................................................................................................................... + ! Calculate the scaling parameters for each channel + !............................................................................................................................... + DO IC=1,NumOutChans ! Loop through the output channels + IF ( ColMax(IC) == ColMin(IC) ) THEN + ColScl(IC) = IntRng/SQRT(EPSILON(1.0_SiKi)) + ELSE + ColScl(IC) = IntRng/REAL( ColMax(IC) - ColMin(IC), SiKi ) + ENDIF + ColOff(IC) = IntMin - ColScl(IC)*REAL( ColMin(IC), SiKi ) + ENDDO !IC + + ENDIF + + !............................................................................................................................... + ! Convert channels to 16-bit integers (packed binary) or (R8Ki if unpacked binary) + !............................................................................................................................... + J = 1 + DO IT=1,NT ! Loop through the time steps + DO IC=1,NumOutChans ! Loop through the output channels + IF ( FileID == FileFmtID_NoCompressWithoutTime ) THEN + TmpR8OutArray(J) = REAL( AllOutData(IC,IT), R8Ki ) + ELSE + TmpOutArray(J) = NINT( Max( Min( REAL( ColScl(IC)*AllOutData(IC,IT) + ColOff(IC), SiKi), IntMax ), IntMin) , B2Ki ) + END IF + J = J + 1 + ENDDO !IC + ENDDO !IT + + !............................................................................................................................... + ! Write the output file header + !............................................................................................................................... + WRITE (UnIn, IOSTAT=ErrStat2) INT( FileID , B2Ki ) ! FAST output file format + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing FileID to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + IF (FileID==FileFmtID_ChanLen_In) THEN + WRITE (UnIn, IOSTAT=ErrStat2) INT( LenName , B2Ki ) ! Length of channel names + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing ChanLen to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) INT( NumOutChans , B4Ki ) ! The number of output channels + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing NumOutChans to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) INT( NT , B4Ki ) ! The number of time steps + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing NT to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + IF ( FileID == FileFmtID_WithTime ) THEN + ! Write the slope and offset for the time channel + + WRITE (UnIn, IOSTAT=ErrStat2) TimeScl ! The time slope for scaling + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TimeScl to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) TimeOff ! The time offset for scaling + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TimeOff to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + ELSE ! FileFmtID_WithoutTime and FileFmtID_NoCompressWithoutTime + ! Write the first output time and the time step + + WRITE (UnIn, IOSTAT=ErrStat2) TimeOut1 ! The first output time + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TimeOut1 to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) TimeIncrement ! The time increment (between subsequent outputs) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing TimeIncrement to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + END IF + + IF ( FileID /= FileFmtID_NoCompressWithoutTime ) THEN + + WRITE (UnIn, IOSTAT=ErrStat2) ColScl(:) ! The channel slopes for scaling + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing ColScl to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) ColOff(:) ! The channel offsets for scaling + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing ColOff to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) INT( LenDesc , B4Ki ) ! The number of characters in the string + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing LenDesc to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) DescStrASCII ! DescStr converted to ASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing file description to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + WRITE (UnIn, IOSTAT=ErrStat2) ChanNameASCII ! ChanName converted to ASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing channel names to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + + WRITE (UnIn, IOSTAT=ErrStat2) ChanUnitASCII ! ChanUnit converted to ASCII + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing channel units to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + !............................................................................................................................... + ! Write the channel data + !............................................................................................................................... + IF ( FileID == FileFmtID_WithTime ) THEN + WRITE (UnIn, IOSTAT=ErrStat2) TmpTimeArray ! TimeData converted to packed binary (32-bit) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing time data to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + END IF ! FileID + + IF ( FileID == FileFmtID_NoCompressWithoutTime ) THEN + WRITE (UnIn, IOSTAT=ErrStat2) TmpR8OutArray ! AllOutData + ELSE + WRITE (UnIn, IOSTAT=ErrStat2) TmpOutArray ! AllOutData converted to packed binary (16-bit) + END IF + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error writing channel data to the FAST binary file.', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup( ) + RETURN + END IF + + !............................................................................................................................... + ! We're finished: clean up ALLOCATABLE arrays and close the file + !............................................................................................................................... + + CALL Cleanup() + RETURN + +!.................................................................................................................................. + CONTAINS + !............................................................................................................................ + SUBROUTINE Cleanup() + ! This subroutine cleans up all the allocatable arrays and closes the binary file. + !............................................................................................................................ + + ! Deallocate local arrays: + IF ( ALLOCATED( ColMax ) ) DEALLOCATE( ColMax ) + IF ( ALLOCATED( ColMin ) ) DEALLOCATE( ColMin ) + IF ( ALLOCATED( ColOff ) ) DEALLOCATE( ColOff ) + IF ( ALLOCATED( ColScl ) ) DEALLOCATE( ColScl ) + IF ( ALLOCATED( TmpTimeArray ) ) DEALLOCATE( TmpTimeArray ) + IF ( ALLOCATED( TmpOutArray ) ) DEALLOCATE( TmpOutArray ) + IF ( ALLOCATED( TmpR8OutArray ) ) DEALLOCATE( TmpR8OutArray ) + IF ( ALLOCATED( DescStrASCII ) ) DEALLOCATE( DescStrASCII ) + IF ( ALLOCATED( ChanNameASCII ) ) DEALLOCATE( ChanNameASCII ) + IF ( ALLOCATED( ChanUnitASCII ) ) DEALLOCATE( ChanUnitASCII ) + + ! Close file: + CLOSE ( UnIn ) + + END SUBROUTINE Cleanup + !............................................................................................................................... + END SUBROUTINE WrBinFAST +!================================================================================================================================== +!> This routine writes out a string to the file connected to Unit without following it with a new line. + SUBROUTINE WrFileNR ( Unit, Str ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Unit ! I/O unit for input file. + + CHARACTER(*), INTENT(IN) :: Str ! String to be written without a newline at the end. + + + + WRITE (Unit,'(A)',ADVANCE='NO') Str + + + RETURN + END SUBROUTINE WrFileNR +!======================================================================= +!> This routine writes all the values of a 1- or 2-dimensional array, A, +!! of real numbers to unit Un, using ReFmt for each individual value +!! in the array. If MatName is present, it also preceeds the matrix +!! with "MatName" and the number of rows (dimension 1 of A) and columns (dimension 2 of A). +!! It is useful for debugging and/or writing summary files. +!! Use WrMatrix (nwtc_io::wrmatrix) instead of directly calling a specific routine in the generic interface. + SUBROUTINE WrMatrix1R4( A, Un, ReFmt, MatName ) + + + REAL(SiKi), INTENT(IN) :: A(:) !< vector/matrix to be written + INTEGER, INTENT(IN) :: Un !< Fortran unit number where matrix will be written + CHARACTER(*), INTENT(IN) :: ReFmt !< Format for printing numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName !< name of matrix + + INTEGER :: ErrStat + INTEGER :: nr ! size (rows and columns) of A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), "1" + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nr))//"(1x,"//ReFmt//"))" + + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix1R4().') + RETURN + END IF + + RETURN + END SUBROUTINE WrMatrix1R4 +!======================================================================= +!> \copydoc nwtc_io::wrmatrix1r4 + SUBROUTINE WrMatrix1R8( A, Un, ReFmt, MatName ) + + REAL(R8Ki), INTENT(IN) :: A(:) + INTEGER, INTENT(IN) :: Un + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName + + INTEGER :: ErrStat + INTEGER :: nr ! size (rows and columns) of A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), "1" + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nr))//"(1x,"//ReFmt//"))" + + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix1R8().') + RETURN + END IF + + RETURN + END SUBROUTINE WrMatrix1R8 +!======================================================================= +!> \copydoc nwtc_io::wrmatrix1r4 + SUBROUTINE WrMatrix1R16( A, Un, ReFmt, MatName ) + + REAL(QuKi), INTENT(IN) :: A(:) + INTEGER, INTENT(IN) :: Un + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName + + INTEGER :: ErrStat + INTEGER :: nr ! size (rows and columns) of A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), "1" + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nr))//"(1x,"//ReFmt//"))" + + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix1R16().') + RETURN + END IF + + RETURN + END SUBROUTINE WrMatrix1R16 +!======================================================================= +!> \copydoc nwtc_io::wrmatrix1r4 + SUBROUTINE WrMatrix2R4( A, Un, ReFmt, MatName ) + + REAL(SiKi), INTENT(IN) :: A(:,:) + INTEGER, INTENT(IN) :: Un + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName + + INTEGER :: ErrStat + INTEGER :: nr, nc ! size (rows and columns) of A + INTEGER :: i ! indices into A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + nc = SIZE(A,2) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), TRIM(Num2LStr(nc)) + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nc))//"(1x,"//ReFmt//"))" + + DO i=1,nr + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(i,:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix2R4().') + RETURN + END IF + + + END DO + + RETURN + END SUBROUTINE WrMatrix2R4 +!======================================================================= +!> \copydoc nwtc_io::wrmatrix1r4 + SUBROUTINE WrMatrix2R8( A, Un, ReFmt, MatName ) + + REAL(R8Ki), INTENT(IN) :: A(:,:) + INTEGER, INTENT(IN) :: Un + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName + + INTEGER :: ErrStat + INTEGER :: nr, nc ! size (rows and columns) of A + INTEGER :: i ! indices into A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + nc = SIZE(A,2) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), TRIM(Num2LStr(nc)) + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nc))//"(1x,"//ReFmt//"))" + + DO i=1,nr + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(i,:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix2R8().') + RETURN + END IF + + + END DO + + RETURN + END SUBROUTINE WrMatrix2R8 +!======================================================================= +!> \copydoc nwtc_io::wrmatrix1r4 + SUBROUTINE WrMatrix2R16( A, Un, ReFmt, MatName ) + + REAL(QuKi), INTENT(IN) :: A(:,:) + INTEGER, INTENT(IN) :: Un + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), OPTIONAL, INTENT(IN) :: MatName + + INTEGER :: ErrStat + INTEGER :: nr, nc ! size (rows and columns) of A + INTEGER :: i ! indices into A + CHARACTER(256) :: Fmt + + + nr = SIZE(A,1) + nc = SIZE(A,2) + + IF ( PRESENT(MatName) ) THEN + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), TRIM(Num2LStr(nc)) + END IF + + Fmt = "(2x, "//TRIM(Num2LStr(nc))//"(1x,"//ReFmt//"))" + + DO i=1,nr + WRITE( Un, Fmt, IOSTAT=ErrStat ) A(i,:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix2R16().') + RETURN + END IF + + + END DO + + RETURN + END SUBROUTINE WrMatrix2R16 +!======================================================================= +!> Based on nwtc_io::wrmatrix, this routine writes a matrix to an already-open text file. It allows +!! the user to omit rows and columns of A in the the file. +!! Use WrPartialMatrix (nwtc_io::wrpartialmatrix) instead of directly calling a specific routine in the generic interface. + SUBROUTINE WrPartialMatrix1R8( A, Un, ReFmt, MatName, UseCol, UseAllCols, ExtCol ) + + REAL(R8Ki), INTENT(IN) :: A(:) !< matrix to write + INTEGER, INTENT(IN) :: Un !< unit where matrix will be written + CHARACTER(*), INTENT(IN) :: ReFmt !< Format for printing ReKi numbers + CHARACTER(*), INTENT(IN) :: MatName !< name of the matrix to write + LOGICAL, OPTIONAL, INTENT(IN) :: UseCol(:) !< must be size(A,2); this routine will print only the columns where UseCol is true + LOGICAL, OPTIONAL, INTENT(IN) :: UseAllCols !< a scalar that, if set to true, overrides UseCol and will print all columns + REAL(R8Ki), OPTIONAL, INTENT(IN) :: ExtCol(:) !< columns to add to the end of matrix A + + INTEGER :: ErrStat + INTEGER :: nc ! size (rows and columns) of A + INTEGER :: j ! indices into A + INTEGER :: jc ! index into ThisRow + CHARACTER(256) :: Fmt + LOGICAL :: UseAllCols2 + REAL(R8Ki), ALLOCATABLE :: ThisRow(:) + + + UseAllCols2 = .false. + if (.not. present(UseCol)) then + UseAllCols2 = .true. + else + if (present(UseAllCols)) then + if (UseAllCols) UseAllCols2 = .true. + end if + end if + + ! how many columns will we print? + if (UseAllCols2) then + nc = SIZE(A) ! default number of columns + else + nc = 0 + do j = 1,size(A) + if (UseCol(j)) nc = nc + 1 + end do + end if + if (present(ExtCol)) nc = nc + size(ExtCol) + + + + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), '1', TRIM(Num2LStr(nc)) + + Fmt = "(2x, "//TRIM(Num2LStr(nc))//"(1x,"//ReFmt//"))" + + ALLOCATE(ThisRow(nc), STAT=ErrStat) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' allocating temporary row WrPartialMatrix1().') + RETURN + END IF + + + if (UseAllCols2) then + ThisRow = A + else + jc = 1 + do j = 1,size(A) + if (UseCol(j)) then + ThisRow(jc) = A(j) + jc = jc + 1 + end if + end do + if (present(ExtCol)) ThisRow(jc:) = ExtCol(:) + end if + + WRITE( Un, Fmt, IOSTAT=ErrStat ) ThisRow + IF (ErrStat /= 0) THEN + deallocate(ThisRow) + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrPartialMatrix1().') + RETURN + END IF + + deallocate(ThisRow) + RETURN + END SUBROUTINE WrPartialMatrix1R8 +!======================================================================= +!> \copydoc nwtc_io::wrpartialmatrix1r8 + SUBROUTINE WrPartialMatrix2R8( A, Un, ReFmt, MatName, UseRow, UseCol, UseAllRows, UseAllCols, ExtCol ) + + REAL(R8Ki), INTENT(IN) :: A(:,:) ! matrix to write + INTEGER, INTENT(IN) :: Un ! unit where matrix will be written + CHARACTER(*), INTENT(IN) :: ReFmt ! Format for printing ReKi numbers + CHARACTER(*), INTENT(IN) :: MatName ! name of the matrix to write + LOGICAL, OPTIONAL, INTENT(IN) :: UseRow(:) !< must be size(A,1); this routine will print only the rows where UseRow is true + LOGICAL, OPTIONAL, INTENT(IN) :: UseCol(:) ! must be size(A,2); this routine will print only the columns where UseCol is true + LOGICAL, OPTIONAL, INTENT(IN) :: UseAllRows !< a scalar that, if set to true, overrides UseRow and will print all rows + LOGICAL, OPTIONAL, INTENT(IN) :: UseAllCols ! a scalar that, if set to true, overrides UseCol and will print all columns + REAL(R8Ki), OPTIONAL, INTENT(IN) :: ExtCol(:,:) ! columns to add to the end of matrix A + + INTEGER :: ErrStat + INTEGER :: nr, nc ! size (rows and columns) of A + INTEGER :: i, j ! indices into A + INTEGER :: jc ! index into ThisRow + CHARACTER(256) :: Fmt + LOGICAL :: UseAllRows2 + LOGICAL :: UseAllCols2 + REAL(R8Ki), ALLOCATABLE :: ThisRow(:) + + + UseAllRows2 = .false. + if (.not. present(UseRow)) then + UseAllRows2 = .true. + else + if (present(UseAllRows)) then + if (UseAllRows) UseAllRows2 = .true. + end if + end if + + UseAllCols2 = .false. + if (.not. present(UseCol)) then + UseAllCols2 = .true. + else + if (present(UseAllCols)) then + if (UseAllCols) UseAllCols2 = .true. + end if + end if + + ! how many rows will we print? + if (UseAllRows2) then + nr = SIZE(A,1) ! default number of rows + else + nr = 0 + do i = 1,size(A,1) + if (UseRow(i)) nr = nr + 1 + end do + end if + + + ! how many columns will we print? + if (UseAllCols2) then + nc = SIZE(A,2) ! default number of columns + else + nc = 0 + do j = 1,size(A,2) + if (UseCol(j)) nc = nc + 1 + end do + end if + + if (present(ExtCol)) nc = nc + size(ExtCol,2) + + + if (nr == 0 .or. nc == 0) return !don't print anything if the matrix is empty + + + + WRITE( Un, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) TRIM(MatName), TRIM(Num2LStr(nr)), TRIM(Num2LStr(nc)) + + Fmt = "(2x, "//TRIM(Num2LStr(nc))//"(1x,"//ReFmt//"))" + + ALLOCATE(ThisRow(nc), STAT=ErrStat) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' allocating temporary row WrPartialMatrix2().') + RETURN + END IF + + + DO i=1,size(A,1) ! loop through rows + + if ( .not. UseAllRows2 ) then + if (.not. UseRow(i)) cycle ! skip this row + end if + + if (UseAllCols2) then + ThisRow(1:size(A,2)) = A(i,:) + if (present(ExtCol)) ThisRow(size(A,2)+1:) = ExtCol(i,:) + else + jc = 1 + do j = 1,size(A,2) + if (UseCol(j)) then + ThisRow(jc) = A(i,j) + jc = jc + 1 + end if + end do + if (present(ExtCol)) ThisRow(jc:) = ExtCol(i,:) + end if + + WRITE( Un, Fmt, IOSTAT=ErrStat ) ThisRow + IF (ErrStat /= 0) THEN + deallocate(ThisRow) + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrPartialMatrix2().') + RETURN + END IF + + + END DO + + deallocate(ThisRow) + RETURN + END SUBROUTINE WrPartialMatrix2R8 +!======================================================================= +!> This routine writes out a prompt to the screen without +!! following it with a new line, though a new line precedes it. + SUBROUTINE WrPr ( Str ) + + ! Argument declarations: + + CHARACTER(*), INTENT(IN) :: Str !< The prompt string to print. + + + + CALL WrScr ( ' ' ) + CALL WrNR ( TRIM( Str )//' > ' ) + + + RETURN + END SUBROUTINE WrPr +!======================================================================= +!> This routine writes out a real array to the file connected to Unit without following it with a new line. +!! Use WrNumAryFileNR (nwtc_io::wrnumaryfilenr) instead of directly calling a specific routine in the generic interface. + SUBROUTINE WrR4AryFileNR ( Unit, Ary, Fmt, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Unit !< I/O unit for input file. + REAL(SiKi), INTENT(IN) :: Ary (:) !< Array to be written without a newline at the end. + CHARACTER(*), INTENT(IN) :: Fmt !< Fmt of one element to be written. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with ErrStat + + ! Local variables: + CHARACTER(50) :: Fmt2 ! Fmt of entire array to be written (will be copied). + + + + IF ( SIZE(Ary) == 0 ) THEN + ErrStat = ErrID_None + ErrMsg = '' + RETURN + END IF + + + WRITE(Fmt2,*) SIZE(Ary) + Fmt2 = '('//TRIM(Fmt2)//'('//TRIM(Fmt)//'))' + + WRITE (Unit,Fmt2,ADVANCE='NO',IOSTAT=ErrStat) Ary + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'WrR4AryFileNR:Error '//TRIM(Num2LStr(ErrStat))//' occurred while writing to file using this format: '//TRIM(Fmt2) + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE WrR4AryFileNR +!======================================================================= +!> This routine writes out an integer array to the file connected to Unit without following it with a new line. +!! Use WrNumAryFileNR (nwtc_io::wrnumaryfilenr) instead of directly calling a specific routine in the generic interface. + SUBROUTINE WrIAryFileNR ( Unit, Ary, Fmt, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Unit !< I/O unit for input file. + INTEGER(IntKi), INTENT(IN) :: Ary (:) !< Array to be written without a newline at the end. + CHARACTER(*), INTENT(IN) :: Fmt !< Fmt of one element to be written. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message associated with ErrStat + + ! Local variables: + CHARACTER(50) :: Fmt2 ! Fmt of entire array to be written (will be copied). + + + + IF ( SIZE(Ary) == 0 ) THEN + ErrStat = ErrID_None + ErrMsg = '' + RETURN + END IF + + + WRITE(Fmt2,*) SIZE(Ary) + Fmt2 = '('//TRIM(Fmt2)//'('//TRIM(Fmt)//'))' + + WRITE (Unit,Fmt2,ADVANCE='NO',IOSTAT=ErrStat) Ary + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'WrIAryFileNR:Error '//TRIM(Num2LStr(ErrStat))//' occurred while writing to file using this format: '//TRIM(Fmt2) + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE WrIAryFileNR +!======================================================================= +!> \copydoc nwtc_io::wrr4aryfilenr + SUBROUTINE WrR8AryFileNR ( Unit, Ary, Fmt, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Unit ! I/O unit for input file. + REAL(R8Ki), INTENT(IN) :: Ary (:) ! Array to be written without a newline at the end. + CHARACTER(*), INTENT(IN) :: Fmt ! Fmt of one element to be written. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + ! Local variables: + CHARACTER(50) :: Fmt2 ! Fmt of entire array to be written (will be copied). + + + + IF ( SIZE(Ary) == 0 ) THEN + ErrStat = ErrID_None + ErrMsg = '' + RETURN + END IF + + + WRITE(Fmt2,*) SIZE(Ary) + Fmt2 = '('//TRIM(Fmt2)//'('//TRIM(Fmt)//'))' + + WRITE (Unit,Fmt2,ADVANCE='NO',IOSTAT=ErrStat) Ary + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'WrR8AryFileNR:Error '//TRIM(Num2LStr(ErrStat))//' occurred while writing to file using this format: '//TRIM(Fmt2) + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE WrR8AryFileNR +!======================================================================= +!> \copydoc nwtc_io::wrr4aryfilenr + SUBROUTINE WrR16AryFileNR ( Unit, Ary, Fmt, ErrStat, ErrMsg ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Unit ! I/O unit for input file. + REAL(QuKi), INTENT(IN) :: Ary (:) ! Array to be written without a newline at the end. + CHARACTER(*), INTENT(IN) :: Fmt ! Fmt of one element to be written. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message associated with ErrStat + + ! Local variables: + CHARACTER(50) :: Fmt2 ! Fmt of entire array to be written (will be copied). + + + + IF ( SIZE(Ary) == 0 ) THEN + ErrStat = ErrID_None + ErrMsg = '' + RETURN + END IF + + + WRITE(Fmt2,*) SIZE(Ary) + Fmt2 = '('//TRIM(Fmt2)//'('//TRIM(Fmt)//'))' + + WRITE (Unit,Fmt2,ADVANCE='NO',IOSTAT=ErrStat) Ary + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'WrR16AryFileNR:Error '//TRIM(Num2LStr(ErrStat))//' occurred while writing to file using this format: '//TRIM(Fmt2) + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + + RETURN + END SUBROUTINE WrR16AryFileNR +!======================================================================= +!> This routine writes out a string to the screen. + RECURSIVE SUBROUTINE WrScr ( InStr ) + + + IMPLICIT NONE + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: InStr !< The input string to write to the screen. + + + ! Local declarations. + + INTEGER :: Beg ! The beginning of the next line of text. + INTEGER :: Indent ! The amunt to be indented. + INTEGER :: LStr ! The length of the remaining portion of the string. + INTEGER :: MaxLen ! Maximum number of columns to be written to the screen. + INTEGER :: NewLineIndx ! The string index where the NewLine character occurs + + CHARACTER(10) :: Frm ! Format specifier for the output. + CHARACTER(LEN(InStr)) :: Str ! The next string to be processed + + + + Str = InStr + + ! Check if we are writing multiple lines: + + NewLineIndx = INDEX( Str, NewLine, BACK=.TRUE. ) + IF ( NewLineIndx > 0 ) THEN ! The user requested a new line + IF ( NewLineIndx == 1 ) THEN ! The first character is a new line, so write a blank line + CALL WrScr( '' ) + ELSE + CALL WrScr( Str(:NewLineIndx-1) ) ! Write everything up to the new line (recursively) + END IF + Str = Str( (NewLineIndx + LEN(NewLine)): ) ! Remove the part we already wrote to the screen (also remove the NewLine character) + END IF + + + ! Find the amount of indent. Create format. + + MaxLen = MaxWrScrLen + Indent = LEN_TRIM( Str ) - LEN_TRIM( ADJUSTL( Str ) ) + Indent = MIN( Indent, MaxLen-2 ) ! at least 2 characters per line + MaxLen = MaxLen - Indent + IF ( Indent > 0 ) THEN + Frm = '(1X, X,A)' + WRITE (Frm(5:6),'(I2)') Indent + ELSE + Frm = '(1X,A)' + END IF + + + ! Break long messages into multiple lines. + + Beg = Indent + 1 + LStr = LEN_TRIM( Str(Beg:) ) + + + + DO WHILE ( Lstr > MaxLen ) + + CALL FindLine ( Str(Beg:) , MaxLen , LStr ) + + CALL WriteScr( TRIM( ADJUSTL( Str(Beg:Beg+LStr-1) ) ), Frm ) + + Beg = Beg + LStr + + + ! If we have a space at the beginning of the string, let's get rid of it + + DO WHILE ( Beg < LEN_TRIM( Str ) .AND. Str(Beg:Beg) == ' ' ) + Beg = Beg + 1 + ENDDO + + LStr = LEN_TRIM( Str(Beg:) ) + + ENDDO + + CALL WriteScr( TRIM( ADJUSTL( Str(Beg:Beg+LStr-1) ) ), Frm ) + + + RETURN + END SUBROUTINE WrScr +!======================================================================= +!> This routine writes out a string to the screen after a blank line. + SUBROUTINE WrScr1 ( Str ) + + ! This routine is DEPRECATED. Call WrScr directly instead. + + ! Argument declarations. + + CHARACTER(*) :: Str !< The string to print. + + + CALL WrScr( NewLine//TRIM( Str ) ) + + + RETURN + END SUBROUTINE WrScr1 +!======================================================================= +!> This routine writes out the heading for an vtk xml file (associated footer generated in +!! nwtc_io::wrvtk_footer). It tries to open a text file for writing and returns the Unit number of the opened file. + SUBROUTINE WrVTK_header( FileName, NumberOfPoints, NumberOfLines, NumberOfPolys, Un, ErrStat, ErrMsg ) + + CHARACTER(*) , INTENT(IN ) :: FileName !< Name of output file + INTEGER(IntKi) , INTENT(IN ) :: NumberOfPoints !< Number of points in this VTK file + INTEGER(IntKi) , INTENT(IN ) :: NumberOfLines !< Number of lines in this VTK file + INTEGER(IntKi) , INTENT(IN ) :: NumberOfPolys !< Number of polygons in this VTK file + INTEGER(IntKi) , INTENT( OUT) :: Un !< unit number of opened file + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + + CALL GetNewUnit( Un, ErrStat, ErrMsg ) + CALL OpenFOutFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + + ! Write a VTP mesh file (Polygonal VTK file) with positions and polygons (surfaces) + ! (note alignment of WRITE statements to make sure spaces are lined up in XML file) + WRITE(Un,'(A)') '<?xml version="1.0"?>' + WRITE(Un,'(A)') '<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian">' ! bjj note: we don't have binary data in this file, so byte_order shouldn't matter, right? + WRITE(Un,'(A)') ' <PolyData>' + WRITE(Un,'(2(A,i7),A)') ' <Piece NumberOfPoints="', NumberOfPoints, '" NumberOfVerts=" 0" NumberOfLines="', NumberOfLines, '"' + WRITE(Un,'(A,i7,A)') ' NumberOfStrips=" 0" NumberOfPolys="', NumberOfPolys, '">' + + RETURN + END SUBROUTINE WrVTK_header +!======================================================================= +!> This routine writes out the footer for an vtk xml file (associated header generated +!! in nwtc_io::wrvtk_header). It closes the file Un. + SUBROUTINE WrVTK_footer( Un ) + + INTEGER(IntKi) , INTENT(IN ) :: Un !< unit number of opened file + + WRITE(Un,'(A)') ' </Piece>' + WRITE(Un,'(A)') ' </PolyData>' + WRITE(Un,'(A)') '</VTKFile>' + CLOSE(Un) + + RETURN + END SUBROUTINE WrVTK_footer + +!======================================================================= +!> This routine reads the header for a vtk, ascii, structured_points dataset file, +!! including all the information about the structured points. It tries to open a +!! text file for reading and returns the Unit number of the opened file. +!! The caller is responsible for closing the file unit unless caller set Un = -1! + SUBROUTINE ReadVTK_SP_info( FileName, descr, dims, origin, gridSpacing, vecLabel, Un, ErrStat, ErrMsg ) + + CHARACTER(*) , INTENT(IN ) :: FileName !< Name of output file + CHARACTER(1024) , INTENT( OUT) :: descr !< Line describing the contents of the file + INTEGER(IntKi) , INTENT( OUT) :: dims(3) !< dimension of the 3D grid (nX,nY,nZ) + REAL(ReKi) , INTENT( OUT) :: origin(3) !< the lower-left corner of the 3D grid (X0,Y0,Z0) + REAL(ReKi) , INTENT( OUT) :: gridSpacing(3) !< spacing between grid points in each of the 3 directions (dX,dY,dZ) + CHARACTER(1024) , INTENT( OUT) :: vecLabel + INTEGER(IntKi) , INTENT(INOUT) :: Un !< unit number of opened file + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + + INTEGER(IntKi) :: ErrStat2 ! local error level/status of OpenFOutFile operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local message when error occurs + CHARACTER(1024) :: Line, Line2 ! one line of the file + CHARACTER(1024) :: formatLbl + CHARACTER(*), PARAMETER :: RoutineName = 'ReadVTK_SP_info' + INTEGER(IntKi) :: sz, nPts + LOGICAL :: closeOnReturn + + ErrStat = ErrID_None + ErrMsg = '' + + IF (Un == -1 ) THEN + closeOnReturn = .TRUE. + ELSE + closeOnReturn = .FALSE. + END IF + + CALL GetNewUnit( Un, ErrStat, ErrMsg ) + CALL OpenFInpFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + + CALL ReadCom( Un, FileName, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, 0 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadStr( Un, FileName, descr, 'descr', 'File Description line', ErrStat2, ErrMsg2, 0 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + formatLbl = "" + CALL ReadStr( Un, FileName, formatLbl, 'formatLbl', 'ASCII label', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call Conv2UC(formatLbl) + if (INDEX(formatLbl, "ASCII" ) /= 1 ) THEN ! If this line doesn't contain the word ASCII, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find ASCII label', ErrStat, ErrMsg, RoutineName ) + end if + Line = "" + CALL ReadStr( Un, FileName, Line, "dataset", "DATASET STRUCTURED_POINTS", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DATASET" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find DATASET label', ErrStat, ErrMsg, RoutineName ) + END IF + IF ( INDEX(Line, "STRUCTURED_POINTS" ) == 0 ) THEN ! If this line doesn't also contain the word structured_points, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find STRUCTURED_POINTS label', ErrStat, ErrMsg, RoutineName ) + end if + + ! Dimensions + Line = "" + CALL ReadStr( Un, FileName, Line, "Dimensions", "DIMENSIONS data", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = trim(Line) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DIMENSIONS" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find DIMENSIONS label', ErrStat, ErrMsg, RoutineName ) + ELSE + sz = len(Line) + Line = Line(12:sz) + READ(Line,*, IOSTAT=ErrStat2) dims + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, 'Error reading "dims".', ErrStat, ErrMsg, RoutineName ) + end if + END IF + + ! Origin + Line = "" + CALL ReadStr( Un, FileName, Line, "Origin", "ORIGIN data", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = trim(Line) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "ORIGIN" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find ORIGIN label', ErrStat, ErrMsg, RoutineName ) + ELSE + sz = len(Line) + Line = Line(8:sz) + READ(Line,*, IOSTAT=ErrStat2) origin + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, 'Error reading "origin".', ErrStat, ErrMsg, RoutineName ) + end if + + END IF + + ! Spacing + Line = "" + CALL ReadStr( Un, FileName, Line, "gridSpacing", "SPACING data", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = trim(Line) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "SPACING" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find SPACING label', ErrStat, ErrMsg, RoutineName ) + ELSE + sz = len(Line) + Line = Line(9:sz) + READ(Line,*,IOSTAT=ErrStat2) gridSpacing + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, 'Error reading "gridSpacing".', ErrStat, ErrMsg, RoutineName ) + end if + + END IF + + ! Point Data + Line = "" + CALL ReadStr( Un, FileName, Line, "Point_Data", "POINT_DATA", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = trim(Line) + CALL Conv2UC( Line ) + IF ( INDEX(Line, "POINT_DATA" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find POINT_DATA label', ErrStat, ErrMsg, RoutineName ) + ELSE + sz = len(Line) + Line = Line(12:sz) + READ(Line,*,IOSTAT=ErrStat2) nPts + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, 'Error reading "nPts".', ErrStat, ErrMsg, RoutineName ) + end if + END IF + + ! Vector Label + Line = "" + CALL ReadStr( Un, FileName, Line, "Vectors", "VECTORS label", ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + Line = trim(Line) + Line2 = Line + CALL Conv2UC( Line2 ) + IF ( INDEX(Line2, "VECTORS" ) /= 1 ) THEN ! If this line doesn't contain the word dataset, we have a bad file header + CALL SetErrStat( ErrID_Fatal, 'Invalid vtk structured_points file: did not find VECTORS label', ErrStat, ErrMsg, RoutineName ) + ELSE + sz = INDEX(Line2, "FLOAT" ) + IF ( sz == 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Invalid VECTORS datatype. Must be set to float.', ErrStat, ErrMsg, RoutineName ) + ELSE + vecLabel = Line(9:sz-2) + END IF + END IF + + IF ( (ErrStat >= AbortErrLev) .or. closeOnReturn ) THEN + close(Un) + Un = -1 + RETURN + END IF + + RETURN + END SUBROUTINE ReadVTK_SP_info + +!======================================================================= +!> This routine reads the vector data for a vtk, ascii, structured_points dataset file, +!! The Unit number of the file is already assumed to be valid via a previous call to +!! ReadVTK_SP_info. + SUBROUTINE ReadVTK_SP_vectors( Un, dims, gridVals, ErrStat, ErrMsg ) + + INTEGER(IntKi) , INTENT(IN ) :: Un !< unit number of opened file + INTEGER(IntKi) , INTENT(IN ) :: dims(3) !< dimension of the 3D grid (nX,nY,nZ) + REAL(ReKi) , INTENT( OUT) :: gridVals(:,:,:,:) !< 4D array of data, size (3,nX,nY,nZ), must be pre-allocated + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + + INTEGER(IntKi) :: ErrStat2 ! local error level/status of OpenFOutFile operation + CHARACTER(*), PARAMETER :: RoutineName = 'ReadVTK_SP_vectors' + + ErrStat = ErrID_None + ErrMsg = '' + + READ(Un,*, IOSTAT=ErrStat2) gridVals(1:3,1:dims(1),1:dims(2),1:dims(3)) + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, 'Error reading vector data.', ErrStat, ErrMsg, RoutineName ) + end if + + close(Un) + + END SUBROUTINE ReadVTK_SP_vectors + +!======================================================================= +!> This routine writes out the heading for an vtk, ascii, structured_points dataset file . +!! It tries to open a text file for writing and returns the Unit number of the opened file. + SUBROUTINE WrVTK_SP_header( FileName, descr, Un, ErrStat, ErrMsg ) + + CHARACTER(*) , INTENT(IN ) :: FileName !< Name of output file + CHARACTER(*) , INTENT(IN ) :: descr !< Line describing the contents of the file + INTEGER(IntKi) , INTENT( OUT) :: Un !< unit number of opened file + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + + CALL GetNewUnit( Un, ErrStat, ErrMsg ) + CALL OpenFOutFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + + WRITE(Un,'(A)') '# vtk DataFile Version 3.0' + WRITE(Un,'(A)') trim(descr) + WRITE(Un,'(A)') 'ASCII' + WRITE(Un,'(A)') 'DATASET STRUCTURED_POINTS' + + RETURN + END SUBROUTINE WrVTK_SP_header + + + + SUBROUTINE WrVTK_SP_vectors3D( Un, dataDescr, dims, origin, gridSpacing, gridVals, ErrStat, ErrMsg ) + + INTEGER(IntKi) , INTENT(IN ) :: Un !< unit number of previously opened file (via call to WrVTK_SP_header) + CHARACTER(*) , INTENT(IN ) :: dataDescr !< Short label describing the vector data + INTEGER(IntKi) , INTENT(IN ) :: dims(3) !< dimension of the 3D grid (nX,nY,nZ) + REAL(ReKi) , INTENT(IN ) :: origin(3) !< the lower-left corner of the 3D grid (X0,Y0,Z0) + REAL(ReKi) , INTENT(IN ) :: gridSpacing(3) !< spacing between grid points in each of the 3 directions (dX,dY,dZ) + REAL(ReKi) , INTENT(IN ) :: gridVals(:,:,:,:) !< 3D array of data, size (nX,nY,nZ) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + + INTEGER(IntKi) :: nPts ! Total number of grid points + + if ( .not. (Un > 0) ) then + ErrStat = ErrID_Fatal + ErrMsg = 'WrVTK_SP_points: Invalid file unit, be sure to call WrVTK_SP_header prior to calling WrVTK_SP_points.' + return + end if + + ErrStat = ErrID_None + ErrMsg = '' + nPts = dims(1)*dims(2)*dims(3) + + ! Note: gridVals must be stored such that the left-most dimension is X and the right-most dimension is Z + WRITE(Un,'(A,3(i5,1X))') 'DIMENSIONS ', dims + WRITE(Un,'(A,3(f10.2,1X))') 'ORIGIN ' , origin + WRITE(Un,'(A,3(f10.2,1X))') 'SPACING ' , gridSpacing + WRITE(Un,'(A,i15)') 'POINT_DATA ', nPts + WRITE(Un,'(A)') 'VECTORS '//trim(dataDescr)//' float' + WRITE(Un,'(3(f10.2,1X))') gridVals + close(Un) + RETURN + + END SUBROUTINE WrVTK_SP_vectors3D + +END MODULE NWTC_IO diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_Library.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_Library.f90 new file mode 100644 index 000000000..232c9c971 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_Library.f90 @@ -0,0 +1,115 @@ +!********************************************************************************************************************************** +! LICENSING +!> Copyright (C) 2013-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. +!! +!> \author Bonnie Jonkman +!> \author Marshall Buhl +!> \author John Michalakes +!********************************************************************************************************************************** +MODULE NWTC_Library + + ! Compiling Notes: + ! ----------------------------------- + ! Your project must include the following files: + ! SingPrec.f90 - Use preprocessor definition DOUBLE_PRECISION to use double-precision arithemitic + ! NWTC_Base.f90 + ! NWTC_IO.f90 + ! NWTC_Library.f90 + ! NWTC_Library_Types.f90 + ! NWTC_Num.f90 + ! ModMesh.f90 + ! ModMesh_Types.f90 + ! + ! If you are not compiling with -DNO_MESHMAPPING, your project must include this file: + ! ModMesh_Mapping.f90 (do not use if compiling with -DNO_MESHMAPPING) + ! + ! Your project must include one, and only one, of the following files: + ! SysIVF.f90 - for Intel Visual Fortran for Windows compiler + ! SysIFL.f90 - for Intel Fortran for Linux compiler + ! SysGnuWin.f90 - for Gnu Fortran for Windows compiler + ! SysGnuLinux.f90 - for Gnu Fortran for Linux compiler + ! SysMatlab.f90 - for Intel Visual Fortran for Windows compiler with Matlab's mex functions for printing + ! SysIVF_Labview.f90 - for Intel Visual Fortran for Windows compiler with references to IFPORT removed and no writing to the screen (uses a file instead) + ! + ! + ! Compilation order for command-line compilation: + ! SingPrec.f90 + ! NWTC_Base.f90 + ! SysIVF.f90 (or other Sys*.f90 file) + ! NWTC_Library_Types.f90 + ! NWTC_IO.f90 + ! NWTC_Num.f90 + ! ModMesh_Types.f90 + ! ModMesh.f90 + ! ModMesh_Mapping.f90 (remove if compiling with -DNO_MESHMAPPING) + ! NWTC_Library.f90 + ! + !> This software uses preprocessor directives, some lines exceed 132 characters, and ModMesh_Mapping.f90 depends on lapack routines. + !! so, you must compile with these options: \n + !! Intel: /fpp /Qmkl:sequential \n + !! Gnu: -x f95-cpp-input -ffree-line-length-none -llapack -lblas + !! note that lapack and blas [binary] libraries must be installed for you to compile the ModMesh_Mapping.f90 file. + !! if you do not wish to use lapack, you can compile using the NO_MESHMAPPING compiler directive: + !! -DNO_MESHMAPPING + ! + !> Usage notes: + !! ----------------------------------- + !! Invoking programs should call NWTC_Init() to initialize data important to the use of the library. Currently, + !! this is used for the NaN, Inf, and Pi-based constants. NWTC_Init also opens the console for writing to the screen. + !! (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_Num ! technically we don't need to specify this if we have ModMesh (because ModMesh USEs NWTC_Num) + USE ModMesh + +#ifndef NO_MESHMAPPING + ! Note that ModMesh_Mapping also includes LAPACK routines + USE ModMesh_Mapping !contains PRIVATE statement so we must also include ModMesh +#endif + + IMPLICIT NONE + + CONTAINS + + SUBROUTINE NWTC_Init( ProgNameIn, ProgVerIn, EchoLibVer ) + ! Initializes use of NWTC library routines. + ! It sets constants (like pi) and opens the console + ! for writing if necessary. If requested, it will also + ! write the NWTC version information to the screen. + + ! passed parameters + LOGICAL, INTENT(IN), OPTIONAL :: EchoLibVer ! A flag to tell NWTC_Init whether to echo the version of the Library to the screen. + CHARACTER(*), INTENT(IN), OPTIONAL :: ProgNameIn ! The name of the program calling the library. (Note, modules should not use this input) + CHARACTER(*), INTENT(IN), OPTIONAL :: ProgVerIn ! The version of the program calling the library. (Note, modules should not use this input) + + ! Initialize ProgName and ProgVer if parameters have been passed + IF ( PRESENT(ProgNameIN) ) ProgName = ProgNameIN + IF ( PRESENT(ProgVerIn) ) ProgVer = ProgVerIn + + ! This routine calls all required initialization routines. + CALL SetConstants() + + !mlb Let's get rid of this once FLUSH works. + !bjj: let's keep it so that we can open files or DLL to write somewhere besides the screen.... (we can get rid of FLUSH from OpenCon, though) + CALL OpenCon( ) + + ! Write the version of the NWTC subroutine library that we are running + IF ( PRESENT(EchoLibVer) ) THEN + IF (EchoLibVer) CALL DispNVD (NWTC_Ver) + ENDIF + + END SUBROUTINE NWTC_Init + +END MODULE NWTC_Library diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_Library_Types.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_Library_Types.f90 new file mode 100644 index 000000000..61640b532 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_Library_Types.f90 @@ -0,0 +1,1458 @@ +!STARTOFREGISTRYGENERATEDFILE 'NWTC_Library_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 +!********************************************************************************************************************************* +! NWTC_Library_Types +!................................................................................................................................. +! This file is part of NWTC_Library. +! +! 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. +! +! +! bjj: modifications made +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in NWTC_Library. 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 NWTC_Library_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE SysSubs +IMPLICIT NONE +! ========= ProgDesc ======= + TYPE, PUBLIC :: ProgDesc + CHARACTER(99) :: Name !< Name of the program or module [-] + CHARACTER(99) :: Ver !< Version number of the program or module [-] + CHARACTER(24) :: Date !< String containing date module was last updated [-] + END TYPE ProgDesc +! ======================= +! ========= FASTdataType ======= + TYPE, PUBLIC :: FASTdataType + CHARACTER(1024) :: File !< Name of the FAST-style binary file [-] + CHARACTER(1024) :: Descr !< String describing file [-] + INTEGER(IntKi) :: NumChans !< Number of output channels in this binary file (not including the time channel) [-] + INTEGER(IntKi) :: NumRecs !< Number of records (rows) of data in the file [-] + REAL(DbKi) :: TimeStep !< Time step for evenly-spaced data in the output file (when NumRecs is not allo [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: ChanNames !< Strings describing the names of the channels from the binary file (including the time channel) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: ChanUnits !< Strings describing the units of the channels from the binary file (including the time channel) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Data !< numeric data (rows and columns) from the binary file, including the time channel [-] + END TYPE FASTdataType +! ======================= +! ========= OutParmType ======= + TYPE, PUBLIC :: OutParmType + INTEGER(IntKi) :: Indx !< An index into AllOuts array where this channel is computed/stored [-] + CHARACTER(ChanLen) :: Name !< Name of the output channel [-] + CHARACTER(ChanLen) :: Units !< Units this channel is specified in [-] + INTEGER(IntKi) :: SignM !< Multiplier for output channel; usually -1 (minus) or 0 (invalid channel) [-] + END TYPE OutParmType +! ======================= +! ========= FileInfoType ======= + TYPE, PUBLIC :: FileInfoType + INTEGER(IntKi) :: NumLines + INTEGER(IntKi) :: NumFiles + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: FileLine + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: FileIndx + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: FileList + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: Lines + END TYPE FileInfoType +! ======================= +! ========= Quaternion ======= + TYPE, PUBLIC :: Quaternion + REAL(ReKi) :: q0 + REAL(ReKi) , DIMENSION(1:3) :: v + END TYPE Quaternion +! ======================= +! ========= NWTC_RandomNumber_ParameterType ======= + TYPE, PUBLIC :: NWTC_RandomNumber_ParameterType + INTEGER(IntKi) :: pRNG + INTEGER(IntKi) , DIMENSION(1:3) :: RandSeed + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: RandSeedAry + CHARACTER(6) :: RNG_type + END TYPE NWTC_RandomNumber_ParameterType +! ======================= +CONTAINS + +!======================================================================= +!> This routine sets the error status and error message for a routine +!! that may set non-AbortErrLev errors. It concatenates error messages +!! and has the ability to provide a sort of traceback message of called +!! routines (if this is called consistently). +!! Modules in the FAST framework are recommend to use it. + SUBROUTINE SetErrStat ( ErrStatLcl, ErrMessLcl, ErrStat, ErrMess, RoutineName ) + + ! This routine is placed in this file because it is called in code generated by the FAST Registry (and I don't feel like putting it in the Sys files) ... be careful not to delete this routine! + + + INTEGER(IntKi), INTENT(IN ) :: ErrStatLcl ! Error status of the operation + CHARACTER(*), INTENT(IN ) :: ErrMessLcl ! Error message if ErrStat /= ErrID_None + + INTEGER(IntKi), INTENT(INOUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(INOUT) :: ErrMess ! Error message if ErrStat /= ErrID_None + + CHARACTER(*), INTENT(IN ) :: RoutineName ! Name of the routine error occurred in + + + IF ( ErrStatLcl /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMess = TRIM(ErrMess)//NewLine + ErrMess = TRIM(ErrMess)//TRIM(RoutineName)//':'//TRIM(ErrMessLcl) + ErrStat = MAX(ErrStat,ErrStatLcl) + + END IF + + END SUBROUTINE SetErrStat +!======================================================================= + + SUBROUTINE NWTC_Library_CopyProgDesc( SrcProgDescData, DstProgDescData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ProgDesc), INTENT(IN) :: SrcProgDescData + TYPE(ProgDesc), INTENT(INOUT) :: DstProgDescData + 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 = 'NWTC_Library_CopyProgDesc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstProgDescData%Name = SrcProgDescData%Name + DstProgDescData%Ver = SrcProgDescData%Ver + DstProgDescData%Date = SrcProgDescData%Date + END SUBROUTINE NWTC_Library_CopyProgDesc + + SUBROUTINE NWTC_Library_DestroyProgDesc( ProgDescData, ErrStat, ErrMsg ) + TYPE(ProgDesc), INTENT(INOUT) :: ProgDescData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyProgDesc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE NWTC_Library_DestroyProgDesc + + SUBROUTINE NWTC_Library_PackProgDesc( 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(ProgDesc), 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 = 'NWTC_Library_PackProgDesc' + ! 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%Name) ! Name + Int_BufSz = Int_BufSz + 1*LEN(InData%Ver) ! Ver + Int_BufSz = Int_BufSz + 1*LEN(InData%Date) ! Date + 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%Name) + IntKiBuf(Int_Xferred) = ICHAR(InData%Name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Ver) + IntKiBuf(Int_Xferred) = ICHAR(InData%Ver(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Date) + IntKiBuf(Int_Xferred) = ICHAR(InData%Date(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE NWTC_Library_PackProgDesc + + SUBROUTINE NWTC_Library_UnPackProgDesc( 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(ProgDesc), 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 = 'NWTC_Library_UnPackProgDesc' + ! 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%Name) + OutData%Name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Ver) + OutData%Ver(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Date) + OutData%Date(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE NWTC_Library_UnPackProgDesc + + SUBROUTINE NWTC_Library_CopyFASTdataType( SrcFASTdataTypeData, DstFASTdataTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FASTdataType), INTENT(IN) :: SrcFASTdataTypeData + TYPE(FASTdataType), INTENT(INOUT) :: DstFASTdataTypeData + 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 = 'NWTC_Library_CopyFASTdataType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstFASTdataTypeData%File = SrcFASTdataTypeData%File + DstFASTdataTypeData%Descr = SrcFASTdataTypeData%Descr + DstFASTdataTypeData%NumChans = SrcFASTdataTypeData%NumChans + DstFASTdataTypeData%NumRecs = SrcFASTdataTypeData%NumRecs + DstFASTdataTypeData%TimeStep = SrcFASTdataTypeData%TimeStep +IF (ALLOCATED(SrcFASTdataTypeData%ChanNames)) THEN + i1_l = LBOUND(SrcFASTdataTypeData%ChanNames,1) + i1_u = UBOUND(SrcFASTdataTypeData%ChanNames,1) + IF (.NOT. ALLOCATED(DstFASTdataTypeData%ChanNames)) THEN + ALLOCATE(DstFASTdataTypeData%ChanNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFASTdataTypeData%ChanNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFASTdataTypeData%ChanNames = SrcFASTdataTypeData%ChanNames +ENDIF +IF (ALLOCATED(SrcFASTdataTypeData%ChanUnits)) THEN + i1_l = LBOUND(SrcFASTdataTypeData%ChanUnits,1) + i1_u = UBOUND(SrcFASTdataTypeData%ChanUnits,1) + IF (.NOT. ALLOCATED(DstFASTdataTypeData%ChanUnits)) THEN + ALLOCATE(DstFASTdataTypeData%ChanUnits(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFASTdataTypeData%ChanUnits.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFASTdataTypeData%ChanUnits = SrcFASTdataTypeData%ChanUnits +ENDIF +IF (ALLOCATED(SrcFASTdataTypeData%Data)) THEN + i1_l = LBOUND(SrcFASTdataTypeData%Data,1) + i1_u = UBOUND(SrcFASTdataTypeData%Data,1) + i2_l = LBOUND(SrcFASTdataTypeData%Data,2) + i2_u = UBOUND(SrcFASTdataTypeData%Data,2) + IF (.NOT. ALLOCATED(DstFASTdataTypeData%Data)) THEN + ALLOCATE(DstFASTdataTypeData%Data(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFASTdataTypeData%Data.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFASTdataTypeData%Data = SrcFASTdataTypeData%Data +ENDIF + END SUBROUTINE NWTC_Library_CopyFASTdataType + + SUBROUTINE NWTC_Library_DestroyFASTdataType( FASTdataTypeData, ErrStat, ErrMsg ) + TYPE(FASTdataType), INTENT(INOUT) :: FASTdataTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyFASTdataType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(FASTdataTypeData%ChanNames)) THEN + DEALLOCATE(FASTdataTypeData%ChanNames) +ENDIF +IF (ALLOCATED(FASTdataTypeData%ChanUnits)) THEN + DEALLOCATE(FASTdataTypeData%ChanUnits) +ENDIF +IF (ALLOCATED(FASTdataTypeData%Data)) THEN + DEALLOCATE(FASTdataTypeData%Data) +ENDIF + END SUBROUTINE NWTC_Library_DestroyFASTdataType + + SUBROUTINE NWTC_Library_PackFASTdataType( 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(FASTdataType), 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 = 'NWTC_Library_PackFASTdataType' + ! 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%File) ! File + Int_BufSz = Int_BufSz + 1*LEN(InData%Descr) ! Descr + Int_BufSz = Int_BufSz + 1 ! NumChans + Int_BufSz = Int_BufSz + 1 ! NumRecs + Db_BufSz = Db_BufSz + 1 ! TimeStep + Int_BufSz = Int_BufSz + 1 ! ChanNames allocated yes/no + IF ( ALLOCATED(InData%ChanNames) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ChanNames upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ChanNames)*LEN(InData%ChanNames) ! ChanNames + END IF + Int_BufSz = Int_BufSz + 1 ! ChanUnits allocated yes/no + IF ( ALLOCATED(InData%ChanUnits) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ChanUnits upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ChanUnits)*LEN(InData%ChanUnits) ! ChanUnits + END IF + Int_BufSz = Int_BufSz + 1 ! Data allocated yes/no + IF ( ALLOCATED(InData%Data) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Data upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Data) ! Data + 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%File) + IntKiBuf(Int_Xferred) = ICHAR(InData%File(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Descr) + IntKiBuf(Int_Xferred) = ICHAR(InData%Descr(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NumChans + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumRecs + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimeStep + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ChanNames) ) 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%ChanNames,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChanNames,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ChanNames,1), UBOUND(InData%ChanNames,1) + DO I = 1, LEN(InData%ChanNames) + IntKiBuf(Int_Xferred) = ICHAR(InData%ChanNames(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ChanUnits) ) 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%ChanUnits,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChanUnits,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ChanUnits,1), UBOUND(InData%ChanUnits,1) + DO I = 1, LEN(InData%ChanUnits) + IntKiBuf(Int_Xferred) = ICHAR(InData%ChanUnits(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Data) ) 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%Data,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Data,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Data,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Data,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Data,2), UBOUND(InData%Data,2) + DO i1 = LBOUND(InData%Data,1), UBOUND(InData%Data,1) + ReKiBuf(Re_Xferred) = InData%Data(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE NWTC_Library_PackFASTdataType + + SUBROUTINE NWTC_Library_UnPackFASTdataType( 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(FASTdataType), 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 = 'NWTC_Library_UnPackFASTdataType' + ! 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%File) + OutData%File(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Descr) + OutData%Descr(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NumChans = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumRecs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TimeStep = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChanNames 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%ChanNames)) DEALLOCATE(OutData%ChanNames) + ALLOCATE(OutData%ChanNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ChanNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ChanNames,1), UBOUND(OutData%ChanNames,1) + DO I = 1, LEN(OutData%ChanNames) + OutData%ChanNames(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChanUnits 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%ChanUnits)) DEALLOCATE(OutData%ChanUnits) + ALLOCATE(OutData%ChanUnits(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ChanUnits.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ChanUnits,1), UBOUND(OutData%ChanUnits,1) + DO I = 1, LEN(OutData%ChanUnits) + OutData%ChanUnits(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Data 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%Data)) DEALLOCATE(OutData%Data) + ALLOCATE(OutData%Data(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Data.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Data,2), UBOUND(OutData%Data,2) + DO i1 = LBOUND(OutData%Data,1), UBOUND(OutData%Data,1) + OutData%Data(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE NWTC_Library_UnPackFASTdataType + + SUBROUTINE NWTC_Library_CopyOutParmType( SrcOutParmTypeData, DstOutParmTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OutParmType), INTENT(IN) :: SrcOutParmTypeData + TYPE(OutParmType), INTENT(INOUT) :: DstOutParmTypeData + 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 = 'NWTC_Library_CopyOutParmType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutParmTypeData%Indx = SrcOutParmTypeData%Indx + DstOutParmTypeData%Name = SrcOutParmTypeData%Name + DstOutParmTypeData%Units = SrcOutParmTypeData%Units + DstOutParmTypeData%SignM = SrcOutParmTypeData%SignM + END SUBROUTINE NWTC_Library_CopyOutParmType + + SUBROUTINE NWTC_Library_DestroyOutParmType( OutParmTypeData, ErrStat, ErrMsg ) + TYPE(OutParmType), INTENT(INOUT) :: OutParmTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyOutParmType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE NWTC_Library_DestroyOutParmType + + SUBROUTINE NWTC_Library_PackOutParmType( 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(OutParmType), 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 = 'NWTC_Library_PackOutParmType' + ! 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 ! Indx + Int_BufSz = Int_BufSz + 1*LEN(InData%Name) ! Name + Int_BufSz = Int_BufSz + 1*LEN(InData%Units) ! Units + Int_BufSz = Int_BufSz + 1 ! SignM + 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%Indx + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Name) + IntKiBuf(Int_Xferred) = ICHAR(InData%Name(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%Units) + IntKiBuf(Int_Xferred) = ICHAR(InData%Units(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%SignM + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE NWTC_Library_PackOutParmType + + SUBROUTINE NWTC_Library_UnPackOutParmType( 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(OutParmType), 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 = 'NWTC_Library_UnPackOutParmType' + ! 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%Indx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Name) + OutData%Name(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%Units) + OutData%Units(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%SignM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE NWTC_Library_UnPackOutParmType + + SUBROUTINE NWTC_Library_CopyFileInfoType( SrcFileInfoTypeData, DstFileInfoTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FileInfoType), INTENT(IN) :: SrcFileInfoTypeData + TYPE(FileInfoType), INTENT(INOUT) :: DstFileInfoTypeData + 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 = 'NWTC_Library_CopyFileInfoType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstFileInfoTypeData%NumLines = SrcFileInfoTypeData%NumLines + DstFileInfoTypeData%NumFiles = SrcFileInfoTypeData%NumFiles +IF (ALLOCATED(SrcFileInfoTypeData%FileLine)) THEN + i1_l = LBOUND(SrcFileInfoTypeData%FileLine,1) + i1_u = UBOUND(SrcFileInfoTypeData%FileLine,1) + IF (.NOT. ALLOCATED(DstFileInfoTypeData%FileLine)) THEN + ALLOCATE(DstFileInfoTypeData%FileLine(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFileInfoTypeData%FileLine.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFileInfoTypeData%FileLine = SrcFileInfoTypeData%FileLine +ENDIF +IF (ALLOCATED(SrcFileInfoTypeData%FileIndx)) THEN + i1_l = LBOUND(SrcFileInfoTypeData%FileIndx,1) + i1_u = UBOUND(SrcFileInfoTypeData%FileIndx,1) + IF (.NOT. ALLOCATED(DstFileInfoTypeData%FileIndx)) THEN + ALLOCATE(DstFileInfoTypeData%FileIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFileInfoTypeData%FileIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFileInfoTypeData%FileIndx = SrcFileInfoTypeData%FileIndx +ENDIF +IF (ALLOCATED(SrcFileInfoTypeData%FileList)) THEN + i1_l = LBOUND(SrcFileInfoTypeData%FileList,1) + i1_u = UBOUND(SrcFileInfoTypeData%FileList,1) + IF (.NOT. ALLOCATED(DstFileInfoTypeData%FileList)) THEN + ALLOCATE(DstFileInfoTypeData%FileList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFileInfoTypeData%FileList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFileInfoTypeData%FileList = SrcFileInfoTypeData%FileList +ENDIF +IF (ALLOCATED(SrcFileInfoTypeData%Lines)) THEN + i1_l = LBOUND(SrcFileInfoTypeData%Lines,1) + i1_u = UBOUND(SrcFileInfoTypeData%Lines,1) + IF (.NOT. ALLOCATED(DstFileInfoTypeData%Lines)) THEN + ALLOCATE(DstFileInfoTypeData%Lines(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFileInfoTypeData%Lines.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFileInfoTypeData%Lines = SrcFileInfoTypeData%Lines +ENDIF + END SUBROUTINE NWTC_Library_CopyFileInfoType + + SUBROUTINE NWTC_Library_DestroyFileInfoType( FileInfoTypeData, ErrStat, ErrMsg ) + TYPE(FileInfoType), INTENT(INOUT) :: FileInfoTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyFileInfoType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(FileInfoTypeData%FileLine)) THEN + DEALLOCATE(FileInfoTypeData%FileLine) +ENDIF +IF (ALLOCATED(FileInfoTypeData%FileIndx)) THEN + DEALLOCATE(FileInfoTypeData%FileIndx) +ENDIF +IF (ALLOCATED(FileInfoTypeData%FileList)) THEN + DEALLOCATE(FileInfoTypeData%FileList) +ENDIF +IF (ALLOCATED(FileInfoTypeData%Lines)) THEN + DEALLOCATE(FileInfoTypeData%Lines) +ENDIF + END SUBROUTINE NWTC_Library_DestroyFileInfoType + + SUBROUTINE NWTC_Library_PackFileInfoType( 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(FileInfoType), 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 = 'NWTC_Library_PackFileInfoType' + ! 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 ! NumLines + Int_BufSz = Int_BufSz + 1 ! NumFiles + Int_BufSz = Int_BufSz + 1 ! FileLine allocated yes/no + IF ( ALLOCATED(InData%FileLine) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FileLine upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FileLine) ! FileLine + END IF + Int_BufSz = Int_BufSz + 1 ! FileIndx allocated yes/no + IF ( ALLOCATED(InData%FileIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FileIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FileIndx) ! FileIndx + END IF + Int_BufSz = Int_BufSz + 1 ! FileList allocated yes/no + IF ( ALLOCATED(InData%FileList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FileList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%FileList)*LEN(InData%FileList) ! FileList + END IF + Int_BufSz = Int_BufSz + 1 ! Lines allocated yes/no + IF ( ALLOCATED(InData%Lines) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Lines upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Lines)*LEN(InData%Lines) ! Lines + 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%NumLines + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumFiles + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FileLine) ) 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%FileLine,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FileLine,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FileLine,1), UBOUND(InData%FileLine,1) + IntKiBuf(Int_Xferred) = InData%FileLine(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FileIndx) ) 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%FileIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FileIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FileIndx,1), UBOUND(InData%FileIndx,1) + IntKiBuf(Int_Xferred) = InData%FileIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FileList) ) 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%FileList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FileList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FileList,1), UBOUND(InData%FileList,1) + DO I = 1, LEN(InData%FileList) + IntKiBuf(Int_Xferred) = ICHAR(InData%FileList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Lines) ) 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%Lines,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Lines,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Lines,1), UBOUND(InData%Lines,1) + DO I = 1, LEN(InData%Lines) + IntKiBuf(Int_Xferred) = ICHAR(InData%Lines(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE NWTC_Library_PackFileInfoType + + SUBROUTINE NWTC_Library_UnPackFileInfoType( 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(FileInfoType), 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 = 'NWTC_Library_UnPackFileInfoType' + ! 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%NumLines = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumFiles = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FileLine 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%FileLine)) DEALLOCATE(OutData%FileLine) + ALLOCATE(OutData%FileLine(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FileLine.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FileLine,1), UBOUND(OutData%FileLine,1) + OutData%FileLine(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FileIndx 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%FileIndx)) DEALLOCATE(OutData%FileIndx) + ALLOCATE(OutData%FileIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FileIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FileIndx,1), UBOUND(OutData%FileIndx,1) + OutData%FileIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FileList 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%FileList)) DEALLOCATE(OutData%FileList) + ALLOCATE(OutData%FileList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FileList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FileList,1), UBOUND(OutData%FileList,1) + DO I = 1, LEN(OutData%FileList) + OutData%FileList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Lines 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%Lines)) DEALLOCATE(OutData%Lines) + ALLOCATE(OutData%Lines(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Lines.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Lines,1), UBOUND(OutData%Lines,1) + DO I = 1, LEN(OutData%Lines) + OutData%Lines(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE NWTC_Library_UnPackFileInfoType + + SUBROUTINE NWTC_Library_CopyQuaternion( SrcQuaternionData, DstQuaternionData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Quaternion), INTENT(IN) :: SrcQuaternionData + TYPE(Quaternion), INTENT(INOUT) :: DstQuaternionData + 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 = 'NWTC_Library_CopyQuaternion' +! + ErrStat = ErrID_None + ErrMsg = "" + DstQuaternionData%q0 = SrcQuaternionData%q0 + DstQuaternionData%v = SrcQuaternionData%v + END SUBROUTINE NWTC_Library_CopyQuaternion + + SUBROUTINE NWTC_Library_DestroyQuaternion( QuaternionData, ErrStat, ErrMsg ) + TYPE(Quaternion), INTENT(INOUT) :: QuaternionData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyQuaternion' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE NWTC_Library_DestroyQuaternion + + SUBROUTINE NWTC_Library_PackQuaternion( 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(Quaternion), 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 = 'NWTC_Library_PackQuaternion' + ! 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 ! q0 + Re_BufSz = Re_BufSz + SIZE(InData%v) ! v + 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%q0 + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%v,1), UBOUND(InData%v,1) + ReKiBuf(Re_Xferred) = InData%v(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE NWTC_Library_PackQuaternion + + SUBROUTINE NWTC_Library_UnPackQuaternion( 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(Quaternion), 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 = 'NWTC_Library_UnPackQuaternion' + ! 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%q0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%v,1) + i1_u = UBOUND(OutData%v,1) + DO i1 = LBOUND(OutData%v,1), UBOUND(OutData%v,1) + OutData%v(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE NWTC_Library_UnPackQuaternion + + SUBROUTINE NWTC_Library_CopyNWTC_RandomNumber_ParameterType( SrcNWTC_RandomNumber_ParameterTypeData, DstNWTC_RandomNumber_ParameterTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(NWTC_RandomNumber_ParameterType), INTENT(IN) :: SrcNWTC_RandomNumber_ParameterTypeData + TYPE(NWTC_RandomNumber_ParameterType), INTENT(INOUT) :: DstNWTC_RandomNumber_ParameterTypeData + 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 = 'NWTC_Library_CopyNWTC_RandomNumber_ParameterType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstNWTC_RandomNumber_ParameterTypeData%pRNG = SrcNWTC_RandomNumber_ParameterTypeData%pRNG + DstNWTC_RandomNumber_ParameterTypeData%RandSeed = SrcNWTC_RandomNumber_ParameterTypeData%RandSeed +IF (ALLOCATED(SrcNWTC_RandomNumber_ParameterTypeData%RandSeedAry)) THEN + i1_l = LBOUND(SrcNWTC_RandomNumber_ParameterTypeData%RandSeedAry,1) + i1_u = UBOUND(SrcNWTC_RandomNumber_ParameterTypeData%RandSeedAry,1) + IF (.NOT. ALLOCATED(DstNWTC_RandomNumber_ParameterTypeData%RandSeedAry)) THEN + ALLOCATE(DstNWTC_RandomNumber_ParameterTypeData%RandSeedAry(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstNWTC_RandomNumber_ParameterTypeData%RandSeedAry.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstNWTC_RandomNumber_ParameterTypeData%RandSeedAry = SrcNWTC_RandomNumber_ParameterTypeData%RandSeedAry +ENDIF + DstNWTC_RandomNumber_ParameterTypeData%RNG_type = SrcNWTC_RandomNumber_ParameterTypeData%RNG_type + END SUBROUTINE NWTC_Library_CopyNWTC_RandomNumber_ParameterType + + SUBROUTINE NWTC_Library_DestroyNWTC_RandomNumber_ParameterType( NWTC_RandomNumber_ParameterTypeData, ErrStat, ErrMsg ) + TYPE(NWTC_RandomNumber_ParameterType), INTENT(INOUT) :: NWTC_RandomNumber_ParameterTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'NWTC_Library_DestroyNWTC_RandomNumber_ParameterType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(NWTC_RandomNumber_ParameterTypeData%RandSeedAry)) THEN + DEALLOCATE(NWTC_RandomNumber_ParameterTypeData%RandSeedAry) +ENDIF + END SUBROUTINE NWTC_Library_DestroyNWTC_RandomNumber_ParameterType + + SUBROUTINE NWTC_Library_PackNWTC_RandomNumber_ParameterType( 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(NWTC_RandomNumber_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 = 'NWTC_Library_PackNWTC_RandomNumber_ParameterType' + ! 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 ! pRNG + Int_BufSz = Int_BufSz + SIZE(InData%RandSeed) ! RandSeed + Int_BufSz = Int_BufSz + 1 ! RandSeedAry allocated yes/no + IF ( ALLOCATED(InData%RandSeedAry) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RandSeedAry upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RandSeedAry) ! RandSeedAry + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%RNG_type) ! RNG_type + 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%pRNG + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RandSeed,1), UBOUND(InData%RandSeed,1) + IntKiBuf(Int_Xferred) = InData%RandSeed(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%RandSeedAry) ) 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%RandSeedAry,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RandSeedAry,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RandSeedAry,1), UBOUND(InData%RandSeedAry,1) + IntKiBuf(Int_Xferred) = InData%RandSeedAry(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DO I = 1, LEN(InData%RNG_type) + IntKiBuf(Int_Xferred) = ICHAR(InData%RNG_type(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE NWTC_Library_PackNWTC_RandomNumber_ParameterType + + SUBROUTINE NWTC_Library_UnPackNWTC_RandomNumber_ParameterType( 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(NWTC_RandomNumber_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 = 'NWTC_Library_UnPackNWTC_RandomNumber_ParameterType' + ! 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%pRNG = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RandSeed,1) + i1_u = UBOUND(OutData%RandSeed,1) + DO i1 = LBOUND(OutData%RandSeed,1), UBOUND(OutData%RandSeed,1) + OutData%RandSeed(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RandSeedAry 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%RandSeedAry)) DEALLOCATE(OutData%RandSeedAry) + ALLOCATE(OutData%RandSeedAry(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RandSeedAry.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RandSeedAry,1), UBOUND(OutData%RandSeedAry,1) + OutData%RandSeedAry(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DO I = 1, LEN(OutData%RNG_type) + OutData%RNG_type(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE NWTC_Library_UnPackNWTC_RandomNumber_ParameterType + +END MODULE NWTC_Library_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_Num.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_Num.f90 new file mode 100644 index 000000000..2b0786ed4 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_Num.f90 @@ -0,0 +1,6907 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +!********************************************************************************************************************************** + +!.................................................................................................................................. +!> This module contains numeric-type routines with non-system-specific logic and references. +MODULE NWTC_Num +!.................................................................................................................................. + + USE NWTC_IO + + IMPLICIT NONE + +!======================================================================= + + ! Global numeric-related variables. + + REAL(DbKi) :: D2R_D !< Factor to convert degrees to radians in double precision + REAL(DbKi) :: Inf_D !< IEEE value for NaN (not-a-number) in double precision + REAL(DbKi) :: Inv2Pi_D !< 0.5/Pi (1/(2*Pi)) in double precision + REAL(DbKi) :: NaN_D !< IEEE value for Inf (infinity) in double precision + REAL(DbKi) :: Pi_D !< Ratio of a circle's circumference to its diameter in double precision + REAL(DbKi) :: PiBy2_D !< Pi/2 in double precision + REAL(DbKi) :: R2D_D !< Factor to convert radians to degrees in double precision + REAL(DbKi) :: RPM2RPS_D !< Factor to convert revolutions per minute to radians per second in double precision + REAL(DbKi) :: RPS2RPM_D !< Factor to convert radians per second to revolutions per minute in double precision + REAL(DbKi) :: TwoByPi_D !< 2/Pi in double precision + REAL(DbKi) :: TwoPi_D !< 2*Pi in double precision + + + REAL(ReKi) :: D2R !< Factor to convert degrees to radians + REAL(ReKi) :: Inf !< IEEE value for NaN (not-a-number) + REAL(ReKi) :: Inv2Pi !< 0.5/Pi = 1 / (2*pi) + REAL(ReKi) :: NaN !< IEEE value for Inf (infinity) + REAL(ReKi) :: Pi !< Ratio of a circle's circumference to its diameter + REAL(ReKi) :: PiBy2 !< Pi/2 + REAL(ReKi) :: R2D !< Factor to convert radians to degrees + REAL(ReKi) :: RPM2RPS !< Factor to convert revolutions per minute to radians per second + REAL(ReKi) :: RPS2RPM !< Factor to convert radians per second to revolutions per minute + REAL(ReKi) :: TwoByPi !< 2/Pi + REAL(ReKi) :: TwoPi !< 2*Pi + + REAL(SiKi) :: Pi_R4 !< Ratio of a circle's circumference to its diameter in 4-byte precision + REAL(R8Ki) :: Pi_R8 !< Ratio of a circle's circumference to its diameter in 8-byte precision + REAL(QuKi) :: Pi_R16 !< Ratio of a circle's circumference to its diameter in 16-byte precision + + REAL(SiKi) :: TwoPi_R4 !< 2*pi in 4-byte precision + REAL(R8Ki) :: TwoPi_R8 !< 2*pi in 8-byte precision + REAL(QuKi) :: TwoPi_R16 !< 2*pi in 16-byte precision +!======================================================================= + + ! Create interfaces for generic routines that use specific routines. + + !> \copydoc nwtc_num::equalrealnos4() + INTERFACE EqualRealNos + MODULE PROCEDURE EqualRealNos4 + MODULE PROCEDURE EqualRealNos8 + MODULE PROCEDURE EqualRealNos16 + END INTERFACE + + !> \copydoc nwtc_num::eulerconstructr4() + INTERFACE EulerConstruct + MODULE PROCEDURE EulerConstructR4 + MODULE PROCEDURE EulerConstructR8 + MODULE PROCEDURE EulerConstructR16 + END INTERFACE + + !> \copydoc nwtc_num::eulerextractr4() + INTERFACE EulerExtract + MODULE PROCEDURE EulerExtractR4 + MODULE PROCEDURE EulerExtractR8 + MODULE PROCEDURE EulerExtractR16 + END INTERFACE + + !> \copydoc nwtc_num::outerproductr4 + INTERFACE OuterProduct + MODULE PROCEDURE OuterProductR4 + MODULE PROCEDURE OuterProductR8 + MODULE PROCEDURE OuterProductR16 + END INTERFACE + + !> \copydoc nwtc_num::cross_productr4() + INTERFACE Cross_Product + MODULE PROCEDURE Cross_ProductR4 + MODULE PROCEDURE Cross_ProductR4R8 + MODULE PROCEDURE Cross_ProductR8 + MODULE PROCEDURE Cross_ProductR8R4 + MODULE PROCEDURE Cross_ProductR16 + END INTERFACE + + !> \copydoc nwtc_num::smllrottransd() + INTERFACE SmllRotTrans + MODULE PROCEDURE SmllRotTransDD + MODULE PROCEDURE SmllRotTransD + MODULE PROCEDURE SmllRotTransR + END INTERFACE + + !> \copydoc nwtc_num::getsmllrotangsd() + INTERFACE GetSmllRotAngs + MODULE PROCEDURE GetSmllRotAngsD + MODULE PROCEDURE GetSmllRotAngsR + END INTERFACE + + !> \copydoc nwtc_num::zero2twopir4 + INTERFACE Zero2TwoPi + MODULE PROCEDURE Zero2TwoPiR4 + MODULE PROCEDURE Zero2TwoPiR8 + MODULE PROCEDURE Zero2TwoPiR16 + END INTERFACE + + !> \copydoc nwtc_num::twonormr4 + INTERFACE TwoNorm + MODULE PROCEDURE TwoNormR4 + MODULE PROCEDURE TwoNormR8 + MODULE PROCEDURE TwoNormR16 + END INTERFACE + + !> \copydoc nwtc_num::tracer4 + INTERFACE trace + MODULE PROCEDURE traceR4 + MODULE PROCEDURE traceR8 + MODULE PROCEDURE traceR16 + END INTERFACE + + !> \copydoc nwtc_num::dcm_expd + INTERFACE DCM_exp + MODULE PROCEDURE DCM_expR + MODULE PROCEDURE DCM_expD + END INTERFACE + + !> \copydoc nwtc_num::dcm_logmapd + INTERFACE DCM_logMap + MODULE PROCEDURE DCM_logMapR + MODULE PROCEDURE DCM_logMapD + END INTERFACE + + !> \copydoc nwtc_num::dcm_setlogmapforinterpd + INTERFACE DCM_SetLogMapForInterp + MODULE PROCEDURE DCM_SetLogMapForInterpR + MODULE PROCEDURE DCM_SetLogMapForInterpD + END INTERFACE + + !> \copydoc nwtc_num::eye2 + INTERFACE Eye + MODULE PROCEDURE Eye2 ! matrix of two dimensions + MODULE PROCEDURE Eye2D ! matrix of two dimensions (double precision) + MODULE PROCEDURE Eye3 ! matrix of three dimensions + MODULE PROCEDURE Eye3D ! matrix of three dimensions + END INTERFACE + + !> \copydoc nwtc_num::interpbincomp + INTERFACE InterpBin + MODULE PROCEDURE InterpBinComp + MODULE PROCEDURE InterpBinReal + END INTERFACE + + !> \copydoc nwtc_num::interpstpcomp4 + INTERFACE InterpStp + MODULE PROCEDURE InterpStpComp4 + MODULE PROCEDURE InterpStpComp8 + MODULE PROCEDURE InterpStpComp16 + MODULE PROCEDURE InterpStpReal4 + MODULE PROCEDURE InterpStpReal4_8 + MODULE PROCEDURE InterpStpReal8 + MODULE PROCEDURE InterpStpReal16 + END INTERFACE + + !> \copydoc nwtc_num::interparrayr4 + INTERFACE InterpArray + MODULE PROCEDURE InterpArrayR4 + MODULE PROCEDURE InterpArrayR8 + MODULE PROCEDURE InterpArrayR16 + END INTERFACE + + !> \copydoc nwtc_num::interpwrappedstpreal4 + INTERFACE InterpWrappedStpReal + MODULE PROCEDURE InterpWrappedStpReal4 + MODULE PROCEDURE InterpWrappedStpReal4_8 + MODULE PROCEDURE InterpWrappedStpReal8 + MODULE PROCEDURE InterpWrappedStpReal16 + END INTERFACE + + !> \copydoc nwtc_num::locatestpr4 + INTERFACE LocateStp + MODULE PROCEDURE LocateStpR4 + MODULE PROCEDURE LocateStpR8 + MODULE PROCEDURE LocateStpR16 + END INTERFACE + + !> \copydoc nwtc_num::skewsymmatr4 + INTERFACE SkewSymMat + MODULE PROCEDURE SkewSymMatR4 + MODULE PROCEDURE SkewSymMatR8 + MODULE PROCEDURE SkewSymMatR16 + END INTERFACE + + !> \copydoc nwtc_num::angle_extrapinterp2_r4 + INTERFACE Angles_ExtrapInterp + MODULE PROCEDURE Angles_ExtrapInterp1_R4 + MODULE PROCEDURE Angles_ExtrapInterp1_R8 + MODULE PROCEDURE Angles_ExtrapInterp1_R16 + MODULE PROCEDURE Angles_ExtrapInterp1_R4R + MODULE PROCEDURE Angles_ExtrapInterp1_R8R + MODULE PROCEDURE Angles_ExtrapInterp1_R16R + MODULE PROCEDURE Angles_ExtrapInterp2_R4 + MODULE PROCEDURE Angles_ExtrapInterp2_R8 + MODULE PROCEDURE Angles_ExtrapInterp2_R16 + MODULE PROCEDURE Angles_ExtrapInterp2_R4R + MODULE PROCEDURE Angles_ExtrapInterp2_R8R + MODULE PROCEDURE Angles_ExtrapInterp2_R16R + END INTERFACE + + !> \copydoc nwtc_num::addorsub2pi_r4 + INTERFACE AddOrSub2Pi + MODULE PROCEDURE AddOrSub2Pi_R4 + MODULE PROCEDURE AddOrSub2Pi_R8 + MODULE PROCEDURE AddOrSub2Pi_R16 + END INTERFACE + + !> \copydoc nwtc_num::mpi2pi_r4 + INTERFACE MPi2Pi + MODULE PROCEDURE MPi2Pi_R4 + MODULE PROCEDURE MPi2Pi_R8 + MODULE PROCEDURE MPi2Pi_R16 + END INTERFACE + +CONTAINS + +!======================================================================= +!> This routine is used to convert NewAngle to an angle within Pi of +!! OldAngle by adding or subtracting 2*Pi accordingly. +!! This routine is useful for converting +!! angles returned from a call to the ATAN2() FUNCTION into angles that may +!! exceed the -Pi to Pi limit of ATAN2(). For example, if the nacelle yaw +!! angle was 179deg in the previous time step and the yaw angle increased +!! by 2deg in the new time step, we want the new yaw angle returned from a +!! call to the ATAN2() FUNCTION to be 181deg instead of -179deg. This +!! routine assumes that the angle change between calls is not more than +!! Pi in absolute value. +!! Use AddOrSub2Pi (nwtc_num::addorsub2pi) instead of directly calling a specific routine in the generic interface. + SUBROUTINE AddOrSub2Pi_R4 ( OldAngle, NewAngle ) + ! Argument declarations: + + REAL(SiKi), INTENT(IN ) :: OldAngle !< Angle from which NewAngle will be converted to within Pi of, rad. + REAL(SiKi), INTENT(INOUT) :: NewAngle !< Angle to be converted to within 2*Pi of OldAngle, rad. + + + ! Local declarations: + + REAL(SiKi) :: DelAngle ! The difference between OldAngle and NewAngle, rad. + + + + ! Add or subtract 2*Pi in order to convert NewAngle two within Pi of OldAngle: + + + DelAngle = OldAngle - NewAngle + + DO WHILE ( ABS( DelAngle ) > Pi_R4 ) + + NewAngle = NewAngle + SIGN( TwoPi_R4, DelAngle ) + DelAngle = OldAngle - NewAngle + + END DO + + RETURN + END SUBROUTINE AddOrSub2Pi_R4 +!======================================================================= +!> \copydoc nwtc_num::addorsub2pi_r4 + SUBROUTINE AddOrSub2Pi_R8 ( OldAngle, NewAngle ) + + ! Argument declarations: + + REAL(R8Ki), INTENT(IN ) :: OldAngle ! Angle from which NewAngle will be converted to within Pi of, rad. + REAL(R8Ki), INTENT(INOUT) :: NewAngle ! Angle to be converted to within Pi of OldAngle, rad. + + + ! Local declarations: + + REAL(R8Ki) :: DelAngle ! The difference between OldAngle and NewAngle, rad. + + + + ! Add or subtract 2*Pi in order to convert NewAngle two within Pi of OldAngle: + + + DelAngle = OldAngle - NewAngle + + DO WHILE ( ABS( DelAngle ) > Pi_R8 ) + + NewAngle = NewAngle + SIGN( TwoPi_R8, DelAngle ) + DelAngle = OldAngle - NewAngle + + END DO + + RETURN + END SUBROUTINE AddOrSub2Pi_R8 +!======================================================================= +!> \copydoc nwtc_num::addorsub2pi_r4 + SUBROUTINE AddOrSub2Pi_R16 ( OldAngle, NewAngle ) + + ! Argument declarations: + + REAL(QuKi), INTENT(IN ) :: OldAngle ! Angle from which NewAngle will be converted to within 2*Pi of, rad. + REAL(QuKi), INTENT(INOUT) :: NewAngle ! Angle to be converted to within 2*Pi of OldAngle, rad. + + + ! Local declarations: + + REAL(QuKi) :: DelAngle ! The difference between OldAngle and NewAngle, rad. + + + + ! Add or subtract 2*Pi in order to convert NewAngle two within Pi of OldAngle: + + + DelAngle = OldAngle - NewAngle + + DO WHILE ( ABS( DelAngle ) > Pi_R16 ) + + NewAngle = NewAngle + SIGN( TwoPi_R16, DelAngle ) + DelAngle = OldAngle - NewAngle + + END DO + + RETURN + END SUBROUTINE AddOrSub2Pi_R16 +!======================================================================= + FUNCTION BlendCosine( x, LowerBound, UpperBound ) RESULT(S) + + REAL(ReKi), INTENT(IN) :: x ! + REAL(ReKi), INTENT(IN) :: LowerBound !< if x <= LowerBound, S=0 + REAL(ReKi), INTENT(IN) :: UpperBound !< if x >= UpperBound, S=1 + REAL(ReKi) :: S + + if (x >= UpperBound) then + S = 1.0_ReKi + elseif (x <= LowerBound) then + S = 0.0_ReKi + elseif (LowerBound < UpperBound) then + S = 0.5_ReKi*(1.0_ReKi - cos((x-LowerBound) / (UpperBound-LowerBound)*pi)) + else ! can only get here if LowerBound>=UpperBound>x , which should be an error + S = 0.0_ReKi + end if + + END FUNCTION BlendCosine +!======================================================================= +!> This routine sorts a list of real numbers. It uses the bubble sort algorithm, +!! which is only suitable for short lists. + SUBROUTINE BSortReal ( RealAry, NumPts ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: NumPts !< The length of the list to be sorted. + + REAL(ReKi), INTENT(INOUT) :: RealAry(NumPts) !< The list of real numbers to be sorted. + + + ! Local declarations: + + REAL(ReKi) :: Temp ! Temporary variable to hold the current element. + + INTEGER :: I ! Index into the array. + + LOGICAL :: Change ! Flag to indicate if a change of order was made. + + + ! Sort the list + + Change = .TRUE. + + DO WHILE ( Change ) + + Change = .FALSE. + + DO I=2,NumPts + IF ( RealAry(I) < RealAry(I-1) ) THEN + Temp = RealAry(I) + RealAry(I) = RealAry(I-1) + RealAry(I-1) = Temp + Change = .TRUE. + END IF + END DO ! I + + END DO ! WHILE + + + RETURN + END SUBROUTINE BSortReal ! ( RealAry, NumPts ) +!======================================================================= +!> This function computes the cross product of two 3-element arrays (resulting in a vector): \n +!! cross_product = Vector1 \f$\times\f$ Vector2 \n +!! Use cross_product (nwtc_num::cross_product) instead of directly calling a specific routine in the generic interface. + FUNCTION Cross_ProductR4(Vector1, Vector2) result(CProd) + + ! Argument declarations. + + REAL(SiKi), INTENT(IN ) :: Vector1 (3) + REAL(SiKi), INTENT(IN ) :: Vector2 (3) + + ! Function definition + REAL(SiKi) :: CProd (3) ! = Vector1 X Vector2 (resulting in a vector) + + + CProd(1) = Vector1(2)*Vector2(3) - Vector1(3)*Vector2(2) + CProd(2) = Vector1(3)*Vector2(1) - Vector1(1)*Vector2(3) + CProd(3) = Vector1(1)*Vector2(2) - Vector1(2)*Vector2(1) + + + RETURN + END FUNCTION Cross_ProductR4 +!======================================================================= +!> \copydoc nwtc_num::cross_productr4 + FUNCTION Cross_ProductR4R8(Vector1, Vector2) result(CProd) + + ! Argument declarations. + + REAL(SiKi), INTENT(IN ) :: Vector1 (3) + REAL(R8Ki), INTENT(IN ) :: Vector2 (3) + + ! Function definition + REAL(R8Ki) :: CProd (3) ! = Vector1 X Vector2 (resulting in a vector) + + + CProd(1) = Vector1(2)*Vector2(3) - Vector1(3)*Vector2(2) + CProd(2) = Vector1(3)*Vector2(1) - Vector1(1)*Vector2(3) + CProd(3) = Vector1(1)*Vector2(2) - Vector1(2)*Vector2(1) + + + RETURN + END FUNCTION Cross_ProductR4R8 +!======================================================================= +!> \copydoc nwtc_num::cross_productr4 + FUNCTION Cross_ProductR8(Vector1, Vector2) result(CProd) + + ! Argument declarations. + + REAL(R8Ki), INTENT(IN ) :: Vector1 (3) + REAL(R8Ki), INTENT(IN ) :: Vector2 (3) + + ! Function definition + REAL(R8Ki) :: CProd (3) ! = Vector1 X Vector2 (resulting in a vector) + + + CProd(1) = Vector1(2)*Vector2(3) - Vector1(3)*Vector2(2) + CProd(2) = Vector1(3)*Vector2(1) - Vector1(1)*Vector2(3) + CProd(3) = Vector1(1)*Vector2(2) - Vector1(2)*Vector2(1) + + + RETURN + END FUNCTION Cross_ProductR8 +!======================================================================= +!> \copydoc nwtc_num::cross_productr4 + FUNCTION Cross_ProductR8R4(Vector1, Vector2) result(CProd) + + ! Argument declarations. + + REAL(R8Ki), INTENT(IN ) :: Vector1 (3) + REAL(SiKi), INTENT(IN ) :: Vector2 (3) + + ! Function definition + REAL(R8Ki) :: CProd (3) ! = Vector1 X Vector2 (resulting in a vector) + + + CProd(1) = Vector1(2)*Vector2(3) - Vector1(3)*Vector2(2) + CProd(2) = Vector1(3)*Vector2(1) - Vector1(1)*Vector2(3) + CProd(3) = Vector1(1)*Vector2(2) - Vector1(2)*Vector2(1) + + + RETURN + END FUNCTION Cross_ProductR8R4 +!======================================================================= +!> \copydoc nwtc_num::cross_productr4 + FUNCTION Cross_ProductR16(Vector1, Vector2) result(CProd) + + ! Argument declarations. + + REAL(QuKi), INTENT(IN ) :: Vector1 (3) + REAL(QuKi), INTENT(IN ) :: Vector2 (3) + + ! Function definition + REAL(QuKi) :: CProd (3) ! = Vector1 X Vector2 (resulting in a vector) + + + CProd(1) = Vector1(2)*Vector2(3) - Vector1(3)*Vector2(2) + CProd(2) = Vector1(3)*Vector2(1) - Vector1(1)*Vector2(3) + CProd(3) = Vector1(1)*Vector2(2) - Vector1(2)*Vector2(1) + + + RETURN + END FUNCTION Cross_ProductR16 +!======================================================================= +!> This routine calculates the parameters needed to compute a irregularly-spaced natural cubic spline. +!! Natural cubic splines are used in that the curvature at the end points is zero. +!! This routine does not require that the XAry be regularly spaced. + SUBROUTINE CubicSplineInit ( AryLen, XAry, YAry, Coef, ErrStat, ErrMsg ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array + + REAL(ReKi), INTENT(OUT) :: Coef (AryLen-1,0:3) !< The coefficients for the cubic polynomials + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Input array of x values + REAL(ReKi), INTENT(IN) :: YAry (AryLen) !< Input array of y values + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + REAL(ReKi), ALLOCATABLE :: DelX (:) ! The distances between the randomly spaced points. + REAL(ReKi), ALLOCATABLE :: Slope (:) ! The AryLen-1 length array of slopes between points. + REAL(ReKi), ALLOCATABLE :: U (:) ! An AryLen-1 length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: V (:) ! An AryLen-1 length array used in the Gaussian elimination. + REAL(ReKi) :: ZHi ! A parameter used to calculate the polynomial coefficients. + REAL(ReKi) :: ZLo ! A parameter used to calculate the polynomial coefficients. + + INTEGER(IntKi) :: ErrStatLcL ! Local error status. + INTEGER :: I ! The index into the arrays. + CHARACTER(*), PARAMETER :: RoutineName = 'CubicSplineInit' + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate the various intermediate arrays. + + ALLOCATE ( DelX( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the DelX array.' ) + RETURN + ENDIF + + ALLOCATE ( Slope( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the Slope array.' ) + RETURN + ENDIF + + ALLOCATE ( U( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the U array.' ) + RETURN + ENDIF + + ALLOCATE ( V( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the V array.' ) + RETURN + ENDIF + + + ! Compute the distance between XAry values and the slopes between points. + + DO I=1,AryLen-1 + DelX (I) = XAry(I+1) - XAry(I) + Slope(I) = ( YAry(I+1) - YAry(I) )/DelX(I) + END DO ! I + + + ! Use Gaussian elimination to solve the tri-diagonal matrix. + + U(1) = 2.0_ReKi*( DelX (2) + DelX (1) ) + V(1) = 6.0_ReKi*( Slope(2) - Slope(1) ) + + DO I=2,AryLen-1 + U(I) = 2.0_ReKi*( DelX(I-1) + DelX(I) ) - DelX(I-1)*DelX(I-1)/U(I-1) + V(I) = 6.0_ReKi*( Slope(I) - Slope(I-1) ) - DelX(I-1)* V(I-1)/U(I-1) + END DO ! I + + + ! Determine the coefficients of the polynomials. + + Coef(:,0) = YAry(:) + + ZHi = 0.0_ReKi + + DO I=AryLen-1,1,-1 + ZLo = ( V(I) - DelX(I)*ZHi )/U(I) + Coef(I,1) = Slope(I) - DelX(I)*( ZHi/6.0_ReKi + ZLo/3.0_ReKi ) + Coef(I,2) = 0.5_ReKi*ZLo + Coef(I,3) = ( ZHi - ZLo )/( 6.0_ReKi*DelX(I) ) + ZHi = ZLo + END DO ! I + + + + CALL ExitThisRoutine ( ErrID_None, 'No Problemo' ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + ! Deallocate the Words array if it had been allocated. + + IF ( ALLOCATED( DelX ) ) DEALLOCATE( DelX ) + IF ( ALLOCATED( Slope ) ) DEALLOCATE( Slope ) + IF ( ALLOCATED( U ) ) DEALLOCATE( U ) + IF ( ALLOCATED( V ) ) DEALLOCATE( V ) + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE CubicSplineInit ! ( AryLen, XAry, YAry, YAry, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine calculates the parameters needed to compute a irregularly-spaced natural cubic spline. +!! Natural cubic splines are used in that the curvature at the end points is zero. +!! This routine does not require that the XAry be regularly spaced. +!! This version of the routine works with multiple curves that share the same X values. + SUBROUTINE CubicSplineInitM ( XAry, YAry, Coef, ErrStat, ErrMsg ) + + ! Argument declarations: + + REAL(ReKi), INTENT(OUT) :: Coef (:,:,0:) !< The coefficients for the cubic polynomials + REAL(ReKi), INTENT(IN) :: XAry (:) !< Input array of x values + REAL(ReKi), INTENT(IN) :: YAry (:,:) !< Input array of y values with multiple curves + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations: + + REAL(ReKi), ALLOCATABLE :: DelX (:) ! The distances between the randomly spaced points. + REAL(ReKi), ALLOCATABLE :: Slope (:,:) ! The NumPts-1 length array of slopes between points. + REAL(ReKi), ALLOCATABLE :: U (:) ! An NumPts-1 length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: V (:,:) ! An NumPts-1 by NumCrvs length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: ZHi (:) ! A parameter used to calculate the polynomial coefficients. + REAL(ReKi), ALLOCATABLE :: ZLo (:) ! A parameter used to calculate the polynomial coefficients. + + INTEGER(IntKi) :: ErrStatLcL ! Local error status. + + INTEGER :: I ! The index into the arrays. + INTEGER :: NumCrvs ! Number of curves to be interpolated. + INTEGER :: NumPts ! Number of points in each curve. + CHARACTER(*), PARAMETER :: RoutineName = 'CubicSplineInitM' + + + ! How big are the arrays? + + NumPts = SIZE( XAry ) + NumCrvs = SIZE( YAry, 2 ) + + + ! Allocate the various intermediate arrays. + + ALLOCATE ( ZLo( NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the ZLo array.' ) + RETURN + ENDIF + + ALLOCATE ( ZHi( NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the ZHi array.' ) + RETURN + ENDIF + + ALLOCATE ( DelX( NumPts - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the DelX array.' ) + RETURN + ENDIF + + ALLOCATE ( Slope( NumPts-1, NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the Slope array.' ) + RETURN + ENDIF + + ALLOCATE ( U( NumPts - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the U array.' ) + RETURN + ENDIF + + ALLOCATE ( V( NumPts-1, NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the V array.' ) + RETURN + ENDIF + + + ! Compute the distance between XAry values and the slopes between points. + + DO I=1,NumPts-1 + DelX (I ) = XAry(I+1 ) - XAry(I ) + + if ( equalRealNos( DelX(I), 0.0_ReKi ) ) then + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':XAry must have unique values.' ) + RETURN + ENDIF + + Slope(I,:) = ( YAry(I+1,:) - YAry(I,:) )/DelX(I) + END DO ! I + + + ! Use Gaussian elimination to solve the tri-diagonal matrix. + + U(1 ) = 2.0_ReKi*( DelX (2) + DelX (1 ) ) + V(1,:) = 6.0_ReKi*( Slope(2,:) - Slope(1,:) ) + + DO I=2,NumPts-1 + if ( equalRealNos( U(I-1), 0.0_ReKi ) ) then + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':XAry must be monotonic.' ) + RETURN + ENDIF + + U(I) = 2.0_ReKi*( DelX (I-1) + DelX (I) ) - DelX(I-1)*DelX(I-1 )/U(I-1) + V(I,:) = 6.0_ReKi*( Slope(I,:) - Slope(I-1,:) ) - DelX(I-1)* V(I-1,:)/U(I-1) + END DO ! I + + + ! Determine the coefficients of the polynomials. + + Coef(:,:,0) = YAry(1:NumPts-1,:) + + ZHi(:) = 0.0_ReKi + + DO I=NumPts-1,1,-1 + ZLo(:) = ( V(I,:) - DelX(I)*ZHi(:) )/U(I) ! bjj: already checked for u(I) == 0 + Coef(I,:,1) = Slope(I,:) - DelX(I)*( ZHi(:)/6.0_ReKi + ZLo(:)/3.0_ReKi ) + Coef(I,:,2) = 0.5_ReKi*ZLo(:) + Coef(I,:,3) = ( ZHi(:) - ZLo(:) )/( 6.0_ReKi*DelX(I) ) ! bjj: already checked for DelX(I) == 0 + ZHi(:) = ZLo(:) + END DO ! I + + CALL ExitThisRoutine ( ErrID_None, 'No Problemo' ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + ! Deallocate the Words array if it had been allocated. + + IF ( ALLOCATED( DelX ) ) DEALLOCATE( DelX ) + IF ( ALLOCATED( Slope ) ) DEALLOCATE( Slope ) + IF ( ALLOCATED( U ) ) DEALLOCATE( U ) + IF ( ALLOCATED( V ) ) DEALLOCATE( V ) + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE CubicSplineInitM ! ( XAry, YAry, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine calculates the parameters needed to compute a irregularly-spaced natural linear spline. +!! This routine does not require that the XAry be regularly spaced. + SUBROUTINE CubicLinSplineInitM ( XAry, YAry, Coef, ErrStat, ErrMsg ) + + ! Argument declarations: + + REAL(ReKi), INTENT(OUT) :: Coef (:,:,0:) !< The coefficients for the cubic polynomials + REAL(ReKi), INTENT(IN) :: XAry (:) !< Input array of x values + REAL(ReKi), INTENT(IN) :: YAry (:,:) !< Input array of y values with multiple curves + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + REAL(ReKi) :: DelX ! The distances between the randomly spaced points. + + INTEGER :: I ! The index into the arrays. + INTEGER :: NumPts ! Number of points in each curve. + CHARACTER(*), PARAMETER :: RoutineName = 'CubicLinSplineInitM' + + + ! How big are the arrays? + + NumPts = SIZE( XAry ) + ErrStat = ErrID_None + ErrMsg = "" + + ! Determine the coefficients of the polynomials. + + + DO I=NumPts-1,1,-1 + DelX = XAry(I+1 ) - XAry(I ) + + if ( equalRealNos( DelX, 0.0_ReKi ) ) then + CALL SetErrStat ( ErrID_Fatal, 'XAry must have unique values.',ErrStat,ErrMsg,RoutineName ) + RETURN + ENDIF + + + Coef(I,:,0) = YAry(I,:) + Coef(I,:,1) = (YAry(I+1,: ) - YAry(I,: )) / DelX + Coef(I,:,2) = 0.0_ReKi + Coef(I,:,3) = 0.0_ReKi + END DO ! I + + + RETURN + + + END SUBROUTINE CubicLinSplineInitM ! ( XAry, YAry, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine interpolates a pair of arrays using cubic splines to find the function value at X. +!! One must call cubicsplineinit first to compute the coefficients of the cubics. +!! This routine does not require that the XAry be regularly spaced. + FUNCTION CubicSplineInterp ( X, AryLen, XAry, YAry, Coef, ErrStat, ErrMsg ) + + ! Function declaration. + + REAL(ReKi) :: CubicSplineInterp ! This function + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array + + REAL(ReKi), INTENT(IN) :: Coef (AryLen-1,0:3) !< The coefficients for the cubic polynomials + REAL(ReKi), INTENT(IN) :: X !< The value we are trying to interpolate for + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Input array of regularly spaced x values + REAL(ReKi), INTENT(IN) :: YAry (AryLen) !< Input array of y values + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + REAL(ReKi) :: XOff ! The distance from X to XAry(ILo). + +! INTEGER(IntKi) :: ErrStatLcL ! Local error status. + INTEGER :: ILo ! The index into the array for which X is just above or equal to XAry(ILo). + + + ErrStat = ErrID_None + ErrMsg = "" + + ! See if X is within the range of XAry. Return the end point if it is not. + + IF ( X <= XAry(1) ) THEN + CubicSplineInterp = YAry(1) + RETURN + ELSEIF ( X >= XAry(AryLen) ) THEN + CubicSplineInterp = YAry(AryLen) + RETURN + ENDIF ! ( X <= XAry(1) ) + + + ! We are somewhere inside XAry. Find the segment that bounds X using binary search. + + CALL LocateBin( X, XAry, ILo, AryLen ) + + XOff = X - XAry(ILo) + + CubicSplineInterp = Coef(ILo,0) + XOff*( Coef(ILo,1) + XOff*( Coef(ILo,2) + XOff*Coef(ILo,3) ) ) + + + RETURN + END FUNCTION CubicSplineInterp ! ( X, AryLen, XAry, YAry, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine interpolates a pair of arrays using cubic splines to find the function value at X. +!! One must call cubicsplineinit first to compute the coefficients of the cubics. +!! This routine does not require that the XAry be regularly spaced. +!! This version of the routine works with multiple curves that share the same X values. + FUNCTION CubicSplineInterpM ( X, XAry, YAry, Coef, ErrStat, ErrMsg ) RESULT( Res ) + + ! Function declaration. + + REAL(ReKi), ALLOCATABLE :: Res(:) ! The result of this function + + + ! Argument declarations: + + REAL(ReKi), INTENT(IN) :: Coef (:,:,0:) !< The coefficients for the cubic polynomials + REAL(ReKi), INTENT(IN) :: X !< The value we are trying to interpolate for + REAL(ReKi), INTENT(IN) :: XAry (:) !< Input array of regularly spaced x values + REAL(ReKi), INTENT(IN) :: YAry (:,:) !< Input array of y values with multiple curves + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! Local declarations. + + REAL(ReKi) :: XOff ! The distance from X to XAry(ILo). + + INTEGER(IntKi) :: ErrStatLcL ! Local error status. + INTEGER :: ILo ! The index into the array for which X is just above or equal to XAry(ILo). + INTEGER :: NumCrvs ! Number of curves to be interpolated. + INTEGER :: NumPts ! Number of points in each curve. + + CHARACTER(*), PARAMETER :: RoutineName = 'RegCubicSplineInterpM' + + ! How big are the arrays? + + NumPts = SIZE( XAry ) + NumCrvs = SIZE( YAry, 2 ) + !NumCrvs = SIZE( YAry, 2 ) + + ALLOCATE ( Res( NumCrvs ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//':Error allocating memory for the function result array.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = "" + ENDIF + + + ! See if X is within the range of XAry. Return the end point if it is not. + + IF ( X <= XAry(1) ) THEN + Res(:) = YAry(1,:) + RETURN + ELSEIF ( X >= XAry(NumPts) ) THEN + Res(:) = YAry(NumPts,:) + RETURN + ENDIF ! ( X <= XAry(1) ) + + + ! We are somewhere inside XAry. Find the segment that bounds X using binary search. + + CALL LocateBin( X, XAry, ILo, NumPts ) + + XOff = X - XAry(ILo) + + Res(:) = Coef(ILo,:,0) + XOff*( Coef(ILo,:,1) + XOff*( Coef(ILo,:,2) + XOff*Coef(ILo,:,3) ) ) + + RETURN + + END FUNCTION CubicSplineInterpM ! ( X, XAry, YAry, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This function returns the matrix exponential, \f$\Lambda = \exp(\lambda)\f$, of an input skew-symmetric matrix, \f$\lambda\f$. +!! +!! \f$\lambda\f$ is defined as: +!! +!! \f{equation}{ \lambda = \begin{bmatrix} +!! 0 & \lambda_3 & -\lambda_2 \\ +!! -\lambda_3 & 0 & \lambda_1 \\ +!! \lambda_2 & -\lambda_1 & 0 +!! \end{bmatrix} +!! \f} +!! The angle of rotation for \f$\lambda\f$ is +!! \f{equation}{ \theta = \sqrt{{\lambda_1}^2+{\lambda_2}^2+{\lambda_3}^2} \f} +!! +!! The matrix exponential is calculated as +!! \f{equation}{ +!! \Lambda = \exp(\lambda) = \left\{ \begin{matrix} +!! I & \theta = 0 \\ +!! I + \frac{\sin\theta}{\theta}\lambda + \frac{1-\cos\theta}{\theta^2}\lambda^2 & \theta > 0 +!! \end{matrix} \right. +!! \f} +!! +!! This routine is the inverse of DCM_logMap (nwtc_num::dcm_logmap). \n +!! Use DCM_exp (nwtc_num::dcm_exp) instead of directly calling a specific routine in the generic interface. + FUNCTION DCM_expD(lambda) + + + REAL(DbKi), INTENT(IN) :: lambda(3) !< vector containing \f$\lambda_1\f$, \f$\lambda_2\f$, and \f$\lambda_3\f$, the unique components of skew-symmetric matrix \f$\lambda\f$ + REAL(DbKi) :: DCM_expD(3,3) !< the computed matrix exponential, \f$\Lambda\f$ + + ! local variables + REAL(DbKi) :: stheta ! sine of angle of rotation + REAL(DbKi) :: theta ! angle of rotation + REAL(DbKi) :: theta2 ! angle of rotation squared + REAL(DbKi) :: tmp_Mat(3,3) + + INTEGER(IntKi) :: ErrStat + CHARACTER(30) :: ErrMsg + + + theta = TwoNorm(lambda) ! Eq. 32 + theta2 = theta**2 + + IF ( EqualRealNos(theta, 0.0_DbKi) .or. & + EqualRealNos(theta2, 0.0_DbKi) ) THEN ! + + CALL eye(DCM_expD, ErrStat, ErrMsg) ! Eq. 33a + + ELSE + + ! convert lambda to skew-symmetric matrix: + tmp_mat(1,1) = 0.0_DbKi + tmp_mat(2,1) = -lambda(3) + tmp_mat(3,1) = lambda(2) + tmp_mat(1,2) = lambda(3) + tmp_mat(2,2) = 0.0_DbKi + tmp_mat(3,2) = -lambda(1) + tmp_mat(1,3) = -lambda(2) + tmp_mat(2,3) = lambda(1) + tmp_mat(3,3) = 0.0_DbKi + + + ! Eq. 33b + !DCM_exp = I + sin(theta)/theta*tmp_mat + (1-cos(theta))/theta**2)*matmul(tmp_mat,tmp_mat) + + ! one method: + !CALL eye(DCM_exp, ErrStat, ErrMsg) + !DCM_exp = DCM_exp + sin(theta)/theta*tmp_mat + !DCM_exp = DCM_exp + (1-cos(theta))/theta2 * MATMUL(tmp_mat, tmp_mat) + + ! hopefully this order of calculations gives better numerical results: + stheta = sin(theta) + DCM_expD = (1-cos(theta))/theta * tmp_mat + DCM_expD(1,1) = DCM_expD(1,1) + stheta + DCM_expD(2,2) = DCM_expD(2,2) + stheta + DCM_expD(3,3) = DCM_expD(3,3) + stheta + + DCM_expD = matmul( DCM_expD, tmp_mat ) + DCM_expD = DCM_expD / theta + DCM_expD(1,1) = DCM_expD(1,1) + 1.0_DbKi ! add identity + DCM_expD(2,2) = DCM_expD(2,2) + 1.0_DbKi + DCM_expD(3,3) = DCM_expD(3,3) + 1.0_DbKi + + END IF + + + + END FUNCTION DCM_expD +!======================================================================= +!> \copydoc nwtc_num::dcm_expd + FUNCTION DCM_expR(lambda) + ! This function computes a matrix exponential. + ! + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 31-33 + + REAL(ReKi), INTENT(IN) :: lambda(3) !< vector containing unique components of skew-symmetric matrix: \f$\lambda_1\f$, \f$\lambda_2\f$, and \f$\lambda_3\f$ + REAL(ReKi) :: DCM_expR(3,3) !< the computed matrix exponential, \f$\Lambda\f$ + + ! local variables + REAL(ReKi) :: stheta ! sine of angle of rotation + REAL(ReKi) :: theta ! angle of rotation + REAL(ReKi) :: theta2 ! angle of rotation squared + REAL(ReKi) :: tmp_Mat(3,3) + + INTEGER(IntKi) :: ErrStat + CHARACTER(30) :: ErrMsg + + + theta = TwoNorm(lambda) ! Eq. 32 + theta2 = theta**2 + + IF ( EqualRealNos(theta, 0.0_ReKi) .or. & + EqualRealNos(theta2, 0.0_ReKi) ) THEN ! + + CALL eye(DCM_expR, ErrStat, ErrMsg) ! Eq. 33a + + ELSE + + ! convert lambda to skew-symmetric matrix: + !tmp_mat = -SkewSymMat(lambda) + tmp_mat(1,1) = 0.0_ReKi + tmp_mat(2,1) = -lambda(3) + tmp_mat(3,1) = lambda(2) + tmp_mat(1,2) = lambda(3) + tmp_mat(2,2) = 0.0_ReKi + tmp_mat(3,2) = -lambda(1) + tmp_mat(1,3) = -lambda(2) + tmp_mat(2,3) = lambda(1) + tmp_mat(3,3) = 0.0_ReKi + + + ! Eq. 33b + !DCM_exp = I + sin(theta)/theta*tmp_mat + (1-cos(theta))/theta**2)*matmul(tmp_mat,tmp_mat) + + ! one method: + !CALL eye(DCM_exp, ErrStat, ErrMsg) + !DCM_exp = DCM_exp + sin(theta)/theta*tmp_mat + !DCM_exp = DCM_exp + (1-cos(theta))/theta2 * MATMUL(tmp_mat, tmp_mat) + + ! hopefully this order of calculations gives better numerical results: + stheta = sin(theta) + DCM_expR = (1-cos(theta))/theta * tmp_mat + DCM_expR(1,1) = DCM_expR(1,1) + stheta + DCM_expR(2,2) = DCM_expR(2,2) + stheta + DCM_expR(3,3) = DCM_expR(3,3) + stheta + + DCM_expR = matmul( DCM_expR, tmp_mat ) + DCM_expR = DCM_expR / theta + DCM_expR(1,1) = DCM_expR(1,1) + 1.0_ReKi ! add identity + DCM_expR(2,2) = DCM_expR(2,2) + 1.0_ReKi + DCM_expR(3,3) = DCM_expR(3,3) + 1.0_ReKi + + END IF + + + + END FUNCTION DCM_expR +!======================================================================= +!> For any direction cosine matrix (DCM), \f$\Lambda\f$, this routine calculates the +!! logarithmic map, \f$\lambda\f$, which a skew-symmetric matrix: +!! +!! \f{equation}{ +!! \lambda +!! = \log( \Lambda ) +!! = \begin{bmatrix} +!! 0 & \lambda_3 & -\lambda_2 \\ +!! -\lambda_3 & 0 & \lambda_1 \\ +!! \lambda_2 & -\lambda_1 & 0 +!! \end{bmatrix} +!! \f} +!! The angle of rotation for \f$\Lambda\f$ is +!! \f{equation}{ +!! \theta= \begin{matrix} \cos^{-1}\left(\frac{1}{2}\left(\mathrm{trace}(\Lambda)-1\right)\right) & \theta \in \left[0,\pi\right]\end{matrix} +!! \f} +!! And the logarithmic map is +!! \f{equation}{ +!! \lambda = \left\{ \begin{matrix} +!! 0 & \theta = 0 \\ +!! \frac{\theta}{2\sin\theta} \left( \Lambda - \Lambda^T\right) & \theta \in \left(0,\pi\right) \\ +!! \pm\pi v & \theta = \pi +!! \end{matrix} \right. +!! \f} +!! where \f$v\f$ is the skew-symmetric matrix associated with the unit-length eigenvector of \f$\Lambda\f$ associated with the eigenvalue 1. +!! However, this equation has numerical issues near \f$\theta = \pi\f$, so for \f$\theta > 3.1\f$ we instead implement +!! a separate equation to find lambda * sign(lambda(indx_max)) +!! and use \f$\Lambda - \Lambda^T\f$ to choose the appropriate signs. +!! +!! This routine is the inverse of DCM_exp (nwtc_num::dcm_exp). \n +!! Use DCM_logMap (nwtc_num::dcm_logmap) instead of directly calling a specific routine in the generic interface. + SUBROUTINE DCM_logMapD(DCM, logMap, ErrStat, ErrMsg, thetaOut) + + REAL(DbKi), INTENT(IN) :: DCM(3,3) !< the direction cosine matrix, \f$\Lambda\f$ + REAL(DbKi), INTENT( OUT) :: logMap(3) !< vector containing \f$\lambda_1\f$, \f$\lambda_2\f$, and \f$\lambda_3\f$, the unique components of skew-symmetric matrix \f$\lambda\f$ + REAL(DbKi),OPTIONAL,INTENT( OUT) :: thetaOut !< the angle of rotation, \f$\theta\f$; output only for debugging + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: theta + REAL(DbKi) :: cosTheta + REAL(DbKi) :: TwoSinTheta + REAL(DbKi) :: v(3) + REAL(DbKi) :: divisor + INTEGER(IntKi) :: indx_max + + ! initialization + ErrStat = ErrID_None + ErrMsg = "" + + + cosTheta = 0.5_DbKi*( trace(DCM) - 1.0_DbKi ) + cosTheta = min( max(cosTheta,-1.0_DbKi), 1.0_DbKi ) !make sure it's in a valid range (to avoid cases where this is slightly outside the +/-1 range) + theta = ACOS( cosTheta ) ! Eq. 25 ( 0<=theta<=pi ) + + IF ( PRESENT( thetaOut ) ) THEN + thetaOut = theta + END IF + + !> Note that \f$ DCM = \begin{bmatrix} + !! 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_3^2 + \lambda_2^2\right) + !! & \frac{\sin\theta}{\theta}\lambda_3+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_2 + !! & -\frac{\sin\theta}{\theta}\lambda_2+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_3 \\ + !! -\frac{\sin\theta}{\theta}\lambda_3+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_2 + !! & 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_3^2 + \lambda_1^2\right) + !! & \frac{\sin\theta}{\theta}\lambda_1+\frac{1-\cos\theta}{\theta^2}\lambda_2\lambda_3 \\ + !! \frac{\sin\theta}{\theta}\lambda_2+\frac{1-\cos\theta}{\theta^2}\lambda_1\lambda_3 + !! & -\frac{\sin\theta}{\theta}\lambda_1+\frac{1-\cos\theta}{\theta^2}\lambda_2\lambda_3 + !! & 1-\frac{1-\cos\theta}{\theta^2}\left( \lambda_2^2 + \lambda_1^2\right) \\ + !! \end{bmatrix} \f$ + + + !IF ( EqualRealNos( pi_D, theta ) ) THEN + IF ( theta > 3.1_DbKi ) THEN ! theta/(2*sin(theta)) blows up quickly as theta approaches pi, + ! so I'm putting a pretty large tolerance on pi here, and using a different equation to find the solution near pi + + logMap(1) = 1.0_DbKi + DCM(1,1) - DCM(2,2) - DCM(3,3); + logMap(2) = 1.0_DbKi - DCM(1,1) + DCM(2,2) - DCM(3,3); + logMap(3) = 1.0_DbKi - DCM(1,1) - DCM(2,2) + DCM(3,3); + + indx_max = maxloc( abs(logMap), 1 ) + + divisor = sqrt(abs( logMap(indx_max) * 2.0_DbKi*(1.0_DbKi - cosTheta) )) / theta ! 2*(1-cosTheta)/theta^2 * abs(lambda(indx_max)) + if (indx_max == 1) then + !logMap(1) = 1.0 + DCM(1,1) - DCM(2,2) - DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(1) + logMap(2) = DCM(1,2) + DCM(2,1) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(2) + logMap(3) = DCM(1,3) + DCM(3,1) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(3) + elseif (indx_max == 2) then + logMap(1) = DCM(1,2) + DCM(2,1) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(1) + !logMap(2) = 1.0 - DCM(1,1) + DCM(2,2) - DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(2) + logMap(3) = DCM(2,3) + DCM(3,2) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(3) + else + logMap(1) = DCM(1,3) + DCM(3,1) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(1) + logMap(2) = DCM(2,3) + DCM(3,2) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(2) + !logMap(3) = 1.0 - DCM(1,1) - DCM(2,2) + DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(3) + end if + logMap = logMap / divisor ! lambda * sign(lambda(indx_max)) + + ! at this point we may have the wrong sign for logMap (though if theta==pi, it doesn't matter because we can change it in the DCM_setLogMapforInterp() routines) + ! we'll do a little checking to see if we should change the sign: + + IF ( EqualRealNos( pi_D, theta ) ) RETURN + + v(1) = -DCM(3,2) + DCM(2,3) !-skewSym(3,2) = 2*sin(theta)/theta * lambda(1) = (small positive value with theta near pi) * lambda(1) + v(2) = DCM(3,1) - DCM(1,3) ! skewSym(3,1) = 2*sin(theta)/theta * lambda(2) = (small positive value with theta near pi) * lambda(2) + v(3) = -DCM(2,1) + DCM(1,2) !-skewSym(2,1) = 2*sin(theta)/theta * lambda(3) = (small positive value with theta near pi) * lambda(3) + + indx_max = maxloc( abs(v), 1 ) ! find component with largest magnitude + if ( .not. EqualRealNos( sign(1.0_DbKi,v(indx_max)), sign(1.0_DbKi,logMap(indx_max)) )) logMap = -logMap + + ELSE + + TwoSinTheta = 2.0_DbKi*sin(theta) + + IF ( EqualRealNos(0.0_DbKi, theta) .or. EqualRealNos( 0.0_DbKi, TwoSinTheta ) ) THEN + + !skewSym = DCM - TRANSPOSE(DCM) + ! + !logMap(1) = -skewSym(3,2) + !logMap(2) = skewSym(3,1) + !logMap(3) = -skewSym(2,1) + ! + !logMap = 0.5_DbKi * logMap ! Eq. 26b with limit as x approaches 0 of (x/sin(x)) = 1 + + + logMap = 0.0_DbKi ! Eq. 26a + + ELSE ! 0 < theta < pi + + !skewSym = DCM - TRANSPOSE(DCM) + + logMap(1) = -DCM(3,2) + DCM(2,3) !-skewSym(3,2) + logMap(2) = DCM(3,1) - DCM(1,3) ! skewSym(3,1) + logMap(3) = -DCM(2,1) + DCM(1,2) !-skewSym(2,1) + + logMap = theta / TwoSinTheta * logMap ! Eq. 26b + END IF + + END IF + + + END SUBROUTINE DCM_logMapD +!======================================================================= +!> \copydoc nwtc_num::dcm_logmapd + SUBROUTINE DCM_logMapR(DCM, logMap, ErrStat, ErrMsg, thetaOut) + + ! This function computes the logarithmic map for a direction cosine matrix. + + REAL(ReKi), INTENT(IN) :: DCM(3,3) + REAL(ReKi), INTENT( OUT) :: logMap(3) + REAL(ReKi),OPTIONAL,INTENT( OUT) :: thetaOut + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + REAL(ReKi) :: cosTheta + REAL(ReKi) :: theta + REAL(ReKi) :: TwoSinTheta + REAL(ReKi) :: v(3) + REAL(ReKi) :: divisor + INTEGER(IntKi) :: indx_max + + ! initialization + ErrStat = ErrID_None + ErrMsg = "" + + + cosTheta = 0.5_ReKi*( trace(DCM) - 1.0_ReKi ) + cosTheta = min( max(cosTheta,-1.0_ReKi), 1.0_ReKi ) !make sure it's in a valid range (to avoid cases where this is slightly outside the +/-1 range) + theta = ACOS( cosTheta ) ! Eq. 25 ( 0<=theta<=pi ) + + + !IF ( EqualRealNos( pi, theta ) ) THEN + IF ( theta > 3.1_ReKi ) THEN ! theta/(2*sin(theta)) blows up quickly as theta approaches pi, + ! so I'm putting a pretty large tolerance on pi here, and using a different equation to find the solution near pi + + logMap(1) = 1.0_ReKi + DCM(1,1) - DCM(2,2) - DCM(3,3); + logMap(2) = 1.0_ReKi - DCM(1,1) + DCM(2,2) - DCM(3,3); + logMap(3) = 1.0_ReKi - DCM(1,1) - DCM(2,2) + DCM(3,3); + + indx_max = maxloc( abs(logMap), 1 ) + + divisor = sqrt(abs( logMap(indx_max) * 2.0_ReKi*(1.0_ReKi - cosTheta) )) / theta ! 2*(1-cosTheta)/theta^2 * abs(lambda(indx_max)) + if (indx_max == 1) then + !logMap(1) = 1.0 + DCM(1,1) - DCM(2,2) - DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(1) + logMap(2) = DCM(1,2) + DCM(2,1) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(2) + logMap(3) = DCM(1,3) + DCM(3,1) ! 2*(1-cosTheta)/theta^2 * lambda(1) * lambda(3) + elseif (indx_max == 2) then + logMap(1) = DCM(1,2) + DCM(2,1) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(1) + !logMap(2) = 1.0 - DCM(1,1) + DCM(2,2) - DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(2) + logMap(3) = DCM(2,3) + DCM(3,2) ! 2*(1-cosTheta)/theta^2 * lambda(2) * lambda(3) + else + logMap(1) = DCM(1,3) + DCM(3,1) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(1) + logMap(2) = DCM(2,3) + DCM(3,2) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(2) + !logMap(3) = 1.0 - DCM(1,1) - DCM(2,2) + DCM(3,3) ! 2*(1-cosTheta)/theta^2 * lambda(3) * lambda(3) + end if + logMap = logMap / divisor ! lambda * sign(lambda(indx)) + + ! at this point we may have the wrong sign for logMap (though if theta==pi, it doesn't matter because we can change it in the DCM_setLogMapforInterp() routines) + ! we'll do a little checking to see if we should change the sign: + + IF ( EqualRealNos( pi, theta ) ) RETURN + + v(1) = -DCM(3,2) + DCM(2,3) !-skewSym(3,2) + v(2) = DCM(3,1) - DCM(1,3) ! skewSym(3,1) + v(3) = -DCM(2,1) + DCM(1,2) !-skewSym(2,1) + + indx_max = maxloc( abs(v), 1 ) ! find component with largest magnitude + if ( .not. EqualRealNos( sign(1.0_ReKi,v(indx_max)), sign(1.0_ReKi,logMap(indx_max)) )) logMap = -logMap + + ELSE + + TwoSinTheta = 2.0_ReKi*sin(theta) + + IF ( EqualRealNos(0.0_ReKi, theta) .or. EqualRealNos( 0.0_ReKi, TwoSinTheta ) ) THEN + + !skewSym = DCM - TRANSPOSE(DCM) + ! + !logMap(1) = -skewSym(3,2) + !logMap(2) = skewSym(3,1) + !logMap(3) = -skewSym(2,1) + ! + !logMap = 0.5_ReKi * logMap ! Eq. 26b with limit as x approaches 0 of (x/sin(x)) = 1 + + + logMap = 0.0_ReKi ! Eq. 26a + + ELSE ! 0 < theta < pi + + logMap(1) = -DCM(3,2) + DCM(2,3) !-skewSym(3,2) + logMap(2) = DCM(3,1) - DCM(1,3) ! skewSym(3,1) + logMap(3) = -DCM(2,1) + DCM(1,2) !-skewSym(2,1) + + logMap = theta / TwoSinTheta * logMap ! Eq. 26b + END IF + + END IF + + IF ( PRESENT( thetaOut ) ) THEN + thetaOut = theta + END IF + + END SUBROUTINE DCM_logMapR +!======================================================================= +!> This routine sets the rotation parameters (logMap tensors from dcm_logmap) +!! so that they can be appropriately interpolated, based on +!! continunity of the neighborhood. The tensor input matrix has columns +!! of rotational parameters; one column for each set of values to be +!! interpolated (i.e., for each column, i, tensor(:,i) is the returned logMap value from the routine dcm_logmap). +!! +!! This is based on the \f$2\pi\f$ periodicity of rotations: \n +!! if \f$\lambda\f$ is one solution to \f$\log(\Lambda)\f$, then so is +!! \f$\lambda_k = \lambda \left( 1 + \frac{2k\pi}{\left\| \lambda \right\|}\right)\f$ for any integer k. +!! +!! Use DCM_SetLogMapForInterp (nwtc_num::dcm_setlogmapforinterp) instead of directly calling a specific routine in the generic interface. + SUBROUTINE DCM_SetLogMapForInterpD( tensor ) + + REAL(DbKi), INTENT(INOUT) :: tensor(:,:) !< a 3xn matrix, whose columns represent individual skew-symmmetric matrices. On exit, + !! each column will be within \f$2\pi\f$ of the previous column, allowing for interpolation + !! of the quantities. + + REAL(DbKi) :: diff1, diff2 ! magnitude-squared of difference between two adjacent values + REAL(DbKi) :: temp(3), temp1(3) ! difference between two tensors + REAL(DbKi) :: period(3) ! the period to add to the rotational parameters + INTEGER(IntKi) :: nc ! size of the tensors matrix + INTEGER(IntKi) :: ic ! loop counters for each array dimension + + nc = size(tensor,2) + + ! + do ic=2,nc + + diff1 = TwoNorm( tensor(:,ic) ) + + if ( .NOT. EqualRealNos( diff1, 0.0_DbKi) ) then + ! check if we're going around a 2pi boundary: + + period = tensor(:,ic) * ( Twopi_D/diff1 ) + + temp1 = tensor(:,ic-1) - tensor(:,ic) + diff1 = DOT_PRODUCT( temp1, temp1 ) + + ! try for k < 0 + temp = temp1 + period !k=-1; + diff2 = DOT_PRODUCT( temp, temp ) + + if (diff2 < diff1) then + + do while (diff2 < diff1) + tensor(:,ic) = tensor(:,ic) - period !k=k-1 + + diff1 = diff2 + temp = temp + period !k=k-1; % = tensor(:,ic-1) - tensor(:,ic) + diff2 = DOT_PRODUCT( temp, temp ) + end do + + else + ! try for k > 0 + + ! check if the new value is too small: + temp = temp1 - period !k=+1; + diff2 = DOT_PRODUCT( temp, temp ) + + do while (diff2 < diff1) + tensor(:,ic) = tensor(:,ic) + period !k=k+1 + + diff1 = diff2 + temp = temp - period !k=k+1; % = tensor(:,ic-1) - tensor(:,ic) + diff2 = DOT_PRODUCT( temp, temp ) + end do + + end if + + end if ! tensor vector isn't zero=length + + end do + + END SUBROUTINE DCM_SetLogMapForInterpD +!======================================================================= +!> \copydoc nwtc_num::dcm_setlogmapforinterpd + SUBROUTINE DCM_SetLogMapForInterpR( tensor ) + + ! this routine sets the rotation parameters (tensors from DCM_logMap) + ! so that they can be appropriately interpolated, based on + ! continunity of the neighborhood. The tensor input matrix has columns + ! of rotational parameters; one column for each set of values to be + ! interpolated + ! + ! This is based on the 2pi periodicity of rotations: + ! if tensor is one solution to DCM_logMap( DCM ), then so is + ! tensor*( 1 + TwoPi*k/TwoNorm(tensor) ) for any integer k + + + REAL(ReKi), INTENT(INOUT) :: tensor(:,:) + + REAL(ReKi) :: diff1, diff2 ! magnitude-squared of difference between two adjacent values + REAL(ReKi) :: temp(3), temp1(3) ! difference between two tensors + REAL(ReKi) :: period(3) ! the period to add to the rotational parameters + INTEGER(IntKi) :: nc ! size of the tensors matrix + INTEGER(IntKi) :: ic ! loop counters for each array dimension + + nc = size(tensor,2) + + ! + do ic=2,nc + + diff1 = TwoNorm( tensor(:,ic) ) + + if ( .NOT. EqualRealNos( diff1, 0.0_ReKi) ) then + ! check if we're going around a 2pi boundary: + + period = tensor(:,ic) * ( Twopi/diff1 ) + + temp1 = tensor(:,ic-1) - tensor(:,ic) + diff1 = DOT_PRODUCT( temp1, temp1 ) + + ! try for k < 0 + temp = temp1 + period !k=-1; + diff2 = DOT_PRODUCT( temp, temp ) + + if (diff2 < diff1) then + + do while (diff2 < diff1) + tensor(:,ic) = tensor(:,ic) - period !k=k-1 + + diff1 = diff2 + temp = temp + period !k=k-1; % = tensor(:,ic-1) - tensor(:,ic) + diff2 = DOT_PRODUCT( temp, temp ) + end do + + else + ! try for k > 0 + + ! check if the new value is too small: + temp = temp1 - period !k=+1; + diff2 = DOT_PRODUCT( temp, temp ) + + do while (diff2 < diff1) + tensor(:,ic) = tensor(:,ic) + period !k=k+1 + + diff1 = diff2 + temp = temp - period !k=k+1; % = tensor(:,ic-1) - tensor(:,ic) + diff2 = DOT_PRODUCT( temp, temp ) + end do + + end if + + end if ! tensor vector isn't zero=length + + end do + + END SUBROUTINE DCM_SetLogMapForInterpR +!======================================================================= +!> This function compares two real numbers and determines if they +!! are "almost" equal, i.e. within some relative tolerance (basically ignoring the last 2 significant digits) +!! (see "Safe Comparisons" suggestion from http://www.lahey.com/float.htm) +!! +!! Note that the numbers are added together in this routine, so overflow can result if comparing two "huge" numbers. \n +!! Use EqualRealNos (nwtc_num::equalrealnos) instead of directly calling a specific routine in the generic interface. + FUNCTION EqualRealNos4 ( ReNum1, ReNum2 ) + + ! passed variables + + REAL(SiKi), INTENT(IN ) :: ReNum1 !< the first real number to compare + REAL(SiKi), INTENT(IN ) :: ReNum2 !< the second real number to compare + + LOGICAL :: EqualRealNos4 !< .true. if and only if the numbers are almost equal + + ! local variables + REAL(SiKi), PARAMETER :: Eps = EPSILON(ReNum1) ! machine precision + REAL(SiKi), PARAMETER :: Tol = 100.0_SiKi*Eps / 2.0_SiKi ! absolute tolerance (ignore the last 2 significant digits) + + REAL(SiKi) :: Fraction + + + ! make sure we're never trying to get more precision than Tol + + Fraction = MAX( ABS(ReNum1+ReNum2), 1.0_SiKi ) + + + + ! determine if ReNum1 and ReNum2 are approximately equal + + IF ( ABS(ReNum1 - ReNum2) <= Fraction*Tol ) THEN ! the relative error + EqualRealNos4 = .TRUE. + ELSE + EqualRealNos4 = .FALSE. + ENDIF + + + END FUNCTION EqualRealNos4 +!======================================================================= +!> \copydoc nwtc_num::equalrealnos4 + FUNCTION EqualRealNos8 ( ReNum1, ReNum2 ) + + ! passed variables + + REAL(R8Ki), INTENT(IN ) :: ReNum1 ! the first real number to compare + REAL(R8Ki), INTENT(IN ) :: ReNum2 ! the second real number to compare + + LOGICAL :: EqualRealNos8 !< .true. if and only if the numbers are almost equal + + ! local variables + REAL(R8Ki), PARAMETER :: Eps = EPSILON(ReNum1) ! machine precision + REAL(R8Ki), PARAMETER :: Tol = 100.0_R8Ki*Eps / 2.0_R8Ki ! absolute tolerance (ignore the last 2 significant digits) + + REAL(R8Ki) :: Fraction + + + ! make sure we're never trying to get more precision than Tol + + Fraction = MAX( ABS(ReNum1+ReNum2), 1.0_R8Ki ) + + + + ! determine if ReNum1 and ReNum2 are approximately equal + + IF ( ABS(ReNum1 - ReNum2) <= Fraction*Tol ) THEN ! the relative error + EqualRealNos8 = .TRUE. + ELSE + EqualRealNos8 = .FALSE. + ENDIF + + + END FUNCTION EqualRealNos8 +!======================================================================= +!> \copydoc nwtc_num::equalrealnos4 + FUNCTION EqualRealNos16 ( ReNum1, ReNum2 ) + + ! passed variables + + REAL(QuKi), INTENT(IN ) :: ReNum1 ! the first real number to compare + REAL(QuKi), INTENT(IN ) :: ReNum2 ! the second real number to compare + + LOGICAL :: EqualRealNos16 !< .true. if and only if the numbers are almost equal + + ! local variables + REAL(QuKi), PARAMETER :: Eps = EPSILON(ReNum1) ! machine precision + REAL(QuKi), PARAMETER :: Tol = 100.0_QuKi*Eps / 2.0_QuKi ! absolute tolerance (ignore the last 2 significant digits) + + REAL(QuKi) :: Fraction + + + ! make sure we're never trying to get more precision than Tol + + Fraction = MAX( ABS(ReNum1+ReNum2), 1.0_QuKi ) + + + + ! determine if ReNum1 and ReNum2 are approximately equal + + IF ( ABS(ReNum1 - ReNum2) <= Fraction*Tol ) THEN ! the relative error + EqualRealNos16 = .TRUE. + ELSE + EqualRealNos16 = .FALSE. + ENDIF + + + END FUNCTION EqualRealNos16 +!======================================================================= +!> This function creates a rotation matrix, M, from a 1-2-3 rotation +!! sequence of the 3 Euler angles, \f$\theta_x\f$, \f$\theta_y\f$, and \f$\theta_z\f$, in radians. +!! M represents a change of basis (from global to local coordinates; +!! not a physical rotation of the body). It is the inverse of EulerExtract (nwtc_num::eulerextract). +!! +!! \f{eqnarray*}{ +!! M & = & R(\theta_z) R(\theta_y) R(\theta_x) \\ +!! & = & \begin{bmatrix} \cos(\theta_z) & \sin(\theta_z) & 0 \\ +!! -\sin(\theta_z) & \cos(\theta_z) & 0 \\ +!! 0 & 0 & 1 \end{bmatrix} +!! \begin{bmatrix} \cos(\theta_y) & 0 & -\sin(\theta_y) \\ +!! 0 & 1 & 0 \\ +!! \sin(\theta_y) & 0 & \cos(\theta_y) \end{bmatrix} +!! \begin{bmatrix} 1 & 0 & 0 \\ +!! 0 & \cos(\theta_x) & \sin(\theta_x) \\ +!! 0 & -\sin(\theta_x) & \cos(\theta_x) \end{bmatrix} \\ +!! & = & \begin{bmatrix} +!! \cos(\theta_y)\cos(\theta_z) & \cos(\theta_x)\sin(\theta_z)+\sin(\theta_x)\sin(\theta_y)\cos(\theta_z) & +!! \sin(\theta_x)\sin(\theta_z)-\cos(\theta_x)\sin(\theta_y)\cos(\theta_z) \\ +!! -\cos(\theta_y)\sin(\theta_z) & \cos(\theta_x)\cos(\theta_z)-\sin(\theta_x)\sin(\theta_y)\sin(\theta_z) & +!! \sin(\theta_x)\cos(\theta_z)+\cos(\theta_x)\sin(\theta_y)\sin(\theta_z) \\ +!! \sin(\theta_y) & -\sin(\theta_x)\cos(\theta_y) & \cos(\theta_x)\cos(\theta_y) \\ +!! \end{bmatrix} +!! \f} +!! Use EulerConstruct (nwtc_num::eulerconstruct) instead of directly calling a specific routine in the generic interface. + FUNCTION EulerConstructR4(theta) result(M) + + + REAL(SiKi) :: M(3,3) !< rotation matrix, M + REAL(SiKi), INTENT(IN) :: theta(3) !< the 3 rotation angles: \f$\theta_x, \theta_y, \theta_z\f$ + + REAL(SiKi) :: cx ! cos(theta_x) + REAL(SiKi) :: sx ! sin(theta_x) + REAL(SiKi) :: cy ! cos(theta_y) + REAL(SiKi) :: sy ! sin(theta_y) + REAL(SiKi) :: cz ! cos(theta_z) + REAL(SiKi) :: sz ! sin(theta_z) + + + cx = cos( theta(1) ) + sx = sin( theta(1) ) + + cy = cos( theta(2) ) + sy = sin( theta(2) ) + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + M(1,1) = cy*cz + M(2,1) = -cy*sz + M(3,1) = sy + + M(1,2) = cx*sz+sx*sy*cz + M(2,2) = cx*cz-sx*sy*sz + M(3,2) = -sx*cy + + M(1,3) = sx*sz-cx*sy*cz + M(2,3) = sx*cz+cx*sy*sz + M(3,3) = cx*cy + + END FUNCTION EulerConstructR4 +!======================================================================= +!> \copydoc nwtc_num::eulerconstructr4 + FUNCTION EulerConstructR8(theta) result(M) + + ! this function creates a rotation matrix, M, from a 1-2-3 rotation + ! sequence of the 3 Euler angles, theta_x, theta_y, and theta_z, in radians. + ! M represents a change of basis (from global to local coordinates; + ! not a physical rotation of the body). it is the inverse of EulerExtract (nwtc_num::eulerextract). + ! + ! M = R(theta_z) * R(theta_y) * R(theta_x) + ! = [ cz sz 0 | [ cy 0 -sy | [ 1 0 0 | + ! |-sz cz 0 | * | 0 1 0 | * | 0 cx sx | + ! | 0 0 1 ] | sy 0 cy ] | 0 -sx cx ] + ! = [ cy*cz cx*sz+sx*sy*cz sx*sz-cx*sy*cz | + ! |-cy*sz cx*cz-sx*sy*sz sx*cz+cx*sy*sz | + ! | sy -sx*cy cx*cy ] + ! where cz = cos(theta_z), sz = sin(theta_z), cy = cos(theta_y), etc. + + REAL(R8Ki) :: M(3,3) ! rotation matrix M + REAL(R8Ki), INTENT(IN) :: theta(3) ! the 3 rotation angles: theta_x, theta_y, theta_z + + REAL(R8Ki) :: cx ! cos(theta_x) + REAL(R8Ki) :: sx ! sin(theta_x) + REAL(R8Ki) :: cy ! cos(theta_y) + REAL(R8Ki) :: sy ! sin(theta_y) + REAL(R8Ki) :: cz ! cos(theta_z) + REAL(R8Ki) :: sz ! sin(theta_z) + + + cx = cos( theta(1) ) + sx = sin( theta(1) ) + + cy = cos( theta(2) ) + sy = sin( theta(2) ) + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + M(1,1) = cy*cz + M(2,1) = -cy*sz + M(3,1) = sy + + M(1,2) = cx*sz+sx*sy*cz + M(2,2) = cx*cz-sx*sy*sz + M(3,2) = -sx*cy + + M(1,3) = sx*sz-cx*sy*cz + M(2,3) = sx*cz+cx*sy*sz + M(3,3) = cx*cy + + END FUNCTION EulerConstructR8 +!======================================================================= +!> \copydoc nwtc_num::eulerconstructr4 + FUNCTION EulerConstructR16(theta) result(M) + + ! this function creates a rotation matrix, M, from a 1-2-3 rotation + ! sequence of the 3 Euler angles, theta_x, theta_y, and theta_z, in radians. + ! M represents a change of basis (from global to local coordinates; + ! not a physical rotation of the body). it is the inverse of EulerExtract(). + ! + ! M = R(theta_z) * R(theta_y) * R(theta_x) + ! = [ cz sz 0 | [ cy 0 -sy | [ 1 0 0 | + ! |-sz cz 0 | * | 0 1 0 | * | 0 cx sx | + ! | 0 0 1 ] | sy 0 cy ] | 0 -sx cx ] + ! = [ cy*cz cx*sz+sx*sy*cz sx*sz-cx*sy*cz | + ! |-cy*sz cx*cz-sx*sy*sz sx*cz+cx*sy*sz | + ! | sy -sx*cy cx*cy ] + ! where cz = cos(theta_z), sz = sin(theta_z), cy = cos(theta_y), etc. + + REAL(QuKi) :: M(3,3) ! rotation matrix M + REAL(QuKi), INTENT(IN) :: theta(3) ! the 3 rotation angles: theta_x, theta_y, theta_z + + REAL(QuKi) :: cx ! cos(theta_x) + REAL(QuKi) :: sx ! sin(theta_x) + REAL(QuKi) :: cy ! cos(theta_y) + REAL(QuKi) :: sy ! sin(theta_y) + REAL(QuKi) :: cz ! cos(theta_z) + REAL(QuKi) :: sz ! sin(theta_z) + + + cx = cos( theta(1) ) + sx = sin( theta(1) ) + + cy = cos( theta(2) ) + sy = sin( theta(2) ) + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + M(1,1) = cy*cz + M(2,1) = -cy*sz + M(3,1) = sy + + M(1,2) = cx*sz+sx*sy*cz + M(2,2) = cx*cz-sx*sy*sz + M(3,2) = -sx*cy + + M(1,3) = sx*sz-cx*sy*cz + M(2,3) = sx*cz+cx*sy*sz + M(3,3) = cx*cy + + END FUNCTION EulerConstructR16 +!======================================================================= +!> if M is a rotation matrix from a 1-2-3 rotation sequence, this function returns +!! the 3 Euler angles, \f$\theta_x\f$, \f$\theta_y\f$, and \f$\theta_z\f$ (in radians), that formed +!! the matrix. M represents a change of basis (from global to local coordinates; +!! not a physical rotation of the body). M is the inverse of EulerConstruct (nwtc_num::eulerconstruct). +!! +!! \f{eqnarray*}{ +!! M & = & R(\theta_z) R(\theta_y) R(\theta_x) \\ +!! & = & \begin{bmatrix} \cos(\theta_z) & \sin(\theta_z) & 0 \\ +!! -\sin(\theta_z) & \cos(\theta_z) & 0 \\ +!! 0 & 0 & 1 \end{bmatrix} +!! \begin{bmatrix} \cos(\theta_y) & 0 & -\sin(\theta_y) \\ +!! 0 & 1 & 0 \\ +!! \sin(\theta_y) & 0 & \cos(\theta_y) \end{bmatrix} +!! \begin{bmatrix} 1 & 0 & 0 \\ +!! 0 & \cos(\theta_x) & \sin(\theta_x) \\ +!! 0 & -\sin(\theta_x) & \cos(\theta_x) \end{bmatrix} \\ +!! & = & \begin{bmatrix} +!! \cos(\theta_y)\cos(\theta_z) & \cos(\theta_x)\sin(\theta_z)+\sin(\theta_x)\sin(\theta_y)\cos(\theta_z) & +!! \sin(\theta_x)\sin(\theta_z)-\cos(\theta_x)\sin(\theta_y)\cos(\theta_z) \\ +!! -\cos(\theta_y)\sin(\theta_z) & \cos(\theta_x)\cos(\theta_z)-\sin(\theta_x)\sin(\theta_y)\sin(\theta_z) & +!! \sin(\theta_x)\cos(\theta_z)+\cos(\theta_x)\sin(\theta_y)\sin(\theta_z) \\ +!! \sin(\theta_y) & -\sin(\theta_x)\cos(\theta_y) & \cos(\theta_x)\cos(\theta_y) \\ +!! \end{bmatrix} +!! \f} +!! returned angles are in the range \f$\theta_x,\theta_y, \theta_z \in \left[ \pi, -\pi \right]\f$ \n +!! Use EulerExtract (nwtc_num::eulerextract) instead of directly calling a specific routine in the generic interface. + FUNCTION EulerExtractR4(M) result(theta) + + + REAL(SiKi), INTENT(IN) :: M(3,3) !< rotation matrix, M + REAL(SiKi) :: theta(3) !< the 3 rotation angles: \f$\theta_x, \theta_y, \theta_z\f$ + + REAL(SiKi) :: cx ! cos(theta_x) + REAL(SiKi) :: sx ! sin(theta_x) + REAL(SiKi) :: cy ! cos(theta_y) +! REAL(SiKi) :: sy ! sin(theta_y) + REAL(SiKi) :: cz ! cos(theta_z) + REAL(SiKi) :: sz ! sin(theta_z) + + ! use trig identity sz**2 + cz**2 = 1 to get abs(cy): + cy = sqrt( m(1,1)**2 + m(2,1)**2 ) +! cy = sqrt( m(3,3)**2 + m(3,2)**2 ) + + if ( EqualRealNos(cy,0.0_SiKi) ) then + !if ( cy < 16*epsilon(0.0_ReKi) ) then + + theta(2) = atan2( m(3,1), cy ) ! theta_y + + ! cy = 0 -> sy = +/- 1 + ! M = [ 0 cx*sz+/-sx*cz sx*sz-/+cx*cz | + ! | 0 cx*cz-/+sx*sz sx*cz+/-cx*sz | + ! |+/-1 0 0 ] + + ! gimbal lock allows us to choose theta_z = 0 + theta(3) = 0.0_SiKi ! theta_z + + ! which reduces the matrix to + ! M = [ 0 +/-sx -/+cx | + ! | 0 cx sx | + ! |+/-1 0 0 ] + + theta(1) = atan2( m(2,3), m(2,2) ) ! theta_x + + else + ! atan2( cy*sz, cy*cz ) + theta(3) = atan2( -m(2,1), m(1,1) ) ! theta_z + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + ! get the appropriate sign for cy: + if ( EqualRealNos(cz, 0.0_SiKi) ) then + cy = sign( cy, -m(2,1)/sz ) + !cy = -m(2,1)/sz + else + cy = sign( cy, m(1,1)/cz ) + !cy = -m(1,1)/cz + end if + theta(2) = atan2( m(3,1), cy ) ! theta_y + + !theta(1) = atan2( -m(3,2), m(3,3) ) ! theta_x + + ! for numerical reasons, we're going to get theta_x using + ! M' = (R(theta_z) * R(theta_y))^T * M = R(theta_x) + ! = [ cy 0 sy | [ cz -sz 0 | [ 1 0 0 | + ! | 0 1 0 | * | sz cz 0 | * M = | 0 cx sx | + ! |-sy 0 cy ] | 0 0 1 ] | 0 -sx cx ] + ! = [ cy*cz -cy*sz sy | [ 1 0 0 | + ! | sz cz 0 | * M = | 0 cx sx | + ! |-sy*cz sy*sz cy ] | 0 -sx cx ] + ! taking M'(2,2) and M'(2,3) , we get cx and sx: + ! sz*m(1,2) + cz*m(2,2) = cx + ! sz*m(1,3) + cz*m(2,3) = sx + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + cx = sz*m(1,2) + cz*m(2,2) + sx = sz*m(1,3) + cz*m(2,3) + + theta(1) = atan2( sx, cx ) + + end if + + + END FUNCTION EulerExtractR4 +!======================================================================= +!> \copydoc nwtc_num::eulerextractr4 + FUNCTION EulerExtractR8(M) result(theta) + + ! if M is a rotation matrix from a 1-2-3 rotation sequence, this function returns + ! the 3 Euler angles, theta_x, theta_y, and theta_z (in radians), that formed + ! the matrix. M represents a change of basis (from global to local coordinates; + ! not a physical rotation of the body). M is the inverse of EulerConstruct(). + ! + ! M = R(theta_z) * R(theta_y) * R(theta_x) + ! = [ cz sz 0 | [ cy 0 -sy | [ 1 0 0 | + ! |-sz cz 0 | * | 0 1 0 | * | 0 cx sx | + ! | 0 0 1 ] | sy 0 cy ] | 0 -sx cx ] + ! = [ cy*cz cx*sz+sx*sy*cz sx*sz-cx*sy*cz | + ! |-cy*sz cx*cz-sx*sy*sz sx*cz+cx*sy*sz | + ! | sy -sx*cy cx*cy ] + ! where cz = cos(theta_z), sz = sin(theta_z), cy = cos(theta_y), etc. + ! + ! returned angles are in the range [-pi, pi] + + REAL(R8Ki), INTENT(IN) :: M(3,3) ! rotation matrix M + REAL(R8Ki) :: theta(3) ! the 3 rotation angles: theta_x, theta_y, theta_z + + REAL(R8Ki) :: cx ! cos(theta_x) + REAL(R8Ki) :: sx ! sin(theta_x) + REAL(R8Ki) :: cy ! cos(theta_y) +! REAL(R8Ki) :: sy ! sin(theta_y) + REAL(R8Ki) :: cz ! cos(theta_z) + REAL(R8Ki) :: sz ! sin(theta_z) + + ! use trig identity sz**2 + cz**2 = 1 to get abs(cy): + cy = sqrt( m(1,1)**2 + m(2,1)**2 ) +! cy = sqrt( m(3,3)**2 + m(3,2)**2 ) + + if ( EqualRealNos(cy,0.0_R8Ki) ) then + !if ( cy < 16*epsilon(0.0_ReKi) ) then + + theta(2) = atan2( m(3,1), cy ) ! theta_y + + ! cy = 0 -> sy = +/- 1 + ! M = [ 0 cx*sz+/-sx*cz sx*sz-/+cx*cz | + ! | 0 cx*cz-/+sx*sz sx*cz+/-cx*sz | + ! |+/-1 0 0 ] + + ! gimbal lock allows us to choose theta_z = 0 + theta(3) = 0.0_R8Ki ! theta_z + + ! which reduces the matrix to + ! M = [ 0 +/-sx -/+cx | + ! | 0 cx sx | + ! |+/-1 0 0 ] + + theta(1) = atan2( m(2,3), m(2,2) ) ! theta_x + + else + ! atan2( cy*sz, cy*cz ) + theta(3) = atan2( -m(2,1), m(1,1) ) ! theta_z + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + ! get the appropriate sign for cy: + if ( EqualRealNos(cz, 0.0_R8Ki) ) then + cy = sign( cy, -m(2,1)/sz ) + !cy = -m(2,1)/sz + else + cy = sign( cy, m(1,1)/cz ) + !cy = -m(1,1)/cz + end if + theta(2) = atan2( m(3,1), cy ) ! theta_y + + !theta(1) = atan2( -m(3,2), m(3,3) ) ! theta_x + + ! for numerical reasons, we're going to get theta_x using + ! M' = (R(theta_z) * R(theta_y))^T * M = R(theta_x) + ! = [ cy 0 sy | [ cz -sz 0 | [ 1 0 0 | + ! | 0 1 0 | * | sz cz 0 | * M = | 0 cx sx | + ! |-sy 0 cy ] | 0 0 1 ] | 0 -sx cx ] + ! = [ cy*cz -cy*sz sy | [ 1 0 0 | + ! | sz cz 0 | * M = | 0 cx sx | + ! |-sy*cz sy*sz cy ] | 0 -sx cx ] + ! taking M'(2,2) and M'(2,3) , we get cx and sx: + ! sz*m(1,2) + cz*m(2,2) = cx + ! sz*m(1,3) + cz*m(2,3) = sx + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + cx = sz*m(1,2) + cz*m(2,2) + sx = sz*m(1,3) + cz*m(2,3) + + theta(1) = atan2( sx, cx ) + + end if + + + END FUNCTION EulerExtractR8 +!======================================================================= +!> \copydoc nwtc_num::eulerextractr4 + FUNCTION EulerExtractR16(M) result(theta) + + ! if M is a rotation matrix from a 1-2-3 rotation sequence, this function returns + ! the 3 Euler angles, theta_x, theta_y, and theta_z (in radians), that formed + ! the matrix. M represents a change of basis (from global to local coordinates; + ! not a physical rotation of the body). M is the inverse of EulerConstruct(). + ! + ! M = R(theta_z) * R(theta_y) * R(theta_x) + ! = [ cz sz 0 | [ cy 0 -sy | [ 1 0 0 | + ! |-sz cz 0 | * | 0 1 0 | * | 0 cx sx | + ! | 0 0 1 ] | sy 0 cy ] | 0 -sx cx ] + ! = [ cy*cz cx*sz+sx*sy*cz sx*sz-cx*sy*cz | + ! |-cy*sz cx*cz-sx*sy*sz sx*cz+cx*sy*sz | + ! | sy -sx*cy cx*cy ] + ! where cz = cos(theta_z), sz = sin(theta_z), cy = cos(theta_y), etc. + ! + ! returned angles are in the range [-pi, pi] + + REAL(QuKi), INTENT(IN) :: M(3,3) ! rotation matrix M + REAL(QuKi) :: theta(3) ! the 3 rotation angles: theta_x, theta_y, theta_z + + REAL(QuKi) :: cx ! cos(theta_x) + REAL(QuKi) :: sx ! sin(theta_x) + REAL(QuKi) :: cy ! cos(theta_y) +! REAL(QuKi) :: sy ! sin(theta_y) + REAL(QuKi) :: cz ! cos(theta_z) + REAL(QuKi) :: sz ! sin(theta_z) + + ! use trig identity sz**2 + cz**2 = 1 to get abs(cy): + cy = sqrt( m(1,1)**2 + m(2,1)**2 ) +! cy = sqrt( m(3,3)**2 + m(3,2)**2 ) + + if ( EqualRealNos(cy,0.0_QuKi) ) then + !if ( cy < 16*epsilon(0.0_ReKi) ) then + + theta(2) = atan2( m(3,1), cy ) ! theta_y + + ! cy = 0 -> sy = +/- 1 + ! M = [ 0 cx*sz+/-sx*cz sx*sz-/+cx*cz | + ! | 0 cx*cz-/+sx*sz sx*cz+/-cx*sz | + ! |+/-1 0 0 ] + + ! gimbal lock allows us to choose theta_z = 0 + theta(3) = 0.0_QuKi ! theta_z + + ! which reduces the matrix to + ! M = [ 0 +/-sx -/+cx | + ! | 0 cx sx | + ! |+/-1 0 0 ] + + theta(1) = atan2( m(2,3), m(2,2) ) ! theta_x + + else + ! atan2( cy*sz, cy*cz ) + theta(3) = atan2( -m(2,1), m(1,1) ) ! theta_z + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + ! get the appropriate sign for cy: + if ( EqualRealNos(cz, 0.0_QuKi) ) then + cy = sign( cy, -m(2,1)/sz ) + !cy = -m(2,1)/sz + else + cy = sign( cy, m(1,1)/cz ) + !cy = -m(1,1)/cz + end if + theta(2) = atan2( m(3,1), cy ) ! theta_y + + !theta(1) = atan2( -m(3,2), m(3,3) ) ! theta_x + + ! for numerical reasons, we're going to get theta_x using + ! M' = (R(theta_z) * R(theta_y))^T * M = R(theta_x) + ! = [ cy 0 sy | [ cz -sz 0 | [ 1 0 0 | + ! | 0 1 0 | * | sz cz 0 | * M = | 0 cx sx | + ! |-sy 0 cy ] | 0 0 1 ] | 0 -sx cx ] + ! = [ cy*cz -cy*sz sy | [ 1 0 0 | + ! | sz cz 0 | * M = | 0 cx sx | + ! |-sy*cz sy*sz cy ] | 0 -sx cx ] + ! taking M'(2,2) and M'(2,3) , we get cx and sx: + ! sz*m(1,2) + cz*m(2,2) = cx + ! sz*m(1,3) + cz*m(2,3) = sx + + cz = cos( theta(3) ) + sz = sin( theta(3) ) + + cx = sz*m(1,2) + cz*m(2,2) + sx = sz*m(1,3) + cz*m(2,3) + + theta(1) = atan2( sx, cx ) + + end if + + + END FUNCTION EulerExtractR16 +!======================================================================= +!> This routine sets the matrices in the first two dimensions of A equal +!! to the identity matrix (all zeros, with ones on the diagonal). +!! If the first two dimensions of A are not equal (i.e., matrix A(:,:,n) +!! is non-square), this routine returns the pseudo-identity. +!! +!! Use eye (nwtc_num::eye) instead of directly calling a specific routine in the generic interface. + SUBROUTINE Eye2( A, ErrStat, ErrMsg ) + + + REAL(ReKi), INTENT(INOUT) :: A (:,:) !< Array to set to the identity matrix (nr,nc,n) + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT(OUT) :: ErrMsg !< ErrMsg corresponding to ErrStat + + ! local variables + INTEGER :: j ! loop counter + INTEGER :: nr ! number of rows + INTEGER :: nc ! number of columns + + + nr = SIZE(A,1) + nc = SIZE(A,2) + + IF (nr /= nc) THEN + ErrStat = ErrID_Info + ErrMsg = 'NWTC Library, Eye(): Matrix is not square.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + ! initialize to zero: + A = 0._ReKi + + ! set the diagonals to one: + DO j = 1, MIN(nr,nc) ! the diagonal of the matrix + A(j,j) = 1._ReKi + END DO + + END SUBROUTINE Eye2 +!======================================================================= +!> \copydoc nwtc_num::eye2 + SUBROUTINE Eye2D( A, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(INOUT) :: A (:,:) !< Array to set to the identity matrix (nr,nc,n) + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT(OUT) :: ErrMsg !< ErrMsg corresponding to ErrStat + + ! local variables + INTEGER :: j ! loop counter + INTEGER :: nr ! number of rows + INTEGER :: nc ! number of columns + + + nr = SIZE(A,1) + nc = SIZE(A,2) + + IF (nr /= nc) THEN + ErrStat = ErrID_Info + ErrMsg = 'NWTC Library, Eye(): Matrix is not square.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + ! initialize to zero: + A = 0._DbKi + + ! set the diagonals to one: + DO j = 1, MIN(nr,nc) ! the diagonal of the matrix + A(j,j) = 1._DbKi + END DO + + END SUBROUTINE Eye2D +!======================================================================= +!> \copybrief nwtc_num::eye2 + SUBROUTINE Eye3( A, ErrStat, ErrMsg ) + + ! This routine sets each of the n matries A(:,:,n) to the identity + ! matrix (all zeros, with ones on the diagonal). + ! Note that this also returns the "pseudo-identity" when A(:,:) + ! is not square (i.e., nr/=nc). + + REAL(ReKi), INTENT(INOUT) :: A (:,:,:) ! Array to set to the identity matrix (nr,nc,n) + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error level + CHARACTER(*), INTENT(OUT) :: ErrMsg ! ErrMsg corresponding to ErrStat + + ! local variables + INTEGER :: i, j ! loop counters + INTEGER :: nr ! number of rows + INTEGER :: nc ! number of columns + INTEGER :: n ! number of matricies + + + nr = SIZE(A,1) + nc = SIZE(A,2) + n = SIZE(A,3) + + IF (nr /= nc) THEN + ErrStat = ErrID_Info + ErrMsg = 'NWTC Library, Eye(): Matrix is not square.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + ! initialize to zero: + A = 0._ReKi + + ! set the diagonals to one: + DO i = 1, n ! loop through the matrices + DO j = 1, MIN(nr,nc) ! the diagonal of the matrix + A(j,j,i) = 1._ReKi + END DO + END DO + + END SUBROUTINE Eye3 +!======================================================================= +!> \copybrief nwtc_num::eye2 + SUBROUTINE Eye3D( A, ErrStat, ErrMsg ) + + ! This routine sets each of the n matries A(:,:,n) to the identity + ! matrix (all zeros, with ones on the diagonal). + ! Note that this also returns the "pseudo-identity" when A(:,:) + ! is not square (i.e., nr/=nc). + + REAL(DbKi), INTENT(INOUT) :: A (:,:,:) !< Array to set to the identity matrix (nr,nc,n) + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT(OUT) :: ErrMsg !< ErrMsg corresponding to ErrStat + + ! local variables + INTEGER :: i, j ! loop counters + INTEGER :: nr ! number of rows + INTEGER :: nc ! number of columns + INTEGER :: n ! number of matricies + + + nr = SIZE(A,1) + nc = SIZE(A,2) + n = SIZE(A,3) + + IF (nr /= nc) THEN + ErrStat = ErrID_Info + ErrMsg = 'NWTC Library, Eye(): Matrix is not square.' + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + ! initialize to zero: + A = 0._ReKi + + ! set the diagonals to one: + DO i = 1, n ! loop through the matrices + DO j = 1, MIN(nr,nc) ! the diagonal of the matrix + A(j,j,i) = 1._DbKi + END DO + END DO + + END SUBROUTINE Eye3D +!======================================================================= +!> This routine uses the Gauss-Jordan elimination method for the +!! solution of a given set of simultaneous linear equations. +!! NOTE: this routine works if no pivot points are zero and you +!! don't want the eschelon or reduced eschelon form of the +!! augmented matrix. The form of the original augmented matrix +!! IS preserved in this call. +!! This routine was originally in FAST.f90. +!! When AugMatIn = [ A b ], this routine returns the solution +!! vector x to the equation Ax = b. + SUBROUTINE GaussElim( AugMatIn, NumEq, x, ErrStat, ErrMsg ) + + + IMPLICIT NONE + + + ! Passed variables: + + INTEGER(IntKi), INTENT(IN ) :: NumEq !< Number of equations in augmented matrix + + REAL(ReKi), INTENT(IN ) :: AugMatIn (NumEq, NumEq+1 ) !< Augmented matrix passed into this subroutine ( AugMatIn = [ A b ] + REAL(ReKi), INTENT(OUT) :: x (NumEq) !< Solution vector + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT(OUT) :: ErrMsg !< ErrMsg corresponding to ErrStat + + + ! Local variables: + + REAL(ReKi) :: AugMat (NumEq,( NumEq + 1 )) ! The augmented matrix [A b] + + INTEGER(IntKi) :: I ! Steps through columns + INTEGER(IntKi) :: J ! Steps through rows + INTEGER(IntKi) :: L ! Steps through rows + INTEGER(IntKi) :: NAug ! Column dimension of augmented matrix + + + ! Initialize variables: + + ErrStat = ErrID_None ! No error has occurred + NAug = NumEq + 1 ! The column dimension of the augmented matrix + + + ! Create the augmented matrix, AugMat = [A b] (we make a copy so we don't overwrite the existing matrix): + + AugMat = AugMatIn + + + + ! Perform Gauss-Jordan elimination and store the solution vector + ! in the last column of the augmented matrix: + + DO L = 1,NumEq ! Loop through all rows + + IF ( EqualRealNos( AugMat(L,L), 0.0_ReKi ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Division by zero in NWTC Library subroutine GaussElim.' + RETURN + END IF + + DO I = ( L + 1 ), NAug ! Loop through all columns above current row number + + AugMat(L,I) = AugMat(L,I) / AugMat(L,L) + + DO J = 1,NumEq ! Loop through all rows except L + IF ( J /= L ) AugMat(J,I) = AugMat(J,I) - ( AugMat(J,L)*AugMat(L,I) ) + ENDDO ! J - All rows except L + + ENDDO ! I - All columns above current row number + + ENDDO ! L - All rows + + + ! Transfer the solution vector from AugMat() to x(): + + x = AugMat(:,NAug) + + + + RETURN + + END SUBROUTINE GaussElim +!======================================================================= +!> Determine index of the point in Ary just below Val and the fractional distance to the next point in the array. +!! The elements of the array are assumed to be regularly spaced. + SUBROUTINE GetOffsetReg ( Ary, NumPts, Val, Ind, Fract, ErrStat, ErrMsg ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: NumPts !< Length of the array. + + REAL(ReKi), INTENT(IN) :: Ary (NumPts) !< Input array of regularly spaced values. + REAL(ReKi), INTENT(OUT) :: Fract !< The fractional distance of Val between the surrounding array elements. + REAL(ReKi), INTENT(IN) :: Val !< The value we hope to bound in the array. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + INTEGER(IntKi), INTENT(OUT) :: Ind !< The index of the point in Ary just below Val. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + + ! Local declarations. + + REAL(ReKi) :: Del ! The distances between the regularly spaced points. + +! INTEGER(IntKi) :: ErrStatLcL ! Local error status. + + + + ! Check the validity of the data. + + IF ( NumPts == 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'GetOffsetReg:The value of NumPts cannot be zero.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + + + ! Compute the distance between Ary values. + + Del = ( Ary(NumPts) - Ary(1) )/REAL( NumPts-1, ReKi ) ! QUESTION: Is this more accurate than computing the distance between two adjacent points? + + + ! Find the index of the array element just below Val. + + IF ( Val <= Ary(1) ) THEN + Ind = 1 + Fract = 0.0_ReKi + RETURN + ELSEIF ( Val >= Ary(NumPts) ) THEN + Ind = NumPts + Fract = 0.0_ReKi + RETURN + ENDIF ! ( X <= XAry(1) ) + + Ind = INT( ( Val - Ary(1) )/Del ) + 1 + Fract = ( Val - Ary(Ind) )/Del + + RETURN + + END SUBROUTINE GetOffsetReg ! ( Ary, NumPts, Val, Ind, Fract, ErrStat, ErrMsg ) +!======================================================================= +! SUBROUTINE GetPermMat ( InpMat, PMat, ErrStat ) +! +! ! This subroutine computes a permutation matrix, PMat, for a given +! ! input matrix, InpMat. It assumes that InpMat is of full rank +! ! and for now, the matrices are 3 x 3. +! +! ! passed variables +! +! REAL(ReKi), INTENT(IN ) :: InpMat (3,3) +! REAL(ReKi), INTENT(OUT ) :: PMat (3,3) !this could be integer, but we'll leave it real now +! INTEGER, INTENT(OUT ) :: ErrStat ! a non-zero value indicates an error in the permutation matrix algorithm +! +! ! local variables +! INTEGER :: iCol ! loop counter +! INTEGER :: iRow ! loop counter +! INTEGER :: MaxCol ! holds index of maximum value in a column +! +! LOGICAL :: ChkCols (3) ! a check to make sure we have only one non-zero element per column +! +! ! initialize some variables +! PMat = 0.0 +! ChkCols = .FALSE. +! ErrStat = 0 +! +! ! find the pivots +! DO iRow = 1,3 +! +! MaxCol = 1 ! initialize max index +! DO iCol = 2,3 +! IF ( ABS(InpMat(iRow,iCol)) > ABS(InpMat(iRow,MaxCol)) ) & +! MaxCol = iCol +! END DO ! iCol +! +! IF ( ChkCols(MaxCol) ) THEN ! we can have only 1 non-zero entry per row and column, but we've just violated that! +! CALL ProgAbort( ' Error in GetPermMat(): InpMat is not full rank.', TrapErrors = .TRUE. ) +! ErrStat = 1 +! END IF +! +! PMat(MaxCol, iRow) = SIGN( 1.0_ReKi, InpMat(iRow,MaxCol) ) ! technically a permutation matrix would only have +1.0 (not -1.0) +! ChkCols(MaxCol) = .TRUE. +! +! END DO ! iRow +! +! RETURN +! END SUBROUTINE GetPermMat ! ( InpMat, PMat, ErrStat ) +!======================================================================= +!> This subroutine computes the angles that make up the input direction cosine matrix, DCMat, +!! assuming small angles. It is the inverse of SmllRotTrans (nwtc_num::smllrottrans). \n +!! Use GetSmllRotAngs (nwtc_num::getsmllrotangs) instead of directly calling a specific routine in the generic interface. +!======================================================================= + FUNCTION GetSmllRotAngsD ( DCMat, ErrStat, ErrMsg ) + + ! passed variables + + REAL(DbKi), INTENT(IN ) :: DCMat (3,3) !< a direction cosine matrix + INTEGER, INTENT(OUT ) :: ErrStat !< a non-zero value indicates an error in the permutation matrix algorithm + CHARACTER(*),INTENT(OUT ),OPTIONAL :: ErrMsg !< a non-zero value indicates an error in the permutation matrix algorithm + + REAL(DbKi) :: GetSmllRotAngsD ( 3 ) !< the rotational angles + + ! local variables + REAL(DbKi) :: denom ! the denominator of the resulting matrix + REAL(DbKi), PARAMETER :: LrgAngle = 0.4_DbKi ! Threshold for when a small angle becomes large (about 23deg). This comes from: COS(SmllAngle) ~ 1/SQRT( 1 + SmllAngle^2 ) and SIN(SmllAngle) ~ SmllAngle/SQRT( 1 + SmllAngle^2 ) results in ~5% error when SmllAngle = 0.4rad. + + + + ! initialize output angles (just in case there is an error that prevents them from getting set) + + GetSmllRotAngsD = 0.0_DbKi + ErrStat = ErrID_None + ErrMsg = "" + + ! calculate the small angles + GetSmllRotAngsD(1) = DCMat(2,3) - DCMat(3,2) + GetSmllRotAngsD(2) = DCMat(3,1) - DCMat(1,3) + GetSmllRotAngsD(3) = DCMat(1,2) - DCMat(2,1) + + denom = DCMat(1,1) + DCMat(2,2) + DCMat(3,3) - 1.0_DbKi + + IF ( .NOT. EqualRealNos( denom, 0.0_DbKi ) ) THEN + GetSmllRotAngsD = GetSmllRotAngsD / denom + + ! check that the angles are, in fact, small + IF ( ANY( ABS(GetSmllRotAngsD) > LrgAngle ) ) THEN + ErrStat = ErrID_Severe + + IF (PRESENT(ErrMsg)) THEN + ErrMsg = ' Angles in GetSmllRotAngs() are larger than '//TRIM(Num2LStr(LrgAngle))//' radians.' + ELSE + CALL ProgWarn( ' Angles in GetSmllRotAngs() are larger than '//TRIM(Num2LStr(LrgAngle))//' radians.' ) + END IF + + END IF + + ELSE + ! check that the angles are, in fact, small (denom should be close to 2 if angles are small) + ErrStat = ErrID_Fatal + + IF (PRESENT(ErrMsg)) THEN + ErrMsg = ' Denominator is zero in GetSmllRotAngs().' + ELSE + CALL ProgAbort( ' Denominator is zero in GetSmllRotAngs().', TrapErrors = .TRUE. ) + END IF + + END IF + + + END FUNCTION GetSmllRotAngsD +!======================================================================= +!> \copydoc nwtc_num::getsmllrotangsd + FUNCTION GetSmllRotAngsR ( DCMat, ErrStat, ErrMsg ) + + ! passed variables + + REAL(ReKi), INTENT(IN ) :: DCMat (3,3) + INTEGER, INTENT(OUT ) :: ErrStat ! a non-zero value indicates an error in the permutation matrix algorithm + CHARACTER(*),INTENT(OUT ),OPTIONAL :: ErrMsg ! a non-zero value indicates an error in the permutation matrix algorithm + + REAL(ReKi) :: GetSmllRotAngsR ( 3 ) + + ! local variables + REAL(ReKi) :: denom ! the denominator of the resulting matrix + REAL(ReKi), PARAMETER :: LrgAngle = 0.4_ReKi ! Threshold for when a small angle becomes large (about 23deg). This comes from: COS(SmllAngle) ~ 1/SQRT( 1 + SmllAngle^2 ) and SIN(SmllAngle) ~ SmllAngle/SQRT( 1 + SmllAngle^2 ) results in ~5% error when SmllAngle = 0.4rad. + + + + ! initialize output angles (just in case there is an error that prevents them from getting set) + + GetSmllRotAngsR = 0.0_ReKi + ErrStat = ErrID_None + ErrMsg = "" + + ! calculate the small angles + GetSmllRotAngsR(1) = DCMat(2,3) - DCMat(3,2) + GetSmllRotAngsR(2) = DCMat(3,1) - DCMat(1,3) + GetSmllRotAngsR(3) = DCMat(1,2) - DCMat(2,1) + + denom = DCMat(1,1) + DCMat(2,2) + DCMat(3,3) - 1.0_ReKi + + IF ( .NOT. EqualRealNos( denom, 0.0_ReKi ) ) THEN + GetSmllRotAngsR = GetSmllRotAngsR / denom + + ! check that the angles are, in fact, small + IF ( ANY( ABS(GetSmllRotAngsR) > LrgAngle ) ) THEN + ErrStat = ErrID_Severe + + IF (PRESENT(ErrMsg)) THEN + ErrMsg = ' Angles in GetSmllRotAngs() are larger than '//TRIM(Num2LStr(LrgAngle))//' radians.' + ELSE + CALL ProgWarn( ' Angles in GetSmllRotAngs() are larger than '//TRIM(Num2LStr(LrgAngle))//' radians.' ) + END IF + + END IF + + ELSE + ! check that the angles are, in fact, small (denom should be close to 2 if angles are small) + ErrStat = ErrID_Fatal + + IF (PRESENT(ErrMsg)) THEN + ErrMsg = ' Denominator is zero in GetSmllRotAngs().' + ELSE + CALL ProgAbort( ' Denominator is zero in GetSmllRotAngs().', TrapErrors = .TRUE. ) + END IF + + END IF + + + END FUNCTION GetSmllRotAngsR +!======================================================================= +!> This funtion returns the non-dimensional (-1:+1) location of the given Gauss-Legendre Quadrature point and its weight. +!! It works for NPts \f$\in \left[{1,6\right]\f$. +!! The values came from Carnahan, Brice; Luther, H.A.; Wilkes, James O. (1969) "Applied Numerical Methods." + SUBROUTINE GL_Pts ( IPt, NPts, Loc, Wt, ErrStat, ErrMsg ) + + ! Argument declarations. + + REAL(ReKi), INTENT(OUT) :: Loc !< The location of the specified point. + REAL(ReKi), INTENT(OUT) :: Wt !< The weight for the specified point. + + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*),INTENT(OUT) :: ErrMsg !< Error message + INTEGER, INTENT(IN ) :: IPt !< The quadrature point in question. + INTEGER, INTENT(IN ) :: NPts !< The number of points used in the quadrature. + + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Check to see if the number of points and the specific point are valid values. + + IF ( ( NPts < 1 ) .OR. ( NPts > 6 ) ) THEN + ErrMsg = 'In function GL_Loc, the number of points used for Gauss-Legendre Quadrature must be between 1 and 6' & + //' (inclusive). Instead, it is "'//TRIM( Int2LStr( NPts ) )//'".' + ErrStat = ErrID_Fatal + RETURN + END IF + + IF ( ( Ipt < 1 ) .OR. ( Ipt > NPts ) ) THEN + ErrMsg = 'In function GL_Loc, the point being used for Gauss-Legendre Quadrature must be between 1 and ' & + //TRIM( Int2LStr( NPts ) )//' (inclusive). Instead, it is "'//TRIM( Int2LStr( Ipt ) )//'".' + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Set the location and weight of the point. + + SELECT CASE ( NPts ) + CASE ( 1 ) ! Case 1 is really just rectangular integration. + Loc = 0.0 + Wt = 2.0 + CASE ( 2 ) + SELECT CASE ( Ipt ) + CASE ( 1 ) + Loc = -0.5773503 + Wt = 1.0 + CASE ( 2 ) + Loc = 0.5773503 + Wt = 1.0 + END SELECT ! Ipt + CASE ( 3 ) + SELECT CASE ( Ipt ) + CASE ( 1 ) + Loc = -0.7745967 + Wt = 0.5555556 + CASE ( 2 ) + Loc = 0.0 + Wt = 0.8888889 + CASE ( 3 ) + Loc = 0.7745967 + Wt = 0.5555556 + END SELECT ! Ipt + CASE ( 4 ) + SELECT CASE ( Ipt ) + CASE ( 1 ) + Loc = -0.8611363 + Wt = 0.3478548 + CASE ( 2 ) + Loc = -0.3399810 + Wt = 0.6521452 + CASE ( 3 ) + Loc = 0.3399810 + Wt = 0.6521452 + CASE ( 4 ) + Loc = 0.8611363 + Wt = 0.3478548 + END SELECT ! Ipt + CASE ( 5 ) + SELECT CASE ( Ipt ) + CASE ( 1 ) + Loc = -0.9061798 + Wt = 0.2369269 + CASE ( 2 ) + Loc = -0.5384693 + Wt = 0.4786287 + CASE ( 3 ) + Loc = 0.0 + Wt = 0.5688889 + CASE ( 4 ) + Loc = 0.5384693 + Wt = 0.4786287 + CASE ( 5 ) + Loc = 0.9061798 + Wt = 0.2369269 + END SELECT ! Ipt + CASE ( 6 ) + SELECT CASE ( Ipt ) + CASE ( 1 ) + Loc = -0.9324695 + Wt = 0.1713245 + CASE ( 2 ) + Loc = -0.6612094 + Wt = 0.3607616 + CASE ( 3 ) + Loc = -0.2386192 + Wt = 0.4679139 + CASE ( 4 ) + Loc = 0.2386192 + Wt = 0.4679139 + CASE ( 5 ) + Loc = 0.6612094 + Wt = 0.3607616 + CASE ( 6 ) + Loc = 0.9324695 + Wt = 0.1713245 + END SELECT ! Ipt + END SELECT ! Npts + + RETURN + END SUBROUTINE GL_Pts ! ( IPt, NPts, Loc, Wt [, ErrStat] ) +!======================================================================= +!> This funtion returns an integer index such that CAry(IndexCharAry) = CVal. If +!! no element in the array matches CVal, the value -1 is returned. The routine +!! performs a binary search on the input array to determine if CVal is an +!! element of the array; thus, CAry must be sorted and stored in increasing +!! alphebetical (ASCII) order. The routine does not check that the array is +!! sorted. The routine assumes that CVal is type CHARACTER and CAry +!! is an array of CHARACTERS. + FUNCTION IndexCharAry( CVal, CAry ) + + ! Function declaration. + + + INTEGER :: IndexCharAry !< integer index such that CAry(IndexCharAry) = CVal + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: CVal !< String to find + CHARACTER(*), INTENT(IN) :: CAry(:) !< Array of strings to search + + + + ! Local declarations. + + INTEGER :: IHi ! The high index into the arrays. + INTEGER :: IMid ! The mid-point index between IHi and ILo. + INTEGER :: ILo + + + ! Initialize some variables + + ILo = 1 + IHi = SIZE(CAry) + + IF ( CVal == CAry(ILo) ) THEN + IndexCharAry = ILo + ELSEIF ( CVal == CAry(IHi) ) THEN + IndexCharAry = IHi + ELSE + IndexCharAry = -1 + + + ! Let's search! + + DO WHILE ( IHi-ILo > 1 ) + + IMid = ( IHi + ILo )/2 + + IF( CVal > CAry(IMid) ) THEN + ILo = IMid + ELSEIF (CVal < CAry(IMid) ) THEN + IHi = IMid + ELSE !Found it + IndexCharAry = IMid + EXIT + END IF + + END DO + + END IF + + + RETURN + + END FUNCTION IndexCharAry +!======================================================================= +!> This funtion returns a y-value that corresponds to an input x-value by interpolating into the arrays. +!! It uses a binary interpolation scheme that takes about log(AryLen) / log(2) steps to converge. +!! It returns the first or last YAry() value if XVal is outside the limits of XAry(). +!! +!! Use InterpBin (nwtc_num::interpbin) instead of directly calling a specific routine in the generic interface. + FUNCTION InterpBinComp( XVal, XAry, YAry, ILo, AryLen ) + + ! Function declaration. + + + COMPLEX(ReKi) :: InterpBinComp !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: ILo !< The low index into the arrays. + + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(ReKi), INTENT(IN) :: XVal !< X value to be interpolated. + + COMPLEX(ReKi), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + + ! Local declarations. + + INTEGER :: IHi ! The high index into the arrays. + INTEGER :: IMid ! The mid-point index between IHi and ILo. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpBinComp = YAry(1) + ILo = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpBinComp = YAry(AryLen) + ILo = AryLen - 1 + RETURN + END IF + + + ! Let's interpolate! + + ILo = 1 + IHi = AryLen + + DO WHILE ( IHi-ILo > 1 ) + + IMid = ( IHi + ILo )/2 + + IF ( XVal >= XAry(IMid) ) THEN + ILo = IMid + ELSE + IHi = IMid + END IF + + END DO + + InterpBinComp = YAry(ILo) + ( YAry(IHi) - YAry(ILo) )*( XVal - XAry(ILo) )/( XAry(IHi) - XAry(ILo) ) + + + RETURN + END FUNCTION InterpBinComp ! ( XVal, XAry, YAry, ILo, AryLen ) +!======================================================================= +!> \copydoc nwtc_num::interpbincomp + FUNCTION InterpBinReal( XVal, XAry, YAry, ILo, AryLen ) + + ! Function declaration. + + + REAL(ReKi) :: InterpBinReal !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: ILo !< The low index into the arrays. + + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(ReKi), INTENT(IN) :: XVal !< X value to be interpolated. + REAL(ReKi), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + + ! Local declarations. + + INTEGER :: IHi ! The high index into the arrays. + INTEGER :: IMid ! The mid-point index between IHi and ILo. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpBinReal = YAry(1) + ILo = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpBinReal = YAry(AryLen) + ILo = AryLen - 1 + RETURN + END IF + + + ! Let's interpolate! + + ILo = 1 + IHi = AryLen + + DO WHILE ( IHi-ILo > 1 ) + + IMid = ( IHi + ILo )/2 + + IF ( XVal >= XAry(IMid) ) THEN + ILo = IMid + ELSE + IHi = IMid + END IF + + END DO + + InterpBinReal = YAry(ILo) + ( YAry(IHi) - YAry(ILo) )*( XVal - XAry(ILo) )/( XAry(IHi) - XAry(ILo) ) + + + RETURN + END FUNCTION InterpBinReal ! ( XVal, XAry, YAry, ILo, AryLen ) +!======================================================================= +!> This funtion returns a y-value that corresponds to an input x-value by interpolating into the arrays. +!! It uses the passed index as the starting point and does a stepwise interpolation from there. This is +!! especially useful when the calling routines save the value from the last time this routine was called +!! for a given case where XVal does not change much from call to call. When there is no correlation +!! from one interpolation to another, InterpBin() (nwtc_num::interpbin) may be a better choice. +!! It returns the first or last YAry() value if XVal is outside the limits of XAry(). +!! +!! Use InterpStp (nwtc_num::interpstp) instead of directly calling a specific routine in the generic interface. + FUNCTION InterpStpComp4( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + COMPLEX(SiKi) :: InterpStpComp4 ! The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XVal !< X value to be interpolated. + + COMPLEX(SiKi), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpComp4 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpComp4 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpComp4 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpComp4 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpComp8( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + COMPLEX(R8Ki) :: InterpStpComp8 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the arrays. + + REAL(R8Ki), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(R8Ki), INTENT(IN) :: XVal !< X value to be interpolated. + + COMPLEX(R8Ki), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpComp8 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpComp8 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpComp8 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpComp8 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpComp16( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + COMPLEX(QuKi) :: InterpStpComp16 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the arrays. + + REAL(QuKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(QuKi), INTENT(IN) :: XVal !< X value to be interpolated. + + COMPLEX(QuKi), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpComp16 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpComp16 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpComp16 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpComp16 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpReal4( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(SiKi) :: InterpStpReal4 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XVal ! X value to be interpolated. + REAL(SiKi), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpReal4 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpReal4 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpReal4 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpReal4 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpReal4_8( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(R8Ki) :: InterpStpReal4_8 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XVal ! X value to be interpolated. + REAL(R8Ki), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpReal4_8 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpReal4_8 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpReal4_8 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpReal4_8 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpReal8( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(R8Ki) :: InterpStpReal8 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(R8Ki), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(R8Ki), INTENT(IN) :: XVal ! X value to be interpolated. + REAL(R8Ki), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpReal8 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpReal8 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpReal8 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpReal8 +!======================================================================= +!> \copydoc nwtc_num::interpstpcomp4 + FUNCTION InterpStpReal16( XVal, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(QuKi) :: InterpStpReal16 !< The interpolated value of Y at XVal + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(QuKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(QuKi), INTENT(IN) :: XVal ! X value to be interpolated. + REAL(QuKi), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + InterpStpReal16 = YAry(1) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + InterpStpReal16 = YAry(AryLen) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + InterpStpReal16 = ( YAry(Ind+1) - YAry(Ind) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + YAry(Ind) + RETURN + + END IF + + END DO + + + RETURN + END FUNCTION InterpStpReal16 +!======================================================================= +!> This funtion returns a y-value array that corresponds to an input x-value by interpolating into the arrays. +!! It uses the passed index as the starting point and does a stepwise interpolation from there. This is +!! especially useful when the calling routines save the value from the last time this routine was called +!! for a given case where XVal does not change much from call to call. +!! It returns the first or last Y() row value if XVal is outside the limits of XAry(). + SUBROUTINE InterpStpMat( XVal, XAry, Y, Ind, AryLen, yInterp ) + + ! Function declaration. + + REAL(ReKi), intent(out) :: yInterp(:) !< The interpolated value(s) of Y(dim=2) at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the arrays. + + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(ReKi), INTENT(IN) :: XVal !< X value to be interpolated. + REAL(ReKi), INTENT(IN) :: Y (:,:) !< Matrix of Y values to be interpolated; First dimension is AryLen. + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + yInterp = Y(1,:) + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + yInterp = Y(AryLen,:) + Ind = MAX(AryLen - 1, 1) + RETURN + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + yInterp = ( Y(Ind+1,:) - Y(Ind,:) )*( XVal - XAry(Ind) )/( XAry(Ind+1) - XAry(Ind) ) + Y(Ind,:) + RETURN + + END IF + + END DO + + + RETURN + END SUBROUTINE InterpStpMat +!======================================================================= +!< This routine linearly interpolates Dataset. It is +!! set for a 2-d interpolation on x and y of the input point. +!! x and y must be in increasing order. Each dimension may contain only 1 value. +!! The method is described in this paper: +!! http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.Ch11.d/AFEM.Ch11.pdf + SUBROUTINE InterpStpReal2D( InCoord, Dataset, x, y, LastIndex, InterpData ) + + INTEGER, PARAMETER :: NumDimensions = 2 + + ! I/O variables + + REAL(ReKi), INTENT(IN ) :: InCoord(NumDimensions) !< Arranged as (x, y) + REAL(ReKi), INTENT(IN ) :: Dataset(:,:) !< Arranged as (x, y) + REAL(ReKi), INTENT(IN ) :: x(:) !< first dimension in increasing order + REAL(ReKi), INTENT(IN ) :: y(:) !< second dimension in increasing order + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(NumDimensions) !< Index for the last (x, y) used + REAL(ReKi), INTENT( OUT) :: InterpData !< The interpolated value of Dataset(:,:) at InCoord + + + ! Local variables + + INTEGER(IntKi) :: Indx_Lo(NumDimensions) ! index associated with lower bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + INTEGER(IntKi) :: Indx_Hi(NumDimensions) ! index associated with upper bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + REAL(ReKi) :: Pos_Lo(NumDimensions) ! coordinate value with lower bound of dimension 1,2 + REAL(ReKi) :: Pos_Hi(NumDimensions) ! coordinate value with upper bound of dimension 1,2 + + REAL(ReKi) :: isopc(NumDimensions) ! isoparametric coordinates + + REAL(ReKi) :: N(2**NumDimensions) ! size 2^n + REAL(ReKi) :: u(2**NumDimensions) ! size 2^n + + INTEGER(IntKi) :: nx, ny + + + ! find the indices into the arrays representing coordinates of each dimension: + ! (by using LocateStp, we do not require equally spaced arrays) + + nx = SIZE(x) + ny = SIZE(y) + + CALL LocateStp( InCoord(1), x, LastIndex(1), nx ) + CALL LocateStp( InCoord(2), y, LastIndex(2), ny ) + + Indx_Lo = LastIndex ! at this point, 0 <= Indx_Lo(i) <= n(i) for all i + + + ! x (indx 1) + IF (Indx_Lo(1) == 0) THEN + Indx_Lo(1) = 1 + ELSEIF (Indx_Lo(1) == nx ) THEN + Indx_Lo(1) = max( nx - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(1) = min( Indx_Lo(1) + 1 , nx ) ! make sure it's a valid index + + ! y (indx 2) + IF (Indx_Lo(2) == 0) THEN + Indx_Lo(2) = 1 + ELSEIF (Indx_Lo(2) == ny ) THEN + Indx_Lo(2) = max( ny - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(2) = min( Indx_Lo(2) + 1 , ny ) ! make sure it's a valid index + + + ! calculate the bounding box; the positions of all dimensions: + + pos_Lo(1) = x( Indx_Lo(1) ) + pos_Hi(1) = x( Indx_Hi(1) ) + + pos_Lo(2) = y( Indx_Lo(2) ) + pos_Hi(2) = y( Indx_Hi(2) ) + + + ! 2-D linear interpolation: + + CALL IsoparametricCoords( InCoord, pos_Lo, pos_Hi, isopc ) ! Calculate iospc + + N(1) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi - isopc(2) ) + N(2) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi + isopc(2) ) + N(3) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi + isopc(2) ) + N(4) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi - isopc(2) ) + N = N / REAL( SIZE(N), ReKi ) ! normalize + + + u(1) = Dataset( Indx_Hi(1), Indx_Lo(2) ) + u(2) = Dataset( Indx_Hi(1), Indx_Hi(2) ) + u(3) = Dataset( Indx_Lo(1), Indx_Hi(2) ) + u(4) = Dataset( Indx_Lo(1), Indx_Lo(2) ) + + InterpData = SUM ( N * u ) + + + END SUBROUTINE InterpStpReal2D +!======================================================================= +!< This routine linearly interpolates Dataset. It is set for a 3-d +!! interpolation on x and y of the input point. x, y, and z must be +!! in increasing order. Each dimension may contain only 1 value. +!! The method is described in this paper: +!! http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.Ch11.d/AFEM.Ch11.pdf + SUBROUTINE InterpStpReal3D( InCoord, Dataset, x, y, z, LastIndex, InterpData ) + ! This routine linearly interpolates Dataset. It is set for a 3-d + ! interpolation on x and y of the input point. x, y, and z must be + ! in increasing order. Each dimension may contain only 1 value. + ! The method is described in this paper: + ! http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.Ch11.d/AFEM.Ch11.pdf + + INTEGER, PARAMETER :: NumDimensions = 3 + + ! I/O variables + + REAL(ReKi), INTENT(IN ) :: InCoord(NumDimensions) !< Arranged as (x, y, z) + REAL(ReKi), INTENT(IN ) :: Dataset(:,:,:) !< Arranged as (x, y, z) + REAL(ReKi), INTENT(IN ) :: x(:) !< first dimension in increasing order + REAL(ReKi), INTENT(IN ) :: y(:) !< second dimension in increasing order + REAL(ReKi), INTENT(IN ) :: z(:) !< third dimension in increasing order + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(NumDimensions) !< Index for the last (x, y, z) used + REAL(ReKi), INTENT( OUT) :: InterpData !< The interpolated value of Dataset(:,:,:) at InCoord + + + ! Local variables + + INTEGER(IntKi) :: Indx_Lo(NumDimensions) ! index associated with lower bound of dimension i where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + INTEGER(IntKi) :: Indx_Hi(NumDimensions) ! index associated with upper bound of dimension i where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + REAL(ReKi) :: Pos_Lo(NumDimensions) ! coordinate value with lower bound of dimension i + REAL(ReKi) :: Pos_Hi(NumDimensions) ! coordinate value with upper bound of dimension i + + REAL(ReKi) :: isopc(NumDimensions) ! isoparametric coordinates + + REAL(ReKi) :: N(2**NumDimensions) ! size 2^NumDimensions + REAL(ReKi) :: u(2**NumDimensions) ! size 2^NumDimensions + + INTEGER(IntKi) :: nd(NumDimensions) ! size of each dimension + INTEGER(IntKi) :: i + + + ! find the indices into the arrays representing coordinates of each dimension: + ! (by using LocateStp, we do not require equally spaced frequencies or points) + + nd(1) = SIZE(x) + nd(2) = SIZE(y) + nd(3) = SIZE(z) + + CALL LocateStp( InCoord(1), x, LastIndex(1), nd(1) ) + CALL LocateStp( InCoord(2), y, LastIndex(2), nd(2) ) + CALL LocateStp( InCoord(3), z, LastIndex(3), nd(3) ) + + Indx_Lo = LastIndex ! at this point, 0 <= Indx_Lo(i) <= n(i) for all i + + + DO i=1,NumDimensions + IF (Indx_Lo(i) == 0) THEN + Indx_Lo(i) = 1 + ELSEIF (Indx_Lo(i) == nd(i) ) THEN + Indx_Lo(i) = max( nd(i) - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(i) = min( Indx_Lo(i) + 1 , nd(i) ) ! make sure it's a valid index + END DO + + + + ! calculate the bounding box; the positions of all dimensions: + + pos_Lo(1) = x( Indx_Lo(1) ) + pos_Hi(1) = x( Indx_Hi(1) ) + + pos_Lo(2) = y( Indx_Lo(2) ) + pos_Hi(2) = y( Indx_Hi(2) ) + + pos_Lo(3) = z( Indx_Lo(3) ) + pos_Hi(3) = z( Indx_Hi(3) ) + + + ! 2-D linear interpolation: + + CALL IsoparametricCoords( InCoord, pos_Lo, pos_Hi, isopc ) ! Calculate iospc + + + N(1) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi - isopc(2) )*( 1.0_ReKi - isopc(3) ) + N(2) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi + isopc(2) )*( 1.0_ReKi - isopc(3) ) + N(3) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi + isopc(2) )*( 1.0_ReKi - isopc(3) ) + N(4) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi - isopc(2) )*( 1.0_ReKi - isopc(3) ) + N(5) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi - isopc(2) )*( 1.0_ReKi + isopc(3) ) + N(6) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi + isopc(2) )*( 1.0_ReKi + isopc(3) ) + N(7) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi + isopc(2) )*( 1.0_ReKi + isopc(3) ) + N(8) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi - isopc(2) )*( 1.0_ReKi + isopc(3) ) + N = N / REAL( SIZE(N), ReKi ) ! normalize + + u(1) = Dataset( Indx_Hi(1), Indx_Lo(2), Indx_Lo(3) ) + u(2) = Dataset( Indx_Hi(1), Indx_Hi(2), Indx_Lo(3) ) + u(3) = Dataset( Indx_Lo(1), Indx_Hi(2), Indx_Lo(3) ) + u(4) = Dataset( Indx_Lo(1), Indx_Lo(2), Indx_Lo(3) ) + u(5) = Dataset( Indx_Hi(1), Indx_Lo(2), Indx_Hi(3) ) + u(6) = Dataset( Indx_Hi(1), Indx_Hi(2), Indx_Hi(3) ) + u(7) = Dataset( Indx_Lo(1), Indx_Hi(2), Indx_Hi(3) ) + u(8) = Dataset( Indx_Lo(1), Indx_Lo(2), Indx_Hi(3) ) + + InterpData = SUM ( N * u ) ! could use dot_product, though I'm not sure it's the came for complex numbers + + + END SUBROUTINE InterpStpReal3D +!======================================================================= +!> This funtion returns a y-value that corresponds to an input x-value which is wrapped back +!! into the range [0-XAry(AryLen)] by interpolating into the arrays. +!! It is assumed that XAry is sorted in ascending order. +!! It uses the passed index as the starting point and does a stepwise interpolation from there. This is +!! especially useful when the calling routines save the value from the last time this routine was called +!! for a given case where XVal does not change much from call to call. When there is no correlation +!! from one interpolation to another, InterpBin() may be a better choice. +!! It returns the first or last YAry() value if XVal is outside the limits of XAry(). +!! +!! Use InterpWrappedStpReal (nwtc_num::interpwrappedstpreal) instead of directly calling a specific routine in the generic interface. + FUNCTION InterpWrappedStpReal4( XValIn, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(SiKi) :: InterpWrappedStpReal4 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XValIn !< X value to be interpolated. + REAL(SiKi), INTENT(IN) :: YAry (AryLen) !< Array of Y values to be interpolated. + + REAL(SiKi) :: XVal !< X value to be interpolated. + + + + ! Wrap XValIn into the range XAry(1) to XAry(AryLen) + XVal = MOD(XValIn, XAry(AryLen)) + + ! Set the Ind to the first index if we are at the beginning of XAry + IF ( XVal <= XAry(2) ) THEN + Ind = 1 + END IF + + InterpWrappedStpReal4 = InterpStp( XVal, XAry, YAry, Ind, AryLen ) + + + END FUNCTION InterpWrappedStpReal4 +!======================================================================= +!> \copydoc nwtc_num::interpwrappedstpreal4 + FUNCTION InterpWrappedStpReal4_8( XValIn, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(R8Ki) :: InterpWrappedStpReal4_8 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XValIn ! X value to be interpolated. + REAL(R8Ki), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + REAL(SiKi) :: XVal ! X value to be interpolated. + + + + ! Wrap XValIn into the range XAry(1) to XAry(AryLen) + XVal = MOD(XValIn, XAry(AryLen)) + + ! Set the Ind to the first index if we are at the beginning of XAry + IF ( XVal <= XAry(2) ) THEN + Ind = 1 + END IF + + InterpWrappedStpReal4_8 = InterpStp( XVal, XAry, YAry, Ind, AryLen ) + + + END FUNCTION InterpWrappedStpReal4_8 +!======================================================================= +!> \copydoc nwtc_num::interpwrappedstpreal4 + FUNCTION InterpWrappedStpReal8( XValIn, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(R8Ki) :: InterpWrappedStpReal8 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(R8Ki), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(R8Ki), INTENT(IN) :: XValIn ! X value to be interpolated. + REAL(R8Ki), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + REAL(R8Ki) :: XVal ! X value to be interpolated. + + + + ! Wrap XValIn into the range XAry(1) to XAry(AryLen) + XVal = MOD(XValIn, XAry(AryLen)) + + ! Set the Ind to the first index if we are at the beginning of XAry + IF ( XVal <= XAry(2) ) THEN + Ind = 1 + END IF + + InterpWrappedStpReal8 = InterpStp( XVal, XAry, YAry, Ind, AryLen ) + + + END FUNCTION InterpWrappedStpReal8 +!======================================================================= +!> \copydoc nwtc_num::interpwrappedstpreal4 + FUNCTION InterpWrappedStpReal16( XValIn, XAry, YAry, Ind, AryLen ) + + ! Function declaration. + + REAL(QuKi) :: InterpWrappedStpReal16 !< The interpolated value of Y at XVal + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the arrays. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(QuKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(QuKi), INTENT(IN) :: XValIn ! X value to be interpolated. + REAL(QuKi), INTENT(IN) :: YAry (AryLen) ! Array of Y values to be interpolated. + + REAL(QuKi) :: XVal ! X value to be interpolated. + + + + ! Wrap XValIn into the range XAry(1) to XAry(AryLen) + XVal = MOD(XValIn, XAry(AryLen)) + + ! Set the Ind to the first index if we are at the beginning of XAry + IF ( XVal <= XAry(2) ) THEN + Ind = 1 + END IF + + InterpWrappedStpReal16 = InterpStp( XVal, XAry, YAry, Ind, AryLen ) + + + END FUNCTION InterpWrappedStpReal16 +!======================================================================= +!> This subroutine calculates interpolated values for an array of input values. +!! The size of the xknown and yknown arrays must match, and the size of the +!! xnew and ynew arrays must match. Xknown must be in ascending order. +!! Values outside the range of xknown are fixed to the end points. + SUBROUTINE InterpArrayR4( xknown, yknown, xnew, ynew ) + REAL(SiKi), INTENT(IN ) :: xknown(:) + REAL(SiKi), INTENT(IN ) :: yknown(:) + REAL(SiKi), INTENT(IN ) :: xnew(:) + REAL(SiKi), INTENT( OUT) :: ynew(:) + integer(IntKi) i,itmp,nknown + nknown=size(xknown) + do i=1,size(xnew) + itmp=minloc(abs(xnew(i)-xknown),dim=1) + if (itmp==nknown) then + if (xknown(itmp)>xnew(i)) then + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + else + ! The current x is above the max of xknown + ! extrapolation required, here fixed to upper bound + ynew(i)=yknown(nknown) + endif + elseif (xknown(itmp)<xnew(i)) then + ! normal case, x between itmp and itmp+1 + ynew(i)=interp_lin0(xnew(i),xknown(itmp),xknown(itmp+1),yknown(itmp),yknown(itmp+1)) + elseif (itmp==1) then + ! The current x is below the min of xknown + ynew(i)=yknown(1) + else + ! normal case but inverted, x between itmp-1 and itmp + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + endif + enddo + CONTAINS + function interp_lin0(x,x0,x1,f0,f1) ! Linear interpolation function + real(SiKi) ::interp_lin0 + real(SiKi),intent(in):: x,x0,x1,f0,f1 + if (EqualRealNos(x0,x1)) then ! to avoid division by zero + interp_lin0=f0 + else + interp_lin0=(x-x1)/(x0-x1)*f0+(x-x0)/(x1-x0)*f1 + endif + end function interp_lin0 + END SUBROUTINE InterpArrayR4 +!======================================================================= +!> \copydoc nwtc_num::interparrayr4 + SUBROUTINE InterpArrayR8( xknown, yknown, xnew, ynew ) + REAL(R8Ki), INTENT(IN ) :: xknown(:) + REAL(R8Ki), INTENT(IN ) :: yknown(:) + REAL(R8Ki), INTENT(IN ) :: xnew(:) + REAL(R8Ki), INTENT( OUT) :: ynew(:) + integer(IntKi) i,itmp,nknown + nknown=size(xknown) + do i=1,size(xnew) + itmp=minloc(abs(xnew(i)-xknown),dim=1) + if (itmp==nknown) then + if (xknown(itmp)>xnew(i)) then + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + else + ! The current x is above the max of xknown + ! extrapolation required, here fixed to upper bound + ynew(i)=yknown(nknown) + endif + elseif (xknown(itmp)<xnew(i)) then + ! normal case, x between itmp and itmp+1 + ynew(i)=interp_lin0(xnew(i),xknown(itmp),xknown(itmp+1),yknown(itmp),yknown(itmp+1)) + elseif (itmp==1) then + ! The current x is below the min of xknown + ynew(i)=yknown(1) + else + ! normal case but inverted, x between itmp-1 and itmp + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + endif + enddo + CONTAINS + function interp_lin0(x,x0,x1,f0,f1) ! Linear interpolation function + real(R8Ki) ::interp_lin0 + real(R8Ki),intent(in):: x,x0,x1,f0,f1 + if (EqualRealNos(x0,x1)) then ! to avoid division by zero + interp_lin0=f0 + else + interp_lin0=(x-x1)/(x0-x1)*f0+(x-x0)/(x1-x0)*f1 + endif + end function interp_lin0 + END SUBROUTINE InterpArrayR8 +!======================================================================= +!> \copydoc nwtc_num::interparrayr4 + SUBROUTINE InterpArrayR16( xknown, yknown, xnew, ynew ) + REAL(QuKi), INTENT(IN ) :: xknown(:) + REAL(QuKi), INTENT(IN ) :: yknown(:) + REAL(QuKi), INTENT(IN ) :: xnew(:) + REAL(QuKi), INTENT( OUT) :: ynew(:) + integer(IntKi) i,itmp,nknown + nknown=size(xknown) + do i=1,size(xnew) + itmp=minloc(abs(xnew(i)-xknown),dim=1) + if (itmp==nknown) then + if (xknown(itmp)>xnew(i)) then + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + else + ! The current x is above the max of xknown + ! extrapolation required, here fixed to upper bound + ynew(i)=yknown(nknown) + endif + elseif (xknown(itmp)<xnew(i)) then + ! normal case, x between itmp and itmp+1 + ynew(i)=interp_lin0(xnew(i),xknown(itmp),xknown(itmp+1),yknown(itmp),yknown(itmp+1)) + elseif (itmp==1) then + ! The current x is below the min of xknown + ynew(i)=yknown(1) + else + ! normal case but inverted, x between itmp-1 and itmp + ynew(i)=interp_lin0(xnew(i),xknown(itmp-1),xknown(itmp),yknown(itmp-1),yknown(itmp)) + endif + enddo + CONTAINS + function interp_lin0(x,x0,x1,f0,f1) ! Linear interpolation function + real(QuKi) ::interp_lin0 + real(QuKi),intent(in):: x,x0,x1,f0,f1 + if (EqualRealNos(x0,x1)) then ! to avoid division by zero + interp_lin0=f0 + else + interp_lin0=(x-x1)/(x0-x1)*f0+(x-x0)/(x1-x0)*f1 + endif + end function interp_lin0 + END SUBROUTINE InterpArrayR16 +!======================================================================= +!> This subroutine calculates the iosparametric coordinates, isopc, which is a value between -1 and 1 +!! (for each dimension of a dataset), indicating where InCoord falls between posLo and posHi. +!! It is used in InterpStpReal2D (nwtcnum::interpstpreal2d) and InterpStpReal3D (nwtcnum::interpstpreal3d). + SUBROUTINE IsoparametricCoords( InCoord, posLo, posHi, isopc ) + + REAL(ReKi), INTENT(IN ) :: InCoord(:) !< Coordinate values we're interpolating to; (size = number of interpolation dimensions) + REAL(ReKi), INTENT(IN ) :: posLo(:) !< coordinate values associated with Indx_Lo; (size = number of interpolation dimensions) + REAL(ReKi), INTENT(IN ) :: posHi(:) !< coordinate values associated with Indx_Hi; (size = number of interpolation dimensions) + REAL(ReKi), INTENT( OUT) :: isopc(:) !< isoparametric coordinates; (position within the box) + + ! local variables + REAL(ReKi) :: dx ! difference between high and low coordinates in the bounding "box" + INTEGER(IntKi) :: i ! loop counter + + + do i=1,size(isopc) + + dx = posHi(i) - posLo(i) + if (EqualRealNos(dx, 0.0_ReKi)) then + isopc(i) = 1.0_ReKi + else + isopc(i) = ( 2.0_ReKi*InCoord(i) - posLo(i) - posHi(i) ) / dx + ! to verify that we don't extrapolate, make sure this is bound between -1 and 1 (effectively nearest neighbor) + isopc(i) = min( 1.0_ReKi, isopc(i) ) + isopc(i) = max(-1.0_ReKi, isopc(i) ) + end if + + end do + + END SUBROUTINE IsoparametricCoords +!======================================================================= +!> This function returns a logical TRUE/FALSE value that indicates +!! if the given (2-dimensional) matrix, A, is symmetric. If A is not +!! square it returns FALSE. + FUNCTION IsSymmetric( A ) + + ! passed variables + + REAL(ReKi), INTENT(IN) :: A(:,:) !< a real matrix A, whose symmetry is questioned + LOGICAL :: IsSymmetric !< true if A is symmetric, false if not + + ! local variables + + INTEGER(IntKi) :: i ! counter for rows + INTEGER(IntKi) :: j ! counter for columns + INTEGER(IntKi) :: N ! size of A + + + ! If A is non-square, it is not symmetric: + + N = SIZE(A,1) + + IF ( N /= SIZE(A,2) ) THEN + IsSymmetric = .FALSE. + RETURN + END IF + + + ! If A(i,j) /= A(j,i), it is not symmetric: + + IsSymmetric = .TRUE. + + DO i = 1,(N-1) ! Loop through the 1st N-1 rows of A + DO j = (i+1),N ! Loop through upper triangular part of A + + IsSymmetric = EqualRealNos( A(i,j), A(j,i) ) + IF ( .NOT. IsSymmetric ) RETURN + + END DO ! j - All columns (rows) past I + END DO ! i - The 1st N-1 rows (columns) of A + + + END FUNCTION IsSymmetric +!======================================================================= +!> This subroutine finds the lower-bound index of an input x-value located in an array. +!! On return, Ind has a value such that +!! XAry(Ind) <= XVal < XAry(Ind+1), with the exceptions that +!! Ind = 0 when XVal < XAry(1), and +!! Ind = AryLen when XAry(AryLen) <= XVal. +!! +!! It uses a binary interpolation scheme that takes about log(AryLen)/log(2) steps to converge. +!! If the index doesn't change much between calls, LocateStp() (nwtc_num::locatestp) may be a better option. + SUBROUTINE LocateBin( XVal, XAry, Ind, AryLen ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(OUT) :: Ind !< Final (low) index into the array. + + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(ReKi), INTENT(IN) :: XVal !< X value to be interpolated. + + + ! Local declarations. + + INTEGER :: IHi ! The high index into the arrays. + INTEGER :: IMid ! The mid-point index between IHi and Ind. + + + + ! Let's check the limits first. + + IF ( XVal < XAry(1) ) THEN + Ind = 0 + ELSE IF ( XVal >= XAry(AryLen) ) THEN + Ind = AryLen + ELSE + ! Let's interpolate! + + Ind = 1 + IHi = AryLen + + DO WHILE ( IHi-Ind > 1 ) + + IMid = ( IHi + Ind )/2 + + IF ( XVal >= XAry(IMid) ) THEN + Ind = IMid + ELSE + IHi = IMid + END IF + + END DO + + END IF + + RETURN + END SUBROUTINE LocateBin +!======================================================================= +!> This subroutine finds the lower-bound index of an input x-value located in an array. +!! On return, Ind has a value such that +!! XAry(Ind) <= XVal < XAry(Ind+1), with the exceptions that +!! Ind = 0 when XVal < XAry(1), and +!! Ind = AryLen when XAry(AryLen) <= XVal. +!! +!! It uses the passed index as the starting point and does a stepwise search from there. This is +!! especially useful when the calling routines save the value from the last time this routine was called +!! for a given case where XVal does not change much from call to call. When there is no correlation +!! from one interpolation to another, a binary search may be a better choice (see nwtc_num::locatebin). +!! +!! Use LocateStp (nwtc_num::locatestp) instead of directly calling a specific routine in the generic interface. + SUBROUTINE LocateStpR4( XVal, XAry, Ind, AryLen ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + INTEGER, INTENT(INOUT) :: Ind !< Initial and final index into the array. + + REAL(SiKi), INTENT(IN) :: XAry (AryLen) !< Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XVal !< X value to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal < XAry(1) ) THEN + Ind = 0 + ELSE IF ( XVal >= XAry(AryLen) ) THEN + Ind = AryLen + ELSE + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + RETURN + + END IF + + END DO + + + END IF + + RETURN + + END SUBROUTINE LocateStpR4 +!======================================================================= +!> \copydoc nwtc_num::locatestpr4 + SUBROUTINE LocateStpR8( XVal, XAry, Ind, AryLen ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the array. + + REAL(R8Ki), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(R8Ki), INTENT(IN) :: XVal ! X value to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal < XAry(1) ) THEN + Ind = 0 + ELSE IF ( XVal >= XAry(AryLen) ) THEN + Ind = AryLen + ELSE + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + RETURN + + END IF + + END DO + + + END IF + + RETURN + + END SUBROUTINE LocateStpR8 +!======================================================================= +!> \copydoc nwtc_num::locatestpr4 + SUBROUTINE LocateStpR16( XVal, XAry, Ind, AryLen ) + + ! Argument declarations. + + INTEGER, INTENT(IN) :: AryLen ! Length of the array. + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the array. + + REAL(QuKi), INTENT(IN) :: XAry (AryLen) ! Array of X values to be interpolated. + REAL(QuKi), INTENT(IN) :: XVal ! X value to be interpolated. + + + + ! Let's check the limits first. + + IF ( XVal < XAry(1) ) THEN + Ind = 0 + ELSE IF ( XVal >= XAry(AryLen) ) THEN + Ind = AryLen + ELSE + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + RETURN + + END IF + + END DO + + + END IF + + RETURN + + END SUBROUTINE LocateStpR16 +!======================================================================= +!> This routine calculates the mean value of an array. + FUNCTION Mean ( Ary, AryLen ) + + !NOTE: We should make AryLen an optional argument and use SIZE( Ary ) if it is not present. + + ! Function declaration. + + REAL(ReKi) :: Mean ! The mean of the values in Ary. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + + REAL(ReKi), INTENT(IN) :: Ary (AryLen) !< Input array. + + + ! Local declarations. + + REAL(DbKi) :: Sum ! A temporary sum. + + INTEGER :: I ! The index into the array. + + + + Sum = 0.0_DbKi + + DO I=1,AryLen + Sum = Sum + Ary(I) + END DO ! I + + Mean = Sum/AryLen + + + RETURN + END FUNCTION Mean ! ( Ary, AryLen ) +!======================================================================= +!> This routine is used to convert Angle to an equivalent value +!! between \f$-\pi\f$ and \f$pi\f$. +!! +!! Use MPi2Pi (nwtc_num::mpi2pi) instead of directly calling a specific routine in the generic interface. + SUBROUTINE MPi2Pi_R4 ( Angle ) + + + ! Argument declarations: + + REAL(SiKi), INTENT(INOUT) :: Angle !< Angle (in radians) to be converted + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R4 ) + + + ! Get the angle between -Pi and Pi. + + IF ( Angle > Pi_R4 ) THEN + Angle = Angle - TwoPi_R4 + END IF + + + RETURN + END SUBROUTINE MPi2Pi_R4 +!======================================================================= +!> \copydoc nwtc_num::mpi2pi_r4 + SUBROUTINE MPi2Pi_R8 ( Angle ) + + + ! Argument declarations: + + REAL(R8Ki), INTENT(INOUT) :: Angle + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R8 ) + + + ! Get the angle between -Pi and Pi. + + IF ( Angle > Pi_R8 ) THEN + Angle = Angle - TwoPi_R8 + END IF + + + RETURN + END SUBROUTINE MPi2Pi_R8 +!======================================================================= +!> \copydoc nwtc_num::mpi2pi_r4 + SUBROUTINE MPi2Pi_R16 ( Angle ) + + + ! Argument declarations: + + REAL(QuKi), INTENT(INOUT) :: Angle + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R16 ) + + + ! Get the angle between -Pi and Pi. + + IF ( Angle > Pi_R16 ) THEN + Angle = Angle - TwoPi_R16 + END IF + + + RETURN + END SUBROUTINE MPi2Pi_R16 +!======================================================================= +!> This function takes an angle in radians and converts it to +!! an angle in degrees in the range [-180,180] +real(reKi) function Rad2M180to180Deg(Angle) result(Alpha) + + real(ReKi), intent(in ) :: Angle !< input angle, radians + + Alpha = Angle + + call MPi2Pi ( Alpha ) ! change Angle into range of -pi to pi + Alpha = Alpha*R2D ! change Angle into degrees + +end function Rad2M180to180Deg +!======================================================================= + +!> This routine calculates the outer product of two vectors, +!! \f$u = \left(u_1, u_2, \ldots, u_m\right)\f$ and +!! \f$v = \left(v_1, v_2, \ldots ,v_n\right)\f$. The outer product is defined as +!! \f{equation}{ +!! A = u \otimes v = \begin{bmatrix} +!! u_1 v_1 & u_1 v_2 & \dots & u_1 v_n \\ +!! u_2 v_1 & u_2 v_2 & \dots & u_2 v_n \\ +!! \vdots & \vdots & \ddots & \vdots \\ +!! u_m v_1 & u_m v_2 & \dots & u_m v_n +!! \end{bmatrix} +!! \f} +!! +!! Use OuterProduct (nwtc_num::outerproduct) instead of directly calling a specific routine in the generic interface. + FUNCTION OuterProductR4(u,v) + + + REAL(SiKi), INTENT(IN) :: u(:) !< first vector, \f$u\f$, in the outer product + REAL(SiKi), INTENT(IN) :: v(:) !< second vector, \f$v\f$, in the outer product + REAL(SiKi) :: OuterProductR4(SIZE(u),SIZE(v)) !< the resultant matrix, A + + INTEGER(IntKi)::i,j,n1,n2 + + n1=SIZE(u) + n2=SIZE(v) + + DO i=1,n1 + DO j=1,n2 + OuterProductR4(i,j) = u(i) * v(j) + ENDDO + ENDDO + + END FUNCTION OuterProductR4 +!======================================================================= +!> \copydoc nwtc_num::outerproductr4 + FUNCTION OuterProductR8(u,v) + + ! this routine calculates the outer product of two vectors + + REAL(R8Ki),INTENT(IN):: u(:) + REAL(R8Ki),INTENT(IN):: v(:) + REAL(R8Ki)::OuterProductR8(SIZE(u),SIZE(v)) + + INTEGER(IntKi)::i,j,n1,n2 + + n1=SIZE(u) + n2=SIZE(v) + + DO i=1,n1 + DO j=1,n2 + OuterProductR8(i,j) = u(i) * v(j) + ENDDO + ENDDO + + END FUNCTION OuterProductR8 +!======================================================================= +!> \copydoc nwtc_num::outerproductr4 + FUNCTION OuterProductR16(u,v) + + ! this routine calculates the outer product of two vectors + + REAL(QuKi),INTENT(IN):: u(:),v(:) + REAL(QuKi)::OuterProductR16(SIZE(u),SIZE(v)) + + INTEGER(IntKi)::i,j,n1,n2 + + n1=SIZE(u) + n2=SIZE(v) + + DO i=1,n1 + DO j=1,n2 + OuterProductR16(i,j) = u(i) * v(j) + ENDDO + ENDDO + + END FUNCTION OuterProductR16 +!======================================================================= +!> This subroutine perturbs an orientation matrix by a small angle, using +!! a logarithmic map. For small angles, the change in angle is equivalent to +!! a change in log map parameters. + SUBROUTINE PerturbOrientationMatrix( Orientation, Perturbation, AngleDim ) + REAL(R8Ki), INTENT(INOUT) :: Orientation(3,3) + REAL(R8Ki), INTENT(IN) :: Perturbation ! angle (radians) of the perturbation + INTEGER, INTENT(IN) :: AngleDim + + ! Local variables + REAL(R8Ki) :: angles(3) + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + CALL DCM_LogMap( Orientation, angles, ErrStat2, ErrMsg2 ) + + angles(AngleDim) = angles(AngleDim) + Perturbation + + Orientation = DCM_exp( angles ) + + END SUBROUTINE PerturbOrientationMatrix +!======================================================================= +!> This routine factors the number N into its primes. If any of those +!! prime factors is greater than the NumPrimes'th prime, a value of 1 +!! is added to N and the new number is factored. This process is +!! repeated until no prime factors are greater than the NumPrimes'th +!! prime. +!! +!! If subract is .true., we will subtract 1 from the value of N instead +!! of adding it. + FUNCTION PSF ( Npsf, NumPrimes, subtract ) + + + IMPLICIT NONE + + !Passed variables + INTEGER, INTENT(IN) :: Npsf !< Initial number we're trying to factor. + INTEGER, INTENT(IN) :: NumPrimes !< Number of unique primes. + INTEGER :: PSF !< The smallest number at least as large as Npsf, that is the product of small factors when we return. + !! IF subtract is present and .TRUE., PSF is the largest number not greater than Npsf that is a product of small factors. + LOGICAL,OPTIONAL,INTENT(IN) :: subtract !< if PRESENT and .TRUE., we will subtract instead of add 1 to the number when looking for the value of PSF to return. + + !Other variables + INTEGER :: sign ! +1 or -1 + INTEGER :: IPR ! A counter for the NPrime array + INTEGER, PARAMETER :: NFact = 9 ! The number of prime numbers (the first NFact primes) + INTEGER :: NP ! A temp variable to determine if NPr divides NTR + INTEGER :: NPr ! A small prime number + INTEGER :: NT ! A temp variable to determine if NPr divides NTR: INT( NTR / NPr ) + INTEGER :: NTR ! The number we're trying to factor in each iteration + INTEGER, PARAMETER :: NPrime(NFact) = (/ 2, 3, 5, 7, 11, 13, 17, 19, 23 /) ! The first 9 prime numbers + + LOGICAL :: DividesN1(NFact) ! Does this factor divide NTR-1? + + + + DividesN1(:) = .FALSE. ! We need to check all of the primes the first time through + + sign = 1 + IF ( PRESENT( subtract ) ) THEN + IF (subtract) THEN + sign = -1 + END IF + END IF + + PSF = Npsf + + DO + ! First: Factor NTR into its primes. + + NTR = PSF + + DO IPR=1,MIN( NumPrimes, NFact ) + + IF ( DividesN1(IPR) ) THEN + + ! If P divides N-1, then P cannot divide N. + + DividesN1(IPR) = .FALSE. ! This prime number does not divide psf; We'll check it next time. + + ELSE + + NPr = NPrime(IPR) ! The small prime number we will try to find the the factorization of NTR + + DO + NT = NTR/NPr ! Doing some modular arithmetic to see if + NP = NT*NPr ! MOD( NTR, NPr ) == 0, i.e. if NPr divides NTR + + IF ( NP /= NTR ) EXIT ! There aren't any more of this prime number in the factorization + + NTR = NT ! This is the new number we need to get factors for + DividesN1(IPR) = .TRUE. ! This prime number divides psf, so we won't check it next time (on Npsf+1). + + ENDDO + + IF ( NTR .EQ. 1 ) RETURN ! We've found all the prime factors, so we're finished + + ENDIF ! DividesN1 + + ENDDO ! IPR + + ! Second: There is at least one prime larger than NPrime(NumPrimes). Add or subtract + ! a point to NTR and factor again. + + PSF = PSF + sign*1 + + ENDDO + + + RETURN + END FUNCTION PSF +!======================================================================= +!> This function computes the conjugate of a quaternion, q + FUNCTION Quaternion_Conjugate(q) + + ! + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 6 + + TYPE(Quaternion), INTENT(IN) :: q !< quaternion + + TYPE(Quaternion) :: Quaternion_Conjugate !< conjugate of the quaternion + + + Quaternion_Conjugate%q0 = q%q0 + Quaternion_Conjugate%v = -q%v + + END FUNCTION Quaternion_Conjugate +!======================================================================= +!> This function computes the 2-norm of a quaternion, q + FUNCTION Quaternion_Norm(q) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 5 + + TYPE(Quaternion), INTENT(IN) :: q !< quaternion + + REAL(ReKi) :: Quaternion_Norm !< 2-norm of q + + + Quaternion_Norm = sqrt( q%q0**2 + DOT_PRODUCT(q%v, q%v) ) + + + END FUNCTION Quaternion_Norm +!======================================================================= +!> This function computes the quaternion, q, raised to an arbitrary +!! real exponent, alpha. + FUNCTION Quaternion_Power(q,alpha) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 7-8 + + TYPE(Quaternion), INTENT(IN) :: q !< quaternion + REAL(ReKi) , INTENT(IN) :: alpha !< exponent + + TYPE(Quaternion) :: Quaternion_Power !< q^alpha + + + ! local variables + REAL(ReKi) :: greek ! the product of alpha and theta + REAL(ReKi) :: n(3) + REAL(ReKi) :: q_norm + REAL(ReKi) :: q_norm_power + REAL(ReKi) :: theta + + + q_norm = Quaternion_Norm( q ) + theta = acos( max(-1.0_ReKi, min(1.0_ReKi, q%q0 / q_norm)) ) + n = q%v / TwoNorm(q%v) + + greek = alpha * theta + q_norm_power = q_norm ** alpha + + Quaternion_Power%q0 = q_norm_power * cos( greek ) + Quaternion_Power%v = q_norm_power * sin( greek ) * n + + END FUNCTION Quaternion_Power +!======================================================================= +!> This function computes the product of two quaternions, p and q + FUNCTION Quaternion_Product(p, q) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 4 + + TYPE(Quaternion), INTENT(IN) :: p !< quaternion + TYPE(Quaternion), INTENT(IN) :: q !< quaternion + + TYPE(Quaternion) :: Quaternion_Product !< quaternion product, p*q + + + Quaternion_Product%q0 = p%q0 * q%q0 - DOT_PRODUCT(p%v, q%v) + Quaternion_Product%v = p%q0*q%v + q%q0*p%v + CROSS_PRODUCT( p%v, q%v ) + + + END FUNCTION Quaternion_Product +!======================================================================= +!> This function converts a quaternion to an equivalent direction cosine matrix. + FUNCTION Quaternion_to_DCM(q) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 9-17 + + TYPE(Quaternion), INTENT(IN) :: q !< quaternion + + REAL(ReKi) :: Quaternion_to_DCM (3,3) ! equivalent direction cosine matrix + + ! local variables (products of quaternion terms) + REAL(ReKi) :: q0q0, q0q1, q0q2, q0q3 + REAL(ReKi) :: q1q1, q1q2, q1q3 + REAL(ReKi) :: q2q2, q2q3 + REAL(ReKi) :: q3q3 + + q0q0 = q%q0**2 + q0q1 = q%q0 * q%v(1) + q0q2 = q%q0 * q%v(2) + q0q3 = q%q0 * q%v(3) + + q1q1 = q%v(1)**2 + q1q2 = q%v(1) * q%v(2) + q1q3 = q%v(1) * q%v(3) + + q2q2 = q%v(2)**2 + q2q3 = q%v(2) * q%v(3) + + q3q3 = q%v(2)**2 + + + Quaternion_to_DCM(1,1) = q0q0 + q1q1 - q2q2 - q3q3 ! Eq. 9 + Quaternion_to_DCM(1,2) = 2.0_ReKi*q1q2 + 2.0_ReKi*q0q3 ! Eq. 10 + Quaternion_to_DCM(1,3) = 2.0_ReKi*q1q3 + 2.0_ReKi*q0q2 ! Eq. 11 + + Quaternion_to_DCM(2,1) = 2.0_ReKi*q1q2 - 2.0_ReKi*q0q3 ! Eq. 12 + Quaternion_to_DCM(2,2) = q0q0 - q1q1 + q2q2 - q3q3 ! Eq. 13 + Quaternion_to_DCM(2,3) = 2.0_ReKi*q2q3 + q0q1 ! Eq. 14 + + + Quaternion_to_DCM(3,1) = 2.0_ReKi*q1q3 + q0q2 ! Eq. 15 + Quaternion_to_DCM(3,2) = 2.0_ReKi*q2q3 - q0q1 ! Eq. 16 + Quaternion_to_DCM(3,3) = q0q0 - q1q1 - q2q2 + q3q3 ! Eq. 17 + + + END FUNCTION Quaternion_to_DCM +!======================================================================= +!> This function converts a direction cosine matrix to an equivalent quaternion. + FUNCTION DCM_to_Quaternion(DCM) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 18-21 + + REAL(ReKi) , INTENT(IN) :: DCM (3,3) !< direction cosine matrix + TYPE(Quaternion) :: DCM_to_Quaternion !< equivalent quaternion + + + DCM_to_Quaternion%q0 = 0.5_ReKi * sqrt( 1.0_ReKi + DCM(1,1) + DCM(2,2) + DCM(3,3) ) ! Eq. 18 + DCM_to_Quaternion%v(1) = sign(0.5_ReKi * sqrt( 1.0_ReKi + DCM(1,1) - DCM(2,2) - DCM(3,3) ) , DCM(2,3) - DCM(3,2) ) ! Eq. 19 + DCM_to_Quaternion%v(2) = sign(0.5_ReKi * sqrt( 1.0_ReKi - DCM(1,1) + DCM(2,2) - DCM(3,3) ) , DCM(3,1) - DCM(1,3) ) ! Eq. 20 + DCM_to_Quaternion%v(3) = sign(0.5_ReKi * sqrt( 1.0_ReKi - DCM(1,1) - DCM(2,2) + DCM(3,3) ) , DCM(1,2) - DCM(2,1) ) ! Eq. 21 + + + + END FUNCTION DCM_to_Quaternion +!======================================================================= +!> This function computes the interpolated quaternion at time +!! t1 + s*(t2-t1) and s is in [0,1] + FUNCTION Quaternion_Interp(q1,q2,s) + + ! "'Interpolation' of DCMs", M.A. Sprague, 11 March 2014, Eq. 23 + + TYPE(Quaternion), INTENT(IN) :: q1 !< quaternion at t1 + TYPE(Quaternion), INTENT(IN) :: q2 !< quaternion at t2 + REAL(ReKi), INTENT(IN) :: s !< fraction of distance between t1 and t2: s must be in [0,1] + + TYPE(Quaternion) :: Quaternion_Interp !< interpolated quaternion at s + + + Quaternion_Interp = Quaternion_Conjugate(q1) + Quaternion_Interp = Quaternion_Product(Quaternion_Interp, q2) + Quaternion_Interp = Quaternion_Power( Quaternion_Interp, s ) + Quaternion_Interp = Quaternion_Product(q1, Quaternion_Interp) + + +! bjj: this function has not been tested. I have not tested any of the quaternion routines, either. + + END FUNCTION Quaternion_Interp +!======================================================================= +!> This routine calculates the parameters needed to compute a regularly-spaced natural cubic spline. +!! Natural cubic splines are used in that the curvature at the end points is zero. +!! It assumes the XAry values are equally spaced for speed. If you have multiple curves that share the +!! same value, use RegCubicSplineInitM (nwtc_num::regcubicsplineinitm) instead of calling this routine multiple times. + SUBROUTINE RegCubicSplineInit ( AryLen, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + + REAL(ReKi), INTENT(OUT) :: Coef (AryLen-1,0:3) !< The coefficients for the cubic polynomials. + REAL(ReKi), INTENT(OUT) :: DelX !< The distance between the equally spaced points. + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Input array of x values. + REAL(ReKi), INTENT(IN) :: YAry (AryLen) !< Input array of y values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + + ! Local declarations. + + REAL(ReKi) :: DelX2 ! The square of the distance between points. + REAL(ReKi) :: DelX4 ! Four times the distance between points. + REAL(ReKi) :: DelX6 ! Six times the distance between points. + REAL(ReKi), ALLOCATABLE :: Slope (:) ! The AryLen-1 length array of slopes between points. + REAL(ReKi), ALLOCATABLE :: U (:) ! An AryLen-1 length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: V (:) ! An AryLen-1 length array used in the Gaussian elimination. + REAL(ReKi) :: ZHi ! A parameter used to calculate the polynomial coefficients. + REAL(ReKi) :: ZLo ! A parameter used to calculate the polynomial coefficients. + + INTEGER(IntKi) :: ErrStatLcL ! Local error status. + INTEGER :: I ! The index into the arrays. + CHARACTER(*), PARAMETER :: RoutineName = 'RegCubicSplineInit' + + + ! Allocate the various intermediate arrays. + + ALLOCATE ( Slope( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the Slope array.' ) + RETURN + ENDIF + + ALLOCATE ( U( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the U array.' ) + RETURN + ENDIF + + ALLOCATE ( V( AryLen - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the V array.' ) + RETURN + ENDIF + + + ! Compute the distance between XAry values and the slopes between points. + + DelX = ( XAry(AryLen) - XAry(1) )/REAL( AryLen-1, ReKi ) ! Is this more accurate than XAry(2) - XAry(1)? + DelX2 = DelX*DelX + DelX4 = 4_ReKI*DelX + DelX6 = 6_ReKI*DelX + + DO I=1,AryLen-1 + Slope(I) = ( YAry(I+1) - YAry(I) )/DelX + END DO ! I + + + ! Use Gaussian elimination to solve the tri-diagonal matrix. + + U(1) = DelX4 + V(1) = 6.0_ReKi*( Slope(2) - Slope(1) ) + + DO I=2,AryLen-1 + U(I) = DelX4 - DelX2/U(I-1) + V(I) = 6.0_ReKi*( Slope(I) - Slope(I-1) ) - DelX*V(I-1)/U(I-1) + END DO ! I + + + ! Determine the coefficients of the polynomials. + + Coef(:,0) = YAry(1:AryLen-1) + + ZHi = 0.0_ReKi + + DO I=AryLen-1,1,-1 + ZLo = ( V(I) - DelX*ZHi )/U(I) + Coef(I,1) = Slope(I) - DelX*( ZHi/6.0_ReKi + ZLo/3.0_ReKi ) + Coef(I,2) = 0.5_ReKi*ZLo + Coef(I,3) = ( ZHi - ZLo )/DelX6 + ZHi = ZLo + END DO ! I + + + CALL ExitThisRoutine ( ErrID_None, 'No Problemo' ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + ! Deallocate the Words array if it had been allocated. + + IF ( ALLOCATED( Slope ) ) DEALLOCATE( Slope ) + IF ( ALLOCATED( U ) ) DEALLOCATE( U ) + IF ( ALLOCATED( V ) ) DEALLOCATE( V ) + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE RegCubicSplineInit ! ( AryLen, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine calculates the parameters needed to compute a regularly-spaced natural cubic spline. +!! Natural cubic splines are used in that the curvature at the end points is zero. +!! It assumes the XAry values are equally spaced for speed. +!! This version of the routine works with multiple curves that share the same X values. + SUBROUTINE RegCubicSplineInitM ( XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) + + ! Argument declarations: + + REAL(ReKi), INTENT(OUT) :: Coef (:,:,0:) ! The coefficients for the cubic polynomials. + REAL(ReKi), INTENT(OUT) :: DelX ! The distance between X values in XAry. + REAL(ReKi), INTENT(IN) :: XAry (:) ! Input array of regularly spaced x values. + REAL(ReKi), INTENT(IN) :: YAry (:,:) ! Input array of y values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. + + + ! Local declarations. + + REAL(ReKi) :: DelX2 ! The square of the distance between points. + REAL(ReKi) :: DelX4 ! Four times the distance between points. + REAL(ReKi) :: DelX6 ! Six times the distance between points. + REAL(ReKi), ALLOCATABLE :: Slope (:,:) ! The NumPts-1 length array of slopes between points. + REAL(ReKi), ALLOCATABLE :: U (:) ! An NumPts-1 length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: V (:,:) ! An NumPts-1 length array used in the Gaussian elimination. + REAL(ReKi), ALLOCATABLE :: ZHi (:) ! A parameter used to calculate the polynomial coefficients. + REAL(ReKi), ALLOCATABLE :: ZLo (:) ! A parameter used to calculate the polynomial coefficients. + + INTEGER(IntKi) :: ErrStatLcL ! Local error status. + INTEGER :: I ! The index into the arrays. +! INTEGER :: IC ! The curve index into the arrays. + INTEGER :: NumCrvs ! Number of curves to be interpolated. + INTEGER :: NumPts ! Number of points in each curve. + + CHARACTER(*), PARAMETER :: RoutineName = 'RegCubicSplineInitM' + + ! How big are the arrays? + + NumPts = SIZE( XAry ) + NumCrvs = SIZE( YAry, 2 ) + + + ! Allocate the various intermediate arrays. + + ALLOCATE ( ZLo( NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the ZLo array.' ) + RETURN + ENDIF + + ALLOCATE ( ZHi( NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the ZHi array.' ) + RETURN + ENDIF + + ALLOCATE ( Slope( NumPts-1, NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the Slope array.' ) + RETURN + ENDIF + + ALLOCATE ( U( NumPts - 1 ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the U array.' ) + RETURN + ENDIF + + ALLOCATE ( V( NumPts-1, NumCrvs ), STAT=ErrStatLcL ) + IF ( ErrStatLcL /= 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, RoutineName//':Error allocating memory for the V array.' ) + RETURN + ENDIF + + + ! Compute the distance between XAry values and the slopes between points. + + DelX = ( XAry(NumPts) - XAry(1) )/REAL( NumPts-1, ReKi ) ! Is this more accurate than XAry(2) - XAry(1)? + DelX2 = DelX*DelX + DelX4 = 4_ReKI*DelX + DelX6 = 6_ReKI*DelX + + DO I=1,NumPts-1 + Slope(I,:) = ( YAry(I+1,:) - YAry(I,:) )/DelX + END DO ! I + + + ! Use Gaussian elimination to solve the tri-diagonal matrix. + + U(1) = DelX4 + + DO I=2,NumPts-1 + U(I) = DelX4 - DelX2/U(I-1) + END DO ! I + + V(1,:) = 6.0_ReKi*( Slope(2,:) - Slope(1,:) ) + + DO I=2,NumPts-1 + V(I,:) = 6.0_ReKi*( Slope(I,:) - Slope(I-1,:) ) - DelX*V(I-1,:)/U(I-1) + END DO ! I + + + ! Determine the coefficients of the polynomials. + + Coef(:,:,0) = YAry(1:NumPts-1,:) + + ZHi(:) = 0.0_ReKi + + DO I=NumPts-1,1,-1 + ZLo(:) = ( V(I,:) - DelX*ZHi(:) )/U(I) + Coef(I,:,1) = Slope(I,:) - DelX*( ZHi(:)/6.0_ReKi + ZLo(:)/3.0_ReKi ) + Coef(I,:,2) = 0.5_ReKi*ZLo(:) + Coef(I,:,3) = ( ZHi(:) - ZLo(:) )/DelX6 + ZHi(:) = ZLo(:) + END DO ! I + + + CALL ExitThisRoutine ( ErrID_None, 'No Problemo' ) + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + ! Deallocate the Words array if it had been allocated. + + IF ( ALLOCATED( ZHi ) ) DEALLOCATE( ZHi ) + IF ( ALLOCATED( ZLo ) ) DEALLOCATE( ZLo ) + IF ( ALLOCATED( Slope ) ) DEALLOCATE( Slope ) + IF ( ALLOCATED( U ) ) DEALLOCATE( U ) + IF ( ALLOCATED( V ) ) DEALLOCATE( V ) + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE RegCubicSplineInitM ! ( XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine interpolates a pair of arrays using cubic splines to find the function value at X. +!! One must call RegCubicSplineInit() (nwtc_num::regcubicsplineinit) first to compute the coefficients of the cubics. +!! This routine requires that the XAry be regularly spaced, which improves performance. + FUNCTION RegCubicSplineInterp ( X, AryLen, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) + + ! Function declaration. + + REAL(ReKi) :: RegCubicSplineInterp !< This function. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + + REAL(ReKi), INTENT(IN) :: Coef (AryLen-1,0:3) !< The coefficients for the cubic polynomials. + REAL(ReKi), INTENT(IN) :: DelX !< The distance between X values in XAry. + REAL(ReKi), INTENT(IN) :: X !< The value we are trying to interpolate for. + REAL(ReKi), INTENT(IN) :: XAry (AryLen) !< Input array of regularly spaced x values. + REAL(ReKi), INTENT(IN) :: YAry (AryLen) !< Input array of y values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + + ! Local declarations. + + REAL(ReKi) :: XOff ! The distance from X to XAry(ILo). + + INTEGER :: ILo ! The index into the array for which X is just above or equal to XAry(ILo). + + ErrStat = ErrID_None + ErrMsg = "" + + ! See if X is within the range of XAry. Return the end point if it is not. + + IF ( X <= XAry(1) ) THEN + RegCubicSplineInterp = YAry(1) + RETURN + ELSEIF ( X >= XAry(AryLen) ) THEN + RegCubicSplineInterp = YAry(AryLen) + RETURN + ENDIF ! ( X <= XAry(1) ) + + + ! We are somewhere inside XAry. Find the segment that bounds X. + + ILo = INT( ( X - XAry(1) )/DelX ) + 1 + + XOff = X - XAry(ILo) + + RegCubicSplineInterp = Coef(ILo,0) + XOff*( Coef(ILo,1) + XOff*( Coef(ILo,2) + XOff*Coef(ILo,3) ) ) + + + RETURN + + END FUNCTION RegCubicSplineInterp ! ( X, AryLen, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine interpolates a pair of arrays using cubic splines to find the function value at X. +!! One must call RegCubicSplineInitM() (nwtc_num::regcubicsplineinitm) first to compute the coefficients of the cubics. +!! This routine requires that the XAry be regularly spaced, which improves performance. +!! This version of the routine works with multiple curves that share the same X values. + FUNCTION RegCubicSplineInterpM ( X, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) RESULT( Res ) + + ! Function declaration. + + REAL(ReKi), ALLOCATABLE :: Res(:) !< The result of this function. + + + ! Argument declarations: + + REAL(ReKi), INTENT(IN) :: Coef (:,:,0:) !< The coefficients for the cubic polynomials. + REAL(ReKi), INTENT(IN) :: DelX !< The distance between X values in XAry. + REAL(ReKi), INTENT(IN) :: X !< The value we are trying to interpolate for. + REAL(ReKi), INTENT(IN) :: XAry (:) !< Input array of regularly spaced x values. + REAL(ReKi), INTENT(IN) :: YAry (:,:) !< Input array of y values. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status. + + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message. + + + ! Local declarations. + + REAL(ReKi) :: XOff ! The distance from X to XAry(ILo). + + INTEGER :: ErrStatLcL ! Local error status. + INTEGER :: ILo ! The index into the array for which X is just above or equal to XAry(ILo). + INTEGER :: NumCrvs ! Number of curves. + INTEGER :: NumPts ! Number of points in each curve. + + + ErrStat = ErrID_None + ErrMsg = "" + + ! How big are the arrays? Use the size to allocate the result. + + NumPts = SIZE( XAry ) + NumCrvs = SIZE( YAry, 2 ) + + ALLOCATE ( Res( NumCrvs ) , STAT=ErrStatLcl ) + IF ( ErrStatLcl /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "RegCubicSplineInterpM:Error allocating memory for the function result." + RETURN + ENDIF + + + ! See if X is within the range of XAry. Return the end point if it is not. + + IF ( X <= XAry(1) ) THEN + Res(:) = YAry(1,:) + RETURN + ELSEIF ( X >= XAry(NumPts) ) THEN + Res(:) = YAry(NumPts,:) + RETURN + ENDIF ! ( X <= XAry(1) ) + + + ! We are somewhere inside XAry. Find the segment that bounds X. + + ILo = INT( ( X - XAry(1) )/DelX ) + 1 + + XOff = X - XAry(ILo) + + Res(:) = Coef(ILo,:,0) + XOff*( Coef(ILo,:,1) + XOff*( Coef(ILo,:,2) + XOff*Coef(ILo,:,3) ) ) + + + RETURN + END FUNCTION RegCubicSplineInterpM ! ( X, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) +!======================================================================= +!> This routine is used to integrate funciton f over the interval [a, b]. This routine +!! is useful for sufficiently smooth (e.g., analytic) integrands, integrated over +!! intervals which contain no singularities, and where the endpoints are also nonsingular. +!! +!! f is an external function. For example f(x) = 1 + x. +!! +!! FUNCTION f(x) +!! USE PRECISION +!! IMPLICIT NONE +!! +!! REAL(ReKi) f +!! REAL(ReKi) x +!! +!! f = 1 + x +!! +!! RETURN +!! END FUNCTION f + SUBROUTINE RombergInt(f, a, b, R, err, eps, ErrStat) + + + IMPLICIT NONE + + ! Argument declarations: + + REAL(ReKi), EXTERNAL :: f !< Integrand function name + REAL(ReKi), INTENT(IN) :: a !< Lower integration limit + REAL(ReKi), INTENT(IN) :: b !< Upper integration limit + REAL(ReKi), INTENT(IN) :: eps !< Absolute error bound + REAL(ReKi), INTENT(OUT) :: R !< The result of integration + REAL(ReKi), INTENT(OUT) :: err !< Actual absolute error + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat !< Error status; if present, program does not abort on error + + ! Local declarations: + + INTEGER :: m, i, j, k, IOS + INTEGER, PARAMETER :: mmax = 50 ! Maximum iteration number for m + INTEGER, PARAMETER :: imax = 50 ! Maximum iteration number for i + + REAL(ReKi), ALLOCATABLE :: T(:,:) + REAL(ReKi) :: h ! Step length + REAL(ReKi) :: sumf + + ! Initialize T + ALLOCATE( T( mmax, imax ), Stat=ios ) + IF (IOS /= 0) THEN + CALL ProgAbort ( 'RombergInt: Error allocating T.', PRESENT(ErrStat) ) + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + RETURN + END IF + END IF + + T = 0 + + T(1, 1) = 0.5*(b - a)*( f(a) + f(b) ) + + k = 2 + DO m = 1, mmax-2 + h = (b-a)*(0.5)**m + + sumf = 0 + DO i = 1, 2**(m-1) + sumf = sumf + f(a + (2*i-1)*h) + k = k + 1 + END DO + + + T( m+1, 1) = 0.5*T( m, 1 )+ h * sumf + + DO j = 1, m + T(m-j+1, j+1) = ( 4.0**j * T(m-j+2, j) - T(m-j+1, j) )/(4.0**j - 1.0) + + ! absolute error + err = ABS( T(m-j+1, j+1) - T( m-j+2, j ) ) + + ! set k >=9 to prevent early terminations + IF( (err .LT. eps) .and. (k >= 9) ) THEN + + ! return the intergration result if the conditions are met + R = T(m-j+1, j+1) + + IF( ALLOCATED(T) ) DEALLOCATE(T) + + RETURN + END IF + + END DO + + END DO + + err = ABS( T(m-j+1, j+1) - T( m-j+2, j ) ) + R = T(m-j+1, j+1) + + IF( ALLOCATED(T) ) DEALLOCATE(T) + + ! Return error message if the maximum iteration number is reached. + CALL ProgAbort ( ' In subroutine RombergInt, the iteration reaches the maximum number. The integration did NOT converge! ', & + PRESENT(ErrStat) ) + IF ( PRESENT(ErrStat) ) THEN + ErrStat = ErrID_Fatal + RETURN + END IF + + RETURN + END SUBROUTINE RombergInt +!======================================================================= +!> This routine displays a message that gives that status of the simulation and the predicted end time of day. +!! It is intended to be used with SimStatus (nwtc_num::simstatus) and SimStatus_FirstTime (nwtc_num::simstatus_firsttime). + SUBROUTINE RunTimes( StrtTime, UsrTime1, SimStrtTime, UsrTime2, ZTime, UnSum, UsrTime_out, DescStrIn ) + + IMPLICIT NONE + + ! Passed variables + + INTEGER , INTENT(IN) :: StrtTime (8) !< Start time of simulation (including initialization) + INTEGER , INTENT(IN) :: SimStrtTime (8) !< Start time of simulation (after initialization) + REAL(ReKi), INTENT(IN) :: UsrTime1 !< User CPU time for simulation initialization. + REAL(ReKi), INTENT(IN) :: UsrTime2 !< User CPU time for simulation (without intialization) + REAL(DbKi), INTENT(IN) :: ZTime !< The final simulation time (not necessarially TMax) + INTEGER(IntKi), INTENT(IN), OPTIONAL:: UnSum !< optional unit number of file. If present and > 0, + REAL(ReKi), INTENT(OUT),OPTIONAL:: UsrTime_out !< User CPU time for entire run - optional value returned to calling routine + + CHARACTER(*), INTENT(IN), OPTIONAL :: DescStrIn !< optional additional string to print for SimStatus + + ! Local variables + + REAL(ReKi) :: ClckTime ! Elapsed clock time for the entire run. + REAL(ReKi) :: ClckTimeSim ! Elapsed clock time for the simulation phase of the run. + REAL(ReKi) :: Factor ! Ratio of seconds to a specified time period. + REAL(ReKi) :: TRatio ! Ratio of simulation time to elapsed clock time. + REAL(ReKi), PARAMETER :: SecPerDay = 24*60*60.0_ReKi ! Number of seconds per day + + REAL(ReKi) :: UsrTime ! User CPU time for entire run. + REAL(ReKi) :: UsrTimeSim ! User CPU time for simulation (not including initialization). + INTEGER :: EndTimes (8) ! An array holding the ending clock time of the simulation. + + CHARACTER( 8) :: TimePer + CHARACTER(MaxWrScrLen) :: BlankLine + CHARACTER(10) :: DescStr !< optional additional string to print for SimStatus + + + if (present(DescStrIn)) then + DescStr = DescStrIn + else + DescStr = "" + end if + + ! Get the end times to compare with start times. + + CALL DATE_AND_TIME ( VALUES=EndTimes ) + CALL CPU_TIME ( UsrTime ) + UsrTime = MAX( 0.0_ReKi, UsrTime ) ! CPU_TIME: If a meaningful time cannot be returned, a processor-dependent negative value is returned + + + ! Calculate the elapsed wall-clock time in seconds. + + ClckTime = GetClockTime(StrtTime, EndTimes) + !ClckTimeInit = GetClockTime(StrtTime, SimStrtTime) + ClckTimeSim = GetClockTime(SimStrtTime, EndTimes) + + ! Calculate CPU times. + + UsrTime = MAX( 0.0_ReKi, UsrTime - UsrTime1 ) + UsrTimeSim = MAX( 0.0_ReKi, UsrTime - UsrTime2 ) + + + IF ( .NOT. EqualRealNos( UsrTimeSim, 0.0_ReKi ) .AND. ZTime > 0.0_DbKi ) THEN + + TRatio = REAL(ZTime,ReKi) / UsrTimeSim + + IF ( UsrTime > SecPerDay ) THEN + Factor = 1.0_ReKi/SecPerDay + TimePer = ' days' + ELSEIF ( UsrTime > 3600.0_ReKi ) THEN + Factor = 1.0_ReKi/3600.0_ReKi + TimePer = ' hours' + ELSEIF ( UsrTime > 60.0_ReKi ) THEN + Factor = 1.0_ReKi/60.0_ReKi + TimePer = ' minutes' + ELSE + Factor = 1.0_ReKi + TimePer = ' seconds' + ENDIF + + BlankLine = "" + CALL WrOver( BlankLine ) ! BlankLine contains MaxWrScrLen spaces + CALL WrScr ( DescStr ) + CALL WrScr ( ' Total Real Time: '//TRIM( Num2LStr( Factor*ClckTime ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Total CPU Time: '//TRIM( Num2LStr( Factor*UsrTime ) )//TRIM( TimePer ) ) + ! CALL WrScr ( ' ') + ! CALL WrScr ( ' Simulation Real Time: '//TRIM( Num2LStr( Factor*ClckTimeSim ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Simulation CPU Time: '//TRIM( Num2LStr( Factor*UsrTimeSim ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Simulated Time: '//TRIM( Num2LStr( Factor*REAL( ZTime ) ) )//TRIM( TimePer ) ) + CALL WrScr ( ' Time Ratio (Sim/CPU): '//TRIM( Num2LStr( TRatio ) ) ) + + IF (PRESENT(UnSum)) THEN + IF (UnSum>0) THEN + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A)') ' Total Real Time: '//TRIM( Num2LStr( Factor*ClckTime ) )//TRIM( TimePer ) + WRITE( UnSum, '(A)') ' Total CPU Time: '//TRIM( Num2LStr( Factor*UsrTime ) )//TRIM( TimePer ) + WRITE( UnSum, '(A)') ' Simulation CPU Time: '//TRIM( Num2LStr( Factor*UsrTimeSim ) )//TRIM( TimePer ) + WRITE( UnSum, '(A)') ' Simulated Time: '//TRIM( Num2LStr( Factor*REAL( ZTime ) ) )//TRIM( TimePer ) + WRITE( UnSum, '(A)') ' Time Ratio (Sim/CPU): '//TRIM( Num2LStr( TRatio ) ) + END IF + END IF + + + + ENDIF + + IF (PRESENT(UsrTime_out)) UsrTime_out = UsrTime + RETURN + CONTAINS + + FUNCTION GetClockTime(StartClockTime, EndClockTime) + ! return the number of seconds between StartClockTime and EndClockTime + + REAL :: GetClockTime ! Elapsed clock time for the simulation phase of the run. + INTEGER , INTENT(IN) :: StartClockTime (8) ! Start time of simulation (after initialization) + INTEGER , INTENT(IN) :: EndClockTime (8) ! Start time of simulation (after initialization) + + !bjj: This calculation will be wrong at certain times (e.g. if it's near midnight on the last day of the month), but to my knowledge, no one has complained... + GetClockTime = 0.001*( EndClockTime(8) - StartClockTime(8) ) & ! Is the milliseconds of the second (range 0 to 999) - local time + + ( EndClockTime(7) - StartClockTime(7) ) & ! Is the seconds of the minute (range 0 to 59) - local time + + 60.0*( EndClockTime(6) - StartClockTime(6) ) & ! Is the minutes of the hour (range 0 to 59) - local time + + 3600.0*( EndClockTime(5) - StartClockTime(5) ) & ! Is the hour of the day (range 0 to 23) - local time + + SecPerDay*( EndClockTime(3) - StartClockTime(3) ) ! Is the day of the month + + + END FUNCTION GetClockTime + + END SUBROUTINE RunTimes +!======================================================================= +!> this routine takes angles (in radians) and converts them to appropriate +!! ranges so they can be interpolated appropriately +!! (i.e., interpolating between pi+.1 and -pi should give pi+0.5 +!! instead of of 0.05 radians, so we return the angles pi+.1 and -pi+2pi=pi +!! we assume the interpolation occurs in the second dimension of angles +!! and it is done for each angle in the first dimension + SUBROUTINE SetAnglesForInterp( angles ) + + + REAL(ReKi), INTENT(INOUT) :: angles(:,:) ! + + REAL(ReKi) :: diff ! difference between two adjacent angles + INTEGER(IntKi) :: nr, nc ! size of the angles matrix + INTEGER(IntKi) :: ir, ic ! loop counters for each array dimension + + nr = size(angles,1) + nc = size(angles,2) + + + ! now let's make sure they don't cross a 2pi boundary (max |difference| can be pi): + ! bjj: this is a dumb algorithm that should be revisited sometime + + do ic=2,nc + do ir=1,nr + diff = angles(ir,ic-1) - angles(ir,ic) + do while ( diff > pi ) + angles(ir,ic) = angles(ir,ic) + TwoPi + diff = angles(ir,ic-1) - angles(ir,ic) + end do + do while ( diff < -pi ) + angles(ir,ic) = angles(ir,ic) - TwoPi + diff = angles(ir,ic-1) - angles(ir,ic) + end do + end do + end do + + + END SUBROUTINE SetAnglesForInterp +!======================================================================= +!> This routine computes numeric constants stored in the NWTC Library + SUBROUTINE SetConstants( ) + + ! Constants based upon Pi: + + Pi_D = ACOS( -1.0_DbKi ) + D2R_D = Pi_D/180.0_DbKi + R2D_D = 180.0_DbKi/Pi_D + PiBy2_D = Pi_D/2.0_DbKi + RPM2RPS_D = Pi_D/30.0_DbKi + RPS2RPM_D = 30.0_DbKi/Pi_D + TwoByPi_D = 2.0_DbKi/Pi_D + TwoPi_D = 2.0_DbKi*Pi_D + Inv2Pi_D = 0.5_DbKi/Pi_D ! 1.0_DbKi/TwoPi_D + + Pi = ACOS( -1.0_ReKi ) + D2R = Pi/180.0_ReKi + R2D = 180.0_ReKi/Pi + PiBy2 = Pi/2.0_ReKi + RPM2RPS = Pi/30.0_ReKi + RPS2RPM = 30.0_ReKi/Pi + TwoByPi = 2.0_ReKi/Pi + TwoPi = 2.0_ReKi*Pi + Inv2Pi = 0.5_ReKi/Pi ! 1.0/TwoPi + + Pi_R4 = ACOS( -1.0_SiKi ) + Pi_R8 = ACOS( -1.0_R8Ki ) + Pi_R16 = ACOS( -1.0_QuKi ) + + TwoPi_R4 = Pi_R4 *2.0_SiKi + TwoPi_R8 = Pi_R8 *2.0_R8Ki + TwoPi_R16 = Pi_R16*2.0_QuKi + + ! IEEE constants: + CALL Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + + RETURN + END SUBROUTINE SetConstants +!======================================================================= +!> This routine displays a message that gives that status of the simulation. +!! It is intended to be used with RunTimes (nwtc_num::runtimes) and SimStatus (nwtc_num::simstatus). + SUBROUTINE SimStatus_FirstTime( PrevSimTime, PrevClockTime, SimStrtTime, UsrTimeSim, ZTime, TMax, DescStrIn ) + + IMPLICIT NONE + + ! Passed variables + REAL(DbKi), INTENT(IN ) :: ZTime !< Current simulation time (s) + REAL(DbKi), INTENT(IN ) :: TMax !< Expected simulation time (s) + REAL(DbKi), INTENT( OUT) :: PrevSimTime !< Previous time message was written to screen (s > 0) + REAL(ReKi), INTENT( OUT) :: PrevClockTime !< Previous clock time in seconds past midnight + INTEGER, INTENT( OUT) :: SimStrtTime (8) !< An array containing the elements of the start time. + REAL(ReKi), INTENT( OUT) :: UsrTimeSim !< User CPU time for simulation (without intialization) + + CHARACTER(*), INTENT(IN), OPTIONAL :: DescStrIn !< optional additional string to print for SimStatus + + ! Local variables. + + REAL(ReKi) :: CurrClockTime ! Current time in seconds past midnight. + CHARACTER(10) :: DescStr !< optional additional string to print for SimStatus + + + if (present(DescStrIn)) then + DescStr = DescStrIn + else + DescStr = "" + end if + + + ! How many seconds past midnight? + + CALL DATE_AND_TIME ( Values=SimStrtTime ) + CALL CPU_TIME ( UsrTimeSim ) ! Initial CPU time + UsrTimeSim = MAX( 0.0_ReKi, UsrTimeSim ) ! CPU_TIME: If a meaningful time cannot be returned, a processor-dependent negative value is returned + + CurrClockTime = TimeValues2Seconds( SimStrtTime ) + + + CALL WrScr ( trim(DescStr)//' Time: '//TRIM( Num2LStr( NINT( ZTime ) ) )//' of '//TRIM( Num2LStr( TMax ) )//' seconds.') + + + ! Let's save this time as the previous time for the next call to the routine + PrevClockTime = CurrClockTime + PrevSimTime = ZTime + + RETURN + END SUBROUTINE SimStatus_FirstTime +!======================================================================= +!> This routine displays a message that gives that status of the simulation and the predicted end time of day. +!! It is intended to be used with RunTimes (nwtc_num::runtimes) and SimStatus_FirstTime (nwtc_num::simstatus_firsttime). + SUBROUTINE SimStatus( PrevSimTime, PrevClockTime, ZTime, TMax, DescStrIn, StatInfoIn) + + + IMPLICIT NONE + + ! Passed variables + REAL(DbKi), INTENT(IN) :: ZTime !< Current simulation time (s) + REAL(DbKi), INTENT(IN) :: TMax !< Expected simulation time (s) + REAL(DbKi), INTENT(INOUT) :: PrevSimTime !< Previous time message was written to screen (s > 0) + REAL(ReKi), INTENT(INOUT) :: PrevClockTime !< Previous clock time in seconds past midnight + + CHARACTER(*), INTENT(IN), OPTIONAL :: DescStrIn !< optional additional string to print at start of SimStatus + CHARACTER(*), INTENT(IN), OPTIONAL :: StatInfoIn !< optional additional string to print at end of SimStatus + + ! Local variables. + + REAL(ReKi) :: CurrClockTime ! Current time in seconds past midnight. + REAL(ReKi) :: DeltTime ! The amount of time elapsed since the last call. + REAL(ReKi) :: EndTime ! Approximate time of day when simulation will complete. + REAL(ReKi), PARAMETER :: InSecHr = 1.0_ReKi/3600.0_ReKi ! Inverse of the number of seconds in an hour + REAL(ReKi), PARAMETER :: InSecMn = 1.0_ReKi/ 60.0_ReKi ! Inverse of the number of seconds in a minute + REAL(ReKi) :: SimTimeLeft ! Approximate clock time remaining before simulation completes + + REAL(ReKi), PARAMETER :: SecPerDay = 24*60*60.0_ReKi ! Number of seconds per day + + INTEGER(4) :: EndHour ! The hour when the simulations is expected to complete. + INTEGER(4) :: EndMin ! The minute when the simulations is expected to complete. + INTEGER(4) :: EndSec ! The second when the simulations is expected to complete. + INTEGER(4) :: TimeAry (8) ! An array containing the elements of the start time. + + CHARACTER(MaxWrScrLen) :: BlankLine + CHARACTER( 8) :: ETimeStr ! String containing the end time. + CHARACTER( 10) :: DescStr !< optional additional string to print for SimStatus + CHARACTER(200) :: StatInfo !< optional additional string to print for SimStatus + + + IF ( ZTime <= PrevSimTime ) RETURN + + + if (present(DescStrIn)) then + DescStr = DescStrIn + else + DescStr = "" + end if + + if (present(StatInfoIn)) then + StatInfo = StatInfoIn + else + StatInfo = "" + end if + + ! How many seconds past midnight? + + CALL DATE_AND_TIME ( Values=TimeAry ) + CurrClockTime = TimeValues2Seconds( TimeAry ) + + ! Calculate elapsed clock time + + DeltTime = CurrClockTime - PrevClockTime + + + ! We may have passed midnight since the last revoultion. We will assume that (ZTime - PrevSimTime) of + ! simulation time doesn't take more than a day. + + IF ( CurrClockTime < PrevClockTime ) THEN + DeltTime = DeltTime + SecPerDay + ENDIF + + + ! Estimate the end time in hours, minutes, and seconds + + SimTimeLeft = REAL( ( TMax - ZTime )*DeltTime/( ZTime - PrevSimTime ), ReKi ) ! DeltTime/( ZTime - PrevSimTime ) is the delta_ClockTime divided by the delta_SimulationTime + EndTime = MOD( CurrClockTime+SimTimeLeft, SecPerDay ) + EndHour = INT( EndTime*InSecHr ) + EndMin = INT( ( EndTime - REAL( 3600*EndHour ) )*InSecMn ) + EndSec = NINT( EndTime - REAL( 3600*EndHour + 60*EndMin ) ) !bjj: this NINT can make the seconds say "60" + + WRITE (ETimeStr,"(I2.2,2(':',I2.2))") EndHour, EndMin, EndSec + + BlankLine = "" + CALL WrOver( BlankLine ) ! BlankLine contains MaxWrScrLen spaces + CALL WrOver ( trim(DescStr)//' Time: '//TRIM( Num2LStr( NINT( ZTime ) ) )//' of '//TRIM( Num2LStr( TMax ) )// & + ' seconds. '//trim(StatInfo)// & + ' Estimated final completion at '//ETimeStr//'.') + + ! Let's save this time as the previous time for the next call to the routine + PrevClockTime = CurrClockTime + PrevSimTime = ZTime + + RETURN + END SUBROUTINE SimStatus +!======================================================================= +!> This routine computes the 3x3 transformation matrix, \f$TransMat\f$, +!! to a coordinate system \f$x\f$ (with orthogonal axes \f$x_1, x_2, x_3\f$) +!! resulting from three rotations (\f$\theta_1\f$, \f$\theta_2\f$, \f$\theta_3\f$) about the +!! orthogonal axes (\f$X_1, X_2, X_3\f$) of coordinate system \f$X\f$. All angles +!! are assummed to be small, as such, the order of rotations does +!! not matter and Euler angles do not need to be used. This routine +!! is used to compute the transformation matrix (\f$TransMat\f$) between +!! undeflected (\f$X\f$) and deflected (\f$x\f$) coordinate systems. In matrix +!! form: +!! \f{equation}{ +!! \left\{ \begin{matrix} x_1 \\ x_2 \\ x_3 \end{matrix} \right\} = +!! \left[ TransMat(\theta_1, \theta_2, \theta_3) \right] +!! \left\{ \begin{matrix} X_1 \\ X_2 \\ X_3 \end{matrix} \right\} +!! \f} +!! +!! The transformation matrix, \f$TransMat\f$, is the closest orthonormal +!! matrix to the nonorthonormal, but skew-symmetric, Bernoulli-Euler +!! matrix: +!! \f{equation}{ A = +!! \begin{bmatrix} 1 & \theta_3 & -\theta_2 \\ +!! -\theta_3 & 1 & \theta_1 \\ +!! \theta_2 & -\theta_1 & 1 \end{bmatrix} +!! \f} +!! In the Frobenius Norm sense, the closest orthornormal matrix is: +!! \f$TransMat = U V^T\f$, +!! where the columns of \f$U\f$ contain the eigenvectors of\f$ AA^T\f$ and the +!! columns of \f$V\f$ contain the eigenvectors of \f$A^TA\f$ (note that \f$^T\f$ = transpose). +!! This result comes directly from the Singular Value Decomposition +!! (SVD) of \f$A = USV^T\f$ where \f$S\f$ is a diagonal matrix containing the +!! singular values of \f$A\f$, which are sqrt( eigenvalues of \f$AA^T\f$ ) = +!! sqrt( eigenvalues of \f$A^TA\f$ ). +!! +!! The algebraic form of the transformation matrix, as implemented +!! below, was derived symbolically by J. Jonkman by computing \f$UV^T\f$ +!! by hand with verification in Mathematica. +!! +!! This routine is the inverse of GetSmllRotAngs (nwtc_num::getsmllrotangs). \n +!! Use SmllRotTrans (nwtc_num::smllrottrans) instead of directly calling a specific routine in the generic interface. + SUBROUTINE SmllRotTransD( RotationType, Theta1, Theta2, Theta3, TransMat, ErrTxt, ErrStat, ErrMsg ) + + ! Passed Variables: + + REAL(ReKi), INTENT(IN ) :: Theta1 !< \f$\theta_1\f$: the small rotation about \f$X_1\f$, (rad). + REAL(ReKi), INTENT(IN ) :: Theta2 !< \f$\theta_2\f$: the small rotation about \f$X_2\f$, (rad). + REAL(ReKi), INTENT(IN ) :: Theta3 !< \f$\theta_3\f$: the small rotation about \f$X_3\f$, (rad). + REAL(DbKi), INTENT(OUT) :: TransMat (3,3) !< The resulting transformation matrix from \f$X\f$ to \f$x\f$, (-). + + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message corresponding to ErrStat + + CHARACTER(*), INTENT(IN) :: RotationType !< The type of rotation; used to inform the user where a large rotation is occuring upon such an event. + CHARACTER(*), INTENT(IN ), OPTIONAL :: ErrTxt !< an additional message to be displayed as a warning (typically the simulation time) + + ! Local Variables: + + REAL(DbKi) :: ComDenom ! = ( Theta1^2 + Theta2^2 + Theta3^2 )*SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + REAL(DbKi), PARAMETER :: LrgAngle = 0.4 ! Threshold for when a small angle becomes large (about 23deg). This comes from: COS(SmllAngle) ~ 1/SQRT( 1 + SmllAngle^2 ) and SIN(SmllAngle) ~ SmllAngle/SQRT( 1 + SmllAngle^2 ) results in ~5% error when SmllAngle = 0.4rad. + REAL(DbKi) :: Theta11 ! = Theta1^2 + REAL(DbKi) :: Theta12S ! = Theta1*Theta2*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta13S ! = Theta1*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta22 ! = Theta2^2 + REAL(DbKi) :: Theta23S ! = Theta2*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta33 ! = Theta3^2 + REAL(DbKi) :: SqrdSum ! = Theta1^2 + Theta2^2 + Theta3^2 + REAL(DbKi) :: SQRT1SqrdSum ! = SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + + LOGICAL, SAVE :: FrstWarn = .TRUE. ! When .TRUE., indicates that we're on the first warning. + + + ErrStat = ErrID_None + ErrMsg = '' + + ! Display a warning message if at least one angle gets too large in magnitude: + + IF ( ( ( ABS(Theta1) > LrgAngle ) .OR. ( ABS(Theta2) > LrgAngle ) .OR. ( ABS(Theta3) > LrgAngle ) ) .AND. FrstWarn ) THEN + + ErrStat= ErrID_Severe + ErrMsg = 'Small angle assumption violated in SUBROUTINE SmllRotTrans() due to a large '//TRIM(RotationType)//'. '// & + 'The solution may be inaccurate. Simulation continuing, but future warnings from SmllRotTrans() will be suppressed.' + + IF ( PRESENT(ErrTxt) ) THEN + ErrMsg = TRIM(ErrMsg)//NewLine//' Additional debugging message from SUBROUTINE SmllRotTrans(): '//TRIM(ErrTxt) + END IF + + !CALL ProgWarn( TRIM(ErrMsg) ) + + FrstWarn = .FALSE. ! Don't enter here again! + + ENDIF + + + ! Compute some intermediate results: + + Theta11 = Theta1*Theta1 + Theta22 = Theta2*Theta2 + Theta33 = Theta3*Theta3 + + SqrdSum = Theta11 + Theta22 + Theta33 + SQRT1SqrdSum = SQRT( 1.0_DbKi + SqrdSum ) + ComDenom = SqrdSum*SQRT1SqrdSum + + Theta12S = Theta1*Theta2*( SQRT1SqrdSum - 1.0_DbKi ) + Theta13S = Theta1*Theta3*( SQRT1SqrdSum - 1.0_DbKi ) + Theta23S = Theta2*Theta3*( SQRT1SqrdSum - 1.0_DbKi ) + + + ! Define the transformation matrix: + + IF ( ComDenom == 0.0_DbKi ) THEN ! All angles are zero and matrix is ill-conditioned (the matrix is derived assuming that the angles are not zero); return identity + + TransMat(1,:) = (/ 1.0_DbKi, 0.0_DbKi, 0.0_DbKi /) + TransMat(2,:) = (/ 0.0_DbKi, 1.0_DbKi, 0.0_DbKi /) + TransMat(3,:) = (/ 0.0_DbKi, 0.0_DbKi, 1.0_DbKi /) + + ELSE ! At least one angle is nonzero + + TransMat(1,1) = ( Theta11*SQRT1SqrdSum + Theta22 + Theta33 )/ComDenom + TransMat(2,2) = ( Theta11 + Theta22*SQRT1SqrdSum + Theta33 )/ComDenom + TransMat(3,3) = ( Theta11 + Theta22 + Theta33*SQRT1SqrdSum )/ComDenom + TransMat(1,2) = ( Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(2,1) = ( -Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(1,3) = ( -Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(3,1) = ( Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(2,3) = ( Theta1*SqrdSum + Theta23S )/ComDenom + TransMat(3,2) = ( -Theta1*SqrdSum + Theta23S )/ComDenom + + ENDIF + + + RETURN + END SUBROUTINE SmllRotTransD +!======================================================================= +!> \copydoc nwtc_num::smllrottransd + SUBROUTINE SmllRotTransDD( RotationType, Theta1, Theta2, Theta3, TransMat, ErrTxt, ErrStat, ErrMsg ) + + ! Passed Variables: + + REAL(DbKi), INTENT(IN ) :: Theta1 !< The small rotation about X1, (rad). + REAL(DbKi), INTENT(IN ) :: Theta2 !< The small rotation about X2, (rad). + REAL(DbKi), INTENT(IN ) :: Theta3 !< The small rotation about X3, (rad). + REAL(DbKi), INTENT(OUT) :: TransMat (3,3) !< The resulting transformation matrix from X to x, (-). + + INTEGER(IntKi),INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message corresponding to ErrStat + + CHARACTER(*), INTENT(IN) :: RotationType !< The type of rotation; used to inform the user where a large rotation is occuring upon such an event. + CHARACTER(*), INTENT(IN ), OPTIONAL :: ErrTxt !< an additional message to be displayed as a warning (typically the simulation time) + + ! Local Variables: + + REAL(DbKi) :: ComDenom ! = ( Theta1^2 + Theta2^2 + Theta3^2 )*SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + REAL(DbKi), PARAMETER :: LrgAngle = 0.4 ! Threshold for when a small angle becomes large (about 23deg). This comes from: COS(SmllAngle) ~ 1/SQRT( 1 + SmllAngle^2 ) and SIN(SmllAngle) ~ SmllAngle/SQRT( 1 + SmllAngle^2 ) results in ~5% error when SmllAngle = 0.4rad. + REAL(DbKi) :: Theta11 ! = Theta1^2 + REAL(DbKi) :: Theta12S ! = Theta1*Theta2*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta13S ! = Theta1*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta22 ! = Theta2^2 + REAL(DbKi) :: Theta23S ! = Theta2*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(DbKi) :: Theta33 ! = Theta3^2 + REAL(DbKi) :: SqrdSum ! = Theta1^2 + Theta2^2 + Theta3^2 + REAL(DbKi) :: SQRT1SqrdSum ! = SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + + LOGICAL, SAVE :: FrstWarn = .TRUE. ! When .TRUE., indicates that we're on the first warning. + + + ErrStat = ErrID_None + ErrMsg = '' + + ! Display a warning message if at least one angle gets too large in magnitude: + + IF ( ( ( ABS(Theta1) > LrgAngle ) .OR. ( ABS(Theta2) > LrgAngle ) .OR. ( ABS(Theta3) > LrgAngle ) ) .AND. FrstWarn ) THEN + + ErrStat= ErrID_Severe + ErrMsg = 'Small angle assumption violated in SUBROUTINE SmllRotTrans() due to a large '//TRIM(RotationType)//'. '// & + 'The solution may be inaccurate. Simulation continuing, but future warnings from SmllRotTrans() will be suppressed.' + + IF ( PRESENT(ErrTxt) ) THEN + ErrMsg = TRIM(ErrMsg)//NewLine//' Additional debugging message from SUBROUTINE SmllRotTrans(): '//TRIM(ErrTxt) + END IF + + !CALL ProgWarn( TRIM(ErrMsg) ) + + FrstWarn = .FALSE. ! Don't enter here again! + + ENDIF + + + ! Compute some intermediate results: + + Theta11 = Theta1*Theta1 + Theta22 = Theta2*Theta2 + Theta33 = Theta3*Theta3 + + SqrdSum = Theta11 + Theta22 + Theta33 + SQRT1SqrdSum = SQRT( 1.0_DbKi + SqrdSum ) + ComDenom = SqrdSum*SQRT1SqrdSum + + Theta12S = Theta1*Theta2*( SQRT1SqrdSum - 1.0_DbKi ) + Theta13S = Theta1*Theta3*( SQRT1SqrdSum - 1.0_DbKi ) + Theta23S = Theta2*Theta3*( SQRT1SqrdSum - 1.0_DbKi ) + + + ! Define the transformation matrix: + + IF ( ComDenom == 0.0_DbKi ) THEN ! All angles are zero and matrix is ill-conditioned (the matrix is derived assuming that the angles are not zero); return identity + + TransMat(1,:) = (/ 1.0_DbKi, 0.0_DbKi, 0.0_DbKi /) + TransMat(2,:) = (/ 0.0_DbKi, 1.0_DbKi, 0.0_DbKi /) + TransMat(3,:) = (/ 0.0_DbKi, 0.0_DbKi, 1.0_DbKi /) + + ELSE ! At least one angle is nonzero + + TransMat(1,1) = ( Theta11*SQRT1SqrdSum + Theta22 + Theta33 )/ComDenom + TransMat(2,2) = ( Theta11 + Theta22*SQRT1SqrdSum + Theta33 )/ComDenom + TransMat(3,3) = ( Theta11 + Theta22 + Theta33*SQRT1SqrdSum )/ComDenom + TransMat(1,2) = ( Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(2,1) = ( -Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(1,3) = ( -Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(3,1) = ( Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(2,3) = ( Theta1*SqrdSum + Theta23S )/ComDenom + TransMat(3,2) = ( -Theta1*SqrdSum + Theta23S )/ComDenom + + ENDIF + + + RETURN + END SUBROUTINE SmllRotTransDD +!======================================================================= +!> \copydoc nwtc_num::smllrottransd + SUBROUTINE SmllRotTransR( RotationType, Theta1, Theta2, Theta3, TransMat, ErrTxt, ErrStat, ErrMsg ) + + + ! This routine computes the 3x3 transformation matrix, TransMat, + ! to a coordinate system x (with orthogonal axes x1, x2, x3) + ! resulting from three rotations (Theta1, Theta2, Theta3) about the + ! orthogonal axes (X1, X2, X3) of coordinate system X. All angles + ! are assummed to be small, as such, the order of rotations does + ! not matter and Euler angles do not need to be used. This routine + ! is used to compute the transformation matrix (TransMat) between + ! undeflected (X) and deflected (x) coordinate systems. In matrix + ! form: + ! {x1} [TransMat(Theta1, ] {X1} + ! {x2} = [ Theta2, ]*{X2} + ! {x3} [ Theta3 )] {X3} + ! + ! The transformation matrix, TransMat, is the closest orthonormal + ! matrix to the nonorthonormal, but skew-symmetric, Bernoulli-Euler + ! matrix: + ! [ 1.0 Theta3 -Theta2 ] + ! A = [ -Theta3 1.0 Theta1 ] + ! [ Theta2 -Theta1 1.0 ] + ! + ! In the Frobenius Norm sense, the closest orthornormal matrix is: + ! TransMat = U*V^T, + ! + ! where the columns of U contain the eigenvectors of A*A^T and the + ! columns of V contain the eigenvectors of A^T*A (^T = transpose). + ! This result comes directly from the Singular Value Decomposition + ! (SVD) of A = U*S*V^T where S is a diagonal matrix containing the + ! singular values of A, which are SQRT( eigenvalues of A*A^T ) = + ! SQRT( eigenvalues of A^T*A ). + ! + ! The algebraic form of the transformation matrix, as implemented + ! below, was derived symbolically by J. Jonkman by computing U*V^T + ! by hand with verification in Mathematica. + ! + ! This routine is the inverse of GetSmllRotAngs() + + ! Passed Variables: + + REAL(ReKi), INTENT(IN ) :: Theta1 ! The small rotation about X1, (rad). + REAL(ReKi), INTENT(IN ) :: Theta2 ! The small rotation about X2, (rad). + REAL(ReKi), INTENT(IN ) :: Theta3 ! The small rotation about X3, (rad). + REAL(ReKi), INTENT(OUT) :: TransMat (3,3) ! The resulting transformation matrix from X to x, (-). + + INTEGER(IntKi),INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMsg + + CHARACTER(*), INTENT(IN) :: RotationType ! The type of rotation; used to inform the user where a large rotation is occuring upon such an event. + CHARACTER(*), INTENT(IN ), OPTIONAL :: ErrTxt ! an additional message to be displayed as a warning (typically the simulation time) + + ! Local Variables: + + REAL(ReKi) :: ComDenom ! = ( Theta1^2 + Theta2^2 + Theta3^2 )*SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + REAL(ReKi), PARAMETER :: LrgAngle = 0.4 ! Threshold for when a small angle becomes large (about 23deg). This comes from: COS(SmllAngle) ~ 1/SQRT( 1 + SmllAngle^2 ) and SIN(SmllAngle) ~ SmllAngle/SQRT( 1 + SmllAngle^2 ) results in ~5% error when SmllAngle = 0.4rad. + REAL(ReKi) :: Theta11 ! = Theta1^2 + REAL(ReKi) :: Theta12S ! = Theta1*Theta2*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(ReKi) :: Theta13S ! = Theta1*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(ReKi) :: Theta22 ! = Theta2^2 + REAL(ReKi) :: Theta23S ! = Theta2*Theta3*[ SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) - 1.0 ] + REAL(ReKi) :: Theta33 ! = Theta3^2 + REAL(ReKi) :: SqrdSum ! = Theta1^2 + Theta2^2 + Theta3^2 + REAL(ReKi) :: SQRT1SqrdSum ! = SQRT( 1.0 + Theta1^2 + Theta2^2 + Theta3^2 ) + + LOGICAL, SAVE :: FrstWarn = .TRUE. ! When .TRUE., indicates that we're on the first warning. + + + ErrStat = ErrID_None + ErrMsg = '' + + ! Display a warning message if at least one angle gets too large in magnitude: + + IF ( ( ( ABS(Theta1) > LrgAngle ) .OR. ( ABS(Theta2) > LrgAngle ) .OR. ( ABS(Theta3) > LrgAngle ) ) .AND. FrstWarn ) THEN + + ErrStat= ErrID_Severe + ErrMsg = 'Small angle assumption violated in SUBROUTINE SmllRotTrans() due to a large '//TRIM(RotationType)//'. '// & + 'The solution may be inaccurate. Simulation continuing, but future warnings from SmllRotTrans() will be suppressed.' + + IF ( PRESENT(ErrTxt) ) THEN + ErrMsg = TRIM(ErrMsg)//NewLine//' Additional debugging message from SUBROUTINE SmllRotTrans(): '//TRIM(ErrTxt) + END IF + + !CALL ProgWarn( TRIM(ErrMsg) ) + + FrstWarn = .FALSE. ! Don't enter here again! + + ENDIF + + + ! Compute some intermediate results: + + Theta11 = Theta1*Theta1 + Theta22 = Theta2*Theta2 + Theta33 = Theta3*Theta3 + + SqrdSum = Theta11 + Theta22 + Theta33 + SQRT1SqrdSum = SQRT( 1.0_ReKi + SqrdSum ) + ComDenom = SqrdSum*SQRT1SqrdSum + + Theta12S = Theta1*Theta2*( SQRT1SqrdSum - 1.0_Reki ) + Theta13S = Theta1*Theta3*( SQRT1SqrdSum - 1.0_Reki ) + Theta23S = Theta2*Theta3*( SQRT1SqrdSum - 1.0_Reki ) + + + ! Define the transformation matrix: + + IF ( ComDenom == 0.0_ReKi ) THEN ! All angles are zero and matrix is ill-conditioned (the matrix is derived assuming that the angles are not zero); return identity + + TransMat(1,:) = (/ 1.0_ReKi, 0.0_ReKi, 0.0_ReKi /) + TransMat(2,:) = (/ 0.0_ReKi, 1.0_ReKi, 0.0_ReKi /) + TransMat(3,:) = (/ 0.0_ReKi, 0.0_ReKi, 1.0_ReKi /) + + ELSE ! At least one angle is nonzero + + TransMat(1,1) = ( Theta11*SQRT1SqrdSum + Theta22 + Theta33 )/ComDenom + TransMat(2,2) = ( Theta11 + Theta22*SQRT1SqrdSum + Theta33 )/ComDenom + TransMat(3,3) = ( Theta11 + Theta22 + Theta33*SQRT1SqrdSum )/ComDenom + TransMat(1,2) = ( Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(2,1) = ( -Theta3*SqrdSum + Theta12S )/ComDenom + TransMat(1,3) = ( -Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(3,1) = ( Theta2*SqrdSum + Theta13S )/ComDenom + TransMat(2,3) = ( Theta1*SqrdSum + Theta23S )/ComDenom + TransMat(3,2) = ( -Theta1*SqrdSum + Theta23S )/ComDenom + + ENDIF + + + RETURN + END SUBROUTINE SmllRotTransR +!======================================================================= +!> This routine takes two sorted arrays and finds the sorted union of the two. +!! +!! Note: If the same value is found in both arrays, only one is kept. However, if either +!! array as multiple occurances of the same value, the largest multiple will be +!! kept. Duplicates should be eliminated externally if this is not desirable. + SUBROUTINE SortUnion ( Ary1, N1, Ary2, N2, Ary, N ) + + ! Argument declarations: + + INTEGER, INTENT(OUT) :: N !< The length of the output array. + INTEGER, INTENT(IN) :: N1 !< The length of the first input array. + INTEGER, INTENT(IN) :: N2 !< The length of the second input array. + + REAL(ReKi), INTENT(OUT) :: Ary(N1+N2) !< The sorted union. + REAL(ReKi), INTENT(IN) :: Ary1(N1) !< The first list of sorted real numbers. + REAL(ReKi), INTENT(IN) :: Ary2(N2) !< The second list of sorted real numbers. + + + ! Local declarations: + + INTEGER :: I1 ! Index into the first array. + INTEGER :: I2 ! Index into the second array. + + + + I1 = 1 + I2 = 1 + N = 1 + + DO WHILE ( ( I1 <= N1 ) .AND. ( I2 <= N2 ) ) + + IF ( Ary1(I1) < Ary2(I2) ) THEN + Ary(N) = Ary1(I1) + I1 = I1 + 1 + ELSE IF ( Ary1(I1) > Ary2(I2) ) THEN + Ary(N) = Ary2(I2) + I2 = I2 + 1 + ELSE + Ary(N) = Ary1(I1) + I1 = I1 + 1 + I2 = I2 + 1 + END IF + + N = N + 1 + + END DO ! WHILE + + + ! We've reached the end of one array, but we need to add the end + ! of the other array if we haven't reached the end of it yet. + + IF ( I1 <= N1 ) THEN + Ary(N:N+N1-I1) = Ary1(I1:) + N = N+N1-I1 + ELSEIF ( I2 <= N2 ) THEN + Ary(N:N+N2-I2) = Ary2(I2:) + N = N+N2-I2 + ELSE + N = N - 1 + ENDIF + + + RETURN + END SUBROUTINE SortUnion ! ( Ary1, N1, Ary2, N2, Ary, N ) +!======================================================================= +!> This routine calculates the standard deviation of a population contained in Ary. +!! +!! This can be calculated as either\n +!! \f$ \sqrt{ \frac{\sum_{i=1}^N \left(x_i -\bar{x}\right)^2 }{N-1} } \f$ \n +!! or \n +!! \f$ \sqrt{ \frac{\sum_{i=1}^N \left(x_i -\bar{x}\right)^2 }{N} } \f$ if `UseN` is true \n + FUNCTION StdDevFn ( Ary, AryLen, Mean, UseN ) + + ! Function declaration. + + REAL(ReKi) :: StdDevFn !< This function. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: AryLen !< Length of the array. + + REAL(ReKi), INTENT(IN) :: Ary (AryLen) !< Input array. + REAL(ReKi), INTENT(IN) :: Mean !< The previously calculated mean of the array. + LOGICAL, OPTIONAL, INTENT(IN) :: UseN !< Use `N` insted of `N-1` in denomenator + + + ! Local declarations. + + REAL(DbKi) :: Sum ! A temporary sum. + + INTEGER :: I ! The index into the array. + INTEGER :: Denom ! Denominator + + IF(PRESENT(UseN)) THEN + IF (UseN) THEN + Denom = AryLen + ELSE + Denom = AryLen-1 + ENDIF + ELSE + Denom = AryLen-1 + ENDIF + + Sum = 0.0_DbKi + + DO I=1,AryLen + Sum = Sum + ( Ary(I) - Mean )**2 + END DO ! I + + StdDevFn = SQRT( Sum/( Denom ) ) + + + RETURN + END FUNCTION StdDevFn +!======================================================================= +!> This function returns the 3x3 skew-symmetric matrix for cross-product +!! calculation of vector \f$\vec{x}\f$ via matrix multiplication, defined as +!! \f{equation}{ +!! f_{_\times}\left( \vec{x} \right) = +!! \begin{bmatrix} +!! 0 & -x_3 & x_2 \\ +!! x_3 & 0 & -x_1 \\ +!! -x_2 & x_1 & 0 +!! \end{bmatrix} +!! \f} +!> Use SkewSymMat (nwtc_num::skewsymmat) instead of directly calling a specific routine in the generic interface. + FUNCTION SkewSymMatR4 ( x ) RESULT(M) + + ! Function arguments + + REAL(SiKi) :: M(3,3) !< skew-symmetric matrix formed from input vector \f$x\f$ + REAL(SiKi), INTENT(IN) :: x(3) !< input vector \f$x\f$ + + M(1,1) = 0.0_SiKi + M(2,1) = x(3) + M(3,1) = -x(2) + + M(1,2) = -x(3) + M(2,2) = 0.0_SiKi + M(3,2) = x(1) + + M(1,3) = x(2) + M(2,3) = -x(1) + M(3,3) = 0.0_SiKi + + RETURN + END FUNCTION SkewSymMatR4 +!======================================================================= +!> \copydoc nwtc_num::skewsymmatr4 + FUNCTION SkewSymMatR8 ( x ) RESULT(M) + + ! Function arguments + + REAL(R8Ki) :: M(3,3) ! skew-symmetric matrix formed from input vector \f$x\f$ + REAL(R8Ki), INTENT(IN) :: x(3) ! input vector \f$x\f$ + + M(1,1) = 0.0_R8Ki + M(2,1) = x(3) + M(3,1) = -x(2) + + M(1,2) = -x(3) + M(2,2) = 0.0_R8Ki + M(3,2) = x(1) + + M(1,3) = x(2) + M(2,3) = -x(1) + M(3,3) = 0.0_R8Ki + + RETURN + END FUNCTION SkewSymMatR8 +!======================================================================= +!> \copydoc nwtc_num::skewsymmatr4 + FUNCTION SkewSymMatR16 ( x ) RESULT(M) + + ! Function arguments + + REAL(QuKi) :: M(3,3) ! skew-symmetric matrix formed from input vector \f$x\f$ + REAL(QuKi), INTENT(IN) :: x(3) ! input vector \f$x\f$ + + M(1,1) = 0.0_QuKi + M(2,1) = x(3) + M(3,1) = -x(2) + + M(1,2) = -x(3) + M(2,2) = 0.0_QuKi + M(3,2) = x(1) + + M(1,3) = x(2) + M(2,3) = -x(1) + M(3,3) = 0.0_QuKi + + RETURN + END FUNCTION SkewSymMatR16 + +!======================================================================= +!> This routine takes an array of time values such as that returned from +!! CALL DATE_AND_TIME ( Values=TimeAry ) +!! and converts TimeAry to the number of seconds past midnight. + FUNCTION TimeValues2Seconds( TimeAry ) + + ! Passed variables: + INTEGER, INTENT(IN) :: TimeAry (8) ! An array containing the elements of the time + REAL(ReKi) :: TimeValues2Seconds ! Current time in seconds past midnight + + + TimeValues2Seconds = 3600*TimeAry(5) + 60*TimeAry(6) + TimeAry(7) + 0.001_ReKi*TimeAry(8) + + END FUNCTION TimeValues2Seconds +!======================================================================= +!> This function computes the trace of a matrix \f$A \in \mathbb{R}^{m,n}\f$. The +!! trace of \f$A\f$, \f$\mathrm{Tr}\left[ A \right]\f$, is the sum of the diagonal elements of \f$A\f$: +!! \f{equation}{ +!! \mathrm{Tr}\left[ A \right] = \sum_{i=1}^{\min(m,n)} A(i,i) +!! \f} +!! +!! Use trace (nwtc_num::trace) instead of directly calling a specific routine in the generic interface. + FUNCTION traceR4(A) + + REAL(SiKi), INTENT(IN) :: A(:,:) !< matrix A + REAL(SiKi) :: traceR4 !< sum of the diagonal elements of A + + INTEGER(IntKi) :: n ! rows/cols in A + INTEGER(IntKi) :: i ! loop counter + + n = min( SIZE(A,1), SIZE(A,2) ) + + traceR4 = 0.0_ReKi + do i=1,n + traceR4 = traceR4 + A(i,i) + end do + + END FUNCTION traceR4 +!======================================================================= +!> \copydoc nwtc_num::tracer4 + FUNCTION traceR8(A) + + REAL(R8Ki), INTENT(IN) :: A(:,:) !< matrix A + REAL(R8Ki) :: traceR8 !< sum of the diagonal elements of A + + INTEGER(IntKi) :: n ! rows/cols in A + INTEGER(IntKi) :: i ! loop counter + + n = min( SIZE(A,1), SIZE(A,2) ) + + traceR8 = 0.0_ReKi + do i=1,n + traceR8 = traceR8 + A(i,i) + end do + + END FUNCTION traceR8 +!======================================================================= +!> \copydoc nwtc_num::tracer4 + FUNCTION traceR16(A) + + REAL(QuKi), INTENT(IN) :: A(:,:) + REAL(QuKi) :: traceR16 + + INTEGER(IntKi) :: n ! rows/cols in A + INTEGER(IntKi) :: i ! loop counter + + n = min( SIZE(A,1), SIZE(A,2) ) + + traceR16 = 0.0_ReKi + do i=1,n + traceR16 = traceR16 + A(i,i) + end do + + END FUNCTION traceR16 +!======================================================================= +!> This function returns the \f$l_2\f$ (Euclidian) norm of a vector, +!! \f$v = \left(v_1, v_2, \ldots ,v_n\right)\f$. The \f$l_2\f$-norm is defined as +!! \f{equation}{ +!! \lVert v \rVert_2 = \left( \sum_{i=1}^{n} {v_i}^2 \right)^{1/2} +!! \f} \n +!! Use TwoNorm (nwtc_num::twonorm) instead of directly calling a specific routine in the generic interface. + FUNCTION TwoNormR4(v) + + ! fortran 2008 has Norm2() built in + + REAL(SiKi), INTENT(IN) :: v(:) !< vector, v + REAL(SiKi) :: TwoNormR4 !< two-norm of v + + TwoNormR4 = SQRT( DOT_PRODUCT(v, v) ) + + + END FUNCTION +!======================================================================= +!> \copydoc nwtc_num::twonormr4 + FUNCTION TwoNormR8(v) + + ! this function returns the 2-norm of a vector v + ! fortran 2008 has Norm2() built in + + REAL(R8Ki), INTENT(IN) :: v(:) + REAL(R8Ki) :: TwoNormR8 + + TwoNormR8 = SQRT( DOT_PRODUCT(v, v) ) + + + END FUNCTION +!======================================================================= +!> \copydoc nwtc_num::twonormr4 + FUNCTION TwoNormR16(v) + + ! this function returns the 2-norm of a vector v + ! fortran 2008 has Norm2() built in + + REAL(QuKi), INTENT(IN) :: v(:) + REAL(QuKi) :: TwoNormR16 + + TwoNormR16 = SQRT( DOT_PRODUCT(v, v) ) + + + END FUNCTION +!======================================================================= +!> This routine is used to convert Angle to an equivalent value +!! in the range \f$[0, 2\pi)\f$. \n +!! Use Zero2TwoPi (nwtc_num::zero2twopi) instead of directly calling a specific routine in the generic interface. + SUBROUTINE Zero2TwoPiR4 ( Angle ) + + ! Argument declarations: + + REAL(SiKi), INTENT(INOUT) :: Angle !< angle that is input and converted to equivalent in range \f$[0, 2\pi)\f$ + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R4 ) + + + ! Check numerical case where Angle == 2Pi. + + IF ( Angle == TwoPi_R4 ) THEN + Angle = 0.0_ReKi + END IF + + + RETURN + END SUBROUTINE Zero2TwoPiR4 +!======================================================================= +!> \copydoc nwtc_num::zero2twopir4 + SUBROUTINE Zero2TwoPiR8 ( Angle ) + + ! This routine is used to convert Angle to an equivalent value + ! in the range [0, 2*pi). + + + ! Argument declarations: + + REAL(R8Ki), INTENT(INOUT) :: Angle + + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R8 ) + + + ! Check numerical case where Angle == 2Pi. + + IF ( Angle == TwoPi_R8 ) THEN + Angle = 0.0_DbKi + END IF + + + RETURN + END SUBROUTINE Zero2TwoPiR8 +!======================================================================= +!> \copydoc nwtc_num::zero2twopir4 + SUBROUTINE Zero2TwoPiR16 ( Angle ) + + ! This routine is used to convert Angle to an equivalent value + ! in the range [0, 2*pi). + + + ! Argument declarations: + + REAL(QuKi), INTENT(INOUT) :: Angle + + + + ! Get the angle between 0 and 2Pi. + + Angle = MODULO( Angle, TwoPi_R16 ) + + + ! Check numerical case where Angle == 2Pi. + + IF ( Angle == TwoPi_R16 ) THEN + Angle = 0.0_DbKi + END IF + + + RETURN + END SUBROUTINE Zero2TwoPiR16 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R4(Angle1, Angle2, tin, Angle_out, tin_out ) + REAL(SiKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(SiKi), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(SiKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(SiKi) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) + +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R4 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R8(Angle1, Angle2, tin, Angle_out, tin_out) + REAL(R8Ki), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(R8Ki), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(R8Ki), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(R8Ki) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R8 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R16(Angle1, Angle2, tin, Angle_out, tin_out) + REAL(QuKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(QuKi), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(QuKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(QuKi) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R16 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R4R(Angle1, Angle2, tin, Angle_out, tin_out ) + REAL(SiKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(SiKi), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(SiKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(SiKi) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) + +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R4R +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R8R(Angle1, Angle2, tin, Angle_out, tin_out) + REAL(R8Ki), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(R8Ki), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(R8Ki), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(R8Ki) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R8R +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp1_R16R(Angle1, Angle2, tin, Angle_out, tin_out) + REAL(QuKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 + REAL(QuKi), INTENT(IN ) :: Angle2 !< Angle at t2 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(QuKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 1 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(QuKi) :: Angle2_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + ! if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: size(t) must equal 2.' + ! RETURN + ! end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp1: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + call AddOrSub2Pi( Angle1, Angle2_mod ) + + Angle_out = Angle1 + (Angle2_mod - Angle1) * t_out / t(2) +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp1_R16R +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R4(Angle1, Angle2, Angle3, tin, Angle_out, tin_out ) + REAL(SiKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(SiKi), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(SiKi), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(SiKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(SiKi) :: Angle2_mod + REAL(SiKi) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out + +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R4 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R8(Angle1, Angle2, Angle3, tin, Angle_out, tin_out) + REAL(R8Ki), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(R8Ki), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(R8Ki), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(R8Ki), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(R8Ki) :: Angle2_mod + REAL(R8Ki) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! some error checking: + + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R8 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R16(Angle1, Angle2, Angle3, tin, Angle_out, tin_out ) + REAL(QuKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(QuKi), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(QuKi), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(DbKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(QuKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(QuKi) :: Angle2_mod + REAL(QuKi) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! some error checking: + + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R16 +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R4R(Angle1, Angle2, Angle3, tin, Angle_out, tin_out ) + REAL(SiKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(SiKi), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(SiKi), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(SiKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(SiKi) :: Angle2_mod + REAL(SiKi) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! ! some error checking: + ! + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out + +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R4R +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R8R(Angle1, Angle2, Angle3, tin, Angle_out, tin_out) + REAL(R8Ki), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(R8Ki), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(R8Ki), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(R8Ki), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(R8Ki) :: Angle2_mod + REAL(R8Ki) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! some error checking: + + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R8R +!======================================================================= + !< This routine extrapolates or interpolates between angles + SUBROUTINE Angles_ExtrapInterp2_R16R(Angle1, Angle2, Angle3, tin, Angle_out, tin_out ) + REAL(QuKi), INTENT(IN ) :: Angle1 !< Angle at t1 > t2 > t3 + REAL(QuKi), INTENT(IN ) :: Angle2 !< Angle at t2 > t3 + REAL(QuKi), INTENT(IN ) :: Angle3 !< Angle at t3 + REAL(ReKi), INTENT(IN ) :: tin(:) !< Times associated with the inputs + REAL(QuKi), INTENT(INOUT) :: Angle_out !< Input at tin_out + REAL(ReKi), INTENT(IN ) :: tin_out !< time to be extrap/interp'd to + + ! local variables + INTEGER(IntKi), parameter :: order = 2 ! order of polynomial fit (max 2) + REAL(ReKi) :: t(SIZE(tin)) ! Times associated with the inputs + REAL(ReKi) :: t_out ! Time to which to be extrap/interpd + + REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation + REAL(QuKi) :: Angle2_mod + REAL(QuKi) :: Angle3_mod + + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + ! some error checking: + + !if ( size(t) .ne. order+1) then + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: size(t) must equal 3.' + ! RETURN + !end if + ! + !IF ( EqualRealNos( t(1), t(2) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(2) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(2), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(2) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + !IF ( EqualRealNos( t(1), t(3) ) ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Angles_ExtrapInterp2: t(1) must not equal t(3) to avoid a division-by-zero error.' + ! RETURN + !END IF + + Angle2_mod = Angle2 + Angle3_mod = Angle3 + call AddOrSub2Pi( Angle1, Angle2_mod ) + call AddOrSub2Pi( Angle2_mod, Angle3_mod ) + + scaleFactor = t_out / ( t(2) * t(3) * (t(2) - t(3)) ) + + Angle_out = Angle1 & + + ( t(3)**2 * (Angle1 - Angle2_mod) + t(2)**2*(-Angle1 + Angle3_mod) ) * scaleFactor & + + ( (t(2)-t(3))*Angle1 + t(3)*Angle2_mod - t(2)*Angle3_mod ) *scaleFactor * t_out +! call Zero2TwoPi(Angle_out) +! call MPi2Pi(Angle_out) + + END SUBROUTINE Angles_ExtrapInterp2_R16R +!======================================================================= +END MODULE NWTC_Num diff --git a/OpenFAST/modules/nwtc-library/src/NWTC_RandomNumber.f90 b/OpenFAST/modules/nwtc-library/src/NWTC_RandomNumber.f90 new file mode 100644 index 000000000..ed8b6648f --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NWTC_RandomNumber.f90 @@ -0,0 +1,190 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2020 National Renewable Energy Laboratory +! +! This file is part of NWTC 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 NWTC_RandomNumber + +USE Ran_Lux_Mod +USE NWTC_Library_Types +USE NWTC_IO + +IMPLICIT NONE + +INTEGER(IntKi), PARAMETER :: pRNG_RANLUX = 1 +INTEGER(IntKi), PARAMETER :: pRNG_INTRINSIC = 2 + +INTEGER, PARAMETER :: LuxLevel = 3 ! Luxury Level for RanLux RNG + +!> \copydoc nwtc_randomnumber::uniformrandomnumbersr4 +INTERFACE UniformRandomNumbers +MODULE PROCEDURE UniformRandomNumbersR4 ! 4-byte reals +MODULE PROCEDURE UniformRandomNumbersR8 ! 8-byte reals +MODULE PROCEDURE UniformRandomNumbersR16 ! 16-byte reals +END INTERFACE + +CONTAINS + +SUBROUTINE RandNum_Init(p, ErrStat, ErrMsg ) + + ! Initialize the Random Number Generators + + IMPLICIT NONE + + TYPE(NWTC_RandomNumber_ParameterType), INTENT(IN ) :: p ! PARAMETERs for random number generation + INTEGER(IntKi) , INTENT(OUT) :: ErrStat ! allocation status + CHARACTER(*) , INTENT(OUT) :: ErrMsg ! error message + + INTEGER :: I ! loop counter + INTEGER(IntKi), ALLOCATABLE :: NextSeed(:) ! The array that holds the next random seed for each component + INTEGER :: NumSeeds ! number of seeds in the intrinsic random number generator + + ErrStat = ErrID_None + ErrMsg = "" + + IF (p%pRNG == pRNG_RANLUX) THEN + + CALL RLuxGo ( LuxLevel, ABS( p%RandSeed(1) ), 0, 0 ) + + IF (.NOT. ALLOCATED( NextSeed ) ) THEN + CALL AllocAry( NextSeed, 2, 'nextSeed', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + ELSEIF (p%pRNG == pRNG_INTRINSIC) THEN + + ! determine the number of seeds necessary (gfortran needs 8 or 12 seeds, not just 2) + + CALL RANDOM_SEED ( SIZE = NumSeeds ) + + IF ( NumSeeds /= 2 ) THEN + CALL ProgWarn( ' The random number generator in use differs from the original code provided by NREL. This pRNG uses ' & + //trim(Int2LStr(NumSeeds))//' seeds instead of the 2 in the input file.') + END IF + + IF ( .NOT. ALLOCATED( NextSeed ) ) THEN + CALL AllocAry( NextSeed, NumSeeds, 'nextSeed', ErrSTat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + ! We'll just populate this with odd seeds = Seed(1) and even seeds = Seed(2) + DO I = 1, NumSeeds,2 + NextSeed(I) = p%RandSeed(1) + END DO + DO I = 2, NumSeeds,2 + NextSeed(I) = p%RandSeed(2) + END DO + + CALL RANDOM_SEED( PUT=NextSeed ) + + ELSE + + ! Invalid pRNG requested + ErrMsg = "Invalid pRNG requested." + ErrStat = ErrID_Fatal + RETURN + + END IF + +END SUBROUTINE RandNum_Init + +!======================================================================= +!> This subroutine produces uniformly distributed random numbers, based on +!! the pRNG requested. This routine assumes that the random number +!! generator has been initialized earlier in the main program. +SUBROUTINE UniformRandomNumbersR4( pRNG_Type, RandomNumbers ) + + IMPLICIT NONE + + INTEGER, INTENT(IN ) :: pRNG_Type + REAL(SiKi), INTENT( OUT), DIMENSION(:) :: RandomNumbers + + REAL(ReKi), ALLOCATABLE :: RN(:) + + IF ( pRNG_Type == pRNG_INTRINSIC ) THEN + + ! The Fortran intrinsic has an interface for various floating + ! point types, so pass the variable directly + CALL RANDOM_NUMBER( RandomNumbers ) + + ELSEIF ( pRNG_Type == pRNG_RANLUX ) THEN + + ! RanLux, as implemented, uses ReKi, so cast the return value as needed + ALLOCATE( RN( SIZE(RandomNumbers) ) ) + CALL RanLux ( RN ) + RandomNumbers = REAL(RN, KIND=SiKi) + + END IF + +END SUBROUTINE UniformRandomNumbersR4 +!======================================================================= +!> \copydoc nwtc_randomnumber::uniformrandomnumbersr4 +SUBROUTINE UniformRandomNumbersR8( pRNG_Type, RandomNumbers ) + + IMPLICIT NONE + + INTEGER, INTENT(IN ) :: pRNG_Type + REAL(R8Ki), INTENT( OUT), DIMENSION(:) :: RandomNumbers + + REAL(ReKi), ALLOCATABLE :: RN(:) + + IF ( pRNG_Type == pRNG_INTRINSIC ) THEN + + ! The Fortran intrinsic has an interface for various floating + ! point types, so pass the variable directly + CALL RANDOM_NUMBER( RandomNumbers ) + + ELSEIF ( pRNG_Type == pRNG_RANLUX ) THEN + + ! RanLux, as implemented, uses ReKi, so cast the return value as needed + ALLOCATE( RN( SIZE(RandomNumbers) ) ) + CALL RanLux ( RN ) + RandomNumbers = REAL(RN, KIND=R8Ki) + + END IF + +END SUBROUTINE UniformRandomNumbersR8 +!======================================================================= +!> \copydoc nwtc_randomnumber::uniformrandomnumbersr4 +SUBROUTINE UniformRandomNumbersR16( pRNG_Type, RandomNumbers ) + + IMPLICIT NONE + + INTEGER, INTENT(IN ) :: pRNG_Type + REAL(QuKi), INTENT( OUT), DIMENSION(:) :: RandomNumbers + + REAL(ReKi), ALLOCATABLE :: RN(:) + + IF ( pRNG_Type == pRNG_INTRINSIC ) THEN + + ! The Fortran intrinsic has an interface for various floating + ! point types, so pass the variable directly + CALL RANDOM_NUMBER( RandomNumbers ) + + ELSEIF ( pRNG_Type == pRNG_RANLUX ) THEN + + ! RanLux, as implemented, uses ReKi, so cast the return value as needed + ALLOCATE( RN( SIZE(RandomNumbers) ) ) + CALL RanLux ( RN ) + RandomNumbers = REAL(RN, KIND=QuKi) + + END IF + +END SUBROUTINE UniformRandomNumbersR16 + +END MODULE diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/NWTC_FitPack.f90 b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/NWTC_FitPack.f90 new file mode 100644 index 000000000..588cc0026 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/NWTC_FitPack.f90 @@ -0,0 +1,721 @@ +!********************************************************************************************************************************** +! Copyright (C) 2014 National Renewable Energy Laboratory +! +! This code provides a wrapper for Dierckx's FitPack routines currently used at the NWTC (mainly codes in the FAST framework). +! +!********************************************************************************************************************************** +MODULE NWTC_FitPack + + + ! This Fortran module consists of single-precision wrappers for some of Paul Dierckx's FitPack routines. + + + USE NWTC_Library +! USE, INTRINSIC :: ISO_C_Binding, only: C_FLOAT, C_DOUBLE ! this is included in NWTC_Library + + ! Notes: + + ! Your project must include the following files: + ! From the NWTC Subroutine Library: + ! SingPrec.f90 [from NWTC Library] + ! Sys*.f90 [from NWTC Library] + ! NWTC_Base.f90 [from NWTC Library] + ! fitpack library (preferably a binary, but available in source form from http://www.netlib.org/dierckx/, too). + ! This wrapper file: + ! NWTC_FitPack.f90 + + IMPLICIT NONE + + INTERFACE FitPack_BispevLite ! Computes bicubic splines of a rectangular grid of data. +! MODULE PROCEDURE FitPack_dBispevLite ! Dummy routine that prints an error message if double precision is used. + MODULE PROCEDURE FitPack_sBispevLite ! Single-precision version. + END INTERFACE + + INTERFACE FitPack_RegridLite ! Computes bicubic splines of a rectangular grid of data. + MODULE PROCEDURE FitPack_dRegridLite ! Dummy routine that prints an error message if double precision is used. + MODULE PROCEDURE FitPack_sRegridLite ! Single-precision version. + END INTERFACE + +! INTERFACE FitPack_surfit ! Fits a 2D surface to a randomly located set of points. +! MODULE PROCEDURE FitPack_dsurfit +! MODULE PROCEDURE FitPack_ssurfit +! END INTERFACE + + +CONTAINS + +!======================================================================= + SUBROUTINE FitPack_sBispevLite ( NumX, X, NumY, Y, SCsize, SplCoef, ErrStat, ErrMsg ) +! subroutine bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, +! * iwrk,kwrk,ier) + + + ! This Fortran routine is a wrapper for Paul Dierckx's FitPack bispev.f routine. + ! This works only with single-precision values (SiKi). + ! It *may* assume that the length of REALs and INTEGERs are the same. + ! Hard-coded assumptions: + ! The calling routine passes it a rectangular grid of data stored as a vector. + ! You can blame Marshall Buhl for this mess. + + ! This routine calls bispev and bispev uses the following routines either directly or indirectly: + ! fpbisp and fpbspl. + ! + ! bispev + ! fpbisp + ! fpbspl + + USE NWTC_Base ! We only need the precision and error level constants + + IMPLICIT NONE + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: NumX ! The length of the X array. + INTEGER, INTENT(IN) :: NumY ! The length of the Y array. + INTEGER, INTENT(IN) :: SCsize ! The length of the SplCoef array. + + REAL(SiKi), INTENT(OUT) :: SplCoef(SCsize) ! The resulting spline coefficients. + REAL(SiKi), INTENT(IN) :: X (NumX) ! X coordinates for the Elev array. + REAL(SiKi), INTENT(IN) :: Y (NumY) ! Y coordinates for the Elev array. + + INTEGER, INTENT(OUT) :: ErrStat ! The error status to be returned to the calling program. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. + + + ! Local declarations. + +!NOTE: For the surface elevation, regrid() needs a rank-1 array with the Y values varying most rapidly. It would be best to make that for AoA and use X for Control, which there will most often be only one value. + + REAL(SiKi) :: ResidSq ! The sum of squared residuals of the spline approximation + REAL(SiKi), ALLOCATABLE :: ReWorkAry (:) ! A working array of type REAL. +!MLB: Should SmthFact be a user-specified parameter? It almost seems like it would be dependent on airfoils. Andrew used 0.1 for lift and 0.2 for drag because of the relative sizes of the curves. +! We decided that for the first cut, force it to zero (no smoothing), but maybe eventually making it user-specified. + REAL(SiKi), PARAMETER :: SmthFact = 0.0_SiKi ! The non-negative smoothing factor. Hard-coded to 0 for no smoothing. + REAL(SiKi), ALLOCATABLE :: Xknots (:) ! The array of knots in the X direction. + REAL(SiKi), ALLOCATABLE :: Yknots (:) ! The array of knots in the Y direction. + + INTEGER, PARAMETER :: CubicSpl = 3 ! The degree of the cubic-spline polynomials. + INTEGER(IntKi) :: ErrStatLcl ! The local version of the error status. + INTEGER(IntKi) :: I ! A DO counter. + INTEGER(IntKi), ALLOCATABLE :: InWorkAry (:) ! A working array of type INTEGER. + INTEGER(IntKi) :: LenIWrkAry ! The size of InWorkAry. + INTEGER(IntKi) :: LenRWrkAry ! The size of ReWorkAry. + INTEGER(IntKi) :: MaxXknots ! The maximum number of knots in the X direction. + INTEGER(IntKi) :: MaxYknots ! The maximum number of knots in the Y direction. + INTEGER(IntKi) :: NumXknots ! The number of knots in the X direction. + INTEGER(IntKi) :: NumYknots ! The number of knots in the Y direction. +!mlb: testing INTEGER(IntKi), PARAMETER :: Option = -1 ! The degree of the spline polynomials. + INTEGER(IntKi), PARAMETER :: Option = 1 ! The degree of the spline polynomials. + INTEGER :: SplDegX ! The degree of the spline polynomials in the X direction. + INTEGER :: SplDegY ! The degree of the spline polynomials in the Y direction. + + + + ! Check to see if this program was compiled with non-standard REALs (not four bytes). + ! We do this because the FitPack routines *may* require the word length of REALs and INTEGERs to be the same. + + IF ( KIND( 1.0 ) /= SiKi ) THEN + CALL ExitThisRoutine( ErrID_SEVERE, ' The FitPack routines have not been tested with REALs that are not four bytes.' ) + RETURN + END IF + + SplCoef = 0.0 + + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Deallocate the work arrays. + + IF ( ALLOCATED( ReWorkAry ) ) DEALLOCATE( ReWorkAry ) + IF ( ALLOCATED( InWorkAry ) ) DEALLOCATE( InWorkAry ) + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE FitPack_sBispevLite +!======================================================================= + SUBROUTINE FitPack_dRegridLite ( NumX, X, NumY, Y, ElSize, Elev, SCsize, SplCoef, ErrStat, ErrMsg ) + + + ! This Fortran routine is a wrapper for Paul Dierckx's FitPack regrid.f routine. + ! This works only with single-precision values (SiKi). + ! It *may* assume that the length of REALs and INTEGERs are the same. + ! Hard-coded assumptions: + ! The calling routine passes it a rectangular grid of data. + ! The knots will be at the original X,Y points (Option = -1). + ! It will generate cubic splines in both directions. + ! No smoothing will be done. + ! You can blame Marshall Buhl for this mess. + + ! This routine calls regrid and regrid uses the following routines either directly or indirectly: + ! fpback, fpbspl, fpchec, fpdisc, fpgivs, fpgrre, fpknot, fpregr, and fprota. + ! + ! regrid + ! fpchec + ! fpregr + ! fpgrre + ! fpbspl + ! fpdisc + ! fpgivs + ! fprota + ! fpback + ! fpknot + + USE NWTC_Base ! We only need the precision and error level constants + + IMPLICIT NONE + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: ElSize ! The length of the Elev array. + INTEGER, INTENT(IN) :: NumX ! The length of the X array. + INTEGER, INTENT(IN) :: NumY ! The length of the Y array. + INTEGER, INTENT(IN) :: SCsize ! The length of the SplCoef array. + + REAL(R8Ki), INTENT(IN) :: Elev (ElSize) ! The "elevations" for the x and y coordinates for which spline coefficients will be computed. + REAL(R8Ki), INTENT(OUT) :: SplCoef(SCsize) ! The resulting spline coefficients. + REAL(R8Ki), INTENT(IN) :: X (NumX) ! X coordinates for the Elev array. + REAL(R8Ki), INTENT(IN) :: Y (NumY) ! Y coordinates for the Elev array. + + INTEGER, INTENT(OUT) :: ErrStat ! The error status to be returned to the calling program. + INTEGER, PARAMETER :: SplDeg = 3 ! The degree of the spline polynomials. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. +!NOTE: For the surface elevation, regrid() needs a rank-1 array with the Y values varying most rapidly. It would be best to make that for AoA and use X for Control, which there will most often be only one value. + + +! ! Local declarations. +! +! REAL(DbKi) :: ResidSq ! The sum of squared residuals of the spline approximation +! REAL(DbKi), ALLOCATABLE :: ReWorkAry (:) ! A working array of type REAL. +!!MLB: Should SmthFact be a user-specified parameter? It almost seems like it would be dependent on airfoils. Andrew used 0.1 for lift and 0.2 for drag because of the relative sizes of the curves. +!! We decided that for the first cut, force it to zero (no smoothing), but maybe eventually making it user-specified. +! REAL(DbKi), PARAMETER :: SmthFact = 0.0_SiKi ! The non-negative smoothing factor. Hard-coded to 0 for no smoothing. +! +! INTEGER(IntKi) :: ErrStatLcl ! The local version of the error status. +! INTEGER(IntKi), ALLOCATABLE :: InWorkAry (:) ! A working array of type INTEGER. +! INTEGER(IntKi) :: LenIWrkAry ! The size of InWorkAry. +! INTEGER(IntKi) :: LenRWrkAry ! The size of ReWorkAry. +! INTEGER(IntKi) :: LenSpCoAry ! The size of SplCoef. +! INTEGER(IntKi) :: MaxXknots ! The maximum number of knots in the X direction. +! INTEGER(IntKi) :: MaxYknots ! The maximum number of knots in the Y direction. +! INTEGER(IntKi), PARAMETER :: Option = -1 ! The degree of the spline polynomials. +! +! + ! This routine is just a dummy. + + SplCoef(:) = 0.0_R8Ki + + CALL ExitThisRoutine ( ErrID_Fatal, ' Error >> FitPack_RegridLite is not available for 8-byte real precision.' ) +! +! ! Check to see if this program was compiled with non-standard REALs (not four bytes). +! ! We do this because the FitPack routines *may* require the word length of REALs and INTEGERs to be the same. +! +! IF ( KIND( 1.0 ) /= SiKi ) THEN +! CALL ExitThisRoutine( ErrID_SEVERE, ' The FitPack routines have not been tested with REALs that are not four bytes.' ) +! END IF +! +! +! ! Let's set some array limits. +! +! MaxXknots = NumX + SplDeg + 1 +! MaxYknots = NumY + SplDeg + 1 +! LenIWrkAry = 3 + NumX + NumY + MaxXknots + MaxYknots +! LenRWrkAry = 4 + MaxXknots*( NumY + 2*SplDeg + 5 ) + MaxYknots*( 2*SplDeg + 5 ) + NumX*( SplDeg + 1 ) & +! + NumY*( SplDeg + 1 ) + MAX( NumY, MaxXknots ) +! LenSpCoAry = ( MaxXknots - SplDeg - 1 )*( MaxYknots - SplDeg - 1 ) +! +! +! ! Allocate the arrays. +! +! CALL AllocAry ( SplCoef, LenSpCoAry, "array for spline coefficients for airfoil data" & +! , ErrStatLcl, ErrMsg ) +! IF ( ErrStatLcl /= 0 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) +! END IF +! +! CALL AllocAry ( InWorkAry, LenIWrkAry, 'the INTEGER work array for regrid', ErrStatLcL, ErrMsg ) +! IF ( ErrStatLcl /= 0 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) +! END IF +! +! CALL AllocAry ( ReWorkAry, LenRWrkAry, 'the REAL work array for regrid', ErrStatLcL, ErrMsg ) +! IF ( ErrStatLcl /= 0 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) +! END IF +! +! +! ! Compute the spline coefficients. +! +! CALL regrid ( iopt=Option, mx=NumX, x=X, my=NumY, y=Y, z=Elev, xb=X(1), xe=X(NumX), yb=Y(1), ye=Y(NumY), kx=SplDeg & +! , ky=SplDeg, s=SmthFact, nxest=MaxXknots, nyest=MaxYknots, nx=NumX, tx=X, ny=NumY, ty=Y, c=SplCoef & +! , fp=ResidSq, wrk=ReWorkAry, lwrk=LenRWrkAry, iwrk=InWorkAry, kwrk=LenIWrkAry, ier=ErrStatLcl ) +! +! +! ! Check for errors. +! +! IF ( ErrStatLcl == 1 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, 'regrid: The required storage space exceeds the available storage space, as ' & +! //'specified by the parameters nxest and nyest.' ) +! ELSEIF ( ErrStatLcl == 2 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, 'regrid: A theoretically impossible result was found during the iteration process ' & +! //'for finding a smoothing spline.' ) +! ELSEIF ( ErrStatLcl == 3 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, 'regrid: The maximal number of iterations maxit (set to 20 by the program) allowed ' & +! //'for finding a smoothing spline with fp=s has been reached.' ) +! ELSEIF ( ErrStatLcl == 10 ) THEN +! CALL ExitThisRoutine( ErrID_FATAL, 'regrid: One or more input conditions were invalid.' ) +! ELSE +! CALL ExitThisRoutine( ErrID_None, '' ) +! END IF + + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Deallocate the work arrays. + +! IF ( ALLOCATED( ReWorkAry ) ) DEALLOCATE( ReWorkAry ) +! IF ( ALLOCATED( InWorkAry ) ) DEALLOCATE( InWorkAry ) + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE FitPack_dRegridLite +!======================================================================= + SUBROUTINE FitPack_sRegridLite ( NumX , X & + , NumY , Y & + , ElSize , Elev & + , NumXknots, Xknots & + , NumYknots, Yknots & + , SCsize , SplCoef & + , ErrStat , ErrMsg ) + + + ! This Fortran routine is a wrapper for Paul Dierckx's FitPack regrid.f routine. + ! This works only with single-precision values (SiKi). + ! It *may* assume that the length of REALs and INTEGERs are the same. + ! Hard-coded assumptions: + ! The calling routine passes it a rectangular grid of data stored as a vector. + ! The knots will be at the original X,Y points (Option = -1). MLB + ! It will generate cubic splines in both directions unless there are fewer than four points. + ! If there are less than four points in a given direction, the spline degree will be NumPts-1. + ! No smoothing will be done. + ! You can blame Marshall Buhl for this mess. + + ! This routine calls regrid and regrid uses the following routines either directly or indirectly: + ! fpback, fpbspl, fpchec, fpdisc, fpgivs, fpgrre, fpknot, fpregr, and fprota. + ! + ! regrid + ! fpchec + ! fpregr + ! fpgrre + ! fpbspl + ! fpdisc + ! fpgivs + ! fprota + ! fpback + ! fpknot + + USE NWTC_Base ! We only need the precision and error level constants + + IMPLICIT NONE + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: ElSize ! The length of the Elev array. + INTEGER, INTENT(IN) :: NumX ! The length of the X array. + INTEGER, INTENT(IN) :: NumY ! The length of the Y array. + INTEGER, INTENT(IN) :: SCsize ! The length of the SplCoef array. + + REAL(ReKi), INTENT(IN) :: Elev (ElSize) ! The "elevations" for the x and y coordinates for which spline coefficients will be computed. + REAL(ReKi), INTENT(OUT) :: SplCoef(SCsize) ! The resulting spline coefficients. + REAL(ReKi), INTENT(IN) :: X (NumX) ! X coordinates for the Elev array. + REAL(ReKi), INTENT(IN) :: Y (NumY) ! Y coordinates for the Elev array. + REAL(ReKi), INTENT(OUT), ALLOCATABLE :: Xknots (:) ! The computed knots in the X direction. + REAL(ReKi), INTENT(OUT), ALLOCATABLE :: Yknots (:) ! The computed knots in the Y direction. + + INTEGER, INTENT(OUT) :: ErrStat ! The error status to be returned to the calling program. + INTEGER, INTENT(OUT) :: NumXknots ! The number of knots in the X direction. + INTEGER, INTENT(OUT) :: NumYknots ! The number of knots in the Y direction. + + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. + + + ! Local declarations. + +!NOTE: For the surface elevation, regrid() needs a rank-1 array with the Y values varying most rapidly. It would be best to make that for AoA and use X for Control, which there will most often be only one value. + + REAL(ReKi) :: ResidSq ! The sum of squared residuals of the spline approximation + REAL(ReKi), ALLOCATABLE :: ReWorkAry (:) ! A working array of type REAL. +!MLB: Should SmthFact be a user-specified parameter? It almost seems like it would be dependent on airfoils. Andrew used 0.1 for lift and 0.2 for drag because of the relative sizes of the curves. +! We decided that for the first cut, force it to zero (no smoothing), but maybe eventually making it user-specified. + REAL(ReKi), PARAMETER :: SmthFact = 0.0_ReKi ! The non-negative smoothing factor. Hard-coded to 0 for no smoothing. + + INTEGER, PARAMETER :: CubicSpl = 3 ! The degree of the cubic-spline polynomials. + INTEGER(IntKi) :: ErrStatLcl ! The local version of the error status. + INTEGER(IntKi) :: I ! A DO counter. + INTEGER(IntKi), ALLOCATABLE :: InWorkAry (:) ! A working array of type INTEGER. + INTEGER(IntKi) :: LenIWrkAry ! The size of InWorkAry. + INTEGER(IntKi) :: LenRWrkAry ! The size of ReWorkAry. + INTEGER(IntKi) :: MaxXknots ! The maximum number of knots in the X direction. + INTEGER(IntKi) :: MaxYknots ! The maximum number of knots in the Y direction. +!mlb: testing INTEGER(IntKi), PARAMETER :: Option = -1 ! The degree of the spline polynomials. + INTEGER(IntKi), PARAMETER :: Option = 1 ! The degree of the spline polynomials. + INTEGER :: SplDegX ! The degree of the spline polynomials in the X direction. + INTEGER :: SplDegY ! The degree of the spline polynomials in the Y direction. + + + + ! Check to see if this program was compiled with non-standard REALs (not four bytes). + ! We do this because the FitPack routines *may* require the word length of REALs and INTEGERs to be the same. + + !IF ( KIND( 1.0 ) /= SiKi ) THEN + ! CALL ExitThisRoutine( ErrID_SEVERE, ' The FitPack routines have not been tested with REALs that are not four bytes.' ) + ! RETURN + !END IF + + + ! Determine what degree of polynomial to use for each direction. + + SplDegX = MIN( CubicSpl, NumX-1 ) + SplDegY = MIN( CubicSpl, NumY-1 ) + + + ! Let's set some array limits. + + MaxXknots = NumX + SplDegX + 1 + MaxYknots = NumY + SplDegY + 1 +! MaxXknots = NumX + 2*( SplDegX + 1 ) +! MaxYknots = NumY + 2*( SplDegY + 1 ) +! NumXknots = NumX +! NumYknots = NumY + LenIWrkAry = 3 + NumX + NumY + MaxXknots + MaxYknots + LenRWrkAry = 4 + MaxXknots*( NumY + 2*SplDegX + 5 ) + MaxYknots*( 2*SplDegY + 5 ) + NumX*( SplDegX + 1 ) & + + NumY*( SplDegY + 1 ) + MAX( NumY, MaxXknots ) + + + ! Allocate the working arrays. + + CALL AllocAry ( Xknots, MaxXknots, 'the array of knots in the X direction for regrid', ErrStatLcL, ErrMsg ) + IF ( ErrStatLcl /= 0 ) THEN + CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) + RETURN + END IF + + CALL AllocAry ( Yknots, MaxYknots, 'the array of knots in the Y direction for regrid', ErrStatLcL, ErrMsg ) + IF ( ErrStatLcl /= 0 ) THEN + CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) + RETURN + END IF + + CALL AllocAry ( InWorkAry, LenIWrkAry, 'the INTEGER work array for regrid', ErrStatLcL, ErrMsg ) + IF ( ErrStatLcl /= 0 ) THEN + CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) + RETURN + END IF + + CALL AllocAry ( ReWorkAry, LenRWrkAry, 'the REAL work array for regrid', ErrStatLcL, ErrMsg ) + IF ( ErrStatLcl /= 0 ) THEN + CALL ExitThisRoutine( ErrID_FATAL, ErrMsg ) + RETURN + END IF + + + ! Prefill the arrays of knots. + +! DO I=1,NumXknots +! Xknots(I+SplDegX+1) = X(I) +! END DO ! I +! +! DO I=1,NumYknots +! Yknots(I+SplDegY+1) = Y(I) +! END DO ! I + + + ! Compute the spline coefficients. + + !CALL regrid ( iopt=Option, mx=NumX, x=X, my=NumY, y=Y, z=Elev, xb=X(1), xe=X(NumX), yb=Y(1), ye=Y(NumY), kx=SplDegX & + ! , ky=SplDegY, s=SmthFact, nxest=MaxXknots, nyest=MaxYknots, nx=NumXknots, tx=Xknots, ny=NumYknots, ty=Yknots & + ! , c=SplCoef, fp=ResidSq, wrk=ReWorkAry, lwrk=LenRWrkAry, iwrk=InWorkAry, kwrk=LenIWrkAry, ier=ErrStatLcl ) + CALL regrid ( Option, NumX, X, NumY, Y, Elev, X(1), X(NumX), Y(1), Y(NumY), SplDegX & + , SplDegY, SmthFact, MaxXknots, MaxYknots, NumXknots, Xknots, NumYknots, Yknots & + , SplCoef, ResidSq, ReWorkAry, LenRWrkAry, InWorkAry, LenIWrkAry, ErrStatLcl ) + + + ! Check for errors. + + IF ( ErrStatLcl == 1 ) THEN + CALL ExitThisRoutine( ErrID_FATAL & + , 'Error >> regrid: The required storage space exceeds the available storage space, as ' & + //'specified by the parameters MaxXknots and MaxYknots.' ) + ELSEIF ( ErrStatLcl == 2 ) THEN + CALL ExitThisRoutine( ErrID_FATAL & + , 'Error >> regrid: A theoretically impossible result was found during the iteration process ' & + //'for finding a smoothing spline.' ) + ELSEIF ( ErrStatLcl == 3 ) THEN + CALL ExitThisRoutine( ErrID_FATAL & + , 'Error >> regrid: The maximal number of iterations maxit (set to 20 by the program) allowed ' & + //'for finding a smoothing spline with ResidSq=SmthFact has been reached.' ) + ELSEIF ( ErrStatLcl == 10 ) THEN + CALL ExitThisRoutine( ErrID_FATAL & + , 'Error >> regrid: One or more input conditions were invalid.' ) + ELSE + CALL ExitThisRoutine( ErrID_None, '' ) + END IF + + + RETURN + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up the parent routine before exiting. + + + ! Argument declarations. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Local declarations. + + LOGICAL :: IsOpen ! A flag that indicates if the input unit is still open. + + + ! Deallocate the work arrays. + + IF ( ALLOCATED( ReWorkAry ) ) DEALLOCATE( ReWorkAry ) + IF ( ALLOCATED( InWorkAry ) ) DEALLOCATE( InWorkAry ) + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + + RETURN + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + + END SUBROUTINE FitPack_sRegridLite +!======================================================================= +! SUBROUTINE FitPack_dsurfit ( Option, NumPts, X, Y, Z, Wts, Xbeg, Xend, Ybeg, Yend, SmthFact, nxest,nyest, nmax, Eps, Tx, Ty, nxest, nyest, quiet, ErrStat, ErrMsg ) +! subroutine surfit(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest, +! * nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) +! +! +! ! This Fortran routine is a wrapper for Paul Dierckx's FitPack surfit.f routine. +! ! Effort on this routine was abandoned in favor of requiring users to specify rectangular grids of aerodynamic coefficients. +! +! ! Find a bivariate B-spline representation of a surface. +! +! ! Given a set of data points (x[i], y[i], z[i]) representing a surface +! ! z=f(x,y), compute a B-spline representation of the surface. Based on +! ! the routine SURFIT from FITPACK. +! +! ! If Task=0, find knots in X and Y and coefficients for a given smoothing factor, S. [default] +! ! If Task=1, find knots and coefficients for another value of the smoothing factor, S. bisplrep must have been previously called with task=0 or task=1. +! ! If Task=-1, find coefficients for a given set of knots Tx, Ty. +! +! +! USE NWTC_Base ! We only need the precision and error level constants +! +! IMPLICIT NONE +! +! +! ! Argument declarations: +! +! INTEGER(IntKi), INTENT(IN) :: NumPts ! The length of the W, X, Y, and Z arrays. +! +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Eps ! A threshold for determining the effective rank of an over-determined linear system of equations (0 < eps < 1). +! ! Eps is not likely to need changing. Default is 1.0e-16. +! REAL(DbKi), OPTIONAL, INTENT(IN) :: SmthFact ! A non-negative smoothing factor. If weights correspond to the inverse of the standard-deviation of the errors in Z, +! ! then a good value for SmthFact would be found in the range (NumPts-SQRT(2*NumPts),NumPts+SQRT(2*NumPts)). +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Tx(NumPts) ! The arrays of the X-direction knots of the spline for task=-1. +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Ty(NumPts) ! The arrays of the Y-direction knots of the spline for task=-1. +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Ty(NumPts) ! Weights of the data points for fitting a smooth surface. +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Wts(NumPts) ! Weights of the data points for fitting a smooth surface. +! REAL(DbKi), INTENT(IN) :: X (NumPts) ! X coordinates for random data points to fit a surface to. +! REAL(DbKi), INTENT(IN) :: Xbeg ! Beginning of the X region to be approximated. Default is the minimum X value. +! REAL(DbKi), INTENT(IN) :: Xend ! Ending of the X region to be approximated. Default is the maximum X value. +! REAL(DbKi), INTENT(IN) :: Y (NumPts) ! Y coordinates for random data points to fit a surface to. +! REAL(DbKi), INTENT(IN) :: Ybeg ! Beginning of the Y region to be approximated. Default is the minimum X value. +! REAL(DbKi), INTENT(IN) :: Yend ! Ending of the Y region to be approximated. Default is the maximum Y value. +! REAL(DbKi), INTENT(IN) :: Z (NumPts) ! Z is f(X,Y) values of the random data points to fit a surface to. +! +! INTEGER(IntKi), OPTIONAL, INTENT(IN) :: Kx ! The degree of the splines in the X direction. Default is 3. +! INTEGER(IntKi), OPTIONAL, INTENT(IN) :: Ky ! The degree of the splines in the Y direction. Default is 3. +! INTEGER(IntKi), INTENT(IN) :: Option ! The type of task to do. Possibilities are -1, 0, 1. Default is 0. +! +! CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message. +! +! +! ! Local declarations. +! +! REAL(DbKi), OPTIONAL, INTENT(IN) :: Epslon ! The local version of the threshold for determining the effective rank of an over-determined linear system of equations (0 < eps < 1). +! REAL(DbKi) :: SmthFact ! The local version of the non-negative smoothing factor. +! REAL(DbKi), ALLOCATABLE :: Wts(:) ! The local version of the weights. +! +! INTEGER(IntKi) :: ErrStatLcl ! The local version of the error status. +! INTEGER(IntKi) :: SplDegX ! The local version of the degree of the splines in the X direction. +! INTEGER(IntKi) :: SplDegY ! The local version of the degree of the splines in the Y direction. +! +! +! +! ErrStat = ErrID_None +! ErrMsg = "" +! +! +! IF ( .NOT. PRESENT( W ) ) THEN +! CALL AllocAry ( Wts, NumPts, 'Array of weights in BiSplRep', ErrStatLcl, ErrMsg ) +! IF ( ErrStatLcl /= 0 ) THEN +! CALL ExitThisRoutine ( ErrID_Fatal, ErrMsg ) +! ENDIF +! Wts(:) = 1.0 +! ENDIF +! +! IF ( PRESENT( Kx ) ) THEN +! SplDegX = Kx +! ELSE +! SplDegX = 3 +! ENDIF +! +! IF ( PRESENT( Ky ) ) THEN +! SplDegY = Ky +! ELSE +! SplDegY = 3 +! ENDIF +! +! CALL DSurFit ( Opt, NumPts, X, Y, Z, Wts, Xbeg, Xend,Ybeg,Yend,kx,ky,SmthFact, nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) +! +! +! +! IF (INFO /= 0) THEN +! ErrStat = ErrID_FATAL +! WRITE( ErrMsg, * ) INFO +! IF (INFO < 0) THEN +! ErrMsg = "LAPACK_DGBSV: illegal value in argument "//TRIM(ErrMsg)//"." +! ELSE +! ErrMsg = 'LAPACK_DGBSV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' +! END IF +! END IF +! +! +! RETURN +! END SUBROUTINE FitPack_dsurfit +!!======================================================================= +! SUBROUTINE FitPack_ssurfit( N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, ErrStat, ErrMsg ) +! +! +! ! passed parameters +! +! INTEGER, intent(in ) :: KL ! The number of subdiagonals within the band of A. KL >= 0. +! INTEGER, intent(in ) :: KU ! The number of superdiagonals within the band of A. KU >= 0. +! INTEGER, intent(in ) :: N ! The number of linear equations, i.e., the order of the matrix A. N >= 0. +! INTEGER, intent(in ) :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. +! INTEGER, intent(in ) :: LDAB ! The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +! INTEGER, intent(in ) :: LDB ! The leading dimension of the array B. LDB >= max(1,N). +! +! ! .. Array Arguments .. +! REAL(SiKi) ,intent(inout) :: AB( LDAB, * ) ! On entry, the matrix A in band storage, in rows KL+1 to 2*KL+KU+1; rows 1 to KL of the array need not be set. +! ! The j-th column of A is stored in the j-th column of the array AB as follows: +! ! AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL) +! ! On exit, details of the factorization: U is stored as an upper triangular band matrix with KL+KU superdiagonals in +! ! rows 1 to KL+KU+1, and the multipliers used during the factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +! REAL(SiKi) ,intent(inout) :: B( LDB, * ) ! On entry, the N-by-NRHS right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. +! INTEGER, intent( out) :: IPIV( * ) ! The pivot indices that define the permutation matrix P; row i of the matrix was interchanged with row IPIV(i). +! +! INTEGER(IntKi), intent( out) :: ErrStat ! Error level +! CHARACTER(*), intent( out) :: ErrMsg ! Message describing error +! +! ! local variables +! INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. +! ! > 0: if INFO = i, U(i,i) is exactly zero. The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed. +! +! +! +! ErrStat = ErrID_None +! ErrMsg = "" +! +! CALL SGBSV (N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO) +! +! IF (INFO /= 0) THEN +! ErrStat = ErrID_FATAL +! WRITE( ErrMsg, * ) INFO +! IF (INFO < 0) THEN +! ErrMsg = "LAPACK_SGBSV: illegal value in argument "//TRIM(ErrMsg)//"." +! ELSE +! ErrMsg = 'LAPACK_SGBSV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' +! END IF +! END IF +! +! +! RETURN +! END SUBROUTINE FitPack_ssurfit +!======================================================================= +END MODULE NWTC_FitPack diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/dierckx_fitpack.f b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/dierckx_fitpack.f new file mode 100644 index 000000000..81928abd9 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/dierckx_fitpack.f @@ -0,0 +1,1517 @@ + subroutine bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, + * iwrk,kwrk,ier) +c subroutine bispev evaluates on a grid (x(i),y(j)),i=1,...,mx; j=1,... +c ,my a bivariate spline s(x,y) of degrees kx and ky, given in the +c b-spline representation. +c +c calling sequence: +c call bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, +c * iwrk,kwrk,ier) +c +c input parameters: +c tx : real array, length nx, which contains the position of the +c knots in the x-direction. +c nx : integer, giving the total number of knots in the x-direction +c ty : real array, length ny, which contains the position of the +c knots in the y-direction. +c ny : integer, giving the total number of knots in the y-direction +c c : real array, length (nx-kx-1)*(ny-ky-1), which contains the +c b-spline coefficients. +c kx,ky : integer values, giving the degrees of the spline. +c x : real array of dimension (mx). +c before entry x(i) must be set to the x co-ordinate of the +c i-th grid point along the x-axis. +c tx(kx+1)<=x(i-1)<=x(i)<=tx(nx-kx), i=2,...,mx. +c mx : on entry mx must specify the number of grid points along +c the x-axis. mx >=1. +c y : real array of dimension (my). +c before entry y(j) must be set to the y co-ordinate of the +c j-th grid point along the y-axis. +c ty(ky+1)<=y(j-1)<=y(j)<=ty(ny-ky), j=2,...,my. +c my : on entry my must specify the number of grid points along +c the y-axis. my >=1. +c wrk : real array of dimension lwrk. used as workspace. +c lwrk : integer, specifying the dimension of wrk. +c lwrk >= mx*(kx+1)+my*(ky+1) +c iwrk : integer array of dimension kwrk. used as workspace. +c kwrk : integer, specifying the dimension of iwrk. kwrk >= mx+my. +c +c output parameters: +c z : real array of dimension (mx*my). +c on succesful exit z(my*(i-1)+j) contains the value of s(x,y) +c at the point (x(i),y(j)),i=1,...,mx;j=1,...,my. +c ier : integer error flag +c ier=0 : normal return +c ier=10: invalid input data (see restrictions) +c +c restrictions: +c mx >=1, my >=1, lwrk>=mx*(kx+1)+my*(ky+1), kwrk>=mx+my +c tx(kx+1) <= x(i-1) <= x(i) <= tx(nx-kx), i=2,...,mx +c ty(ky+1) <= y(j-1) <= y(j) <= ty(ny-ky), j=2,...,my +c +c other subroutines required: +c fpbisp,fpbspl +c +c references : +c de boor c : on calculating with b-splines, j. approximation theory +c 6 (1972) 50-62. +c cox m.g. : the numerical evaluation of b-splines, j. inst. maths +c applics 10 (1972) 134-149. +c dierckx p. : curve and surface fitting with splines, monographs on +c numerical analysis, oxford university press, 1993. +c +c author : +c p.dierckx +c dept. computer science, k.u.leuven +c celestijnenlaan 200a, b-3001 heverlee, belgium. +c e-mail : Paul.Dierckx@cs.kuleuven.ac.be +c +c latest update : march 1987 +c +c ..scalar arguments.. + integer nx,ny,kx,ky,mx,my,lwrk,kwrk,ier +c ..array arguments.. + integer iwrk(kwrk) + real tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),x(mx),y(my),z(mx*my), + * wrk(lwrk) +c ..local scalars.. + integer i,iw,lwest +c .. +c before starting computations a data check is made. if the input data +c are invalid control is immediately repassed to the calling program. + ier = 10 + lwest = (kx+1)*mx+(ky+1)*my + if(lwrk.lt.lwest) go to 100 + if(kwrk.lt.(mx+my)) go to 100 + if(mx-1) 100,30,10 + 10 do 20 i=2,mx + if(x(i).lt.x(i-1)) go to 100 + 20 continue + 30 if(my-1) 100,60,40 + 40 do 50 i=2,my + if(y(i).lt.y(i-1)) go to 100 + 50 continue + 60 ier = 0 + iw = mx*(kx+1)+1 + call fpbisp(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk(1),wrk(iw), + * iwrk(1),iwrk(mx+1)) + 100 return + end + subroutine fpback(a,z,n,k,c,nest) +c subroutine fpback calculates the solution of the system of +c equations a*c = z with a a n x n upper triangular matrix +c of bandwidth k. +c .. +c ..scalar arguments.. + integer n,k,nest +c ..array arguments.. + real a(nest,k),z(n),c(n) +c ..local scalars.. + real store + integer i,i1,j,k1,l,m +c .. + k1 = k-1 + c(n) = z(n)/a(n,1) + i = n-1 + if(i.eq.0) go to 30 + do 20 j=2,n + store = z(i) + i1 = k1 + if(j.le.k1) i1 = j-1 + m = i + do 10 l=1,i1 + m = m+1 + store = store-c(m)*a(i,l+1) + 10 continue + c(i) = store/a(i,1) + i = i-1 + 20 continue + 30 return + end + subroutine fpbisp(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wx,wy,lx,ly) +c ..scalar arguments.. + integer nx,ny,kx,ky,mx,my +c ..array arguments.. + integer lx(mx),ly(my) + real tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),x(mx),y(my),z(mx*my), + * wx(mx,kx+1),wy(my,ky+1) +c ..local scalars.. + integer i, j, i1, j1 + integer kx1,ky1,l,l1,l2,m,nkx1,nky1 + real arg,sp,tb,te +c ..local arrays.. + real h(6) +c ..subroutine references.. +c fpbspl +c .. + kx1 = kx+1 + nkx1 = nx-kx1 + tb = tx(kx1) + te = tx(nkx1+1) + l = kx1 + l1 = l+1 + do 40 i=1,mx + arg = x(i) + if(arg.lt.tb) arg = tb + if(arg.gt.te) arg = te + 10 if(arg.lt.tx(l1) .or. l.eq.nkx1) go to 20 + l = l1 + l1 = l+1 + go to 10 + 20 call fpbspl(tx,nx,kx,arg,l,h) + lx(i) = l-kx1 + do 30 j=1,kx1 + wx(i,j) = h(j) + 30 continue + 40 continue + ky1 = ky+1 + nky1 = ny-ky1 + tb = ty(ky1) + te = ty(nky1+1) + l = ky1 + l1 = l+1 + do 80 i=1,my + arg = y(i) + if(arg.lt.tb) arg = tb + if(arg.gt.te) arg = te + 50 if(arg.lt.ty(l1) .or. l.eq.nky1) go to 60 + l = l1 + l1 = l+1 + go to 50 + 60 call fpbspl(ty,ny,ky,arg,l,h) + ly(i) = l-ky1 + do 70 j=1,ky1 + wy(i,j) = h(j) + 70 continue + 80 continue + m = 0 + do 130 i=1,mx + l = lx(i)*nky1 + do 90 i1=1,kx1 + h(i1) = wx(i,i1) + 90 continue + do 120 j=1,my + l1 = l+ly(j) + sp = 0. + do 110 i1=1,kx1 + l2 = l1 + do 100 j1=1,ky1 + l2 = l2+1 + sp = sp+c(l2)*h(i1)*wy(j,j1) + 100 continue + l1 = l1+nky1 + 110 continue + m = m+1 + z(m) = sp + 120 continue + 130 continue + return + end + + subroutine fpbspl(t,n,k,x,l,h) +c subroutine fpbspl evaluates the (k+1) non-zero b-splines of +c degree k at t(l) <= x < t(l+1) using the stable recurrence +c relation of de boor and cox. +c .. +c ..scalar arguments.. + real x + integer n,k,l +c ..array arguments.. + real t(n),h(6) +c ..local scalars.. + real f,one + integer i,j,li,lj +c ..local arrays.. + real hh(5) +c .. + one = 0.1e+01 + h(1) = one + do 20 j=1,k + do 10 i=1,j + hh(i) = h(i) + 10 continue + h(1) = 0. + do 20 i=1,j + li = l+i + lj = li-j + f = hh(i)/(t(li)-t(lj)) + h(i) = h(i)+f*(t(li)-x) + h(i+1) = f*(x-t(lj)) + 20 continue + return + end + subroutine fpchec(x,m,t,n,k,ier) +c subroutine fpchec verifies the number and the position of the knots +c t(j),j=1,2,...,n of a spline of degree k, in relation to the number +c and the position of the data points x(i),i=1,2,...,m. if all of the +c following conditions are fulfilled, the error parameter ier is set +c to zero. if one of the conditions is violated ier is set to ten. +c 1) k+1 <= n-k-1 <= m +c 2) t(1) <= t(2) <= ... <= t(k+1) +c t(n-k) <= t(n-k+1) <= ... <= t(n) +c 3) t(k+1) < t(k+2) < ... < t(n-k) +c 4) t(k+1) <= x(i) <= t(n-k) +c 5) the conditions specified by schoenberg and whitney must hold +c for at least one subset of data points, i.e. there must be a +c subset of data points y(j) such that +c t(j) < y(j) < t(j+k+1), j=1,2,...,n-k-1 +c .. +c ..scalar arguments.. + integer m,n,k,ier +c ..array arguments.. + real x(m),t(n) +c ..local scalars.. + integer i,j,k1,k2,l,nk1,nk2,nk3 + real tj,tl +c .. + k1 = k+1 + k2 = k1+1 + nk1 = n-k1 + nk2 = nk1+1 + ier = 10 +c check condition no 1 + if(nk1.lt.k1 .or. nk1.gt.m) go to 80 +c check condition no 2 + j = n + do 20 i=1,k + if(t(i).gt.t(i+1)) go to 80 + if(t(j).lt.t(j-1)) go to 80 + j = j-1 + 20 continue +c check condition no 3 + do 30 i=k2,nk2 + if(t(i).le.t(i-1)) go to 80 + 30 continue +c check condition no 4 + if(x(1).lt.t(k1) .or. x(m).gt.t(nk2)) go to 80 +c check condition no 5 + if(x(1).ge.t(k2) .or. x(m).le.t(nk1)) go to 80 + i = 1 + l = k2 + nk3 = nk1-1 + if(nk3.lt.2) go to 70 + do 60 j=2,nk3 + tj = t(j) + l = l+1 + tl = t(l) + 40 i = i+1 + if(i.ge.m) go to 80 + if(x(i).le.tj) go to 40 + if(x(i).ge.tl) go to 80 + 60 continue + 70 ier = 0 + 80 return + end + subroutine fpdisc(t,n,k2,b,nest) +c subroutine fpdisc calculates the discontinuity jumps of the kth +c derivative of the b-splines of degree k at the knots t(k+2)..t(n-k-1) +c ..scalar arguments.. + integer n,k2,nest +c ..array arguments.. + real t(n),b(nest,k2) +c ..local scalars.. + real an,fac,prod + integer i,ik,j,jk,k,k1,l,lj,lk,lmk,lp,nk1,nrint +c ..local array.. + real h(12) +c .. + k1 = k2-1 + k = k1-1 + nk1 = n-k1 + nrint = nk1-k + an = nrint + fac = an/(t(nk1+1)-t(k1)) + do 40 l=k2,nk1 + lmk = l-k1 + do 10 j=1,k1 + ik = j+k1 + lj = l+j + lk = lj-k2 + h(j) = t(l)-t(lk) + h(ik) = t(l)-t(lj) + 10 continue + lp = lmk + do 30 j=1,k2 + jk = j + prod = h(j) + do 20 i=1,k + jk = jk+1 + prod = prod*h(jk)*fac + 20 continue + lk = lp+k1 + b(lmk,j) = (t(lk)-t(lp))/prod + lp = lp+1 + 30 continue + 40 continue + return + end + subroutine fpgivs(piv,ww,cos,sin) +c subroutine fpgivs calculates the parameters of a givens +c transformation . +c .. +c ..scalar arguments.. + real piv,ww,cos,sin +c ..local scalars.. + real dd,one,store +c ..function references.. + real abs,sqrt +c .. + one = 0.1e+01 + store = abs(piv) + if(store.ge.ww) dd = store*sqrt(one+(ww/piv)**2) + if(store.lt.ww) dd = ww*sqrt(one+(piv/ww)**2) + cos = ww/dd + sin = piv/dd + ww = dd + return + end + subroutine fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx, + * ty,ny,p,c,nc,fp,fpx,fpy,mm,mynx,kx1,kx2,ky1,ky2,spx,spy,right,q, + * ax,ay,bx,by,nrx,nry) +c .. +c ..scalar arguments.. + real p,fp + integer ifsx,ifsy,ifbx,ifby,mx,my,mz,kx,ky,nx,ny,nc,mm,mynx, + * kx1,kx2,ky1,ky2 +c ..array arguments.. + real x(mx),y(my),z(mz),tx(nx),ty(ny),c(nc),spx(mx,kx1),spy(my,ky1) + * ,right(mm),q(mynx),ax(nx,kx2),bx(nx,kx2),ay(ny,ky2),by(ny,ky2), + * fpx(nx),fpy(ny) + integer nrx(mx),nry(my) +c ..local scalars.. + real arg,cos,fac,pinv,piv,sin,term,one,half + integer i,ibandx,ibandy,ic,iq,irot,it,iz,i1,i2,i3,j,k,k1,k2,l, + * l1,l2,ncof,nk1x,nk1y,nrold,nroldx,nroldy,number,numx,numx1, + * numy,numy1,n1 +c ..local arrays.. + real h(7) +c ..subroutine references.. +c fpback,fpbspl,fpgivs,fpdisc,fprota +c .. +c the b-spline coefficients of the smoothing spline are calculated as +c the least-squares solution of the over-determined linear system of +c equations (ay) c (ax)' = q where +c +c | (spx) | | (spy) | +c (ax) = | ---------- | (ay) = | ---------- | +c | (1/p) (bx) | | (1/p) (by) | +c +c | z ' 0 | +c q = | ------ | +c | 0 ' 0 | +c +c with c : the (ny-ky-1) x (nx-kx-1) matrix which contains the +c b-spline coefficients. +c z : the my x mx matrix which contains the function values. +c spx,spy: the mx x (nx-kx-1) and my x (ny-ky-1) observation +c matrices according to the least-squares problems in +c the x- and y-direction. +c bx,by : the (nx-2*kx-1) x (nx-kx-1) and (ny-2*ky-1) x (ny-ky-1) +c matrices which contain the discontinuity jumps of the +c derivatives of the b-splines in the x- and y-direction. + one = 1 + half = 0.5 + nk1x = nx-kx1 + nk1y = ny-ky1 + if(p.gt.0.) pinv = one/p +c it depends on the value of the flags ifsx,ifsy,ifbx and ifby and on +c the value of p whether the matrices (spx),(spy),(bx) and (by) still +c must be determined. + if(ifsx.ne.0) go to 50 +c calculate the non-zero elements of the matrix (spx) which is the +c observation matrix according to the least-squares spline approximat- +c ion problem in the x-direction. + l = kx1 + l1 = kx2 + number = 0 + do 40 it=1,mx + arg = x(it) + 10 if(arg.lt.tx(l1) .or. l.eq.nk1x) go to 20 + l = l1 + l1 = l+1 + number = number+1 + go to 10 + 20 call fpbspl(tx,nx,kx,arg,l,h) + do 30 i=1,kx1 + spx(it,i) = h(i) + 30 continue + nrx(it) = number + 40 continue + ifsx = 1 + 50 if(ifsy.ne.0) go to 100 +c calculate the non-zero elements of the matrix (spy) which is the +c observation matrix according to the least-squares spline approximat- +c ion problem in the y-direction. + l = ky1 + l1 = ky2 + number = 0 + do 90 it=1,my + arg = y(it) + 60 if(arg.lt.ty(l1) .or. l.eq.nk1y) go to 70 + l = l1 + l1 = l+1 + number = number+1 + go to 60 + 70 call fpbspl(ty,ny,ky,arg,l,h) + do 80 i=1,ky1 + spy(it,i) = h(i) + 80 continue + nry(it) = number + 90 continue + ifsy = 1 + 100 if(p.le.0.) go to 120 +c calculate the non-zero elements of the matrix (bx). + if(ifbx.ne.0 .or. nx.eq.2*kx1) go to 110 + call fpdisc(tx,nx,kx2,bx,nx) + ifbx = 1 +c calculate the non-zero elements of the matrix (by). + 110 if(ifby.ne.0 .or. ny.eq.2*ky1) go to 120 + call fpdisc(ty,ny,ky2,by,ny) + ifby = 1 +c reduce the matrix (ax) to upper triangular form (rx) using givens +c rotations. apply the same transformations to the rows of matrix q +c to obtain the my x (nx-kx-1) matrix g. +c store matrix (rx) into (ax) and g into q. + 120 l = my*nk1x +c initialization. + do 130 i=1,l + q(i) = 0. + 130 continue + do 140 i=1,nk1x + do 140 j=1,kx2 + ax(i,j) = 0. + 140 continue + l = 0 + nrold = 0 +c ibandx denotes the bandwidth of the matrices (ax) and (rx). + ibandx = kx1 + do 270 it=1,mx + number = nrx(it) + 150 if(nrold.eq.number) go to 180 + if(p.le.0.) go to 260 + ibandx = kx2 +c fetch a new row of matrix (bx). + n1 = nrold+1 + do 160 j=1,kx2 + h(j) = bx(n1,j)*pinv + 160 continue +c find the appropriate column of q. + do 170 j=1,my + right(j) = 0. + 170 continue + irot = nrold + go to 210 +c fetch a new row of matrix (spx). + 180 h(ibandx) = 0. + do 190 j=1,kx1 + h(j) = spx(it,j) + 190 continue +c find the appropriate column of q. + do 200 j=1,my + l = l+1 + right(j) = z(l) + 200 continue + irot = number +c rotate the new row of matrix (ax) into triangle. + 210 do 240 i=1,ibandx + irot = irot+1 + piv = h(i) + if(piv.eq.0.) go to 240 +c calculate the parameters of the givens transformation. + call fpgivs(piv,ax(irot,1),cos,sin) +c apply that transformation to the rows of matrix q. + iq = (irot-1)*my + do 220 j=1,my + iq = iq+1 + call fprota(cos,sin,right(j),q(iq)) + 220 continue +c apply that transformation to the columns of (ax). + if(i.eq.ibandx) go to 250 + i2 = 1 + i3 = i+1 + do 230 j=i3,ibandx + i2 = i2+1 + call fprota(cos,sin,h(j),ax(irot,i2)) + 230 continue + 240 continue + 250 if(nrold.eq.number) go to 270 + 260 nrold = nrold+1 + go to 150 + 270 continue +c reduce the matrix (ay) to upper triangular form (ry) using givens +c rotations. apply the same transformations to the columns of matrix g +c to obtain the (ny-ky-1) x (nx-kx-1) matrix h. +c store matrix (ry) into (ay) and h into c. + ncof = nk1x*nk1y +c initialization. + do 280 i=1,ncof + c(i) = 0. + 280 continue + do 290 i=1,nk1y + do 290 j=1,ky2 + ay(i,j) = 0. + 290 continue + nrold = 0 +c ibandy denotes the bandwidth of the matrices (ay) and (ry). + ibandy = ky1 + do 420 it=1,my + number = nry(it) + 300 if(nrold.eq.number) go to 330 + if(p.le.0.) go to 410 + ibandy = ky2 +c fetch a new row of matrix (by). + n1 = nrold+1 + do 310 j=1,ky2 + h(j) = by(n1,j)*pinv + 310 continue +c find the appropiate row of g. + do 320 j=1,nk1x + right(j) = 0. + 320 continue + irot = nrold + go to 360 +c fetch a new row of matrix (spy) + 330 h(ibandy) = 0. + do 340 j=1,ky1 + h(j) = spy(it,j) + 340 continue +c find the appropiate row of g. + l = it + do 350 j=1,nk1x + right(j) = q(l) + l = l+my + 350 continue + irot = number +c rotate the new row of matrix (ay) into triangle. + 360 do 390 i=1,ibandy + irot = irot+1 + piv = h(i) + if(piv.eq.0.) go to 390 +c calculate the parameters of the givens transformation. + call fpgivs(piv,ay(irot,1),cos,sin) +c apply that transformation to the colums of matrix g. + ic = irot + do 370 j=1,nk1x + call fprota(cos,sin,right(j),c(ic)) + ic = ic+nk1y + 370 continue +c apply that transformation to the columns of matrix (ay). + if(i.eq.ibandy) go to 400 + i2 = 1 + i3 = i+1 + do 380 j=i3,ibandy + i2 = i2+1 + call fprota(cos,sin,h(j),ay(irot,i2)) + 380 continue + 390 continue + 400 if(nrold.eq.number) go to 420 + 410 nrold = nrold+1 + go to 300 + 420 continue +c backward substitution to obtain the b-spline coefficients as the +c solution of the linear system (ry) c (rx)' = h. +c first step: solve the system (ry) (c1) = h. + k = 1 + do 450 i=1,nk1x + call fpback(ay,c(k),nk1y,ibandy,c(k),ny) + k = k+nk1y + 450 continue +c second step: solve the system c (rx)' = (c1). + k = 0 + do 480 j=1,nk1y + k = k+1 + l = k + do 460 i=1,nk1x + right(i) = c(l) + l = l+nk1y + 460 continue + call fpback(ax,right,nk1x,ibandx,right,nx) + l = k + do 470 i=1,nk1x + c(l) = right(i) + l = l+nk1y + 470 continue + 480 continue +c calculate the quantities +c res(i,j) = (z(i,j) - s(x(i),y(j)))**2 , i=1,2,..,mx;j=1,2,..,my +c fp = sumi=1,mx(sumj=1,my(res(i,j))) +c fpx(r) = sum''i(sumj=1,my(res(i,j))) , r=1,2,...,nx-2*kx-1 +c tx(r+kx) <= x(i) <= tx(r+kx+1) +c fpy(r) = sumi=1,mx(sum''j(res(i,j))) , r=1,2,...,ny-2*ky-1 +c ty(r+ky) <= y(j) <= ty(r+ky+1) + fp = 0. + do 490 i=1,nx + fpx(i) = 0. + 490 continue + do 500 i=1,ny + fpy(i) = 0. + 500 continue + nk1y = ny-ky1 + iz = 0 + nroldx = 0 +c main loop for the different grid points. + do 550 i1=1,mx + numx = nrx(i1) + numx1 = numx+1 + nroldy = 0 + do 540 i2=1,my + numy = nry(i2) + numy1 = numy+1 + iz = iz+1 +c evaluate s(x,y) at the current grid point by making the sum of the +c cross products of the non-zero b-splines at (x,y), multiplied with +c the appropiate b-spline coefficients. + term = 0. + k1 = numx*nk1y+numy + do 520 l1=1,kx1 + k2 = k1 + fac = spx(i1,l1) + do 510 l2=1,ky1 + k2 = k2+1 + term = term+fac*spy(i2,l2)*c(k2) + 510 continue + k1 = k1+nk1y + 520 continue +c calculate the squared residual at the current grid point. + term = (z(iz)-term)**2 +c adjust the different parameters. + fp = fp+term + fpx(numx1) = fpx(numx1)+term + fpy(numy1) = fpy(numy1)+term + fac = term*half + if(numy.eq.nroldy) go to 530 + fpy(numy1) = fpy(numy1)-fac + fpy(numy) = fpy(numy)+fac + 530 nroldy = numy + if(numx.eq.nroldx) go to 540 + fpx(numx1) = fpx(numx1)-fac + fpx(numx) = fpx(numx)+fac + 540 continue + nroldx = numx + 550 continue + return + end + + subroutine fpknot(x,m,t,n,fpint,nrdata,nrint,nest,istart) +c subroutine fpknot locates an additional knot for a spline of degree +c k and adjusts the corresponding parameters,i.e. +c t : the position of the knots. +c n : the number of knots. +c nrint : the number of knotintervals. +c fpint : the sum of squares of residual right hand sides +c for each knot interval. +c nrdata: the number of data points inside each knot interval. +c istart indicates that the smallest data point at which the new knot +c may be added is x(istart+1) +c .. +c ..scalar arguments.. + integer m,n,nrint,nest,istart +c ..array arguments.. + real x(m),t(nest),fpint(nest) + integer nrdata(nest) +c ..local scalars.. + real an,am,fpmax + integer ihalf,j,jbegin,jj,jk,jpoint,k,maxbeg,maxpt, + * next,nrx,number +c .. + k = (n-nrint-1)/2 +c search for knot interval t(number+k) <= x <= t(number+k+1) where +c fpint(number) is maximal on the condition that nrdata(number) +c not equals zero. + fpmax = 0. + jbegin = istart + do 20 j=1,nrint + jpoint = nrdata(j) + if(fpmax.ge.fpint(j) .or. jpoint.eq.0) go to 10 + fpmax = fpint(j) + number = j + maxpt = jpoint + maxbeg = jbegin + 10 jbegin = jbegin+jpoint+1 + 20 continue +c let coincide the new knot t(number+k+1) with a data point x(nrx) +c inside the old knot interval t(number+k) <= x <= t(number+k+1). + ihalf = maxpt/2+1 + nrx = maxbeg+ihalf + next = number+1 + if(next.gt.nrint) go to 40 +c adjust the different parameters. + do 30 j=next,nrint + jj = next+nrint-j + fpint(jj+1) = fpint(jj) + nrdata(jj+1) = nrdata(jj) + jk = jj+k + t(jk+1) = t(jk) + 30 continue + 40 nrdata(number) = ihalf-1 + nrdata(next) = maxpt-ihalf + am = maxpt + an = nrdata(number) + fpint(number) = fpmax*an/am + an = nrdata(next) + fpint(next) = fpmax*an/am + jk = next+k + t(jk) = x(nrx) + n = n+1 + nrint = nrint+1 + return + end + real function fprati(p1,f1,p2,f2,p3,f3) +c given three points (p1,f1),(p2,f2) and (p3,f3), function fprati +c gives the value of p such that the rational interpolating function +c of the form r(p) = (u*p+v)/(p+w) equals zero at p. +c .. +c ..scalar arguments.. + real p1,f1,p2,f2,p3,f3 +c ..local scalars.. + real h1,h2,h3,p +c .. + if(p3.gt.0.) go to 10 +c value of p in case p3 = infinity. + p = (p1*(f1-f3)*f2-p2*(f2-f3)*f1)/((f1-f2)*f3) + go to 20 +c value of p in case p3 ^= infinity. + 10 h1 = f1*(f2-f3) + h2 = f2*(f3-f1) + h3 = f3*(f1-f2) + p = -(p1*p2*h3+p2*p3*h1+p3*p1*h2)/(p1*h1+p2*h2+p3*h3) +c adjust the value of p1,f1,p3 and f3 such that f1 > 0 and f3 < 0. + 20 if(f2.lt.0.) go to 30 + p1 = p2 + f1 = f2 + go to 40 + 30 p3 = p2 + f3 = f2 + 40 fprati = p + return + end + subroutine fpregr(iopt,x,mx,y,my,z,mz,xb,xe,yb,ye,kx,ky,s, + * nxest,nyest,tol,maxit,nc,nx,tx,ny,ty,c,fp,fp0,fpold,reducx, + * reducy,fpintx,fpinty,lastdi,nplusx,nplusy,nrx,nry,nrdatx,nrdaty, + * wrk,lwrk,ier) +c .. +c ..scalar arguments.. + real xb,xe,yb,ye,s,tol,fp,fp0,fpold,reducx,reducy + integer iopt,mx,my,mz,kx,ky,nxest,nyest,maxit,nc,nx,ny,lastdi, + * nplusx,nplusy,lwrk,ier +c ..array arguments.. + real x(mx),y(my),z(mz),tx(nxest),ty(nyest),c(nc),fpintx(nxest), + * fpinty(nyest),wrk(lwrk) + integer nrdatx(nxest),nrdaty(nyest),nrx(mx),nry(my) +c ..local scalars + real acc,fpms,f1,f2,f3,p,p1,p2,p3,rn,one,half,con1,con9,con4 + integer i,ich1,ich3,ifbx,ifby,ifsx,ifsy,iter,j,kx1,kx2,ky1,ky2, + * k3,l,lax,lay,lbx,lby,lq,lri,lsx,lsy,mk1,mm,mpm,mynx,ncof, + * nk1x,nk1y,nmaxx,nmaxy,nminx,nminy,nplx,nply,npl1,nrintx, + * nrinty,nxe,nxk,nye +c ..function references.. + real abs,fprati + integer max0,min0 +c ..subroutine references.. +c fpgrre,fpknot +c .. +c set constants + one = 1 + half = 0.5e0 + con1 = 0.1e0 + con9 = 0.9e0 + con4 = 0.4e-01 +c we partition the working space. + kx1 = kx+1 + ky1 = ky+1 + kx2 = kx1+1 + ky2 = ky1+1 + lsx = 1 + lsy = lsx+mx*kx1 + lri = lsy+my*ky1 + mm = max0(nxest,my) + lq = lri+mm + mynx = nxest*my + lax = lq+mynx + nxk = nxest*kx2 + lbx = lax+nxk + lay = lbx+nxk + lby = lay+nyest*ky2 +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c part 1: determination of the number of knots and their position. c +c **************************************************************** c +c given a set of knots we compute the least-squares spline sinf(x,y), c +c and the corresponding sum of squared residuals fp=f(p=inf). c +c if iopt=-1 sinf(x,y) is the requested approximation. c +c if iopt=0 or iopt=1 we check whether we can accept the knots: c +c if fp <=s we will continue with the current set of knots. c +c if fp > s we will increase the number of knots and compute the c +c corresponding least-squares spline until finally fp<=s. c +c the initial choice of knots depends on the value of s and iopt. c +c if s=0 we have spline interpolation; in that case the number of c +c knots equals nmaxx = mx+kx+1 and nmaxy = my+ky+1. c +c if s>0 and c +c *iopt=0 we first compute the least-squares polynomial of degree c +c kx in x and ky in y; nx=nminx=2*kx+2 and ny=nymin=2*ky+2. c +c *iopt=1 we start with the knots found at the last call of the c +c routine, except for the case that s > fp0; then we can compute c +c the least-squares polynomial directly. c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c determine the number of knots for polynomial approximation. + nminx = 2*kx1 + nminy = 2*ky1 + if(iopt.lt.0) go to 120 +c acc denotes the absolute tolerance for the root of f(p)=s. + acc = tol*s +c find nmaxx and nmaxy which denote the number of knots in x- and y- +c direction in case of spline interpolation. + nmaxx = mx+kx1 + nmaxy = my+ky1 +c find nxe and nye which denote the maximum number of knots +c allowed in each direction + nxe = min0(nmaxx,nxest) + nye = min0(nmaxy,nyest) + if(s.gt.0.) go to 100 +c if s = 0, s(x,y) is an interpolating spline. + nx = nmaxx + ny = nmaxy +c test whether the required storage space exceeds the available one. + if(ny.gt.nyest .or. nx.gt.nxest) go to 420 +c find the position of the interior knots in case of interpolation. +c the knots in the x-direction. + mk1 = mx-kx1 + if(mk1.eq.0) go to 60 + k3 = kx/2 + i = kx1+1 + j = k3+2 + if(k3*2.eq.kx) go to 40 + do 30 l=1,mk1 + tx(i) = x(j) + i = i+1 + j = j+1 + 30 continue + go to 60 + 40 do 50 l=1,mk1 + tx(i) = (x(j)+x(j-1))*half + i = i+1 + j = j+1 + 50 continue +c the knots in the y-direction. + 60 mk1 = my-ky1 + if(mk1.eq.0) go to 120 + k3 = ky/2 + i = ky1+1 + j = k3+2 + if(k3*2.eq.ky) go to 80 + do 70 l=1,mk1 + ty(i) = y(j) + i = i+1 + j = j+1 + 70 continue + go to 120 + 80 do 90 l=1,mk1 + ty(i) = (y(j)+y(j-1))*half + i = i+1 + j = j+1 + 90 continue + go to 120 +c if s > 0 our initial choice of knots depends on the value of iopt. + 100 if(iopt.eq.0) go to 115 + if(fp0.le.s) go to 115 +c if iopt=1 and fp0 > s we start computing the least- squares spline +c according to the set of knots found at the last call of the routine. +c we determine the number of grid coordinates x(i) inside each knot +c interval (tx(l),tx(l+1)). + l = kx2 + j = 1 + nrdatx(1) = 0 + mpm = mx-1 + do 105 i=2,mpm + nrdatx(j) = nrdatx(j)+1 + if(x(i).lt.tx(l)) go to 105 + nrdatx(j) = nrdatx(j)-1 + l = l+1 + j = j+1 + nrdatx(j) = 0 + 105 continue +c we determine the number of grid coordinates y(i) inside each knot +c interval (ty(l),ty(l+1)). + l = ky2 + j = 1 + nrdaty(1) = 0 + mpm = my-1 + do 110 i=2,mpm + nrdaty(j) = nrdaty(j)+1 + if(y(i).lt.ty(l)) go to 110 + nrdaty(j) = nrdaty(j)-1 + l = l+1 + j = j+1 + nrdaty(j) = 0 + 110 continue + go to 120 +c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares +c polynomial of degree kx in x and ky in y (which is a spline without +c interior knots). + 115 nx = nminx + ny = nminy + nrdatx(1) = mx-2 + nrdaty(1) = my-2 + lastdi = 0 + nplusx = 0 + nplusy = 0 + fp0 = 0. + fpold = 0. + reducx = 0. + reducy = 0. + 120 mpm = mx+my + ifsx = 0 + ifsy = 0 + ifbx = 0 + ifby = 0 + p = -one +c main loop for the different sets of knots.mpm=mx+my is a save upper +c bound for the number of trials. + do 250 iter=1,mpm + if(nx.eq.nminx .and. ny.eq.nminy) ier = -2 +c find nrintx (nrinty) which is the number of knot intervals in the +c x-direction (y-direction). + nrintx = nx-nminx+1 + nrinty = ny-nminy+1 +c find ncof, the number of b-spline coefficients for the current set +c of knots. + nk1x = nx-kx1 + nk1y = ny-ky1 + ncof = nk1x*nk1y +c find the position of the additional knots which are needed for the +c b-spline representation of s(x,y). + i = nx + do 130 j=1,kx1 + tx(j) = xb + tx(i) = xe + i = i-1 + 130 continue + i = ny + do 140 j=1,ky1 + ty(j) = yb + ty(i) = ye + i = i-1 + 140 continue +c find the least-squares spline sinf(x,y) and calculate for each knot +c interval tx(j+kx)<=x<=tx(j+kx+1) (ty(j+ky)<=y<=ty(j+ky+1)) the sum +c of squared residuals fpintx(j),j=1,2,...,nx-2*kx-1 (fpinty(j),j=1,2, +c ...,ny-2*ky-1) for the data points having their absciss (ordinate)- +c value belonging to that interval. +c fp gives the total sum of squared residuals. + call fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx,ty, + * ny,p,c,nc,fp,fpintx,fpinty,mm,mynx,kx1,kx2,ky1,ky2,wrk(lsx), + * wrk(lsy),wrk(lri),wrk(lq),wrk(lax),wrk(lay),wrk(lbx),wrk(lby), + * nrx,nry) + if(ier.eq.(-2)) fp0 = fp +c test whether the least-squares spline is an acceptable solution. + if(iopt.lt.0) go to 440 + fpms = fp-s + if(abs(fpms) .lt. acc) go to 440 +c if f(p=inf) < s, we accept the choice of knots. + if(fpms.lt.0.) go to 300 +c if nx=nmaxx and ny=nmaxy, sinf(x,y) is an interpolating spline. + if(nx.eq.nmaxx .and. ny.eq.nmaxy) go to 430 +c increase the number of knots. +c if nx=nxe and ny=nye we cannot further increase the number of knots +c because of the storage capacity limitation. + if(nx.eq.nxe .and. ny.eq.nye) go to 420 + ier = 0 +c adjust the parameter reducx or reducy according to the direction +c in which the last added knots were located. + if(lastdi) 150,170,160 + 150 reducx = fpold-fp + go to 170 + 160 reducy = fpold-fp +c store the sum of squared residuals for the current set of knots. + 170 fpold = fp +c find nplx, the number of knots we should add in the x-direction. + nplx = 1 + if(nx.eq.nminx) go to 180 + npl1 = nplusx*2 + rn = nplusx + if(reducx.gt.acc) npl1 = rn*fpms/reducx + nplx = min0(nplusx*2,max0(npl1,nplusx/2,1)) +c find nply, the number of knots we should add in the y-direction. + 180 nply = 1 + if(ny.eq.nminy) go to 190 + npl1 = nplusy*2 + rn = nplusy + if(reducy.gt.acc) npl1 = rn*fpms/reducy + nply = min0(nplusy*2,max0(npl1,nplusy/2,1)) + 190 if(nplx-nply) 210,200,230 + 200 if(lastdi.lt.0) go to 230 + 210 if(nx.eq.nxe) go to 230 +c addition in the x-direction. + lastdi = -1 + nplusx = nplx + ifsx = 0 + do 220 l=1,nplusx +c add a new knot in the x-direction + call fpknot(x,mx,tx,nx,fpintx,nrdatx,nrintx,nxest,1) +c test whether we cannot further increase the number of knots in the +c x-direction. + if(nx.eq.nxe) go to 250 + 220 continue + go to 250 + 230 if(ny.eq.nye) go to 210 +c addition in the y-direction. + lastdi = 1 + nplusy = nply + ifsy = 0 + do 240 l=1,nplusy +c add a new knot in the y-direction. + call fpknot(y,my,ty,ny,fpinty,nrdaty,nrinty,nyest,1) +c test whether we cannot further increase the number of knots in the +c y-direction. + if(ny.eq.nye) go to 250 + 240 continue +c restart the computations with the new set of knots. + 250 continue +c test whether the least-squares polynomial is a solution of our +c approximation problem. + 300 if(ier.eq.(-2)) go to 440 +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c part 2: determination of the smoothing spline sp(x,y) c +c ***************************************************** c +c we have determined the number of knots and their position. we now c +c compute the b-spline coefficients of the smoothing spline sp(x,y). c +c this smoothing spline varies with the parameter p in such a way thatc +c f(p) = sumi=1,mx(sumj=1,my((z(i,j)-sp(x(i),y(j)))**2) c +c is a continuous, strictly decreasing function of p. moreover the c +c least-squares polynomial corresponds to p=0 and the least-squares c +c spline to p=infinity. iteratively we then have to determine the c +c positive value of p such that f(p)=s. the process which is proposed c +c here makes use of rational interpolation. f(p) is approximated by a c +c rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3) c +c with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c +c are used to calculate the new value of p such that r(p)=s. c +c convergence is guaranteed by taking f1 > 0 and f3 < 0. c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c initial value for p. + p1 = 0. + f1 = fp0-s + p3 = -one + f3 = fpms + p = one + ich1 = 0 + ich3 = 0 +c iteration process to find the root of f(p)=s. + do 350 iter = 1,maxit +c find the smoothing spline sp(x,y) and the corresponding sum of +c squared residuals fp. + call fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx,ty, + * ny,p,c,nc,fp,fpintx,fpinty,mm,mynx,kx1,kx2,ky1,ky2,wrk(lsx), + * wrk(lsy),wrk(lri),wrk(lq),wrk(lax),wrk(lay),wrk(lbx),wrk(lby), + * nrx,nry) +c test whether the approximation sp(x,y) is an acceptable solution. + fpms = fp-s + if(abs(fpms).lt.acc) go to 440 +c test whether the maximum allowable number of iterations has been +c reached. + if(iter.eq.maxit) go to 400 +c carry out one more step of the iteration process. + p2 = p + f2 = fpms + if(ich3.ne.0) go to 320 + if((f2-f3).gt.acc) go to 310 +c our initial choice of p is too large. + p3 = p2 + f3 = f2 + p = p*con4 + if(p.le.p1) p = p1*con9 + p2*con1 + go to 350 + 310 if(f2.lt.0.) ich3 = 1 + 320 if(ich1.ne.0) go to 340 + if((f1-f2).gt.acc) go to 330 +c our initial choice of p is too small + p1 = p2 + f1 = f2 + p = p/con4 + if(p3.lt.0.) go to 350 + if(p.ge.p3) p = p2*con1 + p3*con9 + go to 350 +c test whether the iteration process proceeds as theoretically +c expected. + 330 if(f2.gt.0.) ich1 = 1 + 340 if(f2.ge.f1 .or. f2.le.f3) go to 410 +c find the new value of p. + p = fprati(p1,f1,p2,f2,p3,f3) + 350 continue +c error codes and messages. + 400 ier = 3 + go to 440 + 410 ier = 2 + go to 440 + 420 ier = 1 + go to 440 + 430 ier = -1 + fp = 0. + 440 return + end + + subroutine fprota(cos,sin,a,b) +c subroutine fprota applies a givens rotation to a and b. +c .. +c ..scalar arguments.. + real cos,sin,a,b +c ..local scalars.. + real stor1,stor2 +c .. + stor1 = a + stor2 = b + b = cos*stor2+sin*stor1 + a = cos*stor1-sin*stor2 + return + end + subroutine regrid(iopt,mx,x,my,y,z,xb,xe,yb,ye,kx,ky,s, + * nxest,nyest,nx,tx,ny,ty,c,fp,wrk,lwrk,iwrk,kwrk,ier) +c given the set of values z(i,j) on the rectangular grid (x(i),y(j)), +c i=1,...,mx;j=1,...,my, subroutine regrid determines a smooth bivar- +c iate spline approximation s(x,y) of degrees kx and ky on the rect- +c angle xb <= x <= xe, yb <= y <= ye. +c if iopt = -1 regrid calculates the least-squares spline according +c to a given set of knots. +c if iopt >= 0 the total numbers nx and ny of these knots and their +c position tx(j),j=1,...,nx and ty(j),j=1,...,ny are chosen automatic- +c ally by the routine. the smoothness of s(x,y) is then achieved by +c minimalizing the discontinuity jumps in the derivatives of s(x,y) +c across the boundaries of the subpanels (tx(i),tx(i+1))*(ty(j),ty(j+1). +c the amounth of smoothness is determined by the condition that f(p) = +c sum ((z(i,j)-s(x(i),y(j))))**2) be <= s, with s a given non-negative +c constant, called the smoothing factor. +c the fit is given in the b-spline representation (b-spline coefficients +c c((ny-ky-1)*(i-1)+j),i=1,...,nx-kx-1;j=1,...,ny-ky-1) and can be eval- +c uated by means of subroutine bispev. +c +c calling sequence: +c call regrid(iopt,mx,x,my,y,z,xb,xe,yb,ye,kx,ky,s,nxest,nyest, +c * nx,tx,ny,ty,c,fp,wrk,lwrk,iwrk,kwrk,ier) +c +c parameters: +c iopt : integer flag. on entry iopt must specify whether a least- +c squares spline (iopt=-1) or a smoothing spline (iopt=0 or 1) +c must be determined. +c if iopt=0 the routine will start with an initial set of knots +c tx(i)=xb,tx(i+kx+1)=xe,i=1,...,kx+1;ty(i)=yb,ty(i+ky+1)=ye,i= +c 1,...,ky+1. if iopt=1 the routine will continue with the set +c of knots found at the last call of the routine. +c attention: a call with iopt=1 must always be immediately pre- +c ceded by another call with iopt=1 or iopt=0 and +c s.ne.0. +c unchanged on exit. +c mx : integer. on entry mx must specify the number of grid points +c along the x-axis. mx > kx . unchanged on exit. +c x : real array of dimension at least (mx). before entry, x(i) +c must be set to the x-co-ordinate of the i-th grid point +c along the x-axis, for i=1,2,...,mx. these values must be +c supplied in strictly ascending order. unchanged on exit. +c my : integer. on entry my must specify the number of grid points +c along the y-axis. my > ky . unchanged on exit. +c y : real array of dimension at least (my). before entry, y(j) +c must be set to the y-co-ordinate of the j-th grid point +c along the y-axis, for j=1,2,...,my. these values must be +c supplied in strictly ascending order. unchanged on exit. +c z : real array of dimension at least (mx*my). +c before entry, z(my*(i-1)+j) must be set to the data value at +c the grid point (x(i),y(j)) for i=1,...,mx and j=1,...,my. +c unchanged on exit. +c xb,xe : real values. on entry xb,xe,yb and ye must specify the bound- +c yb,ye aries of the rectangular approximation domain. +c xb<=x(i)<=xe,i=1,...,mx; yb<=y(j)<=ye,j=1,...,my. +c unchanged on exit. +c kx,ky : integer values. on entry kx and ky must specify the degrees +c of the spline. 1<=kx,ky<=5. it is recommended to use bicubic +c (kx=ky=3) splines. unchanged on exit. +c s : real. on entry (in case iopt>=0) s must specify the smoothing +c factor. s >=0. unchanged on exit. +c for advice on the choice of s see further comments +c nxest : integer. unchanged on exit. +c nyest : integer. unchanged on exit. +c on entry, nxest and nyest must specify an upper bound for the +c number of knots required in the x- and y-directions respect. +c these numbers will also determine the storage space needed by +c the routine. nxest >= 2*(kx+1), nyest >= 2*(ky+1). +c in most practical situation nxest = mx/2, nyest=my/2, will +c be sufficient. always large enough are nxest=mx+kx+1, nyest= +c my+ky+1, the number of knots needed for interpolation (s=0). +c see also further comments. +c nx : integer. +c unless ier=10 (in case iopt >=0), nx will contain the total +c number of knots with respect to the x-variable, of the spline +c approximation returned. if the computation mode iopt=1 is +c used, the value of nx should be left unchanged between sub- +c sequent calls. +c in case iopt=-1, the value of nx should be specified on entry +c tx : real array of dimension nmax. +c on succesful exit, this array will contain the knots of the +c spline with respect to the x-variable, i.e. the position of +c the interior knots tx(kx+2),...,tx(nx-kx-1) as well as the +c position of the additional knots tx(1)=...=tx(kx+1)=xb and +c tx(nx-kx)=...=tx(nx)=xe needed for the b-spline representat. +c if the computation mode iopt=1 is used, the values of tx(1), +c ...,tx(nx) should be left unchanged between subsequent calls. +c if the computation mode iopt=-1 is used, the values tx(kx+2), +c ...tx(nx-kx-1) must be supplied by the user, before entry. +c see also the restrictions (ier=10). +c ny : integer. +c unless ier=10 (in case iopt >=0), ny will contain the total +c number of knots with respect to the y-variable, of the spline +c approximation returned. if the computation mode iopt=1 is +c used, the value of ny should be left unchanged between sub- +c sequent calls. +c in case iopt=-1, the value of ny should be specified on entry +c ty : real array of dimension nmax. +c on succesful exit, this array will contain the knots of the +c spline with respect to the y-variable, i.e. the position of +c the interior knots ty(ky+2),...,ty(ny-ky-1) as well as the +c position of the additional knots ty(1)=...=ty(ky+1)=yb and +c ty(ny-ky)=...=ty(ny)=ye needed for the b-spline representat. +c if the computation mode iopt=1 is used, the values of ty(1), +c ...,ty(ny) should be left unchanged between subsequent calls. +c if the computation mode iopt=-1 is used, the values ty(ky+2), +c ...ty(ny-ky-1) must be supplied by the user, before entry. +c see also the restrictions (ier=10). +c c : real array of dimension at least (nxest-kx-1)*(nyest-ky-1). +c on succesful exit, c contains the coefficients of the spline +c approximation s(x,y) +c fp : real. unless ier=10, fp contains the sum of squared +c residuals of the spline approximation returned. +c wrk : real array of dimension (lwrk). used as workspace. +c if the computation mode iopt=1 is used the values of wrk(1), +c ...,wrk(4) should be left unchanged between subsequent calls. +c lwrk : integer. on entry lwrk must specify the actual dimension of +c the array wrk as declared in the calling (sub)program. +c lwrk must not be too small. +c lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ +c my*(ky+1) +u +c where u is the larger of my and nxest. +c iwrk : integer array of dimension (kwrk). used as workspace. +c if the computation mode iopt=1 is used the values of iwrk(1), +c ...,iwrk(3) should be left unchanged between subsequent calls +c kwrk : integer. on entry kwrk must specify the actual dimension of +c the array iwrk as declared in the calling (sub)program. +c kwrk >= 3+mx+my+nxest+nyest. +c ier : integer. unless the routine detects an error, ier contains a +c non-positive value on exit, i.e. +c ier=0 : normal return. the spline returned has a residual sum of +c squares fp such that abs(fp-s)/s <= tol with tol a relat- +c ive tolerance set to 0.001 by the program. +c ier=-1 : normal return. the spline returned is an interpolating +c spline (fp=0). +c ier=-2 : normal return. the spline returned is the least-squares +c polynomial of degrees kx and ky. in this extreme case fp +c gives the upper bound for the smoothing factor s. +c ier=1 : error. the required storage space exceeds the available +c storage space, as specified by the parameters nxest and +c nyest. +c probably causes : nxest or nyest too small. if these param- +c eters are already large, it may also indicate that s is +c too small +c the approximation returned is the least-squares spline +c according to the current set of knots. the parameter fp +c gives the corresponding sum of squared residuals (fp>s). +c ier=2 : error. a theoretically impossible result was found during +c the iteration proces for finding a smoothing spline with +c fp = s. probably causes : s too small. +c there is an approximation returned but the corresponding +c sum of squared residuals does not satisfy the condition +c abs(fp-s)/s < tol. +c ier=3 : error. the maximal number of iterations maxit (set to 20 +c by the program) allowed for finding a smoothing spline +c with fp=s has been reached. probably causes : s too small +c there is an approximation returned but the corresponding +c sum of squared residuals does not satisfy the condition +c abs(fp-s)/s < tol. +c ier=10 : error. on entry, the input data are controlled on validity +c the following restrictions must be satisfied. +c -1<=iopt<=1, 1<=kx,ky<=5, mx>kx, my>ky, nxest>=2*kx+2, +c nyest>=2*ky+2, kwrk>=3+mx+my+nxest+nyest, +c lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ +c my*(ky+1) +max(my,nxest), +c xb<=x(i-1)<x(i)<=xe,i=2,..,mx,yb<=y(j-1)<y(j)<=ye,j=2,..,my +c if iopt=-1: 2*kx+2<=nx<=min(nxest,mx+kx+1) +c xb<tx(kx+2)<tx(kx+3)<...<tx(nx-kx-1)<xe +c 2*ky+2<=ny<=min(nyest,my+ky+1) +c yb<ty(ky+2)<ty(ky+3)<...<ty(ny-ky-1)<ye +c the schoenberg-whitney conditions, i.e. there must +c be subset of grid co-ordinates xx(p) and yy(q) such +c that tx(p) < xx(p) < tx(p+kx+1) ,p=1,...,nx-kx-1 +c ty(q) < yy(q) < ty(q+ky+1) ,q=1,...,ny-ky-1 +c if iopt>=0: s>=0 +c if s=0 : nxest>=mx+kx+1, nyest>=my+ky+1 +c if one of these conditions is found to be violated,control +c is immediately repassed to the calling program. in that +c case there is no approximation returned. +c +c further comments: +c regrid does not allow individual weighting of the data-values. +c so, if these were determined to widely different accuracies, then +c perhaps the general data set routine surfit should rather be used +c in spite of efficiency. +c by means of the parameter s, the user can control the tradeoff +c between closeness of fit and smoothness of fit of the approximation. +c if s is too large, the spline will be too smooth and signal will be +c lost ; if s is too small the spline will pick up too much noise. in +c the extreme cases the program will return an interpolating spline if +c s=0 and the least-squares polynomial (degrees kx,ky) if s is +c very large. between these extremes, a properly chosen s will result +c in a good compromise between closeness of fit and smoothness of fit. +c to decide whether an approximation, corresponding to a certain s is +c satisfactory the user is highly recommended to inspect the fits +c graphically. +c recommended values for s depend on the accuracy of the data values. +c if the user has an idea of the statistical errors on the data, he +c can also find a proper estimate for s. for, by assuming that, if he +c specifies the right s, regrid will return a spline s(x,y) which +c exactly reproduces the function underlying the data he can evaluate +c the sum((z(i,j)-s(x(i),y(j)))**2) to find a good estimate for this s +c for example, if he knows that the statistical errors on his z(i,j)- +c values is not greater than 0.1, he may expect that a good s should +c have a value not larger than mx*my*(0.1)**2. +c if nothing is known about the statistical error in z(i,j), s must +c be determined by trial and error, taking account of the comments +c above. the best is then to start with a very large value of s (to +c determine the least-squares polynomial and the corresponding upper +c bound fp0 for s) and then to progressively decrease the value of s +c ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... +c and more carefully as the approximation shows more detail) to +c obtain closer fits. +c to economize the search for a good s-value the program provides with +c different modes of computation. at the first call of the routine, or +c whenever he wants to restart with the initial set of knots the user +c must set iopt=0. +c if iopt=1 the program will continue with the set of knots found at +c the last call of the routine. this will save a lot of computation +c time if regrid is called repeatedly for different values of s. +c the number of knots of the spline returned and their location will +c depend on the value of s and on the complexity of the shape of the +c function underlying the data. if the computation mode iopt=1 +c is used, the knots returned may also depend on the s-values at +c previous calls (if these were smaller). therefore, if after a number +c of trials with different s-values and iopt=1, the user can finally +c accept a fit as satisfactory, it may be worthwhile for him to call +c regrid once more with the selected value for s but now with iopt=0. +c indeed, regrid may then return an approximation of the same quality +c of fit but with fewer knots and therefore better if data reduction +c is also an important objective for the user. +c the number of knots may also depend on the upper bounds nxest and +c nyest. indeed, if at a certain stage in regrid the number of knots +c in one direction (say nx) has reached the value of its upper bound +c (nxest), then from that moment on all subsequent knots are added +c in the other (y) direction. this may indicate that the value of +c nxest is too small. on the other hand, it gives the user the option +c of limiting the number of knots the routine locates in any direction +c for example, by setting nxest=2*kx+2 (the lowest allowable value for +c nxest), the user can indicate that he wants an approximation which +c is a simple polynomial of degree kx in the variable x. +c +c other subroutines required: +c fpback,fpbspl,fpregr,fpdisc,fpgivs,fpgrre,fprati,fprota,fpchec, +c fpknot +c +c references: +c dierckx p. : a fast algorithm for smoothing data on a rectangular +c grid while using spline functions, siam j.numer.anal. +c 19 (1982) 1286-1304. +c dierckx p. : a fast algorithm for smoothing data on a rectangular +c grid while using spline functions, report tw53, dept. +c computer science,k.u.leuven, 1980. +c dierckx p. : curve and surface fitting with splines, monographs on +c numerical analysis, oxford university press, 1993. +c +c author: +c p.dierckx +c dept. computer science, k.u. leuven +c celestijnenlaan 200a, b-3001 heverlee, belgium. +c e-mail : Paul.Dierckx@cs.kuleuven.ac.be +c +c creation date : may 1979 +c latest update : march 1989 +c +c .. + implicit none +c ..scalar arguments.. + real xb,xe,yb,ye,s,fp + integer iopt,mx,my,kx,ky,nxest,nyest,nx,ny,lwrk,kwrk,ier +c ..array arguments.. + real x(mx),y(my),z(mx*my),tx(nxest),ty(nyest), + * c((nxest-kx-1)*(nyest-ky-1)),wrk(lwrk) + integer iwrk(kwrk) +c ..local scalars.. + real tol + integer i,j,jwrk,kndx,kndy,knrx,knry,kwest,kx1,kx2,ky1,ky2, + * lfpx,lfpy,lwest,lww,maxit,nc,nminx,nminy,mz +c ..function references.. + integer max0 +c ..subroutine references.. +c fpregr,fpchec +c .. +c we set up the parameters tol and maxit. + maxit = 20 + tol = 0.1e-02 +c before starting computations a data check is made. if the input data +c are invalid, control is immediately repassed to the calling program. + ier = 10 + if(kx.le.0 .or. kx.gt.5) go to 70 + kx1 = kx+1 + kx2 = kx1+1 + if(ky.le.0 .or. ky.gt.5) go to 70 + ky1 = ky+1 + ky2 = ky1+1 + if(iopt.lt.(-1) .or. iopt.gt.1) go to 70 + nminx = 2*kx1 + if(mx.lt.kx1 .or. nxest.lt.nminx) go to 70 + nminy = 2*ky1 + if(my.lt.ky1 .or. nyest.lt.nminy) go to 70 + mz = mx*my + nc = (nxest-kx1)*(nyest-ky1) + lwest = 4+nxest*(my+2*kx2+1)+nyest*(2*ky2+1)+mx*kx1+ + * my*ky1+max0(nxest,my) + kwest = 3+mx+my+nxest+nyest + if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 70 + if(xb.gt.x(1) .or. xe.lt.x(mx)) go to 70 + do 10 i=2,mx + if(x(i-1).ge.x(i)) go to 70 + 10 continue + if(yb.gt.y(1) .or. ye.lt.y(my)) go to 70 + do 20 i=2,my + if(y(i-1).ge.y(i)) go to 70 + 20 continue + if(iopt.ge.0) go to 50 + if(nx.lt.nminx .or. nx.gt.nxest) go to 70 + j = nx + do 30 i=1,kx1 + tx(i) = xb + tx(j) = xe + j = j-1 + 30 continue + call fpchec(x,mx,tx,nx,kx,ier) + if(ier.ne.0) go to 70 + if(ny.lt.nminy .or. ny.gt.nyest) go to 70 + j = ny + do 40 i=1,ky1 + ty(i) = yb + ty(j) = ye + j = j-1 + 40 continue + call fpchec(y,my,ty,ny,ky,ier) + if(ier) 70,60,70 + 50 if(s.lt.0.) go to 70 + if(s.eq.0. .and. (nxest.lt.(mx+kx1) .or. nyest.lt.(my+ky1)) ) + * go to 70 + ier = 0 +c we partition the working space and determine the spline approximation + 60 lfpx = 5 + lfpy = lfpx+nxest + lww = lfpy+nyest + jwrk = lwrk-4-nxest-nyest + knrx = 4 + knry = knrx+mx + kndx = knry+my + kndy = kndx+nxest + call fpregr(iopt,x,mx,y,my,z,mz,xb,xe,yb,ye,kx,ky,s,nxest,nyest, + * tol,maxit,nc,nx,tx,ny,ty,c,fp,wrk(1),wrk(2),wrk(3),wrk(4), + * wrk(lfpx),wrk(lfpy),iwrk(1),iwrk(2),iwrk(3),iwrk(knrx), + * iwrk(knry),iwrk(kndx),iwrk(kndy),wrk(lww),jwrk,ier) + 70 return + end + diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/readme.txt b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/readme.txt new file mode 100644 index 000000000..47b9e311c --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/Dierckx_FitPack/readme.txt @@ -0,0 +1,50 @@ + FITPACK + +FITPACK is a collection of FORTRAN programs for CURVE and SURFACE FITTING with +SPLINES and TENSOR PRODUCT SPLINES. + +Features included are automatic knot selection, error smoothing and data +reduction. Besides the set of data points, the user merely has to provide a +single parameter, called the smoothing factor, to control the tradeoff between +closeness of fit and smoothness of fit. Confidence limits for this parameter +are available if the statistical errors on the data can be estimated. + +In addition to a standard routine for curve fitting over an interval and a +routine for fitting a bivariate spline function to a set of scattered data on a +rectangular domain, there are special programs for smoothing periodic functions, +parametric curves and surfaces, functions with convexity constraints. data over +the sphere and other non-rectangular approximation domains. Very efficient +surface fitting routines are provided for applications with data given either +on a rectangular, polar or spherical grid. Routines are included for evaluation, +differentiation and integration of the spline approximations. FITPACK also +contains an insertion algorithm and routines for calculating zeros and Fourier +coefficients of cubic splines. + +The subdirectory ex contains a test program for each of the 29 +main routines, e.g. the file mncurf.f contains a sample program for curfit, +mnperc.f a test program for percur.f, etc. Some of the test programs need some +input data. These can be found in the files with initials da, e.g. the program +in mnpasu.f needs the data which are stored in dapasu, etc. + +The user-level routines should be fairly well documented. Besides a parameter +description, there is a pointer to the lower level FITPACK routines, needed by +this particular routine. This may be useful in case only a restricted number +of fitting routines would be needed. A user guide of approximately 300 pages +can be ordered by sending a check of 25 US dollars to + Prof. P. Dierckx + Department of Computer Science + K.U.Leuven + Celestijnenlaan 200 A + B 3001, Heverlee, Belgium + +The mathematical fundamentals of FITPACK are described in the book: + Curve and Surface Fitting with Splines, by P. Dierckx, + Monographs on Numerical Analysis, Oxford University Press, 1993, + (ISBN 0-19-853441-8, 286 pages, 56 line figures) +In addition, potential FITPACK users will find there a lot of practical advice, +illustrated with many examples, both purely academic as well as taken from +real live. Comments on the software or the book may be addressed to the author +via email at the following address: Paul.Dierckx@cs.kuleuven.ac.be + +Finally, it should be noted that this software has no connection with +the FITPACK software package of Alan Cline. diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/NWTC_FFTPACK.f90 b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/NWTC_FFTPACK.f90 new file mode 100644 index 000000000..21a3840e3 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/NWTC_FFTPACK.f90 @@ -0,0 +1,859 @@ + ! NOTE: This MODULE isused in HydroDyn and TurbSim. + ! BJJ: 02/22/2008: Updated to work with NWTC_Library v1.01.09 + ! all Abort() functions changed to ProgAbort() + ! BJJ: 12/03/2010: Updated to add optional ErrStat return values + ! instead of aborting on errors (note not all changes documented) + ! BJJ: 12/20/2010: Updated to add defined type and remove global data variables + ! Also updated to check that transform has been initialized for the + ! correct type (to avoid having wSave too small) + ! ADP: 07/28/2014: Added in the complex FFT routines from fftpack v. 4.1 +!======================================================================= +MODULE NWTC_FFTPACK +!----------------------------------------------------------------------- +! DESCRIPTION OF THE INVERSE FOURIER TRANSFORM ROUTINE: +! +! Given an array, H, of N complex numbers, calculate an array, h, of N real +! numbers: +! h(J) = the sum from K=1,...,N of [ H(K)*exp(i*(J-1)*(K-1)*2*pi/N) ] +! for J = 1,...,N +! +! where: +! i=sqrt(-1) +! +! In order for h to be real, the real components of H must be an even function +! of frequency and the imaginary components of H must be an odd function of +! frequency. Thus, only the first N/2 + 1 values of H are unique. (The first +! N/2 + 1 are the positive frequencies including zero; the last N/2 - 1 values +! are the negative frequencies.) +! +! We accomplish this by defining a real array, R, where: +! R(1) = REAL( H(1) ), +! R(2) = REAL( H(2) ), R(3) = IMAG( H(2) ), +! R(4) = REAL( H(3) ), R(5) = IMAG( H(3) ),... +! R(N) = REAL( H(N/2 + 1) ). +! Note that the values of IMAG( H(1) ) and IMAG( H(N/2 + 1) ) must be zero for +! the result to be real, else the routine will abort. +! +! We return the array, r = h, of real numbers as calculated by: +! h(J) = r(J) = R(1) + (-1)**(J-1)*R(N) +! + the sum from K=2,...,N/2 of +! [ 2*R(2*K-2)*COS((K-1)*(J-1)*2*PI/N) +! -2*R(2*K-1)*SIN((K-1)*(J-1)*2*PI/N) ] +! for J = 1,...,N, where N is an even number +! +! The routine is most effecient when N is a product of small primes. +! +! If the Normalization flag is set to "TRUE" in the initialization, we +! normalize the result by 1/N. +!------------------------------------------------------------------------ +! DESCRIPTION OF THE COSINE TRANSFORM ROUTINE: +! +! Given an array, X, of N real numbers, calculate an array, x, of N real +! numbers: +! x(J) = X(1) + (-1)**(J-1)*X(N) +! + the sum from K=2,...,N-1 of [ 2*X(K)*COS((K-1)*(J-1)*PI/(N-1)) ] +! for J = 1,...,N, where N is an odd number +! +! The routine is most effecient when N-1 is a product of small primes. +! +! If the Normalization flag is set to "TRUE" in the initialization, we +! normalize the result by 1/(N-1). +!------------------------------------------------------------------------ +! DESCRIPTION OF THE SINE TRANSFORM ROUTINE: +! +! Given an array, X, of N real numbers, calculate an array, x, of N real +! numbers: +! x(1) = X(1) = 0 +! x(J) = the sum from K=2,...,N-1 of [ 2*X(K)*SIN((K-1)*(J-1)*PI/(N-1)) ] +! for J = 2,...,N-1, where N is an odd number +! x(N) = X(N) = 0 +! +! Note that the values of X(1) and X(N) must be zero, else the routine will +! abort. +! +! The routine is most effecient when N-1 is a product of small primes. +! +! If the Normalization flag is set to "TRUE" in the initialization, we +! normalize the result by 1/(N-1). +!------------------------------------------------------------------------ + +! We need the Precision module and the Abort() and +! Int2LStr() functions from the NWTC_IO module. + + USE NWTC_Library + + + IMPLICIT NONE + + INTEGER, PARAMETER, PRIVATE :: Undef_trans = -1 ! transformation type is undefined + INTEGER, PARAMETER, PRIVATE :: COS_trans = 1 ! COSINE transformation + INTEGER, PARAMETER, PRIVATE :: Fourier_trans = 2 ! FAST FOURIER transformation + INTEGER, PARAMETER, PRIVATE :: SIN_trans = 3 ! SINE transformation + + TYPE, PUBLIC :: FFT_DataType + PRIVATE + REAL(SiKi) :: InvN = 0.0_SiKi ! Normalization constant + REAL(SiKi), ALLOCATABLE :: wSave(:) ! Working array for performing transforms + INTEGER :: N = -1 ! Number of steps + LOGICAL :: Normalize = .FALSE. ! Whether or not to normalize + INTEGER :: TransformType = Undef_trans ! the type of transfer function this is for + END TYPE FFT_DataType + + +!------------------------------------------------------------------------ +CONTAINS + + SUBROUTINE ApplyCOST( TRH, FFT_Data, ErrStat ) + + ! Perform cosine transform. + + IMPLICIT NONE + + REAL(SiKi), INTENT(INOUT) :: TRH(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + LOGICAL :: TrapErrors + + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + ! Make sure the array isn't too small + + IF ( SIZE(TRH) < FFT_Data%N ) THEN + CALL ProgAbort( 'Error in call to cosine transform. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= COS_trans ) THEN + CALL ProgAbort( 'Error in call to cosine transform. FFT_Data not initialized for cosine transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Perform the cosine transform with a FFTpack routine + + CALL COST(FFT_Data%N, TRH, FFT_Data%wSave) ! FFTpack routine + + IF (FFT_Data%Normalize) THEN + TRH(1:FFT_Data%N) = FFT_Data%InvN * TRH(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplyCOST +!------------------------------------------------------------------------ + SUBROUTINE ApplyCFFT( TRH_complex_return, TRH_complex, FFT_Data, ErrStat ) + ! Perform Backward complex FFT: given TRH_complex, an array of complex numbers, + ! return an array TRH_complex_return, of complex numbers + + ! TRH_complex is of size FFT_Data%N/2 and represents the complex amplitude in frequency + ! space of only the positive frequencies. This is padded with zeros for the upper half + ! the frequency domain. + + ! TRH_complex_return is of size FFT_Data%N and represents the complex amplitude in the + ! time domain. + + IMPLICIT NONE + + COMPLEX(SiKi), INTENT(OUT) :: TRH_complex_return(:) + COMPLEX(SiKi), INTENT(IN) :: TRH_complex(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + REAL(SiKi), ALLOCATABLE :: TRH(:) ! real array to help process the complex-array that fftpack defines as IMPLICIT (real) + + INTEGER :: I + + INTEGER(IntKi) :: ErrStatTmp + LOGICAL :: TrapErrors + character(ErrMsgLen) :: ErrMsg + + ErrStatTmp = ErrID_None + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + ! Make sure the arrays aren't too small + IF ( ( SIZE(TRH_complex_return) < FFT_Data%N ) .OR. ( SIZE(TRH_complex) < ( FFT_Data%N/2 + 1 ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= Fourier_trans ) THEN + CALL ProgAbort( 'Error in call to FFT. FFT_Data not initialized for Fourier transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + + ! Make sure that the imaginary components at the zeroeth and largest + ! positive frequency are zero, else abort. + + IF ( .NOT. EqualRealNos( 0.0_SiKi, AIMAG( TRH_complex(1 ) ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. The imaginary component at the zeroeth frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + ELSE IF ( .NOT. EqualRealNos( 0.0_SiKi, AIMAG( TRH_complex(FFT_Data%N/2+1) ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. '// & + 'The imaginary component at the largest positive frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + + ! Populate the array for the frequency information. Only the first half is populated (note that + ! this algorithm does not make any assumptions about double sided conjugate pairing) + TRH_complex_return = CMPLX(0.0_SiKi,0.0_SiKi) + DO I=1,FFT_Data%N/2 + TRH_complex_return(I) = TRH_complex(I) + ENDDO + + + CALL AllocAry( TRH, 2*size(TRH_complex_return,1), 'ApplyCFFT:TRH', ErrStat, ErrMsg ) !allocate two real for each complex variable + IF (ErrStat >= AbortErrLev) THEN + CALL WrScr( TRIM(ErrMsg) ) + RETURN + END IF + + !TRH = TRANSFER(TRH_complex_return, TRH) ! this function apparently uses stack space and is causing stack overflow on large models + do i=1,size(TRH_complex_return,1) + TRH(2*i-1) = REAL(TRH_complex_return(i)) + TRH(2*i ) = AIMAG(TRH_complex_return(i)) + end do + + + CALL CFFTB(FFT_Data%N, TRH, FFT_Data%wSave) + + ! put real values back into complex array + !TRH = TRH_complex_return = TRANSFER(TRH, TRH_complex) ! this function apparently uses stack space and is causing stack overflow on large models + do i=1,size(TRH_complex_return,1) + TRH_complex_return(i) = CMPLX(TRH(2*i-1),TRH(2*i)) + end do + + DEALLOCATE(TRH) + + + ! Apply normalization, if any + + IF (FFT_Data%Normalize) THEN + TRH_complex_return(1:FFT_Data%N) = FFT_Data%InvN * TRH_complex_return(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplyCFFT + !------------------------------------------------------------------------ + SUBROUTINE ApplyCFFT_f( TRH_complex, FFT_Data, ErrStat ) +!FIXME: THIS ROUTINE HAS NOT BEEN TESTED!!!!! + ! Perform Forward complex FFT: + ! give an array TRH, of complex amplitudes in the time domain, + ! return TRH, a complex array in the frequency domain + + IMPLICIT NONE + + COMPLEX(SiKi), INTENT(INOUT) :: TRH_complex(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + + REAL(SiKi), ALLOCATABLE :: TRH(:) + + LOGICAL :: TrapErrors + character(ErrMsgLen) :: ErrMsg + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + ! Make sure the array isn't too small + + IF ( SIZE(TRH_complex) < FFT_Data%N ) THEN + CALL ProgAbort( 'Error in call to FFT. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= Fourier_trans ) THEN + CALL ProgAbort( 'Error in call to FFT. FFT_Data not initialized for Fourier transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Perform the FFT with a FFTpack routine + + CALL AllocAry( TRH, 2*size(TRH,1), 'ApplyCFFT_f:TRH', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) THEN + CALL WrScr( TRIM(ErrMsg) ) + RETURN + END IF + + TRH = TRANSFER(TRH_complex, TRH) + + CALL CFFTF(FFT_Data%N, TRH, FFT_Data%wSave) ! FFTpack routine + + ! put real values back into complex array + TRH_complex = TRANSFER(TRH, TRH_complex) + DEALLOCATE(TRH) + + + IF (FFT_Data%Normalize) THEN + TRH_complex(1:FFT_Data%N) = FFT_Data%InvN * TRH_complex(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplyCFFT_f + !------------------------------------------------------------------------ + SUBROUTINE ApplyFFT( TRH, FFT_Data, ErrStat ) + ! Perform Backward FFT: given TRH, a REAL array representing complex numbers, + ! return an array TRH, of real numbers. + ! CALL FOURTH ( TRH, NumSteps, 1, WorkT, NumSteps+2 ) ! Sandia + + IMPLICIT NONE + + REAL(SiKi), INTENT(INOUT) :: TRH(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + LOGICAL :: TrapErrors + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + + ! Make sure the array isn't too small + + IF ( SIZE(TRH) < FFT_Data%N ) THEN + CALL ProgAbort( 'Error in call to FFT. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= Fourier_trans ) THEN + CALL ProgAbort( 'Error in call to FFT. FFT_Data not initialized for Fourier transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Perform the FFT with a FFTpack routine + + CALL RFFTB(FFT_Data%N, TRH, FFT_Data%wSave) ! FFTpack routine + + IF (FFT_Data%Normalize) THEN + TRH(1:FFT_Data%N) = FFT_Data%InvN * TRH(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplyFFT + !------------------------------------------------------------------------ + SUBROUTINE ApplyFFT_f( TRH, FFT_Data, ErrStat ) + ! Perform Forward FFT: + ! give an array TRH, of real numbers, + ! return TRH, a REAL array representing complex numbers (magnitude and phase). + + IMPLICIT NONE + + REAL(SiKi), INTENT(INOUT) :: TRH(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + LOGICAL :: TrapErrors + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + ! Make sure the array isn't too small + + IF ( SIZE(TRH) < FFT_Data%N ) THEN + CALL ProgAbort( 'Error in call to FFT. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= Fourier_trans ) THEN + CALL ProgAbort( 'Error in call to FFT. FFT_Data not initialized for Fourier transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Perform the FFT with a FFTpack routine + + CALL RFFTF(FFT_Data%N, TRH, FFT_Data%wSave) ! FFTpack routine + + IF (FFT_Data%Normalize) THEN + TRH(1:FFT_Data%N) = FFT_Data%InvN * TRH(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplyFFT_f +!------------------------------------------------------------------------ + SUBROUTINE ApplyFFT_cx( TRH, TRH_complex, FFT_Data, ErrStat ) + ! Perform Backward FFT: given TRH, a REAL array representing complex numbers, + ! return an array TRH, of real numbers. + + IMPLICIT NONE + + REAL(SiKi), INTENT(OUT) :: TRH(:) + COMPLEX(SiKi), INTENT(IN) :: TRH_complex(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + INTEGER :: I + INTEGER :: Indx + + LOGICAL :: TrapErrors + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + + ! Make sure the arrays aren't too small + + IF ( ( SIZE(TRH) < FFT_Data%N ) .OR. ( SIZE(TRH_complex) < ( FFT_Data%N/2 + 1 ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + IF ( FFT_Data%TransformType /= Fourier_trans ) THEN + CALL ProgAbort( 'Error in call to FFT. FFT_Data not initialized for Fourier transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Make sure that the imaginary components at the zeroeth and largest + ! positive frequency are zero, else abort. + + IF ( .NOT. EqualRealNos( 0.0_SiKi, AIMAG( TRH_complex(1 ) ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. The imaginary component at the zeroeth frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + ELSE IF ( .NOT. EqualRealNos( 0.0_SiKi, AIMAG( TRH_complex(FFT_Data%N/2+1) ) ) ) THEN + CALL ProgAbort( 'Error in call to FFT. '// & + 'The imaginary component at the largest positive frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal ! The code can't get here unless PRESENT(ErrStat) + RETURN + END IF + + ! Initialize the TRH array with Complex numbers + + TRH(1) = REAL( TRH_complex(1 ) ) + + Indx = 1 + DO I=2,FFT_Data%N-2, 2 + Indx = Indx + 1 ! I/2 + 1 + + TRH(I) = REAL( TRH_complex(Indx) ) + TRH(I+1) = AIMAG( TRH_complex(Indx) ) + ENDDO + + TRH(FFT_Data%N) = REAL( TRH_complex(FFT_Data%N/2+1) ) + + + ! Perform the FFT with a FFTpack routine + + CALL RFFTB(FFT_Data%N, TRH, FFT_Data%wSave) + + IF (FFT_Data%Normalize) THEN + TRH(1:FFT_Data%N) = FFT_Data%InvN * TRH(1:FFT_Data%N) + ENDIF + + + END SUBROUTINE ApplyFFT_cx + !------------------------------------------------------------------------ + SUBROUTINE ApplySINT( TRH, FFT_Data, ErrStat ) + ! Perform sine transform. + + IMPLICIT NONE + + REAL(SiKi), INTENT(INOUT) :: TRH(:) + TYPE(FFT_DataType), INTENT(IN):: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL:: ErrStat + + LOGICAL :: TrapErrors + + + IF ( PRESENT(ErrStat) ) THEN + TrapErrors = .TRUE. + ErrStat = ErrID_None + ELSE + TrapErrors = .FALSE. + END IF + + + ! Make sure the array isn't too small + + IF ( SIZE(TRH) < FFT_Data%N ) THEN + CALL ProgAbort( 'Error in call to sine transform. Array size is not large enough.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + IF ( FFT_Data%TransformType /= SIN_trans ) THEN + CALL ProgAbort( 'Error in call to sine transform. FFT_Data not initialized for sine transform.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Make sure that the value at the zeroeth and largest positive + ! frequency are zero, else abort. + + IF ( TRH(1) /= 0.0 ) THEN + CALL ProgAbort( 'Error in call to FFT. The value at the zeroeth frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + ELSE IF ( TRH(FFT_Data%N) /= 0.0 ) THEN + CALL ProgAbort( 'Error in call to FFT. The value at the largest positive frequency must be zero.', TrapErrors ) + ErrStat = ErrID_Fatal + RETURN + END IF + + ! Perform the sine transform with a FFTpack routine + + CALL SINT(FFT_Data%N-2, TRH(2:FFT_Data%N-1), FFT_Data%wSave) ! FFTpack routine + + IF (FFT_Data%Normalize) THEN + TRH(1:FFT_Data%N) = FFT_Data%InvN * TRH(1:FFT_Data%N) + ENDIF + + END SUBROUTINE ApplySINT + !------------------------------------------------------------------------ + SUBROUTINE ExitCFFT(FFT_Data, ErrStat) + + TYPE(FFT_DataType), INTENT(INOUT) :: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat + INTEGER :: Alloc_Stat + + ! This subroutine cleans up the backward FFT working space + + FFT_Data%N = -1 + FFT_Data%TransformType = Undef_trans + + Alloc_Stat = 0 + IF ( ALLOCATED (FFT_Data%wSave) ) DEALLOCATE( FFT_Data%wSave, STAT=Alloc_Stat ) + + IF ( PRESENT( ErrStat ) ) ErrStat = Alloc_Stat + + END SUBROUTINE ExitCFFT + !------------------------------------------------------------------------ + SUBROUTINE ExitCOST(FFT_Data, ErrStat) + + TYPE(FFT_DataType), INTENT(INOUT) :: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat + INTEGER :: Alloc_Stat + + + ! This subroutine cleans up the cosine transform working space + + FFT_Data%N = -1 + FFT_Data%TransformType = Undef_trans + + Alloc_Stat = 0 + IF ( ALLOCATED (FFT_Data%wSave) ) DEALLOCATE( FFT_Data%wSave, STAT=Alloc_Stat ) + + IF ( PRESENT( ErrStat ) ) ErrStat = Alloc_Stat + + END SUBROUTINE ExitCOST + !------------------------------------------------------------------------ + SUBROUTINE ExitFFT(FFT_Data, ErrStat) + + TYPE(FFT_DataType), INTENT(INOUT) :: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat + INTEGER :: Alloc_Stat + + ! This subroutine cleans up the backward FFT working space + + FFT_Data%N = -1 + FFT_Data%TransformType = Undef_trans + + Alloc_Stat = 0 + IF ( ALLOCATED (FFT_Data%wSave) ) DEALLOCATE( FFT_Data%wSave, STAT=Alloc_Stat ) + + IF ( PRESENT( ErrStat ) ) ErrStat = Alloc_Stat + + END SUBROUTINE ExitFFT + !------------------------------------------------------------------------ + SUBROUTINE ExitSINT(FFT_Data, ErrStat) + + TYPE(FFT_DataType), INTENT(INOUT) :: FFT_Data ! the handle to this instance of the FFT Module + INTEGER, INTENT(OUT), OPTIONAL :: ErrStat + INTEGER :: Alloc_Stat + + ! This subroutine cleans up the sine transform working space + + FFT_Data%N = -1 + FFT_Data%TransformType = Undef_trans + + Alloc_Stat = 0 + IF ( ALLOCATED (FFT_Data%wSave) ) DEALLOCATE( FFT_Data%wSave, STAT=Alloc_Stat ) + + IF ( PRESENT( ErrStat ) ) ErrStat = Alloc_Stat + + END SUBROUTINE ExitSINT + !------------------------------------------------------------------------ + SUBROUTINE InitCOST( NumSteps, FFT_Data, NormalizeIn, ErrStat ) + + ! This subroutine initializes the cosine transform working space + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: NumSteps ! Number of steps in the array + INTEGER :: Sttus ! Array allocation status + + TYPE(FFT_DataType),INTENT(OUT):: FFT_Data ! the handle to this instance of the FFT Module + LOGICAL, INTENT(IN), OPTIONAL :: NormalizeIn ! Whether or not to normalize + INTEGER, INTENT(OUT),OPTIONAL :: ErrStat ! returns non-zero if an error occurred + + + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + + ! Number of timesteps in the time series returned from the cosine transform + ! N should be odd: + + FFT_Data%N = NumSteps + + IF ( MOD(FFT_Data%N,2) /= 1 ) THEN + CALL ProgAbort ( 'The number of steps in the cosine transform must be odd', PRESENT(ErrStat) ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Determine if we should normalize the cosine transform: + + IF ( PRESENT( NormalizeIn ) ) THEN + FFT_Data%Normalize = NormalizeIn + FFT_Data%InvN = 1. / ( FFT_Data%N - 1 ) + ELSE + FFT_Data%Normalize = .FALSE. + ENDIF + + ! According to FFTPACK documentation, the working array must be at + ! least size 3N+15 + + ALLOCATE ( FFT_Data%wSave(3*FFT_Data%N + 15) , STAT=Sttus ) + + IF ( Sttus /= 0 ) THEN + CALL ProgAbort ( 'Error allocating memory for the cosine transform working array.', PRESENT(ErrStat) ) + ErrStat = Sttus + RETURN + ENDIF + + + ! Initialize the FFTPACK working space + + CALL COSTI(FFT_Data%N, FFT_Data%wSave) + + FFT_Data%TransformType = COS_trans + + + END SUBROUTINE InitCOST + !------------------------------------------------------------------------ + SUBROUTINE InitCFFT( NumSteps, FFT_Data, NormalizeIn, ErrStat ) + + ! This subroutine initializes the backward FFT working space + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: NumSteps ! Number of steps in the array + INTEGER :: Sttus ! Array allocation status + + TYPE(FFT_DataType),INTENT(OUT):: FFT_Data ! the handle to this instance of the FFT Module + LOGICAL, INTENT(IN), OPTIONAL :: NormalizeIn ! Whether or not to normalize the FFT + INTEGER, INTENT(OUT),OPTIONAL :: ErrStat ! returns non-zero if an error occurred + + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + + ! Number of timesteps in the time series returned from the backward FFT + ! N should be even: + + FFT_Data%N = NumSteps + + IF ( MOD(FFT_Data%N,2) /= 0 ) THEN + CALL ProgAbort ( 'The number of steps in the FFT must be even', PRESENT(ErrStat) ) ! For this Real FFT + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Determine if we should normalize the FFT + + IF ( PRESENT( NormalizeIn ) ) THEN + FFT_Data%Normalize = NormalizeIn + FFT_Data%InvN = 1. / FFT_Data%N + ELSE + FFT_Data%Normalize = .FALSE. + ENDIF + + ! According to FFTPACK documentation, the working array must be at + ! least size 4N+15 + + ALLOCATE ( FFT_Data%wSave(4*FFT_Data%N + 15) , STAT=Sttus ) + + IF ( Sttus /= 0 ) THEN + CALL ProgAbort ( 'Error allocating memory for the complex FFT working array.', PRESENT(ErrStat) ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + + ! Initialize the FFTPACK working space + + CALL CFFTI(FFT_Data%N, FFT_Data%wSave) + + + FFT_Data%TransformType = Fourier_trans + + END SUBROUTINE InitCFFT + !------------------------------------------------------------------------ + SUBROUTINE InitFFT( NumSteps, FFT_Data, NormalizeIn, ErrStat ) + + ! This subroutine initializes the backward FFT working space + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: NumSteps ! Number of steps in the array + INTEGER :: Sttus ! Array allocation status + + TYPE(FFT_DataType),INTENT(OUT):: FFT_Data ! the handle to this instance of the FFT Module + LOGICAL, INTENT(IN), OPTIONAL :: NormalizeIn ! Whether or not to normalize the FFT + INTEGER, INTENT(OUT),OPTIONAL :: ErrStat ! returns non-zero if an error occurred + + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + + ! Number of timesteps in the time series returned from the backward FFT + ! N should be even: + + FFT_Data%N = NumSteps + + IF ( MOD(FFT_Data%N,2) /= 0 ) THEN + CALL ProgAbort ( 'The number of steps in the FFT must be even', PRESENT(ErrStat) ) ! For this Real FFT + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Determine if we should normalize the FFT + + IF ( PRESENT( NormalizeIn ) ) THEN + FFT_Data%Normalize = NormalizeIn + FFT_Data%InvN = 1. / FFT_Data%N + ELSE + FFT_Data%Normalize = .FALSE. + FFT_Data%InvN = 1. + ENDIF + + ! According to FFTPACK documentation, the working array must be at + ! least size 2N+15 + + ALLOCATE ( FFT_Data%wSave(2*FFT_Data%N + 15) , STAT=Sttus ) + + IF ( Sttus /= 0 ) THEN + CALL ProgAbort ( 'Error allocating memory for the FFT working array.', PRESENT(ErrStat) ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + + ! Initialize the FFTPACK working space + + CALL RFFTI(FFT_Data%N, FFT_Data%wSave) + + FFT_Data%TransformType = Fourier_trans + + END SUBROUTINE InitFFT + !------------------------------------------------------------------------ + SUBROUTINE InitSINT( NumSteps, FFT_Data, NormalizeIn, ErrStat ) + + ! This subroutine initializes the sine transform working space + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: NumSteps ! Number of steps in the array + INTEGER :: Sttus ! Array allocation status + + TYPE(FFT_DataType),INTENT(OUT):: FFT_Data ! the handle to this instance of the FFT Module + LOGICAL, INTENT(IN), OPTIONAL :: NormalizeIn ! Whether or not to normalize + INTEGER, INTENT(OUT),OPTIONAL :: ErrStat ! returns non-zero if an error occurred + + + IF ( PRESENT(ErrStat) ) ErrStat = ErrID_None + + ! Number of timesteps in the time series returned from the sine transform + ! N should be odd: + + FFT_Data%N = NumSteps + + IF ( MOD(FFT_Data%N,2) /= 1 ) THEN + CALL ProgAbort ( 'The number of steps in the sine transform must be odd.', PRESENT(ErrStat) ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + ! Determine if we should normalize the sine transform: + + IF ( PRESENT( NormalizeIn ) ) THEN + FFT_Data%Normalize = NormalizeIn + FFT_Data%InvN = 1. / ( FFT_Data%N - 1 ) + ELSE + FFT_Data%Normalize = .FALSE. + ENDIF + + ! According to FFTPACK documentation, the working array must be at + ! least size 2.5N+15; however, our N is +2 greater than their N + + ALLOCATE ( FFT_Data%wSave( CEILING( 2.5*(FFT_Data%N-2) ) + 15 ) , STAT=Sttus ) + + IF ( Sttus /= 0 ) THEN + CALL ProgAbort ( 'Error allocating memory for the sine transform working array.', PRESENT(ErrStat) ) + ErrStat = ErrID_Fatal + RETURN + ENDIF + + + ! Initialize the FFTPACK working space + + CALL SINTI(FFT_Data%N-2, FFT_Data%wSave) + + + FFT_Data%TransformType = SIN_trans + + + END SUBROUTINE InitSINT + !------------------------------------------------------------------------ + + +END MODULE NWTC_FFTPACK +!======================================================================= diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/doc.txt b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/doc.txt new file mode 100644 index 000000000..4a08e2ebe --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/doc.txt @@ -0,0 +1,866 @@ + + FFTPACK + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + version 4 april 1985 + + a package of fortran subprograms for the fast fourier + transform of periodic and other symmetric sequences + + by + + paul n swarztrauber + + national center for atmospheric research boulder,colorado 80307 + + which is sponsored by the national science foundation + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +this package consists of programs which perform fast fourier +transforms for both complex and real periodic sequences and +certain other symmetric sequences that are listed below. + +1. rffti initialize rfftf and rfftb +2. rfftf forward transform of a real periodic sequence +3. rfftb backward transform of a real coefficient array + +4. ezffti initialize ezfftf and ezfftb +5. ezfftf a simplified real periodic forward transform +6. ezfftb a simplified real periodic backward transform + +7. sinti initialize sint +8. sint sine transform of a real odd sequence + +9. costi initialize cost +10. cost cosine transform of a real even sequence + +11. sinqi initialize sinqf and sinqb +12. sinqf forward sine transform with odd wave numbers +13. sinqb unnormalized inverse of sinqf + +14. cosqi initialize cosqf and cosqb +15. cosqf forward cosine transform with odd wave numbers +16. cosqb unnormalized inverse of cosqf + +17. cffti initialize cfftf and cfftb +18. cfftf forward transform of a complex periodic sequence +19. cfftb unnormalized inverse of cfftf + + +****************************************************************** + +subroutine rffti(n,wsave) + + **************************************************************** + +subroutine rffti initializes the array wsave which is used in +both rfftf and rfftb. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed. + +output parameter + +wsave a work array which must be dimensioned at least 2*n+15. + the same work array can be used for both rfftf and rfftb + as long as n remains unchanged. different wsave arrays + are required for different values of n. the contents of + wsave must not be changed between calls of rfftf or rfftb. + +****************************************************************** + +subroutine rfftf(n,r,wsave) + +****************************************************************** + +subroutine rfftf computes the fourier coefficients of a real +perodic sequence (fourier analysis). the transform is defined +below at output parameter r. + +input parameters + +n the length of the array r to be transformed. the method + is most efficient when n is a product of small primes. + n may change so long as different work arrays are provided + +r a real array of length n which contains the sequence + to be transformed + +wsave a work array which must be dimensioned at least 2*n+15. + in the program that calls rfftf. the wsave array must be + initialized by calling subroutine rffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by rfftf and rfftb. + + +output parameters + +r r(1) = the sum from i=1 to i=n of r(i) + + if n is even set l =n/2 , if n is odd set l = (n+1)/2 + + then for k = 2,...,l + + r(2*k-2) = the sum from i = 1 to i = n of + + r(i)*cos((k-1)*(i-1)*2*pi/n) + + r(2*k-1) = the sum from i = 1 to i = n of + + -r(i)*sin((k-1)*(i-1)*2*pi/n) + + if n is even + + r(n) = the sum from i = 1 to i = n of + + (-1)**(i-1)*r(i) + + ***** note + this transform is unnormalized since a call of rfftf + followed by a call of rfftb will multiply the input + sequence by n. + +wsave contains results which must not be destroyed between + calls of rfftf or rfftb. + + +****************************************************************** + +subroutine rfftb(n,r,wsave) + +****************************************************************** + +subroutine rfftb computes the real perodic sequence from its +fourier coefficients (fourier synthesis). the transform is defined +below at output parameter r. + +input parameters + +n the length of the array r to be transformed. the method + is most efficient when n is a product of small primes. + n may change so long as different work arrays are provided + +r a real array of length n which contains the sequence + to be transformed + +wsave a work array which must be dimensioned at least 2*n+15. + in the program that calls rfftb. the wsave array must be + initialized by calling subroutine rffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by rfftf and rfftb. + + +output parameters + +r for n even and for i = 1,...,n + + r(i) = r(1)+(-1)**(i-1)*r(n) + + plus the sum from k=2 to k=n/2 of + + 2.*r(2*k-2)*cos((k-1)*(i-1)*2*pi/n) + + -2.*r(2*k-1)*sin((k-1)*(i-1)*2*pi/n) + + for n odd and for i = 1,...,n + + r(i) = r(1) plus the sum from k=2 to k=(n+1)/2 of + + 2.*r(2*k-2)*cos((k-1)*(i-1)*2*pi/n) + + -2.*r(2*k-1)*sin((k-1)*(i-1)*2*pi/n) + + ***** note + this transform is unnormalized since a call of rfftf + followed by a call of rfftb will multiply the input + sequence by n. + +wsave contains results which must not be destroyed between + calls of rfftb or rfftf. + + +****************************************************************** + +subroutine ezffti(n,wsave) + +****************************************************************** + +subroutine ezffti initializes the array wsave which is used in +both ezfftf and ezfftb. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed. + +output parameter + +wsave a work array which must be dimensioned at least 3*n+15. + the same work array can be used for both ezfftf and ezfftb + as long as n remains unchanged. different wsave arrays + are required for different values of n. + + +****************************************************************** + +subroutine ezfftf(n,r,azero,a,b,wsave) + +****************************************************************** + +subroutine ezfftf computes the fourier coefficients of a real +perodic sequence (fourier analysis). the transform is defined +below at output parameters azero,a and b. ezfftf is a simplified +but slower version of rfftf. + +input parameters + +n the length of the array r to be transformed. the method + is must efficient when n is the product of small primes. + +r a real array of length n which contains the sequence + to be transformed. r is not destroyed. + + +wsave a work array which must be dimensioned at least 3*n+15. + in the program that calls ezfftf. the wsave array must be + initialized by calling subroutine ezffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by ezfftf and ezfftb. + +output parameters + +azero the sum from i=1 to i=n of r(i)/n + +a,b for n even b(n/2)=0. and a(n/2) is the sum from i=1 to + i=n of (-1)**(i-1)*r(i)/n + + for n even define kmax=n/2-1 + for n odd define kmax=(n-1)/2 + + then for k=1,...,kmax + + a(k) equals the sum from i=1 to i=n of + + 2./n*r(i)*cos(k*(i-1)*2*pi/n) + + b(k) equals the sum from i=1 to i=n of + + 2./n*r(i)*sin(k*(i-1)*2*pi/n) + + +****************************************************************** + +subroutine ezfftb(n,r,azero,a,b,wsave) + +****************************************************************** + +subroutine ezfftb computes a real perodic sequence from its +fourier coefficients (fourier synthesis). the transform is +defined below at output parameter r. ezfftb is a simplified +but slower version of rfftb. + +input parameters + +n the length of the output array r. the method is most + efficient when n is the product of small primes. + +azero the constant fourier coefficient + +a,b arrays which contain the remaining fourier coefficients + these arrays are not destroyed. + + the length of these arrays depends on whether n is even or + odd. + + if n is even n/2 locations are required + if n is odd (n-1)/2 locations are required + +wsave a work array which must be dimensioned at least 3*n+15. + in the program that calls ezfftb. the wsave array must be + initialized by calling subroutine ezffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by ezfftf and ezfftb. + + +output parameters + +r if n is even define kmax=n/2 + if n is odd define kmax=(n-1)/2 + + then for i=1,...,n + + r(i)=azero plus the sum from k=1 to k=kmax of + + a(k)*cos(k*(i-1)*2*pi/n)+b(k)*sin(k*(i-1)*2*pi/n) + +********************* complex notation ************************** + + for j=1,...,n + + r(j) equals the sum from k=-kmax to k=kmax of + + c(k)*exp(i*k*(j-1)*2*pi/n) + + where + + c(k) = .5*cmplx(a(k),-b(k)) for k=1,...,kmax + + c(-k) = conjg(c(k)) + + c(0) = azero + + and i=sqrt(-1) + +*************** amplitude - phase notation *********************** + + for i=1,...,n + + r(i) equals azero plus the sum from k=1 to k=kmax of + + alpha(k)*cos(k*(i-1)*2*pi/n+beta(k)) + + where + + alpha(k) = sqrt(a(k)*a(k)+b(k)*b(k)) + + cos(beta(k))=a(k)/alpha(k) + + sin(beta(k))=-b(k)/alpha(k) + +****************************************************************** + +subroutine sinti(n,wsave) + +****************************************************************** + +subroutine sinti initializes the array wsave which is used in +subroutine sint. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed. the method + is most efficient when n+1 is a product of small primes. + +output parameter + +wsave a work array with at least int(2.5*n+15) locations. + different wsave arrays are required for different values + of n. the contents of wsave must not be changed between + calls of sint. + +****************************************************************** + +subroutine sint(n,x,wsave) + +****************************************************************** + +subroutine sint computes the discrete fourier sine transform +of an odd sequence x(i). the transform is defined below at +output parameter x. + +sint is the unnormalized inverse of itself since a call of sint +followed by another call of sint will multiply the input sequence +x by 2*(n+1). + +the array wsave which is used by subroutine sint must be +initialized by calling subroutine sinti(n,wsave). + +input parameters + +n the length of the sequence to be transformed. the method + is most efficient when n+1 is the product of small primes. + +x an array which contains the sequence to be transformed + + +wsave a work array with dimension at least int(2.5*n+15) + in the program that calls sint. the wsave array must be + initialized by calling subroutine sinti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i)= the sum from k=1 to k=n + + 2*x(k)*sin(k*i*pi/(n+1)) + + a call of sint followed by another call of + sint will multiply the sequence x by 2*(n+1). + hence sint is the unnormalized inverse + of itself. + +wsave contains initialization calculations which must not be + destroyed between calls of sint. + +****************************************************************** + +subroutine costi(n,wsave) + +****************************************************************** + +subroutine costi initializes the array wsave which is used in +subroutine cost. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed. the method + is most efficient when n-1 is a product of small primes. + +output parameter + +wsave a work array which must be dimensioned at least 3*n+15. + different wsave arrays are required for different values + of n. the contents of wsave must not be changed between + calls of cost. + +****************************************************************** + +subroutine cost(n,x,wsave) + +****************************************************************** + +subroutine cost computes the discrete fourier cosine transform +of an even sequence x(i). the transform is defined below at output +parameter x. + +cost is the unnormalized inverse of itself since a call of cost +followed by another call of cost will multiply the input sequence +x by 2*(n-1). the transform is defined below at output parameter x + +the array wsave which is used by subroutine cost must be +initialized by calling subroutine costi(n,wsave). + +input parameters + +n the length of the sequence x. n must be greater than 1. + the method is most efficient when n-1 is a product of + small primes. + +x an array which contains the sequence to be transformed + +wsave a work array which must be dimensioned at least 3*n+15 + in the program that calls cost. the wsave array must be + initialized by calling subroutine costi(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i) = x(1)+(-1)**(i-1)*x(n) + + + the sum from k=2 to k=n-1 + + 2*x(k)*cos((k-1)*(i-1)*pi/(n-1)) + + a call of cost followed by another call of + cost will multiply the sequence x by 2*(n-1) + hence cost is the unnormalized inverse + of itself. + +wsave contains initialization calculations which must not be + destroyed between calls of cost. + +****************************************************************** + +subroutine sinqi(n,wsave) + +****************************************************************** + +subroutine sinqi initializes the array wsave which is used in +both sinqf and sinqb. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed. the method + is most efficient when n is a product of small primes. + +output parameter + +wsave a work array which must be dimensioned at least 3*n+15. + the same work array can be used for both sinqf and sinqb + as long as n remains unchanged. different wsave arrays + are required for different values of n. the contents of + wsave must not be changed between calls of sinqf or sinqb. + +****************************************************************** + +subroutine sinqf(n,x,wsave) + +****************************************************************** + +subroutine sinqf computes the fast fourier transform of quarter +wave data. that is , sinqf computes the coefficients in a sine +series representation with only odd wave numbers. the transform +is defined below at output parameter x. + +sinqb is the unnormalized inverse of sinqf since a call of sinqf +followed by a call of sinqb will multiply the input sequence x +by 4*n. + +the array wsave which is used by subroutine sinqf must be +initialized by calling subroutine sinqi(n,wsave). + + +input parameters + +n the length of the array x to be transformed. the method + is most efficient when n is a product of small primes. + +x an array which contains the sequence to be transformed + +wsave a work array which must be dimensioned at least 3*n+15. + in the program that calls sinqf. the wsave array must be + initialized by calling subroutine sinqi(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i) = (-1)**(i-1)*x(n) + + + the sum from k=1 to k=n-1 of + + 2*x(k)*sin((2*i-1)*k*pi/(2*n)) + + a call of sinqf followed by a call of + sinqb will multiply the sequence x by 4*n. + therefore sinqb is the unnormalized inverse + of sinqf. + +wsave contains initialization calculations which must not + be destroyed between calls of sinqf or sinqb. + +****************************************************************** + +subroutine sinqb(n,x,wsave) + +****************************************************************** + +subroutine sinqb computes the fast fourier transform of quarter +wave data. that is , sinqb computes a sequence from its +representation in terms of a sine series with odd wave numbers. +the transform is defined below at output parameter x. + +sinqf is the unnormalized inverse of sinqb since a call of sinqb +followed by a call of sinqf will multiply the input sequence x +by 4*n. + +the array wsave which is used by subroutine sinqb must be +initialized by calling subroutine sinqi(n,wsave). + + +input parameters + +n the length of the array x to be transformed. the method + is most efficient when n is a product of small primes. + +x an array which contains the sequence to be transformed + +wsave a work array which must be dimensioned at least 3*n+15. + in the program that calls sinqb. the wsave array must be + initialized by calling subroutine sinqi(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i)= the sum from k=1 to k=n of + + 4*x(k)*sin((2k-1)*i*pi/(2*n)) + + a call of sinqb followed by a call of + sinqf will multiply the sequence x by 4*n. + therefore sinqf is the unnormalized inverse + of sinqb. + +wsave contains initialization calculations which must not + be destroyed between calls of sinqb or sinqf. + +****************************************************************** + +subroutine cosqi(n,wsave) + +****************************************************************** + +subroutine cosqi initializes the array wsave which is used in +both cosqf and cosqb. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the array to be transformed. the method + is most efficient when n is a product of small primes. + +output parameter + +wsave a work array which must be dimensioned at least 3*n+15. + the same work array can be used for both cosqf and cosqb + as long as n remains unchanged. different wsave arrays + are required for different values of n. the contents of + wsave must not be changed between calls of cosqf or cosqb. + +****************************************************************** + +subroutine cosqf(n,x,wsave) + +****************************************************************** + +subroutine cosqf computes the fast fourier transform of quarter +wave data. that is , cosqf computes the coefficients in a cosine +series representation with only odd wave numbers. the transform +is defined below at output parameter x + +cosqf is the unnormalized inverse of cosqb since a call of cosqf +followed by a call of cosqb will multiply the input sequence x +by 4*n. + +the array wsave which is used by subroutine cosqf must be +initialized by calling subroutine cosqi(n,wsave). + + +input parameters + +n the length of the array x to be transformed. the method + is most efficient when n is a product of small primes. + +x an array which contains the sequence to be transformed + +wsave a work array which must be dimensioned at least 3*n+15 + in the program that calls cosqf. the wsave array must be + initialized by calling subroutine cosqi(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i) = x(1) plus the sum from k=2 to k=n of + + 2*x(k)*cos((2*i-1)*(k-1)*pi/(2*n)) + + a call of cosqf followed by a call of + cosqb will multiply the sequence x by 4*n. + therefore cosqb is the unnormalized inverse + of cosqf. + +wsave contains initialization calculations which must not + be destroyed between calls of cosqf or cosqb. + +****************************************************************** + +subroutine cosqb(n,x,wsave) + +****************************************************************** + +subroutine cosqb computes the fast fourier transform of quarter +wave data. that is , cosqb computes a sequence from its +representation in terms of a cosine series with odd wave numbers. +the transform is defined below at output parameter x. + +cosqb is the unnormalized inverse of cosqf since a call of cosqb +followed by a call of cosqf will multiply the input sequence x +by 4*n. + +the array wsave which is used by subroutine cosqb must be +initialized by calling subroutine cosqi(n,wsave). + + +input parameters + +n the length of the array x to be transformed. the method + is most efficient when n is a product of small primes. + +x an array which contains the sequence to be transformed + +wsave a work array that must be dimensioned at least 3*n+15 + in the program that calls cosqb. the wsave array must be + initialized by calling subroutine cosqi(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + +output parameters + +x for i=1,...,n + + x(i)= the sum from k=1 to k=n of + + 4*x(k)*cos((2*k-1)*(i-1)*pi/(2*n)) + + a call of cosqb followed by a call of + cosqf will multiply the sequence x by 4*n. + therefore cosqf is the unnormalized inverse + of cosqb. + +wsave contains initialization calculations which must not + be destroyed between calls of cosqb or cosqf. + +****************************************************************** + +subroutine cffti(n,wsave) + +****************************************************************** + +subroutine cffti initializes the array wsave which is used in +both cfftf and cfftb. the prime factorization of n together with +a tabulation of the trigonometric functions are computed and +stored in wsave. + +input parameter + +n the length of the sequence to be transformed + +output parameter + +wsave a work array which must be dimensioned at least 4*n+15 + the same work array can be used for both cfftf and cfftb + as long as n remains unchanged. different wsave arrays + are required for different values of n. the contents of + wsave must not be changed between calls of cfftf or cfftb. + +****************************************************************** + +subroutine cfftf(n,c,wsave) + +****************************************************************** + +subroutine cfftf computes the forward complex discrete fourier +transform (the fourier analysis). equivalently , cfftf computes +the fourier coefficients of a complex periodic sequence. +the transform is defined below at output parameter c. + +the transform is not normalized. to obtain a normalized transform +the output must be divided by n. otherwise a call of cfftf +followed by a call of cfftb will multiply the sequence by n. + +the array wsave which is used by subroutine cfftf must be +initialized by calling subroutine cffti(n,wsave). + +input parameters + + +n the length of the complex sequence c. the method is + more efficient when n is the product of small primes. n + +c a complex array of length n which contains the sequence + +wsave a real work array which must be dimensioned at least 4n+15 + in the program that calls cfftf. the wsave array must be + initialized by calling subroutine cffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by cfftf and cfftb. + +output parameters + +c for j=1,...,n + + c(j)=the sum from k=1,...,n of + + c(k)*exp(-i*(j-1)*(k-1)*2*pi/n) + + where i=sqrt(-1) + +wsave contains initialization calculations which must not be + destroyed between calls of subroutine cfftf or cfftb + +****************************************************************** + +subroutine cfftb(n,c,wsave) + +****************************************************************** + +subroutine cfftb computes the backward complex discrete fourier +transform (the fourier synthesis). equivalently , cfftb computes +a complex periodic sequence from its fourier coefficients. +the transform is defined below at output parameter c. + +a call of cfftf followed by a call of cfftb will multiply the +sequence by n. + +the array wsave which is used by subroutine cfftb must be +initialized by calling subroutine cffti(n,wsave). + +input parameters + + +n the length of the complex sequence c. the method is + more efficient when n is the product of small primes. + +c a complex array of length n which contains the sequence + +wsave a real work array which must be dimensioned at least 4n+15 + in the program that calls cfftb. the wsave array must be + initialized by calling subroutine cffti(n,wsave) and a + different wsave array must be used for each different + value of n. this initialization does not have to be + repeated so long as n remains unchanged thus subsequent + transforms can be obtained faster than the first. + the same wsave array can be used by cfftf and cfftb. + +output parameters + +c for j=1,...,n + + c(j)=the sum from k=1,...,n of + + c(k)*exp(i*(j-1)*(k-1)*2*pi/n) + + where i=sqrt(-1) + +wsave contains initialization calculations which must not be + destroyed between calls of subroutine cfftf or cfftb + + + +["send index for vfftpk" describes a vectorized version of fftpack] + diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/fftpack4.1.f b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/fftpack4.1.f new file mode 100644 index 000000000..34cee05a8 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/fftpack/fftpack4.1.f @@ -0,0 +1,2327 @@ +#define IMPLICIT_STATEMENT IMPLICIT INTEGER(4) (I-N), REAL(4) (A-H, O-Z) +#define IFAC_TYPE REAL(4) + +C -------------------------------------------------------------- +C Source code obtained from FFTPACK version 4.1 , available at +C http://www.scd.ucar.edu/softlib/mathlib.html +C -------------------------------------------------------------- +C SUBROUTINE RFFTI(N,WSAVE) +C +C SUBROUTINE RFFTI INITIALIZES THE ARRAY WSAVE WHICH IS USED IN +C BOTH RFFTF AND RFFTB. THE PRIME FACTORIZATION OF N TOGETHER WITH +C A TABULATION OF THE TRIGONOMETRIC FUNCTIONS ARE COMPUTED AND +C STORED IN WSAVE. +C +C INPUT PARAMETER +C +C N THE LENGTH OF THE SEQUENCE TO BE TRANSFORMED. +C +C OUTPUT PARAMETER +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 2*N+15. +C THE SAME WORK ARRAY CAN BE USED FOR BOTH RFFTF AND RFFTB +C AS LONG AS N REMAINS UNCHANGED. DIFFERENT WSAVE ARRAYS +C ARE REQUIRED FOR DIFFERENT VALUES OF N. THE CONTENTS OF +C WSAVE MUST NOT BE CHANGED BETWEEN CALLS OF RFFTF OR RFFTB. +C + SUBROUTINE RFFTI (N,WSAVE) + IMPLICIT_STATEMENT + DIMENSION WSAVE(*) +C + IF (N .EQ. 1) RETURN + CALL RFFTI1 (N,WSAVE(N+1),WSAVE(2*N+1)) + RETURN + END + + + SUBROUTINE RFFTI1 (N,WA,IFAC) + IMPLICIT_STATEMENT +!!bjj START (fix for compatibility in double precision): +!! also note I added nint() around places where IFAC is on the right-hand side of the equation +! DIMENSION WA(*) ,IFAC(*) ,NTRYH(4) + IFAC_TYPE, DIMENSION(*) :: IFAC + DIMENSION WA(*) ,NTRYH(4) +!!bjj END + DATA NTRYH(1),NTRYH(2),NTRYH(3),NTRYH(4)/4,2,3,5/ + NL = N + NF = 0 + J = 0 + 101 J = J+1 + IF (J-4) 102,102,103 + 102 NTRY = NTRYH(J) + GO TO 104 + 103 NTRY = NTRY+2 + 104 NQ = NL/NTRY + NR = NL-NTRY*NQ + IF (NR) 101,105,101 + 105 NF = NF+1 + IFAC(NF+2) = NTRY + NL = NQ + IF (NTRY .NE. 2) GO TO 107 + IF (NF .EQ. 1) GO TO 107 + DO 106 I=2,NF + IB = NF-I+2 + IFAC(IB+2) = nint(IFAC(IB+1)) + 106 CONTINUE + IFAC(3) = 2 + 107 IF (NL .NE. 1) GO TO 104 + IFAC(1) = N + IFAC(2) = NF + TPI = 2.0*PIMACH(DUM) + ARGH = TPI/FLOAT(N) + IS = 0 + NFM1 = NF-1 + L1 = 1 + IF (NFM1 .EQ. 0) RETURN + DO 110 K1=1,NFM1 + IP = nint(IFAC(K1+2)) + LD = 0 + L2 = L1*IP + IDO = N/L2 + IPM = IP-1 + DO 109 J=1,IPM + LD = LD+L1 + I = IS + ARGLD = FLOAT(LD)*ARGH + FI = 0. + DO 108 II=3,IDO,2 + I = I+2 + FI = FI+1. + ARG = FI*ARGLD + WA(I-1) = COS(ARG) + WA(I) = SIN(ARG) + 108 CONTINUE + IS = IS+IDO + 109 CONTINUE + L1 = L2 + 110 CONTINUE + RETURN + END + + +C SUBROUTINE RFFTB(N,R,WSAVE) +C +C SUBROUTINE RFFTB COMPUTES THE REAL PERODIC SEQUENCE FROM ITS +C FOURIER COEFFICIENTS (FOURIER SYNTHESIS). THE TRANSFORM IS DEFINED +C BELOW AT OUTPUT PARAMETER R. +C +C INPUT PARAMETERS +C +C N THE LENGTH OF THE ARRAY R TO BE TRANSFORMED. THE METHOD +C IS MOST EFFICIENT WHEN N IS A PRODUCT OF SMALL PRIMES. +C N MAY CHANGE SO LONG AS DIFFERENT WORK ARRAYS ARE PROVIDED +C +C R A REAL ARRAY OF LENGTH N WHICH CONTAINS THE SEQUENCE +C TO BE TRANSFORMED +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 2*N+15. +C IN THE PROGRAM THAT CALLS RFFTB. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE RFFTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C THE SAME WSAVE ARRAY CAN BE USED BY RFFTF AND RFFTB. +C +C +C OUTPUT PARAMETERS +C +C R FOR N EVEN AND FOR I = 1,...,N +C +C R(I) = R(1)+(-1)**(I-1)*R(N) +C +C PLUS THE SUM FROM K=2 TO K=N/2 OF +C +C 2.*R(2*K-2)*COS((K-1)*(I-1)*2*PI/N) +C +C -2.*R(2*K-1)*SIN((K-1)*(I-1)*2*PI/N) +C +C FOR N ODD AND FOR I = 1,...,N +C +C R(I) = R(1) PLUS THE SUM FROM K=2 TO K=(N+1)/2 OF +C +C 2.*R(2*K-2)*COS((K-1)*(I-1)*2*PI/N) +C +C -2.*R(2*K-1)*SIN((K-1)*(I-1)*2*PI/N) +C +C ***** NOTE +C THIS TRANSFORM IS UNNORMALIZED SINCE A CALL OF RFFTF +C FOLLOWED BY A CALL OF RFFTB WILL MULTIPLY THE INPUT +C SEQUENCE BY N. +C +C WSAVE CONTAINS RESULTS WHICH MUST NOT BE DESTROYED BETWEEN +C CALLS OF RFFTB OR RFFTF. +C +C + SUBROUTINE RFFTB (N,R,WSAVE) + IMPLICIT_STATEMENT + DIMENSION R(*) ,WSAVE(*) +C + IF (N .EQ. 1) RETURN + CALL RFFTB1 (N,R,WSAVE,WSAVE(N+1),WSAVE(2*N+1)) + RETURN + END + + + SUBROUTINE RFFTB1 (N,C,CH,WA,IFAC) + IMPLICIT_STATEMENT +!!bjj START (fix for compatibility in double precision): +!! also note I added nint() around places where IFAC is on the right-hand side of the equation +! DIMENSION CH(*) ,C(*) ,WA(*) ,IFAC(*) + IFAC_TYPE, DIMENSION(*) :: IFAC + DIMENSION CH(*) ,C(*) ,WA(*) +!!bjj End + NF = nint(IFAC(2)) + NA = 0 + L1 = 1 + IW = 1 + DO 116 K1=1,NF + IP = nint(IFAC(K1+2)) + L2 = IP*L1 + IDO = N/L2 + IDL1 = IDO*L1 + IF (IP .NE. 4) GO TO 103 + IX2 = IW+IDO + IX3 = IX2+IDO + IF (NA .NE. 0) GO TO 101 + CALL RADB4 (IDO,L1,C,CH,WA(IW),WA(IX2),WA(IX3)) + GO TO 102 + 101 CALL RADB4 (IDO,L1,CH,C,WA(IW),WA(IX2),WA(IX3)) + 102 NA = 1-NA + GO TO 115 + 103 IF (IP .NE. 2) GO TO 106 + IF (NA .NE. 0) GO TO 104 + CALL RADB2 (IDO,L1,C,CH,WA(IW)) + GO TO 105 + 104 CALL RADB2 (IDO,L1,CH,C,WA(IW)) + 105 NA = 1-NA + GO TO 115 + 106 IF (IP .NE. 3) GO TO 109 + IX2 = IW+IDO + IF (NA .NE. 0) GO TO 107 + CALL RADB3 (IDO,L1,C,CH,WA(IW),WA(IX2)) + GO TO 108 + 107 CALL RADB3 (IDO,L1,CH,C,WA(IW),WA(IX2)) + 108 NA = 1-NA + GO TO 115 + 109 IF (IP .NE. 5) GO TO 112 + IX2 = IW+IDO + IX3 = IX2+IDO + IX4 = IX3+IDO + IF (NA .NE. 0) GO TO 110 + CALL RADB5 (IDO,L1,C,CH,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + GO TO 111 + 110 CALL RADB5 (IDO,L1,CH,C,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + 111 NA = 1-NA + GO TO 115 + 112 IF (NA .NE. 0) GO TO 113 + CALL RADBG (IDO,IP,L1,IDL1,C,C,C,CH,CH,WA(IW)) + GO TO 114 + 113 CALL RADBG (IDO,IP,L1,IDL1,CH,CH,CH,C,C,WA(IW)) + 114 IF (IDO .EQ. 1) NA = 1-NA + 115 L1 = L2 + IW = IW+(IP-1)*IDO + 116 CONTINUE + IF (NA .EQ. 0) RETURN + DO 117 I=1,N + C(I) = CH(I) + 117 CONTINUE + RETURN + END + + + SUBROUTINE RADB2 (IDO,L1,CC,CH,WA1) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,2,L1) ,CH(IDO,L1,2) , + 1 WA1(*) + DO 101 K=1,L1 + CH(1,K,1) = CC(1,1,K)+CC(IDO,2,K) + CH(1,K,2) = CC(1,1,K)-CC(IDO,2,K) + 101 CONTINUE + IF (IDO-2) 107,105,102 + 102 IDP2 = IDO+2 + DO 104 K=1,L1 + DO 103 I=3,IDO,2 + IC = IDP2-I + CH(I-1,K,1) = CC(I-1,1,K)+CC(IC-1,2,K) + TR2 = CC(I-1,1,K)-CC(IC-1,2,K) + CH(I,K,1) = CC(I,1,K)-CC(IC,2,K) + TI2 = CC(I,1,K)+CC(IC,2,K) + CH(I-1,K,2) = WA1(I-2)*TR2-WA1(I-1)*TI2 + CH(I,K,2) = WA1(I-2)*TI2+WA1(I-1)*TR2 + 103 CONTINUE + 104 CONTINUE + IF (MOD(IDO,2) .EQ. 1) RETURN + 105 DO 106 K=1,L1 + CH(IDO,K,1) = CC(IDO,1,K)+CC(IDO,1,K) + CH(IDO,K,2) = -(CC(1,2,K)+CC(1,2,K)) + 106 CONTINUE + 107 RETURN + END + + + SUBROUTINE RADB3 (IDO,L1,CC,CH,WA1,WA2) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,3,L1) ,CH(IDO,L1,3) , + 1 WA1(*) ,WA2(*) + DATA TAUR,TAUI /-.5,.866025403784439/ + DO 101 K=1,L1 + TR2 = CC(IDO,2,K)+CC(IDO,2,K) + CR2 = CC(1,1,K)+TAUR*TR2 + CH(1,K,1) = CC(1,1,K)+TR2 + CI3 = TAUI*(CC(1,3,K)+CC(1,3,K)) + CH(1,K,2) = CR2-CI3 + CH(1,K,3) = CR2+CI3 + 101 CONTINUE + IF (IDO .EQ. 1) RETURN + IDP2 = IDO+2 + DO 103 K=1,L1 + DO 102 I=3,IDO,2 + IC = IDP2-I + TR2 = CC(I-1,3,K)+CC(IC-1,2,K) + CR2 = CC(I-1,1,K)+TAUR*TR2 + CH(I-1,K,1) = CC(I-1,1,K)+TR2 + TI2 = CC(I,3,K)-CC(IC,2,K) + CI2 = CC(I,1,K)+TAUR*TI2 + CH(I,K,1) = CC(I,1,K)+TI2 + CR3 = TAUI*(CC(I-1,3,K)-CC(IC-1,2,K)) + CI3 = TAUI*(CC(I,3,K)+CC(IC,2,K)) + DR2 = CR2-CI3 + DR3 = CR2+CI3 + DI2 = CI2+CR3 + DI3 = CI2-CR3 + CH(I-1,K,2) = WA1(I-2)*DR2-WA1(I-1)*DI2 + CH(I,K,2) = WA1(I-2)*DI2+WA1(I-1)*DR2 + CH(I-1,K,3) = WA2(I-2)*DR3-WA2(I-1)*DI3 + CH(I,K,3) = WA2(I-2)*DI3+WA2(I-1)*DR3 + 102 CONTINUE + 103 CONTINUE + RETURN + END + + + SUBROUTINE RADB4 (IDO,L1,CC,CH,WA1,WA2,WA3) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,4,L1) ,CH(IDO,L1,4) , + 1 WA1(*) ,WA2(*) ,WA3(*) + DATA SQRT2 /1.414213562373095/ + DO 101 K=1,L1 + TR1 = CC(1,1,K)-CC(IDO,4,K) + TR2 = CC(1,1,K)+CC(IDO,4,K) + TR3 = CC(IDO,2,K)+CC(IDO,2,K) + TR4 = CC(1,3,K)+CC(1,3,K) + CH(1,K,1) = TR2+TR3 + CH(1,K,2) = TR1-TR4 + CH(1,K,3) = TR2-TR3 + CH(1,K,4) = TR1+TR4 + 101 CONTINUE + IF (IDO-2) 107,105,102 + 102 IDP2 = IDO+2 + DO 104 K=1,L1 + DO 103 I=3,IDO,2 + IC = IDP2-I + TI1 = CC(I,1,K)+CC(IC,4,K) + TI2 = CC(I,1,K)-CC(IC,4,K) + TI3 = CC(I,3,K)-CC(IC,2,K) + TR4 = CC(I,3,K)+CC(IC,2,K) + TR1 = CC(I-1,1,K)-CC(IC-1,4,K) + TR2 = CC(I-1,1,K)+CC(IC-1,4,K) + TI4 = CC(I-1,3,K)-CC(IC-1,2,K) + TR3 = CC(I-1,3,K)+CC(IC-1,2,K) + CH(I-1,K,1) = TR2+TR3 + CR3 = TR2-TR3 + CH(I,K,1) = TI2+TI3 + CI3 = TI2-TI3 + CR2 = TR1-TR4 + CR4 = TR1+TR4 + CI2 = TI1+TI4 + CI4 = TI1-TI4 + CH(I-1,K,2) = WA1(I-2)*CR2-WA1(I-1)*CI2 + CH(I,K,2) = WA1(I-2)*CI2+WA1(I-1)*CR2 + CH(I-1,K,3) = WA2(I-2)*CR3-WA2(I-1)*CI3 + CH(I,K,3) = WA2(I-2)*CI3+WA2(I-1)*CR3 + CH(I-1,K,4) = WA3(I-2)*CR4-WA3(I-1)*CI4 + CH(I,K,4) = WA3(I-2)*CI4+WA3(I-1)*CR4 + 103 CONTINUE + 104 CONTINUE + IF (MOD(IDO,2) .EQ. 1) RETURN + 105 CONTINUE + DO 106 K=1,L1 + TI1 = CC(1,2,K)+CC(1,4,K) + TI2 = CC(1,4,K)-CC(1,2,K) + TR1 = CC(IDO,1,K)-CC(IDO,3,K) + TR2 = CC(IDO,1,K)+CC(IDO,3,K) + CH(IDO,K,1) = TR2+TR2 + CH(IDO,K,2) = SQRT2*(TR1-TI1) + CH(IDO,K,3) = TI2+TI2 + CH(IDO,K,4) = -SQRT2*(TR1+TI1) + 106 CONTINUE + 107 RETURN + END + + + SUBROUTINE RADB5 (IDO,L1,CC,CH,WA1,WA2,WA3,WA4) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,5,L1) ,CH(IDO,L1,5) , + 1 WA1(*) ,WA2(*) ,WA3(*) ,WA4(*) + DATA TR11,TI11,TR12,TI12 /.309016994374947,.951056516295154, + 1-.809016994374947,.587785252292473/ + DO 101 K=1,L1 + TI5 = CC(1,3,K)+CC(1,3,K) + TI4 = CC(1,5,K)+CC(1,5,K) + TR2 = CC(IDO,2,K)+CC(IDO,2,K) + TR3 = CC(IDO,4,K)+CC(IDO,4,K) + CH(1,K,1) = CC(1,1,K)+TR2+TR3 + CR2 = CC(1,1,K)+TR11*TR2+TR12*TR3 + CR3 = CC(1,1,K)+TR12*TR2+TR11*TR3 + CI5 = TI11*TI5+TI12*TI4 + CI4 = TI12*TI5-TI11*TI4 + CH(1,K,2) = CR2-CI5 + CH(1,K,3) = CR3-CI4 + CH(1,K,4) = CR3+CI4 + CH(1,K,5) = CR2+CI5 + 101 CONTINUE + IF (IDO .EQ. 1) RETURN + IDP2 = IDO+2 + DO 103 K=1,L1 + DO 102 I=3,IDO,2 + IC = IDP2-I + TI5 = CC(I,3,K)+CC(IC,2,K) + TI2 = CC(I,3,K)-CC(IC,2,K) + TI4 = CC(I,5,K)+CC(IC,4,K) + TI3 = CC(I,5,K)-CC(IC,4,K) + TR5 = CC(I-1,3,K)-CC(IC-1,2,K) + TR2 = CC(I-1,3,K)+CC(IC-1,2,K) + TR4 = CC(I-1,5,K)-CC(IC-1,4,K) + TR3 = CC(I-1,5,K)+CC(IC-1,4,K) + CH(I-1,K,1) = CC(I-1,1,K)+TR2+TR3 + CH(I,K,1) = CC(I,1,K)+TI2+TI3 + CR2 = CC(I-1,1,K)+TR11*TR2+TR12*TR3 + CI2 = CC(I,1,K)+TR11*TI2+TR12*TI3 + CR3 = CC(I-1,1,K)+TR12*TR2+TR11*TR3 + CI3 = CC(I,1,K)+TR12*TI2+TR11*TI3 + CR5 = TI11*TR5+TI12*TR4 + CI5 = TI11*TI5+TI12*TI4 + CR4 = TI12*TR5-TI11*TR4 + CI4 = TI12*TI5-TI11*TI4 + DR3 = CR3-CI4 + DR4 = CR3+CI4 + DI3 = CI3+CR4 + DI4 = CI3-CR4 + DR5 = CR2+CI5 + DR2 = CR2-CI5 + DI5 = CI2-CR5 + DI2 = CI2+CR5 + CH(I-1,K,2) = WA1(I-2)*DR2-WA1(I-1)*DI2 + CH(I,K,2) = WA1(I-2)*DI2+WA1(I-1)*DR2 + CH(I-1,K,3) = WA2(I-2)*DR3-WA2(I-1)*DI3 + CH(I,K,3) = WA2(I-2)*DI3+WA2(I-1)*DR3 + CH(I-1,K,4) = WA3(I-2)*DR4-WA3(I-1)*DI4 + CH(I,K,4) = WA3(I-2)*DI4+WA3(I-1)*DR4 + CH(I-1,K,5) = WA4(I-2)*DR5-WA4(I-1)*DI5 + CH(I,K,5) = WA4(I-2)*DI5+WA4(I-1)*DR5 + 102 CONTINUE + 103 CONTINUE + RETURN + END + + + SUBROUTINE RADBG (IDO,IP,L1,IDL1,CC,C1,C2,CH,CH2,WA) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,L1,IP) ,CC(IDO,IP,L1) , + 1 C1(IDO,L1,IP) ,C2(IDL1,IP), + 2 CH2(IDL1,IP) ,WA(*) + TPI = 2.0*PIMACH(DUM) + ARG = TPI/FLOAT(IP) + DCP = COS(ARG) + DSP = SIN(ARG) + IDP2 = IDO+2 + NBD = (IDO-1)/2 + IPP2 = IP+2 + IPPH = (IP+1)/2 + IF (IDO .LT. L1) GO TO 103 + DO 102 K=1,L1 + DO 101 I=1,IDO + CH(I,K,1) = CC(I,1,K) + 101 CONTINUE + 102 CONTINUE + GO TO 106 + 103 DO 105 I=1,IDO + DO 104 K=1,L1 + CH(I,K,1) = CC(I,1,K) + 104 CONTINUE + 105 CONTINUE + 106 DO 108 J=2,IPPH + JC = IPP2-J + J2 = J+J + DO 107 K=1,L1 + CH(1,K,J) = CC(IDO,J2-2,K)+CC(IDO,J2-2,K) + CH(1,K,JC) = CC(1,J2-1,K)+CC(1,J2-1,K) + 107 CONTINUE + 108 CONTINUE + IF (IDO .EQ. 1) GO TO 116 + IF (NBD .LT. L1) GO TO 112 + DO 111 J=2,IPPH + JC = IPP2-J + DO 110 K=1,L1 + DO 109 I=3,IDO,2 + IC = IDP2-I + CH(I-1,K,J) = CC(I-1,2*J-1,K)+CC(IC-1,2*J-2,K) + CH(I-1,K,JC) = CC(I-1,2*J-1,K)-CC(IC-1,2*J-2,K) + CH(I,K,J) = CC(I,2*J-1,K)-CC(IC,2*J-2,K) + CH(I,K,JC) = CC(I,2*J-1,K)+CC(IC,2*J-2,K) + 109 CONTINUE + 110 CONTINUE + 111 CONTINUE + GO TO 116 + 112 DO 115 J=2,IPPH + JC = IPP2-J + DO 114 I=3,IDO,2 + IC = IDP2-I + DO 113 K=1,L1 + CH(I-1,K,J) = CC(I-1,2*J-1,K)+CC(IC-1,2*J-2,K) + CH(I-1,K,JC) = CC(I-1,2*J-1,K)-CC(IC-1,2*J-2,K) + CH(I,K,J) = CC(I,2*J-1,K)-CC(IC,2*J-2,K) + CH(I,K,JC) = CC(I,2*J-1,K)+CC(IC,2*J-2,K) + 113 CONTINUE + 114 CONTINUE + 115 CONTINUE + 116 AR1 = 1. + AI1 = 0. + DO 120 L=2,IPPH + LC = IPP2-L + AR1H = DCP*AR1-DSP*AI1 + AI1 = DCP*AI1+DSP*AR1 + AR1 = AR1H + DO 117 IK=1,IDL1 + C2(IK,L) = CH2(IK,1)+AR1*CH2(IK,2) + C2(IK,LC) = AI1*CH2(IK,IP) + 117 CONTINUE + DC2 = AR1 + DS2 = AI1 + AR2 = AR1 + AI2 = AI1 + DO 119 J=3,IPPH + JC = IPP2-J + AR2H = DC2*AR2-DS2*AI2 + AI2 = DC2*AI2+DS2*AR2 + AR2 = AR2H + DO 118 IK=1,IDL1 + C2(IK,L) = C2(IK,L)+AR2*CH2(IK,J) + C2(IK,LC) = C2(IK,LC)+AI2*CH2(IK,JC) + 118 CONTINUE + 119 CONTINUE + 120 CONTINUE + DO 122 J=2,IPPH + DO 121 IK=1,IDL1 + CH2(IK,1) = CH2(IK,1)+CH2(IK,J) + 121 CONTINUE + 122 CONTINUE + DO 124 J=2,IPPH + JC = IPP2-J + DO 123 K=1,L1 + CH(1,K,J) = C1(1,K,J)-C1(1,K,JC) + CH(1,K,JC) = C1(1,K,J)+C1(1,K,JC) + 123 CONTINUE + 124 CONTINUE + IF (IDO .EQ. 1) GO TO 132 + IF (NBD .LT. L1) GO TO 128 + DO 127 J=2,IPPH + JC = IPP2-J + DO 126 K=1,L1 + DO 125 I=3,IDO,2 + CH(I-1,K,J) = C1(I-1,K,J)-C1(I,K,JC) + CH(I-1,K,JC) = C1(I-1,K,J)+C1(I,K,JC) + CH(I,K,J) = C1(I,K,J)+C1(I-1,K,JC) + CH(I,K,JC) = C1(I,K,J)-C1(I-1,K,JC) + 125 CONTINUE + 126 CONTINUE + 127 CONTINUE + GO TO 132 + 128 DO 131 J=2,IPPH + JC = IPP2-J + DO 130 I=3,IDO,2 + DO 129 K=1,L1 + CH(I-1,K,J) = C1(I-1,K,J)-C1(I,K,JC) + CH(I-1,K,JC) = C1(I-1,K,J)+C1(I,K,JC) + CH(I,K,J) = C1(I,K,J)+C1(I-1,K,JC) + CH(I,K,JC) = C1(I,K,J)-C1(I-1,K,JC) + 129 CONTINUE + 130 CONTINUE + 131 CONTINUE + 132 CONTINUE + IF (IDO .EQ. 1) RETURN + DO 133 IK=1,IDL1 + C2(IK,1) = CH2(IK,1) + 133 CONTINUE + DO 135 J=2,IP + DO 134 K=1,L1 + C1(1,K,J) = CH(1,K,J) + 134 CONTINUE + 135 CONTINUE + IF (NBD .GT. L1) GO TO 139 + IS = -IDO + DO 138 J=2,IP + IS = IS+IDO + IDIJ = IS + DO 137 I=3,IDO,2 + IDIJ = IDIJ+2 + DO 136 K=1,L1 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)-WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)+WA(IDIJ)*CH(I-1,K,J) + 136 CONTINUE + 137 CONTINUE + 138 CONTINUE + GO TO 143 + 139 IS = -IDO + DO 142 J=2,IP + IS = IS+IDO + DO 141 K=1,L1 + IDIJ = IS + DO 140 I=3,IDO,2 + IDIJ = IDIJ+2 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)-WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)+WA(IDIJ)*CH(I-1,K,J) + 140 CONTINUE + 141 CONTINUE + 142 CONTINUE + 143 RETURN + END + + + FUNCTION PIMACH (DUM) + IMPLICIT_STATEMENT +C PI=3.1415926535897932384626433832795028841971693993751058209749446 +C + PIMACH = 4.*ATAN(1.0) + RETURN + END + + +C SUBROUTINE COSTI(N,WSAVE) +C +C SUBROUTINE COSTI INITIALIZES THE ARRAY WSAVE WHICH IS USED IN +C SUBROUTINE COST. THE PRIME FACTORIZATION OF N TOGETHER WITH +C A TABULATION OF THE TRIGONOMETRIC FUNCTIONS ARE COMPUTED AND +C STORED IN WSAVE. +C +C INPUT PARAMETER +C +C N THE LENGTH OF THE SEQUENCE TO BE TRANSFORMED. THE METHOD +C IS MOST EFFICIENT WHEN N-1 IS A PRODUCT OF SMALL PRIMES. +C +C OUTPUT PARAMETER +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 3*N+15. +C DIFFERENT WSAVE ARRAYS ARE REQUIRED FOR DIFFERENT VALUES +C OF N. THE CONTENTS OF WSAVE MUST NOT BE CHANGED BETWEEN +C CALLS OF COST. +C + SUBROUTINE COSTI (N,WSAVE) + IMPLICIT_STATEMENT + DIMENSION WSAVE(*) +C + PI = PIMACH(DUM) + IF (N .LE. 3) RETURN + NM1 = N-1 + NP1 = N+1 + NS2 = N/2 + DT = PI/FLOAT(NM1) + FK = 0. + DO 101 K=2,NS2 + KC = NP1-K + FK = FK+1. + WSAVE(K) = 2.*SIN(FK*DT) + WSAVE(KC) = 2.*COS(FK*DT) + 101 CONTINUE + CALL RFFTI (NM1,WSAVE(N+1)) + RETURN + END + + +C SUBROUTINE COST(N,X,WSAVE) +C +C SUBROUTINE COST COMPUTES THE DISCRETE FOURIER COSINE TRANSFORM +C OF AN EVEN SEQUENCE X(I). THE TRANSFORM IS DEFINED BELOW AT OUTPUT +C PARAMETER X. +C +C COST IS THE UNNORMALIZED INVERSE OF ITSELF SINCE A CALL OF COST +C FOLLOWED BY ANOTHER CALL OF COST WILL MULTIPLY THE INPUT SEQUENCE +C X BY 2*(N-1). THE TRANSFORM IS DEFINED BELOW AT OUTPUT PARAMETER X +C +C THE ARRAY WSAVE WHICH IS USED BY SUBROUTINE COST MUST BE +C INITIALIZED BY CALLING SUBROUTINE COSTI(N,WSAVE). +C +C INPUT PARAMETERS +C +C N THE LENGTH OF THE SEQUENCE X. N MUST BE GREATER THAN 1. +C THE METHOD IS MOST EFFICIENT WHEN N-1 IS A PRODUCT OF +C SMALL PRIMES. +C +C X AN ARRAY WHICH CONTAINS THE SEQUENCE TO BE TRANSFORMED +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 3*N+15 +C IN THE PROGRAM THAT CALLS COST. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE COSTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C +C OUTPUT PARAMETERS +C +C X FOR I=1,...,N +C +C X(I) = X(1)+(-1)**(I-1)*X(N) +C +C + THE SUM FROM K=2 TO K=N-1 +C +C 2*X(K)*COS((K-1)*(I-1)*PI/(N-1)) +C +C A CALL OF COST FOLLOWED BY ANOTHER CALL OF +C COST WILL MULTIPLY THE SEQUENCE X BY 2*(N-1) +C HENCE COST IS THE UNNORMALIZED INVERSE +C OF ITSELF. +C +C WSAVE CONTAINS INITIALIZATION CALCULATIONS WHICH MUST NOT BE +C DESTROYED BETWEEN CALLS OF COST. +C + SUBROUTINE COST (N,X,WSAVE) + IMPLICIT_STATEMENT + DIMENSION X(*) ,WSAVE(*) +C + NM1 = N-1 + NP1 = N+1 + NS2 = N/2 + IF (N-2) 106,101,102 + 101 X1H = X(1)+X(2) + X(2) = X(1)-X(2) + X(1) = X1H + RETURN + 102 IF (N .GT. 3) GO TO 103 + X1P3 = X(1)+X(3) + TX2 = X(2)+X(2) + X(2) = X(1)-X(3) + X(1) = X1P3+TX2 + X(3) = X1P3-TX2 + RETURN + 103 C1 = X(1)-X(N) + X(1) = X(1)+X(N) + DO 104 K=2,NS2 + KC = NP1-K + T1 = X(K)+X(KC) + T2 = X(K)-X(KC) + C1 = C1+WSAVE(KC)*T2 + T2 = WSAVE(K)*T2 + X(K) = T1-T2 + X(KC) = T1+T2 + 104 CONTINUE + MODN = MOD(N,2) + IF (MODN .NE. 0) X(NS2+1) = X(NS2+1)+X(NS2+1) + CALL RFFTF (NM1,X,WSAVE(N+1)) + XIM2 = X(2) + X(2) = C1 + DO 105 I=4,N,2 + XI = X(I) + X(I) = X(I-2)-X(I-1) + X(I-1) = XIM2 + XIM2 = XI + 105 CONTINUE + IF (MODN .NE. 0) X(N) = XIM2 + 106 RETURN + END + + +C SUBROUTINE RFFTF(N,R,WSAVE) +C +C SUBROUTINE RFFTF COMPUTES THE FOURIER COEFFICIENTS OF A REAL +C PERODIC SEQUENCE (FOURIER ANALYSIS). THE TRANSFORM IS DEFINED +C BELOW AT OUTPUT PARAMETER R. +C +C INPUT PARAMETERS +C +C N THE LENGTH OF THE ARRAY R TO BE TRANSFORMED. THE METHOD +C IS MOST EFFICIENT WHEN N IS A PRODUCT OF SMALL PRIMES. +C N MAY CHANGE SO LONG AS DIFFERENT WORK ARRAYS ARE PROVIDED +C +C R A REAL ARRAY OF LENGTH N WHICH CONTAINS THE SEQUENCE +C TO BE TRANSFORMED +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 2*N+15. +C IN THE PROGRAM THAT CALLS RFFTF. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE RFFTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C THE SAME WSAVE ARRAY CAN BE USED BY RFFTF AND RFFTB. +C +C +C OUTPUT PARAMETERS +C +C R R(1) = THE SUM FROM I=1 TO I=N OF R(I) +C +C IF N IS EVEN SET L =N/2 , IF N IS ODD SET L = (N+1)/2 +C +C THEN FOR K = 2,...,L +C +C R(2*K-2) = THE SUM FROM I = 1 TO I = N OF +C +C R(I)*COS((K-1)*(I-1)*2*PI/N) +C +C R(2*K-1) = THE SUM FROM I = 1 TO I = N OF +C +C -R(I)*SIN((K-1)*(I-1)*2*PI/N) +C +C IF N IS EVEN +C +C R(N) = THE SUM FROM I = 1 TO I = N OF +C +C (-1)**(I-1)*R(I) +C +C ***** NOTE +C THIS TRANSFORM IS UNNORMALIZED SINCE A CALL OF RFFTF +C FOLLOWED BY A CALL OF RFFTB WILL MULTIPLY THE INPUT +C SEQUENCE BY N. +C +C WSAVE CONTAINS RESULTS WHICH MUST NOT BE DESTROYED BETWEEN +C CALLS OF RFFTF OR RFFTB. +C + SUBROUTINE RFFTF (N,R,WSAVE) + IMPLICIT_STATEMENT + DIMENSION R(*) ,WSAVE(*) +C + IF (N .EQ. 1) RETURN + CALL RFFTF1 (N,R,WSAVE,WSAVE(N+1),WSAVE(2*N+1)) + RETURN + END + SUBROUTINE RFFTF1 (N,C,CH,WA,IFAC) + IMPLICIT_STATEMENT +!bjj START (fix for compatibility in double precision): +! also note I added nint() around places where IFAC is on the right-hand side of the equation +! DIMENSION CH(*) ,C(*) ,WA(*) ,IFAC(*) + DIMENSION CH(*) ,C(*) ,WA(*) + IFAC_TYPE, DIMENSION(*) :: IFAC +!bjj End + NF = nint(IFAC(2)) + NA = 1 + L2 = N + IW = N + DO 111 K1=1,NF + KH = NF-K1 + IP = nint(IFAC(KH+3)) + L1 = L2/IP + IDO = N/L2 + IDL1 = IDO*L1 + IW = IW-(IP-1)*IDO + NA = 1-NA + IF (IP .NE. 4) GO TO 102 + IX2 = IW+IDO + IX3 = IX2+IDO + IF (NA .NE. 0) GO TO 101 + CALL RADF4 (IDO,L1,C,CH,WA(IW),WA(IX2),WA(IX3)) + GO TO 110 + 101 CALL RADF4 (IDO,L1,CH,C,WA(IW),WA(IX2),WA(IX3)) + GO TO 110 + 102 IF (IP .NE. 2) GO TO 104 + IF (NA .NE. 0) GO TO 103 + CALL RADF2 (IDO,L1,C,CH,WA(IW)) + GO TO 110 + 103 CALL RADF2 (IDO,L1,CH,C,WA(IW)) + GO TO 110 + 104 IF (IP .NE. 3) GO TO 106 + IX2 = IW+IDO + IF (NA .NE. 0) GO TO 105 + CALL RADF3 (IDO,L1,C,CH,WA(IW),WA(IX2)) + GO TO 110 + 105 CALL RADF3 (IDO,L1,CH,C,WA(IW),WA(IX2)) + GO TO 110 + 106 IF (IP .NE. 5) GO TO 108 + IX2 = IW+IDO + IX3 = IX2+IDO + IX4 = IX3+IDO + IF (NA .NE. 0) GO TO 107 + CALL RADF5 (IDO,L1,C,CH,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + GO TO 110 + 107 CALL RADF5 (IDO,L1,CH,C,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + GO TO 110 + 108 IF (IDO .EQ. 1) NA = 1-NA + IF (NA .NE. 0) GO TO 109 + CALL RADFG (IDO,IP,L1,IDL1,C,C,C,CH,CH,WA(IW)) + NA = 1 + GO TO 110 + 109 CALL RADFG (IDO,IP,L1,IDL1,CH,CH,CH,C,C,WA(IW)) + NA = 0 + 110 L2 = L1 + 111 CONTINUE + IF (NA .EQ. 1) RETURN + DO 112 I=1,N + C(I) = CH(I) + 112 CONTINUE + RETURN + END + + + SUBROUTINE RADF2 (IDO,L1,CC,CH,WA1) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,2,L1) ,CC(IDO,L1,2) , + 1 WA1(*) + DO 101 K=1,L1 + CH(1,1,K) = CC(1,K,1)+CC(1,K,2) + CH(IDO,2,K) = CC(1,K,1)-CC(1,K,2) + 101 CONTINUE + IF (IDO-2) 107,105,102 + 102 IDP2 = IDO+2 + DO 104 K=1,L1 + DO 103 I=3,IDO,2 + IC = IDP2-I + TR2 = WA1(I-2)*CC(I-1,K,2)+WA1(I-1)*CC(I,K,2) + TI2 = WA1(I-2)*CC(I,K,2)-WA1(I-1)*CC(I-1,K,2) + CH(I,1,K) = CC(I,K,1)+TI2 + CH(IC,2,K) = TI2-CC(I,K,1) + CH(I-1,1,K) = CC(I-1,K,1)+TR2 + CH(IC-1,2,K) = CC(I-1,K,1)-TR2 + 103 CONTINUE + 104 CONTINUE + IF (MOD(IDO,2) .EQ. 1) RETURN + 105 DO 106 K=1,L1 + CH(1,2,K) = -CC(IDO,K,2) + CH(IDO,1,K) = CC(IDO,K,1) + 106 CONTINUE + 107 RETURN + END + + + SUBROUTINE RADF3 (IDO,L1,CC,CH,WA1,WA2) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,3,L1) ,CC(IDO,L1,3) , + 1 WA1(*) ,WA2(*) + DATA TAUR,TAUI /-.5,.866025403784439/ + DO 101 K=1,L1 + CR2 = CC(1,K,2)+CC(1,K,3) + CH(1,1,K) = CC(1,K,1)+CR2 + CH(1,3,K) = TAUI*(CC(1,K,3)-CC(1,K,2)) + CH(IDO,2,K) = CC(1,K,1)+TAUR*CR2 + 101 CONTINUE + IF (IDO .EQ. 1) RETURN + IDP2 = IDO+2 + DO 103 K=1,L1 + DO 102 I=3,IDO,2 + IC = IDP2-I + DR2 = WA1(I-2)*CC(I-1,K,2)+WA1(I-1)*CC(I,K,2) + DI2 = WA1(I-2)*CC(I,K,2)-WA1(I-1)*CC(I-1,K,2) + DR3 = WA2(I-2)*CC(I-1,K,3)+WA2(I-1)*CC(I,K,3) + DI3 = WA2(I-2)*CC(I,K,3)-WA2(I-1)*CC(I-1,K,3) + CR2 = DR2+DR3 + CI2 = DI2+DI3 + CH(I-1,1,K) = CC(I-1,K,1)+CR2 + CH(I,1,K) = CC(I,K,1)+CI2 + TR2 = CC(I-1,K,1)+TAUR*CR2 + TI2 = CC(I,K,1)+TAUR*CI2 + TR3 = TAUI*(DI2-DI3) + TI3 = TAUI*(DR3-DR2) + CH(I-1,3,K) = TR2+TR3 + CH(IC-1,2,K) = TR2-TR3 + CH(I,3,K) = TI2+TI3 + CH(IC,2,K) = TI3-TI2 + 102 CONTINUE + 103 CONTINUE + RETURN + END + + + SUBROUTINE RADF4 (IDO,L1,CC,CH,WA1,WA2,WA3) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,L1,4) ,CH(IDO,4,L1) , + 1 WA1(*) ,WA2(*) ,WA3(*) + DATA HSQT2 /.7071067811865475/ + DO 101 K=1,L1 + TR1 = CC(1,K,2)+CC(1,K,4) + TR2 = CC(1,K,1)+CC(1,K,3) + CH(1,1,K) = TR1+TR2 + CH(IDO,4,K) = TR2-TR1 + CH(IDO,2,K) = CC(1,K,1)-CC(1,K,3) + CH(1,3,K) = CC(1,K,4)-CC(1,K,2) + 101 CONTINUE + IF (IDO-2) 107,105,102 + 102 IDP2 = IDO+2 + DO 104 K=1,L1 + DO 103 I=3,IDO,2 + IC = IDP2-I + CR2 = WA1(I-2)*CC(I-1,K,2)+WA1(I-1)*CC(I,K,2) + CI2 = WA1(I-2)*CC(I,K,2)-WA1(I-1)*CC(I-1,K,2) + CR3 = WA2(I-2)*CC(I-1,K,3)+WA2(I-1)*CC(I,K,3) + CI3 = WA2(I-2)*CC(I,K,3)-WA2(I-1)*CC(I-1,K,3) + CR4 = WA3(I-2)*CC(I-1,K,4)+WA3(I-1)*CC(I,K,4) + CI4 = WA3(I-2)*CC(I,K,4)-WA3(I-1)*CC(I-1,K,4) + TR1 = CR2+CR4 + TR4 = CR4-CR2 + TI1 = CI2+CI4 + TI4 = CI2-CI4 + TI2 = CC(I,K,1)+CI3 + TI3 = CC(I,K,1)-CI3 + TR2 = CC(I-1,K,1)+CR3 + TR3 = CC(I-1,K,1)-CR3 + CH(I-1,1,K) = TR1+TR2 + CH(IC-1,4,K) = TR2-TR1 + CH(I,1,K) = TI1+TI2 + CH(IC,4,K) = TI1-TI2 + CH(I-1,3,K) = TI4+TR3 + CH(IC-1,2,K) = TR3-TI4 + CH(I,3,K) = TR4+TI3 + CH(IC,2,K) = TR4-TI3 + 103 CONTINUE + 104 CONTINUE + IF (MOD(IDO,2) .EQ. 1) RETURN + 105 CONTINUE + DO 106 K=1,L1 + TI1 = -HSQT2*(CC(IDO,K,2)+CC(IDO,K,4)) + TR1 = HSQT2*(CC(IDO,K,2)-CC(IDO,K,4)) + CH(IDO,1,K) = TR1+CC(IDO,K,1) + CH(IDO,3,K) = CC(IDO,K,1)-TR1 + CH(1,2,K) = TI1-CC(IDO,K,3) + CH(1,4,K) = TI1+CC(IDO,K,3) + 106 CONTINUE + 107 RETURN + END + + + SUBROUTINE RADF5 (IDO,L1,CC,CH,WA1,WA2,WA3,WA4) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,L1,5) ,CH(IDO,5,L1) , + 1 WA1(*) ,WA2(*) ,WA3(*) ,WA4(*) + DATA TR11,TI11,TR12,TI12 /.309016994374947,.951056516295154, + 1-.809016994374947,.587785252292473/ + DO 101 K=1,L1 + CR2 = CC(1,K,5)+CC(1,K,2) + CI5 = CC(1,K,5)-CC(1,K,2) + CR3 = CC(1,K,4)+CC(1,K,3) + CI4 = CC(1,K,4)-CC(1,K,3) + CH(1,1,K) = CC(1,K,1)+CR2+CR3 + CH(IDO,2,K) = CC(1,K,1)+TR11*CR2+TR12*CR3 + CH(1,3,K) = TI11*CI5+TI12*CI4 + CH(IDO,4,K) = CC(1,K,1)+TR12*CR2+TR11*CR3 + CH(1,5,K) = TI12*CI5-TI11*CI4 + 101 CONTINUE + IF (IDO .EQ. 1) RETURN + IDP2 = IDO+2 + DO 103 K=1,L1 + DO 102 I=3,IDO,2 + IC = IDP2-I + DR2 = WA1(I-2)*CC(I-1,K,2)+WA1(I-1)*CC(I,K,2) + DI2 = WA1(I-2)*CC(I,K,2)-WA1(I-1)*CC(I-1,K,2) + DR3 = WA2(I-2)*CC(I-1,K,3)+WA2(I-1)*CC(I,K,3) + DI3 = WA2(I-2)*CC(I,K,3)-WA2(I-1)*CC(I-1,K,3) + DR4 = WA3(I-2)*CC(I-1,K,4)+WA3(I-1)*CC(I,K,4) + DI4 = WA3(I-2)*CC(I,K,4)-WA3(I-1)*CC(I-1,K,4) + DR5 = WA4(I-2)*CC(I-1,K,5)+WA4(I-1)*CC(I,K,5) + DI5 = WA4(I-2)*CC(I,K,5)-WA4(I-1)*CC(I-1,K,5) + CR2 = DR2+DR5 + CI5 = DR5-DR2 + CR5 = DI2-DI5 + CI2 = DI2+DI5 + CR3 = DR3+DR4 + CI4 = DR4-DR3 + CR4 = DI3-DI4 + CI3 = DI3+DI4 + CH(I-1,1,K) = CC(I-1,K,1)+CR2+CR3 + CH(I,1,K) = CC(I,K,1)+CI2+CI3 + TR2 = CC(I-1,K,1)+TR11*CR2+TR12*CR3 + TI2 = CC(I,K,1)+TR11*CI2+TR12*CI3 + TR3 = CC(I-1,K,1)+TR12*CR2+TR11*CR3 + TI3 = CC(I,K,1)+TR12*CI2+TR11*CI3 + TR5 = TI11*CR5+TI12*CR4 + TI5 = TI11*CI5+TI12*CI4 + TR4 = TI12*CR5-TI11*CR4 + TI4 = TI12*CI5-TI11*CI4 + CH(I-1,3,K) = TR2+TR5 + CH(IC-1,2,K) = TR2-TR5 + CH(I,3,K) = TI2+TI5 + CH(IC,2,K) = TI5-TI2 + CH(I-1,5,K) = TR3+TR4 + CH(IC-1,4,K) = TR3-TR4 + CH(I,5,K) = TI3+TI4 + CH(IC,4,K) = TI4-TI3 + 102 CONTINUE + 103 CONTINUE + RETURN + END + + + SUBROUTINE RADFG (IDO,IP,L1,IDL1,CC,C1,C2,CH,CH2,WA) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,L1,IP) ,CC(IDO,IP,L1) , + 1 C1(IDO,L1,IP) ,C2(IDL1,IP), + 2 CH2(IDL1,IP) ,WA(*) + TPI = 2.0*PIMACH(DUM) + ARG = TPI/FLOAT(IP) + DCP = COS(ARG) + DSP = SIN(ARG) + IPPH = (IP+1)/2 + IPP2 = IP+2 + IDP2 = IDO+2 + NBD = (IDO-1)/2 + IF (IDO .EQ. 1) GO TO 119 + DO 101 IK=1,IDL1 + CH2(IK,1) = C2(IK,1) + 101 CONTINUE + DO 103 J=2,IP + DO 102 K=1,L1 + CH(1,K,J) = C1(1,K,J) + 102 CONTINUE + 103 CONTINUE + IF (NBD .GT. L1) GO TO 107 + IS = -IDO + DO 106 J=2,IP + IS = IS+IDO + IDIJ = IS + DO 105 I=3,IDO,2 + IDIJ = IDIJ+2 + DO 104 K=1,L1 + CH(I-1,K,J) = WA(IDIJ-1)*C1(I-1,K,J)+WA(IDIJ)*C1(I,K,J) + CH(I,K,J) = WA(IDIJ-1)*C1(I,K,J)-WA(IDIJ)*C1(I-1,K,J) + 104 CONTINUE + 105 CONTINUE + 106 CONTINUE + GO TO 111 + 107 IS = -IDO + DO 110 J=2,IP + IS = IS+IDO + DO 109 K=1,L1 + IDIJ = IS + DO 108 I=3,IDO,2 + IDIJ = IDIJ+2 + CH(I-1,K,J) = WA(IDIJ-1)*C1(I-1,K,J)+WA(IDIJ)*C1(I,K,J) + CH(I,K,J) = WA(IDIJ-1)*C1(I,K,J)-WA(IDIJ)*C1(I-1,K,J) + 108 CONTINUE + 109 CONTINUE + 110 CONTINUE + 111 IF (NBD .LT. L1) GO TO 115 + DO 114 J=2,IPPH + JC = IPP2-J + DO 113 K=1,L1 + DO 112 I=3,IDO,2 + C1(I-1,K,J) = CH(I-1,K,J)+CH(I-1,K,JC) + C1(I-1,K,JC) = CH(I,K,J)-CH(I,K,JC) + C1(I,K,J) = CH(I,K,J)+CH(I,K,JC) + C1(I,K,JC) = CH(I-1,K,JC)-CH(I-1,K,J) + 112 CONTINUE + 113 CONTINUE + 114 CONTINUE + GO TO 121 + 115 DO 118 J=2,IPPH + JC = IPP2-J + DO 117 I=3,IDO,2 + DO 116 K=1,L1 + C1(I-1,K,J) = CH(I-1,K,J)+CH(I-1,K,JC) + C1(I-1,K,JC) = CH(I,K,J)-CH(I,K,JC) + C1(I,K,J) = CH(I,K,J)+CH(I,K,JC) + C1(I,K,JC) = CH(I-1,K,JC)-CH(I-1,K,J) + 116 CONTINUE + 117 CONTINUE + 118 CONTINUE + GO TO 121 + 119 DO 120 IK=1,IDL1 + C2(IK,1) = CH2(IK,1) + 120 CONTINUE + 121 DO 123 J=2,IPPH + JC = IPP2-J + DO 122 K=1,L1 + C1(1,K,J) = CH(1,K,J)+CH(1,K,JC) + C1(1,K,JC) = CH(1,K,JC)-CH(1,K,J) + 122 CONTINUE + 123 CONTINUE +C + AR1 = 1. + AI1 = 0. + DO 127 L=2,IPPH + LC = IPP2-L + AR1H = DCP*AR1-DSP*AI1 + AI1 = DCP*AI1+DSP*AR1 + AR1 = AR1H + DO 124 IK=1,IDL1 + CH2(IK,L) = C2(IK,1)+AR1*C2(IK,2) + CH2(IK,LC) = AI1*C2(IK,IP) + 124 CONTINUE + DC2 = AR1 + DS2 = AI1 + AR2 = AR1 + AI2 = AI1 + DO 126 J=3,IPPH + JC = IPP2-J + AR2H = DC2*AR2-DS2*AI2 + AI2 = DC2*AI2+DS2*AR2 + AR2 = AR2H + DO 125 IK=1,IDL1 + CH2(IK,L) = CH2(IK,L)+AR2*C2(IK,J) + CH2(IK,LC) = CH2(IK,LC)+AI2*C2(IK,JC) + 125 CONTINUE + 126 CONTINUE + 127 CONTINUE + DO 129 J=2,IPPH + DO 128 IK=1,IDL1 + CH2(IK,1) = CH2(IK,1)+C2(IK,J) + 128 CONTINUE + 129 CONTINUE +C + IF (IDO .LT. L1) GO TO 132 + DO 131 K=1,L1 + DO 130 I=1,IDO + CC(I,1,K) = CH(I,K,1) + 130 CONTINUE + 131 CONTINUE + GO TO 135 + 132 DO 134 I=1,IDO + DO 133 K=1,L1 + CC(I,1,K) = CH(I,K,1) + 133 CONTINUE + 134 CONTINUE + 135 DO 137 J=2,IPPH + JC = IPP2-J + J2 = J+J + DO 136 K=1,L1 + CC(IDO,J2-2,K) = CH(1,K,J) + CC(1,J2-1,K) = CH(1,K,JC) + 136 CONTINUE + 137 CONTINUE + IF (IDO .EQ. 1) RETURN + IF (NBD .LT. L1) GO TO 141 + DO 140 J=2,IPPH + JC = IPP2-J + J2 = J+J + DO 139 K=1,L1 + DO 138 I=3,IDO,2 + IC = IDP2-I + CC(I-1,J2-1,K) = CH(I-1,K,J)+CH(I-1,K,JC) + CC(IC-1,J2-2,K) = CH(I-1,K,J)-CH(I-1,K,JC) + CC(I,J2-1,K) = CH(I,K,J)+CH(I,K,JC) + CC(IC,J2-2,K) = CH(I,K,JC)-CH(I,K,J) + 138 CONTINUE + 139 CONTINUE + 140 CONTINUE + RETURN + 141 DO 144 J=2,IPPH + JC = IPP2-J + J2 = J+J + DO 143 I=3,IDO,2 + IC = IDP2-I + DO 142 K=1,L1 + CC(I-1,J2-1,K) = CH(I-1,K,J)+CH(I-1,K,JC) + CC(IC-1,J2-2,K) = CH(I-1,K,J)-CH(I-1,K,JC) + CC(I,J2-1,K) = CH(I,K,J)+CH(I,K,JC) + CC(IC,J2-2,K) = CH(I,K,JC)-CH(I,K,J) + 142 CONTINUE + 143 CONTINUE + 144 CONTINUE + RETURN + END + + +C SUBROUTINE SINTI(N,WSAVE) +C +C SUBROUTINE SINTI INITIALIZES THE ARRAY WSAVE WHICH IS USED IN +C SUBROUTINE SINT. THE PRIME FACTORIZATION OF N TOGETHER WITH +C A TABULATION OF THE TRIGONOMETRIC FUNCTIONS ARE COMPUTED AND +C STORED IN WSAVE. +C +C INPUT PARAMETER +C +C N THE LENGTH OF THE SEQUENCE TO BE TRANSFORMED. THE METHOD +C IS MOST EFFICIENT WHEN N+1 IS A PRODUCT OF SMALL PRIMES. +C +C OUTPUT PARAMETER +C +C WSAVE A WORK ARRAY WITH AT LEAST INT(2.5*N+15) LOCATIONS. +C DIFFERENT WSAVE ARRAYS ARE REQUIRED FOR DIFFERENT VALUES +C OF N. THE CONTENTS OF WSAVE MUST NOT BE CHANGED BETWEEN +C CALLS OF SINT. +C + SUBROUTINE SINTI (N,WSAVE) + IMPLICIT_STATEMENT + DIMENSION WSAVE(*) +C + PI = PIMACH(DUM) + IF (N .LE. 1) RETURN + NS2 = N/2 + NP1 = N+1 + DT = PI/FLOAT(NP1) + DO 101 K=1,NS2 + WSAVE(K) = 2.*SIN(K*DT) + 101 CONTINUE + CALL RFFTI (NP1,WSAVE(NS2+1)) + RETURN + END + + +C SUBROUTINE SINT(N,X,WSAVE) +C +C SUBROUTINE SINT COMPUTES THE DISCRETE FOURIER SINE TRANSFORM +C OF AN ODD SEQUENCE X(I). THE TRANSFORM IS DEFINED BELOW AT +C OUTPUT PARAMETER X. +C +C SINT IS THE UNNORMALIZED INVERSE OF ITSELF SINCE A CALL OF SINT +C FOLLOWED BY ANOTHER CALL OF SINT WILL MULTIPLY THE INPUT SEQUENCE +C X BY 2*(N+1). +C +C THE ARRAY WSAVE WHICH IS USED BY SUBROUTINE SINT MUST BE +C INITIALIZED BY CALLING SUBROUTINE SINTI(N,WSAVE). +C +C INPUT PARAMETERS +C +C N THE LENGTH OF THE SEQUENCE TO BE TRANSFORMED. THE METHOD +C IS MOST EFFICIENT WHEN N+1 IS THE PRODUCT OF SMALL PRIMES. +C +C X AN ARRAY WHICH CONTAINS THE SEQUENCE TO BE TRANSFORMED +C +C +C WSAVE A WORK ARRAY WITH DIMENSION AT LEAST INT(2.5*N+15) +C IN THE PROGRAM THAT CALLS SINT. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE SINTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C +C OUTPUT PARAMETERS +C +C X FOR I=1,...,N +C +C X(I)= THE SUM FROM K=1 TO K=N +C +C 2*X(K)*SIN(K*I*PI/(N+1)) +C +C A CALL OF SINT FOLLOWED BY ANOTHER CALL OF +C SINT WILL MULTIPLY THE SEQUENCE X BY 2*(N+1). +C HENCE SINT IS THE UNNORMALIZED INVERSE +C OF ITSELF. +C +C WSAVE CONTAINS INITIALIZATION CALCULATIONS WHICH MUST NOT BE +C DESTROYED BETWEEN CALLS OF SINT. +C + SUBROUTINE SINT (N,X,WSAVE) + IMPLICIT_STATEMENT + DIMENSION X(*) ,WSAVE(*) +C + NP1 = N+1 + IW1 = N/2+1 + IW2 = IW1+NP1 + IW3 = IW2+NP1 + CALL SINT1(N,X,WSAVE,WSAVE(IW1),WSAVE(IW2),WSAVE(IW3)) + RETURN + END + + + SUBROUTINE SINT1(N,WAR,WAS,XH,X,IFAC) + IMPLICIT_STATEMENT +!!bjj START (fix for compatibility in double precision): +! DIMENSION WAR(*),WAS(*),X(*),XH(*),IFAC(*) + DIMENSION WAR(*),WAS(*),X(*),XH(*) + IFAC_TYPE, DIMENSION(*) :: IFAC +!!bjj End + DATA SQRT3 /1.73205080756888/ + DO 100 I=1,N + XH(I) = WAR(I) + WAR(I) = X(I) + 100 CONTINUE + IF (N-2) 101,102,103 + 101 XH(1) = XH(1)+XH(1) + GO TO 106 + 102 XHOLD = SQRT3*(XH(1)+XH(2)) + XH(2) = SQRT3*(XH(1)-XH(2)) + XH(1) = XHOLD + GO TO 106 + 103 NP1 = N+1 + NS2 = N/2 + X(1) = 0. + DO 104 K=1,NS2 + KC = NP1-K + T1 = XH(K)-XH(KC) + T2 = WAS(K)*(XH(K)+XH(KC)) + X(K+1) = T1+T2 + X(KC+1) = T2-T1 + 104 CONTINUE + MODN = MOD(N,2) + IF (MODN .NE. 0) X(NS2+2) = 4.*XH(NS2+1) + CALL RFFTF1 (NP1,X,XH,WAR,IFAC) + XH(1) = .5*X(1) + DO 105 I=3,N,2 + XH(I-1) = -X(I) + XH(I) = XH(I-2)+X(I-1) + 105 CONTINUE + IF (MODN .NE. 0) GO TO 106 + XH(N) = -X(N+1) + 106 DO 107 I=1,N + X(I) = WAR(I) + WAR(I) = XH(I) + 107 CONTINUE + RETURN + END + + +C ********************************************************************** +C +C SUBROUTINE CFFTI(N,WSAVE) +C +C SUBROUTINE CFFTI INITIALIZES THE ARRAY WSAVE WHICH IS USED IN +C BOTH CFFTF AND CFFTB. THE PRIME FACTORIZATION OF N TOGETHER WITH +C A TABULATION OF THE TRIGONOMETRIC FUNCTIONS ARE COMPUTED AND +C STORED IN WSAVE. +C +C INPUT PARAMETER +C +C N THE LENGTH OF THE SEQUENCE TO BE TRANSFORMED +C +C OUTPUT PARAMETER +C +C WSAVE A WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 4*N+15 +C THE SAME WORK ARRAY CAN BE USED FOR BOTH CFFTF AND CFFTB +C AS LONG AS N REMAINS UNCHANGED. DIFFERENT WSAVE ARRAYS +C ARE REQUIRED FOR DIFFERENT VALUES OF N. THE CONTENTS OF +C WSAVE MUST NOT BE CHANGED BETWEEN CALLS OF CFFTF OR CFFTB. +C +C ********************************************************************** + SUBROUTINE CFFTI (N,WSAVE) + IMPLICIT_STATEMENT + DIMENSION WSAVE(*) +C + IF (N .EQ. 1) RETURN + IW1 = N+N+1 + IW2 = IW1+N+N + CALL CFFTI1 (N,WSAVE(IW1),WSAVE(IW2)) + RETURN + END + + + SUBROUTINE CFFTI1 (N,WA,IFAC) + IMPLICIT_STATEMENT + IFAC_TYPE, DIMENSION(*) :: IFAC + DIMENSION WA(*) ,NTRYH(4) + DATA NTRYH(1),NTRYH(2),NTRYH(3),NTRYH(4)/3,4,2,5/ + NL = N + NF = 0 + J = 0 + 101 J = J+1 + IF (J-4) 102,102,103 + 102 NTRY = NTRYH(J) + GO TO 104 + 103 NTRY = NTRY+2 + 104 NQ = NL/NTRY + NR = NL-NTRY*NQ + IF (NR) 101,105,101 + 105 NF = NF+1 + IFAC(NF+2) = NTRY + NL = NQ + IF (NTRY .NE. 2) GO TO 107 + IF (NF .EQ. 1) GO TO 107 + DO 106 I=2,NF + IB = NF-I+2 + IFAC(IB+2) = nint(IFAC(IB+1)) + 106 CONTINUE + IFAC(3) = 2 + 107 IF (NL .NE. 1) GO TO 104 + IFAC(1) = N + IFAC(2) = NF + TPI = 2.*PIMACH(DUM) + ARGH = TPI/FLOAT(N) + I = 2 + L1 = 1 + DO 110 K1=1,NF + IP = nint(IFAC(K1+2)) + LD = 0 + L2 = L1*IP + IDO = N/L2 + IDOT = IDO+IDO+2 + IPM = IP-1 + DO 109 J=1,IPM + I1 = I + WA(I-1) = 1. + WA(I) = 0. + LD = LD+L1 + FI = 0. + ARGLD = FLOAT(LD)*ARGH + DO 108 II=4,IDOT,2 + I = I+2 + FI = FI+1. + ARG = FI*ARGLD + WA(I-1) = COS(ARG) + WA(I) = SIN(ARG) + 108 CONTINUE + IF (IP .LE. 5) GO TO 109 + WA(I1-1) = WA(I-1) + WA(I1) = WA(I) + 109 CONTINUE + L1 = L2 + 110 CONTINUE + RETURN + END + + +C ********************************************************************** +C +C SUBROUTINE CFFTB(N,C,WSAVE) +C +C SUBROUTINE CFFTB COMPUTES THE BACKWARD COMPLEX DISCRETE FOURIER +C TRANSFORM (THE FOURIER SYNTHESIS). EQUIVALENTLY , CFFTB COMPUTES +C A COMPLEX PERIODIC SEQUENCE FROM ITS FOURIER COEFFICIENTS. +C THE TRANSFORM IS DEFINED BELOW AT OUTPUT PARAMETER C. +C +C A CALL OF CFFTF FOLLOWED BY A CALL OF CFFTB WILL MULTIPLY THE +C SEQUENCE BY N. +C +C THE ARRAY WSAVE WHICH IS USED BY SUBROUTINE CFFTB MUST BE +C INITIALIZED BY CALLING SUBROUTINE CFFTI(N,WSAVE). +C +C INPUT PARAMETERS +C +C +C N THE LENGTH OF THE COMPLEX SEQUENCE C. THE METHOD IS +C MORE EFFICIENT WHEN N IS THE PRODUCT OF SMALL PRIMES. +C +C C A COMPLEX ARRAY OF LENGTH N WHICH CONTAINS THE SEQUENCE +C +C WSAVE A REAL WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 4N+15 +C IN THE PROGRAM THAT CALLS CFFTB. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE CFFTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C THE SAME WSAVE ARRAY CAN BE USED BY CFFTF AND CFFTB. +C +C OUTPUT PARAMETERS +C +C C FOR J=1,...,N +C +C C(J)=THE SUM FROM K=1,...,N OF +C +C C(K)*EXP(I*(J-1)*(K-1)*2*PI/N) +C +C WHERE I=SQRT(-1) +C +C WSAVE CONTAINS INITIALIZATION CALCULATIONS WHICH MUST NOT BE +C DESTROYED BETWEEN CALLS OF SUBROUTINE CFFTF OR CFFTB +C ********************************************************************** + SUBROUTINE CFFTB (N,C,WSAVE) + IMPLICIT_STATEMENT + DIMENSION C(*) ,WSAVE(*) +C + IF (N .EQ. 1) RETURN + IW1 = N+N+1 + IW2 = IW1+N+N + CALL CFFTB1 (N,C,WSAVE,WSAVE(IW1),WSAVE(IW2)) + RETURN + END + + + SUBROUTINE CFFTB1 (N,C,CH,WA,IFAC) + IMPLICIT_STATEMENT + IFAC_TYPE, DIMENSION(*) :: IFAC + DIMENSION CH(*) ,C(*) ,WA(*) + NF = nint(IFAC(2)) + NA = 0 + L1 = 1 + IW = 1 + DO 116 K1=1,NF + IP = nint(IFAC(K1+2)) + L2 = IP*L1 + IDO = N/L2 + IDOT = IDO+IDO + IDL1 = IDOT*L1 + IF (IP .NE. 4) GO TO 103 + IX2 = IW+IDOT + IX3 = IX2+IDOT + IF (NA .NE. 0) GO TO 101 + CALL PASSB4 (IDOT,L1,C,CH,WA(IW),WA(IX2),WA(IX3)) + GO TO 102 + 101 CALL PASSB4 (IDOT,L1,CH,C,WA(IW),WA(IX2),WA(IX3)) + 102 NA = 1-NA + GO TO 115 + 103 IF (IP .NE. 2) GO TO 106 + IF (NA .NE. 0) GO TO 104 + CALL PASSB2 (IDOT,L1,C,CH,WA(IW)) + GO TO 105 + 104 CALL PASSB2 (IDOT,L1,CH,C,WA(IW)) + 105 NA = 1-NA + GO TO 115 + 106 IF (IP .NE. 3) GO TO 109 + IX2 = IW+IDOT + IF (NA .NE. 0) GO TO 107 + CALL PASSB3 (IDOT,L1,C,CH,WA(IW),WA(IX2)) + GO TO 108 + 107 CALL PASSB3 (IDOT,L1,CH,C,WA(IW),WA(IX2)) + 108 NA = 1-NA + GO TO 115 + 109 IF (IP .NE. 5) GO TO 112 + IX2 = IW+IDOT + IX3 = IX2+IDOT + IX4 = IX3+IDOT + IF (NA .NE. 0) GO TO 110 + CALL PASSB5 (IDOT,L1,C,CH,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + GO TO 111 + 110 CALL PASSB5 (IDOT,L1,CH,C,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + 111 NA = 1-NA + GO TO 115 + 112 IF (NA .NE. 0) GO TO 113 + CALL PASSB (NAC,IDOT,IP,L1,IDL1,C,C,C,CH,CH,WA(IW)) + GO TO 114 + 113 CALL PASSB (NAC,IDOT,IP,L1,IDL1,CH,CH,CH,C,C,WA(IW)) + 114 IF (NAC .NE. 0) NA = 1-NA + 115 L1 = L2 + IW = IW+(IP-1)*IDOT + 116 CONTINUE + IF (NA .EQ. 0) RETURN + N2 = N+N + DO 117 I=1,N2 + C(I) = CH(I) + 117 CONTINUE + RETURN + END + SUBROUTINE PASSB2 (IDO,L1,CC,CH,WA1) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,2,L1) ,CH(IDO,L1,2) , + 1 WA1(*) +!ADP: change WA1(1) to WA1(*) + IF (IDO .GT. 2) GO TO 102 + DO 101 K=1,L1 + CH(1,K,1) = CC(1,1,K)+CC(1,2,K) + CH(1,K,2) = CC(1,1,K)-CC(1,2,K) + CH(2,K,1) = CC(2,1,K)+CC(2,2,K) + CH(2,K,2) = CC(2,1,K)-CC(2,2,K) + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + CH(I-1,K,1) = CC(I-1,1,K)+CC(I-1,2,K) + TR2 = CC(I-1,1,K)-CC(I-1,2,K) + CH(I,K,1) = CC(I,1,K)+CC(I,2,K) + TI2 = CC(I,1,K)-CC(I,2,K) + CH(I,K,2) = WA1(I-1)*TI2+WA1(I)*TR2 + CH(I-1,K,2) = WA1(I-1)*TR2-WA1(I)*TI2 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSB3 (IDO,L1,CC,CH,WA1,WA2) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,3,L1) ,CH(IDO,L1,3) , + 1 WA1(*) ,WA2(*) + DATA TAUR,TAUI /-.5,.866025403784439/ + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TR2 = CC(1,2,K)+CC(1,3,K) + CR2 = CC(1,1,K)+TAUR*TR2 + CH(1,K,1) = CC(1,1,K)+TR2 + TI2 = CC(2,2,K)+CC(2,3,K) + CI2 = CC(2,1,K)+TAUR*TI2 + CH(2,K,1) = CC(2,1,K)+TI2 + CR3 = TAUI*(CC(1,2,K)-CC(1,3,K)) + CI3 = TAUI*(CC(2,2,K)-CC(2,3,K)) + CH(1,K,2) = CR2-CI3 + CH(1,K,3) = CR2+CI3 + CH(2,K,2) = CI2+CR3 + CH(2,K,3) = CI2-CR3 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TR2 = CC(I-1,2,K)+CC(I-1,3,K) + CR2 = CC(I-1,1,K)+TAUR*TR2 + CH(I-1,K,1) = CC(I-1,1,K)+TR2 + TI2 = CC(I,2,K)+CC(I,3,K) + CI2 = CC(I,1,K)+TAUR*TI2 + CH(I,K,1) = CC(I,1,K)+TI2 + CR3 = TAUI*(CC(I-1,2,K)-CC(I-1,3,K)) + CI3 = TAUI*(CC(I,2,K)-CC(I,3,K)) + DR2 = CR2-CI3 + DR3 = CR2+CI3 + DI2 = CI2+CR3 + DI3 = CI2-CR3 + CH(I,K,2) = WA1(I-1)*DI2+WA1(I)*DR2 + CH(I-1,K,2) = WA1(I-1)*DR2-WA1(I)*DI2 + CH(I,K,3) = WA2(I-1)*DI3+WA2(I)*DR3 + CH(I-1,K,3) = WA2(I-1)*DR3-WA2(I)*DI3 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSB4 (IDO,L1,CC,CH,WA1,WA2,WA3) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,4,L1) ,CH(IDO,L1,4) , + 1 WA1(*) ,WA2(*) ,WA3(*) + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TI1 = CC(2,1,K)-CC(2,3,K) + TI2 = CC(2,1,K)+CC(2,3,K) + TR4 = CC(2,4,K)-CC(2,2,K) + TI3 = CC(2,2,K)+CC(2,4,K) + TR1 = CC(1,1,K)-CC(1,3,K) + TR2 = CC(1,1,K)+CC(1,3,K) + TI4 = CC(1,2,K)-CC(1,4,K) + TR3 = CC(1,2,K)+CC(1,4,K) + CH(1,K,1) = TR2+TR3 + CH(1,K,3) = TR2-TR3 + CH(2,K,1) = TI2+TI3 + CH(2,K,3) = TI2-TI3 + CH(1,K,2) = TR1+TR4 + CH(1,K,4) = TR1-TR4 + CH(2,K,2) = TI1+TI4 + CH(2,K,4) = TI1-TI4 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TI1 = CC(I,1,K)-CC(I,3,K) + TI2 = CC(I,1,K)+CC(I,3,K) + TI3 = CC(I,2,K)+CC(I,4,K) + TR4 = CC(I,4,K)-CC(I,2,K) + TR1 = CC(I-1,1,K)-CC(I-1,3,K) + TR2 = CC(I-1,1,K)+CC(I-1,3,K) + TI4 = CC(I-1,2,K)-CC(I-1,4,K) + TR3 = CC(I-1,2,K)+CC(I-1,4,K) + CH(I-1,K,1) = TR2+TR3 + CR3 = TR2-TR3 + CH(I,K,1) = TI2+TI3 + CI3 = TI2-TI3 + CR2 = TR1+TR4 + CR4 = TR1-TR4 + CI2 = TI1+TI4 + CI4 = TI1-TI4 + CH(I-1,K,2) = WA1(I-1)*CR2-WA1(I)*CI2 + CH(I,K,2) = WA1(I-1)*CI2+WA1(I)*CR2 + CH(I-1,K,3) = WA2(I-1)*CR3-WA2(I)*CI3 + CH(I,K,3) = WA2(I-1)*CI3+WA2(I)*CR3 + CH(I-1,K,4) = WA3(I-1)*CR4-WA3(I)*CI4 + CH(I,K,4) = WA3(I-1)*CI4+WA3(I)*CR4 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSB5 (IDO,L1,CC,CH,WA1,WA2,WA3,WA4) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,5,L1) ,CH(IDO,L1,5) , + 1 WA1(*) ,WA2(*) ,WA3(*) ,WA4(*) + DATA TR11,TI11,TR12,TI12 /.309016994374947,.951056516295154, + 1-.809016994374947,.587785252292473/ + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TI5 = CC(2,2,K)-CC(2,5,K) + TI2 = CC(2,2,K)+CC(2,5,K) + TI4 = CC(2,3,K)-CC(2,4,K) + TI3 = CC(2,3,K)+CC(2,4,K) + TR5 = CC(1,2,K)-CC(1,5,K) + TR2 = CC(1,2,K)+CC(1,5,K) + TR4 = CC(1,3,K)-CC(1,4,K) + TR3 = CC(1,3,K)+CC(1,4,K) + CH(1,K,1) = CC(1,1,K)+TR2+TR3 + CH(2,K,1) = CC(2,1,K)+TI2+TI3 + CR2 = CC(1,1,K)+TR11*TR2+TR12*TR3 + CI2 = CC(2,1,K)+TR11*TI2+TR12*TI3 + CR3 = CC(1,1,K)+TR12*TR2+TR11*TR3 + CI3 = CC(2,1,K)+TR12*TI2+TR11*TI3 + CR5 = TI11*TR5+TI12*TR4 + CI5 = TI11*TI5+TI12*TI4 + CR4 = TI12*TR5-TI11*TR4 + CI4 = TI12*TI5-TI11*TI4 + CH(1,K,2) = CR2-CI5 + CH(1,K,5) = CR2+CI5 + CH(2,K,2) = CI2+CR5 + CH(2,K,3) = CI3+CR4 + CH(1,K,3) = CR3-CI4 + CH(1,K,4) = CR3+CI4 + CH(2,K,4) = CI3-CR4 + CH(2,K,5) = CI2-CR5 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TI5 = CC(I,2,K)-CC(I,5,K) + TI2 = CC(I,2,K)+CC(I,5,K) + TI4 = CC(I,3,K)-CC(I,4,K) + TI3 = CC(I,3,K)+CC(I,4,K) + TR5 = CC(I-1,2,K)-CC(I-1,5,K) + TR2 = CC(I-1,2,K)+CC(I-1,5,K) + TR4 = CC(I-1,3,K)-CC(I-1,4,K) + TR3 = CC(I-1,3,K)+CC(I-1,4,K) + CH(I-1,K,1) = CC(I-1,1,K)+TR2+TR3 + CH(I,K,1) = CC(I,1,K)+TI2+TI3 + CR2 = CC(I-1,1,K)+TR11*TR2+TR12*TR3 + CI2 = CC(I,1,K)+TR11*TI2+TR12*TI3 + CR3 = CC(I-1,1,K)+TR12*TR2+TR11*TR3 + CI3 = CC(I,1,K)+TR12*TI2+TR11*TI3 + CR5 = TI11*TR5+TI12*TR4 + CI5 = TI11*TI5+TI12*TI4 + CR4 = TI12*TR5-TI11*TR4 + CI4 = TI12*TI5-TI11*TI4 + DR3 = CR3-CI4 + DR4 = CR3+CI4 + DI3 = CI3+CR4 + DI4 = CI3-CR4 + DR5 = CR2+CI5 + DR2 = CR2-CI5 + DI5 = CI2-CR5 + DI2 = CI2+CR5 + CH(I-1,K,2) = WA1(I-1)*DR2-WA1(I)*DI2 + CH(I,K,2) = WA1(I-1)*DI2+WA1(I)*DR2 + CH(I-1,K,3) = WA2(I-1)*DR3-WA2(I)*DI3 + CH(I,K,3) = WA2(I-1)*DI3+WA2(I)*DR3 + CH(I-1,K,4) = WA3(I-1)*DR4-WA3(I)*DI4 + CH(I,K,4) = WA3(I-1)*DI4+WA3(I)*DR4 + CH(I-1,K,5) = WA4(I-1)*DR5-WA4(I)*DI5 + CH(I,K,5) = WA4(I-1)*DI5+WA4(I)*DR5 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSB (NAC,IDO,IP,L1,IDL1,CC,C1,C2,CH,CH2,WA) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,L1,IP) ,CC(IDO,IP,L1) , + 1 C1(IDO,L1,IP) ,WA(*) ,C2(IDL1,IP), + 2 CH2(IDL1,IP) + IDOT = IDO/2 + NT = IP*IDL1 + IPP2 = IP+2 + IPPH = (IP+1)/2 + IDP = IP*IDO +C + IF (IDO .LT. L1) GO TO 106 + DO 103 J=2,IPPH + JC = IPP2-J + DO 102 K=1,L1 + DO 101 I=1,IDO + CH(I,K,J) = CC(I,J,K)+CC(I,JC,K) + CH(I,K,JC) = CC(I,J,K)-CC(I,JC,K) + 101 CONTINUE + 102 CONTINUE + 103 CONTINUE + DO 105 K=1,L1 + DO 104 I=1,IDO + CH(I,K,1) = CC(I,1,K) + 104 CONTINUE + 105 CONTINUE + GO TO 112 + 106 DO 109 J=2,IPPH + JC = IPP2-J + DO 108 I=1,IDO + DO 107 K=1,L1 + CH(I,K,J) = CC(I,J,K)+CC(I,JC,K) + CH(I,K,JC) = CC(I,J,K)-CC(I,JC,K) + 107 CONTINUE + 108 CONTINUE + 109 CONTINUE + DO 111 I=1,IDO + DO 110 K=1,L1 + CH(I,K,1) = CC(I,1,K) + 110 CONTINUE + 111 CONTINUE + 112 IDL = 2-IDO + INC = 0 + DO 116 L=2,IPPH + LC = IPP2-L + IDL = IDL+IDO + DO 113 IK=1,IDL1 + C2(IK,L) = CH2(IK,1)+WA(IDL-1)*CH2(IK,2) + C2(IK,LC) = WA(IDL)*CH2(IK,IP) + 113 CONTINUE + IDLJ = IDL + INC = INC+IDO + DO 115 J=3,IPPH + JC = IPP2-J + IDLJ = IDLJ+INC + IF (IDLJ .GT. IDP) IDLJ = IDLJ-IDP + WAR = WA(IDLJ-1) + WAI = WA(IDLJ) + DO 114 IK=1,IDL1 + C2(IK,L) = C2(IK,L)+WAR*CH2(IK,J) + C2(IK,LC) = C2(IK,LC)+WAI*CH2(IK,JC) + 114 CONTINUE + 115 CONTINUE + 116 CONTINUE + DO 118 J=2,IPPH + DO 117 IK=1,IDL1 + CH2(IK,1) = CH2(IK,1)+CH2(IK,J) + 117 CONTINUE + 118 CONTINUE + DO 120 J=2,IPPH + JC = IPP2-J + DO 119 IK=2,IDL1,2 + CH2(IK-1,J) = C2(IK-1,J)-C2(IK,JC) + CH2(IK-1,JC) = C2(IK-1,J)+C2(IK,JC) + CH2(IK,J) = C2(IK,J)+C2(IK-1,JC) + CH2(IK,JC) = C2(IK,J)-C2(IK-1,JC) + 119 CONTINUE + 120 CONTINUE + NAC = 1 + IF (IDO .EQ. 2) RETURN + NAC = 0 + DO 121 IK=1,IDL1 + C2(IK,1) = CH2(IK,1) + 121 CONTINUE + DO 123 J=2,IP + DO 122 K=1,L1 + C1(1,K,J) = CH(1,K,J) + C1(2,K,J) = CH(2,K,J) + 122 CONTINUE + 123 CONTINUE + IF (IDOT .GT. L1) GO TO 127 + IDIJ = 0 + DO 126 J=2,IP + IDIJ = IDIJ+2 + DO 125 I=4,IDO,2 + IDIJ = IDIJ+2 + DO 124 K=1,L1 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)-WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)+WA(IDIJ)*CH(I-1,K,J) + 124 CONTINUE + 125 CONTINUE + 126 CONTINUE + RETURN + 127 IDJ = 2-IDO + DO 130 J=2,IP + IDJ = IDJ+IDO + DO 129 K=1,L1 + IDIJ = IDJ + DO 128 I=4,IDO,2 + IDIJ = IDIJ+2 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)-WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)+WA(IDIJ)*CH(I-1,K,J) + 128 CONTINUE + 129 CONTINUE + 130 CONTINUE + RETURN + END + + + + +C ********************************************************************** +C +C SUBROUTINE CFFTF(N,C,WSAVE) +C +C SUBROUTINE CFFTF COMPUTES THE FORWARD COMPLEX DISCRETE FOURIER +C TRANSFORM (THE FOURIER ANALYSIS). EQUIVALENTLY , CFFTF COMPUTES +C THE FOURIER COEFFICIENTS OF A COMPLEX PERIODIC SEQUENCE. +C THE TRANSFORM IS DEFINED BELOW AT OUTPUT PARAMETER C. +C +C THE TRANSFORM IS NOT NORMALIZED. TO OBTAIN A NORMALIZED TRANSFORM +C THE OUTPUT MUST BE DIVIDED BY N. OTHERWISE A CALL OF CFFTF +C FOLLOWED BY A CALL OF CFFTB WILL MULTIPLY THE SEQUENCE BY N. +C +C THE ARRAY WSAVE WHICH IS USED BY SUBROUTINE CFFTF MUST BE +C INITIALIZED BY CALLING SUBROUTINE CFFTI(N,WSAVE). +C +C INPUT PARAMETERS +C +C +C N THE LENGTH OF THE COMPLEX SEQUENCE C. THE METHOD IS +C MORE EFFICIENT WHEN N IS THE PRODUCT OF SMALL PRIMES. N +C +C C A COMPLEX ARRAY OF LENGTH N WHICH CONTAINS THE SEQUENCE +C +C WSAVE A REAL WORK ARRAY WHICH MUST BE DIMENSIONED AT LEAST 4N+15 +C IN THE PROGRAM THAT CALLS CFFTF. THE WSAVE ARRAY MUST BE +C INITIALIZED BY CALLING SUBROUTINE CFFTI(N,WSAVE) AND A +C DIFFERENT WSAVE ARRAY MUST BE USED FOR EACH DIFFERENT +C VALUE OF N. THIS INITIALIZATION DOES NOT HAVE TO BE +C REPEATED SO LONG AS N REMAINS UNCHANGED THUS SUBSEQUENT +C TRANSFORMS CAN BE OBTAINED FASTER THAN THE FIRST. +C THE SAME WSAVE ARRAY CAN BE USED BY CFFTF AND CFFTB. +C +C OUTPUT PARAMETERS +C +C C FOR J=1,...,N +C +C C(J)=THE SUM FROM K=1,...,N OF +C +C C(K)*EXP(-I*(J-1)*(K-1)*2*PI/N) +C +C WHERE I=SQRT(-1) +C +C WSAVE CONTAINS INITIALIZATION CALCULATIONS WHICH MUST NOT BE +C DESTROYED BETWEEN CALLS OF SUBROUTINE CFFTF OR CFFTB +C +C ********************************************************************** + SUBROUTINE CFFTF (N,C,WSAVE) + IMPLICIT_STATEMENT + DIMENSION C(*) ,WSAVE(*) +C + IF (N .EQ. 1) RETURN + IW1 = N+N+1 + IW2 = IW1+N+N + CALL CFFTF1 (N,C,WSAVE,WSAVE(IW1),WSAVE(IW2)) + RETURN + END + SUBROUTINE CFFTF1 (N,C,CH,WA,IFAC) + IMPLICIT_STATEMENT + IFAC_TYPE, DIMENSION(*) :: IFAC + DIMENSION CH(*) ,C(*) ,WA(*) + NF = nint(IFAC(2)) + NA = 0 + L1 = 1 + IW = 1 + DO 116 K1=1,NF + IP = nint(IFAC(K1+2)) + L2 = IP*L1 + IDO = N/L2 + IDOT = IDO+IDO + IDL1 = IDOT*L1 + IF (IP .NE. 4) GO TO 103 + IX2 = IW+IDOT + IX3 = IX2+IDOT + IF (NA .NE. 0) GO TO 101 + CALL PASSF4 (IDOT,L1,C,CH,WA(IW),WA(IX2),WA(IX3)) + GO TO 102 + 101 CALL PASSF4 (IDOT,L1,CH,C,WA(IW),WA(IX2),WA(IX3)) + 102 NA = 1-NA + GO TO 115 + 103 IF (IP .NE. 2) GO TO 106 + IF (NA .NE. 0) GO TO 104 + CALL PASSF2 (IDOT,L1,C,CH,WA(IW)) + GO TO 105 + 104 CALL PASSF2 (IDOT,L1,CH,C,WA(IW)) + 105 NA = 1-NA + GO TO 115 + 106 IF (IP .NE. 3) GO TO 109 + IX2 = IW+IDOT + IF (NA .NE. 0) GO TO 107 + CALL PASSF3 (IDOT,L1,C,CH,WA(IW),WA(IX2)) + GO TO 108 + 107 CALL PASSF3 (IDOT,L1,CH,C,WA(IW),WA(IX2)) + 108 NA = 1-NA + GO TO 115 + 109 IF (IP .NE. 5) GO TO 112 + IX2 = IW+IDOT + IX3 = IX2+IDOT + IX4 = IX3+IDOT + IF (NA .NE. 0) GO TO 110 + CALL PASSF5 (IDOT,L1,C,CH,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + GO TO 111 + 110 CALL PASSF5 (IDOT,L1,CH,C,WA(IW),WA(IX2),WA(IX3),WA(IX4)) + 111 NA = 1-NA + GO TO 115 + 112 IF (NA .NE. 0) GO TO 113 + CALL PASSF (NAC,IDOT,IP,L1,IDL1,C,C,C,CH,CH,WA(IW)) + GO TO 114 + 113 CALL PASSF (NAC,IDOT,IP,L1,IDL1,CH,CH,CH,C,C,WA(IW)) + 114 IF (NAC .NE. 0) NA = 1-NA + 115 L1 = L2 + IW = IW+(IP-1)*IDOT + 116 CONTINUE + IF (NA .EQ. 0) RETURN + N2 = N+N + DO 117 I=1,N2 + C(I) = CH(I) + 117 CONTINUE + RETURN + END + SUBROUTINE PASSF2 (IDO,L1,CC,CH,WA1) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,2,L1) ,CH(IDO,L1,2) , + 1 WA1(*) + IF (IDO .GT. 2) GO TO 102 + DO 101 K=1,L1 + CH(1,K,1) = CC(1,1,K)+CC(1,2,K) + CH(1,K,2) = CC(1,1,K)-CC(1,2,K) + CH(2,K,1) = CC(2,1,K)+CC(2,2,K) + CH(2,K,2) = CC(2,1,K)-CC(2,2,K) + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + CH(I-1,K,1) = CC(I-1,1,K)+CC(I-1,2,K) + TR2 = CC(I-1,1,K)-CC(I-1,2,K) + CH(I,K,1) = CC(I,1,K)+CC(I,2,K) + TI2 = CC(I,1,K)-CC(I,2,K) + CH(I,K,2) = WA1(I-1)*TI2-WA1(I)*TR2 + CH(I-1,K,2) = WA1(I-1)*TR2+WA1(I)*TI2 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSF3 (IDO,L1,CC,CH,WA1,WA2) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,3,L1) ,CH(IDO,L1,3) , + 1 WA1(*) ,WA2(*) + DATA TAUR,TAUI /-.5,-.866025403784439/ + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TR2 = CC(1,2,K)+CC(1,3,K) + CR2 = CC(1,1,K)+TAUR*TR2 + CH(1,K,1) = CC(1,1,K)+TR2 + TI2 = CC(2,2,K)+CC(2,3,K) + CI2 = CC(2,1,K)+TAUR*TI2 + CH(2,K,1) = CC(2,1,K)+TI2 + CR3 = TAUI*(CC(1,2,K)-CC(1,3,K)) + CI3 = TAUI*(CC(2,2,K)-CC(2,3,K)) + CH(1,K,2) = CR2-CI3 + CH(1,K,3) = CR2+CI3 + CH(2,K,2) = CI2+CR3 + CH(2,K,3) = CI2-CR3 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TR2 = CC(I-1,2,K)+CC(I-1,3,K) + CR2 = CC(I-1,1,K)+TAUR*TR2 + CH(I-1,K,1) = CC(I-1,1,K)+TR2 + TI2 = CC(I,2,K)+CC(I,3,K) + CI2 = CC(I,1,K)+TAUR*TI2 + CH(I,K,1) = CC(I,1,K)+TI2 + CR3 = TAUI*(CC(I-1,2,K)-CC(I-1,3,K)) + CI3 = TAUI*(CC(I,2,K)-CC(I,3,K)) + DR2 = CR2-CI3 + DR3 = CR2+CI3 + DI2 = CI2+CR3 + DI3 = CI2-CR3 + CH(I,K,2) = WA1(I-1)*DI2-WA1(I)*DR2 + CH(I-1,K,2) = WA1(I-1)*DR2+WA1(I)*DI2 + CH(I,K,3) = WA2(I-1)*DI3-WA2(I)*DR3 + CH(I-1,K,3) = WA2(I-1)*DR3+WA2(I)*DI3 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSF4 (IDO,L1,CC,CH,WA1,WA2,WA3) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,4,L1) ,CH(IDO,L1,4) , + 1 WA1(*) ,WA2(*) ,WA3(*) + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TI1 = CC(2,1,K)-CC(2,3,K) + TI2 = CC(2,1,K)+CC(2,3,K) + TR4 = CC(2,2,K)-CC(2,4,K) + TI3 = CC(2,2,K)+CC(2,4,K) + TR1 = CC(1,1,K)-CC(1,3,K) + TR2 = CC(1,1,K)+CC(1,3,K) + TI4 = CC(1,4,K)-CC(1,2,K) + TR3 = CC(1,2,K)+CC(1,4,K) + CH(1,K,1) = TR2+TR3 + CH(1,K,3) = TR2-TR3 + CH(2,K,1) = TI2+TI3 + CH(2,K,3) = TI2-TI3 + CH(1,K,2) = TR1+TR4 + CH(1,K,4) = TR1-TR4 + CH(2,K,2) = TI1+TI4 + CH(2,K,4) = TI1-TI4 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TI1 = CC(I,1,K)-CC(I,3,K) + TI2 = CC(I,1,K)+CC(I,3,K) + TI3 = CC(I,2,K)+CC(I,4,K) + TR4 = CC(I,2,K)-CC(I,4,K) + TR1 = CC(I-1,1,K)-CC(I-1,3,K) + TR2 = CC(I-1,1,K)+CC(I-1,3,K) + TI4 = CC(I-1,4,K)-CC(I-1,2,K) + TR3 = CC(I-1,2,K)+CC(I-1,4,K) + CH(I-1,K,1) = TR2+TR3 + CR3 = TR2-TR3 + CH(I,K,1) = TI2+TI3 + CI3 = TI2-TI3 + CR2 = TR1+TR4 + CR4 = TR1-TR4 + CI2 = TI1+TI4 + CI4 = TI1-TI4 + CH(I-1,K,2) = WA1(I-1)*CR2+WA1(I)*CI2 + CH(I,K,2) = WA1(I-1)*CI2-WA1(I)*CR2 + CH(I-1,K,3) = WA2(I-1)*CR3+WA2(I)*CI3 + CH(I,K,3) = WA2(I-1)*CI3-WA2(I)*CR3 + CH(I-1,K,4) = WA3(I-1)*CR4+WA3(I)*CI4 + CH(I,K,4) = WA3(I-1)*CI4-WA3(I)*CR4 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSF5 (IDO,L1,CC,CH,WA1,WA2,WA3,WA4) + IMPLICIT_STATEMENT + DIMENSION CC(IDO,5,L1) ,CH(IDO,L1,5) , + 1 WA1(*) ,WA2(*) ,WA3(*) ,WA4(*) + DATA TR11,TI11,TR12,TI12 /.309016994374947,-.951056516295154, + 1-.809016994374947,-.587785252292473/ + IF (IDO .NE. 2) GO TO 102 + DO 101 K=1,L1 + TI5 = CC(2,2,K)-CC(2,5,K) + TI2 = CC(2,2,K)+CC(2,5,K) + TI4 = CC(2,3,K)-CC(2,4,K) + TI3 = CC(2,3,K)+CC(2,4,K) + TR5 = CC(1,2,K)-CC(1,5,K) + TR2 = CC(1,2,K)+CC(1,5,K) + TR4 = CC(1,3,K)-CC(1,4,K) + TR3 = CC(1,3,K)+CC(1,4,K) + CH(1,K,1) = CC(1,1,K)+TR2+TR3 + CH(2,K,1) = CC(2,1,K)+TI2+TI3 + CR2 = CC(1,1,K)+TR11*TR2+TR12*TR3 + CI2 = CC(2,1,K)+TR11*TI2+TR12*TI3 + CR3 = CC(1,1,K)+TR12*TR2+TR11*TR3 + CI3 = CC(2,1,K)+TR12*TI2+TR11*TI3 + CR5 = TI11*TR5+TI12*TR4 + CI5 = TI11*TI5+TI12*TI4 + CR4 = TI12*TR5-TI11*TR4 + CI4 = TI12*TI5-TI11*TI4 + CH(1,K,2) = CR2-CI5 + CH(1,K,5) = CR2+CI5 + CH(2,K,2) = CI2+CR5 + CH(2,K,3) = CI3+CR4 + CH(1,K,3) = CR3-CI4 + CH(1,K,4) = CR3+CI4 + CH(2,K,4) = CI3-CR4 + CH(2,K,5) = CI2-CR5 + 101 CONTINUE + RETURN + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TI5 = CC(I,2,K)-CC(I,5,K) + TI2 = CC(I,2,K)+CC(I,5,K) + TI4 = CC(I,3,K)-CC(I,4,K) + TI3 = CC(I,3,K)+CC(I,4,K) + TR5 = CC(I-1,2,K)-CC(I-1,5,K) + TR2 = CC(I-1,2,K)+CC(I-1,5,K) + TR4 = CC(I-1,3,K)-CC(I-1,4,K) + TR3 = CC(I-1,3,K)+CC(I-1,4,K) + CH(I-1,K,1) = CC(I-1,1,K)+TR2+TR3 + CH(I,K,1) = CC(I,1,K)+TI2+TI3 + CR2 = CC(I-1,1,K)+TR11*TR2+TR12*TR3 + CI2 = CC(I,1,K)+TR11*TI2+TR12*TI3 + CR3 = CC(I-1,1,K)+TR12*TR2+TR11*TR3 + CI3 = CC(I,1,K)+TR12*TI2+TR11*TI3 + CR5 = TI11*TR5+TI12*TR4 + CI5 = TI11*TI5+TI12*TI4 + CR4 = TI12*TR5-TI11*TR4 + CI4 = TI12*TI5-TI11*TI4 + DR3 = CR3-CI4 + DR4 = CR3+CI4 + DI3 = CI3+CR4 + DI4 = CI3-CR4 + DR5 = CR2+CI5 + DR2 = CR2-CI5 + DI5 = CI2-CR5 + DI2 = CI2+CR5 + CH(I-1,K,2) = WA1(I-1)*DR2+WA1(I)*DI2 + CH(I,K,2) = WA1(I-1)*DI2-WA1(I)*DR2 + CH(I-1,K,3) = WA2(I-1)*DR3+WA2(I)*DI3 + CH(I,K,3) = WA2(I-1)*DI3-WA2(I)*DR3 + CH(I-1,K,4) = WA3(I-1)*DR4+WA3(I)*DI4 + CH(I,K,4) = WA3(I-1)*DI4-WA3(I)*DR4 + CH(I-1,K,5) = WA4(I-1)*DR5+WA4(I)*DI5 + CH(I,K,5) = WA4(I-1)*DI5-WA4(I)*DR5 + 103 CONTINUE + 104 CONTINUE + RETURN + END + SUBROUTINE PASSF (NAC,IDO,IP,L1,IDL1,CC,C1,C2,CH,CH2,WA) + IMPLICIT_STATEMENT + DIMENSION CH(IDO,L1,IP) ,CC(IDO,IP,L1) , + 1 C1(IDO,L1,IP) ,WA(*) ,C2(IDL1,IP), + 2 CH2(IDL1,IP) + IDOT = IDO/2 + NT = IP*IDL1 + IPP2 = IP+2 + IPPH = (IP+1)/2 + IDP = IP*IDO +C + IF (IDO .LT. L1) GO TO 106 + DO 103 J=2,IPPH + JC = IPP2-J + DO 102 K=1,L1 + DO 101 I=1,IDO + CH(I,K,J) = CC(I,J,K)+CC(I,JC,K) + CH(I,K,JC) = CC(I,J,K)-CC(I,JC,K) + 101 CONTINUE + 102 CONTINUE + 103 CONTINUE + DO 105 K=1,L1 + DO 104 I=1,IDO + CH(I,K,1) = CC(I,1,K) + 104 CONTINUE + 105 CONTINUE + GO TO 112 + 106 DO 109 J=2,IPPH + JC = IPP2-J + DO 108 I=1,IDO + DO 107 K=1,L1 + CH(I,K,J) = CC(I,J,K)+CC(I,JC,K) + CH(I,K,JC) = CC(I,J,K)-CC(I,JC,K) + 107 CONTINUE + 108 CONTINUE + 109 CONTINUE + DO 111 I=1,IDO + DO 110 K=1,L1 + CH(I,K,1) = CC(I,1,K) + 110 CONTINUE + 111 CONTINUE + 112 IDL = 2-IDO + INC = 0 + DO 116 L=2,IPPH + LC = IPP2-L + IDL = IDL+IDO + DO 113 IK=1,IDL1 + C2(IK,L) = CH2(IK,1)+WA(IDL-1)*CH2(IK,2) + C2(IK,LC) = -WA(IDL)*CH2(IK,IP) + 113 CONTINUE + IDLJ = IDL + INC = INC+IDO + DO 115 J=3,IPPH + JC = IPP2-J + IDLJ = IDLJ+INC + IF (IDLJ .GT. IDP) IDLJ = IDLJ-IDP + WAR = WA(IDLJ-1) + WAI = WA(IDLJ) + DO 114 IK=1,IDL1 + C2(IK,L) = C2(IK,L)+WAR*CH2(IK,J) + C2(IK,LC) = C2(IK,LC)-WAI*CH2(IK,JC) + 114 CONTINUE + 115 CONTINUE + 116 CONTINUE + DO 118 J=2,IPPH + DO 117 IK=1,IDL1 + CH2(IK,1) = CH2(IK,1)+CH2(IK,J) + 117 CONTINUE + 118 CONTINUE + DO 120 J=2,IPPH + JC = IPP2-J + DO 119 IK=2,IDL1,2 + CH2(IK-1,J) = C2(IK-1,J)-C2(IK,JC) + CH2(IK-1,JC) = C2(IK-1,J)+C2(IK,JC) + CH2(IK,J) = C2(IK,J)+C2(IK-1,JC) + CH2(IK,JC) = C2(IK,J)-C2(IK-1,JC) + 119 CONTINUE + 120 CONTINUE + NAC = 1 + IF (IDO .EQ. 2) RETURN + NAC = 0 + DO 121 IK=1,IDL1 + C2(IK,1) = CH2(IK,1) + 121 CONTINUE + DO 123 J=2,IP + DO 122 K=1,L1 + C1(1,K,J) = CH(1,K,J) + C1(2,K,J) = CH(2,K,J) + 122 CONTINUE + 123 CONTINUE + IF (IDOT .GT. L1) GO TO 127 + IDIJ = 0 + DO 126 J=2,IP + IDIJ = IDIJ+2 + DO 125 I=4,IDO,2 + IDIJ = IDIJ+2 + DO 124 K=1,L1 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)+WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)-WA(IDIJ)*CH(I-1,K,J) + 124 CONTINUE + 125 CONTINUE + 126 CONTINUE + RETURN + 127 IDJ = 2-IDO + DO 130 J=2,IP + IDJ = IDJ+IDO + DO 129 K=1,L1 + IDIJ = IDJ + DO 128 I=4,IDO,2 + IDIJ = IDIJ+2 + C1(I-1,K,J) = WA(IDIJ-1)*CH(I-1,K,J)+WA(IDIJ)*CH(I,K,J) + C1(I,K,J) = WA(IDIJ-1)*CH(I,K,J)-WA(IDIJ)*CH(I-1,K,J) + 128 CONTINUE + 129 CONTINUE + 130 CONTINUE + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 b/OpenFAST/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 new file mode 100644 index 000000000..99cdd7a08 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 @@ -0,0 +1,1580 @@ +!********************************************************************************************************************************** +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +!> This code provides a wrapper for the LAPACK routines currently used at the NWTC (mainly codes in the FAST framework). This +!! enables us to call generic routines (not single- or double-precision specific ones) so that we don't have to change source +!! code to compile in double vs. single precision. +! +!********************************************************************************************************************************** +MODULE NWTC_LAPACK + + USE NWTC_Base ! we only need the precision and error level constants + + +! USE, INTRINSIC :: ISO_C_Binding, only: C_FLOAT, C_DOUBLE ! this is included in NWTC_Library + + ! Notes: + + ! Your project must include the following files: + ! From the NWTC Subroutine Library: + ! SingPrec.f90 [from NWTC Library] + ! Sys*.f90 [from NWTC Library] + ! NWTC_Base.f90 [from NWTC Library] + ! lapack library (preferably a binary, but available in source form from http://www.netlib.org/, too) + ! This wrapper file: + ! NWTC_LAPACK.f90 + + !INTEGER, PARAMETER :: Lib_ReKi = SiKi ! + !INTEGER, PARAMETER :: Lib_DbKi = R8Ki ! DbKi + ! + ! bjj: when using the built-in (or dynamic) lapack libraries, S=Real(SiKi); D=Real(R8Ki). + ! if people are compiling the lapack source, S=real; D=double precision. (default real and doubles) + ! we need to check this somehow to make sure the right routines are called. + ! (or define a directive) + + ! http://www.netlib.org/lapack/explore-html/ + + + IMPLICIT NONE + + !> Computes the solution to system of linear equations A * X = B for GB matrices. + INTERFACE LAPACK_gbsv + MODULE PROCEDURE LAPACK_dgbsv + MODULE PROCEDURE LAPACK_sgbsv + END INTERFACE + + !> Computes scalar1*op( A )*op( B ) + scalar2*C where op(x) = x or op(x) = x**T for matrices A, B, and C. + INTERFACE LAPACK_gemm + MODULE PROCEDURE LAPACK_dgemm + MODULE PROCEDURE LAPACK_sgemm + END INTERFACE + + !> Computes the solution to system of linear equations A * X = B for GE matrices. + INTERFACE LAPACK_gesv + MODULE PROCEDURE LAPACK_dgesv + MODULE PROCEDURE LAPACK_sgesv + END INTERFACE + + !> Factor matrix into A=PLU. + INTERFACE LAPACK_getrf + MODULE PROCEDURE LAPACK_dgetrf + MODULE PROCEDURE LAPACK_sgetrf + END INTERFACE + + !> Compute the inverse of a matrix using the LU factorization. + INTERFACE LAPACK_getri + MODULE PROCEDURE LAPACK_dgetri + MODULE PROCEDURE LAPACK_sgetri + END INTERFACE + + !> Solve system(s) of linear equations Ax=PLUx=b. + INTERFACE LAPACK_getrs + MODULE PROCEDURE LAPACK_dgetrs + MODULE PROCEDURE LAPACK_sgetrs + MODULE PROCEDURE LAPACK_dgetrs1 + MODULE PROCEDURE LAPACK_sgetrs1 + END INTERFACE + + !> Compute generalized eigenvalues and/or eigenvectors for a pair of N-by-N real nonsymmetric matrices (A,B). + INTERFACE LAPACK_ggev + MODULE PROCEDURE LAPACK_dggev + MODULE PROCEDURE LAPACK_sggev + END INTERFACE + + !> Compute the solution to system of linear equations A * X = B for PO matrices. + INTERFACE LAPACK_posv + MODULE PROCEDURE LAPACK_dposv + MODULE PROCEDURE LAPACK_sposv + END INTERFACE + + !> Compute the Cholesky factorization of a real symmetric positive definite matrix A stored in packed format. + INTERFACE LAPACK_pptrf + MODULE PROCEDURE LAPACK_dpptrf + MODULE PROCEDURE LAPACK_spptrf + END INTERFACE + +!> Compute the SVD for a general matrix A = USV^T. + INTERFACE LAPACK_gesvd + MODULE PROCEDURE LAPACK_dgesvd + MODULE PROCEDURE LAPACK_sgesvd + END INTERFACE + + +!> straight-up lapack routines (from ExtPtfm_MCKF): + + INTERFACE LAPACK_COPY + SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) + USE Precision, only: R8Ki + INTEGER :: INCX,INCY,N + real(R8Ki) :: DX(*),DY(*) + ENDSUBROUTINE + SUBROUTINE SCOPY(N,X,INCX,Y,INCY) + USE Precision, only: SiKi + INTEGER :: INCX,INCY,N + real(SiKi) :: X(*),Y(*) + ENDSUBROUTINE + END INTERFACE + + INTERFACE LAPACK_GEMV + SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) + USE Precision, only: R8Ki + real(R8Ki) :: ALPHA,BETA + integer :: INCX,INCY,LDA,M,N + character :: TRANS + real(R8Ki) :: A(LDA,*),X(*),Y(*) + ENDSUBROUTINE + SUBROUTINE SGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) + USE Precision, only: SiKi + real(SiKi) :: ALPHA,BETA + integer :: INCX,INCY,LDA,M,N + character :: TRANS + real(SiKi) :: A(LDA,*),X(*),Y(*) + ENDSUBROUTINE + END INTERFACE LAPACK_GEMV + + INTERFACE LAPACK_AXPY + SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) + USE Precision, only: R8Ki + real(R8Ki) :: DA + integer :: INCX,INCY,N + real(R8Ki) :: DX(*),DY(*) + ENDSUBROUTINE + SUBROUTINE SAXPY(N,A,X,INCX,Y,INCY) + USE Precision, only: SiKi + real(SiKi) :: A + integer :: INCX,INCY,N + real(SiKi) :: X(*),Y(*) + ENDSUBROUTINE + END INTERFACE + + CONTAINS + +!======================================================================= +!> general banded solve: Computes the solution to system of linear equations A * X = B for GB (general, banded) matrices. +!! use LAPACK_GBSV (nwtc_lapack::lapack_gbsv) instead of this specific function. + SUBROUTINE LAPACK_DGBSV( N, KL, KU, NRHS, AB, IPIV, B, ErrStat, ErrMsg ) + + + ! passed parameters + + INTEGER, intent(in ) :: KL !< The number of subdiagonals within the band of A. KL >= 0. + INTEGER, intent(in ) :: KU !< The number of superdiagonals within the band of A. KU >= 0. + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + INTEGER, intent(in ) :: NRHS !< The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + + ! .. Array Arguments .. + REAL(R8Ki) ,intent(inout) :: AB( :, : ) !< On entry, the matrix A in band storage, in rows KL+1 to 2*KL+KU+1; rows 1 to KL of the array need not be set. + !! The j-th column of A is stored in the j-th column of the array AB as follows: + !! AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL) + !! On exit, details of the factorization: U is stored as an upper triangular band matrix with KL+KU superdiagonals in + !! rows 1 to KL+KU+1, and the multipliers used during the factorization are stored in rows KL+KU+2 to 2*KL+KU+1. + REAL(R8Ki) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices that define the permutation matrix P; row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, U(i,i) is exactly zero. The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed. + INTEGER :: LDAB ! The leading dimension of the array AB. LDAB >= 2*KL+KU+1. + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDAB = SIZE(AB,1) + LDB = SIZE(B, 1) + + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL dgbsv (N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGBSV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGBSV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGBSV +!======================================================================= +!> general banded solve: Computes the solution to system of linear equations A * X = B for GB (general, banded) matrices. +!! use LAPACK_GBSV (nwtc_lapack::lapack_gbsv) instead of this specific function. + SUBROUTINE LAPACK_SGBSV( N, KL, KU, NRHS, AB, IPIV, B, ErrStat, ErrMsg ) + + + ! passed parameters + + INTEGER, intent(in ) :: KL !< The number of subdiagonals within the band of A. KL >= 0. + INTEGER, intent(in ) :: KU !< The number of superdiagonals within the band of A. KU >= 0. + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + INTEGER, intent(in ) :: NRHS !< The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + + ! .. Array Arguments .. + REAL(SiKi) ,intent(inout) :: AB( :, : ) !< On entry, the matrix A in band storage, in rows KL+1 to 2*KL+KU+1; rows 1 to KL of the array need not be set. + !! The j-th column of A is stored in the j-th column of the array AB as follows: + !! AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL) + !! On exit, details of the factorization: U is stored as an upper triangular band matrix with KL+KU superdiagonals in + !! rows 1 to KL+KU+1, and the multipliers used during the factorization are stored in rows KL+KU+2 to 2*KL+KU+1. + REAL(SiKi) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices that define the permutation matrix P; row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, U(i,i) is exactly zero. The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed. + + INTEGER :: LDAB ! The leading dimension of the array AB. LDAB >= 2*KL+KU+1. + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDAB = SIZE(AB,1) + LDB = SIZE(B, 1) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SGBSV (N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGBSV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGBSV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGBSV +!======================================================================= +!> general matrix multiply: computes C = alpha*op( A )*op( B ) + beta*C where op(x) = x or op(x) = x**T for matrices A, B, and C +!! use LAPACK_GEMM (nwtc_lapack::lapack_gemm) instead of this specific function. + SUBROUTINE LAPACK_DGEMM( TRANSA, TRANSB, ALPHA, A, B, BETA, C, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANSA !< On entry, TRANSA specifies the form of op( A ) to be used in the matrix multiplication as follows: + !! TRANSA = 'N' or 'n', op( A ) = A. + !! TRANSA = 'T' or 't', op( A ) = A**T. + CHARACTER(1), intent(in ) :: TRANSB !< On entry, TRANSB specifies the form of op( A ) to be used in the matrix multiplication as follows: + !! TRANSB = 'N' or 'n', op( B ) = B. + !! TRANSB = 'T' or 't', op( B ) = B**T. + + REAL(R8Ki) ,intent(in ) :: ALPHA !< On entry, ALPHA specifies the scalar alpha. + REAL(R8Ki) ,intent(in ) :: BETA !< On entry, BETA specifies the scalar beta. When BETA is supplied as zero then C need not be set on input. + REAL(R8Ki) ,intent(in ) :: A( :, : ) !< Matrix A + REAL(R8Ki) ,intent(in ) :: B( :, : ) !< Matrix B + REAL(R8Ki) ,intent(inout) :: C( :, : ) !< Matrix C: Before entry, C must contain the matrix C, except when beta is zero, in which case C need not + !< be set on entry. On exit, the array C is overwritten by the m by n matrix ( alpha*op( A )*op( B ) + beta*C ). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + + INTEGER :: M ! M specifies the number of rows of the matrix op(A) + INTEGER :: K ! K specifies the number of columns of the matrix op(A) + INTEGER :: N ! N specifies the number of columns of the matrix op(B) + INTEGER :: KB ! KB specifies the number of rows of the matrix op(B) + + INTEGER :: LDA ! LDA specifies the first dimension of A as declared in the calling (sub) program. When TRANSA = 'N' or 'n' then + ! LDA must be at least max( 1, m ), otherwise LDA must be at least max( 1, k ). + + INTEGER :: LDB ! LDB specifies the first dimension of B as declared in the calling (sub) program. When TRANSB = 'N' or 'n' then + ! LDB must be at least max( 1, k ), otherwise LDB must be at least max( 1, n ). + + CHARACTER(*), PARAMETER :: RoutineName = 'LAPACK_DGEMM' + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + IF (INDEX('Nn',TransA) > 0) THEN + M = SIZE(A,1) + K = SIZE(A,2) + ELSE + M = SIZE(A,2) + K = SIZE(A,1) + END IF + + IF (INDEX('Nn',TransB) > 0) THEN + N = SIZE(B,2) + Kb = SIZE(B,1) + ELSE + N = SIZE(B,1) + Kb = SIZE(B,2) + END IF + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( K /= Kb ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":Size of Matrix A is incompatible with size of Matrix B." + RETURN + END IF + + IF ( M /= SIZE(C,1) .OR. N /= SIZE(C,2) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":Size of Matrix C is incompatible with Matrix A and Matrix B." + RETURN + END IF + + IF ( M == 0 .or. N == 0 ) THEN + ! this is a null case... + RETURN + END IF + + IF (K == 0) THEN + C = C * beta ! A*B is null + RETURN + END IF + + + CALL DGEMM (TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, M) + + + RETURN + END SUBROUTINE LAPACK_DGEMM +!======================================================================= +!> general matrix multiply: computes C = alpha*op( A )*op( B ) + beta*C where op(x) = x or op(x) = x**T for matrices A, B, and C +!! use LAPACK_GEMM (nwtc_lapack::lapack_gemm) instead of this specific function. + SUBROUTINE LAPACK_SGEMM( TRANSA, TRANSB, ALPHA, A, B, BETA, C, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANSA !< On entry, TRANSA specifies the form of op( A ) to be used in the matrix multiplication as follows: + !! TRANSA = 'N' or 'n', op( A ) = A. + !! TRANSA = 'T' or 't', op( A ) = A**T. + CHARACTER(1), intent(in ) :: TRANSB !< On entry, TRANSB specifies the form of op( A ) to be used in the matrix multiplication as follows: + !! TRANSB = 'N' or 'n', op( B ) = B. + !! TRANSB = 'T' or 't', op( B ) = B**T. + + REAL(SiKi) ,intent(in ) :: ALPHA !< On entry, ALPHA specifies the scalar alpha. + REAL(SiKi) ,intent(in ) :: BETA !< On entry, BETA specifies the scalar beta. When BETA is supplied as zero then C need not be set on input. + REAL(SiKi) ,intent(in ) :: A( :, : ) !< Matrix A + REAL(SiKi) ,intent(in ) :: B( :, : ) !< Matrix B + REAL(SiKi) ,intent(inout) :: C( :, : ) !< Matrix C: Before entry, C must contain the matrix C, except when beta is zero, in which case C need not + !! be set on entry. On exit, the array C is overwritten by the m by n matrix ( alpha*op( A )*op( B ) + beta*C ). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + + INTEGER :: M ! M specifies the number of rows of the matrix op(A) + INTEGER :: K ! K specifies the number of columns of the matrix op(A) + INTEGER :: N ! N specifies the number of columns of the matrix op(B) + INTEGER :: KB ! KB specifies the number of rows of the matrix op(B) + + INTEGER :: LDA ! LDA specifies the first dimension of A as declared in the calling (sub) program. When TRANSA = 'N' or 'n' then + ! LDA must be at least max( 1, m ), otherwise LDA must be at least max( 1, k ). + + INTEGER :: LDB ! LDB specifies the first dimension of B as declared in the calling (sub) program. When TRANSB = 'N' or 'n' then + ! LDB must be at least max( 1, k ), otherwise LDB must be at least max( 1, n ). + + CHARACTER(*), PARAMETER :: RoutineName = 'LAPACK_SGEMM' + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + IF (INDEX('Nn',TransA) > 0) THEN + M = SIZE(A,1) + K = SIZE(A,2) + ELSE + M = SIZE(A,2) + K = SIZE(A,1) + END IF + + IF (INDEX('Nn',TransB) > 0) THEN + N = SIZE(B,2) + Kb = SIZE(B,1) + ELSE + N = SIZE(B,1) + Kb = SIZE(B,2) + END IF + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( K /= Kb ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":Size of Matrix A is incompatible with size of Matrix B." + RETURN + END IF + + IF ( M /= SIZE(C,1) .OR. N /= SIZE(C,2) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = RoutineName//":Size of Matrix C is incompatible with Matrix A and Matrix B." + RETURN + END IF + + IF ( M == 0 .or. N == 0 ) THEN + ! this is a null case... + RETURN + END IF + + IF (K == 0) THEN + C = C * beta ! A*B is null + RETURN + END IF + + + CALL SGEMM (TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, M) + + + RETURN + END SUBROUTINE LAPACK_SGEMM +!======================================================================= +!> general solve: Computes the solution to system of linear equations A * X = B for GE matrices. +!! use LAPACK_GESV (nwtc_lapack::lapack_gesv) instead of this specific function. + SUBROUTINE LAPACK_DGESV ( N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(R8Ki) ,intent(inout) :: A( :, : ) !< On entry, the N-by-N coefficient matrix A. On exit, the factors L and U from the factorization A = P*L*U; the unit diagonal elements of L are not stored. + REAL(R8Ki) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS matrix of right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices that define the permutation matrix P; row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, U(i,i) is exactly zero. The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed. + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = SIZE(B,2) + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGESV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGESV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGESV +!======================================================================= +!> general solve: Computes the solution to system of linear equations A * X = B for GE matrices. +!! use LAPACK_GESV (nwtc_lapack::lapack_gesv) instead of this specific function. + SUBROUTINE LAPACK_SGESV ( N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(SiKi) ,intent(inout) :: A( :, : ) !< On entry, the N-by-N coefficient matrix A. On exit, the factors L and U from the factorization A = P*L*U; the unit diagonal elements of L are not stored. + REAL(SiKi) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS matrix of right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices that define the permutation matrix P; row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, U(i,i) is exactly zero. The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed. + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = SIZE(B,2) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGESV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGESV: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGESV +!======================================================================= +!> general matrix factorization: Factor matrix into A=PLU. +!! use LAPACK_GETRF (nwtc_lapack::lapack_getrf) instead of this specific function. + SUBROUTINE LAPACK_DGETRF( M, N, A, IPIV, ErrStat, ErrMsg ) + + ! passed parameters + + INTEGER, intent(in ) :: M !< The number of rows of the matrix A. M >= 0. + INTEGER, intent(in ) :: N !< The number of columns of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(R8Ki) ,intent(inout) :: A( :, : ) !< On entry, the M-by-N matrix to be factored. On exit, the factors L and U from the factorization A = P*L*U; the unit diagonal elements of L are not stored. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices; for 1 <= i <= min(M,N), row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. The factor U is exactly singular. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + + LDA = SIZE(A,1) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGETRF( M, N, A, LDA, IPIV, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGETRF: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGETRF: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGETRF +!======================================================================= +!> general matrix factorization: Factor matrix into A=PLU. +!! use LAPACK_GETRF (nwtc_lapack::lapack_getrf) instead of this specific function. + SUBROUTINE LAPACK_SGETRF( M, N, A, IPIV, ErrStat, ErrMsg ) + + + ! passed parameters + + INTEGER, intent(in ) :: M !< The number of rows of the matrix A. M >= 0. + INTEGER, intent(in ) :: N !< The number of columns of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(SiKi) ,intent(inout) :: A( :, : ) !< On entry, the M-by-N matrix to be factored. On exit, the factors L and U from the factorization A = P*L*U; the unit diagonal elements of L are not stored. + INTEGER, intent( out) :: IPIV( : ) !< The pivot indices; for 1 <= i <= min(M,N), row i of the matrix was interchanged with row IPIV(i). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. The factor U is exactly singular. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + + LDA = SIZE(A,1) + + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SGETRF( M, N, A, LDA, IPIV, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGETRF: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGETRF: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Factor U is exactly singular.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGETRF +!======================================================================= +!> general solve of factorized matrix: Solve system of linear equations Ax=PLUx=b. +!! use LAPACK_GETRS (nwtc_lapack::lapack_getrs) instead of this specific function. + SUBROUTINE LAPACK_DGETRS( TRANS, N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANS !< Specifies the form of the system of equations: = 'N': A * X = B (No transpose) + !! = 'T': A**T* X = B (Transpose) + !! = 'C': A**T* X = B (Conjugate transpose = Transpose) + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< The pivot indices from DGETRF (nwtc_lapack::lapack_getrf); for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(R8Ki) ,intent(in ) :: A( :, : ) !< The factors L and U from the factorization A = P*L*U as computed by DGETRF. + REAL(R8Ki) ,intent(inout) :: B( :, : ) !< On entry, the right hand side matrix B. On exit, the solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = SIZE(B,2) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) -INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGETRS: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGETRS: unknown error -'//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGETRS +!======================================================================= +!> general solve of factorized matrix: Solve system of linear equations Ax=PLUx=b. +!! use LAPACK_GETRS (nwtc_lapack::lapack_getrs) instead of this specific function. + SUBROUTINE LAPACK_DGETRS1( TRANS, N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANS !< Specifies the form of the system of equations: = 'N': A * X = B (No transpose) + !! = 'T': A**T* X = B (Transpose) + !! = 'C': A**T* X = B (Conjugate transpose = Transpose) + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< The pivot indices from DGETRF (nwtc_lapack::lapack_getrf); for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(R8Ki) ,intent(in ) :: A( :, : ) !< The factors L and U from the factorization A = P*L*U as computed by DGETRF. + REAL(R8Ki) ,intent(inout) :: B( : ) !< On entry, the right hand side matrix B. On exit, the solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = 1 + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) -INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGETRS1: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGETRS1: unknown error -'//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGETRS1 +!======================================================================= +!> general solve of factorized matrix: Solve system of linear equations Ax=PLUx=b. +!! use LAPACK_GETRS (nwtc_lapack::lapack_getrs) instead of this specific function. + SUBROUTINE LAPACK_SGETRS( TRANS, N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANS !< Specifies the form of the system of equations: = 'N': A * X = B (No transpose) + !! = 'T': A**T* X = B (Transpose) + !! = 'C': A**T* X = B (Conjugate transpose = Transpose) + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< The pivot indices from DGETRF; for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(SiKi), intent(in ) :: A( :, : ) !< The factors L and U from the factorization A = P*L*U as computed by SGETRF. + REAL(SiKi), intent(inout) :: B( :, : ) !< On entry, the right hand side matrix B. On exit, the solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = SIZE(B,2) + + + ErrStat = ErrID_None + ErrMsg = "" + + !IF (ReKi == C_FLOAT) THEN + CALL SGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + !ELSEIF (ReKi == C_DOUBLE) THEN + ! CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + !ELSE + ! ErrStat = ErrID_FATAL + ! ErrMsg = "LAPACK_SGETRS: Matrix A is an invalid type." + ! RETURN + !END IF + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) -INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGETRS: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGETRS: unknown error -'//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGETRS +!======================================================================= +!> general solve of factorized matrix: Solve system of linear equations Ax=PLUx=b. +!! use LAPACK_GETRS (nwtc_lapack::lapack_getrs) instead of this specific function. + SUBROUTINE LAPACK_SGETRS1( TRANS, N, A, IPIV, B, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER(1), intent(in ) :: TRANS !< Specifies the form of the system of equations: = 'N': A * X = B (No transpose) + !! = 'T': A**T* X = B (Transpose) + !! = 'C': A**T* X = B (Conjugate transpose = Transpose) + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< The pivot indices from DGETRF; for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(SiKi), intent(in ) :: A( :, : ) !< The factors L and U from the factorization A = P*L*U as computed by SGETRF. + REAL(SiKi), intent(inout) :: B( : ) !< On entry, the right hand side matrix B. On exit, the solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + INTEGER :: NRHS ! The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + NRHS = 1 + + + ErrStat = ErrID_None + ErrMsg = "" + + + !IF (ReKi == C_FLOAT) THEN + CALL SGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + !ELSEIF (ReKi == C_DOUBLE) THEN + ! CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + !ELSE + ! ErrStat = ErrID_FATAL + ! ErrMsg = "LAPACK_SGETRS: Matrix A is an invalid type." + ! RETURN + !END IF + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) -INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGETRS1: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGETRS1: unknown error -'//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGETRS1 +!======================================================================= +!> Compute the inverse of a general matrix using the LU factorization. +!! use LAPACK_GETRI (nwtc_lapack::lapack_getri) instead of this specific function. + SUBROUTINE LAPACK_DGETRI( N, A, IPIV, WORK, LWORK, ErrStat, ErrMsg ) + + ! passed parameters + + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. LWORK >= max(1,N). For optimal performance LWORK >= N*NB, where NB is the optimal blocksize returned by ILAENV. + !! If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first + !! entry of the WORK array, and no error message related to LWORK is issued by XERBLA. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< dimension (N). The pivot indices from DGETRF; for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(R8Ki) ,intent(inout) :: A( :, : ) !< On entry, the factors L and U from the factorization A = P*L*U as computed by DGETRF. On exit, if INFO = 0, the inverse of the original matrix A. + REAL(R8Ki) ,intent(inout) :: WORK( : ) !< On exit, if INFO=0, then WORK(1) returns the optimal LWORK. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. The matrix is singular and its inverse could not be computed. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + + LDA = SIZE(A,1) + + ErrStat = ErrID_None + ErrMsg = "" + + !IF (DbKi == C_DOUBLE) THEN + CALL DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) + !ELSEIF (DbKi == C_FLOAT) THEN + ! CALL DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) + !ELSE + ! ErrStat = ErrID_FATAL + ! ErrMsg = "LAPACK_DGETRI: Matrix A is an invalid type." + ! RETURN + !END IF + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGETRI: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DGETRI: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Matrix is singular and its inverse cannot be computed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGETRI +!======================================================================= +!> Compute the inverse of a general matrix using the LU factorization. +!! use LAPACK_GETRI (nwtc_lapack::lapack_getri) instead of this specific function. + SUBROUTINE LAPACK_SGETRI( N, A, IPIV, WORK, LWORK, ErrStat, ErrMsg ) + + ! passed parameters + + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. LWORK >= max(1,N). For optimal performance LWORK >= N*NB, where NB is the optimal blocksize returned by ILAENV. + !! If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first + !! entry of the WORK array, and no error message related to LWORK is issued by XERBLA. + + ! .. Array Arguments .. + INTEGER, intent(in ) :: IPIV( : ) !< dimension (N). The pivot indices from DGETRF; for 1<=i<=N, row i of the matrix was interchanged with row IPIV(i). + REAL(SiKi), intent(inout) :: A( :, : ) !< On entry, the factors L and U from the factorization A = P*L*U as computed by SGETRF. On exit, if INFO = 0, the inverse of the original matrix A. + REAL(SiKi), intent(inout) :: WORK( : ) !< On exit, if INFO=0, then WORK(1) returns the optimal LWORK. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. The matrix is singular and its inverse could not be computed. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + + LDA = SIZE(A,1) + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL SGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGETRI: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SGETRI: U('//TRIM(ErrMsg)//','//TRIM(ErrMsg)//')=0. Matrix is singular and its inverse cannot be computed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGETRI +!======================================================================= +!> Compute generalized eigenvalues and/or eigenvectors for a pair of N-by-N real nonsymmetric matrices (A,B). +!! use LAPACK_GGEV (nwtc_lapack::lapack_ggev) instead of this specific function. + SUBROUTINE LAPACK_DGGEV(JOBVL, JOBVR, N, A, B, ALPHAR, ALPHAI, BETA, VL, VR, WORK, LWORK, ErrStat, ErrMsg) + + ! passed variables/parameters: + + CHARACTER(1), intent(in ) :: JOBVL !< = 'N': do not compute the left generalized eigenvectors; = 'V': compute the left generalized eigenvectors. + CHARACTER(1), intent(in ) :: JOBVR !< = 'N': do not compute the right generalized eigenvectors; = 'V': compute the right generalized eigenvectors. + + INTEGER, intent(in ) :: N !< The order of the matrices A, B, VL, and VR. N >= 0. + + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. LWORK >= max(1,8*N). For good performance, LWORK must generally be larger. + !! If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns + !! this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. + + + REAL(R8Ki) ,intent(inout) :: A( :, : ) !< dimension (LDA, N). On entry, the matrix A in the pair (A,B). On exit, A has been overwritten. + REAL(R8Ki) ,intent(inout) :: B( :, : ) !< dimension (LDB, N). On entry, the matrix B in the pair (A,B). On exit, B has been overwritten. + + REAL(R8Ki) ,intent( out) :: ALPHAR( : ) !< dimension (N). See comments for variable "Beta" + REAL(R8Ki) ,intent( out) :: ALPHAI( : ) !< dimension (N). See comments for variable "Beta". + REAL(R8Ki) ,intent( out) :: BETA( : ) !< On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will be the generalized eigenvalues. If ALPHAI(j) is zero, then + !! the j-th eigenvalue is real; if positive, then the j-th and (j+1)-st eigenvalues are a complex conjugate pair, with + !! ALPHAI(j+1) negative. + !! + !! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + !! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + !! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). + + + REAL(R8Ki) ,intent( out) :: VL( :, : ) !< dimension (LDVL,N). If JOBVL = 'V', the left eigenvectors u(j) are stored one after another in the columns of VL, in the same + !! order as their eigenvalues. If the j-th eigenvalue is real, then u(j) = VL(:,j), the j-th column of VL. If the j-th and + !! (j+1)-th eigenvalues form a complex conjugate pair, then u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1). + !! Each eigenvector is scaled so the largest component has abs(real part)+abs(imag. part)=1. Not referenced if JOBVL = 'N'. + REAL(R8Ki) ,intent( out) :: VR( :, : ) !< dimension (LDVR,N). If JOBVR = 'V', the right eigenvectors v(j) are stored one after another in the columns of VR, in the same + !! order as their eigenvalues. If the j-th eigenvalue is real, then v(j) = VR(:,j), the j-th column of VR. If the j-th and + !! (j+1)-th eigenvalues form a complex conjugate pair, then v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). + !! Each eigenvector is scaled so the largest component has abs(real part)+abs(imag. part)=1. Not referenced if JOBVR = 'N'. + + REAL(R8Ki) ,intent(inout) :: WORK( : ) !< dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK. + + + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ! local variables + INTEGER :: INFO ! = 0: successful exit; + ! < 0: + ! = -i, the i-th argument had an illegal value; + ! > 0: + ! = 1,...,N: The QZ iteration failed. No eigenvectors have been calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j=INFO+1,...,N. + ! = N+1: other than QZ iteration failed in DHGEQZ. + ! = N+2: error return from DTGEVC. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + INTEGER :: LDVL ! The leading dimension of the matrix VL. LDVL >= 1, and if JOBVL = 'V', LDVL >= N + INTEGER :: LDVR ! The leading dimension of the matrix VR. LDVR >= 1, and if JOBVR = 'V', LDVR >= N. + CHARACTER(20) :: n_str + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + LDVL = SIZE(VL,1) + LDVR = SIZE(VR,1) + + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGGEV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGGEV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSEIF (INFO <N) THEN + !ErrStat = ErrID_Severe + WRITE( ErrMsg, * ) INFO + 1 + WRITE( n_str, * ) n + ErrMsg = "LAPACK_DGGEV: The QZ iteration failed. No eigenvectors have been calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j="& + //TRIM(ErrMsg)//",...,"//TRIM(n_str)//"." + ELSEIF (INFO == N ) THEN + ErrMsg = "LAPACK_DGGEV: The QZ iteration failed. No eigenvectors have been calculated." + ELSEIF (INFO == N+1) THEN + ErrMsg = "LAPACK_DGGEV: other than QZ iteration failed in DHGEQZ." + ELSEIF (INFO == N+2) THEN + ErrMsg = "LAPACK_DGGEV: error return from DTGEVC." + ELSE + ErrMsg = 'LAPACK_DGGEV: unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DGGEV +!======================================================================= +!> Compute generalized eigenvalues and/or eigenvectors for a pair of N-by-N real nonsymmetric matrices (A,B). +!! use LAPACK_GGEV (nwtc_lapack::lapack_ggev) instead of this specific function. + SUBROUTINE LAPACK_SGGEV(JOBVL, JOBVR, N, A, B, ALPHAR, ALPHAI, BETA, VL, VR, WORK, LWORK, ErrStat, ErrMsg) + + ! subroutine arguments + + CHARACTER(1), intent(in ) :: JOBVL !< = 'N': do not compute the left generalized eigenvectors; = 'V': compute the left generalized eigenvectors. + CHARACTER(1), intent(in ) :: JOBVR !< = 'N': do not compute the right generalized eigenvectors; = 'V': compute the right generalized eigenvectors. + + INTEGER, intent(in ) :: N !< The order of the matrices A, B, VL, and VR. N >= 0. + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. LWORK >= max(1,8*N). For good performance, LWORK must generally be larger. + !! If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns + !! this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. + + + REAL(SiKi), intent(inout) :: A( :, : ) !< dimension (LDA, N). On entry, the matrix A in the pair (A,B). On exit, A has been overwritten. + REAL(SiKi), intent(inout) :: B( :, : ) !< dimension (LDB, N). On entry, the matrix B in the pair (A,B). On exit, B has been overwritten. + + + REAL(SiKi), intent( out) :: ALPHAR( : ) !< dimension (N). See comments for variable "Beta" + REAL(SiKi), intent( out) :: ALPHAI( : ) !< dimension (N). See comments for variable "Beta". + REAL(SiKi), intent( out) :: BETA( : ) !< On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will be the generalized eigenvalues. If ALPHAI(j) is zero, then + !! the j-th eigenvalue is real; if positive, then the j-th and (j+1)-st eigenvalues are a complex conjugate pair, with + !! ALPHAI(j+1) negative. + !! + !! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + !! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + !! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). + + + REAL(SiKi), intent( out) :: VL( :, : ) !< dimension (LDVL,N). If JOBVL = 'V', the left eigenvectors u(j) are stored one after another in the columns of VL, in the same + !! order as their eigenvalues. If the j-th eigenvalue is real, then u(j) = VL(:,j), the j-th column of VL. If the j-th and + !! (j+1)-th eigenvalues form a complex conjugate pair, then u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1). + !! Each eigenvector is scaled so the largest component has abs(real part)+abs(imag. part)=1. Not referenced if JOBVL = 'N'. + REAL(SiKi), intent( out) :: VR( :, : ) !< dimension (LDVR,N). If JOBVR = 'V', the right eigenvectors v(j) are stored one after another in the columns of VR, in the same + !! order as their eigenvalues. If the j-th eigenvalue is real, then v(j) = VR(:,j), the j-th column of VR. If the j-th and + !! (j+1)-th eigenvalues form a complex conjugate pair, then v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). + !! Each eigenvector is scaled so the largest component has abs(real part)+abs(imag. part)=1. Not referenced if JOBVR = 'N'. + + REAL(SiKi), intent(inout) :: WORK( : ) !< dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK. + + + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit; + ! < 0: + ! = -i, the i-th argument had an illegal value; + ! > 0: + ! = 1,...,N: The QZ iteration failed. No eigenvectors have been calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j=INFO+1,...,N. + ! = N+1: other than QZ iteration failed in SHGEQZ. + ! = N+2: error return from STGEVC. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + INTEGER :: LDVL ! The leading dimension of the matrix VL. LDVL >= 1, and if JOBVL = 'V', LDVL >= N + INTEGER :: LDVR ! The leading dimension of the matrix VR. LDVR >= 1, and if JOBVR = 'V', LDVR >= N. + CHARACTER(20) :: n_str + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + LDVL = SIZE(VL,1) + LDVR = SIZE(VR,1) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SGGEV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGGEV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSEIF (INFO <=N) THEN + !ErrStat = ErrID_Severe + WRITE( ErrMsg, * ) INFO + 1 + WRITE( n_str, * ) n + ErrMsg = "LAPACK_SGGEV: The QZ iteration failed. No eigenvectors have been calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) should be correct for j="& + //TRIM(ErrMsg)//",...,"//TRIM(n_str)//"." + ELSEIF (INFO == N ) THEN + ErrMsg = "LAPACK_SGGEV: The QZ iteration failed. No eigenvectors have been calculated." + ELSEIF (INFO == N+1) THEN + ErrMsg = "LAPACK_SGGEV: other than QZ iteration failed in SHGEQZ." + ELSEIF (INFO == N+2) THEN + ErrMsg = "LAPACK_SGGEV: error return from STGEVC." + ELSE + ErrMsg = 'LAPACK_SGGEV: unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SGGEV +!======================================================================= +!> Compute the solution to system of linear equations A * X = B for PO (positive-definite) matrices. +!! use LAPACK_POSV (nwtc_lapack::lapack_posv) instead of this specific function. + SUBROUTINE LAPACK_DPOSV (UPLO, N, NRHS, A, B, ErrStat, ErrMsg) + + + ! passed parameters + + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + INTEGER, intent(in ) :: NRHS !< The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + + ! .. Array Arguments .. + REAL(R8Ki) ,intent(inout) :: A( :, : ) !< On entry, the symmetric matrix A. If UPLO = 'U', the leading N-by-N upper triangular part of A contains the upper + !! triangular part of the matrix A, and the strictly lower triangular part of A is not referenced. If UPLO = 'L', the + !! leading N-by-N lower triangular part of A contains the lower triangular part of the matrix A, and the strictly upper + !! triangular part of A is not referenced. + !! On exit, if INFO = 0, the factor U or L from the Cholesky factorization A = U**T*U or A = L*L**T. + REAL(R8Ki) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS matrix of right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + CHARACTER(1), intent(in ) :: UPLO !< 'U': Upper triangle of A is stored; 'L': Lower triangle of A is stored. + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, the leading minor of order i of A is not positive definite, so the factorization could not be + ! completed, and the solution has not been computed. + + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DPOSV (UPLO, N, NRHS, A, LDA, B, LDB, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DPOSV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DPOSV: Leading minor order '//TRIM(ErrMsg)//' of A is not positive definite, so factorization could not be completed, and the solution has not been computed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DPOSV +!======================================================================= +!> Compute the solution to system of linear equations A * X = B for PO (positive-definite) matrices. +!! use LAPACK_POSV (nwtc_lapack::lapack_posv) instead of this specific function. + SUBROUTINE LAPACK_SPOSV (UPLO, N, NRHS, A, B, ErrStat, ErrMsg) + + + ! passed parameters + + INTEGER, intent(in ) :: N !< The number of linear equations, i.e., the order of the matrix A. N >= 0. + INTEGER, intent(in ) :: NRHS !< The number of right hand sides, i.e., the number of columns of the matrix B. NRHS >= 0. + + ! .. Array Arguments .. + REAL(SiKi) ,intent(inout) :: A( :, : ) !< On entry, the symmetric matrix A. If UPLO = 'U', the leading N-by-N upper triangular part of A contains the upper + !! triangular part of the matrix A, and the strictly lower triangular part of A is not referenced. If UPLO = 'L', the + !! leading N-by-N lower triangular part of A contains the lower triangular part of the matrix A, and the strictly upper + !! triangular part of A is not referenced. + !! On exit, if INFO = 0, the factor U or L from the Cholesky factorization A = U**T*U or A = L*L**T. + REAL(SiKi) ,intent(inout) :: B( :, : ) !< On entry, the N-by-NRHS matrix of right hand side matrix B. On exit, if INFO = 0, the N-by-NRHS solution matrix X. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + CHARACTER(1), intent(in ) :: UPLO !< 'U': Upper triangle of A is stored; 'L': Lower triangle of A is stored. + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; > 0: if INFO = i, U(i,i) is exactly zero. + ! > 0: if INFO = i, the leading minor of order i of A is not positive definite, so the factorization could not be + ! completed, and the solution has not been computed. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,N). + INTEGER :: LDB ! The leading dimension of the array B. LDB >= max(1,N). + + + LDA = SIZE(A,1) + LDB = SIZE(B,1) + + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SPOSV (UPLO, N, NRHS, A, LDA, B, LDB, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SPOSV: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SPOSV: Leading minor order '//TRIM(ErrMsg)//' of A is not positive definite, so factorization could not be completed, and the solution has not been computed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SPOSV +!======================================================================= +!> Compute the Cholesky factorization of a real symmetric positive definite matrix A stored in packed format. +!! use LAPACK_PPTRF (nwtc_lapack::lapack_pptrf) instead of this specific function. + SUBROUTINE LAPACK_DPPTRF (UPLO, N, AP, ErrStat, ErrMsg) + + ! DPPTRF computes the Cholesky factorization of a real symmetric + ! positive definite matrix A stored in packed format. + ! + ! The factorization has the form + ! A = U**T * U, if UPLO = 'U', or + ! A = L * L**T, if UPLO = 'L', + ! where U is an upper triangular matrix and L is lower triangular. + + + ! passed parameters + + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(R8Ki) ,intent(inout) :: AP( : ) !< AP is REAL array, dimension (N*(N+1)/2) + !! On entry, the upper or lower triangle of the symmetric matrix A, packed columnwise in a linear array. The j-th column of A + !! is stored in the array AP as follows: + !! if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; + !! if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n. + !! See below for further details. + !! On exit, if INFO = 0, the triangular factor U or L from the Cholesky factorization A = U**T*U or A = L*L**T, in the same storage format as A. + !! + !! Further details: + !! The packed storage scheme is illustrated by the following example + !! when N = 4, UPLO = 'U': + !! + !! Two-dimensional storage of the symmetric matrix A: + !! + !! a11 a12 a13 a14 + !! a22 a23 a24 + !! a33 a34 (aij = aji) + !! a44 + !! + !! Packed storage of the upper triangle of A: + !! + !! AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ] + + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + CHARACTER(1), intent(in ) :: UPLO !< 'U': Upper triangle of A is stored; 'L': Lower triangle of A is stored. + + + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + ! > 0: if INFO = i, the leading minor of order i is not positive definite, and the factorization could not be completed. + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DPPTRF (UPLO, N, AP, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DPPTRF: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DPPTRF: Leading minor order '//TRIM(ErrMsg)//' of A is not positive definite, so Cholesky factorization could not be completed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_DPPTRF +!======================================================================= +!> Compute the Cholesky factorization of a real symmetric positive definite matrix A stored in packed format. +!! use LAPACK_PPTRF (nwtc_lapack::lapack_pptrf) instead of this specific function. + SUBROUTINE LAPACK_SPPTRF (UPLO, N, AP, ErrStat, ErrMsg) + + ! SPPTRF computes the Cholesky factorization of a real symmetric + ! positive definite matrix A stored in packed format. + ! + ! The factorization has the form + ! A = U**T * U, if UPLO = 'U', or + ! A = L * L**T, if UPLO = 'L', + ! where U is an upper triangular matrix and L is lower triangular. + + + ! passed parameters + + INTEGER, intent(in ) :: N !< The order of the matrix A. N >= 0. + + ! .. Array Arguments .. + REAL(SiKi) ,intent(inout) :: AP( : ) !< AP is REAL array, dimension (N*(N+1)/2) + !! On entry, the upper or lower triangle of the symmetric matrix A, packed columnwise in a linear array. The j-th column of A + !! is stored in the array AP as follows: + !! if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; + !! if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n. + !! See LAPACK_DPPTRF for further details. + !! On exit, if INFO = 0, the triangular factor U or L from the Cholesky factorization A = U**T*U or A = L*L**T, in the same storage format as A. + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + CHARACTER(1), intent(in ) :: UPLO !< 'U': Upper triangle of A is stored; 'L': Lower triangle of A is stored. + + ! local variables + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value; + ! > 0: if INFO = i, the leading minor of order i is not positive definite, and the factorization could not be completed + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SPPTRF (UPLO, N, AP, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SPPTRF: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_SPPTRF: Leading minor order '//TRIM(ErrMsg)//' of A is not positive definite, so Cholesky factorization could not be completed.' + END IF + END IF + + + RETURN + END SUBROUTINE LAPACK_SPPTRF +!======================================================================= +!> Compute singular value decomposition (SVD) for a general matrix, A. +!! use LAPACK_DGESVD (nwtc_lapack::lapack_dgesvd) instead of this specific function. + SUBROUTINE LAPACK_DGESVD(JOBU, JOBVT, M, N, A, S, U, VT, WORK, LWORK, ErrStat, ErrMsg) + + ! passed variables/parameters: + + CHARACTER(1), intent(in ) :: JOBU !< 'A': all M columns of U are returned in array U; + !! 'S': the first min(m,n) columns of U (the left singular + !! vectors) are returned in the array U; + !! 'O': the first min(m,n) columns of U (the left singular + !! vectors) are overwritten on the array A; + !! 'N': no columns of U (no left singular vectors) are + !! computed. + CHARACTER(1), intent(in ) :: JOBVT !< 'A': all N rows of V^T are returned in the array VT; + !! 'S': the first min(m,n) rows of V^T (the right singular + !! vectors) are returned in the array VT; + !! 'O': the first min(m,n) rows of V^T (the right singular + !! vectors) are overwritten on the array A; + !! 'N': no rows of V**T (no right singular vectors) are + !! computed. + + INTEGER, intent(in ) :: M !< The number of rows of the input matrix A. M >= 0. + INTEGER, intent(in ) :: N !< The number of columns of the input matrix A. N >= 0. + + REAL(R8Ki), intent(inout) :: A( :, : ) !< A is DOUBLE PRECISION array, dimension (LDA,N) + !! On entry, the M-by-N matrix A. + !! On exit, + !! if JOBU = 'O', A is overwritten with the first min(m,n) + !! columns of U (the left singular vectors, + !! stored columnwise); + !! if JOBVT = 'O', A is overwritten with the first min(m,n) + !! rows of V**T (the right singular vectors, + !! stored rowwise); + !! if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A + !! are destroyed. + + REAL(R8Ki), intent( out) :: S( : ) !< S is DOUBLE PRECISION array, dimension (min(M,N)) + !! The singular values of A, sorted so that S(i) >= S(i+1). + REAL(R8Ki), intent( out) :: U( :, : ) !< U is DOUBLE PRECISION array, dimension (LDU,UCOL) + !! (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'. + !! If JOBU = 'A', U contains the M-by-M orthogonal matrix U; + !! if JOBU = 'S', U contains the first min(m,n) columns of U + !! (the left singular vectors, stored columnwise); + !! if JOBU = 'N' or 'O', U is not referenced. + REAL(R8Ki), intent( out) :: VT( :, : ) !< VT is DOUBLE PRECISION array, dimension (LDVT,N) + !! If JOBVT = 'A', VT contains the N-by-N orthogonal matrix + !! V**T; + !! if JOBVT = 'S', VT contains the first min(m,n) rows of + !! V**T (the right singular vectors, stored rowwise); + !! if JOBVT = 'N' or 'O', VT is not referenced. + + REAL(R8Ki), intent(inout) :: WORK( : ) !< dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK. + + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. + !! LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code): + !! - PATH 1 (M much larger than N, JOBU='N') + !! - PATH 1t (N much larger than M, JOBVT='N') + !! LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths + !! For good performance, LWORK should generally be larger. + !! If LWORK = -1, then a workspace query is assumed; the routine + !! only calculates the optimal size of the WORK array, returns + !! this value as the first entry of the WORK array, and no error + !! message related to LWORK is issued by XERBLA. + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit. + ! < 0: if INFO = -i, the i-th argument had an illegal value. + ! > 0: if DBDSQR did not converge, INFO specifies how many + ! superdiagonals of an intermediate bidiagonal form B + ! did not converge to zero. See the description of WORK + ! above for details. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + INTEGER :: LDU ! The leading dimension of the array U. LDU >= 1; if JOBU = 'S' or 'A', LDU >= M. + INTEGER :: LDVT ! The leading dimension of the array VT. LDVT >= 1; if + !! JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N). + + LDA = SIZE(A,1) + LDU = SIZE(U,1) + LDVT = SIZE(VT,1) + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DGESVD(JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DGESVD: illegal value in argument "//TRIM(ErrMsg)//"." + ELSEIF (INFO > 0) THEN + !ErrStat = ErrID_Severe + ErrMsg = "DBDSQR did not converge, INFO specifies how many superdiagonals of an intermediate bidiagonal form B did not converge to zero"& + //TRIM(ErrMsg)//",...,"//"." + ELSE + ErrMsg = 'LAPACK_DGESVD: unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + RETURN + END SUBROUTINE LAPACK_DGESVD +!======================================================================= +!> Compute singular value decomposition (SVD) for a general matrix, A. +!! use LAPACK_SGESVD (nwtc_lapack::lapack_sgesvd) instead of this specific function. + SUBROUTINE LAPACK_SGESVD(JOBU, JOBVT, M, N, A, S, U, VT, WORK, LWORK, ErrStat, ErrMsg) + + ! passed variables/parameters: + + CHARACTER(1), intent(in ) :: JOBU !< 'A': all M columns of U are returned in array U; + !! 'S': the first min(m,n) columns of U (the left singular + !! vectors) are returned in the array U; + !! 'O': the first min(m,n) columns of U (the left singular + !! vectors) are overwritten on the array A; + !! 'N': no columns of U (no left singular vectors) are + !! computed. + CHARACTER(1), intent(in ) :: JOBVT !< 'A': all N rows of V^T are returned in the array VT; + !! 'S': the first min(m,n) rows of V^T (the right singular + !! vectors) are returned in the array VT; + !! 'O': the first min(m,n) rows of V^T (the right singular + !! vectors) are overwritten on the array A; + !! 'N': no rows of V**T (no right singular vectors) are + !! computed. + + INTEGER, intent(in ) :: M !< The number of rows of the input matrix A. M >= 0. + INTEGER, intent(in ) :: N !< The number of columns of the input matrix A. N >= 0. + + REAL(SiKi), intent(inout) :: A( :, : ) !< A is SINGLE PRECISION array, dimension (LDA,N) + !! On entry, the M-by-N matrix A. + !! On exit, + !! if JOBU = 'O', A is overwritten with the first min(m,n) + !! columns of U (the left singular vectors, + !! stored columnwise); + !! if JOBVT = 'O', A is overwritten with the first min(m,n) + !! rows of V**T (the right singular vectors, + !! stored rowwise); + !! if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A + !! are destroyed. + + REAL(SiKi), intent( out) :: S( : ) !< S is SINGLE PRECISION array, dimension (min(M,N)) + !! The singular values of A, sorted so that S(i) >= S(i+1). + REAL(SiKi), intent( out) :: U( :, : ) !< U is SINGLE PRECISION array, dimension (LDU,UCOL) + !! (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'. + !! If JOBU = 'A', U contains the M-by-M orthogonal matrix U; + !! if JOBU = 'S', U contains the first min(m,n) columns of U + !! (the left singular vectors, stored columnwise); + !! if JOBU = 'N' or 'O', U is not referenced. + REAL(SiKi), intent( out) :: VT( :, : ) !< VT is SINGLE PRECISION array, dimension (LDVT,N) + !! If JOBVT = 'A', VT contains the N-by-N orthogonal matrix + !! V**T; + !! if JOBVT = 'S', VT contains the first min(m,n) rows of + !! V**T (the right singular vectors, stored rowwise); + !! if JOBVT = 'N' or 'O', VT is not referenced. + + REAL(SiKi), intent(inout) :: WORK( : ) !< dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK. + + INTEGER, intent(in ) :: LWORK !< The dimension of the array WORK. + !! LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code): + !! - PATH 1 (M much larger than N, JOBU='N') + !! - PATH 1t (N much larger than M, JOBVT='N') + !! LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths + !! For good performance, LWORK should generally be larger. + !! If LWORK = -1, then a workspace query is assumed; the routine + !! only calculates the optimal size of the WORK array, returns + !! this value as the first entry of the WORK array, and no error + !! message related to LWORK is issued by XERBLA. + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + INTEGER :: INFO ! = 0: successful exit. + ! < 0: if INFO = -i, the i-th argument had an illegal value. + ! > 0: if SBDSQR did not converge, INFO specifies how many + ! superdiagonals of an intermediate bidiagonal form B + ! did not converge to zero. See the description of WORK + ! above for details. + INTEGER :: LDA ! The leading dimension of the array A. LDA >= max(1,M). + INTEGER :: LDU ! The leading dimension of the array U. LDU >= 1; if JOBU = 'S' or 'A', LDU >= M. + INTEGER :: LDVT ! The leading dimension of the array VT. LDVT >= 1; if + !! JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N). + + LDA = SIZE(A,1) + LDU = SIZE(U,1) + LDVT = SIZE(VT,1) + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SGESVD(JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_SGESVD: illegal value in argument "//TRIM(ErrMsg)//"." + ELSEIF (INFO > 0) THEN + !ErrStat = ErrID_Severe + ErrMsg = "DBDSQR did not converge, INFO specifies how many superdiagonals of an intermediate bidiagonal form B did not converge to zero"& + //TRIM(ErrMsg)//",...,"//"." + ELSE + ErrMsg = 'LAPACK_SGESVD: unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + RETURN + END SUBROUTINE LAPACK_SGESVD +!======================================================================= +END MODULE NWTC_LAPACK diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/NWTC_ScaLAPACK.f90 b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/NWTC_ScaLAPACK.f90 new file mode 100644 index 000000000..556220d10 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/NWTC_ScaLAPACK.f90 @@ -0,0 +1,107 @@ +!********************************************************************************************************************************** +! Copyright (C) 2013-2014 National Renewable Energy Laboratory +! +! This code provides a wrapper for the ScaLAPACK routines currently used at the NWTC (mainly codes in the FAST framework). +! +!********************************************************************************************************************************** +MODULE NWTC_ScaLAPACK + + USE NWTC_Base ! we only need the precision and error level constants +! USE, INTRINSIC :: ISO_C_Binding, only: C_FLOAT, C_DOUBLE ! this is included in NWTC_Library + + ! Notes: + + ! Your project must include the following files: + ! NWTC_Base.f90 [from NWTC Library] + ! NWTC_ScaLAPACK.f90 + ! dlasrt2.f + ! slasrt2.f + + IMPLICIT NONE + + INTERFACE ScaLAPACK_LASRT ! sort + MODULE PROCEDURE ScaLAPACK_DLASRT2 + MODULE PROCEDURE ScaLAPACK_SLASRT2 + END INTERFACE + + + +CONTAINS + +!======================================================================= +!INTERFACE ScaLAPACK_LASRT: +! Sort the numbers in D in increasing order (if ID = 'I') or in decreasing order (if ID = 'D' ). +! See documentation in DLASRT2/SLASRT2 source code. + SUBROUTINE ScaLAPACK_DLASRT2( ID, N, D, KEY, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER, intent(in ) :: ID ! = 'I': sort D in increasing order; = 'D': sort D in decreasing order. + INTEGER, intent(in ) :: N ! The length of the array D. + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + ! .. Array Arguments .. + INTEGER, intent(inout) :: KEY( : ) + DOUBLE PRECISION,intent(inout) :: D( : ) ! On entry, the array to be sorted. On exit, D has been sorted into increasing/decreasing order, depending on ID + + ! Local variable + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL DLASRT2( ID, N, D, KEY, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "ScaLAPACK_DLSRT2: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'ScaLAPACK_DLSRT2: Unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE ScaLAPACK_DLASRT2 +!======================================================================= + SUBROUTINE ScaLAPACK_SLASRT2( ID, N, D, KEY, ErrStat, ErrMsg ) + + ! passed parameters + + CHARACTER, intent(in ) :: ID ! = 'I': sort D in increasing order; = 'D': sort D in decreasing order. + INTEGER, intent(in ) :: N ! The length of the array D. + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + ! .. Array Arguments .. + INTEGER, intent(inout) :: KEY( : ) + REAL, intent(inout) :: D( : ) ! On entry, the array to be sorted. On exit, D has been sorted into increasing/decreasing order, depending on ID + + ! Local variable + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SLASRT2( ID, N, D, KEY, INFO ) + + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "ScaLAPACK_SLSRT2: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'ScaLAPACK_SLSRT2: Unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + + + RETURN + END SUBROUTINE ScaLAPACK_SLASRT2 +!======================================================================= +END MODULE NWTC_ScaLAPACK diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/dlasrt2.f b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/dlasrt2.f new file mode 100644 index 000000000..b134da5c3 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/dlasrt2.f @@ -0,0 +1,270 @@ +* +* + SUBROUTINE DLASRT2( ID, N, D, KEY, INFO ) +* +* -- ScaLAPACK routine (version 1.7) -- +* University of Tennessee, Knoxville, Oak Ridge National Laboratory, +* and University of California, Berkeley. +* May 1, 1997 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + INTEGER KEY( * ) + DOUBLE PRECISION D( * ) +* .. +* +* Purpose +* ======= +* +* Sort the numbers in D in increasing order (if ID = 'I') or +* in decreasing order (if ID = 'D' ). +* +* Use Quick Sort, reverting to Insertion sort on arrays of +* size <= 20. Dimension of STACK limits N to about 2**32. +* +* Arguments +* ========= +* +* ID (input) CHARACTER*1 +* = 'I': sort D in increasing order; +* = 'D': sort D in decreasing order. +* +* N (input) INTEGER +* The length of the array D. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the array to be sorted. +* On exit, D has been sorted into increasing order +* (D(1) <= ... <= D(N) ) or into decreasing order +* (D(1) >= ... >= D(N) ), depending on ID. +* +* KEY (input/output) INTEGER array, dimension (N) +* On entry, KEY contains a key to each of the entries in D() +* Typically, KEY(I) = I for all I +* On exit, KEY is permuted in exactly the same manner as +* D() was permuted from input to output +* Therefore, if KEY(I) = I for all I upon input, then +* D_out(I) = D_in(KEY(I)) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT, TMPKEY + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + TMPKEY = KEY( J ) + KEY( J ) = KEY( J-1 ) + KEY( J-1 ) = TMPKEY + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + TMPKEY = KEY( J ) + KEY( J ) = KEY( J-1 ) + KEY( J-1 ) = TMPKEY + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + TMPKEY = KEY( J ) + KEY( J ) = KEY( I ) + KEY( I ) = TMPKEY + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + TMPKEY = KEY( J ) + KEY( J ) = KEY( I ) + KEY( I ) = TMPKEY + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 +* +* + RETURN +* +* End of DLASRT2 +* + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/slasrt2.f b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/slasrt2.f new file mode 100644 index 000000000..7c4b9ce2d --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/scalapack/slasrt2.f @@ -0,0 +1,270 @@ +* +* + SUBROUTINE SLASRT2( ID, N, D, KEY, INFO ) +* +* -- ScaLAPACK routine (version 1.7) -- +* University of Tennessee, Knoxville, Oak Ridge National Laboratory, +* and University of California, Berkeley. +* May 1, 1997 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + INTEGER KEY( * ) + REAL D( * ) +* .. +* +* Purpose +* ======= +* +* Sort the numbers in D in increasing order (if ID = 'I') or +* in decreasing order (if ID = 'D' ). +* +* Use Quick Sort, reverting to Insertion sort on arrays of +* size <= 20. Dimension of STACK limits N to about 2**32. +* +* Arguments +* ========= +* +* ID (input) CHARACTER*1 +* = 'I': sort D in increasing order; +* = 'D': sort D in decreasing order. +* +* N (input) INTEGER +* The length of the array D. +* +* D (input/output) REAL array, dimension (N) +* On entry, the array to be sorted. +* On exit, D has been sorted into increasing order +* (D(1) <= ... <= D(N) ) or into decreasing order +* (D(1) >= ... >= D(N) ), depending on ID. +* +* KEY (input/output) INTEGER array, dimension (N) +* On entry, KEY contains a key to each of the entries in D() +* Typically, KEY(I) = I for all I +* On exit, KEY is permuted in exactly the same manner as +* D() was permuted from input to output +* Therefore, if KEY(I) = I for all I upon input, then +* D_out(I) = D_in(KEY(I)) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT, TMPKEY + REAL D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'SLASRT2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + TMPKEY = KEY( J ) + KEY( J ) = KEY( J-1 ) + KEY( J-1 ) = TMPKEY + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + TMPKEY = KEY( J ) + KEY( J ) = KEY( J-1 ) + KEY( J-1 ) = TMPKEY + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + TMPKEY = KEY( J ) + KEY( J ) = KEY( I ) + KEY( I ) = TMPKEY + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + TMPKEY = KEY( J ) + KEY( J ) = KEY( I ) + KEY( I ) = TMPKEY + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 +* +* + RETURN +* +* End of SLASRT2 +* + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/NWTC_SLATEC.f90 b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/NWTC_SLATEC.f90 new file mode 100644 index 000000000..68fe20777 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/NWTC_SLATEC.f90 @@ -0,0 +1,67 @@ +!********************************************************************************************************************************** +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +!> This code provides a wrapper for the SLATEC routines currently used at the NWTC (mainly codes in the FAST framework). This +!! enables us to call generic routines (not single- or double-precision specific ones) so that we don't have to change source +!! code to compile in double vs. single precision. +! +!********************************************************************************************************************************** +MODULE NWTC_SLATEC + + USE NWTC_Base ! we only need the precision and error level constants + + + ! Notes: + + ! Your project must include the following files: + ! From the NWTC Subroutine Library: + ! SingPrec.f90 [from NWTC Library] + ! Sys*.f90 [from NWTC Library] + ! NWTC_Base.f90 [from NWTC Library] + ! lapack library (preferably a binary, but available in source form from http://www.netlib.org/, too) + ! This wrapper file: + ! NWTC_SLATEC.f90 + + ! NOTES: + ! The routines in the slatec library use REAL and DOUBLE PRECISION. When compiling in double precision + ! the -fdefault-real-8 option is used, which promotes all DOUBLE to QUAD. Therefore the interaces here + ! are done using ReKi and DBKi to interface to the appropriate library. This allows the user to specify + ! the typing of variables passed to these routines as ReKi, DBKi, or R8Ki. + ! Note that SiKi can'bt be specified in the calling variable type as it will still be kind=4, which + ! won't have any promoted routines to match to in DOUBLE precision compiles. + + ! http://www.netlib.org/slatec/explore-html/ + + + IMPLICIT NONE + + !> integrate an external function using the 61-point kronrod rule + interface slatec_qk61 + module procedure wrap_qk61 + module procedure wrap_dqk61 + end interface + + CONTAINS + + + !> Single precision wrapper for the qk61 integration routine from the slatec library + !! Note that the qk61 routine follows -fdefault-real-8 setting, so it is of type ReKi + subroutine wrap_qk61(func,low,hi,answer,abserr,resabs,resasc) + real(ReKi), intent(in ) :: low,hi ! integration limits + real(ReKi), intent( out) :: answer + real(ReKi), intent(in ) :: abserr,resabs,resasc + real(ReKi), external :: func ! function + call qk61(func,low,hi,answer,abserr,resabs,resasc) + end subroutine wrap_qk61 + + !> Double precision wrapper for the dqk61 integration routine from the slatec library + !! Note that the qk61 routine follows -fdefault-real-8 setting, so it is of type DbKi + subroutine wrap_dqk61(func,low,hi,answer,abserr,resabs,resasc) + real(DbKi), intent(in ) :: low,hi ! integration limits + real(DbKi), intent( out) :: answer + real(DbKi), intent(in ) :: abserr,resabs,resasc + real(DbKi), external :: func ! function + call dqk61(func,low,hi,answer,abserr,resabs,resasc) + end subroutine wrap_dqk61 + +END MODULE NWTC_SLATEC diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/aaaaaa.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/aaaaaa.f new file mode 100644 index 000000000..ef2a541e9 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/aaaaaa.f @@ -0,0 +1,71 @@ +*DECK AAAAAA + SUBROUTINE AAAAAA (VER) +C***BEGIN PROLOGUE AAAAAA +C***PURPOSE SLATEC Common Mathematical Library disclaimer and version. +C***LIBRARY SLATEC +C***CATEGORY Z +C***TYPE ALL (AAAAAA-A) +C***KEYWORDS DISCLAIMER, DOCUMENTATION, VERSION +C***AUTHOR SLATEC Common Mathematical Library Committee +C***DESCRIPTION +C +C The SLATEC Common Mathematical Library is issued by the following +C +C Air Force Weapons Laboratory, Albuquerque +C Lawrence Livermore National Laboratory, Livermore +C Los Alamos National Laboratory, Los Alamos +C National Institute of Standards and Technology, Washington +C National Energy Research Supercomputer Center, Livermore +C Oak Ridge National Laboratory, Oak Ridge +C Sandia National Laboratories, Albuquerque +C Sandia National Laboratories, Livermore +C +C All questions concerning the distribution of the library should be +C directed to the NATIONAL ENERGY SOFTWARE CENTER, 9700 Cass Ave., +C Argonne, Illinois 60439, and not to the authors of the subprograms. +C +C * * * * * Notice * * * * * +C +C This material was prepared as an account of work sponsored by the +C United States Government. Neither the United States, nor the +C Department of Energy, nor the Department of Defense, nor any of +C their employees, nor any of their contractors, subcontractors, or +C their employees, makes any warranty, expressed or implied, or +C assumes any legal liability or responsibility for the accuracy, +C completeness, or usefulness of any information, apparatus, product, +C or process disclosed, or represents that its use would not infringe +C upon privately owned rights. +C +C *Usage: +C +C CHARACTER * 16 VER +C +C CALL AAAAAA (VER) +C +C *Arguments: +C +C VER:OUT will contain the version number of the SLATEC CML. +C +C *Description: +C +C This routine contains the SLATEC Common Mathematical Library +C disclaimer and can be used to return the library version number. +C +C***REFERENCES Kirby W. Fong, Thomas H. Jefferson, Tokihiko Suyehiro +C and Lee Walton, Guide to the SLATEC Common Mathema- +C tical Library, April 10, 1990. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 800424 DATE WRITTEN +C 890414 REVISION DATE from Version 3.2 +C 890713 Routine modified to return version number. (WRB) +C 900330 Prologue converted to Version 4.0 format. (BAB) +C 920501 Reformatted the REFERENCES section. (WRB) +C 921215 Updated for Version 4.0. (WRB) +C 930701 Updated for Version 4.1. (WRB) +C***END PROLOGUE AAAAAA + CHARACTER * (*) VER +C***FIRST EXECUTABLE STATEMENT AAAAAA + VER = ' 4.1' + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/d1mach.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/d1mach.f new file mode 100644 index 000000000..6f10f7035 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/d1mach.f @@ -0,0 +1,502 @@ +*DECK D1MACH + DOUBLE PRECISION FUNCTION D1MACH (I) +C***BEGIN PROLOGUE D1MACH +C***PURPOSE Return floating point machine dependent constants. +C***LIBRARY SLATEC +C***CATEGORY R1 +C***TYPE DOUBLE PRECISION (R1MACH-S, D1MACH-D) +C***KEYWORDS MACHINE CONSTANTS +C***AUTHOR Fox, P. A., (Bell Labs) +C Hall, A. D., (Bell Labs) +C Schryer, N. L., (Bell Labs) +C***DESCRIPTION +C +C D1MACH can be used to obtain machine-dependent parameters for the +C local machine environment. It is a function subprogram with one +C (input) argument, and can be referenced as follows: +C +C D = D1MACH(I) +C +C where I=1,...,5. The (output) value of D above is determined by +C the (input) value of I. The results for various values of I are +C discussed below. +C +C D1MACH( 1) = B**(EMIN-1), the smallest positive magnitude. +C D1MACH( 2) = B**EMAX*(1 - B**(-T)), the largest magnitude. +C D1MACH( 3) = B**(-T), the smallest relative spacing. +C D1MACH( 4) = B**(1-T), the largest relative spacing. +C D1MACH( 5) = LOG10(B) +C +C Assume double precision numbers are represented in the T-digit, +C base-B form +C +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, 0 .LT. X(1), and +C EMIN .LE. E .LE. EMAX. +C +C The values of B, T, EMIN and EMAX are provided in I1MACH as +C follows: +C I1MACH(10) = B, the base. +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, the desired +C set of DATA statements should be activated by removing the C from +C column 1. Also, the values of D1MACH(1) - D1MACH(4) should be +C checked for consistency with the local operating system. +C +C***REFERENCES P. A. Fox, A. D. Hall and N. L. Schryer, Framework for +C a portable library, ACM Transactions on Mathematical +C Software 4, 2 (June 1978), pp. 177-188. +C***ROUTINES CALLED XERMSG +C***REVISION HISTORY (YYMMDD) +C 750101 DATE WRITTEN +C 890213 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) +C 900618 Added DEC RISC constants. (WRB) +C 900723 Added IBM RS 6000 constants. (WRB) +C 900911 Added SUN 386i constants. (WRB) +C 910710 Added HP 730 constants. (SMR) +C 911114 Added Convex IEEE constants. (WRB) +C 920121 Added SUN -r8 compiler option constants. (WRB) +C 920229 Added Touchstone Delta i860 constants. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C 920625 Added CONVEX -p8 and -pd8 compiler option constants. +C (BKS, WRB) +C 930201 Added DEC Alpha and SGI constants. (RWC and WRB) +C***END PROLOGUE D1MACH +C + INTEGER SMALL(4) + INTEGER LARGE(4) + INTEGER RIGHT(4) + INTEGER DIVER(4) + INTEGER LOG10(4) +C + DOUBLE PRECISION DMACH(5) + SAVE DMACH +C + EQUIVALENCE (DMACH(1),SMALL(1)) + EQUIVALENCE (DMACH(2),LARGE(1)) + EQUIVALENCE (DMACH(3),RIGHT(1)) + EQUIVALENCE (DMACH(4),DIVER(1)) + EQUIVALENCE (DMACH(5),LOG10(1)) +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT FORTRAN COMPILER USING THE 68020/68881 COMPILER OPTION +C +C DATA SMALL(1), SMALL(2) / Z'00100000', Z'00000000' / +C DATA LARGE(1), LARGE(2) / Z'7FEFFFFF', Z'FFFFFFFF' / +C DATA RIGHT(1), RIGHT(2) / Z'3CA00000', Z'00000000' / +C DATA DIVER(1), DIVER(2) / Z'3CB00000', Z'00000000' / +C DATA LOG10(1), LOG10(2) / Z'3FD34413', Z'509F79FF' / +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT FORTRAN COMPILER USING SOFTWARE FLOATING POINT +C +C DATA SMALL(1), SMALL(2) / Z'00100000', Z'00000000' / +C DATA LARGE(1), LARGE(2) / Z'7FDFFFFF', Z'FFFFFFFF' / +C DATA RIGHT(1), RIGHT(2) / Z'3CA00000', Z'00000000' / +C DATA DIVER(1), DIVER(2) / Z'3CB00000', Z'00000000' / +C DATA LOG10(1), LOG10(2) / Z'3FD34413', Z'509F79FF' / +C +C MACHINE CONSTANTS FOR THE APOLLO +C +C DATA SMALL(1), SMALL(2) / 16#00100000, 16#00000000 / +C DATA LARGE(1), LARGE(2) / 16#7FFFFFFF, 16#FFFFFFFF / +C DATA RIGHT(1), RIGHT(2) / 16#3CA00000, 16#00000000 / +C DATA DIVER(1), DIVER(2) / 16#3CB00000, 16#00000000 / +C DATA LOG10(1), LOG10(2) / 16#3FD34413, 16#509F79FF / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM +C +C DATA SMALL(1) / ZC00800000 / +C DATA SMALL(2) / Z000000000 / +C DATA LARGE(1) / ZDFFFFFFFF / +C DATA LARGE(2) / ZFFFFFFFFF / +C DATA RIGHT(1) / ZCC5800000 / +C DATA RIGHT(2) / Z000000000 / +C DATA DIVER(1) / ZCC6800000 / +C DATA DIVER(2) / Z000000000 / +C DATA LOG10(1) / ZD00E730E7 / +C DATA LOG10(2) / ZC77800DC0 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM +C +C DATA SMALL(1) / O1771000000000000 / +C DATA SMALL(2) / O0000000000000000 / +C DATA LARGE(1) / O0777777777777777 / +C DATA LARGE(2) / O0007777777777777 / +C DATA RIGHT(1) / O1461000000000000 / +C DATA RIGHT(2) / O0000000000000000 / +C DATA DIVER(1) / O1451000000000000 / +C DATA DIVER(2) / O0000000000000000 / +C DATA LOG10(1) / O1157163034761674 / +C DATA LOG10(2) / O0006677466732724 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS +C +C DATA SMALL(1) / O1771000000000000 / +C DATA SMALL(2) / O7770000000000000 / +C DATA LARGE(1) / O0777777777777777 / +C DATA LARGE(2) / O7777777777777777 / +C DATA RIGHT(1) / O1461000000000000 / +C DATA RIGHT(2) / O0000000000000000 / +C DATA DIVER(1) / O1451000000000000 / +C DATA DIVER(2) / O0000000000000000 / +C DATA LOG10(1) / O1157163034761674 / +C DATA LOG10(2) / O0006677466732724 / +C +C MACHINE CONSTANTS FOR THE CDC 170/180 SERIES USING NOS/VE +C +C DATA SMALL(1) / Z"3001800000000000" / +C DATA SMALL(2) / Z"3001000000000000" / +C DATA LARGE(1) / Z"4FFEFFFFFFFFFFFE" / +C DATA LARGE(2) / Z"4FFE000000000000" / +C DATA RIGHT(1) / Z"3FD2800000000000" / +C DATA RIGHT(2) / Z"3FD2000000000000" / +C DATA DIVER(1) / Z"3FD3800000000000" / +C DATA DIVER(2) / Z"3FD3000000000000" / +C DATA LOG10(1) / Z"3FFF9A209A84FBCF" / +C DATA LOG10(2) / Z"3FFFF7988F8959AC" / +C +C MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES +C +C DATA SMALL(1) / 00564000000000000000B / +C DATA SMALL(2) / 00000000000000000000B / +C DATA LARGE(1) / 37757777777777777777B / +C DATA LARGE(2) / 37157777777777777777B / +C DATA RIGHT(1) / 15624000000000000000B / +C DATA RIGHT(2) / 00000000000000000000B / +C DATA DIVER(1) / 15634000000000000000B / +C DATA DIVER(2) / 00000000000000000000B / +C DATA LOG10(1) / 17164642023241175717B / +C DATA LOG10(2) / 16367571421742254654B / +C +C MACHINE CONSTANTS FOR THE CELERITY C1260 +C +C DATA SMALL(1), SMALL(2) / Z'00100000', Z'00000000' / +C DATA LARGE(1), LARGE(2) / Z'7FEFFFFF', Z'FFFFFFFF' / +C DATA RIGHT(1), RIGHT(2) / Z'3CA00000', Z'00000000' / +C DATA DIVER(1), DIVER(2) / Z'3CB00000', Z'00000000' / +C DATA LOG10(1), LOG10(2) / Z'3FD34413', Z'509F79FF' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fn OR -pd8 COMPILER OPTION +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FFFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CC0000000000000' / +C DATA DMACH(4) / Z'3CD0000000000000' / +C DATA DMACH(5) / Z'3FF34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fi COMPILER OPTION +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CA0000000000000' / +C DATA DMACH(4) / Z'3CB0000000000000' / +C DATA DMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -p8 COMPILER OPTION +C +C DATA DMACH(1) / Z'00010000000000000000000000000000' / +C DATA DMACH(2) / Z'7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3F900000000000000000000000000000' / +C DATA DMACH(4) / Z'3F910000000000000000000000000000' / +C DATA DMACH(5) / Z'3FFF34413509F79FEF311F12B35816F9' / +C +C MACHINE CONSTANTS FOR THE CRAY +C +C DATA SMALL(1) / 201354000000000000000B / +C DATA SMALL(2) / 000000000000000000000B / +C DATA LARGE(1) / 577767777777777777777B / +C DATA LARGE(2) / 000007777777777777774B / +C DATA RIGHT(1) / 376434000000000000000B / +C DATA RIGHT(2) / 000000000000000000000B / +C DATA DIVER(1) / 376444000000000000000B / +C DATA DIVER(2) / 000000000000000000000B / +C DATA LOG10(1) / 377774642023241175717B / +C DATA LOG10(2) / 000007571421742254654B / +C +C MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200 +C NOTE - IT MAY BE APPROPRIATE TO INCLUDE THE FOLLOWING CARD - +C STATIC DMACH(5) +C +C DATA SMALL / 20K, 3*0 / +C DATA LARGE / 77777K, 3*177777K / +C DATA RIGHT / 31420K, 3*0 / +C DATA DIVER / 32020K, 3*0 / +C DATA LOG10 / 40423K, 42023K, 50237K, 74776K / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING G_FLOAT +C +C DATA DMACH(1) / '0000000000000010'X / +C DATA DMACH(2) / 'FFFFFFFFFFFF7FFF'X / +C DATA DMACH(3) / '0000000000003CC0'X / +C DATA DMACH(4) / '0000000000003CD0'X / +C DATA DMACH(5) / '79FF509F44133FF3'X / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING IEEE_FORMAT +C +C DATA DMACH(1) / '0010000000000000'X / +C DATA DMACH(2) / '7FEFFFFFFFFFFFFF'X / +C DATA DMACH(3) / '3CA0000000000000'X / +C DATA DMACH(4) / '3CB0000000000000'X / +C DATA DMACH(5) / '3FD34413509F79FF'X / +C +C MACHINE CONSTANTS FOR THE DEC RISC +C +C DATA SMALL(1), SMALL(2) / Z'00000000', Z'00100000'/ +C DATA LARGE(1), LARGE(2) / Z'FFFFFFFF', Z'7FEFFFFF'/ +C DATA RIGHT(1), RIGHT(2) / Z'00000000', Z'3CA00000'/ +C DATA DIVER(1), DIVER(2) / Z'00000000', Z'3CB00000'/ +C DATA LOG10(1), LOG10(2) / Z'509F79FF', Z'3FD34413'/ +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING D_FLOATING +C (EXPRESSED IN INTEGER AND HEXADECIMAL) +C THE HEX FORMAT BELOW MAY NOT BE SUITABLE FOR UNIX SYSTEMS +C THE INTEGER FORMAT SHOULD BE OK FOR UNIX SYSTEMS +C +C DATA SMALL(1), SMALL(2) / 128, 0 / +C DATA LARGE(1), LARGE(2) / -32769, -1 / +C DATA RIGHT(1), RIGHT(2) / 9344, 0 / +C DATA DIVER(1), DIVER(2) / 9472, 0 / +C DATA LOG10(1), LOG10(2) / 546979738, -805796613 / +C +C DATA SMALL(1), SMALL(2) / Z00000080, Z00000000 / +C DATA LARGE(1), LARGE(2) / ZFFFF7FFF, ZFFFFFFFF / +C DATA RIGHT(1), RIGHT(2) / Z00002480, Z00000000 / +C DATA DIVER(1), DIVER(2) / Z00002500, Z00000000 / +C DATA LOG10(1), LOG10(2) / Z209A3F9A, ZCFF884FB / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING G_FLOATING +C (EXPRESSED IN INTEGER AND HEXADECIMAL) +C THE HEX FORMAT BELOW MAY NOT BE SUITABLE FOR UNIX SYSTEMS +C THE INTEGER FORMAT SHOULD BE OK FOR UNIX SYSTEMS +C +C DATA SMALL(1), SMALL(2) / 16, 0 / +C DATA LARGE(1), LARGE(2) / -32769, -1 / +C DATA RIGHT(1), RIGHT(2) / 15552, 0 / +C DATA DIVER(1), DIVER(2) / 15568, 0 / +C DATA LOG10(1), LOG10(2) / 1142112243, 2046775455 / +C +C DATA SMALL(1), SMALL(2) / Z00000010, Z00000000 / +C DATA LARGE(1), LARGE(2) / ZFFFF7FFF, ZFFFFFFFF / +C DATA RIGHT(1), RIGHT(2) / Z00003CC0, Z00000000 / +C DATA DIVER(1), DIVER(2) / Z00003CD0, Z00000000 / +C DATA LOG10(1), LOG10(2) / Z44133FF3, Z79FF509F / +C +C MACHINE CONSTANTS FOR THE ELXSI 6400 +C (ASSUMING REAL*8 IS THE DEFAULT DOUBLE PRECISION) +C +C DATA SMALL(1), SMALL(2) / '00100000'X,'00000000'X / +C DATA LARGE(1), LARGE(2) / '7FEFFFFF'X,'FFFFFFFF'X / +C DATA RIGHT(1), RIGHT(2) / '3CB00000'X,'00000000'X / +C DATA DIVER(1), DIVER(2) / '3CC00000'X,'00000000'X / +C DATA LOG10(1), LOG10(2) / '3FD34413'X,'509F79FF'X / +C +C MACHINE CONSTANTS FOR THE HARRIS 220 +C +C DATA SMALL(1), SMALL(2) / '20000000, '00000201 / +C DATA LARGE(1), LARGE(2) / '37777777, '37777577 / +C DATA RIGHT(1), RIGHT(2) / '20000000, '00000333 / +C DATA DIVER(1), DIVER(2) / '20000000, '00000334 / +C DATA LOG10(1), LOG10(2) / '23210115, '10237777 / +C +C MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 SERIES +C +C DATA SMALL(1), SMALL(2) / O402400000000, O000000000000 / +C DATA LARGE(1), LARGE(2) / O376777777777, O777777777777 / +C DATA RIGHT(1), RIGHT(2) / O604400000000, O000000000000 / +C DATA DIVER(1), DIVER(2) / O606400000000, O000000000000 / +C DATA LOG10(1), LOG10(2) / O776464202324, O117571775714 / +C +C MACHINE CONSTANTS FOR THE HP 730 +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CA0000000000000' / +C DATA DMACH(4) / Z'3CB0000000000000' / +C DATA DMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C THREE WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA SMALL(1), SMALL(2), SMALL(3) / 40000B, 0, 1 / +C DATA LARGE(1), LARGE(2), LARGE(3) / 77777B, 177777B, 177776B / +C DATA RIGHT(1), RIGHT(2), RIGHT(3) / 40000B, 0, 265B / +C DATA DIVER(1), DIVER(2), DIVER(3) / 40000B, 0, 276B / +C DATA LOG10(1), LOG10(2), LOG10(3) / 46420B, 46502B, 77777B / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C FOUR WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA SMALL(1), SMALL(2) / 40000B, 0 / +C DATA SMALL(3), SMALL(4) / 0, 1 / +C DATA LARGE(1), LARGE(2) / 77777B, 177777B / +C DATA LARGE(3), LARGE(4) / 177777B, 177776B / +C DATA RIGHT(1), RIGHT(2) / 40000B, 0 / +C DATA RIGHT(3), RIGHT(4) / 0, 225B / +C DATA DIVER(1), DIVER(2) / 40000B, 0 / +C DATA DIVER(3), DIVER(4) / 0, 227B / +C DATA LOG10(1), LOG10(2) / 46420B, 46502B / +C DATA LOG10(3), LOG10(4) / 76747B, 176377B / +C +C MACHINE CONSTANTS FOR THE HP 9000 +C +C DATA SMALL(1), SMALL(2) / 00040000000B, 00000000000B / +C DATA LARGE(1), LARGE(2) / 17737777777B, 37777777777B / +C DATA RIGHT(1), RIGHT(2) / 07454000000B, 00000000000B / +C DATA DIVER(1), DIVER(2) / 07460000000B, 00000000000B / +C DATA LOG10(1), LOG10(2) / 07764642023B, 12047674777B / +C +C MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, +C THE XEROX SIGMA 5/7/9, THE SEL SYSTEMS 85/86, AND +C THE PERKIN ELMER (INTERDATA) 7/32. +C +C DATA SMALL(1), SMALL(2) / Z00100000, Z00000000 / +C DATA LARGE(1), LARGE(2) / Z7FFFFFFF, ZFFFFFFFF / +C DATA RIGHT(1), RIGHT(2) / Z33100000, Z00000000 / +C DATA DIVER(1), DIVER(2) / Z34100000, Z00000000 / +C DATA LOG10(1), LOG10(2) / Z41134413, Z509F79FF / +C +C MACHINE CONSTANTS FOR THE IBM PC +C ASSUMES THAT ALL ARITHMETIC IS DONE IN DOUBLE PRECISION +C ON 8088, I.E., NOT IN 80 BIT FORM FOR THE 8087. +C +C DATA SMALL(1) / 2.23D-308 / +C DATA LARGE(1) / 1.79D+308 / +C DATA RIGHT(1) / 1.11D-16 / +C DATA DIVER(1) / 2.22D-16 / +C DATA LOG10(1) / 0.301029995663981195D0 / +C +C MACHINE CONSTANTS FOR THE IBM RS 6000 +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CA0000000000000' / +C DATA DMACH(4) / Z'3CB0000000000000' / +C DATA DMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE INTEL i860 +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CA0000000000000' / +C DATA DMACH(4) / Z'3CB0000000000000' / +C DATA DMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR) +C +C DATA SMALL(1), SMALL(2) / "033400000000, "000000000000 / +C DATA LARGE(1), LARGE(2) / "377777777777, "344777777777 / +C DATA RIGHT(1), RIGHT(2) / "113400000000, "000000000000 / +C DATA DIVER(1), DIVER(2) / "114400000000, "000000000000 / +C DATA LOG10(1), LOG10(2) / "177464202324, "144117571776 / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR) +C +C DATA SMALL(1), SMALL(2) / "000400000000, "000000000000 / +C DATA LARGE(1), LARGE(2) / "377777777777, "377777777777 / +C DATA RIGHT(1), RIGHT(2) / "103400000000, "000000000000 / +C DATA DIVER(1), DIVER(2) / "104400000000, "000000000000 / +C DATA LOG10(1), LOG10(2) / "177464202324, "476747767461 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 32-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). +C +C DATA SMALL(1), SMALL(2) / 8388608, 0 / +C DATA LARGE(1), LARGE(2) / 2147483647, -1 / +C DATA RIGHT(1), RIGHT(2) / 612368384, 0 / +C DATA DIVER(1), DIVER(2) / 620756992, 0 / +C DATA LOG10(1), LOG10(2) / 1067065498, -2063872008 / +C +C DATA SMALL(1), SMALL(2) / O00040000000, O00000000000 / +C DATA LARGE(1), LARGE(2) / O17777777777, O37777777777 / +C DATA RIGHT(1), RIGHT(2) / O04440000000, O00000000000 / +C DATA DIVER(1), DIVER(2) / O04500000000, O00000000000 / +C DATA LOG10(1), LOG10(2) / O07746420232, O20476747770 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 16-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). +C +C DATA SMALL(1), SMALL(2) / 128, 0 / +C DATA SMALL(3), SMALL(4) / 0, 0 / +C DATA LARGE(1), LARGE(2) / 32767, -1 / +C DATA LARGE(3), LARGE(4) / -1, -1 / +C DATA RIGHT(1), RIGHT(2) / 9344, 0 / +C DATA RIGHT(3), RIGHT(4) / 0, 0 / +C DATA DIVER(1), DIVER(2) / 9472, 0 / +C DATA DIVER(3), DIVER(4) / 0, 0 / +C DATA LOG10(1), LOG10(2) / 16282, 8346 / +C DATA LOG10(3), LOG10(4) / -31493, -12296 / +C +C DATA SMALL(1), SMALL(2) / O000200, O000000 / +C DATA SMALL(3), SMALL(4) / O000000, O000000 / +C DATA LARGE(1), LARGE(2) / O077777, O177777 / +C DATA LARGE(3), LARGE(4) / O177777, O177777 / +C DATA RIGHT(1), RIGHT(2) / O022200, O000000 / +C DATA RIGHT(3), RIGHT(4) / O000000, O000000 / +C DATA DIVER(1), DIVER(2) / O022400, O000000 / +C DATA DIVER(3), DIVER(4) / O000000, O000000 / +C DATA LOG10(1), LOG10(2) / O037632, O020232 / +C DATA LOG10(3), LOG10(4) / O102373, O147770 / +C +C MACHINE CONSTANTS FOR THE SILICON GRAPHICS +C +C DATA SMALL(1), SMALL(2) / Z'00100000', Z'00000000' / +C DATA LARGE(1), LARGE(2) / Z'7FEFFFFF', Z'FFFFFFFF' / +C DATA RIGHT(1), RIGHT(2) / Z'3CA00000', Z'00000000' / +C DATA DIVER(1), DIVER(2) / Z'3CB00000', Z'00000000' / +C DATA LOG10(1), LOG10(2) / Z'3FD34413', Z'509F79FF' / +C +C MACHINE CONSTANTS FOR THE SUN +C +C DATA DMACH(1) / Z'0010000000000000' / +C DATA DMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3CA0000000000000' / +C DATA DMACH(4) / Z'3CB0000000000000' / +C DATA DMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE SUN +C USING THE -r8 COMPILER OPTION +C +C DATA DMACH(1) / Z'00010000000000000000000000000000' / +C DATA DMACH(2) / Z'7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF' / +C DATA DMACH(3) / Z'3F8E0000000000000000000000000000' / +C DATA DMACH(4) / Z'3F8F0000000000000000000000000000' / +C DATA DMACH(5) / Z'3FFD34413509F79FEF311F12B35816F9' / +C +C MACHINE CONSTANTS FOR THE SUN 386i +C +C DATA SMALL(1), SMALL(2) / Z'FFFFFFFD', Z'000FFFFF' / +C DATA LARGE(1), LARGE(2) / Z'FFFFFFB0', Z'7FEFFFFF' / +C DATA RIGHT(1), RIGHT(2) / Z'000000B0', Z'3CA00000' / +C DATA DIVER(1), DIVER(2) / Z'FFFFFFCB', Z'3CAFFFFF' +C DATA LOG10(1), LOG10(2) / Z'509F79E9', Z'3FD34413' / +C +C MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES FTN COMPILER +C +C DATA SMALL(1), SMALL(2) / O000040000000, O000000000000 / +C DATA LARGE(1), LARGE(2) / O377777777777, O777777777777 / +C DATA RIGHT(1), RIGHT(2) / O170540000000, O000000000000 / +C DATA DIVER(1), DIVER(2) / O170640000000, O000000000000 / +C DATA LOG10(1), LOG10(2) / O177746420232, O411757177572 / +C +C***FIRST EXECUTABLE STATEMENT D1MACH + IF (I .LT. 1 .OR. I .GT. 5) CALL XERMSG ('SLATEC', 'D1MACH', + + 'I OUT OF BOUNDS', 1, 2) +C + D1MACH = DMACH(I) + RETURN +C + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/dqk61.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/dqk61.f new file mode 100644 index 000000000..16d852c8e --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/dqk61.f @@ -0,0 +1,241 @@ +*DECK DQK61 + SUBROUTINE DQK61 (F, A, B, RESULT, ABSERR, RESABS, RESASC) +C***BEGIN PROLOGUE DQK61 +C***PURPOSE To compute I = Integral of F over (A,B) with error +C estimate +C J = Integral of ABS(F) over (A,B) +C***LIBRARY SLATEC (QUADPACK) +C***CATEGORY H2A1A2 +C***TYPE DOUBLE PRECISION (QK61-S, DQK61-D) +C***KEYWORDS 61-POINT GAUSS-KRONROD RULES, QUADPACK, QUADRATURE +C***AUTHOR Piessens, Robert +C Applied Mathematics and Programming Division +C K. U. Leuven +C de Doncker, Elise +C Applied Mathematics and Programming Division +C K. U. Leuven +C***DESCRIPTION +C +C Integration rule +C Standard fortran subroutine +C Double precision version +C +C +C PARAMETERS +C ON ENTRY +C F - Double precision +C Function subprogram defining the integrand +C function F(X). The actual name for F needs to be +C declared E X T E R N A L in the calling program. +C +C A - Double precision +C Lower limit of integration +C +C B - Double precision +C Upper limit of integration +C +C ON RETURN +C RESULT - Double precision +C Approximation to the integral I +C RESULT is computed by applying the 61-point +C Kronrod rule (RESK) obtained by optimal addition of +C abscissae to the 30-point Gauss rule (RESG). +C +C ABSERR - Double precision +C Estimate of the modulus of the absolute error, +C which should equal or exceed ABS(I-RESULT) +C +C RESABS - Double precision +C Approximation to the integral J +C +C RESASC - Double precision +C Approximation to the integral of ABS(F-I/(B-A)) +C +C***REFERENCES (NONE) +C***ROUTINES CALLED D1MACH +C***REVISION HISTORY (YYMMDD) +C 800101 DATE WRITTEN +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890531 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C***END PROLOGUE DQK61 +C + DOUBLE PRECISION A,DABSC,ABSERR,B,CENTR,DHLGTH, + 1 D1MACH,EPMACH,F,FC,FSUM,FVAL1,FVAL2,FV1,FV2,HLGTH,RESABS,RESASC, + 2 RESG,RESK,RESKH,RESULT,UFLOW,WG,WGK,XGK + INTEGER J,JTW,JTWM1 + EXTERNAL F +C + DIMENSION FV1(30),FV2(30),XGK(31),WGK(31),WG(15) +C +C THE ABSCISSAE AND WEIGHTS ARE GIVEN FOR THE +C INTERVAL (-1,1). BECAUSE OF SYMMETRY ONLY THE POSITIVE +C ABSCISSAE AND THEIR CORRESPONDING WEIGHTS ARE GIVEN. +C +C XGK - ABSCISSAE OF THE 61-POINT KRONROD RULE +C XGK(2), XGK(4) ... ABSCISSAE OF THE 30-POINT +C GAUSS RULE +C XGK(1), XGK(3) ... OPTIMALLY ADDED ABSCISSAE +C TO THE 30-POINT GAUSS RULE +C +C WGK - WEIGHTS OF THE 61-POINT KRONROD RULE +C +C WG - WEIGHTS OF THE 30-POINT GAUSS RULE +C +C +C GAUSS QUADRATURE WEIGHTS AND KRONROD QUADRATURE ABSCISSAE AND WEIGHTS +C AS EVALUATED WITH 80 DECIMAL DIGIT ARITHMETIC BY L. W. FULLERTON, +C BELL LABS, NOV. 1981. +C + SAVE WG, XGK, WGK + DATA WG ( 1) / 0.0079681924 9616660561 5465883474 674 D0 / + DATA WG ( 2) / 0.0184664683 1109095914 2302131912 047 D0 / + DATA WG ( 3) / 0.0287847078 8332336934 9719179611 292 D0 / + DATA WG ( 4) / 0.0387991925 6962704959 6801936446 348 D0 / + DATA WG ( 5) / 0.0484026728 3059405290 2938140422 808 D0 / + DATA WG ( 6) / 0.0574931562 1761906648 1721689402 056 D0 / + DATA WG ( 7) / 0.0659742298 8218049512 8128515115 962 D0 / + DATA WG ( 8) / 0.0737559747 3770520626 8243850022 191 D0 / + DATA WG ( 9) / 0.0807558952 2942021535 4694938460 530 D0 / + DATA WG ( 10) / 0.0868997872 0108297980 2387530715 126 D0 / + DATA WG ( 11) / 0.0921225222 3778612871 7632707087 619 D0 / + DATA WG ( 12) / 0.0963687371 7464425963 9468626351 810 D0 / + DATA WG ( 13) / 0.0995934205 8679526706 2780282103 569 D0 / + DATA WG ( 14) / 0.1017623897 4840550459 6428952168 554 D0 / + DATA WG ( 15) / 0.1028526528 9355884034 1285636705 415 D0 / +C + DATA XGK ( 1) / 0.9994844100 5049063757 1325895705 811 D0 / + DATA XGK ( 2) / 0.9968934840 7464954027 1630050918 695 D0 / + DATA XGK ( 3) / 0.9916309968 7040459485 8628366109 486 D0 / + DATA XGK ( 4) / 0.9836681232 7974720997 0032581605 663 D0 / + DATA XGK ( 5) / 0.9731163225 0112626837 4693868423 707 D0 / + DATA XGK ( 6) / 0.9600218649 6830751221 6871025581 798 D0 / + DATA XGK ( 7) / 0.9443744447 4855997941 5831324037 439 D0 / + DATA XGK ( 8) / 0.9262000474 2927432587 9324277080 474 D0 / + DATA XGK ( 9) / 0.9055733076 9990779854 6522558925 958 D0 / + DATA XGK ( 10) / 0.8825605357 9205268154 3116462530 226 D0 / + DATA XGK ( 11) / 0.8572052335 4606109895 8658510658 944 D0 / + DATA XGK ( 12) / 0.8295657623 8276839744 2898119732 502 D0 / + DATA XGK ( 13) / 0.7997278358 2183908301 3668942322 683 D0 / + DATA XGK ( 14) / 0.7677774321 0482619491 7977340974 503 D0 / + DATA XGK ( 15) / 0.7337900624 5322680472 6171131369 528 D0 / + DATA XGK ( 16) / 0.6978504947 9331579693 2292388026 640 D0 / + DATA XGK ( 17) / 0.6600610641 2662696137 0053668149 271 D0 / + DATA XGK ( 18) / 0.6205261829 8924286114 0477556431 189 D0 / + DATA XGK ( 19) / 0.5793452358 2636169175 6024932172 540 D0 / + DATA XGK ( 20) / 0.5366241481 4201989926 4169793311 073 D0 / + DATA XGK ( 21) / 0.4924804678 6177857499 3693061207 709 D0 / + DATA XGK ( 22) / 0.4470337695 3808917678 0609900322 854 D0 / + DATA XGK ( 23) / 0.4004012548 3039439253 5476211542 661 D0 / + DATA XGK ( 24) / 0.3527047255 3087811347 1037207089 374 D0 / + DATA XGK ( 25) / 0.3040732022 7362507737 2677107199 257 D0 / + DATA XGK ( 26) / 0.2546369261 6788984643 9805129817 805 D0 / + DATA XGK ( 27) / 0.2045251166 8230989143 8957671002 025 D0 / + DATA XGK ( 28) / 0.1538699136 0858354696 3794672743 256 D0 / + DATA XGK ( 29) / 0.1028069379 6673703014 7096751318 001 D0 / + DATA XGK ( 30) / 0.0514718425 5531769583 3025213166 723 D0 / + DATA XGK ( 31) / 0.0000000000 0000000000 0000000000 000 D0 / +C + DATA WGK ( 1) / 0.0013890136 9867700762 4551591226 760 D0 / + DATA WGK ( 2) / 0.0038904611 2709988405 1267201844 516 D0 / + DATA WGK ( 3) / 0.0066307039 1593129217 3319826369 750 D0 / + DATA WGK ( 4) / 0.0092732796 5951776342 8441146892 024 D0 / + DATA WGK ( 5) / 0.0118230152 5349634174 2232898853 251 D0 / + DATA WGK ( 6) / 0.0143697295 0704580481 2451432443 580 D0 / + DATA WGK ( 7) / 0.0169208891 8905327262 7572289420 322 D0 / + DATA WGK ( 8) / 0.0194141411 9394238117 3408951050 128 D0 / + DATA WGK ( 9) / 0.0218280358 2160919229 7167485738 339 D0 / + DATA WGK ( 10) / 0.0241911620 7808060136 5686370725 232 D0 / + DATA WGK ( 11) / 0.0265099548 8233310161 0601709335 075 D0 / + DATA WGK ( 12) / 0.0287540487 6504129284 3978785354 334 D0 / + DATA WGK ( 13) / 0.0309072575 6238776247 2884252943 092 D0 / + DATA WGK ( 14) / 0.0329814470 5748372603 1814191016 854 D0 / + DATA WGK ( 15) / 0.0349793380 2806002413 7499670731 468 D0 / + DATA WGK ( 16) / 0.0368823646 5182122922 3911065617 136 D0 / + DATA WGK ( 17) / 0.0386789456 2472759295 0348651532 281 D0 / + DATA WGK ( 18) / 0.0403745389 5153595911 1995279752 468 D0 / + DATA WGK ( 19) / 0.0419698102 1516424614 7147541285 970 D0 / + DATA WGK ( 20) / 0.0434525397 0135606931 6831728117 073 D0 / + DATA WGK ( 21) / 0.0448148001 3316266319 2355551616 723 D0 / + DATA WGK ( 22) / 0.0460592382 7100698811 6271735559 374 D0 / + DATA WGK ( 23) / 0.0471855465 6929915394 5261478181 099 D0 / + DATA WGK ( 24) / 0.0481858617 5708712914 0779492298 305 D0 / + DATA WGK ( 25) / 0.0490554345 5502977888 7528165367 238 D0 / + DATA WGK ( 26) / 0.0497956834 2707420635 7811569379 942 D0 / + DATA WGK ( 27) / 0.0504059214 0278234684 0893085653 585 D0 / + DATA WGK ( 28) / 0.0508817958 9874960649 2297473049 805 D0 / + DATA WGK ( 29) / 0.0512215478 4925877217 0656282604 944 D0 / + DATA WGK ( 30) / 0.0514261285 3745902593 3862879215 781 D0 / + DATA WGK ( 31) / 0.0514947294 2945156755 8340433647 099 D0 / +C +C LIST OF MAJOR VARIABLES +C ----------------------- +C +C CENTR - MID POINT OF THE INTERVAL +C HLGTH - HALF-LENGTH OF THE INTERVAL +C DABSC - ABSCISSA +C FVAL* - FUNCTION VALUE +C RESG - RESULT OF THE 30-POINT GAUSS RULE +C RESK - RESULT OF THE 61-POINT KRONROD RULE +C RESKH - APPROXIMATION TO THE MEAN VALUE OF F +C OVER (A,B), I.E. TO I/(B-A) +C +C MACHINE DEPENDENT CONSTANTS +C --------------------------- +C +C EPMACH IS THE LARGEST RELATIVE SPACING. +C UFLOW IS THE SMALLEST POSITIVE MAGNITUDE. +C +C***FIRST EXECUTABLE STATEMENT DQK61 + EPMACH = D1MACH(4) + UFLOW = D1MACH(1) +C + CENTR = 0.5D+00*(B+A) + HLGTH = 0.5D+00*(B-A) + DHLGTH = ABS(HLGTH) +C +C COMPUTE THE 61-POINT KRONROD APPROXIMATION TO THE +C INTEGRAL, AND ESTIMATE THE ABSOLUTE ERROR. +C + RESG = 0.0D+00 + FC = F(CENTR) + RESK = WGK(31)*FC + RESABS = ABS(RESK) + DO 10 J=1,15 + JTW = J*2 + DABSC = HLGTH*XGK(JTW) + FVAL1 = F(CENTR-DABSC) + FVAL2 = F(CENTR+DABSC) + FV1(JTW) = FVAL1 + FV2(JTW) = FVAL2 + FSUM = FVAL1+FVAL2 + RESG = RESG+WG(J)*FSUM + RESK = RESK+WGK(JTW)*FSUM + RESABS = RESABS+WGK(JTW)*(ABS(FVAL1)+ABS(FVAL2)) + 10 CONTINUE + DO 15 J=1,15 + JTWM1 = J*2-1 + DABSC = HLGTH*XGK(JTWM1) + FVAL1 = F(CENTR-DABSC) + FVAL2 = F(CENTR+DABSC) + FV1(JTWM1) = FVAL1 + FV2(JTWM1) = FVAL2 + FSUM = FVAL1+FVAL2 + RESK = RESK+WGK(JTWM1)*FSUM + RESABS = RESABS+WGK(JTWM1)*(ABS(FVAL1)+ABS(FVAL2)) + 15 CONTINUE + RESKH = RESK*0.5D+00 + RESASC = WGK(31)*ABS(FC-RESKH) + DO 20 J=1,30 + RESASC = RESASC+WGK(J)*(ABS(FV1(J)-RESKH)+ABS(FV2(J)-RESKH)) + 20 CONTINUE + RESULT = RESK*HLGTH + RESABS = RESABS*DHLGTH + RESASC = RESASC*DHLGTH + ABSERR = ABS((RESK-RESG)*HLGTH) + IF(RESASC.NE.0.0D+00.AND.ABSERR.NE.0.0D+00) + 1 ABSERR = RESASC*MIN(0.1D+01,(0.2D+03*ABSERR/RESASC)**1.5D+00) + IF(RESABS.GT.UFLOW/(0.5D+02*EPMACH)) ABSERR = MAX + 1 ((EPMACH*0.5D+02)*RESABS,ABSERR) + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/fdump.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/fdump.f new file mode 100644 index 000000000..1f44a57a0 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/fdump.f @@ -0,0 +1,31 @@ +*DECK FDUMP + SUBROUTINE FDUMP +C***BEGIN PROLOGUE FDUMP +C***PURPOSE Symbolic dump (should be locally written). +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3 +C***TYPE ALL (FDUMP-A) +C***KEYWORDS ERROR, XERMSG +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C ***Note*** Machine Dependent Routine +C FDUMP is intended to be replaced by a locally written +C version which produces a symbolic dump. Failing this, +C it should be replaced by a version which prints the +C subprogram nesting list. Note that this dump must be +C printed on each of up to five files, as indicated by the +C XGETUA routine. See XSETUA and XGETUA for details. +C +C Written by Ron Jones, with SLATEC Common Math Library Subcommittee +C +C***REFERENCES (NONE) +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C***END PROLOGUE FDUMP +C***FIRST EXECUTABLE STATEMENT FDUMP + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/i1mach.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/i1mach.f new file mode 100644 index 000000000..ad04e7b08 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/i1mach.f @@ -0,0 +1,888 @@ +*DECK I1MACH + INTEGER FUNCTION I1MACH (I) +C***BEGIN PROLOGUE I1MACH +C***PURPOSE Return integer machine dependent constants. +C***LIBRARY SLATEC +C***CATEGORY R1 +C***TYPE INTEGER (I1MACH-I) +C***KEYWORDS MACHINE CONSTANTS +C***AUTHOR Fox, P. A., (Bell Labs) +C Hall, A. D., (Bell Labs) +C Schryer, N. L., (Bell Labs) +C***DESCRIPTION +C +C I1MACH can be used to obtain machine-dependent parameters for the +C local machine environment. It is a function subprogram with one +C (input) argument and can be referenced as follows: +C +C K = I1MACH(I) +C +C where I=1,...,16. The (output) value of K above is determined by +C the (input) value of I. The results for various values of I are +C discussed below. +C +C I/O unit numbers: +C I1MACH( 1) = the standard input unit. +C I1MACH( 2) = the standard output unit. +C I1MACH( 3) = the standard punch unit. +C I1MACH( 4) = the standard error message unit. +C +C Words: +C I1MACH( 5) = the number of bits per integer storage unit. +C I1MACH( 6) = the number of characters per integer storage unit. +C +C Integers: +C assume integers are represented in the S-digit, base-A form +C +C sign ( X(S-1)*A**(S-1) + ... + X(1)*A + X(0) ) +C +C where 0 .LE. X(I) .LT. A for I=0,...,S-1. +C I1MACH( 7) = A, the base. +C I1MACH( 8) = S, the number of base-A digits. +C I1MACH( 9) = A**S - 1, the largest magnitude. +C +C Floating-Point Numbers: +C Assume floating-point numbers are represented in the T-digit, +C base-B form +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, +C 0 .LT. X(1), and EMIN .LE. E .LE. EMAX. +C I1MACH(10) = B, the base. +C +C Single-Precision: +C I1MACH(11) = T, the number of base-B digits. +C I1MACH(12) = EMIN, the smallest exponent E. +C I1MACH(13) = EMAX, the largest exponent E. +C +C Double-Precision: +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, the desired +C set of DATA statements should be activated by removing the C from +C column 1. Also, the values of I1MACH(1) - I1MACH(4) should be +C checked for consistency with the local operating system. +C +C***REFERENCES P. A. Fox, A. D. Hall and N. L. Schryer, Framework for +C a portable library, ACM Transactions on Mathematical +C Software 4, 2 (June 1978), pp. 177-188. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 750101 DATE WRITTEN +C 891012 Added VAX G-floating constants. (WRB) +C 891012 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900618 Added DEC RISC constants. (WRB) +C 900723 Added IBM RS 6000 constants. (WRB) +C 901009 Correct I1MACH(7) for IBM Mainframes. Should be 2 not 16. +C (RWC) +C 910710 Added HP 730 constants. (SMR) +C 911114 Added Convex IEEE constants. (WRB) +C 920121 Added SUN -r8 compiler option constants. (WRB) +C 920229 Added Touchstone Delta i860 constants. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C 920625 Added Convex -p8 and -pd8 compiler option constants. +C (BKS, WRB) +C 930201 Added DEC Alpha and SGI constants. (RWC and WRB) +C 930618 Corrected I1MACH(5) for Convex -p8 and -pd8 compiler +C options. (DWL, RWC and WRB). +C***END PROLOGUE I1MACH +C + INTEGER IMACH(16),OUTPUT + SAVE IMACH + EQUIVALENCE (IMACH(4),OUTPUT) +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT COMPILER +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE APOLLO +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 129 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1025 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM +C +C DATA IMACH( 1) / 7 / +C DATA IMACH( 2) / 2 / +C DATA IMACH( 3) / 2 / +C DATA IMACH( 4) / 2 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 33 / +C DATA IMACH( 9) / Z1FFFFFFFF / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -256 / +C DATA IMACH(13) / 255 / +C DATA IMACH(14) / 60 / +C DATA IMACH(15) / -256 / +C DATA IMACH(16) / 255 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 48 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 39 / +C DATA IMACH( 9) / O0007777777777777 / +C DATA IMACH(10) / 8 / +C DATA IMACH(11) / 13 / +C DATA IMACH(12) / -50 / +C DATA IMACH(13) / 76 / +C DATA IMACH(14) / 26 / +C DATA IMACH(15) / -50 / +C DATA IMACH(16) / 76 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 48 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 39 / +C DATA IMACH( 9) / O0007777777777777 / +C DATA IMACH(10) / 8 / +C DATA IMACH(11) / 13 / +C DATA IMACH(12) / -50 / +C DATA IMACH(13) / 76 / +C DATA IMACH(14) / 26 / +C DATA IMACH(15) / -32754 / +C DATA IMACH(16) / 32780 / +C +C MACHINE CONSTANTS FOR THE CDC 170/180 SERIES USING NOS/VE +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -4095 / +C DATA IMACH(13) / 4094 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -4095 / +C DATA IMACH(16) / 4094 / +C +C MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6LOUTPUT/ +C DATA IMACH( 5) / 60 / +C DATA IMACH( 6) / 10 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 48 / +C DATA IMACH( 9) / 00007777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -929 / +C DATA IMACH(13) / 1070 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -929 / +C DATA IMACH(16) / 1069 / +C +C MACHINE CONSTANTS FOR THE CELERITY C1260 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / Z'7FFFFFFF' / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fn COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fi COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -p8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1023 / +C DATA IMACH(13) / 1023 / +C DATA IMACH(14) / 113 / +C DATA IMACH(15) / -16383 / +C DATA IMACH(16) / 16383 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -pd8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1023 / +C DATA IMACH(13) / 1023 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CRAY +C USING THE 46 BIT INTEGER COMPILER OPTION +C +C DATA IMACH( 1) / 100 / +C DATA IMACH( 2) / 101 / +C DATA IMACH( 3) / 102 / +C DATA IMACH( 4) / 101 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 46 / +C DATA IMACH( 9) / 1777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -8189 / +C DATA IMACH(13) / 8190 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -8099 / +C DATA IMACH(16) / 8190 / +C +C MACHINE CONSTANTS FOR THE CRAY +C USING THE 64 BIT INTEGER COMPILER OPTION +C +C DATA IMACH( 1) / 100 / +C DATA IMACH( 2) / 101 / +C DATA IMACH( 3) / 102 / +C DATA IMACH( 4) / 101 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 777777777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -8189 / +C DATA IMACH(13) / 8190 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -8099 / +C DATA IMACH(16) / 8190 / +C +C MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200 +C +C DATA IMACH( 1) / 11 / +C DATA IMACH( 2) / 12 / +C DATA IMACH( 3) / 8 / +C DATA IMACH( 4) / 10 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 16 / +C DATA IMACH(11) / 6 / +C DATA IMACH(12) / -64 / +C DATA IMACH(13) / 63 / +C DATA IMACH(14) / 14 / +C DATA IMACH(15) / -64 / +C DATA IMACH(16) / 63 / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING G_FLOAT +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING IEEE_FLOAT +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE DEC RISC +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING D_FLOATING +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING G_FLOATING +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE ELXSI 6400 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 32 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE HARRIS 220 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 24 / +C DATA IMACH( 6) / 3 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 23 / +C DATA IMACH( 9) / 8388607 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 38 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 SERIES +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 43 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / O377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 63 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 730 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 3 WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 4 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 39 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 4 WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 4 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 55 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 9000 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 7 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 32 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1015 / +C DATA IMACH(16) / 1017 / +C +C MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, +C THE XEROX SIGMA 5/7/9, THE SEL SYSTEMS 85/86, AND +C THE PERKIN ELMER (INTERDATA) 7/32. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / Z7FFFFFFF / +C DATA IMACH(10) / 16 / +C DATA IMACH(11) / 6 / +C DATA IMACH(12) / -64 / +C DATA IMACH(13) / 63 / +C DATA IMACH(14) / 14 / +C DATA IMACH(15) / -64 / +C DATA IMACH(16) / 63 / +C +C MACHINE CONSTANTS FOR THE IBM PC +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE IBM RS 6000 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE INTEL i860 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR) +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 5 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / "377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 54 / +C DATA IMACH(15) / -101 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR) +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 5 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / "377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 62 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 32-BIT INTEGER ARITHMETIC. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 16-BIT INTEGER ARITHMETIC. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE SILICON GRAPHICS +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE SUN +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE SUN +C USING THE -r8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1021 / +C DATA IMACH(13) / 1024 / +C DATA IMACH(14) / 113 / +C DATA IMACH(15) / -16381 / +C DATA IMACH(16) / 16384 / +C +C MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES FTN COMPILER +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 1 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / O377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 60 / +C DATA IMACH(15) / -1024 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE Z80 MICROPROCESSOR +C +C DATA IMACH( 1) / 1 / +C DATA IMACH( 2) / 1 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C***FIRST EXECUTABLE STATEMENT I1MACH + IF (I .LT. 1 .OR. I .GT. 16) GO TO 10 +C + I1MACH = IMACH(I) + RETURN +C + 10 CONTINUE + WRITE (UNIT = OUTPUT, FMT = 9000) + 9000 FORMAT ('1ERROR 1 IN I1MACH - I OUT OF BOUNDS') +C +C CALL FDUMP +C + STOP + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/j4save.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/j4save.f new file mode 100644 index 000000000..6ec799ba1 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/j4save.f @@ -0,0 +1,65 @@ +*DECK J4SAVE + FUNCTION J4SAVE (IWHICH, IVALUE, ISET) +C***BEGIN PROLOGUE J4SAVE +C***SUBSIDIARY +C***PURPOSE Save or recall global variables needed by error +C handling routines. +C***LIBRARY SLATEC (XERROR) +C***TYPE INTEGER (J4SAVE-I) +C***KEYWORDS ERROR MESSAGES, ERROR NUMBER, RECALL, SAVE, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C J4SAVE saves and recalls several global variables needed +C by the library error handling routines. +C +C Description of Parameters +C --Input-- +C IWHICH - Index of item desired. +C = 1 Refers to current error number. +C = 2 Refers to current error control flag. +C = 3 Refers to current unit number to which error +C messages are to be sent. (0 means use standard.) +C = 4 Refers to the maximum number of times any +C message is to be printed (as set by XERMAX). +C = 5 Refers to the total number of units to which +C each error message is to be written. +C = 6 Refers to the 2nd unit for error messages +C = 7 Refers to the 3rd unit for error messages +C = 8 Refers to the 4th unit for error messages +C = 9 Refers to the 5th unit for error messages +C IVALUE - The value to be set for the IWHICH-th parameter, +C if ISET is .TRUE. . +C ISET - If ISET=.TRUE., the IWHICH-th parameter will BE +C given the value, IVALUE. If ISET=.FALSE., the +C IWHICH-th parameter will be unchanged, and IVALUE +C is a dummy parameter. +C --Output-- +C The (old) value of the IWHICH-th parameter will be returned +C in the function value, J4SAVE. +C +C***SEE ALSO XERMSG +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900205 Minor modifications to prologue. (WRB) +C 900402 Added TYPE section. (WRB) +C 910411 Added KEYWORDS section. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE J4SAVE + LOGICAL ISET + INTEGER IPARAM(9) + SAVE IPARAM + DATA IPARAM(1),IPARAM(2),IPARAM(3),IPARAM(4)/0,2,0,10/ + DATA IPARAM(5)/1/ + DATA IPARAM(6),IPARAM(7),IPARAM(8),IPARAM(9)/0,0,0,0/ +C***FIRST EXECUTABLE STATEMENT J4SAVE + J4SAVE = IPARAM(IWHICH) + IF (ISET) IPARAM(IWHICH) = IVALUE + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/qk61.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/qk61.f new file mode 100644 index 000000000..c1691262f --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/qk61.f @@ -0,0 +1,202 @@ + subroutine qk61(f,a,b,result,abserr,resabs,resasc) +c***begin prologue qk61 +c***date written 800101 (yymmdd) +c***revision date 830518 (yymmdd) +c***category no. h2a1a2 +c***keywords 61-point gauss-kronrod rules +c***author piessens,robert,appl. math. & progr. div. - k.u.leuven +c de doncker,elise,appl. math. & progr. div. - k.u.leuven +c***purpose to compute i = integral of f over (a,b) with error +c estimate +c j = integral of dabs(f) over (a,b) +c***description +c +c integration rule +c standard fortran subroutine +c real version +c +c +c parameters +c on entry +c f - real +c function subprogram defining the integrand +c function f(x). the actual name for f needs to be +c declared e x t e r n a l in the calling program. +c +c a - real +c lower limit of integration +c +c b - real +c upper limit of integration +c +c on return +c result - real +c approximation to the integral i +c result is computed by applying the 61-point +c kronrod rule (resk) obtained by optimal addition of +c abscissae to the 30-point gauss rule (resg). +c +c abserr - real +c estimate of the modulus of the absolute error, +c which should equal or exceed dabs(i-result) +c +c resabs - real +c approximation to the integral j +c +c resasc - real +c approximation to the integral of dabs(f-i/(b-a)) +c +c +c***references (none) +c***routines called r1mach +c***end prologue qk61 +c + real a,absc,abserr,b,centr,dhlgth,epmach,f,fc,fsum,fval1,fval2, + * fv1,fv2,hlgth,resabs,resasc,resg,resk,reskh,result,r1mach,uflow, + * wg,wgk,xgk + integer j,jtw,jtwm1 + external f +c + dimension fv1(30),fv2(30),xgk(31),wgk(31),wg(15) +c +c the abscissae and weights are given for the +c interval (-1,1). because of symmetry only the positive +c abscissae and their corresponding weights are given. +c +c xgk - abscissae of the 61-point kronrod rule +c xgk(2), xgk(4) ... abscissae of the 30-point +c gauss rule +c xgk(1), xgk(3) ... optimally added abscissae +c to the 30-point gauss rule +c +c wgk - weights of the 61-point kronrod rule +c +c wg - weigths of the 30-point gauss rule +c + data xgk(1),xgk(2),xgk(3),xgk(4),xgk(5),xgk(6),xgk(7),xgk(8), + * xgk(9),xgk(10)/ + * 0.9994844100504906e+00, 0.9968934840746495e+00, + * 0.9916309968704046e+00, 0.9836681232797472e+00, + * 0.9731163225011263e+00, 0.9600218649683075e+00, + * 0.9443744447485600e+00, 0.9262000474292743e+00, + * 0.9055733076999078e+00, 0.8825605357920527e+00/ + data xgk(11),xgk(12),xgk(13),xgk(14),xgk(15),xgk(16), + * xgk(17),xgk(18),xgk(19),xgk(20)/ + * 0.8572052335460611e+00, 0.8295657623827684e+00, + * 0.7997278358218391e+00, 0.7677774321048262e+00, + * 0.7337900624532268e+00, 0.6978504947933158e+00, + * 0.6600610641266270e+00, 0.6205261829892429e+00, + * 0.5793452358263617e+00, 0.5366241481420199e+00/ + data xgk(21),xgk(22),xgk(23),xgk(24), + * xgk(25),xgk(26),xgk(27),xgk(28),xgk(29),xgk(30),xgk(31)/ + * 0.4924804678617786e+00, 0.4470337695380892e+00, + * 0.4004012548303944e+00, 0.3527047255308781e+00, + * 0.3040732022736251e+00, 0.2546369261678898e+00, + * 0.2045251166823099e+00, 0.1538699136085835e+00, + * 0.1028069379667370e+00, 0.5147184255531770e-01, + * 0.0e+00 / + data wgk(1),wgk(2),wgk(3),wgk(4),wgk(5),wgk(6),wgk(7),wgk(8), + * wgk(9),wgk(10)/ + * 0.1389013698677008e-02, 0.3890461127099884e-02, + * 0.6630703915931292e-02, 0.9273279659517763e-02, + * 0.1182301525349634e-01, 0.1436972950704580e-01, + * 0.1692088918905327e-01, 0.1941414119394238e-01, + * 0.2182803582160919e-01, 0.2419116207808060e-01/ + data wgk(11),wgk(12),wgk(13),wgk(14),wgk(15),wgk(16), + * wgk(17),wgk(18),wgk(19),wgk(20)/ + * 0.2650995488233310e-01, 0.2875404876504129e-01, + * 0.3090725756238776e-01, 0.3298144705748373e-01, + * 0.3497933802806002e-01, 0.3688236465182123e-01, + * 0.3867894562472759e-01, 0.4037453895153596e-01, + * 0.4196981021516425e-01, 0.4345253970135607e-01/ + data wgk(21),wgk(22),wgk(23),wgk(24), + * wgk(25),wgk(26),wgk(27),wgk(28),wgk(29),wgk(30),wgk(31)/ + * 0.4481480013316266e-01, 0.4605923827100699e-01, + * 0.4718554656929915e-01, 0.4818586175708713e-01, + * 0.4905543455502978e-01, 0.4979568342707421e-01, + * 0.5040592140278235e-01, 0.5088179589874961e-01, + * 0.5122154784925877e-01, 0.5142612853745903e-01, + * 0.5149472942945157e-01/ + data wg(1),wg(2),wg(3),wg(4),wg(5),wg(6),wg(7),wg(8)/ + * 0.7968192496166606e-02, 0.1846646831109096e-01, + * 0.2878470788332337e-01, 0.3879919256962705e-01, + * 0.4840267283059405e-01, 0.5749315621761907e-01, + * 0.6597422988218050e-01, 0.7375597473770521e-01/ + data wg(9),wg(10),wg(11),wg(12),wg(13),wg(14),wg(15)/ + * 0.8075589522942022e-01, 0.8689978720108298e-01, + * 0.9212252223778613e-01, 0.9636873717464426e-01, + * 0.9959342058679527e-01, 0.1017623897484055e+00, + * 0.1028526528935588e+00/ +c +c list of major variables +c ----------------------- +c +c centr - mid point of the interval +c hlgth - half-length of the interval +c absc - abscissa +c fval* - function value +c resg - result of the 30-point gauss rule +c resk - result of the 61-point kronrod rule +c reskh - approximation to the mean value of f +c over (a,b), i.e. to i/(b-a) +c +c machine dependent constants +c --------------------------- +c +c epmach is the largest relative spacing. +c uflow is the smallest positive magnitude. +c +c***first executable statement qk61 + epmach = r1mach(4) + uflow = r1mach(1) +c + centr = 0.5e+00*(b+a) + hlgth = 0.5e+00*(b-a) + dhlgth = abs(hlgth) +c +c compute the 61-point kronrod approximation to the +c integral, and estimate the absolute error. +c + resg = 0.0e+00 + fc = f(centr) + resk = wgk(31)*fc + resabs = abs(resk) + do 10 j=1,15 + jtw = j*2 + absc = hlgth*xgk(jtw) + fval1 = f(centr-absc) + fval2 = f(centr+absc) + fv1(jtw) = fval1 + fv2(jtw) = fval2 + fsum = fval1+fval2 + resg = resg+wg(j)*fsum + resk = resk+wgk(jtw)*fsum + resabs = resabs+wgk(jtw)*(abs(fval1)+abs(fval2)) + 10 continue + do 15 j=1,15 + jtwm1 = j*2-1 + absc = hlgth*xgk(jtwm1) + fval1 = f(centr-absc) + fval2 = f(centr+absc) + fv1(jtwm1) = fval1 + fv2(jtwm1) = fval2 + fsum = fval1+fval2 + resk = resk+wgk(jtwm1)*fsum + resabs = resabs+wgk(jtwm1)*(abs(fval1)+abs(fval2)) + 15 continue + reskh = resk*0.5e+00 + resasc = wgk(31)*abs(fc-reskh) + do 20 j=1,30 + resasc = resasc+wgk(j)*(abs(fv1(j)-reskh)+abs(fv2(j)-reskh)) + 20 continue + result = resk*hlgth + resabs = resabs*dhlgth + resasc = resasc*dhlgth + abserr = abs((resk-resg)*hlgth) + if(resasc.ne.0.0e+00.and.abserr.ne.0.0e+00) + * abserr = resasc*amin1(0.1e+01, + * (0.2e+03*abserr/resasc)**1.5e+00) + if(resabs.gt.uflow/(0.5e+02*epmach)) abserr = amax1 + * ((epmach*0.5e+02)*resabs,abserr) + return + end diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/r1mach.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/r1mach.f new file mode 100644 index 000000000..43bc45179 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/r1mach.f @@ -0,0 +1,419 @@ +*DECK R1MACH + REAL FUNCTION R1MACH (I) +C***BEGIN PROLOGUE R1MACH +C***PURPOSE Return floating point machine dependent constants. +C***LIBRARY SLATEC +C***CATEGORY R1 +C***TYPE SINGLE PRECISION (R1MACH-S, D1MACH-D) +C***KEYWORDS MACHINE CONSTANTS +C***AUTHOR Fox, P. A., (Bell Labs) +C Hall, A. D., (Bell Labs) +C Schryer, N. L., (Bell Labs) +C***DESCRIPTION +C +C R1MACH can be used to obtain machine-dependent parameters for the +C local machine environment. It is a function subprogram with one +C (input) argument, and can be referenced as follows: +C +C A = R1MACH(I) +C +C where I=1,...,5. The (output) value of A above is determined by +C the (input) value of I. The results for various values of I are +C discussed below. +C +C R1MACH(1) = B**(EMIN-1), the smallest positive magnitude. +C R1MACH(2) = B**EMAX*(1 - B**(-T)), the largest magnitude. +C R1MACH(3) = B**(-T), the smallest relative spacing. +C R1MACH(4) = B**(1-T), the largest relative spacing. +C R1MACH(5) = LOG10(B) +C +C Assume single precision numbers are represented in the T-digit, +C base-B form +C +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, 0 .LT. X(1), and +C EMIN .LE. E .LE. EMAX. +C +C The values of B, T, EMIN and EMAX are provided in I1MACH as +C follows: +C I1MACH(10) = B, the base. +C I1MACH(11) = T, the number of base-B digits. +C I1MACH(12) = EMIN, the smallest exponent E. +C I1MACH(13) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, the desired +C set of DATA statements should be activated by removing the C from +C column 1. Also, the values of R1MACH(1) - R1MACH(4) should be +C checked for consistency with the local operating system. +C +C***REFERENCES P. A. Fox, A. D. Hall and N. L. Schryer, Framework for +C a portable library, ACM Transactions on Mathematical +C Software 4, 2 (June 1978), pp. 177-188. +C***ROUTINES CALLED XERMSG +C***REVISION HISTORY (YYMMDD) +C 790101 DATE WRITTEN +C 890213 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) +C 900618 Added DEC RISC constants. (WRB) +C 900723 Added IBM RS 6000 constants. (WRB) +C 910710 Added HP 730 constants. (SMR) +C 911114 Added Convex IEEE constants. (WRB) +C 920121 Added SUN -r8 compiler option constants. (WRB) +C 920229 Added Touchstone Delta i860 constants. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C 920625 Added CONVEX -p8 and -pd8 compiler option constants. +C (BKS, WRB) +C 930201 Added DEC Alpha and SGI constants. (RWC and WRB) +C***END PROLOGUE R1MACH +C + INTEGER SMALL(2) + INTEGER LARGE(2) + INTEGER RIGHT(2) + INTEGER DIVER(2) + INTEGER LOG10(2) +C + REAL RMACH(5) + SAVE RMACH +C + EQUIVALENCE (RMACH(1),SMALL(1)) + EQUIVALENCE (RMACH(2),LARGE(1)) + EQUIVALENCE (RMACH(3),RIGHT(1)) + EQUIVALENCE (RMACH(4),DIVER(1)) + EQUIVALENCE (RMACH(5),LOG10(1)) +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT FORTRAN COMPILER USING THE 68020/68881 COMPILER OPTION +C +C DATA SMALL(1) / Z'00800000' / +C DATA LARGE(1) / Z'7F7FFFFF' / +C DATA RIGHT(1) / Z'33800000' / +C DATA DIVER(1) / Z'34000000' / +C DATA LOG10(1) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT FORTRAN COMPILER USING SOFTWARE FLOATING POINT +C +C DATA SMALL(1) / Z'00800000' / +C DATA LARGE(1) / Z'7EFFFFFF' / +C DATA RIGHT(1) / Z'33800000' / +C DATA DIVER(1) / Z'34000000' / +C DATA LOG10(1) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE APOLLO +C +C DATA SMALL(1) / 16#00800000 / +C DATA LARGE(1) / 16#7FFFFFFF / +C DATA RIGHT(1) / 16#33800000 / +C DATA DIVER(1) / 16#34000000 / +C DATA LOG10(1) / 16#3E9A209B / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM +C +C DATA RMACH(1) / Z400800000 / +C DATA RMACH(2) / Z5FFFFFFFF / +C DATA RMACH(3) / Z4E9800000 / +C DATA RMACH(4) / Z4EA800000 / +C DATA RMACH(5) / Z500E730E8 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 5700/6700/7700 SYSTEMS +C +C DATA RMACH(1) / O1771000000000000 / +C DATA RMACH(2) / O0777777777777777 / +C DATA RMACH(3) / O1311000000000000 / +C DATA RMACH(4) / O1301000000000000 / +C DATA RMACH(5) / O1157163034761675 / +C +C MACHINE CONSTANTS FOR THE CDC 170/180 SERIES USING NOS/VE +C +C DATA RMACH(1) / Z"3001800000000000" / +C DATA RMACH(2) / Z"4FFEFFFFFFFFFFFE" / +C DATA RMACH(3) / Z"3FD2800000000000" / +C DATA RMACH(4) / Z"3FD3800000000000" / +C DATA RMACH(5) / Z"3FFF9A209A84FBCF" / +C +C MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES +C +C DATA RMACH(1) / 00564000000000000000B / +C DATA RMACH(2) / 37767777777777777776B / +C DATA RMACH(3) / 16414000000000000000B / +C DATA RMACH(4) / 16424000000000000000B / +C DATA RMACH(5) / 17164642023241175720B / +C +C MACHINE CONSTANTS FOR THE CELERITY C1260 +C +C DATA SMALL(1) / Z'00800000' / +C DATA LARGE(1) / Z'7F7FFFFF' / +C DATA RIGHT(1) / Z'33800000' / +C DATA DIVER(1) / Z'34000000' / +C DATA LOG10(1) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fn COMPILER OPTION +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7FFFFFFF' / +C DATA RMACH(3) / Z'34800000' / +C DATA RMACH(4) / Z'35000000' / +C DATA RMACH(5) / Z'3F9A209B' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fi COMPILER OPTION +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -p8 OR -pd8 COMPILER OPTION +C +C DATA RMACH(1) / Z'0010000000000000' / +C DATA RMACH(2) / Z'7FFFFFFFFFFFFFFF' / +C DATA RMACH(3) / Z'3CC0000000000000' / +C DATA RMACH(4) / Z'3CD0000000000000' / +C DATA RMACH(5) / Z'3FF34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE CRAY +C +C DATA RMACH(1) / 200034000000000000000B / +C DATA RMACH(2) / 577767777777777777776B / +C DATA RMACH(3) / 377224000000000000000B / +C DATA RMACH(4) / 377234000000000000000B / +C DATA RMACH(5) / 377774642023241175720B / +C +C MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200 +C NOTE - IT MAY BE APPROPRIATE TO INCLUDE THE FOLLOWING CARD - +C STATIC RMACH(5) +C +C DATA SMALL / 20K, 0 / +C DATA LARGE / 77777K, 177777K / +C DATA RIGHT / 35420K, 0 / +C DATA DIVER / 36020K, 0 / +C DATA LOG10 / 40423K, 42023K / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING G_FLOAT +C +C DATA RMACH(1) / '00000080'X / +C DATA RMACH(2) / 'FFFF7FFF'X / +C DATA RMACH(3) / '00003480'X / +C DATA RMACH(4) / '00003500'X / +C DATA RMACH(5) / '209B3F9A'X / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING IEEE_FLOAT +C +C DATA RMACH(1) / '00800000'X / +C DATA RMACH(2) / '7F7FFFFF'X / +C DATA RMACH(3) / '33800000'X / +C DATA RMACH(4) / '34000000'X / +C DATA RMACH(5) / '3E9A209B'X / +C +C MACHINE CONSTANTS FOR THE DEC RISC +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C (EXPRESSED IN INTEGER AND HEXADECIMAL) +C THE HEX FORMAT BELOW MAY NOT BE SUITABLE FOR UNIX SYSTEMS +C THE INTEGER FORMAT SHOULD BE OK FOR UNIX SYSTEMS +C +C DATA SMALL(1) / 128 / +C DATA LARGE(1) / -32769 / +C DATA RIGHT(1) / 13440 / +C DATA DIVER(1) / 13568 / +C DATA LOG10(1) / 547045274 / +C +C DATA SMALL(1) / Z00000080 / +C DATA LARGE(1) / ZFFFF7FFF / +C DATA RIGHT(1) / Z00003480 / +C DATA DIVER(1) / Z00003500 / +C DATA LOG10(1) / Z209B3F9A / +C +C MACHINE CONSTANTS FOR THE ELXSI 6400 +C (ASSUMING REAL*4 IS THE DEFAULT REAL) +C +C DATA SMALL(1) / '00800000'X / +C DATA LARGE(1) / '7F7FFFFF'X / +C DATA RIGHT(1) / '33800000'X / +C DATA DIVER(1) / '34000000'X / +C DATA LOG10(1) / '3E9A209B'X / +C +C MACHINE CONSTANTS FOR THE HARRIS 220 +C +C DATA SMALL(1), SMALL(2) / '20000000, '00000201 / +C DATA LARGE(1), LARGE(2) / '37777777, '00000177 / +C DATA RIGHT(1), RIGHT(2) / '20000000, '00000352 / +C DATA DIVER(1), DIVER(2) / '20000000, '00000353 / +C DATA LOG10(1), LOG10(2) / '23210115, '00000377 / +C +C MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 SERIES +C +C DATA RMACH(1) / O402400000000 / +C DATA RMACH(2) / O376777777777 / +C DATA RMACH(3) / O714400000000 / +C DATA RMACH(4) / O716400000000 / +C DATA RMACH(5) / O776464202324 / +C +C MACHINE CONSTANTS FOR THE HP 730 +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 3 WORD DOUBLE PRECISION WITH FTN4 +C +C DATA SMALL(1), SMALL(2) / 40000B, 1 / +C DATA LARGE(1), LARGE(2) / 77777B, 177776B / +C DATA RIGHT(1), RIGHT(2) / 40000B, 325B / +C DATA DIVER(1), DIVER(2) / 40000B, 327B / +C DATA LOG10(1), LOG10(2) / 46420B, 46777B / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 4 WORD DOUBLE PRECISION WITH FTN4 +C +C DATA SMALL(1), SMALL(2) / 40000B, 1 / +C DATA LARGE(1), LARGE(2) / 77777B, 177776B / +C DATA RIGHT(1), RIGHT(2) / 40000B, 325B / +C DATA DIVER(1), DIVER(2) / 40000B, 327B / +C DATA LOG10(1), LOG10(2) / 46420B, 46777B / +C +C MACHINE CONSTANTS FOR THE HP 9000 +C +C DATA SMALL(1) / 00004000000B / +C DATA LARGE(1) / 17677777777B / +C DATA RIGHT(1) / 06340000000B / +C DATA DIVER(1) / 06400000000B / +C DATA LOG10(1) / 07646420233B / +C +C MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, +C THE XEROX SIGMA 5/7/9, THE SEL SYSTEMS 85/86 AND +C THE PERKIN ELMER (INTERDATA) 7/32. +C +C DATA RMACH(1) / Z00100000 / +C DATA RMACH(2) / Z7FFFFFFF / +C DATA RMACH(3) / Z3B100000 / +C DATA RMACH(4) / Z3C100000 / +C DATA RMACH(5) / Z41134413 / +C +C MACHINE CONSTANTS FOR THE IBM PC +C +C DATA SMALL(1) / 1.18E-38 / +C DATA LARGE(1) / 3.40E+38 / +C DATA RIGHT(1) / 0.595E-07 / +C DATA DIVER(1) / 1.19E-07 / +C DATA LOG10(1) / 0.30102999566 / +C +C MACHINE CONSTANTS FOR THE IBM RS 6000 +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE INTEL i860 +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KA OR KI PROCESSOR) +C +C DATA RMACH(1) / "000400000000 / +C DATA RMACH(2) / "377777777777 / +C DATA RMACH(3) / "146400000000 / +C DATA RMACH(4) / "147400000000 / +C DATA RMACH(5) / "177464202324 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 32-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). +C +C DATA SMALL(1) / 8388608 / +C DATA LARGE(1) / 2147483647 / +C DATA RIGHT(1) / 880803840 / +C DATA DIVER(1) / 889192448 / +C DATA LOG10(1) / 1067065499 / +C +C DATA RMACH(1) / O00040000000 / +C DATA RMACH(2) / O17777777777 / +C DATA RMACH(3) / O06440000000 / +C DATA RMACH(4) / O06500000000 / +C DATA RMACH(5) / O07746420233 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 16-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). +C +C DATA SMALL(1), SMALL(2) / 128, 0 / +C DATA LARGE(1), LARGE(2) / 32767, -1 / +C DATA RIGHT(1), RIGHT(2) / 13440, 0 / +C DATA DIVER(1), DIVER(2) / 13568, 0 / +C DATA LOG10(1), LOG10(2) / 16282, 8347 / +C +C DATA SMALL(1), SMALL(2) / O000200, O000000 / +C DATA LARGE(1), LARGE(2) / O077777, O177777 / +C DATA RIGHT(1), RIGHT(2) / O032200, O000000 / +C DATA DIVER(1), DIVER(2) / O032400, O000000 / +C DATA LOG10(1), LOG10(2) / O037632, O020233 / +C +C MACHINE CONSTANTS FOR THE SILICON GRAPHICS +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE SUN +C +C DATA RMACH(1) / Z'00800000' / +C DATA RMACH(2) / Z'7F7FFFFF' / +C DATA RMACH(3) / Z'33800000' / +C DATA RMACH(4) / Z'34000000' / +C DATA RMACH(5) / Z'3E9A209B' / +C +C MACHINE CONSTANTS FOR THE SUN +C USING THE -r8 COMPILER OPTION +C +C DATA RMACH(1) / Z'0010000000000000' / +C DATA RMACH(2) / Z'7FEFFFFFFFFFFFFF' / +C DATA RMACH(3) / Z'3CA0000000000000' / +C DATA RMACH(4) / Z'3CB0000000000000' / +C DATA RMACH(5) / Z'3FD34413509F79FF' / +C +C MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES +C +C DATA RMACH(1) / O000400000000 / +C DATA RMACH(2) / O377777777777 / +C DATA RMACH(3) / O146400000000 / +C DATA RMACH(4) / O147400000000 / +C DATA RMACH(5) / O177464202324 / +C +C MACHINE CONSTANTS FOR THE Z80 MICROPROCESSOR +C +C DATA SMALL(1), SMALL(2) / 0, 256/ +C DATA LARGE(1), LARGE(2) / -1, -129/ +C DATA RIGHT(1), RIGHT(2) / 0, 26880/ +C DATA DIVER(1), DIVER(2) / 0, 27136/ +C DATA LOG10(1), LOG10(2) / 8347, 32538/ +C +C***FIRST EXECUTABLE STATEMENT R1MACH + IF (I .LT. 1 .OR. I .GT. 5) CALL XERMSG ('SLATEC', 'R1MACH', + + 'I OUT OF BOUNDS', 1, 2) +C + R1MACH = RMACH(I) + RETURN +C + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xercnt.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xercnt.f new file mode 100644 index 000000000..06c82ab18 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xercnt.f @@ -0,0 +1,60 @@ +*DECK XERCNT + SUBROUTINE XERCNT (LIBRAR, SUBROU, MESSG, NERR, LEVEL, KONTRL) +C***BEGIN PROLOGUE XERCNT +C***SUBSIDIARY +C***PURPOSE Allow user control over handling of errors. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERCNT-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C Allows user control over handling of individual errors. +C Just after each message is recorded, but before it is +C processed any further (i.e., before it is printed or +C a decision to abort is made), a call is made to XERCNT. +C If the user has provided his own version of XERCNT, he +C can then override the value of KONTROL used in processing +C this message by redefining its value. +C KONTRL may be set to any value from -2 to 2. +C The meanings for KONTRL are the same as in XSETF, except +C that the value of KONTRL changes only for this message. +C If KONTRL is set to a value outside the range from -2 to 2, +C it will be moved back into that range. +C +C Description of Parameters +C +C --Input-- +C LIBRAR - the library that the routine is in. +C SUBROU - the subroutine that XERMSG is being called from +C MESSG - the first 20 characters of the error message. +C NERR - same as in the call to XERMSG. +C LEVEL - same as in the call to XERMSG. +C KONTRL - the current value of the control flag as set +C by a call to XSETF. +C +C --Output-- +C KONTRL - the new value of KONTRL. If KONTRL is not +C defined, it will remain at its original value. +C This changed value of control affects only +C the current occurrence of the current message. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900206 Routine changed from user-callable to subsidiary. (WRB) +C 900510 Changed calling sequence to include LIBRARY and SUBROUTINE +C names, changed routine name from XERCTL to XERCNT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERCNT + CHARACTER*(*) LIBRAR, SUBROU, MESSG +C***FIRST EXECUTABLE STATEMENT XERCNT + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerhlt.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerhlt.f new file mode 100644 index 000000000..89b2a7709 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerhlt.f @@ -0,0 +1,39 @@ +*DECK XERHLT + SUBROUTINE XERHLT (MESSG) +C***BEGIN PROLOGUE XERHLT +C***SUBSIDIARY +C***PURPOSE Abort program execution and print error message. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERHLT-A) +C***KEYWORDS ABORT PROGRAM EXECUTION, ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C ***Note*** machine dependent routine +C XERHLT aborts the execution of the program. +C The error message causing the abort is given in the calling +C sequence, in case one needs it for printing on a dayfile, +C for example. +C +C Description of Parameters +C MESSG is as in XERMSG. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900206 Routine changed from user-callable to subsidiary. (WRB) +C 900510 Changed calling sequence to delete length of character +C and changed routine name from XERABT to XERHLT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERHLT + CHARACTER*(*) MESSG +C***FIRST EXECUTABLE STATEMENT XERHLT + STOP + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xermsg.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xermsg.f new file mode 100644 index 000000000..46c83ec07 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xermsg.f @@ -0,0 +1,364 @@ +*DECK XERMSG + SUBROUTINE XERMSG (LIBRAR, SUBROU, MESSG, NERR, LEVEL) +C***BEGIN PROLOGUE XERMSG +C***PURPOSE Process error messages for SLATEC and other libraries. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERMSG-A) +C***KEYWORDS ERROR MESSAGE, XERROR +C***AUTHOR Fong, Kirby, (NMFECC at LLNL) +C***DESCRIPTION +C +C XERMSG processes a diagnostic message in a manner determined by the +C value of LEVEL and the current value of the library error control +C flag, KONTRL. See subroutine XSETF for details. +C +C LIBRAR A character constant (or character variable) with the name +C of the library. This will be 'SLATEC' for the SLATEC +C Common Math Library. The error handling package is +C general enough to be used by many libraries +C simultaneously, so it is desirable for the routine that +C detects and reports an error to identify the library name +C as well as the routine name. +C +C SUBROU A character constant (or character variable) with the name +C of the routine that detected the error. Usually it is the +C name of the routine that is calling XERMSG. There are +C some instances where a user callable library routine calls +C lower level subsidiary routines where the error is +C detected. In such cases it may be more informative to +C supply the name of the routine the user called rather than +C the name of the subsidiary routine that detected the +C error. +C +C MESSG A character constant (or character variable) with the text +C of the error or warning message. In the example below, +C the message is a character constant that contains a +C generic message. +C +C CALL XERMSG ('SLATEC', 'MMPY', +C *'THE ORDER OF THE MATRIX EXCEEDS THE ROW DIMENSION', +C *3, 1) +C +C It is possible (and is sometimes desirable) to generate a +C specific message--e.g., one that contains actual numeric +C values. Specific numeric values can be converted into +C character strings using formatted WRITE statements into +C character variables. This is called standard Fortran +C internal file I/O and is exemplified in the first three +C lines of the following example. You can also catenate +C substrings of characters to construct the error message. +C Here is an example showing the use of both writing to +C an internal file and catenating character strings. +C +C CHARACTER*5 CHARN, CHARL +C WRITE (CHARN,10) N +C WRITE (CHARL,10) LDA +C 10 FORMAT(I5) +C CALL XERMSG ('SLATEC', 'MMPY', 'THE ORDER'//CHARN// +C * ' OF THE MATRIX EXCEEDS ITS ROW DIMENSION OF'// +C * CHARL, 3, 1) +C +C There are two subtleties worth mentioning. One is that +C the // for character catenation is used to construct the +C error message so that no single character constant is +C continued to the next line. This avoids confusion as to +C whether there are trailing blanks at the end of the line. +C The second is that by catenating the parts of the message +C as an actual argument rather than encoding the entire +C message into one large character variable, we avoid +C having to know how long the message will be in order to +C declare an adequate length for that large character +C variable. XERMSG calls XERPRN to print the message using +C multiple lines if necessary. If the message is very long, +C XERPRN will break it into pieces of 72 characters (as +C requested by XERMSG) for printing on multiple lines. +C Also, XERMSG asks XERPRN to prefix each line with ' * ' +C so that the total line length could be 76 characters. +C Note also that XERPRN scans the error message backwards +C to ignore trailing blanks. Another feature is that +C the substring '$$' is treated as a new line sentinel +C by XERPRN. If you want to construct a multiline +C message without having to count out multiples of 72 +C characters, just use '$$' as a separator. '$$' +C obviously must occur within 72 characters of the +C start of each line to have its intended effect since +C XERPRN is asked to wrap around at 72 characters in +C addition to looking for '$$'. +C +C NERR An integer value that is chosen by the library routine's +C author. It must be in the range -99 to 999 (three +C printable digits). Each distinct error should have its +C own error number. These error numbers should be described +C in the machine readable documentation for the routine. +C The error numbers need be unique only within each routine, +C so it is reasonable for each routine to start enumerating +C errors from 1 and proceeding to the next integer. +C +C LEVEL An integer value in the range 0 to 2 that indicates the +C level (severity) of the error. Their meanings are +C +C -1 A warning message. This is used if it is not clear +C that there really is an error, but the user's attention +C may be needed. An attempt is made to only print this +C message once. +C +C 0 A warning message. This is used if it is not clear +C that there really is an error, but the user's attention +C may be needed. +C +C 1 A recoverable error. This is used even if the error is +C so serious that the routine cannot return any useful +C answer. If the user has told the error package to +C return after recoverable errors, then XERMSG will +C return to the Library routine which can then return to +C the user's routine. The user may also permit the error +C package to terminate the program upon encountering a +C recoverable error. +C +C 2 A fatal error. XERMSG will not return to its caller +C after it receives a fatal error. This level should +C hardly ever be used; it is much better to allow the +C user a chance to recover. An example of one of the few +C cases in which it is permissible to declare a level 2 +C error is a reverse communication Library routine that +C is likely to be called repeatedly until it integrates +C across some interval. If there is a serious error in +C the input such that another step cannot be taken and +C the Library routine is called again without the input +C error having been corrected by the caller, the Library +C routine will probably be called forever with improper +C input. In this case, it is reasonable to declare the +C error to be fatal. +C +C Each of the arguments to XERMSG is input; none will be modified by +C XERMSG. A routine may make multiple calls to XERMSG with warning +C level messages; however, after a call to XERMSG with a recoverable +C error, the routine should return to the user. Do not try to call +C XERMSG with a second recoverable error after the first recoverable +C error because the error package saves the error number. The user +C can retrieve this error number by calling another entry point in +C the error handling package and then clear the error number when +C recovering from the error. Calling XERMSG in succession causes the +C old error number to be overwritten by the latest error number. +C This is considered harmless for error numbers associated with +C warning messages but must not be done for error numbers of serious +C errors. After a call to XERMSG with a recoverable error, the user +C must be given a chance to call NUMXER or XERCLR to retrieve or +C clear the error number. +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED FDUMP, J4SAVE, XERCNT, XERHLT, XERPRN, XERSVE +C***REVISION HISTORY (YYMMDD) +C 880101 DATE WRITTEN +C 880621 REVISED AS DIRECTED AT SLATEC CML MEETING OF FEBRUARY 1988. +C THERE ARE TWO BASIC CHANGES. +C 1. A NEW ROUTINE, XERPRN, IS USED INSTEAD OF XERPRT TO +C PRINT MESSAGES. THIS ROUTINE WILL BREAK LONG MESSAGES +C INTO PIECES FOR PRINTING ON MULTIPLE LINES. '$$' IS +C ACCEPTED AS A NEW LINE SENTINEL. A PREFIX CAN BE +C ADDED TO EACH LINE TO BE PRINTED. XERMSG USES EITHER +C ' ***' OR ' * ' AND LONG MESSAGES ARE BROKEN EVERY +C 72 CHARACTERS (AT MOST) SO THAT THE MAXIMUM LINE +C LENGTH OUTPUT CAN NOW BE AS GREAT AS 76. +C 2. THE TEXT OF ALL MESSAGES IS NOW IN UPPER CASE SINCE THE +C FORTRAN STANDARD DOCUMENT DOES NOT ADMIT THE EXISTENCE +C OF LOWER CASE. +C 880708 REVISED AFTER THE SLATEC CML MEETING OF JUNE 29 AND 30. +C THE PRINCIPAL CHANGES ARE +C 1. CLARIFY COMMENTS IN THE PROLOGUES +C 2. RENAME XRPRNT TO XERPRN +C 3. REWORK HANDLING OF '$$' IN XERPRN TO HANDLE BLANK LINES +C SIMILAR TO THE WAY FORMAT STATEMENTS HANDLE THE / +C CHARACTER FOR NEW RECORDS. +C 890706 REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO +C CLEAN UP THE CODING. +C 890721 REVISED TO USE NEW FEATURE IN XERPRN TO COUNT CHARACTERS IN +C PREFIX. +C 891013 REVISED TO CORRECT COMMENTS. +C 891214 Prologue converted to Version 4.0 format. (WRB) +C 900510 Changed test on NERR to be -9999999 < NERR < 99999999, but +C NERR .ne. 0, and on LEVEL to be -2 < LEVEL < 3. Added +C LEVEL=-1 logic, changed calls to XERSAV to XERSVE, and +C XERCTL to XERCNT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERMSG + CHARACTER*(*) LIBRAR, SUBROU, MESSG + CHARACTER*8 XLIBR, XSUBR + CHARACTER*72 TEMP + CHARACTER*20 LFIRST +C***FIRST EXECUTABLE STATEMENT XERMSG + LKNTRL = J4SAVE (2, 0, .FALSE.) + MAXMES = J4SAVE (4, 0, .FALSE.) +C +C LKNTRL IS A LOCAL COPY OF THE CONTROL FLAG KONTRL. +C MAXMES IS THE MAXIMUM NUMBER OF TIMES ANY PARTICULAR MESSAGE +C SHOULD BE PRINTED. +C +C WE PRINT A FATAL ERROR MESSAGE AND TERMINATE FOR AN ERROR IN +C CALLING XERMSG. THE ERROR NUMBER SHOULD BE POSITIVE, +C AND THE LEVEL SHOULD BE BETWEEN 0 AND 2. +C + IF (NERR.LT.-9999999 .OR. NERR.GT.99999999 .OR. NERR.EQ.0 .OR. + * LEVEL.LT.-1 .OR. LEVEL.GT.2) THEN + CALL XERPRN (' ***', -1, 'FATAL ERROR IN...$$ ' // + * 'XERMSG -- INVALID ERROR NUMBER OR LEVEL$$ '// + * 'JOB ABORT DUE TO FATAL ERROR.', 72) + CALL XERSVE (' ', ' ', ' ', 0, 0, 0, KDUMMY) + CALL XERHLT (' ***XERMSG -- INVALID INPUT') + RETURN + ENDIF +C +C RECORD THE MESSAGE. +C + I = J4SAVE (1, NERR, .TRUE.) + CALL XERSVE (LIBRAR, SUBROU, MESSG, 1, NERR, LEVEL, KOUNT) +C +C HANDLE PRINT-ONCE WARNING MESSAGES. +C + IF (LEVEL.EQ.-1 .AND. KOUNT.GT.1) RETURN +C +C ALLOW TEMPORARY USER OVERRIDE OF THE CONTROL FLAG. +C + XLIBR = LIBRAR + XSUBR = SUBROU + LFIRST = MESSG + LERR = NERR + LLEVEL = LEVEL + CALL XERCNT (XLIBR, XSUBR, LFIRST, LERR, LLEVEL, LKNTRL) +C + LKNTRL = MAX(-2, MIN(2,LKNTRL)) + MKNTRL = ABS(LKNTRL) +C +C SKIP PRINTING IF THE CONTROL FLAG VALUE AS RESET IN XERCNT IS +C ZERO AND THE ERROR IS NOT FATAL. +C + IF (LEVEL.LT.2 .AND. LKNTRL.EQ.0) GO TO 30 + IF (LEVEL.EQ.0 .AND. KOUNT.GT.MAXMES) GO TO 30 + IF (LEVEL.EQ.1 .AND. KOUNT.GT.MAXMES .AND. MKNTRL.EQ.1) GO TO 30 + IF (LEVEL.EQ.2 .AND. KOUNT.GT.MAX(1,MAXMES)) GO TO 30 +C +C ANNOUNCE THE NAMES OF THE LIBRARY AND SUBROUTINE BY BUILDING A +C MESSAGE IN CHARACTER VARIABLE TEMP (NOT EXCEEDING 66 CHARACTERS) +C AND SENDING IT OUT VIA XERPRN. PRINT ONLY IF CONTROL FLAG +C IS NOT ZERO. +C + IF (LKNTRL .NE. 0) THEN + TEMP(1:21) = 'MESSAGE FROM ROUTINE ' + I = MIN(LEN(SUBROU), 16) + TEMP(22:21+I) = SUBROU(1:I) + TEMP(22+I:33+I) = ' IN LIBRARY ' + LTEMP = 33 + I + I = MIN(LEN(LIBRAR), 16) + TEMP(LTEMP+1:LTEMP+I) = LIBRAR (1:I) + TEMP(LTEMP+I+1:LTEMP+I+1) = '.' + LTEMP = LTEMP + I + 1 + CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72) + ENDIF +C +C IF LKNTRL IS POSITIVE, PRINT AN INTRODUCTORY LINE BEFORE +C PRINTING THE MESSAGE. THE INTRODUCTORY LINE TELLS THE CHOICE +C FROM EACH OF THE FOLLOWING THREE OPTIONS. +C 1. LEVEL OF THE MESSAGE +C 'INFORMATIVE MESSAGE' +C 'POTENTIALLY RECOVERABLE ERROR' +C 'FATAL ERROR' +C 2. WHETHER CONTROL FLAG WILL ALLOW PROGRAM TO CONTINUE +C 'PROG CONTINUES' +C 'PROG ABORTED' +C 3. WHETHER OR NOT A TRACEBACK WAS REQUESTED. (THE TRACEBACK +C MAY NOT BE IMPLEMENTED AT SOME SITES, SO THIS ONLY TELLS +C WHAT WAS REQUESTED, NOT WHAT WAS DELIVERED.) +C 'TRACEBACK REQUESTED' +C 'TRACEBACK NOT REQUESTED' +C NOTICE THAT THE LINE INCLUDING FOUR PREFIX CHARACTERS WILL NOT +C EXCEED 74 CHARACTERS. +C WE SKIP THE NEXT BLOCK IF THE INTRODUCTORY LINE IS NOT NEEDED. +C + IF (LKNTRL .GT. 0) THEN +C +C THE FIRST PART OF THE MESSAGE TELLS ABOUT THE LEVEL. +C + IF (LEVEL .LE. 0) THEN + TEMP(1:20) = 'INFORMATIVE MESSAGE,' + LTEMP = 20 + ELSEIF (LEVEL .EQ. 1) THEN + TEMP(1:30) = 'POTENTIALLY RECOVERABLE ERROR,' + LTEMP = 30 + ELSE + TEMP(1:12) = 'FATAL ERROR,' + LTEMP = 12 + ENDIF +C +C THEN WHETHER THE PROGRAM WILL CONTINUE. +C + IF ((MKNTRL.EQ.2 .AND. LEVEL.GE.1) .OR. + * (MKNTRL.EQ.1 .AND. LEVEL.EQ.2)) THEN + TEMP(LTEMP+1:LTEMP+14) = ' PROG ABORTED,' + LTEMP = LTEMP + 14 + ELSE + TEMP(LTEMP+1:LTEMP+16) = ' PROG CONTINUES,' + LTEMP = LTEMP + 16 + ENDIF +C +C FINALLY TELL WHETHER THERE SHOULD BE A TRACEBACK. +C + IF (LKNTRL .GT. 0) THEN + TEMP(LTEMP+1:LTEMP+20) = ' TRACEBACK REQUESTED' + LTEMP = LTEMP + 20 + ELSE + TEMP(LTEMP+1:LTEMP+24) = ' TRACEBACK NOT REQUESTED' + LTEMP = LTEMP + 24 + ENDIF + CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72) + ENDIF +C +C NOW SEND OUT THE MESSAGE. +C + CALL XERPRN (' * ', -1, MESSG, 72) +C +C IF LKNTRL IS POSITIVE, WRITE THE ERROR NUMBER AND REQUEST A +C TRACEBACK. +C + IF (LKNTRL .GT. 0) THEN + WRITE (TEMP, '(''ERROR NUMBER = '', I8)') NERR + DO 10 I=16,22 + IF (TEMP(I:I) .NE. ' ') GO TO 20 + 10 CONTINUE +C + 20 CALL XERPRN (' * ', -1, TEMP(1:15) // TEMP(I:23), 72) + CALL FDUMP + ENDIF +C +C IF LKNTRL IS NOT ZERO, PRINT A BLANK LINE AND AN END OF MESSAGE. +C + IF (LKNTRL .NE. 0) THEN + CALL XERPRN (' * ', -1, ' ', 72) + CALL XERPRN (' ***', -1, 'END OF MESSAGE', 72) + CALL XERPRN (' ', 0, ' ', 72) + ENDIF +C +C IF THE ERROR IS NOT FATAL OR THE ERROR IS RECOVERABLE AND THE +C CONTROL FLAG IS SET FOR RECOVERY, THEN RETURN. +C + 30 IF (LEVEL.LE.0 .OR. (LEVEL.EQ.1 .AND. MKNTRL.LE.1)) RETURN +C +C THE PROGRAM WILL BE STOPPED DUE TO AN UNRECOVERED ERROR OR A +C FATAL ERROR. PRINT THE REASON FOR THE ABORT AND THE ERROR +C SUMMARY IF THE CONTROL FLAG AND THE MAXIMUM ERROR COUNT PERMIT. +C + IF (LKNTRL.GT.0 .AND. KOUNT.LT.MAX(1,MAXMES)) THEN + IF (LEVEL .EQ. 1) THEN + CALL XERPRN + * (' ***', -1, 'JOB ABORT DUE TO UNRECOVERED ERROR.', 72) + ELSE + CALL XERPRN(' ***', -1, 'JOB ABORT DUE TO FATAL ERROR.', 72) + ENDIF + CALL XERSVE (' ', ' ', ' ', -1, 0, 0, KDUMMY) + CALL XERHLT (' ') + ELSE + CALL XERHLT (MESSG) + ENDIF + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerprn.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerprn.f new file mode 100644 index 000000000..97eedf480 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xerprn.f @@ -0,0 +1,228 @@ +*DECK XERPRN + SUBROUTINE XERPRN (PREFIX, NPREF, MESSG, NWRAP) +C***BEGIN PROLOGUE XERPRN +C***SUBSIDIARY +C***PURPOSE Print error messages processed by XERMSG. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERPRN-A) +C***KEYWORDS ERROR MESSAGES, PRINTING, XERROR +C***AUTHOR Fong, Kirby, (NMFECC at LLNL) +C***DESCRIPTION +C +C This routine sends one or more lines to each of the (up to five) +C logical units to which error messages are to be sent. This routine +C is called several times by XERMSG, sometimes with a single line to +C print and sometimes with a (potentially very long) message that may +C wrap around into multiple lines. +C +C PREFIX Input argument of type CHARACTER. This argument contains +C characters to be put at the beginning of each line before +C the body of the message. No more than 16 characters of +C PREFIX will be used. +C +C NPREF Input argument of type INTEGER. This argument is the number +C of characters to use from PREFIX. If it is negative, the +C intrinsic function LEN is used to determine its length. If +C it is zero, PREFIX is not used. If it exceeds 16 or if +C LEN(PREFIX) exceeds 16, only the first 16 characters will be +C used. If NPREF is positive and the length of PREFIX is less +C than NPREF, a copy of PREFIX extended with blanks to length +C NPREF will be used. +C +C MESSG Input argument of type CHARACTER. This is the text of a +C message to be printed. If it is a long message, it will be +C broken into pieces for printing on multiple lines. Each line +C will start with the appropriate prefix and be followed by a +C piece of the message. NWRAP is the number of characters per +C piece; that is, after each NWRAP characters, we break and +C start a new line. In addition the characters '$$' embedded +C in MESSG are a sentinel for a new line. The counting of +C characters up to NWRAP starts over for each new line. The +C value of NWRAP typically used by XERMSG is 72 since many +C older error messages in the SLATEC Library are laid out to +C rely on wrap-around every 72 characters. +C +C NWRAP Input argument of type INTEGER. This gives the maximum size +C piece into which to break MESSG for printing on multiple +C lines. An embedded '$$' ends a line, and the count restarts +C at the following character. If a line break does not occur +C on a blank (it would split a word) that word is moved to the +C next line. Values of NWRAP less than 16 will be treated as +C 16. Values of NWRAP greater than 132 will be treated as 132. +C The actual line length will be NPREF + NWRAP after NPREF has +C been adjusted to fall between 0 and 16 and NWRAP has been +C adjusted to fall between 16 and 132. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED I1MACH, XGETUA +C***REVISION HISTORY (YYMMDD) +C 880621 DATE WRITTEN +C 880708 REVISED AFTER THE SLATEC CML SUBCOMMITTEE MEETING OF +C JUNE 29 AND 30 TO CHANGE THE NAME TO XERPRN AND TO REWORK +C THE HANDLING OF THE NEW LINE SENTINEL TO BEHAVE LIKE THE +C SLASH CHARACTER IN FORMAT STATEMENTS. +C 890706 REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO +C STREAMLINE THE CODING AND FIX A BUG THAT CAUSED EXTRA BLANK +C LINES TO BE PRINTED. +C 890721 REVISED TO ADD A NEW FEATURE. A NEGATIVE VALUE OF NPREF +C CAUSES LEN(PREFIX) TO BE USED AS THE LENGTH. +C 891013 REVISED TO CORRECT ERROR IN CALCULATING PREFIX LENGTH. +C 891214 Prologue converted to Version 4.0 format. (WRB) +C 900510 Added code to break messages between words. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERPRN + CHARACTER*(*) PREFIX, MESSG + INTEGER NPREF, NWRAP + CHARACTER*148 CBUFF + INTEGER IU(5), NUNIT + CHARACTER*2 NEWLIN + PARAMETER (NEWLIN = '$$') +C***FIRST EXECUTABLE STATEMENT XERPRN + CALL XGETUA(IU,NUNIT) +C +C A ZERO VALUE FOR A LOGICAL UNIT NUMBER MEANS TO USE THE STANDARD +C ERROR MESSAGE UNIT INSTEAD. I1MACH(4) RETRIEVES THE STANDARD +C ERROR MESSAGE UNIT. +C + N = I1MACH(4) + DO 10 I=1,NUNIT + IF (IU(I) .EQ. 0) IU(I) = N + 10 CONTINUE +C +C LPREF IS THE LENGTH OF THE PREFIX. THE PREFIX IS PLACED AT THE +C BEGINNING OF CBUFF, THE CHARACTER BUFFER, AND KEPT THERE DURING +C THE REST OF THIS ROUTINE. +C + IF ( NPREF .LT. 0 ) THEN + LPREF = LEN(PREFIX) + ELSE + LPREF = NPREF + ENDIF + LPREF = MIN(16, LPREF) + IF (LPREF .NE. 0) CBUFF(1:LPREF) = PREFIX +C +C LWRAP IS THE MAXIMUM NUMBER OF CHARACTERS WE WANT TO TAKE AT ONE +C TIME FROM MESSG TO PRINT ON ONE LINE. +C + LWRAP = MAX(16, MIN(132, NWRAP)) +C +C SET LENMSG TO THE LENGTH OF MESSG, IGNORE ANY TRAILING BLANKS. +C + LENMSG = LEN(MESSG) + N = LENMSG + DO 20 I=1,N + IF (MESSG(LENMSG:LENMSG) .NE. ' ') GO TO 30 + LENMSG = LENMSG - 1 + 20 CONTINUE + 30 CONTINUE +C +C IF THE MESSAGE IS ALL BLANKS, THEN PRINT ONE BLANK LINE. +C + IF (LENMSG .EQ. 0) THEN + CBUFF(LPREF+1:LPREF+1) = ' ' + DO 40 I=1,NUNIT + WRITE(IU(I), '(A)') CBUFF(1:LPREF+1) + 40 CONTINUE + RETURN + ENDIF +C +C SET NEXTC TO THE POSITION IN MESSG WHERE THE NEXT SUBSTRING +C STARTS. FROM THIS POSITION WE SCAN FOR THE NEW LINE SENTINEL. +C WHEN NEXTC EXCEEDS LENMSG, THERE IS NO MORE TO PRINT. +C WE LOOP BACK TO LABEL 50 UNTIL ALL PIECES HAVE BEEN PRINTED. +C +C WE LOOK FOR THE NEXT OCCURRENCE OF THE NEW LINE SENTINEL. THE +C INDEX INTRINSIC FUNCTION RETURNS ZERO IF THERE IS NO OCCURRENCE +C OR IF THE LENGTH OF THE FIRST ARGUMENT IS LESS THAN THE LENGTH +C OF THE SECOND ARGUMENT. +C +C THERE ARE SEVERAL CASES WHICH SHOULD BE CHECKED FOR IN THE +C FOLLOWING ORDER. WE ARE ATTEMPTING TO SET LPIECE TO THE NUMBER +C OF CHARACTERS THAT SHOULD BE TAKEN FROM MESSG STARTING AT +C POSITION NEXTC. +C +C LPIECE .EQ. 0 THE NEW LINE SENTINEL DOES NOT OCCUR IN THE +C REMAINDER OF THE CHARACTER STRING. LPIECE +C SHOULD BE SET TO LWRAP OR LENMSG+1-NEXTC, +C WHICHEVER IS LESS. +C +C LPIECE .EQ. 1 THE NEW LINE SENTINEL STARTS AT MESSG(NEXTC: +C NEXTC). LPIECE IS EFFECTIVELY ZERO, AND WE +C PRINT NOTHING TO AVOID PRODUCING UNNECESSARY +C BLANK LINES. THIS TAKES CARE OF THE SITUATION +C WHERE THE LIBRARY ROUTINE HAS A MESSAGE OF +C EXACTLY 72 CHARACTERS FOLLOWED BY A NEW LINE +C SENTINEL FOLLOWED BY MORE CHARACTERS. NEXTC +C SHOULD BE INCREMENTED BY 2. +C +C LPIECE .GT. LWRAP+1 REDUCE LPIECE TO LWRAP. +C +C ELSE THIS LAST CASE MEANS 2 .LE. LPIECE .LE. LWRAP+1 +C RESET LPIECE = LPIECE-1. NOTE THAT THIS +C PROPERLY HANDLES THE END CASE WHERE LPIECE .EQ. +C LWRAP+1. THAT IS, THE SENTINEL FALLS EXACTLY +C AT THE END OF A LINE. +C + NEXTC = 1 + 50 LPIECE = INDEX(MESSG(NEXTC:LENMSG), NEWLIN) + IF (LPIECE .EQ. 0) THEN +C +C THERE WAS NO NEW LINE SENTINEL FOUND. +C + IDELTA = 0 + LPIECE = MIN(LWRAP, LENMSG+1-NEXTC) + IF (LPIECE .LT. LENMSG+1-NEXTC) THEN + DO 52 I=LPIECE+1,2,-1 + IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN + LPIECE = I-1 + IDELTA = 1 + GOTO 54 + ENDIF + 52 CONTINUE + ENDIF + 54 CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + IDELTA + ELSEIF (LPIECE .EQ. 1) THEN +C +C WE HAVE A NEW LINE SENTINEL AT MESSG(NEXTC:NEXTC+1). +C DON'T PRINT A BLANK LINE. +C + NEXTC = NEXTC + 2 + GO TO 50 + ELSEIF (LPIECE .GT. LWRAP+1) THEN +C +C LPIECE SHOULD BE SET DOWN TO LWRAP. +C + IDELTA = 0 + LPIECE = LWRAP + DO 56 I=LPIECE+1,2,-1 + IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN + LPIECE = I-1 + IDELTA = 1 + GOTO 58 + ENDIF + 56 CONTINUE + 58 CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + IDELTA + ELSE +C +C IF WE ARRIVE HERE, IT MEANS 2 .LE. LPIECE .LE. LWRAP+1. +C WE SHOULD DECREMENT LPIECE BY ONE. +C + LPIECE = LPIECE - 1 + CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + 2 + ENDIF +C +C PRINT +C + DO 60 I=1,NUNIT + WRITE(IU(I), '(A)') CBUFF(1:LPREF+LPIECE) + 60 CONTINUE +C + IF (NEXTC .LE. LENMSG) GO TO 50 + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xersve.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xersve.f new file mode 100644 index 000000000..6bd2a4f7a --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xersve.f @@ -0,0 +1,155 @@ +*DECK XERSVE + SUBROUTINE XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL, + + ICOUNT) +C***BEGIN PROLOGUE XERSVE +C***SUBSIDIARY +C***PURPOSE Record that an error has occurred. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3 +C***TYPE ALL (XERSVE-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C *Usage: +C +C INTEGER KFLAG, NERR, LEVEL, ICOUNT +C CHARACTER * (len) LIBRAR, SUBROU, MESSG +C +C CALL XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL, ICOUNT) +C +C *Arguments: +C +C LIBRAR :IN is the library that the message is from. +C SUBROU :IN is the subroutine that the message is from. +C MESSG :IN is the message to be saved. +C KFLAG :IN indicates the action to be performed. +C when KFLAG > 0, the message in MESSG is saved. +C when KFLAG=0 the tables will be dumped and +C cleared. +C when KFLAG < 0, the tables will be dumped and +C not cleared. +C NERR :IN is the error number. +C LEVEL :IN is the error severity. +C ICOUNT :OUT the number of times this message has been seen, +C or zero if the table has overflowed and does not +C contain this message specifically. When KFLAG=0, +C ICOUNT will not be altered. +C +C *Description: +C +C Record that this error occurred and possibly dump and clear the +C tables. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED I1MACH, XGETUA +C***REVISION HISTORY (YYMMDD) +C 800319 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900413 Routine modified to remove reference to KFLAG. (WRB) +C 900510 Changed to add LIBRARY NAME and SUBROUTINE to calling +C sequence, use IF-THEN-ELSE, make number of saved entries +C easily changeable, changed routine name from XERSAV to +C XERSVE. (RWC) +C 910626 Added LIBTAB and SUBTAB to SAVE statement. (BKS) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERSVE + PARAMETER (LENTAB=10) + INTEGER LUN(5) + CHARACTER*(*) LIBRAR, SUBROU, MESSG + CHARACTER*8 LIBTAB(LENTAB), SUBTAB(LENTAB), LIB, SUB + CHARACTER*20 MESTAB(LENTAB), MES + DIMENSION NERTAB(LENTAB), LEVTAB(LENTAB), KOUNT(LENTAB) + SAVE LIBTAB, SUBTAB, MESTAB, NERTAB, LEVTAB, KOUNT, KOUNTX, NMSG + DATA KOUNTX/0/, NMSG/0/ +C***FIRST EXECUTABLE STATEMENT XERSVE +C + IF (KFLAG.LE.0) THEN +C +C Dump the table. +C + IF (NMSG.EQ.0) RETURN +C +C Print to each unit. +C + CALL XGETUA (LUN, NUNIT) + DO 20 KUNIT = 1,NUNIT + IUNIT = LUN(KUNIT) + IF (IUNIT.EQ.0) IUNIT = I1MACH(4) +C +C Print the table header. +C + WRITE (IUNIT,9000) +C +C Print body of table. +C + DO 10 I = 1,NMSG + WRITE (IUNIT,9010) LIBTAB(I), SUBTAB(I), MESTAB(I), + * NERTAB(I),LEVTAB(I),KOUNT(I) + 10 CONTINUE +C +C Print number of other errors. +C + IF (KOUNTX.NE.0) WRITE (IUNIT,9020) KOUNTX + WRITE (IUNIT,9030) + 20 CONTINUE +C +C Clear the error tables. +C + IF (KFLAG.EQ.0) THEN + NMSG = 0 + KOUNTX = 0 + ENDIF + ELSE +C +C PROCESS A MESSAGE... +C SEARCH FOR THIS MESSG, OR ELSE AN EMPTY SLOT FOR THIS MESSG, +C OR ELSE DETERMINE THAT THE ERROR TABLE IS FULL. +C + LIB = LIBRAR + SUB = SUBROU + MES = MESSG + DO 30 I = 1,NMSG + IF (LIB.EQ.LIBTAB(I) .AND. SUB.EQ.SUBTAB(I) .AND. + * MES.EQ.MESTAB(I) .AND. NERR.EQ.NERTAB(I) .AND. + * LEVEL.EQ.LEVTAB(I)) THEN + KOUNT(I) = KOUNT(I) + 1 + ICOUNT = KOUNT(I) + RETURN + ENDIF + 30 CONTINUE +C + IF (NMSG.LT.LENTAB) THEN +C +C Empty slot found for new message. +C + NMSG = NMSG + 1 + LIBTAB(I) = LIB + SUBTAB(I) = SUB + MESTAB(I) = MES + NERTAB(I) = NERR + LEVTAB(I) = LEVEL + KOUNT (I) = 1 + ICOUNT = 1 + ELSE +C +C Table is full. +C + KOUNTX = KOUNTX+1 + ICOUNT = 0 + ENDIF + ENDIF + RETURN +C +C Formats. +C + 9000 FORMAT ('0 ERROR MESSAGE SUMMARY' / + + ' LIBRARY SUBROUTINE MESSAGE START NERR', + + ' LEVEL COUNT') + 9010 FORMAT (1X,A,3X,A,3X,A,3I10) + 9020 FORMAT ('0OTHER ERRORS NOT INDIVIDUALLY TABULATED = ', I10) + 9030 FORMAT (1X) + END diff --git a/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xgetua.f b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xgetua.f new file mode 100644 index 000000000..2e7db0212 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/NetLib/slatec/xgetua.f @@ -0,0 +1,51 @@ +*DECK XGETUA + SUBROUTINE XGETUA (IUNITA, N) +C***BEGIN PROLOGUE XGETUA +C***PURPOSE Return unit number(s) to which error messages are being +C sent. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XGETUA-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C XGETUA may be called to determine the unit number or numbers +C to which error messages are being sent. +C These unit numbers may have been set by a call to XSETUN, +C or a call to XSETUA, or may be a default value. +C +C Description of Parameters +C --Output-- +C IUNIT - an array of one to five unit numbers, depending +C on the value of N. A value of zero refers to the +C default unit, as defined by the I1MACH machine +C constant routine. Only IUNIT(1),...,IUNIT(N) are +C defined by XGETUA. The values of IUNIT(N+1),..., +C IUNIT(5) are not defined (for N .LT. 5) or altered +C in any way by XGETUA. +C N - the number of units to which copies of the +C error messages are being sent. N will be in the +C range from 1 to 5. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED J4SAVE +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XGETUA + DIMENSION IUNITA(5) +C***FIRST EXECUTABLE STATEMENT XGETUA + N = J4SAVE(5,0,.FALSE.) + DO 30 I=1,N + INDEX = I+4 + IF (I.EQ.1) INDEX = 3 + IUNITA(I) = J4SAVE(INDEX,0,.FALSE.) + 30 CONTINUE + RETURN + END diff --git a/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library.txt b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library.txt new file mode 100644 index 000000000..a237d6de6 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library.txt @@ -0,0 +1,71 @@ +# This file defines types that may be used from the NWTC_Library +# include this into a component registry file if you wish to use these types +# the "usefrom" keyword defines the types for the registry without generating +# a NWTC_Library_Types.f90 file +# +#............................................................. + + +usefrom NWTC_Library ProgDesc CHARACTER(99) Name +usefrom ^ ^ CHARACTER(99) Ver +usefrom ^ ^ CHARACTER(24) Date + +usefrom ^ FASTdataType CHARACTER(1024) File +usefrom ^ ^ CHARACTER(1024) Descr +usefrom ^ ^ IntKi NumChans +usefrom ^ ^ IntKi NumRecs +usefrom ^ ^ DbKi TimeStep +usefrom ^ ^ CHARACTER(ChanLen) ChanNames {:} +usefrom ^ ^ CHARACTER(ChanLen) ChanUnits {:} +usefrom ^ ^ ReKi Data {:}{:} + +usefrom NWTC_Library OutParmType IntKi Indx +usefrom ^ ^ CHARACTER(ChanLen) Name +usefrom ^ ^ CHARACTER(ChanLen) Units +usefrom ^ ^ IntKi SignM + +usefrom NWTC_Library FileInfoType IntKi NumLines +usefrom ^ ^ IntKi NumFiles +usefrom ^ ^ IntKi FileLine {:} +usefrom ^ ^ IntKi FileIndx {:} +usefrom ^ ^ CHARACTER(1024) FileList {:} +usefrom ^ ^ CHARACTER(1024) Lines {:} + +usefrom NWTC_Library Quaternion ReKi q0 +usefrom ^ ^ ReKi v {3} + +usefrom NWTC_Library NWTC_RandomNumber_ParameterType IntKi pRNG +usefrom ^ ^ IntKi RandSeed {3} +usefrom ^ ^ IntKi RandSeedAry {:} +usefrom ^ ^ CHARACTER(6) RNG_type + +#BJJ: the following three types will actually be placed in the ModMesh_Mapping.f90 file instead of NWTC_Library_Types.f90 +usefrom NWTC_Library MapType IntKi OtherMesh_Element +usefrom ^ ^ R8Ki distance - +usefrom ^ ^ R8Ki couple_arm {3} +usefrom ^ ^ R8Ki shape_fn {2} + +usefrom NWTC_Library MeshMapLinearizationType R8Ki mi {:}{:} +usefrom ^ ^ R8Ki fx_p {:}{:} +usefrom ^ ^ R8Ki tv_uD {:}{:} +usefrom ^ ^ R8Ki tv_uS {:}{:} +usefrom ^ ^ R8Ki ta_uD {:}{:} +usefrom ^ ^ R8Ki ta_uS {:}{:} +usefrom ^ ^ R8Ki ta_rv {:}{:} +usefrom ^ ^ R8Ki li {:}{:} +usefrom ^ ^ R8Ki M_u {:}{:} +usefrom ^ ^ R8Ki M_t {:}{:} +usefrom ^ ^ R8Ki M_f {:}{:} + +usefrom NWTC_Library MeshMapType MapType MapLoads {:} +usefrom ^ ^ MapType MapMotions {:} +usefrom ^ ^ MapType MapSrcToAugmt {:} +usefrom ^ ^ MeshType Augmented_Ln2_Src - +usefrom ^ ^ MeshType Lumped_Points_Src - +usefrom ^ ^ INTEGER LoadLn2_A_Mat_Piv {:} +usefrom ^ ^ R8Ki DisplacedPosition {:}{:}{:} +usefrom ^ ^ R8Ki LoadLn2_A_Mat {:}{:} +usefrom ^ ^ R8Ki LoadLn2_F {:}{:} +usefrom ^ ^ R8Ki LoadLn2_M {:}{:} +usefrom ^ ^ MeshMapLinearizationType dM + diff --git a/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_mesh.txt b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_mesh.txt new file mode 100644 index 000000000..e1720a477 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_mesh.txt @@ -0,0 +1,40 @@ +# This file defines types that may be used from the NWTC_Library +# include this into a component registry file if you wish to use these types +# the "usefrom" keyword defines the types for the registry without generating +# a NWTC_Library_Types.f90 file +# +#............................................................. + + + +#BJJ: the following three types will actually be placed in the ModMesh_Mapping.f90 file instead of NWTC_Library_Types.f90 +typedef NWTC_Library MapType IntKi OtherMesh_Element - - - "Node (for point meshes) or Element (for line2 meshes) number on other mesh; for loads, other mesh is Dest, for motions/scalars, other mesh is Src" +typedef ^ ^ R8Ki distance - - - "Magnitude of couple_arm" m +typedef ^ ^ R8Ki couple_arm {3} - - "Vector between a point and node 1 of an element (p_ODR - p_OSR)" m +typedef ^ ^ R8Ki shape_fn {2} - - "shape functions: 1-D element-level location [0,1] based on closest-line projection of point" - + +typedef NWTC_Library MeshMapLinearizationType R8Ki mi {:}{:} - - "block matrix of motions that reflects identity (i.e., solely the mapping of one quantity to itself on another mesh)" +typedef ^ ^ R8Ki fx_p {:}{:} - - "block matrix of motions that reflects skew-symmetric (cross-product) matrix" +typedef ^ ^ R8Ki tv_uD {:}{:} - - "block matrix of translational velocity that is multiplied by destination translational displacement" +typedef ^ ^ R8Ki tv_uS {:}{:} - - "block matrix of translational velocity that is multiplied by source translational displacement" +typedef ^ ^ R8Ki ta_uD {:}{:} - - "block matrix of translational acceleration that is multiplied by destination translational displacement" +typedef ^ ^ R8Ki ta_uS {:}{:} - - "block matrix of translational acceleration that is multiplied by source translational displacement" +typedef ^ ^ R8Ki ta_rv {:}{:} - - "block matrix of translational acceleration that is multiplied by omega (RotationVel)" +typedef ^ ^ R8Ki li {:}{:} - - "block matrix of loads that reflects identity (i.e., solely the mapping on one quantity to itself on another mesh)" +typedef ^ ^ R8Ki M_uS {:}{:} - - "block matrix of moment that is multiplied by Source u (translationDisp)" +typedef ^ ^ R8Ki M_uD {:}{:} - - "block matrix of moment that is multiplied by Destination u (translationDisp)" +typedef ^ ^ R8Ki M_f {:}{:} - - "block matrix of moment that is multiplied by force" + +typedef NWTC_Library MeshMapType MapType MapLoads {:} - - "mapping data structure for load fields on the mesh" +typedef ^ ^ MapType MapMotions {:} - - "mapping data structure for motion and/or scalar fields on the mesh" +typedef ^ ^ MapType MapSrcToAugmt {:} - - "for source line2 loads, we map between source and an augmented source mesh, then between augmented source and destination" +typedef ^ ^ MeshType Augmented_Ln2_Src - - - "temporary mesh for storing augmented line2 source values" +typedef ^ ^ MeshType Lumped_Points_Src - - - "temporary mesh for lumping lines to points, stored here for efficiency" +typedef ^ ^ INTEGER LoadLn2_A_Mat_Piv {:} - - "The pivot values for the factorization of LoadLn2_A_Mat" +typedef ^ ^ R8Ki DisplacedPosition {:}{:}{:} - - "couple_arm +Scr%Disp - Dest%Disp for each mapped node (stored here for efficiency)" m +typedef ^ ^ R8Ki LoadLn2_A_Mat {:}{:} - - "The 3-components of the forces for each node of an element in the point-to-line load mapping (for each element)" +typedef ^ ^ R8Ki LoadLn2_F {:}{:} - - "The 6-by-6 matrix that makes up the diagonal of the [A 0; B A] matrix in the point-to-line load mapping" +typedef ^ ^ R8Ki LoadLn2_M {:}{:} - - "The 3-components of the moments for each node of an element in the point-to-line load mapping (for each element)" +typedef ^ ^ MeshMapLinearizationType dM +#typedef ^ ^ MeshType Lumped_Points_Dest - - - "temporary mesh for debugging the lumped values in the line2-to-line2" + diff --git a/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_nomesh.txt b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_nomesh.txt new file mode 100644 index 000000000..3207dde39 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/Registry_NWTC_Library_typedef_nomesh.txt @@ -0,0 +1,40 @@ +# This file defines types that may be used from the NWTC_Library +# include this into a component registry file if you wish to use these types +# the "usefrom" keyword defines the types for the registry without generating +# a NWTC_Library_Types.f90 file +# +#............................................................. + + +typedef NWTC_Library ProgDesc CHARACTER(99) Name - - - "Name of the program or module" +typedef ^ ^ CHARACTER(99) Ver - - - "Version number of the program or module" +typedef ^ ^ CHARACTER(24) Date - - - "String containing date module was last updated" + +typedef NWTC_Library FASTdataType CHARACTER(1024) File - - - "Name of the FAST-style binary file" +typedef ^ ^ CHARACTER(1024) Descr - - - "String describing file" +typedef ^ ^ IntKi NumChans - - - "Number of output channels in this binary file (not including the time channel)" +typedef ^ ^ IntKi NumRecs - - - "Number of records (rows) of data in the file" +typedef ^ ^ DbKi TimeStep - - - "Time step for evenly-spaced data in the output file (when NumRecs is not allo" +typedef ^ ^ CHARACTER(ChanLen) ChanNames {:} - - "Strings describing the names of the channels from the binary file (including the time channel)" +typedef ^ ^ CHARACTER(ChanLen) ChanUnits {:} - - "Strings describing the units of the channels from the binary file (including the time channel)" +typedef ^ ^ ReKi Data {:}{:} - - "numeric data (rows and columns) from the binary file, including the time channel" + +typedef NWTC_Library OutParmType IntKi Indx - - - "An index into AllOuts array where this channel is computed/stored" +typedef ^ ^ CHARACTER(ChanLen) Name - - - "Name of the output channel" +typedef ^ ^ CHARACTER(ChanLen) Units - - - "Units this channel is specified in" +typedef ^ ^ IntKi SignM - - - "Multiplier for output channel; usually -1 (minus) or 0 (invalid channel)" + +typedef NWTC_Library FileInfoType IntKi NumLines +typedef ^ ^ IntKi NumFiles +typedef ^ ^ IntKi FileLine {:} +typedef ^ ^ IntKi FileIndx {:} +typedef ^ ^ CHARACTER(1024) FileList {:} +typedef ^ ^ CHARACTER(1024) Lines {:} + +typedef NWTC_Library Quaternion ReKi q0 +typedef ^ ^ ReKi v {3} + +typedef NWTC_Library NWTC_RandomNumber_ParameterType IntKi pRNG +typedef ^ ^ IntKi RandSeed {3} +typedef ^ ^ IntKi RandSeedAry {:} +typedef ^ ^ CHARACTER(6) RNG_type diff --git a/OpenFAST/modules/nwtc-library/src/SingPrec.f90 b/OpenFAST/modules/nwtc-library/src/SingPrec.f90 new file mode 100644 index 000000000..3f98240cd --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SingPrec.f90 @@ -0,0 +1,78 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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. +! +!********************************************************************************************************************************** + +!.................................................................................................................................. +!> This module stores constants to specify the KIND of variables. +!! +!! NOTE: When using preprocessor definition DOUBLE_PRECISION (which sets ReKi=R8Ki and DbKi=QuKi), you +!! may need to use a compile option to convert default reals to 8 bytes: \n +!! - Intel: /real_size:64 /double_size:128 +!! - Gnu: -fdefault-real-8 +MODULE Precision +!.................................................................................................................................. + +#ifdef HAS_FORTRAN2008_FEATURES +USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: real32, real64, real128 +#endif + +IMPLICIT NONE + +INTEGER, PARAMETER :: B1Ki = SELECTED_INT_KIND( 2 ) !< Kind for one-byte whole numbers +INTEGER, PARAMETER :: B2Ki = SELECTED_INT_KIND( 4 ) !< Kind for two-byte whole numbers +INTEGER, PARAMETER :: B4Ki = SELECTED_INT_KIND( 9 ) !< Kind for four-byte whole numbers +INTEGER, PARAMETER :: B8Ki = SELECTED_INT_KIND( 18 ) !< Kind for eight-byte whole numbers + +#ifdef HAS_FORTRAN2008_FEATURES +INTEGER, PARAMETER :: QuKi = real128 !< Kind for 16-byte, floating-point numbers +INTEGER, PARAMETER :: R8Ki = real64 !< Kind for eight-byte floating-point numbers +INTEGER, PARAMETER :: SiKi = real32 !< Kind for four-byte, floating-point numbers +#else +INTEGER, PARAMETER :: QuKi = SELECTED_REAL_KIND( 20, 500 ) !< Kind for 16-byte, floating-point numbers +INTEGER, PARAMETER :: R8Ki = SELECTED_REAL_KIND( 14, 300 ) !< Kind for eight-byte floating-point numbers +INTEGER, PARAMETER :: SiKi = SELECTED_REAL_KIND( 6, 30 ) !< Kind for four-byte, floating-point numbers +#endif + +INTEGER, PARAMETER :: BYTES_IN_SiKi = 4 !< Number of bytes per SiKi number +INTEGER, PARAMETER :: BYTES_IN_R8Ki = 8 !< Number of bytes per R8Ki number +INTEGER, PARAMETER :: BYTES_IN_QuKi = 16 !< Number of bytes per QuKi number + + + + ! The default kinds for reals and integers, and the number of bytes they contain: + +INTEGER, PARAMETER :: IntKi = B4Ki !< Default kind for integers +INTEGER, PARAMETER :: BYTES_IN_INT = 4 !< Number of bytes per IntKi number - use SIZEOF() + +#if !defined (DOUBLE_PRECISION) && !defined (OPENFAST_DOUBLE_PRECISION) +INTEGER, PARAMETER :: ReKi = SiKi !< Default kind for floating-point numbers +INTEGER, PARAMETER :: DbKi = R8Ki !< Default kind for double floating-point numbers + +INTEGER, PARAMETER :: BYTES_IN_REAL = BYTES_IN_SiKi !< Number of bytes per ReKi number - use SIZEOF() +INTEGER, PARAMETER :: BYTES_IN_DBL = BYTES_IN_R8Ki !< Number of bytes per DbKi number - use SIZEOF() +#else +INTEGER, PARAMETER :: ReKi = R8Ki !< Default kind for floating-point numbers +INTEGER, PARAMETER :: DbKi = QuKi !< Default kind for double floating-point numbers + +INTEGER, PARAMETER :: BYTES_IN_REAL = BYTES_IN_R8Ki !< Number of bytes per ReKi number - use SIZEOF() +INTEGER, PARAMETER :: BYTES_IN_DBL = BYTES_IN_QuKi !< Number of bytes per DbKi number - use SIZEOF() +#endif + + +END MODULE Precision diff --git a/OpenFAST/modules/nwtc-library/src/SysGnuLinux.f90 b/OpenFAST/modules/nwtc-library/src/SysGnuLinux.f90 new file mode 100644 index 000000000..b036c045c --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysGnuLinux.f90 @@ -0,0 +1,562 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! SysGnuLinux.f90 is specifically for the GNU Fortran (gfortran) compiler on Linux and macOS. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .TRUE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'GNU Fortran for Linux' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '/' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '-' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'UNFORMATTED' ! The string to specify unformatted I/O files. + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + INTEGER(4) :: StatArray(13) ! An array returned by FSTAT that includes the file size. + INTEGER(4) :: Status ! The status returned by + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! Note that IsNaN does not exist in earlier versions of gfortran (e.g., 4.2.1), + ! but does exist in version 4.4. It should be replaced with the standard + ! IEEE_IS_NAN when gfortran implements it. + + REAL(DbKi), INTENT(IN) :: DblNum + LOGICAL :: Is_Nan + + Is_NaN = IsNaN( DblNum ) + + RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +SUBROUTINE FlushOut ( Unit ) + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + ! CALL FLUSH ( Unit ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +!bjj note: this subroutine is not tested for this compiler +SUBROUTINE Get_CWD ( DirName, Status ) + + ! This routine retrieves the path of the current working directory. + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +SUBROUTINE MKDIR ( new_directory_path ) + + ! This routine creates a given directory if it does not exist. + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( file=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir -p '//trim(new_directory_path) + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +SUBROUTINE OpenCon + + ! This routine opens the console for standard output. + +!bjj: Because CU = 6 now, this statement is not necessary +! OPEN ( CU , FILE='/dev/stdout' , STATUS='OLD' ) + +! CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ' ) ! Use this for UNIX systems. + ! ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +SUBROUTINE ProgExit ( StatCode ) + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF + +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) F03 has standard intrinsic routines to do this, + ! but Gnu has not yet implemented it. This code will fail if + ! the compiler checks for floating-point-error, hence the + ! compiler directive FPE_TRAP_ENABLED. + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) + REAL(DbKi) :: Neg_D ! a negative real(DbKi) number + REAL(ReKi) :: Neg ! a negative real(ReKi) number + + + ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. + ! note that anything that refers to NaN or Inf will be incorrect in that case. + +#ifndef FPE_TRAP_ENABLED + ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) + Neg_D = -1.0_DbKi + Neg = -1.0_ReKi + + NaN_D = SQRT ( Neg_D ) + NaN = SQRT ( Neg ) + + ! set variables to zero to calculate Infs (using division by zero) + Neg_D = 0.0_DbKi + Neg = 0.0_ReKi + + Inf_D = 1.0_DbKi / Neg_D + Inf = 1.0_ReKi / Neg +#endif + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +SUBROUTINE UsrAlarm + + ! This routine generates an alarm to warn the user that something went wrong. + + CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +SUBROUTINE WrNR ( Str ) + + ! This routine writes out a string to the screen without following it with a new line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + WRITE (CU,'(A)',ADVANCE='NO') Str + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + INTEGER(IntKi) :: NChars ! Number of characters to write + CHARACTER(1), PARAMETER :: CR = ACHAR( 13 ) ! The carriage return character. + CHARACTER(25) :: Fmt = '(2A, (" "))' ! The format specifier for the output. + + NChars = MaxWrScrLen - LEN( Str ) + + IF ( NChars > 0 ) THEN + ! bjj: note that this will produce an error if NChars > 999 + WRITE (Fmt(5:7),'(I3)') NChars + WRITE (CU,Fmt,ADVANCE='NO') CR, Str + ELSE + ! bjj: note that this will almost certainly write more than MaxWrScrLen characters on a line + WRITE (CU,'(2A)',ADVANCE='NO') CR, Str + END IF + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + + IF ( ErrStat /= 0 ) THEN + print *, ' WriteScr produced an error. Please inform the programmer.' + ENDIF + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +#ifdef USE_DLL_INTERFACE + +!bjj: these are values I found on the web; I have no idea if they actually work... +!bjj: hopefully we can find them pre-defined in a header somewhere + INTEGER(C_INT), PARAMETER :: RTLD_LAZY=1 ! "Perform lazy binding. Only resolve symbols as the code that references them is executed. If the symbol is never referenced, then it is never resolved. (Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.) " + INTEGER(C_INT), PARAMETER :: RTLD_NOW=2 ! "If this value is specified, or the environment variable LD_BIND_NOW is set to a nonempty string, all undefined symbols in the library are resolved before dlopen() returns. If this cannot be done, an error is returned." + INTEGER(C_INT), PARAMETER :: RTLD_GLOBAL=256 ! "The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries" + INTEGER(C_INT), PARAMETER :: RTLD_LOCAL=0 ! "This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. Symbols defined in this library are not made available to resolve references in subsequently loaded libraries." + + INTERFACE !linux API routines + !bjj see http://linux.die.net/man/3/dlopen + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html + + FUNCTION dlOpen(filename,mode) BIND(C,NAME="dlopen") + ! void *dlopen(const char *filename, int mode); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_PTR) :: dlOpen + CHARACTER(C_CHAR), INTENT(IN) :: filename(*) + INTEGER(C_INT), VALUE :: mode + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + + DLL%FileAddrX = dlOpen( TRIM(DLL%FileName)//C_NULL_CHAR, RTLD_LAZY ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a procedure from a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: i + +#ifdef USE_DLL_INTERFACE + + INTERFACE !linux API routines + + !bjj see http://linux.die.net/man/3/dlsym + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlsym.3.html + + FUNCTION dlSym(handle,name) BIND(C,NAME="dlsym") + ! void *dlsym(void *handle, const char *name); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_FUNPTR) :: dlSym ! A function pointer + TYPE(C_PTR), VALUE :: handle + CHARACTER(C_CHAR), INTENT(IN) :: name(*) + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + DLL%ProcAddr(i) = dlSym( DLL%FileAddrX, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLibProc: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(C_INT) :: Success ! Whether or not the call to dlClose was successful + INTEGER(C_INT), PARAMETER :: TRUE = 0 + +#ifdef USE_DLL_INTERFACE +!bjj: note that this is not tested. + + INTERFACE !linux API routine + !bjj see http://linux.die.net/man/3/dlclose + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlclose.3.html + + FUNCTION dlClose(handle) BIND(C,NAME="dlclose") + ! int dlclose(void *handle); + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(C_INT) :: dlClose + TYPE(C_PTR), VALUE :: handle + END FUNCTION + + END INTERFACE + + ! Close the library: + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) RETURN + Success = dlClose( DLL%FileAddrX ) !The function dlclose() returns 0 on success, and nonzero on error. + + IF ( Success /= TRUE ) THEN !bjj: note that this is not the same as LOGICAL .TRUE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddrX = C_NULL_PTR + END IF + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' FreeDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysGnuWin.f90 b/OpenFAST/modules/nwtc-library/src/SysGnuWin.f90 new file mode 100644 index 000000000..048b82c3e --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysGnuWin.f90 @@ -0,0 +1,531 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! SysGnuWin.f90 is specifically for the GNU Fortran (gfortran) compiler on Windows. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .TRUE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'GNU Fortran for Windows' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '\' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '/' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'UNFORMATTED' ! The string to specify unformatted I/O files. + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + INTEGER(4) :: StatArray(13) ! An array returned by FSTAT that includes the file size. + INTEGER(4) :: Status ! The status returned by + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! Note that IsNaN does not exist in earlier versions of gfortran (e.g., 4.2.1), + ! but does exist in version 4.4. It should be replaced with the standard + ! IEEE_IS_NAN when gfortran implements it. + + REAL(DbKi), INTENT(IN) :: DblNum + LOGICAL :: Is_Nan + + Is_NaN = IsNaN( DblNum ) + + RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +SUBROUTINE FlushOut ( Unit ) + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + ! CALL FLUSH ( Unit ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +!bjj note: this subroutine is not tested for this compiler +SUBROUTINE Get_CWD ( DirName, Status ) + + ! This routine retrieves the path of the current working directory. + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +SUBROUTINE MKDIR ( new_directory_path ) + + ! This routine creates a given directory if it does not exist. + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( file=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir "'//trim(new_directory_path)//'"' + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +SUBROUTINE OpenCon + + ! This routine opens the console for standard output. + +!bjj: removed for use with CygWin; Because CU = 6 now, this statement is not necessary +! OPEN ( CU , FILE='/dev/stdout' , STATUS='OLD' ) + +! CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ' ) ! Use this for UNIX systems. + ! ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +SUBROUTINE ProgExit ( StatCode ) + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF + +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) F03 has standard intrinsic routines to do this, + ! but Gnu has not yet implemented it. This code will fail if + ! the compiler checks for floating-point-error, hence the + ! compiler directive FPE_TRAP_ENABLED. + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) + REAL(DbKi) :: Neg_D ! a negative real(DbKi) number + REAL(ReKi) :: Neg ! a negative real(ReKi) number + + + ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. + ! note that anything that refers to NaN or Inf will be incorrect in that case. + +#ifndef FPE_TRAP_ENABLED + ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) + Neg_D = -1.0_DbKi + Neg = -1.0_ReKi + + NaN_D = SQRT ( Neg_D ) + NaN = SQRT ( Neg ) + + ! set variables to zero to calculate Infs (using division by zero) + Neg_D = 0.0_DbKi + Neg = 0.0_ReKi + + Inf_D = 1.0_DbKi / Neg_D + Inf = 1.0_ReKi / Neg +#endif + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +SUBROUTINE UsrAlarm + + ! This routine generates an alarm to warn the user that something went wrong. + + CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +SUBROUTINE WrNR ( Str ) + + ! This routine writes out a string to the screen without following it with a new line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + INTEGER(IntKi) :: NChars ! Number of characters to write + CHARACTER(1), PARAMETER :: CR = ACHAR( 13 ) ! The carriage return character. + CHARACTER(25) :: Fmt = '(2A, (" "))' ! The format specifier for the output. + + NChars = MaxWrScrLen - LEN( Str ) + + IF ( NChars > 0 ) THEN + ! bjj: note that this will produce an error if NChars > 999 + WRITE (Fmt(5:7),'(I3)') NChars + WRITE (CU,Fmt,ADVANCE='NO') CR, Str + ELSE + ! bjj: note that this will almost certainly write more than MaxWrScrLen characters on a line + WRITE (CU,'(2A)',ADVANCE='NO') CR, Str + END IF + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + + IF ( ErrStat /= 0 ) THEN + print *, ' WriteScr produced an error. Please inform the programmer.' + ENDIF + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTERFACE ! Definitions of Windows API routines + + !........................... + !bjj: I have been unable to find a solution that works with both IVF and gfortran... + !bjj: note that "Intel Fortran does not support use of STDCALL with BIND(C) at this time" + ! See this link: http://software.intel.com/en-us/articles/replacing-intel-fortran-attributes-with-c-interoperability-features + !bjj: Until this is fixed, Intel uses kernel32.f90 definitions instead of the interface below: + !........................... + + FUNCTION LoadLibrary(lpFileName) BIND(C,NAME='LoadLibraryA') + USE, INTRINSIC :: ISO_C_BINDING + IMPLICIT NONE + !GCC$ ATTRIBUTES STDCALL :: LoadLibrary + INTEGER(C_INTPTR_T) :: LoadLibrary + CHARACTER(KIND=C_CHAR) :: lpFileName(*) + END FUNCTION LoadLibrary + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + DLL%FileAddr = LoadLibrary( TRIM(DLL%FileName)//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a procedure in a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: i + + INTERFACE ! Definitions of Windows API routines + + !........................... + !bjj: I have been unable to find a solution that works with both IVF and gfortran... + !bjj: note that "Intel Fortran does not support use of STDCALL with BIND(C) at this time" + ! See this link: http://software.intel.com/en-us/articles/replacing-intel-fortran-attributes-with-c-interoperability-features + !bjj: Until this is fixed, Intel uses kernel32.f90 definitions instead of the interface below: + !........................... + + FUNCTION GetProcAddress(hModule, lpProcName) BIND(C, NAME='GetProcAddress') + USE, INTRINSIC :: ISO_C_BINDING + IMPLICIT NONE + !GCC$ ATTRIBUTES STDCALL :: GetProcAddress + TYPE(C_FUNPTR) :: GetProcAddress + INTEGER(C_INTPTR_T),VALUE :: hModule + CHARACTER(KIND=C_CHAR) :: lpProcName(*) + END FUNCTION GetProcAddress + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Get the procedure addresses: + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + DLL%ProcAddr(i) = GetProcAddress( DLL%FileAddr, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + end if + end do + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variable: + INTEGER(C_INT) :: Success ! Whether or not the call to FreeLibrary was successful + INTEGER(C_INT), PARAMETER :: FALSE = 0 + + INTERFACE ! Definitions of Windows API routines + + FUNCTION FreeLibrary(hLibModule) BIND(C, NAME='FreeLibrary') + USE, INTRINSIC :: ISO_C_BINDING + IMPLICIT NONE + !GCC$ ATTRIBUTES STDCALL :: FreeLibrary + INTEGER(C_INT) :: FreeLibrary ! BOOL + INTEGER(C_INTPTR_T),VALUE :: hLibModule ! HMODULE hLibModule + END FUNCTION + + END INTERFACE + + ! Free the DLL: + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) RETURN + + Success = FreeLibrary( DLL%FileAddr ) !If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. + + IF ( Success == FALSE ) THEN !BJJ: note that this isn't the same as the Fortran LOGICAL .FALSE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddr = INT(0,C_INTPTR_T) + END IF + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysIFL.f90 b/OpenFAST/modules/nwtc-library/src/SysIFL.f90 new file mode 100644 index 000000000..b5cf3fd39 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysIFL.f90 @@ -0,0 +1,541 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! SysIFL.f90 is specifically for the Intel Fortran for Linux compiler. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .TRUE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Fortran for Linux' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '/' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '-' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'UNFORMATTED' ! The string to specify unformatted I/O files. + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + USE IFPORT + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. + INTEGER :: Status ! The status returned by + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN in new code, but remains here for + ! backwards compatibility. + + USE, INTRINSIC :: ieee_arithmetic + + REAL(DbKi), INTENT(IN) :: DblNum + LOGICAL :: Is_Nan + + Is_NaN = IEEE_IS_NAN( DblNum ) + + RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +SUBROUTINE FlushOut ( Unit ) + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + USE IFPORT + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + CALL FLUSH ( INT(Unit, B4Ki) ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +SUBROUTINE Get_CWD ( DirName, Status ) + + USE IFPORT, ONLY: GETCWD + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +SUBROUTINE MKDIR ( new_directory_path ) + + ! This routine creates a given directory if it does not exist. + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( directory=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir -p '//trim(new_directory_path) + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +SUBROUTINE OpenCon + + ! This routine opens the console for standard output. + + USE IFPORT + +!bjj: Because CU = 6 now, this statement is not necessary +! OPEN ( CU , FILE='/dev/stdout' , STATUS='UNKNOWN' , CARRIAGECONTROL='FORTRAN', RECL=ConRecL ) + +! CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ' ) ! Use this for UNIX systems. +! ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +SUBROUTINE ProgExit ( StatCode ) + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF + +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) This uses standard F03 intrinsic routines, + ! however Gnu has not yet implemented it, so we've placed this + ! routine in the system-specific code. + + USE, INTRINSIC :: ieee_arithmetic ! use this for compilers that have implemented ieee_arithmetic from F03 standard (otherwise see logic in SysGnu*.f90) + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) + Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) + + NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) + Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +SUBROUTINE UsrAlarm + + ! This routine generates an alarm to warn the user that something went wrong. + + CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +SUBROUTINE WrNR ( Str ) + + ! This routine writes out a string to the screen without following it with a new line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + WRITE (CU,'(''+'',A)') Str + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + + IF ( ErrStat /= 0 ) THEN + print *, ' WriteScr produced an error. Please inform the programmer.' + ENDIF + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +#ifdef USE_DLL_INTERFACE + +!bjj: these are values I found on the web; I have no idea if they actually work... +!bjj: hopefully we can find them pre-defined in a header somewhere + INTEGER(C_INT), PARAMETER :: RTLD_LAZY=1 ! "Perform lazy binding. Only resolve symbols as the code that references them is executed. If the symbol is never referenced, then it is never resolved. (Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.) " + INTEGER(C_INT), PARAMETER :: RTLD_NOW=2 ! "If this value is specified, or the environment variable LD_BIND_NOW is set to a nonempty string, all undefined symbols in the library are resolved before dlopen() returns. If this cannot be done, an error is returned." + INTEGER(C_INT), PARAMETER :: RTLD_GLOBAL=256 ! "The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries" + INTEGER(C_INT), PARAMETER :: RTLD_LOCAL=0 ! "This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. Symbols defined in this library are not made available to resolve references in subsequently loaded libraries." + + INTERFACE !linux API routines + !bjj see http://linux.die.net/man/3/dlopen + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html + + FUNCTION dlOpen(filename,mode) BIND(C,NAME="dlopen") + ! void *dlopen(const char *filename, int mode); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_PTR) :: dlOpen + CHARACTER(C_CHAR), INTENT(IN) :: filename(*) + INTEGER(C_INT), VALUE :: mode + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + + DLL%FileAddrX = dlOpen( TRIM(DLL%FileName)//C_NULL_CHAR, RTLD_LAZY ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a procedure from a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: i + +#ifdef USE_DLL_INTERFACE + + INTERFACE !linux API routines + + !bjj see http://linux.die.net/man/3/dlsym + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlsym.3.html + + FUNCTION dlSym(handle,name) BIND(C,NAME="dlsym") + ! void *dlsym(void *handle, const char *name); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_FUNPTR) :: dlSym ! A function pointer + TYPE(C_PTR), VALUE :: handle + CHARACTER(C_CHAR), INTENT(IN) :: name(*) + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + DLL%ProcAddr(i) = dlSym( DLL%FileAddrX, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLibProc: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(C_INT) :: Success ! Whether or not the call to dlClose was successful + INTEGER(C_INT), PARAMETER :: TRUE = 0 + +#ifdef USE_DLL_INTERFACE +!bjj: note that this is not tested. + + INTERFACE !linux API routine + !bjj see http://linux.die.net/man/3/dlclose + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlclose.3.html + + FUNCTION dlClose(handle) BIND(C,NAME="dlclose") + ! int dlclose(void *handle); + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(C_INT) :: dlClose + TYPE(C_PTR), VALUE :: handle + END FUNCTION + + END INTERFACE + + ! Close the library: + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) RETURN + Success = dlClose( DLL%FileAddrX ) !The function dlclose() returns 0 on success, and nonzero on error. + + IF ( Success /= TRUE ) THEN !bjj: note that this is not the same as LOGICAL .TRUE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddrX = C_NULL_PTR + END IF + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' FreeDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN + END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysIVF.f90 b/OpenFAST/modules/nwtc-library/src/SysIVF.f90 new file mode 100644 index 000000000..b0329e466 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysIVF.f90 @@ -0,0 +1,470 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! SysIVF.f90 is specifically for the Intel Visual Fortran for Windows compiler. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 7 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .TRUE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Visual Fortran for Windows'! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '\' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '/' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'BINARY' ! The string to specify unformatted I/O files. (used in OpenUOutFile and OpenUInpFile [see TurbSim's .bin files]) + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + +USE IFPORT + +INTEGER(B8Ki) :: FileSize !< The size of the file in bytes to be returned. +INTEGER, INTENT(IN) :: Unit !< The I/O unit number of the pre-opened file. +INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. +INTEGER :: Status ! The status returned by + +Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + +IF ( Status /= 0 ) THEN + FileSize = -1 +ELSE + FileSize = StatArray(8) +END IF + +RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a NaN (not-a-number) value. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN, but remains here for + ! backwards compatibility (some older compilers aren't yet current). + +USE, INTRINSIC :: ieee_arithmetic + +REAL(DbKi), INTENT(IN) :: DblNum !< scalar value in question +LOGICAL :: Is_Nan + +Is_NaN = IEEE_IS_NAN( DblNum ) + +RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +!> This function returns the ERF value of its argument. The result has a value equal +!! to the Gauss error function: +!! \f{equation}{ +!! \mathrm{erf}(x)=\frac{2}{\sqrt{\pi}}\int_0^x e^{-t^2}\,dt +!! \f} \n +!! Use NWTC_ERF (syssubs::nwtc_erf) instead of directly calling a specific routine in the generic interface. +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x !< input + REAL(SiKi) :: NWTC_ERFR4 !< \f$\mathrm{erf}(x)\f$ + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +!> \copydoc syssubs::nwtc_erfr4 +FUNCTION NWTC_ERFR8( x ) + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! this function + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +!> \copydoc syssubs::nwtc_erfr4 +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +!> Returns the gamma value of its argument. The result has a value equal +!! to a processor-dependent approximation to the gamma function of x: +!! \f{equation}{ +!! \mathrm{ \Gamma }(x) = \int_0^\infty t^{x-1}e^{-t}\,dt +!! \f} \n +!! Use NWTC_Gamma (syssubs::nwtc_gamma) instead of directly calling a specific routine in the generic interface. +FUNCTION NWTC_GammaR4( x ) + +! \mathrm{ \Gamma }(x) = \int_0^\infinity t^{x-1}e^{-t}\,dt + + REAL(SiKi), INTENT(IN) :: x !< input + REAL(SiKi) :: NWTC_GammaR4 !< \f$\mathrm{\Gamma}(x)\f$ + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +!> \copydoc syssubs::nwtc_gammar4 +FUNCTION NWTC_GammaR8( x ) + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +!> \copydoc syssubs::nwtc_gammar4 +FUNCTION NWTC_GammaR16( x ) + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +!> This subroutine flushes the buffer on the specified Unit. +!! It is especially useful when printing "running..." type messages. +SUBROUTINE FlushOut ( Unit ) + + USE IFPORT + + INTEGER, INTENT(IN) :: Unit !< The unit number of the file being flushed. + + CALL FLUSH ( INT(Unit, B4Ki) ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +!> This routine retrieves the path of the current working directory. +SUBROUTINE Get_CWD ( DirName, Status ) + + USE IFPORT, ONLY: GETCWD + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName !< A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status !< Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +!> This routine creates a given directory if it does not already exist. +SUBROUTINE MKDIR ( new_directory_path ) + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( directory=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir "'//trim(new_directory_path)//'"' + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +!> This routine opens the console for standard output. +SUBROUTINE OpenCon() + + USE IFPORT + + OPEN ( CU , FILE='CON' , STATUS='UNKNOWN' , CARRIAGECONTROL='FORTRAN', RECL=ConRecL ) + + CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +!> This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) +!! Data are stored in RecLen-byte records. (This routine is used for +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un !< Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file. + INTEGER, INTENT(IN) :: RecLen !< Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error !< Flag to indicate the open failed (true indicates an error occurred). + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ! ACTION='READ' ) ! Use this for UNIX systems. + ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +!> This routine stops the program immediately. If the compiler supports the EXIT routine, +!! pass the program status to it. Otherwise, do a STOP. +SUBROUTINE ProgExit ( StatCode ) + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +!> This routine sets the values of NaN_D, Inf_D, NaN, Inf (IEEE +!! values for not-a-number and infinity in sindle and double +!! precision) This uses standard F03 intrinsic routines, +!! however Gnu has not yet implemented it, so we've placed this +!! routine in the system-specific code. +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + USE, INTRINSIC :: ieee_arithmetic ! use this for compilers that have implemented ieee_arithmetic from F03 standard (otherwise see logic in SysGnu*.f90) + + REAL(DbKi), INTENT(inout) :: Inf_D !< IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D !< IEEE value for Inf (infinity) in double precision + + REAL(ReKi), INTENT(inout) :: Inf !< IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN !< IEEE value for Inf (infinity) + + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) + Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) + + NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) + Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +!> This routine generates an alarm to warn the user that something went wrong. +SUBROUTINE UsrAlarm() + + CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +!> This routine writes out a string to the screen without following it with a new line. +SUBROUTINE WrNR ( Str ) + + CHARACTER(*), INTENT(IN) :: Str !< The string to write to the screen. + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +!> This routine writes out a string that overwrites the previous line +SUBROUTINE WrOver ( Str ) + + CHARACTER(*), INTENT(IN) :: Str !< The string to write to the screen. + + INTEGER :: MaxLen !< maximum length of string to be written to the screen (cannot exceed ConRecL here) + + ! When the file is opened using CARRIAGECONTROL='FORTRAN', the "+" character allows writing over the previous line. However, the Fortran carriage control has been deleted from the Fortran standard. + + MaxLen = min(ConRecL-1, len(Str)) + if (MaxLen > 0) then + WRITE (CU,'("+",A)') Str(1:MaxLen) + end if + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +!> This routine writes out a string to the screen. +SUBROUTINE WriteScr ( Str, Frm ) + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str !< The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm !< Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +!> This subroutine is used to dynamically load a DLL, using operating-system API routines to do so. +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + USE IFWINTY, ONLY : HANDLE + USE kernel32, ONLY : LoadLibrary + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(HANDLE) :: FileAddr ! The address of file FileName. (RETURN value from LoadLibrary in kernel32.f90) + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + FileAddr = LoadLibrary( TRIM(DLL%FileName)//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + DLL%FileAddr = TRANSFER(FileAddr, DLL%FileAddr) !convert INTEGER(HANDLE) to INTEGER(C_INTPTR_T) [used only for compatibility with gfortran] + + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This subroutine is used to dynamically load a procedure in a DLL, using operating-system API routines to do so. + + USE IFWINTY, ONLY : LPVOID + USE kernel32, ONLY : GetProcAddress + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(LPVOID) :: ProcAddr ! The address of procedure ProcName. (RETURN value from GetProcAddress in kernel32.f90) + INTEGER(IntKi) :: i + + ErrStat = ErrID_None + ErrMsg = '' + + ! Get the procedure addresses: + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + ProcAddr = GetProcAddress( DLL%FileAddr, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + DLL%ProcAddr(i) = TRANSFER(ProcAddr, DLL%ProcAddr(i)) !convert INTEGER(LPVOID) to INTEGER(C_FUNPTR) [used only for compatibility with gfortran] + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) +! This subroutine is used to free a dynamically loaded DLL (loaded in LoadDynamicLib (syssubs::loaddynamiclib)), using operating-system API routines to do so. + + USE IFWINTY, ONLY : BOOL, HANDLE, FALSE !, LPVOID + USE kernel32, ONLY : FreeLibrary + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(HANDLE) :: FileAddr ! The address of file FileName. (RETURN value from LoadLibrary in kernel32.f90) + INTEGER(BOOL) :: Success ! Whether or not the call to FreeLibrary was successful + + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) RETURN + + FileAddr = TRANSFER(DLL%FileAddr, FileAddr) !convert INTEGER(C_INTPTR_T) to INTEGER(HANDLE) [used only for compatibility with gfortran] + + ! Free the DLL: + Success = FreeLibrary( FileAddr ) !If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. + + IF ( Success == FALSE ) THEN !BJJ: note that this is the Windows BOOL type so FALSE isn't the same as the Fortran LOGICAL .FALSE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddr = INT(0,C_INTPTR_T) + END IF + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysIVF_Labview.f90 b/OpenFAST/modules/nwtc-library/src/SysIVF_Labview.f90 new file mode 100644 index 000000000..05dc72ae5 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysIVF_Labview.f90 @@ -0,0 +1,543 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013 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. +! +!********************************************************************************************************************************** +! File last committed: $Date$ +! (File) Revision #: $Rev$ +! URL: $HeadURL$ +!********************************************************************************************************************************** +MODULE SysSubs + + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + + ! SysIVF.f90 is specifically for the Intel Visual Fortran for Windows compiler. + + + ! It contains the following routines: + + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! SUBROUTINE FlushOut ( Unit ) + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_Gamma( x ) ! Returns the gamma value of its argument. + ! per MLB, this can be removed, but only if CU is OUTPUT_UNIT: + ! SUBROUTINE OpenCon ! Actually, it can't be removed until we get Intel's FLUSH working. (mlb) + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + + +!======================================================================= + + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 7 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + + LOGICAL, PARAMETER :: KBInputOK = .FALSE. ! A flag to tell the program that keyboard input is allowed in the environment. + + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Visual Fortran for Windows/LabVIEW' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '\' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '/' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'BINARY' ! The string to specify unformatted I/O files. (used in OpenUOutFile and OpenUInpFile [see TurbSim's .bin files]) + +CONTAINS + +!======================================================================= + FUNCTION FileSize( Unit ) + + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + + !USE IFPORT + + + ! Function declaration. + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + + + ! Local declarations: + + INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. + INTEGER :: Status ! The status returned by + + + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + + RETURN + END FUNCTION FileSize ! ( Unit ) +!======================================================================= + SUBROUTINE FlushOut ( Unit ) + + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + + ! Argument declarations: + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + + + RETURN + END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= + SUBROUTINE Get_CWD ( DirName, Status ) + + + ! This routine retrieves the path of the current working directory. + + + IMPLICIT NONE + + + ! Passed variables. + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + + DirName = '.'//PathSep + Status = 0 + + RETURN + END SUBROUTINE Get_CWD +!======================================================================= + FUNCTION Is_NaN( DblNum ) + + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN in new code, but remains here for + ! backwards compatibility. + + + + ! Argument declarations. + + REAL(DbKi), INTENT(IN) :: DblNum + + + ! Function declaration. + + LOGICAL :: Is_Nan + + + + Is_NaN = 0 + + + RETURN + END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= + FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + + NWTC_ERFR4 = ERF( x ) + + END FUNCTION NWTC_ERFR4 +!======================================================================= + FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + + NWTC_ERFR8 = ERF( x ) + + END FUNCTION NWTC_ERFR8 +!======================================================================= + FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + + NWTC_ERFR16 = ERF( x ) + + END FUNCTION NWTC_ERFR16 +!======================================================================= + FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + + NWTC_GammaR4 = gamma( x ) + + END FUNCTION NWTC_GammaR4 +!======================================================================= + FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + + NWTC_GammaR8 = gamma( x ) + + END FUNCTION NWTC_GammaR8 +!======================================================================= + FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + + NWTC_GammaR16 = gamma( x ) + + END FUNCTION NWTC_GammaR16 +!======================================================================= + SUBROUTINE OpenCon + + + ! This routine opens the console for standard output. + ! MODIFIED for labview: to call write all text to an output file (see SUBROUTINE OpenFOutFile()) + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + + OPEN ( CU , FILE='CONSOLE.TXT' , STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + + + + IF ( IOS /= 0 ) THEN +! CALL WrScr( ' Cannot open CONSOLE.TXT. Another program like MS Excel may have locked it for writing.' ) + CALL ProgExit ( 1 ) + END IF + + + + RETURN + END SUBROUTINE OpenCon +!======================================================================= + SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. +! ACTION='READ' ) ! Use this for UNIX systems. + + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + + RETURN + END SUBROUTINE OpenUnfInpBEFile +!======================================================================= + SUBROUTINE ProgExit ( StatCode ) + + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + + ! Argument declarations. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + + + CALL EXIT ( StatCode ) + + + END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= + SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) F03 has standard intrinsic routines to do this, + ! but older compilers have not implemented it. This code will + ! fail if the compiler checks for floating-point-error, hence + ! the compiler directive FPE_TRAP_ENABLED. + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) + REAL(DbKi) :: Neg_D ! a negative real(DbKi) number + REAL(ReKi) :: Neg ! a negative real(ReKi) number + + + ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. + ! note that anything that refers to NaN or Inf will be incorrect in that case. + +#ifndef FPE_TRAP_ENABLED + ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) + Neg_D = -1.0_DbKi + Neg = -1.0_ReKi + + NaN_D = SQRT ( Neg_D ) + NaN = SQRT ( Neg ) + + ! set variables to zero to calculate Infs (using division by zero) + Neg_D = 0.0_DbKi + Neg = 0.0_ReKi + + Inf_D = 1.0_DbKi / Neg_D + Inf = 1.0_ReKi / Neg +#endif + + END SUBROUTINE Set_IEEE_Constants +!======================================================================= + SUBROUTINE UsrAlarm + + + ! This routine does nothing for the LabVIEW environment. + + + + RETURN + END SUBROUTINE UsrAlarm +!======================================================================= + SUBROUTINE WrNR ( Str ) + + + ! This routine writes out a string to the screen without following it with a new line. + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + + + RETURN + END SUBROUTINE WrNR ! ( Str ) +!======================================================================= + SUBROUTINE WrOver ( Str ) + + + ! This routine writes out a string that overwrites the previous line + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + + +!!mlb Leave this as it was until FLUSH get fixed. +! WRITE (CU,'(''+'',A)') Str + WRITE (CU,'(A)',ADVANCE='NO') CHAR( 13 )//' '//Str + + + + RETURN + END SUBROUTINE WrOver ! ( Str ) +!======================================================================= + SUBROUTINE WriteScr ( Str, Frm ) + + + ! This routine writes out a string to the screen. + + + IMPLICIT NONE + + + ! Argument declarations. + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + + + END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= + +!================================================================================================================================== +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + ! Passed Variables: + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLib: Not implemented for '//TRIM(OS_Desc) + + + + RETURN +END SUBROUTINE LoadDynamicLib +!================================================================================================================================== +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + ! Passed Variables: + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLibProc: Not implemented for '//TRIM(OS_Desc) + + + + RETURN +END SUBROUTINE LoadDynamicLibProc +!================================================================================================================================== +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + ! Passed Variables: + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ErrStat = ErrID_Fatal + ErrMsg = ' FreeDynamicLib: Not implemented for '//TRIM(OS_Desc) + + + RETURN +END SUBROUTINE FreeDynamicLib +!================================================================================================================================== + + +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxGnu.f90 b/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxGnu.f90 new file mode 100644 index 000000000..7c2931c26 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxGnu.f90 @@ -0,0 +1,559 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! This system configuration requires linking with the matlab library, libmex.dll or libmex.dylib or libmex.so, from the matlab + ! installation directory. + ! SysMatlabGnuLinux.f90 is specifically for the GNU Fortran (gfortran) compiler on Linux and macOS. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .FALSE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'GNU Fortran for Linux with Matlab' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '/' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '-' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'UNFORMATTED' ! The string to specify unformatted I/O files. + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + INTEGER(4) :: StatArray(13) ! An array returned by FSTAT that includes the file size. + INTEGER(4) :: Status ! The status returned by + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! Note that IsNaN does not exist in earlier versions of gfortran (e.g., 4.2.1), + ! but does exist in version 4.4. It should be replaced with the standard + ! IEEE_IS_NAN when gfortran implements it. + + REAL(DbKi), INTENT(IN) :: DblNum + LOGICAL :: Is_Nan + + Is_NaN = IsNaN( DblNum ) + + RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +SUBROUTINE FlushOut ( Unit ) + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + ! CALL FLUSH ( Unit ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +!bjj note: this subroutine is not tested for this compiler +SUBROUTINE Get_CWD ( DirName, Status ) + + ! This routine retrieves the path of the current working directory. + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +SUBROUTINE MKDIR ( new_directory_path ) + + ! This routine creates a given directory if it does not exist. + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( file=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir -p '//trim(new_directory_path) + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +SUBROUTINE OpenCon + + ! This routine opens the console for standard output. + +!bjj: Because CU = 6 now, this statement is not necessary +! OPEN ( CU , FILE='/dev/stdout' , STATUS='OLD' ) + +! CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ' ) ! Use this for UNIX systems. + ! ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +SUBROUTINE ProgExit ( StatCode ) + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + ! CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF + +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) F03 has standard intrinsic routines to do this, + ! but Gnu has not yet implemented it. This code will fail if + ! the compiler checks for floating-point-error, hence the + ! compiler directive FPE_TRAP_ENABLED. + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) + REAL(DbKi) :: Neg_D ! a negative real(DbKi) number + REAL(ReKi) :: Neg ! a negative real(ReKi) number + + + ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. + ! note that anything that refers to NaN or Inf will be incorrect in that case. + +#ifndef FPE_TRAP_ENABLED + ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) + Neg_D = -1.0_DbKi + Neg = -1.0_ReKi + + NaN_D = SQRT ( Neg_D ) + NaN = SQRT ( Neg ) + + ! set variables to zero to calculate Infs (using division by zero) + Neg_D = 0.0_DbKi + Neg = 0.0_ReKi + + Inf_D = 1.0_DbKi / Neg_D + Inf = 1.0_ReKi / Neg +#endif + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +SUBROUTINE UsrAlarm + + ! This routine generates an alarm to warn the user that something went wrong. + + CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +SUBROUTINE WrNR ( Str ) + + ! This routine writes out a string to the screen without following it with a new line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + INTEGER :: Stat ! Number of characters printed + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + CHARACTER(1024), SAVE :: Str2 ! bjj: need static variable to print to Matlab command window + + Str2 = ' '//Str + Stat = mexPrintF( Str2 ) + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + CALL WriteScr( Str, '(A)' ) + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + INTEGER :: Stat ! Number of characters printed to the screen + CHARACTER( 1024 ), SAVE :: Str2 ! A temporary string (Str written with the Frm Format specification) (bjj: this apparently needs to be a static variable so it writes to the Matlab command window) + + IF ( LEN_TRIM(Str) < 1 ) THEN + Str2='' + ELSE + WRITE (Str2,Frm, IOSTAT=Stat) ADJUSTL( Str ) + END IF + + Str2 = trim(Str2)//NewLine + Stat = mexPrintF( Str2 ) + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +#ifdef USE_DLL_INTERFACE + +!bjj: these are values I found on the web; I have no idea if they actually work... +!bjj: hopefully we can find them pre-defined in a header somewhere + INTEGER(C_INT), PARAMETER :: RTLD_LAZY=1 ! "Perform lazy binding. Only resolve symbols as the code that references them is executed. If the symbol is never referenced, then it is never resolved. (Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.) " + INTEGER(C_INT), PARAMETER :: RTLD_NOW=2 ! "If this value is specified, or the environment variable LD_BIND_NOW is set to a nonempty string, all undefined symbols in the library are resolved before dlopen() returns. If this cannot be done, an error is returned." + INTEGER(C_INT), PARAMETER :: RTLD_GLOBAL=256 ! "The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries" + INTEGER(C_INT), PARAMETER :: RTLD_LOCAL=0 ! "This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. Symbols defined in this library are not made available to resolve references in subsequently loaded libraries." + + INTERFACE !linux API routines + !bjj see http://linux.die.net/man/3/dlopen + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html + + FUNCTION dlOpen(filename,mode) BIND(C,NAME="dlopen") + ! void *dlopen(const char *filename, int mode); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_PTR) :: dlOpen + CHARACTER(C_CHAR), INTENT(IN) :: filename(*) + INTEGER(C_INT), VALUE :: mode + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + + DLL%FileAddrX = dlOpen( TRIM(DLL%FileName)//C_NULL_CHAR, RTLD_LAZY ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a procedure from a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: i + +#ifdef USE_DLL_INTERFACE + + INTERFACE !linux API routines + + !bjj see http://linux.die.net/man/3/dlsym + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlsym.3.html + + FUNCTION dlSym(handle,name) BIND(C,NAME="dlsym") + ! void *dlsym(void *handle, const char *name); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_FUNPTR) :: dlSym ! A function pointer + TYPE(C_PTR), VALUE :: handle + CHARACTER(C_CHAR), INTENT(IN) :: name(*) + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + DLL%ProcAddr(i) = dlSym( DLL%FileAddrX, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLibProc: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(C_INT) :: Success ! Whether or not the call to dlClose was successful + INTEGER(C_INT), PARAMETER :: TRUE = 0 + +#ifdef USE_DLL_INTERFACE +!bjj: note that this is not tested. + + INTERFACE !linux API routine + !bjj see http://linux.die.net/man/3/dlclose + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlclose.3.html + + FUNCTION dlClose(handle) BIND(C,NAME="dlclose") + ! int dlclose(void *handle); + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(C_INT) :: dlClose + TYPE(C_PTR), VALUE :: handle + END FUNCTION + + END INTERFACE + + ! Close the library: + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) RETURN + Success = dlClose( DLL%FileAddrX ) !The function dlclose() returns 0 on success, and nonzero on error. + + IF ( Success /= TRUE ) THEN !bjj: note that this is not the same as LOGICAL .TRUE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddrX = C_NULL_PTR + END IF + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' FreeDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxIntel.f90 b/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxIntel.f90 new file mode 100644 index 000000000..cb6601281 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysMatlabLinuxIntel.f90 @@ -0,0 +1,551 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2015 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + ! This system configuration requires linking with the matlab library, libmex.dll or libmex.dylib or libmex.so, from the matlab + ! installation directory. + ! SysMatlabLinux.f90 is specifically for the Intel fortran compiler (ifort) on Linux and macOS. + ! It contains the following routines: + ! FUNCTION FileSize( Unit ) ! Returns the size (in bytes) of an open file. + ! FUNCTION Is_NaN( DblNum ) ! Please use IEEE_IS_NAN() instead + ! FUNCTION NWTC_ERF( x ) + ! FUNCTION NWTC_gamma( x ) ! Returns the gamma value of its argument. + ! SUBROUTINE FlushOut ( Unit ) + ! SUBROUTINE GET_CWD( DirName, Status ) + ! SUBROUTINE MKDIR( new_directory_path ) + ! SUBROUTINE OpenCon + ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + ! SUBROUTINE ProgExit ( StatCode ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE UsrAlarm + ! SUBROUTINE WrNR ( Str ) + ! SUBROUTINE WrOver ( Str ) + ! SUBROUTINE WriteScr ( Str, Frm ) + ! SUBROUTINE LoadDynamicLib( DLL, ErrStat, ErrMsg ) + ! SUBROUTINE FreeDynamicLib( DLL, ErrStat, ErrMsg ) + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + LOGICAL, PARAMETER :: KBInputOK = .FALSE. ! A flag to tell the program that keyboard input is allowed in the environment. + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Fortran for Linux with Matlab' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '/' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '-' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'UNFORMATTED' ! The string to specify unformatted I/O files. + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + + USE IFPORT + + INTEGER(B8Ki) :: FileSize ! The size of the file in bytes to be returned. + INTEGER, INTENT(IN) :: Unit ! The I/O unit number of the pre-opened file. + INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. + INTEGER :: Status ! The status returned by + + Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + + IF ( Status /= 0 ) THEN + FileSize = -1 + ELSE + FileSize = StatArray(8) + END IF + + RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= +FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a proper number. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN in new code, but remains here for + ! backwards compatibility. + + USE, INTRINSIC :: ieee_arithmetic + + REAL(DbKi), INTENT(IN) :: DblNum + LOGICAL :: Is_Nan + + Is_NaN = IEEE_IS_NAN( DblNum ) + + RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_ERFR4 ! result + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +FUNCTION NWTC_ERFR8( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! result + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +FUNCTION NWTC_GammaR4( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(SiKi), INTENT(IN) :: x ! input + REAL(SiKi) :: NWTC_GammaR4 ! result + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +FUNCTION NWTC_GammaR8( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +FUNCTION NWTC_GammaR16( x ) + + ! Returns the gamma value of its argument. The result has a value equal + ! to a processor-dependent approximation to the gamma function of x. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +SUBROUTINE FlushOut ( Unit ) + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + + USE IFPORT + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + CALL FLUSH ( INT(Unit, B4Ki) ) + + RETURN +END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= +SUBROUTINE Get_CWD ( DirName, Status ) + + USE IFPORT, ONLY: GETCWD + + IMPLICIT NONE + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + Status = GETCWD ( DirName ) + + RETURN +END SUBROUTINE Get_CWD +!======================================================================= +SUBROUTINE MKDIR ( new_directory_path ) + + ! This routine creates a given directory if it does not exist. + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( directory=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir -p '//trim(new_directory_path) + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +SUBROUTINE OpenCon + + ! This routine opens the console for standard output. + + USE IFPORT + +!bjj: Because CU = 6 now, this statement is not necessary +! OPEN ( CU , FILE='/dev/stdout' , STATUS='UNKNOWN' , CARRIAGECONTROL='FORTRAN', RECL=ConRecL ) + + CALL FlushOut ( CU ) + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + ! This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) + ! Data are stored in RecLen-byte records. + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un ! Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile ! Name of the input file. + INTEGER, INTENT(IN) :: RecLen ! Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error ! Flag to indicate the open failed. + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ACTION='READ' ) ! Use this for UNIX systems. +! ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +SUBROUTINE ProgExit ( StatCode ) + + ! This routine stops the program. If the compiler supports the EXIT routine, + ! pass the program status to it. Otherwise, do a STOP. + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + + ! CALL EXIT ( StatCode ) + + ! IF ( StatCode == 0 ) THEN + ! STOP 0 + ! ELSE + ! IF ( StatCode < 0 ) THEN + ! CALL WrScr( 'Invalid STOP code.' ) + ! END IF + ! STOP 1 + ! END IF + +END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE + ! values for not-a-number and infinity in sindle and double + ! precision) This uses standard F03 intrinsic routines, + ! however Gnu has not yet implemented it, so we've placed this + ! routine in the system-specific code. + + USE, INTRINSIC :: ieee_arithmetic ! use this for compilers that have implemented ieee_arithmetic from F03 standard (otherwise see logic in SysGnu*.f90) + + REAL(DbKi), INTENT(inout) :: Inf_D ! IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision + + REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + + + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) + Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) + + NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) + Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +SUBROUTINE UsrAlarm + + ! This routine generates an alarm to warn the user that something went wrong. + ! This routine does nothing for the MATLAB environment. + + ! CALL WrNR ( CHAR( 7 ) ) + + RETURN +END SUBROUTINE UsrAlarm +!======================================================================= +SUBROUTINE WrNR ( Str ) + + ! This routine writes out a string to the screen without following it with a new line. + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + INTEGER :: Stat ! Number of characters printed + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + CHARACTER(1024), SAVE :: Str2 ! bjj: need static variable to print to Matlab command window + + Str2 = ' '//Str + Stat = mexPrintF( Str2 ) + + RETURN +END SUBROUTINE WrNR ! ( Str ) +!======================================================================= +SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + CALL WriteScr( Str, '(A)' ) + + RETURN +END SUBROUTINE WrOver ! ( Str ) +!======================================================================= +SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + INTEGER :: Stat ! Number of characters printed to the screen + CHARACTER( 1024 ), SAVE :: Str2 ! A temporary string (Str written with the Frm Format specification) (bjj: this apparently needs to be a static variable so it writes to the Matlab command window) + + IF ( LEN_TRIM(Str) < 1 ) THEN + Str2='' + ELSE + WRITE (Str2,Frm, IOSTAT=Stat) ADJUSTL( Str ) + END IF + + Str2 = trim(Str2)//NewLine + Stat = mexPrintF( Str2 ) + +END SUBROUTINE WriteScr ! ( Str ) +!======================================================================= +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +#ifdef USE_DLL_INTERFACE + +!bjj: these are values I found on the web; I have no idea if they actually work... +!bjj: hopefully we can find them pre-defined in a header somewhere + INTEGER(C_INT), PARAMETER :: RTLD_LAZY=1 ! "Perform lazy binding. Only resolve symbols as the code that references them is executed. If the symbol is never referenced, then it is never resolved. (Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.) " + INTEGER(C_INT), PARAMETER :: RTLD_NOW=2 ! "If this value is specified, or the environment variable LD_BIND_NOW is set to a nonempty string, all undefined symbols in the library are resolved before dlopen() returns. If this cannot be done, an error is returned." + INTEGER(C_INT), PARAMETER :: RTLD_GLOBAL=256 ! "The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries" + INTEGER(C_INT), PARAMETER :: RTLD_LOCAL=0 ! "This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. Symbols defined in this library are not made available to resolve references in subsequently loaded libraries." + + INTERFACE !linux API routines + !bjj see http://linux.die.net/man/3/dlopen + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html + + FUNCTION dlOpen(filename,mode) BIND(C,NAME="dlopen") + ! void *dlopen(const char *filename, int mode); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_PTR) :: dlOpen + CHARACTER(C_CHAR), INTENT(IN) :: filename(*) + INTEGER(C_INT), VALUE :: mode + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + + DLL%FileAddrX = dlOpen( TRIM(DLL%FileName)//C_NULL_CHAR, RTLD_LAZY ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to dynamically load a procedure from a DLL. + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: i + +#ifdef USE_DLL_INTERFACE + + INTERFACE !linux API routines + + !bjj see http://linux.die.net/man/3/dlsym + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlsym.3.html + + FUNCTION dlSym(handle,name) BIND(C,NAME="dlsym") + ! void *dlsym(void *handle, const char *name); + USE ISO_C_BINDING + IMPLICIT NONE + TYPE(C_FUNPTR) :: dlSym ! A function pointer + TYPE(C_PTR), VALUE :: handle + CHARACTER(C_CHAR), INTENT(IN) :: name(*) + END FUNCTION + + END INTERFACE + + ErrStat = ErrID_None + ErrMsg = '' + + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + DLL%ProcAddr(i) = dlSym( DLL%FileAddrX, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' LoadDynamicLibProc: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) + + ! This SUBROUTINE is used to free a dynamically loaded DLL (loaded in LoadDynamicLib). + + TYPE (DLL_Type), INTENT(INOUT) :: DLL ! The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(C_INT) :: Success ! Whether or not the call to dlClose was successful + INTEGER(C_INT), PARAMETER :: TRUE = 0 + +#ifdef USE_DLL_INTERFACE +!bjj: note that this is not tested. + + INTERFACE !linux API routine + !bjj see http://linux.die.net/man/3/dlclose + ! and https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlclose.3.html + + FUNCTION dlClose(handle) BIND(C,NAME="dlclose") + ! int dlclose(void *handle); + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(C_INT) :: dlClose + TYPE(C_PTR), VALUE :: handle + END FUNCTION + + END INTERFACE + + ! Close the library: + + IF( .NOT. C_ASSOCIATED(DLL%FileAddrX) ) RETURN + Success = dlClose( DLL%FileAddrX ) !The function dlclose() returns 0 on success, and nonzero on error. + + IF ( Success /= TRUE ) THEN !bjj: note that this is not the same as LOGICAL .TRUE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddrX = C_NULL_PTR + END IF + +#else + + ErrStat = ErrID_Fatal + ErrMsg = ' FreeDynamicLib: Not compiled with -DUSE_DLL_INTERFACE for '//TRIM(OS_Desc) + +#endif + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/SysMatlabWindows.f90 b/OpenFAST/modules/nwtc-library/src/SysMatlabWindows.f90 new file mode 100644 index 000000000..ced8ee971 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/SysMatlabWindows.f90 @@ -0,0 +1,518 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 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 SysSubs + + ! This module contains routines with system-specific logic and references, including all references to the console unit, CU. + ! It also contains standard (but not system-specific) routines it uses. + + ! bjj: if compiling this to write to the Matlab command window using mexPrintf, you must link with + ! libmex.lib in the matlab/extern/lib/{architecture}/{compiler} folder + ! otherwise, use preprocessor definition CONSOLE_FILE to output everything to a file named CONSOLE.TXT + + + + + + USE NWTC_Base + + IMPLICIT NONE + + INTERFACE NWTC_ERF ! Returns the ERF value of its argument + MODULE PROCEDURE NWTC_ERFR4 + MODULE PROCEDURE NWTC_ERFR8 + MODULE PROCEDURE NWTC_ERFR16 + END INTERFACE + + INTERFACE NWTC_gamma ! Returns the gamma value of its argument + ! note: gamma is part of the F08 standard, but may not be implemented everywhere... + MODULE PROCEDURE NWTC_gammaR4 + MODULE PROCEDURE NWTC_gammaR8 + MODULE PROCEDURE NWTC_gammaR16 + END INTERFACE + +!======================================================================= + + + INTEGER, PARAMETER :: ConRecL = 120 ! The record length for console output. + INTEGER, PARAMETER :: CU = 6 ! The I/O unit for the console. Unit 6 causes ADAMS to crash. + INTEGER, PARAMETER :: MaxWrScrLen = 98 ! The maximum number of characters allowed to be written to a line in WrScr + + LOGICAL, PARAMETER :: KBInputOK = .FALSE. ! A flag to tell the program that keyboard input is allowed in the environment. + + CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}] + CHARACTER(*), PARAMETER :: OS_Desc = 'Intel Visual Fortran for Windows/Matlab' ! Description of the language/OS + CHARACTER( 1), PARAMETER :: PathSep = '\' ! The path separator. + CHARACTER( 1), PARAMETER :: SwChar = '/' ! The switch character for command-line options. + CHARACTER(11), PARAMETER :: UnfForm = 'BINARY' ! The string to specify unformatted I/O files. (used in OpenUOutFile and OpenUInpFile [see TurbSim's .bin files]) + +CONTAINS + +!======================================================================= +FUNCTION FileSize( Unit ) + ! This function calls the portability routine, FSTAT, to obtain the file size + ! in bytes corresponding to a file unit number or returns -1 on error. + +USE IFPORT + +INTEGER(B8Ki) :: FileSize !< The size of the file in bytes to be returned. +INTEGER, INTENT(IN) :: Unit !< The I/O unit number of the pre-opened file. +INTEGER :: StatArray(12) ! An array returned by FSTAT that includes the file size. +INTEGER :: Status ! The status returned by + +Status = FSTAT( INT( Unit, B4Ki ), StatArray ) + +IF ( Status /= 0 ) THEN + FileSize = -1 +ELSE + FileSize = StatArray(8) +END IF + +RETURN +END FUNCTION FileSize ! ( Unit ) +!======================================================================= + SUBROUTINE FlushOut ( Unit ) + + + ! This subroutine flushes the buffer on the specified Unit. + ! It is especially useful when printing "running..." type messages. + +#ifndef CONSOLE_FILE + USE IFPORT, ONLY: FLUSH +#endif + + ! Argument declarations: + + INTEGER, INTENT(IN) :: Unit ! The unit number of the file being flushed. + + +#ifndef CONSOLE_FILE + CALL FLUSH ( INT(Unit, B4Ki) ) +#endif + + RETURN + END SUBROUTINE FlushOut ! ( Unit ) +!======================================================================= + SUBROUTINE Get_CWD ( DirName, Status ) + + + ! This routine retrieves the path of the current working directory. + + + USE IFPORT, ONLY: GETCWD + + IMPLICIT NONE + + + ! Passed variables. + + CHARACTER(*), INTENT(OUT) :: DirName ! A CHARACTER string containing the path of the current working directory. + INTEGER, INTENT(OUT) :: Status ! Status returned by the call to a portability routine. + + + Status = GETCWD ( DirName ) + + RETURN + END SUBROUTINE Get_CWD +!======================================================================= + FUNCTION Is_NaN( DblNum ) + + ! This routine determines if a REAL(DbKi) variable holds a NaN (not-a-number) value. + ! BJJ: this routine is used in CRUNCH. + ! It should be replaced with IEEE_IS_NAN, but remains here for + ! backwards compatibility (some older compilers aren't yet current). + +USE, INTRINSIC :: ieee_arithmetic + +REAL(DbKi), INTENT(IN) :: DblNum !< scalar value in question +LOGICAL :: Is_Nan + +Is_NaN = IEEE_IS_NAN( DblNum ) + +RETURN +END FUNCTION Is_NaN ! ( DblNum ) +!======================================================================= +!> This function returns the ERF value of its argument. The result has a value equal +!! to the Gauss error function: +!! \f{equation}{ +!! \mathrm{erf}(x)=\frac{2}{\sqrt{\pi}}\int_0^x e^{-t^2}\,dt +!! \f} \n +!! Use NWTC_ERF (syssubs::nwtc_erf) instead of directly calling a specific routine in the generic interface. +FUNCTION NWTC_ERFR4( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(SiKi), INTENT(IN) :: x !< input + REAL(SiKi) :: NWTC_ERFR4 !< \f$\mathrm{erf}(x)\f$ + + NWTC_ERFR4 = ERF( x ) + +END FUNCTION NWTC_ERFR4 +!======================================================================= +!> \copydoc syssubs::nwtc_erfr4 +FUNCTION NWTC_ERFR8( x ) + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_ERFR8 ! this function + + NWTC_ERFR8 = ERF( x ) + +END FUNCTION NWTC_ERFR8 +!======================================================================= +!> \copydoc syssubs::nwtc_erfr4 +FUNCTION NWTC_ERFR16( x ) + + ! Returns the ERF value of its argument. The result has a value equal + ! to the error function: 2/pi * integral_from_0_to_x of e^(-t^2) dt. + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_ERFR16 ! result + + NWTC_ERFR16 = ERF( x ) + +END FUNCTION NWTC_ERFR16 +!======================================================================= +!> Returns the gamma value of its argument. The result has a value equal +!! to a processor-dependent approximation to the gamma function of x: +!! \f{equation}{ +!! \mathrm{ \Gamma }(x) = \int_0^\infty t^{x-1}e^{-t}\,dt +!! \f} \n +!! Use NWTC_Gamma (syssubs::nwtc_gamma) instead of directly calling a specific routine in the generic interface. +FUNCTION NWTC_GammaR4( x ) + +! \mathrm{ \Gamma }(x) = \int_0^\infinity t^{x-1}e^{-t}\,dt + + REAL(SiKi), INTENT(IN) :: x !< input + REAL(SiKi) :: NWTC_GammaR4 !< \f$\mathrm{\Gamma}(x)\f$ + + NWTC_GammaR4 = gamma( x ) + +END FUNCTION NWTC_GammaR4 +!======================================================================= +!> \copydoc syssubs::nwtc_gammar4 +FUNCTION NWTC_GammaR8( x ) + + REAL(R8Ki), INTENT(IN) :: x ! input + REAL(R8Ki) :: NWTC_GammaR8 ! result + + NWTC_GammaR8 = gamma( x ) + +END FUNCTION NWTC_GammaR8 +!======================================================================= +!> \copydoc syssubs::nwtc_gammar4 +FUNCTION NWTC_GammaR16( x ) + + REAL(QuKi), INTENT(IN) :: x ! input + REAL(QuKi) :: NWTC_GammaR16 ! result + + NWTC_GammaR16 = gamma( x ) + +END FUNCTION NWTC_GammaR16 +!======================================================================= +!> This routine creates a given directory if it does not already exist. +SUBROUTINE MKDIR ( new_directory_path ) + + implicit none + + character(*), intent(in) :: new_directory_path + character(1024) :: make_command + logical :: directory_exists + + ! Check if the directory exists first + inquire( directory=trim(new_directory_path), exist=directory_exists ) + + if ( .NOT. directory_exists ) then + make_command = 'mkdir "'//trim(new_directory_path)//'"' + call system( make_command ) + endif + +END SUBROUTINE MKDIR +!======================================================================= +!> This routine opens the console for standard output. +SUBROUTINE OpenCon() + + +#ifdef CONSOLE_FILE + ! MODIFIED to write all text to an output file (see SUBROUTINE OpenFOutFile()) + + + ! Local declarations. + + INTEGER :: IOS ! I/O status of OPEN. + + + OPEN ( CU , FILE='CONSOLE.TXT' , STATUS='UNKNOWN', FORM='FORMATTED', IOSTAT=IOS, ACTION="WRITE" ) + + IF ( IOS /= 0 ) THEN +! CALL WrScr( ' Cannot open CONSOLE.TXT. Another program like MS Excel may have locked it for writing.' ) + CALL ProgExit ( 1 ) + END IF + +#endif + + RETURN +END SUBROUTINE OpenCon +!======================================================================= +!> This routine opens a binary input file with data stored in Big Endian format (created on a UNIX machine.) +!! Data are stored in RecLen-byte records. (This routine is used for +SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) + + IMPLICIT NONE + + INTEGER, INTENT(IN) :: Un !< Logical unit for the input file. + CHARACTER(*), INTENT(IN) :: InFile !< Name of the input file. + INTEGER, INTENT(IN) :: RecLen !< Size of records in the input file, in bytes. + LOGICAL, INTENT(OUT) :: Error !< Flag to indicate the open failed (true indicates an error occurred). + INTEGER :: IOS ! I/O status of OPEN. + + ! Open input file. Make sure it worked. + + ! The non-standard CONVERT keyword allows us to read UNIX binary files, whose bytes are in reverse order (i.e., stored in BIG ENDIAN format). + ! NOTE: using RecLen in bytes requires using the /assume:byterecl compiler option! + OPEN ( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='DIRECT', RECL=RecLen, IOSTAT=IOS, & + ! ACTION='READ' ) ! Use this for UNIX systems. + ACTION='READ', CONVERT='BIG_ENDIAN' ) ! Use this for PC systems. + + IF ( IOS /= 0 ) THEN + Error = .TRUE. + ELSE + Error = .FALSE. + END IF + + RETURN +END SUBROUTINE OpenUnfInpBEFile +!======================================================================= +!> This routine stops the program immediately. If the compiler supports the EXIT routine, +!! pass the program status to it. Otherwise, do a STOP. +SUBROUTINE ProgExit ( StatCode ) + + INTEGER, INTENT(IN) :: StatCode ! The status code to pass to the OS. + +#ifdef CONSOLE_FILE + CLOSE ( CU ) +#endif + + END SUBROUTINE ProgExit ! ( StatCode ) +!======================================================================= +!> This routine sets the values of NaN_D, Inf_D, NaN, Inf (IEEE +!! values for not-a-number and infinity in sindle and double +!! precision) This uses standard F03 intrinsic routines, +!! however Gnu has not yet implemented it, so we've placed this +!! routine in the system-specific code. +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + + USE, INTRINSIC :: ieee_arithmetic ! use this for compilers that have implemented ieee_arithmetic from F03 standard (otherwise see logic in SysGnu*.f90) + + REAL(DbKi), INTENT(inout) :: Inf_D !< IEEE value for NaN (not-a-number) in double precision + REAL(DbKi), INTENT(inout) :: NaN_D !< IEEE value for Inf (infinity) in double precision + + REAL(ReKi), INTENT(inout) :: Inf !< IEEE value for NaN (not-a-number) + REAL(ReKi), INTENT(inout) :: NaN !< IEEE value for Inf (infinity) + + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) + Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) + + NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) + Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + +END SUBROUTINE Set_IEEE_Constants +!======================================================================= +!> This routine generates an alarm to warn the user that something went wrong. +SUBROUTINE UsrAlarm() + + + ! This routine does nothing for the MATLAB environment. + + + RETURN + END SUBROUTINE UsrAlarm +!======================================================================= +!> This routine writes out a string to the screen without following it with a new line. + SUBROUTINE WrNR ( Str ) + + CHARACTER(*), INTENT(IN) :: Str !< The string to write to the screen. + +#ifdef CONSOLE_FILE + + WRITE (CU,'(1X,A)',ADVANCE='NO') Str + +#else + INTEGER :: Stat ! Number of characters printed + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + CHARACTER(1024),SAVE :: Str2 ! bjj: need static variable to print to Matlab command window + + Str2 = ' '//Str//C_NULL_CHAR !bjj: not sure C_NULL_CHAR is necessary + Stat = mexPrintF( Str2 ) + +#endif + + RETURN + END SUBROUTINE WrNR ! ( Str ) +!======================================================================= + SUBROUTINE WrOver ( Str ) + + ! This routine writes out a string that overwrites the previous line + + CHARACTER(*), INTENT(IN) :: Str ! The string to write to the screen. + + CALL WriteScr( Str, '(A)' ) + + RETURN + END SUBROUTINE WrOver ! ( Str ) +!======================================================================= + SUBROUTINE WriteScr ( Str, Frm ) + + ! This routine writes out a string to the screen. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: Str ! The input string to write to the screen. + CHARACTER(*), INTENT(IN) :: Frm ! Format specifier for the output. + +#ifdef CONSOLE_FILE + + INTEGER :: ErrStat ! Error status of write operation (so code doesn't crash) + + + IF ( LEN_TRIM(Str) < 1 ) THEN + WRITE ( CU, '()', IOSTAT=ErrStat ) + ELSE + WRITE ( CU, Frm, IOSTAT=ErrStat ) TRIM(Str) + END IF + +#else + + INTEGER, EXTERNAL :: mexPrintF ! Matlab function to print to the command window + INTEGER :: Stat ! Number of characters printed to the screen + CHARACTER( 1024 ), SAVE :: Str2 ! A temporary string (Str written with the Frm Format specification) (bjj: this apparently needs to be a static variable so it writes to the Matlab command window) + + IF ( LEN_TRIM(Str) < 1 ) THEN + Str2='' + ELSE + WRITE (Str2,Frm, IOSTAT=Stat) ADJUSTL( Str ) + END IF + Str2 = trim(Str2)//NewLine//C_NULL_CHAR !bjj: not sure C_NULL_CHAR is necessary + Stat = mexPrintf( Str2 ) + !call mexEvalString("drawnow;"); ! !bjj: may have to call this to dump string to the screen immediately. + +#endif + + END SUBROUTINE WriteScr ! ( Str ) + +!======================================================================= +!> This subroutine is used to dynamically load a DLL, using operating-system API routines to do so. +SUBROUTINE LoadDynamicLib ( DLL, ErrStat, ErrMsg ) + + USE IFWINTY, ONLY : HANDLE + USE kernel32, ONLY : LoadLibrary + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(HANDLE) :: FileAddr ! The address of file FileName. (RETURN value from LoadLibrary in kernel32.f90) + + ErrStat = ErrID_None + ErrMsg = '' + + ! Load the DLL and get the file address: + FileAddr = LoadLibrary( TRIM(DLL%FileName)//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + DLL%FileAddr = TRANSFER(FileAddr, DLL%FileAddr) !convert INTEGER(HANDLE) to INTEGER(C_INTPTR_T) [used only for compatibility with gfortran] + + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) THEN + ErrStat = ErrID_Fatal + WRITE(ErrMsg,'(I2)') BITS_IN_ADDR + ErrMsg = 'The dynamic library '//TRIM(DLL%FileName)//' could not be loaded. Check that the file '// & + 'exists in the specified location and that it is compiled for '//TRIM(ErrMsg)//'-bit applications.' + RETURN + END IF + + ! Get the procedure address: + CALL LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + RETURN +END SUBROUTINE LoadDynamicLib +!======================================================================= +SUBROUTINE LoadDynamicLibProc ( DLL, ErrStat, ErrMsg ) + + ! This subroutine is used to dynamically load a procedure in a DLL, using operating-system API routines to do so. + + USE IFWINTY, ONLY : LPVOID + USE kernel32, ONLY : GetProcAddress + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be loaded. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(LPVOID) :: ProcAddr ! The address of procedure ProcName. (RETURN value from GetProcAddress in kernel32.f90) + INTEGER(IntKi) :: i + + ErrStat = ErrID_None + ErrMsg = '' + + ! Get the procedure addresses: + do i=1,NWTC_MAX_DLL_PROC + if ( len_trim( DLL%ProcName(i) ) > 0 ) then + + ProcAddr = GetProcAddress( DLL%FileAddr, TRIM(DLL%ProcName(i))//C_NULL_CHAR ) !the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + DLL%ProcAddr(i) = TRANSFER(ProcAddr, DLL%ProcAddr(i)) !convert INTEGER(LPVOID) to INTEGER(C_FUNPTR) [used only for compatibility with gfortran] + + IF(.NOT. C_ASSOCIATED(DLL%ProcAddr(i))) THEN + ErrStat = ErrID_Fatal + i - 1 + ErrMsg = 'The procedure '//TRIM(DLL%ProcName(i))//' in file '//TRIM(DLL%FileName)//' could not be loaded.' + RETURN + END IF + + end if + end do + + RETURN +END SUBROUTINE LoadDynamicLibProc +!======================================================================= +SUBROUTINE FreeDynamicLib ( DLL, ErrStat, ErrMsg ) +! This subroutine is used to free a dynamically loaded DLL (loaded in LoadDynamicLib (syssubs::loaddynamiclib)), using operating-system API routines to do so. + + USE IFWINTY, ONLY : BOOL, HANDLE, FALSE !, LPVOID + USE kernel32, ONLY : FreeLibrary + + TYPE (DLL_Type), INTENT(INOUT) :: DLL !< The DLL to be freed. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(HANDLE) :: FileAddr ! The address of file FileName. (RETURN value from LoadLibrary in kernel32.f90) + INTEGER(BOOL) :: Success ! Whether or not the call to FreeLibrary was successful + + IF ( DLL%FileAddr == INT(0,C_INTPTR_T) ) RETURN + + FileAddr = TRANSFER(DLL%FileAddr, FileAddr) !convert INTEGER(C_INTPTR_T) to INTEGER(HANDLE) [used only for compatibility with gfortran] + + ! Free the DLL: + Success = FreeLibrary( FileAddr ) !If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. + + IF ( Success == FALSE ) THEN !BJJ: note that this is the Windows BOOL type so FALSE isn't the same as the Fortran LOGICAL .FALSE. + ErrStat = ErrID_Fatal + ErrMsg = 'The dynamic library could not be freed.' + RETURN + ELSE + ErrStat = ErrID_None + ErrMsg = '' + DLL%FileAddr = INT(0,C_INTPTR_T) + END IF + + RETURN +END SUBROUTINE FreeDynamicLib +!======================================================================= +END MODULE SysSubs diff --git a/OpenFAST/modules/nwtc-library/src/ranlux/RANLUX.f90 b/OpenFAST/modules/nwtc-library/src/ranlux/RANLUX.f90 new file mode 100644 index 000000000..a9ae2063f --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/ranlux/RANLUX.f90 @@ -0,0 +1,379 @@ +! Borrowed from the v1.50 distribution of Turbsim + Module Ran_Lux_Mod +! Subtract-and-borrow random number generator proposed by Marsaglia and Zaman, implemented by F. James with the name RCARRY in 1991, +! and later improved by Martin Luescher in 1993 to produce "Luxury Pseudorandom Numbers". Fortran 77 coded by F. James, 1993. +! Converted to Fortran 90 [and Lahey Elf90 subset] by Loren Meissner, 1995. +! +! References: M. Luscher, Computer Physics Communications 79 (1994) 100; F. James, Computer Physics Communications 79 (1994) 111 +! +! LUXURY LEVELS. -- The available luxury levels are: +! level 0 (p = 24) : equivalent to the original RCARRY of Marsaglia and Zaman, very long period, but fails many tests. +! level 1 (p = 48) : considerable improvement in quality over level 0, now passes the gap test, but still fails spectral test. +! level 2 (p = 97) : passes all known tests, but theoretically still defective. +! level 3 (p = 223) : DEFAULT VALUE. Any theoretically possible correlations have very small chance of being observed. +! level 4 (p = 389) : highest possible luxury, all 24 bits chaotic. +! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +! Calling sequences for RanLux: +! call RanLux (RVec) +! Returns a vector RVec of Len(RVec) 32-bit random floating point numbers X, such that 0.0 < X < 1.0 . +! call RLuxGo (Lux, Int, K1, K2) +! Initializes the generator from one 32-bit integer INT and sets Luxury Level LUX which is integer between zero and MaxLev, or +! if Lux > 24, it sets p = Lux directly. K1 and K2 should be set to zero unless restarting at a break point given by output of +! RLuxAt (see RLuxAt). +! call RLuxAt (Lux, Int, K1, K2) +! Gets the values of four integers which can be used to restart the RanLux generator at the current point by calling RLuxGo. +! K1 and K2 specify how many numbers were generated since the initialization with Lux and Int. The restarting skips over +! K1 + K2 * 1E9 numbers, so it can be long. A more efficient but less convenient way of restarting is by: +! call RLuxIn (ISVec) ! Restart the generator from vector ISVec of 25 32-bit integers (see RLXUt) +! call RLuxUt (ISVec) ! Output the current values of the 25 32-bit integer Seeds, to be used for restarting. +! The array argument to RLuxIn or RLuxUt must be dimensioned 25 in the calling program +! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +! default +! Luxury Level 0 1 2 * 3 * 4 +! 0 24 73 199 365 +! corresponds to p = 24 48 97 223 389 +! time factor 1 2 3 6 10 on slow workstation +! 1 1.5 2 3 5 on fast mainframe +! +! NotYet is .TRUE. if no initialization has been performed yet. +!Start bjj: We want to write to the screen instead of "print *" +! use NWTC_IO +!End bjj: + use precision + implicit none + + integer, parameter :: NSeeds = 25, MaxLev = 4, LxDflt = 3 + real(ReKi), parameter :: TwoP12 = 4096.0 + integer, parameter :: IGiga = 1000000000, JSDFlt = 314159265, ITwo24 = 2 ** 24, ICons = 2147483563 + integer :: I_ranLux + integer, parameter :: Next(NSeeds - 1) = (/ NSeeds - 1, (I_ranLux, I_ranLux = 1, NSeeds - 2) /) ! Table look-up (faster than Mod function). + + integer :: I24 = 24, J24 = 10, In24 = 0, Kount = 0, LuxLev = LxDflt, MKount = 0 ! Initialized variables are automatically saved. + integer, dimension(0: MaxLev) :: NDSkip = (/ 0, 24, 73, 199, 365 /) ! Initialized variables are automatically saved. + integer, save :: NSkip, InSeed + real(ReKi) :: Carry = 0.0 ! Initialized variables are automatically saved. + real(ReKi), save :: Seeds(NSeeds - 1), TwoM24, TwoM12 + logical, save :: NotYet = .TRUE. + + real(ReKi) :: Uni + +!bjj + character(300) :: RanLux_str +!bjj + + private :: RCarry + +contains +!============================================================================ + subroutine RanLux (RVec) + ! Default Initialization by Multiplicative Congruential + real(ReKi), intent(out) :: RVec(:) + integer :: ISeeds(NSeeds - 1), I, IVec, JSeed, K, LEnv, LP + + real(ReKi) :: tmpTwoM24, tmpTwoM24Seed + +! start subroutine RanLux + LEnv = Size (RVec) + if (NotYet) then + NotYet = .FALSE. + JSeed = JSDFlt + InSeed = JSeed +!begin bjj +! print *, " RanLux default initialization: ", JSeed +! write( RanLux_str, '(I12)' ) JSeed +! CALL WrScr( " RanLux default initialization: "//TRIM( ADJUSTL( RanLux_str ) ) ) +!end bjj + LuxLev = LxDflt + NSkip = NDSkip(LuxLev) + LP = NSkip + NSeeds - 1 + In24 = 0 + Kount = 0 + MKount = 0 +!begin bjj +! print *, " RanLux default luxury level = ", LuxLev, " p = ", LP +! write( RanLux_str, '(A,I5,A,I12)' ) " RanLux default luxury level = ", LuxLev, " p = ", LP +! CALL WrScr( TRIM( RanLux_str ) ) +!end bjj + + TwoM24 = 1.0 + do I = 1, NSeeds - 1 + TwoM24 = TwoM24 * 0.5 + K = JSeed / 53668 + JSeed = 40014 * (JSeed - K * 53668) - K * 12211 + if (JSeed < 0) JSeed = JSeed + ICons + ISeeds(I) = Mod (JSeed, ITwo24) + end do + TwoM12 = TwoM24 * 4096.0 + Seeds = Real (ISeeds) * TwoM24 + I24 = NSeeds - 1 + J24 = 10 + Carry = Merge (TwoM24, 0.0_ReKi, Seeds(NSeeds - 1) == 0.0) + end if + + !bjj added to speed up later calculations (b/c I had to fix the "where" statement) + tmpTwoM24Seed = TwoM24 * Seeds(J24) + tmpTwoM24 = TwoM24 * TwoM24 + !bjj end of modifications + + do IVec = 1, LEnv + RVec(IVec) = RCarry (1) + ! Skipping to Luxury. As proposed by Martin Luscher. + In24 = In24 + 1 + if (In24 == NSeeds - 1) then + In24 = 0 + Kount = Kount + NSkip + Uni = RCarry (NSkip) + end if + + !bjj modified code to eliminate code crashing on "where" statement for large arrays + ! "Pad" small numbers (with less than 12 "significant" bits) and eliminate zero values (in case someone takes a logarithm) + if ( RVec(IVec) < TwoM12 ) RVec(IVec) = RVec(IVec) + tmpTwoM24Seed + if ( Rvec(IVec) == 0.0 ) RVec(IVec) = tmpTwoM24 + !bjj end of modifications + + end do + !bjj removed to eliminate crashing in SNwind + ! "Pad" small numbers (with less than 12 "significant" bits) and eliminate zero values (in case someone takes a logarithm) + !where (RVec < TwoM12) RVec = RVec + TwoM24 * Seeds(J24) + !where (Rvec == 0.0) RVec = TwoM24 * TwoM24 + !bjj end of modifications + + Kount = Kount + LEnv + if (Kount >= IGiga) then + MKount = MKount + 1 + Kount = Kount - IGiga + end if + return + end subroutine RanLux +!============================================================================ +! Input and float integer Seeds from previous run + subroutine RLuxIn (ISDext) + integer, intent(in) :: ISDext(:) + integer :: I, ISD +! start subroutine RLuxIn + if (Size(ISDext) /= NSeeds) then +!begin bjj +! print *, " Array size for RLuxIn must be ", NSeeds +! write( RanLux_str, '(I5)' ) NSeeds +! CALL WrScr( " Array size for RLuxIn must be "//TRIM( ADJUSTL(RanLux_str) ) ) +!end bjj + + return + end if + ! The following IF block added by Phillip Helbig, based on conversation with Fred James; + ! an equivalent correction has been published by James. + if (NotYet) then +!begin bjj +! print *, " Proper results only with initialisation from 25 integers obtained with RLuxUt" +! CALL WrScr( " Proper results only with initialisation from 25 integers obtained with RLuxUt" ) +!end bjj + NotYet = .FALSE. + end if + TwoM24 = 1.0 + do I = 1, NSeeds - 1 + TwoM24 = TwoM24 * 0.5 + end do + TwoM12 = TwoM24 * 4096.0 +!Start bjj +! print *, " Full initialization of RanLux with 25 integers:" +! print *, ISDext +! CALL WrScr ( " Full initialization of RanLux with 25 integers:" ) +! write( RanLux_str, '(25(I11,1x))' ) ISDext +! CALL WrScr ( TRIM( RanLux_str ) ) +!End bjj + Seeds = Real (ISDext(: NSeeds - 1)) * TwoM24 + Carry = 0.0 + if (ISDext(NSeeds) < 0) Carry = TwoM24 + ISD = Abs (ISDext(NSeeds)) + I24 = Mod (ISD, 100) + ISD = ISD / 100 + J24 = Mod (ISD, 100) + ISD = ISD / 100 + In24 = Mod (ISD, 100) + ISD = ISD / 100 + LuxLev = ISD + +!start bjj + write( RanLux_str, "(I5)" ) LuxLev +!end bjj + + if (LuxLev <= MaxLev) then + NSkip = NDSkip(LuxLev) +!start bjj +! print *, " RanLux luxury level set by RLuxIn to: ", LuxLev\ +! CALL WrScr( " RanLux luxury level set by RLuxIn to: "//TRIM(ADJUSTL(RanLux_str) )) +!end bjj + else if (LuxLev >= NSeeds - 1) then + NSkip = LuxLev - NSeeds + 1 +!start bjj +! print *, " RanLux p-value set by RLuxIn to:", LuxLev +! CALL WrScr( " RanLux p-value set by RLuxIn to: "//TRIM(ADJUSTL(RanLux_str) )) +!end bjj + else + NSkip = NDSkip(MaxLev) +!start bjj +! print *, " RanLux illegal luxury RLuxIn: ", LuxLev +! CALL WrScr( " RanLux illegal luxury RLuxIn: "//TRIM(ADJUSTL(RanLux_str) )) +!end bjj + LuxLev = MaxLev + end if + InSeed = - 1 + return + end subroutine RLuxIn +!============================================================================ +! Ouput Seeds as integers + subroutine RLuxUt (ISDext) + integer, intent(out) :: ISDext(:) +! start subroutine RLuxUt + if (Size(ISDext) /= NSeeds) then + ISDext = 0 +!start bjj +! print *, " Array size for RLuxUt must be ", NSeeds +! write( RanLux_str, '(I20)' ) NSeeds +! CALL WrScr( " Array size for RLuxUt must be "//TRIM( ADJUSTL(RanLux_str ))) +!end bjj + return + end if + ISDext(: NSeeds - 1) = Int (Seeds * TwoP12 * TwoP12) + ISDext(NSeeds) = Merge (-ISDext(NSeeds), I24 + 100 * J24 + 10000 * In24 + 1000000 * LuxLev, Carry > 0.0) + return + end subroutine RLuxUt +!============================================================================ +! Output the "convenient" restart point + subroutine RLuxAt (LOut, InOut, K1, K2) + integer, intent(out) :: LOut, InOut, K1, K2 +! start subroutine RLuxAt + LOut = LuxLev + InOut = InSeed + K1 = Kount + K2 = MKount + return + end subroutine RLuxAt +!============================================================================ +! Initialize from one or three integers + subroutine RLuxGo (Lux, Int, K1, K2) + integer, intent(in) :: Lux, Int, K1, K2 + integer :: ISeeds(NSeeds - 1), ILx, I, IOuter, IZip, IZip2, JSeed, K +! start subroutine RLuxGo + if (Lux < 0) then + LuxLev = LxDflt + else if (Lux <= MaxLev) then + LuxLev = Lux + else if (Lux < NSeeds - 1 .or. Lux > 2000) then + LuxLev = MaxLev +!start bjj +! print *, " RanLux illegal luxury level in RLuxGo: ", Lux +! write( RanLux_str, '(I20)' ) Lux +! Call WrScr( " RanLux illegal luxury level in RLuxGo: "//TRIM( ADJUSTL(RanLux_str ) )) +!end bjj + else + LuxLev = Lux + do ILx = 0, MaxLev + if (Lux == NDSkip(ILx) + NSeeds - 1) then + LuxLev = ILx + end if + end do + end if + if (LuxLev <= MaxLev) then + NSkip = NDSkip(LuxLev) +!start bjj +! print *, " RanLux luxury level set by RLuxGo :", LuxLev, " p = ", NSkip + NSeeds - 1 +! write (RanLux_str, '(A,I5)') " RanLux luxury level set by RLuxGo :", LuxLev +! write (RanLux_str, '(A,I12)') TRIM(RanLux_str)//" p = ", NSkip + NSeeds - 1 +! CALL WrScr( TRIM(RanLux_str) ) +!end bjj + else + NSkip = LuxLev - 24 +!start bjj +! print *, " RanLux p-value set by RLuxGo to:", LuxLev +! write( RanLux_str, '(I20)' ) LuxLev +! CALL WrScr( " RanLux p-value set by RLuxGo to: "//TRIM( ADJUSTL(RanLux_str ) )) +!end bjj + end if + In24 = 0 + if (Int < 0) then +!start bjj +! print *, " Illegal initialization by RLuxGo, negative input seed" +! CALL WrScr( " Illegal initialization by RLuxGo, negative input seed" ) +!end bjj + else if (Int > 0) then + JSeed = Int +!start bjj +! print *, " RanLux initialized by RLuxGo from Seeds", JSeed, K1, K2 +! write( RanLux_str, '(3(I12))' ) JSeed, K1, K2 +! CALL WrScr( " RanLux initialized by RLuxGo from Seeds"//TRIM( RanLux_str ) ) +!end bjj + else + JSeed = JSDFlt +!start bjj +! print *, " RanLux initialized by RLuxGo from default seed" +! CALL WrScr( " RanLux initialized by RLuxGo from default seed" ) +!end bjj + end if + InSeed = JSeed + NotYet = .FALSE. + TwoM24 = 1.0 + do I = 1, NSeeds - 1 + TwoM24 = TwoM24 * 0.5 + K = JSeed / 53668 + JSeed = 40014 * (JSeed - K * 53668) - K * 12211 + if (JSeed < 0) JSeed = JSeed + ICons + ISeeds(I) = Mod (JSeed, ITwo24) + end do + TwoM12 = TwoM24 * 4096.0 + Seeds = Real (ISeeds) * TwoM24 + I24 = NSeeds - 1 + J24 = 10 + Carry = Merge (TwoM24, 0.0_ReKi, Seeds(NSeeds - 1) == 0.0) + + ! If restarting at a break point, skip K1 + IGIGA * K2 + ! Note that this is the number of numbers delivered to the user PLUS the number skipped (if Luxury > 0) . + Kount = Abs (K1) + MKount = Abs (K2) + if (Kount + MKount /= 0) then + do IOuter = 1, MKount + 1 + Uni = RCarry (Merge (Kount, IGiga, IOuter == MKount + 1)) + end do + ! Get the right value of IN24 by direct calculation + In24 = Mod (Kount, NSkip + NSeeds - 1) + if (MKount > 0) then + IZip = Mod (IGiga, NSkip + NSeeds - 1) + IZip2 = MKount * IZip + In24 + In24 = Mod (IZip2, NSkip + NSeeds - 1) + end if + ! Now IN24 had better be between zero and 23 inclusive + if ((In24 < 1) .or. (In24 >= NSeeds - 1)) then +!start bjj +! print *, " Error in restarting with RLuxGo: the values", Int, K1, K2, " cannot occur at luxury level", LuxLev +! write( RanLux_str, '(A,3(I12),A,I5)' ) " Error in restarting with RLuxGo: the values ", Int, K1, K2, & +! " cannot occur at luxury level ", LuxLev +! CALL WrScr( TRIM(RanLux_str ) ) +!end bjj + In24 = 0 + end if + end if + return + end subroutine RLuxGo +!============================================================================ + function RCarry (N) result (Uni) ! Private (in module); generates a sequence of N uniform random numbers; returns the last one. + real(ReKi) :: Uni + integer, intent(in) :: N + integer :: Many +! start function RCarry + do Many = 1, N + ! The Generator proper: "Subtract-with-borrow", as proposed by Marsaglia and Zaman, Florida State University, March, 1989 + Uni = Seeds(J24) - Seeds(I24) - Carry + if (Uni < 0.0) then + Uni = Uni + 1.0 + Carry = TwoM24 + else + Carry = 0.0 + end if + Seeds(I24) = Uni + I24 = Next(I24) + J24 = Next(J24) + end do + return + end function RCarry +!============================================================================ + end Module Ran_Lux_Mod diff --git a/OpenFAST/modules/nwtc-library/src/readme.txt b/OpenFAST/modules/nwtc-library/src/readme.txt new file mode 100644 index 000000000..607db5ced --- /dev/null +++ b/OpenFAST/modules/nwtc-library/src/readme.txt @@ -0,0 +1,8 @@ +The two NWTC_Library-related types files cannot be generated through the registry. At the moment it is a manual process. + +The NWTC registry input file gets split into two sections: one for the mesh mapping and everything else. +It's not an automatic process since you have to copy the SetErrStat routine into NWTC_Library_Types.f90, +and you have to copy the mesh-related types/routines into the ModMesh_Types.f90 file. +Originally, we also had to change some other parts, too, but I've hard-coded some stuff +in the registry source code for when it is trying to generate types for the NWTC_Library module. +We could hard-code the registry to generate SetErrStat() at some point, too. \ No newline at end of file diff --git a/OpenFAST/modules/nwtc-library/test/Compare_LAPACK_MUMPS/Compare_LAPACK_MUMPS.f90 b/OpenFAST/modules/nwtc-library/test/Compare_LAPACK_MUMPS/Compare_LAPACK_MUMPS.f90 new file mode 100644 index 000000000..b2ff8091b --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Compare_LAPACK_MUMPS/Compare_LAPACK_MUMPS.f90 @@ -0,0 +1,249 @@ +!********************************************************************************************************************************** +! +! PROGRAM: Compare_LAPACK_MUMPS.f90 +! +! PURPOSE: Compares a solve of a system of equations by LAPACK and MUMPS. +! +! + +!********************************************************************************************************************************** + +PROGRAM Compare_LAPACK_MUMPS + + USE NWTC_Library + USE NWTC_LAPACK + USE MUMPS + IMPLICIT NONE + + + + ! Variables + + + ! File name + CHARACTER(*),PARAMETER :: InputFilePath='C:\Users\bjonkman\Documents\DATA\DesignCodes\simulators\FAST\SVNdirectory\branches\FAST_MUMPS\CertTest\Test21' + CHARACTER(1024) :: InputFileRoot + CHARACTER(1024) :: InputFileName + CHARACTER(10) :: TmpLine + + + INTEGER(IntKi) :: ErrStat + CHARACTER(1024) :: ErrMsg + + integer :: i, j, K, iTest, i_rhs, N, NZ + integer :: UnIn, UnOut, UnOut2 + REAL :: time_begin, time_end + REAL :: time_begin2, time_end2 + REAL :: init_time, init_time2 + REAL :: total_time, total_time2 + + real, allocatable :: full_jac(:,:), rhs(:) + integer,allocatable :: ipiv(:) + + type(SMUMPS_STRUC) :: mumps_par + + + !............................................................................................................................... + ! Initialize the library + !............................................................................................................................... + + CALL NWTC_Init( ) + + + UnOut = -1 + UnOut2 = -1 + CALL GetNewUnit( UnOut ) + CALL OpenFOutFile( UnOut, 'LAPACK_MUMPS_timings.txt' ) + + CALL GetNewUnit( UnOut2 ) + CALL OpenFOutFile( UnOut2, 'LAPACK_MUMPS_table.txt' ) + + + !............................................................................................................................... + ! Initialize MUMPS + !............................................................................................................................... + CALL CPU_TIME(time_begin) + + CALL NWTC_SMUMPS_Init( mumps_par, ErrStat, ErrMsg ) + + CALL CPU_TIME ( time_end ) + + WRITE(UnOut,'(A,ES15.7,A,ES15.7,A)') 'Initialization: MUMPS = ', time_end - time_begin, ' seconds' !; LAPACK = ', time_end2 - time_begin2, ' seconds.' + + + UnIn = -1 + do iTest = 27,19,-1 + + CALL WrScr( 'Test'//TRIM(num2lstr(iTest)) ) + + WRITE(UnOut,'(A)' ) '-----------------------------------------------------------------' + + + !............................................................................................................................... + ! Read the input files for matrix A + !............................................................................................................................... + + if (iTest==26) then + InputFileRoot = TRIM(InputFilePath)//'/10/Test21' + elseif (iTest==27) then + InputFileRoot = TRIM(InputFilePath)//'/05/Test21' + else + InputFileRoot = InputFilePath//'/Test'//TRIM(num2lstr(iTest)) + end if + + + !...................... + CALL GetNewUnit( UnIn ) + InputFileName = TRIM(InputFileRoot)//'.0.Jacobian.Sparse' + CALL OpenFInpFile( UnIn, TRIM(InputFileName) ) + + READ(UnIn, *) N, NZ + read(UnIn,*) tmpLine + + CALL NWTC_SMUMPS_CreateMatrix(mumps_par,n, ErrStat, ErrMsg, nz) + mumps_par%NZ = nz + + DO I = 1, mumps_par%NZ + READ(UnIn,*) mumps_par%IRN(I),mumps_par%JCN(I),mumps_par%A(I) + END DO + + CLOSE(UnIn) + + !...................... + InputFileName = TRIM(InputFileRoot)//'.0.Jacobian' + CALL OpenFInpFile( UnIn, TRIM(InputFileName) ) + + ALLOCATE( full_jac ( mumps_par%N, mumps_par%N ) ) + ALLOCATE( ipiv ( mumps_par%N ) ) + ALLOCATE( rhs ( mumps_par%N ) ) + + read(UnIn,*) tmpLine + DO I = 1, mumps_par%N + read(UnIn,*) full_jac(i,:) + END DO + CLOSE(UnIn) + + + !...................... + InputFileName = TRIM(InputFileRoot)//'.0.RHS' + CALL OpenFInpFile( UnIn, TRIM(InputFileName) ) + !...................... + + !CALL WrScr( ' finished reading matrices' ) + + !............................................................................................................................... + ! Factor matrix A + !............................................................................................................................... + + ! MUMPS + + CALL CPU_TIME(time_begin) + CALL NWTC_SMUMPS_AnalyzeAndFactor(mumps_par, ErrStat, ErrMsg) + CALL CPU_TIME ( time_end ) + if (ErrStat /= ErrID_None) THEN + DEALLOCATE( full_jac ) + DEALLOCATE( ipiv ) + DEALLOCATE( rhs ) + CALL WrScr(TRIM(ErrMsg)) + CALL NWTC_SMUMPS_DestroyMatrix(mumps_par) + CYCLE + end if + + + init_time = time_end - time_begin + + ! LAPACK + + CALL CPU_TIME(time_begin2) + CALL LAPACK_getrf( M=mumps_par%N, N=mumps_par%N, A=FULL_JAC, IPIV=ipiv, ErrStat=ErrStat, ErrMsg=ErrMsg ) + CALL CPU_TIME ( time_end2 ) + if (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + init_time2 = time_end2 - time_begin2 + + + ! Compare results + WRITE(UnOut,'( 2(A,ES15.7) )') 'Test'//trim(num2lstr(iTest))//' factorization times: MUMPS = ', init_time, & + ' seconds; LAPACK = ', init_time2 + + + !CALL WrScr( ' finished factoring matrices' ) + + !............................................................................................................................... + ! solve Ax=b + !............................................................................................................................... + READ(UnIn,*,iostat=ErrStat) mumps_par%RHS + + i_rhs = 0 + total_time = 0. + total_time2 = 0. + + do while (ErrStat == 0 ) + rhs = mumps_par%RHS + i_rhs = i_rhs + 1 + !call wrscr('RHS'//trim(num2lstr(i_rhs)) ) + + ! MUMPS + + CALL CPU_TIME(time_begin) + CALL NWTC_SMUMPS_Solve(mumps_par, ErrStat, ErrMsg) + CALL CPU_TIME ( time_end ) + total_time = total_time + time_end - time_begin + if (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + ! LAPACK + + CALL CPU_TIME(time_begin2) + CALL LAPACK_getrs( TRANS='N', N=mumps_par%N, A=FULL_JAC, IPIV=ipiv, B=rhs, ErrStat=ErrStat, ErrMsg=ErrMsg ) + CALL CPU_TIME ( time_end2 ) + total_time2 = total_time2 + time_end2 - time_begin2 + if (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + WRITE(UnOut,'( 3(A,ES15.7) )') 'Test'//trim(num2lstr(iTest))//' solve times: MUMPS = ', time_end - time_begin, & + ' seconds; LAPACK = ', time_end2 - time_begin2, & + ' seconds. Norm of difference = ', TwoNorm( rhs - mumps_par%rhs ) + + + READ(UnIn,*,iostat=ErrStat) mumps_par%RHS + + end do !while there is a line in the file + + + WRITE(UnOut,'( 2(A,ES15.7),A,I5 )') 'Test'//trim(num2lstr(iTest))//' solve times: MUMPS = ', total_time, & + ' seconds; LAPACK = ', total_time2, & + ' seconds. Number of solves = ', i_rhs + + WRITE(UnOut2, '( 3(I15,1x), 8(ES15.7,1x), I15, 2(1x,ES15.7) )') & + iTest, mumps_par%n, mumps_par%nz, 100.0*mumps_par%nz/(mumps_par%n**2), & + 0.0, 0.0, 0.0, & !time savings columns + init_time, init_time2, & !init time + total_time/i_rhs, total_time2/i_rhs, & !solve time (calculated) + i_rhs, total_time, total_time2 + + + !............................................................................................................................... + ! Deallocate arrays and close open files + !............................................................................................................................... + + CLOSE(UnIn) + + DEALLOCATE( full_jac ) + DEALLOCATE( ipiv ) + DEALLOCATE( rhs ) + + CALL CPU_TIME(time_begin) + CALL NWTC_SMUMPS_DestroyMatrix(mumps_par) + CALL CPU_TIME ( time_end ) + !WRITE (UnOut,*) 'MUMPS exit time: ', time_end - time_begin, ' seconds' + WRITE(UnOut,* ) !blank line + + end do ! next test case + + CLOSE( UnOut ) + CLOSE( UnOut2 ) + CALL NWTC_SMUMPS_End(mumps_par) + + +END PROGRAM Compare_LAPACK_MUMPS + diff --git a/OpenFAST/modules/nwtc-library/test/Test_CheckArgs.f90 b/OpenFAST/modules/nwtc-library/test/Test_CheckArgs.f90 new file mode 100644 index 000000000..8c833e1a2 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_CheckArgs.f90 @@ -0,0 +1,44 @@ + PROGRAM Test_CheckArgs + + + ! This program is used to test the use of CheckArgs() in NWTC_IO.f90. + + + USE :: NWTC_Library + + IMPLICIT NONE + + + CHARACTER(1024) :: InpFile = '' + + ProgName = 'Test_CheckArgs' + ProgVer = '(v1.00.00, 12-Dec-2012)' + + + ! Initialize the NWTC Library, which will initialize Pi-based constants. + +CALL NWTC_Init ( ProgName, ProgVer ) + + + ! Print out program and library name, version, and date. + +CALL DispNVD + + + ! Get the name of the primary input file from the command line. + + CALL CheckArgs ( InpFile ) + + IF ( LEN_TRIM( InpFile ) == 0 ) THEN + CALL WrScr1 ( ' Syntax is:' ) + CALL WrScr ( ' '//TRIM( ProgName )//' ['//SwChar//'h] <infile>' ) + CALL WrScr ( ' where:' ) + CALL WrScr ( ' '//SwChar//'h generates this help message.' ) +! CALL ProgAbort ( ' <infile> is the name of the required primary input file.', TimeWait=4.0, ErrLevel=1 ) +! CALL ProgAbort ( ' <infile> is the name of the required primary input file.', TimeWait=0.0, ErrLevel=1 ) + CALL ProgAbort ( ' <infile> is the name of the required primary input file.', TimeWait=-1.0, ErrLevel=1 ) + ENDIF + + + STOP + END PROGRAM Test_CheckArgs diff --git a/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/Test_ChkRealFmtStr.f90 b/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/Test_ChkRealFmtStr.f90 new file mode 100644 index 000000000..8044a1516 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/Test_ChkRealFmtStr.f90 @@ -0,0 +1,49 @@ +PROGRAM Test_ChkRealFmtStr + + + ! This program tests NWTC_IO.f90\ChkRealFmtStr(). + + +USE NWTC_Library + +IMPLICIT NONE + +INTEGER(IntKi) :: ErrStat ! An error status to be returned by ChkRealFmtStr. +INTEGER(IntKi) :: FmtWidth ! The number of characters that will result from writes using RealFmt. + +CHARACTER(200) :: ErrMsg ! An error message to be returned by ChkRealFmtStr. + + + +CALL NWTC_Init ( 'Test_ChkRealFmtStr', 'v1.00.00, 08-Jan-2013' ) +CALL WrScr ( ' Running Test_ChkRealFmtStr (v1.00.00, 07-Jan-2013)' ) + +CALL ChkRealFmtStr ( '1ES12.4', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "1ES12.4", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL ChkRealFmtStr ( 'F11.4', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "F11.4", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL ChkRealFmtStr ( 'xyzzy', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "xyzzy", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL ChkRealFmtStr ( 'F1.0', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "F1.0", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL ChkRealFmtStr ( '1ES2.4', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "1ES2.4", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL ChkRealFmtStr ( '1ES2.1', 'RealFmt', FmtWidth, ErrStat, ErrMsg ) +CALL WrScr1 ( ' Message = "'//TRIM(ErrMsg)//'"' ) +CALL WrScr ( ' Format = "1ES2.1", Field width = '//TRIM( Num2LStr( FmtWidth ) ) ) + +CALL WrScr ( '' ) + + +STOP +END \ No newline at end of file diff --git a/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/makefile b/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/makefile new file mode 100644 index 000000000..a860779ef --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_ChkRealFmtStr/makefile @@ -0,0 +1,117 @@ +#============================================================================================# +# This makefile created by M. Buhl on 26-Dec-2012. # +# # +# This makefile has been tested on Windows 7 with gfortran. # +# This makefile works with mingw32-make.exe. # +# # +# It was designed to be used with: # +# Test_ChkRealFmtStr (v1.00.00, 08-Jan-2013) # +# NWTC Subroutine Library (v1.06.00c-mlb, 12-Dec-2012) # +# # +# Older versions of Test_ChkRealFmtStr and the NWTC Library may not work with this makefile. # +#============================================================================================# + + # Location of source files for Test_OpenCon_Gnu and the NWTC Library. You will probably need to change these for your system. + +LIB_DIR = D:/CAEtools/Miscellaneous/NWTC_Library/trunk/source +TEST_DIR = . + + # System-specific settings. + + # Windows +DEL_CMD = del +MD_CMD = mkdir +PATH_SEP = \\ +EXE_EXT = .exe +OBJ_EXT = .obj +SYS_FILE = SysGnuWin + + # Linux +#DEL_CMD = rm -f +#MD_CMD = mkdir -p +#PATH_SEP = / +#EXE_EXT = +#OBJ_EXT = .o +#SYS_FILE = SysGnuLinux + + # Program name. + +PROG = Test_ChkRealFmtStr + + # Name of compiler to use and flags to use. + +FC = gfortran +FFLAGS = -O3 -fbacktrace + + # Destinations for executable and intermediate files. + +DEST_DIR = . +INTER_DIR = Obj + + # Precision. + +# Change to "DoubPrec" for double precision. You may also need to change an option switch to make constants DP. +PREC = SingPrec + + # Library files. + +LIB_SOURCES = \ + $(PREC).f90 \ + $(SYS_FILE).f90 \ + NWTC_IO.f90 \ + NWTC_Num.f90 \ + ModMesh.f90 \ + NWTC_Aero.f90 \ + NWTC_Library.f90 + + #==========================================================# + # You should not need to change anything beyond this point # + #==========================================================# + +TEST_SOURCES = $(PROG).f90 + +vpath %.f90 $(LIB_DIR) $(TEST_DIR) +vpath %.mod $(INTER_DIR) +vpath %.obj $(INTER_DIR) + +LIB_OBJS = $(LIB_SOURCES:.f90=.obj) +TEST_OBJS = $(TEST_SOURCES:.f90=.obj) + + # Rule to do everything. + +all: default +default: $(INTER_DIR) $(DEST_DIR)/$(PROG)$(EXE_EXT) + + # General rule for making the files. + +%.obj: %.f90 + $(FC) $(FFLAGS) -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) + + # Dependency rules. + +$(SYS_FILE).obj: $(PREC).obj +ModMesh.obj: $(PREC).obj +NWTC_IO.obj: $(SYS_FILE).obj +NWTC_Num.obj: NWTC_IO.obj +NWTC_Aero.obj: NWTC_IO.obj NWTC_Num.obj +NWTC_Library.obj: NWTC_Aero.obj ModMesh.obj +$(PROG).obj: NWTC_Library.obj +$(PROG).exe: $(PROG).obj + + # Make sure the destination directory for the intermediate files exist. + +$(INTER_DIR): + $(MD_CMD) $(INTER_DIR) + + # For compiling Test_OpenCon_Gnu. + +$(DEST_DIR)/$(PROG)$(EXE_EXT): $(LIB_OBJS) $(TEST_OBJS) | $(INTER_DIR) + $(FC) $(FLAGS) -I $(INTER_DIR) -o $(DEST_DIR)/$(PROG)$(EXE_EXT) \ + $(foreach src, $(LIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(TEST_OBJS), $(addprefix $(INTER_DIR)/,$(src))) + + # Cleanup afterwards. + +clean: + $(DEL_CMD) $(INTER_DIR)$(PATH_SEP)*.mod $(INTER_DIR)$(PATH_SEP)*.obj + diff --git a/OpenFAST/modules/nwtc-library/test/Test_FileSize/Test_FileSize.f90 b/OpenFAST/modules/nwtc-library/test/Test_FileSize/Test_FileSize.f90 new file mode 100644 index 000000000..910c1154f --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_FileSize/Test_FileSize.f90 @@ -0,0 +1,21 @@ +PROGRAM Test_FileSize + + ! This program tests the FileSize() function in the library. + +USE NWTC_Library + +IMPLICIT NONE + +INTEGER :: Unit = 11 + +CALL NWTC_Init ( 'Test_FileSize', 'v1.00.01, 01-Mar-2013' ) +CALL WrScr ( ' Running Test_FileSize (v1.00.01, 01-Mar-2013)' ) + +OPEN ( Unit, FILE='Test_FileSize.f90', STATUS='OLD' ) + +PRINT '(/,A,/)', ' Size of Test_FileSize.f90 = '//TRIM( Num2LStr( Int( FileSize( Unit ) ) ) )//' bytes.' + +CALL ProgPause + +STOP +END diff --git a/OpenFAST/modules/nwtc-library/test/Test_FileSize/makefile b/OpenFAST/modules/nwtc-library/test/Test_FileSize/makefile new file mode 100644 index 000000000..4f80a02b5 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_FileSize/makefile @@ -0,0 +1,140 @@ +#================================================================================# +# This makefile was last updated by M. Buhl on 26-Feb-2013. # +# # +# This makefile has been tested with: # +# Windows 7 # +# GNU Make3.81 # +# gfortran v4.6.1 # +# Ubuntu 12.04.0 LTS # +# GNU Make3.82 # +# gfortran v4.6.3 # +# # +# It was designed to be used with: # +# Test_FileSize (v1.00.00 , 26-Feb-2013) # +# NWTC Subroutine Library (v2.00.00c-bjj, 05-Feb-2013) # +#================================================================================# + + +# WARNING!!!!! This makefile doesn't actually work and I have no idea why. It will not compile the Library on Windows. + + + # Windows or Linux? 32-bit or 64-bit? + +BITS = 32 +BITS = 64 + + # Location of source files for the NWTC Library. You will probably need to change these for your system. + +ifeq ($(OS),Windows_NT) + LIB_DIR = C:\Users\mbuhl\UserData\CAEtools\Miscellaneous\NWTC_Library\branches\BJonkman\source + #LIB_DIR = C:\Users\mbuhl\UserData\CAEtools\Miscellaneous\NWTC_Library\trunk\source +else + LIB_DIR = $(HOME)/PC/CAEtools/Miscellaneous/NWTC_Library/branches/BJonkman/source +endif + +TEST_DIR = . + + # Name of compiler to use and flags to use. + +FC = gfortran +FFLAGS = -O3 -m$(BITS) -fbacktrace -x f95-cpp-input -ffree-line-length-none +LFLAGS = -m$(BITS) + + # Precision. + +# Use "SingPrec" for single precision and "DoubPrec" for double precision. You may also need to change an option switch to make constants DP. +PREC = SingPrec + + #==========================================================# + # You should not need to change anything beyond this point # + #==========================================================# + + + # System-specific settings. + +ifeq ($(OS),Windows_NT) + # Windows + DEL_CMD = del + EXE_EXT = _gwin$(BITS).exe + INTER_DIR = Obj_win$(BITS) + MD_CMD = @mkdir + OBJ_EXT = .obj + PATH_SEP = \\ + SYS_FILE = SysGnuWin +else + # Linux + DEL_CMD = rm -f + EXE_EXT = _glin$(BITS) + INTER_DIR = Obj_lin$(BITS) + MD_CMD = @mkdir -p + OBJ_EXT = .o + PATH_SEP = / + SYS_FILE = SysGnuLinux +endif + + # Destination for executable. + +DEST_DIR = . + + # Library files. + +LIB_SOURCES = \ + $(PREC).f90 \ + $(SYS_FILE).f90 \ + NWTC_IO.f90 \ + NWTC_Num.f90 \ + ModMesh_Types.f90 \ + ModMesh.f90 \ + NWTC_Aero.f90 \ + NWTC_Library.f90 + +TEST_SOURCES = \ + Test_FileSize.f90 + +vpath %.f90 $(LIB_DIR) $(TEST_DIR) +vpath %.mod $(INTER_DIR) +vpath %.obj $(INTER_DIR) + +LIB_OBJS = $(LIB_SOURCES:.f90=.obj) +TEST_OBJS = $(TEST_SOURCES:.f90=.obj) + + # Rule to do everything. + +all: default +default: $(INTER_DIR) $(DEST_DIR)/Test_FileSize$(EXE_EXT) + + # General rule for making the files. + +%.obj: %.f90 + $(FC) $(FFLAGS) -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) + + # Dependency rules. + +$(SYS_FILE).obj: $(PREC).obj +ModMesh_Types.obj: $(PREC).obj +ModMesh.obj: ModMesh_Types.obj +NWTC_IO.obj: $(SYS_FILE).obj +NWTC_Num.obj: NWTC_IO.obj +NWTC_Aero.obj: NWTC_IO.obj NWTC_Num.obj +NWTC_Library.obj: NWTC_Aero.obj ModMesh.obj +Test_FileSize.obj: NWTC_Library.obj + +#Test_FileSize$(EXE_EXT): Test_FileSize.obj + + # Make sure the destination directory for the intermediate files exist. + +$(INTER_DIR): + $(MD_CMD) $(INTER_DIR) + + # For compiling Test_FileSize. + +$(DEST_DIR)/Test_FileSize$(EXE_EXT): $(LIB_OBJS) $(TEST_OBJS) | $(INTER_DIR) + $(FC) $(LFLAGS) -I $(INTER_DIR) -o $(DEST_DIR)/Test_FileSize$(EXE_EXT) \ + $(foreach src, $(LIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(TEST_OBJS), $(addprefix $(INTER_DIR)/,$(src))) + + # Cleanup afterwards. + +clean: + $(DEL_CMD) $(INTER_DIR)$(PATH_SEP)*.mod $(INTER_DIR)$(PATH_SEP)*.obj + diff --git a/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Makefile b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Makefile new file mode 100644 index 000000000..b05f1e038 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Makefile @@ -0,0 +1,173 @@ +#================================================================================# +# This makefile copied from B. Jonkman by J. Michalakes on 29-Jan-2013, # +# adapted from Crunch (M. Buhl on 25-Jan-2013). # +# # +# This makefile has been tested on Windows 7 with gfortran. # +# This makefile works with mingw32-make.exe. # +# # +# It was designed to be used with: # +# Module1 (v1.00.04, 29-Jan-2013) # +# Module2 (v1.00.04, 29-Jan-2013) # +# NWTC Subroutine Library (CSC version 29-Jan-2013) # +# # +# Older versions of ModuleName and NWTC Library may not work with this makefile. # +#================================================================================# + + # 32-bit or 64-bit? +BITS = 32 +#BITS = 64 + + + # Location of source files for ModuleName and the NWTC Library. You will probably need to change these for your system. +#OS = Linux + +# these settings are overridden below +ifeq ($(OS),Windows_NT) + LIB_DIR = C:/Users/bjonkman/Documents/DATA/DesignCodes/miscellaneous/nwtc_subs/SVNdirectory/trunk/source + Work_DIR = C:/Users/bjonkman/Documents/DATA/DesignCodes/miscellaneous/nwtc_subs/SVNdirectory/branches/MeshMapping + REGISTRY = Registry + LAPACK_DIR = C:/LAPACK/win32 + NETLIB_DIR = C:/Users/bjonkman/Documents/DATA/DesignCodes/Simulators/FAST/SVNdirectory/branches/BJonkman/source/dependencies/NetLib +else +# LIB_DIR = $(HOME)/PC/CAEtools/Miscellaneous/NWTC_Library/trunk/source + LIB_DIR = ../NWTC_Library/source + REGISTRY = ../FAST/Registry/Source/registry.exe +endif + +MODNAME_DIR = . + + + + # Name of compiler to use and flags to use. + +FC = gfortran +FFLAGS = -O3 -m$(BITS) -fbacktrace -ffree-line-length-none -x f95-cpp-input -ffree-line-length-none +FFLAGS = -O3 -fbacktrace -ffree-line-length-none -x f95-cpp-input -DMESH_DEBUG +LDFLAGS = -O3 -fbacktrace -llapack -lblas -L$(LAPACK_DIR) + + # Precision. + +# Use "SingPrec" for single precision and "DoubPrec" for double precision. You may also need to change an option switch to make constants DP. +PREC = SingPrec +#PREC = DoubPrec + + #==========================================================# + # You should not need to change anything beyond this point # + #==========================================================# + + # System-specific settings. + +ifeq ($(OS),Windows_NT) + # Windows + DEL_CMD = del + EXE_EXT = _gwin$(BITS).exe + INTER_DIR = Obj_win$(BITS) + MD_CMD = @mkdir + OBJ_EXT = .obj + PATH_SEP = \\ + SYS_FILE = SysGnuWin +else + # Linux + DEL_CMD = rm -f + EXE_EXT = _glin$(BITS) + INTER_DIR = Obj_lin$(BITS) + MD_CMD = @mkdir -p + OBJ_EXT = .o + PATH_SEP = / + SYS_FILE = SysGnuLinux +endif + + # Destination and RootName for executable + +OUTPUT_NAME = Test_MeshMapping +DEST_DIR = . + + # Library files. + +LIB_SOURCES = \ + $(PREC).f90 \ + NWTC_Base.f90 \ + $(SYS_FILE).f90 \ + NWTC_IO.f90 \ + NWTC_Library_Types.f90 \ + ModMesh_Types.f90 \ + ModMesh.f90 \ + ModMesh_Mapping.f90 \ + NWTC_Library.f90 \ + NWTC_Num.f90 + +NETLIB_SOURCES = \ + NWTC_ScaLAPACK.f90 \ + NWTC_LAPACK.f90 \ + DLASRT2.f \ + SLASRT2.f + + +MODNAME_SOURCES = \ + Test_MeshMapping.f90 + +vpath %.f90 $(Work_DIR) $(LIB_DIR) $(NETLIB_DIR) $(MODNAME_DIR) +vpath %.mod $(INTER_DIR) +vpath %.obj $(INTER_DIR) + + +LIB_OBJS = $(LIB_SOURCES:.f90=.obj) +NETLIB_OBJS = NWTC_LAPACK.obj +#NWTC_ScaLAPACK.obj DLASRT2.obj SLASRT2.obj +MODNAME_OBJS = $(MODNAME_SOURCES:.f90=.obj) + + # Rule to do everything. + +all: default +default: Test_MeshMapping.f90 $(INTER_DIR) $(DEST_DIR)/$(OUTPUT_NAME)$(EXE_EXT) + + # General rule for making the files. + +%.obj: %.f90 + $(FC) -I $(INTER_DIR) $(FFLAGS) -g -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) + +%.obj: %.f + $(F77) -I $(INTER_DIR) $(FFLAGS) -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) -B $(INTER_DIR) + + + # Dependency rules. + +NWTC_LAPACK.obj: NWTC_Base.obj +NWTC_ScaLAPACK.obj: NWTC_Base.obj DLASRT2.obj SLASRT2.obj + +NWTC_Base.obj: $(PREC).obj +$(SYS_FILE).obj: NWTC_Base.obj +NWTC_Library_Types.obj: $(SYS_FILE).obj +NWTC_IO.obj: NWTC_Library_Types.obj +NWTC_Num.obj: NWTC_IO.obj +ModMesh_Types.obj: NWTC_Num.obj +ModMesh.obj: ModMesh_Types.obj +ModMesh_Mapping.obj: ModMesh.obj NWTC_LAPACK.obj +NWTC_Library.obj: ModMesh.obj ModMesh_Mapping.obj + + +Test_MeshMapping.obj: ModMesh_Mapping.obj NWTC_Library.obj + + +#$(OUTPUT_NAME)$(EXE_EXT): Test_MeshMapping.obj + + # Make sure the destination directory for the intermediate files exist. + +$(INTER_DIR): + $(MD_CMD) $(INTER_DIR) + + + + # For compiling the driver/glue code. + +$(DEST_DIR)/$(OUTPUT_NAME)$(EXE_EXT): $(LIB_OBJS) $(MODNAME_OBJS) | $(INTER_DIR) + $(FC) $(LDFLAGS) -I $(INTER_DIR) -o $(DEST_DIR)/$(OUTPUT_NAME)$(EXE_EXT) \ + $(foreach src, $(NETLIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(LIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(MODNAME_OBJS), $(addprefix $(INTER_DIR)/,$(src))) + + # Cleanup afterwards. + +clean: + $(DEL_CMD) $(INTER_DIR)$(PATH_SEP)*.mod $(INTER_DIR)$(PATH_SEP)*.obj $(OUTPUT_NAME)$(EXE_EXT) + diff --git a/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping.f90 b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping.f90 new file mode 100644 index 000000000..7f8b6bce4 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping.f90 @@ -0,0 +1,728 @@ + +subroutine Test_TestMeshMapping() + + USE NWTC_Library + use TestMeshMapping_Mod + + IMPLICIT NONE + + REAL(ReKi), allocatable :: LinVec_2_tmp(:), LinVec_2_a_tmp(:) + + REAL(ReKi), allocatable :: LinVec_1(:), LinVec_1_a(:), LinVec_1_b(:), LinVec_1_c(:), LinVec_1_d(:) + REAL(ReKi), allocatable :: LinVec_2(:), LinVec_2_a(:), LinVec_2_b(:), LinVec_2_c(:) ! data for linearization testing + logical, parameter :: TestLinearization = .true. + integer :: seed(15) + + INTEGER :: TestNumber + CHARACTER(256) :: BinOutputName + + seed = 0 + call random_seed(SIZE=n1) + CALL RANDOM_SEED (PUT = SEED (1 : n1)) + + ! CALL NWTC_Init( ) + + DO TestNumber=1,13 + + debug_print = .false. + + print *, '---------------------------------------------------------------' + print *, ' Test ', TestNumber + print *, '---------------------------------------------------------------' + ! .............................................................................................................................. + ! Mesh1 fields: + ! Mesh1_I (input) has loads + ! Mesh1_O (output) has motions + ! .............................................................................................................................. + + ! .............................................................................................................................. + ! Mesh2 fields: + ! Mesh2_I (input) has motions + ! Mesh2_O (output) has loads + ! .............................................................................................................................. + + + + ! .............................................................................................................................. + ! Create output meshes: + ! Mesh1_O (output) has motions + ! Mesh2_O (output) has loads + ! .............................................................................................................................. + + ! These subroutines will set the Mesh1Type and Mesh2Type variables, then create the output meshes, set reference + ! position/orientation, and set initial outputs for each module (to test mapping to inputs) + SELECT CASE ( TestNumber ) + CASE(1) ! 1 point to 5 points + CALL CreateOutputMeshes_Test1() + CASE(2) ! 'T' with resolution gain + CALL CreateOutputMeshes_Test2('A') ! was 'A' + CASE(3) ! 'T' with loss of resolution + CALL CreateOutputMeshes_Test2('B') + CASE(4) ! 'T' with equal nodes + CALL CreateOutputMeshes_Test2('C') + CASE(5) + CALL CreateOutputMeshes_Test5() + CASE(6) + CALL CreateOutputMeshes_Test6() + CASE(7) + CALL CreateOutputMeshes_Test7('A') + CASE(8) + CALL CreateOutputMeshes_Test7('B') + CASE(9) + CALL CreateOutputMeshes_Test9() + CASE(10) !monopile (point-to-point) + CALL CreateOutputMeshes_Test10() + CASE(11) + CALL CreateOutputMeshes_Test11() + CASE(12) + CALL CreateOutputMeshes_Test5Orient + CASE(13) + CALL CreateOutputMeshes_Test13 + END SELECT + + WRITE(BinOutputName,'(A,A,A)') 'Test', TRIM(Num2LStr(TestNumber)),'Meshes.bin' + + + ! .............................................................................................................................. + ! Create sibling input meshes: + ! Mesh1_I (input) has loads + ! Mesh2_I (input) has motions + ! .............................................................................................................................. + + + CALL MeshCopy ( SrcMesh = mesh1_O & + , DestMesh = mesh1_I & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_INPUT & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + !.............................. + + CALL MeshCopy ( SrcMesh = mesh2_O & + , DestMesh = mesh2_I & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_INPUT & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + ! .............................................................................................................................. + ! Initialize the mapping data: + ! .............................................................................................................................. + + CALL MeshMapCreate( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshMapCreate( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + Mesh1_O%RemapFlag = .false. + Mesh2_O%RemapFlag = .false. + + ! .............................................................................................................................. + ! Map the outputs to inputs: + ! .............................................................................................................................. + IF (Mesh1Type == ELEMENT_POINT ) THEN + IF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Point_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Transfer_Point_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + ELSEIF ( Mesh2Type == ELEMENT_LINE2) THEN + CALL Transfer_Point_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Transfer_Line2_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + END IF + ELSEIF ( Mesh1Type == ELEMENT_LINE2 ) THEN + IF ( Mesh2Type == ELEMENT_LINE2 ) THEN + CALL Transfer_Line2_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + if (TestNumber == 5 .or. TestNumber == 12 ) call InitTest5Loads() + if (TestNumber == 13 ) call InitTest13Loads() + CALL Transfer_Line2_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + ELSEIF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Line2_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Transfer_Point_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + END IF + END IF + + + ! .............................................................................................................................. + ! Write results to file(s) + ! .............................................................................................................................. + call WriteMappingTransferToFile(Mesh1_I, Mesh1_O, Mesh2_I, Mesh2_O, Map_Mod1_Mod2, Map_Mod2_Mod1, BinOutputName) + + if (TestNumber == 13) then + + !write( 21, '(A)' ) + DO i=1,mesh2_o%nnodes + n1 = mesh1_o%ElemTable(ELEMENT_LINE2)%Elements(Map_Mod1_Mod2%MapMotions(i)%OtherMesh_Element)%ElemNodes(1) + n2 = mesh1_o%ElemTable(ELEMENT_LINE2)%Elements(Map_Mod1_Mod2%MapMotions(i)%OtherMesh_Element)%ElemNodes(2) + + WRITE (21, '(6(F15.5))' ) atan2( mesh2_i%refOrientation(1,2,i ) , mesh2_i%refOrientation(1,1,i ) ),& + atan2( mesh2_i%Orientation( 1,2,i ) , mesh2_i%Orientation( 1,1,i ) ),& + atan2( mesh1_o%refOrientation(1,2,n1) , mesh1_o%refOrientation(1,1,n1) ),& + atan2( mesh1_o%Orientation( 1,2,n1) , mesh1_o%Orientation( 1,1,n1) ),& + atan2( mesh1_o%refOrientation(1,2,n2) , mesh1_o%refOrientation(1,1,n2) ),& + atan2( mesh1_o%Orientation( 1,2,n2) , mesh1_o%Orientation( 1,1,n2) ) + end do + + + + end if + +if ( TestLinearization ) then + + ! .............................................................................................................................. + ! Linearize about the operating points: + ! .............................................................................................................................. + + call AllocAry( LinVec_1, Mesh1_O%nnodes*3, 'LinVec_1', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_1_a, Mesh1_O%nnodes*3, 'LinVec_1_a', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_1_b, Mesh1_O%nnodes*3, 'LinVec_1_b', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_1_c, Mesh1_O%nnodes*3, 'LinVec_1_c', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_1_d, Mesh1_O%nnodes*3, 'LinVec_1_d', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + call AllocAry( LinVec_2, Mesh2_O%nnodes*3, 'LinVec_2', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_2_a, Mesh2_O%nnodes*3, 'LinVec_2_a', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_2_b, Mesh2_O%nnodes*3, 'LinVec_2_b', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_2_c, Mesh2_O%nnodes*3, 'LinVec_2_c', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + call AllocAry( LinVec_2_tmp, Mesh2_O%nnodes*9, 'LinVec_2_tmp', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call AllocAry( LinVec_2_a_tmp, Mesh2_O%nnodes*9, 'LinVec_2_a_tmp', ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + ! make copies of operating point values + CALL MeshCopy (mesh1_O, mesh1_O_op, MESH_NEWCOPY, ErrStat , ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshCopy (mesh2_O, mesh2_O_op, MESH_NEWCOPY, ErrStat , ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshCopy (mesh1_I, mesh1_I_op, MESH_NEWCOPY, ErrStat , ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshCopy (mesh2_I, mesh2_I_op, MESH_NEWCOPY, ErrStat , ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + +write(99, *) '---------------------------------------------------------------' +write(99, *) ' Test ', TestNumber +write(99, *) '---------------------------------------------------------------' + + ! all of these meshes are set to their operating point values + + IF (Mesh1Type == ELEMENT_POINT ) THEN + IF ( Mesh2Type == ELEMENT_POINT ) THEN + write(*,*) 'POINT-to-POINT' + CALL Linearize_Point_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Linearize_Point_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + ELSEIF ( Mesh2Type == ELEMENT_LINE2) THEN + write(*,*) 'POINT-to-LINE2 MOTIONS and LINE2-to-POINT LOADS' + CALL Linearize_Point_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Linearize_Line2_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + END IF + ELSEIF ( Mesh1Type == ELEMENT_LINE2 ) THEN + IF ( Mesh2Type == ELEMENT_LINE2 ) THEN + write(*,*) 'LINE2-to-LINE2' + CALL Linearize_Line2_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Linearize_Line2_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + ELSEIF ( Mesh2Type == ELEMENT_POINT ) THEN + write(*,*) 'LINE2-to-POINT MOTIONS and POINT-to-LINE2 LOADS' + CALL Linearize_Line2_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + CALL Linearize_Point_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ); IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + END IF + END IF + + + if (allocated(map_mod1_mod2%dm%mi)) call wrmatrix(map_mod1_mod2%dm%mi, 99,Fmt,'Mi') + if (allocated(map_mod1_mod2%dm%fx_p)) call wrmatrix(map_mod1_mod2%dm%fx_p,99,Fmt,'fx_p') + !if (allocated(map_mod1_mod2%dm%tv_uD)) call wrmatrix(map_mod1_mod2%dm%tv_uD, 99,Fmt,'tv_uD') + !if (allocated(map_mod1_mod2%dm%tv_uS)) call wrmatrix(map_mod1_mod2%dm%tv_uS, 99,Fmt,'tv_uD') + !if (allocated(map_mod1_mod2%dm%ta_uD)) call wrmatrix(map_mod1_mod2%dm%ta_uD, 99,Fmt,'ta_uD') + !if (allocated(map_mod1_mod2%dm%ta_uS)) call wrmatrix(map_mod1_mod2%dm%ta_uS, 99,Fmt,'ta_uS') + !if (allocated(map_mod1_mod2%dm%ta_rv)) call wrmatrix(map_mod1_mod2%dm%ta_rv, 99,Fmt,'ta_rv') + ! + !if (allocated(map_mod2_mod1%dm%li )) call wrmatrix(map_mod2_mod1%dm%li, 99,Fmt,'li') + !if (allocated(map_mod2_mod1%dm%M_uD)) call wrmatrix(map_mod2_mod1%dm%M_uD,99,Fmt,'M_uD') + !if (allocated(map_mod2_mod1%dm%M_uS)) call wrmatrix(map_mod2_mod1%dm%M_uS,99,Fmt,'m_uS') + !if (allocated(map_mod2_mod1%dm%M_f)) call wrmatrix(map_mod2_mod1%dm%M_f, 99,Fmt,'m_f') + + + write(*,ErrTxtFmt) 'Field','#','Absolute Err','Percent Err','Max perturb:D','Max OP:S','Max delta:S','Max delta:S','Max delta:S','Max delta:S' + write(*,ErrTxtFmt) '-----','-','------------','-----------','-------------','--------','-----------','-----------','-----------','-----------' + ! .................. + ! Rotational displacement: + ! .................. + + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh2_O_op, Mesh2_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRotationPerturb(LinVec_1) + + LinVec_2_a = matmul( map_mod1_mod2%dm%mi, LinVec_1 ) ! approximate delta theta^D + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + + ! delta theta^S + call SmllRotTrans( 'orientation', LinVec_1(j ) & + , LinVec_1(j+1) & + , LinVec_1(j+2) & + , Orientation, ErrStat=ErrStat, ErrMsg=ErrMsg) + + ! Mesh1_O%Orientation = theta^S|_op + delta theta^S + Mesh1_O%Orientation(:,:,i) = matmul( Mesh1_O_op%Orientation(:,:,i), Orientation ) + + !IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + end do + + !M( x^S|_op + delta x^S ) + call TransferMotionData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + + !theta^D|_op + delta theta^D = theta^D -> + !delta theta^D = (theta^D|_op)^(-1) * theta^D + Orientation = matmul( transpose(Mesh2_I_op%Orientation(:,:,i)), Mesh2_I%Orientation(:,:,i) ) + + LinVec_2(j:j+2) = GetSmllRotAngs(Orientation,ErrStat,ErrMsg) + IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end do + + call WrErrorLine('Rotational Displacement', LinVec_2, LinVec_2_a, 00_ReKi*Mesh1_O_op%TranslationVel, LinVec_1) + +debug_print = .false. + end do + write(*,*) ! blank line + + ! .................. + ! Translational displacement: + ! .................. + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRandomVector(LinVec_1) + call getRotationPerturb(LinVec_1_a) + +!LinVec_1 =0 +call wrmatrix( LinVec_1, 26, 'ES15.5' ) +call wrmatrix( LinVec_1_a, 27, 'ES15.5' ) + + + LinVec_2_a = matmul( map_mod1_mod2%dm%mi, LinVec_1 ) + matmul( map_mod1_mod2%dm%fx_p, LinVec_1_a ) ! approximate delta theta^D + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + + ! Mesh1_O%TranslationDisp = u^S|_op + delta u^S + Mesh1_O%TranslationDisp(:,i) = Mesh1_O_op%TranslationDisp(:,i) + LinVec_1(j:j+2) + + ! Mesh1_O%Orientation = theta^S|_op + delta theta^S + call getLinearOrient(LinVec_1_a(j:j+2), Orientation) + Mesh1_O%Orientation(:,:,i) = matmul( Mesh1_O_op%Orientation(:,:,i), Orientation ) + + + !IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end do + + + !M( x^S|_op + delta x^S ) + call TransferMotionData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%TranslationDisp(:,i) - Mesh2_I_op%TranslationDisp(:,i) + end do + +if (TestNumber==13) debug_print = .true. + call WrErrorLine('Translational Displacement', LinVec_2, LinVec_2_a, Mesh1_O_op%TranslationVel, LinVec_1, LinVec_1_a) +debug_print = .false. + +call wrmatrix( LinVec_2, 28, 'ES15.5' ) +call wrmatrix( LinVec_2_a, 29, 'ES15.5' ) + +call wrmatrix( LinVec_2 - LinVec_2_a , 51, 'ES15.5' ) + + + end do + + write(*,*) ! blank line + + ! .................. + ! Rotational velocity: + ! .................. + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRandomVector(LinVec_1) + + LinVec_2_a = matmul( map_mod1_mod2%dm%mi, LinVec_1 ) ! approximate delta theta^D + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + ! Mesh1_O%RotationVel = omega^S|_op + delta omega^S + Mesh1_O%RotationVel(:,i) = Mesh1_O_op%RotationVel(:,i) + LinVec_1(j:j+2) + end do + + !M( x^S|_op + delta x^S ) + call TransferMotionData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%RotationVel(:,i) - Mesh2_I_op%RotationVel(:,i) + end do + + call WrErrorLine('Rotational Velocity', LinVec_2, LinVec_2_a, Mesh1_O_op%RotationVel, LinVec_1) + + end do + + write(*,*) ! blank line + + ! .................. + ! Translational velocity: + ! .................. + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + + !call getRandomVector(LinVec_2_b) ! u^D ! for this, we will actually perturb u^S (LinVec_1_a) and theta^S (LinVec_1) + call getRotationPerturb(LinVec_1) ! theta^S + call getRandomVector(LinVec_1_a) ! u^S + call getRandomVector(LinVec_1_b) ! v^S + call getRandomVector(LinVec_1_c) ! omega^S + + + + ! get the displaced position + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + + ! Mesh1_O%Orientation = theta^S|_op + delta theta^S + call getLinearOrient(LinVec_1(j:j+2), Orientation) + Mesh1_O%Orientation(:,:,i) = matmul( Mesh1_O_op%Orientation(:,:,i), Orientation ) + + ! Mesh1_O%TranslationDisp = u^S|_op + delta u^S + Mesh1_O%TranslationDisp(:,i) = Mesh1_O_op%TranslationDisp(:,i) + LinVec_1_a(j:j+2) + + ! Mesh1_O%TranslationVel = v^S|_op + delta v^S + Mesh1_O%TranslationVel(:,i) = Mesh1_O_op%TranslationVel(:,i) + LinVec_1_b(j:j+2) + + ! Mesh1_O%RotationVel = omega^S|_op + delta omega^S + Mesh1_O%RotationVel(:,i) = Mesh1_O_op%RotationVel(:,i) + LinVec_1_c(j:j+2) + + !IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end do + + + !M( x^S|_op + delta x^S ) + call TransferMotionData() ! this sets Mesh2_I, the displaced source mesh + + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%TranslationVel(:,i) - Mesh2_I_op%TranslationVel(:,i) + end do + + ! delta u^D + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2_b(j:j+2) = Mesh2_I%TranslationDisp(:,i) - Mesh2_I_op%TranslationDisp(:,i) + end do + + LinVec_2_a = matmul( map_mod1_mod2%dm%tv_uD, LinVec_2_b ) + matmul( map_mod1_mod2%dm%tv_uS, LinVec_1_a ) & + + matmul( map_mod1_mod2%dm%mi, LinVec_1_b ) + matmul( map_mod1_mod2%dm%fx_p, LinVec_1_c )! approximate delta theta^D + + + call WrErrorLine('Translational Velocity', LinVec_2, LinVec_2_a, Mesh1_O_op%TranslationVel, LinVec_1, LinVec_1_a, LinVec_1_b) + + end do + write(*,*) ! blank line + + ! .................. + ! Rotational acceleration: + ! .................. + + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh2_O_op, Mesh2_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRandomVector(LinVec_1) + + LinVec_2_a = matmul( map_mod1_mod2%dm%mi, LinVec_1 ) ! approximate delta theta^D + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + ! Mesh1_O%RotationAcc = alpha^S|_op + delta alpha^S + Mesh1_O%RotationAcc(:,i) = Mesh1_O_op%RotationAcc(:,i) + LinVec_1(j:j+2) + end do + + + !M( x^S|_op + delta x^S ) + call TransferMotionData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%RotationAcc(:,i) - Mesh2_I_op%RotationAcc(:,i) + end do + + call WrErrorLine('Rotational Acceleration', LinVec_2, LinVec_2_a, Mesh1_O_op%RotationAcc, LinVec_1) + + end do + write(*,*) ! blank line + + ! .................. + ! Translational acceleration: + ! .................. + + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh2_O_op, Mesh2_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRotationPerturb(LinVec_1) ! delta theta + !call getRandomVector(LinVec_2_b) ! delta u^D ! we'll calculate this from delta theta and delta u^S + call getRandomVector(LinVec_1_a) ! delta u^S + call getRandomVector(LinVec_1_b) ! delta omega^S + call getRandomVector(LinVec_1_c) ! delta a^S + call getRandomVector(LinVec_1_d) ! delta alpha^S + + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + + ! Mesh1_O%Orientation = theta^S|_op + delta theta^S + call getLinearOrient(LinVec_1(j:j+2), Orientation) + Mesh1_O%Orientation(:,:,i) = matmul( Mesh1_O_op%Orientation(:,:,i), Orientation ) + + ! Mesh1_O%TranslationDisp = omega^S|_op + delta u^S + Mesh1_O%TranslationDisp(:,i) = Mesh1_O_op%TranslationDisp(:,i) + LinVec_1_a(j:j+2) + + ! Mesh1_O%RotationVel = omega^S|_op + delta omega^S + Mesh1_O%RotationVel(:,i) = Mesh1_O_op%RotationVel(:,i) + LinVec_1_b(j:j+2) + + ! Mesh1_O%TranslationAcc = a^S|_op + delta a^S + Mesh1_O%TranslationAcc(:,i) = Mesh1_O_op%TranslationAcc(:,i) + LinVec_1_c(j:j+2) + + ! Mesh1_O%RotationAcc = alpha^S|_op + delta alpha^S + Mesh1_O%RotationAcc(:,i) = Mesh1_O_op%RotationAcc(:,i) + LinVec_1_d(j:j+2) + + !IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end do + + + !M( x^S|_op + delta x^S ) + call TransferMotionData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%TranslationAcc(:,i) - Mesh2_I_op%TranslationAcc(:,i) + end do + + + ! delta u^D + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2_b(j:j+2) = Mesh2_I%TranslationDisp(:,i) - Mesh2_I_op%TranslationDisp(:,i) + end do + + LinVec_2_a = matmul( map_mod1_mod2%dm%ta_uD, LinVec_2_b ) + matmul( map_mod1_mod2%dm%ta_uS, LinVec_1_a ) & + + matmul( map_mod1_mod2%dm%ta_rv, LinVec_1_b ) & + + matmul( map_mod1_mod2%dm%mi, LinVec_1_c ) + matmul( map_mod1_mod2%dm%fx_p, LinVec_1_d )! approximate delta theta^D + + call WrErrorLine('Translational Acceleration', LinVec_2, LinVec_2_a, Mesh1_O_op%TranslationAcc, LinVec_1, LinVec_1_a, LinVec_1_b, LinVec_1_c) + + end do + write(*,*) ! blank line + + + ! .................. + ! Forces: + ! .................. + + ! get max Force : + mf=maxval( abs(Mesh2_O_op%Force ) ) + !mf = sqrt( EPSILON(mf)) * max(1.0_ReKi, mf) + + + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh2_O_op, Mesh2_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + do n1=1,15 + + ! perturb x^S: + call getRandomVector(LinVec_2, mf) + + LinVec_1_a = matmul( map_mod2_mod1%dm%li, LinVec_2 ) ! approximate delta theta^D + + do i=1,Mesh2_O%nnodes + j = (i-1)*3 + 1 + + ! Mesh2_O%Force = theta^S|_op + delta theta^S + Mesh2_O%Force(:,i) = Mesh2_O_op%Force(:,i) + LinVec_2(j:j+2) + + end do + + + !M( x^S|_op + delta x^S ) + call TransferLoadData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh1_I%nnodes + j = (i-1)*3 + 1 + LinVec_1(j:j+2) = Mesh1_I%Force(:,i) - Mesh1_I_op%Force(:,i) + end do + + call WrErrorLine('Forces', LinVec_1, LinVec_1_a, Mesh2_O_op%Force, LinVec_2) + + end do + write(*,*) ! blank line + + ! .................. + ! Moments: + ! .................. + + ! get max Moment : + mf=maxval( abs(Mesh2_O_op%Force ) ) + mm=maxval( abs(Mesh2_O_op%Moment ) ) + + call meshcopy( Mesh2_O_op, Mesh2_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh1_O_op, Mesh1_O, MESH_UPDATECOPY, ErrStat, ErrMsg) + + do n1=1,15 + + + call meshcopy( Mesh2_I_op, Mesh2_I, MESH_UPDATECOPY, ErrStat, ErrMsg) + call meshcopy( Mesh1_I_op, Mesh1_I, MESH_UPDATECOPY, ErrStat, ErrMsg) + + ! perturb x^S: + !...... + call getRandomVector(LinVec_2_b, max(1.0_ReKi,mf)) ! delta f + call getRandomVector(LinVec_2_c, max(1.0_ReKi,mm)) ! delta m + + ! for u and theta, we actually perturb x^D and transfer to x^S to get delta x^S + call getRandomVector(LinVec_1_b) !delta uD + call getRotationPerturb(LinVec_1_c) ! delta theta^D + +!LinVec_1_b = 0 + + ! get Mesh1_O (destination, perturbed) + + do i=1,Mesh1_O%nnodes + j = (i-1)*3 + 1 + ! bjj: we need translation to be consistent on transfered meshe + + ! Mesh2_I%TranslationDisp = u^S|_op + delta u^S + if (allocated(map_mod2_mod1%dm%M_uD)) Mesh1_O%TranslationDisp(:,i) = Mesh1_O_op%TranslationDisp(:,i) + LinVec_1_b(j:j+2) + + + ! Mesh2_I%Orientation = theta^S|_op + delta theta^S + call getLinearOrient(LinVec_1_c(j:j+2), Orientation) + Mesh1_O%Orientation(:,:,i) = matmul( Mesh1_O_op%Orientation(:,:,i), Orientation ) + end do + + call TransferMotionData() ! this sets Mesh2_I, the displaced source mesh + + ! now figure out what that means for the x^S perturbations: + + ! LinVec_2 for delta u^S + if (allocated(map_mod2_mod1%dm%M_uS)) then + do i=1,Mesh2_I%nnodes + j = (i-1)*3 + 1 + LinVec_2(j:j+2) = Mesh2_I%TranslationDisp(:,i) - Mesh2_I_op%TranslationDisp(:,i) + end do + else + LinVec_2 = 0 + end if + + ! ! LinVec_2_a for delta theta^S + !if (allocated(map_mod2_mod1%dm%M_uD)) then + ! do i=1,Mesh2_I%nnodes + ! j = (i-1)*3 + 1 + ! Orientation = matmul( transpose( Mesh2_I_op%Orientation(:,:,i) ), Mesh2_I%Orientation(:,:,i) ) + ! LinVec_2_a(j:j+2) = GetSmllRotAngs(Orientation,ErrStat,ErrMsg) + ! end do + !end if + !...... + + LinVec_1_a = matmul( map_mod2_mod1%dm%m_f, LinVec_2_b ) & ! approximate delta theta^D (after we add the u and t components on the next lines) + + matmul( map_mod2_mod1%dm%li, LinVec_2_c ) + + if (allocated(map_mod2_mod1%dm%M_uS)) LinVec_1_a = LinVec_1_a + matmul( map_mod2_mod1%dm%m_uS, LinVec_2 ) ! uS + if (allocated(map_mod2_mod1%dm%M_uD)) LinVec_1_a = LinVec_1_a + matmul( map_mod2_mod1%dm%M_uD, LinVec_1_b ) ! uD + + do i=1,Mesh2_O%nnodes + j = (i-1)*3 + 1 + ! bjj: we need orientation and translation to be consistent on same meshes as well as on transfered meshes; + ! so we need to actually perturb the destination and transfer to the source to get the source perturbations + + ! Mesh2_O%Force = Force^S|_op + delta Force^S + Mesh2_O%Force(:,i) = Mesh2_O_op%Force(:,i) + LinVec_2_b(j:j+2) + + ! Mesh2_O%Moment = Moment^S|_op + delta Moment^S + Mesh2_O%Moment(:,i) = Mesh2_O_op%Moment(:,i) + LinVec_2_c(j:j+2) + end do + + + + !M( x^S|_op + delta x^S ) + call TransferLoadData() + + ! delta x^D = M( x^S|_op + delta x^S ) - x^D|_op + do i=1,Mesh1_I%nnodes + j = (i-1)*3 + 1 + LinVec_1(j:j+2) = Mesh1_I%Moment(:,i) - Mesh1_I_op%Moment(:,i) + end do + + call WrErrorLine('Moments', LinVec_1, LinVec_1_a, Mesh2_O_op%Moment, LinVec_1_b, LinVec_2, LinVec_2_b, LinVec_2_c) + end do + +end if ! linearization or mapping test + + ! .............................................................................................................................. + ! Destroy data structures: + ! .............................................................................................................................. + + CALL MeshDestroy( mesh1_I, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh1_O, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_I, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_O, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshDestroy( mesh1_I_op, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh1_O_op, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_I_op, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshDestroy( mesh2_O_op, ErrStat, ErrMsg ); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + call MeshMapDestroy(Map_Mod1_Mod2, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + call MeshMapDestroy(Map_Mod2_Mod1, ErrStat, ErrMsg);IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + if (allocated(LinVec_1)) deallocate(LinVec_1) + if (allocated(LinVec_1_a)) deallocate(LinVec_1_a) + if (allocated(LinVec_1_b)) deallocate(LinVec_1_b) + if (allocated(LinVec_1_c)) deallocate(LinVec_1_c) + if (allocated(LinVec_1_d)) deallocate(LinVec_1_d) + if (allocated(LinVec_2)) deallocate(LinVec_2) + if (allocated(LinVec_2_a)) deallocate(LinVec_2_a) + if (allocated(LinVec_2_b)) deallocate(LinVec_2_b) + if (allocated(LinVec_2_c)) deallocate(LinVec_2_c) + + if (allocated(LinVec_2_tmp)) deallocate(LinVec_2_tmp) + if (allocated(LinVec_2_a_tmp)) deallocate(LinVec_2_a_tmp) + + end do + + + +END subroutine Test_TestMeshMapping + diff --git a/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping_Mod.f90 b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping_Mod.f90 new file mode 100644 index 000000000..c770a5ab6 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_MeshMapping/Test_MeshMapping_Mod.f90 @@ -0,0 +1,1738 @@ +module TestMeshMapping_Mod + + USE NWTC_Library + + implicit none + + TYPE(meshtype) :: mesh1_I, mesh1_O + TYPE(meshtype) :: mesh2_I, mesh2_O + + TYPE(meshtype) :: mesh1_I_op, mesh1_O_op + TYPE(meshtype) :: mesh2_I_op, mesh2_O_op + + + TYPE(MeshMapType) :: Map_Mod1_Mod2 ! Data for mapping meshes from mod1 to mod2 + TYPE(MeshMapType) :: Map_Mod2_Mod1 ! Data for mapping meshes from mod1 to mod2 + + REAL(R8Ki) :: Orientation(3,3), angles(3) + REAL(ReKi) :: position(3) + REAL(ReKi) :: Angle, e, mf, mm + + CHARACTER(*), PARAMETER :: Fmt = '(ES10.3E2)' + CHARACTER(*), PARAMETER :: ErrFmt = '(A28,i2,1x,F18.8,1x,F18.4,13(1x,F18.8))' + CHARACTER(*), PARAMETER :: ErrTxtFmt = '(A28,A2,15(1x,A18))' + + ! + INTEGER :: NNodes, I,J, n1, n2 + + INTEGER :: Mesh1Type + INTEGER :: Mesh2Type + + INTEGER(IntKi) :: ErrStat + CHARACTER(1024) :: ErrMsg + + logical :: debug_print = .false. + + + +contains + + ! .............................................. + subroutine getRotationPerturb(Vec) + real(reki), intent(inout) :: vec(:) + + real(reki) :: mx,mn + integer :: nq + + !call getRandomVector(Vec, 0.4_ReKi) + + call random_number( Vec ) + mx = maxval(Vec) + mn = minval(Vec) + + Vec = 0.4_ReKi*(2.*(Vec-mn)/(mx-mn)-1.)/real(n1**2) !note n1 from the loop this is called in + + do nq=2,size(Vec),3 + Vec(nq-1)=0 + Vec(nq+1)=0 + end do + + + !vec = 0.0_ReKi + + end subroutine getRotationPerturb + ! .............................................. + subroutine getRandomVector(Vec, InLimits) + real(reki), intent(inout) :: vec(:) + real(reki), intent(in ), optional :: InLimits + real(reki) :: Limits + + real(reki) :: mx,mn + + if (present(InLimits)) then + Limits = abs(InLimits) + if (EqualRealNos( Limits, 0.0_ReKi ) ) Limits = 1.0_ReKi + else + Limits = 1.0_ReKi + end if + + call random_number( Vec ) + mx = maxval(Vec) + mn = minval(Vec) + + Vec = Limits*(2.*(Vec-mn)/(mx-mn)-1.)/real(n1**3) !note n1 from the loop this is called in + !Vec = (Vec)/real(n1**3) !note n1 from the loop this is called in + + end subroutine getRandomVector + ! .............................................. + subroutine getLinearOrient(theta, Orientation) + real(reki), intent(in ) :: theta(3) + real(R8ki), intent(inout) :: Orientation(3,3) + + !call eye(Orientation,ErrStat,ErrMsg) + !Orientation = Orientation - SkewSymMat(theta) + + call SmllRotTrans( 'orientation', theta(1) & + , theta(2) & + , theta(3) & + , Orientation, ErrStat=ErrStat, ErrMsg=ErrMsg) + + + end subroutine getLinearOrient + ! .............................................. + subroutine WrErrorLine(Desc, Actual, Approx, DestField, DeltaS1, DeltaS2, DeltaS3, DeltaS4) + character(*), intent(in) :: Desc + real(reki) , intent(in) :: Actual(:) + real(reki) , intent(in) :: Approx(:) + real(reki) , intent(in) :: DestField(:,:) + real(reki) , intent(in) :: DeltaS1(:) + real(reki) , intent(in), optional :: DeltaS2(:) + real(reki) , intent(in), optional :: DeltaS3(:) + real(reki) , intent(in), optional :: DeltaS4(:) + + real(reki) :: MaxAbsErr, MaxRelErr + real(reki) :: AbsErr, RelErr, Denom + real(reki) :: v(3) + + integer(intki) :: i + REAL(ReKi), parameter :: mmin = 1D-7; !sqrt(epsilon(mmin)) !1D-7 ! + + + MaxAbsErr = 0.0_ReKi + MaxRelErr = 0.0_ReKi + + do i=1,size(Actual)-1,3 + v = Actual(i:i+2) - Approx(i:i+2) + AbsErr = TwoNorm( v ) + + v = Actual(i:i+2) + Denom = TwoNorm(v) + RelErr = AbsErr / max(mmin, Denom) + + if (AbsErr > MaxAbsErr) then + MaxAbsErr = max(MaxAbsErr,AbsErr) + + MaxRelErr = RelErr !jmj wants the relative error associated with the node with greatest absolute error + !MaxRelErr = max(MaxAbsErr,RelErr) + end if + + if (debug_print) then + call WrNumAryFileNR ( 58, (/ AbsErr /), 'ES15.8', ErrStat, ErrMsg ) + call WrNumAryFileNR ( 59, (/ RelErr /), 'ES15.8', ErrStat, ErrMsg ) + call WrNumAryFileNR ( 60, (/ Denom /), 'ES15.8', ErrStat, ErrMsg ) + end if + + end do + + if (debug_print) then + write( 58, *) + write( 59, *) + write( 60, *) + end if + + + !do i=1,size(Actual) + ! + ! AbsErr = abs(Actual(i) - Approx(i)) + ! if (AbsErr > MaxAbsErr) then + ! MaxAbsErr = max(MaxAbsErr,AbsErr) + ! + ! RelErr = AbsErr / max(mmin, Actual(i)) + ! + ! MaxRelErr = RelErr !jmj wants the relative error associated with the node with greatest absolute error + ! !MaxRelErr = max(MaxAbsErr,RelErr) + ! end if + ! + !end do + + MaxRelErr = MaxRelErr*100. + !note: n1 comes from loops where this is called (global variable)! + + if (present(DeltaS4)) then + write(*,ErrFmt) Desc//': ', n1, MaxAbsErr, MaxRelErr, maxval(abs(Actual)), maxval(abs(DestField)), maxval(abs(DeltaS1)), maxval(abs(DeltaS2)), maxval(abs(DeltaS3)), maxval(abs(DeltaS4)) + elseif (present(DeltaS3)) then + write(*,ErrFmt) Desc//': ', n1, MaxAbsErr, MaxRelErr, maxval(abs(Actual)), maxval(abs(DestField)), maxval(abs(DeltaS1)), maxval(abs(DeltaS2)), maxval(abs(DeltaS3)) + elseif (present(DeltaS2)) then + write(*,ErrFmt) Desc//': ', n1, MaxAbsErr, MaxRelErr, maxval(abs(Actual)), maxval(abs(DestField)), maxval(abs(DeltaS1)), maxval(abs(DeltaS2)) + else + write(*,ErrFmt) Desc//': ', n1, MaxAbsErr, MaxRelErr, maxval(abs(Actual)), maxval(abs(DestField)), maxval(abs(DeltaS1)) + end if + + + end subroutine + ! .............................................. + subroutine CreateOutputMeshes_Test1() + ! this is a point-to-point mapping, with one point going to many. + ! it is a figure in the AIAA paper. + + real(ReKi) :: dz + + Mesh1Type = ELEMENT_POINT + Mesh2Type = ELEMENT_POINT + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = 1 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshConstructElement ( mesh1_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 1.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + ! Angle = 0 + ! Angle = (20*j)*D2R + Angle = (20)*D2R + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,:,j) = GetDCM(Angle, 1) + + Mesh1_O%TranslationDisp(:,j) = (/ 2.00, 0., 0. /) + Mesh1_O%TranslationVel(:,j) = (/ 0.5, 0.0, 0.0 /) + Mesh1_O%RotationVel(:,j) = (/ 2.0, 0.0, 0.0 /) + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.115 + Mesh1_O%RotationAcc(:,j) = (/ 2.0, 0.0, 0.0 /) + + end do + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + + NNodes = 5 + dz = 1.0/(Nnodes-1) + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = (-25. + j*j)*D2R !note this "looks" like the transpose, but isn't + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, dz*(j-1) /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, & + Orient= Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshConstructElement ( mesh2_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + END DO + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 1.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ 1.0, 0., 0. /) !*(j*0.5) + Mesh2_O%Moment(:,j) = (/ 0.0, 0.5, 0.5 /)*(-j*0.0) + end do + + + end subroutine CreateOutputMeshes_Test1 + ! .............................................. + subroutine CreateOutputMeshes_Test2(ThisCase) + ! this is a line2-to-line2 mapping, with the same meshes in an upside-down "T" shape, though + ! one is discretized more than the other. + character(1), intent(in) :: ThisCase + real(reki) :: dx, dz + integer NumHorizNodes, NumVertNodes, ConnectionNode + REAL(ReKi), PARAMETER :: Len_Horiz = 4 + REAL(ReKi), PARAMETER :: Len_Vert = 2 + type(meshtype) :: rotateMesh + type(meshmaptype) :: rotateMesh_map + + + Mesh1Type = ELEMENT_LINE2 + Mesh2Type = ELEMENT_LINE2 + + !......................... + ! Mesh1 (Output: Motions) + !......................... + SELECT CASE (ThisCase) + CASE ('A') + NumHorizNodes = 9 + ConnectionNode = 5 + NumVertNodes = 8 + CASE ('B','C','D') + NumHorizNodes = 5 + ConnectionNode = 3 + NumVertNodes = 2 + END SELECT + + + Nnodes = NumHorizNodes + NumVertNodes !7 + dx = Len_Horiz/(NumHorizNodes-1) !1.0 + dz = Len_Vert/(NumVertNodes) !1.0 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + CALL PositionNodesElements(mesh1_O, NumHorizNodes, ConnectionNode, dx,dz,ErrStat,ErrMsg) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 2.") + + !.............. + ! initialize Mesh1 output fields: + !.............. + + !... temp mesh, for rotation only: + CALL MeshCreate(BlankMesh = RotateMesh & + , IOS = COMPONENT_OUTPUT & + , NNodes = 1 & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationVel = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + CALL MeshPositionNode(RotateMesh, 1, mesh1_O%Position(:,ConnectionNode), ErrStat=ErrStat, ErrMess=ErrMsg, & + Orient=mesh1_O%RefOrientation(:,:,ConnectionNode) ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshConstructElement ( RotateMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1 ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL MeshCommit ( RotateMesh, ErrStat, ErrMsg ) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + Angle = (15.)*D2R + !note this "looks" like the transpose, but isn't + RotateMesh%Orientation(:,1,1) = (/ COS(Angle) , -1.*SIN(Angle), 0.0_ReKi /) + RotateMesh%Orientation(:,2,1) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + RotateMesh%Orientation(:,3,1) = (/ 0.0, 0.0, 1.0 /) + RotateMesh%TranslationDisp(:,1) = (/ 1.00, 1.50, 0.00 /) + RotateMesh%TranslationVel( :,1) = (/ Pi, Pi, 0.00_ReKi /) *0.0 + RotateMesh%RotationVel( :,1) = (/ 0.00, 0.00, 0.5 /) + + CALL MeshMapCreate( RotateMesh, Mesh1_O, rotateMesh_map, ErrStat, ErrMsg) ; IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + CALL Transfer_Point_to_Line2( RotateMesh, Mesh1_O, rotateMesh_map, ErrStat, ErrMsg); IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + call MeshDestroy(rotateMesh,ErrStat,ErrMsg) + call MeshMapDestroy( rotateMesh_map,ErrStat,ErrMsg) + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + SELECT CASE (ThisCase) + CASE ('B') + NumHorizNodes = 9 + ConnectionNode = 5 + NumVertNodes = 8 + CASE ('A','C') + NumHorizNodes = 5 + ConnectionNode = 3 + NumVertNodes = 2 + CASE ('D') + NumHorizNodes = 3 + ConnectionNode = 2 + NumVertNodes = 2 + END SELECT + + + dx = Len_Horiz/(NumHorizNodes-1) !1/2 + dz = Len_Vert/(NumVertNodes) !1/4 + + Nnodes = NumHorizNodes + NumVertNodes !17 + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL PositionNodesElements(mesh2_O, NumHorizNodes, ConnectionNode, dx,dz,ErrStat,ErrMsg) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 2.") + + + !.............. + ! initialize Mesh2 output fields: + !.............. + + Mesh2_O%Force = 0.0 + Mesh2_O%Moment = 0.0 + + Mesh2_O%Force(3, 1: NumHorizNodes) = 1. + Mesh2_O%Force(1, ConnectionNode) = 0.5 + do j=NumHorizNodes+1,Mesh2_O%NNodes + Mesh2_O%Force(1, j) = (0.5*Mesh2_O%Position(3,j))**5 + Mesh2_O%Force(1, ConnectionNode) + end do + + + + return + end subroutine CreateOutputMeshes_Test2 + !------------------------------------------------------------------------------------------------- + subroutine PositionNodesElements(ThisMesh, NumHorizNodes, ConnectionNode, dx,dz,ErrStat,ErrMsg) + ! this positions nodes, creates elements, and committs the mesh for Test2 + + TYPE(MeshType), INTENT(INOUT) :: ThisMesh + real(reki), INTENT(IN) :: dx, dz + integer, INTENT(IN) :: NumHorizNodes, ConnectionNode + INTEGER(IntKi), INTENT(OUT) :: ErrStat + character(*), INTENT(OUT) :: ErrMsg + + integer :: j + + ! create a "T" + + ! position nodes: + + + ! horizontal line: + DO j=1,NumHorizNodes + position = (/dx*(j-ConnectionNode), 0.0_ReKi, 0.0_ReKi /) + CALL MeshPositionNode ( ThisMesh, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + + ! vertical line: + DO j=(NumHorizNodes+1),ThisMesh%Nnodes + position = (/0.0_ReKi, 0.0_ReKi, dz*(j-NumHorizNodes) /) + CALL MeshPositionNode ( ThisMesh, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + ! construct elements: + + + ! horizontal line: + do j=2,NumHorizNodes + CALL MeshConstructElement ( ThisMesh, ELEMENT_LINE2, ErrStat, ErrMsg, P1=j-1, P2=J ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + ! vertical line: + CALL MeshConstructElement ( ThisMesh, ELEMENT_LINE2, ErrStat, ErrMsg, P1=ConnectionNode, P2=NumHorizNodes+1 ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + DO j=(NumHorizNodes+2),ThisMesh%Nnodes + CALL MeshConstructElement ( ThisMesh, ELEMENT_LINE2, ErrStat, ErrMsg, P1=j-1, P2=j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + ! that's our entire mesh: + CALL MeshCommit ( ThisMesh, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("") + + end subroutine PositionNodesElements + !------------------------------------------------------------------------------------------------- + subroutine CreateOutputMeshes_Test5 + + real(reki) :: z + + + Mesh1Type = ELEMENT_LINE2 + Mesh2Type = ELEMENT_LINE2 + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = 6 + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1)/(Nnodes-1) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_LINE2, ErrStat, ErrMsg, J-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do + + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 3.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + !Angle = 0 + Angle = 0.5*Mesh1_O%Position(3,j) + + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,1,j) = (/ COS(Angle), 0.0_ReKi, 1.*SIN(Angle) /) + Mesh1_O%Orientation(:,2,j) = (/ 0.0, 1.0, 0.0 /) + Mesh1_O%Orientation(:,3,j) = (/-1.*SIN(Angle), 0.0_ReKi, COS(Angle) /) + + Mesh1_O%TranslationDisp(:,j) = (/ 2.*(1.0-COS(Angle)), 0._ReKi, 2.0*SIN(Angle)-Mesh1_O%Position(3,j) /) + + Mesh1_O%TranslationVel( :,j) = Mesh1_O%TranslationDisp(:,j)*1.5 + Mesh1_O%RotationVel(:,j) = (/ 0.0_ReKi, Angle, 0.0_ReKi /)*1.5 + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi + + end do + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = 8 + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = 30.*D2R !note this "looks" like the transpose, but isn't + !Angle = 0 + Orientation(:,1) = (/ COS(Angle), 0.0_ReKi, 1.*SIN(Angle) /) + Orientation(:,2) = (/ 0.0, 1.0, 0.0 /) + Orientation(:,3) = (/-1.*SIN(Angle), 0.0_ReKi, COS(Angle) /) + + ! place nodes in a line + z = (j-1.0)/(NNodes-1.0) + position = (/(sqrt(3.0)/3.0)*z-(sqrt(3.0)/6.0), 0.0_ReKi, z /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, & + Orient= Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_LINE2, ErrStat, ErrMsg, J-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 1.") + + !.............. + ! initialize output fields: + !.............. + ! This is done in another subroutine + + !do j=1,Mesh2_O%NNodes + ! Mesh2_I%Orientation(:,:,j) + ! + ! Mesh2_O%Force( :,j) = Mesh2_I%Orientation(:,1,j)*5 + ! Mesh2_O%Moment(:,j) = 0.0 ! (/ 0.0, 0.0, 0.5 /)*(-j*0.0) + !end do + + + + end subroutine CreateOutputMeshes_Test5 + subroutine InitTest5Loads() + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = Mesh2_I%Orientation(1,:,j)*0.75 + Mesh2_O%Moment(:,j) = 0.0 ! (/ 0.0, 0.0, 0.5 /)*(-j*0.0) + end do + + end subroutine InitTest5Loads + subroutine CreateOutputMeshes_Test5Orient + + real(reki) :: z + real(r8ki) :: DCM(3,3) + + + Mesh1Type = ELEMENT_LINE2 + Mesh2Type = ELEMENT_LINE2 + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes =5 !100 !100 !5 + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1)/(Nnodes-1) /) + + !CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg, orient=orientation ) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + !do j=1,NNodes + ! CALL MeshConstructElement ( mesh1_O, Mesh1Type, ErrStat, ErrMsg, j ) + ! IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + !end do + + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, Mesh1Type, ErrStat, ErrMsg, J-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do + + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 3.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + !Angle = 0 + !Angle = 0.5* Mesh1_O%Position(3,j) !28.6479 + Angle = 45.0_ReKi*Mesh1_O%Position(3,j)*D2R + Mesh1_O%Orientation(:,:,j) = GetDCM(Angle,2) + + Mesh1_O%TranslationDisp(:,j) = (/ 2.*(1.0-COS(Angle)), 0._ReKi, 2.0*SIN(Angle)-Mesh1_O%Position(3,j) /) + + Mesh1_O%TranslationVel( :,j) = Mesh1_O%TranslationDisp(:,j)*1.5 + Mesh1_O%RotationVel(:,j) = (/ 0.0_ReKi, Angle, 0.0_ReKi /)*1.5 + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi + + end do + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = 8 !105 ! + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = 30.*D2R !note this "looks" like the transpose, but isn't + DCM = GetDCM(Angle,2) + + ! place nodes in a line + z = (j-1.0)/(NNodes-1.0) + position = (/(sqrt(3.0)/3.0)*z-(sqrt(3.0)/6.0), 0.0_ReKi, z /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, Orient=DCM ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + !do j=1,NNodes + ! CALL MeshConstructElement ( mesh2_O, Mesh2Type, ErrStat, ErrMsg, J ) + ! IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + !end do + + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, Mesh2Type, ErrStat, ErrMsg, J-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do + + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 1.") + + !.............. + ! initialize output fields: + !.............. + ! This is done in another subroutine + + !do j=1,Mesh2_O%NNodes + ! Mesh2_I%Orientation(:,:,j) + ! + ! Mesh2_O%Force( :,j) = Mesh2_I%Orientation(:,1,j)*5 + ! Mesh2_O%Moment(:,j) = 0.0 ! (/ 0.0, 0.0, 0.5 /)*(-j*0.0) + !end do + + + + end subroutine CreateOutputMeshes_Test5Orient + ! .............................................. + subroutine CreateOutputMeshes_Test6() + + REAL(reKi) :: dx + + + Mesh1Type = ELEMENT_POINT + Mesh2Type = ELEMENT_LINE2 + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = 1 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshConstructElement ( mesh1_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 4.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + Angle = 0 + ! Angle = (20*j)*D2R + Angle = (20)*D2R + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,1,j) = (/ 1.0, 0.0 , 0.0 /) + Mesh1_O%Orientation(:,2,j) = (/ 0.0_ReKi, COS(Angle), -1.*SIN(Angle) /) + Mesh1_O%Orientation(:,3,j) = (/ 0.0_ReKi, SIN(Angle), COS(Angle) /) + + Mesh1_O%TranslationDisp(:,j) = (/ 2.00, 0., 0. /) + Mesh1_O%TranslationVel(:,j) = (/ 0.5, 0.0, 0.0 /) + Mesh1_O%RotationVel(:,j) = (/ 2.0, 0.0, 0.0 /) + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.115 + Mesh1_O%RotationAcc(:,j) = (/ 2.0, 0.0, 0.0 /) + + end do + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + + NNodes = 5 + dx = 0.25 + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = (-25. + j*j)*D2R !note this "looks" like the transpose, but isn't + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, dx*(j-1) /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, & + Orient= Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1,j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 4.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ Nnodes / (dx*(Nnodes-1)), 0.0_ReKi, 0.0_ReKi /) + Mesh2_O%Moment(:,j) = 0.0 + end do + + + end subroutine CreateOutputMeshes_Test6 + ! .............................................. + subroutine CreateOutputMeshes_Test7(ThisCase) + + character(1), intent(in) :: ThisCase + integer, parameter :: Nnodes = 10 + + SELECT CASE (ThisCase) + CASE ('A') + Mesh1Type = ELEMENT_POINT + Mesh2Type = ELEMENT_LINE2 + CASE ('B') + Mesh1Type = ELEMENT_LINE2 + Mesh2Type = ELEMENT_POINT + END SELECT + + CALL CreateTest7_Motions(Mesh1Type,Nnodes) + CALL CreateTest7_Loads(Mesh2Type) + + + end subroutine CreateOutputMeshes_Test7 + ! .............................................. + subroutine CreateTest7_Motions(MeshType,Nnodes) + + INTEGER, INTENT(IN) :: MeshType + INTEGER, INTENT(IN) :: Nnodes + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + IF (MeshType == ELEMENT_POINT) THEN + do j=1,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + ELSEIF (MeshType == ELEMENT_LINE2) THEN + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1,j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + END IF + + + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 5.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + Angle = 0 + ! Angle = (20*j)*D2R + ! Angle = (20)*D2R + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,1,j) = (/ 1.0, 0.0 , 0.0 /) + Mesh1_O%Orientation(:,2,j) = (/ 0.0_ReKi, COS(Angle), -1.*SIN(Angle) /) + Mesh1_O%Orientation(:,3,j) = (/ 0.0_ReKi, SIN(Angle), COS(Angle) /) + + Mesh1_O%TranslationDisp(:,j) = (/ 2., 0., 0. /) + Mesh1_O%TranslationVel(:,j) = (/ 2., 0.0, 0.0 /) + Mesh1_O%RotationVel(:,j) = 0.0_ReKi + Mesh1_O%TranslationAcc(:,j) = (/ -1., 0.0, 0.0 /) + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi + + end do + + + + end subroutine CreateTest7_Motions + ! .............................................. + subroutine CreateTest7_Loads(MeshType) + + INTEGER, INTENT(IN) :: MeshType + integer :: nnodes + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = mesh1_O%Nnodes + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + ! place nodes in a line + CALL MeshPositionNode ( mesh2_O, j, mesh1_O%Position(:,j), ErrStat, ErrMsg, & + Orient= mesh1_O%RefOrientation(:,:,j) ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + + + IF (MeshType == ELEMENT_POINT) THEN + do j=1,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + ELSEIF (MeshType == ELEMENT_LINE2) THEN + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1,j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + END IF + + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 5.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ 1.0, 0.0, 0.0 /) + Mesh2_O%Moment(:,j) = 0.0 + end do + + END subroutine CreateTest7_Loads + ! .............................................. + subroutine CreateOutputMeshes_Test9 + + Mesh1Type = ELEMENT_Line2 + Mesh2Type = ELEMENT_POINT + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = 2 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi*(j-1) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 9.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + Angle = 0 + ! Angle = (20*j)*D2R + ! Angle = (20)*D2R + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,1,j) = (/ 1.0, 0.0 , 0.0 /) + Mesh1_O%Orientation(:,2,j) = (/ 0.0_ReKi, COS(Angle), -1.*SIN(Angle) /) + Mesh1_O%Orientation(:,3,j) = (/ 0.0_ReKi, SIN(Angle), COS(Angle) /) + + Mesh1_O%TranslationVel(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.5 + Mesh1_O%RotationVel(:,j) = 0.0_ReKi ! (/ 0., 0.5, 0.5 /)*.5 + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.115 + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 1. /)*.115 + + Mesh1_O%TranslationDisp(:,J) = 0.0_ReKi !(/ 2., 0., 0. /) + + end do + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = 1 + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = 0 + !Angle = (-25. + j*j)*D2R !note this "looks" like the transpose, but isn't + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + ! place nodes in a line + position = (/0.25_ReKi, 0.5_ReKi, 1.0_ReKi*(j-1) + 0.25 /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, & + Orient= Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshConstructElement ( mesh2_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + END DO + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 9.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ 0.6, 1.,-0.5 /) !*(j*0.5) + Mesh2_O%Moment(:,j) = (/ 4.0, 0.1, 0.3 /) + end do + + + END subroutine CreateOutputMeshes_Test9 + + ! .............................................. + subroutine CreateOutputMeshes_Test10 + ! monopile case: + real(ReKi),parameter :: z1(5)=(/ 10., -12.5000743865967, -5.00004959106445, 2.49997520446777, -20.0000991821289/) + real(ReKi),parameter :: z2(6)=(/-20.0000991821289, 10., -20. ,0., -20., 0./) + + Mesh1Type = ELEMENT_POINT + Mesh2Type = ELEMENT_POINT + + + !......................... + ! Mesh1 (Output: Motions) i.e., subdyn's y2 mesh + !......................... + + Nnodes = size(z1) + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, z1(j) /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + do j=1,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 10.") + + !.............. + ! initialize output fields: + !.............. + + ! node 1: + Mesh1_O%Orientation(1,:,1)=(/ 1.000000000000000, -0.000000000011870, 0.000000005946981/) + Mesh1_O%Orientation(2,:,1)=(/ 0.000000000011870, 0.999999880790710, 0.000000000735951/) + Mesh1_O%Orientation(3,:,1)=(/-0.000000005946981, -0.000000000735951, 1.000000000000000/) + + ! node 2: + Mesh1_O%Orientation(1,:,2)=(/ 1.000000000000000, 0.000000000001336, -0.000000006893778/) + Mesh1_O%Orientation(2,:,2)=(/-0.000000000001336, 1.000000000000000, 0.000000000002210/) + Mesh1_O%Orientation(3,:,2)=(/ 0.000000006893778, -0.000000000002210, 1.000000000000000/) + + ! node 3: + Mesh1_O%Orientation(1,:,3)=(/ 1.000000000000000, 0.000000000001093, 0.000000012251162/) + Mesh1_O%Orientation(2,:,3)=(/-0.000000000001093, 1.000000000000000, 0.000000000027043/) + Mesh1_O%Orientation(3,:,3)=(/-0.000000012251162, -0.000000000027043, 1.000000000000000/) + + ! node 4: + Mesh1_O%Orientation(1,:,4)=(/ 1.000000000000000, 0.000000000007391, -0.000000013338419/) + Mesh1_O%Orientation(2,:,4)=(/-0.000000000007391, 1.000000000000000, 0.000000000005140/) + Mesh1_O%Orientation(3,:,4)=(/ 0.000000013338419, -0.000000000005140, 1.000000000000000/) + + ! node 5: + Mesh1_O%Orientation(1,:,5)=(/ 1.0, 0.0, 0.0 /) + Mesh1_O%Orientation(2,:,5)=(/ 0.0, 1.0, 0.0 /) + Mesh1_O%Orientation(3,:,5)=(/ 0.0, 0.0, 1.0 /) + + + do i=1,4 + print *, 'DCM * DCM^T ', i + call wrmatrix( MATMUL( Mesh1_O%Orientation(:,:,1) , TRANSPOSE( Mesh1_O%Orientation(:,:,1) ) ),cu,'f15.5' ) + END DO + + + Mesh1_O%TranslationDisp(:,1) = (/ 2.37597159724601e-08, 2.38855668577287e-09,-0.000899768609087914 /) + Mesh1_O%TranslationDisp(:,2) = (/-4.48765788974015e-08,-2.53428389385135e-11,-0.000226117306738161 /) + Mesh1_O%TranslationDisp(:,3) = (/-6.85023735513823e-08,-1.91699989215977e-11,-0.000451665051514283 /) + Mesh1_O%TranslationDisp(:,4) = (/-7.33556220211540e-08,-1.62197810738007e-10,-0.000676169584039599 /) + Mesh1_O%TranslationDisp(:,5) = (/ 0, 0, 0 /) + + Mesh1_O%TranslationVel(:,1) = (/ 9.30248279473744e-05, 9.57865177042550e-06, 0.000917342957109213 /) + Mesh1_O%TranslationVel(:,2) = (/-0.000179907845449634,-6.50597939966247e-08,-0.00444589508697391 /) + Mesh1_O%TranslationVel(:,3) = (/-0.000275392638286576, 1.26055965665728e-09,-0.00660990970209241/) + Mesh1_O%TranslationVel(:,4) = (/-0.000295042205834761,-5.36239895154722e-07,-0.00463324552401900/) + Mesh1_O%TranslationVel(:,5) = (/ 0, 0, 0 /) + + Mesh1_O%RotationVel(:,1) = (/2.96345683636901e-06,-2.34051149163861e-05,-5.91553508400011e-08 /) + Mesh1_O%RotationVel(:,2) = (/4.80349626741372e-09, 2.67697760136798e-05, 2.29704255616525e-09 /) + Mesh1_O%RotationVel(:,3) = (/1.04646687759669e-07,-4.83136973343790e-05,-1.12983400413214e-09 /) + Mesh1_O%RotationVel(:,4) = (/2.53845655606710e-08, 5.26454241480678e-05, 2.01115391007534e-08/) + Mesh1_O%RotationVel(:,5) = (/ 0, 0, 0 /) + + Mesh1_O%TranslationAcc(:,1) = (/ 0.172380834817886, 0.0190481301397085, 1.77754533290863 /) + Mesh1_O%TranslationAcc(:,2) = (/-0.362261772155762,-5.16042709932663e-05, -8.71160507202148 /) + Mesh1_O%TranslationAcc(:,3) = (/-0.560356795787811, 0.000119802658446133,-12.8353881835938 /) + Mesh1_O%TranslationAcc(:,4) = (/-0.600724101066589,-0.000828713586088270, -8.91974353790283 /) + Mesh1_O%TranslationAcc(:,5) = (/ 0, 0, 0 /) + + Mesh1_O%RotationAcc(:,1) = (/ 0.00601908657699823, -0.0441803149878979, -0.000328276102663949/) + Mesh1_O%RotationAcc(:,2) = (/ 4.16704733652296e-06, 0.0473403967916966, 4.39332507085055e-06/) + Mesh1_O%RotationAcc(:,3) = (/ 0.000204067997401580,-0.0911907851696014, -1.95350694411900e-05/) + Mesh1_O%RotationAcc(:,4) = (/ 7.36967340344563e-05, 0.0997802764177322, 7.97090106061660e-05/) + Mesh1_O%RotationAcc(:,5) = (/ 0, 0, 0 /) + + + +! test: +CALL EYE(Mesh1_O%Orientation,ErrStat,ErrMsg) +Mesh1_O%RotationAcc = 0 +Mesh1_O%TranslationAcc = 0 +Mesh1_O%RotationVel = 0 +Mesh1_O%TranslationVel = 0 +Mesh1_O%TranslationDisp = 0 + + !......................... + ! Mesh2 (Output: Loads) i.e., HydroDyn's morision lumped mesh + !......................... + + NNodes = size(z2) + + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, z2(j) /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + CALL MeshConstructElement ( mesh2_O, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 10.") + + !.............. + ! initialize output fields: + !.............. + Mesh2_O%Moment = 0.0 + Mesh2_O%Force = 0.0 + Mesh2_O%Force(3,3:6) = (/5431999., 274118.281250000, -5431999., -274118.281250000/) + !Mesh2_O%Force(3,3:6) = (/5431999., 274118.281250000, -5431999., -274118.281250000/) / 1000.0_ReKi + + + END subroutine CreateOutputMeshes_Test10 + ! .............................................. + subroutine CreateOutputMeshes_Test11 + + + + Mesh1Type = ELEMENT_Line2 + Mesh2Type = ELEMENT_Line2 + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = 10 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + do j=1,NNodes + ! place nodes in a line + position = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi /) + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + mesh1_O%Position(3,:) = (/0., 0.5, 1.5, 2., 4., 4.1, 5., 8., 8.5, 10. /) + + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 11.") + + !.............. + ! initialize output fields: + !.............. + + do j=1,Mesh1_O%NNodes + + Angle = 0 + ! Angle = (20*j)*D2R + ! Angle = (20)*D2R + !note this "looks" like the transpose, but isn't + Mesh1_O%Orientation(:,1,j) = (/ 1.0, 0.0 , 0.0 /) + Mesh1_O%Orientation(:,2,j) = (/ 0.0_ReKi, COS(Angle), -1.*SIN(Angle) /) + Mesh1_O%Orientation(:,3,j) = (/ 0.0_ReKi, SIN(Angle), COS(Angle) /) + + Mesh1_O%TranslationVel(:,j) = (/ 1., 0., 0. /) + Mesh1_O%RotationVel(:,j) = 0.0_ReKi ! (/ 0., 0.5, 0.5 /)*.5 + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.115 + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 1. /)*.115 + + Mesh1_O%TranslationDisp(:,J) = 0.0_ReKi !(/ 2., 0., 0. /) + + end do + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = 7 + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + do j=1,NNodes + + Angle = 0 + !Angle = (-25. + j*j)*D2R !note this "looks" like the transpose, but isn't + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + ! place nodes in a line + position = (/0._ReKi, 0._ReKi, (j-1)*10.0_ReKi/(Nnodes-1) /) + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, & + Orient= Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + + + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 11.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ 0.0, 1.0, 0.0 /) + Mesh2_O%Moment(:,j) = (/ 0.0, 0.0, 0.0 /) + end do + + + END subroutine CreateOutputMeshes_Test11 + ! .............................................. + subroutine CreateOutputMeshes_Test13 + real(reki),parameter :: a = 1. + real(reki),parameter :: omega=2. + real(reki) :: L, LineLen + real(reKi) :: x, dx, yp, omega2, a2 + + real(reKi),parameter :: xAry1_disp(11) = (/ & + 0.00000000000000_DbKi, 0.51960358494079_DbKi, 1.05066474308880_DbKi, 1.58938188333378_DbKi, 2.12044304148178_DbKi, 2.64004662642258_DbKi, 3.15959741148684_DbKi, 3.69065856963484_DbKi, 4.22937570987983_DbKi, 4.76043686802783_DbKi, 5.27998765309209_DbKi /) + + real(reKi),parameter :: xAry1(11) = (/ & + 0.00000000000000_DbKi, 0.24325351916746_DbKi, 0.55141234255808_DbKi, 1.01941540016335_DbKi, 1.32757422355397_DbKi, 1.57082774272143_DbKi, 1.81404984596235_DbKi, 2.12220866935298_DbKi, 2.59021172695825_DbKi, 2.89837055034887_DbKi, 3.14159265358979_DbKi /) + real(reKi),parameter :: xAry2(31) = (/ & + 0.00000000000000_DbKi, 0.07885397560510_DbKi, 0.15927874753700_DbKi, 0.24325351916746_DbKi, 0.33329156461934_DbKi, 0.43357120212193_DbKi, 0.55141234255808_DbKi, 0.69925569283602_DbKi, 0.87157204988542_DbKi, 1.01941540016335_DbKi, 1.13725654059951_DbKi, 1.23753617810209_DbKi, 1.32757422355397_DbKi, 1.41154899518443_DbKi, 1.49197376711633_DbKi, 1.57082774272143_DbKi, 1.64965030240000_DbKi, 1.73007507433190_DbKi, 1.81404984596235_DbKi, 1.90408789141424_DbKi, 2.00436752891682_DbKi, 2.12220866935298_DbKi, 2.27005201963091_DbKi, 2.44236837668031_DbKi, 2.59021172695825_DbKi, 2.70805286739440_DbKi, 2.80833250489699_DbKi, 2.89837055034887_DbKi, 2.98234532197933_DbKi, 3.06277009391123_DbKi, 3.14159265358979_DbKi /) + + Mesh1Type = ELEMENT_Line2 + Mesh2Type = ELEMENT_Line2 + + + !......................... + ! Mesh1 (Output: Motions) + !......................... + + Nnodes = size(xAry1) !11 + + CALL MeshCreate( BlankMesh = mesh1_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Orientation = .TRUE. & + , TranslationDisp = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + L = TwoPi/omega + dx = L/(NNodes-1.0_ReKi) + do j=1,NNodes + ! place nodes in a line + x = xAry1(j) !(j-1.0_ReKi) * dx + yp = a*omega*cos(omega*x) + position = (/x, a*sin(omega*x), 0.0_ReKi /) + Angle = atan(yp) + + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) +!call wrmatrix(orientation,cu,'f15.5','mesh1 '//trim(num2lstr(j))//' '//trim(num2lstr(angle))) + + CALL MeshPositionNode ( mesh1_O, j, position, ErrStat, ErrMsg, orient=Orientation ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + END DO + + do j=2,NNodes + CALL MeshConstructElement ( mesh1_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + CALL MeshCommit ( mesh1_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh1 output for test 13.") + +! LineLen = 0; +! do j=1,mesh1_O%ElemTable(ELEMENT_Line2)%nelem +! LineLen = LineLen + mesh1_O%ElemTable(ELEMENT_Line2)%Elements(j)%det_jac*2 +! end do +! +!print *, 'length of line is =', LineLen +LineLen = 5.27038 + + !.............. + ! initialize output fields: + !.............. + + omega2 = 1.19 !0.5*omega + a2 = 0.25*a !2*a ! + L = TwoPi/omega2 + dx = L/(NNodes-1.0_ReKi) + + do j=1,Mesh1_O%NNodes + + x = xAry1_disp(j) !(j-1.0_ReKi) * dx + yp = a2*omega2*cos(omega2*x) + position = (/x, a2*sin(omega2*x), 0.0_ReKi /) + Mesh1_O%TranslationDisp(:,J) = position - Mesh1_O%Position(:,j) + +!print *,j, Mesh1_O%TranslationDisp(:,J) + + Angle = atan(yp) + + Mesh1_O%Orientation(:,1,j) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Mesh1_O%Orientation(:,2,j) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Mesh1_O%Orientation(:,3,j) = (/ 0., 0.0, 1.0 /) + + Mesh1_O%TranslationVel(:,j) = (/ 0., 0., 0. /) + Mesh1_O%RotationVel(:,j) = 0.0_ReKi ! (/ 0., 0.5, 0.5 /)*.5 + Mesh1_O%TranslationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 0. /)*.115 + Mesh1_O%RotationAcc(:,j) = 0.0_ReKi ! (/ 1., 1., 1. /)*.115 + + + end do + +!Mesh1_O%TranslationDisp = 0.0_ReKi +!Mesh1_O%Orientation = Mesh1_O%RefOrientation + + + + !......................... + ! Mesh2 (Output: Loads) + !......................... + + NNodes = size(xAry2) !31 !19 + L = TwoPi/omega + dx = L/(NNodes-1.0_ReKi) + CALL MeshCreate( BlankMesh = mesh2_O & + , IOS = COMPONENT_OUTPUT & + , NNodes = NNodes & + , Force = .TRUE. & + , Moment = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + + + do j=1,NNodes + ! place nodes in a line + x = xAry2(j) !(j-1.0_ReKi) * dx + yp = a*omega*cos(omega*x) + position = (/x, a*sin(omega*x), 0.0_ReKi /) + Angle = atan(yp) + + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg, Orient= Orientation ) + + !CALL MeshPositionNode ( mesh2_O, j, position, ErrStat, ErrMsg ) + + + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + do j=2,NNodes + CALL MeshConstructElement ( mesh2_O, ELEMENT_LINE2, ErrStat, ErrMsg, j-1, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + end do ! + + + ! that's our entire mesh: + CALL MeshCommit ( mesh2_O, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + if (ErrStat >= AbortErrLev) CALL ProgAbort("Error creating Mesh2 output for test 11.") + + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = (/ 0.0, 0.5, 0.0 /) + Mesh2_O%Moment(:,j) = (/ 0.0, 0.0, 0.0 /) + end do + + + END subroutine CreateOutputMeshes_Test13 + + subroutine InitTest13Loads() + !.............. + ! initialize output fields: + !.............. + do j=1,Mesh2_O%NNodes + Mesh2_O%Force( :,j) = Mesh2_I%Orientation(2,:,j)*0.5 ! (/ 0.0_reKi, Mesh2_I%Orientation(2,2,j)*0.5, 0.0_ReKi /) + Mesh2_O%Moment(:,j) = 0.0 ! (/ 0.0, 0.0, 0.5 /)*(-j*0.0) + end do + end subroutine InitTest13Loads + + ! .............................................. + SUBROUTINE TestOrientations() + + real(reKi) :: DCM(3,3) + real(reKi) :: angles(3), da, astart + !REAL(ReKi), parameter :: da = 4.0 ! degrees + integer :: k + + NNodes = 15 + astart = -180.0_ReKi + + da=abs(astart)*2.0_ReKi/(NNodes-1) + + do i=1,NNodes + angles(1) = (astart + da*(i-1) )*D2R + do j = 1,NNodes + angles(2) = (astart + da*(j-1) )*D2R + do k = 1,NNodes + angles(3) = (astart + da*(k-1) )*D2R + + + CALL SmllRotTrans( 'Mesh Orientation Extrapolation', angles(1), angles(2), angles(3), DCM, 'angle='//trim(num2lstr(angles(1))), ErrStat, ErrMsg ) +write(75,'(I10,2(1x,I10),15(1x,F15.5))') i,j,k, angles, DCM + + DCM = DCM_exp ( angles ) +write(76,'(I10,2(1x,I10),15(1x,F15.5))') i,j,k, angles, DCM + end do + end do + END DO + + close(75) + close(76) + + END SUBROUTINE TestOrientations + + function GetDCM( angle, dim ) + + REAL(ReKi), intent(in) :: angle + REAL(ReKi) :: GetDCM(3,3) + integer(IntKi), intent(in) :: dim + + + ! note that these look like the transpose of the matrix, but each line is a column + select case (dim) + case( 1 ) + GetDCM(:,1) = (/ 1.0, 0.0 , 0.0 /) + GetDCM(:,2) = (/ 0.0_ReKi, COS(Angle), -1.*SIN(Angle) /) + GetDCM(:,3) = (/ 0.0_ReKi, SIN(Angle), COS(Angle) /) + case (2) + GetDCM(:,1) = (/ COS(Angle), 0.0_ReKi, 1.*SIN(Angle) /) + GetDCM(:,2) = (/ 0.0, 1.0, 0.0 /) + GetDCM(:,3) = (/-1.*SIN(Angle), 0.0_ReKi, COS(Angle) /) + case (3) + Orientation(:,1) = (/ COS(Angle), -1.*SIN(Angle), 0.0_ReKi /) + Orientation(:,2) = (/ SIN(Angle), COS(Angle), 0.0_ReKi /) + Orientation(:,3) = (/ 0., 0.0, 1.0 /) + + end select + + + end function GetDCM + ! .............................................. + + subroutine TransferMotionData() + + IF (Mesh1Type == ELEMENT_POINT ) THEN + IF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Point_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); + ELSEIF ( Mesh2Type == ELEMENT_LINE2) THEN + CALL Transfer_Point_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); + END IF + ELSEIF ( Mesh1Type == ELEMENT_LINE2 ) THEN + IF ( Mesh2Type == ELEMENT_LINE2 ) THEN + CALL Transfer_Line2_to_Line2( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ); + ELSEIF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Line2_to_Point( Mesh1_O, Mesh2_I, Map_Mod1_Mod2, ErrStat, ErrMsg ) + END IF + END IF + IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end subroutine TransferMotionData + + subroutine TransferLoadData() + + IF (Mesh1Type == ELEMENT_POINT ) THEN + IF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Point_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ) + ELSEIF ( Mesh2Type == ELEMENT_LINE2) THEN + CALL Transfer_Line2_to_Point( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ) + END IF + ELSEIF ( Mesh1Type == ELEMENT_LINE2 ) THEN + IF ( Mesh2Type == ELEMENT_LINE2 ) THEN + CALL Transfer_Line2_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ) + ELSEIF ( Mesh2Type == ELEMENT_POINT ) THEN + CALL Transfer_Point_to_Line2( Mesh2_O, Mesh1_I, Map_Mod2_Mod1, ErrStat, ErrMsg, Mesh2_I, Mesh1_O ) + END IF + END IF + IF (ErrStat /= ErrID_None) CALL WrScr("*******"//TRIM(ErrMsg)) + + end subroutine TransferLoadData + +end module TestMeshMapping_Mod + diff --git a/OpenFAST/modules/nwtc-library/test/Test_NWTC_Library.f90 b/OpenFAST/modules/nwtc-library/test/Test_NWTC_Library.f90 new file mode 100644 index 000000000..9583ef435 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_NWTC_Library.f90 @@ -0,0 +1,583 @@ +!********************************************************************************************************************************** +! +! PROGRAM: Test_NWTC_Library +! +! PURPOSE: Tests the functionality of the NWTC Subroutine Library using IVF for Windows. +! +! TESTED ROUTINES: +! NWTC_Init +! WrScr +! WrScr1 +! Num2LStr: Int2LStr, R2LStr16 +! TESTED DATA/PARAMETERS: +! QuKi +! + +!********************************************************************************************************************************** + +PROGRAM Test_NWTC_Library + + USE NWTC_Library + USE NWTC_LAPACK + + + IMPLICIT NONE + + + + ! Variables + + ! IVF for Windows hard-coded kinds + + REAL(16) :: Real16Var ! a 16-byte real variable + REAL(8) :: Real8Var ! an 8-byte real variable + REAL(4) :: Real4Var ! a 4-byte real variable + + ! Type-specific Library kinds + + REAL(QuKi) :: RealQuVar ! a 16-byte real variable + REAL(R8Ki) :: RealR8Var ! an 8-byte real variable + REAL(SiKi) :: RealSiVar ! a 4-byte real variable + + ! Default kinds from Library + + REAL(ReKi) :: RealReVar ! a default real variable (different in SingPrec.f90 or DoubPrec.f90) + REAL(DbKi) :: RealDbVar ! a default double variable (different in SingPrec.f90 or DoubPrec.f90) + + + REAL(ReKi), ALLOCATABLE :: RealReAry(:) + + ! File name + CHARACTER(1024) :: InputFileName = 'TestData/TestLibrary_InputFile.txt' + + INTEGER(IntKi) :: ErrStat + CHARACTER(1024) :: ErrMsg + + + INTEGER(IntKi), ALLOCATABLE :: TempVec(:,:) + INTEGER(IntKi), ALLOCATABLE :: IC(:) + integer,parameter :: NMX = 9 + integer :: i, j, k, i4 + + integer, parameter:: m=5 + integer, parameter:: n=5 + double precision :: a(m,n), b(n) + integer :: ipiv(m) + + type(meshtype) :: mesh1, mesh2, mesh3 + + + integer,parameter :: ndims=10 + real(reki),dimension(ndims,3) :: vec1, vec2 + real(reki),dimension(3,ndims) :: vec11, vec21 + real(reki),dimension(3) :: vec3 + + REAL time_begin, time_end + + + integer,parameter :: nx=1, ny=1, nz=2, n4=1 + complex(ReKi) :: data2d(nx,nz), data3d(nx,nz,n4) , data4d(nx,ny,nz,n4) ,interpVal + real(reki) :: x(nx), y(ny), z(nz), w(n4), InCoord2(2), InCoord(3), InCoord4(4) + integer :: LastIndex(3) = 0, LastIndex4(4) = 0, LastIndex2(2) = 0 + !............................................................................................................................... + ! Initialize the library + !............................................................................................................................... + + CALL NWTC_Init( ) + + !print *, sqrt(epsilon(1.0_ReKi)), sqrt(epsilon(1.0_SiKi)), sqrt(epsilon(1.0_R8Ki)) + !stop + + call Test_TestMeshMapping() + stop + + !............................................................................................................................... + ! arrays for interpolation: + +#ifdef WAMIT_INTERPOLATION + + do i=1,n4 + w(i) = -120 + (i-1) * 200/max(1,n4-1) + end do + + do i=1,nz + z(i) = -180 + (i-1) * 90/max(1,nz-1) + end do + + do i=1,ny + y(i) = -10 + (i-1)*20 + end do + + do i=1,nx + x(i) = (i-1)*10 + end do + + !............................................................................................................................... + ! 2d interpolation: + +print *, x +print *, z + + data2d = 0.0_ReKi + do j =1,nz + do i =1,nx + data2d(i,j) = (j-1)*nx + i + end do + end do + + do j =1,nz + do i =1,nx + InCoord2(1) = x(i) + InCoord2(2) = z(j) + 45 + + call WAMIT_Interp2D_Cplx( InCoord2, data2d, x, z, LastIndex2, interpVal, ErrStat, ErrMsg ) + +!if ( .not. equalrealnos( REAL(data2d(i,j)), REAL(interpVal) ) .or. & +! .not. equalrealnos( IMAG(data2d(i,j)), IMAG(interpVal) ) ) then +!print *, '----------------- not equal ---------------------------------------------------' +print *, '**** ', i, j, ' ****' +print *, '' +print *, 'input value:', InCoord2 + +print *, 'data at point:', data2d(i,j) +print *, 'interp data :', interpVal +print *, '-------------------------------------------------------------------------------' +!end if + + end do + end do + + + !............................................................................................................................... + ! 3d interpolation: + + data3d = 0.0_ReKi + do k=1,n4 + do j =1,nz + do i =1,nx + data3d(i,j,k) = (k-1)*(nx*nz) + (j-1)*nx + i + end do + end do + end do + + do k=1,n4 + do j =1,nz + do i =1,nx + InCoord(1) = x(i) + InCoord(2) = z(j) + InCoord(3) = w(k) + + + call WAMIT_Interp3D_Cplx( InCoord, data3d, x, z, w, LastIndex, interpVal, ErrStat, ErrMsg ) + +if ( .not. equalrealnos( REAL(data3d(i,j,k)), REAL(interpVal) ) .or. & + .not. equalrealnos( IMAG(data3d(i,j,k)), IMAG(interpVal) ) ) then +print *, '----------------- not equal ---------------------------------------------------' +print *, '**** ', i, j, k, ' ****' +print *, '' +print *, 'input value:', InCoord + +print *, 'data at point:', data3d(i,j,k) +print *, 'interp data :', interpVal +print *, '-------------------------------------------------------------------------------' +end if + + end do + end do + end do + + + !............................................................................................................................... + ! 4d interpolation: + data4d = 0.0_ReKi + do i4 = 1,n4 + do k=1,nz + do j =1,ny + do i =1,nx + data4d(i,j,k,i4) = (i4-1)*nz*ny*nx + (k-1)*(nx*ny) + (j-1)*nx + i + end do + end do + end do + end do + + + do i4 = 1,n4 + do k=1,nz + do j =1,ny + do i =1,nx + InCoord4(1) = x(i) + InCoord4(2) = y(j) + InCoord4(3) = z(k) + InCoord4(4) = w(i4) + + + call WAMIT_Interp4D_Cplx( InCoord4, data4d, x, y, z, w, LastIndex4, interpVal, ErrStat, ErrMsg ) + +if ( .not. equalrealnos( REAL(data4d(i,j,k,i4)), REAL(interpVal) ) .or. & + .not. equalrealnos( IMAG(data4d(i,j,k,i4)), IMAG(interpVal) ) ) then +print *, '----------------- not equal ---------------------------------------------------' +print *, '**** ', i, j, k, i4 , ' ****' +print *, '' +print *, 'input value:', InCoord4 + +print *, 'data at point:', data4d(i,j,k,i4) +print *, 'interp data :', interpVal +print *, '-------------------------------------------------------------------------------' +end if + end do + end do + end do + end do + + + stop +#endif + !............................................................................................................................... + ! Test cross_product timing with array dimensions + !............................................................................................................................... + + do k=1,5 + + CALL CPU_TIME(time_begin) + vec1 = 1.; + vec2 = 2. + do i=1,ndims + vec1(i,1) = i + vec1(i,2) = 0.2 + vec1(i,3) = 0.25 + do j=1,20 + vec3 = cross_product(vec1(i,:), vec2(i,:)) + vec1(i,:) = vec3 + end do + end do + print *, vec3 + print *, vec1(1,:) + CALL CPU_TIME ( time_end ) + WRITE (*,*) 'Time of operation A was ', time_end - time_begin, ' seconds' + + CALL CPU_TIME(time_begin) + vec11 = 1.; + vec21 = 2. + do i=1,ndims + vec11(1,i) = i + vec11(2,i) = 0.2 + vec11(3,i) = 0.25 + do j=1,20 + vec3 = cross_product(vec11(:,i), vec21(:,i)) + vec11(:,i) = vec3 + end do + end do + print *, vec3 + print *, vec11(:,i) + CALL CPU_TIME ( time_end ) + WRITE (*,*) 'Time of operation B was ', time_end - time_begin, ' seconds' + + end do + +stop; + + !............................................................................................................................... + ! Test interface with LAPACK + !............................................................................................................................... + + call LAPACK_GETRF( m, n, a, IPIV, ErrStat, ErrMsg ) + print *, 'LAPACK_Getrf: ', ErrStat, TRIM(ErrMsg) + + call LAPACK_GETRs( 'N', n, a, IPIV, b, ErrStat, ErrMsg ) + print *, 'LAPACK_GETRs: ', ErrStat, TRIM(ErrMsg) + + + !............................................................................................................................... + ! Let's check that the PRECISION kinds are specified correctly: + !............................................................................................................................... + CALL WrScr( 'Real KIND parameters:' ) + CALL WrScr( ' QuKi is '//Num2LStr(QuKi)//'-> It should be 16.' ) + CALL WrScr( ' R8Ki is '//Num2LStr(R8Ki)//'-> It should be 8.' ) + CALL WrScr( ' SiKi is '//Num2LStr(SiKi)//'-> It should be 4.' ) + CALL WrScr1(' ReKi is '//Num2LStr(ReKi) ) + CALL WrScr( ' DbKi is '//Num2LStr(DbKi) ) + + !............................................................................................................................... + ! Test NWTC_Num routines: EqualRealNos + !............................................................................................................................... + + CALL WrScr1( ' Testing EqualRealNos for quad kinds: ') + + Real16Var = 5.0_QuKi + RealQuVar = Real16Var + 0.00005_QuKi + + print *, Real16Var + print *, RealQuVar + + IF ( EqualRealNos ( Real16Var, RealQuVar ) ) THEN + CALL WrScr( ' '//TRIM(Num2LStr(Real16Var))//' is approximately equal to '//Num2LStr(RealQuVar) ) + ELSE + CALL WrScr( ' '//TRIM(Num2LStr(Real16Var))//' is not equal to '//Num2LStr(RealQuVar) ) + + END IF + + + CALL WrScr1( ' Testing EqualRealNos for double kinds: ') + Real8Var = 5.0_R8Ki + RealR8Var = Real8Var + 0.00005_R8Ki + + print *, Real8Var + print *, RealR8Var + + IF ( EqualRealNos ( Real8Var, RealR8Var ) ) THEN + CALL WrScr( ' '//TRIM(Num2LStr(Real8Var))//' is approximately equal to '//Num2LStr(RealR8Var) ) + ELSE + CALL WrScr( ' '//TRIM(Num2LStr(Real8Var))//' is not equal to '//Num2LStr(RealR8Var) ) + + END IF + + + CALL WrScr1( ' Testing EqualRealNos for single kinds: ') + Real4Var = 5.0_SiKi + RealSiVar = Real8Var + 0.00005_SiKi + + print *, Real4Var + print *, RealSiVar + + IF ( EqualRealNos ( Real4Var, RealSiVar ) ) THEN + CALL WrScr( ' '//TRIM(Num2LStr(Real4Var))//' is approximately equal to '//Num2LStr(RealSiVar) ) + ELSE + CALL WrScr( ' '//TRIM(Num2LStr(Real4Var))//' is not equal to '//Num2LStr(RealSiVar) ) + END IF + + + !............................................................................................................................... + ! Test Formatted Input File: + !............................................................................................................................... + + !CALL OpenFInpFile( ) + +!INTEGER(IntKi) :: TempVec(3,2) + allocate( TempVec(3,2) ) + + TempVec(:,1) = (/ 1, 2, 3 /) + TempVec(:,2) = TempVec(:,1)*6 + + print *, TempVec + + print *, 'SIZE = ', SIZE(TempVec) + + print *, PACK(TempVec,.TRUE.) + print *, TempVec(1:SIZE(TempVec),1) + + print *, TempVec(1:6,1) + + + call WrScr(' This is line 1.'//CHAR(10)//' This is line 2.') + + + call WrScr(NewLine//' This is line 1.'//NewLine//' This is line 2.'//NewLine//' This is line 3.') + CALL WrScr(NewLine//NewLine//NewLine//'This is really important'//NewLine//NewLine//& + ' This is line 2 a really long line that i need to be more than 98 characters so that it will print on two lines. is this long enough, yet. I''m not sure' ) + + call wrscr('') + call wrscr(' one line' ) + call wrscr(' two lines.') + + do i=-1,6 + call wrscr( GetErrStr(i) ) + end do + + + deallocate(TempVec) + + + print *, 'This is the size of a deallocated array: ', size(TempVec), allocated(TempVec) + print *, 'This is the size of a deallocated array: ', size(RealReAry), allocated(RealReAry) + + RealR8Var = 0.00000001_DbKi + print *, MOD( NINT(RealR8Var), 10 ) == 1 + RealR8Var = 1.00000001_DbKi + print *, MOD( NINT(RealR8Var), 10 ) == 1 + RealR8Var = 10.00000001_DbKi + print *, MOD( NINT(RealR8Var), 10 ) == 1 + RealR8Var = 10.00000001_DbKi + 1.0 + print *, MOD( NINT(RealR8Var), 10 ) == 1 + + + +!---------------------------- + !allocate( IC( NMX ) ) + ! + !IC(1) = 1 + !DO I = 2,NMX + ! IC(I) = IC(1) - I + 1 + NMX + !ENDDO + ! + !write( *, '( A, I1, A, '//TRIM(Num2LStr(NMX))//'(I2,1X) )') 'SHIFT ', 0, ': ', IC + ! + !DO j = 1,10 + ! + ! IC(1) = IC(1) + 1 + ! IF ( IC(1) > NMX ) IC(1) = IC(1) - NMX + ! DO I = 2,NMX + ! IC(I) = IC(1) - I + 1 + ! IF ( IC(I) <= 0 ) IC(I) = IC(I) + NMX + ! ENDDO + ! + ! write ( *, '( A, I1, A, '//TRIM(Num2LStr(NMX))//'(I2,1X) )') 'SHIFT ', j, ': ', IC + ! + !end do + ! + !print *, ' ' + ! + !IC(1) = 1 + !DO I = 2,NMX + ! IC(I) = IC(1) - I + 1 + NMX + !ENDDO + ! + !write( *, '( A, I1, A, '//TRIM(Num2LStr(NMX))//'(I2,1X) )') 'SHIFT ', 0, ': ', IC + ! + !DO j = 1,10 + ! + ! IC = CSHIFT( IC, -1 ) + ! write( *, '( A, I1, A, '//TRIM(Num2LStr(NMX))//'(I2,1X) )') 'SHIFT ', j, ': ', IC + ! + ! + !end do + ! + !deallocate( IC ) + + !----------------------------------------------------------- + ! Test some mesh routines: + !----------------------------------------------------------- + + CALL WRSCR( 'start of mesh tests:' ) + ! PAUSE + + + i = 2 + + CALL MeshCreate( BlankMesh = Mesh1 & + ,IOS = COMPONENT_INPUT & + ,NNodes = i & + ,Force = .TRUE. & + ,Moment = .TRUE. & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg ) + + do j=1,i + ! place nodes in a line + CALL MeshPositionNode ( Mesh1, j, (/0.0_ReKi, 0.0_ReKi, j*1.0_ReKi /), ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + ! create an element from this point + + CALL MeshConstructElement ( Mesh1, ELEMENT_POINT, ErrStat, ErrMsg, j ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + + END DO + + ! that's our entire mesh: + CALL MeshCommit ( Mesh1, ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) CALL WrScr(TRIM(ErrMsg)) + Mesh1%Force = 1. + Mesh1%Moment = 0. + + CALL WRSCR( 'finished creating mesh 1' ) + if (i<5) THEN + CALL WRSCR( 'mesh 1 info:' ) + call meshprintinfo(CU,Mesh1) + end if + ! PAUSE + + CALL MeshCopy ( SrcMesh = Mesh1 & + , DestMesh = Mesh2 & + , CtrlCode = MESH_SIBLING & + , RotationVel = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + + CALL WRSCR( 'finished creating sibling mesh 2' ) + Mesh2%RotationVel = 3 + + if (i<5) THEN + CALL WRSCR( 'mesh 2 info:' ) + call meshprintinfo(CU,Mesh2) + end if + ! PAUSE + + CALL MeshCopy ( SrcMesh = Mesh1 & + , DestMesh = Mesh3 & + , CtrlCode = MESH_NEWCOPY & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + CALL WRSCR( 'finished creating new mesh 3' ) + MESH3%Force=10 + if (i<5) THEN + CALL WRSCR( 'mesh 3 info:' ) + call meshprintinfo(CU,Mesh3) + end if + !PAUSE + + CALL MeshDestroy( Mesh2, ErrStat, ErrMsg, .TRUE. ) !delete only mesh 2 (not its sibling, too) + if (i<5) THEN + CALL WRSCR( 'mesh 1 info:' ) + call meshprintinfo(CU,Mesh1) + end if + CALL WRSCR( 'finished deleting mesh 2' ) + !PAUSE + + CALL MeshCopy ( SrcMesh = Mesh1 & + , DestMesh = Mesh2 & + , CtrlCode = MESH_SIBLING & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , TranslationVel = .TRUE. & + , RotationAcc = .TRUE. & + , TranslationAcc = .TRUE. & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + + + CALL WRSCR( 'finished creating sibling mesh 2' ) + !PAUSE + + + CALL MeshDestroy( Mesh2, ErrStat, ErrMsg, .true. ) !delete mesh 2 BUT NOT its sibling (mesh 1) + CALL WRSCR( 'finished deleting mesh 1' ) + !CALL MeshDestroy( Mesh2, ErrStat, ErrMsg, .FALSE. ) !delete both mesh 2 and its sibling (mesh 1) + !CALL WRSCR( 'finished deleting meshes 1 and 2' ) + !PAUSE + + CALL MeshDestroy( Mesh3, ErrStat, ErrMsg ) !delete mesh 3 + CALL WRSCR( 'finished deleting mesh 3' ) + !PAUSE + + CALL WRSCR( 'finished this test' ) + ! PAUSE + + do i=1,10000 + print *, i, 'Copy:' + CALL MeshCopy ( SrcMesh = Mesh1 & + , DestMesh = Mesh3 & + , CtrlCode = MESH_NEWCOPY & + , ErrStat = ErrStat & + , ErrMess = ErrMsg ) + IF (ErrStat/=ErrID_None) print *, TRIM(ErrMsg) + + print *, i, 'Destroy:' + CALL MeshDestroy( Mesh3, ErrStat, ErrMsg, .FALSE. ) !delete mesh 3 + IF (ErrStat/=ErrID_None) print *, TRIM(ErrMsg) + + + END DO + + + CALL MeshDestroy( Mesh1, ErrStat, ErrMsg, .FALSE. ) + CALL WRSCR( 'finished mesh copy/destroy test' ) + !! PAUSE + + !----------------------------------------------------------- + + +END PROGRAM Test_NWTC_Library + diff --git a/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/Test_OpenCon_GnuWin.f90 b/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/Test_OpenCon_GnuWin.f90 new file mode 100644 index 000000000..01e4cf3e7 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/Test_OpenCon_GnuWin.f90 @@ -0,0 +1,44 @@ +PROGRAM Test_OpenCon_GnuWin + + +! This program test OpenCon() and WrOvr() in SysGnuWin. + +! This was created because the console could not be redirected in v1.06.00c-mlb +! and plus signs showed up on screen when WrOvr() was used. + +! Programmer: Marshall Buhl +! National Wind Technology Center +! National Renewable Energy Laboratory + + +USE NWTC_Library + +IMPLICIT NONE + + + ! Local declarations. + +TYPE(ProgDesc), PARAMETER :: ProgInfo = ProgDesc( 'NWTC Test_OpenCon_GnuWin', '', '') ! The name, version, and date of this program. + + + ! Initialize the NWTC Library, which will initialize Pi-based constants. + +CALL NWTC_Init + + + ! Print out program and library name, version, and date. + +CALL DispNVD ( ProgInfo ) + + + ! Test overwriting of output. + +CALL WrScr ( '' ) +CALL WrNR ( 'This line should be overwritten. What happens if it is longer than the second line?' ) +CALL WrOver ( 'This line should overwrite the first.' ) +CALL WrOver ( 'This line should overwrite the second.' ) + + +STOP +END + diff --git a/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/makefile b/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/makefile new file mode 100644 index 000000000..b13650471 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_OpenCon_GnuWin/makefile @@ -0,0 +1,117 @@ +#==========================================================================================# +# This makefile created by M. Buhl on 26-Dec-2012. # +# # +# This makefile has been tested on Windows 7 with gfortran. # +# This makefile works with mingw32-make.exe. # +# # +# It was designed to be used with: # +# Test_OpenCon_Gnu (v1.00.00, 26-Dec-2012) # +# NWTC Subroutine Library (v1.06.00c-mlb, 12-Dec-2012) # +# # +# Older versions of Test_OpenCon_Gnu and the NWTC Library may not work with this makefile. # +#==========================================================================================# + + # Location of source files for Test_OpenCon_Gnu and the NWTC Library. You will probably need to change these for your system. + +LIB_DIR = D:/CAEtools/Miscellaneous/NWTC_Library/trunk/source +TEST_DIR = . + + # System-specific settings. + + # Windows +DEL_CMD = del +MD_CMD = mkdir +PATH_SEP = \\ +EXE_EXT = .exe +OBJ_EXT = .obj +SYS_FILE = SysGnuWin + + # Linux +#DEL_CMD = rm -f +#MD_CMD = mkdir -p +#PATH_SEP = / +#EXE_EXT = +#OBJ_EXT = .o +#SYS_FILE = SysGnuLinux + + # Program name. + +PROG = Test_OpenCon_GnuWin + + # Name of compiler to use and flags to use. + +FC = gfortran +FFLAGS = -O3 -fbacktrace + + # Destinations for executable and intermediate files. + +DEST_DIR = . +INTER_DIR = Obj + + # Precision. + +# Change to "DoubPrec" for double precision. You may also need to change an option switch to make constants DP. +PREC = SingPrec + + # Library files. + +LIB_SOURCES = \ + $(PREC).f90 \ + $(SYS_FILE).f90 \ + NWTC_IO.f90 \ + NWTC_Num.f90 \ + ModMesh.f90 \ + NWTC_Aero.f90 \ + NWTC_Library.f90 + + #==========================================================# + # You should not need to change anything beyond this point # + #==========================================================# + +TEST_SOURCES = $(PROG).f90 + +vpath %.f90 $(LIB_DIR) $(TEST_DIR) +vpath %.mod $(INTER_DIR) +vpath %.obj $(INTER_DIR) + +LIB_OBJS = $(LIB_SOURCES:.f90=.obj) +TEST_OBJS = $(TEST_SOURCES:.f90=.obj) + + # Rule to do everything. + +all: default +default: $(INTER_DIR) $(DEST_DIR)/$(PROG)$(EXE_EXT) + + # General rule for making the files. + +%.obj: %.f90 + $(FC) $(FFLAGS) -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) + + # Dependency rules. + +$(SYS_FILE).obj: $(PREC).obj +ModMesh.obj: $(PREC).obj +NWTC_IO.obj: $(SYS_FILE).obj +NWTC_Num.obj: NWTC_IO.obj +NWTC_Aero.obj: NWTC_IO.obj NWTC_Num.obj +NWTC_Library.obj: NWTC_Aero.obj ModMesh.obj +$(PROG).obj: NWTC_Library.obj +$(PROG).exe: $(PROG).obj + + # Make sure the destination directory for the intermediate files exist. + +$(INTER_DIR): + $(MD_CMD) $(INTER_DIR) + + # For compiling Test_OpenCon_Gnu. + +$(DEST_DIR)/$(PROG)$(EXE_EXT): $(LIB_OBJS) $(TEST_OBJS) | $(INTER_DIR) + $(FC) $(FLAGS) -I $(INTER_DIR) -o $(DEST_DIR)/$(PROG)$(EXE_EXT) \ + $(foreach src, $(LIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(TEST_OBJS), $(addprefix $(INTER_DIR)/,$(src))) + + # Cleanup afterwards. + +clean: + $(DEL_CMD) $(INTER_DIR)$(PATH_SEP)*.mod $(INTER_DIR)$(PATH_SEP)*.obj + diff --git a/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/Test_ReadComFile.f90 b/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/Test_ReadComFile.f90 new file mode 100644 index 000000000..c6d1d491c --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/Test_ReadComFile.f90 @@ -0,0 +1,85 @@ +PROGRAM Test_ReadComFile + + + ! This program tests the ScanComFile and ReadComFile routines in the NWTC Library. + ! Created by Marshall Buhl. + + + USE :: NWTC_Library + + IMPLICIT NONE + + + ! Type declarations. + + INTEGER(IntKi) :: ErrStat = 0 ! Error status. + + INTEGER :: Line ! Index into the arrays. + + CHARACTER(256) :: ErrMsg = 'No Error' ! Error message. + CHARACTER(512) :: TopFileName ! The top-level file name. It may include other files. + + TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. + + + + CALL NWTC_Init ( 'Test_ReadComFile', 'v1.02.00, 23-Apr-2013' ) + CALL WrScr ( NewLine//' Running Test_ReadComFile (v1.02.00, 23-Apr-2013)' ) + + + ! Get the name of a file with comments in it. + + CALL GET_COMMAND_ARGUMENT( 1, TopFileName, STATUS=ErrStat ) + IF ( ErrStat > 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, ' Syntax: Test_ReadComFile <input_file>' ) + CALL ProgAbort ( ErrMsg ) + ENDIF + + + ! Process the (possibly) nested set of files. + + CALL ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) + IF ( ErrStat > 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, ErrMsg ) + CALL ProgAbort ( ErrMsg ) + ENDIF + + + ! Print the decommented file(s) to the screen. + + PRINT '(/,A,/)', ' The decommented contents of "'//TRIM( FileInfo%FileList(1) )//'" and its included files are:' + PRINT '( A)', ' AggLine FileName FileLine LineText' + PRINT '( A)', ' ------- -------- -------- --------' + + DO Line=1,FileInfo%NumLines + PRINT '(5X,I2.2,4X,A16,5X,I2.2,6X,A)', Line, '"'//TRIM( FileInfo%FileList(FileInfo%FileIndx(Line)) )//'"', & + FileInfo%FileLine(Line), '"'//TRIM( FileInfo%Lines(Line) )//'"' + ENDDO ! Line + + CALL ExitThisRoutine( ErrID_None, '' ) + + STOP + + !======================================================================= + CONTAINS + !======================================================================= + SUBROUTINE ExitThisRoutine ( ErrID, Msg ) + + ! This subroutine cleans up all the allocatable arrays, sets the error status/message and closes the binary file + + ! Passed arguments. + + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrLev) + + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + ! Set error status/message + + ErrStat = ErrID + ErrMsg = Msg + + END SUBROUTINE ExitThisRoutine ! ( ErrID, Msg ) + +END PROGRAM Test_ReadComFile +!======================================================================= diff --git a/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/makefile b/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/makefile new file mode 100644 index 000000000..86dde6dcf --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_ReadComFile/makefile @@ -0,0 +1,135 @@ +#================================================================================# +# This makefile was last updated by M. Buhl on 12-Mar-2013. # +# # +# This makefile has been tested with: # +# Windows 7 # +# GNU Make3.81 # +# gfortran v4.6.1 # +# Ubuntu 12.04.0 LTS # +# GNU Make3.82 # +# gfortran v4.6.3 # +# # +# It was designed to be used with: # +# Test_ReadComFile (v1.00.00 , 12-Mar-2013) # +# NWTC Subroutine Library (v2.00.00c-bjj, 05-Feb-2013) # +#================================================================================# + + + # Windows or Linux? 32-bit or 64-bit? + +BITS = 32 +#BITS = 64 + + # Location of source files for the NWTC Library. You will probably need to change these for your system. + +ifeq ($(OS),Windows_NT) + LIB_DIR = C:\Users\mbuhl\UserData\CAEtools\Miscellaneous\NWTC_Library\branches\BJonkman\source + #LIB_DIR = C:\Users\mbuhl\UserData\CAEtools\Miscellaneous\NWTC_Library\trunk\source +else + LIB_DIR = $(HOME)/PC/CAEtools/Miscellaneous/NWTC_Library/branches/BJonkman/source +endif + +TEST_DIR = . + + # Name of compiler to use and flags to use. + +FC = gfortran +FFLAGS = -O3 -m$(BITS) -fbacktrace -x f95-cpp-input -ffree-line-length-none +LFLAGS = -m$(BITS) + + # Precision. + +# Use "SingPrec" for single precision and "DoubPrec" for double precision. You may also need to change an option switch to make constants DP. +PREC = SingPrec + + #==========================================================# + # You should not need to change anything beyond this point # + #==========================================================# + + + # System-specific settings. + +ifeq ($(OS),Windows_NT) + # Windows + DEL_CMD = del + EXE_EXT = _gwin$(BITS).exe + INTER_DIR = Obj_win$(BITS) + MD_CMD = @mkdir + OBJ_EXT = .obj + PATH_SEP = \\ + SYS_FILE = SysGnuWin +else + # Linux + DEL_CMD = rm -f + EXE_EXT = _glin$(BITS) + INTER_DIR = Obj_lin$(BITS) + MD_CMD = @mkdir -p + OBJ_EXT = .o + PATH_SEP = / + SYS_FILE = SysGnuLinux +endif + + # Destination for executable. + +DEST_DIR = . + + # Library files. + +LIB_SOURCES = \ + $(PREC).f90 \ + $(SYS_FILE).f90 \ + NWTC_IO.f90 \ + NWTC_Num.f90 \ + ModMesh_Types.f90 \ + ModMesh.f90 \ + NWTC_Library.f90 + +TEST_SOURCES = \ + Test_ReadComFile.f90 + +vpath %.f90 $(LIB_DIR) $(TEST_DIR) +vpath %.mod $(INTER_DIR) +vpath %.obj $(INTER_DIR) + +LIB_OBJS = $(LIB_SOURCES:.f90=.obj) +TEST_OBJS = $(TEST_SOURCES:.f90=.obj) + + # Rule to do everything. + +all: default +default: $(INTER_DIR) $(DEST_DIR)/Test_ReadComFile$(EXE_EXT) + + # General rule for making the files. + +%.obj: %.f90 + $(FC) $(FFLAGS) -c $< -o $(INTER_DIR)/$@ -J $(INTER_DIR) + + # Dependency rules. + +$(SYS_FILE).obj: $(PREC).obj +ModMesh_Types.obj: $(PREC).obj +ModMesh.obj: ModMesh_Types.obj +NWTC_IO.obj: $(SYS_FILE).obj +NWTC_Num.obj: NWTC_IO.obj +NWTC_Library.obj: NWTC_Num.obj ModMesh.obj +Test_ReadComFile.obj: NWTC_Library.obj + +#Test_ReadComFile$(EXE_EXT): Test_ReadComFile.obj + + # Make sure the destination directory for the intermediate files exist. + +$(INTER_DIR): + $(MD_CMD) $(INTER_DIR) + + # For compiling Test_ReadComFile. + +$(DEST_DIR)/Test_ReadComFile$(EXE_EXT): $(LIB_OBJS) $(TEST_OBJS) | $(INTER_DIR) + $(FC) $(LFLAGS) -I $(INTER_DIR) -o $(DEST_DIR)/Test_ReadComFile$(EXE_EXT) \ + $(foreach src, $(LIB_OBJS), $(addprefix $(INTER_DIR)/,$(src))) \ + $(foreach src, $(TEST_OBJS), $(addprefix $(INTER_DIR)/,$(src))) + + # Cleanup afterwards. + +clean: + $(DEL_CMD) $(INTER_DIR)$(PATH_SEP)*.mod $(INTER_DIR)$(PATH_SEP)*.obj + diff --git a/OpenFAST/modules/nwtc-library/test/Test_ReadFASTbin.f90 b/OpenFAST/modules/nwtc-library/test/Test_ReadFASTbin.f90 new file mode 100644 index 000000000..093e7984c --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_ReadFASTbin.f90 @@ -0,0 +1,106 @@ +PROGRAM Test_ReadFASTbin + + + ! This program is used to test the TestReadFASTbin_Mod module. + + + USE :: NWTC_Library + + IMPLICIT NONE + + ! Local declarations. + + INTEGER(IntKi) :: ErrLev ! The error level returned by ReadFASTbin. + INTEGER(IntKi) :: IO_Unit = 1 ! The IO unit for the FAST binary file. + INTEGER(IntKi) :: IRec ! The record index used for DO loops. + + LOGICAL :: Error ! A flag returned by Get_Arg(). + + CHARACTER(200) :: ErrMsg ! A possible error message returned by ReadFASTbin. + CHARACTER( 21) :: Fmt ! The format specifier for the channel headings. + CHARACTER( 4) :: OutExt = 'outc' ! The extension of the converted output file. + CHARACTER(256) :: OutFile ! The extension of the converted output file. + CHARACTER(200) :: RootName ! The root name of the FAST data files. + + TYPE (FASTdataType) :: FASTdata ! The derived type for holding FAST output data. + + + + ! Initialize the NWTC Library. + + CALL NWTC_Init ( 'Test_ReadFASTbin', 'v1.01.00a-mlb, 10-Jan-2003' ) + + + ! Get the name of the FAST binary data file. + + CALL GET_COMMAND_ARGUMENT( 1, FASTdata%File, STATUS=ErrLev ) + + IF ( ErrLev > 0 ) THEN + CALL ProgAbort ( ' Syntax: Test_ReadFASTbin <input_file>' ) + ENDIF + + CALL GetRoot( FASTdata%File, RootName ) + + OutFile = TRIM( RootName )//'.'//OutExt + + + ! Read the FAST binary file. + + CALL ReadFASTbin ( IO_Unit, .FALSE., FASTdata, ErrLev, ErrMsg ) + + IF ( ErrLev /= 0 ) THEN + CALL ProgAbort ( TRIM( ErrMsg ) ) + END IF ! ( ErrLev /= 0 ) + + + ! Open the formatted output file. + + CALL OpenFOutFile ( IO_Unit, TRIM( OutFile ), ErrLev ) + + IF ( ErrLev /= 0 ) THEN + CALL ProgAbort ( 'Unable to open the formatted output file, "'//TRIM( OutFile )//'".' ) + END IF ! ( ErrLev /= 0 ) + + + ! Write out the contents of the formatted output file (description, channel names and units, and data). + + CALL WrScr1 ( ' Writing formatted data to '//TRIM( OutFile )//'".' ) + + WRITE (IO_Unit,'(/,A,/)') FASTdata%Descr + + Fmt = '( (1X,A10))' ! Format specified for channel names and units. + + WRITE (Fmt(2:6),'(I5)') FASTdata%NumChans+1 + + WRITE (IO_Unit,Fmt) FASTdata%ChanNames + WRITE (IO_Unit,Fmt) FASTdata%ChanUnits + + Fmt = '(F10.3, (ES11.3))' ! Format specified for data. Time is in fixed-point form. + + WRITE (Fmt(8:12),'(I5)') FASTdata%NumChans+1 + + DO IRec=1,FASTdata%NumRecs + WRITE (IO_Unit,Fmt) FASTdata%Data(IRec,:) + END DO + + + ! Close the output file. + + CLOSE ( IO_Unit ) + + + ! Deallocate the arrays. + + IF ( ALLOCATED( FASTdata%ChanNames ) ) DEALLOCATE( FASTdata%ChanNames ) + IF ( ALLOCATED( FASTdata%ChanUnits ) ) DEALLOCATE( FASTdata%ChanUnits ) + IF ( ALLOCATED( FASTdata%Data ) ) DEALLOCATE( FASTdata%Data ) + + + ! We be done. + + CALL WrScr1 ( ' Test_ReadFASTbin processing complete.' ) + + + STOP + +END diff --git a/OpenFAST/modules/nwtc-library/test/Test_RegCubicSpline/Test_RegCubicSpline.f90 b/OpenFAST/modules/nwtc-library/test/Test_RegCubicSpline/Test_RegCubicSpline.f90 new file mode 100644 index 000000000..a96762c98 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/test/Test_RegCubicSpline/Test_RegCubicSpline.f90 @@ -0,0 +1,138 @@ +PROGRAM Test_RegCubicSpline + + + ! This program is used to test the routines to interpolate regularly spaced arrays using cubic splines. + + + USE :: NWTC_Library + + IMPLICIT NONE + + + ! Type declarations. + + INTEGER, PARAMETER :: AryLen = 10 ! Index into the arrays. + + REAL(ReKi) :: X ! The value to interpolate for. + REAL(ReKi) :: Y ! The interpolated value from regularly spaced data. + REAL(ReKi) :: Z ! The interpolated value from irregularly spaced data. + + INTEGER :: I ! Index into the arrays. + INTEGER(IntKi) :: ErrStat ! Error status. + + CHARACTER(4096) :: ErrMsg ! Error message. + + TYPE( CubSplineType) :: CubSplineData ! Derived type to hold data for irregularly spaced cubic splines. + TYPE(RegCubSplineType) :: RegCubSplineData ! Derived type to hold data for regularly spaced cubic splines. + + + + ! Initialize the NWTC Library. + + CALL NWTC_Init ( 'Test_RegCubicSpline', 'v1.00.00, 17-May-2013', EchoLibVer=.FALSE. ) + CALL WrScr ( NewLine//' Running Test_RegCubicSpline (v1.00.00, 17-May-2013)' ) + + + ! Set up the regularly spaced data to be interpolated. + + RegCubSplineData%NumPts = 10 + + ALLOCATE ( RegCubSplineData%XAry( RegCubSplineData%NumPts ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the RegCubSplineData%XAry array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + ALLOCATE ( RegCubSplineData%YAry( RegCubSplineData%NumPts ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the RegCubSplineData%YAry array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + ALLOCATE ( RegCubSplineData%Coef( RegCubSplineData%NumPts-1, 0:3 ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the RegCubSplineData%Coef array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + + ! Set up the irregularly spaced data to be interpolated. + + CubSplineData%NumPts = RegCubSplineData%NumPts + + ALLOCATE ( CubSplineData%XAry( CubSplineData%NumPts ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the CubSplineData%XAry array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + ALLOCATE ( CubSplineData%YAry( CubSplineData%NumPts ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the CubSplineData%YAry array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + ALLOCATE ( CubSplineData%Coef( CubSplineData%NumPts-1, 0:3 ), STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + CALL ProgAbort ( ' >> Error allocating memory for the CubSplineData%Coef array in Test_RegCubicSpline.', .FALSE., 1.0, & + ErrStat ) + ENDIF + + + ! Create an array to interpolate. + + PRINT * + + DO I=1,AryLen + RegCubSplineData%XAry(I) = REAL( 2*I - 2 )*Pi/REAL( AryLen - 1 ) ! Values from 0 to 2*Pi in steps of 2*Pi/(AryLen-1) + RegCubSplineData%YAry(I) = SIN( RegCubSplineData%XAry(I) ) + CubSplineData%XAry(I) = RegCubSplineData%XAry(I) + CubSplineData%YAry(I) = RegCubSplineData%YAry(I) + PRINT '(I5,1X,F12.4)', NINT( R2D*RegCubSplineData%XAry(I) ), RegCubSplineData%YAry(I) + ENDDO ! I + + + ! Compute the coefficients of the piecewise polynomials for the regularly-spaced data. + + CALL RegCubicSplineInit ( RegCubSplineData%NumPts, RegCubSplineData%XAry, RegCubSplineData%YAry, RegCubSplineData%DelX & + , RegCubSplineData%Coef, ErrStat, ErrMsg ) + IF ( ErrStat == ErrID_Fatal ) THEN + CALL ProgAbort ( ErrMsg, .FALSE., 1.0, ErrStat ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr ( ErrMsg ) + ENDIF + + + ! Compute the coefficients of the piecewise polynomials for the irregularly-spaced data. + + CALL CubicSplineInit ( CubSplineData%NumPts, CubSplineData%XAry, CubSplineData%YAry & + , CubSplineData%Coef, ErrStat, ErrMsg ) + IF ( ErrStat == ErrID_Fatal ) THEN + CALL ProgAbort ( ErrMsg, .FALSE., 1.0, ErrStat ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr ( ErrMsg ) + ENDIF + + + ! Write out the interpolated values for both sets of interpolated data. + + PRINT * + + DO I=0,360,1 + X = REAL( I )*D2R + Y = RegCubicSplineInterp( X, RegCubSplineData%NumPts, RegCubSplineData%XAry, RegCubSplineData%YAry & + , RegCubSplineData%DelX , RegCubSplineData%Coef, ErrStat, ErrMsg ) + Z = CubicSplineInterp ( X, CubSplineData%NumPts, CubSplineData%XAry, CubSplineData%YAry & + , CubSplineData%Coef, ErrStat, ErrMsg ) + IF ( ErrStat == ErrID_Fatal ) THEN + CALL ProgAbort ( ErrMsg, .FALSE., 1.0, ErrStat ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr ( ErrMsg ) + ENDIF + PRINT '(I5,2(1X,F12.4))', I, Y, Z + ENDDO ! I + + + CALL NormStop + +END PROGRAM Test_RegCubicSpline \ No newline at end of file diff --git a/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_CheckArgs.F90 b/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_CheckArgs.F90 new file mode 100644 index 000000000..1249751ea --- /dev/null +++ b/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_CheckArgs.F90 @@ -0,0 +1,381 @@ +module test_NWTC_IO_CheckArgs + + use pFUnit_mod + use NWTC_IO + + implicit none + + integer, parameter :: stdout=6 + character(9), parameter :: nullfile="/dev/null" + character(11), parameter :: terminal="/dev/stdout" + +contains + + ! PASSING CASES + + ! ************************************************************************ + ! To read the input file, a default may be provided and a user-specified + ! input file may be used instead. + + @test + subroutine test_input_file_user_specified() + + ! executable.exe FileName + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(1)) + argument_array = (/ & + "first_arg.txt " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_input_file_default() + + ! executable.exe + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "default.txt" + allocate(argument_array(0)) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "default.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_input_file_default_user_specified() + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "default.txt" + allocate(argument_array(1)) + argument_array = (/ & + "first_arg.txt " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! Given a restart flag, the flag should be parsed along with the input + ! file and second argument regardless of the position of the flag. + ! The first argument is optional in this case. + + @test + subroutine test_restart_flag1() + + ! executable.exe -Flag FileName Arg2 + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(3)) + argument_array = (/ & + "-restart ", & + "first_arg.txt ", & + "second_arg " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "second_arg", second_argument ) + @assertEqual( "RESTART", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_restart_flag2() + + ! executable.exe FileName -Flag Arg2 + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(3)) + argument_array = (/ & + "first_arg.txt ", & + "-restart ", & + "second_arg " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "second_arg", second_argument ) + @assertEqual( "RESTART", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_restart_flag3() + + ! executable.exe -restart Arg1 + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "-restart ", & + "first_arg.txt " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "first_arg.txt", second_argument ) + @assertEqual( "RESTART", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! The second argument should be returned when provided even outside + ! of the restart functionality. + + @test + subroutine test_second_argument() + + ! executable.exe FileName Arg2 + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "first_arg.txt ", & + "second_arg " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "second_arg", second_argument ) + @assertEqual( "", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! The help flag in any position should show the help prompt and exit + ! normally. + + @test + subroutine test_help1() + + ! executable.exe -Flag FileName + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "-h ", & + "first_arg.txt " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "H", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_help2() + + ! executable.exe FileName -Flag + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "first_arg.txt ", & + "-h " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "H", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! The version flag in any position should show the version info and exit + ! normally. + + @test + subroutine test_version1() + + ! executable.exe -v FileName + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "-v ", & + "first_arg.txt " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "V", flag ) + deallocate(argument_array) + end subroutine + + @test + subroutine test_version2() + + ! executable.exe FileName -VERSION + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "first_arg.txt ", & + "-VERSION " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 0, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "VERSION", flag ) + deallocate(argument_array) + end subroutine + + ! FAILING CASES + + ! ************************************************************************ + ! No arguments and no default input file should exit with an error + + @test + subroutine test_no_args_no_default() + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(0)) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "", filename ) + @assertEqual( 4, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! An unsupported flag should exit with an error + + @test + subroutine test_unsupported_flag() + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(2)) + argument_array = (/ & + "first_arg.txt ", & + "-flag " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "first_arg.txt", filename ) + @assertEqual( 4, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "FLAG", flag ) + deallocate(argument_array) + end subroutine + + ! ************************************************************************ + ! The restart flag requires at least one additional argument + + @test + subroutine test_restart_bad_syntax() + + character(1024) :: filename, second_argument, flag + integer(IntKi) :: error_status + character(16), dimension(:), allocatable :: argument_array + + filename = "" + allocate(argument_array(1)) + argument_array = (/ & + "-restart " & + /) + open(unit=stdout, file=nullfile, status="old") + call CheckArgs( filename, error_status, second_argument, flag, argument_array ) + open(unit=stdout, file=terminal, status="old") + @assertEqual( "", filename ) + @assertEqual( 4, error_status ) + @assertEqual( "", second_argument ) + @assertEqual( "RESTART", flag ) + deallocate(argument_array) + end subroutine + +end module diff --git a/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_FileInfo.F90 b/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_FileInfo.F90 new file mode 100644 index 000000000..3dd9a6ea3 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/tests/test_NWTC_IO_FileInfo.F90 @@ -0,0 +1,84 @@ +module test_NWTC_IO_FileInfo + + use pFUnit_mod + use NWTC_IO + + implicit none + +contains + +@test +subroutine test_initfileinfo() + + ! This case should result in error status 0. + ! It's a normal initialization of FileInfoType. + + integer, parameter :: num_lines = 5 + integer, parameter :: num_files = 1 + + integer(IntKi) :: error_status + character(ErrMsgLen) :: error_message + character(1024) :: input_strings(num_lines) + type(FileInfoType) :: file_info_type + integer :: i + + input_strings = (/ & + "line 0", & + "line 1", & + "line 2", & + "line 3", & + "line 4" & + /) + call InitFileInfo( input_strings, file_info_type, error_status, error_message ) + + @assertEqual(num_lines, file_info_type%NumLines) + @assertEqual(num_files, file_info_type%NumFiles) + do i = 1, num_lines + @assertEqual(i, file_info_type%FileLine(i)) + end do + do i = 1, num_files + @assertEqual(i, file_info_type%FileIndx(i)) + end do + + ! TODO: test FileList when we actually use it + + do i = 1, num_lines + @assertEqual( trim(input_strings(i)), trim(file_info_type%Lines(i)) ) + end do + + @assertEqual( 0, error_status ) + @assertEqual( "", error_message ) +end subroutine + +@test +subroutine test_initfileinfo2() + + ! This case should result in a non-zero error status. + ! It attempts to initialize FileInfoType without having + ! properly initializing the input strings array. + + integer, parameter :: num_lines = 5 + integer, parameter :: num_files = 1 + + integer(IntKi) :: error_status + character(ErrMsgLen) :: error_message + character(1025) :: input_strings(num_lines) + type(FileInfoType) :: file_info_type + integer :: i + + input_strings = (/ & + "line 0", & + "line 1", & + "line 2", & + "line 3", & + "line 4" & + /) + call InitFileInfo( input_strings, file_info_type, error_status, error_message ) + + @assertEqual(num_lines, file_info_type%NumLines) + @assertEqual(num_files, file_info_type%NumFiles) + @assertEqual( 4, error_status ) + +end subroutine + +end module \ No newline at end of file diff --git a/OpenFAST/modules/nwtc-library/tests/test_NWTC_RandomNumber.F90 b/OpenFAST/modules/nwtc-library/tests/test_NWTC_RandomNumber.F90 new file mode 100644 index 000000000..4e3d472f0 --- /dev/null +++ b/OpenFAST/modules/nwtc-library/tests/test_NWTC_RandomNumber.F90 @@ -0,0 +1,58 @@ +module test_NWTC_RandomNumber + + use pFUnit_mod + use NWTC_RandomNumber + + implicit none + + integer, parameter :: stdout=6 + character(9), parameter :: nullfile="/dev/null" + character(11), parameter :: terminal="/dev/stdout" + +contains + +@test +subroutine test_RANLUX() + + type(NWTC_RandomNumber_ParameterType) :: p ! Paramters for random number generation + integer(IntKi) :: error_status + character(ErrMsgLen) :: error_message + + real(ReKi) :: random_numbers(2) ! Uniformly distributed random numbers + + p%pRNG = pRNG_RANLUX + p%RandSeed(1) = 1 + + call RandNum_Init(p, error_status, error_message) + @assertEqual( 0, error_status ) + + call UniformRandomNumbers(p%pRNG, random_numbers) + @assertEqual( (/ 0.94589489698410034, 0.47347849607467651 /), random_numbers ) + +end subroutine + +@test +subroutine test_INTRINSIC() + + type(NWTC_RandomNumber_ParameterType) :: p ! Paramters for random number generation + integer(IntKi) :: error_status + character(ErrMsgLen) :: error_message + + integer :: expected_seed_count + real(ReKi) :: random_numbers(2) ! Uniformly distributed random numbers + + p%pRNG = pRNG_INTRINSIC + p%RandSeed(1) = 1 + p%RandSeed(2) = 2 + + open(unit=stdout, file=nullfile, status="old") + call RandNum_Init(p, error_status, error_message) + open(unit=stdout, file=terminal, status="old") + @assertEqual( 0, error_status ) + + ! We cant use this test since it will fail for various machine/compiler combinations + ! call UniformRandomNumbers(p%pRNG, random_numbers) + ! @assertEqual( (/ 0.80377975339288821, 0.47469797199574959 /), random_numbers ) +end subroutine + +end module diff --git a/OpenFAST/modules/openfast-library/CMakeLists.txt b/OpenFAST/modules/openfast-library/CMakeLists.txt new file mode 100644 index 000000000..aa52e1be8 --- /dev/null +++ b/OpenFAST/modules/openfast-library/CMakeLists.txt @@ -0,0 +1,81 @@ +# +# Copyright 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. +# + +if(APPLE OR UNIX) + add_definitions(-DIMPLICIT_DLLEXPORT) +endif() + +if (GENERATE_TYPES) + generate_f90_types(src/FAST_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/FAST_Types.f90 -noextrap) +endif() + +add_library(openfast_prelib src/FAST_Types.f90) + +target_link_libraries(openfast_prelib + nwtclibs + ifwlib + aerodynlib + aerodyn14lib + servodynlib + elastodynlib + beamdynlib + subdynlib + hydrodynlib + orcaflexlib + extptfm_mckflib + openfoamtypeslib + sctypeslib + feamlib + moordynlib + icedynlib + icefloelib + maplib +) + +add_library(openfast_postlib + src/FAST_Lin.f90 + src/FAST_Mods.f90 + src/FAST_Subs.f90 + src/FAST_Solver.f90 + ) +target_link_libraries(openfast_postlib openfast_prelib scfastlib foamfastlib versioninfolib) + +add_library(openfastlib SHARED src/FAST_Library.f90) +target_link_libraries(openfastlib openfast_postlib openfast_prelib scfastlib foamfastlib) + +string(TOUPPER ${CMAKE_Fortran_COMPILER_ID} _compiler_id) +string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type) +if (${_compiler_id} STREQUAL "GNU" AND ${_build_type} STREQUAL "RELEASE") + # With variable tracking enabled, the compile step frequently aborts on large modules and + # restarts with this option off. Disabling in Release mode avoids this problem when compiling with + # full optimizations, but leaves it enabled for RelWithDebInfo which adds both -O2 and -g flags. + # https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html + set_source_files_properties( + src/FAST_Subs.f90 src/FAST_Types.f90 src/FAST_Library.f90 + PROPERTIES + COMPILE_FLAGS "-fno-var-tracking -fno-var-tracking-assignments" + ) +endif() + +install(TARGETS openfastlib openfast_prelib openfast_postlib + EXPORT ${CMAKE_PROJECT_NAME}Libraries + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +install(FILES + src/FAST_Library.h + DESTINATION include) diff --git a/OpenFAST/modules/openfast-library/README.md b/OpenFAST/modules/openfast-library/README.md new file mode 100644 index 000000000..9ca65673f --- /dev/null +++ b/OpenFAST/modules/openfast-library/README.md @@ -0,0 +1,6 @@ +# OpenFAST Library Module + +## Overview +The OpenFAST Library contains all of the subroutines making up the OpenFAST +glue code. These subroutines coordinate the initialization, solving, and +data output for the multiphysics simulation. diff --git a/OpenFAST/modules/openfast-library/src/FAST_Library.f90 b/OpenFAST/modules/openfast-library/src/FAST_Library.f90 new file mode 100644 index 000000000..ea564eb34 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Library.f90 @@ -0,0 +1,724 @@ +! FAST_Library.f90 +! +! FUNCTIONS/SUBROUTINES exported from FAST_Library.dll: +! FAST_Start - subroutine +! FAST_Update - subroutine +! FAST_End - subroutine +! +! DO NOT REMOVE or MODIFY LINES starting with "!DEC$" or "!GCC$" +! !DEC$ specifies attributes for IVF and !GCC$ specifies attributes for gfortran +! +!================================================================================================================================== +MODULE FAST_Data + + USE, INTRINSIC :: ISO_C_Binding + USE FAST_Subs ! all of the ModuleName and ModuleName_types modules are inherited from FAST_Subs + + IMPLICIT NONE + SAVE + + ! Local parameters: + REAL(DbKi), PARAMETER :: t_initial = 0.0_DbKi ! Initial time + INTEGER(IntKi) :: NumTurbines + INTEGER, PARAMETER :: IntfStrLen = 1025 ! length of strings through the C interface + INTEGER(IntKi), PARAMETER :: MAXOUTPUTS = 4000 ! Maximum number of outputs + INTEGER(IntKi), PARAMETER :: MAXInitINPUTS = 10 ! Maximum number of initialization values from Simulink + INTEGER(IntKi), PARAMETER :: NumFixedInputs = 8 + + + ! Global (static) data: + TYPE(FAST_TurbineType), ALLOCATABLE :: Turbine(:) ! Data for each turbine + INTEGER(IntKi) :: n_t_global ! simulation time step, loop counter for global (FAST) simulation + INTEGER(IntKi) :: ErrStat ! Error status + CHARACTER(IntfStrLen-1) :: ErrMsg ! Error message (this needs to be static so that it will print in Matlab's mex library) + +contains +!================================================================================================================================== +subroutine FAST_AllocateTurbines(nTurbines, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_AllocateTurbines') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_AllocateTurbines +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_AllocateTurbines +#endif + INTEGER(C_INT), INTENT(IN ) :: nTurbines + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + if (nTurbines .gt. 0) then + NumTurbines = nTurbines + end if + + if (nTurbines .gt. 10) then + call wrscr1('Number of turbines is > 10! Are you sure you have enough memory?') + call wrscr1('Proceeding anyway') + end if + + allocate(Turbine(0:NumTurbines-1),Stat=ErrStat) !Allocate in C style because most of the other Turbine properties from the input file are in C style inside the C++ driver + + if (ErrStat /= 0) then + ErrStat_c = ErrID_Fatal + ErrMsg = "Error allocating turbine data."//C_NULL_CHAR + else + ErrStat_c = ErrID_None + ErrMsg = " "//C_NULL_CHAR + end if + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + +end subroutine FAST_AllocateTurbines + +subroutine FAST_DeallocateTurbines(ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_DeallocateTurbines') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_DeallocateTurbines +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_DeallocateTurbines +#endif + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + if (Allocated(Turbine)) then + deallocate(Turbine) + end if + + ErrStat_c = ErrID_None + ErrMsg_c = C_NULL_CHAR +end subroutine + +subroutine FAST_Sizes(iTurb, TMax, InitInpAry, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, ErrStat_c, ErrMsg_c, ChannelNames_c) BIND (C, NAME='FAST_Sizes') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + REAL(C_DOUBLE), INTENT(IN ) :: TMax + REAL(C_DOUBLE), INTENT(IN ) :: InitInpAry(MAXInitINPUTS) + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT( OUT) :: NumOuts_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ChannelNames_c(ChanLen*MAXOUTPUTS+1) + + ! local + CHARACTER(IntfStrLen) :: InputFileName + INTEGER :: i, j, k + TYPE(FAST_ExternInitType) :: ExternInitData + + ! transfer the character array from C to a Fortran string: + InputFileName = TRANSFER( InputFileName_c, InputFileName ) + I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... + IF ( I > 0 ) InputFileName = InputFileName(1:I) ! remove it + + ! initialize variables: + n_t_global = 0 + + ExternInitData%TMax = TMax + ExternInitData%TurbineID = -1 ! we're not going to use this to simulate a wind farm + ExternInitData%TurbinePos = 0.0_ReKi ! turbine position is at the origin + ExternInitData%NumCtrl2SC = 0 + ExternInitData%NumSC2Ctrl = 0 + ExternInitData%SensorType = NINT(InitInpAry(1)) + ! -- MATLAB Integration -- + ! Make sure fast farm integration is false + ExternInitData%FarmIntegration = .false. + + IF ( NINT(InitInpAry(2)) == 1 ) THEN + ExternInitData%LidRadialVel = .true. + ELSE + ExternInitData%LidRadialVel = .false. + END IF + + + + CALL FAST_InitializeAll_T( t_initial, 1_IntKi, Turbine(iTurb), ErrStat, ErrMsg, InputFileName, ExternInitData ) + + AbortErrLev_c = AbortErrLev + NumOuts_c = min(MAXOUTPUTS, 1 + SUM( Turbine(iTurb)%y_FAST%numOuts )) ! includes time + dt_c = Turbine(iTurb)%p_FAST%dt + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + + ! return the names of the output channels + IF ( ALLOCATED( Turbine(iTurb)%y_FAST%ChannelNames ) ) then + k = 1; + DO i=1,NumOuts_c + DO j=1,ChanLen + ChannelNames_c(k)=Turbine(iTurb)%y_FAST%ChannelNames(i)(j:j) + k = k+1 + END DO + END DO + ChannelNames_c(k) = C_NULL_CHAR + ELSE + ChannelNames_c = C_NULL_CHAR + END IF + +end subroutine FAST_Sizes +!================================================================================================================================== +subroutine FAST_Start(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Start') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_Start +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_Start +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c + REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) + REAL(C_DOUBLE), INTENT( OUT) :: OutputAry(NumOutputs_c) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + + ! local + CHARACTER(IntfStrLen) :: InputFileName + INTEGER :: i + REAL(ReKi) :: Outputs(NumOutputs_c-1) + + INTEGER(IntKi) :: ErrStat2 ! Error status + CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) + + ! initialize variables: + n_t_global = 0 + +#ifdef SIMULINK_DirectFeedThrough + IF( NumInputs_c /= NumFixedInputs .AND. NumInputs_c /= NumFixedInputs+3 ) THEN + ErrStat_c = ErrID_Fatal + ErrMsg = "FAST_Start:size of InputAry is invalid."//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + RETURN + END IF + + CALL FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, Turbine(iTurb)%m_FAST) + +#endif + !............................................................................................................................... + ! Initialization of solver: (calculate outputs based on states at t=t_initial as well as guesses of inputs and constraint states) + !............................................................................................................................... + CALL FAST_Solution0_T(Turbine(iTurb), ErrStat, ErrMsg ) + + if (ErrStat <= AbortErrLev) then + ! return outputs here, too + IF(NumOutputs_c /= SIZE(Turbine(iTurb)%y_FAST%ChannelNames) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = trim(ErrMsg)//NewLine//"FAST_Start:size of NumOutputs is invalid." + ELSE + + CALL FillOutputAry_T(Turbine(iTurb), Outputs) + OutputAry(1) = Turbine(iTurb)%m_FAST%t_global + OutputAry(2:NumOutputs_c) = Outputs + + CALL FAST_Linearize_T(t_initial, 0, Turbine(iTurb), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + ErrStat = max(ErrStat,ErrStat2) + ErrMsg = TRIM(ErrMsg)//NewLine//TRIM(ErrMsg2) + end if + + + END IF + end if + + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + +end subroutine FAST_Start +!================================================================================================================================== +subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_Update +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_Update +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c + REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) + REAL(C_DOUBLE), INTENT( OUT) :: OutputAry(NumOutputs_c) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + ! local variables + REAL(ReKi) :: Outputs(NumOutputs_c-1) + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 ! Error status + CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) + + + IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish + + ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation + + IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved + n_t_global = n_t_global + 1 + ErrStat_c = ErrID_None + ErrMsg = C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + ELSE + ErrStat_c = ErrID_Info + ErrMsg = "Simulation completed."//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + END IF + + ELSEIF(NumOutputs_c /= SIZE(Turbine(iTurb)%y_FAST%ChannelNames) ) THEN + ErrStat_c = ErrID_Fatal + ErrMsg = "FAST_Update:size of OutputAry is invalid or FAST has too many outputs."//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + RETURN + ELSEIF( NumInputs_c /= NumFixedInputs .AND. NumInputs_c /= NumFixedInputs+3 ) THEN + ErrStat_c = ErrID_Fatal + ErrMsg = "FAST_Update:size of InputAry is invalid."//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + RETURN + ELSE + + CALL FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, Turbine(iTurb)%m_FAST) + + CALL FAST_Solution_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) + n_t_global = n_t_global + 1 + + CALL FAST_Linearize_T( t_initial, n_t_global, Turbine(iTurb), ErrStat2, ErrMsg2) + if (ErrStat2 /= ErrID_None) then + ErrStat = max(ErrStat,ErrStat2) + ErrMsg = TRIM(ErrMsg)//NewLine//TRIM(ErrMsg2) + end if + + + ! set the outputs for external code here... + ! return y_FAST%ChannelNames + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + END IF + + CALL FillOutputAry_T(Turbine(iTurb), Outputs) + OutputAry(1) = Turbine(iTurb)%m_FAST%t_global + OutputAry(2:NumOutputs_c) = Outputs + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + +end subroutine FAST_Update +!================================================================================================================================== +subroutine FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, m_FAST) + + USE, INTRINSIC :: ISO_C_Binding + USE FAST_Types +! USE FAST_Data, only: NumFixedInputs + + IMPLICIT NONE + + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) ! Inputs from Simulink + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST ! Miscellaneous variables + + ! set the inputs from external code here... + ! transfer inputs from Simulink to FAST + IF ( NumInputs_c < NumFixedInputs ) RETURN ! This is an error + + m_FAST%ExternInput%GenTrq = InputAry(1) + m_FAST%ExternInput%ElecPwr = InputAry(2) + m_FAST%ExternInput%YawPosCom = InputAry(3) + m_FAST%ExternInput%YawRateCom = InputAry(4) + m_FAST%ExternInput%BlPitchCom = InputAry(5:7) + m_FAST%ExternInput%HSSBrFrac = InputAry(8) + + IF ( NumInputs_c > NumFixedInputs ) THEN ! NumFixedInputs is the fixed number of inputs + IF ( NumInputs_c == NumFixedInputs + 3 ) & + m_FAST%ExternInput%LidarFocus = InputAry(9:11) + END IF + +end subroutine FAST_SetExternalInputs +!================================================================================================================================== +subroutine FAST_End(iTurb, StopTheProgram) BIND (C, NAME='FAST_End') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_End +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_End +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + LOGICAL(C_BOOL), INTENT(IN) :: StopTheProgram ! flag indicating if the program should end (false if there are more turbines to end) + + CALL ExitThisProgram_T( Turbine(iTurb), ErrID_None, LOGICAL(StopTheProgram)) + +end subroutine FAST_End +!================================================================================================================================== +subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CreateCheckpoint') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + ! local + CHARACTER(IntfStrLen) :: CheckpointRootName + INTEGER(IntKi) :: I + INTEGER(IntKi) :: Unit + + + ! transfer the character array from C to a Fortran string: + CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) + I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... + IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it + + if ( LEN_TRIM(CheckpointRootName) == 0 ) then + CheckpointRootName = TRIM(Turbine(iTurb)%p_FAST%OutFileRoot)//'.'//trim( Num2LStr(n_t_global) ) + end if + + + Unit = -1 + CALL FAST_CreateCheckpoint_T(t_initial, n_t_global, 1, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) + + ! transfer Fortran variables to C: + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + +end subroutine FAST_CreateCheckpoint +!================================================================================================================================== +subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, dt_c, n_t_global_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Restart') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_Restart +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_Restart +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT( OUT) :: NumOuts_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: n_t_global_c + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + ! local + CHARACTER(IntfStrLen) :: CheckpointRootName + INTEGER(IntKi) :: I + INTEGER(IntKi) :: Unit + REAL(DbKi) :: t_initial_out + INTEGER(IntKi) :: NumTurbines_out + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + + + ! transfer the character array from C to a Fortran string: + CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) + I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... + IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it + + Unit = -1 + CALL FAST_RestoreFromCheckpoint_T(t_initial_out, n_t_global, NumTurbines_out, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) + + ! check that these are valid: + IF (t_initial_out /= t_initial) CALL SetErrStat(ErrID_Fatal, "invalid value of t_initial.", ErrStat, ErrMsg, RoutineName ) + IF (NumTurbines_out /= 1) CALL SetErrStat(ErrID_Fatal, "invalid value of NumTurbines.", ErrStat, ErrMsg, RoutineName ) + + + ! transfer Fortran variables to C: + n_t_global_c = n_t_global + AbortErrLev_c = AbortErrLev + NumOuts_c = min(MAXOUTPUTS, 1 + SUM( Turbine(iTurb)%y_FAST%numOuts )) ! includes time + dt_c = Turbine(iTurb)%p_FAST%dt + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + +end subroutine FAST_Restart +!================================================================================================================================== +subroutine FAST_OpFM_Init(iTurb, TMax, InputFileName_c, TurbID, NumSC2Ctrl, NumCtrl2SC, NumActForcePtsBlade, NumActForcePtsTower, TurbPosn, AbortErrLev_c, dt_c, NumBl_c, NumBlElem_c, & + OpFM_Input_from_FAST, OpFM_Output_to_FAST, SC_Input_from_FAST, SC_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_OpFM_Init') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Init +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Init +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + REAL(C_DOUBLE), INTENT(IN ) :: TMax + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) + INTEGER(C_INT), INTENT(IN ) :: TurbID ! Need not be same as iTurb + INTEGER(C_INT), INTENT(IN ) :: NumSC2Ctrl ! Supercontroller outputs = controller inputs + INTEGER(C_INT), INTENT(IN ) :: NumCtrl2SC ! controller outputs = Supercontroller inputs + INTEGER(C_INT), INTENT(IN ) :: NumActForcePtsBlade ! number of actuator line force points in blade + INTEGER(C_INT), INTENT(IN ) :: NumActForcePtsTower ! number of actuator line force points in tower + REAL(C_FLOAT), INTENT(IN ) :: TurbPosn(3) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: NumBl_c + INTEGER(C_INT), INTENT( OUT) :: NumBlElem_c + TYPE(OpFM_InputType_C), INTENT( OUT) :: OpFM_Input_from_FAST + TYPE(OpFM_OutputType_C),INTENT( OUT) :: OpFM_Output_to_FAST + TYPE(SC_InputType_C), INTENT(INOUT) :: SC_Input_from_FAST + TYPE(SC_OutputType_C), INTENT(INOUT) :: SC_Output_to_FAST + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + ! local + CHARACTER(IntfStrLen) :: InputFileName + INTEGER(C_INT) :: i + TYPE(FAST_ExternInitType) :: ExternInitData + + ! transfer the character array from C to a Fortran string: + InputFileName = TRANSFER( InputFileName_c, InputFileName ) + I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... + IF ( I > 0 ) InputFileName = InputFileName(1:I) ! remove it + + ! initialize variables: + n_t_global = 0 + ErrStat = ErrID_None + ErrMsg = "" + + ExternInitData%TMax = TMax + ExternInitData%TurbineID = TurbID + ExternInitData%TurbinePos = TurbPosn + ExternInitData%SensorType = SensorType_None + ExternInitData%NumCtrl2SC = NumCtrl2SC + ExternInitData%NumSC2Ctrl = NumSC2Ctrl + ExternInitData%NumActForcePtsBlade = NumActForcePtsBlade + ExternInitData%NumActForcePtsTower = NumActForcePtsTower + + CALL FAST_InitializeAll_T( t_initial, 1_IntKi, Turbine(iTurb), ErrStat, ErrMsg, InputFileName, ExternInitData ) + + ! set values for return to OpenFOAM + AbortErrLev_c = AbortErrLev + dt_c = Turbine(iTurb)%p_FAST%dt + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL WrScr( "Error in FAST_OpFM_Init:FAST_InitializeAll_T" // TRIM(ErrMsg) ) + IF (ALLOCATED(Turbine)) DEALLOCATE(Turbine) + RETURN + END IF + + call SetOpenFOAM_pointers(iTurb, OpFM_Input_from_FAST, OpFM_Output_to_FAST, SC_Input_from_FAST, SC_Output_to_FAST) + + ! 7-Sep-2015: Sang wants these integers for the OpenFOAM mapping, which is tied to the AeroDyn nodes. FAST doesn't restrict the number of nodes on each + ! blade mesh to be the same, so if this DOES ever change, we'll need to make OpenFOAM less tied to the AeroDyn mapping. + IF (Turbine(iTurb)%p_FAST%CompAero == MODULE_AD14) THEN + NumBl_c = SIZE(Turbine(iTurb)%AD14%Input(1)%InputMarkers) + NumBlElem_c = Turbine(iTurb)%AD14%Input(1)%InputMarkers(1)%Nnodes + ELSEIF (Turbine(iTurb)%p_FAST%CompAero == MODULE_AD) THEN + NumBl_c = SIZE(Turbine(iTurb)%AD%Input(1)%BladeMotion) + NumBlElem_c = Turbine(iTurb)%AD%Input(1)%BladeMotion(1)%Nnodes + ELSE + NumBl_c = 0 + NumBlElem_c = 0 + END IF + +end subroutine +!================================================================================================================================== +subroutine FAST_OpFM_Solution0(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_OpFM_Solution0') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Solution0 +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Solution0 +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + if(Turbine(iTurb)%SC%p%scOn) then + CALL SC_SetOutputs(Turbine(iTurb)%p_FAST, Turbine(iTurb)%SrvD%Input(1), Turbine(iTurb)%SC, ErrStat, ErrMsg) + end if + + call FAST_Solution0_T(Turbine(iTurb), ErrStat, ErrMsg ) + + if(Turbine(iTurb)%SC%p%scOn) then + CALL SC_SetInputs(Turbine(iTurb)%p_FAST, Turbine(iTurb)%SrvD%y, Turbine(iTurb)%SC, ErrStat, ErrMsg) + end if + + ! set values for return to OpenFOAM + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + + +end subroutine FAST_OpFM_Solution0 +!================================================================================================================================== +subroutine FAST_OpFM_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c, numblades_c, numElementsPerBlade_c, n_t_global_c, & + OpFM_Input_from_FAST, OpFM_Output_to_FAST, SC_Input_from_FAST, SC_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_OpFM_Restart') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Restart +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Restart +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT( OUT) :: numblades_c + INTEGER(C_INT), INTENT( OUT) :: numElementsPerBlade_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: n_t_global_c + TYPE(OpFM_InputType_C), INTENT( OUT) :: OpFM_Input_from_FAST + TYPE(OpFM_OutputType_C),INTENT( OUT) :: OpFM_Output_to_FAST + TYPE(SC_InputType_C), INTENT(INOUT) :: SC_Input_from_FAST + TYPE(SC_OutputType_C), INTENT(INOUT) :: SC_Output_to_FAST + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + ! local variables + INTEGER(C_INT) :: NumOuts_c + CHARACTER(IntfStrLen) :: CheckpointRootName + INTEGER(IntKi) :: I + INTEGER(IntKi) :: Unit + REAL(DbKi) :: t_initial_out + INTEGER(IntKi) :: NumTurbines_out + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + + CALL NWTC_Init() + ! transfer the character array from C to a Fortran string: + CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) + I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... + IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it + + Unit = -1 + CALL FAST_RestoreFromCheckpoint_T(t_initial_out, n_t_global, NumTurbines_out, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) + + ! check that these are valid: + IF (t_initial_out /= t_initial) CALL SetErrStat(ErrID_Fatal, "invalid value of t_initial.", ErrStat, ErrMsg, RoutineName ) + IF (NumTurbines_out /= 1) CALL SetErrStat(ErrID_Fatal, "invalid value of NumTurbines.", ErrStat, ErrMsg, RoutineName ) + + ! transfer Fortran variables to C: + n_t_global_c = n_t_global + AbortErrLev_c = AbortErrLev + NumOuts_c = min(MAXOUTPUTS, 1 + SUM( Turbine(iTurb)%y_FAST%numOuts )) ! includes time + numBlades_c = Turbine(iTurb)%ad%p%numblades + numElementsPerBlade_c = Turbine(iTurb)%ad%p%numblnds ! I'm not sure if FASTv8 can handle different number of blade nodes for each blade. + dt_c = Turbine(iTurb)%p_FAST%dt + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + +#ifdef CONSOLE_FILE + if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) +#endif + + call SetOpenFOAM_pointers(iTurb, OpFM_Input_from_FAST, OpFM_Output_to_FAST, SC_Input_from_FAST, SC_Output_to_FAST) + +end subroutine FAST_OpFM_Restart +!================================================================================================================================== +subroutine SetOpenFOAM_pointers(iTurb, OpFM_Input_from_FAST, OpFM_Output_to_FAST, SC_Input_from_FAST, SC_Output_to_FAST) + + IMPLICIT NONE + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + TYPE(OpFM_InputType_C), INTENT(INOUT) :: OpFM_Input_from_FAST + TYPE(OpFM_OutputType_C),INTENT(INOUT) :: OpFM_Output_to_FAST + TYPE(SC_InputType_C), INTENT(INOUT) :: SC_Input_from_FAST + TYPE(SC_OutputType_C), INTENT(INOUT) :: SC_Output_to_FAST + + OpFM_Input_from_FAST%pxVel_Len = Turbine(iTurb)%OpFM%u%c_obj%pxVel_Len; OpFM_Input_from_FAST%pxVel = Turbine(iTurb)%OpFM%u%c_obj%pxVel + OpFM_Input_from_FAST%pyVel_Len = Turbine(iTurb)%OpFM%u%c_obj%pyVel_Len; OpFM_Input_from_FAST%pyVel = Turbine(iTurb)%OpFM%u%c_obj%pyVel + OpFM_Input_from_FAST%pzVel_Len = Turbine(iTurb)%OpFM%u%c_obj%pzVel_Len; OpFM_Input_from_FAST%pzVel = Turbine(iTurb)%OpFM%u%c_obj%pzVel + OpFM_Input_from_FAST%pxForce_Len = Turbine(iTurb)%OpFM%u%c_obj%pxForce_Len; OpFM_Input_from_FAST%pxForce = Turbine(iTurb)%OpFM%u%c_obj%pxForce + OpFM_Input_from_FAST%pyForce_Len = Turbine(iTurb)%OpFM%u%c_obj%pyForce_Len; OpFM_Input_from_FAST%pyForce = Turbine(iTurb)%OpFM%u%c_obj%pyForce + OpFM_Input_from_FAST%pzForce_Len = Turbine(iTurb)%OpFM%u%c_obj%pzForce_Len; OpFM_Input_from_FAST%pzForce = Turbine(iTurb)%OpFM%u%c_obj%pzForce + OpFM_Input_from_FAST%xdotForce_Len = Turbine(iTurb)%OpFM%u%c_obj%xdotForce_Len; OpFM_Input_from_FAST%xdotForce = Turbine(iTurb)%OpFM%u%c_obj%xdotForce + OpFM_Input_from_FAST%ydotForce_Len = Turbine(iTurb)%OpFM%u%c_obj%ydotForce_Len; OpFM_Input_from_FAST%ydotForce = Turbine(iTurb)%OpFM%u%c_obj%ydotForce + OpFM_Input_from_FAST%zdotForce_Len = Turbine(iTurb)%OpFM%u%c_obj%zdotForce_Len; OpFM_Input_from_FAST%zdotForce = Turbine(iTurb)%OpFM%u%c_obj%zdotForce + OpFM_Input_from_FAST%pOrientation_Len = Turbine(iTurb)%OpFM%u%c_obj%pOrientation_Len; OpFM_Input_from_FAST%pOrientation = Turbine(iTurb)%OpFM%u%c_obj%pOrientation + OpFM_Input_from_FAST%fx_Len = Turbine(iTurb)%OpFM%u%c_obj%fx_Len; OpFM_Input_from_FAST%fx = Turbine(iTurb)%OpFM%u%c_obj%fx + OpFM_Input_from_FAST%fy_Len = Turbine(iTurb)%OpFM%u%c_obj%fy_Len; OpFM_Input_from_FAST%fy = Turbine(iTurb)%OpFM%u%c_obj%fy + OpFM_Input_from_FAST%fz_Len = Turbine(iTurb)%OpFM%u%c_obj%fz_Len; OpFM_Input_from_FAST%fz = Turbine(iTurb)%OpFM%u%c_obj%fz + OpFM_Input_from_FAST%momentx_Len = Turbine(iTurb)%OpFM%u%c_obj%momentx_Len; OpFM_Input_from_FAST%momentx = Turbine(iTurb)%OpFM%u%c_obj%momentx + OpFM_Input_from_FAST%momenty_Len = Turbine(iTurb)%OpFM%u%c_obj%momenty_Len; OpFM_Input_from_FAST%momenty = Turbine(iTurb)%OpFM%u%c_obj%momenty + OpFM_Input_from_FAST%momentz_Len = Turbine(iTurb)%OpFM%u%c_obj%momentz_Len; OpFM_Input_from_FAST%momentz = Turbine(iTurb)%OpFM%u%c_obj%momentz + OpFM_Input_from_FAST%forceNodesChord_Len = Turbine(iTurb)%OpFM%u%c_obj%forceNodesChord_Len; OpFM_Input_from_FAST%forceNodesChord = Turbine(iTurb)%OpFM%u%c_obj%forceNodesChord + OpFM_Input_from_FAST%SuperController_Len = Turbine(iTurb)%OpFM%u%c_obj%SuperController_Len + OpFM_Input_from_FAST%SuperController = Turbine(iTurb)%OpFM%u%c_obj%SuperController + + SC_Input_from_FAST%toSC_Len = Turbine(iTurb)%SC%u%c_obj%toSC_Len + SC_Input_from_FAST%toSC = Turbine(iTurb)%SC%u%c_obj%toSC + + OpFM_Output_to_FAST%u_Len = Turbine(iTurb)%OpFM%y%c_obj%u_Len; OpFM_Output_to_FAST%u = Turbine(iTurb)%OpFM%y%c_obj%u + OpFM_Output_to_FAST%v_Len = Turbine(iTurb)%OpFM%y%c_obj%v_Len; OpFM_Output_to_FAST%v = Turbine(iTurb)%OpFM%y%c_obj%v + OpFM_Output_to_FAST%w_Len = Turbine(iTurb)%OpFM%y%c_obj%w_Len; OpFM_Output_to_FAST%w = Turbine(iTurb)%OpFM%y%c_obj%w + OpFM_Output_to_FAST%SuperController_Len = Turbine(iTurb)%OpFM%y%c_obj%SuperController_Len + OpFM_Output_to_FAST%SuperController = Turbine(iTurb)%OpFM%y%c_obj%SuperController + + SC_Output_to_FAST%fromSC_Len = Turbine(iTurb)%SC%y%c_obj%fromSC_Len + SC_Output_to_FAST%fromSC = Turbine(iTurb)%SC%y%c_obj%fromSC + +end subroutine SetOpenFOAM_pointers +!================================================================================================================================== +subroutine FAST_OpFM_Step(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_OpFM_Step') + IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Step +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_OpFM_Step +#endif + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + + + IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish + + ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation + + if (iTurb .eq. (NumTurbines-1) ) then + IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved + n_t_global = n_t_global + 1 + ErrStat_c = ErrID_None + ErrMsg = C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + ELSE + ErrStat_c = ErrID_Info + ErrMsg = "Simulation completed."//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + END IF + end if + + ELSE + + if(Turbine(iTurb)%SC%p%scOn) then + CALL SC_SetOutputs(Turbine(iTurb)%p_FAST, Turbine(iTurb)%SrvD%Input(1), Turbine(iTurb)%SC, ErrStat, ErrMsg) + end if + + CALL FAST_Solution_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) + + if(Turbine(iTurb)%SC%p%scOn) then + CALL SC_SetInputs(Turbine(iTurb)%p_FAST, Turbine(iTurb)%SrvD%y, Turbine(iTurb)%SC, ErrStat, ErrMsg) + end if + + if (iTurb .eq. (NumTurbines-1) ) then + n_t_global = n_t_global + 1 + end if + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) + END IF + + +end subroutine FAST_OpFM_Step +!================================================================================================================================== +END MODULE FAST_Data diff --git a/OpenFAST/modules/openfast-library/src/FAST_Library.h b/OpenFAST/modules/openfast-library/src/FAST_Library.h new file mode 100644 index 000000000..494769c09 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Library.h @@ -0,0 +1,53 @@ +#ifndef FAST_LIBRARY_H +#define FAST_LIBRARY_H + +// routines in FAST_Library_$(PlatformName).dll +#include "OpenFOAM_Types.h" +#include "SuperController_Types.h" + +#ifdef __cplusplus +#define EXTERNAL_ROUTINE extern "C" +#else +#define EXTERNAL_ROUTINE extern +#endif + +EXTERNAL_ROUTINE void FAST_AllocateTurbines(int * iTurb, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_DeallocateTurbines(int *ErrStat, char *ErrMsg); + +EXTERNAL_ROUTINE void FAST_OpFM_Restart(int * iTurb, const char *CheckpointRootName, int *AbortErrLev, double * dt, int * NumBl, int * NumBlElem, int * n_t_global, + OpFM_InputType_t* OpFM_Input, OpFM_OutputType_t* OpFM_Output, SC_InputType_t* SC_Input, SC_OutputType_t* SC_Output, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_OpFM_Init(int * iTurb, double *TMax, const char *InputFileName, int * TurbineID, int * NumSC2Ctrl, int * NumCtrl2SC, int * NumActForcePtsBlade, int * NumActForcePtsTower, float * TurbinePosition, + int *AbortErrLev, double * dt, int * NumBl, int * NumBlElem, OpFM_InputType_t* OpFM_Input, OpFM_OutputType_t* OpFM_Output, SC_InputType_t* SC_Input, SC_OutputType_t* SC_Output, + int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_OpFM_Solution0(int * iTurb, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_OpFM_Step(int * iTurb, int *ErrStat, char *ErrMsg); + +EXTERNAL_ROUTINE void FAST_Restart(int * iTurb, const char *CheckpointRootName, int *AbortErrLev, int * NumOuts, double * dt, int * n_t_global, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_Sizes(int * iTurb, double *TMax, double *InitInputAry, const char *InputFileName, int *AbortErrLev, int * NumOuts, double * dt, int *ErrStat, char *ErrMsg, char *ChannelNames); +EXTERNAL_ROUTINE void FAST_Start(int * iTurb, int *NumInputs_c, int *NumOutputs_c, double *InputAry, double *OutputAry, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_Update(int * iTurb, int *NumInputs_c, int *NumOutputs_c, double *InputAry, double *OutputAry, int *ErrStat, char *ErrMsg); +EXTERNAL_ROUTINE void FAST_End(int * iTurb, bool * stopThisProgram); +EXTERNAL_ROUTINE void FAST_CreateCheckpoint(int * iTurb, const char *CheckpointRootName, int *ErrStat, char *ErrMsg); + +// some constants (keep these synced with values in FAST's fortran code) +#define INTERFACE_STRING_LENGTH 1025 + +#define ErrID_None 0 +#define ErrID_Info 1 +#define ErrID_Warn 2 +#define ErrID_Severe 3 +#define ErrID_Fatal 4 + + +#define SensorType_None -1 + +// make sure these parameters match with FAST_Library.f90 and NWTC_Base.f90 +#define MAXIMUM_BLADES 3 +#define MAXIMUM_OUTPUTS 4000 +#define CHANNEL_LENGTH 20 +#define MAXInitINPUTS 10 + +#define NumFixedInputs 2 + 2 + MAXIMUM_BLADES + 1 + + +#endif diff --git a/OpenFAST/modules/openfast-library/src/FAST_Lin.f90 b/OpenFAST/modules/openfast-library/src/FAST_Lin.f90 new file mode 100644 index 000000000..8b05043ad --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Lin.f90 @@ -0,0 +1,5633 @@ +!********************************************************************************************************************************** +! FAST_Solver.f90, FAST_Subs.f90, FAST_Lin.f90, and FAST_Mods.f90 make up the FAST glue code in the FAST Modularization Framework. +! FAST_Prog.f90, FAST_Library.f90, FAST_Prog.c are different drivers for this code. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! Copyright (C) 2018 Envision Energy USA, LTD +! +! This file is part of FAST. +! +! 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 FAST_Linear + + USE FAST_Solver ! I mostly just want the modules that are inherited from this module, not the routines in it + + IMPLICIT NONE + + CONTAINS +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that initializes some variables for linearization. +SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED input array) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: i, j, k ! loop/temp variables + INTEGER(IntKi) :: ThisModule ! Module ID # + INTEGER(IntKi) :: NumInstances ! Number of instances of each module + INTEGER(IntKi) :: NumStates ! Number of states required for the x_eig arrays + + INTEGER(IntKi) :: i_u ! loop/temp variables + INTEGER(IntKi) :: i_y, i_x ! loop/temp variables + + INTEGER(IntKi) :: NextStart(3) ! allocated to be size(LinStartIndx)=size(SizeLin); helps compute the next starting index for the module components + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Lin' + CHARACTER(200) :: ModAbrev + + + ErrStat = ErrID_None + ErrMsg = "" + + !..................... + ! determine the number of modules that will be linearized: + !..................... + p_FAST%Lin_NumMods = 0 + + ! InflowWind is first, if activated: + if ( p_FAST%CompInflow == Module_IfW ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_IfW + + call Init_Lin_IfW( p_FAST, y_FAST, AD%Input(1) ) ! overwrite some variables based on knowledge from glue code + + end if + + ! ServoDyn is next, if activated: + if ( p_FAST%CompServo == Module_SrvD ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_SrvD + end if + + + ! ElastoDyn is next; it is always activated: + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_ED + + ! BeamDyn is next, if activated: + if (p_FAST%CompElast == Module_BD) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_BD + end if + + ! AeroDyn is next, if activated: + if ( p_FAST%CompAero == Module_AD ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_AD + end if + + ! HydroDyn is next, if activated: + if ( p_FAST%CompHydro == Module_HD ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_HD + end if + + ! MAP is next, if activated: + if ( p_FAST%CompMooring == Module_MAP ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_MAP + end if + + ! ExtPtfm is next, if activated: + if ( p_FAST%CompSub == Module_ExtPtfm ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_ExtPtfm + end if + + !..................... + ! determine total number of inputs/outputs/contStates: + !..................... + y_FAST%Lin%Glue%SizeLin = 0 + y_FAST%Lin%Glue%NumOutputs = 0 + + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin = 0 + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_u)) y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_INPUT_COL) = size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_u) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_y)) y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) = size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_y) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_x)) y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) = size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_x) + + y_FAST%Lin%Glue%SizeLin = y_FAST%Lin%Glue%SizeLin + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin ! total number of inputs, outputs, and continuous states + + y_FAST%Lin%Glue%NumOutputs = y_FAST%Lin%Glue%NumOutputs + y_FAST%Lin%Modules(ThisModule)%Instance(k)%NumOutputs ! total number of WriteOutputs + end do + end do + + !..................... + ! compute the starting index in the combined (full) matrices: + !..................... + NextStart = 1 ! whole array + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%LinStartIndx = NextStart + NextStart = NextStart + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin + end do + end do + + + ! ................................... + ! determine which of the module inputs/outputs are written to file + ! ................................... + call Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! ................................... + ! get names of inputs, outputs, and continuous states + ! ................................... + call AllocAry( y_FAST%Lin%Glue%names_u, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'names_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%names_y, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'names_y', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%names_x, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'names_x', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%Use_u, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'use_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%Use_y, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'use_y', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%RotFrame_u, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'RotFrame_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%RotFrame_y, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'RotFrame_y', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%RotFrame_x, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'RotFrame_x', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%DerivOrder_x, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'DerivOrder_x', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%IsLoad_u, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'IsLoad_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + + i_u = 1 + i_y = 1 + i_x = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + ModAbrev = y_FAST%Module_Abrev(ThisModule) + NumInstances = size(y_FAST%Lin%Modules(ThisModule)%Instance) + + ! inputs + do k=1,NumInstances + if (NumInstances > 1 .or. trim(y_FAST%Module_Abrev(ThisModule)) == "BD") then + ModAbrev = TRIM(y_FAST%Module_Abrev(ThisModule))//'_'//trim(num2lstr(k)) + end if + + do j=1,y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_INPUT_COL) + y_FAST%Lin%Glue%names_u(i_u) = TRIM(ModAbrev)//' '//y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_u(j) + y_FAST%Lin%Glue%use_u( i_u) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_u(j) + y_FAST%Lin%Glue%IsLoad_u(i_u) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%IsLoad_u(j) + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_u)) then + y_FAST%Lin%Glue%RotFrame_u(i_u) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_u(j) + else + y_FAST%Lin%Glue%RotFrame_u(i_u) = .false. + end if + i_u = i_u + 1; + end do + + end do + + ! outputs + do k=1,NumInstances + if (NumInstances > 1 .or. trim(y_FAST%Module_Abrev(ThisModule)) == "BD") then + ModAbrev = TRIM(y_FAST%Module_Abrev(ThisModule))//'_'//trim(num2lstr(k)) + end if + + do j=1,y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) + y_FAST%Lin%Glue%names_y(i_y) = TRIM(ModAbrev)//' '//y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_y(j) + y_FAST%Lin%Glue%use_y( i_y) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_y(j) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_y)) then + y_FAST%Lin%Glue%RotFrame_y(i_y) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_y(j) + else + y_FAST%Lin%Glue%RotFrame_y(i_y) = .false. + end if + i_y = i_y + 1; + end do + end do + + ! continuous states + do k=1,NumInstances + if (NumInstances > 1 .or. trim(y_FAST%Module_Abrev(ThisModule)) == "BD") then + ModAbrev = TRIM(y_FAST%Module_Abrev(ThisModule))//'_'//trim(num2lstr(k)) + end if + + if (y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) > 0) then + if (p_FAST%WrVTK == VTK_ModeShapes) then ! allocate these for restart later + if (ThisModule == Module_ED) then + ! ED has only the active DOFs as the continuous states, but to perturb the OP [Perterb_OP()], we need all of the DOFs + NumStates = ED%p%NDOF*2 + else + NumStates = y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + end if + + call AllocAry( y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag, NumStates, 'op_x_eig_mag', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_phase, NumStates, 'op_x_eig_phase', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) return + + y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag = 0.0_R8Ki + y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_phase = 0.0_R8Ki + end if + end if + + + do j=1,y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + y_FAST%Lin%Glue%names_x( i_x) = TRIM(ModAbrev)//' '//y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_x( j) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_x)) then + y_FAST%Lin%Glue%RotFrame_x(i_x) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%RotFrame_x(j) + else + y_FAST%Lin%Glue%RotFrame_x(i_x) = .false. + end if + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%DerivOrder_x)) then + y_FAST%Lin%Glue%DerivOrder_x(i_x) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%DerivOrder_x(j) + else + y_FAST%Lin%Glue%DerivOrder_x(i_x) = 0 + end if + i_x = i_x + 1; + end do + end do + + end do ! each module + + + !..................... + ! initialize variables for periodic steady state solution + !..................... + + m_FAST%Lin%NextLinTimeIndx = 1 + m_FAST%Lin%CopyOP_CtrlCode = MESH_NEWCOPY + m_FAST%Lin%n_rot = 0 + m_FAST%Lin%IsConverged = .false. + m_FAST%Lin%FoundSteady = .false. + m_FAST%Lin%AzimIndx = 1 + + p_FAST%AzimDelta = TwoPi / p_FAST%NLinTimes + + ! allocate space to save operating points + if (p_FAST%CalcSteady .or. p_FAST%WrVTK==VTK_ModeShapes) then + + call AllocateOP(p_FAST, y_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! allocate spaces for variables needed to determine + if (p_FAST%CalcSteady) then + + !call AllocAry(m_FAST%Lin%AzimTarget, p_FAST%NLinTimes,'AzimTarget', ErrStat2, ErrMsg2) + allocate( m_FAST%Lin%AzimTarget(0 : p_FAST%NLinTimes+1), stat=ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal,"Unable to allocate space for AzimTarget.",ErrStat,ErrMsg,RoutineName) + end if + + call AllocAry( m_FAST%Lin%LinTimes, p_FAST%NLinTimes, 'LinTimes', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AllocAry( m_FAST%Lin%Psi, p_FAST%LinInterpOrder+1, 'Psi', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! these flattened output arrays will contain spaces for %WriteOutputs, which are being ignored for purposes of CalcSteady computations + call AllocAry( m_FAST%Lin%y_interp, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'y_interp', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AllocAry( m_FAST%Lin%Y_prevRot, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), p_FAST%NLinTimes, 'Y_prevRot', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AllocAry( m_FAST%Lin%y_ref, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'y_ref', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (ErrStat < AbortErrLev) then + m_FAST%Lin%y_interp = 0.0_R8Ki + m_FAST%Lin%Y_prevRot = 0.0_R8Ki + m_FAST%Lin%y_ref = 1.0_R8Ki + end if + + end if + + end if + + +END SUBROUTINE Init_Lin +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that initializes the names and rotating frame portion of IfW. +SUBROUTINE Init_Lin_IfW( p_FAST, y_FAST, u_AD ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(AD_InputType), INTENT(IN) :: u_AD !< The input meshes (already calculated) from AeroDyn + + INTEGER(IntKi) :: i, j, k ! loop counters + INTEGER(IntKi) :: i2 ! loop counters + INTEGER(IntKi) :: Node ! InflowWind node number + CHARACTER(25) :: NodeDesc ! Node description + INTEGER(IntKi) :: position ! position in string + + + ! compare with IfW_InputSolve(): + + Node = 0 !InflowWind node + + ! I'm going to overwrite some of the input/output descriptions + if (p_FAST%CompServo == MODULE_SrvD) then + Node = Node + 1 + NodeDesc = ' (hub)' + + do i=1,3 + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i)(position+1:) + end do + do i=1,3 + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i)(position+1:) + end do + end if + + IF (p_FAST%CompAero == MODULE_AD) THEN + + DO K = 1,SIZE(u_AD%BladeMotion) + DO J = 1,u_AD%BladeMotion(k)%Nnodes + Node = Node + 1 ! InflowWind node + NodeDesc = ' (blade '//trim(num2lstr(k))//', node '//trim(num2lstr(j))//')' + + do i=1,3 !XYZ components of this node + i2 = (Node-1)*3 + i + + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2)(position+1:) + + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2)(position+1:) + + ! IfW has inputs and outputs in the global frame + !y_FAST%Lin%Modules(Module_IfW)%Instance(1)%RotFrame_u(i2) = .true. + !y_FAST%Lin%Modules(Module_IfW)%Instance(1)%RotFrame_y(i2) = .true. + + end do + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + END DO !K = 1,p%NumBl + + ! tower: + DO J=1,u_AD%TowerMotion%nnodes + Node = Node + 1 + NodeDesc = ' (Tower node '//trim(num2lstr(j))//')' + + do i=1,3 !XYZ components of this node + i2 = (Node-1)*3 + i + + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_u(i2)(position+1:) + + position = index(y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2), ',') - 1 + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2) = y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2)(1:position)//trim(NodeDesc)//& + y_FAST%Lin%Modules(Module_IfW)%Instance(1)%Names_y(i2)(position+1:) + end do + END DO + + END IF + +END SUBROUTINE Init_Lin_IfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that initializes some use_u and use_y, which determine which, if any, inputs and outputs are output in the linearization file. +SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED input array) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: i, j, col ! loop/temp variables + INTEGER(IntKi) :: k ! loop/temp variables + INTEGER(IntKi) :: ThisModule ! Module ID # + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Init_Lin_InputOutput' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! ................................... + ! allocate module arrays + ! ................................... + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + call AllocAry ( y_FAST%Lin%Modules(ThisModule)%Instance(k)%Use_u, size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_u), TRIM(y_FAST%Module_Abrev(ThisModule))//'_Use_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry ( y_FAST%Lin%Modules(ThisModule)%Instance(k)%Use_y, size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%Names_y), TRIM(y_FAST%Module_Abrev(ThisModule))//'_Use_y', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end do + + end do + if (ErrStat >= AbortErrLev) return + + + ! ................................... + ! set true/false flags for inputs: + ! ................................... + + if (p_FAST%LinInputs == LIN_NONE) then + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_u = .false. + end do + end do + elseif(p_FAST%LinInputs == LIN_STANDARD) then + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_u = .false. + end do + end do + + ! ED standard inputs: BlPitchCom, YawMom, GenTrq, extended input (collective pitch) + do j=1,NumBl+3 + y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + + ! IfW standard inputs: HWindSpeed, PLexp, PropagationDir + if (p_FAST%CompInflow == MODULE_IfW) then + do j = 1,3 + y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + end if + + ! HD standard inputs: WaveElev0 + if (p_FAST%CompHydro == MODULE_HD) then + y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%SizeLin(LIN_INPUT_COL)) = .true. + end if + + !bjj: removed because I'm not sure these should be included in the "standard" inputs + !!!! ExtPtfm standard inputs: x1, x1dot x1ddot ! TODO TODO TODO CHECK + !!!if (p_FAST%CompSub == MODULE_ExtPtfm) then + !!! do j = 1,18 + !!! y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + !!! end do + !!!end if + + elseif(p_FAST%LinInputs == LIN_ALL) then + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_u = .true. + end do + end do + end if + + + ! ................................... + ! set true/false flags for outputs: + ! ................................... + + if (p_FAST%LinOutputs == LIN_NONE) then + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_y = .false. + end do + end do + elseif(p_FAST%LinOutputs == LIN_STANDARD) then + + ! WriteOutput values are the last entries of the modules + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + col = y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) - y_FAST%Lin%Modules(ThisModule)%Instance(k)%NumOutputs !last column before WriteOutput occurs + do j=1,col + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_y(j) = .false. + end do + do j=col+1,y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_y(j) = .true. + end do + end do + end do + + elseif(p_FAST%LinOutputs == LIN_ALL) then + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + y_FAST%Lin%Modules(ThisModule)%Instance(k)%use_y = .true. + end do + end do + end if + + +END SUBROUTINE Init_Lin_InputOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that performs lineaization at current operating point for a turbine. +SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, MeshMapData, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_global !< current (global) simulation time + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: Un ! unit number for linearization output file (written in two parts) + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Linearize_OP' + + REAL(R8Ki), ALLOCATABLE :: dUdu(:,:), dUdy(:,:) ! variables for glue-code linearization + integer(intki) :: NumBl + integer(intki) :: k + CHARACTER(1024) :: LinRootName + CHARACTER(1024) :: OutFileName + CHARACTER(200) :: SimStr + CHARACTER(MaxWrScrLen) :: BlankLine + CHARACTER(*), PARAMETER :: Fmt = 'F10.2' + + + + ErrStat = ErrID_None + ErrMsg = "" + Un = -1 + + !..................... + SimStr = '(RotSpeed='//trim(num2lstr(ED%y%RotSpeed*RPS2RPM,Fmt))//' rpm, BldPitch1='//trim(num2lstr(ED%y%BlPitch(1)*R2D,Fmt))//' deg)' + + BlankLine = "" + CALL WrOver( BlankLine ) ! BlankLine contains MaxWrScrLen spaces + CALL WrOver ( ' Performing linearization '//trim(num2lstr(m_FAST%Lin%NextLinTimeIndx))//' at simulation time '//TRIM( Num2LStr(t_global) )//' s. '//trim(SimStr) ) + CALL WrScr('') + + !..................... + + LinRootName = TRIM(p_FAST%OutFileRoot)//'.'//trim(num2lstr(m_FAST%Lin%NextLinTimeIndx)) + + if (p_FAST%WrVTK == VTK_ModeShapes .and. .not. p_FAST%CalcSteady) then ! we already saved these for the CalcSteady case + call SaveOP(m_FAST%Lin%NextLinTimeIndx, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg, m_FAST%Lin%CopyOP_CtrlCode ) + !m_FAST%Lin%CopyOP_CtrlCode = MESH_UPDATECOPY ! we need a new copy for each LinTime + end if + + + NumBl = size(ED%Input(1)%BlPitchCom) + y_FAST%Lin%RotSpeed = ED%y%RotSpeed + y_FAST%Lin%Azimuth = ED%y%LSSTipPxa + !..................... + ! ElastoDyn + !..................... + ! get the jacobians + call ED_JacobianPInput( t_global, ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y, ED%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_ED)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_ED)%Instance(1)%B ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call ED_JacobianPContState( t_global, ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y, ED%m, ErrStat2, ErrMsg2, dYdx=y_FAST%Lin%Modules(Module_ED)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_ED)%Instance(1)%A ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call ED_GetOP( t_global, ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y, ED%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_ED)%Instance(1)%op_u, & + y_op=y_FAST%Lin%Modules(Module_ED)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_ED)%Instance(1)%op_x, & + dx_op=y_FAST%Lin%Modules(Module_ED)%Instance(1)%op_dx ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_ED)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_ED)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dXdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_ED)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx' ) + + !dXdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_ED)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_ED)%Instance(1)%use_u ) + + ! dYdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_ED)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_ED)%Instance(1)%use_y ) + + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_ED)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_ED)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_ED)%Instance(1)%use_u ) + + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_ED)%Instance(1) ) + + end if + + !..................... + ! BeamDyn + !..................... + if ( p_FAST%CompElast == Module_BD ) then + do k=1,p_FAST%nBeams + + ! get the jacobians + call BD_JacobianPInput( t_global, BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), BD%OtherSt(k,STATE_CURR), & + BD%y(k), BD%m(k), ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_BD)%Instance(k)%D, & + dXdu=y_FAST%Lin%Modules(Module_BD)%Instance(k)%B, & + StateRel_x =y_FAST%Lin%Modules(Module_BD)%Instance(k)%StateRel_x, & + StateRel_xdot=y_FAST%Lin%Modules(Module_BD)%Instance(k)%StateRel_xdot ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call BD_JacobianPContState( t_global, BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), BD%OtherSt(k,STATE_CURR), & + BD%y(k), BD%m(k), ErrStat2, ErrMsg2, dYdx=y_FAST%Lin%Modules(Module_BD)%Instance(k)%C, dXdx=y_FAST%Lin%Modules(Module_BD)%Instance(k)%A, & + StateRotation=y_FAST%Lin%Modules(Module_BD)%Instance(k)%StateRotation) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call BD_GetOP( t_global, BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), BD%OtherSt(k,STATE_CURR), & + BD%y(k), BD%m(k), ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_BD)%Instance(k)%op_u, y_op=y_FAST%Lin%Modules(Module_BD)%Instance(k)%op_y, & + x_op=y_FAST%Lin%Modules(Module_BD)%Instance(k)%op_x, dx_op=y_FAST%Lin%Modules(Module_BD)%Instance(k)%op_dx ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_BD))//TRIM(num2lstr(k)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_BD)%Instance(k), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dXdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_BD)%Instance(k)%A, Un, p_FAST%OutFmt, 'dXdx' ) + + !dXdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_BD)%Instance(k)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_BD)%Instance(k)%use_u ) + + !dYdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_BD)%Instance(k)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_BD)%Instance(k)%use_y ) + + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_BD)%Instance(k)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_BD)%Instance(k)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_BD)%Instance(k)%use_u ) + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_BD)%Instance(k) ) + end if + + end do + end if !BeamDyn + + + !..................... + ! InflowWind + !..................... + if ( p_FAST%CompInflow == Module_IfW ) then + + ! get the jacobians + call InflowWind_JacobianPInput( t_global, IfW%Input(1), IfW%p, IfW%x(STATE_CURR), IfW%xd(STATE_CURR), IfW%z(STATE_CURR), & + IfW%OtherSt(STATE_CURR), IfW%y, IfW%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%D ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call InflowWind_GetOP( t_global, IfW%Input(1), IfW%p, IfW%x(STATE_CURR), IfW%xd(STATE_CURR), IfW%z(STATE_CURR), & + IfW%OtherSt(STATE_CURR), IfW%y, IfW%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%op_u, & + y_op=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%op_y ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_IfW)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_IfW)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_IfW)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', & + UseRow=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%use_y, UseCol=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%use_u ) + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_IfW)%Instance(1) ) + + end if + + end if + + !..................... + ! ServoDyn + !..................... + if ( p_FAST%CompServo == Module_SrvD ) then + ! get the jacobians + call SrvD_JacobianPInput( t_global, SrvD%Input(1), SrvD%p, SrvD%x(STATE_CURR), SrvD%xd(STATE_CURR), SrvD%z(STATE_CURR), & + SrvD%OtherSt(STATE_CURR), SrvD%y, SrvD%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%D ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call SrvD_GetOP( t_global, SrvD%Input(1), SrvD%p, SrvD%x(STATE_CURR), SrvD%xd(STATE_CURR), SrvD%z(STATE_CURR), & + SrvD%OtherSt(STATE_CURR), SrvD%y, SrvD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%op_u, & + y_op=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%op_y ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SrvD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SrvD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! Jacobians + if (p_FAST%LinOutJac) then + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', & + UseRow=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%use_y, UseCol=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%use_u ) + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_SrvD)%Instance(1) ) + + end if + end if + + !..................... + ! AeroDyn + !..................... + if ( p_FAST%CompAero == Module_AD ) then + ! get the jacobians + call AD_JacobianPInput( t_global, AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), & + AD%OtherSt(STATE_CURR), AD%y, AD%m, ErrStat2, ErrMsg2, & + dXdu=y_FAST%Lin%Modules(Module_AD)%Instance(1)%B, & + dYdu=y_FAST%Lin%Modules(Module_AD)%Instance(1)%D ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call AD_JacobianPContState( t_global, AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), & + AD%OtherSt(STATE_CURR), AD%y, AD%m, ErrStat2, ErrMsg2, & + dXdx=y_FAST%Lin%Modules(Module_AD)%Instance(1)%A, & + dYdx=y_FAST%Lin%Modules(Module_AD)%Instance(1)%C ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call AD_GetOP( t_global, AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), & + AD%OtherSt(STATE_CURR), AD%y, AD%m, ErrStat2, ErrMsg2, & + u_op=y_FAST%Lin%Modules(Module_AD)%Instance(1)%op_u, & + y_op=y_FAST%Lin%Modules(Module_AD)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_AD)%Instance(1)%op_x, & + dx_op=y_FAST%Lin%Modules(Module_AD)%Instance(1)%op_dx ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_AD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_AD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + call WrPartialMatrix( y_FAST%Lin%Modules(Module_AD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx' ) + + call WrPartialMatrix( y_FAST%Lin%Modules(Module_AD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', & + UseCol=y_FAST%Lin%Modules(Module_AD)%Instance(1)%use_u ) + + call WrPartialMatrix( y_FAST%Lin%Modules(Module_AD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', & + UseRow=y_FAST%Lin%Modules(Module_AD)%Instance(1)%use_y ) + + call WrPartialMatrix( y_FAST%Lin%Modules(Module_AD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', & + UseRow=y_FAST%Lin%Modules(Module_AD)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_AD)%Instance(1)%use_u ) + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_AD)%Instance(1) ) + end if + + end if + + !..................... + ! HydroDyn + !..................... + if ( p_FAST%CompHydro == Module_HD ) then + ! get the jacobians + call HD_JacobianPInput( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%B ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call HD_JacobianPContState( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, dYdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%A ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call HD_GetOP( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_u, y_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_dx ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_HD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dXdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx' ) + + !dXdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) + + !dYdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y ) + + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) + + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1) ) + + end if ! LIN-TODO: Check if this is really where we want to terminate the if block + end if + !..................... + ! MAP + !..................... + if ( p_FAST%CompMooring == Module_MAP ) then + ! LIN-TODO: We need this to compute the dYdu total derivative which is D for MAP, and the template uses OtherSt(STATE_CURR), but the FAST MAP DATA has OtherSt as a scalar + call MAP_JacobianPInput( t_global, MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), & + MAPp%OtherSt, MAPp%y, ErrStat2, ErrMsg2, y_FAST%Lin%Modules(Module_MAP)%Instance(1)%D ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! et the operating point + !LIN-TODO: template uses OtherSt(STATE_CURR), but the FAST MAP DATA has OtherSt as a scalar + call MAP_GetOP( t_global, MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), & + MAPp%OtherSt, MAPp%y, ErrStat2, ErrMsg2, & + y_FAST%Lin%Modules(Module_MAP)%Instance(1)%op_u, y_FAST%Lin%Modules(Module_MAP)%Instance(1)%op_y ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_MAP)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_MAP)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_MAP)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', & + UseRow=y_FAST%Lin%Modules(Module_MAP)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_MAP)%Instance(1)%use_u ) + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_MAP)%Instance(1) ) + + end if ! if ( p_FAST%LinOutMod ) + end if ! if ( p_FAST%CompMooring == Module_MAP ) + !..................... + ! ExtPtfm + !..................... + if ( p_FAST%CompSub == Module_ExtPtfm ) then + ! get the jacobians + call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & + ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & + dYdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B ) + if(Failed()) return; + + call ExtPtfm_JacobianPContState( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & + ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2,& + dYdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A ) + if(Failed()) return; + + ! get the operating point + call ExtPtfm_GetOP(t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR),& + ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_u,& + y_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_dx) + if(Failed()) return; + + ! write the module matrices: + if (p_FAST%LinOutMod) then + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_ExtPtfm)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) + if(Failed()) return; + + if (p_FAST%LinOutJac) then + ! Jacobians + call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx') + call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_u) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_y) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_u) + end if + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1) ) + end if + end if ! ExtPtfm + + + !..................... + ! Linearization of glue code Input/Output solve: + !..................... + + !..................... + ! Glue code (currently a linearization of SolveOption2): + ! Make sure we avoid any case where the operating point values change earlier in this routine (e.g., by calling the module Jacobian routines). + !..................... + + call Glue_GetOP(p_FAST, y_FAST, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! get the dUdu and dUdy matrices, which linearize SolveOption2 for the modules we've included in linearization + call Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, MAPp, FEAM, MD, Orca, & + IceF, IceD, MeshMapData, dUdu, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Glue, LinRootName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + if (p_FAST%LinOutJac) then + ! Jacobians + call WrPartialMatrix( dUdu, Un, p_FAST%OutFmt, 'dUdu', UseRow=y_FAST%Lin%Glue%use_u, UseCol=y_FAST%Lin%Glue%use_u ) + call WrPartialMatrix( dUdy, Un, p_FAST%OutFmt, 'dUdy', UseRow=y_FAST%Lin%Glue%use_u, UseCol=y_FAST%Lin%Glue%use_y ) + end if + + + ! calculate the glue-code state matrices + call Glue_StateMatrices( p_FAST, y_FAST, dUdu, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + ! Write the results to the file: + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Glue ) + + m_FAST%Lin%NextLinTimeIndx = m_FAST%Lin%NextLinTimeIndx + 1 + +contains + logical function Failed() + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + Failed = ErrStat >= AbortErrLev + if(Failed) call cleanup() + end function Failed + subroutine cleanup() + + if (allocated(dUdu)) deallocate(dUdu) + if (allocated(dUdy)) deallocate(dUdy) + + if (Un > 0) close(Un) + + end subroutine cleanup +END SUBROUTINE FAST_Linearize_OP +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that writes the A,B,C,D matrices from linearization to a text file. +SUBROUTINE WrLinFile_txt_Head(t_global, p_FAST, y_FAST, LinData, FileName, Un, ErrStat, ErrMsg) + + INTEGER(IntKi), INTENT( OUT) :: Un !< unit number + REAL(DbKi), INTENT(IN ) :: t_global !< current (global) simulation time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameters + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(FAST_LinType), INTENT(IN ) :: LinData !< Linearization data for individual module or glue (coupled system) + CHARACTER(*), INTENT(IN ) :: FileName !< root name of the linearization file to open for writing + 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 ! loop counter + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'WrLinFile_txt_Head' + INTEGER(IntKi) :: n(5) ! sizes of arrays to print + CHARACTER(*), PARAMETER :: TypeNames(5) = (/ 'continuous states', & + 'discrete states ', & + 'constraint states', & + 'inputs ', & + 'outputs ' /) + CHARACTER(50) :: Fmt + CHARACTER(32) :: Desc + + integer, parameter :: Indx_x = 1 + integer, parameter :: Indx_xd = 2 + integer, parameter :: Indx_z = 3 + integer, parameter :: Indx_u = 4 + integer, parameter :: Indx_y = 5 + + + ErrStat = ErrID_None + ErrMsg = "" + + n = 0; + if (allocated(LinData%names_x )) n(Indx_x) = size(LinData%names_x ) + if (allocated(LinData%names_xd)) n(Indx_xd) = size(LinData%names_xd) + if (allocated(LinData%names_z )) n(Indx_z) = size(LinData%names_z ) + !if (allocated(LinData%names_u )) n(Indx_u) = size(LinData%names_u ) + !if (allocated(LinData%names_y )) n(Indx_y) = size(LinData%names_y ) + + if (allocated(LinData%names_u )) then + do i=1,size(LinData%use_u) + if (LinData%use_u(i)) n(Indx_u) = n(Indx_u)+1 + end do + end if + + if (allocated(LinData%names_y )) then + do i=1,size(LinData%use_y) + if (LinData%use_y(i)) n(Indx_y) = n(Indx_y)+1 + end do + end if + + + CALL GetNewUnit( Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + Un = -1 + return + end if + + CALL OpenFOutFile ( Un, TRIM(FileName)//'.lin', ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + close( Un ) + Un = -1 + return + end if + + ! heading + + ! Add some file information: + + WRITE (Un,'(/,A)') 'Linearized model: '//TRIM( y_FAST%FileDescLines(1) ) + WRITE (Un,'(1X,A)') TRIM( y_FAST%FileDescLines(2) ) + WRITE (Un,'()' ) !print a blank line + WRITE (Un,'(A)' ) TRIM( y_FAST%FileDescLines(3) ) + WRITE (Un,'()' ) !print a blank line + + WRITE(Un, '(A)') 'Simulation information:' + fmt = '(3x,A,1x,'//trim(p_FAST%OutFmt_t)//',1x,A)' + Desc = 'Simulation time:'; WRITE (Un, fmt) Desc, t_global, 's' + Desc = 'Rotor Speed:'; WRITE (Un, fmt) Desc, y_FAST%Lin%RotSpeed, 'rad/s' + Desc = 'Azimuth:'; WRITE (Un, fmt) Desc, y_FAST%Lin%Azimuth, 'rad' + Desc = 'Wind Speed:'; WRITE (Un, fmt) Desc, y_FAST%Lin%WindSpeed, 'm/s' + + fmt = '(3x,A,1x,I5)' + do i=1,size(n) + Desc = 'Number of '//trim(TypeNames(i))//':' + WRITE(Un, fmt) Desc, n(i) + end do + + Desc = 'Jacobians included in this file?' + fmt = '(3x,A,1x,A5)' + if (p_FAST%LinOutJac) then + write (Un, fmt) Desc, 'Yes' + else + write (Un, fmt) Desc, 'No' + end if + + WRITE (Un,'()' ) !print a blank line + + + !...................................................... + ! Write the names of the output parameters on one line: + !...................................................... + if (n(Indx_x) > 0) then + WRITE(Un, '(A)') 'Order of continuous states:' + call WrLinFile_txt_Table(p_FAST, Un, "Row/Column", LinData%op_x, LinData%names_x, rotFrame=LinData%RotFrame_x, derivOrder=LinData%DerivOrder_x ) + + WRITE(Un, '(A)') 'Order of continuous state derivatives:' + call WrLinFile_txt_Table(p_FAST, Un, "Row/Column", LinData%op_dx, LinData%names_x, rotFrame=LinData%RotFrame_x, deriv=.true., derivOrder=LinData%DerivOrder_x ) + end if + + if (n(Indx_xd) > 0) then + WRITE(Un, '(A)') 'Order of discrete states:' + call WrLinFile_txt_Table(p_FAST, Un, "Row/Column", LinData%op_xd, LinData%names_xd ) + end if + + if (n(Indx_z) > 0) then + WRITE(Un, '(A)') 'Order of constraint states:' + call WrLinFile_txt_Table(p_FAST, Un, "Row/Column", LinData%op_z, LinData%names_z, rotFrame=LinData%RotFrame_z ) + end if + + if (n(Indx_u) > 0) then + WRITE(Un, '(A)') 'Order of inputs:' + call WrLinFile_txt_Table(p_FAST, Un, "Column ", LinData%op_u, LinData%names_u, rotFrame=LinData%RotFrame_u, UseCol=LinData%use_u ) + end if + + if (n(Indx_y) > 0) then + WRITE(Un, '(A)') 'Order of outputs:' + call WrLinFile_txt_Table(p_FAST, Un, "Row ", LinData%op_y, LinData%names_y, rotFrame=LinData%RotFrame_y, UseCol=LinData%use_y ) + end if + + !............. + if (p_FAST%LinOutJac) then + WRITE (Un,'(/,A,/)' ) 'Jacobian matrices:' !print a blank line + ! we'll have the modules write their own Jacobians outside this routine + end if + + +END SUBROUTINE WrLinFile_txt_Head +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that writes the A,B,C,D matrices from linearization to a text file. +SUBROUTINE WrLinFile_txt_End(Un, p_FAST, LinData) + + INTEGER(IntKi), INTENT(INOUT) :: Un !< unit number + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameters + TYPE(FAST_LinType), INTENT(IN ) :: LinData !< Linearization data for individual module or glue (coupled system) + + ! local variables + + WRITE (Un,'(/,A,/)' ) 'Linearized state matrices:' !print a blank line + + ! A matrix + if (allocated(LinData%A)) call WrPartialMatrix( LinData%A, Un, p_FAST%OutFmt, 'A' ) + ! B matrix + if (allocated(LinData%B)) call WrPartialMatrix( LinData%B, Un, p_FAST%OutFmt, 'B', UseCol=LinData%use_u ) + + ! C matrix + if (allocated(LinData%C)) call WrPartialMatrix( LinData%C, Un, p_FAST%OutFmt, 'C', UseRow=LinData%use_y ) + ! D matrix + if (allocated(LinData%D)) call WrPartialMatrix( LinData%D, Un, p_FAST%OutFmt, 'D', UseRow=LinData%use_y, UseCol=LinData%use_u ) + + ! StateRotation matrix + if (allocated(LinData%StateRotation)) call WrPartialMatrix( LinData%StateRotation, Un, p_FAST%OutFmt, 'StateRotation' ) + + ! RelState matrices + if (allocated(LinData%StateRel_x)) call WrPartialMatrix( LinData%StateRel_x, Un, p_FAST%OutFmt, 'State_Rel_x' ) + if (allocated(LinData%StateRel_xdot)) call WrPartialMatrix( LinData%StateRel_xdot, Un, p_FAST%OutFmt, 'State_Rel_xdot' ) + + close(Un) + Un = -1 + +END SUBROUTINE WrLinFile_txt_End +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE WrLinFile_txt_Table(p_FAST, Un, RowCol, op, names, rotFrame, deriv, derivOrder, UseCol,start_indx) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameters + INTEGER(IntKi), INTENT(IN ) :: Un !< unit number + CHARACTER(*), INTENT(IN ) :: RowCol !< Row/Column description + REAL(ReKi), INTENT(IN ) :: op(:) !< operating point values (possibly different size that Desc because of orientations) + CHARACTER(LinChanLen), INTENT(IN ) :: names(:) !< Descriptions of the channels (names and units) + logical, optional, INTENT(IN ) :: rotFrame(:) !< determines if this parameter is in the rotating frame + logical, optional, intent(in ) :: deriv !< flag that tells us if we need to modify the channel names for derivatives (xdot) + integer(IntKi), optional, intent(in ) :: derivOrder(:) !< Order of the time derivatives associated with the channel + logical, optional, intent(in ) :: UseCol(:) !< flags that tell us if we should use each column or skip it + INTEGER(IntKi),optional, INTENT(IN ) :: start_indx !< starting index (so extended inputs can be numbered starting after the # of inputs) + + ! local variables + INTEGER(IntKi) :: TS ! tab stop column + INTEGER(IntKi) :: i, i_print ! loop counter + INTEGER(IntKi) :: i_op ! loop counter + + logical :: UseDerivNames !< flag that tells us if we need to modify the channel names for derivatives (xdot) + logical :: UseThisCol !< flag that tells us if we should use this particular column or skip it + logical :: RotatingCol !< flag that tells us if this column is in the rotating frame + integer(IntKi) :: DerivOrdCol !< integer indicating the maximum time-derivative order of a channel (this will be 0 for anything that is not a continuous state) + CHARACTER(*), PARAMETER :: RoutineName = 'WrLinFile_txt_Table' + CHARACTER(100) :: Fmt + CHARACTER(100) :: Fmt_Str + CHARACTER(100) :: FmtOrient + + + + if (present(deriv) ) then + UseDerivNames = deriv + else + UseDerivNames = .false. + end if + + + TS = 14 + 3*p_FAST%FmtWidth+7 ! tab stop after operating point + + Fmt = '(3x,I8,3x,'//trim(p_FAST%OutFmt)//',T'//trim(num2lstr(TS))//',L8,8x,I8,9x,A)' + FmtOrient = '(3x,I8,3x,'//trim(p_FAST%OutFmt)//',2(", ",'//trim(p_FAST%OutFmt)//'),T'//trim(num2lstr(TS))//',L8,8x,I8,9x,A)' + Fmt_Str = '(3x,A10,1x,A,T'//trim(num2lstr(TS))//',A15,1x,A16,1x,A)' + + WRITE(Un, Fmt_Str) RowCol, 'Operating Point', 'Rotating Frame?', 'Derivative Order', 'Description' + WRITE(Un, Fmt_Str) '----------','---------------', '---------------', '----------------', '-----------' + + i_op = 1 + if (present(start_indx)) then + i_print = start_indx + 1 + else + i_print = 1 + end if + + do i=1,size(names) + + UseThisCol = .true. + if (present(UseCol)) then + UseThisCol = useCol(i) + end if + + DerivOrdCol = 0 + if (present(derivOrder)) DerivOrdCol = derivOrder(i) + + RotatingCol = .false. + if (present(rotFrame)) RotatingCol = rotFrame(i) + + if (index(names(i), ' orientation angle, node ') > 0 ) then ! make sure this matches what is written in PackMotionMesh_Names() + if (UseThisCol) then + WRITE(Un, FmtOrient) i_print, op(i_op), op(i_op+1), op(i_op+2), RotatingCol, DerivOrdCol, trim(names(i)) !//' [OP is a row of the DCM] + i_print = i_print + 1 + end if + + i_op = i_op + 3 + else + if (UseThisCol) then + if (UseDerivNames) then + WRITE(Un, Fmt) i_print, op(i_op), RotatingCol, DerivOrdCol, 'First time derivative of '//trim(names(i))//'/s' + else + WRITE(Un, Fmt) i_print, op(i_op), RotatingCol, DerivOrdCol, trim(names(i)) + end if + i_print = i_print + 1 + end if + + i_op = i_op + 1 + end if + end do + + WRITE (Un,'()' ) !print a blank line + + + +END SUBROUTINE WrLinFile_txt_Table +!---------------------------------------------------------------------------------------------------------------------------------- + + +!> This routine returns the operating points for the entire glue code. +SUBROUTINE Glue_GetOP(p_FAST, y_FAST, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameters + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + INTEGER(IntKi) :: i, j, k ! loop/temp variables + INTEGER(IntKi) :: ThisModule ! Module ID # + INTEGER(IntKi) :: i_u ! loop/temp variables + INTEGER(IntKi) :: i_y, i_x ! loop/temp variables + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Glue_GetOP' + + + ErrStat = ErrID_None + ErrMsg = "" + + if (.not. allocated(y_FAST%Lin%Glue%op_u)) then ! assume none of them are allocated + + ! calculate the size of the input and output operating points + ! this size isn't very straightforward since it may contain orientations + i_u = 0 + i_y = 0 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_u)) then + i_u = i_u + size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_u) + end if + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_y)) then + i_y = i_y + size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_y) + end if + end do + end do + + call AllocAry( y_FAST%Lin%Glue%op_u, i_u, 'op_u', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%op_y, i_y, 'op_y', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%op_x, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'op_x', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry( y_FAST%Lin%Glue%op_dx, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'op_dx', ErrStat2, ErrMsg2) + call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >=AbortErrLev) return + end if + + + i_u = 1 + i_y = 1 + i_x = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_u)) then + do j=1,size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_u) + y_FAST%Lin%Glue%op_u(i_u) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_u(j) + i_u = i_u + 1; + end do + end if + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_y)) then + do j=1,size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_y) + y_FAST%Lin%Glue%op_y(i_y) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_y(j) + i_y = i_y + 1; + end do + end if + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x)) then + do j=1,size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x) + y_FAST%Lin%Glue%op_x(i_x) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x(j) + + y_FAST%Lin%Glue%op_dx(i_x) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_dx(j) + i_x = i_x + 1; + end do + end if + + end do + end do + +END SUBROUTINE Glue_GetOP +!---------------------------------------------------------------------------------------------------------------------------------- + +!> This routine forms the Jacobian for the glue-code input-output solves. +SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, MAPp, FEAM, MD, Orca, & + IceF, IceD, MeshMapData, dUdu, dUdy, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), ALLOCATABLE, INTENT(INOUT) :: dUdu(:,:) !< Partial derivatives of input-output equations (U(y,u)=0) with respect + !! to the inputs (u) + REAL(R8Ki), ALLOCATABLE, INTENT(INOUT) :: dUdy(:,:) !< Partial derivatives of input-output equations (U(y,u)=0) with respect + !! to the outputs (y) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! local variables + INTEGER(IntKi) :: ThisModule ! Module ID + INTEGER(IntKi) :: i, j, k ! loop counter + INTEGER(IntKi) :: r_start, r_end ! row start/end of glue matrix + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Glue_Jacobians' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Note: Where the same Linearize_*_to_*() routines for mesh mapping are used in both dUdu and dUdy, the dUdy routines assume dUdu + ! has already called the routine (and so avoids calling the routines a second time). This means the dUdu routines must be called first. + + !..................................... + ! dUdu + !> \f$ \frac{\partial U_\Lambda}{\partial u} = + !! \begin{bmatrix} \frac{\partial U_\Lambda^{IfW}}{\partial u^{IfW}} & \frac{\partial U_\Lambda^{IfW}}{\partial u^{SrvD}} & + !! \frac{\partial U_\Lambda^{IfW}}{\partial u^{ED}} & \frac{\partial U_\Lambda^{IfW}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{IfW}}{\partial u^{AD}} \\ + !! \frac{\partial U_\Lambda^{SrvD}}{\partial u^{IfW}} & \frac{\partial U_\Lambda^{SrvD}}{\partial u^{SrvD}} & + !! \frac{\partial U_\Lambda^{SrvD}}{\partial u^{ED}} & \frac{\partial U_\Lambda^{SrvD}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{SrvD}}{\partial u^{AD}} \\ + !! \frac{\partial U_\Lambda^{ED}}{\partial u^{IfW}} & \frac{\partial U_\Lambda^{ED}}{\partial u^{SrvD}} & + !! \frac{\partial U_\Lambda^{ED}}{\partial u^{ED}} & \frac{\partial U_\Lambda^{ED}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{ED}}{\partial u^{AD}} \\ + !! \frac{\partial U_\Lambda^{BD}}{\partial u^{IfW}} & \frac{\partial U_\Lambda^{BD}}{\partial u^{SrvD}} & + !! \frac{\partial U_\Lambda^{BD}}{\partial u^{ED}} & \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{BD}}{\partial u^{AD}} \\ + !! \frac{\partial U_\Lambda^{AD}}{\partial u^{IfW}} & \frac{\partial U_\Lambda^{AD}}{\partial u^{SrvD}} & + !! \frac{\partial U_\Lambda^{AD}}{\partial u^{ED}} & \frac{\partial U_\Lambda^{AD}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{AD}}{\partial u^{AD}} \\ + !! \end{bmatrix} = + !! \begin{bmatrix} I & 0 & 0 & 0 & \frac{\partial U_\Lambda^{IfW}}{\partial u^{AD}} \\ + !! 0 & I & 0 & 0 & 0 \\ + !! 0 & 0 & I & \frac{\partial U_\Lambda^{ED}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{ED}}{\partial u^{AD}} \\ + !! 0 & 0 & 0 & \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} & \frac{\partial U_\Lambda^{BD}}{\partial u^{AD}} \\ + !! 0 & 0 & 0 & 0 & \frac{\partial U_\Lambda^{AD}}{\partial u^{AD}} \\ + !! \end{bmatrix} \f$ + !..................................... +! LIN-TODO: Add doc strings for new modules: HD & MAP + + if (.not. allocated(dUdu)) then + call AllocAry(dUdu, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'dUdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + dUdu = 0.0_R8Ki ! most of this matrix is zero, so we'll just initialize everything and set only the non-zero parts below + + + !............ + ! \f$ \frac{\partial U_\Lambda^{IfW}}{\partial u^{IfW}} = I \f$ \n + ! \f$ \frac{\partial U_\Lambda^{SrvD}}{\partial u^{SrvD}} = I \f$ \n + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{ED}} = I \f$ \n + ! Note that we're also doing \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} = I \f$ and + ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial u^{AD}} = I \f$ here; We will add values to the off=diagonal terms of those block matrices later. + !............ + do j = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder(j) + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + r_start = y_FAST%Lin%Modules(ThisModule)%Instance(k)%LinStartIndx(LIN_INPUT_COL) + r_end = r_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin( LIN_INPUT_COL) - 1 + do i = r_start,r_end + dUdu(i,i) = 1.0_R8Ki + end do + end do + end do + + + !............ + ! \f$ \frac{\partial U_\Lambda^{IfW}}{\partial u^{AD}} \end{bmatrix} = \f$ (dUdu block row 1=IfW) + !............ + IF (p_FAST%CompInflow == MODULE_IfW .and. p_FAST%CompAero == MODULE_AD) THEN + call Linear_IfW_InputSolve_du_AD( p_FAST, y_FAST, AD%Input(1), dUdu ) + end if ! we're using the InflowWind module + + + !............ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{AD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{BD}} \end{bmatrix} = \f$ (dUdu block row 3=ED) + !............ + ! we need to do this for CompElast=ED and CompElast=BD + + call Linear_ED_InputSolve_du( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !............ + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{AD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} \end{bmatrix} = \f$ (dUdu block row 4=BD) + !............ + IF (p_FAST%CompElast == Module_BD) THEN + call Linear_BD_InputSolve_du( p_FAST, y_FAST, ED%y, AD%y, AD%Input(1), BD, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END IF + + !............ + ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial u^{AD}} \end{bmatrix} = \f$ (dUdu block row 5=AD) + !............ + IF (p_FAST%CompAero == MODULE_AD) THEN + call Linear_AD_InputSolve_du( p_FAST, y_FAST, AD%Input(1), ED%y, BD, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + IF (p_FAST%CompSub == Module_ExtPtfm) THEN + CALL WrScr('>>> FAST_LIN: Linear_ExtPtfm_InputSolve_du, TODO') + ENDIF + + !............ + ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial u^{HD}} \end{bmatrix} = \f$ (dUdu block row 6=HD) + !............ + IF (p_FAST%CompHydro == MODULE_HD) THEN + call Linear_HD_InputSolve_du( p_FAST, y_FAST, HD%Input(1), ED%y, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + ! LIN-TODO: Update the doc lines below to include HD and MAP + !..................................... + ! dUdy + !> \f$ \frac{\partial U_\Lambda}{\partial y} = + !! \begin{bmatrix} \frac{\partial U_\Lambda^{IfW} }{\partial y^{IfW}} & \frac{\partial U_\Lambda^{IfW} }{\partial y^{SrvD}} & + !! \frac{\partial U_\Lambda^{IfW} }{\partial y^{ED} } & \frac{\partial U_\Lambda^{IfW} }{\partial y^{BD} } & \frac{\partial U_\Lambda^{IfW} }{\partial y^{AD}} \\ + !! \frac{\partial U_\Lambda^{SrvD}}{\partial y^{IfW}} & \frac{\partial U_\Lambda^{SrvD}}{\partial y^{SrvD}} & + !! \frac{\partial U_\Lambda^{SrvD}}{\partial y^{ED} } & \frac{\partial U_\Lambda^{SrvD}}{\partial y^{BD} } & \frac{\partial U_\Lambda^{SrvD}}{\partial y^{AD}} \\ + !! \frac{\partial U_\Lambda^{ED} }{\partial y^{IfW}} & \frac{\partial U_\Lambda^{ED} }{\partial y^{SrvD}} & + !! \frac{\partial U_\Lambda^{ED} }{\partial y^{ED} } & \frac{\partial U_\Lambda^{ED} }{\partial y^{BD} } & \frac{\partial U_\Lambda^{ED} }{\partial y^{AD}} \\ + !! \frac{\partial U_\Lambda^{BD} }{\partial y^{IfW}} & \frac{\partial U_\Lambda^{BD} }{\partial y^{SrvD}} & + !! \frac{\partial U_\Lambda^{BD} }{\partial y^{ED} } & \frac{\partial U_\Lambda^{BD} }{\partial y^{BD} } & \frac{\partial U_\Lambda^{BD} }{\partial y^{AD}} \\ + !! \frac{\partial U_\Lambda^{AD} }{\partial y^{IfW}} & \frac{\partial U_\Lambda^{AD} }{\partial y^{SrvD}} & + !! \frac{\partial U_\Lambda^{AD} }{\partial y^{ED} } & \frac{\partial U_\Lambda^{AD} }{\partial y^{BD} } & \frac{\partial U_\Lambda^{AD} }{\partial y^{AD}} \\ + !! \end{bmatrix} = + !! \begin{bmatrix} 0 & 0 & 0 & 0 & 0 \\ + !! 0 & 0 & \frac{\partial U_\Lambda^{SrvD}}{\partial y^{ED}} & 0 & 0 \\ + !! 0 & \frac{\partial U_\Lambda^{ED}}{\partial y^{SrvD}} & \frac{\partial U_\Lambda^{ED}}{\partial y^{ED}} & \frac{\partial U_\Lambda^{ED}}{\partial y^{BD}} & \frac{\partial U_\Lambda^{ED}}{\partial y^{AD}} \\ + !! 0 & 0 & \frac{\partial U_\Lambda^{BD}}{\partial y^{ED}} & \frac{\partial U_\Lambda^{BD}}{\partial y^{BD}} & \frac{\partial U_\Lambda^{BD}}{\partial y^{AD}} \\ + !! \frac{\partial U_\Lambda^{AD}}{\partial y^{IfW}} & 0 & \frac{\partial U_\Lambda^{AD}}{\partial y^{ED}} & \frac{\partial U_\Lambda^{AD}}{\partial y^{BD}} & 0 \\ + !! \end{bmatrix} \f$ + !..................................... + if (.not. allocated(dUdy)) then + call AllocAry(dUdy, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), 'dUdy', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + + dUdy = 0.0_R8Ki ! most of this matrix is zero, so we'll just initialize everything and set only the non-zero parts below + + !............ + ! \f$ \frac{\partial U_\Lambda^{SrvD}}{\partial y^{ED}} \end{bmatrix} = \f$ (dUdy block row 2=SrvD) + !............ + if (p_FAST%CompServo == MODULE_SrvD) then ! need to do this regardless of CompElast + call Linear_SrvD_InputSolve_dy( p_FAST, y_FAST, dUdy ) + end if + + + !............ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{SrvD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{BD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{AD}} \end{bmatrix} = \f$ (dUdy block row 3=ED) + !............ + + call Linear_ED_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, MAPp, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !............ + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{BD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{AD}} \end{bmatrix} = \f$ (dUdy block row 4=BD) + !............ + if (p_FAST%CompElast == MODULE_BD) then + call Linear_BD_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + !............ + ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial y^{IfW}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial y^{BD}} \end{bmatrix} = \f$ (dUdy block row 5=AD) + !............ + if (p_FAST%CompAero == MODULE_AD) then ! need to do this regardless of CompElast + + if (p_FAST%CompInflow == MODULE_IfW) then + call Linear_AD_InputSolve_IfW_dy( p_FAST, y_FAST, AD%Input(1), dUdy ) + end if + + call Linear_AD_InputSolve_NoIfW_dy( p_FAST, y_FAST, AD%Input(1), ED%y, BD, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + end if + +! LIN-TODO: Implement HD-related solve + !............ + ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial y^{ED}} \end{bmatrix} = \f$ (dUdy block row 6=HD) + !............ + if (p_FAST%CompHydro == MODULE_HD) then + call Linear_HD_InputSolve_dy( p_FAST, y_FAST, HD%Input(1), ED%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + +! LIN-TODO: Implement Map-related solve + !............ + ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{ED}} \end{bmatrix} = \f$ (dUdy block row 7=MAP) + !............ + if (p_FAST%CompMooring == MODULE_MAP) then + call Linear_MAP_InputSolve_dy( p_FAST, y_FAST, MAPp%Input(1), ED%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + IF (p_FAST%CompSub == Module_ExtPtfm) THEN + CALL WrScr('>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO') + ENDIF + +END SUBROUTINE Glue_Jacobians +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{IfW}/du^{AD} block of dUdu. (i.e., how do changes in the AD inputs affect IfW inputs?) +SUBROUTINE Linear_IfW_InputSolve_du_AD( p_FAST, y_FAST, u_AD, dUdu ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output data (for linearization) + TYPE(AD_InputType), INTENT(IN) :: u_AD !< The input meshes (already calculated) from AeroDyn + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(IfW)/du^(AD) block + + + INTEGER(IntKi) :: i, j, k ! loop counters + INTEGER(IntKi) :: i2, j2 ! loop counters + INTEGER(IntKi) :: AD_Start_Bl ! starting index of dUdu (column) where AD blade motion inputs are located + INTEGER(IntKi) :: Node ! InflowWind node number + + + ! compare with IfW_InputSolve(): + + Node = 0 !InflowWind node + if (p_FAST%CompServo == MODULE_SrvD) Node = Node + 1 + + IF (p_FAST%CompAero == MODULE_AD) THEN + + ! blades: + AD_Start_Bl = y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) & + + u_AD%TowerMotion%NNodes * 9 & ! 3 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel) with 3 components + + u_AD%HubMotion%NNodes * 9 ! 3 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_RotationVel) with 3 components + + do k = 1,size(u_AD%BladeRootMotion) + AD_Start_Bl = AD_Start_Bl + u_AD%BladeRootMotion(k)%NNodes * 3 ! 1 field (MASKID_Orientation) with 3 components + end do + ! next is u_AD%BladeMotion(k): + + DO K = 1,SIZE(u_AD%BladeMotion) + DO J = 1,u_AD%BladeMotion(k)%Nnodes + Node = Node + 1 ! InflowWind node + do i=1,3 !XYZ components of this node + i2 = y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + (Node-1)*3 + i - 1 + j2 = AD_Start_Bl + (j-1)*3 + i - 1 + dUdu( i2, j2 ) = -1.0_R8Ki + end do + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + + ! get starting AD index of BladeMotion for next blade + AD_Start_Bl = AD_Start_Bl + u_AD%BladeMotion(k)%Nnodes * 9 ! 3 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel) with 3 components + END DO !K = 1,p%NumBl + + ! tower: + DO J=1,u_AD%TowerMotion%nnodes + Node = Node + 1 + do i=1,3 !XYZ components of this node + i2 = y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + (Node-1)*3 + i - 1 + j2 = y_FAST%Lin%Modules(MODULE_AD )%Instance(1)%LinStartIndx(LIN_INPUT_COL) + (j-1)*3 + i - 1 + dUdu( i2, j2 ) = -1.0_R8Ki + end do + END DO + + END IF + +END SUBROUTINE Linear_IfW_InputSolve_du_AD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{ED}/du^{BD} and dU^{ED}/du^{AD} blocks (ED row) of dUdu. (i.e., how do changes in the AD and BD inputs affect the ED inputs?) +SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) +!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) + TYPE(ED_InputType), INTENT(INOUT) :: u_ED !< ED Inputs at t + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linerization) + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: BD_Start ! starting index of dUdu (column) where BD root motion inputs are located + INTEGER(IntKi) :: AD_Start_Bl ! starting index of dUdu (column) where AD blade motion inputs are located + INTEGER(IntKi) :: ED_Start_mt ! starting index of dUdu (row) where ED blade/tower or hub moment inputs are located + INTEGER(IntKi) :: HD_Start + INTEGER(IntKi) :: MAP_Start + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_ED_InputSolve_du' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + !.......... + ! dU^{ED}/du^{AD} + !.......... + IF ( p_FAST%CompAero == Module_AD ) THEN + + ! ED inputs on blade from AeroDyn + IF (p_FAST%CompElast == Module_ED) THEN + + ED_Start_mt = y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + + DO K = 1,SIZE(u_ED%BladePtLoads,1) ! Loop through all blades (p_ED%NumBl) + ED_Start_mt = ED_Start_mt + u_ED%BladePtLoads(k)%NNodes*3 ! skip the forces on this blade + AD_Start_Bl = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) + + CALL Linearize_Line2_to_Point( y_AD%BladeLoad(k), u_ED%BladePtLoads(k), MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), y_ED%BladeLn2Mesh(k) ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! AD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%AD_L_2_BDED_B(k)%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%AD_L_2_BDED_B(k)%dM%m_us, ED_Start_mt, AD_Start_Bl ) + end if + + ! get starting index of next blade + ED_Start_mt = ED_Start_mt + u_ED%BladePtLoads(k)%NNodes* 3 ! skip the moments on this blade + + END DO + + END IF + + ! ED inputs on tower from AD: + + IF ( y_AD%TowerLoad%Committed ) THEN + ED_Start_mt = Indx_u_ED_Tower_Start(u_ED, y_FAST) & + + u_ED%TowerPtLoads%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) + + CALL Linearize_Line2_to_Point( y_AD%TowerLoad, u_ED%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2, u_AD%TowerMotion, y_ED%TowerLn2Mesh ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! AD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%AD_L_2_ED_P_T%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%AD_L_2_ED_P_T%dM%m_us, ED_Start_mt, y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) ) + end if + END IF + + END IF + + + !.......... + ! dU^{ED}/du^{BD} + !.......... + + IF ( p_FAST%CompElast == Module_BD ) THEN ! see routine U_ED_SD_HD_BD_Orca_Residual() in SolveOption1 + ED_Start_mt = Indx_u_ED_Hub_Start(u_ED, y_FAST) & + + u_ED%HubPtLoad%NNodes * 3 ! 3 forces at the hub (so we start at the moments) + + ! Transfer BD loads to ED hub input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + do k=1,p_FAST%nBeams + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) + + CALL Linearize_Point_to_Point( BD%y(k)%ReactionForce, u_ED%HubPtLoad, MeshMapData%BD_P_2_ED_P(k), ErrStat2, ErrMsg2, BD%Input(1,k)%RootMotion, y_ED%HubPtMotion) !u_BD%RootMotion and y_ED%HubPtMotion contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! BD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%BD_P_2_ED_P(k)%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%BD_P_2_ED_P(k)%dM%m_us, ED_Start_mt, BD_Start ) + end if + + end do ! k + + END IF + + !.......... + ! dU^{ED}/du^{HD} + !.......... + + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + + ! we're just going to assume u_ED%PlatformPtMesh is committed + + if ( HD%y%AllHdroOrigin%Committed ) then ! meshes for floating + ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & + + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) + + ! Transfer HD load outputs to ED PlatformPtMesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + HD_Start = Indx_u_HD_PlatformRef_Start(HD%Input(1), y_FAST) + + call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%HD_W_P_2_ED_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%HD_W_P_2_ED_P%dM%m_us, ED_Start_mt, HD_Start ) + end if + + end if + end if + + !.......... + ! dU^{ED}/du^{MAP} + !.......... + ! LIN-TODO: Implement + if ( p_FAST%CompMooring == Module_MAP ) then + + ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & + + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) + + ! Transfer MAP loads to ED PlatformPtmesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + + MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + + ! NOTE: Assumes at least one MAP Fairlead point + + CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%Mooring_P_2_ED_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%Mooring_P_2_ED_P%dM%m_us, ED_Start_mt, MAP_Start ) + end if + + end if + +END SUBROUTINE Linear_ED_InputSolve_du + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{BD}/du^{BD} and dU^{BD}/du^{AD} blocks (BD row) of dUdu. (i.e., how do changes in the AD and BD inputs +!! affect the BD inputs?) This should be called only when p_FAST%CompElast == Module_BD. +SUBROUTINE Linear_BD_InputSolve_du( p_FAST, y_FAST, y_ED, y_AD, u_AD, BD, MeshMapData, dUdu, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linerization) + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: k ! Loops through blades + INTEGER(IntKi) :: BD_Start ! starting index of dUdu (row) where BD inputs are located + INTEGER(IntKi) :: AD_Start ! starting index of dUdu (column) where AD inputs are located + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_BD_InputSolve_du' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + !.......... + ! dU^{BD}/du^{AD} + !.......... + IF ( p_FAST%CompAero == Module_AD ) THEN + + ! BD inputs on blade from AeroDyn + + + if (p_FAST%BD_OutputSibling) then + + DO K = 1,p_FAST%nBeams ! Loop through all blades + CALL Linearize_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), BD%y(k)%BldMotion ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + else + + DO K = 1,p_FAST%nBeams ! Loop through all blades + !linearization for dUdy will need some matrix multiplies because of the transfer (chain rule!), but we will perform individual linearization calculations here + !!! need to transfer the BD output blade motions to nodes on a sibling of the BD blade motion mesh: + CALL Linearize_Line2_to_Line2( BD%y(k)%BldMotion, MeshMapData%y_BD_BldMotion_4Loads(k), MeshMapData%BD_L_2_BD_L(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL Linearize_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), MeshMapData%y_BD_BldMotion_4Loads(k) ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + end if + + + DO K = 1,p_FAST%nBeams ! Loop through all blades + + ! AD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%AD_L_2_BDED_B(k)%dM%m_us )) then + AD_Start = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) ! index for the start of u_AD%BladeMotion(k)%translationDisp field + + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) & + + BD%Input(1,k)%RootMotion%NNodes *18 & ! displacement, rotation, & acceleration fields for each node + + BD%Input(1,k)%PointLoad%NNodes * 6 & ! force + moment fields for each node + + BD%Input(1,k)%DistrLoad%NNodes * 3 ! force field for each node (start with moment field) + + call SetBlockMatrix( dUdu, MeshMapData%AD_L_2_BDED_B(k)%dM%m_us, BD_Start, AD_Start ) + end if + + END DO + + END IF + + !.......... + ! dU^{BD}/du^{BD} + ! note that the 1s on the diagonal have already been set, so we will fill in the off diagonal terms. + !.......... + + !IF ( p_FAST%CompElast == Module_BD ) THEN ! see routine U_ED_SD_HD_BD_Orca_Residual() in SolveOption1 + + ! Transfer ED motions to BD motion input (BD inputs depend on previously calculated BD inputs from ED): + do k=1,p_FAST%nBeams + + call Linearize_Point_to_Point( y_ED%BladeRootMotion(k), BD%Input(1,k)%RootMotion, MeshMapData%ED_P_2_BD_P(k), ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! BD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_BD_P(k)%dM%tv_uD )) then + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) + BD%Input(1,k)%RootMotion%NNodes * 6 ! skip root translational displacement and orientation fields + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_BD_P(k)%dM%tv_uD, BD_Start, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) ) + end if + + ! translational acceleration: + if (allocated(MeshMapData%ED_P_2_BD_P(k)%dM%ta_uD )) then + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) + BD%Input(1,k)%RootMotion%NNodes * 12 ! skip root translational displacement, orientation, and velocity (translation and rotation) fields + + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_BD_P(k)%dM%ta_uD, BD_Start, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) ) + end if + + end do ! k + + !END IF + +END SUBROUTINE Linear_BD_InputSolve_du +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{AD}/du^{AD} block of dUdu. (i.e., how do changes in the AD inputs affect the AD inputs?) +SUBROUTINE Linear_AD_InputSolve_du( p_FAST, y_FAST, u_AD, y_ED, BD, MeshMapData, dUdu, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< The inputs to AeroDyn14 + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: AD_Start_td ! starting index of dUdu (column) where AD translation displacements are located + INTEGER(IntKi) :: AD_Start_tv ! starting index of dUdu (column) where AD translation velocities are located + INTEGER(IntKi) :: AD_Start_ta ! starting index of dUdu (column) where AD translation accelerations are located + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_AD_InputSolve_du' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine + + ! look at how the translational displacement gets transfered to the translational velocity: + !------------------------------------------------------------------------------------------------- + ! Set the inputs from ElastoDyn and/or BeamDyn: + !------------------------------------------------------------------------------------------------- + + ! tower + IF (u_AD%TowerMotion%Committed) THEN + + CALL Linearize_Line2_to_Line2( y_ED%TowerLn2Mesh, u_AD%TowerMotion, MeshMapData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%TowerMotion' ) + + + !AD is the destination here, so we need tv_ud + if (allocated( MeshMapData%ED_L_2_AD_L_T%dM%tv_ud)) then + AD_Start_td = y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + AD_Start_tv = AD_Start_td + u_AD%TowerMotion%NNodes * 6 ! 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + call SetBlockMatrix( dUdu, MeshMapData%ED_L_2_AD_L_T%dM%tv_ud, AD_Start_tv, AD_Start_td ) + end if + + + END IF + + + ! blades + IF (p_FAST%CompElast == Module_ED ) THEN + + DO k=1,size(u_AD%BladeMotion) + CALL Linearize_Line2_to_Line2( y_ED%BladeLn2Mesh(k), u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeMotion('//trim(num2lstr(k))//')' ) + END DO + + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + + DO k=1,size(u_AD%BladeMotion) + CALL Linearize_Line2_to_Line2( BD%y(k)%BldMotion, u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeMotion('//trim(num2lstr(k))//')' ) + END DO + + END IF + + + + DO k=1,size(u_AD%BladeMotion) + AD_Start_td = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) ! index for u_AD%BladeMotion(k)%translationDisp field + + !AD is the destination here, so we need tv_ud + if (allocated( MeshMapData%BDED_L_2_AD_L_B(k)%dM%tv_ud)) then + ! index for u_AD%BladeMotion(k+1)%translationVel field + AD_Start_tv = AD_Start_td + u_AD%BladeMotion(k)%NNodes * 6 ! 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + call SetBlockMatrix( dUdu, MeshMapData%BDED_L_2_AD_L_B(k)%dM%tv_ud, AD_Start_tv, AD_Start_td ) + end if + + if (allocated( MeshMapData%BDED_L_2_AD_L_B(k)%dM%tv_ud)) then + AD_Start_ta = AD_Start_td + u_AD%BladeMotion(k)%NNodes * 12 ! 4 fields (TranslationDisp, Orientation, TranslationVel, and RotationVel) with 3 components before translational velocity field + + call SetBlockMatrix( dUdu, MeshMapData%BDED_L_2_AD_L_B(k)%dM%ta_ud, AD_Start_ta, AD_Start_td ) + end if + + END DO + + + +END SUBROUTINE Linear_AD_InputSolve_du +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{SrvD}/dy^{ED} block of dUdy. (i.e., how do changes in the ED outputs affect the SrvD inputs?) +SUBROUTINE Linear_SrvD_InputSolve_dy( p_FAST, y_FAST, dUdy ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN) :: y_FAST !< Output variables for the glue code + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{SrvD}/dy^{ED} block + + integer(intKi) :: ED_Start_Yaw !< starting index of dUdy (column) where ED Yaw/YawRate/HSS_Spd outputs are located (just before WriteOutput) + integer(intKi) :: thisModule + + + INTEGER(IntKi) :: i ! loop counter + + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_SrvD_InputSolve_dy' + + thisModule = Module_ED + ED_Start_Yaw = Indx_y_Yaw_Start(y_FAST, ThisModule) ! start of ED where Yaw, YawRate, HSS_Spd occur (right before WriteOutputs) + + do i=1,size(SrvD_Indx_Y_BlPitchCom) + dUdy(y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + SrvD_Indx_Y_BlPitchCom(i) - 1, ED_Start_Yaw + i - 1) = -1.0_ReKi + end do + + !IF (u_SrvD%NTMD%Mesh%Committed) THEN + ! + ! CALL Linearize_Point_to_Point( y_ED%NacelleMotion, u_SrvD%NTMD%Mesh, MeshMapData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2 ) + ! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! + !END IF + ! + !IF (u_SrvD%TTMD%Mesh%Committed) THEN + ! + ! CALL Linearize_Line2_to_Point( y_ED%TowerLn2Mesh, u_SrvD%TTMD%Mesh, MeshMapData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2 ) + ! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! + !END IF + +END SUBROUTINE Linear_SrvD_InputSolve_dy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{ED}/dy^{SrvD}, dU^{ED}/dy^{ED}, dU^{ED}/dy^{BD}, dU^{ED}/dy^{AD}, dU^{ED}/dy^{HD}, and dU^{ED}/dy^{MAP} +!! blocks of dUdy. (i.e., how do changes in the SrvD, ED, BD, AD, HD, and MAP outputs effect the ED inputs?) +SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, MAPp, MeshMapData, dUdy, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(INOUT) :: u_ED !< ED Inputs at t + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linerization) + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + !LIN-TODO: Add comments + INTEGER(IntKi) :: i ! rows/columns + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: AD_Out_Start ! starting index of dUdy (column) where particular AD fields are located + INTEGER(IntKi) :: BD_Out_Start ! starting index of dUdy (column) where particular BD fields are located + INTEGER(IntKi) :: ED_Start ! starting index of dUdy (row) where ED input fields are located + INTEGER(IntKi) :: ED_Out_Start ! starting index of dUdy (column) where ED output fields are located + INTEGER(IntKi) :: HD_Out_Start + INTEGER(IntKi) :: MAP_Out_Start + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_ED_InputSolve_dy' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + ! ED inputs from ServoDyn outputs + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + ! BlPitchCom, YawMom, GenTrq + ED_Start = Indx_u_ED_BlPitchCom_Start(u_ED, y_FAST) + do i=1,size(u_ED%BlPitchCom)+2 ! BlPitchCom, YawMom, GenTrq (NOT collective pitch) + dUdy(ED_Start + i - 1, y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + i - 1) = -1.0_ReKi !SrvD_Indx_Y_BlPitchCom + end do + + !IF (y_SrvD%NTMD%Mesh%Committed) THEN + ! CALL Linearize_Point_to_Point( y_SrvD%NTMD%Mesh, u_ED%NacelleLoads, MeshMapData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2, u_SrvD%NTMD%Mesh, y_ED%NacelleMotion ) + ! CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ED%NacelleLoads' ) + !END IF + ! + !IF (y_SrvD%TTMD%Mesh%Committed) THEN + ! CALL Linearize_Point_to_Point( y_SrvD%TTMD%Mesh, u_ED%TowerPtLoads, MeshMapData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2, u_SrvD%TTMD%Mesh, y_ED%TowerLn2Mesh ) + ! CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ED%TowerPtLoads' ) + !END IF + + END IF + + ! parts of dU^{ED}/dy^{AD} and dU^{ED}/dy^{ED}: + + ! ElastoDyn inputs on blade from AeroDyn and ElastoDyn + IF ( p_FAST%CompAero == Module_AD ) THEN + + IF (p_FAST%CompElast == Module_ED) THEN + AD_Out_Start = y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + y_AD%TowerLoad%NNodes * 6 ! start of y_AD%BladeLoad(1)%Force field [2 fields (force, moment) with 3 components] + + DO K = 1,SIZE(u_ED%BladePtLoads,1) ! Loop through all blades (p_ED%NumBl) + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !CALL Linearize_Line2_to_Point( y_AD%BladeLoad(k), u_ED%BladePtLoads(k), MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), y_ED%BladeLn2Mesh(k) ) + + ! AD loads-to-ED loads transfer (dU^{ED}/dy^{AD}): + ED_Start = Indx_u_ED_Blade_Start(u_ED, y_FAST, k) ! start of u_ED%BladePtLoads(k)%Force field + call Assemble_dUdy_Loads(y_AD%BladeLoad(k), u_ED%BladePtLoads(k), MeshMapData%AD_L_2_BDED_B(k), ED_Start, AD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Blade_Start(u_ED, y_FAST, k) + u_ED%BladePtLoads(k)%NNodes*3 ! start of u_ED%BladePtLoads(k)%Moment field (skip the ED forces) + ED_Out_Start = Indx_y_ED_Blade_Start(y_ED, y_FAST, k) ! start of y_ED%BladeLn2Mesh(1)%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMapData%AD_L_2_BDED_B(k)%dM%m_uD, ED_Start, ED_Out_Start ) + + AD_Out_Start = AD_Out_Start + y_AD%BladeLoad(k)%NNodes*6 ! start of y_AD%BladeLoad(k+1)%Force field [skip 2 fields to forces on next blade] + END DO + END IF ! ED + + + IF ( y_AD%TowerLoad%Committed ) THEN + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !CALL Linearize_Line2_to_Point( y_AD%TowerLoad, u_ED%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2, u_AD%TowerMotion, y_ED%TowerLn2Mesh ) + + ! AD loads-to-ED loads transfer (dU^{ED}/dy^{AD}): + ED_Start = Indx_u_ED_Tower_Start(u_ED, y_FAST) ! u_ED%TowerPtLoads%Force field + AD_Out_Start = y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) ! start of y_AD%Tower%Force + call Assemble_dUdy_Loads(y_AD%TowerLoad, u_ED%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ED_Start, AD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = ED_Start + u_ED%TowerPtLoads%NNodes*3 ! start of u_ED%TowerPtLoads%Moment field [skip the ED forces to get to the moments] + ED_Out_Start = Indx_y_ED_Tower_Start(y_ED, y_FAST) ! start of y_ED%TowerLn2Mesh%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMapData%AD_L_2_ED_P_T%dM%m_uD, ED_Start, ED_Out_Start ) + + END IF ! tower + + END IF ! aero loads + + ! U_ED_SD_HD_BD_Orca_Residual() in InputSolve Option 1 + IF (p_FAST%CompElast == Module_BD) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!DO k=1,p_FAST%nBeams + !!! CALL Linearize_Point_to_Point( BD%y(k)%ReactionForce, u_ED%HubPtLoad, MeshMapData%BD_P_2_ED_P(k), ErrStat2, ErrMsg2, BD%Input(1,k)%RootMotion, y_ED%HubPtMotion) + !!!END DO + + ! BD Reaction force-to-ED force transfer (dU^{ED}/dy^{BD}) from BD root-to-ED hub load transfer: + ED_Start = Indx_u_ED_Hub_Start(u_ED, y_FAST) ! start of u_ED%HubPtLoad%Force field + DO k=1,p_FAST%nBeams + BD_Out_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_OUTPUT_COL) ! BD%y(k)%ReactionForce%Force field + call Assemble_dUdy_Loads(BD%y(k)%ReactionForce, u_ED%HubPtLoad, MeshMapData%BD_P_2_ED_P(k), ED_Start, BD_Out_Start, dUdy) + END DO + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}) from BD root-to-ED hub load transfer: + ED_Start = Indx_u_ED_Hub_Start(u_ED, y_FAST) + u_ED%HubPtLoad%NNodes*3 ! start of u_ED%HubPtLoad%Moment field (skip forces) + DO k=1,p_FAST%nBeams + ED_Out_Start = Indx_y_ED_BladeRoot_Start(y_ED, y_FAST, k) ! start of y_ED%BladeRootMotion(k)%TranslationDisp field + call SumBlockMatrix( dUdy, MeshMapData%BD_P_2_ED_P(k)%dM%m_ud, ED_Start, ED_Out_Start) + END DO + + END IF + + ! HD + ! parts of dU^{ED}/dy^{HD} and dU^{ED}/dy^{ED}: + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + + ! we're just going to assume u_ED%PlatformPtMesh is committed + + if ( HD%y%AllHdroOrigin%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + HD_Out_Start = Indx_y_HD_AllHdro_Start(HD%y, y_FAST) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%Moment field + call Assemble_dUdy_Loads(HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMapData%HD_W_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) +! maybe this should be SumBlockMatrix with future changes to linearized modules??? + end if + + + end if + + ! MAP + ! parts of dU^{ED}/dy^{MAP} and dU^{ED}/dy^{ED}: + if ( p_FAST%CompMooring == Module_MAP ) then + if ( MAPp%y%ptFairleadLoad%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations + MAP_Out_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Loads(MAPp%y%ptFairLeadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ED_Start, MAP_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call SumBlockMatrix( dUdy, MeshMapData%Mooring_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) + end if + + end if + +END SUBROUTINE Linear_ED_InputSolve_dy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{BD}/dy^{ED}, dU^{BD}/dy^{BD}, and dU^{BD}/dy^{AD} blocks of dUdy. (i.e., how do +!! changes in the ED, BD, and AD outputs effect the BD inputs?) +SUBROUTINE Linear_BD_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, MeshMapData, dUdy, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(INOUT) :: u_ED !< ED Inputs at t + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linearization) + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BD data at t + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: AD_Out_Start ! starting index of dUdy (column) where particular AD fields are located + INTEGER(IntKi) :: BD_Start ! starting index of dUdy (column) where particular BD fields are located + INTEGER(IntKi) :: BD_Out_Start ! starting index of dUdy (column) where BD output fields are located + INTEGER(IntKi) :: ED_Out_Start ! starting index of dUdy (column) where particular AD fields are located + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + REAL(R8Ki), ALLOCATABLE :: TempMat(:,:) ! temporary matrix for getting linearization matrices when BD input and output meshes are not siblings + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_BD_InputSolve_dy' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + ! parts of dU^{BD}/dy^{AD} and dU^{BD}/dy^{BD}: + + ! BeamDyn inputs on blade from AeroDyn and BeamDyn + IF ( p_FAST%CompAero == Module_AD ) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_BD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!if (p_FAST%BD_OutputSibling) then + !!! CALL Linearize_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), BD%y(k)%BldMotion ) + !!!else + !!! CALL Linearize_Line2_to_Line2( BD%y(k)%BldMotion, MeshMapData%y_BD_BldMotion_4Loads(k), MeshMapData%BD_L_2_BD_L(k), ErrStat2, ErrMsg2 ) + !!! CALL Linearize_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), MeshMapData%y_BD_BldMotion_4Loads(k) ) + !!!end if + + AD_Out_Start = y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + y_AD%TowerLoad%NNodes * 6 ! start of y_AD%BladeLoad(1)%Force field [2 fields (force, moment) with 3 components] + DO K = 1,p_FAST%nBeams ! Loop through all blades + + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) & ! start of BD%Input(1,k)%DistrLoad%Force field + + BD%Input(1,k)%RootMotion%NNodes *18 & ! displacement, rotation, & acceleration fields for each node + + BD%Input(1,k)%PointLoad%NNodes * 6 ! force + moment fields for each node + + ! AD loads-to-BD loads transfer (dU^{BD}/dy^{AD}): + call Assemble_dUdy_Loads(y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), BD_Start, AD_Out_Start, dUdy) + AD_Out_Start = AD_Out_Start + y_AD%BladeLoad(k)%NNodes*6 ! start of y_AD%BladeLoad(k+1)%Force field [skip the moments to get to forces on next blade] + + + ! BD translation displacement-to-BD moment transfer (dU^{BD}/dy^{BD}): + BD_Start = BD_Start + BD%Input(1,k)%DistrLoad%NNodes * 3 ! start of BD%Input(1,k)%DistrLoad%Moment field (start with moment field) + BD_Out_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_OUTPUT_COL) & ! start of BD%y(k)%BldMotion%TranslationDisp field + + BD%y(k)%ReactionForce%NNodes * 6 ! 2 fields with 3 components + + if (p_FAST%BD_OutputSibling) then + call SetBlockMatrix( dUdy, MeshMapData%AD_L_2_BDED_B(k)%dM%m_uD, BD_Start, BD_Out_Start ) + else + call AllocAry(TempMat, size(MeshMapData%AD_L_2_BDED_B(k)%dM%m_uD,1), size(MeshMapData%BD_L_2_BD_L(k)%dM%mi,2), 'TempMat', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat>=AbortErrLev) return + + ! these blocks should be small enough that we can use matmul instead of calling a LAPACK routine to do it. + TempMat = matmul(MeshMapData%AD_L_2_BDED_B(k)%dM%m_uD,MeshMapData%BD_L_2_BD_L(k)%dM%mi) + call SetBlockMatrix( dUdy, TempMat, BD_Start, BD_Out_Start ) + + BD_Out_Start = BD_Out_Start + BD%y(k)%BldMotion%NNodes*3 ! start of BD%y(k)%BldMotion%Orientation field + TempMat = matmul(MeshMapData%AD_L_2_BDED_B(k)%dM%m_uD,MeshMapData%BD_L_2_BD_L(k)%dM%fx_p) + call SetBlockMatrix( dUdy, TempMat, BD_Start, BD_Out_Start ) + + deallocate(TempMat) ! the next blade may have a different number of nodes + end if + + END DO + + END IF ! aero loads + + ! U_ED_SD_HD_BD_Orca_Residual() in InputSolve Option 1; call to Transfer_ED_to_BD_tmp() + !IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + + ! Transfer ED motions to BD inputs (dU^{BD}/dy^{ED}): + do k = 1,size(y_ED%BladeRootMotion) + !!! ! This linearization was done in forming dUdu (see Linear_BD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!CALL Linearize_Point_to_Point( y_ED%BladeRootMotion(k), BD%Input(1,k)%RootMotion, MeshMapData%ED_P_2_BD_P(k), ErrStat2, ErrMsg2 ) + + BD_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_INPUT_COL) ! ! start of BD%Input(1,k)%RootMotion%TranslationDisp field + ED_Out_Start = Indx_y_ED_BladeRoot_Start(y_ED, y_FAST, k) ! start of y_ED%BladeRootMotion(k)%TranslationDisp field + + call Assemble_dUdy_Motions(y_ED%BladeRootMotion(k), BD%Input(1,k)%RootMotion, MeshMapData%ED_P_2_BD_P(k), BD_Start, ED_Out_Start, dUdy) + end do + +END SUBROUTINE Linear_BD_InputSolve_dy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{AD}/dy^{IfW} block of dUdy. (i.e., how do changes in the IfW outputs affect the AD inputs?) +SUBROUTINE Linear_AD_InputSolve_IfW_dy( p_FAST, y_FAST, u_AD, dUdy ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< The inputs to AeroDyn + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{AD}/dy^{IfW} block + + ! Local variables: + + INTEGER(IntKi) :: I ! Loops through components + INTEGER(IntKi) :: J ! Loops through nodes / elements + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: node + INTEGER(IntKi) :: AD_Start ! starting index of dUdy (row) where AD input equations (for specific fields) are located + + + !------------------------------------------------------------------------------------------------- + ! Set the inputs from inflow wind: + !------------------------------------------------------------------------------------------------- + !IF (p_FAST%CompInflow == MODULE_IfW) THEN !already checked in calling routine + + if (p_FAST%CompServo == MODULE_SrvD) then + node = 2 + else + node = 1 + end if + + + AD_Start = Indx_u_AD_BladeInflow_Start(u_AD, y_FAST) ! start of u_AD%InflowOnBlade array + + do k=1,size(u_AD%InflowOnBlade,3) ! blades + do j=1,size(u_AD%InflowOnBlade,2) ! nodes + do i=1,3 !velocity component + dUdy( AD_Start + i - 1, y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + (node-1)*3 + i - 1 ) = -1.0_R8Ki + end do + node = node + 1 + AD_Start = AD_Start + 3 + end do + end do + + if ( allocated(u_AD%InflowOnTower) ) then + do j=1,size(u_AD%InflowOnTower,2) !nodes + do i=1,3 !velocity component + dUdy( AD_Start + i - 1, y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + (node-1)*3 + i - 1 ) = -1.0_R8Ki + end do + node = node + 1 + AD_Start = AD_Start + 3 + end do + end if + + !END IF + + +END SUBROUTINE Linear_AD_InputSolve_IfW_dy +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{AD}/dy^{ED} and dU^{AD}/dy^{BD} blocks of dUdy. (i.e., how do changes in the ED and BD outputs affect +!! the AD inputs?) +SUBROUTINE Linear_AD_InputSolve_NoIfW_dy( p_FAST, y_FAST, u_AD, y_ED, BD, MeshMapData, dUdy, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< The inputs to AeroDyn14 + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BD data at t + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{AD}/dy^{ED} block + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: AD_Start ! starting index of dUdy (column) where particular AD fields are located + INTEGER(IntKi) :: ED_Out_Start! starting index of dUdy (row) where particular ED fields are located + INTEGER(IntKi) :: BD_Out_Start! starting index of dUdy (row) where particular BD fields are located + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_AD_InputSolve_NoIfW_dy' + + + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! Set the inputs from ElastoDyn and/or BeamDyn: + !------------------------------------------------------------------------------------------------- + !................................... + ! tower + !................................... + IF (u_AD%TowerMotion%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_AD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!CALL Linearize_Line2_to_Line2( y_ED%TowerLn2Mesh, u_AD%TowerMotion, MeshMapData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) + + AD_Start = Indx_u_AD_Tower_Start(u_AD, y_FAST) ! start of u_AD%TowerMotion%TranslationDisp field + + ED_Out_Start = Indx_y_ED_Tower_Start(y_ED, y_FAST) ! start of y_ED%TowerLn2Mesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%TowerLn2Mesh, u_AD%TowerMotion, MeshMapData%ED_L_2_AD_L_T, AD_Start, ED_Out_Start, dUdy, skipRotVel=.true.) + + END IF + + !................................... + ! hub + !................................... + CALL Linearize_Point_to_Point( y_ED%HubPtMotion, u_AD%HubMotion, MeshMapData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%HubMotion' ) + if (errStat>=AbortErrLev) return + + ! *** AD translational displacement: from ED translational displacement (MeshMapData%ED_P_2_AD_P_H%dM%mi) and orientation (MeshMapData%ED_P_2_AD_P_H%dM%fx_p) + AD_Start = Indx_u_AD_Hub_Start(u_AD, y_FAST) ! start of u_AD%HubMotion%TranslationDisp field + ED_Out_Start = Indx_y_ED_Hub_Start(y_ED, y_FAST) ! start of y_ED%HubPtMotion%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMapData%ED_P_2_AD_P_H%dM%mi, AD_Start, ED_Out_Start ) + + ED_Out_Start = Indx_y_ED_Hub_Start(y_ED, y_FAST) + y_ED%HubPtMotion%NNodes * 3 ! start of y_ED%HubPtMotion%Orientation field + call SetBlockMatrix( dUdy, MeshMapData%ED_P_2_AD_P_H%dM%fx_p, AD_Start, ED_Out_Start ) + + ! *** AD orientation: from ED orientation + AD_Start = AD_Start + u_AD%HubMotion%NNodes * 3 ! move past the AD translation disp field to orientation field + call SetBlockMatrix( dUdy, MeshMapData%ED_P_2_AD_P_H%dM%mi, AD_Start, ED_Out_Start ) + + ! *** AD rotational velocity: from ED rotational velocity + AD_Start = AD_Start + u_AD%HubMotion%NNodes * 3 ! move past the AD orientation field to rotational velocity field + ED_Out_Start = Indx_y_ED_Hub_Start(y_ED, y_FAST) + y_ED%HubPtMotion%NNodes * 6 ! ! start of y_ED%HubPtMotion%RotationVel field + call SetBlockMatrix( dUdy, MeshMapData%ED_P_2_AD_P_H%dM%mi, AD_Start, ED_Out_Start ) + + + + !................................... + ! blade root + !................................... + DO k=1,size(y_ED%BladeRootMotion) + CALL Linearize_Point_to_Point( y_ED%BladeRootMotion(k), u_AD%BladeRootMotion(k), MeshMapData%ED_P_2_AD_P_R(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeRootMotion('//trim(num2lstr(k))//')' ) + if (errStat>=AbortErrLev) return + + ! *** AD orientation: from ED orientation + AD_Start = Indx_u_AD_BladeRoot_Start(u_AD, y_FAST, k) ! start of u_AD%BladeRootMotion(k)%Orientation field + + ED_Out_Start = Indx_y_ED_BladeRoot_Start(y_ED, y_FAST, k) & ! start of y_ED%BladeRootMotion(k)%TranslationDisp field + + y_ED%BladeRootMotion(k)%NNodes * 3 ! start of y_ED%BladeRootMotion(k)%Orientation field + call SetBlockMatrix( dUdy, MeshMapData%ED_P_2_AD_P_R(k)%dM%mi, AD_Start, ED_Out_Start ) + + END DO + + + !................................... + ! blades + !................................... + IF (p_FAST%CompElast == Module_ED ) THEN + + + DO k=1,size(y_ED%BladeLn2Mesh) + !!! ! This linearization was done in forming dUdu (see Linear_AD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!CALL Linearize_Line2_to_Line2( y_ED%BladeLn2Mesh(k), u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + + AD_Start = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) ! start of u_AD%BladeMotion(k)%TranslationDisp field + ED_Out_Start = Indx_y_ED_Blade_Start(y_ED, y_FAST, k) ! start of y_ED%BladeLn2Mesh(k)%TranslationDisp field + CALL Assemble_dUdy_Motions(y_ED%BladeLn2Mesh(k), u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), AD_Start, ED_Out_Start, dUdy, skipRotAcc=.true.) + + END DO + + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + !!! ! This linearization was done in forming dUdu (see Linear_AD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!CALL Linearize_Line2_to_Line2( BD%y(k)%BldMotion, u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + + DO k=1,p_FAST%nBeams + AD_Start = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) ! start of u_AD%BladeMotion(k)%TranslationDisp field + BD_Out_Start = y_FAST%Lin%Modules(Module_BD)%Instance(k)%LinStartIndx(LIN_OUTPUT_COL) + + CALL Assemble_dUdy_Motions(BD%y(k)%BldMotion, u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), AD_Start, BD_Out_Start, dUdy, skipRotAcc=.true.) + END DO + + END IF + + +END SUBROUTINE Linear_AD_InputSolve_NoIfW_dy +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{HD}/du^{HD} blocks of dUdu. +SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUdu, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< The inputs to HydroDyn + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^{HD}/du^{HD} block + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: HD_Start_td ! starting index of dUdu (column) where particular HD fields are located + INTEGER(IntKi) :: HD_Start_tr ! starting index of dUdu (row) where particular HD fields are located + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_HD_InputSolve_du' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine + ! We need to make six calls to SetBlockMatrix for the different output to input mappings + ! 1) Row 3, Col 1 + ! 2) Row 5, Col 1 + ! 3) Row 9, Col 7 + ! 4) Row 11, Col 7 + ! 5) Row 15, Col 13 + ! 6) Row 17, Col 13 + + ! look at how the translational displacement gets transfered to the translational velocity and translational acceleration: + !------------------------------------------------------------------------------------------------- + ! Set the inputs from ElastoDyn: + !------------------------------------------------------------------------------------------------- + + !.......... + ! dU^{HD}/du^{HD} + ! note that the 1s on the diagonal have already been set, so we will fill in the off diagonal terms. + !.......... + + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + + !=================================================== + ! y_ED%PlatformPtMesh and u_HD%Morison%DistribMesh + !=================================================== + + ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): + + call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + + HD_Start_td = y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + HD_Start_tr = HD_Start_td + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_HD_M_L%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_L%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%ED_P_2_HD_M_L%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_L%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + + !=================================================== + ! y_ED%PlatformPtMesh and u_HD%Morison%LumpedMesh + !=================================================== + + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + HD_Start_td = HD_Start_tr + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 1 field ( TranslationAcc and RotationAcc) + HD_Start_tr = HD_Start_td + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + + if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + + !=================================================== + ! y_ED%PlatformPtMesh and u_HD%Mesh + !=================================================== + + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + HD_Start_td = HD_Start_tr + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 field ( TranslationalAcc and RotationAcc) + HD_Start_tr = HD_Start_td + u_HD%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + + if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + + end if + + +END SUBROUTINE Linear_HD_InputSolve_du +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{HD}/dy^{ED} block of dUdy. (i.e., how do changes in the ED outputs affect +!! the HD inputs?) +SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< The inputs to HydroDyn + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{HD}/dy^{ED} block + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: HD_Start ! starting index of dUdy (column) where particular HD fields are located + INTEGER(IntKi) :: ED_Out_Start! starting index of dUdy (row) where particular ED fields are located + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_HD_InputSolve_dy' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................... + ! Distributed Morison Mesh + !................................... + IF (u_HD%Morison%DistribMesh%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + + HD_Start = Indx_u_HD_Distrib_Start(u_HD, y_FAST) ! start of u_HD%Morison%DistribMesh%TranslationDisp field + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, HD_Start, ED_Out_Start, dUdy) + END IF + + !................................... + ! Lumped Morison Mesh + !................................... + IF (u_HD%Morison%LumpedMesh%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + + HD_Start = Indx_u_HD_Lumped_Start(u_HD, y_FAST) ! start of u_HD%Morison%LumpedMesh%TranslationDisp field + + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy) + END IF + + !................................... + ! Lumped Platform Reference Pt Mesh + !................................... + IF (u_HD%Mesh%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + + HD_Start = Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field + + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy) + + + END IF + + +END SUBROUTINE Linear_HD_InputSolve_dy + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{MAP}/dy^{ED} block of dUdy. (i.e., how do changes in the ED outputs affect +!! the MAP inputs?) +SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< The inputs to MAP + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{MAP}/dy^{ED} block + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: MAP_Start ! starting index of dUdy (column) where particular MAP fields are located + INTEGER(IntKi) :: ED_Out_Start! starting index of dUdy (row) where particular ED fields are located + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_MAP_InputSolve_dy' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................... + ! FairLead Mesh + !................................... + IF (u_MAP%PtFairDisplacement%Committed) THEN + MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, MAP_Start, ED_Out_Start, dUdy, OnlyTranslationDisp=.true.) + + + END IF + +END SUBROUTINE Linear_MAP_InputSolve_dy + +! LIN-TODO: Clean up if not used. +!!---------------------------------------------------------------------------------------------------------------------------------- +!!> This routine forms the dU^{MAP}/dy^{ED} blocks of dUdu. +!SUBROUTINE Linear_MAP_InputSolve_du( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) +! +! ! Passed variables +! TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data +! TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) +! TYPE(HD_InputType), INTENT(INOUT) :: u_MAP !< The inputs to HydroDyn + +! TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module +! TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules +! REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{MAP}/dy^{ED} block +! +! INTEGER(IntKi) :: ErrStat !< Error status of the operation +! CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None +! +! ! Local variables: +! +! INTEGER(IntKi) :: MAP_Start ! starting index of dUdy (column) where particular MAP fields are located +! INTEGER(IntKi) :: ED_Start ! starting index of dUdy (row) where particular ED fields are located +! INTEGER(IntKi) :: ErrStat2 +! CHARACTER(ErrMsgLen) :: ErrMsg2 +! CHARACTER(*), PARAMETER :: RoutineName = 'Linear_MAP_InputSolve_dy' +! +! +! ErrStat = ErrID_None +! ErrMsg = "" +! +! ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine +! ! We need to make six calls to SetBlockMatrix for the different output to input mappings +! ! 1) Row 3, Col 1 +! ! 2) Row 4, Col 1 +! +! +! ! look at how the translational displacement gets transfered to the translational velocity and translational acceleration: +! !------------------------------------------------------------------------------------------------- +! ! Set the inputs from ElastoDyn: +! !------------------------------------------------------------------------------------------------- +! +! !.......... +! ! dU^{MAP}/dy^{ED} +! ! note that the 1s on the diagonal have already been set, so we will fill in the off diagonal terms. +! !.......... +! +! if ( p_FAST%CompMooring == Module_MAP ) then ! MAP- ElastoDyn +! +! !=================================================== +! ! y_ED%PlatformPtMesh and u_MAP%Morison%DistribMesh +! !=================================================== +! +! ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): +! +! call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_MAP%Morison%DistribMesh, MeshMapData%ED_P_2_MAP_M_L, ErrStat2, ErrMsg2 ) +! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) +! +! ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} +! +! HD_Start_td = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) +! HD_Start_tr = HD_Start_td + u_MAP%Morison%DistribMesh%%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field +! +! ! translational velocity: +! if (allocated(MeshMapData%ED_P_2_MAP_M_L%dM%tv_uD )) then +! call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_MAP_M_L%dM%tv_ud, HD_Start_tr, HD_Start_td ) +! end if +! +! ! translational acceleration: +! HD_Start_tr = HD_Start_tr + u_MAP%Morison%DistribMesh%%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) +! if (allocated(MeshMapData%ED_P_2_MAP_M_L%dM%ta_uD )) then +! call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_MAP_M_L%dM%ta_ud, HD_Start_tr, HD_Start_td ) +! end if +! +! end if +! +! +!END SUBROUTINE Linear_MAP_InputSolve_du + +!---------------------------------------------------------------------------------------------------------------------------------- + +!> This routine allocates the state matrices for the glue code and concatenates the module-level state matrices into +!! the first step of computing the full system state matrices. This routine returns +!! \f$ A = A^{ED} \f$, \f$ B = \begin{bmatrix} 0 & 0 & B^{ED} & 0 \end{bmatrix} \f$, +!! \f$ C = \begin{bmatrix} 0 \\ 0 \\ C^{ED} \\ 0 \end{bmatrix} \f$, and +!! \f$ D = \begin{bmatrix} D^{IfW} & 0 & 0 & 0 \\ 0 & D^{SrvD} & 0 & 0 \\ 0 & 0 & D^{ED} & 0 \\ 0 & 0 & 0 & D^{AD}\end{bmatrix}\f$. +SUBROUTINE Glue_FormDiag( p_FAST, y_FAST, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the 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) :: ThisModule ! Module ID # + + INTEGER(IntKi) :: i ! module loop counter + INTEGER(IntKi) :: k ! module instance loop counter + INTEGER(IntKi) :: r ! row loop counter + INTEGER(IntKi) :: c ! column loop counter + INTEGER(IntKi) :: r_start ! row in glue matrix where module block matrix starts + INTEGER(IntKi) :: c_start ! column in glue matrix where module block matrix starts + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Glue_FormDiag' + + ErrStat = ErrID_None + ErrMsg = "" + + + + !..................................... + ! Allocate the state matrices if necessary: + !..................................... + + if (.not. allocated(y_FAST%Lin%Glue%A)) then ! assume none of them are allocated + ! A: rows = x; columns = x + call AllocAry(y_FAST%Lin%Glue%A, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), & + y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'A', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !B: rows = x; columns = u + call AllocAry(y_FAST%Lin%Glue%B, y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), & + y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'B', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !C: rows = y; columns = x + call AllocAry(y_FAST%Lin%Glue%C, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), & + y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'C', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !D: rows = y; columns = u + call AllocAry(y_FAST%Lin%Glue%D, y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL), & + y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'D', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat>=AbortErrLev) return + end if + + + ! The equations of the matrices returned from this routine are really just a general form with the null matrices removed: + + ! A + y_FAST%Lin%Glue%A = 0.0_R8Ki + r_start = 1 + c_start = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated( y_FAST%Lin%Modules(ThisModule)%Instance(k)%A) ) then + do c=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%A, 2) + do r=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%A, 1) + y_FAST%Lin%Glue%A(r_start + r - 1, c_start + c - 1) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%A(r,c) + end do + end do + end if + + r_start = r_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + c_start = c_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + end do + end do + + + ! B + y_FAST%Lin%Glue%B = 0.0_R8Ki + r_start = 1 + c_start = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated( y_FAST%Lin%Modules(ThisModule)%Instance(k)%B) ) then + do c=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%B, 2) + do r=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%B, 1) + y_FAST%Lin%Glue%B(r_start + r - 1, c_start + c - 1) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%B(r,c) + end do + end do + end if + + r_start = r_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + c_start = c_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_INPUT_COL) + end do + end do + + ! C + y_FAST%Lin%Glue%C = 0.0_R8Ki + r_start = 1 + c_start = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated( y_FAST%Lin%Modules(ThisModule)%Instance(k)%C) ) then + do c=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%C, 2) + do r=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%C, 1) + y_FAST%Lin%Glue%C(r_start + r - 1, c_start + c - 1) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%C(r,c) + end do + end do + end if + + r_start = r_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) + c_start = c_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_ContSTATE_COL) + end do + end do + + ! D + y_FAST%Lin%Glue%D = 0.0_R8Ki + r_start = 1 + c_start = 1 + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + if (allocated( y_FAST%Lin%Modules(ThisModule)%Instance(k)%D) ) then + do c=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%D, 2) + do r=1,size( y_FAST%Lin%Modules(ThisModule)%Instance(k)%D, 1) + y_FAST%Lin%Glue%D(r_start + r - 1, c_start + c - 1) = y_FAST%Lin%Modules(ThisModule)%Instance(k)%D(r,c) + end do + end do + end if + + r_start = r_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_OUTPUT_COL) + c_start = c_start + y_FAST%Lin%Modules(ThisModule)%Instance(k)%SizeLin(LIN_INPUT_COL) + end do + end do + + +END SUBROUTINE Glue_FormDiag +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the full-system state matrices for linearization: A, B, C, and D. +!! Note that it uses LAPACK_GEMM instead of MATMUL for matrix multiplications because of stack-space issues (these +!! matrices get large quickly). +SUBROUTINE Glue_StateMatrices( p_FAST, y_FAST, dUdu, dUdy, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< glue-code Jacobian: \f$ \frac{\partial U}{\partial u} \f$; on exit will hold G^{-1}*dUdu + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< glue-code Jacobian: \f$ \frac{\partial U}{\partial y} \f$; on exit will hold G^{-1}*dUdy + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! local variables + REAL(R8Ki), ALLOCATABLE :: G(:,:), tmp(:,:) ! variables for glue-code linearization + INTEGER(IntKi), ALLOCATABLE :: ipiv(:) + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'Glue_StateMatrices' + + ErrStat = ErrID_None + ErrMsg = "" + + + + !..................................... + ! allocate the glue-code state matrices; after this call they will contain the state matrices from the + ! modules (without glue-code influence) on their diagonals + !..................................... + call Glue_FormDiag( p_FAST, y_FAST, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + !if (p_FAST%LinInputs == LIN_NONE .or. p_FAST%LinOutputs == LIN_NONE) then + ! the glue-code input-output solve doesn't affect the rest of the equations, so we'll just return early + ! call cleanup() + ! return + !end if + + + !..................................... + ! solve for state matrices: + !..................................... + + ! *** get G matrix **** + !---------------------- + if (.not. allocated(G)) then + call AllocAry(G, size(dUdu,1), size(dUdu,2), 'G', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call AllocAry( ipiv, size(dUdu,1), 'ipiv', ErrStat2, ErrMsg2 ) ! size(G,1) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + end if + + !G = dUdu + matmul( dUdy, y_FAST%Lin%Glue%D ) + G = dUdu + call LAPACK_GEMM( 'N', 'N', 1.0_R8Ki, dUdy, y_FAST%Lin%Glue%D, 1.0_R8Ki, G, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! because G can be ill-conditioned, we are going to precondition with G_hat = S^(-1) * G * S + ! we will also multiply the right-hand-side of the equations that need G inverse so that + ! dUdy_hat = S^(-1)*dUdy and dUdu_hat = S^(-1)*dUdu + call Precondition(p_FAST, y_FAST, G, dUdu, dUdy) + + + ! now we need to form G_hat^(-1) * (S^-1*dUdy) and G^(-1) * (S^-1*dUdu) + ! factor G for the two solves: + CALL LAPACK_getrf( M=size(G,1), N=size(G,2), A=G, IPIV=ipiv, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) then + call cleanup() + return + end if + + ! after the this solve, dUdy holds G_hat^(-1) * dUdy_hat: + CALL LAPACK_getrs( trans='N', N=size(G,2), A=G, IPIV=ipiv, B=dUdy, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! after the this solve, dUdu holds G_hat^(-1) * dUdu_hat: + CALL LAPACK_getrs( trans='N', N=size(G,2), A=G, IPIV=ipiv, B=dUdu, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + deallocate(G) ! we're finished with the solves, so let's get rid of them + deallocate(ipiv) ! we're finished with the solves, so let's get rid of them + + ! after this call, dUdu holds G^(-1)*dUdu and dUdy holds G^(-1)*dUdy: + call Postcondition(p_FAST, y_FAST, dUdu, dUdy) + + + ! *** get tmp matrix for A and C calculations **** + !---------------------- + call AllocAry(tmp, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), y_FAST%Lin%Glue%SizeLin(LIN_ContSTATE_COL), 'G^-1*dUdy*C', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (errStat>=AbortErrLev) then + call cleanup() + return + end if + + !tmp = G^(-1) * dUdy * diag(C) + call LAPACK_GEMM( 'N', 'N', 1.0_R8Ki, dUdy, y_FAST%Lin%Glue%C, 0.0_R8Ki, tmp, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! A + !---------------------- + !> \f{equation}{ A = + !! \begin{bmatrix} A^{ED} & 0 & 0 \\ 0 & A^{BD} & 0 \\ 0 & 0 & A^{HD}\end{bmatrix} - + !! \begin{bmatrix} 0 & 0 & B^{ED} & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & B^{BD} & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & B^{HD}\end{bmatrix} \, + !! \begin{bmatrix} G \end{bmatrix}^{-1} \, \frac{\partial U}{\partial y} \, \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & 0 \\ C^{ED} & 0 & 0 \\ 0 & C^{BD} & 0 \\ 0 & 0 & 0 \\ 0 & 0 & C^{HD} \\ 0 & 0 & 0\end{bmatrix} + !! \f} + !y_FAST%Lin%Glue%A = y_FAST%Lin%Glue%A - matmul( y_FAST%Lin%Glue%B, tmp ) + call LAPACK_GEMM( 'N', 'N', -1.0_R8Ki, y_FAST%Lin%Glue%B, tmp, 1.0_R8Ki, y_FAST%Lin%Glue%A, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! C + !---------------------- + !> \f{equation}{ C = \begin{bmatrix} 0 & 0 \\ 0 & 0 \\ C^{ED} & 0 \\ 0 & C^{BD} \\ 0 & 0 \end{bmatrix} - + !! \begin{bmatrix} D^{IfW} & 0 & 0 & 0 & 0 \\ 0 & D^{SrvD} & 0 & 0 & 0 \\ 0 & 0 & D^{ED} & 0 & 0 \\ 0 & 0 & 0 & D^{BD} & 0\\ 0 & 0 & 0 & 0 & D^{AD}\end{bmatrix} \, + !! \begin{bmatrix} G \end{bmatrix}^{-1} \, \frac{\partial U}{\partial y} \, \begin{bmatrix} 0 & 0 \\ 0 & 0 \\ C^{ED} & 0 \\ 0 & C^{BD} \\ 0 & 0 \end{bmatrix} + !! \f} + !y_FAST%Lin%Glue%C = y_FAST%Lin%Glue%C - matmul( y_FAST%Lin%Glue%D, tmp ) + call LAPACK_GEMM( 'N', 'N', -1.0_R8Ki, y_FAST%Lin%Glue%D, tmp, 1.0_R8Ki, y_FAST%Lin%Glue%C, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + deallocate(tmp) + + + ! B + !---------------------- + !> \f{equation}{ B = \begin{bmatrix} 0 & 0 \\ 0 & 0 \\ B^{ED} & 0 \\ 0 & B^{BD} \\ 0 & 0 \end{bmatrix} \, + !! \begin{bmatrix} G \end{bmatrix}^{-1} \, \frac{\partial U}{\partial u} + !! \f} + call AllocAry(tmp,size(y_FAST%Lin%Glue%B,1),size(y_FAST%Lin%Glue%B,2),'tmp',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (errStat>=AbortErrLev) then + call cleanup() + return + end if + tmp = y_FAST%Lin%Glue%B + + !y_FAST%Lin%Glue%B = matmul( y_FAST%Lin%Glue%B, dUdu ) + call LAPACK_GEMM( 'N', 'N', 1.0_R8Ki, tmp, dUdu, 0.0_R8Ki, y_FAST%Lin%Glue%B, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + deallocate(tmp) + + ! D + !---------------------- + !> \f{equation}{ D = \begin{bmatrix} D^{IfW} & 0 & 0 & 0 & 0 \\ 0 & D^{SrvD} & 0 & 0 & 0 \\ 0 & 0 & D^{ED} & 0 & 0 \\ 0 & 0 & 0 & D^{BD} & 0\\ 0 & 0 & 0 & 0 & D^{AD}\end{bmatrix} \, + !! \begin{bmatrix} G \end{bmatrix}^{-1} \, \frac{\partial U}{\partial u} + !! \f} + call AllocAry(tmp,size(y_FAST%Lin%Glue%D,1),size(y_FAST%Lin%Glue%D,2),'tmp',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (errStat>=AbortErrLev) then + call cleanup() + return + end if + tmp = y_FAST%Lin%Glue%D + + !y_FAST%Lin%Glue%D = matmul( y_FAST%Lin%Glue%D, dUdu ) + call LAPACK_GEMM( 'N', 'N', 1.0_R8Ki, tmp, dUdu, 0.0_R8Ki, y_FAST%Lin%Glue%D, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + deallocate(tmp) + + call cleanup() + +contains + subroutine cleanup() + if (allocated(ipiv)) deallocate(ipiv) + if (allocated(G)) deallocate(G) + if (allocated(tmp)) deallocate(tmp) + end subroutine cleanup +END SUBROUTINE Glue_StateMatrices +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the preconditioned matrix, \f$ \hat{G} \f$, such that \f$ \hat{G} = S^(-1) G S \f$ with \f$S^(-1)\f$ defined +!! such that loads are scaled by p_FAST\%UJacSclFact. It also returns the preconditioned matrices \f$ \hat{dUdu} \f$ and +!! \f$ \hat{dUdy} \f$ such that \f$ \hat{dUdu} = S^(-1) dUdu \f$ and +!! \f$ \hat{dUdy} = S^(-1) dUdy \f$ for the right-hand sides of the equations to be solved. +SUBROUTINE Precondition(p_FAST, y_FAST, G, dUdu, dUdy) + + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + REAL(R8Ki), INTENT(INOUT) :: G(:,:) !< variable for glue-code linearization (in is G; out is G_hat) + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< jacobian in FAST linearization from right-hand-side of equation + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< jacobian in FAST linearization from right-hand-side of equation + + integer :: r, c + + !! Change G to G_hat: + do c = 1,size(y_FAST%Lin%Glue%IsLoad_u) + + if ( y_FAST%Lin%Glue%IsLoad_u(c) ) then + + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + if ( .not. y_FAST%Lin%Glue%IsLoad_u(r) ) then + ! column is load, but row is a motion: + G(r,c) = G(r,c) * p_FAST%UJacSclFact + end if + end do + + else + + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + if ( y_FAST%Lin%Glue%IsLoad_u(r) ) then + ! column is motion, but row is a load: + G(r,c) = G(r,c) / p_FAST%UJacSclFact + end if + end do + + end if + + end do + + + !! Change dUdu to dUdu_hat (note that multiplying on the left multiplies the entire row): + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + + if ( y_FAST%Lin%Glue%IsLoad_u(r) ) then + dUdu(r,:) = dUdu(r,:) / p_FAST%UJacSclFact + end if + + end do + + !! Change dUdy to dUdy_hat: + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + + if ( y_FAST%Lin%Glue%IsLoad_u(r) ) then + dUdy(r,:) = dUdy(r,:) / p_FAST%UJacSclFact + end if + + end do + + +END SUBROUTINE Precondition +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the matrices \f$ \tilde{dUdu} \f$ and \f$ \tilde{dUdy} \f$ such that +!! \f$ \tilde{dUdu} = G^(-1) dUdu \f$ and +!! \f$ \tilde{dUdy} = G^(-1) dUdy \f$, which have been solved using the preconditioned system defined in fast_lin::precondition. +SUBROUTINE Postcondition(p_FAST, y_FAST, dUdu, dUdy) + + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< jacobian in FAST linearization from right-hand-side of equation + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< jacobian in FAST linearization from right-hand-side of equation + + integer :: r + + !! Change S^(-1) * G_hat^(-1) * dUdu_hat to G^(-1) * dUdu (note that multiplying on the left multiplies the entire row): + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + + if ( y_FAST%Lin%Glue%IsLoad_u(r) ) then + dUdu(r,:) = dUdu(r,:) * p_FAST%UJacSclFact + end if + + end do + + !! Change S^(-1) * G_hat^(-1) * dUdy_hat to G^(-1) * dUdy (note that multiplying on the left multiplies the entire row): + do r = 1,size(y_FAST%Lin%Glue%IsLoad_u) + + if ( y_FAST%Lin%Glue%IsLoad_u(r) ) then + dUdy(r,:) = dUdy(r,:) * p_FAST%UJacSclFact + end if + + end do + + +END SUBROUTINE Postcondition +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetBlockMatrix( matrix, submatrix, RowStart, ColStart ) + REAL(R8Ki), INTENT(INOUT) :: matrix(:,:) !< matrix that will have the negative of the submatrix block added to it + REAL(R8Ki), INTENT(IN ) :: submatrix(:,:) !< block matrix that needs to be added to matrix + INTEGER(IntKi), INTENT(IN ) :: RowStart !< first row in matrix where submatrix should start + INTEGER(IntKi), INTENT(IN ) :: ColStart !< first column in matrix where submatrix should start + + INTEGER(IntKi) :: col + INTEGER(IntKi) :: row + + + do col=1,size( submatrix, 2) + do row=1,size( submatrix, 1) + matrix(RowStart + row - 1, ColStart + col - 1) = - submatrix(row,col) ! note the negative sign here!!!! + end do + end do + + +END SUBROUTINE SetBlockMatrix +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SumBlockMatrix( matrix, submatrix, RowStart, ColStart ) + REAL(R8Ki), INTENT(INOUT) :: matrix(:,:) !< matrix that will have the negative of the submatrix block added to it + REAL(R8Ki), INTENT(IN ) :: submatrix(:,:) !< block matrix that needs to be added to matrix + INTEGER(IntKi), INTENT(IN ) :: RowStart !< first row in matrix where submatrix should start + INTEGER(IntKi), INTENT(IN ) :: ColStart !< first column in matrix where submatrix should start + + INTEGER(IntKi) :: col + INTEGER(IntKi) :: row + + + do col=1,size( submatrix, 2) + do row=1,size( submatrix, 1) + matrix(RowStart + row - 1, ColStart + col - 1) = matrix(RowStart + row - 1, ColStart + col - 1) & + - submatrix(row,col) ! note the negative sign here!!!! + end do + end do + + +END SUBROUTINE SumBlockMatrix +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine assembles the linearization matrices for transfer of motion fields between two meshes. +!> It set the following block matrix, which is the dUdy block for transfering output (source) mesh \f$y\f$ to the +!! input (destination) mesh \f$u\f$:\n +!! \f$ M = - \begin{bmatrix} M_{mi} & M_{f_{\times p}} & 0 & 0 & 0 & 0 \\ +!! 0 & M_{mi} & 0 & 0 & 0 & 0 \\ +!! M_{tv\_uS} & 0 & M_{mi} & M_{f_{\times p}} & 0 & 0 \\ +!! 0 & 0 & 0 & M_{mi} & 0 & 0 \\ +!! M_{ta\_uS} & 0 & 0 & M_{ta\_rv} & M_{mi} & M_{f_{\times p}} \\ +!! 0 & 0 & 0 & 0 & 0 & M_{mi} \\ +!! \end{bmatrix} \f$ +!! where the matrices correspond to +!! \f$ \left\{ \begin{matrix} +!! \vec{u}^S \\ +!! \vec{\theta}^S \\ +!! \vec{v}^S \\ +!! \vec{\omega}^S \\ +!! \vec{a}^S \\ +!! \vec{\alpha}^S \\ +!! \end{matrix} \right\} \f$ +SUBROUTINE Assemble_dUdy_Motions(y, u, MeshMap, BlockRowStart, BlockColStart, dUdy, skipRotVel, skipRotAcc, onlyTranslationDisp) + TYPE(MeshType), INTENT(IN) :: y !< the output (source) mesh that is transfering motions + TYPE(MeshType), INTENT(IN) :: u !< the input (destination) mesh that is receiving motions + TYPE(MeshMapType), INTENT(IN) :: MeshMap !< the mesh mapping from y to u + INTEGER(IntKi), INTENT(IN) :: BlockRowStart !< the index of the row defining the block of dUdy to be set + INTEGER(IntKi), INTENT(IN) :: BlockColStart !< the index of the column defining the block of dUdy to be set + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< full Jacobian matrix + LOGICAL, OPTIONAL, INTENT(IN) :: skipRotVel !< if present and true, we skip the rotational velocity and both acceleration fields and return early + LOGICAL, OPTIONAL, INTENT(IN) :: onlyTranslationDisp !< if present and true, we set only the destination translationDisp fields and return early + LOGICAL, OPTIONAL, INTENT(IN) :: skipRotAcc !< if present and true, we skip the rotational acceleration field + + INTEGER(IntKi) :: row + INTEGER(IntKi) :: col + +!! \f$M_{mi}\f$ is modmesh_mapping::meshmaplinearizationtype::mi (motion identity)\n +!! \f$M_{f_{\times p}}\f$ is modmesh_mapping::meshmaplinearizationtype::fx_p \n +!! \f$M_{tv\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uD \n +!! \f$M_{tv\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::tv_uS \n +!! \f$M_{ta\_uD}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uD \n +!! \f$M_{ta\_uS}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_uS \n +!! \f$M_{ta\_rv}\f$ is modmesh_mapping::meshmaplinearizationtype::ta_rv \n + + !*** row for translational displacement *** + ! source translational displacement to destination translational displacement: + row = BlockRowStart ! start of u%TranslationDisp field + col = BlockColStart ! start of y%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + ! source orientation to destination translational displacement: + row = BlockRowStart ! start of u%TranslationDisp field + col = BlockColStart + y%NNodes*3 ! start of y%Orientation field [skip 1 field with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%fx_p, row, col ) + + + if (PRESENT(onlyTranslationDisp)) then + if (onlyTranslationDisp) return ! destination includes only the translational displacement field, so we'll just return + end if + + + !*** row for orientation *** + ! source orientation to destination orientation: + row = BlockRowStart + u%NNodes*3 ! start of u%Orientation field [skip 1 field with 3 components] + col = BlockColStart + y%NNodes*3 ! start of y%Orientation field [skip 1 field with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + + !*** row for translational velocity *** + ! source translational displacement to destination translational velocity: + row = BlockRowStart + u%NNodes*6 ! start of u%TranslationVel field [skip 2 fields with 3 components] + col = BlockColStart ! start of y%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMap%dM%tv_us, row, col ) + + ! source translational velocity to destination translational velocity: + row = BlockRowStart + u%NNodes*6 ! start of u%TranslationVel field [skip 2 fields with 3 components] + col = BlockColStart + y%NNodes*6 ! start of y%TranslationVel field [skip 2 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + ! source rotational velocity to destination translational velocity: + row = BlockRowStart + u%NNodes*6 ! start of u%TranslationVel field [skip 2 fields with 3 components] + col = BlockColStart + y%NNodes*9 ! start of y%RotationVel field [skip 3 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%fx_p, row, col ) + + + if (PRESENT(skipRotVel)) then + if (skipRotVel) return ! destination does not include rotational velocities or accelerations, so we'll just return + end if + + + !*** row for rotational velocity *** + ! source rotational velocity to destination rotational velocity: + row = BlockRowStart + u%NNodes*9 ! start of u%RotationVel field [skip 3 fields with 3 components] + col = BlockColStart + y%NNodes*9 ! start of y%RotationVel field [skip 3 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + + !*** row for translational acceleration *** + ! source translational displacement to destination translational acceleration: + row = BlockRowStart + u%NNodes*12 ! start of u%TranslationAcc field [skip 4 fields with 3 components] + col = BlockColStart ! start of y%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMap%dM%ta_us, row, col ) + + ! source rotational velocity to destination translational acceleration: + row = BlockRowStart + u%NNodes*12 ! start of u%TranslationAcc field [skip 4 fields with 3 components] + col = BlockColStart + y%NNodes*9 ! start of y%RotationVel field [skip 3 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%ta_rv, row, col ) + + ! source translational acceleration to destination translational acceleration: + row = BlockRowStart + u%NNodes*12 ! start of u%TranslationAcc field [skip 4 fields with 3 components] + col = BlockColStart + y%NNodes*12 ! start of y%TranslationAcc field [skip 4 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + ! source rotational acceleration to destination translational acceleration: + row = BlockRowStart + u%NNodes*12 ! start of u%TranslationAcc field [skip 4 fields with 3 components] + col = BlockColStart + y%NNodes*15 ! start of y%RotationAcc field [skip 5 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%fx_p, row, col ) + + + if (PRESENT(skipRotAcc)) then + if (skipRotAcc) return ! destination does not include rotational accelerations, so we'll just return + end if + + + !*** row for rotational acceleration *** + ! source rotational acceleration to destination rotational acceleration + row = BlockRowStart + u%NNodes*15 ! start of u%RotationAcc field [skip 5 fields with 3 components] + col = BlockColStart + y%NNodes*15 ! start of y%RotationAcc field [skip 5 fields with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%mi, row, col ) + + +END SUBROUTINE Assemble_dUdy_Motions +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine assembles the linearization matrices for transfer of load fields between two meshes. +!> It set the following block matrix, which is the dUdy block for transfering output (source) mesh \f$y\f$ to the +!! input (destination) mesh \f$u\f$:\n +!! \f$ M = - \begin{bmatrix} M_{li} & 0 \\ +!! M_{fm} & M_{li} \\ +!! \end{bmatrix} \f$ +!! & M_{mi} & } +!! \f$ \left\{ \begin{matrix} +!! \vec{F}^S \\ +!! \vec{M}^S +!! \end{matrix} \right\} \f$ +SUBROUTINE Assemble_dUdy_Loads(y, u, MeshMap, BlockRowStart, BlockColStart, dUdy) + TYPE(MeshType), INTENT(IN) :: y !< the output (source) mesh that is transfering loads + TYPE(MeshType), INTENT(IN) :: u !< the input (destination) mesh that is receiving loads + TYPE(MeshMapType), INTENT(IN) :: MeshMap !< the mesh mapping from y to u + INTEGER(IntKi), INTENT(IN) :: BlockRowStart !< the index of the row defining the block of dUdy to be set + INTEGER(IntKi), INTENT(IN) :: BlockColStart !< the index of the column defining the block of dUdy to be set + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< full Jacobian matrix + + INTEGER(IntKi) :: row + INTEGER(IntKi) :: col + + !*** row for force *** + ! source force to destination force: + row = BlockRowStart ! start of u%Force field + col = BlockColStart ! start of y%Force field + call SetBlockMatrix( dUdy, MeshMap%dM%li, row, col ) + + !*** row for moment *** + ! source force to destination moment: + row = BlockRowStart + u%NNodes*3 ! start of u%Moment field [skip 1 field with 3 components] + col = BlockColStart ! start of y%Force field + call SetBlockMatrix( dUdy, MeshMap%dM%m_f, row, col ) + + if (allocated(y%Moment)) then + ! source moment to destination moment: + row = BlockRowStart + u%NNodes*3 ! start of u%Moment field [skip 1 field with 3 components] + col = BlockColStart + y%NNodes*3 ! start of y%Moment field [skip 1 field with 3 components] + call SetBlockMatrix( dUdy, MeshMap%dM%li, row, col ) + end if + +END SUBROUTINE Assemble_dUdy_Loads + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%BladePtLoads(BladeNum) mesh in the FAST linearization inputs. +FUNCTION Indx_u_ED_Blade_Start(u_ED, y_FAST, BladeNum) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + INTEGER, INTENT(IN ) :: BladeNum !< blade number to find index for + INTEGER :: k !< blade number loop + + INTEGER :: ED_Start !< starting index of this blade mesh in ElastoDyn inputs + + ED_Start = y_FAST%Lin%Modules(Module_ED)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + if (allocated(u_ED%BladePtLoads)) then + do k = 1,min(BladeNum-1, size(u_ED%BladePtLoads)) + ED_Start = ED_Start + u_ED%BladePtLoads(k)%NNodes * 6 ! 3 forces + 3 moments at each node on each blade + end do + end if + +END FUNCTION Indx_u_ED_Blade_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%PlatformPtMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_ED_Platform_Start(u_ED, y_FAST) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + INTEGER :: ED_Start !< starting index of this mesh + + ED_Start = Indx_u_ED_Blade_Start(u_ED, y_FAST, MaxNBlades+1) ! skip all of the blades to get to start of platform +END FUNCTION Indx_u_ED_Platform_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%TowerPtLoads mesh in the FAST linearization inputs. +FUNCTION Indx_u_ED_Tower_Start(u_ED, y_FAST) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + + INTEGER :: ED_Start !< starting index of this mesh + + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + ED_Start = ED_Start + u_ED%PlatformPtMesh%NNodes * 6 ! 3 forces + 3 moments at each node +END FUNCTION Indx_u_ED_Tower_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%HubPtLoad mesh in the FAST linearization inputs. +FUNCTION Indx_u_ED_Hub_Start(u_ED, y_FAST) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + + INTEGER :: ED_Start !< starting index of this mesh + + ED_Start = Indx_u_ED_Tower_Start(u_ED, y_FAST) + ED_Start = ED_Start + u_ED%TowerPtLoads%NNodes * 6 ! 3 forces + 3 moments at each node +END FUNCTION Indx_u_ED_Hub_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%NacelleLoads mesh in the FAST linearization inputs. +FUNCTION Indx_u_ED_Nacelle_Start(u_ED, y_FAST) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + + INTEGER :: ED_Start !< starting index of this mesh + + ED_Start = Indx_u_ED_Hub_Start(u_ED, y_FAST) + ED_Start = ED_Start + u_ED%HubPtLoad%NNodes * 6 ! 3 forces + 3 moments at each node +END FUNCTION Indx_u_ED_Nacelle_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_ED%BladePitchCom array in the FAST linearization inputs. +FUNCTION Indx_u_ED_BlPitchCom_Start(u_ED, y_FAST) RESULT(ED_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_InputType), INTENT(IN ) :: u_ED !< ED Inputs at t + + INTEGER :: ED_Start !< starting index of this mesh + + ED_Start = Indx_u_ED_Nacelle_Start(u_ED, y_FAST) + ED_Start = ED_Start + u_ED%NacelleLoads%NNodes * 6 ! 3 forces + 3 moments at each node +END FUNCTION Indx_u_ED_BlPitchCom_Start +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_ED%BladeLn2Mesh(BladeNum) mesh in the FAST linearization outputs. +FUNCTION Indx_y_ED_Blade_Start(y_ED, y_FAST, BladeNum) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ED outputs at t + INTEGER, INTENT(IN ) :: BladeNum !< blade number to find index for + INTEGER :: k !< blade number loop + + INTEGER :: ED_Out_Start !< starting index of this blade mesh in ElastoDyn outputs + + ED_Out_Start = y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) ! start of y_ED%BladeLn2Mesh(1)%TranslationDisp field (blade motions in y_ED) + if (allocated(y_ED%BladeLn2Mesh)) then + do k = 1,min(BladeNum-1,SIZE(y_ED%BladeLn2Mesh,1)) ! Loop through all blades (p_ED%NumBl) + ED_Out_Start = ED_Out_Start + y_ED%BladeLn2Mesh(k)%NNodes*18 ! 6 fields with 3 components on each blade + end do + end if + +END FUNCTION Indx_y_ED_Blade_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_ED%PlatformPtMesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_ED_Platform_Start(y_ED, y_FAST) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ED outputs at t + + INTEGER :: ED_Out_Start !< starting index of this mesh in ElastoDyn outputs + + ED_Out_Start = Indx_y_ED_Blade_Start(y_ED, y_FAST, MaxNBlades+1) ! skip all of the blades to get to start of platform +END FUNCTION Indx_y_ED_Platform_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_ED%TowerLn2Mesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_ED_Tower_Start(y_ED, y_FAST) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ED outputs at t + + INTEGER :: ED_Out_Start !< starting index of this mesh in ElastoDyn outputs + + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) + ED_Out_Start = ED_Out_Start + y_ED%PlatformPtMesh%NNodes*18 ! 6 fields with 3 components +END FUNCTION Indx_y_ED_Tower_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_ED%HubPtMesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_ED_Hub_Start(y_ED, y_FAST) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ED outputs at t + + INTEGER :: ED_Out_Start !< starting index of this mesh in ElastoDyn outputs + + ED_Out_Start = Indx_y_ED_Tower_Start(y_ED, y_FAST) + ED_Out_Start = ED_Out_Start + y_ED%TowerLn2Mesh%NNodes*18 ! 6 fields with 3 components +END FUNCTION Indx_y_ED_Hub_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_ED%BladeRootMotion(BladeNum) mesh in the FAST linearization outputs. +FUNCTION Indx_y_ED_BladeRoot_Start(y_ED, y_FAST, BladeNum) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ED outputs at t + INTEGER, INTENT(IN ) :: BladeNum !< blade number to find index for + INTEGER :: k !< blade number loop + + INTEGER :: ED_Out_Start !< starting index of this blade mesh in ElastoDyn outputs + + ED_Out_Start = Indx_y_ED_Hub_Start(y_ED, y_FAST) + ED_Out_Start = ED_Out_Start + y_ED%HubPtMotion%NNodes*9 ! 3 fields with 3 components + + do k = 1,min(BladeNum-1,size(y_ED%BladeRootMotion)) + ED_Out_Start = ED_Out_Start + y_ED%BladeRootMotion(k)%NNodes*18 + end do +END FUNCTION Indx_y_ED_BladeRoot_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for y_ED%Yaw in the FAST linearization outputs. +FUNCTION Indx_y_Yaw_Start(y_FAST, ThisModule) RESULT(ED_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + INTEGER, INTENT(IN ) :: ThisModule !< which structural module this is for + + INTEGER :: ED_Out_Start !< starting index of this blade mesh in ElastoDyn outputs + + + ED_Out_Start = y_FAST%Lin%Modules(thisModule)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + y_FAST%Lin%Modules(thisModule)%Instance(1)%SizeLin(LIN_OUTPUT_COL) & !end of ED outputs (+1) + - y_FAST%Lin%Modules(thisModule)%Instance(1)%NumOutputs - 3 ! start of ED where Yaw, YawRate, HSS_Spd occur (right before WriteOutputs) + +END FUNCTION Indx_y_Yaw_Start +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_AD%TowerMotion mesh in the FAST linearization inputs. +FUNCTION Indx_u_AD_Tower_Start(u_AD, y_FAST) RESULT(AD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD Inputs at t + + INTEGER :: AD_Start !< starting index of this mesh in AeroDyn inputs + + AD_Start = y_FAST%Lin%Modules(Module_AD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + +END FUNCTION Indx_u_AD_Tower_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_AD%HubMotion mesh in the FAST linearization inputs. +FUNCTION Indx_u_AD_Hub_Start(u_AD, y_FAST) RESULT(AD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD Inputs at t + + INTEGER :: AD_Start !< starting index of this mesh in AeroDyn inputs + + AD_Start = Indx_u_AD_Tower_Start(u_AD, y_FAST) + u_AD%TowerMotion%NNodes * 9 ! 3 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel) with 3 components + +END FUNCTION Indx_u_AD_Hub_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_AD%BladeRootMotion(k) mesh in the FAST linearization inputs. +FUNCTION Indx_u_AD_BladeRoot_Start(u_AD, y_FAST, BladeNum) RESULT(AD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD Inputs at t + INTEGER, INTENT(IN ) :: BladeNum !< blade number to find index for + INTEGER :: k !< blade number loop + + INTEGER :: AD_Start !< starting index of this mesh in AeroDyn inputs + + AD_Start = Indx_u_AD_Hub_Start(u_AD, y_FAST) + u_AD%HubMotion%NNodes * 9 ! 3 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_RotationVel) with 3 components + + do k = 1,min(BladeNum-1,size(u_AD%BladeRootMotion)) + AD_Start = AD_Start + u_AD%BladeRootMotion(k)%NNodes * 3 ! 1 field (MASKID_Orientation) with 3 components + end do +END FUNCTION Indx_u_AD_BladeRoot_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_AD%BladeMotion(k) mesh in the FAST linearization inputs. +FUNCTION Indx_u_AD_Blade_Start(u_AD, y_FAST, BladeNum) RESULT(AD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD Inputs at t + INTEGER, INTENT(IN ) :: BladeNum !< blade number to find index for + INTEGER :: k !< blade number loop + + INTEGER :: AD_Start !< starting index of this mesh in AeroDyn inputs + + AD_Start = Indx_u_AD_BladeRoot_Start(u_AD, y_FAST, MaxNBlades+1) + + do k = 1,min(BladeNum-1,size(u_AD%BladeMotion)) + AD_Start = AD_Start + u_AD%BladeMotion(k)%NNodes * 15 ! 5 fields (TranslationDisp, MASKID_Orientation, TranslationVel, RotationVel, TranslationAcc) with 3 components + end do +END FUNCTION Indx_u_AD_Blade_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_AD%InflowOnBlade array in the FAST linearization inputs. +FUNCTION Indx_u_AD_BladeInflow_Start(u_AD, y_FAST) RESULT(AD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD Inputs at t + + INTEGER :: AD_Start !< starting index of this array in AeroDyn inputs + + AD_Start = Indx_u_AD_Blade_Start(u_AD, y_FAST, MaxNBlades+1) + +END FUNCTION Indx_u_AD_BladeInflow_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_HD%Morison%DistribMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_HD_Distrib_Start(u_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs + + HD_Start = y_FAST%Lin%Modules(Module_HD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + +END FUNCTION Indx_u_HD_Distrib_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_HD%Morison%LumpedMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_HD_Lumped_Start(u_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs + + HD_Start = Indx_u_HD_Distrib_Start(u_HD, y_FAST) + if (u_HD%Morison%DistribMesh%committed) HD_Start = HD_Start + u_HD%Morison%DistribMesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components + +END FUNCTION Indx_u_HD_Lumped_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_HD%Mesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs + + HD_Start = Indx_u_HD_Lumped_Start(u_HD, y_FAST) + if (u_HD%Morison%LumpedMesh%committed) HD_Start = HD_Start + u_HD%Morison%LumpedMesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components + + END FUNCTION Indx_u_HD_PlatformRef_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_HD%Morison%DistribMesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_HD_Distrib_Start(y_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn Outputs + + HD_Start = y_FAST%Lin%Modules(Module_HD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + +END FUNCTION Indx_y_HD_Distrib_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_HD%Morison%LumpedMesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_HD_Lumped_Start(y_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn Outputs + + HD_Start = Indx_y_HD_Distrib_Start(y_HD, y_FAST) + if (y_HD%Morison%DistribMesh%committed) HD_Start = HD_Start + y_HD%Morison%DistribMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + +END FUNCTION Indx_y_HD_Lumped_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_HD%Mesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t + + INTEGER :: HD_Start + + !< starting index of this mesh in HydroDyn Outputs + + HD_Start = Indx_y_HD_Lumped_Start(y_HD, y_FAST) + if (y_HD%Morison%LumpedMesh%committed) HD_Start = HD_Start + y_HD%Morison%LumpedMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + + END FUNCTION Indx_y_HD_PlatformRef_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_HD%AllHdroOrigin mesh in the FAST linearization outputs. +FUNCTION Indx_y_HD_AllHdro_Start(y_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t + + INTEGER :: HD_Start + + !< starting index of this mesh in HydroDyn Outputs + + HD_Start = Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) + if (y_HD%Mesh%committed) HD_Start = HD_Start + y_HD%Mesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + +END FUNCTION Indx_y_HD_AllHdro_Start + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine allocates the arrays that store the operating point at each linearization time for later producing VTK +!! files of the mode shapes. +SUBROUTINE AllocateOP(p_FAST, y_FAST, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the 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) :: ErrStat2 + CHARACTER(*), PARAMETER :: RoutineName = 'AllocateOP' + + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------------------- + !! copy the operating point of the states and inputs at LinTimes(i) + !---------------------------------------------------------------------------------------- + + + ALLOCATE( y_FAST%op%x_ED(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_ED(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_ED(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_ED(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_ED(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + + IF ( p_FAST%CompElast == Module_BD ) THEN + ALLOCATE( y_FAST%op%x_BD(p_FAST%nBeams, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_BD(p_FAST%nBeams, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_BD(p_FAST%nBeams, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_BD(p_FAST%nBeams, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_BD(p_FAST%nBeams, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + + + !IF ( p_FAST%CompAero == Module_AD14 ) THEN + !ELSE + IF ( p_FAST%CompAero == Module_AD ) THEN + ALLOCATE( y_FAST%op%x_AD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_AD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_AD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_AD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_AD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + ALLOCATE( y_FAST%op%x_IfW(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_IfW(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_IfW(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_IfW(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_IfW(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + ALLOCATE( y_FAST%op%x_SrvD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_SrvD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_SrvD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_SrvD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_SrvD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + + IF ( p_FAST%CompHydro == Module_HD ) THEN + ALLOCATE( y_FAST%op%x_HD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_HD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_HD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_HD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_HD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + + ! SubDyn: copy final predictions to actual states + IF ( p_FAST%CompSub == Module_SD ) THEN + ALLOCATE( y_FAST%op%x_SD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_SD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_SD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_SD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_SD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + ALLOCATE( y_FAST%op%x_ExtPtfm(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_ExtPtfm(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_ExtPtfm(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_ExtPtfm(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_ExtPtfm(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + + + ! MAP/MoorDyn/FEAM: copy states and inputs to OP array + IF (p_FAST%CompMooring == Module_MAP) THEN + ALLOCATE( y_FAST%op%x_MAP(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_MAP(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_MAP(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + !ALLOCATE( y_FAST%op%OtherSt_MAP(p_FAST%NLinTimes), STAT=ErrStat2 ) + ! if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_MAP(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + ALLOCATE( y_FAST%op%x_MD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_MD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_MD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_MD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_MD(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + ALLOCATE( y_FAST%op%x_FEAM(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_FEAM(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_FEAM(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_FEAM(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_FEAM(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + !ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + END IF + + ! IceFloe/IceDyn: copy states and inputs to OP array + IF ( p_FAST%CompIce == Module_IceF ) THEN + ALLOCATE( y_FAST%op%x_IceF(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_IceF(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_IceF(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_IceF(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_IceF(p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + ALLOCATE( y_FAST%op%x_IceD(p_FAST%numIceLegs, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%xd_IceD(p_FAST%numIceLegs, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%z_IceD(p_FAST%numIceLegs, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%OtherSt_IceD(p_FAST%numIceLegs, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + ALLOCATE( y_FAST%op%u_IceD(p_FAST%numIceLegs, p_FAST%NLinTimes), STAT=ErrStat2 ) + if (ErrStat2 /= 0) call SetErrStat( ErrID_Fatal, 'Error allocating arrays for VTK operating points.', ErrStat, ErrMsg, RoutineName) + END IF + +END SUBROUTINE AllocateOP +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine is the inverse of SetOperatingPoint(). It saves the current operating points so they can be retrieved +!> when visualizing mode shapes. +SUBROUTINE SaveOP(i, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg, CtrlCode ) + + INTEGER(IntKi) , INTENT(IN ) :: i !< current index into LinTimes + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT(IN ) :: CtrlCode !< mesh copy control code (new, vs update) + + ! local variables + INTEGER(IntKi) :: k ! generic loop counters + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SaveOP' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !---------------------------------------------------------------------------------------- + !! copy the operating point of the states and inputs at LinTimes(i) + !---------------------------------------------------------------------------------------- + + ! ElastoDyn: copy states and inputs to OP array + CALL ED_CopyContState (ED%x( STATE_CURR), y_FAST%op%x_ED( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyDiscState (ED%xd(STATE_CURR), y_FAST%op%xd_ED( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyConstrState (ED%z( STATE_CURR), y_FAST%op%z_ED( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOtherState (ED%OtherSt( STATE_CURR), y_FAST%op%OtherSt_ED( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ED_CopyInput (ED%Input(1), y_FAST%op%u_ED( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! BeamDyn: copy states and inputs to OP array + IF ( p_FAST%CompElast == Module_BD ) THEN + DO k=1,p_FAST%nBeams + CALL BD_CopyContState (BD%x( k,STATE_CURR), y_FAST%op%x_BD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyDiscState (BD%xd(k,STATE_CURR), y_FAST%op%xd_BD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyConstrState (BD%z( k,STATE_CURR), y_FAST%op%z_BD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyOtherState (BD%OtherSt( k,STATE_CURR), y_FAST%op%OtherSt_BD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL BD_CopyInput (BD%Input(1,k), y_FAST%op%u_BD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO + END IF + + + + ! AeroDyn: copy states and inputs to OP array + !IF ( p_FAST%CompAero == Module_AD14 ) THEN + !ELSE + IF ( p_FAST%CompAero == Module_AD ) THEN + CALL AD_CopyContState (AD%x( STATE_CURR), y_FAST%op%x_AD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyDiscState (AD%xd(STATE_CURR), y_FAST%op%xd_AD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyConstrState (AD%z( STATE_CURR), y_FAST%op%z_AD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyOtherState (AD%OtherSt(STATE_CURR), y_FAST%op%OtherSt_AD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AD_CopyInput (AD%Input(1), y_FAST%op%u_AD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ! InflowWind: copy states and inputs to OP array + IF ( p_FAST%CompInflow == Module_IfW ) THEN + CALL InflowWind_CopyContState (IfW%x( STATE_CURR), y_FAST%op%x_IfW( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyDiscState (IfW%xd(STATE_CURR), y_FAST%op%xd_IfW( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyConstrState (IfW%z( STATE_CURR), y_FAST%op%z_IfW( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyOtherState( IfW%OtherSt( STATE_CURR), y_FAST%op%OtherSt_IfW( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL InflowWind_CopyInput (IfW%Input(1), y_FAST%op%u_IfW(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + + ! ServoDyn: copy states and inputs to OP array + IF ( p_FAST%CompServo == Module_SrvD ) THEN + CALL SrvD_CopyContState (SrvD%x( STATE_CURR), y_FAST%op%x_SrvD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyDiscState (SrvD%xd(STATE_CURR), y_FAST%op%xd_SrvD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyConstrState (SrvD%z( STATE_CURR), y_FAST%op%z_SrvD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyOtherState (SrvD%OtherSt( STATE_CURR), y_FAST%op%OtherSt_SrvD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL SrvD_CopyInput (SrvD%Input(1), y_FAST%op%u_SrvD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! HydroDyn: copy states and inputs to OP array + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CopyContState (HD%x( STATE_CURR), y_FAST%op%x_HD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyDiscState (HD%xd(STATE_CURR), y_FAST%op%xd_HD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyConstrState (HD%z( STATE_CURR), y_FAST%op%z_HD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOtherState (HD%OtherSt(STATE_CURR), y_FAST%op%OtherSt_HD( i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL HydroDyn_CopyInput (HD%Input(1), y_FAST%op%u_HD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! SubDyn: copy final predictions to actual states + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CopyContState (y_FAST%op%x_SD(i), SD%x( STATE_CURR), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyDiscState (y_FAST%op%xd_SD(i), SD%xd(STATE_CURR), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyConstrState( y_FAST%op%z_SD(i), SD%z( STATE_CURR), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOtherState (y_FAST%op%OtherSt_SD(i), SD%OtherSt(STATE_CURR), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL SD_CopyInput (y_FAST%op%u_SD(i), SD%Input(1), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CopyContState (ExtPtfm%x( STATE_CURR), y_FAST%op%x_ExtPtfm(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyDiscState (ExtPtfm%xd(STATE_CURR), y_FAST%op%xd_ExtPtfm(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyConstrState (ExtPtfm%z( STATE_CURR), y_FAST%op%z_ExtPtfm(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOtherState (ExtPtfm%OtherSt(STATE_CURR), y_FAST%op%OtherSt_ExtPtfm(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ExtPtfm_CopyInput (ExtPtfm%Input(1), y_FAST%op%u_ExtPtfm(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! MAP/MoorDyn/FEAM: copy states and inputs to OP array + IF (p_FAST%CompMooring == Module_MAP) THEN + CALL MAP_CopyContState (MAPp%x( STATE_CURR), y_FAST%op%x_MAP(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyDiscState (MAPp%xd(STATE_CURR), y_FAST%op%xd_MAP(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyConstrState (MAPp%z( STATE_CURR), y_FAST%op%z_MAP(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !CALL MAP_CopyOtherState (MAPp%OtherSt(STATE_CURR), y_FAST%op%OtherSt_MAP(i), CtrlCode, Errstat2, ErrMsg2) + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MAP_CopyInput (MAPp%Input(1), y_FAST%op%u_MAP(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + CALL MD_CopyContState (MD%x( STATE_CURR), y_FAST%op%x_MD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyDiscState (MD%xd(STATE_CURR), y_FAST%op%xd_MD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyConstrState (MD%z( STATE_CURR), y_FAST%op%z_MD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyOtherState (MD%OtherSt(STATE_CURR), y_FAST%op%OtherSt_MD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MD_CopyInput (MD%Input(1), y_FAST%op%u_MD(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + CALL FEAM_CopyContState (FEAM%x( STATE_CURR), y_FAST%op%x_FEAM(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyDiscState (FEAM%xd(STATE_CURR), y_FAST%op%xd_FEAM(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyConstrState (FEAM%z( STATE_CURR), y_FAST%op%z_FEAM(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyOtherState (FEAM%OtherSt( STATE_CURR), y_FAST%op%OtherSt_FEAM(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL FEAM_CopyInput (FEAM%Input(1), y_FAST%op%u_FEAM(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + END IF + + ! IceFloe/IceDyn: copy states and inputs to OP array + IF ( p_FAST%CompIce == Module_IceF ) THEN + CALL IceFloe_CopyContState (IceF%x( STATE_CURR), y_FAST%op%x_IceF(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyDiscState (IceF%xd(STATE_CURR), y_FAST%op%xd_IceF(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyConstrState (IceF%z( STATE_CURR), y_FAST%op%z_IceF(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyOtherState (IceF%OtherSt(STATE_CURR), y_FAST%op%OtherSt_IceF(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL IceFloe_CopyInput (IceF%Input(1), y_FAST%op%u_IceF(i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + DO k=1,p_FAST%numIceLegs + CALL IceD_CopyContState (IceD%x( k,STATE_CURR), y_FAST%op%x_IceD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyDiscState (IceD%xd(k,STATE_CURR), y_FAST%op%xd_IceD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyConstrState (IceD%z( k,STATE_CURR), y_FAST%op%z_IceD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyOtherState (IceD%OtherSt( k,STATE_CURR), y_FAST%op%OtherSt_IceD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL IceD_CopyInput (IceD%Input(1,k), y_FAST%op%u_IceD(k, i), CtrlCode, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + END IF + + +END SUBROUTINE SaveOP +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine takes arrays representing the eigenvector of the states and uses it to modify the operating points for +!! continuous states. It is highly tied to the module organizaton. +SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t + INTEGER(IntKi), INTENT(IN ) :: iLinTime !< index into LinTimes dimension of arrays (azimuth) + INTEGER(IntKi), INTENT(IN ) :: iMode !< index into Mode dimension of arrays + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: k ! generic loop counters + INTEGER(IntKi) :: i ! generic loop counters + INTEGER(IntKi) :: j ! generic loop counters + INTEGER(IntKi) :: indx ! generic loop counters + INTEGER(IntKi) :: indx_last ! generic loop counters + INTEGER(IntKi) :: i_x ! index into packed array + INTEGER(IntKi) :: nStates ! number of second-order states + INTEGER(IntKi) :: ThisModule ! identifier of current module + + CHARACTER(*), PARAMETER :: RoutineName = 'PerturbOP' + + + ErrStat = ErrID_None + ErrMsg = "" + + + i_x = 1 + + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do k=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag)) then + do j=1,size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x) ! use this for the loop because ED may have a larger op_x_eig_mag array than op_x + + ! this is a hack because not all modules pack the continuous states in the same way: + if (ThisModule == Module_ED) then + if (j<= ED%p%DOFs%NActvDOF) then + indx = ED%p%DOFs%PS(j) + else + indx = ED%p%DOFs%PS(j-ED%p%DOFs%NActvDOF) + ED%p%NDOF + end if + else + indx = j + end if + y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag( indx) = p_FAST%VTK_modes%x_eig_magnitude(i_x, iLinTime, iMode) ! this is going to hold the magnitude of the eigenvector + y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_phase(indx) = p_FAST%VTK_modes%x_eig_phase( i_x, iLinTime, iMode) ! this is going to hold the phase of the eigenvector + i_x = i_x + 1; + end do + end if + + end do + end do + + + + ! ElastoDyn: + ThisModule = Module_ED + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + nStates = size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)/2 + + call GetStateAry(p_FAST, iMode, t, ED%x( STATE_CURR)%QT, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) + call GetStateAry(p_FAST, iMode, t, ED%x( STATE_CURR)%QDT, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) + end if + + ! BeamDyn: + IF ( p_FAST%CompElast == Module_BD ) THEN + ThisModule = Module_BD + DO k=1,p_FAST%nBeams + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag)) then + nStates = size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag)/2 + + indx = 1 + do i=2,BD%p(k)%node_total + indx_last = indx + BD%p(k)%dof_node - 1 + call GetStateAry(p_FAST, iMode, t, BD%x(k, STATE_CURR)%q( :,i), y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag( indx:indx_last ), y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_phase( indx:indx_last )) + call GetStateAry(p_FAST, iMode, t, BD%x(k, STATE_CURR)%dqdt(:,i), y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag(nStates+indx:indx_last+nStates), y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_phase(nStates+indx:indx_last+nStates)) + indx = indx_last+1 + end do + + end if + + END DO + END IF + + + !!! ! AeroDyn: copy final predictions to actual states; copy current outputs to next + !!!!IF ( p_FAST%CompAero == Module_AD14 ) THEN + !!!!ELSE + IF ( p_FAST%CompAero == Module_AD ) THEN + ThisModule = Module_AD + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + + indx = 1 + ! set linearization operating points: + if (AD%p%BEMT%DBEMT%lin_nx>0) then + do j=1,size(AD%x(STATE_CURR)%BEMT%DBEMT%element,2) + do i=1,size(AD%x(STATE_CURR)%BEMT%DBEMT%element,1) + indx_last = indx + size(AD%x(STATE_CURR)%BEMT%DBEMT%element(i,j)%vind) - 1 + call GetStateAry(p_FAST, iMode, t, AD%x(STATE_CURR)%BEMT%DBEMT%element(i,j)%vind, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( indx : indx_last), & + y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(indx : indx_last) ) + indx = indx_last + 1 + end do + end do + + do j=1,size(AD%x(STATE_CURR)%BEMT%DBEMT%element,2) + do i=1,size(AD%x(STATE_CURR)%BEMT%DBEMT%element,1) + indx_last = indx + size(AD%x(STATE_CURR)%BEMT%DBEMT%element(i,j)%vind_dot) - 1 + call GetStateAry(p_FAST, iMode, t, AD%x(STATE_CURR)%BEMT%DBEMT%element(i,j)%vind_dot, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( indx : indx_last), & + y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(indx : indx_last) ) + indx = indx_last + 1 + end do + end do + + end if + + if (AD%p%BEMT%UA%lin_nx>0) then + do j=1,size(AD%x(STATE_CURR)%BEMT%UA%element,2) + do i=1,size(AD%x(STATE_CURR)%BEMT%UA%element,1) + indx_last = indx + size(AD%x(STATE_CURR)%BEMT%UA%element(i,j)%x) - 1 + call GetStateAry(p_FAST, iMode, t, AD%x(STATE_CURR)%BEMT%UA%element(i,j)%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( indx : indx_last), & + y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(indx : indx_last) ) + indx = indx_last + 1 + end do + end do + end if + + end if + END IF + !!! + !!!! InflowWind: copy op to actual states and inputs + !!!IF ( p_FAST%CompInflow == Module_IfW ) THEN + !!!END IF + !!! + !!! + !!!! ServoDyn: copy op to actual states and inputs + !!!IF ( p_FAST%CompServo == Module_SrvD ) THEN + !!!END IF + + + ! HydroDyn: copy op to actual states and inputs + IF ( p_FAST%CompHydro == Module_HD ) THEN + ThisModule = Module_HD + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + nStates = HD%p%WAMIT%SS_Exctn%N + if (nStates > 0) then + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT%SS_Exctn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) + end if + if (nStates < size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT%SS_Rdtn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) + end if + end if + END IF + + + !!!! SubDyn: copy final predictions to actual states + !!!IF ( p_FAST%CompSub == Module_SD ) THEN + !!!ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + !!!END IF + !!! + !!! + !!!! MAP/MoorDyn/FEAM: copy op to actual states and inputs + !!!IF (p_FAST%CompMooring == Module_MAP) THEN + !!!ELSEIF (p_FAST%CompMooring == Module_MD) THEN + !!!ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + !!!!ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + !!!END IF + !!! + !!! ! IceFloe/IceDyn: copy op to actual states and inputs + !!!IF ( p_FAST%CompIce == Module_IceF ) THEN + !!!ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + !!! DO k=1,p_FAST%numIceLegs + !!! END DO + !!!END IF + + +END SUBROUTINE PerturbOP +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetOperatingPoint(i, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat, ErrMsg ) + + INTEGER(IntKi), INTENT(IN ) :: i !< Index into LinTimes (to determine which operating point to copy) + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: k ! generic loop counters + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetOperatingPoint' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !---------------------------------------------------------------------------------------- + !! copy the operating point of the states and inputs at LinTimes(i) + !---------------------------------------------------------------------------------------- + ! ElastoDyn: copy op to actual states and inputs + CALL ED_CopyContState (y_FAST%op%x_ED( i), ED%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyDiscState (y_FAST%op%xd_ED( i), ED%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyConstrState (y_FAST%op%z_ED( i), ED%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOtherState (y_FAST%op%OtherSt_ED( i), ED%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ED_CopyInput (y_FAST%op%u_ED( i), ED%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! BeamDyn: copy op to actual states and inputs + IF ( p_FAST%CompElast == Module_BD ) THEN + DO k=1,p_FAST%nBeams + CALL BD_CopyContState (y_FAST%op%x_BD(k, i), BD%x( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyDiscState (y_FAST%op%xd_BD(k, i), BD%xd(k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyConstrState (y_FAST%op%z_BD(k, i), BD%z( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyOtherState (y_FAST%op%OtherSt_BD(k, i), BD%OtherSt( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL BD_CopyInput (y_FAST%op%u_BD(k, i), BD%Input(1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO + END IF + + ! AeroDyn: copy final predictions to actual states; copy current outputs to next + !IF ( p_FAST%CompAero == Module_AD14 ) THEN + !ELSE + IF ( p_FAST%CompAero == Module_AD ) THEN + CALL AD_CopyContState (y_FAST%op%x_AD( i), AD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyDiscState (y_FAST%op%xd_AD( i), AD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyConstrState (y_FAST%op%z_AD( i), AD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyOtherState (y_FAST%op%OtherSt_AD( i), AD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL AD_CopyInput (y_FAST%op%u_AD(i), AD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ! InflowWind: copy op to actual states and inputs + IF ( p_FAST%CompInflow == Module_IfW ) THEN + CALL InflowWind_CopyContState (y_FAST%op%x_IfW( i), IfW%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyDiscState (y_FAST%op%xd_IfW( i), IfW%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyConstrState (y_FAST%op%z_IfW( i), IfW%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyOtherState (y_FAST%op%OtherSt_IfW( i), IfW%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL InflowWind_CopyInput (y_FAST%op%u_IfW(i), IfW%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + + ! ServoDyn: copy op to actual states and inputs + IF ( p_FAST%CompServo == Module_SrvD ) THEN + CALL SrvD_CopyContState (y_FAST%op%x_SrvD( i), SrvD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyDiscState (y_FAST%op%xd_SrvD( i), SrvD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyConstrState (y_FAST%op%z_SrvD( i), SrvD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyOtherState (y_FAST%op%OtherSt_SrvD( i), SrvD%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL SrvD_CopyInput (y_FAST%op%u_SrvD(i), SrvD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! HydroDyn: copy op to actual states and inputs + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CopyContState (y_FAST%op%x_HD( i), HD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyDiscState (y_FAST%op%xd_HD( i), HD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyConstrState (y_FAST%op%z_HD( i), HD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOtherState (y_FAST%op%OtherSt_HD( i), HD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL HydroDyn_CopyInput (y_FAST%op%u_HD(i), HD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! SubDyn: copy final predictions to actual states + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CopyContState (y_FAST%op%x_SD(i), SD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyDiscState (y_FAST%op%xd_SD(i), SD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyConstrState( y_FAST%op%z_SD(i), SD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOtherState (y_FAST%op%OtherSt_SD(i), SD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL SD_CopyInput (y_FAST%op%u_SD(i), SD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CopyContState (y_FAST%op%x_ExtPtfm(i), ExtPtfm%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyDiscState (y_FAST%op%xd_ExtPtfm(i), ExtPtfm%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyConstrState (y_FAST%op%z_ExtPtfm(i), ExtPtfm%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOtherState (y_FAST%op%OtherSt_ExtPtfm(i), ExtPtfm%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ExtPtfm_CopyInput (y_FAST%op%u_ExtPtfm(i), ExtPtfm%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! MAP/MoorDyn/FEAM: copy op to actual states and inputs + IF (p_FAST%CompMooring == Module_MAP) THEN + CALL MAP_CopyContState (y_FAST%op%x_MAP(i), MAPp%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyDiscState (y_FAST%op%xd_MAP(i), MAPp%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyConstrState (y_FAST%op%z_MAP(i), MAPp%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !CALL MAP_CopyOtherState (y_FAST%op%OtherSt_MAP(i), MAPp%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MAP_CopyInput (y_FAST%op%u_MAP(i), MAPp%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + CALL MD_CopyContState (y_FAST%op%x_MD(i), MD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyDiscState (y_FAST%op%xd_MD(i), MD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyConstrState (y_FAST%op%z_MD(i), MD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyOtherState (y_FAST%op%OtherSt_MD(i), MD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL MD_CopyInput (y_FAST%op%u_MD(i), MD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + CALL FEAM_CopyContState (y_FAST%op%x_FEAM(i), FEAM%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyDiscState (y_FAST%op%xd_FEAM(i), FEAM%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyConstrState (y_FAST%op%z_FEAM(i), FEAM%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyOtherState (y_FAST%op%OtherSt_FEAM(i), FEAM%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL FEAM_CopyInput (y_FAST%op%u_FEAM(i), FEAM%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + END IF + + ! IceFloe/IceDyn: copy op to actual states and inputs + IF ( p_FAST%CompIce == Module_IceF ) THEN + CALL IceFloe_CopyContState (y_FAST%op%x_IceF(i), IceF%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyDiscState (y_FAST%op%xd_IceF(i), IceF%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyConstrState (y_FAST%op%z_IceF(i), IceF%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyOtherState (y_FAST%op%OtherSt_IceF(i), IceF%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL IceFloe_CopyInput (y_FAST%op%u_IceF(i), IceF%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + DO k=1,p_FAST%numIceLegs + CALL IceD_CopyContState (y_FAST%op%x_IceD(k, i), IceD%x( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyDiscState (y_FAST%op%xd_IceD(k, i), IceD%xd(k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyConstrState (y_FAST%op%z_IceD(k, i), IceD%z( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyOtherState (y_FAST%op%OtherSt_IceD(k, i), IceD%OtherSt( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL IceD_CopyInput (y_FAST%op%u_IceD(k, i), IceD%Input(1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + END IF + +END SUBROUTINE SetOperatingPoint +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine GetStateAry(p_FAST, iMode, t, x, x_eig_magnitude, x_eig_phase) + INTEGER(IntKi), INTENT(IN ) :: iMode !< index into Mode dimension of arrays + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + REAL(DbKi) , INTENT(IN ) :: t !< time + REAL(R8Ki), INTENT(INOUT) :: x(:) !< in: state at its operating point; out: added perturbation + REAL(R8Ki), INTENT(IN) :: x_eig_magnitude(:) !< magnitude of the eigenvector + REAL(R8Ki), INTENT(IN) :: x_eig_phase(:) !< phase of the eigenvector + + ! note that this assumes p_FAST%VTK_modes%VTKLinPhase is zero for VTKLinTim=2 + x = x + x_eig_magnitude * p_FAST%VTK_modes%VTKLinScale * cos( TwoPi_D * p_FAST%VTK_modes%DampedFreq_Hz(iMode)*t + x_eig_phase + p_FAST%VTK_modes%VTKLinPhase ) +end subroutine GetStateAry + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine performs the algorithm for computing a periodic steady-state solution. +SUBROUTINE FAST_CalcSteady( n_t_global, t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< integer time step + REAL(DbKi), INTENT(IN ) :: t_global ! current simulation time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: DeltaAzim + REAL(DbKi) :: psi !< psi (rotor azimuth) at which the outputs are defined + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + LOGICAL :: NextAzimuth + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CalcSteady' + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! get azimuth angle + + psi = ED%y%LSSTipPxa + call Zero2TwoPi( psi ) + + if (n_t_global == 0) then + ! initialize a few things on the first call: + call FAST_InitSteadyOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + else + DeltaAzim = psi - m_FAST%Lin%Psi(1) + call Zero2TwoPi(DeltaAzim) + + if (DeltaAzim > p_FAST%AzimDelta) then + call SetErrStat(ErrID_Fatal, "The rotor is spinning too fast. The time step or NLinTimes is too large when CalcSteady=true.", ErrStat, ErrMsg, RoutineName) + return + end if + + ! save the outputs and azimuth angle for possible interpolation later + call FAST_SaveOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + if (ErrStat >= AbortErrLev) return + + + + if ( m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx-1) <= m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx) ) then ! the equal sign takes care of the zero-rpm case + NextAzimuth = psi >= m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx) + else + ! this is the 2pi boundary, so we are either larger than the last target azimuth or less than the next one + NextAzimuth = psi >= m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx) .and. psi < m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx-1) + end if + + if (NextAzimuth) then + + ! interpolate to find y at the target azimuth + call FAST_DiffInterpOutputs( m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx), p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + if (m_FAST%Lin%IsConverged .or. m_FAST%Lin%n_rot == 0) then ! save this operating point for linearization later + m_FAST%Lin%LinTimes(m_FAST%Lin%AzimIndx) = t_global + call SaveOP(m_FAST%Lin%AzimIndx, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg, m_FAST%Lin%CopyOP_CtrlCode ) + end if + + ! increment the counter to check the next azimuth: + m_FAST%Lin%AzimIndx = m_FAST%Lin%AzimIndx + 1 + + ! check if we've completed one rotor revolution + if (m_FAST%Lin%AzimIndx > p_FAST%NLinTimes) then + m_FAST%Lin%n_rot = m_FAST%Lin%n_rot + 1 + + m_FAST%Lin%FoundSteady = m_FAST%Lin%IsConverged + + if (.not. m_FAST%Lin%FoundSteady) then + ! compute the reference values for this rotor revolution + call ComputeOutputRanges(p_FAST, y_FAST, m_FAST, SrvD%y) + m_FAST%Lin%IsConverged = .true. ! check errors next rotor revolution + m_FAST%Lin%AzimIndx = 1 + m_FAST%Lin%CopyOP_CtrlCode = MESH_UPDATECOPY + end if + end if + + end if + + +END SUBROUTINE FAST_CalcSteady +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes variables for calculating periodic steady-state solution. +SUBROUTINE FAST_InitSteadyOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: psi !< psi (rotor azimuth) at which the outputs are defined + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: j, k ! loop counters + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_InitSteadyOutputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + do j=1,p_FAST%NLinTimes + m_FAST%Lin%AzimTarget(j) = (j-1) * p_FAST%AzimDelta + psi + call Zero2TwoPi( m_FAST%Lin%AzimTarget(j) ) + end do + ! this is circular, so I am going to add points at the beginning and end to avoid + ! more IF statements later + m_FAST%Lin%AzimTarget(0) = m_FAST%Lin%AzimTarget(p_FAST%NLinTimes) + m_FAST%Lin%AzimTarget(p_FAST%NLinTimes+1) = m_FAST%Lin%AzimTarget(1) + + + ! Azimuth angles that correspond to Output arrays for interpolation: + !m_FAST%Lin%Psi = psi ! initialize entire array (note that we won't be able to interpolate with a constant array + DO j = 1, p_FAST%LinInterpOrder + 1 + m_FAST%Lin%Psi(j) = psi - (j - 1) * D2R_D ! arbitrarily say azimuth is one degree different + END DO + + + ! ElastoDyn + allocate( ED%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating ED%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call ED_CopyOutput(ED%y, ED%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call ED_CopyOutput(ED%y, ED%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + ! BeamDyn + IF (p_FAST%CompElast == Module_BD) THEN + + allocate( BD%Output( p_FAST%LinInterpOrder+1, p_FAST%nBeams ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating BD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do k=1,p_FAST%nBeams + do j = 1, p_FAST%LinInterpOrder + 1 + call BD_CopyOutput(BD%y(k), BD%Output(j,k), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + end do + + allocate( BD%y_interp( p_FAST%nBeams ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating BD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do k=1,p_FAST%nBeams + call BD_CopyOutput(BD%y(k), BD%y_interp(k), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + end if + + end if + + END IF ! BeamDyn + + ! AeroDyn + IF ( p_FAST%CompAero == Module_AD ) THEN + + allocate( AD%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating AD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call AD_CopyOutput(AD%y, AD%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call AD_CopyOutput(AD%y, AD%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + END IF ! CompAero + + + ! InflowWind + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + allocate( IfW%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating IfW%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call InflowWind_CopyOutput(IfW%y, IfW%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call InflowWind_CopyOutput(IfW%y, IfW%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + END IF ! CompInflow + + + ! ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + allocate( SrvD%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating SrvD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call SrvD_CopyOutput(SrvD%y, SrvD%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call SrvD_CopyOutput(SrvD%y, SrvD%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + END IF ! ServoDyn + + ! HydroDyn + IF ( p_FAST%CompHydro == Module_HD ) THEN + + allocate( HD%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating HD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call HydroDyn_CopyOutput(HD%y, HD%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call HydroDyn_CopyOutput(HD%y, HD%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + END IF ! HydroDyn + + + !! SubDyn/ExtPtfm_MCKF + !IF ( p_FAST%CompSub == Module_SD ) THEN + !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + !END IF ! SubDyn/ExtPtfm_MCKF + + + ! Mooring (MAP , FEAM , MoorDyn) + ! MAP + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + allocate( MAPp%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating MAPp%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call MAP_CopyOutput(MAPp%y, MAPp%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call MAP_CopyOutput(MAPp%y, MAPp%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + + !! MoorDyn + !ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + !! FEAM + !ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + !! OrcaFlex + !ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + + END IF ! MAP/FEAM/MoorDyn/OrcaFlex + + + + !! Ice (IceFloe or IceDyn) + !! IceFloe + !IF ( p_FAST%CompIce == Module_IceF ) THEN + ! + !! IceDyn + !ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + ! + !END IF ! IceFloe/IceDyn + + +END SUBROUTINE FAST_InitSteadyOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine saves outputs for future interpolation at a desired azimuth. +SUBROUTINE FAST_SaveOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: psi !< psi (rotor azimuth) at which the outputs are defined + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: j, k ! loop counters + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_SaveOutputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + DO j = p_FAST%LinInterpOrder, 1, -1 + m_FAST%Lin%Psi(j+1) = m_FAST%Lin%Psi(j) + END DO + + if (psi < m_FAST%Lin%Psi(1)) then + ! if we go around a 2pi boundary, we will subtract 2pi from the saved values so that interpolation works as expected + m_FAST%Lin%Psi = m_FAST%Lin%Psi - TwoPi_D + end if + m_FAST%Lin%Psi(1) = psi + + ! ElastoDyn + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL ED_CopyOutput(ED%Output(j), ED%Output(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL ED_CopyOutput (ED%y, ED%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! BeamDyn + IF (p_FAST%CompElast == Module_BD) THEN + + DO k = 1,p_FAST%nBeams + + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL BD_CopyOutput (BD%Output(j,k), BD%Output(j+1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL BD_CopyOutput (BD%y(k), BD%Output(1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + END DO ! k=p_FAST%nBeams + + END IF ! BeamDyn + + + ! AeroDyn + IF ( p_FAST%CompAero == Module_AD ) THEN + + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL AD_CopyOutput (AD%Output(j), AD%Output(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL AD_CopyOutput (AD%y, AD%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + END IF ! CompAero + + + ! InflowWind + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL InflowWind_CopyOutput (IfW%Output(j), IfW%Output(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL InflowWind_CopyOutput (IfW%y, IfW%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + END IF ! CompInflow + + + ! ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL SrvD_CopyOutput (SrvD%Output(j), SrvD%Output(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL SrvD_CopyOutput (SrvD%y, SrvD%Output(1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + END IF ! ServoDyn + + ! HydroDyn + IF ( p_FAST%CompHydro == Module_HD ) THEN + + DO j = p_FAST%LinInterpOrder, 1, -1 + + CALL HydroDyn_CopyOutput (HD%Output(j), HD%Output(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL HydroDyn_CopyOutput (HD%y, HD%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + END IF ! HydroDyn + + + !! SubDyn/ExtPtfm_MCKF + !IF ( p_FAST%CompSub == Module_SD ) THEN + !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + !END IF ! SubDyn/ExtPtfm_MCKF + + + ! Mooring (MAP , FEAM , MoorDyn) + ! MAP + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL MAP_CopyOutput (MAPp%Output(j), MAPp%Output(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL MAP_CopyOutput (MAPp%y, MAPp%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + !! MoorDyn + !ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + !! FEAM + !ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + !! OrcaFlex + !ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + + END IF ! MAP/FEAM/MoorDyn/OrcaFlex + + + + !! Ice (IceFloe or IceDyn) + !! IceFloe + !IF ( p_FAST%CompIce == Module_IceF ) THEN + ! + !! IceDyn + !ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + ! + !END IF ! IceFloe/IceDyn + + +END SUBROUTINE FAST_SaveOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine interpolates the outputs at the target azimuths, computes the compared to the previous rotation, and stores +!! them for future rotation . +SUBROUTINE FAST_DiffInterpOutputs( psi_target, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: psi_target !< psi (rotor azimuth) at which the outputs are requested + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: k ! loop counters + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + REAL(DbKi) :: t_global + REAL(ReKi) :: eps_squared + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DiffInterpOutputs' + + ErrStat = ErrID_None + ErrMsg = "" + t_global = 0.0_DbKi ! we don't really need this to get the output OPs + + !................................................................................................ + ! Extrapolate outputs to the target azimuth and pack into OP arrays + !................................................................................................ + + ! ElastoDyn + CALL ED_Output_ExtrapInterp (ED%Output, m_FAST%Lin%Psi, ED%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call ED_GetOP( t_global, ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y_interp, ED%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_ED)%Instance(1)%op_y, NeedLogMap=.true.) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! BeamDyn + IF (p_FAST%CompElast == Module_BD) THEN + + DO k = 1,p_FAST%nBeams + + CALL BD_Output_ExtrapInterp (BD%Output(:,k), m_FAST%Lin%Psi, BD%y_interp(k), psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call BD_GetOP( t_global, BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), BD%OtherSt(k,STATE_CURR), & + BD%y_interp(k), BD%m(k), ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_BD)%Instance(k)%op_y, NeedLogMap=.true.) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END DO ! k=p_FAST%nBeams + + END IF ! BeamDyn + + + ! AeroDyn + IF ( p_FAST%CompAero == Module_AD ) THEN + + CALL AD_Output_ExtrapInterp (AD%Output, m_FAST%Lin%Psi, AD%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call AD_GetOP( t_global, AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), AD%OtherSt(STATE_CURR), & + AD%y_interp, AD%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_AD)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END IF ! CompAero + + + ! InflowWind + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + CALL InflowWind_Output_ExtrapInterp (IfW%Output, m_FAST%Lin%Psi, IfW%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call InflowWind_GetOP( t_global, IfW%Input(1), IfW%p, IfW%x(STATE_CURR), IfW%xd(STATE_CURR), IfW%z(STATE_CURR), IfW%OtherSt(STATE_CURR), & + IfW%y_interp, IfW%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_IfW)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END IF ! CompInflow + + + ! ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + CALL SrvD_Output_ExtrapInterp (SrvD%Output, m_FAST%Lin%Psi, SrvD%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call SrvD_GetOP( t_global, SrvD%Input(1), SrvD%p, SrvD%x(STATE_CURR), SrvD%xd(STATE_CURR), SrvD%z(STATE_CURR), SrvD%OtherSt(STATE_CURR), & + SrvD%y_interp, SrvD%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END IF ! ServoDyn + + ! HydroDyn + IF ( p_FAST%CompHydro == Module_HD ) THEN + + CALL HydroDyn_Output_ExtrapInterp (HD%Output, m_FAST%Lin%Psi, HD%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call HD_GetOP( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y_interp, HD%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END IF ! HydroDyn + + + !! SubDyn/ExtPtfm_MCKF + !IF ( p_FAST%CompSub == Module_SD ) THEN + !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + !END IF ! SubDyn/ExtPtfm_MCKF + + + ! Mooring (MAP , FEAM , MoorDyn) + ! MAP + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + CALL MAP_Output_ExtrapInterp (MAPp%Output, m_FAST%Lin%Psi, MAPp%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call MAP_GetOP( t_global, MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), MAPp%OtherSt, & + MAPp%y_interp, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_MAP)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + !! MoorDyn + !ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + !! FEAM + !ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + !! OrcaFlex + !ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + + END IF ! MAP/FEAM/MoorDyn/OrcaFlex + + + + !! Ice (IceFloe or IceDyn) + !! IceFloe + !IF ( p_FAST%CompIce == Module_IceF ) THEN + ! + !! IceDyn + !ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + ! + !END IF ! IceFloe/IceDyn + + + call pack_in_array(p_FAST, y_FAST, m_FAST) + + if (m_FAST%Lin%IsConverged) then + ! check that error equation is less than TrimTol !!!call + call calc_error(p_FAST, y_FAST, m_FAST, SrvD%y, eps_squared) + m_FAST%Lin%IsConverged = eps_squared < p_FAST%TrimTol + end if + + + m_FAST%Lin%Y_prevRot(:,m_FAST%Lin%AzimIndx) = m_FAST%Lin%y_interp + +END SUBROUTINE FAST_DiffInterpOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE pack_in_array(p_FAST, y_FAST, m_FAST) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + + INTEGER(IntKi) :: ThisModule !< module identifier + INTEGER(IntKi) :: ThisInstance !< index of the module instance + + integer :: i, j + integer :: ny + integer :: indx + + ! note that op_y may be larger than SizeLin if there are orientations; also, we are NOT including the WriteOutputs + + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do ThisInstance=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + + ny = y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%SizeLin(LIN_OUTPUT_COL) - y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%NumOutputs !last column before WriteOutput occurs + do j=1,ny + indx = y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%LinStartIndx(LIN_OUTPUT_COL) + j - 1 + + m_FAST%Lin%y_interp( indx ) = y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%op_y(j) + end do + + end do + end do + +END SUBROUTINE pack_in_array +!---------------------------------------------------------------------------------------------------------------------------------- +!> This function computes the error function between this rotor revolution and the previous one. +!! Angles represented in m_FAST%Lin%y_interp may have 2pi added or subtracted to allow the angles to be closer to the previous +!! rotor revolution. +SUBROUTINE calc_error(p_FAST, y_FAST, m_FAST, y_SrvD, eps_squared) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(SrvD_OutputType), INTENT(IN ) :: y_SrvD !< Output variables for the glue code + REAL(ReKi) ,INTENT( OUT) :: eps_squared !< epsilon squared + + INTEGER(IntKi) :: ThisModule !< module identifier + INTEGER(IntKi) :: ThisInstance !< index of the module instance + + integer :: i, j + integer :: ny + integer :: indx + real(ReKi) :: diff + + + ! special cases for angles: + indx = Indx_y_Yaw_Start(y_FAST, Module_ED) ! start of ED where Yaw, YawRate, HSS_Spd occur (right before WriteOutputs) + call AddOrSub2Pi(m_FAST%Lin%Y_prevRot( indx, m_FAST%Lin%AzimIndx ), m_FAST%Lin%y_interp( indx )) + + if (p_FAST%CompServo == Module_SrvD) then + do i = 1, size( y_SrvD%BlPitchCom ) + indx = y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + i - 1 + call AddOrSub2Pi(m_FAST%Lin%Y_prevRot( indx, m_FAST%Lin%AzimIndx ), m_FAST%Lin%y_interp( indx )) + end do + end if + + + ! compute the error: + eps_squared = 0.0_ReKi + + do i = 1,p_FAST%Lin_NumMods + ThisModule = p_FAST%Lin_ModOrder( i ) + + do ThisInstance=1,size(y_FAST%Lin%Modules(ThisModule)%Instance) + + ny = y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%SizeLin(LIN_OUTPUT_COL) - y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%NumOutputs !last column before WriteOutput occurs + + do j=1,ny + indx = y_FAST%Lin%Modules(ThisModule)%Instance(ThisInstance)%LinStartIndx(LIN_OUTPUT_COL) + j - 1 + + if (EqualRealNos(m_FAST%Lin%y_interp( indx ), m_FAST%Lin%Y_prevRot( indx, m_FAST%Lin%AzimIndx ))) then + diff = 0.0_ReKi ! take care of some potential numerical issues + else + diff = m_FAST%Lin%y_interp( indx ) - m_FAST%Lin%Y_prevRot( indx, m_FAST%Lin%AzimIndx ) + end if + + eps_squared = eps_squared + ( diff / m_FAST%Lin%y_ref( indx ) ) ** 2 + end do + + end do + end do + + + !................................. + ! Normalize: + !................................. + eps_squared = eps_squared / ( y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL) - y_FAST%Lin%Glue%NumOutputs ) + +! write(50+m_FAST%Lin%AzimIndx,'(3000(F15.7,1x))') m_FAST%Lin%y_interp, eps_squared +END SUBROUTINE calc_error +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ComputeOutputRanges(p_FAST, y_FAST, m_FAST, y_SrvD) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(SrvD_OutputType), INTENT(IN ) :: y_SrvD !< Output variables for the glue code + + integer :: indx + integer :: i + + ! note that op_y may be larger than SizeLin if there are orientations; also, we are NOT including the WriteOutputs + + do indx = 1,y_FAST%Lin%Glue%SizeLin(LIN_OUTPUT_COL) + m_FAST%Lin%y_ref(indx) = maxval( m_FAST%Lin%Y_prevRot( indx, : ) ) - minval( m_FAST%Lin%Y_prevRot( indx, : ) ) + m_FAST%Lin%y_ref(indx) = max( m_FAST%Lin%y_ref(indx), 0.01_ReKi ) +! if (m_FAST%Lin%y_ref(indx) < 1.0e-4) m_FAST%Lin%y_ref(indx) = 1.0_ReKi ! not sure why we wouldn't just do m_FAST%Lin%y_ref(indx) = max(1.0_ReKi, m_FAST%Lin%y_ref(indx)) or max(1e-4, y_ref(indx)) + end do + + ! special case for angles: + indx = Indx_y_Yaw_Start(y_FAST, Module_ED) ! start of ED where Yaw, YawRate, HSS_Spd occur (right before WriteOutputs) + m_FAST%Lin%y_ref(indx) = min( m_FAST%Lin%y_ref(indx), Pi ) + + if (p_FAST%CompServo == Module_SrvD) then + do i = 1, size( y_SrvD%BlPitchCom ) + indx = y_FAST%Lin%Modules(Module_SrvD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + i - 1 + m_FAST%Lin%y_ref(indx) = min( m_FAST%Lin%y_ref(indx), Pi ) + end do + end if + + ! Note: I'm ignoring the periodicity of the log maps that represent orientations + +END SUBROUTINE ComputeOutputRanges +!---------------------------------------------------------------------------------------------------------------------------------- + +END MODULE FAST_Linear diff --git a/OpenFAST/modules/openfast-library/src/FAST_Mods.f90 b/OpenFAST/modules/openfast-library/src/FAST_Mods.f90 new file mode 100644 index 000000000..f528ae815 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Mods.f90 @@ -0,0 +1,72 @@ +!********************************************************************************************************************************** +! FAST_Prog.f90, FAST_Subs.f90, FAST_Solver.f90, FAST_Lin.f90, FAST_Types.f90, and FAST_Mods.f90 make up the FAST glue code in +! the FAST Modularization Framework. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST. +! +! 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 FAST_ModTypes + + USE NWTC_Library + USE FAST_Types + + TYPE(ProgDesc), PARAMETER :: FAST_Ver = & + ProgDesc( 'OpenFAST', '', '' ) !< The version number of this module + + !.................................................................. + + INTEGER(IntKi), PARAMETER :: Type_LandBased = 1 + INTEGER(IntKi), PARAMETER :: Type_Offshore_Fixed = 2 + INTEGER(IntKi), PARAMETER :: Type_Offshore_Floating = 3 + + ! state array indexes + INTEGER(IntKi), PARAMETER :: STATE_CURR = 1 !< index for "current" (t_global) states + INTEGER(IntKi), PARAMETER :: STATE_PRED = 2 !< index for "predicted" (t_global_next) states + + ! VTK visualization + INTEGER(IntKi), PARAMETER :: VTK_Unknown = -1 !< unknown option (will produce error) + INTEGER(IntKi), PARAMETER :: VTK_None = 0 !< none (no VTK output) + INTEGER(IntKi), PARAMETER :: VTK_InitOnly = 1 !< VTK output only at initialization + INTEGER(IntKi), PARAMETER :: VTK_Animate = 2 !< VTK animation output + INTEGER(IntKi), PARAMETER :: VTK_ModeShapes = 3 !< VTK output after linearization analysis + + INTEGER(IntKi), PARAMETER :: VTK_Surf = 1 !< output surfaces + INTEGER(IntKi), PARAMETER :: VTK_Basic = 2 !< output minimal number of point/line meshes + INTEGER(IntKi), PARAMETER :: VTK_All = 3 !< output all point/line meshes + INTEGER(IntKi), PARAMETER :: VTK_Old = 4 !< output in old binary format (for Matlab viewing) + REAL(SiKi), PARAMETER :: VTK_GroundFactor = 4.0_SiKi !< factor for number of rotor radii -- sets width of seabed, waves, and still water in VTK surface visualization + + ! linearization values + INTEGER(IntKi), PARAMETER :: LIN_NONE = 0 !< no inputs/outputs in linearization + INTEGER(IntKi), PARAMETER :: LIN_STANDARD = 1 !< use standard inputs/outputs in linearization + INTEGER(IntKi), PARAMETER :: LIN_ALL = 2 !< use all inputs/outputs in linearization + + INTEGER(IntKi), PARAMETER :: LIN_INPUT_COL = 1 !< index for inputs + INTEGER(IntKi), PARAMETER :: LIN_OUTPUT_COL = 2 !< index for outputs + INTEGER(IntKi), PARAMETER :: LIN_ContSTATE_COL = 3 !< index for continuous states + + + INTEGER(IntKi), PARAMETER :: SizeJac_ED_HD = 12 + + LOGICAL, PARAMETER :: GenerateAdamsModel = .FALSE. + + LOGICAL, PARAMETER :: BD_Solve_Option1 = .TRUE. + + +END MODULE FAST_ModTypes +!======================================================================= + diff --git a/OpenFAST/modules/openfast-library/src/FAST_Registry.txt b/OpenFAST/modules/openfast-library/src/FAST_Registry.txt new file mode 100644 index 000000000..d599f9326 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Registry.txt @@ -0,0 +1,720 @@ +################################################################################################################################### +# Registry for FAST v8 in the FAST Modularization Framework +# This Registry file is used to create FAST_Types which contains data used in the FAST glue code. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library and module components) ............................................................................ +include Registry_NWTC_Library.txt +usefrom ElastoDyn_Registry.txt +usefrom Registry_BeamDyn.txt +usefrom ServoDyn_Registry.txt +usefrom Registry-AD14.txt +usefrom AeroDyn_Registry.txt +usefrom SubDyn_Registry.txt +usefrom HydroDyn.txt +usefrom IceFloe_FASTRegistry.inp +usefrom InflowWind.txt +usefrom OpenFOAM_Registry.txt +usefrom SuperController_Registry.txt +usefrom Registry_IceDyn.txt +usefrom FEAM_Registry.txt +usefrom MAP_Registry.txt +usefrom MoorDyn_Registry.txt +usefrom OrcaFlexInterface.txt +usefrom ExtPtfm_MCKF_Registry.txt + +# ...... Constants ............................................................................ + +# MODULE IDENTIFIERS: +# NOTE WELL: The order of these modules is the order they get written to the output file; +# Make sure the module identifiers start at 1 and that this order matches the orders in WrOutputLine and FAST_InitOutput!!! +param FAST - INTEGER Module_Unknown - -1 - "Unknown" - +param ^ - INTEGER Module_None - 0 - "No module selected" - +param ^ - INTEGER Module_IfW - 1 - "InflowWind" - +param ^ - INTEGER Module_OpFM - 2 - "OpenFOAM" - +param ^ - INTEGER Module_ED - 3 - "ElastoDyn" - +param ^ - INTEGER Module_BD - 4 - "BeamDyn" - +param ^ - INTEGER Module_AD14 - 5 - "AeroDyn14" - +param ^ - INTEGER Module_AD - 6 - "AeroDyn" - +param ^ - INTEGER Module_SrvD - 7 - "ServoDyn" - +param ^ - INTEGER Module_HD - 8 - "HydroDyn" - +param ^ - INTEGER Module_SD - 9 - "SubDyn" - +param ^ - INTEGER Module_ExtPtfm - 10 - "External Platform Loading MCKF" - +param ^ - INTEGER Module_MAP - 11 - "MAP (Mooring Analysis Program)" - +param ^ - INTEGER Module_FEAM - 12 - "FEAMooring" - +param ^ - INTEGER Module_MD - 13 - "MoorDyn" - +param ^ - INTEGER Module_Orca - 14 - "OrcaFlex integration (HD/Mooring)" - +param ^ - INTEGER Module_IceF - 15 - "IceFloe" - +param ^ - INTEGER Module_IceD - 16 - "IceDyn" - +param ^ - INTEGER NumModules - 16 - "The number of modules available in FAST" - +# Other Constants +param ^ - INTEGER MaxNBlades - 3 - "Maximum number of blades allowed on a turbine" - +param ^ - INTEGER IceD_MaxLegs - 4 - "because I don't know how many legs there are before calling IceD_Init and I don't want to copy the data because of sibling mesh issues, I'm going to allocate IceD based on this number" - +# ...... Data for VTK surface visualization ............................................................................ +typedef ^ FAST_VTK_BLSurfaceType SiKi AirfoilCoords {:}{:}{:} - - "x,y coordinates for airfoil around each blade node on a blade (relative to reference)" - +# ...... Data for VTK surface visualization ............................................................................ +typedef ^ FAST_VTK_SurfaceType IntKi NumSectors - - - "number of sectors in which to split circles (higher number gives smoother surface)" - +typedef ^ FAST_VTK_SurfaceType SiKi HubRad - - - "Preconed hub radius (distance from the rotor apex to the blade root)" m +typedef ^ FAST_VTK_SurfaceType SiKi GroundRad - - - "radius for plotting circle on ground" m +typedef ^ FAST_VTK_SurfaceType SiKi NacelleBox {3}{8} - - "X-Y-Z locations of 8 points that define the nacelle box, relative to the nacelle position" m +typedef ^ FAST_VTK_SurfaceType SiKi TowerRad {:} - - "radius of each ED tower node" m +typedef ^ FAST_VTK_SurfaceType IntKi NWaveElevPts {2} - - "number of points for wave elevation visualization" - +typedef ^ FAST_VTK_SurfaceType SiKi WaveElevXY {:}{:} - - "X-Y locations for WaveElev output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number." "m,-" +typedef ^ FAST_VTK_SurfaceType SiKi WaveElev {:}{:} - - "wave elevation at WaveElevXY; first dimension is time step; second dimension is point number" "m,-" +typedef ^ FAST_VTK_SurfaceType FAST_VTK_BLSurfaceType BladeShape {:} - - "AirfoilCoords for each blade" m +typedef ^ FAST_VTK_SurfaceType SiKi MorisonRad {:} - - "radius of each Morison node" m + + +typedef ^ FAST_VTK_ModeShapeType CHARACTER(1024) CheckpointRoot - - - "name of the checkpoint file written by FAST when linearization data was produced" +typedef ^ FAST_VTK_ModeShapeType CHARACTER(1024) MatlabFileName - - - "name of the file with eigenvectors written by Matlab" +typedef ^ FAST_VTK_ModeShapeType IntKi VTKLinModes - - - "Number of modes to visualize" - +typedef ^ FAST_VTK_ModeShapeType IntKi VTKModes {:} - - "Which modes to visualize" - +typedef ^ FAST_VTK_ModeShapeType IntKi VTKLinTim - - - "Switch to make one animation for all LinTimes together (1) or separate animations for each LinTimes(2)" - +typedef ^ FAST_VTK_ModeShapeType IntKi VTKNLinTimes - - - "number of linearization times to use when VTKLinTim==2" - +typedef ^ FAST_VTK_ModeShapeType ReKi VTKLinScale - - - "Mode shape visualization scaling factor" - +typedef ^ FAST_VTK_ModeShapeType ReKi VTKLinPhase - - - "Phase when making one animation for all LinTimes together (used only when VTKLinTim=1)" - +typedef ^ FAST_VTK_ModeShapeType R8Ki DampingRatio {:} - - "damping ratios from mbc3 analysis" - +typedef ^ FAST_VTK_ModeShapeType R8Ki NaturalFreq_Hz {:} - - "natural frequency from mbc3 analysis" - +typedef ^ FAST_VTK_ModeShapeType R8Ki DampedFreq_Hz {:} - - "damped frequency from mbc3 analysis" - +typedef ^ FAST_VTK_ModeShapeType R8Ki x_eig_magnitude {:}{:}{:} - - "magnitude of eigenvector (dimension 1=state, dim 2= azimuth, dim 3 = mode)" - +typedef ^ FAST_VTK_ModeShapeType R8Ki x_eig_phase {:}{:}{:} - - "phase of eigenvector (dimension 1=state, dim 2= azimuth, dim 3 = mode)" - + + +# ..... FAST_ParameterType data ....................................................................................................... +# Misc data for coupling: +typedef FAST FAST_ParameterType DbKi DT - - - "Integration time step [global time]" s +typedef ^ FAST_ParameterType DbKi DT_module {NumModules} - - "Integration time step [global time]" s +typedef ^ FAST_ParameterType IntKi n_substeps {NumModules} - - "The number of module substeps for advancing states from t_global to t_global_next" - +typedef ^ FAST_ParameterType INTEGER n_TMax_m1 - - - "The time step of TMax - dt (the end time of the simulation)" (-) +typedef ^ FAST_ParameterType DbKi TMax - - - "Total run time" s +typedef ^ FAST_ParameterType IntKi InterpOrder - - - "Interpolation order {0,1,2}" - +typedef ^ FAST_ParameterType IntKi NumCrctn - - - "Number of correction iterations" - +typedef ^ FAST_ParameterType IntKi KMax - - - "Maximum number of input-output-solve iterations (KMax >= 1)" - +typedef ^ FAST_ParameterType IntKi numIceLegs - - - "number of suport-structure legs in contact with ice (IceDyn coupling)" - +typedef ^ FAST_ParameterType IntKi nBeams - - - "number of BeamDyn instances" - +typedef ^ FAST_ParameterType LOGICAL BD_OutputSibling - - - "flag to determine if BD input is sibling of output mesh" - +typedef ^ FAST_ParameterType LOGICAL ModuleInitialized {NumModules} - - "An array determining if the module has been initialized" - +# Data for Jacobians: +typedef ^ FAST_ParameterType DbKi DT_Ujac - - - "Time between when we need to re-calculate these Jacobians" s +typedef ^ FAST_ParameterType Reki UJacSclFact - - - "Scaling factor used to get similar magnitudes between accelerations, forces, and moments in Jacobians" - +typedef ^ FAST_ParameterType IntKi SizeJac_Opt1 {9} - - "(1)=size of matrix; (2)=size of ED portion; (3)=size of SD portion [2 meshes]; (4)=size of HD portion; (5)=size of BD portion blade 1; (6)=size of BD portion blade 2; (7)=size of BD portion blade 3; (8)=size of Orca portion; (9)=size of ExtPtfm portion;" - +# Feature switches and flags: +typedef ^ FAST_ParameterType IntKi CompElast - - - "Compute blade loads (switch) {Module_ED; Module_BD}" - +typedef ^ FAST_ParameterType IntKi CompInflow - - - "Compute inflow wind conditions (switch) {Module_None; Module_IfW; Module_OpFM}" - +typedef ^ FAST_ParameterType IntKi CompAero - - - "Compute aerodynamic loads (switch) {Module_None; Module_AD14; Module_AD}" - +typedef ^ FAST_ParameterType IntKi CompServo - - - "Compute control and electrical-drive dynamics (switch) {Module_None; Module_SrvD}" - +typedef ^ FAST_ParameterType IntKi CompHydro - - - "Compute hydrodynamic loads (switch) {Module_None; Module_HD}" - +typedef ^ FAST_ParameterType IntKi CompSub - - - "Compute sub-structural dynamics (switch) {Module_None; Module_HD}" - +typedef ^ FAST_ParameterType IntKi CompMooring - - - "Compute mooring system (switch) {Module_None; Module_MAP; Module_FEAM; Module_MD; Module_Orca}" - +typedef ^ FAST_ParameterType IntKi CompIce - - - "Compute ice loading (switch) {Module_None; Module_IceF, Module_IceD}" - +typedef ^ FAST_ParameterType LOGICAL UseDWM - - - "Use the DWM module in AeroDyn" - +typedef ^ FAST_ParameterType LOGICAL Linearize - - - "Linearization analysis (flag)" - +# Input file names: +typedef ^ FAST_ParameterType CHARACTER(1024) EDFile - - - "The name of the ElastoDyn input file" - +typedef ^ FAST_ParameterType CHARACTER(1024) BDBldFile {MaxNBlades} - - "Name of files containing BeamDyn inputs for each blade" - +typedef ^ FAST_ParameterType CHARACTER(1024) InflowFile - - - "Name of file containing inflow wind input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) AeroFile - - - "Name of file containing aerodynamic input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) ServoFile - - - "Name of file containing control and electrical-drive input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) HydroFile - - - "Name of file containing hydrodynamic input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) SubFile - - - "Name of file containing sub-structural input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) MooringFile - - - "Name of file containing mooring system input parameters" - +typedef ^ FAST_ParameterType CHARACTER(1024) IceFile - - - "Name of file containing ice loading input parameters" - +# Parameters for file/screen output +#typedef ^ FAST_ParameterType DbKi SttsTime - - - "Amount of time between screen status messages" s +typedef ^ FAST_ParameterType DbKi TStart - - - "Time to begin tabular output" s +typedef ^ FAST_ParameterType DbKi DT_Out - - - "Time step for tabular output" s +typedef ^ FAST_ParameterType LOGICAL WrSttsTime - - - "Whether we should write the status times to the screen" - +typedef ^ FAST_ParameterType INTEGER n_SttsTime - - - "Number of time steps between screen status messages" - +typedef ^ FAST_ParameterType INTEGER n_ChkptTime - - - "Number of time steps between writing checkpoint files" - +typedef ^ FAST_ParameterType INTEGER n_DT_Out - - - "Number of time steps between writing a line in the time-marching output files" - +typedef ^ FAST_ParameterType INTEGER n_VTKTime - - - "Number of time steps between writing VTK files" - +typedef ^ FAST_ParameterType IntKi TurbineType - - - "Type_LandBased, Type_Offshore_Fixed, or Type_Offshore_Floating" - +typedef ^ FAST_ParameterType LOGICAL WrBinOutFile - - - "Write a binary output file? (.outb)" - +typedef ^ FAST_ParameterType LOGICAL WrTxtOutFile - - - "Write a text (formatted) output file? (.out)" - +typedef ^ FAST_ParameterType IntKi WrBinMod - - - "If writing binary, which file format is to be written [1, 2, or 3]" - +typedef ^ FAST_ParameterType LOGICAL SumPrint - - - "Print summary data to file? (.sum)" - +typedef ^ FAST_ParameterType INTEGER WrVTK - 0 - "VTK Visualization data output: (switch) {0=none; 1=initialization data only; 2=animation}" - +typedef ^ FAST_ParameterType INTEGER VTK_Type - - - "Type of VTK visualization data: (switch) {1=surfaces; 2=basic meshes (lines/points); 3=all meshes (debug)}" - +typedef ^ FAST_ParameterType LOGICAL VTK_fields - - - "Write mesh fields to VTK data files? (flag) {true/false}" - +typedef ^ FAST_ParameterType CHARACTER(1) Delim - - - "Delimiter between columns of text output file (.out): space or tab" - +typedef ^ FAST_ParameterType CHARACTER(20) OutFmt - - - "Format used for text tabular output (except time); resulting field should be 10 characters" - +typedef ^ FAST_ParameterType CHARACTER(20) OutFmt_t - - - "Format used for time channel in text tabular output; resulting field should be 10 characters" - +typedef ^ FAST_ParameterType IntKi FmtWidth - - - "width of the time OutFmt specifier" - +typedef ^ FAST_ParameterType IntKi TChanLen - - - "width of the time channel" - +typedef ^ FAST_ParameterType CHARACTER(1024) OutFileRoot - - - "The rootname of the output files" - +typedef ^ FAST_ParameterType CHARACTER(1024) FTitle - - - "The description line from the FAST (glue-code) input file" - +typedef ^ FAST_ParameterType CHARACTER(1024) VTK_OutFileRoot - "''" - "The rootname of the VTK output files" - +typedef ^ FAST_ParameterType INTEGER VTK_tWidth - - - "Width of number of files for leading zeros in file name format" - +typedef ^ FAST_ParameterType DbKi VTK_fps - - - "number of frames per second to output VTK data" - +typedef ^ FAST_ParameterType FAST_VTK_SurfaceType VTK_surface - - - "Data for VTK surface visualization" +typedef ^ FAST_ParameterType SiKi TurbinePos {3} - - "Initial position of turbine base (origin used for graphics)" m +typedef ^ FAST_ParameterType CHARACTER(4) Tdesc - - - "description of turbine ID (for FAST.Farm) screen printing" + +# Parameters for linearization +typedef ^ FAST_ParameterType LOGICAL CalcSteady - - - "Calculate a steady-state periodic operating point before linearization [unused if Linearize=False]" - +typedef ^ FAST_ParameterType IntKi TrimCase - - - "Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [unused if Linearize=False; used only if CalcSteady=True]" - +typedef ^ FAST_ParameterType ReKi TrimTol - - - "Tolerance for the rotational speed convergence (>0) [unused if Linearize=False; used only if CalcSteady=True]" - +typedef ^ FAST_ParameterType ReKi TrimGain - - - "Proportional gain for the rotational speed error (>0) [unused if Linearize=False; used only if CalcSteady=True]" "rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque" +typedef ^ FAST_ParameterType ReKi Twr_Kdmp - - - "Damping factor for the tower [unused if Linearize=False; used only if CalcSteady=True]" "N/(m/s)" +typedef ^ FAST_ParameterType ReKi Bld_Kdmp - - - "Damping factor for the blades [unused if Linearize=False; used only if CalcSteady=True]" "N/(m/s)" +typedef ^ FAST_ParameterType IntKi NLinTimes - - - "Number of LinTimes, or equally-spaced azimuth steps in periodic linearized model (>0)[unused if Linearize=False]" - +typedef ^ FAST_ParameterType DbKi AzimDelta - - - "difference between two consecutive azimuth positions in CalcSteady algorithm" rad + +typedef ^ FAST_ParameterType IntKi LinInputs - - - "Inputs included in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)} [unused if Linearize=False]" - +typedef ^ FAST_ParameterType IntKi LinOutputs - - - "Outputs included in linearization (switch) {0=none; 1=from OutList(s); 2=all module outputs (debug)} [unused if Linearize=False]" - +typedef ^ FAST_ParameterType LOGICAL LinOutJac - - - "Include full Jacabians in linearization output (for debug) (flag) [unused if Linearize=False; used only if LinInputs=LinOutputs=2]" - +typedef ^ FAST_ParameterType LOGICAL LinOutMod - - - "Write module-level linearization output files in addition to output for full system? (flag) [unused if Linearize=False]" - +typedef ^ FAST_ParameterType FAST_VTK_ModeShapeType VTK_modes - - - "Data for VTK mode-shape visualization" + +typedef ^ FAST_ParameterType IntKi Lin_NumMods - - - "number of modules in the linearization" +typedef ^ FAST_ParameterType IntKi Lin_ModOrder {NumModules} - - "indices that determine which order the modules are in the glue-code linearization matrix" +typedef ^ FAST_ParameterType IntKi LinInterpOrder - - - "Interpolation order for CalcSteady solution" - +#typedef ^ FAST_ParameterType LOGICAL CheckHSSBrTrqC - - - "Flag to determine if we should check HSSBrTrqC extrapolation to ElastoDyn" - + + +# SAVED OPERATING POINT DATA FOR VTKLIN (visualization of mode shapes from linearization analysis) +# ..... IceDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave IceD_ContinuousStateType x_IceD {:}{:} - - "Continuous states" +typedef ^ ^ IceD_DiscreteStateType xd_IceD {:}{:} - - "Discrete states" +typedef ^ ^ IceD_ConstraintStateType z_IceD {:}{:} - - "Constraint states" +typedef ^ ^ IceD_OtherStateType OtherSt_IceD {:}{:} - - "Other states" +typedef ^ ^ IceD_InputType u_IceD {:}{:} - - "System inputs" +# ..... BeamDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave BD_ContinuousStateType x_BD {:}{:} - - "Continuous states" +typedef ^ ^ BD_DiscreteStateType xd_BD {:}{:} - - "Discrete states" +typedef ^ ^ BD_ConstraintStateType z_BD {:}{:} - - "Constraint states" +typedef ^ ^ BD_OtherStateType OtherSt_BD {:}{:} - - "Other states" +typedef ^ ^ BD_InputType u_BD {:}{:} - - "System inputs" +# ..... ElastoDyn OP data ..................................................................................................... +typedef FAST FAST_LinStateSave ED_ContinuousStateType x_ED {:} - - "Continuous states" +typedef ^ ^ ED_DiscreteStateType xd_ED {:} - - "Discrete states" +typedef ^ ^ ED_ConstraintStateType z_ED {:} - - "Constraint states" +typedef ^ ^ ED_OtherStateType OtherSt_ED {:} - - "Other states" +typedef ^ ^ ED_InputType u_ED {:} - - "System inputs" +# ..... ServoDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave SrvD_ContinuousStateType x_SrvD {:} - - "Continuous states" +typedef ^ ^ SrvD_DiscreteStateType xd_SrvD {:} - - "Discrete states" +typedef ^ ^ SrvD_ConstraintStateType z_SrvD {:} - - "Constraint states" +typedef ^ ^ SrvD_OtherStateType OtherSt_SrvD {:} - - "Other states" +typedef ^ ^ SrvD_InputType u_SrvD {:} - - "System inputs" +# ..... No AeroDyn14 data ..................................................................................................... +# ..... AeroDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave AD_ContinuousStateType x_AD {:} - - "Continuous states" +typedef ^ ^ AD_DiscreteStateType xd_AD {:} - - "Discrete states" +typedef ^ ^ AD_ConstraintStateType z_AD {:} - - "Constraint states" +typedef ^ ^ AD_OtherStateType OtherSt_AD {:} - - "Other states" +typedef ^ ^ AD_InputType u_AD {:} - - "System inputs" +# ..... InflowWind OP data ....................................................................................................... +typedef FAST FAST_LinStateSave InflowWind_ContinuousStateType x_IfW {:} - - "Continuous states" +typedef ^ ^ InflowWind_DiscreteStateType xd_IfW {:} - - "Discrete states" +typedef ^ ^ InflowWind_ConstraintStateType z_IfW {:} - - "Constraint states" +typedef ^ ^ InflowWind_OtherStateType OtherSt_IfW {:} - - "Other states" +typedef ^ ^ InflowWind_InputType u_IfW {:} - - "System inputs" +# ..... No OpenFOAM integration data ....................................................................................................... +# ..... SubDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave SD_ContinuousStateType x_SD {:} - - "Continuous states" +typedef ^ ^ SD_DiscreteStateType xd_SD {:} - - "Discrete states" +typedef ^ ^ SD_ConstraintStateType z_SD {:} - - "Constraint states" +typedef ^ ^ SD_OtherStateType OtherSt_SD {:} - - "Other states" +typedef ^ ^ SD_InputType u_SD {:} - - "System inputs" +# ..... ExtPtfm OP data ....................................................................................................... +typedef FAST FAST_LinStateSave ExtPtfm_ContinuousStateType x_ExtPtfm {:} - - "Continuous states" +typedef ^ ^ ExtPtfm_DiscreteStateType xd_ExtPtfm {:} - - "Discrete states" +typedef ^ ^ ExtPtfm_ConstraintStateType z_ExtPtfm {:} - - "Constraint states" +typedef ^ ^ ExtPtfm_OtherStateType OtherSt_ExtPtfm {:} - - "Other states" +typedef ^ ^ ExtPtfm_InputType u_ExtPtfm {:} - - "System inputs" +# ..... HydroDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave HydroDyn_ContinuousStateType x_HD {:} - - "Continuous states" +typedef ^ ^ HydroDyn_DiscreteStateType xd_HD {:} - - "Discrete states" +typedef ^ ^ HydroDyn_ConstraintStateType z_HD {:} - - "Constraint states" +typedef ^ ^ HydroDyn_OtherStateType OtherSt_HD {:} - - "Other states" +typedef ^ ^ HydroDyn_InputType u_HD {:} - - "System inputs" +# ..... IceFloe OP data ....................................................................................................... +typedef FAST FAST_LinStateSave IceFloe_ContinuousStateType x_IceF {:} - - "Continuous states" +typedef ^ ^ IceFloe_DiscreteStateType xd_IceF {:} - - "Discrete states" +typedef ^ ^ IceFloe_ConstraintStateType z_IceF {:} - - "Constraint states" +typedef ^ ^ IceFloe_OtherStateType OtherSt_IceF {:} - - "Other states" +typedef ^ ^ IceFloe_InputType u_IceF {:} - - "System inputs" +# ..... MAP OP data ....................................................................................................... +typedef FAST FAST_LinStateSave MAP_ContinuousStateType x_MAP {:} - - "Continuous states" +typedef ^ ^ MAP_DiscreteStateType xd_MAP {:} - - "Discrete states" +typedef ^ ^ MAP_ConstraintStateType z_MAP {:} - - "Constraint states" +#typedef ^ ^ MAP_OtherStateType OtherSt_MAP {:} - - "Other states" +typedef ^ ^ MAP_InputType u_MAP {:} - - "System inputs" +# ..... FEAMooring OP data ....................................................................................................... +typedef FAST FAST_LinStateSave FEAM_ContinuousStateType x_FEAM {:} - - "Continuous states" +typedef ^ ^ FEAM_DiscreteStateType xd_FEAM {:} - - "Discrete states" +typedef ^ ^ FEAM_ConstraintStateType z_FEAM {:} - - "Constraint states" +typedef ^ ^ FEAM_OtherStateType OtherSt_FEAM {:} - - "Other states" +typedef ^ ^ FEAM_InputType u_FEAM {:} - - "System inputs" +# ..... MoorDyn OP data ....................................................................................................... +typedef FAST FAST_LinStateSave MD_ContinuousStateType x_MD {:} - - "Continuous states" +typedef ^ ^ MD_DiscreteStateType xd_MD {:} - - "Discrete states" +typedef ^ ^ MD_ConstraintStateType z_MD {:} - - "Constraint states" +typedef ^ ^ MD_OtherStateType OtherSt_MD {:} - - "Other states" +typedef ^ ^ MD_InputType u_MD {:} - - "System inputs" +# ..... NO OrcaFlex OP data ....................................................................................................... + +# ..... FAST_LinType data ....................................................................................................... +typedef FAST FAST_LinType CHARACTER(LinChanLen) Names_u {:} - - "Names of the linearized inputs" +typedef ^ FAST_LinType CHARACTER(LinChanLen) Names_y {:} - - "Names of the linearized outputs" +typedef ^ FAST_LinType CHARACTER(LinChanLen) Names_x {:} - - "Names of the linearized continuous states" +typedef ^ FAST_LinType CHARACTER(LinChanLen) Names_xd {:} - - "Names of the linearized discrete states" +typedef ^ FAST_LinType CHARACTER(LinChanLen) Names_z {:} - - "Names of the linearized constraint states" +typedef ^ FAST_LinType ReKi op_u {:} - - "input operating point" +typedef ^ FAST_LinType ReKi op_y {:} - - "output operating point" +typedef ^ FAST_LinType ReKi op_x {:} - - "continuous state operating point" +typedef ^ FAST_LinType ReKi op_dx {:} - - "1st time derivative of continuous state operating point" +typedef ^ FAST_LinType ReKi op_xd {:} - - "discrete state operating point" +typedef ^ FAST_LinType ReKi op_z {:} - - "constraint state operating point" +typedef ^ FAST_LinType R8Ki op_x_eig_mag {:} - - "continuous state eigenvector magnitude" +typedef ^ FAST_LinType R8Ki op_x_eig_phase {:} - - "continuous state eigenvector phase" +typedef ^ FAST_LinType Logical Use_u {:} - - "array same size as names_u, which indicates if this input is used in linearization output file" +typedef ^ FAST_LinType Logical Use_y {:} - - "array same size as names_y, which indicates if this output is used in linearization output file" +typedef ^ FAST_LinType R8Ki A {:}{:} - - "A matrix" +typedef ^ FAST_LinType R8Ki B {:}{:} - - "B matrix" +typedef ^ FAST_LinType R8Ki C {:}{:} - - "C matrix" +typedef ^ FAST_LinType R8Ki D {:}{:} - - "D matrix" +typedef ^ FAST_LinType R8Ki StateRotation {:}{:} - - "Matrix that rotates the continuous states" +typedef ^ FAST_LinType R8Ki StateRel_x {:}{:} - - "Matrix that defines the continuous states relative to root motion" +typedef ^ FAST_LinType R8Ki StateRel_xdot {:}{:} - - "Matrix that defines the continuous states relative to root motion" +typedef ^ FAST_LinType Logical IsLoad_u {:} - - "Whether the input is a load (used for scaling for potentially ill-conditioned G matrix)" +typedef ^ FAST_LinType Logical RotFrame_u {:} - - "Whether corresponding input is in rotating frame" +typedef ^ FAST_LinType Logical RotFrame_y {:} - - "Whether corresponding output is in rotating frame" +typedef ^ FAST_LinType Logical RotFrame_x {:} - - "Whether corresponding continuous state is in rotating frame" +typedef ^ FAST_LinType Logical RotFrame_z {:} - - "Whether corresponding constraint state is in rotating frame" +typedef ^ FAST_LinType IntKi DerivOrder_x {:} - - "Derivative order for continuous states" +typedef ^ FAST_LinType IntKi SizeLin {3} - - "sizes of (1) the module's inputs, (2) the module's linearized outputs, and (3) the module's continuous states" - +typedef ^ FAST_LinType IntKi LinStartIndx {3} - - "the starting index in combined matrices of (1) the module's inputs, (2) the module's linearized outputs, and (3) the module's continuous states" - +typedef ^ FAST_LinType IntKi NumOutputs - - - "number of WriteOutputs in each linearized module" - + +# ..... FAST_ModLinType data (for output) ........................................................................................... +typedef ^ FAST_ModLinType FAST_LinType Instance {:} - - "Linearization data for each module instance (e.g., 3 blades for BD)" + +# ..... FAST_LinFileType data ....................................................................................................... +typedef FAST FAST_LinFileType FAST_ModLinType Modules {NumModules} - - "Linearization data for each module" +typedef ^ FAST_LinFileType FAST_LinType Glue - - - "Linearization data for the glue code (coupled system)" +typedef ^ FAST_LinFileType ReKi RotSpeed - - - "Rotor azimuth angular speed" rad/s +typedef ^ FAST_LinFileType ReKi Azimuth - - - "Rotor azimuth position" rad +typedef ^ FAST_LinFileType ReKi WindSpeed - - - "Wind speed at reference height" m/s + + +# ..... FAST_MiscLinType data ....................................................................................................... +typedef ^ FAST_MiscLinType DbKi LinTimes {:} - - "List of times at which to linearize" s +typedef ^ FAST_MiscLinType IntKi CopyOP_CtrlCode - - - "mesh control code for copy type (new on first call; update otherwise)" - +typedef ^ FAST_MiscLinType DbKi AzimTarget {:} - - "target azimuth positions in CalcSteady algorithm" rad +typedef ^ FAST_MiscLinType logical IsConverged - - - "whether the error calculation in the CalcSteady algorithm is converged" - +typedef ^ FAST_MiscLinType logical FoundSteady - - - "whether the CalcSteady algorithm found a steady-state solution" - +typedef ^ FAST_MiscLinType IntKi n_rot - - - "number of rotations completed in CalcSteady algorithm" - +typedef ^ FAST_MiscLinType IntKi AzimIndx - - - "index into target azimuth array in CalcSteady algorithm" - +typedef ^ FAST_MiscLinType IntKi NextLinTimeIndx - - - "index for next time in LinTimes where linearization should occur" - +typedef ^ FAST_MiscLinType DbKi Psi {:} - - "Azimuth angle at the current and previous time steps (uses LinInterpOrder); DbKi so that we can use registry-generated extrap/interp routines" - +typedef ^ FAST_MiscLinType ReKi y_interp {:} - - "Interpolated outputs packed into an array" - +typedef ^ FAST_MiscLinType ReKi y_ref {:} - - "Reference output range for CalcSteady error calculation" - +typedef ^ FAST_MiscLinType ReKi Y_prevRot {:}{:} - - "Linearization outputs from previous rotor revolution at each target azimuth " - + + +# ..... FAST_OutputFileType data ....................................................................................................... +typedef FAST FAST_OutputFileType DbKi TimeData {:} - - "Array to contain the time output data for the binary file (first output time and a time [fixed] increment)" +typedef ^ FAST_OutputFileType ReKi AllOutData {:}{:} - - "Array to contain all the output data (time history of all outputs); Index 1 is NumOuts, Index 2 is Time step" +typedef ^ FAST_OutputFileType IntKi n_Out - - - "Time index into the AllOutData array" +typedef ^ FAST_OutputFileType IntKi NOutSteps - - - "Maximum number of output steps" +typedef ^ FAST_OutputFileType IntKi numOuts {NumModules} - - "number of outputs to print from each module" +typedef ^ FAST_OutputFileType IntKi UnOu - -1 - "I/O unit number for the tabular output file" +typedef ^ FAST_OutputFileType IntKi UnSum - -1 - "I/O unit number for the summary file" +typedef ^ FAST_OutputFileType IntKi UnGra - -1 - "I/O unit number for mesh graphics" +typedef ^ FAST_OutputFileType CHARACTER(1024) FileDescLines {3} - - "Description lines to include in output files (header, time run, plus module names/versions)" +typedef ^ FAST_OutputFileType CHARACTER(ChanLen) ChannelNames {:} - - "Names of the output channels" +typedef ^ FAST_OutputFileType CHARACTER(ChanLen) ChannelUnits {:} - - "Units for the output channels" +typedef ^ FAST_OutputFileType ProgDesc Module_Ver {NumModules} - - "version information from all modules" +typedef ^ FAST_OutputFileType CHARACTER(ChanLen) Module_Abrev {NumModules} - - "abbreviation for module (used in file output naming conventions)" +typedef ^ FAST_OutputFileType LOGICAL WriteThisStep - - - "Whether this step will be written in the FAST output files" +typedef ^ FAST_OutputFileType IntKi VTK_count - - - "Number of VTK files written (for naming output files)" +typedef ^ FAST_OutputFileType IntKi VTK_LastWaveIndx - - - "last index into wave array" - +typedef ^ FAST_OutputFileType FAST_LinFileType Lin - - - "linearization data for output" +typedef ^ FAST_OutputFileType IntKi ActualChanLen - - - "width of the column headers output in the text and/or binary file" - +typedef ^ FAST_OutputFileType CHARACTER(30) OutFmt_a - - - "Format used for text tabular output (except time); combines OutFmt with delim and appropriate spaces" - +typedef ^ FAST_OutputFileType FAST_LinStateSave op - - - "operating points of states and inputs for VTK output of mode shapes" + + +# ..... IceDyn data ....................................................................................................... +# [ the last dimension of each allocatable array is for the instance of IceDyn being used ] +# note that I'm making the allocatable-for-instance-used part INSIDE the data type (as opposed to an array of IceDyn_Data types) because I want to pass arrays of x, xd, z, x_pred, etc) +typedef FAST IceDyn_Data IceD_ContinuousStateType x {:}{:} - - "Continuous states" +typedef ^ ^ IceD_DiscreteStateType xd {:}{:} - - "Discrete states" +typedef ^ ^ IceD_ConstraintStateType z {:}{:} - - "Constraint states" +typedef ^ ^ IceD_OtherStateType OtherSt {:}{:} - - "Other states" +typedef ^ ^ IceD_ParameterType p {:} - - "Parameters" +typedef ^ ^ IceD_InputType u {:} - - "System inputs" +typedef ^ ^ IceD_OutputType y {:} - - "System outputs" +typedef ^ ^ IceD_MiscVarType m {:} - - "Misc/optimization variables" +typedef ^ ^ IceD_InputType Input {:}{:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:}{:} - - "Array of times associated with Input Array" + +# ..... BeamDyn data ....................................................................................................... +# [ the last dimension of each allocatable array is for the instance of BeamDyn being used ] +# note that I'm making the allocatable-for-instance-used part INSIDE the data type (as opposed to an array of IceDyn_Data types) because I want to pass arrays of x, xd, z, x_pred, etc) +typedef FAST BeamDyn_Data BD_ContinuousStateType x {:}{:} - - "Continuous states" +typedef ^ ^ BD_DiscreteStateType xd {:}{:} - - "Discrete states" +typedef ^ ^ BD_ConstraintStateType z {:}{:} - - "Constraint states" +typedef ^ ^ BD_OtherStateType OtherSt {:}{:} - - "Other states" +typedef ^ ^ BD_ParameterType p {:} - - "Parameters" +typedef ^ ^ BD_InputType u {:} - - "System inputs" +typedef ^ ^ BD_OutputType y {:} - - "System outputs" +typedef ^ ^ BD_MiscVarType m {:} - - "Misc/optimization variables" +typedef ^ ^ BD_OutputType Output {:}{:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ BD_OutputType y_interp {:} - - "interpolated system outputs for CalcSteady" +typedef ^ ^ BD_InputType Input {:}{:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:}{:} - - "Array of times associated with Input Array" + +# ..... ElastoDyn data ....................................................................................................... +typedef FAST ElastoDyn_Data ED_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ ED_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ ED_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ ED_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ ED_ParameterType p - - - "Parameters" +typedef ^ ^ ED_InputType u - - - "System inputs" +typedef ^ ^ ED_OutputType y - - - "System outputs" +typedef ^ ^ ED_MiscVarType m - - - "Misc (optimization) variables not associated with time" +typedef ^ ^ ED_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ ED_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ ED_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + + +# ..... ServoDyn data ....................................................................................................... +typedef FAST ServoDyn_Data SrvD_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ SrvD_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ SrvD_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ SrvD_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ SrvD_ParameterType p - - - "Parameters" +typedef ^ ^ SrvD_InputType u - - - "System inputs" +typedef ^ ^ SrvD_OutputType y - - - "System outputs" +typedef ^ ^ SrvD_MiscVarType m - - - "Misc (optimization) variables not associated with time" +typedef ^ ^ SrvD_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ SrvD_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ SrvD_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... AeroDyn14 data ....................................................................................................... +typedef FAST AeroDyn14_Data AD14_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ AD14_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ AD14_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ AD14_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ AD14_ParameterType p - - - "Parameters" +typedef ^ ^ AD14_InputType u - - - "System inputs" +typedef ^ ^ AD14_OutputType y - - - "System outputs" +typedef ^ ^ AD14_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ AD14_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... AeroDyn data ....................................................................................................... +typedef FAST AeroDyn_Data AD_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ AD_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ AD_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ AD_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ AD_ParameterType p - - - "Parameters" +typedef ^ ^ AD_InputType u - - - "System inputs" +typedef ^ ^ AD_OutputType y - - - "System outputs" +typedef ^ ^ AD_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ AD_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ AD_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ AD_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... InflowWind data ....................................................................................................... +typedef FAST InflowWind_Data InflowWind_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ InflowWind_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ InflowWind_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ InflowWind_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ InflowWind_ParameterType p - - - "Parameters" +typedef ^ ^ InflowWind_InputType u - - - "System inputs" +typedef ^ ^ InflowWind_OutputType y - - - "System outputs" +typedef ^ ^ InflowWind_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ InflowWind_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ InflowWind_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ InflowWind_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... OpenFOAM integration data ....................................................................................................... +typedef FAST OpenFOAM_Data OpFM_InputType u - - - "System inputs" +typedef ^ ^ OpFM_OutputType y - - - "System outputs" +typedef ^ ^ OpFM_ParameterType p - - - "Parameters" +typedef ^ ^ OpFM_MiscVarType m - - - "Parameters" + +# ..... SuperController integration data ....................................................................................................... +typedef FAST SuperController_Data SC_InputType u - - - "System inputs" +typedef ^ ^ SC_OutputType y - - - "System outputs" +typedef ^ ^ SC_ParameterType p - - - "System parameters" + +# ..... SubDyn data ....................................................................................................... +typedef FAST SubDyn_Data SD_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ SD_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ SD_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ SD_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ SD_ParameterType p - - - "Parameters" +typedef ^ ^ SD_InputType u - - - "System inputs" +typedef ^ ^ SD_OutputType y - - - "System outputs" +typedef ^ ^ SD_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ SD_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... ExtPtfm data ....................................................................................................... +typedef FAST ExtPtfm_Data ExtPtfm_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ ExtPtfm_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ ExtPtfm_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ ExtPtfm_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ ExtPtfm_ParameterType p - - - "Parameters" +typedef ^ ^ ExtPtfm_InputType u - - - "System inputs" +typedef ^ ^ ExtPtfm_OutputType y - - - "System outputs" +typedef ^ ^ ExtPtfm_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ ExtPtfm_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... HydroDyn data ....................................................................................................... +typedef FAST HydroDyn_Data HydroDyn_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ HydroDyn_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ HydroDyn_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ HydroDyn_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ HydroDyn_ParameterType p - - - "Parameters" +typedef ^ ^ HydroDyn_InputType u - - - "System inputs" +typedef ^ ^ HydroDyn_OutputType y - - - "System outputs" +typedef ^ ^ HydroDyn_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ HydroDyn_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ HydroDyn_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ HydroDyn_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... IceFloe data ....................................................................................................... +typedef FAST IceFloe_Data IceFloe_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ IceFloe_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ IceFloe_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ IceFloe_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ IceFloe_ParameterType p - - - "Parameters" +typedef ^ ^ IceFloe_InputType u - - - "System inputs" +typedef ^ ^ IceFloe_OutputType y - - - "System outputs" +typedef ^ ^ IceFloe_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ IceFloe_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... MAP data ....................................................................................................... +typedef FAST MAP_Data MAP_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ MAP_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ MAP_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ MAP_OtherStateType OtherSt - - - "Other/optimization states" +typedef ^ ^ MAP_ParameterType p - - - "Parameters" +typedef ^ ^ MAP_InputType u - - - "System inputs" +typedef ^ ^ MAP_OutputType y - - - "System outputs" +typedef ^ ^ MAP_OtherStateType OtherSt_old - - - "Other/optimization states (copied for the case of subcycling)" +typedef ^ ^ MAP_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ MAP_OutputType y_interp - - - "interpolated system outputs for CalcSteady" +typedef ^ ^ MAP_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... FEAMooring data ....................................................................................................... +typedef FAST FEAMooring_Data FEAM_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ FEAM_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ FEAM_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ FEAM_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ FEAM_ParameterType p - - - "Parameters" +typedef ^ ^ FEAM_InputType u - - - "System inputs" +typedef ^ ^ FEAM_OutputType y - - - "System outputs" +typedef ^ ^ FEAM_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ FEAM_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... MoorDyn data ....................................................................................................... +typedef FAST MoorDyn_Data MD_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ MD_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ MD_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ MD_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ MD_ParameterType p - - - "Parameters" +typedef ^ ^ MD_InputType u - - - "System inputs" +typedef ^ ^ MD_OutputType y - - - "System outputs" +typedef ^ ^ MD_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ MD_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... OrcaFlex data ....................................................................................................... +typedef FAST OrcaFlex_Data Orca_ContinuousStateType x {2} - - "Continuous states" +typedef ^ ^ Orca_DiscreteStateType xd {2} - - "Discrete states" +typedef ^ ^ Orca_ConstraintStateType z {2} - - "Constraint states" +typedef ^ ^ Orca_OtherStateType OtherSt {2} - - "Other states" +typedef ^ ^ Orca_ParameterType p - - - "Parameters" +typedef ^ ^ Orca_InputType u - - - "System inputs" +typedef ^ ^ Orca_OutputType y - - - "System outputs" +typedef ^ ^ Orca_MiscVarType m - - - "Misc/optimization variables" +typedef ^ ^ Orca_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" + +# ..... FAST_ModuleMapType data ....................................................................................................... +# ! Data structures for mapping and coupling the various modules together +# ED <-> BD +typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P {:} - - "Map ElastoDyn BladeRootMotion meshes to BeamDyn RootMotion point meshes" +typedef FAST FAST_ModuleMapType MeshMapType BD_P_2_ED_P {:} - - "Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh" +typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P_Hub {:} - - "ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator" +# ED <-> HD +typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_W_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point" +typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point (from either y%Mesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point" +typedef ^ FAST_ModuleMapType MeshMapType HD_M_P_2_ED_P - - - "Map HydroDyn Morison Point to ElastoDyn PlatformPtMesh" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_L - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Line2" +typedef ^ FAST_ModuleMapType MeshMapType HD_M_L_2_ED_P - - - "Map HydroDyn Morison Line2 to ElastoDyn PlatformPtMesh" +# ED <-> Mooring (MAP, FEAM, MoorDyn, OrcaFlex) +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_Mooring_P - - - "Map ElastoDyn PlatformPtMesh to MAP/FEAM/MoorDyn/OrcaFlex point mesh" +typedef ^ FAST_ModuleMapType MeshMapType Mooring_P_2_ED_P - - - "Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to ElastoDyn PlatformPtMesh" +# ED <-> SD or User-Platform (ExtPtfm_MCKF) +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_SD_TP - - - "Map ElastoDyn PlatformPtMesh to SubDyn transition-piece point mesh" +typedef ^ FAST_ModuleMapType MeshMapType SD_TP_2_ED_P - - - "Map SubDyn transition-piece point mesh to ElastoDyn PlatformPtMesh" +# SD <-> HD +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_HD_M_P - - - "Map SubDyn y2Mesh Point to HydroDyn Morison Point" +typedef ^ FAST_ModuleMapType MeshMapType HD_M_P_2_SD_P - - - "Map HydroDyn Morison Point to SubDyn y2Mesh Point" +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_HD_M_L - - - "Map SubDyn y2Mesh Point to HydroDyn Morison Line2" +typedef ^ FAST_ModuleMapType MeshMapType HD_M_L_2_SD_P - - - "Map HydroDyn Morison Line2 to SubDyn y2Mesh Point" +# ED <-> SrvD/TMD +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_SrvD_P_N - - - "Map ElastoDyn Nacelle point mesh to ServoDyn/TMD point mesh" +typedef ^ FAST_ModuleMapType MeshMapType SrvD_P_2_ED_P_N - - - "Map ServoDyn nacelle point mesh to ElastoDyn point mesh on the nacelle" +typedef ^ FAST_ModuleMapType MeshMapType ED_L_2_SrvD_P_T - - - "Map ElastoDyn tower line2 mesh to ServoDyn/TTMD point mesh" +typedef ^ FAST_ModuleMapType MeshMapType SrvD_P_2_ED_P_T - - - "Map ServoDyn tower point mesh to ElastoDyn point load mesh on the tower" +# ED/BD <-> AD (blades) +typedef ^ FAST_ModuleMapType MeshMapType BDED_L_2_AD_L_B {:} - - "Map ElastoDyn BladeLn2Mesh point meshes OR BeamDyn BldMotion line2 meshes to AeroDyn14 InputMarkers OR AeroDyn BladeMotion line2 meshes" +typedef ^ FAST_ModuleMapType MeshMapType AD_L_2_BDED_B {:} - - "Map AeroDyn14 InputMarkers or AeroDyn BladeLoad line2 meshes to ElastoDyn BladePtLoad point meshes or BeamDyn BldMotion line2 meshes" +typedef ^ FAST_ModuleMapType MeshMapType BD_L_2_BD_L {:} - - "Map BeamDyn BldMotion output meshes to locations on the BD input DistrLoad mesh stored in MeshMapType%y_BD_BldMotion_4Loads (BD input and output meshes are not siblings and in fact have nodes at different locations" +# ED <-> AD (tower, hub, blade root) +typedef ^ FAST_ModuleMapType MeshMapType ED_L_2_AD_L_T - - - "Map ElastoDyn TowerLn2Mesh line2 mesh to AeroDyn14 Twr_InputMarkers or AeroDyn TowerMotion line2 mesh" +typedef ^ FAST_ModuleMapType MeshMapType AD_L_2_ED_P_T - - - "Map AeroDyn14 Twr_InputMarkers or AeroDyn TowerLoad line2 mesh to ElastoDyn TowerPtLoads point mesh" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_AD_P_R {:} - - "Map ElastoDyn BladeRootMotion point meshes to AeroDyn BladeRootMotion point meshes" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_AD_P_H - - - "Map ElastoDyn HubPtMotion point mesh to AeroDyn HubMotion point mesh" +# IceF <-> SD +typedef ^ FAST_ModuleMapType MeshMapType IceF_P_2_SD_P - - - "Map IceFloe point mesh to SubDyn y2Mesh point mesh" +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_IceF_P - - - "Map SubDyn y2Mesh point mesh to IceFloe point mesh" +# IceD <-> SD +typedef ^ FAST_ModuleMapType MeshMapType IceD_P_2_SD_P {:} - - "Map IceDyn point mesh to SubDyn y2Mesh point mesh" +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_IceD_P {:} - - "Map SubDyn y2Mesh point mesh to IceDyn point mesh" +# Stored Jacobians: +typedef ^ FAST_ModuleMapType ReKi Jacobian_Opt1 {:}{:} - - "Stored Jacobian in ED_HD_InputOutputSolve or FullOpt1_InputOutputSolve" +typedef ^ FAST_ModuleMapType Integer Jacobian_pivot {:} - - "Pivot array used for LU decomposition of Jacobian_Opt1" +typedef ^ FAST_ModuleMapType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" +# Temporary copies of input meshes (stored here so we don't have to keep allocating/destroying them) +typedef ^ FAST_ModuleMapType MeshType u_ED_PlatformPtMesh - - - "copy of ED input mesh" +typedef ^ FAST_ModuleMapType MeshType u_ED_PlatformPtMesh_2 - - - "copy of ED input mesh (used only for temporary storage)" +typedef ^ FAST_ModuleMapType MeshType u_SD_TPMesh - - - "copy of SD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_SD_LMesh - - - "copy of SD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_SD_LMesh_2 - - - "copy of SD input mesh (used only for temporary storage)" +typedef ^ FAST_ModuleMapType MeshType u_HD_M_LumpedMesh - - - "copy of HD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_HD_M_DistribMesh - - - "copy of HD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_HD_Mesh - - - "copy of HD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_ED_HubPtLoad - - - "copy of ED input mesh" +typedef ^ FAST_ModuleMapType MeshType u_ED_HubPtLoad_2 - - - "copy of ED input mesh" +typedef ^ FAST_ModuleMapType MeshType u_BD_RootMotion {:} - - "copy of BD input meshes" +typedef ^ FAST_ModuleMapType MeshType y_BD_BldMotion_4Loads {:} - - "BD blade motion output at locations on DistrLoad input meshes" +typedef ^ FAST_ModuleMapType MeshType u_Orca_PtfmMesh - - - "copy of Orca PtfmMesh input mesh" +typedef ^ FAST_ModuleMapType MeshType u_ExtPtfm_PtfmMesh - - - "copy of ExtPtfm_MCKF PtfmMesh input mesh" +# ..... FAST_ExternalInput data ....................................................................................................... +typedef FAST FAST_ExternInputType ReKi GenTrq - - - "generator torque input from Simulink/Labview" +typedef ^ FAST_ExternInputType ReKi ElecPwr - - - "electric power input from Simulink/Labview" +typedef ^ FAST_ExternInputType ReKi YawPosCom - - 2pi "yaw position command from Simulink/Labview" +typedef ^ FAST_ExternInputType ReKi YawRateCom - - - "yaw rate command from Simulink/Labview" +typedef ^ FAST_ExternInputType ReKi BlPitchCom 3 - 2pi "blade pitch commands from Simulink/Labview" "rad" +typedef ^ FAST_ExternInputType ReKi HSSBrFrac - - - "Fraction of full braking torque: 0 (off) <= HSSBrFrac <= 1 (full) from Simulink or LabVIEW" +typedef ^ FAST_ExternInputType ReKi LidarFocus 3 - - "lidar focus (relative to lidar location)" m + + +# ..... FAST_InitData data ....................................................................................................... +typedef ^ FAST_InitData ED_InitInputType InData_ED - - - "ED Initialization input data" +typedef ^ FAST_InitData ED_InitOutputType OutData_ED - - - "ED Initialization output data" +typedef ^ FAST_InitData BD_InitInputType InData_BD - - - "BD Initialization input data" +typedef ^ FAST_InitData BD_InitOutputType OutData_BD : - - "BD Initialization output data" +typedef ^ FAST_InitData SrvD_InitInputType InData_SrvD - - - "SrvD Initialization input data" +typedef ^ FAST_InitData SrvD_InitOutputType OutData_SrvD - - - "SrvD Initialization output data" +typedef ^ FAST_InitData AD14_InitInputType InData_AD14 - - - "AD14 Initialization input data" +typedef ^ FAST_InitData AD14_InitOutputType OutData_AD14 - - - "AD14 Initialization output data" +typedef ^ FAST_InitData AD_InitInputType InData_AD - - - "AD Initialization input data" +typedef ^ FAST_InitData AD_InitOutputType OutData_AD - - - "AD Initialization output data" +typedef ^ FAST_InitData InflowWind_InitInputType InData_IfW - - - "IfW Initialization input data" +typedef ^ FAST_InitData InflowWind_InitOutputType OutData_IfW - - - "IfW Initialization output data" +typedef ^ FAST_InitData OpFM_InitInputType InData_OpFM - - - "OpFM Initialization input data" +typedef ^ FAST_InitData OpFM_InitOutputType OutData_OpFM - - - "OpFM Initialization output data" +typedef ^ FAST_InitData HydroDyn_InitInputType InData_HD - - - "HD Initialization input data" +typedef ^ FAST_InitData HydroDyn_InitOutputType OutData_HD - - - "HD Initialization output data" +typedef ^ FAST_InitData SD_InitInputType InData_SD - - - "SD Initialization input data" +typedef ^ FAST_InitData SD_InitOutputType OutData_SD - - - "SD Initialization output data" +typedef ^ FAST_InitData ExtPtfm_InitInputType InData_ExtPtfm - - - "ExtPtfm Initialization input data" +typedef ^ FAST_InitData ExtPtfm_InitOutputType OutData_ExtPtfm - - - "ExtPtfm Initialization output data" +typedef ^ FAST_InitData MAP_InitInputType InData_MAP - - - "MAP Initialization input data" +typedef ^ FAST_InitData MAP_InitOutputType OutData_MAP - - - "MAP Initialization output data" +typedef ^ FAST_InitData FEAM_InitInputType InData_FEAM - - - "FEAM Initialization input data" +typedef ^ FAST_InitData FEAM_InitOutputType OutData_FEAM - - - "FEAM Initialization output data" +typedef ^ FAST_InitData MD_InitInputType InData_MD - - - "MD Initialization input data" +typedef ^ FAST_InitData MD_InitOutputType OutData_MD - - - "MD Initialization output data" +typedef ^ FAST_InitData Orca_InitInputType InData_Orca - - - "Orca Initialization input data" +typedef ^ FAST_InitData Orca_InitOutputType OutData_Orca - - - "Orca Initialization output data" +typedef ^ FAST_InitData IceFloe_InitInputType InData_IceF - - - "IceF Initialization input data" +typedef ^ FAST_InitData IceFloe_InitOutputType OutData_IceF - - - "IceF Initialization output data" +typedef ^ FAST_InitData IceD_InitInputType InData_IceD - - - "IceD Initialization input data" +typedef ^ FAST_InitData IceD_InitOutputType OutData_IceD - - - "IceD Initialization output data (each instance will have the same output channels)" +typedef ^ FAST_InitData SC_InitInputType InData_SC - - - "SC Initialization input data" +typedef ^ FAST_InitData SC_InitOutputType OutData_SC - - - "SC Initialization output data" + + +# ..... FAST_MiscVarType data ....................................................................................................... +typedef FAST FAST_MiscVarType DbKi TiLstPrn - - - "The simulation time of the last print (to file)" (s) +typedef ^ FAST_MiscVarType DbKi t_global - - - "Current simulation time (for global/FAST simulation)" (s) +typedef ^ FAST_MiscVarType DbKi NextJacCalcTime - - - "Time between calculating Jacobians in the HD-ED and SD-ED simulations" (s) +typedef ^ FAST_MiscVarType ReKi PrevClockTime - - - "Clock time at start of simulation in seconds" (s) +typedef ^ FAST_MiscVarType ReKi UsrTime1 - - - "User CPU time for simulation initialization" (s) +typedef ^ FAST_MiscVarType ReKi UsrTime2 - - - "User CPU time for simulation (without intialization)" (s) +typedef ^ FAST_MiscVarType INTEGER StrtTime {8} - - "Start time of simulation (including intialization)" +typedef ^ FAST_MiscVarType INTEGER SimStrtTime {8} - - "Start time of simulation (after initialization)" +#typedef ^ FAST_MiscVarType IntKi n_t_global - - - "simulation time step, loop counter for global (FAST) simulation" (s) +typedef ^ FAST_MiscVarType Logical calcJacobian - - - "Should we calculate Jacobians in Option 1?" (flag) +typedef ^ FAST_MiscVarType FAST_ExternInputType ExternInput - - - "external input values" - +typedef ^ FAST_MiscVarType FAST_MiscLinType Lin - - - "misc data for linearization analysis" - + +# ..... FAST External Initialization Input data ....................................................................................................... +typedef ^ FAST_ExternInitType DbKi Tmax - -1 - "External code specified Tmax" s +typedef ^ FAST_ExternInitType IntKi SensorType - SensorType_None - "lidar sensor type, which should not be pulsed at the moment; this input should be replaced with a section in the InflowWind input file" - +typedef ^ FAST_ExternInitType LOGICAL LidRadialVel - - - "TRUE => return radial component, FALSE => return 'x' direction estimate" - +typedef ^ FAST_ExternInitType IntKi TurbineID - 0 - "ID number for turbine (used to create output file naming convention)" - +typedef ^ FAST_ExternInitType ReKi TurbinePos {3} - - "Initial position of turbine base (origin used in future for graphics)" m +typedef ^ FAST_ExternInitType IntKi NumSC2Ctrl - - - "number of controller inputs [from supercontroller]" - +typedef ^ FAST_ExternInitType IntKi NumCtrl2SC - - - "number of controller outputs [to supercontroller]" - +typedef ^ FAST_ExternInitType logical FarmIntegration - .false. - "whether this is called from FAST.Farm (or another program that doesn't want FAST to call all of the init stuff first)" - +typedef ^ FAST_ExternInitType IntKi windGrid_n 4 - - "number of grid points in the x, y, z, and t directions for IfW" - +typedef ^ FAST_ExternInitType ReKi windGrid_delta 4 - - "size between 2 consecutive grid points in each grid direction for IfW" "m,m,m,s" +typedef ^ FAST_ExternInitType ReKi windGrid_pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of IfW m%V(:,1,1,1,:))" m +typedef ^ FAST_ExternInitType CHARACTER(1024) RootName - - - "Root name of FAST output files (overrides normal operation)" - +typedef ^ FAST_ExternInitType IntKi NumActForcePtsBlade - - - "number of actuator line force points in blade" - +typedef ^ FAST_ExternInitType IntKi NumActForcePtsTower - - - "number of actuator line force points in tower" - + + +# ..... FAST Turbine Data (one realization) ....................................................................................................... +typedef ^ FAST_TurbineType IntKi TurbID - 1 - "Turbine ID Number" - +typedef ^ FAST_TurbineType FAST_ParameterType p_FAST - - - "Parameters for the glue code" - +typedef ^ FAST_TurbineType FAST_OutputFileType y_FAST - - - "Output variables for the glue code" - +typedef ^ FAST_TurbineType FAST_MiscVarType m_FAST - - - "Miscellaneous variables" - +typedef ^ FAST_TurbineType FAST_ModuleMapType MeshMapData - - - "Data for mapping between modules" - +typedef ^ FAST_TurbineType ElastoDyn_Data ED - - - "Data for the ElastoDyn module" - +typedef ^ FAST_TurbineType BeamDyn_Data BD - - - "Data for the BeamDyn module" - +typedef ^ FAST_TurbineType ServoDyn_Data SrvD - - - "Data for the ServoDyn module" - +typedef ^ FAST_TurbineType AeroDyn_Data AD - - - "Data for the AeroDyn module" - +typedef ^ FAST_TurbineType AeroDyn14_Data AD14 - - - "Data for the AeroDyn14 module" - +typedef ^ FAST_TurbineType InflowWind_Data IfW - - - "Data for InflowWind module" - +typedef ^ FAST_TurbineType OpenFOAM_Data OpFM - - - "Data for OpenFOAM integration module" - +typedef ^ FAST_TurbineType SuperController_Data SC - - - "Data for SuperController integration module" - +typedef ^ FAST_TurbineType HydroDyn_Data HD - - - "Data for the HydroDyn module" - +typedef ^ FAST_TurbineType SubDyn_Data SD - - - "Data for the SubDyn module" - +typedef ^ FAST_TurbineType MAP_Data MAP - - - "Data for the MAP (Mooring Analysis Program) module" - +typedef ^ FAST_TurbineType FEAMooring_Data FEAM - - - "Data for the FEAMooring module" - +typedef ^ FAST_TurbineType MoorDyn_Data MD - - - "Data for the MoorDyn module" - +typedef ^ FAST_TurbineType OrcaFlex_Data Orca - - - "Data for the OrcaFlex interface module" - +typedef ^ FAST_TurbineType IceFloe_Data IceF - - - "Data for the IceFloe module" - +typedef ^ FAST_TurbineType IceDyn_Data IceD - - - "Data for the IceDyn module" - +typedef ^ FAST_TurbineType ExtPtfm_Data ExtPtfm - - - "Data for the ExtPtfm (external platform loading) module" - +#typedef ^ FAST_TurbineType FAST_InitData Init - - - "Data for all modules at initialization" - diff --git a/OpenFAST/modules/openfast-library/src/FAST_Solver.f90 b/OpenFAST/modules/openfast-library/src/FAST_Solver.f90 new file mode 100644 index 000000000..c6ab8755f --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Solver.f90 @@ -0,0 +1,5883 @@ +!********************************************************************************************************************************** +! FAST_Solver.f90, FAST_Subs.f90, FAST_Lin.f90, and FAST_Mods.f90 make up the FAST glue code in the FAST Modularization Framework. +! FAST_Prog.f90, FAST_Library.f90, FAST_Prog.c are different drivers for this code. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST. +! +! 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. +!********************************************************************************************************************************** +!> This module contains the routines used by FAST to solve input-output equations and to advance states. +MODULE FAST_Solver + + USE NWTC_Library + USE NWTC_LAPACK + + USE FAST_ModTypes + + USE AeroDyn + USE AeroDyn14 + USE InflowWind + USE ElastoDyn + USE BeamDyn + USE FEAMooring + USE MoorDyn + USE MAP + USE OrcaFlexInterface + USE HydroDyn + USE IceDyn + USE IceFloe + USE ServoDyn + USE SubDyn + USE OpenFOAM + USE SuperController + Use ExtPtfm_MCKF + + + IMPLICIT NONE + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for BD--using the Option 2 solve method; currently the only inputs solved in this routine +!! are the blade distributed loads from AD15; other inputs are solved in option 1. +SUBROUTINE BD_InputSolve( p_FAST, BD, y_AD, u_AD, y_ED, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD Inputs at t + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD inputs (for AD-BD load transfer) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + REAL(R8Ki) :: omega_c(3) ! variable for adding damping + REAL(R8Ki) :: r(3) ! variable for adding damping + REAL(R8Ki) :: r_hub(3) ! variable for adding damping + REAL(R8Ki) :: Vrot(3) ! variable for adding damping + + INTEGER(IntKi) :: J ! Loops through blade nodes + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'BD_InputSolve' + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + + ! BD inputs on blade from AeroDyn + IF (p_FAST%CompElast == Module_BD) THEN + + IF ( p_FAST%CompAero == Module_AD ) THEN + + if (p_FAST%BD_OutputSibling) then + + DO K = 1,p_FAST%nBeams ! Loop through all blades + + CALL Transfer_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), BD%y(k)%BldMotion ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + END DO + + else + DO K = 1,p_FAST%nBeams ! Loop through all blades + + ! need to transfer the BD output blade motions to nodes on a sibling of the BD blade motion mesh: + CALL Transfer_Line2_to_Line2( BD%y(k)%BldMotion, MeshMapData%y_BD_BldMotion_4Loads(k), MeshMapData%BD_L_2_BD_L(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL Transfer_Line2_to_Line2( y_AD%BladeLoad(k), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), MeshMapData%y_BD_BldMotion_4Loads(k) ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + END DO + end if + + + ELSE + + DO K = 1,p_FAST%nBeams ! Loop through all blades + BD%Input(1,k)%DistrLoad%Force = 0.0_ReKi + BD%Input(1,k)%DistrLoad%Moment = 0.0_ReKi + END DO + + END IF + + END IF + + ! add damping in blades for linearization convergence + if (p_FAST%CalcSteady) then + + ! note that this assumes sibling meshes for input and output + + omega_c = y_ED%RotSpeed * y_ED%HubPtMotion%Orientation(1,:,1) + r_hub = y_ED%HubPtMotion%Position(:,1) + y_ED%HubPtMotion%TranslationDisp(:,1) + + if (p_FAST%BD_OutputSibling) then + + do k = 1,p_FAST%nBeams ! Loop through all blades + do j = 1,BD%Input(1,k)%DistrLoad%NNodes + r = BD%y(k)%BldMotion%Position(:,j) + BD%y(k)%BldMotion%TranslationDisp(:,j) - r_hub + Vrot = cross_product(omega_c, r) + BD%Input(1,k)%DistrLoad%Force(:,j) = BD%Input(1,k)%DistrLoad%Force(:,j) - p_FAST%Bld_Kdmp * ( BD%y(k)%BldMotion%TranslationVel(:,j) - Vrot ) + end do + end do + + else + + do k = 1,p_FAST%nBeams ! Loop through all blades + do j = 1,BD%Input(1,k)%DistrLoad%NNodes + r = MeshMapData%y_BD_BldMotion_4Loads(k)%Position(:,j) + MeshMapData%y_BD_BldMotion_4Loads(k)%TranslationDisp(:,j) - r_hub + Vrot = cross_product(omega_c, r) + BD%Input(1,k)%DistrLoad%Force(:,j) = BD%Input(1,k)%DistrLoad%Force(:,j) - p_FAST%Bld_Kdmp * ( MeshMapData%y_BD_BldMotion_4Loads(k)%TranslationVel(:,j) - Vrot ) + end do + end do + + end if + + end if + +END SUBROUTINE BD_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for ED--using the Option 2 solve method; currently the only input not solved in this routine +!! are the fields on PlatformPtMesh and HubPtLoad, which are solved in option 1. +SUBROUTINE ED_InputSolve( p_FAST, u_ED, y_ED, p_AD14, y_AD14, y_AD, y_SrvD, u_AD, u_SrvD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(ED_InputType), INTENT(INOUT) :: u_ED !< ED Inputs at t + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(AD14_ParameterType), INTENT(IN ) :: p_AD14 !< AeroDyn14 parameters (a hack because the AD14 meshes aren't set up properly) + TYPE(AD14_OutputType), INTENT(IN ) :: y_AD14 !< AeroDyn14 outputs + TYPE(AD_OutputType), INTENT(IN ) :: y_AD !< AeroDyn outputs + TYPE(AD_InputType), INTENT(IN ) :: u_AD !< AD inputs (for AD-ED load transfer) + TYPE(SrvD_OutputType), INTENT(IN ) :: y_SrvD !< ServoDyn outputs + TYPE(SrvD_InputType), INTENT(IN ) :: u_SrvD !< ServoDyn inputs + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + REAL(R8Ki) :: omega_c(3) ! variable for adding damping + REAL(R8Ki) :: r(3) ! variable for adding damping + REAL(R8Ki) :: r_hub(3) ! variable for adding damping + REAL(R8Ki) :: Vrot(3) ! variable for adding damping + + INTEGER(IntKi) :: J ! Loops through nodes / elements + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'ED_InputSolve' +!bjj: make these misc vars to avoid reallocation each step! + real(reKi) :: Force(3,u_ED%TowerPtLoads%Nnodes) + real(reKi) :: Moment(3,u_ED%TowerPtLoads%Nnodes) + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + Force = 0.0_ReKi + Moment = 0.0_ReKi + + ! ED inputs from ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + u_ED%GenTrq = y_SrvD%GenTrq + u_ED%HSSBrTrqC = y_SrvD%HSSBrTrqC + u_ED%BlPitchCom = y_SrvD%BlPitchCom + u_ED%YawMom = y_SrvD%YawMom + ! u_ED%TBDrCon = y_SrvD%TBDrCon !array + + IF (y_SrvD%NTMD%Mesh%Committed) THEN + + CALL Transfer_Point_to_Point( y_SrvD%NTMD%Mesh, u_ED%NacelleLoads, MeshMapData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2, u_SrvD%NTMD%Mesh, y_ED%NacelleMotion ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ED%NacelleLoads' ) + + END IF + + IF (y_SrvD%TTMD%Mesh%Committed) THEN + + CALL Transfer_Point_to_Point( y_SrvD%TTMD%Mesh, u_ED%TowerPtLoads, MeshMapData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2, u_SrvD%TTMD%Mesh, y_ED%TowerLn2Mesh ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ED%TowerPtLoads' ) + + ! we'll need to add this to the loads from AeroDyn, later, so we're going to transfer to a temp mesh here instead of u_ED%TowerPtLoads + Force = u_ED%TowerPtLoads%force + Moment = u_ED%TowerPtLoads%moment + + END IF + + ELSE !we'll just take the initial guesses.. + END IF + + + ! ED inputs on blade from AeroDyn + IF (p_FAST%CompElast == Module_ED) THEN + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + DO K = 1,SIZE(u_ED%BladePtLoads,1) ! Loop through all blades (p_ED%NumBl) + DO J = 1,y_AD14%OutputLoads(K)%Nnodes ! Loop through the blade nodes / elements (p_ED%BldNodes) + + u_ED%BladePtLoads(K)%Force(:,J) = y_AD14%OutputLoads(K)%Force(:,J)*p_AD14%Blade%DR(J) + u_ED%BladePtLoads(K)%Moment(:,J) = y_AD14%OutputLoads(K)%Moment(:,J)*p_AD14%Blade%DR(J) + + END DO !J + END DO !K + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + DO K = 1,SIZE(u_ED%BladePtLoads,1) ! Loop through all blades (p_ED%NumBl) + CALL Transfer_Line2_to_Point( y_AD%BladeLoad(k), u_ED%BladePtLoads(k), MeshMapData%AD_L_2_BDED_B(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), y_ED%BladeLn2Mesh(k) ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + ELSE + !p_FAST%CompAero = Module_None + DO K = 1,SIZE(u_ED%BladePtLoads,1) ! Loop through all blades (p_ED%NumBl) + u_ED%BladePtLoads(K)%Force = 0.0_ReKi + u_ED%BladePtLoads(K)%Moment = 0.0_ReKi + END DO + + END IF + + END IF + + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + u_ED%TowerPtLoads%Force = 0.0_ReKi + u_ED%TowerPtLoads%Moment = 0.0_ReKi + + ! add aero force to the tower, if it's provided: + IF ( y_AD14%Twr_OutputLoads%Committed ) THEN + + ! we're mapping loads, so we also need the sibling meshes' displacements: + + ! CALL Transfer_Line2_to_Line2( ) + + J = y_AD14%Twr_OutputLoads%NNodes + + IF ( y_AD14%Twr_OutputLoads%FIELDMASK(MASKID_FORCE) ) & + u_ED%TowerPtLoads%Force(:,1:J) = u_ED%TowerPtLoads%Force( :,1:J) + y_AD14%Twr_OutputLoads%Force*p_AD14%TwrProps%TwrNodeWidth(j) + + IF ( y_AD14%Twr_OutputLoads%FIELDMASK(MASKID_MOMENT) ) & + u_ED%TowerPtLoads%Moment(:,1:J) = u_ED%TowerPtLoads%Moment(:,1:J) + y_AD14%Twr_OutputLoads%Moment*p_AD14%TwrProps%TwrNodeWidth(j) + + END IF + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + IF ( y_AD%TowerLoad%Committed ) THEN + CALL Transfer_Line2_to_Point( y_AD%TowerLoad, u_ED%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2, u_AD%TowerMotion, y_ED%TowerLn2Mesh ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + ELSE + u_ED%TowerPtLoads%Force = 0.0_ReKi + u_ED%TowerPtLoads%Moment = 0.0_ReKi + END IF + + ! add potential loads from TMD module: + u_ED%TowerPtLoads%Force = u_ED%TowerPtLoads%Force + Force + u_ED%TowerPtLoads%Moment = u_ED%TowerPtLoads%Moment + Moment + + + u_ED%TwrAddedMass = 0.0_ReKi + u_ED%PtfmAddedMass = 0.0_ReKi + + + ! add damping in blades and tower for linearization convergence + if (p_FAST%CalcSteady) then + + ! note that this assumes sibling meshes for input and output (the ED bladeLn2Mesh has the same first same first BladePtLoads%NNodes nodes as BladePtLoads, so this is okay) + do j = 1,u_ED%TowerPtLoads%NNodes ! u_ED%TowerPtLoads%NNodes is two less than y_ED%TowerLn2Mesh%NNodes + u_ED%TowerPtLoads%Force(:,j) = u_ED%TowerPtLoads%Force(:,j) - p_FAST%Twr_Kdmp * y_ED%TowerLn2Mesh%TranslationVel(:,j) + end do + + IF (p_FAST%CompElast == Module_ED) THEN + omega_c = y_ED%RotSpeed * y_ED%HubPtMotion%Orientation(1,:,1) + r_hub = y_ED%HubPtMotion%Position(:,1) + y_ED%HubPtMotion%TranslationDisp(:,1) + + do k=1,SIZE(u_ED%BladePtLoads,1) + do j = 1,u_ED%BladePtLoads(k)%NNodes + r = y_ED%BladeLn2Mesh(k)%Position(:,j) + y_ED%BladeLn2Mesh(k)%TranslationDisp(:,j) - r_hub + Vrot = cross_product(omega_c, r) + u_ED%BladePtLoads(k)%Force(:,j) = u_ED%BladePtLoads(k)%Force(:,j) - p_FAST%Bld_Kdmp * ( y_ED%BladeLn2Mesh(k)%TranslationVel(:,j) - Vrot ) + end do + end do + END IF + + end if + +END SUBROUTINE ED_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine determines the points in space where InflowWind needs to compute wind speeds. +SUBROUTINE IfW_InputSolve( p_FAST, m_FAST, u_IfW, p_IfW, u_AD14, u_AD, OtherSt_AD, y_ED, ErrStat, ErrMsg ) + + TYPE(InflowWind_InputType), INTENT(INOUT) :: u_IfW(:) !< The inputs to InflowWind + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p_IfW !< The parameters to InflowWind + TYPE(AD14_InputType), INTENT(IN) :: u_AD14 !< The input meshes (already calculated) from AeroDyn14 + TYPE(AD_InputType), INTENT(IN) :: u_AD !< The input meshes (already calculated) from AeroDyn + TYPE(AD_OtherStateType), INTENT(IN) :: OtherSt_AD !< The wake points from AeroDyn are in here (Free Vortex Wake) + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs of the structural dynamics module (for IfW Lidar) + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< misc FAST data, including inputs from external codes like Simulink + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: Node ! Node number for blade/node on mesh + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Fill input array for InflowWind + + Node = 0 + IF (p_FAST%CompServo == MODULE_SrvD) THEN + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = y_ED%HubPtMotion%Position(:,1) ! undisplaced position. Maybe we want to use the displaced position (y_ED%HubPtMotion%TranslationDisp) at some point in time. + END IF + + IF (p_FAST%CompAero == MODULE_AD14) THEN + + DO K = 1,SIZE(u_AD14%InputMarkers) + DO J = 1,u_AD14%InputMarkers(K)%nnodes !this mesh isn't properly set up (it's got the global [absolute] position and no reference position) + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = u_AD14%InputMarkers(K)%Position(:,J) + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + END DO !K = 1,p%NumBl + + DO J=1,u_AD14%Twr_InputMarkers%nnodes + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = u_AD14%Twr_InputMarkers%TranslationDisp(:,J) + u_AD14%Twr_InputMarkers%Position(:,J) + END DO + + ELSEIF (p_FAST%CompAero == MODULE_AD) THEN + + DO K = 1,SIZE(u_AD%BladeMotion) + DO J = 1,u_AD%BladeMotion(k)%Nnodes + + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = u_AD%BladeMotion(k)%TranslationDisp(:,j) + u_AD%BladeMotion(k)%Position(:,j) + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + END DO !K = 1,p%NumBl + + DO J=1,u_AD%TowerMotion%nnodes + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = u_AD%TowerMotion%TranslationDisp(:,J) + u_AD%TowerMotion%Position(:,J) + END DO + + ! vortex points from FVW in AD15 + if (allocated(OtherSt_AD%WakeLocationPoints)) then + do J=1,size(OtherSt_AD%WakeLocationPoints,DIM=2) + Node = Node + 1 + u_IfW(1)%PositionXYZ(:,Node) = OtherSt_AD%WakeLocationPoints(:,J) + ! rewrite the history of this so that extrapolation doesn't make a mess of things + do k=2,size(u_IfW) + if (allocated(u_IfW(k)%PositionXYZ)) u_IfW(k)%PositionXYZ(:,Node) = u_IfW(1)%PositionXYZ(:,Node) + end do + enddo + end if + END IF + + + CALL IfW_SetExternalInputs( p_IfW, m_FAST, y_ED, u_IfW(1) ) + + +END SUBROUTINE IfW_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for InflowWind from an external source (Simulink) +SUBROUTINE IfW_SetExternalInputs( p_IfW, m_FAST, y_ED, u_IfW ) +!.................................................................................................................................. + + TYPE(InflowWind_ParameterType), INTENT(IN) :: p_IfW !< InflowWind parameters + TYPE(FAST_MiscVarType), INTENT(IN) :: m_FAST !< Glue-code misc variables (including inputs from external sources like Simulink) + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs of the structural dynamics module + TYPE(InflowWind_InputType), INTENT(INOUT) :: u_IfW !< InflowWind Inputs at t + + + ! bjj: this is a total hack to get the lidar inputs into InflowWind. We should use a mesh to take care of this messiness (and, really this Lidar Focus should come + ! from Fortran (a scanning pattern or file-lookup inside InflowWind), not MATLAB. + + u_IfW%lidar%LidPosition = y_ED%HubPtMotion%Position(:,1) + y_ED%HubPtMotion%TranslationDisp(:,1) & ! rotor apex position (absolute) + + p_IfW%lidar%RotorApexOffsetPos ! lidar offset-from-rotor-apex position + + u_IfW%lidar%MsrPosition = m_FAST%ExternInput%LidarFocus + u_IfW%lidar%LidPosition + + +END SUBROUTINE IfW_SetExternalInputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the AeroDyn wind inflow inputs. +SUBROUTINE AD_InputSolve_IfW( p_FAST, u_AD, y_IfW, y_OpFM, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< The inputs to AeroDyn + TYPE(InflowWind_OutputType), INTENT(IN) :: y_IfW !< The outputs from InflowWind + TYPE(OpFM_OutputType), INTENT(IN) :: y_OpFM !< outputs from the OpenFOAM integration module + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: NumBl + INTEGER(IntKi) :: NNodes + INTEGER(IntKi) :: node + + + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! Set the inputs from inflow wind: + !------------------------------------------------------------------------------------------------- + IF (p_FAST%CompInflow == MODULE_IfW) THEN + + if (p_FAST%CompServo == MODULE_SrvD) then + node = 2 + else + node = 1 + end if + + + NumBl = size(u_AD%InflowOnBlade,3) + Nnodes = size(u_AD%InflowOnBlade,2) + + do k=1,NumBl + do j=1,Nnodes + u_AD%InflowOnBlade(:,j,k) = y_IfW%VelocityUVW(:,node) + node = node + 1 + end do + end do + + if ( allocated(u_AD%InflowOnTower) ) then + Nnodes = size(u_AD%InflowOnTower,2) + do j=1,Nnodes + u_AD%InflowOnTower(:,j) = y_IfW%VelocityUVW(:,node) + node = node + 1 + end do + end if + ! velocity at vortex wake points velocity array handoff here + if ( allocated(u_AD%InflowWakeVel) ) then + Nnodes = size(u_AD%InflowWakeVel,DIM=2) + do j=1,Nnodes + u_AD%InflowWakeVel(:,j) = y_IfW%VelocityUVW(:,node) + node = node + 1 + end do + end if + + + ELSEIF ( p_FAST%CompInflow == MODULE_OpFM ) THEN + node = 2 !start of inputs to AD15 + + NumBl = size(u_AD%InflowOnBlade,3) + Nnodes = size(u_AD%InflowOnBlade,2) + + do k=1,NumBl + do j=1,Nnodes + u_AD%InflowOnBlade(1,j,k) = y_OpFM%u(node) + u_AD%InflowOnBlade(2,j,k) = y_OpFM%v(node) + u_AD%InflowOnBlade(3,j,k) = y_OpFM%w(node) + node = node + 1 + end do + end do + + if ( allocated(u_AD%InflowOnTower) ) then + Nnodes = size(u_AD%InflowOnTower,2) + do j=1,Nnodes + u_AD%InflowOnTower(1,j) = y_OpFM%u(node) + u_AD%InflowOnTower(2,j) = y_OpFM%v(node) + u_AD%InflowOnTower(3,j) = y_OpFM%w(node) + node = node + 1 + end do + end if + + ELSE + + u_AD%InflowOnBlade = 0.0_ReKi ! whole array + + END IF + + +END SUBROUTINE AD_InputSolve_IfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets all the AeroDyn inputs, except for the wind inflow values. +SUBROUTINE AD_InputSolve_NoIfW( p_FAST, u_AD, y_SrvD, y_ED, BD, MeshMapData, ErrStat, ErrMsg ) + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data + TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< The inputs to AeroDyn14 + TYPE(SrvD_OutputType), INTENT(IN ) :: y_SrvD !< ServoDyn outputs + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(BeamDyn_Data), INTENT(IN) :: BD !< The data from BeamDyn (want the outputs only, but it's in an array) + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: K ! Loops through blades + INTEGER(IntKi) :: k_bl ! Loops through blades + INTEGER(IntKi) :: k_bn ! Loops through blade nodes + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'AD_InputSolve_NoIfW' + + + ErrStat = ErrID_None + ErrMsg = "" + + + !------------------------------------------------------------------------------------------------- + ! Set the inputs from ElastoDyn and/or BeamDyn: + !------------------------------------------------------------------------------------------------- + + ! tower + IF (u_AD%TowerMotion%Committed) THEN + + CALL Transfer_Line2_to_Line2( y_ED%TowerLn2Mesh, u_AD%TowerMotion, MeshMapData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%TowerMotion' ) + + END IF + + + ! hub + CALL Transfer_Point_to_Point( y_ED%HubPtMotion, u_AD%HubMotion, MeshMapData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%HubMotion' ) + + + ! blade root + DO k=1,size(y_ED%BladeRootMotion) + CALL Transfer_Point_to_Point( y_ED%BladeRootMotion(k), u_AD%BladeRootMotion(k), MeshMapData%ED_P_2_AD_P_R(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeRootMotion('//trim(num2lstr(k))//')' ) + END DO + + + ! blades + IF (p_FAST%CompElast == Module_ED ) THEN + + DO k=1,size(y_ED%BladeLn2Mesh) + CALL Transfer_Line2_to_Line2( y_ED%BladeLn2Mesh(k), u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeMotion('//trim(num2lstr(k))//')' ) + END DO + + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + + ! get them from BeamDyn + DO k=1,size(u_AD%BladeMotion) + CALL Transfer_Line2_to_Line2( BD%y(k)%BldMotion, u_AD%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//':u_AD%BladeMotion('//trim(num2lstr(k))//')' ) + END DO + + + END IF + + + ! Set Conrol parameter (i.e. flaps) if using ServoDyn + ! bem: This takes in flap deflection for each blade (only one flap deflection angle per blade), + ! from ServoDyn (which comes from Bladed style DLL controller) + ! Commanded Airfoil UserProp for blade (must be same units as given in AD15 airfoil tables) + ! This is passed to AD15 to be interpolated with the airfoil table userprop column + ! (might be used for airfoil flap angles for example) + if (p_FAST%CompServo == Module_SrvD) then + DO k_bl=1,size(u_AD%UserProp,DIM=2) + DO k_bn=1,size(u_AD%UserProp,DIM=1) + u_AD%UserProp(k_bn , k_bl) = y_SrvD%BlAirfoilCom(k_bl) ! Must be same units as given in airfoil (no unit conversions handled in code) + END DO + END DO + endif + + +END SUBROUTINE AD_InputSolve_NoIfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the AeroDyn14 wind inflow inputs. +SUBROUTINE AD14_InputSolve_IfW( p_FAST, u_AD14, y_IfW, y_OpFM, ErrStat, ErrMsg ) +!,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameter FAST data + TYPE(AD14_InputType), INTENT(INOUT) :: u_AD14 !< The inputs to AeroDyn14 + TYPE(InflowWind_OutputType), INTENT(IN) :: y_IfW !< The outputs from InflowWind + TYPE(OpFM_OutputType), INTENT(IN) :: y_OpFM !< outputs from the OpenFOAM integration module + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: NumBl + INTEGER(IntKi) :: BldNodes + + + ErrStat = ErrID_None + ErrMsg = "" + + NumBl = SIZE(u_AD14%InputMarkers,1) + BldNodes = u_AD14%InputMarkers(1)%Nnodes + + !------------------------------------------------------------------------------------------------- + ! Set the inputs from inflow wind: + !------------------------------------------------------------------------------------------------- + IF (p_FAST%CompInflow == MODULE_IfW) THEN + IF (p_FAST%CompServo == MODULE_SrvD) THEN + u_AD14%InflowVelocity = y_IfW%VelocityUVW(:,2:) ! first point is used for ServoDyn input + ELSE + u_AD14%InflowVelocity = y_IfW%VelocityUVW(:,:) + END IF + ELSEIF ( p_FAST%CompInflow == MODULE_OpFM ) THEN + u_AD14%InflowVelocity(1,:) = y_OpFM%u(2:) + u_AD14%InflowVelocity(2,:) = y_OpFM%v(2:) + u_AD14%InflowVelocity(3,:) = y_OpFM%w(2:) + ELSE + u_AD14%InflowVelocity = 0.0_ReKi ! whole array + END IF + + u_AD14%AvgInfVel = y_IfW%DiskVel + + +END SUBROUTINE AD14_InputSolve_IfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets all the AeroDyn14 inputs, except for the wind inflow values. +!! THIS ROUTINE IS A HACK TO GET THE OUTPUTS FROM ELASTODYN INTO AERODYN14. DO NOT COPY OR USE IN NEW CODE! +SUBROUTINE AD14_InputSolve_NoIfW( p_FAST, u_AD14, y_ED, MeshMapData, ErrStat, ErrMsg ) +!,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< parameter FAST data + TYPE(AD14_InputType), INTENT(INOUT) :: u_AD14 !< The inputs to AeroDyn14 + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: NodeNum ! Node number for blade/node on mesh + INTEGER(IntKi) :: NumBl + INTEGER(IntKi) :: BldNodes + + + ErrStat = ErrID_None + ErrMsg = "" + + NumBl = SIZE(u_AD14%InputMarkers,1) + BldNodes = u_AD14%InputMarkers(1)%Nnodes + + + !------------------------------------------------------------------------------------------------- + ! Blade positions, orientations, and velocities: + !------------------------------------------------------------------------------------------------- + IF (p_FAST%CompElast == Module_ED) THEN + DO K = 1,NumBl !p%NumBl ! Loop through all blades + + !CALL Transfer_Line2_to_Line2( y_ED%BladeLn2Mesh(K), u_AD%InputMarkers(K), MeshMapData%BDED_L_2_AD_L_B(K), ErrStat, ErrMsg ) + ! IF (ErrStat >= AbortErrLev ) RETURN + + u_AD14%InputMarkers(K)%RotationVel = 0.0_ReKi ! bjj: we don't need this field + + DO J = 1,BldNodes !p%BldNodes ! Loop through the blade nodes / elements + + NodeNum = J ! note that this assumes ED has same discretization as AD + + u_AD14%InputMarkers(K)%Position(:,J) = y_ED%BladeLn2Mesh(K)%TranslationDisp(:,NodeNum) + y_ED%BladeLn2Mesh(K)%Position(:,NodeNum) + u_AD14%InputMarkers(K)%Orientation(:,:,J) = y_ED%BladeLn2Mesh(K)%Orientation(:,:,NodeNum) + u_AD14%InputMarkers(K)%TranslationVel(:,J) = y_ED%BladeLn2Mesh(K)%TranslationVel(:,NodeNum) + u_AD14%InputMarkers(K)%TranslationAcc(:,J) = y_ED%BladeLn2Mesh(K)%TranslationAcc(:,NodeNum) + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + END DO !K = 1,p%NumBl + ELSE + ! just leave them as the initial guesses? + DO K = 1,NumBl + u_AD14%InputMarkers(K)%RotationVel = 0.0_ReKi + u_AD14%InputMarkers(K)%TranslationVel = 0.0_ReKi + u_AD14%InputMarkers(K)%TranslationAcc = 0.0_ReKi + END DO + + END IF + + !------------------------------------------------------------------------------------------------- + ! Hub positions, orientations, and velocities: + ! (note that these may have to be adjusted in ElastoDyn as AeroDyn gets rewritten) + !------------------------------------------------------------------------------------------------- + u_AD14%TurbineComponents%Hub%Position = y_ED%HubPtMotion14%TranslationDisp(:,1) + y_ED%HubPtMotion14%Position(:,1) + u_AD14%TurbineComponents%Hub%Orientation = y_ED%HubPtMotion14%Orientation(:,:,1) + u_AD14%TurbineComponents%Hub%RotationVel = y_ED%HubPtMotion14%RotationVel(:,1) + + u_AD14%TurbineComponents%Hub%TranslationVel = 0.0_ReKi !bjj we don't need this field + !------------------------------------------------------------------------------------------------- + ! Blade root orientations: + !------------------------------------------------------------------------------------------------- + + DO K=1,NumBl + u_AD14%TurbineComponents%Blade(K)%Orientation = y_ED%BladeRootMotion14%Orientation(:,:,K) + + u_AD14%TurbineComponents%Blade(K)%Position = 0.0_ReKi !bjj we don't need this field + u_AD14%TurbineComponents%Blade(K)%RotationVel = 0.0_ReKi !bjj we don't need this field + u_AD14%TurbineComponents%Blade(K)%TranslationVel = 0.0_ReKi !bjj we don't need this field + END DO + + + !------------------------------------------------------------------------------------------------- + ! RotorFurl position, orientation, rotational velocity: + !------------------------------------------------------------------------------------------------- + + u_AD14%TurbineComponents%RotorFurl%Position = y_ED%RotorFurlMotion14%TranslationDisp(:,1) + y_ED%RotorFurlMotion14%Position(:,1) + u_AD14%TurbineComponents%RotorFurl%Orientation = y_ED%RotorFurlMotion14%Orientation(:,:,1) + u_AD14%TurbineComponents%RotorFurl%RotationVel = y_ED%RotorFurlMotion14%RotationVel(:,1) + u_AD14%TurbineComponents%RotorFurl%TranslationVel = 0.0_ReKi !bjj we don't need this field + + !------------------------------------------------------------------------------------------------- + ! Nacelle position, orientation, rotational velocity: + !------------------------------------------------------------------------------------------------- + + u_AD14%TurbineComponents%Nacelle%Position = y_ED%NacelleMotion%TranslationDisp(:,1) + y_ED%NacelleMotion%Position(:,1) + u_AD14%TurbineComponents%Nacelle%Orientation = y_ED%NacelleMotion%Orientation(:,:,1) + u_AD14%TurbineComponents%Nacelle%RotationVel = y_ED%NacelleMotion%RotationVel(:,1) + u_AD14%TurbineComponents%Nacelle%TranslationVel = 0.0_ReKi !bjj we don't need this field + + !------------------------------------------------------------------------------------------------- + ! Tower base position, rotational velocity: + !------------------------------------------------------------------------------------------------- + + + ! Tower base position should be rT(0) instead of rZ, but AeroDyn needs this for + ! the HubVDue2Yaw calculation: + u_AD14%TurbineComponents%Tower%Position = y_ED%TowerBaseMotion14%TranslationDisp(:,1) + y_ED%TowerBaseMotion14%Position(:,1) + u_AD14%TurbineComponents%Tower%RotationVel = y_ED%TowerBaseMotion14%RotationVel(:,1) + u_AD14%TurbineComponents%Tower%Orientation = 0.0_ReKi !bjj we don't need this field + u_AD14%TurbineComponents%Tower%TranslationVel = 0.0_ReKi !bjj we don't need this field + + + !------------------------------------------------------------------------------------------------- + ! Tower mesh info: Twr_InputMarkers + !------------------------------------------------------------------------------------------------- + + IF ( u_AD14%Twr_InputMarkers%Committed ) THEN + + !CALL Transfer_Line2_to_Line2( y_ED%TowerLn2Mesh, u_AD%Twr_InputMarkers, MeshMapData%ED_L_2_AD_L_T, ErrStat, ErrMsg ) + ! IF (ErrStat >= AbortErrLev ) RETURN + + J = u_AD14%Twr_InputMarkers%NNodes + u_AD14%Twr_InputMarkers%TranslationDisp = y_ED%TowerLn2Mesh%TranslationDisp(:,1:J) + u_AD14%Twr_InputMarkers%Orientation = y_ED%TowerLn2Mesh%Orientation (:,:,1:J) + + END IF + + !------------------------------------------------------------------------------------------------- + ! If using MulTabLoc feature, set it here: + !------------------------------------------------------------------------------------------------- + + ! u_AD14%MulTabLoc(IElements,IBlades) = ??? + +END SUBROUTINE AD14_InputSolve_NoIfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for ServoDyn +SUBROUTINE SrvD_InputSolve( p_FAST, m_FAST, u_SrvD, y_ED, y_IfW, y_OpFM, y_BD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_MiscVarType), INTENT(IN) :: m_FAST !< Glue-code misc variables (including inputs from external sources like Simulink) + TYPE(SrvD_InputType), INTENT(INOUT) :: u_SrvD !< ServoDyn Inputs at t + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< ElastoDyn outputs + TYPE(InflowWind_OutputType), INTENT(IN) :: y_IfW !< InflowWind outputs + TYPE(OpFM_OutputType), INTENT(IN) :: y_OpFM !< OpenFOAM outputs + TYPE(BD_OutputType), INTENT(IN) :: y_BD(:) !< BD Outputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message +! TYPE(AD_OutputType), INTENT(IN) :: y_AD !< AeroDyn outputs + + INTEGER(IntKi) :: k ! blade loop counter + + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_InputSolve' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Calculate horizontal hub-height wind direction (positive about zi-axis); these are + ! zero if there is no wind input when InflowWind is not used: + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + u_SrvD%WindDir = ATAN2( y_IfW%VelocityUVW(2,1), y_IfW%VelocityUVW(1,1) ) + u_SrvD%YawErr = u_SrvD%WindDir - y_ED%YawAngle + u_SrvD%HorWindV = SQRT( y_IfW%VelocityUVW(1,1)**2 + y_IfW%VelocityUVW(2,1)**2 ) + + ELSEIF ( p_FAST%CompInflow == Module_OpFM ) THEN + + u_SrvD%WindDir = ATAN2( y_OpFM%v(1), y_OpFM%u(1) ) + u_SrvD%YawErr = u_SrvD%WindDir - y_ED%YawAngle + u_SrvD%HorWindV = SQRT( y_OpFM%u(1)**2 + y_OpFM%v(1)**2 ) + + if ( allocated(u_SrvD%SuperController) ) then + u_SrvD%SuperController = y_OpFM%SuperController + end if + + ELSE ! No wind inflow + + u_SrvD%WindDir = 0.0 + u_SrvD%HorWindV = 0.0 + + ENDIF + + + + + ! ServoDyn inputs from combination of InflowWind and ElastoDyn + + u_SrvD%YawAngle = y_ED%YawAngle !nacelle yaw plus platform yaw + u_SrvD%YawErr = u_SrvD%WindDir - u_SrvD%YawAngle ! the nacelle yaw error estimate (positive about zi-axis) + + + ! ServoDyn inputs from ElastoDyn + u_SrvD%Yaw = y_ED%Yaw !nacelle yaw + u_SrvD%YawRate = y_ED%YawRate + u_SrvD%BlPitch = y_ED%BlPitch + u_SrvD%LSS_Spd = y_ED%LSS_Spd + u_SrvD%HSS_Spd = y_ED%HSS_Spd + u_SrvD%RotSpeed = y_ED%RotSpeed + + IF ( p_FAST%CompElast == Module_BD ) THEN + + ! translate "b" system output from BD into "c" system for SrvD + do k=1,p_FAST%nBeams + u_SrvD%RootMxc(k) = y_BD(k)%RootMxr*COS(y_ED%BlPitch(k)) + y_BD(k)%RootMyr*SIN(y_ED%BlPitch(k)) + u_SrvD%RootMyc(k) = -y_BD(k)%RootMxr*SIN(y_ED%BlPitch(k)) + y_BD(k)%RootMyr*COS(y_ED%BlPitch(k)) + end do + + ELSE + u_SrvD%RootMxc = y_ED%RootMxc ! fixed-size arrays: always size 3 + u_SrvD%RootMyc = y_ED%RootMyc ! fixed-size arrays: always size 3 + END IF + + + u_SrvD%YawBrTAxp = y_ED%YawBrTAxp + u_SrvD%YawBrTAyp = y_ED%YawBrTAyp + u_SrvD%LSSTipPxa = y_ED%LSSTipPxa + + u_SrvD%LSSTipMxa = y_ED%LSSTipMxa + u_SrvD%LSSTipMya = y_ED%LSSTipMya + u_SrvD%LSSTipMza = y_ED%LSSTipMza + u_SrvD%LSSTipMys = y_ED%LSSTipMys + u_SrvD%LSSTipMzs = y_ED%LSSTipMzs + + u_SrvD%YawBrMyn = y_ED%YawBrMyn + u_SrvD%YawBrMzn = y_ED%YawBrMzn + u_SrvD%NcIMURAxs = y_ED%NcIMURAxs + u_SrvD%NcIMURAys = y_ED%NcIMURAys + u_SrvD%NcIMURAzs = y_ED%NcIMURAzs + + u_SrvD%RotPwr = y_ED%RotPwr + + ! ! ServoDyn inputs from AeroDyn + !IF ( p_FAST%CompAero == Module_AD ) THEN + !ELSE + !END IF + ! + + IF (u_SrvD%NTMD%Mesh%Committed) THEN + + CALL Transfer_Point_to_Point( y_ED%NacelleMotion, u_SrvD%NTMD%Mesh, MeshMapData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + END IF + + IF (u_SrvD%TTMD%Mesh%Committed) THEN + + CALL Transfer_Line2_to_Point( y_ED%TowerLn2Mesh, u_SrvD%TTMD%Mesh, MeshMapData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + END IF + + +#ifdef SIMULINK_TIMESHIFT + ! we're going to use the extrapolated values instead of the old values (Simulink inputs are from t, not t+dt) + CALL SrvD_SetExternalInputs( p_FAST, m_FAST, u_SrvD ) +#endif + + +END SUBROUTINE SrvD_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for ServoDyn from an external source (Simulink) +SUBROUTINE SrvD_SetExternalInputs( p_FAST, m_FAST, u_SrvD ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_MiscVarType), INTENT(IN) :: m_FAST !< Glue-code misc variables (including inputs from external sources like Simulink) + TYPE(SrvD_InputType), INTENT(INOUT) :: u_SrvD !< ServoDyn Inputs at t + + ! local variables + INTEGER(IntKi) :: i ! loop counter + + ! we are going to use extrapolated values because these external values from Simulink are at n instead of n+1 + u_SrvD%ExternalGenTrq = m_FAST%ExternInput%GenTrq + u_SrvD%ExternalElecPwr = m_FAST%ExternInput%ElecPwr + u_SrvD%ExternalYawPosCom = m_FAST%ExternInput%YawPosCom + u_SrvD%ExternalYawRateCom = m_FAST%ExternInput%YawRateCom + u_SrvD%ExternalHSSBrFrac = m_FAST%ExternInput%HSSBrFrac + + if (ALLOCATED(u_SrvD%ExternalBlPitchCom)) then !there should be no reason this isn't allocated, but OpenFOAM is acting strange... + do i=1,SIZE(u_SrvD%ExternalBlPitchCom) + u_SrvD%ExternalBlPitchCom(i) = m_FAST%ExternInput%BlPitchCom(i) + end do + end if + +END SUBROUTINE SrvD_SetExternalInputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transfers the SD outputs into inputs required for HD +SUBROUTINE Transfer_SD_to_HD( y_SD, u_HD_M_LumpedMesh, u_HD_M_DistribMesh, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< The outputs of the structural dynamics module + TYPE(MeshType), INTENT(INOUT) :: u_HD_M_LumpedMesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) + TYPE(MeshType), INTENT(INOUT) :: u_HD_M_DistribMesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes + + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( u_HD_M_LumpedMesh%Committed ) THEN + + ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body + CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_HD_M_LumpedMesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%Morison%LumpedMesh)' ) + + END IF + + IF ( u_HD_M_DistribMesh%Committed ) THEN + + ! These are the motions for the HD line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body + CALL Transfer_Point_to_Line2( y_SD%y2Mesh, u_HD_M_DistribMesh, MeshMapData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%Morison%DistribMesh)' ) + END IF + +END SUBROUTINE Transfer_SD_to_HD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transfers the platform motion output of the structural module (ED) into inputs required for HD +SUBROUTINE Transfer_PlatformMotion_to_HD( PlatformMotion, u_HD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(MeshType), INTENT(IN ) :: PlatformMotion !< The platform motion outputs of the structural dynamics module + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< HydroDyn input + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_PlatformMotion_to_HD' + + + ErrStat = ErrID_None + ErrMsg = "" + + !bjj: We do this without all the extra meshcopy/destroy calls with u_mapped because these inputs are only from one mesh + + IF ( u_HD%Mesh%Committed ) THEN + + ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, + ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, + ! hydrodynamic added mass + + CALL Transfer_Point_to_Point( PlatformMotion, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Mesh)' ) + + END IF !WAMIT + + + IF ( u_HD%Morison%LumpedMesh%Committed ) THEN + + ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body + CALL Transfer_Point_to_Point( PlatformMotion, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Morison%LumpedMesh)' ) + + END IF + + IF ( u_HD%Morison%DistribMesh%Committed ) THEN + + ! These are the motions for the line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body + CALL Transfer_Point_to_Line2( PlatformMotion, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Morison%DistribMesh)' ) + + END IF + +END SUBROUTINE Transfer_PlatformMotion_to_HD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transfers the ED outputs into inputs required for HD, SD, ExtPtfm, BD, MAP, and/or FEAM +SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, u_MAP, u_FEAM, u_MD, u_Orca, u_BD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< HydroDyn input + TYPE(SD_InputType), INTENT(INOUT) :: u_SD !< SubDyn input + TYPE(ExtPtfm_InputType), INTENT(INOUT) :: u_ExtPtfm !< ExtPtfm_MCKF input + TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< MAP input + TYPE(FEAM_InputType), INTENT(INOUT) :: u_FEAM !< FEAM input + TYPE(MD_InputType), INTENT(INOUT) :: u_MD !< MoorDyn input + TYPE(Orca_InputType), INTENT(INOUT) :: u_Orca !< OrcaFlex input + TYPE(BD_InputType), INTENT(INOUT) :: u_BD(:) !< BeamDyn inputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_ED_to_HD_SD_BD_Mooring' + + ErrStat = ErrID_None + ErrMsg = "" + + ! transfer ED outputs to other modules used in option 1: + + IF ( p_FAST%CompSub == Module_SD ) THEN + + ! Map ED (motion) outputs to SD inputs: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_SD%TPMesh' ) + + IF ( p_FAST%CompHydro == Module_HD ) call TransferFixedBottomToHD() + + ELSEIF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + + ! Map ED (motion) outputs to ExtPtfm inputs: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_ExtPtfm%PtfmMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ExtPtfm%PtfmMesh' ) + + IF ( p_FAST%CompHydro == Module_HD ) call TransferFixedBottomToHD() + + ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN + ! Map ED outputs to HD inputs: + CALL Transfer_PlatformMotion_to_HD( y_ED%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName ) + + END IF + + + + + IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + ! map ED root and hub motion outputs to BeamDyn: + CALL Transfer_ED_to_BD(y_ED, u_BD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName ) + + END IF + + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MAP%PtFairDisplacement' ) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MD%PtFairleadDisplacement' ) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_FEAM%PtFairleadDisplacement' ) + + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_Orca%PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_Orca%PtfmMesh' ) + END IF + +contains + subroutine TransferFixedBottomToHD() + IF ( u_HD%Mesh%Committed ) THEN + + ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, + ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, + ! hydrodynamic added mass + + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Mesh)' ) + + END IF !WAMIT + end subroutine +END SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for MAP. +SUBROUTINE MAP_InputSolve( u_MAP, y_ED, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< MAP input + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + !---------------------------------------------------------------------------------------------------- + ! Map ED outputs to MAP inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + + +END SUBROUTINE MAP_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for FEAM. +SUBROUTINE FEAM_InputSolve( u_FEAM, y_ED, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(FEAM_InputType), INTENT(INOUT) :: u_FEAM !< FEAM input + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + !---------------------------------------------------------------------------------------------------- + ! Map ED outputs to FEAM inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + + +END SUBROUTINE FEAM_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for MoorDyn. +SUBROUTINE MD_InputSolve( u_MD, y_ED, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(MD_InputType), INTENT(INOUT) :: u_MD !< MoorDyn input + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + !---------------------------------------------------------------------------------------------------- + ! Map ED outputs to MoorDyn inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + + +END SUBROUTINE MD_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for IceFloe. +SUBROUTINE IceFloe_InputSolve( u_IceF, y_SD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(IceFloe_InputType), INTENT(INOUT) :: u_IceF !< IceFloe input + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SubDyn outputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + !---------------------------------------------------------------------------------------------------- + ! Map SD outputs to IceFloe inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_IceF%IceMesh, MeshMapData%SD_P_2_IceF_P, ErrStat, ErrMsg ) + +END SUBROUTINE IceFloe_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for IceFloe. +SUBROUTINE IceD_InputSolve( u_IceD, y_SD, MeshMapData, legNum, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(IceD_InputType), INTENT(INOUT) :: u_IceD !< IceDyn input + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SubDyn outputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + INTEGER(IntKi), INTENT(IN ) :: legNum !< which instance of IceDyn we're using + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + !---------------------------------------------------------------------------------------------------- + ! Map SD outputs to IceFloe inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_IceD%PointMesh, MeshMapData%SD_P_2_IceD_P(legNum), ErrStat, ErrMsg ) + +END SUBROUTINE IceD_InputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for IceFloe. +SUBROUTINE Transfer_ED_to_BD( y_ED, u_BD, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(BD_InputType), INTENT(INOUT) :: u_BD(:) !< BeamDyn inputs + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + + ! local variables + INTEGER(IntKi) :: k + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_ED_to_BD' + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------------------------------- + ! Map ED outputs to BeamDyn inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + do k = 1,size(y_ED%BladeRootMotion) + CALL Transfer_Point_to_Point( y_ED%BladeRootMotion(k), u_BD(k)%RootMotion, MeshMapData%ED_P_2_BD_P(k), ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL Transfer_Point_to_Point( y_ED%HubPtMotion, u_BD(k)%HubMotion, MeshMapData%ED_P_2_BD_P_Hub(k), ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end do + + +END SUBROUTINE Transfer_ED_to_BD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the inputs required for IceFloe. +SUBROUTINE Transfer_ED_to_BD_tmp( y_ED, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + + ! local variables + INTEGER(IntKi) :: k + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_ED_to_BD_tmp' + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------------------------------- + ! Map ED outputs to BeamDyn inputs + !---------------------------------------------------------------------------------------------------- + ! motions: + do k = 1,size(y_ED%BladeRootMotion) + CALL Transfer_Point_to_Point( y_ED%BladeRootMotion(k), MeshMapData%u_BD_RootMotion(k), MeshMapData%ED_P_2_BD_P(k), ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + end do + + +END SUBROUTINE Transfer_ED_to_BD_tmp +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transfers the HD outputs into inputs required for ED. Note that this *adds* to the values already in +!! u_SD_LMesh (so initialize it before calling this routine). +SUBROUTINE Transfer_HD_to_SD( u_mapped, u_SD_LMesh, u_mapped_positions, y_HD, u_HD_M_LumpedMesh, u_HD_M_DistribMesh, MeshMapData, ErrStat, ErrMsg ) +!.................................................................................................................................. + TYPE(MeshType), INTENT(INOUT) :: u_mapped !< temporary copy of SD mesh (an argument to avoid another temporary mesh copy) + TYPE(MeshType), INTENT(INOUT) :: u_SD_LMesh !< SD Inputs on LMesh at t (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) + TYPE(MeshType), INTENT(IN ) :: u_mapped_positions !< Mesh sibling of u_mapped, with displaced positions + TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HydroDyn outputs + TYPE(MeshType), INTENT(IN ) :: u_HD_M_LumpedMesh !< HydroDyn input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) + TYPE(MeshType), INTENT(IN ) :: u_HD_M_DistribMesh !< HydroDyn input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Transfer_HD_to_SD' + + ErrStat = ErrID_None + ErrMsg = "" + + !assumes u_SD%LMesh%Committed (i.e., u_SD_LMesh%Committed) + + IF ( y_HD%Morison%LumpedMesh%Committed ) THEN + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD%Morison%LumpedMesh, u_mapped, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, u_HD_M_LumpedMesh, u_mapped_positions ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + u_SD_LMesh%Force = u_SD_LMesh%Force + u_mapped%Force + u_SD_LMesh%Moment = u_SD_LMesh%Moment + u_mapped%Moment + +#ifdef DEBUG_MESH_TRANSFER + CALL WrScr('********************************************************') + CALL WrScr('**** SD to HD point-to-point (morison lumped) *****') + CALL WrScr('********************************************************') + CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_M_LumpedMesh, y_HD%Morison%LumpedMesh,& + MeshMapData%SD_P_2_HD_M_P, MeshMapData%HD_M_P_2_SD_P, & + 'SD_y2_HD_ML_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) + !print * + !pause + +#endif + + END IF + + IF ( y_HD%Morison%DistribMesh%Committed ) THEN + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Line2_to_Point( y_HD%Morison%DistribMesh, u_mapped, MeshMapData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, u_HD_M_DistribMesh, u_mapped_positions ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + u_SD_LMesh%Force = u_SD_LMesh%Force + u_mapped%Force + u_SD_LMesh%Moment = u_SD_LMesh%Moment + u_mapped%Moment + +#ifdef DEBUG_MESH_TRANSFER + CALL WrScr('********************************************************') + CALL WrScr('**** SD to HD point-to-line2 (morison distributed) *****') + CALL WrScr('********************************************************') + CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_M_DistribMesh,y_HD%Morison%DistribMesh,& + MeshMapData%SD_P_2_HD_M_L, MeshMapData%HD_M_L_2_SD_P, & + 'SD_y2_HD_MD_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) + !print * + ! pause +#endif + + END IF + +END SUBROUTINE Transfer_HD_to_SD +!---------------------------------------------------------------------------------------------------------------------------------- +!> function to return the size of perturbation in calculating jacobian with finite differences. Currently hard-coded to return 1. +REAL(ReKi) FUNCTION GetPerturb(x) + REAL(ReKi), INTENT(IN) :: x !< value that we want to perturb + + !GetPerturb = sqrt( EPSILON(x)) * max( abs(x), 1._ReKi) +! GetPerturb = 1.0e6 + GetPerturb = 1.0 + +END FUNCTION GetPerturb +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine performs the Input-Output solve for ED and HD. +!! Note that this has been customized for the physics in the problems and is not a general solution. +SUBROUTINE ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & + , u_ED, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED, m_ED & + , u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD & + , u_MAP, y_MAP, u_FEAM, y_FEAM, u_MD, y_MD & + , MeshMapData , ErrStat, ErrMsg, WriteThisStep ) +!.................................................................................................................................. + + USE ElastoDyn + USE HydroDyn + + ! Passed variables + + REAL(DbKi) , INTENT(IN ) :: this_time !< The current simulation time (actual or time of prediction) + TYPE(FAST_ParameterType) , INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + LOGICAL , INTENT(IN ) :: calcJacobian !< Should we calculate Jacobians this time? (should be TRUE on initialization, then can be false [significantly reducing computational time]) + + !ElastoDyn: + TYPE(ED_ContinuousStateType) , INTENT(IN ) :: x_ED !< Continuous states + TYPE(ED_DiscreteStateType) , INTENT(IN ) :: xd_ED !< Discrete states + TYPE(ED_ConstraintStateType) , INTENT(IN ) :: z_ED !< Constraint states + TYPE(ED_OtherStateType) , INTENT(INOUT) :: OtherSt_ED !< Other states + TYPE(ED_ParameterType) , INTENT(IN ) :: p_ED !< Parameters + TYPE(ED_InputType) , INTENT(INOUT) :: u_ED !< System inputs + TYPE(ED_OutputType) , INTENT(INOUT) :: y_ED !< System outputs + TYPE(ED_MiscVarType) , INTENT(INOUT) :: m_ED !< misc/optimization variables + + !HydroDyn: + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x_HD !< Continuous states + TYPE(HydroDyn_DiscreteStateType) , INTENT(IN ) :: xd_HD !< Discrete states + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z_HD !< Constraint states + TYPE(HydroDyn_OtherStateType) , INTENT(INOUT) :: OtherSt_HD !< Other states + TYPE(HydroDyn_ParameterType) , INTENT(IN ) :: p_HD !< Parameters + TYPE(HydroDyn_InputType) , INTENT(INOUT) :: u_HD !< System inputs + TYPE(HydroDyn_OutputType) , INTENT(INOUT) :: y_HD !< System outputs + TYPE(HydroDyn_MiscVarType) , INTENT(INOUT) :: m_HD !< misc/optimization variables + + ! MAP/FEAM/MoorDyn: + TYPE(MAP_OutputType), INTENT(IN ) :: y_MAP !< MAP outputs + TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< MAP inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(FEAM_OutputType), INTENT(IN ) :: y_FEAM !< FEAM outputs + TYPE(FEAM_InputType), INTENT(INOUT) :: u_FEAM !< FEAM inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(MD_OutputType), INTENT(IN ) :: y_MD !< MoorDyn outputs + TYPE(MD_InputType), INTENT(INOUT) :: u_MD !< MoorDyn inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + + TYPE(FAST_ModuleMapType) , INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + ! Local variables: + INTEGER, PARAMETER :: NumInputs = SizeJac_ED_HD !12 + REAL(ReKi), PARAMETER :: TOL_Squared = (1.0E-4)**2 !not currently used because KMax = 1 + REAL(ReKi) :: ThisPerturb ! an arbitrary perturbation (these are linear, so it shouldn't matter) + + REAL(ReKi) :: u( NumInputs) ! 6 loads, 6 accelerations + REAL(ReKi) :: u_perturb( NumInputs) ! 6 loads, 6 accelerations + REAL(ReKi) :: u_delta( NumInputs) ! + REAL(ReKi) :: Fn_U_perturb(NumInputs) ! value of U with perturbations + REAL(ReKi) :: Fn_U_Resid( NumInputs) ! Residual of U + + + TYPE(ED_OutputType) :: y_ED_input ! Copy of system outputs sent to this routine (routine input value) + TYPE(ED_InputType) :: u_ED_perturb ! Perturbed system inputs + TYPE(ED_OutputType) :: y_ED_perturb ! Perturbed system outputs + TYPE(HydroDyn_InputType) :: u_HD_perturb ! Perturbed system inputs + TYPE(HydroDyn_OutputType) :: y_HD_perturb ! Perturbed system outputs + + + INTEGER(IntKi) :: i ! loop counter (jacobian column number) + INTEGER(IntKi) :: K ! Input-output-solve iteration counter + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'ED_HD_InputOutputSolve' + +#ifdef OUTPUT_ADDEDMASS + REAL(ReKi) :: AddedMassMatrix(6,6) + INTEGER :: UnAM +#endif +#ifdef OUTPUT_JACOBIAN + INTEGER :: UnJac +#endif + + ! Note: p_FAST%UJacSclFact is a scaling factor that gets us similar magnitudes between loads and accelerations... + +!bjj: note, that this routine may have a problem if there is remapping done + + ErrStat = ErrID_None + ErrMsg = "" + + ! note this routine should be called only + ! IF ( p_FAST%CompHydro == Module_HD .AND. p_FAST%CompSub == Module_None .and. p_FAST%CompElast /= Module_BD ) + + !---------------------------------------------------------------------------------------------------- + ! Some more record keeping stuff: + !---------------------------------------------------------------------------------------------------- + + ! We need to know the outputs that were sent to this routine: + CALL ED_CopyOutput( y_ED, y_ED_input, MESH_NEWCOPY, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Local copies for perturbing inputs and outputs (computing Jacobian): + IF ( calcJacobian ) THEN + CALL ED_CopyInput( u_ED, u_ED_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOutput( y_ED, y_ED_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyInput( u_HD, u_HD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOutput( y_HD, y_HD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + !---------------------------------------------------------------------------------------------------- + ! set up u vector, using local initial guesses: + !---------------------------------------------------------------------------------------------------- + + ! make hydrodyn inputs consistant with elastodyn outputs + ! (do this because we're using outputs in the u vector): + CALL Transfer_PlatformMotion_to_HD(y_ED_input%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) ! get u_HD from y_ED_input + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + u( 1: 3) = u_ED%PlatformPtMesh%Force(:,1) / p_FAST%UJacSclFact + u( 4: 6) = u_ED%PlatformPtMesh%Moment(:,1) / p_FAST%UJacSclFact + u( 7: 9) = y_ED_input%PlatformPtMesh%TranslationAcc(:,1) + u(10:12) = y_ED_input%PlatformPtMesh%RotationAcc(:,1) + + K = 0 + + DO + + !------------------------------------------------------------------------------------------------- + ! Calculate outputs at this_time, based on inputs at this_time + !------------------------------------------------------------------------------------------------- + + CALL ED_CalcOutput( this_time, u_ED, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED, m_ED, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL HydroDyn_CalcOutput( this_time, u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( K >= p_FAST%KMax ) EXIT + + + !------------------------------------------------------------------------------------------------- + ! Calculate Jacobian: partial U/partial u: + ! (note that we don't want to change u_ED or u_HD here) + !------------------------------------------------------------------------------------------------- + + CALL U_ED_HD_Residual(y_ED, y_HD, u, Fn_U_Resid) ! U_ED_HD_Residual checks for error + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + IF ( calcJacobian ) THEN + + !............................... + ! Get ElastoDyn's contribution: + !............................... + DO i=1,6 !call ED_CalcOutput + + CALL ED_CopyInput( u_ED, u_ED_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u( i, u_perturb, u_ED_perturb=u_ED_perturb, perturb=ThisPerturb ) ! perturb u and u_ED by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL ED_CalcOutput( this_time, u_ED_perturb, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED_perturb, m_ED, ErrStat2, ErrMsg2 ) !calculate y_ED_perturb + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL U_ED_HD_Residual(y_ED_perturb, y_HD, u_perturb, Fn_U_perturb) ! get this perturbation, U_perturb + IF ( ErrStat >= AbortErrLev ) RETURN ! U_ED_HD_Residual checks for error + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO ! ElastoDyn contribution ( columns 1-6 ) + + !............................... + ! Get HydroDyn's contribution: + !............................... + DO i=7,12 !call HD_CalcOutput + + ! we want to perturb u_HD, but we're going to perturb the input y_ED and transfer that to HD to get u_HD + CALL ED_CopyOutput( y_ED_input, y_ED_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u( i, u_perturb, y_ED_perturb=y_ED_perturb, perturb=ThisPerturb ) ! perturb u and y_ED by ThisPerturb [routine sets ThisPerturb] + CALL Transfer_PlatformMotion_to_HD( y_ED_perturb%PlatformPtMesh, u_HD_perturb, MeshMapData, ErrStat2, ErrMsg2 ) ! get u_HD_perturb + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! calculate outputs with perturbed inputs: + CALL HydroDyn_CalcOutput( this_time, u_HD_perturb, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD_perturb, m_HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL U_ED_HD_Residual(y_ED, y_HD_perturb, u_perturb, Fn_U_perturb) ! get this perturbation ! U_ED_HD_Residual checks for error + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO ! HydroDyn contribution ( columns 7-12 ) + +#ifdef OUTPUT_ADDEDMASS + UnAM = -1 + CALL GetNewUnit( UnAM, ErrStat, ErrMsg ) + CALL OpenFOutFile( UnAM, TRIM(p_FAST%OutFileRoot)//'.AddedMassMatrix', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + AddedMassMatrix = MeshMapData%Jacobian_Opt1(1:6,7:12) * p_FAST%UJacSclFact + CALL WrMatrix(AddedMassMatrix,UnAM, p_FAST%OutFmt) + CLOSE( UnAM ) +#endif +#ifdef OUTPUT_JACOBIAN + UnJac = -1 + CALL GetNewUnit( UnJac, ErrStat2, ErrMsg2 ) + CALL OpenFOutFile( UnJac, TRIM(p_FAST%OutFileRoot)//'.'//TRIM(num2lstr(this_time))//'.Jacobian2', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + CALL WrFileNR(UnJac, ' ') + CALL WrFileNR(UnJac, ' ElastoDyn_Force_X') + CALL WrFileNR(UnJac, ' ElastoDyn_Force_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_Force_Z') + CALL WrFileNR(UnJac, ' ElastoDyn_Moment_X') + CALL WrFileNR(UnJac, ' ElastoDyn_Moment_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_Moment_Z') + + CALL WrFileNR(UnJac, ' y_ED_TranslationAcc_X') + CALL WrFileNR(UnJac, ' y_ED_TranslationAcc_Y') + CALL WrFileNR(UnJac, ' y_ED_TranslationAcc_Z') + CALL WrFileNR(UnJac, ' y_ED_RotationAcc_X') + CALL WrFileNR(UnJac, ' y_ED_RotationAcc_Y') + CALL WrFileNR(UnJac, ' y_ED_RotationAcc_Z') + WRITE(UnJac,'()') + + CALL WrMatrix(MeshMapData%Jacobian_Opt1,UnJac, p_FAST%OutFmt) + CLOSE( UnJac ) +#endif + + + ! Get the LU decomposition of this matrix using a LAPACK routine: + ! The result is of the form MeshMapDat%Jacobian_Opt1 = P * L * U + + CALL LAPACK_getrf( M=NumInputs, N=NumInputs, A=MeshMapData%Jacobian_Opt1, IPIV=MeshMapData%Jacobian_pivot, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + END IF + + !------------------------------------------------------------------------------------------------- + ! Solve for delta u: Jac*u_delta = - Fn_U_Resid + ! using the LAPACK routine + !------------------------------------------------------------------------------------------------- + + u_delta = -Fn_U_Resid + CALL LAPACK_getrs( TRANS='N', N=NumInputs, A=MeshMapData%Jacobian_Opt1, IPIV=MeshMapData%Jacobian_pivot, B=u_delta, & + ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! check for error, update inputs (u_ED and u_HD), and iterate again + !------------------------------------------------------------------------------------------------- + +! IF ( DOT_PRODUCT(u_delta, u_delta) <= TOL_Squared ) EXIT + + u = u + u_delta + + u_ED%PlatformPtMesh%Force( :,1) = u_ED%PlatformPtMesh%Force( :,1) + u_delta( 1: 3) * p_FAST%UJacSclFact + u_ED%PlatformPtMesh%Moment(:,1) = u_ED%PlatformPtMesh%Moment(:,1) + u_delta( 4: 6) * p_FAST%UJacSclFact + y_ED_input%PlatformPtMesh%TranslationAcc(:,1) = y_ED_input%PlatformPtMesh%TranslationAcc(:,1) + u_delta( 7: 9) + y_ED_input%PlatformPtMesh%RotationAcc( :,1) = y_ED_input%PlatformPtMesh%RotationAcc( :,1) + u_delta(10:12) + + CALL Transfer_PlatformMotion_to_HD( y_ED_input%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) ! get u_HD with u_delta changes + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + K = K + 1 + + END DO ! K + + + CALL CleanUp() + +CONTAINS + !............................................................................................................................... + SUBROUTINE Perturb_u( n, u_perturb, u_ED_perturb, y_ED_perturb, perturb ) + ! This routine perturbs the nth element of the u array (and ED input/output it corresponds to) + !............................................................................................................................... +! REAL( ReKi ), INTENT(IN) :: this_U(NumInputs) + INTEGER( IntKi ) , INTENT(IN ) :: n + REAL( ReKi ) , INTENT(INOUT) :: u_perturb(numInputs) + TYPE(ED_InputType) , OPTIONAL , INTENT(INOUT) :: u_ED_perturb ! System inputs (needed only when 1 <= n <= 6) + TYPE(ED_OutputType), OPTIONAL , INTENT(INOUT) :: y_ED_perturb ! System outputs (needed only when 7 <= n <= 12) + REAL( ReKi ) , INTENT( OUT) :: perturb + + if ( n <= 6 ) then ! ED u + + if ( n <= 3 ) then + perturb = GetPerturb( u_ED_perturb%PlatformPtMesh%Force(n ,1) ) + u_ED_perturb%PlatformPtMesh%Force(n ,1) = u_ED_perturb%PlatformPtMesh%Force(n ,1) + perturb * p_FAST%UJacSclFact + else + perturb = GetPerturb( u_ED_perturb%PlatformPtMesh%Moment(n-3,1) ) + u_ED_perturb%PlatformPtMesh%Moment(n-3,1) = u_ED_perturb%PlatformPtMesh%Moment(n-3,1) + perturb * p_FAST%UJacSclFact + end if + + else ! ED y = HD u + + if ( n <= 9 ) then + perturb = GetPerturb( y_ED_perturb%PlatformPtMesh%TranslationAcc(n-6,1) ) + y_ED_perturb%PlatformPtMesh%TranslationAcc(n-6,1) = y_ED_perturb%PlatformPtMesh%TranslationAcc(n-6,1) + perturb + else + perturb = GetPerturb( y_ED_perturb%PlatformPtMesh%RotationAcc(n-9,1) ) + y_ED_perturb%PlatformPtMesh%RotationAcc( n-9,1) = y_ED_perturb%PlatformPtMesh%RotationAcc( n-9,1) + perturb + end if + + end if + + u_perturb(n) = u_perturb(n) + perturb + + + END SUBROUTINE Perturb_u + !............................................................................................................................... + SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) + !............................................................................................................................... + + TYPE(ED_OutputType), TARGET , INTENT(IN ) :: y_ED2 ! System outputs + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y_HD2 ! System outputs + REAL(ReKi) , INTENT(IN ) :: u_in(NumInputs) + REAL(ReKi) , INTENT( OUT) :: U_Resid(NumInputs) + + TYPE(MeshType), POINTER :: PlatformMotions + + PlatformMotions => y_ED2%PlatformPtMesh + + ! ! Transfer motions: + + !.................. + ! Set mooring line inputs (which don't have acceleration fields) + !.................. + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MAP_InputSolve( u_map, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MD_InputSolve( u_MD, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL FEAM_InputSolve( u_FEAM, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE + + MeshMapData%u_ED_PlatformPtMesh_2%Force = 0.0_ReKi + MeshMapData%u_ED_PlatformPtMesh_2%Moment = 0.0_ReKi + + END IF + + ! we use copies of the input meshes (we don't need to update values in the original data structures): + +!bjj: why don't we update u_HD2 here? shouldn't we update before using it to transfer the loads? + + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + + + U_Resid( 1: 3) = u_in( 1: 3) - MeshMapData%u_ED_PlatformPtMesh%Force(:,1) / p_FAST%UJacSclFact + U_Resid( 4: 6) = u_in( 4: 6) - MeshMapData%u_ED_PlatformPtMesh%Moment(:,1) / p_FAST%UJacSclFact + + U_Resid( 7: 9) = u_in( 7: 9) - PlatformMotions%TranslationAcc(:,1) + U_Resid(10:12) = u_in(10:12) - PlatformMotions%RotationAcc(:,1) + + PlatformMotions => NULL() + + END SUBROUTINE U_ED_HD_Residual + !............................................................................................................................... + SUBROUTINE CleanUp() + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + CALL ED_DestroyOutput(y_ED_input, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(RoutineName//'/ED_DestroyOutput: '//TRIM(ErrMsg3) ) + + IF ( calcJacobian ) THEN + CALL ED_DestroyInput( u_ED_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(RoutineName//'/ED_DestroyInput: '//TRIM(ErrMsg3) ) + CALL ED_DestroyOutput(y_ED_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(RoutineName//'/ED_DestroyOutput: '//TRIM(ErrMsg3) ) + + CALL HydroDyn_DestroyInput( u_HD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(RoutineName//'/HydroDyn_DestroyInput: '//TRIM(ErrMsg3) ) + CALL HydroDyn_DestroyOutput(y_HD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(RoutineName//'/HydroDyn_DestroyOutput: '//TRIM(ErrMsg3) ) + END IF + + + + END SUBROUTINE CleanUp + !............................................................................................................................... +END SUBROUTINE ED_HD_InputOutputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine performs the Input-Output solve for ED, SD, HD, BD, and/or the OrcaFlex Interface. +!! Note that this has been customized for the physics in the problems and is not a general solution. +SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & + , u_ED, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED, m_ED & + , u_SD, p_SD, x_SD, xd_SD, z_SD, OtherSt_SD, y_SD, m_SD & + , u_ExtPtfm,p_ExtPtfm,x_ExtPtfm,xd_ExtPtfm,z_ExtPtfm,OtherSt_ExtPtfm,y_ExtPtfm,m_ExtPtfm & + , u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD & + , u_BD, p_BD, x_BD, xd_BD, z_BD, OtherSt_BD, y_BD, m_BD & + , u_Orca, p_Orca, x_Orca, xd_Orca, z_Orca, OtherSt_Orca, y_Orca, m_Orca & + , u_MAP, y_MAP & + , u_FEAM, y_FEAM & + , u_MD, y_MD & + , u_IceF, y_IceF & + , u_IceD, y_IceD & + , MeshMapData , ErrStat, ErrMsg, WriteThisStep ) +!.................................................................................................................................. + + USE ElastoDyn + USE SubDyn + USE HydroDyn + USE BeamDyn + USE OrcaFlexInterface + + ! Passed variables + + REAL(DbKi) , INTENT(IN ) :: this_time !< The current simulation time (actual or time of prediction) + TYPE(FAST_ParameterType) , INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + LOGICAL , INTENT(IN ) :: calcJacobian !< Should we calculate Jacobians this time? + + !ElastoDyn: + TYPE(ED_ContinuousStateType) , INTENT(IN ) :: x_ED !< Continuous states + TYPE(ED_DiscreteStateType) , INTENT(IN ) :: xd_ED !< Discrete states + TYPE(ED_ConstraintStateType) , INTENT(IN ) :: z_ED !< Constraint states + TYPE(ED_OtherStateType) , INTENT(IN ) :: OtherSt_ED !< Other states + TYPE(ED_ParameterType) , INTENT(IN ) :: p_ED !< Parameters + TYPE(ED_InputType) , INTENT(INOUT) :: u_ED !< System inputs + TYPE(ED_OutputType), TARGET , INTENT(INOUT) :: y_ED !< System outputs + TYPE(ED_MiscVarType) , INTENT(INOUT) :: m_ED !< misc/optimization variables + + !BeamDyn (one instance per blade): + TYPE(BD_ContinuousStateType) , INTENT(IN ) :: x_BD(:) !< Continuous states + TYPE(BD_DiscreteStateType) , INTENT(IN ) :: xd_BD(:) !< Discrete states + TYPE(BD_ConstraintStateType) , INTENT(IN ) :: z_BD(:) !< Constraint states + TYPE(BD_OtherStateType) , INTENT(IN ) :: OtherSt_BD(:) !< Other/optimization states + TYPE(BD_ParameterType) , INTENT(IN ) :: p_BD(:) !< Parameters + TYPE(BD_InputType) , INTENT(INOUT) :: u_BD(:) !< System inputs + TYPE(BD_OutputType) , INTENT(INOUT) :: y_BD(:) !< System outputs + TYPE(BD_MiscVarType) , INTENT(INOUT) :: m_BD(:) !< misc/optimization variables + + !SubDyn: + TYPE(SD_ContinuousStateType) , INTENT(IN ) :: x_SD !< Continuous states + TYPE(SD_DiscreteStateType) , INTENT(IN ) :: xd_SD !< Discrete states + TYPE(SD_ConstraintStateType) , INTENT(IN ) :: z_SD !< Constraint states + TYPE(SD_OtherStateType) , INTENT(IN ) :: OtherSt_SD !< Other states + TYPE(SD_ParameterType) , INTENT(IN ) :: p_SD !< Parameters + TYPE(SD_InputType) , INTENT(INOUT) :: u_SD !< System inputs + TYPE(SD_OutputType) , INTENT(INOUT) :: y_SD !< System outputs + TYPE(SD_MiscVarType) , INTENT(INOUT) :: m_SD !< misc/optimization variables + + !ExtPtfm: + TYPE(ExtPtfm_ContinuousStateType) , INTENT(IN ) :: x_ExtPtfm !< Continuous states + TYPE(ExtPtfm_DiscreteStateType) , INTENT(IN ) :: xd_ExtPtfm !< Discrete states + TYPE(ExtPtfm_ConstraintStateType) , INTENT(IN ) :: z_ExtPtfm !< Constraint states + TYPE(ExtPtfm_OtherStateType) , INTENT(IN ) :: OtherSt_ExtPtfm !< Other states + TYPE(ExtPtfm_ParameterType) , INTENT(IN ) :: p_ExtPtfm !< Parameters + TYPE(ExtPtfm_InputType) , INTENT(INOUT) :: u_ExtPtfm !< System inputs + TYPE(ExtPtfm_OutputType) , INTENT(INOUT) :: y_ExtPtfm !< System outputs + TYPE(ExtPtfm_MiscVarType) , INTENT(INOUT) :: m_ExtPtfm !< misc/optimization variables + + !HydroDyn: + TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x_HD !< Continuous states + TYPE(HydroDyn_DiscreteStateType) , INTENT(IN ) :: xd_HD !< Discrete states + TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z_HD !< Constraint states + TYPE(HydroDyn_OtherStateType) , INTENT(INOUT) :: OtherSt_HD !< Other states + TYPE(HydroDyn_ParameterType) , INTENT(IN ) :: p_HD !< Parameters + TYPE(HydroDyn_InputType) , INTENT(INOUT) :: u_HD !< System inputs + TYPE(HydroDyn_OutputType) , INTENT(INOUT) :: y_HD !< System outputs + TYPE(HydroDyn_MiscVarType) , INTENT(INOUT) :: m_HD !< misc/optimization variables + + !OrcaFlex: + TYPE(Orca_ContinuousStateType), INTENT(IN ) :: x_Orca !< Continuous states + TYPE(Orca_DiscreteStateType) , INTENT(IN ) :: xd_Orca !< Discrete states + TYPE(Orca_ConstraintStateType), INTENT(IN ) :: z_Orca !< Constraint states + TYPE(Orca_OtherStateType) , INTENT(IN ) :: OtherSt_Orca !< Other states + TYPE(Orca_ParameterType) , INTENT(IN ) :: p_Orca !< Parameters + TYPE(Orca_InputType) , INTENT(INOUT) :: u_Orca !< System inputs + TYPE(Orca_OutputType) , INTENT(INOUT) :: y_Orca !< System outputs + TYPE(Orca_MiscVarType) , INTENT(INOUT) :: m_Orca !< misc/optimization variables + + + ! MAP/FEAM/MoorDyn/IceFloe/IceDyn: + TYPE(MAP_OutputType), INTENT(IN ) :: y_MAP !< MAP outputs + TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< MAP inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(FEAM_OutputType), INTENT(IN ) :: y_FEAM !< FEAM outputs + TYPE(FEAM_InputType), INTENT(INOUT) :: u_FEAM !< FEAM inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(MD_OutputType), INTENT(IN ) :: y_MD !< MoorDyn outputs + TYPE(MD_InputType), INTENT(INOUT) :: u_MD !< MoorDyn inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(IceFloe_OutputType), INTENT(IN ) :: y_IceF !< IceFloe outputs + TYPE(IceFloe_InputType), INTENT(INOUT) :: u_IceF !< IceFloe inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + TYPE(IceD_OutputType), INTENT(IN ) :: y_IceD(:) !< IceDyn outputs + TYPE(IceD_InputType), INTENT(INOUT) :: u_IceD(:) !< IceDyn inputs (INOUT just because I don't want to use another tempoarary mesh and we'll overwrite this later) + + TYPE(FAST_ModuleMapType) , INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + ! Local variables: + REAL(ReKi), PARAMETER :: TOL_Squared = (1.0E-4)**2 !not currently used because KMax = 1 + REAL(ReKi) :: ThisPerturb ! an arbitrary perturbation (these are linear, so it shouldn't matter) + + CHARACTER(*), PARAMETER :: RoutineName = 'FullOpt1_InputOutputSolve' + +!bjj: store these so that we don't reallocate every time? + REAL(ReKi) :: u( p_FAST%SizeJac_Opt1(1)) ! size of loads/accelerations passed between the 6 modules + REAL(ReKi) :: u_perturb( p_FAST%SizeJac_Opt1(1)) ! size of loads/accelerations passed between the 6 modules + REAL(ReKi) :: u_delta( p_FAST%SizeJac_Opt1(1)) ! size of loads/accelerations passed between the 6 modules + REAL(ReKi) :: Fn_U_perturb(p_FAST%SizeJac_Opt1(1)) ! value of U with perturbations + REAL(ReKi) :: Fn_U_Resid( p_FAST%SizeJac_Opt1(1)) ! Residual of U + + TYPE(ED_InputType) :: u_ED_perturb ! Perturbed system inputs + TYPE(ED_OutputType) :: y_ED_perturb ! Perturbed system outputs + TYPE(SD_InputType) :: u_SD_perturb ! Perturbed system inputs + TYPE(SD_OutputType) :: y_SD_perturb ! Perturbed system outputs + TYPE(HydroDyn_InputType) :: u_HD_perturb ! Perturbed system inputs + TYPE(HydroDyn_OutputType) :: y_HD_perturb ! Perturbed system outputs + TYPE(BD_InputType) :: u_BD_perturb ! Perturbed system inputs + TYPE(BD_OutputType), ALLOCATABLE :: y_BD_perturb(:) ! Perturbed system outputs + TYPE(Orca_InputType) :: u_Orca_perturb ! Perturbed system inputs + TYPE(Orca_OutputType) :: y_Orca_perturb ! Perturbed system outputs + TYPE(ExtPtfm_InputType) :: u_ExtPtfm_perturb ! Perturbed system inputs + TYPE(ExtPtfm_OutputType) :: y_ExtPtfm_perturb ! Perturbed system outputs + + + INTEGER(IntKi) :: i,j ! loop counters (jacobian column number) + INTEGER(IntKi) :: nb ! loop counter (blade number) + INTEGER(IntKi) :: K ! Input-output-solve iteration counter + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + TYPE(MeshType), POINTER :: PlatformMotionMesh + +#ifdef OUTPUT_ADDEDMASS + REAL(ReKi) :: AddedMassMatrix(6,6) + INTEGER :: UnAM + INTEGER :: AMIndx +#endif +#ifdef OUTPUT_JACOBIAN + INTEGER :: UnJac + INTEGER :: TmpIndx +#endif + + LOGICAL :: GetWriteOutput ! flag to determine if we need WriteOutputs from this call to CalcOutput + + ! Note: p_FAST%UJacSclFact is a scaling factor that gets us similar magnitudes between loads and accelerations... + +!bjj: note, that this routine may have a problem if there is remapping done + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------------------------------- + ! Some record keeping stuff: + !---------------------------------------------------------------------------------------------------- + + ! Local copies for perturbing inputs and outputs (computing Jacobian): + IF ( calcJacobian ) THEN + + CALL ED_CopyInput( u_ED, u_ED_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_ED_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOutput( y_ED, y_ED_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_ED_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CopyInput( u_SD, u_SD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_SD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOutput( y_SD, y_SD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_SD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CopyInput( u_ExtPtfm, u_ExtPtfm_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_ExtPtfm_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOutput( y_ExtPtfm, y_ExtPtfm_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_ExtPtfm_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CopyInput( u_HD, u_HD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_HD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOutput( y_HD, y_HD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_HD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + ALLOCATE( y_BD_perturb(p_FAST%nBeams) , STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat( ErrID_Fatal, 'Error allocating y_BD_perturb.', ErrStat, ErrMsg, RoutineName ) + call CleanUp() + return + end if + + !bjj: if this mesh could have different number of nodes per instance, we'd need an array. (but, it's a single point) + CALL BD_CopyInput( u_BD(1), u_BD_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_BD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + do nb=1,p_FAST%nBeams + CALL BD_CopyOutput( y_BD(nb), y_BD_perturb(nb), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_BD_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do + + END IF + + IF ( p_FAST%CompMooring == Module_Orca ) THEN + CALL Orca_CopyInput( u_Orca, u_Orca_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'u_Orca_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyOutput( y_Orca, y_Orca_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, 'y_Orca_perturb:'//ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + END IF + + !---------------------------------------------------------------------------------------------------- + ! set up u vector, using local initial guesses: + !---------------------------------------------------------------------------------------------------- + + ! we need BeamDyn input mesh to be an array of meshes, so first we'll copy into temporary storage: + DO nb=1,p_FAST%nBeams + call MeshCopy( u_BD(nb)%RootMotion, MeshMapData%u_BD_RootMotion(nb), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + CALL Create_FullOpt1_UVector(u, u_ED%PlatformPtMesh, u_SD%TPMesh, u_SD%LMesh, u_HD%Morison%LumpedMesh, & + u_HD%Morison%DistribMesh, u_HD%Mesh, u_ED%HubPtLoad, MeshMapData%u_BD_RootMotion, u_Orca%PtfmMesh, & + u_ExtPtfm%PtfmMesh, p_FAST ) + + K = 0 + + DO + + !------------------------------------------------------------------------------------------------- + ! Calculate outputs at this_time, based on inputs at this_time + !------------------------------------------------------------------------------------------------- + GetWriteOutput = WriteThisStep .and. K >= p_FAST%KMax ! we need this only on the last call to BD + + CALL ED_CalcOutput( this_time, u_ED, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED, m_ED, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CalcOutput( this_time, u_SD, p_SD, x_SD, xd_SD, z_SD, OtherSt_SD, y_SD, m_SD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CalcOutput( this_time, u_ExtPtfm, p_ExtPtfm, x_ExtPtfm, xd_ExtPtfm, z_ExtPtfm, OtherSt_ExtPtfm, & + y_ExtPtfm, m_ExtPtfm, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CalcOutput( this_time, u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + do nb=1,p_FAST%nBeams + CALL BD_CalcOutput( this_time, u_BD(nb), p_BD(nb), x_BD(nb), xd_BD(nb), z_BD(nb), OtherSt_BD(nb), y_BD(nb), m_BD(nb), ErrStat2, ErrMsg2, GetWriteOutput ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do + END IF + + IF ( p_FAST%CompMooring == Module_Orca ) THEN + CALL Orca_CalcOutput( this_time, u_Orca, p_Orca, x_Orca, xd_Orca, z_Orca, OtherSt_Orca, y_Orca, m_Orca, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + IF ( K >= p_FAST%KMax ) EXIT + + + !------------------------------------------------------------------------------------------------- + ! Calculate Jacobian: partial U/partial u: + ! (note that we don't want to change u_ED, u_SD, u_HD, u_BD, u_ExtPtfm, or u_Orca, here) + !------------------------------------------------------------------------------------------------- + + CALL U_FullOpt1_Residual(y_ED, y_SD, y_HD, y_BD, y_Orca, y_ExtPtfm, u, Fn_U_Resid) !May set errors here... + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + IF ( calcJacobian ) THEN + i = 0 + + !............................... + ! Get ElastoDyn's contribution: + !............................... + DO j=1,p_FAST%SizeJac_Opt1(2) !call ED_CalcOutput + i = i + 1 + + ! perturb u_ED: + CALL ED_CopyInput( u_ED, u_ED_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_ED_perturb=u_ED_perturb, perturb=ThisPerturb ) ! perturb u and u_ED by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL ED_CalcOutput( this_time, u_ED_perturb, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED_perturb, m_ED, ErrStat2, ErrMsg2 ) !calculate y_ED_perturb + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL U_FullOpt1_Residual(y_ED_perturb, y_SD, y_HD, y_BD, y_Orca, y_ExtPtfm, u_perturb, Fn_U_perturb) ! get this perturbation, U_perturb + + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO ! ElastoDyn contribution ( columns 1-p_FAST%SizeJac_Opt1(2) ) + + !............................... + ! Get SubDyn's contribution: (note if p_FAST%CompSub /= Module_SD, SizeJac_Opt1(3) = 0) + !............................... + DO j=1,p_FAST%SizeJac_Opt1(3) !call SD_CalcOutput + i = i + 1 ! i = j + p_FAST%SizeJac_Opt1(2) + + ! perturb u_SD: + CALL SD_CopyInput( u_SD, u_SD_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_SD_perturb=u_SD_perturb, perturb=ThisPerturb ) ! perturb u and u_SD by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL SD_CalcOutput( this_time, u_SD_perturb, p_SD, x_SD, xd_SD, z_SD, OtherSt_SD, y_SD_perturb, m_SD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL U_FullOpt1_Residual(y_ED, y_SD_perturb, y_HD, y_BD, y_Orca, y_ExtPtfm, u_perturb, Fn_U_perturb) ! get this perturbation + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO ! SubDyn contribution + + + !............................... + ! Get HydroDyn's contribution: (note if p_FAST%CompHydro /= Module_HD, SizeJac_Opt1(4) = 0) + !............................... + DO j=1,p_FAST%SizeJac_Opt1(4) !call HydroDyn_CalcOutput + i = i + 1 ! i = j + p_FAST%SizeJac_Opt1(2) + p_FAST%SizeJac_Opt1(3) + + ! perturb u_HD: + CALL HydroDyn_CopyInput( u_HD, u_HD_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_HD_perturb=u_HD_perturb, perturb=ThisPerturb ) ! perturb u and u_HD by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL HydroDyn_CalcOutput( this_time, u_HD_perturb, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD_perturb, m_HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL U_FullOpt1_Residual(y_ED, y_SD, y_HD_perturb, y_BD, y_Orca, y_ExtPtfm, u_perturb, Fn_U_perturb) ! get this perturbation + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO !HydroDyn contribution + + !............................... + ! Get BeamDyn's contribution: (note if p_FAST%CompElast /= Module_BD, SizeJac_Opt1(5) = 0) + !............................... + DO nb=1,p_FAST%nBeams + CALL BD_CopyOutput(y_BD(nb),y_BD_perturb(nb),MESH_UPDATECOPY,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + DO nb=1,p_FAST%nBeams + + ! make sure we perturb the outputs from only the current blade (overwrite the previous perturbation with y_BD values) + if (nb > 1) then + CALL BD_CopyOutput( y_BD(nb-1), y_BD_perturb(nb-1), MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + + DO j=1,p_FAST%SizeJac_Opt1(4+nb) !call BD_CalcOutput + i = i + 1 ! i = j + sum(p_FAST%SizeJac_Opt1(2:3+nb)) + ! perturb u_BD: + CALL BD_CopyInput( u_BD(nb), u_BD_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_BD_perturb=u_BD_perturb, perturb=ThisPerturb ) ! perturb u and u_HD by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL BD_CalcOutput( this_time, u_BD_perturb, p_BD(nb), x_BD(nb), xd_BD(nb), z_BD(nb), OtherSt_BD(nb), y_BD_perturb(nb), m_BD(nb), ErrStat2, ErrMsg2, .false. ) ! We don't use the WriteOutput when computing the Jacobian + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL U_FullOpt1_Residual(y_ED, y_SD, y_HD, y_BD_perturb, y_Orca, y_ExtPtfm, u_perturb, Fn_U_perturb) ! get this perturbation + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + END DO + + + END DO !BeamDyn contribution + + + !............................... + ! Get OrcaFlex's contribution: (note if p_FAST%CompMooring /= Module_Orca, SizeJac_Opt1(8) = 0) + !............................... + DO j=1,p_FAST%SizeJac_Opt1(8) !call Orca_CalcOutput + i = i + 1 + + ! perturb u_Orca: + CALL Orca_CopyInput( u_Orca, u_Orca_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_Orca_perturb=u_Orca_perturb, perturb=ThisPerturb ) ! perturb u and u_Orca by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL Orca_CalcOutput( this_time, u_Orca_perturb, p_Orca, x_Orca, xd_Orca, z_Orca, OtherSt_Orca, y_Orca_perturb, m_Orca, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL U_FullOpt1_Residual(y_ED, y_SD, y_HD, y_BD, y_Orca_perturb, y_ExtPtfm, u_perturb, Fn_U_perturb) ! get this perturbation + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO !OrcaFlex contribution + + + !............................... + ! Get ExtPtfm's contribution: (note if p_FAST%CompSub /= Module_ExtPtfm, SizeJac_Opt1(9) = 0) + !............................... + DO j=1,p_FAST%SizeJac_Opt1(9) !call ExtPtfm_CalcOutput + i = i + 1 + + ! perturb u_ExtPtfm: + CALL ExtPtfm_CopyInput( u_ExtPtfm, u_ExtPtfm_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + u_perturb = u + CALL Perturb_u_FullOpt1( p_FAST, MeshMapData%Jac_u_indx, i, u_perturb, u_ExtPtfm_perturb=u_ExtPtfm_perturb, perturb=ThisPerturb ) ! perturb u and u_ExtPtfm by ThisPerturb [routine sets ThisPerturb] + + ! calculate outputs with perturbed inputs: + CALL ExtPtfm_CalcOutput( this_time, u_ExtPtfm_perturb, p_ExtPtfm, x_ExtPtfm, xd_ExtPtfm, z_ExtPtfm, & + OtherSt_ExtPtfm, y_ExtPtfm_perturb, m_ExtPtfm, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL U_FullOpt1_Residual(y_ED, y_SD, y_HD, y_BD, y_Orca, y_ExtPtfm_perturb, u_perturb, Fn_U_perturb) ! get this perturbation + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + MeshMapData%Jacobian_Opt1(:,i) = (Fn_U_perturb - Fn_U_Resid) / ThisPerturb + + END DO !ExtPtfm contribution + +#ifdef OUTPUT_ADDEDMASS +IF (p_FAST%CompHydro == Module_HD ) THEN + UnAM = -1 + CALL GetNewUnit( UnAM, ErrStat2, ErrMsg2 ) + CALL OpenFOutFile( UnAM, TRIM(p_FAST%OutFileRoot)//'.AddedMassMatrix', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + AMIndx = p_FAST%SizeJac_Opt1(1) - 5 - sum(p_FAST%SizeJac_Opt1(5:)) !the start of the HydroDyn Mesh inputs in the Jacobian + AddedMassMatrix = MeshMapData%Jacobian_Opt1(1:6,AMIndx:(AMIndx+5)) * p_FAST%UJacSclFact + CALL WrMatrix(AddedMassMatrix,UnAM, p_FAST%OutFmt) + CLOSE( UnAM ) +END IF +#endif +#ifdef OUTPUT_JACOBIAN + UnJac = -1 + CALL GetNewUnit( UnJac, ErrStat2, ErrMsg2 ) + CALL OpenFOutFile( UnJac, TRIM(p_FAST%OutFileRoot)//'.'//TRIM(num2lstr(this_time))//'.Jacobian', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL WrFileNR(UnJac, ' ') + IF (p_FAST%CompHydro == Module_HD .or. p_FAST%CompSub /= Module_None .or. p_FAST%CompMooring == Module_Orca) then + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Force_X') + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Force_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Force_Z') + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Moment_X') + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Moment_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_Ptfm_Moment_Z') + end if + + IF (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) then + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Force_X') + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Force_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Force_Z') + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Moment_X') + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Moment_Y') + CALL WrFileNR(UnJac, ' ElastoDyn_hub_Moment_Z') + END IF + + + DO TmpIndx=1,u_SD%TPMesh%NNodes + CALL WrFileNR(UnJac, ' SD_TPMesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_TPMesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_TPMesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO TmpIndx=1,u_SD%TPMesh%NNodes + CALL WrFileNR(UnJac, ' SD_TPMesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_TPMesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_TPMesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + IF ( p_FAST%CompHydro == Module_HD ) THEN ! this SD mesh linked only when HD is enabled + DO TmpIndx=1,u_SD%LMesh%NNodes + CALL WrFileNR(UnJac, ' SD_LMesh_Force_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_LMesh_Force_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_LMesh_Force_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + DO TmpIndx=1,u_SD%LMesh%NNodes + CALL WrFileNR(UnJac, ' SD_LMesh_Moment_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_LMesh_Moment_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' SD_LMesh_Moment_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + END IF + + DO TmpIndx=1,u_HD%Morison%LumpedMesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + DO TmpIndx=1,u_HD%Morison%LumpedMesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO TmpIndx=1,u_HD%Morison%DistribMesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + DO TmpIndx=1,u_HD%Morison%DistribMesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO TmpIndx=1,u_HD%Mesh%NNodes + CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + DO TmpIndx=1,u_HD%Mesh%NNodes + CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO nb=1,p_FAST%nBeams + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_TranslationAcc_X') + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_TranslationAcc_Y') + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_TranslationAcc_Z') + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_RotationAcc_X') + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_RotationAcc_Y') + CALL WrFileNR(UnJac, ' BD_Root'//trim(num2lstr(nb))//'Motion_RotationAcc_Z') + END DO + + DO TmpIndx=1,u_Orca%PtfmMesh%NNodes + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO TmpIndx=1,u_Orca%PtfmMesh%NNodes + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' Orca_PtfmMesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + DO TmpIndx=1,u_ExtPtfm%PtfmMesh%NNodes + CALL WrFileNR(UnJac, ' ExtPtfm_PtfmMesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' ExtPtfm_PtfmMesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' ExtPtfm_PtfmMesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + END DO + + + WRITE(UnJac,'()') + + CALL WrMatrix(MeshMapData%Jacobian_Opt1,UnJac, p_FAST%OutFmt) + CLOSE( UnJac ) + +#endif + + + ! Get the LU decomposition of this matrix using a LAPACK routine: + ! The result is of the form MeshMapDat%Jacobian_Opt1 = P * L * U + + CALL LAPACK_getrf( M=p_FAST%SizeJac_Opt1(1), N=p_FAST%SizeJac_Opt1(1), & + A=MeshMapData%Jacobian_Opt1, IPIV=MeshMapData%Jacobian_pivot, & + ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + END IF + + !------------------------------------------------------------------------------------------------- + ! Solve for delta u: Jac*u_delta = - Fn_U_Resid + ! using the LAPACK routine + !------------------------------------------------------------------------------------------------- + + u_delta = -Fn_U_Resid + CALL LAPACK_getrs( TRANS="N", N=p_FAST%SizeJac_Opt1(1), A=MeshMapData%Jacobian_Opt1, & + IPIV=MeshMapData%Jacobian_pivot, B=u_delta, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + !------------------------------------------------------------------------------------------------- + ! check for error, update inputs (u_ED and u_HD), and iterate again + !------------------------------------------------------------------------------------------------- + +! IF ( DOT_PRODUCT(u_delta, u_delta) <= TOL_Squared ) EXIT + + u = u + u_delta + CALL Add_FullOpt1_u_delta( p_FAST, MeshMapData%Jac_u_indx, u_delta, u_ED, u_SD, u_HD, u_BD, u_Orca, u_ExtPtfm ) + + K = K + 1 + + END DO ! K + + !............................................... + ! This is effectively doing option 2, where we set the input velocities and displacements based on the outputs we just calculated + !............................................... + + PlatformMotionMesh => y_ED%PlatformPtMesh + + + ! BD motion inputs: (from ED) + IF (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + + ! Make copies of the accelerations we just solved for (so we don't overwrite them) + do nb = 1,p_FAST%nBeams + MeshMapData%u_BD_RootMotion(nb)%RotationAcc = u_BD(nb)%RootMotion%RotationAcc + MeshMapData%u_BD_RootMotion(nb)%TranslationAcc = u_BD(nb)%RootMotion%TranslationAcc + end do + + call Transfer_ED_to_BD(y_ED, u_BD, MeshMapData, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! put the acceleration data (calucluted in this routine) back + do nb = 1,p_FAST%nBeams + u_BD(nb)%RootMotion%RotationAcc = MeshMapData%u_BD_RootMotion(nb)%RotationAcc + u_BD(nb)%RootMotion%TranslationAcc = MeshMapData%u_BD_RootMotion(nb)%TranslationAcc + end do + + END IF + + + !............... + ! HD motion inputs: (from SD and ED) + IF (p_FAST%CompHydro == Module_HD ) THEN + + ! Make copies of the accelerations we just solved for (so we don't overwrite them) + IF (MeshMapData%u_HD_M_LumpedMesh%Committed) THEN + MeshMapData%u_HD_M_LumpedMesh%RotationAcc = u_HD%Morison%LumpedMesh%RotationAcc + MeshMapData%u_HD_M_LumpedMesh%TranslationAcc = u_HD%Morison%LumpedMesh%TranslationAcc + ENDIF + IF (MeshMapData%u_HD_M_DistribMesh%Committed) THEN + MeshMapData%u_HD_M_DistribMesh%RotationAcc = u_HD%Morison%DistribMesh%RotationAcc + MeshMapData%u_HD_M_DistribMesh%TranslationAcc = u_HD%Morison%DistribMesh%TranslationAcc + ENDIF + IF (MeshMapData%u_HD_Mesh%Committed) THEN + MeshMapData%u_HD_Mesh%RotationAcc = u_HD%Mesh%RotationAcc + MeshMapData%u_HD_Mesh%TranslationAcc = u_HD%Mesh%TranslationAcc + ENDIF + + ! transfer the output data to inputs + + IF ( p_FAST%CompSub == Module_SD ) THEN + ! Map SD outputs to HD inputs (keeping the accelerations we just calculated) + + CALL Transfer_SD_to_HD( y_SD, u_HD%Morison%LumpedMesh, u_HD%Morison%DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Map ED outputs to HD inputs (keeping the accelerations we just calculated): + + CALL Transfer_Point_to_Point( PlatformMotionMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE + + CALL Transfer_PlatformMotion_to_HD( PlatformMotionMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + + ! put the acceleration data (calucluted in this routine) back + IF (MeshMapData%u_HD_M_LumpedMesh%Committed) THEN + u_HD%Morison%LumpedMesh%RotationAcc = MeshMapData%u_HD_M_LumpedMesh%RotationAcc + u_HD%Morison%LumpedMesh%TranslationAcc = MeshMapData%u_HD_M_LumpedMesh%TranslationAcc + ENDIF + IF (MeshMapData%u_HD_M_DistribMesh%Committed) THEN + u_HD%Morison%DistribMesh%RotationAcc = MeshMapData%u_HD_M_DistribMesh%RotationAcc + u_HD%Morison%DistribMesh%TranslationAcc = MeshMapData%u_HD_M_DistribMesh%TranslationAcc + ENDIF + IF (MeshMapData%u_HD_Mesh%Committed) THEN + u_HD%Mesh%RotationAcc = MeshMapData%u_HD_Mesh%RotationAcc + u_HD%Mesh%TranslationAcc = MeshMapData%u_HD_Mesh%TranslationAcc + ENDIF + + !...... + + END IF + + IF ( p_FAST%CompSub == Module_SD ) THEN + !............... + ! SD motion inputs: (from ED) + + ! Map ED outputs to SD inputs (keeping the accelerations we just calculated): + + MeshMapData%u_SD_TPMesh%RotationAcc = u_SD%TPMesh%RotationAcc + MeshMapData%u_SD_TPMesh%TranslationAcc = u_SD%TPMesh%TranslationAcc + + CALL Transfer_Point_to_Point( PlatformMotionMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + u_SD%TPMesh%RotationAcc = MeshMapData%u_SD_TPMesh%RotationAcc + u_SD%TPMesh%TranslationAcc = MeshMapData%u_SD_TPMesh%TranslationAcc + + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + !............... + ! ExtPtfm motion inputs: (from ED) + + ! Map ED outputs to ExtPtfm inputs (keeping the accelerations we just calculated): + + MeshMapData%u_ExtPtfm_PtfmMesh%RotationAcc = u_ExtPtfm%PtfmMesh%RotationAcc + MeshMapData%u_ExtPtfm_PtfmMesh%TranslationAcc = u_ExtPtfm%PtfmMesh%TranslationAcc + + CALL Transfer_Point_to_Point( PlatformMotionMesh, u_ExtPtfm%PtfmMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + u_ExtPtfm%PtfmMesh%RotationAcc = MeshMapData%u_ExtPtfm_PtfmMesh%RotationAcc + u_ExtPtfm%PtfmMesh%TranslationAcc = MeshMapData%u_ExtPtfm_PtfmMesh%TranslationAcc + END IF + + + IF ( p_FAST%CompMooring == Module_Orca ) THEN + !............... + ! Orca motion inputs: (from ED) + + ! Map ED outputs to Orca inputs (keeping the accelerations we just calculated): + + MeshMapData%u_Orca_PtfmMesh%RotationAcc = u_Orca%PtfmMesh%RotationAcc + MeshMapData%u_Orca_PtfmMesh%TranslationAcc = u_Orca%PtfmMesh%TranslationAcc + + CALL Transfer_Point_to_Point( PlatformMotionMesh, u_Orca%PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + u_Orca%PtfmMesh%RotationAcc = MeshMapData%u_Orca_PtfmMesh%RotationAcc + u_Orca%PtfmMesh%TranslationAcc = MeshMapData%u_Orca_PtfmMesh%TranslationAcc + END IF + + !............................................... + ! We're finished + !............................................... + CALL CleanUp() + +CONTAINS + !............................................................................................................................... + SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, u_IN, U_Resid) + ! transfer outputs of ED, HD, SD, BD, and OrcaFlex (and any additional loads that get summed with them) into inputs for ED, HD, SD, BD, and OrcaFlex + !............................................................................................................................... + + TYPE(ED_OutputType), TARGET , INTENT(IN ) :: y_ED2 ! System outputs + TYPE(SD_OutputType) , INTENT(IN ) :: y_SD2 ! System outputs + TYPE(HydroDyn_OutputType) , INTENT(IN ) :: y_HD2 ! System outputs + TYPE(BD_OutputType) , INTENT(IN ) :: y_BD2(:) ! System outputs + TYPE(Orca_OutputType) , INTENT(IN ) :: y_Orca2 ! System outputs + TYPE(ExtPtfm_OutputType) , INTENT(IN ) :: y_ExtPtfm2 ! System outputs + REAL(ReKi) , INTENT(IN ) :: u_in(:) + REAL(ReKi) , INTENT( OUT) :: U_Resid(:) + + INTEGER(IntKi) :: i ! counter for ice leg and beamdyn loops + TYPE(MeshType), POINTER :: PlatformMotions + + PlatformMotions => y_ED2%PlatformPtMesh + + !.................. + ! Set mooring line and ice inputs (which don't have acceleration fields and aren't used elsewhere in this routine, thus we're using the actual inputs (not a copy) + ! Note that these values get overwritten at the completion of this routine.) + !.................. + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MAP_InputSolve( u_map, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MD_InputSolve( u_MD, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL FEAM_InputSolve( u_FEAM, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + + ! Map ED motion output to Orca inputs: + ! note: must be called before setting ED loads inputs (so that Orca motions are known for loads [moment] mapping) + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_Orca_PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + END IF + + + IF ( p_FAST%CompIce == Module_IceF ) THEN + + CALL IceFloe_InputSolve( u_IceF, y_SD2, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + DO i=1,p_FAST%numIceLegs + + CALL IceD_InputSolve( u_IceD(i), y_SD2, MeshMapData, i, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + END DO + + END IF + + IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + + ! Transfer ED motions to BD inputs: + call Transfer_ED_to_BD_tmp( y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) ! sets MeshMapData%u_BD_RootMotion(:) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Transfer BD loads to ED hub input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + MeshMapData%u_ED_HubPtLoad%Force = 0.0_ReKi + MeshMapData%u_ED_HubPtLoad%Moment = 0.0_ReKi + do i=1,p_FAST%nBeams + CALL Transfer_Point_to_Point( y_BD2(i)%ReactionForce, MeshMapData%u_ED_HubPtLoad_2, MeshMapData%BD_P_2_ED_P(i), ErrStat2, ErrMsg2, MeshMapData%u_BD_RootMotion(i), y_ED2%HubPtMotion) !u_BD_RootMotion and y_ED2%HubPtMotion contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_HubPtLoad%Force = MeshMapData%u_ED_HubPtLoad%Force + MeshMapData%u_ED_HubPtLoad_2%Force + MeshMapData%u_ED_HubPtLoad%Moment = MeshMapData%u_ED_HubPtLoad%Moment + MeshMapData%u_ED_HubPtLoad_2%Moment + end do + END IF + + + IF ( p_FAST%CompSub == Module_SD ) THEN + + IF ( p_FAST%CompHydro == Module_HD ) THEN + + ! initialize these SD loads inputs here in case HD is used (note from initialiazation that these meshes don't exist if HD isn't used) + MeshMapData%u_SD_LMesh%Force = 0.0_ReKi + MeshMapData%u_SD_LMesh%Moment = 0.0_ReKi + + + !.................. + ! Get HD inputs on Morison%LumpedMesh and Morison%DistribMesh + !.................. + + ! SD motions to HD: + CALL Transfer_SD_to_HD( y_SD2, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! Map ED motion output to HD inputs: + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !.................. + ! Get SD loads inputs (MeshMapData%u_HD_M_LumpedMesh and MeshMapData%u_HD_M_DistribMesh meshes must be set first) + !.................. + + ! Loads (outputs) from HD meshes transfered to SD LMesh (zero them out first because they get summed in Transfer_HD_to_SD) + + CALL Transfer_HD_to_SD( MeshMapData%u_SD_LMesh_2, MeshMapData%u_SD_LMesh, y_SD2%Y2Mesh, y_HD2, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + IF ( p_FAST%CompIce == Module_IceF ) THEN + + ! SD loads from IceFloe: + IF ( y_IceF%iceMesh%Committed ) THEN + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_IceF%iceMesh, MeshMapData%u_SD_LMesh_2, MeshMapData%IceF_P_2_SD_P, ErrStat2, ErrMsg2, u_IceF%iceMesh, y_SD2%Y2Mesh ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_SD_LMesh%Force = MeshMapData%u_SD_LMesh%Force + MeshMapData%u_SD_LMesh_2%Force + MeshMapData%u_SD_LMesh%Moment = MeshMapData%u_SD_LMesh%Moment + MeshMapData%u_SD_LMesh_2%Moment + +!... +#ifdef DEBUG_MESH_TRANSFER_ICE + if (.not. calcJacobian) then + CALL WrScr('********************************************************') + CALL WrScr('**** IceF to SD point-to-point *****') + CALL WrScr('********************************************************') + CALL WriteMappingTransferToFile(MeshMapData%u_SD_LMesh_2, y_SD2%Y2Mesh, u_IceF%iceMesh, y_IceF%iceMesh,& + MeshMapData%SD_P_2_IceF_P, MeshMapData%IceF_P_2_SD_P, & + 'SD_y2_IceF_Meshes_t'//TRIM(Num2LStr(this_time))//'.I.bin' ) + !print * + !pause + end IF +#endif + + END IF !Module_IceF + + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + ! SD loads from IceDyn: + DO i=1,p_FAST%numIceLegs + + IF ( y_IceD(i)%PointMesh%Committed ) THEN + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_IceD(i)%PointMesh, MeshMapData%u_SD_LMesh_2, MeshMapData%IceD_P_2_SD_P(i), ErrStat2, ErrMsg2, u_IceD(i)%PointMesh, y_SD2%Y2Mesh ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_SD_LMesh%Force = MeshMapData%u_SD_LMesh%Force + MeshMapData%u_SD_LMesh_2%Force + MeshMapData%u_SD_LMesh%Moment = MeshMapData%u_SD_LMesh%Moment + MeshMapData%u_SD_LMesh_2%Moment + + END IF + + END DO + + END IF ! Ice loading + + END IF ! HD is used (IceFloe/IceDyn can't be used unless HydroDyn is used) + + + + !.................. + ! Get SD motions input + !.................. + + ! Motions (outputs) at ED platform ref point transfered to SD transition piece (input): + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_SD_TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !.................. + ! Get ED loads input (from SD and possibly HD) + !.................. + + ! Loads (outputs) on the SD transition piece transfered to ED input location/mesh: + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_SD2%Y1Mesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_SD_TPMesh, PlatformMotions ) !MeshMapData%u_SD_TPMesh contains the orientations needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! WAMIT loads from HD get added to this load: + IF ( y_HD2%Mesh%Committed ) THEN + + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD2%Mesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions ) !u_SD contains the orientations needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + + END IF + + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN + + !.................. + ! Get ExtPtfm motions input + !.................. + + ! Motions (outputs) at ED platform ref point transfered to ExtPtfm PtfmMesh (input): + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_ExtPtfm_PtfmMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !.................. + ! Get ED loads input (from SD and possibly HD) + !.................. + + ! Loads (outputs) on the ExtPtfm platform mesh transfered to ED input location/mesh: + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_ExtPtfm2%PtfmMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_ExtPtfm_PtfmMesh, PlatformMotions ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSE IF ( p_FAST%CompHydro == Module_HD ) THEN + + !.................. + ! Get HD inputs on 3 meshes + !.................. + + ! Map ED motion outputs to HD inputs: + ! basically, we want to call Transfer_PlatformMotion_to_HD, except we have the meshes in a different data structure (not a copy of u_HD) + ! CALL Transfer_PlatformMotion_to_HD( y_ED2%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) + ! so, here are the transfers, again. + + + ! These are the motions for the lumped point loads associated the WAMIT body: + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body + if (MeshMapData%u_HD_M_LumpedMesh%Committed) then + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + + ! These are the motions for the line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body + if (MeshMapData%u_HD_M_DistribMesh%Committed) then + CALL Transfer_Point_to_Line2( PlatformMotions, MeshMapData%u_HD_M_DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + + !.................. + ! Get ED loads input (from HD only) + !.................. + + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ELSE + + ! When using OrcaFlex, we need to zero this out + MeshMapData%u_ED_PlatformPtMesh%Force = 0.0_ReKi + MeshMapData%u_ED_PlatformPtMesh%Moment = 0.0_ReKi + + END IF + + !.................. + ! Get remaining portion of ED loads input on MeshMapData%u_ED_PlatformPtMesh (must do this after MeshMapData%u_SD_TPMesh and MeshMapData%u_HD_Mesh are set) + ! at this point, MeshMapData%u_ED_PlatformPtMesh contains the portion of loads from SD and/or HD + !.................. + + + ! Get the loads for ED from a mooring module and add them: + IF ( p_FAST%CompMooring == Module_MAP ) THEN + CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + CALL Transfer_Point_to_Point( y_Orca2%PtfmMesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_Orca_PtfmMesh, PlatformMotions ) !u_Orca_PtfmMesh and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + END IF + + !.................. + ! Calculate the residual with these new inputs: + !.................. + + CALL Create_FullOpt1_UVector(U_Resid, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%u_SD_TPMesh, MeshMapData%u_SD_LMesh, & + MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData%u_HD_Mesh, & + MeshMapData%u_ED_HubPtLoad, MeshMapData%u_BD_RootMotion, MeshMapData%u_Orca_PtfmMesh, & + MeshMapData%u_ExtPtfm_PtfmMesh, p_FAST ) + + U_Resid = u_in - U_Resid + + PlatformMotions => NULL() + + END SUBROUTINE U_FullOpt1_Residual + !............................................................................................................................... + SUBROUTINE CleanUp() + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + IF ( calcJacobian ) THEN + CALL ED_DestroyInput( u_ED_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + CALL ED_DestroyOutput(y_ED_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + + CALL SD_DestroyInput( u_SD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + CALL SD_DestroyOutput(y_SD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + + CALL HydroDyn_DestroyInput( u_HD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + CALL HydroDyn_DestroyOutput(y_HD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + + CALL BD_DestroyInput( u_BD_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + if (allocated(y_BD_perturb)) then + do nb=1,size(y_BD_perturb) + CALL BD_DestroyOutput(y_BD_perturb(nb), ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + end do + deallocate(y_BD_perturb) + end if + + CALL Orca_DestroyInput( u_Orca_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + CALL Orca_DestroyOutput(y_Orca_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + + CALL ExtPtfm_DestroyInput( u_ExtPtfm_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + CALL ExtPtfm_DestroyOutput(y_ExtPtfm_perturb, ErrStat3, ErrMsg3 ) + IF (ErrStat3 /= ErrID_None) CALL WrScr(' '//RoutineName//TRIM(ErrMsg3) ) + + END IF + + + END SUBROUTINE CleanUp + !............................................................................................................................... +END SUBROUTINE FullOpt1_InputOutputSolve +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing subroutine Create_FullOpt1_UVector()! +SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_LumpedMesh, HD_M_DistribMesh, & + HD_WAMIT_Mesh, ED_HubPtLoad, u_BD, Orca_PtfmMesh, ExtPtfm_PtfmMesh, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType) , INTENT(INOUT) :: p_FAST !< FAST parameters + TYPE(FAST_ModuleMapType) , INTENT(INOUT) :: MeshMapData !< data that maps meshes together + + ! input meshes for each of the 4 modules: + TYPE(MeshType) , INTENT(IN ) :: ED_PlatformPtMesh !< ElastoDyn's PlatformPtMesh + TYPE(MeshType) , INTENT(IN ) :: ED_HubPtLoad !< ElastoDyn's HubPtLoad mesh + TYPE(MeshType) , INTENT(IN ) :: SD_TPMesh !< SubDyn's TP (transition piece) mesh + TYPE(MeshType) , INTENT(IN ) :: SD_LMesh !< SubDyn's LMesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_LumpedMesh !< HydroDyn's Morison Lumped Mesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_DistribMesh !< HydroDyn's Morison Distributed Mesh + TYPE(MeshType) , INTENT(IN ) :: HD_WAMIT_Mesh !< HydroDyn's WAMIT mesh + TYPE(BD_InputType) , INTENT(IN ) :: u_BD(:) !< inputs for each instance of the BeamDyn module (for the RootMotion meshes) + TYPE(MeshType) , INTENT(IN ) :: Orca_PtfmMesh !< OrcaFlex interface PtfmMesh + TYPE(MeshType) , INTENT(IN ) :: ExtPtfm_PtfmMesh !< ExtPtfm_MCKF interface PtfmMesh + + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Init_FullOpt1_Jacobian' + + ! local variables: + INTEGER(IntKi) :: i, j, k, index + + ErrStat = ErrID_None + ErrMsg = "" + + ! determine how many inputs there are between the 6 modules (ED, SD, HD, BD, Orca, ExtPtfm) + p_FAST%SizeJac_Opt1 = 0 ! initialize whole array + + if (p_FAST%CompHydro == Module_HD .or. p_FAST%CompSub /= Module_None .or. p_FAST%CompMooring == Module_Orca) then + p_FAST%SizeJac_Opt1(2) = ED_PlatformPtMesh%NNodes*6 ! ED inputs: 3 forces and 3 moments per node (only 1 node) + else + p_FAST%SizeJac_Opt1(2) = 0 + end if + + + p_FAST%SizeJac_Opt1(3) = SD_TPMesh%NNodes*6 ! SD inputs: 6 accelerations per node (size of SD input from ED) + IF ( p_FAST%CompHydro == Module_HD ) THEN + p_FAST%SizeJac_Opt1(3) = p_FAST%SizeJac_Opt1(3) & + + SD_LMesh%NNodes *6 ! SD inputs: 6 loads per node (size of SD input from HD) + END IF + + p_FAST%SizeJac_Opt1(4) = HD_M_LumpedMesh%NNodes *6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + + HD_M_DistribMesh%NNodes*6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + + HD_WAMIT_Mesh%NNodes*6 ! HD inputs: 6 accelerations per node (on the WAMIT mesh) + + IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN + p_FAST%SizeJac_Opt1(2) = p_FAST%SizeJac_Opt1(2) & + + ED_HubPtLoad%NNodes *6 ! ED inputs: 6 loads per node (size of ED input from BD) + + p_FAST%SizeJac_Opt1(5:7) = 0 ! assumes a max of 3 blades + do k=1,size(u_BD) + p_FAST%SizeJac_Opt1(4+k) = u_BD(k)%RootMotion%NNodes *6 ! BD inputs: 6 accelerations per node (size of BD input from ED) + end do + + END IF + + if ( p_FAST%CompMooring == Module_Orca ) then + p_FAST%SizeJac_Opt1(8) = Orca_PtfmMesh%NNodes*6 + else + p_FAST%SizeJac_Opt1(8) = 0 + end if + + if ( p_FAST%CompSub == Module_ExtPtfm ) then + p_FAST%SizeJac_Opt1(9) = ExtPtfm_PtfmMesh%NNodes*6 + else + p_FAST%SizeJac_Opt1(9) = 0 + end if + + + + p_FAST%SizeJac_Opt1(1) = sum( p_FAST%SizeJac_Opt1 ) ! all the inputs from these modules + + + ! allocate matrix to store jacobian + CALL AllocAry( MeshMapData%Jacobian_Opt1, p_FAST%SizeJac_Opt1(1), p_FAST%SizeJac_Opt1(1), "Jacobian for full option 1", ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! allocate matrix to store index to help us figure out what the ith value of the u vector really means + ALLOCATE ( MeshMapData%Jac_u_indx( p_FAST%SizeJac_Opt1(1), 3 ), STAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Cannot allocate Jac_u_indx.' + RETURN + END IF + + ! fill matrix to store index to help us figure out what the ith value of the u vector really means + ! ( see Create_FullOpt1_UVector() ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index of the acceleration/load field + ! column 3 is the node + + !............... + ! ED inputs: + !............... + + index = 1 + if (p_FAST%CompHydro == Module_HD .or. p_FAST%CompSub /= Module_None .or. p_FAST%CompMooring == Module_Orca) then + + do i=1,ED_PlatformPtMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 1 !Module/Mesh/Field: u_ED%PlatformPtMesh%Force = 1 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,ED_PlatformPtMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 2 !Module/Mesh/Field: u_ED%PlatformPtMesh%Moment = 2 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end if + + + if (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) then + + do i=1,ED_HubPtLoad%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 3 !Module/Mesh/Field: u_ED%HubPtMesh%Force = 3 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + + do i=1,ED_HubPtLoad%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 4 !Module/Mesh/Field: u_ED%HubPtMesh%Moment = 4 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end if + + + !............... + ! SD inputs: + !............... + + ! SD_TPMesh + do i=1,SD_TPMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 5 !Module/Mesh/Field: u_SD%TPMesh%TranslationAcc = 5 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,SD_TPMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 6 !Module/Mesh/Field: u_SD%TPMesh%RotationAcc = 6 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + IF ( p_FAST%CompHydro == Module_HD ) THEN ! this SD mesh linked only when HD is enabled + + ! SD_LMesh + do i=1,SD_LMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 7 !Module/Mesh/Field: u_SD%LMesh%Force = 7 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,SD_LMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 8 !Module/Mesh/Field: u_SD%LMesh%Moment = 8 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + END IF + + !............... + ! HD inputs: + !............... + + !(Morison%LumpedMesh) + do i=1,HD_M_LumpedMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 9 !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,HD_M_LumpedMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 10 !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + + !(Morison%DistribMesh) + do i=1,HD_M_DistribMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 11 !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,HD_M_DistribMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 12 !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + !(Mesh) + do i=1,HD_WAMIT_Mesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 13 !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,HD_WAMIT_Mesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 14 !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + !............... + ! BD inputs: + !............... + + if (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) then + + do k=1,size(u_BD) + + do i=1,u_BD(k)%RootMotion%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 13 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%TranslationAcc = 15 (k=1), 17 (k=2), 19 (k=3) + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,u_BD(k)%RootMotion%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 14 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%RotationAcc = 16 (k=1), 18 (k=2), 20 (k=3) + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + end do !k + + end if + + !............... + ! Orca inputs: + !............... + + ! Orca_PtfmMesh + do i=1,Orca_PtfmMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 21 !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,Orca_PtfmMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 22 !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + !............... + ! ExtPtfm inputs: + !............... + + ! ExtPtfm_PtfmMesh + do i=1,ExtPtfm_PtfmMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 23 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 23 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + do i=1,ExtPtfm_PtfmMesh%NNodes + do j=1,3 + MeshMapData%Jac_u_indx(index,1) = 24 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 24 + MeshMapData%Jac_u_indx(index,2) = j !index: j + MeshMapData%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + + +END SUBROUTINE Init_FullOpt1_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine basically packs the relevant parts of the modules' input meshes for use in this InputOutput solve. +!! Do not change the order of this packing without changing subroutine Init_FullOpt1_Jacobian()! +SUBROUTINE Create_FullOpt1_UVector(u, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_LumpedMesh, HD_M_DistribMesh, HD_WAMIT_Mesh, & + ED_HubPtLoad, BD_RootMotion, Orca_PtfmMesh, ExtPtfm_PtfmMesh, p_FAST ) +!.................................................................................................................................. + + REAL(ReKi) , INTENT(INOUT) :: u(:) !< output u vector + + ! input meshes for each of the 3 modules: + TYPE(MeshType) , INTENT(IN ) :: ED_PlatformPtMesh !< ElastoDyn PlatformPt mesh + TYPE(MeshType) , INTENT(IN ) :: SD_TPMesh !< SubDyn TP mesh + TYPE(MeshType) , INTENT(IN ) :: SD_LMesh !< SubDyn Lmesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_LumpedMesh !< HydroDyn Morison Lumped mesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_DistribMesh !< HydroDyn Morison distributed mesh + TYPE(MeshType) , INTENT(IN ) :: HD_WAMIT_Mesh !< HydroDyn WAMIT mesh + TYPE(MeshType) , INTENT(IN ) :: ED_HubPtLoad !< ElastoDyn HubPt mesh + TYPE(MeshType) , INTENT(IN ) :: BD_RootMotion(:) !< BeamDyn RootMotion meshes + TYPE(MeshType) , INTENT(IN ) :: Orca_PtfmMesh !< OrcaFlex interface PtfmMesh + TYPE(MeshType) , INTENT(IN ) :: ExtPtfm_PtfmMesh !< ExtPtfm interface PtfmMesh + + TYPE(FAST_ParameterType) , INTENT(IN ) :: p_FAST !< FAST parameters + + + ! local variables: + INTEGER(IntKi) :: i, k, indx_first, indx_last + + !............... + ! ED inputs: + !............... + if (p_FAST%CompHydro == Module_HD .or. p_FAST%CompSub /= Module_None .or. p_FAST%CompMooring == MODULE_Orca) then + u( 1: 3) = ED_PlatformPtMesh%Force(:,1) / p_FAST%UJacSclFact + u( 4: 6) = ED_PlatformPtMesh%Moment(:,1) / p_FAST%UJacSclFact + indx_first = 7 + else + indx_first = 1 + end if + + + if (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) then + + do i=1,ED_HubPtLoad%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = ED_HubPtLoad%Force(:,i) / p_FAST%UJacSclFact + indx_first = indx_last + 1 + end do + + do i=1,ED_HubPtLoad%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = ED_HubPtLoad%Moment(:,i) / p_FAST%UJacSclFact + indx_first = indx_last + 1 + end do + + end if + + + !............... + ! SD inputs (SD_TPMesh): + !............... + do i=1,SD_TPMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = SD_TPMesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,SD_TPMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = SD_TPMesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + if ( p_FAST%CompHydro == Module_HD ) then ! this SD mesh linked only when HD is enabled + ! SD inputs (SD_LMesh): + do i=1,SD_LMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = SD_LMesh%Force(:,i) / p_FAST%UJacSclFact + indx_first = indx_last + 1 + end do + + do i=1,SD_LMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = SD_LMesh%Moment(:,i) / p_FAST%UJacSclFact + indx_first = indx_last + 1 + end do + end if + + !............... + ! HD inputs (Morison%LumpedMesh): + !............... + do i=1,HD_M_LumpedMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_M_LumpedMesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,HD_M_LumpedMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_M_LumpedMesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + ! HD inputs (Morison%DistribMesh): + do i=1,HD_M_DistribMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_M_DistribMesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,HD_M_DistribMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_M_DistribMesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + ! HD inputs (Mesh): + do i=1,HD_WAMIT_Mesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_WAMIT_Mesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,HD_WAMIT_Mesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = HD_WAMIT_Mesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + !............... + ! BD inputs: + !............... + if (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) then + + do k=1,p_FAST%nBeams + + do i=1,BD_RootMotion(k)%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = BD_RootMotion(k)%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do !i + + do i=1,BD_RootMotion(k)%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = BD_RootMotion(k)%RotationAcc(:,i) + indx_first = indx_last + 1 + end do !i + + end do !k + + end if + + !............... + ! Orca inputs (Orca_PtfmMesh): + !............... + do i=1,Orca_PtfmMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = Orca_PtfmMesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,Orca_PtfmMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = Orca_PtfmMesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + !............... + ! ExtPtfm inputs (ExtPtfm_PtfmMesh): + !............... + do i=1,ExtPtfm_PtfmMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = ExtPtfm_PtfmMesh%TranslationAcc(:,i) + indx_first = indx_last + 1 + end do + + do i=1,ExtPtfm_PtfmMesh%NNodes + indx_last = indx_first + 2 + u(indx_first:indx_last) = ExtPtfm_PtfmMesh%RotationAcc(:,i) + indx_first = indx_last + 1 + end do + + +END SUBROUTINE Create_FullOpt1_UVector +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine adds u_delta to the corresponding mesh field and scales it as appropriate +SUBROUTINE Add_FullOpt1_u_delta( p_FAST, Jac_u_indx, u_delta, u_ED, u_SD, u_HD, u_BD, u_Orca, u_ExtPtfm ) +!.................................................................................................................................. + TYPE(FAST_ParameterType) , INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + INTEGER( IntKi ) , INTENT(IN ) :: Jac_u_indx(:,:) !< Index to map Jacobian u-vector into mesh fields + REAL( ReKi ) , INTENT(IN ) :: u_delta(:) !< The delta amount to add to the appropriate mesh fields + TYPE(ED_InputType) , INTENT(INOUT) :: u_ED !< ED System inputs + TYPE(SD_InputType) , INTENT(INOUT) :: u_SD !< SD System inputs + TYPE(HydroDyn_InputType) , INTENT(INOUT) :: u_HD !< SD System inputs + TYPE(BD_InputType) , INTENT(INOUT) :: u_BD(:) !< BD System inputs + TYPE(Orca_InputType) , INTENT(INOUT) :: u_Orca !< Orca System inputs + TYPE(ExtPtfm_InputType) , INTENT(INOUT) :: u_ExtPtfm !< ExtPtfm System inputs + + ! local variables + INTEGER :: n + INTEGER :: fieldIndx + INTEGER :: node + + + DO n = 1,SIZE(u_delta) + + fieldIndx = Jac_u_indx(n,2) + node = Jac_u_indx(n,3) + + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( Jac_u_indx(n,1) ) + + CASE ( 1) !Module/Mesh/Field: u_ED%PlatformPtMesh%Force = 1 + u_ED%PlatformPtMesh%Force( fieldIndx,node) = u_ED%PlatformPtMesh%Force( fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + CASE ( 2) !Module/Mesh/Field: u_ED%PlatformPtMesh%Moment = 2 + u_ED%PlatformPtMesh%Moment(fieldIndx,node) = u_ED%PlatformPtMesh%Moment(fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + CASE ( 3) !Module/Mesh/Field: u_ED%HubPtMesh%Force = 3 + u_ED%HubPtLoad%Force( fieldIndx,node) = u_ED%HubPtLoad%Force( fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + CASE ( 4) !Module/Mesh/Field: u_ED%HubPtMesh%Moment = 4 + u_ED%HubPtLoad%Moment(fieldIndx,node) = u_ED%HubPtLoad%Moment(fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + + CASE ( 5) !Module/Mesh/Field: u_SD%TPMesh%TranslationAcc = 5 + u_SD%TPMesh%TranslationAcc(fieldIndx,node) = u_SD%TPMesh%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE ( 6) !Module/Mesh/Field: u_SD%TPMesh%RotationAcc = 6 + u_SD%TPMesh%RotationAcc( fieldIndx,node) = u_SD%TPMesh%RotationAcc( fieldIndx,node) + u_delta(n) + CASE ( 7) !Module/Mesh/Field: u_SD%LMesh%Force = 7 + u_SD%LMesh%Force( fieldIndx,node) = u_SD%LMesh%Force( fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + CASE ( 8) !Module/Mesh/Field: u_SD%LMesh%Moment = 8 + u_SD%LMesh%Moment(fieldIndx,node) = u_SD%LMesh%Moment(fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact + + CASE ( 9) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 + u_HD%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (10) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 + u_HD%Morison%LumpedMesh%RotationAcc( fieldIndx,node) = u_HD%Morison%LumpedMesh%RotationAcc( fieldIndx,node) + u_delta(n) + CASE (11) !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 + u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 + u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) + u_delta(n) + CASE (13) !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 + u_HD%Mesh%TranslationAcc( fieldIndx,node) = u_HD%Mesh%TranslationAcc( fieldIndx,node) + u_delta(n) + CASE (14) !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 + u_HD%Mesh%RotationAcc( fieldIndx,node) = u_HD%Mesh%RotationAcc( fieldIndx,node) + u_delta(n) + + CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) + u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (16) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 16 (k=1) + u_BD(1)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(1)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) + CASE (17) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 17 (k=2) + u_BD(2)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(2)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (18) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 18 (k=2) + u_BD(2)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(2)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) + CASE (19) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 19 (k=3) + u_BD(3)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(3)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (20) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 20 (k=3) + u_BD(3)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(3)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) + + CASE (21) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + u_Orca%PtfmMesh%TranslationAcc( fieldIndx,node) = u_Orca%PtfmMesh%TranslationAcc( fieldIndx,node) + u_delta(n) + CASE (22) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + u_Orca%PtfmMesh%RotationAcc( fieldIndx,node) = u_Orca%PtfmMesh%RotationAcc( fieldIndx,node) + u_delta(n) + + CASE (23) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 23 + u_ExtPtfm%PtfmMesh%TranslationAcc( fieldIndx,node) = u_ExtPtfm%PtfmMesh%TranslationAcc( fieldIndx,node) + u_delta(n) + CASE (24) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 24 + u_ExtPtfm%PtfmMesh%RotationAcc( fieldIndx,node) = u_ExtPtfm%PtfmMesh%RotationAcc( fieldIndx,node) + u_delta(n) + + END SELECT + + END DO + +END SUBROUTINE Add_FullOpt1_u_delta +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +SUBROUTINE Perturb_u_FullOpt1( p_FAST, Jac_u_indx, n, u_perturb, u_ED_perturb, u_SD_perturb, u_HD_perturb, u_BD_perturb, & + u_Orca_perturb, u_ExtPtfm_perturb, perturb ) +!............................................................................................................................... + TYPE(FAST_ParameterType) , INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + INTEGER( IntKi ) , INTENT(IN ) :: Jac_u_indx(:,:) !< Index to map Jacobian u-vector into mesh fields + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + REAL( ReKi ) , INTENT(INOUT) :: u_perturb(:) !< array to be perturbed + TYPE(ED_InputType), OPTIONAL , INTENT(INOUT) :: u_ED_perturb !< ED System inputs (needed only when 1 <= n <= NumEDNodes=NumEDNodes) + TYPE(SD_InputType), OPTIONAL , INTENT(INOUT) :: u_SD_perturb !< SD System inputs (needed only when NumEDNodes +1 <= n <= NumEDNodes+NumSDNodes) [if SD is used] + TYPE(HydroDyn_InputType), OPTIONAL , INTENT(INOUT) :: u_HD_perturb !< HD System inputs (needed only when NumEDNodes+NumSDNodes +1 <= n <= NumEDNodes+NumSDNodes+NumHDNodes) [if HD is used and SD is used. if SD not used, + TYPE(BD_InputType), OPTIONAL , INTENT(INOUT) :: u_BD_perturb !< BD System inputs (needed only when NumEDNodes+NumSDNodes+NumHDNodes+1 <= n <= inf) [if BD is used] + TYPE(Orca_InputType), OPTIONAL , INTENT(INOUT) :: u_Orca_perturb !< Orca System inputs (needed only when NumEDNodes+NumSDNodes+NumHDNodes+NumBDNodes+1 <= n <= inf) [if Orca is used] + TYPE(ExtPtfm_InputType), OPTIONAL , INTENT(INOUT) :: u_ExtPtfm_perturb !< ExtPtfm System inputs (needed only when NumEDNodes+NumSDNodes+NumHDNodes+NumBDNodes+NumOcraNodes+1 <= n <= inf) [if ExtPtfm is used] + REAL( ReKi ) , INTENT( OUT) :: perturb !< amount that u_perturb(n) was perturbed + + ! local variables + INTEGER :: fieldIndx + INTEGER :: node + + + fieldIndx = Jac_u_indx(n,2) + node = Jac_u_indx(n,3) + + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( Jac_u_indx(n,1) ) + + CASE ( 1) !Module/Mesh/Field: u_ED%PlatformPtMesh%Force = 1 + perturb = GetPerturb( u_ED_perturb%PlatformPtMesh%Force(fieldIndx , node) ) + u_ED_perturb%PlatformPtMesh%Force( fieldIndx,node) = u_ED_perturb%PlatformPtMesh%Force( fieldIndx,node) + perturb * p_FAST%UJacSclFact + CASE ( 2) !Module/Mesh/Field: u_ED%PlatformPtMesh%Moment = 2 + perturb = GetPerturb( u_ED_perturb%PlatformPtMesh%Moment(fieldIndx , node) ) + u_ED_perturb%PlatformPtMesh%Moment(fieldIndx,node) = u_ED_perturb%PlatformPtMesh%Moment(fieldIndx,node) + perturb * p_FAST%UJacSclFact + CASE ( 3) !Module/Mesh/Field: u_ED%HubPtMesh%Force = 3 + perturb = GetPerturb( u_ED_perturb%HubPtLoad%Force(fieldIndx , node) ) + u_ED_perturb%HubPtLoad%Force( fieldIndx,node) = u_ED_perturb%HubPtLoad%Force( fieldIndx,node) + perturb * p_FAST%UJacSclFact + CASE ( 4) !Module/Mesh/Field: u_ED%HubPtMesh%Moment = 4 + perturb = GetPerturb( u_ED_perturb%HubPtLoad%Moment(fieldIndx , node) ) + u_ED_perturb%HubPtLoad%Moment( fieldIndx,node) = u_ED_perturb%HubPtLoad%Moment( fieldIndx,node) + perturb * p_FAST%UJacSclFact + + CASE ( 5) !Module/Mesh/Field: u_SD%TPMesh%TranslationAcc = 5 + perturb = GetPerturb( u_SD_perturb%TPMesh%TranslationAcc(fieldIndx , node) ) + u_SD_perturb%TPMesh%TranslationAcc(fieldIndx,node) = u_SD_perturb%TPMesh%TranslationAcc(fieldIndx,node) + perturb + CASE ( 6) !Module/Mesh/Field: u_SD%TPMesh%RotationAcc = 6 + perturb = GetPerturb( u_SD_perturb%TPMesh%RotationAcc(fieldIndx , node) ) + u_SD_perturb%TPMesh%RotationAcc( fieldIndx,node) = u_SD_perturb%TPMesh%RotationAcc( fieldIndx,node) + perturb + CASE ( 7) !Module/Mesh/Field: u_SD%LMesh%Force = 7 + perturb = GetPerturb( u_SD_perturb%LMesh%Force(fieldIndx , node) ) + u_SD_perturb%LMesh%Force( fieldIndx,node) = u_SD_perturb%LMesh%Force( fieldIndx,node) + perturb * p_FAST%UJacSclFact + CASE ( 8) !Module/Mesh/Field: u_SD%LMesh%Moment = 8 + perturb = GetPerturb( u_SD_perturb%LMesh%Moment(fieldIndx , node) ) + u_SD_perturb%LMesh%Moment(fieldIndx,node) = u_SD_perturb%LMesh%Moment(fieldIndx,node) + perturb * p_FAST%UJacSclFact + + CASE ( 9) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 + perturb = GetPerturb( u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) + perturb + CASE ( 10) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 + perturb = GetPerturb( u_HD_perturb%Morison%LumpedMesh%RotationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%LumpedMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%LumpedMesh%RotationAcc( fieldIndx,node) + perturb + CASE (11) !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 + perturb = GetPerturb( u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx,node) + perturb + CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 + perturb = GetPerturb( u_HD_perturb%Morison%DistribMesh%RotationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) + perturb + CASE (13) !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 + perturb = GetPerturb( u_HD_perturb%Mesh%TranslationAcc(fieldIndx , node) ) + u_HD_perturb%Mesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Mesh%TranslationAcc(fieldIndx,node) + perturb + CASE (14) !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 + perturb = GetPerturb( u_HD_perturb%Mesh%RotationAcc(fieldIndx , node) ) + u_HD_perturb%Mesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Mesh%RotationAcc( fieldIndx,node) + perturb + + CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) + perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb + CASE (16) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 16 (k=1) + perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb + CASE (17) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 17 (k=2) + perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb + CASE (18) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 18 (k=2) + perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb + CASE (19) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 19 (k=3) + perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb + CASE (20) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 20 (k=3) + perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) + u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb + + CASE (21) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + perturb = GetPerturb( u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx , node) ) + u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) = u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) + perturb + CASE (22) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + perturb = GetPerturb( u_Orca_perturb%PtfmMesh%RotationAcc(fieldIndx , node) ) + u_Orca_perturb%PtfmMesh%RotationAcc( fieldIndx,node) = u_Orca_perturb%PtfmMesh%RotationAcc( fieldIndx,node) + perturb + + CASE (23) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 21 + perturb = GetPerturb( u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx , node) ) + u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) = u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) + perturb + CASE (24) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 22 + perturb = GetPerturb( u_ExtPtfm_perturb%PtfmMesh%RotationAcc(fieldIndx , node) ) + u_ExtPtfm_perturb%PtfmMesh%RotationAcc( fieldIndx,node) = u_ExtPtfm_perturb%PtfmMesh%RotationAcc( fieldIndx,node) + perturb + + END SELECT + + u_perturb(n) = u_perturb(n) + perturb + + +END SUBROUTINE Perturb_u_FullOpt1 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine resets the remap flags on all of the meshes +SUBROUTINE ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD ) +!............................................................................................................................... + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + !local variable(s) + + INTEGER(IntKi) :: i ! counter for ice legs + INTEGER(IntKi) :: k ! counter for blades + + !..................................................................... + ! Reset each mesh's RemapFlag (after calling all InputSolve routines): + !..................................................................... + + ! ElastoDyn meshes + ED%Input( 1)%PlatformPtMesh%RemapFlag = .FALSE. + ED%y%PlatformPtMesh%RemapFlag = .FALSE. + ED%Input( 1)%TowerPtLoads%RemapFlag = .FALSE. + ED%y%TowerLn2Mesh%RemapFlag = .FALSE. + DO K=1,SIZE(ED%y%BladeRootMotion) + ED%y%BladeRootMotion(K)%RemapFlag = .FALSE. + END DO + if (allocated(ED%Input(1)%BladePtLoads)) then + DO K=1,SIZE(ED%Input(1)%BladePtLoads) + ED%Input( 1)%BladePtLoads(K)%RemapFlag = .FALSE. + ED%y%BladeLn2Mesh(K)%RemapFlag = .FALSE. + END DO + end if + + ED%Input( 1)%NacelleLoads%RemapFlag = .FALSE. + ED%y%NacelleMotion%RemapFlag = .FALSE. + ED%Input( 1)%HubPtLoad%RemapFlag = .FALSE. + ED%y%HubPtMotion%RemapFlag = .FALSE. + + ! BeamDyn meshes + IF ( p_FAST%CompElast == Module_BD ) THEN + DO i=1,p_FAST%nBeams + BD%Input(1,i)%RootMotion%RemapFlag = .FALSE. + BD%Input(1,i)%PointLoad%RemapFlag = .FALSE. + BD%Input(1,i)%DistrLoad%RemapFlag = .FALSE. + BD%Input(1,i)%HubMotion%RemapFlag = .FALSE. + + BD%y(i)%ReactionForce%RemapFlag = .FALSE. + BD%y(i)%BldMotion%RemapFlag = .FALSE. + END DO + END IF + + ! AeroDyn meshes + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + DO k=1,SIZE(AD14%Input(1)%InputMarkers) + AD14%Input(1)%InputMarkers(k)%RemapFlag = .FALSE. + AD14%y%OutputLoads( k)%RemapFlag = .FALSE. + END DO + + IF (AD14%Input(1)%Twr_InputMarkers%Committed) THEN + AD14%Input(1)%Twr_InputMarkers%RemapFlag = .FALSE. + AD14%y%Twr_OutputLoads%RemapFlag = .FALSE. + END IF + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + AD%Input(1)%HubMotion%RemapFlag = .FALSE. + + IF (AD%Input(1)%TowerMotion%Committed) THEN + AD%Input(1)%TowerMotion%RemapFlag = .FALSE. + + IF (AD%y%TowerLoad%Committed) THEN + AD%y%TowerLoad%RemapFlag = .FALSE. + END IF + END IF + + DO k=1,SIZE(AD%Input(1)%BladeMotion) + AD%Input(1)%BladeRootMotion(k)%RemapFlag = .FALSE. + AD%Input(1)%BladeMotion( k)%RemapFlag = .FALSE. + AD%y%BladeLoad( k)%RemapFlag = .FALSE. + END DO + + END IF + + + ! ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + IF (SrvD%y%NTMD%Mesh%Committed) THEN + SrvD%y%NTMD%Mesh%RemapFlag = .FALSE. + SrvD%Input(1)%NTMD%Mesh%RemapFlag = .FALSE. + END IF + + IF (SrvD%y%TTMD%Mesh%Committed) THEN + SrvD%y%TTMD%Mesh%RemapFlag = .FALSE. + SrvD%Input(1)%TTMD%Mesh%RemapFlag = .FALSE. + END IF + END IF + + + ! HydroDyn + IF ( p_FAST%CompHydro == Module_HD ) THEN + IF (HD%Input(1)%Mesh%Committed) THEN + HD%Input(1)%Mesh%RemapFlag = .FALSE. + HD%y%Mesh%RemapFlag = .FALSE. + HD%y%AllHdroOrigin%RemapFlag = .FALSE. + END IF + IF (HD%Input(1)%Morison%LumpedMesh%Committed) THEN + HD%Input(1)%Morison%LumpedMesh%RemapFlag = .FALSE. + HD%y%Morison%LumpedMesh%RemapFlag = .FALSE. + END IF + IF (HD%Input(1)%Morison%DistribMesh%Committed) THEN + HD%Input(1)%Morison%DistribMesh%RemapFlag = .FALSE. + HD%y%Morison%DistribMesh%RemapFlag = .FALSE. + END IF + END IF + + ! SubDyn + IF ( p_FAST%CompSub == Module_SD ) THEN + IF (SD%Input(1)%TPMesh%Committed) THEN + SD%Input(1)%TPMesh%RemapFlag = .FALSE. + SD%y%Y1Mesh%RemapFlag = .FALSE. + END IF + + IF (SD%Input(1)%LMesh%Committed) THEN + SD%Input(1)%LMesh%RemapFlag = .FALSE. + SD%y%Y2Mesh%RemapFlag = .FALSE. + END IF + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + IF (ExtPtfm%Input(1)%PtfmMesh%Committed) THEN + ExtPtfm%Input(1)%PtfmMesh%RemapFlag = .FALSE. + ExtPtfm%y%PtfmMesh%RemapFlag = .FALSE. + END IF + END IF + + + ! MAP , FEAM , MoorDyn, OrcaFlex + IF ( p_FAST%CompMooring == Module_MAP ) THEN + MAPp%Input(1)%PtFairDisplacement%RemapFlag = .FALSE. + MAPp%y%PtFairleadLoad%RemapFlag = .FALSE. + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + MD%Input(1)%PtFairleadDisplacement%RemapFlag = .FALSE. + MD%y%PtFairleadLoad%RemapFlag = .FALSE. + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + FEAM%Input(1)%PtFairleadDisplacement%RemapFlag = .FALSE. + FEAM%y%PtFairleadLoad%RemapFlag = .FALSE. + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + Orca%Input(1)%PtfmMesh%RemapFlag = .FALSE. + Orca%y%PtfmMesh%RemapFlag = .FALSE. + END IF + + ! IceFloe, IceDyn + IF ( p_FAST%CompIce == Module_IceF ) THEN + IF (IceF%Input(1)%iceMesh%Committed) THEN + IceF%Input(1)%iceMesh%RemapFlag = .FALSE. + IceF%y%iceMesh%RemapFlag = .FALSE. + END IF + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + DO i=1,p_FAST%numIceLegs + IF (IceD%Input(1,i)%PointMesh%Committed) THEN + IceD%Input(1,i)%PointMesh%RemapFlag = .FALSE. + IceD%y(i)%PointMesh%RemapFlag = .FALSE. + END IF + END DO + END IF + +END SUBROUTINE ResetRemapFlags +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes all of the mapping data structures needed between the various modules. +SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg) +!............................................................................................................................... + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + + TYPE(ElastoDyn_Data),TARGET,INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + INTEGER :: K, i ! loop counters + INTEGER :: NumBl ! number of blades + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InitModuleMappings' + + TYPE(MeshType), POINTER :: PlatformMotion + TYPE(MeshType), POINTER :: PlatformLoads + !............................................................................................................................ + + ErrStat = ErrID_None + ErrMsg = "" + + NumBl = SIZE(ED%y%BladeRootMotion,1) + PlatformMotion => ED%y%PlatformPtMesh + PlatformLoads => ED%Input(1)%PlatformPtMesh + + !............................................................................................................................ + ! Create the data structures and mappings in MeshMapType + !............................................................................................................................ + +!------------------------- +! ElastoDyn <-> BeamDyn +!------------------------- + IF ( p_FAST%CompElast == Module_BD ) THEN + + ! Blade meshes: (allocate two mapping data structures to number of blades, then allocate data inside the structures) + ALLOCATE( MeshMapData%ED_P_2_BD_P(NumBl), MeshMapData%BD_P_2_ED_P(NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%ED_P_2_BD_P and MeshMapData%BD_P_2_ED_P.', & + ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + DO K=1,NumBl + CALL MeshMapCreate( ED%y%BladeRootMotion(K), BD%Input(1,k)%RootMotion, MeshMapData%ED_P_2_BD_P(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_BD_BladeRootMotion('//TRIM(Num2LStr(K))//')' ) + CALL MeshMapCreate( BD%y(k)%ReactionForce, ED%Input(1)%HubPtLoad, MeshMapData%BD_P_2_ED_P(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':BD_2_ED_ReactionLoad('//TRIM(Num2LStr(K))//')' ) + END DO + + ! Hub meshes: + ALLOCATE( MeshMapData%ED_P_2_BD_P_Hub(NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%ED_P_2_BD_P_Hub.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + DO K=1,NumBl + CALL MeshMapCreate( ED%y%HubPtMotion, BD%Input(1,k)%HubMotion, MeshMapData%ED_P_2_BD_P_Hub(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_BD_HubMotion('//TRIM(Num2LStr(K))//')' ) + END DO + + END IF + + +!------------------------- +! ElastoDyn <-> ServoDyn +!------------------------- + + IF ( SrvD%Input(1)%NTMD%Mesh%Committed ) THEN ! ED-SrvD + + CALL MeshMapCreate( ED%y%NacelleMotion, SrvD%Input(1)%NTMD%Mesh, MeshMapData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_SrvD_NacelleMotion' ) + CALL MeshMapCreate( SrvD%y%NTMD%Mesh, ED%Input(1)%NacelleLoads, MeshMapData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SrvD_2_ED_NacelleLoads' ) + + END IF + + IF ( SrvD%Input(1)%TTMD%Mesh%Committed ) THEN ! ED-SrvD + + CALL MeshMapCreate( ED%y%TowerLn2Mesh, SrvD%Input(1)%TTMD%Mesh, MeshMapData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_SrvD_TowerMotion' ) + CALL MeshMapCreate( SrvD%y%TTMD%Mesh, ED%Input(1)%TowerPtLoads, MeshMapData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SrvD_2_ED_TowerLoad' ) + + END IF + +!------------------------- +! ElastoDyn <-> AeroDyn14 +!------------------------- + + IF ( p_FAST%CompAero == Module_AD14 ) THEN ! ED-AD14 + + ! Blade meshes: (allocate two mapping data structures to number of blades, then allocate data inside the structures) + ! AD14 does not properly set up its blade meshes, so we can't use this + !ALLOCATE( MeshMapData%BDED_L_2_AD_L_B(NumBl), MeshMapData%AD_L_2_BDED_B(NumBl), STAT=ErrStat2 ) + ! IF ( ErrStat2 /= 0 ) THEN + ! CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%BDED_L_2_AD_L_B and MeshMapData%AD_L_2_BDED_B.', & + ! ErrStat, ErrMsg, RoutineName ) + ! RETURN + ! END IF + ! + !DO K=1,NumBl + ! CALL MeshMapCreate( AD14%y%OutputLoads(K), ED%Input(1)%BladePtLoads(K), MeshMapData%AD_L_2_BDED_B(K), ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':AD_L_2_BDED_B('//TRIM(Num2LStr(K))//')' ) + !END DO + + ! Tower mesh: + IF ( AD14%Input(1)%Twr_InputMarkers%Committed ) THEN + CALL MeshMapCreate( ED%y%TowerLn2Mesh, AD14%Input(1)%Twr_InputMarkers, MeshMapData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_AD_TowerMotion' ) + CALL MeshMapCreate( AD14%y%Twr_OutputLoads, ED%Input(1)%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':AD_2_ED_TowerLoad' ) + END IF + + IF (ErrStat >= AbortErrLev ) RETURN + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN ! ED-AD and/or BD-AD + + ! allocate per-blade space for mapping to structural module + + ! Blade root meshes + ALLOCATE( MeshMapData%ED_P_2_AD_P_R(NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%ED_P_2_AD_P_R.', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + ! Blade meshes: (allocate two mapping data structures to number of blades, then allocate data inside the structures) + ALLOCATE( MeshMapData%BDED_L_2_AD_L_B(NumBl), MeshMapData%AD_L_2_BDED_B(NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%BDED_L_2_AD_L_B and MeshMapData%AD_L_2_BDED_B.', & + ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + + +!------------------------- +! ElastoDyn <-> AeroDyn +!------------------------- + + ! blade root meshes + DO K=1,NumBl + CALL MeshMapCreate( ED%y%BladeRootMotion(K), AD%Input(1)%BladeRootMotion(K), MeshMapData%ED_P_2_AD_P_R(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_AD_RootMotion('//TRIM(Num2LStr(K))//')' ) + END DO + + + ! Hub point mesh + CALL MeshMapCreate( ED%y%HubPtMotion, AD%Input(1)%HubMotion, MeshMapData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_AD_HubMotion' ) + + + ! Tower mesh: + IF ( AD%Input(1)%TowerMotion%Committed ) THEN + CALL MeshMapCreate( ED%y%TowerLn2Mesh, AD%Input(1)%TowerMotion, MeshMapData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_AD_TowerMotion' ) + + IF ( AD%y%TowerLoad%Committed ) THEN + CALL MeshMapCreate( AD%y%TowerLoad, ED%Input(1)%TowerPtLoads, MeshMapData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':AD_2_ED_TowerLoad' ) + END IF + END IF + + + IF ( p_FAST%CompElast == Module_ED ) then + + ! Blade meshes: + DO K=1,NumBl + CALL MeshMapCreate( ED%y%BladeLn2Mesh(K), AD%Input(1)%BladeMotion(K), MeshMapData%BDED_L_2_AD_L_B(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_2_AD_BladeMotion('//TRIM(Num2LStr(K))//')' ) + CALL MeshMapCreate( AD%y%BladeLoad(K), ED%Input(1)%BladePtLoads(K), MeshMapData%AD_L_2_BDED_B(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':AD_2_ED_BladeLoad('//TRIM(Num2LStr(K))//')' ) + END DO + + ELSEIF ( p_FAST%CompElast == Module_BD ) then + +!------------------------- +! BeamDyn <-> AeroDyn +!------------------------- + + ! connect AD mesh with BeamDyn + DO K=1,NumBl + CALL MeshMapCreate( BD%y(k)%BldMotion, AD%Input(1)%BladeMotion(K), MeshMapData%BDED_L_2_AD_L_B(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':BD_2_AD_BladeMotion('//TRIM(Num2LStr(K))//')' ) + CALL MeshMapCreate( AD%y%BladeLoad(K), BD%Input(1,k)%DistrLoad, MeshMapData%AD_L_2_BDED_B(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':AD_2_BD_BladeLoad('//TRIM(Num2LStr(K))//')' ) + END DO + +!------------------------- +! BeamDyn <-> BeamDyn +!------------------------- + if (.not. p_FAST%BD_OutputSibling) then + + ! Blade meshes for load transfer: (allocate meshes at BD input locations for motions transferred from BD output locations) + ALLOCATE( MeshMapData%BD_L_2_BD_L(NumBl), MeshMapData%y_BD_BldMotion_4Loads(NumBl), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating MeshMapData%BD_L_2_BD_L and MeshMapData%y_BD_BldMotion_4Loads.', & + ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + DO K=1,NumBl + ! create the new mesh: + CALL MeshCopy ( SrcMesh = BD%Input(1,k)%DistrLoad & + , DestMesh = MeshMapData%y_BD_BldMotion_4Loads(k) & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , RotationVel = .TRUE. & + , TranslationVel = .TRUE. & + , RotationAcc = .TRUE. & + , TranslationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! create the mapping: + CALL MeshMapCreate( BD%y(k)%BldMotion, MeshMapData%y_BD_BldMotion_4Loads(k), MeshMapData%BD_L_2_BD_L(K), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':BD_2_BD_BladeMotion('//TRIM(Num2LStr(K))//')' ) + END DO + + end if !.not. p_FAST%BD_OutputSibling + + END IF ! CompElast + + END IF ! AeroDyn/AeroDyn14 to structural code + + + + IF ( p_FAST%CompHydro == Module_HD ) THEN ! HydroDyn-{ElastoDyn or SubDyn} + + +!------------------------- +! HydroDyn <-> ElastoDyn +!------------------------- + IF ( p_FAST%CompSub /= Module_SD ) THEN ! all of these get mapped to ElastoDyn ! (offshore floating) + + ! we're just going to assume PlatformLoads and PlatformMotion are committed + + IF ( HD%y%AllHdroOrigin%Committed ) THEN ! meshes for floating + ! HydroDyn WAMIT point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( HD%y%AllHdroOrigin, PlatformLoads, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_HD_W_P' ) + END IF + + ! ElastoDyn point mesh HydroDyn Morison point mesh (ED sets inputs, but gets outputs from HD%y%AllHdroOrigin in floating case) + IF ( HD%Input(1)%Morison%LumpedMesh%Committed ) THEN + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_HD_M_P' ) + END IF + + ! ElastoDyn point mesh to HydroDyn Morison line mesh (ED sets inputs, but gets outputs from HD%y%AllHdroOrigin in floating case) + IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_HD_M_L' ) + END IF + + + ELSE ! these get mapped to ElastoDyn AND SubDyn (in ED_SD_HD coupling) ! offshore fixed + + ! HydroDyn WAMIT mesh to ElastoDyn point mesh + IF ( HD%y%Mesh%Committed ) THEN + ! HydroDyn WAMIT point mesh to ElastoDyn point mesh ! meshes for fixed-bottom + CALL MeshMapCreate( HD%y%Mesh, PlatformLoads, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_HD_W_P' ) + END IF + +!------------------------- +! HydroDyn <-> SubDyn +!------------------------- + + ! HydroDyn Morison point mesh to SubDyn point mesh + IF ( HD%y%Morison%LumpedMesh%Committed ) THEN + + CALL MeshMapCreate( HD%y%Morison%LumpedMesh, SD%Input(1)%LMesh, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_P_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%Morison%LumpedMesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_M_P' ) + + END IF + + ! HydroDyn Morison line mesh to SubDyn point mesh + IF ( HD%y%Morison%DistribMesh%Committed ) THEN + + CALL MeshMapCreate( HD%y%Morison%DistribMesh, SD%Input(1)%LMesh, MeshMapData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_L_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%Morison%DistribMesh, MeshMapData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_M_L' ) + + END IF + + + END IF ! HydroDyn-SubDyn + + IF (ErrStat >= AbortErrLev ) RETURN + + END IF !HydroDyn-{ElastoDyn or SubDyn} + + +!------------------------- +! ElastoDyn <-> SubDyn +!------------------------- + IF ( p_FAST%CompSub == Module_SD ) THEN + + ! NOTE: the MeshMapCreate routine returns fatal errors if either mesh is not committed + + ! SubDyn transition piece point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( SD%y%Y1mesh, PlatformLoads, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_TP_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, SD%Input(1)%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_SD_TP' ) + +!------------------------- +! ElastoDyn <-> ExtPtfm +!------------------------- + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + + ! NOTE: the MeshMapCreate routine returns fatal errors if either mesh is not committed + + ! ExtPtfm PtfmMesh point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( ExtPtfm%y%PtfmMesh, PlatformLoads, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_TP_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, ExtPtfm%Input(1)%PtfmMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_SD_TP' ) + + END IF ! SubDyn-ElastoDyn + + + IF ( p_FAST%CompMooring == Module_MAP ) THEN +!------------------------- +! ElastoDyn <-> MAP +!------------------------- + + ! MAP point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( MAPp%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, MAPp%Input(1)%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN +!------------------------- +! ElastoDyn <-> MoorDyn +!------------------------- + + ! MoorDyn point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( MD%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, MD%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN +!------------------------- +! ElastoDyn <-> FEAMooring +!------------------------- + + ! FEAMooring point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( FEAM%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN +!------------------------- +! ElastoDyn <-> OrcaFlex +!------------------------- + + ! OrcaFlex point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( Orca%y%PtfmMesh, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, Orca%Input(1)%PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + + END IF ! MAP-ElastoDyn ; FEAM-ElastoDyn; Orca-ElastoDyn + + +!------------------------- +! SubDyn <-> IceFloe +!------------------------- + + IF ( p_FAST%CompIce == Module_IceF ) THEN + + ! IceFloe iceMesh point mesh to SubDyn LMesh point mesh + CALL MeshMapCreate( IceF%y%iceMesh, SD%Input(1)%LMesh, MeshMapData%IceF_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':IceF_P_2_SD_P' ) + ! SubDyn y2Mesh point mesh to IceFloe iceMesh point mesh + CALL MeshMapCreate( SD%y%y2Mesh, IceF%Input(1)%iceMesh, MeshMapData%SD_P_2_IceF_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_IceF_P' ) + +!------------------------- +! SubDyn <-> IceDyn +!------------------------- + + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + ALLOCATE( MeshMapData%IceD_P_2_SD_P( p_FAST%numIceLegs ) , & + MeshMapData%SD_P_2_IceD_P( p_FAST%numIceLegs ) , Stat=ErrStat2 ) + IF (ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Unable to allocate IceD_P_2_SD_P and SD_P_2_IceD_P', ErrStat, ErrMsg, RoutineName ) + RETURN + END IF + + DO i = 1,p_FAST%numIceLegs + + ! IceDyn PointMesh point mesh to SubDyn LMesh point mesh + CALL MeshMapCreate( IceD%y(i)%PointMesh, SD%Input(1)%LMesh, MeshMapData%IceD_P_2_SD_P(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':IceD_P_2_SD_P('//TRIM(num2LStr(i))//')' ) + ! SubDyn y2Mesh point mesh to IceDyn PointMesh point mesh + CALL MeshMapCreate( SD%y%y2Mesh, IceD%Input(1,i)%PointMesh, MeshMapData%SD_P_2_IceD_P(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_IceD_P('//TRIM(num2LStr(i))//')' ) + + END DO + + END IF ! SubDyn-IceFloe + + IF (ErrStat >= AbortErrLev ) RETURN + + !............................................................................................................................ + ! Initialize the Jacobian structures: + !............................................................................................................................ + !IF ( p_FAST%TurbineType == Type_Offshore_Fixed ) THEN + IF ( p_FAST%CompSub /= Module_None .OR. (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) .or. p_FAST%CompMooring == Module_Orca) THEN !.OR. p_FAST%CompHydro == Module_HD ) THEN + CALL Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED%Input(1)%PlatformPtMesh, SD%Input(1)%TPMesh, SD%Input(1)%LMesh, & + HD%Input(1)%Morison%LumpedMesh, HD%Input(1)%Morison%DistribMesh, HD%Input(1)%Mesh, & + ED%Input(1)%HubPtLoad, BD%Input(1,:), Orca%Input(1)%PtfmMesh, ExtPtfm%Input(1)%PtfmMesh, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN + CALL AllocAry( MeshMapData%Jacobian_Opt1, SizeJac_ED_HD, SizeJac_ED_HD, 'Jacobian for Ptfm-HD coupling', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( ALLOCATED( MeshMapData%Jacobian_Opt1 ) ) THEN + CALL AllocAry( MeshMapData%Jacobian_pivot, SIZE(MeshMapData%Jacobian_Opt1), 'Pivot array for Jacobian LU decomposition', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (ErrStat >= AbortErrLev ) RETURN + + !............................................................................................................................ + ! reset the remap flags (do this before making the copies else the copies will always have remap = true) + !............................................................................................................................ + CALL ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD ) + + !............................................................................................................................ + ! initialize the temporary input meshes (for input-output solves in Solve Option 1): + ! (note that we do this after ResetRemapFlags() so that the copies have remap=false) + !............................................................................................................................ + IF ( p_FAST%CompHydro == Module_HD .OR. p_FAST%CompSub /= Module_None .OR. (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) & + .or. p_FAST%CompMooring == Module_Orca) THEN + + ! Temporary meshes for transfering inputs to ED, HD, BD, Orca, and SD + CALL MeshCopy ( ED%Input(1)%HubPtLoad, MeshMapData%u_ED_HubPtLoad, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_ED_HubPtLoad' ) + + CALL MeshCopy ( ED%Input(1)%PlatformPtMesh, MeshMapData%u_ED_PlatformPtMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_ED_PlatformPtMesh' ) + + CALL MeshCopy ( ED%Input(1)%PlatformPtMesh, MeshMapData%u_ED_PlatformPtMesh_2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_ED_PlatformPtMesh_2' ) + + + IF ( p_FAST%CompElast == Module_BD ) THEN + + ! Temporary meshes for transfering inputs to ED and BD + CALL MeshCopy ( ED%Input(1)%HubPtLoad, MeshMapData%u_ED_HubPtLoad_2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_ED_HubPtLoad_2' ) + + allocate( MeshMapData%u_BD_RootMotion( p_FAST%nBeams ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + CALL SetErrStat( ErrID_Fatal, "Error allocating u_BD_RootMotion", ErrStat, ErrMsg, RoutineName ) + return + end if + + do k=1,p_FAST%nBeams + CALL MeshCopy ( BD%Input(1,k)%RootMotion, MeshMapData%u_BD_RootMotion(k), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_BD_RootMotion('//trim(num2lstr(k))//')' ) + end do + + + END IF + + IF ( p_FAST%CompSub == Module_SD ) THEN + + CALL MeshCopy ( SD%Input(1)%TPMesh, MeshMapData%u_SD_TPMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_SD_TPMesh' ) + + IF ( p_FAST%CompHydro == Module_HD ) THEN + + CALL MeshCopy ( SD%Input(1)%LMesh, MeshMapData%u_SD_LMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_SD_LMesh' ) + + CALL MeshCopy ( SD%Input(1)%LMesh, MeshMapData%u_SD_LMesh_2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_SD_LMesh_2' ) + + END IF + + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + + CALL MeshCopy ( ExtPtfm%Input(1)%PtfmMesh, MeshMapData%u_ExtPtfm_PtfmMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_ExtPtfm_PtfmMesh' ) + + END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + + CALL MeshCopy ( HD%Input(1)%Mesh, MeshMapData%u_HD_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_Mesh' ) + + CALL MeshCopy ( HD%Input(1)%Morison%LumpedMesh, MeshMapData%u_HD_M_LumpedMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_M_LumpedMesh' ) + + CALL MeshCopy ( HD%Input(1)%Morison%DistribMesh, MeshMapData%u_HD_M_DistribMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_M_DistribMesh' ) + + END IF + + IF ( p_FAST%CompMooring == Module_Orca ) THEN + + CALL MeshCopy ( Orca%Input(1)%PtfmMesh, MeshMapData%u_Orca_PtfmMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_Orca_PtfmMesh' ) + + END IF + + + END IF + + + + !............................................................................................................................ + + +END SUBROUTINE InitModuleMappings +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine solves the input-output relations for all of the modules. It is a subroutine because it gets done twice-- +!! once at the start of the n_t_global loop and once in the j_pc loop, using different states. +!! *** Note that modules that do not have direct feedthrough should be called first. *** +SUBROUTINE CalcOutputs_And_SolveForInputs( n_t_global, this_time, this_state, calcJacobian, NextJacCalcTime, & + p_FAST, m_FAST, WriteThisStep, ED, BD, & + SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg ) + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + INTEGER(IntKi) , intent(in ) :: n_t_global !< current time step (used only for SrvD hack) + LOGICAL , intent(inout) :: calcJacobian !< Should we calculate Jacobians in Option 1? + REAL(DbKi) , intent(in ) :: NextJacCalcTime !< Time between calculating Jacobians in the HD-ED and SD-ED simulations + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Misc variables (including external inputs) for the glue code + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CalcOutputs_And_SolveForInputs' + + +#ifdef OUTPUT_MASS_MATRIX + INTEGER :: UnMM +#endif + + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Option 1: Solve for consistent inputs and outputs, which is required when Y has direct feedthrough in modules coupled together + ! bjj: If you are doing this option at the beginning as well as the end (after option 2), you must initialize the values of + ! MAPp%y, + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( EqualRealNos( this_time, NextJacCalcTime ) .OR. NextJacCalcTime < this_time ) THEN + calcJacobian = .TRUE. + ELSE + calcJacobian = .FALSE. + END IF + + + !> ## This is OPTION 2 before OPTION 1: + !! + !! For cases with HydroDyn, BeamDyn, OrcaFlex interface, and/or SubDyn, it calls ED_CalcOuts (a time-sink) 3 times per step/correction + !! (plus the 6 calls when calculating the Jacobian). + !! In cases without HydroDyn or SubDyn, it is the same as Option 1 before 2 (with 1 call to ED_CalcOuts either way). + !! + !! Option 1 before 2 usually requires a correction step, whereas Option 2 before Option 1 often does not. Thus we are using this option, calling + !! ED_CalcOuts 3 times (option 2 before 1 with no correction step) instead of 4 times (option1 before 2 with one correction step). + !! Note that this analysis may change if/when AeroDyn14 (and ServoDyn?) generate different outputs on correction steps. (Currently, AeroDyn (v14) + !! returns old values until time advances.) + !! Also note that AD15's DBEMT module (and UA?) is heavily time-dependent without calling the structural code first (DBEMT's filters do not deal + !! well with the extrapolated inputs). + !! + !! ## Algorithm: + + + !> Solve option 2 (modules without direct feedthrough): + CALL SolveOption2(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, n_t_global < 0, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +#ifdef OUTPUT_MASS_MATRIX + if (n_t_global == 0) then + UnMM = -1 + CALL GetNewUnit( UnMM, ErrStat2, ErrMsg2 ) + CALL OpenFOutFile( UnMM, TRIM(p_FAST%OutFileRoot)//'.EDMassMatrix', ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL WrMatrix(ED%m%AugMat,UnMM, p_FAST%OutFmt) + CLOSE( UnMM ) + end if +#endif + + !> transfer ED outputs to other modules used in option 1: + CALL Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, ED%y, HD%Input(1), SD%Input(1), ExtPtfm%Input(1), & + MAPp%Input(1), FEAM%Input(1), MD%Input(1), & + Orca%Input(1), BD%Input(1,:), MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !> Solve option 1 (rigorous solve on loads/accelerations) + CALL SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !> Now use the ElastoDyn and BD outputs from option1 to update the inputs for InflowWind, AeroDyn, and ServoDyn (necessary only if they have states) + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD14_InputSolve_NoIfW( p_FAST, AD14%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! because we're not calling InflowWind_CalcOutput or getting new values from OpenFOAM, + ! this probably can be skipped + CALL AD14_InputSolve_IfW( p_FAST, AD14%Input(1), IfW%y, OpFM%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + CALL AD_InputSolve_NoIfW( p_FAST, AD%Input(1), SrvD%y, ED%y, BD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! because we're not calling InflowWind_CalcOutput or getting new values from OpenFOAM, + ! this probably can be skipped; + ! @todo: alternatively, we could call InflowWind_CalcOutput, too. + CALL AD_InputSolve_IfW( p_FAST, AD%Input(1), IfW%y, OpFM%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + CALL IfW_InputSolve( p_FAST, m_FAST, IfW%Input(:), IfW%p, AD14%Input(1), AD%Input(1), AD%OtherSt(1), ED%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE IF ( p_FAST%CompInflow == Module_OpFM ) THEN + ! OpenFOAM is the driver and it sets these inputs outside of this solve; the OpenFOAM inputs and outputs thus don't change + ! in this scenario until OpenFOAM takes another step **this is a source of error, but it is the way the OpenFOAM-FAST7 coupling + ! works, so I'm not going to spend time that I don't have now to fix it** + CALL OpFM_SetInputs( p_FAST, AD14%p, AD14%Input(1), AD14%y, AD%Input(1), AD%y, ED%y, SrvD%y, OpFM, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + CALL SrvD_InputSolve( p_FAST, m_FAST, SrvD%Input(1), ED%y, IfW%y, OpFM%y, BD%y, MeshmapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (p_FAST%CompElast == Module_BD .and. .NOT. BD_Solve_Option1) THEN + ! map ED root and hub motion outputs to BeamDyn: + CALL Transfer_ED_to_BD(ED%y, BD%Input(1,:), MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName ) + END IF + + !..................................................................... + ! Reset each mesh's RemapFlag (after calling all InputSolve routines): + !..................................................................... + + CALL ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + + +END SUBROUTINE CalcOutputs_And_SolveForInputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine implements the "option 1" solve for all inputs with direct links to HD, SD, ExtPtfm, MAP, OrcaFlex interface, and the ED +!! platform reference point. Also in solve option 1 are the BD-ED blade root coupling. +SUBROUTINE SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg, WriteThisStep ) +!............................................................................................................................... + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + LOGICAL , intent(in ) :: calcJacobian !< Should we calculate Jacobians in Option 1? + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + !TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD ! ServoDyn data + !TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 ! AeroDyn14 data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + + INTEGER :: i ! loop counter + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'SolveOption1' + + !............................................................................................................................ + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !> Option 1: solve for consistent inputs and outputs, which is required when Y has direct feedthrough in + !! modules coupled together + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + ! Because MAP, FEAM, MoorDyn, IceDyn, and IceFloe do not contain acceleration inputs, we do this outside the DO loop in the ED{_SD}_HD_InputOutput solves. + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + CALL MAP_CalcOutput( this_time, MAPp%Input(1), MAPp%p, MAPp%x(this_state), MAPp%xd(this_state), MAPp%z(this_state), & + MAPp%OtherSt, MAPp%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + + CALL MD_CalcOutput( this_time, MD%Input(1), MD%p, MD%x(this_state), MD%xd(this_state), MD%z(this_state), & + MD%OtherSt(this_state), MD%y, MD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + + CALL FEAM_CalcOutput( this_time, FEAM%Input(1), FEAM%p, FEAM%x(this_state), FEAM%xd(this_state), FEAM%z(this_state), & + FEAM%OtherSt(this_state), FEAM%y, FEAM%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + IF ( p_FAST%CompIce == Module_IceF ) THEN + + CALL IceFloe_CalcOutput( this_time, IceF%Input(1), IceF%p, IceF%x(this_state), IceF%xd(this_state), IceF%z(this_state), & + IceF%OtherSt(this_state), IceF%y, IceF%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + DO i=1,p_FAST%numIceLegs + CALL IceD_CalcOutput( this_time, IceD%Input(1,i), IceD%p(i), IceD%x(i,this_state), IceD%xd(i,this_state), & + IceD%z(i,this_state), IceD%OtherSt(i,this_state), IceD%y(i), IceD%m(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + END IF + + IF (ErrStat >= AbortErrLev) RETURN + + IF ( p_FAST%CompSub /= Module_None .OR. (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) .OR. p_FAST%CompMooring == Module_Orca ) THEN !.OR. p_FAST%CompHydro == Module_HD ) THEN + + CALL FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & + , ED%Input(1), ED%p, ED%x( this_state), ED%xd( this_state), ED%z( this_state), ED%OtherSt( this_state), ED%y, ED%m & + , SD%Input(1), SD%p, SD%x( this_state), SD%xd( this_state), SD%z( this_state), SD%OtherSt( this_state), SD%y , SD%m & + , ExtPtfm%Input(1),ExtPtfm%p,ExtPtfm%x( this_state),ExtPtfm%xd( this_state),ExtPtfm%z( this_state),ExtPtfm%OtherSt( this_state),ExtPtfm%y,ExtPtfm%m & + , HD%Input(1), HD%p, HD%x( this_state), HD%xd( this_state), HD%z( this_state), HD%OtherSt( this_state), HD%y , HD%m & + , BD%Input(1,:), BD%p, BD%x(:,this_state), BD%xd(:,this_state), BD%z(:,this_state), BD%OtherSt(:,this_state), BD%y , BD%m & + , Orca%Input(1), Orca%p, Orca%x( this_state), Orca%xd( this_state), Orca%z( this_state), Orca%OtherSt( this_state), Orca%y , Orca%m & + , MAPp%Input(1), MAPp%y & + , FEAM%Input(1), FEAM%y & + , MD%Input(1), MD%y & + , IceF%Input(1), IceF%y & + , IceD%Input(1,:), IceD%y & ! bjj: I don't really want to make temp copies of input types. perhaps we should pass the whole Input() structure? (likewise for BD)... + , MeshMapData , ErrStat2, ErrMsg2, WriteThisStep ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN + + CALL ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & + , ED%Input(1), ED%p, ED%x(this_state), ED%xd(this_state), ED%z(this_state), ED%OtherSt(this_state), ED%y, ED%m & + , HD%Input(1), HD%p, HD%x(this_state), HD%xd(this_state), HD%z(this_state), HD%OtherSt(this_state), HD%y, HD%m & + , MAPp%Input(1), MAPp%y, FEAM%Input(1), FEAM%y, MD%Input(1), MD%y & + , MeshMapData , ErrStat2, ErrMsg2, WriteThisStep ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF ! HD, BD, and/or SD coupled to ElastoDyn + +!.................. +! Set mooring line and ice inputs (which don't have acceleration fields) +!.................. + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MAP_InputSolve( MAPp%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL MD_InputSolve( MD%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL FEAM_InputSolve( FEAM%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + IF ( p_FAST%CompIce == Module_IceF ) THEN + + CALL IceFloe_InputSolve( IceF%Input(1), SD%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + DO i=1,p_FAST%numIceLegs + + CALL IceD_InputSolve( IceD%Input(1,i), SD%y, MeshMapData, i, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':IceD_InputSolve' ) + + END DO + + END IF + +#ifdef DEBUG_MESH_TRANSFER_ICE + CALL WrScr('********************************************************') + CALL WrScr('**** IceF to SD point-to-point *****') + CALL WrScr('********************************************************') + CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, IceF%Input(1)%iceMesh, IceF%y%iceMesh,& + MeshMapData%SD_P_2_IceF_P, MeshMapData%IceF_P_2_SD_P, & + 'SD_y2_IceF_Meshes_t'//TRIM(Num2LStr(0))//'.PI.bin' ) + + + CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, HD%Input(1)%Morison%LumpedMesh, HD%y%Morison%LumpedMesh,& + MeshMapData%SD_P_2_HD_M_P, MeshMapData%HD_M_P_2_SD_P, & + 'SD_y2_HD_M_L_Meshes_t'//TRIM(Num2LStr(0))//'.PHL.bin' ) + + CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, HD%Input(1)%Morison%DistribMesh, HD%y%Morison%DistribMesh,& + MeshMapData%SD_P_2_HD_M_L, MeshMapData%HD_M_L_2_SD_P, & + 'SD_y2_HD_M_D_Meshes_t'//TRIM(Num2LStr(0))//'.PHD.bin' ) + + + !print * + !pause +#endif + +END SUBROUTINE SolveOption1 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine implements the first part of the "option 2" solve for inputs that apply to BeamDyn and AeroDyn +SUBROUTINE SolveOption2a_Inp2BD(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat, ErrMsg, WriteThisStep) + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Misc variables for the glue code (including external inputs) + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'SolveOption2a_Inp2BD' + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !> ++ Option 2: Solve for inputs based only on the current outputs. + !! This is much faster than option 1 when the coupled modules do not have direct feedthrough. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + CALL ED_CalcOutput( this_time, ED%Input(1), ED%p, ED%x(this_state), ED%xd(this_state), ED%z(this_state), ED%OtherSt(this_state), ED%y, ED%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( p_FAST%CompElast == Module_BD ) THEN + ! map ED root and hub motion outputs to BeamDyn: + CALL Transfer_ED_to_BD(ED%y, BD%Input(1,:), MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName ) + END IF + + +END SUBROUTINE SolveOption2a_Inp2BD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine implements the first part of the "option 2" solve for inputs that apply to AeroDyn & InflowWind +SUBROUTINE SolveOption2b_Inp2IfW(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat, ErrMsg, WriteThisStep) + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Misc variables for the glue code (including external inputs) + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + INTEGER(IntKi) :: k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'SolveOption2b_Inp2IfW' + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !> ++ Option 2: Solve for inputs based only on the current outputs. + !! This is much faster than option 1 when the coupled modules do not have direct feedthrough. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( p_FAST%CompElast == Module_BD .AND. .NOT. BD_Solve_Option1 ) THEN + DO k=1,p_FAST%nBeams + CALL BD_CalcOutput( this_time, BD%Input(1,k), BD%p(k), BD%x(k,this_state), BD%xd(k,this_state),& + BD%z(k,this_state), BD%OtherSt(k,this_state), BD%y(k), BD%m(k), ErrStat2, ErrMsg2, .false. ) ! this WriteOutput will get overwritten in solve option 1 + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + END IF + + ! find the positions where we want inflow wind in AeroDyn (i.e., set all the motion inputs to AeroDyn) + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD14_InputSolve_NoIfW( p_FAST, AD14%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF ( p_FAST%CompAero == Module_AD ) THEN + + ! note that this uses BD outputs, which are from the previous step (and need to be initialized) + CALL AD_InputSolve_NoIfW( p_FAST, AD%Input(1), SrvD%y, ED%y, BD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + IF (p_FAST%CompInflow == Module_IfW) THEN + ! must be done after ED_CalcOutput and before AD_CalcOutput and SrvD + CALL IfW_InputSolve( p_FAST, m_FAST, IfW%Input(:), IfW%p, AD14%Input(1), AD%Input(1), AD%OtherSt(1), ED%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !ELSE IF ( p_FAST%CompInflow == Module_OpFM ) THEN + ! ! OpenFOAM is the driver and it computes outputs outside of this solve; the OpenFOAM inputs and outputs thus don't change + ! ! in this scenario until OpenFOAM takes another step **this is a source of error, but it is the way the OpenFOAM-FAST7 coupling + ! ! works, so I'm not going to spend time that I don't have now to fix it** + ! CALL OpFM_SetInputs( p_FAST, AD14%p, AD14%Input(1), AD14%y, AD%Input(1), AD%y, ED%y, SrvD%y, OpFM, ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + +END SUBROUTINE SolveOption2b_Inp2IfW +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine implements the first part of the "option 2" solve for inputs that apply to AeroDyn and ServoDyn. +SUBROUTINE SolveOption2c_Inp2AD_SrvD(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat, ErrMsg, WriteThisStep) + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Misc variables for the glue code (including external inputs) + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'SolveOption2c_Inp2AD_SrvD' + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !> ++ Option 2: Solve for inputs based only on the current outputs. + !! This is much faster than option 1 when the coupled modules do not have direct feedthrough. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + + IF (p_FAST%CompInflow == Module_IfW) THEN + + CALL InflowWind_CalcOutput( this_time, IfW%Input(1), IfW%p, IfW%x(this_state), IfW%xd(this_state), IfW%z(this_state), & + IfW%OtherSt(this_state), IfW%y, IfW%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !ELSE IF ( p_FAST%CompInflow == Module_OpFM ) THEN + ! ! OpenFOAM is the driver and it computes outputs outside of this solve; the OpenFOAM inputs and outputs thus don't change + ! ! in this scenario until OpenFOAM takes another step **this is a source of error, but it is the way the OpenFOAM-FAST7 coupling + ! ! works, so I'm not going to spend time that I don't have now to fix it** + ! CALL OpFM_SetInputs( p_FAST, AD14%p, AD14%Input(1), AD14%y, AD%Input(1), AD%y, ED%y, SrvD%y, OpFM, ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! CALL OpFM_SetWriteOutput(OpFM) + + END IF + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD14_InputSolve_IfW( p_FAST, AD14%Input(1), IfW%y, OpFM%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF ( p_FAST%CompAero == Module_AD ) THEN + + CALL AD_InputSolve_IfW( p_FAST, AD%Input(1), IfW%y, OpFM%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + CALL SrvD_InputSolve( p_FAST, m_FAST, SrvD%Input(1), ED%y, IfW%y, OpFM%y, BD%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + +END SUBROUTINE SolveOption2c_Inp2AD_SrvD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine implements the "option 2" solve for all inputs without direct links to HD, SD, MAP, or the ED platform reference +!! point. +SUBROUTINE SolveOption2(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat, ErrMsg, firstCall, WriteThisStep) +!............................................................................................................................... + LOGICAL , intent(in ) :: firstCall !< flag to determine how to call ServoDyn (a hack) + REAL(DbKi) , intent(in ) :: this_time !< The current simulation time (actual or time of prediction) + INTEGER(IntKi) , intent(in ) :: this_state !< Index into the state array (current or predicted states) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Misc variables for the glue code (including external inputs) + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step? + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'SolveOption2' + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !> ++ Option 2: Solve for inputs based only on the current outputs. + !! This is much faster than option 1 when the coupled modules do not have direct feedthrough. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + + ! SolveOption2* routines are being called in FAST_AdvanceStates, but the first time we call CalcOutputs_And_SolveForInputs, we haven't called the AdvanceStates routine + IF (firstCall) THEN + ! call ElastoDyn's CalcOutput & compute BD inputs from ED: + CALL SolveOption2a_Inp2BD(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! compute AD position inputs; compute all of IfW inputs from ED/BD outputs: + CALL SolveOption2b_Inp2IfW(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! call IfW's CalcOutput; transfer wind-inflow inputs to AD; compute all of SrvD inputs: + CALL SolveOption2c_Inp2AD_SrvD(this_time, this_state, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! ELSE ! these subroutines are called in the AdvanceStates routine before BD, IfW, AD, and SrvD states are updated. This gives a more accurate solution that would otherwise require a correction step. + END IF + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD14_CalcOutput( this_time, AD14%Input(1), AD14%p, AD14%x(this_state), AD14%xd(this_state), AD14%z(this_state), & + AD14%OtherSt(this_state), AD14%y, AD14%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF ( p_FAST%CompAero == Module_AD ) THEN + + CALL AD_CalcOutput( this_time, AD%Input(1), AD%p, AD%x(this_state), AD%xd(this_state), AD%z(this_state), & + AD%OtherSt(this_state), AD%y, AD%m, ErrStat2, ErrMsg2, WriteThisStep ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + CALL SrvD_CalcOutput( this_time, SrvD%Input(1), SrvD%p, SrvD%x(this_state), SrvD%xd(this_state), SrvD%z(this_state), & + SrvD%OtherSt(this_state), SrvD%y, SrvD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + IF ( p_FAST%CompInflow == Module_OpFM ) THEN + ! OpenFOAM is the driver and it computes outputs outside of this solve; the OpenFOAM inputs and outputs thus don't change + ! in this scenario until OpenFOAM takes another step **this is a source of error, but it is the way the OpenFOAM-FAST7 coupling + ! works, so I'm not going to spend time that I don't have now to fix it** + ! note that I'm setting these inputs AFTER the call to ServoDyn so OpenFOAM gets all the inputs updated at the same step + CALL OpFM_SetInputs( p_FAST, AD14%p, AD14%Input(1), AD14%y, AD%Input(1), AD%y, ED%y, SrvD%y, OpFM, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL OpFM_SetWriteOutput(OpFM) + + END IF + + + !bjj: note ED%Input(1) may be a sibling mesh of output, but ED%u is not (routine may update something that needs to be shared between siblings) + CALL ED_InputSolve( p_FAST, ED%Input(1), ED%y, AD14%p, AD14%y, AD%y, SrvD%y, AD%Input(1), SrvD%Input(1), MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL BD_InputSolve( p_FAST, BD, AD%y, AD%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +END SUBROUTINE SolveOption2 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routines advances the states of each module +SUBROUTINE FAST_AdvanceStates( t_initial, n_t_global, p_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg, WriteThisStep ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial simulation time (almost always 0) + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< integer time step + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn v14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules (added to help BD get better root motion inputs) + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL , INTENT(IN ) :: WriteThisStep !< Will we print the WriteOutput values this step (for optimizations with SolveOption2)? + + ! local variables + INTEGER(IntKi) :: i, k ! loop counters + + REAL(DbKi) :: t_module ! Current simulation time for module + REAL(DbKi) :: t_global_next ! Simulation time for computing outputs + INTEGER(IntKi) :: j_ss ! substep loop counter + INTEGER(IntKi) :: n_t_module ! simulation time step, loop counter for individual modules + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_AdvanceStates' + + + + ErrStat = ErrID_None + ErrMsg = "" + + t_global_next = (n_t_global+1) * p_FAST%dt + t_initial + + !---------------------------------------------------------------------------------------- + ! copy the states at step m_FAST%t_global and get prediction for step t_global_next + ! (note that we need to copy the states because UpdateStates updates the values + ! and we need to have the old values [at m_FAST%t_global] for the next j_pc step) + !---------------------------------------------------------------------------------------- + ! ElastoDyn: get predicted states + CALL ED_CopyContState (ED%x( STATE_CURR), ED%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyDiscState (ED%xd(STATE_CURR), ED%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyConstrState (ED%z( STATE_CURR), ED%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOtherState (ED%OtherSt( STATE_CURR), ED%OtherSt( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( MODULE_ED ) + n_t_module = n_t_global*p_FAST%n_substeps( MODULE_ED ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( MODULE_ED ) + t_initial + + CALL ED_UpdateStates( t_module, n_t_module, ED%Input, ED%InputTimes, ED%p, ED%x(STATE_PRED), ED%xd(STATE_PRED), & + ED%z(STATE_PRED), ED%OtherSt(STATE_PRED), ED%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + END DO !j_ss + + + ! BeamDyn doesn't like extrapolated rotations, so we will calculate them from ED and transfer instead of doing a correction step. + ! (Also calls ED_CalcOutput here so that we can use it for AeroDyn optimization, too): + CALL SolveOption2a_Inp2BD(t_global_next, STATE_PRED, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( p_FAST%CompElast == Module_BD ) THEN + + DO k=1,p_FAST%nBeams + + CALL BD_CopyContState (BD%x( k,STATE_CURR),BD%x( k,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyDiscState (BD%xd(k,STATE_CURR),BD%xd(k,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyConstrState (BD%z( k,STATE_CURR),BD%z( k,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyOtherState (BD%OtherSt( k,STATE_CURR),BD%OtherSt( k,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_BD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_BD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_BD ) + t_initial + + CALL BD_UpdateStates( t_module, n_t_module, BD%Input(:,k), BD%InputTimes(:,k), BD%p(k), BD%x(k,STATE_PRED), & + BD%xd(k,STATE_PRED), BD%z(k,STATE_PRED), BD%OtherSt(k,STATE_PRED), BD%m(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':B'//trim(num2lstr(k))) + END DO !j_ss + + END DO !nBeams + IF (ErrStat >= AbortErrLev) RETURN + + END IF !CompElast + + + ! because AeroDyn DBEMT states depend heavily on getting inputs correct, we are overwriting its inputs with updated structural outputs here + CALL SolveOption2b_Inp2IfW(t_global_next, STATE_PRED, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! InflowWind: get predicted states + IF ( p_FAST%CompInflow == Module_IfW ) THEN + CALL InflowWind_CopyContState (IfW%x( STATE_CURR), IfW%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyDiscState (IfW%xd(STATE_CURR), IfW%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyConstrState (IfW%z( STATE_CURR), IfW%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyOtherState( IfW%OtherSt(STATE_CURR), IfW%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( MODULE_IfW ) + n_t_module = n_t_global*p_FAST%n_substeps( MODULE_IfW ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( MODULE_IfW ) + t_initial + + CALL InflowWind_UpdateStates( t_module, n_t_module, IfW%Input, IfW%InputTimes, IfW%p, IfW%x(STATE_PRED), IfW%xd(STATE_PRED), & + IfW%z(STATE_PRED), IfW%OtherSt(STATE_PRED), IfW%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + END IF + + + ! because AeroDyn DBEMT states depend heavily on getting inputs correct, we are overwriting its inputs with updated inflow outputs here + CALL SolveOption2c_Inp2AD_SrvD(t_global_next, STATE_PRED, p_FAST, m_FAST, ED, BD, AD14, AD, SrvD, IfW, OpFM, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! AeroDyn: get predicted states + IF ( p_FAST%CompAero == Module_AD14 ) THEN + CALL AD14_CopyContState (AD14%x( STATE_CURR), AD14%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyDiscState (AD14%xd(STATE_CURR), AD14%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyConstrState (AD14%z( STATE_CURR), AD14%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyOtherState( AD14%OtherSt(STATE_CURR), AD14%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( MODULE_AD14 ) + n_t_module = n_t_global*p_FAST%n_substeps( MODULE_AD14 ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( MODULE_AD14 ) + t_initial + + CALL AD14_UpdateStates( t_module, n_t_module, AD14%Input, AD14%InputTimes, AD14%p, AD14%x(STATE_PRED), & + AD14%xd(STATE_PRED), AD14%z(STATE_PRED), AD14%OtherSt(STATE_PRED), AD14%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + CALL AD_CopyContState (AD%x( STATE_CURR), AD%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyDiscState (AD%xd(STATE_CURR), AD%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyConstrState (AD%z( STATE_CURR), AD%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyOtherState( AD%OtherSt(STATE_CURR), AD%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( MODULE_AD ) + n_t_module = n_t_global*p_FAST%n_substeps( MODULE_AD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( MODULE_AD ) + t_initial + + CALL AD_UpdateStates( t_module, n_t_module, AD%Input, AD%InputTimes, AD%p, AD%x(STATE_PRED), & + AD%xd(STATE_PRED), AD%z(STATE_PRED), AD%OtherSt(STATE_PRED), AD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! We don't want to extrapolate any values for the WakeLocations (those are exactly calculated) + if (allocated(AD%OtherSt(STATE_PRED)%WakeLocationPoints)) then + AD%OtherSt(STATE_CURR)%WakeLocationPoints = AD%OtherSt(STATE_PRED)%WakeLocationPoints + endif + END DO !j_ss + END IF + + + ! ServoDyn: get predicted states + IF ( p_FAST%CompServo == Module_SrvD ) THEN + CALL SrvD_CopyContState (SrvD%x( STATE_CURR), SrvD%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyDiscState (SrvD%xd(STATE_CURR), SrvD%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyConstrState (SrvD%z( STATE_CURR), SrvD%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyOtherState (SrvD%OtherSt( STATE_CURR), SrvD%OtherSt( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_SrvD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_SrvD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_SrvD ) + t_initial + + CALL SrvD_UpdateStates( t_module, n_t_module, SrvD%Input, SrvD%InputTimes, SrvD%p, SrvD%x(STATE_PRED), SrvD%xd(STATE_PRED), & + SrvD%z(STATE_PRED), SrvD%OtherSt(STATE_PRED), SrvD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + END DO !j_ss + END IF + + + ! HydroDyn: get predicted states + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CopyContState (HD%x( STATE_CURR), HD%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyDiscState (HD%xd(STATE_CURR), HD%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyConstrState (HD%z( STATE_CURR), HD%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOtherState( HD%OtherSt(STATE_CURR), HD%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_HD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_HD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_HD ) + t_initial + + CALL HydroDyn_UpdateStates( t_module, n_t_module, HD%Input, HD%InputTimes, HD%p, HD%x(STATE_PRED), HD%xd(STATE_PRED), & + HD%z(STATE_PRED), HD%OtherSt(STATE_PRED), HD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + + END IF + + + ! SubDyn/ExtPtfm: get predicted states + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CopyContState (SD%x( STATE_CURR), SD%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyDiscState (SD%xd(STATE_CURR), SD%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyConstrState (SD%z( STATE_CURR), SD%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOtherState( SD%OtherSt(STATE_CURR), SD%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_SD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_SD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_SD ) + t_initial + + CALL SD_UpdateStates( t_module, n_t_module, SD%Input, SD%InputTimes, SD%p, SD%x(STATE_PRED), SD%xd(STATE_PRED), & + SD%z(STATE_PRED), SD%OtherSt(STATE_PRED), SD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + ! ExtPtfm: get predicted states + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CopyContState (ExtPtfm%x( STATE_CURR), ExtPtfm%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyDiscState (ExtPtfm%xd(STATE_CURR), ExtPtfm%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyConstrState (ExtPtfm%z( STATE_CURR), ExtPtfm%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOtherState( ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_ExtPtfm ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_ExtPtfm ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_ExtPtfm ) + t_initial + + CALL ExtPtfm_UpdateStates( t_module, n_t_module, ExtPtfm%Input, ExtPtfm%InputTimes, ExtPtfm%p, ExtPtfm%x(STATE_PRED), & + ExtPtfm%xd(STATE_PRED), ExtPtfm%z(STATE_PRED), ExtPtfm%OtherSt(STATE_PRED), ExtPtfm%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + END IF + + + ! Mooring: MAP/FEAM/MD/Orca: get predicted states + IF (p_FAST%CompMooring == Module_MAP) THEN + CALL MAP_CopyContState (MAPp%x( STATE_CURR), MAPp%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyDiscState (MAPp%xd(STATE_CURR), MAPp%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyConstrState (MAPp%z( STATE_CURR), MAPp%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! OtherStates in MAP++ acts like misc variables: + !CALL MAP_CopyOtherState( MAPp%OtherSt(STATE_CURR), MAPp%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + ! CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_MAP ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_MAP ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_MAP ) + t_initial + + CALL MAP_UpdateStates( t_module, n_t_module, MAPp%Input, MAPp%InputTimes, MAPp%p, MAPp%x(STATE_PRED), MAPp%xd(STATE_PRED), MAPp%z(STATE_PRED), MAPp%OtherSt, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + CALL MD_CopyContState (MD%x( STATE_CURR), MD%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyDiscState (MD%xd(STATE_CURR), MD%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyConstrState (MD%z( STATE_CURR), MD%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyOtherState( MD%OtherSt(STATE_CURR), MD%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_MD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_MD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_MD ) + t_initial + + CALL MD_UpdateStates( t_module, n_t_module, MD%Input, MD%InputTimes, MD%p, MD%x(STATE_PRED), MD%xd(STATE_PRED), & + MD%z(STATE_PRED), MD%OtherSt(STATE_PRED), MD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + CALL FEAM_CopyContState (FEAM%x( STATE_CURR), FEAM%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyDiscState (FEAM%xd(STATE_CURR), FEAM%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyConstrState (FEAM%z( STATE_CURR), FEAM%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyOtherState( FEAM%OtherSt(STATE_CURR), FEAM%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_FEAM ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_FEAM ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_FEAM ) + t_initial + + CALL FEAM_UpdateStates( t_module, n_t_module, FEAM%Input, FEAM%InputTimes, FEAM%p, FEAM%x(STATE_PRED), FEAM%xd(STATE_PRED), & + FEAM%z(STATE_PRED), FEAM%OtherSt(STATE_PRED), FEAM%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + + ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + CALL Orca_CopyContState (Orca%x( STATE_CURR), Orca%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyDiscState (Orca%xd(STATE_CURR), Orca%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyConstrState (Orca%z( STATE_CURR), Orca%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyOtherState( Orca%OtherSt(STATE_CURR), Orca%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_Orca ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_Orca ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_Orca ) + t_initial + + CALL Orca_UpdateStates( t_module, n_t_module, Orca%Input, Orca%InputTimes, Orca%p, Orca%x(STATE_PRED), & + Orca%xd(STATE_PRED), Orca%z(STATE_PRED), Orca%OtherSt(STATE_PRED), Orca%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + + END IF + + + ! IceFloe/IceDyn: get predicted states + IF ( p_FAST%CompIce == Module_IceF ) THEN + CALL IceFloe_CopyContState (IceF%x( STATE_CURR), IceF%x( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyDiscState (IceF%xd(STATE_CURR), IceF%xd(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyConstrState (IceF%z( STATE_CURR), IceF%z( STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyOtherState( IceF%OtherSt(STATE_CURR), IceF%OtherSt(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_IceF ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_IceF ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_IceF ) + t_initial + + CALL IceFloe_UpdateStates( t_module, n_t_module, IceF%Input, IceF%InputTimes, IceF%p, IceF%x(STATE_PRED), & + IceF%xd(STATE_PRED), IceF%z(STATE_PRED), IceF%OtherSt(STATE_PRED), IceF%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + DO i=1,p_FAST%numIceLegs + + CALL IceD_CopyContState (IceD%x( i,STATE_CURR),IceD%x( i,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyDiscState (IceD%xd(i,STATE_CURR),IceD%xd(i,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyConstrState (IceD%z( i,STATE_CURR),IceD%z( i,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyOtherState( IceD%OtherSt(i,STATE_CURR), IceD%OtherSt(i,STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + DO j_ss = 1, p_FAST%n_substeps( Module_IceD ) + n_t_module = n_t_global*p_FAST%n_substeps( Module_IceD ) + j_ss - 1 + t_module = n_t_module*p_FAST%dt_module( Module_IceD ) + t_initial + + CALL IceD_UpdateStates( t_module, n_t_module, IceD%Input(:,i), IceD%InputTimes(:,i), IceD%p(i), IceD%x(i,STATE_PRED), & + IceD%xd(i,STATE_PRED), IceD%z(i,STATE_PRED), IceD%OtherSt(i,STATE_PRED), IceD%m(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO !j_ss + END DO + + END IF + +END SUBROUTINE FAST_AdvanceStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine extrapolates inputs to modules to give predicted values at t+dt. +SUBROUTINE FAST_ExtrapInterpMods( t_global_next, p_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_global_next !< next global time step (t + dt), at which we're extrapolating inputs (and ED outputs) + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + !TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData ! Data for mapping between modules + + 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, j, k ! loop counters + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_ExtrapInterpMods' + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! Step 1.a: Extrapolate Inputs (gives predicted values at t+dt) + ! + ! a) Extrapolate inputs + ! to t + dt (i.e., t_global_next); will only be used by modules with an implicit dependence on input data. + ! b) Shift "window" of the ModName%Input + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ErrStat = ErrID_None + ErrMsg = "" + + ! ElastoDyn + CALL ED_Input_ExtrapInterp(ED%Input, ED%InputTimes, ED%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + DO j = p_FAST%InterpOrder, 1, -1 + CALL ED_CopyInput (ED%Input(j), ED%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + ED%InputTimes(j+1) = ED%InputTimes(j) + !ED_OutputTimes(j+1) = ED_OutputTimes(j) + END DO + + CALL ED_CopyInput (ED%u, ED%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + ED%InputTimes(1) = t_global_next + !ED_OutputTimes(1) = t_global_next + + + ! BeamDyn + IF (p_FAST%CompElast == Module_BD) THEN + + DO k = 1,p_FAST%nBeams + + CALL BD_Input_ExtrapInterp(BD%Input(:,k), BD%InputTimes(:,k), BD%u(k), t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of BD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL BD_CopyInput (BD%Input(j,k), BD%Input(j+1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + BD%InputTimes(j+1,k) = BD%InputTimes(j,k) + END DO + + CALL BD_CopyInput (BD%u(k), BD%Input(1,k), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + BD%InputTimes(1,k) = t_global_next + + END DO ! k=p_FAST%nBeams + + END IF ! BeamDyn + + ! AeroDyn v14 + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD14_Input_ExtrapInterp(AD14%Input, AD14%InputTimes, AD14%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of AD14%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL AD14_CopyInput (AD14%Input(j), AD14%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + AD14%InputTimes(j+1) = AD14%InputTimes(j) + END DO + + CALL AD14_CopyInput (AD14%u, AD14%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + AD14%InputTimes(1) = t_global_next + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + CALL AD_Input_ExtrapInterp(AD%Input, AD%InputTimes, AD%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of AD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL AD_CopyInput (AD%Input(j), AD%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + AD%InputTimes(j+1) = AD%InputTimes(j) + END DO + + CALL AD_CopyInput (AD%u, AD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + AD%InputTimes(1) = t_global_next + + END IF ! CompAero + + + ! InflowWind + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + CALL InflowWind_Input_ExtrapInterp(IfW%Input, IfW%InputTimes, IfW%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of IfW%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL InflowWind_CopyInput (IfW%Input(j), IfW%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IfW%InputTimes(j+1) = IfW%InputTimes(j) + END DO + + CALL InflowWind_CopyInput (IfW%u, IfW%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IfW%InputTimes(1) = t_global_next + + END IF ! CompInflow + + + ! ServoDyn + IF ( p_FAST%CompServo == Module_SrvD ) THEN + + CALL SrvD_Input_ExtrapInterp(SrvD%Input, SrvD%InputTimes, SrvD%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of SrvD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL SrvD_CopyInput (SrvD%Input(j), SrvD%Input(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + SrvD%InputTimes(j+1) = SrvD%InputTimes(j) + END DO + + CALL SrvD_CopyInput (SrvD%u, SrvD%Input(1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + SrvD%InputTimes(1) = t_global_next + + END IF ! ServoDyn + + ! HydroDyn + IF ( p_FAST%CompHydro == Module_HD ) THEN + + CALL HydroDyn_Input_ExtrapInterp(HD%Input, HD%InputTimes, HD%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of HD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + + CALL HydroDyn_CopyInput (HD%Input(j), HD%Input(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + HD%InputTimes(j+1) = HD%InputTimes(j) + END DO + + CALL HydroDyn_CopyInput (HD%u, HD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + HD%InputTimes(1) = t_global_next + + END IF ! HydroDyn + + + ! SubDyn/ExtPtfm_MCKF + IF ( p_FAST%CompSub == Module_SD ) THEN + + CALL SD_Input_ExtrapInterp(SD%Input, SD%InputTimes, SD%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of SD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL SD_CopyInput (SD%Input(j), SD%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + SD%InputTimes(j+1) = SD%InputTimes(j) + END DO + + CALL SD_CopyInput (SD%u, SD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + SD%InputTimes(1) = t_global_next + + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + + CALL ExtPtfm_Input_ExtrapInterp(ExtPtfm%Input, ExtPtfm%InputTimes, ExtPtfm%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of ExtPtfm%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL ExtPtfm_CopyInput (ExtPtfm%Input(j), ExtPtfm%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + ExtPtfm%InputTimes(j+1) = ExtPtfm%InputTimes(j) + END DO + + CALL ExtPtfm_CopyInput (ExtPtfm%u, ExtPtfm%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + ExtPtfm%InputTimes(1) = t_global_next + END IF ! SubDyn/ExtPtfm_MCKF + + + ! Mooring (MAP , FEAM , MoorDyn) + ! MAP + IF ( p_FAST%CompMooring == Module_MAP ) THEN + + CALL MAP_Input_ExtrapInterp(MAPp%Input, MAPp%InputTimes, MAPp%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of MAPp%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL MAP_CopyInput (MAPp%Input(j), MAPp%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + MAPp%InputTimes(j+1) = MAPp%InputTimes(j) + END DO + + CALL MAP_CopyInput (MAPp%u, MAPp%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + MAPp%InputTimes(1) = t_global_next + + ! MoorDyn + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + + CALL MD_Input_ExtrapInterp(MD%Input, MD%InputTimes, MD%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of MD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL MD_CopyInput (MD%Input(j), MD%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + MD%InputTimes( j+1) = MD%InputTimes( j) + END DO + + CALL MD_CopyInput (MD%u, MD%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + MD%InputTimes(1) = t_global_next + + ! FEAM + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + + CALL FEAM_Input_ExtrapInterp(FEAM%Input, FEAM%InputTimes, FEAM%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of FEAM%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL FEAM_CopyInput (FEAM%Input(j), FEAM%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + FEAM%InputTimes( j+1) = FEAM%InputTimes( j) + END DO + + CALL FEAM_CopyInput (FEAM%u, FEAM%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + FEAM%InputTimes(1) = t_global_next + + ! OrcaFlex + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + + CALL Orca_Input_ExtrapInterp(Orca%Input, Orca%InputTimes, Orca%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of Orca%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL Orca_CopyInput (Orca%Input(j), Orca%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + Orca%InputTimes( j+1) = Orca%InputTimes( j) + END DO + + CALL Orca_CopyInput (Orca%u, Orca%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + Orca%InputTimes(1) = t_global_next + + END IF ! MAP/FEAM/MoorDyn/OrcaFlex + + + + ! Ice (IceFloe or IceDyn) + ! IceFloe + IF ( p_FAST%CompIce == Module_IceF ) THEN + + CALL IceFloe_Input_ExtrapInterp(IceF%Input, IceF%InputTimes, IceF%u, t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of IceF%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL IceFloe_CopyInput (IceF%Input(j), IceF%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IceF%InputTimes(j+1) = IceF%InputTimes(j) + END DO + + CALL IceFloe_CopyInput (IceF%u, IceF%Input(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IceF%InputTimes(1) = t_global_next + + ! IceDyn + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + DO i = 1,p_FAST%numIceLegs + + CALL IceD_Input_ExtrapInterp(IceD%Input(:,i), IceD%InputTimes(:,i), IceD%u(i), t_global_next, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + ! Shift "window" of IceD%Input + + DO j = p_FAST%InterpOrder, 1, -1 + CALL IceD_CopyInput (IceD%Input(j,i), IceD%Input(j+1,i), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IceD%InputTimes(j+1,i) = IceD%InputTimes(j,i) + END DO + + CALL IceD_CopyInput (IceD%u(i), IceD%Input(1,i), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + IceD%InputTimes(1,i) = t_global_next + + END DO ! numIceLegs + + + END IF ! IceFloe/IceDyn + + +END SUBROUTINE FAST_ExtrapInterpMods +!---------------------------------------------------------------------------------------------------------------------------------- + + + +END MODULE FAST_Solver diff --git a/OpenFAST/modules/openfast-library/src/FAST_Subs.f90 b/OpenFAST/modules/openfast-library/src/FAST_Subs.f90 new file mode 100644 index 000000000..2cbe6cd78 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Subs.f90 @@ -0,0 +1,7281 @@ +!********************************************************************************************************************************** +! FAST_Solver.f90, FAST_Subs.f90, FAST_Lin.f90, and FAST_Mods.f90 make up the FAST glue code in the FAST Modularization Framework. +! FAST_Prog.f90, FAST_Library.f90, FAST_Prog.c are different drivers for this code. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST. +! +! 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 FAST_Subs + + USE FAST_Solver + USE FAST_Linear + + IMPLICIT NONE + +CONTAINS +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! INITIALIZATION ROUTINES +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> a wrapper routine to call FAST_Initialize a the full-turbine simulation level (makes easier to write top-level driver) +SUBROUTINE FAST_InitializeAll_T( t_initial, TurbID, Turbine, ErrStat, ErrMsg, InFile, ExternInitData ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + INTEGER(IntKi), INTENT(IN ) :: TurbID !< turbine Identifier (1-NumTurbines) + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + CHARACTER(*), OPTIONAL,INTENT(IN ) :: InFile !< A CHARACTER string containing the name of the primary FAST input file (if not present, we'll get it from the command line) + TYPE(FAST_ExternInitType),OPTIONAL,INTENT(IN ) :: ExternInitData !< Initialization input data from an external source (Simulink) + + Turbine%TurbID = TurbID + + + IF (PRESENT(InFile)) THEN + IF (PRESENT(ExternInitData)) THEN + CALL FAST_InitializeAll( t_initial, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, Turbine%SC,& + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg, InFile, ExternInitData ) + ELSE + CALL FAST_InitializeAll( t_initial, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, Turbine%SC, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg, InFile ) + END IF + ELSE + CALL FAST_InitializeAll( t_initial, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, Turbine%SC, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg ) + END IF + + +END SUBROUTINE FAST_InitializeAll_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to call Init routine for each module. This routine sets all of the init input data for each module. +SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, SC, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg, InFile, ExternInitData ) + + use ElastoDyn_Parameters, only: Method_RK4 + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(SuperController_Data), INTENT(INOUT) :: SC !< SuperController data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + CHARACTER(*), OPTIONAL, INTENT(IN ) :: InFile !< A CHARACTER string containing the name of the primary FAST input file (if not present, we'll get it from the command line) + + TYPE(FAST_ExternInitType), OPTIONAL, INTENT(IN) :: ExternInitData !< Initialization input data from an external source (Simulink) + + ! local variables + CHARACTER(1024) :: InputFile !< A CHARACTER string containing the name of the primary FAST input file + TYPE(FAST_InitData) :: Init !< Initialization data for all modules + + + REAL(ReKi) :: AirDens ! air density for initialization/normalization of OpenFOAM data + REAL(DbKi) :: dt_IceD ! tmp dt variable to ensure IceDyn doesn't specify different dt values for different legs (IceDyn instances) + REAL(DbKi) :: dt_BD ! tmp dt variable to ensure BeamDyn doesn't specify different dt values for different instances + INTEGER(IntKi) :: ErrStat2 + INTEGER(IntKi) :: IceDim ! dimension we're pre-allocating for number of IceDyn legs/instances + INTEGER(IntKi) :: I ! generic loop counter + INTEGER(IntKi) :: k ! blade loop counter + logical :: CallStart + + CHARACTER(ErrMsgLen) :: ErrMsg2 + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_InitializeAll' + + + !.......... + ErrStat = ErrID_None + ErrMsg = "" + + y_FAST%UnSum = -1 ! set the summary file unit to -1 to indicate it's not open + y_FAST%UnOu = -1 ! set the text output file unit to -1 to indicate it's not open + y_FAST%UnGra = -1 ! set the binary graphics output file unit to -1 to indicate it's not open + + p_FAST%WrVTK = VTK_Unknown ! set this so that we can potentially output VTK information on initialization error + p_FAST%VTK_tWidth = 1 ! initialize in case of error before reading the full file + p_FAST%n_VTKTime = 1 ! initialize in case of error before reading the full file + y_FAST%VTK_LastWaveIndx = 1 ! Start looking for wave data at the first index + y_FAST%VTK_count = 0 ! first VTK file has 0 as output + y_FAST%n_Out = 0 ! set the number of ouptut channels to 0 to indicate there's nothing to write to the binary file + p_FAST%ModuleInitialized = .FALSE. ! (array initialization) no modules are initialized + + ! Get the current time + CALL DATE_AND_TIME ( Values=m_FAST%StrtTime ) ! Let's time the whole simulation + CALL CPU_TIME ( m_FAST%UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + m_FAST%UsrTime1 = MAX( 0.0_ReKi, m_FAST%UsrTime1 ) ! CPU_TIME: If a meaningful time cannot be returned, a processor-dependent negative value is returned + + + m_FAST%t_global = t_initial - 20. ! initialize this to a number < t_initial for error message in ProgAbort + m_FAST%calcJacobian = .TRUE. ! we need to calculate the Jacobian + m_FAST%NextJacCalcTime = m_FAST%t_global ! We want to calculate the Jacobian on the first step + p_FAST%TDesc = '' +! p_FAST%CheckHSSBrTrqC = .false. + + y_FAST%Lin%WindSpeed = 0.0_ReKi + + if (present(ExternInitData)) then + CallStart = .not. ExternInitData%FarmIntegration ! .and. ExternInitData%TurbineID == 1 + if (ExternInitData%TurbineID > 0) p_FAST%TDesc = 'T'//trim(num2lstr(ExternInitData%TurbineID)) + else + CallStart = .true. + end if + + + ! Init NWTC_Library, display copyright and version information: + if (CallStart) then + AbortErrLev = ErrID_Fatal ! Until we read otherwise from the FAST input file, we abort only on FATAL errors + CALL FAST_ProgStart( FAST_Ver ) + p_FAST%WrSttsTime = .TRUE. + else + ! if we don't call the start data (e.g., from FAST.Farm), we won't override AbortErrLev either + CALL DispNVD( FAST_Ver ) + p_FAST%WrSttsTime = .FALSE. + end if + + IF (PRESENT(InFile)) THEN + p_FAST%UseDWM = .FALSE. + InputFile = InFile + ELSE + CALL GetInputFileName(InputFile,p_FAST%UseDWM,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END IF + + ! ... Open and read input files ... + ! also, set turbine reference position for graphics output + if (PRESENT(ExternInitData)) then + p_FAST%TurbinePos = ExternInitData%TurbinePos + + if (ExternInitData%FarmIntegration) then ! we're integrating with FAST.Farm + CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2, ExternInitData%TMax, OverrideAbortLev=.false., RootName=ExternInitData%RootName ) + else + CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2, ExternInitData%TMax, ExternInitData%TurbineID ) ! We have the name of the input file and the simulation length from somewhere else (e.g. Simulink) + end if + + else + p_FAST%TurbinePos = 0.0_ReKi + CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2 ) ! We have the name of the input file from somewhere else (e.g. Simulink) + end if + + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !............................................................................................................................... + + p_FAST%dt_module = p_FAST%dt ! initialize time steps for each module + + ! ........................ + ! initialize ElastoDyn (must be done first) + ! ........................ + + ALLOCATE( ED%Input( p_FAST%InterpOrder+1 ), ED%InputTimes( p_FAST%InterpOrder+1 ),STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating ED%Input and ED%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + Init%InData_ED%Linearize = p_FAST%Linearize + Init%InData_ED%InputFile = p_FAST%EDFile + IF ( p_FAST%CompAero == Module_AD14 ) THEN + Init%InData_ED%ADInputFile = p_FAST%AeroFile + ELSE + Init%InData_ED%ADInputFile = "" + END IF + + Init%InData_ED%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_ED)) + Init%InData_ED%CompElast = p_FAST%CompElast == Module_ED + + CALL ED_Init( Init%InData_ED, ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y, ED%m, p_FAST%dt_module( MODULE_ED ), Init%OutData_ED, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_ED) = .TRUE. + CALL SetModuleSubstepTime(Module_ED, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! bjj: added this check per jmj; perhaps it would be better in ElastoDyn, but I'll leave it here for now: + IF ( p_FAST%TurbineType == Type_Offshore_Floating ) THEN + IF ( ED%p%TowerBsHt < 0.0_ReKi .AND. .NOT. EqualRealNos( ED%p%TowerBsHt, 0.0_ReKi ) ) THEN + CALL SetErrStat(ErrID_Fatal,"ElastoDyn TowerBsHt must not be negative for floating offshore systems.",ErrStat,ErrMsg,RoutineName) + END IF + END IF + + allocate( y_FAST%Lin%Modules(MODULE_ED)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(ED).", ErrStat, ErrMsg, RoutineName ) + else + + if (allocated(Init%OutData_ED%LinNames_y)) call move_alloc(Init%OutData_ED%LinNames_y,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%Names_y) + if (allocated(Init%OutData_ED%LinNames_x)) call move_alloc(Init%OutData_ED%LinNames_x,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%Names_x) + if (allocated(Init%OutData_ED%LinNames_u)) call move_alloc(Init%OutData_ED%LinNames_u,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%Names_u) + if (allocated(Init%OutData_ED%RotFrame_y)) call move_alloc(Init%OutData_ED%RotFrame_y,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%RotFrame_y) + if (allocated(Init%OutData_ED%RotFrame_x)) call move_alloc(Init%OutData_ED%RotFrame_x,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%RotFrame_x) + if (allocated(Init%OutData_ED%DerivOrder_x)) call move_alloc(Init%OutData_ED%DerivOrder_x,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%DerivOrder_x) + if (allocated(Init%OutData_ED%RotFrame_u)) call move_alloc(Init%OutData_ED%RotFrame_u,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%RotFrame_u) + if (allocated(Init%OutData_ED%IsLoad_u )) call move_alloc(Init%OutData_ED%IsLoad_u ,y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%IsLoad_u ) + + if (allocated(Init%OutData_ED%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%NumOutputs = size(Init%OutData_ED%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + if (p_FAST%CalcSteady) then + if ( EqualRealNos(Init%OutData_ED%RotSpeed, 0.0_ReKi) ) then + p_FAST%TrimCase = TrimCase_none + p_FAST%NLinTimes = 1 + p_FAST%LinInterpOrder = 0 ! constant values + elseif ( Init%OutData_ED%isFixed_GenDOF ) then + p_FAST%TrimCase = TrimCase_none + end if + end if + + + ! ........................ + ! initialize BeamDyn + ! ........................ + IF ( p_FAST%CompElast == Module_BD ) THEN + p_FAST%nBeams = Init%OutData_ED%NumBl ! initialize number of BeamDyn instances = number of blades + ELSE + p_FAST%nBeams = 0 + END IF + + ALLOCATE( BD%Input( p_FAST%InterpOrder+1, p_FAST%nBeams ), BD%InputTimes( p_FAST%InterpOrder+1, p_FAST%nBeams ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating BD%Input and BD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ALLOCATE( BD%x( p_FAST%nBeams,2), & + BD%xd( p_FAST%nBeams,2), & + BD%z( p_FAST%nBeams,2), & + BD%OtherSt( p_FAST%nBeams,2), & + BD%p( p_FAST%nBeams ), & + BD%u( p_FAST%nBeams ), & + BD%y( p_FAST%nBeams ), & + BD%m( p_FAST%nBeams ), & + Init%OutData_BD(p_FAST%nBeams ), & + STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating BeamDyn state, input, and output data.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + IF (p_FAST%CompElast == Module_BD) THEN + + Init%InData_BD%DynamicSolve = .TRUE. ! FAST can only couple to BeamDyn when dynamic solve is used. + + Init%InData_BD%Linearize = p_FAST%Linearize + Init%InData_BD%gravity = (/ 0.0_ReKi, 0.0_ReKi, -Init%OutData_ED%Gravity /) ! "Gravitational acceleration" m/s^2 + + ! now initialize BeamDyn for all beams + dt_BD = p_FAST%dt_module( MODULE_BD ) + + Init%InData_BD%HubPos = ED%y%HubPtMotion%Position(:,1) + Init%InData_BD%HubRot = ED%y%HubPtMotion%RefOrientation(:,:,1) + + p_FAST%BD_OutputSibling = .true. + + allocate( y_FAST%Lin%Modules(MODULE_BD)%Instance(p_FAST%nBeams), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(BD).", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + end if + + DO k=1,p_FAST%nBeams + Init%InData_BD%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_BD))//TRIM( Num2LStr(k) ) + + + Init%InData_BD%InputFile = p_FAST%BDBldFile(k) + + Init%InData_BD%GlbPos = ED%y%BladeRootMotion(k)%Position(:,1) ! {:} - - "Initial Position Vector of the local blade coordinate system" + Init%InData_BD%GlbRot = ED%y%BladeRootMotion(k)%RefOrientation(:,:,1) ! {:}{:} - - "Initial direction cosine matrix of the local blade coordinate system" + + Init%InData_BD%RootDisp = ED%y%BladeRootMotion(k)%TranslationDisp(:,1) ! {:} - - "Initial root displacement" + Init%InData_BD%RootOri = ED%y%BladeRootMotion(k)%Orientation(:,:,1) ! {:}{:} - - "Initial root orientation" + Init%InData_BD%RootVel(1:3) = ED%y%BladeRootMotion(k)%TranslationVel(:,1) ! {:} - - "Initial root velocities and angular veolcities" + Init%InData_BD%RootVel(4:6) = ED%y%BladeRootMotion(k)%RotationVel(:,1) ! {:} - - "Initial root velocities and angular veolcities" + + CALL BD_Init( Init%InData_BD, BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), & + BD%OtherSt(k,STATE_CURR), BD%y(k), BD%m(k), dt_BD, Init%OutData_BD(k), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !bjj: we're going to force this to have the same timestep because I don't want to have to deal with n BD modules with n timesteps. + IF ( k == 1 ) THEN + p_FAST%dt_module( MODULE_BD ) = dt_BD + + p_FAST%ModuleInitialized(Module_BD) = .TRUE. ! this really should be once per BD instance, but BD doesn't care so I won't go through the effort to track this + CALL SetModuleSubstepTime(Module_BD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ELSEIF ( .NOT. EqualRealNos( p_FAST%dt_module( MODULE_BD ),dt_BD )) THEN + CALL SetErrStat(ErrID_Fatal,"All instances of BeamDyn (one per blade) must have the same time step.",ErrStat,ErrMsg,RoutineName) + END IF + + ! We're going to do fewer computations if the BD input and output meshes that couple to AD are siblings: + if (BD%p(k)%BldMotionNodeLoc /= BD_MESH_QP) p_FAST%BD_OutputSibling = .false. + + if (ErrStat>=AbortErrLev) exit !exit this loop so we don't get p_FAST%nBeams of the same errors + + if (allocated(Init%OutData_BD(k)%LinNames_y)) call move_alloc(Init%OutData_BD(k)%LinNames_y, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%Names_y ) + if (allocated(Init%OutData_BD(k)%LinNames_x)) call move_alloc(Init%OutData_BD(k)%LinNames_x, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%Names_x ) + if (allocated(Init%OutData_BD(k)%LinNames_u)) call move_alloc(Init%OutData_BD(k)%LinNames_u, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%Names_u ) + if (allocated(Init%OutData_BD(k)%RotFrame_y)) call move_alloc(Init%OutData_BD(k)%RotFrame_y, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%RotFrame_y ) + if (allocated(Init%OutData_BD(k)%RotFrame_x)) call move_alloc(Init%OutData_BD(k)%RotFrame_x, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%RotFrame_x ) + if (allocated(Init%OutData_BD(k)%RotFrame_u)) call move_alloc(Init%OutData_BD(k)%RotFrame_u, y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%RotFrame_u ) + if (allocated(Init%OutData_BD(k)%IsLoad_u )) call move_alloc(Init%OutData_BD(k)%IsLoad_u , y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%IsLoad_u ) + if (allocated(Init%OutData_BD(k)%DerivOrder_x )) call move_alloc(Init%OutData_BD(k)%DerivOrder_x , y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%DerivOrder_x ) + + if (allocated(Init%OutData_BD(k)%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%NumOutputs = size(Init%OutData_BD(k)%WriteOutputHdr) + + END DO + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END IF + + + ! ........................ + ! initialize AeroDyn + ! ........................ + ALLOCATE( AD14%Input( p_FAST%InterpOrder+1 ), AD14%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating AD14%Input and AD14%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ALLOCATE( AD%Input( p_FAST%InterpOrder+1 ), AD%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating AD%Input and AD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + + CALL AD_SetInitInput(Init%InData_AD14, Init%OutData_ED, ED%y, p_FAST, ErrStat2, ErrMsg2) ! set the values in Init%InData_AD14 + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL AD14_Init( Init%InData_AD14, AD14%Input(1), AD14%p, AD14%x(STATE_CURR), AD14%xd(STATE_CURR), AD14%z(STATE_CURR), & + AD14%OtherSt(STATE_CURR), AD14%y, AD14%m, p_FAST%dt_module( MODULE_AD14 ), Init%OutData_AD14, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_AD14) = .TRUE. + CALL SetModuleSubstepTime(Module_AD14, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! bjj: this really shouldn't be in the FAST glue code, but I'm going to put this check here so people don't use an invalid model + ! and send me emails to debug numerical issues in their results. + IF ( AD14%p%TwrProps%PJM_Version .AND. p_FAST%TurbineType == Type_Offshore_Floating ) THEN + CALL SetErrStat(ErrID_Fatal,'AeroDyn v14 tower influence model "NEWTOWER" is invalid for models of floating offshore turbines.',ErrStat,ErrMsg,RoutineName) + END IF + + AirDens = Init%OutData_AD14%AirDens + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + + + ! set initialization data for AD + CALL AllocAry( Init%InData_AD%BladeRootPosition, 3, Init%OutData_ED%NumBl, 'Init%InData_AD%BladeRootPosition', errStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( Init%InData_AD%BladeRootOrientation,3, 3, Init%OutData_ED%NumBl, 'Init%InData_AD%BladeRootOrientation', errStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + Init%InData_AD%Gravity = Init%OutData_ED%Gravity + Init%InData_AD%Linearize = p_FAST%Linearize + Init%InData_AD%InputFile = p_FAST%AeroFile + Init%InData_AD%NumBlades = Init%OutData_ED%NumBl + Init%InData_AD%RootName = p_FAST%OutFileRoot + Init%InData_AD%HubPosition = ED%y%HubPtMotion%Position(:,1) + Init%InData_AD%HubOrientation = ED%y%HubPtMotion%RefOrientation(:,:,1) + + do k=1,Init%OutData_ED%NumBl + Init%InData_AD%BladeRootPosition(:,k) = ED%y%BladeRootMotion(k)%Position(:,1) + Init%InData_AD%BladeRootOrientation(:,:,k) = ED%y%BladeRootMotion(k)%RefOrientation(:,:,1) + end do + + + CALL AD_Init( Init%InData_AD, AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), & + AD%OtherSt(STATE_CURR), AD%y, AD%m, p_FAST%dt_module( MODULE_AD ), Init%OutData_AD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_AD) = .TRUE. + CALL SetModuleSubstepTime(Module_AD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(MODULE_AD)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(AD).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_AD%LinNames_u )) call move_alloc(Init%OutData_AD%LinNames_u ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%Names_u ) + if (allocated(Init%OutData_AD%LinNames_y )) call move_alloc(Init%OutData_AD%LinNames_y ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%Names_y ) + if (allocated(Init%OutData_AD%LinNames_x )) call move_alloc(Init%OutData_AD%LinNames_x ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%Names_x ) + if (allocated(Init%OutData_AD%RotFrame_u )) call move_alloc(Init%OutData_AD%RotFrame_u ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%RotFrame_u ) + if (allocated(Init%OutData_AD%RotFrame_y )) call move_alloc(Init%OutData_AD%RotFrame_y ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%RotFrame_y ) + if (allocated(Init%OutData_AD%RotFrame_x )) call move_alloc(Init%OutData_AD%RotFrame_x ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%RotFrame_x ) + if (allocated(Init%OutData_AD%IsLoad_u )) call move_alloc(Init%OutData_AD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%IsLoad_u ) + if (allocated(Init%OutData_AD%DerivOrder_x)) call move_alloc(Init%OutData_AD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%DerivOrder_x ) + + if (allocated(Init%OutData_AD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%NumOutputs = size(Init%OutData_AD%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + AirDens = Init%OutData_AD%AirDens + + ELSE + AirDens = 0.0_ReKi + END IF ! CompAero + + + ! ........................ + ! initialize InflowWind + ! ........................ + ALLOCATE( IfW%Input( p_FAST%InterpOrder+1 ), IfW%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating IfW%Input and IfW%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + + Init%InData_IfW%Linearize = p_FAST%Linearize + Init%InData_IfW%InputFileName = p_FAST%InflowFile + Init%InData_IfW%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_IfW)) + Init%InData_IfW%UseInputFile = .TRUE. + + Init%InData_IfW%NumWindPoints = 0 + IF ( p_FAST%CompServo == Module_SrvD ) Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + 1 + IF ( p_FAST%CompAero == Module_AD14 ) THEN + Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + Init%OutData_ED%NumBl * AD14%Input(1)%InputMarkers(1)%NNodes + AD14%Input(1)%Twr_InputMarkers%NNodes + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + AD%Input(1)%TowerMotion%NNodes + DO k=1,Init%OutData_ED%NumBl + Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + AD%Input(1)%BladeMotion(k)%NNodes + END DO + if (allocated(AD%OtherSt(STATE_CURR)%WakeLocationPoints)) then + Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + size(AD%OtherSt(STATE_CURR)%WakeLocationPoints,DIM=2) + end if + END IF + + ! lidar + Init%InData_IfW%lidar%Tmax = p_FAST%TMax + Init%InData_IfW%lidar%HubPosition = ED%y%HubPtMotion%Position(:,1) + + IF ( PRESENT(ExternInitData) ) THEN + Init%InData_IfW%Use4Dext = ExternInitData%FarmIntegration + + if (Init%InData_IfW%Use4Dext) then + Init%InData_IfW%FDext%n = ExternInitData%windGrid_n + Init%InData_IfW%FDext%delta = ExternInitData%windGrid_delta + Init%InData_IfW%FDext%pZero = ExternInitData%windGrid_pZero + end if + + ! bjj: these lidar inputs should come from an InflowWind input file; I'm hard coding them here for now + Init%InData_IfW%lidar%SensorType = ExternInitData%SensorType + Init%InData_IfW%lidar%LidRadialVel = ExternInitData%LidRadialVel + Init%InData_IfW%lidar%RotorApexOffsetPos = 0.0 + Init%InData_IfW%lidar%NumPulseGate = 0 + ELSE + Init%InData_IfW%lidar%SensorType = SensorType_None + Init%InData_IfW%Use4Dext = .false. + END IF + + CALL InflowWind_Init( Init%InData_IfW, IfW%Input(1), IfW%p, IfW%x(STATE_CURR), IfW%xd(STATE_CURR), IfW%z(STATE_CURR), & + IfW%OtherSt(STATE_CURR), IfW%y, IfW%m, p_FAST%dt_module( MODULE_IfW ), Init%OutData_IfW, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_IfW) = .TRUE. + CALL SetModuleSubstepTime(Module_IfW, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(MODULE_IfW)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(IfW).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_IfW%LinNames_y)) call move_alloc(Init%OutData_IfW%LinNames_y,y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%Names_y ) + if (allocated(Init%OutData_IfW%LinNames_u)) call move_alloc(Init%OutData_IfW%LinNames_u,y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%Names_u ) + if (allocated(Init%OutData_IfW%RotFrame_y)) call move_alloc(Init%OutData_IfW%RotFrame_y,y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%RotFrame_y ) + if (allocated(Init%OutData_IfW%RotFrame_u)) call move_alloc(Init%OutData_IfW%RotFrame_u,y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%RotFrame_u ) + if (allocated(Init%OutData_IfW%IsLoad_u )) call move_alloc(Init%OutData_IfW%IsLoad_u ,y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%IsLoad_u ) + + if (allocated(Init%OutData_IfW%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_IfW)%Instance(1)%NumOutputs = size(Init%OutData_IfW%WriteOutputHdr) + y_FAST%Lin%WindSpeed = Init%OutData_IfW%WindFileInfo%MWS + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ELSEIF ( p_FAST%CompInflow == Module_OpFM ) THEN + + IF ( PRESENT(ExternInitData) ) THEN + Init%InData_OpFM%NumSC2Ctrl = ExternInitData%NumSC2Ctrl + Init%InData_OpFM%NumCtrl2SC = ExternInitData%NumCtrl2SC + Init%InData_OpFM%NumActForcePtsBlade = ExternInitData%NumActForcePtsBlade + Init%InData_OpFM%NumActForcePtsTower = ExternInitData%NumActForcePtsTower + ELSE + CALL SetErrStat( ErrID_Fatal, 'OpenFOAM integration can be used only with external input data (not the stand-alone executable).', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + Init%InData_OpFM%BladeLength = Init%OutData_ED%BladeLength + Init%InData_OpFM%TowerHeight = Init%OutData_ED%TowerHeight + Init%InData_OpFM%TowerBaseHeight = Init%OutData_ED%TowerBaseHeight + ALLOCATE(Init%InData_OpFM%StructBldRNodes( SIZE(Init%OutData_ED%BldRNodes)), STAT=ErrStat2) + Init%InData_OpFM%StructBldRNodes(:) = Init%OutData_ED%BldRNodes(:) + ALLOCATE(Init%InData_OpFM%StructTwrHNodes( SIZE(Init%OutData_ED%TwrHNodes)), STAT=ErrStat2) + Init%InData_OpFM%StructTwrHNodes(:) = Init%OutData_ED%TwrHNodes(:) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating OpFM%InitInput.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + ! set up the data structures for integration with OpenFOAM + CALL Init_OpFM( Init%InData_OpFM, p_FAST, AirDens, AD14%Input(1), AD%Input(1), Init%OutData_AD, AD%y, ED%y, OpFM, Init%OutData_OpFM, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !bjj: fix me!!! to do + Init%OutData_IfW%WindFileInfo%MWS = 0.0_ReKi + + ELSE + Init%OutData_IfW%WindFileInfo%MWS = 0.0_ReKi + END IF ! CompInflow + + ! ........................ + ! initialize SuperController + ! ........................ + IF ( PRESENT(ExternInitData) ) THEN + Init%InData_SC%NumSC2Ctrl = ExternInitData%NumSC2Ctrl + Init%InData_SC%NumCtrl2SC = ExternInitData%NumCtrl2SC + ELSE + Init%InData_SC%NumSC2Ctrl = 0 + Init%InData_SC%NumCtrl2SC = 0 + END IF + + ! set up the data structures for integration with supercontroller + CALL Init_SC( Init%InData_SC, SC, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! ........................ + ! some checks for AeroDyn14's Dynamic Inflow with Mean Wind Speed from InflowWind: + ! (DO NOT COPY THIS CODE!) + ! bjj: AeroDyn14 should not need this rule of thumb; it should check the instantaneous values when the code runs + ! ........................ + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + IF (AD14%p%DynInfl) THEN + IF ( Init%OutData_IfW%WindFileInfo%MWS < 8.0 ) THEN + CALL SetErrStat(ErrID_Fatal,'AeroDyn v14 "DYNINFL" InfModel is invalid for models with wind speeds less than 8 m/s.',ErrStat,ErrMsg,RoutineName) + !CALL SetErrStat(ErrID_Info,'Estimated average inflow wind speed is less than 8 m/s. Dynamic Inflow will be turned off.',ErrStat,ErrMess,RoutineName ) + END IF + END IF + END IF + + + ! ........................ + ! initialize ServoDyn + ! ........................ + ALLOCATE( SrvD%Input( p_FAST%InterpOrder+1 ), SrvD%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating SrvD%Input and SrvD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + Init%InData_SrvD%InputFile = p_FAST%ServoFile + Init%InData_SrvD%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_SrvD)) + Init%InData_SrvD%NumBl = Init%OutData_ED%NumBl + Init%InData_SrvD%gravity = Init%OutData_ED%gravity + Init%InData_SrvD%r_N_O_G = ED%Input(1)%NacelleLoads%Position(:,1) + Init%InData_SrvD%r_TwrBase = Init%OutData_ED%TwrBasePos + Init%InData_SrvD%TMax = p_FAST%TMax + Init%InData_SrvD%AirDens = AirDens + Init%InData_SrvD%AvgWindSpeed = Init%OutData_IfW%WindFileInfo%MWS + Init%InData_SrvD%Linearize = p_FAST%Linearize + Init%InData_SrvD%TrimCase = p_FAST%TrimCase + Init%InData_SrvD%TrimGain = p_FAST%TrimGain + Init%InData_SrvD%RotSpeedRef = Init%OutData_ED%RotSpeed + + IF ( PRESENT(ExternInitData) ) THEN + Init%InData_SrvD%NumSC2Ctrl = ExternInitData%NumSC2Ctrl + Init%InData_SrvD%NumCtrl2SC = ExternInitData%NumCtrl2SC + ELSE + Init%InData_SrvD%NumSC2Ctrl = 0 + Init%InData_SrvD%NumCtrl2SC = 0 + END IF + + CALL AllocAry(Init%InData_SrvD%BlPitchInit, Init%OutData_ED%NumBl, 'BlPitchInit', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= abortErrLev) then ! make sure allocatable arrays are valid before setting them + CALL Cleanup() + RETURN + end if + + Init%InData_SrvD%BlPitchInit = Init%OutData_ED%BlPitch + CALL SrvD_Init( Init%InData_SrvD, SrvD%Input(1), SrvD%p, SrvD%x(STATE_CURR), SrvD%xd(STATE_CURR), SrvD%z(STATE_CURR), & + SrvD%OtherSt(STATE_CURR), SrvD%y, SrvD%m, p_FAST%dt_module( MODULE_SrvD ), Init%OutData_SrvD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + p_FAST%ModuleInitialized(Module_SrvD) = .TRUE. + + !IF ( Init%OutData_SrvD%CouplingScheme == ExplicitLoose ) THEN ... bjj: abort if we're doing anything else! + + CALL SetModuleSubstepTime(Module_SrvD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !! initialize SrvD%y%ElecPwr and SrvD%y%GenTq because they are one timestep different (used as input for the next step)? + + allocate( y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(SrvD).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_SrvD%LinNames_y)) call move_alloc(Init%OutData_SrvD%LinNames_y,y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%Names_y ) + if (allocated(Init%OutData_SrvD%LinNames_u)) call move_alloc(Init%OutData_SrvD%LinNames_u,y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%Names_u ) + if (allocated(Init%OutData_SrvD%RotFrame_y)) call move_alloc(Init%OutData_SrvD%RotFrame_y,y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%RotFrame_y ) + if (allocated(Init%OutData_SrvD%RotFrame_u)) call move_alloc(Init%OutData_SrvD%RotFrame_u,y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%RotFrame_u ) + if (allocated(Init%OutData_SrvD%IsLoad_u )) call move_alloc(Init%OutData_SrvD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%IsLoad_u ) + + if (allocated(Init%OutData_SrvD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_SrvD)%Instance(1)%NumOutputs = size(Init%OutData_SrvD%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! ........................ + ! some checks for AeroDyn and ElastoDyn inputs with the high-speed shaft brake hack in ElastoDyn: + ! (DO NOT COPY THIS CODE!) + ! ........................ + ! bjj: this is a hack to get high-speed shaft braking in FAST v8 + + IF ( Init%OutData_SrvD%UseHSSBrake ) THEN + IF ( p_FAST%CompAero == Module_AD14 ) THEN + IF ( AD14%p%DYNINFL ) THEN + CALL SetErrStat(ErrID_Fatal,'AeroDyn v14 "DYNINFL" InfModel is invalid for models with high-speed shaft braking.',ErrStat,ErrMsg,RoutineName) + END IF + END IF + + + IF ( ED%p%method == Method_RK4 ) THEN ! bjj: should be using ElastoDyn's Method_ABM4 Method_AB4 parameters + CALL SetErrStat(ErrID_Fatal,'ElastoDyn must use the AB4 or ABM4 integration method to implement high-speed shaft braking.',ErrStat,ErrMsg,RoutineName) + ENDIF + END IF ! Init%OutData_SrvD%UseHSSBrake + + + END IF + + ! ........................ + ! set some VTK parameters required before HydroDyn init (so we can get wave elevations for visualization) + ! ........................ + + ! get wave elevation data for visualization + if ( p_FAST%WrVTK > VTK_None ) then + call SetVTKParameters_B4HD(p_FAST, Init%OutData_ED, Init%InData_HD, BD, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + end if + + + ! ........................ + ! initialize HydroDyn + ! ........................ + ALLOCATE( HD%Input( p_FAST%InterpOrder+1 ), HD%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating HD%Input and HD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + + Init%InData_HD%Gravity = Init%OutData_ED%Gravity + Init%InData_HD%UseInputFile = .TRUE. + Init%InData_HD%InputFile = p_FAST%HydroFile + Init%InData_HD%OutRootName = p_FAST%OutFileRoot + Init%InData_HD%TMax = p_FAST%TMax + Init%InData_HD%hasIce = p_FAST%CompIce /= Module_None + Init%InData_HD%Linearize = p_FAST%Linearize + + ! if wave field needs an offset, modify these values (added at request of SOWFA developers): + Init%InData_HD%PtfmLocationX = p_FAST%TurbinePos(1) + Init%InData_HD%PtfmLocationY = p_FAST%TurbinePos(2) + + CALL HydroDyn_Init( Init%InData_HD, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), & + HD%OtherSt(STATE_CURR), HD%y, HD%m, p_FAST%dt_module( MODULE_HD ), Init%OutData_HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_HD) = .TRUE. + CALL SetModuleSubstepTime(Module_HD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(MODULE_HD)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(HD).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_HD%LinNames_y)) call move_alloc(Init%OutData_HD%LinNames_y,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_y ) + if (allocated(Init%OutData_HD%LinNames_u)) call move_alloc(Init%OutData_HD%LinNames_u,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_u ) + if (allocated(Init%OutData_HD%LinNames_x)) call move_alloc(Init%OutData_HD%LinNames_x, y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_x ) +! LIN-TODO: Determine if we need to create this data even though we don't have rotating frames in HD + !if (allocated(Init%OutData_HD%RotFrame_y)) call move_alloc(Init%OutData_HD%RotFrame_y,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%RotFrame_y ) + !if (allocated(Init%OutData_HD%RotFrame_u)) call move_alloc(Init%OutData_HD%RotFrame_u,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%RotFrame_u ) + if (allocated(Init%OutData_HD%DerivOrder_x)) call move_alloc(Init%OutData_HD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%DerivOrder_x) + if (allocated(Init%OutData_HD%IsLoad_u )) call move_alloc(Init%OutData_HD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%IsLoad_u ) + + if (allocated(Init%OutData_HD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%NumOutputs = size(Init%OutData_HD%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END IF ! CompHydro + + ! ........................ + ! initialize SubDyn or ExtPtfm_MCKF + ! ........................ + ALLOCATE( SD%Input( p_FAST%InterpOrder+1 ), SD%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating SD%Input and SD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ALLOCATE( ExtPtfm%Input( p_FAST%InterpOrder+1 ), ExtPtfm%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating ExtPtfm%Input and ExtPtfm%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + IF ( p_FAST%CompSub == Module_SD ) THEN + + IF ( p_FAST%CompHydro == Module_HD ) THEN + Init%InData_SD%WtrDpth = Init%OutData_HD%WtrDpth + ELSE + Init%InData_SD%WtrDpth = 0.0_ReKi + END IF + + Init%InData_SD%g = Init%OutData_ED%Gravity + !Init%InData_SD%UseInputFile = .TRUE. + Init%InData_SD%SDInputFile = p_FAST%SubFile + Init%InData_SD%RootName = p_FAST%OutFileRoot + Init%InData_SD%TP_RefPoint = ED%y%PlatformPtMesh%Position(:,1) ! bjj: not sure what this is supposed to be + Init%InData_SD%SubRotateZ = 0.0 ! bjj: not sure what this is supposed to be + + + CALL SD_Init( Init%InData_SD, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR), & + SD%OtherSt(STATE_CURR), SD%y, SD%m, p_FAST%dt_module( MODULE_SD ), Init%OutData_SD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_SD) = .TRUE. + CALL SetModuleSubstepTime(Module_SD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + + Init%InData_ExtPtfm%InputFile = p_FAST%SubFile + Init%InData_ExtPtfm%RootName = trim(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_ExtPtfm)) + Init%InData_ExtPtfm%Linearize = p_FAST%Linearize + Init%InData_ExtPtfm%PtfmRefzt = ED%p%PtfmRefzt ! Required + + CALL ExtPtfm_Init( Init%InData_ExtPtfm, ExtPtfm%Input(1), ExtPtfm%p, & + ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), & + ExtPtfm%y, ExtPtfm%m, p_FAST%dt_module( MODULE_ExtPtfm ), Init%OutData_ExtPtfm, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(MODULE_ExtPtfm) = .TRUE. + CALL SetModuleSubstepTime(MODULE_ExtPtfm, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(ExtPtfm).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_ExtPtfm%LinNames_y)) call move_alloc(Init%OutData_ExtPtfm%LinNames_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_y) + if (allocated(Init%OutData_ExtPtfm%LinNames_x)) call move_alloc(Init%OutData_ExtPtfm%LinNames_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_x) + if (allocated(Init%OutData_ExtPtfm%LinNames_u)) call move_alloc(Init%OutData_ExtPtfm%LinNames_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_u) + if (allocated(Init%OutData_ExtPtfm%RotFrame_y)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_y) + if (allocated(Init%OutData_ExtPtfm%RotFrame_x)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_x) + if (allocated(Init%OutData_ExtPtfm%RotFrame_u)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_u) + if (allocated(Init%OutData_ExtPtfm%IsLoad_u )) call move_alloc(Init%OutData_ExtPtfm%IsLoad_u ,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%IsLoad_u ) + if (allocated(Init%OutData_ExtPtfm%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%NumOutputs = size(Init%OutData_ExtPtfm%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END IF + + ! ------------------------------ + ! initialize CompMooring modules + ! ------------------------------ + ALLOCATE( MAPp%Input( p_FAST%InterpOrder+1 ), MAPp%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating MAPp%Input and MAPp%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + ALLOCATE( MD%Input( p_FAST%InterpOrder+1 ), MD%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating MD%Input and MD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + ALLOCATE( FEAM%Input( p_FAST%InterpOrder+1 ), FEAM%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating FEAM%Input and FEAM%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + ALLOCATE( Orca%Input( p_FAST%InterpOrder+1 ), Orca%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating Orca%Input and Orca%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ! ........................ + ! initialize MAP + ! ........................ + IF (p_FAST%CompMooring == Module_MAP) THEN + !bjj: until we modify this, MAP requires HydroDyn to be used. (perhaps we could send air density from AeroDyn or something...) + + CALL WrScr(NewLine) !bjj: I'm printing two blank lines here because MAP seems to be writing over the last line on the screen. + + +! Init%InData_MAP%rootname = p_FAST%OutFileRoot ! Output file name + Init%InData_MAP%gravity = Init%OutData_ED%Gravity ! This need to be according to g used in ElastoDyn + Init%InData_MAP%sea_density = Init%OutData_HD%WtrDens ! This needs to be set according to seawater density in HydroDyn + Init%InData_MAP%depth = Init%OutData_HD%WtrDpth ! This need to be set according to the water depth in HydroDyn + + ! differences for MAP++ + Init%InData_MAP%file_name = p_FAST%MooringFile ! This needs to be set according to what is in the FAST input file. + Init%InData_MAP%summary_file_name = TRIM(p_FAST%OutFileRoot)//'.MAP.sum' ! Output file name + Init%InData_MAP%depth = -Init%OutData_HD%WtrDpth ! This need to be set according to the water depth in HydroDyn + + Init%InData_MAP%LinInitInp%Linearize = p_FAST%Linearize + + CALL MAP_Init( Init%InData_MAP, MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), MAPp%OtherSt, & + MAPp%y, p_FAST%dt_module( MODULE_MAP ), Init%OutData_MAP, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_MAP) = .TRUE. + CALL SetModuleSubstepTime(Module_MAP, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(Module_MAP)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(MAP).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(Init%OutData_MAP%LinInitOut%LinNames_y)) call move_alloc(Init%OutData_MAP%LinInitOut%LinNames_y,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%Names_y ) + if (allocated(Init%OutData_MAP%LinInitOut%LinNames_u)) call move_alloc(Init%OutData_MAP%LinInitOut%LinNames_u,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%Names_u ) +! LIN-TODO: Determine if we need to create this data even though we don't have rotating frames in MAP + !if (allocated(Init%OutData_MAP%LinInitOut%RotFrame_y)) call move_alloc(Init%OutData_MAP%LinInitOut%RotFrame_y,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%RotFrame_y ) + !if (allocated(Init%OutData_MAP%LinInitOut%RotFrame_u)) call move_alloc(Init%OutData_MAP%LinInitOut%RotFrame_u,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%RotFrame_u ) + if (allocated(Init%OutData_MAP%LinInitOut%IsLoad_u )) call move_alloc(Init%OutData_MAP%LinInitOut%IsLoad_u ,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%IsLoad_u ) + + if (allocated(Init%OutData_MAP%WriteOutputHdr)) y_FAST%Lin%Modules(Module_MAP)%Instance(1)%NumOutputs = size(Init%OutData_MAP%WriteOutputHdr) + end if + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! ........................ + ! initialize MoorDyn + ! ........................ + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + + Init%InData_MD%FileName = p_FAST%MooringFile ! This needs to be set according to what is in the FAST input file. + Init%InData_MD%RootName = p_FAST%OutFileRoot + + Init%InData_MD%PtfmInit = Init%OutData_ED%PlatformPos !ED%x(STATE_CURR)%QT(1:6) ! initial position of the platform !bjj: this should come from Init%OutData_ED, not x_ED + Init%InData_MD%g = Init%OutData_ED%Gravity ! This need to be according to g used in ElastoDyn + Init%InData_MD%rhoW = Init%OutData_HD%WtrDens ! This needs to be set according to seawater density in HydroDyn + Init%InData_MD%WtrDepth = Init%OutData_HD%WtrDpth ! This need to be set according to the water depth in HydroDyn + + CALL MD_Init( Init%InData_MD, MD%Input(1), MD%p, MD%x(STATE_CURR), MD%xd(STATE_CURR), MD%z(STATE_CURR), & + MD%OtherSt(STATE_CURR), MD%y, MD%m, p_FAST%dt_module( MODULE_MD ), Init%OutData_MD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_MD) = .TRUE. + CALL SetModuleSubstepTime(Module_MD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! ........................ + ! initialize FEAM + ! ........................ + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + + Init%InData_FEAM%InputFile = p_FAST%MooringFile ! This needs to be set according to what is in the FAST input file. + Init%InData_FEAM%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_FEAM)) + + Init%InData_FEAM%PtfmInit = Init%OutData_ED%PlatformPos !ED%x(STATE_CURR)%QT(1:6) ! initial position of the platform !bjj: this should come from Init%OutData_ED, not x_ED + Init%InData_FEAM%NStepWave = 1 ! an arbitrary number > 0 (to set the size of the wave data, which currently contains all zero values) + Init%InData_FEAM%gravity = Init%OutData_ED%Gravity ! This need to be according to g used in ElastoDyn + Init%InData_FEAM%WtrDens = Init%OutData_HD%WtrDens ! This needs to be set according to seawater density in HydroDyn +! Init%InData_FEAM%depth = Init%OutData_HD%WtrDpth ! This need to be set according to the water depth in HydroDyn + + CALL FEAM_Init( Init%InData_FEAM, FEAM%Input(1), FEAM%p, FEAM%x(STATE_CURR), FEAM%xd(STATE_CURR), FEAM%z(STATE_CURR), & + FEAM%OtherSt(STATE_CURR), FEAM%y, FEAM%m, p_FAST%dt_module( MODULE_FEAM ), Init%OutData_FEAM, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_FEAM) = .TRUE. + CALL SetModuleSubstepTime(Module_FEAM, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! ........................ + ! initialize OrcaFlex Interface + ! ........................ + ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + + Init%InData_Orca%InputFile = p_FAST%MooringFile + Init%InData_Orca%RootName = p_FAST%OutFileRoot + Init%InData_Orca%TMax = p_FAST%TMax + + CALL Orca_Init( Init%InData_Orca, Orca%Input(1), Orca%p, Orca%x(STATE_CURR), Orca%xd(STATE_CURR), Orca%z(STATE_CURR), Orca%OtherSt(STATE_CURR), & + Orca%y, Orca%m, p_FAST%dt_module( MODULE_Orca ), Init%OutData_Orca, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(MODULE_Orca) = .TRUE. + CALL SetModuleSubstepTime(MODULE_Orca, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END IF + + ! ------------------------------ + ! initialize CompIce modules + ! ------------------------------ + ALLOCATE( IceF%Input( p_FAST%InterpOrder+1 ), IceF%InputTimes( p_FAST%InterpOrder+1 ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating IceF%Input and IceF%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ! We need this to be allocated (else we have issues passing nonallocated arrays and using the first index of Input(), + ! but we don't need the space of IceD_MaxLegs if we're not using it. + IF ( p_FAST%CompIce /= Module_IceD ) THEN + IceDim = 1 + ELSE + IceDim = IceD_MaxLegs + END IF + + ! because there may be multiple instances of IceDyn, we'll allocate arrays for that here + ! we could allocate these after + ALLOCATE( IceD%Input( p_FAST%InterpOrder+1, IceDim ), IceD%InputTimes( p_FAST%InterpOrder+1, IceDim ), STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating IceD%Input and IceD%InputTimes.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + ALLOCATE( IceD%x( IceDim,2), & + IceD%xd( IceDim,2), & + IceD%z( IceDim,2), & + IceD%OtherSt( IceDim,2), & + IceD%p( IceDim ), & + IceD%u( IceDim ), & + IceD%y( IceDim ), & + IceD%m( IceDim ), & + STAT = ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating IceD state, input, and output data.",ErrStat,ErrMsg,RoutineName) + CALL Cleanup() + RETURN + END IF + + + ! ........................ + ! initialize IceFloe + ! ........................ + IF ( p_FAST%CompIce == Module_IceF ) THEN + + Init%InData_IceF%InputFile = p_FAST%IceFile + Init%InData_IceF%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_IceF)) + Init%InData_IceF%simLength = p_FAST%TMax !bjj: IceFloe stores this as single-precision (ReKi) TMax is DbKi + Init%InData_IceF%MSL2SWL = Init%OutData_HD%MSL2SWL + Init%InData_IceF%gravity = Init%OutData_ED%Gravity + + CALL IceFloe_Init( Init%InData_IceF, IceF%Input(1), IceF%p, IceF%x(STATE_CURR), IceF%xd(STATE_CURR), IceF%z(STATE_CURR), & + IceF%OtherSt(STATE_CURR), IceF%y, IceF%m, p_FAST%dt_module( MODULE_IceF ), Init%OutData_IceF, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_IceF) = .TRUE. + CALL SetModuleSubstepTime(Module_IceF, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! ........................ + ! initialize IceDyn + ! ........................ + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + + Init%InData_IceD%InputFile = p_FAST%IceFile + Init%InData_IceD%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_IceD))//'1' + Init%InData_IceD%MSL2SWL = Init%OutData_HD%MSL2SWL + Init%InData_IceD%WtrDens = Init%OutData_HD%WtrDens + Init%InData_IceD%gravity = Init%OutData_ED%Gravity + Init%InData_IceD%TMax = p_FAST%TMax + Init%InData_IceD%LegNum = 1 + + CALL IceD_Init( Init%InData_IceD, IceD%Input(1,1), IceD%p(1), IceD%x(1,STATE_CURR), IceD%xd(1,STATE_CURR), IceD%z(1,STATE_CURR), & + IceD%OtherSt(1,STATE_CURR), IceD%y(1), IceD%m(1), p_FAST%dt_module( MODULE_IceD ), Init%OutData_IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + p_FAST%ModuleInitialized(Module_IceD) = .TRUE. + CALL SetModuleSubstepTime(Module_IceD, p_FAST, y_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! now initialize IceD for additional legs (if necessary) + dt_IceD = p_FAST%dt_module( MODULE_IceD ) + p_FAST%numIceLegs = Init%OutData_IceD%numLegs + + IF (p_FAST%numIceLegs > IceD_MaxLegs) THEN + CALL SetErrStat(ErrID_Fatal,'IceDyn-FAST coupling is supported for up to '//TRIM(Num2LStr(IceD_MaxLegs))//' legs, but ' & + //TRIM(Num2LStr(p_FAST%numIceLegs))//' legs were specified.',ErrStat,ErrMsg,RoutineName) + END IF + + + DO i=2,p_FAST%numIceLegs ! basically, we just need IceDyn to set up its meshes for inputs/outputs and possibly initial values for states + Init%InData_IceD%LegNum = i + Init%InData_IceD%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_IceD))//TRIM(Num2LStr(i)) + + CALL IceD_Init( Init%InData_IceD, IceD%Input(1,i), IceD%p(i), IceD%x(i,STATE_CURR), IceD%xd(i,STATE_CURR), IceD%z(i,STATE_CURR), & + IceD%OtherSt(i,STATE_CURR), IceD%y(i), IceD%m(i), dt_IceD, Init%OutData_IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !bjj: we're going to force this to have the same timestep because I don't want to have to deal with n IceD modules with n timesteps. + IF (.NOT. EqualRealNos( p_FAST%dt_module( MODULE_IceD ),dt_IceD )) THEN + CALL SetErrStat(ErrID_Fatal,"All instances of IceDyn (one per support-structure leg) must be the same",ErrStat,ErrMsg,RoutineName) + END IF + END DO + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + END IF + + + ! ........................ + ! Set up output for glue code (must be done after all modules are initialized so we have their WriteOutput information) + ! ........................ + + CALL FAST_InitOutput( p_FAST, y_FAST, Init, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! ------------------------------------------------------------------------- + ! Initialize mesh-mapping data + ! ------------------------------------------------------------------------- + + CALL InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ELSEIF (ErrStat /= ErrID_None) THEN + ! a little work-around in case the mesh mapping info messages get too long + CALL WrScr( NewLine//TRIM(ErrMsg)//NewLine ) + ErrStat = ErrID_None + ErrMsg = "" + END IF + + ! ------------------------------------------------------------------------- + ! Initialize for linearization: + ! ------------------------------------------------------------------------- + if ( p_FAST%Linearize ) then + call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + end if + + + ! ------------------------------------------------------------------------- + ! Initialize data for VTK output + ! ------------------------------------------------------------------------- + if ( p_FAST%WrVTK > VTK_None ) then + call SetVTKParameters(p_FAST, Init%OutData_ED, Init%OutData_AD, Init%InData_HD, Init%OutData_HD, ED, BD, AD, HD, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + ! ------------------------------------------------------------------------- + ! Write initialization data to FAST summary file: + ! ------------------------------------------------------------------------- + if (p_FAST%SumPrint) then + CALL FAST_WrSum( p_FAST, y_FAST, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + endif + + + ! ------------------------------------------------------------------------- + ! other misc variables initialized here: + ! ------------------------------------------------------------------------- + + m_FAST%t_global = t_initial + + ! Initialize external inputs for first step + if ( p_FAST%CompServo == MODULE_SrvD ) then + m_FAST%ExternInput%GenTrq = SrvD%Input(1)%ExternalGenTrq !0.0_ReKi + m_FAST%ExternInput%ElecPwr = SrvD%Input(1)%ExternalElecPwr + m_FAST%ExternInput%YawPosCom = SrvD%Input(1)%ExternalYawPosCom + m_FAST%ExternInput%YawRateCom = SrvD%Input(1)%ExternalYawRateCom + m_FAST%ExternInput%HSSBrFrac = SrvD%Input(1)%ExternalHSSBrFrac + + do i=1,SIZE(SrvD%Input(1)%ExternalBlPitchCom) + m_FAST%ExternInput%BlPitchCom(i) = SrvD%Input(1)%ExternalBlPitchCom(i) + end do + end if + + m_FAST%ExternInput%LidarFocus = 1.0_ReKi ! make this non-zero (until we add the initial position in the InflowWind input file) + + + !............................................................................................................................... + ! Destroy initializion data + !............................................................................................................................... + CALL Cleanup() + +CONTAINS + SUBROUTINE Cleanup() + !............................................................................................................................... + ! Destroy initializion data + !............................................................................................................................... + CALL FAST_DestroyInitData( Init, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + END SUBROUTINE Cleanup + +END SUBROUTINE FAST_InitializeAll + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This function returns a string describing the glue code and some of the compilation options we're using. +FUNCTION GetVersion(ThisProgVer) + + ! Passed Variables: + + TYPE(ProgDesc), INTENT( IN ) :: ThisProgVer !< program name/date/version description + CHARACTER(1024) :: GetVersion !< String containing a description of the compiled precision. + + CHARACTER(200) :: git_commit + + GetVersion = TRIM(GetNVD(ThisProgVer))//', compiled' + + IF ( Cmpl4SFun ) THEN ! FAST has been compiled as an S-Function for Simulink + GetVersion = TRIM(GetVersion)//' as a DLL S-Function for Simulink' + ELSEIF ( Cmpl4LV ) THEN ! FAST has been compiled as a DLL for Labview + GetVersion = TRIM(GetVersion)//' as a DLL for LabVIEW' + ENDIF + + GetVersion = TRIM(GetVersion)//' as a '//TRIM(Num2LStr(BITS_IN_ADDR))//'-bit application using' + + ! determine precision + + IF ( ReKi == SiKi ) THEN ! Single precision + GetVersion = TRIM(GetVersion)//' single' + ELSEIF ( ReKi == R8Ki ) THEN ! Double precision + GetVersion = TRIM(GetVersion)// ' double' + ELSE ! Unknown precision + GetVersion = TRIM(GetVersion)//' unknown' + ENDIF + + +! GetVersion = TRIM(GetVersion)//' precision with '//OS_Desc + GetVersion = TRIM(GetVersion)//' precision' + + ! add git info + git_commit = QueryGitVersion() + GetVersion = TRIM(GetVersion)//' at commit '//git_commit + + RETURN +END FUNCTION GetVersion + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine is called at the start (or restart) of a FAST program (or FAST.Farm). It initializes the NWTC subroutine library, +!! displays the copyright notice, and displays some version information (including addressing scheme and precision). +SUBROUTINE FAST_ProgStart(ThisProgVer) + TYPE(ProgDesc), INTENT(IN) :: ThisProgVer !< program name/date/version description + + ! ... Initialize NWTC Library (open console, set pi constants) ... + ! sets the pi constants, open console for output, etc... + CALL NWTC_Init( ProgNameIN=ThisProgVer%Name, EchoLibVer=.FALSE. ) + + ! Display the copyright notice + CALL DispCopyrightLicense( ThisProgVer%Name ) + + CALL DispCompileRuntimeInfo + +END SUBROUTINE FAST_ProgStart +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine gets the name of the FAST input file from the command line. It also returns a logical indicating if this there +!! was a "DWM" argument after the file name. +SUBROUTINE GetInputFileName(InputFile,UseDWM,ErrStat,ErrMsg) + CHARACTER(*), INTENT(OUT) :: InputFile !< A CHARACTER string containing the name of the primary FAST input file (if not present, we'll get it from the command line) + LOGICAL, INTENT(OUT) :: UseDWM !< whether the last argument from the command line is "DWM" + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + INTEGER(IntKi) :: ErrStat2 ! local error stat + CHARACTER(1024) :: LastArg ! A second command-line argument that will allow DWM module to be used in AeroDyn + + ErrStat = ErrID_None + ErrMsg = '' + + UseDWM = .FALSE. ! by default, we're not going to use the DWM module + InputFile = "" ! initialize to empty string to make sure it's input from the command line + CALL CheckArgs( InputFile, ErrStat2, LastArg ) ! if ErrStat2 /= ErrID_None, we'll ignore and deal with the problem when we try to read the input file + + IF (LEN_TRIM(InputFile) == 0) THEN ! no input file was specified + ErrStat = ErrID_Fatal + ErrMsg = 'The required input file was not specified on the command line.' + RETURN + END IF + + IF (LEN_TRIM(LastArg) > 0) THEN ! see if DWM was specified as the second option + CALL Conv2UC( LastArg ) + IF ( TRIM(LastArg) == "DWM" ) THEN + UseDWM = .TRUE. + END IF + END IF + +END SUBROUTINE GetInputFileName +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine checks for command-line arguments, gets the root name of the input files +!! (including full path name), and creates the names of the output files. +SUBROUTINE FAST_Init( p, m_FAST, y_FAST, t_initial, InputFile, ErrStat, ErrMsg, TMax, TurbID, OverrideAbortLev, RootName ) + + IMPLICIT NONE + + ! Passed variables + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p !< The parameter data for the FAST (glue-code) simulation + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< The output data for the FAST (glue-code) simulation + REAL(DbKi), INTENT(IN) :: t_initial !< the beginning time of the simulation + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: InputFile !< A CHARACTER string containing the name of the primary FAST input file (if not present, we'll get it from the command line) + REAL(DbKi), INTENT(IN), OPTIONAL :: TMax !< the length of the simulation (from Simulink or FAST.Farm) + INTEGER(IntKi), INTENT(IN), OPTIONAL :: TurbID !< an ID for naming the tubine output file + LOGICAL, INTENT(IN), OPTIONAL :: OverrideAbortLev !< whether or not we should override the abort error level (e.g., FAST.Farm) + CHARACTER(*), INTENT(IN), OPTIONAL :: RootName !< A CHARACTER string containing the root name of FAST output files, overriding normal naming convention + ! Local variables + + INTEGER :: i ! loop counter + !CHARACTER(1024) :: DirName ! A CHARACTER string containing the path of the current working directory + + + LOGICAL :: OverrideAbortErrLev + CHARACTER(*), PARAMETER :: RoutineName = "FAST_Init" + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ! Initialize some variables + ErrStat = ErrID_None + ErrMsg = '' + + IF (PRESENT(OverrideAbortLev)) THEN + OverrideAbortErrLev = OverrideAbortLev + ELSE + OverrideAbortErrLev = .true. + END IF + + + + !............................................................................................................................... + ! Set the root name of the output files based on the input file name + !............................................................................................................................... + + if (present(RootName)) then + p%OutFileRoot = RootName + else + ! Determine the root name of the primary file (will be used for output files) + CALL GetRoot( InputFile, p%OutFileRoot ) + IF ( Cmpl4SFun ) p%OutFileRoot = TRIM( p%OutFileRoot )//'.SFunc' + IF ( PRESENT(TurbID) ) THEN + IF ( TurbID > 0 ) THEN + p%OutFileRoot = TRIM( p%OutFileRoot )//'.T'//TRIM(Num2LStr(TurbID)) + END IF + END IF + + end if + p%VTK_OutFileRoot = p%OutFileRoot !initialize this here in case of error before it is set later + + + !............................................................................................................................... + ! Initialize the module name/date/version info: + !............................................................................................................................... + + DO i=1,NumModules + y_FAST%Module_Ver(i)%Date = 'unknown date' + y_FAST%Module_Ver(i)%Ver = 'unknown version' + END DO + y_FAST%Module_Ver( Module_IfW )%Name = 'InflowWind' + y_FAST%Module_Ver( Module_OpFM )%Name = 'OpenFOAM integration' + y_FAST%Module_Ver( Module_ED )%Name = 'ElastoDyn' + y_FAST%Module_Ver( Module_BD )%Name = 'BeamDyn' + y_FAST%Module_Ver( Module_AD14 )%Name = 'AeroDyn14' + y_FAST%Module_Ver( Module_AD )%Name = 'AeroDyn' + y_FAST%Module_Ver( Module_SrvD )%Name = 'ServoDyn' + y_FAST%Module_Ver( Module_HD )%Name = 'HydroDyn' + y_FAST%Module_Ver( Module_SD )%Name = 'SubDyn' + y_FAST%Module_Ver( Module_ExtPtfm)%Name = 'ExtPtfm_MCKF' + y_FAST%Module_Ver( Module_MAP )%Name = 'MAP' + y_FAST%Module_Ver( Module_FEAM )%Name = 'FEAMooring' + y_FAST%Module_Ver( Module_MD )%Name = 'MoorDyn' + y_FAST%Module_Ver( Module_Orca )%Name = 'OrcaFlexInterface' + y_FAST%Module_Ver( Module_IceF )%Name = 'IceFloe' + y_FAST%Module_Ver( Module_IceD )%Name = 'IceDyn' + + y_FAST%Module_Abrev( Module_IfW ) = 'IfW' + y_FAST%Module_Abrev( Module_OpFM ) = 'OpFM' + y_FAST%Module_Abrev( Module_ED ) = 'ED' + y_FAST%Module_Abrev( Module_BD ) = 'BD' + y_FAST%Module_Abrev( Module_AD14 ) = 'AD' + y_FAST%Module_Abrev( Module_AD ) = 'AD' + y_FAST%Module_Abrev( Module_SrvD ) = 'SrvD' + y_FAST%Module_Abrev( Module_HD ) = 'HD' + y_FAST%Module_Abrev( Module_SD ) = 'SD' + y_FAST%Module_Abrev( Module_ExtPtfm) = 'ExtPtfm' + y_FAST%Module_Abrev( Module_MAP ) = 'MAP' + y_FAST%Module_Abrev( Module_FEAM ) = 'FEAM' + y_FAST%Module_Abrev( Module_MD ) = 'MD' + y_FAST%Module_Abrev( Module_Orca ) = 'Orca' + y_FAST%Module_Abrev( Module_IceF ) = 'IceF' + y_FAST%Module_Abrev( Module_IceD ) = 'IceD' + + p%n_substeps = 1 ! number of substeps for between modules and global/FAST time + p%BD_OutputSibling = .false. + + !............................................................................................................................... + ! Read the primary file for the glue code: + !............................................................................................................................... + CALL FAST_ReadPrimaryFile( InputFile, p, m_FAST, OverrideAbortErrLev, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! make sure some linearization variables are consistant + if (.not. p%Linearize) p%CalcSteady = .false. + if (.not. p%CalcSteady) p%TrimCase = TrimCase_none + m_FAST%Lin%FoundSteady = .false. + p%LinInterpOrder = p%InterpOrder ! 1 ! always use linear (or constant) interpolation on rotor? + + ! overwrite TMax if necessary) + IF (PRESENT(TMax)) THEN + p%TMax = TMax + !p%TMax = MAX( TMax, p%TMax ) + END IF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + p%KMax = 1 ! after more checking, we may put this in the input file... + !IF (p%CompIce == Module_IceF) p%KMax = 2 + p%SizeJac_Opt1 = 0 ! initialize this vector to zero; after we figure out what size the ED/SD/HD/BD meshes are, we'll fill this + + p%numIceLegs = 0 ! initialize number of support-structure legs in contact with ice (IceDyn will set this later) + + p%nBeams = 0 ! initialize number of BeamDyn instances (will be set later) + + ! determine what kind of turbine we're modeling: + IF ( p%CompHydro == Module_HD ) THEN + IF ( p%CompSub == Module_SD ) THEN + p%TurbineType = Type_Offshore_Fixed + ELSE + p%TurbineType = Type_Offshore_Floating + END IF + ELSEIF ( p%CompMooring == Module_Orca ) THEN + p%TurbineType = Type_Offshore_Floating + ELSEIF ( p%CompSub == Module_ExtPtfm ) THEN + p%TurbineType = Type_Offshore_Fixed + ELSE + p%TurbineType = Type_LandBased + END IF + + + p%n_TMax_m1 = CEILING( ( (p%TMax - t_initial) / p%DT ) ) - 1 ! We're going to go from step 0 to n_TMax (thus the -1 here) + + if (p%TMax < 1.0_DbKi) then ! log10(0) gives floating point divide-by-zero error + p%TChanLen = MinChanLen + else + p%TChanLen = max( MinChanLen, int(log10(p%TMax))+7 ) + end if + p%OutFmt_t = 'F'//trim(num2lstr( p%TChanLen ))//'.4' ! 'F10.4' + + !............................................................................................................................... + ! Do some error checking on the inputs (validation): + !............................................................................................................................... + call ValidateInputData(p, m_FAST, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + + IF ( ErrStat >= AbortErrLev ) RETURN + + + RETURN +END SUBROUTINE FAST_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates FAST data. +SUBROUTINE ValidateInputData(p, m_FAST, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p !< The parameter data for the FAST (glue-code) simulation + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< The misc data for the FAST (glue-code) simulation + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + REAL(DbKi) :: TmpTime ! A temporary variable for error checking + + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName='ValidateInputData' + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( p%TMax < 0.0_DbKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TMax must not be a negative number.', ErrStat, ErrMsg, RoutineName ) + ELSE IF ( p%TMax < p%TStart ) THEN + CALL SetErrStat( ErrID_Fatal, 'TMax must not be less than TStart.', ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p%n_ChkptTime < p%n_TMax_m1 ) THEN + if (.NOT. p%WrBinOutFile) CALL SetErrStat( ErrID_Severe, 'It is highly recommended that time-marching output files be generated in binary format when generating checkpoint files.', ErrStat, ErrMsg, RoutineName ) + if (p%CompMooring==MODULE_Orca) CALL SetErrStat( ErrID_Fatal, 'Restart capability for OrcaFlexInterface is not supported. Set ChkptTime larger than TMax.', ErrStat, ErrMsg, RoutineName ) + ! also check for other features that aren't supported with restart (like ServoDyn's user-defined control routines) + END IF + + IF ( p%DT <= 0.0_DbKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'DT must be greater than 0.', ErrStat, ErrMsg, RoutineName ) + ELSE ! Test DT and TMax to ensure numerical stability -- HINT: see the use of OnePlusEps + TmpTime = p%TMax*EPSILON(p%DT) + IF ( p%DT <= TmpTime ) THEN + CALL SetErrStat( ErrID_Fatal, 'DT must be greater than '//TRIM ( Num2LStr( TmpTime ) )//' seconds.', ErrStat, ErrMsg, RoutineName ) + END IF + END IF + + ! Check that InputFileData%OutFmt is a valid format specifier and will fit over the column headings + CALL ChkRealFmtStr( p%OutFmt, 'OutFmt', p%FmtWidth, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( p%WrTxtOutFile .and. p%FmtWidth < MinChanLen ) CALL SetErrStat( ErrID_Warn, 'OutFmt produces a column width of '// & + TRIM(Num2LStr(p%FmtWidth))//'), which may be too small.', ErrStat, ErrMsg, RoutineName ) + + IF ( p%WrTxtOutFile .AND. p%TChanLen > ChanLen ) THEN ! ( p%TMax > 9999.999_DbKi ) + CALL SetErrStat( ErrID_Warn, 'TMax is too large for a '//trim(num2lstr(ChanLen))//'-character time column in text tabular (time-marching) output files.'// & + ' Postprocessors with this limitation may not work.', ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p%TStart < 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'TStart must not be less than 0 seconds.', ErrStat, ErrMsg, RoutineName ) +! IF ( p%SttsTime <= 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'SttsTime must be greater than 0 seconds.', ErrStat, ErrMsg, RoutineName ) + IF ( p%n_SttsTime < 1_IntKi ) CALL SetErrStat( ErrID_Fatal, 'SttsTime must be greater than 0 seconds.', ErrStat, ErrMsg, RoutineName ) + IF ( p%n_ChkptTime < 1_IntKi ) CALL SetErrStat( ErrID_Fatal, 'ChkptTime must be greater than 0 seconds.', ErrStat, ErrMsg, RoutineName ) + IF ( p%KMax < 1_IntKi ) CALL SetErrStat( ErrID_Fatal, 'KMax must be greater than 0.', ErrStat, ErrMsg, RoutineName ) + + IF (p%CompElast == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompElast must be 1 (ElastoDyn) or 2 (BeamDyn).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompAero == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompAero must be 0 (None), 1 (AeroDyn14), or 2 (AeroDyn).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompServo == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompServo must be 0 (None) or 1 (ServoDyn).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompHydro == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompHydro must be 0 (None) or 1 (HydroDyn).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompSub == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompSub must be 0 (None), 1 (SubDyn), or 2 (ExtPtfm_MCKF).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompMooring == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompMooring must be 0 (None), 1 (MAP), 2 (FEAMooring), 3 (MoorDyn), or 4 (OrcaFlex).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompIce == Module_Unknown) CALL SetErrStat( ErrID_Fatal, 'CompIce must be 0 (None) or 1 (IceFloe).', ErrStat, ErrMsg, RoutineName ) + IF (p%CompHydro /= Module_HD) THEN + IF (p%CompMooring == Module_MAP) THEN + CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when MAP is used. Set CompHydro > 0 or CompMooring = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + ELSEIF (p%CompMooring == Module_FEAM) THEN + CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when FEAMooring is used. Set CompHydro > 0 or CompMooring = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + END IF + ELSE + IF (p%CompMooring == Module_Orca) CALL SetErrStat( ErrID_Fatal, 'HydroDyn cannot be used if OrcaFlex is used. Set CompHydro = 0 or CompMooring < 4 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + IF (p%CompSub == Module_ExtPtfm) CALL SetErrStat( ErrID_Fatal, 'HydroDyn cannot be used if ExtPtfm_MCKF is used. Set CompHydro = 0 or CompSub < 2 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + END IF + + + IF (p%CompIce == Module_IceF) THEN + IF (p%CompSub /= Module_SD) CALL SetErrStat( ErrID_Fatal, 'SubDyn must be used when IceFloe is used. Set CompSub > 0 or CompIce = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + IF (p%CompHydro /= Module_HD) CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when IceFloe is used. Set CompHydro > 0 or CompIce = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + ELSEIF (p%CompIce == Module_IceD) THEN + IF (p%CompSub /= Module_SD) CALL SetErrStat( ErrID_Fatal, 'SubDyn must be used when IceDyn is used. Set CompSub > 0 or CompIce = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + IF (p%CompHydro /= Module_HD) CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when IceDyn is used. Set CompHydro > 0 or CompIce = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + END IF + + IF (p%CompElast == Module_BD .and. p%CompAero == Module_AD14 ) CALL SetErrStat( ErrID_Fatal, 'AeroDyn14 cannot be used when BeamDyn is used. Change CompAero or CompElast in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + +! IF ( p%InterpOrder < 0 .OR. p%InterpOrder > 2 ) THEN + IF ( p%InterpOrder < 1 .OR. p%InterpOrder > 2 ) THEN + CALL SetErrStat( ErrID_Fatal, 'InterpOrder must be 1 or 2.', ErrStat, ErrMsg, RoutineName ) ! 5/13/14 bjj: MAS and JMJ compromise for certain integrators is that InterpOrder cannot be 0 + p%InterpOrder = 1 ! Avoid problems in error handling by setting this to 0 + END IF + + IF ( p%NumCrctn < 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'NumCrctn must be 0 or greater.', ErrStat, ErrMsg, RoutineName ) + END IF + + + if ( p%WrVTK == VTK_Unknown ) then + call SetErrStat(ErrID_Fatal, 'WrVTK must be 0 (none), 1 (initialization only), 2 (animation), or 3 (mode shapes).', ErrStat, ErrMsg, RoutineName) + else + if ( p%VTK_type == VTK_Unknown ) then + call SetErrStat(ErrID_Fatal, 'VTK_type must be 1 (surfaces), 2 (basic meshes:lines/points), or 3 (all meshes).', ErrStat, ErrMsg, RoutineName) + ! note I'm not going to write that 4 (old) is an option + end if + + if (p%WrVTK == VTK_ModeShapes .and. .not. p%Linearize) then + call SetErrStat(ErrID_Fatal, 'WrVTK cannot be 3 (mode shapes) when Linearize is false. (Mode shapes require linearization analysis.)', ErrStat, ErrMsg, RoutineName) + end if + end if + + if (p%Linearize) then + + if (p%CalcSteady) then + if (p%NLinTimes < 1) call SetErrStat(ErrID_Fatal,'NLinTimes must be at least 1 for linearization analysis.',ErrStat, ErrMsg, RoutineName) + if (p%TrimCase /= TrimCase_yaw .and. p%TrimCase /= TrimCase_torque .and. p%TrimCase /= TrimCase_pitch) then + call SetErrStat(ErrID_Fatal,'TrimCase must be either 1, 2, or 3.',ErrStat, ErrMsg, RoutineName) + end if + + if (p%TrimTol <= epsilon(p%TrimTol)) call SetErrStat(ErrID_Fatal,'TrimTol must be larger than '//trim(num2lstr(epsilon(p%TrimTol)))//'.',ErrStat, ErrMsg, RoutineName) + if (p%Twr_Kdmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'Twr_Kdmp must not be negative.',ErrStat, ErrMsg, RoutineName) + if (p%Bld_Kdmp < 0.0_ReKi) call SetErrStat(ErrID_Fatal,'Bld_Kdmp must not be negative.',ErrStat, ErrMsg, RoutineName) + else + + if (.not. allocated(m_FAST%Lin%LinTimes)) then + call SetErrStat(ErrID_Fatal, 'NLinTimes must be at least 1 for linearization analysis.',ErrStat, ErrMsg, RoutineName) + else + do i=1,p%NLinTimes + if (m_FAST%Lin%LinTimes(i) < 0) call SetErrStat(ErrID_Fatal,'LinTimes must be positive values.',ErrStat, ErrMsg, RoutineName) + end do + do i=2,p%NLinTimes + if (m_FAST%Lin%LinTimes(i) <= m_FAST%Lin%LinTimes(i-1)) call SetErrStat(ErrID_Fatal,'LinTimes must be unique values entered in increasing order.',ErrStat, ErrMsg, RoutineName) + end do + + if (m_FAST%Lin%LinTimes(p%NLinTimes) > p%TMax) call SetErrStat(ErrID_Info, 'Tmax is less than the last linearization time. Linearization analysis will not be performed after TMax.',ErrStat, ErrMsg, RoutineName) + end if + + end if + + if (p%LinInputs < LIN_NONE .or. p%LinInputs > LIN_ALL) call SetErrStat(ErrID_Fatal,'LinInputs must be 0, 1, or 2.',ErrStat, ErrMsg, RoutineName) + if (p%LinOutputs < LIN_NONE .or. p%LinOutputs > LIN_ALL) call SetErrStat(ErrID_Fatal,'LinOutputs must be 0, 1, or 2.',ErrStat, ErrMsg, RoutineName) + + if (p%LinOutJac) then + if ( p%LinInputs /= LIN_ALL .or. p%LinOutputs /= LIN_ALL) then + call SetErrStat(ErrID_Info,'LinOutJac can be used only when LinInputs=LinOutputs=2.',ErrStat, ErrMsg, RoutineName) + p%LinOutJac = .false. + end if + end if + + ! now, make sure we haven't asked for any modules that we can't yet linearize: + if (p%CompInflow == MODULE_OpFM) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the OpenFOAM coupling.',ErrStat, ErrMsg, RoutineName) + if (p%CompAero == MODULE_AD14) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the AeroDyn v14 module.',ErrStat, ErrMsg, RoutineName) + !if (p%CompSub == MODULE_SD) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the SubDyn module.',ErrStat, ErrMsg, RoutineName) + if (p%CompSub /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the any of the substructure modules.',ErrStat, ErrMsg, RoutineName) + if (p%CompMooring /= MODULE_None .and. p%CompMooring /= MODULE_MAP) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the FEAMooring or MoorDyn mooring modules.',ErrStat, ErrMsg, RoutineName) + if (p%CompIce /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for any of the ice loading modules.',ErrStat, ErrMsg, RoutineName) + + end if + + + if ( p%TurbineType /= Type_LandBased .and. .not. EqualRealNos(p%TurbinePos(3), 0.0_SiKi) ) then + call SetErrStat(ErrID_Fatal, 'Height of turbine location, TurbinePos(3), must be 0 for offshore turbines.', ErrStat, ErrMsg, RoutineName) + end if + + !............................................................................................................................... + + ! temporary check on p_FAST%DT_out + + IF ( .NOT. EqualRealNos( p%DT_out, p%DT ) ) THEN + IF ( p%DT_out < p%DT ) THEN + CALL SetErrStat( ErrID_Fatal, 'DT_out must be at least DT ('//TRIM(Num2LStr(p%DT))//' s).', ErrStat, ErrMsg, RoutineName ) + ELSEIF ( .NOT. EqualRealNos( p%DT_out, p%DT * p%n_DT_Out ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'DT_out must be an integer multiple of DT.', ErrStat, ErrMsg, RoutineName ) + END IF + END IF + + + +END SUBROUTINE ValidateInputData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the output for the glue code, including writing the header for the primary output file. +SUBROUTINE FAST_InitOutput( p_FAST, y_FAST, Init, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(INOUT) :: y_FAST !< Glue-code simulation outputs + TYPE(FAST_InitData), INTENT(IN) :: Init !< Initialization data for all modules + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message corresponding to ErrStat + + + ! Local variables. + + INTEGER(IntKi) :: I, J ! Generic index for DO loops. + INTEGER(IntKi) :: indxNext ! The index of the next value to be written to an array + INTEGER(IntKi) :: NumOuts ! number of channels to be written to the output file(s) + + + + !...................................................... + ! Set the description lines to be printed in the output file + !...................................................... + y_FAST%FileDescLines(1) = 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using '//TRIM(GetVersion(FAST_Ver)) + y_FAST%FileDescLines(2) = 'linked with ' //' '//TRIM(GetNVD(NWTC_Ver )) ! we'll get the rest of the linked modules in the section below + y_FAST%FileDescLines(3) = 'Description from the FAST input file: '//TRIM(p_FAST%FTitle) + + !...................................................... + ! We'll fill out the rest of FileDescLines(2), + ! and save the module version info for later use, too: + !...................................................... + + y_FAST%Module_Ver( Module_ED ) = Init%OutData_ED%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_ED ) )) + + IF ( p_FAST%CompElast == Module_BD ) THEN + y_FAST%Module_Ver( Module_BD ) = Init%OutData_BD(1)%Ver ! call copy routine for this type if it every uses dynamic memory + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_BD ))) + END IF + + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + y_FAST%Module_Ver( Module_IfW ) = Init%OutData_IfW%Ver ! call copy routine for this type if it every uses dynamic memory + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_IfW ))) + ELSEIF ( p_FAST%CompInflow == Module_OpFM ) THEN + y_FAST%Module_Ver( Module_OpFM ) = Init%OutData_OpFM%Ver ! call copy routine for this type if it every uses dynamic memory + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_OpFM ))) + END IF + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + y_FAST%Module_Ver( Module_AD14 ) = Init%OutData_AD14%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_AD14 ) )) + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + y_FAST%Module_Ver( Module_AD ) = Init%OutData_AD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_AD ) )) + END IF + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + y_FAST%Module_Ver( Module_SrvD ) = Init%OutData_SrvD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_SrvD ))) + END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + y_FAST%Module_Ver( Module_HD ) = Init%OutData_HD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_HD ))) + END IF + + IF ( p_FAST%CompSub == Module_SD ) THEN + y_FAST%Module_Ver( Module_SD ) = Init%OutData_SD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_SD ))) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + y_FAST%Module_Ver( Module_ExtPtfm ) = Init%OutData_ExtPtfm%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_ExtPtfm ))) + END IF + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + y_FAST%Module_Ver( Module_MAP ) = Init%OutData_MAP%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_MAP ))) + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + y_FAST%Module_Ver( Module_MD ) = Init%OutData_MD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_MD ))) + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + y_FAST%Module_Ver( Module_FEAM ) = Init%OutData_FEAM%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_FEAM ))) + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + y_FAST%Module_Ver( Module_Orca ) = Init%OutData_Orca%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_Orca))) + END IF + + IF ( p_FAST%CompIce == Module_IceF ) THEN + y_FAST%Module_Ver( Module_IceF ) = Init%OutData_IceF%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_IceF ))) + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + y_FAST%Module_Ver( Module_IceD ) = Init%OutData_IceD%Ver + y_FAST%FileDescLines(2) = TRIM(y_FAST%FileDescLines(2) ) //'; '//TRIM(GetNVD(y_FAST%Module_Ver( Module_IceD ))) + END IF + + !...................................................... + ! Set the number of output columns from each module + !...................................................... + y_FAST%numOuts = 0 ! Inintialize entire array + + + + !y_FAST%numOuts(Module_InfW) = 3 !hack for now: always output 3 wind speeds at hub-height + IF ( ALLOCATED( Init%OutData_IfW%WriteOutputHdr ) ) y_FAST%numOuts(Module_IfW) = SIZE(Init%OutData_IfW%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_OpFM%WriteOutputHdr ) ) y_FAST%numOuts(Module_OpFM) = SIZE(Init%OutData_OpFM%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_ED%WriteOutputHdr ) ) y_FAST%numOuts(Module_ED) = SIZE(Init%OutData_ED%WriteOutputHdr) +do i=1,p_FAST%nBeams + IF ( ALLOCATED( Init%OutData_BD(i)%WriteOutputHdr) ) y_FAST%numOuts(Module_BD) = y_FAST%numOuts(Module_BD) + SIZE(Init%OutData_BD(i)%WriteOutputHdr) +end do +!ad14 doesn't have outputs: + y_FAST%numOuts(Module_AD14) = 0 + + IF ( ALLOCATED( Init%OutData_AD%WriteOutputHdr ) ) y_FAST%numOuts(Module_AD) = SIZE(Init%OutData_AD%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_SrvD%WriteOutputHdr ) ) y_FAST%numOuts(Module_SrvD) = SIZE(Init%OutData_SrvD%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_HD%WriteOutputHdr ) ) y_FAST%numOuts(Module_HD) = SIZE(Init%OutData_HD%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_SD%WriteOutputHdr ) ) y_FAST%numOuts(Module_SD) = SIZE(Init%OutData_SD%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_ExtPtfm%WriteOutputHdr) ) y_FAST%numOuts(Module_ExtPtfm)= SIZE(Init%OutData_ExtPtfm%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_MAP%WriteOutputHdr ) ) y_FAST%numOuts(Module_MAP) = SIZE(Init%OutData_MAP%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_FEAM%WriteOutputHdr ) ) y_FAST%numOuts(Module_FEAM) = SIZE(Init%OutData_FEAM%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_MD%WriteOutputHdr ) ) y_FAST%numOuts(Module_MD) = SIZE(Init%OutData_MD%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_Orca%WriteOutputHdr ) ) y_FAST%numOuts(Module_Orca) = SIZE(Init%OutData_Orca%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_IceF%WriteOutputHdr ) ) y_FAST%numOuts(Module_IceF) = SIZE(Init%OutData_IceF%WriteOutputHdr) + IF ( ALLOCATED( Init%OutData_IceD%WriteOutputHdr ) ) y_FAST%numOuts(Module_IceD) = SIZE(Init%OutData_IceD%WriteOutputHdr)*p_FAST%numIceLegs + + !...................................................... + ! Initialize the output channel names and units + !...................................................... + NumOuts = 1 + SUM( y_FAST%numOuts ) + + CALL AllocAry( y_FAST%ChannelNames,NumOuts, 'ChannelNames', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + CALL AllocAry( y_FAST%ChannelUnits,NumOuts, 'ChannelUnits', ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + y_FAST%ChannelNames(1) = 'Time' + y_FAST%ChannelUnits(1) = '(s)' + + indxNext = 2 + DO i=1,y_FAST%numOuts(Module_IfW) !InflowWind + y_FAST%ChannelNames(indxNext) = Init%OutData_IfW%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_IfW%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_OpFM) !OpenFOAM + y_FAST%ChannelNames(indxNext) = Init%OutData_OpFM%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_OpFM%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_ED) !ElastoDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_ED%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_ED%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + IF ( y_FAST%numOuts(Module_BD) > 0_IntKi ) THEN !BeamDyn + do i=1,p_FAST%nBeams + if ( allocated(Init%OutData_BD(i)%WriteOutputHdr) ) then + do j=1,size(Init%OutData_BD(i)%WriteOutputHdr) + y_FAST%ChannelNames(indxNext) = 'B'//TRIM(Num2Lstr(i))//trim(Init%OutData_BD(i)%WriteOutputHdr(j)) + y_FAST%ChannelUnits(indxNext) = Init%OutData_BD(i)%WriteOutputUnt(j) + indxNext = indxNext + 1 + end do ! j + end if + end do + END IF + + + ! none for AeroDyn14 + + DO i=1,y_FAST%numOuts(Module_AD) !AeroDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_AD%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_AD%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_SrvD) !ServoDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_SrvD%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_SrvD%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_HD) !HydroDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_HD%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_HD%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_SD) !SubDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_SD%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_SD%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_ExtPtfm) !ExtPtfm_MCKF + y_FAST%ChannelNames(indxNext) = Init%OutData_ExtPtfm%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_ExtPtfm%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_MAP) !MAP + y_FAST%ChannelNames(indxNext) = Init%OutData_MAP%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_MAP%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_MD) !MoorDyn + y_FAST%ChannelNames(indxNext) = Init%OutData_MD%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_MD%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_FEAM) !FEAMooring + y_FAST%ChannelNames(indxNext) = Init%OutData_FEAM%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_FEAM%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_Orca) !OrcaFlex + y_FAST%ChannelNames(indxNext) = Init%OutData_Orca%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_Orca%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + DO i=1,y_FAST%numOuts(Module_IceF) !IceFloe + y_FAST%ChannelNames(indxNext) = Init%OutData_IceF%WriteOutputHdr(i) + y_FAST%ChannelUnits(indxNext) = Init%OutData_IceF%WriteOutputUnt(i) + indxNext = indxNext + 1 + END DO + + IF ( y_FAST%numOuts(Module_IceD) > 0_IntKi ) THEN !IceDyn + DO I=1,p_FAST%numIceLegs + DO J=1,SIZE(Init%OutData_IceD%WriteOutputHdr) + y_FAST%ChannelNames(indxNext) =TRIM(Init%OutData_IceD%WriteOutputHdr(J))//'L'//TRIM(Num2Lstr(I)) !bjj: do we want this "Lx" at the end? + y_FAST%ChannelUnits(indxNext) = Init%OutData_IceD%WriteOutputUnt(J) + indxNext = indxNext + 1 + END DO ! J + END DO ! I + END IF + + + !...................................................... + ! Open the text output file and print the headers + !...................................................... + + IF (p_FAST%WrTxtOutFile) THEN + + y_FAST%ActualChanLen = max( MinChanLen, p_FAST%FmtWidth ) + DO I=1,NumOuts + y_FAST%ActualChanLen = max( y_FAST%ActualChanLen, LEN_TRIM(y_FAST%ChannelNames(I)) ) + y_FAST%ActualChanLen = max( y_FAST%ActualChanLen, LEN_TRIM(y_FAST%ChannelUnits(I)) ) + ENDDO ! I + + y_FAST%OutFmt_a = '"'//p_FAST%Delim//'"'//p_FAST%OutFmt ! format for array elements from individual modules + if (p_FAST%FmtWidth < y_FAST%ActualChanLen) then + y_FAST%OutFmt_a = trim(y_FAST%OutFmt_a)//','//trim(num2lstr(y_FAST%ActualChanLen - p_FAST%FmtWidth))//'x' + end if + + CALL GetNewUnit( y_FAST%UnOu, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL OpenFOutFile ( y_FAST%UnOu, TRIM(p_FAST%OutFileRoot)//'.out', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Add some file information: + + WRITE (y_FAST%UnOu,'(/,A)') TRIM( y_FAST%FileDescLines(1) ) + WRITE (y_FAST%UnOu,'(1X,A)') TRIM( y_FAST%FileDescLines(2) ) + WRITE (y_FAST%UnOu,'()' ) !print a blank line + WRITE (y_FAST%UnOu,'(A)' ) TRIM( y_FAST%FileDescLines(3) ) + WRITE (y_FAST%UnOu,'()' ) !print a blank line + + + !...................................................... + ! Write the names of the output parameters on one line: + !...................................................... + if (p_FAST%Delim /= " ") then ! trim trailing spaces if not space delimited: + + CALL WrFileNR ( y_FAST%UnOu, trim(y_FAST%ChannelNames(1)) ) ! first one is time, with a special format + + DO I=2,NumOuts + CALL WrFileNR ( y_FAST%UnOu, p_FAST%Delim//trim(y_FAST%ChannelNames(I)) ) + ENDDO ! I + else + + CALL WrFileNR ( y_FAST%UnOu, y_FAST%ChannelNames(1)(1:p_FAST%TChanLen) ) ! first one is time, with a special format + + DO I=2,NumOuts + CALL WrFileNR ( y_FAST%UnOu, p_FAST%Delim//y_FAST%ChannelNames(I)(1:y_FAST%ActualChanLen) ) + ENDDO ! I + end if + + WRITE (y_FAST%UnOu,'()') + + !...................................................... + ! Write the units of the output parameters on one line: + !...................................................... + + if (p_FAST%Delim /= " ") then + + CALL WrFileNR ( y_FAST%UnOu, trim(y_FAST%ChannelUnits(1)) ) + + DO I=2,NumOuts + CALL WrFileNR ( y_FAST%UnOu, p_FAST%Delim//trim(y_FAST%ChannelUnits(I)) ) + ENDDO ! I + else + + CALL WrFileNR ( y_FAST%UnOu, y_FAST%ChannelUnits(1)(1:p_FAST%TChanLen) ) + + DO I=2,NumOuts + CALL WrFileNR ( y_FAST%UnOu, p_FAST%Delim//y_FAST%ChannelUnits(I)(1:y_FAST%ActualChanLen) ) + ENDDO ! I + end if + + WRITE (y_FAST%UnOu,'()') + + END IF + + !...................................................... + ! Allocate data for binary output file + !...................................................... + IF (p_FAST%WrBinOutFile) THEN + + ! calculate the size of the array of outputs we need to store + y_FAST%NOutSteps = CEILING ( (p_FAST%TMax - p_FAST%TStart) / p_FAST%DT_OUT ) + 1 + + CALL AllocAry( y_FAST%AllOutData, NumOuts-1, y_FAST%NOutSteps, 'AllOutData', ErrStat, ErrMsg ) + y_FAST%AllOutData = 0.0_ReKi + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( p_FAST%WrBinMod == FileFmtID_WithTime ) THEN ! we store the entire time array + CALL AllocAry( y_FAST%TimeData, y_FAST%NOutSteps, 'TimeData', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + ELSE + CALL AllocAry( y_FAST%TimeData, 2_IntKi, 'TimeData', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + y_FAST%TimeData(1) = 0.0_DbKi ! This is the first output time, which we will set later + y_FAST%TimeData(2) = p_FAST%DT_out ! This is the (constant) time between subsequent writes to the output file + END IF + + y_FAST%n_Out = 0 !number of steps actually written to the file + + END IF + + y_FAST%VTK_count = 0 ! first VTK file has 0 as output + +RETURN +END SUBROUTINE FAST_InitOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary FAST input file, does some validation, and places the values it reads in the +!! parameter structure (p). It prints to an echo file if requested. +SUBROUTINE FAST_ReadPrimaryFile( InputFile, p, m_FAST, OverrideAbortErrLev, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables + TYPE(FAST_ParameterType), INTENT(INOUT) :: p !< The parameter data for the FAST (glue-code) simulation + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + LOGICAL, INTENT(IN) :: OverrideAbortErrLev !< Determines if we should override AbortErrLev + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables: + REAL(DbKi) :: TmpRate ! temporary variable to read VTK_fps before converting to #steps based on DT + REAL(DbKi) :: TmpTime ! temporary variable to read SttsTime and ChkptTime before converting to #steps based on DT + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + + INTEGER(IntKi) :: IOS ! Temporary Error status + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + INTEGER(IntKi) :: OutFileFmt ! An integer that indicates what kind of tabular output should be generated (1=text, 2=binary, 3=both) + LOGICAL :: Echo ! Determines if an echo file should be written + LOGICAL :: TabDelim ! Determines if text output should be delimited by tabs (true) or space (false) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + CHARACTER(10) :: AbortLevel ! String that indicates which error level should be used to abort the program: WARNING, SEVERE, or FATAL + CHARACTER(30) :: Line ! string for default entry in input file + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_ReadPrimaryFile' + + + ! Initialize some variables: + UnEc = -1 + Echo = .FALSE. ! Don't echo until we've read the "Echo" flag + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + DO + !-------------------------- HEADER --------------------------------------------- + + CALL ReadCom( UnIn, InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + CALL ReadStr( UnIn, InputFile, p%FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + !---------------------- SIMULATION CONTROL -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Simulation Control', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ! Echo - Echo input data to <RootName>.ech (flag): + CALL ReadVar( UnIn, InputFile, Echo, "Echo", "Echo input data to <RootName>.ech (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(p%OutFileRoot)//'.ech', ErrStat2, ErrMsg2, FAST_Ver ) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(FAST_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".',ErrStat,ErrMsg,RoutineName) + call cleanup() + RETURN + END IF + + END DO + + CALL WrScr( TRIM(FAST_Ver%Name)//' input file heading:' ) + CALL WrScr( ' '//TRIM( p%FTitle ) ) + CALL WrScr('') + + + ! AbortLevel - Error level when simulation should abort: + CALL ReadVar( UnIn, InputFile, AbortLevel, "AbortLevel", "Error level when simulation should abort (string)", & + ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF (OverrideAbortErrLev) THEN + ! Let's set the abort level here.... knowing that everything before this aborted only on FATAL errors! + CALL Conv2UC( AbortLevel ) !convert to upper case + SELECT CASE( TRIM(AbortLevel) ) + CASE ( "WARNING" ) + AbortErrLev = ErrID_Warn + CASE ( "SEVERE" ) + AbortErrLev = ErrID_Severe + CASE ( "FATAL" ) + AbortErrLev = ErrID_Fatal + CASE DEFAULT + CALL SetErrStat( ErrID_Fatal, 'Invalid AbortLevel specified in FAST input file. '// & + 'Valid entries are "WARNING", "SEVERE", or "FATAL".',ErrStat,ErrMsg,RoutineName) + call cleanup() + RETURN + END SELECT + END IF + + + ! TMax - Total run time (s): + CALL ReadVar( UnIn, InputFile, p%TMax, "TMax", "Total run time (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! DT - Recommended module time step (s): + CALL ReadVar( UnIn, InputFile, p%DT, "DT", "Recommended module time step (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + if ( EqualRealNos(p%DT, 0.0_DbKi) ) then + ! add a fatal error here because we're going to divide by DT later in this routine: + CALL SetErrStat( ErrID_Fatal, 'DT cannot be zero.', ErrStat, ErrMsg, RoutineName) + call cleanup() + return + end if + + + ! InterpOrder - Interpolation order for inputs and outputs {0=nearest neighbor ,1=linear, 2=quadratic} + CALL ReadVar( UnIn, InputFile, p%InterpOrder, "InterpOrder", "Interpolation order "//& + "for inputs and outputs {0=nearest neighbor ,1=linear, 2=quadratic} (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! NumCrctn - Number of predictor-corrector iterations {1=explicit calculation, i.e., no corrections} + CALL ReadVar( UnIn, InputFile, p%NumCrctn, "NumCrctn", "Number of corrections"//& + "{0=explicit calculation, i.e., no corrections} (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! DT_UJac - Time between calls to get Jacobians (s) + CALL ReadVar( UnIn, InputFile, p%DT_UJac, "DT_UJac", "Time between calls to get Jacobians (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! UJacSclFact - Scaling factor used in Jacobians (-) + CALL ReadVar( UnIn, InputFile, p%UJacSclFact, "UJacSclFact", "Scaling factor used in Jacobians (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + !---------------------- FEATURE SWITCHES AND FLAGS -------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Feature Switches and Flags', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! CompElast - Compute structural dynamics (switch) {1=ElastoDyn; 2=ElastoDyn + BeamDyn for blades}: + CALL ReadVar( UnIn, InputFile, p%CompElast, "CompElast", "Compute structural dynamics (switch) {1=ElastoDyn; 2=ElastoDyn + BeamDyn for blades}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompElast == 1 ) THEN + p%CompElast = Module_ED + ELSEIF ( p%CompElast == 2 ) THEN + p%CompElast = Module_BD + ELSE + p%CompElast = Module_Unknown + END IF + + ! CompInflow - inflow wind velocities (switch) {0=still air; 1=InflowWind}: + CALL ReadVar( UnIn, InputFile, p%CompInflow, "CompInflow", "inflow wind velocities (switch) {0=still air; 1=InflowWind}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompInflow == 0 ) THEN + p%CompInflow = Module_NONE + ELSEIF ( p%CompInflow == 1 ) THEN + p%CompInflow = Module_IfW + ELSEIF ( p%CompInflow == 2 ) THEN + p%CompInflow = Module_OpFM + ELSE + p%CompInflow = Module_Unknown + END IF + + ! CompAero - Compute aerodynamic loads (switch) {0=None; 1=AeroDyn}: + CALL ReadVar( UnIn, InputFile, p%CompAero, "CompAero", "Compute aerodynamic loads (switch) {0=None; 1=AeroDyn}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompAero == 0 ) THEN + p%CompAero = Module_NONE + ELSEIF ( p%CompAero == 1 ) THEN + p%CompAero = Module_AD14 + ELSEIF ( p%CompAero == 2 ) THEN + p%CompAero = Module_AD + ELSE + p%CompAero = Module_Unknown + END IF + + ! CompServo - Compute control and electrical-drive dynamics (switch) {0=None; 1=ServoDyn}: + CALL ReadVar( UnIn, InputFile, p%CompServo, "CompServo", "Compute control and electrical-drive dynamics (switch) {0=None; 1=ServoDyn}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompServo == 0 ) THEN + p%CompServo = Module_NONE + ELSEIF ( p%CompServo == 1 ) THEN + p%CompServo = Module_SrvD + ELSE + p%CompServo = Module_Unknown + END IF + + + ! CompHydro - Compute hydrodynamic loads (switch) {0=None; 1=HydroDyn}: + CALL ReadVar( UnIn, InputFile, p%CompHydro, "CompHydro", "Compute hydrodynamic loads (switch) {0=None; 1=HydroDyn}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompHydro == 0 ) THEN + p%CompHydro = Module_NONE + ELSEIF ( p%CompHydro == 1 ) THEN + p%CompHydro = Module_HD + ELSE + p%CompHydro = Module_Unknown + END IF + + ! CompSub - Compute sub-structural dynamics (switch) {0=None; 1=SubDyn; 2=ExtPtfm_MCKF}: + CALL ReadVar( UnIn, InputFile, p%CompSub, "CompSub", "Compute sub-structural dynamics (switch) {0=None; 1=SubDyn}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompSub == 0 ) THEN + p%CompSub = Module_NONE + ELSEIF ( p%CompSub == 1 ) THEN + p%CompSub = Module_SD + ELSEIF ( p%CompSub == 2 ) THEN + p%CompSub = Module_ExtPtfm + ELSE + p%CompSub = Module_Unknown + END IF + + ! CompMooring - Compute mooring line dynamics (flag): + CALL ReadVar( UnIn, InputFile, p%CompMooring, "CompMooring", "Compute mooring system (switch) {0=None; 1=MAP; 2=FEAMooring; 3=MoorDyn; 4=OrcaFlex}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompMooring == 0 ) THEN + p%CompMooring = Module_NONE + ELSEIF ( p%CompMooring == 1 ) THEN + p%CompMooring = Module_MAP + ELSEIF ( p%CompMooring == 2 ) THEN + p%CompMooring = Module_FEAM + ELSEIF ( p%CompMooring == 3 ) THEN + p%CompMooring = Module_MD + ELSEIF ( p%CompMooring == 4 ) THEN + p%CompMooring = Module_Orca + ELSE + p%CompMooring = Module_Unknown + END IF + + ! CompIce - Compute ice loads (switch) {0=None; 1=IceFloe}: + CALL ReadVar( UnIn, InputFile, p%CompIce, "CompIce", "Compute ice loads (switch) {0=None; 1=IceFloe}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%CompIce == 0 ) THEN + p%CompIce = Module_NONE + ELSEIF ( p%CompIce == 1 ) THEN + p%CompIce = Module_IceF + ELSEIF ( p%CompIce == 2 ) THEN + p%CompIce = Module_IceD + ELSE + p%CompIce = Module_Unknown + END IF + + + !---------------------- INPUT FILES --------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Input Files', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! EDFile - Name of file containing ElastoDyn input parameters (-): + CALL ReadVar( UnIn, InputFile, p%EDFile, "EDFile", "Name of file containing ElastoDyn input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%EDFile ) ) p%EDFile = TRIM(PriPath)//TRIM(p%EDFile) + +DO i=1,MaxNBlades + ! BDBldFile - Name of file containing BeamDyn blade input parameters (-): + CALL ReadVar( UnIn, InputFile, p%BDBldFile(i), "BDBldFile("//TRIM(num2LStr(i))//")", "Name of file containing BeamDyn blade "//trim(num2lstr(i))//"input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%BDBldFile(i) ) ) p%BDBldFile(i) = TRIM(PriPath)//TRIM(p%BDBldFile(i)) +END DO + + ! InflowFile - Name of file containing inflow wind input parameters (-): + CALL ReadVar( UnIn, InputFile, p%InflowFile, "InflowFile", "Name of file containing inflow wind input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%InflowFile ) ) p%InflowFile = TRIM(PriPath)//TRIM(p%InflowFile) + + ! AeroFile - Name of file containing aerodynamic input parameters (-): + CALL ReadVar( UnIn, InputFile, p%AeroFile, "AeroFile", "Name of file containing aerodynamic input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%AeroFile ) ) p%AeroFile = TRIM(PriPath)//TRIM(p%AeroFile) + + ! ServoFile - Name of file containing control and electrical-drive input parameters (-): + CALL ReadVar( UnIn, InputFile, p%ServoFile, "ServoFile", "Name of file containing control and electrical-drive input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%ServoFile ) ) p%ServoFile = TRIM(PriPath)//TRIM(p%ServoFile) + + ! HydroFile - Name of file containing hydrodynamic input parameters (-): + CALL ReadVar( UnIn, InputFile, p%HydroFile, "HydroFile", "Name of file containing hydrodynamic input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%HydroFile ) ) p%HydroFile = TRIM(PriPath)//TRIM(p%HydroFile) + + ! SubFile - Name of file containing sub-structural input parameters (-): + CALL ReadVar( UnIn, InputFile, p%SubFile, "SubFile", "Name of file containing sub-structural input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%SubFile ) ) p%SubFile = TRIM(PriPath)//TRIM(p%SubFile) + + ! MooringFile - Name of file containing mooring system input parameters (-): + CALL ReadVar( UnIn, InputFile, p%MooringFile, "MooringFile", "Name of file containing mooring system input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%MooringFile ) ) p%MooringFile = TRIM(PriPath)//TRIM(p%MooringFile) + + ! IceFile - Name of file containing ice input parameters (-): + CALL ReadVar( UnIn, InputFile, p%IceFile, "IceFile", "Name of file containing ice input parameters (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + IF ( PathIsRelative( p%IceFile ) ) p%IceFile = TRIM(PriPath)//TRIM(p%IceFile) + + + !---------------------- OUTPUT -------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Output', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! SumPrint - Print summary data to <RootName>.sum (flag): + CALL ReadVar( UnIn, InputFile, p%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! SttsTime - Amount of time between screen status messages (s): + CALL ReadVar( UnIn, InputFile, TmpTime, "SttsTime", "Amount of time between screen status messages (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF (TmpTime > p%TMax) THEN + p%n_SttsTime = HUGE(p%n_SttsTime) + ELSE + p%n_SttsTime = NINT( TmpTime / p%DT ) + END IF + + ! ChkptTime - Amount of time between creating checkpoint files for potential restart (s): + CALL ReadVar( UnIn, InputFile, TmpTime, "ChkptTime", "Amount of time between creating checkpoint files for potential restart (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF (TmpTime > p%TMax) THEN + p%n_ChkptTime = HUGE(p%n_ChkptTime) + ELSE + p%n_ChkptTime = NINT( TmpTime / p%DT ) + END IF + + ! DT_Out - Time step for tabular output (s): + CALL ReadVar( UnIn, InputFile, Line, "DT_Out", "Time step for tabular output (s)", ErrStat2, ErrMsg2, UnEc) + !CALL ReadVar( UnIn, InputFile, p%DT_Out, "DT_Out", "Time step for tabular output (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) == 1 ) THEN + p%DT_Out = p%DT + ELSE + ! If it's not "default", read this variable; otherwise use the value in p%DT + READ( Line, *, IOSTAT=IOS) p%DT_Out + CALL CheckIOS ( IOS, InputFile, 'DT_Out', NumType, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + END IF + + p%n_DT_Out = NINT( p%DT_Out / p%DT ) + + ! TStart - Time to begin tabular output (s): + CALL ReadVar( UnIn, InputFile, p%TStart, "TStart", "Time to begin tabular output (s)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + !> OutFileFmt - Format for tabular (time-marching) output file (switch) {1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 4: HDF5 [<RootName>.h5], add for combinations} + !! + !! Combinations of output files are possible by adding the values corresponding to each file. The possible combination of options are therefore + !! + !! | `OutFileFmt` | Description | + !! |:------------:|:---------------------------------------------------------------------| + !! | 1 | Text file only `<RootName>.out` | + !! | 2 | Binary file only `<RootName>.outb` | + !! | 3 | Text and binary files | + !! | 4 | uncompressed binary file `<RootName>.outbu` | + !! | 5 | Text and uncompressed binary files | + !! | 6 => 4 | Binary (not written) and uncompressed binary files; same as 4 | + !! | 7 => 5 | Text, Binary (not written), and uncompressed binary files; same as 5 | + !! + + ! OutFileFmt - Format for tabular (time-marching) output file(s) (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both) (-): + CALL ReadVar( UnIn, InputFile, OutFileFmt, "OutFileFmt", "Format for tabular (time-marching) output file(s) {0: uncompressed binary and text file, 1: text file [<RootName>.out], 2: compressed binary file [<RootName>.outb], 3: both text and compressed binary, 4: uncompressed binary <RootName>.outb]; add for combinations) (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + if (OutFileFmt == 0) OutFileFmt = 5 + + ! convert integer to binary representation of which file formats to generate: + p%WrTxtOutFile = mod(OutFileFmt,2) == 1 + + OutFileFmt = OutFileFmt / 2 ! integer division + p%WrBinOutFile = mod(OutFileFmt,2) == 1 + + OutFileFmt = OutFileFmt / 2 ! integer division + if (mod(OutFileFmt,2) == 1) then + ! This is a feature for the regression testing system. It writes binary output stored as uncompressed double floating point data instead of compressed int16 data. + ! If the compressed binary version was requested, that will not be generated + if (p%WrBinOutFile) then + call SetErrStat(ErrID_Warn,'Binary compressed file will not be generated because the uncompressed version was also requested.', ErrStat, ErrMsg, RoutineName) + else + p%WrBinOutFile = .true. + end if + p%WrBinMod = FileFmtID_NoCompressWithoutTime ! A format specifier for the binary output file format (3=don't include time channel and do not pack data) + else + p%WrBinMod = FileFmtID_ChanLen_In ! A format specifier for the binary output file format (4=don't include time channel; do include channel width; do pack data) + end if + + OutFileFmt = OutFileFmt / 2 ! integer division + + if (OutFileFmt /= 0) then + call SetErrStat( ErrID_Fatal, "OutFileFmt must be 0, 1, 2, or 3.",ErrStat,ErrMsg,RoutineName) + call cleanup() + return + end if + + ! TabDelim - Use tab delimiters in text tabular output file? (flag): + CALL ReadVar( UnIn, InputFile, TabDelim, "TabDelim", "Use tab delimiters in text tabular output file? (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF ( TabDelim ) THEN + p%Delim = TAB + ELSE + p%Delim = ' ' + END IF + + ! OutFmt - Format used for text tabular output (except time). Resulting field should be 10 characters. (-): + CALL ReadVar( UnIn, InputFile, p%OutFmt, "OutFmt", "Format used for text tabular output (except time). Resulting field should be 10 characters. (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + !---------------------- LINEARIZATION ----------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Linearization', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ! Linearize - Linearization analysis (flag) + CALL ReadVar( UnIn, InputFile, p%Linearize, "Linearize", "Linearization analysis (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ! CalcSteady - Calculate a steady-state periodic operating point before linearization? [unused if Linearize=False] (flag) + CALL ReadVar( UnIn, InputFile, p%CalcSteady, "CalcSteady", "Calculate a steady-state periodic operating point before linearization? (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! TrimCase - Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] (-) + CALL ReadVar( UnIn, InputFile, p%TrimCase, "TrimCase", "Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! TrimTol - Tolerance for the rotational speed convergence [used only if CalcSteady=True] (-) + CALL ReadVar( UnIn, InputFile, p%TrimTol, "TrimTol", "Tolerance for the rotational speed convergence (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! TrimGain - Proportional gain for the rotational speed error (>0) [used only if CalcSteady=True] (rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque) + CALL ReadVar( UnIn, InputFile, p%TrimGain, "TrimGain", "Proportional gain for the rotational speed error (>0) (rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Twr_Kdmp - Damping factor for the tower [used only if CalcSteady=True] (N/(m/s)) + CALL ReadVar( UnIn, InputFile, p%Twr_Kdmp, "Twr_Kdmp", "Damping factor for the tower (N/(m/s))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Bld_Kdmp - Damping factor for the blades [used only if CalcSteady=True] (N/(m/s)) + CALL ReadVar( UnIn, InputFile, p%Bld_Kdmp, "Bld_Kdmp", "Damping factor for the blades (N/(m/s))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! NLinTimes - Number of times to linearize (or number of equally spaced azimuth steps in periodic linearized model) (-) [>=1] + CALL ReadVar( UnIn, InputFile, p%NLinTimes, "NLinTimes", "Number of times to linearize (-) [>=1]", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + if (.not. p%Linearize) then + p%CalcSteady = .false. + p%NLinTimes = 0 + end if + + ! LinTimes - Times to linearize (s) [1 to NLinTimes] + if (.not. p%CalcSteady .and. p%NLinTimes >= 1 ) then + call AllocAry( m_FAST%Lin%LinTimes, p%NLinTimes, 'LinTimes', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + CALL ReadAry( UnIn, InputFile, m_FAST%Lin%LinTimes, p%NLinTimes, "LinTimes", "Times to linearize (s) [1 to NLinTimes]", ErrStat2, ErrMsg2, UnEc) + else + CALL ReadCom( UnIn, InputFile, 'Times to linearize (s) [1 to NLinTimes] ', ErrStat2, ErrMsg2, UnEc ) + end if + CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! LinInputs - Include inputs in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)} + CALL ReadVar( UnIn, InputFile, p%LinInputs, "LinInputs", "Include inputs in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)}", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! LinOutputs - Include outputs in linearization (switch) (0=none; 1=from OutList(s); 2=all module outputs (debug)) + CALL ReadVar( UnIn, InputFile, p%LinOutputs, "LinOutputs", "Include outputs in linearization (switch) (0=none; 1=from OutList(s); 2=all module outputs (debug))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! LinOutJac - Include full Jacabians in linearization output (for debug) (flag) + CALL ReadVar( UnIn, InputFile, p%LinOutJac, "LinOutJac", "Include full Jacabians in linearization output (for debug) (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! LinOutMod - Write module-level linearization output files in addition to output for full system? (flag) + CALL ReadVar( UnIn, InputFile, p%LinOutMod, "LinOutMod", "Write module-level linearization output files in addition to output for full system? (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + !---------------------- VISUALIZATION ----------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Visualization', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! WrVTK - VTK Visualization data output: (switch) {0=none; 1=initialization data only; 2=animation; 3=mode shapes}: + CALL ReadVar( UnIn, InputFile, p%WrVTK, "WrVTK", "Write VTK visualization files (0=none; 1=initialization data only; 2=animation; 3=mode shapes)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + IF ( p%WrVTK < 0 .OR. p%WrVTK > 3 ) THEN + p%WrVTK = VTK_Unknown + END IF + + ! VTK_Type - Type of VTK visualization data: (switch) {1=surfaces; 2=basic meshes (lines/points); 3=all meshes (debug)}: + CALL ReadVar( UnIn, InputFile, p%VTK_Type, "VTK_Type", "Type of VTK visualization data: (1=surfaces; 2=basic meshes (lines/points); 3=all meshes)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! immediately convert to values used inside the code: + IF ( p%VTK_Type == 0 ) THEN + p%VTK_Type = VTK_None + ELSEIF ( p%VTK_Type == 1 ) THEN + p%VTK_Type = VTK_Surf + ELSEIF ( p%VTK_Type == 2 ) THEN + p%VTK_Type = VTK_Basic + ELSEIF ( p%VTK_Type == 3 ) THEN + p%VTK_Type = VTK_All + ELSEIF ( p%VTK_Type == 4 ) THEN + p%VTK_Type = VTK_Old + ELSE + p%VTK_Type = VTK_Unknown + END IF + + !! equivalent: + !IF ( p%VTK_Type < 0 .OR. p%VTK_Type > 4 ) THEN + ! p%VTK_Type = VTK_Unknown + !END IF + + ! VTK_fields - Write mesh fields to VTK data files? (flag) {true/false}: + CALL ReadVar( UnIn, InputFile, p%VTK_fields, "VTK_fields", "Write mesh fields to VTK data files? (flag)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + ! VTK_fps - Frame rate for VTK output (frames per second) {will use closest integer multiple of DT} + CALL ReadVar( UnIn, InputFile, p%VTK_fps, "VTK_fps", "Frame rate for VTK output(fps)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ! convert frames-per-second to seconds per sample: + if ( EqualRealNos(p%VTK_fps, 0.0_DbKi) ) then + TmpTime = p%TMax + p%DT + else + TmpTime = 1.0_DbKi / p%VTK_fps + end if + + ! now save the number of time steps between VTK file output: + IF (p%WrVTK == VTK_ModeShapes) THEN + p%n_VTKTime = 1 + ELSE IF (TmpTime > p%TMax) THEN + p%n_VTKTime = HUGE(p%n_VTKTime) + ELSE + p%n_VTKTime = NINT( TmpTime / p%DT ) + ! I'll warn if p%n_VTKTime*p%DT is not TmpTime + IF (p%WrVTK == VTK_Animate) THEN + TmpRate = p%n_VTKTime*p%DT + if (.not. EqualRealNos(TmpRate, TmpTime)) then + call SetErrStat(ErrID_Info, '1/VTK_fps is not an integer multiple of DT. FAST will output VTK information at '//& + trim(num2lstr(1.0_DbKi/TmpRate))//' fps, the closest rate possible.',ErrStat,ErrMsg,RoutineName) + end if + END IF + + END IF + + call cleanup() + RETURN + +CONTAINS + !............................................................................................................................... + subroutine cleanup() + CLOSE( UnIn ) + IF ( UnEc > 0 ) CLOSE ( UnEc ) + end subroutine cleanup + !............................................................................................................................... +END SUBROUTINE FAST_ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets up some of the information needed for plotting VTK surfaces. It initializes only the data needed before +!! HD initialization. (HD needs some of this data so it can return the wave elevation data we want.) +SUBROUTINE SetVTKParameters_B4HD(p_FAST, InitOutData_ED, InitInData_HD, BD, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< The parameters of the glue code + TYPE(ED_InitOutputType), INTENT(IN ) :: InitOutData_ED !< The initialization output from structural dynamics module + TYPE(HydroDyn_InitInputType), INTENT(INOUT) :: InitInData_HD !< The initialization input to HydroDyn + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + REAL(SiKi) :: BladeLength, Width, WidthBy2 + REAL(SiKi) :: dx, dy + INTEGER(IntKi) :: i, j, n + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetVTKParameters_B4HD' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get radius for ground (blade length + hub radius): + if ( p_FAST%CompElast == Module_BD ) then + BladeLength = TwoNorm(BD%y(1)%BldMotion%Position(:,1) - BD%y(1)%BldMotion%Position(:,BD%y(1)%BldMotion%Nnodes)) + else + BladeLength = InitOutData_ED%BladeLength + end if + p_FAST%VTK_Surface%HubRad = InitOutData_ED%HubRad + p_FAST%VTK_Surface%GroundRad = BladeLength + p_FAST%VTK_Surface%HubRad + + !........................................................................................................ + ! We don't use the rest of this routine for stick-figure output + if (p_FAST%VTK_Type /= VTK_Surf) return + !........................................................................................................ + + ! initialize wave elevation data: + if ( p_FAST%CompHydro == Module_HD ) then + + p_FAST%VTK_surface%NWaveElevPts(1) = 25 + p_FAST%VTK_surface%NWaveElevPts(2) = 25 + + call allocAry( InitInData_HD%WaveElevXY, 2, p_FAST%VTK_surface%NWaveElevPts(1)*p_FAST%VTK_surface%NWaveElevPts(2), 'WaveElevXY', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + Width = p_FAST%VTK_Surface%GroundRad * VTK_GroundFactor + dx = Width / (p_FAST%VTK_surface%NWaveElevPts(1) - 1) + dy = Width / (p_FAST%VTK_surface%NWaveElevPts(2) - 1) + + WidthBy2 = Width / 2.0_SiKi + n = 1 + do i=1,p_FAST%VTK_surface%NWaveElevPts(1) + do j=1,p_FAST%VTK_surface%NWaveElevPts(2) + InitInData_HD%WaveElevXY(1,n) = dx*(i-1) - WidthBy2 !+ p_FAST%TurbinePos(1) ! HD takes p_FAST%TurbinePos into account already + InitInData_HD%WaveElevXY(2,n) = dy*(j-1) - WidthBy2 !+ p_FAST%TurbinePos(2) + n = n+1 + end do + end do + + end if + + +END SUBROUTINE SetVTKParameters_B4HD +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets up the information needed for plotting VTK surfaces. +SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_AD, InitInData_HD, InitOutData_HD, ED, BD, AD, HD, ErrStat, ErrMsg) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< The parameters of the glue code + TYPE(ED_InitOutputType), INTENT(IN ) :: InitOutData_ED !< The initialization output from structural dynamics module + TYPE(AD_InitOutputType), INTENT(INOUT) :: InitOutData_AD !< The initialization output from AeroDyn + TYPE(HydroDyn_InitInputType), INTENT(INOUT) :: InitInData_HD !< The initialization input to HydroDyn + TYPE(HydroDyn_InitOutputType),INTENT(INOUT) :: InitOutData_HD !< The initialization output from HydroDyn + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(SiKi) :: RefPoint(3), RefLengths(2) + REAL(SiKi) :: x, y + REAL(SiKi) :: TwrDiam_top, TwrDiam_base, TwrRatio, TwrLength + INTEGER(IntKi) :: topNode, baseNode + INTEGER(IntKi) :: NumBl, k + CHARACTER(1024) :: vtkroot + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetVTKParameters' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! get the name of the output directory for vtk files (in a subdirectory called "vtk" of the output directory), and + ! create the VTK directory if it does not exist + + call GetPath ( p_FAST%OutFileRoot, p_FAST%VTK_OutFileRoot, vtkroot ) ! the returned p_FAST%VTK_OutFileRoot includes a file separator character at the end + p_FAST%VTK_OutFileRoot = trim(p_FAST%VTK_OutFileRoot) // 'vtk' + + call MKDIR( trim(p_FAST%VTK_OutFileRoot) ) + + p_FAST%VTK_OutFileRoot = trim( p_FAST%VTK_OutFileRoot ) // PathSep // trim(vtkroot) + + + ! calculate the number of digits in 'y_FAST%NOutSteps' (Maximum number of output steps to be written) + ! this will be used to pad the write-out step in the VTK filename with zeros in calls to MeshWrVTK() + if (p_FAST%WrVTK == VTK_ModeShapes .AND. p_FAST%VTK_modes%VTKLinTim==1) then + if (p_FAST%NLinTimes < 1) p_FAST%NLinTimes = 1 !in case we reached here with an error + p_FAST%VTK_tWidth = CEILING( log10( real( p_FAST%NLinTimes) ) ) + 1 + else + p_FAST%VTK_tWidth = CEILING( log10( real(p_FAST%n_TMax_m1+1, ReKi) / p_FAST%n_VTKTime ) ) + 1 + end if + + ! determine number of blades + NumBl = InitOutData_ED%NumBl + + ! initialize the vtk data + + p_FAST%VTK_Surface%NumSectors = 25 + ! NOTE: we set p_FAST%VTK_Surface%GroundRad and p_FAST%VTK_Surface%HubRad in SetVTKParameters_B4HD + + + ! write the ground or seabed reference polygon: + RefPoint = p_FAST%TurbinePos + if (p_FAST%CompHydro == MODULE_HD) then + RefLengths = p_FAST%VTK_Surface%GroundRad*VTK_GroundFactor/2.0_SiKi + + ! note that p_FAST%TurbinePos(3) must be 0 for offshore turbines + RefPoint(3) = p_FAST%TurbinePos(3) - InitOutData_HD%WtrDpth + call WrVTK_Ground ( RefPoint, RefLengths, trim(p_FAST%VTK_OutFileRoot) // '.SeabedSurface', ErrStat2, ErrMsg2 ) + + RefPoint(3) = p_FAST%TurbinePos(3) - InitOutData_HD%MSL2SWL + call WrVTK_Ground ( RefPoint, RefLengths, trim(p_FAST%VTK_OutFileRoot) // '.StillWaterSurface', ErrStat2, ErrMsg2 ) + else + RefLengths = p_FAST%VTK_Surface%GroundRad !array = scalar + call WrVTK_Ground ( RefPoint, RefLengths, trim(p_FAST%VTK_OutFileRoot) // '.GroundSurface', ErrStat2, ErrMsg2 ) + end if + + + !........................................................................................................ + ! We don't use the rest of this routine for stick-figure output + if (p_FAST%VTK_Type /= VTK_Surf) return + !........................................................................................................ + + ! we're going to create a box using these dimensions + y = ED%y%HubPtMotion%Position(3, 1) - ED%y%NacelleMotion%Position(3, 1) + x = TwoNorm( ED%y%HubPtMotion%Position(1:2,1) - ED%y%NacelleMotion%Position(1:2,1) ) - p_FAST%VTK_Surface%HubRad + + + p_FAST%VTK_Surface%NacelleBox(:,1) = (/ -x, y, 0.0_SiKi /) + p_FAST%VTK_Surface%NacelleBox(:,2) = (/ x, y, 0.0_SiKi /) + p_FAST%VTK_Surface%NacelleBox(:,3) = (/ x, -y, 0.0_SiKi /) + p_FAST%VTK_Surface%NacelleBox(:,4) = (/ -x, -y, 0.0_SiKi /) + p_FAST%VTK_Surface%NacelleBox(:,5) = (/ -x, -y, 2*y /) + p_FAST%VTK_Surface%NacelleBox(:,6) = (/ x, -y, 2*y /) + p_FAST%VTK_Surface%NacelleBox(:,7) = (/ x, y, 2*y /) + p_FAST%VTK_Surface%NacelleBox(:,8) = (/ -x, y, 2*y /) + + !....................... + ! tapered tower + !....................... + + CALL AllocAry(p_FAST%VTK_Surface%TowerRad,ED%y%TowerLn2Mesh%NNodes,'VTK_Surface%TowerRad',ErrStat2,ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + topNode = ED%y%TowerLn2Mesh%NNodes - 1 + baseNode = ED%y%TowerLn2Mesh%refNode + TwrLength = TwoNorm( ED%y%TowerLn2Mesh%position(:,topNode) - ED%y%TowerLn2Mesh%position(:,baseNode) ) ! this is the assumed length of the tower + TwrRatio = TwrLength / 87.6_SiKi ! use ratio of the tower length to the length of the 5MW tower + TwrDiam_top = 3.87*TwrRatio + TwrDiam_base = 6.0*TwrRatio + + TwrRatio = 0.5 * (TwrDiam_top - TwrDiam_base) / TwrLength + do k=1,ED%y%TowerLn2Mesh%NNodes + TwrLength = TwoNorm( ED%y%TowerLn2Mesh%position(:,k) - ED%y%TowerLn2Mesh%position(:,baseNode) ) + p_FAST%VTK_Surface%TowerRad(k) = 0.5*TwrDiam_Base + TwrRatio*TwrLength + end do + + + + !....................... + ! blade surfaces + !....................... + allocate(p_FAST%VTK_Surface%BladeShape(NumBl),stat=ErrStat2) + if (errStat2/=0) then + call setErrStat(ErrID_Fatal,'Error allocating VTK_Surface%BladeShape.',ErrStat,ErrMsg,RoutineName) + return + end if + + IF ( p_FAST%CompAero == Module_AD ) THEN ! These meshes may have airfoil data associated with nodes... + + IF (ALLOCATED(InitOutData_AD%BladeShape)) THEN + do k=1,NumBl + call move_alloc( InitOutData_AD%BladeShape(k)%AirfoilCoords, p_FAST%VTK_Surface%BladeShape(k)%AirfoilCoords ) + end do + ELSE +#ifndef USE_DEFAULT_BLADE_SURFACE + call setErrStat(ErrID_Fatal,'Cannot do surface visualization without airfoil coordinates defined in AeroDyn.',ErrStat,ErrMsg,RoutineName) + return + END IF + ELSE + call setErrStat(ErrID_Fatal,'Cannot do surface visualization without using AeroDyn.',ErrStat,ErrMsg,RoutineName) + return + END IF +#else + ! AD used without airfoil coordinates specified + + rootNode = 1 + + DO K=1,NumBl + tipNode = AD%Input(1)%BladeMotion(K)%NNodes + cylNode = min(3,AD%Input(1)%BladeMotion(K)%Nnodes) + + call SetVTKDefaultBladeParams(AD%Input(1)%BladeMotion(K), p_FAST%VTK_Surface%BladeShape(K), tipNode, rootNode, cylNode, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + END DO + END IF + + ELSE IF ( p_FAST%CompElast == Module_BD ) THEN + rootNode = 1 + DO K=1,NumBl + tipNode = BD%y(k)%BldMotion%NNodes + cylNode = min(3,BD%y(k)%BldMotion%NNodes) + + call SetVTKDefaultBladeParams(BD%y(k)%BldMotion, p_FAST%VTK_Surface%BladeShape(K), tipNode, rootNode, cylNode, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + END DO + ELSE + DO K=1,NumBl + rootNode = ED%y%BladeLn2Mesh(K)%NNodes + tipNode = ED%y%BladeLn2Mesh(K)%NNodes-1 + cylNode = min(2,ED%y%BladeLn2Mesh(K)%NNodes) + + call SetVTKDefaultBladeParams(ED%y%BladeLn2Mesh(K), p_FAST%VTK_Surface%BladeShape(K), tipNode, rootNode, cylNode, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + END DO + END IF +#endif + + + !....................... + ! wave elevation + !....................... + + !bjj: interpolate here instead of each time step? + if ( allocated(InitOutData_HD%WaveElevSeries) ) then + call move_alloc( InitInData_HD%WaveElevXY, p_FAST%VTK_Surface%WaveElevXY ) + call move_alloc( InitOutData_HD%WaveElevSeries, p_FAST%VTK_Surface%WaveElev ) + + ! put the following lines in loops to avoid stack-size issues: + do k=1,size(p_FAST%VTK_Surface%WaveElevXY,2) + p_FAST%VTK_Surface%WaveElevXY(:,k) = p_FAST%VTK_Surface%WaveElevXY(:,k) + p_FAST%TurbinePos(1:2) + end do + + ! note that p_FAST%TurbinePos(3) must be 0 for offshore turbines + !do k=1,size(p_FAST%VTK_Surface%WaveElev,2) + ! p_FAST%VTK_Surface%WaveElev(:,k) = p_FAST%VTK_Surface%WaveElev(:,k) + p_FAST%TurbinePos(3) ! not sure this is really accurate if p_FAST%TurbinePos(3) is non-zero + !end do + + end if + + !....................... + ! morison surfaces + !....................... + + IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN + + call move_alloc(InitOutData_HD%Morison%Morison_Rad, p_FAST%VTK_Surface%MorisonRad) + + END IF + +END SUBROUTINE SetVTKParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine comes up with some default airfoils for blade surfaces for a given blade mesh, M. +SUBROUTINE SetVTKDefaultBladeParams(M, BladeShape, tipNode, rootNode, cylNode, ErrStat, ErrMsg) + + TYPE(MeshType), INTENT(IN ) :: M !< The Mesh the defaults should be calculated for + TYPE(FAST_VTK_BLSurfaceType), INTENT(INOUT) :: BladeShape !< BladeShape to set to default values + INTEGER(IntKi), INTENT(IN ) :: rootNode !< Index of root node (innermost node) for this mesh + INTEGER(IntKi), INTENT(IN ) :: tipNode !< Index of tip node (outermost node) for this mesh + INTEGER(IntKi), INTENT(IN ) :: cylNode !< Index of last node to have a cylinder shape + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + REAL(SiKi) :: bladeLength, chord, pitchAxis + REAL(SiKi) :: bladeLengthFract, bladeLengthFract2, ratio, posLength ! temporary quantities + REAL(SiKi) :: cylinderLength, x, y, angle + INTEGER(IntKi) :: i, j + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetVTKDefaultBladeParams' + + !Note: jmj does not like this default option + + integer, parameter :: N = 66 + + ! default airfoil shape coordinates; uses S809 values from http://wind.nrel.gov/airfoils/Shapes/S809_Shape.html: + real, parameter, dimension(N) :: xc=(/ 1.0,0.996203,0.98519,0.967844,0.945073,0.917488,0.885293,0.848455,0.80747,0.763042,0.715952,0.667064,0.617331,0.56783,0.519832,0.474243,0.428461,0.382612,0.33726,0.29297,0.250247,0.209576,0.171409,0.136174,0.104263,0.076035,0.051823,0.03191,0.01659,0.006026,0.000658,0.000204,0.0,0.000213,0.001045,0.001208,0.002398,0.009313,0.02323,0.04232,0.065877,0.093426,0.124111,0.157653,0.193738,0.231914,0.271438,0.311968,0.35337,0.395329,0.438273,0.48192,0.527928,0.576211,0.626092,0.676744,0.727211,0.776432,0.823285,0.86663,0.905365,0.938474,0.965086,0.984478,0.996141,1.0 /) + real, parameter, dimension(N) :: yc=(/ 0.0,0.000487,0.002373,0.00596,0.011024,0.017033,0.023458,0.03028,0.037766,0.045974,0.054872,0.064353,0.074214,0.084095,0.093268,0.099392,0.10176,0.10184,0.10007,0.096703,0.091908,0.085851,0.078687,0.07058,0.061697,0.052224,0.042352,0.032299,0.02229,0.012615,0.003723,0.001942,-0.00002,-0.001794,-0.003477,-0.003724,-0.005266,-0.011499,-0.020399,-0.030269,-0.040821,-0.051923,-0.063082,-0.07373,-0.083567,-0.092442,-0.099905,-0.105281,-0.108181,-0.108011,-0.104552,-0.097347,-0.086571,-0.073979,-0.060644,-0.047441,-0.0351,-0.024204,-0.015163,-0.008204,-0.003363,-0.000487,0.000743,0.000775,0.00029,0.0 /) + + call AllocAry(BladeShape%AirfoilCoords, 2, N, M%NNodes, 'BladeShape%AirfoilCoords', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ! Chord length and pitch axis location are given by scaling law + bladeLength = TwoNorm( M%position(:,tipNode) - M%Position(:,rootNode) ) + cylinderLength = TwoNorm( M%Position(:,cylNode) - M%Position(:,rootNode) ) + bladeLengthFract = 0.22*bladeLength + bladeLengthFract2 = bladeLength-bladeLengthFract != 0.78*bladeLength + + DO i=1,M%Nnodes + posLength = TwoNorm( M%Position(:,i) - M%Position(:,rootNode) ) + + IF (posLength .LE. bladeLengthFract) THEN + ratio = posLength/bladeLengthFract + chord = (0.06 + 0.02*ratio)*bladeLength + pitchAxis = 0.25 + 0.125*ratio + ELSE + chord = (0.08 - 0.06*(posLength-bladeLengthFract)/bladeLengthFract2)*bladeLength + pitchAxis = 0.375 + END IF + + IF (posLength .LE. cylinderLength) THEN + ! create a cylinder for this node + + chord = chord/2.0_SiKi + + DO j=1,N + ! normalized x,y coordinates for airfoil + x = yc(j) + y = xc(j) - 0.5 + + angle = ATAN2( y, x) + + ! x,y coordinates for cylinder + BladeShape%AirfoilCoords(1,j,i) = chord*COS(angle) ! x (note that "chord" is really representing chord/2 here) + BladeShape%AirfoilCoords(2,j,i) = chord*SIN(angle) ! y (note that "chord" is really representing chord/2 here) + END DO + + ELSE + ! create an airfoil for this node + + DO j=1,N + ! normalized x,y coordinates for airfoil, assuming an upwind turbine + x = yc(j) + y = xc(j) - pitchAxis + + ! x,y coordinates for airfoil + BladeShape%AirfoilCoords(1,j,i) = chord*x + BladeShape%AirfoilCoords(2,j,i) = chord*y + END DO + + END IF + + END DO ! nodes on mesh + +END SUBROUTINE SetVTKDefaultBladeParams +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes the ground or seabed reference surface information in VTK format. +!! see VTK file information format for XML, here: http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf +SUBROUTINE WrVTK_Ground ( RefPoint, HalfLengths, FileRootName, ErrStat, ErrMsg ) + + REAL(SiKi), INTENT(IN) :: RefPoint(3) !< reference point (plane will be created around it) + REAL(SiKi), INTENT(IN) :: HalfLengths(2) !< half of the X-Y lengths of plane surrounding RefPoint + CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in (excluding extension) + + 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) :: Un ! fortran unit number + INTEGER(IntKi) :: ix ! loop counters + CHARACTER(1024) :: FileName + INTEGER(IntKi), parameter :: NumberOfPoints = 4 + INTEGER(IntKi), parameter :: NumberOfLines = 0 + INTEGER(IntKi), parameter :: NumberOfPolys = 1 + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'WrVTK_Ground' + + ErrStat = ErrID_None + ErrMsg = "" + + !................................................................. + ! write the data that potentially changes each time step: + !................................................................. + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) file + FileName = TRIM(FileRootName)//'.vtp' + + call WrVTK_header( FileName, NumberOfPoints, NumberOfLines, NumberOfPolys, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + +! points (nodes, augmented with NumSegments): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + + WRITE(Un,VTK_AryFmt) RefPoint(1) + HalfLengths(1) , RefPoint(2) + HalfLengths(2), RefPoint(3) + WRITE(Un,VTK_AryFmt) RefPoint(1) + HalfLengths(1) , RefPoint(2) - HalfLengths(2), RefPoint(3) + WRITE(Un,VTK_AryFmt) RefPoint(1) - HalfLengths(1) , RefPoint(2) - HalfLengths(2), RefPoint(3) + WRITE(Un,VTK_AryFmt) RefPoint(1) - HalfLengths(1) , RefPoint(2) + HalfLengths(2), RefPoint(3) + + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + + + WRITE(Un,'(A)') ' <Polys>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + WRITE(Un,'('//trim(num2lstr(NumberOfPoints))//'(i7))') (ix, ix=0,NumberOfPoints-1) + WRITE(Un,'(A)') ' </DataArray>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + WRITE(Un,'(i7)') NumberOfPoints + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Polys>' + + call WrVTK_footer( Un ) + +END SUBROUTINE WrVTK_Ground +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets up the information needed to initialize AeroDyn, then initializes AeroDyn +SUBROUTINE AD_SetInitInput(InitInData_AD14, InitOutData_ED, y_ED, p_FAST, ErrStat, ErrMsg) + + ! Passed variables: + TYPE(AD14_InitInputType),INTENT(INOUT) :: InitInData_AD14 !< The initialization input to AeroDyn14 + TYPE(ED_InitOutputType), INTENT(IN) :: InitOutData_ED !< The initialization output from structural dynamics module + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs of the structural dynamics module (meshes with position/RefOrientation set) + TYPE(FAST_ParameterType),INTENT(IN) :: p_FAST !< The parameters of the glue code + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + + !TYPE(AD_InitOptions) :: ADOptions ! Options for AeroDyn + + INTEGER :: K + + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Set up the AeroDyn parameters + InitInData_AD14%ADFileName = p_FAST%AeroFile + InitInData_AD14%OutRootName = p_FAST%OutFileRoot + InitInData_AD14%WrSumFile = p_FAST%SumPrint + InitInData_AD14%NumBl = InitOutData_ED%NumBl + InitInData_AD14%UseDWM = p_FAST%UseDWM + + InitInData_AD14%DWM%IfW%InputFileName = p_FAST%InflowFile + + ! Hub position and orientation (relative here, but does not need to be) + + InitInData_AD14%TurbineComponents%Hub%Position(:) = y_ED%HubPtMotion14%Position(:,1) - y_ED%HubPtMotion14%Position(:,1) ! bjj: was 0; mesh was changed by adding p_ED%HubHt to 3rd component + InitInData_AD14%TurbineComponents%Hub%Orientation(:,:) = y_ED%HubPtMotion14%RefOrientation(:,:,1) + InitInData_AD14%TurbineComponents%Hub%TranslationVel = 0.0_ReKi ! bjj: we don't need this field + InitInData_AD14%TurbineComponents%Hub%RotationVel = 0.0_ReKi ! bjj: we don't need this field + + ! Blade root position and orientation (relative here, but does not need to be) + + IF (.NOT. ALLOCATED( InitInData_AD14%TurbineComponents%Blade ) ) THEN + ALLOCATE( InitInData_AD14%TurbineComponents%Blade( InitInData_AD14%NumBl ), STAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating space for InitInData_AD%TurbineComponents%Blade.' + RETURN + ELSE + ErrStat = ErrID_None !reset to ErrID_None, just in case ErrID_None /= 0 + END IF + END IF + + DO K=1, InitInData_AD14%NumBl + InitInData_AD14%TurbineComponents%Blade(K)%Position = y_ED%BladeRootMotion14%Position(:,K) + InitInData_AD14%TurbineComponents%Blade(K)%Orientation = y_ED%BladeRootMotion14%RefOrientation(:,:,K) + InitInData_AD14%TurbineComponents%Blade(K)%TranslationVel = 0.0_ReKi ! bjj: we don't need this field + InitInData_AD14%TurbineComponents%Blade(K)%RotationVel = 0.0_ReKi ! bjj: we don't need this field + END DO + + + ! Blade length + IF (p_FAST%CompElast == Module_ED) THEN ! note, we can't get here if we're using BeamDyn.... + InitInData_AD14%TurbineComponents%BladeLength = InitOutData_ED%BladeLength + END IF + + + ! Tower mesh ( here only because we currently need line2 meshes to contain the same nodes/elements ) + + InitInData_AD14%NumTwrNodes = y_ED%TowerLn2Mesh%NNodes - 2 + IF (.NOT. ALLOCATED( InitInData_AD14%TwrNodeLocs ) ) THEN + ALLOCATE( InitInData_AD14%TwrNodeLocs( 3, InitInData_AD14%NumTwrNodes ), STAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' Error allocating space for InitInData_AD%TwrNodeLocs.' + RETURN + ELSE + ErrStat = ErrID_None + END IF + END IF + + IF ( InitInData_AD14%NumTwrNodes > 0 ) THEN + InitInData_AD14%TwrNodeLocs = y_ED%TowerLn2Mesh%Position(:,1:InitInData_AD14%NumTwrNodes) ! ED has extra nodes at beginning and top and bottom of tower + END IF + + ! hub height + InitInData_AD14%HubHt = InitOutData_ED%HubHt + + + RETURN +END SUBROUTINE AD_SetInitInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine sets the number of subcycles (substeps) for modules at initialization, checking to make sure that their requested +!! time step is valid. +SUBROUTINE SetModuleSubstepTime(ModuleID, p_FAST, y_FAST, ErrStat, ErrMsg) + INTEGER(IntKi), INTENT(IN ) :: ModuleID !< ID of the module to check time step and set + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( EqualRealNos( p_FAST%dt_module( ModuleID ), p_FAST%dt ) ) THEN + p_FAST%n_substeps(ModuleID) = 1 + ELSE + IF ( p_FAST%dt_module( ModuleID ) > p_FAST%dt ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "The "//TRIM(y_FAST%Module_Ver(ModuleID)%Name)//" module time step ("//& + TRIM(Num2LStr(p_FAST%dt_module( ModuleID )))// & + " s) cannot be larger than FAST time step ("//TRIM(Num2LStr(p_FAST%dt))//" s)." + ELSE + ! calculate the number of subcycles: + p_FAST%n_substeps(ModuleID) = NINT( p_FAST%dt / p_FAST%dt_module( ModuleID ) ) + + ! let's make sure THE module DT is an exact integer divisor of the global (FAST) time step: + IF ( .NOT. EqualRealNos( p_FAST%dt, p_FAST%dt_module( ModuleID ) * p_FAST%n_substeps(ModuleID) ) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "The "//TRIM(y_FAST%Module_Ver(ModuleID)%Name)//" module time step ("//& + TRIM(Num2LStr(p_FAST%dt_module( ModuleID )))// & + " s) must be an integer divisor of the FAST time step ("//TRIM(Num2LStr(p_FAST%dt))//" s)." + END IF + + END IF + END IF + + RETURN + +END SUBROUTINE SetModuleSubstepTime +!---------------------------------------------------------------------------------------------------------------------------------- +!> This writes data to the FAST summary file. +SUBROUTINE FAST_WrSum( p_FAST, y_FAST, MeshMapData, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Glue-code simulation outputs (changes value of UnSum) + TYPE(FAST_ModuleMapType), INTENT(IN) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status (level) + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Message describing error reported in ErrStat + + ! local variables + REAL(ReKi) :: TmpRate ! temporary rate for vtk output + INTEGER(IntKi) :: I ! temporary counter + INTEGER(IntKi) :: J ! temporary counter + INTEGER(IntKi) :: Module_Number ! loop counter through the modules + CHARACTER(200) :: Fmt ! temporary format string + CHARACTER(200) :: DescStr ! temporary string to write text + CHARACTER(*), PARAMETER :: NotUsedTxt = " [not called]" ! text written if a module is not called + CHARACTER(ChanLen) :: ChanTxt(2) ! temp strings to help with formatting with unknown ChanLen size + + ! Get a unit number and open the file: + + CALL GetNewUnit( y_FAST%UnSum, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL OpenFOutFile ( y_FAST%UnSum, TRIM(p_FAST%OutFileRoot)//'.sum', ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Add some file information: + + !.......................... Module Versions ..................................................... + !bjj: modules in this list are ordered by the order they are specified in the FAST input file + + WRITE (y_FAST%UnSum,'(/A)') 'FAST Summary File' + WRITE (y_FAST%UnSum,'(/A)') TRIM( y_FAST%FileDescLines(1) ) + + WRITE (y_FAST%UnSum,'(2X,A)' ) 'compiled with' + Fmt = '(4x,A)' + WRITE (y_FAST%UnSum,Fmt) TRIM( GetNVD( NWTC_Ver ) ) + WRITE (y_FAST%UnSum,Fmt) TRIM( GetNVD( y_FAST%Module_Ver( Module_ED ) ) ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_BD ) ) + IF ( p_FAST%CompElast /= Module_BD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_IfW ) ) + IF ( p_FAST%CompInflow /= Module_IfW ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + ! I'm not going to write the openfoam module info to the summary file + !DescStr = GetNVD( y_FAST%Module_Ver( Module_OpFM ) ) + !IF ( p_FAST%CompInflow /= Module_OpFM ) DescStr = TRIM(DescStr)//NotUsedTxt + !WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_AD14 ) ) + IF ( p_FAST%CompAero /= Module_AD14 ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_AD ) ) + IF ( p_FAST%CompAero /= Module_AD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_SrvD ) ) + IF ( p_FAST%CompServo /= Module_SrvD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_HD ) ) + IF ( p_FAST%CompHydro /= Module_HD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_SD ) ) + IF ( p_FAST%CompSub /= Module_SD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_ExtPtfm ) ) + IF ( p_FAST%CompSub /= Module_ExtPtfm ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_MAP ) ) + IF ( p_FAST%CompMooring /= Module_MAP ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_FEAM ) ) + IF ( p_FAST%CompMooring /= Module_FEAM ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_MD ) ) + IF ( p_FAST%CompMooring /= Module_MD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_Orca ) ) + IF ( p_FAST%CompMooring /= Module_Orca ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_IceF ) ) + IF ( p_FAST%CompIce /= Module_IceF ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + DescStr = GetNVD( y_FAST%Module_Ver( Module_IceD ) ) + IF ( p_FAST%CompIce /= Module_IceD ) DescStr = TRIM(DescStr)//NotUsedTxt + WRITE (y_FAST%UnSum,Fmt) TRIM( DescStr ) + + + !.......................... Information from FAST input File ...................................... +! OTHER information we could print here: +! current working directory +! output file root name +! output file time step +! output file format (text/binary) +! coupling method + + SELECT CASE ( p_FAST%TurbineType ) + CASE ( Type_LandBased ) + DescStr = 'Modeling a land-based turbine' + CASE ( Type_Offshore_Fixed ) + DescStr = 'Modeling a fixed-bottom offshore turbine' + CASE ( Type_Offshore_Floating ) + DescStr = 'Modeling a floating offshore turbine' + CASE DEFAULT ! This should never happen + DescStr="" + END SELECT + WRITE(y_FAST%UnSum,'(//A)') TRIM(DescStr) + + WRITE (y_FAST%UnSum,'(A)' ) 'Description from the FAST input file: ' + WRITE (y_FAST%UnSum,'(2X,A)') TRIM(p_FAST%FTitle) + + !.......................... Requested Features ................................................... + + SELECT CASE ( p_FAST%InterpOrder ) + CASE (0) + DescStr = ' (nearest neighbor)' + CASE (1) + DescStr = ' (linear)' + CASE (2) + DescStr = ' (quadratic)' + CASE DEFAULT + DescStr = ' ( )' + END SELECT + + WRITE(y_FAST%UnSum,'(/A,I1,A)' ) 'Interpolation order for input/output time histories: ', p_FAST%InterpOrder, TRIM(DescStr) + WRITE(y_FAST%UnSum,'( A,I2)' ) 'Number of correction iterations: ', p_FAST%NumCrctn + + + !.......................... Information About Coupling ................................................... + + IF ( ALLOCATED( MeshMapData%Jacobian_Opt1 ) ) then ! we're using option 1 + + IF ( p_FAST%CompSub /= Module_None .OR. p_FAST%CompElast == Module_BD .OR. p_FAST%CompMooring == Module_Orca ) THEN ! SubDyn-BeamDyn-HydroDyn-ElastoDyn-ExtPtfm + DescStr = 'ElastoDyn, SubDyn, HydroDyn, OrcaFlex, ExtPtfm_MCKF, and/or BeamDyn' + ELSE ! IF ( p_FAST%CompHydro == Module_HD ) THEN + DescStr = "ElastoDyn to HydroDyn" + END IF + + WRITE(y_FAST%UnSum,'( A,I6)' ) 'Number of rows in Jacobian matrix used for coupling '//TRIM(DescStr)//': ', & + SIZE(MeshMapData%Jacobian_Opt1, 1) + END IF + + !.......................... Time step information: ................................................... + + WRITE (y_FAST%UnSum,'(//,2X,A)') " Requested Time Steps " + WRITE (y_FAST%UnSum, '(2X,A)') "-------------------------------------------------" + Fmt = '(2X,A17,2X,A15,2X,A13)' + WRITE (y_FAST%UnSum, Fmt ) "Component ", "Time Step (s) ", "Subcycles (-)" + WRITE (y_FAST%UnSum, Fmt ) "-----------------", "---------------", "-------------" + Fmt = '(2X,A17,2X,'//TRIM(p_FAST%OutFmt)//',:,T37,2X,I8,:,A)' + WRITE (y_FAST%UnSum, Fmt ) "FAST (glue code) ", p_FAST%DT + DO Module_Number=1,NumModules + IF (p_FAST%ModuleInitialized(Module_Number)) THEN + WRITE (y_FAST%UnSum, Fmt ) y_FAST%Module_Ver(Module_Number)%Name, p_FAST%DT_module(Module_Number), p_FAST%n_substeps(Module_Number) + END IF + END DO + IF ( p_FAST%n_DT_Out == 1_IntKi ) THEN + WRITE (y_FAST%UnSum, Fmt ) "FAST output files", p_FAST%DT_out, 1_IntKi ! we'll write "1" instead of "1^-1" + ELSE + WRITE (y_FAST%UnSum, Fmt ) "FAST output files", p_FAST%DT_out, p_FAST%n_DT_Out,"^-1" + END IF + + IF (p_FAST%WrVTK == VTK_Animate) THEN + + TmpRate = p_FAST%DT*p_FAST%n_VTKTime + + IF ( p_FAST%n_VTKTime == 1_IntKi ) THEN + WRITE (y_FAST%UnSum, Fmt ) "VTK output files ", p_FAST%DT, 1_IntKi ! we'll write "1" instead of "1^-1" + ELSE + WRITE (y_FAST%UnSum, Fmt ) "VTK output files ", TmpRate, p_FAST%n_VTKTime,"^-1" + END IF + ELSE + TmpRate = p_FAST%VTK_fps + END IF + + ! bjj: fix this; possibly add names of which files will be generated? + IF (p_FAST%WrVTK == VTK_Animate .or. p_FAST%WrVTK == VTK_ModeShapes) THEN + Fmt = '(2X,A17,2X,'//TRIM(p_FAST%OutFmt)//',:,T37,:,A)' + + WRITE (y_FAST%UnSum,'(//,2X,A)') " Requested Visualization Output" + WRITE (y_FAST%UnSum, '(2X,A)') "-------------------------------------------------" + WRITE (y_FAST%UnSum, Fmt ) "Frame rate", 1.0_DbKi/TmpRate, " fps" + END IF + + + !.......................... Requested Output Channels ............................................ + + WRITE (y_FAST%UnSum,'(//,2X,A)') " Requested Channels in FAST Output File(s) " + WRITE (y_FAST%UnSum, '(2X,A)') "--------------------------------------------" + Fmt = '(2X,A6,2(2X,A'//TRIM(num2lstr(ChanLen))//'),2X,A)' + ChanTxt(1) = 'Name' + ChanTxt(2) = 'Units' + WRITE (y_FAST%UnSum, Fmt ) "Number", ChanTxt, "Generated by" + ChanTxt = '--------------------' !this ought to be sufficiently long + WRITE (y_FAST%UnSum, Fmt ) "------", ChanTxt, "------------" + + Fmt = '(4X,I4,2(2X,A'//TRIM(num2lstr(ChanLen))//'),2X,A)' + I = 1 + WRITE (y_FAST%UnSum, Fmt ) I, y_FAST%ChannelNames(I), y_FAST%ChannelUnits(I), TRIM(FAST_Ver%Name) + + + DO Module_Number = 1,NumModules + DO J = 1,y_FAST%numOuts( Module_Number ) + I = I + 1 + WRITE (y_FAST%UnSum, Fmt ) I, y_FAST%ChannelNames(I), y_FAST%ChannelUnits(I), TRIM(y_FAST%Module_Ver( Module_Number )%Name) + END DO + END DO + + + !.......................... End of Summary File ............................................ + + ! bjj: note that I'm not closing the summary file here, though at the present time we don't write to this file again. + ! In the future, we may want to write additional information to this file during the simulation. + ! bjj 4/21/2015: closing the file now because of restart. If it needs to be open later, we can change it again. + + CLOSE( y_FAST%UnSum ) + y_FAST%UnSum = -1 + +END SUBROUTINE FAST_WrSum +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! TIME-STEP SOLVER ROUTINES (includes initialization after first call to calcOutput at t=0) +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine that calls FAST_Solution0 for one instance of a Turbine data structure. This is a separate subroutine so that the FAST +!! driver programs do not need to change or operate on the individual module level. +SUBROUTINE FAST_Solution0_T(Turbine, ErrStat, ErrMsg) + + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + CALL FAST_Solution0(Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg ) + +END SUBROUTINE FAST_Solution0_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calls CalcOutput for the first time of the simulation (at t=0). After the initial solve, data arrays are initialized. +SUBROUTINE FAST_Solution0(p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi), PARAMETER :: n_t_global = -1 ! loop counter + INTEGER(IntKi), PARAMETER :: n_t_global_next = 0 ! loop counter + REAL(DbKi) :: t_initial ! next simulation time (t_global_next) + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Solution0' + + + !NOTE: m_FAST%t_global is t_initial in this routine + + ErrStat = ErrID_None + ErrMsg = "" + + t_initial = m_FAST%t_global ! which is used in place of t_global_next + y_FAST%WriteThisStep = NeedWriteOutput(n_t_global_next, t_initial, p_FAST) + + IF (p_FAST%WrSttsTime) then + CALL SimStatus_FirstTime( m_FAST%TiLstPrn, m_FAST%PrevClockTime, m_FAST%SimStrtTime, m_FAST%UsrTime2, t_initial, p_FAST%TMax, p_FAST%TDesc ) + END IF + + + ! Solve input-output relations; this section of code corresponds to Eq. (35) in Gasmi et al. (2013) + ! This code will be specific to the underlying modules + + ! the initial ServoDyn and IfW/Lidar inputs from Simulink: + IF ( p_FAST%CompServo == Module_SrvD ) CALL SrvD_SetExternalInputs( p_FAST, m_FAST, SrvD%Input(1) ) + IF ( p_FAST%CompInflow == Module_IfW ) CALL IfW_SetExternalInputs( IfW%p, m_FAST, ED%y, IfW%Input(1) ) + + CALL CalcOutputs_And_SolveForInputs( n_t_global, t_initial, STATE_CURR, m_FAST%calcJacobian, m_FAST%NextJacCalcTime, & + p_FAST, m_FAST, y_FAST%WriteThisStep, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !---------------------------------------------------------------------------------------- + ! Check to see if we should output data this time step: + !---------------------------------------------------------------------------------------- + + CALL WriteOutputToFile(n_t_global_next, t_initial, p_FAST, y_FAST, ED, BD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! turn off VTK output when + if (p_FAST%WrVTK == VTK_InitOnly) then + ! Write visualization data for initialization (and also note that we're ignoring any errors that occur doing so) + + call WriteVTK(t_initial, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + + end if + + + !............... + ! Copy values of these initial guesses for interpolation/extrapolation and + ! initialize predicted states for j_pc loop (use MESH_NEWCOPY here so we can use MESH_UPDATE copy later) + !............... + + ! Initialize Input-Output arrays for interpolation/extrapolation: + + CALL FAST_InitIOarrays( m_FAST%t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + +END SUBROUTINE FAST_Solution0 +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine initializes the input and output arrays stored for extrapolation. They are initialized after the first input-output solve so that the first +!! extrapolations are used with values from the solution, not just initial guesses. It also creates new copies of the state variables, which need to +!! be stored for the predictor-corrector loop. +SUBROUTINE FAST_InitIOarrays( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< start time of the simulation + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn v14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + 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, j, k ! loop counters + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_InitIOarrays' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! We fill ED%InputTimes with negative times, but the ED%Input values are identical for each of those times; this allows + ! us to use, e.g., quadratic interpolation that effectively acts as a zeroth-order extrapolation and first-order extrapolation + ! for the first and second time steps. (The interpolation order in the ExtrapInput routines are determined as + ! order = SIZE(ED%Input) + + + DO j = 1, p_FAST%InterpOrder + 1 + ED%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !ED_OutputTimes(j) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL ED_CopyInput (ED%Input(1), ED%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL ED_CopyInput (ED%Input(1), ED%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL ED_CopyContState (ED%x( STATE_CURR), ED%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyDiscState (ED%xd(STATE_CURR), ED%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyConstrState (ED%z( STATE_CURR), ED%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOtherState (ED%OtherSt( STATE_CURR), ED%OtherSt( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + IF (p_FAST%CompElast == Module_BD ) THEN + + DO k = 1,p_FAST%nBeams + + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + BD%InputTimes(j,k) = t_initial - (j - 1) * p_FAST%dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL BD_CopyInput (BD%Input(1,k), BD%Input(j,k), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL BD_CopyInput (BD%Input(1,k), BD%u(k), MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL BD_CopyContState (BD%x( k,STATE_CURR), BD%x( k,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyDiscState (BD%xd(k,STATE_CURR), BD%xd(k,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyConstrState (BD%z( k,STATE_CURR), BD%z( k,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyOtherState (BD%OtherSt( k,STATE_CURR), BD%OtherSt( k,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO ! nBeams + + END IF ! CompElast + + + IF ( p_FAST%CompServo == Module_SrvD ) THEN + ! Initialize Input-Output arrays for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + SrvD%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !SrvD_OutputTimes(j) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL SrvD_CopyInput (SrvD%Input(1), SrvD%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL SrvD_CopyInput (SrvD%Input(1), SrvD%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL SrvD_CopyContState (SrvD%x( STATE_CURR), SrvD%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyDiscState (SrvD%xd(STATE_CURR), SrvD%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyConstrState (SrvD%z( STATE_CURR), SrvD%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyOtherState( SrvD%OtherSt(STATE_CURR), SrvD%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF ! CompServo + + + IF ( p_FAST%CompAero == Module_AD14 ) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + AD14%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL AD14_CopyInput (AD14%Input(1), AD14%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL AD14_CopyInput (AD14%Input(1), AD14%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL AD14_CopyContState (AD14%x( STATE_CURR), AD14%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyDiscState (AD14%xd(STATE_CURR), AD14%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyConstrState (AD14%z( STATE_CURR), AD14%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyOtherState( AD14%OtherSt(STATE_CURR), AD14%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + AD%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL AD_CopyInput (AD%Input(1), AD%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL AD_CopyInput (AD%Input(1), AD%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL AD_CopyContState(AD%x(STATE_CURR), AD%x(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyDiscState(AD%xd(STATE_CURR), AD%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyConstrState(AD%z(STATE_CURR), AD%z(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyOtherState(AD%OtherSt(STATE_CURR), AD%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF ! CompAero == Module_AD + + + + IF ( p_FAST%CompInflow == Module_IfW ) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + IfW%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !IfW%OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL InflowWind_CopyInput (IfW%Input(1), IfW%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL InflowWind_CopyInput (IfW%Input(1), IfW%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL InflowWind_CopyContState (IfW%x( STATE_CURR), IfW%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyDiscState (IfW%xd(STATE_CURR), IfW%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyConstrState (IfW%z( STATE_CURR), IfW%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyOtherState( IfW%OtherSt(STATE_CURR), IfW%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF ! CompInflow == Module_IfW + + + IF ( p_FAST%CompHydro == Module_HD ) THEN + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + HD%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !HD_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL HydroDyn_CopyInput (HD%Input(1), HD%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL HydroDyn_CopyInput (HD%Input(1), HD%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL HydroDyn_CopyContState (HD%x( STATE_CURR), HD%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyDiscState (HD%xd(STATE_CURR), HD%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyConstrState (HD%z( STATE_CURR), HD%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOtherState( HD%OtherSt(STATE_CURR), HD%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF !CompHydro + + + IF (p_FAST%CompSub == Module_SD ) THEN + + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + SD%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !SD_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL SD_CopyInput (SD%Input(1), SD%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL SD_CopyInput (SD%Input(1), SD%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL SD_CopyContState (SD%x( STATE_CURR), SD%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyDiscState (SD%xd(STATE_CURR), SD%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyConstrState (SD%z( STATE_CURR), SD%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOtherState( SD%OtherSt(STATE_CURR), SD%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSE IF (p_FAST%CompSub == Module_ExtPtfm ) THEN + + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + ExtPtfm%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL ExtPtfm_CopyInput (ExtPtfm%Input(1), ExtPtfm%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL ExtPtfm_CopyInput (ExtPtfm%Input(1), ExtPtfm%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL ExtPtfm_CopyContState (ExtPtfm%x( STATE_CURR), ExtPtfm%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyDiscState (ExtPtfm%xd(STATE_CURR), ExtPtfm%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyConstrState (ExtPtfm%z( STATE_CURR), ExtPtfm%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOtherState( ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF ! CompSub + + + IF (p_FAST%CompMooring == Module_MAP) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + MAPp%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !MAP_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL MAP_CopyInput (MAPp%Input(1), MAPp%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL MAP_CopyInput (MAPp%Input(1), MAPp%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL MAP_CopyContState (MAPp%x( STATE_CURR), MAPp%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyDiscState (MAPp%xd(STATE_CURR), MAPp%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyConstrState (MAPp%z( STATE_CURR), MAPp%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( p_FAST%n_substeps( MODULE_MAP ) > 1 ) THEN + CALL MAP_CopyOtherState( MAPp%OtherSt, MAPp%OtherSt_old, MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + MD%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !MD_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL MD_CopyInput (MD%Input(1), MD%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL MD_CopyInput (MD%Input(1), MD%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL MD_CopyContState (MD%x( STATE_CURR), MD%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyDiscState (MD%xd(STATE_CURR), MD%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyConstrState (MD%z( STATE_CURR), MD%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyOtherState( MD%OtherSt(STATE_CURR), MD%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + FEAM%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !FEAM_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL FEAM_CopyInput (FEAM%Input(1), FEAM%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL FEAM_CopyInput (FEAM%Input(1), FEAM%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL FEAM_CopyContState (FEAM%x( STATE_CURR), FEAM%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyDiscState (FEAM%xd(STATE_CURR), FEAM%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyConstrState (FEAM%z( STATE_CURR), FEAM%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyOtherState( FEAM%OtherSt(STATE_CURR), FEAM%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + ! Copy values for interpolation/extrapolation: + + DO j = 1, p_FAST%InterpOrder + 1 + Orca%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL Orca_CopyInput (Orca%Input(1), Orca%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL Orca_CopyInput (Orca%Input(1), Orca%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Initialize predicted states for j_pc loop: + CALL Orca_CopyContState (Orca%x( STATE_CURR), Orca%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyDiscState (Orca%xd(STATE_CURR), Orca%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyConstrState (Orca%z( STATE_CURR), Orca%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyOtherState( Orca%OtherSt(STATE_CURR), Orca%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF ! CompMooring + + + IF (p_FAST%CompIce == Module_IceF ) THEN + + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + IceF%InputTimes(j) = t_initial - (j - 1) * p_FAST%dt + !IceF_OutputTimes(i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL IceFloe_CopyInput (IceF%Input(1), IceF%Input(j), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL IceFloe_CopyInput (IceF%Input(1), IceF%u, MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL IceFloe_CopyContState (IceF%x( STATE_CURR), IceF%x( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyDiscState (IceF%xd(STATE_CURR), IceF%xd(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyConstrState (IceF%z( STATE_CURR), IceF%z( STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyOtherState( IceF%OtherSt(STATE_CURR), IceF%OtherSt(STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ELSEIF (p_FAST%CompIce == Module_IceD ) THEN + + DO i = 1,p_FAST%numIceLegs + + ! Copy values for interpolation/extrapolation: + DO j = 1, p_FAST%InterpOrder + 1 + IceD%InputTimes(j,i) = t_initial - (j - 1) * p_FAST%dt + !IceD%OutputTimes(j,i) = t_initial - (j - 1) * dt + END DO + + DO j = 2, p_FAST%InterpOrder + 1 + CALL IceD_CopyInput (IceD%Input(1,i), IceD%Input(j,i), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + CALL IceD_CopyInput (IceD%Input(1,i), IceD%u(i), MESH_NEWCOPY, Errstat2, ErrMsg2) ! do this to initialize meshes/allocatable arrays for output of ExtrapInterp routine + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Initialize predicted states for j_pc loop: + CALL IceD_CopyContState (IceD%x( i,STATE_CURR), IceD%x( i,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyDiscState (IceD%xd(i,STATE_CURR), IceD%xd(i,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyConstrState (IceD%z( i,STATE_CURR), IceD%z( i,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyOtherState( IceD%OtherSt(i,STATE_CURR), IceD%OtherSt(i,STATE_PRED), MESH_NEWCOPY, Errstat2, ErrMsg2) + CALL SetErrStat( Errstat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO ! numIceLegs + + END IF ! CompIce + + +END SUBROUTINE FAST_InitIOarrays +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calls FAST_Solution for one instance of a Turbine data structure. This is a separate subroutine so that the FAST +!! driver programs do not need to change or operate on the individual module level. +SUBROUTINE FAST_Solution_T(t_initial, n_t_global, Turbine, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< loop counter + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + CALL FAST_Solution(t_initial, n_t_global, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg ) + +END SUBROUTINE FAST_Solution_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine takes data from n_t_global and gets values at n_t_global + 1 +SUBROUTINE FAST_Solution(t_initial, n_t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< loop counter + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: t_global_next ! next simulation time (m_FAST%t_global + p_FAST%dt) + INTEGER(IntKi) :: n_t_global_next ! n_t_global + 1 + INTEGER(IntKi) :: j_pc ! predictor-corrector loop counter + INTEGER(IntKi) :: NumCorrections ! number of corrections for this time step + INTEGER(IntKi), parameter :: MaxCorrections = 20 ! maximum number of corrections allowed + LOGICAL :: WriteThisStep ! Whether WriteOutput values will be printed + + INTEGER(IntKi) :: I, k ! generic loop counters + + !REAL(ReKi) :: ControlInputGuess ! value of controller inputs + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Solution' + + + ErrStat = ErrID_None + ErrMsg = "" + + n_t_global_next = n_t_global+1 + t_global_next = t_initial + n_t_global_next*p_FAST%DT ! = m_FAST%t_global + p_FAST%dt + + y_FAST%WriteThisStep = NeedWriteOutput(n_t_global_next, t_global_next, p_FAST) + + !! determine if the Jacobian should be calculated this time + IF ( m_FAST%calcJacobian ) THEN ! this was true (possibly at initialization), so we'll advance the time for the next calculation of the Jacobian + + if (p_FAST%CompMooring == Module_Orca .and. n_t_global < 5) then + m_FAST%NextJacCalcTime = m_FAST%t_global + p_FAST%DT ! the jacobian calculated with OrcaFlex at t=0 is incorrect, but is okay on the 2nd step (it's not okay for OrcaFlex version 10, so I increased this to 5) + else + m_FAST%NextJacCalcTime = m_FAST%t_global + p_FAST%DT_UJac + end if + + END IF + + ! set number of corrections to be used for this time step: + IF ( p_FAST%CompElast == Module_BD ) THEN ! BD accelerations have fewer spikes with these corrections on the first several time steps + if (n_t_global > 2) then ! this 2 should probably be related to p_FAST%InterpOrder + NumCorrections = p_FAST%NumCrctn + elseif (n_t_global == 0) then + NumCorrections = max(p_FAST%NumCrctn,16) + else + NumCorrections = max(p_FAST%NumCrctn,1) + end if + ELSE + NumCorrections = p_FAST%NumCrctn + END IF + + ! the ServoDyn inputs from Simulink are for t, not t+dt, so we're going to overwrite the inputs from + ! the previous step before we extrapolate these inputs: + IF ( p_FAST%CompServo == Module_SrvD ) CALL SrvD_SetExternalInputs( p_FAST, m_FAST, SrvD%Input(1) ) + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! ## Step 1.a: Extrapolate Inputs + !! + !! gives predicted values at t+dt + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + CALL FAST_ExtrapInterpMods( t_global_next, p_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + !! predictor-corrector loop: + j_pc = 0 + do while (j_pc <= NumCorrections) + WriteThisStep = y_FAST%WriteThisStep .AND. j_pc==NumCorrections + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! ## Step 1.b: Advance states (yield state and constraint values at t_global_next) + !! + !! STATE_CURR values of x, xd, z, and OtherSt contain values at m_FAST%t_global; + !! STATE_PRED values contain values at t_global_next. + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + CALL FAST_AdvanceStates( t_initial, n_t_global, p_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! ## Step 1.c: Input-Output Solve + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ! save predicted inputs for comparison with corrected value later + !IF (p_FAST%CheckHSSBrTrqC) THEN + ! ControlInputGuess = ED%Input(1)%HSSBrTrqC + !END IF + + CALL CalcOutputs_And_SolveForInputs( n_t_global, t_global_next, STATE_PRED, m_FAST%calcJacobian, m_FAST%NextJacCalcTime, & + p_FAST, m_FAST, WriteThisStep, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! ## Step 2: Correct (continue in loop) + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + j_pc = j_pc + 1 + + ! ! Check if the predicted inputs were significantly different than the corrected inputs + ! ! (values before and after CalcOutputs_And_SolveForInputs) + !if (j_pc > NumCorrections) then + ! + ! !if (p_FAST%CheckHSSBrTrqC) then + ! ! if ( abs(ControlInputGuess - ED%Input(1)%HSSBrTrqC) > 50.0_ReKi ) then ! I randomly picked 50 N-m + ! ! NumCorrections = min(p_FAST%NumCrctn + 1, MaxCorrections) + ! ! ! print *, 'correction:', t_global_next, NumCorrections + ! ! cycle + ! ! end if + ! !end if + ! + ! ! check pitch position input to structural code (not implemented, yet) + !end if + + enddo ! j_pc + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! ## Step 3: Save all final variables (advance to next time) + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + !---------------------------------------------------------------------------------------- + !! copy the final predicted states from step t_global_next to actual states for that step + !---------------------------------------------------------------------------------------- + + ! ElastoDyn: copy final predictions to actual states + CALL ED_CopyContState (ED%x( STATE_PRED), ED%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyDiscState (ED%xd(STATE_PRED), ED%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyConstrState (ED%z( STATE_PRED), ED%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ED_CopyOtherState (ED%OtherSt( STATE_PRED), ED%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! BeamDyn: copy final predictions to actual states + IF ( p_FAST%CompElast == Module_BD ) THEN + DO k=1,p_FAST%nBeams + CALL BD_CopyContState (BD%x( k,STATE_PRED), BD%x( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyDiscState (BD%xd(k,STATE_PRED), BD%xd(k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyConstrState (BD%z( k,STATE_PRED), BD%z( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL BD_CopyOtherState (BD%OtherSt( k,STATE_PRED), BD%OtherSt( k,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + END IF + + + ! AeroDyn: copy final predictions to actual states; copy current outputs to next + IF ( p_FAST%CompAero == Module_AD14 ) THEN + CALL AD14_CopyContState (AD14%x( STATE_PRED), AD14%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyDiscState (AD14%xd(STATE_PRED), AD14%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyConstrState (AD14%z( STATE_PRED), AD14%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD14_CopyOtherState (AD14%OtherSt(STATE_PRED), AD14%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN + CALL AD_CopyContState (AD%x( STATE_PRED), AD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyDiscState (AD%xd(STATE_PRED), AD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyConstrState (AD%z( STATE_PRED), AD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AD_CopyOtherState (AD%OtherSt(STATE_PRED), AD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! InflowWind: copy final predictions to actual states; copy current outputs to next + IF ( p_FAST%CompInflow == Module_IfW ) THEN + CALL InflowWind_CopyContState (IfW%x( STATE_PRED), IfW%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyDiscState (IfW%xd(STATE_PRED), IfW%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyConstrState (IfW%z( STATE_PRED), IfW%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL InflowWind_CopyOtherState (IfW%OtherSt( STATE_PRED), IfW%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! ServoDyn: copy final predictions to actual states; copy current outputs to next + IF ( p_FAST%CompServo == Module_SrvD ) THEN + CALL SrvD_CopyContState (SrvD%x( STATE_PRED), SrvD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyDiscState (SrvD%xd(STATE_PRED), SrvD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyConstrState (SrvD%z( STATE_PRED), SrvD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SrvD_CopyOtherState (SrvD%OtherSt( STATE_PRED), SrvD%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! HydroDyn: copy final predictions to actual states + IF ( p_FAST%CompHydro == Module_HD ) THEN + CALL HydroDyn_CopyContState (HD%x( STATE_PRED), HD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyDiscState (HD%xd(STATE_PRED), HD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyConstrState (HD%z( STATE_PRED), HD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL HydroDyn_CopyOtherState (HD%OtherSt(STATE_PRED), HD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! SubDyn: copy final predictions to actual states + IF ( p_FAST%CompSub == Module_SD ) THEN + CALL SD_CopyContState (SD%x( STATE_PRED), SD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyDiscState (SD%xd(STATE_PRED), SD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyConstrState (SD%z( STATE_PRED), SD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL SD_CopyOtherState (SD%OtherSt(STATE_PRED), SD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + CALL ExtPtfm_CopyContState (ExtPtfm%x( STATE_PRED), ExtPtfm%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyDiscState (ExtPtfm%xd(STATE_PRED), ExtPtfm%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyConstrState (ExtPtfm%z( STATE_PRED), ExtPtfm%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL ExtPtfm_CopyOtherState (ExtPtfm%OtherSt(STATE_PRED), ExtPtfm%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! MAP: copy final predictions to actual states + IF (p_FAST%CompMooring == Module_MAP) THEN + CALL MAP_CopyContState (MAPp%x( STATE_PRED), MAPp%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyDiscState (MAPp%xd(STATE_PRED), MAPp%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MAP_CopyConstrState (MAPp%z( STATE_PRED), MAPp%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !CALL MAP_CopyOtherState (MAPp%OtherSt(STATE_PRED), MAPp%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + ! CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_MD) THEN + CALL MD_CopyContState (MD%x( STATE_PRED), MD%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyDiscState (MD%xd(STATE_PRED), MD%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyConstrState (MD%z( STATE_PRED), MD%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL MD_CopyOtherState (MD%OtherSt(STATE_PRED), MD%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN + CALL FEAM_CopyContState (FEAM%x( STATE_PRED), FEAM%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyDiscState (FEAM%xd(STATE_PRED), FEAM%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyConstrState (FEAM%z( STATE_PRED), FEAM%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL FEAM_CopyOtherState (FEAM%OtherSt( STATE_PRED), FEAM%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF (p_FAST%CompMooring == Module_Orca) THEN + CALL Orca_CopyContState (Orca%x( STATE_PRED), Orca%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyDiscState (Orca%xd(STATE_PRED), Orca%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyConstrState (Orca%z( STATE_PRED), Orca%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL Orca_CopyOtherState (Orca%OtherSt( STATE_PRED), Orca%OtherSt( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ! IceFloe: copy final predictions to actual states + IF ( p_FAST%CompIce == Module_IceF ) THEN + CALL IceFloe_CopyContState (IceF%x( STATE_PRED), IceF%x( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyDiscState (IceF%xd(STATE_PRED), IceF%xd(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyConstrState (IceF%z( STATE_PRED), IceF%z( STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceFloe_CopyOtherState (IceF%OtherSt(STATE_PRED), IceF%OtherSt(STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + DO i=1,p_FAST%numIceLegs + CALL IceD_CopyContState (IceD%x( i,STATE_PRED), IceD%x( i,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyDiscState (IceD%xd(i,STATE_PRED), IceD%xd(i,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyConstrState (IceD%z( i,STATE_PRED), IceD%z( i,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL IceD_CopyOtherState (IceD%OtherSt( i,STATE_PRED), IceD%OtherSt( i,STATE_CURR), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + END IF + + + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + !! We've advanced everything to the next time step: + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + !! update the global time + + m_FAST%t_global = t_global_next + + + !---------------------------------------------------------------------------------------- + !! Check to see if we should output data this time step: + !---------------------------------------------------------------------------------------- + + CALL WriteOutputToFile(n_t_global_next, t_global_next, p_FAST, y_FAST, ED, BD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + SrvD, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !---------------------------------------------------------------------------------------- + !! Display simulation status every SttsTime-seconds (i.e., n_SttsTime steps): + !---------------------------------------------------------------------------------------- + + IF (p_FAST%WrSttsTime) then + IF ( MOD( n_t_global_next, p_FAST%n_SttsTime ) == 0 ) THEN + CALL SimStatus( m_FAST%TiLstPrn, m_FAST%PrevClockTime, m_FAST%t_global, p_FAST%TMax, p_FAST%TDesc ) + + ENDIF + ENDIF + +END SUBROUTINE FAST_Solution +!---------------------------------------------------------------------------------------------------------------------------------- +! ROUTINES TO OUTPUT WRITE DATA TO FILE AT EACH REQUSTED TIME STEP +!---------------------------------------------------------------------------------------------------------------------------------- +FUNCTION NeedWriteOutput(n_t_global, t_global, p_FAST) + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< Current global time step + REAL(DbKi), INTENT(IN ) :: t_global !< Current global time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + + LOGICAL :: NeedWriteOutput !< Function result; if true, WriteOutput values are needed on this time step + + IF ( t_global >= p_FAST%TStart ) THEN ! note that if TStart isn't an multiple of DT_out, we will not necessarially start output to the file at TStart + NeedWriteOutput = MOD( n_t_global, p_FAST%n_DT_Out ) == 0 + ELSE + NeedWriteOutput = .FALSE. + END IF + +END FUNCTION NeedWriteOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine determines if it's time to write to the output files--based on a previous call to fast_subs::needwriteoutput--, and +!! calls the routine to write to the files with the output data. It should be called after all the output solves for a given time +!! have been completed, and assumes y_FAST\%WriteThisStep has been set. +SUBROUTINE WriteOutputToFile(n_t_global, t_global, p_FAST, y_FAST, ED, BD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + SrvD, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg) +!............................................................................................................................... + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< Current global time step + REAL(DbKi), INTENT(IN ) :: t_global !< Current global time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(IN ) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(IN ) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(IN ) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(IN ) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(IN ) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(IN ) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(IN ) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(IN ) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(IN ) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(IN ) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(IN ) :: MeshMapData !< Data for mapping between modules + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + CHARACTER(*), PARAMETER :: RoutineName = 'WriteOutputToFile' + + ErrStat = ErrID_None + ErrMsg = "" + + ! Write time-series channel data + + !y_FAST%WriteThisStep = NeedWriteOutput(n_t_global, t_global, p_FAST) + IF ( y_FAST%WriteThisStep ) THEN + + ! Generate glue-code output file + + CALL WrOutputLine( t_global, p_FAST, y_FAST, IfW%y%WriteOutput, OpFM%y%WriteOutput, ED%y%WriteOutput, & + AD%y%WriteOutput, SrvD%y%WriteOutput, HD%y%WriteOutput, SD%y%WriteOutput, ExtPtfm%y%WriteOutput, MAPp%y%WriteOutput, & + FEAM%y%WriteOutput, MD%y%WriteOutput, Orca%y%WriteOutput, IceF%y%WriteOutput, IceD%y, BD%y, ErrStat, ErrMsg ) + + ENDIF + + ! Write visualization data (and also note that we're ignoring any errors that occur doing so) + IF ( p_FAST%WrVTK == VTK_Animate ) THEN + IF ( MOD( n_t_global, p_FAST%n_VTKTime ) == 0 ) THEN + call WriteVTK(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + END IF + END IF + + +END SUBROUTINE WriteOutputToFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes the module output to the primary output file(s). +SUBROUTINE WrOutputLine( t, p_FAST, y_FAST, IfWOutput, OpFMOutput, EDOutput, ADOutput, SrvDOutput, HDOutput, SDOutput, ExtPtfmOutput,& + MAPOutput, FEAMOutput, MDOutput, OrcaOutput, IceFOutput, y_IceD, y_BD, ErrStat, ErrMsg) + + IMPLICIT NONE + + ! Passed variables + REAL(DbKi), INTENT(IN) :: t !< Current simulation time, in seconds + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Glue-code simulation outputs + + + REAL(ReKi), INTENT(IN) :: IfWOutput (:) !< InflowWind WriteOutput values + REAL(ReKi), INTENT(IN) :: OpFMOutput (:) !< OpenFOAM WriteOutput values + REAL(ReKi), INTENT(IN) :: EDOutput (:) !< ElastoDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: ADOutput (:) !< AeroDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: SrvDOutput (:) !< ServoDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: HDOutput (:) !< HydroDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: SDOutput (:) !< SubDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: ExtPtfmOutput (:) !< ExtPtfm_MCKF WriteOutput values + REAL(ReKi), INTENT(IN) :: MAPOutput (:) !< MAP WriteOutput values + REAL(ReKi), INTENT(IN) :: FEAMOutput (:) !< FEAMooring WriteOutput values + REAL(ReKi), INTENT(IN) :: MDOutput (:) !< MoorDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: OrcaOutput (:) !< OrcaFlex interface WriteOutput values + REAL(ReKi), INTENT(IN) :: IceFOutput (:) !< IceFloe WriteOutput values + TYPE(IceD_OutputType), INTENT(IN) :: y_IceD (:) !< IceDyn outputs (WriteOutput values are subset) + TYPE(BD_OutputType), INTENT(IN) :: y_BD (:) !< BeamDyn outputs (WriteOutput values are subset) + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + ! Local variables. + + CHARACTER(200) :: Frmt ! A string to hold a format specifier + CHARACTER(p_FAST%TChanLen) :: TmpStr ! temporary string to print the time output as text + + REAL(ReKi) :: OutputAry(SIZE(y_FAST%ChannelNames)-1) + + ErrStat = ErrID_None + ErrMsg = '' + + CALL FillOutputAry(p_FAST, y_FAST, IfWOutput, OpFMOutput, EDOutput, ADOutput, SrvDOutput, HDOutput, SDOutput, ExtPtfmOutput, & + MAPOutput, FEAMOutput, MDOutput, OrcaOutput, IceFOutput, y_IceD, y_BD, OutputAry) + + IF (p_FAST%WrTxtOutFile) THEN + + ! Write one line of tabular output: + ! Frmt = '(F8.3,'//TRIM(Num2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' + Frmt = '"'//p_FAST%Delim//'"'//p_FAST%OutFmt ! format for array elements from individual modules + + ! time + WRITE( TmpStr, '('//trim(p_FAST%OutFmt_t)//')' ) t + CALL WrFileNR( y_FAST%UnOu, TmpStr ) + + ! write the individual module output (convert to SiKi if necessary, so that we don't need to print so many digits in the exponent) + CALL WrNumAryFileNR ( y_FAST%UnOu, REAL(OutputAry,SiKi), Frmt, ErrStat, ErrMsg ) + !IF ( ErrStat >= AbortErrLev ) RETURN + + ! write a new line (advance to the next line) + WRITE (y_FAST%UnOu,'()') + + END IF + + + IF (p_FAST%WrBinOutFile) THEN + + ! Write data to array for binary output file + + IF ( y_FAST%n_Out == y_FAST%NOutSteps ) THEN + ErrStat = ErrID_Warn + ErrMsg = 'Not all data could be written to the binary output file.' + !CALL ProgWarn( 'Not all data could be written to the binary output file.' ) + !this really would only happen if we have an error somewhere else, right? + !otherwise, we could allocate a new, larger array and move existing data + ELSE + y_FAST%n_Out = y_FAST%n_Out + 1 + + ! store time data + IF ( y_FAST%n_Out == 1_IntKi .OR. p_FAST%WrBinMod == FileFmtID_WithTime ) THEN + y_FAST%TimeData(y_FAST%n_Out) = t ! Time associated with these outputs + END IF + + ! store individual module data + y_FAST%AllOutData(:, y_FAST%n_Out) = OutputAry + + END IF + + END IF + + RETURN +END SUBROUTINE WrOutputLine +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calls FillOutputAry for one instance of a Turbine data structure. This is a separate subroutine so that the FAST +!! driver programs do not need to change or operate on the individual module level. (Called from Simulink interface.) +SUBROUTINE FillOutputAry_T(Turbine, Outputs) + + TYPE(FAST_TurbineType), INTENT(IN ) :: Turbine !< all data for one instance of a turbine + REAL(ReKi), INTENT( OUT) :: Outputs(:) !< single array of output + + + CALL FillOutputAry(Turbine%p_FAST, Turbine%y_FAST, Turbine%IfW%y%WriteOutput, Turbine%OpFM%y%WriteOutput, & + Turbine%ED%y%WriteOutput, Turbine%AD%y%WriteOutput, Turbine%SrvD%y%WriteOutput, & + Turbine%HD%y%WriteOutput, Turbine%SD%y%WriteOutput, Turbine%ExtPtfm%y%WriteOutput, Turbine%MAP%y%WriteOutput, & + Turbine%FEAM%y%WriteOutput, Turbine%MD%y%WriteOutput, Turbine%Orca%y%WriteOutput, & + Turbine%IceF%y%WriteOutput, Turbine%IceD%y, Turbine%BD%y, Outputs) + +END SUBROUTINE FillOutputAry_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine concatenates all of the WriteOutput values from the module Output into one array to be written to the FAST +!! output file. +SUBROUTINE FillOutputAry(p_FAST, y_FAST, IfWOutput, OpFMOutput, EDOutput, ADOutput, SrvDOutput, HDOutput, SDOutput, ExtPtfmOutput, & + MAPOutput, FEAMOutput, MDOutput, OrcaOutput, IceFOutput, y_IceD, y_BD, OutputAry) + + TYPE(FAST_ParameterType), INTENT(IN) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType),INTENT(IN) :: y_FAST !< Glue-code simulation outputs + + REAL(ReKi), INTENT(IN) :: IfWOutput (:) !< InflowWind WriteOutput values + REAL(ReKi), INTENT(IN) :: OpFMOutput (:) !< OpenFOAM WriteOutput values + REAL(ReKi), INTENT(IN) :: EDOutput (:) !< ElastoDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: ADOutput (:) !< AeroDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: SrvDOutput (:) !< ServoDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: HDOutput (:) !< HydroDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: SDOutput (:) !< SubDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: ExtPtfmOutput (:) !< ExtPtfm_MCKF WriteOutput values + REAL(ReKi), INTENT(IN) :: MAPOutput (:) !< MAP WriteOutput values + REAL(ReKi), INTENT(IN) :: FEAMOutput (:) !< FEAMooring WriteOutput values + REAL(ReKi), INTENT(IN) :: MDOutput (:) !< MoorDyn WriteOutput values + REAL(ReKi), INTENT(IN) :: OrcaOutput (:) !< OrcaFlex interface WriteOutput values + REAL(ReKi), INTENT(IN) :: IceFOutput (:) !< IceFloe WriteOutput values + TYPE(IceD_OutputType), INTENT(IN) :: y_IceD (:) !< IceDyn outputs (WriteOutput values are subset) + TYPE(BD_OutputType), INTENT(IN) :: y_BD (:) !< BeamDyn outputs (WriteOutput values are subset) + + REAL(ReKi), INTENT(OUT) :: OutputAry(:) !< single array of output + + INTEGER(IntKi) :: i ! loop counter + INTEGER(IntKi) :: indxLast ! The index of the last row value to be written to AllOutData for this time step (column). + INTEGER(IntKi) :: indxNext ! The index of the next row value to be written to AllOutData for this time step (column). + + + ! store individual module data into one array for output + + indxLast = 0 + indxNext = 1 + + IF ( y_FAST%numOuts(Module_IfW) > 0 ) THEN + indxLast = indxNext + SIZE(IfWOutput) - 1 + OutputAry(indxNext:indxLast) = IfWOutput + indxNext = IndxLast + 1 + ELSEIF ( y_FAST%numOuts(Module_OpFM) > 0 ) THEN + indxLast = indxNext + SIZE(OpFMOutput) - 1 + OutputAry(indxNext:indxLast) = OpFMOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_ED) > 0 ) THEN + indxLast = indxNext + SIZE(EDOutput) - 1 + OutputAry(indxNext:indxLast) = EDOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_BD) > 0 ) THEN + do i=1,SIZE(y_BD) + indxLast = indxNext + SIZE(y_BD(i)%WriteOutput) - 1 + OutputAry(indxNext:indxLast) = y_BD(i)%WriteOutput + indxNext = IndxLast + 1 + end do + END IF + + IF ( y_FAST%numOuts(Module_AD) > 0 ) THEN + indxLast = indxNext + SIZE(ADOutput) - 1 + OutputAry(indxNext:indxLast) = ADOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_SrvD) > 0 ) THEN + indxLast = indxNext + SIZE(SrvDOutput) - 1 + OutputAry(indxNext:indxLast) = SrvDOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_HD) > 0 ) THEN + indxLast = indxNext + SIZE(HDOutput) - 1 + OutputAry(indxNext:indxLast) = HDOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_SD) > 0 ) THEN + indxLast = indxNext + SIZE(SDOutput) - 1 + OutputAry(indxNext:indxLast) = SDOutput + indxNext = IndxLast + 1 + ELSE IF ( y_FAST%numOuts(Module_ExtPtfm) > 0 ) THEN + indxLast = indxNext + SIZE(ExtPtfmOutput) - 1 + OutputAry(indxNext:indxLast) = ExtPtfmOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_MAP) > 0 ) THEN + indxLast = indxNext + SIZE(MAPOutput) - 1 + OutputAry(indxNext:indxLast) = MAPOutput + indxNext = IndxLast + 1 + ELSEIF ( y_FAST%numOuts(Module_MD) > 0 ) THEN + indxLast = indxNext + SIZE(MDOutput) - 1 + OutputAry(indxNext:indxLast) = MDOutput + indxNext = IndxLast + 1 + ELSEIF ( y_FAST%numOuts(Module_FEAM) > 0 ) THEN + indxLast = indxNext + SIZE(FEAMOutput) - 1 + OutputAry(indxNext:indxLast) = FEAMOutput + indxNext = IndxLast + 1 + ELSEIF ( y_FAST%numOuts(Module_Orca) > 0 ) THEN + indxLast = indxNext + SIZE(OrcaOutput) - 1 + OutputAry(indxNext:indxLast) = OrcaOutput + indxNext = IndxLast + 1 + END IF + + IF ( y_FAST%numOuts(Module_IceF) > 0 ) THEN + indxLast = indxNext + SIZE(IceFOutput) - 1 + OutputAry(indxNext:indxLast) = IceFOutput + indxNext = IndxLast + 1 + ELSEIF ( y_FAST%numOuts(Module_IceD) > 0 ) THEN + DO i=1,p_FAST%numIceLegs + indxLast = indxNext + SIZE(y_IceD(i)%WriteOutput) - 1 + OutputAry(indxNext:indxLast) = y_IceD(i)%WriteOutput + indxNext = IndxLast + 1 + END DO + END IF + +END SUBROUTINE FillOutputAry +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE WriteVTK(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + REAL(DbKi), INTENT(IN ) :: t_global !< Current global time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code (only because we're updating VTK_LastWaveIndx) + TYPE(FAST_ModuleMapType), INTENT(IN ) :: MeshMapData !< Data for mapping between modules + + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(IN ) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(IN ) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(IN ) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(IN ) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(IN ) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(IN ) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(IN ) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(IN ) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(IN ) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WriteVTK' + + + IF ( p_FAST%VTK_Type == VTK_Surf ) THEN + CALL WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + ELSE IF ( p_FAST%VTK_Type == VTK_Basic ) THEN + CALL WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + ELSE IF ( p_FAST%VTK_Type == VTK_All ) THEN + CALL WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + ELSE IF (p_FAST%VTK_Type==VTK_Old) THEN + CALL WriteInputMeshesToFile( ED%Input(1), AD%Input(1), SD%Input(1), HD%Input(1), MAPp%Input(1), BD%Input(1,:), TRIM(p_FAST%OutFileRoot)//'.InputMeshes.bin', ErrStat2, ErrMsg2) + CALL WriteMotionMeshesToFile(t_global, ED%y, SD%Input(1), SD%y, HD%Input(1), MAPp%Input(1), BD%y, BD%Input(1,:), y_FAST%UnGra, ErrStat2, ErrMsg2, TRIM(p_FAST%OutFileRoot)//'.gra') + !unOut = -1 + !CALL MeshWrBin ( unOut, AD%y%BladeLoad(2), ErrStat2, ErrMsg2, 'AD_2_ED_loads.bin'); IF (ErrStat2 /= ErrID_None) CALL WrScr(TRIM(ErrMsg2)) + !CALL MeshWrBin ( unOut, ED%Input(1)%BladePtLoads(2),ErrStat2, ErrMsg2, 'AD_2_ED_loads.bin'); IF (ErrStat2 /= ErrID_None) CALL WrScr(TRIM(ErrMsg2)) + !CALL MeshMapWrBin( unOut, AD%y%BladeLoad(2), ED%Input(1)%BladePtLoads(2), MeshMapData%AD_L_2_BDED_B(2), ErrStat2, ErrMsg2, 'AD_2_ED_loads.bin' ); IF (ErrStat2 /= ErrID_None) CALL WrScr(TRIM(ErrMsg2)) + !close( unOut ) + END IF + + y_FAST%VTK_count = y_FAST%VTK_count + 1 + +END SUBROUTINE WriteVTK +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes all the committed meshes to VTK-formatted files. It doesn't bother with returning an error code. +SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + use FVW_IO, only: WrVTK_FVW + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(FAST_ModuleMapType), INTENT(IN ) :: MeshMapData !< Data for mapping between modules + + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(IN ) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(IN ) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(IN ) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(IN ) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(IN ) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(IN ) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(IN ) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(IN ) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(IN ) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop + + + logical :: outputFields ! flag to determine if we want to output the HD mesh fields + INTEGER(IntKi) :: NumBl, k + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WrVTK_AllMeshes' + + + + NumBl = 0 + if (allocated(ED%y%BladeRootMotion)) then + NumBl = SIZE(ED%y%BladeRootMotion) + end if + + + +! I'm first going to just put all of the meshes that get mapped together, then decide if we're going to print/plot them all + +! ElastoDyn + if (allocated(ED%Input)) then + + ! ElastoDyn outputs (motions) + DO K=1,NumBl + !%BladeLn2Mesh(K) used only when not BD (see below) + call MeshWrVTK(p_FAST%TurbinePos, ED%y%BladeRootMotion(K), trim(p_FAST%VTK_OutFileRoot)//'.ED_BladeRootMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + END DO + + call MeshWrVTK(p_FAST%TurbinePos, ED%y%TowerLn2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_TowerLn2Mesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + +! these will get output with their sibling input meshes + !call MeshWrVTK(p_FAST%TurbinePos, ED%y%HubPtMotion, trim(p_FAST%VTK_OutFileRoot)//'.ED_HubPtMotion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + !call MeshWrVTK(p_FAST%TurbinePos, ED%y%NacelleMotion, trim(p_FAST%VTK_OutFileRoot)//'.ED_NacelleMotion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + !call MeshWrVTK(p_FAST%TurbinePos, ED%y%PlatformPtMesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_PlatformPtMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + + ! ElastoDyn inputs (loads) + ! %BladePtLoads used only when not BD (see below) + call MeshWrVTK(p_FAST%TurbinePos, ED%Input(1)%TowerPtLoads, trim(p_FAST%VTK_OutFileRoot)//'.ED_TowerPtLoads', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ED%y%TowerLn2Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, ED%Input(1)%HubPtLoad, trim(p_FAST%VTK_OutFileRoot)//'.ED_Hub', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ED%y%HubPtMotion ) + call MeshWrVTK(p_FAST%TurbinePos, ED%Input(1)%NacelleLoads, trim(p_FAST%VTK_OutFileRoot)//'.ED_Nacelle' ,y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ED%y%NacelleMotion ) + call MeshWrVTK(p_FAST%TurbinePos, ED%Input(1)%PlatformPtMesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_PlatformPtMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ED%y%PlatformPtMesh ) + end if + + +! BeamDyn + IF ( p_FAST%CompElast == Module_BD .and. allocated(BD%Input) .and. allocated(BD%y)) THEN + + do K=1,NumBl + ! BeamDyn inputs + !call MeshWrVTK(p_FAST%TurbinePos, BD%Input(1,k)%RootMotion, trim(p_FAST%VTK_OutFileRoot)//'.BD_RootMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + call MeshWrVTK(p_FAST%TurbinePos, BD%Input(1,k)%HubMotion, trim(p_FAST%VTK_OutFileRoot)//'.BD_HubMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end do + if (allocated(MeshMapData%y_BD_BldMotion_4Loads)) then + do K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, BD%Input(1,k)%DistrLoad, trim(p_FAST%VTK_OutFileRoot)//'.BD_DistrLoad'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, MeshMapData%y_BD_BldMotion_4Loads(k) ) + ! skipping PointLoad + end do + elseif (p_FAST%BD_OutputSibling) then + do K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, BD%Input(1,k)%DistrLoad, trim(p_FAST%VTK_OutFileRoot)//'.BD_Blade'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, BD%y(k)%BldMotion ) + ! skipping PointLoad + end do + end if + + do K=1,NumBl + ! BeamDyn outputs + call MeshWrVTK(p_FAST%TurbinePos, BD%y(k)%ReactionForce, trim(p_FAST%VTK_OutFileRoot)//'.BD_ReactionForce_RootMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, BD%Input(1,k)%RootMotion ) + end do + + if (.not. p_FAST%BD_OutputSibling) then !otherwise this mesh has been put with the DistrLoad mesh + do K=1,NumBl + ! BeamDyn outputs + call MeshWrVTK(p_FAST%TurbinePos, BD%y(k)%BldMotion, trim(p_FAST%VTK_OutFileRoot)//'.BD_BldMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end do + end if + + + ELSE if (p_FAST%CompElast == Module_ED .and. allocated(ED%Input)) then + ! ElastoDyn + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, ED%y%BladeLn2Mesh(K), trim(p_FAST%VTK_OutFileRoot)//'.ED_BladeLn2Mesh_motion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + call MeshWrVTK(p_FAST%TurbinePos, ED%Input(1)%BladePtLoads(K), trim(p_FAST%VTK_OutFileRoot)//'.ED_BladePtLoads'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ED%y%BladeLn2Mesh(K) ) + END DO + END IF + +! ServoDyn + if (allocated(SrvD%Input)) then + IF ( SrvD%Input(1)%NTMD%Mesh%Committed ) THEN + !call MeshWrVTK(p_FAST%TurbinePos, SrvD%Input(1)%NTMD%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SrvD_NTMD_Motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + call MeshWrVTK(p_FAST%TurbinePos, SrvD%y%NTMD%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SrvD_NTMD', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, SrvD%Input(1)%TTMD%Mesh ) + END IF + IF ( SrvD%Input(1)%TTMD%Mesh%Committed ) THEN + !call MeshWrVTK(p_FAST%TurbinePos, SrvD%Input(1)%TTMD%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SrvD_TTMD_Motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + call MeshWrVTK(p_FAST%TurbinePos, SrvD%y%TTMD%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SrvD_TTMD', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, SrvD%Input(1)%TTMD%Mesh ) + END IF + end if + + +! AeroDyn + IF ( p_FAST%CompAero == Module_AD .and. allocated(AD%Input)) THEN + + if (allocated(AD%Input(1)%BladeRootMotion)) then + + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%BladeRootMotion(K), trim(p_FAST%VTK_OutFileRoot)//'.AD_BladeRootMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + !call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%BladeMotion(K), trim(p_FAST%VTK_OutFileRoot)//'.AD_BladeMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + END DO + + call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%HubMotion, trim(p_FAST%VTK_OutFileRoot)//'.AD_HubMotion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + !call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%TowerMotion, trim(p_FAST%VTK_OutFileRoot)//'.AD_TowerMotion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, AD%y%BladeLoad(K), trim(p_FAST%VTK_OutFileRoot)//'.AD_Blade'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, AD%Input(1)%BladeMotion(k) ) + END DO + call MeshWrVTK(p_FAST%TurbinePos, AD%y%TowerLoad, trim(p_FAST%VTK_OutFileRoot)//'.AD_Tower', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, AD%Input(1)%TowerMotion ) + + end if + + ! FVW submodule of AD15 + if (allocated(AD%m%FVW_u)) then + if (allocated(AD%m%FVW_u(1)%WingsMesh)) then + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, AD%m%FVW_u(1)%WingsMesh(k), trim(p_FAST%VTK_OutFileRoot)//'.FVW_WingsMesh'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, AD%Input(1)%BladeMotion(k) ) + !call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%BladeMotion(K), trim(p_FAST%OutFileRoot)//'.AD_BladeMotion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) + END DO + ! Free wake + call WrVTK_FVW(AD%p%FVW, AD%x(1)%FVW, AD%z(1)%FVW, AD%m%FVW, trim(p_FAST%VTK_OutFileRoot)//'.FVW', y_FAST%VTK_count, p_FAST%VTK_tWidth, bladeFrame=.FALSE.) ! bladeFrame==.FALSE. to output in global coords + end if + end if + END IF + +! HydroDyn + IF ( p_FAST%CompHydro == Module_HD .and. allocated(HD%Input)) THEN + !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) + !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%LumpedMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonLumped_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) + !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) + + if (p_FAST%CompSub == Module_NONE) then + call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) + outputFields = .false. + else + call MeshWrVTK(p_FAST%TurbinePos, HD%y%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) + outputFields = p_FAST%VTK_fields + end if + call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%LumpedMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonLumped', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%LumpedMesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%DistribMesh ) + + + END IF + +! SubDyn + IF ( p_FAST%CompSub == Module_SD .and. allocated(SD%Input)) THEN + !call MeshWrVTK(p_FAST%TurbinePos, SD%Input(1)%TPMesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_TPMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + call MeshWrVTK(p_FAST%TurbinePos, SD%Input(1)%LMesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_LMesh_y2Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, SD%y%y2Mesh ) + + call MeshWrVTK(p_FAST%TurbinePos, SD%y%y1Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y1Mesh_TPMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, SD%Input(1)%TPMesh ) + !call MeshWrVTK(p_FAST%TurbinePos, SD%y%y2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y2Mesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm .and. allocated(ExtPtfm%Input)) THEN + call MeshWrVTK(p_FAST%TurbinePos, ExtPtfm%y%PtfmMesh, trim(p_FAST%VTK_OutFileRoot)//'.ExtPtfm', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, ExtPtfm%Input(1)%PtfmMesh ) + END IF + +! MAP + IF ( p_FAST%CompMooring == Module_MAP ) THEN + if (allocated(MAPp%Input)) then + call MeshWrVTK(p_FAST%TurbinePos, MAPp%y%PtFairleadLoad, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFairlead', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, MAPp%Input(1)%PtFairDisplacement ) + !call MeshWrVTK(p_FAST%TurbinePos, MAPp%Input(1)%PtFairDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end if + +! MoorDyn + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + if (allocated(MD%Input)) then + call MeshWrVTK(p_FAST%TurbinePos, MD%y%PtFairleadLoad, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFairlead', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, MD%Input(1)%PtFairleadDisplacement ) + !call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end if + +! FEAMooring + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + if (allocated(FEAM%Input)) then + call MeshWrVTK(p_FAST%TurbinePos, FEAM%y%PtFairleadLoad, trim(p_FAST%VTK_OutFileRoot)//'.FEAM_PtFairlead', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, FEAM%Input(1)%PtFairleadDisplacement ) + !call MeshWrVTK(p_FAST%TurbinePos, FEAM%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.FEAM_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end if + +! Orca + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + if (allocated(Orca%Input)) then + call MeshWrVTK(p_FAST%TurbinePos, Orca%y%PtfmMesh, trim(p_FAST%VTK_OutFileRoot)//'.Orca_PtfmMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Orca%Input(1)%PtfmMesh ) + !call MeshWrVTK(p_FAST%TurbinePos, Orca%Input(1)%PtfmMesh, trim(p_FAST%VTK_OutFileRoot)//'.Orca_PtfmMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end if + END IF + + +! IceFloe + IF ( p_FAST%CompIce == Module_IceF ) THEN + if (allocated(IceF%Input)) then + call MeshWrVTK(p_FAST%TurbinePos, IceF%y%iceMesh, trim(p_FAST%VTK_OutFileRoot)//'.IceF_iceMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, IceF%Input(1)%iceMesh ) + !call MeshWrVTK(p_FAST%TurbinePos, IceF%Input(1)%iceMesh, trim(p_FAST%VTK_OutFileRoot)//'.IceF_iceMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + end if + +! IceDyn + ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN + if (allocated(IceD%Input)) then + + DO k = 1,p_FAST%numIceLegs + call MeshWrVTK(p_FAST%TurbinePos, IceD%y(k)%PointMesh, trim(p_FAST%VTK_OutFileRoot)//'.IceD_PointMesh'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, IceD%Input(1,k)%PointMesh ) + !call MeshWrVTK(p_FAST%TurbinePos, IceD%Input(1,k)%PointMesh, trim(p_FAST%VTK_OutFileRoot)//'.IceD_PointMesh_motion'//trim(num2lstr(k)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + END DO + end if + + END IF + + +END SUBROUTINE WrVTK_AllMeshes +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes a minimal subset of meshes (enough to visualize the turbine) to VTK-formatted files. It doesn't bother with +!! returning an error code. +SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(IN ) :: y_FAST !< Output variables for the glue code + TYPE(FAST_ModuleMapType), INTENT(IN ) :: MeshMapData !< Data for mapping between modules + + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(IN ) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(IN ) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(IN ) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(IN ) :: SD !< SubDyn data + TYPE(MAP_Data), INTENT(IN ) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(IN ) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(IN ) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(IN ) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop + + logical :: OutputFields + INTEGER(IntKi) :: NumBl, k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WrVTK_BasicMeshes' + + + NumBl = 0 + if (allocated(ED%y%BladeRootMotion)) then + NumBl = SIZE(ED%y%BladeRootMotion) + end if + + +! Blades + IF ( p_FAST%CompAero == Module_AD ) THEN ! These meshes may have airfoil data associated with nodes... + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, AD%Input(1)%BladeMotion(K), trim(p_FAST%VTK_OutFileRoot)//'.AD_Blade'//trim(num2lstr(k)), & + y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=AD%y%BladeLoad(K) ) + END DO + ELSE IF ( p_FAST%CompElast == Module_BD ) THEN + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, BD%y(k)%BldMotion, trim(p_FAST%VTK_OutFileRoot)//'.BD_BldMotion'//trim(num2lstr(k)), & + y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + END DO + ELSE IF ( p_FAST%CompElast == Module_ED ) THEN + DO K=1,NumBl + call MeshWrVTK(p_FAST%TurbinePos, ED%y%BladeLn2Mesh(K), trim(p_FAST%VTK_OutFileRoot)//'.ED_BladeLn2Mesh_motion'//trim(num2lstr(k)), & + y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + END DO + END IF + +! Nacelle + call MeshWrVTK(p_FAST%TurbinePos, ED%y%NacelleMotion, trim(p_FAST%VTK_OutFileRoot)//'.ED_Nacelle', y_FAST%VTK_count, & + p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=ED%Input(1)%NacelleLoads ) + +! Hub + call MeshWrVTK(p_FAST%TurbinePos, ED%y%HubPtMotion, trim(p_FAST%VTK_OutFileRoot)//'.ED_Hub', y_FAST%VTK_count, & + p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=ED%Input(1)%HubPtLoad ) +! Tower motions + call MeshWrVTK(p_FAST%TurbinePos, ED%y%TowerLn2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_TowerLn2Mesh_motion', & + y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + + + +! Substructure +! call MeshWrVTK(p_FAST%TurbinePos, ED%y%PlatformPtMesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_PlatformPtMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! IF ( p_FAST%CompSub == Module_SD ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, SD%Input(1)%TPMesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_TPMesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! call MeshWrVTK(p_FAST%TurbinePos, SD%y%y2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y2Mesh_motion', y_FAST%VTK_count, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! END IF + + IF ( p_FAST%CompHydro == Module_HD ) THEN + + if (p_FAST%CompSub == Module_NONE) then + call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) + outputFields = .false. + else + OutputFields = p_FAST%VTK_fields + end if + + call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=HD%y%Morison%DistribMesh ) + END IF + + +! Mooring Lines? +! IF ( p_FAST%CompMooring == Module_MAP ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, MAPp%Input(1)%PtFairDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, FEAM%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'FEAM_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) +! END IF + + +END SUBROUTINE WrVTK_BasicMeshes +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes a minimal subset of meshes with surfaces to VTK-formatted files. It doesn't bother with +!! returning an error code. +SUBROUTINE WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + use FVW_IO, only: WrVTK_FVW + + REAL(DbKi), INTENT(IN ) :: t_global !< Current global time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code (only because we're updating VTK_LastWaveIndx) + TYPE(FAST_ModuleMapType), INTENT(IN ) :: MeshMapData !< Data for mapping between modules + + TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(IN ) :: SrvD !< ServoDyn data + TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(IN ) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(IN ) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(IN ) :: SD !< SubDyn data + TYPE(MAP_Data), INTENT(IN ) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(IN ) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(IN ) :: MD !< MoorDyn data + TYPE(OrcaFlex_Data), INTENT(IN ) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop + + + logical, parameter :: OutputFields = .FALSE. ! due to confusion about what fields mean on a surface, we are going to just output the basic meshes if people ask for fields + INTEGER(IntKi) :: NumBl, k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMSg2 + CHARACTER(*), PARAMETER :: RoutineName = 'WrVTK_Surfaces' + + NumBl = 0 + if (allocated(ED%y%BladeRootMotion)) then + NumBl = SIZE(ED%y%BladeRootMotion) + end if + +! Ground (written at initialization) + +! Wave elevation + if ( allocated( p_FAST%VTK_Surface%WaveElev ) ) call WrVTK_WaveElev( t_global, p_FAST, y_FAST, HD) + +! Nacelle + call MeshWrVTK_PointSurface (p_FAST%TurbinePos, ED%y%NacelleMotion, trim(p_FAST%VTK_OutFileRoot)//'.NacelleSurface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth , verts = p_FAST%VTK_Surface%NacelleBox, Sib=ED%Input(1)%NacelleLoads ) + + +! Hub + call MeshWrVTK_PointSurface (p_FAST%TurbinePos, ED%y%HubPtMotion, trim(p_FAST%VTK_OutFileRoot)//'.HubSurface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth , & + NumSegments=p_FAST%VTK_Surface%NumSectors, radius=p_FAST%VTK_Surface%HubRad, Sib=ED%Input(1)%HubPtLoad ) + +! Tower motions + call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, ED%y%TowerLn2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.TowerSurface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, p_FAST%VTK_Surface%TowerRad ) + +! Blades + IF ( p_FAST%CompAero == Module_AD ) THEN ! These meshes may have airfoil data associated with nodes... + DO K=1,NumBl + call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, AD%Input(1)%BladeMotion(K), trim(p_FAST%VTK_OutFileRoot)//'.Blade'//trim(num2lstr(k))//'Surface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth , verts=p_FAST%VTK_Surface%BladeShape(K)%AirfoilCoords & + ,Sib=AD%y%BladeLoad(k) ) + END DO + ELSE IF ( p_FAST%CompElast == Module_BD ) THEN + DO K=1,NumBl + call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, BD%y(k)%BldMotion, trim(p_FAST%VTK_OutFileRoot)//'.Blade'//trim(num2lstr(k))//'Surface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth , verts=p_FAST%VTK_Surface%BladeShape(K)%AirfoilCoords ) + END DO + ELSE IF ( p_FAST%CompElast == Module_ED ) THEN + DO K=1,NumBl + call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, ED%y%BladeLn2Mesh(K), trim(p_FAST%VTK_OutFileRoot)//'.Blade'//trim(num2lstr(k))//'Surface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth , verts=p_FAST%VTK_Surface%BladeShape(K)%AirfoilCoords ) + END DO + END IF + +! Free wake + if (allocated(AD%m%FVW_u)) then + if (allocated(AD%m%FVW_u(1)%WingsMesh)) then + call WrVTK_FVW(AD%p%FVW, AD%x(1)%FVW, AD%z(1)%FVW, AD%m%FVW, trim(p_FAST%VTK_OutFileRoot)//'.FVW', y_FAST%VTK_count, p_FAST%VTK_tWidth, bladeFrame=.FALSE.) ! bladeFrame==.FALSE. to output in global coords + end if + end if + + +! Platform +! call MeshWrVTK_PointSurface (p_FAST%TurbinePos, ED%y%PlatformPtMesh, trim(p_FAST%VTK_OutFileRoot)//'.PlatformSurface', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, Radius = p_FAST%VTK_Surface%GroundRad ) + + +! Substructure +! call MeshWrVTK(p_FAST%TurbinePos, ED%y%PlatformPtMesh, trim(p_FAST%VTK_OutFileRoot)//'.ED_PlatformPtMesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! IF ( p_FAST%CompSub == Module_SD ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, SD%Input(1)%TPMesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_TPMesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! call MeshWrVTK(p_FAST%TurbinePos, SD%y%y2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y2Mesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! END IF + + IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN + !if ( p_FAST%CompSub == Module_NONE ) then ! floating + ! OutputFields = .false. + !else + ! OutputFields = p_FAST%VTK_fields + !end if + + call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, & + p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%DistribMesh ) + END IF + + +! Mooring Lines? +! IF ( p_FAST%CompMooring == Module_MAP ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, MAPp%Input(1)%PtFairDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN +! call MeshWrVTK(p_FAST%TurbinePos, FEAM%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'FEAM_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) +! END IF + + + if (p_FAST%VTK_fields) then + call WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + end if + + +END SUBROUTINE WrVTK_Surfaces +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine writes the wave elevation data for a given time step +SUBROUTINE WrVTK_WaveElev(t_global, p_FAST, y_FAST, HD) + + REAL(DbKi), INTENT(IN ) :: t_global !< Current global time + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + + TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data + + ! local variables + INTEGER(IntKi) :: Un ! fortran unit number + INTEGER(IntKi) :: n, iy, ix ! loop counters + REAL(SiKi) :: t + CHARACTER(1024) :: FileName + INTEGER(IntKi) :: NumberOfPoints + INTEGER(IntKi), parameter :: NumberOfLines = 0 + INTEGER(IntKi) :: NumberOfPolys + CHARACTER(1024) :: Tstr + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*),PARAMETER :: RoutineName = 'WrVTK_WaveElev' + + + NumberOfPoints = size(p_FAST%VTK_surface%WaveElevXY,2) + ! I'm going to make triangles for now. we should probably just make this a structured file at some point + NumberOfPolys = ( p_FAST%VTK_surface%NWaveElevPts(1) - 1 ) * & + ( p_FAST%VTK_surface%NWaveElevPts(2) - 1 ) * 2 + + !................................................................. + ! write the data that potentially changes each time step: + !................................................................. + ! construct the string for the zero-padded VTK write-out step + write(Tstr, '(i' // trim(Num2LStr(p_FAST%VTK_tWidth)) //'.'// trim(Num2LStr(p_FAST%VTK_tWidth)) // ')') y_FAST%VTK_count + + ! PolyData (.vtp) - Serial vtkPolyData (unstructured) file + FileName = TRIM(p_FAST%VTK_OutFileRoot)//'.WaveSurface.'//TRIM(Tstr)//'.vtp' + + call WrVTK_header( FileName, NumberOfPoints, NumberOfLines, NumberOfPolys, Un, ErrStat2, ErrMsg2 ) + if (ErrStat2 >= AbortErrLev) return + +! points (nodes, augmented with NumSegments): + WRITE(Un,'(A)') ' <Points>' + WRITE(Un,'(A)') ' <DataArray type="Float32" NumberOfComponents="3" format="ascii">' + + ! I'm not going to interpolate in time; I'm just going to get the index of the closest wave time value + t = REAL(t_global,SiKi) + call GetWaveElevIndx( t, HD%p%WaveTime, y_FAST%VTK_LastWaveIndx ) + + n = 1 + do ix=1,p_FAST%VTK_surface%NWaveElevPts(1) + do iy=1,p_FAST%VTK_surface%NWaveElevPts(2) + WRITE(Un,VTK_AryFmt) p_FAST%VTK_surface%WaveElevXY(:,n), p_FAST%VTK_surface%WaveElev(y_FAST%VTK_LastWaveIndx,n) + n = n+1 + end do + end do + + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Points>' + + + WRITE(Un,'(A)') ' <Polys>' + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="connectivity" format="ascii">' + + do ix=1,p_FAST%VTK_surface%NWaveElevPts(1)-1 + do iy=1,p_FAST%VTK_surface%NWaveElevPts(2)-1 + n = p_FAST%VTK_surface%NWaveElevPts(1)*(ix-1)+iy - 1 ! points start at 0 + + WRITE(Un,'(3(i7))') n, n+1, n+p_FAST%VTK_surface%NWaveElevPts(2) + WRITE(Un,'(3(i7))') n+1, n+1+p_FAST%VTK_surface%NWaveElevPts(2), n+p_FAST%VTK_surface%NWaveElevPts(2) + + end do + end do + WRITE(Un,'(A)') ' </DataArray>' + + WRITE(Un,'(A)') ' <DataArray type="Int32" Name="offsets" format="ascii">' + do n=1,NumberOfPolys + WRITE(Un,'(i7)') 3*n + end do + WRITE(Un,'(A)') ' </DataArray>' + WRITE(Un,'(A)') ' </Polys>' + + call WrVTK_footer( Un ) + +END SUBROUTINE WrVTK_WaveElev +!---------------------------------------------------------------------------------------------------------------------------------- +!> This function returns the index, Ind, of the XAry closest to XValIn, where XAry is assumed to be periodic. It starts +!! searching at the value of Ind from a previous step. +SUBROUTINE GetWaveElevIndx( XValIn, XAry, Ind ) + + ! Argument declarations. + + INTEGER, INTENT(INOUT) :: Ind ! Initial and final index into the arrays. + + REAL(SiKi), INTENT(IN) :: XAry (:) !< Array of X values to be interpolated. + REAL(SiKi), INTENT(IN) :: XValIn !< X value to be found + + + INTEGER :: AryLen ! Length of the arrays. + REAL(SiKi) :: XVal !< X to be found (wrapped/periodic) + + + AryLen = size(XAry) + + ! Wrap XValIn into the range XAry(1) to XAry(AryLen) + XVal = MOD(XValIn, XAry(AryLen)) + + + + ! Let's check the limits first. + + IF ( XVal <= XAry(1) ) THEN + Ind = 1 + RETURN + ELSE IF ( XVal >= XAry(AryLen) ) THEN + Ind = AryLen + RETURN + ELSE + ! Set the Ind to the first index if we are at the beginning of XAry + IF ( XVal <= XAry(2) ) THEN + Ind = 1 + END IF + END IF + + + ! Let's interpolate! + + Ind = MAX( MIN( Ind, AryLen-1 ), 1 ) + + DO + + IF ( XVal < XAry(Ind) ) THEN + + Ind = Ind - 1 + + ELSE IF ( XVal >= XAry(Ind+1) ) THEN + + Ind = Ind + 1 + + ELSE + + ! XAry(Ind) <= XVal < XAry(Ind+1) + ! this would make it the "closest" node, but I'm not going to worry about that for visualization purposes + !if ( XVal > (XAry(Ind+1) + XAry(Ind))/2.0_SiKi ) Ind = Ind + 1 + + RETURN + + END IF + + END DO + + RETURN +END SUBROUTINE GetWaveElevIndx +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes Input Mesh information to a binary file (for debugging). It both opens and closes the file. +SUBROUTINE WriteInputMeshesToFile(u_ED, u_AD, u_SD, u_HD, u_MAP, u_BD, FileName, ErrStat, ErrMsg) + TYPE(ED_InputType), INTENT(IN) :: u_ED !< ElastoDyn inputs + TYPE(AD_InputType), INTENT(IN) :: u_AD !< AeroDyn inputs + TYPE(SD_InputType), INTENT(IN) :: u_SD !< SubDyn inputs + TYPE(HydroDyn_InputType), INTENT(IN) :: u_HD !< HydroDyn inputs + TYPE(MAP_InputType), INTENT(IN) :: u_MAP !< MAP inputs + TYPE(BD_InputType), INTENT(IN) :: u_BD(:) !< BeamDyn inputs + CHARACTER(*), INTENT(IN) :: FileName !< Name of file to write this information to + INTEGER(IntKi) :: ErrStat !< Error status of the operation + CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + INTEGER(IntKi) :: unOut + INTEGER(IntKi) :: K_local + INTEGER(B4Ki), PARAMETER :: File_ID = 3 + INTEGER(B4Ki) :: NumBl + + ! Open the binary output file: + unOut=-1 + CALL GetNewUnit( unOut, ErrStat, ErrMsg ) + CALL OpenBOutFile ( unOut, TRIM(FileName), ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) RETURN + + ! note that I'm not doing anything with the errors here, so it won't tell + ! you there was a problem writing the data unless it was the last call. + + ! Add a file identification number (in case we ever have to change this): + WRITE( unOut, IOSTAT=ErrStat ) File_ID + + ! Add how many blade meshes there are: + NumBl = SIZE(u_ED%BladePtLoads,1) ! Note that NumBl is B4Ki + WRITE( unOut, IOSTAT=ErrStat ) NumBl + + ! Add all of the input meshes: + DO K_local = 1,NumBl + CALL MeshWrBin( unOut, u_ED%BladePtLoads(K_local), ErrStat, ErrMsg ) + END DO + CALL MeshWrBin( unOut, u_ED%TowerPtLoads, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_ED%PlatformPtMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_SD%LMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) + ! Add how many BD blade meshes there are: + NumBl = SIZE(u_BD,1) ! Note that NumBl is B4Ki + WRITE( unOut, IOSTAT=ErrStat ) NumBl + + DO K_local = 1,NumBl + CALL MeshWrBin( unOut, u_BD(K_local)%RootMotion, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_BD(K_local)%DistrLoad, ErrStat, ErrMsg ) + END DO + + ! Add how many AD blade meshes there are: + NumBl = SIZE(u_AD%BladeMotion,1) ! Note that NumBl is B4Ki + WRITE( unOut, IOSTAT=ErrStat ) NumBl + + DO K_local = 1,NumBl + CALL MeshWrBin( unOut, u_AD%BladeMotion(k_local), ErrStat, ErrMsg ) + END DO + + ! Close the file + CLOSE(unOut) + +END SUBROUTINE WriteInputMeshesToFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine writes motion mesh data to a binary file (for rudimentary visualization and debugging). If unOut < 0, a new file +!! will be opened for writing (FileName). It is up to the caller of this routine to close the file. +SUBROUTINE WriteMotionMeshesToFile(time, y_ED, u_SD, y_SD, u_HD, u_MAP, y_BD, u_BD, UnOut, ErrStat, ErrMsg, FileName) + REAL(DbKi), INTENT(IN) :: time !< current simulation time + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< ElastoDyn outputs + TYPE(SD_InputType), INTENT(IN) :: u_SD !< SubDyn inputs + TYPE(SD_OutputType), INTENT(IN) :: y_SD !< SubDyn outputs + TYPE(HydroDyn_InputType), INTENT(IN) :: u_HD !< HydroDyn inputs + TYPE(MAP_InputType), INTENT(IN) :: u_MAP !< MAP inputs + TYPE(BD_OutputType), INTENT(IN) :: y_BD(:) !< BeamDyn outputs + TYPE(BD_InputType), INTENT(IN) :: u_BD(:) !< BeamDyn inputs + INTEGER(IntKi) , INTENT(INOUT) :: unOut !< Unit number to write where this info should be written. If unOut < 0, a new file will be opened and the opened unit number will be returned. + CHARACTER(*), INTENT(IN) :: FileName !< If unOut < 0, FileName will be opened for writing this mesh information. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + REAL(R8Ki) :: t + + INTEGER(IntKi) :: K_local + INTEGER(B4Ki), PARAMETER :: File_ID = 101 + INTEGER(B4Ki) :: NumBl + + t = time ! convert to 8-bytes if necessary (DbKi might not be R8Ki) + + ! note that I'm not doing anything with the errors here, so it won't tell + ! you there was a problem writing the data unless it was the last call. + + + ! Open the binary output file and write a header: + if (unOut<0) then + CALL GetNewUnit( unOut, ErrStat, ErrMsg ) + + CALL OpenBOutFile ( unOut, TRIM(FileName), ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) RETURN + + ! Add a file identification number (in case we ever have to change this): + WRITE( unOut, IOSTAT=ErrStat ) File_ID + + ! Add how many blade meshes there are: + NumBl = SIZE(y_ED%BladeLn2Mesh,1) ! Note that NumBl is B4Ki + WRITE( unOut, IOSTAT=ErrStat ) NumBl + NumBl = SIZE(y_BD,1) ! Note that NumBl is B4Ki + WRITE( unOut, IOSTAT=ErrStat ) NumBl + end if + + WRITE( unOut, IOSTAT=ErrStat ) t + + ! Add all of the meshes with motions: + DO K_local = 1,SIZE(y_ED%BladeLn2Mesh,1) + CALL MeshWrBin( unOut, y_ED%BladeLn2Mesh(K_local), ErrStat, ErrMsg ) + END DO + CALL MeshWrBin( unOut, y_ED%TowerLn2Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, y_ED%PlatformPtMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, y_SD%y2Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) + DO K_local = 1,SIZE(y_BD,1) + CALL MeshWrBin( unOut, u_BD(K_local)%RootMotion, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, y_BD(K_local)%BldMotion, ErrStat, ErrMsg ) + END DO + + ! + ! ! Close the file + !CLOSE(unOut) + ! +END SUBROUTINE WriteMotionMeshesToFile +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! Linerization routines +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine that calls FAST_Linearize_T for an array of Turbine data structures if the linearization flag is set for each individual turbine. +SUBROUTINE FAST_Linearize_Tary(t_initial, n_t_global, Turbine, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial simulation time (almost always 0) + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< integer time step + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine(:) !< all data for one instance of a turbine + 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_turb, NumTurbines + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Linearize_Tary' + + + NumTurbines = SIZE(Turbine) + ErrStat = ErrID_None + ErrMsg = "" + + DO i_turb = 1,NumTurbines + + CALL FAST_Linearize_T(t_initial, n_t_global, Turbine(i_turb), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + END DO + + +END SUBROUTINE FAST_Linearize_Tary +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that performs lineaization at an operating point for a turbine. This is a separate subroutine so that the FAST +!! driver programs do not need to change or operate on the individual module level. +SUBROUTINE FAST_Linearize_T(t_initial, n_t_global, Turbine, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial simulation time (almost always 0) + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< integer time step + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: t_global ! current simulation time + REAL(DbKi) :: next_lin_time ! next simulation time where linearization analysis should be performed + INTEGER(IntKi) :: iLinTime ! loop counter + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Linearize_T' + + + ErrStat = ErrID_None + ErrMsg = "" + + if ( .not. Turbine%p_FAST%Linearize ) return + + if (.not. Turbine%p_FAST%CalcSteady) then + + if ( Turbine%m_FAST%Lin%NextLinTimeIndx <= Turbine%p_FAST%NLinTimes ) then !bjj: maybe this logic should go in FAST_Linearize_OP??? + + next_lin_time = Turbine%m_FAST%Lin%LinTimes( Turbine%m_FAST%Lin%NextLinTimeIndx ) + t_global = t_initial + n_t_global*Turbine%p_FAST%dt + + if ( EqualRealNos( t_global, next_lin_time ) .or. t_global > next_lin_time ) then + + CALL FAST_Linearize_OP(t_global, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + if (Turbine%p_FAST%WrVTK == VTK_ModeShapes) then + if (Turbine%m_FAST%Lin%NextLinTimeIndx > Turbine%p_FAST%NLinTimes) call WrVTKCheckpoint() + end if + + end if + + end if + + else ! CalcSteady + + t_global = t_initial + n_t_global*Turbine%p_FAST%dt + + call FAST_CalcSteady( n_t_global, t_global, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, Turbine%ED, Turbine%BD, Turbine%SrvD, & + Turbine%AD, Turbine%IfW, Turbine%OpFM, Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, & + Turbine%Orca, Turbine%IceF, Turbine%IceD, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (Turbine%m_FAST%Lin%FoundSteady) then + + do iLinTime=1,Turbine%p_FAST%NLinTimes + t_global = Turbine%m_FAST%Lin%LinTimes(iLinTime) + + call SetOperatingPoint(iLinTime, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, Turbine%ED, Turbine%BD, Turbine%SrvD, & + Turbine%AD, Turbine%IfW, Turbine%OpFM, Turbine%HD, Turbine%SD, Turbine%ExtPtfm, & + Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, Turbine%IceF, Turbine%IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + if (Turbine%p_FAST%DT_UJac < Turbine%p_FAST%TMax) then + Turbine%m_FAST%calcJacobian = .true. + Turbine%m_FAST%NextJacCalcTime = t_global + end if + + CALL CalcOutputs_And_SolveForInputs( -1, t_global, STATE_CURR, Turbine%m_FAST%calcJacobian, Turbine%m_FAST%NextJacCalcTime, & + Turbine%p_FAST, Turbine%m_FAST, .false., Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL FAST_Linearize_OP(t_global, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + end do + + if (Turbine%p_FAST%WrVTK == VTK_ModeShapes) CALL WrVTKCheckpoint() + + end if + + end if + return + +contains + subroutine WrVTKCheckpoint() + ! we are creating a checkpoint file for each turbine, so setting NumTurbines=1 in the file + CALL FAST_CreateCheckpoint_T(t_initial, Turbine%p_FAST%n_TMax_m1+1, 1, Turbine, TRIM(Turbine%p_FAST%OutFileRoot)//'.ModeShapeVTK', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end subroutine WrVTKCheckpoint +END SUBROUTINE FAST_Linearize_T +!---------------------------------------------------------------------------------------------------------------------------------- + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! PROGRAM EXIT ROUTINES +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine that calls ExitThisProgram for one instance of a Turbine data structure. This is a separate subroutine so that the FAST +!! driver programs do not need to change or operate on the individual module level. +!! This routine should be called from glue code only (e.g., FAST_Prog.f90). It should not be called in any of these driver routines. +SUBROUTINE ExitThisProgram_T( Turbine, ErrLevel_in, StopTheProgram, ErrLocMsg, SkipRunTimeMsg ) + + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< Data for one turbine instance + INTEGER(IntKi), INTENT(IN) :: ErrLevel_in !< Error level when Error == .TRUE. (required when Error is .TRUE.) + LOGICAL, INTENT(IN) :: StopTheProgram !< flag indicating if the program should end (false if there are more turbines to end) + CHARACTER(*), OPTIONAL, INTENT(IN) :: ErrLocMsg !< an optional message describing the location of the error + LOGICAL, OPTIONAL, INTENT(IN) :: SkipRunTimeMsg !< an optional message describing run-time stats + + LOGICAL :: SkipRunTimes + + IF (PRESENT(SkipRunTimeMsg)) THEN + SkipRunTimes = SkipRunTimeMsg + ELSE + SkipRunTimes = .FALSE. + END IF + + + IF (PRESENT(ErrLocMsg)) THEN + + CALL ExitThisProgram( Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrLevel_in, StopTheProgram, ErrLocMsg, SkipRunTimes ) + + ELSE + + CALL ExitThisProgram( Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + Turbine%ED, Turbine%BD, Turbine%SrvD, Turbine%AD14, Turbine%AD, Turbine%IfW, Turbine%OpFM, & + Turbine%HD, Turbine%SD, Turbine%ExtPtfm, Turbine%MAP, Turbine%FEAM, Turbine%MD, Turbine%Orca, & + Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrLevel_in, StopTheProgram, SkipRunTimeMsg=SkipRunTimes ) + + END IF + +END SUBROUTINE ExitThisProgram_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine is called when FAST exits. It calls all the modules' end routines and cleans up variables declared in the +!! main program. If there was an error, it also aborts. Otherwise, it prints the run times and performs a normal exit. +!! This routine should not be called from glue code (e.g., FAST_Prog.f90) or ExitThisProgram_T only. It should not be called in any +!! of these driver routines. +SUBROUTINE ExitThisProgram( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrLevel_in, StopTheProgram, ErrLocMsg, SkipRunTimeMsg ) +!............................................................................................................................... + + ! Passed arguments + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn v14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + INTEGER(IntKi), INTENT(IN) :: ErrLevel_in !< Error level when Error == .TRUE. (required when Error is .TRUE.) + LOGICAL, INTENT(IN) :: StopTheProgram !< flag indicating if the program should end (false if there are more turbines to end) + CHARACTER(*), OPTIONAL, INTENT(IN) :: ErrLocMsg !< an optional message describing the location of the error + LOGICAL, OPTIONAL, INTENT(IN) :: SkipRunTimeMsg !< an optional message describing run-time stats + + + ! Local variables: + INTEGER(IntKi) :: ErrorLevel + LOGICAL :: PrintRunTimes + + INTEGER(IntKi) :: ErrStat2 ! Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message + CHARACTER(1224) :: SimMsg ! optional message to print about where the error took place in the simulation + + CHARACTER(*), PARAMETER :: RoutineName = 'ExitThisProgram' + + + ErrorLevel = ErrLevel_in + + ! for debugging, let's output the meshes and all of their fields + IF ( ErrorLevel >= AbortErrLev .AND. p_FAST%WrVTK > VTK_None) THEN + p_FAST%VTK_OutFileRoot = trim(p_FAST%VTK_OutFileRoot)//'.DebugError' + p_FAST%VTK_fields = .true. + CALL WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + end if + + + + ! End all modules + CALL FAST_EndMods( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat2, ErrMsg2 ) + IF (ErrStat2 /= ErrID_None) THEN + CALL WrScr( NewLine//RoutineName//':'//TRIM(ErrMsg2)//NewLine ) + ErrorLevel = MAX(ErrorLevel,ErrStat2) + END IF + + ! Destroy all data associated with FAST variables: + + CALL FAST_DestroyAll( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2 ) + IF (ErrStat2 /= ErrID_None) THEN + CALL WrScr( NewLine//RoutineName//':'//TRIM(ErrMsg2)//NewLine ) + ErrorLevel = MAX(ErrorLevel,ErrStat2) + END IF + + + !............................................................................................................................ + ! Set exit error code if there was an error; + !............................................................................................................................ + IF ( ErrorLevel >= AbortErrLev ) THEN + + IF (PRESENT(ErrLocMsg)) THEN + SimMsg = ErrLocMsg + ELSE + SimMsg = 'after the simulation completed' + END IF + + IF (y_FAST%UnSum > 0) THEN + CLOSE(y_FAST%UnSum) + y_FAST%UnSum = -1 + END IF + + + SimMsg = 'FAST encountered an error '//TRIM(SimMsg)//'.'//NewLine//' Simulation error level: '//TRIM(GetErrStr(ErrorLevel)) + if (StopTheProgram) then + CALL ProgAbort( trim(SimMsg), TrapErrors=.FALSE., TimeWait=3._ReKi ) ! wait 3 seconds (in case they double-clicked and got an error) + else + CALL WrScr(trim(SimMsg)) + end if + + END IF + + !............................................................................................................................ + ! Write simulation times and stop + !............................................................................................................................ + if (present(SkipRunTimeMsg)) then + PrintRunTimes = .not. SkipRunTimeMsg + else + PrintRunTimes = .true. + end if + + IF (p_FAST%WrSttsTime .and. PrintRunTimes) THEN + CALL RunTimes( m_FAST%StrtTime, m_FAST%UsrTime1, m_FAST%SimStrtTime, m_FAST%UsrTime2, m_FAST%t_global, UnSum=y_FAST%UnSum, DescStrIn=p_FAST%TDesc ) + END IF + IF (y_FAST%UnSum > 0) THEN + CLOSE(y_FAST%UnSum) + y_FAST%UnSum = -1 + END IF + + if (StopTheProgram) then +#if (defined COMPILE_SIMULINK || defined COMPILE_LABVIEW) + ! for Simulink, this may not be a normal stop. It might call this after an error in the model. + CALL WrScr( NewLine//' '//TRIM(FAST_Ver%Name)//' completed.'//NewLine ) +#else + CALL NormStop( ) +#endif + end if + + +END SUBROUTINE ExitThisProgram +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine is called at program termination. It writes any additional output files, +!! deallocates variables for FAST file I/O and closes files. +SUBROUTINE FAST_EndOutput( p_FAST, y_FAST, m_FAST, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< FAST Parameters + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< FAST Output + TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST !< Miscellaneous variables (only for the final time) + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Message associated with errro status + + ! local variables + CHARACTER(LEN(y_FAST%FileDescLines)*3) :: FileDesc ! The description of the run, to be written in the binary output file + + + ! Initialize some values + + ErrStat = ErrID_None + ErrMsg = '' + + !------------------------------------------------------------------------------------------------- + ! Write the binary output file if requested + !------------------------------------------------------------------------------------------------- + + IF (p_FAST%WrBinOutFile .AND. y_FAST%n_Out > 0) THEN + + FileDesc = TRIM(y_FAST%FileDescLines(1))//' '//TRIM(y_FAST%FileDescLines(2))//'; '//TRIM(y_FAST%FileDescLines(3)) + + CALL WrBinFAST(TRIM(p_FAST%OutFileRoot)//'.outb', Int(p_FAST%WrBinMod, B2Ki), TRIM(FileDesc), & + y_FAST%ChannelNames, y_FAST%ChannelUnits, y_FAST%TimeData, y_FAST%AllOutData(:,1:y_FAST%n_Out), ErrStat, ErrMsg) + + IF ( ErrStat /= ErrID_None ) CALL WrScr( TRIM(GetErrStr(ErrStat))//' when writing binary output file: '//TRIM(ErrMsg) ) + + END IF + + + !------------------------------------------------------------------------------------------------- + ! Close the text tabular output file and summary file (if opened) + !------------------------------------------------------------------------------------------------- + IF (y_FAST%UnOu > 0) THEN ! I/O unit number for the tabular output file + CLOSE( y_FAST%UnOu ) + y_FAST%UnOu = -1 + END IF + + IF (y_FAST%UnSum > 0) THEN ! I/O unit number for the tabular output file + CLOSE( y_FAST%UnSum ) + y_FAST%UnSum = -1 + END IF + + IF (y_FAST%UnGra > 0) THEN ! I/O unit number for the graphics output file + CLOSE( y_FAST%UnGra ) + y_FAST%UnGra = -1 + END IF + + !------------------------------------------------------------------------------------------------- + ! Deallocate arrays + !------------------------------------------------------------------------------------------------- + + ! Output + IF ( ALLOCATED(y_FAST%AllOutData ) ) DEALLOCATE(y_FAST%AllOutData ) + IF ( ALLOCATED(y_FAST%TimeData ) ) DEALLOCATE(y_FAST%TimeData ) + IF ( ALLOCATED(y_FAST%ChannelNames ) ) DEALLOCATE(y_FAST%ChannelNames ) + IF ( ALLOCATED(y_FAST%ChannelUnits ) ) DEALLOCATE(y_FAST%ChannelUnits ) + + +END SUBROUTINE FAST_EndOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calls the end routines for each module that was previously initialized. +SUBROUTINE FAST_EndMods( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn v14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + 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, k ! loop counter + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_EndMods' + + !............................................................................................................................... + ! End all modules (and write binary FAST output file) + !............................................................................................................................... + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL FAST_EndOutput( p_FAST, y_FAST, m_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( p_FAST%ModuleInitialized(Module_ED) ) THEN + CALL ED_End( ED%Input(1), ED%p, ED%x(STATE_CURR), ED%xd(STATE_CURR), ED%z(STATE_CURR), ED%OtherSt(STATE_CURR), & + ED%y, ED%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_BD) ) THEN + + DO k=1,p_FAST%nBeams + CALL BD_End(BD%Input(1,k), BD%p(k), BD%x(k,STATE_CURR), BD%xd(k,STATE_CURR), BD%z(k,STATE_CURR), & + BD%OtherSt(k,STATE_CURR), BD%y(k), BD%m(k), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + END IF + + + IF ( p_FAST%ModuleInitialized(Module_AD14) ) THEN + CALL AD14_End( AD14%Input(1), AD14%p, AD14%x(STATE_CURR), AD14%xd(STATE_CURR), AD14%z(STATE_CURR), & + AD14%OtherSt(STATE_CURR), AD14%y, AD14%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%ModuleInitialized(Module_AD) ) THEN + CALL AD_End( AD%Input(1), AD%p, AD%x(STATE_CURR), AD%xd(STATE_CURR), AD%z(STATE_CURR), & + AD%OtherSt(STATE_CURR), AD%y, AD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_IfW) ) THEN + CALL InflowWind_End( IfW%Input(1), IfW%p, IfW%x(STATE_CURR), IfW%xd(STATE_CURR), IfW%z(STATE_CURR), IfW%OtherSt(STATE_CURR), & + IfW%y, IfW%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_SrvD) ) THEN + CALL SrvD_End( SrvD%Input(1), SrvD%p, SrvD%x(STATE_CURR), SrvD%xd(STATE_CURR), SrvD%z(STATE_CURR), SrvD%OtherSt(STATE_CURR), & + SrvD%y, SrvD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_HD) ) THEN + CALL HydroDyn_End( HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_SD) ) THEN + CALL SD_End( SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), & + SD%y, SD%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSE IF ( p_FAST%ModuleInitialized(Module_ExtPtfm) ) THEN + CALL ExtPtfm_End( ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR), & + ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_MAP) ) THEN + CALL MAP_End( MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), MAPp%OtherSt, & + MAPp%y, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%ModuleInitialized(Module_MD) ) THEN + CALL MD_End( MD%Input(1), MD%p, MD%x(STATE_CURR), MD%xd(STATE_CURR), MD%z(STATE_CURR), MD%OtherSt(STATE_CURR), & + MD%y, MD%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%ModuleInitialized(Module_FEAM) ) THEN + CALL FEAM_End( FEAM%Input(1), FEAM%p, FEAM%x(STATE_CURR), FEAM%xd(STATE_CURR), FEAM%z(STATE_CURR), & + FEAM%OtherSt(STATE_CURR), FEAM%y, FEAM%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%ModuleInitialized(Module_Orca) ) THEN + CALL Orca_End( Orca%Input(1), Orca%p, Orca%x(STATE_CURR), Orca%xd(STATE_CURR), Orca%z(STATE_CURR), Orca%OtherSt(STATE_CURR), & + Orca%y, Orca%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p_FAST%ModuleInitialized(Module_IceF) ) THEN + CALL IceFloe_End(IceF%Input(1), IceF%p, IceF%x(STATE_CURR), IceF%xd(STATE_CURR), IceF%z(STATE_CURR), & + IceF%OtherSt(STATE_CURR), IceF%y, IceF%m, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%ModuleInitialized(Module_IceD) ) THEN + + DO i=1,p_FAST%numIceLegs + CALL IceD_End(IceD%Input(1,i), IceD%p(i), IceD%x(i,STATE_CURR), IceD%xd(i,STATE_CURR), IceD%z(i,STATE_CURR), & + IceD%OtherSt(i,STATE_CURR), IceD%y(i), IceD%m(i), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END DO + + END IF + +END SUBROUTINE FAST_EndMods +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calls the destroy routines for each module. (It is basically a duplicate of FAST_DestroyTurbineType().) +SUBROUTINE FAST_DestroyAll( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn v14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyAll' + + + + ! ------------------------------------------------------------------------- + ! Deallocate/Destroy structures associated with mesh mapping + ! ------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = "" + + + ! FAST + CALL FAST_DestroyParam( p_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL FAST_DestroyOutputFileType( y_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL FAST_DestroyMisc( m_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ElastoDyn + CALL FAST_DestroyElastoDyn_Data( ED, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! BeamDyn + CALL FAST_DestroyBeamDyn_Data( BD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ServoDyn + CALL FAST_DestroyServoDyn_Data( SrvD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! AeroDyn14 + CALL FAST_DestroyAeroDyn14_Data( AD14, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! AeroDyn + CALL FAST_DestroyAeroDyn_Data( AD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! InflowWind + CALL FAST_DestroyInflowWind_Data( IfW, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! OpenFOAM + CALL FAST_DestroyOpenFOAM_Data( OpFM, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HydroDyn + CALL FAST_DestroyHydroDyn_Data( HD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! SubDyn + CALL FAST_DestroySubDyn_Data( SD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ExtPtfm + CALL FAST_DestroyExtPtfm_Data( ExtPtfm, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! MAP + CALL FAST_DestroyMAP_Data( MAPp, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! FEAMooring + CALL FAST_DestroyFEAMooring_Data( FEAM, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! MoorDyn + CALL FAST_DestroyMoorDyn_Data( MD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Orca + CALL FAST_DestroyOrcaFlex_Data( Orca, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! IceFloe + CALL FAST_DestroyIceFloe_Data( IceF, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! IceDyn + CALL FAST_DestroyIceDyn_Data( IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Module (Mesh) Mapping data + CALL FAST_DestroyModuleMapType( MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + + END SUBROUTINE FAST_DestroyAll +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! CHECKPOINT/RESTART ROUTINES +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine that calls FAST_CreateCheckpoint_T for an array of Turbine data structures. +SUBROUTINE FAST_CreateCheckpoint_Tary(t_initial, n_t_global, Turbine, CheckpointRoot, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< loop counter + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine(:) !< all data for all turbines + CHARACTER(*), INTENT(IN ) :: CheckpointRoot !< Rootname of checkpoint file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: NumTurbines ! Number of turbines in this simulation + INTEGER(IntKi) :: i_turb + INTEGER :: Unit + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CreateCheckpoint_Tary' + + + NumTurbines = SIZE(Turbine) + ErrStat = ErrID_None + ErrMsg = "" + + ! TRIM(CheckpointRoot)//'.'//TRIM(Num2LStr(Turbine%TurbID))// + + !! This allows us to put all the turbine data in one file. + Unit = -1 + DO i_turb = 1,NumTurbines + CALL FAST_CreateCheckpoint_T(t_initial, n_t_global, NumTurbines, Turbine(i_turb), CheckpointRoot, ErrStat2, ErrMsg2, Unit ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev ) then + if (Unit > 0) close(Unit) + RETURN + end if + + END DO + + +END SUBROUTINE FAST_CreateCheckpoint_Tary +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that packs all of the data from one turbine instance into arrays and writes checkpoint files. If Unit is present and +!! greater than 0, it will append the data to an already open file. Otherwise, it opens a new file and writes header information +!! before writing the turbine data to the file. +SUBROUTINE FAST_CreateCheckpoint_T(t_initial, n_t_global, NumTurbines, Turbine, CheckpointRoot, ErrStat, ErrMsg, Unit ) + + USE BladedInterface, ONLY: CallBladedDLL ! Hack for Bladed-style DLL + USE BladedInterface, ONLY: GH_DISCON_STATUS_CHECKPOINT + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + INTEGER(IntKi), INTENT(IN ) :: n_t_global !< loop counter + INTEGER(IntKi), INTENT(IN ) :: NumTurbines !< Number of turbines in this simulation + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine (INTENT(OUT) only because of hack for Bladed DLL) + CHARACTER(*), INTENT(IN ) :: CheckpointRoot !< Rootname of checkpoint file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), OPTIONAL, INTENT(INOUT) :: Unit !< unit number for output file + + ! local variables: + REAL(ReKi), ALLOCATABLE :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE :: IntKiBuf(:) + + INTEGER(B4Ki) :: ArraySizes(3) + + INTEGER(IntKi) :: unOut ! unit number for output file + INTEGER(IntKi) :: old_avrSwap1 ! previous value of avrSwap(1) !hack for Bladed DLL checkpoint/restore + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CreateCheckpoint_T' + + CHARACTER(1024) :: FileName ! Name of the (output) checkpoint file + CHARACTER(1024) :: DLLFileName ! Name of the (output) checkpoint file + + ! init error status + ErrStat = ErrID_None + ErrMsg = "" + + ! Get the arrays of data to be stored in the output file + CALL FAST_PackTurbineType( ReKiBuf, DbKiBuf, IntKiBuf, Turbine, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if + + + ArraySizes = 0 + IF ( ALLOCATED(ReKiBuf) ) ArraySizes(1) = SIZE(ReKiBuf) + IF ( ALLOCATED(DbKiBuf) ) ArraySizes(2) = SIZE(DbKiBuf) + IF ( ALLOCATED(IntKiBuf) ) ArraySizes(3) = SIZE(IntKiBuf) + + FileName = TRIM(CheckpointRoot)//'.chkp' + DLLFileName = TRIM(CheckpointRoot)//'.dll.chkp' + + unOut=-1 + IF (PRESENT(Unit)) unOut = Unit + + IF ( unOut < 0 ) THEN + + CALL GetNewUnit( unOut, ErrStat2, ErrMsg2 ) + CALL OpenBOutFile ( unOut, FileName, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev ) then + call cleanup() + IF (.NOT. PRESENT(Unit)) THEN + CLOSE(unOut) + unOut = -1 + END IF + + RETURN + end if + + ! checkpoint file header: + WRITE (unOut, IOSTAT=ErrStat2) INT(ReKi ,B4Ki) ! let's make sure we've got the correct number of bytes for reals on restart. + WRITE (unOut, IOSTAT=ErrStat2) INT(DbKi ,B4Ki) ! let's make sure we've got the correct number of bytes for doubles on restart. + WRITE (unOut, IOSTAT=ErrStat2) INT(IntKi ,B4Ki) ! let's make sure we've got the correct number of bytes for integers on restart. + WRITE (unOut, IOSTAT=ErrStat2) AbortErrLev + WRITE (unOut, IOSTAT=ErrStat2) NumTurbines ! Number of turbines + WRITE (unOut, IOSTAT=ErrStat2) t_initial ! initial time + WRITE (unOut, IOSTAT=ErrStat2) n_t_global ! current time step + + END IF + + + ! data from current turbine at time step: + WRITE (unOut, IOSTAT=ErrStat2) ArraySizes ! Number of reals, doubles, and integers written to file + WRITE (unOut, IOSTAT=ErrStat2) ReKiBuf ! Packed reals + WRITE (unOut, IOSTAT=ErrStat2) DbKiBuf ! Packed doubles + WRITE (unOut, IOSTAT=ErrStat2) IntKiBuf ! Packed integers + + + IF ( ALLOCATED(ReKiBuf) ) DEALLOCATE(ReKiBuf) + IF ( ALLOCATED(DbKiBuf) ) DEALLOCATE(DbKiBuf) + IF ( ALLOCATED(IntKiBuf) ) DEALLOCATE(IntKiBuf) + + !CALL FAST_CreateCheckpoint(t_initial, n_t_global, Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, & + ! Turbine%ED, Turbine%SrvD, Turbine%AD, Turbine%IfW, & + ! Turbine%HD, Turbine%SD, Turbine%MAP, Turbine%FEAM, Turbine%MD, & + ! Turbine%IceF, Turbine%IceD, Turbine%MeshMapData, ErrStat, ErrMsg ) + + + IF (Turbine%TurbID == NumTurbines .OR. .NOT. PRESENT(Unit)) THEN + CLOSE(unOut) + unOut = -1 + END IF + + IF (PRESENT(Unit)) Unit = unOut + + ! A hack to pack Bladed-style DLL data + IF (Turbine%SrvD%p%UseBladedInterface) THEN + if (Turbine%SrvD%m%dll_data%avrSWAP( 1) > 0 ) then + ! store value to be overwritten + old_avrSwap1 = Turbine%SrvD%m%dll_data%avrSWAP( 1) + FileName = Turbine%SrvD%m%dll_data%DLL_InFile + ! overwrite values: + Turbine%SrvD%m%dll_data%DLL_InFile = DLLFileName + Turbine%SrvD%m%dll_data%avrSWAP(50) = REAL( LEN_TRIM(DLLFileName) ) +1 ! No. of characters in the "INFILE" argument (-) (we add one for the C NULL CHARACTER) + Turbine%SrvD%m%dll_data%avrSWAP( 1) = GH_DISCON_STATUS_CHECKPOINT + Turbine%SrvD%m%dll_data%SimStatus = Turbine%SrvD%m%dll_data%avrSWAP( 1) + CALL CallBladedDLL(Turbine%SrvD%Input(1), Turbine%SrvD%p, Turbine%SrvD%m%dll_data, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! put values back: + Turbine%SrvD%m%dll_data%DLL_InFile = FileName + Turbine%SrvD%m%dll_data%avrSWAP(50) = REAL( LEN_TRIM(FileName) ) +1 ! No. of characters in the "INFILE" argument (-) (we add one for the C NULL CHARACTER) + Turbine%SrvD%m%dll_data%avrSWAP( 1) = old_avrSwap1 + Turbine%SrvD%m%dll_data%SimStatus = Turbine%SrvD%m%dll_data%avrSWAP( 1) + end if + END IF + + call cleanup() + +contains + subroutine cleanup() + IF ( ALLOCATED(ReKiBuf) ) DEALLOCATE(ReKiBuf) + IF ( ALLOCATED(DbKiBuf) ) DEALLOCATE(DbKiBuf) + IF ( ALLOCATED(IntKiBuf) ) DEALLOCATE(IntKiBuf) + end subroutine cleanup +END SUBROUTINE FAST_CreateCheckpoint_T +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calls FAST_RestoreFromCheckpoint_T for an array of Turbine data structures. +SUBROUTINE FAST_RestoreFromCheckpoint_Tary(t_initial, n_t_global, Turbine, CheckpointRoot, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time (for comparing with time from checkpoint file) + INTEGER(IntKi), INTENT( OUT) :: n_t_global !< loop counter + TYPE(FAST_TurbineType), INTENT( OUT) :: Turbine(:) !< all data for one instance of a turbine + CHARACTER(*), INTENT(IN ) :: CheckpointRoot !< Rootname of checkpoint file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: t_initial_out + INTEGER(IntKi) :: NumTurbines_out + INTEGER(IntKi) :: NumTurbines ! Number of turbines in this simulation + INTEGER(IntKi) :: i_turb + INTEGER :: Unit + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_RestoreFromCheckpoint_Tary' + + + NumTurbines = SIZE(Turbine) + ErrStat = ErrID_None + ErrMsg = "" + + ! Init NWTC_Library, display copyright and version information: + CALL FAST_ProgStart( FAST_Ver ) + + ! Restore data from checkpoint file + Unit = -1 + DO i_turb = 1,NumTurbines + CALL FAST_RestoreFromCheckpoint_T(t_initial_out, n_t_global, NumTurbines_out, Turbine(i_turb), CheckpointRoot, ErrStat2, ErrMsg2, Unit ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (t_initial_out /= t_initial) CALL SetErrStat(ErrID_Fatal, "invalid value of t_initial.", ErrStat, ErrMsg, RoutineName ) + IF (NumTurbines_out /= NumTurbines) CALL SetErrStat(ErrID_Fatal, "invalid value of NumTurbines.", ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + END DO + + CALL WrScr( ' Restarting simulation at '//TRIM(Num2LStr(n_t_global*Turbine(1)%p_FAST%DT))//' seconds.' ) + + +END SUBROUTINE FAST_RestoreFromCheckpoint_Tary +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is the inverse of FAST_CreateCheckpoint_T. It reads data from a checkpoint file and populates data structures for +!! the turbine instance. +SUBROUTINE FAST_RestoreFromCheckpoint_T(t_initial, n_t_global, NumTurbines, Turbine, CheckpointRoot, ErrStat, ErrMsg, Unit ) + USE BladedInterface, ONLY: CallBladedDLL ! Hack for Bladed-style DLL + USE BladedInterface, ONLY: GH_DISCON_STATUS_RESTARTING + + REAL(DbKi), INTENT(INOUT) :: t_initial !< initial time + INTEGER(IntKi), INTENT(INOUT) :: n_t_global !< loop counter + INTEGER(IntKi), INTENT(INOUT) :: NumTurbines !< Number of turbines in this simulation + TYPE(FAST_TurbineType), INTENT(INOUT) :: Turbine !< all data for one instance of a turbine (bjj: note that is intent INOUT instead of OUT only because of a gfortran compiler memory issue) + CHARACTER(*), INTENT(IN ) :: CheckpointRoot !< Rootname of checkpoint file + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), OPTIONAL, INTENT(INOUT) :: Unit !< unit number for output file + + ! local variables: + REAL(ReKi), ALLOCATABLE :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE :: IntKiBuf(:) + + INTEGER(B4Ki) :: ArraySizes(3) + + INTEGER(IntKi) :: unIn ! unit number for input file + INTEGER(IntKi) :: old_avrSwap1 ! previous value of avrSwap(1) !hack for Bladed DLL checkpoint/restore + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_RestoreFromCheckpoint_T' + + CHARACTER(1024) :: FileName ! Name of the (input) checkpoint file + CHARACTER(1024) :: DLLFileName ! Name of the (input) checkpoint file + + + ErrStat=ErrID_None + ErrMsg="" + + FileName = TRIM(CheckpointRoot)//'.chkp' + DLLFileName = TRIM(CheckpointRoot)//'.dll.chkp' + ! FileName = TRIM(CheckpointRoot)//'.cp' + unIn=-1 + IF (PRESENT(Unit)) unIn = Unit + + IF ( unIn < 0 ) THEN + + CALL GetNewUnit( unIn, ErrStat2, ErrMsg2 ) + + CALL OpenBInpFile ( unIn, FileName, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev ) RETURN + + ! checkpoint file header: + READ (unIn, IOSTAT=ErrStat2) ArraySizes ! let's make sure we've got the correct number of bytes for reals, doubles, and integers on restart. + + IF ( ArraySizes(1) /= ReKi ) CALL SetErrStat(ErrID_Fatal,"ReKi on restart is different than when checkpoint file was created.",ErrStat,ErrMsg,RoutineName) + IF ( ArraySizes(2) /= DbKi ) CALL SetErrStat(ErrID_Fatal,"DbKi on restart is different than when checkpoint file was created.",ErrStat,ErrMsg,RoutineName) + IF ( ArraySizes(3) /= IntKi ) CALL SetErrStat(ErrID_Fatal,"IntKi on restart is different than when checkpoint file was created.",ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CLOSE(unIn) + unIn = -1 + IF (PRESENT(Unit)) Unit = unIn + RETURN + END IF + + READ (unIn, IOSTAT=ErrStat2) AbortErrLev + READ (unIn, IOSTAT=ErrStat2) NumTurbines ! Number of turbines + READ (unIn, IOSTAT=ErrStat2) t_initial ! initial time + READ (unIn, IOSTAT=ErrStat2) n_t_global ! current time step + + END IF + + ! in case the Turbine data structure isn't empty on entry of this routine: + call FAST_DestroyTurbineType( Turbine, ErrStat2, ErrMsg2 ) + + ! data from current time step: + READ (unIn, IOSTAT=ErrStat2) ArraySizes ! Number of reals, doubles, and integers written to file + + ALLOCATE(ReKiBuf( ArraySizes(1)), STAT=ErrStat2) + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not allocate ReKiBuf", ErrStat, ErrMsg, RoutineName ) + ALLOCATE(DbKiBuf( ArraySizes(2)), STAT=ErrStat2) + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not allocate DbKiBuf", ErrStat, ErrMsg, RoutineName ) + ALLOCATE(IntKiBuf(ArraySizes(3)), STAT=ErrStat2) + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not allocate IntKiBuf", ErrStat, ErrMsg, RoutineName ) + + ! Read the packed arrays + IF (ErrStat < AbortErrLev) THEN + + READ (unIn, IOSTAT=ErrStat2) ReKiBuf ! Packed reals + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not read ReKiBuf", ErrStat, ErrMsg, RoutineName ) + READ (unIn, IOSTAT=ErrStat2) DbKiBuf ! Packed doubles + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not read DbKiBuf", ErrStat, ErrMsg, RoutineName ) + READ (unIn, IOSTAT=ErrStat2) IntKiBuf ! Packed integers + IF (ErrStat2 /=0) CALL SetErrStat(ErrID_Fatal, "Could not read IntKiBuf", ErrStat, ErrMsg, RoutineName ) + + END IF + + ! Put the arrays back in the data types + IF (ErrStat < AbortErrLev) THEN + CALL FAST_UnpackTurbineType( ReKiBuf, DbKiBuf, IntKiBuf, Turbine, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! close file if necessary (do this after unpacking turbine data, so that TurbID is set) + IF (Turbine%TurbID == NumTurbines .OR. .NOT. PRESENT(Unit)) THEN + CLOSE(unIn) + unIn = -1 + END IF + + IF (PRESENT(Unit)) Unit = unIn + + + IF ( ALLOCATED(ReKiBuf) ) DEALLOCATE(ReKiBuf) + IF ( ALLOCATED(DbKiBuf) ) DEALLOCATE(DbKiBuf) + IF ( ALLOCATED(IntKiBuf) ) DEALLOCATE(IntKiBuf) + + + ! A sort-of hack to restore MAP DLL data (in particular Turbine%MAP%OtherSt%C_Obj%object) + ! these must be the same variables that are used in MAP_Init because they get allocated in the DLL and + ! destroyed in MAP_End (also, inside the DLL) + IF (Turbine%p_FAST%CompMooring == Module_MAP) THEN + CALL MAP_Restart( Turbine%MAP%Input(1), Turbine%MAP%p, Turbine%MAP%x(STATE_CURR), Turbine%MAP%xd(STATE_CURR), & + Turbine%MAP%z(STATE_CURR), Turbine%MAP%OtherSt, Turbine%MAP%y, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + ! A hack to restore Bladed-style DLL data + if (Turbine%SrvD%p%UseBladedInterface) then + if (Turbine%SrvD%m%dll_data%avrSWAP( 1) > 0 ) then ! this isn't allocated if UseBladedInterface is FALSE + ! store value to be overwritten + old_avrSwap1 = Turbine%SrvD%m%dll_data%avrSWAP( 1) + FileName = Turbine%SrvD%m%dll_data%DLL_InFile + ! overwrite values before calling DLL: + Turbine%SrvD%m%dll_data%DLL_InFile = DLLFileName + Turbine%SrvD%m%dll_data%avrSWAP(50) = REAL( LEN_TRIM(DLLFileName) ) +1 ! No. of characters in the "INFILE" argument (-) (we add one for the C NULL CHARACTER) + Turbine%SrvD%m%dll_data%avrSWAP( 1) = GH_DISCON_STATUS_RESTARTING + Turbine%SrvD%m%dll_data%SimStatus = Turbine%SrvD%m%dll_data%avrSWAP( 1) + CALL CallBladedDLL(Turbine%SrvD%Input(1), Turbine%SrvD%p, Turbine%SrvD%m%dll_data, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! put values back: + Turbine%SrvD%m%dll_data%DLL_InFile = FileName + Turbine%SrvD%m%dll_data%avrSWAP(50) = REAL( LEN_TRIM(FileName) ) +1 ! No. of characters in the "INFILE" argument (-) (we add one for the C NULL CHARACTER) + Turbine%SrvD%m%dll_data%avrSWAP( 1) = old_avrSwap1 + Turbine%SrvD%m%dll_data%SimStatus = Turbine%SrvD%m%dll_data%avrSWAP( 1) + end if + end if + + ! deal with sibling meshes here: + ! (ignoring for now; they are not going to be siblings on restart) + + ! deal with files that were open: + IF (Turbine%p_FAST%WrTxtOutFile) THEN + CALL OpenFunkFileAppend ( Turbine%y_FAST%UnOu, TRIM(Turbine%p_FAST%OutFileRoot)//'.out', ErrStat2, ErrMsg2) + IF ( ErrStat2 >= AbortErrLev ) RETURN + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL WrFileNR ( Turbine%y_FAST%UnOu, '#Restarting here') + WRITE(Turbine%y_FAST%UnOu, '()') + END IF + ! (ignoring for now; will have fort.x files if any were open [though I printed a warning about not outputting binary files earlier]) + + +END SUBROUTINE FAST_RestoreFromCheckpoint_T +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calls FAST_RestoreForVTKModeShape_T for an array of Turbine data structures. +SUBROUTINE FAST_RestoreForVTKModeShape_Tary(t_initial, Turbine, InputFileName, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time (for comparing with time from checkpoint file) + TYPE(FAST_TurbineType), INTENT( OUT) :: Turbine(:) !< all data for one instance of a turbine + CHARACTER(*), INTENT(IN ) :: InputFileName !< Name of the input file + 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_turb + INTEGER(IntKi) :: n_t_global !< loop counter + INTEGER(IntKi) :: NumTurbines ! Number of turbines in this simulation + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_RestoreForVTKModeShape_Tary' + + + ErrStat = ErrID_None + ErrMsg = "" + + NumTurbines = SIZE(Turbine) + if (NumTurbines /=1) then + call SetErrStat(ErrID_Fatal, "Mode-shape visualization is not available for multiple turbines.", ErrStat, ErrMsg, RoutineName) + return + end if + + + CALL ReadModeShapeFile( Turbine(1)%p_FAST, trim(InputFileName), ErrStat2, ErrMsg2, checkpointOnly=.true. ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + CALL FAST_RestoreFromCheckpoint_Tary( t_initial, n_t_global, Turbine, trim(Turbine(1)%p_FAST%VTK_modes%CheckpointRoot), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + DO i_turb = 1,NumTurbines + if (.not. allocated(Turbine(i_turb)%m_FAST%Lin%LinTimes)) then + call SetErrStat(ErrID_Fatal, "Mode-shape visualization requires a checkpoint file from a simulation with linearization analysis, but NLinTimes is 0.", ErrStat, ErrMsg, RoutineName) + return + end if + + CALL FAST_RestoreForVTKModeShape_T(t_initial, Turbine(i_turb)%p_FAST, Turbine(i_turb)%y_FAST, Turbine(i_turb)%m_FAST, & + Turbine(i_turb)%ED, Turbine(i_turb)%BD, Turbine(i_turb)%SrvD, Turbine(i_turb)%AD14, Turbine(i_turb)%AD, Turbine(i_turb)%IfW, Turbine(i_turb)%OpFM, & + Turbine(i_turb)%HD, Turbine(i_turb)%SD, Turbine(i_turb)%ExtPtfm, Turbine(i_turb)%MAP, Turbine(i_turb)%FEAM, Turbine(i_turb)%MD, Turbine(i_turb)%Orca, & + Turbine(i_turb)%IceF, Turbine(i_turb)%IceD, Turbine(i_turb)%MeshMapData, trim(InputFileName), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + +END SUBROUTINE FAST_RestoreForVTKModeShape_Tary + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the motions generated by mode shapes and outputs VTK data for it +SUBROUTINE FAST_RestoreForVTKModeShape_T(t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, InputFileName, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t_initial !< initial time + + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code + TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables + + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ED !< ElastoDyn data + TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BeamDyn data + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrvD !< ServoDyn data + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AD14 !< AeroDyn14 data + TYPE(AeroDyn_Data), INTENT(INOUT) :: AD !< AeroDyn data + TYPE(InflowWind_Data), INTENT(INOUT) :: IfW !< InflowWind data + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM !< OpenFOAM data + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HydroDyn data + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SubDyn data + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm !< ExtPtfm_MCKF data + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAM !< FEAMooring data + TYPE(MoorDyn_Data), INTENT(INOUT) :: MD !< Data for the MoorDyn module + TYPE(OrcaFlex_Data), INTENT(INOUT) :: Orca !< OrcaFlex interface data + TYPE(IceFloe_Data), INTENT(INOUT) :: IceF !< IceFloe data + TYPE(IceDyn_Data), INTENT(INOUT) :: IceD !< All the IceDyn data used in time-step loop + + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + CHARACTER(*), INTENT(IN ) :: InputFileName !< Name of the input file + + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + REAL(DbKi) :: dt ! time + REAL(DbKi) :: tprime ! time + INTEGER(IntKi) :: nt + + INTEGER(IntKi) :: iLinTime ! generic loop counters + INTEGER(IntKi) :: it ! generic loop counters + INTEGER(IntKi) :: iMode ! generic loop counters + INTEGER(IntKi) :: ModeNo ! mode number + INTEGER(IntKi) :: NLinTimes + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_RestoreForVTKModeShape_T' + CHARACTER(1024) :: VTK_RootName + + + ErrStat = ErrID_None + ErrMsg = "" + + CALL ReadModeShapeFile( p_FAST, trim(InputFileName), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev) return + + call ReadModeShapeMatlabFile( p_FAST, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat >= AbortErrLev ) return + + y_FAST%WriteThisStep = .true. + y_FAST%UnSum = -1 + + NLinTimes = min( p_FAST%VTK_modes%VTKNLinTimes, size(p_FAST%VTK_modes%x_eig_magnitude,2), p_FAST%NLinTimes ) + + VTK_RootName = p_FAST%VTK_OutFileRoot + + select case (p_FAST%VTK_modes%VTKLinTim) + case (1) + + do iMode = 1,p_FAST%VTK_modes%VTKLinModes + ModeNo = p_FAST%VTK_modes%VTKModes(iMode) + + call GetTimeConstants(p_FAST%VTK_modes%DampedFreq_Hz(ModeNo), p_FAST%VTK_fps, nt, dt, p_FAST%VTK_tWidth ) + if (nt > 500) cycle + + p_FAST%VTK_OutFileRoot = trim(VTK_RootName)//'.Mode'//trim(num2lstr(ModeNo)) + y_FAST%VTK_count = 1 ! we are skipping the reference meshes by starting at 1 + do iLinTime = 1,NLinTimes + tprime = m_FAST%Lin%LinTimes(iLinTime) - m_FAST%Lin%LinTimes(1) + + if (p_FAST%DT_UJac < p_FAST%TMax) then + m_FAST%calcJacobian = .true. + m_FAST%NextJacCalcTime = m_FAST%Lin%LinTimes(iLinTime) + end if + + call SetOperatingPoint(iLinTime, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! set perturbation of states based on x_eig magnitude and phase + call PerturbOP(tprime, iLinTime, ModeNo, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CalcOutputs_And_SolveForInputs( -1, m_FAST%Lin%LinTimes(iLinTime), STATE_CURR, m_FAST%calcJacobian, m_FAST%NextJacCalcTime, & + p_FAST, m_FAST, .true., ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + call WriteVTK(m_FAST%Lin%LinTimes(iLinTime), p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + + end do ! iLinTime + end do ! iMode + + case (2) + + do iMode = 1,p_FAST%VTK_modes%VTKLinModes + ModeNo = p_FAST%VTK_modes%VTKModes(iMode) + + call GetTimeConstants(p_FAST%VTK_modes%DampedFreq_Hz(ModeNo), p_FAST%VTK_fps, nt, dt, p_FAST%VTK_tWidth ) + if (nt > 500) cycle + + do iLinTime = 1,NLinTimes + p_FAST%VTK_OutFileRoot = trim(VTK_RootName)//'.Mode'//trim(num2lstr(ModeNo))//'.LinTime'//trim(num2lstr(iLinTime)) + y_FAST%VTK_count = 1 ! we are skipping the reference meshes by starting at 1 + + if (p_FAST%DT_UJac < p_FAST%TMax) then + m_FAST%calcJacobian = .true. + m_FAST%NextJacCalcTime = m_FAST%Lin%LinTimes(iLinTime) + end if + + do it = 1,nt + tprime = (it-1)*dt + + call SetOperatingPoint(iLinTime, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, & + MAPp, FEAM, MD, Orca, IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! set perturbation of states based on x_eig magnitude and phase + call PerturbOP(tprime, iLinTime, ModeNo, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & + IceF, IceD, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL CalcOutputs_And_SolveForInputs( -1, m_FAST%Lin%LinTimes(iLinTime), STATE_CURR, m_FAST%calcJacobian, m_FAST%NextJacCalcTime, & + p_FAST, m_FAST, .true., ED, BD, SrvD, AD14, AD, IfW, OpFM, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + call WriteVTK(m_FAST%Lin%LinTimes(iLinTime)+tprime, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, HD, SD, ExtPtfm, SrvD, MAPp, FEAM, MD, Orca, IceF, IceD) + + end do + + + end do ! iLinTime + end do ! iMode + + end select + +END SUBROUTINE FAST_RestoreForVTKModeShape_T +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE GetTimeConstants(DampedFreq_Hz, VTK_fps, nt, dt, VTK_tWidth ) + REAL(R8Ki), INTENT(IN ) :: DampedFreq_Hz + REAL(DbKi), INTENT(IN ) :: VTK_fps + INTEGER(IntKi), INTENT( OUT) :: nt !< number of steps + REAL(DbKi), INTENT( OUT) :: dt !< time step + INTEGER(IntKi), INTENT( OUT) :: VTK_tWidth + + REAL(DbKi) :: cycle_time ! time for one cycle of mode + INTEGER(IntKi) :: NCycles + INTEGER(IntKi), PARAMETER :: MinFrames = 5 + + if (DampedFreq_Hz <= 0.0_DbKi) then + nt = huge(nt) + dt = epsilon(dt) + VTK_tWidth = 1 + return + end if + + nt = 1 + NCycles = 0 + do while (nt<MinFrames) + NCycles = NCycles + 1 + cycle_time = NCycles * 1.0_DbKi / DampedFreq_Hz + + nt = NINT( max(1.0_DbKi, VTK_fps) * cycle_time ) + end do + + dt = cycle_time / nt + + VTK_tWidth = CEILING( log10( real(nt) ) ) + 1 + +END SUBROUTINE GetTimeConstants +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadModeShapeMatlabFile(p_FAST, ErrStat, ErrMsg) + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ReadModeShapeMatlabFile' + + INTEGER(4) :: FileType + INTEGER(4) :: nModes + INTEGER(4) :: nStates + INTEGER(4) :: NLinTimes + INTEGER(IntKi) :: iMode + INTEGER(IntKi) :: UnIn + + ErrStat = ErrID_None + ErrMsg = "" + + ! Open data file. + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + + CALL OpenBInpFile ( UnIn, trim(p_FAST%VTK_modes%MatlabFileName), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Process the requested data records of this file. + + CALL WrScr ( NewLine//' =======================================================' ) + CALL WrScr ( ' Reading in data from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".'//NewLine ) + + + ! Read some of the header information. + + READ (UnIn, IOSTAT=ErrStat2) FileType ! placeholder for future file format changes + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading FileType from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) nModes ! number of modes in the file + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading nModes from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) nStates ! number of states in the file + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading nStates from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ (UnIn, IOSTAT=ErrStat2) NLinTimes ! number of linearization times / azimuths in the file + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading NLinTimes from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ALLOCATE( p_FAST%VTK_Modes%NaturalFreq_Hz(nModes), & + p_FAST%VTK_Modes%DampingRatio( nModes), & + p_FAST%VTK_Modes%DampedFreq_Hz( nModes), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating arrays to read from file.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + + READ(UnIn, IOSTAT=ErrStat2) p_FAST%VTK_Modes%NaturalFreq_Hz ! read entire array + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading NaturalFreq_Hz array from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ(UnIn, IOSTAT=ErrStat2) p_FAST%VTK_Modes%DampingRatio ! read entire array + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading DampingRatio array from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ(UnIn, IOSTAT=ErrStat2) p_FAST%VTK_Modes%DampedFreq_Hz ! read entire array + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading DampedFreq_Hz array from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + if (nModes < p_FAST%VTK_Modes%VTKLinModes) CALL SetErrStat(ErrID_Severe,'Number of modes requested exceeds the number of modes in the linearization analysis file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName) + if (NLinTimes /= p_FAST%NLinTimes) CALL SetErrStat(ErrID_Severe,'Number of times linearization was performed is not the same as the number of linearization times in the linearization analysis file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName) + + + !Let's read only the number of modes we need to use + nModes = min( nModes, p_FAST%VTK_Modes%VTKLinModes ) + + ALLOCATE( p_FAST%VTK_Modes%x_eig_magnitude(nStates, NLinTimes, nModes), & + p_FAST%VTK_Modes%x_eig_phase( nStates, NLinTimes, nModes), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating arrays to read from file.', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + do iMode = 1,nModes + + READ(UnIn, IOSTAT=ErrStat2) p_FAST%VTK_Modes%x_eig_magnitude(:,:,iMode) ! read data for one mode + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading x_eig_magnitude from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + READ(UnIn, IOSTAT=ErrStat2) p_FAST%VTK_Modes%x_eig_phase(:,:,iMode) ! read data for one mode + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat ( ErrID_Fatal, 'Fatal error reading x_eig_phase from file "'//TRIM( p_FAST%VTK_modes%MatlabFileName )//'".', ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + end do + +END SUBROUTINE ReadModeShapeMatlabFile +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE ReadModeShapeFile(p_FAST, InputFile, ErrStat, ErrMsg, checkpointOnly) + TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code + CHARACTER(*), INTENT(IN ) :: InputFile !< Name of the text input file to read + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + LOGICAL, OPTIONAL, INTENT(IN ) :: checkpointOnly !< Whether to return after reading checkpoint file name + + ! local variables + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ReadModeShapeFile' + + CHARACTER(1024) :: PriPath ! Path name of the primary file + INTEGER(IntKi) :: i + INTEGER(IntKi) :: UnIn + INTEGER(IntKi) :: UnEc + LOGICAL :: VTKLinTimes1 + + ErrStat = ErrID_None + ErrMsg = "" + UnEc = -1 + + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + ! Open data file. + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + + CALL ReadCom( UnIn, InputFile, 'File header: (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadCom( UnIn, InputFile, 'File header: (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !----------- FILE NAMES ---------------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: File Names', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%CheckpointRoot, 'CheckpointRoot', 'Name of the checkpoint file written by FAST when linearization data was produced', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF ( PathIsRelative( p_FAST%VTK_modes%CheckpointRoot ) ) p_FAST%VTK_modes%CheckpointRoot = TRIM(PriPath)//TRIM(p_FAST%VTK_modes%CheckpointRoot) + + if (present(checkpointOnly)) then + if (checkpointOnly) then + call cleanup() + return + end if + end if + + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%MatlabFileName, 'MatlabFileName', 'Name of the file with eigenvectors written by Matlab', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( p_FAST%VTK_modes%MatlabFileName ) ) p_FAST%VTK_modes%MatlabFileName = TRIM(PriPath)//TRIM(p_FAST%VTK_modes%MatlabFileName) + + !----------- VISUALIZATION OPTIONS ------------------------------------------ + + CALL ReadCom( UnIn, InputFile, 'Section Header: Visualization Options', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%VTKLinModes, 'VTKLinModes', 'Number of modes to visualize', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + if (p_FAST%VTK_modes%VTKLinModes <= 0) CALL SetErrStat( ErrID_Fatal, "VTKLinModes must be a positive number.", ErrStat, ErrMsg, RoutineName ) + + if (ErrStat >= AbortErrLev) then + CALL Cleanup() + RETURN + end if + + + call AllocAry( p_FAST%VTK_modes%VTKModes, p_FAST%VTK_modes%VTKLinModes, 'VTKModes', ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if ( ErrStat >= AbortErrLev ) then + call Cleanup() + return + end if + + p_FAST%VTK_modes%VTKModes = -1 + + CALL ReadAry( UnIn, InputFile, p_FAST%VTK_modes%VTKModes, p_FAST%VTK_modes%VTKLinModes, 'VTKModes', 'List of modes to visualize', ErrStat2, ErrMsg2, UnEc ) + ! note that we don't check the ErrStat here; if the user entered fewer than p_FAST%VTK_modes%VTKLinModes values, we will use the + ! last entry to fill in remaining values. + !Check 1st value, we need at least one good value from user or throw error + IF (p_FAST%VTK_modes%VTKModes(1) < 0 ) THEN + call SetErrStat( ErrID_Fatal, "VTKModes must contain positive numbers.", ErrStat, ErrMsg, RoutineName ) + CALL CleanUp() + RETURN + ELSE + DO i = 2, p_FAST%VTK_modes%VTKLinModes + IF ( p_FAST%VTK_modes%VTKModes(i) < 0 ) THEN + p_FAST%VTK_modes%VTKModes(i)=p_FAST%VTK_modes%VTKModes(i-1) + 1 + ENDIF + ENDDO + ENDIF + + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%VTKLinScale, 'VTKLinScale', 'Mode shape visualization scaling factor', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%VTKLinTim, 'VTKLinTim', 'Switch to make one animation for all LinTimes together (1) or separate animations for each LinTimes(2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + CALL ReadVar( UnIn, InputFile, VTKLinTimes1, 'VTKLinTimes1', 'If VTKLinTim=2, visualize modes at LinTimes(1) only?', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + CALL ReadVar( UnIn, InputFile, p_FAST%VTK_modes%VTKLinPhase, 'VTKLinPhase', 'Phase when making one animation for all LinTimes together (used only when VTKLinTim=1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + +! overwrite these based on inputs: + + if (p_FAST%VTK_modes%VTKLinTim == 2) then + p_FAST%VTK_modes%VTKLinPhase = 0 ! "Phase when making one animation for all LinTimes together (used only when VTKLinTim=1)" - + + if (VTKLinTimes1) then + p_FAST%VTK_modes%VTKNLinTimes = 1 + else + p_FAST%VTK_modes%VTKNLinTimes = p_FAST%NLinTimes + end if + else + p_FAST%VTK_modes%VTKNLinTimes = p_FAST%NLinTimes + end if + +contains + SUBROUTINE Cleanup() + IF (UnIn > 0) CLOSE(UnIn) + END SUBROUTINE Cleanup + +END SUBROUTINE ReadModeShapeFile +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE FAST_Subs +!---------------------------------------------------------------------------------------------------------------------------------- diff --git a/OpenFAST/modules/openfast-library/src/FAST_Types.f90 b/OpenFAST/modules/openfast-library/src/FAST_Types.f90 new file mode 100644 index 000000000..5fae28075 --- /dev/null +++ b/OpenFAST/modules/openfast-library/src/FAST_Types.f90 @@ -0,0 +1,46499 @@ +!STARTOFREGISTRYGENERATEDFILE 'FAST_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 +!********************************************************************************************************************************* +! FAST_Types +!................................................................................................................................. +! This file is part of FAST. +! +! 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 FAST. 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 FAST_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE ElastoDyn_Types +USE BeamDyn_Types +USE TMD_Types +USE ServoDyn_Types +USE IfW_UniformWind_Types +USE IfW_FFWind_Base_Types +USE IfW_TSFFWind_Types +USE IfW_BladedFFWind_Types +USE IfW_HAWCWind_Types +USE IfW_UserWind_Types +USE IfW_4Dext_Types +USE Lidar_Types +USE InflowWind_Types +USE DWM_Types +USE AeroDyn14_Types +USE AirfoilInfo_Types +USE UnsteadyAero_Types +USE DBEMT_Types +USE BEMT_Types +USE FVW_Types +USE AeroAcoustics_Types +USE AeroDyn_Types +USE SubDyn_Types +USE Current_Types +USE Waves_Types +USE Waves2_Types +USE Conv_Radiation_Types +USE SS_Radiation_Types +USE SS_Excitation_Types +USE WAMIT_Types +USE WAMIT2_Types +USE Morison_Types +USE HydroDyn_Types +USE IceFloe_Types +USE OpenFOAM_Types +USE SuperController_Types +USE IceDyn_Types +USE FEAMooring_Types +USE MAP_Fortran_Types +USE MAP_Types +USE MoorDyn_Types +USE OrcaFlexInterface_Types +USE ExtPtfm_MCKF_Types +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_Unknown = -1 ! Unknown [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_None = 0 ! No module selected [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_IfW = 1 ! InflowWind [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_OpFM = 2 ! OpenFOAM [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_ED = 3 ! ElastoDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_BD = 4 ! BeamDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_AD14 = 5 ! AeroDyn14 [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_AD = 6 ! AeroDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_SrvD = 7 ! ServoDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_HD = 8 ! HydroDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_SD = 9 ! SubDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_ExtPtfm = 10 ! External Platform Loading MCKF [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_MAP = 11 ! MAP (Mooring Analysis Program) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_FEAM = 12 ! FEAMooring [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_MD = 13 ! MoorDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_Orca = 14 ! OrcaFlex integration (HD/Mooring) [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_IceF = 15 ! IceFloe [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Module_IceD = 16 ! IceDyn [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: NumModules = 16 ! The number of modules available in FAST [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxNBlades = 3 ! Maximum number of blades allowed on a turbine [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: IceD_MaxLegs = 4 ! because I don't know how many legs there are before calling IceD_Init and I don't want to copy the data because of sibling mesh issues, I'm going to allocate IceD based on this number [-] +! ========= FAST_VTK_BLSurfaceType ======= + TYPE, PUBLIC :: FAST_VTK_BLSurfaceType + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: AirfoilCoords !< x,y coordinates for airfoil around each blade node on a blade (relative to reference) [-] + END TYPE FAST_VTK_BLSurfaceType +! ======================= +! ========= FAST_VTK_SurfaceType ======= + TYPE, PUBLIC :: FAST_VTK_SurfaceType + INTEGER(IntKi) :: NumSectors !< number of sectors in which to split circles (higher number gives smoother surface) [-] + REAL(SiKi) :: HubRad !< Preconed hub radius (distance from the rotor apex to the blade root) [m] + REAL(SiKi) :: GroundRad !< radius for plotting circle on ground [m] + REAL(SiKi) , DIMENSION(1:3,1:8) :: NacelleBox !< X-Y-Z locations of 8 points that define the nacelle box, relative to the nacelle position [m] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: TowerRad !< radius of each ED tower node [m] + INTEGER(IntKi) , DIMENSION(1:2) :: NWaveElevPts !< number of points for wave elevation visualization [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< X-Y locations for WaveElev output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number. [m,-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< wave elevation at WaveElevXY; first dimension is time step; second dimension is point number [m,-] + TYPE(FAST_VTK_BLSurfaceType) , DIMENSION(:), ALLOCATABLE :: BladeShape !< AirfoilCoords for each blade [m] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: MorisonRad !< radius of each Morison node [m] + END TYPE FAST_VTK_SurfaceType +! ======================= +! ========= FAST_VTK_ModeShapeType ======= + TYPE, PUBLIC :: FAST_VTK_ModeShapeType + CHARACTER(1024) :: CheckpointRoot !< name of the checkpoint file written by FAST when linearization data was produced [-] + CHARACTER(1024) :: MatlabFileName !< name of the file with eigenvectors written by Matlab [-] + INTEGER(IntKi) :: VTKLinModes !< Number of modes to visualize [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: VTKModes !< Which modes to visualize [-] + INTEGER(IntKi) :: VTKLinTim !< Switch to make one animation for all LinTimes together (1) or separate animations for each LinTimes(2) [-] + INTEGER(IntKi) :: VTKNLinTimes !< number of linearization times to use when VTKLinTim==2 [-] + REAL(ReKi) :: VTKLinScale !< Mode shape visualization scaling factor [-] + REAL(ReKi) :: VTKLinPhase !< Phase when making one animation for all LinTimes together (used only when VTKLinTim=1) [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: DampingRatio !< damping ratios from mbc3 analysis [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: NaturalFreq_Hz !< natural frequency from mbc3 analysis [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: DampedFreq_Hz !< damped frequency from mbc3 analysis [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: x_eig_magnitude !< magnitude of eigenvector (dimension 1=state, dim 2= azimuth, dim 3 = mode) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: x_eig_phase !< phase of eigenvector (dimension 1=state, dim 2= azimuth, dim 3 = mode) [-] + END TYPE FAST_VTK_ModeShapeType +! ======================= +! ========= FAST_ParameterType ======= + TYPE, PUBLIC :: FAST_ParameterType + REAL(DbKi) :: DT !< Integration time step [global time] [s] + REAL(DbKi) , DIMENSION(NumModules) :: DT_module !< Integration time step [global time] [s] + INTEGER(IntKi) , DIMENSION(NumModules) :: n_substeps !< The number of module substeps for advancing states from t_global to t_global_next [-] + INTEGER(IntKi) :: n_TMax_m1 !< The time step of TMax - dt (the end time of the simulation) [(-)] + REAL(DbKi) :: TMax !< Total run time [s] + INTEGER(IntKi) :: InterpOrder !< Interpolation order {0,1,2} [-] + INTEGER(IntKi) :: NumCrctn !< Number of correction iterations [-] + INTEGER(IntKi) :: KMax !< Maximum number of input-output-solve iterations (KMax >= 1) [-] + INTEGER(IntKi) :: numIceLegs !< number of suport-structure legs in contact with ice (IceDyn coupling) [-] + INTEGER(IntKi) :: nBeams !< number of BeamDyn instances [-] + LOGICAL :: BD_OutputSibling !< flag to determine if BD input is sibling of output mesh [-] + LOGICAL , DIMENSION(NumModules) :: ModuleInitialized !< An array determining if the module has been initialized [-] + REAL(DbKi) :: DT_Ujac !< Time between when we need to re-calculate these Jacobians [s] + REAL(ReKi) :: UJacSclFact !< Scaling factor used to get similar magnitudes between accelerations, forces, and moments in Jacobians [-] + INTEGER(IntKi) , DIMENSION(1:9) :: SizeJac_Opt1 !< (1)=size of matrix; (2)=size of ED portion; (3)=size of SD portion [2 meshes]; (4)=size of HD portion; (5)=size of BD portion blade 1; (6)=size of BD portion blade 2; (7)=size of BD portion blade 3; (8)=size of Orca portion; (9)=size of ExtPtfm portion; [-] + INTEGER(IntKi) :: CompElast !< Compute blade loads (switch) {Module_ED; Module_BD} [-] + INTEGER(IntKi) :: CompInflow !< Compute inflow wind conditions (switch) {Module_None; Module_IfW; Module_OpFM} [-] + INTEGER(IntKi) :: CompAero !< Compute aerodynamic loads (switch) {Module_None; Module_AD14; Module_AD} [-] + INTEGER(IntKi) :: CompServo !< Compute control and electrical-drive dynamics (switch) {Module_None; Module_SrvD} [-] + INTEGER(IntKi) :: CompHydro !< Compute hydrodynamic loads (switch) {Module_None; Module_HD} [-] + INTEGER(IntKi) :: CompSub !< Compute sub-structural dynamics (switch) {Module_None; Module_HD} [-] + INTEGER(IntKi) :: CompMooring !< Compute mooring system (switch) {Module_None; Module_MAP; Module_FEAM; Module_MD; Module_Orca} [-] + INTEGER(IntKi) :: CompIce !< Compute ice loading (switch) {Module_None; Module_IceF, Module_IceD} [-] + LOGICAL :: UseDWM !< Use the DWM module in AeroDyn [-] + LOGICAL :: Linearize !< Linearization analysis (flag) [-] + CHARACTER(1024) :: EDFile !< The name of the ElastoDyn input file [-] + CHARACTER(1024) , DIMENSION(MaxNBlades) :: BDBldFile !< Name of files containing BeamDyn inputs for each blade [-] + CHARACTER(1024) :: InflowFile !< Name of file containing inflow wind input parameters [-] + CHARACTER(1024) :: AeroFile !< Name of file containing aerodynamic input parameters [-] + CHARACTER(1024) :: ServoFile !< Name of file containing control and electrical-drive input parameters [-] + CHARACTER(1024) :: HydroFile !< Name of file containing hydrodynamic input parameters [-] + CHARACTER(1024) :: SubFile !< Name of file containing sub-structural input parameters [-] + CHARACTER(1024) :: MooringFile !< Name of file containing mooring system input parameters [-] + CHARACTER(1024) :: IceFile !< Name of file containing ice loading input parameters [-] + REAL(DbKi) :: TStart !< Time to begin tabular output [s] + REAL(DbKi) :: DT_Out !< Time step for tabular output [s] + LOGICAL :: WrSttsTime !< Whether we should write the status times to the screen [-] + INTEGER(IntKi) :: n_SttsTime !< Number of time steps between screen status messages [-] + INTEGER(IntKi) :: n_ChkptTime !< Number of time steps between writing checkpoint files [-] + INTEGER(IntKi) :: n_DT_Out !< Number of time steps between writing a line in the time-marching output files [-] + INTEGER(IntKi) :: n_VTKTime !< Number of time steps between writing VTK files [-] + INTEGER(IntKi) :: TurbineType !< Type_LandBased, Type_Offshore_Fixed, or Type_Offshore_Floating [-] + LOGICAL :: WrBinOutFile !< Write a binary output file? (.outb) [-] + LOGICAL :: WrTxtOutFile !< Write a text (formatted) output file? (.out) [-] + INTEGER(IntKi) :: WrBinMod !< If writing binary, which file format is to be written [1, 2, or 3] [-] + LOGICAL :: SumPrint !< Print summary data to file? (.sum) [-] + INTEGER(IntKi) :: WrVTK = 0 !< VTK Visualization data output: (switch) {0=none; 1=initialization data only; 2=animation} [-] + INTEGER(IntKi) :: VTK_Type !< Type of VTK visualization data: (switch) {1=surfaces; 2=basic meshes (lines/points); 3=all meshes (debug)} [-] + LOGICAL :: VTK_fields !< Write mesh fields to VTK data files? (flag) {true/false} [-] + CHARACTER(1) :: Delim !< Delimiter between columns of text output file (.out): space or tab [-] + CHARACTER(20) :: OutFmt !< Format used for text tabular output (except time); resulting field should be 10 characters [-] + CHARACTER(20) :: OutFmt_t !< Format used for time channel in text tabular output; resulting field should be 10 characters [-] + INTEGER(IntKi) :: FmtWidth !< width of the time OutFmt specifier [-] + INTEGER(IntKi) :: TChanLen !< width of the time channel [-] + CHARACTER(1024) :: OutFileRoot !< The rootname of the output files [-] + CHARACTER(1024) :: FTitle !< The description line from the FAST (glue-code) input file [-] + CHARACTER(1024) :: VTK_OutFileRoot = '' !< The rootname of the VTK output files [-] + INTEGER(IntKi) :: VTK_tWidth !< Width of number of files for leading zeros in file name format [-] + REAL(DbKi) :: VTK_fps !< number of frames per second to output VTK data [-] + TYPE(FAST_VTK_SurfaceType) :: VTK_surface !< Data for VTK surface visualization [-] + REAL(SiKi) , DIMENSION(1:3) :: TurbinePos !< Initial position of turbine base (origin used for graphics) [m] + CHARACTER(4) :: Tdesc !< description of turbine ID (for FAST.Farm) screen printing [-] + LOGICAL :: CalcSteady !< Calculate a steady-state periodic operating point before linearization [unused if Linearize=False] [-] + INTEGER(IntKi) :: TrimCase !< Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [unused if Linearize=False; used only if CalcSteady=True] [-] + REAL(ReKi) :: TrimTol !< Tolerance for the rotational speed convergence (>0) [unused if Linearize=False; used only if CalcSteady=True] [-] + REAL(ReKi) :: TrimGain !< Proportional gain for the rotational speed error (>0) [unused if Linearize=False; used only if CalcSteady=True] [rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque] + REAL(ReKi) :: Twr_Kdmp !< Damping factor for the tower [unused if Linearize=False; used only if CalcSteady=True] [N/(m/s)] + REAL(ReKi) :: Bld_Kdmp !< Damping factor for the blades [unused if Linearize=False; used only if CalcSteady=True] [N/(m/s)] + INTEGER(IntKi) :: NLinTimes !< Number of LinTimes, or equally-spaced azimuth steps in periodic linearized model (>0)[unused if Linearize=False] [-] + REAL(DbKi) :: AzimDelta !< difference between two consecutive azimuth positions in CalcSteady algorithm [rad] + INTEGER(IntKi) :: LinInputs !< Inputs included in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)} [unused if Linearize=False] [-] + INTEGER(IntKi) :: LinOutputs !< Outputs included in linearization (switch) {0=none; 1=from OutList(s); 2=all module outputs (debug)} [unused if Linearize=False] [-] + LOGICAL :: LinOutJac !< Include full Jacabians in linearization output (for debug) (flag) [unused if Linearize=False; used only if LinInputs=LinOutputs=2] [-] + LOGICAL :: LinOutMod !< Write module-level linearization output files in addition to output for full system? (flag) [unused if Linearize=False] [-] + TYPE(FAST_VTK_ModeShapeType) :: VTK_modes !< Data for VTK mode-shape visualization [-] + INTEGER(IntKi) :: Lin_NumMods !< number of modules in the linearization [-] + INTEGER(IntKi) , DIMENSION(NumModules) :: Lin_ModOrder !< indices that determine which order the modules are in the glue-code linearization matrix [-] + INTEGER(IntKi) :: LinInterpOrder !< Interpolation order for CalcSteady solution [-] + END TYPE FAST_ParameterType +! ======================= +! ========= FAST_LinStateSave ======= + TYPE, PUBLIC :: FAST_LinStateSave + TYPE(IceD_ContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: x_IceD !< Continuous states [-] + TYPE(IceD_DiscreteStateType) , DIMENSION(:,:), ALLOCATABLE :: xd_IceD !< Discrete states [-] + TYPE(IceD_ConstraintStateType) , DIMENSION(:,:), ALLOCATABLE :: z_IceD !< Constraint states [-] + TYPE(IceD_OtherStateType) , DIMENSION(:,:), ALLOCATABLE :: OtherSt_IceD !< Other states [-] + TYPE(IceD_InputType) , DIMENSION(:,:), ALLOCATABLE :: u_IceD !< System inputs [-] + TYPE(BD_ContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: x_BD !< Continuous states [-] + TYPE(BD_DiscreteStateType) , DIMENSION(:,:), ALLOCATABLE :: xd_BD !< Discrete states [-] + TYPE(BD_ConstraintStateType) , DIMENSION(:,:), ALLOCATABLE :: z_BD !< Constraint states [-] + TYPE(BD_OtherStateType) , DIMENSION(:,:), ALLOCATABLE :: OtherSt_BD !< Other states [-] + TYPE(BD_InputType) , DIMENSION(:,:), ALLOCATABLE :: u_BD !< System inputs [-] + TYPE(ED_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_ED !< Continuous states [-] + TYPE(ED_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_ED !< Discrete states [-] + TYPE(ED_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_ED !< Constraint states [-] + TYPE(ED_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_ED !< Other states [-] + TYPE(ED_InputType) , DIMENSION(:), ALLOCATABLE :: u_ED !< System inputs [-] + TYPE(SrvD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_SrvD !< Continuous states [-] + TYPE(SrvD_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_SrvD !< Discrete states [-] + TYPE(SrvD_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_SrvD !< Constraint states [-] + TYPE(SrvD_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_SrvD !< Other states [-] + TYPE(SrvD_InputType) , DIMENSION(:), ALLOCATABLE :: u_SrvD !< System inputs [-] + TYPE(AD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_AD !< Continuous states [-] + TYPE(AD_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_AD !< Discrete states [-] + TYPE(AD_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_AD !< Constraint states [-] + TYPE(AD_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_AD !< Other states [-] + TYPE(AD_InputType) , DIMENSION(:), ALLOCATABLE :: u_AD !< System inputs [-] + TYPE(InflowWind_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_IfW !< Continuous states [-] + TYPE(InflowWind_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_IfW !< Discrete states [-] + TYPE(InflowWind_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_IfW !< Constraint states [-] + TYPE(InflowWind_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_IfW !< Other states [-] + TYPE(InflowWind_InputType) , DIMENSION(:), ALLOCATABLE :: u_IfW !< System inputs [-] + TYPE(SD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_SD !< Continuous states [-] + TYPE(SD_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_SD !< Discrete states [-] + TYPE(SD_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_SD !< Constraint states [-] + TYPE(SD_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_SD !< Other states [-] + TYPE(SD_InputType) , DIMENSION(:), ALLOCATABLE :: u_SD !< System inputs [-] + TYPE(ExtPtfm_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_ExtPtfm !< Continuous states [-] + TYPE(ExtPtfm_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_ExtPtfm !< Discrete states [-] + TYPE(ExtPtfm_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_ExtPtfm !< Constraint states [-] + TYPE(ExtPtfm_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_ExtPtfm !< Other states [-] + TYPE(ExtPtfm_InputType) , DIMENSION(:), ALLOCATABLE :: u_ExtPtfm !< System inputs [-] + TYPE(HydroDyn_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_HD !< Continuous states [-] + TYPE(HydroDyn_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_HD !< Discrete states [-] + TYPE(HydroDyn_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_HD !< Constraint states [-] + TYPE(HydroDyn_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_HD !< Other states [-] + TYPE(HydroDyn_InputType) , DIMENSION(:), ALLOCATABLE :: u_HD !< System inputs [-] + TYPE(IceFloe_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_IceF !< Continuous states [-] + TYPE(IceFloe_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_IceF !< Discrete states [-] + TYPE(IceFloe_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_IceF !< Constraint states [-] + TYPE(IceFloe_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_IceF !< Other states [-] + TYPE(IceFloe_InputType) , DIMENSION(:), ALLOCATABLE :: u_IceF !< System inputs [-] + TYPE(MAP_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_MAP !< Continuous states [-] + TYPE(MAP_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_MAP !< Discrete states [-] + TYPE(MAP_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_MAP !< Constraint states [-] + TYPE(MAP_InputType) , DIMENSION(:), ALLOCATABLE :: u_MAP !< System inputs [-] + TYPE(FEAM_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_FEAM !< Continuous states [-] + TYPE(FEAM_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_FEAM !< Discrete states [-] + TYPE(FEAM_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_FEAM !< Constraint states [-] + TYPE(FEAM_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_FEAM !< Other states [-] + TYPE(FEAM_InputType) , DIMENSION(:), ALLOCATABLE :: u_FEAM !< System inputs [-] + TYPE(MD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: x_MD !< Continuous states [-] + TYPE(MD_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: xd_MD !< Discrete states [-] + TYPE(MD_ConstraintStateType) , DIMENSION(:), ALLOCATABLE :: z_MD !< Constraint states [-] + TYPE(MD_OtherStateType) , DIMENSION(:), ALLOCATABLE :: OtherSt_MD !< Other states [-] + TYPE(MD_InputType) , DIMENSION(:), ALLOCATABLE :: u_MD !< System inputs [-] + END TYPE FAST_LinStateSave +! ======================= +! ========= FAST_LinType ======= + TYPE, PUBLIC :: FAST_LinType + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: Names_u !< Names of the linearized inputs [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: Names_y !< Names of the linearized outputs [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: Names_x !< Names of the linearized continuous states [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: Names_xd !< Names of the linearized discrete states [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: Names_z !< Names of the linearized constraint states [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_u !< input operating point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_y !< output operating point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_x !< continuous state operating point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_dx !< 1st time derivative of continuous state operating point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_xd !< discrete state operating point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: op_z !< constraint state operating point [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: op_x_eig_mag !< continuous state eigenvector magnitude [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: op_x_eig_phase !< continuous state eigenvector phase [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: Use_u !< array same size as names_u, which indicates if this input is used in linearization output file [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: Use_y !< array same size as names_y, which indicates if this output is used in linearization output file [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: B !< B matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: D !< D matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: StateRotation !< Matrix that rotates the continuous states [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: StateRel_x !< Matrix that defines the continuous states relative to root motion [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: StateRel_xdot !< Matrix that defines the continuous states relative to root motion [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Whether the input is a load (used for scaling for potentially ill-conditioned G matrix) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Whether corresponding input is in rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Whether corresponding output is in rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Whether corresponding continuous state is in rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_z !< Whether corresponding constraint state is in rotating frame [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Derivative order for continuous states [-] + INTEGER(IntKi) , DIMENSION(1:3) :: SizeLin !< sizes of (1) the module's inputs, (2) the module's linearized outputs, and (3) the module's continuous states [-] + INTEGER(IntKi) , DIMENSION(1:3) :: LinStartIndx !< the starting index in combined matrices of (1) the module's inputs, (2) the module's linearized outputs, and (3) the module's continuous states [-] + INTEGER(IntKi) :: NumOutputs !< number of WriteOutputs in each linearized module [-] + END TYPE FAST_LinType +! ======================= +! ========= FAST_ModLinType ======= + TYPE, PUBLIC :: FAST_ModLinType + TYPE(FAST_LinType) , DIMENSION(:), ALLOCATABLE :: Instance !< Linearization data for each module instance (e.g., 3 blades for BD) [-] + END TYPE FAST_ModLinType +! ======================= +! ========= FAST_LinFileType ======= + TYPE, PUBLIC :: FAST_LinFileType + TYPE(FAST_ModLinType) , DIMENSION(NumModules) :: Modules !< Linearization data for each module [-] + TYPE(FAST_LinType) :: Glue !< Linearization data for the glue code (coupled system) [-] + REAL(ReKi) :: RotSpeed !< Rotor azimuth angular speed [rad/s] + REAL(ReKi) :: Azimuth !< Rotor azimuth position [rad] + REAL(ReKi) :: WindSpeed !< Wind speed at reference height [m/s] + END TYPE FAST_LinFileType +! ======================= +! ========= FAST_MiscLinType ======= + TYPE, PUBLIC :: FAST_MiscLinType + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: LinTimes !< List of times at which to linearize [s] + INTEGER(IntKi) :: CopyOP_CtrlCode !< mesh control code for copy type (new on first call; update otherwise) [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: AzimTarget !< target azimuth positions in CalcSteady algorithm [rad] + LOGICAL :: IsConverged !< whether the error calculation in the CalcSteady algorithm is converged [-] + LOGICAL :: FoundSteady !< whether the CalcSteady algorithm found a steady-state solution [-] + INTEGER(IntKi) :: n_rot !< number of rotations completed in CalcSteady algorithm [-] + INTEGER(IntKi) :: AzimIndx !< index into target azimuth array in CalcSteady algorithm [-] + INTEGER(IntKi) :: NextLinTimeIndx !< index for next time in LinTimes where linearization should occur [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: Psi !< Azimuth angle at the current and previous time steps (uses LinInterpOrder); DbKi so that we can use registry-generated extrap/interp routines [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: y_interp !< Interpolated outputs packed into an array [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: y_ref !< Reference output range for CalcSteady error calculation [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Y_prevRot !< Linearization outputs from previous rotor revolution at each target azimuth [-] + END TYPE FAST_MiscLinType +! ======================= +! ========= FAST_OutputFileType ======= + TYPE, PUBLIC :: FAST_OutputFileType + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: TimeData !< Array to contain the time output data for the binary file (first output time and a time [fixed] increment) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AllOutData !< Array to contain all the output data (time history of all outputs); Index 1 is NumOuts, Index 2 is Time step [-] + INTEGER(IntKi) :: n_Out !< Time index into the AllOutData array [-] + INTEGER(IntKi) :: NOutSteps !< Maximum number of output steps [-] + INTEGER(IntKi) , DIMENSION(NumModules) :: numOuts !< number of outputs to print from each module [-] + INTEGER(IntKi) :: UnOu = -1 !< I/O unit number for the tabular output file [-] + INTEGER(IntKi) :: UnSum = -1 !< I/O unit number for the summary file [-] + INTEGER(IntKi) :: UnGra = -1 !< I/O unit number for mesh graphics [-] + CHARACTER(1024) , DIMENSION(1:3) :: FileDescLines !< Description lines to include in output files (header, time run, plus module names/versions) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: ChannelNames !< Names of the output channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: ChannelUnits !< Units for the output channels [-] + TYPE(ProgDesc) , DIMENSION(NumModules) :: Module_Ver !< version information from all modules [-] + CHARACTER(ChanLen) , DIMENSION(NumModules) :: Module_Abrev !< abbreviation for module (used in file output naming conventions) [-] + LOGICAL :: WriteThisStep !< Whether this step will be written in the FAST output files [-] + INTEGER(IntKi) :: VTK_count !< Number of VTK files written (for naming output files) [-] + INTEGER(IntKi) :: VTK_LastWaveIndx !< last index into wave array [-] + TYPE(FAST_LinFileType) :: Lin !< linearization data for output [-] + INTEGER(IntKi) :: ActualChanLen !< width of the column headers output in the text and/or binary file [-] + CHARACTER(30) :: OutFmt_a !< Format used for text tabular output (except time); combines OutFmt with delim and appropriate spaces [-] + TYPE(FAST_LinStateSave) :: op !< operating points of states and inputs for VTK output of mode shapes [-] + END TYPE FAST_OutputFileType +! ======================= +! ========= IceDyn_Data ======= + TYPE, PUBLIC :: IceDyn_Data + TYPE(IceD_ContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: x !< Continuous states [-] + TYPE(IceD_DiscreteStateType) , DIMENSION(:,:), ALLOCATABLE :: xd !< Discrete states [-] + TYPE(IceD_ConstraintStateType) , DIMENSION(:,:), ALLOCATABLE :: z !< Constraint states [-] + TYPE(IceD_OtherStateType) , DIMENSION(:,:), ALLOCATABLE :: OtherSt !< Other states [-] + TYPE(IceD_ParameterType) , DIMENSION(:), ALLOCATABLE :: p !< Parameters [-] + TYPE(IceD_InputType) , DIMENSION(:), ALLOCATABLE :: u !< System inputs [-] + TYPE(IceD_OutputType) , DIMENSION(:), ALLOCATABLE :: y !< System outputs [-] + TYPE(IceD_MiscVarType) , DIMENSION(:), ALLOCATABLE :: m !< Misc/optimization variables [-] + TYPE(IceD_InputType) , DIMENSION(:,:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE IceDyn_Data +! ======================= +! ========= BeamDyn_Data ======= + TYPE, PUBLIC :: BeamDyn_Data + TYPE(BD_ContinuousStateType) , DIMENSION(:,:), ALLOCATABLE :: x !< Continuous states [-] + TYPE(BD_DiscreteStateType) , DIMENSION(:,:), ALLOCATABLE :: xd !< Discrete states [-] + TYPE(BD_ConstraintStateType) , DIMENSION(:,:), ALLOCATABLE :: z !< Constraint states [-] + TYPE(BD_OtherStateType) , DIMENSION(:,:), ALLOCATABLE :: OtherSt !< Other states [-] + TYPE(BD_ParameterType) , DIMENSION(:), ALLOCATABLE :: p !< Parameters [-] + TYPE(BD_InputType) , DIMENSION(:), ALLOCATABLE :: u !< System inputs [-] + TYPE(BD_OutputType) , DIMENSION(:), ALLOCATABLE :: y !< System outputs [-] + TYPE(BD_MiscVarType) , DIMENSION(:), ALLOCATABLE :: m !< Misc/optimization variables [-] + TYPE(BD_OutputType) , DIMENSION(:,:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(BD_OutputType) , DIMENSION(:), ALLOCATABLE :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(BD_InputType) , DIMENSION(:,:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE BeamDyn_Data +! ======================= +! ========= ElastoDyn_Data ======= + TYPE, PUBLIC :: ElastoDyn_Data + TYPE(ED_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(ED_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(ED_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(ED_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(ED_ParameterType) :: p !< Parameters [-] + TYPE(ED_InputType) :: u !< System inputs [-] + TYPE(ED_OutputType) :: y !< System outputs [-] + TYPE(ED_MiscVarType) :: m !< Misc (optimization) variables not associated with time [-] + TYPE(ED_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(ED_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(ED_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE ElastoDyn_Data +! ======================= +! ========= ServoDyn_Data ======= + TYPE, PUBLIC :: ServoDyn_Data + TYPE(SrvD_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(SrvD_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(SrvD_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(SrvD_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(SrvD_ParameterType) :: p !< Parameters [-] + TYPE(SrvD_InputType) :: u !< System inputs [-] + TYPE(SrvD_OutputType) :: y !< System outputs [-] + TYPE(SrvD_MiscVarType) :: m !< Misc (optimization) variables not associated with time [-] + TYPE(SrvD_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(SrvD_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(SrvD_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE ServoDyn_Data +! ======================= +! ========= AeroDyn14_Data ======= + TYPE, PUBLIC :: AeroDyn14_Data + TYPE(AD14_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(AD14_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(AD14_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(AD14_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(AD14_ParameterType) :: p !< Parameters [-] + TYPE(AD14_InputType) :: u !< System inputs [-] + TYPE(AD14_OutputType) :: y !< System outputs [-] + TYPE(AD14_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(AD14_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE AeroDyn14_Data +! ======================= +! ========= AeroDyn_Data ======= + TYPE, PUBLIC :: AeroDyn_Data + TYPE(AD_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(AD_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(AD_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(AD_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(AD_ParameterType) :: p !< Parameters [-] + TYPE(AD_InputType) :: u !< System inputs [-] + TYPE(AD_OutputType) :: y !< System outputs [-] + TYPE(AD_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(AD_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(AD_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(AD_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE AeroDyn_Data +! ======================= +! ========= InflowWind_Data ======= + TYPE, PUBLIC :: InflowWind_Data + TYPE(InflowWind_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(InflowWind_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(InflowWind_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(InflowWind_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(InflowWind_ParameterType) :: p !< Parameters [-] + TYPE(InflowWind_InputType) :: u !< System inputs [-] + TYPE(InflowWind_OutputType) :: y !< System outputs [-] + TYPE(InflowWind_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(InflowWind_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(InflowWind_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(InflowWind_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE InflowWind_Data +! ======================= +! ========= OpenFOAM_Data ======= + TYPE, PUBLIC :: OpenFOAM_Data + TYPE(OpFM_InputType) :: u !< System inputs [-] + TYPE(OpFM_OutputType) :: y !< System outputs [-] + TYPE(OpFM_ParameterType) :: p !< Parameters [-] + TYPE(OpFM_MiscVarType) :: m !< Parameters [-] + END TYPE OpenFOAM_Data +! ======================= +! ========= SuperController_Data ======= + TYPE, PUBLIC :: SuperController_Data + TYPE(SC_InputType) :: u !< System inputs [-] + TYPE(SC_OutputType) :: y !< System outputs [-] + TYPE(SC_ParameterType) :: p !< System parameters [-] + END TYPE SuperController_Data +! ======================= +! ========= SubDyn_Data ======= + TYPE, PUBLIC :: SubDyn_Data + TYPE(SD_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(SD_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(SD_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(SD_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(SD_ParameterType) :: p !< Parameters [-] + TYPE(SD_InputType) :: u !< System inputs [-] + TYPE(SD_OutputType) :: y !< System outputs [-] + TYPE(SD_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(SD_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE SubDyn_Data +! ======================= +! ========= ExtPtfm_Data ======= + TYPE, PUBLIC :: ExtPtfm_Data + TYPE(ExtPtfm_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(ExtPtfm_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(ExtPtfm_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(ExtPtfm_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(ExtPtfm_ParameterType) :: p !< Parameters [-] + TYPE(ExtPtfm_InputType) :: u !< System inputs [-] + TYPE(ExtPtfm_OutputType) :: y !< System outputs [-] + TYPE(ExtPtfm_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(ExtPtfm_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE ExtPtfm_Data +! ======================= +! ========= HydroDyn_Data ======= + TYPE, PUBLIC :: HydroDyn_Data + TYPE(HydroDyn_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(HydroDyn_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(HydroDyn_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(HydroDyn_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(HydroDyn_ParameterType) :: p !< Parameters [-] + TYPE(HydroDyn_InputType) :: u !< System inputs [-] + TYPE(HydroDyn_OutputType) :: y !< System outputs [-] + TYPE(HydroDyn_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(HydroDyn_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(HydroDyn_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(HydroDyn_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE HydroDyn_Data +! ======================= +! ========= IceFloe_Data ======= + TYPE, PUBLIC :: IceFloe_Data + TYPE(IceFloe_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(IceFloe_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(IceFloe_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(IceFloe_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(IceFloe_ParameterType) :: p !< Parameters [-] + TYPE(IceFloe_InputType) :: u !< System inputs [-] + TYPE(IceFloe_OutputType) :: y !< System outputs [-] + TYPE(IceFloe_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(IceFloe_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE IceFloe_Data +! ======================= +! ========= MAP_Data ======= + TYPE, PUBLIC :: MAP_Data + TYPE(MAP_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(MAP_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(MAP_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(MAP_OtherStateType) :: OtherSt !< Other/optimization states [-] + TYPE(MAP_ParameterType) :: p !< Parameters [-] + TYPE(MAP_InputType) :: u !< System inputs [-] + TYPE(MAP_OutputType) :: y !< System outputs [-] + TYPE(MAP_OtherStateType) :: OtherSt_old !< Other/optimization states (copied for the case of subcycling) [-] + TYPE(MAP_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(MAP_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] + TYPE(MAP_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE MAP_Data +! ======================= +! ========= FEAMooring_Data ======= + TYPE, PUBLIC :: FEAMooring_Data + TYPE(FEAM_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(FEAM_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(FEAM_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(FEAM_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(FEAM_ParameterType) :: p !< Parameters [-] + TYPE(FEAM_InputType) :: u !< System inputs [-] + TYPE(FEAM_OutputType) :: y !< System outputs [-] + TYPE(FEAM_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(FEAM_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE FEAMooring_Data +! ======================= +! ========= MoorDyn_Data ======= + TYPE, PUBLIC :: MoorDyn_Data + TYPE(MD_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(MD_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(MD_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(MD_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(MD_ParameterType) :: p !< Parameters [-] + TYPE(MD_InputType) :: u !< System inputs [-] + TYPE(MD_OutputType) :: y !< System outputs [-] + TYPE(MD_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(MD_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE MoorDyn_Data +! ======================= +! ========= OrcaFlex_Data ======= + TYPE, PUBLIC :: OrcaFlex_Data + TYPE(Orca_ContinuousStateType) , DIMENSION(1:2) :: x !< Continuous states [-] + TYPE(Orca_DiscreteStateType) , DIMENSION(1:2) :: xd !< Discrete states [-] + TYPE(Orca_ConstraintStateType) , DIMENSION(1:2) :: z !< Constraint states [-] + TYPE(Orca_OtherStateType) , DIMENSION(1:2) :: OtherSt !< Other states [-] + TYPE(Orca_ParameterType) :: p !< Parameters [-] + TYPE(Orca_InputType) :: u !< System inputs [-] + TYPE(Orca_OutputType) :: y !< System outputs [-] + TYPE(Orca_MiscVarType) :: m !< Misc/optimization variables [-] + TYPE(Orca_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] + END TYPE OrcaFlex_Data +! ======================= +! ========= FAST_ModuleMapType ======= + TYPE, PUBLIC :: FAST_ModuleMapType + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_BD_P !< Map ElastoDyn BladeRootMotion meshes to BeamDyn RootMotion point meshes [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: BD_P_2_ED_P !< Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_BD_P_Hub !< ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator [-] + TYPE(MeshMapType) :: ED_P_2_HD_W_P !< Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point [-] + TYPE(MeshMapType) :: HD_W_P_2_ED_P !< Map HydroDyn WAMIT Point (from either y%Mesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: ED_P_2_HD_M_P !< Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point [-] + TYPE(MeshMapType) :: HD_M_P_2_ED_P !< Map HydroDyn Morison Point to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: ED_P_2_HD_M_L !< Map ElastoDyn PlatformPtMesh to HydroDyn Morison Line2 [-] + TYPE(MeshMapType) :: HD_M_L_2_ED_P !< Map HydroDyn Morison Line2 to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: ED_P_2_Mooring_P !< Map ElastoDyn PlatformPtMesh to MAP/FEAM/MoorDyn/OrcaFlex point mesh [-] + TYPE(MeshMapType) :: Mooring_P_2_ED_P !< Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: ED_P_2_SD_TP !< Map ElastoDyn PlatformPtMesh to SubDyn transition-piece point mesh [-] + TYPE(MeshMapType) :: SD_TP_2_ED_P !< Map SubDyn transition-piece point mesh to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: SD_P_2_HD_M_P !< Map SubDyn y2Mesh Point to HydroDyn Morison Point [-] + TYPE(MeshMapType) :: HD_M_P_2_SD_P !< Map HydroDyn Morison Point to SubDyn y2Mesh Point [-] + TYPE(MeshMapType) :: SD_P_2_HD_M_L !< Map SubDyn y2Mesh Point to HydroDyn Morison Line2 [-] + TYPE(MeshMapType) :: HD_M_L_2_SD_P !< Map HydroDyn Morison Line2 to SubDyn y2Mesh Point [-] + TYPE(MeshMapType) :: ED_P_2_SrvD_P_N !< Map ElastoDyn Nacelle point mesh to ServoDyn/TMD point mesh [-] + TYPE(MeshMapType) :: SrvD_P_2_ED_P_N !< Map ServoDyn nacelle point mesh to ElastoDyn point mesh on the nacelle [-] + TYPE(MeshMapType) :: ED_L_2_SrvD_P_T !< Map ElastoDyn tower line2 mesh to ServoDyn/TTMD point mesh [-] + TYPE(MeshMapType) :: SrvD_P_2_ED_P_T !< Map ServoDyn tower point mesh to ElastoDyn point load mesh on the tower [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: BDED_L_2_AD_L_B !< Map ElastoDyn BladeLn2Mesh point meshes OR BeamDyn BldMotion line2 meshes to AeroDyn14 InputMarkers OR AeroDyn BladeMotion line2 meshes [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: AD_L_2_BDED_B !< Map AeroDyn14 InputMarkers or AeroDyn BladeLoad line2 meshes to ElastoDyn BladePtLoad point meshes or BeamDyn BldMotion line2 meshes [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: BD_L_2_BD_L !< Map BeamDyn BldMotion output meshes to locations on the BD input DistrLoad mesh stored in MeshMapType%y_BD_BldMotion_4Loads (BD input and output meshes are not siblings and in fact have nodes at different locations [-] + TYPE(MeshMapType) :: ED_L_2_AD_L_T !< Map ElastoDyn TowerLn2Mesh line2 mesh to AeroDyn14 Twr_InputMarkers or AeroDyn TowerMotion line2 mesh [-] + TYPE(MeshMapType) :: AD_L_2_ED_P_T !< Map AeroDyn14 Twr_InputMarkers or AeroDyn TowerLoad line2 mesh to ElastoDyn TowerPtLoads point mesh [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_AD_P_R !< Map ElastoDyn BladeRootMotion point meshes to AeroDyn BladeRootMotion point meshes [-] + TYPE(MeshMapType) :: ED_P_2_AD_P_H !< Map ElastoDyn HubPtMotion point mesh to AeroDyn HubMotion point mesh [-] + TYPE(MeshMapType) :: IceF_P_2_SD_P !< Map IceFloe point mesh to SubDyn y2Mesh point mesh [-] + TYPE(MeshMapType) :: SD_P_2_IceF_P !< Map SubDyn y2Mesh point mesh to IceFloe point mesh [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: IceD_P_2_SD_P !< Map IceDyn point mesh to SubDyn y2Mesh point mesh [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: SD_P_2_IceD_P !< Map SubDyn y2Mesh point mesh to IceDyn point mesh [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Jacobian_Opt1 !< Stored Jacobian in ED_HD_InputOutputSolve or FullOpt1_InputOutputSolve [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Jacobian_pivot !< Pivot array used for LU decomposition of Jacobian_Opt1 [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + TYPE(MeshType) :: u_ED_PlatformPtMesh !< copy of ED input mesh [-] + TYPE(MeshType) :: u_ED_PlatformPtMesh_2 !< copy of ED input mesh (used only for temporary storage) [-] + TYPE(MeshType) :: u_SD_TPMesh !< copy of SD input mesh [-] + TYPE(MeshType) :: u_SD_LMesh !< copy of SD input mesh [-] + TYPE(MeshType) :: u_SD_LMesh_2 !< copy of SD input mesh (used only for temporary storage) [-] + TYPE(MeshType) :: u_HD_M_LumpedMesh !< copy of HD input mesh [-] + TYPE(MeshType) :: u_HD_M_DistribMesh !< copy of HD input mesh [-] + TYPE(MeshType) :: u_HD_Mesh !< copy of HD input mesh [-] + TYPE(MeshType) :: u_ED_HubPtLoad !< copy of ED input mesh [-] + TYPE(MeshType) :: u_ED_HubPtLoad_2 !< copy of ED input mesh [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: u_BD_RootMotion !< copy of BD input meshes [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: y_BD_BldMotion_4Loads !< BD blade motion output at locations on DistrLoad input meshes [-] + TYPE(MeshType) :: u_Orca_PtfmMesh !< copy of Orca PtfmMesh input mesh [-] + TYPE(MeshType) :: u_ExtPtfm_PtfmMesh !< copy of ExtPtfm_MCKF PtfmMesh input mesh [-] + END TYPE FAST_ModuleMapType +! ======================= +! ========= FAST_ExternInputType ======= + TYPE, PUBLIC :: FAST_ExternInputType + REAL(ReKi) :: GenTrq !< generator torque input from Simulink/Labview [-] + REAL(ReKi) :: ElecPwr !< electric power input from Simulink/Labview [-] + REAL(ReKi) :: YawPosCom !< yaw position command from Simulink/Labview [-] + REAL(ReKi) :: YawRateCom !< yaw rate command from Simulink/Labview [-] + REAL(ReKi) , DIMENSION(1:3) :: BlPitchCom !< blade pitch commands from Simulink/Labview [rad] + REAL(ReKi) :: HSSBrFrac !< Fraction of full braking torque: 0 (off) <= HSSBrFrac <= 1 (full) from Simulink or LabVIEW [-] + REAL(ReKi) , DIMENSION(1:3) :: LidarFocus !< lidar focus (relative to lidar location) [m] + END TYPE FAST_ExternInputType +! ======================= +! ========= FAST_InitData ======= + TYPE, PUBLIC :: FAST_InitData + TYPE(ED_InitInputType) :: InData_ED !< ED Initialization input data [-] + TYPE(ED_InitOutputType) :: OutData_ED !< ED Initialization output data [-] + TYPE(BD_InitInputType) :: InData_BD !< BD Initialization input data [-] + TYPE(BD_InitOutputType) , DIMENSION(:), ALLOCATABLE :: OutData_BD !< BD Initialization output data [-] + TYPE(SrvD_InitInputType) :: InData_SrvD !< SrvD Initialization input data [-] + TYPE(SrvD_InitOutputType) :: OutData_SrvD !< SrvD Initialization output data [-] + TYPE(AD14_InitInputType) :: InData_AD14 !< AD14 Initialization input data [-] + TYPE(AD14_InitOutputType) :: OutData_AD14 !< AD14 Initialization output data [-] + TYPE(AD_InitInputType) :: InData_AD !< AD Initialization input data [-] + TYPE(AD_InitOutputType) :: OutData_AD !< AD Initialization output data [-] + TYPE(InflowWind_InitInputType) :: InData_IfW !< IfW Initialization input data [-] + TYPE(InflowWind_InitOutputType) :: OutData_IfW !< IfW Initialization output data [-] + TYPE(OpFM_InitInputType) :: InData_OpFM !< OpFM Initialization input data [-] + TYPE(OpFM_InitOutputType) :: OutData_OpFM !< OpFM Initialization output data [-] + TYPE(HydroDyn_InitInputType) :: InData_HD !< HD Initialization input data [-] + TYPE(HydroDyn_InitOutputType) :: OutData_HD !< HD Initialization output data [-] + TYPE(SD_InitInputType) :: InData_SD !< SD Initialization input data [-] + TYPE(SD_InitOutputType) :: OutData_SD !< SD Initialization output data [-] + TYPE(ExtPtfm_InitInputType) :: InData_ExtPtfm !< ExtPtfm Initialization input data [-] + TYPE(ExtPtfm_InitOutputType) :: OutData_ExtPtfm !< ExtPtfm Initialization output data [-] + TYPE(MAP_InitInputType) :: InData_MAP !< MAP Initialization input data [-] + TYPE(MAP_InitOutputType) :: OutData_MAP !< MAP Initialization output data [-] + TYPE(FEAM_InitInputType) :: InData_FEAM !< FEAM Initialization input data [-] + TYPE(FEAM_InitOutputType) :: OutData_FEAM !< FEAM Initialization output data [-] + TYPE(MD_InitInputType) :: InData_MD !< MD Initialization input data [-] + TYPE(MD_InitOutputType) :: OutData_MD !< MD Initialization output data [-] + TYPE(Orca_InitInputType) :: InData_Orca !< Orca Initialization input data [-] + TYPE(Orca_InitOutputType) :: OutData_Orca !< Orca Initialization output data [-] + TYPE(IceFloe_InitInputType) :: InData_IceF !< IceF Initialization input data [-] + TYPE(IceFloe_InitOutputType) :: OutData_IceF !< IceF Initialization output data [-] + TYPE(IceD_InitInputType) :: InData_IceD !< IceD Initialization input data [-] + TYPE(IceD_InitOutputType) :: OutData_IceD !< IceD Initialization output data (each instance will have the same output channels) [-] + TYPE(SC_InitInputType) :: InData_SC !< SC Initialization input data [-] + TYPE(SC_InitOutputType) :: OutData_SC !< SC Initialization output data [-] + END TYPE FAST_InitData +! ======================= +! ========= FAST_MiscVarType ======= + TYPE, PUBLIC :: FAST_MiscVarType + REAL(DbKi) :: TiLstPrn !< The simulation time of the last print (to file) [(s)] + REAL(DbKi) :: t_global !< Current simulation time (for global/FAST simulation) [(s)] + REAL(DbKi) :: NextJacCalcTime !< Time between calculating Jacobians in the HD-ED and SD-ED simulations [(s)] + REAL(ReKi) :: PrevClockTime !< Clock time at start of simulation in seconds [(s)] + REAL(ReKi) :: UsrTime1 !< User CPU time for simulation initialization [(s)] + REAL(ReKi) :: UsrTime2 !< User CPU time for simulation (without intialization) [(s)] + INTEGER(IntKi) , DIMENSION(1:8) :: StrtTime !< Start time of simulation (including intialization) [-] + INTEGER(IntKi) , DIMENSION(1:8) :: SimStrtTime !< Start time of simulation (after initialization) [-] + LOGICAL :: calcJacobian !< Should we calculate Jacobians in Option 1? [(flag)] + TYPE(FAST_ExternInputType) :: ExternInput !< external input values [-] + TYPE(FAST_MiscLinType) :: Lin !< misc data for linearization analysis [-] + END TYPE FAST_MiscVarType +! ======================= +! ========= FAST_ExternInitType ======= + TYPE, PUBLIC :: FAST_ExternInitType + REAL(DbKi) :: Tmax = -1 !< External code specified Tmax [s] + INTEGER(IntKi) :: SensorType = SensorType_None !< lidar sensor type, which should not be pulsed at the moment; this input should be replaced with a section in the InflowWind input file [-] + LOGICAL :: LidRadialVel !< TRUE => return radial component, FALSE => return 'x' direction estimate [-] + INTEGER(IntKi) :: TurbineID = 0 !< ID number for turbine (used to create output file naming convention) [-] + REAL(ReKi) , DIMENSION(1:3) :: TurbinePos !< Initial position of turbine base (origin used in future for graphics) [m] + INTEGER(IntKi) :: NumSC2Ctrl !< number of controller inputs [from supercontroller] [-] + INTEGER(IntKi) :: NumCtrl2SC !< number of controller outputs [to supercontroller] [-] + LOGICAL :: FarmIntegration = .false. !< whether this is called from FAST.Farm (or another program that doesn't want FAST to call all of the init stuff first) [-] + INTEGER(IntKi) , DIMENSION(1:4) :: windGrid_n !< number of grid points in the x, y, z, and t directions for IfW [-] + REAL(ReKi) , DIMENSION(1:4) :: windGrid_delta !< size between 2 consecutive grid points in each grid direction for IfW [m,m,m,s] + REAL(ReKi) , DIMENSION(1:3) :: windGrid_pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of IfW m%V(:,1,1,1,:)) [m] + CHARACTER(1024) :: RootName !< Root name of FAST output files (overrides normal operation) [-] + INTEGER(IntKi) :: NumActForcePtsBlade !< number of actuator line force points in blade [-] + INTEGER(IntKi) :: NumActForcePtsTower !< number of actuator line force points in tower [-] + END TYPE FAST_ExternInitType +! ======================= +! ========= FAST_TurbineType ======= + TYPE, PUBLIC :: FAST_TurbineType + INTEGER(IntKi) :: TurbID = 1 !< Turbine ID Number [-] + TYPE(FAST_ParameterType) :: p_FAST !< Parameters for the glue code [-] + TYPE(FAST_OutputFileType) :: y_FAST !< Output variables for the glue code [-] + TYPE(FAST_MiscVarType) :: m_FAST !< Miscellaneous variables [-] + TYPE(FAST_ModuleMapType) :: MeshMapData !< Data for mapping between modules [-] + TYPE(ElastoDyn_Data) :: ED !< Data for the ElastoDyn module [-] + TYPE(BeamDyn_Data) :: BD !< Data for the BeamDyn module [-] + TYPE(ServoDyn_Data) :: SrvD !< Data for the ServoDyn module [-] + TYPE(AeroDyn_Data) :: AD !< Data for the AeroDyn module [-] + TYPE(AeroDyn14_Data) :: AD14 !< Data for the AeroDyn14 module [-] + TYPE(InflowWind_Data) :: IfW !< Data for InflowWind module [-] + TYPE(OpenFOAM_Data) :: OpFM !< Data for OpenFOAM integration module [-] + TYPE(SuperController_Data) :: SC !< Data for SuperController integration module [-] + TYPE(HydroDyn_Data) :: HD !< Data for the HydroDyn module [-] + TYPE(SubDyn_Data) :: SD !< Data for the SubDyn module [-] + TYPE(MAP_Data) :: MAP !< Data for the MAP (Mooring Analysis Program) module [-] + TYPE(FEAMooring_Data) :: FEAM !< Data for the FEAMooring module [-] + TYPE(MoorDyn_Data) :: MD !< Data for the MoorDyn module [-] + TYPE(OrcaFlex_Data) :: Orca !< Data for the OrcaFlex interface module [-] + TYPE(IceFloe_Data) :: IceF !< Data for the IceFloe module [-] + TYPE(IceDyn_Data) :: IceD !< Data for the IceDyn module [-] + TYPE(ExtPtfm_Data) :: ExtPtfm !< Data for the ExtPtfm (external platform loading) module [-] + END TYPE FAST_TurbineType +! ======================= +CONTAINS + SUBROUTINE FAST_CopyVTK_BLSurfaceType( SrcVTK_BLSurfaceTypeData, DstVTK_BLSurfaceTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_VTK_BLSurfaceType), INTENT(IN) :: SrcVTK_BLSurfaceTypeData + TYPE(FAST_VTK_BLSurfaceType), INTENT(INOUT) :: DstVTK_BLSurfaceTypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CopyVTK_BLSurfaceType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcVTK_BLSurfaceTypeData%AirfoilCoords)) THEN + i1_l = LBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,1) + i1_u = UBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,1) + i2_l = LBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,2) + i2_u = UBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,2) + i3_l = LBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,3) + i3_u = UBOUND(SrcVTK_BLSurfaceTypeData%AirfoilCoords,3) + IF (.NOT. ALLOCATED(DstVTK_BLSurfaceTypeData%AirfoilCoords)) THEN + ALLOCATE(DstVTK_BLSurfaceTypeData%AirfoilCoords(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_BLSurfaceTypeData%AirfoilCoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_BLSurfaceTypeData%AirfoilCoords = SrcVTK_BLSurfaceTypeData%AirfoilCoords +ENDIF + END SUBROUTINE FAST_CopyVTK_BLSurfaceType + + SUBROUTINE FAST_DestroyVTK_BLSurfaceType( VTK_BLSurfaceTypeData, ErrStat, ErrMsg ) + TYPE(FAST_VTK_BLSurfaceType), INTENT(INOUT) :: VTK_BLSurfaceTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyVTK_BLSurfaceType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(VTK_BLSurfaceTypeData%AirfoilCoords)) THEN + DEALLOCATE(VTK_BLSurfaceTypeData%AirfoilCoords) +ENDIF + END SUBROUTINE FAST_DestroyVTK_BLSurfaceType + + SUBROUTINE FAST_PackVTK_BLSurfaceType( 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(FAST_VTK_BLSurfaceType), 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 = 'FAST_PackVTK_BLSurfaceType' + ! 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 ! AirfoilCoords allocated yes/no + IF ( ALLOCATED(InData%AirfoilCoords) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AirfoilCoords upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AirfoilCoords) ! AirfoilCoords + 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%AirfoilCoords) ) 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%AirfoilCoords,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AirfoilCoords,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AirfoilCoords,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AirfoilCoords,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AirfoilCoords,3), UBOUND(InData%AirfoilCoords,3) + DO i2 = LBOUND(InData%AirfoilCoords,2), UBOUND(InData%AirfoilCoords,2) + DO i1 = LBOUND(InData%AirfoilCoords,1), UBOUND(InData%AirfoilCoords,1) + ReKiBuf(Re_Xferred) = InData%AirfoilCoords(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FAST_PackVTK_BLSurfaceType + + SUBROUTINE FAST_UnPackVTK_BLSurfaceType( 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(FAST_VTK_BLSurfaceType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_UnPackVTK_BLSurfaceType' + ! 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 ! AirfoilCoords 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%AirfoilCoords)) DEALLOCATE(OutData%AirfoilCoords) + ALLOCATE(OutData%AirfoilCoords(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%AirfoilCoords.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AirfoilCoords,3), UBOUND(OutData%AirfoilCoords,3) + DO i2 = LBOUND(OutData%AirfoilCoords,2), UBOUND(OutData%AirfoilCoords,2) + DO i1 = LBOUND(OutData%AirfoilCoords,1), UBOUND(OutData%AirfoilCoords,1) + OutData%AirfoilCoords(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FAST_UnPackVTK_BLSurfaceType + + SUBROUTINE FAST_CopyVTK_SurfaceType( SrcVTK_SurfaceTypeData, DstVTK_SurfaceTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_VTK_SurfaceType), INTENT(IN) :: SrcVTK_SurfaceTypeData + TYPE(FAST_VTK_SurfaceType), INTENT(INOUT) :: DstVTK_SurfaceTypeData + 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 = 'FAST_CopyVTK_SurfaceType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstVTK_SurfaceTypeData%NumSectors = SrcVTK_SurfaceTypeData%NumSectors + DstVTK_SurfaceTypeData%HubRad = SrcVTK_SurfaceTypeData%HubRad + DstVTK_SurfaceTypeData%GroundRad = SrcVTK_SurfaceTypeData%GroundRad + DstVTK_SurfaceTypeData%NacelleBox = SrcVTK_SurfaceTypeData%NacelleBox +IF (ALLOCATED(SrcVTK_SurfaceTypeData%TowerRad)) THEN + i1_l = LBOUND(SrcVTK_SurfaceTypeData%TowerRad,1) + i1_u = UBOUND(SrcVTK_SurfaceTypeData%TowerRad,1) + IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%TowerRad)) THEN + ALLOCATE(DstVTK_SurfaceTypeData%TowerRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%TowerRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_SurfaceTypeData%TowerRad = SrcVTK_SurfaceTypeData%TowerRad +ENDIF + DstVTK_SurfaceTypeData%NWaveElevPts = SrcVTK_SurfaceTypeData%NWaveElevPts +IF (ALLOCATED(SrcVTK_SurfaceTypeData%WaveElevXY)) THEN + i1_l = LBOUND(SrcVTK_SurfaceTypeData%WaveElevXY,1) + i1_u = UBOUND(SrcVTK_SurfaceTypeData%WaveElevXY,1) + i2_l = LBOUND(SrcVTK_SurfaceTypeData%WaveElevXY,2) + i2_u = UBOUND(SrcVTK_SurfaceTypeData%WaveElevXY,2) + IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%WaveElevXY)) THEN + ALLOCATE(DstVTK_SurfaceTypeData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_SurfaceTypeData%WaveElevXY = SrcVTK_SurfaceTypeData%WaveElevXY +ENDIF +IF (ALLOCATED(SrcVTK_SurfaceTypeData%WaveElev)) THEN + i1_l = LBOUND(SrcVTK_SurfaceTypeData%WaveElev,1) + i1_u = UBOUND(SrcVTK_SurfaceTypeData%WaveElev,1) + i2_l = LBOUND(SrcVTK_SurfaceTypeData%WaveElev,2) + i2_u = UBOUND(SrcVTK_SurfaceTypeData%WaveElev,2) + IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%WaveElev)) THEN + ALLOCATE(DstVTK_SurfaceTypeData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_SurfaceTypeData%WaveElev = SrcVTK_SurfaceTypeData%WaveElev +ENDIF +IF (ALLOCATED(SrcVTK_SurfaceTypeData%BladeShape)) THEN + i1_l = LBOUND(SrcVTK_SurfaceTypeData%BladeShape,1) + i1_u = UBOUND(SrcVTK_SurfaceTypeData%BladeShape,1) + IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%BladeShape)) THEN + ALLOCATE(DstVTK_SurfaceTypeData%BladeShape(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%BladeShape.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcVTK_SurfaceTypeData%BladeShape,1), UBOUND(SrcVTK_SurfaceTypeData%BladeShape,1) + CALL FAST_Copyvtk_blsurfacetype( SrcVTK_SurfaceTypeData%BladeShape(i1), DstVTK_SurfaceTypeData%BladeShape(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcVTK_SurfaceTypeData%MorisonRad)) THEN + i1_l = LBOUND(SrcVTK_SurfaceTypeData%MorisonRad,1) + i1_u = UBOUND(SrcVTK_SurfaceTypeData%MorisonRad,1) + IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%MorisonRad)) THEN + ALLOCATE(DstVTK_SurfaceTypeData%MorisonRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%MorisonRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_SurfaceTypeData%MorisonRad = SrcVTK_SurfaceTypeData%MorisonRad +ENDIF + END SUBROUTINE FAST_CopyVTK_SurfaceType + + SUBROUTINE FAST_DestroyVTK_SurfaceType( VTK_SurfaceTypeData, ErrStat, ErrMsg ) + TYPE(FAST_VTK_SurfaceType), INTENT(INOUT) :: VTK_SurfaceTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyVTK_SurfaceType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(VTK_SurfaceTypeData%TowerRad)) THEN + DEALLOCATE(VTK_SurfaceTypeData%TowerRad) +ENDIF +IF (ALLOCATED(VTK_SurfaceTypeData%WaveElevXY)) THEN + DEALLOCATE(VTK_SurfaceTypeData%WaveElevXY) +ENDIF +IF (ALLOCATED(VTK_SurfaceTypeData%WaveElev)) THEN + DEALLOCATE(VTK_SurfaceTypeData%WaveElev) +ENDIF +IF (ALLOCATED(VTK_SurfaceTypeData%BladeShape)) THEN +DO i1 = LBOUND(VTK_SurfaceTypeData%BladeShape,1), UBOUND(VTK_SurfaceTypeData%BladeShape,1) + CALL FAST_Destroyvtk_blsurfacetype( VTK_SurfaceTypeData%BladeShape(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(VTK_SurfaceTypeData%BladeShape) +ENDIF +IF (ALLOCATED(VTK_SurfaceTypeData%MorisonRad)) THEN + DEALLOCATE(VTK_SurfaceTypeData%MorisonRad) +ENDIF + END SUBROUTINE FAST_DestroyVTK_SurfaceType + + SUBROUTINE FAST_PackVTK_SurfaceType( 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(FAST_VTK_SurfaceType), 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 = 'FAST_PackVTK_SurfaceType' + ! 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 ! NumSectors + Re_BufSz = Re_BufSz + 1 ! HubRad + Re_BufSz = Re_BufSz + 1 ! GroundRad + Re_BufSz = Re_BufSz + SIZE(InData%NacelleBox) ! NacelleBox + Int_BufSz = Int_BufSz + 1 ! TowerRad allocated yes/no + IF ( ALLOCATED(InData%TowerRad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TowerRad upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TowerRad) ! TowerRad + END IF + Int_BufSz = Int_BufSz + SIZE(InData%NWaveElevPts) ! NWaveElevPts + Int_BufSz = Int_BufSz + 1 ! WaveElevXY allocated yes/no + IF ( ALLOCATED(InData%WaveElevXY) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElevXY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElevXY) ! WaveElevXY + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev allocated yes/no + IF ( ALLOCATED(InData%WaveElev) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev) ! WaveElev + END IF + Int_BufSz = Int_BufSz + 1 ! BladeShape allocated yes/no + IF ( ALLOCATED(InData%BladeShape) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BladeShape upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%BladeShape,1), UBOUND(InData%BladeShape,1) + Int_BufSz = Int_BufSz + 3 ! BladeShape: size of buffers for each call to pack subtype + CALL FAST_Packvtk_blsurfacetype( Re_Buf, Db_Buf, Int_Buf, InData%BladeShape(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BladeShape + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BladeShape + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BladeShape + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BladeShape + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MorisonRad allocated yes/no + IF ( ALLOCATED(InData%MorisonRad) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MorisonRad upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MorisonRad) ! MorisonRad + 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%NumSectors + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HubRad + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GroundRad + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%NacelleBox,2), UBOUND(InData%NacelleBox,2) + DO i1 = LBOUND(InData%NacelleBox,1), UBOUND(InData%NacelleBox,1) + ReKiBuf(Re_Xferred) = InData%NacelleBox(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( .NOT. ALLOCATED(InData%TowerRad) ) 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%TowerRad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TowerRad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TowerRad,1), UBOUND(InData%TowerRad,1) + ReKiBuf(Re_Xferred) = InData%TowerRad(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%NWaveElevPts,1), UBOUND(InData%NWaveElevPts,1) + IntKiBuf(Int_Xferred) = InData%NWaveElevPts(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%WaveElevXY) ) 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%WaveElevXY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElevXY,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElevXY,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElevXY,2), UBOUND(InData%WaveElevXY,2) + DO i1 = LBOUND(InData%WaveElevXY,1), UBOUND(InData%WaveElevXY,1) + ReKiBuf(Re_Xferred) = InData%WaveElevXY(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev) ) 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%WaveElev,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev,2), UBOUND(InData%WaveElev,2) + DO i1 = LBOUND(InData%WaveElev,1), UBOUND(InData%WaveElev,1) + ReKiBuf(Re_Xferred) = InData%WaveElev(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BladeShape) ) 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%BladeShape,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BladeShape,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BladeShape,1), UBOUND(InData%BladeShape,1) + CALL FAST_Packvtk_blsurfacetype( Re_Buf, Db_Buf, Int_Buf, InData%BladeShape(i1), ErrStat2, ErrMsg2, OnlySize ) ! BladeShape + 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%MorisonRad) ) 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%MorisonRad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MorisonRad,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MorisonRad,1), UBOUND(InData%MorisonRad,1) + ReKiBuf(Re_Xferred) = InData%MorisonRad(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackVTK_SurfaceType + + SUBROUTINE FAST_UnPackVTK_SurfaceType( 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(FAST_VTK_SurfaceType), 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 = 'FAST_UnPackVTK_SurfaceType' + ! 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%NumSectors = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HubRad = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + OutData%GroundRad = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%NacelleBox,1) + i1_u = UBOUND(OutData%NacelleBox,1) + i2_l = LBOUND(OutData%NacelleBox,2) + i2_u = UBOUND(OutData%NacelleBox,2) + DO i2 = LBOUND(OutData%NacelleBox,2), UBOUND(OutData%NacelleBox,2) + DO i1 = LBOUND(OutData%NacelleBox,1), UBOUND(OutData%NacelleBox,1) + OutData%NacelleBox(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TowerRad 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%TowerRad)) DEALLOCATE(OutData%TowerRad) + ALLOCATE(OutData%TowerRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TowerRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TowerRad,1), UBOUND(OutData%TowerRad,1) + OutData%TowerRad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%NWaveElevPts,1) + i1_u = UBOUND(OutData%NWaveElevPts,1) + DO i1 = LBOUND(OutData%NWaveElevPts,1), UBOUND(OutData%NWaveElevPts,1) + OutData%NWaveElevPts(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevXY 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%WaveElevXY)) DEALLOCATE(OutData%WaveElevXY) + ALLOCATE(OutData%WaveElevXY(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElevXY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElevXY,2), UBOUND(OutData%WaveElevXY,2) + DO i1 = LBOUND(OutData%WaveElevXY,1), UBOUND(OutData%WaveElevXY,1) + OutData%WaveElevXY(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev 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%WaveElev)) DEALLOCATE(OutData%WaveElev) + ALLOCATE(OutData%WaveElev(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev,2), UBOUND(OutData%WaveElev,2) + DO i1 = LBOUND(OutData%WaveElev,1), UBOUND(OutData%WaveElev,1) + OutData%WaveElev(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BladeShape 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%BladeShape)) DEALLOCATE(OutData%BladeShape) + ALLOCATE(OutData%BladeShape(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BladeShape.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BladeShape,1), UBOUND(OutData%BladeShape,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 FAST_Unpackvtk_blsurfacetype( Re_Buf, Db_Buf, Int_Buf, OutData%BladeShape(i1), ErrStat2, ErrMsg2 ) ! BladeShape + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MorisonRad 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%MorisonRad)) DEALLOCATE(OutData%MorisonRad) + ALLOCATE(OutData%MorisonRad(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MorisonRad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MorisonRad,1), UBOUND(OutData%MorisonRad,1) + OutData%MorisonRad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackVTK_SurfaceType + + SUBROUTINE FAST_CopyVTK_ModeShapeType( SrcVTK_ModeShapeTypeData, DstVTK_ModeShapeTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_VTK_ModeShapeType), INTENT(IN) :: SrcVTK_ModeShapeTypeData + TYPE(FAST_VTK_ModeShapeType), INTENT(INOUT) :: DstVTK_ModeShapeTypeData + 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CopyVTK_ModeShapeType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstVTK_ModeShapeTypeData%CheckpointRoot = SrcVTK_ModeShapeTypeData%CheckpointRoot + DstVTK_ModeShapeTypeData%MatlabFileName = SrcVTK_ModeShapeTypeData%MatlabFileName + DstVTK_ModeShapeTypeData%VTKLinModes = SrcVTK_ModeShapeTypeData%VTKLinModes +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%VTKModes)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%VTKModes,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%VTKModes,1) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%VTKModes)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%VTKModes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%VTKModes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%VTKModes = SrcVTK_ModeShapeTypeData%VTKModes +ENDIF + DstVTK_ModeShapeTypeData%VTKLinTim = SrcVTK_ModeShapeTypeData%VTKLinTim + DstVTK_ModeShapeTypeData%VTKNLinTimes = SrcVTK_ModeShapeTypeData%VTKNLinTimes + DstVTK_ModeShapeTypeData%VTKLinScale = SrcVTK_ModeShapeTypeData%VTKLinScale + DstVTK_ModeShapeTypeData%VTKLinPhase = SrcVTK_ModeShapeTypeData%VTKLinPhase +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%DampingRatio)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%DampingRatio,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%DampingRatio,1) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%DampingRatio)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%DampingRatio(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%DampingRatio.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%DampingRatio = SrcVTK_ModeShapeTypeData%DampingRatio +ENDIF +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%NaturalFreq_Hz)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%NaturalFreq_Hz,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%NaturalFreq_Hz,1) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%NaturalFreq_Hz)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%NaturalFreq_Hz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%NaturalFreq_Hz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%NaturalFreq_Hz = SrcVTK_ModeShapeTypeData%NaturalFreq_Hz +ENDIF +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%DampedFreq_Hz)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%DampedFreq_Hz,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%DampedFreq_Hz,1) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%DampedFreq_Hz)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%DampedFreq_Hz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%DampedFreq_Hz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%DampedFreq_Hz = SrcVTK_ModeShapeTypeData%DampedFreq_Hz +ENDIF +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%x_eig_magnitude)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,1) + i2_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,2) + i2_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,2) + i3_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,3) + i3_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_magnitude,3) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%x_eig_magnitude)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%x_eig_magnitude(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%x_eig_magnitude.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%x_eig_magnitude = SrcVTK_ModeShapeTypeData%x_eig_magnitude +ENDIF +IF (ALLOCATED(SrcVTK_ModeShapeTypeData%x_eig_phase)) THEN + i1_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,1) + i1_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,1) + i2_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,2) + i2_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,2) + i3_l = LBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,3) + i3_u = UBOUND(SrcVTK_ModeShapeTypeData%x_eig_phase,3) + IF (.NOT. ALLOCATED(DstVTK_ModeShapeTypeData%x_eig_phase)) THEN + ALLOCATE(DstVTK_ModeShapeTypeData%x_eig_phase(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_ModeShapeTypeData%x_eig_phase.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstVTK_ModeShapeTypeData%x_eig_phase = SrcVTK_ModeShapeTypeData%x_eig_phase +ENDIF + END SUBROUTINE FAST_CopyVTK_ModeShapeType + + SUBROUTINE FAST_DestroyVTK_ModeShapeType( VTK_ModeShapeTypeData, ErrStat, ErrMsg ) + TYPE(FAST_VTK_ModeShapeType), INTENT(INOUT) :: VTK_ModeShapeTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyVTK_ModeShapeType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(VTK_ModeShapeTypeData%VTKModes)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%VTKModes) +ENDIF +IF (ALLOCATED(VTK_ModeShapeTypeData%DampingRatio)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%DampingRatio) +ENDIF +IF (ALLOCATED(VTK_ModeShapeTypeData%NaturalFreq_Hz)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%NaturalFreq_Hz) +ENDIF +IF (ALLOCATED(VTK_ModeShapeTypeData%DampedFreq_Hz)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%DampedFreq_Hz) +ENDIF +IF (ALLOCATED(VTK_ModeShapeTypeData%x_eig_magnitude)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%x_eig_magnitude) +ENDIF +IF (ALLOCATED(VTK_ModeShapeTypeData%x_eig_phase)) THEN + DEALLOCATE(VTK_ModeShapeTypeData%x_eig_phase) +ENDIF + END SUBROUTINE FAST_DestroyVTK_ModeShapeType + + SUBROUTINE FAST_PackVTK_ModeShapeType( 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(FAST_VTK_ModeShapeType), 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 = 'FAST_PackVTK_ModeShapeType' + ! 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%CheckpointRoot) ! CheckpointRoot + Int_BufSz = Int_BufSz + 1*LEN(InData%MatlabFileName) ! MatlabFileName + Int_BufSz = Int_BufSz + 1 ! VTKLinModes + Int_BufSz = Int_BufSz + 1 ! VTKModes allocated yes/no + IF ( ALLOCATED(InData%VTKModes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VTKModes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%VTKModes) ! VTKModes + END IF + Int_BufSz = Int_BufSz + 1 ! VTKLinTim + Int_BufSz = Int_BufSz + 1 ! VTKNLinTimes + Re_BufSz = Re_BufSz + 1 ! VTKLinScale + Re_BufSz = Re_BufSz + 1 ! VTKLinPhase + Int_BufSz = Int_BufSz + 1 ! DampingRatio allocated yes/no + IF ( ALLOCATED(InData%DampingRatio) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DampingRatio upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DampingRatio) ! DampingRatio + END IF + Int_BufSz = Int_BufSz + 1 ! NaturalFreq_Hz allocated yes/no + IF ( ALLOCATED(InData%NaturalFreq_Hz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NaturalFreq_Hz upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%NaturalFreq_Hz) ! NaturalFreq_Hz + END IF + Int_BufSz = Int_BufSz + 1 ! DampedFreq_Hz allocated yes/no + IF ( ALLOCATED(InData%DampedFreq_Hz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DampedFreq_Hz upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%DampedFreq_Hz) ! DampedFreq_Hz + END IF + Int_BufSz = Int_BufSz + 1 ! x_eig_magnitude allocated yes/no + IF ( ALLOCATED(InData%x_eig_magnitude) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! x_eig_magnitude upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x_eig_magnitude) ! x_eig_magnitude + END IF + Int_BufSz = Int_BufSz + 1 ! x_eig_phase allocated yes/no + IF ( ALLOCATED(InData%x_eig_phase) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! x_eig_phase upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%x_eig_phase) ! x_eig_phase + 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%CheckpointRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%CheckpointRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%MatlabFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%MatlabFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%VTKLinModes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%VTKModes) ) 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%VTKModes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VTKModes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VTKModes,1), UBOUND(InData%VTKModes,1) + IntKiBuf(Int_Xferred) = InData%VTKModes(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%VTKLinTim + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTKNLinTimes + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VTKLinScale + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VTKLinPhase + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%DampingRatio) ) 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%DampingRatio,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampingRatio,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DampingRatio,1), UBOUND(InData%DampingRatio,1) + DbKiBuf(Db_Xferred) = InData%DampingRatio(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NaturalFreq_Hz) ) 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%NaturalFreq_Hz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NaturalFreq_Hz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NaturalFreq_Hz,1), UBOUND(InData%NaturalFreq_Hz,1) + DbKiBuf(Db_Xferred) = InData%NaturalFreq_Hz(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DampedFreq_Hz) ) 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%DampedFreq_Hz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DampedFreq_Hz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DampedFreq_Hz,1), UBOUND(InData%DampedFreq_Hz,1) + DbKiBuf(Db_Xferred) = InData%DampedFreq_Hz(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%x_eig_magnitude) ) 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%x_eig_magnitude,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_magnitude,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_eig_magnitude,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_magnitude,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_eig_magnitude,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_magnitude,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%x_eig_magnitude,3), UBOUND(InData%x_eig_magnitude,3) + DO i2 = LBOUND(InData%x_eig_magnitude,2), UBOUND(InData%x_eig_magnitude,2) + DO i1 = LBOUND(InData%x_eig_magnitude,1), UBOUND(InData%x_eig_magnitude,1) + DbKiBuf(Db_Xferred) = InData%x_eig_magnitude(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%x_eig_phase) ) 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%x_eig_phase,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_phase,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_eig_phase,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_phase,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_eig_phase,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_eig_phase,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%x_eig_phase,3), UBOUND(InData%x_eig_phase,3) + DO i2 = LBOUND(InData%x_eig_phase,2), UBOUND(InData%x_eig_phase,2) + DO i1 = LBOUND(InData%x_eig_phase,1), UBOUND(InData%x_eig_phase,1) + DbKiBuf(Db_Xferred) = InData%x_eig_phase(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FAST_PackVTK_ModeShapeType + + SUBROUTINE FAST_UnPackVTK_ModeShapeType( 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(FAST_VTK_ModeShapeType), 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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_UnPackVTK_ModeShapeType' + ! 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%CheckpointRoot) + OutData%CheckpointRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%MatlabFileName) + OutData%MatlabFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%VTKLinModes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VTKModes 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%VTKModes)) DEALLOCATE(OutData%VTKModes) + ALLOCATE(OutData%VTKModes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VTKModes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VTKModes,1), UBOUND(OutData%VTKModes,1) + OutData%VTKModes(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%VTKLinTim = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKNLinTimes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTKLinScale = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VTKLinPhase = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DampingRatio 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%DampingRatio)) DEALLOCATE(OutData%DampingRatio) + ALLOCATE(OutData%DampingRatio(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DampingRatio.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DampingRatio,1), UBOUND(OutData%DampingRatio,1) + OutData%DampingRatio(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NaturalFreq_Hz 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%NaturalFreq_Hz)) DEALLOCATE(OutData%NaturalFreq_Hz) + ALLOCATE(OutData%NaturalFreq_Hz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NaturalFreq_Hz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NaturalFreq_Hz,1), UBOUND(OutData%NaturalFreq_Hz,1) + OutData%NaturalFreq_Hz(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DampedFreq_Hz 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%DampedFreq_Hz)) DEALLOCATE(OutData%DampedFreq_Hz) + ALLOCATE(OutData%DampedFreq_Hz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DampedFreq_Hz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DampedFreq_Hz,1), UBOUND(OutData%DampedFreq_Hz,1) + OutData%DampedFreq_Hz(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_eig_magnitude 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%x_eig_magnitude)) DEALLOCATE(OutData%x_eig_magnitude) + ALLOCATE(OutData%x_eig_magnitude(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%x_eig_magnitude.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%x_eig_magnitude,3), UBOUND(OutData%x_eig_magnitude,3) + DO i2 = LBOUND(OutData%x_eig_magnitude,2), UBOUND(OutData%x_eig_magnitude,2) + DO i1 = LBOUND(OutData%x_eig_magnitude,1), UBOUND(OutData%x_eig_magnitude,1) + OutData%x_eig_magnitude(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_eig_phase 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%x_eig_phase)) DEALLOCATE(OutData%x_eig_phase) + ALLOCATE(OutData%x_eig_phase(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%x_eig_phase.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%x_eig_phase,3), UBOUND(OutData%x_eig_phase,3) + DO i2 = LBOUND(OutData%x_eig_phase,2), UBOUND(OutData%x_eig_phase,2) + DO i1 = LBOUND(OutData%x_eig_phase,1), UBOUND(OutData%x_eig_phase,1) + OutData%x_eig_phase(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE FAST_UnPackVTK_ModeShapeType + + SUBROUTINE FAST_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_ParameterType), INTENT(IN) :: SrcParamData + TYPE(FAST_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 = 'FAST_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%DT_module = SrcParamData%DT_module + DstParamData%n_substeps = SrcParamData%n_substeps + DstParamData%n_TMax_m1 = SrcParamData%n_TMax_m1 + DstParamData%TMax = SrcParamData%TMax + DstParamData%InterpOrder = SrcParamData%InterpOrder + DstParamData%NumCrctn = SrcParamData%NumCrctn + DstParamData%KMax = SrcParamData%KMax + DstParamData%numIceLegs = SrcParamData%numIceLegs + DstParamData%nBeams = SrcParamData%nBeams + DstParamData%BD_OutputSibling = SrcParamData%BD_OutputSibling + DstParamData%ModuleInitialized = SrcParamData%ModuleInitialized + DstParamData%DT_Ujac = SrcParamData%DT_Ujac + DstParamData%UJacSclFact = SrcParamData%UJacSclFact + DstParamData%SizeJac_Opt1 = SrcParamData%SizeJac_Opt1 + DstParamData%CompElast = SrcParamData%CompElast + DstParamData%CompInflow = SrcParamData%CompInflow + DstParamData%CompAero = SrcParamData%CompAero + DstParamData%CompServo = SrcParamData%CompServo + DstParamData%CompHydro = SrcParamData%CompHydro + DstParamData%CompSub = SrcParamData%CompSub + DstParamData%CompMooring = SrcParamData%CompMooring + DstParamData%CompIce = SrcParamData%CompIce + DstParamData%UseDWM = SrcParamData%UseDWM + DstParamData%Linearize = SrcParamData%Linearize + DstParamData%EDFile = SrcParamData%EDFile + DstParamData%BDBldFile = SrcParamData%BDBldFile + DstParamData%InflowFile = SrcParamData%InflowFile + DstParamData%AeroFile = SrcParamData%AeroFile + DstParamData%ServoFile = SrcParamData%ServoFile + DstParamData%HydroFile = SrcParamData%HydroFile + DstParamData%SubFile = SrcParamData%SubFile + DstParamData%MooringFile = SrcParamData%MooringFile + DstParamData%IceFile = SrcParamData%IceFile + DstParamData%TStart = SrcParamData%TStart + DstParamData%DT_Out = SrcParamData%DT_Out + DstParamData%WrSttsTime = SrcParamData%WrSttsTime + DstParamData%n_SttsTime = SrcParamData%n_SttsTime + DstParamData%n_ChkptTime = SrcParamData%n_ChkptTime + DstParamData%n_DT_Out = SrcParamData%n_DT_Out + DstParamData%n_VTKTime = SrcParamData%n_VTKTime + DstParamData%TurbineType = SrcParamData%TurbineType + DstParamData%WrBinOutFile = SrcParamData%WrBinOutFile + DstParamData%WrTxtOutFile = SrcParamData%WrTxtOutFile + DstParamData%WrBinMod = SrcParamData%WrBinMod + DstParamData%SumPrint = SrcParamData%SumPrint + DstParamData%WrVTK = SrcParamData%WrVTK + DstParamData%VTK_Type = SrcParamData%VTK_Type + DstParamData%VTK_fields = SrcParamData%VTK_fields + DstParamData%Delim = SrcParamData%Delim + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutFmt_t = SrcParamData%OutFmt_t + DstParamData%FmtWidth = SrcParamData%FmtWidth + DstParamData%TChanLen = SrcParamData%TChanLen + DstParamData%OutFileRoot = SrcParamData%OutFileRoot + DstParamData%FTitle = SrcParamData%FTitle + DstParamData%VTK_OutFileRoot = SrcParamData%VTK_OutFileRoot + DstParamData%VTK_tWidth = SrcParamData%VTK_tWidth + DstParamData%VTK_fps = SrcParamData%VTK_fps + CALL FAST_Copyvtk_surfacetype( SrcParamData%VTK_surface, DstParamData%VTK_surface, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%TurbinePos = SrcParamData%TurbinePos + DstParamData%Tdesc = SrcParamData%Tdesc + DstParamData%CalcSteady = SrcParamData%CalcSteady + DstParamData%TrimCase = SrcParamData%TrimCase + DstParamData%TrimTol = SrcParamData%TrimTol + DstParamData%TrimGain = SrcParamData%TrimGain + DstParamData%Twr_Kdmp = SrcParamData%Twr_Kdmp + DstParamData%Bld_Kdmp = SrcParamData%Bld_Kdmp + DstParamData%NLinTimes = SrcParamData%NLinTimes + DstParamData%AzimDelta = SrcParamData%AzimDelta + DstParamData%LinInputs = SrcParamData%LinInputs + DstParamData%LinOutputs = SrcParamData%LinOutputs + DstParamData%LinOutJac = SrcParamData%LinOutJac + DstParamData%LinOutMod = SrcParamData%LinOutMod + CALL FAST_Copyvtk_modeshapetype( SrcParamData%VTK_modes, DstParamData%VTK_modes, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstParamData%Lin_NumMods = SrcParamData%Lin_NumMods + DstParamData%Lin_ModOrder = SrcParamData%Lin_ModOrder + DstParamData%LinInterpOrder = SrcParamData%LinInterpOrder + END SUBROUTINE FAST_CopyParam + + SUBROUTINE FAST_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(FAST_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL FAST_Destroyvtk_surfacetype( ParamData%VTK_surface, ErrStat, ErrMsg ) + CALL FAST_Destroyvtk_modeshapetype( ParamData%VTK_modes, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyParam + + SUBROUTINE FAST_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(FAST_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 = 'FAST_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 + Db_BufSz = Db_BufSz + 1 ! DT + Db_BufSz = Db_BufSz + SIZE(InData%DT_module) ! DT_module + Int_BufSz = Int_BufSz + SIZE(InData%n_substeps) ! n_substeps + Int_BufSz = Int_BufSz + 1 ! n_TMax_m1 + Db_BufSz = Db_BufSz + 1 ! TMax + Int_BufSz = Int_BufSz + 1 ! InterpOrder + Int_BufSz = Int_BufSz + 1 ! NumCrctn + Int_BufSz = Int_BufSz + 1 ! KMax + Int_BufSz = Int_BufSz + 1 ! numIceLegs + Int_BufSz = Int_BufSz + 1 ! nBeams + Int_BufSz = Int_BufSz + 1 ! BD_OutputSibling + Int_BufSz = Int_BufSz + SIZE(InData%ModuleInitialized) ! ModuleInitialized + Db_BufSz = Db_BufSz + 1 ! DT_Ujac + Re_BufSz = Re_BufSz + 1 ! UJacSclFact + Int_BufSz = Int_BufSz + SIZE(InData%SizeJac_Opt1) ! SizeJac_Opt1 + Int_BufSz = Int_BufSz + 1 ! CompElast + Int_BufSz = Int_BufSz + 1 ! CompInflow + Int_BufSz = Int_BufSz + 1 ! CompAero + Int_BufSz = Int_BufSz + 1 ! CompServo + Int_BufSz = Int_BufSz + 1 ! CompHydro + Int_BufSz = Int_BufSz + 1 ! CompSub + Int_BufSz = Int_BufSz + 1 ! CompMooring + Int_BufSz = Int_BufSz + 1 ! CompIce + Int_BufSz = Int_BufSz + 1 ! UseDWM + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1*LEN(InData%EDFile) ! EDFile + Int_BufSz = Int_BufSz + SIZE(InData%BDBldFile)*LEN(InData%BDBldFile) ! BDBldFile + Int_BufSz = Int_BufSz + 1*LEN(InData%InflowFile) ! InflowFile + Int_BufSz = Int_BufSz + 1*LEN(InData%AeroFile) ! AeroFile + Int_BufSz = Int_BufSz + 1*LEN(InData%ServoFile) ! ServoFile + Int_BufSz = Int_BufSz + 1*LEN(InData%HydroFile) ! HydroFile + Int_BufSz = Int_BufSz + 1*LEN(InData%SubFile) ! SubFile + Int_BufSz = Int_BufSz + 1*LEN(InData%MooringFile) ! MooringFile + Int_BufSz = Int_BufSz + 1*LEN(InData%IceFile) ! IceFile + Db_BufSz = Db_BufSz + 1 ! TStart + Db_BufSz = Db_BufSz + 1 ! DT_Out + Int_BufSz = Int_BufSz + 1 ! WrSttsTime + Int_BufSz = Int_BufSz + 1 ! n_SttsTime + Int_BufSz = Int_BufSz + 1 ! n_ChkptTime + Int_BufSz = Int_BufSz + 1 ! n_DT_Out + Int_BufSz = Int_BufSz + 1 ! n_VTKTime + Int_BufSz = Int_BufSz + 1 ! TurbineType + Int_BufSz = Int_BufSz + 1 ! WrBinOutFile + Int_BufSz = Int_BufSz + 1 ! WrTxtOutFile + Int_BufSz = Int_BufSz + 1 ! WrBinMod + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! WrVTK + Int_BufSz = Int_BufSz + 1 ! VTK_Type + Int_BufSz = Int_BufSz + 1 ! VTK_fields + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt_t) ! OutFmt_t + Int_BufSz = Int_BufSz + 1 ! FmtWidth + Int_BufSz = Int_BufSz + 1 ! TChanLen + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFileRoot) ! OutFileRoot + Int_BufSz = Int_BufSz + 1*LEN(InData%FTitle) ! FTitle + Int_BufSz = Int_BufSz + 1*LEN(InData%VTK_OutFileRoot) ! VTK_OutFileRoot + Int_BufSz = Int_BufSz + 1 ! VTK_tWidth + Db_BufSz = Db_BufSz + 1 ! VTK_fps + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! VTK_surface: size of buffers for each call to pack subtype + CALL FAST_Packvtk_surfacetype( Re_Buf, Db_Buf, Int_Buf, InData%VTK_surface, ErrStat2, ErrMsg2, .TRUE. ) ! VTK_surface + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! VTK_surface + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! VTK_surface + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! VTK_surface + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + SIZE(InData%TurbinePos) ! TurbinePos + Int_BufSz = Int_BufSz + 1*LEN(InData%Tdesc) ! Tdesc + Int_BufSz = Int_BufSz + 1 ! CalcSteady + Int_BufSz = Int_BufSz + 1 ! TrimCase + Re_BufSz = Re_BufSz + 1 ! TrimTol + Re_BufSz = Re_BufSz + 1 ! TrimGain + Re_BufSz = Re_BufSz + 1 ! Twr_Kdmp + Re_BufSz = Re_BufSz + 1 ! Bld_Kdmp + Int_BufSz = Int_BufSz + 1 ! NLinTimes + Db_BufSz = Db_BufSz + 1 ! AzimDelta + Int_BufSz = Int_BufSz + 1 ! LinInputs + Int_BufSz = Int_BufSz + 1 ! LinOutputs + Int_BufSz = Int_BufSz + 1 ! LinOutJac + Int_BufSz = Int_BufSz + 1 ! LinOutMod + Int_BufSz = Int_BufSz + 3 ! VTK_modes: size of buffers for each call to pack subtype + CALL FAST_Packvtk_modeshapetype( Re_Buf, Db_Buf, Int_Buf, InData%VTK_modes, ErrStat2, ErrMsg2, .TRUE. ) ! VTK_modes + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! VTK_modes + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! VTK_modes + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! VTK_modes + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Lin_NumMods + Int_BufSz = Int_BufSz + SIZE(InData%Lin_ModOrder) ! Lin_ModOrder + Int_BufSz = Int_BufSz + 1 ! LinInterpOrder + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%DT_module,1), UBOUND(InData%DT_module,1) + DbKiBuf(Db_Xferred) = InData%DT_module(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%n_substeps,1), UBOUND(InData%n_substeps,1) + IntKiBuf(Int_Xferred) = InData%n_substeps(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%n_TMax_m1 + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TMax + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%InterpOrder + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCrctn + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%KMax + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%numIceLegs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nBeams + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BD_OutputSibling, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%ModuleInitialized,1), UBOUND(InData%ModuleInitialized,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%ModuleInitialized(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%DT_Ujac + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UJacSclFact + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%SizeJac_Opt1,1), UBOUND(InData%SizeJac_Opt1,1) + IntKiBuf(Int_Xferred) = InData%SizeJac_Opt1(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%CompElast + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompInflow + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompAero + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompServo + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompHydro + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompSub + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompMooring + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%CompIce + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseDWM, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%EDFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%EDFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%BDBldFile,1), UBOUND(InData%BDBldFile,1) + DO I = 1, LEN(InData%BDBldFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%BDBldFile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + DO I = 1, LEN(InData%InflowFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InflowFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%AeroFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%AeroFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%ServoFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%ServoFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%HydroFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%HydroFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%SubFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SubFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%MooringFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%MooringFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%IceFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%IceFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%TStart + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT_Out + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WrSttsTime, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_SttsTime + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_ChkptTime + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_DT_Out + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_VTKTime + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TurbineType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WrBinOutFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WrTxtOutFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WrBinMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WrVTK + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTK_Type + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%VTK_fields, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutFmt_t) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt_t(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%FmtWidth + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TChanLen + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFileRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFileRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%FTitle) + IntKiBuf(Int_Xferred) = ICHAR(InData%FTitle(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%VTK_OutFileRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%VTK_OutFileRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%VTK_tWidth + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%VTK_fps + Db_Xferred = Db_Xferred + 1 + CALL FAST_Packvtk_surfacetype( Re_Buf, Db_Buf, Int_Buf, InData%VTK_surface, ErrStat2, ErrMsg2, OnlySize ) ! VTK_surface + 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%TurbinePos,1), UBOUND(InData%TurbinePos,1) + ReKiBuf(Re_Xferred) = InData%TurbinePos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(InData%Tdesc) + IntKiBuf(Int_Xferred) = ICHAR(InData%Tdesc(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcSteady, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TrimCase + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TrimTol + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TrimGain + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Twr_Kdmp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Bld_Kdmp + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NLinTimes + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%AzimDelta + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%LinInputs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%LinOutputs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LinOutJac, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LinOutMod, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL FAST_Packvtk_modeshapetype( Re_Buf, Db_Buf, Int_Buf, InData%VTK_modes, ErrStat2, ErrMsg2, OnlySize ) ! VTK_modes + 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%Lin_NumMods + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%Lin_ModOrder,1), UBOUND(InData%Lin_ModOrder,1) + IntKiBuf(Int_Xferred) = InData%Lin_ModOrder(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%LinInterpOrder + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_PackParam + + SUBROUTINE FAST_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(FAST_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 = 'FAST_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%DT_module,1) + i1_u = UBOUND(OutData%DT_module,1) + DO i1 = LBOUND(OutData%DT_module,1), UBOUND(OutData%DT_module,1) + OutData%DT_module(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%n_substeps,1) + i1_u = UBOUND(OutData%n_substeps,1) + DO i1 = LBOUND(OutData%n_substeps,1), UBOUND(OutData%n_substeps,1) + OutData%n_substeps(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%n_TMax_m1 = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%InterpOrder = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumCrctn = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%KMax = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%numIceLegs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nBeams = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BD_OutputSibling = TRANSFER(IntKiBuf(Int_Xferred), OutData%BD_OutputSibling) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%ModuleInitialized,1) + i1_u = UBOUND(OutData%ModuleInitialized,1) + DO i1 = LBOUND(OutData%ModuleInitialized,1), UBOUND(OutData%ModuleInitialized,1) + OutData%ModuleInitialized(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%ModuleInitialized(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%DT_Ujac = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%UJacSclFact = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%SizeJac_Opt1,1) + i1_u = UBOUND(OutData%SizeJac_Opt1,1) + DO i1 = LBOUND(OutData%SizeJac_Opt1,1), UBOUND(OutData%SizeJac_Opt1,1) + OutData%SizeJac_Opt1(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%CompElast = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompInflow = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompAero = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompServo = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompHydro = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompSub = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompMooring = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompIce = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UseDWM = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseDWM) + Int_Xferred = Int_Xferred + 1 + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%EDFile) + OutData%EDFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%BDBldFile,1) + i1_u = UBOUND(OutData%BDBldFile,1) + DO i1 = LBOUND(OutData%BDBldFile,1), UBOUND(OutData%BDBldFile,1) + DO I = 1, LEN(OutData%BDBldFile) + OutData%BDBldFile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + DO I = 1, LEN(OutData%InflowFile) + OutData%InflowFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%AeroFile) + OutData%AeroFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%ServoFile) + OutData%ServoFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%HydroFile) + OutData%HydroFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%SubFile) + OutData%SubFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%MooringFile) + OutData%MooringFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%IceFile) + OutData%IceFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%TStart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DT_Out = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%WrSttsTime = TRANSFER(IntKiBuf(Int_Xferred), OutData%WrSttsTime) + Int_Xferred = Int_Xferred + 1 + OutData%n_SttsTime = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_ChkptTime = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_DT_Out = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%n_VTKTime = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TurbineType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WrBinOutFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%WrBinOutFile) + Int_Xferred = Int_Xferred + 1 + OutData%WrTxtOutFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%WrTxtOutFile) + Int_Xferred = Int_Xferred + 1 + OutData%WrBinMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%WrVTK = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTK_Type = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTK_fields = TRANSFER(IntKiBuf(Int_Xferred), OutData%VTK_fields) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutFmt_t) + OutData%OutFmt_t(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%FmtWidth = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TChanLen = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFileRoot) + OutData%OutFileRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%FTitle) + OutData%FTitle(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%VTK_OutFileRoot) + OutData%VTK_OutFileRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%VTK_tWidth = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTK_fps = DbKiBuf(Db_Xferred) + Db_Xferred = Db_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 FAST_Unpackvtk_surfacetype( Re_Buf, Db_Buf, Int_Buf, OutData%VTK_surface, ErrStat2, ErrMsg2 ) ! VTK_surface + 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%TurbinePos,1) + i1_u = UBOUND(OutData%TurbinePos,1) + DO i1 = LBOUND(OutData%TurbinePos,1), UBOUND(OutData%TurbinePos,1) + OutData%TurbinePos(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(OutData%Tdesc) + OutData%Tdesc(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CalcSteady = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcSteady) + Int_Xferred = Int_Xferred + 1 + OutData%TrimCase = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TrimTol = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TrimGain = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Twr_Kdmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Bld_Kdmp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NLinTimes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AzimDelta = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%LinInputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%LinOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%LinOutJac = TRANSFER(IntKiBuf(Int_Xferred), OutData%LinOutJac) + Int_Xferred = Int_Xferred + 1 + OutData%LinOutMod = TRANSFER(IntKiBuf(Int_Xferred), OutData%LinOutMod) + 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 FAST_Unpackvtk_modeshapetype( Re_Buf, Db_Buf, Int_Buf, OutData%VTK_modes, ErrStat2, ErrMsg2 ) ! VTK_modes + 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%Lin_NumMods = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%Lin_ModOrder,1) + i1_u = UBOUND(OutData%Lin_ModOrder,1) + DO i1 = LBOUND(OutData%Lin_ModOrder,1), UBOUND(OutData%Lin_ModOrder,1) + OutData%Lin_ModOrder(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%LinInterpOrder = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_UnPackParam + + SUBROUTINE FAST_CopyLinStateSave( SrcLinStateSaveData, DstLinStateSaveData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_LinStateSave), INTENT(INOUT) :: SrcLinStateSaveData + TYPE(FAST_LinStateSave), INTENT(INOUT) :: DstLinStateSaveData + 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 = 'FAST_CopyLinStateSave' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcLinStateSaveData%x_IceD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_IceD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_IceD,1) + i2_l = LBOUND(SrcLinStateSaveData%x_IceD,2) + i2_u = UBOUND(SrcLinStateSaveData%x_IceD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_IceD)) THEN + ALLOCATE(DstLinStateSaveData%x_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%x_IceD,2), UBOUND(SrcLinStateSaveData%x_IceD,2) + DO i1 = LBOUND(SrcLinStateSaveData%x_IceD,1), UBOUND(SrcLinStateSaveData%x_IceD,1) + CALL IceD_CopyContState( SrcLinStateSaveData%x_IceD(i1,i2), DstLinStateSaveData%x_IceD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_IceD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_IceD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_IceD,1) + i2_l = LBOUND(SrcLinStateSaveData%xd_IceD,2) + i2_u = UBOUND(SrcLinStateSaveData%xd_IceD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_IceD)) THEN + ALLOCATE(DstLinStateSaveData%xd_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%xd_IceD,2), UBOUND(SrcLinStateSaveData%xd_IceD,2) + DO i1 = LBOUND(SrcLinStateSaveData%xd_IceD,1), UBOUND(SrcLinStateSaveData%xd_IceD,1) + CALL IceD_CopyDiscState( SrcLinStateSaveData%xd_IceD(i1,i2), DstLinStateSaveData%xd_IceD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_IceD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_IceD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_IceD,1) + i2_l = LBOUND(SrcLinStateSaveData%z_IceD,2) + i2_u = UBOUND(SrcLinStateSaveData%z_IceD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_IceD)) THEN + ALLOCATE(DstLinStateSaveData%z_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%z_IceD,2), UBOUND(SrcLinStateSaveData%z_IceD,2) + DO i1 = LBOUND(SrcLinStateSaveData%z_IceD,1), UBOUND(SrcLinStateSaveData%z_IceD,1) + CALL IceD_CopyConstrState( SrcLinStateSaveData%z_IceD(i1,i2), DstLinStateSaveData%z_IceD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_IceD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_IceD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_IceD,1) + i2_l = LBOUND(SrcLinStateSaveData%OtherSt_IceD,2) + i2_u = UBOUND(SrcLinStateSaveData%OtherSt_IceD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_IceD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%OtherSt_IceD,2), UBOUND(SrcLinStateSaveData%OtherSt_IceD,2) + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_IceD,1), UBOUND(SrcLinStateSaveData%OtherSt_IceD,1) + CALL IceD_CopyOtherState( SrcLinStateSaveData%OtherSt_IceD(i1,i2), DstLinStateSaveData%OtherSt_IceD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_IceD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_IceD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_IceD,1) + i2_l = LBOUND(SrcLinStateSaveData%u_IceD,2) + i2_u = UBOUND(SrcLinStateSaveData%u_IceD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_IceD)) THEN + ALLOCATE(DstLinStateSaveData%u_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%u_IceD,2), UBOUND(SrcLinStateSaveData%u_IceD,2) + DO i1 = LBOUND(SrcLinStateSaveData%u_IceD,1), UBOUND(SrcLinStateSaveData%u_IceD,1) + CALL IceD_CopyInput( SrcLinStateSaveData%u_IceD(i1,i2), DstLinStateSaveData%u_IceD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_BD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_BD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_BD,1) + i2_l = LBOUND(SrcLinStateSaveData%x_BD,2) + i2_u = UBOUND(SrcLinStateSaveData%x_BD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_BD)) THEN + ALLOCATE(DstLinStateSaveData%x_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%x_BD,2), UBOUND(SrcLinStateSaveData%x_BD,2) + DO i1 = LBOUND(SrcLinStateSaveData%x_BD,1), UBOUND(SrcLinStateSaveData%x_BD,1) + CALL BD_CopyContState( SrcLinStateSaveData%x_BD(i1,i2), DstLinStateSaveData%x_BD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_BD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_BD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_BD,1) + i2_l = LBOUND(SrcLinStateSaveData%xd_BD,2) + i2_u = UBOUND(SrcLinStateSaveData%xd_BD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_BD)) THEN + ALLOCATE(DstLinStateSaveData%xd_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%xd_BD,2), UBOUND(SrcLinStateSaveData%xd_BD,2) + DO i1 = LBOUND(SrcLinStateSaveData%xd_BD,1), UBOUND(SrcLinStateSaveData%xd_BD,1) + CALL BD_CopyDiscState( SrcLinStateSaveData%xd_BD(i1,i2), DstLinStateSaveData%xd_BD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_BD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_BD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_BD,1) + i2_l = LBOUND(SrcLinStateSaveData%z_BD,2) + i2_u = UBOUND(SrcLinStateSaveData%z_BD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_BD)) THEN + ALLOCATE(DstLinStateSaveData%z_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%z_BD,2), UBOUND(SrcLinStateSaveData%z_BD,2) + DO i1 = LBOUND(SrcLinStateSaveData%z_BD,1), UBOUND(SrcLinStateSaveData%z_BD,1) + CALL BD_CopyConstrState( SrcLinStateSaveData%z_BD(i1,i2), DstLinStateSaveData%z_BD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_BD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_BD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_BD,1) + i2_l = LBOUND(SrcLinStateSaveData%OtherSt_BD,2) + i2_u = UBOUND(SrcLinStateSaveData%OtherSt_BD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_BD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%OtherSt_BD,2), UBOUND(SrcLinStateSaveData%OtherSt_BD,2) + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_BD,1), UBOUND(SrcLinStateSaveData%OtherSt_BD,1) + CALL BD_CopyOtherState( SrcLinStateSaveData%OtherSt_BD(i1,i2), DstLinStateSaveData%OtherSt_BD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_BD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_BD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_BD,1) + i2_l = LBOUND(SrcLinStateSaveData%u_BD,2) + i2_u = UBOUND(SrcLinStateSaveData%u_BD,2) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_BD)) THEN + ALLOCATE(DstLinStateSaveData%u_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcLinStateSaveData%u_BD,2), UBOUND(SrcLinStateSaveData%u_BD,2) + DO i1 = LBOUND(SrcLinStateSaveData%u_BD,1), UBOUND(SrcLinStateSaveData%u_BD,1) + CALL BD_CopyInput( SrcLinStateSaveData%u_BD(i1,i2), DstLinStateSaveData%u_BD(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_ED)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_ED,1) + i1_u = UBOUND(SrcLinStateSaveData%x_ED,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_ED)) THEN + ALLOCATE(DstLinStateSaveData%x_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_ED,1), UBOUND(SrcLinStateSaveData%x_ED,1) + CALL ED_CopyContState( SrcLinStateSaveData%x_ED(i1), DstLinStateSaveData%x_ED(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_ED)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_ED,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_ED,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_ED)) THEN + ALLOCATE(DstLinStateSaveData%xd_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_ED,1), UBOUND(SrcLinStateSaveData%xd_ED,1) + CALL ED_CopyDiscState( SrcLinStateSaveData%xd_ED(i1), DstLinStateSaveData%xd_ED(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_ED)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_ED,1) + i1_u = UBOUND(SrcLinStateSaveData%z_ED,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_ED)) THEN + ALLOCATE(DstLinStateSaveData%z_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_ED,1), UBOUND(SrcLinStateSaveData%z_ED,1) + CALL ED_CopyConstrState( SrcLinStateSaveData%z_ED(i1), DstLinStateSaveData%z_ED(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_ED)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_ED,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_ED,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_ED)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_ED,1), UBOUND(SrcLinStateSaveData%OtherSt_ED,1) + CALL ED_CopyOtherState( SrcLinStateSaveData%OtherSt_ED(i1), DstLinStateSaveData%OtherSt_ED(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_ED)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_ED,1) + i1_u = UBOUND(SrcLinStateSaveData%u_ED,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_ED)) THEN + ALLOCATE(DstLinStateSaveData%u_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_ED,1), UBOUND(SrcLinStateSaveData%u_ED,1) + CALL ED_CopyInput( SrcLinStateSaveData%u_ED(i1), DstLinStateSaveData%u_ED(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_SrvD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_SrvD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_SrvD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_SrvD)) THEN + ALLOCATE(DstLinStateSaveData%x_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_SrvD,1), UBOUND(SrcLinStateSaveData%x_SrvD,1) + CALL SrvD_CopyContState( SrcLinStateSaveData%x_SrvD(i1), DstLinStateSaveData%x_SrvD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_SrvD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_SrvD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_SrvD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_SrvD)) THEN + ALLOCATE(DstLinStateSaveData%xd_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_SrvD,1), UBOUND(SrcLinStateSaveData%xd_SrvD,1) + CALL SrvD_CopyDiscState( SrcLinStateSaveData%xd_SrvD(i1), DstLinStateSaveData%xd_SrvD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_SrvD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_SrvD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_SrvD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_SrvD)) THEN + ALLOCATE(DstLinStateSaveData%z_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_SrvD,1), UBOUND(SrcLinStateSaveData%z_SrvD,1) + CALL SrvD_CopyConstrState( SrcLinStateSaveData%z_SrvD(i1), DstLinStateSaveData%z_SrvD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_SrvD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_SrvD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_SrvD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_SrvD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_SrvD,1), UBOUND(SrcLinStateSaveData%OtherSt_SrvD,1) + CALL SrvD_CopyOtherState( SrcLinStateSaveData%OtherSt_SrvD(i1), DstLinStateSaveData%OtherSt_SrvD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_SrvD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_SrvD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_SrvD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_SrvD)) THEN + ALLOCATE(DstLinStateSaveData%u_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_SrvD,1), UBOUND(SrcLinStateSaveData%u_SrvD,1) + CALL SrvD_CopyInput( SrcLinStateSaveData%u_SrvD(i1), DstLinStateSaveData%u_SrvD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_AD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_AD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_AD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_AD)) THEN + ALLOCATE(DstLinStateSaveData%x_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_AD,1), UBOUND(SrcLinStateSaveData%x_AD,1) + CALL AD_CopyContState( SrcLinStateSaveData%x_AD(i1), DstLinStateSaveData%x_AD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_AD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_AD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_AD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_AD)) THEN + ALLOCATE(DstLinStateSaveData%xd_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_AD,1), UBOUND(SrcLinStateSaveData%xd_AD,1) + CALL AD_CopyDiscState( SrcLinStateSaveData%xd_AD(i1), DstLinStateSaveData%xd_AD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_AD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_AD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_AD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_AD)) THEN + ALLOCATE(DstLinStateSaveData%z_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_AD,1), UBOUND(SrcLinStateSaveData%z_AD,1) + CALL AD_CopyConstrState( SrcLinStateSaveData%z_AD(i1), DstLinStateSaveData%z_AD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_AD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_AD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_AD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_AD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_AD,1), UBOUND(SrcLinStateSaveData%OtherSt_AD,1) + CALL AD_CopyOtherState( SrcLinStateSaveData%OtherSt_AD(i1), DstLinStateSaveData%OtherSt_AD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_AD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_AD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_AD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_AD)) THEN + ALLOCATE(DstLinStateSaveData%u_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_AD,1), UBOUND(SrcLinStateSaveData%u_AD,1) + CALL AD_CopyInput( SrcLinStateSaveData%u_AD(i1), DstLinStateSaveData%u_AD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_IfW)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_IfW,1) + i1_u = UBOUND(SrcLinStateSaveData%x_IfW,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_IfW)) THEN + ALLOCATE(DstLinStateSaveData%x_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_IfW,1), UBOUND(SrcLinStateSaveData%x_IfW,1) + CALL InflowWind_CopyContState( SrcLinStateSaveData%x_IfW(i1), DstLinStateSaveData%x_IfW(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_IfW)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_IfW,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_IfW,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_IfW)) THEN + ALLOCATE(DstLinStateSaveData%xd_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_IfW,1), UBOUND(SrcLinStateSaveData%xd_IfW,1) + CALL InflowWind_CopyDiscState( SrcLinStateSaveData%xd_IfW(i1), DstLinStateSaveData%xd_IfW(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_IfW)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_IfW,1) + i1_u = UBOUND(SrcLinStateSaveData%z_IfW,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_IfW)) THEN + ALLOCATE(DstLinStateSaveData%z_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_IfW,1), UBOUND(SrcLinStateSaveData%z_IfW,1) + CALL InflowWind_CopyConstrState( SrcLinStateSaveData%z_IfW(i1), DstLinStateSaveData%z_IfW(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_IfW)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_IfW,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_IfW,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_IfW)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_IfW,1), UBOUND(SrcLinStateSaveData%OtherSt_IfW,1) + CALL InflowWind_CopyOtherState( SrcLinStateSaveData%OtherSt_IfW(i1), DstLinStateSaveData%OtherSt_IfW(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_IfW)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_IfW,1) + i1_u = UBOUND(SrcLinStateSaveData%u_IfW,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_IfW)) THEN + ALLOCATE(DstLinStateSaveData%u_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_IfW,1), UBOUND(SrcLinStateSaveData%u_IfW,1) + CALL InflowWind_CopyInput( SrcLinStateSaveData%u_IfW(i1), DstLinStateSaveData%u_IfW(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_SD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_SD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_SD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_SD)) THEN + ALLOCATE(DstLinStateSaveData%x_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_SD,1), UBOUND(SrcLinStateSaveData%x_SD,1) + CALL SD_CopyContState( SrcLinStateSaveData%x_SD(i1), DstLinStateSaveData%x_SD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_SD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_SD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_SD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_SD)) THEN + ALLOCATE(DstLinStateSaveData%xd_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_SD,1), UBOUND(SrcLinStateSaveData%xd_SD,1) + CALL SD_CopyDiscState( SrcLinStateSaveData%xd_SD(i1), DstLinStateSaveData%xd_SD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_SD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_SD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_SD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_SD)) THEN + ALLOCATE(DstLinStateSaveData%z_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_SD,1), UBOUND(SrcLinStateSaveData%z_SD,1) + CALL SD_CopyConstrState( SrcLinStateSaveData%z_SD(i1), DstLinStateSaveData%z_SD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_SD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_SD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_SD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_SD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_SD,1), UBOUND(SrcLinStateSaveData%OtherSt_SD,1) + CALL SD_CopyOtherState( SrcLinStateSaveData%OtherSt_SD(i1), DstLinStateSaveData%OtherSt_SD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_SD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_SD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_SD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_SD)) THEN + ALLOCATE(DstLinStateSaveData%u_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_SD,1), UBOUND(SrcLinStateSaveData%u_SD,1) + CALL SD_CopyInput( SrcLinStateSaveData%u_SD(i1), DstLinStateSaveData%u_SD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_ExtPtfm)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_ExtPtfm,1) + i1_u = UBOUND(SrcLinStateSaveData%x_ExtPtfm,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_ExtPtfm)) THEN + ALLOCATE(DstLinStateSaveData%x_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_ExtPtfm,1), UBOUND(SrcLinStateSaveData%x_ExtPtfm,1) + CALL ExtPtfm_CopyContState( SrcLinStateSaveData%x_ExtPtfm(i1), DstLinStateSaveData%x_ExtPtfm(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_ExtPtfm)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_ExtPtfm,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_ExtPtfm,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_ExtPtfm)) THEN + ALLOCATE(DstLinStateSaveData%xd_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_ExtPtfm,1), UBOUND(SrcLinStateSaveData%xd_ExtPtfm,1) + CALL ExtPtfm_CopyDiscState( SrcLinStateSaveData%xd_ExtPtfm(i1), DstLinStateSaveData%xd_ExtPtfm(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_ExtPtfm)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_ExtPtfm,1) + i1_u = UBOUND(SrcLinStateSaveData%z_ExtPtfm,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_ExtPtfm)) THEN + ALLOCATE(DstLinStateSaveData%z_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_ExtPtfm,1), UBOUND(SrcLinStateSaveData%z_ExtPtfm,1) + CALL ExtPtfm_CopyConstrState( SrcLinStateSaveData%z_ExtPtfm(i1), DstLinStateSaveData%z_ExtPtfm(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_ExtPtfm)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_ExtPtfm,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_ExtPtfm,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_ExtPtfm)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_ExtPtfm,1), UBOUND(SrcLinStateSaveData%OtherSt_ExtPtfm,1) + CALL ExtPtfm_CopyOtherState( SrcLinStateSaveData%OtherSt_ExtPtfm(i1), DstLinStateSaveData%OtherSt_ExtPtfm(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_ExtPtfm)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_ExtPtfm,1) + i1_u = UBOUND(SrcLinStateSaveData%u_ExtPtfm,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_ExtPtfm)) THEN + ALLOCATE(DstLinStateSaveData%u_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_ExtPtfm,1), UBOUND(SrcLinStateSaveData%u_ExtPtfm,1) + CALL ExtPtfm_CopyInput( SrcLinStateSaveData%u_ExtPtfm(i1), DstLinStateSaveData%u_ExtPtfm(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_HD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_HD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_HD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_HD)) THEN + ALLOCATE(DstLinStateSaveData%x_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_HD,1), UBOUND(SrcLinStateSaveData%x_HD,1) + CALL HydroDyn_CopyContState( SrcLinStateSaveData%x_HD(i1), DstLinStateSaveData%x_HD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_HD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_HD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_HD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_HD)) THEN + ALLOCATE(DstLinStateSaveData%xd_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_HD,1), UBOUND(SrcLinStateSaveData%xd_HD,1) + CALL HydroDyn_CopyDiscState( SrcLinStateSaveData%xd_HD(i1), DstLinStateSaveData%xd_HD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_HD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_HD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_HD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_HD)) THEN + ALLOCATE(DstLinStateSaveData%z_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_HD,1), UBOUND(SrcLinStateSaveData%z_HD,1) + CALL HydroDyn_CopyConstrState( SrcLinStateSaveData%z_HD(i1), DstLinStateSaveData%z_HD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_HD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_HD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_HD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_HD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_HD,1), UBOUND(SrcLinStateSaveData%OtherSt_HD,1) + CALL HydroDyn_CopyOtherState( SrcLinStateSaveData%OtherSt_HD(i1), DstLinStateSaveData%OtherSt_HD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_HD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_HD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_HD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_HD)) THEN + ALLOCATE(DstLinStateSaveData%u_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_HD,1), UBOUND(SrcLinStateSaveData%u_HD,1) + CALL HydroDyn_CopyInput( SrcLinStateSaveData%u_HD(i1), DstLinStateSaveData%u_HD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_IceF)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_IceF,1) + i1_u = UBOUND(SrcLinStateSaveData%x_IceF,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_IceF)) THEN + ALLOCATE(DstLinStateSaveData%x_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_IceF,1), UBOUND(SrcLinStateSaveData%x_IceF,1) + CALL IceFloe_CopyContState( SrcLinStateSaveData%x_IceF(i1), DstLinStateSaveData%x_IceF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_IceF)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_IceF,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_IceF,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_IceF)) THEN + ALLOCATE(DstLinStateSaveData%xd_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_IceF,1), UBOUND(SrcLinStateSaveData%xd_IceF,1) + CALL IceFloe_CopyDiscState( SrcLinStateSaveData%xd_IceF(i1), DstLinStateSaveData%xd_IceF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_IceF)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_IceF,1) + i1_u = UBOUND(SrcLinStateSaveData%z_IceF,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_IceF)) THEN + ALLOCATE(DstLinStateSaveData%z_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_IceF,1), UBOUND(SrcLinStateSaveData%z_IceF,1) + CALL IceFloe_CopyConstrState( SrcLinStateSaveData%z_IceF(i1), DstLinStateSaveData%z_IceF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_IceF)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_IceF,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_IceF,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_IceF)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_IceF,1), UBOUND(SrcLinStateSaveData%OtherSt_IceF,1) + CALL IceFloe_CopyOtherState( SrcLinStateSaveData%OtherSt_IceF(i1), DstLinStateSaveData%OtherSt_IceF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_IceF)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_IceF,1) + i1_u = UBOUND(SrcLinStateSaveData%u_IceF,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_IceF)) THEN + ALLOCATE(DstLinStateSaveData%u_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_IceF,1), UBOUND(SrcLinStateSaveData%u_IceF,1) + CALL IceFloe_CopyInput( SrcLinStateSaveData%u_IceF(i1), DstLinStateSaveData%u_IceF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_MAP)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_MAP,1) + i1_u = UBOUND(SrcLinStateSaveData%x_MAP,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_MAP)) THEN + ALLOCATE(DstLinStateSaveData%x_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_MAP,1), UBOUND(SrcLinStateSaveData%x_MAP,1) + CALL MAP_CopyContState( SrcLinStateSaveData%x_MAP(i1), DstLinStateSaveData%x_MAP(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_MAP)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_MAP,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_MAP,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_MAP)) THEN + ALLOCATE(DstLinStateSaveData%xd_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_MAP,1), UBOUND(SrcLinStateSaveData%xd_MAP,1) + CALL MAP_CopyDiscState( SrcLinStateSaveData%xd_MAP(i1), DstLinStateSaveData%xd_MAP(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_MAP)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_MAP,1) + i1_u = UBOUND(SrcLinStateSaveData%z_MAP,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_MAP)) THEN + ALLOCATE(DstLinStateSaveData%z_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_MAP,1), UBOUND(SrcLinStateSaveData%z_MAP,1) + CALL MAP_CopyConstrState( SrcLinStateSaveData%z_MAP(i1), DstLinStateSaveData%z_MAP(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_MAP)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_MAP,1) + i1_u = UBOUND(SrcLinStateSaveData%u_MAP,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_MAP)) THEN + ALLOCATE(DstLinStateSaveData%u_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_MAP,1), UBOUND(SrcLinStateSaveData%u_MAP,1) + CALL MAP_CopyInput( SrcLinStateSaveData%u_MAP(i1), DstLinStateSaveData%u_MAP(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_FEAM)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_FEAM,1) + i1_u = UBOUND(SrcLinStateSaveData%x_FEAM,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_FEAM)) THEN + ALLOCATE(DstLinStateSaveData%x_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_FEAM,1), UBOUND(SrcLinStateSaveData%x_FEAM,1) + CALL FEAM_CopyContState( SrcLinStateSaveData%x_FEAM(i1), DstLinStateSaveData%x_FEAM(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_FEAM)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_FEAM,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_FEAM,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_FEAM)) THEN + ALLOCATE(DstLinStateSaveData%xd_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_FEAM,1), UBOUND(SrcLinStateSaveData%xd_FEAM,1) + CALL FEAM_CopyDiscState( SrcLinStateSaveData%xd_FEAM(i1), DstLinStateSaveData%xd_FEAM(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_FEAM)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_FEAM,1) + i1_u = UBOUND(SrcLinStateSaveData%z_FEAM,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_FEAM)) THEN + ALLOCATE(DstLinStateSaveData%z_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_FEAM,1), UBOUND(SrcLinStateSaveData%z_FEAM,1) + CALL FEAM_CopyConstrState( SrcLinStateSaveData%z_FEAM(i1), DstLinStateSaveData%z_FEAM(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_FEAM)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_FEAM,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_FEAM,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_FEAM)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_FEAM,1), UBOUND(SrcLinStateSaveData%OtherSt_FEAM,1) + CALL FEAM_CopyOtherState( SrcLinStateSaveData%OtherSt_FEAM(i1), DstLinStateSaveData%OtherSt_FEAM(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_FEAM)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_FEAM,1) + i1_u = UBOUND(SrcLinStateSaveData%u_FEAM,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_FEAM)) THEN + ALLOCATE(DstLinStateSaveData%u_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_FEAM,1), UBOUND(SrcLinStateSaveData%u_FEAM,1) + CALL FEAM_CopyInput( SrcLinStateSaveData%u_FEAM(i1), DstLinStateSaveData%u_FEAM(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%x_MD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%x_MD,1) + i1_u = UBOUND(SrcLinStateSaveData%x_MD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%x_MD)) THEN + ALLOCATE(DstLinStateSaveData%x_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%x_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%x_MD,1), UBOUND(SrcLinStateSaveData%x_MD,1) + CALL MD_CopyContState( SrcLinStateSaveData%x_MD(i1), DstLinStateSaveData%x_MD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%xd_MD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%xd_MD,1) + i1_u = UBOUND(SrcLinStateSaveData%xd_MD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%xd_MD)) THEN + ALLOCATE(DstLinStateSaveData%xd_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%xd_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%xd_MD,1), UBOUND(SrcLinStateSaveData%xd_MD,1) + CALL MD_CopyDiscState( SrcLinStateSaveData%xd_MD(i1), DstLinStateSaveData%xd_MD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%z_MD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%z_MD,1) + i1_u = UBOUND(SrcLinStateSaveData%z_MD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%z_MD)) THEN + ALLOCATE(DstLinStateSaveData%z_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%z_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%z_MD,1), UBOUND(SrcLinStateSaveData%z_MD,1) + CALL MD_CopyConstrState( SrcLinStateSaveData%z_MD(i1), DstLinStateSaveData%z_MD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%OtherSt_MD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%OtherSt_MD,1) + i1_u = UBOUND(SrcLinStateSaveData%OtherSt_MD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%OtherSt_MD)) THEN + ALLOCATE(DstLinStateSaveData%OtherSt_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%OtherSt_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%OtherSt_MD,1), UBOUND(SrcLinStateSaveData%OtherSt_MD,1) + CALL MD_CopyOtherState( SrcLinStateSaveData%OtherSt_MD(i1), DstLinStateSaveData%OtherSt_MD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcLinStateSaveData%u_MD)) THEN + i1_l = LBOUND(SrcLinStateSaveData%u_MD,1) + i1_u = UBOUND(SrcLinStateSaveData%u_MD,1) + IF (.NOT. ALLOCATED(DstLinStateSaveData%u_MD)) THEN + ALLOCATE(DstLinStateSaveData%u_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinStateSaveData%u_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcLinStateSaveData%u_MD,1), UBOUND(SrcLinStateSaveData%u_MD,1) + CALL MD_CopyInput( SrcLinStateSaveData%u_MD(i1), DstLinStateSaveData%u_MD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + END SUBROUTINE FAST_CopyLinStateSave + + SUBROUTINE FAST_DestroyLinStateSave( LinStateSaveData, ErrStat, ErrMsg ) + TYPE(FAST_LinStateSave), INTENT(INOUT) :: LinStateSaveData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyLinStateSave' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(LinStateSaveData%x_IceD)) THEN +DO i2 = LBOUND(LinStateSaveData%x_IceD,2), UBOUND(LinStateSaveData%x_IceD,2) +DO i1 = LBOUND(LinStateSaveData%x_IceD,1), UBOUND(LinStateSaveData%x_IceD,1) + CALL IceD_DestroyContState( LinStateSaveData%x_IceD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%x_IceD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_IceD)) THEN +DO i2 = LBOUND(LinStateSaveData%xd_IceD,2), UBOUND(LinStateSaveData%xd_IceD,2) +DO i1 = LBOUND(LinStateSaveData%xd_IceD,1), UBOUND(LinStateSaveData%xd_IceD,1) + CALL IceD_DestroyDiscState( LinStateSaveData%xd_IceD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%xd_IceD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_IceD)) THEN +DO i2 = LBOUND(LinStateSaveData%z_IceD,2), UBOUND(LinStateSaveData%z_IceD,2) +DO i1 = LBOUND(LinStateSaveData%z_IceD,1), UBOUND(LinStateSaveData%z_IceD,1) + CALL IceD_DestroyConstrState( LinStateSaveData%z_IceD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%z_IceD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_IceD)) THEN +DO i2 = LBOUND(LinStateSaveData%OtherSt_IceD,2), UBOUND(LinStateSaveData%OtherSt_IceD,2) +DO i1 = LBOUND(LinStateSaveData%OtherSt_IceD,1), UBOUND(LinStateSaveData%OtherSt_IceD,1) + CALL IceD_DestroyOtherState( LinStateSaveData%OtherSt_IceD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_IceD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_IceD)) THEN +DO i2 = LBOUND(LinStateSaveData%u_IceD,2), UBOUND(LinStateSaveData%u_IceD,2) +DO i1 = LBOUND(LinStateSaveData%u_IceD,1), UBOUND(LinStateSaveData%u_IceD,1) + CALL IceD_DestroyInput( LinStateSaveData%u_IceD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%u_IceD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_BD)) THEN +DO i2 = LBOUND(LinStateSaveData%x_BD,2), UBOUND(LinStateSaveData%x_BD,2) +DO i1 = LBOUND(LinStateSaveData%x_BD,1), UBOUND(LinStateSaveData%x_BD,1) + CALL BD_DestroyContState( LinStateSaveData%x_BD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%x_BD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_BD)) THEN +DO i2 = LBOUND(LinStateSaveData%xd_BD,2), UBOUND(LinStateSaveData%xd_BD,2) +DO i1 = LBOUND(LinStateSaveData%xd_BD,1), UBOUND(LinStateSaveData%xd_BD,1) + CALL BD_DestroyDiscState( LinStateSaveData%xd_BD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%xd_BD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_BD)) THEN +DO i2 = LBOUND(LinStateSaveData%z_BD,2), UBOUND(LinStateSaveData%z_BD,2) +DO i1 = LBOUND(LinStateSaveData%z_BD,1), UBOUND(LinStateSaveData%z_BD,1) + CALL BD_DestroyConstrState( LinStateSaveData%z_BD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%z_BD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_BD)) THEN +DO i2 = LBOUND(LinStateSaveData%OtherSt_BD,2), UBOUND(LinStateSaveData%OtherSt_BD,2) +DO i1 = LBOUND(LinStateSaveData%OtherSt_BD,1), UBOUND(LinStateSaveData%OtherSt_BD,1) + CALL BD_DestroyOtherState( LinStateSaveData%OtherSt_BD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_BD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_BD)) THEN +DO i2 = LBOUND(LinStateSaveData%u_BD,2), UBOUND(LinStateSaveData%u_BD,2) +DO i1 = LBOUND(LinStateSaveData%u_BD,1), UBOUND(LinStateSaveData%u_BD,1) + CALL BD_DestroyInput( LinStateSaveData%u_BD(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(LinStateSaveData%u_BD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_ED)) THEN +DO i1 = LBOUND(LinStateSaveData%x_ED,1), UBOUND(LinStateSaveData%x_ED,1) + CALL ED_DestroyContState( LinStateSaveData%x_ED(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_ED) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_ED)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_ED,1), UBOUND(LinStateSaveData%xd_ED,1) + CALL ED_DestroyDiscState( LinStateSaveData%xd_ED(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_ED) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_ED)) THEN +DO i1 = LBOUND(LinStateSaveData%z_ED,1), UBOUND(LinStateSaveData%z_ED,1) + CALL ED_DestroyConstrState( LinStateSaveData%z_ED(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_ED) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_ED)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_ED,1), UBOUND(LinStateSaveData%OtherSt_ED,1) + CALL ED_DestroyOtherState( LinStateSaveData%OtherSt_ED(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_ED) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_ED)) THEN +DO i1 = LBOUND(LinStateSaveData%u_ED,1), UBOUND(LinStateSaveData%u_ED,1) + CALL ED_DestroyInput( LinStateSaveData%u_ED(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_ED) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_SrvD)) THEN +DO i1 = LBOUND(LinStateSaveData%x_SrvD,1), UBOUND(LinStateSaveData%x_SrvD,1) + CALL SrvD_DestroyContState( LinStateSaveData%x_SrvD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_SrvD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_SrvD)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_SrvD,1), UBOUND(LinStateSaveData%xd_SrvD,1) + CALL SrvD_DestroyDiscState( LinStateSaveData%xd_SrvD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_SrvD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_SrvD)) THEN +DO i1 = LBOUND(LinStateSaveData%z_SrvD,1), UBOUND(LinStateSaveData%z_SrvD,1) + CALL SrvD_DestroyConstrState( LinStateSaveData%z_SrvD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_SrvD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_SrvD)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_SrvD,1), UBOUND(LinStateSaveData%OtherSt_SrvD,1) + CALL SrvD_DestroyOtherState( LinStateSaveData%OtherSt_SrvD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_SrvD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_SrvD)) THEN +DO i1 = LBOUND(LinStateSaveData%u_SrvD,1), UBOUND(LinStateSaveData%u_SrvD,1) + CALL SrvD_DestroyInput( LinStateSaveData%u_SrvD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_SrvD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_AD)) THEN +DO i1 = LBOUND(LinStateSaveData%x_AD,1), UBOUND(LinStateSaveData%x_AD,1) + CALL AD_DestroyContState( LinStateSaveData%x_AD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_AD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_AD)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_AD,1), UBOUND(LinStateSaveData%xd_AD,1) + CALL AD_DestroyDiscState( LinStateSaveData%xd_AD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_AD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_AD)) THEN +DO i1 = LBOUND(LinStateSaveData%z_AD,1), UBOUND(LinStateSaveData%z_AD,1) + CALL AD_DestroyConstrState( LinStateSaveData%z_AD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_AD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_AD)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_AD,1), UBOUND(LinStateSaveData%OtherSt_AD,1) + CALL AD_DestroyOtherState( LinStateSaveData%OtherSt_AD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_AD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_AD)) THEN +DO i1 = LBOUND(LinStateSaveData%u_AD,1), UBOUND(LinStateSaveData%u_AD,1) + CALL AD_DestroyInput( LinStateSaveData%u_AD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_AD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_IfW)) THEN +DO i1 = LBOUND(LinStateSaveData%x_IfW,1), UBOUND(LinStateSaveData%x_IfW,1) + CALL InflowWind_DestroyContState( LinStateSaveData%x_IfW(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_IfW) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_IfW)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_IfW,1), UBOUND(LinStateSaveData%xd_IfW,1) + CALL InflowWind_DestroyDiscState( LinStateSaveData%xd_IfW(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_IfW) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_IfW)) THEN +DO i1 = LBOUND(LinStateSaveData%z_IfW,1), UBOUND(LinStateSaveData%z_IfW,1) + CALL InflowWind_DestroyConstrState( LinStateSaveData%z_IfW(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_IfW) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_IfW)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_IfW,1), UBOUND(LinStateSaveData%OtherSt_IfW,1) + CALL InflowWind_DestroyOtherState( LinStateSaveData%OtherSt_IfW(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_IfW) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_IfW)) THEN +DO i1 = LBOUND(LinStateSaveData%u_IfW,1), UBOUND(LinStateSaveData%u_IfW,1) + CALL InflowWind_DestroyInput( LinStateSaveData%u_IfW(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_IfW) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_SD)) THEN +DO i1 = LBOUND(LinStateSaveData%x_SD,1), UBOUND(LinStateSaveData%x_SD,1) + CALL SD_DestroyContState( LinStateSaveData%x_SD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_SD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_SD)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_SD,1), UBOUND(LinStateSaveData%xd_SD,1) + CALL SD_DestroyDiscState( LinStateSaveData%xd_SD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_SD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_SD)) THEN +DO i1 = LBOUND(LinStateSaveData%z_SD,1), UBOUND(LinStateSaveData%z_SD,1) + CALL SD_DestroyConstrState( LinStateSaveData%z_SD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_SD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_SD)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_SD,1), UBOUND(LinStateSaveData%OtherSt_SD,1) + CALL SD_DestroyOtherState( LinStateSaveData%OtherSt_SD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_SD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_SD)) THEN +DO i1 = LBOUND(LinStateSaveData%u_SD,1), UBOUND(LinStateSaveData%u_SD,1) + CALL SD_DestroyInput( LinStateSaveData%u_SD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_SD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_ExtPtfm)) THEN +DO i1 = LBOUND(LinStateSaveData%x_ExtPtfm,1), UBOUND(LinStateSaveData%x_ExtPtfm,1) + CALL ExtPtfm_DestroyContState( LinStateSaveData%x_ExtPtfm(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_ExtPtfm) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_ExtPtfm)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_ExtPtfm,1), UBOUND(LinStateSaveData%xd_ExtPtfm,1) + CALL ExtPtfm_DestroyDiscState( LinStateSaveData%xd_ExtPtfm(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_ExtPtfm) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_ExtPtfm)) THEN +DO i1 = LBOUND(LinStateSaveData%z_ExtPtfm,1), UBOUND(LinStateSaveData%z_ExtPtfm,1) + CALL ExtPtfm_DestroyConstrState( LinStateSaveData%z_ExtPtfm(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_ExtPtfm) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_ExtPtfm)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_ExtPtfm,1), UBOUND(LinStateSaveData%OtherSt_ExtPtfm,1) + CALL ExtPtfm_DestroyOtherState( LinStateSaveData%OtherSt_ExtPtfm(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_ExtPtfm) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_ExtPtfm)) THEN +DO i1 = LBOUND(LinStateSaveData%u_ExtPtfm,1), UBOUND(LinStateSaveData%u_ExtPtfm,1) + CALL ExtPtfm_DestroyInput( LinStateSaveData%u_ExtPtfm(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_ExtPtfm) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_HD)) THEN +DO i1 = LBOUND(LinStateSaveData%x_HD,1), UBOUND(LinStateSaveData%x_HD,1) + CALL HydroDyn_DestroyContState( LinStateSaveData%x_HD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_HD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_HD)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_HD,1), UBOUND(LinStateSaveData%xd_HD,1) + CALL HydroDyn_DestroyDiscState( LinStateSaveData%xd_HD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_HD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_HD)) THEN +DO i1 = LBOUND(LinStateSaveData%z_HD,1), UBOUND(LinStateSaveData%z_HD,1) + CALL HydroDyn_DestroyConstrState( LinStateSaveData%z_HD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_HD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_HD)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_HD,1), UBOUND(LinStateSaveData%OtherSt_HD,1) + CALL HydroDyn_DestroyOtherState( LinStateSaveData%OtherSt_HD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_HD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_HD)) THEN +DO i1 = LBOUND(LinStateSaveData%u_HD,1), UBOUND(LinStateSaveData%u_HD,1) + CALL HydroDyn_DestroyInput( LinStateSaveData%u_HD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_HD) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_IceF)) THEN +DO i1 = LBOUND(LinStateSaveData%x_IceF,1), UBOUND(LinStateSaveData%x_IceF,1) + CALL IceFloe_DestroyContState( LinStateSaveData%x_IceF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_IceF) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_IceF)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_IceF,1), UBOUND(LinStateSaveData%xd_IceF,1) + CALL IceFloe_DestroyDiscState( LinStateSaveData%xd_IceF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_IceF) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_IceF)) THEN +DO i1 = LBOUND(LinStateSaveData%z_IceF,1), UBOUND(LinStateSaveData%z_IceF,1) + CALL IceFloe_DestroyConstrState( LinStateSaveData%z_IceF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_IceF) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_IceF)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_IceF,1), UBOUND(LinStateSaveData%OtherSt_IceF,1) + CALL IceFloe_DestroyOtherState( LinStateSaveData%OtherSt_IceF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_IceF) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_IceF)) THEN +DO i1 = LBOUND(LinStateSaveData%u_IceF,1), UBOUND(LinStateSaveData%u_IceF,1) + CALL IceFloe_DestroyInput( LinStateSaveData%u_IceF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_IceF) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_MAP)) THEN +DO i1 = LBOUND(LinStateSaveData%x_MAP,1), UBOUND(LinStateSaveData%x_MAP,1) + CALL MAP_DestroyContState( LinStateSaveData%x_MAP(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_MAP) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_MAP)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_MAP,1), UBOUND(LinStateSaveData%xd_MAP,1) + CALL MAP_DestroyDiscState( LinStateSaveData%xd_MAP(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_MAP) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_MAP)) THEN +DO i1 = LBOUND(LinStateSaveData%z_MAP,1), UBOUND(LinStateSaveData%z_MAP,1) + CALL MAP_DestroyConstrState( LinStateSaveData%z_MAP(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_MAP) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_MAP)) THEN +DO i1 = LBOUND(LinStateSaveData%u_MAP,1), UBOUND(LinStateSaveData%u_MAP,1) + CALL MAP_DestroyInput( LinStateSaveData%u_MAP(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_MAP) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_FEAM)) THEN +DO i1 = LBOUND(LinStateSaveData%x_FEAM,1), UBOUND(LinStateSaveData%x_FEAM,1) + CALL FEAM_DestroyContState( LinStateSaveData%x_FEAM(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_FEAM) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_FEAM)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_FEAM,1), UBOUND(LinStateSaveData%xd_FEAM,1) + CALL FEAM_DestroyDiscState( LinStateSaveData%xd_FEAM(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_FEAM) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_FEAM)) THEN +DO i1 = LBOUND(LinStateSaveData%z_FEAM,1), UBOUND(LinStateSaveData%z_FEAM,1) + CALL FEAM_DestroyConstrState( LinStateSaveData%z_FEAM(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_FEAM) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_FEAM)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_FEAM,1), UBOUND(LinStateSaveData%OtherSt_FEAM,1) + CALL FEAM_DestroyOtherState( LinStateSaveData%OtherSt_FEAM(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_FEAM) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_FEAM)) THEN +DO i1 = LBOUND(LinStateSaveData%u_FEAM,1), UBOUND(LinStateSaveData%u_FEAM,1) + CALL FEAM_DestroyInput( LinStateSaveData%u_FEAM(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_FEAM) +ENDIF +IF (ALLOCATED(LinStateSaveData%x_MD)) THEN +DO i1 = LBOUND(LinStateSaveData%x_MD,1), UBOUND(LinStateSaveData%x_MD,1) + CALL MD_DestroyContState( LinStateSaveData%x_MD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%x_MD) +ENDIF +IF (ALLOCATED(LinStateSaveData%xd_MD)) THEN +DO i1 = LBOUND(LinStateSaveData%xd_MD,1), UBOUND(LinStateSaveData%xd_MD,1) + CALL MD_DestroyDiscState( LinStateSaveData%xd_MD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%xd_MD) +ENDIF +IF (ALLOCATED(LinStateSaveData%z_MD)) THEN +DO i1 = LBOUND(LinStateSaveData%z_MD,1), UBOUND(LinStateSaveData%z_MD,1) + CALL MD_DestroyConstrState( LinStateSaveData%z_MD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%z_MD) +ENDIF +IF (ALLOCATED(LinStateSaveData%OtherSt_MD)) THEN +DO i1 = LBOUND(LinStateSaveData%OtherSt_MD,1), UBOUND(LinStateSaveData%OtherSt_MD,1) + CALL MD_DestroyOtherState( LinStateSaveData%OtherSt_MD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%OtherSt_MD) +ENDIF +IF (ALLOCATED(LinStateSaveData%u_MD)) THEN +DO i1 = LBOUND(LinStateSaveData%u_MD,1), UBOUND(LinStateSaveData%u_MD,1) + CALL MD_DestroyInput( LinStateSaveData%u_MD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(LinStateSaveData%u_MD) +ENDIF + END SUBROUTINE FAST_DestroyLinStateSave + + SUBROUTINE FAST_PackLinStateSave( 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(FAST_LinStateSave), 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 = 'FAST_PackLinStateSave' + ! 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 ! x_IceD allocated yes/no + IF ( ALLOCATED(InData%x_IceD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! x_IceD upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%x_IceD,2), UBOUND(InData%x_IceD,2) + DO i1 = LBOUND(InData%x_IceD,1), UBOUND(InData%x_IceD,1) + Int_BufSz = Int_BufSz + 3 ! x_IceD: size of buffers for each call to pack subtype + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IceD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! x_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_IceD allocated yes/no + IF ( ALLOCATED(InData%xd_IceD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! xd_IceD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%xd_IceD,2), UBOUND(InData%xd_IceD,2) + DO i1 = LBOUND(InData%xd_IceD,1), UBOUND(InData%xd_IceD,1) + Int_BufSz = Int_BufSz + 3 ! xd_IceD: size of buffers for each call to pack subtype + CALL IceD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IceD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! xd_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_IceD allocated yes/no + IF ( ALLOCATED(InData%z_IceD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! z_IceD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%z_IceD,2), UBOUND(InData%z_IceD,2) + DO i1 = LBOUND(InData%z_IceD,1), UBOUND(InData%z_IceD,1) + Int_BufSz = Int_BufSz + 3 ! z_IceD: size of buffers for each call to pack subtype + CALL IceD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IceD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! z_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_IceD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_IceD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OtherSt_IceD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%OtherSt_IceD,2), UBOUND(InData%OtherSt_IceD,2) + DO i1 = LBOUND(InData%OtherSt_IceD,1), UBOUND(InData%OtherSt_IceD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_IceD: size of buffers for each call to pack subtype + CALL IceD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IceD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_IceD allocated yes/no + IF ( ALLOCATED(InData%u_IceD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! u_IceD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%u_IceD,2), UBOUND(InData%u_IceD,2) + DO i1 = LBOUND(InData%u_IceD,1), UBOUND(InData%u_IceD,1) + Int_BufSz = Int_BufSz + 3 ! u_IceD: size of buffers for each call to pack subtype + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IceD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! u_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_BD allocated yes/no + IF ( ALLOCATED(InData%x_BD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! x_BD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%x_BD,2), UBOUND(InData%x_BD,2) + DO i1 = LBOUND(InData%x_BD,1), UBOUND(InData%x_BD,1) + Int_BufSz = Int_BufSz + 3 ! x_BD: size of buffers for each call to pack subtype + CALL BD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_BD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! x_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_BD allocated yes/no + IF ( ALLOCATED(InData%xd_BD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! xd_BD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%xd_BD,2), UBOUND(InData%xd_BD,2) + DO i1 = LBOUND(InData%xd_BD,1), UBOUND(InData%xd_BD,1) + Int_BufSz = Int_BufSz + 3 ! xd_BD: size of buffers for each call to pack subtype + CALL BD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_BD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! xd_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_BD allocated yes/no + IF ( ALLOCATED(InData%z_BD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! z_BD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%z_BD,2), UBOUND(InData%z_BD,2) + DO i1 = LBOUND(InData%z_BD,1), UBOUND(InData%z_BD,1) + Int_BufSz = Int_BufSz + 3 ! z_BD: size of buffers for each call to pack subtype + CALL BD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_BD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! z_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_BD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_BD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OtherSt_BD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%OtherSt_BD,2), UBOUND(InData%OtherSt_BD,2) + DO i1 = LBOUND(InData%OtherSt_BD,1), UBOUND(InData%OtherSt_BD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_BD: size of buffers for each call to pack subtype + CALL BD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_BD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_BD allocated yes/no + IF ( ALLOCATED(InData%u_BD) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! u_BD upper/lower bounds for each dimension + DO i2 = LBOUND(InData%u_BD,2), UBOUND(InData%u_BD,2) + DO i1 = LBOUND(InData%u_BD,1), UBOUND(InData%u_BD,1) + Int_BufSz = Int_BufSz + 3 ! u_BD: size of buffers for each call to pack subtype + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_BD(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! u_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_ED allocated yes/no + IF ( ALLOCATED(InData%x_ED) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_ED upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_ED,1), UBOUND(InData%x_ED,1) + Int_BufSz = Int_BufSz + 3 ! x_ED: size of buffers for each call to pack subtype + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_ED(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_ED allocated yes/no + IF ( ALLOCATED(InData%xd_ED) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_ED upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_ED,1), UBOUND(InData%xd_ED,1) + Int_BufSz = Int_BufSz + 3 ! xd_ED: size of buffers for each call to pack subtype + CALL ED_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_ED(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_ED allocated yes/no + IF ( ALLOCATED(InData%z_ED) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_ED upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_ED,1), UBOUND(InData%z_ED,1) + Int_BufSz = Int_BufSz + 3 ! z_ED: size of buffers for each call to pack subtype + CALL ED_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_ED(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_ED allocated yes/no + IF ( ALLOCATED(InData%OtherSt_ED) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_ED upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_ED,1), UBOUND(InData%OtherSt_ED,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_ED: size of buffers for each call to pack subtype + CALL ED_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_ED(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_ED allocated yes/no + IF ( ALLOCATED(InData%u_ED) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_ED upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_ED,1), UBOUND(InData%u_ED,1) + Int_BufSz = Int_BufSz + 3 ! u_ED: size of buffers for each call to pack subtype + CALL ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_ED(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_SrvD allocated yes/no + IF ( ALLOCATED(InData%x_SrvD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_SrvD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_SrvD,1), UBOUND(InData%x_SrvD,1) + Int_BufSz = Int_BufSz + 3 ! x_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_SrvD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_SrvD allocated yes/no + IF ( ALLOCATED(InData%xd_SrvD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_SrvD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_SrvD,1), UBOUND(InData%xd_SrvD,1) + Int_BufSz = Int_BufSz + 3 ! xd_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_SrvD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_SrvD allocated yes/no + IF ( ALLOCATED(InData%z_SrvD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_SrvD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_SrvD,1), UBOUND(InData%z_SrvD,1) + Int_BufSz = Int_BufSz + 3 ! z_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_SrvD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_SrvD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_SrvD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_SrvD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_SrvD,1), UBOUND(InData%OtherSt_SrvD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_SrvD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_SrvD allocated yes/no + IF ( ALLOCATED(InData%u_SrvD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_SrvD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_SrvD,1), UBOUND(InData%u_SrvD,1) + Int_BufSz = Int_BufSz + 3 ! u_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_SrvD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_AD allocated yes/no + IF ( ALLOCATED(InData%x_AD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_AD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_AD,1), UBOUND(InData%x_AD,1) + Int_BufSz = Int_BufSz + 3 ! x_AD: size of buffers for each call to pack subtype + CALL AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_AD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_AD allocated yes/no + IF ( ALLOCATED(InData%xd_AD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_AD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_AD,1), UBOUND(InData%xd_AD,1) + Int_BufSz = Int_BufSz + 3 ! xd_AD: size of buffers for each call to pack subtype + CALL AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_AD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_AD allocated yes/no + IF ( ALLOCATED(InData%z_AD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_AD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_AD,1), UBOUND(InData%z_AD,1) + Int_BufSz = Int_BufSz + 3 ! z_AD: size of buffers for each call to pack subtype + CALL AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_AD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_AD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_AD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_AD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_AD,1), UBOUND(InData%OtherSt_AD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_AD: size of buffers for each call to pack subtype + CALL AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_AD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_AD allocated yes/no + IF ( ALLOCATED(InData%u_AD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_AD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_AD,1), UBOUND(InData%u_AD,1) + Int_BufSz = Int_BufSz + 3 ! u_AD: size of buffers for each call to pack subtype + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_AD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_IfW allocated yes/no + IF ( ALLOCATED(InData%x_IfW) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_IfW upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_IfW,1), UBOUND(InData%x_IfW,1) + Int_BufSz = Int_BufSz + 3 ! x_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IfW(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_IfW allocated yes/no + IF ( ALLOCATED(InData%xd_IfW) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_IfW upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_IfW,1), UBOUND(InData%xd_IfW,1) + Int_BufSz = Int_BufSz + 3 ! xd_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IfW(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_IfW allocated yes/no + IF ( ALLOCATED(InData%z_IfW) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_IfW upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_IfW,1), UBOUND(InData%z_IfW,1) + Int_BufSz = Int_BufSz + 3 ! z_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IfW(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_IfW allocated yes/no + IF ( ALLOCATED(InData%OtherSt_IfW) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_IfW upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_IfW,1), UBOUND(InData%OtherSt_IfW,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IfW(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_IfW allocated yes/no + IF ( ALLOCATED(InData%u_IfW) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_IfW upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_IfW,1), UBOUND(InData%u_IfW,1) + Int_BufSz = Int_BufSz + 3 ! u_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IfW(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_SD allocated yes/no + IF ( ALLOCATED(InData%x_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_SD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_SD,1), UBOUND(InData%x_SD,1) + Int_BufSz = Int_BufSz + 3 ! x_SD: size of buffers for each call to pack subtype + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_SD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_SD allocated yes/no + IF ( ALLOCATED(InData%xd_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_SD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_SD,1), UBOUND(InData%xd_SD,1) + Int_BufSz = Int_BufSz + 3 ! xd_SD: size of buffers for each call to pack subtype + CALL SD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_SD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_SD allocated yes/no + IF ( ALLOCATED(InData%z_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_SD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_SD,1), UBOUND(InData%z_SD,1) + Int_BufSz = Int_BufSz + 3 ! z_SD: size of buffers for each call to pack subtype + CALL SD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_SD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_SD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_SD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_SD,1), UBOUND(InData%OtherSt_SD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_SD: size of buffers for each call to pack subtype + CALL SD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_SD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_SD allocated yes/no + IF ( ALLOCATED(InData%u_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_SD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_SD,1), UBOUND(InData%u_SD,1) + Int_BufSz = Int_BufSz + 3 ! u_SD: size of buffers for each call to pack subtype + CALL SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_SD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_ExtPtfm allocated yes/no + IF ( ALLOCATED(InData%x_ExtPtfm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_ExtPtfm upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_ExtPtfm,1), UBOUND(InData%x_ExtPtfm,1) + Int_BufSz = Int_BufSz + 3 ! x_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_ExtPtfm(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_ExtPtfm allocated yes/no + IF ( ALLOCATED(InData%xd_ExtPtfm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_ExtPtfm upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_ExtPtfm,1), UBOUND(InData%xd_ExtPtfm,1) + Int_BufSz = Int_BufSz + 3 ! xd_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_ExtPtfm(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_ExtPtfm allocated yes/no + IF ( ALLOCATED(InData%z_ExtPtfm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_ExtPtfm upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_ExtPtfm,1), UBOUND(InData%z_ExtPtfm,1) + Int_BufSz = Int_BufSz + 3 ! z_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_ExtPtfm(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_ExtPtfm allocated yes/no + IF ( ALLOCATED(InData%OtherSt_ExtPtfm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_ExtPtfm upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_ExtPtfm,1), UBOUND(InData%OtherSt_ExtPtfm,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_ExtPtfm(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_ExtPtfm allocated yes/no + IF ( ALLOCATED(InData%u_ExtPtfm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_ExtPtfm upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_ExtPtfm,1), UBOUND(InData%u_ExtPtfm,1) + Int_BufSz = Int_BufSz + 3 ! u_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_ExtPtfm(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_HD allocated yes/no + IF ( ALLOCATED(InData%x_HD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_HD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_HD,1), UBOUND(InData%x_HD,1) + Int_BufSz = Int_BufSz + 3 ! x_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_HD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_HD allocated yes/no + IF ( ALLOCATED(InData%xd_HD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_HD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_HD,1), UBOUND(InData%xd_HD,1) + Int_BufSz = Int_BufSz + 3 ! xd_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_HD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_HD allocated yes/no + IF ( ALLOCATED(InData%z_HD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_HD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_HD,1), UBOUND(InData%z_HD,1) + Int_BufSz = Int_BufSz + 3 ! z_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_HD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_HD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_HD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_HD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_HD,1), UBOUND(InData%OtherSt_HD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_HD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_HD allocated yes/no + IF ( ALLOCATED(InData%u_HD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_HD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_HD,1), UBOUND(InData%u_HD,1) + Int_BufSz = Int_BufSz + 3 ! u_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_HD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_IceF allocated yes/no + IF ( ALLOCATED(InData%x_IceF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_IceF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_IceF,1), UBOUND(InData%x_IceF,1) + Int_BufSz = Int_BufSz + 3 ! x_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IceF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_IceF allocated yes/no + IF ( ALLOCATED(InData%xd_IceF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_IceF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_IceF,1), UBOUND(InData%xd_IceF,1) + Int_BufSz = Int_BufSz + 3 ! xd_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IceF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_IceF allocated yes/no + IF ( ALLOCATED(InData%z_IceF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_IceF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_IceF,1), UBOUND(InData%z_IceF,1) + Int_BufSz = Int_BufSz + 3 ! z_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IceF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_IceF allocated yes/no + IF ( ALLOCATED(InData%OtherSt_IceF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_IceF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_IceF,1), UBOUND(InData%OtherSt_IceF,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IceF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_IceF allocated yes/no + IF ( ALLOCATED(InData%u_IceF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_IceF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_IceF,1), UBOUND(InData%u_IceF,1) + Int_BufSz = Int_BufSz + 3 ! u_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IceF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_MAP allocated yes/no + IF ( ALLOCATED(InData%x_MAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_MAP upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_MAP,1), UBOUND(InData%x_MAP,1) + Int_BufSz = Int_BufSz + 3 ! x_MAP: size of buffers for each call to pack subtype + CALL MAP_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_MAP(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_MAP allocated yes/no + IF ( ALLOCATED(InData%xd_MAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_MAP upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_MAP,1), UBOUND(InData%xd_MAP,1) + Int_BufSz = Int_BufSz + 3 ! xd_MAP: size of buffers for each call to pack subtype + CALL MAP_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_MAP(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_MAP allocated yes/no + IF ( ALLOCATED(InData%z_MAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_MAP upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_MAP,1), UBOUND(InData%z_MAP,1) + Int_BufSz = Int_BufSz + 3 ! z_MAP: size of buffers for each call to pack subtype + CALL MAP_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_MAP(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_MAP allocated yes/no + IF ( ALLOCATED(InData%u_MAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_MAP upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_MAP,1), UBOUND(InData%u_MAP,1) + Int_BufSz = Int_BufSz + 3 ! u_MAP: size of buffers for each call to pack subtype + CALL MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_MAP(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_FEAM allocated yes/no + IF ( ALLOCATED(InData%x_FEAM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_FEAM upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_FEAM,1), UBOUND(InData%x_FEAM,1) + Int_BufSz = Int_BufSz + 3 ! x_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_FEAM(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_FEAM allocated yes/no + IF ( ALLOCATED(InData%xd_FEAM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_FEAM upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_FEAM,1), UBOUND(InData%xd_FEAM,1) + Int_BufSz = Int_BufSz + 3 ! xd_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_FEAM(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_FEAM allocated yes/no + IF ( ALLOCATED(InData%z_FEAM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_FEAM upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_FEAM,1), UBOUND(InData%z_FEAM,1) + Int_BufSz = Int_BufSz + 3 ! z_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_FEAM(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_FEAM allocated yes/no + IF ( ALLOCATED(InData%OtherSt_FEAM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_FEAM upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_FEAM,1), UBOUND(InData%OtherSt_FEAM,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_FEAM(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_FEAM allocated yes/no + IF ( ALLOCATED(InData%u_FEAM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_FEAM upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_FEAM,1), UBOUND(InData%u_FEAM,1) + Int_BufSz = Int_BufSz + 3 ! u_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_FEAM(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! x_MD allocated yes/no + IF ( ALLOCATED(InData%x_MD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! x_MD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%x_MD,1), UBOUND(InData%x_MD,1) + Int_BufSz = Int_BufSz + 3 ! x_MD: size of buffers for each call to pack subtype + CALL MD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_MD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd_MD allocated yes/no + IF ( ALLOCATED(InData%xd_MD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_MD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%xd_MD,1), UBOUND(InData%xd_MD,1) + Int_BufSz = Int_BufSz + 3 ! xd_MD: size of buffers for each call to pack subtype + CALL MD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_MD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z_MD allocated yes/no + IF ( ALLOCATED(InData%z_MD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! z_MD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%z_MD,1), UBOUND(InData%z_MD,1) + Int_BufSz = Int_BufSz + 3 ! z_MD: size of buffers for each call to pack subtype + CALL MD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_MD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt_MD allocated yes/no + IF ( ALLOCATED(InData%OtherSt_MD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OtherSt_MD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OtherSt_MD,1), UBOUND(InData%OtherSt_MD,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt_MD: size of buffers for each call to pack subtype + CALL MD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_MD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u_MD allocated yes/no + IF ( ALLOCATED(InData%u_MD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_MD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_MD,1), UBOUND(InData%u_MD,1) + Int_BufSz = Int_BufSz + 3 ! u_MD: size of buffers for each call to pack subtype + CALL MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_MD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%x_IceD) ) 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%x_IceD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_IceD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_IceD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_IceD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%x_IceD,2), UBOUND(InData%x_IceD,2) + DO i1 = LBOUND(InData%x_IceD,1), UBOUND(InData%x_IceD,1) + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IceD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! x_IceD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%xd_IceD) ) 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%xd_IceD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_IceD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xd_IceD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_IceD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%xd_IceD,2), UBOUND(InData%xd_IceD,2) + DO i1 = LBOUND(InData%xd_IceD,1), UBOUND(InData%xd_IceD,1) + CALL IceD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IceD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! xd_IceD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%z_IceD) ) 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%z_IceD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_IceD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%z_IceD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_IceD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%z_IceD,2), UBOUND(InData%z_IceD,2) + DO i1 = LBOUND(InData%z_IceD,1), UBOUND(InData%z_IceD,1) + CALL IceD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IceD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! z_IceD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%OtherSt_IceD) ) 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%OtherSt_IceD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_IceD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OtherSt_IceD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_IceD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OtherSt_IceD,2), UBOUND(InData%OtherSt_IceD,2) + DO i1 = LBOUND(InData%OtherSt_IceD,1), UBOUND(InData%OtherSt_IceD,1) + CALL IceD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IceD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_IceD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%u_IceD) ) 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%u_IceD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_IceD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%u_IceD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_IceD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%u_IceD,2), UBOUND(InData%u_IceD,2) + DO i1 = LBOUND(InData%u_IceD,1), UBOUND(InData%u_IceD,1) + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IceD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! u_IceD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%x_BD) ) 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%x_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_BD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x_BD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_BD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%x_BD,2), UBOUND(InData%x_BD,2) + DO i1 = LBOUND(InData%x_BD,1), UBOUND(InData%x_BD,1) + CALL BD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_BD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! x_BD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%xd_BD) ) 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%xd_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_BD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xd_BD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_BD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%xd_BD,2), UBOUND(InData%xd_BD,2) + DO i1 = LBOUND(InData%xd_BD,1), UBOUND(InData%xd_BD,1) + CALL BD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_BD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! xd_BD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%z_BD) ) 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%z_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_BD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%z_BD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_BD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%z_BD,2), UBOUND(InData%z_BD,2) + DO i1 = LBOUND(InData%z_BD,1), UBOUND(InData%z_BD,1) + CALL BD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_BD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! z_BD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%OtherSt_BD) ) 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%OtherSt_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_BD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OtherSt_BD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_BD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OtherSt_BD,2), UBOUND(InData%OtherSt_BD,2) + DO i1 = LBOUND(InData%OtherSt_BD,1), UBOUND(InData%OtherSt_BD,1) + CALL BD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_BD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_BD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%u_BD) ) 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%u_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_BD,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%u_BD,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_BD,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%u_BD,2), UBOUND(InData%u_BD,2) + DO i1 = LBOUND(InData%u_BD,1), UBOUND(InData%u_BD,1) + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_BD(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! u_BD + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%x_ED) ) 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%x_ED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_ED,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_ED,1), UBOUND(InData%x_ED,1) + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_ED(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_ED + 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%xd_ED) ) 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%xd_ED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_ED,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_ED,1), UBOUND(InData%xd_ED,1) + CALL ED_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_ED(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_ED + 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%z_ED) ) 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%z_ED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_ED,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_ED,1), UBOUND(InData%z_ED,1) + CALL ED_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_ED(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_ED + 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%OtherSt_ED) ) 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%OtherSt_ED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_ED,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_ED,1), UBOUND(InData%OtherSt_ED,1) + CALL ED_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_ED(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_ED + 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%u_ED) ) 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%u_ED,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_ED,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_ED,1), UBOUND(InData%u_ED,1) + CALL ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_ED(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_ED + 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%x_SrvD) ) 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%x_SrvD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_SrvD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_SrvD,1), UBOUND(InData%x_SrvD,1) + CALL SrvD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_SrvD(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_SrvD + 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%xd_SrvD) ) 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%xd_SrvD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_SrvD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_SrvD,1), UBOUND(InData%xd_SrvD,1) + CALL SrvD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_SrvD(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_SrvD + 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%z_SrvD) ) 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%z_SrvD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_SrvD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_SrvD,1), UBOUND(InData%z_SrvD,1) + CALL SrvD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_SrvD(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_SrvD + 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%OtherSt_SrvD) ) 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%OtherSt_SrvD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_SrvD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_SrvD,1), UBOUND(InData%OtherSt_SrvD,1) + CALL SrvD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_SrvD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_SrvD + 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%u_SrvD) ) 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%u_SrvD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_SrvD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_SrvD,1), UBOUND(InData%u_SrvD,1) + CALL SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_SrvD(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_SrvD + 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%x_AD) ) 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%x_AD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_AD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_AD,1), UBOUND(InData%x_AD,1) + CALL AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_AD(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_AD + 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%xd_AD) ) 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%xd_AD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_AD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_AD,1), UBOUND(InData%xd_AD,1) + CALL AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_AD(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_AD + 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%z_AD) ) 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%z_AD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_AD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_AD,1), UBOUND(InData%z_AD,1) + CALL AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_AD(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_AD + 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%OtherSt_AD) ) 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%OtherSt_AD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_AD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_AD,1), UBOUND(InData%OtherSt_AD,1) + CALL AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_AD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_AD + 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%u_AD) ) 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%u_AD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_AD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_AD,1), UBOUND(InData%u_AD,1) + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_AD(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_AD + 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%x_IfW) ) 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%x_IfW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_IfW,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_IfW,1), UBOUND(InData%x_IfW,1) + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IfW(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_IfW + 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%xd_IfW) ) 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%xd_IfW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_IfW,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_IfW,1), UBOUND(InData%xd_IfW,1) + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IfW(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_IfW + 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%z_IfW) ) 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%z_IfW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_IfW,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_IfW,1), UBOUND(InData%z_IfW,1) + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IfW(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_IfW + 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%OtherSt_IfW) ) 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%OtherSt_IfW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_IfW,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_IfW,1), UBOUND(InData%OtherSt_IfW,1) + CALL InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IfW(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_IfW + 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%u_IfW) ) 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%u_IfW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_IfW,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_IfW,1), UBOUND(InData%u_IfW,1) + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IfW(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_IfW + 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%x_SD) ) 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%x_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_SD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_SD,1), UBOUND(InData%x_SD,1) + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_SD(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_SD + 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%xd_SD) ) 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%xd_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_SD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_SD,1), UBOUND(InData%xd_SD,1) + CALL SD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_SD(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_SD + 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%z_SD) ) 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%z_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_SD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_SD,1), UBOUND(InData%z_SD,1) + CALL SD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_SD(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_SD + 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%OtherSt_SD) ) 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%OtherSt_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_SD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_SD,1), UBOUND(InData%OtherSt_SD,1) + CALL SD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_SD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_SD + 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%u_SD) ) 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%u_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_SD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_SD,1), UBOUND(InData%u_SD,1) + CALL SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_SD(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_SD + 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%x_ExtPtfm) ) 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%x_ExtPtfm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_ExtPtfm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_ExtPtfm,1), UBOUND(InData%x_ExtPtfm,1) + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_ExtPtfm(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_ExtPtfm + 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%xd_ExtPtfm) ) 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%xd_ExtPtfm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_ExtPtfm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_ExtPtfm,1), UBOUND(InData%xd_ExtPtfm,1) + CALL ExtPtfm_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_ExtPtfm(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_ExtPtfm + 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%z_ExtPtfm) ) 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%z_ExtPtfm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_ExtPtfm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_ExtPtfm,1), UBOUND(InData%z_ExtPtfm,1) + CALL ExtPtfm_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_ExtPtfm(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_ExtPtfm + 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%OtherSt_ExtPtfm) ) 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%OtherSt_ExtPtfm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_ExtPtfm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_ExtPtfm,1), UBOUND(InData%OtherSt_ExtPtfm,1) + CALL ExtPtfm_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_ExtPtfm(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_ExtPtfm + 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%u_ExtPtfm) ) 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%u_ExtPtfm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_ExtPtfm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_ExtPtfm,1), UBOUND(InData%u_ExtPtfm,1) + CALL ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_ExtPtfm(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_ExtPtfm + 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%x_HD) ) 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%x_HD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_HD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_HD,1), UBOUND(InData%x_HD,1) + CALL HydroDyn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_HD(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_HD + 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%xd_HD) ) 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%xd_HD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_HD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_HD,1), UBOUND(InData%xd_HD,1) + CALL HydroDyn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_HD(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_HD + 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%z_HD) ) 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%z_HD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_HD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_HD,1), UBOUND(InData%z_HD,1) + CALL HydroDyn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_HD(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_HD + 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%OtherSt_HD) ) 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%OtherSt_HD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_HD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_HD,1), UBOUND(InData%OtherSt_HD,1) + CALL HydroDyn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_HD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_HD + 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%u_HD) ) 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%u_HD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_HD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_HD,1), UBOUND(InData%u_HD,1) + CALL HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_HD(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_HD + 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%x_IceF) ) 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%x_IceF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_IceF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_IceF,1), UBOUND(InData%x_IceF,1) + CALL IceFloe_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_IceF(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_IceF + 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%xd_IceF) ) 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%xd_IceF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_IceF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_IceF,1), UBOUND(InData%xd_IceF,1) + CALL IceFloe_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_IceF(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_IceF + 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%z_IceF) ) 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%z_IceF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_IceF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_IceF,1), UBOUND(InData%z_IceF,1) + CALL IceFloe_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_IceF(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_IceF + 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%OtherSt_IceF) ) 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%OtherSt_IceF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_IceF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_IceF,1), UBOUND(InData%OtherSt_IceF,1) + CALL IceFloe_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_IceF(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_IceF + 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%u_IceF) ) 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%u_IceF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_IceF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_IceF,1), UBOUND(InData%u_IceF,1) + CALL IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_IceF(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_IceF + 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%x_MAP) ) 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%x_MAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_MAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_MAP,1), UBOUND(InData%x_MAP,1) + CALL MAP_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_MAP(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_MAP + 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%xd_MAP) ) 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%xd_MAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_MAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_MAP,1), UBOUND(InData%xd_MAP,1) + CALL MAP_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_MAP(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_MAP + 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%z_MAP) ) 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%z_MAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_MAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_MAP,1), UBOUND(InData%z_MAP,1) + CALL MAP_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_MAP(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_MAP + 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%u_MAP) ) 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%u_MAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_MAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_MAP,1), UBOUND(InData%u_MAP,1) + CALL MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_MAP(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_MAP + 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%x_FEAM) ) 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%x_FEAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_FEAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_FEAM,1), UBOUND(InData%x_FEAM,1) + CALL FEAM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_FEAM(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_FEAM + 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%xd_FEAM) ) 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%xd_FEAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_FEAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_FEAM,1), UBOUND(InData%xd_FEAM,1) + CALL FEAM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_FEAM(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_FEAM + 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%z_FEAM) ) 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%z_FEAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_FEAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_FEAM,1), UBOUND(InData%z_FEAM,1) + CALL FEAM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_FEAM(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_FEAM + 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%OtherSt_FEAM) ) 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%OtherSt_FEAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_FEAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_FEAM,1), UBOUND(InData%OtherSt_FEAM,1) + CALL FEAM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_FEAM(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_FEAM + 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%u_FEAM) ) 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%u_FEAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_FEAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_FEAM,1), UBOUND(InData%u_FEAM,1) + CALL FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_FEAM(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_FEAM + 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%x_MD) ) 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%x_MD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x_MD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%x_MD,1), UBOUND(InData%x_MD,1) + CALL MD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x_MD(i1), ErrStat2, ErrMsg2, OnlySize ) ! x_MD + 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%xd_MD) ) 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%xd_MD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_MD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_MD,1), UBOUND(InData%xd_MD,1) + CALL MD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd_MD(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd_MD + 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%z_MD) ) 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%z_MD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z_MD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%z_MD,1), UBOUND(InData%z_MD,1) + CALL MD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z_MD(i1), ErrStat2, ErrMsg2, OnlySize ) ! z_MD + 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%OtherSt_MD) ) 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%OtherSt_MD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt_MD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OtherSt_MD,1), UBOUND(InData%OtherSt_MD,1) + CALL MD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_MD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_MD + 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%u_MD) ) 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%u_MD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_MD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_MD,1), UBOUND(InData%u_MD,1) + CALL MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_MD(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_MD + 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 + END SUBROUTINE FAST_PackLinStateSave + + SUBROUTINE FAST_UnPackLinStateSave( 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(FAST_LinStateSave), 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 = 'FAST_UnPackLinStateSave' + ! 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 ! x_IceD 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%x_IceD)) DEALLOCATE(OutData%x_IceD) + ALLOCATE(OutData%x_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%x_IceD,2), UBOUND(OutData%x_IceD,2) + DO i1 = LBOUND(OutData%x_IceD,1), UBOUND(OutData%x_IceD,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 IceD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_IceD(i1,i2), ErrStat2, ErrMsg2 ) ! x_IceD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_IceD 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%xd_IceD)) DEALLOCATE(OutData%xd_IceD) + ALLOCATE(OutData%xd_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%xd_IceD,2), UBOUND(OutData%xd_IceD,2) + DO i1 = LBOUND(OutData%xd_IceD,1), UBOUND(OutData%xd_IceD,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 IceD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_IceD(i1,i2), ErrStat2, ErrMsg2 ) ! xd_IceD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_IceD 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%z_IceD)) DEALLOCATE(OutData%z_IceD) + ALLOCATE(OutData%z_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%z_IceD,2), UBOUND(OutData%z_IceD,2) + DO i1 = LBOUND(OutData%z_IceD,1), UBOUND(OutData%z_IceD,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 IceD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_IceD(i1,i2), ErrStat2, ErrMsg2 ) ! z_IceD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_IceD 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%OtherSt_IceD)) DEALLOCATE(OutData%OtherSt_IceD) + ALLOCATE(OutData%OtherSt_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OtherSt_IceD,2), UBOUND(OutData%OtherSt_IceD,2) + DO i1 = LBOUND(OutData%OtherSt_IceD,1), UBOUND(OutData%OtherSt_IceD,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 IceD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_IceD(i1,i2), ErrStat2, ErrMsg2 ) ! OtherSt_IceD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_IceD 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%u_IceD)) DEALLOCATE(OutData%u_IceD) + ALLOCATE(OutData%u_IceD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_IceD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%u_IceD,2), UBOUND(OutData%u_IceD,2) + DO i1 = LBOUND(OutData%u_IceD,1), UBOUND(OutData%u_IceD,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 IceD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_IceD(i1,i2), ErrStat2, ErrMsg2 ) ! u_IceD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_BD 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%x_BD)) DEALLOCATE(OutData%x_BD) + ALLOCATE(OutData%x_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%x_BD,2), UBOUND(OutData%x_BD,2) + DO i1 = LBOUND(OutData%x_BD,1), UBOUND(OutData%x_BD,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 BD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_BD(i1,i2), ErrStat2, ErrMsg2 ) ! x_BD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_BD 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%xd_BD)) DEALLOCATE(OutData%xd_BD) + ALLOCATE(OutData%xd_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%xd_BD,2), UBOUND(OutData%xd_BD,2) + DO i1 = LBOUND(OutData%xd_BD,1), UBOUND(OutData%xd_BD,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 BD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_BD(i1,i2), ErrStat2, ErrMsg2 ) ! xd_BD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_BD 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%z_BD)) DEALLOCATE(OutData%z_BD) + ALLOCATE(OutData%z_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%z_BD,2), UBOUND(OutData%z_BD,2) + DO i1 = LBOUND(OutData%z_BD,1), UBOUND(OutData%z_BD,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 BD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_BD(i1,i2), ErrStat2, ErrMsg2 ) ! z_BD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_BD 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%OtherSt_BD)) DEALLOCATE(OutData%OtherSt_BD) + ALLOCATE(OutData%OtherSt_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OtherSt_BD,2), UBOUND(OutData%OtherSt_BD,2) + DO i1 = LBOUND(OutData%OtherSt_BD,1), UBOUND(OutData%OtherSt_BD,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 BD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_BD(i1,i2), ErrStat2, ErrMsg2 ) ! OtherSt_BD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_BD 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%u_BD)) DEALLOCATE(OutData%u_BD) + ALLOCATE(OutData%u_BD(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%u_BD,2), UBOUND(OutData%u_BD,2) + DO i1 = LBOUND(OutData%u_BD,1), UBOUND(OutData%u_BD,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 BD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_BD(i1,i2), ErrStat2, ErrMsg2 ) ! u_BD + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_ED 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%x_ED)) DEALLOCATE(OutData%x_ED) + ALLOCATE(OutData%x_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_ED,1), UBOUND(OutData%x_ED,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 ED_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_ED(i1), ErrStat2, ErrMsg2 ) ! x_ED + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_ED 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%xd_ED)) DEALLOCATE(OutData%xd_ED) + ALLOCATE(OutData%xd_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_ED,1), UBOUND(OutData%xd_ED,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 ED_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_ED(i1), ErrStat2, ErrMsg2 ) ! xd_ED + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_ED 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%z_ED)) DEALLOCATE(OutData%z_ED) + ALLOCATE(OutData%z_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_ED,1), UBOUND(OutData%z_ED,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 ED_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_ED(i1), ErrStat2, ErrMsg2 ) ! z_ED + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_ED 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%OtherSt_ED)) DEALLOCATE(OutData%OtherSt_ED) + ALLOCATE(OutData%OtherSt_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_ED,1), UBOUND(OutData%OtherSt_ED,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 ED_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_ED(i1), ErrStat2, ErrMsg2 ) ! OtherSt_ED + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_ED 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%u_ED)) DEALLOCATE(OutData%u_ED) + ALLOCATE(OutData%u_ED(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_ED.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_ED,1), UBOUND(OutData%u_ED,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 ED_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_ED(i1), ErrStat2, ErrMsg2 ) ! u_ED + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_SrvD 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%x_SrvD)) DEALLOCATE(OutData%x_SrvD) + ALLOCATE(OutData%x_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_SrvD,1), UBOUND(OutData%x_SrvD,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 SrvD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_SrvD(i1), ErrStat2, ErrMsg2 ) ! x_SrvD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_SrvD 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%xd_SrvD)) DEALLOCATE(OutData%xd_SrvD) + ALLOCATE(OutData%xd_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_SrvD,1), UBOUND(OutData%xd_SrvD,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 SrvD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_SrvD(i1), ErrStat2, ErrMsg2 ) ! xd_SrvD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_SrvD 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%z_SrvD)) DEALLOCATE(OutData%z_SrvD) + ALLOCATE(OutData%z_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_SrvD,1), UBOUND(OutData%z_SrvD,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 SrvD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_SrvD(i1), ErrStat2, ErrMsg2 ) ! z_SrvD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_SrvD 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%OtherSt_SrvD)) DEALLOCATE(OutData%OtherSt_SrvD) + ALLOCATE(OutData%OtherSt_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_SrvD,1), UBOUND(OutData%OtherSt_SrvD,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 SrvD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_SrvD(i1), ErrStat2, ErrMsg2 ) ! OtherSt_SrvD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_SrvD 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%u_SrvD)) DEALLOCATE(OutData%u_SrvD) + ALLOCATE(OutData%u_SrvD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_SrvD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_SrvD,1), UBOUND(OutData%u_SrvD,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 SrvD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_SrvD(i1), ErrStat2, ErrMsg2 ) ! u_SrvD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_AD 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%x_AD)) DEALLOCATE(OutData%x_AD) + ALLOCATE(OutData%x_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_AD,1), UBOUND(OutData%x_AD,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 AD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_AD(i1), ErrStat2, ErrMsg2 ) ! x_AD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_AD 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%xd_AD)) DEALLOCATE(OutData%xd_AD) + ALLOCATE(OutData%xd_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_AD,1), UBOUND(OutData%xd_AD,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 AD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_AD(i1), ErrStat2, ErrMsg2 ) ! xd_AD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_AD 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%z_AD)) DEALLOCATE(OutData%z_AD) + ALLOCATE(OutData%z_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_AD,1), UBOUND(OutData%z_AD,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 AD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_AD(i1), ErrStat2, ErrMsg2 ) ! z_AD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_AD 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%OtherSt_AD)) DEALLOCATE(OutData%OtherSt_AD) + ALLOCATE(OutData%OtherSt_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_AD,1), UBOUND(OutData%OtherSt_AD,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 AD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_AD(i1), ErrStat2, ErrMsg2 ) ! OtherSt_AD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_AD 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%u_AD)) DEALLOCATE(OutData%u_AD) + ALLOCATE(OutData%u_AD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_AD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_AD,1), UBOUND(OutData%u_AD,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 AD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_AD(i1), ErrStat2, ErrMsg2 ) ! u_AD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_IfW 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%x_IfW)) DEALLOCATE(OutData%x_IfW) + ALLOCATE(OutData%x_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_IfW,1), UBOUND(OutData%x_IfW,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_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_IfW(i1), ErrStat2, ErrMsg2 ) ! x_IfW + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_IfW 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%xd_IfW)) DEALLOCATE(OutData%xd_IfW) + ALLOCATE(OutData%xd_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_IfW,1), UBOUND(OutData%xd_IfW,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_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_IfW(i1), ErrStat2, ErrMsg2 ) ! xd_IfW + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_IfW 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%z_IfW)) DEALLOCATE(OutData%z_IfW) + ALLOCATE(OutData%z_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_IfW,1), UBOUND(OutData%z_IfW,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_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_IfW(i1), ErrStat2, ErrMsg2 ) ! z_IfW + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_IfW 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%OtherSt_IfW)) DEALLOCATE(OutData%OtherSt_IfW) + ALLOCATE(OutData%OtherSt_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_IfW,1), UBOUND(OutData%OtherSt_IfW,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_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_IfW(i1), ErrStat2, ErrMsg2 ) ! OtherSt_IfW + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_IfW 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%u_IfW)) DEALLOCATE(OutData%u_IfW) + ALLOCATE(OutData%u_IfW(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_IfW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_IfW,1), UBOUND(OutData%u_IfW,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_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_IfW(i1), ErrStat2, ErrMsg2 ) ! u_IfW + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_SD 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%x_SD)) DEALLOCATE(OutData%x_SD) + ALLOCATE(OutData%x_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_SD,1), UBOUND(OutData%x_SD,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 SD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_SD(i1), ErrStat2, ErrMsg2 ) ! x_SD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_SD 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%xd_SD)) DEALLOCATE(OutData%xd_SD) + ALLOCATE(OutData%xd_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_SD,1), UBOUND(OutData%xd_SD,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 SD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_SD(i1), ErrStat2, ErrMsg2 ) ! xd_SD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_SD 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%z_SD)) DEALLOCATE(OutData%z_SD) + ALLOCATE(OutData%z_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_SD,1), UBOUND(OutData%z_SD,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 SD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_SD(i1), ErrStat2, ErrMsg2 ) ! z_SD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_SD 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%OtherSt_SD)) DEALLOCATE(OutData%OtherSt_SD) + ALLOCATE(OutData%OtherSt_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_SD,1), UBOUND(OutData%OtherSt_SD,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 SD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_SD(i1), ErrStat2, ErrMsg2 ) ! OtherSt_SD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_SD 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%u_SD)) DEALLOCATE(OutData%u_SD) + ALLOCATE(OutData%u_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_SD,1), UBOUND(OutData%u_SD,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 SD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_SD(i1), ErrStat2, ErrMsg2 ) ! u_SD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_ExtPtfm 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%x_ExtPtfm)) DEALLOCATE(OutData%x_ExtPtfm) + ALLOCATE(OutData%x_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_ExtPtfm,1), UBOUND(OutData%x_ExtPtfm,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 ExtPtfm_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_ExtPtfm(i1), ErrStat2, ErrMsg2 ) ! x_ExtPtfm + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_ExtPtfm 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%xd_ExtPtfm)) DEALLOCATE(OutData%xd_ExtPtfm) + ALLOCATE(OutData%xd_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_ExtPtfm,1), UBOUND(OutData%xd_ExtPtfm,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 ExtPtfm_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_ExtPtfm(i1), ErrStat2, ErrMsg2 ) ! xd_ExtPtfm + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_ExtPtfm 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%z_ExtPtfm)) DEALLOCATE(OutData%z_ExtPtfm) + ALLOCATE(OutData%z_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_ExtPtfm,1), UBOUND(OutData%z_ExtPtfm,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 ExtPtfm_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_ExtPtfm(i1), ErrStat2, ErrMsg2 ) ! z_ExtPtfm + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_ExtPtfm 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%OtherSt_ExtPtfm)) DEALLOCATE(OutData%OtherSt_ExtPtfm) + ALLOCATE(OutData%OtherSt_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_ExtPtfm,1), UBOUND(OutData%OtherSt_ExtPtfm,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 ExtPtfm_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_ExtPtfm(i1), ErrStat2, ErrMsg2 ) ! OtherSt_ExtPtfm + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_ExtPtfm 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%u_ExtPtfm)) DEALLOCATE(OutData%u_ExtPtfm) + ALLOCATE(OutData%u_ExtPtfm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_ExtPtfm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_ExtPtfm,1), UBOUND(OutData%u_ExtPtfm,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 ExtPtfm_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_ExtPtfm(i1), ErrStat2, ErrMsg2 ) ! u_ExtPtfm + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_HD 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%x_HD)) DEALLOCATE(OutData%x_HD) + ALLOCATE(OutData%x_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_HD,1), UBOUND(OutData%x_HD,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 HydroDyn_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_HD(i1), ErrStat2, ErrMsg2 ) ! x_HD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_HD 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%xd_HD)) DEALLOCATE(OutData%xd_HD) + ALLOCATE(OutData%xd_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_HD,1), UBOUND(OutData%xd_HD,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 HydroDyn_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_HD(i1), ErrStat2, ErrMsg2 ) ! xd_HD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_HD 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%z_HD)) DEALLOCATE(OutData%z_HD) + ALLOCATE(OutData%z_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_HD,1), UBOUND(OutData%z_HD,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 HydroDyn_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_HD(i1), ErrStat2, ErrMsg2 ) ! z_HD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_HD 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%OtherSt_HD)) DEALLOCATE(OutData%OtherSt_HD) + ALLOCATE(OutData%OtherSt_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_HD,1), UBOUND(OutData%OtherSt_HD,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 HydroDyn_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_HD(i1), ErrStat2, ErrMsg2 ) ! OtherSt_HD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_HD 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%u_HD)) DEALLOCATE(OutData%u_HD) + ALLOCATE(OutData%u_HD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_HD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_HD,1), UBOUND(OutData%u_HD,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 HydroDyn_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_HD(i1), ErrStat2, ErrMsg2 ) ! u_HD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_IceF 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%x_IceF)) DEALLOCATE(OutData%x_IceF) + ALLOCATE(OutData%x_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_IceF,1), UBOUND(OutData%x_IceF,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 IceFloe_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_IceF(i1), ErrStat2, ErrMsg2 ) ! x_IceF + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_IceF 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%xd_IceF)) DEALLOCATE(OutData%xd_IceF) + ALLOCATE(OutData%xd_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_IceF,1), UBOUND(OutData%xd_IceF,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 IceFloe_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_IceF(i1), ErrStat2, ErrMsg2 ) ! xd_IceF + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_IceF 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%z_IceF)) DEALLOCATE(OutData%z_IceF) + ALLOCATE(OutData%z_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_IceF,1), UBOUND(OutData%z_IceF,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 IceFloe_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_IceF(i1), ErrStat2, ErrMsg2 ) ! z_IceF + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_IceF 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%OtherSt_IceF)) DEALLOCATE(OutData%OtherSt_IceF) + ALLOCATE(OutData%OtherSt_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_IceF,1), UBOUND(OutData%OtherSt_IceF,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 IceFloe_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_IceF(i1), ErrStat2, ErrMsg2 ) ! OtherSt_IceF + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_IceF 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%u_IceF)) DEALLOCATE(OutData%u_IceF) + ALLOCATE(OutData%u_IceF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_IceF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_IceF,1), UBOUND(OutData%u_IceF,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 IceFloe_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_IceF(i1), ErrStat2, ErrMsg2 ) ! u_IceF + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_MAP 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%x_MAP)) DEALLOCATE(OutData%x_MAP) + ALLOCATE(OutData%x_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_MAP,1), UBOUND(OutData%x_MAP,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 MAP_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_MAP(i1), ErrStat2, ErrMsg2 ) ! x_MAP + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_MAP 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%xd_MAP)) DEALLOCATE(OutData%xd_MAP) + ALLOCATE(OutData%xd_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_MAP,1), UBOUND(OutData%xd_MAP,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 MAP_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_MAP(i1), ErrStat2, ErrMsg2 ) ! xd_MAP + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_MAP 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%z_MAP)) DEALLOCATE(OutData%z_MAP) + ALLOCATE(OutData%z_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_MAP,1), UBOUND(OutData%z_MAP,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 MAP_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_MAP(i1), ErrStat2, ErrMsg2 ) ! z_MAP + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_MAP 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%u_MAP)) DEALLOCATE(OutData%u_MAP) + ALLOCATE(OutData%u_MAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_MAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_MAP,1), UBOUND(OutData%u_MAP,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 MAP_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_MAP(i1), ErrStat2, ErrMsg2 ) ! u_MAP + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_FEAM 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%x_FEAM)) DEALLOCATE(OutData%x_FEAM) + ALLOCATE(OutData%x_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_FEAM,1), UBOUND(OutData%x_FEAM,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 FEAM_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_FEAM(i1), ErrStat2, ErrMsg2 ) ! x_FEAM + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_FEAM 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%xd_FEAM)) DEALLOCATE(OutData%xd_FEAM) + ALLOCATE(OutData%xd_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_FEAM,1), UBOUND(OutData%xd_FEAM,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 FEAM_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_FEAM(i1), ErrStat2, ErrMsg2 ) ! xd_FEAM + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_FEAM 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%z_FEAM)) DEALLOCATE(OutData%z_FEAM) + ALLOCATE(OutData%z_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_FEAM,1), UBOUND(OutData%z_FEAM,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 FEAM_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_FEAM(i1), ErrStat2, ErrMsg2 ) ! z_FEAM + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_FEAM 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%OtherSt_FEAM)) DEALLOCATE(OutData%OtherSt_FEAM) + ALLOCATE(OutData%OtherSt_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_FEAM,1), UBOUND(OutData%OtherSt_FEAM,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 FEAM_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_FEAM(i1), ErrStat2, ErrMsg2 ) ! OtherSt_FEAM + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_FEAM 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%u_FEAM)) DEALLOCATE(OutData%u_FEAM) + ALLOCATE(OutData%u_FEAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_FEAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_FEAM,1), UBOUND(OutData%u_FEAM,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 FEAM_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_FEAM(i1), ErrStat2, ErrMsg2 ) ! u_FEAM + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! x_MD 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%x_MD)) DEALLOCATE(OutData%x_MD) + ALLOCATE(OutData%x_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%x_MD,1), UBOUND(OutData%x_MD,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 MD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x_MD(i1), ErrStat2, ErrMsg2 ) ! x_MD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_MD 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%xd_MD)) DEALLOCATE(OutData%xd_MD) + ALLOCATE(OutData%xd_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_MD,1), UBOUND(OutData%xd_MD,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 MD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd_MD(i1), ErrStat2, ErrMsg2 ) ! xd_MD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z_MD 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%z_MD)) DEALLOCATE(OutData%z_MD) + ALLOCATE(OutData%z_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%z_MD,1), UBOUND(OutData%z_MD,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 MD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z_MD(i1), ErrStat2, ErrMsg2 ) ! z_MD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt_MD 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%OtherSt_MD)) DEALLOCATE(OutData%OtherSt_MD) + ALLOCATE(OutData%OtherSt_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OtherSt_MD,1), UBOUND(OutData%OtherSt_MD,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 MD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_MD(i1), ErrStat2, ErrMsg2 ) ! OtherSt_MD + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_MD 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%u_MD)) DEALLOCATE(OutData%u_MD) + ALLOCATE(OutData%u_MD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_MD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_MD,1), UBOUND(OutData%u_MD,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 MD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_MD(i1), ErrStat2, ErrMsg2 ) ! u_MD + 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 DO + END IF + END SUBROUTINE FAST_UnPackLinStateSave + + SUBROUTINE FAST_CopyLinType( SrcLinTypeData, DstLinTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_LinType), INTENT(IN) :: SrcLinTypeData + TYPE(FAST_LinType), INTENT(INOUT) :: DstLinTypeData + 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 = 'FAST_CopyLinType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcLinTypeData%Names_u)) THEN + i1_l = LBOUND(SrcLinTypeData%Names_u,1) + i1_u = UBOUND(SrcLinTypeData%Names_u,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Names_u)) THEN + ALLOCATE(DstLinTypeData%Names_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Names_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Names_u = SrcLinTypeData%Names_u +ENDIF +IF (ALLOCATED(SrcLinTypeData%Names_y)) THEN + i1_l = LBOUND(SrcLinTypeData%Names_y,1) + i1_u = UBOUND(SrcLinTypeData%Names_y,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Names_y)) THEN + ALLOCATE(DstLinTypeData%Names_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Names_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Names_y = SrcLinTypeData%Names_y +ENDIF +IF (ALLOCATED(SrcLinTypeData%Names_x)) THEN + i1_l = LBOUND(SrcLinTypeData%Names_x,1) + i1_u = UBOUND(SrcLinTypeData%Names_x,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Names_x)) THEN + ALLOCATE(DstLinTypeData%Names_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Names_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Names_x = SrcLinTypeData%Names_x +ENDIF +IF (ALLOCATED(SrcLinTypeData%Names_xd)) THEN + i1_l = LBOUND(SrcLinTypeData%Names_xd,1) + i1_u = UBOUND(SrcLinTypeData%Names_xd,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Names_xd)) THEN + ALLOCATE(DstLinTypeData%Names_xd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Names_xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Names_xd = SrcLinTypeData%Names_xd +ENDIF +IF (ALLOCATED(SrcLinTypeData%Names_z)) THEN + i1_l = LBOUND(SrcLinTypeData%Names_z,1) + i1_u = UBOUND(SrcLinTypeData%Names_z,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Names_z)) THEN + ALLOCATE(DstLinTypeData%Names_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Names_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Names_z = SrcLinTypeData%Names_z +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_u)) THEN + i1_l = LBOUND(SrcLinTypeData%op_u,1) + i1_u = UBOUND(SrcLinTypeData%op_u,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_u)) THEN + ALLOCATE(DstLinTypeData%op_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_u = SrcLinTypeData%op_u +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_y)) THEN + i1_l = LBOUND(SrcLinTypeData%op_y,1) + i1_u = UBOUND(SrcLinTypeData%op_y,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_y)) THEN + ALLOCATE(DstLinTypeData%op_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_y = SrcLinTypeData%op_y +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_x)) THEN + i1_l = LBOUND(SrcLinTypeData%op_x,1) + i1_u = UBOUND(SrcLinTypeData%op_x,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_x)) THEN + ALLOCATE(DstLinTypeData%op_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_x = SrcLinTypeData%op_x +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_dx)) THEN + i1_l = LBOUND(SrcLinTypeData%op_dx,1) + i1_u = UBOUND(SrcLinTypeData%op_dx,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_dx)) THEN + ALLOCATE(DstLinTypeData%op_dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_dx = SrcLinTypeData%op_dx +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_xd)) THEN + i1_l = LBOUND(SrcLinTypeData%op_xd,1) + i1_u = UBOUND(SrcLinTypeData%op_xd,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_xd)) THEN + ALLOCATE(DstLinTypeData%op_xd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_xd = SrcLinTypeData%op_xd +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_z)) THEN + i1_l = LBOUND(SrcLinTypeData%op_z,1) + i1_u = UBOUND(SrcLinTypeData%op_z,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_z)) THEN + ALLOCATE(DstLinTypeData%op_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_z = SrcLinTypeData%op_z +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_x_eig_mag)) THEN + i1_l = LBOUND(SrcLinTypeData%op_x_eig_mag,1) + i1_u = UBOUND(SrcLinTypeData%op_x_eig_mag,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_x_eig_mag)) THEN + ALLOCATE(DstLinTypeData%op_x_eig_mag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_x_eig_mag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_x_eig_mag = SrcLinTypeData%op_x_eig_mag +ENDIF +IF (ALLOCATED(SrcLinTypeData%op_x_eig_phase)) THEN + i1_l = LBOUND(SrcLinTypeData%op_x_eig_phase,1) + i1_u = UBOUND(SrcLinTypeData%op_x_eig_phase,1) + IF (.NOT. ALLOCATED(DstLinTypeData%op_x_eig_phase)) THEN + ALLOCATE(DstLinTypeData%op_x_eig_phase(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%op_x_eig_phase.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%op_x_eig_phase = SrcLinTypeData%op_x_eig_phase +ENDIF +IF (ALLOCATED(SrcLinTypeData%Use_u)) THEN + i1_l = LBOUND(SrcLinTypeData%Use_u,1) + i1_u = UBOUND(SrcLinTypeData%Use_u,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Use_u)) THEN + ALLOCATE(DstLinTypeData%Use_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Use_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Use_u = SrcLinTypeData%Use_u +ENDIF +IF (ALLOCATED(SrcLinTypeData%Use_y)) THEN + i1_l = LBOUND(SrcLinTypeData%Use_y,1) + i1_u = UBOUND(SrcLinTypeData%Use_y,1) + IF (.NOT. ALLOCATED(DstLinTypeData%Use_y)) THEN + ALLOCATE(DstLinTypeData%Use_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%Use_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%Use_y = SrcLinTypeData%Use_y +ENDIF +IF (ALLOCATED(SrcLinTypeData%A)) THEN + i1_l = LBOUND(SrcLinTypeData%A,1) + i1_u = UBOUND(SrcLinTypeData%A,1) + i2_l = LBOUND(SrcLinTypeData%A,2) + i2_u = UBOUND(SrcLinTypeData%A,2) + IF (.NOT. ALLOCATED(DstLinTypeData%A)) THEN + ALLOCATE(DstLinTypeData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%A = SrcLinTypeData%A +ENDIF +IF (ALLOCATED(SrcLinTypeData%B)) THEN + i1_l = LBOUND(SrcLinTypeData%B,1) + i1_u = UBOUND(SrcLinTypeData%B,1) + i2_l = LBOUND(SrcLinTypeData%B,2) + i2_u = UBOUND(SrcLinTypeData%B,2) + IF (.NOT. ALLOCATED(DstLinTypeData%B)) THEN + ALLOCATE(DstLinTypeData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%B = SrcLinTypeData%B +ENDIF +IF (ALLOCATED(SrcLinTypeData%C)) THEN + i1_l = LBOUND(SrcLinTypeData%C,1) + i1_u = UBOUND(SrcLinTypeData%C,1) + i2_l = LBOUND(SrcLinTypeData%C,2) + i2_u = UBOUND(SrcLinTypeData%C,2) + IF (.NOT. ALLOCATED(DstLinTypeData%C)) THEN + ALLOCATE(DstLinTypeData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%C = SrcLinTypeData%C +ENDIF +IF (ALLOCATED(SrcLinTypeData%D)) THEN + i1_l = LBOUND(SrcLinTypeData%D,1) + i1_u = UBOUND(SrcLinTypeData%D,1) + i2_l = LBOUND(SrcLinTypeData%D,2) + i2_u = UBOUND(SrcLinTypeData%D,2) + IF (.NOT. ALLOCATED(DstLinTypeData%D)) THEN + ALLOCATE(DstLinTypeData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%D = SrcLinTypeData%D +ENDIF +IF (ALLOCATED(SrcLinTypeData%StateRotation)) THEN + i1_l = LBOUND(SrcLinTypeData%StateRotation,1) + i1_u = UBOUND(SrcLinTypeData%StateRotation,1) + i2_l = LBOUND(SrcLinTypeData%StateRotation,2) + i2_u = UBOUND(SrcLinTypeData%StateRotation,2) + IF (.NOT. ALLOCATED(DstLinTypeData%StateRotation)) THEN + ALLOCATE(DstLinTypeData%StateRotation(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%StateRotation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%StateRotation = SrcLinTypeData%StateRotation +ENDIF +IF (ALLOCATED(SrcLinTypeData%StateRel_x)) THEN + i1_l = LBOUND(SrcLinTypeData%StateRel_x,1) + i1_u = UBOUND(SrcLinTypeData%StateRel_x,1) + i2_l = LBOUND(SrcLinTypeData%StateRel_x,2) + i2_u = UBOUND(SrcLinTypeData%StateRel_x,2) + IF (.NOT. ALLOCATED(DstLinTypeData%StateRel_x)) THEN + ALLOCATE(DstLinTypeData%StateRel_x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%StateRel_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%StateRel_x = SrcLinTypeData%StateRel_x +ENDIF +IF (ALLOCATED(SrcLinTypeData%StateRel_xdot)) THEN + i1_l = LBOUND(SrcLinTypeData%StateRel_xdot,1) + i1_u = UBOUND(SrcLinTypeData%StateRel_xdot,1) + i2_l = LBOUND(SrcLinTypeData%StateRel_xdot,2) + i2_u = UBOUND(SrcLinTypeData%StateRel_xdot,2) + IF (.NOT. ALLOCATED(DstLinTypeData%StateRel_xdot)) THEN + ALLOCATE(DstLinTypeData%StateRel_xdot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%StateRel_xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%StateRel_xdot = SrcLinTypeData%StateRel_xdot +ENDIF +IF (ALLOCATED(SrcLinTypeData%IsLoad_u)) THEN + i1_l = LBOUND(SrcLinTypeData%IsLoad_u,1) + i1_u = UBOUND(SrcLinTypeData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstLinTypeData%IsLoad_u)) THEN + ALLOCATE(DstLinTypeData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%IsLoad_u = SrcLinTypeData%IsLoad_u +ENDIF +IF (ALLOCATED(SrcLinTypeData%RotFrame_u)) THEN + i1_l = LBOUND(SrcLinTypeData%RotFrame_u,1) + i1_u = UBOUND(SrcLinTypeData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstLinTypeData%RotFrame_u)) THEN + ALLOCATE(DstLinTypeData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%RotFrame_u = SrcLinTypeData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcLinTypeData%RotFrame_y)) THEN + i1_l = LBOUND(SrcLinTypeData%RotFrame_y,1) + i1_u = UBOUND(SrcLinTypeData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstLinTypeData%RotFrame_y)) THEN + ALLOCATE(DstLinTypeData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%RotFrame_y = SrcLinTypeData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcLinTypeData%RotFrame_x)) THEN + i1_l = LBOUND(SrcLinTypeData%RotFrame_x,1) + i1_u = UBOUND(SrcLinTypeData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstLinTypeData%RotFrame_x)) THEN + ALLOCATE(DstLinTypeData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%RotFrame_x = SrcLinTypeData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcLinTypeData%RotFrame_z)) THEN + i1_l = LBOUND(SrcLinTypeData%RotFrame_z,1) + i1_u = UBOUND(SrcLinTypeData%RotFrame_z,1) + IF (.NOT. ALLOCATED(DstLinTypeData%RotFrame_z)) THEN + ALLOCATE(DstLinTypeData%RotFrame_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%RotFrame_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%RotFrame_z = SrcLinTypeData%RotFrame_z +ENDIF +IF (ALLOCATED(SrcLinTypeData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcLinTypeData%DerivOrder_x,1) + i1_u = UBOUND(SrcLinTypeData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstLinTypeData%DerivOrder_x)) THEN + ALLOCATE(DstLinTypeData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstLinTypeData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstLinTypeData%DerivOrder_x = SrcLinTypeData%DerivOrder_x +ENDIF + DstLinTypeData%SizeLin = SrcLinTypeData%SizeLin + DstLinTypeData%LinStartIndx = SrcLinTypeData%LinStartIndx + DstLinTypeData%NumOutputs = SrcLinTypeData%NumOutputs + END SUBROUTINE FAST_CopyLinType + + SUBROUTINE FAST_DestroyLinType( LinTypeData, ErrStat, ErrMsg ) + TYPE(FAST_LinType), INTENT(INOUT) :: LinTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyLinType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(LinTypeData%Names_u)) THEN + DEALLOCATE(LinTypeData%Names_u) +ENDIF +IF (ALLOCATED(LinTypeData%Names_y)) THEN + DEALLOCATE(LinTypeData%Names_y) +ENDIF +IF (ALLOCATED(LinTypeData%Names_x)) THEN + DEALLOCATE(LinTypeData%Names_x) +ENDIF +IF (ALLOCATED(LinTypeData%Names_xd)) THEN + DEALLOCATE(LinTypeData%Names_xd) +ENDIF +IF (ALLOCATED(LinTypeData%Names_z)) THEN + DEALLOCATE(LinTypeData%Names_z) +ENDIF +IF (ALLOCATED(LinTypeData%op_u)) THEN + DEALLOCATE(LinTypeData%op_u) +ENDIF +IF (ALLOCATED(LinTypeData%op_y)) THEN + DEALLOCATE(LinTypeData%op_y) +ENDIF +IF (ALLOCATED(LinTypeData%op_x)) THEN + DEALLOCATE(LinTypeData%op_x) +ENDIF +IF (ALLOCATED(LinTypeData%op_dx)) THEN + DEALLOCATE(LinTypeData%op_dx) +ENDIF +IF (ALLOCATED(LinTypeData%op_xd)) THEN + DEALLOCATE(LinTypeData%op_xd) +ENDIF +IF (ALLOCATED(LinTypeData%op_z)) THEN + DEALLOCATE(LinTypeData%op_z) +ENDIF +IF (ALLOCATED(LinTypeData%op_x_eig_mag)) THEN + DEALLOCATE(LinTypeData%op_x_eig_mag) +ENDIF +IF (ALLOCATED(LinTypeData%op_x_eig_phase)) THEN + DEALLOCATE(LinTypeData%op_x_eig_phase) +ENDIF +IF (ALLOCATED(LinTypeData%Use_u)) THEN + DEALLOCATE(LinTypeData%Use_u) +ENDIF +IF (ALLOCATED(LinTypeData%Use_y)) THEN + DEALLOCATE(LinTypeData%Use_y) +ENDIF +IF (ALLOCATED(LinTypeData%A)) THEN + DEALLOCATE(LinTypeData%A) +ENDIF +IF (ALLOCATED(LinTypeData%B)) THEN + DEALLOCATE(LinTypeData%B) +ENDIF +IF (ALLOCATED(LinTypeData%C)) THEN + DEALLOCATE(LinTypeData%C) +ENDIF +IF (ALLOCATED(LinTypeData%D)) THEN + DEALLOCATE(LinTypeData%D) +ENDIF +IF (ALLOCATED(LinTypeData%StateRotation)) THEN + DEALLOCATE(LinTypeData%StateRotation) +ENDIF +IF (ALLOCATED(LinTypeData%StateRel_x)) THEN + DEALLOCATE(LinTypeData%StateRel_x) +ENDIF +IF (ALLOCATED(LinTypeData%StateRel_xdot)) THEN + DEALLOCATE(LinTypeData%StateRel_xdot) +ENDIF +IF (ALLOCATED(LinTypeData%IsLoad_u)) THEN + DEALLOCATE(LinTypeData%IsLoad_u) +ENDIF +IF (ALLOCATED(LinTypeData%RotFrame_u)) THEN + DEALLOCATE(LinTypeData%RotFrame_u) +ENDIF +IF (ALLOCATED(LinTypeData%RotFrame_y)) THEN + DEALLOCATE(LinTypeData%RotFrame_y) +ENDIF +IF (ALLOCATED(LinTypeData%RotFrame_x)) THEN + DEALLOCATE(LinTypeData%RotFrame_x) +ENDIF +IF (ALLOCATED(LinTypeData%RotFrame_z)) THEN + DEALLOCATE(LinTypeData%RotFrame_z) +ENDIF +IF (ALLOCATED(LinTypeData%DerivOrder_x)) THEN + DEALLOCATE(LinTypeData%DerivOrder_x) +ENDIF + END SUBROUTINE FAST_DestroyLinType + + SUBROUTINE FAST_PackLinType( 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(FAST_LinType), 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 = 'FAST_PackLinType' + ! 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 ! Names_u allocated yes/no + IF ( ALLOCATED(InData%Names_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Names_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Names_u)*LEN(InData%Names_u) ! Names_u + END IF + Int_BufSz = Int_BufSz + 1 ! Names_y allocated yes/no + IF ( ALLOCATED(InData%Names_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Names_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Names_y)*LEN(InData%Names_y) ! Names_y + END IF + Int_BufSz = Int_BufSz + 1 ! Names_x allocated yes/no + IF ( ALLOCATED(InData%Names_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Names_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Names_x)*LEN(InData%Names_x) ! Names_x + END IF + Int_BufSz = Int_BufSz + 1 ! Names_xd allocated yes/no + IF ( ALLOCATED(InData%Names_xd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Names_xd upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Names_xd)*LEN(InData%Names_xd) ! Names_xd + END IF + Int_BufSz = Int_BufSz + 1 ! Names_z allocated yes/no + IF ( ALLOCATED(InData%Names_z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Names_z upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Names_z)*LEN(InData%Names_z) ! Names_z + END IF + Int_BufSz = Int_BufSz + 1 ! op_u allocated yes/no + IF ( ALLOCATED(InData%op_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_u) ! op_u + END IF + Int_BufSz = Int_BufSz + 1 ! op_y allocated yes/no + IF ( ALLOCATED(InData%op_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_y upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_y) ! op_y + END IF + Int_BufSz = Int_BufSz + 1 ! op_x allocated yes/no + IF ( ALLOCATED(InData%op_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_x upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_x) ! op_x + END IF + Int_BufSz = Int_BufSz + 1 ! op_dx allocated yes/no + IF ( ALLOCATED(InData%op_dx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_dx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_dx) ! op_dx + END IF + Int_BufSz = Int_BufSz + 1 ! op_xd allocated yes/no + IF ( ALLOCATED(InData%op_xd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_xd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_xd) ! op_xd + END IF + Int_BufSz = Int_BufSz + 1 ! op_z allocated yes/no + IF ( ALLOCATED(InData%op_z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_z upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%op_z) ! op_z + END IF + Int_BufSz = Int_BufSz + 1 ! op_x_eig_mag allocated yes/no + IF ( ALLOCATED(InData%op_x_eig_mag) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_x_eig_mag upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%op_x_eig_mag) ! op_x_eig_mag + END IF + Int_BufSz = Int_BufSz + 1 ! op_x_eig_phase allocated yes/no + IF ( ALLOCATED(InData%op_x_eig_phase) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! op_x_eig_phase upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%op_x_eig_phase) ! op_x_eig_phase + END IF + Int_BufSz = Int_BufSz + 1 ! Use_u allocated yes/no + IF ( ALLOCATED(InData%Use_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Use_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Use_u) ! Use_u + END IF + Int_BufSz = Int_BufSz + 1 ! Use_y allocated yes/no + IF ( ALLOCATED(InData%Use_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Use_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Use_y) ! Use_y + END IF + Int_BufSz = Int_BufSz + 1 ! A allocated yes/no + IF ( ALLOCATED(InData%A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! A upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%A) ! A + END IF + Int_BufSz = Int_BufSz + 1 ! B allocated yes/no + IF ( ALLOCATED(InData%B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! B upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%B) ! B + END IF + Int_BufSz = Int_BufSz + 1 ! C allocated yes/no + IF ( ALLOCATED(InData%C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%C) ! C + END IF + Int_BufSz = Int_BufSz + 1 ! D allocated yes/no + IF ( ALLOCATED(InData%D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%D) ! D + END IF + Int_BufSz = Int_BufSz + 1 ! StateRotation allocated yes/no + IF ( ALLOCATED(InData%StateRotation) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StateRotation upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%StateRotation) ! StateRotation + END IF + Int_BufSz = Int_BufSz + 1 ! StateRel_x allocated yes/no + IF ( ALLOCATED(InData%StateRel_x) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StateRel_x upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%StateRel_x) ! StateRel_x + END IF + Int_BufSz = Int_BufSz + 1 ! StateRel_xdot allocated yes/no + IF ( ALLOCATED(InData%StateRel_xdot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! StateRel_xdot upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%StateRel_xdot) ! StateRel_xdot + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_z allocated yes/no + IF ( ALLOCATED(InData%RotFrame_z) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_z upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_z) ! RotFrame_z + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF + Int_BufSz = Int_BufSz + SIZE(InData%SizeLin) ! SizeLin + Int_BufSz = Int_BufSz + SIZE(InData%LinStartIndx) ! LinStartIndx + Int_BufSz = Int_BufSz + 1 ! NumOutputs + 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%Names_u) ) 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%Names_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Names_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Names_u,1), UBOUND(InData%Names_u,1) + DO I = 1, LEN(InData%Names_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%Names_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Names_y) ) 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%Names_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Names_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Names_y,1), UBOUND(InData%Names_y,1) + DO I = 1, LEN(InData%Names_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%Names_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Names_x) ) 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%Names_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Names_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Names_x,1), UBOUND(InData%Names_x,1) + DO I = 1, LEN(InData%Names_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%Names_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Names_xd) ) 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%Names_xd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Names_xd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Names_xd,1), UBOUND(InData%Names_xd,1) + DO I = 1, LEN(InData%Names_xd) + IntKiBuf(Int_Xferred) = ICHAR(InData%Names_xd(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Names_z) ) 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%Names_z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Names_z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Names_z,1), UBOUND(InData%Names_z,1) + DO I = 1, LEN(InData%Names_z) + IntKiBuf(Int_Xferred) = ICHAR(InData%Names_z(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_u) ) 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%op_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_u,1), UBOUND(InData%op_u,1) + ReKiBuf(Re_Xferred) = InData%op_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_y) ) 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%op_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_y,1), UBOUND(InData%op_y,1) + ReKiBuf(Re_Xferred) = InData%op_y(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_x) ) 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%op_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_x,1), UBOUND(InData%op_x,1) + ReKiBuf(Re_Xferred) = InData%op_x(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_dx) ) 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%op_dx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_dx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_dx,1), UBOUND(InData%op_dx,1) + ReKiBuf(Re_Xferred) = InData%op_dx(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_xd) ) 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%op_xd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_xd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_xd,1), UBOUND(InData%op_xd,1) + ReKiBuf(Re_Xferred) = InData%op_xd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_z) ) 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%op_z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_z,1), UBOUND(InData%op_z,1) + ReKiBuf(Re_Xferred) = InData%op_z(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_x_eig_mag) ) 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%op_x_eig_mag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_x_eig_mag,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_x_eig_mag,1), UBOUND(InData%op_x_eig_mag,1) + DbKiBuf(Db_Xferred) = InData%op_x_eig_mag(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%op_x_eig_phase) ) 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%op_x_eig_phase,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%op_x_eig_phase,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%op_x_eig_phase,1), UBOUND(InData%op_x_eig_phase,1) + DbKiBuf(Db_Xferred) = InData%op_x_eig_phase(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Use_u) ) 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%Use_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Use_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Use_u,1), UBOUND(InData%Use_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%Use_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Use_y) ) 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%Use_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Use_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Use_y,1), UBOUND(InData%Use_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%Use_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%A) ) 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%A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%A,2), UBOUND(InData%A,2) + DO i1 = LBOUND(InData%A,1), UBOUND(InData%A,1) + DbKiBuf(Db_Xferred) = InData%A(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%B) ) 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%B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%B,2), UBOUND(InData%B,2) + DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) + DbKiBuf(Db_Xferred) = InData%B(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C) ) 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%C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C,2), UBOUND(InData%C,2) + DO i1 = LBOUND(InData%C,1), UBOUND(InData%C,1) + DbKiBuf(Db_Xferred) = InData%C(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D) ) 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%D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D,2), UBOUND(InData%D,2) + DO i1 = LBOUND(InData%D,1), UBOUND(InData%D,1) + DbKiBuf(Db_Xferred) = InData%D(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StateRotation) ) 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%StateRotation,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRotation,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StateRotation,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRotation,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StateRotation,2), UBOUND(InData%StateRotation,2) + DO i1 = LBOUND(InData%StateRotation,1), UBOUND(InData%StateRotation,1) + DbKiBuf(Db_Xferred) = InData%StateRotation(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StateRel_x) ) 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%StateRel_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRel_x,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StateRel_x,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRel_x,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StateRel_x,2), UBOUND(InData%StateRel_x,2) + DO i1 = LBOUND(InData%StateRel_x,1), UBOUND(InData%StateRel_x,1) + DbKiBuf(Db_Xferred) = InData%StateRel_x(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%StateRel_xdot) ) 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%StateRel_xdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRel_xdot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%StateRel_xdot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StateRel_xdot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%StateRel_xdot,2), UBOUND(InData%StateRel_xdot,2) + DO i1 = LBOUND(InData%StateRel_xdot,1), UBOUND(InData%StateRel_xdot,1) + DbKiBuf(Db_Xferred) = InData%StateRel_xdot(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) 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%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_z) ) 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%RotFrame_z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_z,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_z,1), UBOUND(InData%RotFrame_z,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_z(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) 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%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%SizeLin,1), UBOUND(InData%SizeLin,1) + IntKiBuf(Int_Xferred) = InData%SizeLin(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%LinStartIndx,1), UBOUND(InData%LinStartIndx,1) + IntKiBuf(Int_Xferred) = InData%LinStartIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumOutputs + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_PackLinType + + SUBROUTINE FAST_UnPackLinType( 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(FAST_LinType), 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 = 'FAST_UnPackLinType' + ! 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 ! Names_u 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%Names_u)) DEALLOCATE(OutData%Names_u) + ALLOCATE(OutData%Names_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Names_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Names_u,1), UBOUND(OutData%Names_u,1) + DO I = 1, LEN(OutData%Names_u) + OutData%Names_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Names_y 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%Names_y)) DEALLOCATE(OutData%Names_y) + ALLOCATE(OutData%Names_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Names_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Names_y,1), UBOUND(OutData%Names_y,1) + DO I = 1, LEN(OutData%Names_y) + OutData%Names_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Names_x 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%Names_x)) DEALLOCATE(OutData%Names_x) + ALLOCATE(OutData%Names_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Names_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Names_x,1), UBOUND(OutData%Names_x,1) + DO I = 1, LEN(OutData%Names_x) + OutData%Names_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Names_xd 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%Names_xd)) DEALLOCATE(OutData%Names_xd) + ALLOCATE(OutData%Names_xd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Names_xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Names_xd,1), UBOUND(OutData%Names_xd,1) + DO I = 1, LEN(OutData%Names_xd) + OutData%Names_xd(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Names_z 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%Names_z)) DEALLOCATE(OutData%Names_z) + ALLOCATE(OutData%Names_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Names_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Names_z,1), UBOUND(OutData%Names_z,1) + DO I = 1, LEN(OutData%Names_z) + OutData%Names_z(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_u 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%op_u)) DEALLOCATE(OutData%op_u) + ALLOCATE(OutData%op_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_u,1), UBOUND(OutData%op_u,1) + OutData%op_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_y 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%op_y)) DEALLOCATE(OutData%op_y) + ALLOCATE(OutData%op_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_y,1), UBOUND(OutData%op_y,1) + OutData%op_y(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_x 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%op_x)) DEALLOCATE(OutData%op_x) + ALLOCATE(OutData%op_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_x,1), UBOUND(OutData%op_x,1) + OutData%op_x(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_dx 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%op_dx)) DEALLOCATE(OutData%op_dx) + ALLOCATE(OutData%op_dx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_dx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_dx,1), UBOUND(OutData%op_dx,1) + OutData%op_dx(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_xd 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%op_xd)) DEALLOCATE(OutData%op_xd) + ALLOCATE(OutData%op_xd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_xd,1), UBOUND(OutData%op_xd,1) + OutData%op_xd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_z 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%op_z)) DEALLOCATE(OutData%op_z) + ALLOCATE(OutData%op_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_z,1), UBOUND(OutData%op_z,1) + OutData%op_z(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_x_eig_mag 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%op_x_eig_mag)) DEALLOCATE(OutData%op_x_eig_mag) + ALLOCATE(OutData%op_x_eig_mag(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_x_eig_mag.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_x_eig_mag,1), UBOUND(OutData%op_x_eig_mag,1) + OutData%op_x_eig_mag(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! op_x_eig_phase 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%op_x_eig_phase)) DEALLOCATE(OutData%op_x_eig_phase) + ALLOCATE(OutData%op_x_eig_phase(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%op_x_eig_phase.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%op_x_eig_phase,1), UBOUND(OutData%op_x_eig_phase,1) + OutData%op_x_eig_phase(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Use_u 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%Use_u)) DEALLOCATE(OutData%Use_u) + ALLOCATE(OutData%Use_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Use_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Use_u,1), UBOUND(OutData%Use_u,1) + OutData%Use_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%Use_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Use_y 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%Use_y)) DEALLOCATE(OutData%Use_y) + ALLOCATE(OutData%Use_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Use_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Use_y,1), UBOUND(OutData%Use_y,1) + OutData%Use_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%Use_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! A 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%A)) DEALLOCATE(OutData%A) + ALLOCATE(OutData%A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%A,2), UBOUND(OutData%A,2) + DO i1 = LBOUND(OutData%A,1), UBOUND(OutData%A,1) + OutData%A(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! B 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%B)) DEALLOCATE(OutData%B) + ALLOCATE(OutData%B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%B,2), UBOUND(OutData%B,2) + DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) + OutData%B(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C 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%C)) DEALLOCATE(OutData%C) + ALLOCATE(OutData%C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C,2), UBOUND(OutData%C,2) + DO i1 = LBOUND(OutData%C,1), UBOUND(OutData%C,1) + OutData%C(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D 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%D)) DEALLOCATE(OutData%D) + ALLOCATE(OutData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D,2), UBOUND(OutData%D,2) + DO i1 = LBOUND(OutData%D,1), UBOUND(OutData%D,1) + OutData%D(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StateRotation 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%StateRotation)) DEALLOCATE(OutData%StateRotation) + ALLOCATE(OutData%StateRotation(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StateRotation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StateRotation,2), UBOUND(OutData%StateRotation,2) + DO i1 = LBOUND(OutData%StateRotation,1), UBOUND(OutData%StateRotation,1) + OutData%StateRotation(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StateRel_x 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%StateRel_x)) DEALLOCATE(OutData%StateRel_x) + ALLOCATE(OutData%StateRel_x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StateRel_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StateRel_x,2), UBOUND(OutData%StateRel_x,2) + DO i1 = LBOUND(OutData%StateRel_x,1), UBOUND(OutData%StateRel_x,1) + OutData%StateRel_x(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StateRel_xdot 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%StateRel_xdot)) DEALLOCATE(OutData%StateRel_xdot) + ALLOCATE(OutData%StateRel_xdot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StateRel_xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%StateRel_xdot,2), UBOUND(OutData%StateRel_xdot,2) + DO i1 = LBOUND(OutData%StateRel_xdot,1), UBOUND(OutData%StateRel_xdot,1) + OutData%StateRel_xdot(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x 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%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_z 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%RotFrame_z)) DEALLOCATE(OutData%RotFrame_z) + ALLOCATE(OutData%RotFrame_z(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_z,1), UBOUND(OutData%RotFrame_z,1) + OutData%RotFrame_z(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_z(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x 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%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%SizeLin,1) + i1_u = UBOUND(OutData%SizeLin,1) + DO i1 = LBOUND(OutData%SizeLin,1), UBOUND(OutData%SizeLin,1) + OutData%SizeLin(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%LinStartIndx,1) + i1_u = UBOUND(OutData%LinStartIndx,1) + DO i1 = LBOUND(OutData%LinStartIndx,1), UBOUND(OutData%LinStartIndx,1) + OutData%LinStartIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%NumOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_UnPackLinType + + SUBROUTINE FAST_CopyModLinType( SrcModLinTypeData, DstModLinTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_ModLinType), INTENT(IN) :: SrcModLinTypeData + TYPE(FAST_ModLinType), INTENT(INOUT) :: DstModLinTypeData + 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 = 'FAST_CopyModLinType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcModLinTypeData%Instance)) THEN + i1_l = LBOUND(SrcModLinTypeData%Instance,1) + i1_u = UBOUND(SrcModLinTypeData%Instance,1) + IF (.NOT. ALLOCATED(DstModLinTypeData%Instance)) THEN + ALLOCATE(DstModLinTypeData%Instance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModLinTypeData%Instance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModLinTypeData%Instance,1), UBOUND(SrcModLinTypeData%Instance,1) + CALL FAST_Copylintype( SrcModLinTypeData%Instance(i1), DstModLinTypeData%Instance(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + END SUBROUTINE FAST_CopyModLinType + + SUBROUTINE FAST_DestroyModLinType( ModLinTypeData, ErrStat, ErrMsg ) + TYPE(FAST_ModLinType), INTENT(INOUT) :: ModLinTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyModLinType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ModLinTypeData%Instance)) THEN +DO i1 = LBOUND(ModLinTypeData%Instance,1), UBOUND(ModLinTypeData%Instance,1) + CALL FAST_Destroylintype( ModLinTypeData%Instance(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModLinTypeData%Instance) +ENDIF + END SUBROUTINE FAST_DestroyModLinType + + SUBROUTINE FAST_PackModLinType( 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(FAST_ModLinType), 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 = 'FAST_PackModLinType' + ! 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 ! Instance allocated yes/no + IF ( ALLOCATED(InData%Instance) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Instance upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Instance,1), UBOUND(InData%Instance,1) + Int_BufSz = Int_BufSz + 3 ! Instance: size of buffers for each call to pack subtype + CALL FAST_Packlintype( Re_Buf, Db_Buf, Int_Buf, InData%Instance(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Instance + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Instance + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Instance + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Instance + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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%Instance) ) 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%Instance,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Instance,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Instance,1), UBOUND(InData%Instance,1) + CALL FAST_Packlintype( Re_Buf, Db_Buf, Int_Buf, InData%Instance(i1), ErrStat2, ErrMsg2, OnlySize ) ! Instance + 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 + END SUBROUTINE FAST_PackModLinType + + SUBROUTINE FAST_UnPackModLinType( 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(FAST_ModLinType), 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 = 'FAST_UnPackModLinType' + ! 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 ! Instance 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%Instance)) DEALLOCATE(OutData%Instance) + ALLOCATE(OutData%Instance(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Instance.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Instance,1), UBOUND(OutData%Instance,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 FAST_Unpacklintype( Re_Buf, Db_Buf, Int_Buf, OutData%Instance(i1), ErrStat2, ErrMsg2 ) ! Instance + 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 DO + END IF + END SUBROUTINE FAST_UnPackModLinType + + SUBROUTINE FAST_CopyLinFileType( SrcLinFileTypeData, DstLinFileTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_LinFileType), INTENT(IN) :: SrcLinFileTypeData + TYPE(FAST_LinFileType), INTENT(INOUT) :: DstLinFileTypeData + 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 = 'FAST_CopyLinFileType' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcLinFileTypeData%Modules,1), UBOUND(SrcLinFileTypeData%Modules,1) + CALL FAST_Copymodlintype( SrcLinFileTypeData%Modules(i1), DstLinFileTypeData%Modules(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL FAST_Copylintype( SrcLinFileTypeData%Glue, DstLinFileTypeData%Glue, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstLinFileTypeData%RotSpeed = SrcLinFileTypeData%RotSpeed + DstLinFileTypeData%Azimuth = SrcLinFileTypeData%Azimuth + DstLinFileTypeData%WindSpeed = SrcLinFileTypeData%WindSpeed + END SUBROUTINE FAST_CopyLinFileType + + SUBROUTINE FAST_DestroyLinFileType( LinFileTypeData, ErrStat, ErrMsg ) + TYPE(FAST_LinFileType), INTENT(INOUT) :: LinFileTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyLinFileType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(LinFileTypeData%Modules,1), UBOUND(LinFileTypeData%Modules,1) + CALL FAST_Destroymodlintype( LinFileTypeData%Modules(i1), ErrStat, ErrMsg ) +ENDDO + CALL FAST_Destroylintype( LinFileTypeData%Glue, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyLinFileType + + SUBROUTINE FAST_PackLinFileType( 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(FAST_LinFileType), 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 = 'FAST_PackLinFileType' + ! 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) + DO i1 = LBOUND(InData%Modules,1), UBOUND(InData%Modules,1) + Int_BufSz = Int_BufSz + 3 ! Modules: size of buffers for each call to pack subtype + CALL FAST_Packmodlintype( Re_Buf, Db_Buf, Int_Buf, InData%Modules(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Modules + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Modules + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Modules + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Modules + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! Glue: size of buffers for each call to pack subtype + CALL FAST_Packlintype( Re_Buf, Db_Buf, Int_Buf, InData%Glue, ErrStat2, ErrMsg2, .TRUE. ) ! Glue + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Glue + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Glue + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Glue + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Re_BufSz = Re_BufSz + 1 ! Azimuth + Re_BufSz = Re_BufSz + 1 ! WindSpeed + 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%Modules,1), UBOUND(InData%Modules,1) + CALL FAST_Packmodlintype( Re_Buf, Db_Buf, Int_Buf, InData%Modules(i1), ErrStat2, ErrMsg2, OnlySize ) ! Modules + 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 + CALL FAST_Packlintype( Re_Buf, Db_Buf, Int_Buf, InData%Glue, ErrStat2, ErrMsg2, OnlySize ) ! Glue + 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 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Azimuth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WindSpeed + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FAST_PackLinFileType + + SUBROUTINE FAST_UnPackLinFileType( 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(FAST_LinFileType), 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 = 'FAST_UnPackLinFileType' + ! 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%Modules,1) + i1_u = UBOUND(OutData%Modules,1) + DO i1 = LBOUND(OutData%Modules,1), UBOUND(OutData%Modules,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 FAST_Unpackmodlintype( Re_Buf, Db_Buf, Int_Buf, OutData%Modules(i1), ErrStat2, ErrMsg2 ) ! Modules + 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 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 FAST_Unpacklintype( Re_Buf, Db_Buf, Int_Buf, OutData%Glue, ErrStat2, ErrMsg2 ) ! Glue + 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%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Azimuth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FAST_UnPackLinFileType + + SUBROUTINE FAST_CopyMiscLinType( SrcMiscLinTypeData, DstMiscLinTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_MiscLinType), INTENT(IN) :: SrcMiscLinTypeData + TYPE(FAST_MiscLinType), INTENT(INOUT) :: DstMiscLinTypeData + 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 = 'FAST_CopyMiscLinType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscLinTypeData%LinTimes)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%LinTimes,1) + i1_u = UBOUND(SrcMiscLinTypeData%LinTimes,1) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%LinTimes)) THEN + ALLOCATE(DstMiscLinTypeData%LinTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%LinTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%LinTimes = SrcMiscLinTypeData%LinTimes +ENDIF + DstMiscLinTypeData%CopyOP_CtrlCode = SrcMiscLinTypeData%CopyOP_CtrlCode +IF (ALLOCATED(SrcMiscLinTypeData%AzimTarget)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%AzimTarget,1) + i1_u = UBOUND(SrcMiscLinTypeData%AzimTarget,1) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%AzimTarget)) THEN + ALLOCATE(DstMiscLinTypeData%AzimTarget(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%AzimTarget.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%AzimTarget = SrcMiscLinTypeData%AzimTarget +ENDIF + DstMiscLinTypeData%IsConverged = SrcMiscLinTypeData%IsConverged + DstMiscLinTypeData%FoundSteady = SrcMiscLinTypeData%FoundSteady + DstMiscLinTypeData%n_rot = SrcMiscLinTypeData%n_rot + DstMiscLinTypeData%AzimIndx = SrcMiscLinTypeData%AzimIndx + DstMiscLinTypeData%NextLinTimeIndx = SrcMiscLinTypeData%NextLinTimeIndx +IF (ALLOCATED(SrcMiscLinTypeData%Psi)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%Psi,1) + i1_u = UBOUND(SrcMiscLinTypeData%Psi,1) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%Psi)) THEN + ALLOCATE(DstMiscLinTypeData%Psi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%Psi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%Psi = SrcMiscLinTypeData%Psi +ENDIF +IF (ALLOCATED(SrcMiscLinTypeData%y_interp)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%y_interp,1) + i1_u = UBOUND(SrcMiscLinTypeData%y_interp,1) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%y_interp)) THEN + ALLOCATE(DstMiscLinTypeData%y_interp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%y_interp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%y_interp = SrcMiscLinTypeData%y_interp +ENDIF +IF (ALLOCATED(SrcMiscLinTypeData%y_ref)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%y_ref,1) + i1_u = UBOUND(SrcMiscLinTypeData%y_ref,1) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%y_ref)) THEN + ALLOCATE(DstMiscLinTypeData%y_ref(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%y_ref.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%y_ref = SrcMiscLinTypeData%y_ref +ENDIF +IF (ALLOCATED(SrcMiscLinTypeData%Y_prevRot)) THEN + i1_l = LBOUND(SrcMiscLinTypeData%Y_prevRot,1) + i1_u = UBOUND(SrcMiscLinTypeData%Y_prevRot,1) + i2_l = LBOUND(SrcMiscLinTypeData%Y_prevRot,2) + i2_u = UBOUND(SrcMiscLinTypeData%Y_prevRot,2) + IF (.NOT. ALLOCATED(DstMiscLinTypeData%Y_prevRot)) THEN + ALLOCATE(DstMiscLinTypeData%Y_prevRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscLinTypeData%Y_prevRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscLinTypeData%Y_prevRot = SrcMiscLinTypeData%Y_prevRot +ENDIF + END SUBROUTINE FAST_CopyMiscLinType + + SUBROUTINE FAST_DestroyMiscLinType( MiscLinTypeData, ErrStat, ErrMsg ) + TYPE(FAST_MiscLinType), INTENT(INOUT) :: MiscLinTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyMiscLinType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscLinTypeData%LinTimes)) THEN + DEALLOCATE(MiscLinTypeData%LinTimes) +ENDIF +IF (ALLOCATED(MiscLinTypeData%AzimTarget)) THEN + DEALLOCATE(MiscLinTypeData%AzimTarget) +ENDIF +IF (ALLOCATED(MiscLinTypeData%Psi)) THEN + DEALLOCATE(MiscLinTypeData%Psi) +ENDIF +IF (ALLOCATED(MiscLinTypeData%y_interp)) THEN + DEALLOCATE(MiscLinTypeData%y_interp) +ENDIF +IF (ALLOCATED(MiscLinTypeData%y_ref)) THEN + DEALLOCATE(MiscLinTypeData%y_ref) +ENDIF +IF (ALLOCATED(MiscLinTypeData%Y_prevRot)) THEN + DEALLOCATE(MiscLinTypeData%Y_prevRot) +ENDIF + END SUBROUTINE FAST_DestroyMiscLinType + + SUBROUTINE FAST_PackMiscLinType( 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(FAST_MiscLinType), 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 = 'FAST_PackMiscLinType' + ! 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 ! LinTimes allocated yes/no + IF ( ALLOCATED(InData%LinTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%LinTimes) ! LinTimes + END IF + Int_BufSz = Int_BufSz + 1 ! CopyOP_CtrlCode + Int_BufSz = Int_BufSz + 1 ! AzimTarget allocated yes/no + IF ( ALLOCATED(InData%AzimTarget) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AzimTarget upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%AzimTarget) ! AzimTarget + END IF + Int_BufSz = Int_BufSz + 1 ! IsConverged + Int_BufSz = Int_BufSz + 1 ! FoundSteady + Int_BufSz = Int_BufSz + 1 ! n_rot + Int_BufSz = Int_BufSz + 1 ! AzimIndx + Int_BufSz = Int_BufSz + 1 ! NextLinTimeIndx + Int_BufSz = Int_BufSz + 1 ! Psi allocated yes/no + IF ( ALLOCATED(InData%Psi) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Psi upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Psi) ! Psi + END IF + Int_BufSz = Int_BufSz + 1 ! y_interp allocated yes/no + IF ( ALLOCATED(InData%y_interp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y_interp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%y_interp) ! y_interp + END IF + Int_BufSz = Int_BufSz + 1 ! y_ref allocated yes/no + IF ( ALLOCATED(InData%y_ref) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y_ref upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%y_ref) ! y_ref + END IF + Int_BufSz = Int_BufSz + 1 ! Y_prevRot allocated yes/no + IF ( ALLOCATED(InData%Y_prevRot) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Y_prevRot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Y_prevRot) ! Y_prevRot + 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%LinTimes) ) 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%LinTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinTimes,1), UBOUND(InData%LinTimes,1) + DbKiBuf(Db_Xferred) = InData%LinTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%CopyOP_CtrlCode + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AzimTarget) ) 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%AzimTarget,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AzimTarget,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AzimTarget,1), UBOUND(InData%AzimTarget,1) + DbKiBuf(Db_Xferred) = InData%AzimTarget(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsConverged, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FoundSteady, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%n_rot + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%AzimIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NextLinTimeIndx + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Psi) ) 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%Psi,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Psi,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Psi,1), UBOUND(InData%Psi,1) + DbKiBuf(Db_Xferred) = InData%Psi(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%y_interp) ) 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%y_interp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y_interp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y_interp,1), UBOUND(InData%y_interp,1) + ReKiBuf(Re_Xferred) = InData%y_interp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%y_ref) ) 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%y_ref,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y_ref,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y_ref,1), UBOUND(InData%y_ref,1) + ReKiBuf(Re_Xferred) = InData%y_ref(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Y_prevRot) ) 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%Y_prevRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y_prevRot,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Y_prevRot,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Y_prevRot,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Y_prevRot,2), UBOUND(InData%Y_prevRot,2) + DO i1 = LBOUND(InData%Y_prevRot,1), UBOUND(InData%Y_prevRot,1) + ReKiBuf(Re_Xferred) = InData%Y_prevRot(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_PackMiscLinType + + SUBROUTINE FAST_UnPackMiscLinType( 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(FAST_MiscLinType), 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 = 'FAST_UnPackMiscLinType' + ! 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 ! LinTimes 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%LinTimes)) DEALLOCATE(OutData%LinTimes) + ALLOCATE(OutData%LinTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinTimes,1), UBOUND(OutData%LinTimes,1) + OutData%LinTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%CopyOP_CtrlCode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AzimTarget 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%AzimTarget)) DEALLOCATE(OutData%AzimTarget) + ALLOCATE(OutData%AzimTarget(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AzimTarget.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AzimTarget,1), UBOUND(OutData%AzimTarget,1) + OutData%AzimTarget(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%IsConverged = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsConverged) + Int_Xferred = Int_Xferred + 1 + OutData%FoundSteady = TRANSFER(IntKiBuf(Int_Xferred), OutData%FoundSteady) + Int_Xferred = Int_Xferred + 1 + OutData%n_rot = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%AzimIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NextLinTimeIndx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Psi 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%Psi)) DEALLOCATE(OutData%Psi) + ALLOCATE(OutData%Psi(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Psi.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Psi,1), UBOUND(OutData%Psi,1) + OutData%Psi(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y_interp 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%y_interp)) DEALLOCATE(OutData%y_interp) + ALLOCATE(OutData%y_interp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y_interp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y_interp,1), UBOUND(OutData%y_interp,1) + OutData%y_interp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y_ref 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%y_ref)) DEALLOCATE(OutData%y_ref) + ALLOCATE(OutData%y_ref(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y_ref.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y_ref,1), UBOUND(OutData%y_ref,1) + OutData%y_ref(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Y_prevRot 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%Y_prevRot)) DEALLOCATE(OutData%Y_prevRot) + ALLOCATE(OutData%Y_prevRot(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Y_prevRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Y_prevRot,2), UBOUND(OutData%Y_prevRot,2) + DO i1 = LBOUND(OutData%Y_prevRot,1), UBOUND(OutData%Y_prevRot,1) + OutData%Y_prevRot(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_UnPackMiscLinType + + SUBROUTINE FAST_CopyOutputFileType( SrcOutputFileTypeData, DstOutputFileTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_OutputFileType), INTENT(INOUT) :: SrcOutputFileTypeData + TYPE(FAST_OutputFileType), INTENT(INOUT) :: DstOutputFileTypeData + 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 = 'FAST_CopyOutputFileType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputFileTypeData%TimeData)) THEN + i1_l = LBOUND(SrcOutputFileTypeData%TimeData,1) + i1_u = UBOUND(SrcOutputFileTypeData%TimeData,1) + IF (.NOT. ALLOCATED(DstOutputFileTypeData%TimeData)) THEN + ALLOCATE(DstOutputFileTypeData%TimeData(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputFileTypeData%TimeData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputFileTypeData%TimeData = SrcOutputFileTypeData%TimeData +ENDIF +IF (ALLOCATED(SrcOutputFileTypeData%AllOutData)) THEN + i1_l = LBOUND(SrcOutputFileTypeData%AllOutData,1) + i1_u = UBOUND(SrcOutputFileTypeData%AllOutData,1) + i2_l = LBOUND(SrcOutputFileTypeData%AllOutData,2) + i2_u = UBOUND(SrcOutputFileTypeData%AllOutData,2) + IF (.NOT. ALLOCATED(DstOutputFileTypeData%AllOutData)) THEN + ALLOCATE(DstOutputFileTypeData%AllOutData(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputFileTypeData%AllOutData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputFileTypeData%AllOutData = SrcOutputFileTypeData%AllOutData +ENDIF + DstOutputFileTypeData%n_Out = SrcOutputFileTypeData%n_Out + DstOutputFileTypeData%NOutSteps = SrcOutputFileTypeData%NOutSteps + DstOutputFileTypeData%numOuts = SrcOutputFileTypeData%numOuts + DstOutputFileTypeData%UnOu = SrcOutputFileTypeData%UnOu + DstOutputFileTypeData%UnSum = SrcOutputFileTypeData%UnSum + DstOutputFileTypeData%UnGra = SrcOutputFileTypeData%UnGra + DstOutputFileTypeData%FileDescLines = SrcOutputFileTypeData%FileDescLines +IF (ALLOCATED(SrcOutputFileTypeData%ChannelNames)) THEN + i1_l = LBOUND(SrcOutputFileTypeData%ChannelNames,1) + i1_u = UBOUND(SrcOutputFileTypeData%ChannelNames,1) + IF (.NOT. ALLOCATED(DstOutputFileTypeData%ChannelNames)) THEN + ALLOCATE(DstOutputFileTypeData%ChannelNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputFileTypeData%ChannelNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputFileTypeData%ChannelNames = SrcOutputFileTypeData%ChannelNames +ENDIF +IF (ALLOCATED(SrcOutputFileTypeData%ChannelUnits)) THEN + i1_l = LBOUND(SrcOutputFileTypeData%ChannelUnits,1) + i1_u = UBOUND(SrcOutputFileTypeData%ChannelUnits,1) + IF (.NOT. ALLOCATED(DstOutputFileTypeData%ChannelUnits)) THEN + ALLOCATE(DstOutputFileTypeData%ChannelUnits(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputFileTypeData%ChannelUnits.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputFileTypeData%ChannelUnits = SrcOutputFileTypeData%ChannelUnits +ENDIF + DO i1 = LBOUND(SrcOutputFileTypeData%Module_Ver,1), UBOUND(SrcOutputFileTypeData%Module_Ver,1) + CALL NWTC_Library_Copyprogdesc( SrcOutputFileTypeData%Module_Ver(i1), DstOutputFileTypeData%Module_Ver(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DstOutputFileTypeData%Module_Abrev = SrcOutputFileTypeData%Module_Abrev + DstOutputFileTypeData%WriteThisStep = SrcOutputFileTypeData%WriteThisStep + DstOutputFileTypeData%VTK_count = SrcOutputFileTypeData%VTK_count + DstOutputFileTypeData%VTK_LastWaveIndx = SrcOutputFileTypeData%VTK_LastWaveIndx + CALL FAST_Copylinfiletype( SrcOutputFileTypeData%Lin, DstOutputFileTypeData%Lin, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstOutputFileTypeData%ActualChanLen = SrcOutputFileTypeData%ActualChanLen + DstOutputFileTypeData%OutFmt_a = SrcOutputFileTypeData%OutFmt_a + CALL FAST_Copylinstatesave( SrcOutputFileTypeData%op, DstOutputFileTypeData%op, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyOutputFileType + + SUBROUTINE FAST_DestroyOutputFileType( OutputFileTypeData, ErrStat, ErrMsg ) + TYPE(FAST_OutputFileType), INTENT(INOUT) :: OutputFileTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyOutputFileType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputFileTypeData%TimeData)) THEN + DEALLOCATE(OutputFileTypeData%TimeData) +ENDIF +IF (ALLOCATED(OutputFileTypeData%AllOutData)) THEN + DEALLOCATE(OutputFileTypeData%AllOutData) +ENDIF +IF (ALLOCATED(OutputFileTypeData%ChannelNames)) THEN + DEALLOCATE(OutputFileTypeData%ChannelNames) +ENDIF +IF (ALLOCATED(OutputFileTypeData%ChannelUnits)) THEN + DEALLOCATE(OutputFileTypeData%ChannelUnits) +ENDIF +DO i1 = LBOUND(OutputFileTypeData%Module_Ver,1), UBOUND(OutputFileTypeData%Module_Ver,1) + CALL NWTC_Library_Destroyprogdesc( OutputFileTypeData%Module_Ver(i1), ErrStat, ErrMsg ) +ENDDO + CALL FAST_Destroylinfiletype( OutputFileTypeData%Lin, ErrStat, ErrMsg ) + CALL FAST_Destroylinstatesave( OutputFileTypeData%op, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyOutputFileType + + SUBROUTINE FAST_PackOutputFileType( 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(FAST_OutputFileType), 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 = 'FAST_PackOutputFileType' + ! 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 ! TimeData allocated yes/no + IF ( ALLOCATED(InData%TimeData) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TimeData upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%TimeData) ! TimeData + END IF + Int_BufSz = Int_BufSz + 1 ! AllOutData allocated yes/no + IF ( ALLOCATED(InData%AllOutData) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AllOutData upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AllOutData) ! AllOutData + END IF + Int_BufSz = Int_BufSz + 1 ! n_Out + Int_BufSz = Int_BufSz + 1 ! NOutSteps + Int_BufSz = Int_BufSz + SIZE(InData%numOuts) ! numOuts + Int_BufSz = Int_BufSz + 1 ! UnOu + Int_BufSz = Int_BufSz + 1 ! UnSum + Int_BufSz = Int_BufSz + 1 ! UnGra + Int_BufSz = Int_BufSz + SIZE(InData%FileDescLines)*LEN(InData%FileDescLines) ! FileDescLines + Int_BufSz = Int_BufSz + 1 ! ChannelNames allocated yes/no + IF ( ALLOCATED(InData%ChannelNames) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ChannelNames upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ChannelNames)*LEN(InData%ChannelNames) ! ChannelNames + END IF + Int_BufSz = Int_BufSz + 1 ! ChannelUnits allocated yes/no + IF ( ALLOCATED(InData%ChannelUnits) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ChannelUnits upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ChannelUnits)*LEN(InData%ChannelUnits) ! ChannelUnits + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%Module_Ver,1), UBOUND(InData%Module_Ver,1) + Int_BufSz = Int_BufSz + 3 ! Module_Ver: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Module_Ver(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Module_Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Module_Ver + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Module_Ver + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Module_Ver + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + SIZE(InData%Module_Abrev)*LEN(InData%Module_Abrev) ! Module_Abrev + Int_BufSz = Int_BufSz + 1 ! WriteThisStep + Int_BufSz = Int_BufSz + 1 ! VTK_count + Int_BufSz = Int_BufSz + 1 ! VTK_LastWaveIndx + Int_BufSz = Int_BufSz + 3 ! Lin: size of buffers for each call to pack subtype + CALL FAST_Packlinfiletype( Re_Buf, Db_Buf, Int_Buf, InData%Lin, ErrStat2, ErrMsg2, .TRUE. ) ! Lin + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Lin + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Lin + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Lin + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! ActualChanLen + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt_a) ! OutFmt_a + Int_BufSz = Int_BufSz + 3 ! op: size of buffers for each call to pack subtype + CALL FAST_Packlinstatesave( Re_Buf, Db_Buf, Int_Buf, InData%op, ErrStat2, ErrMsg2, .TRUE. ) ! op + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! op + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! op + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! op + 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 + + IF ( .NOT. ALLOCATED(InData%TimeData) ) 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%TimeData,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TimeData,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TimeData,1), UBOUND(InData%TimeData,1) + DbKiBuf(Db_Xferred) = InData%TimeData(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AllOutData) ) 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%AllOutData,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOutData,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AllOutData,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOutData,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AllOutData,2), UBOUND(InData%AllOutData,2) + DO i1 = LBOUND(InData%AllOutData,1), UBOUND(InData%AllOutData,1) + ReKiBuf(Re_Xferred) = InData%AllOutData(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%n_Out + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NOutSteps + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%numOuts,1), UBOUND(InData%numOuts,1) + IntKiBuf(Int_Xferred) = InData%numOuts(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%UnOu + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnSum + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnGra + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%FileDescLines,1), UBOUND(InData%FileDescLines,1) + DO I = 1, LEN(InData%FileDescLines) + IntKiBuf(Int_Xferred) = ICHAR(InData%FileDescLines(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IF ( .NOT. ALLOCATED(InData%ChannelNames) ) 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%ChannelNames,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChannelNames,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ChannelNames,1), UBOUND(InData%ChannelNames,1) + DO I = 1, LEN(InData%ChannelNames) + IntKiBuf(Int_Xferred) = ICHAR(InData%ChannelNames(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ChannelUnits) ) 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%ChannelUnits,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ChannelUnits,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ChannelUnits,1), UBOUND(InData%ChannelUnits,1) + DO I = 1, LEN(InData%ChannelUnits) + IntKiBuf(Int_Xferred) = ICHAR(InData%ChannelUnits(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO i1 = LBOUND(InData%Module_Ver,1), UBOUND(InData%Module_Ver,1) + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Module_Ver(i1), ErrStat2, ErrMsg2, OnlySize ) ! Module_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 DO + DO i1 = LBOUND(InData%Module_Abrev,1), UBOUND(InData%Module_Abrev,1) + DO I = 1, LEN(InData%Module_Abrev) + IntKiBuf(Int_Xferred) = ICHAR(InData%Module_Abrev(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%WriteThisStep, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTK_count + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VTK_LastWaveIndx + Int_Xferred = Int_Xferred + 1 + CALL FAST_Packlinfiletype( Re_Buf, Db_Buf, Int_Buf, InData%Lin, ErrStat2, ErrMsg2, OnlySize ) ! Lin + 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%ActualChanLen + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt_a) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt_a(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + CALL FAST_Packlinstatesave( Re_Buf, Db_Buf, Int_Buf, InData%op, ErrStat2, ErrMsg2, OnlySize ) ! op + 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 FAST_PackOutputFileType + + SUBROUTINE FAST_UnPackOutputFileType( 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(FAST_OutputFileType), 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 = 'FAST_UnPackOutputFileType' + ! 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 ! TimeData 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%TimeData)) DEALLOCATE(OutData%TimeData) + ALLOCATE(OutData%TimeData(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TimeData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TimeData,1), UBOUND(OutData%TimeData,1) + OutData%TimeData(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOutData 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%AllOutData)) DEALLOCATE(OutData%AllOutData) + ALLOCATE(OutData%AllOutData(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOutData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AllOutData,2), UBOUND(OutData%AllOutData,2) + DO i1 = LBOUND(OutData%AllOutData,1), UBOUND(OutData%AllOutData,1) + OutData%AllOutData(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%n_Out = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NOutSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%numOuts,1) + i1_u = UBOUND(OutData%numOuts,1) + DO i1 = LBOUND(OutData%numOuts,1), UBOUND(OutData%numOuts,1) + OutData%numOuts(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%UnOu = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnSum = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnGra = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%FileDescLines,1) + i1_u = UBOUND(OutData%FileDescLines,1) + DO i1 = LBOUND(OutData%FileDescLines,1), UBOUND(OutData%FileDescLines,1) + DO I = 1, LEN(OutData%FileDescLines) + OutData%FileDescLines(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChannelNames 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%ChannelNames)) DEALLOCATE(OutData%ChannelNames) + ALLOCATE(OutData%ChannelNames(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ChannelNames.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ChannelNames,1), UBOUND(OutData%ChannelNames,1) + DO I = 1, LEN(OutData%ChannelNames) + OutData%ChannelNames(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ChannelUnits 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%ChannelUnits)) DEALLOCATE(OutData%ChannelUnits) + ALLOCATE(OutData%ChannelUnits(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ChannelUnits.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ChannelUnits,1), UBOUND(OutData%ChannelUnits,1) + DO I = 1, LEN(OutData%ChannelUnits) + OutData%ChannelUnits(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + i1_l = LBOUND(OutData%Module_Ver,1) + i1_u = UBOUND(OutData%Module_Ver,1) + DO i1 = LBOUND(OutData%Module_Ver,1), UBOUND(OutData%Module_Ver,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%Module_Ver(i1), ErrStat2, ErrMsg2 ) ! Module_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 DO + i1_l = LBOUND(OutData%Module_Abrev,1) + i1_u = UBOUND(OutData%Module_Abrev,1) + DO i1 = LBOUND(OutData%Module_Abrev,1), UBOUND(OutData%Module_Abrev,1) + DO I = 1, LEN(OutData%Module_Abrev) + OutData%Module_Abrev(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%WriteThisStep = TRANSFER(IntKiBuf(Int_Xferred), OutData%WriteThisStep) + Int_Xferred = Int_Xferred + 1 + OutData%VTK_count = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VTK_LastWaveIndx = 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 FAST_Unpacklinfiletype( Re_Buf, Db_Buf, Int_Buf, OutData%Lin, ErrStat2, ErrMsg2 ) ! Lin + 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%ActualChanLen = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt_a) + OutData%OutFmt_a(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 FAST_Unpacklinstatesave( Re_Buf, Db_Buf, Int_Buf, OutData%op, ErrStat2, ErrMsg2 ) ! op + 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 FAST_UnPackOutputFileType + + SUBROUTINE FAST_CopyIceDyn_Data( SrcIceDyn_DataData, DstIceDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceDyn_Data), INTENT(INOUT) :: SrcIceDyn_DataData + TYPE(IceDyn_Data), INTENT(INOUT) :: DstIceDyn_DataData + 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 = 'FAST_CopyIceDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcIceDyn_DataData%x)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%x,1) + i1_u = UBOUND(SrcIceDyn_DataData%x,1) + i2_l = LBOUND(SrcIceDyn_DataData%x,2) + i2_u = UBOUND(SrcIceDyn_DataData%x,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%x)) THEN + ALLOCATE(DstIceDyn_DataData%x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcIceDyn_DataData%x,2), UBOUND(SrcIceDyn_DataData%x,2) + DO i1 = LBOUND(SrcIceDyn_DataData%x,1), UBOUND(SrcIceDyn_DataData%x,1) + CALL IceD_CopyContState( SrcIceDyn_DataData%x(i1,i2), DstIceDyn_DataData%x(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%xd)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%xd,1) + i1_u = UBOUND(SrcIceDyn_DataData%xd,1) + i2_l = LBOUND(SrcIceDyn_DataData%xd,2) + i2_u = UBOUND(SrcIceDyn_DataData%xd,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%xd)) THEN + ALLOCATE(DstIceDyn_DataData%xd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcIceDyn_DataData%xd,2), UBOUND(SrcIceDyn_DataData%xd,2) + DO i1 = LBOUND(SrcIceDyn_DataData%xd,1), UBOUND(SrcIceDyn_DataData%xd,1) + CALL IceD_CopyDiscState( SrcIceDyn_DataData%xd(i1,i2), DstIceDyn_DataData%xd(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%z)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%z,1) + i1_u = UBOUND(SrcIceDyn_DataData%z,1) + i2_l = LBOUND(SrcIceDyn_DataData%z,2) + i2_u = UBOUND(SrcIceDyn_DataData%z,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%z)) THEN + ALLOCATE(DstIceDyn_DataData%z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcIceDyn_DataData%z,2), UBOUND(SrcIceDyn_DataData%z,2) + DO i1 = LBOUND(SrcIceDyn_DataData%z,1), UBOUND(SrcIceDyn_DataData%z,1) + CALL IceD_CopyConstrState( SrcIceDyn_DataData%z(i1,i2), DstIceDyn_DataData%z(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%OtherSt)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%OtherSt,1) + i1_u = UBOUND(SrcIceDyn_DataData%OtherSt,1) + i2_l = LBOUND(SrcIceDyn_DataData%OtherSt,2) + i2_u = UBOUND(SrcIceDyn_DataData%OtherSt,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%OtherSt)) THEN + ALLOCATE(DstIceDyn_DataData%OtherSt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%OtherSt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcIceDyn_DataData%OtherSt,2), UBOUND(SrcIceDyn_DataData%OtherSt,2) + DO i1 = LBOUND(SrcIceDyn_DataData%OtherSt,1), UBOUND(SrcIceDyn_DataData%OtherSt,1) + CALL IceD_CopyOtherState( SrcIceDyn_DataData%OtherSt(i1,i2), DstIceDyn_DataData%OtherSt(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%p)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%p,1) + i1_u = UBOUND(SrcIceDyn_DataData%p,1) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%p)) THEN + ALLOCATE(DstIceDyn_DataData%p(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcIceDyn_DataData%p,1), UBOUND(SrcIceDyn_DataData%p,1) + CALL IceD_CopyParam( SrcIceDyn_DataData%p(i1), DstIceDyn_DataData%p(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%u)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%u,1) + i1_u = UBOUND(SrcIceDyn_DataData%u,1) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%u)) THEN + ALLOCATE(DstIceDyn_DataData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcIceDyn_DataData%u,1), UBOUND(SrcIceDyn_DataData%u,1) + CALL IceD_CopyInput( SrcIceDyn_DataData%u(i1), DstIceDyn_DataData%u(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%y)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%y,1) + i1_u = UBOUND(SrcIceDyn_DataData%y,1) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%y)) THEN + ALLOCATE(DstIceDyn_DataData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcIceDyn_DataData%y,1), UBOUND(SrcIceDyn_DataData%y,1) + CALL IceD_CopyOutput( SrcIceDyn_DataData%y(i1), DstIceDyn_DataData%y(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%m)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%m,1) + i1_u = UBOUND(SrcIceDyn_DataData%m,1) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%m)) THEN + ALLOCATE(DstIceDyn_DataData%m(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcIceDyn_DataData%m,1), UBOUND(SrcIceDyn_DataData%m,1) + CALL IceD_CopyMisc( SrcIceDyn_DataData%m(i1), DstIceDyn_DataData%m(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%Input,1) + i1_u = UBOUND(SrcIceDyn_DataData%Input,1) + i2_l = LBOUND(SrcIceDyn_DataData%Input,2) + i2_u = UBOUND(SrcIceDyn_DataData%Input,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%Input)) THEN + ALLOCATE(DstIceDyn_DataData%Input(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcIceDyn_DataData%Input,2), UBOUND(SrcIceDyn_DataData%Input,2) + DO i1 = LBOUND(SrcIceDyn_DataData%Input,1), UBOUND(SrcIceDyn_DataData%Input,1) + CALL IceD_CopyInput( SrcIceDyn_DataData%Input(i1,i2), DstIceDyn_DataData%Input(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcIceDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcIceDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcIceDyn_DataData%InputTimes,1) + i2_l = LBOUND(SrcIceDyn_DataData%InputTimes,2) + i2_u = UBOUND(SrcIceDyn_DataData%InputTimes,2) + IF (.NOT. ALLOCATED(DstIceDyn_DataData%InputTimes)) THEN + ALLOCATE(DstIceDyn_DataData%InputTimes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstIceDyn_DataData%InputTimes = SrcIceDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyIceDyn_Data + + SUBROUTINE FAST_DestroyIceDyn_Data( IceDyn_DataData, ErrStat, ErrMsg ) + TYPE(IceDyn_Data), INTENT(INOUT) :: IceDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyIceDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(IceDyn_DataData%x)) THEN +DO i2 = LBOUND(IceDyn_DataData%x,2), UBOUND(IceDyn_DataData%x,2) +DO i1 = LBOUND(IceDyn_DataData%x,1), UBOUND(IceDyn_DataData%x,1) + CALL IceD_DestroyContState( IceDyn_DataData%x(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(IceDyn_DataData%x) +ENDIF +IF (ALLOCATED(IceDyn_DataData%xd)) THEN +DO i2 = LBOUND(IceDyn_DataData%xd,2), UBOUND(IceDyn_DataData%xd,2) +DO i1 = LBOUND(IceDyn_DataData%xd,1), UBOUND(IceDyn_DataData%xd,1) + CALL IceD_DestroyDiscState( IceDyn_DataData%xd(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(IceDyn_DataData%xd) +ENDIF +IF (ALLOCATED(IceDyn_DataData%z)) THEN +DO i2 = LBOUND(IceDyn_DataData%z,2), UBOUND(IceDyn_DataData%z,2) +DO i1 = LBOUND(IceDyn_DataData%z,1), UBOUND(IceDyn_DataData%z,1) + CALL IceD_DestroyConstrState( IceDyn_DataData%z(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(IceDyn_DataData%z) +ENDIF +IF (ALLOCATED(IceDyn_DataData%OtherSt)) THEN +DO i2 = LBOUND(IceDyn_DataData%OtherSt,2), UBOUND(IceDyn_DataData%OtherSt,2) +DO i1 = LBOUND(IceDyn_DataData%OtherSt,1), UBOUND(IceDyn_DataData%OtherSt,1) + CALL IceD_DestroyOtherState( IceDyn_DataData%OtherSt(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(IceDyn_DataData%OtherSt) +ENDIF +IF (ALLOCATED(IceDyn_DataData%p)) THEN +DO i1 = LBOUND(IceDyn_DataData%p,1), UBOUND(IceDyn_DataData%p,1) + CALL IceD_DestroyParam( IceDyn_DataData%p(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(IceDyn_DataData%p) +ENDIF +IF (ALLOCATED(IceDyn_DataData%u)) THEN +DO i1 = LBOUND(IceDyn_DataData%u,1), UBOUND(IceDyn_DataData%u,1) + CALL IceD_DestroyInput( IceDyn_DataData%u(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(IceDyn_DataData%u) +ENDIF +IF (ALLOCATED(IceDyn_DataData%y)) THEN +DO i1 = LBOUND(IceDyn_DataData%y,1), UBOUND(IceDyn_DataData%y,1) + CALL IceD_DestroyOutput( IceDyn_DataData%y(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(IceDyn_DataData%y) +ENDIF +IF (ALLOCATED(IceDyn_DataData%m)) THEN +DO i1 = LBOUND(IceDyn_DataData%m,1), UBOUND(IceDyn_DataData%m,1) + CALL IceD_DestroyMisc( IceDyn_DataData%m(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(IceDyn_DataData%m) +ENDIF +IF (ALLOCATED(IceDyn_DataData%Input)) THEN +DO i2 = LBOUND(IceDyn_DataData%Input,2), UBOUND(IceDyn_DataData%Input,2) +DO i1 = LBOUND(IceDyn_DataData%Input,1), UBOUND(IceDyn_DataData%Input,1) + CALL IceD_DestroyInput( IceDyn_DataData%Input(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(IceDyn_DataData%Input) +ENDIF +IF (ALLOCATED(IceDyn_DataData%InputTimes)) THEN + DEALLOCATE(IceDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyIceDyn_Data + + SUBROUTINE FAST_PackIceDyn_Data( 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(IceDyn_Data), 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 = 'FAST_PackIceDyn_Data' + ! 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 ! x allocated yes/no + IF ( ALLOCATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! x upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%x,2), UBOUND(InData%x,2) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd allocated yes/no + IF ( ALLOCATED(InData%xd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! xd upper/lower bounds for each dimension + DO i2 = LBOUND(InData%xd,2), UBOUND(InData%xd,2) + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL IceD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z allocated yes/no + IF ( ALLOCATED(InData%z) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! z upper/lower bounds for each dimension + DO i2 = LBOUND(InData%z,2), UBOUND(InData%z,2) + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL IceD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt allocated yes/no + IF ( ALLOCATED(InData%OtherSt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OtherSt upper/lower bounds for each dimension + DO i2 = LBOUND(InData%OtherSt,2), UBOUND(InData%OtherSt,2) + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL IceD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! p allocated yes/no + IF ( ALLOCATED(InData%p) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! p upper/lower bounds for each dimension + DO i1 = LBOUND(InData%p,1), UBOUND(InData%p,1) + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL IceD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p(i1), ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u allocated yes/no + IF ( ALLOCATED(InData%u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ALLOCATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL IceD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y(i1), ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! m allocated yes/no + IF ( ALLOCATED(InData%m) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m upper/lower bounds for each dimension + DO i1 = LBOUND(InData%m,1), UBOUND(InData%m,1) + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL IceD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m(i1), ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Input upper/lower bounds for each dimension + DO i2 = LBOUND(InData%Input,2), UBOUND(InData%Input,2) + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%x,2), UBOUND(InData%x,2) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + CALL IceD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%xd) ) 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%xd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%xd,2), UBOUND(InData%xd,2) + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL IceD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%z) ) 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%z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%z,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%z,2), UBOUND(InData%z,2) + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL IceD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%OtherSt) ) 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%OtherSt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OtherSt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OtherSt,2), UBOUND(InData%OtherSt,2) + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL IceD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%p) ) 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%p,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%p,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%p,1), UBOUND(InData%p,1) + CALL IceD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p(i1), ErrStat2, ErrMsg2, OnlySize ) ! p + 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%u) ) 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%u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, OnlySize ) ! u + 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%y) ) 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%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + CALL IceD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y(i1), ErrStat2, ErrMsg2, OnlySize ) ! y + 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%m) ) 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%m,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m,1), UBOUND(InData%m,1) + CALL IceD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m(i1), ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Input,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Input,2), UBOUND(InData%Input,2) + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL IceD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InputTimes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InputTimes,2), UBOUND(InData%InputTimes,2) + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_PackIceDyn_Data + + SUBROUTINE FAST_UnPackIceDyn_Data( 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(IceDyn_Data), 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 = 'FAST_UnPackIceDyn_Data' + ! 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 ! x 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%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%x,2), UBOUND(OutData%x,2) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 IceD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1,i2), ErrStat2, ErrMsg2 ) ! x + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd 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%xd)) DEALLOCATE(OutData%xd) + ALLOCATE(OutData%xd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%xd,2), UBOUND(OutData%xd,2) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 IceD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1,i2), ErrStat2, ErrMsg2 ) ! xd + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z 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%z)) DEALLOCATE(OutData%z) + ALLOCATE(OutData%z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%z,2), UBOUND(OutData%z,2) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 IceD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1,i2), ErrStat2, ErrMsg2 ) ! z + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt 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%OtherSt)) DEALLOCATE(OutData%OtherSt) + ALLOCATE(OutData%OtherSt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OtherSt,2), UBOUND(OutData%OtherSt,2) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 IceD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1,i2), ErrStat2, ErrMsg2 ) ! OtherSt + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! p 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%p)) DEALLOCATE(OutData%p) + ALLOCATE(OutData%p(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%p,1), UBOUND(OutData%p,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 IceD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p(i1), ErrStat2, ErrMsg2 ) ! p + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u 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%u)) DEALLOCATE(OutData%u) + ALLOCATE(OutData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u,1), UBOUND(OutData%u,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 IceD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u(i1), ErrStat2, ErrMsg2 ) ! u + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y 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%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,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 IceD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y(i1), ErrStat2, ErrMsg2 ) ! y + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m 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%m)) DEALLOCATE(OutData%m) + ALLOCATE(OutData%m(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m,1), UBOUND(OutData%m,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 IceD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m(i1), ErrStat2, ErrMsg2 ) ! m + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Input,2), UBOUND(OutData%Input,2) + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 IceD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1,i2), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InputTimes,2), UBOUND(OutData%InputTimes,2) + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_UnPackIceDyn_Data + + SUBROUTINE FAST_CopyBeamDyn_Data( SrcBeamDyn_DataData, DstBeamDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BeamDyn_Data), INTENT(INOUT) :: SrcBeamDyn_DataData + TYPE(BeamDyn_Data), INTENT(INOUT) :: DstBeamDyn_DataData + 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 = 'FAST_CopyBeamDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcBeamDyn_DataData%x)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%x,1) + i1_u = UBOUND(SrcBeamDyn_DataData%x,1) + i2_l = LBOUND(SrcBeamDyn_DataData%x,2) + i2_u = UBOUND(SrcBeamDyn_DataData%x,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%x)) THEN + ALLOCATE(DstBeamDyn_DataData%x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%x,2), UBOUND(SrcBeamDyn_DataData%x,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%x,1), UBOUND(SrcBeamDyn_DataData%x,1) + CALL BD_CopyContState( SrcBeamDyn_DataData%x(i1,i2), DstBeamDyn_DataData%x(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%xd)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%xd,1) + i1_u = UBOUND(SrcBeamDyn_DataData%xd,1) + i2_l = LBOUND(SrcBeamDyn_DataData%xd,2) + i2_u = UBOUND(SrcBeamDyn_DataData%xd,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%xd)) THEN + ALLOCATE(DstBeamDyn_DataData%xd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%xd,2), UBOUND(SrcBeamDyn_DataData%xd,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%xd,1), UBOUND(SrcBeamDyn_DataData%xd,1) + CALL BD_CopyDiscState( SrcBeamDyn_DataData%xd(i1,i2), DstBeamDyn_DataData%xd(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%z)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%z,1) + i1_u = UBOUND(SrcBeamDyn_DataData%z,1) + i2_l = LBOUND(SrcBeamDyn_DataData%z,2) + i2_u = UBOUND(SrcBeamDyn_DataData%z,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%z)) THEN + ALLOCATE(DstBeamDyn_DataData%z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%z,2), UBOUND(SrcBeamDyn_DataData%z,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%z,1), UBOUND(SrcBeamDyn_DataData%z,1) + CALL BD_CopyConstrState( SrcBeamDyn_DataData%z(i1,i2), DstBeamDyn_DataData%z(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%OtherSt)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%OtherSt,1) + i1_u = UBOUND(SrcBeamDyn_DataData%OtherSt,1) + i2_l = LBOUND(SrcBeamDyn_DataData%OtherSt,2) + i2_u = UBOUND(SrcBeamDyn_DataData%OtherSt,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%OtherSt)) THEN + ALLOCATE(DstBeamDyn_DataData%OtherSt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%OtherSt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%OtherSt,2), UBOUND(SrcBeamDyn_DataData%OtherSt,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%OtherSt,1), UBOUND(SrcBeamDyn_DataData%OtherSt,1) + CALL BD_CopyOtherState( SrcBeamDyn_DataData%OtherSt(i1,i2), DstBeamDyn_DataData%OtherSt(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%p)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%p,1) + i1_u = UBOUND(SrcBeamDyn_DataData%p,1) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%p)) THEN + ALLOCATE(DstBeamDyn_DataData%p(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBeamDyn_DataData%p,1), UBOUND(SrcBeamDyn_DataData%p,1) + CALL BD_CopyParam( SrcBeamDyn_DataData%p(i1), DstBeamDyn_DataData%p(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%u)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%u,1) + i1_u = UBOUND(SrcBeamDyn_DataData%u,1) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%u)) THEN + ALLOCATE(DstBeamDyn_DataData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBeamDyn_DataData%u,1), UBOUND(SrcBeamDyn_DataData%u,1) + CALL BD_CopyInput( SrcBeamDyn_DataData%u(i1), DstBeamDyn_DataData%u(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%y)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%y,1) + i1_u = UBOUND(SrcBeamDyn_DataData%y,1) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%y)) THEN + ALLOCATE(DstBeamDyn_DataData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBeamDyn_DataData%y,1), UBOUND(SrcBeamDyn_DataData%y,1) + CALL BD_CopyOutput( SrcBeamDyn_DataData%y(i1), DstBeamDyn_DataData%y(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%m)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%m,1) + i1_u = UBOUND(SrcBeamDyn_DataData%m,1) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%m)) THEN + ALLOCATE(DstBeamDyn_DataData%m(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBeamDyn_DataData%m,1), UBOUND(SrcBeamDyn_DataData%m,1) + CALL BD_CopyMisc( SrcBeamDyn_DataData%m(i1), DstBeamDyn_DataData%m(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%Output,1) + i1_u = UBOUND(SrcBeamDyn_DataData%Output,1) + i2_l = LBOUND(SrcBeamDyn_DataData%Output,2) + i2_u = UBOUND(SrcBeamDyn_DataData%Output,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%Output)) THEN + ALLOCATE(DstBeamDyn_DataData%Output(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%Output,2), UBOUND(SrcBeamDyn_DataData%Output,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%Output,1), UBOUND(SrcBeamDyn_DataData%Output,1) + CALL BD_CopyOutput( SrcBeamDyn_DataData%Output(i1,i2), DstBeamDyn_DataData%Output(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%y_interp)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%y_interp,1) + i1_u = UBOUND(SrcBeamDyn_DataData%y_interp,1) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%y_interp)) THEN + ALLOCATE(DstBeamDyn_DataData%y_interp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%y_interp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBeamDyn_DataData%y_interp,1), UBOUND(SrcBeamDyn_DataData%y_interp,1) + CALL BD_CopyOutput( SrcBeamDyn_DataData%y_interp(i1), DstBeamDyn_DataData%y_interp(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%Input,1) + i1_u = UBOUND(SrcBeamDyn_DataData%Input,1) + i2_l = LBOUND(SrcBeamDyn_DataData%Input,2) + i2_u = UBOUND(SrcBeamDyn_DataData%Input,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%Input)) THEN + ALLOCATE(DstBeamDyn_DataData%Input(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i2 = LBOUND(SrcBeamDyn_DataData%Input,2), UBOUND(SrcBeamDyn_DataData%Input,2) + DO i1 = LBOUND(SrcBeamDyn_DataData%Input,1), UBOUND(SrcBeamDyn_DataData%Input,1) + CALL BD_CopyInput( SrcBeamDyn_DataData%Input(i1,i2), DstBeamDyn_DataData%Input(i1,i2), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + ENDDO +ENDIF +IF (ALLOCATED(SrcBeamDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcBeamDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcBeamDyn_DataData%InputTimes,1) + i2_l = LBOUND(SrcBeamDyn_DataData%InputTimes,2) + i2_u = UBOUND(SrcBeamDyn_DataData%InputTimes,2) + IF (.NOT. ALLOCATED(DstBeamDyn_DataData%InputTimes)) THEN + ALLOCATE(DstBeamDyn_DataData%InputTimes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBeamDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBeamDyn_DataData%InputTimes = SrcBeamDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyBeamDyn_Data + + SUBROUTINE FAST_DestroyBeamDyn_Data( BeamDyn_DataData, ErrStat, ErrMsg ) + TYPE(BeamDyn_Data), INTENT(INOUT) :: BeamDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyBeamDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BeamDyn_DataData%x)) THEN +DO i2 = LBOUND(BeamDyn_DataData%x,2), UBOUND(BeamDyn_DataData%x,2) +DO i1 = LBOUND(BeamDyn_DataData%x,1), UBOUND(BeamDyn_DataData%x,1) + CALL BD_DestroyContState( BeamDyn_DataData%x(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%x) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%xd)) THEN +DO i2 = LBOUND(BeamDyn_DataData%xd,2), UBOUND(BeamDyn_DataData%xd,2) +DO i1 = LBOUND(BeamDyn_DataData%xd,1), UBOUND(BeamDyn_DataData%xd,1) + CALL BD_DestroyDiscState( BeamDyn_DataData%xd(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%xd) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%z)) THEN +DO i2 = LBOUND(BeamDyn_DataData%z,2), UBOUND(BeamDyn_DataData%z,2) +DO i1 = LBOUND(BeamDyn_DataData%z,1), UBOUND(BeamDyn_DataData%z,1) + CALL BD_DestroyConstrState( BeamDyn_DataData%z(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%z) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%OtherSt)) THEN +DO i2 = LBOUND(BeamDyn_DataData%OtherSt,2), UBOUND(BeamDyn_DataData%OtherSt,2) +DO i1 = LBOUND(BeamDyn_DataData%OtherSt,1), UBOUND(BeamDyn_DataData%OtherSt,1) + CALL BD_DestroyOtherState( BeamDyn_DataData%OtherSt(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%OtherSt) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%p)) THEN +DO i1 = LBOUND(BeamDyn_DataData%p,1), UBOUND(BeamDyn_DataData%p,1) + CALL BD_DestroyParam( BeamDyn_DataData%p(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BeamDyn_DataData%p) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%u)) THEN +DO i1 = LBOUND(BeamDyn_DataData%u,1), UBOUND(BeamDyn_DataData%u,1) + CALL BD_DestroyInput( BeamDyn_DataData%u(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BeamDyn_DataData%u) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%y)) THEN +DO i1 = LBOUND(BeamDyn_DataData%y,1), UBOUND(BeamDyn_DataData%y,1) + CALL BD_DestroyOutput( BeamDyn_DataData%y(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BeamDyn_DataData%y) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%m)) THEN +DO i1 = LBOUND(BeamDyn_DataData%m,1), UBOUND(BeamDyn_DataData%m,1) + CALL BD_DestroyMisc( BeamDyn_DataData%m(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BeamDyn_DataData%m) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%Output)) THEN +DO i2 = LBOUND(BeamDyn_DataData%Output,2), UBOUND(BeamDyn_DataData%Output,2) +DO i1 = LBOUND(BeamDyn_DataData%Output,1), UBOUND(BeamDyn_DataData%Output,1) + CALL BD_DestroyOutput( BeamDyn_DataData%Output(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%Output) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%y_interp)) THEN +DO i1 = LBOUND(BeamDyn_DataData%y_interp,1), UBOUND(BeamDyn_DataData%y_interp,1) + CALL BD_DestroyOutput( BeamDyn_DataData%y_interp(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BeamDyn_DataData%y_interp) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%Input)) THEN +DO i2 = LBOUND(BeamDyn_DataData%Input,2), UBOUND(BeamDyn_DataData%Input,2) +DO i1 = LBOUND(BeamDyn_DataData%Input,1), UBOUND(BeamDyn_DataData%Input,1) + CALL BD_DestroyInput( BeamDyn_DataData%Input(i1,i2), ErrStat, ErrMsg ) +ENDDO +ENDDO + DEALLOCATE(BeamDyn_DataData%Input) +ENDIF +IF (ALLOCATED(BeamDyn_DataData%InputTimes)) THEN + DEALLOCATE(BeamDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyBeamDyn_Data + + SUBROUTINE FAST_PackBeamDyn_Data( 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(BeamDyn_Data), 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 = 'FAST_PackBeamDyn_Data' + ! 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 ! x allocated yes/no + IF ( ALLOCATED(InData%x) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! x upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i2 = LBOUND(InData%x,2), UBOUND(InData%x,2) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL BD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! xd allocated yes/no + IF ( ALLOCATED(InData%xd) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! xd upper/lower bounds for each dimension + DO i2 = LBOUND(InData%xd,2), UBOUND(InData%xd,2) + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL BD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! z allocated yes/no + IF ( ALLOCATED(InData%z) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! z upper/lower bounds for each dimension + DO i2 = LBOUND(InData%z,2), UBOUND(InData%z,2) + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL BD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OtherSt allocated yes/no + IF ( ALLOCATED(InData%OtherSt) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! OtherSt upper/lower bounds for each dimension + DO i2 = LBOUND(InData%OtherSt,2), UBOUND(InData%OtherSt,2) + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL BD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! p allocated yes/no + IF ( ALLOCATED(InData%p) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! p upper/lower bounds for each dimension + DO i1 = LBOUND(InData%p,1), UBOUND(InData%p,1) + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL BD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p(i1), ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! u allocated yes/no + IF ( ALLOCATED(InData%u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ALLOCATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y(i1), ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! m allocated yes/no + IF ( ALLOCATED(InData%m) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m upper/lower bounds for each dimension + DO i1 = LBOUND(InData%m,1), UBOUND(InData%m,1) + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL BD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m(i1), ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Output upper/lower bounds for each dimension + DO i2 = LBOUND(InData%Output,2), UBOUND(InData%Output,2) + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! y_interp allocated yes/no + IF ( ALLOCATED(InData%y_interp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y_interp upper/lower bounds for each dimension + DO i1 = LBOUND(InData%y_interp,1), UBOUND(InData%y_interp,1) + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp(i1), ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Input upper/lower bounds for each dimension + DO i2 = LBOUND(InData%Input,2), UBOUND(InData%Input,2) + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1,i2), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x) ) 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%x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%x,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%x,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%x,2), UBOUND(InData%x,2) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + CALL BD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%xd) ) 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%xd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xd,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%xd,2), UBOUND(InData%xd,2) + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL BD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%z) ) 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%z,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%z,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%z,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%z,2), UBOUND(InData%z,2) + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL BD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%OtherSt) ) 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%OtherSt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OtherSt,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OtherSt,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OtherSt,2), UBOUND(InData%OtherSt,2) + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL BD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%p) ) 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%p,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%p,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%p,1), UBOUND(InData%p,1) + CALL BD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p(i1), ErrStat2, ErrMsg2, OnlySize ) ! p + 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%u) ) 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%u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u(i1), ErrStat2, ErrMsg2, OnlySize ) ! u + 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%y) ) 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%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y(i1), ErrStat2, ErrMsg2, OnlySize ) ! y + 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%m) ) 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%m,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m,1), UBOUND(InData%m,1) + CALL BD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m(i1), ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Output,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Output,2), UBOUND(InData%Output,2) + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%y_interp) ) 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%y_interp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y_interp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y_interp,1), UBOUND(InData%y_interp,1) + CALL BD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp(i1), ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Input,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Input,2), UBOUND(InData%Input,2) + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL BD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1,i2), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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 DO + END IF + IF ( .NOT. ALLOCATED(InData%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%InputTimes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%InputTimes,2), UBOUND(InData%InputTimes,2) + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_PackBeamDyn_Data + + SUBROUTINE FAST_UnPackBeamDyn_Data( 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(BeamDyn_Data), 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 = 'FAST_UnPackBeamDyn_Data' + ! 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 ! x 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%x)) DEALLOCATE(OutData%x) + ALLOCATE(OutData%x(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%x,2), UBOUND(OutData%x,2) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 BD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1,i2), ErrStat2, ErrMsg2 ) ! x + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd 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%xd)) DEALLOCATE(OutData%xd) + ALLOCATE(OutData%xd(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%xd,2), UBOUND(OutData%xd,2) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 BD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1,i2), ErrStat2, ErrMsg2 ) ! xd + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! z 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%z)) DEALLOCATE(OutData%z) + ALLOCATE(OutData%z(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%z.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%z,2), UBOUND(OutData%z,2) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 BD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1,i2), ErrStat2, ErrMsg2 ) ! z + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OtherSt 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%OtherSt)) DEALLOCATE(OutData%OtherSt) + ALLOCATE(OutData%OtherSt(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OtherSt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%OtherSt,2), UBOUND(OutData%OtherSt,2) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 BD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1,i2), ErrStat2, ErrMsg2 ) ! OtherSt + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! p 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%p)) DEALLOCATE(OutData%p) + ALLOCATE(OutData%p(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%p.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%p,1), UBOUND(OutData%p,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 BD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p(i1), ErrStat2, ErrMsg2 ) ! p + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u 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%u)) DEALLOCATE(OutData%u) + ALLOCATE(OutData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u,1), UBOUND(OutData%u,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 BD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u(i1), ErrStat2, ErrMsg2 ) ! u + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y 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%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,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 BD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y(i1), ErrStat2, ErrMsg2 ) ! y + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m 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%m)) DEALLOCATE(OutData%m) + ALLOCATE(OutData%m(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m,1), UBOUND(OutData%m,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 BD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m(i1), ErrStat2, ErrMsg2 ) ! m + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Output,2), UBOUND(OutData%Output,2) + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 BD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1,i2), ErrStat2, ErrMsg2 ) ! Output + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y_interp 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%y_interp)) DEALLOCATE(OutData%y_interp) + ALLOCATE(OutData%y_interp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y_interp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y_interp,1), UBOUND(OutData%y_interp,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 BD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp(i1), ErrStat2, ErrMsg2 ) ! y_interp + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Input,2), UBOUND(OutData%Input,2) + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 BD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1,i2), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%InputTimes,2), UBOUND(OutData%InputTimes,2) + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FAST_UnPackBeamDyn_Data + + SUBROUTINE FAST_CopyElastoDyn_Data( SrcElastoDyn_DataData, DstElastoDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElastoDyn_Data), INTENT(INOUT) :: SrcElastoDyn_DataData + TYPE(ElastoDyn_Data), INTENT(INOUT) :: DstElastoDyn_DataData + 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 = 'FAST_CopyElastoDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcElastoDyn_DataData%x,1), UBOUND(SrcElastoDyn_DataData%x,1) + CALL ED_CopyContState( SrcElastoDyn_DataData%x(i1), DstElastoDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcElastoDyn_DataData%xd,1), UBOUND(SrcElastoDyn_DataData%xd,1) + CALL ED_CopyDiscState( SrcElastoDyn_DataData%xd(i1), DstElastoDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcElastoDyn_DataData%z,1), UBOUND(SrcElastoDyn_DataData%z,1) + CALL ED_CopyConstrState( SrcElastoDyn_DataData%z(i1), DstElastoDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcElastoDyn_DataData%OtherSt,1), UBOUND(SrcElastoDyn_DataData%OtherSt,1) + CALL ED_CopyOtherState( SrcElastoDyn_DataData%OtherSt(i1), DstElastoDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL ED_CopyParam( SrcElastoDyn_DataData%p, DstElastoDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ED_CopyInput( SrcElastoDyn_DataData%u, DstElastoDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ED_CopyOutput( SrcElastoDyn_DataData%y, DstElastoDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ED_CopyMisc( SrcElastoDyn_DataData%m, DstElastoDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcElastoDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcElastoDyn_DataData%Output,1) + i1_u = UBOUND(SrcElastoDyn_DataData%Output,1) + IF (.NOT. ALLOCATED(DstElastoDyn_DataData%Output)) THEN + ALLOCATE(DstElastoDyn_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElastoDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcElastoDyn_DataData%Output,1), UBOUND(SrcElastoDyn_DataData%Output,1) + CALL ED_CopyOutput( SrcElastoDyn_DataData%Output(i1), DstElastoDyn_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL ED_CopyOutput( SrcElastoDyn_DataData%y_interp, DstElastoDyn_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcElastoDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcElastoDyn_DataData%Input,1) + i1_u = UBOUND(SrcElastoDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstElastoDyn_DataData%Input)) THEN + ALLOCATE(DstElastoDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElastoDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcElastoDyn_DataData%Input,1), UBOUND(SrcElastoDyn_DataData%Input,1) + CALL ED_CopyInput( SrcElastoDyn_DataData%Input(i1), DstElastoDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcElastoDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcElastoDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcElastoDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstElastoDyn_DataData%InputTimes)) THEN + ALLOCATE(DstElastoDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstElastoDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstElastoDyn_DataData%InputTimes = SrcElastoDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyElastoDyn_Data + + SUBROUTINE FAST_DestroyElastoDyn_Data( ElastoDyn_DataData, ErrStat, ErrMsg ) + TYPE(ElastoDyn_Data), INTENT(INOUT) :: ElastoDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyElastoDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(ElastoDyn_DataData%x,1), UBOUND(ElastoDyn_DataData%x,1) + CALL ED_DestroyContState( ElastoDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ElastoDyn_DataData%xd,1), UBOUND(ElastoDyn_DataData%xd,1) + CALL ED_DestroyDiscState( ElastoDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ElastoDyn_DataData%z,1), UBOUND(ElastoDyn_DataData%z,1) + CALL ED_DestroyConstrState( ElastoDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ElastoDyn_DataData%OtherSt,1), UBOUND(ElastoDyn_DataData%OtherSt,1) + CALL ED_DestroyOtherState( ElastoDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL ED_DestroyParam( ElastoDyn_DataData%p, ErrStat, ErrMsg ) + CALL ED_DestroyInput( ElastoDyn_DataData%u, ErrStat, ErrMsg ) + CALL ED_DestroyOutput( ElastoDyn_DataData%y, ErrStat, ErrMsg ) + CALL ED_DestroyMisc( ElastoDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(ElastoDyn_DataData%Output)) THEN +DO i1 = LBOUND(ElastoDyn_DataData%Output,1), UBOUND(ElastoDyn_DataData%Output,1) + CALL ED_DestroyOutput( ElastoDyn_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ElastoDyn_DataData%Output) +ENDIF + CALL ED_DestroyOutput( ElastoDyn_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(ElastoDyn_DataData%Input)) THEN +DO i1 = LBOUND(ElastoDyn_DataData%Input,1), UBOUND(ElastoDyn_DataData%Input,1) + CALL ED_DestroyInput( ElastoDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ElastoDyn_DataData%Input) +ENDIF +IF (ALLOCATED(ElastoDyn_DataData%InputTimes)) THEN + DEALLOCATE(ElastoDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyElastoDyn_Data + + SUBROUTINE FAST_PackElastoDyn_Data( 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(ElastoDyn_Data), 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 = 'FAST_PackElastoDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL ED_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL ED_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL ED_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL ED_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL ED_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL ED_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL ED_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL ED_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL ED_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL ED_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 ED_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL ED_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL ED_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackElastoDyn_Data + + SUBROUTINE FAST_UnPackElastoDyn_Data( 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(ElastoDyn_Data), 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 = 'FAST_UnPackElastoDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 ED_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 ED_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 ED_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 ED_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 ED_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 ED_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 ED_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 ED_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 ED_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 ED_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 ED_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackElastoDyn_Data + + SUBROUTINE FAST_CopyServoDyn_Data( SrcServoDyn_DataData, DstServoDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ServoDyn_Data), INTENT(INOUT) :: SrcServoDyn_DataData + TYPE(ServoDyn_Data), INTENT(INOUT) :: DstServoDyn_DataData + 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 = 'FAST_CopyServoDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcServoDyn_DataData%x,1), UBOUND(SrcServoDyn_DataData%x,1) + CALL SrvD_CopyContState( SrcServoDyn_DataData%x(i1), DstServoDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcServoDyn_DataData%xd,1), UBOUND(SrcServoDyn_DataData%xd,1) + CALL SrvD_CopyDiscState( SrcServoDyn_DataData%xd(i1), DstServoDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcServoDyn_DataData%z,1), UBOUND(SrcServoDyn_DataData%z,1) + CALL SrvD_CopyConstrState( SrcServoDyn_DataData%z(i1), DstServoDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcServoDyn_DataData%OtherSt,1), UBOUND(SrcServoDyn_DataData%OtherSt,1) + CALL SrvD_CopyOtherState( SrcServoDyn_DataData%OtherSt(i1), DstServoDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL SrvD_CopyParam( SrcServoDyn_DataData%p, DstServoDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SrvD_CopyInput( SrcServoDyn_DataData%u, DstServoDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SrvD_CopyOutput( SrcServoDyn_DataData%y, DstServoDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SrvD_CopyMisc( SrcServoDyn_DataData%m, DstServoDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcServoDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcServoDyn_DataData%Output,1) + i1_u = UBOUND(SrcServoDyn_DataData%Output,1) + IF (.NOT. ALLOCATED(DstServoDyn_DataData%Output)) THEN + ALLOCATE(DstServoDyn_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstServoDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcServoDyn_DataData%Output,1), UBOUND(SrcServoDyn_DataData%Output,1) + CALL SrvD_CopyOutput( SrcServoDyn_DataData%Output(i1), DstServoDyn_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL SrvD_CopyOutput( SrcServoDyn_DataData%y_interp, DstServoDyn_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcServoDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcServoDyn_DataData%Input,1) + i1_u = UBOUND(SrcServoDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstServoDyn_DataData%Input)) THEN + ALLOCATE(DstServoDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstServoDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcServoDyn_DataData%Input,1), UBOUND(SrcServoDyn_DataData%Input,1) + CALL SrvD_CopyInput( SrcServoDyn_DataData%Input(i1), DstServoDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcServoDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcServoDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcServoDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstServoDyn_DataData%InputTimes)) THEN + ALLOCATE(DstServoDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstServoDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstServoDyn_DataData%InputTimes = SrcServoDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyServoDyn_Data + + SUBROUTINE FAST_DestroyServoDyn_Data( ServoDyn_DataData, ErrStat, ErrMsg ) + TYPE(ServoDyn_Data), INTENT(INOUT) :: ServoDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyServoDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(ServoDyn_DataData%x,1), UBOUND(ServoDyn_DataData%x,1) + CALL SrvD_DestroyContState( ServoDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ServoDyn_DataData%xd,1), UBOUND(ServoDyn_DataData%xd,1) + CALL SrvD_DestroyDiscState( ServoDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ServoDyn_DataData%z,1), UBOUND(ServoDyn_DataData%z,1) + CALL SrvD_DestroyConstrState( ServoDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ServoDyn_DataData%OtherSt,1), UBOUND(ServoDyn_DataData%OtherSt,1) + CALL SrvD_DestroyOtherState( ServoDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL SrvD_DestroyParam( ServoDyn_DataData%p, ErrStat, ErrMsg ) + CALL SrvD_DestroyInput( ServoDyn_DataData%u, ErrStat, ErrMsg ) + CALL SrvD_DestroyOutput( ServoDyn_DataData%y, ErrStat, ErrMsg ) + CALL SrvD_DestroyMisc( ServoDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(ServoDyn_DataData%Output)) THEN +DO i1 = LBOUND(ServoDyn_DataData%Output,1), UBOUND(ServoDyn_DataData%Output,1) + CALL SrvD_DestroyOutput( ServoDyn_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ServoDyn_DataData%Output) +ENDIF + CALL SrvD_DestroyOutput( ServoDyn_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(ServoDyn_DataData%Input)) THEN +DO i1 = LBOUND(ServoDyn_DataData%Input,1), UBOUND(ServoDyn_DataData%Input,1) + CALL SrvD_DestroyInput( ServoDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ServoDyn_DataData%Input) +ENDIF +IF (ALLOCATED(ServoDyn_DataData%InputTimes)) THEN + DEALLOCATE(ServoDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyServoDyn_Data + + SUBROUTINE FAST_PackServoDyn_Data( 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(ServoDyn_Data), 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 = 'FAST_PackServoDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL SrvD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL SrvD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL SrvD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL SrvD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL SrvD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL SrvD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL SrvD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL SrvD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL SrvD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL SrvD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL SrvD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 SrvD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL SrvD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL SrvD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackServoDyn_Data + + SUBROUTINE FAST_UnPackServoDyn_Data( 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(ServoDyn_Data), 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 = 'FAST_UnPackServoDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 SrvD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 SrvD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 SrvD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 SrvD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 SrvD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 SrvD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 SrvD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 SrvD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 SrvD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 SrvD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 SrvD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackServoDyn_Data + + SUBROUTINE FAST_CopyAeroDyn14_Data( SrcAeroDyn14_DataData, DstAeroDyn14_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AeroDyn14_Data), INTENT(INOUT) :: SrcAeroDyn14_DataData + TYPE(AeroDyn14_Data), INTENT(INOUT) :: DstAeroDyn14_DataData + 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 = 'FAST_CopyAeroDyn14_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcAeroDyn14_DataData%x,1), UBOUND(SrcAeroDyn14_DataData%x,1) + CALL AD14_CopyContState( SrcAeroDyn14_DataData%x(i1), DstAeroDyn14_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn14_DataData%xd,1), UBOUND(SrcAeroDyn14_DataData%xd,1) + CALL AD14_CopyDiscState( SrcAeroDyn14_DataData%xd(i1), DstAeroDyn14_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn14_DataData%z,1), UBOUND(SrcAeroDyn14_DataData%z,1) + CALL AD14_CopyConstrState( SrcAeroDyn14_DataData%z(i1), DstAeroDyn14_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn14_DataData%OtherSt,1), UBOUND(SrcAeroDyn14_DataData%OtherSt,1) + CALL AD14_CopyOtherState( SrcAeroDyn14_DataData%OtherSt(i1), DstAeroDyn14_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL AD14_CopyParam( SrcAeroDyn14_DataData%p, DstAeroDyn14_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_CopyInput( SrcAeroDyn14_DataData%u, DstAeroDyn14_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_CopyOutput( SrcAeroDyn14_DataData%y, DstAeroDyn14_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_CopyMisc( SrcAeroDyn14_DataData%m, DstAeroDyn14_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcAeroDyn14_DataData%Input)) THEN + i1_l = LBOUND(SrcAeroDyn14_DataData%Input,1) + i1_u = UBOUND(SrcAeroDyn14_DataData%Input,1) + IF (.NOT. ALLOCATED(DstAeroDyn14_DataData%Input)) THEN + ALLOCATE(DstAeroDyn14_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroDyn14_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcAeroDyn14_DataData%Input,1), UBOUND(SrcAeroDyn14_DataData%Input,1) + CALL AD14_CopyInput( SrcAeroDyn14_DataData%Input(i1), DstAeroDyn14_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcAeroDyn14_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcAeroDyn14_DataData%InputTimes,1) + i1_u = UBOUND(SrcAeroDyn14_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstAeroDyn14_DataData%InputTimes)) THEN + ALLOCATE(DstAeroDyn14_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroDyn14_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAeroDyn14_DataData%InputTimes = SrcAeroDyn14_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyAeroDyn14_Data + + SUBROUTINE FAST_DestroyAeroDyn14_Data( AeroDyn14_DataData, ErrStat, ErrMsg ) + TYPE(AeroDyn14_Data), INTENT(INOUT) :: AeroDyn14_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyAeroDyn14_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(AeroDyn14_DataData%x,1), UBOUND(AeroDyn14_DataData%x,1) + CALL AD14_DestroyContState( AeroDyn14_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn14_DataData%xd,1), UBOUND(AeroDyn14_DataData%xd,1) + CALL AD14_DestroyDiscState( AeroDyn14_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn14_DataData%z,1), UBOUND(AeroDyn14_DataData%z,1) + CALL AD14_DestroyConstrState( AeroDyn14_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn14_DataData%OtherSt,1), UBOUND(AeroDyn14_DataData%OtherSt,1) + CALL AD14_DestroyOtherState( AeroDyn14_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL AD14_DestroyParam( AeroDyn14_DataData%p, ErrStat, ErrMsg ) + CALL AD14_DestroyInput( AeroDyn14_DataData%u, ErrStat, ErrMsg ) + CALL AD14_DestroyOutput( AeroDyn14_DataData%y, ErrStat, ErrMsg ) + CALL AD14_DestroyMisc( AeroDyn14_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(AeroDyn14_DataData%Input)) THEN +DO i1 = LBOUND(AeroDyn14_DataData%Input,1), UBOUND(AeroDyn14_DataData%Input,1) + CALL AD14_DestroyInput( AeroDyn14_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(AeroDyn14_DataData%Input) +ENDIF +IF (ALLOCATED(AeroDyn14_DataData%InputTimes)) THEN + DEALLOCATE(AeroDyn14_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyAeroDyn14_Data + + SUBROUTINE FAST_PackAeroDyn14_Data( 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(AeroDyn14_Data), 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 = 'FAST_PackAeroDyn14_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL AD14_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL AD14_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL AD14_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL AD14_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL AD14_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL AD14_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL AD14_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL AD14_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL AD14_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL AD14_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL AD14_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL AD14_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL AD14_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL AD14_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 AD14_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 AD14_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 AD14_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL AD14_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackAeroDyn14_Data + + SUBROUTINE FAST_UnPackAeroDyn14_Data( 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(AeroDyn14_Data), 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 = 'FAST_UnPackAeroDyn14_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 AD14_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 AD14_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 AD14_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 AD14_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 AD14_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 AD14_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 AD14_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 AD14_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 AD14_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackAeroDyn14_Data + + SUBROUTINE FAST_CopyAeroDyn_Data( SrcAeroDyn_DataData, DstAeroDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(AeroDyn_Data), INTENT(INOUT) :: SrcAeroDyn_DataData + TYPE(AeroDyn_Data), INTENT(INOUT) :: DstAeroDyn_DataData + 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 = 'FAST_CopyAeroDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcAeroDyn_DataData%x,1), UBOUND(SrcAeroDyn_DataData%x,1) + CALL AD_CopyContState( SrcAeroDyn_DataData%x(i1), DstAeroDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn_DataData%xd,1), UBOUND(SrcAeroDyn_DataData%xd,1) + CALL AD_CopyDiscState( SrcAeroDyn_DataData%xd(i1), DstAeroDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn_DataData%z,1), UBOUND(SrcAeroDyn_DataData%z,1) + CALL AD_CopyConstrState( SrcAeroDyn_DataData%z(i1), DstAeroDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcAeroDyn_DataData%OtherSt,1), UBOUND(SrcAeroDyn_DataData%OtherSt,1) + CALL AD_CopyOtherState( SrcAeroDyn_DataData%OtherSt(i1), DstAeroDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL AD_CopyParam( SrcAeroDyn_DataData%p, DstAeroDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyInput( SrcAeroDyn_DataData%u, DstAeroDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyOutput( SrcAeroDyn_DataData%y, DstAeroDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyMisc( SrcAeroDyn_DataData%m, DstAeroDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcAeroDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcAeroDyn_DataData%Output,1) + i1_u = UBOUND(SrcAeroDyn_DataData%Output,1) + IF (.NOT. ALLOCATED(DstAeroDyn_DataData%Output)) THEN + ALLOCATE(DstAeroDyn_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcAeroDyn_DataData%Output,1), UBOUND(SrcAeroDyn_DataData%Output,1) + CALL AD_CopyOutput( SrcAeroDyn_DataData%Output(i1), DstAeroDyn_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL AD_CopyOutput( SrcAeroDyn_DataData%y_interp, DstAeroDyn_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcAeroDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcAeroDyn_DataData%Input,1) + i1_u = UBOUND(SrcAeroDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstAeroDyn_DataData%Input)) THEN + ALLOCATE(DstAeroDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcAeroDyn_DataData%Input,1), UBOUND(SrcAeroDyn_DataData%Input,1) + CALL AD_CopyInput( SrcAeroDyn_DataData%Input(i1), DstAeroDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcAeroDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcAeroDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcAeroDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstAeroDyn_DataData%InputTimes)) THEN + ALLOCATE(DstAeroDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstAeroDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstAeroDyn_DataData%InputTimes = SrcAeroDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyAeroDyn_Data + + SUBROUTINE FAST_DestroyAeroDyn_Data( AeroDyn_DataData, ErrStat, ErrMsg ) + TYPE(AeroDyn_Data), INTENT(INOUT) :: AeroDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyAeroDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(AeroDyn_DataData%x,1), UBOUND(AeroDyn_DataData%x,1) + CALL AD_DestroyContState( AeroDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn_DataData%xd,1), UBOUND(AeroDyn_DataData%xd,1) + CALL AD_DestroyDiscState( AeroDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn_DataData%z,1), UBOUND(AeroDyn_DataData%z,1) + CALL AD_DestroyConstrState( AeroDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(AeroDyn_DataData%OtherSt,1), UBOUND(AeroDyn_DataData%OtherSt,1) + CALL AD_DestroyOtherState( AeroDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL AD_DestroyParam( AeroDyn_DataData%p, ErrStat, ErrMsg ) + CALL AD_DestroyInput( AeroDyn_DataData%u, ErrStat, ErrMsg ) + CALL AD_DestroyOutput( AeroDyn_DataData%y, ErrStat, ErrMsg ) + CALL AD_DestroyMisc( AeroDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(AeroDyn_DataData%Output)) THEN +DO i1 = LBOUND(AeroDyn_DataData%Output,1), UBOUND(AeroDyn_DataData%Output,1) + CALL AD_DestroyOutput( AeroDyn_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(AeroDyn_DataData%Output) +ENDIF + CALL AD_DestroyOutput( AeroDyn_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(AeroDyn_DataData%Input)) THEN +DO i1 = LBOUND(AeroDyn_DataData%Input,1), UBOUND(AeroDyn_DataData%Input,1) + CALL AD_DestroyInput( AeroDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(AeroDyn_DataData%Input) +ENDIF +IF (ALLOCATED(AeroDyn_DataData%InputTimes)) THEN + DEALLOCATE(AeroDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyAeroDyn_Data + + SUBROUTINE FAST_PackAeroDyn_Data( 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(AeroDyn_Data), 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 = 'FAST_PackAeroDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL AD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL AD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL AD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL AD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL AD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL AD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL AD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 AD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL AD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL AD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackAeroDyn_Data + + SUBROUTINE FAST_UnPackAeroDyn_Data( 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(AeroDyn_Data), 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 = 'FAST_UnPackAeroDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 AD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 AD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 AD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 AD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 AD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 AD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 AD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 AD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 AD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 AD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 AD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackAeroDyn_Data + + SUBROUTINE FAST_CopyInflowWind_Data( SrcInflowWind_DataData, DstInflowWind_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(InflowWind_Data), INTENT(IN) :: SrcInflowWind_DataData + TYPE(InflowWind_Data), INTENT(INOUT) :: DstInflowWind_DataData + 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 = 'FAST_CopyInflowWind_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcInflowWind_DataData%x,1), UBOUND(SrcInflowWind_DataData%x,1) + CALL InflowWind_CopyContState( SrcInflowWind_DataData%x(i1), DstInflowWind_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcInflowWind_DataData%xd,1), UBOUND(SrcInflowWind_DataData%xd,1) + CALL InflowWind_CopyDiscState( SrcInflowWind_DataData%xd(i1), DstInflowWind_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcInflowWind_DataData%z,1), UBOUND(SrcInflowWind_DataData%z,1) + CALL InflowWind_CopyConstrState( SrcInflowWind_DataData%z(i1), DstInflowWind_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcInflowWind_DataData%OtherSt,1), UBOUND(SrcInflowWind_DataData%OtherSt,1) + CALL InflowWind_CopyOtherState( SrcInflowWind_DataData%OtherSt(i1), DstInflowWind_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL InflowWind_CopyParam( SrcInflowWind_DataData%p, DstInflowWind_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyInput( SrcInflowWind_DataData%u, DstInflowWind_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyOutput( SrcInflowWind_DataData%y, DstInflowWind_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyMisc( SrcInflowWind_DataData%m, DstInflowWind_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInflowWind_DataData%Output)) THEN + i1_l = LBOUND(SrcInflowWind_DataData%Output,1) + i1_u = UBOUND(SrcInflowWind_DataData%Output,1) + IF (.NOT. ALLOCATED(DstInflowWind_DataData%Output)) THEN + ALLOCATE(DstInflowWind_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInflowWind_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInflowWind_DataData%Output,1), UBOUND(SrcInflowWind_DataData%Output,1) + CALL InflowWind_CopyOutput( SrcInflowWind_DataData%Output(i1), DstInflowWind_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL InflowWind_CopyOutput( SrcInflowWind_DataData%y_interp, DstInflowWind_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInflowWind_DataData%Input)) THEN + i1_l = LBOUND(SrcInflowWind_DataData%Input,1) + i1_u = UBOUND(SrcInflowWind_DataData%Input,1) + IF (.NOT. ALLOCATED(DstInflowWind_DataData%Input)) THEN + ALLOCATE(DstInflowWind_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInflowWind_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInflowWind_DataData%Input,1), UBOUND(SrcInflowWind_DataData%Input,1) + CALL InflowWind_CopyInput( SrcInflowWind_DataData%Input(i1), DstInflowWind_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcInflowWind_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcInflowWind_DataData%InputTimes,1) + i1_u = UBOUND(SrcInflowWind_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstInflowWind_DataData%InputTimes)) THEN + ALLOCATE(DstInflowWind_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInflowWind_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInflowWind_DataData%InputTimes = SrcInflowWind_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyInflowWind_Data + + SUBROUTINE FAST_DestroyInflowWind_Data( InflowWind_DataData, ErrStat, ErrMsg ) + TYPE(InflowWind_Data), INTENT(INOUT) :: InflowWind_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyInflowWind_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(InflowWind_DataData%x,1), UBOUND(InflowWind_DataData%x,1) + CALL InflowWind_DestroyContState( InflowWind_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(InflowWind_DataData%xd,1), UBOUND(InflowWind_DataData%xd,1) + CALL InflowWind_DestroyDiscState( InflowWind_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(InflowWind_DataData%z,1), UBOUND(InflowWind_DataData%z,1) + CALL InflowWind_DestroyConstrState( InflowWind_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(InflowWind_DataData%OtherSt,1), UBOUND(InflowWind_DataData%OtherSt,1) + CALL InflowWind_DestroyOtherState( InflowWind_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL InflowWind_DestroyParam( InflowWind_DataData%p, ErrStat, ErrMsg ) + CALL InflowWind_DestroyInput( InflowWind_DataData%u, ErrStat, ErrMsg ) + CALL InflowWind_DestroyOutput( InflowWind_DataData%y, ErrStat, ErrMsg ) + CALL InflowWind_DestroyMisc( InflowWind_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(InflowWind_DataData%Output)) THEN +DO i1 = LBOUND(InflowWind_DataData%Output,1), UBOUND(InflowWind_DataData%Output,1) + CALL InflowWind_DestroyOutput( InflowWind_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InflowWind_DataData%Output) +ENDIF + CALL InflowWind_DestroyOutput( InflowWind_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(InflowWind_DataData%Input)) THEN +DO i1 = LBOUND(InflowWind_DataData%Input,1), UBOUND(InflowWind_DataData%Input,1) + CALL InflowWind_DestroyInput( InflowWind_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InflowWind_DataData%Input) +ENDIF +IF (ALLOCATED(InflowWind_DataData%InputTimes)) THEN + DEALLOCATE(InflowWind_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyInflowWind_Data + + SUBROUTINE FAST_PackInflowWind_Data( 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_Data), 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 = 'FAST_PackInflowWind_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL InflowWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL InflowWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL InflowWind_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL InflowWind_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL InflowWind_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL InflowWind_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL InflowWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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, ErrStat2, ErrMsg2, OnlySize ) ! u + 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_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL InflowWind_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackInflowWind_Data + + SUBROUTINE FAST_UnPackInflowWind_Data( 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_Data), 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 = 'FAST_UnPackInflowWind_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 InflowWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 InflowWind_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 InflowWind_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 InflowWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 InflowWind_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackInflowWind_Data + + SUBROUTINE FAST_CopyOpenFOAM_Data( SrcOpenFOAM_DataData, DstOpenFOAM_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpenFOAM_Data), INTENT(INOUT) :: SrcOpenFOAM_DataData + TYPE(OpenFOAM_Data), INTENT(INOUT) :: DstOpenFOAM_DataData + 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 = 'FAST_CopyOpenFOAM_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL OpFM_CopyInput( SrcOpenFOAM_DataData%u, DstOpenFOAM_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL OpFM_CopyOutput( SrcOpenFOAM_DataData%y, DstOpenFOAM_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL OpFM_CopyParam( SrcOpenFOAM_DataData%p, DstOpenFOAM_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL OpFM_CopyMisc( SrcOpenFOAM_DataData%m, DstOpenFOAM_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyOpenFOAM_Data + + SUBROUTINE FAST_DestroyOpenFOAM_Data( OpenFOAM_DataData, ErrStat, ErrMsg ) + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpenFOAM_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyOpenFOAM_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL OpFM_DestroyInput( OpenFOAM_DataData%u, ErrStat, ErrMsg ) + CALL OpFM_DestroyOutput( OpenFOAM_DataData%y, ErrStat, ErrMsg ) + CALL OpFM_DestroyParam( OpenFOAM_DataData%p, ErrStat, ErrMsg ) + CALL OpFM_DestroyMisc( OpenFOAM_DataData%m, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyOpenFOAM_Data + + SUBROUTINE FAST_PackOpenFOAM_Data( 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(OpenFOAM_Data), 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 = 'FAST_PackOpenFOAM_Data' + ! 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 ! u: size of buffers for each call to pack subtype + CALL OpFM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL OpFM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL OpFM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL OpFM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + 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 OpFM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 OpFM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 OpFM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 OpFM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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 FAST_PackOpenFOAM_Data + + SUBROUTINE FAST_UnPackOpenFOAM_Data( 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(OpenFOAM_Data), 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 = 'FAST_UnPackOpenFOAM_Data' + ! 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 OpFM_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 OpFM_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 OpFM_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 OpFM_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 FAST_UnPackOpenFOAM_Data + + SUBROUTINE FAST_CopySuperController_Data( SrcSuperController_DataData, DstSuperController_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SuperController_Data), INTENT(IN) :: SrcSuperController_DataData + TYPE(SuperController_Data), INTENT(INOUT) :: DstSuperController_DataData + 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 = 'FAST_CopySuperController_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SC_CopyInput( SrcSuperController_DataData%u, DstSuperController_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SC_CopyOutput( SrcSuperController_DataData%y, DstSuperController_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SC_CopyParam( SrcSuperController_DataData%p, DstSuperController_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopySuperController_Data + + SUBROUTINE FAST_DestroySuperController_Data( SuperController_DataData, ErrStat, ErrMsg ) + TYPE(SuperController_Data), INTENT(INOUT) :: SuperController_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroySuperController_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SC_DestroyInput( SuperController_DataData%u, ErrStat, ErrMsg ) + CALL SC_DestroyOutput( SuperController_DataData%y, ErrStat, ErrMsg ) + CALL SC_DestroyParam( SuperController_DataData%p, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroySuperController_Data + + SUBROUTINE FAST_PackSuperController_Data( 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(SuperController_Data), 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 = 'FAST_PackSuperController_Data' + ! 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 ! u: size of buffers for each call to pack subtype + CALL SC_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL SC_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL SC_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + 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 SC_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 SC_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 SC_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 FAST_PackSuperController_Data + + SUBROUTINE FAST_UnPackSuperController_Data( 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(SuperController_Data), 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 = 'FAST_UnPackSuperController_Data' + ! 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 SC_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 SC_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 SC_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 FAST_UnPackSuperController_Data + + SUBROUTINE FAST_CopySubDyn_Data( SrcSubDyn_DataData, DstSubDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SubDyn_Data), INTENT(INOUT) :: SrcSubDyn_DataData + TYPE(SubDyn_Data), INTENT(INOUT) :: DstSubDyn_DataData + 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 = 'FAST_CopySubDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcSubDyn_DataData%x,1), UBOUND(SrcSubDyn_DataData%x,1) + CALL SD_CopyContState( SrcSubDyn_DataData%x(i1), DstSubDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcSubDyn_DataData%xd,1), UBOUND(SrcSubDyn_DataData%xd,1) + CALL SD_CopyDiscState( SrcSubDyn_DataData%xd(i1), DstSubDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcSubDyn_DataData%z,1), UBOUND(SrcSubDyn_DataData%z,1) + CALL SD_CopyConstrState( SrcSubDyn_DataData%z(i1), DstSubDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcSubDyn_DataData%OtherSt,1), UBOUND(SrcSubDyn_DataData%OtherSt,1) + CALL SD_CopyOtherState( SrcSubDyn_DataData%OtherSt(i1), DstSubDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL SD_CopyParam( SrcSubDyn_DataData%p, DstSubDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SD_CopyInput( SrcSubDyn_DataData%u, DstSubDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SD_CopyOutput( SrcSubDyn_DataData%y, DstSubDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SD_CopyMisc( SrcSubDyn_DataData%m, DstSubDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcSubDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcSubDyn_DataData%Input,1) + i1_u = UBOUND(SrcSubDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstSubDyn_DataData%Input)) THEN + ALLOCATE(DstSubDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstSubDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcSubDyn_DataData%Input,1), UBOUND(SrcSubDyn_DataData%Input,1) + CALL SD_CopyInput( SrcSubDyn_DataData%Input(i1), DstSubDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcSubDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcSubDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcSubDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstSubDyn_DataData%InputTimes)) THEN + ALLOCATE(DstSubDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstSubDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstSubDyn_DataData%InputTimes = SrcSubDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopySubDyn_Data + + SUBROUTINE FAST_DestroySubDyn_Data( SubDyn_DataData, ErrStat, ErrMsg ) + TYPE(SubDyn_Data), INTENT(INOUT) :: SubDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroySubDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(SubDyn_DataData%x,1), UBOUND(SubDyn_DataData%x,1) + CALL SD_DestroyContState( SubDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(SubDyn_DataData%xd,1), UBOUND(SubDyn_DataData%xd,1) + CALL SD_DestroyDiscState( SubDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(SubDyn_DataData%z,1), UBOUND(SubDyn_DataData%z,1) + CALL SD_DestroyConstrState( SubDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(SubDyn_DataData%OtherSt,1), UBOUND(SubDyn_DataData%OtherSt,1) + CALL SD_DestroyOtherState( SubDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL SD_DestroyParam( SubDyn_DataData%p, ErrStat, ErrMsg ) + CALL SD_DestroyInput( SubDyn_DataData%u, ErrStat, ErrMsg ) + CALL SD_DestroyOutput( SubDyn_DataData%y, ErrStat, ErrMsg ) + CALL SD_DestroyMisc( SubDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(SubDyn_DataData%Input)) THEN +DO i1 = LBOUND(SubDyn_DataData%Input,1), UBOUND(SubDyn_DataData%Input,1) + CALL SD_DestroyInput( SubDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(SubDyn_DataData%Input) +ENDIF +IF (ALLOCATED(SubDyn_DataData%InputTimes)) THEN + DEALLOCATE(SubDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroySubDyn_Data + + SUBROUTINE FAST_PackSubDyn_Data( 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(SubDyn_Data), 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 = 'FAST_PackSubDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL SD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL SD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL SD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL SD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL SD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL SD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL SD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL SD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL SD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 SD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL SD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackSubDyn_Data + + SUBROUTINE FAST_UnPackSubDyn_Data( 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(SubDyn_Data), 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 = 'FAST_UnPackSubDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 SD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 SD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 SD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 SD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 SD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 SD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 SD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 SD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 SD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackSubDyn_Data + + SUBROUTINE FAST_CopyExtPtfm_Data( SrcExtPtfm_DataData, DstExtPtfm_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPtfm_Data), INTENT(INOUT) :: SrcExtPtfm_DataData + TYPE(ExtPtfm_Data), INTENT(INOUT) :: DstExtPtfm_DataData + 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 = 'FAST_CopyExtPtfm_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcExtPtfm_DataData%x,1), UBOUND(SrcExtPtfm_DataData%x,1) + CALL ExtPtfm_CopyContState( SrcExtPtfm_DataData%x(i1), DstExtPtfm_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcExtPtfm_DataData%xd,1), UBOUND(SrcExtPtfm_DataData%xd,1) + CALL ExtPtfm_CopyDiscState( SrcExtPtfm_DataData%xd(i1), DstExtPtfm_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcExtPtfm_DataData%z,1), UBOUND(SrcExtPtfm_DataData%z,1) + CALL ExtPtfm_CopyConstrState( SrcExtPtfm_DataData%z(i1), DstExtPtfm_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcExtPtfm_DataData%OtherSt,1), UBOUND(SrcExtPtfm_DataData%OtherSt,1) + CALL ExtPtfm_CopyOtherState( SrcExtPtfm_DataData%OtherSt(i1), DstExtPtfm_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL ExtPtfm_CopyParam( SrcExtPtfm_DataData%p, DstExtPtfm_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ExtPtfm_CopyInput( SrcExtPtfm_DataData%u, DstExtPtfm_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ExtPtfm_CopyOutput( SrcExtPtfm_DataData%y, DstExtPtfm_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ExtPtfm_CopyMisc( SrcExtPtfm_DataData%m, DstExtPtfm_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcExtPtfm_DataData%Input)) THEN + i1_l = LBOUND(SrcExtPtfm_DataData%Input,1) + i1_u = UBOUND(SrcExtPtfm_DataData%Input,1) + IF (.NOT. ALLOCATED(DstExtPtfm_DataData%Input)) THEN + ALLOCATE(DstExtPtfm_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtPtfm_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcExtPtfm_DataData%Input,1), UBOUND(SrcExtPtfm_DataData%Input,1) + CALL ExtPtfm_CopyInput( SrcExtPtfm_DataData%Input(i1), DstExtPtfm_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcExtPtfm_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcExtPtfm_DataData%InputTimes,1) + i1_u = UBOUND(SrcExtPtfm_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstExtPtfm_DataData%InputTimes)) THEN + ALLOCATE(DstExtPtfm_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtPtfm_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstExtPtfm_DataData%InputTimes = SrcExtPtfm_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyExtPtfm_Data + + SUBROUTINE FAST_DestroyExtPtfm_Data( ExtPtfm_DataData, ErrStat, ErrMsg ) + TYPE(ExtPtfm_Data), INTENT(INOUT) :: ExtPtfm_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyExtPtfm_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(ExtPtfm_DataData%x,1), UBOUND(ExtPtfm_DataData%x,1) + CALL ExtPtfm_DestroyContState( ExtPtfm_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ExtPtfm_DataData%xd,1), UBOUND(ExtPtfm_DataData%xd,1) + CALL ExtPtfm_DestroyDiscState( ExtPtfm_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ExtPtfm_DataData%z,1), UBOUND(ExtPtfm_DataData%z,1) + CALL ExtPtfm_DestroyConstrState( ExtPtfm_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(ExtPtfm_DataData%OtherSt,1), UBOUND(ExtPtfm_DataData%OtherSt,1) + CALL ExtPtfm_DestroyOtherState( ExtPtfm_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL ExtPtfm_DestroyParam( ExtPtfm_DataData%p, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyInput( ExtPtfm_DataData%u, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyOutput( ExtPtfm_DataData%y, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyMisc( ExtPtfm_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(ExtPtfm_DataData%Input)) THEN +DO i1 = LBOUND(ExtPtfm_DataData%Input,1), UBOUND(ExtPtfm_DataData%Input,1) + CALL ExtPtfm_DestroyInput( ExtPtfm_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ExtPtfm_DataData%Input) +ENDIF +IF (ALLOCATED(ExtPtfm_DataData%InputTimes)) THEN + DEALLOCATE(ExtPtfm_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyExtPtfm_Data + + SUBROUTINE FAST_PackExtPtfm_Data( 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(ExtPtfm_Data), 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 = 'FAST_PackExtPtfm_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL ExtPtfm_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL ExtPtfm_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL ExtPtfm_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL ExtPtfm_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL ExtPtfm_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL ExtPtfm_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL ExtPtfm_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL ExtPtfm_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL ExtPtfm_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL ExtPtfm_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL ExtPtfm_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 ExtPtfm_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 ExtPtfm_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL ExtPtfm_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackExtPtfm_Data + + SUBROUTINE FAST_UnPackExtPtfm_Data( 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(ExtPtfm_Data), 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 = 'FAST_UnPackExtPtfm_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 ExtPtfm_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 ExtPtfm_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 ExtPtfm_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 ExtPtfm_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 ExtPtfm_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 ExtPtfm_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 ExtPtfm_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 ExtPtfm_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 ExtPtfm_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackExtPtfm_Data + + SUBROUTINE FAST_CopyHydroDyn_Data( SrcHydroDyn_DataData, DstHydroDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HydroDyn_Data), INTENT(INOUT) :: SrcHydroDyn_DataData + TYPE(HydroDyn_Data), INTENT(INOUT) :: DstHydroDyn_DataData + 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 = 'FAST_CopyHydroDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcHydroDyn_DataData%x,1), UBOUND(SrcHydroDyn_DataData%x,1) + CALL HydroDyn_CopyContState( SrcHydroDyn_DataData%x(i1), DstHydroDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcHydroDyn_DataData%xd,1), UBOUND(SrcHydroDyn_DataData%xd,1) + CALL HydroDyn_CopyDiscState( SrcHydroDyn_DataData%xd(i1), DstHydroDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcHydroDyn_DataData%z,1), UBOUND(SrcHydroDyn_DataData%z,1) + CALL HydroDyn_CopyConstrState( SrcHydroDyn_DataData%z(i1), DstHydroDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcHydroDyn_DataData%OtherSt,1), UBOUND(SrcHydroDyn_DataData%OtherSt,1) + CALL HydroDyn_CopyOtherState( SrcHydroDyn_DataData%OtherSt(i1), DstHydroDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL HydroDyn_CopyParam( SrcHydroDyn_DataData%p, DstHydroDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_CopyInput( SrcHydroDyn_DataData%u, DstHydroDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_CopyOutput( SrcHydroDyn_DataData%y, DstHydroDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_CopyMisc( SrcHydroDyn_DataData%m, DstHydroDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcHydroDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcHydroDyn_DataData%Output,1) + i1_u = UBOUND(SrcHydroDyn_DataData%Output,1) + IF (.NOT. ALLOCATED(DstHydroDyn_DataData%Output)) THEN + ALLOCATE(DstHydroDyn_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstHydroDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcHydroDyn_DataData%Output,1), UBOUND(SrcHydroDyn_DataData%Output,1) + CALL HydroDyn_CopyOutput( SrcHydroDyn_DataData%Output(i1), DstHydroDyn_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL HydroDyn_CopyOutput( SrcHydroDyn_DataData%y_interp, DstHydroDyn_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcHydroDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcHydroDyn_DataData%Input,1) + i1_u = UBOUND(SrcHydroDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstHydroDyn_DataData%Input)) THEN + ALLOCATE(DstHydroDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstHydroDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcHydroDyn_DataData%Input,1), UBOUND(SrcHydroDyn_DataData%Input,1) + CALL HydroDyn_CopyInput( SrcHydroDyn_DataData%Input(i1), DstHydroDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcHydroDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcHydroDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcHydroDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstHydroDyn_DataData%InputTimes)) THEN + ALLOCATE(DstHydroDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstHydroDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstHydroDyn_DataData%InputTimes = SrcHydroDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyHydroDyn_Data + + SUBROUTINE FAST_DestroyHydroDyn_Data( HydroDyn_DataData, ErrStat, ErrMsg ) + TYPE(HydroDyn_Data), INTENT(INOUT) :: HydroDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyHydroDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(HydroDyn_DataData%x,1), UBOUND(HydroDyn_DataData%x,1) + CALL HydroDyn_DestroyContState( HydroDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(HydroDyn_DataData%xd,1), UBOUND(HydroDyn_DataData%xd,1) + CALL HydroDyn_DestroyDiscState( HydroDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(HydroDyn_DataData%z,1), UBOUND(HydroDyn_DataData%z,1) + CALL HydroDyn_DestroyConstrState( HydroDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(HydroDyn_DataData%OtherSt,1), UBOUND(HydroDyn_DataData%OtherSt,1) + CALL HydroDyn_DestroyOtherState( HydroDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL HydroDyn_DestroyParam( HydroDyn_DataData%p, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyInput( HydroDyn_DataData%u, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyOutput( HydroDyn_DataData%y, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyMisc( HydroDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(HydroDyn_DataData%Output)) THEN +DO i1 = LBOUND(HydroDyn_DataData%Output,1), UBOUND(HydroDyn_DataData%Output,1) + CALL HydroDyn_DestroyOutput( HydroDyn_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(HydroDyn_DataData%Output) +ENDIF + CALL HydroDyn_DestroyOutput( HydroDyn_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(HydroDyn_DataData%Input)) THEN +DO i1 = LBOUND(HydroDyn_DataData%Input,1), UBOUND(HydroDyn_DataData%Input,1) + CALL HydroDyn_DestroyInput( HydroDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(HydroDyn_DataData%Input) +ENDIF +IF (ALLOCATED(HydroDyn_DataData%InputTimes)) THEN + DEALLOCATE(HydroDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyHydroDyn_Data + + SUBROUTINE FAST_PackHydroDyn_Data( 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(HydroDyn_Data), 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 = 'FAST_PackHydroDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL HydroDyn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL HydroDyn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL HydroDyn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL HydroDyn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL HydroDyn_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL HydroDyn_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL HydroDyn_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL HydroDyn_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL HydroDyn_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL HydroDyn_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL HydroDyn_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 HydroDyn_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL HydroDyn_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL HydroDyn_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackHydroDyn_Data + + SUBROUTINE FAST_UnPackHydroDyn_Data( 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(HydroDyn_Data), 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 = 'FAST_UnPackHydroDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 HydroDyn_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 HydroDyn_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 HydroDyn_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 HydroDyn_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 HydroDyn_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 HydroDyn_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 HydroDyn_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 HydroDyn_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 HydroDyn_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 HydroDyn_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 HydroDyn_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackHydroDyn_Data + + SUBROUTINE FAST_CopyIceFloe_Data( SrcIceFloe_DataData, DstIceFloe_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IceFloe_Data), INTENT(INOUT) :: SrcIceFloe_DataData + TYPE(IceFloe_Data), INTENT(INOUT) :: DstIceFloe_DataData + 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 = 'FAST_CopyIceFloe_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcIceFloe_DataData%x,1), UBOUND(SrcIceFloe_DataData%x,1) + CALL IceFloe_CopyContState( SrcIceFloe_DataData%x(i1), DstIceFloe_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcIceFloe_DataData%xd,1), UBOUND(SrcIceFloe_DataData%xd,1) + CALL IceFloe_CopyDiscState( SrcIceFloe_DataData%xd(i1), DstIceFloe_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcIceFloe_DataData%z,1), UBOUND(SrcIceFloe_DataData%z,1) + CALL IceFloe_CopyConstrState( SrcIceFloe_DataData%z(i1), DstIceFloe_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcIceFloe_DataData%OtherSt,1), UBOUND(SrcIceFloe_DataData%OtherSt,1) + CALL IceFloe_CopyOtherState( SrcIceFloe_DataData%OtherSt(i1), DstIceFloe_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL IceFloe_CopyParam( SrcIceFloe_DataData%p, DstIceFloe_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceFloe_CopyInput( SrcIceFloe_DataData%u, DstIceFloe_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceFloe_CopyOutput( SrcIceFloe_DataData%y, DstIceFloe_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceFloe_CopyMisc( SrcIceFloe_DataData%m, DstIceFloe_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcIceFloe_DataData%Input)) THEN + i1_l = LBOUND(SrcIceFloe_DataData%Input,1) + i1_u = UBOUND(SrcIceFloe_DataData%Input,1) + IF (.NOT. ALLOCATED(DstIceFloe_DataData%Input)) THEN + ALLOCATE(DstIceFloe_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceFloe_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcIceFloe_DataData%Input,1), UBOUND(SrcIceFloe_DataData%Input,1) + CALL IceFloe_CopyInput( SrcIceFloe_DataData%Input(i1), DstIceFloe_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcIceFloe_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcIceFloe_DataData%InputTimes,1) + i1_u = UBOUND(SrcIceFloe_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstIceFloe_DataData%InputTimes)) THEN + ALLOCATE(DstIceFloe_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIceFloe_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstIceFloe_DataData%InputTimes = SrcIceFloe_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyIceFloe_Data + + SUBROUTINE FAST_DestroyIceFloe_Data( IceFloe_DataData, ErrStat, ErrMsg ) + TYPE(IceFloe_Data), INTENT(INOUT) :: IceFloe_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyIceFloe_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(IceFloe_DataData%x,1), UBOUND(IceFloe_DataData%x,1) + CALL IceFloe_DestroyContState( IceFloe_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(IceFloe_DataData%xd,1), UBOUND(IceFloe_DataData%xd,1) + CALL IceFloe_DestroyDiscState( IceFloe_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(IceFloe_DataData%z,1), UBOUND(IceFloe_DataData%z,1) + CALL IceFloe_DestroyConstrState( IceFloe_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(IceFloe_DataData%OtherSt,1), UBOUND(IceFloe_DataData%OtherSt,1) + CALL IceFloe_DestroyOtherState( IceFloe_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL IceFloe_DestroyParam( IceFloe_DataData%p, ErrStat, ErrMsg ) + CALL IceFloe_DestroyInput( IceFloe_DataData%u, ErrStat, ErrMsg ) + CALL IceFloe_DestroyOutput( IceFloe_DataData%y, ErrStat, ErrMsg ) + CALL IceFloe_DestroyMisc( IceFloe_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(IceFloe_DataData%Input)) THEN +DO i1 = LBOUND(IceFloe_DataData%Input,1), UBOUND(IceFloe_DataData%Input,1) + CALL IceFloe_DestroyInput( IceFloe_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(IceFloe_DataData%Input) +ENDIF +IF (ALLOCATED(IceFloe_DataData%InputTimes)) THEN + DEALLOCATE(IceFloe_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyIceFloe_Data + + SUBROUTINE FAST_PackIceFloe_Data( 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(IceFloe_Data), 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 = 'FAST_PackIceFloe_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL IceFloe_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL IceFloe_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL IceFloe_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL IceFloe_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL IceFloe_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL IceFloe_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL IceFloe_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL IceFloe_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL IceFloe_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL IceFloe_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL IceFloe_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL IceFloe_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 IceFloe_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 IceFloe_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL IceFloe_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackIceFloe_Data + + SUBROUTINE FAST_UnPackIceFloe_Data( 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(IceFloe_Data), 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 = 'FAST_UnPackIceFloe_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 IceFloe_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 IceFloe_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 IceFloe_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 IceFloe_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 IceFloe_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 IceFloe_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 IceFloe_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 IceFloe_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 IceFloe_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackIceFloe_Data + + SUBROUTINE FAST_CopyMAP_Data( SrcMAP_DataData, DstMAP_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MAP_Data), INTENT(INOUT) :: SrcMAP_DataData + TYPE(MAP_Data), INTENT(INOUT) :: DstMAP_DataData + 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 = 'FAST_CopyMAP_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcMAP_DataData%x,1), UBOUND(SrcMAP_DataData%x,1) + CALL MAP_CopyContState( SrcMAP_DataData%x(i1), DstMAP_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcMAP_DataData%xd,1), UBOUND(SrcMAP_DataData%xd,1) + CALL MAP_CopyDiscState( SrcMAP_DataData%xd(i1), DstMAP_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcMAP_DataData%z,1), UBOUND(SrcMAP_DataData%z,1) + CALL MAP_CopyConstrState( SrcMAP_DataData%z(i1), DstMAP_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL MAP_CopyOtherState( SrcMAP_DataData%OtherSt, DstMAP_DataData%OtherSt, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyParam( SrcMAP_DataData%p, DstMAP_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyInput( SrcMAP_DataData%u, DstMAP_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyOutput( SrcMAP_DataData%y, DstMAP_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyOtherState( SrcMAP_DataData%OtherSt_old, DstMAP_DataData%OtherSt_old, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMAP_DataData%Output)) THEN + i1_l = LBOUND(SrcMAP_DataData%Output,1) + i1_u = UBOUND(SrcMAP_DataData%Output,1) + IF (.NOT. ALLOCATED(DstMAP_DataData%Output)) THEN + ALLOCATE(DstMAP_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMAP_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMAP_DataData%Output,1), UBOUND(SrcMAP_DataData%Output,1) + CALL MAP_CopyOutput( SrcMAP_DataData%Output(i1), DstMAP_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MAP_CopyOutput( SrcMAP_DataData%y_interp, DstMAP_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMAP_DataData%Input)) THEN + i1_l = LBOUND(SrcMAP_DataData%Input,1) + i1_u = UBOUND(SrcMAP_DataData%Input,1) + IF (.NOT. ALLOCATED(DstMAP_DataData%Input)) THEN + ALLOCATE(DstMAP_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMAP_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMAP_DataData%Input,1), UBOUND(SrcMAP_DataData%Input,1) + CALL MAP_CopyInput( SrcMAP_DataData%Input(i1), DstMAP_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMAP_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcMAP_DataData%InputTimes,1) + i1_u = UBOUND(SrcMAP_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstMAP_DataData%InputTimes)) THEN + ALLOCATE(DstMAP_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMAP_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMAP_DataData%InputTimes = SrcMAP_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyMAP_Data + + SUBROUTINE FAST_DestroyMAP_Data( MAP_DataData, ErrStat, ErrMsg ) + TYPE(MAP_Data), INTENT(INOUT) :: MAP_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyMAP_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(MAP_DataData%x,1), UBOUND(MAP_DataData%x,1) + CALL MAP_DestroyContState( MAP_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(MAP_DataData%xd,1), UBOUND(MAP_DataData%xd,1) + CALL MAP_DestroyDiscState( MAP_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(MAP_DataData%z,1), UBOUND(MAP_DataData%z,1) + CALL MAP_DestroyConstrState( MAP_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO + CALL MAP_DestroyOtherState( MAP_DataData%OtherSt, ErrStat, ErrMsg ) + CALL MAP_DestroyParam( MAP_DataData%p, ErrStat, ErrMsg ) + CALL MAP_DestroyInput( MAP_DataData%u, ErrStat, ErrMsg ) + CALL MAP_DestroyOutput( MAP_DataData%y, ErrStat, ErrMsg ) + CALL MAP_DestroyOtherState( MAP_DataData%OtherSt_old, ErrStat, ErrMsg ) +IF (ALLOCATED(MAP_DataData%Output)) THEN +DO i1 = LBOUND(MAP_DataData%Output,1), UBOUND(MAP_DataData%Output,1) + CALL MAP_DestroyOutput( MAP_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MAP_DataData%Output) +ENDIF + CALL MAP_DestroyOutput( MAP_DataData%y_interp, ErrStat, ErrMsg ) +IF (ALLOCATED(MAP_DataData%Input)) THEN +DO i1 = LBOUND(MAP_DataData%Input,1), UBOUND(MAP_DataData%Input,1) + CALL MAP_DestroyInput( MAP_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MAP_DataData%Input) +ENDIF +IF (ALLOCATED(MAP_DataData%InputTimes)) THEN + DEALLOCATE(MAP_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyMAP_Data + + SUBROUTINE FAST_PackMAP_Data( 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(MAP_Data), 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 = 'FAST_PackMAP_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL MAP_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL MAP_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL MAP_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL MAP_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt, ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL MAP_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OtherSt_old: size of buffers for each call to pack subtype + CALL MAP_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_old, ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt_old + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt_old + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt_old + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt_old + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL MAP_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL MAP_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL MAP_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + CALL MAP_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt, ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 MAP_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 MAP_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt_old, ErrStat2, ErrMsg2, OnlySize ) ! OtherSt_old + 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%Output) ) 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%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + 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 + CALL MAP_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL MAP_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackMAP_Data + + SUBROUTINE FAST_UnPackMAP_Data( 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(MAP_Data), 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 = 'FAST_UnPackMAP_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 MAP_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 MAP_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 MAP_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 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 MAP_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt, ErrStat2, ErrMsg2 ) ! OtherSt + 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 MAP_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 MAP_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 MAP_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 MAP_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt_old, ErrStat2, ErrMsg2 ) ! OtherSt_old + 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 ! Output 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%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,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 MAP_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + 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 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 MAP_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 MAP_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackMAP_Data + + SUBROUTINE FAST_CopyFEAMooring_Data( SrcFEAMooring_DataData, DstFEAMooring_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEAMooring_Data), INTENT(INOUT) :: SrcFEAMooring_DataData + TYPE(FEAMooring_Data), INTENT(INOUT) :: DstFEAMooring_DataData + 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 = 'FAST_CopyFEAMooring_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcFEAMooring_DataData%x,1), UBOUND(SrcFEAMooring_DataData%x,1) + CALL FEAM_CopyContState( SrcFEAMooring_DataData%x(i1), DstFEAMooring_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcFEAMooring_DataData%xd,1), UBOUND(SrcFEAMooring_DataData%xd,1) + CALL FEAM_CopyDiscState( SrcFEAMooring_DataData%xd(i1), DstFEAMooring_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcFEAMooring_DataData%z,1), UBOUND(SrcFEAMooring_DataData%z,1) + CALL FEAM_CopyConstrState( SrcFEAMooring_DataData%z(i1), DstFEAMooring_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcFEAMooring_DataData%OtherSt,1), UBOUND(SrcFEAMooring_DataData%OtherSt,1) + CALL FEAM_CopyOtherState( SrcFEAMooring_DataData%OtherSt(i1), DstFEAMooring_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL FEAM_CopyParam( SrcFEAMooring_DataData%p, DstFEAMooring_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FEAM_CopyInput( SrcFEAMooring_DataData%u, DstFEAMooring_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FEAM_CopyOutput( SrcFEAMooring_DataData%y, DstFEAMooring_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FEAM_CopyMisc( SrcFEAMooring_DataData%m, DstFEAMooring_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcFEAMooring_DataData%Input)) THEN + i1_l = LBOUND(SrcFEAMooring_DataData%Input,1) + i1_u = UBOUND(SrcFEAMooring_DataData%Input,1) + IF (.NOT. ALLOCATED(DstFEAMooring_DataData%Input)) THEN + ALLOCATE(DstFEAMooring_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEAMooring_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcFEAMooring_DataData%Input,1), UBOUND(SrcFEAMooring_DataData%Input,1) + CALL FEAM_CopyInput( SrcFEAMooring_DataData%Input(i1), DstFEAMooring_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcFEAMooring_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcFEAMooring_DataData%InputTimes,1) + i1_u = UBOUND(SrcFEAMooring_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstFEAMooring_DataData%InputTimes)) THEN + ALLOCATE(DstFEAMooring_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEAMooring_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFEAMooring_DataData%InputTimes = SrcFEAMooring_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyFEAMooring_Data + + SUBROUTINE FAST_DestroyFEAMooring_Data( FEAMooring_DataData, ErrStat, ErrMsg ) + TYPE(FEAMooring_Data), INTENT(INOUT) :: FEAMooring_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyFEAMooring_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(FEAMooring_DataData%x,1), UBOUND(FEAMooring_DataData%x,1) + CALL FEAM_DestroyContState( FEAMooring_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(FEAMooring_DataData%xd,1), UBOUND(FEAMooring_DataData%xd,1) + CALL FEAM_DestroyDiscState( FEAMooring_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(FEAMooring_DataData%z,1), UBOUND(FEAMooring_DataData%z,1) + CALL FEAM_DestroyConstrState( FEAMooring_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(FEAMooring_DataData%OtherSt,1), UBOUND(FEAMooring_DataData%OtherSt,1) + CALL FEAM_DestroyOtherState( FEAMooring_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL FEAM_DestroyParam( FEAMooring_DataData%p, ErrStat, ErrMsg ) + CALL FEAM_DestroyInput( FEAMooring_DataData%u, ErrStat, ErrMsg ) + CALL FEAM_DestroyOutput( FEAMooring_DataData%y, ErrStat, ErrMsg ) + CALL FEAM_DestroyMisc( FEAMooring_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(FEAMooring_DataData%Input)) THEN +DO i1 = LBOUND(FEAMooring_DataData%Input,1), UBOUND(FEAMooring_DataData%Input,1) + CALL FEAM_DestroyInput( FEAMooring_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(FEAMooring_DataData%Input) +ENDIF +IF (ALLOCATED(FEAMooring_DataData%InputTimes)) THEN + DEALLOCATE(FEAMooring_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyFEAMooring_Data + + SUBROUTINE FAST_PackFEAMooring_Data( 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(FEAMooring_Data), 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 = 'FAST_PackFEAMooring_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL FEAM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL FEAM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL FEAM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL FEAM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL FEAM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL FEAM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL FEAM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL FEAM_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL FEAM_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL FEAM_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL FEAM_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL FEAM_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 FEAM_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 FEAM_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL FEAM_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackFEAMooring_Data + + SUBROUTINE FAST_UnPackFEAMooring_Data( 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(FEAMooring_Data), 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 = 'FAST_UnPackFEAMooring_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 FEAM_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 FEAM_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 FEAM_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 FEAM_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 FEAM_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 FEAM_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 FEAM_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 FEAM_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 FEAM_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackFEAMooring_Data + + SUBROUTINE FAST_CopyMoorDyn_Data( SrcMoorDyn_DataData, DstMoorDyn_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MoorDyn_Data), INTENT(INOUT) :: SrcMoorDyn_DataData + TYPE(MoorDyn_Data), INTENT(INOUT) :: DstMoorDyn_DataData + 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 = 'FAST_CopyMoorDyn_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcMoorDyn_DataData%x,1), UBOUND(SrcMoorDyn_DataData%x,1) + CALL MD_CopyContState( SrcMoorDyn_DataData%x(i1), DstMoorDyn_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcMoorDyn_DataData%xd,1), UBOUND(SrcMoorDyn_DataData%xd,1) + CALL MD_CopyDiscState( SrcMoorDyn_DataData%xd(i1), DstMoorDyn_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcMoorDyn_DataData%z,1), UBOUND(SrcMoorDyn_DataData%z,1) + CALL MD_CopyConstrState( SrcMoorDyn_DataData%z(i1), DstMoorDyn_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcMoorDyn_DataData%OtherSt,1), UBOUND(SrcMoorDyn_DataData%OtherSt,1) + CALL MD_CopyOtherState( SrcMoorDyn_DataData%OtherSt(i1), DstMoorDyn_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL MD_CopyParam( SrcMoorDyn_DataData%p, DstMoorDyn_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MD_CopyInput( SrcMoorDyn_DataData%u, DstMoorDyn_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MD_CopyOutput( SrcMoorDyn_DataData%y, DstMoorDyn_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MD_CopyMisc( SrcMoorDyn_DataData%m, DstMoorDyn_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcMoorDyn_DataData%Input)) THEN + i1_l = LBOUND(SrcMoorDyn_DataData%Input,1) + i1_u = UBOUND(SrcMoorDyn_DataData%Input,1) + IF (.NOT. ALLOCATED(DstMoorDyn_DataData%Input)) THEN + ALLOCATE(DstMoorDyn_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMoorDyn_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMoorDyn_DataData%Input,1), UBOUND(SrcMoorDyn_DataData%Input,1) + CALL MD_CopyInput( SrcMoorDyn_DataData%Input(i1), DstMoorDyn_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMoorDyn_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcMoorDyn_DataData%InputTimes,1) + i1_u = UBOUND(SrcMoorDyn_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstMoorDyn_DataData%InputTimes)) THEN + ALLOCATE(DstMoorDyn_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMoorDyn_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMoorDyn_DataData%InputTimes = SrcMoorDyn_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyMoorDyn_Data + + SUBROUTINE FAST_DestroyMoorDyn_Data( MoorDyn_DataData, ErrStat, ErrMsg ) + TYPE(MoorDyn_Data), INTENT(INOUT) :: MoorDyn_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyMoorDyn_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(MoorDyn_DataData%x,1), UBOUND(MoorDyn_DataData%x,1) + CALL MD_DestroyContState( MoorDyn_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(MoorDyn_DataData%xd,1), UBOUND(MoorDyn_DataData%xd,1) + CALL MD_DestroyDiscState( MoorDyn_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(MoorDyn_DataData%z,1), UBOUND(MoorDyn_DataData%z,1) + CALL MD_DestroyConstrState( MoorDyn_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(MoorDyn_DataData%OtherSt,1), UBOUND(MoorDyn_DataData%OtherSt,1) + CALL MD_DestroyOtherState( MoorDyn_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL MD_DestroyParam( MoorDyn_DataData%p, ErrStat, ErrMsg ) + CALL MD_DestroyInput( MoorDyn_DataData%u, ErrStat, ErrMsg ) + CALL MD_DestroyOutput( MoorDyn_DataData%y, ErrStat, ErrMsg ) + CALL MD_DestroyMisc( MoorDyn_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(MoorDyn_DataData%Input)) THEN +DO i1 = LBOUND(MoorDyn_DataData%Input,1), UBOUND(MoorDyn_DataData%Input,1) + CALL MD_DestroyInput( MoorDyn_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MoorDyn_DataData%Input) +ENDIF +IF (ALLOCATED(MoorDyn_DataData%InputTimes)) THEN + DEALLOCATE(MoorDyn_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyMoorDyn_Data + + SUBROUTINE FAST_PackMoorDyn_Data( 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(MoorDyn_Data), 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 = 'FAST_PackMoorDyn_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL MD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL MD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL MD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL MD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL MD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL MD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL MD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL MD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL MD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL MD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL MD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL MD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 MD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 MD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL MD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackMoorDyn_Data + + SUBROUTINE FAST_UnPackMoorDyn_Data( 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(MoorDyn_Data), 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 = 'FAST_UnPackMoorDyn_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 MD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 MD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 MD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 MD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 MD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 MD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 MD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 MD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 MD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackMoorDyn_Data + + SUBROUTINE FAST_CopyOrcaFlex_Data( SrcOrcaFlex_DataData, DstOrcaFlex_DataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OrcaFlex_Data), INTENT(INOUT) :: SrcOrcaFlex_DataData + TYPE(OrcaFlex_Data), INTENT(INOUT) :: DstOrcaFlex_DataData + 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 = 'FAST_CopyOrcaFlex_Data' +! + ErrStat = ErrID_None + ErrMsg = "" + DO i1 = LBOUND(SrcOrcaFlex_DataData%x,1), UBOUND(SrcOrcaFlex_DataData%x,1) + CALL Orca_CopyContState( SrcOrcaFlex_DataData%x(i1), DstOrcaFlex_DataData%x(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcOrcaFlex_DataData%xd,1), UBOUND(SrcOrcaFlex_DataData%xd,1) + CALL Orca_CopyDiscState( SrcOrcaFlex_DataData%xd(i1), DstOrcaFlex_DataData%xd(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcOrcaFlex_DataData%z,1), UBOUND(SrcOrcaFlex_DataData%z,1) + CALL Orca_CopyConstrState( SrcOrcaFlex_DataData%z(i1), DstOrcaFlex_DataData%z(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + DO i1 = LBOUND(SrcOrcaFlex_DataData%OtherSt,1), UBOUND(SrcOrcaFlex_DataData%OtherSt,1) + CALL Orca_CopyOtherState( SrcOrcaFlex_DataData%OtherSt(i1), DstOrcaFlex_DataData%OtherSt(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO + CALL Orca_CopyParam( SrcOrcaFlex_DataData%p, DstOrcaFlex_DataData%p, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Orca_CopyInput( SrcOrcaFlex_DataData%u, DstOrcaFlex_DataData%u, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Orca_CopyOutput( SrcOrcaFlex_DataData%y, DstOrcaFlex_DataData%y, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Orca_CopyMisc( SrcOrcaFlex_DataData%m, DstOrcaFlex_DataData%m, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOrcaFlex_DataData%Input)) THEN + i1_l = LBOUND(SrcOrcaFlex_DataData%Input,1) + i1_u = UBOUND(SrcOrcaFlex_DataData%Input,1) + IF (.NOT. ALLOCATED(DstOrcaFlex_DataData%Input)) THEN + ALLOCATE(DstOrcaFlex_DataData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOrcaFlex_DataData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOrcaFlex_DataData%Input,1), UBOUND(SrcOrcaFlex_DataData%Input,1) + CALL Orca_CopyInput( SrcOrcaFlex_DataData%Input(i1), DstOrcaFlex_DataData%Input(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcOrcaFlex_DataData%InputTimes)) THEN + i1_l = LBOUND(SrcOrcaFlex_DataData%InputTimes,1) + i1_u = UBOUND(SrcOrcaFlex_DataData%InputTimes,1) + IF (.NOT. ALLOCATED(DstOrcaFlex_DataData%InputTimes)) THEN + ALLOCATE(DstOrcaFlex_DataData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOrcaFlex_DataData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOrcaFlex_DataData%InputTimes = SrcOrcaFlex_DataData%InputTimes +ENDIF + END SUBROUTINE FAST_CopyOrcaFlex_Data + + SUBROUTINE FAST_DestroyOrcaFlex_Data( OrcaFlex_DataData, ErrStat, ErrMsg ) + TYPE(OrcaFlex_Data), INTENT(INOUT) :: OrcaFlex_DataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyOrcaFlex_Data' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +DO i1 = LBOUND(OrcaFlex_DataData%x,1), UBOUND(OrcaFlex_DataData%x,1) + CALL Orca_DestroyContState( OrcaFlex_DataData%x(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(OrcaFlex_DataData%xd,1), UBOUND(OrcaFlex_DataData%xd,1) + CALL Orca_DestroyDiscState( OrcaFlex_DataData%xd(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(OrcaFlex_DataData%z,1), UBOUND(OrcaFlex_DataData%z,1) + CALL Orca_DestroyConstrState( OrcaFlex_DataData%z(i1), ErrStat, ErrMsg ) +ENDDO +DO i1 = LBOUND(OrcaFlex_DataData%OtherSt,1), UBOUND(OrcaFlex_DataData%OtherSt,1) + CALL Orca_DestroyOtherState( OrcaFlex_DataData%OtherSt(i1), ErrStat, ErrMsg ) +ENDDO + CALL Orca_DestroyParam( OrcaFlex_DataData%p, ErrStat, ErrMsg ) + CALL Orca_DestroyInput( OrcaFlex_DataData%u, ErrStat, ErrMsg ) + CALL Orca_DestroyOutput( OrcaFlex_DataData%y, ErrStat, ErrMsg ) + CALL Orca_DestroyMisc( OrcaFlex_DataData%m, ErrStat, ErrMsg ) +IF (ALLOCATED(OrcaFlex_DataData%Input)) THEN +DO i1 = LBOUND(OrcaFlex_DataData%Input,1), UBOUND(OrcaFlex_DataData%Input,1) + CALL Orca_DestroyInput( OrcaFlex_DataData%Input(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OrcaFlex_DataData%Input) +ENDIF +IF (ALLOCATED(OrcaFlex_DataData%InputTimes)) THEN + DEALLOCATE(OrcaFlex_DataData%InputTimes) +ENDIF + END SUBROUTINE FAST_DestroyOrcaFlex_Data + + SUBROUTINE FAST_PackOrcaFlex_Data( 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(OrcaFlex_Data), 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 = 'FAST_PackOrcaFlex_Data' + ! 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) + DO i1 = LBOUND(InData%x,1), UBOUND(InData%x,1) + Int_BufSz = Int_BufSz + 3 ! x: size of buffers for each call to pack subtype + CALL Orca_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, .TRUE. ) ! x + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! x + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! x + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! x + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + Int_BufSz = Int_BufSz + 3 ! xd: size of buffers for each call to pack subtype + CALL Orca_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xd + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xd + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xd + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xd + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + Int_BufSz = Int_BufSz + 3 ! z: size of buffers for each call to pack subtype + CALL Orca_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, .TRUE. ) ! z + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! z + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! z + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! z + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + Int_BufSz = Int_BufSz + 3 ! OtherSt: size of buffers for each call to pack subtype + CALL Orca_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OtherSt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OtherSt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OtherSt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OtherSt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + Int_BufSz = Int_BufSz + 3 ! p: size of buffers for each call to pack subtype + CALL Orca_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, .TRUE. ) ! p + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u: size of buffers for each call to pack subtype + CALL Orca_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, .TRUE. ) ! u + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y: size of buffers for each call to pack subtype + CALL Orca_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, .TRUE. ) ! y + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m: size of buffers for each call to pack subtype + CALL Orca_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, .TRUE. ) ! m + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Input allocated yes/no + IF ( ALLOCATED(InData%Input) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Input upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + Int_BufSz = Int_BufSz + 3 ! Input: size of buffers for each call to pack subtype + CALL Orca_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Input + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Input + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Input + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Input + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no + IF ( ALLOCATED(InData%InputTimes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%InputTimes) ! InputTimes + 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%x,1), UBOUND(InData%x,1) + CALL Orca_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%x(i1), ErrStat2, ErrMsg2, OnlySize ) ! x + 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 + DO i1 = LBOUND(InData%xd,1), UBOUND(InData%xd,1) + CALL Orca_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%xd(i1), ErrStat2, ErrMsg2, OnlySize ) ! xd + 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 + DO i1 = LBOUND(InData%z,1), UBOUND(InData%z,1) + CALL Orca_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%z(i1), ErrStat2, ErrMsg2, OnlySize ) ! z + 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 + DO i1 = LBOUND(InData%OtherSt,1), UBOUND(InData%OtherSt,1) + CALL Orca_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%OtherSt(i1), ErrStat2, ErrMsg2, OnlySize ) ! OtherSt + 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 + CALL Orca_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p, ErrStat2, ErrMsg2, OnlySize ) ! p + 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 Orca_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u, ErrStat2, ErrMsg2, OnlySize ) ! u + 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 Orca_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y, ErrStat2, ErrMsg2, OnlySize ) ! y + 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 Orca_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m, ErrStat2, ErrMsg2, OnlySize ) ! m + 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%Input) ) 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%Input,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Input,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Input,1), UBOUND(InData%Input,1) + CALL Orca_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%Input(i1), ErrStat2, ErrMsg2, OnlySize ) ! Input + 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%InputTimes) ) 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%InputTimes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InputTimes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%InputTimes,1), UBOUND(InData%InputTimes,1) + DbKiBuf(Db_Xferred) = InData%InputTimes(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_PackOrcaFlex_Data + + SUBROUTINE FAST_UnPackOrcaFlex_Data( 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(OrcaFlex_Data), 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 = 'FAST_UnPackOrcaFlex_Data' + ! 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%x,1) + i1_u = UBOUND(OutData%x,1) + DO i1 = LBOUND(OutData%x,1), UBOUND(OutData%x,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 Orca_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%x(i1), ErrStat2, ErrMsg2 ) ! x + 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 DO + i1_l = LBOUND(OutData%xd,1) + i1_u = UBOUND(OutData%xd,1) + DO i1 = LBOUND(OutData%xd,1), UBOUND(OutData%xd,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 Orca_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%xd(i1), ErrStat2, ErrMsg2 ) ! xd + 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 DO + i1_l = LBOUND(OutData%z,1) + i1_u = UBOUND(OutData%z,1) + DO i1 = LBOUND(OutData%z,1), UBOUND(OutData%z,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 Orca_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%z(i1), ErrStat2, ErrMsg2 ) ! z + 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 DO + i1_l = LBOUND(OutData%OtherSt,1) + i1_u = UBOUND(OutData%OtherSt,1) + DO i1 = LBOUND(OutData%OtherSt,1), UBOUND(OutData%OtherSt,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 Orca_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%OtherSt(i1), ErrStat2, ErrMsg2 ) ! OtherSt + 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 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 Orca_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p, ErrStat2, ErrMsg2 ) ! p + 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 Orca_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u, ErrStat2, ErrMsg2 ) ! u + 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 Orca_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y, ErrStat2, ErrMsg2 ) ! y + 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 Orca_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m, ErrStat2, ErrMsg2 ) ! m + 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 ! Input 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%Input)) DEALLOCATE(OutData%Input) + ALLOCATE(OutData%Input(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Input.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Input,1), UBOUND(OutData%Input,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 Orca_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%Input(i1), ErrStat2, ErrMsg2 ) ! Input + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes 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%InputTimes)) DEALLOCATE(OutData%InputTimes) + ALLOCATE(OutData%InputTimes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%InputTimes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%InputTimes,1), UBOUND(OutData%InputTimes,1) + OutData%InputTimes(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + END SUBROUTINE FAST_UnPackOrcaFlex_Data + + SUBROUTINE FAST_CopyModuleMapType( SrcModuleMapTypeData, DstModuleMapTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: SrcModuleMapTypeData + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: DstModuleMapTypeData + 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 = 'FAST_CopyModuleMapType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcModuleMapTypeData%ED_P_2_BD_P)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%ED_P_2_BD_P,1) + i1_u = UBOUND(SrcModuleMapTypeData%ED_P_2_BD_P,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%ED_P_2_BD_P)) THEN + ALLOCATE(DstModuleMapTypeData%ED_P_2_BD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%ED_P_2_BD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%ED_P_2_BD_P,1), UBOUND(SrcModuleMapTypeData%ED_P_2_BD_P,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_BD_P(i1), DstModuleMapTypeData%ED_P_2_BD_P(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%BD_P_2_ED_P)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%BD_P_2_ED_P,1) + i1_u = UBOUND(SrcModuleMapTypeData%BD_P_2_ED_P,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%BD_P_2_ED_P)) THEN + ALLOCATE(DstModuleMapTypeData%BD_P_2_ED_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%BD_P_2_ED_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%BD_P_2_ED_P,1), UBOUND(SrcModuleMapTypeData%BD_P_2_ED_P,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%BD_P_2_ED_P(i1), DstModuleMapTypeData%BD_P_2_ED_P(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%ED_P_2_BD_P_Hub)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%ED_P_2_BD_P_Hub,1) + i1_u = UBOUND(SrcModuleMapTypeData%ED_P_2_BD_P_Hub,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%ED_P_2_BD_P_Hub)) THEN + ALLOCATE(DstModuleMapTypeData%ED_P_2_BD_P_Hub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%ED_P_2_BD_P_Hub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%ED_P_2_BD_P_Hub,1), UBOUND(SrcModuleMapTypeData%ED_P_2_BD_P_Hub,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_BD_P_Hub(i1), DstModuleMapTypeData%ED_P_2_BD_P_Hub(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_W_P, DstModuleMapTypeData%ED_P_2_HD_W_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_W_P_2_ED_P, DstModuleMapTypeData%HD_W_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_M_P, DstModuleMapTypeData%ED_P_2_HD_M_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_P_2_ED_P, DstModuleMapTypeData%HD_M_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_M_L, DstModuleMapTypeData%ED_P_2_HD_M_L, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_L_2_ED_P, DstModuleMapTypeData%HD_M_L_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_Mooring_P, DstModuleMapTypeData%ED_P_2_Mooring_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%Mooring_P_2_ED_P, DstModuleMapTypeData%Mooring_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_SD_TP, DstModuleMapTypeData%ED_P_2_SD_TP, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_TP_2_ED_P, DstModuleMapTypeData%SD_TP_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_HD_M_P, DstModuleMapTypeData%SD_P_2_HD_M_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_P_2_SD_P, DstModuleMapTypeData%HD_M_P_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_HD_M_L, DstModuleMapTypeData%SD_P_2_HD_M_L, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_L_2_SD_P, DstModuleMapTypeData%HD_M_L_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_SrvD_P_N, DstModuleMapTypeData%ED_P_2_SrvD_P_N, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SrvD_P_2_ED_P_N, DstModuleMapTypeData%SrvD_P_2_ED_P_N, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_L_2_SrvD_P_T, DstModuleMapTypeData%ED_L_2_SrvD_P_T, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SrvD_P_2_ED_P_T, DstModuleMapTypeData%SrvD_P_2_ED_P_T, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcModuleMapTypeData%BDED_L_2_AD_L_B)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%BDED_L_2_AD_L_B,1) + i1_u = UBOUND(SrcModuleMapTypeData%BDED_L_2_AD_L_B,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%BDED_L_2_AD_L_B)) THEN + ALLOCATE(DstModuleMapTypeData%BDED_L_2_AD_L_B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%BDED_L_2_AD_L_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%BDED_L_2_AD_L_B,1), UBOUND(SrcModuleMapTypeData%BDED_L_2_AD_L_B,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%BDED_L_2_AD_L_B(i1), DstModuleMapTypeData%BDED_L_2_AD_L_B(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%AD_L_2_BDED_B)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%AD_L_2_BDED_B,1) + i1_u = UBOUND(SrcModuleMapTypeData%AD_L_2_BDED_B,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%AD_L_2_BDED_B)) THEN + ALLOCATE(DstModuleMapTypeData%AD_L_2_BDED_B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%AD_L_2_BDED_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%AD_L_2_BDED_B,1), UBOUND(SrcModuleMapTypeData%AD_L_2_BDED_B,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%AD_L_2_BDED_B(i1), DstModuleMapTypeData%AD_L_2_BDED_B(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%BD_L_2_BD_L)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%BD_L_2_BD_L,1) + i1_u = UBOUND(SrcModuleMapTypeData%BD_L_2_BD_L,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%BD_L_2_BD_L)) THEN + ALLOCATE(DstModuleMapTypeData%BD_L_2_BD_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%BD_L_2_BD_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%BD_L_2_BD_L,1), UBOUND(SrcModuleMapTypeData%BD_L_2_BD_L,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%BD_L_2_BD_L(i1), DstModuleMapTypeData%BD_L_2_BD_L(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_L_2_AD_L_T, DstModuleMapTypeData%ED_L_2_AD_L_T, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%AD_L_2_ED_P_T, DstModuleMapTypeData%AD_L_2_ED_P_T, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcModuleMapTypeData%ED_P_2_AD_P_R)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%ED_P_2_AD_P_R,1) + i1_u = UBOUND(SrcModuleMapTypeData%ED_P_2_AD_P_R,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%ED_P_2_AD_P_R)) THEN + ALLOCATE(DstModuleMapTypeData%ED_P_2_AD_P_R(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%ED_P_2_AD_P_R.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%ED_P_2_AD_P_R,1), UBOUND(SrcModuleMapTypeData%ED_P_2_AD_P_R,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_AD_P_R(i1), DstModuleMapTypeData%ED_P_2_AD_P_R(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_AD_P_H, DstModuleMapTypeData%ED_P_2_AD_P_H, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%IceF_P_2_SD_P, DstModuleMapTypeData%IceF_P_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_IceF_P, DstModuleMapTypeData%SD_P_2_IceF_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcModuleMapTypeData%IceD_P_2_SD_P)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%IceD_P_2_SD_P,1) + i1_u = UBOUND(SrcModuleMapTypeData%IceD_P_2_SD_P,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%IceD_P_2_SD_P)) THEN + ALLOCATE(DstModuleMapTypeData%IceD_P_2_SD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%IceD_P_2_SD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%IceD_P_2_SD_P,1), UBOUND(SrcModuleMapTypeData%IceD_P_2_SD_P,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%IceD_P_2_SD_P(i1), DstModuleMapTypeData%IceD_P_2_SD_P(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%SD_P_2_IceD_P)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%SD_P_2_IceD_P,1) + i1_u = UBOUND(SrcModuleMapTypeData%SD_P_2_IceD_P,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%SD_P_2_IceD_P)) THEN + ALLOCATE(DstModuleMapTypeData%SD_P_2_IceD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%SD_P_2_IceD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%SD_P_2_IceD_P,1), UBOUND(SrcModuleMapTypeData%SD_P_2_IceD_P,1) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_IceD_P(i1), DstModuleMapTypeData%SD_P_2_IceD_P(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%Jacobian_Opt1)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%Jacobian_Opt1,1) + i1_u = UBOUND(SrcModuleMapTypeData%Jacobian_Opt1,1) + i2_l = LBOUND(SrcModuleMapTypeData%Jacobian_Opt1,2) + i2_u = UBOUND(SrcModuleMapTypeData%Jacobian_Opt1,2) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%Jacobian_Opt1)) THEN + ALLOCATE(DstModuleMapTypeData%Jacobian_Opt1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%Jacobian_Opt1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstModuleMapTypeData%Jacobian_Opt1 = SrcModuleMapTypeData%Jacobian_Opt1 +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%Jacobian_pivot)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%Jacobian_pivot,1) + i1_u = UBOUND(SrcModuleMapTypeData%Jacobian_pivot,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%Jacobian_pivot)) THEN + ALLOCATE(DstModuleMapTypeData%Jacobian_pivot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%Jacobian_pivot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstModuleMapTypeData%Jacobian_pivot = SrcModuleMapTypeData%Jacobian_pivot +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%Jac_u_indx,1) + i1_u = UBOUND(SrcModuleMapTypeData%Jac_u_indx,1) + i2_l = LBOUND(SrcModuleMapTypeData%Jac_u_indx,2) + i2_u = UBOUND(SrcModuleMapTypeData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%Jac_u_indx)) THEN + ALLOCATE(DstModuleMapTypeData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstModuleMapTypeData%Jac_u_indx = SrcModuleMapTypeData%Jac_u_indx +ENDIF + CALL MeshCopy( SrcModuleMapTypeData%u_ED_PlatformPtMesh, DstModuleMapTypeData%u_ED_PlatformPtMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_ED_PlatformPtMesh_2, DstModuleMapTypeData%u_ED_PlatformPtMesh_2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_SD_TPMesh, DstModuleMapTypeData%u_SD_TPMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_SD_LMesh, DstModuleMapTypeData%u_SD_LMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_SD_LMesh_2, DstModuleMapTypeData%u_SD_LMesh_2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_HD_M_LumpedMesh, DstModuleMapTypeData%u_HD_M_LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_HD_M_DistribMesh, DstModuleMapTypeData%u_HD_M_DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_HD_Mesh, DstModuleMapTypeData%u_HD_Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_ED_HubPtLoad, DstModuleMapTypeData%u_ED_HubPtLoad, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_ED_HubPtLoad_2, DstModuleMapTypeData%u_ED_HubPtLoad_2, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcModuleMapTypeData%u_BD_RootMotion)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%u_BD_RootMotion,1) + i1_u = UBOUND(SrcModuleMapTypeData%u_BD_RootMotion,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%u_BD_RootMotion)) THEN + ALLOCATE(DstModuleMapTypeData%u_BD_RootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%u_BD_RootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%u_BD_RootMotion,1), UBOUND(SrcModuleMapTypeData%u_BD_RootMotion,1) + CALL MeshCopy( SrcModuleMapTypeData%u_BD_RootMotion(i1), DstModuleMapTypeData%u_BD_RootMotion(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcModuleMapTypeData%y_BD_BldMotion_4Loads)) THEN + i1_l = LBOUND(SrcModuleMapTypeData%y_BD_BldMotion_4Loads,1) + i1_u = UBOUND(SrcModuleMapTypeData%y_BD_BldMotion_4Loads,1) + IF (.NOT. ALLOCATED(DstModuleMapTypeData%y_BD_BldMotion_4Loads)) THEN + ALLOCATE(DstModuleMapTypeData%y_BD_BldMotion_4Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstModuleMapTypeData%y_BD_BldMotion_4Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcModuleMapTypeData%y_BD_BldMotion_4Loads,1), UBOUND(SrcModuleMapTypeData%y_BD_BldMotion_4Loads,1) + CALL MeshCopy( SrcModuleMapTypeData%y_BD_BldMotion_4Loads(i1), DstModuleMapTypeData%y_BD_BldMotion_4Loads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL MeshCopy( SrcModuleMapTypeData%u_Orca_PtfmMesh, DstModuleMapTypeData%u_Orca_PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcModuleMapTypeData%u_ExtPtfm_PtfmMesh, DstModuleMapTypeData%u_ExtPtfm_PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyModuleMapType + + SUBROUTINE FAST_DestroyModuleMapType( ModuleMapTypeData, ErrStat, ErrMsg ) + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: ModuleMapTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyModuleMapType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ModuleMapTypeData%ED_P_2_BD_P)) THEN +DO i1 = LBOUND(ModuleMapTypeData%ED_P_2_BD_P,1), UBOUND(ModuleMapTypeData%ED_P_2_BD_P,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_BD_P(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%ED_P_2_BD_P) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%BD_P_2_ED_P)) THEN +DO i1 = LBOUND(ModuleMapTypeData%BD_P_2_ED_P,1), UBOUND(ModuleMapTypeData%BD_P_2_ED_P,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%BD_P_2_ED_P(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%BD_P_2_ED_P) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%ED_P_2_BD_P_Hub)) THEN +DO i1 = LBOUND(ModuleMapTypeData%ED_P_2_BD_P_Hub,1), UBOUND(ModuleMapTypeData%ED_P_2_BD_P_Hub,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_BD_P_Hub(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%ED_P_2_BD_P_Hub) +ENDIF + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_W_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_W_P_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_M_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_P_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_M_L, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_L_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%Mooring_P_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_SD_TP, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_TP_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_HD_M_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_P_2_SD_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_HD_M_L, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_L_2_SD_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_SrvD_P_N, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SrvD_P_2_ED_P_N, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_L_2_SrvD_P_T, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SrvD_P_2_ED_P_T, ErrStat, ErrMsg ) +IF (ALLOCATED(ModuleMapTypeData%BDED_L_2_AD_L_B)) THEN +DO i1 = LBOUND(ModuleMapTypeData%BDED_L_2_AD_L_B,1), UBOUND(ModuleMapTypeData%BDED_L_2_AD_L_B,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%BDED_L_2_AD_L_B(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%BDED_L_2_AD_L_B) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%AD_L_2_BDED_B)) THEN +DO i1 = LBOUND(ModuleMapTypeData%AD_L_2_BDED_B,1), UBOUND(ModuleMapTypeData%AD_L_2_BDED_B,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%AD_L_2_BDED_B(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%AD_L_2_BDED_B) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%BD_L_2_BD_L)) THEN +DO i1 = LBOUND(ModuleMapTypeData%BD_L_2_BD_L,1), UBOUND(ModuleMapTypeData%BD_L_2_BD_L,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%BD_L_2_BD_L(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%BD_L_2_BD_L) +ENDIF + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_L_2_AD_L_T, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%AD_L_2_ED_P_T, ErrStat, ErrMsg ) +IF (ALLOCATED(ModuleMapTypeData%ED_P_2_AD_P_R)) THEN +DO i1 = LBOUND(ModuleMapTypeData%ED_P_2_AD_P_R,1), UBOUND(ModuleMapTypeData%ED_P_2_AD_P_R,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_AD_P_R(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%ED_P_2_AD_P_R) +ENDIF + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_AD_P_H, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%IceF_P_2_SD_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_IceF_P, ErrStat, ErrMsg ) +IF (ALLOCATED(ModuleMapTypeData%IceD_P_2_SD_P)) THEN +DO i1 = LBOUND(ModuleMapTypeData%IceD_P_2_SD_P,1), UBOUND(ModuleMapTypeData%IceD_P_2_SD_P,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%IceD_P_2_SD_P(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%IceD_P_2_SD_P) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%SD_P_2_IceD_P)) THEN +DO i1 = LBOUND(ModuleMapTypeData%SD_P_2_IceD_P,1), UBOUND(ModuleMapTypeData%SD_P_2_IceD_P,1) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_IceD_P(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%SD_P_2_IceD_P) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%Jacobian_Opt1)) THEN + DEALLOCATE(ModuleMapTypeData%Jacobian_Opt1) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%Jacobian_pivot)) THEN + DEALLOCATE(ModuleMapTypeData%Jacobian_pivot) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%Jac_u_indx)) THEN + DEALLOCATE(ModuleMapTypeData%Jac_u_indx) +ENDIF + CALL MeshDestroy( ModuleMapTypeData%u_ED_PlatformPtMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_ED_PlatformPtMesh_2, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_SD_TPMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_SD_LMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_SD_LMesh_2, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_HD_M_LumpedMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_HD_M_DistribMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_HD_Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_ED_HubPtLoad, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_ED_HubPtLoad_2, ErrStat, ErrMsg ) +IF (ALLOCATED(ModuleMapTypeData%u_BD_RootMotion)) THEN +DO i1 = LBOUND(ModuleMapTypeData%u_BD_RootMotion,1), UBOUND(ModuleMapTypeData%u_BD_RootMotion,1) + CALL MeshDestroy( ModuleMapTypeData%u_BD_RootMotion(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%u_BD_RootMotion) +ENDIF +IF (ALLOCATED(ModuleMapTypeData%y_BD_BldMotion_4Loads)) THEN +DO i1 = LBOUND(ModuleMapTypeData%y_BD_BldMotion_4Loads,1), UBOUND(ModuleMapTypeData%y_BD_BldMotion_4Loads,1) + CALL MeshDestroy( ModuleMapTypeData%y_BD_BldMotion_4Loads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ModuleMapTypeData%y_BD_BldMotion_4Loads) +ENDIF + CALL MeshDestroy( ModuleMapTypeData%u_Orca_PtfmMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_ExtPtfm_PtfmMesh, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyModuleMapType + + SUBROUTINE FAST_PackModuleMapType( 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(FAST_ModuleMapType), 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 = 'FAST_PackModuleMapType' + ! 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 ! ED_P_2_BD_P allocated yes/no + IF ( ALLOCATED(InData%ED_P_2_BD_P) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ED_P_2_BD_P upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%ED_P_2_BD_P,1), UBOUND(InData%ED_P_2_BD_P,1) + Int_BufSz = Int_BufSz + 3 ! ED_P_2_BD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_BD_P(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_BD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_BD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_BD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_BD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BD_P_2_ED_P allocated yes/no + IF ( ALLOCATED(InData%BD_P_2_ED_P) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BD_P_2_ED_P upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BD_P_2_ED_P,1), UBOUND(InData%BD_P_2_ED_P,1) + Int_BufSz = Int_BufSz + 3 ! BD_P_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BD_P_2_ED_P(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BD_P_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BD_P_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BD_P_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BD_P_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ED_P_2_BD_P_Hub allocated yes/no + IF ( ALLOCATED(InData%ED_P_2_BD_P_Hub) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ED_P_2_BD_P_Hub upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ED_P_2_BD_P_Hub,1), UBOUND(InData%ED_P_2_BD_P_Hub,1) + Int_BufSz = Int_BufSz + 3 ! ED_P_2_BD_P_Hub: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_BD_P_Hub(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_BD_P_Hub + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_BD_P_Hub + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_BD_P_Hub + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_BD_P_Hub + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_W_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_W_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_HD_W_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_HD_W_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_HD_W_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_W_P_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_W_P_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_W_P_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_W_P_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_W_P_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_M_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_M_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_HD_M_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_HD_M_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_HD_M_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_M_P_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_P_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_M_P_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_M_P_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_M_P_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_M_L: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_M_L + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_HD_M_L + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_HD_M_L + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_HD_M_L + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_M_L_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_L_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_M_L_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_M_L_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_M_L_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_Mooring_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_Mooring_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_Mooring_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_Mooring_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_Mooring_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Mooring_P_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! Mooring_P_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mooring_P_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mooring_P_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mooring_P_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_SD_TP: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_SD_TP, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_SD_TP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_SD_TP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_SD_TP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_SD_TP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SD_TP_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! SD_TP_2_ED_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD_TP_2_ED_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD_TP_2_ED_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD_TP_2_ED_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SD_P_2_HD_M_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_HD_M_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_HD_M_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_HD_M_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_HD_M_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_M_P_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_P_2_SD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_M_P_2_SD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_M_P_2_SD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_M_P_2_SD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SD_P_2_HD_M_L: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_HD_M_L + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_HD_M_L + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_HD_M_L + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_HD_M_L + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD_M_L_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_L_2_SD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD_M_L_2_SD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD_M_L_2_SD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD_M_L_2_SD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_SrvD_P_N: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_SrvD_P_N + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_SrvD_P_N + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_SrvD_P_N + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_SrvD_P_N + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SrvD_P_2_ED_P_N: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2, .TRUE. ) ! SrvD_P_2_ED_P_N + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SrvD_P_2_ED_P_N + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SrvD_P_2_ED_P_N + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SrvD_P_2_ED_P_N + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED_L_2_SrvD_P_T: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2, .TRUE. ) ! ED_L_2_SrvD_P_T + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_L_2_SrvD_P_T + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_L_2_SrvD_P_T + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_L_2_SrvD_P_T + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SrvD_P_2_ED_P_T: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2, .TRUE. ) ! SrvD_P_2_ED_P_T + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SrvD_P_2_ED_P_T + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SrvD_P_2_ED_P_T + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SrvD_P_2_ED_P_T + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! BDED_L_2_AD_L_B allocated yes/no + IF ( ALLOCATED(InData%BDED_L_2_AD_L_B) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BDED_L_2_AD_L_B upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BDED_L_2_AD_L_B,1), UBOUND(InData%BDED_L_2_AD_L_B,1) + Int_BufSz = Int_BufSz + 3 ! BDED_L_2_AD_L_B: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BDED_L_2_AD_L_B(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BDED_L_2_AD_L_B + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BDED_L_2_AD_L_B + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BDED_L_2_AD_L_B + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BDED_L_2_AD_L_B + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! AD_L_2_BDED_B allocated yes/no + IF ( ALLOCATED(InData%AD_L_2_BDED_B) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AD_L_2_BDED_B upper/lower bounds for each dimension + DO i1 = LBOUND(InData%AD_L_2_BDED_B,1), UBOUND(InData%AD_L_2_BDED_B,1) + Int_BufSz = Int_BufSz + 3 ! AD_L_2_BDED_B: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%AD_L_2_BDED_B(i1), ErrStat2, ErrMsg2, .TRUE. ) ! AD_L_2_BDED_B + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AD_L_2_BDED_B + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AD_L_2_BDED_B + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AD_L_2_BDED_B + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! BD_L_2_BD_L allocated yes/no + IF ( ALLOCATED(InData%BD_L_2_BD_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BD_L_2_BD_L upper/lower bounds for each dimension + DO i1 = LBOUND(InData%BD_L_2_BD_L,1), UBOUND(InData%BD_L_2_BD_L,1) + Int_BufSz = Int_BufSz + 3 ! BD_L_2_BD_L: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BD_L_2_BD_L(i1), ErrStat2, ErrMsg2, .TRUE. ) ! BD_L_2_BD_L + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BD_L_2_BD_L + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BD_L_2_BD_L + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BD_L_2_BD_L + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! ED_L_2_AD_L_T: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2, .TRUE. ) ! ED_L_2_AD_L_T + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_L_2_AD_L_T + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_L_2_AD_L_T + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_L_2_AD_L_T + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AD_L_2_ED_P_T: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2, .TRUE. ) ! AD_L_2_ED_P_T + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AD_L_2_ED_P_T + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AD_L_2_ED_P_T + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AD_L_2_ED_P_T + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! ED_P_2_AD_P_R allocated yes/no + IF ( ALLOCATED(InData%ED_P_2_AD_P_R) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ED_P_2_AD_P_R upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ED_P_2_AD_P_R,1), UBOUND(InData%ED_P_2_AD_P_R,1) + Int_BufSz = Int_BufSz + 3 ! ED_P_2_AD_P_R: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_AD_P_R(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_AD_P_R + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_AD_P_R + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_AD_P_R + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_AD_P_R + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_AD_P_H: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_AD_P_H + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_AD_P_H + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_AD_P_H + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_AD_P_H + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IceF_P_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%IceF_P_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! IceF_P_2_SD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IceF_P_2_SD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IceF_P_2_SD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IceF_P_2_SD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SD_P_2_IceF_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_IceF_P, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_IceF_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_IceF_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_IceF_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_IceF_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! IceD_P_2_SD_P allocated yes/no + IF ( ALLOCATED(InData%IceD_P_2_SD_P) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IceD_P_2_SD_P upper/lower bounds for each dimension + DO i1 = LBOUND(InData%IceD_P_2_SD_P,1), UBOUND(InData%IceD_P_2_SD_P,1) + Int_BufSz = Int_BufSz + 3 ! IceD_P_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%IceD_P_2_SD_P(i1), ErrStat2, ErrMsg2, .TRUE. ) ! IceD_P_2_SD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IceD_P_2_SD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IceD_P_2_SD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IceD_P_2_SD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! SD_P_2_IceD_P allocated yes/no + IF ( ALLOCATED(InData%SD_P_2_IceD_P) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SD_P_2_IceD_P upper/lower bounds for each dimension + DO i1 = LBOUND(InData%SD_P_2_IceD_P,1), UBOUND(InData%SD_P_2_IceD_P,1) + Int_BufSz = Int_BufSz + 3 ! SD_P_2_IceD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_IceD_P(i1), ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_IceD_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_IceD_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_IceD_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_IceD_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Jacobian_Opt1 allocated yes/no + IF ( ALLOCATED(InData%Jacobian_Opt1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jacobian_Opt1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Jacobian_Opt1) ! Jacobian_Opt1 + END IF + Int_BufSz = Int_BufSz + 1 ! Jacobian_pivot allocated yes/no + IF ( ALLOCATED(InData%Jacobian_pivot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Jacobian_pivot upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jacobian_pivot) ! Jacobian_pivot + END IF + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 3 ! u_ED_PlatformPtMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_ED_PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_ED_PlatformPtMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ED_PlatformPtMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ED_PlatformPtMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ED_PlatformPtMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_ED_PlatformPtMesh_2: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_ED_PlatformPtMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_ED_PlatformPtMesh_2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ED_PlatformPtMesh_2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ED_PlatformPtMesh_2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ED_PlatformPtMesh_2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_SD_TPMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_SD_TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_SD_TPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_SD_TPMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_SD_TPMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_SD_TPMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_SD_LMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_SD_LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_SD_LMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_SD_LMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_SD_LMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_SD_LMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_SD_LMesh_2: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_SD_LMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_SD_LMesh_2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_SD_LMesh_2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_SD_LMesh_2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_SD_LMesh_2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_HD_M_LumpedMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_M_LumpedMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_HD_M_LumpedMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_HD_M_LumpedMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_HD_M_LumpedMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_HD_M_DistribMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_M_DistribMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_HD_M_DistribMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_HD_M_DistribMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_HD_M_DistribMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_HD_Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_HD_Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_HD_Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_HD_Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_ED_HubPtLoad: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_ED_HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_ED_HubPtLoad + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ED_HubPtLoad + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ED_HubPtLoad + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ED_HubPtLoad + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_ED_HubPtLoad_2: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_ED_HubPtLoad_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_ED_HubPtLoad_2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ED_HubPtLoad_2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ED_HubPtLoad_2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ED_HubPtLoad_2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! u_BD_RootMotion allocated yes/no + IF ( ALLOCATED(InData%u_BD_RootMotion) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_BD_RootMotion upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_BD_RootMotion,1), UBOUND(InData%u_BD_RootMotion,1) + Int_BufSz = Int_BufSz + 3 ! u_BD_RootMotion: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_BD_RootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_BD_RootMotion + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_BD_RootMotion + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_BD_RootMotion + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_BD_RootMotion + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! y_BD_BldMotion_4Loads allocated yes/no + IF ( ALLOCATED(InData%y_BD_BldMotion_4Loads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y_BD_BldMotion_4Loads upper/lower bounds for each dimension + DO i1 = LBOUND(InData%y_BD_BldMotion_4Loads,1), UBOUND(InData%y_BD_BldMotion_4Loads,1) + Int_BufSz = Int_BufSz + 3 ! y_BD_BldMotion_4Loads: size of buffers for each call to pack subtype + CALL MeshPack( InData%y_BD_BldMotion_4Loads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! y_BD_BldMotion_4Loads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_BD_BldMotion_4Loads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_BD_BldMotion_4Loads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_BD_BldMotion_4Loads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! u_Orca_PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_Orca_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_Orca_PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_Orca_PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_Orca_PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_Orca_PtfmMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! u_ExtPtfm_PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_ExtPtfm_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_ExtPtfm_PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! u_ExtPtfm_PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! u_ExtPtfm_PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! u_ExtPtfm_PtfmMesh + 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 + + IF ( .NOT. ALLOCATED(InData%ED_P_2_BD_P) ) 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%ED_P_2_BD_P,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ED_P_2_BD_P,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ED_P_2_BD_P,1), UBOUND(InData%ED_P_2_BD_P,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_BD_P(i1), ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_BD_P + 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%BD_P_2_ED_P) ) 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%BD_P_2_ED_P,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BD_P_2_ED_P,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BD_P_2_ED_P,1), UBOUND(InData%BD_P_2_ED_P,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BD_P_2_ED_P(i1), ErrStat2, ErrMsg2, OnlySize ) ! BD_P_2_ED_P + 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%ED_P_2_BD_P_Hub) ) 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%ED_P_2_BD_P_Hub,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ED_P_2_BD_P_Hub,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ED_P_2_BD_P_Hub,1), UBOUND(InData%ED_P_2_BD_P_Hub,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_BD_P_Hub(i1), ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_BD_P_Hub + 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 + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_W_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_W_P_2_ED_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_M_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_P_2_ED_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_M_L + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_L_2_ED_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_Mooring_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! Mooring_P_2_ED_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_SD_TP, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_SD_TP + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! SD_TP_2_ED_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_HD_M_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_P_2_SD_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_HD_M_L + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_L_2_SD_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_SrvD_P_N + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2, OnlySize ) ! SrvD_P_2_ED_P_N + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2, OnlySize ) ! ED_L_2_SrvD_P_T + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2, OnlySize ) ! SrvD_P_2_ED_P_T + 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%BDED_L_2_AD_L_B) ) 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%BDED_L_2_AD_L_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BDED_L_2_AD_L_B,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BDED_L_2_AD_L_B,1), UBOUND(InData%BDED_L_2_AD_L_B,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BDED_L_2_AD_L_B(i1), ErrStat2, ErrMsg2, OnlySize ) ! BDED_L_2_AD_L_B + 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%AD_L_2_BDED_B) ) 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%AD_L_2_BDED_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AD_L_2_BDED_B,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AD_L_2_BDED_B,1), UBOUND(InData%AD_L_2_BDED_B,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%AD_L_2_BDED_B(i1), ErrStat2, ErrMsg2, OnlySize ) ! AD_L_2_BDED_B + 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%BD_L_2_BD_L) ) 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%BD_L_2_BD_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BD_L_2_BD_L,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BD_L_2_BD_L,1), UBOUND(InData%BD_L_2_BD_L,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%BD_L_2_BD_L(i1), ErrStat2, ErrMsg2, OnlySize ) ! BD_L_2_BD_L + 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 + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2, OnlySize ) ! ED_L_2_AD_L_T + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2, OnlySize ) ! AD_L_2_ED_P_T + 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%ED_P_2_AD_P_R) ) 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%ED_P_2_AD_P_R,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ED_P_2_AD_P_R,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ED_P_2_AD_P_R,1), UBOUND(InData%ED_P_2_AD_P_R,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_AD_P_R(i1), ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_AD_P_R + 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 + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_AD_P_H + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%IceF_P_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! IceF_P_2_SD_P + 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 NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_IceF_P, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_IceF_P + 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%IceD_P_2_SD_P) ) 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%IceD_P_2_SD_P,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IceD_P_2_SD_P,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IceD_P_2_SD_P,1), UBOUND(InData%IceD_P_2_SD_P,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%IceD_P_2_SD_P(i1), ErrStat2, ErrMsg2, OnlySize ) ! IceD_P_2_SD_P + 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%SD_P_2_IceD_P) ) 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%SD_P_2_IceD_P,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SD_P_2_IceD_P,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SD_P_2_IceD_P,1), UBOUND(InData%SD_P_2_IceD_P,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_IceD_P(i1), ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_IceD_P + 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%Jacobian_Opt1) ) 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%Jacobian_Opt1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jacobian_Opt1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jacobian_Opt1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jacobian_Opt1,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jacobian_Opt1,2), UBOUND(InData%Jacobian_Opt1,2) + DO i1 = LBOUND(InData%Jacobian_Opt1,1), UBOUND(InData%Jacobian_Opt1,1) + ReKiBuf(Re_Xferred) = InData%Jacobian_Opt1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Jacobian_pivot) ) 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%Jacobian_pivot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jacobian_pivot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Jacobian_pivot,1), UBOUND(InData%Jacobian_pivot,1) + IntKiBuf(Int_Xferred) = InData%Jacobian_pivot(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) 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%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + CALL MeshPack( InData%u_ED_PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_ED_PlatformPtMesh + 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 MeshPack( InData%u_ED_PlatformPtMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_ED_PlatformPtMesh_2 + 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 MeshPack( InData%u_SD_TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_SD_TPMesh + 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 MeshPack( InData%u_SD_LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_SD_LMesh + 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 MeshPack( InData%u_SD_LMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_SD_LMesh_2 + 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 MeshPack( InData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_M_LumpedMesh + 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 MeshPack( InData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_M_DistribMesh + 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 MeshPack( InData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_Mesh + 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 MeshPack( InData%u_ED_HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_ED_HubPtLoad + 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 MeshPack( InData%u_ED_HubPtLoad_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_ED_HubPtLoad_2 + 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%u_BD_RootMotion) ) 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%u_BD_RootMotion,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_BD_RootMotion,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_BD_RootMotion,1), UBOUND(InData%u_BD_RootMotion,1) + CALL MeshPack( InData%u_BD_RootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_BD_RootMotion + 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%y_BD_BldMotion_4Loads) ) 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%y_BD_BldMotion_4Loads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y_BD_BldMotion_4Loads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y_BD_BldMotion_4Loads,1), UBOUND(InData%y_BD_BldMotion_4Loads,1) + CALL MeshPack( InData%y_BD_BldMotion_4Loads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! y_BD_BldMotion_4Loads + 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 + CALL MeshPack( InData%u_Orca_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_Orca_PtfmMesh + 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 MeshPack( InData%u_ExtPtfm_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_ExtPtfm_PtfmMesh + 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 FAST_PackModuleMapType + + SUBROUTINE FAST_UnPackModuleMapType( 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(FAST_ModuleMapType), 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 = 'FAST_UnPackModuleMapType' + ! 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 ! ED_P_2_BD_P 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%ED_P_2_BD_P)) DEALLOCATE(OutData%ED_P_2_BD_P) + ALLOCATE(OutData%ED_P_2_BD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ED_P_2_BD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ED_P_2_BD_P,1), UBOUND(OutData%ED_P_2_BD_P,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_BD_P(i1), ErrStat2, ErrMsg2 ) ! ED_P_2_BD_P + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BD_P_2_ED_P 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%BD_P_2_ED_P)) DEALLOCATE(OutData%BD_P_2_ED_P) + ALLOCATE(OutData%BD_P_2_ED_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BD_P_2_ED_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BD_P_2_ED_P,1), UBOUND(OutData%BD_P_2_ED_P,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%BD_P_2_ED_P(i1), ErrStat2, ErrMsg2 ) ! BD_P_2_ED_P + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ED_P_2_BD_P_Hub 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%ED_P_2_BD_P_Hub)) DEALLOCATE(OutData%ED_P_2_BD_P_Hub) + ALLOCATE(OutData%ED_P_2_BD_P_Hub(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ED_P_2_BD_P_Hub.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ED_P_2_BD_P_Hub,1), UBOUND(OutData%ED_P_2_BD_P_Hub,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_BD_P_Hub(i1), ErrStat2, ErrMsg2 ) ! ED_P_2_BD_P_Hub + 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 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) ! ED_P_2_HD_W_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) ! HD_W_P_2_ED_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) ! ED_P_2_HD_M_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2 ) ! HD_M_P_2_ED_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) ! ED_P_2_HD_M_L + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2 ) ! HD_M_L_2_ED_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) ! ED_P_2_Mooring_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) ! Mooring_P_2_ED_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) ! ED_P_2_SD_TP + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_TP_2_ED_P, ErrStat2, ErrMsg2 ) ! SD_TP_2_ED_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) ! SD_P_2_HD_M_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2 ) ! HD_M_P_2_SD_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) ! SD_P_2_HD_M_L + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2 ) ! HD_M_L_2_SD_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_SrvD_P_N, ErrStat2, ErrMsg2 ) ! ED_P_2_SrvD_P_N + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SrvD_P_2_ED_P_N, ErrStat2, ErrMsg2 ) ! SrvD_P_2_ED_P_N + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_L_2_SrvD_P_T, ErrStat2, ErrMsg2 ) ! ED_L_2_SrvD_P_T + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SrvD_P_2_ED_P_T, ErrStat2, ErrMsg2 ) ! SrvD_P_2_ED_P_T + 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 ! BDED_L_2_AD_L_B 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%BDED_L_2_AD_L_B)) DEALLOCATE(OutData%BDED_L_2_AD_L_B) + ALLOCATE(OutData%BDED_L_2_AD_L_B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BDED_L_2_AD_L_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BDED_L_2_AD_L_B,1), UBOUND(OutData%BDED_L_2_AD_L_B,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%BDED_L_2_AD_L_B(i1), ErrStat2, ErrMsg2 ) ! BDED_L_2_AD_L_B + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AD_L_2_BDED_B 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%AD_L_2_BDED_B)) DEALLOCATE(OutData%AD_L_2_BDED_B) + ALLOCATE(OutData%AD_L_2_BDED_B(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AD_L_2_BDED_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AD_L_2_BDED_B,1), UBOUND(OutData%AD_L_2_BDED_B,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%AD_L_2_BDED_B(i1), ErrStat2, ErrMsg2 ) ! AD_L_2_BDED_B + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BD_L_2_BD_L 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%BD_L_2_BD_L)) DEALLOCATE(OutData%BD_L_2_BD_L) + ALLOCATE(OutData%BD_L_2_BD_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BD_L_2_BD_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BD_L_2_BD_L,1), UBOUND(OutData%BD_L_2_BD_L,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%BD_L_2_BD_L(i1), ErrStat2, ErrMsg2 ) ! BD_L_2_BD_L + 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 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_L_2_AD_L_T, ErrStat2, ErrMsg2 ) ! ED_L_2_AD_L_T + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%AD_L_2_ED_P_T, ErrStat2, ErrMsg2 ) ! AD_L_2_ED_P_T + 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 ! ED_P_2_AD_P_R 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%ED_P_2_AD_P_R)) DEALLOCATE(OutData%ED_P_2_AD_P_R) + ALLOCATE(OutData%ED_P_2_AD_P_R(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ED_P_2_AD_P_R.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ED_P_2_AD_P_R,1), UBOUND(OutData%ED_P_2_AD_P_R,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_AD_P_R(i1), ErrStat2, ErrMsg2 ) ! ED_P_2_AD_P_R + 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 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_AD_P_H, ErrStat2, ErrMsg2 ) ! ED_P_2_AD_P_H + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%IceF_P_2_SD_P, ErrStat2, ErrMsg2 ) ! IceF_P_2_SD_P + 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 NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_IceF_P, ErrStat2, ErrMsg2 ) ! SD_P_2_IceF_P + 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 ! IceD_P_2_SD_P 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%IceD_P_2_SD_P)) DEALLOCATE(OutData%IceD_P_2_SD_P) + ALLOCATE(OutData%IceD_P_2_SD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IceD_P_2_SD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IceD_P_2_SD_P,1), UBOUND(OutData%IceD_P_2_SD_P,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%IceD_P_2_SD_P(i1), ErrStat2, ErrMsg2 ) ! IceD_P_2_SD_P + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SD_P_2_IceD_P 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%SD_P_2_IceD_P)) DEALLOCATE(OutData%SD_P_2_IceD_P) + ALLOCATE(OutData%SD_P_2_IceD_P(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SD_P_2_IceD_P.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SD_P_2_IceD_P,1), UBOUND(OutData%SD_P_2_IceD_P,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_IceD_P(i1), ErrStat2, ErrMsg2 ) ! SD_P_2_IceD_P + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jacobian_Opt1 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%Jacobian_Opt1)) DEALLOCATE(OutData%Jacobian_Opt1) + ALLOCATE(OutData%Jacobian_Opt1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jacobian_Opt1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jacobian_Opt1,2), UBOUND(OutData%Jacobian_Opt1,2) + DO i1 = LBOUND(OutData%Jacobian_Opt1,1), UBOUND(OutData%Jacobian_Opt1,1) + OutData%Jacobian_Opt1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jacobian_pivot 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%Jacobian_pivot)) DEALLOCATE(OutData%Jacobian_pivot) + ALLOCATE(OutData%Jacobian_pivot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jacobian_pivot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Jacobian_pivot,1), UBOUND(OutData%Jacobian_pivot,1) + OutData%Jacobian_pivot(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx 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%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_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 MeshUnpack( OutData%u_ED_PlatformPtMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_ED_PlatformPtMesh + 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 MeshUnpack( OutData%u_ED_PlatformPtMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_ED_PlatformPtMesh_2 + 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 MeshUnpack( OutData%u_SD_TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_SD_TPMesh + 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 MeshUnpack( OutData%u_SD_LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_SD_LMesh + 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 MeshUnpack( OutData%u_SD_LMesh_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_SD_LMesh_2 + 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 MeshUnpack( OutData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_M_LumpedMesh + 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 MeshUnpack( OutData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_M_DistribMesh + 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 MeshUnpack( OutData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_Mesh + 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 MeshUnpack( OutData%u_ED_HubPtLoad, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_ED_HubPtLoad + 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 MeshUnpack( OutData%u_ED_HubPtLoad_2, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_ED_HubPtLoad_2 + 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 ! u_BD_RootMotion 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%u_BD_RootMotion)) DEALLOCATE(OutData%u_BD_RootMotion) + ALLOCATE(OutData%u_BD_RootMotion(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_BD_RootMotion.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_BD_RootMotion,1), UBOUND(OutData%u_BD_RootMotion,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 MeshUnpack( OutData%u_BD_RootMotion(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_BD_RootMotion + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y_BD_BldMotion_4Loads 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%y_BD_BldMotion_4Loads)) DEALLOCATE(OutData%y_BD_BldMotion_4Loads) + ALLOCATE(OutData%y_BD_BldMotion_4Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y_BD_BldMotion_4Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y_BD_BldMotion_4Loads,1), UBOUND(OutData%y_BD_BldMotion_4Loads,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 MeshUnpack( OutData%y_BD_BldMotion_4Loads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! y_BD_BldMotion_4Loads + 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 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 MeshUnpack( OutData%u_Orca_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_Orca_PtfmMesh + 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 MeshUnpack( OutData%u_ExtPtfm_PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_ExtPtfm_PtfmMesh + 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 FAST_UnPackModuleMapType + + SUBROUTINE FAST_CopyExternInputType( SrcExternInputTypeData, DstExternInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_ExternInputType), INTENT(IN) :: SrcExternInputTypeData + TYPE(FAST_ExternInputType), INTENT(INOUT) :: DstExternInputTypeData + 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 = 'FAST_CopyExternInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstExternInputTypeData%GenTrq = SrcExternInputTypeData%GenTrq + DstExternInputTypeData%ElecPwr = SrcExternInputTypeData%ElecPwr + DstExternInputTypeData%YawPosCom = SrcExternInputTypeData%YawPosCom + DstExternInputTypeData%YawRateCom = SrcExternInputTypeData%YawRateCom + DstExternInputTypeData%BlPitchCom = SrcExternInputTypeData%BlPitchCom + DstExternInputTypeData%HSSBrFrac = SrcExternInputTypeData%HSSBrFrac + DstExternInputTypeData%LidarFocus = SrcExternInputTypeData%LidarFocus + END SUBROUTINE FAST_CopyExternInputType + + SUBROUTINE FAST_DestroyExternInputType( ExternInputTypeData, ErrStat, ErrMsg ) + TYPE(FAST_ExternInputType), INTENT(INOUT) :: ExternInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyExternInputType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FAST_DestroyExternInputType + + SUBROUTINE FAST_PackExternInputType( 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(FAST_ExternInputType), 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 = 'FAST_PackExternInputType' + ! 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 ! GenTrq + Re_BufSz = Re_BufSz + 1 ! ElecPwr + Re_BufSz = Re_BufSz + 1 ! YawPosCom + Re_BufSz = Re_BufSz + 1 ! YawRateCom + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchCom) ! BlPitchCom + Re_BufSz = Re_BufSz + 1 ! HSSBrFrac + Re_BufSz = Re_BufSz + SIZE(InData%LidarFocus) ! LidarFocus + 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%GenTrq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ElecPwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawPosCom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRateCom + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%BlPitchCom,1), UBOUND(InData%BlPitchCom,1) + ReKiBuf(Re_Xferred) = InData%BlPitchCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%HSSBrFrac + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%LidarFocus,1), UBOUND(InData%LidarFocus,1) + ReKiBuf(Re_Xferred) = InData%LidarFocus(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FAST_PackExternInputType + + SUBROUTINE FAST_UnPackExternInputType( 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(FAST_ExternInputType), 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 = 'FAST_UnPackExternInputType' + ! 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%GenTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ElecPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawPosCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRateCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%BlPitchCom,1) + i1_u = UBOUND(OutData%BlPitchCom,1) + DO i1 = LBOUND(OutData%BlPitchCom,1), UBOUND(OutData%BlPitchCom,1) + OutData%BlPitchCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%HSSBrFrac = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%LidarFocus,1) + i1_u = UBOUND(OutData%LidarFocus,1) + DO i1 = LBOUND(OutData%LidarFocus,1), UBOUND(OutData%LidarFocus,1) + OutData%LidarFocus(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE FAST_UnPackExternInputType + + SUBROUTINE FAST_CopyInitData( SrcInitDataData, DstInitDataData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_InitData), INTENT(INOUT) :: SrcInitDataData + TYPE(FAST_InitData), INTENT(INOUT) :: DstInitDataData + 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 = 'FAST_CopyInitData' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL ED_CopyInitInput( SrcInitDataData%InData_ED, DstInitDataData%InData_ED, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ED_CopyInitOutput( SrcInitDataData%OutData_ED, DstInitDataData%OutData_ED, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL BD_CopyInitInput( SrcInitDataData%InData_BD, DstInitDataData%InData_BD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitDataData%OutData_BD)) THEN + i1_l = LBOUND(SrcInitDataData%OutData_BD,1) + i1_u = UBOUND(SrcInitDataData%OutData_BD,1) + IF (.NOT. ALLOCATED(DstInitDataData%OutData_BD)) THEN + ALLOCATE(DstInitDataData%OutData_BD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitDataData%OutData_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitDataData%OutData_BD,1), UBOUND(SrcInitDataData%OutData_BD,1) + CALL BD_CopyInitOutput( SrcInitDataData%OutData_BD(i1), DstInitDataData%OutData_BD(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL SrvD_CopyInitInput( SrcInitDataData%InData_SrvD, DstInitDataData%InData_SrvD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SrvD_CopyInitOutput( SrcInitDataData%OutData_SrvD, DstInitDataData%OutData_SrvD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_CopyInitInput( SrcInitDataData%InData_AD14, DstInitDataData%InData_AD14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD14_CopyInitOutput( SrcInitDataData%OutData_AD14, DstInitDataData%OutData_AD14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyInitInput( SrcInitDataData%InData_AD, DstInitDataData%InData_AD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL AD_CopyInitOutput( SrcInitDataData%OutData_AD, DstInitDataData%OutData_AD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyInitInput( SrcInitDataData%InData_IfW, DstInitDataData%InData_IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL InflowWind_CopyInitOutput( SrcInitDataData%OutData_IfW, DstInitDataData%OutData_IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL OpFM_CopyInitInput( SrcInitDataData%InData_OpFM, DstInitDataData%InData_OpFM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL OpFM_CopyInitOutput( SrcInitDataData%OutData_OpFM, DstInitDataData%OutData_OpFM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_CopyInitInput( SrcInitDataData%InData_HD, DstInitDataData%InData_HD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL HydroDyn_CopyInitOutput( SrcInitDataData%OutData_HD, DstInitDataData%OutData_HD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SD_CopyInitInput( SrcInitDataData%InData_SD, DstInitDataData%InData_SD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SD_CopyInitOutput( SrcInitDataData%OutData_SD, DstInitDataData%OutData_SD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ExtPtfm_CopyInitInput( SrcInitDataData%InData_ExtPtfm, DstInitDataData%InData_ExtPtfm, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL ExtPtfm_CopyInitOutput( SrcInitDataData%OutData_ExtPtfm, DstInitDataData%OutData_ExtPtfm, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyInitInput( SrcInitDataData%InData_MAP, DstInitDataData%InData_MAP, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MAP_CopyInitOutput( SrcInitDataData%OutData_MAP, DstInitDataData%OutData_MAP, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FEAM_CopyInitInput( SrcInitDataData%InData_FEAM, DstInitDataData%InData_FEAM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FEAM_CopyInitOutput( SrcInitDataData%OutData_FEAM, DstInitDataData%OutData_FEAM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MD_CopyInitInput( SrcInitDataData%InData_MD, DstInitDataData%InData_MD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MD_CopyInitOutput( SrcInitDataData%OutData_MD, DstInitDataData%OutData_MD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Orca_CopyInitInput( SrcInitDataData%InData_Orca, DstInitDataData%InData_Orca, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL Orca_CopyInitOutput( SrcInitDataData%OutData_Orca, DstInitDataData%OutData_Orca, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceFloe_CopyInitInput( SrcInitDataData%InData_IceF, DstInitDataData%InData_IceF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceFloe_CopyInitOutput( SrcInitDataData%OutData_IceF, DstInitDataData%OutData_IceF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceD_CopyInitInput( SrcInitDataData%InData_IceD, DstInitDataData%InData_IceD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IceD_CopyInitOutput( SrcInitDataData%OutData_IceD, DstInitDataData%OutData_IceD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SC_CopyInitInput( SrcInitDataData%InData_SC, DstInitDataData%InData_SC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL SC_CopyInitOutput( SrcInitDataData%OutData_SC, DstInitDataData%OutData_SC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyInitData + + SUBROUTINE FAST_DestroyInitData( InitDataData, ErrStat, ErrMsg ) + TYPE(FAST_InitData), INTENT(INOUT) :: InitDataData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyInitData' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL ED_DestroyInitInput( InitDataData%InData_ED, ErrStat, ErrMsg ) + CALL ED_DestroyInitOutput( InitDataData%OutData_ED, ErrStat, ErrMsg ) + CALL BD_DestroyInitInput( InitDataData%InData_BD, ErrStat, ErrMsg ) +IF (ALLOCATED(InitDataData%OutData_BD)) THEN +DO i1 = LBOUND(InitDataData%OutData_BD,1), UBOUND(InitDataData%OutData_BD,1) + CALL BD_DestroyInitOutput( InitDataData%OutData_BD(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitDataData%OutData_BD) +ENDIF + CALL SrvD_DestroyInitInput( InitDataData%InData_SrvD, ErrStat, ErrMsg ) + CALL SrvD_DestroyInitOutput( InitDataData%OutData_SrvD, ErrStat, ErrMsg ) + CALL AD14_DestroyInitInput( InitDataData%InData_AD14, ErrStat, ErrMsg ) + CALL AD14_DestroyInitOutput( InitDataData%OutData_AD14, ErrStat, ErrMsg ) + CALL AD_DestroyInitInput( InitDataData%InData_AD, ErrStat, ErrMsg ) + CALL AD_DestroyInitOutput( InitDataData%OutData_AD, ErrStat, ErrMsg ) + CALL InflowWind_DestroyInitInput( InitDataData%InData_IfW, ErrStat, ErrMsg ) + CALL InflowWind_DestroyInitOutput( InitDataData%OutData_IfW, ErrStat, ErrMsg ) + CALL OpFM_DestroyInitInput( InitDataData%InData_OpFM, ErrStat, ErrMsg ) + CALL OpFM_DestroyInitOutput( InitDataData%OutData_OpFM, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyInitInput( InitDataData%InData_HD, ErrStat, ErrMsg ) + CALL HydroDyn_DestroyInitOutput( InitDataData%OutData_HD, ErrStat, ErrMsg ) + CALL SD_DestroyInitInput( InitDataData%InData_SD, ErrStat, ErrMsg ) + CALL SD_DestroyInitOutput( InitDataData%OutData_SD, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyInitInput( InitDataData%InData_ExtPtfm, ErrStat, ErrMsg ) + CALL ExtPtfm_DestroyInitOutput( InitDataData%OutData_ExtPtfm, ErrStat, ErrMsg ) + CALL MAP_DestroyInitInput( InitDataData%InData_MAP, ErrStat, ErrMsg ) + CALL MAP_DestroyInitOutput( InitDataData%OutData_MAP, ErrStat, ErrMsg ) + CALL FEAM_DestroyInitInput( InitDataData%InData_FEAM, ErrStat, ErrMsg ) + CALL FEAM_DestroyInitOutput( InitDataData%OutData_FEAM, ErrStat, ErrMsg ) + CALL MD_DestroyInitInput( InitDataData%InData_MD, ErrStat, ErrMsg ) + CALL MD_DestroyInitOutput( InitDataData%OutData_MD, ErrStat, ErrMsg ) + CALL Orca_DestroyInitInput( InitDataData%InData_Orca, ErrStat, ErrMsg ) + CALL Orca_DestroyInitOutput( InitDataData%OutData_Orca, ErrStat, ErrMsg ) + CALL IceFloe_DestroyInitInput( InitDataData%InData_IceF, ErrStat, ErrMsg ) + CALL IceFloe_DestroyInitOutput( InitDataData%OutData_IceF, ErrStat, ErrMsg ) + CALL IceD_DestroyInitInput( InitDataData%InData_IceD, ErrStat, ErrMsg ) + CALL IceD_DestroyInitOutput( InitDataData%OutData_IceD, ErrStat, ErrMsg ) + CALL SC_DestroyInitInput( InitDataData%InData_SC, ErrStat, ErrMsg ) + CALL SC_DestroyInitOutput( InitDataData%OutData_SC, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyInitData + + SUBROUTINE FAST_PackInitData( 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(FAST_InitData), 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 = 'FAST_PackInitData' + ! 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 ! InData_ED: size of buffers for each call to pack subtype + CALL ED_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_ED, ErrStat2, ErrMsg2, .TRUE. ) ! InData_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_ED: size of buffers for each call to pack subtype + CALL ED_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_ED, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_BD: size of buffers for each call to pack subtype + CALL BD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_BD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! OutData_BD allocated yes/no + IF ( ALLOCATED(InData%OutData_BD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutData_BD upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OutData_BD,1), UBOUND(InData%OutData_BD,1) + Int_BufSz = Int_BufSz + 3 ! OutData_BD: size of buffers for each call to pack subtype + CALL BD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_BD(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutData_BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! InData_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SrvD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_SrvD: size of buffers for each call to pack subtype + CALL SrvD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SrvD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_AD14: size of buffers for each call to pack subtype + CALL AD14_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_AD14, ErrStat2, ErrMsg2, .TRUE. ) ! InData_AD14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_AD14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_AD14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_AD14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_AD14: size of buffers for each call to pack subtype + CALL AD14_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_AD14, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_AD14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_AD14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_AD14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_AD14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_AD: size of buffers for each call to pack subtype + CALL AD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_AD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_AD: size of buffers for each call to pack subtype + CALL AD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_AD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IfW, ErrStat2, ErrMsg2, .TRUE. ) ! InData_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_IfW: size of buffers for each call to pack subtype + CALL InflowWind_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IfW, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_OpFM: size of buffers for each call to pack subtype + CALL OpFM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_OpFM, ErrStat2, ErrMsg2, .TRUE. ) ! InData_OpFM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_OpFM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_OpFM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_OpFM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_OpFM: size of buffers for each call to pack subtype + CALL OpFM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_OpFM, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_OpFM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_OpFM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_OpFM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_OpFM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_HD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_HD: size of buffers for each call to pack subtype + CALL HydroDyn_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_HD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_SD: size of buffers for each call to pack subtype + CALL SD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_SD: size of buffers for each call to pack subtype + CALL SD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_ExtPtfm, ErrStat2, ErrMsg2, .TRUE. ) ! InData_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_ExtPtfm: size of buffers for each call to pack subtype + CALL ExtPtfm_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_ExtPtfm, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_ExtPtfm + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_MAP: size of buffers for each call to pack subtype + CALL MAP_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_MAP, ErrStat2, ErrMsg2, .TRUE. ) ! InData_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_MAP: size of buffers for each call to pack subtype + CALL MAP_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_MAP, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_FEAM, ErrStat2, ErrMsg2, .TRUE. ) ! InData_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_FEAM: size of buffers for each call to pack subtype + CALL FEAM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_FEAM, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_MD: size of buffers for each call to pack subtype + CALL MD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_MD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_MD: size of buffers for each call to pack subtype + CALL MD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_MD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_Orca: size of buffers for each call to pack subtype + CALL Orca_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_Orca, ErrStat2, ErrMsg2, .TRUE. ) ! InData_Orca + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_Orca + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_Orca + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_Orca + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_Orca: size of buffers for each call to pack subtype + CALL Orca_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_Orca, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_Orca + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_Orca + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_Orca + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_Orca + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IceF, ErrStat2, ErrMsg2, .TRUE. ) ! InData_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_IceF: size of buffers for each call to pack subtype + CALL IceFloe_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IceF, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_IceD: size of buffers for each call to pack subtype + CALL IceD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IceD, ErrStat2, ErrMsg2, .TRUE. ) ! InData_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_IceD: size of buffers for each call to pack subtype + CALL IceD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IceD, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! InData_SC: size of buffers for each call to pack subtype + CALL SC_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SC, ErrStat2, ErrMsg2, .TRUE. ) ! InData_SC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! InData_SC + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! InData_SC + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! InData_SC + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OutData_SC: size of buffers for each call to pack subtype + CALL SC_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SC, ErrStat2, ErrMsg2, .TRUE. ) ! OutData_SC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutData_SC + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutData_SC + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutData_SC + 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 ED_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_ED, ErrStat2, ErrMsg2, OnlySize ) ! InData_ED + 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 ED_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_ED, ErrStat2, ErrMsg2, OnlySize ) ! OutData_ED + 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 BD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_BD, ErrStat2, ErrMsg2, OnlySize ) ! InData_BD + 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%OutData_BD) ) 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%OutData_BD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutData_BD,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutData_BD,1), UBOUND(InData%OutData_BD,1) + CALL BD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_BD(i1), ErrStat2, ErrMsg2, OnlySize ) ! OutData_BD + 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 + CALL SrvD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SrvD, ErrStat2, ErrMsg2, OnlySize ) ! InData_SrvD + 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 SrvD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SrvD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_SrvD + 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 AD14_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_AD14, ErrStat2, ErrMsg2, OnlySize ) ! InData_AD14 + 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 AD14_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_AD14, ErrStat2, ErrMsg2, OnlySize ) ! OutData_AD14 + 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 AD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_AD, ErrStat2, ErrMsg2, OnlySize ) ! InData_AD + 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 AD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_AD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_AD + 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_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IfW, ErrStat2, ErrMsg2, OnlySize ) ! InData_IfW + 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_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IfW, ErrStat2, ErrMsg2, OnlySize ) ! OutData_IfW + 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 OpFM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_OpFM, ErrStat2, ErrMsg2, OnlySize ) ! InData_OpFM + 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 OpFM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_OpFM, ErrStat2, ErrMsg2, OnlySize ) ! OutData_OpFM + 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 HydroDyn_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_HD, ErrStat2, ErrMsg2, OnlySize ) ! InData_HD + 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 HydroDyn_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_HD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_HD + 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 SD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SD, ErrStat2, ErrMsg2, OnlySize ) ! InData_SD + 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 SD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_SD + 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 ExtPtfm_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_ExtPtfm, ErrStat2, ErrMsg2, OnlySize ) ! InData_ExtPtfm + 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 ExtPtfm_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_ExtPtfm, ErrStat2, ErrMsg2, OnlySize ) ! OutData_ExtPtfm + 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 MAP_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_MAP, ErrStat2, ErrMsg2, OnlySize ) ! InData_MAP + 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 MAP_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_MAP, ErrStat2, ErrMsg2, OnlySize ) ! OutData_MAP + 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 FEAM_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_FEAM, ErrStat2, ErrMsg2, OnlySize ) ! InData_FEAM + 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 FEAM_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_FEAM, ErrStat2, ErrMsg2, OnlySize ) ! OutData_FEAM + 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 MD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_MD, ErrStat2, ErrMsg2, OnlySize ) ! InData_MD + 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 MD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_MD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_MD + 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 Orca_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_Orca, ErrStat2, ErrMsg2, OnlySize ) ! InData_Orca + 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 Orca_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_Orca, ErrStat2, ErrMsg2, OnlySize ) ! OutData_Orca + 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 IceFloe_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IceF, ErrStat2, ErrMsg2, OnlySize ) ! InData_IceF + 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 IceFloe_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IceF, ErrStat2, ErrMsg2, OnlySize ) ! OutData_IceF + 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 IceD_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_IceD, ErrStat2, ErrMsg2, OnlySize ) ! InData_IceD + 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 IceD_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_IceD, ErrStat2, ErrMsg2, OnlySize ) ! OutData_IceD + 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 SC_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%InData_SC, ErrStat2, ErrMsg2, OnlySize ) ! InData_SC + 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 SC_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%OutData_SC, ErrStat2, ErrMsg2, OnlySize ) ! OutData_SC + 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 FAST_PackInitData + + SUBROUTINE FAST_UnPackInitData( 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(FAST_InitData), 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 = 'FAST_UnPackInitData' + ! 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 ED_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_ED, ErrStat2, ErrMsg2 ) ! InData_ED + 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 ED_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_ED, ErrStat2, ErrMsg2 ) ! OutData_ED + 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 BD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_BD, ErrStat2, ErrMsg2 ) ! InData_BD + 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 ! OutData_BD 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%OutData_BD)) DEALLOCATE(OutData%OutData_BD) + ALLOCATE(OutData%OutData_BD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutData_BD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutData_BD,1), UBOUND(OutData%OutData_BD,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 BD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_BD(i1), ErrStat2, ErrMsg2 ) ! OutData_BD + 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 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 SrvD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_SrvD, ErrStat2, ErrMsg2 ) ! InData_SrvD + 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 SrvD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_SrvD, ErrStat2, ErrMsg2 ) ! OutData_SrvD + 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 AD14_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_AD14, ErrStat2, ErrMsg2 ) ! InData_AD14 + 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 AD14_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_AD14, ErrStat2, ErrMsg2 ) ! OutData_AD14 + 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 AD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_AD, ErrStat2, ErrMsg2 ) ! InData_AD + 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 AD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_AD, ErrStat2, ErrMsg2 ) ! OutData_AD + 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 InflowWind_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_IfW, ErrStat2, ErrMsg2 ) ! InData_IfW + 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 InflowWind_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_IfW, ErrStat2, ErrMsg2 ) ! OutData_IfW + 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 OpFM_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_OpFM, ErrStat2, ErrMsg2 ) ! InData_OpFM + 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 OpFM_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_OpFM, ErrStat2, ErrMsg2 ) ! OutData_OpFM + 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 HydroDyn_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_HD, ErrStat2, ErrMsg2 ) ! InData_HD + 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 HydroDyn_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_HD, ErrStat2, ErrMsg2 ) ! OutData_HD + 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 SD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_SD, ErrStat2, ErrMsg2 ) ! InData_SD + 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 SD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_SD, ErrStat2, ErrMsg2 ) ! OutData_SD + 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 ExtPtfm_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_ExtPtfm, ErrStat2, ErrMsg2 ) ! InData_ExtPtfm + 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 ExtPtfm_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_ExtPtfm, ErrStat2, ErrMsg2 ) ! OutData_ExtPtfm + 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 MAP_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_MAP, ErrStat2, ErrMsg2 ) ! InData_MAP + 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 MAP_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_MAP, ErrStat2, ErrMsg2 ) ! OutData_MAP + 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 FEAM_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_FEAM, ErrStat2, ErrMsg2 ) ! InData_FEAM + 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 FEAM_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_FEAM, ErrStat2, ErrMsg2 ) ! OutData_FEAM + 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 MD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_MD, ErrStat2, ErrMsg2 ) ! InData_MD + 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 MD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_MD, ErrStat2, ErrMsg2 ) ! OutData_MD + 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 Orca_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_Orca, ErrStat2, ErrMsg2 ) ! InData_Orca + 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 Orca_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_Orca, ErrStat2, ErrMsg2 ) ! OutData_Orca + 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 IceFloe_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_IceF, ErrStat2, ErrMsg2 ) ! InData_IceF + 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 IceFloe_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_IceF, ErrStat2, ErrMsg2 ) ! OutData_IceF + 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 IceD_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_IceD, ErrStat2, ErrMsg2 ) ! InData_IceD + 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 IceD_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_IceD, ErrStat2, ErrMsg2 ) ! OutData_IceD + 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 SC_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%InData_SC, ErrStat2, ErrMsg2 ) ! InData_SC + 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 SC_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%OutData_SC, ErrStat2, ErrMsg2 ) ! OutData_SC + 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 FAST_UnPackInitData + + SUBROUTINE FAST_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(FAST_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%TiLstPrn = SrcMiscData%TiLstPrn + DstMiscData%t_global = SrcMiscData%t_global + DstMiscData%NextJacCalcTime = SrcMiscData%NextJacCalcTime + DstMiscData%PrevClockTime = SrcMiscData%PrevClockTime + DstMiscData%UsrTime1 = SrcMiscData%UsrTime1 + DstMiscData%UsrTime2 = SrcMiscData%UsrTime2 + DstMiscData%StrtTime = SrcMiscData%StrtTime + DstMiscData%SimStrtTime = SrcMiscData%SimStrtTime + DstMiscData%calcJacobian = SrcMiscData%calcJacobian + CALL FAST_Copyexterninputtype( SrcMiscData%ExternInput, DstMiscData%ExternInput, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copymisclintype( SrcMiscData%Lin, DstMiscData%Lin, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyMisc + + SUBROUTINE FAST_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(FAST_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL FAST_Destroyexterninputtype( MiscData%ExternInput, ErrStat, ErrMsg ) + CALL FAST_Destroymisclintype( MiscData%Lin, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyMisc + + SUBROUTINE FAST_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(FAST_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 = 'FAST_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 + Db_BufSz = Db_BufSz + 1 ! TiLstPrn + Db_BufSz = Db_BufSz + 1 ! t_global + Db_BufSz = Db_BufSz + 1 ! NextJacCalcTime + Re_BufSz = Re_BufSz + 1 ! PrevClockTime + Re_BufSz = Re_BufSz + 1 ! UsrTime1 + Re_BufSz = Re_BufSz + 1 ! UsrTime2 + Int_BufSz = Int_BufSz + SIZE(InData%StrtTime) ! StrtTime + Int_BufSz = Int_BufSz + SIZE(InData%SimStrtTime) ! SimStrtTime + Int_BufSz = Int_BufSz + 1 ! calcJacobian + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! ExternInput: size of buffers for each call to pack subtype + CALL FAST_Packexterninputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExternInput, ErrStat2, ErrMsg2, .TRUE. ) ! ExternInput + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ExternInput + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ExternInput + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ExternInput + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Lin: size of buffers for each call to pack subtype + CALL FAST_Packmisclintype( Re_Buf, Db_Buf, Int_Buf, InData%Lin, ErrStat2, ErrMsg2, .TRUE. ) ! Lin + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Lin + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Lin + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Lin + 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 + + DbKiBuf(Db_Xferred) = InData%TiLstPrn + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%t_global + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%NextJacCalcTime + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PrevClockTime + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UsrTime1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%UsrTime2 + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%StrtTime,1), UBOUND(InData%StrtTime,1) + IntKiBuf(Int_Xferred) = InData%StrtTime(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SimStrtTime,1), UBOUND(InData%SimStrtTime,1) + IntKiBuf(Int_Xferred) = InData%SimStrtTime(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%calcJacobian, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL FAST_Packexterninputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExternInput, ErrStat2, ErrMsg2, OnlySize ) ! ExternInput + 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 FAST_Packmisclintype( Re_Buf, Db_Buf, Int_Buf, InData%Lin, ErrStat2, ErrMsg2, OnlySize ) ! Lin + 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 FAST_PackMisc + + SUBROUTINE FAST_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(FAST_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_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%TiLstPrn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%t_global = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NextJacCalcTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%PrevClockTime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UsrTime1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UsrTime2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%StrtTime,1) + i1_u = UBOUND(OutData%StrtTime,1) + DO i1 = LBOUND(OutData%StrtTime,1), UBOUND(OutData%StrtTime,1) + OutData%StrtTime(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SimStrtTime,1) + i1_u = UBOUND(OutData%SimStrtTime,1) + DO i1 = LBOUND(OutData%SimStrtTime,1), UBOUND(OutData%SimStrtTime,1) + OutData%SimStrtTime(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + OutData%calcJacobian = TRANSFER(IntKiBuf(Int_Xferred), OutData%calcJacobian) + 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 FAST_Unpackexterninputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExternInput, ErrStat2, ErrMsg2 ) ! ExternInput + 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 FAST_Unpackmisclintype( Re_Buf, Db_Buf, Int_Buf, OutData%Lin, ErrStat2, ErrMsg2 ) ! Lin + 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 FAST_UnPackMisc + + SUBROUTINE FAST_CopyExternInitType( SrcExternInitTypeData, DstExternInitTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_ExternInitType), INTENT(IN) :: SrcExternInitTypeData + TYPE(FAST_ExternInitType), INTENT(INOUT) :: DstExternInitTypeData + 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 = 'FAST_CopyExternInitType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstExternInitTypeData%Tmax = SrcExternInitTypeData%Tmax + DstExternInitTypeData%SensorType = SrcExternInitTypeData%SensorType + DstExternInitTypeData%LidRadialVel = SrcExternInitTypeData%LidRadialVel + DstExternInitTypeData%TurbineID = SrcExternInitTypeData%TurbineID + DstExternInitTypeData%TurbinePos = SrcExternInitTypeData%TurbinePos + DstExternInitTypeData%NumSC2Ctrl = SrcExternInitTypeData%NumSC2Ctrl + DstExternInitTypeData%NumCtrl2SC = SrcExternInitTypeData%NumCtrl2SC + DstExternInitTypeData%FarmIntegration = SrcExternInitTypeData%FarmIntegration + DstExternInitTypeData%windGrid_n = SrcExternInitTypeData%windGrid_n + DstExternInitTypeData%windGrid_delta = SrcExternInitTypeData%windGrid_delta + DstExternInitTypeData%windGrid_pZero = SrcExternInitTypeData%windGrid_pZero + DstExternInitTypeData%RootName = SrcExternInitTypeData%RootName + DstExternInitTypeData%NumActForcePtsBlade = SrcExternInitTypeData%NumActForcePtsBlade + DstExternInitTypeData%NumActForcePtsTower = SrcExternInitTypeData%NumActForcePtsTower + END SUBROUTINE FAST_CopyExternInitType + + SUBROUTINE FAST_DestroyExternInitType( ExternInitTypeData, ErrStat, ErrMsg ) + TYPE(FAST_ExternInitType), INTENT(INOUT) :: ExternInitTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyExternInitType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE FAST_DestroyExternInitType + + SUBROUTINE FAST_PackExternInitType( 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(FAST_ExternInitType), 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 = 'FAST_PackExternInitType' + ! 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 + Db_BufSz = Db_BufSz + 1 ! Tmax + Int_BufSz = Int_BufSz + 1 ! SensorType + Int_BufSz = Int_BufSz + 1 ! LidRadialVel + Int_BufSz = Int_BufSz + 1 ! TurbineID + Re_BufSz = Re_BufSz + SIZE(InData%TurbinePos) ! TurbinePos + Int_BufSz = Int_BufSz + 1 ! NumSC2Ctrl + Int_BufSz = Int_BufSz + 1 ! NumCtrl2SC + Int_BufSz = Int_BufSz + 1 ! FarmIntegration + Int_BufSz = Int_BufSz + SIZE(InData%windGrid_n) ! windGrid_n + Re_BufSz = Re_BufSz + SIZE(InData%windGrid_delta) ! windGrid_delta + Re_BufSz = Re_BufSz + SIZE(InData%windGrid_pZero) ! windGrid_pZero + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! NumActForcePtsBlade + Int_BufSz = Int_BufSz + 1 ! NumActForcePtsTower + 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 + + DbKiBuf(Db_Xferred) = InData%Tmax + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SensorType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LidRadialVel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TurbineID + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TurbinePos,1), UBOUND(InData%TurbinePos,1) + ReKiBuf(Re_Xferred) = InData%TurbinePos(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NumSC2Ctrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCtrl2SC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FarmIntegration, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%windGrid_n,1), UBOUND(InData%windGrid_n,1) + IntKiBuf(Int_Xferred) = InData%windGrid_n(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%windGrid_delta,1), UBOUND(InData%windGrid_delta,1) + ReKiBuf(Re_Xferred) = InData%windGrid_delta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%windGrid_pZero,1), UBOUND(InData%windGrid_pZero,1) + ReKiBuf(Re_Xferred) = InData%windGrid_pZero(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%NumActForcePtsBlade + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumActForcePtsTower + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_PackExternInitType + + SUBROUTINE FAST_UnPackExternInitType( 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(FAST_ExternInitType), 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 = 'FAST_UnPackExternInitType' + ! 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%Tmax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%SensorType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%LidRadialVel = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidRadialVel) + Int_Xferred = Int_Xferred + 1 + OutData%TurbineID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TurbinePos,1) + i1_u = UBOUND(OutData%TurbinePos,1) + DO i1 = LBOUND(OutData%TurbinePos,1), UBOUND(OutData%TurbinePos,1) + OutData%TurbinePos(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%NumSC2Ctrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumCtrl2SC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FarmIntegration = TRANSFER(IntKiBuf(Int_Xferred), OutData%FarmIntegration) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%windGrid_n,1) + i1_u = UBOUND(OutData%windGrid_n,1) + DO i1 = LBOUND(OutData%windGrid_n,1), UBOUND(OutData%windGrid_n,1) + OutData%windGrid_n(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%windGrid_delta,1) + i1_u = UBOUND(OutData%windGrid_delta,1) + DO i1 = LBOUND(OutData%windGrid_delta,1), UBOUND(OutData%windGrid_delta,1) + OutData%windGrid_delta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%windGrid_pZero,1) + i1_u = UBOUND(OutData%windGrid_pZero,1) + DO i1 = LBOUND(OutData%windGrid_pZero,1), UBOUND(OutData%windGrid_pZero,1) + OutData%windGrid_pZero(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NumActForcePtsBlade = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumActForcePtsTower = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE FAST_UnPackExternInitType + + SUBROUTINE FAST_CopyTurbineType( SrcTurbineTypeData, DstTurbineTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FAST_TurbineType), INTENT(INOUT) :: SrcTurbineTypeData + TYPE(FAST_TurbineType), INTENT(INOUT) :: DstTurbineTypeData + 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 = 'FAST_CopyTurbineType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstTurbineTypeData%TurbID = SrcTurbineTypeData%TurbID + CALL FAST_CopyParam( SrcTurbineTypeData%p_FAST, DstTurbineTypeData%p_FAST, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyoutputfiletype( SrcTurbineTypeData%y_FAST, DstTurbineTypeData%y_FAST, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_CopyMisc( SrcTurbineTypeData%m_FAST, DstTurbineTypeData%m_FAST, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copymodulemaptype( SrcTurbineTypeData%MeshMapData, DstTurbineTypeData%MeshMapData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyelastodyn_data( SrcTurbineTypeData%ED, DstTurbineTypeData%ED, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copybeamdyn_data( SrcTurbineTypeData%BD, DstTurbineTypeData%BD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyservodyn_data( SrcTurbineTypeData%SrvD, DstTurbineTypeData%SrvD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyaerodyn_data( SrcTurbineTypeData%AD, DstTurbineTypeData%AD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyaerodyn14_data( SrcTurbineTypeData%AD14, DstTurbineTypeData%AD14, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyinflowwind_data( SrcTurbineTypeData%IfW, DstTurbineTypeData%IfW, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyopenfoam_data( SrcTurbineTypeData%OpFM, DstTurbineTypeData%OpFM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copysupercontroller_data( SrcTurbineTypeData%SC, DstTurbineTypeData%SC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyhydrodyn_data( SrcTurbineTypeData%HD, DstTurbineTypeData%HD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copysubdyn_data( SrcTurbineTypeData%SD, DstTurbineTypeData%SD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copymap_data( SrcTurbineTypeData%MAP, DstTurbineTypeData%MAP, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyfeamooring_data( SrcTurbineTypeData%FEAM, DstTurbineTypeData%FEAM, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copymoordyn_data( SrcTurbineTypeData%MD, DstTurbineTypeData%MD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyorcaflex_data( SrcTurbineTypeData%Orca, DstTurbineTypeData%Orca, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyicefloe_data( SrcTurbineTypeData%IceF, DstTurbineTypeData%IceF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyicedyn_data( SrcTurbineTypeData%IceD, DstTurbineTypeData%IceD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FAST_Copyextptfm_data( SrcTurbineTypeData%ExtPtfm, DstTurbineTypeData%ExtPtfm, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FAST_CopyTurbineType + + SUBROUTINE FAST_DestroyTurbineType( TurbineTypeData, ErrStat, ErrMsg ) + TYPE(FAST_TurbineType), INTENT(INOUT) :: TurbineTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_DestroyTurbineType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL FAST_DestroyParam( TurbineTypeData%p_FAST, ErrStat, ErrMsg ) + CALL FAST_Destroyoutputfiletype( TurbineTypeData%y_FAST, ErrStat, ErrMsg ) + CALL FAST_DestroyMisc( TurbineTypeData%m_FAST, ErrStat, ErrMsg ) + CALL FAST_Destroymodulemaptype( TurbineTypeData%MeshMapData, ErrStat, ErrMsg ) + CALL FAST_Destroyelastodyn_data( TurbineTypeData%ED, ErrStat, ErrMsg ) + CALL FAST_Destroybeamdyn_data( TurbineTypeData%BD, ErrStat, ErrMsg ) + CALL FAST_Destroyservodyn_data( TurbineTypeData%SrvD, ErrStat, ErrMsg ) + CALL FAST_Destroyaerodyn_data( TurbineTypeData%AD, ErrStat, ErrMsg ) + CALL FAST_Destroyaerodyn14_data( TurbineTypeData%AD14, ErrStat, ErrMsg ) + CALL FAST_Destroyinflowwind_data( TurbineTypeData%IfW, ErrStat, ErrMsg ) + CALL FAST_Destroyopenfoam_data( TurbineTypeData%OpFM, ErrStat, ErrMsg ) + CALL FAST_Destroysupercontroller_data( TurbineTypeData%SC, ErrStat, ErrMsg ) + CALL FAST_Destroyhydrodyn_data( TurbineTypeData%HD, ErrStat, ErrMsg ) + CALL FAST_Destroysubdyn_data( TurbineTypeData%SD, ErrStat, ErrMsg ) + CALL FAST_Destroymap_data( TurbineTypeData%MAP, ErrStat, ErrMsg ) + CALL FAST_Destroyfeamooring_data( TurbineTypeData%FEAM, ErrStat, ErrMsg ) + CALL FAST_Destroymoordyn_data( TurbineTypeData%MD, ErrStat, ErrMsg ) + CALL FAST_Destroyorcaflex_data( TurbineTypeData%Orca, ErrStat, ErrMsg ) + CALL FAST_Destroyicefloe_data( TurbineTypeData%IceF, ErrStat, ErrMsg ) + CALL FAST_Destroyicedyn_data( TurbineTypeData%IceD, ErrStat, ErrMsg ) + CALL FAST_Destroyextptfm_data( TurbineTypeData%ExtPtfm, ErrStat, ErrMsg ) + END SUBROUTINE FAST_DestroyTurbineType + + SUBROUTINE FAST_PackTurbineType( 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(FAST_TurbineType), 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 = 'FAST_PackTurbineType' + ! 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 ! TurbID + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! p_FAST: size of buffers for each call to pack subtype + CALL FAST_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p_FAST, ErrStat2, ErrMsg2, .TRUE. ) ! p_FAST + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! p_FAST + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! p_FAST + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! p_FAST + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! y_FAST: size of buffers for each call to pack subtype + CALL FAST_Packoutputfiletype( Re_Buf, Db_Buf, Int_Buf, InData%y_FAST, ErrStat2, ErrMsg2, .TRUE. ) ! y_FAST + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_FAST + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_FAST + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_FAST + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! m_FAST: size of buffers for each call to pack subtype + CALL FAST_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m_FAST, ErrStat2, ErrMsg2, .TRUE. ) ! m_FAST + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! m_FAST + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! m_FAST + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! m_FAST + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! MeshMapData: size of buffers for each call to pack subtype + CALL FAST_Packmodulemaptype( Re_Buf, Db_Buf, Int_Buf, InData%MeshMapData, ErrStat2, ErrMsg2, .TRUE. ) ! MeshMapData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MeshMapData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MeshMapData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MeshMapData + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ED: size of buffers for each call to pack subtype + CALL FAST_Packelastodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%ED, ErrStat2, ErrMsg2, .TRUE. ) ! ED + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! BD: size of buffers for each call to pack subtype + CALL FAST_Packbeamdyn_data( Re_Buf, Db_Buf, Int_Buf, InData%BD, ErrStat2, ErrMsg2, .TRUE. ) ! BD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! BD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! BD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! BD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SrvD: size of buffers for each call to pack subtype + CALL FAST_Packservodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%SrvD, ErrStat2, ErrMsg2, .TRUE. ) ! SrvD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SrvD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SrvD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SrvD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AD: size of buffers for each call to pack subtype + CALL FAST_Packaerodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%AD, ErrStat2, ErrMsg2, .TRUE. ) ! AD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! AD14: size of buffers for each call to pack subtype + CALL FAST_Packaerodyn14_data( Re_Buf, Db_Buf, Int_Buf, InData%AD14, ErrStat2, ErrMsg2, .TRUE. ) ! AD14 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! AD14 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! AD14 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! AD14 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IfW: size of buffers for each call to pack subtype + CALL FAST_Packinflowwind_data( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, .TRUE. ) ! IfW + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IfW + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IfW + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IfW + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! OpFM: size of buffers for each call to pack subtype + CALL FAST_Packopenfoam_data( Re_Buf, Db_Buf, Int_Buf, InData%OpFM, ErrStat2, ErrMsg2, .TRUE. ) ! OpFM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OpFM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OpFM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OpFM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SC: size of buffers for each call to pack subtype + CALL FAST_Packsupercontroller_data( Re_Buf, Db_Buf, Int_Buf, InData%SC, ErrStat2, ErrMsg2, .TRUE. ) ! SC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SC + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SC + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SC + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HD: size of buffers for each call to pack subtype + CALL FAST_Packhydrodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%HD, ErrStat2, ErrMsg2, .TRUE. ) ! HD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! SD: size of buffers for each call to pack subtype + CALL FAST_Packsubdyn_data( Re_Buf, Db_Buf, Int_Buf, InData%SD, ErrStat2, ErrMsg2, .TRUE. ) ! SD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! MAP: size of buffers for each call to pack subtype + CALL FAST_Packmap_data( Re_Buf, Db_Buf, Int_Buf, InData%MAP, ErrStat2, ErrMsg2, .TRUE. ) ! MAP + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MAP + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MAP + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MAP + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FEAM: size of buffers for each call to pack subtype + CALL FAST_Packfeamooring_data( Re_Buf, Db_Buf, Int_Buf, InData%FEAM, ErrStat2, ErrMsg2, .TRUE. ) ! FEAM + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FEAM + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FEAM + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FEAM + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! MD: size of buffers for each call to pack subtype + CALL FAST_Packmoordyn_data( Re_Buf, Db_Buf, Int_Buf, InData%MD, ErrStat2, ErrMsg2, .TRUE. ) ! MD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Orca: size of buffers for each call to pack subtype + CALL FAST_Packorcaflex_data( Re_Buf, Db_Buf, Int_Buf, InData%Orca, ErrStat2, ErrMsg2, .TRUE. ) ! Orca + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Orca + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Orca + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Orca + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IceF: size of buffers for each call to pack subtype + CALL FAST_Packicefloe_data( Re_Buf, Db_Buf, Int_Buf, InData%IceF, ErrStat2, ErrMsg2, .TRUE. ) ! IceF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IceF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IceF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IceF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! IceD: size of buffers for each call to pack subtype + CALL FAST_Packicedyn_data( Re_Buf, Db_Buf, Int_Buf, InData%IceD, ErrStat2, ErrMsg2, .TRUE. ) ! IceD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! IceD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! IceD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! IceD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ExtPtfm: size of buffers for each call to pack subtype + CALL FAST_Packextptfm_data( Re_Buf, Db_Buf, Int_Buf, InData%ExtPtfm, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPtfm + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ExtPtfm + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ExtPtfm + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ExtPtfm + 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%TurbID + Int_Xferred = Int_Xferred + 1 + CALL FAST_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%p_FAST, ErrStat2, ErrMsg2, OnlySize ) ! p_FAST + 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 FAST_Packoutputfiletype( Re_Buf, Db_Buf, Int_Buf, InData%y_FAST, ErrStat2, ErrMsg2, OnlySize ) ! y_FAST + 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 FAST_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%m_FAST, ErrStat2, ErrMsg2, OnlySize ) ! m_FAST + 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 FAST_Packmodulemaptype( Re_Buf, Db_Buf, Int_Buf, InData%MeshMapData, ErrStat2, ErrMsg2, OnlySize ) ! MeshMapData + 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 FAST_Packelastodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%ED, ErrStat2, ErrMsg2, OnlySize ) ! ED + 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 FAST_Packbeamdyn_data( Re_Buf, Db_Buf, Int_Buf, InData%BD, ErrStat2, ErrMsg2, OnlySize ) ! BD + 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 FAST_Packservodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%SrvD, ErrStat2, ErrMsg2, OnlySize ) ! SrvD + 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 FAST_Packaerodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%AD, ErrStat2, ErrMsg2, OnlySize ) ! AD + 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 FAST_Packaerodyn14_data( Re_Buf, Db_Buf, Int_Buf, InData%AD14, ErrStat2, ErrMsg2, OnlySize ) ! AD14 + 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 FAST_Packinflowwind_data( Re_Buf, Db_Buf, Int_Buf, InData%IfW, ErrStat2, ErrMsg2, OnlySize ) ! IfW + 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 FAST_Packopenfoam_data( Re_Buf, Db_Buf, Int_Buf, InData%OpFM, ErrStat2, ErrMsg2, OnlySize ) ! OpFM + 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 FAST_Packsupercontroller_data( Re_Buf, Db_Buf, Int_Buf, InData%SC, ErrStat2, ErrMsg2, OnlySize ) ! SC + 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 FAST_Packhydrodyn_data( Re_Buf, Db_Buf, Int_Buf, InData%HD, ErrStat2, ErrMsg2, OnlySize ) ! HD + 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 FAST_Packsubdyn_data( Re_Buf, Db_Buf, Int_Buf, InData%SD, ErrStat2, ErrMsg2, OnlySize ) ! SD + 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 FAST_Packmap_data( Re_Buf, Db_Buf, Int_Buf, InData%MAP, ErrStat2, ErrMsg2, OnlySize ) ! MAP + 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 FAST_Packfeamooring_data( Re_Buf, Db_Buf, Int_Buf, InData%FEAM, ErrStat2, ErrMsg2, OnlySize ) ! FEAM + 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 FAST_Packmoordyn_data( Re_Buf, Db_Buf, Int_Buf, InData%MD, ErrStat2, ErrMsg2, OnlySize ) ! MD + 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 FAST_Packorcaflex_data( Re_Buf, Db_Buf, Int_Buf, InData%Orca, ErrStat2, ErrMsg2, OnlySize ) ! Orca + 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 FAST_Packicefloe_data( Re_Buf, Db_Buf, Int_Buf, InData%IceF, ErrStat2, ErrMsg2, OnlySize ) ! IceF + 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 FAST_Packicedyn_data( Re_Buf, Db_Buf, Int_Buf, InData%IceD, ErrStat2, ErrMsg2, OnlySize ) ! IceD + 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 FAST_Packextptfm_data( Re_Buf, Db_Buf, Int_Buf, InData%ExtPtfm, ErrStat2, ErrMsg2, OnlySize ) ! ExtPtfm + 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 FAST_PackTurbineType + + SUBROUTINE FAST_UnPackTurbineType( 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(FAST_TurbineType), 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 = 'FAST_UnPackTurbineType' + ! 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%TurbID = 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 FAST_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%p_FAST, ErrStat2, ErrMsg2 ) ! p_FAST + 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 FAST_Unpackoutputfiletype( Re_Buf, Db_Buf, Int_Buf, OutData%y_FAST, ErrStat2, ErrMsg2 ) ! y_FAST + 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 FAST_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%m_FAST, ErrStat2, ErrMsg2 ) ! m_FAST + 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 FAST_Unpackmodulemaptype( Re_Buf, Db_Buf, Int_Buf, OutData%MeshMapData, ErrStat2, ErrMsg2 ) ! MeshMapData + 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 FAST_Unpackelastodyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%ED, ErrStat2, ErrMsg2 ) ! ED + 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 FAST_Unpackbeamdyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%BD, ErrStat2, ErrMsg2 ) ! BD + 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 FAST_Unpackservodyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%SrvD, ErrStat2, ErrMsg2 ) ! SrvD + 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 FAST_Unpackaerodyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%AD, ErrStat2, ErrMsg2 ) ! AD + 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 FAST_Unpackaerodyn14_data( Re_Buf, Db_Buf, Int_Buf, OutData%AD14, ErrStat2, ErrMsg2 ) ! AD14 + 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 FAST_Unpackinflowwind_data( Re_Buf, Db_Buf, Int_Buf, OutData%IfW, ErrStat2, ErrMsg2 ) ! IfW + 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 FAST_Unpackopenfoam_data( Re_Buf, Db_Buf, Int_Buf, OutData%OpFM, ErrStat2, ErrMsg2 ) ! OpFM + 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 FAST_Unpacksupercontroller_data( Re_Buf, Db_Buf, Int_Buf, OutData%SC, ErrStat2, ErrMsg2 ) ! SC + 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 FAST_Unpackhydrodyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%HD, ErrStat2, ErrMsg2 ) ! HD + 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 FAST_Unpacksubdyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%SD, ErrStat2, ErrMsg2 ) ! SD + 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 FAST_Unpackmap_data( Re_Buf, Db_Buf, Int_Buf, OutData%MAP, ErrStat2, ErrMsg2 ) ! MAP + 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 FAST_Unpackfeamooring_data( Re_Buf, Db_Buf, Int_Buf, OutData%FEAM, ErrStat2, ErrMsg2 ) ! FEAM + 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 FAST_Unpackmoordyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%MD, ErrStat2, ErrMsg2 ) ! MD + 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 FAST_Unpackorcaflex_data( Re_Buf, Db_Buf, Int_Buf, OutData%Orca, ErrStat2, ErrMsg2 ) ! Orca + 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 FAST_Unpackicefloe_data( Re_Buf, Db_Buf, Int_Buf, OutData%IceF, ErrStat2, ErrMsg2 ) ! IceF + 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 FAST_Unpackicedyn_data( Re_Buf, Db_Buf, Int_Buf, OutData%IceD, ErrStat2, ErrMsg2 ) ! IceD + 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 FAST_Unpackextptfm_data( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPtfm, ErrStat2, ErrMsg2 ) ! ExtPtfm + 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 FAST_UnPackTurbineType + +END MODULE FAST_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/openfast-registry/CMakeLists.txt b/OpenFAST/modules/openfast-registry/CMakeLists.txt new file mode 100644 index 000000000..8e373eb4a --- /dev/null +++ b/OpenFAST/modules/openfast-registry/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# Copyright 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. +# + +set(REGISTRY_SOURCES + src/data.c + src/gen_c_types.c + src/gen_module_files.c + src/misc.c + src/my_strtok.c + src/reg_parse.c + src/registry.c + src/sym.c + src/symtab_gen.c + src/type.c + ) + +add_executable(openfast_registry ${REGISTRY_SOURCES}) + +set_target_properties(openfast_registry PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/modules/openfast-registry + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/modules/openfast-registry +) diff --git a/OpenFAST/modules/openfast-registry/README.md b/OpenFAST/modules/openfast-registry/README.md new file mode 100644 index 000000000..985db5770 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/README.md @@ -0,0 +1,64 @@ +# OpenFAST Registry Module +The legacy version of this module and additional documentation are available +at the [NWTC Legacy Repository](https://github.com/old-NWTC/FAST_Registry). + +## Overview +The OpenFAST Registry is a utility for generating code for module data types in +the OpenFAST Framework. + +The OpenFAST Registry allows the developer to specify the data types for a +module once and in a single location, automating the time consuming and +error-prone task of generating the code. The tables in the Registry text input +files serve as a data dictionary for improving understandability and +maintainability of the code. + +The FAST Registry is borrowed from a mechanism that was originally developed at +NCAR for the [Weather Research and Forecast (WRF) model software] +(http://www.mmm.ucar.edu/wrf/WG2/software_2.0/registry_schaffer.pdf). It has +been modified for the FAST Modularization Framework to +create *ModuleName*_Types.f90 files along with any necessary C source code or +header files associated with the *ModuleName*_Types.f90 files. + +## Syntax +To create *ModuleName*_Types.f90 from data defined in RegistryFile.txt: +``` + >>> openfast_registry RegistryFile.txt [options] +``` +To create template *ModuleName*_Registry.txt file: +``` + >>> openfast_registry -registry ModuleName ModName +``` +To create template file for *ModuleName*.f90: +``` + >>> openfast_registry -template ModuleName ModName +``` +Summary of options: + +``` + >>> openfast_registry -h + + ----- FAST Registry (v3.01.00, 11-Jan-2016) -------------- + ---------------------------------------------------------- + Usage: Registry_win32.exe registryfile [options] -or- + [-force] [-template|-registry] ModuleName ModName + Options: + -h this summary + -I <dir> look for usefrom files in directory "dir" + -O <dir> generate types files in directory "dir" + -noextrap do not generate ModName_Input_ExtrapInterp or ModName_Output_ExtrapInterp routines + -D<SYM> define symbol for conditional evaluation inside registry file + -ccode generate additional code for interfacing with C/C++ + -keep do not delete temporary files from registry program + -shownodes output a listing of the nodes in registry's AST + === alternate usage for generating templates === + -template ModuleName ModName + Generate a template Module file none exists + -registry ModuleName ModName + Generate a template registry file if none exists + -force Force generating of template or registry file + (the / character can be used in place of - when specifying options) +``` + +## Manual +For more information and syntax, please refer to the +[NWTC Programmer's Handbook](https://nwtc.nrel.gov/system/files/ProgrammingHandbook_Mod20130717.pdf). diff --git a/OpenFAST/modules/openfast-registry/src/FAST_preamble.h b/OpenFAST/modules/openfast-registry/src/FAST_preamble.h new file mode 100644 index 000000000..74de0a837 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/FAST_preamble.h @@ -0,0 +1,45 @@ +static char *FAST_preamble[] = { +"!*********************************************************************************************************************************\n", +"! %s_Types\n", +"!.................................................................................................................................\n", +"! This file is part of %s.\n", +"!\n", +"! Copyright (C) 2012-2016 National Renewable Energy Laboratory\n", +"!\n", +"! Licensed under the Apache License, Version 2.0 (the \"License\");\n", +"! you may not use this file except in compliance with the License.\n", +"! You may obtain a copy of the License at\n", +"!\n", +"! http://www.apache.org/licenses/LICENSE-2.0\n", +"!\n", +"! Unless required by applicable law or agreed to in writing, software\n", +"! distributed under the License is distributed on an \"AS IS\" BASIS,\n", +"! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", +"! See the License for the specific language governing permissions and\n", +"! limitations under the License.\n", +"!\n", +"!\n", +"! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost.\n", +"!\n", +"!*********************************************************************************************************************************\n", +"!> This module contains the user-defined types needed in %s. It also contains copy, destroy, pack, and\n", +"!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry.\n", +"MODULE %s_Types\n", +"!---------------------------------------------------------------------------------------------------------------------------------\n", +// We may be generating the types for the library, so defer writing this: "USE NWTC_Library\n", +// We may want to tack some more USE statements on so defer writing this: "IMPLICIT NONE\n", +0L} ; + + + + + + + + + + + + + + diff --git a/OpenFAST/modules/openfast-registry/src/Template_data.c b/OpenFAST/modules/openfast-registry/src/Template_data.c new file mode 100644 index 000000000..22aa731e7 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/Template_data.c @@ -0,0 +1,849 @@ +char *template_data[] = { +"!**********************************************************************************************************************************", +"!> ## ModuleName", +"!! The ModuleName and ModuleName_Types modules make up a template for creating user-defined calculations in the FAST Modularization", +"!! Framework. ModuleName_Types will be auto-generated by the FAST registry program, based on the variables specified in the", +"!! ModuleName_Registry.txt file.", +"!!", +"! ..................................................................................................................................", +"!! ## LICENSING", +"!! Copyright (C) 2012-2013, 2015-2016 National Renewable Energy Laboratory", +"!!", +"!! This file is part of ModuleName.", +"!!", +"!! 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 ModuleName", +"", +" USE ModuleName_Types", +" USE NWTC_Library", +"", +" IMPLICIT NONE", +"", +" PRIVATE", +"", +" TYPE(ProgDesc), PARAMETER :: ModName_Ver = ProgDesc( 'ModuleName', '', '' ) !< module date/version information", +"", +"", +" ! ..... Public Subroutines ...................................................................................................", +"", +" PUBLIC :: ModName_Init ! Initialization routine", +" PUBLIC :: ModName_End ! Ending routine (includes clean up)", +"", +" PUBLIC :: ModName_UpdateStates ! Loose coupling routine for solving for constraint states, integrating", +" ! continuous states, and updating discrete states", +" PUBLIC :: ModName_CalcOutput ! Routine for computing outputs", +"", +" PUBLIC :: ModName_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual", +" PUBLIC :: ModName_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states", +" PUBLIC :: ModName_UpdateDiscState ! Tight coupling routine for updating discrete states", +"", +" PUBLIC :: ModName_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 :: ModName_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 :: ModName_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 :: ModName_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 :: ModName_GetOP ! Routine to get the operating-point values for linearization (from data structures to arrays)", +"", +"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.", +"!! The initial states and initial guess for the input are defined. ", +"SUBROUTINE ModName_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, InitOut, ErrStat, ErrMsg )", +"!..................................................................................................................................", +"", +" TYPE(ModName_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine", +" TYPE(ModName_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined", +" TYPE(ModName_ParameterType), INTENT( OUT) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states", +" TYPE(ModName_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states", +" TYPE(ModName_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states", +" TYPE(ModName_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (logical, etc)", +" TYPE(ModName_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated;", +" !! only the output mesh is initialized)", +" TYPE(ModName_MiscVarType), INTENT( OUT) :: misc !< Misc variables for optimization (not copied in glue code)", +" REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that", +" !! (1) ModName_UpdateStates() is called in loose coupling &", +" !! (2) ModName_UpdateDiscState() is called in tight coupling.", +" !! Input is the suggested time from the glue code;", +" !! Output is the actual coupling interval that will be used", +" !! by the glue code.", +" TYPE(ModName_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine", +" INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation", +" CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None", +"", +" ! local variables", +"", +" INTEGER(IntKi) :: NumOuts ! number of outputs; would probably be in the parameter type", +" INTEGER(IntKi) :: ErrStat2 ! local error status", +" CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message", +" CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Init'", +"", +" !! Initialize variables", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +" NumOuts = 2", +"", +"", +" ! Initialize the NWTC Subroutine Library", +"", +" call NWTC_Init( )", +"", +" ! Display the module information", +"", +" call DispNVD( ModName_Ver )", +"", +"", +" ! Define parameters here:", +"", +" p%DT = Interval", +"", +"", +" ! Define initial system states here:", +"", +" x%DummyContState = 0.0_ReKi", +" xd%DummyDiscState = 0.0_ReKi", +" z%DummyConstrState = 0.0_ReKi", +" OtherState%DummyOtherState = 0.0_ReKi", +"", +" ! define optimization variables here:", +" misc%DummyMiscVar = 0.0_ReKi", +"", +" ! Define initial guess for the system inputs here:", +"", +" u%DummyInput = 0.0_ReKi", +"", +"", +" ! Define system output initializations (set up mesh) here:", +" call AllocAry( y%WriteOutput, NumOuts, 'WriteOutput', ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! set return error status based on local (concatenate errors)", +" if (ErrStat >= AbortErrLev) return ! if there are local variables that need to be deallocated, do so before early return", +" ", +" y%DummyOutput = 0", +" y%WriteOutput = 0", +"", +"", +" ! Define initialization-routine output here:", +" call AllocAry(InitOut%WriteOutputHdr,NumOuts,'WriteOutputHdr',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" call AllocAry(InitOut%WriteOutputUnt,NumOuts,'WriteOutputUnt',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if (ErrStat >= AbortErrLev) return ! if there are local variables that need to be deallocated, do so before early return", +"", +" InitOut%WriteOutputHdr = (/ 'Time ', 'Column2' /)", +" InitOut%WriteOutputUnt = (/ '(s)', '(-)' /)", +"", +"", +" ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which", +" ! this module must be called here:", +"", +" !Interval = p%DT", +"", +"", +" if (InitInp%Linearize) then", +"", +" ! If this module does not implement the four Jacobian routines at the end of this template, or the module cannot", +" ! linearize with the features that are enabled, stop the simulation if InitInp%Linearize is true.", +"", +" CALL SetErrStat( ErrID_Fatal, 'ModuleName cannot perform linearization analysis.', ErrStat, ErrMsg, RoutineName)", +"", +" ! Otherwise, if the module does allow linearization, return the appropriate Jacobian row/column names and rotating-frame flags here:", +" ! Allocate and set these variables: InitOut%LinNames_y, InitOut%LinNames_x, InitOut%LinNames_xd, InitOut%LinNames_z, InitOut%LinNames_u", +" ! Allocate and set these variables: InitOut%RotFrame_y, InitOut%RotFrame_x, InitOut%RotFrame_xd, InitOut%RotFrame_z, InitOut%RotFrame_u", +" ! Allocate and set these variables: InitOut%IsLoad_u, InitOut%DerivOrder_x", +"", +" end if", +"", +"", +"END SUBROUTINE ModName_Init", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> This routine is called at the end of the simulation.", +"SUBROUTINE ModName_End( u, p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg )", +"!..................................................................................................................................", +"", +" TYPE(ModName_InputType), INTENT(INOUT) :: u !< System inputs", +" TYPE(ModName_ParameterType), INTENT(INOUT) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states", +" TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states", +" TYPE(ModName_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states", +" TYPE(ModName_OtherStateType), INTENT(INOUT) :: OtherState !< Other states", +" TYPE(ModName_OutputType), INTENT(INOUT) :: y !< System outputs", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< 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) :: ErrStat2 ! local error status", +" CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message", +" CHARACTER(*), PARAMETER :: RoutineName = 'ModName_End'", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" !! Place any last minute operations or calculations here:", +"", +"", +" !! Close files here (but because of checkpoint-restart capability, it is not recommended to have files open during the simulation):", +"", +"", +" !! Destroy the input data:", +"", +" call ModName_DestroyInput( u, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +"", +"", +" !! Destroy the parameter data:", +"", +" call ModName_DestroyParam( p, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +"", +" !! Destroy the state data:", +"", +" call ModName_DestroyContState( x, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" call ModName_DestroyDiscState( xd, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" call ModName_DestroyConstrState( z, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" call ModName_DestroyOtherState( OtherState, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +"", +"", +" !! Destroy the output data:", +"", +" call ModName_DestroyOutput( y, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +"", +" ", +" !! Destroy the misc data:", +"", +" call ModName_DestroyMisc( misc, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +"", +"", +"END SUBROUTINE ModName_End", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> 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 ModName_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, misc, 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(ModName_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes (output from this routine only ", +" !! because of record keeping in routines that copy meshes)", +" REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t;", +" !! Output: Continuous states at t + Interval", +" TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t;", +" !! Output: Discrete states at t + Interval", +" TYPE(ModName_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t;", +" !! Output: Constraint states at t + Interval", +" TYPE(ModName_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t;", +" !! Output: Other states at t + Interval", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< 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", +"", +" TYPE(ModName_ContinuousStateType) :: dxdt ! Continuous state derivatives at t", +" TYPE(ModName_DiscreteStateType) :: xd_t ! Discrete states at t (copy)", +" TYPE(ModName_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z)", +" TYPE(ModName_InputType) :: u ! Instantaneous inputs", +" ", +" INTEGER(IntKi) :: ErrStat2 ! local error status", +" CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message", +" CHARACTER(*), PARAMETER :: RoutineName = 'ModName_UpdateStates'", +"", +"", +" ! Initialize variables", +"", +" ErrStat = ErrID_None ! no error has occurred", +" ErrMsg = ''", +"", +"", +" ! This subroutine contains an example of how the states could be updated. Developers will", +" ! want to adjust the logic as necessary for their own situations.", +"", +"", +"", +" ! Get the inputs at time t, based on the array of values sent by the glue code:", +"", +" ! before calling ExtrapInterp routine, memory in u must be allocated; we can do that with a copy:", +" call ModName_CopyInput( Inputs(1), u, MESH_NEWCOPY, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup() ! to avoid memory leaks, we have to destroy the local variables that may have allocatable arrays or meshes", +" return", +" end if", +"", +" call ModName_Input_ExtrapInterp( Inputs, InputTimes, u, t, ErrStat2, ErrMsg2 ) ", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup()", +" return", +" end if", +"", +"", +"", +" ! Get first time derivatives of continuous states (dxdt):", +"", +" call ModName_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, misc, dxdt, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup()", +" return", +" end if", +"", +"", +" ! Update discrete states:", +" ! Note that xd [discrete state] is changed in ModName_UpdateDiscState() so xd will now contain values at t+Interval", +" ! We'll first make a copy that contains xd at time t, which will be used in computing the constraint states", +" call ModName_CopyDiscState( xd, xd_t, MESH_NEWCOPY, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup()", +" return", +" end if", +"", +" call ModName_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, misc, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup()", +" return", +" end if", +"", +"", +" ! Solve for the constraint states (z) here:", +"", +" ! Iterate until the value is within a given tolerance.", +"", +" ! DO ", +"", +" call ModName_CalcConstrStateResidual( t, u, p, x, xd_t, z, OtherState, misc, Z_Residual, ErrStat2, ErrMsg2 )", +" call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)", +" if ( ErrStat >= AbortErrLev ) then", +" call cleanup()", +" return", +" end if", +"", +" ! z =", +"", +" ! END DO", +"", +"", +"", +" ! Integrate (update) continuous states (x) here:", +"", +" !x = function of dxdt and x", +"", +"", +" ! Destroy local variables before returning", +" call cleanup()", +"", +"", +"CONTAINS", +" SUBROUTINE cleanup()", +" ! note that this routine inherits all of the data in ModName_UpdateStates", +"", +"", +" CALL ModName_DestroyInput( u, ErrStat2, ErrMsg2)", +" CALL ModName_DestroyConstrState( Z_Residual, ErrStat2, ErrMsg2)", +" CALL ModName_DestroyContState( dxdt, ErrStat2, ErrMsg2)", +" CALL ModName_DestroyDiscState( xd_t, ErrStat2, ErrMsg2) ", +"", +" END SUBROUTINE cleanup", +"END SUBROUTINE ModName_UpdateStates", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> This is a routine for computing outputs, used in both loose and tight coupling.", +"SUBROUTINE ModName_CalcOutput( t, u, p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg )", +"!..................................................................................................................................", +"", +" REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds", +" TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< Misc variables for optimization (not copied in glue code)", +" TYPE(ModName_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con-", +" !! nectivity information does not have to be recalculated)", +" INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation", +" CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None", +"", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" ! Compute outputs here:", +" y%DummyOutput = 2.0_ReKi", +"", +" y%WriteOutput(1) = REAL(t,ReKi)", +" y%WriteOutput(2) = 1.0_ReKi", +"", +"", +"END SUBROUTINE ModName_CalcOutput", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> This is a tight coupling routine for computing derivatives of continuous states.", +"SUBROUTINE ModName_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, misc, dxdt, ErrStat, ErrMsg )", +"!..................................................................................................................................", +"", +" REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds", +" TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< Misc variables for optimization (not copied in glue code)", +" TYPE(ModName_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t", +" INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation", +" CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None", +"", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" ! Compute the first time derivatives of the continuous states here:", +"", +" dxdt%DummyContState = 0.0_ReKi", +"", +"", +"END SUBROUTINE ModName_CalcContStateDeriv", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> This is a tight coupling routine for updating discrete states.", +"SUBROUTINE ModName_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, misc, 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(ModName_InputType), INTENT(IN ) :: u !< Inputs at t", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t", +" TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t;", +" !! Output: Discrete states at t + Interval", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< 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", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" ! Update discrete states here:", +"", +" xd%DummyDiscState = 0.0_Reki", +"", +"END SUBROUTINE ModName_UpdateDiscState", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> This is a tight coupling routine for solving for the residual of the constraint state functions.", +"SUBROUTINE ModName_CalcConstrStateResidual( t, u, p, x, xd, z, OtherState, misc, Z_residual, ErrStat, ErrMsg )", +"!..................................................................................................................................", +"", +" REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds", +" TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess)", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t", +" TYPE(ModName_MiscVarType), INTENT(INOUT) :: misc !< Misc variables for optimization (not copied in glue code)", +" TYPE(ModName_ConstraintStateType), INTENT( OUT) :: Z_residual !< Residual of the constraint state functions 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", +"", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" ! Solve for the residual of the constraint state functions here:", +"", +" Z_residual%DummyConstrState = 0.0_ReKi", +"", +"END SUBROUTINE ModName_CalcConstrStateResidual", +"", +"", +"!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"! ###### The following four routines are Jacobian routines for linearization capabilities #######", +"! If the module does not implement them, set ErrStat = ErrID_Fatal in ModName_Init() when InitInp%Linearize is .true.", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> 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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required)", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point", +" TYPE(ModName_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(ModName_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 the inputs (u) [intent in to avoid deallocation]", +" REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with", +" !! respect to the inputs (u) [intent in to avoid deallocation]", +" REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with", +" !! respect to the inputs (u) [intent in to avoid deallocation]", +" REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with", +" !! respect to the inputs (u) [intent in to avoid deallocation]", +"", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +"", +" IF ( PRESENT( dYdu ) ) THEN", +"", +" ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here:", +"", +" ! allocate and set dYdu", +"", +" END IF", +"", +" IF ( PRESENT( dXdu ) ) THEN", +"", +" ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here:", +"", +" ! allocate and set dXdu", +"", +" END IF", +"", +" IF ( PRESENT( dXddu ) ) THEN", +"", +" ! Calculate the partial derivative of the discrete state functions (Xd) with respect to the inputs (u) here:", +"", +" ! allocate and set dXddu", +"", +" END IF", +"", +" IF ( PRESENT( dZdu ) ) THEN", +"", +" ! Calculate the partial derivative of the constraint state functions (Z) with respect to the inputs (u) here:", +"", +" ! allocate and set dZdu", +"", +" END IF", +"", +"", +"END SUBROUTINE ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required)", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point", +" TYPE(ModName_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(ModName_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 ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required)", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point", +" TYPE(ModName_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(ModName_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 ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required)", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point", +" TYPE(ModName_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(ModName_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 ModName_JacobianPConstrState", +"!----------------------------------------------------------------------------------------------------------------------------------", +"!> Routine to pack the data structures representing the operating points into arrays for linearization.", +"SUBROUTINE ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required)", +" TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters", +" TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point", +" TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point", +" TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point", +" TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point", +" TYPE(ModName_OutputType), INTENT(IN ) :: y !< Output at operating point", +" TYPE(ModName_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", +"", +"", +" ! Initialize ErrStat", +"", +" ErrStat = ErrID_None", +" ErrMsg = ''", +"", +" IF ( PRESENT( u_op ) ) THEN", +"", +" END IF", +"", +" IF ( PRESENT( y_op ) ) THEN", +" END IF", +"", +" IF ( PRESENT( x_op ) ) THEN", +"", +" END IF", +"", +" IF ( PRESENT( dx_op ) ) THEN", +"", +" END IF", +"", +" IF ( PRESENT( xd_op ) ) THEN", +"", +" END IF", +"", +" IF ( PRESENT( z_op ) ) THEN", +"", +" END IF", +"", +"END SUBROUTINE ModName_GetOP", +"!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"", +"END MODULE ModuleName", +"!**********************************************************************************************************************************", +0L } ; diff --git a/OpenFAST/modules/openfast-registry/src/Template_registry.c b/OpenFAST/modules/openfast-registry/src/Template_registry.c new file mode 100644 index 000000000..e06dc7dca --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/Template_registry.c @@ -0,0 +1,81 @@ +char *template_registry[] = { +"###################################################################################################################################", +"# Registry for ModuleName in the FAST Modularization Framework", +"# This Registry file is used to create MODULE ModuleName_Types, which contains all of the user-defined types needed in ModuleName.", +"# It also contains copy, destroy, pack, and unpack routines associated with each defined data types.", +"#", +"# Entries are of the form", +"# keyword <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS>", +"#", +"# Use ^ as a shortcut for the value from the previous line.", +"# See NWTC Programmer's Handbook at https://nwtc.nrel.gov/FAST-Developers for further information on the format/contents of this file.", +"###################################################################################################################################", +"", +"# ...... Include files (definitions from NWTC Library) ............................................................................", +"include Registry_NWTC_Library.txt", +"", +"", +"# ..... Initialization data .......................................................................................................", +"# Define inputs that the initialization routine may need here:", +"# e.g., the name of the input file, the file root name, etc.", +"typedef ModuleName/ModName InitInputType CHARACTER(1024) InputFile - - - \"Name of the input file; remove if there is no file\" -", +"typedef ^ ^ LOGICAL Linearize - .FALSE. - \"Flag that tells this module if the glue code wants to linearize.\" -", +"", +"# Define outputs from the initialization routine here:", +"typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - \"Names of the output-to-file channels\" -", +"typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - \"Units of the output-to-file channels\" -", +"# if this module has implemented linearization, return the names of the rows/columns of the Jacobian matrices:", +"#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - \"Names of the outputs used in linearization\" - ", +"#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - \"Names of the continuous states used in linearization\" -", +"#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_xd {:} - - \"Names of the discrete states used in linearization\" -", +"#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_z {:} - - \"Names of the constraint states 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\" -", +"#typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - \"Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame\" -", +"#typedef ^ InitOutputType LOGICAL RotFrame_xd {:} - - \"Flag that tells FAST if the discrete states used in linearization are in the rotating frame\" -", +"#typedef ^ InitOutputType LOGICAL RotFrame_z {:} - - \"Flag that tells FAST if the constraint states used in linearization are in the rotating frame\" -", +"#typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - \"Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame\" -", +"#typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - \"Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrices)\" -", +"#typedef ^ InitOutputType IntKi DerivOrder_x {:} - - \"Integer that tells FAST/MBC3 the order derivative for the continuous states used in linearization\" -", +"", +"", +"# ..... States ....................................................................................................................", +"# Define continuous (differentiable) states here:", +"typedef ^ ContinuousStateType ReKi DummyContState - - - \"Remove this variable if you have continuous states\" -", +"", +"# Define discrete (nondifferentiable) states here:", +"typedef ^ DiscreteStateType ReKi DummyDiscState - - - \"Remove this variable if you have discrete states\" -", +"", +"# Define constraint states here:", +"typedef ^ ConstraintStateType ReKi DummyConstrState - - - \"Remove this variable if you have constraint states\" -", +"", +"# Define any other states, including integer or logical states here:", +"typedef ^ OtherStateType IntKi 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/optimization 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 DbKi DT - - - \"Time step for cont. state integration & disc. state update\" seconds", +"", +"", +"# ..... Inputs ....................................................................................................................", +"# Define inputs that are contained on the mesh here:", +"#typedef ^ InputType MeshType MeshedInput - - - \"Meshed data\" -", +"# Define inputs that are not on this mesh here:", +"typedef ^ InputType ReKi DummyInput - - - \"Remove this variable if you have input data\" -", +"", +"", +"# ..... Outputs ...................................................................................................................", +"# Define outputs that are contained on the mesh here:", +"#typedef ^ OutputType MeshType MeshedOutput - - - \"Meshed data\" -", +"# Define outputs that are not on this mesh here:", +"typedef ^ OutputType ReKi WriteOutput {:} - - \"Example of data to be written to an output file\" \"s,-\"", +"", +0L } ; diff --git a/OpenFAST/modules/openfast-registry/src/data.c b/OpenFAST/modules/openfast-registry/src/data.c new file mode 100644 index 000000000..3224b9118 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/data.c @@ -0,0 +1,229 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef _WIN32 +#define rindex(X,Y) strrchr(X,Y) +#define index(X,Y) strchr(X,Y) +#define bzero(X,Y) memset(X,0,Y) +#else +# include <strings.h> +#endif + +#include "registry.h" +#include "protos.h" +#include "data.h" + +int +init_modname_table() +{ + ModNames = NULL ; + return(0) ; +} + +int +init_dim_table() +{ + Dim = NULL ; + return(0) ; +} + +node_t * +new_node ( int kind ) +{ node_t *p ; + p = (node_t *)malloc(sizeof(node_t)) ; + bzero(p,sizeof(node_t)); + p->node_kind = kind ; + + p->fields = NULL; + p->params = NULL; + p->type = NULL; + p->module = NULL; + p->module_ddt_list = NULL; + p->next = NULL; + //p->coord_end_param = NULL; + strcpy(p->dim_param_name, ""); + p->dim_param = 0; + p->type_type = 0; + p->max_ndims = 0; + p->containsPtr = 0; + p->ndims = 0; + p->deferred = 0; + p->usefrom = 0; + p->is_interface_type = 0; + strcpy(p->name, ""); + strcpy(p->mapsto, ""); + strcpy(p->nickname, ""); + strcpy(p->descrip, ""); + strcpy(p->units, ""); + + return (p) ; } + +int +add_node_to_end ( node_t * node , node_t ** list ) +{ + node_t * p ; + if ( *list == NULL ) + { *list = node ; } + else + { + for ( p = *list ; p->next != NULL ; p = p->next ) ; + p->next = node ; + } + return(0) ; +} + +int +add_node_to_beg ( node_t * node , node_t ** list ) +{ + node_t * p ; + if ( *list == NULL ) + { + *list = node ; + (*list)->next = NULL ; + } + else + { +//fprintf(stderr," add_node_to_beg: node %s to existing list. CH %s CN %08x\n", node->name,(*list)->name,(*list)->next) ; +//if ( (*list)->next ) fprintf(stderr," CN name %s\n",(*list)->next->name ) ; + p = (*list) ; + *list = node ; + (*list)->next = p ; + } + return(0) ; +} + + +#if 0 +int +add_node_to_end_4d ( node_t * node , node_t ** list ) +{ + node_t * p ; + if ( *list == NULL ) + { *list = node ; } + else + { + for ( p = *list ; p->next4d != NULL ; p = p->next4d ) ; + p->next4d = node ; + } + return(0) ; +} +#endif + +#if 1 + +void +show_nodelist( node_t * p ) +{ + show_nodelist1( p , 0 ) ; +} + +void +show_nodelist1( node_t * p , int indent ) +{ + if ( p == NULL ) return; + show_node1( p, indent) ; + show_nodelist1( p->next, indent ) ; +} + +int +show_node( node_t * p ) +{ + return(show_node1(p,0)) ; +} + +int +show_node1( node_t * p, int indent ) +{ + char spaces[] = " " ; + char tmp[25] , t1[25] , t2[25] ; + char * x, *ca, *ld, *ss, *se, *sg ; + char *nodekind ; + int nl ; + int i ; + + if ( p == NULL ) return(1) ; + strcpy(tmp, spaces) ; + if ( indent >= 0 && indent < 20 ) tmp[indent] = '\0' ; + +// this doesn't make much sense any more, ever since node_kind was +// changed to a bit mask + nodekind = "" ; + if ( p->node_kind & FIELD ) nodekind = "FIELD" ; + else if ( p->node_kind & MODNAME ) nodekind = "MODNAME" ; + else if ( p->node_kind & TYPE ) nodekind = "TYPE" ; + + switch ( p->node_kind ) + { + case MODNAME : + fprintf(stderr,"%s%s : %s nickname %s\n",tmp,nodekind,p->name,p->nickname) ; + show_nodelist1(p->module_ddt_list, indent+1) ; + break ; + case FIELD : + fprintf(stderr,"%s%s : %10s ndims %1d\n",tmp,nodekind,p->name, p->ndims) ; + for ( i = 0 ; i < p->ndims ; i++ ) + { + sg = "" ; + ca = "" ; + switch ( p->dims[i]->coord_axis ) { + case COORD_C : ca = "C" ; break ; + } + switch ( p->dims[i]->len_defined_how ) { + case DOMAIN_STANDARD : ld = "STANDARD" ; ss = "" ; se = "" ; break ; + case CONSTANT : ld = "CONSTANT" ; sprintf(t1,"%d",p->dims[i]->coord_start) ; ss = t1 ; + sprintf(t2,"%d",p->dims[i]->coord_end ) ; se = t2 ; + break ; + } + fprintf(stderr," dim %0d: {%s} %2s%s %10s %10s %10s\n",i,p->dims[i]->dim_name,ca,sg,ld,ss,se) ; + } + nl = 0 ; + if ( strlen( p->use ) > 0 ) { + nl = 1 ; fprintf(stderr," use: %s",p->use) ; + } + if ( strlen( p->descrip ) > 0 ) { nl = 1 ; fprintf(stderr," descrip: %s",p->descrip) ; } + if ( nl == 1 ) fprintf(stderr,"\n") ; + show_node1( p->type, indent+1 ) ; + break ; + case TYPE : + x = "derived" ; + if ( p->type_type == SIMPLE ) x = "simple" ; + fprintf(stderr,"%sTYPE : %10s %s ndims %1d\n",tmp,p->name,x, p->ndims) ; + show_nodelist1( p->fields, indent+1 ) ; + break ; + case DIM : + break ; + default : + break ; + } + return(0) ; +} +#endif + +int +set_mark ( int val , node_t * lst ) +{ + node_t * p ; + if ( lst == NULL ) return(0) ; + for ( p = lst ; p != NULL ; p = p->next ) + { + p->mark = val ; + set_mark( val , p->fields ) ; + } + return(0) ; +} + +#if 0 +int +set_mark_4d ( int val , node_t * lst ) +{ + node_t * p ; + if ( lst == NULL ) return(0) ; + for ( p = lst ; p != NULL ; p = p->next4d ) + { + p->mark = val ; + set_mark( val , p->fields ) ; + set_mark( val , p->members ) ; + } + return(0) ; +} +#endif + diff --git a/OpenFAST/modules/openfast-registry/src/data.h b/OpenFAST/modules/openfast-registry/src/data.h new file mode 100644 index 000000000..bc81980c7 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/data.h @@ -0,0 +1,132 @@ +#ifndef DATA_H +#include "registry.h" + +typedef struct node_struct { + + int node_kind ; + int type_type ; + char name[NAMELEN] ; + char mapsto[NAMELEN] ; + char nickname[NAMELEN] ; + struct node_struct * fields ; + struct node_struct * params ; + struct node_struct * type ; + struct node_struct * module ; /* type node pointer back to module node it is defined in */ + int max_ndims; // max number of dimensions (so we don't have hundreds of unused variables that produce warnings) + int containsPtr; // if contains a pointer in type/subtype + int ndims ; + struct node_struct * dims[MAXDIMS] ; + int proc_orient ; /* ALL_[ZXY]_ON_PROC which dimension is all on processor */ + int ntl ; + int subject_to_communication ; + int boundary_array ; + int boundary_array_4d ; + char use[NAMELEN] ; + char inival[NAMELEN] ; + char descrip[NAMELEN] ; + char units[NAMELEN] ; + +/* I/O flags */ + int restart ; + int boundary ; + int namelist ; + char namelistsection[NAMELEN] ; + +/* Fields for Modname */ + struct node_struct * module_ddt_list ; + + +/* CTRL */ + int gen_periodic ; + struct node_struct * next ; + +/* fields used by rconfig nodes */ + char nentries[NAMELEN] ; + char howset[NAMELEN] ; + char dflt[NAMELEN] ; + +/* fields used by Dim nodes */ + + char dim_name[32] ; + char dim_data_name[NAMELEN] ; + int coord_axis ; /* X, Y, Z, C */ + /* DOMAIN_STANDARD, NAMELIST, CONSTANT */ + int len_defined_how ; + char assoc_nl_var_s[NAMELEN] ; /* for NAMELIST */ + char assoc_nl_var_e[NAMELEN] ; /* for NAMELIST */ + int coord_start ; /* for CONSTANT */ + int coord_end ; /* for CONSTANT */ + int dim_param; /* for using PARAMETER dimension */ + char dim_param_name[NAMELEN]; /* for using PARAMETER dimension */ + + int dim_order ; /* order that dimensions are specified + in framework */ + int subgrid ; /* 1=subgrid dimension */ + int deferred ; /* a deferred-shape dimension, that is, a colon */ + + int usefrom ; + +/* fields used by Package nodes */ + char pkg_assoc[NAMELEN] ; + char pkg_statevars[NAMELEN] ; + char pkg_4dscalars[NAMELEN_LONG] ; + +/* fields used by Comm (halo, period, xpose) nodes */ + char comm_define[2*8192] ; + + int is_interface_type ; + +/* marker */ + int mark ; + +} node_t ; + +#ifndef DEFINE_GLOBALS +# define EXTERN extern +#else +# define EXTERN +#endif + +EXTERN int sw_output_template_force ; +EXTERN char sw_commpath[NAMELEN] ; +EXTERN char sw_modname_subst[NAMELEN] ; +EXTERN char sw_modnickname_subst[NAMELEN] ; +EXTERN int sw_new_bdys ; /* 20070207 JM support decomposed boundary arrays */ +EXTERN int sw_unidir_shift_halo ; /* 20100210 JM assume that halo to shift is same in both directions and only gen one of them */ +EXTERN int sw_new_with_old_bdys ; /* 20070207 JM for debugging interim phase, new comms w/ old data structs */ +EXTERN int sw_norealloc_lsh; /* 20070207 addresses compilers like gfortran that do not /assume:realloc_lhs */ +EXTERN int sw_ccode ; /* 20130523 generate C code too */ +EXTERN int sw_noextrap; +EXTERN char sw_shownodes ; + +EXTERN node_t * Type ; +EXTERN node_t * Dim ; +EXTERN node_t * Packages ; +EXTERN node_t * Halos ; +EXTERN node_t * Periods ; +EXTERN node_t * Xposes ; +EXTERN node_t * FourD ; +EXTERN node_t * Swaps ; +EXTERN node_t * Cycles ; +EXTERN node_t * ModNames ; + +EXTERN node_t Domain ; + +EXTERN char t1[NAMELEN], t2[NAMELEN], t3[NAMELEN], t4[NAMELEN], t5[NAMELEN], t6[NAMELEN] ; +EXTERN char thiscom[NAMELEN] ; + +EXTERN int max_time_level ; /* Maximum number of time levels of any state variable */ + +#define MAXINCLDIRS 50 +EXTERN int nincldirs ; +EXTERN char IncludeDirs[MAXINCLDIRS][NAMELEN] ; +EXTERN char OutDir[NAMELEN]; + +#define P_XSB 1 +#define P_XEB 2 +#define P_YSB 3 +#define P_YEB 4 + + +#define DATA_H +#endif diff --git a/OpenFAST/modules/openfast-registry/src/gen_c_types.c b/OpenFAST/modules/openfast-registry/src/gen_c_types.c new file mode 100644 index 000000000..74bd14d66 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/gen_c_types.c @@ -0,0 +1,428 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#ifndef _WIN32 +# include <strings.h> +#endif + +#include "protos.h" +#include "registry.h" +#include "data.h" + + +#if 0 +void +gen_c_unpack( FILE * fp, const node_t * ModName, char * inout, char * inoutlong ) +{ + char tmp[NAMELEN], tmp2[NAMELEN], tmp3[NAMELEN], tmp4[NAMELEN], addnick[NAMELEN], nonick[NAMELEN] ; + node_t *q, * r ; + int d, idim, frst ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; + sprintf(tmp,"%s",addnick) ; + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_Unpack%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + return;//(1) ; + } + +fprintf(fp,"\nint\n") ; +fprintf(fp,"C_%s_Unpack%s( float * ReKiBuf, \n",ModName->nickname,nonick) ; +fprintf(fp," double * DbKiBuf, \n") ; +fprintf(fp," int * IntKiBuf, \n") ; +fprintf(fp," %s_t *OutData, char * ErrMsg )\n", addnick) ; +fprintf(fp,"{\n") ; +fprintf(fp," int ErrStat = 0;\n") ; +fprintf(fp," int Re_BufSz2 = 0 ;\n") ; +fprintf(fp," int Db_BufSz2 = 0 ;\n") ; +fprintf(fp," int Int_BufSz2 = 0 ;\n") ; +fprintf(fp," int Re_Xferred = 0 ;\n") ; +fprintf(fp," int Db_Xferred = 0 ;\n") ; +fprintf(fp," int Int_Xferred = 0 ;\n") ; +fprintf(fp," int Re_CurrSz = 0 ;\n") ; +fprintf(fp," int Db_CurrSz = 0 ;\n") ; +fprintf(fp," int Int_CurrSz = 0 ;\n") ; +fprintf(fp," int one = 1 ;\n") ; +fprintf(fp," int i,i1,i2,i3,i4,i5 ;\n") ; + + fprintf(fp," // buffers to store meshes, if any\n") ; + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type == NULL ) { + fprintf(stderr,"Registry warning generating %s_Unpack%s: %s has no type.\n",ModName->nickname,nonick,r->name) ; + return ; // EARLY RETURN + } else { + if ( !strcmp( r->type->name, "meshtype" ) || (r->type->type_type == DERIVED && ! r->type->usefrom ) ) { + fprintf(fp," float * Re_%s_Buf ;\n",r->name) ; + fprintf(fp," double * Db_%s_Buf ;\n",r->name) ; + fprintf(fp," int * Int_%s_Buf ;\n",r->name) ; + } + } + } +fprintf(fp," ReKiBuf = NULL ;\n") ; +fprintf(fp," DbKiBuf = NULL ;\n") ; +fprintf(fp," IntKiBuf = NULL ;\n") ; + + // Unpack data + frst = 1 ; + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type->type_type == DERIVED && ! r->type->usefrom && strcmp(make_lower_temp(r->type->mapsto),"meshtype") ) { + char nonick2[NAMELEN] ; + remove_nickname(ModName->nickname,r->type->name,nonick2) ; + fprintf(fp," // first call %s_Pack%s to get correctly sized buffers for unpacking\n", + ModName->nickname,fast_interface_type_shortname(nonick2)) ; + fprintf(fp," ErrStat = C_%s_Pack%s( Re_%s_Buf, &Re_BufSz2, Db_%s_Buf, &Db_BufSz2, Int_%s_Buf, &Int_BufSz2, &(OutData->%s%s), ErrMsg, &one ) ; // %s \n", + ModName->nickname,fast_interface_type_shortname(nonick2), r->name, r->name, r->name, r->name, dimstr_c(r->ndims),r->name ) ; + + fprintf(fp," if ( Re_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( Re_%s_Buf, &(ReKiBuf[ Re_Xferred] ), Re_BufSz2 ) ;\n",r->name ) ; + fprintf(fp," Re_Xferred += Re_BufSz2 ; // %s \n",r->name) ; + fprintf(fp," }\n" ) ; + fprintf(fp," if ( Db_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( Db_%s_Buf, &(DbKiBuf[ Db_Xferred] ), Db_BufSz2 ) ;\n",r->name ) ; + fprintf(fp," Db_Xferred += Db_BufSz2 ; // %s \n",r->name) ; + fprintf(fp," }\n" ) ; + fprintf(fp," if ( Int_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( Int_%s_Buf, &(IntKiBuf[ Int_Xferred] ), Int_BufSz2 ) ;\n",r->name ) ; + fprintf(fp," Int_Xferred += Int_BufSz2 ; // %s \n",r->name) ; + fprintf(fp," }\n" ) ; + fprintf(fp," ErrStat = C_%s_Unpack%s( Re_%s_Buf, Db_%s_Buf, Int_%s_Buf, &(OutData->%s%s), ErrMsg ) ; // %s \n", + ModName->nickname,fast_interface_type_shortname(nonick2), r->name, r->name, r->name, r->name, + dimstr(r->ndims), + r->name ) ; +// fprintf(fp," if ( Re_%s_Buf != NULL) { free(Re_%s_Buf) ; Re_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; +// fprintf(fp," if ( Db_%s_Buf != NULL) { free(Db_%s_Buf) ; Db_%s_Buf = NULL ;}\n",r->name, r->name, r->name) ; +// fprintf(fp," if ( Int_%s_Buf != NULL) { free(Int_%s_Buf) ; Int_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; + + } else { + char * indent, * ty ; + char arrayname[NAMELEN], tmp[NAMELEN], tmp2[NAMELEN] ; + + sprintf(arrayname,"OutData%%%s",r->name) ; + sprintf(tmp2,"SIZE(OutData%%%s)",r->name) ; + if ( r->ndims==0 ) { strcpy(tmp3,"") ; } + else if ( r->ndims==1 ) { strcpy(tmp3,"") ; } + else if ( r->ndims==2 ) { sprintf(tmp3,"(1:(%s),1)",tmp2) ; } + else if ( r->ndims==3 ) { sprintf(tmp3,"(1:(%s),1,1)",tmp2) ; } + else if ( r->ndims==4 ) { sprintf(tmp3,"(1:(%s),1,1,1)",tmp2) ; } + else if ( r->ndims==5 ) { sprintf(tmp3,"(1:(%s),1,1,1,1)",tmp2) ; } + else { fprintf(stderr,"Registry WARNING: too many dimensions for %s\n",r->name) ; } + indent = "" ; + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp( r->type->mapsto, "REAL(DbKi)") || + !strcmp( r->type->mapsto, "INTEGER(IntKi)") ) { + if ( r->ndims > 0 && has_deferred_dim( r, 0 )) { + fprintf(fp," if ( OutData->%s != NULL ) {\n", r->name ) ; + indent = " " ; + } + + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") ) ty = "Re" ; + if ( !strcmp( r->type->mapsto, "REAL(DbKi)") ) ty = "Db" ; + if ( !strcmp( r->type->mapsto, "REAL(IntKi)") ) ty = "Int" ; + + if ( r->ndims > 0 ) { + if ( has_deferred_dim( r, 0 ) ) { + fprintf(fp,"%s memcpy( OutData->%s,&(%sKiBuf[ %s_Xferred ]),OutData->%s_Len) ;\n",indent,r->name,ty,ty,r->name) ; + fprintf(fp,"%s %s_Xferred = %s_Xferred + OutData->%s_Len ; \n",indent,ty,ty,r->name ) ; + } else { + int i ; + strcpy(tmp2,"") ; + for ( i = 0 ; i < r->ndims ; i++ ) + { + sprintf(tmp,"((%d)-(%d)+1)",r->dims[i]->coord_end,r->dims[i]->coord_start) ; + strcat(tmp2,tmp) ; + if ( i < r->ndims-1 ) strcat(tmp2,"*") ; + } + fprintf(fp,"%s memcpy( OutData->%s,&(%sKiBuf[ %s_Xferred ]),(%s)*sizeof(%s)) ;\n", + indent,r->name,ty,ty,tmp2,C_type(r->type->mapsto)) ; + fprintf(fp,"%s %s_Xferred = %s_Xferred + (%s)*sizeof(%s) ; \n", + indent,ty,ty,tmp2,C_type(r->type->mapsto) ) ; + } + } else { + fprintf(fp,"%s OutData->%s = %sKiBuf [ %s_Xferred ] ; \n",indent,r->name,ty,ty) ; + fprintf(fp,"%s %s_Xferred = %s_Xferred + 1 ; \n",indent,ty,ty ) ; + } + + if ( r->ndims > 0 && has_deferred_dim( r, 0 )) { + fprintf(fp," }\n" ) ; + } + + } + } + } + fprintf(fp," if ( ReKiBuf != NULL ) free(ReKiBuf) ;\n") ; + fprintf(fp," if ( DbKiBuf != NULL ) free(DbKiBuf) ;\n") ; + fprintf(fp," if ( IntKiBuf != NULL ) free(IntKiBuf) ;\n") ; + fprintf(fp," return(ErrStat) ;\n") ; + fprintf(fp,"}\n") ; + return;//(0) ; +} + +void +gen_c_pack( FILE * fp, const node_t * ModName, char * inout, char *inoutlong ) +{ + char tmp[NAMELEN], tmp2[NAMELEN], tmp3[NAMELEN], addnick[NAMELEN], nonick[NAMELEN] ; + node_t *q, * r ; + int frst, d ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; + sprintf(tmp,"%s",addnick) ; + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_Pack%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + return;//(1) ; + } +fprintf(fp,"\nint\n") ; +fprintf(fp,"C_%s_Pack%s( float * ReKiBuf, int * Re_BufSz ,\n",ModName->nickname,nonick) ; +fprintf(fp," double * DbKiBuf, int * Db_BufSz ,\n") ; +fprintf(fp," int * IntKiBuf, int * Int_BufSz ,\n") ; +fprintf(fp," %s_t *InData, char * ErrMsg, int *SizeOnly )\n", addnick) ; +fprintf(fp,"{\n") ; +fprintf(fp," int ErrStat = 0;\n") ; +fprintf(fp," int OnlySize ;\n") ; +fprintf(fp," int Re_BufSz2 ;\n") ; +fprintf(fp," int Db_BufSz2 ;\n") ; +fprintf(fp," int Int_BufSz2 ;\n") ; +fprintf(fp," int Re_Xferred = 0 ;\n") ; +fprintf(fp," int Db_Xferred = 0 ;\n") ; +fprintf(fp," int Int_Xferred = 0 ;\n") ; +fprintf(fp," int one = 1 ;\n") ; +fprintf(fp," int i,i1,i2,i3,i4,i5 ;\n") ; +fprintf(fp," // buffers to store meshes and subtypes, if any\n") ; + + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type == NULL ) { + fprintf(stderr,"Registry warning generating %s_Pack%s: %s has no type.\n",ModName->nickname,nonick,r->name) ; + return ; // EARLY RETURN + } else { + if ( !strcmp( r->type->name, "meshtype" ) || (r->type->type_type == DERIVED && ! r->type->usefrom ) ) { + fprintf(fp," float * Re_%s_Buf ;\n",r->name) ; + fprintf(fp," double * Db_%s_Buf ;\n",r->name) ; + fprintf(fp," int * Int_%s_Buf ;\n",r->name) ; + } + } + } + +fprintf(fp,"\n") ; +fprintf(fp," OnlySize = *SizeOnly ;\n") ; +fprintf(fp,"\n") ; +fprintf(fp," *Re_BufSz = 0 ;\n") ; +fprintf(fp," *Db_BufSz = 0 ;\n") ; +fprintf(fp," *Int_BufSz = 0 ;\n") ; +fprintf(fp," ReKiBuf = NULL ;\n") ; +fprintf(fp," DbKiBuf = NULL ;\n") ; +fprintf(fp," IntKiBuf = NULL ;\n") ; + frst = 1 ; + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type->type_type == DERIVED && ! r->type->usefrom && strcmp(make_lower_temp(r->type->mapsto),"meshtype") ) { + char nonick2[NAMELEN] ; + remove_nickname(ModName->nickname,r->type->name,nonick2) ; + fprintf(fp," ErrStat = C_%s_Pack%s( Re_%s_Buf, &Re_BufSz2 ,\n", + ModName->nickname,fast_interface_type_shortname(nonick2), r->name) ; + fprintf(fp," Db_%s_Buf, &Db_BufSz2 ,\n",r->name ) ; + fprintf(fp," Int_%s_Buf, &Int_BufSz2 , &(InData->%s%s), ErrMsg, &one ) ; // %s \n", + r->name, r->name, dimstr(r->ndims), r->name ) ; + fprintf(fp," *Re_BufSz += Re_BufSz2 ; // %s\n",r->name ) ; + fprintf(fp," *Db_BufSz += Db_BufSz2 ; // %s\n",r->name ) ; + fprintf(fp," *Int_BufSz += Int_BufSz2 ; // %s\n",r->name ) ; + fprintf(fp," if ( Re_%s_Buf != NULL) { free(Re_%s_Buf) ; Re_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; + fprintf(fp," if ( Db_%s_Buf != NULL) { free(Db_%s_Buf) ; Db_%s_Buf = NULL ;}\n",r->name, r->name, r->name) ; + fprintf(fp," if ( Int_%s_Buf != NULL) { free(Int_%s_Buf) ; Int_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; + } else if ( r->ndims == 0 ) { // scalars + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") ) { + fprintf(fp," *Re_BufSz += 1 ; // %s\n",r->name ) ; + } + else if ( !strcmp( r->type->mapsto, "REAL(DbKi)") ) { + fprintf(fp," *Db_BufSz += 1 ; // %s\n",r->name ) ; + } + else if ( !strcmp( r->type->mapsto, "INTEGER(IntKi)") ) { + fprintf(fp," *Int_BufSz += 1 ; // %s\n",r->name ) ; + } + } else { // r->ndims > 0 + if ( r->dims[0]->deferred ) { + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") ) { + fprintf(fp," *Re_BufSz += InData->%s_Len ; // %s \n", r->name , r->name ) ; + } + else if ( !strcmp( r->type->mapsto, "REAL(DbKi)") ) { + fprintf(fp," *Db_BufSz += InData->%s_Len ; // %s \n", r->name , r->name ) ; + } + else if ( !strcmp( r->type->mapsto, "INTEGER(IntKi)") ) { + fprintf(fp," *Int_BufSz += InData->%s_Len ; // %s \n", r->name , r->name ) ; + } + } else { + } + } + } + + fprintf(fp," if ( ! OnlySize ) {\n") ; + // Allocate buffers + fprintf(fp," if ( *Re_BufSz > 0 ) ReKiBuf = (float *)malloc(*Re_BufSz*sizeof(float) ) ;\n") ; + fprintf(fp," if ( *Db_BufSz > 0 ) DbKiBuf = (double *)malloc(*Db_BufSz*sizeof(double) ) ;\n") ; + fprintf(fp," if ( *Int_BufSz > 0 ) IntKiBuf = (int *)malloc(*Int_BufSz*sizeof(int) ) ;\n") ; + + // Pack data + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type->type_type == DERIVED && ! r->type->usefrom && strcmp(make_lower_temp(r->type->mapsto),"meshtype") ) { + char nonick2[NAMELEN] ; + remove_nickname(ModName->nickname,r->type->name,nonick2) ; + fprintf(fp," ErrStat = C_%s_Pack%s( Re_%s_Buf, &Re_BufSz2 ,\n", + ModName->nickname,fast_interface_type_shortname(nonick2), r->name) ; + fprintf(fp," Db_%s_Buf, &Db_BufSz2 ,\n",r->name ) ; + fprintf(fp," Int_%s_Buf, &Int_BufSz2 , &(InData->%s%s), ErrMsg, &one ) ; // %s \n", + r->name, r->name, dimstr(r->ndims), r->name ) ; + + fprintf(fp," if ( Re_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( &ReKiBuf[Re_Xferred], Re_%s_Buf, Re_BufSz2*sizeof(float) ) ;\n",r->name) ; + fprintf(fp," Re_Xferred += Re_BufSz2 ;\n") ; + fprintf(fp," }\n" ) ; + fprintf(fp," if ( Db_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( &DbKiBuf[Db_Xferred], Db_%s_Buf, Db_BufSz2*sizeof(double) ) ;\n",r->name) ; + fprintf(fp," Db_Xferred += Db_BufSz2 ;\n") ; + fprintf(fp," }\n" ) ; + fprintf(fp," if ( Int_%s_Buf != NULL ) {\n",r->name) ; + fprintf(fp," memcpy( &IntKiBuf[Int_Xferred], Int_%s_Buf, Int_BufSz2*sizeof(int) ) ;\n",r->name) ; + fprintf(fp," Int_Xferred += Int_BufSz2 ;\n") ; + fprintf(fp," }\n" ) ; + fprintf(fp," if ( Re_%s_Buf != NULL) { free(Re_%s_Buf) ; Re_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; + fprintf(fp," if ( Db_%s_Buf != NULL) { free(Db_%s_Buf) ; Db_%s_Buf = NULL ;}\n",r->name, r->name, r->name) ; + fprintf(fp," if ( Int_%s_Buf != NULL) { free(Int_%s_Buf) ; Int_%s_Buf = NULL ;} \n",r->name, r->name, r->name) ; + + } else { + char * indent, *ty, *cty ; + sprintf(tmp2,"InData->%s_Len)",r->name) ; + if ( r->ndims==0 ) { + strcpy(tmp3,"") ; + } else if ( r->ndims==1 ) { + strcpy(tmp3,"") ; + } else if ( r->ndims==2 ) { + sprintf(tmp3,"(1:(%s),1)",tmp2) ; + } else if ( r->ndims==3 ) { + sprintf(tmp3,"(1:(%s),1,1)",tmp2) ; + } else if ( r->ndims==4 ) { + sprintf(tmp3,"(1:(%s),1,1,1)",tmp2) ; + } else if ( r->ndims==5 ) { + sprintf(tmp3,"(1:(%s),1,1,1,1)",tmp2) ; + } else { + fprintf(stderr,"Registry WARNING: too many dimensions for %s\n",r->name) ; + } + indent = " " ; + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp( r->type->mapsto, "REAL(DbKi)") || + !strcmp( r->type->mapsto, "INTEGER(IntKi)") ) + { + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") ) {ty = "Re" ; cty = "float" ; } + else if ( !strcmp( r->type->mapsto, "REAL(DbKi)") ) {ty = "Db" ; cty = "double" ; } + else if ( !strcmp( r->type->mapsto, "REAL(IntKi)") ) {ty = "Int" ; cty = "int" ; } + indent = " " ; + if ( r->ndims > 0 && has_deferred_dim( r, 0 )) { + fprintf(fp,"%sfor ( i = 0 ; i < InData->%s_Len ; i++ ) {\n",indent, r->name ) ; + fprintf(fp,"%s if ( !OnlySize ) memcpy( &(%sKiBuf[%s_Xferred+i]), &(InData->%s[i]), sizeof(%s)) ;\n", + indent,ty,ty,r->name,cty ) ; + fprintf(fp,"%s %s_Xferred++ ;\n",indent,ty) ; + fprintf(fp,"%s}\n",indent) ; + } else if ( r->ndims == 0 ) { + fprintf(fp," %sKiBuf[%s_Xferred++] = InData->%s ;\n",ty,ty,r->name) ; + } + } + } + } + +fprintf(fp," }\n") ; +fprintf(fp," return(ErrStat) ;\n") ; +fprintf(fp,"}\n") ; +return;//(0) ; +} +#endif + + +void +gen_c_module( FILE * fph, node_t * ModName ) +{ + node_t * q, * r ; + int i ; + char nonick[NAMELEN], star ; + + if ( strlen(ModName->nickname) > 0 ) { +// generate each derived data type + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + if (*q->mapsto) remove_nickname(ModName->nickname, make_lower_temp(q->mapsto), nonick); + fprintf(fph, " typedef struct %s {\n",q->mapsto) ; + //if (!strcmp(make_lower_temp(nonick), "otherstatetype") !strcmp(make_lower_temp(nonick), "initinputtype")){ + fprintf(fph, " void * object ;\n"); + //} + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type != NULL ) { + star = ' ' ; + if ( r->ndims > 0 ) { + if ( has_deferred_dim(r, 0) ) star = '*'; + } + if ( r->type->type_type == DERIVED ) { + if ( strcmp(make_lower_temp(r->type->mapsto),"meshtype") ) { // do not output mesh types for C code, + //fprintf(fph," struct %s %c%s",r->type->mapsto,star,r->name ) ; + } + } else { + char tmp[NAMELEN] ; tmp[0] = '\0' ; + if (*q->mapsto) remove_nickname( ModName->nickname, make_lower_temp(q->mapsto) , tmp ) ; + if (r->ndims > 0 && has_deferred_dim(r, 0)) { + fprintf(fph," %s * %s ; ",C_type( r->type->mapsto), r->name ) ; + fprintf(fph," int %s_Len ;",r->name ) ; + } else { + char *p = r->type->mapsto; + char buf[10]; +// bjj: this assumes all character strings are defined with numeric lengths +// It should be modified to allow use of parameters, too. (and parameters defined in the registry should also be defined in the .h file) + while (*p) { + if (isdigit(*p)) { + long val = strtol(p, &p, 10); + snprintf(buf, 10, "%lu", val); + } else { + p++; + } + + + } + if (strcmp(C_type(r->type->mapsto), "char") == 0 ){ // if it's a char we need to add the array size + if (r->ndims == 0) + fprintf(fph," %s %s[%s] ;",C_type( r->type->mapsto ),r->name,buf ) ; + } else { // else, it's just a double or int value + fprintf(fph," %s %s ;",C_type( r->type->mapsto ),r->name ) ; + } + } + } + for ( i = 0 ; i < r->ndims ; i++ ) + { + if (!has_deferred_dim(r, 0) && (strcmp(C_type(r->type->mapsto), "char") || r->ndims == 0)) // skip this for characters? + fprintf(fph,"[%d] ;",r->dims[i]->coord_end - r->dims[i]->coord_start +1) ; + } + fprintf(fph, "\n"); + } + } + fprintf(fph," } %s_t ;\n", q->mapsto ) ; + } + } + + + fprintf(fph," typedef struct %s_UserData {\n", ModName->nickname) ; + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + remove_nickname(ModName->nickname,q->name,nonick) ; + if ( is_a_fast_interface_type(nonick) ) { + char temp[NAMELEN] ; + sprintf(temp, "%s_t", q->mapsto ) ; + fprintf(fph," %-30s %s_%s ;\n", temp, ModName->nickname, fast_interface_type_shortname(nonick) ) ; + } + } + fprintf(fph," } %s_t ;\n", ModName->nickname ) ; + + } +} diff --git a/OpenFAST/modules/openfast-registry/src/gen_module_files.c b/OpenFAST/modules/openfast-registry/src/gen_module_files.c new file mode 100644 index 000000000..df4acfe9d --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/gen_module_files.c @@ -0,0 +1,2466 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef _WIN32 +# include <strings.h> +#endif + +#include "protos.h" +#include "registry.h" +#include "data.h" + +#include "FAST_preamble.h" + +void gen_mask_alloc( FILE *fp, int ndims, char *tmp ); + +/** + * ============== Create the C2Farry Copy Subroutine in ModName_Types.f90 ====================== + * + * In the C2F routines, we associate the pointer created in C with the variables in the + * corresponding Fortran types. + * ====================================================================================== + */ +int +gen_copy_c2f( FILE *fp , // *.f90 file we are writting to + const node_t *ModName , // module name + char *inout , // character string written out + char *inoutlong ) // not sure what this is used for +{ + node_t *q, *r ; + char tmp[NAMELEN]; + char addnick[NAMELEN]; + char nonick[NAMELEN] ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; + fprintf(fp," SUBROUTINE %s_C2Fary_Copy%s( %sData, ErrStat, ErrMsg, SkipPointers )\n", ModName->nickname, nonick,nonick ); + fprintf(fp," TYPE(%s), INTENT(INOUT) :: %sData\n" , addnick, nonick ); + fprintf(fp," INTEGER(IntKi), INTENT( OUT) :: ErrStat\n" ); + fprintf(fp," CHARACTER(*), INTENT( OUT) :: ErrMsg\n" ); + fprintf(fp," LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers\n" ); + fprintf(fp," ! \n" ); + fprintf(fp," LOGICAL :: SkipPointers_local\n"); + fprintf(fp," ErrStat = ErrID_None\n" ); + fprintf(fp," ErrMsg = \"\"\n\n" ); + fprintf(fp," IF (PRESENT(SkipPointers)) THEN\n"); + fprintf(fp," SkipPointers_local = SkipPointers\n"); + fprintf(fp," ELSE\n"); + fprintf(fp," SkipPointers_local = .false.\n"); + fprintf(fp," END IF\n"); + + sprintf(tmp,"%s",addnick) ; + + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_C2Fary_Copy%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + } else { + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type != NULL ) { + if ( r->type->type_type == DERIVED ) { // && ! r->type->usefrom + fprintf(stderr,"Registry WARNING: derived data type %s of type %s is not passed through C interface\n",r->name,r->type->name) ; + } else { + if ( is_pointer(r) ) { + fprintf(fp,"\n ! -- %s %s Data fields\n",r->name,nonick) ; + fprintf(fp," IF ( .NOT. SkipPointers_local ) THEN\n"); + fprintf(fp," IF ( .NOT. C_ASSOCIATED( %sData%%C_obj%%%s ) ) THEN\n",nonick,r->name) ; + fprintf(fp," NULLIFY( %sData%%%s )\n",nonick,r->name) ; + fprintf(fp," ELSE\n") ; + fprintf(fp," CALL C_F_POINTER(%sData%%C_obj%%%s, %sData%%%s, (/%sData%%C_obj%%%s_Len/))\n",nonick,r->name,nonick,r->name,nonick,r->name) ; + fprintf(fp," END IF\n") ; + fprintf(fp, " END IF\n"); + } + else if (!has_deferred_dim(r, 0)) { + if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "INTEGER(IntKi)") || + !strcmp(r->type->mapsto, "LOGICAL")) + { + fprintf(fp, " %sData%%%s = %sData%%C_obj%%%s\n", nonick, r->name, nonick, r->name); + } + else { // characters need to be copied differently + if (r->ndims == 0){ + fprintf(fp, " %sData%%%s = TRANSFER(%sData%%C_obj%%%s, %sData%%%s )\n", nonick, r->name, nonick, r->name, nonick, r->name); + } + } + } + } + } + } + } + + fprintf(fp," END SUBROUTINE %s_C2Fary_Copy%s\n\n", ModName->nickname,nonick ) ; + return(0) ; +} + +int +gen_copy_f2c(FILE *fp, // *.f90 file we are writting to + const node_t *ModName, // module name + char *inout, // character string written out + char *inoutlong) // not sure what this is used for +{ + node_t *q, *r; + char tmp[NAMELEN]; + char addnick[NAMELEN]; + char nonick[NAMELEN]; + + remove_nickname(ModName->nickname, inout, nonick); + append_nickname((is_a_fast_interface_type(inoutlong)) ? ModName->nickname : "", inoutlong, addnick); + fprintf(fp, " SUBROUTINE %s_F2C_Copy%s( %sData, ErrStat, ErrMsg, SkipPointers )\n", ModName->nickname, nonick, nonick); + fprintf(fp, " TYPE(%s), INTENT(INOUT) :: %sData\n", addnick, nonick); + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat\n"); + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg\n"); + fprintf(fp, " LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers\n"); + fprintf(fp, " ! \n"); + fprintf(fp, " LOGICAL :: SkipPointers_local\n"); + fprintf(fp, " ErrStat = ErrID_None\n"); + fprintf(fp, " ErrMsg = \"\"\n\n"); + fprintf(fp, " IF (PRESENT(SkipPointers)) THEN\n"); + fprintf(fp, " SkipPointers_local = SkipPointers\n"); + fprintf(fp, " ELSE\n"); + fprintf(fp, " SkipPointers_local = .false.\n"); + fprintf(fp, " END IF\n"); + + sprintf(tmp, "%s", addnick); + + if ((q = get_entry(make_lower_temp(tmp), ModName->module_ddt_list)) == NULL) + { + fprintf(stderr, "Registry warning: generating %s_F2C_Copy%s: cannot find definition for %s\n", ModName->nickname, nonick, tmp); + } + else { + for (r = q->fields; r; r = r->next) + { + if (r->type != NULL) { + if (r->type->type_type == DERIVED) { // && ! r->type->usefrom + fprintf(stderr, "Registry WARNING: derived data type %s of type %s is not passed through F-C interface\n", r->name, r->type->name); + } + else { + if (is_pointer(r)) { + fprintf(fp, "\n ! -- %s %s Data fields\n", r->name, nonick); + fprintf(fp, " IF ( .NOT. SkipPointers_local ) THEN\n"); + fprintf(fp, " IF ( .NOT. %s(%sData%%%s)) THEN \n", assoc_or_allocated(r), nonick, r->name); + fprintf(fp, " %sData%%c_obj%%%s_Len = 0\n", nonick, r->name); + fprintf(fp, " %sData%%c_obj%%%s = C_NULL_PTR\n", nonick, r->name); + fprintf(fp, " ELSE\n"); + fprintf(fp, " %sData%%c_obj%%%s_Len = SIZE(%sData%%%s)\n", nonick, r->name, nonick, r->name); + fprintf(fp, " IF (%sData%%c_obj%%%s_Len > 0) &\n", nonick, r->name); + fprintf(fp, " %sData%%c_obj%%%s = C_LOC( %sData%%%s( LBOUND(%sData%%%s,1) ) ) \n", nonick, r->name, nonick, r->name, nonick, r->name ); + fprintf(fp, " END IF\n"); + fprintf(fp, " END IF\n"); + } + else if (!has_deferred_dim(r, 0)) { + if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "INTEGER(IntKi)") || + !strcmp(r->type->mapsto, "LOGICAL")) + { + fprintf(fp, " %sData%%C_obj%%%s = %sData%%%s\n", nonick, r->name, nonick, r->name); + } + else { // characters need to be copied differently + if (r->ndims == 0) { + //fprintf(stderr, "Registry WARNING: character data type %s of type %s is not passed through F-C interface\n", r->name, r->type->name); + fprintf(fp, " %sData%%C_obj%%%s = TRANSFER(%sData%%%s, %sData%%C_obj%%%s )\n", nonick, r->name, nonick, r->name, nonick, r->name); + } + } + } + } + } + } + } + + fprintf(fp, " END SUBROUTINE %s_F2C_Copy%s\n\n", ModName->nickname, nonick); + return(0); +} + + +int +gen_copy( FILE * fp, const node_t * ModName, char * inout, char * inoutlong, const node_t * q_in ) +{ + char tmp[NAMELEN], tmp2[NAMELEN], addnick[NAMELEN], nonick[NAMELEN] ; + node_t *q, * r ; + int d ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; + fprintf(fp," SUBROUTINE %s_Copy%s( Src%sData, Dst%sData, CtrlCode, ErrStat, ErrMsg )\n",ModName->nickname,nonick,nonick,nonick ) ; + fprintf(fp, " TYPE(%s), INTENT(%s) :: Src%sData\n", addnick, (q_in->containsPtr == 1) ? "INOUT" : "IN", nonick); +//fprintf(fp, " TYPE(%s), INTENT(INOUT) :: Src%sData\n", addnick, nonick); + fprintf(fp," TYPE(%s), INTENT(INOUT) :: Dst%sData\n",addnick,nonick) ; + fprintf(fp," INTEGER(IntKi), INTENT(IN ) :: CtrlCode\n") ; + fprintf(fp," INTEGER(IntKi), INTENT( OUT) :: ErrStat\n") ; + fprintf(fp," CHARACTER(*), INTENT( OUT) :: ErrMsg\n") ; + fprintf(fp,"! Local \n") ; + fprintf(fp," INTEGER(IntKi) :: i,j,k\n") ; + for (d = 1; d <= q_in->max_ndims; d++){ + fprintf(fp, " INTEGER(IntKi) :: i%d, i%d_l, i%d_u ! bounds (upper/lower) for an array dimension %d\n", d, d, d, d); + } + fprintf(fp," INTEGER(IntKi) :: ErrStat2\n") ; + fprintf(fp," CHARACTER(ErrMsgLen) :: ErrMsg2\n"); + fprintf(fp," CHARACTER(*), PARAMETER :: RoutineName = '%s_Copy%s'\n", ModName->nickname, nonick); + fprintf(fp, "! \n"); + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp," ErrMsg = \"\"\n") ; + +// sprintf(tmp,"%s_%s",ModName->nickname,inoutlong) ; +// sprintf(tmp,"%s",inoutlong) ; + sprintf(tmp,"%s",addnick) ; + + sprintf(tmp2,"%s",make_lower_temp(tmp)) ; + + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_Copy%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + } else { + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type != NULL ) { + +// check if this is an allocatable array: + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp,"IF (%s(Src%sData%%%s)) THEN\n",assoc_or_allocated(r),nonick,r->name) ; + strcpy(tmp,"") ; + + for (d = 1; d <= r->ndims; d++) { + fprintf(fp, " i%d_l = LBOUND(Src%sData%%%s,%d)\n", d, nonick, r->name, d); + fprintf(fp, " i%d_u = UBOUND(Src%sData%%%s,%d)\n", d, nonick, r->name, d); + sprintf(tmp2, ",i%d_l:i%d_u", d, d); + strcat(tmp, tmp2); + } +//fprintf(fp," nonick=%s\n", nonick ); + fprintf(fp," IF (.NOT. %s(Dst%sData%%%s)) THEN \n",assoc_or_allocated(r),nonick,r->name) ; + fprintf(fp," ALLOCATE(Dst%sData%%%s(%s),STAT=ErrStat2)\n",nonick,r->name,(char*)&(tmp[1])) ; + fprintf(fp," IF (ErrStat2 /= 0) THEN \n") ; + fprintf(fp," CALL SetErrStat(ErrID_Fatal, 'Error allocating Dst%sData%%%s.', ErrStat, ErrMsg,RoutineName)\n",nonick,r->name); + fprintf(fp," RETURN\n") ; + fprintf(fp," END IF\n") ; + + if ( sw_ccode && is_pointer(r) ) { // bjj: this needs to be updated if we've got multiple dimension arrays + fprintf(fp," Dst%sData%%c_obj%%%s_Len = SIZE(Dst%sData%%%s)\n",nonick,r->name,nonick,r->name) ; + fprintf(fp," IF (Dst%sData%%c_obj%%%s_Len > 0) &\n",nonick,r->name) ; + fprintf(fp," Dst%sData%%c_obj%%%s = C_LOC( Dst%sData%%%s(i1_l) ) \n",nonick,r->name, nonick,r->name ) ; + } + + fprintf(fp," END IF\n") ; // end dest allocated/associated + } + + if ( r->type->type_type == DERIVED ) { // includes mesh and dll_type + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp," DO i%d = LBOUND(Src%sData%%%s,%d), UBOUND(Src%sData%%%s,%d)\n",d,nonick,r->name,d,nonick,r->name,d ) ; + } + + if (!strcmp(r->type->name, "meshtype")) { + fprintf(fp," CALL MeshCopy( Src%sData%%%s%s, Dst%sData%%%s%s, CtrlCode, ErrStat2, ErrMsg2 )\n",nonick,r->name,dimstr(r->ndims),nonick,r->name,dimstr(r->ndims)) ; + fprintf(fp," CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)\n"); + fprintf(fp," IF (ErrStat>=AbortErrLev) RETURN\n"); + } else if ( !strcmp( r->type->name, "dll_type" ) ) { + fprintf(fp," Dst%sData%%%s = Src%sData%%%s\n",nonick,r->name,nonick,r->name) ; + } + else { // && ! r->type->usefrom ) { + char nonick2[NAMELEN]; + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + + fprintf(fp, " CALL %s_Copy%s( Src%sData%%%s%s, Dst%sData%%%s%s, CtrlCode, ErrStat2, ErrMsg2 )\n", + r->type->module->nickname, fast_interface_type_shortname(nonick2), + nonick, r->name, dimstr(r->ndims), + nonick, r->name, dimstr(r->ndims)); + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " IF (ErrStat>=AbortErrLev) RETURN\n"); + + } + + for ( d = r->ndims ; d >= 1 ; d-- ) { + fprintf(fp," ENDDO\n") ; + } + } else { // not a derived type + fprintf(fp, " Dst%sData%%%s = Src%sData%%%s\n",nonick,r->name,nonick,r->name) ; + if (sw_ccode && !is_pointer(r)){ + + //if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + // !strcmp(r->type->mapsto, "REAL(SiKi)") || + // !strcmp(r->type->mapsto, "REAL(DbKi)") || + // !strcmp(r->type->mapsto, "REAL(R8Ki)") || + // !strcmp(r->type->mapsto, "INTEGER(IntKi)") || + // !strcmp(r->type->mapsto, "LOGICAL") || + // r->ndims == 0) + if ( r->ndims == 0 ) // scalar of any type OR a character array + { + // fprintf(fp, " Dst%sData%%C_obj%%%s = Dst%sData%%%s\n", nonick, r->name, nonick, r->name); + fprintf(fp, " Dst%sData%%C_obj%%%s = Src%sData%%C_obj%%%s\n", nonick, r->name, nonick, r->name); + } + } + } + +// close IF (check on allocatable array) + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp,"ENDIF\n") ; + } + + } // if non-null field + } // each field + } + + fprintf(fp," END SUBROUTINE %s_Copy%s\n\n", ModName->nickname,nonick ) ; + return(0) ; +} + +void +gen_pack( FILE * fp, const node_t * ModName, char * inout, char *inoutlong ) +{ + + char tmp[NAMELEN], tmp2[NAMELEN], addnick[NAMELEN], nonick[NAMELEN] ; + char nonick2[NAMELEN], indent[NAMELEN], mainIndent[6]; + node_t *q, * r ; + int frst, d, i; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; +// sprintf(tmp,"%s_%s",ModName->nickname,inoutlong) ; +// sprintf(tmp,"%s",inoutlong) ; + sprintf(tmp,"%s",addnick) ; + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_Pack%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + return;//(1) ; + } + + fprintf(fp, " SUBROUTINE %s_Pack%s( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly )\n", ModName->nickname,nonick) ; + fprintf(fp, " REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:)\n") ; + fprintf(fp, " REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:)\n") ; + fprintf(fp, " INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:)\n") ; + fprintf(fp, " TYPE(%s), INTENT(IN) :: InData\n",addnick ) ; + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat\n") ; + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg\n") ; + fprintf(fp, " LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly\n") ; + fprintf(fp, " ! Local variables\n") ; + fprintf(fp, " INTEGER(IntKi) :: Re_BufSz\n") ; + fprintf(fp, " INTEGER(IntKi) :: Re_Xferred\n") ; + fprintf(fp, " INTEGER(IntKi) :: Db_BufSz\n") ; + fprintf(fp, " INTEGER(IntKi) :: Db_Xferred\n") ; + fprintf(fp, " INTEGER(IntKi) :: Int_BufSz\n") ; + fprintf(fp, " INTEGER(IntKi) :: Int_Xferred\n") ; + fprintf(fp, " INTEGER(IntKi) :: i,i1,i2,i3,i4,i5\n") ; + fprintf(fp, " LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers\n") ; + fprintf(fp, " INTEGER(IntKi) :: ErrStat2\n"); + fprintf(fp, " CHARACTER(ErrMsgLen) :: ErrMsg2\n"); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_Pack%s'\n", ModName->nickname, nonick); + + fprintf(fp, " ! buffers to store subtypes, if any\n"); + fprintf(fp, " REAL(ReKi), ALLOCATABLE :: Re_Buf(:)\n"); + fprintf(fp, " REAL(DbKi), ALLOCATABLE :: Db_Buf(:)\n"); + fprintf(fp, " INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)\n\n"); + + fprintf(fp," OnlySize = .FALSE.\n") ; + fprintf(fp," IF ( PRESENT(SizeOnly) ) THEN\n") ; + fprintf(fp," OnlySize = SizeOnly\n") ; + fprintf(fp," ENDIF\n") ; + fprintf(fp," !\n") ; + + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp," ErrMsg = \"\"\n") ; + fprintf(fp," Re_BufSz = 0\n") ; + fprintf(fp," Db_BufSz = 0\n") ; + fprintf(fp," Int_BufSz = 0\n") ; + + + frst = 1; + for (r = q->fields; r; r = r->next) + { + if (r->type == NULL) { + fprintf(stderr, "Registry warning generating %s_Pack%s: %s has no type.\n", ModName->nickname, nonick, r->name); + return; // EARLY RETURN + } + + if (has_deferred_dim(r, 0)){ + //fprintf(fp, "\n"); + fprintf(fp, " Int_BufSz = Int_BufSz + 1 ! %s allocated yes/no\n", r->name); + + fprintf(fp, " IF ( %s(InData%%%s) ) THEN\n", assoc_or_allocated(r), r->name); + fprintf(fp, " Int_BufSz = Int_BufSz + 2*%d ! %s upper/lower bounds for each dimension\n", r->ndims, r->name); + } + + if (!strcmp(r->type->name, "meshtype") || + !strcmp(r->type->name, "dll_type") || + (r->type->type_type == DERIVED) ) { // call individual routines to pack data from subtypes: + + if (frst == 1) { + fprintf(fp, " ! Allocate buffers for subtypes, if any (we'll get sizes from these) \n"); frst = 0; + } + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " DO i%d = LBOUND(InData%%%s,%d), UBOUND(InData%%%s,%d)\n", d, r->name, d, r->name, d); + } + fprintf(fp, " Int_BufSz = Int_BufSz + 3 ! %s: size of buffers for each call to pack subtype\n", r->name); + + if ( !strcmp( r->type->name, "meshtype" ) ) { + fprintf(fp, " CALL MeshPack( InData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! %s \n", + r->name,dimstr(r->ndims),r->name ) ; + } else if ( !strcmp( r->type->name, "dll_type" ) ) { + fprintf(fp, " CALL DLLTypePack( InData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! %s \n", + r->name,dimstr(r->ndims), r->name ) ; + } else if (r->type->type_type == DERIVED) { // && ! r->type->usefrom ) { + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + fprintf(fp, " CALL %s_Pack%s( Re_Buf, Db_Buf, Int_Buf, InData%%%s%s, ErrStat2, ErrMsg2, .TRUE. ) ! %s \n", + r->type->module->nickname, fast_interface_type_shortname(nonick2), r->name, + dimstr(r->ndims), r->name); + } + + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)\n"); + fprintf(fp, " IF (ErrStat >= AbortErrLev) RETURN\n\n"); + + fprintf(fp, " IF(ALLOCATED(Re_Buf)) THEN ! %s\n", r->name); + fprintf(fp, " Re_BufSz = Re_BufSz + SIZE( Re_Buf )\n"); + fprintf(fp, " DEALLOCATE(Re_Buf)\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " IF(ALLOCATED(Db_Buf)) THEN ! %s\n", r->name); + fprintf(fp, " Db_BufSz = Db_BufSz + SIZE( Db_Buf )\n"); + fprintf(fp, " DEALLOCATE(Db_Buf)\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " IF(ALLOCATED(Int_Buf)) THEN ! %s\n", r->name); + fprintf(fp, " Int_BufSz = Int_BufSz + SIZE( Int_Buf )\n"); + fprintf(fp, " DEALLOCATE(Int_Buf)\n"); + fprintf(fp, " END IF\n"); + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " END DO\n"); + } + + } else { // intrinsic data types + + // do all dimensions of arrays (no need for loop over i%d) + + sprintf(tmp2, "SIZE(InData%%%s)", r->name); + + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp( r->type->mapsto, "REAL(SiKi)") ) { + fprintf(fp, " Re_BufSz = Re_BufSz + %s ! %s\n", (r->ndims>0) ? tmp2 : "1", r->name); + } + else if ( !strcmp( r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)")) { + fprintf(fp, " Db_BufSz = Db_BufSz + %s ! %s\n", (r->ndims>0) ? tmp2 : "1", r->name); + } + else if ( !strcmp( r->type->mapsto, "INTEGER(IntKi)") || + !strcmp( r->type->mapsto, "LOGICAL" ) ) { + fprintf(fp, " Int_BufSz = Int_BufSz + %s ! %s\n", (r->ndims>0) ? tmp2 : "1", r->name); + } + else /*if (!strcmp(r->type->mapsto, "CHARACTER")) */{ + fprintf(fp, " Int_BufSz = Int_BufSz + %s*LEN(InData%%%s) ! %s\n", (r->ndims>0) ? tmp2 : "1", r->name, r->name); + } + /*else + { + fprintf(fp,"! missing buffer for %s\n",r->name ) ; + }*/ + } + + if (has_deferred_dim(r, 0)){ + fprintf(fp, " END IF\n"); + } + // fprintf(fp, "\n"); // space between variables + + + } + + // Allocate buffers + fprintf(fp, " IF ( Re_BufSz .GT. 0 ) THEN \n"); + fprintf(fp, " ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " IF ( Db_BufSz .GT. 0 ) THEN \n"); + fprintf(fp, " ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 )\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " IF ( Int_BufSz .GT. 0 ) THEN \n"); + fprintf(fp, " ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 )\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + fprintf(fp, " END IF\n"); + fprintf(fp, " IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them)\n\n"); + + if (sw_ccode) { + fprintf(fp, " IF (C_ASSOCIATED(InData%%C_obj%%object)) "); + fprintf(fp, "CALL SetErrStat(ErrID_Severe,'C_obj%%object cannot be packed.',ErrStat,ErrMsg,RoutineName)\n\n"); + } + + + fprintf(fp, " Re_Xferred = 1\n"); + fprintf(fp, " Db_Xferred = 1\n"); + fprintf(fp, " Int_Xferred = 1\n\n"); + + + // Pack data + for ( r = q->fields ; r ; r = r->next ) + { + + if (has_deferred_dim(r, 0)) { + // store whether the data type is allocated and the bounds of each dimension + fprintf(fp, " IF ( .NOT. %s(InData%%%s) ) THEN\n", assoc_or_allocated(r), r->name); + fprintf(fp, " IntKiBuf( Int_Xferred ) = 0\n"); // not allocated + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + //fprintf(fp, " IntKiBuf( Int_Xferred:Int_Xferred+2*%d-1 ) = 0\n", r->ndims, r->name); + //fprintf(fp, " Int_Xferred = Int_Xferred + 2*%d\n", r->ndims); + fprintf(fp, " ELSE\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = 1\n"); // allocated + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + for (d = 1; d <= r->ndims; d++) { + fprintf(fp, " IntKiBuf( Int_Xferred ) = LBOUND(InData%%%s,%d)\n", r->name, d); + fprintf(fp, " IntKiBuf( Int_Xferred + 1) = UBOUND(InData%%%s,%d)\n", r->name, d); + fprintf(fp, " Int_Xferred = Int_Xferred + 2\n"); + } + fprintf(fp, "\n"); + strcpy(mainIndent, " "); + } + else { + strcpy(mainIndent, ""); + } + + + if (!strcmp(r->type->name, "meshtype") || + !strcmp(r->type->name, "dll_type") || + (r->type->type_type == DERIVED)) { // call individual routines to pack data from subtypes: + + if (frst == 1) { + fprintf(fp, " ! Allocate buffers for subtypes, if any (we'll get sizes from these) \n"); frst = 0; + } + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " DO i%d = LBOUND(InData%%%s,%d), UBOUND(InData%%%s,%d)\n", d, r->name, d, r->name, d); + } + + if (!strcmp(r->type->name, "meshtype")) { + fprintf(fp, " CALL MeshPack( InData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! %s \n", + r->name, dimstr(r->ndims), r->name); + } + else if (!strcmp(r->type->name, "dll_type")) { + fprintf(fp, " CALL DLLTypePack( InData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! %s \n", + r->name, dimstr(r->ndims), r->name); + } + else if (r->type->type_type == DERIVED) { // && ! r->type->usefrom ) { + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + fprintf(fp, " CALL %s_Pack%s( Re_Buf, Db_Buf, Int_Buf, InData%%%s%s, ErrStat2, ErrMsg2, OnlySize ) ! %s \n", + r->type->module->nickname, fast_interface_type_shortname(nonick2), r->name, + dimstr(r->ndims),r->name); + } + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)\n"); + fprintf(fp, " IF (ErrStat >= AbortErrLev) RETURN\n\n"); + + fprintf(fp, " IF(ALLOCATED(Re_Buf)) THEN\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf\n"); + fprintf(fp, " Re_Xferred = Re_Xferred + SIZE(Re_Buf)\n"); + fprintf(fp, " DEALLOCATE(Re_Buf)\n"); + fprintf(fp, " ELSE\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " ENDIF\n"); + + fprintf(fp, " IF(ALLOCATED(Db_Buf)) THEN\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf\n"); + fprintf(fp, " Db_Xferred = Db_Xferred + SIZE(Db_Buf)\n"); + fprintf(fp, " DEALLOCATE(Db_Buf)\n"); + fprintf(fp, " ELSE\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " ENDIF\n"); + + fprintf(fp, " IF(ALLOCATED(Int_Buf)) THEN\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + SIZE(Int_Buf)\n"); + fprintf(fp, " DEALLOCATE(Int_Buf)\n"); + fprintf(fp, " ELSE\n"); + fprintf(fp, " IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " ENDIF\n"); + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " END DO\n"); + } + + } + else { + // intrinsic data types + // do all dimensions of arrays (no need for loop over i%d) + + strcpy(indent, " "); + strcat(indent, mainIndent); + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, "%s DO i%d = LBOUND(InData%%%s,%d), UBOUND(InData%%%s,%d)\n", indent, d, r->name, d, r->name, d); + strcat(indent, " "); //create an indent + } + + + if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)")) { + fprintf(fp, "%s ReKiBuf(Re_Xferred) = InData%%%s%s\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Re_Xferred = Re_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)")) { + fprintf(fp, "%s DbKiBuf(Db_Xferred) = InData%%%s%s\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Db_Xferred = Db_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "INTEGER(IntKi)") ) { + fprintf(fp, "%s IntKiBuf(Int_Xferred) = InData%%%s%s\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "LOGICAL") ) { + fprintf(fp, "%s IntKiBuf(Int_Xferred) = TRANSFER(InData%%%s%s, IntKiBuf(1))\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + } + + else /*if (!strcmp(r->type->mapsto, "CHARACTER")) */{ + + fprintf(fp, "%s DO I = 1, LEN(InData%%%s)\n", indent, r->name); + fprintf(fp, "%s IntKiBuf(Int_Xferred) = ICHAR(InData%%%s%s(I:I), IntKi)\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + fprintf(fp, "%s END DO ! I\n", indent); + + } + + for (d = r->ndims; d >= 1; d--) { + strcpy(indent, " "); + strcat(indent, mainIndent); + for (i = 1; i < d; i++) { + strcat(indent, " "); + } + fprintf(fp, "%s END DO\n", indent); + } + + } + + if (has_deferred_dim(r, 0)){ + fprintf(fp, " END IF\n"); + } + } + + fprintf(fp," END SUBROUTINE %s_Pack%s\n\n", ModName->nickname,nonick ) ; + return;//(0) ; +} + +void +gen_unpack( FILE * fp, const node_t * ModName, char * inout, char * inoutlong ) +{ + char tmp[NAMELEN], tmp2[NAMELEN], indent[NAMELEN], addnick[NAMELEN], nonick[NAMELEN], nonick2[NAMELEN], mainIndent[6]; + node_t *q, * r ; + int d, i ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; +// sprintf(tmp,"%s_%s",ModName->nickname,inoutlong) ; +// sprintf(tmp,"%s",inoutlong) ; + sprintf(tmp,"%s",addnick) ; + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_UnPack%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + return;//(1) ; + } + + fprintf(fp," SUBROUTINE %s_UnPack%s( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )\n", ModName->nickname,nonick ) ; + fprintf(fp," REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:)\n") ; + fprintf(fp," REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:)\n") ; + fprintf(fp," INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:)\n") ; + fprintf(fp," TYPE(%s), INTENT(INOUT) :: OutData\n",addnick ) ; + fprintf(fp," INTEGER(IntKi), INTENT( OUT) :: ErrStat\n") ; + fprintf(fp," CHARACTER(*), INTENT( OUT) :: ErrMsg\n") ; + fprintf(fp," ! Local variables\n") ; + fprintf(fp," INTEGER(IntKi) :: Buf_size\n") ; + fprintf(fp," INTEGER(IntKi) :: Re_Xferred\n") ; + fprintf(fp," INTEGER(IntKi) :: Db_Xferred\n") ; + fprintf(fp," INTEGER(IntKi) :: Int_Xferred\n") ; + fprintf(fp," INTEGER(IntKi) :: i\n") ; + for (d = 1; d <= q->max_ndims; d++){ + fprintf(fp," INTEGER(IntKi) :: i%d, i%d_l, i%d_u ! bounds (upper/lower) for an array dimension %d\n", d, d, d, d); + } + fprintf(fp, " INTEGER(IntKi) :: ErrStat2\n"); + fprintf(fp, " CHARACTER(ErrMsgLen) :: ErrMsg2\n"); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_UnPack%s'\n", ModName->nickname, nonick); + + fprintf(fp," ! buffers to store meshes, if any\n") ; + fprintf(fp," REAL(ReKi), ALLOCATABLE :: Re_Buf(:)\n") ; + fprintf(fp," REAL(DbKi), ALLOCATABLE :: Db_Buf(:)\n") ; + fprintf(fp," INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)\n") ; + fprintf(fp," !\n") ; + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp," ErrMsg = \"\"\n") ; + fprintf(fp," Re_Xferred = 1\n") ; + fprintf(fp," Db_Xferred = 1\n") ; + fprintf(fp," Int_Xferred = 1\n") ; + + +// BJJ: TODO: if there are C types, we're going to have to associate with C data structures.... + + // Unpack data + for (r = q->fields; r; r = r->next) + { + + strcpy(tmp, ""); + if (has_deferred_dim(r, 0)){ + // determine if the array was allocated when packed: + fprintf(fp, " IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! %s not allocated\n", r->name); // not allocated + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + //fprintf(fp, " Int_Xferred = Int_Xferred + 2*%d\n", r->ndims); + fprintf(fp, " ELSE\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + + for (d = 1; d <= r->ndims; d++) { + fprintf(fp, " i%d_l = IntKiBuf( Int_Xferred )\n", d); //fprintf(fp, " IntKiBuf( Int_Xferred ) = LBOUND(OutData%%%s,%d)\n", r->name, d); + fprintf(fp, " i%d_u = IntKiBuf( Int_Xferred + 1)\n", d); //fprintf(fp, " IntKiBuf( Int_Xferred + 1) = UBOUND(OutData%%%s,%d)\n", r->name, d); + fprintf(fp, " Int_Xferred = Int_Xferred + 2\n"); + sprintf(tmp2, ",i%d_l:i%d_u", d, d); + strcat(tmp, tmp2); + } + + fprintf(fp, " IF (%s(OutData%%%s)) DEALLOCATE(OutData%%%s)\n", assoc_or_allocated(r), r->name, r->name); // BJJ: need NULLIFY(), too? + fprintf(fp, " ALLOCATE(OutData%%%s(%s),STAT=ErrStat2)\n", r->name, (char*)&(tmp[1])); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%%%s.', ErrStat, ErrMsg,RoutineName)\n", r->name); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + + if (sw_ccode && is_pointer(r)) { // bjj: this needs to be updated if we've got multiple dimension arrays + fprintf(fp, " OutData%%c_obj%%%s_Len = SIZE(OutData%%%s)\n", r->name, r->name); + fprintf(fp, " IF (OutData%%c_obj%%%s_Len > 0) &\n", r->name); + fprintf(fp, " OutData%%c_obj%%%s = C_LOC( OutData%%%s(i1_l) ) \n", r->name, r->name); + } + strcpy(mainIndent, " "); + } + else{ + for (d = 1; d <= r->ndims; d++) { + fprintf(fp, " i%d_l = LBOUND(OutData%%%s,%d)\n", d, r->name, d); + fprintf(fp, " i%d_u = UBOUND(OutData%%%s,%d)\n", d, r->name, d); + sprintf(tmp2, ",i%d_l:i%d_u", d, d); + strcat(tmp, tmp2); + } + strcpy(mainIndent, ""); + } + + if (!strcmp(r->type->name, "meshtype") || + !strcmp(r->type->name, "dll_type") || + (r->type->type_type == DERIVED)) { // call individual routines to pack data from subtypes: + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " DO i%d = LBOUND(OutData%%%s,%d), UBOUND(OutData%%%s,%d)\n", d, r->name, d, r->name, d); + } + + // initialize buffers to send to subtype-unpack routines: + // reals: + fprintf(fp, " Buf_size=IntKiBuf( Int_Xferred )\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF(Buf_size > 0) THEN\n"); + fprintf(fp, " ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )\n"); + fprintf(fp, " Re_Xferred = Re_Xferred + Buf_size\n"); + fprintf(fp, " END IF\n"); + + // doubles: + fprintf(fp, " Buf_size=IntKiBuf( Int_Xferred )\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF(Buf_size > 0) THEN\n"); + fprintf(fp, " ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )\n"); + fprintf(fp, " Db_Xferred = Db_Xferred + Buf_size\n"); + fprintf(fp, " END IF\n"); + + // integers: + fprintf(fp, " Buf_size=IntKiBuf( Int_Xferred )\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + 1\n"); + fprintf(fp, " IF(Buf_size > 0) THEN\n"); + fprintf(fp, " ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)\n"); + fprintf(fp, " IF (ErrStat2 /= 0) THEN \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n"); + + fprintf(fp, " Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )\n"); + fprintf(fp, " Int_Xferred = Int_Xferred + Buf_size\n"); + fprintf(fp, " END IF\n"); + + + if (!strcmp(r->type->name, "meshtype")) { + fprintf(fp, " CALL MeshUnpack( OutData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! %s \n", + r->name, dimstr(r->ndims), r->name); + } + else if (!strcmp(r->type->name, "dll_type")) { + fprintf(fp, " CALL DLLTypeUnpack( OutData%%%s%s, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! %s \n", + r->name, dimstr(r->ndims), r->name); + } + else if (r->type->type_type == DERIVED) { // && ! r->type->usefrom ) { + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + fprintf(fp, " CALL %s_Unpack%s( Re_Buf, Db_Buf, Int_Buf, OutData%%%s%s, ErrStat2, ErrMsg2 ) ! %s \n", + r->type->module->nickname, fast_interface_type_shortname(nonick2), r->name, + dimstr(r->ndims), r->name); + } + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)\n"); + fprintf(fp, " IF (ErrStat >= AbortErrLev) RETURN\n\n"); + + fprintf(fp, " IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )\n"); + fprintf(fp, " IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )\n"); + fprintf(fp, " IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)\n"); + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, " END DO\n"); + } + + } + else + { + strcpy(indent, " "); + strcat(indent, mainIndent); + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, "%s DO i%d = LBOUND(OutData%%%s,%d), UBOUND(OutData%%%s,%d)\n", indent, d, r->name, d, r->name, d); + strcat(indent, " "); //create an indent + } + + + if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)")) { + if (sw_ccode && is_pointer(r)) { + fprintf(fp, "%s OutData%%%s%s = REAL(ReKiBuf(Re_Xferred), C_FLOAT)\n", indent, r->name, dimstr(r->ndims)); + } + else if (!strcmp(r->type->mapsto, "REAL(SiKi)")) { + fprintf(fp, "%s OutData%%%s%s = REAL(ReKiBuf(Re_Xferred), SiKi)\n", indent, r->name, dimstr(r->ndims)); + } + else { + fprintf(fp, "%s OutData%%%s%s = ReKiBuf(Re_Xferred)\n", indent, r->name, dimstr(r->ndims)); + } + fprintf(fp, "%s Re_Xferred = Re_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)")) { + if (sw_ccode && is_pointer(r)) { + fprintf(fp, "%s OutData%%%s%s = REAL(DbKiBuf(Db_Xferred), C_DOUBLE)\n", indent, r->name, dimstr(r->ndims)); + } + else if (!strcmp(r->type->mapsto, "REAL(R8Ki)")) { + fprintf(fp, "%s OutData%%%s%s = REAL(DbKiBuf(Db_Xferred), R8Ki)\n", indent, r->name, dimstr(r->ndims)); + } + else { + fprintf(fp, "%s OutData%%%s%s = DbKiBuf(Db_Xferred)\n", indent, r->name, dimstr(r->ndims)); + } + fprintf(fp, "%s Db_Xferred = Db_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "INTEGER(IntKi)")) { + fprintf(fp, "%s OutData%%%s%s = IntKiBuf(Int_Xferred)\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + } + else if (!strcmp(r->type->mapsto, "LOGICAL")) { + fprintf(fp, "%s OutData%%%s%s = TRANSFER(IntKiBuf(Int_Xferred), OutData%%%s%s)\n", indent, r->name, dimstr(r->ndims), r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + } + + else /*if (!strcmp(r->type->mapsto, "CHARACTER")) */ { + + fprintf(fp, "%s DO I = 1, LEN(OutData%%%s)\n", indent, r->name); + fprintf(fp, "%s OutData%%%s%s(I:I) = CHAR(IntKiBuf(Int_Xferred))\n", indent, r->name, dimstr(r->ndims)); + fprintf(fp, "%s Int_Xferred = Int_Xferred + 1\n", indent); + fprintf(fp, "%s END DO ! I\n", indent); + + } + + for (d = r->ndims; d >= 1; d--) { + strcpy(indent, " "); + strcat(indent, mainIndent); + for (i = 1; i < d; i++) { + strcat(indent, " "); + } + fprintf(fp, "%s END DO\n", indent); + } + +// need to move scalars and strings to the %c_obj% type, too! +// compare with copy routine + + if (sw_ccode && !is_pointer(r) && r->ndims == 0) { + if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(DbKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "INTEGER(IntKi)") || + !strcmp(r->type->mapsto, "LOGICAL")) + { + fprintf(fp, " OutData%%C_obj%%%s = OutData%%%s\n", r->name, r->name); + } + else { // characters need to be copied differently + fprintf(fp, " OutData%%C_obj%%%s = TRANSFER(OutData%%%s, OutData%%C_obj%%%s )\n", r->name, r->name, r->name); + } + } + + } + + if (has_deferred_dim(r, 0)){ + fprintf(fp, " END IF\n"); + } + } + + fprintf(fp," END SUBROUTINE %s_UnPack%s\n\n", ModName->nickname,nonick ) ; + return;//(0) ; +} + +void +gen_mask_alloc( FILE *fp, int ndims, char *tmp ) +{ + if ( ndims == 1 ) { + fprintf(fp," ALLOCATE(mask%d(SIZE(%s,1)))\n mask%d = .TRUE.\n",ndims,tmp,ndims) ; + } else if ( ndims == 2 ) { + fprintf(fp," ALLOCATE(mask%d(SIZE(%s,1),SIZE(%s,2)))\n mask%d = .TRUE.\n",ndims,tmp,tmp,ndims) ; + } else if ( ndims == 3 ) { + fprintf(fp," ALLOCATE(mask%d(SIZE(%s,1),SIZE(%s,2),SIZE(%s,3)))\n mask%d = .TRUE.\n",ndims,tmp,tmp,tmp,ndims) ; + } else if ( ndims == 4 ) { + fprintf(fp," ALLOCATE(mask%d(SIZE(%s,1),SIZE(%s,2),SIZE(%s,3),SIZE(%s,4)))\n mask%d = .TRUE.\n",ndims,tmp,tmp,tmp,tmp,ndims) ; + } else if ( ndims == 5 ) { + fprintf(fp," ALLOCATE(mask%d(SIZE(%s,1),SIZE(%s,2),SIZE(%s,3),SIZE(%s,4),SIZE(%s,5)))\n mask%d = .TRUE.\n",ndims,tmp,tmp,tmp,tmp,tmp,ndims) ; + } +} + + + +int +gen_destroy( FILE * fp, const node_t * ModName, char * inout, char * inoutlong ) +{ + char tmp[NAMELEN], addnick[NAMELEN], nonick[NAMELEN] ; + node_t *q, * r ; + int d ; + + remove_nickname(ModName->nickname,inout,nonick) ; + append_nickname((is_a_fast_interface_type(inoutlong))?ModName->nickname:"",inoutlong,addnick) ; + fprintf(fp, " SUBROUTINE %s_Destroy%s( %sData, ErrStat, ErrMsg )\n",ModName->nickname,nonick,nonick ); + fprintf(fp, " TYPE(%s), INTENT(INOUT) :: %sData\n",addnick,nonick) ; + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat\n") ; + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg\n"); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_Destroy%s'\n", ModName->nickname, nonick); + fprintf(fp, " INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 \n"); + fprintf(fp,"! \n") ; + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp, " ErrMsg = \"\"\n"); + +// sprintf(tmp,"%s_%s",ModName->nickname,inoutlong) ; +// sprintf(tmp,"%s",inoutlong) ; + sprintf(tmp,"%s",addnick) ; + if (( q = get_entry( make_lower_temp(tmp),ModName->module_ddt_list ) ) == NULL ) + { + fprintf(stderr,"Registry warning: generating %s_Destroy%s: cannot find definition for %s\n",ModName->nickname,nonick,tmp) ; + } else { + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type == NULL ) { + fprintf(stderr,"Registry warning generating %s_Destroy%s: %s has no type.\n",ModName->nickname,nonick,r->name) ; + } else { + + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp,"IF (%s(%sData%%%s)) THEN\n",assoc_or_allocated(r),nonick,r->name) ; + } + + if (r->type->type_type == DERIVED){ + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, "DO i%d = LBOUND(%sData%%%s,%d), UBOUND(%sData%%%s,%d)\n", d, nonick, r->name, d, nonick, r->name, d); + } + + if (!strcmp(r->type->name, "meshtype")) { + fprintf(fp, " CALL MeshDestroy( %sData%%%s%s, ErrStat, ErrMsg )\n", nonick, r->name, dimstr(r->ndims)); + } + else if (!strcmp(r->type->name, "dll_type")) { + fprintf(fp, " CALL FreeDynamicLib( %sData%%%s%s, ErrStat, ErrMsg )\n", nonick, r->name, dimstr(r->ndims)); + } + else { //if (r->type->type_type == DERIVED) { // && ! r->type->usefrom ) { + char nonick2[NAMELEN]; + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + fprintf(fp, " CALL %s_Destroy%s( %sData%%%s%s, ErrStat, ErrMsg )\n", + r->type->module->nickname, fast_interface_type_shortname(nonick2), nonick, r->name, dimstr(r->ndims)); + } + + for (d = r->ndims; d >= 1; d--) { + fprintf(fp, "ENDDO\n"); + } + } + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp," DEALLOCATE(%sData%%%s)\n",nonick,r->name) ; + if ( is_pointer(r) ) { + fprintf(fp, " %sData%%%s => NULL()\n",nonick,r->name) ; + if (sw_ccode){ + fprintf(fp, " %sData%%C_obj%%%s = C_NULL_PTR\n", nonick, r->name); + fprintf(fp, " %sData%%C_obj%%%s_Len = 0\n", nonick, r->name); + } + } + fprintf(fp,"ENDIF\n") ; + } + + + } + } + } + + fprintf(fp," END SUBROUTINE %s_Destroy%s\n\n", ModName->nickname,nonick ) ; + return(0) ; +} + + +#define MAXRECURSE 9 +// HERE +#if 0 +void gen_extint_order(FILE *fp, const node_t *ModName, char * typnm, char * uy, const int order, node_t *r, char * deref, int recurselevel) { + node_t *q, *r1 ; + int j ; + int mesh = 0 ; + char derefrecurse[NAMELEN],tmp[NAMELEN] ; + if ( recurselevel > MAXRECURSE ) { + fprintf(stderr,"REGISTRY ERROR: too many levels of array subtypes\n") ; + exit(9) ; + } + if ( r->type != NULL ) { + +// check if this is an allocatable array: + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp,"IF (%s(%s_out%s%%%s) .AND. %s(%s(1)%s%%%s)) THEN\n",assoc_or_allocated(r),uy,deref,r->name, + assoc_or_allocated(r), uy, deref, r->name); + } + if ( r->type->type_type == DERIVED ) { + if (( q = get_entry( make_lower_temp(r->type->name),ModName->module_ddt_list ) ) != NULL ) { + for ( r1 = q->fields ; r1 ; r1 = r1->next ) + { + sprintf(derefrecurse,"%s%%%s",deref,r->name) ; + for ( j = r->ndims ; j > 0 ; j-- ) { + + fprintf(fp, " DO i%d%d = LBOUND(%s_out%s,%d),UBOUND(%s_out%s,%d)\n", recurselevel, j, uy, derefrecurse, j, uy, derefrecurse, j); + sprintf(derefrecurse,"%s%%%s(i%d%d)",deref,r->name,recurselevel,j) ; + } + gen_extint_order( fp, ModName, typnm, uy, order, r1, derefrecurse, recurselevel+1 ) ; + for ( j = r->ndims ; j > 0 ; j-- ) { + fprintf(fp," ENDDO\n") ; + } + } + } else if ( !strcmp( r->type->mapsto, "MeshType" ) ) { + for ( j = r->ndims ; j > 0 ; j-- ) { + fprintf(fp, " DO i%d%d = LBOUND(%s_out%s%%%s,%d),UBOUND(%s_out%s%%%s,%d)\n", 0, j, uy, deref, r->name, j, uy, deref, r->name, j); + } + + if ( order == 0 ) { + fprintf(fp, " CALL MeshCopy(%s(1)%s%%%s%s, %s_out%s%%%s%s, MESH_UPDATECOPY, ErrStat2, ErrMsg2 )\n", uy, deref, r->name, dimstr(r->ndims) + , uy, deref, r->name, dimstr(r->ndims)); + } else if ( order == 1 ) { + fprintf(fp," CALL MeshExtrapInterp1(%s(1)%s%%%s%s, %s(2)%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n" + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } else if ( order == 2 ) { + fprintf(fp," CALL MeshExtrapInterp2(%s(1)%s%%%s%s, %s(2)%s%%%s%s, %s(3)%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n" + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " IF (ErrStat>=AbortErrLev) RETURN\n"); + + for ( j = r->ndims ; j > 0 ; j-- ) { + fprintf(fp," ENDDO\n") ; + } + } else { + + + char nonick2[NAMELEN] ; + remove_nickname(r->type->module->nickname,r->type->name,nonick2) ; + strcpy(dimstr(r->ndims),"") ; + for ( j = r->ndims ; j >= 1 ; j-- ) { + fprintf(fp, " DO i%d%d = LBOUND(%s_out%s%%%s,%d), UBOUND(%s_out%s%%%s,%d)\n", 0, j, uy, deref, r->name, j, uy, deref, r->name, j); + if ( j == r->ndims ) strcat(dimstr(r->ndims),"(") ; + sprintf(tmp,"i%d%d",0,j) ; + if ( j == 1 ) strcat(tmp,")") ; else strcat(tmp,",") ; + strcat(dimstr(r->ndims),tmp) ; + } + + + fprintf(fp," CALL %s_%s_ExtrapInterp( %s%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n", + r->type->module->nickname,fast_interface_type_shortname(nonick2) + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + fprintf(fp," CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp," IF (ErrStat>=AbortErrLev) RETURN\n"); + + + for ( j = r->ndims ; j >= 1 ; j-- ) { + fprintf(fp," ENDDO\n") ; + } + + } + } else if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp( r->type->mapsto, "REAL(SiKi)") || + !strcmp( r->type->mapsto, "REAL(DbKi)") ) { + if ( r->ndims==0 ) { + } else if ( r->ndims==1 && order > 0 ) { + fprintf(fp, " ALLOCATE(b1(SIZE(%s_out%s%%%s,1)))\n", uy, deref, r->name); + fprintf(fp, " ALLOCATE(c1(SIZE(%s_out%s%%%s,1)))\n", uy, deref, r->name); + } else if ( r->ndims==2 && order > 0 ) { + fprintf(fp, " ALLOCATE(b2(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2) ))\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " ALLOCATE(c2(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2) ))\n", uy, deref, r->name, uy, deref, r->name); + } else if ( r->ndims==3 && order > 0 ) { + fprintf(fp, " ALLOCATE(b3(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3) ))\n", uy, deref, r->name); + fprintf(fp, " ALLOCATE(c3(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3) ))\n", uy, deref, r->name); + } else if ( r->ndims==4 && order > 0 ) { + fprintf(fp, " ALLOCATE(b4(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3),SIZE(%s_out%s%%%s,4) ))\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " ALLOCATE(c4(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3),SIZE(%s_out%s%%%s,4) ))\n", uy, deref, r->name, uy, deref, r->name); + } else if ( r->ndims==5 && order > 0 ) { + fprintf(fp, " ALLOCATE(b5(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3),SIZE(%s_out%s%%%s,4), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,5) ))\n", uy, deref, r->name); + fprintf(fp, " ALLOCATE(c5(SIZE(%s_out%s%%%s,1),SIZE(%s_out%s%%%s,2), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,3),SIZE(%s_out%s%%%s,4), &\n", uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " SIZE(%s_out%s%%%s,5) ))\n", uy, deref, r->name); + } else { + if (order > 0) fprintf(stderr, "Registry WARNING: too many dimensions for %s%%%s\n", deref, r->name); + } + + if ( order == 0 ) { + fprintf(fp, " %s_out%s%%%s = %s(1)%s%%%s\n", uy, deref, r->name, uy, deref, r->name); + } else if ( order == 1 ) { + fprintf(fp, " b%d = -(%s(1)%s%%%s - %s(2)%s%%%s)/t(2)\n", r->ndims, uy, deref, r->name, uy, deref, r->name); + fprintf(fp, " %s_out%s%%%s = %s(1)%s%%%s + b%d * t_out\n", uy, deref, r->name, uy, deref, r->name, r->ndims); + } else if ( order == 2 ) { + fprintf(fp," b%d = (t(3)**2*(%s(1)%s%%%s - %s(2)%s%%%s) + t(2)**2*(-%s(1)%s%%%s + %s(3)%s%%%s))/(t(2)*t(3)*(t(2) - t(3)))\n", + r->ndims, uy, deref, r->name, uy, deref, r->name, uy, deref, r->name, uy, deref, r->name); + fprintf(fp," c%d = ( (t(2)-t(3))*%s(1)%s%%%s + t(3)*%s(2)%s%%%s - t(2)*%s(3)%s%%%s ) / (t(2)*t(3)*(t(2) - t(3)))\n", + r->ndims, uy, deref, r->name, uy, deref, r->name, uy, deref, r->name); + fprintf(fp," %s_out%s%%%s = %s(1)%s%%%s + b%d * t_out + c%d * t_out**2\n" + , uy, deref, r->name, uy, deref, r->name, r->ndims, r->ndims); + } + if ( r->ndims>=1 && order > 0 ) { + fprintf(fp," DEALLOCATE(b%d)\n",r->ndims) ; + fprintf(fp," DEALLOCATE(c%d)\n",r->ndims) ; + } + } +// check if this is an allocatable array: + if ( r->ndims > 0 && has_deferred_dim(r,0) ) { + fprintf(fp,"END IF ! check if allocated\n") ; + } + + } +} +#endif +void gen_extint_order(FILE *fp, const node_t *ModName, char * typnm, char * uy, const int order, node_t *r, char * deref, int recurselevel) { + node_t *q, *r1; + int i, j; + int mesh = 0; + char derefrecurse[NAMELEN], indent[NAMELEN], tmp[NAMELEN]; + if (recurselevel > MAXRECURSE) { + fprintf(stderr, "REGISTRY ERROR: too many levels of array subtypes\n"); + exit(9); + } + if (r->type != NULL) { + + // check if this is an allocatable array: + if (r->ndims > 0 && has_deferred_dim(r, 0)) { + fprintf(fp, "IF (%s(%s_out%s%%%s) .AND. %s(%s1%s%%%s)) THEN\n", assoc_or_allocated(r), uy, deref, r->name, + assoc_or_allocated(r), uy, deref, r->name); + } + if (r->type->type_type == DERIVED) { + + if ((q = get_entry(make_lower_temp(r->type->name), ModName->module_ddt_list)) != NULL) { + for (r1 = q->fields; r1; r1 = r1->next) + { + sprintf(derefrecurse, "%s%%%s", deref, r->name); + + for (j = r->ndims; j > 0; j--) { + fprintf(fp, " DO i%d%d = LBOUND(%s_out%s,%d),UBOUND(%s_out%s,%d)\n", recurselevel, j, uy, derefrecurse, j, uy, derefrecurse, j); + } + + + if (r->ndims > 0) { + strcat(derefrecurse, "("); + for (j = 1; j <= r->ndims; j++) { + sprintf(tmp, "i%d%d", recurselevel, j); + strcat(derefrecurse, tmp); + if (j < r->ndims) { + strcat(derefrecurse, ","); + } + } + strcat(derefrecurse, ")"); + } + + gen_extint_order(fp, ModName, typnm, uy, order, r1, derefrecurse, recurselevel + 1); + for (j = r->ndims; j > 0; j--) { + fprintf(fp, " ENDDO\n"); + } + } + } + + else { + + for (j = r->ndims; j > 0; j--) { + fprintf(fp, " DO i%d = LBOUND(%s_out%s%%%s,%d),UBOUND(%s_out%s%%%s,%d)\n", j, uy, deref, r->name, j, uy, deref, r->name, j); + } + + if (!strcmp(r->type->mapsto, "MeshType")) { + if (order == 0) { + fprintf(fp, " CALL MeshCopy(%s1%s%%%s%s, %s_out%s%%%s%s, MESH_UPDATECOPY, ErrStat2, ErrMsg2 )\n", uy, deref, r->name, dimstr(r->ndims) + , uy, deref, r->name, dimstr(r->ndims)); + } + else if (order == 1) { + fprintf(fp, " CALL MeshExtrapInterp1(%s1%s%%%s%s, %s2%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n" + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + else if (order == 2) { + fprintf(fp, " CALL MeshExtrapInterp2(%s1%s%%%s%s, %s2%s%%%s%s, %s3%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n" + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + } + else { + char nonick2[NAMELEN]; + remove_nickname(r->type->module->nickname, r->type->name, nonick2); + + if (order == 0) { + fprintf(fp, " CALL %s_Copy%s(%s1%s%%%s%s, %s_out%s%%%s%s, MESH_UPDATECOPY, ErrStat2, ErrMsg2 )\n", r->type->module->nickname, fast_interface_type_shortname(nonick2) + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + else if (order == 1) { + fprintf(fp, " CALL %s_%s_ExtrapInterp1( %s1%s%%%s%s, %s2%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n", + r->type->module->nickname, fast_interface_type_shortname(nonick2) + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + else if (order == 2) { + fprintf(fp, " CALL %s_%s_ExtrapInterp2( %s1%s%%%s%s, %s2%s%%%s%s, %s3%s%%%s%s, tin, %s_out%s%%%s%s, tin_out, ErrStat2, ErrMsg2 )\n", + r->type->module->nickname, fast_interface_type_shortname(nonick2) + , uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + } + + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + //fprintf(fp, " IF (ErrStat>=AbortErrLev) RETURN\n"); + for (j = r->ndims; j >= 1; j--) { + fprintf(fp, " ENDDO\n"); + } + + } + } + else if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "REAL(DbKi)")) { + + + if (order == 0) { + //bjj: this should probably have some "IF ALLOCATED" statements around it, but we're just calling + // the copy routine + fprintf(fp, " %s_out%s%%%s = %s1%s%%%s\n", uy, deref, r->name, uy, deref, r->name); + } + else + strcpy(indent, ""); + for (j = r->ndims; j > 0; j--) { + fprintf(fp, "%s DO i%d = LBOUND(%s_out%s%%%s,%d),UBOUND(%s_out%s%%%s,%d)\n", indent, j, uy, deref, r->name, j, uy, deref, r->name, j); + strcat(indent, " "); //create an indent + } + + if (order == 1) { + if (r->gen_periodic) { + fprintf(fp, "%s CALL Angles_ExtrapInterp( %s1%s%%%s%s, %s2%s%%%s%s, tin, %s_out%s%%%s%s, tin_out )\n", + indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + else { + fprintf(fp, "%s b = -(%s1%s%%%s%s - %s2%s%%%s%s)\n", indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + fprintf(fp, "%s %s_out%s%%%s%s = %s1%s%%%s%s + b * ScaleFactor\n", indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + }; + } + if (order == 2) { + if (r->gen_periodic) { + fprintf(fp, "%s CALL Angles_ExtrapInterp( %s1%s%%%s%s, %s2%s%%%s%s, %s3%s%%%s%s, tin, %s_out%s%%%s%s, tin_out )\n", + indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + else { + fprintf(fp, "%s b = (t(3)**2*(%s1%s%%%s%s - %s2%s%%%s%s) + t(2)**2*(-%s1%s%%%s%s + %s3%s%%%s%s))* scaleFactor\n", + indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + fprintf(fp, "%s c = ( (t(2)-t(3))*%s1%s%%%s%s + t(3)*%s2%s%%%s%s - t(2)*%s3%s%%%s%s ) * scaleFactor\n", + indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + fprintf(fp, "%s %s_out%s%%%s%s = %s1%s%%%s%s + b + c * t_out\n", + indent, uy, deref, r->name, dimstr(r->ndims), uy, deref, r->name, dimstr(r->ndims)); + } + } + for (j = r->ndims; j >= 1; j--) { + strcpy(indent, ""); + for (i = 1; i < j; i++) { + strcat(indent, " "); + } + fprintf(fp, "%s END DO\n", indent); + } + } + // check if this is an allocatable array: + if (r->ndims > 0 && has_deferred_dim(r, 0)) { + fprintf(fp, "END IF ! check if allocated\n"); + } + } + +} // gen_extint_order + +void calc_extint_order(FILE *fp, const node_t *ModName, node_t *r, int recurselevel, int *max_ndims, int *max_nrecurs, int *max_alloc_ndims) { + node_t *q, *r1 ; +// bjj: make sure this is consistent with logic of gen_extint_order + + if ( r->type != NULL ) { + // if(r->ndims > *max_ndims )* max_ndims = r->ndims; + + if (r->type->type_type == DERIVED) { + if ((q = get_entry(make_lower_temp(r->type->name), ModName->module_ddt_list)) != NULL) { + for (r1 = q->fields; r1; r1 = r1->next) + { + if (r->ndims > 0) { + if (recurselevel > *max_nrecurs) *max_nrecurs = recurselevel; + if (r->ndims > *max_ndims ) *max_ndims = r->ndims; + } + calc_extint_order(fp, ModName, r1, recurselevel + 1, max_ndims, max_nrecurs, max_alloc_ndims); + } + } + else if (!strcmp(r->type->mapsto, "MeshType")) { + if (r->ndims > 0) { + if (r->ndims > *max_ndims)* max_ndims = r->ndims; + } + } + else { + if (r->ndims >= 1) { + if (r->ndims > *max_ndims)* max_ndims = r->ndims; + } + } + + } + else if (!strcmp(r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "REAL(DbKi)")) { + if (/*order > 0 &&*/ r->ndims > *max_alloc_ndims) *max_alloc_ndims = r->ndims; + if (r->ndims > *max_ndims)* max_ndims = r->ndims; + } + + + } + + if ( recurselevel > MAXRECURSE ) { + fprintf(stderr,"REGISTRY ERROR: too many levels of array subtypes\n") ; + exit(9) ; + } + +} + +#if 0 +void +gen_ExtrapInterp( FILE *fp , const node_t * ModName, char * typnm, char * typnmlong ) +{ + char nonick[NAMELEN] ; + char *ddtname; char uy[2]; + node_t *q, * r ; + int i, j, max_ndims, max_nrecurs, max_alloc_ndims; + + if (!strcmp(make_lower_temp(typnm), "output")){ + strcpy(uy,"y"); + } + else{ + strcpy(uy, "u"); + } + + fprintf(fp,"\n") ; + fprintf(fp," SUBROUTINE %s_%s_ExtrapInterp(%s, tin, %s_out, tin_out, ErrStat, ErrMsg )\n",ModName->nickname,typnm,uy,uy) ; + fprintf(fp,"!\n") ; + fprintf(fp, "! This subroutine calculates a extrapolated (or interpolated) %s %s_out at time t_out, from previous/future time\n", typnm, uy); + fprintf(fp, "! values of %s (which has values associated with times in t). Order of the interpolation is given by the size of %s\n", uy, uy); + fprintf(fp,"!\n") ; + fprintf(fp,"! expressions below based on either\n") ; + fprintf(fp,"!\n") ; + fprintf(fp,"! f(t) = a\n") ; + fprintf(fp,"! f(t) = a + b * t, or\n") ; + fprintf(fp,"! f(t) = a + b * t + c * t**2\n") ; + fprintf(fp,"!\n") ; + fprintf(fp,"! where a, b and c are determined as the solution to\n") ; + fprintf(fp, "! f(t1) = %s1, f(t2) = %s2, f(t3) = %s3 (as appropriate)\n", uy, uy, uy); + fprintf(fp,"!\n") ; + fprintf(fp,"!..................................................................................................................................\n") ; + fprintf(fp,"\n") ; + + + fprintf(fp, " TYPE(%s_%s), INTENT(INOUT) :: %s(:) ! %s at t1 > t2 > t3\n", ModName->nickname, typnmlong, uy, typnm); + fprintf(fp, " REAL(DbKi), INTENT(IN ) :: tin(:) ! Times associated with the %ss\n", typnm); +//jm Modified from INTENT( OUT) to INTENT(INOUT) to prevent ALLOCATABLE array arguments in the DDT +//jm from being maliciously deallocated through the call.See Sec. 5.1.2.7 of bonehead Fortran 2003 standard + fprintf(fp, " TYPE(%s_%s), INTENT(INOUT) :: %s_out ! %s at tin_out\n", ModName->nickname, typnmlong, uy, typnm); + fprintf(fp," REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to\n") ; + fprintf(fp," INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation\n") ; + fprintf(fp," CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None\n") ; + fprintf(fp," ! local variables\n") ; + fprintf(fp, " REAL(DbKi) :: t(SIZE(tin)) ! Times associated with the %ss\n", typnm); + fprintf(fp," REAL(DbKi) :: t_out ! Time to which to be extrap/interpd\n") ; + fprintf(fp," INTEGER(IntKi) :: order ! order of polynomial fit (max 2)\n") ; + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_%s_ExtrapInterp'\n", ModName->nickname, typnm); + + max_ndims = 0; // ModName->module_ddt_list->max_ndims; //bjj: this is max for module, not for typnmlong + max_nrecurs = 0; // MAXRECURSE; + max_alloc_ndims = 0; + + for (q = ModName->module_ddt_list; q; q = q->next) + { + if (q->usefrom == 0) { + ddtname = q->name; + remove_nickname(ModName->nickname, ddtname, nonick); + if (!strcmp(nonick, make_lower_temp(typnmlong))) { + for (r = q->fields; r; r = r->next) + { + // recursive + calc_extint_order(fp, ModName, r, 0, &max_ndims, &max_nrecurs, &max_alloc_ndims); + } + } + } + } + //fprintf(stderr, "ndims=%d nrecurs=%d %d\n\n", max_ndims, max_nrecurs, max_alloc_ndims); + + if (max_alloc_ndims >= 0){ + fprintf(fp," REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation\n") ; + if (max_alloc_ndims >= 1){ + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation\n") ; + if (max_alloc_ndims >= 2){ + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: b2 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:) :: c2 ! temporary for extrapolation/interpolation\n") ; + if (max_alloc_ndims >= 3){ + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:) :: b3 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:) :: c3 ! temporary for extrapolation/interpolation\n") ; + if (max_alloc_ndims >= 4){ + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:,:) :: b4 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:,:) :: c4 ! temporary for extrapolation/interpolation\n") ; + if (max_alloc_ndims >= 5){ + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:,:,:):: b5 ! temporary for extrapolation/interpolation\n") ; + fprintf(fp," REAL(DbKi),ALLOCATABLE,DIMENSION(:,:,:,:,:):: c5 ! temporary for extrapolation/interpolation\n") ; + } // 5 + } // 4 + } // 3 + } // 2 + } // 1 + } // 0 + fprintf(fp," INTEGER(IntKi) :: ErrStat2 ! local errors\n"); + fprintf(fp," CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors\n"); + for ( j = 1 ; j <= max_ndims ; j++ ) { + for ( i = 0 ; i <= max_nrecurs ; i++ ) { + fprintf(fp," INTEGER :: i%d%d ! dim%d level %d counter variable for arrays of ddts\n",i,j,j,i) ; + } + } + fprintf(fp," ! Initialize ErrStat\n") ; + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp," ErrMsg = \"\"\n") ; + fprintf(fp," ! we'll subtract a constant from the times to resolve some \n") ; + fprintf(fp," ! numerical issues when t gets large (and to simplify the equations)\n") ; + fprintf(fp," t = tin - tin(1)\n") ; + fprintf(fp," t_out = tin_out - tin(1)\n") ; + fprintf(fp,"\n") ; + fprintf(fp, " if ( size(t) .ne. size(%s)) then\n", uy); + fprintf(fp," ErrStat = ErrID_Fatal\n") ; + fprintf(fp, " ErrMsg = ' Error in %s_%s_ExtrapInterp: size(t) must equal size(%s) '\n", ModName->nickname, typnm, uy); + fprintf(fp," RETURN\n") ; + fprintf(fp," endif\n") ; + fprintf(fp, " if (size(%s) .gt. 3) then\n", uy); + fprintf(fp," ErrStat = ErrID_Fatal\n") ; + fprintf(fp, " ErrMsg = ' Error in %s_%s_ExtrapInterp: size(%s) must be less than 4 '\n", ModName->nickname, typnm, uy); + fprintf(fp," RETURN\n") ; + fprintf(fp," endif\n") ; + + fprintf(fp, " order = SIZE(%s) - 1\n", uy); + + fprintf(fp," IF ( order .eq. 0 ) THEN\n") ; + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, make_lower_temp(typnmlong) )) { + for ( r = q->fields ; r ; r = r->next ) + { + // recursive + gen_extint_order( fp, ModName, typnm, uy, 0, r, "", 0 ) ; + } + } + } + } + + fprintf(fp," ELSE IF ( order .eq. 1 ) THEN\n") ; +fprintf(fp," IF ( EqualRealNos( t(1), t(2) ) ) THEN\n") ; +fprintf(fp," ErrStat = ErrID_Fatal\n") ; +fprintf(fp," ErrMsg = ' Error in %s_%s_ExtrapInterp: t(1) must not equal t(2) to avoid a division-by-zero error.'\n",ModName->nickname,typnm) ; +fprintf(fp," RETURN\n") ; +fprintf(fp," END IF\n") ; + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, make_lower_temp(typnmlong) )) { + for ( r = q->fields ; r ; r = r->next ) + { + // recursive + gen_extint_order( fp, ModName, typnm, uy, 1, r, "", 0 ) ; + } + } + } + } + fprintf(fp," ELSE IF ( order .eq. 2 ) THEN\n") ; +fprintf(fp," IF ( EqualRealNos( t(1), t(2) ) ) THEN\n") ; +fprintf(fp," ErrStat = ErrID_Fatal\n") ; +fprintf(fp," ErrMsg = ' Error in %s_%s_ExtrapInterp: t(1) must not equal t(2) to avoid a division-by-zero error.'\n",ModName->nickname,typnm) ; +fprintf(fp," RETURN\n") ; +fprintf(fp," END IF\n") ; +fprintf(fp," IF ( EqualRealNos( t(2), t(3) ) ) THEN\n") ; +fprintf(fp," ErrStat = ErrID_Fatal\n") ; +fprintf(fp," ErrMsg = ' Error in %s_%s_ExtrapInterp: t(2) must not equal t(3) to avoid a division-by-zero error.'\n",ModName->nickname,typnm) ; +fprintf(fp," RETURN\n") ; +fprintf(fp," END IF\n") ; +fprintf(fp," IF ( EqualRealNos( t(1), t(3) ) ) THEN\n") ; +fprintf(fp," ErrStat = ErrID_Fatal\n") ; +fprintf(fp," ErrMsg = ' Error in %s_%s_ExtrapInterp: t(1) must not equal t(3) to avoid a division-by-zero error.'\n",ModName->nickname,typnm) ; +fprintf(fp," RETURN\n") ; +fprintf(fp," END IF\n") ; + + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, make_lower_temp(typnmlong) )) { + for ( r = q->fields ; r ; r = r->next ) + { + // recursive + gen_extint_order( fp, ModName, typnm, uy, 2, r, "", 0 ) ; + } + } + } + } + fprintf(fp," ELSE \n") ; + fprintf(fp," ErrStat = ErrID_Fatal\n") ; + fprintf(fp," ErrMsg = ' order must be less than 3 in %s_%s_ExtrapInterp '\n",ModName->nickname,typnm) ; + fprintf(fp," RETURN\n") ; + fprintf(fp," ENDIF \n") ; + + + fprintf(fp," END SUBROUTINE %s_%s_ExtrapInterp\n",ModName->nickname,typnm) ; + fprintf(fp,"\n") ; +} +#endif + +void +gen_ExtrapInterp1(FILE *fp, const node_t * ModName, char * typnm, char * typnmlong, char * xtypnm, char * uy, const int max_ndims, const int max_nrecurs, const int max_alloc_ndims, const node_t *q) +{ + node_t *r; + int i, j; + + fprintf(fp, "\n"); + fprintf(fp, " SUBROUTINE %s_%s_ExtrapInterp1(%s1, %s2, tin, %s_out, tin_out, ErrStat, ErrMsg )\n", ModName->nickname, typnm, uy, uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "! This subroutine calculates a extrapolated (or interpolated) %s %s_out at time t_out, from previous/future time\n", typnm, uy); + fprintf(fp, "! values of %s (which has values associated with times in t). Order of the interpolation is 1.\n", uy); + fprintf(fp, "!\n"); + fprintf(fp, "! f(t) = a + b * t, or\n"); + fprintf(fp, "!\n"); + fprintf(fp, "! where a and b are determined as the solution to\n"); + fprintf(fp, "! f(t1) = %s1, f(t2) = %s2\n", uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "!..................................................................................................................................\n"); + fprintf(fp, "\n"); + + + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s1 ! %s at t1 > t2\n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s2 ! %s at t2 \n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: tin(2) ! Times associated with the %ss\n", xtypnm, typnm); + fprintf(fp, " TYPE(%s_%s), INTENT(INOUT) :: %s_out ! %s at tin_out\n", ModName->nickname, typnmlong, uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to\n", xtypnm); + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation\n"); + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None\n"); + fprintf(fp, " ! local variables\n"); + fprintf(fp, " REAL(%s) :: t(2) ! Times associated with the %ss\n", xtypnm, typnm); + fprintf(fp, " REAL(%s) :: t_out ! Time to which to be extrap/interpd\n", xtypnm); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_%s_ExtrapInterp1'\n", ModName->nickname, typnm); + + + fprintf(fp, " REAL(DbKi) :: b ! temporary for extrapolation/interpolation\n"); + fprintf(fp, " REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation\n"); + fprintf(fp, " INTEGER(IntKi) :: ErrStat2 ! local errors\n"); + fprintf(fp, " CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors\n"); + for (j = 1; j <= max_ndims; j++) { + for (i = 0; i <= max_nrecurs; i++) { + fprintf(fp, " INTEGER :: i%d%d ! dim%d level %d counter variable for arrays of ddts\n", i, j, j, i); + } + } + for (j = 1; j <= max_ndims; j++) { + fprintf(fp, " INTEGER :: i%d ! dim%d counter variable for arrays\n", j, j); + } + + fprintf(fp, " ! Initialize ErrStat\n"); + fprintf(fp, " ErrStat = ErrID_None\n"); + fprintf(fp, " ErrMsg = \"\"\n"); + fprintf(fp, " ! we'll subtract a constant from the times to resolve some \n"); + fprintf(fp, " ! numerical issues when t gets large (and to simplify the equations)\n"); + fprintf(fp, " t = tin - tin(1)\n"); + fprintf(fp, " t_out = tin_out - tin(1)\n"); + fprintf(fp, "\n"); + + fprintf(fp, " IF ( EqualRealNos( t(1), t(2) ) ) THEN\n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n\n"); + + fprintf(fp, " ScaleFactor = t_out / t(2)\n"); + + for (r = q->fields; r; r = r->next) + { + // recursive + gen_extint_order(fp, ModName, typnm, uy, 1, r, "", 0); + } + + + fprintf(fp, " END SUBROUTINE %s_%s_ExtrapInterp1\n", ModName->nickname, typnm); + fprintf(fp, "\n"); +} + +void +gen_ExtrapInterp2(FILE *fp, const node_t * ModName, char * typnm, char * typnmlong, char * xtypnm, char * uy, const int max_ndims, const int max_nrecurs, const int max_alloc_ndims, const node_t *q) +{ + node_t *r; + int i, j; + + fprintf(fp, "\n"); + fprintf(fp, " SUBROUTINE %s_%s_ExtrapInterp2(%s1, %s2, %s3, tin, %s_out, tin_out, ErrStat, ErrMsg )\n", ModName->nickname, typnm, uy, uy, uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "! This subroutine calculates a extrapolated (or interpolated) %s %s_out at time t_out, from previous/future time\n", typnm, uy); + fprintf(fp, "! values of %s (which has values associated with times in t). Order of the interpolation is 2.\n", uy); + fprintf(fp, "!\n"); + fprintf(fp, "! expressions below based on either\n"); + fprintf(fp, "!\n"); + fprintf(fp, "! f(t) = a + b * t + c * t**2\n"); + fprintf(fp, "!\n"); + fprintf(fp, "! where a, b and c are determined as the solution to\n"); + fprintf(fp, "! f(t1) = %s1, f(t2) = %s2, f(t3) = %s3\n", uy, uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "!..................................................................................................................................\n"); + fprintf(fp, "\n"); + + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s1 ! %s at t1 > t2 > t3\n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s2 ! %s at t2 > t3\n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s3 ! %s at t3\n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: tin(3) ! Times associated with the %ss\n", xtypnm, typnm); + fprintf(fp, " TYPE(%s_%s), INTENT(INOUT) :: %s_out ! %s at tin_out\n", ModName->nickname, typnmlong, uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to\n", xtypnm); + + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation\n" ); + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None\n"); + fprintf(fp, " ! local variables\n"); + fprintf(fp, " REAL(%s) :: t(3) ! Times associated with the %ss\n", xtypnm, typnm); + fprintf(fp, " REAL(%s) :: t_out ! Time to which to be extrap/interpd\n", xtypnm); + fprintf(fp, " INTEGER(IntKi) :: order ! order of polynomial fit (max 2)\n"); + + fprintf(fp, " REAL(DbKi) :: b ! temporary for extrapolation/interpolation\n"); + fprintf(fp, " REAL(DbKi) :: c ! temporary for extrapolation/interpolation\n"); + fprintf(fp, " REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation\n"); + fprintf(fp, " INTEGER(IntKi) :: ErrStat2 ! local errors\n"); + fprintf(fp, " CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors\n"); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_%s_ExtrapInterp2'\n", ModName->nickname, typnm); + for (j = 1; j <= max_ndims; j++) { + for (i = 0; i <= max_nrecurs; i++) { + fprintf(fp, " INTEGER :: i%d%d ! dim%d level %d counter variable for arrays of ddts\n", i, j, j, i); + } + } + for (j = 1; j <= max_ndims; j++) { + fprintf(fp, " INTEGER :: i%d ! dim%d counter variable for arrays\n", j, j); + } + fprintf(fp, " ! Initialize ErrStat\n"); + fprintf(fp, " ErrStat = ErrID_None\n"); + fprintf(fp, " ErrMsg = \"\"\n"); + fprintf(fp, " ! we'll subtract a constant from the times to resolve some \n"); + fprintf(fp, " ! numerical issues when t gets large (and to simplify the equations)\n"); + fprintf(fp, " t = tin - tin(1)\n"); + fprintf(fp, " t_out = tin_out - tin(1)\n"); + fprintf(fp, "\n"); + + + fprintf(fp, " IF ( EqualRealNos( t(1), t(2) ) ) THEN\n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN\n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN\n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " RETURN\n"); + fprintf(fp, " END IF\n\n"); + + fprintf(fp, " ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3)))\n"); + + + + for (r = q->fields; r; r = r->next) + { + // recursive + gen_extint_order(fp, ModName, typnm, uy, 2, r, "", 0); + } + + + fprintf(fp, " END SUBROUTINE %s_%s_ExtrapInterp2\n", ModName->nickname, typnm); + fprintf(fp, "\n"); +} + + +void +gen_ExtrapInterp(FILE *fp, const node_t * ModName, char * typnm, char * typnmlong, char * xtypnm) +{ + char nonick[NAMELEN]; + char *ddtname; char uy[2]; + node_t *q, *r; + int max_ndims, max_nrecurs, max_alloc_ndims; + + if (!strcmp(make_lower_temp(typnm), "output")){ + strcpy(uy, "y"); + } + else{ + strcpy(uy, "u"); + } + + for (q = ModName->module_ddt_list; q; q = q->next) + { + if (q->usefrom == 0) { + ddtname = q->name; + remove_nickname(ModName->nickname, ddtname, nonick); + if (!strcmp(nonick, make_lower_temp(typnmlong))) { + + fprintf(fp, "\n"); + fprintf(fp, " SUBROUTINE %s_%s_ExtrapInterp(%s, t, %s_out, t_out, ErrStat, ErrMsg )\n", ModName->nickname, typnm, uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "! This subroutine calculates a extrapolated (or interpolated) %s %s_out at time t_out, from previous/future time\n", typnm, uy); + fprintf(fp, "! values of %s (which has values associated with times in t). Order of the interpolation is given by the size of %s\n", uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "! expressions below based on either\n"); + fprintf(fp, "!\n"); + fprintf(fp, "! f(t) = a\n"); + fprintf(fp, "! f(t) = a + b * t, or\n"); + fprintf(fp, "! f(t) = a + b * t + c * t**2\n"); + fprintf(fp, "!\n"); + fprintf(fp, "! where a, b and c are determined as the solution to\n"); + fprintf(fp, "! f(t1) = %s1, f(t2) = %s2, f(t3) = %s3 (as appropriate)\n", uy, uy, uy); + fprintf(fp, "!\n"); + fprintf(fp, "!..................................................................................................................................\n"); + fprintf(fp, "\n"); + + + fprintf(fp, " TYPE(%s_%s), INTENT(%s) :: %s(:) ! %s at t1 > t2 > t3\n", ModName->nickname, typnmlong, (q->containsPtr == 1) ? "INOUT" : "IN", uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: t(:) ! Times associated with the %ss\n", xtypnm, typnm); + //jm Modified from INTENT( OUT) to INTENT(INOUT) to prevent ALLOCATABLE array arguments in the DDT + //jm from being maliciously deallocated through the call.See Sec. 5.1.2.7 of bonehead Fortran 2003 standard + fprintf(fp, " TYPE(%s_%s), INTENT(INOUT) :: %s_out ! %s at tin_out\n", ModName->nickname, typnmlong, uy, typnm); + fprintf(fp, " REAL(%s), INTENT(IN ) :: t_out ! time to be extrap/interp'd to\n", xtypnm); + fprintf(fp, " INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation\n"); + fprintf(fp, " CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None\n"); + fprintf(fp, " ! local variables\n"); + fprintf(fp, " INTEGER(IntKi) :: order ! order of polynomial fit (max 2)\n"); + fprintf(fp, " INTEGER(IntKi) :: ErrStat2 ! local errors\n"); + fprintf(fp, " CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors\n"); + fprintf(fp, " CHARACTER(*), PARAMETER :: RoutineName = '%s_%s_ExtrapInterp'\n", ModName->nickname, typnm); + fprintf(fp, " ! Initialize ErrStat\n"); + fprintf(fp, " ErrStat = ErrID_None\n"); + fprintf(fp, " ErrMsg = \"\"\n"); + fprintf(fp, " if ( size(t) .ne. size(%s)) then\n", uy); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(%s)',ErrStat,ErrMsg,RoutineName)\n",uy); + fprintf(fp, " RETURN\n"); + fprintf(fp, " endif\n"); + + fprintf(fp, " order = SIZE(%s) - 1\n", uy); + + fprintf(fp, " IF ( order .eq. 0 ) THEN\n"); + fprintf(fp, " CALL %s_Copy%s(%s(1), %s_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 )\n", ModName->nickname, typnm, uy, uy); + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " ELSE IF ( order .eq. 1 ) THEN\n"); + fprintf(fp, " CALL %s_%s_ExtrapInterp1(%s(1), %s(2), t, %s_out, t_out, ErrStat2, ErrMsg2 )\n", ModName->nickname, typnm, uy, uy, uy); + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " ELSE IF ( order .eq. 2 ) THEN\n"); + fprintf(fp, " CALL %s_%s_ExtrapInterp2(%s(1), %s(2), %s(3), t, %s_out, t_out, ErrStat2, ErrMsg2 )\n", ModName->nickname, typnm, uy, uy, uy, uy); + fprintf(fp, " CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)\n"); + fprintf(fp, " ELSE \n"); + fprintf(fp, " CALL SetErrStat(ErrID_Fatal,'size(%s) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName)\n", uy); + fprintf(fp, " RETURN\n"); + fprintf(fp, " ENDIF \n"); + + fprintf(fp, " END SUBROUTINE %s_%s_ExtrapInterp\n", ModName->nickname, typnm); + fprintf(fp, "\n"); + + + max_ndims = 0; // ModName->module_ddt_list->max_ndims; //bjj: this is max for module, not for typnmlong + max_nrecurs = 0; // MAXRECURSE; + max_alloc_ndims = 0; + + for (r = q->fields; r; r = r->next) + { + // recursive + calc_extint_order(fp, ModName, r, 0, &max_ndims, &max_nrecurs, &max_alloc_ndims); + } + + gen_ExtrapInterp1(fp, ModName, typnm, typnmlong, xtypnm, uy, max_ndims, max_nrecurs, max_alloc_ndims, q); + gen_ExtrapInterp2(fp, ModName, typnm, typnmlong, xtypnm, uy, max_ndims, max_nrecurs, max_alloc_ndims, q); + + } + } + } + + + +} + + + + + + + +void +gen_rk4( FILE *fp , const node_t * ModName ) +{ + char nonick[NAMELEN] ; + char *ddtname ; + node_t *q, * r ; + int founddt, k ; + +// make sure the user has dt in their parameter types + founddt = 0 ; + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, "parametertype")) { + for ( r = q->fields ; r ; r = r->next ) + { + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp( r->type->mapsto, "REAL(SiKi)") || + !strcmp( r->type->mapsto, "REAL(R8Ki)") || + !strcmp( r->type->mapsto, "REAL(DbKi)")) + { + if ( !strcmp(make_lower_temp(r->name),"dt") ) { + founddt = 1 ; + } + } + } + } + } + } + if ( !founddt ) { + fprintf(stderr,"Registry warning: cannot generate %s_RK4. Add dt to ParameterType for this module\n", ModName->nickname) ; + return ; + } + + + fprintf(fp," SUBROUTINE %s_RK4(t, u, u_next, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg )\n", + ModName->nickname) ; + fprintf(fp," REAL(DbKi), INTENT(IN ) :: t ! Current simulation time in seconds\n") ; + fprintf(fp," TYPE(%s_InputType), INTENT(IN ) :: u ! Inputs at t\n", ModName->nickname) ; + fprintf(fp," TYPE(%s_InputType), INTENT(IN ) :: u_next ! Inputs at t\n", ModName->nickname) ; + fprintf(fp," TYPE(%s_ParameterType), INTENT(IN ) :: p ! Parameters\n", ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType), INTENT(INOUT) :: x ! Continuous states at t on input at t + dt on output\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_DiscreteStateType), INTENT(INOUT) :: xd ! Discrete states at t\n", ModName->nickname) ; + fprintf(fp," TYPE(%s_ConstraintStateType), INTENT(IN ) :: z ! Constraint states at t (possibly a guess)\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_OtherStateType), INTENT(INOUT) :: OtherState ! Other states\n", ModName->nickname) ; + fprintf(fp, " TYPE(%s_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables\n", ModName->nickname); + fprintf(fp, " TYPE(%s_ContinuousStateType), INTENT(IN ) :: xdot ! Continuous states at t on input at t + dt on output\n", + ModName->nickname) ; + fprintf(fp," INTEGER(IntKi), INTENT( OUT) :: ErrStat\n") ; + fprintf(fp," CHARACTER(*), INTENT( OUT) :: ErrMsg\n") ; + fprintf(fp," ! Local variables\n" ) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: xdot_local ! t derivatives of continuous states\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: k1\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: k2\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: k3\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: k4\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_ContinuousStateType) :: x_tmp ! Holds temporary modification to x\n", + ModName->nickname) ; + fprintf(fp," TYPE(%s_InputType) :: u_interp\n", + ModName->nickname) ; + fprintf(fp," REAL(ReKi) :: alpha\n") ; + + fprintf(fp," ! Initialize ErrStat\n") ; + + fprintf(fp," ErrStat = ErrID_None\n") ; + fprintf(fp," ErrMsg = \"\"\n") ; + fprintf(fp," !CALL %s_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, xdot_local, ErrStat, ErrMsg )\n", + ModName->nickname) ; + fprintf(fp," alpha = 0.5\n") ; + for ( k = 1 ; k <= 4 ; k++ ) + { +// generate statements for k1 + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, "continuousstatetype")) { + for ( r = q->fields ; r ; r = r->next ) + { + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "REAL(DbKi)")) + { + fprintf(fp," k%d%%%s = p%%dt * xdot%s%%%s\n",k,r->name,(k<2)?"":"_local",r->name) ; + } + } + } + } + } +// generate statements for x_tmp + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + ddtname = q->name ; + remove_nickname(ModName->nickname,ddtname,nonick) ; + if ( !strcmp( nonick, "continuousstatetype")) { + for ( r = q->fields ; r ; r = r->next ) + { + if ( !strcmp( r->type->mapsto, "REAL(ReKi)") || + !strcmp(r->type->mapsto, "REAL(SiKi)") || + !strcmp(r->type->mapsto, "REAL(R8Ki)") || + !strcmp(r->type->mapsto, "REAL(DbKi)")) + { + if ( k < 4 ) { + fprintf(fp," x_tmp%%%s = x%%%s + %s k%d%%%s\n",r->name,r->name,(k<3)?"0.5*":"",k,r->name) ; + } else { + fprintf(fp," x%%%s = x%%%s + ( k1%%%s + 2. * k2%%%s + 2. * k3%%%s + k4%%%s ) / 6.\n",r->name,r->name,r->name,r->name,r->name,r->name) ; + } + } + } + } + } + } + + if (k == 1) fprintf(fp," CALL %s_LinearInterpInput(u, u_next, u_interp, alpha, ErrStat, ErrMsg)\n", + ModName->nickname) ; + if (k < 4 )fprintf(fp," CALL %s_CalcContStateDeriv( t+%sp%%dt, u_%s, p, x_tmp, xd, z, OtherState, m, xdot_local, ErrStat, ErrMsg )\n", + ModName->nickname, + (k<3)?"0.5*":"", + (k<3)?"interp":"next") ; + fprintf(fp,"\n") ; + } + fprintf(fp," END SUBROUTINE %s_RK4\n",ModName->nickname) ; + + +} + + +void +gen_module( FILE * fp , node_t * ModName, char * prog_ver ) +{ + node_t * p, * q, * r ; + int i ; + int ipass ; + char nonick[NAMELEN] ; + char tmp[NAMELEN] ; + char ** p1; + + if ( strlen(ModName->nickname) > 0 ) { +// gen preamble + { + fprintf( fp, "! %s\n", prog_ver ); + + for ( p1 = FAST_preamble ; *p1 ; p1++ ) { fprintf( fp, *p1, ModName->name ) ; } + } + for ( p = ModNames ; p ; p = p->next ) + { + // Add use declarations for Modules that are included as "usefrom" + if ( p->usefrom ) { + if ( strcmp(make_lower_temp(p->name),"nwtc_library") ) { + fprintf(fp,"USE %s_Types\n",p->name) ; + } + } + } + if ( sw_ccode ) { +// Generate a container object for the Fortran code to carry around a pointer to the CPP object(s) + //fprintf(fp,"USE %s_C_Types\n",ModName->nickname) ; + fprintf(fp,"!USE, INTRINSIC :: ISO_C_Binding\n") ; // this is inherited from NWTC_Library.f90, and older versions of gfortran complain about ambiguous data when we use this (it thinks it's declared twice; see http://gcc.gnu.org/ml/fortran/2013-04/msg00166.html ) + } + +// if this is the NWTC Library, we're not going to print "USE NWTC_Library" + if ( strcmp(make_lower_temp(ModName->name),"nwtc_library") == 0 ) { + fprintf(fp,"USE SysSubs\n"); + } else { + fprintf(fp,"USE NWTC_Library\n"); + } + + fprintf(fp,"IMPLICIT NONE\n") ; + +#if 0 + if ( sw_ccode ) { + fprintf(fp," TYPE MAP_In_C \n") ; + fprintf(fp," ! This allows us to create an instance of a C++ \n") ; + fprintf(fp," ! object in Fortran. From the perspective of \n") ; + fprintf(fp," ! Fortran, this is seen as an address in memory\n") ; + fprintf(fp," PRIVATE\n") ; + fprintf(fp," TYPE(C_ptr) :: %s_UserData = C_NULL_ptr\n",ModName->nickname) ; + fprintf(fp," END TYPE MAP_In_C \n") ; + } +#endif + +// generate parameters + for ( q = ModName->params ; q ; q = q->next ) + { + fprintf(fp," %s, PUBLIC, PARAMETER ",q->type->mapsto ) ; + if ( q->ndims > 0 ) + { + if ( q->dims[0]->deferred ) + { + fprintf(stderr,"Registry warning: parameter %s can not have deferred type\n",q->name) ; + fprintf(fp,"), ALLOCATABLE ") ; + } else { + fprintf(fp,", DIMENSION(") ; + for ( i = 0 ; i < q->ndims ; i++ ) + { + fprintf(fp,"%d:%d",q->dims[i]->coord_start,q->dims[i]->coord_end) ; + if ( i < q->ndims-1 ) fprintf(fp,",") ; + } + fprintf(fp,") ") ; + } + } + if ( strlen(q->inival) > 0 ) { + if ( q->ndims > 0 ) { + fprintf(fp," :: %s = (/%s/)", q->name, q->inival ) ; + } else { + fprintf(fp," :: %s = %s ", q->name, q->inival ) ; + } + } else { + fprintf(fp," :: %s",q->name) ; + } + if ( strcmp( q->descrip, "-" ) || strcmp( q->units, "-" ) ) /* that is, if not equal "-" */ { + fprintf(fp," ! %s [%s]", q->descrip, q->units) ; + } + fprintf(fp,"\n") ; + } + +// generate each derived data type + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if (*q->mapsto) remove_nickname( ModName->nickname, make_lower_temp(q->mapsto) , nonick ) ; + fprintf(fp, "! ========= %s%s =======\n", q->mapsto, (sw_ccode) ? "_C" : ""); + for ( ipass = (sw_ccode)?0:1 ; ipass < 2 ; ipass++ ) { // 2 passes for C code, 1st pass generates bound ddt + if ( q->usefrom == 0 ) { + fprintf(fp," TYPE, %s :: %s%s\n",(ipass==0)?"BIND(C)":"PUBLIC",q->mapsto,(ipass==0)?"_C":"") ; + if ( sw_ccode ) { + if ( ipass == 0 ) { +// q->containsPtr = 1; + //if (!strcmp(make_lower_temp(nonick), "otherstatetype") || !strcmp(make_lower_temp(nonick), "initinputtype")){ + fprintf(fp, " TYPE(C_PTR) :: object = C_NULL_PTR\n"); + //} + } else { + fprintf(fp," TYPE( %s_C ) :: C_obj\n",q->mapsto) ; + } + } + for ( r = q->fields ; r ; r = r->next ) + { + if ( r->type != NULL ) { + // check max number of dimmensions + // check if this type contains any pointers/meshes or types that have pointers/meshes + if (r->ndims > q->max_ndims) q->max_ndims = r->ndims; + if (r->ndims > ModName->module_ddt_list->max_ndims) ModName->module_ddt_list->max_ndims = r->ndims; + if ( ipass == 0 ) { + //r->containsPtr = 1; + //q->containsPtr = 1; + if ( r->ndims == 0 && r->type->type_type != DERIVED ) { + fprintf(fp," %s :: %s \n",c_types_binding( r->type->mapsto), r->name) ; + } else if ( r->ndims > 0 && r->type->type_type != DERIVED ) { + if (r->dims[0]->deferred ) { + fprintf(fp," TYPE(C_ptr) :: %s = C_NULL_PTR \n", r->name) ; + fprintf(fp," INTEGER(C_int) :: %s_Len = 0 \n", r->name) ; + } + else { + if (strcmp(C_type(r->type->mapsto), "char")){ + fprintf(fp," TYPE(C_PTR) :: %s(", r->name) ; + for ( i = 0 ; i < r->ndims ; i++ ) + { + fprintf(fp,"%d",r->dims[i]->coord_end) ; + if ( i < r->ndims-1 ) fprintf(fp,",") ; + } + fprintf(fp,")\n") ; + } + + } + } + } else { // ipass /= 0 + if ( r->type->type_type == DERIVED ) { + fprintf(fp," TYPE(%s) ",r->type->mapsto ) ; + + checkContainsMesh(r); + if (r->containsPtr) q->containsPtr = 1; + + // bjj: we need to make sure these types map to reals, too + tmp[0] = '\0' ; + if (*q->mapsto ) remove_nickname( ModName->nickname, make_lower_temp(q->mapsto) , tmp ) ; + if ( must_have_real_or_double(tmp) ) checkOnlyReals( q->mapsto, r ); + + + } else { + tmp[0] = '\0' ; + if (*q->mapsto ) remove_nickname( ModName->nickname, make_lower_temp(q->mapsto) , tmp ) ; + if ( must_have_real_or_double(tmp) ) { + if ( strncmp(r->type->mapsto,"REAL",4) ) { + fprintf(stderr,"Registry warning: %s contains a field (%s) whose type is not real or double: %s\n", + q->mapsto, r->name , r->type->mapsto ) ; + } + + } + if ( is_pointer(r) ) { + fprintf(fp," %s ",c_types_binding(r->type->mapsto) ) ; + } else { + fprintf(fp," %s ",r->type->mapsto ) ; + } + } + + if ( r->ndims > 0 ) + { + if ( r->dims[0]->deferred ) // if one dim is deferred they all have to be; see check in type.c + { + fprintf(fp,", DIMENSION(") ; + for ( i = 0 ; i < r->ndims ; i++ ) + { + fprintf(fp,":") ; + if ( i < r->ndims-1 ) fprintf(fp,",") ; + } + if ( is_pointer(r) ) { + fprintf(fp,"), POINTER ") ; + } else { + fprintf(fp,"), ALLOCATABLE ") ; + } + + } else { + fprintf(fp,", DIMENSION(") ; + for ( i = 0 ; i < r->ndims ; i++ ) + { + if (r->dims[i]->dim_param == 0){ + fprintf(fp, "%d:%d", r->dims[i]->coord_start, r->dims[i]->coord_end) ; + } + else { + //fprintf(stderr, "start, %s, %s, %s\n", dimspec, dim_entry->name, dim_entry->module); + // if (r->module != NULL) { node_t *param_dim = get_entry(r->dims[i]->dim_param_name, r->module->params); } + + fprintf(fp, "%s", r->dims[i]->dim_param_name); + } + if ( i < r->ndims-1 ) fprintf(fp,",") ; + } + fprintf(fp,") ") ; + } + } + + + if ( is_pointer( r ) ) { + fprintf(fp," :: %s => NULL() ",r->name) ; + } else if ( r->ndims == 0 && strlen(r->inival) > 0 ) { + fprintf(fp," :: %s = %s ", r->name, r->inival ) ; + } else { + fprintf(fp," :: %s ",r->name) ; + } + + if ( strcmp( r->descrip, "-" ) || strcmp( r->units, "-" ) ) /* that is, if not equal "-" */ { + fprintf(fp," !< %s [%s]", r->descrip, r->units) ; + } + fprintf(fp,"\n") ; + } // ipass /= 0 + } + } + fprintf(fp," END TYPE %s%s\n",q->mapsto,(ipass==0)?"_C":"") ; + //fprintf(stderr, "module %d type %d\n", ModName->module_ddt_list->max_ndims, q->max_ndims); + + } + } + fprintf(fp,"! =======================\n") ; + } + + if ( sw_ccode ) { + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + + if ( q->usefrom == 0 ) { + + char * ddtname, * ddtnamelong, nonick[NAMELEN] ; + ddtname = q->name ; + + remove_nickname(ModName->nickname,ddtname,nonick) ; + + if ( is_a_fast_interface_type( nonick ) ) { + ddtnamelong = nonick ; + ddtname = fast_interface_type_shortname( nonick ) ; + } else { + ddtnamelong = ddtname ; + } + + } + } + } // sw_ccode + + + fprintf(fp,"CONTAINS\n") ; + for ( q = ModName->module_ddt_list ; q ; q = q->next ) + { + if ( q->usefrom == 0 ) { + + char * ddtname, * ddtnamelong, nonick[NAMELEN] ; + //ddtname = q->name ; + ddtname = q->mapsto; + + remove_nickname(ModName->nickname,ddtname,nonick) ; + +//fprintf(stderr,">> %s %s %s \n",ModName->name, ddtname, nonick) ; + + if ( is_a_fast_interface_type( nonick ) ) { + ddtnamelong = nonick ; + ddtname = fast_interface_type_shortname( nonick ) ; + } else { + ddtnamelong = ddtname ; + } + + gen_copy( fp, ModName, ddtname, ddtnamelong , q) ; + gen_destroy( fp, ModName, ddtname, ddtnamelong ) ; + gen_pack( fp, ModName, ddtname, ddtnamelong ) ; + gen_unpack( fp, ModName, ddtname, ddtnamelong ) ; + if ( sw_ccode ) { + gen_copy_c2f( fp, ModName, ddtname, ddtnamelong ) ; + gen_copy_f2c(fp, ModName, ddtname, ddtnamelong); + } + + } + } +// bjj: removed gen_modname_pack and gen_modname_unpack because i don't see them being used any differently than the other pack/unpack routines 02/22/2014 +// gen_modname_pack( fp, ModName ) ; +// gen_modname_unpack( fp, ModName ) ; +// gen_rk4( fp, ModName ) ; + + if (strcmp(make_lower_temp(ModName->name), "airfoilinfo") == 0) { // make interpolation routines for AirfoilInfo module + gen_ExtrapInterp(fp, ModName, "Output", "OutputType","ReKi"); + gen_ExtrapInterp(fp, ModName, "UA_BL_Type", "UA_BL_Type", "ReKi"); + } else if (!sw_noextrap) { + if (strcmp(make_lower_temp(ModName->name), "dbemt") == 0) { // make interpolation routines for element-level DBEMT module + + gen_ExtrapInterp(fp, ModName, "ElementInputType", "ElementInputType", "DbKi"); + } + + gen_ExtrapInterp(fp, ModName, "Input", "InputType", "DbKi"); + gen_ExtrapInterp(fp, ModName, "Output", "OutputType", "DbKi"); + } + + fprintf(fp,"END MODULE %s_Types\n",ModName->name ) ; + } + +} + + +int +gen_module_files ( char * dirname, char * prog_ver ) +{ + FILE * fp, *fph ; + char fname[NAMELEN], fname2[NAMELEN] ; + + node_t * p ; + + for ( p = ModNames ; p ; p = p->next ) + { + if ( strlen( p->nickname ) > 0 && ! p->usefrom ) { + fp = NULL ; + + if ( strlen(dirname) > 0 ) + { sprintf(fname,"%s/%s_Types.f90",dirname,p->name) ; } + else + { sprintf(fname,"%s_Types.f90",p->name) ; } + sprintf(fname2, "%s_Types.f90", p->name); + + fprintf(stderr,"generating %s\n",fname) ; + + if ((fp = fopen( fname , "w" )) == NULL ) return(1) ; + print_warning(fp,fname2, ""); + + if ( sw_ccode == 1 ) { + + + if ( strlen(dirname) > 0 ) + { sprintf(fname,"%s/%s_Types.h",dirname,p->name) ; } + else + { sprintf(fname, "%s_Types.h",p->name) ;} + sprintf(fname2,"%s_Types.h",p->name) ; + if ((fph = fopen( fname , "w" )) == NULL ) return(1) ; + + + print_warning(fph,fname2, "//") ; + + fprintf(fph,"\n#ifndef _%s_TYPES_H\n",p->name); + fprintf(fph,"#define _%s_TYPES_H\n\n",p->name); + fprintf(fph,"\n#ifdef _WIN32 //define something for Windows (32-bit)\n"); + fprintf(fph,"# include \"stdbool.h\"\n"); + fprintf(fph,"# define CALL __declspec( dllexport )\n"); + fprintf(fph,"#elif _WIN64 //define something for Windows (64-bit)\n"); + fprintf(fph,"# include \"stdbool.h\"\n"); + fprintf(fph,"# define CALL __declspec( dllexport ) \n"); + fprintf(fph,"#else\n"); + fprintf(fph,"# include <stdbool.h>\n"); + fprintf(fph,"# define CALL \n"); + fprintf(fph,"#endif\n\n\n"); + } + gen_module ( fp , p, prog_ver ) ; + close_the_file( fp, "" ) ; + if ( sw_ccode ) { + gen_c_module ( fph , p ) ; + + fprintf(fph,"\n#endif // _%s_TYPES_H\n\n\n",p->name); + close_the_file( fph,"//") ; + + } + } + } + return(0) ; +} + +void +remove_nickname( const char *nickname, char *src, char *dst ) +{ + char tmp[NAMELEN]; + char srclo[NAMELEN]; + int n; + strcpy(tmp,make_lower_temp(nickname)) ; + strcpy(srclo, make_lower_temp(src)); + strcat(tmp,"_") ; + n = strlen(tmp) ; + if (!strncmp(tmp, srclo, n)) { + strcpy(dst,&(src[n])) ; + } else { + strcpy(dst,src) ; + } +} + +void +append_nickname( const char *nickname, char *src, char *dst ) +{ + int n ; + n = strlen(nickname) ; + if ( n > 0 ) { + sprintf(dst,"%s_%s",nickname,src) ; + } else { + strcpy(dst,src) ; + } +} + +char * dimstr( int d ) +{ + char * retval ; + if ( d == 0 ) { + retval = "" ; + } else if ( d == 1 ) { + retval = "(i1)" ; + } else if ( d == 2 ) { + retval = "(i1,i2)" ; + } else if ( d == 3 ) { + retval = "(i1,i2,i3)" ; + } else if ( d == 4 ) { + retval = "(i1,i2,i3,i4)" ; + } else if ( d == 5 ) { + retval = "(i1,i2,i3,i4,i5)" ; + } else { + retval = " REGISTRY ERROR TOO MANY DIMS " ; + } + return(retval) ; + + //strcpy(dex, ""); + //strcat(dex, "("); + //for (j = 1; j <= d; j++) { + // sprintf(tmp, "i%d%d", 0, j); + // strcat(dex, tmp); + // if (j == d) strcat(dex, ")"); else strcat(dex, ","); + //} + +} + +char * dimstr_c( int d ) +{ + char * retval ; + if ( d == 0 ) { + retval = "" ; + } else if ( d == 1 ) { + retval = "[i1]" ; + } else if ( d == 2 ) { + retval = "[i2][i1]" ; + } else if ( d == 3 ) { + retval = "[i3][i2][i1]" ; + } else if ( d == 4 ) { + retval = "[i4][i3][i2][i1]" ; + } else if ( d == 5 ) { + retval = "[i5][i4][i3][i2][i1]" ; + } else { + retval = " REGISTRY ERROR TOO MANY DIMS " ; + } + return(retval) ; +} + +void +checkOnlyReals( const char *q_mapsto, node_t * q) //, int recurselevel) +{ + node_t * r ; + + if ( q->type->type_type == DERIVED ) + { + if ( strcmp( q->type->name, "meshtype" ) ) // skip meshes + { + for ( r = q->type->fields ; r ; r = r->next ) + { + checkOnlyReals( q_mapsto, r); + } + } + + } else { // SIMPLE + + if ( strncmp(q->type->mapsto,"REAL",4) ) + { + fprintf(stderr,"Registry warning: %s contains a field (%s) in a derived type whose type is not real or double: %s\n", + q_mapsto, q->name , q->type->mapsto ) ; + } + + } + return; +} + +void +checkContainsMesh( node_t * q) //, int recurselevel) +{ + node_t * r; + + if (q->type->type_type == DERIVED) + { + if (!strcmp(q->type->name, "meshtype") || !strcmp(q->type->name, "meshmaptype")){ // is a mesh or (a bad workaround for meshmaptype which contains meshtype in "usefrom" instead of "typedef") + q->containsPtr = 1; + } + + else { + for (r = q->type->fields; r; r = r->next) + { + checkContainsMesh(r); + if (r->containsPtr) q->containsPtr = 1; + } + } + + } + + return; +} diff --git a/OpenFAST/modules/openfast-registry/src/misc.c b/OpenFAST/modules/openfast-registry/src/misc.c new file mode 100644 index 000000000..628aa05bc --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/misc.c @@ -0,0 +1,710 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#ifdef _WIN32 +# define rindex(X,Y) strrchr(X,Y) +# define index(X,Y) strchr(X,Y) +# include <process.h> +# define getpid _getpid +#else +# include <strings.h> +# include <sys/types.h> +# include <unistd.h> +#endif + +#include "protos.h" +#include "registry.h" +#include "data.h" + +char * +dimension_with_colons( char * pre , char * tmp , node_t * p , char * post ) +{ + int i ; + if ( p == NULL ) return("") ; + if ( p->ndims <= 0 && ! p->boundary_array ) return("") ; + strcpy(tmp,"") ; + if ( pre != NULL ) strcat(tmp,pre) ; + if ( p->boundary_array ) + { + if ( ! sw_new_bdys ) { strcat( tmp,":,") ; } + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { + strcat( tmp, ":,:,:,:" ) ; /* boundary array for 4d tracer array */ + } else { + strcat( tmp, ":,:,:" ) ; /* most always have four dimensions */ + } + } + else + { + for ( i = 0 ; i < p->ndims ; i++ ) strcat(tmp,":,") ; + if ( p->node_kind & FOURD ) strcat(tmp,":,") ; /* add an extra for 4d arrays */ + tmp[strlen(tmp)-1] = '\0' ; + } + if ( post != NULL ) strcat(tmp,post) ; + return(tmp) ; +} + +char * +dimension_with_ones( char * pre , char * tmp , node_t * p , char * post ) +{ + int i ; + char r[NAMELEN],s[NAMELEN],four_d[NAMELEN] ; + char *pp ; + if ( p == NULL ) return("") ; + if ( p->ndims <= 0 && ! p->boundary_array ) return("") ; + strcpy(tmp,"") ; + if ( pre != NULL ) strcat(tmp,pre) ; + + if ( p->boundary_array ) + { + if ( ! sw_new_bdys ) { strcpy( tmp,"(1,") ; } + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { /* if a boundary array for a 4d tracer */ + strcpy(s, p->name ) ; /* copy the name and then remove everything after last underscore */ + if ((pp=rindex( s, '_' )) != NULL ) *pp = '\0' ; + sprintf( four_d, "num_%s,", s ) ; + } else { + strcpy( four_d, "" ) ; + } + + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { + sprintf( r, "1,1,1,%s", four_d ) ; /* boundary array for 4d tracer array */ + strcat( tmp, r ) ; + } else { + strcat( tmp, "1,1,1," ) ; + } + tmp[strlen(tmp)-1] = '\0' ; + } + else + { + for ( i = 0 ; i < p->ndims ; i++ ) strcat(tmp,"1,") ; + if ( p->node_kind & FOURD ) strcat(tmp,"1,") ; /* add an extra for 4d arrays */ + tmp[strlen(tmp)-1] = '\0' ; + } + if ( post != NULL ) strcat(tmp,post) ; + return(tmp) ; +} + +char * +dimension_with_ranges( char * refarg , char * pre , + int bdy , /* as defined in data.h */ + char * tmp , node_t * p , char * post , + char * nlstructname ) /* added 20020130; + provides name (with %) of structure in + which a namelist supplied dimension + should be dereference from, or "" */ +{ + int i ; + char tx[NAMELEN] ; + char r[NAMELEN],s[NAMELEN],four_d[NAMELEN] ; + int bdex, xdex, ydex, zdex ; + node_t *xdim, *ydim, *zdim ; + char *pp ; + if ( p == NULL ) return("") ; + if ( p->ndims <= 0 && !p->boundary_array ) return("") ; + strcpy(tmp,"") ; + if ( pre != NULL ) strcat(tmp,pre) ; + strcpy(r,"") ; + if ( refarg != NULL ) strcat(r,refarg) ; + + if ( p->boundary_array ) + { + if ( p->ndims > 0 ) + { + xdim = get_dimnode_for_coord( p , COORD_X ) ; + ydim = get_dimnode_for_coord( p , COORD_Y ) ; + zdim = get_dimnode_for_coord( p , COORD_Z ) ; + if ( ydim == NULL ) + { fprintf(stderr,"dimension_with_ranges: y dimension not specified for %s\n",p->name) ; return("") ; } + if ( xdim == NULL ) + { fprintf(stderr,"dimension_with_ranges: x dimension not specified for %s\n",p->name) ; return("") ; } + + xdex = xdim->dim_order ; + ydex = ydim->dim_order ; + + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { /* if a boundary array for a 4d tracer */ + strcpy(s, p->name ) ; /* copy the name and then remove everything after last underscore */ + if ((pp=rindex( s, '_' )) != NULL ) *pp = '\0' ; + sprintf( four_d, "num_%s,", s ) ; + } else { + strcpy( four_d, "" ) ; + } + if ( sw_new_bdys ) { + if ( bdy == P_XSB || bdy == P_XEB ) { bdex = ydex ; } + else if ( bdy == P_YSB || bdy == P_YEB ) { bdex = xdex ; } + else { fprintf(stderr,"REGISTRY WARNING: internal error %s %d, bdy=%d,%s,%d \n",__FILE__,__LINE__,bdy,p->name,p->boundary) ; } + if ( zdim != NULL ) { + zdex = zdim->dim_order ; + sprintf(tx,"%ssm3%d:%sem3%d,%ssm3%d:%sem3%d,%sspec_bdy_width,%s", r,bdex,r,bdex,r,zdex,r,zdex,r,four_d ) ; + } else { + sprintf(tx,"%ssm3%d:%sem3%d,1,%sspec_bdy_width,%s", r,bdex,r,bdex,r,four_d ) ; + } + } else { + if ( zdim != NULL ) { + zdex = zdim->dim_order ; + sprintf(tx,"max(%sed3%d,%sed3%d),%ssd3%d:%sed3%d,%sspec_bdy_width,4,%s", r,xdex,r,ydex,r,zdex,r,zdex,r,four_d ) ; + } else { + sprintf(tx,"max(%sed3%d,%sed3%d),1,%sspec_bdy_width,4,%s", r,xdex,r,ydex,r,four_d ) ; + } + } + } + else + { + sprintf(tx,"%sspec_bdy_width,",r ) ; + } + strcat(tmp,tx) ; + } + else + { + for ( i = 0 ; i < p->ndims ; i++ ) + { + range_of_dimension( r, tx , i , p , nlstructname ) ; + strcat(tmp,tx) ; + strcat(tmp,",") ; + } + } + tmp[strlen(tmp)-1] = '\0' ; + if ( post != NULL ) strcat(tmp,post) ; + + return(tmp) ; +} + +void +range_of_dimension ( char * r , char * tx , int i , node_t * p , char * nlstructname ) +{ + char s[NAMELEN], e[NAMELEN] ; + + get_elem( r , nlstructname , s , i , p , 0 ) ; + get_elem( r , nlstructname , e , i , p , 1 ) ; + sprintf(tx,"%s:%s", s , e ) ; + +} + +char * +index_with_firstelem( char * pre , char * dref , int bdy , /* as defined in data.h */ + char * tmp , node_t * p , char * post ) +{ + int i ; + char tx[NAMELEN] ; + int bdex, xdex, ydex, zdex = 0 ; + node_t *xdim, *ydim, *zdim ; + char r[NAMELEN] ; + + if ( p == NULL ) return("") ; + if ( p->ndims <= 0 ) return("") ; + strcpy(tmp,"") ; + if ( pre != NULL ) strcat(tmp,pre) ; + + strcpy(r,"") ; + if ( dref != NULL ) strcat(r,dref) ; + + if ( p->boundary_array ) + { + if ( sw_new_bdys ) { + + xdim = get_dimnode_for_coord( p , COORD_X ) ; + ydim = get_dimnode_for_coord( p , COORD_Y ) ; + zdim = get_dimnode_for_coord( p , COORD_Z ) ; + if ( ydim == NULL ) + { fprintf(stderr,"dimension_with_ranges: y dimension not specified for %s\n",p->name) ; return("") ; } + if ( xdim == NULL ) + { fprintf(stderr,"dimension_with_ranges: x dimension not specified for %s\n",p->name) ; return("") ; } + + xdex = xdim->dim_order ; + ydex = ydim->dim_order ; + + if ( bdy == P_XSB || bdy == P_XEB ) { bdex = ydex ; } + else if ( bdy == P_YSB || bdy == P_YEB ) { bdex = xdex ; } + else { fprintf(stderr,"REGISTRY WARNING: internal error %s %d \n",__FILE__,__LINE__) ; } + if ( p->ndims > 0 ) + { + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { + sprintf(tmp,"%ssm3%d,%ssm3%d,1,1", r,bdex,r,zdex ) ; + } else { + sprintf(tmp,"%ssm3%d,%ssm3%d,1", r,bdex,r,zdex ) ; + } + } + else + { + sprintf(tx,"1," ) ; + strcat(tmp,tx) ; + } + + } else { + if ( p->ndims > 0 ) + { + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { + strcat(tmp,"1,1,1,1,1,") ; + } else { + strcat(tmp,"1,1,1,1,") ; + } + } + else + { + sprintf(tx,"1," ) ; + strcat(tmp,tx) ; + } + } + } + else + { + for ( i = 0 ; i < p->ndims ; i++ ) + { + get_elem( dref, "", tx, i, p , 0 ) ; + strcat( tmp, tx ) ; + strcat(tmp,",") ; + } + } + tmp[strlen(tmp)-1] = '\0' ; /* remove trailing comma */ + if ( post != NULL ) strcat(tmp,post) ; + return(tmp) ; +} + +void +get_elem ( char * structname , char * nlstructname , char * tx , int i , node_t * p , int first_last ) +{ + char dref[NAMELEN], nlstruct[NAMELEN] ; + char d, d1 ; + + if ( structname == NULL ) { strcpy( dref, "" ) ;} + else { strcpy( dref, structname ) ; } + if ( nlstructname == NULL ) { strcpy( nlstruct, "" ) ;} + else { strcpy( nlstruct, nlstructname ) ; } + if ( p->dims[i] != NULL ) + { + switch ( p->dims[i]->len_defined_how ) + { + case (DOMAIN_STANDARD) : + { + char *ornt ; + if ( p->proc_orient == ALL_X_ON_PROC ) ornt = "x" ; + else if ( p->proc_orient == ALL_Y_ON_PROC ) ornt = "y" ; + else ornt = "" ; + + switch( p->dims[i]->coord_axis ) + { + case(COORD_X) : d = 'i' ; d1 = 'x' ; break ; + case(COORD_Y) : d = 'j' ; d1 = 'y' ; break ; + case(COORD_Z) : d = 'k' ; d1 = 'z' ; break ; + default : break ; + } + + if ( p->dims[i]->subgrid ) + { + if ( first_last == 0 ) { /*first*/ + sprintf(tx,"(%ssm3%d%s-1)*%ssr_%c+1",dref,p->dims[i]->dim_order,ornt,dref,d1) ; + }else{ /*last*/ + sprintf(tx,"%sem3%d%s*%ssr_%c" ,dref,p->dims[i]->dim_order,ornt,dref,d1) ; + } + } + else + { + sprintf(tx,"%s%cm3%d%s",dref,first_last==0?'s':'e',p->dims[i]->dim_order,ornt) ; + } + } + break ; + case (NAMELIST) : + if ( first_last == 0 ) { if ( !strcmp( p->dims[i]->assoc_nl_var_s , "1" ) ) { + sprintf(tx,"%s",p->dims[i]->assoc_nl_var_s) ; + } else { + sprintf(tx,"%s%s%s",nlstructname,structname,p->dims[i]->assoc_nl_var_s) ; + } + } + else { sprintf(tx,"%s%s%s",nlstructname,structname,p->dims[i]->assoc_nl_var_e) ; } + break ; + case (CONSTANT) : + if ( first_last == 0 ) { sprintf(tx,"%d",p->dims[i]->coord_start) ; } + else { sprintf(tx,"%d",p->dims[i]->coord_end) ; } + break ; + default : break ; + } + } + else + { + fprintf(stderr,"WARNING: %s %d: something wrong with internal representation for dim %d\n",__FILE__,__LINE__,i) ; + } +} + +char * +declare_array_as_pointer( char * tmp , node_t * p ) +{ + strcpy( tmp , "" ) ; + if ( p != NULL ) { +#ifdef USE_ALLOCATABLES + if ( p->ndims > 0 || p->boundary_array ) strcpy ( tmp, ",ALLOCATABLE" ) ; +#else + if ( p->ndims > 0 || p->boundary_array ) strcpy ( tmp, ",POINTER" ) ; +#endif + } + return(tmp); +} + +char * +field_type( char * tmp , node_t * p ) +{ + if ( p == NULL ) { + strcpy( tmp , "" ) ; + } else if ( p->type == NULL ) { + strcpy( tmp , "" ) ; + } else if ( p->type->type_type == SIMPLE ) { + strcpy( tmp , p->type->name ) ; + } else { + sprintf( tmp , "TYPE(%s)", p->type->name ) ; + } + return( tmp ) ; +} + +char * +field_name( char * tmp , node_t * p , int tag ) +{ + if ( p == NULL ) return("") ; + return( tmp ) ; +} + +char * +field_name_bdy( char * tmp , node_t * p , int tag, int bdy ) +{ + if ( p == NULL ) return("") ; + if ( tag < 1 ) + { + strcpy(tmp,p->name) ; + } + else + { + sprintf(tmp,"%s_%d",p->name,tag) ; + } + return( tmp ) ; +} + +static char *emp_str = "" ; +static char *xs_str = "xs" ; +static char *xe_str = "xe" ; +static char *ys_str = "ys" ; +static char *ye_str = "ye" ; + +char * +bdy_indicator( int bdy ) +{ + char * res ; + res = emp_str ; + if ( bdy == P_XSB ) { res = xs_str ; } + else if ( bdy == P_XEB ) { res = xe_str ; } + else if ( bdy == P_YSB ) { res = ys_str ; } + else if ( bdy == P_YEB ) { res = ye_str ; } + return(res) ; +} + +int +print_warning( FILE * fp , char * fname, char comment[] ) +{ +fprintf(fp,"%s!STARTOFREGISTRYGENERATEDFILE '%s'\n", comment, fname) ; +fprintf(fp,"%s!\n", comment) ; +fprintf(fp,"%s! WARNING This file is generated automatically by the FAST registry.\n", comment) ; +fprintf(fp,"%s! Do not edit. Your changes to this file will be lost.\n", comment) ; +fprintf(fp,"%s!\n", comment) ; +return(0) ; +} + +void +close_the_file( FILE * fp, char comment[] ) +{ +fprintf(fp,"%s!ENDOFREGISTRYGENERATEDFILE\n",comment) ; +fclose(fp) ; +} + +int +make_entries_uniq ( char * fname ) +{ + char tempfile[NAMELEN] ; + /* Had to increase size for SOA from 4096 to 7000 */ + char commline[7000] ; + sprintf(tempfile,"regtmp1%d",getpid()) ; + sprintf(commline,"%s < %s > %s ; %s %s %s ", + UNIQSORT,fname,tempfile, + MVCOMM,tempfile,fname ) ; + return(system(commline)) ; +} + +int +add_warning ( char * fname ) +{ + FILE * fp ; + char tempfile[NAMELEN] ; + char tempfile1[NAMELEN] ; + /* Had to increase size for SOA from 4096 to 7000 */ + char commline[7000] ; + sprintf(tempfile,"regtmp1%d",getpid()) ; + sprintf(tempfile1,"regtmp2%d",getpid()) ; + if (( fp = fopen( tempfile, "w" )) == NULL ) return(1) ; + print_warning(fp,tempfile, "") ; + close_the_file(fp, "") ; + sprintf(commline,"%s %s %s > %s ; %s %s %s ; %s %s ", + CATCOMM,tempfile,fname,tempfile1, + MVCOMM,tempfile1,fname, + RMCOMM,tempfile) ; + return(system(commline)) ; +} + +/* DESTRUCTIVE */ +char * +make_upper_case ( char * str ) +{ + char * p ; + if ( str == NULL ) return (NULL) ; + for ( p = str ; *p ; p++ ) *p = toupper(*p) ; + return(str) ; +} + +/* DESTRUCTIVE */ +char * +make_lower_case ( char * str ) +{ + char * p ; + if ( str == NULL ) return (NULL) ; + for ( p = str ; *p ; p++ ) *p = tolower(*p) ; + return(str) ; +} + +/* Routines for keeping typedef history -ajb */ + +static int NumTypeDefs ; +static char typedefs[MAX_TYPEDEFS][NAMELEN] ; + +int +init_typedef_history() +{ + NumTypeDefs = 0 ; + return(0) ; +} + +int +get_num_typedefs() +{ + return( NumTypeDefs ) ; +} + +char * +get_typename_i(int i) +{ + if ( i >= 0 && i < NumTypeDefs ) return( typedefs[i] ) ; + return(NULL) ; +} + +int +add_typedef_name ( char * name ) +{ + if ( name == NULL ) return(1) ; + if ( get_typedef_name ( name ) == NULL ) + { + if ( NumTypeDefs >= MAX_TYPEDEFS ) return(1) ; + strcpy( typedefs[NumTypeDefs++] , name ) ; + } + return(0) ; +} + +char * +get_typedef_name ( char * name ) +{ + int i ; + if ( name == NULL ) return(NULL) ; + for ( i = 0 ; i < NumTypeDefs ; i++ ) + { + if ( !strcmp(name,typedefs[i]) ) return( typedefs[i] ) ; + } + return(NULL) ; +} + +int +associated_with_4d_array( node_t * p ) +{ + int res = 0 ; + node_t * possble ; + char * last_underscore ; + char name_copy[128] ; + if ( p != NULL ) + { + /* check this variable and see if it is a boundary variable that is associated with a 4d array */ + strcpy( name_copy, p->name ) ; + if (( last_underscore = rindex( name_copy , '_' )) != NULL ) { + if ( !strcmp( last_underscore , "_b" ) || !strcmp( last_underscore , "_bt" ) ) { + *last_underscore = '\0' ; + if (( possble = get_entry( name_copy , Domain.fields )) != NULL ) { + res = possble->node_kind & FOURD ; + } + } + } + } + return(res) ; +} + +char * +array_size_expression ( char * refarg , char * pre , + int bdy , /* as defined in data.h */ + char * tmp , node_t * p , char * post , + char * nlstructname ) /* provides name (with %) of structure in + which a namelist supplied dimension + should be dereference from, or "" */ +{ + int i ; + char tx[NAMELEN] ; + char r[NAMELEN],s[NAMELEN],four_d[NAMELEN] ; + int bdex, xdex, ydex, zdex ; + node_t *xdim, *ydim, *zdim ; + char *pp ; + if ( p == NULL ) return("") ; + if ( p->ndims <= 0 && !p->boundary_array ) return("") ; + strcpy(tmp,"") ; + if ( pre != NULL ) strcat(tmp,pre) ; + strcpy(r,"") ; + if ( refarg != NULL ) strcat(r,refarg) ; + + if ( p->boundary_array ) + { + if ( p->ndims > 0 ) + { + xdim = get_dimnode_for_coord( p , COORD_X ) ; + ydim = get_dimnode_for_coord( p , COORD_Y ) ; + zdim = get_dimnode_for_coord( p , COORD_Z ) ; + if ( ydim == NULL ) + { fprintf(stderr,"dimension_with_ranges: y dimension not specified for %s\n",p->name) ; return("") ; } + if ( xdim == NULL ) + { fprintf(stderr,"dimension_with_ranges: x dimension not specified for %s\n",p->name) ; return("") ; } + + xdex = xdim->dim_order ; + ydex = ydim->dim_order ; + + if ( !strcmp( p->use , "_4d_bdy_array_" ) ) { /* if a boundary array for a 4d tracer */ + strcpy(s, p->name ) ; /* copy the name and then remove everything after last underscore */ + if ((pp=rindex( s, '_' )) != NULL ) *pp = '\0' ; + sprintf( four_d, "*num_%s,", s ) ; + } else { + strcpy( four_d, "" ) ; + } + if ( sw_new_bdys ) { + if ( bdy == P_XSB || bdy == P_XEB ) { bdex = ydex ; } + else if ( bdy == P_YSB || bdy == P_YEB ) { bdex = xdex ; } + else { fprintf(stderr,"REGISTRY WARNING: internal error %s %d, bdy=%d,%s,%d \n",__FILE__,__LINE__,bdy,p->name,p->boundary) ; } + if ( zdim != NULL ) { + zdex = zdim->dim_order ; + sprintf(tx,"(%sem3%d-%ssm3%d+1)*(%sem3%d-%ssm3%d+1)*(%sspec_bdy_width)%s", r,bdex,r,bdex,r,zdex,r,zdex,r,four_d ) ; + } else { + sprintf(tx,"(%sem3%d-%ssm3%d+1)*(%sspec_bdy_width)%s", r,bdex,r,bdex,r,four_d ) ; + } + } else { + if ( zdim != NULL ) { + zdex = zdim->dim_order ; + sprintf(tx,"max(%sed3%d,%sed3%d)*(%sed3%d-%ssd3%d+1)*%sspec_bdy_width*4*%s", r,xdex,r,ydex,r,zdex,r,zdex,r,four_d ) ; + } else { + sprintf(tx,"max(%sed3%d,%sed3%d)*%sspec_bdy_width*4*%s", r,xdex,r,ydex,r,four_d ) ; + } + if ( tx[strlen(tx)-1] == '*' ) tx[strlen(tx)-1] = '\0' ; /* chop trailing * if four_d is "" */ + } + } + else + { + sprintf(tx,"%sspec_bdy_width,",r ) ; + } + strcat(tmp,tx) ; + } + else + { + for ( i = 0 ; i < p->ndims ; i++ ) + { + dimension_size_expression( r, tx , i , p , nlstructname ) ; + strcat(tmp,tx) ; + strcat(tmp,")*(") ; + } + } + if ( tmp[strlen(tmp)-1] == '(' ) { + tmp[strlen(tmp)-3] = '\0' ; /* get rid of trailing )*( */ + } else if ( tmp[strlen(tmp)-1] == ',' ) { + tmp[strlen(tmp)-1] = '\0' ; + } + if ( post != NULL ) strcat(tmp,post) ; + + return(tmp) ; +} + +void +dimension_size_expression ( char * r , char * tx , int i , node_t * p , char * nlstructname ) +{ + char s[NAMELEN], e[NAMELEN] ; + + get_elem( r , nlstructname , s , i , p , 0 ) ; + get_elem( r , nlstructname , e , i , p , 1 ) ; + sprintf(tx,"((%s)-(%s)+1)", e , s ) ; + +} + +#ifdef FUTURE +void +reset_mask ( unsigned int * mask , int e ) +{ + int w ; + unsigned int m, n ; + + w = e / (8*sizeof(int)-1) ; + n = 1 ; + m = ~( n << e % (8*sizeof(int)-1) ) ; + if ( w >= 0 && w < IO_MASK_SIZE ) { + mask[w] &= m ; + } +} + +void +set_mask ( unsigned int * mask , int e ) +{ + int w ; + unsigned int m, n ; + + w = e / (8*sizeof(int)-1) ; + n = 1 ; + m = ( n << e % (8*sizeof(int)-1) ) ; + if ( w >= 0 && w < IO_MASK_SIZE ) { + mask[w] |= m ; + } +} + +int +get_mask ( unsigned int * mask , int e ) +{ + int w ; + unsigned int m, n ; + + w = e / (8*sizeof(int)-1) ; /* 8 is number of bits per byte */ + if ( w >= 0 && w < IO_MASK_SIZE ) { + m = mask[w] ; + n = ( 1 << e % (8*sizeof(int)-1) ) ;; + return ( (m & n) != 0 ) ; + } else { + return(0) ; + } +} +#endif + +#if 0 +main() +{ + unsigned int m[5] ; + int i, ii ; + + for ( i = 0 ; i < 5*32 ; i++ ) { + for ( ii = 0 ; ii < 5 ; ii++ ) { m[ii] = 0xffffffff ; } + reset_mask( m, i ) ; + for ( ii = 4 ; ii >= 0 ; ii-- ) { printf(" %08x ", m[ii]) ; } + printf("\n") ; + } + + for ( i = 0 ; i < 5*32 ; i++ ) { + for ( ii = 0 ; ii < 5 ; ii++ ) { m[ii] = 0x0 ; } + set_mask( m, i ) ; + for ( ii = 4 ; ii >= 0 ; ii-- ) { printf(" %08x ", m[ii]) ; } + printf("\n") ; + } + + for ( ii = 0 ; ii < 5 ; ii++ ) { m[ii] = 0x0 ; } + set_mask( m, 82 ) ; + for ( i = 0 ; i < 5*32 ; i++ ) { + printf("%d %0d\n",i,get_mask(m,i) ) ; + } +} +#endif diff --git a/OpenFAST/modules/openfast-registry/src/my_strtok.c b/OpenFAST/modules/openfast-registry/src/my_strtok.c new file mode 100644 index 000000000..ec7f479a9 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/my_strtok.c @@ -0,0 +1,139 @@ +#include <stdio.h> +#include <stdlib.h> +#include "registry.h" +#include "protos.h" +#include "ctype.h" + + +/* work sort of like strtok but mind quote chars */ +static char * tokpos = NULL ; +char * +my_strtok( char * s1 ) +{ + char *p, *retval ; + int state ; + state = 0 ; + retval = NULL ; + if ( s1 == NULL && tokpos == NULL ) return( NULL ) ; + if ( s1 != NULL ) tokpos = s1 ; + for ( p = tokpos ; *p ; p++ ) + { +/* check for non-printable characters in input. this can happen cutting and pasting from a + MS office document or PDF */ + + if ( !( (' ' <= *p && *p <= '~') || *p == '\t' ) ) { + fprintf(stderr,"Registry error: FATAL: Invalid character '%c' (maybe invisible: can happen if you cut-and-paste from a Office doc or PDF)\n",*p) ; + exit(2) ; + } + if ( state == 0 && (*p == ' ' || *p == '\t') ) continue ; + if ( state == 0 && !(*p == ' ' || *p == '\t') ) { state = 1 ; retval = p ; } ; + if ( state == 1 && (*p == '"') ) { state = 2 ; } + else if ( state == 2 && (*p == '"') ) { state = 1 ; } + if ( state == 1 && (*p == ' ' || *p == '\t') ) { *p = '\0' ; p++ ; break ; } + } + tokpos = p ; + return( retval ) ; +} + + +/* posix like rentrant strtok; not quote safe, and not quite strtok -- new version; skips multi delims */ +char * +strtok_rentr( char * s1 , char * s2, char ** tokpos ) +{ + char *p, *q, *retval ; + int match ; + retval = NULL ; + if ( s1 == NULL && s2 == NULL ) return( NULL ) ; + if ( s1 != NULL ) { *tokpos = s1 ; } + if ( **tokpos ) retval = *tokpos ; + for ( p = *tokpos ; *p ; p++ ) + { + for ( q = s2 ; *q ; q++ ) + { + if ( *p == *q ) { *p = '\0' ; p++ ; goto foundit ; } + } + } +foundit: +/* skip over multi-delims */ + for ( ; *p ; p++ ) + { + match = 0 ; + for ( q = s2 ; *q ; q++ ) + { + if ( *p == *q ) { *p = '\0' ; match++ ; } + } + if ( match == 0 ) { break ; } + } + *tokpos = p ; + return( retval ) ; +} + +#if 0 +/* posix like rentrant strtok; not quote safe, and not quite strtok -- won't skip over multiple delims */ +char * +strtok_rentr( char * s1 , char * s2, char ** tokpos ) +{ + char *p, *q, *retval ; + retval = NULL ; + if ( s1 == NULL && s2 == NULL ) return( NULL ) ; + if ( s1 != NULL ) { *tokpos = s1 ; } + if ( **tokpos ) retval = *tokpos ; + for ( p = *tokpos ; *p ; p++ ) + { + for ( q = s2 ; *q ; q++ ) + { + if ( *p == *q ) { *p = '\0' ; p++ ; goto foundit ; } + } + } +foundit: + *tokpos = p ; + return( retval ) ; +} +#endif + +char * +make_lower( char * s1 ) +{ + char * p ; + int state ; + state = 0 ; + for ( p = s1 ; *p ; p++ ) + { + if ( state == 0 && *p == '"' ) state = 1 ; + else if ( state == 1 && *p == '"' ) state = 0 ; + if ( state == 0 ) + { + *p = tolower(*p) ; + } + } + return(s1) ; +} + +/* do not store the result of this routine */ +#define LENRING 500 +static char t[LENRING][NAMELEN] ; +static int tcurs = 0 ; +char * +make_lower_temp( const char * s1 ) +{ + const char * p; + char *q ; + int state ; + state = 0 ; + for ( p = s1, q = t[tcurs] ; *p ; p++, q++ ) + { + if ( state == 0 && *p == '"' ) state = 1 ; + else if ( state == 1 && *p == '"' ) state = 0 ; + *q = *p ; + if ( state == 0 ) + { + *q = tolower(*p) ; + } + } + *q = '\0' ; + q = t[tcurs] ; + tcurs = (tcurs+1)%LENRING ; + return(q) ; +} + + diff --git a/OpenFAST/modules/openfast-registry/src/protos.h b/OpenFAST/modules/openfast-registry/src/protos.h new file mode 100644 index 000000000..1c8e06c00 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/protos.h @@ -0,0 +1,189 @@ +#ifndef PROTOS_H +#include "registry.h" +#include "data.h" + +void substitute( char * str , char * match , char * replace, char * result ); + +int init_dim_table() ; +char * make_lower( char * s1 ) ; +char * make_lower_temp( const char * s1 ) ; +int check_dimspecs(); +int init_parser(); +int is_a_fast_interface_type( char *str ); +int pre_parse( char * dir, FILE * infile, FILE * outfile, int usefrom_sw ); +int reg_parse( FILE * infile ) ; +int must_have_real_or_double( char *str ); +int set_dim_len ( char * dimspec , node_t * dim_entry ) ; +int set_dim_order ( char * dimorder , node_t * dim_entry ) ; +int set_dim_orient ( char * dimorient , node_t * dim_entry ) ; +int add_node_to_end ( node_t * node , node_t ** list ) ; +int add_node_to_beg ( node_t * node , node_t ** list ) ; +int add_node_to_end_4d ( node_t * node , node_t ** list ) ; +int init_type_table() ; +int set_state_type ( char * , node_t *, node_t *, node_t * ) ; +int set_state_dims ( char * dims , node_t * node ) ; +int set_ctrl ( char * ctrl , node_t * node ) ; +int gen_state_struct ( char * fname ) ; + +#if 1 +int show_node( node_t * p ) ; +int show_node1( node_t * p, int indent ) ; +void show_nodelist( node_t * p ) ; +void show_nodelist1( node_t * p , int indent ) ; +#endif + +void gen_c_module( FILE * fph, node_t * ModName ); + +int gen_state_struct ( char * fname ) ; +int gen_decls ( FILE * fp , node_t * node , int sw_ranges, int sw_point , int mask , int layer ) ; +int gen_state_subtypes ( char * fname ) ; +int gen_state_subtypes1 ( FILE * fp , node_t * node , int sw_ranges, int sw_point , int mask ) ; +int print_warning( FILE * fp , char * fname, char * comment ) ; +void close_the_file( FILE * fp, char * comment ) ; +int make_entries_uniq ( char * fname ) ; +int add_warning ( char * fname ) ; + +int init_modname_table(); +node_t * get_type_entry ( char * typename ) ; +node_t * get_modname_entry ( char * modname ) ; +node_t * get_rconfig_entry( char * name ) ; +node_t * get_entry ( char * name , node_t * node ) ; +node_t * get_entry_r ( char * name , char * use , node_t * node ) ; +node_t * get_dim_entry( char *s, int ) ; +node_t * new_node ( int kind ) ; + +node_t * get_4d_entry ( char * name ) ; +node_t * get_dimnode_for_coord ( node_t * node , int coord_axis ) ; +int get_index_for_coord ( node_t * node , int coord_axis ) ; + +char * my_strtok( char * s1 ) ; +char * strtok_rentr( char * s1 , char * s2, char ** tokpos ) ; + +char * bdy_indicator( int bdy ) ; +char * make_upper_case ( char * str ); +char * make_lower_case ( char * str ); + +char * field_name( char * tmp, node_t * p , int tag ) ; +char * field_name_bdy( char * tmp, node_t * p , int tag, int bdy ) ; +char * dimension_with_colons( char * pre, char * tmp, node_t * p, char * post) ; +char * dimension_with_ones( char * pre, char * tmp, node_t * p, char * post) ; +char * dimension_with_ranges( char * ref , char * pre, int bdy , char * tmp, node_t * p, char * post, char * nlstructname ) ; +char * arrray_size_expression( char * refarg , char * pre , int bdy , char * tmp , node_t * p , char * post , char * nlstructname ) ; +char * index_with_firstelem( char * pre , char * dref , int bdy , char * tmp , node_t * p , char * post ) ; + +char * declare_array_as_pointer( char * tmp, node_t * p ) ; +char * field_type( char * tmp , node_t * p ) ; + +/* For typedef history -ajb */ +int init_typedef_history() ; +int add_typedef_name ( char * name ) ; +int get_num_typedefs() ; +char * get_typedef_name ( char * name ) ; +char * get_typename_i(int i) ; + +int gen_alloc ( char * dirname ) ; +int gen_alloc1 ( char * dirname ) ; +int gen_alloc2 ( FILE * fp , char * structname , node_t * node, int *j, int *iguy, int *fraction, int numguys, int frac, int sw ); + +int gen_module_files ( char * dirname, char * prog_ver ); +int gen_module_state_description ( char * dirname ) ; +int gen_module_state_description1 ( FILE * fp , node_t * node ) ; + +void remove_nickname( const char *nickname, char *src, char *dst ); +void append_nickname( const char *nickname, char *src, char *dst ); +char * dimstr_c( int d ); +void checkOnlyReals( const char *q_mapsto, node_t * q); +void checkContainsMesh(node_t * q); + +int gen_scalar_indices ( char * dirname ) ; +int gen_scalar_indices1 ( FILE * fp, FILE ** fp2 ) ; + +int gen_actual_args ( char * dirname ) ; +int gen_dummy_args ( char * dirname ) ; +int gen_dummy_decls ( char * dn ) ; +int gen_args ( char * dirname , int sw ) ; +int gen_args1 ( FILE * fp , char * outstr, char * structname , node_t * node , int *linelen , int sw , int deep ) ; + +int gen_scalar_derefs ( char * dirname ) ; +int scalar_derefs ( char * dirname ) ; +int scalar_derefs1 ( FILE * fp , node_t * node, int direction ) ; + +int set_mark ( int val , node_t * lst ) ; +int set_mark_4d ( int val , node_t * lst ) ; + +int gen_i1_decls ( char * dn ) ; +int gen_get_nl_config ( char * dirname ) ; + +int gen_config_assigns ( char * dirname ) ; +int gen_config_reads ( char * dirname ) ; + +char * set_mem_order( node_t * node , char * str , int n ) ; + +int gen_wrf_io ( char * dirname ) ; +int set_dim_strs ( node_t *node , char ddim[3][2][NAMELEN], char mdim[3][2][NAMELEN], char pdim[3][2][NAMELEN] , char * prepend, int sw_allow_stagger ) ; +int set_dim_strs2 ( node_t *node , char ddim[3][2][NAMELEN], char mdim[3][2][NAMELEN], char pdim[3][2][NAMELEN] , char * prepend, int sw_disregard_stag ) ; +int set_dim_strs3 ( node_t *node , char ddim[3][2][NAMELEN], char mdim[3][2][NAMELEN], char pdim[3][2][NAMELEN] , char * prepend, int sw_disregard_stag ) ; +int gen_wrf_io2 ( FILE * fp , char * fname , char * structname , char * fourdname , node_t * node , int sw_io ) ; + +int gen_namelist_defines ( char * dirname , int sw_dimension ) ; +int gen_namelist_defaults ( char * dirname ) ; +int gen_namelist_script ( char * dirname ) ; + +int gen_model_data_ord ( char * dirname ) ; + +void get_elem ( char * structname , char * nlstructname , char * tx , int i , node_t * p , int first_last ) ; + +int associated_with_4d_array( node_t * p ) ; + + +/* PGI Addition to resolve non-prototype function warnings */ +char * array_size_expression ( char *, char *, int, char *, node_t *, char * ,char * ); +void range_of_dimension ( char *, char * , int, node_t *, char * ); +void dimension_size_expression ( char *, char *, int, node_t *, char *); +int gen_alloc_count ( char *); +int gen_alloc_count1 ( char *); +int gen_ddt_write ( char * ); +int gen_ddt_write1 ( FILE *, char *, node_t *); +int gen_dealloc ( char * ); +int gen_dealloc1 ( char * ); +int gen_dealloc2 ( FILE *, char *, node_t *); +int gen_scalar_tables ( FILE *); +int gen_scalar_tables_init ( FILE *); +int gen_scalar_indices_init ( FILE *); +int hash(char *); +int create_ht( char *** p ); +int gen_nest_interp1 ( FILE *, node_t *, char *, int, int ); +int gen_packs_halo ( FILE *fp , node_t *p, char *shw, int xy /* 0=y,1=x */ , int pu /* 0=pack,1=unpack */, char * packname, char * commname ); +int gen_packs ( FILE *fp , node_t *p, int shw, int xy /* 0=y,1=x */ , int pu /* 0=pack,1=unpack */, char * packname, char * commname ); +int gen_periods ( char * dirname , node_t * periods ); +int gen_swaps ( char * dirname , node_t * swaps ); +int gen_cycles ( char * dirname , node_t * cycles ); +int gen_xposes ( char * dirname ); +int gen_comm_descrips ( char * dirname ); +int gen_shift ( char * dirname ); +int gen_datacalls ( char * dirname ); +int gen_nest_packing ( char * dirname ); +int gen_nest_pack ( char * dirname ); +int gen_nest_unpack ( char * dirname ); +int gen_nest_packunpack ( FILE *fp , node_t * node , int dir, int down_path ); +int count_fields ( node_t * node , int * d2 , int * d3 , char * fourd_names, int down_path ); +int gen_debug ( char * dirname ); + +void reset_mask ( unsigned int * mask , int e ) ; +void set_mask ( unsigned int * mask , int e ) ; +int get_mask ( unsigned int * mask , int e ) ; + +char * fast_interface_type_shortname ( char * ) ; +char * std_case( char * ) ; + +char * dimstr( int ) ; + +char * C_type ( char * ) ; +char * c_types_binding( char *s ); +char * assoc_or_allocated( node_t * r ); +int is_pointer( node_t * r ); +int has_deferred_dim( node_t * node, int noisy ); + +#define PROTOS_H +#endif + diff --git a/OpenFAST/modules/openfast-registry/src/reg_parse.c b/OpenFAST/modules/openfast-registry/src/reg_parse.c new file mode 100644 index 000000000..37d457abc --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/reg_parse.c @@ -0,0 +1,756 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#ifdef _WIN32 +# define rindex(X,Y) strrchr(X,Y) +# define index(X,Y) strchr(X,Y) +#else +# include <strings.h> +#endif + +#include "registry.h" +#include "protos.h" +#include "data.h" +#include "sym.h" + +/* fields for state entries (note, these get converted to field entries in the + reg_parse routine; therefore, only TABLE needs to be looked at */ +#define TABLE 0 + +/* fields for field entries (TABLE="typedef" and, with some munging, TABLE="state") */ +#define FIELD_MODNAME 1 +#define FIELD_OF 2 +#define FIELD_TYPE 3 +#define FIELD_SYM 4 +#define FIELD_DIMS 5 +#define FIELD_INIVAL 6 +#define FIELD_CTRL 7 +#define FIELD_DESCRIP 8 +#define FIELD_UNITS 9 + +#define F_MODNAME 0 +#define F_OF 1 +#define F_TYPE 2 +#define F_SYM 3 +#define F_DIMS 4 +#define F_INIVAL 5 +#define F_CTRL 6 +#define F_DESCRIP 7 +#define F_UNITS 8 + +/* fields for dimension entries (TABLE="dimspec") */ +#define DIM_NAME 1 +//#define DIM_ORDER 2 +#define DIM_SPEC 2 + +#define INLN_SIZE 8000 +#define PARSELINE_SIZE 8000 + +int isNum( char c ) +{ + if ( c < '0' || c > '9' ) return 0; + return 1 ; +} + +int +pre_parse( char * dir, FILE * infile, FILE * outfile, int usefrom_sw ) +{ + /* Decreased size for SOA from 8192 to 8000--double check if necessary, Manish Shrivastava 2010 */ + char inln[INLN_SIZE], parseline[PARSELINE_SIZE], parseline_save[PARSELINE_SIZE] ; + char *p, *q, *p1, *p2 ; + char *tokens[MAXTOKENS] ; + int i, ifile ; + int ifdef_stack_ptr = 0 ; + int ifdef_stack[100] ; + int inquote, retval ; + int foundit ; + + ifdef_stack[0] = 1 ; + retval = 0 ; + + parseline[0] = '\0' ; + while ( fgets ( inln , INLN_SIZE , infile ) != NULL ) + { +/*** preprocessing directives ****/ + /* look for an include statement */ + if (( p = index( inln , '\n' )) != NULL ) *p = '\0' ; /* discard newlines */ + if (( p = index( inln , '\r' )) != NULL ) *p = '\0' ; /* discard carriage returns (happens on Windows)*/ + for ( p = inln ; ( *p == ' ' || *p == '\t' ) && *p != '\0' ; p++ ) ; + p1 = make_lower_temp(p) ; + if ( (!strncmp( p1 , "include", 7 ) || !strncmp( p1, "usefrom", 7 )) && ! ( ifdef_stack_ptr >= 0 && ! ifdef_stack[ifdef_stack_ptr] ) ) + { + FILE *include_fp ; + char include_file_name[NAMELEN] ; + char include_file_name_tmp[NAMELEN] ; + int checking_for_usefrom = !strncmp( p1, "usefrom", 7 ) ; +//fprintf(stderr,"checking_for_usefrom %d |%s|\n",checking_for_usefrom,p1) ; + + p += 7 ; for ( ; ( *p == ' ' || *p == '\t' ) && *p != '\0' ; p++ ) ; + if ( strlen( p ) > 127 ) { fprintf(stderr,"Registry warning: invalid include file name: %s\n", p ) ; } + else { +/* look in a few places for valid include files */ + foundit = 0 ; + + // See if it might be in the current directory + sprintf( include_file_name , "%s", p ) ; // first name in line from registry file, without the include or usefrom + for ( p2 = include_file_name ; !( *p2 == ' ' || *p2 == '\t' || *p2 == '\n' ) && *p2 != '\0' ; p2++ ) {} + *p2 = '\0' ; // drop tailing white space + if ( (q=index(include_file_name,'\n')) != NULL ) *q = '\0' ; + if (( include_fp = fopen( include_file_name , "r" )) != NULL ) { foundit = 1 ; goto gotit ; } + + // See if it might be in the directory specified (or whatever dir is). Don't remove spaces from the dir name though. + sprintf( include_file_name , "%s", p ) ; // first name in line from registry file, without the include or usefrom + for ( p2 = include_file_name ; !( *p2 == ' ' || *p2 == '\t' || *p2 == '\n' ) && *p2 != '\0' ; p2++ ) {} + *p2 = '\0' ; // drop tailing white space + sprintf( include_file_name , "%s/%s", dir, p ); // set the dir + file + if ( (q=index(include_file_name,'\n')) != NULL ) *q = '\0' ; + if (( include_fp = fopen( include_file_name , "r" )) != NULL ) { foundit = 1 ; goto gotit ; } + + // Check in the list of include dirs + for ( ifile = 0 ; ifile < nincldirs ; ifile++ ) { + sprintf( include_file_name_tmp , "%s", p ) ; // first name in line from registry file, without the include or usefrom + for ( p2 = include_file_name_tmp ; !( *p2 == ' ' || *p2 == '\t' || *p2 == '\n' ) && *p2 != '\0' ; p2++ ) {} + *p2 = '\0' ; // drop tailing white space + sprintf( include_file_name, "%s/%s", IncludeDirs[ifile] , include_file_name_tmp ) ; // dir specified with -I + if ( (q=index(include_file_name,'\n')) != NULL ) *q = '\0' ; + if (( include_fp = fopen( include_file_name , "r" )) != NULL ) { foundit = 1 ; goto gotit ; } + } + + // Cygwin specific -- assuming spaces in dir are ok. + for ( ifile = 0 ; ifile < nincldirs ; ifile++ ) { + int drive_specified = 0 ; + sprintf( include_file_name_tmp , "%s", p ) ; // first name in line from registry file, without the include or usefrom + for ( p2 = include_file_name_tmp ; !( *p2 == ' ' || *p2 == '\t' || *p2 == '\n' ) && *p2 != '\0' ; p2++ ) {} + *p2 = '\0' ; + sprintf( include_file_name , "%s/%s", IncludeDirs[ifile] , include_file_name_tmp ) ; // dir munged for cigwin + if ( include_file_name[0] == '/' ) { + char tmp[NAMELEN], tmp2[NAMELEN], *dr ; + strcpy( tmp2, include_file_name ) ; + if ( !strncmp( tmp2, "/cygdrive/", 10 )) { + strcpy(tmp,tmp2+11) ; // skip past /cygdrive/c + strcpy(tmp2,tmp) ; + drive_specified = 1 ; + } + for ( dr = "abcdefmy" ; *dr ; dr++ ) { + sprintf(tmp,"%c:%s%s",*dr,(drive_specified)?"":"/cygwin",tmp2) ; + strcpy( include_file_name, tmp ) ; + for ( p2 = include_file_name ; !( *p2 == ' ' || *p2 == '\t' || *p2 == '\n' ) && *p2 != '\0' ; p2++ ) {} + *p2 = '\0' ; + if ( (q=index(include_file_name,'\n')) != NULL ) *q = '\0' ; + if (( include_fp = fopen( include_file_name , "r" )) != NULL ) { foundit = 1 ; goto gotit ; } + } + } + } + +gotit: + if ( foundit ) { + fprintf(stderr,"opening %s %s\n",include_file_name, + (checking_for_usefrom || usefrom_sw)?"in usefrom mode":"" ) ; + parseline[0] = '\0' ; + pre_parse( dir , include_fp , outfile, ( checking_for_usefrom || usefrom_sw ) ) ; + parseline[0] = '\0' ; +// fprintf(stderr,"closing %s %s\n",include_file_name, +// (checking_for_usefrom || usefrom_sw)?"in usefrom mode":"" ) ; + fclose( include_fp ) ; + continue ; + } else { + if ( ! checking_for_usefrom ) { + fprintf(stderr,"Registry warning: cannot open %s . Ignoring.\n", include_file_name ) ; + } + } + } + } + else if ( !strncmp( make_lower_temp(p) , "ifdef", 5 ) ) { + char value[32] ; + p += 5 ; for ( ; ( *p == ' ' || *p == '\t' ) && *p != '\0' ; p++ ) ; + strncpy(value, p, 31 ) ; value[31] = '\0' ; + if ( (p=index(value,'\n')) != NULL ) *p = '\0' ; + if ( (p=index(value,' ')) != NULL ) *p = '\0' ; + if ( (p=index(value,'\t')) != NULL ) *p = '\0' ; + ifdef_stack_ptr++ ; + ifdef_stack[ifdef_stack_ptr] = ( sym_get(value) != NULL && ifdef_stack[ifdef_stack_ptr-1] ) ; + if ( ifdef_stack_ptr >= 100 ) { fprintf(stderr,"Registry fatal: too many nested ifdefs\n") ; exit(1) ; } + continue ; + } + else if ( !strncmp( make_lower_temp(p) , "ifndef", 6 ) ) { + char value[32] ; + p += 6 ; for ( ; ( *p == ' ' || *p == '\t') && *p != '\0' ; p++ ) ; + strncpy(value, p, 31 ) ; value[31] = '\0' ; + if ( (p=index(value,'\n')) != NULL ) *p = '\0' ; + if ( (p=index(value,' ')) != NULL ) *p = '\0' ; + if ( (p=index(value,'\t')) != NULL ) *p = '\0' ; + ifdef_stack_ptr++ ; + ifdef_stack[ifdef_stack_ptr] = ( sym_get(value) == NULL && ifdef_stack[ifdef_stack_ptr-1] ) ; + if ( ifdef_stack_ptr >= 100 ) { fprintf(stderr,"Registry fatal: too many nested ifdefs\n") ; exit(1) ; } + continue ; + } + else if ( !strncmp( make_lower_temp(p) , "endif", 5 ) ) { + ifdef_stack_ptr-- ; + if ( ifdef_stack_ptr < 0 ) { fprintf(stderr,"Registry fatal: unmatched endif\n") ; exit(1) ; } + continue ; + } + else if ( !strncmp( make_lower_temp(p) , "define", 6 ) ) { + char value[32] ; + p += 6 ; for ( ; ( *p == ' ' || *p == '\t') && *p != '\0' ; p++ ) ; + strncpy(value, p, 31 ) ; value[31] = '\0' ; + if ( (p=index(value,'\n')) != NULL ) *p = '\0' ; + if ( (p=index(value,' ')) != NULL ) *p = '\0' ; + if ( (p=index(value,'\t')) != NULL ) *p = '\0' ; + sym_add( value ) ; + continue ; + } + if ( ifdef_stack_ptr >= 0 && ! ifdef_stack[ifdef_stack_ptr] ) continue ; +/*** end of preprocessing directives ****/ +//fprintf(stderr,"parseline |%s|\n",parseline) ; +//fprintf(stderr,"inln |%s|\n",inln) ; + + strcat( parseline , inln ) ; + + /* allow \ to continue the end of a line */ + if (( p = index( parseline, '\\' )) != NULL ) + { + if ( *(p+1) == '\n' || *(p+1) == '\0' ) + { + *p = '\0' ; + continue ; /* go get another line */ + } + } +// make_lower( parseline ) ; + + if (( p = index( parseline , '\n' )) != NULL ) *p = '\0' ; /* discard newlines */ + + /* check line and zap any # characters that are in double quotes */ + + for ( p = parseline, inquote = 0 ; *p ; p++ ) { + if ( *p == '"' && inquote ) inquote = 0 ; + else if ( *p == '"' && !inquote ) inquote = 1 ; + else if ( *p == '#' && inquote ) *p = ' ' ; + else if ( *p == '#' && !inquote ) { *p = '\0' ; break ; } + } + if ( inquote ) { retval=1 ; fprintf(stderr,"Registry error: unbalanced quotes in line:\n%s\n",parseline) ;} + + for ( i = 0 ; i < MAXTOKENS ; i++ ) tokens[i] = NULL ; + i = 0 ; + + // get parsline_save, the value written to the output file... + //fprintf(stderr,"parseline_save |%s|\n",parseline_save) ; + //strcpy(parseline_save, parseline); + for (p = parseline; (*p == ' ' || *p == '\t') && *p != '\0'; p++); + strcpy(parseline_save, p); // get rid of leading spaces + + if (!strncmp(parseline_save, "typedef", 7)) + { + char tmp[PARSELINE_SIZE], *x; + strcpy(tmp, parseline_save); + x = strpbrk(tmp, " \t"); // find the first space or tab + if (usefrom_sw && x) { + sprintf(parseline_save, "usefrom %s", x); + } + } + + // parse tokens from parseline + if ((tokens[i] = my_strtok(parseline)) != NULL ) i++ ; + while (( tokens[i] = my_strtok(NULL) ) != NULL && i < MAXTOKENS ) i++ ; + if ( i <= 0 ) continue ; + + for ( i = 0 ; i < MAXTOKENS ; i++ ) + { + if ( tokens[i] == NULL ) tokens[i] = "-" ; + } + +/* remove quotes from quoted entries */ + for ( i = 0 ; i < MAXTOKENS ; i++ ) + { + char * pp ; + if ( tokens[i][0] == '"' ) tokens[i]++ ; + if ((pp=rindex( tokens[i], '"' )) != NULL ) *pp = '\0' ; + } + + + +//normal: + /* otherwise output the line as is */ + fprintf(outfile,"%s\n",parseline_save) ; + parseline[0] = '\0' ; /* reset parseline */ + parseline_save[0] = '\0' ; /* reset parseline_save */ + } + return(retval) ; +} + +int +reg_parse( FILE * infile ) +{ + /* Had to increase size for SOA from 4096 to 7000, Manish Shrivastava 2010 */ + char inln[INLN_SIZE], parseline[PARSELINE_SIZE] ; + char *p ; + char *tokens[MAXTOKENS],*ditto[MAXTOKENS] ; + int i ; + int defining_state_field, defining_rconfig_field, defining_i1_field ; + + parseline[0] = '\0' ; + + max_time_level = 1 ; + + for ( i = 0 ; i < MAXTOKENS ; i++ ) { ditto[i] = (char *)malloc(NAMELEN) ; strcpy(ditto[i],"-") ; } + +/* main parse loop over registry lines */ + while ( fgets ( inln , INLN_SIZE , infile ) != NULL ) + { + strcat( parseline , inln ) ; + /* allow \ to continue the end of a line */ + if (( p = index( parseline, '\\' )) != NULL ) + { + if ( *(p+1) == '\n' || *(p+1) == '\0' ) + { + *p = '\0' ; + continue ; /* go get another line */ + } + } + + //make_lower( parseline ) ; + if (( p = index( parseline , '#' )) != NULL ) *p = '\0' ; /* discard comments (dont worry about quotes for now) */ + if (( p = index( parseline , '\n' )) != NULL ) *p = '\0' ; /* discard newlines */ + if (( p = index( parseline , '\r' )) != NULL ) *p = '\0' ; /* discard carriage returns (happens on Windows)*/ + for ( i = 0 ; i < MAXTOKENS ; i++ ) tokens[i] = NULL ; + i = 0 ; + + if ((tokens[i] = my_strtok(parseline)) != NULL ) i++ ; + while (( tokens[i] = my_strtok(NULL) ) != NULL && i < MAXTOKENS ) i++ ; + if ( i <= 0 ) continue ; + + + for ( i = 0 ; i < MAXTOKENS ; i++ ) + { + if ( tokens[i] == NULL ) tokens[i] = "-" ; + if ( strcmp(tokens[i],"^") ) { // that is, if *not* ^ + strcpy(ditto[i],tokens[i]) ; + } else { // if is ^ + tokens[i] = ditto[i] ; + } + } + +/* remove quotes from quoted entries */ + for ( i = 0 ; i < MAXTOKENS ; i++ ) + { + char * pp ; + if ( tokens[i][0] == '"' ) tokens[i]++ ; + if ((pp=rindex( tokens[i], '"' )) != NULL ) *pp = '\0' ; + } + + defining_state_field = 0 ; + defining_rconfig_field = 0 ; + defining_i1_field = 0 ; + +/* typedef, usefrom, and param entries */ + if ( !strcmp( tokens[ TABLE ] , "typedef" ) + || !strcmp( tokens[ TABLE ] , "usefrom" ) + || !strcmp( tokens[ TABLE ] , "param" ) ) + { + node_t * param_struct ; + node_t * field_struct ; + node_t * type_struct ; + node_t * modname_struct ; + char tmpstr[NAMELEN], ddtname[NAMELEN] ; + +// FAST registry, construct a list of module nodes + strcpy(tmpstr, make_lower_temp(tokens[ FIELD_MODNAME ])) ; + if ( (p = index(tmpstr,'/')) != NULL ) *p = '\0' ; + modname_struct = get_modname_entry( tmpstr ) ; + if ( modname_struct == NULL ) + { + char *p ; + modname_struct = new_node( MODNAME ) ; + strcpy( modname_struct->name, tokens[FIELD_MODNAME] ) ; + // if a shortname is indicated after a slash, record that, otherwise use full name for both + if ( (p = index(modname_struct->name,'/')) != NULL ) { + *p = '\0' ; + strcpy( modname_struct->nickname, p+1 ) ; + } else { + strcpy( modname_struct->nickname, modname_struct->name ) ; + } + + modname_struct->module_ddt_list = NULL ; + modname_struct->next = NULL ; + add_node_to_end( modname_struct , &ModNames ) ; + } + if ( !strcmp( tokens[ TABLE ] , "usefrom" ) ) + { + modname_struct->usefrom = 1 ; + } + + if ( !strcmp( tokens[ TABLE ] , "param" ) ) { +// FAST registry, construct list of params specified for the Module + param_struct = new_node( PARAM ) ; + sprintf(param_struct->name,"%s",tokens[ FIELD_SYM ]) ; // name of parameter + if ( set_state_type( tokens[FIELD_TYPE], param_struct, Type, NULL ) ) // Only search type list, not ddts for module + { fprintf(stderr,"Registry warning: type %s used before defined for %s\n",tokens[FIELD_TYPE],tokens[FIELD_SYM] ) ; } + if ( set_state_dims( tokens[FIELD_DIMS], param_struct ) ) + { fprintf(stderr,"Registry warning: some problem with dimstring %s for %s\n", tokens[FIELD_DIMS],tokens[FIELD_SYM] ) ; } + param_struct->inival[0] = '\0' ; + if ( strcmp( tokens[FIELD_INIVAL], "-" ) ) /* that is, if not equal "-" */ + { strcpy( param_struct->inival , tokens[FIELD_INIVAL] ) ; } + strcpy(param_struct->descrip,"-") ; + if ( strcmp( tokens[FIELD_DESCRIP], "-" ) ) /* that is, if not equal "-" */ + { strcpy( param_struct->descrip , tokens[FIELD_DESCRIP] ) ; } + strcpy(param_struct->units,"-") ; + if ( strcmp( tokens[FIELD_UNITS], "-" ) ) /* that is, if not equal "-" */ + { strcpy( param_struct->units , tokens[FIELD_UNITS] ) ; } + + add_node_to_end( param_struct , &(modname_struct->params) ) ; + + } else { // not param + +// FAST registry, construct list of derived data types specified for the Module +// Only the FAST interface defined types should have the Module's nickname prepended + sprintf(ddtname,"%s",tokens[ FIELD_OF ]) ; + modname_struct->is_interface_type = 0 ; + if ( strcmp(modname_struct->nickname,"") ) { + if ( is_a_fast_interface_type(tokens[FIELD_OF] ) ) { + sprintf(ddtname,"%s_%s",modname_struct->nickname,tokens[ FIELD_OF ]) ; + modname_struct->is_interface_type = 1 ; + } + } + sprintf(tmpstr,"%s",make_lower_temp(ddtname)) ; + type_struct = get_entry( tmpstr, modname_struct->module_ddt_list ) ; + if ( type_struct == NULL && modname_struct->usefrom) + { + type_struct = get_entry( tmpstr, Type ) ; + } + + if ( type_struct == NULL ) + { + type_struct = new_node( TYPE ) ; + strcpy( type_struct->name, tmpstr ) ; + strcpy(type_struct->mapsto,ddtname) ; + type_struct->type_type = DERIVED ; + type_struct->next = NULL ; + type_struct->usefrom = modname_struct->usefrom ; + type_struct->module = modname_struct ; + add_node_to_end( type_struct,(type_struct->usefrom)? &Type : &(modname_struct->module_ddt_list ) ) ; + } + +// FAST registry, construct the list of fields in the derived types in the Module + field_struct = new_node( FIELD ) ; + strcpy( field_struct->name, tokens[FIELD_SYM] ) ; + if ( set_state_type( tokens[FIELD_TYPE], field_struct, Type, modname_struct->module_ddt_list ) ) + { fprintf(stderr,"Registry warning: type %s used before defined for %s\n",tokens[FIELD_TYPE],tokens[FIELD_SYM] ) ; } + if ( set_state_dims( tokens[FIELD_DIMS], field_struct ) ) + { fprintf(stderr,"Registry warning: some problem with dimstring %s for %s\n", tokens[FIELD_DIMS],tokens[FIELD_SYM] ) ; } + if ( set_ctrl( tokens[FIELD_CTRL], field_struct ) ) + { fprintf(stderr,"Registry warning: some problem with ctrl %s for %s\n", tokens[FIELD_CTRL],tokens[FIELD_SYM] ) ; } + + field_struct->inival[0] = '\0' ; + if ( strcmp( tokens[FIELD_INIVAL], "-" ) ) /* that is, if not equal "-" */ + { strcpy( field_struct->inival , tokens[FIELD_INIVAL] ) ; } + strcpy(field_struct->descrip,"-") ; + if ( strcmp( tokens[FIELD_DESCRIP], "-" ) ) /* that is, if not equal "-" */ + { strcpy( field_struct->descrip , tokens[FIELD_DESCRIP] ) ; } + strcpy(field_struct->units,"-") ; + if ( strcmp( tokens[FIELD_UNITS], "-" ) ) /* that is, if not equal "-" */ + { strcpy( field_struct->units , tokens[FIELD_UNITS] ) ; } +#ifdef OVERSTRICT + if ( field_struct->type != NULL ) + if ( field_struct->type->type_type == DERIVED && field_struct->ndims > 0 ) + { fprintf(stderr,"Registry warning: type item %s of type %s can not be multi-dimensional ", + tokens[FIELD_SYM], tokens[FIELD_TYPE] ) ; } +#endif + field_struct->usefrom = type_struct->usefrom ; + + add_node_to_end( field_struct , &(type_struct->fields) ) ; + } // not param + + } + +/* dimspec entry */ + else if ( !strcmp( tokens[ TABLE ] , "dimspec" ) ) + { + node_t * dim_struct ; + dim_struct = new_node( DIM ) ; + if ( get_dim_entry ( tokens[DIM_NAME], 0 ) != NULL ) + { fprintf(stderr,"Registry warning: dimspec (%s) already defined\n",tokens[DIM_NAME] ) ; } + strcpy(dim_struct->dim_name,tokens[DIM_NAME]) ; + if ( set_dim_len( tokens[DIM_SPEC], dim_struct ) ) + { fprintf(stderr,"Registry warning: problem with dimspec (%s)\n",tokens[DIM_SPEC] ) ; } + + add_node_to_end( dim_struct , &Dim ) ; + } + + parseline[0] = '\0' ; /* reset parseline */ + } + +/* Domain is a type node with fields that are not part of any type. WRF "state" entries + were these. They were simply fields of the data type for a domain (as opposed to + fields within derived data types that were fields in a domain). The FAST registry + does not have the concept of a Domain. Leave the following assignment here but + put a test around it so we do not segfault if there aren't any "state" entries. */ + if ( get_type_entry( "domain" ) ) { + Domain = *(get_type_entry( "domain" )) ; + } + + return(0) ; + +} + +node_t * +get_dim_entry( char *s, int sw ) // sw = 1 is used when checking an inline dimspec +{ + node_t * p ; + for ( p = Dim ; p != NULL ; p = p->next ) + { + if ( !strcmp(p->dim_name, s ) ) { + return( p ) ; + } + } + /* not found, check if dimension is specified in line */ + if ( 1 && sw ) { + node_t * dim_struct ; + dim_struct = new_node( DIM ) ; + strcpy(dim_struct->dim_name,s) ; +// strncpy(dim_struct->dim_name,s,1) ; + if ( set_dim_len( s, dim_struct ) ) + { + fprintf(stderr,"Registry warning: get_dim_entry: problem with dimspec (%s)\n",s ) ; + } + else + { + add_node_to_end( dim_struct , &Dim ) ; + return( dim_struct ) ; + } + } + return(NULL) ; +} + +int +set_state_type( char * typename, node_t * state_entry, node_t * typelist, node_t * ddtlist ) +{ + node_t *p ; + int retval ; + + if ( typename == NULL ) return(1) ; + retval = 0 ; + if ( ( state_entry->type = get_entry( make_lower_temp(typename), ddtlist )) == NULL ) { + if ( ( state_entry->type = get_entry( make_lower_temp(typename), typelist )) == NULL ) { + if ( !strncmp(make_lower_temp(typename),"character",9) ) + { + p = new_node( TYPE ) ; + strcpy( p->name, make_lower_temp(typename) ) ; + strcpy( p->mapsto, typename ) ; + add_node_to_end( p , &(state_entry->type) ) ; + } else { + retval = 1 ; + } + } + } + return(retval) ; +} + +int +set_dim_len ( char * dimspec , node_t * dim_entry ) +{ + dim_entry->deferred = 0 ; + if (!strcmp( dimspec , "standard_domain" )) + { dim_entry->len_defined_how = DOMAIN_STANDARD ; } + else if (!strncmp( dimspec, "constant=" , 9 ) || isNum(dimspec[0]) || dimspec[0] == ':' || dimspec[0] == '(' ) + { + char *p, *colon, *paren ; + p = (isNum(dimspec[0])||dimspec[0]==':'||dimspec[0]=='(')?dimspec:&(dimspec[9]) ; + /* check for colon */ + if (( colon = index(p,':')) != NULL ) + { + *colon = '\0' ; + if (( paren = index(p,'(')) !=NULL ) + { + dim_entry->coord_start = atoi(paren+1) ; + } + else if ( isNum(*p) ) { + dim_entry->coord_start = atoi(p) ; + } + else + { + dim_entry->deferred = 1 ; + } + dim_entry->coord_end = atoi(colon+1) ; + } + else + { + dim_entry->coord_start = 1 ; + dim_entry->coord_end = atoi(p) ; + } + dim_entry->len_defined_how = CONSTANT ; + } + else if (!strncmp( dimspec, "namelist=", 9 )) + { + char *p, *colon ; + + p = &(dimspec[9]) ; + /* check for colon */ + if (( colon = index(p,':')) != NULL ) + { + *colon = '\0' ; + strcpy( dim_entry->assoc_nl_var_s, p ) ; + strcpy( dim_entry->assoc_nl_var_e, colon+1 ) ; + } + else + { + strcpy( dim_entry->assoc_nl_var_s, "1" ) ; + strcpy( dim_entry->assoc_nl_var_e, p ) ; + } + dim_entry->len_defined_how = NAMELIST ; + } + else /* if (param_dim != NULL) */ { + dim_entry->coord_start = 1; + dim_entry->len_defined_how = CONSTANT; + strcpy(dim_entry->dim_param_name, dimspec); + dim_entry->dim_param = 1; + } +/* else + { + return(1) ; + } +*/ + return(0) ; +} + +int +set_ctrl( char *ctrl , node_t * field_struct ) +// process CTRL keys -- only '2pi' (interpolation of values with 2pi period). Default is no special interpolation. +{ + char tmp[NAMELEN] ; + char *p ; + strcpy(tmp,ctrl) ; + if (( p = index(tmp,'=') ) != NULL ) { *p = '\0' ; } + if (!strcmp(make_lower_temp(tmp), "2pi")) { + field_struct->gen_periodic = PERIOD_2PI; + } + else { + field_struct->gen_periodic = PERIOD_NONE; + } + + return(0) ; +} + + +/* integrity checking of dimension list */ +int +check_dimspecs() +{ + return(0) ; +} + +int +init_parser() +{ + return(0) ; +} + +int +is_a_fast_interface_type( char *str ) +{ + int retval ; + + retval = ( + !strcmp(make_lower_temp(str), "initinputtype") || + !strcmp(make_lower_temp(str), "initoutputtype") || + !strcmp(make_lower_temp(str), "inputtype") || + !strcmp(make_lower_temp(str), "outputtype") || + !strcmp(make_lower_temp(str), "continuousstatetype") || + !strcmp(make_lower_temp(str), "discretestatetype") || + !strcmp(make_lower_temp(str), "constraintstatetype") || + !strcmp(make_lower_temp(str), "otherstatetype") || + !strcmp(make_lower_temp(str), "parametertype") || + !strcmp(make_lower_temp(str), "miscvartype") || + !strcmp(make_lower_temp(str), "partialoutputpinputtype") || + !strcmp(make_lower_temp(str), "partialcontstatepinputtype") || + !strcmp(make_lower_temp(str), "partialdiscstatepinputtype") || + !strcmp(make_lower_temp(str), "partialconstrstatepinputtype") || + 0 ) ; + + return(retval) ; +} + +int +must_have_real_or_double( char *str ) +{ + int retval ; + + retval = ( + !strcmp(make_lower_temp(str), "inputtype") || + !strcmp(make_lower_temp(str), "outputtype") || + !strcmp(make_lower_temp(str), "continuousstatetype") || + !strcmp(make_lower_temp(str), "discretestatetype") || + !strcmp(make_lower_temp(str), "constraintstatetype") || + !strcmp(make_lower_temp(str), "partialoutputpinputtype") || + !strcmp(make_lower_temp(str), "partialcontstatepinputtype") || + !strcmp(make_lower_temp(str), "partialdiscstatepinputtype") || + !strcmp(make_lower_temp(str), "partialconstrstatepinputtype") || + 0 ) ; + + return(retval) ; +} + +char * +fast_interface_type_shortname( char *str ) +{ + char * retval, *str2; + str2 = make_lower_temp(str); + + if ( !strcmp(str2, "initinputtype") ) { + retval = "InitInput" ; + } else if ( !strcmp(str2, "initoutputtype") ) { + retval = "InitOutput" ; + } else if ( !strcmp(str2, "inputtype") ) { + retval = "Input" ; + } else if ( !strcmp(str2, "outputtype") ) { + retval = "Output" ; + } else if ( !strcmp(str2, "continuousstatetype") ) { + retval = "ContState" ; + } else if ( !strcmp(str2, "discretestatetype") ) { + retval = "DiscState" ; + } else if ( !strcmp(str2, "constraintstatetype") ) { + retval = "ConstrState" ; + } else if ( !strcmp(str2, "otherstatetype") ) { + retval = "OtherState" ; + } else if ( !strcmp(str2, "miscvartype") ) { + retval = "Misc"; + } else if ( !strcmp(str2, "parametertype") ) { + retval = "Param" ; + } else if ( !strcmp(str2, "partialoutputpinputtype") ) { + retval = "dYdu" ; + } else if ( !strcmp(str2, "partialcontstatepinputtype") ) { + retval = "dXdu" ; + } else if ( !strcmp(str2, "partialdiscstatepinputtype") ) { + retval = "dXddu" ; + } else if ( !strcmp(str2, "partialconstrstatepinputtype") ) { + retval = "dZdu" ; + } + else{ + retval = str; + } + + + return(retval) ; +} + +char * +std_case( char *str ) // returns the name in CamelBack case or just the name itself +{ + if ( !strcmp(make_lower_temp(str), "initinputtype")) {return("InitInputType");} + else if ( !strcmp(make_lower_temp(str), "initoutputtype")) {return("InitOutputType");} + else if ( !strcmp(make_lower_temp(str), "inputtype")) {return("InputType");} + else if ( !strcmp(make_lower_temp(str), "outputtype")) {return("OutputType");} + else if ( !strcmp(make_lower_temp(str), "continuousstatetype")) {return("ContinuousStateType");} + else if ( !strcmp(make_lower_temp(str), "discretestatetype")) {return("DiscreteStateType");} + else if ( !strcmp(make_lower_temp(str), "constraintstatetype")) {return("ConstraintStateType");} + else if ( !strcmp(make_lower_temp(str), "otherstatetype")) {return("OtherStateType");} + else if ( !strcmp(make_lower_temp(str), "miscvartype")) {return("MiscVarType"); } + else if ( !strcmp(make_lower_temp(str), "parametertype")) {return("ParameterType"); } + else if ( !strcmp(make_lower_temp(str), "partialoutputpinputtype")) {return("PartialOutputPInputType");} + else if ( !strcmp(make_lower_temp(str), "partialcontstatepinputtype")) {return("PartialConstStatePInputType");} + else if ( !strcmp(make_lower_temp(str), "partialdiscstatepinputtype")) {return("PartialDiscStatePInputType");} + else if ( !strcmp(make_lower_temp(str), "partialconstrstatepinputtype")) {return("PartialConstrStatePInputType");} + else {return(str);} + // shouldn't happen + return("") ; +} + diff --git a/OpenFAST/modules/openfast-registry/src/registry.c b/OpenFAST/modules/openfast-registry/src/registry.c new file mode 100644 index 000000000..2fe9dc566 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/registry.c @@ -0,0 +1,311 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef _WIN32 +# include <io.h> +# define rindex(X,Y) strrchr(X,Y) +# define index(X,Y) strchr(X,Y) +# include <process.h> +# define getpid _getpid +#else +# include <sys/time.h> +# include <sys/resource.h> +# include <unistd.h> +# include <strings.h> +#endif + +#define DEFINE_GLOBALS +#include "protos.h" +#include "registry.h" +#include "data.h" +#include "sym.h" + +void output_template( char * sw_modname_subst, char * sw_modnickname_subst, int force, int sw ); +int matches( char * str , char * match ); + +int +main( int argc, char *argv[], char *env[] ) +{ + char fname_in[NAMELEN], dir[NAMELEN], fname_tmp[NAMELEN], command[NAMELEN] ; + FILE * fp_in, *fp_tmp ; + char * thisprog ; + char * thisprog_ver; + int mypid ; + int wrote_template ; + int sw_keep = 0 ; +#ifndef _WIN32 + struct rlimit rlim ; +#endif + + mypid = (int) getpid() ; + strcpy( thiscom, argv[0] ) ; + argv++ ; + + sw_output_template_force = 0 ; + sw_norealloc_lsh = 1 ; + sw_ccode = 0 ; + sw_noextrap = 0 ; + sw_shownodes = 0 ; + strcpy( fname_in , "" ) ; + +#ifndef _WIN32 + rlim.rlim_cur = RLIM_INFINITY ; + rlim.rlim_max = RLIM_INFINITY ; + setrlimit ( RLIMIT_STACK , &rlim ) ; +#endif + + thisprog_ver = "FAST Registry"; + + fprintf(stderr,"\n") ; + fprintf(stderr,"----- %s --------------\n", thisprog_ver) ; + fprintf(stderr,"----------------------------------------------------------\n") ; + + sym_forget() ; + //thisprog = *argv ; + // strcpy(thisprog, thiscom); + thisprog = "registry.exe"; + strcpy(fname_in, ""); + strcpy(OutDir, "."); // if no OutDir is listed, use current directory + wrote_template = 0; + + + while (*argv) { + + if (!strncmp(*argv,"-D",2)) { + char * p ; + p = *argv ; + sym_add(p+2) ; + } else if (!strncmp(*argv,"/D=",3)) { + char * p ; + p = *argv ; + sym_add(p+3) ; + } else if (!strcmp(*argv,"-force") || !strcmp(*argv,"/force") ) { + sw_output_template_force = 1 ; + } else if (!strcmp(*argv,"-O") || !strcmp(*argv,"/O") ) { + argv++ ; if ( *argv ) { strcpy( OutDir, *argv ) ; } + } else if (!strcmp(*argv,"-I") || !strcmp(*argv,"/I") ) { + argv++ ; if ( *argv ) { if( nincldirs < MAXINCLDIRS ) { strcpy( IncludeDirs[nincldirs++], *argv ) ; } } + } else if (!strcmp(*argv, "-ccode") || !strcmp(*argv, "/ccode")) { + sw_ccode = 1 ; + } else if (!strcmp(*argv, "-noextrap") || !strcmp(*argv, "/noextrap")) { + sw_noextrap = 1; + } else if (!strncmp(*argv, "-shownodes", 4) || !strncmp(*argv, "/shownodes", 4)) { + sw_shownodes = 1 ; + } else if (!strcmp(*argv,"-template") || !strcmp(*argv,"-registry") || + !strcmp(*argv,"/template") || !strcmp(*argv,"/registry") ) { + char * arg ; + arg = *argv ; + argv++ ; if ( *argv ) { strcpy( sw_modname_subst, *argv ) ; } else { goto usage ; } + argv++ ; if ( *argv ) { strcpy( sw_modnickname_subst, *argv ) ; } else { goto usage ; } + if (!strcmp(arg+1,"template")) output_template(sw_modname_subst,sw_modnickname_subst,sw_output_template_force,0) ; + if (!strcmp(arg+1,"registry")) output_template(sw_modname_subst,sw_modnickname_subst,sw_output_template_force,1) ; + wrote_template = 1 ; + } else if (!strcmp(*argv,"-h") || !strcmp(*argv,"/h")) { +usage: +// fprintf(stderr,"Usage: %s [options] registryfile -or- \n",thisprog) ; + fprintf(stderr, "Usage: %s registryfile [options] -or- \n",thiscom) ; + fprintf(stderr, " [-force] [-template|-registry] ModuleName ModName \n") ; + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h this summary\n"); + fprintf(stderr, " -I <dir> look for usefrom files in directory \"dir\"\n"); + fprintf(stderr, " -O <dir> generate types files in directory \"dir\"\n"); + fprintf(stderr, " -noextrap do not generate ModName_Input_ExtrapInterp or ModName_Output_ExtrapInterp routines\n"); + fprintf(stderr, " -D<SYM> define symbol for conditional evaluation inside registry file\n"); + fprintf(stderr, " -ccode generate additional code for interfacing with C/C++\n") ; + fprintf(stderr, " -keep do not delete temporary files from registry program\n") ; + fprintf(stderr, " -shownodes output a listing of the nodes in registry's AST\n") ; + fprintf(stderr, " === alternate usage for generating templates ===\n") ; + fprintf(stderr, " -template ModuleName ModName\n") ; + fprintf(stderr, " Generate a template Module file none exists\n") ; + fprintf(stderr, " -registry ModuleName ModName\n") ; + fprintf(stderr, " Generate a template registry file if none exists\n") ; + fprintf(stderr, " -force Force generating of template or registry file\n") ; + fprintf(stderr, " (the / character can be used in place of - when specifying options)\n") ; + exit(1) ; + } else if (!strcmp(*argv,"-keep") || !strcmp(*argv,"/keep") ) { + sw_keep = 1 ; + } + else { /* consider it an input file */ + strcpy( fname_in , *argv ) ; + } + argv++ ; + } + if ( wrote_template ) exit(0) ; + + if ( !strcmp(fname_in,"") ) goto usage ; + +#ifdef FUTURE + gen_io_boilerplate() ; /* 20091213 jm. Generate the io_boilerplate_temporary.inc file */ +#endif + + fprintf(stderr,"input file: %s\n",fname_in); + + init_parser() ; + init_type_table() ; + init_dim_table() ; + init_modname_table() ; + + if ( !strcmp(fname_in,"") ) fp_in = stdin ; + else + if (( fp_in = fopen( fname_in , "r" )) == NULL ) + { + fprintf(stderr,"Registry program cannot open %s for reading. Ending.\n", fname_in ) ; + exit(2) ; + } + + sprintf( fname_tmp , "Registry_tmp.%d",mypid) ; + if (( fp_tmp = fopen( fname_tmp , "w" )) == NULL ) + { + fprintf(stderr,"Registry program cannot open temporary %s for writing. Ending.\n", fname_tmp ) ; + exit(2) ; + } + + { char *e ; + strcpy( dir , fname_in ) ; + if ( ( e = rindex ( dir , '/' ) ) != NULL ) { *e = '\0' ; } else { strcpy( dir, "." ) ; } + } + if ( pre_parse( dir, fp_in, fp_tmp, 0 ) ) { + fprintf(stderr,"Problem with Registry File %s\n", fname_in ) ; + goto cleanup ; + } + sym_forget() ; + + fclose(fp_in) ; + fclose(fp_tmp) ; + + if (( fp_tmp = fopen( fname_tmp , "r" )) == NULL ) + { + fprintf(stderr,"Registry program cannot open %s for reading. Ending.\n", fname_tmp ) ; + goto cleanup ; + } + + reg_parse(fp_tmp) ; + + fclose(fp_tmp) ; + + check_dimspecs() ; + + if (sw_shownodes) { + fprintf(stderr,"--- ModNames ---\n") ; + show_nodelist(ModNames) ; + fprintf(stderr,"--- Done ---\n") ; + } + + gen_module_files( OutDir, thisprog_ver); + +cleanup: + if ( ! sw_keep ) { +#ifdef _WIN32 + sprintf(command,"del /F /Q %s\n",fname_tmp ); +#else + sprintf(command,"/bin/rm -f %s\n",fname_tmp ); +#endif + system( command ) ; + } + + exit( 0 ) ; + +} +#include "Template_data.c" +#include "Template_registry.c" + +void +output_template( char * sw_modname_subst, char * sw_modnickname_subst, int force, int sw ) // sw = 0, template; 1 = registry +{ + char ** p ; + FILE *fp ; + char fname[NAMELEN] ; + char tmp1[2096], tmp2[2096], tmp3[2096] ; + if ( sw == 0 ) { sprintf(fname,"%s.f90",sw_modname_subst) ; } + else { sprintf(fname,"%s_Registry.txt",sw_modname_subst) ; } + + if ( ! force ) { // check if file exists by trying to open file for reading. If the read is successful, exit program: + if ( (fp = fopen( fname,"r" )) != NULL ) { + fprintf(stderr,"Registry exiting. Attempt to overwrite file (%s) . Move out of the way or specify -force before -template option. \n", fname) ; + exit(1) ; + } + } + + if ( (fp = fopen( fname,"w" )) == NULL ) { + fprintf(stderr,"Registry exiting. Failure opening %s.\n", fname ) ; + exit(1) ; + } + if ( sw == 0 ) { + for ( p = template_data ; *p ; p++ ) { + strcpy(tmp1,*p) ; + substitute(tmp1,"ModuleName",sw_modname_subst,tmp2) ; + substitute(tmp2,"ModName",sw_modnickname_subst,tmp3) ; + fprintf(fp,"%s\n",tmp3) ; + } + } else { + for ( p = template_registry ; *p ; p++ ) { + strcpy(tmp1,*p) ; + substitute(tmp1,"ModuleName",sw_modname_subst,tmp2) ; + substitute(tmp2,"ModName",sw_modnickname_subst,tmp3) ; + fprintf(fp,"%s\n",tmp3) ; + } + } + fclose(fp) ; +} + + + +// would use regex for this but it does not seem to be uniformly or universally supported + +void +substitute( char * str , char * match , char * replace, char * result ) +{ + char * p, *q ; + char allup[NAMELEN], alllo[NAMELEN] ; + size_t n, m ; + int nmatch = 0 ; + + n = strlen( replace ) ; + m = strlen( match ) ; + strcpy(allup,replace) ; make_upper_case(allup) ; + strcpy(alllo,replace) ; make_lower_case(alllo) ; +// watch for #defines, in which case first sub should be all upper, next all lower + if ( str[0] == '#' ) { + for ( p = str ; *p ; p++ ) { + if ( matches( p, "define" ) ) nmatch = 2 ; + } + } + + for ( p = str , q = result ; *p ; ) + { + if ( matches( p, match ) ) + { + if ( nmatch == 2 ) { + strncpy( q, replace, n ) ; + nmatch-- ; + } else if ( nmatch == 1 ) { + strncpy( q, alllo, n ) ; + nmatch-- ; + } else { + strncpy( q, replace, n ) ; + } + q += n ; + p += m ; + } else { + *q = *p ; + p++ ; + q++ ; + } + } + *q = '\0' ; + strcpy( str, result ) ; +} + +int +matches( char * str , char * match ) // both must be null terminated +{ + char * p, * q ; + int n ; + + for ( n = 0, p = str, q = match ; (*p && *q) ; p++, q++, n++ ) + { + if ( *p != *q ) return(0) ; + } + if ( n != strlen(match) ) return(0) ; + return(1) ; +} diff --git a/OpenFAST/modules/openfast-registry/src/registry.h b/OpenFAST/modules/openfast-registry/src/registry.h new file mode 100644 index 000000000..524bbe7e1 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/registry.h @@ -0,0 +1,63 @@ +#ifndef REGISTRY_H +#define NAMELEN 512 +#define NAMELEN_LONG 12500 /*changed from 8192 to 12500 by PNNL on 12/22/2010*/ +#define MAXDIMS 21 +#define MAX_DYNCORES 50 /* ha ha, just kidding */ +/* #define MAX_ARGLINE 175 WRF uses 128 by default, but the nested chem version hit the continuation line limit for efc so it had to be increased, wig 14-Oct-2004 */ +#define MAX_ARGLINE 128 /* welp, 175 means lines longer than 130 chars, which is a Fortran no no */ +#define MAX_TYPEDEFS 50 /* typedef history -ajb */ +#define MAXTOKENS 100 + +/* defines of system commands */ +#define UNIQSORT "/bin/sort -u" +#define CATCOMM "/bin/cat" +#define RMCOMM "/bin/rm" +#define MVCOMM "/bin/mv" + +#define DRIVER_LAYER 100 +#define MEDIATION_LAYER 200 + +enum coord_axis { COORD_X , COORD_Y , COORD_Z , COORD_C } ; +enum len_defined_how { DOMAIN_STANDARD , NAMELIST , CONSTANT } ; +enum type_type { SIMPLE , DERIVED } ; +enum proc_orient { ALL_Z_ON_PROC , ALL_X_ON_PROC , ALL_Y_ON_PROC } ; + +/* wrapping options */ +#define PERIOD_2PI 2 +#define PERIOD_OTHER 1 +#define PERIOD_NONE 0 + + +/* node_kind mask settings */ +#define FIELD 1 +#define PARAM 2 +#define RCONFIG 4 +#define FOURD 8 +#define MEMBER 16 +#define TYPE 32 +#define DIM 64 +#define MODNAME 128 +#define HALO 256 +#define PERIOD 512 +#define SWAP 1024 +#define CYCLE 2048 +#define XPOSE 4096 +#define FOURD1 8192 +#define BDYONLY 16384 + +#define RESTART 0x02000000 /* 25 */ +#define BOUNDARY 0x04000000 /* 26 */ +#define INTERP_DOWN 0x08000000 /* 27 */ +#define FORCE_DOWN 0x10000000 /* 28 */ +#define INTERP_UP 0x20000000 /* 29 */ +#define SMOOTH_UP 0x40000000 /* 20 */ +#define METADATA 0x80000000 /* 31 */ + + +#define REGISTRY_H +#endif + +#ifdef WIN32 +#define snprintf _snprintf +#endif + diff --git a/OpenFAST/modules/openfast-registry/src/sym.c b/OpenFAST/modules/openfast-registry/src/sym.c new file mode 100644 index 000000000..689f5800b --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/sym.c @@ -0,0 +1,163 @@ +/*********************************************************************** + + COPYRIGHT + + The following is a notice of limited availability of the code and + Government license and disclaimer which must be included in the + prologue of the code and in all source listings of the code. + + Copyright notice + (c) 1977 University of Chicago + + Permission is hereby granted to use, reproduce, prepare + derivative works, and to redistribute to others at no charge. If + you distribute a copy or copies of the Software, or you modify a + copy or copies of the Software or any portion of it, thus forming + a work based on the Software and make and/or distribute copies of + such work, you must meet the following conditions: + + a) If you make a copy of the Software (modified or verbatim) + it must include the copyright notice and Government + license and disclaimer. + + b) You must cause the modified Software to carry prominent + notices stating that you changed specified portions of + the Software. + + This software was authored by: + + Argonne National Laboratory + J. Michalakes: (630) 252-6646; email: michalak@mcs.anl.gov + Mathematics and Computer Science Division + Argonne National Laboratory, Argonne, IL 60439 + + ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES + OF ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, + AND OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A + CONTRACT WITH THE DEPARTMENT OF ENERGY. + + GOVERNMENT LICENSE AND DISCLAIMER + + This computer code material was prepared, in part, as an account + of work sponsored by an agency of the United States Government. + The Government is granted for itself and others acting on its + behalf a paid-up, nonexclusive, irrevocable worldwide license in + this data to reproduce, prepare derivative works, distribute + copies to the public, perform publicly and display publicly, and + to permit others to do so. NEITHER THE UNITED STATES GOVERNMENT + NOR ANY AGENCY THEREOF, NOR THE UNIVERSITY OF CHICAGO, NOR ANY OF + THEIR EMPLOYEES, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR + ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, + COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, + PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD + NOT INFRINGE PRIVATELY OWNED RIGHTS. + +***************************************************************************/ +/* sym.c + + Implementation dependent routines for using symtab_gen.c + in N32 . + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "sym.h" +#include "protos.h" + +extern sym_nodeptr symget() ; + +static char ** symtab ; /* 2-19-90 */ + +int +sym_init() /* 2-19-90, initialize symbol table package */ +{ + create_ht( &symtab ) ; + if (symtab == NULL) + { + fprintf(stderr,"init_sym(): could not create hash table") ; + exit(1) ; + } + return(0) ; +} + +sym_nodeptr +sym_add( name ) +char * name ; +{ + sym_nodeptr new_sym_node(); + char **node_name() ; + sym_nodeptr *node_next() ; + return( symget( name, new_sym_node, node_name, node_next, symtab, 1 ) ) ; +} + +sym_nodeptr +sym_get( name ) +char * name ; +{ + sym_nodeptr new_sym_node(); + char **node_name() ; + sym_nodeptr *node_next() ; + return( symget( name, new_sym_node, node_name, node_next, symtab, 0 ) ) ; +} + +sym_nodeptr +new_sym_node() +{ + void * malloc() ; + sym_nodeptr p ; + p = (sym_nodeptr) malloc( sizeof( struct sym_node ) ) ; + p->name = NULL ; + p->next = NULL ; + + return( p ) ; +} + +char ** +node_name(p) +sym_nodeptr p ; +{ + char ** x ; + x = &(p->name) ; + return( x ) ; +} + +sym_nodeptr * +node_next(p) +sym_nodeptr p ; +{ + sym_nodeptr *x ; + x = &(p->next) ; + return( x ) ; +} + +int +show_entry(x) +sym_nodeptr x ; +{ + int i ; + if ( x == NULL ) return(0) ; + printf("Symbol table entry:\n") ; + printf("lexeme %s\n", x->name ) ; + printf(" dim %s\n", (x->dim==1?"M":(x->dim==2?"N":"O")) ) ; + printf(" ndims %d\n", x->ndims ) ; + for ( i = 0 ; i < x->ndims && i < 7 ; i++ ) + printf(" dim %d -> %s\n",i,(x->dims[i]==1?"M":(x->dims[i]==2?"N":"O")) ) ; + return(0) ; +} + +/* MEMORY LEAK !!!! -- this just abandons the old table and leaves on the heap. */ +/* The registry mechanism is not a long-running program and is not apt to + run into memory problems. Might want to fix this anyway, though, someday. */ +int +sym_forget() +{ + create_ht( &symtab ) ; + if (symtab == NULL) + { + fprintf(stderr,"init_sym(): could not create hash table") ; + exit(1) ; + } + return(0) ; +} + diff --git a/OpenFAST/modules/openfast-registry/src/sym.h b/OpenFAST/modules/openfast-registry/src/sym.h new file mode 100644 index 000000000..71de45686 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/sym.h @@ -0,0 +1,97 @@ +/*********************************************************************** + + COPYRIGHT + + The following is a notice of limited availability of the code and + Government license and disclaimer which must be included in the + prologue of the code and in all source listings of the code. + + Copyright notice + (c) 1977 University of Chicago + + Permission is hereby granted to use, reproduce, prepare + derivative works, and to redistribute to others at no charge. If + you distribute a copy or copies of the Software, or you modify a + copy or copies of the Software or any portion of it, thus forming + a work based on the Software and make and/or distribute copies of + such work, you must meet the following conditions: + + a) If you make a copy of the Software (modified or verbatim) + it must include the copyright notice and Government + license and disclaimer. + + b) You must cause the modified Software to carry prominent + notices stating that you changed specified portions of + the Software. + + This software was authored by: + + Argonne National Laboratory + J. Michalakes: (630) 252-6646; email: michalak@mcs.anl.gov + Mathematics and Computer Science Division + Argonne National Laboratory, Argonne, IL 60439 + + ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES + OF ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, + AND OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A + CONTRACT WITH THE DEPARTMENT OF ENERGY. + + GOVERNMENT LICENSE AND DISCLAIMER + + This computer code material was prepared, in part, as an account + of work sponsored by an agency of the United States Government. + The Government is granted for itself and others acting on its + behalf a paid-up, nonexclusive, irrevocable worldwide license in + this data to reproduce, prepare derivative works, distribute + copies to the public, perform publicly and display publicly, and + to permit others to do so. NEITHER THE UNITED STATES GOVERNMENT + NOR ANY AGENCY THEREOF, NOR THE UNIVERSITY OF CHICAGO, NOR ANY OF + THEIR EMPLOYEES, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR + ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, + COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, + PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD + NOT INFRINGE PRIVATELY OWNED RIGHTS. + +***************************************************************************/ +#ifndef SYM_H +#define SYM_H + +/* file: sym.h + + Header info for symbol table module. + +*/ + +typedef struct sym_node * sym_nodeptr ; + +struct sym_node +{ + char * name ; /* lexeme */ + sym_nodeptr next ; /* pointer to next node in symbol table */ +/* fields that are associated with dimension declaration constants */ + unsigned char dim ; +/* fields that are associated with arrays */ + int ndims ; + int MDEX ; /* which index is the M dimension */ + int NDEX ; /* which index is the N dimension */ + unsigned char dims[7] ; + char dimname[7][64] ; +/* name of temporary variable associated with string. variable */ + char varx[32] ; +/* name of core association, July 2004 */ + char core_name[64] ; +/* internal name of variable associated with dataname entry, July 2004 */ + char internal_name[64] ; +/* fields associated with integer scalar variables */ + unsigned long info ; + unsigned long assigned ; /* pointer to assignment statement */ + unsigned long thisif ; + int iflev ; + int marked ; /* general purpose marker */ +} ; + +sym_nodeptr sym_add() ; +sym_nodeptr sym_get() ; +int sym_forget(); + +#endif diff --git a/OpenFAST/modules/openfast-registry/src/symtab_gen.c b/OpenFAST/modules/openfast-registry/src/symtab_gen.c new file mode 100644 index 000000000..944ce461b --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/symtab_gen.c @@ -0,0 +1,208 @@ +/* symtab.c + +Symbol Table Handler -- Generic + +The routine symget() returns a pointer to a C structure matching a +given lexeme. If the lexeme does not already exist in the symbol +table, the routine will create a new symbol structure, store it, and +then return a pointer to the newly created structure. + +It is up to the calling module to declare the symbol structure as +well as several routines for manipulating the symbol structure. The +routines are passed to symget as pointers. + + name type description + + newnode() *char returns a pointer to a symbol structure. + + nodename() **char retrieves the lexeme name from a symbol + structure, returned as a pointer to a + character array. + + nodenext() **char retrieves pointer to the next field of + the symbol structure (the next field + is itself a pointer to a symbol structure) + +For a sample main or calling program see the end of this file. + +**** + REVISED 2-19-90. Added code to make hashtable interchangible. + new routine: create_ht() creates new hashtable + rev routine: symget() added parameter to pass hash table +*/ + +#include <stdio.h> +#include <string.h> +#ifndef _WIN32 +# include <strings.h> +#endif + +#include "protos.h" + +#define HASHSIZE 1024 + +/* commented out 2-29-90 +static char * symtab[HASHSIZE] ; +*/ + +void * malloc() ; +void * calloc() ; + +char * symget(name,newnode,nodename,nodenext,symtab,flag) +char *name ; +char *(*newnode)(), **(*nodename)(), **(*nodenext)() ; +char *symtab[] ; +int flag ; /* 1 is create if not there, 0 return NULL if not there */ +{ + int index ; + int found ; + register char *s ; + register char *t ; + char **x ; + char *p ; + + index = hash( name ) ; + p = symtab[index] ; + found = 0 ; + + while (p) { + s = name ; + t = *(*nodename)(p) ; + while (*s && *t && *s == *t ) { + s++ ; + t++ ; + } + if (!*s && !*t) { + found = 1 ; + break ; + } + p = *(*nodenext)(p) ; + } + + if (!found ) { + if (flag ) { + p = (*newnode)() ; + x = (*nodename)(p) ; + *x = (char *) malloc(strlen(name)+1) ; + strcpy(*x,name) ; + x = (*nodenext)(p) ; + *x = symtab[index] ; + symtab[index] = p ; + } else { + return(NULL) ; + } + } + + return(p) ; +} + +int +hash(name) +char * name ; +{ + register int result = 0 ; + register char * p = name ; + + while (*p) + result = 3*result + (int)*p++ ; + + result = result % HASHSIZE ; + while (result < 0) + result = result + HASHSIZE ; + return(result) ; +} + + +/* added 2-19-90, attaches a new hash table to pointer */ + +int +create_ht( p ) +char *** p ; +{ + *p = (char **) calloc( HASHSIZE , sizeof( char * ) ) ; + return(0) ; +} + + +/* added 4-15-92. + +This is a generic routine that, given a hash table pointer, +will traverse the hash table and apply a caller supplied +function to each entry + +*/ + +int +sym_traverse( ht, nodenext, f ) +char *ht[] ; +char **(*nodenext)() ; +void (*f)() ; +{ + char * p, **x ; + int i ; + for ( i = 0 ; i < HASHSIZE ; i++ ) + { + if ( ( p = ht[i] ) != NULL ) + { + while ( p ) + { + (*f)(p) ; + x = (*nodenext)(p) ; + p = *x ; + } + } + } + return(0) ; +} + +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ + +#ifdef COMMENTOUTSAMPLE +/* sample_main.c + + sample main program for symget() in the file symtab.c + +*/ + +#include <stdio.h> + +struct symnode { + char * name ; + struct symnode *next ; +} ; + +extern struct symnode * symget() ; + +struct symnode * +newnode() +{ + struct symnode * malloc() ; + return( malloc( sizeof( struct symnode ) ) ) ; +} + +char ** +nodename(p) +struct symnode *p ; +{ + char ** x ; + x = &(p->name) ; + return( x ) ; +} + +struct symnode ** +nodenext(p) +struct symnode *p ; +{ + struct symnode **x ; + x = &(p->next) ; + return( x ) ; +} + +#endif + +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ + diff --git a/OpenFAST/modules/openfast-registry/src/type.c b/OpenFAST/modules/openfast-registry/src/type.c new file mode 100644 index 000000000..310d7b793 --- /dev/null +++ b/OpenFAST/modules/openfast-registry/src/type.c @@ -0,0 +1,426 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#ifdef _WIN32 +# define rindex(X,Y) strrchr(X,Y) +# define index(X,Y) strchr(X,Y) +#else +# include <strings.h> +#endif + + +#include "registry.h" +#include "protos.h" +#include "data.h" + +int +init_type_table() +{ + node_t *p ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "integer" ) ; + strcpy( p->mapsto, "INTEGER(IntKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "intki" ) ; + strcpy( p->mapsto, "INTEGER(IntKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "b4ki" ) ; // this won't necesarially work as intended! + strcpy( p->mapsto, "INTEGER(IntKi)") ; + add_node_to_end ( p , &Type ) ; + + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "real" ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "real" ) ; + strcpy( p->mapsto, "REAL(ReKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "reki" ) ; + strcpy( p->mapsto, "REAL(ReKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "siki" ) ; + strcpy( p->mapsto, "REAL(SiKi)") ; + add_node_to_end ( p , &Type ) ; + + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "logical" ) ; + strcpy( p->mapsto, "LOGICAL") ; + add_node_to_end ( p , &Type ) ; + +#if 0 // bjj: would like to add this back to see if we can use this for pack/unpack +// these have to be handled individually because people can and will put lengths after them +// so can't make a generic type node here + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "character" ) ; + strcpy( p->mapsto, "CHARACTER") /**/ ; + add_node_to_end ( p , &Type ) ; +#endif + + + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "doubleprecision" ) ; + strcpy( p->mapsto, "REAL(DbKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "dbki" ) ; + strcpy( p->mapsto, "REAL(DbKi)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "r8ki" ) ; + strcpy( p->mapsto, "REAL(R8Ki)") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = DERIVED ; strcpy( p->name , "meshtype" ) ; + strcpy( p->mapsto, "MeshType") ; + add_node_to_end ( p , &Type ) ; + p = new_node(TYPE) ; p->type_type = DERIVED ; strcpy( p->name , "dll_type" ) ; + strcpy( p->mapsto, "DLL_Type") ; + add_node_to_end ( p , &Type ) ; + + return(0) ; +} + + + +/* return the C equivalent of the simple Fortran types, expects the "mapsto" strings, set above */ +char * +C_type( char * s ) +{ + if ( !strcmp( s, "INTEGER(IntKi)") ) return("int" ) ; + if ( !strcmp( s, "LOGICAL" ) ) return("bool" ) ; + if (!strcmp(s, "REAL(ReKi)")) return("float"); + if (!strcmp(s, "REAL(SiKi)")) return("float"); + if (!strcmp(s, "REAL(DbKi)")) return("double"); + if (!strcmp(s, "REAL(R8Ki)")) return("double"); + if (!strncmp(s, "CHARACTER", 9)) return("char"); + return("unknown") ; +} + +char * +c_types_binding( char *s ) +{ + char * str_to_return = "CHARACTER(KIND=C_CHAR), DIMENSION("; + char * name_with_extension; + + + if ( !strcmp( s, "INTEGER(IntKi)") ) return("INTEGER(KIND=C_INT)" ) ; + if ( !strcmp( s, "LOGICAL" ) ) return("LOGICAL(KIND=C_BOOL)") ; + if (!strcmp(s, "REAL(ReKi)")) return("REAL(KIND=C_FLOAT)"); + if (!strcmp(s, "REAL(SiKi)")) return("REAL(KIND=C_FLOAT)"); + if (!strcmp(s, "REAL(DbKi)")) return("REAL(KIND=C_DOUBLE)"); + if (!strcmp(s, "REAL(R8Ki)")) return("REAL(KIND=C_DOUBLE)"); + if (!strncmp(s, "CHARACTER", 9)) { // give the C string a length identical to the fortran type + char *p = s, buf[10]; + while ( *p ) { + if ( isdigit(*p) ) { + long val = strtol( p, &p, 10 ); + snprintf( buf, 10, "%lu", val ); + } else { + p++; + } + } + + + name_with_extension = malloc(strlen(str_to_return)+15); // memory leak, should take care of this ? //bjj: made it larger to account for size of buf + strcpy(name_with_extension, str_to_return); + strcat(name_with_extension, buf); + strcat(name_with_extension, ")"); + + return name_with_extension; + }; + return("unknown") ; +} + +char * +assoc_or_allocated( node_t * r ) +{ + + if ( is_pointer(r) ){ + return("ASSOCIATED"); + } else { + return("ALLOCATED"); + } + +} + +int +is_pointer( node_t * r ) +{ + + if ( sw_ccode && r->ndims > 0 && r->dims[0]->deferred ){ + if ( !strncmp( make_lower_temp(r-> name), "writeoutput", 11) ) { // this covers WriteOutput, WriteOutputHdr, and WriteOutputUnt + return( 0 ); // we're going to use these in the glue code, so these will be a special case + } else if (r->type->type_type == DERIVED){ + return(0); // derived types aren't passed through the c-interface, so don't make them pointers + } else { + return(1); + } + } else { + return( 0 ); + } + +} + + +int +set_state_dims ( char * dims , node_t * node ) +{ + int modifiers ; + node_t *d, *d1 ; + char *c ; + char dspec[NAMELEN] ; + int inbrace ; + + if ( dims == NULL ) dims = "-" ; + modifiers = 0 ; + node->ndims = 0 ; + node->boundary_array = 0 ; + + inbrace = 0 ; + node->subgrid = 0 ; + strcpy(dspec,"") ; + for ( c = dims ; *c ; c++ ) + { + if ( *c == '-' && ! inbrace ) + { + break ; + } + else if ( *c == '{' && ! inbrace ) + { + inbrace = 1 ; + continue ; + } + else if ( modifiers == 0 ) + { + if ( *c == '}' && inbrace ) { inbrace = 0 ; } + else { int n = strlen(dspec) ; dspec[n] = *c ; dspec[n+1]='\0' ; } + if ( inbrace ) { + continue ; + } + d1 = new_node(DIM) ; /* make a copy */ + if (( d = get_dim_entry ( dspec, 1 )) != NULL ) { + *d1 = *d ; + } else { + set_dim_len( dspec , d1 ) ; + } + node->dims[node->ndims++] = d1 ; + strcpy(dspec,"") ; + } + } + // check to make sure that if any dimension is deferred they all must be + + has_deferred_dim( node, 1 ) ; + + return (0) ; +} + +int +has_deferred_dim( node_t * node, int noisy ) +{ + int deferred, i ; + deferred = 0 ; + if ( node->ndims > 0 ) { + deferred = node->dims[0]->deferred ; + for ( i = 1 ; i < node->ndims ; i++ ) + { + if ( deferred != node->dims[i]->deferred ) { + if ( node->dims[i]->deferred ) { + if ( noisy ) fprintf(stderr, + "Registry warning: dimension %d of %s is allocatable while others are not.\n",i,node->name) ; + } else { + if ( noisy ) fprintf(stderr, + "Registry warning: dimension %d of %s is not allocatable while others are.\n",i,node->name) ; + } + } + if ( node->dims[i]->deferred ) deferred = 1 ; + } + } + return(deferred) ; +} + +#if 0 +node_t * +get_4d_entry ( char * name ) +{ + node_t *p ; + if ( name == NULL ) return (NULL) ; + for ( p = FourD ; p != NULL ; p = p->next4d ) + { + if ( !strcmp( p->name , name ) ) + { + return(p) ; + } + } + return(NULL) ; +} +#endif + +node_t * +get_type_entry ( char * typename ) +{ + node_t * retval ; + retval = get_entry(typename,Type) ; + return(retval) ; +} + +node_t * +get_modname_entry ( char * modname ) +{ + return(get_entry(modname,ModNames)) ; +} + +node_t * +get_rconfig_entry ( char * name ) +{ + node_t * p ; + if ((p=get_entry(name,Domain.fields))==NULL) return(NULL) ; + if (p->node_kind & RCONFIG) return(p) ; + return(NULL) ; +} + +node_t * +get_entry ( char * name , node_t * node ) +{ + node_t *p ; + char tmp[NAMELEN] ; + if ( name == NULL ) return (NULL) ; + if ( node == NULL ) return (NULL) ; + strcpy( tmp, name ) ; + make_lower_temp(tmp) ; + for ( p = node ; p != NULL ; p = p->next ) + { + if ( !strncmp( name , "character", 9 ) ) + { + if ( !strncmp( p->name , name, 9 ) ) + { + return(p) ; + } + } else { + if ( !strcmp( make_lower_temp(p->name) , tmp ) ) + { + return(p) ; + } + } + } + return(NULL) ; +} + +/* this gets the entry for the node even if it */ +/* is a derived data structure; does this by following */ +/* the fully specified f90 reference. For example: */ +/* "xa%f" for the field of derived type xa. */ +/* note it will also take care to ignore the _1 or _2 */ +/* suffixes from variables that have ntl > 1 */ +/* 11/10/2001 -- added use field; if the entry has a use */ +/* that starts with "dyn_" and use doesn't correspond to */ +/* that, skip that entry and continue */ + +node_t * +get_entry_r ( char * name , char * use , node_t * node ) +{ + node_t *p ; + char tmp[NAMELEN], *t1, *t2 ; + + if ( name == NULL ) return (NULL) ; + if ( node == NULL ) return (NULL) ; + + for ( p = node ; p != NULL ; p = p->next ) + { + strcpy( tmp, name ) ; + + /* first check for exact match */ + if ( !strcmp( p->name , tmp ) ) + { + return(p) ; + } + + t1 = NULL ; + if ((t1 = index(tmp,'%'))!= NULL ) *t1 = '\0' ; + + if ( p->ntl > 1 ) + { + if (( t2 = rindex( tmp , '_' )) != NULL ) + { + /* be sure it really is an integer that follows the _ and that */ + /* that is that is the last character */ + if ((*(t2+1) >= '0' && *(t2+1) <= '9') && *(t2+2)=='\0') *t2 = '\0' ; + } + } + + /* also allow _tend */ + if (( t2 = rindex( tmp , '_' )) != NULL ) { + if (!strcmp(t2,"_tend")) *t2 = '\0' ; + } + + /* also allow _tend */ + if (( t2 = rindex( tmp , '_' )) != NULL ) { + if (!strcmp(t2,"_old")) *t2 = '\0' ; + } + + if ( !strcmp( p->name , tmp ) ) + { + if ( t1 != NULL ) return( get_entry_r( t1+1 , use , p->type->fields ) ) ; + return(p) ; + } + } + return(NULL) ; +} + +node_t * +get_dimnode_for_coord ( node_t * node , int coord_axis ) +{ + int i ; + if ( node == NULL ) return(NULL) ; + for ( i = 0 ; i < node->ndims ; i++ ) + { + if ( node->dims[i] == NULL ) continue ; + if ( node->dims[i]->coord_axis == coord_axis ) + { + return(node->dims[i]) ; + } + } + return(NULL) ; +} + +int +get_index_for_coord ( node_t * node , int coord_axis ) +{ + int i ; + if ( node == NULL ) return( -1 ) ; + for ( i = 0 ; i < node->ndims ; i++ ) + { + if ( node->dims[i] == NULL ) continue ; + if ( node->dims[i]->coord_axis == coord_axis ) + { + return(i) ; + } + } + return(-1) ; +} + + +char * +set_mem_order( node_t * node , char * str , int n ) +{ + int i ; + node_t * p ; + + if ( str == NULL || node == NULL ) return(NULL) ; + strcpy(str,"") ; + if ( node->boundary_array ) + { + strcpy(str, "C") ; /* if this is called for a boundary array, just give it a */ + /* "reasonable" value and move on. */ + } + else + { + if ( node->ndims <= 0 ) + { + strcat(str,"0") ; return(str) ; + } + for ( i = 0 ; i < node->ndims && i < n ; i++ ) + { + p = node->dims[i] ; + switch( p->coord_axis ) + { + case(COORD_X) : strcat(str,"X") ; break ; + case(COORD_Y) : strcat(str,"Y") ; break ; + case(COORD_Z) : strcat(str,"Z") ; break ; + case(COORD_C) : strcat(str,"C") ; break ; + default : break ; + } + } + } + return(str) ; +} diff --git a/OpenFAST/modules/openfoam/CMakeLists.txt b/OpenFAST/modules/openfoam/CMakeLists.txt new file mode 100644 index 000000000..7d895a7cf --- /dev/null +++ b/OpenFAST/modules/openfoam/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/OpenFOAM_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/OpenFOAM_Types.f90 -ccode) +endif() + +# copy the header files to their build location +configure_file(src/OpenFOAM_Types.h ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) + +add_library(openfoamtypeslib src/OpenFOAM_Types.f90) +target_link_libraries(openfoamtypeslib nwtclibs) + +add_library(foamfastlib + src/OpenFOAM.f90 +) +target_link_libraries(foamfastlib openfoamtypeslib openfast_prelib nwtclibs) + +install(TARGETS openfoamtypeslib foamfastlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/OpenFOAM_Types.h + DESTINATION include +) diff --git a/OpenFAST/modules/openfoam/README.md b/OpenFAST/modules/openfoam/README.md new file mode 100644 index 000000000..0d5740074 --- /dev/null +++ b/OpenFAST/modules/openfoam/README.md @@ -0,0 +1,5 @@ +# OpenFOAM Module + +## Overview +This is a pseudo module used to couple OpenFAST with OpenFOAM; +it is considered part of the OpenFAST glue code. diff --git a/OpenFAST/modules/openfoam/src/OpenFOAM.f90 b/OpenFAST/modules/openfoam/src/OpenFOAM.f90 new file mode 100644 index 000000000..807f2644b --- /dev/null +++ b/OpenFAST/modules/openfoam/src/OpenFOAM.f90 @@ -0,0 +1,1210 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! Lidar module, a submodule 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 OpenFOAM + +! This is a pseudo module used to couple FAST v8 with OpenFOAM; it is considered part of the FAST glue code + USE FAST_Types +! USE OpenFOAM_IO + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: OpFM_Ver = ProgDesc( 'OpenFOAM Integration', '', '' ) + + +! ===================================================================================================" + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Init_OpFM ! Initialization routine + PUBLIC :: OpFM_SetInputs ! Glue-code routine to update inputs for OpenFOAM + PUBLIC :: OpFM_SetWriteOutput + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_OpFM( InitInp, p_FAST, AirDens, u_AD14, u_AD, initOut_AD, y_AD, y_ED, OpFM, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(OpFM_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + REAL(ReKi), INTENT(IN ) :: AirDens ! Air Density kg/m^3 + TYPE(AD14_InputType), INTENT(IN ) :: u_AD14 ! AeroDyn14 input data + TYPE(AD_InputType), INTENT(IN ) :: u_AD ! AeroDyn input data + TYPE(AD_OutputType), INTENT(IN ) :: y_AD ! AeroDyn output data (for mesh mapping) + TYPE(AD_InitOutputType), INTENT(IN ) :: initOut_AD ! AeroDyn InitOutput data (for BladeProps) + TYPE(ED_OutputType), INTENT(IN) :: y_ED ! The outputs of the structural dynamics module + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + TYPE(OpFM_InitOutputType), INTENT(INOUT) :: InitOut ! Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER(IntKi) :: k ! blade loop counter + + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Init_OpFM' + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + + ! number of velocity nodes in the interface: + + OpFM%p%NnodesVel = 1 ! always want the hub point + IF ( p_FAST%CompAero == Module_AD14 ) THEN ! AeroDyn 14 needs these velocities + CALL SetErrStat(ErrID_Fatal, 'Error AeroDyn14 is not supported yet with different number of velocity and force actuator nodes', ErrStat, ErrMsg, RoutineName) + RETURN + ELSEIF ( p_FAST%CompAero == Module_AD ) THEN ! AeroDyn 15 needs these velocities + OpFM%p%NumBl = SIZE( u_AD%BladeMotion, 1 ) + + OpFM%p%NnodesVel = OpFM%p%NnodesVel + y_AD%TowerLoad%NNodes ! tower nodes (if any) + DO k=1,OpFM%p%NumBl + OpFM%p%NnodesVel = OpFM%p%NnodesVel + u_AD%BladeMotion(k)%NNodes ! blade nodes + END DO + END IF + + ! number of force nodes in the interface + Opfm%p%NnodesForceBlade = InitInp%NumActForcePtsBlade + OpFM%p%NnodesForceTower = InitInp%NumActForcePtsTower + OpFM%p%NnodesForce = 1 + OpFM%p%NumBl * InitInp%NumActForcePtsBlade + OpFM%p%BladeLength = InitInp%BladeLength + + if ( y_AD%TowerLoad%NNodes > 0 ) then + OpFM%p%NMappings = OpFM%p%NumBl + 1 + OpFM%p%TowerHeight = InitInp%TowerHeight + OpFM%p%TowerBaseHeight = InitInp%TowerBaseHeight + OpFM%p%NnodesForce = OpFM%p%NnodesForce + InitInp%NumActForcePtsTower + else + OpFM%p%NMappings = OpFM%p%NumBl + end if + + ! air density, required for normalizing values sent to OpenFOAM: + OpFM%p%AirDens = AirDens + if ( EqualRealNos( AirDens, 0.0_ReKi ) ) & + CALL SetErrStat( ErrID_Fatal, 'Air density cannot be zero for OpenFOAM integration. Check that AeroDyn is used and that air density is set properly', ErrStat,ErrMsg,RoutineName) + + !............................................................................................ + ! Allocate arrays and define initial guesses for the OpenFOAM inputs here: + !............................................................................................ + CALL AllocPAry( OpFM%u%pxVel, OpFM%p%NnodesVel, 'pxVel', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pyVel, OpFM%p%NnodesVel, 'pyVel', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pzVel, OpFM%p%NnodesVel, 'pzVel', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pxForce, OpFM%p%NnodesForce, 'pxForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pyForce, OpFM%p%NnodesForce, 'pyForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pzForce, OpFM%p%NnodesForce, 'pzForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%xdotForce, OpFM%p%NnodesForce, 'xdotForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%ydotForce, OpFM%p%NnodesForce, 'ydotForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%zdotForce, OpFM%p%NnodesForce, 'zdotForce', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%pOrientation, 3*3*OpFM%p%NnodesForce, 'pOrientation', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%fx, OpFM%p%NnodesForce, 'fx', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%fy, OpFM%p%NnodesForce, 'fy', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%fz, OpFM%p%NnodesForce, 'fz', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%momentx, OpFM%p%NnodesForce, 'momentx', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%momenty, OpFM%p%NnodesForce, 'momenty', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%momentz, OpFM%p%NnodesForce, 'momentz', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%u%forceNodesChord, OpFM%p%NnodesForce, 'forceNodesChord', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + IF (InitInp%NumCtrl2SC > 0) THEN + CALL AllocPAry( OpFM%u%SuperController, InitInp%NumCtrl2SC, 'u%SuperController', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (ErrStat >= AbortErrLev) RETURN + + ! make sure the C versions are synced with these arrays + OpFM%u%c_obj%pxVel_Len = OpFM%p%NnodesVel; OpFM%u%c_obj%pxVel = C_LOC( OpFM%u%pxVel(1) ) + OpFM%u%c_obj%pyVel_Len = OpFM%p%NnodesVel; OpFM%u%c_obj%pyVel = C_LOC( OpFM%u%pyVel(1) ) + OpFM%u%c_obj%pzVel_Len = OpFM%p%NnodesVel; OpFM%u%c_obj%pzVel = C_LOC( OpFM%u%pzVel(1) ) + OpFM%u%c_obj%pxForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%pxForce = C_LOC( OpFM%u%pxForce(1) ) + OpFM%u%c_obj%pyForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%pyForce = C_LOC( OpFM%u%pyForce(1) ) + OpFM%u%c_obj%pzForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%pzForce = C_LOC( OpFM%u%pzForce(1) ) + OpFM%u%c_obj%xdotForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%xdotForce = C_LOC( OpFM%u%xdotForce(1) ) + OpFM%u%c_obj%ydotForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%ydotForce = C_LOC( OpFM%u%ydotForce(1) ) + OpFM%u%c_obj%zdotForce_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%zdotForce = C_LOC( OpFM%u%zdotForce(1) ) + OpFM%u%c_obj%pOrientation_Len = OpFM%p%NnodesForce*3*3; OpFM%u%c_obj%pOrientation = C_LOC( OpFM%u%pOrientation(1) ) + OpFM%u%c_obj%fx_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%fx = C_LOC( OpFM%u%fx(1) ) + OpFM%u%c_obj%fy_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%fy = C_LOC( OpFM%u%fy(1) ) + OpFM%u%c_obj%fz_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%fz = C_LOC( OpFM%u%fz(1) ) + OpFM%u%c_obj%momentx_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%momentx = C_LOC( OpFM%u%momentx(1) ) + OpFM%u%c_obj%momenty_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%momenty = C_LOC( OpFM%u%momenty(1) ) + OpFM%u%c_obj%momentz_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%momentz = C_LOC( OpFM%u%momentz(1) ) + OpFM%u%c_obj%forceNodesChord_Len = OpFM%p%NnodesForce; OpFM%u%c_obj%forceNodesChord = C_LOC( OpFM%u%forceNodesChord(1) ) + if (InitInp%NumCtrl2SC > 0) then + OpFM%u%c_obj%SuperController_Len = InitInp%NumCtrl2SC + OpFM%u%c_obj%SuperController = C_LOC( OpFM%u%SuperController(1) ) + OpFM%u%SuperController = 0.0_ReKi + end if + + ! initialize the arrays: + call OpFM_CreateActForceBladeTowerNodes(OpFM%p, ErrStat2, ErrMsg2) !Creates the blade and tower nodes in radial and tower height co-ordinates + call OpFM_InterpolateForceNodesChord(initOut_AD, OpFM%p, OpFM%u, ErrStat2, ErrMsg2) !Interpolates the chord distribution to the force nodes + call OpFM_CreateActForceMotionsMesh( p_FAST, y_ED, InitInp, OpFM, ErrStat2, ErrMsg2) + + !............................................................................................ + ! Allocate arrays and set up mappings to point loads (for AD15 only): + ! (bjj: note that normally I'd put these things in the FAST_ModuleMapType, but I don't want + ! to add OpenFOAM integrations in the rest fo the code). + !............................................................................................ + ! Allocate space for mapping data structures + ALLOCATE( OpFM%m%ActForceLoads(OpFM%p%NMappings), OpFM%m%Line2_to_Line2_Loads(OpFM%p%NMappings), OpFM%m%Line2_to_Line2_Motions(OpFM%p%NMappings),STAT=ErrStat2) + ALLOCATE( OpFM%m%ActForceLoadsPoints(OpFM%p%NMappings), OpFM%m%Line2_to_Point_Loads(OpFM%p%NMappings), OpFM%m%Line2_to_Point_Motions(OpFM%p%NMappings),STAT=ErrStat2) + + do k=1,OpFM%p%NMappings + call MeshCopy ( SrcMesh = OpFM%m%ActForceMotions(k) & + , DestMesh = OpFM%m%ActForceLoads(k) & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , Force = .true. & + , Moment = .true. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + OpFM%m%ActForceLoads(k)%RemapFlag = .true. + call MeshCopy ( SrcMesh = OpFM%m%ActForceMotionsPoints(k) & + , DestMesh = OpFM%m%ActForceLoadsPoints(k) & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_OUTPUT & + , Force = .true. & + , Moment = .true. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + OpFM%m%ActForceLoadsPoints(k)%RemapFlag = .true. + end do + + ! create the mapping data structures: + DO k=1,OpFM%p%NumBl + IF (p_FAST%CompElast == Module_ED ) THEN + call MeshMapCreate( y_ED%BladeLn2Mesh(k), OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ); + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + ! call MeshMapCreate( BD%y(k)%BldMotion, OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ); + END IF + call MeshMapCreate( y_AD%BladeLoad(k), OpFM%m%ActForceLoads(k), OpFM%m%Line2_to_Line2_Loads(k), ErrStat2, ErrMsg2 ); + + call MeshMapCreate( OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k), OpFM%m%Line2_to_Point_Motions(k), ErrStat2, ErrMsg2 ); + call MeshMapCreate( OpFM%m%ActForceLoads(k), OpFM%m%ActForceLoadsPoints(k), OpFM%m%Line2_to_Point_Loads(k), ErrStat2, ErrMsg2 ); +! OpFM%m%ActForceLoads(k)%RemapFlag = .false. + END DO + + do k=OpFM%p%NumBl+1,OpFM%p%NMappings + call MeshMapCreate( y_ED%TowerLn2Mesh, OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ); + call MeshMapCreate( OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k), OpFM%m%Line2_to_Point_Motions(k), ErrStat2, ErrMsg2 ); + + if ( y_AD%TowerLoad%nnodes > 0 ) then ! we can have an input mesh on the tower without having an output mesh. + call MeshMapCreate( y_AD%TowerLoad, OpFM%m%ActForceLoads(k), OpFM%m%Line2_to_Line2_Loads(k), ErrStat2, ErrMsg2 ); + call MeshMapCreate( OpFM%m%ActForceLoads(k), OpFM%m%ActForceLoadsPoints(k), OpFM%m%Line2_to_Point_Loads(k), ErrStat2, ErrMsg2 ); +! OpFM%m%ActForceLoads(k)%RemapFlag = .false. + end if + + end do + + call SetOpFMPositions(p_FAST, u_AD14, u_AD, y_ED, OpFM) + OpFM%u%fx = 0.0_ReKi + OpFM%u%fy = 0.0_ReKi + OpFM%u%fz = 0.0_ReKi + + !............................................................................................ + ! Define system output initializations (set up mesh) here: + !............................................................................................ + CALL AllocPAry( OpFM%y%u, OpFM%p%NnodesVel, 'u', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%y%v, OpFM%p%NnodesVel, 'v', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocPAry( OpFM%y%w, OpFM%p%NnodesVel, 'w', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (InitInp%NumSC2Ctrl > 0) then + CALL AllocPAry( OpFM%y%SuperController, InitInp%NumSC2Ctrl, 'y%SuperController', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + IF (ErrStat >= AbortErrLev) RETURN + + ! make sure the C versions are synced with these arrays + OpFM%y%c_obj%u_Len = OpFM%p%NnodesVel; OpFM%y%c_obj%u = C_LOC( OpFM%y%u(1) ) + OpFM%y%c_obj%v_Len = OpFM%p%NnodesVel; OpFM%y%c_obj%v = C_LOC( OpFM%y%v(1) ) + OpFM%y%c_obj%w_Len = OpFM%p%NnodesVel; OpFM%y%c_obj%w = C_LOC( OpFM%y%w(1) ) + + if (InitInp%NumSC2Ctrl > 0) then + OpFM%y%c_obj%SuperController_Len = InitInp%NumSC2Ctrl + OpFM%y%c_obj%SuperController = C_LOC( OpFM%y%SuperController(1) ) + end if + + + + !............................................................................................ + ! Define initialization-routine output (including writeOutput array) here: + !............................................................................................ + + CALL AllocAry( InitOut%WriteOutputHdr, 3, 'WriteOutputHdr', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( InitOut%WriteOutputUnt, 3, 'WriteOutputUnt', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( OpFM%y%WriteOutput, 3, 'WriteOutput', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + InitOut%WriteOutputHdr(1) = 'Wind1VelX'; InitOut%WriteOutputUnt(1) = '(m/s)' + InitOut%WriteOutputHdr(2) = 'Wind1VelY'; InitOut%WriteOutputUnt(2) = '(m/s)' + InitOut%WriteOutputHdr(3) = 'Wind1VelZ'; InitOut%WriteOutputUnt(3) = '(m/s)' + OpFM%y%WriteOutput = 0.0_ReKi + + InitOut%Ver = OpFM_Ver + + RETURN + +END SUBROUTINE Init_OpFM +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE OpFM_SetInputs( p_FAST, p_AD14, u_AD14, y_AD14, u_AD, y_AD, y_ED, y_SrvD, OpFM, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(AD14_ParameterType), INTENT(IN) :: p_AD14 ! The parameters from AeroDyn14 (for mesh transfer with improperly set meshes) + TYPE(AD14_InputType), INTENT(IN) :: u_AD14 ! The input meshes (already calculated) from AeroDyn14 + TYPE(AD14_OutputType), INTENT(IN) :: y_AD14 ! The output meshes (already calculated) from AeroDyn14 + TYPE(AD_InputType), INTENT(IN) :: u_AD ! The input meshes (already calculated) from AeroDyn + TYPE(AD_OutputType), INTENT(IN) :: y_AD ! The output meshes (already calculated) from AeroDyn + TYPE(ED_OutputType), INTENT(IN) :: y_ED ! The outputs of the structural dynamics module + TYPE(SrvD_OutputType), INTENT(IN) :: y_SrvD ! The outputs of the ServoDyn module (control) + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_SetInputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! set the positions + call SetOpFMPositions(p_FAST, u_AD14, u_AD, y_ED, OpFM) + + ! set the forces + call SetOpFMForces(p_FAST, p_AD14, u_AD14, y_AD14, u_AD, y_AD, y_ED, OpFM, ErrStat2, ErrMsg2) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! set SuperController inputs + if (p_FAST%CompServo == Module_SrvD) then + if (allocated(y_SrvD%SuperController).and. associated(OpFM%u%SuperController)) OpFM%u%SuperController = y_SrvD%SuperController + end if + + +END SUBROUTINE OpFM_SetInputs +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetOpFMPositions(p_FAST, u_AD14, u_AD, y_ED, OpFM) + + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + TYPE(AD14_InputType), INTENT(IN) :: u_AD14 ! The input meshes (already calculated) from AeroDyn14 + TYPE(AD_InputType), INTENT(IN) :: u_AD ! The input meshes (already calculated) from AeroDyn + TYPE(ED_OutputType), INTENT(IN) :: y_ED ! The outputs of the structural dynamics module + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! FAST parameter data + + + ! Local variables: + + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: J ! Loops through nodes / elements. + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: Node ! Node number for blade/node on mesh + + + ! Do the Velocity (AeroDyn) nodes first + !------------------------------------------------------------------------------------------------- + Node = 1 ! displaced hub position + OpFM%u%pxVel(Node) = y_ED%HubPtMotion%Position(1,1) + y_ED%HubPtMotion%TranslationDisp(1,1) + OpFM%u%pyVel(Node) = y_ED%HubPtMotion%Position(2,1) + y_ED%HubPtMotion%TranslationDisp(2,1) + OpFM%u%pzVel(Node) = y_ED%HubPtMotion%Position(3,1) + y_ED%HubPtMotion%TranslationDisp(3,1) + + + ! blade nodes + DO K = 1,SIZE(u_AD%BladeMotion) + DO J = 1,u_AD%BladeMotion(k)%Nnodes + + Node = Node + 1 + OpFM%u%pxVel(Node) = u_AD%BladeMotion(k)%TranslationDisp(1,j) + u_AD%BladeMotion(k)%Position(1,j) + OpFM%u%pyVel(Node) = u_AD%BladeMotion(k)%TranslationDisp(2,j) + u_AD%BladeMotion(k)%Position(2,j) + OpFM%u%pzVel(Node) = u_AD%BladeMotion(k)%TranslationDisp(3,j) + u_AD%BladeMotion(k)%Position(3,j) + + END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements + END DO !K = 1,p%NumBl + + if (OpFM%p%NMappings .gt. OpFM%p%NumBl) then + ! tower nodes + DO J=1,u_AD%TowerMotion%nnodes + Node = Node + 1 + OpFM%u%pxVel(Node) = u_AD%TowerMotion%TranslationDisp(1,J) + u_AD%TowerMotion%Position(1,J) + OpFM%u%pyVel(Node) = u_AD%TowerMotion%TranslationDisp(2,J) + u_AD%TowerMotion%Position(2,J) + OpFM%u%pzVel(Node) = u_AD%TowerMotion%TranslationDisp(3,J) + u_AD%TowerMotion%Position(3,J) + END DO + end if + + ! Do the Actuator Force nodes now + Node = 1 ! displaced hub position + OpFM%u%pxForce(Node) = OpFM%u%pxVel(Node) + OpFM%u%pyForce(Node) = OpFM%u%pyVel(Node) + OpFM%u%pzForce(Node) = OpFM%u%pzVel(Node) + OpFM%u%pOrientation((Node-1)*9 + 1) = y_ED%HubPtMotion%Orientation(1,1,1) + OpFM%u%pOrientation((Node-1)*9 + 2) = y_ED%HubPtMotion%Orientation(2,1,1) + OpFM%u%pOrientation((Node-1)*9 + 3) = y_ED%HubPtMotion%Orientation(3,1,1) + OpFM%u%pOrientation((Node-1)*9 + 4) = y_ED%HubPtMotion%Orientation(1,2,1) + OpFM%u%pOrientation((Node-1)*9 + 5) = y_ED%HubPtMotion%Orientation(2,2,1) + OpFM%u%pOrientation((Node-1)*9 + 6) = y_ED%HubPtMotion%Orientation(3,2,1) + OpFM%u%pOrientation((Node-1)*9 + 7) = y_ED%HubPtMotion%Orientation(1,3,1) + OpFM%u%pOrientation((Node-1)*9 + 8) = y_ED%HubPtMotion%Orientation(2,3,1) + OpFM%u%pOrientation((Node-1)*9 + 9) = y_ED%HubPtMotion%Orientation(3,3,1) + + + DO K = 1,OpFM%p%NumBl + ! mesh mapping from line2 mesh to point mesh + IF (p_FAST%CompElast == Module_ED ) THEN + call Transfer_Line2_to_Line2( y_ED%BladeLn2Mesh(k), OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ) + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + ! call Transfer_Line2_to_Point( BD%y(k)%BldMotion, OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ) + END IF + call Transfer_Line2_to_Point( OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k), OpFM%m%Line2_to_Point_Motions(k), ErrStat2, ErrMsg2 ) + + + DO J = 1, OpFM%p%NnodesForceBlade + Node = Node + 1 + OpFM%u%pxForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(1,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(1,J) + OpFM%u%pyForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(2,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(2,J) + OpFM%u%pzForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(3,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(3,J) + OpFM%u%xdotForce(Node) = OpFM%m%ActForceMotionsPoints(k)%TranslationVel(1,J) + OpFM%u%ydotForce(Node) = OpFM%m%ActForceMotionsPoints(k)%TranslationVel(2,J) + OpFM%u%zdotForce(Node) = OpFM%m%ActForceMotionsPoints(k)%TranslationVel(3,J) + OpFM%u%pOrientation((Node-1)*9 + 1) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,1,J) + OpFM%u%pOrientation((Node-1)*9 + 2) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,1,J) + OpFM%u%pOrientation((Node-1)*9 + 3) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,1,J) + OpFM%u%pOrientation((Node-1)*9 + 4) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,2,J) + OpFM%u%pOrientation((Node-1)*9 + 5) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,2,J) + OpFM%u%pOrientation((Node-1)*9 + 6) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,2,J) + OpFM%u%pOrientation((Node-1)*9 + 7) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,3,J) + OpFM%u%pOrientation((Node-1)*9 + 8) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,3,J) + OpFM%u%pOrientation((Node-1)*9 + 9) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,3,J) + END DO + + END DO + + DO K = OpFM%p%NumBl+1,OpFM%p%NMappings + + call Transfer_Line2_to_Line2( y_ED%TowerLn2Mesh, OpFM%m%ActForceMotions(k), OpFM%m%Line2_to_Line2_Motions(k), ErrStat2, ErrMsg2 ) + call Transfer_Line2_to_Point( OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k), OpFM%m%Line2_to_Point_Motions(k), ErrStat2, ErrMsg2 ) + + DO J=1,OpFM%p%NnodesForceTower + Node = Node + 1 + OpFM%u%pxForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(1,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(1,J) + OpFM%u%pyForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(2,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(2,J) + OpFM%u%pzForce(Node) = OpFM%m%ActForceMotionsPoints(k)%Position(3,J) + OpFM%m%ActForceMotionsPoints(k)%TranslationDisp(3,J) + OpFM%u%pOrientation((Node-1)*9 + 1) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,1,J) + OpFM%u%pOrientation((Node-1)*9 + 2) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,1,J) + OpFM%u%pOrientation((Node-1)*9 + 3) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,1,J) + OpFM%u%pOrientation((Node-1)*9 + 4) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,2,J) + OpFM%u%pOrientation((Node-1)*9 + 5) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,2,J) + OpFM%u%pOrientation((Node-1)*9 + 6) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,2,J) + OpFM%u%pOrientation((Node-1)*9 + 7) = OpFM%m%ActForceMotionsPoints(k)%Orientation(1,3,J) + OpFM%u%pOrientation((Node-1)*9 + 8) = OpFM%m%ActForceMotionsPoints(k)%Orientation(2,3,J) + OpFM%u%pOrientation((Node-1)*9 + 9) = OpFM%m%ActForceMotionsPoints(k)%Orientation(3,3,J) + + END DO + + END DO + + +END SUBROUTINE SetOpFMPositions +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetOpFMForces(p_FAST, p_AD14, u_AD14, y_AD14, u_AD, y_AD, y_ED, OpFM, ErrStat, ErrMsg) + + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + TYPE(AD14_ParameterType), INTENT(IN) :: p_AD14 ! The input meshes (already calculated) from AeroDyn14 + TYPE(AD14_InputType), INTENT(IN) :: u_AD14 ! The input meshes (already calculated) from AeroDyn14 + TYPE(AD14_OutputType), INTENT(IN) :: y_AD14 ! The output meshes (already calculated) from AeroDyn14 + TYPE(AD_InputType), INTENT(IN) :: u_AD ! The input meshes (already calculated) from AeroDyn + TYPE(AD_OutputType), INTENT(IN) :: y_AD ! The output meshes (already calculated) from AeroDyn + TYPE(ED_OutputType), INTENT(IN) :: y_ED ! The outputs of the structural dynamics module + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! FAST parameter data + !TYPE(FAST_MiscVarType), INTENT(IN ) :: m_FAST ! misc FAST data, including inputs from external codes like Simulink + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables: + REAL(ReKi) :: dRforceNodes ! Uniform distance between two consecutive blade force nodes + REAL(ReKi) :: dHforceNodes ! Uniform distance between two consecutive tower force nodes + + INTEGER(IntKi) :: J ! Loops through nodes / elements + INTEGER(IntKi) :: K ! Loops through blades. + INTEGER(IntKi) :: Node ! Node number for blade/node on mesh +#ifdef DEBUG_OPENFOAM + INTEGER(IntKi) :: actForcesFile, aerodynForcesFile ! Unit numbers for files containing actuator forces and aerodyn forces +#endif + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'SetOpFMForces' + + ErrStat = ErrID_None + ErrMsg = '' + + !------------------------------------------------------------------------------------------------- + Node = 1 ! undisplaced hub position (no aerodynamics computed here) + OpFM%u%fx(Node) = 0.0_ReKi + OpFM%u%fy(Node) = 0.0_ReKi + OpFM%u%fz(Node) = 0.0_ReKi + + !....................... + ! blade nodes + !....................... + +#ifdef DEBUG_OPENFOAM + CALL GetNewUnit( aerodynForcesFile ) + open(unit=aerodynForcesFile,file='fast_aerodyn_velocity_forces.csv') + write(aerodynForcesFile,*) '#x, y, z, fx, fy, fz' + + CALL GetNewUnit( actForcesFile ) + open(unit=actForcesFile,file='fast_actuator_forces.csv') + write(actForcesFile,*) '#x, y, z, fx, fy, fz' +#endif + + DO K = 1,OpFM%p%NumBl + +#ifdef DEBUG_OPENFOAM + DO J = 1,u_AD%BladeMotion(k)%NNodes + write(aerodynForcesFile,*) u_AD%BladeMotion(k)%TranslationDisp(1,j) + u_AD%BladeMotion(k)%Position(1,j), ', ', u_AD%BladeMotion(k)%TranslationDisp(2,j) + u_AD%BladeMotion(k)%Position(2,j), ', ', u_AD%BladeMotion(k)%TranslationDisp(3,j) + u_AD%BladeMotion(k)%Position(3,j), ', ', OpFM%y%u(1 + (k-1)*u_AD%BladeMotion(k)%NNodes + j), ', ', OpFM%y%v(1 + (k-1)*u_AD%BladeMotion(k)%NNodes + j), ', ', OpFM%y%w(1 + (k-1)*u_AD%BladeMotion(k)%NNodes + j), ', ', y_AD%BladeLoad(k)%Force(1,j), ', ', y_AD%BladeLoad(k)%Force(2,j), ', ', y_AD%BladeLoad(k)%Force(2,j) + END DO +#endif + + call Transfer_Line2_to_Line2( y_AD%BladeLoad(k), OpFM%m%ActForceLoads(k), OpFM%m%Line2_to_Line2_Loads(k), ErrStat2, ErrMsg2, u_AD%BladeMotion(k), OpFM%m%ActForceMotions(k) ) + call Transfer_Line2_to_Point( OpFM%m%ActForceLoads(k), OpFM%m%ActForceLoadsPoints(k), OpFM%m%Line2_to_Point_Loads(k), ErrStat2, ErrMsg2, OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k) ) + + DO J = 1, OpFM%p%NnodesForceBlade + Node = Node + 1 + OpFM%u%fx(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(1,j) + OpFM%u%fy(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(2,j) + OpFM%u%fz(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(3,j) + OpFM%u%momentx(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(1,j) + OpFM%u%momenty(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(2,j) + OpFM%u%momentz(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(3,j) + +#ifdef DEBUG_OPENFOAM + write(actForcesFile,*) OpFM%u%pxForce(Node), ', ', OpFM%u%pyForce(Node), ', ', OpFM%u%pzForce(Node), ', ', OpFM%u%fx(Node), ', ', OpFM%u%fy(Node), ', ', OpFM%u%fz(Node), ', ' +#endif + + END DO + + END DO !K = 1,OpFM%p%NumBl + + !....................... + ! tower nodes + !....................... + + ! mesh mapping from line2 mesh to point mesh + DO K = OpFM%p%NumBl+1,OpFM%p%NMappings + +#ifdef DEBUG_OPENFOAM + DO J = 1,u_AD%TowerMotion%NNodes + write(aerodynForcesFile,*) u_AD%TowerMotion%TranslationDisp(1,j) + u_AD%TowerMotion%Position(1,j), ', ', u_AD%TowerMotion%TranslationDisp(2,j) + u_AD%TowerMotion%Position(2,j), ', ', u_AD%TowerMotion%TranslationDisp(3,j) + u_AD%TowerMotion%Position(3,j), ', ', OpFM%y%u(1 + OpFM%p%NumBl*u_AD%BladeMotion(k)%NNodes + j), ', ', OpFM%y%v(1 + OpFM%p%NumBl*u_AD%BladeMotion(k)%NNodes + j), ', ', OpFM%y%w(1 + OpFM%p%NumBl*u_AD%BladeMotion(k)%NNodes + j), ', ', y_AD%TowerLoad%Force(1,j), ', ', y_AD%TowerLoad%Force(2,j), ', ', y_AD%TowerLoad%Force(2,j) + END DO +#endif + + call Transfer_Line2_to_Line2( y_AD%TowerLoad, OpFM%m%ActForceLoads(k), OpFM%m%Line2_to_Line2_Loads(k), ErrStat2, ErrMsg2, u_AD%TowerMotion, OpFM%m%ActForceMotions(k) ) + call Transfer_Line2_to_Point( OpFM%m%ActForceLoads(k), OpFM%m%ActForceLoadsPoints(k), OpFM%m%Line2_to_Point_Loads(k), ErrStat2, ErrMsg2, OpFM%m%ActForceMotions(k), OpFM%m%ActForceMotionsPoints(k) ) + + DO J=1,OpFM%p%NnodesForceTower + Node = Node + 1 + OpFM%u%fx(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(1,j) + OpFM%u%fy(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(2,j) + OpFM%u%fz(Node) = OpFM%m%ActForceLoadsPoints(k)%Force(3,j) + OpFM%u%momentx(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(1,j) + OpFM%u%momenty(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(2,j) + OpFM%u%momentz(Node) = OpFM%m%ActForceLoadsPoints(k)%Moment(3,j) + +#ifdef DEBUG_OPENFOAM + write(actForcesFile,*) OpFM%u%pxForce(Node), ', ', OpFM%u%pyForce(Node), ', ', OpFM%u%pzForce(Node), ', ', OpFM%u%fx(Node), ', ', OpFM%u%fy(Node), ', ', OpFM%u%fz(Node), ', ' +#endif + END DO + +#ifdef DEBUG_OPENFOAM + close(aerodynForcesFile) + close(actForcesFile) +#endif + + END DO + +END SUBROUTINE SetOpFMForces +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE OpFM_SetWriteOutput( OpFM ) +!.................................................................................................................................. + + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + + ! set the hub-height wind speeds + IF ( ALLOCATED( OpFM%y%WriteOutput ) ) THEN + IF ( ASSOCIATED( OpFM%y%u ) ) then + OpFM%y%WriteOutput(1) = OpFM%y%u(1) + OpFM%y%WriteOutput(2) = OpFM%y%v(1) + OpFM%y%WriteOutput(3) = OpFM%y%w(1) + END IF + END IF + + + +END SUBROUTINE OpFM_SetWriteOutput +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE OpFM_CreateActForceMotionsMesh( p_FAST, y_ED, InitIn_OpFM, OpFM, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(ED_OutputType), INTENT(IN) :: y_ED ! The outputs of the structural dynamics module + TYPE(OpFM_InitInputType), INTENT(IN ) :: InitIn_OpFM ! InitInp data for the OpenFOAM integration module + TYPE(OpenFOAM_Data), INTENT(INOUT) :: OpFM ! data for the OpenFOAM integration module + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: tmpActForceMotionsMesh !< temporary mesh for interpolating orientation to actuator force points [-] + INTEGER(IntKi) :: k ! blade loop counter + INTEGER(IntKi) :: i,j ! node counter + + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_CreateActForceMotionsMesh' + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate space for mapping data structures + ALLOCATE(tmpActForceMotionsMesh(OpFM%p%NMappings) , STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating force nodes mesh mapping types', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + CALL OpFM_CreateTmpActForceMotionsMesh( p_FAST, y_ED, OpFM%p, InitIn_OpFM, tmpActForceMotionsMesh, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (errStat >= AbortErrLev) return + + ALLOCATE(OpFM%m%ActForceMotions(OpFM%p%NMappings), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating force nodes mesh', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + ALLOCATE(OpFM%m%ActForceMotionsPoints(OpFM%p%NMappings), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating force nodes mesh', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + DO k=1,OpFM%p%NumBl + call MeshCreate ( BlankMesh = OpFM%m%ActForceMotions(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = OpFM%p%NnodesForceBlade & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ,RotationVel = .true. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + OpFM%m%ActForceMotions(k)%RemapFlag = .false. + + call MeshCreate ( BlankMesh = OpFM%m%ActForceMotionsPoints(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = OpFM%p%NnodesForceBlade & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ,RotationVel = .true. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + OpFM%m%ActForceMotions(k)%RemapFlag = .false. + + do j=1,OpFM%p%NnodesForceBlade + call MeshPositionNode(OpFM%m%ActForceMotions(k), j, tmpActForceMotionsMesh(k)%position(:,j), errStat2, errMsg2, & + orient=tmpActForceMotionsMesh(k)%Orientation(:,:,j) ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshPositionNode(OpFM%m%ActForceMotionsPoints(k), j, tmpActForceMotionsMesh(k)%position(:,j), errStat2, errMsg2, & + orient=tmpActForceMotionsMesh(k)%Orientation(:,:,j) ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call MeshConstructElement(OpFM%m%ActForceMotionsPoints(k), ELEMENT_POINT, errStat2, errMsg2, p1=j ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + ! create elements: + DO J = 2,OpFM%p%NnodesForceBlade + call MeshConstructElement ( Mesh = OpFM%m%ActForceMotions(k) & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + END DO ! J (blade nodes) + call MeshCommit(OpFM%m%ActForceMotions(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + call MeshCommit(OpFM%m%ActForceMotionsPoints(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + END DO + + DO k=OpFM%p%NumBl+1,OpFM%p%NMappings !Tower if present + call MeshCreate ( BlankMesh = OpFM%m%ActForceMotions(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = OpFM%p%NnodesForceTower & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ,RotationVel = .true. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + OpFM%m%ActForceMotions(k)%RemapFlag = .false. + + call MeshCreate ( BlankMesh = OpFM%m%ActForceMotionsPoints(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = OpFM%p%NnodesForceTower & + ,Orientation = .true. & + ,TranslationDisp = .true. & + ,TranslationVel = .true. & + ,RotationVel = .true. & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + OpFM%m%ActForceMotionsPoints(k)%RemapFlag = .false. + + do j=1,OpFM%p%NnodesForceTower + call MeshPositionNode(OpFM%m%ActForceMotions(k), j, tmpActForceMotionsMesh(k)%position(:,j), errStat2, errMsg2, & + orient=tmpActForceMotionsMesh(k)%Orientation(:,:,j) ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshPositionNode(OpFM%m%ActForceMotionsPoints(k), j, tmpActForceMotionsMesh(k)%position(:,j), errStat2, errMsg2, & + orient=tmpActForceMotionsMesh(k)%Orientation(:,:,j) ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + call MeshConstructElement(OpFM%m%ActForceMotionsPoints(k), ELEMENT_POINT, errStat2, errMsg2, p1=j ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + ! create elements: + DO J = 2,OpFM%p%NnodesForceTower + call MeshConstructElement ( Mesh = OpFM%m%ActForceMotions(k) & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + END DO ! J (tower nodes) + + call MeshCommit(OpFM%m%ActForceMotions(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + call MeshCommit(OpFM%m%ActForceMotionsPoints(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + END DO + + DO k=1,OpFM%p%NMappings + call MeshDestroy ( tmpActForceMotionsMesh(k), ErrStat2, ErrMsg2 ) + END DO + DEALLOCATE(tmpActForceMotionsMesh) + +END SUBROUTINE OpFM_CreateActForceMotionsMesh +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE OpFM_CreateTmpActForceMotionsMesh( p_FAST, y_ED, p_OpFM, InitIn_OpFM, tmpActForceMotions, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(ED_OutputType), INTENT(IN ) :: y_ED ! The outputs of the structural dynamics module + TYPE(OpFM_ParameterType), INTENT(IN ) :: p_OpFM ! data for the OpenFOAM integration module + TYPE(OpFM_InitInputType), INTENT(IN ) :: InitIn_OpFM ! InitInp data for the OpenFOAM integration module + TYPE(MeshType), INTENT(INOUT) :: tmpActForceMotions(:) ! temporary mesh to create the actuator force nodes + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: tmp_line2_to_point_Motions !< mapping data structure to convert orientation of structural nodes to actuator force nodes [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: tmp_StructModelMesh !< temporary mesh copying Structural model mesh + REAL(ReKi), DIMENSION(:,:), ALLOCATABLE :: forceNodePositions ! new positions for the force actuator nodes + INTEGER(IntKi) :: NumBl ! number of blades + INTEGER(IntKi) :: k ! blade loop counter + INTEGER(IntKi) :: i,j ! node counter + + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_CreateTmpActForceMotionsMesh' + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + ! Make a copy of the Structural model mesh with the reference orientation set to zero + ALLOCATE(tmp_StructModelMesh(p_OpFM%NMappings) , STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating temporary copy of ElastoDyn mesh type', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + CALL CreateTmpStructModelMesh(p_FAST, y_ED, p_OpFM, tmp_StructModelMesh, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Allocate space for mapping data structures + ALLOCATE( tmp_line2_to_point_Motions(p_OpFM%NMappings),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating temporary actuator force mesh mapping types', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + ! create meshes to map: + ALLOCATE(forceNodePositions(3,p_OpFM%NnodesForceBlade)) ! Allocate space to create new positions + DO k=1,p_OpFM%NumBl + call MeshCreate ( BlankMesh = tmpActForceMotions(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p_OpFM%NnodesForceBlade & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,force = .false. & + ,moment = .false. & + ,orientation = .true. & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + tmpActForceMotions(k)%RemapFlag = .false. + call CalcForceActuatorPositionsBlade(InitIn_OpFM, p_OpFM, tmp_StructModelMesh(k)%position, forceNodePositions, errStat2, errMsg2) + do j=1,p_OpFM%NnodesForceBlade + call MeshPositionNode(tmpActForceMotions(k), j, forceNodePositions(:,j), errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshConstructElement( tmpActForceMotions(k), ELEMENT_POINT, errStat2, errMsg2, p1=j ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + call MeshCommit(tmpActForceMotions(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + end do + DEALLOCATE(forceNodePositions) ! Free space + + ALLOCATE(forceNodePositions(3,p_OpFM%NnodesForceTower)) ! Allocate space to create new positions + DO k=p_OpFM%NumBl+1,p_OpFM%NMappings + call CalcForceActuatorPositionsTower(InitIn_OpFM, p_OpFM, tmp_StructModelMesh(k)%position, forceNodePositions, errStat2, errMsg2) + + call MeshCreate ( BlankMesh = tmpActForceMotions(k) & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p_OpFM%NnodesForceTower & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,force = .false. & + ,moment = .false. & + ,orientation = .true. & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + tmpActForceMotions(k)%RemapFlag = .false. + do j=1,p_OpFM%NnodesForceTower + call MeshPositionNode(tmpActForceMotions(k), j, forceNodePositions(:,j), errStat2, errMsg2) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + + call MeshConstructElement( tmpActForceMotions(k), ELEMENT_POINT, errStat2, errMsg2, p1=j ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + end do !j + + call MeshCommit(tmpActForceMotions(k), errStat2, errMsg2 ) + call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName ) + if (errStat >= AbortErrLev) return + END DO + DEALLOCATE(forceNodePositions) ! Free space + + ! create the mapping data structures: + DO k=1,p_OpFM%NumBl + call MeshMapCreate( tmp_StructModelMesh(k), tmpActForceMotions(k), tmp_line2_to_point_Motions(k), ErrStat2, ErrMsg2 ); + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + DO k=p_OpFM%NumBl+1,p_OpFM%NMappings + call MeshMapCreate( tmp_StructModelMesh(k), tmpActForceMotions(k), tmp_line2_to_point_Motions(k), ErrStat2, ErrMsg2 ); + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + ! Map the orientation + DO K = 1,p_OpFM%NMappings + ! mesh mapping from line2 mesh to point mesh + call Transfer_Line2_to_Point( tmp_StructModelMesh(k), tmpActForceMotions(k), tmp_line2_to_point_Motions(k), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END DO + + DO k=1,p_OpFM%NMappings + call MeshDestroy ( tmp_StructModelMesh(k), ErrStat2, ErrMsg2 ) + call MeshMapDestroy ( tmp_line2_to_point_Motions(k), ErrStat2, ErrMsg2 ) + END DO + DEALLOCATE(tmp_StructModelMesh) + DEALLOCATE(tmp_line2_to_point_Motions) + + RETURN + +END SUBROUTINE OpFM_CreateTmpActForceMotionsMesh +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CreateTmpStructModelMesh(p_FAST, y_ED, p_OpFM, tmpStructModelMesh, ErrStat, ErrMsg ) + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(ED_OutputType), INTENT(IN ) :: y_ED ! The outputs of the structural dynamics module + TYPE(OpFM_ParameterType), INTENT(IN ) :: p_OpFM ! Parameters of the OpenFOAM integration module + TYPE(MeshType), INTENT(INOUT) :: tmpStructModelMesh(:) ! temporary copy of structural model mesh + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + !Local variables + INTEGER(IntKi) :: nNodesStructModel ! Number of nodes (tower/blade) in the structural model mesh + + INTEGER(IntKi) :: i,j ! node counter + INTEGER(IntKi) :: k ! blade counter + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'CreateTmpStructModelMesh' + + + IF (p_FAST%CompElast == Module_ED ) THEN + + + DO K = 1,p_OpFM%NumBl + + nNodesStructModel = SIZE(y_ED%BladeLn2Mesh(K)%position(1,:)) + + CALL MeshCreate( BlankMesh = tmpStructModelMesh(K) & + , NNodes = nNodesStructModel & + , IOS = COMPONENT_OUTPUT & + , Orientation = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + tmpStructModelMesh(K)%RemapFlag = .false. + !For some reason, ElastoDyn keeps the last point as the blade/tower root + CALL MeshPositionNode ( tmpStructModelMesh(K), 1, y_ED%BladeLn2Mesh(K)%Position(:,nNodesStructModel), ErrStat2, ErrMsg2 ) + DO J = 1,nNodesStructModel-1 + CALL MeshPositionNode ( tmpStructModelMesh(K), J+1, y_ED%BladeLn2Mesh(K)%Position(:,J), ErrStat2, ErrMsg2 ) + END DO + + ! create elements: + DO J = 2,nNodesStructModel + + CALL MeshConstructElement ( Mesh = tmpStructModelMesh(K) & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + END DO ! J (blade nodes) + + ! that's our entire mesh: + CALL MeshCommit ( tmpStructModelMesh(K), ErrStat2, ErrMsg2 ) + + ! Copy the orientation + tmpStructModelMesh(K)%Orientation(:,:,1) = y_ED%BladeLn2Mesh(k)%RefOrientation(:,:,nNodesStructModel) + DO J=1,nNodesStructModel-1 + tmpStructModelMesh(K)%Orientation(:,:,J+1) = y_ED%BladeLn2Mesh(K)%RefOrientation(:,:,J) + END DO + + END DO + + DO K = p_OpFM%NumBl+1, p_OpFM%NMappings + + nNodesStructModel = SIZE(y_ED%TowerLn2Mesh%position(1,:)) + + CALL MeshCreate( BlankMesh = tmpStructModelMesh(K) & + , NNodes = nNodesStructModel & + , IOS = COMPONENT_OUTPUT & + , Orientation = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + tmpStructModelMesh(K)%RemapFlag = .false. + !For some reason, ElastoDyn keeps the last point as the blade/tower root + CALL MeshPositionNode ( tmpStructModelMesh(K), 1, y_ED%TowerLn2Mesh%Position(:,nNodesStructModel), ErrStat2, ErrMsg2 ) + DO J = 1,nNodesStructModel-1 + CALL MeshPositionNode ( tmpStructModelMesh(K), J+1, y_ED%TowerLn2Mesh%Position(:,J), ErrStat2, ErrMsg2 ) + END DO + + ! create elements: + DO J = 2,nNodesStructModel + + CALL MeshConstructElement ( Mesh = tmpStructModelMesh(K) & + , Xelement = ELEMENT_LINE2 & + , P1 = J-1 & ! node1 number + , P2 = J & ! node2 number + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) + + END DO ! J (blade nodes) + + ! that's our entire mesh: + CALL MeshCommit ( tmpStructModelMesh(K), ErrStat2, ErrMsg2 ) + + ! Copy the orientation + tmpStructModelMesh(K)%Orientation(:,:,1) = y_ED%TowerLn2Mesh%RefOrientation(:,:,nNodesStructModel) + DO J=1,nNodesStructModel-1 + tmpStructModelMesh(K)%Orientation(:,:,J+1) = y_ED%TowerLn2Mesh%RefOrientation(:,:,J) + END DO + + END DO + + + ELSEIF (p_FAST%CompElast == Module_BD ) THEN + + CALL SetErrStat(ErrID_Fatal, 'Error BeamDyn is not supported yet with OpenFOAM module', ErrStat, ErrMsg, RoutineName) + RETURN + + END IF + + RETURN +END SUBROUTINE CreateTmpStructModelMesh +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CalcForceActuatorPositionsBlade(InitIn_OpFM, p_OpFM, structPositions, forceNodePositions, ErrStat2, ErrMsg2) + + TYPE(OpFM_InitInputType), INTENT(IN ) :: InitIn_OpFM ! data for the OpenFOAM integration module + TYPE(OpFM_ParameterType), INTENT(IN ) :: p_OpFM ! data for the OpenFOAM integration module + REAL(ReKi), POINTER :: structPositions(:,:) ! structural model positions + REAL(ReKi), INTENT(INOUT) :: forceNodePositions(:,:) ! Array to store the newly created positions + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + + !Local variables + INTEGER(IntKi) :: nStructNodes ! Number of velocity nodes + REAL(ReKi), DIMENSION(:), ALLOCATABLE :: rStructNodes ! Distance of velocity nodes from the first node - Used as a parameter for curve fitting + INTEGER(IntKI) :: i ! Loop variables + INTEGER(IntKI) :: jLower ! Index of the struct node just smaller than the force node + REAL(ReKi) :: rInterp ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + + nStructNodes = SIZE(structPositions,2) + ALLOCATE(rStructNodes(nStructNodes), STAT=ErrStat2) + + ! Store the distance of the structural model nodes from the root into an array + rStructNodes(1) = 0.0 ! First node + rStructNodes(2:nStructNodes-1) = InitIn_OpFM%StructBldRnodes(:) + rStructNodes(nStructNodes) = p_OpFM%BladeLength + + ! Now calculate the positions of the force nodes based on interpolation + forceNodePositions(:,1) = structPositions(:,1) + DO I=2,p_OpFM%NnodesForceBlade-1 ! Calculate the position of the force nodes + do jLower = 1, (nStructNodes - 1) + if ((rStructNodes(jLower) - p_OpFM%forceBldRnodes(I))*(rStructNodes(jLower+1) - p_OpFM%forceBldRnodes(I)) .le. 0) then + exit + endif + end do + rInterp = (p_OpFM%forceBldRnodes(I) - rStructNodes(jLower))/(rStructNodes(jLower+1)-rStructNodes(jLower)) ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + forceNodePositions(:,I) = structPositions(:,jLower) + rInterp * (structPositions(:,jLower+1) - structPositions(:,jLower)) + END DO + forceNodePositions(:,p_OpFM%NnodesForceBlade) = structPositions(:,nStructNodes) + + DEALLOCATE(rStructNodes) + + RETURN + +END SUBROUTINE CalcForceActuatorPositionsBlade +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE CalcForceActuatorPositionsTower(InitIn_OpFM, p_OpFM, structPositions, forceNodePositions, ErrStat, ErrMsg) + + TYPE(OpFM_InitInputType), INTENT(IN ) :: InitIn_OpFM ! data for the OpenFOAM integration module + TYPE(OpFM_ParameterType), INTENT(IN ) :: p_OpFM ! data for the OpenFOAM integration module + REAL(ReKi), POINTER :: structPositions(:,:) ! structural model positions + REAL(ReKi), INTENT(INOUT) :: forceNodePositions(:,:) ! Array to store the newly created positions + INTEGER(IntKi) , intent(out) :: ErrStat ! temporary Error status of the operation + CHARACTER(ErrMsgLen) , intent(out) :: ErrMsg ! temporary Error message if ErrStat /= ErrID_None + + + !Local variables + INTEGER(IntKi) :: nStructNodes ! Number of velocity nodes + REAL(ReKi), DIMENSION(:), ALLOCATABLE :: hStructNodes ! Distance of velocity nodes from the first node - Used as a parameter for curve fitting + INTEGER(IntKI) :: i ! Loop variables + INTEGER(IntKI) :: jLower ! Index of the struct node just smaller than the force node + REAL(ReKi) :: hInterp ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + + nStructNodes = SIZE(structPositions,2) + ALLOCATE(hStructNodes(nStructNodes), STAT=ErrStat) + IF (ErrStat /= 0) then + ErrStat=ErrID_Fatal + ErrMsg = "error allocating hStructNodes" + return + ELSE + ErrStat = ErrID_None + ErrMsg = "" + END IF + + ! Store the distance of the structural model nodes from the root into an array + hStructNodes(1) = 0.0 ! First node + hStructNodes(2:nStructNodes-1) = InitIn_OpFM%StructTwrHnodes(:) + hStructNodes(nStructNodes) = p_OpFM%TowerHeight + + ! Now calculate the positions of the force nodes based on interpolation + forceNodePositions(:,1) = structPositions(:,1) + DO I=2,p_OpFM%NnodesForceTower-1 ! Calculate the position of the force nodes + do jLower = 1, (nStructNodes - 1) + if ((hStructNodes(jLower) - p_OpFM%forceTwrHnodes(I))*(hStructNodes(jLower+1) - p_OpFM%forceTwrHnodes(I)) .le. 0) then + exit + endif + enddo + hInterp = (p_OpFM%forceTwrHnodes(I) - hStructNodes(jLower))/(hStructNodes(jLower+1)-hStructNodes(jLower)) ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + forceNodePositions(:,I) = structPositions(:,jLower) + hInterp * (structPositions(:,jLower+1) - structPositions(:,jLower)) + END DO + forceNodePositions(:,p_OpFM%NnodesForceTower) = structPositions(:,nStructNodes) + DEALLOCATE(hStructNodes) + + RETURN + +END SUBROUTINE CalcForceActuatorPositionsTower + +SUBROUTINE OpFM_CreateActForceBladeTowerNodes(p_OpFM, ErrStat, ErrMsg) +!Creates the blade and tower nodes in radial and tower height co-ordinates + + TYPE(OpFM_ParameterType), INTENT(INOUT) :: p_OpFM ! data for the OpenFOAM integration module + INTEGER(IntKi) :: ErrStat ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg ! temporary Error message if ErrStat /= ErrID_None + + !Local variables + REAL(ReKi) :: dRforceNodes ! Uniform distance between two consecutive force nodes + INTEGER(IntKI) :: i ! Loop variables + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + + ErrStat = ErrID_None + ErrMsg = "" + + ! Line2 to Line2 mapping expects the destination mesh to be smaller than the source mesh for deformation mapping and larger than the source mesh for load mapping. This forces me to create nodes at the very ends of the blade. + + !Do the blade first + allocate(p_OpFM%forceBldRnodes(p_OpFM%NnodesForceBlade), stat=errStat2) + dRforceNodes = p_OpFM%BladeLength/(p_OpFM%NnodesForceBlade-1) + do i=1,p_OpFM%NnodesForceBlade-1 + p_OpFM%forceBldRnodes(i) = (i-1)*dRforceNodes + end do + p_OpFM%forceBldRnodes(p_OpFM%NnodesForceBlade) = p_OpFM%BladeLength + + + if (p_OpFM%NMappings .gt. p_OpFM%NumBl) then + !Do the tower now + allocate(p_OpFM%forceTwrHnodes(p_OpFM%NnodesForceTower), stat=errStat2) + dRforceNodes = p_OpFM%TowerHeight/(p_OpFM%NnodesForceTower-1) + do i=1,p_OpFM%NnodesForceTower-1 + p_OpFM%forceTwrHnodes(i) = (i-1)*dRforceNodes + end do + p_OpFM%forceTwrHnodes(p_OpFM%NnodesForceTower) = p_OpFM%TowerHeight + end if + + return + +END SUBROUTINE OpFM_CreateActForceBladeTowerNodes + +SUBROUTINE OpFM_InterpolateForceNodesChord(InitOut_AD, p_OpFM, u_OpFM, ErrStat, ErrMsg) + + !Interpolates the chord distribution to the force nodes + + TYPE(AD_InitOutputType), INTENT(IN ) :: InitOut_AD ! InitOut data for the OpenFOAM integration module + TYPE(OpFM_ParameterType), INTENT(IN ) :: p_OpFM ! Input data for the OpenFOAM integration module + TYPE(OpFM_InputType), INTENT(INOUT) :: u_OpFM ! Parameter data for the OpenFOAM integration module + INTEGER(IntKi) :: ErrStat ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg ! temporary Error message if ErrStat /= ErrID_None + + !Local variables + INTEGER(IntKI) :: i,k,node ! Loop variables + INTEGER(IntKI) :: nNodesBladeProps ! Number of nodes in the blade properties for a given blade + INTEGER(IntKI) :: nNodesTowerProps ! Number of nodes in the tower properties + INTEGER(IntKI) :: jLower ! Index of the blade properties node just smaller than the force node + REAL(ReKi) :: rInterp ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + + ErrStat = ErrID_None + ErrMsg = "" + + ! Set the chord for the hub node to be zero. Ideally, I'd like this to be the hub radius. Will figure this out later. + Node = 1 + u_OpFM%forceNodesChord(Node) = 0.0_ReKi + + ! The blades first + do k = 1, p_OpFM%NumBl + ! Calculate the chord at the force nodes based on interpolation + nNodesBladeProps = SIZE(InitOut_AD%BladeProps(k)%BlChord) + DO I=1,p_OpFM%NnodesForceBlade + Node = Node + 1 + do jLower = 1, (nNodesBladeProps - 1) + if ( (InitOut_AD%BladeProps(k)%BlSpn(jLower) - p_OpFM%forceBldRnodes(I))*(InitOut_AD%BladeProps(k)%BlSpn(jLower+1) - p_OpFM%forceBldRnodes(I)) .le. 0 ) then + exit + endif + enddo + if (jLower .lt. nNodesBladeProps) then + rInterp = (p_OpFM%forceBldRnodes(I) - InitOut_AD%BladeProps(k)%BlSpn(jLower))/(InitOut_AD%BladeProps(k)%BlSpn(jLower+1)-InitOut_AD%BladeProps(k)%BlSpn(jLower)) ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + u_OpFM%forceNodesChord(Node) = InitOut_AD%BladeProps(k)%BlChord(jLower) + rInterp * (InitOut_AD%BladeProps(k)%BlChord(jLower+1) - InitOut_AD%BladeProps(k)%BlChord(jLower)) + else + u_OpFM%forceNodesChord(Node) = InitOut_AD%BladeProps(k)%BlChord(nNodesBladeProps) !Work around for when the last node of the actuator mesh is slightly outside of the Aerodyn blade properties. Surprisingly this is not an issue with the tower. + end if + END DO + + + end do + + + ! The tower now + do k = p_OpFM%NumBl+1,p_OpFM%NMappings + nNodesTowerProps = SIZE(InitOut_AD%TwrElev) + ! Calculate the chord at the force nodes based on interpolation + DO I=1,p_OpFM%NnodesForceTower + Node = Node + 1 + do jLower = 1, (nNodesTowerProps - 1) + if ( (InitOut_AD%TwrElev(jLower) - p_OpFM%forceTwrHnodes(I)-p_OpFM%TowerBaseHeight)*(InitOut_AD%TwrElev(jLower+1) - p_OpFM%forceTwrHnodes(I)-p_OpFM%TowerBaseHeight) .le. 0) then + exit + endif + enddo + if (jLower .lt. nNodesTowerProps) then + rInterp = (p_OpFM%forceTwrHnodes(I)+p_OpFM%TowerBaseHeight - InitOut_AD%TwrElev(jLower))/(InitOut_AD%TwrElev(jLower+1)-InitOut_AD%TwrElev(jLower)) ! The location of this force node in (0,1) co-ordinates between the jLower and jLower+1 nodes + u_OpFM%forceNodesChord(Node) = InitOut_AD%TwrDiam(jLower) + rInterp * (InitOut_AD%TwrDiam(jLower+1) - InitOut_AD%TwrDiam(jLower)) + else + u_OpFM%forceNodesChord(Node) = InitOut_AD%TwrDiam(nNodesTowerProps) !Work around for when the last node of the actuator mesh is slightly outside of the Aerodyn tower properties. + end if + END DO + end do + +END SUBROUTINE OpFM_InterpolateForceNodesChord + +END MODULE OpenFOAM +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/openfoam/src/OpenFOAM_Registry.txt b/OpenFAST/modules/openfoam/src/OpenFOAM_Registry.txt new file mode 100644 index 000000000..f714a11e5 --- /dev/null +++ b/OpenFAST/modules/openfoam/src/OpenFOAM_Registry.txt @@ -0,0 +1,85 @@ +################################################################################################################################### +# Registry for OpenFOAM - CFD interface types in the FAST Modularization Framework +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + + +# ..... OpenFOAM_InitInputType data ....................................................................................................... +typedef OpenFOAM/OpFM InitInputType IntKi NumSC2Ctrl - - - "number of controller inputs [from supercontroller]" - +typedef ^ ^ IntKi NumCtrl2SC - - - "number of controller outputs [to supercontroller]" - +typedef ^ ^ IntKi NumActForcePtsBlade - - - "number of actuator line force points in blade" - +typedef ^ ^ IntKi NumActForcePtsTower - - - "number of actuator line force points in tower" - +typedef ^ ^ ReKi StructBldRNodes {:} - - "Radius to structural model analysis nodes relative to hub" +typedef ^ ^ ReKi StructTwrHNodes {:} - - "Location of variable-spaced structural model tower nodes (relative to the tower rigid base height)" +typedef ^ ^ ReKi BladeLength - - - "Blade length" meters +typedef ^ ^ ReKi TowerHeight - - - "Tower Height" meters +typedef ^ ^ ReKi TowerBaseHeight - - - "Tower Base Height" meters + + + + + +# ..... OpenFOAM_InitOutputType data ....................................................................................................... +# Define outputs from the initialization routine here: +typedef OpenFOAM/OpFM InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +# ..... MiscVars ................................................................................................................ +typedef OpenFOAM/OpFM OpFM_MiscVarType MeshType ActForceLoads {:} - - "line2 mesh for transferring AeroDyn distributed loads to OpenFOAM" - +typedef ^ ^ MeshType ActForceMotions {:} - - "line2 mesh for transferring AeroDyn distributed loads to OpenFOAM (needs translationDisp)" - +typedef ^ ^ MeshType ActForceMotionsPoints {:} - - "point mesh for transferring AeroDyn distributed loads to OpenFOAM (needs translationDisp)" - +typedef ^ ^ MeshType ActForceLoadsPoints {:} - - "point mesh for transferring AeroDyn distributed loads to OpenFOAM" - +typedef ^ ^ MeshMapType Line2_to_Line2_Loads {:} - - "mapping data structure to convert line2 loads to line2 loads" - +typedef ^ ^ MeshMapType Line2_to_Line2_Motions {:} - - "mapping data structure to convert line2 loads to line2 motions" - +typedef ^ ^ MeshMapType Line2_to_Point_Loads {:} - - "mapping data structure to convert line2 loads to point loads" - +typedef ^ ^ MeshMapType Line2_to_Point_Motions {:} - - "mapping data structure to convert line2 loads to point motions" - + + +# ..... Parameters ................................................................................................................ +typedef OpenFOAM/OpFM ParameterType ReKi AirDens - - - "Air density for normalization of loads sent to OpenFOAM" kg/m^3 +typedef OpenFOAM/OpFM ParameterType IntKi NumBl - - - "Number of blades" - +typedef OpenFOAM/OpFM ParameterType IntKi NMappings - - - "Number of mappings" - +typedef OpenFOAM/OpFM ParameterType IntKi NnodesVel - - - "number of velocity nodes on FAST v8-OpenFOAM interface" - +typedef OpenFOAM/OpFM ParameterType IntKi NnodesForce - - - "number of force nodes on FAST v8-OpenFOAM interface" - +typedef OpenFOAM/OpFM ParameterType IntKi NnodesForceBlade - - - "number of force nodes on FAST v8-OpenFOAM interface" - +typedef OpenFOAM/OpFM ParameterType IntKi NnodesForceTower - - - "number of force nodes on FAST v8-OpenFOAM interface" - +typedef ^ ^ ReKi forceBldRnodes {:} "Radial location of force nodes" - +typedef ^ ^ ReKi forceTwrHnodes {:} "Radial location of force nodes" - +typedef ^ ^ ReKi BladeLength - - - "Blade length (same for all blades)" "m" +typedef ^ ^ ReKi TowerHeight - - - "Tower height" "m" +typedef ^ ^ ReKi TowerBaseHeight - - - "Tower base height" "m" + + +# ..... OpenFOAM_InputType data ....................................................................................................... +typedef ^ InputType ReKi pxVel {:} - - "x position of velocity interface (Aerodyn) nodes" "m" +typedef ^ InputType ReKi pyVel {:} - - "y position of velocity interface (Aerodyn) nodes" "m" +typedef ^ InputType ReKi pzVel {:} - - "z position of velocity interface (Aerodyn) nodes" "m" +typedef ^ InputType ReKi pxForce {:} - - "x position of actuator force nodes" "m" +typedef ^ InputType ReKi pyForce {:} - - "y position of actuator force nodes" "m" +typedef ^ InputType ReKi pzForce {:} - - "z position of actuator force nodes" "m" +typedef ^ InputType ReKi xdotForce {:} - - "x velocity of actuator force nodes" "m/s" +typedef ^ InputType ReKi ydotForce {:} - - "y velocity of actuator force nodes" "m/s" +typedef ^ InputType ReKi zdotForce {:} - - "z velocity of actuator force nodes" "m/s" +typedef ^ InputType ReKi pOrientation {:} - - "Direction cosine matrix to transform vectors from global frame of reference to actuator force node frame of reference" - +typedef ^ InputType ReKi fx {:} - - "normalized x force at actuator force nodes" "N/kg/m^3" +typedef ^ InputType ReKi fy {:} - - "normalized y force at actuator force nodes" "N/kg/m^3" +typedef ^ InputType ReKi fz {:} - - "normalized z force at actuator force nodes" "N/kg/m^3" +typedef ^ InputType ReKi momentx {:} - - "normalized x moment at actuator force nodes" "Nm/kg/m^3" +typedef ^ InputType ReKi momenty {:} - - "normalized y moment at actuator force nodes" "Nm/kg/m^3" +typedef ^ InputType ReKi momentz {:} - - "normalized z moment at actuator force nodes" "Nm/kg/m^3" +typedef ^ InputType ReKi forceNodesChord {:} - - "chord distribution at the actuator force nodes" "m" +typedef ^ InputType ReKi SuperController {:} - - "inputs to the super controller (from the turbine controller)" - + +# ..... OpenFOAM_OutputType data ....................................................................................................... +typedef OpenFOAM/OpFM OutputType ReKi u {:} - - "U-component wind speed (in the X-direction) at interface nodes" m/s +typedef ^ OutputType ReKi v {:} - - "V-component wind speed (in the Y-direction) at interface nodes" m/s +typedef ^ OutputType ReKi w {:} - - "W-component wind speed (in the Z-direction) at interface nodes" m/s +typedef ^ OutputType ReKi SuperController {:} - - "outputs of the super controller (to the turbine controller)" - +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" diff --git a/OpenFAST/modules/openfoam/src/OpenFOAM_Types.f90 b/OpenFAST/modules/openfoam/src/OpenFOAM_Types.f90 new file mode 100644 index 000000000..d613cd232 --- /dev/null +++ b/OpenFAST/modules/openfoam/src/OpenFOAM_Types.f90 @@ -0,0 +1,5488 @@ +!STARTOFREGISTRYGENERATEDFILE 'OpenFOAM_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 +!********************************************************************************************************************************* +! OpenFOAM_Types +!................................................................................................................................. +! This file is part of OpenFOAM. +! +! 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 OpenFOAM. 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 OpenFOAM_Types +!--------------------------------------------------------------------------------------------------------------------------------- +!USE, INTRINSIC :: ISO_C_Binding +USE NWTC_Library +IMPLICIT NONE +! ========= OpFM_InitInputType_C ======= + TYPE, BIND(C) :: OpFM_InitInputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + INTEGER(KIND=C_INT) :: NumSC2Ctrl + INTEGER(KIND=C_INT) :: NumCtrl2SC + INTEGER(KIND=C_INT) :: NumActForcePtsBlade + INTEGER(KIND=C_INT) :: NumActForcePtsTower + TYPE(C_ptr) :: StructBldRNodes = C_NULL_PTR + INTEGER(C_int) :: StructBldRNodes_Len = 0 + TYPE(C_ptr) :: StructTwrHNodes = C_NULL_PTR + INTEGER(C_int) :: StructTwrHNodes_Len = 0 + REAL(KIND=C_FLOAT) :: BladeLength + REAL(KIND=C_FLOAT) :: TowerHeight + REAL(KIND=C_FLOAT) :: TowerBaseHeight + END TYPE OpFM_InitInputType_C + TYPE, PUBLIC :: OpFM_InitInputType + TYPE( OpFM_InitInputType_C ) :: C_obj + INTEGER(IntKi) :: NumSC2Ctrl !< number of controller inputs [from supercontroller] [-] + INTEGER(IntKi) :: NumCtrl2SC !< number of controller outputs [to supercontroller] [-] + INTEGER(IntKi) :: NumActForcePtsBlade !< number of actuator line force points in blade [-] + INTEGER(IntKi) :: NumActForcePtsTower !< number of actuator line force points in tower [-] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: StructBldRNodes => NULL() !< Radius to structural model analysis nodes relative to hub [-] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: StructTwrHNodes => NULL() !< Location of variable-spaced structural model tower nodes (relative to the tower rigid base height) [-] + REAL(ReKi) :: BladeLength !< Blade length [meters] + REAL(ReKi) :: TowerHeight !< Tower Height [meters] + REAL(ReKi) :: TowerBaseHeight !< Tower Base Height [meters] + END TYPE OpFM_InitInputType +! ======================= +! ========= OpFM_InitOutputType_C ======= + TYPE, BIND(C) :: OpFM_InitOutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: WriteOutputHdr = C_NULL_PTR + INTEGER(C_int) :: WriteOutputHdr_Len = 0 + TYPE(C_ptr) :: WriteOutputUnt = C_NULL_PTR + INTEGER(C_int) :: WriteOutputUnt_Len = 0 + END TYPE OpFM_InitOutputType_C + TYPE, PUBLIC :: OpFM_InitOutputType + TYPE( OpFM_InitOutputType_C ) :: C_obj + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE OpFM_InitOutputType +! ======================= +! ========= OpFM_MiscVarType_C ======= + TYPE, BIND(C) :: OpFM_MiscVarType_C + TYPE(C_PTR) :: object = C_NULL_PTR + END TYPE OpFM_MiscVarType_C + TYPE, PUBLIC :: OpFM_MiscVarType + TYPE( OpFM_MiscVarType_C ) :: C_obj + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: ActForceLoads !< line2 mesh for transferring AeroDyn distributed loads to OpenFOAM [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: ActForceMotions !< line2 mesh for transferring AeroDyn distributed loads to OpenFOAM (needs translationDisp) [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: ActForceMotionsPoints !< point mesh for transferring AeroDyn distributed loads to OpenFOAM (needs translationDisp) [-] + TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: ActForceLoadsPoints !< point mesh for transferring AeroDyn distributed loads to OpenFOAM [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: Line2_to_Line2_Loads !< mapping data structure to convert line2 loads to line2 loads [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: Line2_to_Line2_Motions !< mapping data structure to convert line2 loads to line2 motions [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: Line2_to_Point_Loads !< mapping data structure to convert line2 loads to point loads [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: Line2_to_Point_Motions !< mapping data structure to convert line2 loads to point motions [-] + END TYPE OpFM_MiscVarType +! ======================= +! ========= OpFM_ParameterType_C ======= + TYPE, BIND(C) :: OpFM_ParameterType_C + TYPE(C_PTR) :: object = C_NULL_PTR + REAL(KIND=C_FLOAT) :: AirDens + INTEGER(KIND=C_INT) :: NumBl + INTEGER(KIND=C_INT) :: NMappings + INTEGER(KIND=C_INT) :: NnodesVel + INTEGER(KIND=C_INT) :: NnodesForce + INTEGER(KIND=C_INT) :: NnodesForceBlade + INTEGER(KIND=C_INT) :: NnodesForceTower + TYPE(C_ptr) :: forceBldRnodes = C_NULL_PTR + INTEGER(C_int) :: forceBldRnodes_Len = 0 + TYPE(C_ptr) :: forceTwrHnodes = C_NULL_PTR + INTEGER(C_int) :: forceTwrHnodes_Len = 0 + REAL(KIND=C_FLOAT) :: BladeLength + REAL(KIND=C_FLOAT) :: TowerHeight + REAL(KIND=C_FLOAT) :: TowerBaseHeight + END TYPE OpFM_ParameterType_C + TYPE, PUBLIC :: OpFM_ParameterType + TYPE( OpFM_ParameterType_C ) :: C_obj + REAL(ReKi) :: AirDens !< Air density for normalization of loads sent to OpenFOAM [kg/m^3] + INTEGER(IntKi) :: NumBl !< Number of blades [-] + INTEGER(IntKi) :: NMappings !< Number of mappings [-] + INTEGER(IntKi) :: NnodesVel !< number of velocity nodes on FAST v8-OpenFOAM interface [-] + INTEGER(IntKi) :: NnodesForce !< number of force nodes on FAST v8-OpenFOAM interface [-] + INTEGER(IntKi) :: NnodesForceBlade !< number of force nodes on FAST v8-OpenFOAM interface [-] + INTEGER(IntKi) :: NnodesForceTower !< number of force nodes on FAST v8-OpenFOAM interface [-] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: forceBldRnodes => NULL() + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: forceTwrHnodes => NULL() + REAL(ReKi) :: BladeLength !< Blade length (same for all blades) [m] + REAL(ReKi) :: TowerHeight !< Tower height [m] + REAL(ReKi) :: TowerBaseHeight !< Tower base height [m] + END TYPE OpFM_ParameterType +! ======================= +! ========= OpFM_InputType_C ======= + TYPE, BIND(C) :: OpFM_InputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: pxVel = C_NULL_PTR + INTEGER(C_int) :: pxVel_Len = 0 + TYPE(C_ptr) :: pyVel = C_NULL_PTR + INTEGER(C_int) :: pyVel_Len = 0 + TYPE(C_ptr) :: pzVel = C_NULL_PTR + INTEGER(C_int) :: pzVel_Len = 0 + TYPE(C_ptr) :: pxForce = C_NULL_PTR + INTEGER(C_int) :: pxForce_Len = 0 + TYPE(C_ptr) :: pyForce = C_NULL_PTR + INTEGER(C_int) :: pyForce_Len = 0 + TYPE(C_ptr) :: pzForce = C_NULL_PTR + INTEGER(C_int) :: pzForce_Len = 0 + TYPE(C_ptr) :: xdotForce = C_NULL_PTR + INTEGER(C_int) :: xdotForce_Len = 0 + TYPE(C_ptr) :: ydotForce = C_NULL_PTR + INTEGER(C_int) :: ydotForce_Len = 0 + TYPE(C_ptr) :: zdotForce = C_NULL_PTR + INTEGER(C_int) :: zdotForce_Len = 0 + TYPE(C_ptr) :: pOrientation = C_NULL_PTR + INTEGER(C_int) :: pOrientation_Len = 0 + TYPE(C_ptr) :: fx = C_NULL_PTR + INTEGER(C_int) :: fx_Len = 0 + TYPE(C_ptr) :: fy = C_NULL_PTR + INTEGER(C_int) :: fy_Len = 0 + TYPE(C_ptr) :: fz = C_NULL_PTR + INTEGER(C_int) :: fz_Len = 0 + TYPE(C_ptr) :: momentx = C_NULL_PTR + INTEGER(C_int) :: momentx_Len = 0 + TYPE(C_ptr) :: momenty = C_NULL_PTR + INTEGER(C_int) :: momenty_Len = 0 + TYPE(C_ptr) :: momentz = C_NULL_PTR + INTEGER(C_int) :: momentz_Len = 0 + TYPE(C_ptr) :: forceNodesChord = C_NULL_PTR + INTEGER(C_int) :: forceNodesChord_Len = 0 + TYPE(C_ptr) :: SuperController = C_NULL_PTR + INTEGER(C_int) :: SuperController_Len = 0 + END TYPE OpFM_InputType_C + TYPE, PUBLIC :: OpFM_InputType + TYPE( OpFM_InputType_C ) :: C_obj + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pxVel => NULL() !< x position of velocity interface (Aerodyn) nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pyVel => NULL() !< y position of velocity interface (Aerodyn) nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pzVel => NULL() !< z position of velocity interface (Aerodyn) nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pxForce => NULL() !< x position of actuator force nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pyForce => NULL() !< y position of actuator force nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pzForce => NULL() !< z position of actuator force nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: xdotForce => NULL() !< x velocity of actuator force nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: ydotForce => NULL() !< y velocity of actuator force nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: zdotForce => NULL() !< z velocity of actuator force nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: pOrientation => NULL() !< Direction cosine matrix to transform vectors from global frame of reference to actuator force node frame of reference [-] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: fx => NULL() !< normalized x force at actuator force nodes [N/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: fy => NULL() !< normalized y force at actuator force nodes [N/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: fz => NULL() !< normalized z force at actuator force nodes [N/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: momentx => NULL() !< normalized x moment at actuator force nodes [Nm/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: momenty => NULL() !< normalized y moment at actuator force nodes [Nm/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: momentz => NULL() !< normalized z moment at actuator force nodes [Nm/kg/m^3] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: forceNodesChord => NULL() !< chord distribution at the actuator force nodes [m] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: SuperController => NULL() !< inputs to the super controller (from the turbine controller) [-] + END TYPE OpFM_InputType +! ======================= +! ========= OpFM_OutputType_C ======= + TYPE, BIND(C) :: OpFM_OutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: u = C_NULL_PTR + INTEGER(C_int) :: u_Len = 0 + TYPE(C_ptr) :: v = C_NULL_PTR + INTEGER(C_int) :: v_Len = 0 + TYPE(C_ptr) :: w = C_NULL_PTR + INTEGER(C_int) :: w_Len = 0 + TYPE(C_ptr) :: SuperController = C_NULL_PTR + INTEGER(C_int) :: SuperController_Len = 0 + TYPE(C_ptr) :: WriteOutput = C_NULL_PTR + INTEGER(C_int) :: WriteOutput_Len = 0 + END TYPE OpFM_OutputType_C + TYPE, PUBLIC :: OpFM_OutputType + TYPE( OpFM_OutputType_C ) :: C_obj + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: u => NULL() !< U-component wind speed (in the X-direction) at interface nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: v => NULL() !< V-component wind speed (in the Y-direction) at interface nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: w => NULL() !< W-component wind speed (in the Z-direction) at interface nodes [m/s] + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: SuperController => NULL() !< outputs of the super controller (to the turbine controller) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + END TYPE OpFM_OutputType +! ======================= +CONTAINS + SUBROUTINE OpFM_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(OpFM_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 = 'OpFM_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%NumSC2Ctrl = SrcInitInputData%NumSC2Ctrl + DstInitInputData%C_obj%NumSC2Ctrl = SrcInitInputData%C_obj%NumSC2Ctrl + DstInitInputData%NumCtrl2SC = SrcInitInputData%NumCtrl2SC + DstInitInputData%C_obj%NumCtrl2SC = SrcInitInputData%C_obj%NumCtrl2SC + DstInitInputData%NumActForcePtsBlade = SrcInitInputData%NumActForcePtsBlade + DstInitInputData%C_obj%NumActForcePtsBlade = SrcInitInputData%C_obj%NumActForcePtsBlade + DstInitInputData%NumActForcePtsTower = SrcInitInputData%NumActForcePtsTower + DstInitInputData%C_obj%NumActForcePtsTower = SrcInitInputData%C_obj%NumActForcePtsTower +IF (ASSOCIATED(SrcInitInputData%StructBldRNodes)) THEN + i1_l = LBOUND(SrcInitInputData%StructBldRNodes,1) + i1_u = UBOUND(SrcInitInputData%StructBldRNodes,1) + IF (.NOT. ASSOCIATED(DstInitInputData%StructBldRNodes)) THEN + ALLOCATE(DstInitInputData%StructBldRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%StructBldRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInitInputData%c_obj%StructBldRNodes_Len = SIZE(DstInitInputData%StructBldRNodes) + IF (DstInitInputData%c_obj%StructBldRNodes_Len > 0) & + DstInitInputData%c_obj%StructBldRNodes = C_LOC( DstInitInputData%StructBldRNodes(i1_l) ) + END IF + DstInitInputData%StructBldRNodes = SrcInitInputData%StructBldRNodes +ENDIF +IF (ASSOCIATED(SrcInitInputData%StructTwrHNodes)) THEN + i1_l = LBOUND(SrcInitInputData%StructTwrHNodes,1) + i1_u = UBOUND(SrcInitInputData%StructTwrHNodes,1) + IF (.NOT. ASSOCIATED(DstInitInputData%StructTwrHNodes)) THEN + ALLOCATE(DstInitInputData%StructTwrHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%StructTwrHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInitInputData%c_obj%StructTwrHNodes_Len = SIZE(DstInitInputData%StructTwrHNodes) + IF (DstInitInputData%c_obj%StructTwrHNodes_Len > 0) & + DstInitInputData%c_obj%StructTwrHNodes = C_LOC( DstInitInputData%StructTwrHNodes(i1_l) ) + END IF + DstInitInputData%StructTwrHNodes = SrcInitInputData%StructTwrHNodes +ENDIF + DstInitInputData%BladeLength = SrcInitInputData%BladeLength + DstInitInputData%C_obj%BladeLength = SrcInitInputData%C_obj%BladeLength + DstInitInputData%TowerHeight = SrcInitInputData%TowerHeight + DstInitInputData%C_obj%TowerHeight = SrcInitInputData%C_obj%TowerHeight + DstInitInputData%TowerBaseHeight = SrcInitInputData%TowerBaseHeight + DstInitInputData%C_obj%TowerBaseHeight = SrcInitInputData%C_obj%TowerBaseHeight + END SUBROUTINE OpFM_CopyInitInput + + SUBROUTINE OpFM_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(OpFM_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(InitInputData%StructBldRNodes)) THEN + DEALLOCATE(InitInputData%StructBldRNodes) + InitInputData%StructBldRNodes => NULL() + InitInputData%C_obj%StructBldRNodes = C_NULL_PTR + InitInputData%C_obj%StructBldRNodes_Len = 0 +ENDIF +IF (ASSOCIATED(InitInputData%StructTwrHNodes)) THEN + DEALLOCATE(InitInputData%StructTwrHNodes) + InitInputData%StructTwrHNodes => NULL() + InitInputData%C_obj%StructTwrHNodes = C_NULL_PTR + InitInputData%C_obj%StructTwrHNodes_Len = 0 +ENDIF + END SUBROUTINE OpFM_DestroyInitInput + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 ! NumSC2Ctrl + Int_BufSz = Int_BufSz + 1 ! NumCtrl2SC + Int_BufSz = Int_BufSz + 1 ! NumActForcePtsBlade + Int_BufSz = Int_BufSz + 1 ! NumActForcePtsTower + Int_BufSz = Int_BufSz + 1 ! StructBldRNodes allocated yes/no + IF ( ASSOCIATED(InData%StructBldRNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StructBldRNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StructBldRNodes) ! StructBldRNodes + END IF + Int_BufSz = Int_BufSz + 1 ! StructTwrHNodes allocated yes/no + IF ( ASSOCIATED(InData%StructTwrHNodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! StructTwrHNodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%StructTwrHNodes) ! StructTwrHNodes + END IF + Re_BufSz = Re_BufSz + 1 ! BladeLength + Re_BufSz = Re_BufSz + 1 ! TowerHeight + Re_BufSz = Re_BufSz + 1 ! TowerBaseHeight + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%NumSC2Ctrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCtrl2SC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumActForcePtsBlade + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumActForcePtsTower + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ASSOCIATED(InData%StructBldRNodes) ) 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%StructBldRNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StructBldRNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StructBldRNodes,1), UBOUND(InData%StructBldRNodes,1) + ReKiBuf(Re_Xferred) = InData%StructBldRNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%StructTwrHNodes) ) 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%StructTwrHNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%StructTwrHNodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%StructTwrHNodes,1), UBOUND(InData%StructTwrHNodes,1) + ReKiBuf(Re_Xferred) = InData%StructTwrHNodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerBaseHeight + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE OpFM_PackInitInput + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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%NumSC2Ctrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumSC2Ctrl = OutData%NumSC2Ctrl + OutData%NumCtrl2SC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumCtrl2SC = OutData%NumCtrl2SC + OutData%NumActForcePtsBlade = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumActForcePtsBlade = OutData%NumActForcePtsBlade + OutData%NumActForcePtsTower = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumActForcePtsTower = OutData%NumActForcePtsTower + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StructBldRNodes 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 (ASSOCIATED(OutData%StructBldRNodes)) DEALLOCATE(OutData%StructBldRNodes) + ALLOCATE(OutData%StructBldRNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StructBldRNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%StructBldRNodes_Len = SIZE(OutData%StructBldRNodes) + IF (OutData%c_obj%StructBldRNodes_Len > 0) & + OutData%c_obj%StructBldRNodes = C_LOC( OutData%StructBldRNodes(i1_l) ) + DO i1 = LBOUND(OutData%StructBldRNodes,1), UBOUND(OutData%StructBldRNodes,1) + OutData%StructBldRNodes(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! StructTwrHNodes 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 (ASSOCIATED(OutData%StructTwrHNodes)) DEALLOCATE(OutData%StructTwrHNodes) + ALLOCATE(OutData%StructTwrHNodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%StructTwrHNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%StructTwrHNodes_Len = SIZE(OutData%StructTwrHNodes) + IF (OutData%c_obj%StructTwrHNodes_Len > 0) & + OutData%c_obj%StructTwrHNodes = C_LOC( OutData%StructTwrHNodes(i1_l) ) + DO i1 = LBOUND(OutData%StructTwrHNodes,1), UBOUND(OutData%StructTwrHNodes,1) + OutData%StructTwrHNodes(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%BladeLength = OutData%BladeLength + OutData%TowerHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%TowerHeight = OutData%TowerHeight + OutData%TowerBaseHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%TowerBaseHeight = OutData%TowerBaseHeight + END SUBROUTINE OpFM_UnPackInitInput + + SUBROUTINE OpFM_C2Fary_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%NumSC2Ctrl = InitInputData%C_obj%NumSC2Ctrl + InitInputData%NumCtrl2SC = InitInputData%C_obj%NumCtrl2SC + InitInputData%NumActForcePtsBlade = InitInputData%C_obj%NumActForcePtsBlade + InitInputData%NumActForcePtsTower = InitInputData%C_obj%NumActForcePtsTower + + ! -- StructBldRNodes InitInput Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InitInputData%C_obj%StructBldRNodes ) ) THEN + NULLIFY( InitInputData%StructBldRNodes ) + ELSE + CALL C_F_POINTER(InitInputData%C_obj%StructBldRNodes, InitInputData%StructBldRNodes, (/InitInputData%C_obj%StructBldRNodes_Len/)) + END IF + END IF + + ! -- StructTwrHNodes InitInput Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InitInputData%C_obj%StructTwrHNodes ) ) THEN + NULLIFY( InitInputData%StructTwrHNodes ) + ELSE + CALL C_F_POINTER(InitInputData%C_obj%StructTwrHNodes, InitInputData%StructTwrHNodes, (/InitInputData%C_obj%StructTwrHNodes_Len/)) + END IF + END IF + InitInputData%BladeLength = InitInputData%C_obj%BladeLength + InitInputData%TowerHeight = InitInputData%C_obj%TowerHeight + InitInputData%TowerBaseHeight = InitInputData%C_obj%TowerBaseHeight + END SUBROUTINE OpFM_C2Fary_CopyInitInput + + SUBROUTINE OpFM_F2C_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%C_obj%NumSC2Ctrl = InitInputData%NumSC2Ctrl + InitInputData%C_obj%NumCtrl2SC = InitInputData%NumCtrl2SC + InitInputData%C_obj%NumActForcePtsBlade = InitInputData%NumActForcePtsBlade + InitInputData%C_obj%NumActForcePtsTower = InitInputData%NumActForcePtsTower + + ! -- StructBldRNodes InitInput Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InitInputData%StructBldRNodes)) THEN + InitInputData%c_obj%StructBldRNodes_Len = 0 + InitInputData%c_obj%StructBldRNodes = C_NULL_PTR + ELSE + InitInputData%c_obj%StructBldRNodes_Len = SIZE(InitInputData%StructBldRNodes) + IF (InitInputData%c_obj%StructBldRNodes_Len > 0) & + InitInputData%c_obj%StructBldRNodes = C_LOC( InitInputData%StructBldRNodes( LBOUND(InitInputData%StructBldRNodes,1) ) ) + END IF + END IF + + ! -- StructTwrHNodes InitInput Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InitInputData%StructTwrHNodes)) THEN + InitInputData%c_obj%StructTwrHNodes_Len = 0 + InitInputData%c_obj%StructTwrHNodes = C_NULL_PTR + ELSE + InitInputData%c_obj%StructTwrHNodes_Len = SIZE(InitInputData%StructTwrHNodes) + IF (InitInputData%c_obj%StructTwrHNodes_Len > 0) & + InitInputData%c_obj%StructTwrHNodes = C_LOC( InitInputData%StructTwrHNodes( LBOUND(InitInputData%StructTwrHNodes,1) ) ) + END IF + END IF + InitInputData%C_obj%BladeLength = InitInputData%BladeLength + InitInputData%C_obj%TowerHeight = InitInputData%TowerHeight + InitInputData%C_obj%TowerBaseHeight = InitInputData%TowerBaseHeight + END SUBROUTINE OpFM_F2C_CopyInitInput + + SUBROUTINE OpFM_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(OpFM_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 = 'OpFM_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE OpFM_CopyInitOutput + + SUBROUTINE OpFM_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(OpFM_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE OpFM_DestroyInitOutput + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 OpFM_PackInitOutput + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 OpFM_UnPackInitOutput + + SUBROUTINE OpFM_C2Fary_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE OpFM_C2Fary_CopyInitOutput + + SUBROUTINE OpFM_F2C_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE OpFM_F2C_CopyInitOutput + + SUBROUTINE OpFM_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_MiscVarType), INTENT(INOUT) :: SrcMiscData + TYPE(OpFM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%ActForceLoads)) THEN + i1_l = LBOUND(SrcMiscData%ActForceLoads,1) + i1_u = UBOUND(SrcMiscData%ActForceLoads,1) + IF (.NOT. ALLOCATED(DstMiscData%ActForceLoads)) THEN + ALLOCATE(DstMiscData%ActForceLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ActForceLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%ActForceLoads,1), UBOUND(SrcMiscData%ActForceLoads,1) + CALL MeshCopy( SrcMiscData%ActForceLoads(i1), DstMiscData%ActForceLoads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%ActForceMotions)) THEN + i1_l = LBOUND(SrcMiscData%ActForceMotions,1) + i1_u = UBOUND(SrcMiscData%ActForceMotions,1) + IF (.NOT. ALLOCATED(DstMiscData%ActForceMotions)) THEN + ALLOCATE(DstMiscData%ActForceMotions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ActForceMotions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%ActForceMotions,1), UBOUND(SrcMiscData%ActForceMotions,1) + CALL MeshCopy( SrcMiscData%ActForceMotions(i1), DstMiscData%ActForceMotions(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%ActForceMotionsPoints)) THEN + i1_l = LBOUND(SrcMiscData%ActForceMotionsPoints,1) + i1_u = UBOUND(SrcMiscData%ActForceMotionsPoints,1) + IF (.NOT. ALLOCATED(DstMiscData%ActForceMotionsPoints)) THEN + ALLOCATE(DstMiscData%ActForceMotionsPoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ActForceMotionsPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%ActForceMotionsPoints,1), UBOUND(SrcMiscData%ActForceMotionsPoints,1) + CALL MeshCopy( SrcMiscData%ActForceMotionsPoints(i1), DstMiscData%ActForceMotionsPoints(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%ActForceLoadsPoints)) THEN + i1_l = LBOUND(SrcMiscData%ActForceLoadsPoints,1) + i1_u = UBOUND(SrcMiscData%ActForceLoadsPoints,1) + IF (.NOT. ALLOCATED(DstMiscData%ActForceLoadsPoints)) THEN + ALLOCATE(DstMiscData%ActForceLoadsPoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ActForceLoadsPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%ActForceLoadsPoints,1), UBOUND(SrcMiscData%ActForceLoadsPoints,1) + CALL MeshCopy( SrcMiscData%ActForceLoadsPoints(i1), DstMiscData%ActForceLoadsPoints(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%Line2_to_Line2_Loads)) THEN + i1_l = LBOUND(SrcMiscData%Line2_to_Line2_Loads,1) + i1_u = UBOUND(SrcMiscData%Line2_to_Line2_Loads,1) + IF (.NOT. ALLOCATED(DstMiscData%Line2_to_Line2_Loads)) THEN + ALLOCATE(DstMiscData%Line2_to_Line2_Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line2_to_Line2_Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%Line2_to_Line2_Loads,1), UBOUND(SrcMiscData%Line2_to_Line2_Loads,1) + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Line2_to_Line2_Loads(i1), DstMiscData%Line2_to_Line2_Loads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%Line2_to_Line2_Motions)) THEN + i1_l = LBOUND(SrcMiscData%Line2_to_Line2_Motions,1) + i1_u = UBOUND(SrcMiscData%Line2_to_Line2_Motions,1) + IF (.NOT. ALLOCATED(DstMiscData%Line2_to_Line2_Motions)) THEN + ALLOCATE(DstMiscData%Line2_to_Line2_Motions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line2_to_Line2_Motions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%Line2_to_Line2_Motions,1), UBOUND(SrcMiscData%Line2_to_Line2_Motions,1) + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Line2_to_Line2_Motions(i1), DstMiscData%Line2_to_Line2_Motions(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%Line2_to_Point_Loads)) THEN + i1_l = LBOUND(SrcMiscData%Line2_to_Point_Loads,1) + i1_u = UBOUND(SrcMiscData%Line2_to_Point_Loads,1) + IF (.NOT. ALLOCATED(DstMiscData%Line2_to_Point_Loads)) THEN + ALLOCATE(DstMiscData%Line2_to_Point_Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line2_to_Point_Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%Line2_to_Point_Loads,1), UBOUND(SrcMiscData%Line2_to_Point_Loads,1) + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Line2_to_Point_Loads(i1), DstMiscData%Line2_to_Point_Loads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%Line2_to_Point_Motions)) THEN + i1_l = LBOUND(SrcMiscData%Line2_to_Point_Motions,1) + i1_u = UBOUND(SrcMiscData%Line2_to_Point_Motions,1) + IF (.NOT. ALLOCATED(DstMiscData%Line2_to_Point_Motions)) THEN + ALLOCATE(DstMiscData%Line2_to_Point_Motions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Line2_to_Point_Motions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%Line2_to_Point_Motions,1), UBOUND(SrcMiscData%Line2_to_Point_Motions,1) + CALL NWTC_Library_Copymeshmaptype( SrcMiscData%Line2_to_Point_Motions(i1), DstMiscData%Line2_to_Point_Motions(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + END SUBROUTINE OpFM_CopyMisc + + SUBROUTINE OpFM_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(OpFM_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%ActForceLoads)) THEN +DO i1 = LBOUND(MiscData%ActForceLoads,1), UBOUND(MiscData%ActForceLoads,1) + CALL MeshDestroy( MiscData%ActForceLoads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%ActForceLoads) +ENDIF +IF (ALLOCATED(MiscData%ActForceMotions)) THEN +DO i1 = LBOUND(MiscData%ActForceMotions,1), UBOUND(MiscData%ActForceMotions,1) + CALL MeshDestroy( MiscData%ActForceMotions(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%ActForceMotions) +ENDIF +IF (ALLOCATED(MiscData%ActForceMotionsPoints)) THEN +DO i1 = LBOUND(MiscData%ActForceMotionsPoints,1), UBOUND(MiscData%ActForceMotionsPoints,1) + CALL MeshDestroy( MiscData%ActForceMotionsPoints(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%ActForceMotionsPoints) +ENDIF +IF (ALLOCATED(MiscData%ActForceLoadsPoints)) THEN +DO i1 = LBOUND(MiscData%ActForceLoadsPoints,1), UBOUND(MiscData%ActForceLoadsPoints,1) + CALL MeshDestroy( MiscData%ActForceLoadsPoints(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%ActForceLoadsPoints) +ENDIF +IF (ALLOCATED(MiscData%Line2_to_Line2_Loads)) THEN +DO i1 = LBOUND(MiscData%Line2_to_Line2_Loads,1), UBOUND(MiscData%Line2_to_Line2_Loads,1) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Line2_to_Line2_Loads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%Line2_to_Line2_Loads) +ENDIF +IF (ALLOCATED(MiscData%Line2_to_Line2_Motions)) THEN +DO i1 = LBOUND(MiscData%Line2_to_Line2_Motions,1), UBOUND(MiscData%Line2_to_Line2_Motions,1) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Line2_to_Line2_Motions(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%Line2_to_Line2_Motions) +ENDIF +IF (ALLOCATED(MiscData%Line2_to_Point_Loads)) THEN +DO i1 = LBOUND(MiscData%Line2_to_Point_Loads,1), UBOUND(MiscData%Line2_to_Point_Loads,1) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Line2_to_Point_Loads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%Line2_to_Point_Loads) +ENDIF +IF (ALLOCATED(MiscData%Line2_to_Point_Motions)) THEN +DO i1 = LBOUND(MiscData%Line2_to_Point_Motions,1), UBOUND(MiscData%Line2_to_Point_Motions,1) + CALL NWTC_Library_Destroymeshmaptype( MiscData%Line2_to_Point_Motions(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%Line2_to_Point_Motions) +ENDIF + END SUBROUTINE OpFM_DestroyMisc + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 ! ActForceLoads allocated yes/no + IF ( ALLOCATED(InData%ActForceLoads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActForceLoads upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%ActForceLoads,1), UBOUND(InData%ActForceLoads,1) + Int_BufSz = Int_BufSz + 3 ! ActForceLoads: size of buffers for each call to pack subtype + CALL MeshPack( InData%ActForceLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ActForceLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ActForceLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ActForceLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ActForceLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ActForceMotions allocated yes/no + IF ( ALLOCATED(InData%ActForceMotions) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActForceMotions upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ActForceMotions,1), UBOUND(InData%ActForceMotions,1) + Int_BufSz = Int_BufSz + 3 ! ActForceMotions: size of buffers for each call to pack subtype + CALL MeshPack( InData%ActForceMotions(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ActForceMotions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ActForceMotions + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ActForceMotions + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ActForceMotions + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ActForceMotionsPoints allocated yes/no + IF ( ALLOCATED(InData%ActForceMotionsPoints) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActForceMotionsPoints upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ActForceMotionsPoints,1), UBOUND(InData%ActForceMotionsPoints,1) + Int_BufSz = Int_BufSz + 3 ! ActForceMotionsPoints: size of buffers for each call to pack subtype + CALL MeshPack( InData%ActForceMotionsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ActForceMotionsPoints + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ActForceMotionsPoints + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ActForceMotionsPoints + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ActForceMotionsPoints + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ActForceLoadsPoints allocated yes/no + IF ( ALLOCATED(InData%ActForceLoadsPoints) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ActForceLoadsPoints upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ActForceLoadsPoints,1), UBOUND(InData%ActForceLoadsPoints,1) + Int_BufSz = Int_BufSz + 3 ! ActForceLoadsPoints: size of buffers for each call to pack subtype + CALL MeshPack( InData%ActForceLoadsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! ActForceLoadsPoints + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ActForceLoadsPoints + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ActForceLoadsPoints + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ActForceLoadsPoints + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Line2_to_Line2_Loads allocated yes/no + IF ( ALLOCATED(InData%Line2_to_Line2_Loads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Line2_to_Line2_Loads upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Line2_to_Line2_Loads,1), UBOUND(InData%Line2_to_Line2_Loads,1) + Int_BufSz = Int_BufSz + 3 ! Line2_to_Line2_Loads: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Line2_Loads(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Line2_to_Line2_Loads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Line2_to_Line2_Loads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Line2_to_Line2_Loads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Line2_to_Line2_Loads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Line2_to_Line2_Motions allocated yes/no + IF ( ALLOCATED(InData%Line2_to_Line2_Motions) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Line2_to_Line2_Motions upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Line2_to_Line2_Motions,1), UBOUND(InData%Line2_to_Line2_Motions,1) + Int_BufSz = Int_BufSz + 3 ! Line2_to_Line2_Motions: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Line2_Motions(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Line2_to_Line2_Motions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Line2_to_Line2_Motions + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Line2_to_Line2_Motions + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Line2_to_Line2_Motions + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Line2_to_Point_Loads allocated yes/no + IF ( ALLOCATED(InData%Line2_to_Point_Loads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Line2_to_Point_Loads upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Line2_to_Point_Loads,1), UBOUND(InData%Line2_to_Point_Loads,1) + Int_BufSz = Int_BufSz + 3 ! Line2_to_Point_Loads: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Point_Loads(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Line2_to_Point_Loads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Line2_to_Point_Loads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Line2_to_Point_Loads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Line2_to_Point_Loads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! Line2_to_Point_Motions allocated yes/no + IF ( ALLOCATED(InData%Line2_to_Point_Motions) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Line2_to_Point_Motions upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Line2_to_Point_Motions,1), UBOUND(InData%Line2_to_Point_Motions,1) + Int_BufSz = Int_BufSz + 3 ! Line2_to_Point_Motions: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Point_Motions(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Line2_to_Point_Motions + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Line2_to_Point_Motions + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Line2_to_Point_Motions + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Line2_to_Point_Motions + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%ActForceLoads) ) 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%ActForceLoads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActForceLoads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActForceLoads,1), UBOUND(InData%ActForceLoads,1) + CALL MeshPack( InData%ActForceLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ActForceLoads + 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%ActForceMotions) ) 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%ActForceMotions,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActForceMotions,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActForceMotions,1), UBOUND(InData%ActForceMotions,1) + CALL MeshPack( InData%ActForceMotions(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ActForceMotions + 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%ActForceMotionsPoints) ) 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%ActForceMotionsPoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActForceMotionsPoints,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActForceMotionsPoints,1), UBOUND(InData%ActForceMotionsPoints,1) + CALL MeshPack( InData%ActForceMotionsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ActForceMotionsPoints + 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%ActForceLoadsPoints) ) 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%ActForceLoadsPoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ActForceLoadsPoints,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ActForceLoadsPoints,1), UBOUND(InData%ActForceLoadsPoints,1) + CALL MeshPack( InData%ActForceLoadsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! ActForceLoadsPoints + 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%Line2_to_Line2_Loads) ) 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%Line2_to_Line2_Loads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line2_to_Line2_Loads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Line2_to_Line2_Loads,1), UBOUND(InData%Line2_to_Line2_Loads,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Line2_Loads(i1), ErrStat2, ErrMsg2, OnlySize ) ! Line2_to_Line2_Loads + 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%Line2_to_Line2_Motions) ) 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%Line2_to_Line2_Motions,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line2_to_Line2_Motions,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Line2_to_Line2_Motions,1), UBOUND(InData%Line2_to_Line2_Motions,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Line2_Motions(i1), ErrStat2, ErrMsg2, OnlySize ) ! Line2_to_Line2_Motions + 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%Line2_to_Point_Loads) ) 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%Line2_to_Point_Loads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line2_to_Point_Loads,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Line2_to_Point_Loads,1), UBOUND(InData%Line2_to_Point_Loads,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Point_Loads(i1), ErrStat2, ErrMsg2, OnlySize ) ! Line2_to_Point_Loads + 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%Line2_to_Point_Motions) ) 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%Line2_to_Point_Motions,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Line2_to_Point_Motions,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Line2_to_Point_Motions,1), UBOUND(InData%Line2_to_Point_Motions,1) + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Line2_to_Point_Motions(i1), ErrStat2, ErrMsg2, OnlySize ) ! Line2_to_Point_Motions + 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 + END SUBROUTINE OpFM_PackMisc + + SUBROUTINE OpFM_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(OpFM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_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 ! ActForceLoads 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%ActForceLoads)) DEALLOCATE(OutData%ActForceLoads) + ALLOCATE(OutData%ActForceLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActForceLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActForceLoads,1), UBOUND(OutData%ActForceLoads,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 MeshUnpack( OutData%ActForceLoads(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ActForceLoads + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ActForceMotions 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%ActForceMotions)) DEALLOCATE(OutData%ActForceMotions) + ALLOCATE(OutData%ActForceMotions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActForceMotions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActForceMotions,1), UBOUND(OutData%ActForceMotions,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 MeshUnpack( OutData%ActForceMotions(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ActForceMotions + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ActForceMotionsPoints 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%ActForceMotionsPoints)) DEALLOCATE(OutData%ActForceMotionsPoints) + ALLOCATE(OutData%ActForceMotionsPoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActForceMotionsPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActForceMotionsPoints,1), UBOUND(OutData%ActForceMotionsPoints,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 MeshUnpack( OutData%ActForceMotionsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ActForceMotionsPoints + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ActForceLoadsPoints 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%ActForceLoadsPoints)) DEALLOCATE(OutData%ActForceLoadsPoints) + ALLOCATE(OutData%ActForceLoadsPoints(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ActForceLoadsPoints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ActForceLoadsPoints,1), UBOUND(OutData%ActForceLoadsPoints,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 MeshUnpack( OutData%ActForceLoadsPoints(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! ActForceLoadsPoints + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line2_to_Line2_Loads 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%Line2_to_Line2_Loads)) DEALLOCATE(OutData%Line2_to_Line2_Loads) + ALLOCATE(OutData%Line2_to_Line2_Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Line2_to_Line2_Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Line2_to_Line2_Loads,1), UBOUND(OutData%Line2_to_Line2_Loads,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Line2_to_Line2_Loads(i1), ErrStat2, ErrMsg2 ) ! Line2_to_Line2_Loads + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line2_to_Line2_Motions 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%Line2_to_Line2_Motions)) DEALLOCATE(OutData%Line2_to_Line2_Motions) + ALLOCATE(OutData%Line2_to_Line2_Motions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Line2_to_Line2_Motions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Line2_to_Line2_Motions,1), UBOUND(OutData%Line2_to_Line2_Motions,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Line2_to_Line2_Motions(i1), ErrStat2, ErrMsg2 ) ! Line2_to_Line2_Motions + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line2_to_Point_Loads 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%Line2_to_Point_Loads)) DEALLOCATE(OutData%Line2_to_Point_Loads) + ALLOCATE(OutData%Line2_to_Point_Loads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Line2_to_Point_Loads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Line2_to_Point_Loads,1), UBOUND(OutData%Line2_to_Point_Loads,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Line2_to_Point_Loads(i1), ErrStat2, ErrMsg2 ) ! Line2_to_Point_Loads + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Line2_to_Point_Motions 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%Line2_to_Point_Motions)) DEALLOCATE(OutData%Line2_to_Point_Motions) + ALLOCATE(OutData%Line2_to_Point_Motions(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Line2_to_Point_Motions.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Line2_to_Point_Motions,1), UBOUND(OutData%Line2_to_Point_Motions,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_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Line2_to_Point_Motions(i1), ErrStat2, ErrMsg2 ) ! Line2_to_Point_Motions + 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 DO + END IF + END SUBROUTINE OpFM_UnPackMisc + + SUBROUTINE OpFM_C2Fary_CopyMisc( MiscData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE OpFM_C2Fary_CopyMisc + + SUBROUTINE OpFM_F2C_CopyMisc( MiscData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE OpFM_F2C_CopyMisc + + SUBROUTINE OpFM_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_ParameterType), INTENT(IN) :: SrcParamData + TYPE(OpFM_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 = 'OpFM_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%AirDens = SrcParamData%AirDens + DstParamData%C_obj%AirDens = SrcParamData%C_obj%AirDens + DstParamData%NumBl = SrcParamData%NumBl + DstParamData%C_obj%NumBl = SrcParamData%C_obj%NumBl + DstParamData%NMappings = SrcParamData%NMappings + DstParamData%C_obj%NMappings = SrcParamData%C_obj%NMappings + DstParamData%NnodesVel = SrcParamData%NnodesVel + DstParamData%C_obj%NnodesVel = SrcParamData%C_obj%NnodesVel + DstParamData%NnodesForce = SrcParamData%NnodesForce + DstParamData%C_obj%NnodesForce = SrcParamData%C_obj%NnodesForce + DstParamData%NnodesForceBlade = SrcParamData%NnodesForceBlade + DstParamData%C_obj%NnodesForceBlade = SrcParamData%C_obj%NnodesForceBlade + DstParamData%NnodesForceTower = SrcParamData%NnodesForceTower + DstParamData%C_obj%NnodesForceTower = SrcParamData%C_obj%NnodesForceTower +IF (ASSOCIATED(SrcParamData%forceBldRnodes)) THEN + i1_l = LBOUND(SrcParamData%forceBldRnodes,1) + i1_u = UBOUND(SrcParamData%forceBldRnodes,1) + IF (.NOT. ASSOCIATED(DstParamData%forceBldRnodes)) THEN + ALLOCATE(DstParamData%forceBldRnodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%forceBldRnodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstParamData%c_obj%forceBldRnodes_Len = SIZE(DstParamData%forceBldRnodes) + IF (DstParamData%c_obj%forceBldRnodes_Len > 0) & + DstParamData%c_obj%forceBldRnodes = C_LOC( DstParamData%forceBldRnodes(i1_l) ) + END IF + DstParamData%forceBldRnodes = SrcParamData%forceBldRnodes +ENDIF +IF (ASSOCIATED(SrcParamData%forceTwrHnodes)) THEN + i1_l = LBOUND(SrcParamData%forceTwrHnodes,1) + i1_u = UBOUND(SrcParamData%forceTwrHnodes,1) + IF (.NOT. ASSOCIATED(DstParamData%forceTwrHnodes)) THEN + ALLOCATE(DstParamData%forceTwrHnodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%forceTwrHnodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstParamData%c_obj%forceTwrHnodes_Len = SIZE(DstParamData%forceTwrHnodes) + IF (DstParamData%c_obj%forceTwrHnodes_Len > 0) & + DstParamData%c_obj%forceTwrHnodes = C_LOC( DstParamData%forceTwrHnodes(i1_l) ) + END IF + DstParamData%forceTwrHnodes = SrcParamData%forceTwrHnodes +ENDIF + DstParamData%BladeLength = SrcParamData%BladeLength + DstParamData%C_obj%BladeLength = SrcParamData%C_obj%BladeLength + DstParamData%TowerHeight = SrcParamData%TowerHeight + DstParamData%C_obj%TowerHeight = SrcParamData%C_obj%TowerHeight + DstParamData%TowerBaseHeight = SrcParamData%TowerBaseHeight + DstParamData%C_obj%TowerBaseHeight = SrcParamData%C_obj%TowerBaseHeight + END SUBROUTINE OpFM_CopyParam + + SUBROUTINE OpFM_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(OpFM_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(ParamData%forceBldRnodes)) THEN + DEALLOCATE(ParamData%forceBldRnodes) + ParamData%forceBldRnodes => NULL() + ParamData%C_obj%forceBldRnodes = C_NULL_PTR + ParamData%C_obj%forceBldRnodes_Len = 0 +ENDIF +IF (ASSOCIATED(ParamData%forceTwrHnodes)) THEN + DEALLOCATE(ParamData%forceTwrHnodes) + ParamData%forceTwrHnodes => NULL() + ParamData%C_obj%forceTwrHnodes = C_NULL_PTR + ParamData%C_obj%forceTwrHnodes_Len = 0 +ENDIF + END SUBROUTINE OpFM_DestroyParam + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 ! AirDens + Int_BufSz = Int_BufSz + 1 ! NumBl + Int_BufSz = Int_BufSz + 1 ! NMappings + Int_BufSz = Int_BufSz + 1 ! NnodesVel + Int_BufSz = Int_BufSz + 1 ! NnodesForce + Int_BufSz = Int_BufSz + 1 ! NnodesForceBlade + Int_BufSz = Int_BufSz + 1 ! NnodesForceTower + Int_BufSz = Int_BufSz + 1 ! forceBldRnodes allocated yes/no + IF ( ASSOCIATED(InData%forceBldRnodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! forceBldRnodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%forceBldRnodes) ! forceBldRnodes + END IF + Int_BufSz = Int_BufSz + 1 ! forceTwrHnodes allocated yes/no + IF ( ASSOCIATED(InData%forceTwrHnodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! forceTwrHnodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%forceTwrHnodes) ! forceTwrHnodes + END IF + Re_BufSz = Re_BufSz + 1 ! BladeLength + Re_BufSz = Re_BufSz + 1 ! TowerHeight + Re_BufSz = Re_BufSz + 1 ! TowerBaseHeight + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NMappings + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NnodesVel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NnodesForce + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NnodesForceBlade + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NnodesForceTower + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ASSOCIATED(InData%forceBldRnodes) ) 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%forceBldRnodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%forceBldRnodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%forceBldRnodes,1), UBOUND(InData%forceBldRnodes,1) + ReKiBuf(Re_Xferred) = InData%forceBldRnodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%forceTwrHnodes) ) 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%forceTwrHnodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%forceTwrHnodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%forceTwrHnodes,1), UBOUND(InData%forceTwrHnodes,1) + ReKiBuf(Re_Xferred) = InData%forceTwrHnodes(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%BladeLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TowerBaseHeight + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE OpFM_PackParam + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%AirDens = OutData%AirDens + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumBl = OutData%NumBl + OutData%NMappings = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NMappings = OutData%NMappings + OutData%NnodesVel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NnodesVel = OutData%NnodesVel + OutData%NnodesForce = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NnodesForce = OutData%NnodesForce + OutData%NnodesForceBlade = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NnodesForceBlade = OutData%NnodesForceBlade + OutData%NnodesForceTower = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NnodesForceTower = OutData%NnodesForceTower + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! forceBldRnodes 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 (ASSOCIATED(OutData%forceBldRnodes)) DEALLOCATE(OutData%forceBldRnodes) + ALLOCATE(OutData%forceBldRnodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%forceBldRnodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%forceBldRnodes_Len = SIZE(OutData%forceBldRnodes) + IF (OutData%c_obj%forceBldRnodes_Len > 0) & + OutData%c_obj%forceBldRnodes = C_LOC( OutData%forceBldRnodes(i1_l) ) + DO i1 = LBOUND(OutData%forceBldRnodes,1), UBOUND(OutData%forceBldRnodes,1) + OutData%forceBldRnodes(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! forceTwrHnodes 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 (ASSOCIATED(OutData%forceTwrHnodes)) DEALLOCATE(OutData%forceTwrHnodes) + ALLOCATE(OutData%forceTwrHnodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%forceTwrHnodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%forceTwrHnodes_Len = SIZE(OutData%forceTwrHnodes) + IF (OutData%c_obj%forceTwrHnodes_Len > 0) & + OutData%c_obj%forceTwrHnodes = C_LOC( OutData%forceTwrHnodes(i1_l) ) + DO i1 = LBOUND(OutData%forceTwrHnodes,1), UBOUND(OutData%forceTwrHnodes,1) + OutData%forceTwrHnodes(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%BladeLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%BladeLength = OutData%BladeLength + OutData%TowerHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%TowerHeight = OutData%TowerHeight + OutData%TowerBaseHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_obj%TowerBaseHeight = OutData%TowerBaseHeight + END SUBROUTINE OpFM_UnPackParam + + SUBROUTINE OpFM_C2Fary_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%AirDens = ParamData%C_obj%AirDens + ParamData%NumBl = ParamData%C_obj%NumBl + ParamData%NMappings = ParamData%C_obj%NMappings + ParamData%NnodesVel = ParamData%C_obj%NnodesVel + ParamData%NnodesForce = ParamData%C_obj%NnodesForce + ParamData%NnodesForceBlade = ParamData%C_obj%NnodesForceBlade + ParamData%NnodesForceTower = ParamData%C_obj%NnodesForceTower + + ! -- forceBldRnodes Param Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ParamData%C_obj%forceBldRnodes ) ) THEN + NULLIFY( ParamData%forceBldRnodes ) + ELSE + CALL C_F_POINTER(ParamData%C_obj%forceBldRnodes, ParamData%forceBldRnodes, (/ParamData%C_obj%forceBldRnodes_Len/)) + END IF + END IF + + ! -- forceTwrHnodes Param Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( ParamData%C_obj%forceTwrHnodes ) ) THEN + NULLIFY( ParamData%forceTwrHnodes ) + ELSE + CALL C_F_POINTER(ParamData%C_obj%forceTwrHnodes, ParamData%forceTwrHnodes, (/ParamData%C_obj%forceTwrHnodes_Len/)) + END IF + END IF + ParamData%BladeLength = ParamData%C_obj%BladeLength + ParamData%TowerHeight = ParamData%C_obj%TowerHeight + ParamData%TowerBaseHeight = ParamData%C_obj%TowerBaseHeight + END SUBROUTINE OpFM_C2Fary_CopyParam + + SUBROUTINE OpFM_F2C_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%C_obj%AirDens = ParamData%AirDens + ParamData%C_obj%NumBl = ParamData%NumBl + ParamData%C_obj%NMappings = ParamData%NMappings + ParamData%C_obj%NnodesVel = ParamData%NnodesVel + ParamData%C_obj%NnodesForce = ParamData%NnodesForce + ParamData%C_obj%NnodesForceBlade = ParamData%NnodesForceBlade + ParamData%C_obj%NnodesForceTower = ParamData%NnodesForceTower + + ! -- forceBldRnodes Param Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ParamData%forceBldRnodes)) THEN + ParamData%c_obj%forceBldRnodes_Len = 0 + ParamData%c_obj%forceBldRnodes = C_NULL_PTR + ELSE + ParamData%c_obj%forceBldRnodes_Len = SIZE(ParamData%forceBldRnodes) + IF (ParamData%c_obj%forceBldRnodes_Len > 0) & + ParamData%c_obj%forceBldRnodes = C_LOC( ParamData%forceBldRnodes( LBOUND(ParamData%forceBldRnodes,1) ) ) + END IF + END IF + + ! -- forceTwrHnodes Param Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(ParamData%forceTwrHnodes)) THEN + ParamData%c_obj%forceTwrHnodes_Len = 0 + ParamData%c_obj%forceTwrHnodes = C_NULL_PTR + ELSE + ParamData%c_obj%forceTwrHnodes_Len = SIZE(ParamData%forceTwrHnodes) + IF (ParamData%c_obj%forceTwrHnodes_Len > 0) & + ParamData%c_obj%forceTwrHnodes = C_LOC( ParamData%forceTwrHnodes( LBOUND(ParamData%forceTwrHnodes,1) ) ) + END IF + END IF + ParamData%C_obj%BladeLength = ParamData%BladeLength + ParamData%C_obj%TowerHeight = ParamData%TowerHeight + ParamData%C_obj%TowerBaseHeight = ParamData%TowerBaseHeight + END SUBROUTINE OpFM_F2C_CopyParam + + SUBROUTINE OpFM_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_InputType), INTENT(IN) :: SrcInputData + TYPE(OpFM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcInputData%pxVel)) THEN + i1_l = LBOUND(SrcInputData%pxVel,1) + i1_u = UBOUND(SrcInputData%pxVel,1) + IF (.NOT. ASSOCIATED(DstInputData%pxVel)) THEN + ALLOCATE(DstInputData%pxVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pxVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pxVel_Len = SIZE(DstInputData%pxVel) + IF (DstInputData%c_obj%pxVel_Len > 0) & + DstInputData%c_obj%pxVel = C_LOC( DstInputData%pxVel(i1_l) ) + END IF + DstInputData%pxVel = SrcInputData%pxVel +ENDIF +IF (ASSOCIATED(SrcInputData%pyVel)) THEN + i1_l = LBOUND(SrcInputData%pyVel,1) + i1_u = UBOUND(SrcInputData%pyVel,1) + IF (.NOT. ASSOCIATED(DstInputData%pyVel)) THEN + ALLOCATE(DstInputData%pyVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pyVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pyVel_Len = SIZE(DstInputData%pyVel) + IF (DstInputData%c_obj%pyVel_Len > 0) & + DstInputData%c_obj%pyVel = C_LOC( DstInputData%pyVel(i1_l) ) + END IF + DstInputData%pyVel = SrcInputData%pyVel +ENDIF +IF (ASSOCIATED(SrcInputData%pzVel)) THEN + i1_l = LBOUND(SrcInputData%pzVel,1) + i1_u = UBOUND(SrcInputData%pzVel,1) + IF (.NOT. ASSOCIATED(DstInputData%pzVel)) THEN + ALLOCATE(DstInputData%pzVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pzVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pzVel_Len = SIZE(DstInputData%pzVel) + IF (DstInputData%c_obj%pzVel_Len > 0) & + DstInputData%c_obj%pzVel = C_LOC( DstInputData%pzVel(i1_l) ) + END IF + DstInputData%pzVel = SrcInputData%pzVel +ENDIF +IF (ASSOCIATED(SrcInputData%pxForce)) THEN + i1_l = LBOUND(SrcInputData%pxForce,1) + i1_u = UBOUND(SrcInputData%pxForce,1) + IF (.NOT. ASSOCIATED(DstInputData%pxForce)) THEN + ALLOCATE(DstInputData%pxForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pxForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pxForce_Len = SIZE(DstInputData%pxForce) + IF (DstInputData%c_obj%pxForce_Len > 0) & + DstInputData%c_obj%pxForce = C_LOC( DstInputData%pxForce(i1_l) ) + END IF + DstInputData%pxForce = SrcInputData%pxForce +ENDIF +IF (ASSOCIATED(SrcInputData%pyForce)) THEN + i1_l = LBOUND(SrcInputData%pyForce,1) + i1_u = UBOUND(SrcInputData%pyForce,1) + IF (.NOT. ASSOCIATED(DstInputData%pyForce)) THEN + ALLOCATE(DstInputData%pyForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pyForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pyForce_Len = SIZE(DstInputData%pyForce) + IF (DstInputData%c_obj%pyForce_Len > 0) & + DstInputData%c_obj%pyForce = C_LOC( DstInputData%pyForce(i1_l) ) + END IF + DstInputData%pyForce = SrcInputData%pyForce +ENDIF +IF (ASSOCIATED(SrcInputData%pzForce)) THEN + i1_l = LBOUND(SrcInputData%pzForce,1) + i1_u = UBOUND(SrcInputData%pzForce,1) + IF (.NOT. ASSOCIATED(DstInputData%pzForce)) THEN + ALLOCATE(DstInputData%pzForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pzForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pzForce_Len = SIZE(DstInputData%pzForce) + IF (DstInputData%c_obj%pzForce_Len > 0) & + DstInputData%c_obj%pzForce = C_LOC( DstInputData%pzForce(i1_l) ) + END IF + DstInputData%pzForce = SrcInputData%pzForce +ENDIF +IF (ASSOCIATED(SrcInputData%xdotForce)) THEN + i1_l = LBOUND(SrcInputData%xdotForce,1) + i1_u = UBOUND(SrcInputData%xdotForce,1) + IF (.NOT. ASSOCIATED(DstInputData%xdotForce)) THEN + ALLOCATE(DstInputData%xdotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%xdotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%xdotForce_Len = SIZE(DstInputData%xdotForce) + IF (DstInputData%c_obj%xdotForce_Len > 0) & + DstInputData%c_obj%xdotForce = C_LOC( DstInputData%xdotForce(i1_l) ) + END IF + DstInputData%xdotForce = SrcInputData%xdotForce +ENDIF +IF (ASSOCIATED(SrcInputData%ydotForce)) THEN + i1_l = LBOUND(SrcInputData%ydotForce,1) + i1_u = UBOUND(SrcInputData%ydotForce,1) + IF (.NOT. ASSOCIATED(DstInputData%ydotForce)) THEN + ALLOCATE(DstInputData%ydotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%ydotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%ydotForce_Len = SIZE(DstInputData%ydotForce) + IF (DstInputData%c_obj%ydotForce_Len > 0) & + DstInputData%c_obj%ydotForce = C_LOC( DstInputData%ydotForce(i1_l) ) + END IF + DstInputData%ydotForce = SrcInputData%ydotForce +ENDIF +IF (ASSOCIATED(SrcInputData%zdotForce)) THEN + i1_l = LBOUND(SrcInputData%zdotForce,1) + i1_u = UBOUND(SrcInputData%zdotForce,1) + IF (.NOT. ASSOCIATED(DstInputData%zdotForce)) THEN + ALLOCATE(DstInputData%zdotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%zdotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%zdotForce_Len = SIZE(DstInputData%zdotForce) + IF (DstInputData%c_obj%zdotForce_Len > 0) & + DstInputData%c_obj%zdotForce = C_LOC( DstInputData%zdotForce(i1_l) ) + END IF + DstInputData%zdotForce = SrcInputData%zdotForce +ENDIF +IF (ASSOCIATED(SrcInputData%pOrientation)) THEN + i1_l = LBOUND(SrcInputData%pOrientation,1) + i1_u = UBOUND(SrcInputData%pOrientation,1) + IF (.NOT. ASSOCIATED(DstInputData%pOrientation)) THEN + ALLOCATE(DstInputData%pOrientation(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%pOrientation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%pOrientation_Len = SIZE(DstInputData%pOrientation) + IF (DstInputData%c_obj%pOrientation_Len > 0) & + DstInputData%c_obj%pOrientation = C_LOC( DstInputData%pOrientation(i1_l) ) + END IF + DstInputData%pOrientation = SrcInputData%pOrientation +ENDIF +IF (ASSOCIATED(SrcInputData%fx)) THEN + i1_l = LBOUND(SrcInputData%fx,1) + i1_u = UBOUND(SrcInputData%fx,1) + IF (.NOT. ASSOCIATED(DstInputData%fx)) THEN + ALLOCATE(DstInputData%fx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%fx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%fx_Len = SIZE(DstInputData%fx) + IF (DstInputData%c_obj%fx_Len > 0) & + DstInputData%c_obj%fx = C_LOC( DstInputData%fx(i1_l) ) + END IF + DstInputData%fx = SrcInputData%fx +ENDIF +IF (ASSOCIATED(SrcInputData%fy)) THEN + i1_l = LBOUND(SrcInputData%fy,1) + i1_u = UBOUND(SrcInputData%fy,1) + IF (.NOT. ASSOCIATED(DstInputData%fy)) THEN + ALLOCATE(DstInputData%fy(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%fy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%fy_Len = SIZE(DstInputData%fy) + IF (DstInputData%c_obj%fy_Len > 0) & + DstInputData%c_obj%fy = C_LOC( DstInputData%fy(i1_l) ) + END IF + DstInputData%fy = SrcInputData%fy +ENDIF +IF (ASSOCIATED(SrcInputData%fz)) THEN + i1_l = LBOUND(SrcInputData%fz,1) + i1_u = UBOUND(SrcInputData%fz,1) + IF (.NOT. ASSOCIATED(DstInputData%fz)) THEN + ALLOCATE(DstInputData%fz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%fz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%fz_Len = SIZE(DstInputData%fz) + IF (DstInputData%c_obj%fz_Len > 0) & + DstInputData%c_obj%fz = C_LOC( DstInputData%fz(i1_l) ) + END IF + DstInputData%fz = SrcInputData%fz +ENDIF +IF (ASSOCIATED(SrcInputData%momentx)) THEN + i1_l = LBOUND(SrcInputData%momentx,1) + i1_u = UBOUND(SrcInputData%momentx,1) + IF (.NOT. ASSOCIATED(DstInputData%momentx)) THEN + ALLOCATE(DstInputData%momentx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%momentx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%momentx_Len = SIZE(DstInputData%momentx) + IF (DstInputData%c_obj%momentx_Len > 0) & + DstInputData%c_obj%momentx = C_LOC( DstInputData%momentx(i1_l) ) + END IF + DstInputData%momentx = SrcInputData%momentx +ENDIF +IF (ASSOCIATED(SrcInputData%momenty)) THEN + i1_l = LBOUND(SrcInputData%momenty,1) + i1_u = UBOUND(SrcInputData%momenty,1) + IF (.NOT. ASSOCIATED(DstInputData%momenty)) THEN + ALLOCATE(DstInputData%momenty(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%momenty.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%momenty_Len = SIZE(DstInputData%momenty) + IF (DstInputData%c_obj%momenty_Len > 0) & + DstInputData%c_obj%momenty = C_LOC( DstInputData%momenty(i1_l) ) + END IF + DstInputData%momenty = SrcInputData%momenty +ENDIF +IF (ASSOCIATED(SrcInputData%momentz)) THEN + i1_l = LBOUND(SrcInputData%momentz,1) + i1_u = UBOUND(SrcInputData%momentz,1) + IF (.NOT. ASSOCIATED(DstInputData%momentz)) THEN + ALLOCATE(DstInputData%momentz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%momentz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%momentz_Len = SIZE(DstInputData%momentz) + IF (DstInputData%c_obj%momentz_Len > 0) & + DstInputData%c_obj%momentz = C_LOC( DstInputData%momentz(i1_l) ) + END IF + DstInputData%momentz = SrcInputData%momentz +ENDIF +IF (ASSOCIATED(SrcInputData%forceNodesChord)) THEN + i1_l = LBOUND(SrcInputData%forceNodesChord,1) + i1_u = UBOUND(SrcInputData%forceNodesChord,1) + IF (.NOT. ASSOCIATED(DstInputData%forceNodesChord)) THEN + ALLOCATE(DstInputData%forceNodesChord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%forceNodesChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%forceNodesChord_Len = SIZE(DstInputData%forceNodesChord) + IF (DstInputData%c_obj%forceNodesChord_Len > 0) & + DstInputData%c_obj%forceNodesChord = C_LOC( DstInputData%forceNodesChord(i1_l) ) + END IF + DstInputData%forceNodesChord = SrcInputData%forceNodesChord +ENDIF +IF (ASSOCIATED(SrcInputData%SuperController)) THEN + i1_l = LBOUND(SrcInputData%SuperController,1) + i1_u = UBOUND(SrcInputData%SuperController,1) + IF (.NOT. ASSOCIATED(DstInputData%SuperController)) THEN + ALLOCATE(DstInputData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%SuperController_Len = SIZE(DstInputData%SuperController) + IF (DstInputData%c_obj%SuperController_Len > 0) & + DstInputData%c_obj%SuperController = C_LOC( DstInputData%SuperController(i1_l) ) + END IF + DstInputData%SuperController = SrcInputData%SuperController +ENDIF + END SUBROUTINE OpFM_CopyInput + + SUBROUTINE OpFM_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(OpFM_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(InputData%pxVel)) THEN + DEALLOCATE(InputData%pxVel) + InputData%pxVel => NULL() + InputData%C_obj%pxVel = C_NULL_PTR + InputData%C_obj%pxVel_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pyVel)) THEN + DEALLOCATE(InputData%pyVel) + InputData%pyVel => NULL() + InputData%C_obj%pyVel = C_NULL_PTR + InputData%C_obj%pyVel_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pzVel)) THEN + DEALLOCATE(InputData%pzVel) + InputData%pzVel => NULL() + InputData%C_obj%pzVel = C_NULL_PTR + InputData%C_obj%pzVel_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pxForce)) THEN + DEALLOCATE(InputData%pxForce) + InputData%pxForce => NULL() + InputData%C_obj%pxForce = C_NULL_PTR + InputData%C_obj%pxForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pyForce)) THEN + DEALLOCATE(InputData%pyForce) + InputData%pyForce => NULL() + InputData%C_obj%pyForce = C_NULL_PTR + InputData%C_obj%pyForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pzForce)) THEN + DEALLOCATE(InputData%pzForce) + InputData%pzForce => NULL() + InputData%C_obj%pzForce = C_NULL_PTR + InputData%C_obj%pzForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%xdotForce)) THEN + DEALLOCATE(InputData%xdotForce) + InputData%xdotForce => NULL() + InputData%C_obj%xdotForce = C_NULL_PTR + InputData%C_obj%xdotForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%ydotForce)) THEN + DEALLOCATE(InputData%ydotForce) + InputData%ydotForce => NULL() + InputData%C_obj%ydotForce = C_NULL_PTR + InputData%C_obj%ydotForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%zdotForce)) THEN + DEALLOCATE(InputData%zdotForce) + InputData%zdotForce => NULL() + InputData%C_obj%zdotForce = C_NULL_PTR + InputData%C_obj%zdotForce_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%pOrientation)) THEN + DEALLOCATE(InputData%pOrientation) + InputData%pOrientation => NULL() + InputData%C_obj%pOrientation = C_NULL_PTR + InputData%C_obj%pOrientation_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%fx)) THEN + DEALLOCATE(InputData%fx) + InputData%fx => NULL() + InputData%C_obj%fx = C_NULL_PTR + InputData%C_obj%fx_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%fy)) THEN + DEALLOCATE(InputData%fy) + InputData%fy => NULL() + InputData%C_obj%fy = C_NULL_PTR + InputData%C_obj%fy_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%fz)) THEN + DEALLOCATE(InputData%fz) + InputData%fz => NULL() + InputData%C_obj%fz = C_NULL_PTR + InputData%C_obj%fz_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%momentx)) THEN + DEALLOCATE(InputData%momentx) + InputData%momentx => NULL() + InputData%C_obj%momentx = C_NULL_PTR + InputData%C_obj%momentx_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%momenty)) THEN + DEALLOCATE(InputData%momenty) + InputData%momenty => NULL() + InputData%C_obj%momenty = C_NULL_PTR + InputData%C_obj%momenty_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%momentz)) THEN + DEALLOCATE(InputData%momentz) + InputData%momentz => NULL() + InputData%C_obj%momentz = C_NULL_PTR + InputData%C_obj%momentz_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%forceNodesChord)) THEN + DEALLOCATE(InputData%forceNodesChord) + InputData%forceNodesChord => NULL() + InputData%C_obj%forceNodesChord = C_NULL_PTR + InputData%C_obj%forceNodesChord_Len = 0 +ENDIF +IF (ASSOCIATED(InputData%SuperController)) THEN + DEALLOCATE(InputData%SuperController) + InputData%SuperController => NULL() + InputData%C_obj%SuperController = C_NULL_PTR + InputData%C_obj%SuperController_Len = 0 +ENDIF + END SUBROUTINE OpFM_DestroyInput + + SUBROUTINE OpFM_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(OpFM_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 = 'OpFM_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 ! pxVel allocated yes/no + IF ( ASSOCIATED(InData%pxVel) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pxVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pxVel) ! pxVel + END IF + Int_BufSz = Int_BufSz + 1 ! pyVel allocated yes/no + IF ( ASSOCIATED(InData%pyVel) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pyVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pyVel) ! pyVel + END IF + Int_BufSz = Int_BufSz + 1 ! pzVel allocated yes/no + IF ( ASSOCIATED(InData%pzVel) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pzVel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pzVel) ! pzVel + END IF + Int_BufSz = Int_BufSz + 1 ! pxForce allocated yes/no + IF ( ASSOCIATED(InData%pxForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pxForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pxForce) ! pxForce + END IF + Int_BufSz = Int_BufSz + 1 ! pyForce allocated yes/no + IF ( ASSOCIATED(InData%pyForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pyForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pyForce) ! pyForce + END IF + Int_BufSz = Int_BufSz + 1 ! pzForce allocated yes/no + IF ( ASSOCIATED(InData%pzForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pzForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pzForce) ! pzForce + END IF + Int_BufSz = Int_BufSz + 1 ! xdotForce allocated yes/no + IF ( ASSOCIATED(InData%xdotForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xdotForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%xdotForce) ! xdotForce + END IF + Int_BufSz = Int_BufSz + 1 ! ydotForce allocated yes/no + IF ( ASSOCIATED(InData%ydotForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ydotForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ydotForce) ! ydotForce + END IF + Int_BufSz = Int_BufSz + 1 ! zdotForce allocated yes/no + IF ( ASSOCIATED(InData%zdotForce) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! zdotForce upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%zdotForce) ! zdotForce + END IF + Int_BufSz = Int_BufSz + 1 ! pOrientation allocated yes/no + IF ( ASSOCIATED(InData%pOrientation) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! pOrientation upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%pOrientation) ! pOrientation + END IF + Int_BufSz = Int_BufSz + 1 ! fx allocated yes/no + IF ( ASSOCIATED(InData%fx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! fx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fx) ! fx + END IF + Int_BufSz = Int_BufSz + 1 ! fy allocated yes/no + IF ( ASSOCIATED(InData%fy) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! fy upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fy) ! fy + END IF + Int_BufSz = Int_BufSz + 1 ! fz allocated yes/no + IF ( ASSOCIATED(InData%fz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! fz upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fz) ! fz + END IF + Int_BufSz = Int_BufSz + 1 ! momentx allocated yes/no + IF ( ASSOCIATED(InData%momentx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! momentx upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%momentx) ! momentx + END IF + Int_BufSz = Int_BufSz + 1 ! momenty allocated yes/no + IF ( ASSOCIATED(InData%momenty) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! momenty upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%momenty) ! momenty + END IF + Int_BufSz = Int_BufSz + 1 ! momentz allocated yes/no + IF ( ASSOCIATED(InData%momentz) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! momentz upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%momentz) ! momentz + END IF + Int_BufSz = Int_BufSz + 1 ! forceNodesChord allocated yes/no + IF ( ASSOCIATED(InData%forceNodesChord) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! forceNodesChord upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%forceNodesChord) ! forceNodesChord + END IF + Int_BufSz = Int_BufSz + 1 ! SuperController allocated yes/no + IF ( ASSOCIATED(InData%SuperController) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SuperController upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SuperController) ! SuperController + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%pxVel) ) 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%pxVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pxVel,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pxVel,1), UBOUND(InData%pxVel,1) + ReKiBuf(Re_Xferred) = InData%pxVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pyVel) ) 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%pyVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pyVel,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pyVel,1), UBOUND(InData%pyVel,1) + ReKiBuf(Re_Xferred) = InData%pyVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pzVel) ) 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%pzVel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pzVel,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pzVel,1), UBOUND(InData%pzVel,1) + ReKiBuf(Re_Xferred) = InData%pzVel(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pxForce) ) 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%pxForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pxForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pxForce,1), UBOUND(InData%pxForce,1) + ReKiBuf(Re_Xferred) = InData%pxForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pyForce) ) 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%pyForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pyForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pyForce,1), UBOUND(InData%pyForce,1) + ReKiBuf(Re_Xferred) = InData%pyForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pzForce) ) 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%pzForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pzForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pzForce,1), UBOUND(InData%pzForce,1) + ReKiBuf(Re_Xferred) = InData%pzForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%xdotForce) ) 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%xdotForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdotForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xdotForce,1), UBOUND(InData%xdotForce,1) + ReKiBuf(Re_Xferred) = InData%xdotForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%ydotForce) ) 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%ydotForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ydotForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ydotForce,1), UBOUND(InData%ydotForce,1) + ReKiBuf(Re_Xferred) = InData%ydotForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%zdotForce) ) 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%zdotForce,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%zdotForce,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%zdotForce,1), UBOUND(InData%zdotForce,1) + ReKiBuf(Re_Xferred) = InData%zdotForce(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%pOrientation) ) 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%pOrientation,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%pOrientation,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%pOrientation,1), UBOUND(InData%pOrientation,1) + ReKiBuf(Re_Xferred) = InData%pOrientation(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%fx) ) 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%fx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%fx,1), UBOUND(InData%fx,1) + ReKiBuf(Re_Xferred) = InData%fx(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%fy) ) 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%fy,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fy,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%fy,1), UBOUND(InData%fy,1) + ReKiBuf(Re_Xferred) = InData%fy(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%fz) ) 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%fz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%fz,1), UBOUND(InData%fz,1) + ReKiBuf(Re_Xferred) = InData%fz(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%momentx) ) 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%momentx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%momentx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%momentx,1), UBOUND(InData%momentx,1) + ReKiBuf(Re_Xferred) = InData%momentx(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%momenty) ) 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%momenty,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%momenty,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%momenty,1), UBOUND(InData%momenty,1) + ReKiBuf(Re_Xferred) = InData%momenty(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%momentz) ) 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%momentz,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%momentz,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%momentz,1), UBOUND(InData%momentz,1) + ReKiBuf(Re_Xferred) = InData%momentz(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%forceNodesChord) ) 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%forceNodesChord,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%forceNodesChord,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%forceNodesChord,1), UBOUND(InData%forceNodesChord,1) + ReKiBuf(Re_Xferred) = InData%forceNodesChord(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%SuperController) ) 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%SuperController,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SuperController,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SuperController,1), UBOUND(InData%SuperController,1) + ReKiBuf(Re_Xferred) = InData%SuperController(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE OpFM_PackInput + + SUBROUTINE OpFM_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(OpFM_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_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 ! pxVel 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 (ASSOCIATED(OutData%pxVel)) DEALLOCATE(OutData%pxVel) + ALLOCATE(OutData%pxVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pxVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pxVel_Len = SIZE(OutData%pxVel) + IF (OutData%c_obj%pxVel_Len > 0) & + OutData%c_obj%pxVel = C_LOC( OutData%pxVel(i1_l) ) + DO i1 = LBOUND(OutData%pxVel,1), UBOUND(OutData%pxVel,1) + OutData%pxVel(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pyVel 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 (ASSOCIATED(OutData%pyVel)) DEALLOCATE(OutData%pyVel) + ALLOCATE(OutData%pyVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pyVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pyVel_Len = SIZE(OutData%pyVel) + IF (OutData%c_obj%pyVel_Len > 0) & + OutData%c_obj%pyVel = C_LOC( OutData%pyVel(i1_l) ) + DO i1 = LBOUND(OutData%pyVel,1), UBOUND(OutData%pyVel,1) + OutData%pyVel(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pzVel 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 (ASSOCIATED(OutData%pzVel)) DEALLOCATE(OutData%pzVel) + ALLOCATE(OutData%pzVel(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pzVel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pzVel_Len = SIZE(OutData%pzVel) + IF (OutData%c_obj%pzVel_Len > 0) & + OutData%c_obj%pzVel = C_LOC( OutData%pzVel(i1_l) ) + DO i1 = LBOUND(OutData%pzVel,1), UBOUND(OutData%pzVel,1) + OutData%pzVel(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pxForce 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 (ASSOCIATED(OutData%pxForce)) DEALLOCATE(OutData%pxForce) + ALLOCATE(OutData%pxForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pxForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pxForce_Len = SIZE(OutData%pxForce) + IF (OutData%c_obj%pxForce_Len > 0) & + OutData%c_obj%pxForce = C_LOC( OutData%pxForce(i1_l) ) + DO i1 = LBOUND(OutData%pxForce,1), UBOUND(OutData%pxForce,1) + OutData%pxForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pyForce 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 (ASSOCIATED(OutData%pyForce)) DEALLOCATE(OutData%pyForce) + ALLOCATE(OutData%pyForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pyForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pyForce_Len = SIZE(OutData%pyForce) + IF (OutData%c_obj%pyForce_Len > 0) & + OutData%c_obj%pyForce = C_LOC( OutData%pyForce(i1_l) ) + DO i1 = LBOUND(OutData%pyForce,1), UBOUND(OutData%pyForce,1) + OutData%pyForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pzForce 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 (ASSOCIATED(OutData%pzForce)) DEALLOCATE(OutData%pzForce) + ALLOCATE(OutData%pzForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pzForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pzForce_Len = SIZE(OutData%pzForce) + IF (OutData%c_obj%pzForce_Len > 0) & + OutData%c_obj%pzForce = C_LOC( OutData%pzForce(i1_l) ) + DO i1 = LBOUND(OutData%pzForce,1), UBOUND(OutData%pzForce,1) + OutData%pzForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdotForce 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 (ASSOCIATED(OutData%xdotForce)) DEALLOCATE(OutData%xdotForce) + ALLOCATE(OutData%xdotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%xdotForce_Len = SIZE(OutData%xdotForce) + IF (OutData%c_obj%xdotForce_Len > 0) & + OutData%c_obj%xdotForce = C_LOC( OutData%xdotForce(i1_l) ) + DO i1 = LBOUND(OutData%xdotForce,1), UBOUND(OutData%xdotForce,1) + OutData%xdotForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ydotForce 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 (ASSOCIATED(OutData%ydotForce)) DEALLOCATE(OutData%ydotForce) + ALLOCATE(OutData%ydotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ydotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%ydotForce_Len = SIZE(OutData%ydotForce) + IF (OutData%c_obj%ydotForce_Len > 0) & + OutData%c_obj%ydotForce = C_LOC( OutData%ydotForce(i1_l) ) + DO i1 = LBOUND(OutData%ydotForce,1), UBOUND(OutData%ydotForce,1) + OutData%ydotForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! zdotForce 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 (ASSOCIATED(OutData%zdotForce)) DEALLOCATE(OutData%zdotForce) + ALLOCATE(OutData%zdotForce(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%zdotForce.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%zdotForce_Len = SIZE(OutData%zdotForce) + IF (OutData%c_obj%zdotForce_Len > 0) & + OutData%c_obj%zdotForce = C_LOC( OutData%zdotForce(i1_l) ) + DO i1 = LBOUND(OutData%zdotForce,1), UBOUND(OutData%zdotForce,1) + OutData%zdotForce(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! pOrientation 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 (ASSOCIATED(OutData%pOrientation)) DEALLOCATE(OutData%pOrientation) + ALLOCATE(OutData%pOrientation(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%pOrientation.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%pOrientation_Len = SIZE(OutData%pOrientation) + IF (OutData%c_obj%pOrientation_Len > 0) & + OutData%c_obj%pOrientation = C_LOC( OutData%pOrientation(i1_l) ) + DO i1 = LBOUND(OutData%pOrientation,1), UBOUND(OutData%pOrientation,1) + OutData%pOrientation(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fx 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 (ASSOCIATED(OutData%fx)) DEALLOCATE(OutData%fx) + ALLOCATE(OutData%fx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%fx_Len = SIZE(OutData%fx) + IF (OutData%c_obj%fx_Len > 0) & + OutData%c_obj%fx = C_LOC( OutData%fx(i1_l) ) + DO i1 = LBOUND(OutData%fx,1), UBOUND(OutData%fx,1) + OutData%fx(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fy 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 (ASSOCIATED(OutData%fy)) DEALLOCATE(OutData%fy) + ALLOCATE(OutData%fy(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fy.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%fy_Len = SIZE(OutData%fy) + IF (OutData%c_obj%fy_Len > 0) & + OutData%c_obj%fy = C_LOC( OutData%fy(i1_l) ) + DO i1 = LBOUND(OutData%fy,1), UBOUND(OutData%fy,1) + OutData%fy(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! fz 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 (ASSOCIATED(OutData%fz)) DEALLOCATE(OutData%fz) + ALLOCATE(OutData%fz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%fz_Len = SIZE(OutData%fz) + IF (OutData%c_obj%fz_Len > 0) & + OutData%c_obj%fz = C_LOC( OutData%fz(i1_l) ) + DO i1 = LBOUND(OutData%fz,1), UBOUND(OutData%fz,1) + OutData%fz(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! momentx 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 (ASSOCIATED(OutData%momentx)) DEALLOCATE(OutData%momentx) + ALLOCATE(OutData%momentx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%momentx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%momentx_Len = SIZE(OutData%momentx) + IF (OutData%c_obj%momentx_Len > 0) & + OutData%c_obj%momentx = C_LOC( OutData%momentx(i1_l) ) + DO i1 = LBOUND(OutData%momentx,1), UBOUND(OutData%momentx,1) + OutData%momentx(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! momenty 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 (ASSOCIATED(OutData%momenty)) DEALLOCATE(OutData%momenty) + ALLOCATE(OutData%momenty(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%momenty.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%momenty_Len = SIZE(OutData%momenty) + IF (OutData%c_obj%momenty_Len > 0) & + OutData%c_obj%momenty = C_LOC( OutData%momenty(i1_l) ) + DO i1 = LBOUND(OutData%momenty,1), UBOUND(OutData%momenty,1) + OutData%momenty(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! momentz 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 (ASSOCIATED(OutData%momentz)) DEALLOCATE(OutData%momentz) + ALLOCATE(OutData%momentz(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%momentz.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%momentz_Len = SIZE(OutData%momentz) + IF (OutData%c_obj%momentz_Len > 0) & + OutData%c_obj%momentz = C_LOC( OutData%momentz(i1_l) ) + DO i1 = LBOUND(OutData%momentz,1), UBOUND(OutData%momentz,1) + OutData%momentz(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! forceNodesChord 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 (ASSOCIATED(OutData%forceNodesChord)) DEALLOCATE(OutData%forceNodesChord) + ALLOCATE(OutData%forceNodesChord(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%forceNodesChord.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%forceNodesChord_Len = SIZE(OutData%forceNodesChord) + IF (OutData%c_obj%forceNodesChord_Len > 0) & + OutData%c_obj%forceNodesChord = C_LOC( OutData%forceNodesChord(i1_l) ) + DO i1 = LBOUND(OutData%forceNodesChord,1), UBOUND(OutData%forceNodesChord,1) + OutData%forceNodesChord(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SuperController 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 (ASSOCIATED(OutData%SuperController)) DEALLOCATE(OutData%SuperController) + ALLOCATE(OutData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%SuperController_Len = SIZE(OutData%SuperController) + IF (OutData%c_obj%SuperController_Len > 0) & + OutData%c_obj%SuperController = C_LOC( OutData%SuperController(i1_l) ) + DO i1 = LBOUND(OutData%SuperController,1), UBOUND(OutData%SuperController,1) + OutData%SuperController(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE OpFM_UnPackInput + + SUBROUTINE OpFM_C2Fary_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- pxVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pxVel ) ) THEN + NULLIFY( InputData%pxVel ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pxVel, InputData%pxVel, (/InputData%C_obj%pxVel_Len/)) + END IF + END IF + + ! -- pyVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pyVel ) ) THEN + NULLIFY( InputData%pyVel ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pyVel, InputData%pyVel, (/InputData%C_obj%pyVel_Len/)) + END IF + END IF + + ! -- pzVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pzVel ) ) THEN + NULLIFY( InputData%pzVel ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pzVel, InputData%pzVel, (/InputData%C_obj%pzVel_Len/)) + END IF + END IF + + ! -- pxForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pxForce ) ) THEN + NULLIFY( InputData%pxForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pxForce, InputData%pxForce, (/InputData%C_obj%pxForce_Len/)) + END IF + END IF + + ! -- pyForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pyForce ) ) THEN + NULLIFY( InputData%pyForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pyForce, InputData%pyForce, (/InputData%C_obj%pyForce_Len/)) + END IF + END IF + + ! -- pzForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pzForce ) ) THEN + NULLIFY( InputData%pzForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pzForce, InputData%pzForce, (/InputData%C_obj%pzForce_Len/)) + END IF + END IF + + ! -- xdotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%xdotForce ) ) THEN + NULLIFY( InputData%xdotForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%xdotForce, InputData%xdotForce, (/InputData%C_obj%xdotForce_Len/)) + END IF + END IF + + ! -- ydotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%ydotForce ) ) THEN + NULLIFY( InputData%ydotForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%ydotForce, InputData%ydotForce, (/InputData%C_obj%ydotForce_Len/)) + END IF + END IF + + ! -- zdotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%zdotForce ) ) THEN + NULLIFY( InputData%zdotForce ) + ELSE + CALL C_F_POINTER(InputData%C_obj%zdotForce, InputData%zdotForce, (/InputData%C_obj%zdotForce_Len/)) + END IF + END IF + + ! -- pOrientation Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%pOrientation ) ) THEN + NULLIFY( InputData%pOrientation ) + ELSE + CALL C_F_POINTER(InputData%C_obj%pOrientation, InputData%pOrientation, (/InputData%C_obj%pOrientation_Len/)) + END IF + END IF + + ! -- fx Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%fx ) ) THEN + NULLIFY( InputData%fx ) + ELSE + CALL C_F_POINTER(InputData%C_obj%fx, InputData%fx, (/InputData%C_obj%fx_Len/)) + END IF + END IF + + ! -- fy Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%fy ) ) THEN + NULLIFY( InputData%fy ) + ELSE + CALL C_F_POINTER(InputData%C_obj%fy, InputData%fy, (/InputData%C_obj%fy_Len/)) + END IF + END IF + + ! -- fz Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%fz ) ) THEN + NULLIFY( InputData%fz ) + ELSE + CALL C_F_POINTER(InputData%C_obj%fz, InputData%fz, (/InputData%C_obj%fz_Len/)) + END IF + END IF + + ! -- momentx Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%momentx ) ) THEN + NULLIFY( InputData%momentx ) + ELSE + CALL C_F_POINTER(InputData%C_obj%momentx, InputData%momentx, (/InputData%C_obj%momentx_Len/)) + END IF + END IF + + ! -- momenty Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%momenty ) ) THEN + NULLIFY( InputData%momenty ) + ELSE + CALL C_F_POINTER(InputData%C_obj%momenty, InputData%momenty, (/InputData%C_obj%momenty_Len/)) + END IF + END IF + + ! -- momentz Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%momentz ) ) THEN + NULLIFY( InputData%momentz ) + ELSE + CALL C_F_POINTER(InputData%C_obj%momentz, InputData%momentz, (/InputData%C_obj%momentz_Len/)) + END IF + END IF + + ! -- forceNodesChord Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%forceNodesChord ) ) THEN + NULLIFY( InputData%forceNodesChord ) + ELSE + CALL C_F_POINTER(InputData%C_obj%forceNodesChord, InputData%forceNodesChord, (/InputData%C_obj%forceNodesChord_Len/)) + END IF + END IF + + ! -- SuperController Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%SuperController ) ) THEN + NULLIFY( InputData%SuperController ) + ELSE + CALL C_F_POINTER(InputData%C_obj%SuperController, InputData%SuperController, (/InputData%C_obj%SuperController_Len/)) + END IF + END IF + END SUBROUTINE OpFM_C2Fary_CopyInput + + SUBROUTINE OpFM_F2C_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- pxVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pxVel)) THEN + InputData%c_obj%pxVel_Len = 0 + InputData%c_obj%pxVel = C_NULL_PTR + ELSE + InputData%c_obj%pxVel_Len = SIZE(InputData%pxVel) + IF (InputData%c_obj%pxVel_Len > 0) & + InputData%c_obj%pxVel = C_LOC( InputData%pxVel( LBOUND(InputData%pxVel,1) ) ) + END IF + END IF + + ! -- pyVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pyVel)) THEN + InputData%c_obj%pyVel_Len = 0 + InputData%c_obj%pyVel = C_NULL_PTR + ELSE + InputData%c_obj%pyVel_Len = SIZE(InputData%pyVel) + IF (InputData%c_obj%pyVel_Len > 0) & + InputData%c_obj%pyVel = C_LOC( InputData%pyVel( LBOUND(InputData%pyVel,1) ) ) + END IF + END IF + + ! -- pzVel Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pzVel)) THEN + InputData%c_obj%pzVel_Len = 0 + InputData%c_obj%pzVel = C_NULL_PTR + ELSE + InputData%c_obj%pzVel_Len = SIZE(InputData%pzVel) + IF (InputData%c_obj%pzVel_Len > 0) & + InputData%c_obj%pzVel = C_LOC( InputData%pzVel( LBOUND(InputData%pzVel,1) ) ) + END IF + END IF + + ! -- pxForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pxForce)) THEN + InputData%c_obj%pxForce_Len = 0 + InputData%c_obj%pxForce = C_NULL_PTR + ELSE + InputData%c_obj%pxForce_Len = SIZE(InputData%pxForce) + IF (InputData%c_obj%pxForce_Len > 0) & + InputData%c_obj%pxForce = C_LOC( InputData%pxForce( LBOUND(InputData%pxForce,1) ) ) + END IF + END IF + + ! -- pyForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pyForce)) THEN + InputData%c_obj%pyForce_Len = 0 + InputData%c_obj%pyForce = C_NULL_PTR + ELSE + InputData%c_obj%pyForce_Len = SIZE(InputData%pyForce) + IF (InputData%c_obj%pyForce_Len > 0) & + InputData%c_obj%pyForce = C_LOC( InputData%pyForce( LBOUND(InputData%pyForce,1) ) ) + END IF + END IF + + ! -- pzForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pzForce)) THEN + InputData%c_obj%pzForce_Len = 0 + InputData%c_obj%pzForce = C_NULL_PTR + ELSE + InputData%c_obj%pzForce_Len = SIZE(InputData%pzForce) + IF (InputData%c_obj%pzForce_Len > 0) & + InputData%c_obj%pzForce = C_LOC( InputData%pzForce( LBOUND(InputData%pzForce,1) ) ) + END IF + END IF + + ! -- xdotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%xdotForce)) THEN + InputData%c_obj%xdotForce_Len = 0 + InputData%c_obj%xdotForce = C_NULL_PTR + ELSE + InputData%c_obj%xdotForce_Len = SIZE(InputData%xdotForce) + IF (InputData%c_obj%xdotForce_Len > 0) & + InputData%c_obj%xdotForce = C_LOC( InputData%xdotForce( LBOUND(InputData%xdotForce,1) ) ) + END IF + END IF + + ! -- ydotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%ydotForce)) THEN + InputData%c_obj%ydotForce_Len = 0 + InputData%c_obj%ydotForce = C_NULL_PTR + ELSE + InputData%c_obj%ydotForce_Len = SIZE(InputData%ydotForce) + IF (InputData%c_obj%ydotForce_Len > 0) & + InputData%c_obj%ydotForce = C_LOC( InputData%ydotForce( LBOUND(InputData%ydotForce,1) ) ) + END IF + END IF + + ! -- zdotForce Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%zdotForce)) THEN + InputData%c_obj%zdotForce_Len = 0 + InputData%c_obj%zdotForce = C_NULL_PTR + ELSE + InputData%c_obj%zdotForce_Len = SIZE(InputData%zdotForce) + IF (InputData%c_obj%zdotForce_Len > 0) & + InputData%c_obj%zdotForce = C_LOC( InputData%zdotForce( LBOUND(InputData%zdotForce,1) ) ) + END IF + END IF + + ! -- pOrientation Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%pOrientation)) THEN + InputData%c_obj%pOrientation_Len = 0 + InputData%c_obj%pOrientation = C_NULL_PTR + ELSE + InputData%c_obj%pOrientation_Len = SIZE(InputData%pOrientation) + IF (InputData%c_obj%pOrientation_Len > 0) & + InputData%c_obj%pOrientation = C_LOC( InputData%pOrientation( LBOUND(InputData%pOrientation,1) ) ) + END IF + END IF + + ! -- fx Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%fx)) THEN + InputData%c_obj%fx_Len = 0 + InputData%c_obj%fx = C_NULL_PTR + ELSE + InputData%c_obj%fx_Len = SIZE(InputData%fx) + IF (InputData%c_obj%fx_Len > 0) & + InputData%c_obj%fx = C_LOC( InputData%fx( LBOUND(InputData%fx,1) ) ) + END IF + END IF + + ! -- fy Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%fy)) THEN + InputData%c_obj%fy_Len = 0 + InputData%c_obj%fy = C_NULL_PTR + ELSE + InputData%c_obj%fy_Len = SIZE(InputData%fy) + IF (InputData%c_obj%fy_Len > 0) & + InputData%c_obj%fy = C_LOC( InputData%fy( LBOUND(InputData%fy,1) ) ) + END IF + END IF + + ! -- fz Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%fz)) THEN + InputData%c_obj%fz_Len = 0 + InputData%c_obj%fz = C_NULL_PTR + ELSE + InputData%c_obj%fz_Len = SIZE(InputData%fz) + IF (InputData%c_obj%fz_Len > 0) & + InputData%c_obj%fz = C_LOC( InputData%fz( LBOUND(InputData%fz,1) ) ) + END IF + END IF + + ! -- momentx Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%momentx)) THEN + InputData%c_obj%momentx_Len = 0 + InputData%c_obj%momentx = C_NULL_PTR + ELSE + InputData%c_obj%momentx_Len = SIZE(InputData%momentx) + IF (InputData%c_obj%momentx_Len > 0) & + InputData%c_obj%momentx = C_LOC( InputData%momentx( LBOUND(InputData%momentx,1) ) ) + END IF + END IF + + ! -- momenty Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%momenty)) THEN + InputData%c_obj%momenty_Len = 0 + InputData%c_obj%momenty = C_NULL_PTR + ELSE + InputData%c_obj%momenty_Len = SIZE(InputData%momenty) + IF (InputData%c_obj%momenty_Len > 0) & + InputData%c_obj%momenty = C_LOC( InputData%momenty( LBOUND(InputData%momenty,1) ) ) + END IF + END IF + + ! -- momentz Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%momentz)) THEN + InputData%c_obj%momentz_Len = 0 + InputData%c_obj%momentz = C_NULL_PTR + ELSE + InputData%c_obj%momentz_Len = SIZE(InputData%momentz) + IF (InputData%c_obj%momentz_Len > 0) & + InputData%c_obj%momentz = C_LOC( InputData%momentz( LBOUND(InputData%momentz,1) ) ) + END IF + END IF + + ! -- forceNodesChord Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%forceNodesChord)) THEN + InputData%c_obj%forceNodesChord_Len = 0 + InputData%c_obj%forceNodesChord = C_NULL_PTR + ELSE + InputData%c_obj%forceNodesChord_Len = SIZE(InputData%forceNodesChord) + IF (InputData%c_obj%forceNodesChord_Len > 0) & + InputData%c_obj%forceNodesChord = C_LOC( InputData%forceNodesChord( LBOUND(InputData%forceNodesChord,1) ) ) + END IF + END IF + + ! -- SuperController Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%SuperController)) THEN + InputData%c_obj%SuperController_Len = 0 + InputData%c_obj%SuperController = C_NULL_PTR + ELSE + InputData%c_obj%SuperController_Len = SIZE(InputData%SuperController) + IF (InputData%c_obj%SuperController_Len > 0) & + InputData%c_obj%SuperController = C_LOC( InputData%SuperController( LBOUND(InputData%SuperController,1) ) ) + END IF + END IF + END SUBROUTINE OpFM_F2C_CopyInput + + SUBROUTINE OpFM_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(OpFM_OutputType), INTENT(IN) :: SrcOutputData + TYPE(OpFM_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'OpFM_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcOutputData%u)) THEN + i1_l = LBOUND(SrcOutputData%u,1) + i1_u = UBOUND(SrcOutputData%u,1) + IF (.NOT. ASSOCIATED(DstOutputData%u)) THEN + ALLOCATE(DstOutputData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%u_Len = SIZE(DstOutputData%u) + IF (DstOutputData%c_obj%u_Len > 0) & + DstOutputData%c_obj%u = C_LOC( DstOutputData%u(i1_l) ) + END IF + DstOutputData%u = SrcOutputData%u +ENDIF +IF (ASSOCIATED(SrcOutputData%v)) THEN + i1_l = LBOUND(SrcOutputData%v,1) + i1_u = UBOUND(SrcOutputData%v,1) + IF (.NOT. ASSOCIATED(DstOutputData%v)) THEN + ALLOCATE(DstOutputData%v(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%v.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%v_Len = SIZE(DstOutputData%v) + IF (DstOutputData%c_obj%v_Len > 0) & + DstOutputData%c_obj%v = C_LOC( DstOutputData%v(i1_l) ) + END IF + DstOutputData%v = SrcOutputData%v +ENDIF +IF (ASSOCIATED(SrcOutputData%w)) THEN + i1_l = LBOUND(SrcOutputData%w,1) + i1_u = UBOUND(SrcOutputData%w,1) + IF (.NOT. ASSOCIATED(DstOutputData%w)) THEN + ALLOCATE(DstOutputData%w(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%w.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%w_Len = SIZE(DstOutputData%w) + IF (DstOutputData%c_obj%w_Len > 0) & + DstOutputData%c_obj%w = C_LOC( DstOutputData%w(i1_l) ) + END IF + DstOutputData%w = SrcOutputData%w +ENDIF +IF (ASSOCIATED(SrcOutputData%SuperController)) THEN + i1_l = LBOUND(SrcOutputData%SuperController,1) + i1_u = UBOUND(SrcOutputData%SuperController,1) + IF (.NOT. ASSOCIATED(DstOutputData%SuperController)) THEN + ALLOCATE(DstOutputData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%SuperController_Len = SIZE(DstOutputData%SuperController) + IF (DstOutputData%c_obj%SuperController_Len > 0) & + DstOutputData%c_obj%SuperController = C_LOC( DstOutputData%SuperController(i1_l) ) + END IF + DstOutputData%SuperController = SrcOutputData%SuperController +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE OpFM_CopyOutput + + SUBROUTINE OpFM_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(OpFM_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(OutputData%u)) THEN + DEALLOCATE(OutputData%u) + OutputData%u => NULL() + OutputData%C_obj%u = C_NULL_PTR + OutputData%C_obj%u_Len = 0 +ENDIF +IF (ASSOCIATED(OutputData%v)) THEN + DEALLOCATE(OutputData%v) + OutputData%v => NULL() + OutputData%C_obj%v = C_NULL_PTR + OutputData%C_obj%v_Len = 0 +ENDIF +IF (ASSOCIATED(OutputData%w)) THEN + DEALLOCATE(OutputData%w) + OutputData%w => NULL() + OutputData%C_obj%w = C_NULL_PTR + OutputData%C_obj%w_Len = 0 +ENDIF +IF (ASSOCIATED(OutputData%SuperController)) THEN + DEALLOCATE(OutputData%SuperController) + OutputData%SuperController => NULL() + OutputData%C_obj%SuperController = C_NULL_PTR + OutputData%C_obj%SuperController_Len = 0 +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE OpFM_DestroyOutput + + SUBROUTINE OpFM_PackOutput( 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(OpFM_OutputType), 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 = 'OpFM_PackOutput' + ! 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 ! u allocated yes/no + IF ( ASSOCIATED(InData%u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%u) ! u + END IF + Int_BufSz = Int_BufSz + 1 ! v allocated yes/no + IF ( ASSOCIATED(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 ! w allocated yes/no + IF ( ASSOCIATED(InData%w) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! w upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%w) ! w + END IF + Int_BufSz = Int_BufSz + 1 ! SuperController allocated yes/no + IF ( ASSOCIATED(InData%SuperController) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SuperController upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SuperController) ! SuperController + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%u) ) 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%u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u,1), UBOUND(InData%u,1) + ReKiBuf(Re_Xferred) = InData%u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(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. ASSOCIATED(InData%w) ) 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%w,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%w,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%w,1), UBOUND(InData%w,1) + ReKiBuf(Re_Xferred) = InData%w(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ASSOCIATED(InData%SuperController) ) 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%SuperController,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SuperController,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SuperController,1), UBOUND(InData%SuperController,1) + ReKiBuf(Re_Xferred) = InData%SuperController(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE OpFM_PackOutput + + SUBROUTINE OpFM_UnPackOutput( 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(OpFM_OutputType), 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 = 'OpFM_UnPackOutput' + ! 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 ! u 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 (ASSOCIATED(OutData%u)) DEALLOCATE(OutData%u) + ALLOCATE(OutData%u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%u_Len = SIZE(OutData%u) + IF (OutData%c_obj%u_Len > 0) & + OutData%c_obj%u = C_LOC( OutData%u(i1_l) ) + DO i1 = LBOUND(OutData%u,1), UBOUND(OutData%u,1) + OutData%u(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + 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 (ASSOCIATED(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 + OutData%c_obj%v_Len = SIZE(OutData%v) + IF (OutData%c_obj%v_Len > 0) & + OutData%c_obj%v = C_LOC( OutData%v(i1_l) ) + DO i1 = LBOUND(OutData%v,1), UBOUND(OutData%v,1) + OutData%v(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! w 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 (ASSOCIATED(OutData%w)) DEALLOCATE(OutData%w) + ALLOCATE(OutData%w(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%w.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%w_Len = SIZE(OutData%w) + IF (OutData%c_obj%w_Len > 0) & + OutData%c_obj%w = C_LOC( OutData%w(i1_l) ) + DO i1 = LBOUND(OutData%w,1), UBOUND(OutData%w,1) + OutData%w(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SuperController 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 (ASSOCIATED(OutData%SuperController)) DEALLOCATE(OutData%SuperController) + ALLOCATE(OutData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%SuperController_Len = SIZE(OutData%SuperController) + IF (OutData%c_obj%SuperController_Len > 0) & + OutData%c_obj%SuperController = C_LOC( OutData%SuperController(i1_l) ) + DO i1 = LBOUND(OutData%SuperController,1), UBOUND(OutData%SuperController,1) + OutData%SuperController(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE OpFM_UnPackOutput + + SUBROUTINE OpFM_C2Fary_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- u Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%u ) ) THEN + NULLIFY( OutputData%u ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%u, OutputData%u, (/OutputData%C_obj%u_Len/)) + END IF + END IF + + ! -- v Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%v ) ) THEN + NULLIFY( OutputData%v ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%v, OutputData%v, (/OutputData%C_obj%v_Len/)) + END IF + END IF + + ! -- w Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%w ) ) THEN + NULLIFY( OutputData%w ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%w, OutputData%w, (/OutputData%C_obj%w_Len/)) + END IF + END IF + + ! -- SuperController Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%SuperController ) ) THEN + NULLIFY( OutputData%SuperController ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%SuperController, OutputData%SuperController, (/OutputData%C_obj%SuperController_Len/)) + END IF + END IF + END SUBROUTINE OpFM_C2Fary_CopyOutput + + SUBROUTINE OpFM_F2C_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(OpFM_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- u Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%u)) THEN + OutputData%c_obj%u_Len = 0 + OutputData%c_obj%u = C_NULL_PTR + ELSE + OutputData%c_obj%u_Len = SIZE(OutputData%u) + IF (OutputData%c_obj%u_Len > 0) & + OutputData%c_obj%u = C_LOC( OutputData%u( LBOUND(OutputData%u,1) ) ) + END IF + END IF + + ! -- v Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%v)) THEN + OutputData%c_obj%v_Len = 0 + OutputData%c_obj%v = C_NULL_PTR + ELSE + OutputData%c_obj%v_Len = SIZE(OutputData%v) + IF (OutputData%c_obj%v_Len > 0) & + OutputData%c_obj%v = C_LOC( OutputData%v( LBOUND(OutputData%v,1) ) ) + END IF + END IF + + ! -- w Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%w)) THEN + OutputData%c_obj%w_Len = 0 + OutputData%c_obj%w = C_NULL_PTR + ELSE + OutputData%c_obj%w_Len = SIZE(OutputData%w) + IF (OutputData%c_obj%w_Len > 0) & + OutputData%c_obj%w = C_LOC( OutputData%w( LBOUND(OutputData%w,1) ) ) + END IF + END IF + + ! -- SuperController Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%SuperController)) THEN + OutputData%c_obj%SuperController_Len = 0 + OutputData%c_obj%SuperController = C_NULL_PTR + ELSE + OutputData%c_obj%SuperController_Len = SIZE(OutputData%SuperController) + IF (OutputData%c_obj%SuperController_Len > 0) & + OutputData%c_obj%SuperController = C_LOC( OutputData%SuperController( LBOUND(OutputData%SuperController,1) ) ) + END IF + END IF + END SUBROUTINE OpFM_F2C_CopyOutput + + + SUBROUTINE OpFM_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(OpFM_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(OpFM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL OpFM_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL OpFM_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL OpFM_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE OpFM_Input_ExtrapInterp + + + SUBROUTINE OpFM_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(OpFM_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(OpFM_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(OpFM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(u_out%pxVel) .AND. ASSOCIATED(u1%pxVel)) THEN + DO i1 = LBOUND(u_out%pxVel,1),UBOUND(u_out%pxVel,1) + b = -(u1%pxVel(i1) - u2%pxVel(i1)) + u_out%pxVel(i1) = u1%pxVel(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pyVel) .AND. ASSOCIATED(u1%pyVel)) THEN + DO i1 = LBOUND(u_out%pyVel,1),UBOUND(u_out%pyVel,1) + b = -(u1%pyVel(i1) - u2%pyVel(i1)) + u_out%pyVel(i1) = u1%pyVel(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pzVel) .AND. ASSOCIATED(u1%pzVel)) THEN + DO i1 = LBOUND(u_out%pzVel,1),UBOUND(u_out%pzVel,1) + b = -(u1%pzVel(i1) - u2%pzVel(i1)) + u_out%pzVel(i1) = u1%pzVel(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pxForce) .AND. ASSOCIATED(u1%pxForce)) THEN + DO i1 = LBOUND(u_out%pxForce,1),UBOUND(u_out%pxForce,1) + b = -(u1%pxForce(i1) - u2%pxForce(i1)) + u_out%pxForce(i1) = u1%pxForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pyForce) .AND. ASSOCIATED(u1%pyForce)) THEN + DO i1 = LBOUND(u_out%pyForce,1),UBOUND(u_out%pyForce,1) + b = -(u1%pyForce(i1) - u2%pyForce(i1)) + u_out%pyForce(i1) = u1%pyForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pzForce) .AND. ASSOCIATED(u1%pzForce)) THEN + DO i1 = LBOUND(u_out%pzForce,1),UBOUND(u_out%pzForce,1) + b = -(u1%pzForce(i1) - u2%pzForce(i1)) + u_out%pzForce(i1) = u1%pzForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%xdotForce) .AND. ASSOCIATED(u1%xdotForce)) THEN + DO i1 = LBOUND(u_out%xdotForce,1),UBOUND(u_out%xdotForce,1) + b = -(u1%xdotForce(i1) - u2%xdotForce(i1)) + u_out%xdotForce(i1) = u1%xdotForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%ydotForce) .AND. ASSOCIATED(u1%ydotForce)) THEN + DO i1 = LBOUND(u_out%ydotForce,1),UBOUND(u_out%ydotForce,1) + b = -(u1%ydotForce(i1) - u2%ydotForce(i1)) + u_out%ydotForce(i1) = u1%ydotForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%zdotForce) .AND. ASSOCIATED(u1%zdotForce)) THEN + DO i1 = LBOUND(u_out%zdotForce,1),UBOUND(u_out%zdotForce,1) + b = -(u1%zdotForce(i1) - u2%zdotForce(i1)) + u_out%zdotForce(i1) = u1%zdotForce(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pOrientation) .AND. ASSOCIATED(u1%pOrientation)) THEN + DO i1 = LBOUND(u_out%pOrientation,1),UBOUND(u_out%pOrientation,1) + b = -(u1%pOrientation(i1) - u2%pOrientation(i1)) + u_out%pOrientation(i1) = u1%pOrientation(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fx) .AND. ASSOCIATED(u1%fx)) THEN + DO i1 = LBOUND(u_out%fx,1),UBOUND(u_out%fx,1) + b = -(u1%fx(i1) - u2%fx(i1)) + u_out%fx(i1) = u1%fx(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fy) .AND. ASSOCIATED(u1%fy)) THEN + DO i1 = LBOUND(u_out%fy,1),UBOUND(u_out%fy,1) + b = -(u1%fy(i1) - u2%fy(i1)) + u_out%fy(i1) = u1%fy(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fz) .AND. ASSOCIATED(u1%fz)) THEN + DO i1 = LBOUND(u_out%fz,1),UBOUND(u_out%fz,1) + b = -(u1%fz(i1) - u2%fz(i1)) + u_out%fz(i1) = u1%fz(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momentx) .AND. ASSOCIATED(u1%momentx)) THEN + DO i1 = LBOUND(u_out%momentx,1),UBOUND(u_out%momentx,1) + b = -(u1%momentx(i1) - u2%momentx(i1)) + u_out%momentx(i1) = u1%momentx(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momenty) .AND. ASSOCIATED(u1%momenty)) THEN + DO i1 = LBOUND(u_out%momenty,1),UBOUND(u_out%momenty,1) + b = -(u1%momenty(i1) - u2%momenty(i1)) + u_out%momenty(i1) = u1%momenty(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momentz) .AND. ASSOCIATED(u1%momentz)) THEN + DO i1 = LBOUND(u_out%momentz,1),UBOUND(u_out%momentz,1) + b = -(u1%momentz(i1) - u2%momentz(i1)) + u_out%momentz(i1) = u1%momentz(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%forceNodesChord) .AND. ASSOCIATED(u1%forceNodesChord)) THEN + DO i1 = LBOUND(u_out%forceNodesChord,1),UBOUND(u_out%forceNodesChord,1) + b = -(u1%forceNodesChord(i1) - u2%forceNodesChord(i1)) + u_out%forceNodesChord(i1) = u1%forceNodesChord(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%SuperController) .AND. ASSOCIATED(u1%SuperController)) THEN + DO i1 = LBOUND(u_out%SuperController,1),UBOUND(u_out%SuperController,1) + b = -(u1%SuperController(i1) - u2%SuperController(i1)) + u_out%SuperController(i1) = u1%SuperController(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE OpFM_Input_ExtrapInterp1 + + + SUBROUTINE OpFM_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(OpFM_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(OpFM_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(OpFM_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(OpFM_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(u_out%pxVel) .AND. ASSOCIATED(u1%pxVel)) THEN + DO i1 = LBOUND(u_out%pxVel,1),UBOUND(u_out%pxVel,1) + b = (t(3)**2*(u1%pxVel(i1) - u2%pxVel(i1)) + t(2)**2*(-u1%pxVel(i1) + u3%pxVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pxVel(i1) + t(3)*u2%pxVel(i1) - t(2)*u3%pxVel(i1) ) * scaleFactor + u_out%pxVel(i1) = u1%pxVel(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pyVel) .AND. ASSOCIATED(u1%pyVel)) THEN + DO i1 = LBOUND(u_out%pyVel,1),UBOUND(u_out%pyVel,1) + b = (t(3)**2*(u1%pyVel(i1) - u2%pyVel(i1)) + t(2)**2*(-u1%pyVel(i1) + u3%pyVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pyVel(i1) + t(3)*u2%pyVel(i1) - t(2)*u3%pyVel(i1) ) * scaleFactor + u_out%pyVel(i1) = u1%pyVel(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pzVel) .AND. ASSOCIATED(u1%pzVel)) THEN + DO i1 = LBOUND(u_out%pzVel,1),UBOUND(u_out%pzVel,1) + b = (t(3)**2*(u1%pzVel(i1) - u2%pzVel(i1)) + t(2)**2*(-u1%pzVel(i1) + u3%pzVel(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pzVel(i1) + t(3)*u2%pzVel(i1) - t(2)*u3%pzVel(i1) ) * scaleFactor + u_out%pzVel(i1) = u1%pzVel(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pxForce) .AND. ASSOCIATED(u1%pxForce)) THEN + DO i1 = LBOUND(u_out%pxForce,1),UBOUND(u_out%pxForce,1) + b = (t(3)**2*(u1%pxForce(i1) - u2%pxForce(i1)) + t(2)**2*(-u1%pxForce(i1) + u3%pxForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pxForce(i1) + t(3)*u2%pxForce(i1) - t(2)*u3%pxForce(i1) ) * scaleFactor + u_out%pxForce(i1) = u1%pxForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pyForce) .AND. ASSOCIATED(u1%pyForce)) THEN + DO i1 = LBOUND(u_out%pyForce,1),UBOUND(u_out%pyForce,1) + b = (t(3)**2*(u1%pyForce(i1) - u2%pyForce(i1)) + t(2)**2*(-u1%pyForce(i1) + u3%pyForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pyForce(i1) + t(3)*u2%pyForce(i1) - t(2)*u3%pyForce(i1) ) * scaleFactor + u_out%pyForce(i1) = u1%pyForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pzForce) .AND. ASSOCIATED(u1%pzForce)) THEN + DO i1 = LBOUND(u_out%pzForce,1),UBOUND(u_out%pzForce,1) + b = (t(3)**2*(u1%pzForce(i1) - u2%pzForce(i1)) + t(2)**2*(-u1%pzForce(i1) + u3%pzForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pzForce(i1) + t(3)*u2%pzForce(i1) - t(2)*u3%pzForce(i1) ) * scaleFactor + u_out%pzForce(i1) = u1%pzForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%xdotForce) .AND. ASSOCIATED(u1%xdotForce)) THEN + DO i1 = LBOUND(u_out%xdotForce,1),UBOUND(u_out%xdotForce,1) + b = (t(3)**2*(u1%xdotForce(i1) - u2%xdotForce(i1)) + t(2)**2*(-u1%xdotForce(i1) + u3%xdotForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%xdotForce(i1) + t(3)*u2%xdotForce(i1) - t(2)*u3%xdotForce(i1) ) * scaleFactor + u_out%xdotForce(i1) = u1%xdotForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%ydotForce) .AND. ASSOCIATED(u1%ydotForce)) THEN + DO i1 = LBOUND(u_out%ydotForce,1),UBOUND(u_out%ydotForce,1) + b = (t(3)**2*(u1%ydotForce(i1) - u2%ydotForce(i1)) + t(2)**2*(-u1%ydotForce(i1) + u3%ydotForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%ydotForce(i1) + t(3)*u2%ydotForce(i1) - t(2)*u3%ydotForce(i1) ) * scaleFactor + u_out%ydotForce(i1) = u1%ydotForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%zdotForce) .AND. ASSOCIATED(u1%zdotForce)) THEN + DO i1 = LBOUND(u_out%zdotForce,1),UBOUND(u_out%zdotForce,1) + b = (t(3)**2*(u1%zdotForce(i1) - u2%zdotForce(i1)) + t(2)**2*(-u1%zdotForce(i1) + u3%zdotForce(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%zdotForce(i1) + t(3)*u2%zdotForce(i1) - t(2)*u3%zdotForce(i1) ) * scaleFactor + u_out%zdotForce(i1) = u1%zdotForce(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%pOrientation) .AND. ASSOCIATED(u1%pOrientation)) THEN + DO i1 = LBOUND(u_out%pOrientation,1),UBOUND(u_out%pOrientation,1) + b = (t(3)**2*(u1%pOrientation(i1) - u2%pOrientation(i1)) + t(2)**2*(-u1%pOrientation(i1) + u3%pOrientation(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%pOrientation(i1) + t(3)*u2%pOrientation(i1) - t(2)*u3%pOrientation(i1) ) * scaleFactor + u_out%pOrientation(i1) = u1%pOrientation(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fx) .AND. ASSOCIATED(u1%fx)) THEN + DO i1 = LBOUND(u_out%fx,1),UBOUND(u_out%fx,1) + b = (t(3)**2*(u1%fx(i1) - u2%fx(i1)) + t(2)**2*(-u1%fx(i1) + u3%fx(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%fx(i1) + t(3)*u2%fx(i1) - t(2)*u3%fx(i1) ) * scaleFactor + u_out%fx(i1) = u1%fx(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fy) .AND. ASSOCIATED(u1%fy)) THEN + DO i1 = LBOUND(u_out%fy,1),UBOUND(u_out%fy,1) + b = (t(3)**2*(u1%fy(i1) - u2%fy(i1)) + t(2)**2*(-u1%fy(i1) + u3%fy(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%fy(i1) + t(3)*u2%fy(i1) - t(2)*u3%fy(i1) ) * scaleFactor + u_out%fy(i1) = u1%fy(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%fz) .AND. ASSOCIATED(u1%fz)) THEN + DO i1 = LBOUND(u_out%fz,1),UBOUND(u_out%fz,1) + b = (t(3)**2*(u1%fz(i1) - u2%fz(i1)) + t(2)**2*(-u1%fz(i1) + u3%fz(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%fz(i1) + t(3)*u2%fz(i1) - t(2)*u3%fz(i1) ) * scaleFactor + u_out%fz(i1) = u1%fz(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momentx) .AND. ASSOCIATED(u1%momentx)) THEN + DO i1 = LBOUND(u_out%momentx,1),UBOUND(u_out%momentx,1) + b = (t(3)**2*(u1%momentx(i1) - u2%momentx(i1)) + t(2)**2*(-u1%momentx(i1) + u3%momentx(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%momentx(i1) + t(3)*u2%momentx(i1) - t(2)*u3%momentx(i1) ) * scaleFactor + u_out%momentx(i1) = u1%momentx(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momenty) .AND. ASSOCIATED(u1%momenty)) THEN + DO i1 = LBOUND(u_out%momenty,1),UBOUND(u_out%momenty,1) + b = (t(3)**2*(u1%momenty(i1) - u2%momenty(i1)) + t(2)**2*(-u1%momenty(i1) + u3%momenty(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%momenty(i1) + t(3)*u2%momenty(i1) - t(2)*u3%momenty(i1) ) * scaleFactor + u_out%momenty(i1) = u1%momenty(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%momentz) .AND. ASSOCIATED(u1%momentz)) THEN + DO i1 = LBOUND(u_out%momentz,1),UBOUND(u_out%momentz,1) + b = (t(3)**2*(u1%momentz(i1) - u2%momentz(i1)) + t(2)**2*(-u1%momentz(i1) + u3%momentz(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%momentz(i1) + t(3)*u2%momentz(i1) - t(2)*u3%momentz(i1) ) * scaleFactor + u_out%momentz(i1) = u1%momentz(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%forceNodesChord) .AND. ASSOCIATED(u1%forceNodesChord)) THEN + DO i1 = LBOUND(u_out%forceNodesChord,1),UBOUND(u_out%forceNodesChord,1) + b = (t(3)**2*(u1%forceNodesChord(i1) - u2%forceNodesChord(i1)) + t(2)**2*(-u1%forceNodesChord(i1) + u3%forceNodesChord(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%forceNodesChord(i1) + t(3)*u2%forceNodesChord(i1) - t(2)*u3%forceNodesChord(i1) ) * scaleFactor + u_out%forceNodesChord(i1) = u1%forceNodesChord(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(u_out%SuperController) .AND. ASSOCIATED(u1%SuperController)) THEN + DO i1 = LBOUND(u_out%SuperController,1),UBOUND(u_out%SuperController,1) + b = (t(3)**2*(u1%SuperController(i1) - u2%SuperController(i1)) + t(2)**2*(-u1%SuperController(i1) + u3%SuperController(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%SuperController(i1) + t(3)*u2%SuperController(i1) - t(2)*u3%SuperController(i1) ) * scaleFactor + u_out%SuperController(i1) = u1%SuperController(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE OpFM_Input_ExtrapInterp2 + + + SUBROUTINE OpFM_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(OpFM_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(OpFM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL OpFM_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL OpFM_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL OpFM_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE OpFM_Output_ExtrapInterp + + + SUBROUTINE OpFM_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(OpFM_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(OpFM_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(OpFM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(y_out%u) .AND. ASSOCIATED(y1%u)) THEN + DO i1 = LBOUND(y_out%u,1),UBOUND(y_out%u,1) + b = -(y1%u(i1) - y2%u(i1)) + y_out%u(i1) = y1%u(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%v) .AND. ASSOCIATED(y1%v)) THEN + DO i1 = LBOUND(y_out%v,1),UBOUND(y_out%v,1) + b = -(y1%v(i1) - y2%v(i1)) + y_out%v(i1) = y1%v(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%w) .AND. ASSOCIATED(y1%w)) THEN + DO i1 = LBOUND(y_out%w,1),UBOUND(y_out%w,1) + b = -(y1%w(i1) - y2%w(i1)) + y_out%w(i1) = y1%w(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%SuperController) .AND. ASSOCIATED(y1%SuperController)) THEN + DO i1 = LBOUND(y_out%SuperController,1),UBOUND(y_out%SuperController,1) + b = -(y1%SuperController(i1) - y2%SuperController(i1)) + y_out%SuperController(i1) = y1%SuperController(i1) + b * ScaleFactor + 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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE OpFM_Output_ExtrapInterp1 + + + SUBROUTINE OpFM_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(OpFM_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(OpFM_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(OpFM_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(OpFM_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'OpFM_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(y_out%u) .AND. ASSOCIATED(y1%u)) THEN + DO i1 = LBOUND(y_out%u,1),UBOUND(y_out%u,1) + b = (t(3)**2*(y1%u(i1) - y2%u(i1)) + t(2)**2*(-y1%u(i1) + y3%u(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%u(i1) + t(3)*y2%u(i1) - t(2)*y3%u(i1) ) * scaleFactor + y_out%u(i1) = y1%u(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%v) .AND. ASSOCIATED(y1%v)) THEN + DO i1 = LBOUND(y_out%v,1),UBOUND(y_out%v,1) + b = (t(3)**2*(y1%v(i1) - y2%v(i1)) + t(2)**2*(-y1%v(i1) + y3%v(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%v(i1) + t(3)*y2%v(i1) - t(2)*y3%v(i1) ) * scaleFactor + y_out%v(i1) = y1%v(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%w) .AND. ASSOCIATED(y1%w)) THEN + DO i1 = LBOUND(y_out%w,1),UBOUND(y_out%w,1) + b = (t(3)**2*(y1%w(i1) - y2%w(i1)) + t(2)**2*(-y1%w(i1) + y3%w(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%w(i1) + t(3)*y2%w(i1) - t(2)*y3%w(i1) ) * scaleFactor + y_out%w(i1) = y1%w(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ASSOCIATED(y_out%SuperController) .AND. ASSOCIATED(y1%SuperController)) THEN + DO i1 = LBOUND(y_out%SuperController,1),UBOUND(y_out%SuperController,1) + b = (t(3)**2*(y1%SuperController(i1) - y2%SuperController(i1)) + t(2)**2*(-y1%SuperController(i1) + y3%SuperController(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%SuperController(i1) + t(3)*y2%SuperController(i1) - t(2)*y3%SuperController(i1) ) * scaleFactor + y_out%SuperController(i1) = y1%SuperController(i1) + b + c * t_out + 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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE OpFM_Output_ExtrapInterp2 + +END MODULE OpenFOAM_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/openfoam/src/OpenFOAM_Types.h b/OpenFAST/modules/openfoam/src/OpenFOAM_Types.h new file mode 100644 index 000000000..d113c4099 --- /dev/null +++ b/OpenFAST/modules/openfoam/src/OpenFOAM_Types.h @@ -0,0 +1,108 @@ +//!STARTOFREGISTRYGENERATEDFILE 'OpenFOAM_Types.h' +//! +//! WARNING This file is generated automatically by the FAST registry. +//! Do not edit. Your changes to this file will be lost. +//! + +#ifndef _OpenFOAM_TYPES_H +#define _OpenFOAM_TYPES_H + + +#ifdef _WIN32 //define something for Windows (32-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#elif _WIN64 //define something for Windows (64-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#else +# include <stdbool.h> +# define CALL +#endif + + + typedef struct OpFM_InitInputType { + void * object ; + int NumSC2Ctrl ; + int NumCtrl2SC ; + int NumActForcePtsBlade ; + int NumActForcePtsTower ; + float * StructBldRNodes ; int StructBldRNodes_Len ; + float * StructTwrHNodes ; int StructTwrHNodes_Len ; + float BladeLength ; + float TowerHeight ; + float TowerBaseHeight ; + } OpFM_InitInputType_t ; + typedef struct OpFM_InitOutputType { + void * object ; + char * WriteOutputHdr ; int WriteOutputHdr_Len ; + char * WriteOutputUnt ; int WriteOutputUnt_Len ; + + } OpFM_InitOutputType_t ; + typedef struct OpFM_MiscVarType { + void * object ; + + + + + + + + + } OpFM_MiscVarType_t ; + typedef struct OpFM_ParameterType { + void * object ; + float AirDens ; + int NumBl ; + int NMappings ; + int NnodesVel ; + int NnodesForce ; + int NnodesForceBlade ; + int NnodesForceTower ; + float * forceBldRnodes ; int forceBldRnodes_Len ; + float * forceTwrHnodes ; int forceTwrHnodes_Len ; + float BladeLength ; + float TowerHeight ; + float TowerBaseHeight ; + } OpFM_ParameterType_t ; + typedef struct OpFM_InputType { + void * object ; + float * pxVel ; int pxVel_Len ; + float * pyVel ; int pyVel_Len ; + float * pzVel ; int pzVel_Len ; + float * pxForce ; int pxForce_Len ; + float * pyForce ; int pyForce_Len ; + float * pzForce ; int pzForce_Len ; + float * xdotForce ; int xdotForce_Len ; + float * ydotForce ; int ydotForce_Len ; + float * zdotForce ; int zdotForce_Len ; + float * pOrientation ; int pOrientation_Len ; + float * fx ; int fx_Len ; + float * fy ; int fy_Len ; + float * fz ; int fz_Len ; + float * momentx ; int momentx_Len ; + float * momenty ; int momenty_Len ; + float * momentz ; int momentz_Len ; + float * forceNodesChord ; int forceNodesChord_Len ; + float * SuperController ; int SuperController_Len ; + } OpFM_InputType_t ; + typedef struct OpFM_OutputType { + void * object ; + float * u ; int u_Len ; + float * v ; int v_Len ; + float * w ; int w_Len ; + float * SuperController ; int SuperController_Len ; + float * WriteOutput ; int WriteOutput_Len ; + } OpFM_OutputType_t ; + typedef struct OpFM_UserData { + OpFM_InitInputType_t OpFM_InitInput ; + OpFM_InitOutputType_t OpFM_InitOutput ; + OpFM_MiscVarType_t OpFM_Misc ; + OpFM_ParameterType_t OpFM_Param ; + OpFM_InputType_t OpFM_Input ; + OpFM_OutputType_t OpFM_Output ; + } OpFM_t ; + +#endif // _OpenFOAM_TYPES_H + + +//!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/orcaflex-interface/CMakeLists.txt b/OpenFAST/modules/orcaflex-interface/CMakeLists.txt new file mode 100644 index 000000000..fb6da14c5 --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/CMakeLists.txt @@ -0,0 +1,43 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/OrcaFlexInterface.txt ${CMAKE_CURRENT_LIST_DIR}/src/OrcaFlexInterface_Types.f90) +endif() + +if (ORCA_DLL_LOAD) + add_definitions(-DLibLoad) +else (ORCA_DLL_LOAD) + add_definitions(-DNO_LibLoad) +endif (ORCA_DLL_LOAD) + +add_library(orcaflexlib + src/OrcaFlexInterface.f90 + src/OrcaFlexInterface_Types.f90 +) +target_link_libraries(orcaflexlib nwtclibs) + +add_executable(orca_driver + src/OrcaDriver_Subs.f90 + src/OrcaDriver_Types.f90 + src/OrcaDriver.f90) +target_link_libraries(orca_driver orcaflexlib) + +install(TARGETS orcaflexlib orca_driver + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/orcaflex-interface/README.md b/OpenFAST/modules/orcaflex-interface/README.md new file mode 100644 index 000000000..ccf27b6cd --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/README.md @@ -0,0 +1,28 @@ +# OrcaFlex Interface Module +The legacy version of this module and additional documentation are available +the [NWTC Software Portal](https://nwtc.nrel.gov/OrcaFlexInterface/). + +## Overview +OrcaFlex is a commercial software package developed by Orcina for the design +and analysis of marine systems. When the OrcaFlexInterface module is used in +OpenFAST, all hydrodynamic and mooring loads will be computed using OrcaFlex, +while the turbine, tower, and floating platform structural dynamics; +aerodynamics; and control and electrical-drive dynamics will be computed by +OpenFAST. + +To use this module with OpenFAST, you will need the following: +- OpenFAST for Windows® +- A valid OrcaFlex license +- FASTlinkDLL.dll; This DLL is compiled by Orcina and is called by OpenFAST + during the simulation to compute the loads on the platform by OrcaFlex. + Both 32- and 64-bit versions of FASTlinkDLL.dll, which are compatible with + the 32- and 64-bit Windows executable versions of OpenFAST, are available + at https://orcina.com/Support/FASTlink.zip. + +## Sample Models +Sample models for OpenFAST and OrcaFlexInterface can be downloaded +[here](https://nwtc.nrel.gov/enduser). + +This self-extracting archive for Windows contains documentation on using the +OpenFAST-OrcaFlex interface as well as several sample models set to call +FASTlinkDLL. diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaDriver.f90 b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver.f90 new file mode 100644 index 000000000..667e588cd --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver.f90 @@ -0,0 +1,655 @@ +!**************************************************************************** +! +! PROGRAM: OrcaDriver - This program tests the OrcaFlex calling. +! +!**************************************************************************** +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! This file is part of Orca. +! +! 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: 173 $ +! URL: $HeadURL: https://wind-dev.nrel.gov/svn/OrcaFlexInterface/Trunk/Source/Driver/OrcaDriver.f90 $ +!********************************************************************************************************************************** + +PROGRAM OrcaDriver + + USE NWTC_Library + USE OrcaDriver_Types + USE OrcaDriver_Subs + USE OrcaFlexInterface + + IMPLICIT NONE + + ! Info on this code + TYPE( ProgDesc ), PARAMETER :: ProgInfo = ProgDesc("Orca_Driver","","") + INTEGER(IntKi) :: OrcaDriver_Verbose = 5 ! Verbose level. 0 = none, 5 = some, 10 = lots + + ! Types needed here (from Orca module) + TYPE(Orca_InitInputType) :: Orca_InitInp ! Data for initialization -- this is where the input info goes + TYPE(Orca_InputType) :: Orca_u ! input -- contains xyz coords of interest -- set 1 + TYPE(Orca_ParameterType) :: Orca_p ! Parameters + TYPE(Orca_ContinuousStateType) :: Orca_x ! Continous State Data (not used here) + TYPE(Orca_DiscreteStateType) :: Orca_xd ! Discrete State Data (not used here) + TYPE(Orca_ConstraintStateType) :: Orca_z ! Constraint State Data (not used here) + TYPE(Orca_OtherStateType) :: Orca_OtherState ! Other State Data + TYPE(Orca_MiscVarType) :: Orca_m ! Misc/optimization data + TYPE(Orca_OutputType) :: Orca_y ! Output Data -- contains the velocities at xyz -- set 1 + TYPE(Orca_InitOutputType) :: Orca_InitOut ! Output Data -- contains the names and units + + + ! Local variables for this code + TYPE(OrcaDriver_Flags) :: CLSettingsFlags ! Flags indicating which command line arguments were specified + TYPE(OrcaDriver_Settings) :: CLSettings ! Command line arguments passed in + TYPE(OrcaDriver_Flags) :: SettingsFlags ! Flags indicating which settings were specified (includes CL and ipt file) + TYPE(OrcaDriver_Settings) :: Settings ! Driver settings + REAL(DbKi) :: Timer(1: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 + REAL(ReKi) :: CosineMatrix(3,3) ! Cosine matrix for rotations in the mesh + + + ! Local variables for storing the arrays + REAL(ReKi),ALLOCATABLE :: TimeList(:) !< Timestamp data + REAL(ReKi),ALLOCATABLE :: PointsList(:,:) !< (X,Y,Z,R1,R2,R3) coordinates read from Points input file. + REAL(ReKi),ALLOCATABLE :: VelocList(:,:) !< Translational and rotational time derivatives at each point in PointsList + REAL(ReKi),ALLOCATABLE :: AccelList(:,:) !< Translational and rotational 2nd time derivatives at each point in PointsList + INTEGER(IntKi) :: I,J,K,Counter !< Generic counters/indices + + ! Temporary variables + CHARACTER(1024) :: TmpChar ! Temporary character variable + LOGICAL :: TmpFlag ! Temporary flag + INTEGER(IntKi) :: TmpUnit ! Temporary unit for quick I/O operation + INTEGER(IntKi) :: debug_print_unit + + ! Local Error Handling + INTEGER(IntKi) :: ErrStat + CHARACTER(1024) :: ErrMsg + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + INTEGER(IntKi) :: LenErrMsgTmp ! Length of ErrMsgTmp + + + !-------------------------------------------------------------------------- + !-=-=- Initialize the Library -=-=- + !-------------------------------------------------------------------------- + + CALL NWTC_Init + CALL DispNVD(ProgInfo) + +! Beep = .FALSE. + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Setup the program -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + ! Start the timer + CALL CPU_TIME( Timer(1) ) + + + ! Set some CLSettings to null/default values + CLSettings%DvrIptFileName = "" ! No input name name until set + CLSettings%OrcaIptFileName = "" ! No Orca input file name until set + CLSettings%AddedMassFileName = "" ! No summary file name until set + CLSettings%DT = 0.0_DbKi + CLSettings%PtfmCoord = 0.0_ReKi ! Set to origin + CLSettings%PtfmVeloc = 0.0_ReKi ! Set to origin + CLSettings%PtfmAccel = 0.0_ReKi ! Set to origin + CLSettings%PointsFileName = "" ! No points file name until set + CLSettings%PointsOutputName = "" ! No points file name until 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%OrcaIptFile = .FALSE. ! Orca input filename given as command line argument + CLSettingsFlags%AddedMass = .FALSE. ! create a summary at command line? (data extents in the wind file) + CLSettingsFlags%Degrees = .FALSE. ! Angles specified in degrees for PtfmCoord and PtfmVeloc + CLSettingsFlags%PointsDegrees = .FALSE. ! Angles specified in degrees in the points file + CLSettingsFlags%AddedMassFile = .FALSE. ! create a summary file of the output? + CLSettingsFlags%DT = .FALSE. ! specified a resolution in time + CLSettingsFlags%DTDefault = .FALSE. ! specified 'DEFAULT' for resolution in time + CLSettingsFlags%PtfmCoord = .FALSE. ! PtfmCoord specified + CLSettingsFlags%PtfmVeloc = .FALSE. ! PtfmVeloc specified + CLSettingsFlags%PtfmAccel = .FALSE. ! PtfmAccel specified + CLSettingsFlags%PointsFile = .FALSE. ! points filename to read in -- command line option only + 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? + + + ! Initialize the driver settings to their default values (same as the CL -- command line -- values) + Settings = CLSettings + SettingsFlags = CLSettingsFlags + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Parse the command line inputs -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + CALL RetrieveArgs( CLSettings, CLSettingsFlags, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= 0 ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + + ! Check if we are doing verbose error reporting + IF ( CLSettingsFlags%VVerbose ) THEN + OrcaDriver_Verbose = 10_IntKi + ENDIF + IF ( CLSettingsFlags%Verbose ) THEN + OrcaDriver_Verbose = 7_IntKi + ENDIF + + + + ! Verbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr('--- Settings from the command line: ---') + CALL printSettings( CLSettingsFlags, CLSettings ) + CALL WrSCr(NewLine) + ENDIF + + + ! Verbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr('--- Driver settings (before reading driver ipt file): ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + + + ! Copy the input file information from the CLSettings to the Settings. + ! At this point only one input file type can be set. + IF ( CLSettingsFlags%DvrIptFile ) THEN + SettingsFlags%DvrIptFile = CLSettingsFlags%DvrIptFile + Settings%DvrIptFileName = CLSettings%DvrIptFileName + ELSE + SettingsFlags%OrcaIptFile = CLSettingsFlags%OrcaIptFile + Settings%OrcaIptFileName = CLSettings%OrcaIptFileName + ENDIF + + + ! If the filename given was not the Orca input file (-ifw option), then it is treated + ! as the driver input file (flag should be set correctly by RetrieveArgs). So, we must + ! open this. + IF ( SettingsFlags%DvrIptFile ) THEN + + ! Read the driver input file + CALL ReadDvrIptFile( CLSettings%DvrIptFileName, SettingsFlags, Settings, ProgInfo, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= 0 ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + + ! VVerbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after reading the driver ipt file: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + ! VVerbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) CALL WrScr('Updating driver settings with command line arguments') + + + ! Now that we have read in the driver input settings, we need to override these with any + ! values from the command line arguments. The .TRUE. indicates that a driver input file + ! was read. + CALL UpdateSettingsWithCL( SettingsFlags, Settings, CLSettingsFlags, CLSettings, .TRUE., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + ! Verbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrSCr(NewLine//'--- Driver settings after copying over CL settings: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + ELSE + + + ! VVerbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) CALL WrScr('No driver input file used. Updating driver settings with command line arguments') + + + ! Since there were no settings picked up from the driver input file, we need to copy over all + ! the CLSettings into the regular Settings. The .FALSE. is a flag indicating that the driver + ! input file was not read. + CALL UpdateSettingsWithCL( SettingsFlags, Settings, CLSettingsFlags, CLSettings, .FALSE., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + ! Verbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after copying over CL settings: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + ENDIF + + + + ! Sanity check: if an input points file is specified, make sure it actually exists. Open it if specified + + IF ( SettingsFlags%PointsFile ) THEN + 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 + CALL ReadPointsFile( Settings%PointsFileName, SettingsFlags%PointsDegrees, TimeList, PointsList, VelocList, AccelList, ErrStat,ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL ProgAbort( ErrMsg ) + ELSEIF ( ErrStat /= 0 ) THEN + CALL WrScr( NewLine//ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + ! Make name for output + CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName ) + Settings%PointsOutputName = TRIM(Settings%PointsOutputName)//'.Forces.dat' + + CALL WrScr(NewLine//"Read "//TRIM(Num2LStr(SIZE(PointsList,DIM=2)))//" points from '"//TRIM(Settings%PointsFileName)// & + "'. Results output to '"//TRIM(Settings%PointsOutputName)//"'.") + + ! 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)) + + ENDIF + + + + ! AddedMass file output + IF ( SettingsFlags%AddedMassFile ) THEN + + ! Create AddedMassFile output name + IF ( SettingsFlags%DvrIptFile ) THEN + CALL GetRoot( Settings%DvrIptFileName, Settings%AddedMassFileName ) + ELSE + CALL GetRoot( Settings%OrcaIptFileName, Settings%AddedMassFileName ) + ENDIF + + Settings%AddedMassFileName = TRIM(Settings%AddedMassFileName)//'.am' + + IF ( OrcaDriver_Verbose >= 10_IntKi ) CALL WrScr('Driver summary output file: '//TRIM(Settings%AddedMassFileName)) + + ENDIF + + + ! Give status update of the driver flags, if verbose + IF ( OrcaDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after finalizing: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + ! Set the TMax value (this is a made up number just so that we have something we can pass to OrcaFlex + IF ( SettingsFlags%PointsFile ) THEN + Settings%TMax = SIZE(PointsList,DIM=2)*Settings%DT + ELSE + Settings%TMax=100_ReKi + ENDIF + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Initialize the Module -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! Initialize the Orca module --> it will initialize the DLL. + + + ! Some initialization settings + Orca_InitInp%InputFile = Settings%OrcaIptFileName + CALL GetRoot( Orca_InitInp%InputFile, Orca_InitInp%RootName ) + Orca_InitInp%TMax = Settings%TMax + + + IF ( OrcaDriver_Verbose >= 5_IntKi ) CALL WrScr('Calling Orca_Init...') + + + CALL Orca_Init( Orca_InitInp, Orca_u, Orca_p, & + Orca_x, Orca_xd, Orca_z, Orca_OtherState, & + Orca_y, Orca_m, Settings%DT, Orca_InitOut, 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' Orca_Init returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + + + ! Let user know we returned from the Orca code if verbose + IF ( OrcaDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Orca_Init CALL returned without errors.'//NewLine) + + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Other Setup -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! Setup any additional things + + + ! Timestep -- The timestep for the calling Orca_CalcOutput may need to be changed to what is in the file if the + ! DT = DEFAULT option was used in the driver input file. This does not need to be changed in the Orca_Parameters + ! since Orca doesn't care what the timestep is. + + IF ( SettingsFlags%DTDefault ) THEN + + Settings%DT = 0.025_ReKi + + IF ( OrcaDriver_Verbose >= 5 ) CALL WrScr(' DEFAULT requested for DT. Setting to 0.025 for arbitrary reasons (the developer picked some random number here).') + + ENDIF + + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Time stepping loop -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + + IF ( OrcaDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Calling Orca_CalcOutput...'//NewLine) + + + IF ( SettingsFlags%PointsFile ) THEN + DO I=1,SIZE(PointsList,DIM=2) + + ! Setup the mesh coordinates (columns 1-6) + Orca_u%PtfmMesh%TranslationDisp(:,1) = PointsList(1:3,I) + + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', PointsList(4,I), PointsList(5,I), PointsList(6,I), CosineMatrix, 'CosineMatrix calc', ErrStat, ErrMsg ) + Orca_u%PtfmMesh%Orientation(:,:,1) = CosineMatrix + + + ! Setup the velocity terms of the mesh (columns 7:12) + Orca_u%PtfmMesh%TranslationVel(:,1) = VelocList(1:3,I) + Orca_u%PtfmMesh%RotationVel(:,1) = VelocList(4:6,I) + + + ! Setup the Acceleration terms of the mesh (columns 13:18) + Orca_u%PtfmMesh%TranslationAcc(:,1) = AccelList(1:3,I) + Orca_u%PtfmMesh%RotationAcc(:,1) = AccelList(4:6,I) + + + TimeNow = TimeList(I) + + + + + + + ! Get results for Points data from Orca + CALL Orca_CalcOutput( TimeNow, Orca_u, Orca_p, & + Orca_x, Orca_xd, Orca_z, Orca_OtherState, & + Orca_y, Orca_m, ErrStat, ErrMsg) + +!debug_print_unit = 80 +!call WrNumAryFileNR(debug_print_unit,(/TimeNow/), "1x,ES15.5E3", ErrStat, ErrMsg ) +!call WrNumAryFileNR(debug_print_unit,Orca_y%WriteOutput, "1x,ES15.5E3", ErrStat, ErrMsg ) +!write(debug_print_unit,'()') + + + + ! 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' Orca_Calc returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + + ! Output the Points results for this timestep + CALL PointsForce_OutputWrite( Settings%ProgInfo, Settings%PointsOutputUnit, Settings%PointsOutputName, Settings%PointsFileName, & + SettingsFlags%PointsOutputInit, SettingsFlags%PointsDegrees, SIZE(PointsList,DIM=2), & + TimeNow, Orca_InitOut, Orca_p, Orca_u, Orca_y, ErrStat, ErrMsg ) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ENDIF + + + ENDDO + ENDIF + + + IF ( SettingsFlags%PtfmCoord ) THEN + + ! Setup the mesh coordinates (columns 1-6) for the coordinate specified + Orca_u%PtfmMesh%TranslationDisp(:,1) = Settings%PtfmCoord(1:3) + + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', Settings%PtfmCoord(4), Settings%PtfmCoord(5), Settings%PtfmCoord(6), CosineMatrix, 'CosineMatrix calc', ErrStat, ErrMsg ) + Orca_u%PtfmMesh%Orientation(:,:,1) = CosineMatrix + + + ! Setup the velocity terms of the mesh (columns 7:12) + Orca_u%PtfmMesh%TranslationVel(:,1) = Settings%PtfmVeloc(1:3) + Orca_u%PtfmMesh%RotationVel(:,1) = Settings%PtfmVeloc(4:6) + + + ! Setup the Acceleration terms of the mesh (columns 13:18) + Orca_u%PtfmMesh%TranslationAcc(:,1) = Settings%PtfmAccel(1:3) + Orca_u%PtfmMesh%RotationAcc(:,1) = Settings%PtfmAccel(4:6) + + TimeNow = Settings%DT + + ! Get results for Points data from Orca + CALL Orca_CalcOutput( TimeNow, Orca_u, Orca_p, & + Orca_x, Orca_xd, Orca_z, Orca_OtherState, & + Orca_y, Orca_m, 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' Orca_Calc returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + + + + + ! write the output file. This is a bit of a hack here to use the same routine as used for the points file output + TmpFlag = .FALSE. ! Tell the subroutine that it has not initialized the file before + TmpUnit = -1 ! Temporary unit number to pass + CALL GetRoot( Settings%DvrIptFileName, TmpChar ) ! Get the root name + TmpChar=TRIM(TmpChar)//'.out' + + ! Call routine to write the output file for this one point + CALL PointsForce_OutputWrite( Settings%ProgInfo, TmpUnit, TmpChar, TmpChar, TmpFlag, SettingsFlags%Degrees, 0, & + TimeNow, Orca_InitOut, Orca_p, Orca_u, Orca_y, ErrStat, ErrMsg ) + CLOSE(TmpUnit) + + ! 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' PointsForce_OutputWrite: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + + ENDIF + + ! Verbose error reporting + IF ( OrcaDriver_Verbose >= 10_IntKi ) THEN + CALL WrScr(NewLine//'--- Driver settings after CalcOutput call: ---') + CALL printSettings( SettingsFlags, Settings ) + CALL WrScr(NewLine) + ENDIF + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Calculate OtherStates -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + ! + ! None + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- Output results -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + + ! AddedMass output to command line + IF ( SettingsFlags%AddedMass ) THEN + CALL AddedMassMessage( Orca_m%PtfmAM, .FALSE., ErrMsgTmp, LenErrMsgTmp ) ! .FALSE. for no comment characters. ErrMsgTmp holds the message. + CALL WrScr(NewLine//TRIM(ErrMsgTmp)//NewLine) + ENDIF + + ! AddedMass output to file + IF ( SettingsFlags%AddedMassFile ) THEN + CALL AddedMass_OutputWrite( Settings, SettingsFlags%AddedMassOutputInit, & + Orca_m%PtfmAM, 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' AddedMass_OutputWrite ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ENDIF + ENDIF + + + + !-------------------------------------------------------------------------------------------------------------------------------- + !-=-=- We are done, so close everything down -=-=- + !-------------------------------------------------------------------------------------------------------------------------------- + + CALL Orca_DestroyInitOutput( Orca_InitOut, ErrStat, ErrMsg ) + + CALL Orca_End( Orca_u, Orca_p, & + Orca_x, Orca_xd, Orca_z, Orca_OtherState, & + Orca_y, Orca_m, 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. ( OrcaDriver_Verbose >= 7_IntKi ) ) THEN + CALL WrScr(NewLine//' Orca_End returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & + NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( OrcaDriver_Verbose < 7_IntKi ) ) THEN + CALL ProgWarn( ErrMsg ) + ErrStat = ErrID_None + ErrMsg = '' + ELSEIF ( OrcaDriver_Verbose >= 7_IntKi ) THEN + CALL WrScr(NewLine//' Orca_End call: ok') + ENDIF + + + CALL DriverCleanup() + +CONTAINS + + SUBROUTINE DriverCleanup() + + + CLOSE( Settings%AddedMassOutputUnit ) + CLOSE( Settings%PointsOutputUnit ) + + + ! Find out how long this actually took + CALL CPU_TIME( Timer(2) ) + CALL WrScr(NewLine//'Elapsed time: '//TRIM(Num2LStr(Timer(2)-Timer(1)))//' seconds') + + + END SUBROUTINE DriverCleanup + + +END PROGRAM OrcaDriver + + + + diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Subs.f90 b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Subs.f90 new file mode 100644 index 000000000..e07b6105c --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Subs.f90 @@ -0,0 +1,2088 @@ +!********************************************************************************************************************************** +! +! MODULE: OrcaDriver_Subs - This module contains subroutines used by the OrcaFlexInterface Driver program +! +!********************************************************************************************************************************** +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! This file is part of OrcaFlexInterface. +! +! 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: 169 $ +! URL: $HeadURL: https://wind-dev.nrel.gov/svn/OrcaFlexInterface/Trunk/Source/Driver/OrcaDriver_Subs.f90 $ +!********************************************************************************************************************************** +MODULE OrcaDriver_Subs + + USE NWTC_Library + USE OrcaDriver_Types + IMPLICIT NONE + + +CONTAINS +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +SUBROUTINE DispHelpText( ErrStat, ErrMsg ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Print out help information ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + USE NWTC_Library + + IMPLICIT NONE + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Statement about usage + CALL WrScr("") + CALL WrScr(" Syntax: InlowWind_Driver <filename> [options]") + CALL WrScr("") + CALL WrScr(" where: <filename> -- Name of driver input file to use") + CALL WrScr("") + CALL WrScr(" The following options will overwrite values in the driver input file:") + CALL WrScr(" "//SwChar//"DT[#] -- timestep ") + CALL WrScr(" "//SwChar//"degrees -- input angles specified in degrees ") + CALL WrScr(" "//SwChar//"pointsdegrees -- input angles in points filespecified in degrees ") + CALL WrScr(" "//SwChar//"Coord[X,Y,Z,R1,R2,R3] ") + CALL WrScr(" -- platform origin centered at [X,Y,Z] ") + CALL WrScr(" with Roll / Pitch / Yaw of [R1,R2,R3] ") + CALL WrScr(" "//SwChar//"points[FILE] -- calculates at a given position specified in a ") + CALL WrScr(" comma delimited FILE.") + CALL WrScr(" "//SwChar//"v -- increase verbose level to 7 ") + CALL WrScr(" "//SwChar//"vv -- increase verbose level to 10 ") + CALL WrScr(" "//SwChar//"help -- print this help menu and exit") + CALL WrScr("") + CALL WrScr(" Notes:") + CALL WrScr(" -- Options are not case sensitive.") + CALL WrScr(" -- If no coordinates are specified, assumed to be at (0,0,0) with no rotation") + CALL WrScr("") + + +END SUBROUTINE DispHelpText + + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!> This subroutine retrieves the command line arguments and passes them to the +!! ::ParseArg routine for processing. +SUBROUTINE RetrieveArgs( CLSettings, CLFlags, ErrStat, ErrMsg ) + + USE NWTC_Library + USE OrcaDriver_Types + + IMPLICIT NONE + + ! Storing the arguments + TYPE( OrcaDriver_Flags ), INTENT( OUT) :: CLFlags !< Flags indicating which command line arguments were specified + TYPE( OrcaDriver_Settings ), INTENT( OUT) :: CLSettings !< Command line arguments passed in + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + ! Local variable + INTEGER(IntKi) :: i !< Generic counter + CHARACTER(1024) :: Arg !< argument given + CHARACTER(1024) :: ArgUC !< Upper case argument to check + INTEGER(IntKi) :: NumInputArgs !< Number of argements passed in from command line + LOGICAL :: ifwFlag !< The -ifw flag was set + CHARACTER(1024) :: FileName !< Filename from the command line. + LOGICAL :: FileNameGiven !< Flag indicating if a filename was given. + + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status (for calls) + CHARACTER(1024) :: ErrMsgTmp !< Temporary error message (for calls) + CHARACTER(*), PARAMETER :: RoutineName = 'RetrieveArgs' + + + ! initialize some things + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + FileNameGiven = .FALSE. + FileName = '' + + + ! Check how many arguments are passed in + NumInputArgs = COMMAND_ARGUMENT_COUNT() + + ! exit if we don't have enough + IF (NumInputArgs == 0) THEN + CALL SetErrStat(ErrID_Fatal," Insufficient Arguments. Use option "//SwChar//"help for help menu.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + + ! Loop through all the arguments, and store them + DO i=1,NumInputArgs + ! get the ith argument + CALL get_command_argument(i, Arg) + ArgUC = Arg + + ! convert to uppercase + CALL Conv2UC( ArgUC ) + + + ! Check to see if it is a control parameter or the filename + IF ( INDEX( SwChar, ArgUC(1:1) ) > 0 ) THEN + + ! check to see if we asked for help + IF ( ArgUC(2:5) == "HELP" ) THEN + CALL DispHelpText( ErrStat, ErrMsg ) + CALL ProgExit(0) + ENDIF + + + ! Check the argument and put it where it belongs + ! chop the SwChar off before passing the argument + CALL ParseArg( CLSettings, CLFlags, ArgUC(2:), Arg(2:), ifwFlag, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF (ErrStat>AbortErrLev) RETURN + + ELSE + + ! since there is no switch character, assume it is the filename, unless we already set one + IF ( FileNameGiven ) THEN + CALL SetErrStat(ErrID_Fatal," Multiple driver input filenames given: "//TRIM(FileName)//", "//TRIM(Arg), & + ErrStat,ErrMsg,RoutineName) + RETURN + ELSE + FileName = TRIM(Arg) + FileNameGiven = .TRUE. + ENDIF + + ENDIF + END DO + + + ! Was a filename given? + IF ( .NOT. FileNameGiven ) THEN + CALL SetErrStat( ErrID_Fatal, " No filename given.", ErrStat, ErrMsg, RoutineName ) + RETURN + ELSE + CLSettings%DvrIptFileName = TRIM(FileName) + CLFlags%DvrIptFile = .TRUE. + ENDIF + + + + + !------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + CONTAINS + + + !------------------------------------------------------------------------------- + FUNCTION StringToReal( StringIn, ErrStat ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Convert a string to a real number ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + IMPLICIT NONE + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + + ! Input + CHARACTER(*), INTENT(IN ) :: StringIn + + ! Returned value + REAL(ReKi) :: StringToReal + + ! Local Variables + INTEGER(IntKi) :: ErrStatTmp ! Temporary variable to hold the error status + + read( StringIn, *, iostat=ErrStatTmp) StringToReal + + ! If that isn't a number, only warn since we can continue by skipping this value + IF ( ErrStatTmp .ne. 0 ) ErrStat = ErrID_Warn + + END FUNCTION StringToReal + + + + !------------------------------------------------------------------------------- + SUBROUTINE ParseArg( CLSettings, CLFlags, ThisArgUC, ThisArg, ifwFlagSet, ErrStat, ErrMsg ) + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + ! Parse and store the input argument ! + !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-! + + USE NWTC_Library + USE OrcaDriver_Types + USE OrcaFlexInterface_Types + + IMPLICIT NONE + + ! Storing the arguments + TYPE( OrcaDriver_Flags ), INTENT(INOUT) :: CLFlags ! Flags indicating which arguments were specified + TYPE( OrcaDriver_Settings ), INTENT(INOUT) :: CLSettings ! Arguments passed in + + CHARACTER(*), INTENT(IN ) :: ThisArgUC ! The current argument (upper case for testing) + CHARACTER(*), INTENT(IN ) :: ThisArg ! The current argument (as passed in for error messages) + LOGICAL, INTENT(INOUT) :: ifwFlagSet ! Was the -ifw flag given? + + ! Error Handling + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + + ! local variables + INTEGER(IntKi) :: Delim1 ! where the [ is + INTEGER(IntKi) :: Delim2 ! where the ] is + INTEGER(IntKi) :: DelimSep ! where the : is + INTEGER(IntKi) :: DelimSep2 ! where the : is + INTEGER(IntKi) :: DelimSep3 ! where the : is + INTEGER(IntKi) :: DelimSep4 ! where the : is + INTEGER(IntKi) :: DelimSep5 ! where the : is + REAL(ReKi) :: TempReal ! temp variable to hold a real + + INTEGER(IntKi) :: ErrStatTmp ! Temporary error status for calls + CHARACTER(*), PARAMETER :: RoutineName = 'ParseArg' + + + + ! Initialize some things + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + ErrMsg = '' + + ! Get the delimiters -- returns 0 if there isn't one + Delim1 = INDEX(ThisArgUC,'[') + Delim2 = INDEX(ThisArgUC,']') + DelimSep = INDEX(ThisArgUC,':') + + + ! check that if there is an opening bracket, then there is a closing one + IF ( (Delim1 > 0_IntKi ) .and. (Delim2 < Delim1) ) THEN + CALL SetErrStat(ErrID_Warn," Syntax error in option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! check that if there is a colon, then there are brackets + IF ( (DelimSep > 0_IntKi) .and. (Delim1 == 0_IntKi) ) THEN + CALL SetErrStat(ErrID_Warn," Syntax error in option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + + ! If no delimeters were given, than this option is simply a flag + IF ( Delim1 == 0_IntKi ) THEN + ! check to see if the filename is the name of the Orca input file + IF ( ThisArgUC(1:13)== "POINTSDEGREES" ) THEN + CLFlags%PointsDegrees = .TRUE. + RETURN + ELSEIF ( ThisArgUC(1:13)== "AddedMassFile" ) THEN + CLFlags%AddedMassFile = .TRUE. + RETURN + ELSEIF ( ThisArgUC(1:9) == "AddedMass" ) THEN + CLFlags%AddedMass = .TRUE. + RETURN + ELSEIF ( ThisArgUC(1:7) == "DEGREES" ) THEN + CLFlags%Degrees = .TRUE. + RETURN + ELSEIF ( ThisArgUC(1:2) == "VV" ) THEN + CLFlags%VVerbose = .TRUE. + RETURN + ELSEIF ( ThisArgUC(1:1) == "V" ) THEN + CLFlags%Verbose = .TRUE. + RETURN + ELSE + CALL SetErrStat( ErrID_Warn," Unrecognized option '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options.", & + ErrStat,ErrMsg,RoutineName) + ENDIF + + ENDIF + + + + ! "Veloc[X,Y,Z,R1,R2,R3]" + IF ( ThisArgUC(1:Delim1) == "Veloc[" ) THEN + DelimSep = INDEX(ThisArgUC,',') + DelimSep2= INDEX(ThisArgUC(DelimSep+1:),',') + DelimSep + IF ( DelimSep2 <= DelimSep ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep3= INDEX(ThisArgUC(DelimSep2+1:),',') + DelimSep + IF ( DelimSep3 <= DelimSep2 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep4= INDEX(ThisArgUC(DelimSep3+1:),',') + DelimSep + IF ( DelimSep4 <= DelimSep3 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep4+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep4 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep5+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep5 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(1) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_FATAL," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:DelimSep2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(2) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Third Value + TempReal = StringToReal( ThisArgUC(DelimSep2+1:DelimSep3-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(3) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fourth Value + TempReal = StringToReal( ThisArgUC(DelimSep3+1:DelimSep4-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(4) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fifth Value + TempReal = StringToReal( ThisArgUC(DelimSep4+1:DelimSep5-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(5) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Sixth Value + TempReal = StringToReal( ThisArgUC(DelimSep5+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmVeloc = .TRUE. + CLSettings%PtfmVeloc(6) = TempReal + ELSE + CLFlags%PtfmVeloc = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + + + ! "Accel[X,Y,Z,R1,R2,R3]" + ELSEIF ( ThisArgUC(1:Delim1) == "Accel[" ) THEN + DelimSep = INDEX(ThisArgUC,',') + DelimSep2= INDEX(ThisArgUC(DelimSep+1:),',') + DelimSep + IF ( DelimSep2 <= DelimSep ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep3= INDEX(ThisArgUC(DelimSep2+1:),',') + DelimSep + IF ( DelimSep3 <= DelimSep2 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep4= INDEX(ThisArgUC(DelimSep3+1:),',') + DelimSep + IF ( DelimSep4 <= DelimSep3 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep4+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep4 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep5+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep5 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(1) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_FATAL," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:DelimSep2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(2) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Third Value + TempReal = StringToReal( ThisArgUC(DelimSep2+1:DelimSep3-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(3) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fourth Value + TempReal = StringToReal( ThisArgUC(DelimSep3+1:DelimSep4-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(4) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fifth Value + TempReal = StringToReal( ThisArgUC(DelimSep4+1:DelimSep5-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(5) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Sixth Value + TempReal = StringToReal( ThisArgUC(DelimSep5+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmAccel = .TRUE. + CLSettings%PtfmAccel(6) = TempReal + ELSE + CLFlags%PtfmAccel = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! "Coord[X,Y,Z,R1,R2,R3]" + ELSEIF ( ThisArgUC(1:Delim1) == "Coord[" ) THEN + DelimSep = INDEX(ThisArgUC,',') + DelimSep2= INDEX(ThisArgUC(DelimSep+1:),',') + DelimSep + IF ( DelimSep2 <= DelimSep ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep3= INDEX(ThisArgUC(DelimSep2+1:),',') + DelimSep + IF ( DelimSep3 <= DelimSep2 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep4= INDEX(ThisArgUC(DelimSep3+1:),',') + DelimSep + IF ( DelimSep4 <= DelimSep3 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep4+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep4 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + DelimSep5= INDEX(ThisArgUC(DelimSep5+1:),',') + DelimSep + IF ( DelimSep5 <= DelimSep5 ) THEN + CALL SetErrStat(ErrID_Warn," Unrecognized coordinate in '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + ! First Value + TempReal = StringToReal( ThisArgUC(Delim1+1:DelimSep-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(1) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat(ErrID_FATAL," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Second Value + TempReal = StringToReal( ThisArgUC(DelimSep+1:DelimSep2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(2) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat(ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Third Value + TempReal = StringToReal( ThisArgUC(DelimSep2+1:DelimSep3-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(3) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fourth Value + TempReal = StringToReal( ThisArgUC(DelimSep3+1:DelimSep4-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(4) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Fifth Value + TempReal = StringToReal( ThisArgUC(DelimSep4+1:DelimSep5-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(5) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + ! Sixth Value + TempReal = StringToReal( ThisArgUC(DelimSep5+1:Delim2-1), ErrStatTmp ) + IF ( ErrStatTmp == ErrID_None ) THEN + CLFlags%PtfmCoord = .TRUE. + CLSettings%PtfmCoord(6) = TempReal + ELSE + CLFlags%PtfmCoord = .FALSE. + IF ( ErrStatTmp == ErrID_Warn ) THEN + CALL SetErrStat( ErrStatTmp," Invalid number in option '"//SwChar//TRIM(ThisArg)//"'. Ignoring.", & + ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal," Something failed in parsing option '"//SwChar//TRIM(ThisArg)//"'.", & + ErrStat, ErrMsg, RoutineName) + ENDIF + RETURN + ENDIF + + + ! "POINTS[FILE]" + ELSEIF( ThisArgUC(1:Delim1) == "POINTS[" ) THEN + CLFlags%PointsFile = .TRUE. + CLSettings%PointsFileName = ThisArg(Delim1+1:Delim2-1) + ELSE + ErrMsg = " Unrecognized option: '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options." + ErrStat = ErrID_Warn + ENDIF + + END SUBROUTINE ParseArg + !------------------------------------------------------------------------------- + + + +END SUBROUTINE RetrieveArgs + + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!> This subroutine reads the driver input file and sets up the flags and settings +!! for the driver code. Any settings from the command line options will override +!! this. +SUBROUTINE ReadDvrIptFile( DvrFileName, DvrFlags, DvrSettings, ProgInfo, ErrStat, ErrMsg ) + + CHARACTER(1024), INTENT(IN ) :: DvrFileName + TYPE(OrcaDriver_Flags), INTENT(INOUT) :: DvrFlags + TYPE(OrcaDriver_Settings), INTENT(INOUT) :: DvrSettings + TYPE(ProgDesc), INTENT(IN ) :: ProgInfo + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER(IntKi) :: UnIn ! Unit number for the driver input file + CHARACTER(1024) :: FileName ! Name of OrcaFlexInterface driver input file + + ! Input file echoing + LOGICAL :: EchoFileContents ! Do we echo the driver file out or not? + INTEGER(IntKi) :: UnEchoLocal ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFileName ! Name of OrcaFlexInterface driver echo file + + ! Time steps + CHARACTER(1024) :: DTChr ! Character string for timesteps size (to handle DEFAULT value) + + ! Local error handling + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + INTEGER(IntKi) :: ErrStatTmp2 !< Temporary error status for IO checks + CHARACTER(1024) :: ErrMsgTmp !< Temporary error messages for calls + CHARACTER(*), PARAMETER :: RoutineName = 'ReadDvrIptFile' + + ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input + UnEchoLocal = -1 + + FileName = TRIM(DvrFileName) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile( UnIn, FileName, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL WrScr( 'Opening OrcaFlexInterface Driver input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName,' OrcaFlexInterface Driver input file header line 1', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL ReadCom( UnIn, FileName, 'OrcaFlexInterface Driver input file header line 2', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Echo Input Files. + CALL ReadVar ( UnIn, FileName, EchoFileContents, 'Echo', 'Echo Input', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( EchoFileContents ) THEN + + EchoFileName = TRIM(FileName)//'.ech' + CALL GetNewUnit( UnEchoLocal ) + CALL OpenEcho ( UnEchoLocal, EchoFileName, ErrStatTmp, ErrMsgTmp, ProgInfo ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( UnIn ) + RETURN + ENDIF + + + REWIND(UnIn) + + + ! Reread and echo + CALL ReadCom( UnIn, FileName,' OrcaFlexInterface Driver input file header line 1', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + CALL ReadCom( UnIn, FileName, 'OrcaFlexInterface Driver input file header line 2', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Echo Input Files. + CALL ReadVar ( UnIn, FileName, EchoFileContents, 'Echo', 'Echo Input', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + + ENDIF + + + !------------------------------------------------------------------------------------------------- + ! OrcaFlexInterface setup section + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,' OrcaFlexInterface setup section, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! DT -- Timestep size for the driver to take (or DEFAULT for what the file contains) + CALL ReadVar( UnIn, FileName,DTChr,'DTChr',' Character string for Timestep size for the driver to take (or DEFAULT for what the file contains).', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Check if we asked for the DEFAULT (use what is in the file) + CALL Conv2UC( DTChr ) + IF ( TRIM(DTChr) == 'DEFAULT' ) THEN ! we asked for the default value + DvrFlags%DT = .TRUE. + DvrFlags%DTDefault = .TRUE. ! This flag tells us to use the inflow wind file values + ELSE + ! We probably have a number if it isn't 'DEFAULT', so do an internal read and check to + ! make sure that it was appropriately interpretted. + READ (DTChr,*,IOSTAT=ErrStatTmp2) DvrSettings%DT + IF ( ErrStatTmp /= ErrID_None ) THEN ! problem in the read, so parse the error. + CALL CheckIOS ( ErrStatTmp2, '', 'DT',NumType, ErrStatTmp, ErrMsgTmp, .TRUE. ) + RETURN + ELSE ! Was ok, so set the flags + DvrFlags%DT = .TRUE. + DvrFlags%DTDefault = .FALSE. + ENDIF + ENDIF + + + ! OrcaFlexInterface input file + CALL ReadVar( UnIn, FileName,DvrSettings%OrcaIptFileName,'OrcaIptFileName',' OrcaFlexInterface input filename', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ELSE + DvrFlags%OrcaIptFile = .TRUE. + ENDIF + + + + !------------------------------------------------------------------------------------------------- + ! PtfmCoordinates + !------------------------------------------------------------------------------------------------- + + ! Header + CALL ReadCom( UnIn, FileName,' Coordinates, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! PtfmCoord -- PtfmCoord of the windfield needed. + CALL ReadVar( UnIn, FileName,DvrFlags%PtfmCoord,'PtfmCoord',' Use a set of coordinates?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + DvrFlags%PtfmVeloc = DvrFlags%PtfmCoord + DvrFlags%PtfmAccel = DvrFlags%PtfmCoord + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! Read the coordinates if the flag is set, otherwise skip the line + IF ( DvrFlags%PtfmCoord ) THEN + + ! Degrees -- PtfmCoord of the windfield needed. + CALL ReadVar( UnIn, FileName,DvrFlags%Degrees,'Degrees',' Angles specified in degrees?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! PtfmCoord -- The coordinates to pass to the DLL + CALL ReadAry ( UnIn, FileName, DvrSettings%PtfmCoord(1:6), 6, 'PtfmCoord(1:6)', & + 'platform coordinate', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! PtfmVeloc -- The coordinates to pass to the DLL + CALL ReadAry ( UnIn, FileName, DvrSettings%PtfmVeloc(1:6), 6, 'PtfmVeloc(1:6)', & + 'platform coordinate', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! PtfmAccel -- The coordinates to pass to the DLL + CALL ReadAry ( UnIn, FileName, DvrSettings%PtfmAccel(1:6), 6, 'PtfmAccel(1:6)', & + 'platform coordinate', ErrStatTmp, ErrMsgTmp, UnEchoLocal) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + ! Write the added mass matrix to the screen + CALL ReadVar( UnIn, FileName,DvrFlags%AddedMass,'AddedMass',' Write table of added mass to screen.', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ELSE + DvrFlags%AddedMass = .TRUE. + ENDIF + + ! Write the added mass matrix to a file + CALL ReadVar( UnIn, FileName,DvrFlags%AddedMassFile,'AddedMassFile',' Write added Mass matrix to file.', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ELSE + DvrFlags%AddedMassFile = .TRUE. + ENDIF + + ELSE + CALL ReadCom( UnIn, FileName,' Skipping the degrees flag since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the platform coordinate since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the platform velocity since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the platform acceleration since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the Added mass matrix output since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + CALL ReadCom( UnIn, FileName,' Skipping the added mass matrix file output since not calculating anything.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ENDIF + + + + + !------------------------------------------------------------------------------------------------- + ! points file input + !------------------------------------------------------------------------------------------------- + + ! Header line + CALL ReadCom( UnIn, FileName,' Points file input, comment line', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + ! PointsFile -- Read a points file + CALL ReadVar( UnIn, FileName,DvrFlags%PointsFile,'PointsFile',' Read a points file?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + + + IF ( DvrFlags%PointsFile ) THEN + ! Points file in degrees + CALL ReadVar( UnIn, FileName,DvrFlags%PointsDegrees,'PointsDegrees',' Angles in points file given in degrees?', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ! Points input file + CALL ReadVar( UnIn, FileName,DvrSettings%PointsFileName,'PointsFileName',' Points file input filename', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ELSE + ! Skip the next entry points file section. + CALL ReadCom( UnIn, FileName,' Skipping the degreespoints flag since not using it.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ! Skip the next entry points file section. + CALL ReadCom( UnIn, FileName,' Skipping the points filename since not using it.', ErrStatTmp, ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF + ENDIF + + + ! Close the echo and input file + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + + +CONTAINS + + !---------------------------------------------------------------------------------------------------- + !> The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + !! any existing echo information + SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) + LOGICAL, INTENT(IN ) :: EchoFlag ! local version of echo flag + INTEGER(IntKi), INTENT(IN ) :: UnEcho ! echo unit number + + ! Close this module's echo file + IF ( EchoFlag ) THEN + CLOSE(UnEcho) + ENDIF + END SUBROUTINE CleanupEchoFile + + + +END SUBROUTINE ReadDvrIptFile + + +!> This subroutine copies an command line (CL) settings over to the program settings. Warnings are +!! issued if anything is changed from what the driver input file requested. +SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVRIPT, ErrStat, ErrMsg ) + + TYPE(OrcaDriver_Flags), INTENT(INOUT) :: DvrFlags + TYPE(OrcaDriver_Settings), INTENT(INOUT) :: DvrSettings + TYPE(OrcaDriver_Flags), INTENT(IN ) :: CLFlags + TYPE(OrcaDriver_Settings), INTENT(IN ) :: CLSettings + LOGICAL, INTENT(IN ) :: DVRIPT + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + + + ! Local variables + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + CHARACTER(1024) :: ErrMsgTmp !< Temporary error status for calls + CHARACTER(*), PARAMETER :: RoutineName = 'UpdateSettingsWithCL' + LOGICAL :: WindGridModify !< Did we modify any of the WindGrid related settings? + + INTEGER(IntKi) :: I !< local counter + + ! Initialization + WindGridModify = .FALSE. + + ! Initialize the error handling + ErrStat = ErrID_None + ErrMsg = '' + ErrStatTmp = ErrID_None + ErrMsgTmp = '' + + + !-------------------------------------------- + ! Did we change any time information? + !-------------------------------------------- + + + ! Check DT + IF ( CLFlags%DT ) THEN + IF ( DvrFlags%DT .AND. ( .NOT. EqualRealNos(DvrSettings%DT, CLSettings%DT) ) ) THEN + CALL SetErrStat( ErrID_Warn, ' Overriding driver input value for DT with '//TRIM(Num2LStr(CLSettings%DT))//'.', & + ErrStat,ErrMsg,RoutineName) + ELSE + DvrFlags%DT = .TRUE. + ENDIF + DvrSettings%DT = CLSettings%DT + ENDIF + + + !-------------------------------------------- + ! Did we change the coordinate info? + !-------------------------------------------- + + IF ( CLFlags%PtfmCoord ) THEN + ! If we are overriding driver input file settings, tell user + IF ( DvrFlags%PtfmCoord ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for platform coordinate.', & + ErrStat,ErrMsg,RoutineName ) + ENDIF + DvrSettings%PtfmCoord = CLSettings%PtfmCoord + DvrFlags%PtfmCoord = .TRUE. + ENDIF + + IF ( CLFlags%PtfmVeloc ) THEN + ! If we are overriding driver input file settings, tell user + IF ( DvrFlags%PtfmVeloc ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for platform velocities.', & + ErrStat,ErrMsg,RoutineName ) + ENDIF + DvrSettings%PtfmVeloc = CLSettings%PtfmVeloc + DvrFlags%PtfmVeloc = .TRUE. + ENDIF + + IF ( CLFlags%PtfmAccel ) THEN + ! If we are overriding driver input file settings, tell user + IF ( DvrFlags%PtfmAccel ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for platform velocities.', & + ErrStat,ErrMsg,RoutineName ) + ENDIF + DvrSettings%PtfmAccel = CLSettings%PtfmAccel + DvrFlags%PtfmAccel = .TRUE. + ENDIF + + ! If only one of the PtfmCoord, PtfmVeloc, or PtfmAccel flags is set to true, the other should be set also + IF ( DvrFlags%PtfmCoord .OR. DvrFlags%PtfmVeloc .OR. DvrFlags%PtfmAccel ) THEN + DvrFlags%PtfmCoord = .TRUE. + DvrFlags%PtfmVeloc = .TRUE. + DvrFlags%PtfmAccel = .TRUE. + ENDIF + + + !-------------------------------------------- + ! Are PtfmCoord angles in degrees? + !-------------------------------------------- + + IF ( CLFlags%Degrees ) THEN + ! No need to tell the user. They likely only specified this flag with command line coords. + ! The logic needed to check if it is a status change otherwise is not worth the effort. + DvrFlags%Degrees = .TRUE. + ENDIF + + + !-------------------------------------------- + ! Did we request Added Mass matrix results? + !-------------------------------------------- + + IF ( CLFlags%AddedMass ) THEN + IF ( DvrFlags%PtfmCoord .AND. DvrFlags%PtfmVeloc .AND. DvrFlags%PtfmAccel ) THEN + DvrFlags%AddedMass = .TRUE. + ELSE ! give a warning and set the flags. The coordinate is already initialized to (0,0,0,0,0,0) + CALL SetErrStat( ErrID_Warn,' Added mass matrix requested, but no platform location specified. Setting location to (0,0,0,0,0,0).', & + ErrStat,ErrMsg,RoutineName) + DvrFlags%AddedMass = .FALSE. + DvrFlags%PtfmCoord = .TRUE. + DvrFlags%PtfmVeloc = .TRUE. + DvrFlags%PtfmAccel = .TRUE. + ENDIF + ENDIF + + IF ( CLFlags%AddedMassFile ) THEN + IF ( DvrFlags%PtfmCoord .AND. DvrFlags%PtfmVeloc .AND. DvrFlags%PtfmAccel ) THEN + DvrFlags%AddedMassFile = .TRUE. + ELSE ! give a warning and set the flags. The coordinate is already initialized to (0,0,0,0,0,0) + CALL SetErrStat( ErrID_Warn,' Added mass matrix file requested, but no platform location specified. Setting location to (0,0,0,0,0,0).', & + ErrStat,ErrMsg,RoutineName) + DvrFlags%AddedMassFile = .TRUE. + DvrFlags%PtfmCoord = .TRUE. + DvrFlags%PtfmVeloc = .TRUE. + DvrFlags%PtfmAccel = .TRUE. + ENDIF + ENDIF + + + + !-------------------------------------------- + ! Did we request a different Points file? + !-------------------------------------------- + + IF ( CLFlags%PointsFile ) THEN + ! If a name was given in the driver input file, then warn the user. + IF ( DvrFlags%PointsFile ) THEN + CALL SetErrStat( ErrID_Warn,' Overriding driver input file settings for Points file.', & + ErrStat,ErrMsg,RoutineName ) + ENDIF + DvrFlags%PointsFile = .TRUE. + DvrSettings%PointsFileName = CLSettings%PointsFileName + IF ( CLFlags%PointsDegrees ) THEN + DvrFLags%PointsDegrees = .TRUE. + ENDIF + ELSE + IF ( CLFlags%PointsDegrees ) THEN + DvrFlags%PointsDegrees = .TRUE. + CALL SetErrStat( ErrID_Warn,' Overriding driver input file points file angles in degrees.', & + ErrStat,ErrMsg,RoutineName ) + ENDIF + ENDIF + + + ! If no DT value has been set (DEFAULT requested), we need to set a default to pass into Orca + IF ( .NOT. DvrFlags%DT ) THEN + DvrSettings%DT = 0.025_DbKi ! This value gets passed into the Orca_Init routine, so something must be set. + DvrFlags%DT = .TRUE. + ENDIF + + + ! If the angles for PtfmCoord, PtfmVeloc, and PtfmAccel are in degrees, then convert them into radians now + IF ( DvrFlags%Degrees ) THEN + DO I=4,6 + DvrSettings%PtfmCoord(I) = DvrSettings%PtfmCoord(I) * D2R ! D2R is from the library + DvrSettings%PtfmVeloc(I) = DvrSettings%PtfmVeloc(I) * D2R ! D2R is from the library + DvrSettings%PtfmAccel(I) = DvrSettings%PtfmAccel(I) * D2R ! D2R is from the library + ENDDO + ENDIF + + +END SUBROUTINE UpdateSettingsWithCL + + +SUBROUTINE ReadPointsFile( PointsFileName, AnglesInDegrees, TimeList, CoordList, VelocList, AccelList, ErrStat, ErrMsg ) + + CHARACTER(1024), INTENT(IN ) :: PointsFileName !< Name of the points file to read + LOGICAL, INTENT(IN ) :: AnglesInDegrees !< Are the angles specified in degrees? + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: TimeList(:) !< TimeStamps + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: CoordList(:,:) !< The coordinates we read in + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: VelocList(:,:) !< The velocities we read in + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: AccelList(:,:) !< The accelerations we read in + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< The message for the status + + ! Local variables + CHARACTER(1024) :: ErrMsgTmp !< Temporary error message for calls + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls + CHARACTER(*), PARAMETER :: RoutineName = 'ReadPointsFile' + INTEGER(IntKi) :: FiUnitPoints !< Unit number for points file to open + + INTEGER(IntKi) :: NumDataColumns !< Number of data columns + INTEGER(IntKi) :: NumDataPoints !< Number of lines of data (one point per line) + INTEGER(IntKi) :: NumHeaderLines !< Number of header lines to ignore + + INTEGER(IntKi) :: I !< Generic counter + + REAL(ReKi) :: TmpArray(19) !< Temporary array to hold one line of data from the points file + REAL(ReKi) :: ConvToRadians !< Conversion to radians multiplier + + ! Initialization of subroutine + ErrMsg = '' + ErrMsgTmp = '' + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + + ! Set the ConvToRadians multiplier + IF ( AnglesInDegrees) THEN + ConvToRadians = D2R ! Set to the library constant + ELSE + ConvToRadians = 1.0_ReKi + ENDIF + + + + ! Now open file + CALL GetNewUnit( FiUnitPoints ) + CALL OpenFInpFile( FiUnitPoints, TRIM(PointsFileName), ErrStatTmp, ErrMsgTmp ) ! Unformatted input file + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + ! Find out how long the file is + CALL GetFileLength( FiUnitPoints, PointsFileName, NumDataColumns, NumDataPoints, NumHeaderLines, ErrMsgTmp, ErrStatTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + IF ( NumDataColumns /= 19 ) THEN + CALL SetErrStat( ErrID_Fatal,' Expecting 19 columns in '//TRIM(PointsFileName)//' corresponding to '// & + 'timestamp, 3 translation coordinates, 3 rotation angles, 3 translational velocities, 3 rotational velocities, and '// & + '3 translational velocities, 3 rotational velocities. '//& + 'Instead found '//TRIM(Num2LStr(NumDataColumns))//' columns.', & + ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Allocate the storage for the data + CALL AllocAry( TimeList, NumDataPoints, "Array of timestamp data", ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Allocate the storage for the data + CALL AllocAry( CoordList, 6, NumDataPoints, "Array of Points and rotation data", ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Read in the headers and throw them away + ! Allocate the storage for the data + CALL AllocAry( VelocList, 6, NumDataPoints, "Array of translation and rotation derivative data", ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Read in the headers and throw them away + ! Allocate the storage for the data + CALL AllocAry( AccelList, 6, NumDataPoints, "Array of translation and rotation 2nd derivative data", ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp >= AbortErrLev ) THEN + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + + + ! Read in the headers and throw them away + DO I=1,NumHeaderLines + CALL ReadCom( FiUnitPoints, PointsFileName,' Points file header line', ErrStatTmp, ErrMsgTmp ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + ENDDO + + ! Read in the datapoints + DO I=1,NumDataPoints + CALL ReadAry ( FiUnitPoints, PointsFileName, TmpArray(:), 19, 'Temporary coordinate', & + 'Coordinate point from Points file', ErrStatTmp, ErrMsgTmp) + IF ( ErrStat /= ErrID_None ) THEN + CALL SetErrStat( ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CLOSE( FiUnitPoints ) + RETURN + ENDIF + TimeList(I) = TmpArray(1) + CoordList(1:3,I) = TmpArray(2:4) + CoordList(4:6,I) = TmpArray(5:7) * ConvToRadians + VelocList(1:3,I) = TmpArray(8:10) + VelocList(4:6,I) = TmpArray(11:13) * ConvToRadians + AccelList(1:3,I) = TmpArray(14:16) + AccelList(4:6,I) = TmpArray(17:19) * ConvToRadians + ENDDO + + CLOSE( FiUnitPoints ) + +CONTAINS + + !------------------------------------------------------------------------------------------------------------------------------- + !> This subroutine looks at a file that has been opened and finds out how many header lines there are, how many columns there + !! are, and how many lines of data there are in the file. + !! + !! A few things are assumed about the file: + !! 1. Any header lines are the first thing in the file. + !! 2. No text appears anyplace other than in first part of the file + !! 3. The datalines only contain numbers that can be read in as reals. + !! + !! Limitations: + !! 1. only handles up to 20 words (columns) on a line + !! 2. empty lines are considered text lines + !! 3. All data rows must contain the same number of columns + !! + !! + SUBROUTINE GetFileLength(UnitDataFile, DataFileName, NumDataColumns, NumDataLines, NumHeaderLines, ErrMsg, ErrStat) + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: UnitDataFile !< Unit number of the file we are looking at. + CHARACTER(*), INTENT(IN ) :: DataFileName !< The name of the file we are looking at. + INTEGER(IntKi), INTENT( OUT) :: NumDataColumns !< The number of columns in the data file. + INTEGER(IntKi), INTENT( OUT) :: NumDataLines !< Number of lines containing data + INTEGER(IntKi), INTENT( OUT) :: NumHeaderLines !< Number of header lines at the start of the file + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error Message to return (empty if all good) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Status flag if there were any problems (ErrID_None if all good) + + ! Local Variables + CHARACTER(2048) :: ErrMsgTmp !< Temporary message variable. Used in calls. + INTEGER(IntKi) :: ErrStatTmp !< Temporary error status. Used in calls. + CHARACTER(*), PARAMETER :: RoutineName = 'GetFileLength' + INTEGER(IntKi) :: LclErrStat !< Temporary error status. Used locally to indicate when we have reached the end of the file. + INTEGER(IntKi) :: TmpIOErrStat !< Temporary error status for the internal read of the first word to a real number + LOGICAL :: IsRealNum !< Flag indicating if the first word on the line was a real number + + CHARACTER(1024) :: TextLine !< One line of text read from the file + INTEGER(IntKi) :: LineLen !< The length of the line read in + CHARACTER(1024) :: StrRead !< String containing the first word read in + REAL(ReKi) :: RealRead !< Returns value of the number (if there was one), or NaN (as set by NWTC_Num) if there wasn't + CHARACTER(1024) :: VarName !< Name of the variable we are trying to read from the file + CHARACTER(24) :: Words(20) !< Array of words we extract from a line. We shouldn't have more than 20. + INTEGER(IntKi) :: i,j,k !< simple integer counters + INTEGER(IntKi) :: LineNumber !< the line I am on + LOGICAL :: LineHasText !< Flag indicating if the line I just read has text. If so, it is a header line. + LOGICAL :: HaveReadData !< Flag indicating if I have started reading data. + INTEGER(IntKi) :: NumWords !< Number of words on a line + INTEGER(IntKi) :: FirstDataLineNum !< Line number of the first row of data in the file + + + ! Initialize the error handling + ErrStat = ErrID_None + ErrStatTmp = ErrID_None + LclErrStat = ErrID_None + ErrMsg = '' + ErrMsgTmp = '' + + + ! Set some of the flags and counters + HaveReadData = .FALSE. + NumDataColumns = 0 + NumHeaderLines = 0 + NumDataLines = 0 + LineNumber = 0 + + + ! Just in case we were handed a file that we are part way through reading (should never be true), rewind to the start + + REWIND( UnitDataFile ) + + + !------------------------------------ + !> The variable LclErrStat is used to indicate when we have reached the end of the file or had an error from + !! ReadLine. Until that occurs, we read each line, and decide if it contained any non-numeric data. The + !! first group of lines containing non-numeric data is considered the header. The first line of all numeric + !! data is considered the start of the data section. Any non-numeric containing found within the data section + !! will be considered as an invalid file format at which point we will return a fatal error from this routine. + + DO WHILE ( LclErrStat == ErrID_None ) + + !> Reset the indicator flag for the non-numeric content + LineHasText = .FALSE. + + !> Read in a single line from the file + CALL ReadLine( UnitDataFile, '', TextLine, LineLen, LclErrStat ) + + !> If there was an error in reading the file, then exit. + !! Possible causes: reading beyond end of file in which case we are done so don't process it. + IF ( LclErrStat /= ErrID_None ) EXIT + + !> Increment the line counter. + LineNumber = LineNumber + 1 + + !> Read all the words on the line into the array called 'Words'. Only the first words will be encountered + !! will be stored. The others are empty (i.e. only three words on the line, so the remaining 17 are empty). + CALL GetWords( TextLine, Words, 20 ) + + !> Cycle through and count how many are not empty. Once an empty value is encountered, all the rest should + !! be empty if GetWords worked correctly. The index of the last non-empty value is stored. + DO i=1,20 + IF (TRIM(Words(i)) .ne. '') NumWords=i + ENDDO + + + !> Now cycle through the first 'NumWords' of non-empty values stored in 'Words'. Words should contain + !! everything that is one the line. The subroutine ReadRealNumberFromString will set a flag 'IsRealNum' + !! when the value in Words(i) can be read as a real(ReKi). 'StrRead' will contain the string equivalent. + DO i=1,NumWords + CALL ReadRealNumberFromString( Words(i), RealRead, StrRead, IsRealNum, ErrStatTmp, ErrMsgTmp, TmpIOErrStat ) + IF ( .NOT. IsRealNum) THEN + LineHasText = .TRUE. + ENDIF + ENDDO + + !> If all the words on that line had no text in them, then it must have been a line of data. + !! If not, then we have either a header line, which is ok, or a line containing text in the middle of the + !! the data section, which is not good (the flag HaveReadData tells us which case this is). + IF ( LineHasText ) THEN + IF ( HaveReadData ) THEN ! Uh oh, we have already read a line of data before now, so there is a problem + CALL SetErrStat( ErrID_Fatal, ' Found text on line '//TRIM(Num2LStr(LineNumber))//' of '//TRIM(DataFileName)// & + ' when real numbers were expected. There may be a problem with format of the file: '// & + TRIM(DataFileName)//'.', ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + RETURN + ENDIF + ELSE + NumHeaderLines = NumHeaderLines + 1 + ENDIF + ELSE ! No text, must be data line + NumDataLines = NumDataLines + 1 + ! If this is the first row of data, then store the number of words that were on the line + IF ( .NOT. HaveReadData ) THEN + ! If this is the first line of data, keep some relevant info about it and the number of columns in it + HaveReadData = .TRUE. + FirstDataLineNum = LineNumber ! Keep the line number of the first row of data (for error reporting) + NumDataColumns = NumWords + ELSE + ! Make sure that the number columns on the row matches the number of columnns on the first row of data. + IF ( NumWords /= NumDataColumns ) THEN + CALL SetErrStat( ErrID_Fatal, ' Error in file: '//TRIM(DataFileName)//'.'// & + ' The number of data columns on line '//TRIM(Num2LStr(LineNumber))// & + '('//TRIM(Num2LStr(NumWords))//' columns) is different than the number of columns on first row of data '// & + ' (line: '//TRIM(Num2LStr(FirstDataLineNum))//', '//TRIM(Num2LStr(NumDataColumns))//' columns).', & + ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + RETURN + ENDIF + ENDIF + ENDIF + ENDIF + + ENDDO + + + REWIND( UnitDataFile ) + + END SUBROUTINE GetFileLength + + !------------------------------------------------------------------------------- + !> This subroutine takes a line of text that is passed in and reads the first + !! word to see if it is a number. An internal read is used to do this. If + !! it is a number, it is started in ValueRead and returned. The flag IsRealNum + !! is set to true. Otherwise, ValueRead is set to NaN (value from the NWTC_Num) + !! and the flag is set to false. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (IsRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + CHARACTER(*), INTENT(IN ) :: StringToParse !< The string we were handed. + REAL(ReKi), INTENT( OUT) :: ValueRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StringToParse,*,IOSTAT=IOErrStat) StrRead + read(StringToParse,*,IOSTAT=IOErrStat) ValueRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + ValueRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrSTat = ErrID_Severe + endif + + + + RETURN + END SUBROUTINE ReadRealNumberFromString + + + !------------------------------------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------- + !> This subroutine works with the ReadNum routine from the library. ReadNum is + !! called to read a word from the input file. An internal read is then done to + !! convert the string to a number that is stored in VarRead and returned. + !! + !! The IsRealNum flag is set to indicate if we actually have a real number or + !! not. After calling this routine, a simple if statement can be used: + !! + !! @code + !! IF (ISRealNum) THEN + !! ! do something + !! ELSE + !! ! do something else + !! ENDIF + !! @endcode + !! + !------------------------------------------------------------------------------- + SUBROUTINE ReadRealNumber(UnitNum, FileName, VarName, VarRead, StrRead, IsRealNum, ErrStat, ErrMsg, IOErrStat) + + INTEGER(IntKi), INTENT(IN ) :: UnitNum !< The unit number of the file being read + CHARACTER(*), INTENT(IN ) :: FileName !< The name of the file being read. Used in the ErrMsg from ReadNum (Library routine). + CHARACTER(*), INTENT(IN ) :: VarName !< The variable we are reading. Used in the ErrMsg from ReadNum (Library routine)'. + REAL(ReKi), INTENT( OUT) :: VarRead !< The variable being read. Returns as NaN (library defined) if not a Real. + CHARACTER(*), INTENT( OUT) :: StrRead !< A string containing what was read from the ReadNum routine. + LOGICAL, INTENT( OUT) :: IsRealNum !< Flag indicating if we successfully read a Real + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< ErrID level returned from ReadNum + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum + INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + + ! Local vars + INTEGER(IntKi) :: ErrStatTmp + CHARACTER(2048) :: ErrMsgTmp + + + + ! Initialize some things + ErrStat = ErrID_None + ErrMsg = '' + + + ! Now call the ReadNum routine to get the number + ! If it is a word that does not start with T or F, then ReadNum won't give any errors. + CALL ReadNum( UnitNum, FileName, StrRead, VarName, ErrStatTmp, ErrMsgTmp) + + + ! ReadNum returns a string contained in StrRead. So, we now try to do an internal read to VarRead and then trap errors. + read(StrRead,*,IOSTAT=IOErrStat) VarRead + + + ! If IOErrStat==0, then we have a real number, anything else is a problem. + if (IOErrStat==0) then + IsRealNum = .TRUE. + else + IsRealNum = .FALSE. + VarRead = NaN ! This is NaN as defined in the NWTC_Num. + ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine + ErrStat = ErrStatTmp ! The ErrStatTmp returned by the ReadNum routine is an ErrID level. + endif + + + + RETURN + END SUBROUTINE ReadRealNumber + + +END SUBROUTINE ReadPointsFile + + + +SUBROUTINE AddedMassMessage( AM, ToFile, Msg, MsgLen ) + + REAL(ReKi), INTENT(IN ) :: AM(6,6) !< Added mass matrix + LOGICAL, INTENT(IN ) :: ToFile !< Prepend comment character + CHARACTER(2048), INTENT( OUT) :: Msg + INTEGER(IntKi), INTENT( OUT) :: MsgLen + + ! Local Variables + CHARACTER(15) :: TmpNumString + INTEGER(IntKi) :: ErrStatTmp + INTEGER(IntKi) :: I !< Simple counter + + Msg = '' + + IF ( ToFile ) THEN + Msg='# Added Mass Values (kg, kg-m, kg-m^2):'//NewLine//NewLine + ELSE + Msg="Added Mass values (kg, kg-m, kg-m^2):"//NewLine//NewLine + ENDIF + + ! Header info: + Msg = TRIM(Msg) + IF ( ToFile ) Msg=TRIM(Msg)//'#' + Msg = TRIM(Msg)//" Dim TDxi TDyi TDzi RDxi RDyi RDzi "//NewLine + IF ( ToFile ) Msg=TRIM(Msg)//'#' + Msg = TRIM(Msg)//" ------------------------------------------------------------------------------"//NewLine + + MsgLen= LEN_TRIM(Msg)-1 ! Not sure why an extra count exists here. + + + CALL printDirection(" TDxi",1) + CALL printDirection(" TDyi",2) + CALL printDirection(" TDzi",3) + CALL printDirection(" RDxi",4) + CALL printDirection(" RDyi",5) + CALL printDirection(" RDzi",6) + + + + RETURN + + CONTAINS + SUBROUTINE printDirection( NameIn, IndexNum) + + CHARACTER(*), INTENT(IN ) :: NameIn + INTEGER(IntKi), INTENT(IN ) :: IndexNum + + IF ( ToFile ) THEN + Msg= TRIM(Msg)//"#"//TRIM(NameIn) + ELSE + Msg= TRIM(Msg)//" "//TRIM(NameIn) + ENDIF + MsgLen= MsgLen+8 + Msg = Msg(1:MsgLen)//" " + MsgLen= MsgLen+1 + DO I=1,6 + WRITE(TmpNumString,'(ES10.3E2)',IOSTAT=ErrStatTmp) AM(IndexNum,I) + Msg = Msg(1:MsgLen)//TmpNumString(1:10) + MsgLen= MsgLen+2+10 + ENDDO + Msg = Msg(1:MsgLen)//NewLine + + + + RETURN + + END SUBROUTINE printDirection + +END SUBROUTINE AddedMassMessage + + +!> This subroutine writes the Added Mass matrix to a file +SUBROUTINE AddedMass_OutputWrite (DvrSettings, Initialized, PtfmAM, ErrStat, ErrMsg) + + TYPE( OrcaDriver_Settings ), INTENT(INOUT) :: DvrSettings !< Stored settings + LOGICAL, INTENT(INOUT) :: Initialized !< Was this file started before? + REAL(ReKi), INTENT(IN ) :: PtfmAM(6,6) !< The added mass matrix + 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 + CHARACTER(*), PARAMETER :: RoutineName = 'AddedMass_OutputWrite' + INTEGER(IntKi) :: LenErrMsgTmp !< Length of ErrMsgTmp (for getting WindGrid info) + + CHARACTER(25) :: AMfmt !< Format specifier for the output file for wave elevation series + INTEGER(IntKi) :: I !< generic counter + + + AMfmt = "(ES10.3E2,5(3x,ES10.3E2))" + + ErrMsg = '' + ErrStat = ErrID_None + ErrMsgTmp = '' + ErrStatTmp = ErrID_None + + + ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. + IF ( .NOT. Initialized ) THEN + + CALL GetNewUnit( DvrSettings%AddedMassOutputUnit ) + CALL OpenFOutFile( DvrSettings%AddedMassOutputUnit, TRIM(DvrSettings%AddedMassFileName), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + Initialized = .TRUE. + + ! Write header section + WRITE( DvrSettings%AddedMassOutputUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(DvrSettings%ProgInfo))// & + ' on '//CurDate()//' at '//CurTime()//'.' + WRITE( DvrSettings%AddedMassOutputUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the added mass matrix that is returned from OrcaFlex' + WRITE (DvrSettings%AddedMassOutputUnit,'(A)', IOSTAT=ErrStatTmp ) '## It is arranged in a 6x6 matrix' + WRITE (DvrSettings%AddedMassOutputUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' + CALL AddedMassMessage( PtfmAM, .FALSE., ErrMsgTmp, LenErrMsgTmp ) + WRITE (DvrSettings%AddedMassOutputUnit,'(A)', IOSTAT=ErrStatTmp ) ErrMsgTmp(1:LenErrMsgTmp) + ELSE + ! keep this as a placeholder in case we decide to write out at each timestep. + ENDIF + + +END SUBROUTINE AddedMass_OutputWrite + + +SUBROUTINE PointsForce_OutputWrite(ProgInfo, OutUnit, OutFileName, InputFileName, Initialized, AnglesInDegrees, TotalPoints, & + Time, InitOutData, p, u, y, ErrStat, ErrMsg) + + TYPE(ProgDesc), INTENT(IN ) :: ProgInfo !< Program info + INTEGER(IntKi), INTENT(INOUT) :: OutUnit !< Output Unit number + CHARACTER(1024), INTENT(IN ) :: OutFileName !< Name of the file to write to + CHARACTER(1024), INTENT(IN ) :: InputFileName !< Name of the file the points came from + LOGICAL, INTENT(INOUT) :: Initialized !< Is the file initialized + LOGICAL, INTENT(IN ) :: AnglesInDegrees !< The angles are in degrees. + INTEGER(IntKi), INTENT(IN ) :: TotalPoints !< The total number of points in the points file + REAL(DbKi), INTENT(IN ) :: Time !< Current time + TYPE(Orca_InitOutputType), INTENT(IN ) :: InitOutData !< InitOutData -- need the header info + TYPE(Orca_ParameterType), INTENT(IN ) :: p !< p + TYPE(Orca_InputType), INTENT(IN ) :: u !< u + TYPE(Orca_OutputType), INTENT(IN ) :: y !< y + 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(*), PARAMETER :: RoutineName = 'PointsForce_OutputWrite' + CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for the error message + INTEGER(IntKi) :: LenErrMsgTmp !< Length of ErrMsgTmp (for getting WindGrid info) + REAL(ReKi) :: rotdisp(3) !< Rotational displacement (euler angles) + INTEGER(IntKi) :: I !< Generic counter + REAL(ReKi) :: outputArray(13) + + CHARACTER(47) :: PointsOutputFmt !< Format specifier for the output file for wave elevation series + CHARACTER(3) :: AngleUnit !< Units for the angle + + PointsOutputFmt = "(ES10.3E2,18(3x,ES10.3E2))" + + ErrMsg = '' + ErrStat = ErrID_None + ErrMsgTmp = '' + ErrStatTmp = ErrID_None + + + ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. + IF ( .NOT. Initialized ) THEN + + IF ( AnglesInDegrees ) THEN + AngleUnit = "deg" + ELSE + AngleUnit = "rad" + ENDIF + + CALL GetNewUnit( OutUnit ) + CALL OpenFOutFile( OutUnit, TRIM(OutFileName), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + Initialized = .TRUE. + + ! Write header section + WRITE( OutUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(ProgInfo))// & + ' on '//CurDate()//' at '//CurTime()//'.' + IF ( TotalPoints >= 1_IntKi ) THEN + WRITE( OutUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the resulting forces and moments for the '// & + TRIM(Num2LStr(TotalPoints))//' points specified in the '// & + 'file '//TRIM(InputFileName)//'.' + ENDIF + WRITE (OutUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' + CALL WrFileNR( OutUnit, '# Time '// & + ' TDxi TDyi TDzi ' // & + ' RDxi RDyi RDzi ' // & + ' TVxi TVyi TVzi ' // & + ' RVxi RVyi RVzi ' ) + DO I=1,SIZE(InitOutData%WriteOutputHdr) + CALL WrFileNR ( OutUnit, ' '//InitOutData%WriteOutputHdr(I) ) + ENDDO ! I + WRITE (OutUnit,'(A)', IOSTAT=ErrStatTmp ) '' + + + + CALL WrFileNR( OutUnit, '# (s) '// & + ' (m) (m) (m) ' // & + ' ('//AngleUnit//') ('//AngleUnit//') ('//AngleUnit//') '// & + ' (m/s) (m/s) (m/s) ' // & + ' ('//AngleUnit//'/s) ('//AngleUnit//'/s) ('//AngleUnit//'/s) ' ) + DO I=1,SIZE(InitOutData%WriteOutputHdr) + CALL WrFileNR ( OutUnit, ' '//InitOutData%WriteOutputUnt(I) ) + ENDDO ! I + WRITE (OutUnit,'(A)', IOSTAT=ErrStatTmp ) '' + ENDIF + + rotdisp = GetSmllRotAngs ( u%PtfmMesh%Orientation(:,:,1), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + + IF ( AnglesInDegrees ) THEN + outputArray = (/ REAL(Time, ReKi), & + REAL(u%PtfmMesh%TranslationDisp(1,1), ReKi), & + REAL(u%PtfmMesh%TranslationDisp(2,1), ReKi), & + REAL(u%PtfmMesh%TranslationDisp(3,1), ReKi), & + rotdisp(1)*R2D, rotdisp(2)*R2D, rotdisp(3)*R2D, & + u%PtfmMesh%TranslationVel(1,1), u%PtfmMesh%TranslationVel(2,1), u%PtfmMesh%TranslationVel(3,1), & + u%PtfmMesh%RotationVel(1,1)*R2D, u%PtfmMesh%RotationVel(2,1)*R2D, u%PtfmMesh%RotationVel(3,1)*R2D /) + ELSE + outputArray = (/ REAL(Time, ReKi), & + REAL(u%PtfmMesh%TranslationDisp(1,1), ReKi), & + REAL(u%PtfmMesh%TranslationDisp(2,1), ReKi), & + REAL(u%PtfmMesh%TranslationDisp(3,1), ReKi), & + rotdisp(1), rotdisp(2), rotdisp(3), & + u%PtfmMesh%TranslationVel(1,1), u%PtfmMesh%TranslationVel(2,1), u%PtfmMesh%TranslationVel(3,1), & + u%PtfmMesh%RotationVel(1,1), u%PtfmMesh%RotationVel(2,1), u%PtfmMesh%RotationVel(3,1) /) + ENDIF + + CALL WrNumAryFileNR( OutUnit, outputArray, '3x,ES10.3E2', ErrStatTmp, ErrMsgTmp ) + CALL WrNumAryFileNR( OutUnit, y%WriteOutput, '3x,ES10.3E2', ErrStatTmp, ErrMsgTmp ) + WRITE (OutUnit,'(A)', IOSTAT=ErrStatTmp ) '' + +END SUBROUTINE PointsForce_OutputWrite + + + + +!> This routine exists only to support the development of the module. It will not be needed after the module is complete. +SUBROUTINE printSettings( DvrFlags, DvrSettings ) + ! The arguments + TYPE( OrcaDriver_Flags ), INTENT(IN ) :: DvrFlags !< Flags indicating which settings were set + TYPE( OrcaDriver_Settings ), INTENT(IN ) :: DvrSettings !< Stored settings + + CALL WrsCr(TRIM(GetNVD(DvrSettings%ProgInfo))) + CALL WrScr(' DvrIptFile: '//FLAG(DvrFlags%DvrIptFile)// ' '//TRIM(DvrSettings%DvrIptFileName)) + CALL WrScr(' OrcaIptFile: '//FLAG(DvrFlags%OrcaIptFile)// ' '//TRIM(DvrSettings%OrcaIptFileName)) +! CALL WrScr(' DLLPathFileName: '//FLAG(DvrFlags%DLLPathFileName)// ' '//TRIM(DvrSettings%DLLPathFileName)) + CALL WrScr(' PointsFile: '//FLAG(DvrFlags%PointsFile)// ' '//TRIM(DvrSettings%PointsFileName)) + CALL WrScr(' AddedMass: '//FLAG(DvrFlags%AddedMass)) + CALL WrScr(' AddedMassFile: '//FLAG(DvrFlags%AddedMassFile)// ' '//TRIM(DvrSettings%AddedMassFileName)) + IF ( DvrFlags%DTDefault) THEN + CALL WrScr(' DT: '//FLAG(DvrFlags%DT)// ' DEFAULT') + ELSE + CALL WrScr(' DT: '//FLAG(DvrFlags%DT)// ' '//TRIM(Num2LStr(DvrSettings%DT))) + ENDIF + IF ( DvrFlags%Degrees ) THEN + CALL WrScr(' PtfmCoord: '//FLAG(DvrFlags%PtfmCoord)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmCoord(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(4)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(5)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(6)*R2D))//']') + CALL WrScr(' PtfmVeloc: '//FLAG(DvrFlags%PtfmVeloc)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmVeloc(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(4)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(5)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(6)*R2D))//']') + CALL WrScr(' PtfmAccel: '//FLAG(DvrFlags%PtfmAccel)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmAccel(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(4)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(5)*R2D))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(6)*R2D))//']') + ELSE + CALL WrScr(' PtfmCoord: '//FLAG(DvrFlags%PtfmCoord)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmCoord(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(4)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(5)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmCoord(6)))//']') + CALL WrScr(' PtfmVeloc: '//FLAG(DvrFlags%PtfmVeloc)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmVeloc(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(4)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(5)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmVeloc(6)))//']') + CALL WrScr(' PtfmAccel: '//FLAG(DvrFlags%PtfmAccel)// ' ['//TRIM(Num2LStr(DvrSettings%PtfmAccel(1)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(2)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(3)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(4)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(5)))//', '& + //TRIM(Num2LStr(DvrSettings%PtfmAccel(6)))//']') + ENDIF + CALL WrScr(' Degrees: '//FLAG(DvrFlags%Degrees)// ' PtfmCoord, PtfmVeloc, and PtfmAccel angles in degrees') + CALL WrScr(' PointsDegrees: '//FLAG(DvrFlags%PointsDegrees)// ' PointsFile angles in degrees') + CALL WrScr(' PointsOutputInit: '//FLAG(DvrFlags%PointsOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsOutputUnit))) + RETURN +END SUBROUTINE printSettings + + +!> This routine exists only to support the development of the module. It will not be kept after the module is complete. +!! This routine takes a flag setting (LOGICAL) and exports either 'T' or '-' for T/F (respectively) +FUNCTION FLAG(flagval) + LOGICAL, INTENT(IN ) :: flagval !< Value of the flag + CHARACTER(1) :: FLAG !< character interpretation (for prettiness when printing) + IF ( flagval ) THEN + FLAG = 'T' + ELSE + FLAG = '-' + ENDIF + RETURN +END FUNCTION FLAG + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +END MODULE OrcaDriver_Subs diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Types.f90 b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Types.f90 new file mode 100644 index 000000000..78bbd7bf9 --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaDriver_Types.f90 @@ -0,0 +1,94 @@ +!********************************************************************************************************************************** +! +! MODULE: Orca_Driver_Types - This module contains types used by the OrcaFlexInterface Driver program to store arguments passed in +! +! The types listed here are used within the OrcaFlexInterface Driver program to store the settings. These settings are read in as +! command line arguments, then stored within these types. +! +!********************************************************************************************************************************** +! +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! This file is part of OrcaFlexInterface. +! +! OrcaFlexInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as +! published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +! of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License along with OrcaFlexInterface. +! If not, see <http://www.gnu.org/licenses/>. +! +!********************************************************************************************************************************** +! File last committed: $Date: 2014-07-29 13:30:04 -0600 (Tue, 29 Jul 2014) $ +! (File) Revision #: $Rev: 169 $ +! URL: $HeadURL: https://windsvn.nrel.gov/OrcaFlexInterface/branches/modularization2/Source/Driver/OrcaDriver_Types.f90 $ +!********************************************************************************************************************************** + +MODULE OrcaDriver_Types + + USE NWTC_Library + USE OrcaFlexInterface_Types + + IMPLICIT NONE + + !> 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. + !! + !! NOTE: The WindFileType is only set if it is given as a command line option. Otherwise + !! it is handled internally by InflowWInd. + !! + !! NOTE: The wind direction is specified by the OrcaFlexInterface input file. + TYPE :: OrcaDriver_Flags + LOGICAL :: DvrIptFile = .FALSE. !< Was an input file name given on the command line? + LOGICAL :: OrcaIptFile = .FALSE. !< Was an OrcaFlexInterface input file requested? + LOGICAL :: AddedMass = .FALSE. !< create an added mass table at command line? + LOGICAL :: AddedMassFile = .FALSE. !< create an added mass file? + LOGICAL :: DT = .FALSE. !< specified a resolution in time + LOGICAL :: DTDefault = .FALSE. !< specified a 'DEFAULT' for the time resolution + + + LOGICAL :: Degrees = .FALSE. !< angles are specified in degrees + + LOGICAL :: PtfmCoord = .FALSE. !< (x,y,z,R1,R2,R3) coordinate specified + LOGICAL :: PtfmVeloc = .FALSE. !< (x,y,z,R1,R2,R3) coordinate specified + LOGICAL :: PtfmAccel = .FALSE. !< (x,y,z,R1,R2,R3) coordinate specified + + + LOGICAL :: PointsFile = .FALSE. !< points filename to read in + LOGICAL :: PointsDegrees = .FALSE. !< points in the pointsfile are specified in degrees + + LOGICAL :: AddedMassOutputInit = .FALSE. !< Is the WindGridOut file initialized + LOGICAL :: PointsOutputInit = .FALSE. !< Is the Points output file initialized + LOGICAL :: Verbose = .FALSE. !< Verbose error reporting + LOGICAL :: VVerbose = .FALSE. !< Very Verbose error reporting + END TYPE OrcaDriver_Flags + + + ! This contains all the settings (possible passed in arguments). + TYPE :: OrcaDriver_Settings + CHARACTER(1024) :: DvrIptFileName !< Driver input file name + CHARACTER(1024) :: OrcaIptFileName !< Filename of OrcaFlexInterface input file to read (if no driver input file) + CHARACTER(1024) :: AddedMassFileName !< Filename for the added mass matrix output + + CHARACTER(1024) :: PointsFileName !< Filename of points file to read in + CHARACTER(1024) :: PointsOutputName !< Filename for output from points read in from points file + INTEGER(IntKi) :: AddedMassOutputUnit !< Unit number for the output file for the AddedMass matrix + INTEGER(IntKi) :: PointsOutputUnit !< Unit number for the output file for the Points file output + REAL(DbKi) :: DT !< resolution of time + REAL(ReKi) :: TMax !< Maximum time (we calculate this based on the number of points and timestep) + + REAL(ReKi) :: PtfmCoord(1:6) !< (x,y,z,R1,R2,R3) coordinate and rotations to calculate at + REAL(ReKi) :: PtfmVeloc(1:6) !< instantaneous velocities corresponding to the PtfmCoord + REAL(ReKi) :: PtfmAccel(1:6) !< instantaneous velocities corresponding to the PtfmCoord + + TYPE(ProgDesc) :: ProgInfo !< Program info + TYPE(ProgDesc) :: OrcaProgInfo !< Program info for OrcaFlexInterface + + END TYPE OrcaDriver_Settings + + +END MODULE OrcaDriver_Types diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.f90 b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.f90 new file mode 100644 index 000000000..9dcbcbaf9 --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.f90 @@ -0,0 +1,1082 @@ +!********************************************************************************************************************************** +! The OrcaFlexInterface.f90 and OrcaFlexInterface_Types.f90 make up the OrcaFlexInterface module of the +! FAST Modularization Framework. OrcaFlexInterface_Types is auto-generated based on FAST_Registry.txt. +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! +! This file is part of OrcaFlexInterface. +! +! 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. +! +!********************************************************************************************************************************** +!> This module contains definitions of compile-time PARAMETERS for the OrcaFlex Interface module. +!! Every variable defined here MUST have the PARAMETER attribute. +MODULE OrcaFlexInterface_Parameters + + USE NWTC_Library + + IMPLICIT NONE + + TYPE(ProgDesc), PARAMETER :: Orca_Ver = ProgDesc( 'OrcaFlexInterface', '', '' ) + CHARACTER(*), PARAMETER :: Orca_Nickname = 'Orca' + + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 01-Sep-2015 14:29:18. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Platform forces: + + INTEGER(IntKi), PARAMETER :: OrcaFxi = 1 + INTEGER(IntKi), PARAMETER :: OrcaFyi = 2 + INTEGER(IntKi), PARAMETER :: OrcaFzi = 3 + INTEGER(IntKi), PARAMETER :: OrcaMxi = 4 + INTEGER(IntKi), PARAMETER :: OrcaMyi = 5 + INTEGER(IntKi), PARAMETER :: OrcaMzi = 6 + INTEGER(IntKi), PARAMETER :: OrcaHMFxi = 7 + INTEGER(IntKi), PARAMETER :: OrcaHMFyi = 8 + INTEGER(IntKi), PARAMETER :: OrcaHMFzi = 9 + INTEGER(IntKi), PARAMETER :: OrcaHMMxi = 10 + INTEGER(IntKi), PARAMETER :: OrcaHMMyi = 11 + INTEGER(IntKi), PARAMETER :: OrcaHMMzi = 12 + INTEGER(IntKi), PARAMETER :: OrcaAMFxi = 13 + INTEGER(IntKi), PARAMETER :: OrcaAMFyi = 14 + INTEGER(IntKi), PARAMETER :: OrcaAMFzi = 15 + INTEGER(IntKi), PARAMETER :: OrcaAMMxi = 16 + INTEGER(IntKi), PARAMETER :: OrcaAMMyi = 17 + INTEGER(IntKi), PARAMETER :: OrcaAMMzi = 18 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 18 + +!End of code generated by Matlab script +! =================================================================================================== + +END MODULE OrcaFlexInterface_Parameters +!********************************************************************************************************************************** +!> This module is an interface between FAST and OrcaFlex, a commercial software package developed by Orcina. This interfaces calls +!! an OrcaFlex DLL once per time step, and is valid for loose coupling. Tight coupling is not supported. +MODULE OrcaFlexInterface + + USE NWTC_Library + USE NWTC_LAPACK + + USE OrcaFlexInterface_Parameters + USE OrcaFlexInterface_Types + + USE, INTRINSIC :: ISO_C_Binding + + + IMPLICIT NONE + + PRIVATE + + + INTERFACE ! These are interfaces to the DLL + +#ifdef __GFORTRAN__ + SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) BIND(C) +#else + SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) !!!BIND(C) +#endif + USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT + !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLdInitialise'::OrcaFlexUserPtfmLdInitialise + !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdInitialise + REAL(C_FLOAT), INTENT(IN ) :: DT + REAL(C_FLOAT), INTENT(IN ) :: TMax + END SUBROUTINE OrcaFlexUserPtfmLdInitialise + + +#ifdef __GFORTRAN__ + SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) BIND(C) +#else + SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) !!!BIND(C) +#endif + USE, INTRINSIC :: ISO_C_Binding, ONLY: C_FLOAT, C_CHAR + !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLd'::OrcaFlexUserPtfmLd + !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLd + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: DirRoot + REAL(C_FLOAT), INTENT(IN ) :: X(6) !< Translational and rotational displacement (m, radians) relative to inertial frame. + REAL(C_FLOAT), INTENT(IN ) :: XD(6) !< Translational and rotational velocity (m/s, radians/s) relative to inertial frame. + REAL(C_FLOAT), INTENT(IN ) :: ZTime !< Current time in seconds + REAL(C_FLOAT), INTENT( OUT) :: PtfmAM(6,6) !< Added mass matrix (kg, kg-m, kg-m^2) + REAL(C_FLOAT), INTENT( OUT) :: PtfmFt(6) !< Platform forces -- [3 translation (N), 3 moments (N-m)] at reference point. + END SUBROUTINE OrcaFlexUserPtfmLd + + + +#ifdef __GFORTRAN__ + SUBROUTINE OrcaFlexUserPtfmLdFinalise() BIND(C) +#else + SUBROUTINE OrcaFlexUserPtfmLdFinalise() !!!BIND(C) +#endif + USE, INTRINSIC :: ISO_C_BINDING + !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS: 'OrcaFlexUserPtfmLdFinalise'::OrcaFlexUserPtfmLdFinalise + !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdFinalise + ! There is no data to pass. + END SUBROUTINE OrcaFlexUserPtfmLdFinalise + + END INTERFACE + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Orca_Init ! Initialization routine + PUBLIC :: Orca_End ! Ending routine (includes clean up) + + PUBLIC :: Orca_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: Orca_CalcOutput ! Routine for computing outputs + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE Orca_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + + USE, INTRINSIC :: ISO_C_Binding + + TYPE(Orca_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(Orca_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Orca_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Orca_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Orca_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Orca_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Orca_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Orca_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Orca_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Orca_UpdateStates() is called in loose coupling & + !! (2) Orca_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Orca_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + TYPE(Orca_InputFile) :: InputFileData ! Data stored in the module's input file + INTEGER(IntKi) :: ErrStatTmp ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName='Orca_Init' + CHARACTER(ChanLen) :: TmpOutList(MaxOutPts) + + + REAL(C_FLOAT) :: DLL_DT + REAL(C_FLOAT) :: DLL_TMax + + + PROCEDURE(OrcaFlexUserPtfmLdInitialise),POINTER :: OrcaDLL_Init + + + + + ! Initialize variables for this routine + ErrStat = ErrID_None + ErrMsg = "" + + ! dummy variables for the FAST framework: + ! (initialized to prevent compiler warnings about INTENT(OUT) variables) + OtherState%DummyOtherState = 0 + z%DummyConstrState = 0.0_ReKi + xd%Dummy = 0.0_ReKi + x%Dummy = 0.0_ReKi + + + ! Set some things for the DLL + InputFileData%DLL_InitProcName = 'OrcaFlexUserPtfmLdInitialise' + InputFileData%DLL_CalcProcName = 'OrcaFlexUserPtfmLd' + InputFileData%DLL_EndProcName = 'OrcaFlexUserPtfmLdFinalise' + + + ! Display the module information + CALL DispNVD( Orca_Ver ) + + + CALL ReadPrimaryFile( InitInp%InputFile, InputFileData, TRIM(InitInp%RootName)//'.Orca', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + + + ! We are going to output all the possible outlist variables, so pass in to SetOutParam the full list + TmpOutList = (/ & + "OrcaFxi ","OrcaFyi ","OrcaFzi ","OrcaMxi ","OrcaMyi ","OrcaMzi ", & ! Total forces / moments + "OrcaHMFxi","OrcaHMFyi","OrcaHMFzi","OrcaHMMxi","OrcaHMMyi","OrcaHMMzi", & ! hydrodynamic contributions + "OrcaAMFxi","OrcaAMFyi","OrcaAMFzi","OrcaAMMxi","OrcaAMMyi","OrcaAMMzi" & ! Added mass contributions + /) + p%NumOuts = MaxOutPts + CALL SetOutParam( TmpOutList, p, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + + + ! Allocate array for AllOuts + CALL AllocAry( m%AllOuts, p%NumOuts, 'AllOuts', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + m%AllOuts = 0.0_ReKi + + + ! Allocate arrays for the WriteOutput + CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + y%WriteOutput = 0.0_ReKi + + CALL AllocAry( InitOut%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + CALL AllocAry( InitOut%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + InitOut%WriteOutputHdr = p%OutParam(1:p%NumOuts)%Name + InitOut%WriteOutputUnt = p%OutParam(1:p%NumOuts)%Units + + + + + + + + + + ! Init routine load + p%DLL_Orca%FileName = InputFileData%DLL_FileName + p%DLL_Orca%ProcName(1) = InputFileData%DLL_InitProcName + p%DLL_Orca%ProcName(2) = InputFileData%DLL_CalcProcName + p%DLL_Orca%ProcName(3) = InputFileData%DLL_EndProcName + +#ifdef NO_LibLoad + CALL SetErrStat( ErrID_Warn,' --> Skipping LoadDynamicLib call for '//TRIM(p%DLL_Orca%FileName),ErrStat,ErrMsg,RoutineName ) +#else + CALL LoadDynamicLib ( p%DLL_Orca, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + CALL C_F_PROCPOINTER( p%DLL_Orca%ProcAddr(1), OrcaDLL_Init ) +#endif + + + + + ! Set the values to pass to OrcaDLL_Init + DLL_DT = Interval + DLL_TMax = InitInp%TMax + +#ifdef NO_LibLoad + CALL SetErrStat( ErrID_Warn,' --> Skipping OrcaDLL_Init call',ErrStat,ErrMsg,RoutineName ) +#else + CALL OrcaDLL_Init ( DLL_DT, DLL_TMax ) + ! Unfortunately, we don't get any error reporting back from OrcaDLL_Init, so we can't really check anything. + !bjj: we should be warning people to use text output files instead of binary in case OrcaFlex crashes... +#endif + + + ! Copy relevant information into parameters. + p%SimNamePathLen = LEN_TRIM(InputFileData%DirRoot)+1 + p%SimNamePath = TRIM(InputFileData%DirRoot)//CHAR(0) + + + ! Create the input and output meshes associated with lumped loads + CALL MeshCreate( BlankMesh = u%PtfmMesh , & + IOS = COMPONENT_INPUT , & + Nnodes = 1 , & + ErrStat = ErrStatTmp , & + ErrMess = ErrMsgTmp , & + TranslationDisp = .TRUE. , & + Orientation = .TRUE. , & + TranslationVel = .TRUE. , & + RotationVel = .TRUE. , & + TranslationAcc = .TRUE. , & + RotationAcc = .TRUE.) + + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + ! Create the node on the mesh + CALL MeshPositionNode (u%PtfmMesh, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + + ! Create the mesh element + CALL MeshConstructElement ( u%PtfmMesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, 1 ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + + CALL MeshCommit ( u%PtfmMesh, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + CALL MeshCopy( SrcMesh=u%PtfmMesh, DestMesh=y%PtfmMesh, CtrlCode=MESH_SIBLING, IOS=COMPONENT_OUTPUT, & + ErrStat=ErrStatTmp, ErrMess=ErrMsgTmp, Force=.TRUE., Moment=.TRUE. ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp + RETURN + END IF + + + u%PtfmMesh%RemapFlag = .TRUE. + y%PtfmMesh%RemapFlag = .TRUE. + + + + + ! Set zero values for the MiscVar arrays + m%PtfmAM = 0.0_ReKi + m%PtfmFt = 0.0_ReKi + m%LastTimeStep = -1.0_DbKi + + InitOut%Ver = Orca_Ver + + +CONTAINS + !------------------------------------------------------------------ + SUBROUTINE CleanUp() + + IF ( ErrStat >= AbortErrLev ) THEN + CALL Orca_DestroyInputFile(InputFileData, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + END IF + + END SUBROUTINE CleanUp + +END SUBROUTINE Orca_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary OrcaFlex Interface input file and places the values it reads in the InputFileData structure. +!! It opens an echo file if requested. +SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, OutFileRoot, ErrStat, ErrMsg ) + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of the echo file, possibly opened in this routine + + TYPE(Orca_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the OrcaFlex Interface input file + + ! Local variables: + INTEGER(IntKi) :: I ! loop counter +! INTEGER(IntKi) :: NumOuts ! Number of output channel names read from the file + INTEGER(IntKi) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi) :: UnIn ! Unit number for reading file + INTEGER(IntKi) :: IOS + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: CWD ! Path name of the current working directory + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + CHARACTER(*), PARAMETER :: RoutineName = 'ReadPrimaryFile' + + ! Initialize some variables: + Echo = .FALSE. + UnEc = -1 ! Echo file not opened, yet + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + ! OrcaFlex doesn't like relative path names, so we're going to make it absolute + IF ( PathIsRelative( PriPath ) ) THEN + CALL GET_CWD(CWD, ErrStat2) +! PriPath = TRIM(CWD)//PathSep//TRIM(PriPath) + PriPath = TRIM(CWD)//TRIM(PriPath(2:)) + END IF + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "OrcaFlex Interface Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 ! the number of times we've read the file (used for the Echo variable) + DO + !-------------------------- HEADER --------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'File Header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + CALL ReadStr( UnIn, InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- SIMULATION DATA -------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Simulation Control', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Echo - Echo input to "<RootName>.ech". + + CALL ReadVar( UnIn, InputFile, Echo, 'Echo', 'Echo switch', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, Orca_Ver ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(Orca_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + + END DO + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr( ' Heading of the '//TRIM(Orca_Ver%Name)//' input file: ' ) + CALL WrScr( ' '//TRIM( FTitle ) ) + END IF + + + ! InputFileData%DirRoot - Name of the file containing OrcaFlex simulation inputs: + CALL ReadVar ( UnIn, InputFile, InputFileData%DirRoot, 'DirRoot', 'Name of the OrcaFlex simulation input file', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( InputFileData%DirRoot ) ) InputFileData%DirRoot = TRIM(PriPath)//TRIM(InputFileData%DirRoot) + + ! InputFileData%DLLPathFileName - Name of the file containing OrcaFlex simulation inputs: + CALL ReadVar ( UnIn, InputFile, InputFileData%DLL_FileName, 'DLL_FileName', 'Name of the OrcaFlex DLL', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + IF ( PathIsRelative( InputFileData%DLL_FileName ) ) InputFileData%DLL_FileName = TRIM(PriPath)//TRIM(InputFileData%DLL_FileName) + + + ! ! DT - Requested integration time for OrcaFlex (seconds): + !CALL ReadVar( UnIn, InputFile, Line, "DT", "Requested integration time for OrcaFlex (seconds)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + ! CALL Conv2UC( Line ) + ! IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DT + ! READ( Line, *, IOSTAT=IOS) InputFileData%DT + ! IF ( IOS /= 0 ) THEN + ! CALL CheckIOS ( IOS, InputFile, "DT", NumType, ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! RETURN + ! END IF + ! END IF + + + !!---------------------- OUTLIST -------------------------------------------- + !CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! IF ( ErrStat >= AbortErrLev ) THEN + ! CALL Cleanup() + ! RETURN + ! END IF + ! + ! ! OutList - List of user-requested output channels (-): + !CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! IF ( ErrStat >= AbortErrLev ) THEN + ! CALL Cleanup() + ! RETURN + ! END IF + + !---------------------- END OF FILE ----------------------------------------- + + CALL Cleanup() + RETURN + +CONTAINS + SUBROUTINE Cleanup() + + CLOSE(UnIn) + IF (UnEc > 0) CLOSE(UnEc) + + END SUBROUTINE Cleanup +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE Orca_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + TYPE(Orca_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(Orca_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(Orca_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(Orca_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(Orca_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(Orca_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(Orca_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(Orca_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 + + PROCEDURE(OrcaFlexUserPtfmLdFinalise), POINTER :: OrcaDLL_End + + ! Error Handling + INTEGER(IntKi) :: ErrStatTmp ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsgTmp ! temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName='Orca_End' + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ErrStatTmp = ErrID_None + ErrMsgTmp = "" + + + + +#ifdef NO_LibLoad + CALL SetErrStat( ErrID_Warn,' --> Skipping OrcaDLL_End call',ErrStat,ErrMsg,RoutineName ) +#else + ! Release the DLL + CALL C_F_PROCPOINTER( p%DLL_Orca%ProcAddr(3), OrcaDLL_End ) + CALL OrcaDLL_End ! No error handling here. Just have to assume it worked. + + + CALL FreeDynamicLib( p%DLL_Orca, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) +#endif + + + ! Destroy the input data: + CALL Orca_DestroyInput( u, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + + + ! Destroy the parameter data: +#ifdef NO_LibLoad +#else + CALL Orca_DestroyParam( p, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) +#endif + + + ! Destroy the state data: + CALL Orca_DestroyContState( x, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + CALL Orca_DestroyDiscState( xd, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + CALL Orca_DestroyConstrState( z, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + CALL Orca_DestroyOtherState( OtherState, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + + ! Destroy misc variables: + CALL Orca_DestroyMisc( m, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + + + ! Destroy the output data: + CALL Orca_DestroyOutput( y, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName ) + + +END SUBROUTINE Orca_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +!! This SUBROUTINE is used to compute the output channels (motions and loads) and place them in the WriteOutput() array. +!! NOTE: the descriptions of the output channels are not given here. Please see the included OutListParameters.xlsx sheet for +!! for a complete description of each output parameter. +!! NOTE: no matter how many channels are selected for output, all of the outputs are calculated +!! All of the calculated output channels are placed into the m%AllOuts(:), while the channels selected for outputs are +!! placed in the y%WriteOutput(:) array. +SUBROUTINE Orca_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(Orca_InputType), INTENT(IN ) :: u !< Inputs at Time t + TYPE(Orca_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Orca_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(Orca_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(Orca_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(Orca_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(Orca_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(Orca_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 + + PROCEDURE(OrcaFlexUserPtfmLd), POINTER :: OrcaDLL_Calc + + + ! Local variables copied from the mesh + REAL(ReKi) :: rotdisp(3) !< Rotation angles from the mesh + REAL(ReKi) :: q(6) !< Position from the mesh + REAL(ReKi) :: qdot(6) !< Time derivative of position (velocity) from mesh + REAL(ReKi) :: qdotdot(6) !< 2nd time derivative of position (acceleration) from mesh + + + ! Local variables for data manipulation + INTEGER(IntKi) :: I,J !< Generic counters + + + + ! Local variables for the getting the types correct to pass to the DLL + CHARACTER(LEN=p%SimNamePathLen) :: DLL_DirRootName !< Path and simulation name without extension + REAL(C_FLOAT) :: DLL_X(6) !< Translational and rotational displacement (m, radians) relative to inertial frame. + REAL(C_FLOAT) :: DLL_Xdot(6) !< Translational and rotational velocity (m/s, radians/s) relative to inertial frame. + REAL(C_FLOAT) :: DLL_ZTime !< Current time in seconds + REAL(C_FLOAT) :: DLL_PtfmAM(6,6) !< Added mass matrix (kg, kg-m, kg-m^2) + REAL(C_FLOAT) :: DLL_PtfmFt(6) !< Platform forces -- [3 translation (N), 3 moments (N-m)] at reference point. + + + ! Error Handling and data checking + INTEGER(IntKi) :: ErrStatTmp !< Temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsgTmp !< Temporary Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName='Orca_Calc' + REAL(ReKi), PARAMETER :: SymmetryTol = 9.999E-4_ReKi !< Tolerance used to determine if the PtfmAM is symmetric + + + ! Copy over time and name to pass to OrcaFlex DLL + DLL_DirRootName = TRIM(p%SimNamePath)//C_NULL_CHAR ! Path and name of the simulation file without extension. Null character added to convert from Fortran string to C-type string. + DLL_ZTime = t ! Current time + + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( u%PtfmMesh%Orientation(:,:,1), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= ErrID_Fatal) RETURN + + q = reshape((/REAL(u%PtfmMesh%TranslationDisp(:,1),ReKi),rotdisp(:)/),(/6/)) + qdot = reshape((/u%PtfmMesh%TranslationVel(:,1),u%PtfmMesh%RotationVel(:,1)/),(/6/)) + qdotdot = reshape((/u%PtfmMesh%TranslationAcc(:,1),u%PtfmMesh%RotationAcc(:,1)/),(/6/)) + + + ! Copy position and motion information over to pass to the DLL + DO I=1,6 + DLL_X(I) = q(I) + DLL_Xdot(I) = qdot(I) + ENDDO + + + +#ifdef NO_LibLoad + CALL SetErrStat( ErrID_Warn,' --> Skipping OrcaDLL_Calc call',ErrStat,ErrMsg,RoutineName ) + DLL_PtfmAM = 0.0_C_FLOAT + DLL_PtfmFt = 0.0_C_FLOAT +#else + + ! We do not want to call OrcaDLL twice in one timestep. If _CalcOutput is called twice in a timestep, the second + ! call is different from the first only with the accelerations, which OrcaFlex does not do anything with. + IF ( t > m%LastTimeStep .and. .not. EqualRealNos(t,m%LastTimeStep) ) THEN + ! Setup the pointer to the DLL procedure + CALL C_F_PROCPOINTER( p%DLL_Orca%ProcAddr(2), OrcaDLL_Calc ) + ! Call OrcaFlex to run the calculation. There is no error trapping on the OrcaFlex side, so we will have to do some checks on what receive back + CALL OrcaDLL_Calc( DLL_X, DLL_Xdot, DLL_ZTime, DLL_DirRootName, DLL_PtfmAM, DLL_PtfmFt ) + m%LastTimeStep = t + + ! Copy data over from the DLL output to the m + DO I=1,6 + m%PtfmFT(I) = DLL_PtfmFT(I) + DO J=1,6 + m%PtfmAM(J,I) = DLL_PtfmAM(J,I) + ENDDO + ENDDO + + + !!! bjj: commented this out 11=Apr=2016 because it doesn't seem like this is necessary; per jmj + !!! ! Perform some quick QA/QC on the DLL results. There isn't much we can check, so just check that things are symmetric within some tolerance + !!!DO I = 1,5 ! Loop through the 1st 5 rows (columns) of PtfmAM + !!! DO J = (I+1),6 ! Loop through all columns (rows) passed I + !!! IF ( ABS( m%PtfmAM(I,J) - m%PtfmAM(J,I) ) > SymmetryTol ) & + !!! ErrStatTmp = ErrID_Fatal + !!! ErrMsgTmp = ' The platform added mass matrix returned from OrcaFlex is unsymmetric.'// & + !!! ' There may be issues with the OrcaFlex calculations.' + !!! ENDDO ! J - All columns (rows) passed I + !!!ENDDO ! I - The 1st 5 rows (columns) of PtfmAM + !!!CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + !!!IF ( ErrStat >= ErrID_Fatal) RETURN + + ENDIF +#endif + + + ! Now calculate the forces with what OrcaFlex returned + m%F_PtfmAM = -matmul(m%PtfmAM, qdotdot) + + + + ! Update the Mesh with values from OrcaFlex + DO I=1,3 + y%PtfmMesh%Force(I,1) = m%F_PtfmAM(I) + m%PtfmFT(I) + y%PtfmMesh%Moment(I,1) = m%F_PtfmAM(I+3) + m%PtfmFT(I+3) + ENDDO + +!#ifdef NO_LibLoad +! y%PtfmMesh%Force = 6.0E6 +! y%PtfmMesh%Moment = 2.0E6 +!#endif + + + ! Set all the outputs + CALL SetAllOuts( p, y, m, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= ErrID_Fatal) RETURN + + + + RETURN + + +END SUBROUTINE Orca_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 Orca_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current simulation time step n = 0,1,... + TYPE(Orca_InputType), INTENT(INOUT) :: u(:) !< Inputs at utimes (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< Times associated with u(:), in seconds + TYPE(Orca_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Orca_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(Orca_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(Orca_ConstraintStateType), INTENT(INOUT) :: z !< Input: Initial guess of constraint states at t+dt; + !! Output: Constraint states at t+dt + TYPE(Orca_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(Orca_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 + + ErrStat = ErrID_None + ErrMsg = "" + + +END SUBROUTINE Orca_UpdateStates +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 01-Sep-2015 14:29:18. +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +! This routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +! warning if any of the channels are not available outputs from the module. +! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +! the sign is set to 0 if the channel is invalid. +! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) ! The list out user-requested outputs + TYPE(Orca_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 + + ! Local variables + + 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(18) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "ORCAAMFXI","ORCAAMFYI","ORCAAMFZI", & + "ORCAAMMXI","ORCAAMMYI","ORCAAMMZI", & + "ORCAFXI ","ORCAFYI ","ORCAFZI ", & + "ORCAHMFXI","ORCAHMFYI","ORCAHMFZI", & + "ORCAHMMXI","ORCAHMMYI","ORCAHMMZI", & + "ORCAMXI ","ORCAMYI ","ORCAMZI "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(18) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + OrcaAMFxi , OrcaAMFyi , OrcaAMFzi , & + OrcaAMMxi , OrcaAMMyi , OrcaAMMzi , & + OrcaFxi , OrcaFyi , OrcaFzi , & + OrcaHMFxi , OrcaHMFyi , OrcaHMFzi , & + OrcaHMMxi , OrcaHMMyi , OrcaHMMzi , & + OrcaMxi , OrcaMyi , OrcaMzi /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(18) = (/ & ! This lists the units corresponding to the allowed parameters + "(kN) ","(kN) ","(kN) ", & + "(kN m) ","(kN m) ","(kN m) ", & + "(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ", & + "(kN m) ","(kN m) ","(kN m) ", & + "(kN m) ","(kN m) ","(kN m) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + +! ..... Developer must add checking for invalid inputs here: ..... + +! ................. End of validity checking ................. + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the OrcaFlexInterface OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = Time ! pick any valid channel (I just picked "Time" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +SUBROUTINE SetAllOuts( ParamData, OutData, m, ErrStat, ErrMsg ) + + IMPLICIT NONE + + CHARACTER(*), PARAMETER :: RoutineName="SetAllOuts" + + + TYPE(Orca_ParameterType), INTENT(IN ) :: ParamData !< The parameters for Orca + TYPE(Orca_OutputType), INTENT(INOUT) :: OutData !< Outputs + TYPE(Orca_MiscVarType), INTENT(INOUT) :: m !< The MiscVars info for Orca + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status from this subroutine + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message from this subroutine + + + ! Local Variables + INTEGER(IntKi) :: I !< Generic counter + + + ! Initialization + ErrStat = ErrID_None + ErrMsg = '' + + + ! Set the values + m%AllOuts( OrcaFxi ) = OutData%PtfmMesh%Force(1,1)/1000_ReKi + m%AllOuts( OrcaFyi ) = OutData%PtfmMesh%Force(2,1)/1000_ReKi + m%AllOuts( OrcaFzi ) = OutData%PtfmMesh%Force(3,1)/1000_ReKi + m%AllOuts( OrcaMxi ) = OutData%PtfmMesh%Moment(1,1)/1000_ReKi + m%AllOuts( OrcaMyi ) = OutData%PtfmMesh%Moment(2,1)/1000_ReKi + m%AllOuts( OrcaMzi ) = OutData%PtfmMesh%Moment(3,1)/1000_ReKi + + m%AllOuts( OrcaHMFxi ) = m%PtfmFT(1)/1000_ReKi + m%AllOuts( OrcaHMFyi ) = m%PtfmFT(2)/1000_ReKi + m%AllOuts( OrcaHMFzi ) = m%PtfmFT(3)/1000_ReKi + m%AllOuts( OrcaHMMxi ) = m%PtfmFT(4)/1000_ReKi + m%AllOuts( OrcaHMMyi ) = m%PtfmFT(5)/1000_ReKi + m%AllOuts( OrcaHMMzi ) = m%PtfmFT(6)/1000_ReKi + + m%AllOuts( OrcaAMFxi ) = m%F_PtfmAM(1)/1000_ReKi + m%AllOuts( OrcaAMFyi ) = m%F_PtfmAM(2)/1000_ReKi + m%AllOuts( OrcaAMFzi ) = m%F_PtfmAM(3)/1000_ReKi + m%AllOuts( OrcaAMMxi ) = m%F_PtfmAM(4)/1000_ReKi + m%AllOuts( OrcaAMMyi ) = m%F_PtfmAM(5)/1000_ReKi + m%AllOuts( OrcaAMMzi ) = m%F_PtfmAM(6)/1000_ReKi + + ! Set the values for the WriteOutput array + OutData%WriteOutput( OrcaFxi ) = OutData%PtfmMesh%Force(1,1)/1000_ReKi + OutData%WriteOutput( OrcaFyi ) = OutData%PtfmMesh%Force(2,1)/1000_ReKi + OutData%WriteOutput( OrcaFzi ) = OutData%PtfmMesh%Force(3,1)/1000_ReKi + OutData%WriteOutput( OrcaMxi ) = OutData%PtfmMesh%Moment(1,1)/1000_ReKi + OutData%WriteOutput( OrcaMyi ) = OutData%PtfmMesh%Moment(2,1)/1000_ReKi + OutData%WriteOutput( OrcaMzi ) = OutData%PtfmMesh%Moment(3,1)/1000_ReKi + + OutData%WriteOutput( OrcaHMFxi ) = m%PtfmFT(1)/1000_ReKi + OutData%WriteOutput( OrcaHMFyi ) = m%PtfmFT(2)/1000_ReKi + OutData%WriteOutput( OrcaHMFzi ) = m%PtfmFT(3)/1000_ReKi + OutData%WriteOutput( OrcaHMMxi ) = m%PtfmFT(4)/1000_ReKi + OutData%WriteOutput( OrcaHMMyi ) = m%PtfmFT(5)/1000_ReKi + OutData%WriteOutput( OrcaHMMzi ) = m%PtfmFT(6)/1000_ReKi + + OutData%WriteOutput( OrcaAMFxi ) = m%F_PtfmAM(1)/1000_ReKi + OutData%WriteOutput( OrcaAMFyi ) = m%F_PtfmAM(2)/1000_ReKi + OutData%WriteOutput( OrcaAMFzi ) = m%F_PtfmAM(3)/1000_ReKi + OutData%WriteOutput( OrcaAMMxi ) = m%F_PtfmAM(4)/1000_ReKi + OutData%WriteOutput( OrcaAMMyi ) = m%F_PtfmAM(5)/1000_ReKi + OutData%WriteOutput( OrcaAMMzi ) = m%F_PtfmAM(6)/1000_ReKi + + +END SUBROUTINE SetAllOuts + + + + +END MODULE OrcaFlexInterface +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.txt b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.txt new file mode 100644 index 000000000..da75c894e --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface.txt @@ -0,0 +1,75 @@ +################################################################################################################################### +# Registry for OrcaFlexInterface in the FAST Modularization Framework +# This Registry file is used to create MODULE OrcaFlexInterface_Types which contains all of the user-defined types needed in OrcaFlexInterface. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef OrcaFlexInterface/Orca InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files (echo file)" - +typedef ^ ^ ReKi TMax - - - "Maximum Time" seconds + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - + + +# Inputfile information +typedef ^ Orca_InputFile CHARACTER(1024) DLL_FileName - - - "Name of the DLL file" - +typedef ^ ^ CHARACTER(1024) DLL_InitProcName - - - "Name of the DLL procedure to call during initialisation" - +typedef ^ ^ CHARACTER(1024) DLL_CalcProcName - - - "Name of the DLL procedure to call during CalcOutput" - +typedef ^ ^ CHARACTER(1024) DLL_EndProcName - - - "Name of the DLL procedure to call during End" - +typedef ^ ^ CHARACTER(1024) DirRoot - - - "Directory and rootname of simulation input file" - + + + + + +# Define "other" states here: +# note that some of the "miscVars" are associated with time, but due to the nature of calling the DLL only once per time step, I have +# chosen not to place them in other states +typedef ^ OtherStateType SiKi DummyOtherState - - - "Remove if you have OtherStates" - + + +# ..... 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 PtfmAM {6}{6} - - "Added mass matrix results from OrcaFlex" - +typedef ^ ^ ReKi PtfmFt {6} - - "Force/moment results from OrcaFlex" - +typedef ^ ^ ReKi F_PtfmAM {6} - - "Force/moment results calculated from the added mass and accel" - +typedef ^ ^ ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" +typedef ^ ^ DbKi LastTimeStep - - - "The last timestep called" - + + +# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: +typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ^ DLL_Type DLL_Orca - - - "Info for the OrcaFlex DLL" - +typedef ^ ^ CHARACTER(1024) SimNamePath - - - "Path with simulation rootname with null end character for passing to C" - +typedef ^ ^ IntKi SimNamePathLen - - - "Length of SimNamePath (including null char)" - +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" - + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef ^ InputType MeshType PtfmMesh - - - "Displacements at the platform reference point" - + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType PtfmMesh - - - "Loads at the platform reference point" - +typedef ^ OutputType ReKi WriteOutput : - - "Array with values to output to file" - + + + +typedef ^ ContinuousStateType ReKi Dummy - - - "Dummy placeholder" - +typedef ^ DiscreteStateType ReKi Dummy - - - "Dummy placeholder" - +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Dummy placeholder" - diff --git a/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface_Types.f90 b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface_Types.f90 new file mode 100644 index 000000000..51a40873d --- /dev/null +++ b/OpenFAST/modules/orcaflex-interface/src/OrcaFlexInterface_Types.f90 @@ -0,0 +1,2655 @@ +!STARTOFREGISTRYGENERATEDFILE 'OrcaFlexInterface_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 +!********************************************************************************************************************************* +! OrcaFlexInterface_Types +!................................................................................................................................. +! This file is part of OrcaFlexInterface. +! +! 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 OrcaFlexInterface. 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 OrcaFlexInterface_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= Orca_InitInputType ======= + TYPE, PUBLIC :: Orca_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files (echo file) [-] + REAL(ReKi) :: TMax !< Maximum Time [seconds] + END TYPE Orca_InitInputType +! ======================= +! ========= Orca_InitOutputType ======= + TYPE, PUBLIC :: Orca_InitOutputType + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + END TYPE Orca_InitOutputType +! ======================= +! ========= Orca_InputFile ======= + TYPE, PUBLIC :: Orca_InputFile + CHARACTER(1024) :: DLL_FileName !< Name of the DLL file [-] + CHARACTER(1024) :: DLL_InitProcName !< Name of the DLL procedure to call during initialisation [-] + CHARACTER(1024) :: DLL_CalcProcName !< Name of the DLL procedure to call during CalcOutput [-] + CHARACTER(1024) :: DLL_EndProcName !< Name of the DLL procedure to call during End [-] + CHARACTER(1024) :: DirRoot !< Directory and rootname of simulation input file [-] + END TYPE Orca_InputFile +! ======================= +! ========= Orca_OtherStateType ======= + TYPE, PUBLIC :: Orca_OtherStateType + REAL(SiKi) :: DummyOtherState !< Remove if you have OtherStates [-] + END TYPE Orca_OtherStateType +! ======================= +! ========= Orca_MiscVarType ======= + TYPE, PUBLIC :: Orca_MiscVarType + REAL(ReKi) , DIMENSION(1:6,1:6) :: PtfmAM !< Added mass matrix results from OrcaFlex [-] + REAL(ReKi) , DIMENSION(1:6) :: PtfmFt !< Force/moment results from OrcaFlex [-] + REAL(ReKi) , DIMENSION(1:6) :: F_PtfmAM !< Force/moment results calculated from the added mass and accel [-] + 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(DbKi) :: LastTimeStep !< The last timestep called [-] + END TYPE Orca_MiscVarType +! ======================= +! ========= Orca_ParameterType ======= + TYPE, PUBLIC :: Orca_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + TYPE(DLL_Type) :: DLL_Orca !< Info for the OrcaFlex DLL [-] + CHARACTER(1024) :: SimNamePath !< Path with simulation rootname with null end character for passing to C [-] + INTEGER(IntKi) :: SimNamePathLen !< Length of SimNamePath (including null char) [-] + 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 [-] + END TYPE Orca_ParameterType +! ======================= +! ========= Orca_InputType ======= + TYPE, PUBLIC :: Orca_InputType + TYPE(MeshType) :: PtfmMesh !< Displacements at the platform reference point [-] + END TYPE Orca_InputType +! ======================= +! ========= Orca_OutputType ======= + TYPE, PUBLIC :: Orca_OutputType + TYPE(MeshType) :: PtfmMesh !< Loads at the platform reference point [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Array with values to output to file [-] + END TYPE Orca_OutputType +! ======================= +! ========= Orca_ContinuousStateType ======= + TYPE, PUBLIC :: Orca_ContinuousStateType + REAL(ReKi) :: Dummy !< Dummy placeholder [-] + END TYPE Orca_ContinuousStateType +! ======================= +! ========= Orca_DiscreteStateType ======= + TYPE, PUBLIC :: Orca_DiscreteStateType + REAL(ReKi) :: Dummy !< Dummy placeholder [-] + END TYPE Orca_DiscreteStateType +! ======================= +! ========= Orca_ConstraintStateType ======= + TYPE, PUBLIC :: Orca_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Dummy placeholder [-] + END TYPE Orca_ConstraintStateType +! ======================= +CONTAINS + SUBROUTINE Orca_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(Orca_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 = 'Orca_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%TMax = SrcInitInputData%TMax + END SUBROUTINE Orca_CopyInitInput + + SUBROUTINE Orca_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(Orca_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyInitInput + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! TMax + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%TMax + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Orca_PackInitInput + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%TMax = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Orca_UnPackInitInput + + SUBROUTINE Orca_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(Orca_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 = 'Orca_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 +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE Orca_CopyInitOutput + + SUBROUTINE Orca_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(Orca_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE Orca_DestroyInitOutput + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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 + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE Orca_PackInitOutput + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + END SUBROUTINE Orca_UnPackInitOutput + + SUBROUTINE Orca_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(Orca_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'Orca_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DLL_FileName = SrcInputFileData%DLL_FileName + DstInputFileData%DLL_InitProcName = SrcInputFileData%DLL_InitProcName + DstInputFileData%DLL_CalcProcName = SrcInputFileData%DLL_CalcProcName + DstInputFileData%DLL_EndProcName = SrcInputFileData%DLL_EndProcName + DstInputFileData%DirRoot = SrcInputFileData%DirRoot + END SUBROUTINE Orca_CopyInputFile + + SUBROUTINE Orca_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(Orca_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyInputFile + + SUBROUTINE Orca_PackInputFile( 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(Orca_InputFile), 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 = 'Orca_PackInputFile' + ! 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%DLL_FileName) ! DLL_FileName + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_InitProcName) ! DLL_InitProcName + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_CalcProcName) ! DLL_CalcProcName + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_EndProcName) ! DLL_EndProcName + Int_BufSz = Int_BufSz + 1*LEN(InData%DirRoot) ! DirRoot + 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%DLL_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DLL_InitProcName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_InitProcName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DLL_CalcProcName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_CalcProcName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DLL_EndProcName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_EndProcName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DirRoot) + IntKiBuf(Int_Xferred) = ICHAR(InData%DirRoot(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Orca_PackInputFile + + SUBROUTINE Orca_UnPackInputFile( 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(Orca_InputFile), 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 = 'Orca_UnPackInputFile' + ! 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%DLL_FileName) + OutData%DLL_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DLL_InitProcName) + OutData%DLL_InitProcName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DLL_CalcProcName) + OutData%DLL_CalcProcName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DLL_EndProcName) + OutData%DLL_EndProcName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DirRoot) + OutData%DirRoot(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE Orca_UnPackInputFile + + SUBROUTINE Orca_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(Orca_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 = 'Orca_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE Orca_CopyOtherState + + SUBROUTINE Orca_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(Orca_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyOtherState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 Orca_PackOtherState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Orca_UnPackOtherState + + SUBROUTINE Orca_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(Orca_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%PtfmAM = SrcMiscData%PtfmAM + DstMiscData%PtfmFt = SrcMiscData%PtfmFt + DstMiscData%F_PtfmAM = SrcMiscData%F_PtfmAM +IF (ALLOCATED(SrcMiscData%AllOuts)) THEN + i1_l = LBOUND(SrcMiscData%AllOuts,1) + i1_u = UBOUND(SrcMiscData%AllOuts,1) + IF (.NOT. ALLOCATED(DstMiscData%AllOuts)) THEN + ALLOCATE(DstMiscData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%AllOuts = SrcMiscData%AllOuts +ENDIF + DstMiscData%LastTimeStep = SrcMiscData%LastTimeStep + END SUBROUTINE Orca_CopyMisc + + SUBROUTINE Orca_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(Orca_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%AllOuts)) THEN + DEALLOCATE(MiscData%AllOuts) +ENDIF + END SUBROUTINE Orca_DestroyMisc + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 + SIZE(InData%PtfmAM) ! PtfmAM + Re_BufSz = Re_BufSz + SIZE(InData%PtfmFt) ! PtfmFt + Re_BufSz = Re_BufSz + SIZE(InData%F_PtfmAM) ! F_PtfmAM + 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 + Re_BufSz = Re_BufSz + SIZE(InData%AllOuts) ! AllOuts + END IF + Db_BufSz = Db_BufSz + 1 ! LastTimeStep + 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 i2 = LBOUND(InData%PtfmAM,2), UBOUND(InData%PtfmAM,2) + DO i1 = LBOUND(InData%PtfmAM,1), UBOUND(InData%PtfmAM,1) + ReKiBuf(Re_Xferred) = InData%PtfmAM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i1 = LBOUND(InData%PtfmFt,1), UBOUND(InData%PtfmFt,1) + ReKiBuf(Re_Xferred) = InData%PtfmFt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_PtfmAM,1), UBOUND(InData%F_PtfmAM,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%AllOuts) ) 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%AllOuts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AllOuts,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AllOuts,1), UBOUND(InData%AllOuts,1) + ReKiBuf(Re_Xferred) = InData%AllOuts(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%LastTimeStep + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Orca_PackMisc + + SUBROUTINE Orca_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(Orca_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_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 + i1_l = LBOUND(OutData%PtfmAM,1) + i1_u = UBOUND(OutData%PtfmAM,1) + i2_l = LBOUND(OutData%PtfmAM,2) + i2_u = UBOUND(OutData%PtfmAM,2) + DO i2 = LBOUND(OutData%PtfmAM,2), UBOUND(OutData%PtfmAM,2) + DO i1 = LBOUND(OutData%PtfmAM,1), UBOUND(OutData%PtfmAM,1) + OutData%PtfmAM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%PtfmFt,1) + i1_u = UBOUND(OutData%PtfmFt,1) + DO i1 = LBOUND(OutData%PtfmFt,1), UBOUND(OutData%PtfmFt,1) + OutData%PtfmFt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_PtfmAM,1) + i1_u = UBOUND(OutData%F_PtfmAM,1) + DO i1 = LBOUND(OutData%F_PtfmAM,1), UBOUND(OutData%F_PtfmAM,1) + OutData%F_PtfmAM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOuts 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%AllOuts)) DEALLOCATE(OutData%AllOuts) + ALLOCATE(OutData%AllOuts(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AllOuts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AllOuts,1), UBOUND(OutData%AllOuts,1) + OutData%AllOuts(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%LastTimeStep = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE Orca_UnPackMisc + + SUBROUTINE Orca_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_ParameterType), INTENT(IN) :: SrcParamData + TYPE(Orca_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 = 'Orca_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%DLL_Orca = SrcParamData%DLL_Orca + DstParamData%SimNamePath = SrcParamData%SimNamePath + DstParamData%SimNamePathLen = SrcParamData%SimNamePathLen + DstParamData%NumOuts = SrcParamData%NumOuts +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + END SUBROUTINE Orca_CopyParam + + SUBROUTINE Orca_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(Orca_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL FreeDynamicLib( ParamData%DLL_Orca, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE Orca_DestroyParam + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 + Db_BufSz = Db_BufSz + 1 ! DT + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! DLL_Orca: size of buffers for each call to pack subtype + CALL DLLTypePack( InData%DLL_Orca, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DLL_Orca + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DLL_Orca + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DLL_Orca + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DLL_Orca + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%SimNamePath) ! SimNamePath + Int_BufSz = Int_BufSz + 1 ! SimNamePathLen + Int_BufSz = Int_BufSz + 1 ! NumOuts + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + CALL DLLTypePack( InData%DLL_Orca, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DLL_Orca + 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%SimNamePath) + IntKiBuf(Int_Xferred) = ICHAR(InData%SimNamePath(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%SimNamePathLen + 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 + + 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 + END SUBROUTINE Orca_PackParam + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_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 DLLTypeUnpack( OutData%DLL_Orca, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DLL_Orca + 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%SimNamePath) + OutData%SimNamePath(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%SimNamePathLen = 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 + 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + END SUBROUTINE Orca_UnPackParam + + SUBROUTINE Orca_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_InputType), INTENT(INOUT) :: SrcInputData + TYPE(Orca_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%PtfmMesh, DstInputData%PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE Orca_CopyInput + + SUBROUTINE Orca_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(Orca_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%PtfmMesh, ErrStat, ErrMsg ) + END SUBROUTINE Orca_DestroyInput + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtfmMesh + 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 MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtfmMesh + 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 Orca_PackInput + + SUBROUTINE Orca_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(Orca_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_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 + 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 MeshUnpack( OutData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtfmMesh + 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 Orca_UnPackInput + + SUBROUTINE Orca_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(Orca_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'Orca_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%PtfmMesh, DstOutputData%PtfmMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE Orca_CopyOutput + + SUBROUTINE Orca_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(Orca_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%PtfmMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE Orca_DestroyOutput + + SUBROUTINE Orca_PackOutput( 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(Orca_OutputType), 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 = 'Orca_PackOutput' + ! 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 ! PtfmMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PtfmMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PtfmMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PtfmMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PtfmMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PtfmMesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Orca_PackOutput + + SUBROUTINE Orca_UnPackOutput( 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(Orca_OutputType), 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 = 'Orca_UnPackOutput' + ! 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 MeshUnpack( OutData%PtfmMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PtfmMesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE Orca_UnPackOutput + + SUBROUTINE Orca_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(Orca_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 = 'Orca_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%Dummy = SrcContStateData%Dummy + END SUBROUTINE Orca_CopyContState + + SUBROUTINE Orca_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(Orca_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyContState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 ! 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 Orca_PackContState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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%Dummy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Orca_UnPackContState + + SUBROUTINE Orca_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(Orca_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 = 'Orca_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%Dummy = SrcDiscStateData%Dummy + END SUBROUTINE Orca_CopyDiscState + + SUBROUTINE Orca_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(Orca_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyDiscState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 ! 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 Orca_PackDiscState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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%Dummy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE Orca_UnPackDiscState + + SUBROUTINE Orca_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Orca_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(Orca_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 = 'Orca_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE Orca_CopyConstrState + + SUBROUTINE Orca_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(Orca_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Orca_DestroyConstrState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 Orca_PackConstrState + + SUBROUTINE Orca_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(Orca_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 = 'Orca_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 Orca_UnPackConstrState + + + SUBROUTINE Orca_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Orca_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(Orca_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL Orca_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Orca_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Orca_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Orca_Input_ExtrapInterp + + + SUBROUTINE Orca_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(Orca_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Orca_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(Orca_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%PtfmMesh, u2%PtfmMesh, tin, u_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE Orca_Input_ExtrapInterp1 + + + SUBROUTINE Orca_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(Orca_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Orca_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Orca_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(Orca_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%PtfmMesh, u2%PtfmMesh, u3%PtfmMesh, tin, u_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE Orca_Input_ExtrapInterp2 + + + SUBROUTINE Orca_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(Orca_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(Orca_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL Orca_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL Orca_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL Orca_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE Orca_Output_ExtrapInterp + + + SUBROUTINE Orca_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(Orca_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Orca_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(Orca_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%PtfmMesh, y2%PtfmMesh, tin, y_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE Orca_Output_ExtrapInterp1 + + + SUBROUTINE Orca_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(Orca_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Orca_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Orca_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(Orca_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'Orca_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%PtfmMesh, y2%PtfmMesh, y3%PtfmMesh, tin, y_out%PtfmMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE Orca_Output_ExtrapInterp2 + +END MODULE OrcaFlexInterface_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/servodyn/CMakeLists.txt b/OpenFAST/modules/servodyn/CMakeLists.txt new file mode 100644 index 000000000..a02b4400e --- /dev/null +++ b/OpenFAST/modules/servodyn/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/TMD_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/TMD_Types.f90) + generate_f90_types(src/ServoDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/ServoDyn_Types.f90) +endif() + +set(SD_SOURCES + src/BladedInterface.f90 + src/UserSubs.f90 + src/PitchCntrl_ACH.f90 + src/TMD.f90 + src/UserVSCont_KP.f90 + src/ServoDyn.f90 + src/TMD_Types.f90 + src/ServoDyn_Types.f90 +) + +add_library(servodynlib ${SD_SOURCES}) +target_link_libraries(servodynlib nwtclibs) + +add_executable(servodyn_driver src/ServoDyn_Driver.f90) +target_link_libraries(servodyn_driver servodynlib nwtclibs ${CMAKE_DL_LIBS}) + +add_executable(TMD src/TMD_Driver.f90) +target_link_libraries(TMD servodynlib nwtclibs ${CMAKE_DL_LIBS}) + +install(TARGETS servodynlib servodyn_driver TMD + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/servodyn/README.md b/OpenFAST/modules/servodyn/README.md new file mode 100644 index 000000000..e1d650508 --- /dev/null +++ b/OpenFAST/modules/servodyn/README.md @@ -0,0 +1,16 @@ +# ServoDyn Module +The legacy version of TMD and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/TMD/). + +## Overview +ServoDyn is the control and Electrical Drive Dynamics Module for the +OpenFAST framework. + +Included in ServoDyn is the tuned mass damper (TMD) module which adds +functionality to OpenFAST that simulates the addition of TMDs in the +nacelle and/or tower for structural control. The TMDs are two independent, +one-DOF, linear mass-spring-damping elements that act in the fore-aft and +side-side directions or one single omni-directional TMD. They can be placed +relative to the nacelle reference position or base of the undeflected tower +using the options in the input file. The TMD module is added as a sub-module +of ServoDyn. diff --git a/OpenFAST/modules/servodyn/src/BladedInterface.f90 b/OpenFAST/modules/servodyn/src/BladedInterface.f90 new file mode 100644 index 000000000..8fd332cde --- /dev/null +++ b/OpenFAST/modules/servodyn/src/BladedInterface.f90 @@ -0,0 +1,1126 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST's Controls and Electrical Drive Module, "ServoDyn". +! +! 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 BladedInterface + + USE NWTC_Library + + USE ServoDyn_Types + + USE, INTRINSIC :: ISO_C_Binding + + + IMPLICIT NONE + + + TYPE(ProgDesc), PARAMETER :: BladedInterface_Ver = ProgDesc( 'ServoDyn Interface for Bladed Controllers', 'using '//TRIM(OS_Desc), '' ) + + + !> Definition of the DLL Interface (from Bladed): + !! Note that aviFAIL and avcMSG should be used as INTENT(OUT), but I'm defining them INTENT(INOUT) just in case the compiler decides to reinitialize something that's INTENT(OUT) + + ABSTRACT INTERFACE + SUBROUTINE BladedDLL_Legacy_Procedure ( avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) BIND(C) + USE, INTRINSIC :: ISO_C_Binding + + REAL(C_FLOAT), INTENT(INOUT) :: avrSWAP (*) !< DATA + INTEGER(C_INT), INTENT(INOUT) :: aviFAIL !< FLAG (Status set in DLL and returned to simulation code) + CHARACTER(KIND=C_CHAR), INTENT(IN) :: accINFILE (*) !< INFILE + CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcOUTNAME(*) !< OUTNAME (in:Simulation RootName; out:Name:Units; of logging channels) + CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcMSG (*) !< MESSAGE (Message from DLL to simulation code [ErrMsg]) + END SUBROUTINE BladedDLL_Legacy_Procedure + + SUBROUTINE BladedDLL_SC_Procedure ( avrSWAP, from_SC, to_SC, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) BIND(C) + USE, INTRINSIC :: ISO_C_Binding + + REAL(C_FLOAT), INTENT(INOUT) :: avrSWAP (*) !< DATA + REAL(C_FLOAT), INTENT(IN ) :: from_SC (*) !< DATA from the supercontroller + REAL(C_FLOAT), INTENT(INOUT) :: to_SC (*) !< DATA to the supercontroller + INTEGER(C_INT), INTENT(INOUT) :: aviFAIL !< FLAG (Status set in DLL and returned to simulation code) + CHARACTER(KIND=C_CHAR), INTENT(IN) :: accINFILE (*) !< INFILE + CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcOUTNAME(*) !< OUTNAME (Simulation RootName) + CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcMSG (*) !< MESSAGE (Message from DLL to simulation code [ErrMsg]) + END SUBROUTINE BladedDLL_SC_Procedure + + FUNCTION BladedDLL_CONTROLLER_Procedure ( turbine_id ) BIND (C) ! from Bladed 4.8 API + USE, INTRINSIC :: ISO_C_Binding + +! INTEGER(C_SIZE_T), VALUE, INTENT(IN ) :: turbine_id ! pointer (address) of data from Bladed or ENFAST that is required to be used in ExternalControllerApi.dll (as written in Bladed's API) + TYPE(C_PTR), VALUE, INTENT(IN ) :: turbine_id ! pointer (address) of data from Bladed or ENFAST that is required to be used in ExternalControllerApi.dll (using standard Fortran nomenclature for ISO C BINDING) + INTEGER(C_INT) :: BladedDLL_CONTROLLER_Procedure ! an integer determining the status of the call (see aviFAIL) + + END FUNCTION BladedDLL_CONTROLLER_Procedure + + END INTERFACE + + +#ifdef STATIC_DLL_LOAD + INTERFACE + +#ifdef LOAD_SUPERCONTROLLER + SUBROUTINE DISCON ( avrSWAP, from_SC, to_SC, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) BIND(C, NAME='DISCON') +#else + SUBROUTINE DISCON ( avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) BIND(C, NAME='DISCON') +#endif + + USE, INTRINSIC :: ISO_C_Binding + + REAL(C_FLOAT), INTENT(INOUT) :: avrSWAP (*) ! DATA +#ifdef LOAD_SUPERCONTROLLER + REAL(C_FLOAT), INTENT(IN ) :: from_SC (*) ! DATA from the supercontroller + REAL(C_FLOAT), INTENT(INOUT) :: to_SC (*) ! DATA to the supercontroller +#endif + INTEGER(C_INT), INTENT(INOUT) :: aviFAIL ! FLAG (Status set in DLL and returned to simulation code) + CHARACTER(KIND=C_CHAR), INTENT(IN) :: accINFILE (*) ! INFILE + CHARACTER(KIND=C_CHAR), INTENT(IN) :: avcOUTNAME(*) ! OUTNAME (Simulation RootName) + CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcMSG (*) ! MESSAGE (Message from DLL to simulation code [ErrMsg]) + END SUBROUTINE DISCON + END INTERFACE +#endif + + + ! Some constants for the Interface: + + INTEGER(IntKi), PARAMETER :: R_v36 = 85 !< Start of below-rated torque-speed look-up table (record no.) for Bladed version 3.6 + INTEGER(IntKi), PARAMETER :: R_v4 = 145 !< Start of below-rated torque-speed look-up table (record no.) for Bladed version 3.8 - 4.2 + INTEGER(IntKi), PARAMETER :: R_v43 = 165 !< Start of below-rated torque-speed look-up table (record no.) for Bladed version 4.3 and later + + INTEGER(IntKi), PARAMETER :: R = R_v43 !< start of the generator speed look-up table +#ifdef STATIC_DLL_LOAD + INTEGER(IntKi), PARAMETER :: MaxLoggingChannels = 0 +#else + INTEGER(IntKi), PARAMETER :: MaxLoggingChannels = 300 +#endif + + !! GH_DISCON_SIMULATION_STATUS - Flag returned by simulation from GetSimulationStatus. Descriptions taken from the user manual. + INTEGER(IntKi), PARAMETER :: GH_DISCON_STATUS_FINALISING = -1 ! Final call at the end of the simulation. + INTEGER(IntKi), PARAMETER :: GH_DISCON_STATUS_INITIALISING = 0 ! First call at time zero. + INTEGER(IntKi), PARAMETER :: GH_DISCON_STATUS_DISCRETE_STEP = 1 ! Simulation discrete timestep. + INTEGER(IntKi), PARAMETER :: GH_DISCON_STATUS_CHECKPOINT = -8 ! Create a checkpoint file (extension to GH DISCON documentation) + INTEGER(IntKi), PARAMETER :: GH_DISCON_STATUS_RESTARTING = -9 ! Restart step (extension to GH DISCON documentation) + !! GH_DISCON_PITCH_CONTROL - Flag to specify whether the pitch is controlled collectively or individually. + INTEGER(IntKi), PARAMETER :: GH_DISCON_PITCH_CONTROL_COLLECTIVE = 0 ! Pitch is controlled collectively - use GetCollectivePitchAngle and SetDemandedCollectivePitchAngle. + INTEGER(IntKi), PARAMETER :: GH_DISCON_PITCH_CONTROL_INDIVIDUAL = 1 ! Pitch is controlled on each blade individually - use GetPitchAngle and SetDemandedPitchAngle. + !! GH_DISCON_YAW_CONTROL - Flag to represent whether the yaw is controlled by rate or torque. + INTEGER(IntKi), PARAMETER :: GH_DISCON_YAW_CONTROL_RATE = 0 ! Uses the yaw rate demand to control yaw. + INTEGER(IntKi), PARAMETER :: GH_DISCON_YAW_CONTROL_TORQUE = 1 ! Uses the yaw torque demand to control yaw. + +CONTAINS +!================================================================================================================================== +!> This SUBROUTINE is used to call the Bladed-style DLL. +SUBROUTINE CallBladedDLL ( u, p, dll_data, ErrStat, ErrMsg, ChannelNameUnit ) + + TYPE(SrvD_InputType), INTENT(IN ) :: u ! System inputs + TYPE(SrvD_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(BladedDLLType), TARGET, INTENT(INOUT) :: dll_data ! data type containing the inputs for the Bladed DLL interface + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + CHARACTER(*), OPTIONAL, INTENT( OUT) :: ChannelNameUnit ! OUTNAME (Simulation RootName) + + PROCEDURE(BladedDLL_CONTROLLER_Procedure), POINTER :: DLL_CONTROLLER ! The address of the CONTROLLER or CONTROLLER_INIT procedure in the Bladed DLL + INTEGER :: ProcedureIndex + INTEGER(C_INT) :: aviFAIL ! status returned from Bladed controller + TYPE(C_PTR) :: turbine_id + TYPE(BladedDLLType), POINTER :: dll_data_PTR ! pointer to data type containing the inputs for the Bladed DLL interface + + + if (p%UseLegacyInterface) then + if (present(ChannelNameUnit)) then + call CallBladedLegacyDLL ( u, p, dll_data, ErrStat, ErrMsg, ChannelNameUnit ) + else + call CallBladedLegacyDLL ( u, p, dll_data, ErrStat, ErrMsg ) + end if + else + + if ( dll_data%SimStatus == GH_DISCON_STATUS_INITIALISING ) then + ProcedureIndex = 2 ! initialization call to CONTROLLER or CONTROLLER_INIT + else + ProcedureIndex = 1 ! normal call to CONTROLLER + end if + + CALL C_F_PROCPOINTER( p%DLL_Trgt%ProcAddr(ProcedureIndex), DLL_CONTROLLER) + dll_data_PTR => dll_data + turbine_id = C_LOC(dll_data_PTR) + + aviFAIL = DLL_CONTROLLER ( turbine_id ) + + ! these values are set in the controller: + ErrStat = dll_data%ErrStat + ErrMsg = dll_data%ErrMsg + + ! but we must also check the return value from the controller function (i'd think they would be the same) + IF ( aviFAIL /= 0 ) THEN + + IF ( aviFAIL > 0 ) THEN ! warning + ErrStat = max(ErrStat,ErrID_Info) + ELSE ! error + ErrStat = ErrID_Fatal + END IF + + END IF + + IF (ErrStat /= ErrID_None) THEN + ErrMsg = trim(p%DLL_Trgt%ProcName(ProcedureIndex))//trim(ErrMsg) + END IF + + end if + + if ( dll_data%SimStatus == GH_DISCON_STATUS_FINALISING ) then + dll_data%SimStatus = GH_DISCON_STATUS_INITIALISING + else + dll_data%SimStatus = GH_DISCON_STATUS_DISCRETE_STEP + end if + +END SUBROUTINE CallBladedDLL +!================================================================================================================================== +SUBROUTINE CallBladedLegacyDLL ( u, p, dll_data, ErrStat, ErrMsg, ChannelNameUnit ) + ! Passed Variables: + TYPE(SrvD_InputType), INTENT(IN ) :: u ! System inputs + TYPE(SrvD_ParameterType), INTENT(IN ) :: p ! Parameters + TYPE(BladedDLLType), INTENT(INOUT) :: dll_data ! data type containing the avrSWAP, accINFILE, and avcOUTNAME arrays + !REAL(SiKi), INTENT(INOUT) :: avrSWAP (*) ! The swap array, used to pass data to, and receive data from, the DLL controller. + !INTEGER(B1Ki), INTENT(IN ) :: accINFILE (*) ! The address of the first record of an array of 1-byte CHARACTERs giving the name of the parameter input file, 'DISCON.IN'. + !INTEGER(B1Ki), INTENT(INOUT) :: avcOUTNAME(*) ! The address of the first record of an array of 1-byte CHARACTERS giving the simulation run name without extension. + + + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + CHARACTER(*), OPTIONAL, INTENT( OUT) :: ChannelNameUnit ! OUTNAME (Simulation RootName) + + ! Local Variables: + + INTEGER(C_INT) :: aviFAIL ! A flag used to indicate the success of this DLL call set as follows: 0 if the DLL call was successful, >0 if the DLL call was successful but cMessage should be issued as a warning messsage, <0 if the DLL call was unsuccessful or for any other reason the simulation is to be stopped at this point with cMessage as the error message. + CHARACTER(KIND=C_CHAR) :: accINFILE(LEN_TRIM(dll_data%DLL_InFile)+1) ! INFILE + CHARACTER(KIND=C_CHAR) :: avcOUTNAME(p%avcOUTNAME_LEN) ! OUTNAME (in: Simulation RootName; out: string for logging channels Name:Units;) + CHARACTER(KIND=C_CHAR) :: avcMSG(LEN(ErrMsg)+1) ! MESSAGE (Message from DLL to simulation code [ErrMsg]) + + PROCEDURE(BladedDLL_Legacy_Procedure), POINTER :: DLL_Legacy_Subroutine ! The address of the (legacy DISCON) procedure in the Bladed DLL + PROCEDURE(BladedDLL_SC_Procedure), POINTER :: DLL_SC_Subroutine ! The address of the supercontroller procedure in the Bladed DLL + + + ! initialize aviFAIL + aviFAIL = 0 ! bjj, this won't necessarially work if aviFAIL is INTENT(OUT) in DLL_Procedure()--could be undefined??? + + !Convert to C-type characters: the "C_NULL_CHAR" converts the Fortran string to a C-type string (i.e., adds //CHAR(0) to the end) + + avcOUTNAME = TRANSFER( TRIM(dll_data%RootName)//C_NULL_CHAR, avcOUTNAME ) + accINFILE = TRANSFER( TRIM(dll_data%DLL_InFile)//C_NULL_CHAR, accINFILE ) + avcMSG = TRANSFER( C_NULL_CHAR, avcMSG ) !bjj this is intent(out), so we shouldn't have to do this, but, to be safe... + +#ifdef STATIC_DLL_LOAD + + ! if we're statically loading the library (i.e., OpenFOAM), we can just call DISCON(); + ! I'll leave some options for whether the supercontroller is being used +#ifdef LOAD_SUPERCONTROLLER + CALL DISCON( dll_data%avrSWAP, u%SuperController, dll_data%SCoutput, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) +#else + CALL DISCON( dll_data%avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) +#endif + +#else + + IF ( ALLOCATED(dll_data%SCoutput) ) THEN + ! Call the DLL (first associate the address from the procedure in the DLL with the subroutine): + CALL C_F_PROCPOINTER( p%DLL_Trgt%ProcAddr(1), DLL_SC_Subroutine) + CALL DLL_SC_Subroutine ( dll_data%avrSWAP, u%SuperController, dll_data%SCoutput, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) + + ELSE + ! Call the DLL (first associate the address from the procedure in the DLL with the subroutine): + CALL C_F_PROCPOINTER( p%DLL_Trgt%ProcAddr(1), DLL_Legacy_Subroutine) + CALL DLL_Legacy_Subroutine ( dll_data%avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) + END IF + +#endif + + IF ( aviFAIL /= 0 ) THEN + + ErrMsg = TRANSFER(avcMSG,ErrMsg) !convert C character array to Fortran string + CALL RemoveNullChar( ErrMsg ) + + IF ( aviFAIL > 0 ) THEN + ErrStat = ErrID_Info + ELSE + ErrStat = ErrID_Fatal + END IF + + ELSE + ErrStat = ErrID_None + ErrMsg = '' + END IF + + IF (PRESENT(ChannelNameUnit)) THEN + ChannelNameUnit = TRANSFER(avcOUTNAME,ChannelNameUnit) !convert C character array to Fortran string + CALL RemoveNullChar( ChannelNameUnit ) + END IF + + RETURN +END SUBROUTINE CallBladedLegacyDLL +!================================================================================================================================== +!> This routine initializes variables used in the Bladed DLL interface. +SUBROUTINE BladedInterface_Init(u, p, m, y, InputFileData, InitInp, ErrStat, ErrMsg) + + TYPE(SrvD_InputType), INTENT(INOUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SrvD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Initial misc (optimization) variables + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(SrvD_InputFile), INTENT(INOUT) :: InputFileData !< Data stored in the module's input file + TYPE(SrvD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + 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 ! loop counter + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + + + ! Define all the parameters for the Bladed Interface + !IF (ALLOCATED(y%SuperController)) THEN + ! InputFileData%DLL_ProcName = 'DISCON_SC' ! The name of the procedure in the DLL that will be called. + !ELSE + ! InputFileData%DLL_ProcName = 'DISCON' ! The name of the procedure in the DLL that will be called. + !END IF + + ErrStat = ErrID_None + ErrMsg= '' + + CALL DispNVD( BladedInterface_Ver ) ! Display the version of this interface + + p%UseLegacyInterface = InputFileData%UseLegacyInterface + + m%dll_data%Ptch_Cntrl = InputFileData%Ptch_Cntrl + m%dll_data%Gain_OM = InputFileData%Gain_OM ! Optimal mode gain (Nm/(rad/s)^2) + m%dll_data%GenPwr_Dem = InputFileData%GenPwr_Dem ! Demanded power (W) + m%dll_data%GenSpd_Dem = InputFileData%GenSpd_Dem ! Demanded generator speed above rated (rad/s) + m%dll_data%GenSpd_MaxOM = InputFileData%GenSpd_MaxOM ! Optimal mode maximum speed (rad/s) + m%dll_data%GenSpd_MinOM = InputFileData%GenSpd_MinOM ! Minimum generator speed (rad/s) + m%dll_data%GenTrq_Dem = InputFileData%GenTrq_Dem ! Demanded generator torque above rated (Nm) + m%dll_data%Ptch_Max = InputFileData%Ptch_Max ! Maximum pitch angle (rad) + m%dll_data%Ptch_Min = InputFileData%Ptch_Min ! Minimum pitch angle (rad) + m%dll_data%Ptch_SetPnt = InputFileData%Ptch_SetPnt ! Below-rated pitch angle set-point (rad) + m%dll_data%PtchRate_Max = InputFileData%PtchRate_Max ! Maximum pitch rate (rad/s) + m%dll_data%PtchRate_Min = InputFileData%PtchRate_Min ! Minimum pitch rate (most negative value allowed) (rad/s) + p%NacYaw_North = InputFileData%NacYaw_North ! Reference yaw angle of the nacelle when the upwind end points due North (rad) + + m%dll_data%DLL_NumTrq = InputFileData%DLL_NumTrq ! No. of points in torque-speed look-up table: 0 = none and use the optimal mode PARAMETERs instead, nonzero = ignore the optimal mode PARAMETERs by setting Record 16 to 0.0 (-) + + m%dll_data%DLL_InFile = InputFileData%DLL_InFile + m%dll_data%RootName = p%RootName + p%avcOUTNAME_LEN = max( LEN_TRIM(m%dll_data%RootName), MaxLoggingChannels*2*(1+ChanLen) ) + 1 ! = max( size of input, size of output ) + c_null_char + + m%dll_data%DLL_DT = InputFileData%DLL_DT ! Communication interval (sec) + p%DLL_n = NINT( m%dll_data%DLL_DT / p%DT ) + IF ( .NOT. EqualRealNos( p%DLL_n * p%DT, m%dll_data%DLL_DT ) ) THEN + CALL CheckError( ErrID_Fatal, 'DLL_DT must be an integer multiple of DT.' ) + END IF + IF ( m%dll_data%DLL_DT < EPSILON( m%dll_data%DLL_DT ) ) THEN + CALL CheckError( ErrID_Fatal, 'DLL_DT must be larger than zero.' ) + END IF + + p%DLL_Ramp = InputFileData%DLL_Ramp + p%BlAlpha = exp( -TwoPi*p%DT*InputFileData%BPCutoff ) !used only for the DLL + + if (InputFileData%BPCutoff < EPSILON( InputFileData%BPCutoff )) CALL CheckError( ErrID_Fatal, 'BPCutoff must be greater than 0.') + + IF ( m%dll_data%Ptch_Cntrl /= GH_DISCON_PITCH_CONTROL_INDIVIDUAL .AND. m%dll_data%Ptch_Cntrl /= GH_DISCON_PITCH_CONTROL_COLLECTIVE ) THEN + CALL CheckError( ErrID_Fatal, 'Ptch_Cntrl must be 0 (collective) or 1 (individual).') + RETURN + END IF + m%dll_data%Yaw_Cntrl = GH_DISCON_YAW_CONTROL_RATE ! currently only available option + m%dll_data%OverrideYawRateWithTorque = .false. + + CALL AllocAry( m%dll_data%BlPitchInput, p%NumBl, 'm%dll_data%BlPitchInput', ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + + IF ( m%dll_data%DLL_NumTrq < 0_IntKi ) THEN + CALL CheckError( ErrID_Fatal, 'DLL_NumTrq must not be less than zero.') + ELSEIF ( m%dll_data%DLL_NumTrq > 0 ) THEN + m%dll_data%Gain_OM = 0.0 ! 0.0 indicates that torque-speed table look-up is selected + + CALL MOVE_ALLOC(InputFileData%GenSpd_TLU, m%dll_data%GenSpd_TLU) ! Table (array) containing DLL_NumTrq generator speeds for the torque-speed table look-up (TLU) (rad/s) + CALL MOVE_ALLOC(InputFileData%GenTrq_TLU, m%dll_data%GenTrq_TLU) ! Table (array) containing DLL_NumTrq generator torques for the torque-speed table look-up (TLU) (Nm ) + END IF + + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Set status flag and initialize avrSWAP: + m%dll_data%SimStatus = GH_DISCON_STATUS_INITIALISING + + CALL AllocAry( m%dll_data%avrSwap, R+(2*m%dll_data%DLL_NumTrq)-1 + MaxLoggingChannels, 'avrSwap', ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + m%dll_data%avrSWAP = 0.0 + + IF (ALLOCATED(y%SuperController)) THEN + CALL AllocAry( m%dll_data%SCoutput, SIZE(y%SuperController), 'm%dll_data%SuperController', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + m%dll_data%SCoutput = 0.0_SiKi + END IF + + + ! Initialize dll data stored in OtherState + m%dll_data%initialized = .FALSE. + + + +#ifdef STATIC_DLL_LOAD + ! because OpenFOAM needs the MPI task to copy the library, we're not going to dynamically load it; it needs to be loaded at runtime. + p%DLL_Trgt%FileName = '' + p%DLL_Trgt%ProcName = '' +#else + ! Define and load the DLL: + + p%DLL_Trgt%FileName = InputFileData%DLL_FileName + + if (.not. p%UseLegacyInterface) then + p%DLL_Trgt%ProcName = "" ! initialize all procedures to empty so we try to load only two + p%DLL_Trgt%ProcName(1) = "CONTROLLER" + p%DLL_Trgt%ProcName(2) = "CONTROLLER_INIT" + + CALL LoadDynamicLib ( p%DLL_Trgt, ErrStat2, ErrMsg2 ) + if (ErrStat2 > ErrID_Fatal) then ! it loaded the DLL but didn't find the INIT routine + p%DLL_Trgt%ProcName(2) = p%DLL_Trgt%ProcName(1) ! we won't call the separate controller_init routine the first time + p%DLL_Trgt%ProcAddr(2) = p%DLL_Trgt%ProcAddr(1) + elseif (ErrStat2 == ErrID_Fatal) then + CALL CheckError(ErrID_Info,'Error opening BLADED interface DLL. Checking for legacy DLL.') + CALL FreeDynamicLib( p%DLL_Trgt, ErrStat2, ErrMsg2 ) ! this doesn't do anything #ifdef STATIC_DLL_LOAD because p%DLL_Trgt is 0 (NULL) + p%UseLegacyInterface = .true. ! Bladed checks for the legacy version if it can't find the CONTROLL function in the DLL, so that's what we'll have to do, too + end if + end if + + if (p%UseLegacyInterface) then + p%DLL_Trgt%ProcName = "" ! initialize all procedures to empty so we try to load only one + p%DLL_Trgt%ProcName(1) = InputFileData%DLL_ProcName + + CALL LoadDynamicLib ( p%DLL_Trgt, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL WrScr('Using legacy Bladed DLL interface.') + end if + + +!-------------------------------------- + p%NumOuts_DLL = 0 +#ifdef LOAD_DLL_TWICE_FOR_LOGGING_CHANNELS + CALL GetBladedLoggingChannels(u,p,m, ErrStat2, ErrMsg2) ! this calls the DLL, but we don't have the correct inputs for a time step, so we'll close the DLL and start it again + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! close and reload library here... + ! (if the DLL could be guaranteed to not do anything with the + ! inputs on the initial step, we could avoid this this part) + + CALL BladedInterface_End(u, p, m, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL LoadDynamicLib ( p%DLL_Trgt, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN +#endif + +!-------------------------------------- +#endif + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( ErrStat /= ErrID_None ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'BladedInterface_Init:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + p%UseBladedInterface = .FALSE. + END IF + + END IF + + + END SUBROUTINE CheckError +END SUBROUTINE BladedInterface_Init +!================================================================================================================================== +SUBROUTINE GetBladedLoggingChannels(u,p,m, ErrStat, ErrMsg) + + TYPE(SrvD_InputType), INTENT(IN ) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SrvD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Initial misc (optimization) variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! local variables + + INTEGER(IntKi) :: StartIndx ! starting index used to parse name/unit from Bladed DLL + INTEGER(IntKi) :: Indx ! index used to parse name/unit from Bladed DLL + INTEGER(IntKi) :: i ! The error status code + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER( p%avcOUTNAME_LEN ) :: LoggingChannelStr ! The error message, if an error occurred + CHARACTER(*), PARAMETER :: RoutineName = "GetBladedLoggingChannels" + + + CALL Fill_CONTROL_vars( 0.0_DbKi, u, p, LEN(ErrMsg), m%dll_data ) + + if (p%UseLegacyInterface) then + + CALL CallBladedDLL(u, p, m%dll_data, ErrStat, ErrMsg, LoggingChannelStr) + IF ( ErrStat >= AbortErrLev ) RETURN + + p%NumOuts_DLL = NINT( m%dll_data%avrSWAP(65) ) ! number of channels returned for logging + + ALLOCATE ( m%dll_data%LogChannels_OutParam(p%NumOuts_DLL) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the Bladed DLL logging channels name array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ALLOCATE( m%dll_data%LogChannels(p%NumOuts_DLL), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the Bladed DLL logging channels array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! get names and units of channels + do i=1,p%NumOuts_DLL + m%dll_data%LogChannels_OutParam(i)%Indx = 0 + m%dll_data%LogChannels_OutParam(i)%SignM = 1 + m%dll_data%LogChannels_OutParam(i)%Name = "LogChan"//trim(num2lstr(i)) + m%dll_data%LogChannels_OutParam(i)%Units = "Unknown" + end do + + StartIndx = 1 + do i=1,p%NumOuts_DLL + + ! parse the channel name + indx = StartIndx + INDEX( LoggingChannelStr(StartIndx:), ':' ) - 1 + if (indx > len(LoggingChannelStr) .or. indx < 1) then + call SetErrStat( ErrID_Severe,"Error getting logging channel name.", ErrStat, ErrMsg, RoutineName ) + endif + + m%dll_data%LogChannels_OutParam(I)%Name = LoggingChannelStr(StartIndx:indx-1) + StartIndx = indx + 1 + + ! parse the channel units + indx = StartIndx + INDEX( LoggingChannelStr(StartIndx:), ';' ) - 1 + if (indx > len(LoggingChannelStr) .or. indx < 1) then + call SetErrStat( ErrID_Severe,"Error getting logging channel units.", ErrStat, ErrMsg, RoutineName ) + endif + + m%dll_data%LogChannels_OutParam(I)%Units = LoggingChannelStr(StartIndx:indx-1) + StartIndx = indx + 1 + end do + + !todo: make sure trim(m%dll_data%LogChannels_OutParam(i)%Name) does not contain spaces; replace with '_' if necessary + + else + + + ALLOCATE( m%dll_data%LogChannels( MaxLoggingChannels), & + m%dll_data%LogChannels_OutParam(MaxLoggingChannels), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the Bladed DLL logging channels.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + CALL CallBladedDLL(u, p, m%dll_data, ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + + p%NumOuts_DLL = m%dll_data%NumLogChannels ! set this as a parameter in case the DLL changes the value during the simulation + + end if + + + ! convert Bladed-allowed unit specifiers to actual units + do i=1,p%NumOuts_DLL + select case (m%dll_data%LogChannels_OutParam(I)%Units) + case('1/T') + m%dll_data%LogChannels_OutParam(I)%Units = 'Hz' + case('A') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad' + case('A/P') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad/W' + case('A/PT') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad/Ws' + case('A/PTT') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad/Ws^2' + case('A/T') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad/s' + case('A/TT') + m%dll_data%LogChannels_OutParam(I)%Units = 'rad/s^2' + case('F') + m%dll_data%LogChannels_OutParam(I)%Units = 'N' + case('F/L') + m%dll_data%LogChannels_OutParam(I)%Units = 'N/m' + case('F/LL') + m%dll_data%LogChannels_OutParam(I)%Units = 'N/m^2' + case('FL') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nm' + case('FL/A') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nm/rad' + case('FL/L') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nm/m' + case('FLL') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nm^2' + case('FLT/A') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nms/rad' + case('FLTT/AA') + m%dll_data%LogChannels_OutParam(I)%Units = 'Nms^2/rad^2' + case('I') + m%dll_data%LogChannels_OutParam(I)%Units = 'A' + case('L') + m%dll_data%LogChannels_OutParam(I)%Units = 'm' + case('L/T') + m%dll_data%LogChannels_OutParam(I)%Units = 'm/s' + case('L/TT') + m%dll_data%LogChannels_OutParam(I)%Units = 'm/s^2' + case('LLL') + m%dll_data%LogChannels_OutParam(I)%Units = 'm^3' + case('LLL/A') + m%dll_data%LogChannels_OutParam(I)%Units = 'm^3/rad' + case('M') + m%dll_data%LogChannels_OutParam(I)%Units = 'kg' + case('M/L') + m%dll_data%LogChannels_OutParam(I)%Units = 'kg/m' + case('M/LLL') + m%dll_data%LogChannels_OutParam(I)%Units = 'kg/m^3' + case('M/LT') + m%dll_data%LogChannels_OutParam(I)%Units = 'kg/ms' + case('MLL') + m%dll_data%LogChannels_OutParam(I)%Units = 'kgm^2' + case('N') + m%dll_data%LogChannels_OutParam(I)%Units = '-' + case('P') + m%dll_data%LogChannels_OutParam(I)%Units = 'W' + case('PT') + m%dll_data%LogChannels_OutParam(I)%Units = 'J' + case('Q') + m%dll_data%LogChannels_OutParam(I)%Units = 'VAr' + case('T') + m%dll_data%LogChannels_OutParam(I)%Units = 's' + case('VI') + m%dll_data%LogChannels_OutParam(I)%Units = 'VA' + end select + + end do + +END SUBROUTINE GetBladedLoggingChannels +!================================================================================================================================== + +!> This routine calls the DLL for the final time (if it was previously called), and frees the dynamic library. +SUBROUTINE BladedInterface_End(u, p, m, ErrStat, ErrMsg) + + TYPE(SrvD_InputType), INTENT(IN ) :: u !< System inputs + TYPE(SrvD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SrvD_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 + + ! local variables: + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + + ! call DLL final time, but skip if we've never called it + if (allocated(m%dll_data%avrSWAP)) then + IF ( m%dll_data%SimStatus /= GH_DISCON_STATUS_INITIALISING ) THEN + m%dll_data%SimStatus = GH_DISCON_STATUS_FINALISING + m%dll_data%avrSWAP(1) = m%dll_data%SimStatus ! we aren't calling fill_avrSWAP, so set this manually + CALL CallBladedDLL(u, p, m%dll_data, ErrStat, ErrMsg) + END IF + end if + + CALL FreeDynamicLib( p%DLL_Trgt, ErrStat2, ErrMsg2 ) ! this doesn't do anything #ifdef STATIC_DLL_LOAD because p%DLL_Trgt is 0 (NULL) + IF (ErrStat2 /= ErrID_None) THEN + ErrStat = MAX(ErrStat, ErrStat2) + ErrMsg = TRIM(ErrMsg)//NewLine//TRIM(ErrMsg2) + END IF + +END SUBROUTINE BladedInterface_End +!================================================================================================================================== +!> This routine sets the AVRswap array, calls the routine from the BladedDLL, and sets the outputs from the call to be used as +!! necessary in the main ServoDyn CalcOutput routine. +SUBROUTINE BladedInterface_CalcOutput(t, u, p, m, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_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 + + ! local variables: + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + character(*), parameter :: RoutineName = 'BladedInterface_CalcOutput' + + ! Initialize error values: + ErrStat = ErrID_None + ErrMsg= '' + + + ! Set the input values of the avrSWAP array: + CALL Fill_CONTROL_vars( t, u, p, LEN(ErrMsg), m%dll_data ) + + +#ifdef DEBUG_BLADED_INTERFACE +!CALL WrNumAryFileNR ( 58, (/t/),'1x,ES15.6E2', ErrStat2, ErrMsg2 ) +CALL WrNumAryFileNR ( 58, m%dll_data%avrSWAP,'1x,ES15.6E2', ErrStat2, ErrMsg2 ) +write(58,'()') +#endif + + ! Call the Bladed-style DLL controller: + CALL CallBladedDLL(u, p, m%dll_data, ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + +#ifdef DEBUG_BLADED_INTERFACE +!CALL WrNumAryFileNR ( 59, (/t/),'1x,ES15.6E2', ErrStat2, ErrMsg2 ) +CALL WrNumAryFileNR ( 59, m%dll_data%avrSWAP,'1x,ES15.6E2', ErrStat2, ErrMsg2 ) +write(59,'()') +#endif + + ! Get the output values from the avrSWAP array: + + CALL CheckDLLReturnValues( p, m%dll_data, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +END SUBROUTINE BladedInterface_CalcOutput +!================================================================================================================================== +!> This routine fills the avrSWAP array with its inputs, as described in Appendices A and B of the Bladed User Manual of Bladed +!! version 3.81. +SUBROUTINE Fill_avrSWAP( t, u, p, ErrMsgSz, dll_data ) +!SUBROUTINE Fill_avrSWAP( StatFlag, t, u, p, ErrMsgSz, dll_data ) +!.................................................................................................................................. + +! INTEGER(IntKi), INTENT(IN ) :: StatFlag ! Status flag set as follows: 0 if this is the first call, 1 for all subsequent time steps, -1 if this is the final call at the end of the simulation (-) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ErrMsgSz !< Allowed size of the DLL-returned error message (-) + TYPE(BladedDLLType), INTENT(INOUT) :: dll_data !< data for the Bladed DLL + + ! local variables: + INTEGER(IntKi) :: I ! Loop counter + + !> The following are values ServoDyn sends to the Bladed DLL. + !! For variables returned from the DLL, see bladedinterface::retrieve_avrswap. + dll_data%avrSWAP( 1) = dll_data%SimStatus + !> * Record 1: Status flag set as follows: 0 if this is the first call, 1 for all subsequent time steps, -1 if this is the final call at the end of the simulation (-) + dll_data%avrSWAP( 2) = REAL(t, SiKi) !> * Record 2: Current time (sec) [t in single precision] + dll_data%avrSWAP( 3) = dll_data%DLL_DT !> * Record 3: Communication interval (sec) [in FAST v7 this was \f$ y\_SrvD\%AllOuts(Time) - LastTime \f$, but is now the SrvD DLL_DT parameter] + dll_data%avrSWAP( 4) = u%BlPitch(1) !> * Record 4: Blade 1 pitch angle (rad) [SrvD input] + dll_data%avrSWAP( 5) = dll_data%Ptch_SetPnt !> * Record 5: Below-rated pitch angle set-point (rad) [SrvD Ptch_SetPnt parameter] + dll_data%avrSWAP( 6) = dll_data%Ptch_Min !> * Record 6: Minimum pitch angle (rad) [SrvD Ptch_Min parameter] + dll_data%avrSWAP( 7) = dll_data%Ptch_Max !> * Record 7: Maximum pitch angle (rad) [SrvD Ptch_Max parameter] + dll_data%avrSWAP( 8) = dll_data%PtchRate_Min !> * Record 8: Minimum pitch rate (most negative value allowed) (rad/s) [SrvD PtchRate_Min parameter] + dll_data%avrSWAP( 9) = dll_data%PtchRate_Max !> * Record 9: Maximum pitch rate (rad/s) [SrvD PtchRate_Max parameter] + dll_data%avrSWAP(10) = 0.0 !> * Record 10: 0 = pitch position actuator, 1 = pitch rate actuator (-) [must be 0 for ServoDyn] + dll_data%avrSWAP(11) = dll_data%BlPitchCom(1) !> * Record 11: Current demanded pitch angle (rad) [I am sending the previous value for blade 1 from the DLL, in the absence of any more information provided in Bladed documentation] + dll_data%avrSWAP(12) = 0.0 !> * Record 12: Current demanded pitch rate (rad/s) [always zero for ServoDyn] + dll_data%avrSWAP(13) = dll_data%GenPwr_Dem !> * Record 13: Demanded power (W) [SrvD GenPwr_Dem parameter from input file] + dll_data%avrSWAP(14) = u%RotPwr !> * Record 14: Measured shaft power (W) [SrvD input] + dll_data%avrSWAP(15) = dll_data%ElecPwr_prev !> * Record 15: Measured electrical power output (W) [SrvD calculation from previous step; should technically be a state] + dll_data%avrSWAP(16) = dll_data%Gain_OM !> * Record 16: Optimal mode gain (Nm/(rad/s)^2) [if torque-speed table look-up not selected in input file, use SrvD Gain_OM parameter, otherwise use 0 (already overwritten in Init routine)] + dll_data%avrSWAP(17) = dll_data%GenSpd_MinOM !> * Record 17: Minimum generator speed (rad/s) [SrvD GenSpd_MinOM parameter] + dll_data%avrSWAP(18) = dll_data%GenSpd_MaxOM !> * Record 18: Optimal mode maximum speed (rad/s) [SrvD GenSpd_MaxOMp arameter] + dll_data%avrSWAP(19) = dll_data%GenSpd_Dem !> * Record 19: Demanded generator speed above rated (rad/s) [SrvD GenSpd_Dem parameter] + dll_data%avrSWAP(20) = u%HSS_Spd !> * Record 20: Measured generator speed (rad/s) [SrvD input] + dll_data%avrSWAP(21) = u%RotSpeed !> * Record 21: Measured rotor speed (rad/s) [SrvD input] + dll_data%avrSWAP(22) = dll_data%GenTrq_Dem !> * Record 22: Demanded generator torque above rated (Nm) [SrvD GenTrq_Dem parameter from input file] +!bjj: this assumes it is the value at the previous step; but we actually want the output GenTrq... + dll_data%avrSWAP(23) = dll_data%GenTrq_prev !> * Record 23: Measured generator torque (Nm) [SrvD calculation from previous step; should technically be a state] + dll_data%avrSWAP(24) = u%YawErr !> * Record 24: Measured yaw error (rad) [SrvD input] + IF ( dll_data%DLL_NumTrq == 0 ) THEN ! Torque-speed table look-up not selected + dll_data%avrSWAP(25) = 0.0 ! Start of below-rated torque-speed look-up table (record no.) -- 0.0 indicates that torque-speed table look-up is not selected + ELSE ! Torque-speed table look-up selected + dll_data%avrSWAP(25) = R !> * Record 25: Start of below-rated torque-speed look-up table (record no.) [parameter \f$R\f$ (bladedinterface::r) or 0 if DLL_NumTrq == 0] + ENDIF + dll_data%avrSWAP(26) = dll_data%DLL_NumTrq !> * Record 26: No. of points in torque-speed look-up table (-) [SrvD DLL_NumTrq parameter] + dll_data%avrSWAP(27) = u%HorWindV !> * Record 27: Hub wind speed (m/s) [SrvD input] + dll_data%avrSWAP(28) = dll_data%Ptch_Cntrl !> * Record 28: Pitch control: 0 = collective, 1 = individual (-) [SrvD Ptch_Cntrl parameter] + dll_data%avrSWAP(29) = dll_data%Yaw_Cntrl !> * Record 29: Yaw control: 0 = yaw rate control, 1 = yaw torque control (-) [must be 0 for ServoDyn] + !^^^ bjj: maybe torque control can be used in ServoDyn? can we specifiy yaw torque control? + dll_data%avrSWAP(30) = u%RootMyc(1) !> * Record 30: Blade 1 root out-of-plane bending moment (Nm) [SrvD input] + dll_data%avrSWAP(31) = u%RootMyc(2) !> * Record 31: Blade 2 root out-of-plane bending moment (Nm) [SrvD input] + dll_data%avrSWAP(32) = u%RootMyc(3) !> * Record 32: Blade 3 root out-of-plane bending moment (Nm) [SrvD input] +IF ( p%NumBl > 1 ) THEN + dll_data%avrSWAP(33) = u%BlPitch(2) !> * Record 33: Blade 2 pitch angle (rad) [SrvD input] +END IF +IF ( p%NumBl > 2 ) THEN + dll_data%avrSWAP(34) = u%BlPitch(3) !> * Record 34: Blade 3 pitch angle (rad) [SrvD input] +! dll_data%avrSWAP(34) = u%BlPitch(3) !> * Record 34: Blade 3 pitch angle (rad) [SrvD input] +END IF + dll_data%avrSWAP(35) = dll_data%GenState !> * Record 35: Generator contactor (-) [GenState from previous call to DLL (initialized to 1)] +! record 36 is initialized to 0 (brake off); then we will keep the brake status set in previous call to DLL +! dll_data%avrSWAP(36) = dll_data%HSSBrFrac !> * Record 36: Shaft brake status: 0 = off, 1 = on (full), 16 = Get brake torque from record 107 (-) [HSSBrFrac from previous call to DLL (initialized to 0)] + dll_data%avrSWAP(37) = u%YawAngle - p%NacYaw_North !> * Record 37: Nacelle yaw angle from North (rad) [ \f$ u\%YawAngle - p\%NacYaw\_North \f$ ] +! Records 38-48 are outputs [see Retrieve_avrSWAP()] + dll_data%avrSWAP(49) = ErrMsgSz + 1 !> * Record 49: Maximum number of characters in the "MESSAGE" argument (-) [size of ErrMsg argument plus 1 (we add one for the C NULL CHARACTER)] + dll_data%avrSWAP(50) = LEN_TRIM(dll_data%DLL_InFile) +1 !> * Record 50: Number of characters in the "INFILE" argument (-) [trimmed length of DLL_InFile parameter plus 1 (we add one for the C NULL CHARACTER)] + dll_data%avrSWAP(51) = LEN_TRIM(dll_data%RootName) +1 !> * Record 51: Number of characters in the "OUTNAME" argument (-) [trimmed length of RootName parameter plus 1 (we add one for the C NULL CHARACTER)] +! Record 52 is reserved for future use ! DLL interface version number (-) + dll_data%avrSWAP(53) = u%YawBrTAxp !> * Record 53: Tower top fore-aft acceleration (m/s^2) [SrvD input] + dll_data%avrSWAP(54) = u%YawBrTAyp !> * Record 54: Tower top side-to-side acceleration (m/s^2) [SrvD input] +! Records 55-59 are outputs [see Retrieve_avrSWAP()] + dll_data%avrSWAP(60) = u%LSSTipPxa !> * Record 60: Rotor azimuth angle (rad) [SrvD input] + dll_data%avrSWAP(61) = p%NumBl !> * Record 61: Number of blades (-) [SrvD NumBl parameter] + dll_data%avrSWAP(62) = MaxLoggingChannels !> * Record 62: Maximum number of values which can be returned for logging (-) [set to parameter bladedinterface::maxloggingchannels] + dll_data%avrSWAP(63) = R + (2*dll_data%DLL_NumTrq) !> * Record 63: Record number for start of logging output (-) [set to R + (2*p\%DLL_NumTrq)] + dll_data%avrSWAP(64) = p%avcOUTNAME_LEN !> * Record 64: Maximum number of characters which can be returned in "OUTNAME" (-) [set to bladedinterface::MaxLoggingChannels * (2+nwtc_base::chanlen) + 1 (we add one for the C NULL CHARACTER)] +! Record 65 is output [see Retrieve_avrSWAP()] +! Records 66-68 are reserved + + dll_data%avrSWAP(69) = u%RootMxc(1) !> * Record 69: Blade 1 root in-plane bending moment (Nm) [SrvD input] + dll_data%avrSWAP(70) = u%RootMxc(2) !> * Record 70: Blade 2 root in-plane bending moment (Nm) [SrvD input] + dll_data%avrSWAP(71) = u%RootMxc(3) !> * Record 71: Blade 3 root in-plane bending moment (Nm) [SrvD input] +! Record 72 is output [see Retrieve_avrSWAP()] + dll_data%avrSWAP(73) = u%LSSTipMya !> * Record 73: Rotating hub My (GL co-ords) (Nm) [SrvD input] + dll_data%avrSWAP(74) = u%LSSTipMza !> * Record 74: Rotating hub Mz (GL co-ords) (Nm) [SrvD input] + dll_data%avrSWAP(75) = u%LSSTipMys !> * Record 75: Fixed hub My (GL co-ords) (Nm) [SrvD input] + dll_data%avrSWAP(76) = u%LSSTipMzs !> * Record 76: Fixed hub Mz (GL co-ords) (Nm) [SrvD input] + dll_data%avrSWAP(77) = u%YawBrMyn !> * Record 77: Yaw bearing My (GL co-ords) (Nm) [SrvD input] + dll_data%avrSWAP(78) = u%YawBrMzn !> * Record 78: Yaw bearing Mz (GL co-ords) (Nm) [SrvD input] +! Records 79-80 are outputs [see Retrieve_avrSWAP()] +! Record 81 is the variable slip current demand; both input and output [see Retrieve_avrSWAP()] + ! variable slip current demand is ignored; instead, the generator torque demand from Record 47 is used + dll_data%avrSWAP(82) = u%NcIMURAxs !> * Record 82: Nacelle roll acceleration (rad/s^2) [SrvD input] -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + dll_data%avrSWAP(83) = u%NcIMURAys !> * Record 83: Nacelle nodding acceleration (rad/s^2) [SrvD input] + dll_data%avrSWAP(84) = u%NcIMURAzs !> * Record 84: Nacelle yaw acceleration (rad/s^2) [SrvD input] -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + + + +! Records 92-94 are outputs [see Retrieve_avrSWAP()] + + ! these two "inputs" are actually customizations for a particular DLL + dll_data%avrSWAP(95) = p%AirDens !> * Record 95: Reserved (SrvD customization: set to SrvD AirDens parameter) + dll_data%avrSWAP(96) = p%AvgWindSpeed !> * Record 96: Reserved (SrvD customization: set to SrvD AvgWindSpeed parameter) + +! Record 98 is output [see Retrieve_avrSWAP()] + dll_data%avrSWAP(98) = 0 !> * Record 98: set to 0 + +! Records 102-104 are outputs [see Retrieve_avrSWAP()] +! Records 107-108 are outputs [see Retrieve_avrSWAP()] + + dll_data%avrSWAP(109) = u%LSSTipMxa ! or u%LSShftMxs !> * Record 109: Shaft torque (=hub Mx for clockwise rotor) (Nm) [SrvD input] + dll_data%avrSWAP(117) = 0 !> * Record 117: Controller state [always set to 0] + + !> * Records \f$R\f$ through \f$R + 2*DLL\_NumTrq - 1\f$: torque-speed look-up table elements. + DO I = 1,dll_data%DLL_NumTrq ! Loop through all torque-speed look-up table elements + dll_data%avrSWAP( R + (2*I) - 2 ) = dll_data%GenSpd_TLU(I) !> + Records \f$R, R+2, R+4, \dots, R + 2*DLL\_NumTrq - 2\f$: Generator speed look-up table elements (rad/s) + dll_data%avrSWAP( R + (2*I) - 1 ) = dll_data%GenTrq_TLU(I) !> + Records \f$R+1, R+3, R+5, \dots, R + 2*DLL\_NumTrq - 1\f$: Generator torque look-up table elements (Nm) + ENDDO + + +!> * Records 120-129: User-defined variables 1-10; ignored in ServoDyn +! Records 130-142 are outputs [see Retrieve_avrSWAP()] +! Records L1 and onward are outputs [see Retrieve_avrSWAP()] + + + + RETURN + +END SUBROUTINE Fill_avrSWAP +!================================================================================================================================== +!> This routine fills the dll_data variables that are used in the non-legacy version of the Bladed DLL interface with inputs, +!! as described in Appendices A and B of the Bladed User Manual of Bladed version 4.8. +SUBROUTINE Fill_CONTROL_vars( t, u, p, ErrMsgSz, dll_data ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ErrMsgSz !< Allowed size of the DLL-returned error message (-) +! REAL(SiKi), INTENT(INOUT) :: avrSWAP(:) ! the SWAP array for the Bladed DLL Interface + TYPE(BladedDLLType), INTENT(INOUT) :: dll_data !< data for the Bladed DLL + + ! local variables: + INTEGER(IntKi) :: i ! Loop counter + INTEGER(IntKi) :: j ! Loop counter + + if (dll_data%SimStatus == GH_DISCON_STATUS_INITIALISING) then + dll_data%avrSWAP = 0.0 + dll_data%NumLogChannels = 0 + + dll_data%GenState = 1 + dll_data%GenTrq = 0.0 + dll_data%YawRateCom = 0.0 + dll_data%HSSBrTrqDemand = 0.0 + dll_data%ShaftBrakeStatusBinaryFlag = 0 ! no brakes deployed + dll_data%HSSBrDeployed = .false. + + dll_data%PrevBlPitch(1:p%NumBl) = p%BlPitchInit + dll_data%BlPitchCom(1:p%NumBl) = p%BlPitchInit + end if + + call Fill_avrSWAP( t, u, p, ErrMsgSz, dll_data ) ! we'll set the avrSWAP variable, for the legacy version of the DLL, too. + + !> The following are values ServoDyn sends to the Bladed DLL. + !! For variables returned from the DLL, see bladedinterface::retrieve_control_vars. + + dll_data%ErrMsg = '' + dll_data%ErrStat = ErrID_None + dll_data%OverrideYawRateWithTorque = .false. + + dll_data%CurrentTime = t ! Current time (sec) + dll_data%BlPitchInput(1:p%NumBl) = u%BlPitch(1:p%NumBl) ! current blade pitch (input) + dll_data%YawAngleFromNorth = u%YawAngle - p%NacYaw_North ! Nacelle yaw angle from North (rad) + dll_data%HorWindV = u%HorWindV ! Hub wind speed (m/s) + dll_data%HSS_Spd = u%HSS_Spd ! Measured generator speed (rad/s) + dll_data%YawErr = u%YawErr ! Measured yaw error (rad) + dll_data%RotSpeed = u%RotSpeed ! Measured rotor speed (rad/s) + dll_data%YawBrTAxp = u%YawBrTAxp ! Tower top fore-aft acceleration (m/s^2) + dll_data%YawBrTAyp = u%YawBrTAyp ! Tower top side-to-side acceleration (m/s^2) + dll_data%LSSTipMys = u%LSSTipMys ! Fixed hub My (GL co-ords) (Nm) + dll_data%LSSTipMzs = u%LSSTipMzs ! Fixed hub Mz (GL co-ords) (Nm) + dll_data%LSSTipPxa = u%LSSTipPxa ! Rotor azimuth angle (rad) + dll_data%Yaw = u%Yaw ! Current nacelle yaw (angular position) (rad) NEW TO DLL!!! + dll_data%YawRate = u%YawRate ! Current nacelle yaw rate (angular velocity) (rad/s) NEW TO DLL!!! + dll_data%LSSTipMya = u%LSSTipMya ! Rotating hub My (GL co-ords) (Nm) + dll_data%LSSTipMza = u%LSSTipMza ! Rotating hub Mz (GL co-ords) (Nm) + dll_data%YawBrMyn = u%YawBrMyn ! Yaw bearing My (GL co-ords) (Nm) + dll_data%YawBrMzn = u%YawBrMzn ! Yaw bearing Mz (GL co-ords) (Nm) + dll_data%RotPwr = u%RotPwr ! Measured shaft power (W) [SrvD input] + dll_data%NcIMURAxs = u%NcIMURAxs ! Nacelle roll acceleration (rad/s^2) -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + dll_data%NcIMURAys = u%NcIMURAys ! Nacelle nodding acceleration (rad/s^2) + dll_data%NcIMURAzs = u%NcIMURAzs ! Nacelle yaw acceleration (rad/s^2) -- this is in the shaft (tilted) coordinate system, instead of the nacelle (nontilted) coordinate system + dll_data%LSSTipMxa = u%LSSTipMxa ! Shaft torque (=hub Mx for clockwise rotor) (Nm) + dll_data%RootMyc = u%RootMyc ! Blade root out-of-plane bending moment (Nm) [SrvD input] + dll_data%RootMxc = u%RootMxc ! Blade root in-plane bending moment (Nm) [SrvD input] + +END SUBROUTINE Fill_CONTROL_vars +!================================================================================================================================== +!> This routine retrieves the DLL return values from the avrSWAP array, as described in Appendices A and B of the Bladed User +!! Manual of Bladed version 3.81. +SUBROUTINE Retrieve_avrSWAP( p, dll_data, ErrStat, ErrMsg ) +!SUBROUTINE Retrieve_avrSWAP( p, dll_data ) +!.................................................................................................................................. + + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BladedDLLType), INTENT(INOUT) :: dll_data !< data for the Bladed DLL + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables: + INTEGER(IntKi) :: K ! Loop counter + CHARACTER(*), PARAMETER :: RoutineName = 'Retrieve_avrSWAP' + + + ! Initialize ErrStat and ErrMsg + ErrStat = ErrID_None + ErrMsg = '' + + !> The following are values the Bladed DLL sends to ServoDyn. Whether or not ServoDyn uses the values in CalcOutput (servodyn::srvd_calcoutput) + !! and/or UpdateStates (servodyn::srvd_updatestates) is determined by other parameters set in the ServoDyn input file. + !! For variables sent to the DLL, see bladedinterface::fill_avrswap. + + + !! Load control demands (commands) out of the avrSWAP array according to + !! Appendix A of the Bladed User Manual: + +!> * Record 35: Generator contactor (-) [sent to DLL at the next call] + dll_data%GenState = NINT( dll_data%avrSWAP(35) ) ! Generator contactor (-) + + +!> * Record 36: Shaft brake status (-) [sent to DLL at the next call; anything other than 0 or 1 is an error] + !dll_data%HSSBrFrac = dll_data%avrSWAP(36) ! Shaft brake status (-) + dll_data%ShaftBrakeStatusBinaryFlag = NINT(dll_data%avrSWAP(36)) + +!! Records 38-40 are reserved +!> * Record 41: demanded yaw actuator torque [this output is ignored since record 29 is set to 0 by ServoDyn indicating yaw rate control] + dll_data%YawTorqueDemand = dll_data%avrSWAP(41) + +! Records 42-46: demanded pitch positions or rates + IF ( dll_data%Ptch_Cntrl == GH_DISCON_PITCH_CONTROL_INDIVIDUAL ) THEN ! Individual pitch control (p%Ptch_Cntrl == 1) +!> * Records 42-44: Demanded Individual Pitch position (rad) (or pitch rate [rad/s]) + DO K = 1,p%NumBl ! Loop through all blades avrSWAP(42), avrSWAP(43), and, if NumBl = 3, avrSWAP(44) + dll_data%BlPitchCom(K) = dll_data%avrSWAP( 41 + K ) ! Demanded individual pitch position of blade K (rad) + ENDDO ! K - blades + + ELSE !IF ( p%Ptch_Cntrl == GH_DISCON_PITCH_CONTROL_COLLECTIVE ) THEN ! Collective pitch control +!> * Record 45: Demanded pitch angle (Collective pitch) (rad) + dll_data%BlPitchCom = dll_data%avrSWAP(45) ! Demanded pitch angle (Collective pitch) (rad) + +!> * Record 46, demanded pitch rate (Collective pitch), is ingored since record 10 is set to 0 by ServoDyn indicating pitch position actuator + + ENDIF + + dll_data%GenTrq = dll_data%avrSWAP(47) !> * Record 47: Demanded generator torque (Nm) + dll_data%YawRateCom = dll_data%avrSWAP(48) !> * Record 48: Demanded nacelle yaw rate (rad/s) + + +!> * Record 55: Pitch override [anything other than 0 is an error in ServoDyn] + IF ( NINT( dll_data%avrSWAP(55) ) /= 0 ) THEN + ! Pitch override requested by DLL; abort program + CALL SetErrStat( ErrID_Severe, 'Built-in pitch override unsupported. Set avrSWAP(55) to 0 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + + END IF + + +!> * Record 56: Torque override + IF ( NINT( dll_data%avrSWAP(56) ) /= 0 ) THEN + ! Torque override requested by DLL; abort program + CALL SetErrStat( ErrID_Severe, 'Built-in torque override unsupported. Set avrSWAP(56) to 0 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + + END IF + + +!! Records 57-59 are reserved + +!> * Record 65: Number of variables returned for logging [anything greater than MaxLoggingChannels is an error] + IF ( NINT( dll_data%avrSWAP(65) ) > MaxLoggingChannels ) THEN + + ! Return variables for logging requested by DLL; abort program + CALL SetErrStat( ErrID_Fatal, 'Return variables exceed maximum number allowed. Set avrSWAP(65) to a number no larger than '// & + trim(num2lstr(MaxLoggingChannels))//' in '//TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + + ENDIF + +!> * Record 72, the generator start-up resistance, is ignored +!> * Record 79, the request for loads, is ignored; instead, the blade, hub, and yaw bearing loads are always passed to the DLL as if Record 79 was set to 4 +!> * Records 80-81, the variable-slip current demand inputs, are ignored; instead, the generator torque demand from Record 47 is used + + +!> * Records 92-94: allow the control to change the wind inflow input; NOT ALLOWED in ServoDyn +!> * Record 98: Safety system number to activate; not used in ServoDyn + +!> * Records 102-104: Yaw control/stiffness/damping; ignored in ServoDyn + if (dll_data%avrSWAP(102)==4) then + dll_data%OverrideYawRateWithTorque = .true. + elseif (dll_data%avrSWAP(102)==0) then + dll_data%OverrideYawRateWithTorque = .false. + else + dll_data%OverrideYawRateWithTorque = .false. + CALL SetErrStat( ErrID_Severe, 'Invalid yaw control flag. Set avrSWAP(102) to 0 or 4 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + end if + +!> * Record 107: Brake torque demand (used only when avrSWAP(36) is 16) + if (dll_data%ShaftBrakeStatusBinaryFlag == 16) then + dll_data%HSSBrTrqDemand = dll_data%avrSWAP(107) + end if + +!> * Record 108: Yaw brake torque demand; ignored in ServoDyn + +!> * Records 120-129: User-defined variables 1-10; ignored in ServoDyn + ! Commanded Airfoil UserProp for blade (must be same units as given in AD15 airfoil tables) + ! This is passed to AD15 to be interpolated with the airfoil table userprop column + ! (might be used for airfoil flap angles for example) + dll_data%BlAirfoilCom(1) = dll_data%avrSWAP(120) + dll_data%BlAirfoilCom(2) = dll_data%avrSWAP(121) + dll_data%BlAirFoilCom(3) = dll_data%avrSWAP(122) + +!> * Records 130-142: Reserved + +!> * L1: variables for logging output; + + do k=1,p%NumOuts_DLL + dll_data%LogChannels(k) = dll_data%avrSWAP( NINT(dll_data%avrSWAP(63))+k-1 ) + end do + + +END SUBROUTINE Retrieve_avrSWAP +!================================================================================================================================== +!> This routine checks that the values returned to FAST from the controller DLL (from either version of the interface) are valid +SUBROUTINE CheckDLLReturnValues( p, dll_data, ErrStat, ErrMsg ) + + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(BladedDLLType), INTENT(INOUT) :: dll_data !< data for the Bladed DLL + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'CheckDLLReturnValues' + + ! Initialize ErrStat and ErrMsg + ErrStat = ErrID_None + ErrMsg = '' + + if (p%UseLegacyInterface) then + CALL Retrieve_avrSWAP( p, dll_data, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + end if + + + IF ( ( dll_data%GenState /= 0_IntKi ) .AND. ( dll_data%GenState /= 1_IntKi ) ) THEN + ! Generator contactor indicates something other than off or main; abort program + if (p%UseLegacyInterface) then + CALL SetErrStat( ErrID_Fatal, 'Only off and main generators supported. Set avrSWAP(35) to 0 or 1 in '//TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + else + CALL SetErrStat( ErrID_Fatal, 'Only off and main generators supported. Call SetGeneratorContactor() with generator_contactor set to 0 or 1 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + end if + END IF + + + SELECT CASE (dll_data%ShaftBrakeStatusBinaryFlag) + CASE (0) + dll_data%HSSBrTrqDemand = 0.0_ReKi + dll_data%HSSBrDeployed = .false. + CASE (1) + if (.not. dll_data%HSSBrDeployed) then + dll_data%TimeHSSBrDeployed = dll_data%CurrentTime + dll_data%TimeHSSBrFullyDeployed = dll_data%TimeHSSBrDeployed + p%HSSBrDT + dll_data%HSSBrDeployed = .true. + dll_data%HSSBrTrqDemand = 0.0_ReKi + else + ! apply a linear ramp up to the maximum value + IF ( dll_data%CurrentTime < dll_data%TimeHSSBrFullyDeployed ) THEN + dll_data%HSSBrTrqDemand = ( dll_data%CurrentTime - dll_data%TimeHSSBrDeployed )/p%HSSBrDT * p%HSSBrTqF + ELSE ! Full braking torque + dll_data%HSSBrTrqDemand = p%HSSBrTqF + ENDIF + end if + CASE (16) + dll_data%HSSBrDeployed = .false. + ! do we need to check that dll_data%HSSBrTrqDemand is set properly???? + CASE DEFAULT + dll_data%HSSBrDeployed = .false. + + ! Fatal issue: shaft brake status specified incorrectly + if (p%UseLegacyInterface) then + CALL SetErrStat( ErrID_Fatal, 'Shaft brake status set improperly. Set avrSWAP(36) to 0, 1, or 16 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + else + CALL SetErrStat( ErrID_Fatal, 'Shaft brake status set improperly. Call SetShaftBrakeStatusBinaryFlag() with binary_brake_status set to 0 or 1 in '// & + TRIM(p%DLL_Trgt%FileName)//'.', ErrStat, ErrMsg, RoutineName) + end if + END SELECT + +END SUBROUTINE CheckDLLReturnValues +!================================================================================================================================== +END MODULE BladedInterface diff --git a/OpenFAST/modules/servodyn/src/PitchCntrl_ACH.f90 b/OpenFAST/modules/servodyn/src/PitchCntrl_ACH.f90 new file mode 100644 index 000000000..167851ce2 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/PitchCntrl_ACH.f90 @@ -0,0 +1,759 @@ + ! NOTE: This source file contains an example PitchCntrl() user-specified + ! routine for computing blade pitch control commands based on transfer + ! function descriptions specified in a pitch.ipt input file. This + ! routine was written by Craig Hansen (ACH) of Windward Engineering + ! LLC. Questions related to the use of this routine should be + ! addressed to Craig Hansen. +module PitchCntrl_ACH +contains +!======================================================================= +SUBROUTINE PitchCntrl ( BlPitch, ElecPwr, LSS_Spd, TwrAccel, NB, ZTime, DT, DirRoot, TFOutput ) + + + ! This routine reads a data file containing user specified transfer + ! function information to allow the use of control systems in FAST + ! and ADAMS. The parameters read in, and array dimensions may be + ! adjusted to suit the users need. + ! The transfer function coefficients are read in, then converted to + ! state space form for integration using a fourth order Runge-Kutta + ! integration scheme. + ! This routine was originally written by C. Hansen in Fortran 77 for + ! use with FAST and ADAMS. It was converted to Modern Fortran by + ! J. Jonkman. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +INTEGER , INTENT(IN ) :: NB ! Number of blades. + +REAL(ReKi), INTENT(IN ) :: BlPitch (NB) ! Current values of the blade pitch angles (rad) +REAL(DbKi), INTENT(IN ) :: DT ! Integration time step (sec) +REAL(ReKi), INTENT(IN ) :: ElecPwr ! Electrical power (watts) +REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed (rad/s) +REAL(ReKi), INTENT(OUT) :: TFOutput(NB) ! Desired pitch angles returned by this subroutine (rad) +REAL(ReKi), INTENT(IN ) :: TwrAccel ! Tower top acceleration (m/s^2) +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time (sec) + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + ! Local Variables: + + ! NOTE: If the values of MSZ OR NSZ are changed, the PARAMETER + ! statements in TFSISO must also be changed to match. +INTEGER , PARAMETER :: MSZ = 12 ! Larger than highest order of transfer function; also used to size number of constants CNST +INTEGER , PARAMETER :: NSZ = 4 ! Number of transfer functions we will use + +REAL(ReKi) :: A0 +REAL(ReKi), SAVE :: AC (MSZ,NSZ) +REAL(ReKi), SAVE :: BC (0:MSZ,NSZ) +REAL(ReKi), SAVE :: CNST (MSZ) ! Maximum of MSZ constants +REAL(ReKi) :: TFInput ! Input to the transfer function +REAL(ReKi), SAVE :: TPCOn ! Time to enable active pitch control. +REAL(ReKi) :: SUM + +INTEGER , SAVE :: CntrlRgn ! Control region (CntrlRgn = 2 = power control, CntrlRgn = 3 = speed control) +INTEGER :: I +INTEGER :: J +INTEGER :: NCNST +INTEGER , SAVE :: NORDER (NSZ) +INTEGER :: NR +INTEGER :: NTEMP + +LOGICAL, SAVE :: INITFLAG = .TRUE. + +CHARACTER(80) :: DESCRIP +CHARACTER( 3) :: FmtText = '(A)' ! Format for outputting pure text. + +CHARACTER(1024) :: PitchFileName ! the name of the input control file +INTEGER(IntKi) :: ErrStat +CHARACTER(ErrMsgLen) :: ErrMsg + + +IF ( INITFLAG ) THEN + + + ! Save the value of time in which pitch control is first activated: + + TPCOn = REAL( ZTime, ReKi) + + ! Read control parameters from 'pitch.ipt' if control is employed + I = INDEX( DirRoot, PathSep, BACK=.TRUE. ) + IF ( I < LEN_TRIM(DirRoot) .OR. I > 0 ) THEN + PitchFileName = DirRoot(1:I)//'pitch.ipt' + ELSE + PitchFileName = 'pitch.ipt' + END IF + + + CALL OpenFInpFile ( 86, TRIM(PitchFileName), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) CALL ProgAbort(TRIM(ErrMsg)) + + + READ(86,FmtText) DESCRIP + + CALL WrScr1( '***********************************************' ) + CALL WrScr( 'Running with control option using data from:' ) + CALL WrScr( TRIM(DESCRIP) ) + CALL WrScr( '***********************************************' ) + CALL WrScr( ' ' ) + + READ(86,*) CntrlRgn + + + READ(86,*) NCNST + + DO I = 1,NCNST + READ(86,*,END=20) CNST(I) + ENDDO + + NR = 1 + + +10 READ(86,*,END=40) NTEMP ! Use NTEMP to avoid array overflow at end of file + NORDER(NR) = NTEMP + READ(86,*,END=30) (BC(I,NR), I = NORDER(NR),0,-1) + READ(86,*,END=30) (AC(I,NR), I = NORDER(NR),1,-1), A0 + + IF ( ABS(A0) > 1.E-7 ) THEN + DO I = 0,NORDER(NR) + BC(I,NR) = BC(I,NR)/A0 + ENDDO + DO I = 1,NORDER(NR) + AC(I,NR) = AC(I,NR)/A0 + ENDDO + ELSE + CALL ProgAbort ( 'Coefficient of largest power of s in the denominator must not be zero.' ) + ENDIF + + + ! Calculate coefficients for state space model + + DO I = 1,NORDER(NR) + SUM = 0.0 + DO J = 1,I + SUM = SUM - AC(J,NR)*BC(I-J,NR) + ENDDO + BC(I,NR) = BC(I,NR) + SUM + ENDDO + + + NR = NR + 1 + + + GOTO 10 + +20 CALL WrScr( 'Error while reading constants from pitch.ipt file' ) + CALL WrScr( 'Encountered end of file while reading constants' ) + CALL WrScr( 'Number of constants expected: '//TRIM(Num2LStr(NCNST)) ) + CALL WrScr( 'Number of constants found: '//TRIM(Num2LStr(I-1 )) ) + CALL ProgAbort( 'Check your pitch.ipt file.' ) + + +30 CALL WrScr( 'Error in specification of transfer function #'//TRIM(Num2LStr(NR)) ) + CALL ProgAbort( 'Check your pitch.ipt file.' ) + + +40 CONTINUE + + + ! Always require that NSZ transfer functions are input to help + ! ensure correct input file for this version of code + + IF( NR-1 /= NSZ ) THEN + CALL WrScr( 'Error in pitch.ipt file' ) + CALL WrScr( 'Incorrect number of transfer functions ' ) + CALL WrScr( 'Number that were read: '//TRIM(Num2LStr(NR-1)) ) + CALL WrScr( 'Number that were expected: '//TRIM(Num2LStr(NSZ )) ) + CALL ProgAbort( 'Check your pitch.ipt file.' ) + ENDIF + + + INITFLAG = .FALSE. + + CLOSE(86) + + + RETURN + + +ENDIF ! Initialization + + + ! Determine the Transfer Function Input, TFInput, based on specified control + ! region: + +SELECT CASE ( CntrlRgn ) ! Which control region are we in? + +CASE ( 2 ) ! Region 2 control = power control + + TFInput = 0.001*ElecPwr ! Electric power, kW + +CASE ( 3 ) ! Region 3 control = speed control + +! TFInput = HSS_Spd/ABS(GBRatio)*RPS2RPM ! LSS speed at gearbox entrance, rpm + TFInput = LSS_Spd*RPS2RPM ! LSS speed at gearbox entrance, rpm + + +CASE DEFAULT ! None of the above + + CALL ProgAbort ( ' CntrlRgn must be 2 or 3.' ) + + +ENDSELECT + + + ! Use the control routine + +CALL CTRL4 ( CNST, AC, BC, NORDER, MSZ, NSZ, & + TFOutput, BlPitch, TFInput, TwrAccel, NB, ZTime, TPCOn ) + + + +RETURN +END SUBROUTINE PitchCntrl +!======================================================================= +SUBROUTINE CTRL4 ( CNST, AC, BC, NORDER, MSZ, NSZ, & + TFOutput, BlPitch, TFInput, TwrAccel, NB, ZTime, TPCOn ) + + + ! In this subroutine dependencies between transfer functions, as well + ! as inputs and outputs of transfer functions are defined. For the + ! call to TFSISO the user need only be concerned with the first + ! three arguments. The first argument is the transfer fuction + ! input, the second is the transfer function output, the third + ! specifies the transfer function number, with the number + ! coresponding to the order in which the transfer functions were + ! read from the input file. + + +USE NWTC_Library + +IMPLICIT NONE + + + ! Passed variables: + +INTEGER , INTENT(IN ) :: MSZ +INTEGER , INTENT(IN ) :: NB ! Number of blades. +INTEGER , INTENT(IN ) :: NSZ + +REAL(ReKi), INTENT(IN ) :: AC (MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: BC (0:MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: BlPitch (NB) ! Current blade pitch. +REAL(ReKi), INTENT(IN ) :: CNST (MSZ) +REAL(ReKi), INTENT(IN ) :: TFInput +REAL(ReKi), INTENT(OUT) :: TFOutput(NB) +REAL(ReKi), INTENT(IN ) :: TPCOn ! Time to enable active pitch control. +REAL(ReKi), INTENT(IN ) :: TwrAccel +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time. + +INTEGER , INTENT(IN ) :: NORDER (NSZ) + + + ! Local variables: + +REAL(ReKi) :: AWIND = 0.0 +REAL(ReKi) :: DTSTRT +REAL(ReKi) :: DTCNTRL +REAL(ReKi) :: GAINSCHED +REAL(ReKi) :: GSCoef +REAL(ReKi) :: GSExp +REAL(ReKi) :: GSPit1 +REAL(ReKi) :: GSPit2 +REAL(ReKi) :: OLDTIME = 0.0 ! Previous time we changed the pitch angle, sec +REAL(ReKi) :: OLDTFOUTPUT +REAL(ReKi), PARAMETER :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of ReKi. +REAL(ReKi) :: PHI0 +REAL(ReKi) :: PHI1 +REAL(ReKi) :: PHI2 +REAL(ReKi) :: PITMAX +REAL(ReKi) :: PITMIN +REAL(ReKi) :: TWROUTPUT +REAL(ReKi) :: U1 +REAL(ReKi) :: U2 +REAL(ReKi) :: X + +INTEGER :: DEBUGFLAG +INTEGER :: K ! Blade number + +LOGICAL :: TRIMFLAG = .TRUE. ! Initialization flag + +CHARACTER( 8) :: Frmt1 = '(20(:A))' +CHARACTER(14) :: Frmt2 = '(20(:G12.5,A))' +INTEGER(IntKi) :: ErrStat +CHARACTER(ErrMsgLen) :: ErrMsg + + +SAVE ! mlb - Do we need to save everything? + + + + ! Enter variables which need to be initialized after trim solution here + +IF ( TRIMFLAG ) THEN + + + PHI0 = BlPitch(1)*R2D ! Initial pitch angle (deg) + OLDTFOUTPUT = BlPitch(1) + TRIMFLAG = .FALSE. + + + ! Assign variable values from the pitch.ipt file + + PITMIN = CNST( 4) ! Minimum pitch angle, deg + PITMAX = CNST( 5) ! Maximum pitch angle, deg + DTCNTRL = CNST( 6) ! Time interval for pitch control, sec + GSPit1 = CNST( 7) ! Pitch angle for start of gain scheduling (>0), rad + GSPit2 = CNST( 8) ! Pitch angle for end of gain scheduling, rad + GSCoef = CNST( 9) ! constant 'a' in gain schedule power law ( GS = a * x**p) + GSExp = CNST(10) ! exponent 'p' in gain schedule power law ( GS = a * x**p) + DEBUGFLAG = CNST(11) ! Debug file output (0=no, 1=yes) + + + ! Open file to receive control variable output for debug (if desired) + + IF( DEBUGFLAG == 1 ) THEN + + CALL OpenFOutFile (40, 'pitcntrl.plt', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) CALL ProgAbort(TRIM(ErrMsg)) + WRITE (40,"( / 'This file was generated by ' , A , A , ' on ' , A , ' at ' , A , '.' / )") & + TRIM(ProgName), TRIM( ProgVer ), CurDate(), CurTime() + + WRITE(40,*) 'Output of PITCH control control subroutine' + WRITE(40,*) 'Gain schedule coeffs = ', GSCoef, GSExp + + WRITE(40,Frmt1) & + 'Time', TAB, & + 'Pitch', TAB, & + 'TFInput', TAB, & + 'TwrAccel', TAB, & + 'TWROUTPUT', TAB, & + 'Input1U1', TAB, & + 'OutputPHI0', TAB, & + 'OutputPHI1', TAB, & + 'OutputPHI2', TAB, & + 'PitchOutput', TAB, & + 'GainSched', TAB, & + 'Awindup' + + ENDIF + + +ENDIF + + +!check for numerical stability +!print *, REAL(ZTime,ReKi) - OLDTIME, (REAL(ZTime,ReKi) - OLDTIME < DTCNTRL ) , EqualRealNos( REAL(ZTime,ReKi), OldTime+DtCntrl ) +IF ( .NOT. EqualRealNos( REAL(ZTime,ReKi), OldTime+DtCntrl ) ) THEN + IF( REAL(ZTime,ReKi) - OLDTIME < DTCNTRL ) THEN ! Time check needed for FAST +!old IF( REAL(ZTime,ReKi) - OLDTIME < DTCNTRL ) THEN ! Time check needed for FAST +!new: IF( ZTime*OnePlusEps - OLDTIME < DTCNTRL ) THEN ! Time check needed for FAST + DO K = 1,NB + TFOutput(K) = OLDTFOUTPUT + ENDDO ! K + RETURN + END IF +ENDIF + + +OLDTIME = REAL(ZTime,ReKi) + + + ! Apply gain scheduling based on measured pitch angle (rad) + +X = SAT2( BlPitch(1), GSPit1, GSPit2 ) ! Use endpoints if outside the endpoints +GAINSCHED = GSCoef*( X**GSExp ) + + + ! Ramp the gains up from zero to the desired values during startup + ! The intent is to avoid controller problems due to startup transients + +DTSTRT = ZTime - TPCOn + 0.01 ! Avoid zero gain by using offset +IF( DTSTRT < 5.0 ) GAINSCHED = GAINSCHED * DTSTRT / 5.0 + + + ! First TF input is error * gain + +U1 = GAINSCHED * CNST(1) * ( CNST(2) - TFInput ) +U2 = GAINSCHED * CNST(3) * AWIND + + + ! U1 = Input to transfer function (rotor RPM or kW error, depending upon PCHMODE) + ! PHI0 = Output of transfer function = pitch in degrees + ! Third argument = number or ID of transfer function + ! First transfer function is integral term of PID pitch demand control + +CALL TFSISO( U1-U2, PHI0, 1, AC, BC, DTCNTRL, NORDER, MSZ, NSZ ) + + + ! Second transfer function is PD terms of PID pitch demand control + ! NOTE: The antiwindup term is not included here + +CALL TFSISO( U1 , PHI1, 2, AC, BC, DTCNTRL, NORDER, MSZ, NSZ ) + + + ! Add these two to get pitch demand control output + +PHI1 = PHI0 + PHI1 + + + ! Now apply third transfer function to represent tower acceleration + ! feedback. If order of 3rd transfer function is zero, this + ! transfer function is not applied. + +IF ( NORDER(3) == 0 ) THEN + TWROUTPUT = 0.0 +ELSE + CALL TFSISO( TwrAccel, TWROUTPUT, 3, AC, BC, DTCNTRL, NORDER, MSZ, NSZ ) +ENDIF + + + ! Add pitch demand from tower accel. to that from speed/power error + +PHI1 = PHI1 + TWROUTPUT + + + ! SAT2 function ensures that the pitch angle demand does not go + ! beyond limits (2nd and 3rd arguments in degrees) + +PHI2 = SAT2( PHI1, PITMIN, PITMAX ) ! Pitch angle, deg + +AWIND = PHI1 - PHI2 ! Anti windup term when pitch demand saturates, deg + + + ! Now apply fourth transfer function to represent the actuator + ! (Do not use this actuator in ADAMS. If order of 4th + ! transfer function is zero, this transfer function is not applied) + +IF ( NORDER(4) == 0 ) THEN + DO K=1,NB + TFOutput(K) = PHI2 + ENDDO ! K +ELSE + CALL TFSISO( PHI2, TFOutput(1), 4, AC, BC, DTCNTRL, NORDER, MSZ, NSZ ) + TFOutput = TFOutput(1) ! All blades use same pitch in this version +ENDIF + + +DO K=1,NB + TFOutput(K) = TFOutput(K)*D2R ! Pitch angle returned by subroutine, rad +ENDDO ! K + + +OLDTFOUTPUT = TFOutput(1) ! Save for use until next control time + + + ! Write to controller output file if desired. + +IF ( DEBUGFLAG == 1 ) THEN + WRITE(40,Frmt2) & + ZTime, TAB, & + BlPitch(1)*R2D, TAB, & + TFInput, TAB, & + TwrAccel, TAB, & + TWROUTPUT, TAB, & + U1, TAB, & + PHI0, TAB, & + PHI1, TAB, & + PHI2, TAB, & + TFOutput(1)*R2D, TAB, & + GAINSCHED, TAB, & + AWIND +ENDIF + + + +RETURN +END SUBROUTINE CTRL4 +!======================================================================= +SUBROUTINE TFSISO ( U, Y, NR, AC, BC, DT, NORDER, MSZ, NSZ ) + + + ! This routine integrates the transfer functions using a fourth order + ! Runge-Kutta method. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +INTEGER , INTENT(IN ) :: MSZ +INTEGER , INTENT(IN ) :: NSZ + +REAL(ReKi), INTENT(IN ) :: AC (MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: BC (0:MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: DT +REAL(ReKi), INTENT(IN ) :: U +REAL(ReKi), INTENT(OUT) :: Y + +INTEGER , INTENT(IN ) :: NORDER (NSZ) +INTEGER , INTENT(IN ) :: NR + + + ! Local variables: + + ! NOTE: If the values of M OR N are changed, the PARAMETER + ! statements in PitchCntrl must also be changed to match. +INTEGER , PARAMETER :: M = 12 ! Larger than highest order of transfer function; also used to size number of constants CNST +INTEGER , PARAMETER :: N = 4 ! Number of transfer functions we will use + +REAL(ReKi) :: DT6 +REAL(ReKi) :: DXDT (MSZ) +REAL(ReKi) :: DXM (MSZ) +REAL(ReKi) :: DXT (MSZ) +REAL(ReKi) :: HDT +REAL(ReKi) :: X (M,N) = 0.0 +REAL(ReKi) :: XT (MSZ) + +INTEGER :: I + +LOGICAL :: INITFLAG(N) = .TRUE. + + + +IF ( INITFLAG(NR) ) THEN + CALL TFINIT( U, Y, X, AC, BC, NORDER, NSZ, MSZ, NR ) + IF( ( NSZ /= N ) .OR. ( MSZ /= M ) ) THEN + PRINT*, 'ERROR IN PARAMETERS M AND/OR N IN TFSISO' + ENDIF + INITFLAG(NR) = .FALSE. +ENDIF + + +HDT = 0.5*DT +DT6 = DT/6.0 + + +DO I = 1,NORDER(NR) + XT(I) = X(I,NR) +ENDDO + + +CALL XDOT( U, XT, AC, BC, DXDT, NORDER, NSZ, MSZ, NR ) +DO I = 1,NORDER(NR) + XT(I) = X(I,NR) + HDT*DXDT(I) +ENDDO + + +CALL XDOT( U, XT, AC, BC, DXT, NORDER, NSZ, MSZ, NR ) +DO I = 1,NORDER(NR) + XT(I) = X(I,NR) + HDT*DXT (I) +ENDDO + + +CALL XDOT( U, XT, AC, BC, DXM, NORDER, NSZ, MSZ, NR ) +DO I = 1,NORDER(NR) + XT(I) = X(I,NR) + DT*DXM (I) + DXM(I) = DXT(I) + DXM(I) +ENDDO + + +CALL XDOT( U, XT, AC, BC, DXT, NORDER, NSZ, MSZ, NR ) +DO I = 1,NORDER(NR) + X(I,NR) = X(I,NR) + DT6*( DXDT(I) + DXT(I) +2.0*DXM(I) ) +ENDDO + + +Y = X(1,NR) + BC(0,NR)*U + + + +RETURN +END SUBROUTINE TFSISO +!======================================================================= +SUBROUTINE XDOT ( U, X, AC, BC, DXDT, NORDER, NSZ, MSZ, NR ) + + + ! This routine calculates derivatives for fourth order Runge-Kutta. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +INTEGER , INTENT(IN ) :: MSZ +INTEGER , INTENT(IN ) :: NSZ + +REAL(ReKi), INTENT(IN ) :: AC (MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: BC (0:MSZ,NSZ) +REAL(ReKi), INTENT(OUT) :: DXDT (MSZ) +REAL(ReKi), INTENT(IN ) :: U +REAL(ReKi), INTENT(IN ) :: X (MSZ) + +INTEGER , INTENT(IN ) :: NORDER (NSZ) +INTEGER , INTENT(IN ) :: NR + + + ! Local variables: + +REAL(ReKi) :: SUM + +INTEGER :: I + + + + ! Derivatives: + +DO I = 1,NORDER(NR)-1 + DXDT(I) = X(I+1) + BC(I,NR)*U +ENDDO + + +SUM = 0.0 +DO I = 1,NORDER(NR) + SUM = SUM - X(I)*AC( NORDER(NR) + 1 - I, NR ) +ENDDO + + +DXDT(NORDER(NR)) = SUM + BC(NORDER(NR),NR)*U + + + +RETURN +END SUBROUTINE XDOT +!======================================================================= +SUBROUTINE TFINIT ( U, Y, X, AC, BC, NORDER, NSZ, MSZ, NR ) + + + ! This routine initialize states for fourth order Runge-Kutta. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +INTEGER , INTENT(IN ) :: MSZ +INTEGER , INTENT(IN ) :: NSZ + +REAL(ReKi), INTENT(IN ) :: AC (MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: BC (0:MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: U +REAL(ReKi), INTENT(OUT) :: X (MSZ,NSZ) +REAL(ReKi), INTENT(IN ) :: Y + +INTEGER , INTENT(IN ) :: NORDER (NSZ) +INTEGER , INTENT(IN ) :: NR + + + ! Local variables: + +REAL(ReKi) :: SUM + +INTEGER :: I + + + +X(1,NR) = Y - BC(0,NR)*U +DO I = 1,NORDER(NR)-1 + X(I+1,NR) = -BC(I,NR)*U +ENDDO + + +SUM = 0.0 +DO I = 1,NORDER(NR)-1 + SUM = SUM - X(I,NR)*AC( NORDER(NR) + 1 - I, NR ) +ENDDO + + + ! Watch out for zero values of AC + +IF( AC(1,NR) /= 0.0 ) THEN + X(NORDER(NR),NR) = ( -SUM - BC(NORDER(NR),NR)*U )/AC(1,NR) +ELSE + X(NORDER(NR),NR) = ( -SUM - BC(NORDER(NR),NR)*U )/0.001 +ENDIF + + + +RETURN +END SUBROUTINE TFINIT +!======================================================================= +FUNCTION SAT2 ( X, XMIN, XMAX ) + + + ! Saturation function. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +REAL(ReKi) :: SAT2 +REAL(ReKi), INTENT(IN ) :: X +REAL(ReKi), INTENT(IN ) :: XMAX +REAL(ReKi), INTENT(IN ) :: XMIN + + + +IF ( X > XMAX ) THEN + SAT2 = XMAX +ELSEIF ( X < XMIN ) THEN + SAT2 = XMIN +ELSE + SAT2 = X +ENDIF + + + +RETURN +END FUNCTION SAT2 +!======================================================================= +FUNCTION DEADBAND ( X, XMIN, XMAX ) + + + ! Deadband function. + + +USE NWTC_Library + + +IMPLICIT NONE + + + ! Passed variables: + +REAL(ReKi) :: DEADBAND +REAL(ReKi), INTENT(IN ) :: X +REAL(ReKi), INTENT(IN ) :: XMAX +REAL(ReKi), INTENT(IN ) :: XMIN + + + +IF ( X > XMAX ) THEN + DEADBAND = X - XMAX +ELSEIF ( X < XMIN ) THEN + DEADBAND = X - XMIN +ELSE + DEADBAND = 0.0 +ENDIF + + + +RETURN +END FUNCTION DEADBAND +!======================================================================= +end module PitchCntrl_ACH + \ No newline at end of file diff --git a/OpenFAST/modules/servodyn/src/ServoDyn.f90 b/OpenFAST/modules/servodyn/src/ServoDyn.f90 new file mode 100644 index 000000000..ac0fd59c8 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/ServoDyn.f90 @@ -0,0 +1,4216 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of FAST's Controls and Electrical Drive Module, "ServoDyn". +! +! 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. +! +!********************************************************************************************************************************** +!> Control and electrical drive dynamics module for FAST +MODULE ServoDyn + + USE ServoDyn_Types + USE NWTC_Library + USE BladedInterface + USE TMD + + USE UserVSCont_KP ! <- module not in the FAST Framework! + USE PitchCntrl_ACH ! <- module not in the FAST Framework! + USE UserSubs ! <- module not in the FAST Framework! + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: SrvD_Ver = ProgDesc( 'ServoDyn', '', '' ) + +#ifdef COMPILE_SIMULINK + LOGICAL, PARAMETER, PUBLIC :: Cmpl4SFun = .TRUE. ! Is the module being compiled as an S-Function for Simulink? +#else + LOGICAL, PARAMETER, PUBLIC :: Cmpl4SFun = .FALSE. ! Is the module being compiled as an S-Function for Simulink? +#endif + +#ifdef COMPILE_LABVIEW + LOGICAL, PARAMETER, PUBLIC :: Cmpl4LV = .TRUE. ! Is the module being compiled for Labview? +#else + LOGICAL, PARAMETER, PUBLIC :: Cmpl4LV = .FALSE. ! Is the module being compiled for Labview? +#endif + + ! indices into linearization arrays + INTEGER, PARAMETER :: Indx_u_Yaw = 1 + INTEGER, PARAMETER :: Indx_u_YawRate = 2 + INTEGER, PARAMETER :: Indx_u_HSS_Spd = 3 + + INTEGER, PARAMETER, PUBLIC :: SrvD_Indx_Y_BlPitchCom(3) = (/1,2,3/) + INTEGER, PARAMETER, PUBLIC :: SrvD_Indx_Y_YawMom = 4 + INTEGER, PARAMETER, PUBLIC :: SrvD_Indx_Y_GenTrq = 5 + INTEGER, PARAMETER, PUBLIC :: SrvD_Indx_Y_ElecPwr = 6 + INTEGER, PARAMETER, PUBLIC :: SrvD_Indx_Y_WrOutput = 6 ! last non-writeoutput variable + +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 05-Nov-2015 09:57:49. + + + ! Parameters related to output length (number of characters allowed in the output data headers): + + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Pitch Control: + + INTEGER(IntKi), PARAMETER :: BlPitchC1 = 1 + INTEGER(IntKi), PARAMETER :: BlPitchC2 = 2 + INTEGER(IntKi), PARAMETER :: BlPitchC3 = 3 + + + ! Generator and Torque Control: + + INTEGER(IntKi), PARAMETER :: GenTq = 4 + INTEGER(IntKi), PARAMETER :: GenPwr = 5 + + + ! High Speed Shaft Brake: + + INTEGER(IntKi), PARAMETER :: HSSBrTqC = 6 + + + ! Nacelle Yaw Control: + + INTEGER(IntKi), PARAMETER :: YawMomCom = 7 + + + ! Nacelle Tuned Mass Damper (TMD): + + INTEGER(IntKi), PARAMETER :: NTMD_XQ = 8 + INTEGER(IntKi), PARAMETER :: NTMD_XQD = 9 + INTEGER(IntKi), PARAMETER :: NTMD_YQ = 10 + INTEGER(IntKi), PARAMETER :: NTMD_YQD = 11 + + + ! Tower Tuned Mass Damper (TMD): + + INTEGER(IntKi), PARAMETER :: TTMD_XQ = 12 + INTEGER(IntKi), PARAMETER :: TTMD_XQD = 13 + INTEGER(IntKi), PARAMETER :: TTMD_YQ = 14 + INTEGER(IntKi), PARAMETER :: TTMD_YQD = 15 + + ! Airfoil Control (might be used for flap actuation): + + INTEGER(IntKi), PARAMETER :: BlAirFlC1 = 16 + INTEGER(IntKi), PARAMETER :: BlAirFlC2 = 17 + INTEGER(IntKi), PARAMETER :: BlAirFlC3 = 18 + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 18 + +!End of code generated by Matlab script +! =================================================================================================== + + INTEGER(IntKi), PARAMETER :: BlPitchC (3) = (/ BlPitchC1, BlPitchC2, BlPitchC3 /) + INTEGER(IntKi), PARAMETER :: BlAirfoilC (3) = (/ BlAirFlC1, BlAirFlC2, BlAirFlC3 /) + +!bjj: added parameters here (after the "(/ /)" above) so VS2010 doesn't get so confused with the previous statement. + + ! Parameters for type of control + + INTEGER(IntKi), PARAMETER :: ControlMode_NONE = 0 !< The (ServoDyn-universal) control code for not using a particular type of control + INTEGER(IntKi), PARAMETER :: ControlMode_SIMPLE = 1 !< The (ServoDyn-universal) control code for obtaining the control values from a simple built-in controller + INTEGER(IntKi), PARAMETER :: ControlMode_ADVANCED = 2 !< The (ServoDyn-universal) control code for not using the control values from an advanced built-in controller (or just a different simple model?) + INTEGER(IntKi), PARAMETER :: ControlMode_USER = 3 !< The (ServoDyn-universal) control code for obtaining the control values from a user-defined routine + INTEGER(IntKi), PARAMETER :: ControlMode_EXTERN = 4 !< The (ServoDyn-universal) control code for obtaining the control values from Simulink or Labivew + INTEGER(IntKi), PARAMETER :: ControlMode_DLL = 5 !< The (ServoDyn-universal) control code for obtaining the control values from a Bladed-Style dynamic-link library + + INTEGER(IntKi), PARAMETER, PUBLIC :: TrimCase_none = 0 + INTEGER(IntKi), PARAMETER, PUBLIC :: TrimCase_yaw = 1 + INTEGER(IntKi), PARAMETER, PUBLIC :: TrimCase_torque = 2 + INTEGER(IntKi), PARAMETER, PUBLIC :: TrimCase_pitch = 3 + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: SrvD_Init ! Initialization routine + PUBLIC :: SrvD_End ! Ending routine (includes clean up) + + PUBLIC :: SrvD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: SrvD_CalcOutput ! Routine for computing outputs + + PUBLIC :: SrvD_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: SrvD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: SrvD_UpdateDiscState ! Tight coupling routine for updating discrete states + + PUBLIC :: SrvD_JacobianPInput ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the inputs (u) + PUBLIC :: SrvD_JacobianPContState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the continuous + ! states (x) + PUBLIC :: SrvD_JacobianPDiscState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the discrete + ! states (xd) + PUBLIC :: SrvD_JacobianPConstrState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the constraint + ! states (z) + PUBLIC :: SrvD_GetOP ! Routine to pack the operating point values (for linearization) into arrays + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE SrvD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SrvD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(SrvD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SrvD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(SrvD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(SrvD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(SrvD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(SrvD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(SrvD_MiscVarType), INTENT( OUT) :: m !< Initial misc (optimization) variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) SrvD_UpdateStates() is called in loose coupling & + !! (2) SrvD_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(SrvD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + TYPE(SrvD_InputFile) :: InputFileData ! Data stored in the module's input file + TYPE(TMD_InitInputType) :: TMD_InitInp ! data to initialize TMD module + TYPE(TMD_InitOutputType) :: TMD_InitOut ! data from TMD module initialization (not used) + INTEGER(IntKi) :: i ! loop counter + INTEGER(IntKi) :: j ! loop counter + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + + CALL DispNVD( SrvD_Ver ) + + !............................................................................................ + ! Read the input file and validate the data + ! (note p%NumBl and p%RootName must be set first!) + !............................................................................................ + p%RootName = InitInp%Rootname ! FAST adds the '.SrvD' before calling this module + p%NumBl = InitInp%NumBl + + CALL SrvD_ReadInput( InitInp, InputFileData, Interval, p%RootName, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL ValidatePrimaryData( InitInp, InputFileData, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + if ( (InitInp%NumCtrl2SC > 0 .and. InitInp%NumCtrl2SC <= 0) .or. & + (InitInp%NumSC2Ctrl <= 0 .and. InitInp%NumSC2Ctrl > 0) ) then + call CheckError( ErrID_Fatal, "If supercontroller is used, there must be at least one supercontroller input and one supercontroller output." ) + return + end if + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + CALL SrvD_SetParameters( InputFileData, p, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + !p%DT = Interval + + ! Set and verify BlPitchInit, which comes from InitInputData (not the inputfiledata) + CALL AllocAry( p%BlPitchInit, p%NumBl, 'BlPitchInit', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + p%BlPitchInit = InitInp%BlPitchInit + + IF ( ANY( p%BlPitchInit <= -pi ) .OR. ANY( p%BlPitchInit > pi ) ) THEN + CALL CheckError( ErrID_Fatal, 'BlPitchInit must be in the range (-pi,pi] radians (i.e., (-180,180] degrees).' ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + + x%DummyContState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + + CALL AllocAry( m%xd_BlPitchFilter, p%NumBl, 'BlPitchFilter', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + m%xd_BlPitchFilter = p%BlPitchInit + + !....................... + ! Other states for pitch maneuver + !....................... + CALL AllocAry( OtherState%BegPitMan, p%NumBl, 'BegPitMan', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%BegPitMan = .false. ! Pitch maneuvers didn't actually start, yet + + CALL AllocAry( OtherState%BlPitchI, p%NumBl, 'BlPitchI', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%BlPitchI = 0.0_ReKi + + CALL AllocAry( OtherState%TPitManE, p%NumBl, 'TPitManE', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%TPitManE = 0.0_DbKi + + !....................... + ! Other states for yaw maneuver + !....................... + OtherState%BegYawMan = .false. ! Yaw maneuver didn't actually start, yet + OtherState%NacYawI = 0.0_ReKi + OtherState%TYawManE = 0.0_ReKi + + !....................... + ! other states for torque control: + !....................... + OtherState%Off4Good = .false. ! generator is not off for good + ! is the generator online at initialization? + IF ( p%GenTiStr .and. p%TimGenOn <= 0.0_ReKi ) THEN ! Start-up of generator determined by time, TimGenOn + OtherState%GenOnLine = .true. + ELSE + OtherState%GenOnLine = .false. + END IF + + + !............................................................................................ + ! Define initial guess for the system inputs here: + !............................................................................................ + + CALL AllocAry( u%BlPitch, p%NumBl, 'BlPitch', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( u%ExternalBlPitchCom, p%NumBl, 'ExternalBlPitchCom', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + IF (InitInp%NumSC2Ctrl > 0 .and. p%UseBladedInterface) THEN + CALL AllocAry( u%SuperController, InitInp%NumSC2Ctrl, 'u%SuperController', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + u%SuperController = 0.0_SiKi + END IF + + + u%BlPitch = p%BlPitchInit + + u%Yaw = p%YawNeut + u%YawRate = 0.0 + + u%LSS_Spd = 0.0 + u%HSS_Spd = 0.0 + u%RotSpeed = 0.0 + + u%ExternalYawPosCom = p%YawNeut + u%ExternalYawRateCom = 0. + u%ExternalBlPitchCom = p%BlPitchInit + u%ExternalGenTrq = 0. + u%ExternalElecPwr = 0. + u%ExternalHSSBrFrac = 0. + + u%TwrAccel = 0. + u%YawErr = 0. + u%WindDir = 0. + + !Inputs for the Bladed Interface: + u%RootMyc = 0. + u%YawBrTAxp = 0. + u%YawBrTAyp = 0. + u%LSSTipPxa = 0. + u%RootMxc = 0. + u%LSSTipMxa = 0. + u%LSSTipMya = 0. + u%LSSTipMza = 0. + u%LSSTipMys = 0. + u%LSSTipMzs = 0. + u%YawBrMyn = 0. + u%YawBrMzn = 0. + u%NcIMURAxs = 0. + u%NcIMURAys = 0. + u%NcIMURAzs = 0. + u%RotPwr = 0. + u%HorWindV = 0. + u%YawAngle = 0. + m%dll_data%ElecPwr_prev = 0. + m%dll_data%GenTrq_prev = 0. + + !............................................................................................ + ! Define system output initializations (set up mesh) here: + !............................................................................................ + CALL AllocAry( y%BlPitchCom, p%NumBl, 'BlPitchCom', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Commanded Airfoil UserProp for blade. Must be same units as given in AD15 airfoil tables + ! This is passed to AD15 to be interpolated with the airfoil table userprop column + CALL AllocAry( y%BlAirfoilCom, p%NumBl, 'BlAirfoilCom', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + y%BlAirfoilCom = 0.0_ReKi + + ! tip brakes - this may be added back, later, so we'll keep these here for now + CALL AllocAry( y%TBDrCon, p%NumBl, 'TBDrCon', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + IF (InitInp%NumCtrl2SC > 0 .and. p%UseBladedInterface) THEN + CALL AllocAry( y%SuperController, InitInp%NumCtrl2SC, 'y%SuperController', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + y%SuperController = 0.0_SiKi + END IF + + + !............................................................................................ + ! tip brakes - this may be added back, later, so we'll keep these here for now + !............................................................................................ + CALL AllocAry( OtherState%BegTpBr, p%NumBl, 'BegTpBr', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%BegTpBr = .FALSE. + + CALL AllocAry( OtherState%TTpBrDp, p%NumBl, 'TTpBrDp', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%TTpBrDp = HUGE(OtherState%TTpBrDp) !basically never deploy them. Eventually this will be added back? + + CALL AllocAry( OtherState%TTpBrFl, p%NumBl, 'TTpBrFl', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + OtherState%TTpBrFl = HUGE(OtherState%TTpBrFl) !basically never deploy them. Eventually this will be added back? + !OtherState%TTpBrFl = InputFileData%TTpBrFl + p%TpBrDT + + + !............................................................................................ + ! yaw control integrated command angle + !............................................................................................ + OtherState%YawPosComInt = p%YawNeut + + + !............................................................................................ + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + !............................................................................................ + + Interval = p%DT + + !............................................................................................ + ! After we've set up all the data for everything else, we'll call the routines to initialize the Bladed Interface + ! (it requires initial guesses for input/output) + !............................................................................................ + + IF ( p%UseBladedInterface ) THEN + + p%AirDens = InitInp%AirDens + p%AvgWindSpeed = InitInp%AvgWindSpeed + + CALL BladedInterface_Init(u, p, m, y, InputFileData, InitInp, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + m%LastTimeCalled = - m%dll_data%DLL_DT ! we'll initialize the last time the DLL was called as -1 DLL_DT. + m%LastTimeFiltered = - p%DT ! we'll initialize the last time the DLL was filtered as -1 DT. + m%FirstWarn = .TRUE. + ELSE + m%dll_data%DLL_DT = p%DT ! DLL_DT is used to compute the pitch rate and acceleration outputs + p%DLL_n = 1 ! Without a call to the DLL, update the history every time step + + p%DLL_Trgt%FileName = "" + p%DLL_Trgt%ProcName = "" + + END IF + + + !............................................................................................ + ! Initialize the TMD module for Nacelle: + !............................................................................................ + IF (p%CompNTMD) THEN + + TMD_InitInp%InputFile = InputFileData%NTMDfile + TMD_InitInp%RootName = TRIM(p%RootName)//'.NTMD' + TMD_InitInp%Gravity = InitInp%gravity + TMD_InitInp%r_N_O_G = InitInp%r_N_O_G + + CALL TMD_Init( TMD_InitInp, u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, y%NTMD, m%NTMD, Interval, TMD_InitOut, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + IF (.NOT. EqualRealNos( Interval, p%DT ) ) THEN + CALL CheckError( ErrID_Fatal, "Nacelle TMD time step differs from SrvD time step." ) + RETURN + END IF + + END IF + + !............................................................................................ + ! Initialize the TMD module for tower: + !............................................................................................ + IF (p%CompTTMD) THEN + + TMD_InitInp%InputFile = InputFileData%TTMDfile + TMD_InitInp%RootName = TRIM(p%RootName)//'.TTMD' + TMD_InitInp%Gravity = InitInp%gravity + TMD_InitInp%r_N_O_G = InitInp%r_TwrBase + + CALL TMD_Init( TMD_InitInp, u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, y%TTMD, m%TTMD, Interval, TMD_InitOut, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + IF (.NOT. EqualRealNos( Interval, p%DT ) ) THEN + CALL CheckError( ErrID_Fatal, "Tower TMD time step differs from SrvD time step." ) + RETURN + END IF + + END IF + + + + !............................................................................................ + ! Set Init outputs for linearization (after TMD, in case we ever add the TMD to the linearization features): + !............................................................................................ + xd%CtrlOffset = 0.0_ReKi ! initialize before first use with TrimCase in linearization + p%TrimCase = InitInp%TrimCase + p%TrimGain = InitInp%TrimGain + p%RotSpeedRef = InitInp%RotSpeedRef + + if (InitInp%Linearize) then + + ! If the module does allow linearization, return the appropriate Jacobian row/column names here: + ! Allocate and set these variables: InitOut%LinNames_y, InitOut%LinNames_x, InitOut%LinNames_xd, InitOut%LinNames_z, InitOut%LinNames_u + + CALL AllocAry( InitOut%RotFrame_y, SrvD_Indx_Y_WrOutput+p%NumOuts, 'RotFrame_y', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( InitOut%LinNames_y, SrvD_Indx_Y_WrOutput+p%NumOuts, 'LinNames_y', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + do i=1,size(SrvD_Indx_Y_BlPitchCom) + InitOut%LinNames_y(SrvD_Indx_Y_BlPitchCom(i)) = 'BlPitchCom('//trim(num2lstr(i))//'), rad' + InitOut%RotFrame_y(SrvD_Indx_Y_BlPitchCom(i)) = .true. + end do + InitOut%LinNames_y(SrvD_Indx_Y_YawMom) = 'YawMom, Nm' + InitOut%RotFrame_y(SrvD_Indx_Y_YawMom) = .false. + + InitOut%LinNames_y(SrvD_Indx_Y_GenTrq) = 'GenTrq, Nm' + InitOut%RotFrame_y(SrvD_Indx_Y_GenTrq) = .false. + + InitOut%LinNames_y(SrvD_Indx_Y_ElecPwr) = 'ElecPwr, W' + InitOut%RotFrame_y(SrvD_Indx_Y_ElecPwr) = .false. + + do i=1,p%NumOuts + InitOut%LinNames_y(i+SrvD_Indx_Y_WrOutput) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + InitOut%RotFrame_y(i+SrvD_Indx_Y_WrOutput) = ANY( p%OutParam(i)%Indx == BlPitchC ) ! the only WriteOutput values in the rotating frame are BlPitch commands + end do + + + CALL AllocAry( InitOut%RotFrame_u, 3, 'RotFrame_u', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( InitOut%IsLoad_u, 3, 'IsLoad_u', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL AllocAry( InitOut%LinNames_u, 3, 'LinNames_u', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + InitOut%LinNames_u(Indx_u_Yaw ) = 'Yaw, rad' + InitOut%LinNames_u(Indx_u_YawRate) = 'YawRate, rad/s' + InitOut%LinNames_u(Indx_u_HSS_Spd) = 'HSS_Spd, rad/s' + InitOut%RotFrame_u = .false. ! none of these are in the rotating frame + InitOut%IsLoad_u = .false. ! none of these linearization inputs are loads + + else + + p%TrimCase = TrimCase_none + + end if + + + !............................................................................................ + ! Define initialization-routine output here: + !............................................................................................ + CALL AllocAry( y%WriteOutput, p%NumOuts+p%NumOuts_DLL, 'WriteOutput', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + y%WriteOutput = 0 + + CALL AllocAry( InitOut%WriteOutputHdr, p%NumOuts+p%NumOuts_DLL, 'WriteOutputHdr', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + CALL AllocAry( InitOut%WriteOutputUnt, p%NumOuts+p%NumOuts_DLL, 'WriteOutputUnt', ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + do i=1,p%NumOuts + InitOut%WriteOutputHdr(i) = p%OutParam(i)%Name + InitOut%WriteOutputUnt(i) = p%OutParam(i)%Units + end do + + j=p%NumOuts + do i=1,p%NumOuts_DLL + j = j + 1 + InitOut%WriteOutputHdr(j) = m%dll_data%LogChannels_OutParam(i)%Name + InitOut%WriteOutputUnt(j) = m%dll_data%LogChannels_OutParam(i)%Units + end do + + InitOut%Ver = SrvD_Ver + + InitOut%UseHSSBrake = (p%HSSBrMode /= ControlMode_None .AND. p%THSSBrDp < InitInp%TMax) .or. p%HSSBrMode == ControlMode_DLL + + IF ( p%UseBladedInterface .OR. InitOut%UseHSSBrake ) THEN + InitOut%CouplingScheme = ExplicitLoose + ! CALL CheckError( ErrID_Info, 'The external dynamic-link library option being used in ServoDyn '& + ! //'requires an explicit-loose coupling scheme.' ) + ELSE + InitOut%CouplingScheme = ExplicitLoose + END IF + + + !............................................................................................ + ! Clean up the local variables: + !............................................................................................ + CALL SrvD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) + CALL TMD_DestroyInitInput(TMD_InitInp, ErrStat2, ErrMsg2 ) + CALL TMD_DestroyInitOutput(TMD_InitOut, ErrStat2, ErrMsg2 ) + + RETURN + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'SrvD_Init:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CALL SrvD_DestroyInputFile(InputFileData, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyInitInput(TMD_InitInp, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyInitOutput(TMD_InitOut, ErrStat3, ErrMsg3 ) + END IF + + END IF + + END SUBROUTINE CheckError +!---------------------------------------------------------------------------------------------------------------------------------- +END SUBROUTINE SrvD_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE SrvD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SrvD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(SrvD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Initial misc (optimization) variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + IF ( p%UseBladedInterface ) THEN + CALL BladedInterface_End(u, p, m, ErrStat, ErrMsg ) + END IF + + IF (p%CompNTMD) THEN + CALL TMD_End( u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, y%NTMD, m%NTMD, ErrStat, ErrMsg ) + END IF + + IF (p%CompTTMD) THEN + CALL TMD_End( u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, y%TTMD, m%TTMD, ErrStat, ErrMsg ) + END IF + + + ! Close files here: + + + ! Destroy the input data: + + CALL SrvD_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL SrvD_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL SrvD_DestroyContState( x, ErrStat, ErrMsg ) + CALL SrvD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL SrvD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL SrvD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + + ! Destroy the misc var data: + + CALL SrvD_DestroyMisc( m, ErrStat, ErrMsg ) + + + ! Destroy the output data: + + CALL SrvD_DestroyOutput( y, ErrStat, ErrMsg ) + + + + +END SUBROUTINE SrvD_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 SrvD_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(SrvD_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(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(SrvD_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 + + ! Local variables + TYPE(TMD_InputType),ALLOCATABLE :: u(:) ! Inputs at t + INTEGER(IntKi) :: i ! loop counter + INTEGER(IntKi) :: order + TYPE(SrvD_InputType) :: u_interp ! interpolated input + ! Local variables: + + + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_UpdateStates' + REAL(DbKi) :: t_next + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + !............................................................................................................................... + ! update states in TMD submodule, if necessary: + !............................................................................................................................... + + ! Convert Inputs(i)%NTMD and/or Inputs(i)%TTMD to u(:) + IF (p%CompNTMD .OR. p%CompTTMD) THEN + + order = SIZE(Inputs) + ALLOCATE(u(order), STAT=ErrStat2) + IF(ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Could not allocate TMD input array, u', ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + + ! Nacelle TMD + IF (p%CompNTMD) THEN + + DO i=1,order + CALL TMD_CopyInput( Inputs(i)%NTMD, u(i), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL TMD_UpdateStates( t, n, u, InputTimes, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, m%NTMD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! destroy these for the next call to TMD_UpdateStates (reset for tower TMD) + DO i=1,SIZE(u) + CALL TMD_DestroyInput(u(i), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END DO + + END IF + + + ! Tower TMD + IF (p%CompTTMD) THEN + + DO i=1,order + CALL TMD_CopyInput( Inputs(i)%TTMD, u(i), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END DO + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL TMD_UpdateStates( t, n, u, InputTimes, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, m%TTMD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + END IF + + END IF + + + !............................................................................................................................... + ! get inputs at t: + !............................................................................................................................... + CALL SrvD_CopyInput( Inputs(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL SrvD_Input_ExtrapInterp( Inputs, InputTimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !............................................................................................................................... + ! update discrete states: + !............................................................................................................................... + ! 1. Get appropriate value of input for the filter in discrete states (this works only for the DLL at this point, so we're going to move it there) + ! 2. Update control offset for trim solutions + + CALL SrvD_UpdateDiscState( t, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + !............................................................................................................................... + ! get inputs at t+dt: + !............................................................................................................................... + t_next = t+p%dt + + CALL SrvD_Input_ExtrapInterp( Inputs, InputTimes, u_interp, t_next, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (p%UseBladedInterface) THEN + CALL DLL_controller_call(t_next, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + END IF + + !............................................................................................................................... + ! update remaining states to values at t+dt: + !............................................................................................................................... + + ! Torque control: + CALL Torque_UpdateStates( t_next, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + ! Pitch control: + CALL Pitch_UpdateStates( t_next, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Yaw control: + CALL Yaw_UpdateStates( t_next, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Tip brake control: + CALL TipBrake_UpdateStates( t_next, u_interp, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + + + !................................................................... + ! Compute ElecPwr and GenTrq for controller (and DLL needs this saved): + !................................................................... + IF ( OtherState%GenOnLine .and. .not. OtherState%Off4Good ) THEN ! Generator is on line. + CALL CalculateTorque( t, u_interp, p, m, m%dll_data%GenTrq_prev, m%dll_data%ElecPwr_prev, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ELSE ! Generator is off line. + m%dll_data%GenTrq_prev = 0.0_ReKi + m%dll_data%ElecPwr_prev = 0.0_ReKi + ENDIF + + !............................................................................................................................... + CALL Cleanup() + + RETURN + +CONTAINS + SUBROUTINE Cleanup() + + IF (ALLOCATED(u)) THEN + DO i=1,SIZE(u) + CALL TMD_DestroyInput(u(i), ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + END DO + DEALLOCATE(u) + END IF + + CALL SrvD_DestroyInput(u_interp, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + END SUBROUTINE Cleanup + +END SUBROUTINE SrvD_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for deciding if Bladed-style DLL controller should be called +SUBROUTINE DLL_controller_call(t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_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 + + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'DLL_controller_call' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! we should be calling this routine ONLY when the following statement is true: + !IF ( p%UseBladedInterface ) THEN + + IF ( .NOT. EqualRealNos( t - m%dll_data%DLL_DT, m%LastTimeCalled ) ) THEN + IF (m%FirstWarn) THEN + IF ( EqualRealNos( p%DT, m%dll_data%DLL_DT ) ) THEN ! This must be because we're doing a correction step or calling multiple times per time step + CALL SetErrStat ( ErrID_Warn, 'BladedInterface option was designed for an explicit-loose '//& + 'coupling scheme. Using last calculated values from DLL on all subsequent calls until time is advanced. '//& + 'Warning will not be displayed again.', ErrStat, ErrMsg, RoutineName ) + ELSE ! this may be because of calling multiple times per time step, but most likely is because DT /= DLL_DT + CALL SetErrStat ( ErrID_Warn, 'Using last calculated values from DLL on all subsequent calls until next DLL_DT has been reached. '//& + 'Warning will not be displayed again.', ErrStat, ErrMsg, RoutineName ) + END IF + m%FirstWarn = .FALSE. + END IF + ELSE + m%dll_data%PrevBlPitch(1:p%NumBl) = m%dll_data%BlPitchCom ! used for linear ramp of delayed signal + m%LastTimeCalled = t + + CALL BladedInterface_CalcOutput( t, u, p, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + m%dll_data%initialized = .true. + END IF + + !END IF + +END SUBROUTINE DLL_controller_call +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE SrvD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SrvD_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 + + ! Local variables + REAL(ReKi) :: AllOuts(0:MaxOutPts) ! All the the available output channels + INTEGER(IntKi) :: I ! Generic loop index + INTEGER(IntKi) :: K ! Blade index + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CalcOutput' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + IF (p%CompNTMD) THEN + CALL TMD_CalcOutput( t, u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, y%NTMD, m%NTMD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (p%CompTTMD) THEN + CALL TMD_CalcOutput( t, u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, y%TTMD, m%TTMD, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + + !............................................................................................................................... + ! Get the demanded values from the external Bladed dynamic link library, if necessary: + !............................................................................................................................... + IF ( p%UseBladedInterface ) THEN + + ! Initialize the DLL controller in CalcOutput ONLY if it hasn't already been initialized in SrvD_UpdateStates + IF (.NOT. m%dll_data%initialized) THEN + CALL DLL_controller_call(t, u, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + ! Commanded Airfoil UserProp for blade (must be same units as given in AD15 airfoil tables) + ! This is passed to AD15 to be interpolated with the airfoil table userprop column + ! (might be used for airfoil flap angles for example) + y%BlAirfoilCom(1:p%NumBl) = m%dll_data%BlAirfoilCom(1:p%NumBl) + + IF (ALLOCATED(y%SuperController)) THEN + y%SuperController = m%dll_data%SCoutput + END IF + + END IF + + !............................................................................................................................... + ! Compute the outputs + !............................................................................................................................... + + ! Torque control: + CALL Torque_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ) ! calculates ElecPwr, which Pitch_CalcOutput will use in the user pitch routine + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Pitch control: + CALL Pitch_CalcOutput( t, u, p, x, xd, z, OtherState, y%BlPitchCom, y%ElecPwr, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Yaw control: + CALL Yaw_CalcOutput( t, u, p, x, xd, z, OtherState, y, m,ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Tip brake control: + CALL TipBrake_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + + + !............................................................................................................................... + ! Calculate all of the available output channels: + !............................................................................................................................... + ! This is overwriting the values if it was called from UpdateStates, but they + ! should be the same and this sets the values if we called the DLL above. + m%dll_data%ElecPwr_prev = y%ElecPwr + m%dll_data%GenTrq_prev = y%GenTrq + + !............................................................................................................................... + ! Calculate all of the available output channels: + !............................................................................................................................... +! AllOuts(Time) = t + + AllOuts(GenTq) = 0.001*y%GenTrq + AllOuts(GenPwr) = 0.001*y%ElecPwr + AllOuts(HSSBrTqC)= 0.001*y%HSSBrTrqC + + DO K=1,p%NumBl + AllOuts( BlPitchC(K) ) = y%BlPitchCom(K)*R2D + AllOuts( BlAirfoilC(K) ) = y%BlAirfoilCom(K) + END DO + + AllOuts(YawMomCom) = -0.001*y%YawMom + + AllOuts(NTMD_XQ ) = x%NTMD%tmd_x(1) + AllOuts(NTMD_XQD) = x%NTMD%tmd_x(2) + AllOuts(NTMD_YQ ) = x%NTMD%tmd_x(3) + AllOuts(NTMD_YQD) = x%NTMD%tmd_x(4) + + AllOuts(TTMD_XQ ) = x%TTMD%tmd_x(1) + AllOuts(TTMD_XQD) = x%TTMD%tmd_x(2) + AllOuts(TTMD_YQ ) = x%TTMD%tmd_x(3) + AllOuts(TTMD_YQD) = x%TTMD%tmd_x(4) + + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) array with the proper sign: + !............................................................................................................................... + + DO I = 1,p%NumOuts ! Loop through all selected output channels + + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + + ENDDO ! I - All selected output channels + + DO I = 1,p%NumOuts_DLL ! Loop through all DLL logging channels + y%WriteOutput(I+p%NumOuts) = m%dll_data%LogChannels( I ) + ENDDO + + RETURN +END SUBROUTINE SrvD_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +SUBROUTINE SrvD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + TYPE(SrvD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CalcContStateDeriv' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + dxdt%DummyContState = 0.0_ReKi + + IF (p%CompNTMD) THEN + CALL TMD_CalcContStateDeriv( t, u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, m%NTMD, dxdt%NTMD, ErrStat, ErrMsg ) + END IF + + IF (p%CompTTMD) THEN + CALL TMD_CalcContStateDeriv( t, u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, m%TTMD, dxdt%TTMD, ErrStat, ErrMsg ) + END IF + + +END SUBROUTINE SrvD_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for updating discrete states. +SUBROUTINE SrvD_UpdateDiscState( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_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 + + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_UpdateDiscState' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + select case (p%TrimCase) + case (TrimCase_yaw) + xd%CtrlOffset = xd%CtrlOffset + (u%RotSpeed - p%RotSpeedRef) * sign(p%TrimGain, p%YawNeut + xd%CtrlOffset) + case (TrimCase_torque, TrimCase_pitch) + xd%CtrlOffset = xd%CtrlOffset + (u%RotSpeed - p%RotSpeedRef) * p%TrimGain +! case default +! xd%CtrlOffset = 0.0_ReKi ! same as initialized value + end select + + + !xd%BlPitchFilter = p%BlAlpha * xd%BlPitchFilter + (1.0_ReKi - p%BlAlpha) * u%BlPitch + + !if ( p%PCMode == ControlMode_DLL ) then + ! if ( p%DLL_Ramp ) then + ! temp = (t - m%LastTimeCalled) / m%dll_data%DLL_DT + ! temp = m%dll_data%PrevBlPitch(1:p%NumBl) + & + ! temp * ( m%dll_data%BlPitchCom(1:p%NumBl) - m%dll_data%PrevBlPitch(1:p%NumBl) ) + ! else + ! temp = m%dll_data%BlPitchCom(1:p%NumBl) + ! end if + ! + ! xd%BlPitchFilter = p%BlAlpha * xd%BlPitchFilter + (1.0_ReKi - p%BlAlpha) * temp + !else + ! + !end if + + + + ! ! Update discrete states here: + !IF (p%CompNTMD) THEN + ! CALL TMD_UpdateDiscState( t, u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, m%NTMD, ErrStat, ErrMsg ) + !END IF + + ! ! Update discrete states here: + !IF (p%CompTTMD) THEN + ! CALL TMD_UpdateDiscState( t, u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, m%TTMD, ErrStat, ErrMsg ) + !END IF + + +END SUBROUTINE SrvD_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for solving for the residual of the constraint state equations. +SUBROUTINE SrvD_CalcConstrStateResidual( t, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + TYPE(SrvD_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 + + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CalcConstrStateResidual' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the constraint states here: + + !IF (p%CompNTMD) THEN + ! CALL TMD_CalcConstrStateResidual( t, u%NTMD, p%NTMD, x%NTMD, xd%NTMD, z%NTMD, OtherState%NTMD, m%NTMD, z_residual%NTMD, ErrStat, ErrMsg ) + !END IF + + !IF (p%CompTTMD) THEN + ! CALL TMD_CalcConstrStateResidual( t, u%TTMD, p%TTMD, x%TTMD, xd%TTMD, z%TTMD, OtherState%TTMD, m%TTMD, z_residual%TTMD, ErrStat, ErrMsg ) + !END IF + + z_residual%DummyConstrState = 0.0_ReKi + + +END SUBROUTINE SrvD_CalcConstrStateResidual + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 derivative dY/du is returned. +SUBROUTINE SrvD_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(SrvD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SrvD_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(SrvD_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 the inputs (u) [intent in to avoid deallocation] + 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) with respect to inputs (u) [intent in to avoid deallocation] + 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 + REAL(R8Ki) :: AllOuts(3,1:MaxOutPts) ! All the the available output channels + REAL(R8Ki) :: GenTrq_du, ElecPwr_du ! derivatives of generator torque and electrical power w.r.t. u%HSS_SPD + INTEGER(IntKi) :: I ! Generic loop index + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_JacobianPInput' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + IF ( PRESENT( dYdu ) ) THEN + + !> \f{equation}{ \frac{\partial Y}{\partial u} = \begin{bmatrix} + !! \frac{\partial Y_{BlPitchCom_1}}{\partial u_{Yaw}} & \frac{\partial Y_{BlPitchCom_1}}{\partial u_{YawRate}} & \frac{\partial Y_{BlPitchCom_1}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{BlPitchCom_2}}{\partial u_{Yaw}} & \frac{\partial Y_{BlPitchCom_2}}{\partial u_{YawRate}} & \frac{\partial Y_{BlPitchCom_2}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{BlPitchCom_3}}{\partial u_{Yaw}} & \frac{\partial Y_{BlPitchCom_3}}{\partial u_{YawRate}} & \frac{\partial Y_{BlPitchCom_3}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{YawMom}}{\partial u_{Yaw}} & \frac{\partial Y_{YawMom}}{\partial u_{YawRate}} & \frac{\partial Y_{YawMom}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{GenTrq}}{\partial u_{Yaw}} & \frac{\partial Y_{GenTrq}}{\partial u_{YawRate}} & \frac{\partial Y_{GenTrq}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{ElecPwr}}{\partial u_{Yaw}} & \frac{\partial Y_{ElecPwr}}{\partial u_{YawRate}} & \frac{\partial Y_{ElecPwr}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{WriteOutput_i}}{\partial u_{Yaw}} & \frac{\partial Y_{WriteOutput_i}}{\partial u_{YawRate}} & \frac{\partial Y_{WriteOutput_i}}{\partial u_{HSS\_Spd}} \end{bmatrix} + !! = \begin{bmatrix} + !! 0 & 0 & 0 \\ + !! 0 & 0 & 0 \\ + !! 0 & 0 & 0 \\ + !! \frac{\partial Y_{YawMom}}{\partial u_{Yaw}} & \frac{\partial Y_{YawMom}}{\partial u_{YawRate}} & 0 \\ + !! 0 & 0 & \frac{\partial Y_{GenTrq}}{\partial u_{HSS\_Spd}} \\ + !! 0 & 0 & \frac{\partial Y_{ElecPwr}}{\partial u_{HSS\_Spd}} \\ + !! \frac{\partial Y_{WriteOutput_i}}{\partial u_{Yaw}} & \frac{\partial Y_{WriteOutput_i}}{\partial u_{YawRate}} & \frac{\partial Y_{WriteOutput_i}}{\partial u_{HSS\_Spd}} \end{bmatrix} + !!\f} + + + ! Note this is similiar to SrvD_CalcOutput + + if (.not. allocated(dYdu)) then + call allocAry(dYdu, SrvD_Indx_Y_WrOutput+p%NumOuts, 3, 'dYdu', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + dYdu = 0.0_R8Ki + + + ! ! Torque control: + !> Compute + !> \f$ \frac{\partial Y_{GenTrq}}{\partial u_{HSS\_Spd}} \f$ and + !> \f$ \frac{\partial Y_{ElecPwr}}{\partial u_{HSS\_Spd}} \f$ in servodyn::torque_jacobianpinput. + call Torque_JacobianPInput( t, u, p, x, xd, z, OtherState, m, GenTrq_du, ElecPwr_du, ErrStat, ErrMsg ) ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + dYdu(SrvD_Indx_Y_GenTrq, Indx_u_HSS_Spd) = GenTrq_du + dYdu(SrvD_Indx_Y_ElecPwr,Indx_u_HSS_Spd) = ElecPwr_du + + + ! Pitch control: + !> \f$ \frac{\partial Y_{BlPitchCom_k}}{\partial u} = 0 \f$ + + ! Yaw control: + !> \f$ \frac{\partial Y_{YawMom}}{\partial u_{Yaw}} = -p\%YawSpr \f$ + dYdu(SrvD_Indx_Y_YawMom,Indx_u_Yaw) = -p%YawSpr ! from Yaw_CalcOutput + !> \f$ \frac{\partial Y_{YawMom}}{\partial u_{YawRate}} = -p\%YawDamp \f$ + dYdu(SrvD_Indx_Y_YawMom,Indx_u_YawRate) = -p%YawDamp ! from Yaw_CalcOutput + + + !......................................................................................................................... + ! Calculate all of the available output channels (because they repeat for the derivative) here: + !......................................................................................................................... + AllOuts = 0.0_R8Ki ! all variables not specified below are zeros (either constant or disabled): + + AllOuts(:, GenTq) = 0.001_R8Ki*dYdu(SrvD_Indx_Y_GenTrq,:) + AllOuts(:, GenPwr) = 0.001_R8Ki*dYdu(SrvD_Indx_Y_ElecPwr,:) + AllOuts(:, YawMomCom) = -0.001_R8Ki*dYdu(SrvD_Indx_Y_YawMom,:) + + !............................................................................................................................... + ! Place the selected output channels into the WriteOutput(:) portion of the jacobian with the proper sign: + !............................................................................................................................... + + DO I = 1,p%NumOuts ! Loop through all selected output channels + dYdu(I+SrvD_Indx_Y_WrOutput,:) = p%OutParam(I)%SignM * AllOuts( :, p%OutParam(I)%Indx ) + ENDDO ! I - All selected output channels + + 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( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + + +END SUBROUTINE SrvD_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. +!! Note SrvD does not have continuous states, so these are not set. +SUBROUTINE SrvD_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(SrvD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SrvD_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(SrvD_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 SrvD_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. +!! Note SrvD does not have discrete states, so these are not set. +SUBROUTINE SrvD_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(SrvD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SrvD_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(SrvD_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 SrvD_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. +!! Note SrvD does not have constraint states, so these are not set. +SUBROUTINE SrvD_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(SrvD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SrvD_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(SrvD_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 SrvD_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE SrvD_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(SrvD_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SrvD_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(SrvD_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) :: i + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_GetOP' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + !.......................................... + IF ( PRESENT( u_op ) ) THEN + + if (.not. allocated(u_op)) then + CALL AllocAry( u_op, 3, 'u_op', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + u_op(Indx_u_Yaw ) = u%Yaw + u_op(Indx_u_YawRate) = u%YawRate + u_op(Indx_u_HSS_Spd) = u%HSS_Spd + + END IF + + !.......................................... + IF ( PRESENT( y_op ) ) THEN + + if (.not. allocated(y_op)) then + CALL AllocAry( y_op, SrvD_Indx_Y_WrOutput+p%NumOuts, 'y_op', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) RETURN + end if + + + do i=1,size(SrvD_Indx_Y_BlPitchCom) + y_op(SrvD_Indx_Y_BlPitchCom(i)) = y%BlPitchCom(i) + end do + y_op(SrvD_Indx_Y_YawMom) = y%YawMom + y_op(SrvD_Indx_Y_GenTrq) = y%GenTrq + y_op(SrvD_Indx_Y_ElecPwr) = y%ElecPwr + do i=1,p%NumOuts + y_op(i+SrvD_Indx_Y_WrOutput) = 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 + + END IF + + IF ( PRESENT( z_op ) ) THEN + + END IF + +END SUBROUTINE SrvD_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reads the input file and stores all the data in the SrvD_InputFile structure. +!! It does not perform data validation. +SUBROUTINE SrvD_ReadInput( InitInp, InputFileData, Default_DT, OutFileRoot, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + TYPE(SrvD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + REAL(DbKi), INTENT(IN) :: Default_DT !< The default DT (from glue code) + + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of all the output files written by this routine. + + TYPE(SrvD_InputFile), INTENT(OUT) :: InputFileData !< Data stored in the module's input file + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_ReadInput' + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = '' + + InputFileData%DT = Default_DT ! the glue code's suggested DT for the module (may be overwritten in ReadPrimaryFile()) + + ! get the primary/platform input-file data + + CALL ReadPrimaryFile( InitInp, InputFileData, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + RETURN + END IF + + + + ! we may need to read additional files here (e.g., Bladed Interface) + + + ! close any echo file that was opened + + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + + +END SUBROUTINE SrvD_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary ServoDyn input file and places the values it reads in the InputFileData structure. +!! It opens and prints to an echo file if requested. +SUBROUTINE ReadPrimaryFile( InitInp, InputFileData, OutFileRoot, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(OUT) :: UnEc !< I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + TYPE(SrvD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of the echo file, possibly opened in this routine + + TYPE(SrvD_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the ServoDyn input file + + ! Local variables: + REAL(ReKi) :: TmpRAry(2) ! A temporary array to read a table from the input file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2, IOS ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + CHARACTER(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") + CHARACTER(*), PARAMETER :: RoutineName = 'ReadPrimaryFile' + + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InitInp%InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InitInp%InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + DO + !-------------------------- HEADER --------------------------------------------- + + CALL ReadCom( UnIn, InitInp%InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadStr( UnIn, InitInp%InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + !---------------------- SIMULATION CONTROL -------------------------------------- + + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Simulation Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Echo - Echo input to "<RootName>.ech". + + CALL ReadVar( UnIn, InitInp%InputFile, Echo, 'Echo', 'Echo switch', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, SrvD_Ver ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(SrvD_Ver%Name)//' primary input file "'//TRIM( InitInp%InputFile )//'":' + + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL CheckError( ErrID_Fatal, 'Error rewinding file "'//TRIM(InitInp%InputFile)//'".' ) + RETURN + END IF + + END DO + + IF (NWTC_VerboseLevel == NWTC_Verbose) THEN + CALL WrScr( ' Heading of the '//TRIM(SrvD_Ver%Name)//' input file: ' ) + CALL WrScr( ' '//TRIM( FTitle ) ) + END IF + + + ! DT - Communication interval for controllers (s): + CALL ReadVar( UnIn, InitInp%InputFile, Line, "DT", "Communication interval for controllers (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DT + READ( Line, *, IOSTAT=IOS) InputFileData%DT + CALL CheckIOS ( IOS, InitInp%InputFile, 'DT', NumType, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2, ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + + !---------------------- PITCH CONTROL ------------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Pitch Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! PCMode - Pitch control mode (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%PCMode, "PCMode", "Pitch control mode (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TPCOn - Time to enable active pitch control [unused when PCMode=0] (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TPCOn, "TPCOn", "Time to enable active pitch control (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TPitManS - Time to start override pitch maneuver for blade (K) and end standard pitch control (s): + CALL ReadAryLines( UnIn, InitInp%InputFile, InputFileData%TPitManS, SIZE(InputFileData%TPitManS), "TPitManS", & + "Time to start override pitch maneuver for blade K and end standard pitch control (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! PitManRat - Pitch rates at which override pitch maneuvers head toward final pitch angles (degrees/s) (read in deg/s and converted to radians/s here): + CALL ReadAryLines( UnIn, InitInp%InputFile, InputFileData%PitManRat, SIZE(InputFileData%PitManRat), "PitManRat", "Pitch rates at which override pitch maneuvers head toward final pitch angles (deg/s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%PitManRat = InputFileData%PitManRat*D2R + + ! BlPitchF - Blade (K) final pitch for pitch maneuvers (deg) (read from file in degrees and converted to radians here): + CALL ReadAryLines( UnIn, InitInp%InputFile, InputFileData%BlPitchF, SIZE(InputFileData%BlPitchF), "BlPitchF", "Blade K final pitch for pitch maneuvers (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%BlPitchF = InputFileData%BlPitchF*D2R + + + !---------------------- GENERATOR AND TORQUE CONTROL ---------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Generator and Torque Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! VSContrl - Variable-speed control mode {0: none, 1: simple VS, 3: user-defined from routine UserVSCont, 4: user-defined from Simulink/LabVIEW} (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%VSContrl, "VSContrl", "Variable-speed control mode (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GenModel - Generator model {1: simple, 2: Thevenin, 3: user-defined from routine UserGen} [used only when VSContrl=0] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenModel, "GenModel", "Generator model {1: simple, 2: Thevenin, 3: user-defined from routine UserGen} [used only when VSContrl=0] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GenEff - Generator efficiency [ignored by the Thevenin and user-defined generator models] (%) (read in percent and converted to a fraction here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenEff, "GenEff", "Generator efficiency [ignored by the Thevenin and user-defined generator models] (%)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%GenEff = InputFileData%GenEff*0.01 + + ! GenTiStr - Method to start the generator {T: timed using TimGenOn, F: generator speed using SpdGenOn} (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenTiStr, "GenTiStr", "Method to start the generator {T: timed using TimGenOn, F: generator speed using SpdGenOn} (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GenTiStp - Method to stop the generator {T: timed using TimGenOf, F: when generator power = 0} (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenTiStp, "GenTiStp", "Method to stop the generator {T: timed using TimGenOf, F: when generator power = 0} (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! SpdGenOn - Generator speed to turn on the generator for a startup (HSS speed) [used only when GenTiStr=False] (rpm) (read in rpm and converted to rad/sec here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SpdGenOn, "SpdGenOn", "Generator speed to turn on the generator for a startup (HSS speed) [used only when GenTiStr=False] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%SpdGenOn = InputFileData%SpdGenOn*RPM2RPS + + ! TimGenOn - Time to turn on the generator for a startup [used only when GenTiStr=True] (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TimGenOn, "TimGenOn", "Time to turn on the generator for a startup [used only when GenTiStr=True] (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TimGenOf - Time to turn off the generator [used only when GenTiStp=True] (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TimGenOf, "TimGenOf", "Time to turn off the generator [used only when GenTiStp=True] (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- SIMPLE VARIABLE-SPEED TORQUE CONTROL -------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Simple Variable-Speed Torque Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! VS_RtGnSp - Rated generator speed for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (rpm) (read in rpm and converted to rad/sec here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%VS_RtGnSp, "VS_RtGnSp", "Rated generator speed for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%VS_RtGnSp = InputFileData%VS_RtGnSp*RPM2RPS + + ! VS_RtTq - Rated generator torque/constant generator torque in Region 3 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (N-m): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%VS_RtTq, "VS_RtTq", "Rated generator torque/constant generator torque in Region 3 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! VS_Rgn2K - Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (N-m/rpm^2) (read in N-m/rpm^2 and converted to N-m/(rad/s)^2 here: + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%VS_Rgn2K, "VS_Rgn2K", "Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] (N-m/rpm^2)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%VS_Rgn2K = InputFileData%VS_Rgn2K/( RPM2RPS**2 ) + + ! VS_SlPc - Rated generator slip percentage in Region 2 1/2 for simple variable-speed generator control [used only when VSContrl=1] (%) (read in percent and converted to a fraction here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%VS_SlPc, "VS_SlPc", "Rated generator slip percentage in Region 2 1/2 for simple variable-speed generator control [used only when VSContrl=1] (%)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%VS_SlPc = InputFileData%VS_SlPc*.01 + + !---------------------- SIMPLE INDUCTION GENERATOR ------------------------------ + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Simple Induction Generator', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! SIG_SlPc - Rated generator slip percentage [used only when VSContrl=0 and GenModel=1] (%) (read in percent and converted to a fraction here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SIG_SlPc, "SIG_SlPc", "Rated generator slip percentage [used only when VSContrl=0 and GenModel=1] (%)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%SIG_SlPc = InputFileData%SIG_SlPc*.01 + + ! SIG_SySp - Synchronous (zero-torque) generator speed [used only when VSContrl=0 and GenModel=1] (rpm) (read in rpm and convert to rad/sec here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SIG_SySp, "SIG_SySp", "Synchronous (zero-torque) generator speed [used only when VSContrl=0 and GenModel=1] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%SIG_SySp = InputFileData%SIG_SySp*RPM2RPS + + + ! SIG_RtTq - Rated torque [used only when VSContrl=0 and GenModel=1] (N-m): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SIG_RtTq, "SIG_RtTq", "Rated torque [used only when VSContrl=0 and GenModel=1] (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! SIG_PORt - Pull-out ratio (Tpullout/Trated) [used only when VSContrl=0 and GenModel=1] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SIG_PORt, "SIG_PORt", "Pull-out ratio (Tpullout/Trated) [used only when VSContrl=0 and GenModel=1] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- THEVENIN-EQUIVALENT INDUCTION GENERATOR ----------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Thevenin-Equivalent Induction Generator', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_Freq - Line frequency [50 or 60] [used only when VSContrl=0 and GenModel=2] (Hz): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_Freq, "TEC_Freq", "Line frequency [50 or 60] [used only when VSContrl=0 and GenModel=2] (Hz)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_NPol - Number of poles [even integer > 0] [used only when VSContrl=0 and GenModel=2] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_NPol, "TEC_NPol", "Number of poles [even integer > 0] [used only when VSContrl=0 and GenModel=2] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_SRes - Stator resistance [used only when VSContrl=0 and GenModel=2] (ohms): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_SRes, "TEC_SRes", "Stator resistance [used only when VSContrl=0 and GenModel=2] (ohms)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_RRes - Rotor resistance [used only when VSContrl=0 and GenModel=2] (ohms): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_RRes, "TEC_RRes", "Rotor resistance [used only when VSContrl=0 and GenModel=2] (ohms)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_VLL - Line-to-line RMS voltage [used only when VSContrl=0 and GenModel=2] (volts): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_VLL, "TEC_VLL", "Line-to-line RMS voltage [used only when VSContrl=0 and GenModel=2] (volts)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_SLR - Stator leakage reactance [used only when VSContrl=0 and GenModel=2] (ohms): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_SLR, "TEC_SLR", "Stator leakage reactance [used only when VSContrl=0 and GenModel=2] (ohms)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_RLR - Rotor leakage reactance [used only when VSContrl=0 and GenModel=2] (ohms): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_RLR, "TEC_RLR", "Rotor leakage reactance [used only when VSContrl=0 and GenModel=2] (ohms)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TEC_MR - Magnetizing reactance [used only when VSContrl=0 and GenModel=2] (ohms): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TEC_MR, "TEC_MR", "Magnetizing reactance [used only when VSContrl=0 and GenModel=2] (ohms)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- HIGH-SPEED SHAFT BRAKE ---------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: High-Speed Shaft Brake', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! HSSBrMode - HSS brake model {0: none, 1: simple, 3: user-defined from routine UserHSSBr, 4: user-defined from LabVIEW} (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%HSSBrMode, "HSSBrMode", "HSS brake model {0: none, 1: simple, 3: user-defined from routine UserHSSBr, 4: user-defined from LabVIEW} (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! THSSBrDp - Time to initiate deployment of the HSS brake (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%THSSBrDp, "THSSBrDp", "Time to initiate deployment of the HSS brake (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! HSSBrDT - Time for HSS-brake to reach full deployment once initiated [used only when HSSBrMode=1] (sec): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%HSSBrDT, "HSSBrDT", "Time for HSS-brake to reach full deployment once initiated [used only when HSSBrMode=1] (sec)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! HSSBrTqF - Fully deployed HSS-brake torque (N-m): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%HSSBrTqF, "HSSBrTqF", "Fully deployed HSS-brake torque (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- YAW CONTROL --------------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Yaw Control', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! YCMode - Yaw control mode {0: none, 3: user-defined from routine UserYawCont, 4: user-defined from Simulink/LabVIEW} (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%YCMode, "YCMode", "Yaw control mode (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TYCOn - Time to enable active yaw control [unused when YCMode=0] (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TYCOn, "TYCOn", "Time to enable active yaw control [unused when YCMode=0] (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! YawNeut - Neutral yaw position--yaw spring force is zero at this yaw (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%YawNeut, "YawNeut", "Neutral yaw position--yaw spring force is zero at this yaw (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%YawNeut = InputFileData%YawNeut*D2R + + ! YawSpr - Nacelle-yaw spring constant (N-m/rad): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%YawSpr, "YawSpr", "Nacelle-yaw spring constant (N-m/rad)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! YawDamp - Nacelle-yaw constant (N-m/(rad/s)): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%YawDamp, "YawDamp", "Nacelle-yaw constant (N-m/(rad/s))", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TYawManS - Time to start override yaw maneuver and end standard yaw control (s): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TYawManS, "TYawManS", "Time to start override yaw maneuver and end standard yaw control (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! YawManRat - Yaw maneuver rate (in absolute value) (deg/s) (read in degrees/second and converted to radians/second here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%YawManRat, "YawManRat", "Yaw maneuver rate (in absolute value) (deg/s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%YawManRat = InputFileData%YawManRat*D2R + + ! NacYawF - Final yaw angle for override yaw maneuvers (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%NacYawF, "NacYawF", "Final yaw angle for override yaw maneuvers (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%NacYawF = InputFileData%NacYawF*D2R + + + !---------------------- TUNED MASS DAMPER ---------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Tuned Mass Damper', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! CompNTMD - Compute nacelle tuned mass damper {true/false} (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%CompNTMD, "CompNTMD", "Compute nacelle tuned mass damper {true/false} (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! NTMDfile - Name of the file for nacelle tuned mass damper (quoted string) [unused when CompNTMD is false]: + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%NTMDfile, "NTMDfile", "Name of the file for nacelle tuned mass dampe [unused when CompNTMD is false] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + IF ( PathIsRelative( InputFileData%NTMDfile ) ) InputFileData%NTMDfile = TRIM(PriPath)//TRIM(InputFileData%NTMDfile) + + ! CompTTMD - Compute tower tuned mass damper {true/false} (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%CompTTMD, "CompTTMD", "Compute tower tuned mass damper {true/false} (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TTMDfile - Name of the file for nacelle tuned mass damper (quoted string) [unused when CompNTMD is false]: + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TTMDfile, "TTMDfile", "Name of the file for tower tuned mass dampe [unused when CompTTMD is false] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + IF ( PathIsRelative( InputFileData%TTMDfile ) ) InputFileData%TTMDfile = TRIM(PriPath)//TRIM(InputFileData%TTMDfile) + + + !---------------------- BLADED INTERFACE ---------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Bladed Interface', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + InputFileData%UseLegacyInterface = .true. + + ! DLL_FileName - Name of the Bladed DLL [used only with DLL Interface] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DLL_FileName, "DLL_FileName", "Name/location of the external library {.dll [Windows]} in the Bladed-DLL format [used only with DLL Interface] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + IF ( PathIsRelative( InputFileData%DLL_FileName ) ) InputFileData%DLL_FileName = TRIM(PriPath)//TRIM(InputFileData%DLL_FileName) + + ! DLL_InFile - Name of input file used in DLL [used only with DLL Interface] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DLL_InFile, "DLL_InFile", "Name of input file used in DLL [used only with DLL Interface] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + IF ( PathIsRelative( InputFileData%DLL_InFile ) ) InputFileData%DLL_InFile = TRIM(PriPath)//TRIM(InputFileData%DLL_InFile) + + ! DLL_ProcName - Name of procedure to be called in DLL [used only with DLL Interface] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DLL_ProcName, "DLL_ProcName", "Name of procedure to be called in DLL [used only with DLL Interface] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! DLL_DT - Communication interval for dynamic library (s): + InputFileData%DLL_DT = InputFileData%DT + CALL ReadVar( UnIn, InitInp%InputFile, Line, "DLL_DT", "Communication interval for dynamic library (s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL Conv2UC( Line ) + IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DLL_DT + READ( Line, *, IOSTAT=IOS) InputFileData%DLL_DT + CALL CheckIOS ( IOS, InitInp%InputFile, 'DLL_DT', NumType, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2, ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + ! DLL_Ramp - Whether a linear ramp should be used between DLL_DT time steps [introduces time shift when true] (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DLL_Ramp, "DLL_Ramp", "Whether a linear ramp should be used between DLL_DT time steps [introduces time shift when true]", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! BPCutoff - Cuttoff frequency for low-pass filter on blade pitch (Hz): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%BPCutoff, "BPCutoff", "Cuttoff frequency for low-pass filter on blade pitch (Hz)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! NacYaw_North - Reference yaw angle of the nacelle when the upwind end points due North (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%NacYaw_North, "NacYaw_North", "Reference yaw angle of the nacelle when the upwind end points due North (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%NacYaw_North = InputFileData%NacYaw_North*D2R + + ! Ptch_Cntrl - Record 28: Use individual pitch control {0: collective pitch; 1: individual pitch control} [used only with DLL Interface] (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Ptch_Cntrl, "Ptch_Cntrl", "Record 28: Use individual pitch control {0: collective pitch; 1: individual pitch control} [used only with DLL Interface] (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Ptch_SetPnt - Record 5: Below-rated pitch angle set-point [used only with DLL Interface] (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Ptch_SetPnt, "Ptch_SetPnt", "Record 5: Below-rated pitch angle set-point [used only with DLL Interface] (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%Ptch_SetPnt = InputFileData%Ptch_SetPnt*D2R + + ! Ptch_Min - Record 6: Minimum pitch angle [used only with DLL Interface] (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Ptch_Min, "Ptch_Min", "Record 6: Minimum pitch angle [used only with DLL Interface] (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%Ptch_Min = InputFileData%Ptch_Min*D2R + + ! Ptch_Max - Record 7: Maximum pitch angle [used only with DLL Interface] (deg) (read from file in degrees and converted to radians here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Ptch_Max, "Ptch_Max", "Record 7: Maximum pitch angle [used only with DLL Interface] (deg)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%Ptch_Max = InputFileData%Ptch_Max*D2R + + ! PtchRate_Min - Record 8: Minimum pitch rate (most negative value allowed) [used only with DLL Interface] (deg/s) (read from file in deg/s and converted to rad/s here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%PtchRate_Min, "PtchRate_Min", "Record 8: Minimum pitch rate (most negative value allowed) [used only with DLL Interface] (deg/s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%PtchRate_Min = InputFileData%PtchRate_Min*D2R + + ! PtchRate_Max - Record 9: Maximum pitch rate [used only with DLL Interface] (deg/s) (read from file in deg/s and converted to rad/s here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%PtchRate_Max, "PtchRate_Max", "Record 9: Maximum pitch rate [used only with DLL Interface] (deg/s)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%PtchRate_Max = InputFileData%PtchRate_Max*D2R + + ! Gain_OM - Record 16: Optimal mode gain [used only with DLL Interface] (Nm/(rad/s)^2): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Gain_OM, "Gain_OM", "Record 16: Optimal mode gain [used only with DLL Interface] (Nm/(rad/s)^2)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GenSpd_MinOM - Record 17: Minimum generator speed [used only with DLL Interface] (rpm) (read from file in rpm and converted to rad/s here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenSpd_MinOM, "GenSpd_MinOM", "Record 17: Minimum generator speed [used only with DLL Interface] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%GenSpd_MinOM = InputFileData%GenSpd_MinOM*RPM2RPS + + ! GenSpd_MaxOM - Record 18: Optimal mode maximum speed [used only with DLL Interface] (rpm) (read from file in rpm and converted to rad/s here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenSpd_MaxOM, "GenSpd_MaxOM", "Record 18: Optimal mode maximum speed [used only with DLL Interface] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%GenSpd_MaxOM = InputFileData%GenSpd_MaxOM*RPM2RPS + + ! GenSpd_Dem - Record 19: Demanded generator speed above rated [used only with DLL Interface] (rpm) (read from file in rpm and converted to rad/s here): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenSpd_Dem, "GenSpd_Dem", "Record 19: Demanded generator speed above rated [used only with DLL Interface] (rpm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + InputFileData%GenSpd_Dem = InputFileData%GenSpd_Dem*RPM2RPS + + ! GenTrq_Dem - Record 22: Demanded generator torque above rated [used only with DLL Interface] (Nm): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenTrq_Dem, "GenTrq_Dem", "Record 22: Demanded generator torque above rated [used only with DLL Interface] (Nm)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! GenPwr_Dem - Record 13: Demanded power [used only with DLL Interface] (W): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%GenPwr_Dem, "GenPwr_Dem", "Record 13: Demanded power [used only with DLL Interface] (W)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- BLADED INTERFACE TORQUE-SPEED LOOK-UP TABLE ------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Bladed Interface Torque-Speed Look-Up Table', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! DLL_NumTrq - Record 26: No. of points in torque-speed look-up table {0 = none and use the optimal mode PARAMETERs instead, nonzero = ignore the optimal mode PARAMETERs by setting Gain_OM (Record 16) to 0.0} (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DLL_NumTrq, "DLL_NumTrq", "Record 26: No. of points in torque-speed look-up table {0 = none and use the optimal mode PARAMETERs instead, nonzero = ignore the optimal mode PARAMETERs by setting Gain_OM (Record 16) to 0.0} (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( InputFileData%DLL_NumTrq > 0 ) THEN + CALL AllocAry( InputFileData%GenSpd_TLU, InputFileData%DLL_NumTrq, 'GenSpd_TLU', ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( InputFileData%GenTrq_TLU, InputFileData%DLL_NumTrq, 'GenTrq_TLU',ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF + + CALL ReadCom( UnIn, InitInp%InputFile, 'Table Header: Bladed Interface Torque-Speed Look-Up Table', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadCom( UnIn, InitInp%InputFile, 'Table Units: Bladed Interface Torque-Speed Look-Up Table', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + DO I=1,InputFileData%DLL_NumTrq + + CALL ReadAry( UnIn, InitInp%InputFile, TmpRAry, 2_IntKi, 'Line'//TRIM(Num2LStr(I)), 'Bladed Interface Torque-Speed Look-Up Table', & + ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + InputFileData%GenSpd_TLU( I) = TmpRAry(1)*RPM2RPS ! GenSpd_TLU - Records R:2:R+2*DLL_NumTrq-2: Generator speed values in look-up table (rpm) (read from file in rpm and converted to rad/s here) + InputFileData%GenTrq_TLU(I) = TmpRAry(2) ! GenTrq_TLU - Records R+1:2:R+2*DLL_NumTrq-1: Generator torque values in look-up table (Nm) + + END DO + + + !---------------------- OUTPUT -------------------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: Output', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! SumPrint - Print summary data to <RootName>.sum (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutFile - Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%OutFile, "OutFile", "Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! ! OutFileFmt - Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both): + !CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%OutFileFmt, "OutFileFmt", "Format for module tabular (time-marching) output: (1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + ! TabDelim - Flag to cause tab-delimited text output (delimited by space otherwise) (flag): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%TabDelim, "TabDelim", "Flag to cause tab-delimited text output (delimited by space otherwise) (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutFmt - Format used for module's text tabult output (except time); resulting field should be 10 characters (-): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%OutFmt, "OutFmt", "Format used for module's text tabular output (except time); resulting field should be 10 characters (-)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Tstart - Time to start module's tabular output (seconds): + CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%Tstart, "Tstart", "Time to start module's tabular output (seconds)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + ! + ! ! DecFact - Decimation factor for module's tabular output (1=output every step) (-): + !CALL ReadVar( UnIn, InitInp%InputFile, InputFileData%DecFact, "DecFact", "Decimation factor for module's tabular output (1=output every step) (-)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- OUTLIST -------------------------------------------- + CALL ReadCom( UnIn, InitInp%InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutList - List of user-requested output channels (-): + CALL ReadOutputList ( UnIn, InitInp%InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- END OF FILE ----------------------------------------- + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + CALL setErrStat(ErrID,Msg,ErrStat,ErrMsg,RoutineName) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the primary input file. +SUBROUTINE ValidatePrimaryData( InitInp, InputFileData, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables: + + TYPE(SrvD_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(SrvD_InputFile), INTENT(IN) :: InputFileData !< All the data in the ServoDyn input file + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + + ! local variables + INTEGER(IntKi) :: K ! Blade number + CHARACTER(*), PARAMETER :: RoutineName = 'ValidatePrimaryData' + INTEGER(IntKi) :: ErrStat2 !< Error status + CHARACTER(ErrMsgLen) :: ErrMsg2 !< temporary Error message if ErrStat /= ErrID_None + + + ErrStat = ErrID_None + ErrMsg = '' + + CALL Pitch_ValidateData() + CALL Yaw_ValidateData() + CALL TipBrake_ValidateData() + CALL Torque_ValidateData() + CALL HSSBr_ValidateData() + + ! Checks for linearization: + if ( InitInp%Linearize ) then + + if ( InputFileData%PCMode /= ControlMode_NONE ) & + call SetErrStat(ErrID_Fatal,"PCMode must be 0 for linearization.",ErrStat,ErrMsg,RoutineName) + if ( InputFileData%VSContrl /= ControlMode_NONE .and. InputFileData%VSContrl /= ControlMode_SIMPLE ) & + call SetErrStat(ErrID_Fatal,"VSContrl must be 0 or 1 for linearization.",ErrStat,ErrMsg,RoutineName) + if ( InputFileData%GenModel /= ControlMode_SIMPLE .and. InputFileData%GenModel /= ControlMode_ADVANCED ) & + call SetErrStat(ErrID_Fatal,"GenModel must be 1 or 2 for linearization.",ErrStat,ErrMsg,RoutineName) + + if ( .not. InputFileData%GenTiStr ) & + call SetErrStat(ErrID_Fatal,"GenTiStr must be TRUE for linearization.",ErrStat,ErrMsg,RoutineName) + if ( .not. InputFileData%GenTiStp ) & + call SetErrStat(ErrID_Fatal,"GenTiStp must be TRUE for linearization.",ErrStat,ErrMsg,RoutineName) + + if (InputFileData%HSSBrMode /= ControlMode_NONE) & + call SetErrStat(ErrID_Fatal,"HSSBrMode must be 0 for linearization.",ErrStat,ErrMsg,RoutineName) + if (InputFileData%YCMode /= ControlMode_NONE) & + call SetErrStat(ErrID_Fatal,"YCMode must be 0 for linearization.",ErrStat,ErrMsg,RoutineName) + + if (InputFileData%CompNTMD .or. InputFileData%CompTTMD) & + call SetErrStat(ErrID_Fatal,"TMD module is not currently allowed in linearization. CompNTMD and CompTTMD must be FALSE.",ErrStat,ErrMsg,RoutineName) + + if (InitInp%TrimCase /= TrimCase_none) then + if (InitInp%TrimCase /= TrimCase_yaw .and. InitInp%TrimCase /= TrimCase_torque .and. InitInp%TrimCase /= TrimCase_pitch) then + call SetErrStat(ErrID_Fatal,"Invalid value entered for TrimCase.",ErrStat,ErrMsg,RoutineName) + else + if (InitInp%TrimGain <= 0.0_ReKi) call SetErrStat(ErrID_Fatal,"TrimGain must be a positive number.",ErrStat,ErrMsg,RoutineName) + end if + end if + + end if + + +! this code was in FASTSimulink.f90 in FAST v7: + IF (Cmpl4SFun) THEN !warn if ServoDyn isn't going to use the inputs from the Simulink interface + IF (InputFileData%YCMode /= ControlMode_EXTERN) CALL SetErrStat( ErrID_Info, 'Yaw angle and rate are not commanded from Simulink model.', ErrStat, ErrMsg, RoutineName ) + IF (InputFileData%PCMode /= ControlMode_EXTERN) CALL SetErrStat( ErrID_Info, 'Pitch angles are not commanded from Simulink model.', ErrStat, ErrMsg, RoutineName ) + IF (InputFileData%VSContrl /= ControlMode_EXTERN) CALL SetErrStat( ErrID_Info, 'Generator torque and power are not commanded from Simulink model.', ErrStat, ErrMsg, RoutineName ) + IF (InputFileData%HSSBrMode /= ControlMode_EXTERN) CALL SetErrStat( ErrID_Info, 'HSS brake is not commanded from Simulink model.', ErrStat, ErrMsg, RoutineName ) + END IF + + RETURN + +CONTAINS + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine performs the checks on inputs for the pitch controller. + SUBROUTINE Pitch_ValidateData( ) + !............................................................................................................................... + + ! Check that the requested pitch control modes are valid: + + IF ( .NOT. Cmpl4SFun .AND. .NOT. Cmpl4LV ) THEN + + IF ( InputFileData%PCMode == ControlMode_EXTERN ) THEN + CALL SetErrStat( ErrID_Fatal, 'PCMode can equal '//TRIM(Num2LStr(ControlMode_EXTERN))//' only when ServoDyn is interfaced with Simulink or LabVIEW.'// & + ' Set PCMode to 0, 3, or 5 or interface ServoDyn with Simulink or LabVIEW.', ErrStat, ErrMsg, RoutineName ) + END IF + + END IF + + + IF ( InputFileData%PCMode /= ControlMode_NONE .and. InputFileData%PCMode /= ControlMode_USER ) THEN + IF ( InputFileData%PCMode /= ControlMode_EXTERN .and. InputFileData%PCMode /= ControlMode_DLL ) & + CALL SetErrStat( ErrID_Fatal, 'PCMode must be 0, 3, 4, or 5.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + + ! Time that pitch control is enabled: + + IF ( InputFileData%TPCOn < 0.0_DbKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TPCOn must not be negative.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + ! Make sure the number of blades in the simulation doesn't exceed 3: + + IF ( InitInp%NumBl > SIZE(InputFileData%TPitManS,1) ) CALL SetErrStat( ErrID_Fatal, 'Number of blades exceeds input values.', ErrStat, ErrMsg, RoutineName ) + + ! Check the pitch-maneuver start times and rates: + + DO K=1,MIN(InitInp%NumBl,SIZE(InputFileData%TPitManS)) + + IF ( InputFileData%TPitManS(K) < 0.0_DbKi ) & + CALL SetErrStat( ErrID_Fatal, 'TPitManS('//TRIM( Num2LStr( K ) )//') must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( EqualRealNos( InputFileData%PitManRat(K), 0.0_ReKi ) ) & + CALL SetErrStat( ErrID_Fatal, 'PitManRat('//TRIM( Num2LStr(K) )//') must not be 0.', ErrStat, ErrMsg, RoutineName ) + + ENDDO ! K + + +!??? IF ( ANY( p%BlPitchInit <= -pi ) .OR. ANY( p%BlPitchInit > pi ) ) THEN +! CALL SetErrStat( ErrID_Fatal, 'BlPitchInit('//TRIM( Num2LStr( K ) )//') must be in the range (-pi,pi] radians (i.e., (-180,180] degrees).' , ErrStat, ErrMsg, RoutineName ) + + + + END SUBROUTINE Pitch_ValidateData + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine performs the checks on inputs for the yaw controller. + SUBROUTINE Yaw_ValidateData( ) + !............................................................................................................................... + + ! checks for yaw control mode: + IF ( InputFileData%YCMode /= ControlMode_NONE .and. InputFileData%YCMode /= ControlMode_USER ) THEN + IF ( InputFileData%YCMode /= ControlMode_DLL .and. InputFileData%YCMode /= ControlMode_EXTERN ) & + CALL SetErrStat( ErrID_Fatal, 'YCMode must be 0, 3, 4 or 5.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + + ! Some special checks based on whether inputs will come from external source (e.g., Simulink, LabVIEW) + IF ( .NOT. Cmpl4SFun .AND. .NOT. Cmpl4LV ) THEN + + IF ( InputFileData%YCMode == ControlMode_EXTERN ) THEN + CALL SetErrStat( ErrID_Fatal, 'YCMode can equal '//TRIM(Num2LStr(ControlMode_EXTERN))//' only when ServoDyn is interfaced with Simulink or LabVIEW.'// & + ' Set YCMode to 0, 3, or 5 or interface ServoDyn with Simulink or LabVIEW.', ErrStat, ErrMsg, RoutineName ) + END IF + + END IF + + + ! Check the start time to enable yaw control mode: + + IF ( InputFileData%TYCOn < 0.0_DbKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'TYCOn must not be negative.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + + ! Check the nacelle-yaw-maneuver start times and rates: + IF ( InputFileData%TYawManS < 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'TYawManS must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( EqualRealNos( InputFileData%YawManRat, 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'YawManRat must not be 0.', ErrStat, ErrMsg, RoutineName ) + ! IF ( InputFileData%TYawManE < InputFileData%TYawManS ) CALL SetErrStat( ErrID_Fatal, 'TYawManE must not be less than TYawManS.', ErrStat, ErrMsg, RoutineName ) + + + ! Check the nacelle-yaw spring and damping constants: + + IF ( InputFileData%YawSpr < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'YawSpr must not be negative.' , ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%YawDamp < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'YawDamp must not be negative.', ErrStat, ErrMsg, RoutineName ) + + ! Check the neutral position: + IF ( InputFileData%YawNeut <= -pi .OR. InputFileData%YawNeut > pi ) & + CALL SetErrStat( ErrID_Fatal, 'YawNeut must be in the range (-pi, pi] radians (i.e., (-180,180] degrees).', ErrStat, ErrMsg, RoutineName ) + + + END SUBROUTINE Yaw_ValidateData + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine performs the checks on inputs for the tip brakes. + SUBROUTINE TipBrake_ValidateData( ) + !............................................................................................................................... + + !IF ( TBDrConN < 0.0 ) CALL ProgAbort ( ' TBDrConN must not be negative.' ) + !IF ( TBDrConD < TBDrConN ) CALL ProgAbort( ' TBDrConD must not be less than TBDrConN.' ) + !IF ( p%TpBrDT < 0.0_DbKi ) CALL ProgAbort ( ' TpBrDT must not be negative.' ) + + + !DO K=1,MIN(InitInp%NumBl,SIZE(InputFileData%TTpBrDp)) + ! IF ( InputFileData%TTpBrDp(K) < 0.0_DbKi ) & + ! CALL SetErrStat( ErrID_Fatal, 'TTpBrDp(' //TRIM( Num2LStr( K ) )//') must not be negative.', ErrStat, ErrMsg, RoutineName ) + ! IF ( InputFileData%TBDepISp(K) < 0.0_DbKi ) & + ! CALL SetErrStat( ErrID_Fatal, 'TBDepISp('//TRIM( Num2LStr( K ) )//') must not be negative.', ErrStat, ErrMsg, RoutineName ) + !ENDDO ! K + + + END SUBROUTINE TipBrake_ValidateData + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine performs the checks on inputs for the torque controller. + SUBROUTINE Torque_ValidateData( ) + !............................................................................................................................... + IF ( .NOT. Cmpl4SFun .AND. .NOT. Cmpl4LV ) THEN + + IF ( InputFileData%VSContrl == ControlMode_EXTERN ) THEN + CALL SetErrStat( ErrID_Fatal, 'VSContrl can equal '//TRIM(Num2LStr(ControlMode_EXTERN))//' only when ServoDyn is interfaced with Simulink or LabVIEW.'// & + ' Set VSContrl to 0, 1, 3, or 5 or interface ServoDyn with Simulink or LabVIEW.', ErrStat, ErrMsg, RoutineName ) + END IF + END IF + + + ! checks for generator and torque control: + IF ( InputFileData%VSContrl /= ControlMode_NONE .and. & + InputFileData%VSContrl /= ControlMode_SIMPLE .AND. InputFileData%VSContrl /= ControlMode_USER ) THEN + IF ( InputFileData%VSContrl /= ControlMode_DLL .AND. InputFileData%VSContrl /=ControlMode_EXTERN ) & + CALL SetErrStat( ErrID_Fatal, 'VSContrl must be either 0, 1, 3, 4, or 5.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + IF ( InputFileData%SpdGenOn < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'SpdGenOn must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TimGenOn < 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'TimGenOn must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TimGenOf < 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'TimGenOf must not be negative.', ErrStat, ErrMsg, RoutineName ) + ! IF ( InputFileData%TimGenOf < InputFileData%TimGenOn ) CALL SetErrStat( ErrID_Fatal, 'TimGenOf must not be before TimGenOn.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%GenEff < 0.0_ReKi .OR. InputFileData%GenEff > 1.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'GenEff must be in the range [0, 1] (i.e., [0, 100] percent)', ErrStat, ErrMsg, RoutineName ) + END IF + + + ! checks for variable-speed torque control: + IF ( InputFileData%VSContrl == ControlMode_SIMPLE ) THEN + IF ( InputFileData%VS_RtGnSp <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'VS_RtGnSp must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%VS_RtTq < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'VS_RtTq must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%VS_Rgn2K < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'VS_Rgn2K must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%VS_Rgn2K*InputFileData%VS_RtGnSp**2 > InputFileData%VS_RtTq ) & + CALL SetErrStat( ErrID_Fatal, 'VS_Rgn2K*VS_RtGnSp^2 must not be greater than VS_RtTq.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%VS_SlPc <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'VS_SlPc must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + + ! checks for generator models (VSControl == 0): + ELSE IF ( InputFileData%VSContrl == ControlMode_NONE ) THEN + + IF ( InputFileData%GenModel /= ControlMode_SIMPLE .AND. InputFileData%GenModel /= ControlMode_ADVANCED .AND. InputFileData%GenModel /= ControlMode_USER ) THEN + CALL SetErrStat( ErrID_Fatal, 'GenModel must be either 1, 2, or 3.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + ! checks for simple induction generator (VSControl=0 & GenModel=1): + IF ( InputFileData%GenModel == ControlMode_SIMPLE ) THEN + IF ( InputFileData%SIG_SlPc <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'SIG_SlPc must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%SIG_SySp <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'SIG_SySp must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%SIG_RtTq <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'SIG_RtTq must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%SIG_PORt < 1.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'SIG_PORt must not be less than 1.' , ErrStat, ErrMsg, RoutineName ) + + ! checks for Thevenin-equivalent induction generator (VSControl=0 & GenModel=2): + ELSE IF ( InputFileData%GenModel == ControlMode_ADVANCED ) THEN + IF ( InputFileData%TEC_Freq <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_Freq must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_NPol <= 0_IntKi .OR. MOD( InputFileData%TEC_NPol, 2_IntKi ) /= 0_IntKi ) & + CALL SetErrStat( ErrID_Fatal, 'TEC_NPol must be an even number greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_SRes <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_SRes must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_RRes <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_RRes must be greater than zero.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_VLL <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_VLL must be greater than zero.' , ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_SLR <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_SLR must be greater than zero.' , ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_RLR <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_RLR must be greater than zero.' , ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%TEC_MR <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TEC_MR must be greater than zero.' , ErrStat, ErrMsg, RoutineName ) + END IF + + END IF + + END SUBROUTINE Torque_ValidateData + !------------------------------------------------------------------------------------------------------------------------------- + !> This routine performs the checks on inputs for the high-speed shaft brake. + SUBROUTINE HSSBr_ValidateData( ) + + ! Some special checks based on whether inputs will come from external source (e.g., Simulink, LabVIEW) + IF ( .NOT. Cmpl4SFun .AND. .NOT. Cmpl4LV ) THEN + + IF ( InputFileData%HSSBrMode == ControlMode_EXTERN ) THEN + CALL SetErrStat( ErrID_Fatal, 'HSSBrMode can be '//TRIM(Num2LStr(ControlMode_EXTERN))//' only when implemented in Simulink or LabVIEW.', ErrStat, ErrMsg, RoutineName ) + ENDIF + + END IF + + ! checks for high-speed shaft brake: + IF ( InputFileData%HSSBrMode /= ControlMode_NONE .and. & + InputFileData%HSSBrMode /= ControlMode_SIMPLE .and. InputFileData%HSSBrMode /= ControlMode_USER ) THEN + IF ( InputFileData%HSSBrMode /= ControlMode_DLL .and. InputFileData%HSSBrMode /= ControlMode_EXTERN ) & + CALL SetErrStat( ErrID_Fatal, 'HSSBrMode must be 0, 1, 3, 4, or 5.', ErrStat, ErrMsg, RoutineName ) + END IF + IF ( InputFileData%THSSBrDp < 0.0_DbKi ) CALL SetErrStat( ErrID_Fatal, 'THSSBrDp must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%HSSBrDT < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'HSSBrDT must not be negative.', ErrStat, ErrMsg, RoutineName ) + IF ( InputFileData%HSSBrTqF < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'HSSBrTqF must not be negative.', ErrStat, ErrMsg, RoutineName ) + + END SUBROUTINE HSSBr_ValidateData + !------------------------------------------------------------------------------------------------------------------------------- +END SUBROUTINE ValidatePrimaryData +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets the parameters, based on the data stored in InputFileData. +SUBROUTINE SrvD_SetParameters( InputFileData, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SrvD_InputFile), INTENT(INOUT) :: InputFileData !< Data stored in the module's input file (intent OUT for MOVE_ALLOC) + TYPE(SrvD_ParameterType), INTENT(INOUT) :: p !< The module's parameter data + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! Local variables + REAL(ReKi) :: ComDenom ! Common denominator of variables used in the TEC model + REAL(ReKi) :: SIG_RtSp ! Rated speed + REAL(ReKi) :: TEC_K1 ! K1 term for Thevenin-equivalent circuit + REAL(ReKi) :: TEC_K2 ! K2 term for Thevenin-equivalent circuit + + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_SetParameters' + + + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + + p%DT = InputFileData%DT + + !............................................. + ! Pitch control parameters + !............................................. + + p%PCMode = InputFileData%PCMode + p%TPCOn = InputFileData%TPCOn + + CALL AllocAry( p%TPitManS, p%NumBl, 'TPitManS', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( p%BlPitchF, p%NumBl, 'BlPitchF', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry( p%PitManRat, p%NumBl, 'PitManRat', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + p%TPitManS = InputFileData%TPitManS(1:p%NumBl) + p%BlPitchF = InputFileData%BlPitchF(1:p%NumBl) + p%PitManRat = InputFileData%PitManRat(1:p%NumBl) + + !............................................. + ! Set generator and torque control parameters: + !............................................. + p%VSContrl = InputFileData%VSContrl + p%GenModel = InputFileData%GenModel + p%GenEff = InputFileData%GenEff + p%GenTiStr = InputFileData%GenTiStr + p%GenTiStp = InputFileData%GenTiStp + p%SpdGenOn = InputFileData%SpdGenOn + p%TimGenOn = InputFileData%TimGenOn + p%TimGenOf = InputFileData%TimGenOf + + + p%THSSBrFl = InputFileData%THSSBrDp + InputFileData%HSSBrDT ! Time at which shaft brake is fully deployed + + SELECT CASE ( p%VSContrl ) + CASE ( ControlMode_NONE ) ! None + + IF ( p%GenModel == ControlMode_SIMPLE ) THEN ! Simple induction generator + + SIG_RtSp = InputFileData%SIG_SySp*( 1.0 + InputFileData%SIG_SlPc ) ! Rated speed + p%SIG_POSl = InputFileData%SIG_PORt*( SIG_RtSp - InputFileData%SIG_SySp ) ! Pullout slip + p%SIG_POTq = InputFileData%SIG_RtTq*InputFileData%SIG_PORt ! Pullout torque + p%SIG_Slop = InputFileData%SIG_RtTq/( SIG_RtSp - InputFileData%SIG_SySp ) ! SIG torque/speed slope + + p%SIG_SySp = InputFileData%SIG_SySp + ELSEIF ( p%GenModel == ControlMode_ADVANCED ) THEN ! Thevenin-equivalent induction generator + + ComDenom = InputFileData%TEC_SRes**2 + ( InputFileData%TEC_SLR + InputFileData%TEC_MR )**2 ! common denominator used in many of the following equations + + p%TEC_Re1 = InputFileData%TEC_SRes*( InputFileData%TEC_MR**2 )/ComDenom ! Thevenin's equivalent stator resistance (ohms) + p%TEC_Xe1 = InputFileData%TEC_MR*( InputFileData%TEC_SRes**2 + InputFileData%TEC_SLR* & + ( InputFileData%TEC_SLR + InputFileData%TEC_MR) )/ComDenom ! Thevenin's equivalent stator leakage reactance (ohms) + p%TEC_V1a = InputFileData%TEC_MR*InputFileData%TEC_VLL/SQRT( 3.0*ComDenom ) ! Thevenin equivalent source voltage + p%TEC_SySp = 4.0*Pi*InputFileData%TEC_Freq/InputFileData%TEC_NPol ! Thevenin equivalent synchronous speed + TEC_K1 = ( p%TEC_Xe1 + InputFileData%TEC_RLR )**2 ! Thevenin equivalent K1 term + TEC_K2 = ( InputFileData%TEC_MR**2 )/ComDenom ! Thevenin equivalent K2 term + p%TEC_A0 = InputFileData%TEC_RRes*TEC_K2/p%TEC_SySp ! Thevenin equivalent A0 term + p%TEC_C0 = InputFileData%TEC_RRes**2 ! Thevenin equivalent C0 term + p%TEC_C1 = -2.0*p%TEC_Re1*InputFileData%TEC_RRes ! Thevenin equivalent C1 term + p%TEC_C2 = p%TEC_Re1**2 + TEC_K1 ! Thevenin equivalent C2 term + + p%TEC_MR = InputFileData%TEC_MR + p%TEC_RLR = InputFileData%TEC_RLR + p%TEC_RRes = InputFileData%TEC_RRes + p%TEC_SRes = InputFileData%TEC_SRes + p%TEC_VLL = InputFileData%TEC_VLL + + ENDIF + + + CASE ( ControlMode_SIMPLE ) ! Simple variable-speed control + + p%VS_SySp = InputFileData%VS_RtGnSp/( 1.0 + InputFileData%VS_SlPc ) ! Synchronous speed of region 2 1/2 induction generator. + IF ( InputFileData%VS_SlPc < SQRT(EPSILON(InputFileData%VS_SlPc) ) ) THEN ! We don't have a region 2 so we'll use VS_TrGnSp = VS_RtGnSp + p%VS_Slope = 9999.9 + p%VS_TrGnSp = InputFileData%VS_RtGnSp + ELSE + p%VS_Slope = InputFileData%VS_RtTq /( InputFileData%VS_RtGnSp - p%VS_SySp ) ! Torque/speed slope of region 2 1/2 induction generator. + IF ( ABS(InputFileData%VS_Rgn2K) < EPSILON(InputFileData%VS_SlPc) ) THEN ! .TRUE. if the Region 2 torque is flat, and thus, the denominator in the ELSE condition is zero + p%VS_TrGnSp = p%VS_SySp ! Transitional generator speed between regions 2 and 2 1/2. + ELSE ! .TRUE. if the Region 2 torque is quadratic with speed + p%VS_TrGnSp = ( p%VS_Slope - SQRT( p%VS_Slope*( p%VS_Slope - 4.0*InputFileData%VS_Rgn2K*p%VS_SySp ) ) ) & + / ( 2.0*InputFileData%VS_Rgn2K ) ! Transitional generator speed between regions 2 and 2 1/2. + ENDIF + END IF + + p%VS_Rgn2K = InputFileData%VS_Rgn2K + p%VS_RtGnSp = InputFileData%VS_RtGnSp + p%VS_RtTq = InputFileData%VS_RtTq + + END SELECT + + !............................................. + ! High-speed shaft brake parameters + !............................................. + p%HSSBrMode = InputFileData%HSSBrMode + p%THSSBrDp = InputFileData%THSSBrDp + p%HSSBrDT = InputFileData%HSSBrDT + p%HSSBrTqF = InputFileData%HSSBrTqF + + !............................................. + ! Nacelle-yaw control parameters + !............................................. + p%YCMode = InputFileData%YCMode + p%TYCOn = InputFileData%TYCOn + p%YawNeut = InputFileData%YawNeut !bjj: this should be renamed... + p%YawSpr = InputFileData%YawSpr + p%YawDamp = InputFileData%YawDamp + + p%TYawManS = InputFileData%TYawManS + p%NacYawF = InputFileData%NacYawF + p%YawManRat = InputFileData%YawManRat ! we change the sign of this variable later + + !............................................. + ! tip-brake parameters (not used in this version) + !............................................. + CALL AllocAry( p%TBDepISp, p%NumBl, 'TBDepISp', ErrStat2, ErrMsg2 ) ! Deployment-initiation speed for the tip brakes + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + p%TBDepISp = HUGE(p%TBDepISp) ! Deployment-initiation speed for the tip brakes: basically never deploy them. Eventually this will be added back? + !p%TBDepISp = InputFileData%TBDepISp*RPM2RPS + + p%TpBrDT = HUGE(p%TpBrDT) ! Time for tip brakes to reach full deployment, once deployed + p%TBDrConN = 0.0_ReKi ! tip-drag constant during normal operation + p%TBDrConD = 0.0_ReKi ! tip-drag constant during fully deployed operation + + + !............................................. + ! Tuned-mass damper parameters + !............................................. + p%CompNTMD = InputFileData%CompNTMD + p%CompTTMD = InputFileData%CompTTMD + + !............................................. + ! Determine if the BladedDLL should be called + !............................................. + + IF ( p%PCMode == ControlMode_DLL .OR. & + p%YCMode == ControlMode_DLL .OR. & + p%VSContrl == ControlMode_DLL .OR. & + p%HSSBrMode == ControlMode_DLL ) THEN + + p%UseBladedInterface = .TRUE. + + ELSE + p%UseBladedInterface = .FALSE. + END IF + + !............................................. + ! Parameters for file output (not including Bladed DLL logging outputs) + !............................................. + p%NumOuts = InputFileData%NumOuts + p%NumOuts_DLL = 0 ! set to zero and overwritten if/when the DLL uses it + + CALL SetOutParam(InputFileData%OutList, p, ErrStat2, ErrMsg2 ) ! requires: p%NumOuts, p%NumBl; sets: p%OutParam. + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF ( InputFileData%TabDelim ) THEN + p%Delim = TAB + ELSE + p%Delim = ' ' + END IF + + +END SUBROUTINE SrvD_SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing the yaw output: a yaw moment. This routine is used in both loose and tight coupling. +SUBROUTINE Yaw_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SrvD_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 + + ! local variables + REAL(ReKi) :: YawPosCom ! Commanded yaw angle from user-defined routines, rad. + REAL(ReKi) :: YawRateCom ! Commanded yaw rate from user-defined routines, rad/s. + REAL(ReKi) :: YawPosComInt ! Integrated yaw commanded (from DLL), rad + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + !................................................................... + ! Override standard yaw control with a linear maneuver if necessary: + !................................................................... + + IF ( OtherState%BegYawMan ) THEN ! Override yaw maneuver is occuring. + + IF ( t >= OtherState%TYawManE ) THEN ! Override yaw maneuver has ended; yaw command is fixed at NacYawF + + YawPosCom = p%NacYawF + YawRateCom = 0.0_ReKi + + ELSE ! Override yaw maneuver in linear ramp + + ! Increment the command yaw and rate using YawManRat + YawRateCom = SIGN( p%YawManRat, p%NacYawF - OtherState%NacYawI ) ! Modify the sign of p%YawManRat based on the direction of the yaw maneuever + YawPosCom = OtherState%NacYawI + YawRateCom*( t - p%TYawManS ) + + ENDIF + + ELSE + + if (p%YCMode == ControlMode_DLL) then + if (m%dll_data%Yaw_Cntrl == GH_DISCON_YAW_CONTROL_TORQUE .or. m%dll_data%OverrideYawRateWithTorque) then + + y%YawMom = m%dll_data%YawTorqueDemand + + return + end if + end if + + !................................................................... + ! Calculate standard yaw position and rate commands: + !................................................................... + + YawPosComInt = OtherState%YawPosComInt ! get state value. We don't update the state here. + CALL CalculateStandardYaw(t, u, p, m, YawPosCom, YawRateCom, YawPosComInt, ErrStat, ErrMsg) + + END IF + !................................................................... + ! Calculate the yaw moment: + !................................................................... + + y%YawMom = - p%YawSpr *( u%Yaw - YawPosCom ) & ! {-f(qd,q,t)}SpringYaw + - p%YawDamp*( u%YawRate - YawRateCom ) ! {-f(qd,q,t)}DampYaw; + + + !................................................................... + ! Apply trim case for linearization: + ! prescribed yaw will be wrong in this case..... + !................................................................... + if (p%TrimCase==TrimCase_yaw) then + y%YawMom = y%YawMom + xd%CtrlOffset * p%YawSpr + end if + + +END SUBROUTINE Yaw_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine that calculates standard yaw position and rate commands: YawPosCom and YawRateCom. +SUBROUTINE CalculateStandardYaw(t, u, p, m, YawPosCom, YawRateCom, YawPosComInt, ErrStat, ErrMsg) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + REAL(ReKi), INTENT( OUT) :: YawPosCom !< Commanded yaw angle from user-defined routines, rad. + REAL(ReKi), INTENT( OUT) :: YawRateCom !< Commanded yaw rate from user-defined routines, rad/s. + REAL(ReKi), INTENT(INOUT) :: YawPosComInt !< Internal variable that integrates the commanded yaw rate and passes it to YawPosCom + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ErrStat = ErrID_None + ErrMsg = "" + + !................................................................... + ! Calculate standard yaw position and rate commands: + !................................................................... + + + IF ( t >= p%TYCOn .AND. p%YCMode /= ControlMode_NONE ) THEN ! Time now to enable active yaw control. + + + SELECT CASE ( p%YCMode ) ! Which yaw control mode are we using? (we already took care of ControlMode_None) + + CASE ( ControlMode_SIMPLE ) ! Simple ... BJJ: THIS will be NEW + + + CASE ( ControlMode_USER ) ! User-defined from routine UserYawCont(). + + CALL UserYawCont ( u%Yaw, u%YawRate, u%WindDir, u%YawErr, p%NumBl, t, p%DT, p%RootName, YawPosCom, YawRateCom ) + + CASE ( ControlMode_EXTERN ) ! User-defined from Simulink or LabVIEW + + YawPosCom = u%ExternalYawPosCom + YawRateCom = u%ExternalYawRateCom + + CASE ( ControlMode_DLL ) ! User-defined yaw control from Bladed-style DLL + + YawPosComInt = YawPosComInt + m%dll_data%YawRateCom*p%DT ! Integrated yaw position + YawPosCom = YawPosComInt !bjj: was this: LastYawPosCom + YawRateCom*( ZTime - LastTime ) + YawRateCom = m%dll_data%YawRateCom + + if (m%dll_data%OverrideYawRateWithTorque .or. m%dll_data%Yaw_Cntrl == GH_DISCON_YAW_CONTROL_TORQUE) then + call SetErrStat(ErrID_Fatal, "Unable to calculate yaw rate control because yaw torque control (or override) was requested from DLL.", ErrStat, ErrMsg, "CalculateStandardYaw") + return + end if + + END SELECT + + + ELSE ! Do not control yaw, maintain initial (neutral) yaw angles + + YawPosCom = p%YawNeut + YawRateCom = 0.0_ReKi + + ENDIF + +END SUBROUTINE CalculateStandardYaw +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine updates the other states associated with the yaw controller: BegYawMan, NacYawI, and TYawManE. +SUBROUTINE Yaw_UpdateStates( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< t+dt + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t+dt + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + dt + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + dt + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + dt + TYPE(SrvD_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 + + ! local variables + REAL(ReKi) :: YawPosCom ! Commanded yaw angle from user-defined routines, rad. + REAL(ReKi) :: YawRateCom ! Commanded yaw rate from user-defined routines, rad/s. + REAL(ReKi) :: YawManRat ! Yaw maneuver rate, rad/s + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................................................... + ! Determine if override of standard yaw control with a linear maneuver is necessary: + !................................................................... + + IF ( t >= p%TYawManS ) THEN ! Override yaw maneuver is occuring. + + + IF ( .not. OtherState%BegYawMan ) THEN ! Override yaw maneuver is just beginning (possibly again). + + CALL CalculateStandardYaw(t, u, p, m, YawPosCom, YawRateCom, OtherState%YawPosComInt, ErrStat, ErrMsg) + + OtherState%NacYawI = YawPosCom !bjj: was u%Yaw ! Store the initial (current) yaw, at the start of the yaw maneuver + YawManRat = SIGN( p%YawManRat, p%NacYawF - OtherState%NacYawI ) ! Modify the sign of YawManRat based on the direction of the yaw maneuever + OtherState%TYawManE = p%TYawManS + ( p%NacYawF - OtherState%NacYawI ) / YawManRat ! Calculate the end time of the override yaw maneuver + + OtherState%BegYawMan = .TRUE. ! Let's remember when we stored this these values + + ENDIF + + ELSE + + !................................................................... + ! Update OtherState%YawPosComInt: + !................................................................... + CALL CalculateStandardYaw(t, u, p, m, YawPosCom, YawRateCom, OtherState%YawPosComInt, ErrStat, ErrMsg) + + ENDIF + + +END SUBROUTINE Yaw_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing the pitch output: blade pitch commands. This routine is used in both loose and tight coupling. +SUBROUTINE Pitch_CalcOutput( t, u, p, x, xd, z, OtherState, BlPitchCom, ElecPwr, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + REAL(ReKi), INTENT(INOUT) :: BlPitchCom(:) !< pitch outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + REAL(ReKi), INTENT(IN ) :: ElecPwr !< Electrical power (watts) + TYPE(SrvD_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 + + ! local variables + REAL(ReKi) :: factor + REAL(ReKi) :: PitManRat + INTEGER(IntKi) :: K ! counter for blades + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................................................... + ! Calculate standard pitch position and rate commands: + !................................................................... + ! Control pitch if requested: + + IF ( t >= p%TPCOn .AND. p%PCMode /= ControlMode_NONE ) THEN ! Time now to enable active pitch control. + + + SELECT CASE ( p%PCMode ) ! Which pitch control mode are we using? + + CASE ( ControlMode_SIMPLE ) ! Simple, built-in pitch-control routine. + + ! bjj: add this! + + CASE ( ControlMode_USER ) ! User-defined from routine PitchCntrl(). + + CALL PitchCntrl ( u%BlPitch, ElecPwr, u%LSS_Spd, u%TwrAccel, p%NumBl, t, p%DT, p%RootName, BlPitchCom ) + + CASE ( ControlMode_EXTERN ) ! User-defined from Simulink or LabVIEW. + + BlPitchCom = u%ExternalBlPitchCom ! copy entire array + + CASE ( ControlMode_DLL ) ! User-defined pitch control from Bladed-style DLL + + + if (p%DLL_Ramp) then + factor = (t - m%LastTimeCalled) / m%dll_data%DLL_DT + BlPitchCom = m%dll_data%PrevBlPitch(1:p%NumBl) + & + factor * ( m%dll_data%BlPitchCom(1:p%NumBl) - m%dll_data%PrevBlPitch(1:p%NumBl) ) + else + BlPitchCom = m%dll_data%BlPitchCom(1:p%NumBl) + end if + + ! update the filter state once per time step + IF ( EqualRealNos( t - p%DT, m%LastTimeFiltered ) ) THEN + m%xd_BlPitchFilter = p%BlAlpha * m%xd_BlPitchFilter + (1.0_ReKi - p%BlAlpha) * BlPitchCom + m%LastTimeFiltered = t + END IF + + BlPitchCom = p%BlAlpha * m%xd_BlPitchFilter + (1.0_ReKi - p%BlAlpha) * BlPitchCom + + END SELECT + + ELSE ! Do not control pitch yet, maintain initial pitch angles. + + ! Use the initial blade pitch angles: + + BlPitchCom = p%BlPitchInit + + ENDIF + + + !................................................................... + ! Override standard pitch control with a linear maneuver if necessary: + !................................................................... + + DO K = 1,p%NumBl ! Loop through all blades + + + IF ( OtherState%BegPitMan(K) ) THEN ! Override pitch maneuver is occuring for this blade. + + IF ( t >= OtherState%TPitManE(K) ) THEN ! Override pitch maneuver has ended, blade is locked at BlPitchF. + + BlPitchCom(K) = p%BlPitchF(K) + + ELSE + + PitManRat = SIGN( p%PitManRat(K), p%BlPitchF(K) - OtherState%BlPitchI(K) ) ! Modify the sign of PitManRat based on the direction of the pitch maneuever + BlPitchCom(K) = OtherState%BlPitchI(K) + PitManRat*( t - p%TPitManS(K) ) ! Increment the blade pitch using PitManRat + + END IF + + ENDIF + + + ENDDO ! K - blades + + !................................................................... + ! Apply trim case for linearization: + !................................................................... + if (p%TrimCase==TrimCase_pitch) then + BlPitchCom = BlPitchCom + xd%CtrlOffset + end if + + +END SUBROUTINE Pitch_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine updates the continuous and other states associated with the pitch controller: BegPitMan, BlPitchI, and TPitManE. +SUBROUTINE Pitch_UpdateStates( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< t+dt + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t+dt + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + dt + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + dt + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + dt + TYPE(SrvD_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 + + ! local variables + REAL(ReKi) :: PitManRat + INTEGER(IntKi) :: K ! counter for blades + + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................................................... + ! Override standard pitch control with a linear maneuver if necessary: + !................................................................... + + DO K = 1,p%NumBl ! Loop through all blades + + + IF ( t >= p%TPitManS(K) ) THEN ! Override pitch maneuver is occuring for this blade. + + + IF ( .not. OtherState%BegPitMan(K) ) THEN ! Override pitch maneuver is just beginning. + + OtherState%BlPitchI (K) = u%BlPitch(K) ! Store the initial (current) pitch, at the start of the pitch maneuver. + + PitManRat = SIGN( p%PitManRat(K), p%BlPitchF(K) - OtherState%BlPitchI(K) ) ! Modify the sign of PitManRat based on the direction of the pitch maneuever + OtherState%TPitManE (K) = p%TPitManS(K) + ( p%BlPitchF(K) - OtherState%BlPitchI(K) )/PitManRat ! Calculate the end time of the override pitch maneuver + + OtherState%BegPitMan(K) = .TRUE. + + ENDIF + + ENDIF + + ENDDO ! K - blades + + +END SUBROUTINE Pitch_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!********************************************************************************************************************************** +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! 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 05-Nov-2015 09:57:49. +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine checks to see if any requested output channel names (stored in the OutList(:)) are invalid. It returns a +!! warning if any of the channels are not available outputs from the module. +!! It assigns the settings for OutParam(:) (i.e, the index, name, and units of the output channels, WriteOutput(:)). +!! the sign is set to 0 if the channel is invalid. +!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here. +SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) ! The list out user-requested outputs + TYPE(SrvD_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 + + ! Local variables + + INTEGER :: ErrStat2 ! temporary (local) error status + INTEGER :: I ! 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) + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) + CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(22) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "BLAIRFLC1","BLAIRFLC2","BLAIRFLC3","BLFLAP1 ","BLFLAP2 ","BLFLAP3 ","BLPITCHC1", & + "BLPITCHC2","BLPITCHC3","GENPWR ","GENTQ ","HSSBRTQC ","NTMD_XQ ","NTMD_XQD ", & + "NTMD_YQ ","NTMD_YQD ","TTMD_XQ ","TTMD_XQD ","TTMD_YQ ","TTMD_YQD ","YAWMOM ", & + "YAWMOMCOM"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(22) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + BlAirFlC1 , BlAirFlC2 , BlAirFlC3 , BlAirFlC1 , BlAirFlC2 , BlAirFlC3 , BlPitchC1 , & + BlPitchC2 , BlPitchC3 , GenPwr , GenTq , HSSBrTqC , NTMD_XQ , NTMD_XQD , & + NTMD_YQ , NTMD_YQD , TTMD_XQ , TTMD_XQD , TTMD_YQ , TTMD_YQD , YawMomCom , & + YawMomCom /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(22) = (/ & ! This lists the units corresponding to the allowed parameters + "(-) ","(-) ","(-) ","(-) ","(-) ","(-) ","(deg) ", & + "(deg) ","(deg) ","(kW) ","(kN-m) ","(kN-m) ","(m) ","(m/s) ", & + "(m) ","(m/s) ","(m) ","(m/s) ","(m) ","(m/s) ","(kN-m) ", & + "(kN-m) "/) + + + ! Initialize values + ErrStat = ErrID_None + ErrMsg = "" + InvalidOutput = .FALSE. + + + ! Determine which inputs are not valid + + InvalidOutput(BlAirFlC3) = ( p%NumBl < 3 ) + InvalidOutput( BlPitchC3) = ( p%NumBl < 3 ) + InvalidOutput( NTMD_XQ) = ( .not. p%CompNTMD ) + InvalidOutput( NTMD_XQD) = ( .not. p%CompNTMD ) + InvalidOutput( NTMD_YQ) = ( .not. p%CompNTMD ) + InvalidOutput( NTMD_YQD) = ( .not. p%CompNTMD ) + InvalidOutput( TTMD_XQ) = ( .not. p%CompTTMD ) + InvalidOutput( TTMD_XQD) = ( .not. p%CompTTMD ) + InvalidOutput( TTMD_YQ) = ( .not. p%CompTTMD ) + InvalidOutput( TTMD_YQD) = ( .not. p%CompTTMD ) + + + !------------------------------------------------------------------------------------------------- + ! Allocate and set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag. + !------------------------------------------------------------------------------------------------- + + ALLOCATE ( p%OutParam(0:p%NumOuts) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the ServoDyn OutParam array.", ErrStat, ErrMsg, RoutineName ) + RETURN + ENDIF + + ! Set index, name, and units for the time output channel: + + p%OutParam(0)%Indx = Time + p%OutParam(0)%Name = "Time" ! OutParam(0) is the time channel by default. + p%OutParam(0)%Units = "(s)" + p%OutParam(0)%SignM = 1 + + + ! Set index, name, and units for all of the output channels. + ! If a selected output channel is not available by this module set ErrStat = ErrID_Warn. + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a "-", "_", "m", or "M" character indicating "minus". + + + CheckOutListAgain = .FALSE. + + IF ( INDEX( "-_", OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, "-TipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( "mM", OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + + + ! If it started with an "M" (CheckOutListAgain) we didn't find the value in our list (Indx < 1) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, "MTipDxc1" causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:OutStrLenM1), ValidParamAry ) + END IF + + + IF ( Indx > 0 ) THEN ! we found the channel name + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN ! but, it isn't valid for these settings + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) ! it's a valid output + END IF + ELSE ! this channel isn't valid + p%OutParam(I)%Indx = Time ! pick any valid channel (I just picked "Time" here because it's universal) + p%OutParam(I)%Units = "INVALID" + p%OutParam(I)%SignM = 0 ! multiply all results by zero + + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) + END IF + + END DO + + RETURN +END SUBROUTINE SetOutParam +!---------------------------------------------------------------------------------------------------------------------------------- +!End of code generated by Matlab script +!********************************************************************************************************************************** + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing the tip-brake output: TBDrCon. This routine is used in both loose and tight coupling. +SUBROUTINE TipBrake_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SrvD_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 + + ! local variables + INTEGER(IntKi) :: K ! counter for blades + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................................................... + ! Calculate standard tip brake commands: + !................................................................... + + DO K = 1,p%NumBl + + IF ( OtherState%BegTpBr(K) ) THEN ! The tip brakes have been deployed. + + y%TBDrCon(K) = p%TBDrConN + ( p%TBDrConD - p%TBDrConN ) * TBFract( t, OtherState%TTpBrDp(K), OtherState%TTpBrFl(K) ) + + ELSE ! The tip brakes haven't been deployed yet. + + y%TBDrCon(K) = p%TBDrConN + + ENDIF + + END DO +!returns TBDrCon, or N and D part of ElastoDyn, return 0<=TBFrac<=1, consistant with other controllers + +END SUBROUTINE TipBrake_CalcOutput +!------------------------------------------------------------------------------------------------------------------------------- +!> A math S-function for the fraction of tip brake drag between normal and fully deployed operation. +!! (This function was formerly part of RtHS.) +FUNCTION TBFract( t, BrakStrt, BrakEnd ) +!............................................................................................................................... + + IMPLICIT NONE + + ! Passed Variables: + + REAL(DbKi), INTENT(IN ) :: t !< Current time + REAL(DbKi), INTENT(IN ) :: BrakEnd !< Time at which brakes are fully deployed + REAL(DbKi), INTENT(IN ) :: BrakStrt !< Time at which brakes are first deployed + REAL(ReKi) :: TBFract !< This function. + + + ! Local Variables. + + REAL(DbKi) :: TmpVar ! A temporary variable + + + + IF ( t <= BrakStrt ) THEN + + TBFract = 0.0 + + ELSEIF ( t < BrakEnd ) THEN + + TmpVar = ( ( t - BrakStrt )/( BrakStrt - BrakEnd ) )**2 + TBFract = TmpVar*( 2.0 - TmpVar ) + + ELSE + + TBFract = 1.0 + + ENDIF + + RETURN +END FUNCTION TBFract +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine updates the other states of the tip brakes: BegTpBr, TTpBrDp, and TTpBrFl +SUBROUTINE TipBrake_UpdateStates( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< t+dt + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t+dt + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + dt + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + dt + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + dt + TYPE(SrvD_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 + + ! local variables + INTEGER(IntKi) :: K ! counter for blades + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !................................................................... + ! Determine if tip brakes should be deployed: + !................................................................... + + DO K = 1,p%NumBl + + IF ( .not. OtherState%BegTpBr(k) ) THEN ! The tip brakes have not been deployed yet + + IF ( u%RotSpeed >= p%TBDepISp(K) ) THEN ! The tip brakes deploy due to speed + + OtherState%BegTpBr(k) = .true. + OtherState%TTpBrDp(K) = t ! time first deployed (0%) + OtherState%TTpBrFl(K) = t + p%TpBrDT ! time fully deployed (100%) + + ENDIF + + END IF + + END DO + +END SUBROUTINE TipBrake_UpdateStates +!------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the drive-train torque outputs: GenTrq, ElecPwr, and HSSBrTrqC +SUBROUTINE Torque_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SrvD_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 + + ! Local variables: + + REAL(ReKi) :: HSSBrFrac ! Fraction of full braking torque {0 (off) <= HSSBrFrac <= 1 (full)} (-) + + + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + + + !................................................................................. + ! Calculate generator torque (y%GenTrq) and electrical power (y%ElecPwr): + !................................................................................. + + IF ( OtherState%GenOnLine .and. .not. OtherState%Off4Good ) THEN ! Generator is on line. + CALL CalculateTorque( t, u, p, m, y%GenTrq, y%ElecPwr, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + ELSE ! Generator is off line. + y%GenTrq = 0.0_ReKi + y%ElecPwr = 0.0_ReKi + ENDIF + + !................................................................... + ! Apply trim case for linearization: + !................................................................... + if (p%TrimCase == TrimCase_torque) then + y%GenTrq = y%GenTrq + xd%CtrlOffset + end if + + !................................................................................. + ! Calculate the magnitude of HSS brake torque from DLL controller + !................................................................................. + IF (p%HSSBrMode == ControlMode_DLL) THEN + + y%HSSBrTrqC = m%dll_data%HSSBrTrqDemand + + ELSE + + !................................................................................. + ! Calculate the fraction of applied HSS-brake torque, HSSBrFrac: + !................................................................................. + IF ( t <= p%THSSBrDp ) THEN ! HSS brake not deployed yet. + + HSSBrFrac = 0.0_ReKi + + ELSE ! HSS brake deployed. + + + SELECT CASE ( p%HSSBrMode ) ! Which HSS brake model are we using? + + CASE ( ControlMode_NONE) ! None + + HSSBrFrac = 0.0_ReKi + + CASE ( ControlMode_SIMPLE ) ! Simple built-in HSS brake model with linear ramp. + + IF ( t < p%THSSBrFl ) THEN ! Linear ramp + HSSBrFrac = ( t - p%THSSBrDp )/p%HSSBrDT + ELSE ! Full braking torque + HSSBrFrac = 1.0 + ENDIF + + CASE ( ControlMode_USER ) ! User-defined HSS brake model. + + CALL UserHSSBr ( y%GenTrq, y%ElecPwr, u%HSS_Spd, p%NumBl, t, p%DT, p%RootName, HSSBrFrac ) + + IF ( ( HSSBrFrac < 0.0_ReKi ) .OR. ( HSSBrFrac > 1.0_ReKi ) ) THEN ! 0 (off) <= HSSBrFrac <= 1 (full); else Abort. + ErrStat = ErrID_Fatal + ErrMsg = 'HSSBrFrac must be between 0.0 (off) and 1.0 (full) (inclusive). Fix logic in routine UserHSSBr().' + RETURN + END IF + + !!!CASE ( ControlMode_DLL ) ! User-defined HSS brake model from Bladed-style DLL + !!! + !!! HSSBrFrac = 1.0_ReKi ! just a placeholder, since it never reaches this case + + CASE ( ControlMode_EXTERN ) ! HSS brake model from LabVIEW. + + HSSBrFrac = u%ExternalHSSBrFrac + + ENDSELECT + + HSSBrFrac = MAX( MIN( HSSBrFrac, 1.0_ReKi ), 0.0_ReKi ) ! make sure we didn't get outside the acceptable range: 0 (off) <= HSSBrFrac <= 1 (full) + + ENDIF + + + ! Calculate the magnitude of HSS brake torque: + + !y%HSSBrTrqC = SIGN( HSSBrFrac*p%HSSBrTqF, u%HSS_Spd ) ! Scale the full braking torque by the brake torque fraction and make sure the brake torque resists motion. + y%HSSBrTrqC = HSSBrFrac*p%HSSBrTqF ! Scale the full braking torque by the brake torque fraction (don't worry about the sign here). + + END IF + + ! to avoid issues with ElastoDyn extrapolating between +/- p%HSSBrTqF, we're going to make this output always positive + y%HSSBrTrqC = ABS(y%HSSBrTrqC) + + RETURN + +END SUBROUTINE Torque_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine updates the other states of the torque control: GenOnLine, and Off4Good +SUBROUTINE Torque_UpdateStates( t, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< t+dt + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t+dt + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + dt + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + dt + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + dt + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + dt + TYPE(SrvD_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 + + + ! Local variables: + REAL(ReKi) :: GenTrq !< generator torque + REAL(ReKi) :: ElecPwr !< electrical power + + + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + + ! See if the generator is on line. + IF ( .not. OtherState%Off4Good ) THEN + + ! The generator is either on-line or has never been turned online. + + IF ( OtherState%GenOnLine ) THEN ! The generator is on-line. + + IF ( ( p%GenTiStp ) .AND. ( t > p%TimGenOf .OR. EqualRealNos(t,p%TimGenOf) ) ) THEN ! Shut-down of generator determined by time, TimGenOf + OtherState%Off4Good = .true. + ENDIF + + ELSE ! The generator has never been turned online. + + IF ( p%GenTiStr ) THEN ! Start-up of generator determined by time, TimGenOn + IF ( t > p%TimGenOn .OR. EqualRealNos(t,p%TimGenOn) ) THEN + OtherState%GenOnLine = .true. + END IF + ELSE ! Start-up of generator determined by HSS speed, SpdGenOn + IF ( u%HSS_Spd > p%SpdGenOn .OR. EqualRealNos(u%HSS_Spd, p%SpdGenOn) ) THEN + OtherState%GenOnLine = .true. + END IF + ENDIF + + ENDIF + + ENDIF + + + IF ( OtherState%GenOnLine .and. .not. OtherState%Off4Good ) THEN ! Generator is on line. + + ! Lets turn the generator offline for good if ( GenTiStp = .FALSE. ) .AND. ( ElecPwr <= 0.0 ): + + IF ( ( .NOT. p%GenTiStp ) ) then + + CALL CalculateTorque( t, u, p, m, GenTrq, ElecPwr, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + + IF ( ElecPwr <= 0.0_ReKi ) THEN ! Shut-down of generator determined by generator power = 0 + OtherState%Off4Good = .true. + END IF + + END IF + + ENDIF + +END SUBROUTINE Torque_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the drive-train torque (GenTrq, ElecPwr) assuming the generator is on. +SUBROUTINE CalculateTorque( t, u, p, m, GenTrq, ElecPwr, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + + REAL(ReKi), INTENT( OUT) :: GenTrq !< generator torque command + REAL(ReKi), INTENT( OUT) :: ElecPwr !< electrical power + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + COMPLEX(ReKi) :: Current1 ! Current passing through the stator (amps) + COMPLEX(ReKi) :: Current2 ! Current passing through the rotor (amps) + COMPLEX(ReKi) :: Currentm ! Magnitizing current (amps) + + REAL(ReKi) :: ComDenom ! Common denominator of variables used in the TEC model + REAL(ReKi) :: PwrLossS ! Power loss in the stator (watts) + REAL(ReKi) :: PwrLossR ! Power loss in the rotor (watts) + REAL(ReKi) :: PwrMech ! Mechanical power (watts) + REAL(ReKi) :: Slip ! Generator slip + REAL(ReKi) :: SlipRat ! Generator slip ratio + + REAL(ReKi) :: S2 ! SlipRat**2 + + character(*), parameter :: RoutineName = 'CalculateTorque' + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + GenTrq = 0.0_ReKi + ElecPwr = 0.0_ReKi + + + ! Are we doing simple variable-speed control, or using a generator model? + + SELECT CASE ( p%VSContrl ) ! Are we using variable-speed control? + + CASE ( ControlMode_NONE ) ! No variable-speed control. Using a generator model. + + + SELECT CASE ( p%GenModel ) ! Which generator model are we using? + + CASE ( ControlMode_SIMPLE ) ! Simple induction-generator model. + + + Slip = u%HSS_Spd - p%SIG_SySp + + IF ( ABS( Slip ) > p%SIG_POSl ) THEN + GenTrq = SIGN( p%SIG_POTq, Slip ) + ELSE + GenTrq = Slip*p%SIG_Slop + ENDIF + + ElecPwr = CalculateElecPwr( GenTrq, u, p ) + + + CASE ( ControlMode_ADVANCED ) ! Thevenin-equivalent generator model. + + + SlipRat = ( u%HSS_Spd - p%TEC_SySp )/p%TEC_SySp + + GenTrq = p%TEC_A0*(p%TEC_VLL**2)*SlipRat & + /( p%TEC_C0 + p%TEC_C1*SlipRat + p%TEC_C2*(SlipRat**2) ) + + ! trying to refactor so we don't divide by SlipRat, which may be 0 + ! jmj tells me I need not worry about ComDenom being zero because these equations behave nicely + S2 = SlipRat**2 + + ComDenom = ( SlipRat*p%TEC_Re1 - p%TEC_RRes )**2 + (SlipRat*( p%TEC_Xe1 + p%TEC_RLR ))**2 + Current2 = CMPLX( p%TEC_V1a*SlipRat*( SlipRat*p%TEC_Re1 - p%TEC_RRes )/ComDenom , & + -p%TEC_V1a*S2 *( p%TEC_Xe1 + p%TEC_RLR )/ComDenom ) + Currentm = CMPLX( 0.0_ReKi , -p%TEC_V1a/p%TEC_MR ) + Current1 = Current2 + Currentm + + PwrLossS = 3.0*( ( ABS( Current1 ) )**2 )*p%TEC_SRes + PwrLossR = 3.0*( ( ABS( Current2 ) )**2 )*p%TEC_RRes + + PwrMech = GenTrq*u%HSS_Spd + ElecPwr = PwrMech - PwrLossS - PwrLossR + + + CASE ( ControlMode_USER ) ! User-defined generator model. + + + ! CALL UserGen ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, DT, p%GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) + CALL UserGen ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%RootName, GenTrq, ElecPwr ) + + END SELECT + + + CASE ( ControlMode_SIMPLE ) ! Simple variable-speed control. + + + if ( u%HSS_Spd < 0.0_ReKi) then + if (.not. equalRealNos(u%HSS_Spd, 0.0_ReKi) ) then + call SetErrStat( ErrID_Fatal, "u%HSS_Spd is negative. Simple variable-speed control model "//& + "is not valid for motoring situations.", ErrStat, ErrMsg, RoutineName) + return + end if + end if + + ! Compute the generator torque, which depends on which region we are in: + + IF ( u%HSS_Spd >= p%VS_RtGnSp ) THEN ! We are in region 3 - torque is constant + GenTrq = p%VS_RtTq + ELSEIF ( u%HSS_Spd < p%VS_TrGnSp ) THEN ! We are in region 2 - torque is proportional to the square of the generator speed + GenTrq = p%VS_Rgn2K* (u%HSS_Spd**2) + ELSE ! We are in region 2 1/2 - simple induction generator transition region + GenTrq = p%VS_Slope*( u%HSS_Spd - p%VS_SySp ) + ENDIF + + + ! It's not possible to motor using this control scheme, so the generator efficiency is always subtractive. + + ElecPwr = GenTrq*u%HSS_Spd*p%GenEff + !y%ElecPwr = CalculateElecPwr( y%GenTrq, u, p ) + + CASE ( ControlMode_USER ) ! User-defined variable-speed control for routine UserVSCont(). + + + CALL UserVSCont ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%RootName, GenTrq, ElecPwr ) + + CASE ( ControlMode_DLL ) ! User-defined variable-speed control from Bladed-style DLL + + ! bjj: I believe this is how the old logic worked, but perhaps now we can be more clever about checking if the generator is off + + IF ( m%dll_data%GenState /= 0_IntKi ) THEN ! generator is on + + GenTrq = m%dll_data%GenTrq + ElecPwr = CalculateElecPwr( GenTrq, u, p ) + + ELSE ! generator is off + + GenTrq = 0.0_ReKi + ElecPwr = 0.0_ReKi + + END IF + + CASE ( ControlMode_EXTERN ) ! User-defined variable-speed control from Simulink or LabVIEW. + + GenTrq = u%ExternalGenTrq + ElecPwr = u%ExternalElecPwr + + END SELECT + + + ! Lets turn the generator offline for good if ( GenTiStp = .FALSE. ) .AND. ( ElecPwr <= 0.0 ): + + IF ( ( .NOT. p%GenTiStp ) .AND. ( ElecPwr <= 0.0_ReKi ) ) THEN ! Shut-down of generator determined by generator power = 0 + GenTrq = 0.0_ReKi + ElecPwr = 0.0_ReKi + ENDIF + + +END SUBROUTINE CalculateTorque +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the electrical power (ElecPwr) after the electrical generator torque (GenTrq) has been calculated. +FUNCTION CalculateElecPwr( GenTrq, u, p ) +!............................................................................................................................... +REAL(ReKi), INTENT(IN) :: GenTrq !< generator torque computed at t +TYPE(SrvD_InputType), INTENT(IN) :: u !< Inputs at t +TYPE(SrvD_ParameterType), INTENT(IN) :: p !< Parameters + +REAL(ReKi) :: CalculateElecPwr !< The result of this function + + !! The generator efficiency is either additive for motoring, + !! or subtractive for generating power. + + IF ( GenTrq >= 0.0_ReKi ) THEN + CalculateElecPwr = GenTrq * u%HSS_Spd * p%GenEff + ELSE + CalculateElecPwr = GenTrq * u%HSS_Spd / p%GenEff + ENDIF + +END FUNCTION CalculateElecPwr +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the partials with respect to inputs of the drive-train torque outputs: GenTrq and ElecPwr +SUBROUTINE Torque_JacobianPInput( t, u, p, x, xd, z, OtherState, m, GenTrq_du, ElecPwr_du, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SrvD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SrvD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SrvD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + REAL(R8Ki), INTENT( OUT) :: GenTrq_du !< partial derivative of generator torque output with respect to HSS_Spd input + REAL(R8Ki), INTENT( OUT) :: ElecPwr_du !< partial derivative of electrical power output with respect to HSS_Spd input + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + !................................................................................. + ! Calculate generator torque (y%GenTrq) and electrical power (y%ElecPwr): + !................................................................................. + + IF ( OtherState%GenOnLine .and. .not. OtherState%Off4Good ) THEN ! Generator is on line. + CALL CalculateTorqueJacobian( t, u, p, m, GenTrq_du, ElecPwr_du, ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) return + ELSE ! Generator is off line. + GenTrq_du = 0.0_R8Ki + ElecPwr_du = 0.0_R8Ki + ENDIF + + + !................................................................................. + ! Calculate the fraction of applied HSS-brake torque, HSSBrFrac: + !................................................................................. + ! we're ignorming HSSBrFrac in linearization + + RETURN + +END SUBROUTINE Torque_JacobianPInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates jacobians (with respect to u%HSS_Spd) of the drive-train torque (GenTrq, ElecPwr) assuming the generator is on. +SUBROUTINE CalculateTorqueJacobian( t, u, p, m, GenTrq_du, ElecPwr_du, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SrvD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SrvD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: m !< Misc (optimization) variables + + REAL(R8Ki), INTENT( OUT) :: GenTrq_du !< partial generator torque / partial u%HSS_Spd + REAL(R8Ki), INTENT( OUT) :: ElecPwr_du !< partialelectrical power / partial u%HSS_Spd + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables: + + REAL(R8Ki) :: Current1_r, Current1_r_du ! Current passing through the stator (amps) and its derivative w.r.t. u%HSS_Spd + REAL(R8Ki) :: Current1_i, Current1_i_du ! Current passing through the stator (amps) and its derivative w.r.t. u%HSS_Spd + REAL(R8Ki) :: Current2_r, Current2_r_du ! Current passing through the rotor (amps) and its derivative w.r.t. u%HSS_Spd + REAL(R8Ki) :: Current2_i, Current2_i_du ! Current passing through the rotor (amps) and its derivative w.r.t. u%HSS_Spd + + REAL(R8Ki) :: GenTrq ! generator torque + + REAL(R8Ki) :: ComDenom, ComDenom_du ! temporary variable (common denominator) + REAL(R8Ki) :: PwrLossS_du ! Power loss in the stator (watts) and its derivative w.r.t. u%HSS_Spd + REAL(R8Ki) :: PwrLossR_du ! Power loss in the rotor (watts) and its derivative w.r.t. u%HSS_Spd + REAL(R8Ki) :: PwrMech_du ! partial derivative of Mechanical power (watts) w.r.t. u%HSS_Spd + REAL(R8Ki) :: Slip ! Generator slip + REAL(R8Ki) :: SlipRat ! Generator slip ratio + + REAL(R8Ki) :: A, B, dAdu, dBdu + REAL(R8Ki) :: SlipRat_du ! temporary variables for computing derivatives + + !REAL(ReKi) :: S2 ! SlipRat**2 + + character(*), parameter :: RoutineName = 'CalculateTorqueJacobian' + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = '' + + GenTrq_du = 0.0_R8Ki + ElecPwr_du = 0.0_R8Ki + + + ! Are we doing simple variable-speed control, or using a generator model? + + SELECT CASE ( p%VSContrl ) ! Are we using variable-speed control? + + CASE ( ControlMode_NONE ) ! No variable-speed control. Using a generator model. + + + SELECT CASE ( p%GenModel ) ! Which generator model are we using? + + CASE ( ControlMode_SIMPLE ) ! Simple induction-generator model. + + Slip = u%HSS_Spd - p%SIG_SySp + + IF ( ABS( Slip ) > p%SIG_POSl ) THEN + GenTrq = SIGN( real(p%SIG_POTq,R8Ki), Slip ) + GenTrq_du = 0.0_R8Ki + ELSE + GenTrq = Slip*p%SIG_Slop + GenTrq_du = p%SIG_Slop + ENDIF + + ! Calculate the electrical powerF + ! As generator: ElecPwr = GenTrq * u%HSS_Spd * m%GenEff + ! As motor: ElecPwr = GenTrq * u%HSS_Spd / m%GenEff + IF ( GenTrq >= 0.0_R8Ki ) THEN + !ElecPwr = GenTrq * u%HSS_Spd * p%GenEff + ElecPwr_du = (GenTrq_du * u%HSS_Spd + GenTrq) * p%GenEff + ELSE + !ElecPwr = GenTrq * u%HSS_Spd / p%GenEff + ElecPwr_du = (GenTrq_du * u%HSS_Spd + GenTrq) / p%GenEff + ENDIF + + CASE ( ControlMode_ADVANCED ) ! Thevenin-equivalent generator model. + + SlipRat = ( u%HSS_Spd - p%TEC_SySp )/p%TEC_SySp + SlipRat_du = 1.0_R8Ki / p%TEC_SySp + + A = p%TEC_A0*(p%TEC_VLL**2)*SlipRat + B = p%TEC_C0 + p%TEC_C1*SlipRat + p%TEC_C2*(SlipRat**2) + + dAdu = p%TEC_A0*(p%TEC_VLL**2)*SlipRat_du + dBdu = p%TEC_C1*SlipRat_du + 2.0_R8Ki*p%TEC_C2*SlipRat*SlipRat_du + + GenTrq = A / B + GenTrq_du = dAdu / B - A/B**2 * dBdu + + + A = SlipRat*p%TEC_Re1 - p%TEC_RRes + B = SlipRat*( p%TEC_Xe1 + p%TEC_RLR ) + dAdu = SlipRat_du * p%TEC_Re1 + dBdu = SlipRat_du * (p%TEC_Xe1 + p%TEC_RLR) + + ComDenom = A**2 + B**2 + ComDenom_du = 2.0_R8Ki * A * dAdu + 2.0_R8Ki * B * dBdu + + + A = SlipRat**2*p%TEC_Re1 - SlipRat*p%TEC_RRes + dAdu = 2.0_R8Ki * SlipRat * SlipRat_du * p%TEC_Re1 - SlipRat_du * p%TEC_RRes + Current2_r = p%TEC_V1a*A/ComDenom + Current2_r_du = p%TEC_V1a*(dAdu/ComDenom - A/ComDenom**2 * ComDenom_du) + + Current2_i = -p%TEC_V1a*( p%TEC_Xe1 + p%TEC_RLR )*SlipRat**2/ComDenom + Current2_i_du = -p%TEC_V1a*( p%TEC_Xe1 + p%TEC_RLR ) * ( 2.0_R8Ki*SlipRat*SlipRat_du / ComDenom - SlipRat**2/(ComDenom**2) * ComDenom_du) + + Current1_r = Current2_r + Current1_i = Current2_i - p%TEC_V1a/p%TEC_MR + Current1_r_du = Current2_r_du + Current1_i_du = Current2_i_du + + + !PwrLossS = 3.0*( Current1_r**2 + Current1_i**2 )*p%TEC_SRes + PwrLossS_du = 3.0_R8Ki*p%TEC_SRes*( 2.0_R8Ki*Current1_r*Current1_r_du + 2.0_R8Ki*Current1_i*Current1_i_du ) + + !PwrLossR = 3.0*( Current2_r**2 + Current2_i**2 )*p%TEC_RRes + PwrLossR_du = 3.0_R8Ki*p%TEC_RRes*( 2.0_R8Ki*Current2_r*Current2_r_du + 2.0_R8Ki*Current2_i*Current2_i_du ) + + !PwrMech = GenTrq*u%HSS_Spd + PwrMech_du = GenTrq_du * u%HSS_Spd + GenTrq + + !ElecPwr = PwrMech - PwrLossS - PwrLossR + ElecPwr_du = PwrMech_du - PwrLossS_du - PwrLossR_du + + CASE ( ControlMode_USER ) ! User-defined generator model. + + ! we should not get here (initialization should have caught this issue) + + GenTrq_du = 0.0_R8Ki + ElecPwr_du = 0.0_R8Ki + + END SELECT + + + CASE ( ControlMode_SIMPLE ) ! Simple variable-speed control. + + + if ( u%HSS_Spd < 0.0_ReKi) then + if (.not. equalRealNos(u%HSS_Spd, 0.0_ReKi) ) then + call SetErrStat( ErrID_Fatal, "u%HSS_Spd is negative. Simple variable-speed control model "//& + "is not valid for motoring situations.", ErrStat, ErrMsg, RoutineName) + return + end if + end if + + ! Compute the generator torque, which depends on which region we are in: + + IF ( u%HSS_Spd >= p%VS_RtGnSp ) THEN ! We are in region 3 - torque is constant + GenTrq = p%VS_RtTq + GenTrq_du = 0.0_R8Ki + ELSEIF ( u%HSS_Spd < p%VS_TrGnSp ) THEN ! We are in region 2 - torque is proportional to the square of the generator speed + GenTrq = p%VS_Rgn2K* (u%HSS_Spd**2) + GenTrq_du = 2.0_R8Ki * p%VS_Rgn2K * u%HSS_Spd + ELSE ! We are in region 2 1/2 - simple induction generator transition region + GenTrq = p%VS_Slope*( u%HSS_Spd - p%VS_SySp ) + GenTrq_du = p%VS_Slope + ENDIF + + ! It's not possible to motor using this control scheme, so the generator efficiency is always subtractive. + + ElecPwr_du = (GenTrq_du * u%HSS_Spd + GenTrq) * p%GenEff + + + CASE ( ControlMode_USER , & ! User-defined variable-speed control for routine UserVSCont(). + ControlMode_DLL , & ! User-defined variable-speed control from Bladed-style DLL + ControlMode_EXTERN ) ! User-defined variable-speed control from Simulink or LabVIEW. + + ! we should not get here (initialization should have caught this issue) + + GenTrq_du = 0.0_R8Ki + ElecPwr_du = 0.0_R8Ki + + END SELECT + +END SUBROUTINE CalculateTorqueJacobian +!---------------------------------------------------------------------------------------------------------------------------------- + + + +END MODULE ServoDyn +!********************************************************************************************************************************** diff --git a/OpenFAST/modules/servodyn/src/ServoDyn_Driver.f90 b/OpenFAST/modules/servodyn/src/ServoDyn_Driver.f90 new file mode 100644 index 000000000..7ba7135f3 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/ServoDyn_Driver.f90 @@ -0,0 +1,191 @@ +!********************************************************************************************************************************** +!> ## ServoDyn_DriverCode: This code tests the template modules +!!.................................................................................................................................. +!! LICENSING +!! Copyright (C) 2016 National Renewable Energy Laboratory +!! +!! This file is part of ServoDyn. +!! +!! 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. +!********************************************************************************************************************************** +PROGRAM SrvD_Driver + + USE NWTC_Library + USE ServoDyn + USE ServoDyn_Types + + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 3 !< Number of inputs sent to SrvD_UpdateStates + + ! Program variables + + REAL(DbKi) :: Time !< Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval !< Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) !< Variable for storing time associated with inputs, in seconds + + TYPE(SrvD_InitInputType) :: InitInData !< Input data for initialization + TYPE(SrvD_InitOutputType) :: InitOutData !< Output data from initialization + + TYPE(SrvD_ContinuousStateType) :: x !< Continuous states + TYPE(SrvD_DiscreteStateType) :: xd !< Discrete states + TYPE(SrvD_ConstraintStateType) :: z !< Constraint states + TYPE(SrvD_ConstraintStateType) :: Z_residual !< Residual of the constraint state functions (Z) + TYPE(SrvD_OtherStateType) :: OtherState !< Other states + TYPE(SrvD_MiscVarType) :: misc !< Optimization variables + + TYPE(SrvD_ParameterType) :: p !< Parameters + TYPE(SrvD_InputType) :: u(NumInp) !< System inputs + TYPE(SrvD_OutputType) :: y !< System outputs + + + + INTEGER(IntKi) :: n !< Loop counter (for time step) + INTEGER(IntKi) :: j !< Loop counter (for interpolation time history) + INTEGER(IntKi) :: ErrStat !< Status of error message + CHARACTER(ErrMsgLen) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + REAL(R8Ki), allocatable :: dYdu(:,:) + INTEGER(IntKi) :: Un + INTEGER(IntKi) :: nMax + CHARACTER(1024) :: OutFile + CHARACTER(20) :: FlagArg !< Flag argument from command line + + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'ServoDyn_driver', '', '' ) + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + CALL NWTC_Init( ProgNameIN=version%Name ) + + ! Populate the InitInData data structure here: + + ! Check for command line arguments. + InitInData%InputFile = '' !'ServoDyn_input.dat' + CALL CheckArgs( InitInData%InputFile, Flag=FlagArg ) + IF ( LEN( TRIM(FlagArg) ) > 0 ) CALL NormStop() + + CALL GetRoot( InitInData%InputFile, OutFile ) + OutFile = trim(OutFile)//'.out' + + CALL GetNewUnit( Un, ErrStat, ErrMsg) + call OpenFOutFile ( Un, OutFile, ErrStat, ErrMsg ) + + ! Set the driver's request for time interval here: + + TimeInterval = 0.01 ! s + InitInData%InputFile = 'ServoDyn.dat' + InitInData%RootName = OutFile(1:(len_trim(OutFile)-4)) + InitInData%NumBl = 3 + InitInData%gravity = 9.81 !m/s^2 + InitInData%r_N_O_G = (/ 90.0, 0.0, 0.0 /) ! m, position of nacelle (for NTMD) + InitInData%r_TwrBase = (/ 0.0, 0.0, 0.0 /) ! m, position of tower base (for TTMD) + InitInData%TMax = 10.0 !s + InitInData%AirDens = 1.225 !kg/m^3 + InitInData%AvgWindSpeed = 10.0 !m/s + InitInData%Linearize = .false. + InitInData%NumSC2Ctrl = 0 + InitInData%NumCtrl2SC = 0 + + CALL AllocAry(InitInData%BlPitchInit, InitInData%NumBl, 'BlPitchInit', ErrStat, ErrMsg) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + InitInData%BlPitchInit = 5.0*pi/180.0 ! radians + + + ! Initialize the module + + CALL SrvD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, misc, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + IF (ErrStat >= AbortErrLev) call ProgAbort('') + END IF + + nMax = nint(InitInData%TMax/TimeInterval) + + + ! Destroy initialization data + + CALL SrvD_DestroyInitInput( InitInData, ErrStat, ErrMsg ) + CALL SrvD_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + + + Time = 0.0_ReKi + DO j = 1, NumInp + InputTime(j) = Time - j*TimeInterval + END DO + DO j = 2, NumInp + CALL SrvD_CopyInput (u(1), u(j), MESH_NEWCOPY, ErrStat, ErrMsg) + END DO + + !............................................................................................................................... + ! Check the results of the Jacobian routines + !............................................................................................................................... + + + CALL SrvD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + write(Un,'(600(ES15.5,1x))') Time, y%BlPitchCom, y%WriteOutput + + + + DO n = 0,nMax + + ! Modify u for inputs at n (likely from the outputs of another module or a set of test conditions) here: + DO j = NumInp-1, 1, -1 + CALL SrvD_CopyInput (u(j), u(j+1), MESH_UPDATECOPY, ErrStat, ErrMsg) + InputTime(j+1) = InputTime(j) + END DO + InputTime(1) = Time + u(1)%BlPitch = y%BlPitchCom + + !u(1)%HSS_Spd = (2000.0_ReKi)/nMax * RPM2RPS * n + + CALL SrvD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + ! Calculate outputs at n + Time = (n+1)*TimeInterval + CALL SrvD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + !call SrvD_JacobianPInput( Time, u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg, dYdu) + + !write(Un,'(100(ES15.5,1x))') u(1)%Yaw, u(1)%YawRate, u(1)%HSS_Spd, y%YawMom, y%GenTrq, y%ElecPwr, dYdu(4,1), dYdu(4,2), dYdu(5,3), dYdu(6,3) + write(Un,'(600(ES15.5,1x))') Time, y%BlPitchCom, y%WriteOutput + + END DO + close (un) + + + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL SrvD_End( u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + +END PROGRAM SrvD_Driver diff --git a/OpenFAST/modules/servodyn/src/ServoDyn_Registry.txt b/OpenFAST/modules/servodyn/src/ServoDyn_Registry.txt new file mode 100644 index 000000000..a157ab73e --- /dev/null +++ b/OpenFAST/modules/servodyn/src/ServoDyn_Registry.txt @@ -0,0 +1,394 @@ +################################################################################################################################### +# Registry for ServoDyn in the FAST Modularization Framework +# This Registry file is used to create MODULE ServoDyn_Types which contains all of the user-defined types needed in ServoDyn. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See the NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt +usefrom TMD_Registry.txt + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +typedef ServoDyn/SrvD InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ InitInputType IntKi NumBl - - - "Number of blades on the turbine" - +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ InitInputType ReKi BlPitchInit {:} - - "Initial blade pitch" - +typedef ^ InitInputType ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ InitInputType ReKi r_N_O_G {3} - - "nacelle origin for setting up mesh" m +typedef ^ InitInputType ReKi r_TwrBase {3} - - "tower base origin for setting up mesh" m +typedef ^ InitInputType DbKi Tmax - - - "max time from glue code" s +typedef ^ InitInputType ReKi AvgWindSpeed - - - "average wind speed for the simulation" m/s +typedef ^ InitInputType ReKi AirDens - - - "air density" kg/m^3 +typedef ^ InitInputType IntKi NumSC2Ctrl - - - "number of controller inputs [from supercontroller]" - +typedef ^ InitInputType IntKi NumCtrl2SC - - - "number of controller outputs [to supercontroller]" - +typedef ^ InitInputType IntKi TrimCase - - - "Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True]" - +typedef ^ InitInputType ReKi TrimGain - - - "Proportional gain for the rotational speed error (>0) [used only if TrimCase>0]" "rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque" +typedef ^ InitInputType ReKi RotSpeedRef - - - "Reference rotor speed" "rad/s" + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType IntKi CouplingScheme - - - "Switch that indicates if a particular coupling scheme is required" - +typedef ^ InitOutputType Logical UseHSSBrake - - - "flag to determine if high-speed shaft brake is potentially used (true=yes)" - +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" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - + +# ..... Input file data ........................................................................................................... +# This is data defined in the Input File for this module (or could otherwise be passed in) +# ..... Primary Input file data ........................................................................................................... +typedef ServoDyn/SrvD SrvD_InputFile DbKi DT - - - "Communication interval for controllers" s +typedef ^ SrvD_InputFile IntKi PCMode - - - "Pitch control mode" - +typedef ^ SrvD_InputFile DbKi TPCOn - - - "Time to enable active pitch control [unused when PCMode=0]" s +typedef ^ SrvD_InputFile DbKi TPitManS 3 - - "Time to start override pitch maneuver for blade (K) and end standard pitch control" s +typedef ^ SrvD_InputFile ReKi PitManRat 3 - - "Pitch rates at which override pitch maneuvers head toward final pitch angles" rad/s +typedef ^ SrvD_InputFile ReKi BlPitchF 3 - - "Blade (K) final pitch for pitch maneuvers" radians +typedef ^ SrvD_InputFile IntKi VSContrl - - - "Variable-speed control mode" - +typedef ^ SrvD_InputFile IntKi GenModel - - - "Generator model [used only when VSContrl=0]" - +typedef ^ SrvD_InputFile ReKi GenEff - - - "Generator efficiency [ignored by the Thevenin and user-defined generator models]" - +typedef ^ SrvD_InputFile LOGICAL GenTiStr - - - "Method to start the generator {T: timed using TimGenOn, F: generator speed using SpdGenOn}" - +typedef ^ SrvD_InputFile LOGICAL GenTiStp - - - "Method to stop the generator {T: timed using TimGenOf, F: when generator power = 0}" - +typedef ^ SrvD_InputFile ReKi SpdGenOn - - - "Generator speed to turn on the generator for a startup (HSS speed) [used only when GenTiStr=False]" rad/s +typedef ^ SrvD_InputFile DbKi TimGenOn - - - "Time to turn on the generator for a startup [used only when GenTiStr=True]" s +typedef ^ SrvD_InputFile DbKi TimGenOf - - - "Time to turn off the generator [used only when GenTiStp=True]" s +typedef ^ SrvD_InputFile ReKi VS_RtGnSp - - - "Rated generator speed for simple variable-speed generator control (HSS side) [used only when VSContrl=1]" rad/s +typedef ^ SrvD_InputFile ReKi VS_RtTq - - - "Rated generator torque/constant generator torque in Region 3 for simple variable-speed generator control (HSS side) [used only when VSContrl=1]" N-m +typedef ^ SrvD_InputFile ReKi VS_Rgn2K - - - "Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1]" N-m/(rad/s)^2 +typedef ^ SrvD_InputFile ReKi VS_SlPc - - - "Rated generator slip percentage in Region 2 1/2 for simple variable-speed generator control [used only when VSContrl=1]" - +typedef ^ SrvD_InputFile ReKi SIG_SlPc - - - "Rated generator slip percentage [used only when VSContrl=0 and GenModel=1]" - +typedef ^ SrvD_InputFile ReKi SIG_SySp - - - "Synchronous (zero-torque) generator speed [used only when VSContrl=0 and GenModel=1]" rad/s +typedef ^ SrvD_InputFile ReKi SIG_RtTq - - - "Rated torque [used only when VSContrl=0 and GenModel=1]" N-m +typedef ^ SrvD_InputFile ReKi SIG_PORt - - - "Pull-out ratio (Tpullout/Trated) [used only when VSContrl=0 and GenModel=1]" - +typedef ^ SrvD_InputFile ReKi TEC_Freq - - - "Line frequency [50 or 60] [used only when VSContrl=0 and GenModel=2]" Hz +typedef ^ SrvD_InputFile IntKi TEC_NPol - - - "Number of poles [even integer > 0] [used only when VSContrl=0 and GenModel=2]" - +typedef ^ SrvD_InputFile ReKi TEC_SRes - - - "Stator resistance [used only when VSContrl=0 and GenModel=2]" ohms +typedef ^ SrvD_InputFile ReKi TEC_RRes - - - "Rotor resistance [used only when VSContrl=0 and GenModel=2]" ohms +typedef ^ SrvD_InputFile ReKi TEC_VLL - - - "Line-to-line RMS voltage [used only when VSContrl=0 and GenModel=2]" volts +typedef ^ SrvD_InputFile ReKi TEC_SLR - - - "Stator leakage reactance [used only when VSContrl=0 and GenModel=2]" ohms +typedef ^ SrvD_InputFile ReKi TEC_RLR - - - "Rotor leakage reactance [used only when VSContrl=0 and GenModel=2]" ohms +typedef ^ SrvD_InputFile ReKi TEC_MR - - - "Magnetizing reactance [used only when VSContrl=0 and GenModel=2]" ohms +typedef ^ SrvD_InputFile IntKi HSSBrMode - - - "HSS brake model" - +typedef ^ SrvD_InputFile DbKi THSSBrDp - - - "Time to initiate deployment of the HSS brake" s +typedef ^ SrvD_InputFile DbKi HSSBrDT - - - "Time for HSS-brake to reach full deployment once initiated [used only when HSSBrMode=1]" s +typedef ^ SrvD_InputFile ReKi HSSBrTqF - - - "Fully deployed HSS-brake torque" N-m +typedef ^ SrvD_InputFile IntKi YCMode - - - "Yaw control mode" - +typedef ^ SrvD_InputFile DbKi TYCOn - - - "Time to enable active yaw control [unused when YCMode=0]" s +typedef ^ SrvD_InputFile ReKi YawNeut - - - "Neutral yaw position--yaw spring force is zero at this yaw" radians +typedef ^ SrvD_InputFile ReKi YawSpr - - - "Nacelle-yaw spring constant" N-m/rad +typedef ^ SrvD_InputFile ReKi YawDamp - - - "Nacelle-yaw constant" N-m/(rad/s) +typedef ^ SrvD_InputFile DbKi TYawManS - - - "Time to start override yaw maneuver and end standard yaw control" s +typedef ^ SrvD_InputFile ReKi YawManRat - - - "Yaw maneuver rate (in absolute value)" rad/s +typedef ^ SrvD_InputFile ReKi NacYawF - - - "Final yaw angle for override yaw maneuvers" radians +typedef ^ SrvD_InputFile LOGICAL SumPrint - - - "Print summary data to <RootName>.sum" - +typedef ^ SrvD_InputFile IntKi OutFile - - - "Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both)" - +typedef ^ SrvD_InputFile LOGICAL TabDelim - - - "Use tab delimiters in text tabular output file?" - +typedef ^ SrvD_InputFile CHARACTER(20) OutFmt - - - "Format used for text tabular output (except time)" - +#typedef ^ SrvD_InputFile IntKi OutFileFmt - - - "Format for module tabular (time-marching) output: {1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both}" - +typedef ^ SrvD_InputFile DbKi Tstart - - - "Time to start module's tabular output" s +typedef ^ SrvD_InputFile IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ SrvD_InputFile CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - + +typedef ^ SrvD_InputFile CHARACTER(1024) DLL_FileName - - - "Name of the DLL file including the full path" - +typedef ^ SrvD_InputFile CHARACTER(1024) DLL_ProcName - - - "Name of the procedure in the DLL that will be called" - +typedef ^ SrvD_InputFile CHARACTER(1024) DLL_InFile - - - "Name of input file used in DLL" - +typedef ^ SrvD_InputFile DbKi DLL_DT - - - "interval for calling DLL (must be integer multiple number of DT steps)" s +typedef ^ SrvD_InputFile LOGICAL DLL_Ramp - - - "whether the DLL pitch should be a ramp (true) or step change (false) when DLL_DT <> DT. If true, introduces a time delay." - +typedef ^ SrvD_InputFile ReKi BPCutoff - - - "The cutoff frequency for the blade pitch low-pass filter. Large values => no filter." Hz +typedef ^ SrvD_InputFile ReKi NacYaw_North - - - "Reference yaw angle of the nacelle when the upwind end points due North [used only with DLL Interface]" radians +typedef ^ SrvD_InputFile IntKi Ptch_Cntrl - - - "Record 28: Use individual pitch control {0: collective pitch; 1: individual pitch control} [used only with DLL Interface]" - +typedef ^ SrvD_InputFile ReKi Ptch_SetPnt - - - "Record 5: Below-rated pitch angle set-point [used only with DLL Interface]" radians +typedef ^ SrvD_InputFile ReKi Ptch_Min - - - "Record 6: Minimum pitch angle [used only with DLL Interface]" radians +typedef ^ SrvD_InputFile ReKi Ptch_Max - - - "Record 7: Maximum pitch angle [used only with DLL Interface]" radians +typedef ^ SrvD_InputFile ReKi PtchRate_Min - - - "Record 8: Minimum pitch rate (most negative value allowed) [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi PtchRate_Max - - - "Record 9: Maximum pitch rate [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi Gain_OM - - - "Record 16: Optimal mode gain [used only with DLL Interface]" Nm/(rad/s)^2 +typedef ^ SrvD_InputFile ReKi GenSpd_MinOM - - - "Record 17: Minimum generator speed [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi GenSpd_MaxOM - - - "Record 18: Optimal mode maximum speed [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi GenSpd_Dem - - - "Record 19: Demanded generator speed above rated [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi GenTrq_Dem - - - "Record 22: Demanded generator torque above rated [used only with DLL Interface]" Nm +typedef ^ SrvD_InputFile ReKi GenPwr_Dem - - - "Record 13: Demanded power [used only with DLL Interface]" W +typedef ^ SrvD_InputFile IntKi DLL_NumTrq - - - "Record 26: No. of points in torque-speed look-up table {0 = none and use the optimal mode PARAMETERs instead, nonzero = ignore the optimal mode PARAMETERs by setting Gain_OM (Record 16) to 0.0} [used only with DLL Interface]" - +typedef ^ SrvD_InputFile ReKi GenSpd_TLU {:} - - "Records R:2:R+2*DLL_NumTrq-2: Generator speed values in look-up table [used only with DLL Interface]" rad/s +typedef ^ SrvD_InputFile ReKi GenTrq_TLU {:} - - "Records R+1:2:R+2*DLL_NumTrq-1: Generator torque values in look-up table [used only with DLL Interface]" Nm +typedef ^ SrvD_InputFile LOGICAL UseLegacyInterface - - - "Flag that determines if the legacy Bladed interface is (legacy=DISCON with avrSWAP instead of CONTROLLER)" - +typedef ^ SrvD_InputFile LOGICAL CompNTMD - - - "Compute nacelle tuned mass damper {true/false}" - +typedef ^ SrvD_InputFile CHARACTER(1024) NTMDfile - - - "File for nacelle tuned mass damper (quoted string)" - +typedef ^ SrvD_InputFile LOGICAL CompTTMD - - - "Compute tower tuned mass damper {true/false}" - +typedef ^ SrvD_InputFile CHARACTER(1024) TTMDfile - - - "File for tower tuned mass damper (quoted string)" - + +# ..... Data for using Bladed DLLs ....................................................................................................... +typedef ^ BladedDLLType SiKi avrSWAP {:} - - "The swap array: used to pass data to and from the DLL controller" "see Bladed DLL documentation" +typedef ^ BladedDLLType ReKi HSSBrTrqDemand - - - "Demanded braking torque - from Bladed DLL" - +typedef ^ BladedDLLType ReKi YawRateCom - - - "Nacelle yaw rate demanded from Bladed DLL" rad/s +typedef ^ BladedDLLType ReKi GenTrq - - - "Electrical generator torque from Bladed DLL" N-m +typedef ^ BladedDLLType IntKi GenState - - - "Generator state from Bladed DLL" - +typedef ^ BladedDLLType ReKi BlPitchCom 3 - - "Commanded blade pitch angles" radians +typedef ^ BladedDLLType ReKi PrevBlPitch 3 - - "Previously commanded blade pitch angles" radians +typedef ^ BladedDLLType ReKi BlAirfoilCom 3 - - "Commanded Airfoil UserProp for blade. Passed to AD15 for airfoil interpolation (must be same units as given in AD15 airfoil tables)" - +typedef ^ BladedDLLType ReKi ElecPwr_prev - - - "Electrical power (from previous step), sent to Bladed DLL" W +typedef ^ BladedDLLType ReKi GenTrq_prev - - - "Electrical generator torque (from previous step), sent to Bladed DLL" N-m +typedef ^ BladedDLLType SiKi SCoutput {:} - - "controller output to supercontroller" - +typedef ^ BladedDLLType logical initialized - - - "flag that determines if DLL has been called (for difference between CalcOutput and UpdateStates)" - +typedef ^ BladedDLLType INTEGER NumLogChannels - - - "number of log channels from controller" - +typedef ^ BladedDLLType OutParmType LogChannels_OutParam {:} - - "Names and units (and other characteristics) of logging outputs from DLL" - +typedef ^ BladedDLLType ReKi LogChannels {:} - - "logging outputs from controller" - +typedef ^ BladedDLLType IntKi ErrStat - - - "error message from external controller API" - +typedef ^ BladedDLLType CHARACTER(ErrMsgLen) ErrMsg - - - "error message from external controller API" - +typedef ^ BladedDLLType R8Ki CurrentTime - - - "Current Simulation Time" s +typedef ^ BladedDLLType IntKi SimStatus - - - "simulation status (see avrSWAP(1): Status flag set as follows: 0 if this is the first call, 1 for all subsequent time steps, -1 if this is the final call at the end of the simulation)" - +typedef ^ BladedDLLType IntKi ShaftBrakeStatusBinaryFlag - - - "binary flag indicating (on/off) status for shaft brake 1, shaft brake 2, generator brake, shaft brake 3, or brake torque set separately (0, 1, or 16 allowed in FAST)"- +typedef ^ BladedDLLType LOGICAL HSSBrDeployed - - - "Whether the HSS brake has been deployed" - +typedef ^ BladedDLLType R8Ki TimeHSSBrFullyDeployed - - - "Time at which the controller high-speed shaft is fully deployed" s +typedef ^ BladedDLLType R8Ki TimeHSSBrDeployed - - - "Time at which the controller high-speed shaft is first deployed" s +typedef ^ BladedDLLType LOGICAL OverrideYawRateWithTorque - - - "acts similiar to Yaw_Cntrl" - +typedef ^ BladedDLLType ReKi YawTorqueDemand - - - "Demanded yaw actuator torque (override of yaw rate control)" Nm +## these are INPUTS copied to the DLL: +typedef ^ BladedDLLType ReKi BlPitchInput {:} - - "Input blade pitch angles" radians +typedef ^ BladedDLLType ReKi YawAngleFromNorth - - - "Yaw angle of the nacelle relative to North (see NacYaw_North)" rad +typedef ^ BladedDLLType ReKi HorWindV - - - "Horizontal hub-height wind velocity magnitude" m/s +typedef ^ BladedDLLType ReKi HSS_Spd - - - "High-speed shaft (HSS) speed" rad/s +typedef ^ BladedDLLType ReKi YawErr - - - "Yaw error" radians +typedef ^ BladedDLLType ReKi RotSpeed - - - "Rotor azimuth angular speed" rad/s +typedef ^ BladedDLLType ReKi YawBrTAxp - - - "Tower-top / yaw bearing fore-aft (translational) acceleration (absolute)" m/s^2 +typedef ^ BladedDLLType ReKi YawBrTAyp - - - "Tower-top / yaw bearing side-to-side (translational) acceleration (absolute)" m/s^2 +typedef ^ BladedDLLType ReKi LSSTipMys - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ BladedDLLType ReKi LSSTipMzs - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ BladedDLLType ReKi LSSTipMya - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ BladedDLLType ReKi LSSTipMza - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ BladedDLLType ReKi LSSTipPxa - - - "Rotor azimuth angle (position)" radians +typedef ^ BladedDLLType ReKi Yaw - - - "Current nacelle yaw" radians +typedef ^ BladedDLLType ReKi YawRate - - - "Current nacelle yaw rate" rad/s +typedef ^ BladedDLLType ReKi YawBrMyn - - - "Rotating (with nacelle) tower-top / yaw bearing pitch moment" N-m +typedef ^ BladedDLLType ReKi YawBrMzn - - - "Tower-top / yaw bearing yaw moment" N-m +typedef ^ BladedDLLType ReKi NcIMURAxs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ BladedDLLType ReKi NcIMURAys - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ BladedDLLType ReKi NcIMURAzs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ BladedDLLType ReKi RotPwr - - - "Rotor power (this is equivalent to the low-speed shaft power)" W +typedef ^ BladedDLLType ReKi LSSTipMxa - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ BladedDLLType ReKi RootMyc 3 - - "Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3)" N-m +typedef ^ BladedDLLType ReKi RootMxc 3 - - "In-plane moment (i.e., the moment caused by in-plane forces) at the blade root" N-m +## these are PARAMETERS sent to the DLL (THEIR VALUES SHOULD NOT CHANGE DURING SIMULATION): +typedef ^ BladedDLLType DbKi DLL_DT - - - "interval for calling DLL (integer multiple number of DT)" s +typedef ^ BladedDLLType CHARACTER(1024) DLL_InFile - - - "Name of input file used in DLL" - +typedef ^ BladedDLLType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ BladedDLLType ReKi GenTrq_Dem - - - "Demanded generator torque above rated" Nm +typedef ^ BladedDLLType ReKi GenSpd_Dem - - - "Demanded generator speed above rated" rad/s +typedef ^ BladedDLLType ReKi Ptch_Max - - - "Maximum pitch angle" rad +typedef ^ BladedDLLType ReKi Ptch_Min - - - "Minimum pitch angle" rad +typedef ^ BladedDLLType ReKi Ptch_SetPnt - - - "Below-rated pitch angle set-point" rad +typedef ^ BladedDLLType ReKi PtchRate_Max - - - "Maximum pitch rate" rad/s +typedef ^ BladedDLLType ReKi PtchRate_Min - - - "Minimum pitch rate (most negative value allowed)" rad/s +typedef ^ BladedDLLType ReKi GenPwr_Dem - - - "Demanded power (This is not valid for variable-speed, pitch-regulated controllers.)" W +typedef ^ BladedDLLType ReKi Gain_OM - - - "Optimal mode gain" Nm/(rad/s)^2 +typedef ^ BladedDLLType ReKi GenSpd_MaxOM - - - "Optimal mode maximum speed" rad/s +typedef ^ BladedDLLType ReKi GenSpd_MinOM - - - "Minimum generator speed" rad/s +typedef ^ BladedDLLType IntKi Ptch_Cntrl - - - "Pitch control: 0 = collective; 1 = individual" - +typedef ^ BladedDLLType IntKi DLL_NumTrq - - - "No. of points in torque-speed look-up table, 0 = none and use the optimal mode PARAMETERs instead; nonzero = ignore the optimal mode PARAMETERs by setting Record 16 to 0.0" - +typedef ^ BladedDLLType ReKi GenSpd_TLU {:} - - "Table (array) containing DLL_NumTrq generator speeds for the torque-speed table look-up (TLU) -- this should be defined using an array constructor; for example, if DLL_NumTrq = 3, GenSpd_TLU(DLL_NumTrq) = (/ 0.0, 99.9, 999.9 /)" rad/s +typedef ^ BladedDLLType ReKi GenTrq_TLU {:} - - "Table (array) containing DLL_NumTrq generator torques for the torque-speed table look-up (TLU) -- this should be defined using an array constructor, for example, if DLL_NumTrq = 3, GenTrq_TLU(DLL_NumTrq) = (/ 0.0, 10, 200.0 /)" Nm +typedef ^ BladedDLLType IntKi Yaw_Cntrl - - - "Yaw control: 0 = rate; 1 = torque" - + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - +typedef ^ ContinuousStateType TMD_ContinuousStateType NTMD - - - "TMD module states - nacelle" - +typedef ^ ContinuousStateType TMD_ContinuousStateType TTMD - - - "TMD module states - tower" - + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi CtrlOffset - - - "Controller offset parameter" N-m +#typedef ^ DiscreteStateType ReKi BlPitchFilter {:} - - "blade pitch filter" - +typedef ^ DiscreteStateType TMD_DiscreteStateType NTMD - - - "TMD module states - nacelle" - +typedef ^ DiscreteStateType TMD_DiscreteStateType TTMD - - - "TMD module states - tower" - + +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - +typedef ^ ConstraintStateType TMD_ConstraintStateType NTMD - - - "TMD module states - nacelle" - +typedef ^ ConstraintStateType TMD_ConstraintStateType TTMD - - - "TMD module states - tower" - + +# Define "other" states (e.g. logical states) here: +# other states for pitch maneuver: +typedef ^ OtherStateType Logical BegPitMan {:} - - "Whether the override pitch maneuver actually began" - +typedef ^ OtherStateType ReKi BlPitchI {:} - - "Initial blade pitch angles at the start of the override pitch maneuver" radians +typedef ^ OtherStateType DbKi TPitManE {:} - - "Time to end pitch maneuvers for each blade" s +# other states for yaw maneuver: +typedef ^ OtherStateType Logical BegYawMan - - - "Whether the yaw maneuver actually began" - +typedef ^ OtherStateType ReKi NacYawI - - - "Initial yaw angle at the start of the override yaw maneuver" radians +typedef ^ OtherStateType DbKi TYawManE - - - "Time to end override yaw maneuver" s +typedef ^ OtherStateType ReKi YawPosComInt - - - "Internal variable that integrates the commanded yaw rate and passes it to YawPosCom" radians +# other states for tip-brake deployment: +typedef ^ OtherStateType Logical BegTpBr {:} - - "Whether the tip brakes actually deployed" - +typedef ^ OtherStateType DbKi TTpBrDp {:} - - "Times to initiate deployment of tip brakes" s +typedef ^ OtherStateType DbKi TTpBrFl {:} - - "Times at which tip brakes are fully deployed" s +# other states for generator on/off: +typedef ^ OtherStateType Logical Off4Good - - - "Is the generator offline for rest of simulation?" - +typedef ^ OtherStateType Logical GenOnLine - - - "Is the generator online?" - +# other states for TMD sub-module: +typedef ^ OtherStateType TMD_OtherStateType NTMD - - - "TMD module states - nacelle" - +typedef ^ OtherStateType TMD_OtherStateType TTMD - - - "TMD module states - tower" - + +# ..... Misc Variables ................................................................................................................ +typedef ^ MiscVarType DbKi LastTimeCalled - - - "last time the CalcOutput/Bladed DLL was called" s +typedef ^ MiscVarType BladedDLLType dll_data - - - "data used for Bladed DLL" - +typedef ^ MiscVarType logical FirstWarn - - - "Whether or not this is the first warning about the DLL being called without Explicit-Loose coupling." - +typedef ^ MiscVarType DbKi LastTimeFiltered - - - "last time the CalcOutput/Bladed DLL was filtered" s +typedef ^ MiscVarType ReKi xd_BlPitchFilter {:} - - "blade pitch filter" - +typedef ^ MiscVarType TMD_MiscVarType NTMD - - - "TMD module misc vars - nacelle" - +typedef ^ MiscVarType TMD_MiscVarType TTMD - - - "TMD module misc vars - tower" - + +# ..... 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 DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds +typedef ^ ParameterType DbKi HSSBrDT - - - "Time it takes for HSS brake to reach full deployment once deployed" seconds +typedef ^ ParameterType ReKi HSSBrTqF - - - "Fully deployed HSS brake torque" +typedef ^ ParameterType ReKi SIG_POSl - - - "Pullout slip" +typedef ^ ParameterType ReKi SIG_POTq - - - "Pullout torque" +typedef ^ ParameterType ReKi SIG_SlPc - - - "Rated generator slip percentage" +typedef ^ ParameterType ReKi SIG_Slop - - - "Torque/Speed slope for simple induction generator" +typedef ^ ParameterType ReKi SIG_SySp - - - "Synchronous (zero-torque) generator speed" rad/s +typedef ^ ParameterType ReKi TEC_A0 - - - "A0 term for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_C0 - - - "C0 term for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_C1 - - - "C1 term for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_C2 - - - "C2 term for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_K2 - - - "K2 term for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_MR - - - "Magnetizing reactance for Thevenin-equivalent circuit" ohms +typedef ^ ParameterType ReKi TEC_Re1 - - - "Thevenin's equivalent stator resistance (ohms)" ohms +typedef ^ ParameterType ReKi TEC_RLR - - - "Rotor leakage reactance for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_RRes - - - "Rotor resistance for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_SRes - - - "Stator resistance for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_SySp - - - "Synchronous speed for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_V1a - - - "Source voltage for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_VLL - - - "Line-to-line RMS voltage for Thevenin-equivalent circuit" +typedef ^ ParameterType ReKi TEC_Xe1 - - - "Thevenin's equivalent stator leakage reactance (ohms)" ohms +typedef ^ ParameterType ReKi GenEff - - - "Generator efficiency" +typedef ^ ParameterType ReKi BlPitchInit {:} - - "Initial blade pitch angles" radians +typedef ^ ParameterType ReKi BlPitchF {:} - - "Final blade pitch" +typedef ^ ParameterType ReKi PitManRat {:} - - "Pitch rates at which override pitch maneuvers head toward final pitch angles (does not include sign)" rad/s +typedef ^ ParameterType ReKi YawManRat - - - "Yaw rate at which override yaw maneuver head toward for final yaw angle (does not include sign)" rad/s +typedef ^ ParameterType ReKi NacYawF - - - "Final yaw angle after override yaw maneuver" +typedef ^ ParameterType ReKi SpdGenOn - - - "Generator speed to turn on the generator for a startup" +typedef ^ ParameterType DbKi THSSBrDp - - - "Time to initiate deployment of the shaft brake" s +typedef ^ ParameterType DbKi THSSBrFl - - - "Time at which shaft brake is fully deployed" s +typedef ^ ParameterType DbKi TimGenOf - - - "Time to turn off generator for braking or modeling a run-away" s +typedef ^ ParameterType DbKi TimGenOn - - - "Time to turn on generator for startup" s +typedef ^ ParameterType DbKi TPCOn - - - "Time to enable active pitch control" s +typedef ^ ParameterType DbKi TPitManS {:} - - "Time to start pitch maneuvers for each blade" s +typedef ^ ParameterType DbKi TYawManS - - - "Time to start override yaw maneuver" s +typedef ^ ParameterType DbKi TYCOn - - - "Time to enable active yaw control" s +typedef ^ ParameterType ReKi VS_RtGnSp - - - "Rated generator speed (HSS side)" rad/s +typedef ^ ParameterType ReKi VS_RtTq - - - "Rated generator torque/constant generator torque in Region 3 (HSS side)" N-m +typedef ^ ParameterType ReKi VS_Slope - - - "Torque/speed slope of region 2 1/2 induction generator" +typedef ^ ParameterType ReKi VS_SlPc - - - "Rated generator slip percentage in Region 2 1/2" - +typedef ^ ParameterType ReKi VS_SySp - - - "Synchronous speed of region 2 1/2 induction generator" +typedef ^ ParameterType ReKi VS_TrGnSp - - - "Transitional generator speed between regions 2 and 2 1/2" +typedef ^ ParameterType ReKi YawPosCom - - - "Commanded yaw angle from user-defined routines" rad +typedef ^ ParameterType ReKi YawRateCom - - - "Commanded yaw rate from user-defined routines" rad/s +typedef ^ ParameterType IntKi GenModel - - - "Generator model" - +typedef ^ ParameterType IntKi HSSBrMode - - - "HSS brake model" - +typedef ^ ParameterType IntKi PCMode - - - "Pitch control mode" - +typedef ^ ParameterType IntKi VSContrl - - - "Variable-speed-generator control switch" - +typedef ^ ParameterType IntKi YCMode - - - "Yaw control mode" - +typedef ^ ParameterType LOGICAL GenTiStp - - - "Stop generator based upon T: time or F: generator power = 0" +typedef ^ ParameterType LOGICAL GenTiStr - - - "Start generator based upon T: time or F: generator speed" +typedef ^ ParameterType ReKi VS_Rgn2K - - - "Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1]" N-m/(rad/s)^2 +typedef ^ ParameterType ReKi YawNeut - - - "Neutral yaw position--yaw spring force is zero at this yaw" radians +typedef ^ ParameterType ReKi YawSpr - - - "Nacelle-yaw spring constant" N-m/rad +typedef ^ ParameterType ReKi YawDamp - - - "Nacelle-yaw constant" N-m/(rad/s) +typedef ^ ParameterType DbKi TpBrDT - - - "Time for tip-brake to reach full deployment once released" s +typedef ^ ParameterType ReKi TBDepISp {:} - - "Deployment-initiation speed for the tip brakes" rad/s +typedef ^ ParameterType ReKi TBDrConN - - - "Tip-brake drag constant during normal operation, Cd*Area" +typedef ^ ParameterType ReKi TBDrConD - - - "Tip-brake drag constant during fully-deployed operation, Cd*Area" +typedef ^ ParameterType IntKi NumBl - - - "Number of blades on the turbine" - +typedef ^ ParameterType LOGICAL CompNTMD - - - "Compute nacelle tuned mass damper {true/false}" - +typedef ^ ParameterType LOGICAL CompTTMD - - - "Compute tower tuned mass damper {true/false}" - +# parameters for output +typedef ^ ParameterType IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - +typedef ^ ParameterType IntKi NumOuts_DLL - - - "Number of logging channels output from the DLL (set at initialization)" - +typedef ^ ParameterType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" - +# parameters for Bladed Interface (dynamic-link library) +typedef ^ ParameterType LOGICAL UseBladedInterface - - - "Flag that determines if BladedInterface was used" - +typedef ^ ParameterType LOGICAL UseLegacyInterface - - - "Flag that determines if the legacy Bladed interface is (legacy=DISCON with avrSWAP instead of CONTROLLER)" - +typedef ^ ParameterType DLL_Type DLL_Trgt - - - "The addresses and names of the Bladed DLL and its procedure" - +typedef ^ ParameterType LOGICAL DLL_Ramp - - - "determines if there is a DLL_DT-ramp time delay (true only when DLL_DT /= DT)" - +typedef ^ ParameterType ReKi BlAlpha - - - "parameter for low-pass filter of blade pitch commands from the controller DLL" - +typedef ^ ParameterType IntKi DLL_n - - - "number of steps between the controller being called and SrvD being called" - +typedef ^ ParameterType IntKi avcOUTNAME_LEN - - - "Length of the avcOUTNAME character array passed to/from the DLL" - +typedef ^ ParameterType ReKi NacYaw_North - - - "Reference yaw angle of the nacelle when the upwind end points due North" rad +typedef ^ ParameterType ReKi AvgWindSpeed - - - "average wind speed for the simulation" m/s +typedef ^ ParameterType ReKi AirDens - - - "air density" kg/m^3 +# parameters for trim-case (linearization): +typedef ^ ParameterType IntKi TrimCase - - - "Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True]" - +typedef ^ ParameterType ReKi TrimGain - - - "Proportional gain for the rotational speed error (>0) [used only if TrimCase>0]" "rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque" +typedef ^ ParameterType ReKi RotSpeedRef - - - "Reference rotor speed" "rad/s" +# parameters for other modules: +typedef ^ ParameterType TMD_ParameterType NTMD - - - "TMD module parameters - nacelle" - +typedef ^ ParameterType TMD_ParameterType TTMD - - - "TMD module parameters - tower" - + +# ..... Inputs .................................................................................................................... +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi BlPitch {:} - 2pi "Current blade pitch angles" radians +typedef ^ InputType ReKi Yaw - - 2pi "Current nacelle yaw" radians +typedef ^ InputType ReKi YawRate - - - "Current nacelle yaw rate" rad/s +typedef ^ InputType ReKi LSS_Spd - - - "Low-speed shaft (LSS) speed at entrance to gearbox" rad/s +typedef ^ InputType ReKi HSS_Spd - - - "High-speed shaft (HSS) speed" rad/s +typedef ^ InputType ReKi RotSpeed - - - "Rotor azimuth angular speed" rad/s +typedef ^ InputType ReKi ExternalYawPosCom - - 2pi "Commanded nacelle yaw position from Simulink or Labview" radians +typedef ^ InputType ReKi ExternalYawRateCom - - - "Commanded nacelle yaw rate from Simulink or Labview" rad/s +typedef ^ InputType ReKi ExternalBlPitchCom {:} - 2pi "Commanded blade pitch from Simulink or LabVIEW" radians +typedef ^ InputType ReKi ExternalGenTrq - - - "Electrical generator torque from Simulink or LabVIEW" N-m +typedef ^ InputType ReKi ExternalElecPwr - - - "Electrical power from Simulink or LabVIEW" W +typedef ^ InputType ReKi ExternalHSSBrFrac - - - "Fraction of full braking torque: 0 (off) <= HSSBrFrac <= 1 (full) from Simulink or LabVIEW" - +typedef ^ InputType ReKi TwrAccel - - - "Tower acceleration for tower feedback control (user routine only)" m/s^2 +typedef ^ InputType ReKi YawErr - - 2pi "Yaw error" radians +typedef ^ InputType ReKi WindDir - - 2pi "Wind direction" radians +typedef ^ InputType ReKi RootMyc 3 - - "Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3)" N-m +typedef ^ InputType ReKi YawBrTAxp - - - "Tower-top / yaw bearing fore-aft (translational) acceleration (absolute)" m/s^2 +typedef ^ InputType ReKi YawBrTAyp - - - "Tower-top / yaw bearing side-to-side (translational) acceleration (absolute)" m/s^2 +typedef ^ InputType ReKi LSSTipPxa - - - "Rotor azimuth angle (position)" radians +typedef ^ InputType ReKi RootMxc 3 - - "In-plane moment (i.e., the moment caused by in-plane forces) at the blade root" N-m +typedef ^ InputType ReKi LSSTipMxa - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ InputType ReKi LSSTipMya - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ InputType ReKi LSSTipMza - - - "Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ InputType ReKi LSSTipMys - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ InputType ReKi LSSTipMzs - - - "Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader)" N-m +typedef ^ InputType ReKi YawBrMyn - - - "Rotating (with nacelle) tower-top / yaw bearing pitch moment" N-m +typedef ^ InputType ReKi YawBrMzn - - - "Tower-top / yaw bearing yaw moment" N-m +typedef ^ InputType ReKi NcIMURAxs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ InputType ReKi NcIMURAys - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ InputType ReKi NcIMURAzs - - - "Nacelle inertial measurement unit angular (rotational) acceleration (absolute)" rad/s^2 +typedef ^ InputType ReKi RotPwr - - - "Rotor power (this is equivalent to the low-speed shaft power)" W +typedef ^ InputType ReKi HorWindV - - - "Horizontal hub-height wind velocity magnitude" m/s +typedef ^ InputType ReKi YawAngle - - 2pi "Estimate of yaw (nacelle + platform)" radians +typedef ^ InputType TMD_InputType NTMD - - - "TMD module inputs - nacelle" - +typedef ^ InputType TMD_InputType TTMD - - - "TMD module inputs - tower" - +typedef ^ InputType SiKi SuperController {:} - - "A swap array: used to pass input data to the DLL controller from the supercontroller" - + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +#typedef ^ OutputType MeshType MeshedOutput - - - "Meshed output data" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" +typedef ^ OutputType ReKi BlPitchCom {:} - 2pi "Commanded blade pitch angles" radians +typedef ^ OutputType ReKi BlAirfoilCom {:} - - "Commanded Airfoil UserProp for blade. Passed to AD15 for airfoil interpolation (must be same units as given in AD15 airfoil tables)" - +typedef ^ OutputType ReKi YawMom - - - "Torque transmitted through the yaw bearing" N-m +typedef ^ OutputType ReKi GenTrq - - - "Electrical generator torque" N-m +typedef ^ OutputType ReKi HSSBrTrqC - - - "Commanded HSS brake torque" N-m +typedef ^ OutputType ReKi ElecPwr - - - "Electrical power" W +typedef ^ OutputType ReKi TBDrCon {:} - - "Instantaneous tip-brake drag constant, Cd*Area" +typedef ^ OutputType TMD_OutputType NTMD - - - "TMD module outputs - nacelle" - +typedef ^ OutputType TMD_OutputType TTMD - - - "TMD module outputs - tower" - +typedef ^ OutputType SiKi SuperController {:} - - "A swap array: used to pass output data from the DLL controller to the supercontroller" - + diff --git a/OpenFAST/modules/servodyn/src/ServoDyn_Types.f90 b/OpenFAST/modules/servodyn/src/ServoDyn_Types.f90 new file mode 100644 index 000000000..0b23dfb3b --- /dev/null +++ b/OpenFAST/modules/servodyn/src/ServoDyn_Types.f90 @@ -0,0 +1,8170 @@ +!STARTOFREGISTRYGENERATEDFILE 'ServoDyn_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 +!********************************************************************************************************************************* +! ServoDyn_Types +!................................................................................................................................. +! This file is part of ServoDyn. +! +! 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 ServoDyn. 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 ServoDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE TMD_Types +USE NWTC_Library +IMPLICIT NONE +! ========= SrvD_InitInputType ======= + TYPE, PUBLIC :: SrvD_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + INTEGER(IntKi) :: NumBl !< Number of blades on the turbine [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchInit !< Initial blade pitch [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) , DIMENSION(1:3) :: r_N_O_G !< nacelle origin for setting up mesh [m] + REAL(ReKi) , DIMENSION(1:3) :: r_TwrBase !< tower base origin for setting up mesh [m] + REAL(DbKi) :: Tmax !< max time from glue code [s] + REAL(ReKi) :: AvgWindSpeed !< average wind speed for the simulation [m/s] + REAL(ReKi) :: AirDens !< air density [kg/m^3] + INTEGER(IntKi) :: NumSC2Ctrl !< number of controller inputs [from supercontroller] [-] + INTEGER(IntKi) :: NumCtrl2SC !< number of controller outputs [to supercontroller] [-] + INTEGER(IntKi) :: TrimCase !< Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] [-] + REAL(ReKi) :: TrimGain !< Proportional gain for the rotational speed error (>0) [used only if TrimCase>0] [rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque] + REAL(ReKi) :: RotSpeedRef !< Reference rotor speed [rad/s] + END TYPE SrvD_InitInputType +! ======================= +! ========= SrvD_InitOutputType ======= + TYPE, PUBLIC :: SrvD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + INTEGER(IntKi) :: CouplingScheme !< Switch that indicates if a particular coupling scheme is required [-] + LOGICAL :: UseHSSBrake !< flag to determine if high-speed shaft brake is potentially used (true=yes) [-] + 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 [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + END TYPE SrvD_InitOutputType +! ======================= +! ========= SrvD_InputFile ======= + TYPE, PUBLIC :: SrvD_InputFile + REAL(DbKi) :: DT !< Communication interval for controllers [s] + INTEGER(IntKi) :: PCMode !< Pitch control mode [-] + REAL(DbKi) :: TPCOn !< Time to enable active pitch control [unused when PCMode=0] [s] + REAL(DbKi) , DIMENSION(1:3) :: TPitManS !< Time to start override pitch maneuver for blade (K) and end standard pitch control [s] + REAL(ReKi) , DIMENSION(1:3) :: PitManRat !< Pitch rates at which override pitch maneuvers head toward final pitch angles [rad/s] + REAL(ReKi) , DIMENSION(1:3) :: BlPitchF !< Blade (K) final pitch for pitch maneuvers [radians] + INTEGER(IntKi) :: VSContrl !< Variable-speed control mode [-] + INTEGER(IntKi) :: GenModel !< Generator model [used only when VSContrl=0] [-] + REAL(ReKi) :: GenEff !< Generator efficiency [ignored by the Thevenin and user-defined generator models] [-] + LOGICAL :: GenTiStr !< Method to start the generator {T: timed using TimGenOn, F: generator speed using SpdGenOn} [-] + LOGICAL :: GenTiStp !< Method to stop the generator {T: timed using TimGenOf, F: when generator power = 0} [-] + REAL(ReKi) :: SpdGenOn !< Generator speed to turn on the generator for a startup (HSS speed) [used only when GenTiStr=False] [rad/s] + REAL(DbKi) :: TimGenOn !< Time to turn on the generator for a startup [used only when GenTiStr=True] [s] + REAL(DbKi) :: TimGenOf !< Time to turn off the generator [used only when GenTiStp=True] [s] + REAL(ReKi) :: VS_RtGnSp !< Rated generator speed for simple variable-speed generator control (HSS side) [used only when VSContrl=1] [rad/s] + REAL(ReKi) :: VS_RtTq !< Rated generator torque/constant generator torque in Region 3 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] [N-m] + REAL(ReKi) :: VS_Rgn2K !< Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] [N-m/(rad/s)^2] + REAL(ReKi) :: VS_SlPc !< Rated generator slip percentage in Region 2 1/2 for simple variable-speed generator control [used only when VSContrl=1] [-] + REAL(ReKi) :: SIG_SlPc !< Rated generator slip percentage [used only when VSContrl=0 and GenModel=1] [-] + REAL(ReKi) :: SIG_SySp !< Synchronous (zero-torque) generator speed [used only when VSContrl=0 and GenModel=1] [rad/s] + REAL(ReKi) :: SIG_RtTq !< Rated torque [used only when VSContrl=0 and GenModel=1] [N-m] + REAL(ReKi) :: SIG_PORt !< Pull-out ratio (Tpullout/Trated) [used only when VSContrl=0 and GenModel=1] [-] + REAL(ReKi) :: TEC_Freq !< Line frequency [50 or 60] [used only when VSContrl=0 and GenModel=2] [Hz] + INTEGER(IntKi) :: TEC_NPol !< Number of poles [even integer > 0] [used only when VSContrl=0 and GenModel=2] [-] + REAL(ReKi) :: TEC_SRes !< Stator resistance [used only when VSContrl=0 and GenModel=2] [ohms] + REAL(ReKi) :: TEC_RRes !< Rotor resistance [used only when VSContrl=0 and GenModel=2] [ohms] + REAL(ReKi) :: TEC_VLL !< Line-to-line RMS voltage [used only when VSContrl=0 and GenModel=2] [volts] + REAL(ReKi) :: TEC_SLR !< Stator leakage reactance [used only when VSContrl=0 and GenModel=2] [ohms] + REAL(ReKi) :: TEC_RLR !< Rotor leakage reactance [used only when VSContrl=0 and GenModel=2] [ohms] + REAL(ReKi) :: TEC_MR !< Magnetizing reactance [used only when VSContrl=0 and GenModel=2] [ohms] + INTEGER(IntKi) :: HSSBrMode !< HSS brake model [-] + REAL(DbKi) :: THSSBrDp !< Time to initiate deployment of the HSS brake [s] + REAL(DbKi) :: HSSBrDT !< Time for HSS-brake to reach full deployment once initiated [used only when HSSBrMode=1] [s] + REAL(ReKi) :: HSSBrTqF !< Fully deployed HSS-brake torque [N-m] + INTEGER(IntKi) :: YCMode !< Yaw control mode [-] + REAL(DbKi) :: TYCOn !< Time to enable active yaw control [unused when YCMode=0] [s] + REAL(ReKi) :: YawNeut !< Neutral yaw position--yaw spring force is zero at this yaw [radians] + REAL(ReKi) :: YawSpr !< Nacelle-yaw spring constant [N-m/rad] + REAL(ReKi) :: YawDamp !< Nacelle-yaw constant [N-m/(rad/s)] + REAL(DbKi) :: TYawManS !< Time to start override yaw maneuver and end standard yaw control [s] + REAL(ReKi) :: YawManRat !< Yaw maneuver rate (in absolute value) [rad/s] + REAL(ReKi) :: NacYawF !< Final yaw angle for override yaw maneuvers [radians] + LOGICAL :: SumPrint !< Print summary data to <RootName>.sum [-] + INTEGER(IntKi) :: OutFile !< Switch to determine where output will be placed: (1: in module output file only; 2: in glue code output file only; 3: both) [-] + LOGICAL :: TabDelim !< Use tab delimiters in text tabular output file? [-] + CHARACTER(20) :: OutFmt !< Format used for text tabular output (except time) [-] + REAL(DbKi) :: Tstart !< Time to start module's tabular output [s] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] + CHARACTER(1024) :: DLL_FileName !< Name of the DLL file including the full path [-] + CHARACTER(1024) :: DLL_ProcName !< Name of the procedure in the DLL that will be called [-] + CHARACTER(1024) :: DLL_InFile !< Name of input file used in DLL [-] + REAL(DbKi) :: DLL_DT !< interval for calling DLL (must be integer multiple number of DT steps) [s] + LOGICAL :: DLL_Ramp !< whether the DLL pitch should be a ramp (true) or step change (false) when DLL_DT <> DT. If true, introduces a time delay. [-] + REAL(ReKi) :: BPCutoff !< The cutoff frequency for the blade pitch low-pass filter. Large values => no filter. [Hz] + REAL(ReKi) :: NacYaw_North !< Reference yaw angle of the nacelle when the upwind end points due North [used only with DLL Interface] [radians] + INTEGER(IntKi) :: Ptch_Cntrl !< Record 28: Use individual pitch control {0: collective pitch; 1: individual pitch control} [used only with DLL Interface] [-] + REAL(ReKi) :: Ptch_SetPnt !< Record 5: Below-rated pitch angle set-point [used only with DLL Interface] [radians] + REAL(ReKi) :: Ptch_Min !< Record 6: Minimum pitch angle [used only with DLL Interface] [radians] + REAL(ReKi) :: Ptch_Max !< Record 7: Maximum pitch angle [used only with DLL Interface] [radians] + REAL(ReKi) :: PtchRate_Min !< Record 8: Minimum pitch rate (most negative value allowed) [used only with DLL Interface] [rad/s] + REAL(ReKi) :: PtchRate_Max !< Record 9: Maximum pitch rate [used only with DLL Interface] [rad/s] + REAL(ReKi) :: Gain_OM !< Record 16: Optimal mode gain [used only with DLL Interface] [Nm/(rad/s)^2] + REAL(ReKi) :: GenSpd_MinOM !< Record 17: Minimum generator speed [used only with DLL Interface] [rad/s] + REAL(ReKi) :: GenSpd_MaxOM !< Record 18: Optimal mode maximum speed [used only with DLL Interface] [rad/s] + REAL(ReKi) :: GenSpd_Dem !< Record 19: Demanded generator speed above rated [used only with DLL Interface] [rad/s] + REAL(ReKi) :: GenTrq_Dem !< Record 22: Demanded generator torque above rated [used only with DLL Interface] [Nm] + REAL(ReKi) :: GenPwr_Dem !< Record 13: Demanded power [used only with DLL Interface] [W] + INTEGER(IntKi) :: DLL_NumTrq !< Record 26: No. of points in torque-speed look-up table {0 = none and use the optimal mode PARAMETERs instead, nonzero = ignore the optimal mode PARAMETERs by setting Gain_OM (Record 16) to 0.0} [used only with DLL Interface] [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: GenSpd_TLU !< Records R:2:R+2*DLL_NumTrq-2: Generator speed values in look-up table [used only with DLL Interface] [rad/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: GenTrq_TLU !< Records R+1:2:R+2*DLL_NumTrq-1: Generator torque values in look-up table [used only with DLL Interface] [Nm] + LOGICAL :: UseLegacyInterface !< Flag that determines if the legacy Bladed interface is (legacy=DISCON with avrSWAP instead of CONTROLLER) [-] + LOGICAL :: CompNTMD !< Compute nacelle tuned mass damper {true/false} [-] + CHARACTER(1024) :: NTMDfile !< File for nacelle tuned mass damper (quoted string) [-] + LOGICAL :: CompTTMD !< Compute tower tuned mass damper {true/false} [-] + CHARACTER(1024) :: TTMDfile !< File for tower tuned mass damper (quoted string) [-] + END TYPE SrvD_InputFile +! ======================= +! ========= BladedDLLType ======= + TYPE, PUBLIC :: BladedDLLType + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: avrSWAP !< The swap array: used to pass data to and from the DLL controller [see Bladed DLL documentation] + REAL(ReKi) :: HSSBrTrqDemand !< Demanded braking torque - from Bladed DLL [-] + REAL(ReKi) :: YawRateCom !< Nacelle yaw rate demanded from Bladed DLL [rad/s] + REAL(ReKi) :: GenTrq !< Electrical generator torque from Bladed DLL [N-m] + INTEGER(IntKi) :: GenState !< Generator state from Bladed DLL [-] + REAL(ReKi) , DIMENSION(1:3) :: BlPitchCom !< Commanded blade pitch angles [radians] + REAL(ReKi) , DIMENSION(1:3) :: PrevBlPitch !< Previously commanded blade pitch angles [radians] + REAL(ReKi) , DIMENSION(1:3) :: BlAirfoilCom !< Commanded Airfoil UserProp for blade. Passed to AD15 for airfoil interpolation (must be same units as given in AD15 airfoil tables) [-] + REAL(ReKi) :: ElecPwr_prev !< Electrical power (from previous step), sent to Bladed DLL [W] + REAL(ReKi) :: GenTrq_prev !< Electrical generator torque (from previous step), sent to Bladed DLL [N-m] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: SCoutput !< controller output to supercontroller [-] + LOGICAL :: initialized !< flag that determines if DLL has been called (for difference between CalcOutput and UpdateStates) [-] + INTEGER(IntKi) :: NumLogChannels !< number of log channels from controller [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: LogChannels_OutParam !< Names and units (and other characteristics) of logging outputs from DLL [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LogChannels !< logging outputs from controller [-] + INTEGER(IntKi) :: ErrStat !< error message from external controller API [-] + CHARACTER(ErrMsgLen) :: ErrMsg !< error message from external controller API [-] + REAL(R8Ki) :: CurrentTime !< Current Simulation Time [s] + INTEGER(IntKi) :: SimStatus !< simulation status (see avrSWAP(1): Status flag set as follows: 0 if this is the first call, 1 for all subsequent time steps, -1 if this is the final call at the end of the simulation) [-] + INTEGER(IntKi) :: ShaftBrakeStatusBinaryFlag !< binary flag indicating (on/off) status for shaft brake 1, shaft brake 2, generator brake, shaft brake 3, or brake torque set separately (0, 1, or 16 allowed in FAST) [-] + LOGICAL :: HSSBrDeployed !< Whether the HSS brake has been deployed [-] + REAL(R8Ki) :: TimeHSSBrFullyDeployed !< Time at which the controller high-speed shaft is fully deployed [s] + REAL(R8Ki) :: TimeHSSBrDeployed !< Time at which the controller high-speed shaft is first deployed [s] + LOGICAL :: OverrideYawRateWithTorque !< acts similiar to Yaw_Cntrl [-] + REAL(ReKi) :: YawTorqueDemand !< Demanded yaw actuator torque (override of yaw rate control) [Nm] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchInput !< Input blade pitch angles [radians] + REAL(ReKi) :: YawAngleFromNorth !< Yaw angle of the nacelle relative to North (see NacYaw_North) [rad] + REAL(ReKi) :: HorWindV !< Horizontal hub-height wind velocity magnitude [m/s] + REAL(ReKi) :: HSS_Spd !< High-speed shaft (HSS) speed [rad/s] + REAL(ReKi) :: YawErr !< Yaw error [radians] + REAL(ReKi) :: RotSpeed !< Rotor azimuth angular speed [rad/s] + REAL(ReKi) :: YawBrTAxp !< Tower-top / yaw bearing fore-aft (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: YawBrTAyp !< Tower-top / yaw bearing side-to-side (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: LSSTipMys !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMzs !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMya !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMza !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipPxa !< Rotor azimuth angle (position) [radians] + REAL(ReKi) :: Yaw !< Current nacelle yaw [radians] + REAL(ReKi) :: YawRate !< Current nacelle yaw rate [rad/s] + REAL(ReKi) :: YawBrMyn !< Rotating (with nacelle) tower-top / yaw bearing pitch moment [N-m] + REAL(ReKi) :: YawBrMzn !< Tower-top / yaw bearing yaw moment [N-m] + REAL(ReKi) :: NcIMURAxs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAys !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAzs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: RotPwr !< Rotor power (this is equivalent to the low-speed shaft power) [W] + REAL(ReKi) :: LSSTipMxa !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) , DIMENSION(1:3) :: RootMyc !< Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3) [N-m] + REAL(ReKi) , DIMENSION(1:3) :: RootMxc !< In-plane moment (i.e., the moment caused by in-plane forces) at the blade root [N-m] + REAL(DbKi) :: DLL_DT !< interval for calling DLL (integer multiple number of DT) [s] + CHARACTER(1024) :: DLL_InFile !< Name of input file used in DLL [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) :: GenTrq_Dem !< Demanded generator torque above rated [Nm] + REAL(ReKi) :: GenSpd_Dem !< Demanded generator speed above rated [rad/s] + REAL(ReKi) :: Ptch_Max !< Maximum pitch angle [rad] + REAL(ReKi) :: Ptch_Min !< Minimum pitch angle [rad] + REAL(ReKi) :: Ptch_SetPnt !< Below-rated pitch angle set-point [rad] + REAL(ReKi) :: PtchRate_Max !< Maximum pitch rate [rad/s] + REAL(ReKi) :: PtchRate_Min !< Minimum pitch rate (most negative value allowed) [rad/s] + REAL(ReKi) :: GenPwr_Dem !< Demanded power (This is not valid for variable-speed, pitch-regulated controllers.) [W] + REAL(ReKi) :: Gain_OM !< Optimal mode gain [Nm/(rad/s)^2] + REAL(ReKi) :: GenSpd_MaxOM !< Optimal mode maximum speed [rad/s] + REAL(ReKi) :: GenSpd_MinOM !< Minimum generator speed [rad/s] + INTEGER(IntKi) :: Ptch_Cntrl !< Pitch control: 0 = collective; 1 = individual [-] + INTEGER(IntKi) :: DLL_NumTrq !< No. of points in torque-speed look-up table, 0 = none and use the optimal mode PARAMETERs instead; nonzero = ignore the optimal mode PARAMETERs by setting Record 16 to 0.0 [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: GenSpd_TLU !< Table (array) containing DLL_NumTrq generator speeds for the torque-speed table look-up (TLU) -- this should be defined using an array constructor; for example, if DLL_NumTrq = 3, GenSpd_TLU(DLL_NumTrq) = (/ 0.0, 99.9, 999.9 /) [rad/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: GenTrq_TLU !< Table (array) containing DLL_NumTrq generator torques for the torque-speed table look-up (TLU) -- this should be defined using an array constructor, for example, if DLL_NumTrq = 3, GenTrq_TLU(DLL_NumTrq) = (/ 0.0, 10, 200.0 /) [Nm] + INTEGER(IntKi) :: Yaw_Cntrl !< Yaw control: 0 = rate; 1 = torque [-] + END TYPE BladedDLLType +! ======================= +! ========= SrvD_ContinuousStateType ======= + TYPE, PUBLIC :: SrvD_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + TYPE(TMD_ContinuousStateType) :: NTMD !< TMD module states - nacelle [-] + TYPE(TMD_ContinuousStateType) :: TTMD !< TMD module states - tower [-] + END TYPE SrvD_ContinuousStateType +! ======================= +! ========= SrvD_DiscreteStateType ======= + TYPE, PUBLIC :: SrvD_DiscreteStateType + REAL(ReKi) :: CtrlOffset !< Controller offset parameter [N-m] + TYPE(TMD_DiscreteStateType) :: NTMD !< TMD module states - nacelle [-] + TYPE(TMD_DiscreteStateType) :: TTMD !< TMD module states - tower [-] + END TYPE SrvD_DiscreteStateType +! ======================= +! ========= SrvD_ConstraintStateType ======= + TYPE, PUBLIC :: SrvD_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + TYPE(TMD_ConstraintStateType) :: NTMD !< TMD module states - nacelle [-] + TYPE(TMD_ConstraintStateType) :: TTMD !< TMD module states - tower [-] + END TYPE SrvD_ConstraintStateType +! ======================= +! ========= SrvD_OtherStateType ======= + TYPE, PUBLIC :: SrvD_OtherStateType + LOGICAL , DIMENSION(:), ALLOCATABLE :: BegPitMan !< Whether the override pitch maneuver actually began [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchI !< Initial blade pitch angles at the start of the override pitch maneuver [radians] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: TPitManE !< Time to end pitch maneuvers for each blade [s] + LOGICAL :: BegYawMan !< Whether the yaw maneuver actually began [-] + REAL(ReKi) :: NacYawI !< Initial yaw angle at the start of the override yaw maneuver [radians] + REAL(DbKi) :: TYawManE !< Time to end override yaw maneuver [s] + REAL(ReKi) :: YawPosComInt !< Internal variable that integrates the commanded yaw rate and passes it to YawPosCom [radians] + LOGICAL , DIMENSION(:), ALLOCATABLE :: BegTpBr !< Whether the tip brakes actually deployed [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: TTpBrDp !< Times to initiate deployment of tip brakes [s] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: TTpBrFl !< Times at which tip brakes are fully deployed [s] + LOGICAL :: Off4Good !< Is the generator offline for rest of simulation? [-] + LOGICAL :: GenOnLine !< Is the generator online? [-] + TYPE(TMD_OtherStateType) :: NTMD !< TMD module states - nacelle [-] + TYPE(TMD_OtherStateType) :: TTMD !< TMD module states - tower [-] + END TYPE SrvD_OtherStateType +! ======================= +! ========= SrvD_MiscVarType ======= + TYPE, PUBLIC :: SrvD_MiscVarType + REAL(DbKi) :: LastTimeCalled !< last time the CalcOutput/Bladed DLL was called [s] + TYPE(BladedDLLType) :: dll_data !< data used for Bladed DLL [-] + LOGICAL :: FirstWarn !< Whether or not this is the first warning about the DLL being called without Explicit-Loose coupling. [-] + REAL(DbKi) :: LastTimeFiltered !< last time the CalcOutput/Bladed DLL was filtered [s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: xd_BlPitchFilter !< blade pitch filter [-] + TYPE(TMD_MiscVarType) :: NTMD !< TMD module misc vars - nacelle [-] + TYPE(TMD_MiscVarType) :: TTMD !< TMD module misc vars - tower [-] + END TYPE SrvD_MiscVarType +! ======================= +! ========= SrvD_ParameterType ======= + TYPE, PUBLIC :: SrvD_ParameterType + REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [seconds] + REAL(DbKi) :: HSSBrDT !< Time it takes for HSS brake to reach full deployment once deployed [seconds] + REAL(ReKi) :: HSSBrTqF !< Fully deployed HSS brake torque [-] + REAL(ReKi) :: SIG_POSl !< Pullout slip [-] + REAL(ReKi) :: SIG_POTq !< Pullout torque [-] + REAL(ReKi) :: SIG_SlPc !< Rated generator slip percentage [-] + REAL(ReKi) :: SIG_Slop !< Torque/Speed slope for simple induction generator [-] + REAL(ReKi) :: SIG_SySp !< Synchronous (zero-torque) generator speed [rad/s] + REAL(ReKi) :: TEC_A0 !< A0 term for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_C0 !< C0 term for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_C1 !< C1 term for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_C2 !< C2 term for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_K2 !< K2 term for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_MR !< Magnetizing reactance for Thevenin-equivalent circuit [ohms] + REAL(ReKi) :: TEC_Re1 !< Thevenin's equivalent stator resistance (ohms) [ohms] + REAL(ReKi) :: TEC_RLR !< Rotor leakage reactance for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_RRes !< Rotor resistance for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_SRes !< Stator resistance for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_SySp !< Synchronous speed for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_V1a !< Source voltage for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_VLL !< Line-to-line RMS voltage for Thevenin-equivalent circuit [-] + REAL(ReKi) :: TEC_Xe1 !< Thevenin's equivalent stator leakage reactance (ohms) [ohms] + REAL(ReKi) :: GenEff !< Generator efficiency [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchInit !< Initial blade pitch angles [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchF !< Final blade pitch [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PitManRat !< Pitch rates at which override pitch maneuvers head toward final pitch angles (does not include sign) [rad/s] + REAL(ReKi) :: YawManRat !< Yaw rate at which override yaw maneuver head toward for final yaw angle (does not include sign) [rad/s] + REAL(ReKi) :: NacYawF !< Final yaw angle after override yaw maneuver [-] + REAL(ReKi) :: SpdGenOn !< Generator speed to turn on the generator for a startup [-] + REAL(DbKi) :: THSSBrDp !< Time to initiate deployment of the shaft brake [s] + REAL(DbKi) :: THSSBrFl !< Time at which shaft brake is fully deployed [s] + REAL(DbKi) :: TimGenOf !< Time to turn off generator for braking or modeling a run-away [s] + REAL(DbKi) :: TimGenOn !< Time to turn on generator for startup [s] + REAL(DbKi) :: TPCOn !< Time to enable active pitch control [s] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: TPitManS !< Time to start pitch maneuvers for each blade [s] + REAL(DbKi) :: TYawManS !< Time to start override yaw maneuver [s] + REAL(DbKi) :: TYCOn !< Time to enable active yaw control [s] + REAL(ReKi) :: VS_RtGnSp !< Rated generator speed (HSS side) [rad/s] + REAL(ReKi) :: VS_RtTq !< Rated generator torque/constant generator torque in Region 3 (HSS side) [N-m] + REAL(ReKi) :: VS_Slope !< Torque/speed slope of region 2 1/2 induction generator [-] + REAL(ReKi) :: VS_SlPc !< Rated generator slip percentage in Region 2 1/2 [-] + REAL(ReKi) :: VS_SySp !< Synchronous speed of region 2 1/2 induction generator [-] + REAL(ReKi) :: VS_TrGnSp !< Transitional generator speed between regions 2 and 2 1/2 [-] + REAL(ReKi) :: YawPosCom !< Commanded yaw angle from user-defined routines [rad] + REAL(ReKi) :: YawRateCom !< Commanded yaw rate from user-defined routines [rad/s] + INTEGER(IntKi) :: GenModel !< Generator model [-] + INTEGER(IntKi) :: HSSBrMode !< HSS brake model [-] + INTEGER(IntKi) :: PCMode !< Pitch control mode [-] + INTEGER(IntKi) :: VSContrl !< Variable-speed-generator control switch [-] + INTEGER(IntKi) :: YCMode !< Yaw control mode [-] + LOGICAL :: GenTiStp !< Stop generator based upon T: time or F: generator power = 0 [-] + LOGICAL :: GenTiStr !< Start generator based upon T: time or F: generator speed [-] + REAL(ReKi) :: VS_Rgn2K !< Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) [used only when VSContrl=1] [N-m/(rad/s)^2] + REAL(ReKi) :: YawNeut !< Neutral yaw position--yaw spring force is zero at this yaw [radians] + REAL(ReKi) :: YawSpr !< Nacelle-yaw spring constant [N-m/rad] + REAL(ReKi) :: YawDamp !< Nacelle-yaw constant [N-m/(rad/s)] + REAL(DbKi) :: TpBrDT !< Time for tip-brake to reach full deployment once released [s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TBDepISp !< Deployment-initiation speed for the tip brakes [rad/s] + REAL(ReKi) :: TBDrConN !< Tip-brake drag constant during normal operation, Cd*Area [-] + REAL(ReKi) :: TBDrConD !< Tip-brake drag constant during fully-deployed operation, Cd*Area [-] + INTEGER(IntKi) :: NumBl !< Number of blades on the turbine [-] + LOGICAL :: CompNTMD !< Compute nacelle tuned mass damper {true/false} [-] + LOGICAL :: CompTTMD !< Compute tower tuned mass damper {true/false} [-] + INTEGER(IntKi) :: NumOuts !< Number of parameters in the output list (number of outputs requested) [-] + INTEGER(IntKi) :: NumOuts_DLL !< Number of logging channels output from the DLL (set at initialization) [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + LOGICAL :: UseBladedInterface !< Flag that determines if BladedInterface was used [-] + LOGICAL :: UseLegacyInterface !< Flag that determines if the legacy Bladed interface is (legacy=DISCON with avrSWAP instead of CONTROLLER) [-] + TYPE(DLL_Type) :: DLL_Trgt !< The addresses and names of the Bladed DLL and its procedure [-] + LOGICAL :: DLL_Ramp !< determines if there is a DLL_DT-ramp time delay (true only when DLL_DT /= DT) [-] + REAL(ReKi) :: BlAlpha !< parameter for low-pass filter of blade pitch commands from the controller DLL [-] + INTEGER(IntKi) :: DLL_n !< number of steps between the controller being called and SrvD being called [-] + INTEGER(IntKi) :: avcOUTNAME_LEN !< Length of the avcOUTNAME character array passed to/from the DLL [-] + REAL(ReKi) :: NacYaw_North !< Reference yaw angle of the nacelle when the upwind end points due North [rad] + REAL(ReKi) :: AvgWindSpeed !< average wind speed for the simulation [m/s] + REAL(ReKi) :: AirDens !< air density [kg/m^3] + INTEGER(IntKi) :: TrimCase !< Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] [-] + REAL(ReKi) :: TrimGain !< Proportional gain for the rotational speed error (>0) [used only if TrimCase>0] [rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque] + REAL(ReKi) :: RotSpeedRef !< Reference rotor speed [rad/s] + TYPE(TMD_ParameterType) :: NTMD !< TMD module parameters - nacelle [-] + TYPE(TMD_ParameterType) :: TTMD !< TMD module parameters - tower [-] + END TYPE SrvD_ParameterType +! ======================= +! ========= SrvD_InputType ======= + TYPE, PUBLIC :: SrvD_InputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitch !< Current blade pitch angles [radians] + REAL(ReKi) :: Yaw !< Current nacelle yaw [radians] + REAL(ReKi) :: YawRate !< Current nacelle yaw rate [rad/s] + REAL(ReKi) :: LSS_Spd !< Low-speed shaft (LSS) speed at entrance to gearbox [rad/s] + REAL(ReKi) :: HSS_Spd !< High-speed shaft (HSS) speed [rad/s] + REAL(ReKi) :: RotSpeed !< Rotor azimuth angular speed [rad/s] + REAL(ReKi) :: ExternalYawPosCom !< Commanded nacelle yaw position from Simulink or Labview [radians] + REAL(ReKi) :: ExternalYawRateCom !< Commanded nacelle yaw rate from Simulink or Labview [rad/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ExternalBlPitchCom !< Commanded blade pitch from Simulink or LabVIEW [radians] + REAL(ReKi) :: ExternalGenTrq !< Electrical generator torque from Simulink or LabVIEW [N-m] + REAL(ReKi) :: ExternalElecPwr !< Electrical power from Simulink or LabVIEW [W] + REAL(ReKi) :: ExternalHSSBrFrac !< Fraction of full braking torque: 0 (off) <= HSSBrFrac <= 1 (full) from Simulink or LabVIEW [-] + REAL(ReKi) :: TwrAccel !< Tower acceleration for tower feedback control (user routine only) [m/s^2] + REAL(ReKi) :: YawErr !< Yaw error [radians] + REAL(ReKi) :: WindDir !< Wind direction [radians] + REAL(ReKi) , DIMENSION(1:3) :: RootMyc !< Out-of-plane moment (i.e., the moment caused by out-of-plane forces) at the blade root for each of the blades (max 3) [N-m] + REAL(ReKi) :: YawBrTAxp !< Tower-top / yaw bearing fore-aft (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: YawBrTAyp !< Tower-top / yaw bearing side-to-side (translational) acceleration (absolute) [m/s^2] + REAL(ReKi) :: LSSTipPxa !< Rotor azimuth angle (position) [radians] + REAL(ReKi) , DIMENSION(1:3) :: RootMxc !< In-plane moment (i.e., the moment caused by in-plane forces) at the blade root [N-m] + REAL(ReKi) :: LSSTipMxa !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMya !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMza !< Rotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMys !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: LSSTipMzs !< Nonrotating low-speed shaft bending moment at the shaft tip (teeter pin for 2-blader, apex of rotation for 3-blader) [N-m] + REAL(ReKi) :: YawBrMyn !< Rotating (with nacelle) tower-top / yaw bearing pitch moment [N-m] + REAL(ReKi) :: YawBrMzn !< Tower-top / yaw bearing yaw moment [N-m] + REAL(ReKi) :: NcIMURAxs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAys !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: NcIMURAzs !< Nacelle inertial measurement unit angular (rotational) acceleration (absolute) [rad/s^2] + REAL(ReKi) :: RotPwr !< Rotor power (this is equivalent to the low-speed shaft power) [W] + REAL(ReKi) :: HorWindV !< Horizontal hub-height wind velocity magnitude [m/s] + REAL(ReKi) :: YawAngle !< Estimate of yaw (nacelle + platform) [radians] + TYPE(TMD_InputType) :: NTMD !< TMD module inputs - nacelle [-] + TYPE(TMD_InputType) :: TTMD !< TMD module inputs - tower [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: SuperController !< A swap array: used to pass input data to the DLL controller from the supercontroller [-] + END TYPE SrvD_InputType +! ======================= +! ========= SrvD_OutputType ======= + TYPE, PUBLIC :: SrvD_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file: see WriteOutputHdr for names of each variable [see WriteOutputUnt] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlPitchCom !< Commanded blade pitch angles [radians] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: BlAirfoilCom !< Commanded Airfoil UserProp for blade. Passed to AD15 for airfoil interpolation (must be same units as given in AD15 airfoil tables) [-] + REAL(ReKi) :: YawMom !< Torque transmitted through the yaw bearing [N-m] + REAL(ReKi) :: GenTrq !< Electrical generator torque [N-m] + REAL(ReKi) :: HSSBrTrqC !< Commanded HSS brake torque [N-m] + REAL(ReKi) :: ElecPwr !< Electrical power [W] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TBDrCon !< Instantaneous tip-brake drag constant, Cd*Area [-] + TYPE(TMD_OutputType) :: NTMD !< TMD module outputs - nacelle [-] + TYPE(TMD_OutputType) :: TTMD !< TMD module outputs - tower [-] + REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: SuperController !< A swap array: used to pass output data from the DLL controller to the supercontroller [-] + END TYPE SrvD_OutputType +! ======================= +CONTAINS + SUBROUTINE SrvD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SrvD_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 = 'SrvD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%NumBl = SrcInitInputData%NumBl + DstInitInputData%RootName = SrcInitInputData%RootName +IF (ALLOCATED(SrcInitInputData%BlPitchInit)) THEN + i1_l = LBOUND(SrcInitInputData%BlPitchInit,1) + i1_u = UBOUND(SrcInitInputData%BlPitchInit,1) + IF (.NOT. ALLOCATED(DstInitInputData%BlPitchInit)) THEN + ALLOCATE(DstInitInputData%BlPitchInit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%BlPitchInit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%BlPitchInit = SrcInitInputData%BlPitchInit +ENDIF + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%r_N_O_G = SrcInitInputData%r_N_O_G + DstInitInputData%r_TwrBase = SrcInitInputData%r_TwrBase + DstInitInputData%Tmax = SrcInitInputData%Tmax + DstInitInputData%AvgWindSpeed = SrcInitInputData%AvgWindSpeed + DstInitInputData%AirDens = SrcInitInputData%AirDens + DstInitInputData%NumSC2Ctrl = SrcInitInputData%NumSC2Ctrl + DstInitInputData%NumCtrl2SC = SrcInitInputData%NumCtrl2SC + DstInitInputData%TrimCase = SrcInitInputData%TrimCase + DstInitInputData%TrimGain = SrcInitInputData%TrimGain + DstInitInputData%RotSpeedRef = SrcInitInputData%RotSpeedRef + END SUBROUTINE SrvD_CopyInitInput + + SUBROUTINE SrvD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SrvD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%BlPitchInit)) THEN + DEALLOCATE(InitInputData%BlPitchInit) +ENDIF + END SUBROUTINE SrvD_DestroyInitInput + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! Linearize + Int_BufSz = Int_BufSz + 1 ! NumBl + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! BlPitchInit allocated yes/no + IF ( ALLOCATED(InData%BlPitchInit) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchInit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchInit) ! BlPitchInit + END IF + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + SIZE(InData%r_N_O_G) ! r_N_O_G + Re_BufSz = Re_BufSz + SIZE(InData%r_TwrBase) ! r_TwrBase + Db_BufSz = Db_BufSz + 1 ! Tmax + Re_BufSz = Re_BufSz + 1 ! AvgWindSpeed + Re_BufSz = Re_BufSz + 1 ! AirDens + Int_BufSz = Int_BufSz + 1 ! NumSC2Ctrl + Int_BufSz = Int_BufSz + 1 ! NumCtrl2SC + Int_BufSz = Int_BufSz + 1 ! TrimCase + Re_BufSz = Re_BufSz + 1 ! TrimGain + Re_BufSz = Re_BufSz + 1 ! RotSpeedRef + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%BlPitchInit) ) 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%BlPitchInit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchInit,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchInit,1), UBOUND(InData%BlPitchInit,1) + ReKiBuf(Re_Xferred) = InData%BlPitchInit(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%r_N_O_G,1), UBOUND(InData%r_N_O_G,1) + ReKiBuf(Re_Xferred) = InData%r_N_O_G(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%r_TwrBase,1), UBOUND(InData%r_TwrBase,1) + ReKiBuf(Re_Xferred) = InData%r_TwrBase(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%Tmax + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AvgWindSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumSC2Ctrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCtrl2SC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TrimCase + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TrimGain + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeedRef + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SrvD_PackInitInput + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchInit 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%BlPitchInit)) DEALLOCATE(OutData%BlPitchInit) + ALLOCATE(OutData%BlPitchInit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchInit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchInit,1), UBOUND(OutData%BlPitchInit,1) + OutData%BlPitchInit(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%r_N_O_G,1) + i1_u = UBOUND(OutData%r_N_O_G,1) + DO i1 = LBOUND(OutData%r_N_O_G,1), UBOUND(OutData%r_N_O_G,1) + OutData%r_N_O_G(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%r_TwrBase,1) + i1_u = UBOUND(OutData%r_TwrBase,1) + DO i1 = LBOUND(OutData%r_TwrBase,1), UBOUND(OutData%r_TwrBase,1) + OutData%r_TwrBase(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%Tmax = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%AvgWindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumSC2Ctrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumCtrl2SC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TrimCase = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TrimGain = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeedRef = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SrvD_UnPackInitInput + + SUBROUTINE SrvD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SrvD_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 = 'SrvD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitOutputData%CouplingScheme = SrcInitOutputData%CouplingScheme + DstInitOutputData%UseHSSBrake = SrcInitOutputData%UseHSSBrake +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF + END SUBROUTINE SrvD_CopyInitOutput + + SUBROUTINE SrvD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SrvD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF + END SUBROUTINE SrvD_DestroyInitOutput + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + 1 ! CouplingScheme + Int_BufSz = Int_BufSz + 1 ! UseHSSBrake + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 + IntKiBuf(Int_Xferred) = InData%CouplingScheme + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseHSSBrake, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) 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%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) 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%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) 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%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) 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%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) 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%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_PackInitOutput + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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%CouplingScheme = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UseHSSBrake = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseHSSBrake) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y 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%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u 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%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y 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%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u 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%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u 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%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_UnPackInitOutput + + SUBROUTINE SrvD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(SrvD_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'SrvD_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%DT = SrcInputFileData%DT + DstInputFileData%PCMode = SrcInputFileData%PCMode + DstInputFileData%TPCOn = SrcInputFileData%TPCOn + DstInputFileData%TPitManS = SrcInputFileData%TPitManS + DstInputFileData%PitManRat = SrcInputFileData%PitManRat + DstInputFileData%BlPitchF = SrcInputFileData%BlPitchF + DstInputFileData%VSContrl = SrcInputFileData%VSContrl + DstInputFileData%GenModel = SrcInputFileData%GenModel + DstInputFileData%GenEff = SrcInputFileData%GenEff + DstInputFileData%GenTiStr = SrcInputFileData%GenTiStr + DstInputFileData%GenTiStp = SrcInputFileData%GenTiStp + DstInputFileData%SpdGenOn = SrcInputFileData%SpdGenOn + DstInputFileData%TimGenOn = SrcInputFileData%TimGenOn + DstInputFileData%TimGenOf = SrcInputFileData%TimGenOf + DstInputFileData%VS_RtGnSp = SrcInputFileData%VS_RtGnSp + DstInputFileData%VS_RtTq = SrcInputFileData%VS_RtTq + DstInputFileData%VS_Rgn2K = SrcInputFileData%VS_Rgn2K + DstInputFileData%VS_SlPc = SrcInputFileData%VS_SlPc + DstInputFileData%SIG_SlPc = SrcInputFileData%SIG_SlPc + DstInputFileData%SIG_SySp = SrcInputFileData%SIG_SySp + DstInputFileData%SIG_RtTq = SrcInputFileData%SIG_RtTq + DstInputFileData%SIG_PORt = SrcInputFileData%SIG_PORt + DstInputFileData%TEC_Freq = SrcInputFileData%TEC_Freq + DstInputFileData%TEC_NPol = SrcInputFileData%TEC_NPol + DstInputFileData%TEC_SRes = SrcInputFileData%TEC_SRes + DstInputFileData%TEC_RRes = SrcInputFileData%TEC_RRes + DstInputFileData%TEC_VLL = SrcInputFileData%TEC_VLL + DstInputFileData%TEC_SLR = SrcInputFileData%TEC_SLR + DstInputFileData%TEC_RLR = SrcInputFileData%TEC_RLR + DstInputFileData%TEC_MR = SrcInputFileData%TEC_MR + DstInputFileData%HSSBrMode = SrcInputFileData%HSSBrMode + DstInputFileData%THSSBrDp = SrcInputFileData%THSSBrDp + DstInputFileData%HSSBrDT = SrcInputFileData%HSSBrDT + DstInputFileData%HSSBrTqF = SrcInputFileData%HSSBrTqF + DstInputFileData%YCMode = SrcInputFileData%YCMode + DstInputFileData%TYCOn = SrcInputFileData%TYCOn + DstInputFileData%YawNeut = SrcInputFileData%YawNeut + DstInputFileData%YawSpr = SrcInputFileData%YawSpr + DstInputFileData%YawDamp = SrcInputFileData%YawDamp + DstInputFileData%TYawManS = SrcInputFileData%TYawManS + DstInputFileData%YawManRat = SrcInputFileData%YawManRat + DstInputFileData%NacYawF = SrcInputFileData%NacYawF + DstInputFileData%SumPrint = SrcInputFileData%SumPrint + DstInputFileData%OutFile = SrcInputFileData%OutFile + DstInputFileData%TabDelim = SrcInputFileData%TabDelim + DstInputFileData%OutFmt = SrcInputFileData%OutFmt + DstInputFileData%Tstart = SrcInputFileData%Tstart + DstInputFileData%NumOuts = SrcInputFileData%NumOuts +IF (ALLOCATED(SrcInputFileData%OutList)) THEN + i1_l = LBOUND(SrcInputFileData%OutList,1) + i1_u = UBOUND(SrcInputFileData%OutList,1) + IF (.NOT. ALLOCATED(DstInputFileData%OutList)) THEN + ALLOCATE(DstInputFileData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%OutList = SrcInputFileData%OutList +ENDIF + DstInputFileData%DLL_FileName = SrcInputFileData%DLL_FileName + DstInputFileData%DLL_ProcName = SrcInputFileData%DLL_ProcName + DstInputFileData%DLL_InFile = SrcInputFileData%DLL_InFile + DstInputFileData%DLL_DT = SrcInputFileData%DLL_DT + DstInputFileData%DLL_Ramp = SrcInputFileData%DLL_Ramp + DstInputFileData%BPCutoff = SrcInputFileData%BPCutoff + DstInputFileData%NacYaw_North = SrcInputFileData%NacYaw_North + DstInputFileData%Ptch_Cntrl = SrcInputFileData%Ptch_Cntrl + DstInputFileData%Ptch_SetPnt = SrcInputFileData%Ptch_SetPnt + DstInputFileData%Ptch_Min = SrcInputFileData%Ptch_Min + DstInputFileData%Ptch_Max = SrcInputFileData%Ptch_Max + DstInputFileData%PtchRate_Min = SrcInputFileData%PtchRate_Min + DstInputFileData%PtchRate_Max = SrcInputFileData%PtchRate_Max + DstInputFileData%Gain_OM = SrcInputFileData%Gain_OM + DstInputFileData%GenSpd_MinOM = SrcInputFileData%GenSpd_MinOM + DstInputFileData%GenSpd_MaxOM = SrcInputFileData%GenSpd_MaxOM + DstInputFileData%GenSpd_Dem = SrcInputFileData%GenSpd_Dem + DstInputFileData%GenTrq_Dem = SrcInputFileData%GenTrq_Dem + DstInputFileData%GenPwr_Dem = SrcInputFileData%GenPwr_Dem + DstInputFileData%DLL_NumTrq = SrcInputFileData%DLL_NumTrq +IF (ALLOCATED(SrcInputFileData%GenSpd_TLU)) THEN + i1_l = LBOUND(SrcInputFileData%GenSpd_TLU,1) + i1_u = UBOUND(SrcInputFileData%GenSpd_TLU,1) + IF (.NOT. ALLOCATED(DstInputFileData%GenSpd_TLU)) THEN + ALLOCATE(DstInputFileData%GenSpd_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%GenSpd_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%GenSpd_TLU = SrcInputFileData%GenSpd_TLU +ENDIF +IF (ALLOCATED(SrcInputFileData%GenTrq_TLU)) THEN + i1_l = LBOUND(SrcInputFileData%GenTrq_TLU,1) + i1_u = UBOUND(SrcInputFileData%GenTrq_TLU,1) + IF (.NOT. ALLOCATED(DstInputFileData%GenTrq_TLU)) THEN + ALLOCATE(DstInputFileData%GenTrq_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%GenTrq_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%GenTrq_TLU = SrcInputFileData%GenTrq_TLU +ENDIF + DstInputFileData%UseLegacyInterface = SrcInputFileData%UseLegacyInterface + DstInputFileData%CompNTMD = SrcInputFileData%CompNTMD + DstInputFileData%NTMDfile = SrcInputFileData%NTMDfile + DstInputFileData%CompTTMD = SrcInputFileData%CompTTMD + DstInputFileData%TTMDfile = SrcInputFileData%TTMDfile + END SUBROUTINE SrvD_CopyInputFile + + SUBROUTINE SrvD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(SrvD_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%OutList)) THEN + DEALLOCATE(InputFileData%OutList) +ENDIF +IF (ALLOCATED(InputFileData%GenSpd_TLU)) THEN + DEALLOCATE(InputFileData%GenSpd_TLU) +ENDIF +IF (ALLOCATED(InputFileData%GenTrq_TLU)) THEN + DEALLOCATE(InputFileData%GenTrq_TLU) +ENDIF + END SUBROUTINE SrvD_DestroyInputFile + + SUBROUTINE SrvD_PackInputFile( 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(SrvD_InputFile), 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 = 'SrvD_PackInputFile' + ! 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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! PCMode + Db_BufSz = Db_BufSz + 1 ! TPCOn + Db_BufSz = Db_BufSz + SIZE(InData%TPitManS) ! TPitManS + Re_BufSz = Re_BufSz + SIZE(InData%PitManRat) ! PitManRat + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchF) ! BlPitchF + Int_BufSz = Int_BufSz + 1 ! VSContrl + Int_BufSz = Int_BufSz + 1 ! GenModel + Re_BufSz = Re_BufSz + 1 ! GenEff + Int_BufSz = Int_BufSz + 1 ! GenTiStr + Int_BufSz = Int_BufSz + 1 ! GenTiStp + Re_BufSz = Re_BufSz + 1 ! SpdGenOn + Db_BufSz = Db_BufSz + 1 ! TimGenOn + Db_BufSz = Db_BufSz + 1 ! TimGenOf + Re_BufSz = Re_BufSz + 1 ! VS_RtGnSp + Re_BufSz = Re_BufSz + 1 ! VS_RtTq + Re_BufSz = Re_BufSz + 1 ! VS_Rgn2K + Re_BufSz = Re_BufSz + 1 ! VS_SlPc + Re_BufSz = Re_BufSz + 1 ! SIG_SlPc + Re_BufSz = Re_BufSz + 1 ! SIG_SySp + Re_BufSz = Re_BufSz + 1 ! SIG_RtTq + Re_BufSz = Re_BufSz + 1 ! SIG_PORt + Re_BufSz = Re_BufSz + 1 ! TEC_Freq + Int_BufSz = Int_BufSz + 1 ! TEC_NPol + Re_BufSz = Re_BufSz + 1 ! TEC_SRes + Re_BufSz = Re_BufSz + 1 ! TEC_RRes + Re_BufSz = Re_BufSz + 1 ! TEC_VLL + Re_BufSz = Re_BufSz + 1 ! TEC_SLR + Re_BufSz = Re_BufSz + 1 ! TEC_RLR + Re_BufSz = Re_BufSz + 1 ! TEC_MR + Int_BufSz = Int_BufSz + 1 ! HSSBrMode + Db_BufSz = Db_BufSz + 1 ! THSSBrDp + Db_BufSz = Db_BufSz + 1 ! HSSBrDT + Re_BufSz = Re_BufSz + 1 ! HSSBrTqF + Int_BufSz = Int_BufSz + 1 ! YCMode + Db_BufSz = Db_BufSz + 1 ! TYCOn + Re_BufSz = Re_BufSz + 1 ! YawNeut + Re_BufSz = Re_BufSz + 1 ! YawSpr + Re_BufSz = Re_BufSz + 1 ! YawDamp + Db_BufSz = Db_BufSz + 1 ! TYawManS + Re_BufSz = Re_BufSz + 1 ! YawManRat + Re_BufSz = Re_BufSz + 1 ! NacYawF + Int_BufSz = Int_BufSz + 1 ! SumPrint + Int_BufSz = Int_BufSz + 1 ! OutFile + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Db_BufSz = Db_BufSz + 1 ! Tstart + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutList allocated yes/no + IF ( ALLOCATED(InData%OutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_FileName) ! DLL_FileName + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_ProcName) ! DLL_ProcName + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_InFile) ! DLL_InFile + Db_BufSz = Db_BufSz + 1 ! DLL_DT + Int_BufSz = Int_BufSz + 1 ! DLL_Ramp + Re_BufSz = Re_BufSz + 1 ! BPCutoff + Re_BufSz = Re_BufSz + 1 ! NacYaw_North + Int_BufSz = Int_BufSz + 1 ! Ptch_Cntrl + Re_BufSz = Re_BufSz + 1 ! Ptch_SetPnt + Re_BufSz = Re_BufSz + 1 ! Ptch_Min + Re_BufSz = Re_BufSz + 1 ! Ptch_Max + Re_BufSz = Re_BufSz + 1 ! PtchRate_Min + Re_BufSz = Re_BufSz + 1 ! PtchRate_Max + Re_BufSz = Re_BufSz + 1 ! Gain_OM + Re_BufSz = Re_BufSz + 1 ! GenSpd_MinOM + Re_BufSz = Re_BufSz + 1 ! GenSpd_MaxOM + Re_BufSz = Re_BufSz + 1 ! GenSpd_Dem + Re_BufSz = Re_BufSz + 1 ! GenTrq_Dem + Re_BufSz = Re_BufSz + 1 ! GenPwr_Dem + Int_BufSz = Int_BufSz + 1 ! DLL_NumTrq + Int_BufSz = Int_BufSz + 1 ! GenSpd_TLU allocated yes/no + IF ( ALLOCATED(InData%GenSpd_TLU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! GenSpd_TLU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GenSpd_TLU) ! GenSpd_TLU + END IF + Int_BufSz = Int_BufSz + 1 ! GenTrq_TLU allocated yes/no + IF ( ALLOCATED(InData%GenTrq_TLU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! GenTrq_TLU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GenTrq_TLU) ! GenTrq_TLU + END IF + Int_BufSz = Int_BufSz + 1 ! UseLegacyInterface + Int_BufSz = Int_BufSz + 1 ! CompNTMD + Int_BufSz = Int_BufSz + 1*LEN(InData%NTMDfile) ! NTMDfile + Int_BufSz = Int_BufSz + 1 ! CompTTMD + Int_BufSz = Int_BufSz + 1*LEN(InData%TTMDfile) ! TTMDfile + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PCMode + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TPCOn + Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%TPitManS,1), UBOUND(InData%TPitManS,1) + DbKiBuf(Db_Xferred) = InData%TPitManS(i1) + Db_Xferred = Db_Xferred + 1 + END DO + DO i1 = LBOUND(InData%PitManRat,1), UBOUND(InData%PitManRat,1) + ReKiBuf(Re_Xferred) = InData%PitManRat(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%BlPitchF,1), UBOUND(InData%BlPitchF,1) + ReKiBuf(Re_Xferred) = InData%BlPitchF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%VSContrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%GenModel + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenEff + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenTiStr, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenTiStp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdGenOn + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimGenOn + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimGenOf + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_RtGnSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_RtTq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_Rgn2K + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_SlPc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_SlPc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_SySp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_RtTq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_PORt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_Freq + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TEC_NPol + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_SRes + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_RRes + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_VLL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_SLR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_RLR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_MR + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%HSSBrMode + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%THSSBrDp + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%HSSBrDT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSSBrTqF + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%YCMode + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TYCOn + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawNeut + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawDamp + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TYawManS + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawManRat + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYawF + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SumPrint, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutFile + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%Tstart + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutList) ) 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%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(InData%DLL_FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DLL_ProcName) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_ProcName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%DLL_InFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_InFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%DLL_DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%DLL_Ramp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BPCutoff + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYaw_North + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Ptch_Cntrl + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_SetPnt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_Min + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_Max + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtchRate_Min + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtchRate_Max + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gain_OM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_MinOM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_MaxOM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_Dem + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenTrq_Dem + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenPwr_Dem + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DLL_NumTrq + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%GenSpd_TLU) ) 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%GenSpd_TLU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GenSpd_TLU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%GenSpd_TLU,1), UBOUND(InData%GenSpd_TLU,1) + ReKiBuf(Re_Xferred) = InData%GenSpd_TLU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GenTrq_TLU) ) 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%GenTrq_TLU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GenTrq_TLU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%GenTrq_TLU,1), UBOUND(InData%GenTrq_TLU,1) + ReKiBuf(Re_Xferred) = InData%GenTrq_TLU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseLegacyInterface, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompNTMD, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%NTMDfile) + IntKiBuf(Int_Xferred) = ICHAR(InData%NTMDfile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompTTMD, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%TTMDfile) + IntKiBuf(Int_Xferred) = ICHAR(InData%TTMDfile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE SrvD_PackInputFile + + SUBROUTINE SrvD_UnPackInputFile( 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(SrvD_InputFile), 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 = 'SrvD_UnPackInputFile' + ! 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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%PCMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TPCOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + i1_l = LBOUND(OutData%TPitManS,1) + i1_u = UBOUND(OutData%TPitManS,1) + DO i1 = LBOUND(OutData%TPitManS,1), UBOUND(OutData%TPitManS,1) + OutData%TPitManS(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + i1_l = LBOUND(OutData%PitManRat,1) + i1_u = UBOUND(OutData%PitManRat,1) + DO i1 = LBOUND(OutData%PitManRat,1), UBOUND(OutData%PitManRat,1) + OutData%PitManRat(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%BlPitchF,1) + i1_u = UBOUND(OutData%BlPitchF,1) + DO i1 = LBOUND(OutData%BlPitchF,1), UBOUND(OutData%BlPitchF,1) + OutData%BlPitchF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%VSContrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%GenModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%GenEff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTiStr = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenTiStr) + Int_Xferred = Int_Xferred + 1 + OutData%GenTiStp = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenTiStp) + Int_Xferred = Int_Xferred + 1 + OutData%SpdGenOn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TimGenOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%TimGenOf = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%VS_RtGnSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_RtTq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_Rgn2K = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_SlPc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_SlPc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_SySp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_RtTq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_PORt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_Freq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_NPol = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TEC_SRes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_RRes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_VLL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_SLR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_RLR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_MR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSSBrMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%THSSBrDp = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HSSBrDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HSSBrTqF = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YCMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TYCOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%YawNeut = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawDamp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TYawManS = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%YawManRat = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacYawF = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SumPrint = TRANSFER(IntKiBuf(Int_Xferred), OutData%SumPrint) + Int_Xferred = Int_Xferred + 1 + OutData%OutFile = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Tstart = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList 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%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + DO I = 1, LEN(OutData%DLL_FileName) + OutData%DLL_FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DLL_ProcName) + OutData%DLL_ProcName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%DLL_InFile) + OutData%DLL_InFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%DLL_DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%DLL_Ramp = TRANSFER(IntKiBuf(Int_Xferred), OutData%DLL_Ramp) + Int_Xferred = Int_Xferred + 1 + OutData%BPCutoff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacYaw_North = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Cntrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Ptch_SetPnt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Min = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Max = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtchRate_Min = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtchRate_Max = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gain_OM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_MinOM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_MaxOM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTrq_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenPwr_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DLL_NumTrq = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GenSpd_TLU 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%GenSpd_TLU)) DEALLOCATE(OutData%GenSpd_TLU) + ALLOCATE(OutData%GenSpd_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GenSpd_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%GenSpd_TLU,1), UBOUND(OutData%GenSpd_TLU,1) + OutData%GenSpd_TLU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GenTrq_TLU 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%GenTrq_TLU)) DEALLOCATE(OutData%GenTrq_TLU) + ALLOCATE(OutData%GenTrq_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GenTrq_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%GenTrq_TLU,1), UBOUND(OutData%GenTrq_TLU,1) + OutData%GenTrq_TLU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%UseLegacyInterface = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseLegacyInterface) + Int_Xferred = Int_Xferred + 1 + OutData%CompNTMD = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompNTMD) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%NTMDfile) + OutData%NTMDfile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CompTTMD = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompTTMD) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%TTMDfile) + OutData%TTMDfile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE SrvD_UnPackInputFile + + SUBROUTINE SrvD_CopyBladedDLLType( SrcBladedDLLTypeData, DstBladedDLLTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladedDLLType), INTENT(IN) :: SrcBladedDLLTypeData + TYPE(BladedDLLType), INTENT(INOUT) :: DstBladedDLLTypeData + 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 = 'SrvD_CopyBladedDLLType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcBladedDLLTypeData%avrSWAP)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%avrSWAP,1) + i1_u = UBOUND(SrcBladedDLLTypeData%avrSWAP,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%avrSWAP)) THEN + ALLOCATE(DstBladedDLLTypeData%avrSWAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%avrSWAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%avrSWAP = SrcBladedDLLTypeData%avrSWAP +ENDIF + DstBladedDLLTypeData%HSSBrTrqDemand = SrcBladedDLLTypeData%HSSBrTrqDemand + DstBladedDLLTypeData%YawRateCom = SrcBladedDLLTypeData%YawRateCom + DstBladedDLLTypeData%GenTrq = SrcBladedDLLTypeData%GenTrq + DstBladedDLLTypeData%GenState = SrcBladedDLLTypeData%GenState + DstBladedDLLTypeData%BlPitchCom = SrcBladedDLLTypeData%BlPitchCom + DstBladedDLLTypeData%PrevBlPitch = SrcBladedDLLTypeData%PrevBlPitch + DstBladedDLLTypeData%BlAirfoilCom = SrcBladedDLLTypeData%BlAirfoilCom + DstBladedDLLTypeData%ElecPwr_prev = SrcBladedDLLTypeData%ElecPwr_prev + DstBladedDLLTypeData%GenTrq_prev = SrcBladedDLLTypeData%GenTrq_prev +IF (ALLOCATED(SrcBladedDLLTypeData%SCoutput)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%SCoutput,1) + i1_u = UBOUND(SrcBladedDLLTypeData%SCoutput,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%SCoutput)) THEN + ALLOCATE(DstBladedDLLTypeData%SCoutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%SCoutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%SCoutput = SrcBladedDLLTypeData%SCoutput +ENDIF + DstBladedDLLTypeData%initialized = SrcBladedDLLTypeData%initialized + DstBladedDLLTypeData%NumLogChannels = SrcBladedDLLTypeData%NumLogChannels +IF (ALLOCATED(SrcBladedDLLTypeData%LogChannels_OutParam)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%LogChannels_OutParam,1) + i1_u = UBOUND(SrcBladedDLLTypeData%LogChannels_OutParam,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%LogChannels_OutParam)) THEN + ALLOCATE(DstBladedDLLTypeData%LogChannels_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%LogChannels_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcBladedDLLTypeData%LogChannels_OutParam,1), UBOUND(SrcBladedDLLTypeData%LogChannels_OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcBladedDLLTypeData%LogChannels_OutParam(i1), DstBladedDLLTypeData%LogChannels_OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcBladedDLLTypeData%LogChannels)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%LogChannels,1) + i1_u = UBOUND(SrcBladedDLLTypeData%LogChannels,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%LogChannels)) THEN + ALLOCATE(DstBladedDLLTypeData%LogChannels(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%LogChannels.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%LogChannels = SrcBladedDLLTypeData%LogChannels +ENDIF + DstBladedDLLTypeData%ErrStat = SrcBladedDLLTypeData%ErrStat + DstBladedDLLTypeData%ErrMsg = SrcBladedDLLTypeData%ErrMsg + DstBladedDLLTypeData%CurrentTime = SrcBladedDLLTypeData%CurrentTime + DstBladedDLLTypeData%SimStatus = SrcBladedDLLTypeData%SimStatus + DstBladedDLLTypeData%ShaftBrakeStatusBinaryFlag = SrcBladedDLLTypeData%ShaftBrakeStatusBinaryFlag + DstBladedDLLTypeData%HSSBrDeployed = SrcBladedDLLTypeData%HSSBrDeployed + DstBladedDLLTypeData%TimeHSSBrFullyDeployed = SrcBladedDLLTypeData%TimeHSSBrFullyDeployed + DstBladedDLLTypeData%TimeHSSBrDeployed = SrcBladedDLLTypeData%TimeHSSBrDeployed + DstBladedDLLTypeData%OverrideYawRateWithTorque = SrcBladedDLLTypeData%OverrideYawRateWithTorque + DstBladedDLLTypeData%YawTorqueDemand = SrcBladedDLLTypeData%YawTorqueDemand +IF (ALLOCATED(SrcBladedDLLTypeData%BlPitchInput)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%BlPitchInput,1) + i1_u = UBOUND(SrcBladedDLLTypeData%BlPitchInput,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%BlPitchInput)) THEN + ALLOCATE(DstBladedDLLTypeData%BlPitchInput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%BlPitchInput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%BlPitchInput = SrcBladedDLLTypeData%BlPitchInput +ENDIF + DstBladedDLLTypeData%YawAngleFromNorth = SrcBladedDLLTypeData%YawAngleFromNorth + DstBladedDLLTypeData%HorWindV = SrcBladedDLLTypeData%HorWindV + DstBladedDLLTypeData%HSS_Spd = SrcBladedDLLTypeData%HSS_Spd + DstBladedDLLTypeData%YawErr = SrcBladedDLLTypeData%YawErr + DstBladedDLLTypeData%RotSpeed = SrcBladedDLLTypeData%RotSpeed + DstBladedDLLTypeData%YawBrTAxp = SrcBladedDLLTypeData%YawBrTAxp + DstBladedDLLTypeData%YawBrTAyp = SrcBladedDLLTypeData%YawBrTAyp + DstBladedDLLTypeData%LSSTipMys = SrcBladedDLLTypeData%LSSTipMys + DstBladedDLLTypeData%LSSTipMzs = SrcBladedDLLTypeData%LSSTipMzs + DstBladedDLLTypeData%LSSTipMya = SrcBladedDLLTypeData%LSSTipMya + DstBladedDLLTypeData%LSSTipMza = SrcBladedDLLTypeData%LSSTipMza + DstBladedDLLTypeData%LSSTipPxa = SrcBladedDLLTypeData%LSSTipPxa + DstBladedDLLTypeData%Yaw = SrcBladedDLLTypeData%Yaw + DstBladedDLLTypeData%YawRate = SrcBladedDLLTypeData%YawRate + DstBladedDLLTypeData%YawBrMyn = SrcBladedDLLTypeData%YawBrMyn + DstBladedDLLTypeData%YawBrMzn = SrcBladedDLLTypeData%YawBrMzn + DstBladedDLLTypeData%NcIMURAxs = SrcBladedDLLTypeData%NcIMURAxs + DstBladedDLLTypeData%NcIMURAys = SrcBladedDLLTypeData%NcIMURAys + DstBladedDLLTypeData%NcIMURAzs = SrcBladedDLLTypeData%NcIMURAzs + DstBladedDLLTypeData%RotPwr = SrcBladedDLLTypeData%RotPwr + DstBladedDLLTypeData%LSSTipMxa = SrcBladedDLLTypeData%LSSTipMxa + DstBladedDLLTypeData%RootMyc = SrcBladedDLLTypeData%RootMyc + DstBladedDLLTypeData%RootMxc = SrcBladedDLLTypeData%RootMxc + DstBladedDLLTypeData%DLL_DT = SrcBladedDLLTypeData%DLL_DT + DstBladedDLLTypeData%DLL_InFile = SrcBladedDLLTypeData%DLL_InFile + DstBladedDLLTypeData%RootName = SrcBladedDLLTypeData%RootName + DstBladedDLLTypeData%GenTrq_Dem = SrcBladedDLLTypeData%GenTrq_Dem + DstBladedDLLTypeData%GenSpd_Dem = SrcBladedDLLTypeData%GenSpd_Dem + DstBladedDLLTypeData%Ptch_Max = SrcBladedDLLTypeData%Ptch_Max + DstBladedDLLTypeData%Ptch_Min = SrcBladedDLLTypeData%Ptch_Min + DstBladedDLLTypeData%Ptch_SetPnt = SrcBladedDLLTypeData%Ptch_SetPnt + DstBladedDLLTypeData%PtchRate_Max = SrcBladedDLLTypeData%PtchRate_Max + DstBladedDLLTypeData%PtchRate_Min = SrcBladedDLLTypeData%PtchRate_Min + DstBladedDLLTypeData%GenPwr_Dem = SrcBladedDLLTypeData%GenPwr_Dem + DstBladedDLLTypeData%Gain_OM = SrcBladedDLLTypeData%Gain_OM + DstBladedDLLTypeData%GenSpd_MaxOM = SrcBladedDLLTypeData%GenSpd_MaxOM + DstBladedDLLTypeData%GenSpd_MinOM = SrcBladedDLLTypeData%GenSpd_MinOM + DstBladedDLLTypeData%Ptch_Cntrl = SrcBladedDLLTypeData%Ptch_Cntrl + DstBladedDLLTypeData%DLL_NumTrq = SrcBladedDLLTypeData%DLL_NumTrq +IF (ALLOCATED(SrcBladedDLLTypeData%GenSpd_TLU)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%GenSpd_TLU,1) + i1_u = UBOUND(SrcBladedDLLTypeData%GenSpd_TLU,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%GenSpd_TLU)) THEN + ALLOCATE(DstBladedDLLTypeData%GenSpd_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%GenSpd_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%GenSpd_TLU = SrcBladedDLLTypeData%GenSpd_TLU +ENDIF +IF (ALLOCATED(SrcBladedDLLTypeData%GenTrq_TLU)) THEN + i1_l = LBOUND(SrcBladedDLLTypeData%GenTrq_TLU,1) + i1_u = UBOUND(SrcBladedDLLTypeData%GenTrq_TLU,1) + IF (.NOT. ALLOCATED(DstBladedDLLTypeData%GenTrq_TLU)) THEN + ALLOCATE(DstBladedDLLTypeData%GenTrq_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstBladedDLLTypeData%GenTrq_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstBladedDLLTypeData%GenTrq_TLU = SrcBladedDLLTypeData%GenTrq_TLU +ENDIF + DstBladedDLLTypeData%Yaw_Cntrl = SrcBladedDLLTypeData%Yaw_Cntrl + END SUBROUTINE SrvD_CopyBladedDLLType + + SUBROUTINE SrvD_DestroyBladedDLLType( BladedDLLTypeData, ErrStat, ErrMsg ) + TYPE(BladedDLLType), INTENT(INOUT) :: BladedDLLTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyBladedDLLType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(BladedDLLTypeData%avrSWAP)) THEN + DEALLOCATE(BladedDLLTypeData%avrSWAP) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%SCoutput)) THEN + DEALLOCATE(BladedDLLTypeData%SCoutput) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%LogChannels_OutParam)) THEN +DO i1 = LBOUND(BladedDLLTypeData%LogChannels_OutParam,1), UBOUND(BladedDLLTypeData%LogChannels_OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( BladedDLLTypeData%LogChannels_OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(BladedDLLTypeData%LogChannels_OutParam) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%LogChannels)) THEN + DEALLOCATE(BladedDLLTypeData%LogChannels) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%BlPitchInput)) THEN + DEALLOCATE(BladedDLLTypeData%BlPitchInput) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%GenSpd_TLU)) THEN + DEALLOCATE(BladedDLLTypeData%GenSpd_TLU) +ENDIF +IF (ALLOCATED(BladedDLLTypeData%GenTrq_TLU)) THEN + DEALLOCATE(BladedDLLTypeData%GenTrq_TLU) +ENDIF + END SUBROUTINE SrvD_DestroyBladedDLLType + + SUBROUTINE SrvD_PackBladedDLLType( 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(BladedDLLType), 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 = 'SrvD_PackBladedDLLType' + ! 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 ! avrSWAP allocated yes/no + IF ( ALLOCATED(InData%avrSWAP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! avrSWAP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%avrSWAP) ! avrSWAP + END IF + Re_BufSz = Re_BufSz + 1 ! HSSBrTrqDemand + Re_BufSz = Re_BufSz + 1 ! YawRateCom + Re_BufSz = Re_BufSz + 1 ! GenTrq + Int_BufSz = Int_BufSz + 1 ! GenState + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchCom) ! BlPitchCom + Re_BufSz = Re_BufSz + SIZE(InData%PrevBlPitch) ! PrevBlPitch + Re_BufSz = Re_BufSz + SIZE(InData%BlAirfoilCom) ! BlAirfoilCom + Re_BufSz = Re_BufSz + 1 ! ElecPwr_prev + Re_BufSz = Re_BufSz + 1 ! GenTrq_prev + Int_BufSz = Int_BufSz + 1 ! SCoutput allocated yes/no + IF ( ALLOCATED(InData%SCoutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SCoutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SCoutput) ! SCoutput + END IF + Int_BufSz = Int_BufSz + 1 ! initialized + Int_BufSz = Int_BufSz + 1 ! NumLogChannels + Int_BufSz = Int_BufSz + 1 ! LogChannels_OutParam allocated yes/no + IF ( ALLOCATED(InData%LogChannels_OutParam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LogChannels_OutParam upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%LogChannels_OutParam,1), UBOUND(InData%LogChannels_OutParam,1) + Int_BufSz = Int_BufSz + 3 ! LogChannels_OutParam: size of buffers for each call to pack subtype + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%LogChannels_OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! LogChannels_OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LogChannels_OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LogChannels_OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LogChannels_OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! LogChannels allocated yes/no + IF ( ALLOCATED(InData%LogChannels) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LogChannels upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LogChannels) ! LogChannels + END IF + Int_BufSz = Int_BufSz + 1 ! ErrStat + Int_BufSz = Int_BufSz + 1*LEN(InData%ErrMsg) ! ErrMsg + Db_BufSz = Db_BufSz + 1 ! CurrentTime + Int_BufSz = Int_BufSz + 1 ! SimStatus + Int_BufSz = Int_BufSz + 1 ! ShaftBrakeStatusBinaryFlag + Int_BufSz = Int_BufSz + 1 ! HSSBrDeployed + Db_BufSz = Db_BufSz + 1 ! TimeHSSBrFullyDeployed + Db_BufSz = Db_BufSz + 1 ! TimeHSSBrDeployed + Int_BufSz = Int_BufSz + 1 ! OverrideYawRateWithTorque + Re_BufSz = Re_BufSz + 1 ! YawTorqueDemand + Int_BufSz = Int_BufSz + 1 ! BlPitchInput allocated yes/no + IF ( ALLOCATED(InData%BlPitchInput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchInput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchInput) ! BlPitchInput + END IF + Re_BufSz = Re_BufSz + 1 ! YawAngleFromNorth + Re_BufSz = Re_BufSz + 1 ! HorWindV + Re_BufSz = Re_BufSz + 1 ! HSS_Spd + Re_BufSz = Re_BufSz + 1 ! YawErr + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Re_BufSz = Re_BufSz + 1 ! YawBrTAxp + Re_BufSz = Re_BufSz + 1 ! YawBrTAyp + Re_BufSz = Re_BufSz + 1 ! LSSTipMys + Re_BufSz = Re_BufSz + 1 ! LSSTipMzs + Re_BufSz = Re_BufSz + 1 ! LSSTipMya + Re_BufSz = Re_BufSz + 1 ! LSSTipMza + Re_BufSz = Re_BufSz + 1 ! LSSTipPxa + Re_BufSz = Re_BufSz + 1 ! Yaw + Re_BufSz = Re_BufSz + 1 ! YawRate + Re_BufSz = Re_BufSz + 1 ! YawBrMyn + Re_BufSz = Re_BufSz + 1 ! YawBrMzn + Re_BufSz = Re_BufSz + 1 ! NcIMURAxs + Re_BufSz = Re_BufSz + 1 ! NcIMURAys + Re_BufSz = Re_BufSz + 1 ! NcIMURAzs + Re_BufSz = Re_BufSz + 1 ! RotPwr + Re_BufSz = Re_BufSz + 1 ! LSSTipMxa + Re_BufSz = Re_BufSz + SIZE(InData%RootMyc) ! RootMyc + Re_BufSz = Re_BufSz + SIZE(InData%RootMxc) ! RootMxc + Db_BufSz = Db_BufSz + 1 ! DLL_DT + Int_BufSz = Int_BufSz + 1*LEN(InData%DLL_InFile) ! DLL_InFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! GenTrq_Dem + Re_BufSz = Re_BufSz + 1 ! GenSpd_Dem + Re_BufSz = Re_BufSz + 1 ! Ptch_Max + Re_BufSz = Re_BufSz + 1 ! Ptch_Min + Re_BufSz = Re_BufSz + 1 ! Ptch_SetPnt + Re_BufSz = Re_BufSz + 1 ! PtchRate_Max + Re_BufSz = Re_BufSz + 1 ! PtchRate_Min + Re_BufSz = Re_BufSz + 1 ! GenPwr_Dem + Re_BufSz = Re_BufSz + 1 ! Gain_OM + Re_BufSz = Re_BufSz + 1 ! GenSpd_MaxOM + Re_BufSz = Re_BufSz + 1 ! GenSpd_MinOM + Int_BufSz = Int_BufSz + 1 ! Ptch_Cntrl + Int_BufSz = Int_BufSz + 1 ! DLL_NumTrq + Int_BufSz = Int_BufSz + 1 ! GenSpd_TLU allocated yes/no + IF ( ALLOCATED(InData%GenSpd_TLU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! GenSpd_TLU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GenSpd_TLU) ! GenSpd_TLU + END IF + Int_BufSz = Int_BufSz + 1 ! GenTrq_TLU allocated yes/no + IF ( ALLOCATED(InData%GenTrq_TLU) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! GenTrq_TLU upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%GenTrq_TLU) ! GenTrq_TLU + END IF + Int_BufSz = Int_BufSz + 1 ! Yaw_Cntrl + 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%avrSWAP) ) 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%avrSWAP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%avrSWAP,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%avrSWAP,1), UBOUND(InData%avrSWAP,1) + ReKiBuf(Re_Xferred) = InData%avrSWAP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%HSSBrTrqDemand + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRateCom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenTrq + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%GenState + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%BlPitchCom,1), UBOUND(InData%BlPitchCom,1) + ReKiBuf(Re_Xferred) = InData%BlPitchCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%PrevBlPitch,1), UBOUND(InData%PrevBlPitch,1) + ReKiBuf(Re_Xferred) = InData%PrevBlPitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%BlAirfoilCom,1), UBOUND(InData%BlAirfoilCom,1) + ReKiBuf(Re_Xferred) = InData%BlAirfoilCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%ElecPwr_prev + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenTrq_prev + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SCoutput) ) 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%SCoutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SCoutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SCoutput,1), UBOUND(InData%SCoutput,1) + ReKiBuf(Re_Xferred) = InData%SCoutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%initialized, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumLogChannels + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LogChannels_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%LogChannels_OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LogChannels_OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LogChannels_OutParam,1), UBOUND(InData%LogChannels_OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%LogChannels_OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! LogChannels_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%LogChannels) ) 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%LogChannels,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LogChannels,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LogChannels,1), UBOUND(InData%LogChannels,1) + ReKiBuf(Re_Xferred) = InData%LogChannels(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%ErrStat + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%ErrMsg) + IntKiBuf(Int_Xferred) = ICHAR(InData%ErrMsg(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DbKiBuf(Db_Xferred) = InData%CurrentTime + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SimStatus + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ShaftBrakeStatusBinaryFlag + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%HSSBrDeployed, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimeHSSBrFullyDeployed + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimeHSSBrDeployed + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OverrideYawRateWithTorque, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawTorqueDemand + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlPitchInput) ) 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%BlPitchInput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchInput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchInput,1), UBOUND(InData%BlPitchInput,1) + ReKiBuf(Re_Xferred) = InData%BlPitchInput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%YawAngleFromNorth + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HorWindV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSS_Spd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawErr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrTAxp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrTAyp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMya + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMza + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipPxa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Yaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRate + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAxs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotPwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMxa + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RootMyc,1), UBOUND(InData%RootMyc,1) + ReKiBuf(Re_Xferred) = InData%RootMyc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%RootMxc,1), UBOUND(InData%RootMxc,1) + ReKiBuf(Re_Xferred) = InData%RootMxc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DbKiBuf(Db_Xferred) = InData%DLL_DT + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(InData%DLL_InFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%DLL_InFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%GenTrq_Dem + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_Dem + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_Max + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_Min + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ptch_SetPnt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtchRate_Max + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PtchRate_Min + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenPwr_Dem + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gain_OM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_MaxOM + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenSpd_MinOM + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Ptch_Cntrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DLL_NumTrq + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%GenSpd_TLU) ) 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%GenSpd_TLU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GenSpd_TLU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%GenSpd_TLU,1), UBOUND(InData%GenSpd_TLU,1) + ReKiBuf(Re_Xferred) = InData%GenSpd_TLU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%GenTrq_TLU) ) 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%GenTrq_TLU,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%GenTrq_TLU,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%GenTrq_TLU,1), UBOUND(InData%GenTrq_TLU,1) + ReKiBuf(Re_Xferred) = InData%GenTrq_TLU(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Yaw_Cntrl + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SrvD_PackBladedDLLType + + SUBROUTINE SrvD_UnPackBladedDLLType( 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(BladedDLLType), 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 = 'SrvD_UnPackBladedDLLType' + ! 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 ! avrSWAP 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%avrSWAP)) DEALLOCATE(OutData%avrSWAP) + ALLOCATE(OutData%avrSWAP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%avrSWAP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%avrSWAP,1), UBOUND(OutData%avrSWAP,1) + OutData%avrSWAP(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%HSSBrTrqDemand = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRateCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenState = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%BlPitchCom,1) + i1_u = UBOUND(OutData%BlPitchCom,1) + DO i1 = LBOUND(OutData%BlPitchCom,1), UBOUND(OutData%BlPitchCom,1) + OutData%BlPitchCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%PrevBlPitch,1) + i1_u = UBOUND(OutData%PrevBlPitch,1) + DO i1 = LBOUND(OutData%PrevBlPitch,1), UBOUND(OutData%PrevBlPitch,1) + OutData%PrevBlPitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%BlAirfoilCom,1) + i1_u = UBOUND(OutData%BlAirfoilCom,1) + DO i1 = LBOUND(OutData%BlAirfoilCom,1), UBOUND(OutData%BlAirfoilCom,1) + OutData%BlAirfoilCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%ElecPwr_prev = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTrq_prev = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SCoutput 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%SCoutput)) DEALLOCATE(OutData%SCoutput) + ALLOCATE(OutData%SCoutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SCoutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SCoutput,1), UBOUND(OutData%SCoutput,1) + OutData%SCoutput(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%initialized = TRANSFER(IntKiBuf(Int_Xferred), OutData%initialized) + Int_Xferred = Int_Xferred + 1 + OutData%NumLogChannels = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LogChannels_OutParam 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%LogChannels_OutParam)) DEALLOCATE(OutData%LogChannels_OutParam) + ALLOCATE(OutData%LogChannels_OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LogChannels_OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LogChannels_OutParam,1), UBOUND(OutData%LogChannels_OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%LogChannels_OutParam(i1), ErrStat2, ErrMsg2 ) ! LogChannels_OutParam + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LogChannels 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%LogChannels)) DEALLOCATE(OutData%LogChannels) + ALLOCATE(OutData%LogChannels(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LogChannels.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LogChannels,1), UBOUND(OutData%LogChannels,1) + OutData%LogChannels(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%ErrStat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%ErrMsg) + OutData%ErrMsg(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%CurrentTime = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%SimStatus = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ShaftBrakeStatusBinaryFlag = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HSSBrDeployed = TRANSFER(IntKiBuf(Int_Xferred), OutData%HSSBrDeployed) + Int_Xferred = Int_Xferred + 1 + OutData%TimeHSSBrFullyDeployed = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%TimeHSSBrDeployed = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + OutData%OverrideYawRateWithTorque = TRANSFER(IntKiBuf(Int_Xferred), OutData%OverrideYawRateWithTorque) + Int_Xferred = Int_Xferred + 1 + OutData%YawTorqueDemand = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchInput 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%BlPitchInput)) DEALLOCATE(OutData%BlPitchInput) + ALLOCATE(OutData%BlPitchInput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchInput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchInput,1), UBOUND(OutData%BlPitchInput,1) + OutData%BlPitchInput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%YawAngleFromNorth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HorWindV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSS_Spd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawErr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrTAxp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrTAyp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMya = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMza = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipPxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Yaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRate = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAxs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RootMyc,1) + i1_u = UBOUND(OutData%RootMyc,1) + DO i1 = LBOUND(OutData%RootMyc,1), UBOUND(OutData%RootMyc,1) + OutData%RootMyc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%RootMxc,1) + i1_u = UBOUND(OutData%RootMxc,1) + DO i1 = LBOUND(OutData%RootMxc,1), UBOUND(OutData%RootMxc,1) + OutData%RootMxc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%DLL_DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(OutData%DLL_InFile) + OutData%DLL_InFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%GenTrq_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Max = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Min = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_SetPnt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtchRate_Max = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PtchRate_Min = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenPwr_Dem = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Gain_OM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_MaxOM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenSpd_MinOM = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ptch_Cntrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DLL_NumTrq = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GenSpd_TLU 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%GenSpd_TLU)) DEALLOCATE(OutData%GenSpd_TLU) + ALLOCATE(OutData%GenSpd_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GenSpd_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%GenSpd_TLU,1), UBOUND(OutData%GenSpd_TLU,1) + OutData%GenSpd_TLU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! GenTrq_TLU 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%GenTrq_TLU)) DEALLOCATE(OutData%GenTrq_TLU) + ALLOCATE(OutData%GenTrq_TLU(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%GenTrq_TLU.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%GenTrq_TLU,1), UBOUND(OutData%GenTrq_TLU,1) + OutData%GenTrq_TLU(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Yaw_Cntrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SrvD_UnPackBladedDLLType + + SUBROUTINE SrvD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(SrvD_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 = 'SrvD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + CALL TMD_CopyContState( SrcContStateData%NTMD, DstContStateData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyContState( SrcContStateData%TTMD, DstContStateData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyContState + + SUBROUTINE SrvD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(SrvD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL TMD_DestroyContState( ContStateData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyContState( ContStateData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyContState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + ReKiBuf(Re_Xferred) = InData%DummyContState + Re_Xferred = Re_Xferred + 1 + CALL TMD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackContState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + 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 TMD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackContState + + SUBROUTINE SrvD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(SrvD_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 = 'SrvD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%CtrlOffset = SrcDiscStateData%CtrlOffset + CALL TMD_CopyDiscState( SrcDiscStateData%NTMD, DstDiscStateData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyDiscState( SrcDiscStateData%TTMD, DstDiscStateData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyDiscState + + SUBROUTINE SrvD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(SrvD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL TMD_DestroyDiscState( DiscStateData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyDiscState( DiscStateData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyDiscState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 ! CtrlOffset + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + ReKiBuf(Re_Xferred) = InData%CtrlOffset + Re_Xferred = Re_Xferred + 1 + CALL TMD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackDiscState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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%CtrlOffset = 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 TMD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackDiscState + + SUBROUTINE SrvD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(SrvD_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 = 'SrvD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + CALL TMD_CopyConstrState( SrcConstrStateData%NTMD, DstConstrStateData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyConstrState( SrcConstrStateData%TTMD, DstConstrStateData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyConstrState + + SUBROUTINE SrvD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(SrvD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL TMD_DestroyConstrState( ConstrStateData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyConstrState( ConstrStateData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyConstrState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + ReKiBuf(Re_Xferred) = InData%DummyConstrState + Re_Xferred = Re_Xferred + 1 + CALL TMD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackConstrState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackConstrState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + 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 TMD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackConstrState( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackConstrState + + SUBROUTINE SrvD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(SrvD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%BegPitMan)) THEN + i1_l = LBOUND(SrcOtherStateData%BegPitMan,1) + i1_u = UBOUND(SrcOtherStateData%BegPitMan,1) + IF (.NOT. ALLOCATED(DstOtherStateData%BegPitMan)) THEN + ALLOCATE(DstOtherStateData%BegPitMan(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%BegPitMan.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%BegPitMan = SrcOtherStateData%BegPitMan +ENDIF +IF (ALLOCATED(SrcOtherStateData%BlPitchI)) THEN + i1_l = LBOUND(SrcOtherStateData%BlPitchI,1) + i1_u = UBOUND(SrcOtherStateData%BlPitchI,1) + IF (.NOT. ALLOCATED(DstOtherStateData%BlPitchI)) THEN + ALLOCATE(DstOtherStateData%BlPitchI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%BlPitchI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%BlPitchI = SrcOtherStateData%BlPitchI +ENDIF +IF (ALLOCATED(SrcOtherStateData%TPitManE)) THEN + i1_l = LBOUND(SrcOtherStateData%TPitManE,1) + i1_u = UBOUND(SrcOtherStateData%TPitManE,1) + IF (.NOT. ALLOCATED(DstOtherStateData%TPitManE)) THEN + ALLOCATE(DstOtherStateData%TPitManE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%TPitManE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%TPitManE = SrcOtherStateData%TPitManE +ENDIF + DstOtherStateData%BegYawMan = SrcOtherStateData%BegYawMan + DstOtherStateData%NacYawI = SrcOtherStateData%NacYawI + DstOtherStateData%TYawManE = SrcOtherStateData%TYawManE + DstOtherStateData%YawPosComInt = SrcOtherStateData%YawPosComInt +IF (ALLOCATED(SrcOtherStateData%BegTpBr)) THEN + i1_l = LBOUND(SrcOtherStateData%BegTpBr,1) + i1_u = UBOUND(SrcOtherStateData%BegTpBr,1) + IF (.NOT. ALLOCATED(DstOtherStateData%BegTpBr)) THEN + ALLOCATE(DstOtherStateData%BegTpBr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%BegTpBr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%BegTpBr = SrcOtherStateData%BegTpBr +ENDIF +IF (ALLOCATED(SrcOtherStateData%TTpBrDp)) THEN + i1_l = LBOUND(SrcOtherStateData%TTpBrDp,1) + i1_u = UBOUND(SrcOtherStateData%TTpBrDp,1) + IF (.NOT. ALLOCATED(DstOtherStateData%TTpBrDp)) THEN + ALLOCATE(DstOtherStateData%TTpBrDp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%TTpBrDp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%TTpBrDp = SrcOtherStateData%TTpBrDp +ENDIF +IF (ALLOCATED(SrcOtherStateData%TTpBrFl)) THEN + i1_l = LBOUND(SrcOtherStateData%TTpBrFl,1) + i1_u = UBOUND(SrcOtherStateData%TTpBrFl,1) + IF (.NOT. ALLOCATED(DstOtherStateData%TTpBrFl)) THEN + ALLOCATE(DstOtherStateData%TTpBrFl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%TTpBrFl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOtherStateData%TTpBrFl = SrcOtherStateData%TTpBrFl +ENDIF + DstOtherStateData%Off4Good = SrcOtherStateData%Off4Good + DstOtherStateData%GenOnLine = SrcOtherStateData%GenOnLine + CALL TMD_CopyOtherState( SrcOtherStateData%NTMD, DstOtherStateData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyOtherState( SrcOtherStateData%TTMD, DstOtherStateData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyOtherState + + SUBROUTINE SrvD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(SrvD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%BegPitMan)) THEN + DEALLOCATE(OtherStateData%BegPitMan) +ENDIF +IF (ALLOCATED(OtherStateData%BlPitchI)) THEN + DEALLOCATE(OtherStateData%BlPitchI) +ENDIF +IF (ALLOCATED(OtherStateData%TPitManE)) THEN + DEALLOCATE(OtherStateData%TPitManE) +ENDIF +IF (ALLOCATED(OtherStateData%BegTpBr)) THEN + DEALLOCATE(OtherStateData%BegTpBr) +ENDIF +IF (ALLOCATED(OtherStateData%TTpBrDp)) THEN + DEALLOCATE(OtherStateData%TTpBrDp) +ENDIF +IF (ALLOCATED(OtherStateData%TTpBrFl)) THEN + DEALLOCATE(OtherStateData%TTpBrFl) +ENDIF + CALL TMD_DestroyOtherState( OtherStateData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyOtherState( OtherStateData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyOtherState + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + Int_BufSz = Int_BufSz + 1 ! BegPitMan allocated yes/no + IF ( ALLOCATED(InData%BegPitMan) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BegPitMan upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BegPitMan) ! BegPitMan + END IF + Int_BufSz = Int_BufSz + 1 ! BlPitchI allocated yes/no + IF ( ALLOCATED(InData%BlPitchI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchI) ! BlPitchI + END IF + Int_BufSz = Int_BufSz + 1 ! TPitManE allocated yes/no + IF ( ALLOCATED(InData%TPitManE) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TPitManE upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%TPitManE) ! TPitManE + END IF + Int_BufSz = Int_BufSz + 1 ! BegYawMan + Re_BufSz = Re_BufSz + 1 ! NacYawI + Db_BufSz = Db_BufSz + 1 ! TYawManE + Re_BufSz = Re_BufSz + 1 ! YawPosComInt + Int_BufSz = Int_BufSz + 1 ! BegTpBr allocated yes/no + IF ( ALLOCATED(InData%BegTpBr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BegTpBr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BegTpBr) ! BegTpBr + END IF + Int_BufSz = Int_BufSz + 1 ! TTpBrDp allocated yes/no + IF ( ALLOCATED(InData%TTpBrDp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TTpBrDp upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%TTpBrDp) ! TTpBrDp + END IF + Int_BufSz = Int_BufSz + 1 ! TTpBrFl allocated yes/no + IF ( ALLOCATED(InData%TTpBrFl) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TTpBrFl upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%TTpBrFl) ! TTpBrFl + END IF + Int_BufSz = Int_BufSz + 1 ! Off4Good + Int_BufSz = Int_BufSz + 1 ! GenOnLine + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + IF ( .NOT. ALLOCATED(InData%BegPitMan) ) 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%BegPitMan,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BegPitMan,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BegPitMan,1), UBOUND(InData%BegPitMan,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%BegPitMan(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlPitchI) ) 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%BlPitchI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchI,1), UBOUND(InData%BlPitchI,1) + ReKiBuf(Re_Xferred) = InData%BlPitchI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TPitManE) ) 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%TPitManE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TPitManE,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TPitManE,1), UBOUND(InData%TPitManE,1) + DbKiBuf(Db_Xferred) = InData%TPitManE(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%BegYawMan, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYawI + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TYawManE + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawPosComInt + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BegTpBr) ) 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%BegTpBr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BegTpBr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BegTpBr,1), UBOUND(InData%BegTpBr,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%BegTpBr(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TTpBrDp) ) 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%TTpBrDp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TTpBrDp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TTpBrDp,1), UBOUND(InData%TTpBrDp,1) + DbKiBuf(Db_Xferred) = InData%TTpBrDp(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TTpBrFl) ) 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%TTpBrFl,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TTpBrFl,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TTpBrFl,1), UBOUND(InData%TTpBrFl,1) + DbKiBuf(Db_Xferred) = InData%TTpBrFl(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%Off4Good, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenOnLine, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL TMD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackOtherState + + SUBROUTINE SrvD_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(SrvD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BegPitMan 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%BegPitMan)) DEALLOCATE(OutData%BegPitMan) + ALLOCATE(OutData%BegPitMan(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BegPitMan.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BegPitMan,1), UBOUND(OutData%BegPitMan,1) + OutData%BegPitMan(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%BegPitMan(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchI 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%BlPitchI)) DEALLOCATE(OutData%BlPitchI) + ALLOCATE(OutData%BlPitchI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchI,1), UBOUND(OutData%BlPitchI,1) + OutData%BlPitchI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TPitManE 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%TPitManE)) DEALLOCATE(OutData%TPitManE) + ALLOCATE(OutData%TPitManE(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TPitManE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TPitManE,1), UBOUND(OutData%TPitManE,1) + OutData%TPitManE(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%BegYawMan = TRANSFER(IntKiBuf(Int_Xferred), OutData%BegYawMan) + Int_Xferred = Int_Xferred + 1 + OutData%NacYawI = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TYawManE = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%YawPosComInt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BegTpBr 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%BegTpBr)) DEALLOCATE(OutData%BegTpBr) + ALLOCATE(OutData%BegTpBr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BegTpBr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BegTpBr,1), UBOUND(OutData%BegTpBr,1) + OutData%BegTpBr(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%BegTpBr(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TTpBrDp 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%TTpBrDp)) DEALLOCATE(OutData%TTpBrDp) + ALLOCATE(OutData%TTpBrDp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TTpBrDp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TTpBrDp,1), UBOUND(OutData%TTpBrDp,1) + OutData%TTpBrDp(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TTpBrFl 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%TTpBrFl)) DEALLOCATE(OutData%TTpBrFl) + ALLOCATE(OutData%TTpBrFl(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TTpBrFl.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TTpBrFl,1), UBOUND(OutData%TTpBrFl,1) + OutData%TTpBrFl(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%Off4Good = TRANSFER(IntKiBuf(Int_Xferred), OutData%Off4Good) + Int_Xferred = Int_Xferred + 1 + OutData%GenOnLine = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenOnLine) + 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 TMD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackOtherState + + SUBROUTINE SrvD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(SrvD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%LastTimeCalled = SrcMiscData%LastTimeCalled + CALL SrvD_Copybladeddlltype( SrcMiscData%dll_data, DstMiscData%dll_data, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%FirstWarn = SrcMiscData%FirstWarn + DstMiscData%LastTimeFiltered = SrcMiscData%LastTimeFiltered +IF (ALLOCATED(SrcMiscData%xd_BlPitchFilter)) THEN + i1_l = LBOUND(SrcMiscData%xd_BlPitchFilter,1) + i1_u = UBOUND(SrcMiscData%xd_BlPitchFilter,1) + IF (.NOT. ALLOCATED(DstMiscData%xd_BlPitchFilter)) THEN + ALLOCATE(DstMiscData%xd_BlPitchFilter(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%xd_BlPitchFilter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%xd_BlPitchFilter = SrcMiscData%xd_BlPitchFilter +ENDIF + CALL TMD_CopyMisc( SrcMiscData%NTMD, DstMiscData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyMisc( SrcMiscData%TTMD, DstMiscData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyMisc + + SUBROUTINE SrvD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(SrvD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL SrvD_Destroybladeddlltype( MiscData%dll_data, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%xd_BlPitchFilter)) THEN + DEALLOCATE(MiscData%xd_BlPitchFilter) +ENDIF + CALL TMD_DestroyMisc( MiscData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyMisc( MiscData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyMisc + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + Db_BufSz = Db_BufSz + 1 ! LastTimeCalled + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! dll_data: size of buffers for each call to pack subtype + CALL SrvD_Packbladeddlltype( Re_Buf, Db_Buf, Int_Buf, InData%dll_data, ErrStat2, ErrMsg2, .TRUE. ) ! dll_data + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! dll_data + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! dll_data + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! dll_data + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! FirstWarn + Db_BufSz = Db_BufSz + 1 ! LastTimeFiltered + Int_BufSz = Int_BufSz + 1 ! xd_BlPitchFilter allocated yes/no + IF ( ALLOCATED(InData%xd_BlPitchFilter) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xd_BlPitchFilter upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%xd_BlPitchFilter) ! xd_BlPitchFilter + END IF + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + DbKiBuf(Db_Xferred) = InData%LastTimeCalled + Db_Xferred = Db_Xferred + 1 + CALL SrvD_Packbladeddlltype( Re_Buf, Db_Buf, Int_Buf, InData%dll_data, ErrStat2, ErrMsg2, OnlySize ) ! dll_data + 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) = TRANSFER(InData%FirstWarn, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%LastTimeFiltered + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%xd_BlPitchFilter) ) 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%xd_BlPitchFilter,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xd_BlPitchFilter,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xd_BlPitchFilter,1), UBOUND(InData%xd_BlPitchFilter,1) + ReKiBuf(Re_Xferred) = InData%xd_BlPitchFilter(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + CALL TMD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackMisc + + SUBROUTINE SrvD_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(SrvD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_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%LastTimeCalled = DbKiBuf(Db_Xferred) + Db_Xferred = Db_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 SrvD_Unpackbladeddlltype( Re_Buf, Db_Buf, Int_Buf, OutData%dll_data, ErrStat2, ErrMsg2 ) ! dll_data + 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%FirstWarn = TRANSFER(IntKiBuf(Int_Xferred), OutData%FirstWarn) + Int_Xferred = Int_Xferred + 1 + OutData%LastTimeFiltered = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xd_BlPitchFilter 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%xd_BlPitchFilter)) DEALLOCATE(OutData%xd_BlPitchFilter) + ALLOCATE(OutData%xd_BlPitchFilter(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xd_BlPitchFilter.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xd_BlPitchFilter,1), UBOUND(OutData%xd_BlPitchFilter,1) + OutData%xd_BlPitchFilter(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 TMD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackMisc + + SUBROUTINE SrvD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SrvD_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 = 'SrvD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%HSSBrDT = SrcParamData%HSSBrDT + DstParamData%HSSBrTqF = SrcParamData%HSSBrTqF + DstParamData%SIG_POSl = SrcParamData%SIG_POSl + DstParamData%SIG_POTq = SrcParamData%SIG_POTq + DstParamData%SIG_SlPc = SrcParamData%SIG_SlPc + DstParamData%SIG_Slop = SrcParamData%SIG_Slop + DstParamData%SIG_SySp = SrcParamData%SIG_SySp + DstParamData%TEC_A0 = SrcParamData%TEC_A0 + DstParamData%TEC_C0 = SrcParamData%TEC_C0 + DstParamData%TEC_C1 = SrcParamData%TEC_C1 + DstParamData%TEC_C2 = SrcParamData%TEC_C2 + DstParamData%TEC_K2 = SrcParamData%TEC_K2 + DstParamData%TEC_MR = SrcParamData%TEC_MR + DstParamData%TEC_Re1 = SrcParamData%TEC_Re1 + DstParamData%TEC_RLR = SrcParamData%TEC_RLR + DstParamData%TEC_RRes = SrcParamData%TEC_RRes + DstParamData%TEC_SRes = SrcParamData%TEC_SRes + DstParamData%TEC_SySp = SrcParamData%TEC_SySp + DstParamData%TEC_V1a = SrcParamData%TEC_V1a + DstParamData%TEC_VLL = SrcParamData%TEC_VLL + DstParamData%TEC_Xe1 = SrcParamData%TEC_Xe1 + DstParamData%GenEff = SrcParamData%GenEff +IF (ALLOCATED(SrcParamData%BlPitchInit)) THEN + i1_l = LBOUND(SrcParamData%BlPitchInit,1) + i1_u = UBOUND(SrcParamData%BlPitchInit,1) + IF (.NOT. ALLOCATED(DstParamData%BlPitchInit)) THEN + ALLOCATE(DstParamData%BlPitchInit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BlPitchInit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BlPitchInit = SrcParamData%BlPitchInit +ENDIF +IF (ALLOCATED(SrcParamData%BlPitchF)) THEN + i1_l = LBOUND(SrcParamData%BlPitchF,1) + i1_u = UBOUND(SrcParamData%BlPitchF,1) + IF (.NOT. ALLOCATED(DstParamData%BlPitchF)) THEN + ALLOCATE(DstParamData%BlPitchF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BlPitchF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%BlPitchF = SrcParamData%BlPitchF +ENDIF +IF (ALLOCATED(SrcParamData%PitManRat)) THEN + i1_l = LBOUND(SrcParamData%PitManRat,1) + i1_u = UBOUND(SrcParamData%PitManRat,1) + IF (.NOT. ALLOCATED(DstParamData%PitManRat)) THEN + ALLOCATE(DstParamData%PitManRat(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PitManRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PitManRat = SrcParamData%PitManRat +ENDIF + DstParamData%YawManRat = SrcParamData%YawManRat + DstParamData%NacYawF = SrcParamData%NacYawF + DstParamData%SpdGenOn = SrcParamData%SpdGenOn + DstParamData%THSSBrDp = SrcParamData%THSSBrDp + DstParamData%THSSBrFl = SrcParamData%THSSBrFl + DstParamData%TimGenOf = SrcParamData%TimGenOf + DstParamData%TimGenOn = SrcParamData%TimGenOn + DstParamData%TPCOn = SrcParamData%TPCOn +IF (ALLOCATED(SrcParamData%TPitManS)) THEN + i1_l = LBOUND(SrcParamData%TPitManS,1) + i1_u = UBOUND(SrcParamData%TPitManS,1) + IF (.NOT. ALLOCATED(DstParamData%TPitManS)) THEN + ALLOCATE(DstParamData%TPitManS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TPitManS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TPitManS = SrcParamData%TPitManS +ENDIF + DstParamData%TYawManS = SrcParamData%TYawManS + DstParamData%TYCOn = SrcParamData%TYCOn + DstParamData%VS_RtGnSp = SrcParamData%VS_RtGnSp + DstParamData%VS_RtTq = SrcParamData%VS_RtTq + DstParamData%VS_Slope = SrcParamData%VS_Slope + DstParamData%VS_SlPc = SrcParamData%VS_SlPc + DstParamData%VS_SySp = SrcParamData%VS_SySp + DstParamData%VS_TrGnSp = SrcParamData%VS_TrGnSp + DstParamData%YawPosCom = SrcParamData%YawPosCom + DstParamData%YawRateCom = SrcParamData%YawRateCom + DstParamData%GenModel = SrcParamData%GenModel + DstParamData%HSSBrMode = SrcParamData%HSSBrMode + DstParamData%PCMode = SrcParamData%PCMode + DstParamData%VSContrl = SrcParamData%VSContrl + DstParamData%YCMode = SrcParamData%YCMode + DstParamData%GenTiStp = SrcParamData%GenTiStp + DstParamData%GenTiStr = SrcParamData%GenTiStr + DstParamData%VS_Rgn2K = SrcParamData%VS_Rgn2K + DstParamData%YawNeut = SrcParamData%YawNeut + DstParamData%YawSpr = SrcParamData%YawSpr + DstParamData%YawDamp = SrcParamData%YawDamp + DstParamData%TpBrDT = SrcParamData%TpBrDT +IF (ALLOCATED(SrcParamData%TBDepISp)) THEN + i1_l = LBOUND(SrcParamData%TBDepISp,1) + i1_u = UBOUND(SrcParamData%TBDepISp,1) + IF (.NOT. ALLOCATED(DstParamData%TBDepISp)) THEN + ALLOCATE(DstParamData%TBDepISp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TBDepISp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TBDepISp = SrcParamData%TBDepISp +ENDIF + DstParamData%TBDrConN = SrcParamData%TBDrConN + DstParamData%TBDrConD = SrcParamData%TBDrConD + DstParamData%NumBl = SrcParamData%NumBl + DstParamData%CompNTMD = SrcParamData%CompNTMD + DstParamData%CompTTMD = SrcParamData%CompTTMD + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%NumOuts_DLL = SrcParamData%NumOuts_DLL + DstParamData%RootName = SrcParamData%RootName +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%Delim = SrcParamData%Delim + DstParamData%UseBladedInterface = SrcParamData%UseBladedInterface + DstParamData%UseLegacyInterface = SrcParamData%UseLegacyInterface + DstParamData%DLL_Trgt = SrcParamData%DLL_Trgt + DstParamData%DLL_Ramp = SrcParamData%DLL_Ramp + DstParamData%BlAlpha = SrcParamData%BlAlpha + DstParamData%DLL_n = SrcParamData%DLL_n + DstParamData%avcOUTNAME_LEN = SrcParamData%avcOUTNAME_LEN + DstParamData%NacYaw_North = SrcParamData%NacYaw_North + DstParamData%AvgWindSpeed = SrcParamData%AvgWindSpeed + DstParamData%AirDens = SrcParamData%AirDens + DstParamData%TrimCase = SrcParamData%TrimCase + DstParamData%TrimGain = SrcParamData%TrimGain + DstParamData%RotSpeedRef = SrcParamData%RotSpeedRef + CALL TMD_CopyParam( SrcParamData%NTMD, DstParamData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyParam( SrcParamData%TTMD, DstParamData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SrvD_CopyParam + + SUBROUTINE SrvD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SrvD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%BlPitchInit)) THEN + DEALLOCATE(ParamData%BlPitchInit) +ENDIF +IF (ALLOCATED(ParamData%BlPitchF)) THEN + DEALLOCATE(ParamData%BlPitchF) +ENDIF +IF (ALLOCATED(ParamData%PitManRat)) THEN + DEALLOCATE(ParamData%PitManRat) +ENDIF +IF (ALLOCATED(ParamData%TPitManS)) THEN + DEALLOCATE(ParamData%TPitManS) +ENDIF +IF (ALLOCATED(ParamData%TBDepISp)) THEN + DEALLOCATE(ParamData%TBDepISp) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + CALL FreeDynamicLib( ParamData%DLL_Trgt, ErrStat, ErrMsg ) + CALL TMD_DestroyParam( ParamData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyParam( ParamData%TTMD, ErrStat, ErrMsg ) + END SUBROUTINE SrvD_DestroyParam + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 + Db_BufSz = Db_BufSz + 1 ! DT + Db_BufSz = Db_BufSz + 1 ! HSSBrDT + Re_BufSz = Re_BufSz + 1 ! HSSBrTqF + Re_BufSz = Re_BufSz + 1 ! SIG_POSl + Re_BufSz = Re_BufSz + 1 ! SIG_POTq + Re_BufSz = Re_BufSz + 1 ! SIG_SlPc + Re_BufSz = Re_BufSz + 1 ! SIG_Slop + Re_BufSz = Re_BufSz + 1 ! SIG_SySp + Re_BufSz = Re_BufSz + 1 ! TEC_A0 + Re_BufSz = Re_BufSz + 1 ! TEC_C0 + Re_BufSz = Re_BufSz + 1 ! TEC_C1 + Re_BufSz = Re_BufSz + 1 ! TEC_C2 + Re_BufSz = Re_BufSz + 1 ! TEC_K2 + Re_BufSz = Re_BufSz + 1 ! TEC_MR + Re_BufSz = Re_BufSz + 1 ! TEC_Re1 + Re_BufSz = Re_BufSz + 1 ! TEC_RLR + Re_BufSz = Re_BufSz + 1 ! TEC_RRes + Re_BufSz = Re_BufSz + 1 ! TEC_SRes + Re_BufSz = Re_BufSz + 1 ! TEC_SySp + Re_BufSz = Re_BufSz + 1 ! TEC_V1a + Re_BufSz = Re_BufSz + 1 ! TEC_VLL + Re_BufSz = Re_BufSz + 1 ! TEC_Xe1 + Re_BufSz = Re_BufSz + 1 ! GenEff + Int_BufSz = Int_BufSz + 1 ! BlPitchInit allocated yes/no + IF ( ALLOCATED(InData%BlPitchInit) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchInit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchInit) ! BlPitchInit + END IF + Int_BufSz = Int_BufSz + 1 ! BlPitchF allocated yes/no + IF ( ALLOCATED(InData%BlPitchF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchF) ! BlPitchF + END IF + Int_BufSz = Int_BufSz + 1 ! PitManRat allocated yes/no + IF ( ALLOCATED(InData%PitManRat) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PitManRat upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PitManRat) ! PitManRat + END IF + Re_BufSz = Re_BufSz + 1 ! YawManRat + Re_BufSz = Re_BufSz + 1 ! NacYawF + Re_BufSz = Re_BufSz + 1 ! SpdGenOn + Db_BufSz = Db_BufSz + 1 ! THSSBrDp + Db_BufSz = Db_BufSz + 1 ! THSSBrFl + Db_BufSz = Db_BufSz + 1 ! TimGenOf + Db_BufSz = Db_BufSz + 1 ! TimGenOn + Db_BufSz = Db_BufSz + 1 ! TPCOn + Int_BufSz = Int_BufSz + 1 ! TPitManS allocated yes/no + IF ( ALLOCATED(InData%TPitManS) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TPitManS upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%TPitManS) ! TPitManS + END IF + Db_BufSz = Db_BufSz + 1 ! TYawManS + Db_BufSz = Db_BufSz + 1 ! TYCOn + Re_BufSz = Re_BufSz + 1 ! VS_RtGnSp + Re_BufSz = Re_BufSz + 1 ! VS_RtTq + Re_BufSz = Re_BufSz + 1 ! VS_Slope + Re_BufSz = Re_BufSz + 1 ! VS_SlPc + Re_BufSz = Re_BufSz + 1 ! VS_SySp + Re_BufSz = Re_BufSz + 1 ! VS_TrGnSp + Re_BufSz = Re_BufSz + 1 ! YawPosCom + Re_BufSz = Re_BufSz + 1 ! YawRateCom + Int_BufSz = Int_BufSz + 1 ! GenModel + Int_BufSz = Int_BufSz + 1 ! HSSBrMode + Int_BufSz = Int_BufSz + 1 ! PCMode + Int_BufSz = Int_BufSz + 1 ! VSContrl + Int_BufSz = Int_BufSz + 1 ! YCMode + Int_BufSz = Int_BufSz + 1 ! GenTiStp + Int_BufSz = Int_BufSz + 1 ! GenTiStr + Re_BufSz = Re_BufSz + 1 ! VS_Rgn2K + Re_BufSz = Re_BufSz + 1 ! YawNeut + Re_BufSz = Re_BufSz + 1 ! YawSpr + Re_BufSz = Re_BufSz + 1 ! YawDamp + Db_BufSz = Db_BufSz + 1 ! TpBrDT + Int_BufSz = Int_BufSz + 1 ! TBDepISp allocated yes/no + IF ( ALLOCATED(InData%TBDepISp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TBDepISp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TBDepISp) ! TBDepISp + END IF + Re_BufSz = Re_BufSz + 1 ! TBDrConN + Re_BufSz = Re_BufSz + 1 ! TBDrConD + Int_BufSz = Int_BufSz + 1 ! NumBl + Int_BufSz = Int_BufSz + 1 ! CompNTMD + Int_BufSz = Int_BufSz + 1 ! CompTTMD + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! NumOuts_DLL + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1 ! UseBladedInterface + Int_BufSz = Int_BufSz + 1 ! UseLegacyInterface + Int_BufSz = Int_BufSz + 3 ! DLL_Trgt: size of buffers for each call to pack subtype + CALL DLLTypePack( InData%DLL_Trgt, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DLL_Trgt + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! DLL_Trgt + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! DLL_Trgt + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! DLL_Trgt + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! DLL_Ramp + Re_BufSz = Re_BufSz + 1 ! BlAlpha + Int_BufSz = Int_BufSz + 1 ! DLL_n + Int_BufSz = Int_BufSz + 1 ! avcOUTNAME_LEN + Re_BufSz = Re_BufSz + 1 ! NacYaw_North + Re_BufSz = Re_BufSz + 1 ! AvgWindSpeed + Re_BufSz = Re_BufSz + 1 ! AirDens + Int_BufSz = Int_BufSz + 1 ! TrimCase + Re_BufSz = Re_BufSz + 1 ! TrimGain + Re_BufSz = Re_BufSz + 1 ! RotSpeedRef + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%HSSBrDT + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSSBrTqF + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_POSl + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_POTq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_SlPc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_Slop + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SIG_SySp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_A0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_C0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_C1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_C2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_K2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_MR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_Re1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_RLR + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_RRes + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_SRes + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_SySp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_V1a + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_VLL + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TEC_Xe1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenEff + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%BlPitchInit) ) 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%BlPitchInit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchInit,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchInit,1), UBOUND(InData%BlPitchInit,1) + ReKiBuf(Re_Xferred) = InData%BlPitchInit(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlPitchF) ) 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%BlPitchF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchF,1), UBOUND(InData%BlPitchF,1) + ReKiBuf(Re_Xferred) = InData%BlPitchF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PitManRat) ) 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%PitManRat,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PitManRat,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PitManRat,1), UBOUND(InData%PitManRat,1) + ReKiBuf(Re_Xferred) = InData%PitManRat(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%YawManRat + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYawF + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SpdGenOn + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%THSSBrDp + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%THSSBrFl + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimGenOf + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TimGenOn + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TPCOn + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TPitManS) ) 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%TPitManS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TPitManS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TPitManS,1), UBOUND(InData%TPitManS,1) + DbKiBuf(Db_Xferred) = InData%TPitManS(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%TYawManS + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TYCOn + Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_RtGnSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_RtTq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_Slope + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_SlPc + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_SySp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_TrGnSp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawPosCom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRateCom + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%GenModel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%HSSBrMode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%PCMode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VSContrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%YCMode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenTiStp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%GenTiStr, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VS_Rgn2K + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawNeut + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawSpr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawDamp + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%TpBrDT + Db_Xferred = Db_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TBDepISp) ) 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%TBDepISp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TBDepISp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TBDepISp,1), UBOUND(InData%TBDepISp,1) + ReKiBuf(Re_Xferred) = InData%TBDepISp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%TBDrConN + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TBDrConD + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumBl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompNTMD, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CompTTMD, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts_DLL + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseBladedInterface, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseLegacyInterface, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL DLLTypePack( InData%DLL_Trgt, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DLL_Trgt + 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) = TRANSFER(InData%DLL_Ramp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%BlAlpha + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DLL_n + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%avcOUTNAME_LEN + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NacYaw_North + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AvgWindSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AirDens + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TrimCase + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TrimGain + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeedRef + Re_Xferred = Re_Xferred + 1 + CALL TMD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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 SrvD_PackParam + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HSSBrDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%HSSBrTqF = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_POSl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_POTq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_SlPc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_Slop = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SIG_SySp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_A0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_C0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_C1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_C2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_K2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_MR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_Re1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_RLR = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_RRes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_SRes = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_SySp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_V1a = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_VLL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TEC_Xe1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenEff = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchInit 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%BlPitchInit)) DEALLOCATE(OutData%BlPitchInit) + ALLOCATE(OutData%BlPitchInit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchInit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchInit,1), UBOUND(OutData%BlPitchInit,1) + OutData%BlPitchInit(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchF 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%BlPitchF)) DEALLOCATE(OutData%BlPitchF) + ALLOCATE(OutData%BlPitchF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchF,1), UBOUND(OutData%BlPitchF,1) + OutData%BlPitchF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PitManRat 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%PitManRat)) DEALLOCATE(OutData%PitManRat) + ALLOCATE(OutData%PitManRat(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PitManRat.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PitManRat,1), UBOUND(OutData%PitManRat,1) + OutData%PitManRat(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%YawManRat = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NacYawF = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SpdGenOn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%THSSBrDp = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%THSSBrFl = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%TimGenOf = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%TimGenOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%TPCOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TPitManS 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%TPitManS)) DEALLOCATE(OutData%TPitManS) + ALLOCATE(OutData%TPitManS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TPitManS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TPitManS,1), UBOUND(OutData%TPitManS,1) + OutData%TPitManS(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + OutData%TYawManS = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%TYCOn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%VS_RtGnSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_RtTq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_Slope = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_SlPc = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_SySp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VS_TrGnSp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawPosCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRateCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenModel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%HSSBrMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PCMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%VSContrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%YCMode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%GenTiStp = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenTiStp) + Int_Xferred = Int_Xferred + 1 + OutData%GenTiStr = TRANSFER(IntKiBuf(Int_Xferred), OutData%GenTiStr) + Int_Xferred = Int_Xferred + 1 + OutData%VS_Rgn2K = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawNeut = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawSpr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawDamp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TpBrDT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TBDepISp 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%TBDepISp)) DEALLOCATE(OutData%TBDepISp) + ALLOCATE(OutData%TBDepISp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TBDepISp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TBDepISp,1), UBOUND(OutData%TBDepISp,1) + OutData%TBDepISp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%TBDrConN = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TBDrConD = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NumBl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CompNTMD = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompNTMD) + Int_Xferred = Int_Xferred + 1 + OutData%CompTTMD = TRANSFER(IntKiBuf(Int_Xferred), OutData%CompTTMD) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts_DLL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%UseBladedInterface = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseBladedInterface) + Int_Xferred = Int_Xferred + 1 + OutData%UseLegacyInterface = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseLegacyInterface) + 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 DLLTypeUnpack( OutData%DLL_Trgt, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DLL_Trgt + 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%DLL_Ramp = TRANSFER(IntKiBuf(Int_Xferred), OutData%DLL_Ramp) + Int_Xferred = Int_Xferred + 1 + OutData%BlAlpha = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DLL_n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%avcOUTNAME_LEN = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NacYaw_North = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AvgWindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AirDens = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TrimCase = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TrimGain = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeedRef = 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 TMD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 SrvD_UnPackParam + + SUBROUTINE SrvD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(SrvD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%BlPitch)) THEN + i1_l = LBOUND(SrcInputData%BlPitch,1) + i1_u = UBOUND(SrcInputData%BlPitch,1) + IF (.NOT. ALLOCATED(DstInputData%BlPitch)) THEN + ALLOCATE(DstInputData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%BlPitch = SrcInputData%BlPitch +ENDIF + DstInputData%Yaw = SrcInputData%Yaw + DstInputData%YawRate = SrcInputData%YawRate + DstInputData%LSS_Spd = SrcInputData%LSS_Spd + DstInputData%HSS_Spd = SrcInputData%HSS_Spd + DstInputData%RotSpeed = SrcInputData%RotSpeed + DstInputData%ExternalYawPosCom = SrcInputData%ExternalYawPosCom + DstInputData%ExternalYawRateCom = SrcInputData%ExternalYawRateCom +IF (ALLOCATED(SrcInputData%ExternalBlPitchCom)) THEN + i1_l = LBOUND(SrcInputData%ExternalBlPitchCom,1) + i1_u = UBOUND(SrcInputData%ExternalBlPitchCom,1) + IF (.NOT. ALLOCATED(DstInputData%ExternalBlPitchCom)) THEN + ALLOCATE(DstInputData%ExternalBlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%ExternalBlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%ExternalBlPitchCom = SrcInputData%ExternalBlPitchCom +ENDIF + DstInputData%ExternalGenTrq = SrcInputData%ExternalGenTrq + DstInputData%ExternalElecPwr = SrcInputData%ExternalElecPwr + DstInputData%ExternalHSSBrFrac = SrcInputData%ExternalHSSBrFrac + DstInputData%TwrAccel = SrcInputData%TwrAccel + DstInputData%YawErr = SrcInputData%YawErr + DstInputData%WindDir = SrcInputData%WindDir + DstInputData%RootMyc = SrcInputData%RootMyc + DstInputData%YawBrTAxp = SrcInputData%YawBrTAxp + DstInputData%YawBrTAyp = SrcInputData%YawBrTAyp + DstInputData%LSSTipPxa = SrcInputData%LSSTipPxa + DstInputData%RootMxc = SrcInputData%RootMxc + DstInputData%LSSTipMxa = SrcInputData%LSSTipMxa + DstInputData%LSSTipMya = SrcInputData%LSSTipMya + DstInputData%LSSTipMza = SrcInputData%LSSTipMza + DstInputData%LSSTipMys = SrcInputData%LSSTipMys + DstInputData%LSSTipMzs = SrcInputData%LSSTipMzs + DstInputData%YawBrMyn = SrcInputData%YawBrMyn + DstInputData%YawBrMzn = SrcInputData%YawBrMzn + DstInputData%NcIMURAxs = SrcInputData%NcIMURAxs + DstInputData%NcIMURAys = SrcInputData%NcIMURAys + DstInputData%NcIMURAzs = SrcInputData%NcIMURAzs + DstInputData%RotPwr = SrcInputData%RotPwr + DstInputData%HorWindV = SrcInputData%HorWindV + DstInputData%YawAngle = SrcInputData%YawAngle + CALL TMD_CopyInput( SrcInputData%NTMD, DstInputData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyInput( SrcInputData%TTMD, DstInputData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%SuperController)) THEN + i1_l = LBOUND(SrcInputData%SuperController,1) + i1_u = UBOUND(SrcInputData%SuperController,1) + IF (.NOT. ALLOCATED(DstInputData%SuperController)) THEN + ALLOCATE(DstInputData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%SuperController = SrcInputData%SuperController +ENDIF + END SUBROUTINE SrvD_CopyInput + + SUBROUTINE SrvD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SrvD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputData%BlPitch)) THEN + DEALLOCATE(InputData%BlPitch) +ENDIF +IF (ALLOCATED(InputData%ExternalBlPitchCom)) THEN + DEALLOCATE(InputData%ExternalBlPitchCom) +ENDIF + CALL TMD_DestroyInput( InputData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyInput( InputData%TTMD, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%SuperController)) THEN + DEALLOCATE(InputData%SuperController) +ENDIF + END SUBROUTINE SrvD_DestroyInput + + SUBROUTINE SrvD_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(SrvD_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 = 'SrvD_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 ! BlPitch allocated yes/no + IF ( ALLOCATED(InData%BlPitch) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitch upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitch) ! BlPitch + END IF + Re_BufSz = Re_BufSz + 1 ! Yaw + Re_BufSz = Re_BufSz + 1 ! YawRate + Re_BufSz = Re_BufSz + 1 ! LSS_Spd + Re_BufSz = Re_BufSz + 1 ! HSS_Spd + Re_BufSz = Re_BufSz + 1 ! RotSpeed + Re_BufSz = Re_BufSz + 1 ! ExternalYawPosCom + Re_BufSz = Re_BufSz + 1 ! ExternalYawRateCom + Int_BufSz = Int_BufSz + 1 ! ExternalBlPitchCom allocated yes/no + IF ( ALLOCATED(InData%ExternalBlPitchCom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ExternalBlPitchCom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ExternalBlPitchCom) ! ExternalBlPitchCom + END IF + Re_BufSz = Re_BufSz + 1 ! ExternalGenTrq + Re_BufSz = Re_BufSz + 1 ! ExternalElecPwr + Re_BufSz = Re_BufSz + 1 ! ExternalHSSBrFrac + Re_BufSz = Re_BufSz + 1 ! TwrAccel + Re_BufSz = Re_BufSz + 1 ! YawErr + Re_BufSz = Re_BufSz + 1 ! WindDir + Re_BufSz = Re_BufSz + SIZE(InData%RootMyc) ! RootMyc + Re_BufSz = Re_BufSz + 1 ! YawBrTAxp + Re_BufSz = Re_BufSz + 1 ! YawBrTAyp + Re_BufSz = Re_BufSz + 1 ! LSSTipPxa + Re_BufSz = Re_BufSz + SIZE(InData%RootMxc) ! RootMxc + Re_BufSz = Re_BufSz + 1 ! LSSTipMxa + Re_BufSz = Re_BufSz + 1 ! LSSTipMya + Re_BufSz = Re_BufSz + 1 ! LSSTipMza + Re_BufSz = Re_BufSz + 1 ! LSSTipMys + Re_BufSz = Re_BufSz + 1 ! LSSTipMzs + Re_BufSz = Re_BufSz + 1 ! YawBrMyn + Re_BufSz = Re_BufSz + 1 ! YawBrMzn + Re_BufSz = Re_BufSz + 1 ! NcIMURAxs + Re_BufSz = Re_BufSz + 1 ! NcIMURAys + Re_BufSz = Re_BufSz + 1 ! NcIMURAzs + Re_BufSz = Re_BufSz + 1 ! RotPwr + Re_BufSz = Re_BufSz + 1 ! HorWindV + Re_BufSz = Re_BufSz + 1 ! YawAngle + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! SuperController allocated yes/no + IF ( ALLOCATED(InData%SuperController) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SuperController upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SuperController) ! SuperController + 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%BlPitch) ) 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%BlPitch,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitch,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitch,1), UBOUND(InData%BlPitch,1) + ReKiBuf(Re_Xferred) = InData%BlPitch(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Yaw + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawRate + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSS_Spd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSS_Spd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ExternalYawPosCom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ExternalYawRateCom + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%ExternalBlPitchCom) ) 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%ExternalBlPitchCom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ExternalBlPitchCom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ExternalBlPitchCom,1), UBOUND(InData%ExternalBlPitchCom,1) + ReKiBuf(Re_Xferred) = InData%ExternalBlPitchCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%ExternalGenTrq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ExternalElecPwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ExternalHSSBrFrac + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TwrAccel + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawErr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WindDir + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RootMyc,1), UBOUND(InData%RootMyc,1) + ReKiBuf(Re_Xferred) = InData%RootMyc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%YawBrTAxp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrTAyp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipPxa + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RootMxc,1), UBOUND(InData%RootMxc,1) + ReKiBuf(Re_Xferred) = InData%RootMxc(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%LSSTipMxa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMya + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMza + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LSSTipMzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMyn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawBrMzn + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAxs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAys + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%NcIMURAzs + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RotPwr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HorWindV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YawAngle + Re_Xferred = Re_Xferred + 1 + CALL TMD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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%SuperController) ) 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%SuperController,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SuperController,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SuperController,1), UBOUND(InData%SuperController,1) + ReKiBuf(Re_Xferred) = InData%SuperController(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_PackInput + + SUBROUTINE SrvD_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(SrvD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_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 ! BlPitch 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%BlPitch)) DEALLOCATE(OutData%BlPitch) + ALLOCATE(OutData%BlPitch(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitch.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitch,1), UBOUND(OutData%BlPitch,1) + OutData%BlPitch(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Yaw = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawRate = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSS_Spd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSS_Spd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ExternalYawPosCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ExternalYawRateCom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ExternalBlPitchCom 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%ExternalBlPitchCom)) DEALLOCATE(OutData%ExternalBlPitchCom) + ALLOCATE(OutData%ExternalBlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ExternalBlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ExternalBlPitchCom,1), UBOUND(OutData%ExternalBlPitchCom,1) + OutData%ExternalBlPitchCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%ExternalGenTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ExternalElecPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ExternalHSSBrFrac = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TwrAccel = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawErr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WindDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RootMyc,1) + i1_u = UBOUND(OutData%RootMyc,1) + DO i1 = LBOUND(OutData%RootMyc,1), UBOUND(OutData%RootMyc,1) + OutData%RootMyc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%YawBrTAxp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrTAyp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipPxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RootMxc,1) + i1_u = UBOUND(OutData%RootMxc,1) + DO i1 = LBOUND(OutData%RootMxc,1), UBOUND(OutData%RootMxc,1) + OutData%RootMxc(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%LSSTipMxa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMya = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMza = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LSSTipMzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMyn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawBrMzn = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAxs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAys = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NcIMURAzs = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HorWindV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YawAngle = 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 TMD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 ! SuperController 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%SuperController)) DEALLOCATE(OutData%SuperController) + ALLOCATE(OutData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SuperController,1), UBOUND(OutData%SuperController,1) + OutData%SuperController(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_UnPackInput + + SUBROUTINE SrvD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SrvD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(SrvD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'SrvD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF +IF (ALLOCATED(SrcOutputData%BlPitchCom)) THEN + i1_l = LBOUND(SrcOutputData%BlPitchCom,1) + i1_u = UBOUND(SrcOutputData%BlPitchCom,1) + IF (.NOT. ALLOCATED(DstOutputData%BlPitchCom)) THEN + ALLOCATE(DstOutputData%BlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%BlPitchCom = SrcOutputData%BlPitchCom +ENDIF +IF (ALLOCATED(SrcOutputData%BlAirfoilCom)) THEN + i1_l = LBOUND(SrcOutputData%BlAirfoilCom,1) + i1_u = UBOUND(SrcOutputData%BlAirfoilCom,1) + IF (.NOT. ALLOCATED(DstOutputData%BlAirfoilCom)) THEN + ALLOCATE(DstOutputData%BlAirfoilCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%BlAirfoilCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%BlAirfoilCom = SrcOutputData%BlAirfoilCom +ENDIF + DstOutputData%YawMom = SrcOutputData%YawMom + DstOutputData%GenTrq = SrcOutputData%GenTrq + DstOutputData%HSSBrTrqC = SrcOutputData%HSSBrTrqC + DstOutputData%ElecPwr = SrcOutputData%ElecPwr +IF (ALLOCATED(SrcOutputData%TBDrCon)) THEN + i1_l = LBOUND(SrcOutputData%TBDrCon,1) + i1_u = UBOUND(SrcOutputData%TBDrCon,1) + IF (.NOT. ALLOCATED(DstOutputData%TBDrCon)) THEN + ALLOCATE(DstOutputData%TBDrCon(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%TBDrCon.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%TBDrCon = SrcOutputData%TBDrCon +ENDIF + CALL TMD_CopyOutput( SrcOutputData%NTMD, DstOutputData%NTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL TMD_CopyOutput( SrcOutputData%TTMD, DstOutputData%TTMD, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%SuperController)) THEN + i1_l = LBOUND(SrcOutputData%SuperController,1) + i1_u = UBOUND(SrcOutputData%SuperController,1) + IF (.NOT. ALLOCATED(DstOutputData%SuperController)) THEN + ALLOCATE(DstOutputData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%SuperController = SrcOutputData%SuperController +ENDIF + END SUBROUTINE SrvD_CopyOutput + + SUBROUTINE SrvD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SrvD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF +IF (ALLOCATED(OutputData%BlPitchCom)) THEN + DEALLOCATE(OutputData%BlPitchCom) +ENDIF +IF (ALLOCATED(OutputData%BlAirfoilCom)) THEN + DEALLOCATE(OutputData%BlAirfoilCom) +ENDIF +IF (ALLOCATED(OutputData%TBDrCon)) THEN + DEALLOCATE(OutputData%TBDrCon) +ENDIF + CALL TMD_DestroyOutput( OutputData%NTMD, ErrStat, ErrMsg ) + CALL TMD_DestroyOutput( OutputData%TTMD, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%SuperController)) THEN + DEALLOCATE(OutputData%SuperController) +ENDIF + END SUBROUTINE SrvD_DestroyOutput + + SUBROUTINE SrvD_PackOutput( 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(SrvD_OutputType), 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 = 'SrvD_PackOutput' + ! 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 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + Int_BufSz = Int_BufSz + 1 ! BlPitchCom allocated yes/no + IF ( ALLOCATED(InData%BlPitchCom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlPitchCom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlPitchCom) ! BlPitchCom + END IF + Int_BufSz = Int_BufSz + 1 ! BlAirfoilCom allocated yes/no + IF ( ALLOCATED(InData%BlAirfoilCom) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! BlAirfoilCom upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%BlAirfoilCom) ! BlAirfoilCom + END IF + Re_BufSz = Re_BufSz + 1 ! YawMom + Re_BufSz = Re_BufSz + 1 ! GenTrq + Re_BufSz = Re_BufSz + 1 ! HSSBrTrqC + Re_BufSz = Re_BufSz + 1 ! ElecPwr + Int_BufSz = Int_BufSz + 1 ! TBDrCon allocated yes/no + IF ( ALLOCATED(InData%TBDrCon) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! TBDrCon upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TBDrCon) ! TBDrCon + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! NTMD: size of buffers for each call to pack subtype + CALL TMD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, .TRUE. ) ! NTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TTMD: size of buffers for each call to pack subtype + CALL TMD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, .TRUE. ) ! TTMD + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TTMD + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TTMD + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TTMD + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! SuperController allocated yes/no + IF ( ALLOCATED(InData%SuperController) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SuperController upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SuperController) ! SuperController + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlPitchCom) ) 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%BlPitchCom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlPitchCom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlPitchCom,1), UBOUND(InData%BlPitchCom,1) + ReKiBuf(Re_Xferred) = InData%BlPitchCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BlAirfoilCom) ) 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%BlAirfoilCom,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlAirfoilCom,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%BlAirfoilCom,1), UBOUND(InData%BlAirfoilCom,1) + ReKiBuf(Re_Xferred) = InData%BlAirfoilCom(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%YawMom + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GenTrq + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HSSBrTrqC + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ElecPwr + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TBDrCon) ) 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%TBDrCon,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TBDrCon,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%TBDrCon,1), UBOUND(InData%TBDrCon,1) + ReKiBuf(Re_Xferred) = InData%TBDrCon(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + CALL TMD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%NTMD, ErrStat2, ErrMsg2, OnlySize ) ! NTMD + 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 TMD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%TTMD, ErrStat2, ErrMsg2, OnlySize ) ! TTMD + 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%SuperController) ) 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%SuperController,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SuperController,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SuperController,1), UBOUND(InData%SuperController,1) + ReKiBuf(Re_Xferred) = InData%SuperController(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_PackOutput + + SUBROUTINE SrvD_UnPackOutput( 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(SrvD_OutputType), 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 = 'SrvD_UnPackOutput' + ! 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlPitchCom 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%BlPitchCom)) DEALLOCATE(OutData%BlPitchCom) + ALLOCATE(OutData%BlPitchCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlPitchCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlPitchCom,1), UBOUND(OutData%BlPitchCom,1) + OutData%BlPitchCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlAirfoilCom 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%BlAirfoilCom)) DEALLOCATE(OutData%BlAirfoilCom) + ALLOCATE(OutData%BlAirfoilCom(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlAirfoilCom.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%BlAirfoilCom,1), UBOUND(OutData%BlAirfoilCom,1) + OutData%BlAirfoilCom(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%YawMom = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GenTrq = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HSSBrTrqC = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ElecPwr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TBDrCon 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%TBDrCon)) DEALLOCATE(OutData%TBDrCon) + ALLOCATE(OutData%TBDrCon(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TBDrCon.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%TBDrCon,1), UBOUND(OutData%TBDrCon,1) + OutData%TBDrCon(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + 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 TMD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%NTMD, ErrStat2, ErrMsg2 ) ! NTMD + 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 TMD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%TTMD, ErrStat2, ErrMsg2 ) ! TTMD + 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 ! SuperController 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%SuperController)) DEALLOCATE(OutData%SuperController) + ALLOCATE(OutData%SuperController(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SuperController.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SuperController,1), UBOUND(OutData%SuperController,1) + OutData%SuperController(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SrvD_UnPackOutput + + + SUBROUTINE SrvD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SrvD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SrvD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SrvD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SrvD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SrvD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SrvD_Input_ExtrapInterp + + + SUBROUTINE SrvD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SrvD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(SrvD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SrvD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%BlPitch) .AND. ALLOCATED(u1%BlPitch)) THEN + DO i1 = LBOUND(u_out%BlPitch,1),UBOUND(u_out%BlPitch,1) + CALL Angles_ExtrapInterp( u1%BlPitch(i1), u2%BlPitch(i1), tin, u_out%BlPitch(i1), tin_out ) + END DO +END IF ! check if allocated + CALL Angles_ExtrapInterp( u1%Yaw, u2%Yaw, tin, u_out%Yaw, tin_out ) + b = -(u1%YawRate - u2%YawRate) + u_out%YawRate = u1%YawRate + b * ScaleFactor + b = -(u1%LSS_Spd - u2%LSS_Spd) + u_out%LSS_Spd = u1%LSS_Spd + b * ScaleFactor + b = -(u1%HSS_Spd - u2%HSS_Spd) + u_out%HSS_Spd = u1%HSS_Spd + b * ScaleFactor + b = -(u1%RotSpeed - u2%RotSpeed) + u_out%RotSpeed = u1%RotSpeed + b * ScaleFactor + CALL Angles_ExtrapInterp( u1%ExternalYawPosCom, u2%ExternalYawPosCom, tin, u_out%ExternalYawPosCom, tin_out ) + b = -(u1%ExternalYawRateCom - u2%ExternalYawRateCom) + u_out%ExternalYawRateCom = u1%ExternalYawRateCom + b * ScaleFactor +IF (ALLOCATED(u_out%ExternalBlPitchCom) .AND. ALLOCATED(u1%ExternalBlPitchCom)) THEN + DO i1 = LBOUND(u_out%ExternalBlPitchCom,1),UBOUND(u_out%ExternalBlPitchCom,1) + CALL Angles_ExtrapInterp( u1%ExternalBlPitchCom(i1), u2%ExternalBlPitchCom(i1), tin, u_out%ExternalBlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated + b = -(u1%ExternalGenTrq - u2%ExternalGenTrq) + u_out%ExternalGenTrq = u1%ExternalGenTrq + b * ScaleFactor + b = -(u1%ExternalElecPwr - u2%ExternalElecPwr) + u_out%ExternalElecPwr = u1%ExternalElecPwr + b * ScaleFactor + b = -(u1%ExternalHSSBrFrac - u2%ExternalHSSBrFrac) + u_out%ExternalHSSBrFrac = u1%ExternalHSSBrFrac + b * ScaleFactor + b = -(u1%TwrAccel - u2%TwrAccel) + u_out%TwrAccel = u1%TwrAccel + b * ScaleFactor + CALL Angles_ExtrapInterp( u1%YawErr, u2%YawErr, tin, u_out%YawErr, tin_out ) + CALL Angles_ExtrapInterp( u1%WindDir, u2%WindDir, tin, u_out%WindDir, tin_out ) + DO i1 = LBOUND(u_out%RootMyc,1),UBOUND(u_out%RootMyc,1) + b = -(u1%RootMyc(i1) - u2%RootMyc(i1)) + u_out%RootMyc(i1) = u1%RootMyc(i1) + b * ScaleFactor + END DO + b = -(u1%YawBrTAxp - u2%YawBrTAxp) + u_out%YawBrTAxp = u1%YawBrTAxp + b * ScaleFactor + b = -(u1%YawBrTAyp - u2%YawBrTAyp) + u_out%YawBrTAyp = u1%YawBrTAyp + b * ScaleFactor + b = -(u1%LSSTipPxa - u2%LSSTipPxa) + u_out%LSSTipPxa = u1%LSSTipPxa + b * ScaleFactor + DO i1 = LBOUND(u_out%RootMxc,1),UBOUND(u_out%RootMxc,1) + b = -(u1%RootMxc(i1) - u2%RootMxc(i1)) + u_out%RootMxc(i1) = u1%RootMxc(i1) + b * ScaleFactor + END DO + b = -(u1%LSSTipMxa - u2%LSSTipMxa) + u_out%LSSTipMxa = u1%LSSTipMxa + b * ScaleFactor + b = -(u1%LSSTipMya - u2%LSSTipMya) + u_out%LSSTipMya = u1%LSSTipMya + b * ScaleFactor + b = -(u1%LSSTipMza - u2%LSSTipMza) + u_out%LSSTipMza = u1%LSSTipMza + b * ScaleFactor + b = -(u1%LSSTipMys - u2%LSSTipMys) + u_out%LSSTipMys = u1%LSSTipMys + b * ScaleFactor + b = -(u1%LSSTipMzs - u2%LSSTipMzs) + u_out%LSSTipMzs = u1%LSSTipMzs + b * ScaleFactor + b = -(u1%YawBrMyn - u2%YawBrMyn) + u_out%YawBrMyn = u1%YawBrMyn + b * ScaleFactor + b = -(u1%YawBrMzn - u2%YawBrMzn) + u_out%YawBrMzn = u1%YawBrMzn + b * ScaleFactor + b = -(u1%NcIMURAxs - u2%NcIMURAxs) + u_out%NcIMURAxs = u1%NcIMURAxs + b * ScaleFactor + b = -(u1%NcIMURAys - u2%NcIMURAys) + u_out%NcIMURAys = u1%NcIMURAys + b * ScaleFactor + b = -(u1%NcIMURAzs - u2%NcIMURAzs) + u_out%NcIMURAzs = u1%NcIMURAzs + b * ScaleFactor + b = -(u1%RotPwr - u2%RotPwr) + u_out%RotPwr = u1%RotPwr + b * ScaleFactor + b = -(u1%HorWindV - u2%HorWindV) + u_out%HorWindV = u1%HorWindV + b * ScaleFactor + CALL Angles_ExtrapInterp( u1%YawAngle, u2%YawAngle, tin, u_out%YawAngle, tin_out ) + CALL TMD_Input_ExtrapInterp1( u1%NTMD, u2%NTMD, tin, u_out%NTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL TMD_Input_ExtrapInterp1( u1%TTMD, u2%TTMD, tin, u_out%TTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%SuperController) .AND. ALLOCATED(u1%SuperController)) THEN + DO i1 = LBOUND(u_out%SuperController,1),UBOUND(u_out%SuperController,1) + b = -(u1%SuperController(i1) - u2%SuperController(i1)) + u_out%SuperController(i1) = u1%SuperController(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE SrvD_Input_ExtrapInterp1 + + + SUBROUTINE SrvD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SrvD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(SrvD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(SrvD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SrvD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%BlPitch) .AND. ALLOCATED(u1%BlPitch)) THEN + DO i1 = LBOUND(u_out%BlPitch,1),UBOUND(u_out%BlPitch,1) + CALL Angles_ExtrapInterp( u1%BlPitch(i1), u2%BlPitch(i1), u3%BlPitch(i1), tin, u_out%BlPitch(i1), tin_out ) + END DO +END IF ! check if allocated + CALL Angles_ExtrapInterp( u1%Yaw, u2%Yaw, u3%Yaw, tin, u_out%Yaw, tin_out ) + b = (t(3)**2*(u1%YawRate - u2%YawRate) + t(2)**2*(-u1%YawRate + u3%YawRate))* scaleFactor + c = ( (t(2)-t(3))*u1%YawRate + t(3)*u2%YawRate - t(2)*u3%YawRate ) * scaleFactor + u_out%YawRate = u1%YawRate + b + c * t_out + b = (t(3)**2*(u1%LSS_Spd - u2%LSS_Spd) + t(2)**2*(-u1%LSS_Spd + u3%LSS_Spd))* scaleFactor + c = ( (t(2)-t(3))*u1%LSS_Spd + t(3)*u2%LSS_Spd - t(2)*u3%LSS_Spd ) * scaleFactor + u_out%LSS_Spd = u1%LSS_Spd + b + c * t_out + b = (t(3)**2*(u1%HSS_Spd - u2%HSS_Spd) + t(2)**2*(-u1%HSS_Spd + u3%HSS_Spd))* scaleFactor + c = ( (t(2)-t(3))*u1%HSS_Spd + t(3)*u2%HSS_Spd - t(2)*u3%HSS_Spd ) * scaleFactor + u_out%HSS_Spd = u1%HSS_Spd + b + c * t_out + b = (t(3)**2*(u1%RotSpeed - u2%RotSpeed) + t(2)**2*(-u1%RotSpeed + u3%RotSpeed))* scaleFactor + c = ( (t(2)-t(3))*u1%RotSpeed + t(3)*u2%RotSpeed - t(2)*u3%RotSpeed ) * scaleFactor + u_out%RotSpeed = u1%RotSpeed + b + c * t_out + CALL Angles_ExtrapInterp( u1%ExternalYawPosCom, u2%ExternalYawPosCom, u3%ExternalYawPosCom, tin, u_out%ExternalYawPosCom, tin_out ) + b = (t(3)**2*(u1%ExternalYawRateCom - u2%ExternalYawRateCom) + t(2)**2*(-u1%ExternalYawRateCom + u3%ExternalYawRateCom))* scaleFactor + c = ( (t(2)-t(3))*u1%ExternalYawRateCom + t(3)*u2%ExternalYawRateCom - t(2)*u3%ExternalYawRateCom ) * scaleFactor + u_out%ExternalYawRateCom = u1%ExternalYawRateCom + b + c * t_out +IF (ALLOCATED(u_out%ExternalBlPitchCom) .AND. ALLOCATED(u1%ExternalBlPitchCom)) THEN + DO i1 = LBOUND(u_out%ExternalBlPitchCom,1),UBOUND(u_out%ExternalBlPitchCom,1) + CALL Angles_ExtrapInterp( u1%ExternalBlPitchCom(i1), u2%ExternalBlPitchCom(i1), u3%ExternalBlPitchCom(i1), tin, u_out%ExternalBlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated + b = (t(3)**2*(u1%ExternalGenTrq - u2%ExternalGenTrq) + t(2)**2*(-u1%ExternalGenTrq + u3%ExternalGenTrq))* scaleFactor + c = ( (t(2)-t(3))*u1%ExternalGenTrq + t(3)*u2%ExternalGenTrq - t(2)*u3%ExternalGenTrq ) * scaleFactor + u_out%ExternalGenTrq = u1%ExternalGenTrq + b + c * t_out + b = (t(3)**2*(u1%ExternalElecPwr - u2%ExternalElecPwr) + t(2)**2*(-u1%ExternalElecPwr + u3%ExternalElecPwr))* scaleFactor + c = ( (t(2)-t(3))*u1%ExternalElecPwr + t(3)*u2%ExternalElecPwr - t(2)*u3%ExternalElecPwr ) * scaleFactor + u_out%ExternalElecPwr = u1%ExternalElecPwr + b + c * t_out + b = (t(3)**2*(u1%ExternalHSSBrFrac - u2%ExternalHSSBrFrac) + t(2)**2*(-u1%ExternalHSSBrFrac + u3%ExternalHSSBrFrac))* scaleFactor + c = ( (t(2)-t(3))*u1%ExternalHSSBrFrac + t(3)*u2%ExternalHSSBrFrac - t(2)*u3%ExternalHSSBrFrac ) * scaleFactor + u_out%ExternalHSSBrFrac = u1%ExternalHSSBrFrac + b + c * t_out + b = (t(3)**2*(u1%TwrAccel - u2%TwrAccel) + t(2)**2*(-u1%TwrAccel + u3%TwrAccel))* scaleFactor + c = ( (t(2)-t(3))*u1%TwrAccel + t(3)*u2%TwrAccel - t(2)*u3%TwrAccel ) * scaleFactor + u_out%TwrAccel = u1%TwrAccel + b + c * t_out + CALL Angles_ExtrapInterp( u1%YawErr, u2%YawErr, u3%YawErr, tin, u_out%YawErr, tin_out ) + CALL Angles_ExtrapInterp( u1%WindDir, u2%WindDir, u3%WindDir, tin, u_out%WindDir, tin_out ) + DO i1 = LBOUND(u_out%RootMyc,1),UBOUND(u_out%RootMyc,1) + b = (t(3)**2*(u1%RootMyc(i1) - u2%RootMyc(i1)) + t(2)**2*(-u1%RootMyc(i1) + u3%RootMyc(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%RootMyc(i1) + t(3)*u2%RootMyc(i1) - t(2)*u3%RootMyc(i1) ) * scaleFactor + u_out%RootMyc(i1) = u1%RootMyc(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%YawBrTAxp - u2%YawBrTAxp) + t(2)**2*(-u1%YawBrTAxp + u3%YawBrTAxp))* scaleFactor + c = ( (t(2)-t(3))*u1%YawBrTAxp + t(3)*u2%YawBrTAxp - t(2)*u3%YawBrTAxp ) * scaleFactor + u_out%YawBrTAxp = u1%YawBrTAxp + b + c * t_out + b = (t(3)**2*(u1%YawBrTAyp - u2%YawBrTAyp) + t(2)**2*(-u1%YawBrTAyp + u3%YawBrTAyp))* scaleFactor + c = ( (t(2)-t(3))*u1%YawBrTAyp + t(3)*u2%YawBrTAyp - t(2)*u3%YawBrTAyp ) * scaleFactor + u_out%YawBrTAyp = u1%YawBrTAyp + b + c * t_out + b = (t(3)**2*(u1%LSSTipPxa - u2%LSSTipPxa) + t(2)**2*(-u1%LSSTipPxa + u3%LSSTipPxa))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipPxa + t(3)*u2%LSSTipPxa - t(2)*u3%LSSTipPxa ) * scaleFactor + u_out%LSSTipPxa = u1%LSSTipPxa + b + c * t_out + DO i1 = LBOUND(u_out%RootMxc,1),UBOUND(u_out%RootMxc,1) + b = (t(3)**2*(u1%RootMxc(i1) - u2%RootMxc(i1)) + t(2)**2*(-u1%RootMxc(i1) + u3%RootMxc(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%RootMxc(i1) + t(3)*u2%RootMxc(i1) - t(2)*u3%RootMxc(i1) ) * scaleFactor + u_out%RootMxc(i1) = u1%RootMxc(i1) + b + c * t_out + END DO + b = (t(3)**2*(u1%LSSTipMxa - u2%LSSTipMxa) + t(2)**2*(-u1%LSSTipMxa + u3%LSSTipMxa))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipMxa + t(3)*u2%LSSTipMxa - t(2)*u3%LSSTipMxa ) * scaleFactor + u_out%LSSTipMxa = u1%LSSTipMxa + b + c * t_out + b = (t(3)**2*(u1%LSSTipMya - u2%LSSTipMya) + t(2)**2*(-u1%LSSTipMya + u3%LSSTipMya))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipMya + t(3)*u2%LSSTipMya - t(2)*u3%LSSTipMya ) * scaleFactor + u_out%LSSTipMya = u1%LSSTipMya + b + c * t_out + b = (t(3)**2*(u1%LSSTipMza - u2%LSSTipMza) + t(2)**2*(-u1%LSSTipMza + u3%LSSTipMza))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipMza + t(3)*u2%LSSTipMza - t(2)*u3%LSSTipMza ) * scaleFactor + u_out%LSSTipMza = u1%LSSTipMza + b + c * t_out + b = (t(3)**2*(u1%LSSTipMys - u2%LSSTipMys) + t(2)**2*(-u1%LSSTipMys + u3%LSSTipMys))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipMys + t(3)*u2%LSSTipMys - t(2)*u3%LSSTipMys ) * scaleFactor + u_out%LSSTipMys = u1%LSSTipMys + b + c * t_out + b = (t(3)**2*(u1%LSSTipMzs - u2%LSSTipMzs) + t(2)**2*(-u1%LSSTipMzs + u3%LSSTipMzs))* scaleFactor + c = ( (t(2)-t(3))*u1%LSSTipMzs + t(3)*u2%LSSTipMzs - t(2)*u3%LSSTipMzs ) * scaleFactor + u_out%LSSTipMzs = u1%LSSTipMzs + b + c * t_out + b = (t(3)**2*(u1%YawBrMyn - u2%YawBrMyn) + t(2)**2*(-u1%YawBrMyn + u3%YawBrMyn))* scaleFactor + c = ( (t(2)-t(3))*u1%YawBrMyn + t(3)*u2%YawBrMyn - t(2)*u3%YawBrMyn ) * scaleFactor + u_out%YawBrMyn = u1%YawBrMyn + b + c * t_out + b = (t(3)**2*(u1%YawBrMzn - u2%YawBrMzn) + t(2)**2*(-u1%YawBrMzn + u3%YawBrMzn))* scaleFactor + c = ( (t(2)-t(3))*u1%YawBrMzn + t(3)*u2%YawBrMzn - t(2)*u3%YawBrMzn ) * scaleFactor + u_out%YawBrMzn = u1%YawBrMzn + b + c * t_out + b = (t(3)**2*(u1%NcIMURAxs - u2%NcIMURAxs) + t(2)**2*(-u1%NcIMURAxs + u3%NcIMURAxs))* scaleFactor + c = ( (t(2)-t(3))*u1%NcIMURAxs + t(3)*u2%NcIMURAxs - t(2)*u3%NcIMURAxs ) * scaleFactor + u_out%NcIMURAxs = u1%NcIMURAxs + b + c * t_out + b = (t(3)**2*(u1%NcIMURAys - u2%NcIMURAys) + t(2)**2*(-u1%NcIMURAys + u3%NcIMURAys))* scaleFactor + c = ( (t(2)-t(3))*u1%NcIMURAys + t(3)*u2%NcIMURAys - t(2)*u3%NcIMURAys ) * scaleFactor + u_out%NcIMURAys = u1%NcIMURAys + b + c * t_out + b = (t(3)**2*(u1%NcIMURAzs - u2%NcIMURAzs) + t(2)**2*(-u1%NcIMURAzs + u3%NcIMURAzs))* scaleFactor + c = ( (t(2)-t(3))*u1%NcIMURAzs + t(3)*u2%NcIMURAzs - t(2)*u3%NcIMURAzs ) * scaleFactor + u_out%NcIMURAzs = u1%NcIMURAzs + b + c * t_out + b = (t(3)**2*(u1%RotPwr - u2%RotPwr) + t(2)**2*(-u1%RotPwr + u3%RotPwr))* scaleFactor + c = ( (t(2)-t(3))*u1%RotPwr + t(3)*u2%RotPwr - t(2)*u3%RotPwr ) * scaleFactor + u_out%RotPwr = u1%RotPwr + b + c * t_out + b = (t(3)**2*(u1%HorWindV - u2%HorWindV) + t(2)**2*(-u1%HorWindV + u3%HorWindV))* scaleFactor + c = ( (t(2)-t(3))*u1%HorWindV + t(3)*u2%HorWindV - t(2)*u3%HorWindV ) * scaleFactor + u_out%HorWindV = u1%HorWindV + b + c * t_out + CALL Angles_ExtrapInterp( u1%YawAngle, u2%YawAngle, u3%YawAngle, tin, u_out%YawAngle, tin_out ) + CALL TMD_Input_ExtrapInterp2( u1%NTMD, u2%NTMD, u3%NTMD, tin, u_out%NTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL TMD_Input_ExtrapInterp2( u1%TTMD, u2%TTMD, u3%TTMD, tin, u_out%TTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%SuperController) .AND. ALLOCATED(u1%SuperController)) THEN + DO i1 = LBOUND(u_out%SuperController,1),UBOUND(u_out%SuperController,1) + b = (t(3)**2*(u1%SuperController(i1) - u2%SuperController(i1)) + t(2)**2*(-u1%SuperController(i1) + u3%SuperController(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%SuperController(i1) + t(3)*u2%SuperController(i1) - t(2)*u3%SuperController(i1) ) * scaleFactor + u_out%SuperController(i1) = u1%SuperController(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE SrvD_Input_ExtrapInterp2 + + + SUBROUTINE SrvD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SrvD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SrvD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SrvD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SrvD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SrvD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SrvD_Output_ExtrapInterp + + + SUBROUTINE SrvD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SrvD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(SrvD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SrvD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlPitchCom) .AND. ALLOCATED(y1%BlPitchCom)) THEN + DO i1 = LBOUND(y_out%BlPitchCom,1),UBOUND(y_out%BlPitchCom,1) + CALL Angles_ExtrapInterp( y1%BlPitchCom(i1), y2%BlPitchCom(i1), tin, y_out%BlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlAirfoilCom) .AND. ALLOCATED(y1%BlAirfoilCom)) THEN + DO i1 = LBOUND(y_out%BlAirfoilCom,1),UBOUND(y_out%BlAirfoilCom,1) + b = -(y1%BlAirfoilCom(i1) - y2%BlAirfoilCom(i1)) + y_out%BlAirfoilCom(i1) = y1%BlAirfoilCom(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + b = -(y1%YawMom - y2%YawMom) + y_out%YawMom = y1%YawMom + b * ScaleFactor + b = -(y1%GenTrq - y2%GenTrq) + y_out%GenTrq = y1%GenTrq + b * ScaleFactor + b = -(y1%HSSBrTrqC - y2%HSSBrTrqC) + y_out%HSSBrTrqC = y1%HSSBrTrqC + b * ScaleFactor + b = -(y1%ElecPwr - y2%ElecPwr) + y_out%ElecPwr = y1%ElecPwr + b * ScaleFactor +IF (ALLOCATED(y_out%TBDrCon) .AND. ALLOCATED(y1%TBDrCon)) THEN + DO i1 = LBOUND(y_out%TBDrCon,1),UBOUND(y_out%TBDrCon,1) + b = -(y1%TBDrCon(i1) - y2%TBDrCon(i1)) + y_out%TBDrCon(i1) = y1%TBDrCon(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + CALL TMD_Output_ExtrapInterp1( y1%NTMD, y2%NTMD, tin, y_out%NTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL TMD_Output_ExtrapInterp1( y1%TTMD, y2%TTMD, tin, y_out%TTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%SuperController) .AND. ALLOCATED(y1%SuperController)) THEN + DO i1 = LBOUND(y_out%SuperController,1),UBOUND(y_out%SuperController,1) + b = -(y1%SuperController(i1) - y2%SuperController(i1)) + y_out%SuperController(i1) = y1%SuperController(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE SrvD_Output_ExtrapInterp1 + + + SUBROUTINE SrvD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SrvD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(SrvD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(SrvD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SrvD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SrvD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlPitchCom) .AND. ALLOCATED(y1%BlPitchCom)) THEN + DO i1 = LBOUND(y_out%BlPitchCom,1),UBOUND(y_out%BlPitchCom,1) + CALL Angles_ExtrapInterp( y1%BlPitchCom(i1), y2%BlPitchCom(i1), y3%BlPitchCom(i1), tin, y_out%BlPitchCom(i1), tin_out ) + END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%BlAirfoilCom) .AND. ALLOCATED(y1%BlAirfoilCom)) THEN + DO i1 = LBOUND(y_out%BlAirfoilCom,1),UBOUND(y_out%BlAirfoilCom,1) + b = (t(3)**2*(y1%BlAirfoilCom(i1) - y2%BlAirfoilCom(i1)) + t(2)**2*(-y1%BlAirfoilCom(i1) + y3%BlAirfoilCom(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%BlAirfoilCom(i1) + t(3)*y2%BlAirfoilCom(i1) - t(2)*y3%BlAirfoilCom(i1) ) * scaleFactor + y_out%BlAirfoilCom(i1) = y1%BlAirfoilCom(i1) + b + c * t_out + END DO +END IF ! check if allocated + b = (t(3)**2*(y1%YawMom - y2%YawMom) + t(2)**2*(-y1%YawMom + y3%YawMom))* scaleFactor + c = ( (t(2)-t(3))*y1%YawMom + t(3)*y2%YawMom - t(2)*y3%YawMom ) * scaleFactor + y_out%YawMom = y1%YawMom + b + c * t_out + b = (t(3)**2*(y1%GenTrq - y2%GenTrq) + t(2)**2*(-y1%GenTrq + y3%GenTrq))* scaleFactor + c = ( (t(2)-t(3))*y1%GenTrq + t(3)*y2%GenTrq - t(2)*y3%GenTrq ) * scaleFactor + y_out%GenTrq = y1%GenTrq + b + c * t_out + b = (t(3)**2*(y1%HSSBrTrqC - y2%HSSBrTrqC) + t(2)**2*(-y1%HSSBrTrqC + y3%HSSBrTrqC))* scaleFactor + c = ( (t(2)-t(3))*y1%HSSBrTrqC + t(3)*y2%HSSBrTrqC - t(2)*y3%HSSBrTrqC ) * scaleFactor + y_out%HSSBrTrqC = y1%HSSBrTrqC + b + c * t_out + b = (t(3)**2*(y1%ElecPwr - y2%ElecPwr) + t(2)**2*(-y1%ElecPwr + y3%ElecPwr))* scaleFactor + c = ( (t(2)-t(3))*y1%ElecPwr + t(3)*y2%ElecPwr - t(2)*y3%ElecPwr ) * scaleFactor + y_out%ElecPwr = y1%ElecPwr + b + c * t_out +IF (ALLOCATED(y_out%TBDrCon) .AND. ALLOCATED(y1%TBDrCon)) THEN + DO i1 = LBOUND(y_out%TBDrCon,1),UBOUND(y_out%TBDrCon,1) + b = (t(3)**2*(y1%TBDrCon(i1) - y2%TBDrCon(i1)) + t(2)**2*(-y1%TBDrCon(i1) + y3%TBDrCon(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%TBDrCon(i1) + t(3)*y2%TBDrCon(i1) - t(2)*y3%TBDrCon(i1) ) * scaleFactor + y_out%TBDrCon(i1) = y1%TBDrCon(i1) + b + c * t_out + END DO +END IF ! check if allocated + CALL TMD_Output_ExtrapInterp2( y1%NTMD, y2%NTMD, y3%NTMD, tin, y_out%NTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL TMD_Output_ExtrapInterp2( y1%TTMD, y2%TTMD, y3%TTMD, tin, y_out%TTMD, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%SuperController) .AND. ALLOCATED(y1%SuperController)) THEN + DO i1 = LBOUND(y_out%SuperController,1),UBOUND(y_out%SuperController,1) + b = (t(3)**2*(y1%SuperController(i1) - y2%SuperController(i1)) + t(2)**2*(-y1%SuperController(i1) + y3%SuperController(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%SuperController(i1) + t(3)*y2%SuperController(i1) - t(2)*y3%SuperController(i1) ) * scaleFactor + y_out%SuperController(i1) = y1%SuperController(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE SrvD_Output_ExtrapInterp2 + +END MODULE ServoDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/servodyn/src/TMD.f90 b/OpenFAST/modules/servodyn/src/TMD.f90 new file mode 100644 index 000000000..df29a5426 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/TMD.f90 @@ -0,0 +1,1692 @@ +!********************************************************************************************************************************** +! WLaCava (WGL) and Matt Lackner (MAL) +! Tuned Mass Damper Module +!********************************************************************************************************************************** +MODULE TMD + + USE TMD_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + + TYPE(ProgDesc), PARAMETER :: TMD_Ver = ProgDesc( 'TMD', '', '' ) + + + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: TMD_Init ! Initialization routine + PUBLIC :: TMD_End ! Ending routine (includes clean up) + + PUBLIC :: TMD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: TMD_CalcOutput ! Routine for computing outputs + + ! PUBLIC :: TMD_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: TMD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + + !PUBLIC :: TMD_UpdateDiscState ! Tight coupling routine for updating discrete states + + !PUBLIC :: TMD_JacobianPInput ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! ! (Xd), and constraint-state (Z) equations all with respect to the inputs (u) + !PUBLIC :: TMD_JacobianPContState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! ! (Xd), and constraint-state (Z) equations all with respect to the continuous + ! ! states (x) + !PUBLIC :: TMD_JacobianPDiscState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! ! (Xd), and constraint-state (Z) equations all with respect to the discrete + ! ! states (xd) + !PUBLIC :: TMD_JacobianPConstrState ! Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- + ! (Xd), and constraint-state (Z) equations all with respect to the constraint + ! states (z) + + + INTEGER(IntKi), PRIVATE, PARAMETER :: ControlMode_NONE = 0 !< The (TMD-universal) control code for not using a particular type of control + + INTEGER(IntKi), PRIVATE, PARAMETER :: DOFMode_Indept = 1 !< independent DOFs + INTEGER(IntKi), PRIVATE, PARAMETER :: DOFMode_Omni = 2 !< omni-directional + + INTEGER(IntKi), PRIVATE, PARAMETER :: CMODE_Semi = 1 !< semi-active control + INTEGER(IntKi), PRIVATE, PARAMETER :: CMODE_Active = 2 !< active control + + INTEGER(IntKi), PRIVATE, PARAMETER :: SA_CMODE_GH_vel = 1 !< 1: velocity-based ground hook control; + INTEGER(IntKi), PRIVATE, PARAMETER :: SA_CMODE_GH_invVel = 2 !< 2: Inverse velocity-based ground hook control + INTEGER(IntKi), PRIVATE, PARAMETER :: SA_CMODE_GH_disp = 3 !< 3: displacement-based ground hook control + INTEGER(IntKi), PRIVATE, PARAMETER :: SA_CMODE_Ph_FF = 4 !< 4: Phase difference Algorithm with Friction Force + INTEGER(IntKi), PRIVATE, PARAMETER :: SA_CMODE_Ph_DF = 5 !< 5: Phase difference Algorithm with Damping Force + + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE TMD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(TMD_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine. + TYPE(TMD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(TMD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(TMD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(TMD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(TMD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(TMD_OutputType), INTENT(INOUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(TMD_MiscVarType), INTENT( OUT) :: m !< Misc (optimization) variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) TMD_UpdateStates() is called in loose coupling & + !! (2) TMD_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(TMD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables + INTEGER(IntKi) :: NumOuts + TYPE(TMD_InputFile) :: InputFileData ! Data stored in the module's input file + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Init' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + NumOuts = 0 + + InitOut%dummyInitOut = 0.0_SiKi ! initialize this so compiler doesn't warn about un-set intent(out) variables + + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( EchoLibVer=.FALSE. ) + + ! Display the module information + CALL DispNVD( TMD_Ver ) + + !............................................................................................ + ! Read the input file and validate the data + ! (note p%RootName must be set first!) + !............................................................................................ + p%RootName = TRIM(InitInp%RootName)//'.TMD' ! all of the output file names from this module will end with '.TMD' + + + CALL TMD_ReadInput( InitInp%InputFile, InputFileData, Interval, p%RootName, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + + !CALL ValidatePrimaryData( InputFileData, InitInp%NumBl, ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF (ErrStat >= AbortErrLev) RETURN + + IF ( InputFileData%TMD_DOF_MODE /= ControlMode_None .and. InputFileData%TMD_DOF_MODE /= DOFMode_Indept .and. InputFileData%TMD_DOF_MODE /= DOFMode_Omni ) & + CALL SetErrStat( ErrID_Fatal, 'DOF mode (TMD_DOF_MODE) must be 0 (no DOF), 1 (two independent DOFs), or 2 (omni-directional).', ErrStat, ErrMsg, RoutineName ) + + IF ( InputFileData%TMD_CMODE /= ControlMode_None .and. InputFileData%TMD_CMODE /= CMODE_Semi ) & + CALL SetErrStat( ErrID_Fatal, 'Control mode (TMD_CMode) must be 0 (none) or 1 (semi-active) in this version of TMD.', ErrStat, ErrMsg, RoutineName ) +! IF ( InputFileData%TMD_CMODE /= ControlMode_None .and. InputFileData%TMD_CMODE /= CMODE_Semi .and. InputFileData%TMD_CMODE /= CMODE_Active) & +! CALL SetErrStat( ErrID_Fatal, 'Control mode (TMD_CMode) must be 0 (none), 1 (semi-active), or 2 (active).', ErrStat, ErrMsg, RoutineName ) + + IF ( InputFileData%TMD_SA_MODE /= SA_CMODE_GH_vel .and. & + InputFileData%TMD_SA_MODE /= SA_CMODE_GH_invVel .and. & + InputFileData%TMD_SA_MODE /= SA_CMODE_GH_disp .and. & + InputFileData%TMD_SA_MODE /= SA_CMODE_Ph_FF .and. & + InputFileData%TMD_SA_MODE /= SA_CMODE_Ph_DF ) then + CALL SetErrStat( ErrID_Fatal, 'Semi-active control mode (TMD_SA_MODE) must be 1 (velocity-based ground hook control), '// & + '2 (inverse velocity-based ground hook control), 3 (displacement-based ground hook control), '// & + '4 (phase difference algorithm with friction force), or 5 (phase difference algorithm with damping force).', ErrStat, ErrMsg, RoutineName ) + END IF + + + !............................................................................................ + ! Define parameters here: + !............................................................................................ + CALL TMD_SetParameters( InputFileData, p, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF (ErrStat >= AbortErrLev) RETURN + + p%DT = Interval + p%Gravity = InitInp%Gravity + ! Destroy the local initialization data + !CALL CleanUp() + + !............................................................................................ + ! Define initial system states here: + !............................................................................................ + ! Define initial system states here: + + xd%DummyDiscState = 0 + z%DummyConstrState = 0 + + ! Initialize other states here: + OtherState%DummyOtherState = 0 + + ! misc variables: external and stop forces + m%F_ext = 0.0_ReKi ! whole array initializaton + m%F_stop = 0.0_ReKi ! whole array initializaton + m%F_fr = 0.0_ReKi ! whole array initialization + m%C_ctrl = 0.0_ReKi ! whole array initialization + m%C_Brake = 0.0_ReKi ! whole array initialization + m%F_table = 0.0_ReKi ! whole array initialization + + ! Define initial guess for the system inputs here: + x%tmd_x(1) = p%X_DSP + x%tmd_x(2) = 0 + x%tmd_x(3) = p%Y_DSP + x%tmd_x(4) = 0 + + + ! Define system output initializations (set up mesh) here: + ! Create the input and output meshes associated with lumped loads + + CALL MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! Create the node on the mesh + + + ! make position node at point P (rest position of TMDs, somewhere above the yaw bearing) + CALL MeshPositionNode (u%Mesh & + , 1 & + , (/InitInp%r_N_O_G(1)+InputFileData%TMD_P_X, InitInp%r_N_O_G(2)+InputFileData%TMD_P_Y, InitInp%r_N_O_G(3)+InputFileData%TMD_P_Z/) & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL MeshCommit ( u%Mesh & + , ErrStat2 & + , ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + CALL MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + !bjj: removed for now; output handled in ServoDyn + !IF (NumOuts > 0) THEN + ! ALLOCATE( y%WriteOutput(NumOuts), STAT = ErrStat ) + ! IF ( ErrStat/= 0 ) THEN + ! CALL SetErrStat(ErrID_Fatal,'Error allocating output array.',ErrStat,ErrMsg,'TMD_Init') + ! CALL Cleanup() + ! RETURN + ! END IF + ! y%WriteOutput = 0 + ! + ! ! Define initialization-routine output here: + ! ALLOCATE( InitOut%WriteOutputHdr(NumOuts), InitOut%WriteOutputUnt(NumOuts), STAT = ErrStat ) + ! IF ( ErrStat/= 0 ) THEN + ! CALL SetErrStat(ErrID_Fatal,'Error allocating output header and units arrays.',ErrStat,ErrMsg,'TMD_Init') + ! CALL Cleanup() + ! RETURN + ! END IF + ! + ! DO i=1,NumOuts + ! InitOut%WriteOutputHdr(i) = "Heading"//trim(num2lstr(i)) + ! InitOut%WriteOutputUnt(i) = "(-)" + ! END DO + ! + !END IF + + !bjj: need to initialize headers/units + + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + !Interval = p%DT + + call cleanup() + +!................................ +CONTAINS + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'TMD_Init:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + call cleanup() + END IF + + END IF + + + END SUBROUTINE CheckError +!......................................... + SUBROUTINE cleanup() + + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + + CALL TMD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2) + + END SUBROUTINE cleanup +!......................................... +END SUBROUTINE TMD_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE TMD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(TMD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(TMD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(TMD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(TMD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(TMD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(TMD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(TMD_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Place any last minute operations or calculations here: + + + + ! Write the TMD-level output file data if the user requested module-level output + ! and the current time has advanced since the last stored time step. + + + + ! Close files here: + + + ! Destroy the input data: + + CALL TMD_DestroyInput( u, ErrStat, ErrMsg ) + + + ! Destroy the parameter data: + + CALL TMD_DestroyParam( p, ErrStat, ErrMsg ) + + + ! Destroy the state data: + + CALL TMD_DestroyContState( x, ErrStat, ErrMsg ) + CALL TMD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL TMD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL TMD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + + CALL TMD_DestroyMisc( m, ErrStat, ErrMsg ) + + ! Destroy the output data: + + CALL TMD_DestroyOutput( y, ErrStat, ErrMsg ) + +END SUBROUTINE TMD_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving constraint states, integrating continuous states, and updating discrete states. +!! Continuous, constraint, and discrete states are updated to values at t + Interval. +SUBROUTINE TMD_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(TMD_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(TMD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(TMD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(TMD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(TMD_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(TMD_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 + + ! Local variables + !INTEGER :: I ! Generic loop counter + !TYPE(TMD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t + !TYPE(TMD_DiscreteStateType) :: xd_t ! Discrete states at t (copy) + !TYPE(TMD_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z) + !TYPE(TMD_InputType) :: u ! Instantaneous inputs + !INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (secondary error) + !CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + !INTEGER :: nTime ! number of inputs + + + CALL TMD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + +END SUBROUTINE TMD_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." Sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE TMD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(TMD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t (out only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(TMD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(TMD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(TMD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(TMD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t + TYPE(TMD_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 + + ! local variables + + TYPE(TMD_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(TMD_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(TMD_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(TMD_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(TMD_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(TMD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(TMD_InputType) :: u_interp ! interpolated value of inputs + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message (ErrMsg) + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + CALL TMD_CopyContState( x, k1, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL TMD_CopyContState( x, k2, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL TMD_CopyContState( x, k3, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL TMD_CopyContState( x, k4, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + CALL TMD_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + CALL TMD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! interpolate u to find u_interp = u(t) + CALL TMD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + CALL TMD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k1%tmd_x = p%dt * xdot%tmd_x + + x_tmp%tmd_x = x%tmd_x + 0.5 * k1%tmd_x + + ! interpolate u to find u_interp = u(t + dt/2) + CALL TMD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt/2 + CALL TMD_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k2%tmd_x = p%dt * xdot%tmd_x + + x_tmp%tmd_x = x%tmd_x + 0.5 * k2%tmd_x + + ! find xdot at t + dt/2 + CALL TMD_CalcContStateDeriv( t + 0.5*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k3%tmd_x = p%dt * xdot%tmd_x + + x_tmp%tmd_x = x%tmd_x + k3%tmd_x + + ! interpolate u to find u_interp = u(t + dt) + CALL TMD_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, ErrStat2, ErrMsg2) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! find xdot at t + dt + CALL TMD_CalcContStateDeriv( t + p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + k4%tmd_x = p%dt * xdot%tmd_x + + x%tmd_x = x%tmd_x + ( k1%tmd_x + 2. * k2%tmd_x + 2. * k3%tmd_x + k4%tmd_x ) / 6. + ! x%tmd_dxdt = x%tmd_dxdt + ( k1%tmd_dxdt + 2. * k2%tmd_dxdt + 2. * k3%tmd_dxdt + k4%tmd_dxdt ) / 6. + + ! clean up local variables: + CALL ExitThisRoutine( ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE ExitThisRoutine() + ! This subroutine destroys all the local variables + !............................................................................................................................... + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL TMD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL TMD_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + + CALL TMD_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + + END SUBROUTINE ExitThisRoutine + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + ! local variables + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'TMD_RK4:'//TRIM(Msg) + ErrStat = MAX(ErrStat,ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + + IF ( ErrStat >= AbortErrLev ) CALL ExitThisRoutine( ) + + + END IF + + END SUBROUTINE CheckError + +END SUBROUTINE TMD_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE TMD_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(TMD_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(TMD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(TMD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(TMD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(TMD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(TMD_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(TMD_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 + + ! local variables + REAL(ReKi), dimension(3) :: a_G_O + REAL(ReKi), dimension(3) :: a_G_N + REAL(ReKi), dimension(3) :: F_P_N + REAL(ReKi), dimension(3) :: M_P_N + !nacelle movement in local coordinates + Real(ReKi), dimension(3) :: r_ddot_P_N + Real(ReKi), dimension(3) :: omega_N_O_N + Real(ReKi), dimension(3) :: alpha_N_O_N + !dependent accelerations + Real(ReKi) :: F_x_tmdY_P_N + Real(ReKi) :: F_z_tmdY_P_N + Real(ReKi) :: F_y_tmdX_P_N + Real(ReKi) :: F_z_tmdX_P_N + + Real(ReKi) :: F_x_tmdXY_P_N + Real(ReKi) :: F_z_tmdXY_P_N + Real(ReKi) :: F_y_tmdXY_P_N + + TYPE(TMD_ContinuousStateType) :: dxdt ! first time derivative of continuous states + + + ErrStat = ErrID_None + ErrMsg = "" + ! gravity vector in global coordinates + a_G_O (1) = 0 + a_G_O (2) = 0 + a_G_O (3) = -p%Gravity + + ! Compute nacelle and gravitational acceleration in nacelle coordinates + a_G_N = matmul(u%Mesh%Orientation(:,:,1),a_G_O) + r_ddot_P_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%TranslationAcc(:,1)) + omega_N_O_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%RotationVel(:,1)) + alpha_N_O_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%RotationAcc(:,1)) + + ! calculate the derivative, only to get updated values of m, which are used in the equations below + CALL TMD_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) + + IF (p%TMD_DOF_MODE == ControlMode_None .OR. p%TMD_DOF_MODE == DOFMode_Indept) THEN + + ! tmd external forces of dependent degrees: + F_x_tmdY_P_N = - p%M_Y * (a_G_N(1) - r_ddot_P_N(1) + (alpha_N_O_N(3) - omega_N_O_N(1)*omega_N_O_N(2))*x%tmd_x(3) + 2*omega_N_O_N(3)*x%tmd_x(4)) + F_z_tmdY_P_N = - p%M_Y * (a_G_N(3) - r_ddot_P_N(3) - (alpha_N_O_N(1) + omega_N_O_N(2)*omega_N_O_N(3))*x%tmd_x(3) - 2*omega_N_O_N(1)*x%tmd_x(4)) + + F_y_tmdX_P_N = - p%M_X *( a_G_N(2) - r_ddot_P_N(2) - (alpha_N_O_N(3) + omega_N_O_N(1)*omega_N_O_N(2))*x%tmd_x(1) - 2*omega_N_O_N(3)*x%tmd_x(2)) + F_z_tmdX_P_N = - p%M_X * (a_G_N(3) - r_ddot_P_N(3) + (alpha_N_O_N(2) - omega_N_O_N(1)*omega_N_O_N(3))*x%tmd_x(1) + 2*omega_N_O_N(2)*x%tmd_x(2)) + + ! forces in local coordinates + F_P_N(1) = p%K_X * x%tmd_x(1) + m%C_ctrl(1) * x%tmd_x(2) + m%C_Brake(1) * x%tmd_x(2) - m%F_stop(1) - m%F_ext(1) - m%F_fr(1) - F_x_tmdY_P_N + m%F_table(1) + F_P_N(2) = p%K_Y * x%tmd_x(3) + m%C_ctrl(2) * x%tmd_x(4) + m%C_Brake(2) * x%tmd_x(4) - m%F_stop(2) - m%F_ext(2) - m%F_fr(2) - F_y_tmdX_P_N + m%F_table(2) + F_P_N(3) = - F_z_tmdX_P_N - F_z_tmdY_P_N + + ! inertial contributions from mass of TMDs and acceleration of nacelle + ! forces in global coordinates + y%Mesh%Force(:,1) = matmul(transpose(u%Mesh%Orientation(:,:,1)),F_P_N) + + ! Moments on nacelle in local coordinates + M_P_N(1) = - F_z_tmdY_P_N * x%tmd_x(3) + M_P_N(2) = F_z_tmdX_P_N * x%tmd_x(1) + M_P_N(3) = (- F_x_tmdY_P_N) * x%tmd_x(3) + (F_y_tmdX_P_N) * x%tmd_x(1) + + ! moments in global coordinates + y%Mesh%Moment(:,1) = matmul(transpose(u%Mesh%Orientation(:,:,1)),M_P_N) + + ELSE IF (p%TMD_DOF_MODE == DOFMode_Omni) THEN + + !note: m%F_k_x and m%F_k_y are computed earlier in TMD_CalcContStateDeriv + + ! tmd external forces of dependent degrees: + F_x_tmdXY_P_N = 0 + F_y_tmdXY_P_N = 0 + F_z_tmdXY_P_N = - p%M_XY * (a_G_N(3) - r_ddot_P_N(3) - (alpha_N_O_N(1) + omega_N_O_N(2)*omega_N_O_N(3))*x%tmd_x(3) + (alpha_N_O_N(2) - omega_N_O_N(1)*omega_N_O_N(3))*x%tmd_x(1) - 2*omega_N_O_N(1)*x%tmd_x(4) + 2*omega_N_O_N(2)*x%tmd_x(2)) + + ! forces in local coordinates + F_P_N(1) = p%K_X * x%tmd_x(1) + m%C_ctrl(1) * x%tmd_x(2) + m%C_Brake(1) * x%tmd_x(2) - m%F_stop(1) - m%F_ext(1) - m%F_fr(1) - F_x_tmdXY_P_N + m%F_table(1)*(m%F_k_x) + F_P_N(2) = p%K_Y * x%tmd_x(3) + m%C_ctrl(2) * x%tmd_x(4) + m%C_Brake(2) * x%tmd_x(4) - m%F_stop(2) - m%F_ext(2) - m%F_fr(2) - F_y_tmdXY_P_N + m%F_table(2)*(m%F_k_y) + F_P_N(3) = - F_z_tmdXY_P_N + + ! inertial contributions from mass of TMDs and acceleration of nacelle + ! forces in global coordinates + y%Mesh%Force(:,1) = matmul(transpose(u%Mesh%Orientation(:,:,1)),F_P_N) + + ! Moments on nacelle in local coordinates + M_P_N(1) = - F_z_tmdXY_P_N * x%tmd_x(3) + M_P_N(2) = F_z_tmdXY_P_N * x%tmd_x(1) + M_P_N(3) = (- F_x_tmdXY_P_N) * x%tmd_x(3) + (F_y_tmdXY_P_N) * x%tmd_x(1) + + ! moments in global coordinates + y%Mesh%Moment(:,1) = matmul(transpose(u%Mesh%Orientation(:,:,1)),M_P_N) + + END IF + +END SUBROUTINE TMD_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +SUBROUTINE TMD_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(TMD_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(TMD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(TMD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(TMD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(TMD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(TMD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at Time + TYPE(TMD_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 + ! local variables + REAL(ReKi), dimension(3) :: a_G_O + REAL(ReKi), dimension(3) :: a_G_N + REAL(ReKi), dimension(3) :: rddot_N_N + REAL(ReKi), dimension(3) :: omega_P_N ! angular velocity of nacelle transformed to nacelle orientation + Real(ReKi), dimension(3) :: alpha_P_N + + REAL(ReKi) :: B_X + REAL(ReKi) :: B_Y + REAL(ReKi), dimension(2) :: K ! tmd stiffness + Real(ReKi) :: denom ! denominator for omni-direction factors + + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! compute stop force (m%F_stop) + IF (p%Use_F_TBL) THEN + m%F_stop = 0.0_ReKi + ELSE + CALL TMD_CalcStopForce(x,p,m%F_stop) + END IF + + ! Compute stiffness + IF (p%Use_F_TBL) THEN ! use stiffness table + CALL SpringForceExtrapInterp(x,p,m%F_table) + K = 0.0_ReKi + ELSE ! use preset values + K(1) = p%K_X + K(2) = p%K_Y + END IF + + ! gravity vector in global coordinates + a_G_O (1) = 0 + a_G_O (2) = 0 + a_G_O (3) = -p%Gravity + + ! Compute nacelle and gravitational acceleration in nacelle coordinates + a_G_N = matmul(u%Mesh%Orientation(:,:,1),a_G_O) + rddot_N_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%TranslationAcc(:,1)) + omega_P_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%RotationVel(:,1)) + alpha_P_N = matmul(u%Mesh%Orientation(:,:,1),u%Mesh%RotationAcc(:,1)) + + ! NOTE: m%F_stop and m%F_table are calculated earlier + IF (p%TMD_DOF_MODE == ControlMode_None) THEN + ! Compute inputs + B_X = - rddot_N_N(1) + a_G_N(1) + 1 / p%M_X * ( m%F_ext(1) + m%F_stop(1) - m%F_table(1) ) + B_Y = - rddot_N_N(2) + a_G_N(2) + 1 / p%M_Y * ( m%F_ext(2) + m%F_stop(2) - m%F_table(2) ) + ELSE IF (p%TMD_DOF_MODE == DOFMode_Indept) THEN + ! Compute inputs + B_X = - rddot_N_N(1) + a_G_N(1) + 1 / p%M_X * ( m%F_ext(1) + m%F_stop(1) - m%F_table(1) ) + B_Y = - rddot_N_N(2) + a_G_N(2) + 1 / p%M_Y * ( m%F_ext(2) + m%F_stop(2) - m%F_table(2) ) + ELSE IF (p%TMD_DOF_MODE == DOFMode_Omni) THEN + + denom = SQRT(x%tmd_x(1)**2+x%tmd_x(3)**2) + IF ( EqualRealNos( denom, 0.0_ReKi) ) THEN + m%F_k_x = 0.0 + m%F_k_y = 0.0 + ELSE + m%F_k_x = x%tmd_x(1)/denom + m%F_k_y = x%tmd_x(3)/denom + END IF + + B_X = - rddot_N_N(1) + a_G_N(1) + 1 / p%M_XY * ( m%F_ext(1) + m%F_stop(1) - m%F_table(1)*(m%F_k_x) ) + B_Y = - rddot_N_N(2) + a_G_N(2) + 1 / p%M_XY * ( m%F_ext(2) + m%F_stop(2) - m%F_table(2)*(m%F_k_y) ) + END IF + + + ! Compute the first time derivatives, dxdt%tmd_x(1) and dxdt%tmd_x(3), of the continuous states,: + ! Compute elements 1 and 3 of dxdt%tmd_x so that we can compute m%C_ctrl,m%C_Brake, and m%F_fr in TMD_GroundHookDamp if necessary + IF (p%TMD_DOF_MODE == ControlMode_None) THEN + + dxdt%tmd_x = 0.0_ReKi ! Whole array + + ELSE + + IF (p%TMD_DOF_MODE == DOFMode_Indept .AND. .NOT. p%TMD_X_DOF) THEN + dxdt%tmd_x(1) = 0.0_ReKi + ELSE + dxdt%tmd_x(1) = x%tmd_x(2) + END IF + + IF (p%TMD_DOF_MODE == DOFMode_Indept .AND. .NOT. p%TMD_Y_DOF) THEN + dxdt%tmd_x(3) = 0.0_ReKi + ELSE + dxdt%tmd_x(3) = x%tmd_x(4) + END IF + + END IF + + + ! compute damping for dxdt%tmd_x(2) and dxdt%tmd_x(4) + IF (p%TMD_CMODE == ControlMode_None) THEN + m%C_ctrl(1) = p%C_X + m%C_ctrl(2) = p%C_Y + + m%C_Brake = 0.0_ReKi + m%F_fr = 0.0_ReKi + ELSE IF (p%TMD_CMODE == CMODE_Semi) THEN ! ground hook control + CALL TMD_GroundHookDamp(dxdt,x,u,p,m%C_ctrl,m%C_Brake,m%F_fr) + END IF + + + ! Compute the first time derivatives, dxdt%tmd_x(2) and dxdt%tmd_x(4), of the continuous states,: + IF (p%TMD_DOF_MODE == DOFMode_Indept) THEN + + IF (p%TMD_X_DOF) THEN + dxdt%tmd_x(2) = (omega_P_N(2)**2 + omega_P_N(3)**2 - K(1) / p%M_X) * x%tmd_x(1) - ( m%C_ctrl(1)/p%M_X ) * x%tmd_x(2) - ( m%C_Brake(1)/p%M_X ) * x%tmd_x(2) + B_X + m%F_fr(1) / p%M_X + ELSE + dxdt%tmd_x(2) = 0.0_ReKi + END IF + IF (p%TMD_Y_DOF) THEN + dxdt%tmd_x(4) = (omega_P_N(1)**2 + omega_P_N(3)**2 - K(2) / p%M_Y) * x%tmd_x(3) - ( m%C_ctrl(2)/p%M_Y ) * x%tmd_x(4) - ( m%C_Brake(2)/p%M_Y ) * x%tmd_x(4) + B_Y + m%F_fr(2) / p%M_Y + ELSE + dxdt%tmd_x(4) = 0.0_ReKi + END IF + + ELSE IF (p%TMD_DOF_MODE == DOFMode_Omni) THEN + ! Compute the first time derivatives of the continuous states of Omnidirectional TMD mode by sm 2015-0904 + dxdt%tmd_x(2) = (omega_P_N(2)**2 + omega_P_N(3)**2 - K(1) / p%M_XY) * x%tmd_x(1) - ( m%C_ctrl(1)/p%M_XY ) * x%tmd_x(2) - ( m%C_Brake(1)/p%M_XY ) * x%tmd_x(2) + B_X + 1 / p%M_XY * ( m%F_fr(1) ) - ( omega_P_N(1)*omega_P_N(2) - alpha_P_N(3) ) * x%tmd_x(3) + 2 * omega_P_N(3) * x%tmd_x(4) + dxdt%tmd_x(4) = (omega_P_N(1)**2 + omega_P_N(3)**2 - K(2) / p%M_XY) * x%tmd_x(3) - ( m%C_ctrl(2)/p%M_XY ) * x%tmd_x(4) - ( m%C_Brake(2)/p%M_XY ) * x%tmd_x(4) + B_Y + 1 / p%M_XY * ( m%F_fr(2) ) - ( omega_P_N(1)*omega_P_N(2) + alpha_P_N(3) ) * x%tmd_x(1) - 2 * omega_P_N(3) * x%tmd_x(2) + END IF + + +END SUBROUTINE TMD_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE TMD_CalcStopForce(x,p,F_stop) + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(TMD_ParameterType), INTENT(IN ) :: p !< Parameters + Real(ReKi), dimension(2), INTENT(INOUT) :: F_stop !< stop forces +! local variables + Real(ReKi), dimension(2) :: F_SK !stop spring forces + Real(ReKi), dimension(2) :: F_SD !stop damping forces + INTEGER(IntKi) :: i ! counter + INTEGER(IntKi) :: j = 1! counter + j=1 + DO i=1,2 + IF (j < 5) THEN + IF ( x%tmd_x(j) > p%P_SP(i) ) THEN + F_SK(i) = p%K_S(i) *( p%P_SP(i) - x%tmd_x(j) ) + ELSEIF ( x%tmd_x(j) < p%N_SP(i) ) THEN + F_SK(i) = p%K_S(i) * ( p%N_SP(i) - x%tmd_x(j) ) + ELSE + F_SK(i) = 0.0_ReKi + ENDIF + IF ( (x%tmd_x(j) > p%P_SP(i)) .AND. (x%tmd_x(j+1) > 0) ) THEN + F_SD(i) = -p%C_S(i) *( x%tmd_x(j+1) ) + ELSEIF ( (x%tmd_x(j) < p%N_SP(i)) .AND. (x%tmd_x(j+1) < 0) ) THEN + F_SD(i) = -p%C_S(i) *( x%tmd_x(j+1) ) + ELSE + F_SD(i) = 0.0_ReKi + ENDIF + F_stop(i) = F_SK(i) + F_SD(i) + j = j+2 + END IF +END DO +END SUBROUTINE TMD_CalcStopForce +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE TMD_GroundHookDamp(dxdt,x,u,p,C_ctrl,C_Brake,F_fr) + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: dxdt !< Derivative of continuous states at Time (needs elements 1 and 3 only) + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(TMD_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(TMD_ParameterType), INTENT(IN) :: p !< The module's parameter data + REAL(ReKi), dimension(2), INTENT(INOUT) :: C_ctrl !< extrapolated/interpolated stiffness values + REAL(ReKi), dimension(2), INTENT(INOUT) :: C_Brake !< extrapolated/interpolated stiffness values + REAL(ReKi), dimension(2), INTENT(INOUT) :: F_fr !< Friction forces + + IF (p%TMD_CMODE == CMODE_Semi .AND. p%TMD_SA_MODE == SA_CMODE_GH_vel) THEN ! velocity-based ground hook control with high damping for braking + + !X + IF (dxdt%tmd_x(1) * u%Mesh%TranslationVel(1,1) <= 0 ) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ELSE + C_ctrl(1) = p%TMD_X_C_LOW + END IF + + !Brake X + IF ( (x%tmd_x(1) > p%P_SP(1)-0.2) .AND. (x%tmd_x(2) > 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE IF ( (x%tmd_x(1) < p%N_SP(1)+0.2) .AND. (x%tmd_x(2) < 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE + C_Brake(1) = 0 + END IF + + + ! Y + IF (dxdt%tmd_x(3) * u%Mesh%TranslationVel(2,1) <= 0 ) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ELSE + C_ctrl(2) = p%TMD_Y_C_LOW + END IF + + !Brake Y + IF ( (x%tmd_x(3) > p%P_SP(2)-0.2) .AND. (x%tmd_x(4) > 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE IF ( (x%tmd_x(3) < p%N_SP(2)+0.2) .AND. (x%tmd_x(4) < 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE + C_Brake(2) = 0 + END IF + + ELSE IF (p%TMD_CMODE == CMODE_Semi .AND. p%TMD_SA_MODE == SA_CMODE_GH_invVel) THEN ! Inverse velocity-based ground hook control with high damping for braking + + ! X + IF (dxdt%tmd_x(1) * u%Mesh%TranslationVel(1,1) >= 0 ) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ELSE + C_ctrl(1) = p%TMD_X_C_LOW + END IF + + !Brake X + IF ( (x%tmd_x(1) > p%P_SP(1)-0.2) .AND. (x%tmd_x(2) > 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE IF ( (x%tmd_x(1) < p%N_SP(1)+0.2) .AND. (x%tmd_x(2) < 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE + C_Brake(1) = 0 + END IF + + ! Y + IF (dxdt%tmd_x(3) * u%Mesh%TranslationVel(2,1) >= 0 ) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ELSE + C_ctrl(2) = p%TMD_Y_C_LOW + END IF + + !Brake Y + IF ( (x%tmd_x(3) > p%P_SP(2)-0.2) .AND. (x%tmd_x(4) > 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE IF ( (x%tmd_x(3) < p%N_SP(2)+0.2) .AND. (x%tmd_x(4) < 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE + C_Brake(2) = 0 + END IF + + ELSE IF (p%TMD_CMODE == CMODE_Semi .AND. p%TMD_SA_MODE == SA_CMODE_GH_disp) THEN ! displacement-based ground hook control with high damping for braking + + ! X + IF (dxdt%tmd_x(1) * u%Mesh%TranslationDisp(1,1) <= 0 ) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ELSE + C_ctrl(1) = p%TMD_X_C_LOW + END IF + + !Brake X + IF ( (x%tmd_x(1) > p%P_SP(1)-0.2) .AND. (x%tmd_x(2) > 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE IF ( (x%tmd_x(1) < p%N_SP(1)+0.2) .AND. (x%tmd_x(2) < 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE + C_Brake(1) = 0 + END IF + + ! Y + IF (dxdt%tmd_x(3) * u%Mesh%TranslationDisp(2,1) <= 0 ) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ELSE + C_ctrl(2) = p%TMD_Y_C_LOW + END IF + + !Brake Y + IF ( (x%tmd_x(3) > p%P_SP(2)-0.2) .AND. (x%tmd_x(4) > 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE IF ( (x%tmd_x(3) < p%N_SP(2)+0.2) .AND. (x%tmd_x(4) < 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE + C_Brake(2) = 0 + END IF + + ELSE IF (p%TMD_CMODE == CMODE_Semi .AND. p%TMD_SA_MODE == SA_CMODE_Ph_FF) THEN ! Phase Difference Algorithm with Friction Force + ! X + ! (a) + IF (u%Mesh%TranslationDisp(1,1) > 0 .AND. u%Mesh%TranslationVel(1,1) < 0 .AND. x%tmd_x(1) > 0 .AND. dxdt%tmd_x(1) < 0) THEN + F_fr(1) = p%TMD_X_C_HIGH + ! (b) + ELSE IF (u%Mesh%TranslationDisp(1,1) < 0 .AND. u%Mesh%TranslationVel(1,1) > 0 .AND. x%tmd_x(1) < 0 .AND. dxdt%tmd_x(1) > 0) THEN + F_fr(1) = -p%TMD_X_C_HIGH + ! (c) + ELSE IF (u%Mesh%TranslationDisp(1,1) < 0 .AND. u%Mesh%TranslationVel(1,1) < 0 .AND. x%tmd_x(1) > 0 .AND. dxdt%tmd_x(1) > 0) THEN + F_fr(1) = -p%TMD_X_C_HIGH + ELSE IF (u%Mesh%TranslationDisp(1,1) > 0 .AND. u%Mesh%TranslationVel(1,1) > 0 .AND. x%tmd_x(1) < 0 .AND. dxdt%tmd_x(1) < 0) THEN + F_fr(1) = p%TMD_X_C_HIGH + ELSE + F_fr(1) = p%TMD_X_C_LOW + END IF + + !Brake X + IF ( (x%tmd_x(1) > p%P_SP(1)-0.2) .AND. (x%tmd_x(2) > 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE IF ( (x%tmd_x(1) < p%N_SP(1)+0.2) .AND. (x%tmd_x(2) < 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE + C_Brake(1) = 0 + END IF + + ! Y + ! (a) + IF (u%Mesh%TranslationDisp(2,1) > 0 .AND. u%Mesh%TranslationVel(2,1) < 0 .AND. x%tmd_x(3) > 0 .AND. dxdt%tmd_x(3) < 0) THEN + F_fr(2) = p%TMD_Y_C_HIGH + ! (b) + ELSE IF (u%Mesh%TranslationDisp(2,1) < 0 .AND. u%Mesh%TranslationVel(2,1) > 0 .AND. x%tmd_x(3) < 0 .AND. dxdt%tmd_x(3) > 0) THEN + F_fr(2) = -p%TMD_Y_C_HIGH + ! (c) + ELSE IF (u%Mesh%TranslationDisp(2,1) < 0 .AND. u%Mesh%TranslationVel(2,1) < 0 .AND. x%tmd_x(3) > 0 .AND. dxdt%tmd_x(3) > 0) THEN + F_fr(2) = -p%TMD_Y_C_HIGH + ELSE IF (u%Mesh%TranslationDisp(2,1) > 0 .AND. u%Mesh%TranslationVel(2,1) > 0 .AND. x%tmd_x(3) < 0 .AND. dxdt%tmd_x(3) < 0) THEN + F_fr(2) = p%TMD_Y_C_HIGH + ELSE + F_fr(2) = p%TMD_Y_C_LOW + END IF + + !Brake Y + IF ( (x%tmd_x(3) > p%P_SP(2)-0.2) .AND. (x%tmd_x(4) > 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE IF ( (x%tmd_x(3) < p%N_SP(2)+0.2) .AND. (x%tmd_x(4) < 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE + C_Brake(2) = 0 + END IF + + ELSE IF (p%TMD_CMODE == CMODE_Semi .AND. p%TMD_SA_MODE == SA_CMODE_Ph_DF) THEN ! Phase Difference Algorithm with Damping On/Off + ! X + ! (a) + IF (u%Mesh%TranslationDisp(1,1) > 0 .AND. u%Mesh%TranslationVel(1,1) < 0 .AND. x%tmd_x(1) > 0 .AND. dxdt%tmd_x(1) < 0) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ! (b) + ELSE IF (u%Mesh%TranslationDisp(1,1) < 0 .AND. u%Mesh%TranslationVel(1,1) > 0 .AND. x%tmd_x(1) < 0 .AND. dxdt%tmd_x(1) > 0) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ! (c) + ELSE IF (u%Mesh%TranslationDisp(1,1) < 0 .AND. u%Mesh%TranslationVel(1,1) < 0 .AND. x%tmd_x(1) > 0 .AND. dxdt%tmd_x(1) > 0) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ELSE IF (u%Mesh%TranslationDisp(1,1) > 0 .AND. u%Mesh%TranslationVel(1,1) > 0 .AND. x%tmd_x(1) < 0 .AND. dxdt%tmd_x(1) < 0) THEN + C_ctrl(1) = p%TMD_X_C_HIGH + ELSE + C_ctrl(1) = p%TMD_X_C_LOW + END IF + + !Brake X + IF ( (x%tmd_x(1) > p%P_SP(1)-0.2) .AND. (x%tmd_x(2) > 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE IF ( (x%tmd_x(1) < p%N_SP(1)+0.2) .AND. (x%tmd_x(2) < 0) ) THEN + C_Brake(1) = p%TMD_X_C_BRAKE + ELSE + C_Brake(1) = 0 + END IF + + ! Y + ! (a) + IF (u%Mesh%TranslationDisp(2,1) > 0 .AND. u%Mesh%TranslationVel(2,1) < 0 .AND. x%tmd_x(3) > 0 .AND. dxdt%tmd_x(3) < 0) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ! (b) + ELSE IF (u%Mesh%TranslationDisp(2,1) < 0 .AND. u%Mesh%TranslationVel(2,1) > 0 .AND. x%tmd_x(3) < 0 .AND. dxdt%tmd_x(3) > 0) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ! (c) + ELSE IF (u%Mesh%TranslationDisp(2,1) < 0 .AND. u%Mesh%TranslationVel(2,1) < 0 .AND. x%tmd_x(3) > 0 .AND. dxdt%tmd_x(3) > 0) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ELSE IF (u%Mesh%TranslationDisp(2,1) > 0 .AND. u%Mesh%TranslationVel(2,1) > 0 .AND. x%tmd_x(3) < 0 .AND. dxdt%tmd_x(3) < 0) THEN + C_ctrl(2) = p%TMD_Y_C_HIGH + ELSE + C_ctrl(2) = p%TMD_Y_C_LOW + END IF + + !Brake Y + IF ( (x%tmd_x(3) > p%P_SP(2)-0.2) .AND. (x%tmd_x(4) > 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE IF ( (x%tmd_x(3) < p%N_SP(2)+0.2) .AND. (x%tmd_x(4) < 0) ) THEN + C_Brake(2) = p%TMD_Y_C_BRAKE + ELSE + C_Brake(2) = 0 + END IF + +END IF + + +END SUBROUTINE TMD_GroundHookDamp +!---------------------------------------------------------------------------------------------------------------------------------- +!> Extrapolate or interpolate stiffness value based on stiffness table. +SUBROUTINE SpringForceExtrapInterp(x, p, F_table) + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(TMD_ParameterType), INTENT(IN) :: p !< The module's parameter data + REAL(ReKi), dimension(2), INTENT(INOUT) :: F_table !< extrapolated/interpolated stiffness values + + !INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + !CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + INTEGER(IntKi) :: ErrStat2 ! error status + INTEGER(IntKi) :: I ! Loop counter + INTEGER(IntKi), DIMENSION(2) :: J = (/1, 3/) ! Loop counter + INTEGER(IntKi) :: M ! location of closest table position + INTEGER(IntKi) :: Nrows ! Number of rows in F_TBL + REAL(ReKi) :: Slope ! + REAL(ReKi) :: DX ! + REAL(ReKi) :: Disp(2) ! Current displacement + REAL(ReKi), ALLOCATABLE :: TmpRAry(:) + + IF (p%TMD_DOF_MODE == DOFMode_Indept .OR. p%TMD_DOF_MODE == DOFMode_Omni) THEN + Nrows = SIZE(p%F_TBL,1) + ALLOCATE(TmpRAry(Nrows),STAT=ErrStat2) + IF (ErrStat2 /= 0) then + CALL WrScr('Error allocating temp array. TMD stiffness results may be inaccurate.') + RETURN + END IF + + IF (p%TMD_DOF_MODE == DOFMode_Indept) THEN + DO I = 1,2 + Disp(I) = x%tmd_x(J(I)) + END DO + ELSE !IF (p%TMD_DOF_MODE == DOFMode_Omni) THEN + Disp = SQRT(x%tmd_x(1)**2+x%tmd_x(3)**2) ! constant assignment to vector + END IF + + DO I = 1,2 + TmpRAry = p%F_TBL(:,J(I))-Disp(I) + TmpRAry = ABS(TmpRAry) + M = MINLOC(TmpRAry,1) + + !interpolate + IF ( (Disp(I) > p%F_TBL(M,J(I)) .AND. M /= Nrows) .OR. (Disp(I) < p%F_TBL(M,J(I)) .AND. M == 1) ) THEN + ! for displacements higher than the closest table value or lower than the lower bound + Slope = ( p%F_TBL(M+1,J(I)+1) - p%F_TBL(M,J(I)+1) ) / ( p%F_TBL(M+1,J(I)) - p%F_TBL(M,J(I)) ) + + ELSE IF ( (Disp(I) < p%F_TBL(M,J(I)) .AND. M /= 1 ) .OR. (Disp(I) > p%F_TBL(M,J(I)) .AND. M == Nrows) ) THEN ! lower + ! for displacements lower than the closest table value or higher than the upper bound + Slope = ( p%F_TBL(M,J(I)+1) - p%F_TBL(M-1,J(I)+1) ) / ( p%F_TBL(M,J(I)) - p%F_TBL(M-1,J(I)) ) + + ELSE ! equal + Slope = 0 + END IF + + F_table(I) = p%F_TBL(M,J(I)+1) + Slope * ( Disp(I) - p%F_TBL(M,J(I)) ) + + END DO + + DEALLOCATE(TmpRAry) + + END IF + +END SUBROUTINE SpringForceExtrapInterp +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine reads the input file and stores all the data in the TMD_InputFile structure. +!! It does not perform data validation. +SUBROUTINE TMD_ReadInput( InputFileName, InputFileData, Default_DT, OutFileRoot, ErrStat, ErrMsg ) +!.................................................................................................................................. + + ! Passed variables + REAL(DbKi), INTENT(IN) :: Default_DT !< The default DT (from glue code) + + CHARACTER(*), INTENT(IN) :: InputFileName !< Name of the input file + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of all the output files written by this routine. + + TYPE(TMD_InputFile), INTENT(OUT) :: InputFileData !< Data stored in the module's input file + + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = "" + + ! InputFileData%DT = Default_DT ! the glue code's suggested DT for the module (may be overwritten in ReadPrimaryFile()) + + ! get the primary/platform input-file data + + CALL ReadPrimaryFile( InputFileName, InputFileData, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! we may need to read additional files here + + + ! close any echo file that was opened + + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'TMD_ReadInput:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE TMD_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine reads in the primary ServoDyn input file and places the values it reads in the InputFileData structure. +!! It opens and prints to an echo file if requested. +SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, OutFileRoot, UnEc, ErrStat, ErrMsg ) +!.................................................................................................................................. + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(OUT) :: UnEc !< I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status + + CHARACTER(*), INTENT(IN) :: InputFile !< Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + CHARACTER(*), INTENT(IN) :: OutFileRoot !< The rootname of the echo file, possibly opened in this routine + + TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData !< All the data in the TMD input file + + ! Local variables: + REAL(ReKi) :: TmpRAry(4) ! A temporary array to read a table from the input file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + CHARACTER(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + INTEGER(IntKi) :: NKInpSt ! Number of stiffness input stations in user table + INTEGER(IntKi) :: NInputCols ! Number of columns in user-defined stiffness table + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + ! DO + !-------------------------- HEADER --------------------------------------------- + + CALL ReadCom( UnIn, InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadStr( UnIn, InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !------------------ TMD DEGREES OF FREEDOM ----------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: TMD DEGREES OF FREEDOM', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_DOF_MODE: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_DOF_MODE, "TMD_DOF_MODE", "DOF mode {0: NO TMD_DOF; 1: TMD_X_DOF and TMD_Y_DOF; 2: TMD_XY_DOF} ", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_DOF: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_DOF, "TMD_X_DOF", "DOF on or off", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_Y_DOF: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_DOF, "TMD_Y_DOF", "DOF on or off", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !------------------ TMD INITIAL CONDITIONS ----------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: TMD INITIAL CONDITIONS', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_DSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_DSP, "TMD_X_DSP", "TMD_X initial displacement", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_Y_DSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_DSP, "TMD_Y_DSP", "TMD_Y initial displacement", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + !------------------ TMD CONFIGURATION ----------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: TMD CONFIGURATION', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_P_X: + CALL ReadVar(UnIn,InputFile,InputFileData%TMD_P_X,"TMD_P_X","at rest position of TMDs (X)",ErrStat2,ErrMsg2,UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_P_Y: + CALL ReadVar(UnIn,InputFile,InputFileData%TMD_P_Y,"TMD_P_Y","at rest position of TMDs (Y)",ErrStat2,ErrMsg2,UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_P_Z: + CALL ReadVar(UnIn,InputFile,InputFileData%TMD_P_Z,"TMD_P_Z","at rest position of TMDs (Z)",ErrStat2,ErrMsg2,UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_DWSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_DWSP, "TMD_X_DWSP", "DW stop position (maximum X mass displacement)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_UWSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_UWSP, "TMD_X_UWSP", "UW stop position (minimum X mass displacement)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_PLSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_PLSP, "TMD_Y_PLSP", "positive lateral stop position (maximum Y mass displacement)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_NLSP: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_NLSP, "TMD_Y_NLSP", "negative lateral stop position (minimum Y mass displacement)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + !------------------ TMD MASS, STIFFNESS, & DAMPING ----------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: TMD MASS, STIFFNESS, & DAMPING', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_X_M: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_M, "TMD_X_M", "X TMD mass", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_M: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_M, "TMD_Y_M", "Y TMD mass", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_XY_M: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_XY_M, "TMD_XY_M", "XY TMD mass", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_X_K: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_K, "TMD_X_K", "X TMD stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_K: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_K, "TMD_Y_K", "Y TMD stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_X_C: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_C, "TMD_X_C", "X TMD damping", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_C: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_C, "TMD_Y_C", "Y TMD damping", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_X_KS: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_KS, "TMD_X_KS", "X stop spring stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_KS: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_KS, "TMD_Y_KS", "Y stop spring stiffness", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_X_CS: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_CS, "TMD_X_CS", "X stop spring damping", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_Y_CS: + CALL ReadVar(UnIn,InputFile,InputFileData%TMD_Y_CS,"TMD_Y_CS","Y stop spring damping",ErrStat2,ErrMsg2,UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! -------------- TMD USER-DEFINED STIFFNESS --------------------------------- + + ! Skip the comment lines. + + CALL ReadCom ( UnIn, InputFile, 'Section Header: TMD USER-DEFINED SPRING FORCE', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Use_F_TBL + CALL ReadVar( UnIn, InputFile, InputFileData%Use_F_TBL, "Use_F_TBL", "use spring force from user-defined table (flag)", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! NKInpSt + CALL ReadVar( UnIn, InputFile, NKInpSt, "NKInpSt", "number of spring force input stations", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadCom ( UnIn, InputFile, 'Section Header: TMD SPRING FORCE TABLE', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadCom ( UnIn, InputFile, 'spring force table column names', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL ReadCom ( UnIn, InputFile, 'spring force table column units', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Read the table. + + NInputCols = 4 + + ! allocate data for F_TBL + ALLOCATE (InputFileData%F_TBL(NKInpSt,NInputCols)) + + DO I=1,NKInpSt + + CALL ReadAry( UnIn, InputFile, TmpRAry, NInputCols, 'Line'//TRIM(Num2LStr(I)), 'TMD Spring force Properties', & + ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + InputFileData%F_TBL(I,1) = TmpRAry(1) ! X + InputFileData%F_TBL(I,2) = TmpRAry(2) ! K_X + InputFileData%F_TBL(I,3) = TmpRAry(3) ! Y + InputFileData%F_TBL(I,4) = TmpRAry(4) ! K_Y + + + ENDDO ! I + !------------------ TMD CONTROL ----------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: TMD CONTROL', ErrStat2, ErrMsg2, UnEc ) + CALL CheckError( ErrStat2, ErrMsg2 ) + + ! TMD_CMODE: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_CMODE, "TMD_CMODE", "control mode {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode;} ", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_SA_MODE: + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_SA_MODE, "TMD_SA_MODE", "Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} ", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_C_HIGH + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_C_HIGH, "TMD_X_C_HIGH", "TMD X high damping for ground hook control", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_C_LOW + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_C_LOW, "TMD_X_C_LOW", "TMD X low damping for ground hook control", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_Y_C_HIGH + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_C_HIGH, "TMD_Y_C_HIGH", "TMD Y high damping for ground hook control", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_Y_C_HIGH + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_C_LOW, "TMD_Y_C_LOW", "TMD Y high damping for ground hook control", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_X_C_BRAKE + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_X_C_BRAKE, "TMD_X_C_BRAKE", "TMD X high damping for braking the TMDX", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! TMD_Y_C_BRAKE + CALL ReadVar( UnIn, InputFile, InputFileData%TMD_Y_C_BRAKE, "TMD_Y_C_BRAKE", "TMD Y high damping for braking the TMDY", ErrStat2, ErrMsg2, UnEc) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + !!---------------------- OUTPUT -------------------------------------------------- + !CALL ReadCom( UnIn, InputFile, 'Section Header: Output', ErrStat2, ErrMsg2, UnEc ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + ! ! SumPrint - Print summary data to <RootName>.sum (flag): + !CALL ReadVar( UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Print summary data to <RootName>.sum (flag)", ErrStat2, ErrMsg2, UnEc) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + !!---------------------- OUTLIST -------------------------------------------- + ! CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + ! OutList - List of user-requested output channels (-): + !CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + !---------------------- END OF FILE ----------------------------------------- + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ReadPrimaryFile +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine sets the parameters, based on the data stored in InputFileData. +SUBROUTINE TMD_SetParameters( InputFileData, p, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(TMD_InputFile), INTENT(IN) :: InputFileData !< Data stored in the module's input file + TYPE(TMD_ParameterType), INTENT(INOUT) :: p !< The module's parameter data + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred + + ! Local variables + INTEGER(IntKi) :: ErrStat2 ! Temporary error ID + !CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary message describing error + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_SetParameters' + + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = '' + + + !p%DT = InputFileData%DT + !p%RootName = 'TMD' + ! DOFs + + + p%TMD_DOF_MODE = InputFileData%TMD_DOF_MODE + p%TMD_X_DOF = InputFileData%TMD_X_DOF + p%TMD_Y_DOF = InputFileData%TMD_Y_DOF + + ! TMD X parameters + p%X_DSP = InputFileData%TMD_X_DSP + p%M_X = InputFileData%TMD_X_M + p%K_X = InputFileData%TMD_X_K + p%C_X = InputFileData%TMD_X_C + + ! TMD Y parameters + p%Y_DSP = InputFileData%TMD_Y_DSP + p%M_Y = InputFileData%TMD_Y_M + p%K_Y = InputFileData%TMD_Y_K + p%C_Y = InputFileData%TMD_Y_C + + p%M_XY = InputFileData%TMD_XY_M + + ! vector parameters + ! stop positions + p%P_SP(1) = InputFileData%TMD_X_DWSP + p%P_SP(2) = InputFileData%TMD_Y_PLSP + p%N_SP(1) = InputFileData%TMD_X_UWSP + p%N_SP(2) = InputFileData%TMD_Y_NLSP + ! stop force stiffness + p%K_S(1) = InputFileData%TMD_X_KS + p%K_S(2) = InputFileData%TMD_Y_KS + ! stop force damping + p%C_S(1) = InputFileData%TMD_X_CS + p%C_S(2) = InputFileData%TMD_Y_CS + + ! ground hook control damping files + p%TMD_CMODE = InputFileData%TMD_CMODE + p%TMD_SA_MODE = InputFileData%TMD_SA_MODE + p%TMD_X_C_HIGH = InputFileData%TMD_X_C_HIGH + p%TMD_X_C_LOW = InputFileData%TMD_X_C_LOW + p%TMD_Y_C_HIGH = InputFileData%TMD_Y_C_HIGH + p%TMD_Y_C_LOW = InputFileData%TMD_Y_C_LOW + p%TMD_X_C_BRAKE = InputFileData%TMD_X_C_BRAKE + p%TMD_Y_C_BRAKE = InputFileData%TMD_Y_C_BRAKE + + ! User Defined Stiffness Table + p%Use_F_TBL = InputFileData%Use_F_TBL + ALLOCATE (p%F_TBL(SIZE(InputFiledata%F_TBL,1),SIZE(InputFiledata%F_TBL,2)), STAT=ErrStat2) + IF (ErrStat2/=0) THEN + CALL SetErrStat(ErrID_Fatal,"Error allocating p%F_TBL.",ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + p%F_TBL = InputFileData%F_TBL; + +END SUBROUTINE TMD_SetParameters +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE TMD +!********************************************************************************************************************************** \ No newline at end of file diff --git a/OpenFAST/modules/servodyn/src/TMD_Driver.f90 b/OpenFAST/modules/servodyn/src/TMD_Driver.f90 new file mode 100644 index 000000000..179a729d4 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/TMD_Driver.f90 @@ -0,0 +1,908 @@ +!********************************************************************************************************************************* +! TMD_Driver: This code tests the template modules +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2014 William La Cava & Matt Lackner, UMass Amherst +! Copyright (C) 2012 National Renewable Energy Laboratory +! +! This file is part of TMD. +! +! 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 read_file_module +! this module reads in external nacelle data for testing the module. + USE NWTC_Library + USE TMD_Types + implicit none +contains + + SUBROUTINE U_ReadInput(APvec,AVvec,AAvec,LAvec, NumSteps, ErrStat, ErrMsg ) +! This subroutine reads the input file and stores all the data in the input vectors. +! It does not perform data validation. +!.................................................................................................................................. + + ! Passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps ! Number of steps + + Real(ReKi), dimension(9, NumSteps), intent(inout) :: APvec + Real(ReKi), dimension(3,NumSteps), intent(inout):: AVvec + Real(ReKi), dimension(3,NumSteps), intent(inout):: AAvec + Real(ReKi), dimension(3,NumSteps), intent(inout):: LAvec + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! The error status code + CHARACTER(*), INTENT(OUT) :: ErrMsg ! The error message, if an error occurred + + ! local variables + + INTEGER(IntKi) :: UnEcho ! Unit number for the echo file + INTEGER(IntKi) :: ErrStat2 ! The error status code + CHARACTER(LEN(ErrMsg)) :: ErrMsg2 ! The error message, if an error occurred + CHARACTER(1024) :: AV_file = 'AngVel_NO_Input_Data.inp' + CHARACTER(1024) :: AA_file = 'AngAccel_NO_Input_Data.inp' + CHARACTER(1024) :: AP_file = 'AngPos_NO_Input_Data.inp' + CHARACTER(1024) :: RA_file = 'rddot_NO_Input_Data.inp' + + ! initialize values: + + ErrStat = ErrID_None + ErrMsg = "" + + + ! get the primary/platform input-file data + !DO i = 1,NumSteps + CALL ReadAngPosFile(AP_file, APvec, NumSteps,UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL ReadAngVelFile( AV_file, AVvec,NumSteps,UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL ReadAngAccelFile( AA_file, AAvec,NumSteps, UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + CALL ReadAccelFile( RA_file, LAvec,NumSteps, UnEcho, ErrStat2, ErrMsg2 ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + ! END DO + ! we may need to read additional files here (e.g., Bladed Interface) + + + ! close any echo file that was opened + + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'TMD_ReadInput:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + IF ( UnEcho > 0 ) CLOSE( UnEcho ) + END IF + + END IF + + + END SUBROUTINE CheckError + +END SUBROUTINE U_ReadInput +!---------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE ReadAngPosFile( InputFile, APvec, NumSteps, UnEc, ErrStat, ErrMsg ) +! This routine reads in the nacelle angular position. +! It opens and prints to an echo file if requested. +!.................................................................................................................................. + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps ! The default DT (from glue code) + INTEGER(IntKi), INTENT(OUT) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + + CHARACTER(*), INTENT(IN) :: InputFile ! Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + !TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData ! All the data in the TMD input file + Real(ReKi), dimension(9, NumSteps), intent(inout) :: APvec + ! Local variables: + REAL(ReKi) :: TmpRAry9(9) ! Temporary variable to read table from file + INTEGER :: I ! loop counter + INTEGER :: J ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(LEN(ErrMsg)) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + ! + DO I=1,NumSteps + CALL ReadAry( UnIn, InputFile, TmpRAry9, 9, 'AngPos_NO', 'Nacelle Rotation Matrix', ErrStat2, ErrMsg2, UnEc ) + + DO J = 1,9 + APvec(J,I) = TmpRAry9(J) + END DO + END DO + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... + END SUBROUTINE ReadAngPosFile + SUBROUTINE ReadAngVelFile( InputFile, AVvec, NumSteps, UnEc, ErrStat, ErrMsg ) +! This routine reads in the nacelle angular velocity. +! It opens and prints to an echo file if requested. +!.................................................................................................................................. + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps ! The default DT (from glue code) + INTEGER(IntKi), INTENT(OUT) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + + CHARACTER(*), INTENT(IN) :: InputFile ! Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + !TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData ! All the data in the TMD input file + Real(ReKi), dimension(3,NumSteps), intent(inout) :: AVvec + ! Local variables: + REAL(ReKi) :: TmpRAry3(3) ! Temporary variable to read table from file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: J ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(LEN(ErrMsg)) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + ! + DO I=1,NumSteps + CALL ReadAry( UnIn, InputFile, TmpRAry3, 3, 'AngVel_NO', 'Nacelle Angular Velocity', ErrStat2, ErrMsg2, UnEc ) + DO J = 1,3 + AVvec(J,I) = TmpRAry3(J) + END DO + END DO + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... + END SUBROUTINE ReadAngVelFile + SUBROUTINE ReadAngAccelFile( InputFile, AAvec, NumSteps, UnEc, ErrStat, ErrMsg ) +! This routine reads in the nacelle angular acceleration. +! It opens and prints to an echo file if requested. +!.................................................................................................................................. + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps ! The default DT (from glue code) + INTEGER(IntKi), INTENT(OUT) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + + CHARACTER(*), INTENT(IN) :: InputFile ! Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + !TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData ! All the data in the TMD input file + Real(ReKi), dimension(3,NumSteps), intent(inout) :: AAvec + ! Local variables: + REAL(ReKi) :: TmpRAry3(3) ! Temporary variable to read table from file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: J ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(LEN(ErrMsg)) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + ! + DO I = 1,NumSteps + CALL ReadAry( UnIn, InputFile, TmpRAry3, 3, 'AngAccel_NO', 'Nacelle Angular Acceleration', ErrStat2, ErrMsg2, UnEc ) + DO J = 1,3 + AAvec(J,I) = TmpRAry3(J) + END DO + END DO + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ReadAngAccelFile + SUBROUTINE ReadAccelFile( InputFile, LAvec, NumSteps, UnEc, ErrStat, ErrMsg ) +! This routine reads in the nacelle translational acceleration. +! It opens and prints to an echo file if requested. +!.................................................................................................................................. + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps ! The default DT (from glue code) + INTEGER(IntKi), INTENT(OUT) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status + + CHARACTER(*), INTENT(IN) :: InputFile ! Name of the file containing the primary input data + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + !TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData ! All the data in the TMD input file + Real(ReKi), dimension(3,NumSteps), intent(inout) :: LAvec + ! Local variables: + REAL(ReKi) :: TmpRAry3(3) ! Temporary variable to read table from file + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: J ! loop counter + INTEGER(IntKi) :: UnIn ! Unit number for reading file + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(LEN(ErrMsg)) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !CALL AllocAry( InputFileData%OutList, MaxOutPts, "ServoDyn Input File's Outlist", ErrStat2, ErrMsg2 ) + ! CALL CheckError( ErrStat2, ErrMsg2 ) + ! IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Get an available unit number for the file. + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the Primary input file. + + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL CheckError( ErrStat2, ErrMsg2 ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + ! I = 1 !set the number of times we've read the file + ! + DO I=1,NumSteps + CALL ReadAry( UnIn, InputFile, TmpRAry3, 3, 'rddot_NO', 'Nacelle Linear Acceleration', ErrStat2, ErrMsg2, UnEc ) + + DO J = 1,3 + LAvec(J,I) = TmpRAry3(J) + END DO + END DO + + CLOSE ( UnIn ) + RETURN + + +CONTAINS + !............................................................................................................................... + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF (ErrStat /= ErrID_None) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//'ReadPrimaryFile:'//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close file, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE( UnIn ) +! IF ( UnEc > 0 ) CLOSE ( UnEc ) + END IF + + END IF + + + END SUBROUTINE CheckError + !............................................................................................................................... +END SUBROUTINE ReadAccelFile + + +!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE TMD_OpenOutputFile(OutputFile,UnIn,ErrStat,ErrMsg) +! This routine is called by the driver, not this module. + CHARACTER(1024), Intent(IN) :: OutputFile ! Name of the file containing the primary input data + INTEGER(IntKi), INTENT(OUT) :: UnIn ! Unit number for writing file + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Temporary error ID + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Temporary message describing error + CHARACTER(1024) :: Header1 + CHARACTER(1024) :: Header2 + + ErrStat = ErrID_None + ErrMsg = '' + !OutputFile = 'TMD_Output_Data.txt' + !Fmt = "F10.2))/" + + CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) + !CALL CheckError( ErrStat, ErrMsg) + !IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Open the output file. + + CALL OpenFOutFile ( UnIn, OutputFile, ErrStat, ErrMsg ) + Header1 = "-------------- TMD Output ------------------------------" + Header2 = "x dxdt y dydt fx fy fz mx my mz" + + WRITE( UnIn, *, IOSTAT=ErrStat ) TRIM(Header1) + WRITE( UnIn, *, IOSTAT=ErrStat ) TRIM(Header2) + +END SUBROUTINE TMD_OpenOutputFile +!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE TMD_CloseOutputFile(Un) +! This routine is called by the driver, not this module. + + INTEGER(IntKi), INTENT(IN) :: Un ! Unit number for writing file + CLOSE ( Un ) +END SUBROUTINE TMD_CloseOutputFile +!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE TMD_WriteOutputFile( x, y, UnIn, ErrStat, ErrMsg ) +! This routine is called by the driver, not this module. +! write output file with TMD states and forces. + + TYPE(TMD_ContinuousStateType), INTENT(IN ) :: x ! Continuous states at Time + TYPE(TMD_OutputType), INTENT(IN ) :: y ! state outputs + INTEGER(IntKi), INTENT(IN) :: UnIn ! Unit number for writing file + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Temporary error ID + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Temporary message describing error + !REAL(DbKi), INTENT(IN ) :: Time ! Current simulation time in seconds + + CHARACTER(1024) :: Fmt !text format + REAL(ReKi), dimension(10) :: OutAry + INTEGER(IntKi) :: i + ErrStat = ErrID_None + ErrMsg = '' + + ! create output array + DO i=1,4 + OutAry(i) = x%tmd_x(i) + END DO + DO i=5,7 + OutAry(i) = y%Mesh%Force(i-4,1) + END DO + DO i=8,10 + OutAry(i) = y%Mesh%Moment(i-7,1) + END DO + !Write output + Fmt = '(10(1x,F10.2))' + WRITE( UnIn, Fmt, IOSTAT=ErrStat ) OutAry(:) + IF (ErrStat /= 0) THEN + CALL WrScr('Error '//TRIM(Num2LStr(ErrStat))//' writing matrix in WrMatrix1R4().') + RETURN + END IF + !CALL WrMatrix( x%tmd_x, UnIn, Fmt ) + +END SUBROUTINE TMD_WriteOutputFile +!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +end module read_file_module + +PROGRAM TestTemplate + + USE NWTC_Library + USE TMD + USE TMD_Types + USE read_file_module + + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 2 ! Number of inputs sent to TMD_UpdateStates + INTEGER(IntKi), PARAMETER :: NumSteps = 100 ! Number of time steps + ! Program variables + REAL(DbKi) :: Time ! Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) ! Variable for storing time associated with inputs, in seconds + + TYPE(TMD_InitInputType) :: InitInData ! Input data for initialization + TYPE(TMD_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(TMD_ContinuousStateType) :: x ! Continuous states + TYPE(TMD_DiscreteStateType) :: xd ! Discrete states + TYPE(TMD_ConstraintStateType) :: z ! Constraint states + TYPE(TMD_ConstraintStateType) :: Z_residual ! Residual of the constraint state functions (Z) + TYPE(TMD_OtherStateType) :: OtherState ! Other states + TYPE(TMD_MiscVarType) :: m ! misc variables + + TYPE(TMD_ParameterType) :: p ! Parameters + TYPE(TMD_InputType) :: u(NumInp) ! System inputs + TYPE(TMD_OutputType) :: y ! System outputs + + TYPE(TMD_ContinuousStateType) :: dxdt ! First time derivatives of the continuous states + integer(IntKi) :: UnOut !output data file number + + + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: i ! Loop counter (for time step) + INTEGER(IntKi) :: j ! Loop counter (for time step) + INTEGER(IntKi) :: count ! Loop counter (for time step) + INTEGER(IntKi) :: ErrStat ! Status of error message + CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi), ALLOCATABLE :: Re_SaveAry (:) ! Array to store reals in packed data structure + REAL(DbKi), ALLOCATABLE :: Db_SaveAry (:) ! Array to store doubles in packed data structure + INTEGER(IntKi), ALLOCATABLE :: Int_SaveAry (:) ! Array to store integers in packed data structure + Real(ReKi), dimension(9,NumSteps) :: APvec + Real(ReKi), dimension(3,NumSteps) :: AVvec + Real(ReKi), dimension(3,NumSteps) :: AAvec + Real(ReKi), dimension(3,NumSteps) :: LAvec + CHARACTER(1024) :: OutputName !text file output +!............................................................................................................................... +! Routines called in initialization +!............................................................................................................................... + ! Populate the InitInData data structure here: + ! input file with TMD settings + InitInData%InputFile = 'TMD_Input_test.dat' + ! gravity + InitInData%Gravity = 9.80665 + ! nacelle origin + InitInData%r_N_O_G(1) = 0 + InitInData%r_N_O_G(2) = 0 + InitInData%r_N_O_G(3) = 0 + + ! Set the driver's request for time interval here: + + TimeInterval = 0.25 ! Glue code's request for delta time (likely based on information from other modules) + + ! Initialize the module + + CALL TMD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + IF (ErrStat >= AbortErrLev) CALL ProgAbort( ErrMsg ) + CALL WrScr( ErrMsg ) + END IF + CALL TMD_CopyInput( u(1), u(2), MESH_NEWCOPY, ErrStat, ErrMsg ) + + ! read in nacelle data from file + CALL U_ReadInput(APvec,AVvec,AAvec,LAvec, NumSteps, ErrStat, ErrMsg ) + + ! Destroy initialization data + CALL TMD_DestroyInitInput( InitInData, ErrStat, ErrMsg ) + CALL TMD_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !.................................................................................................... + ! setup the output file: + OutputName = 'TMD_Output_Data.txt' + CALL TMD_OpenOutputFile(OutputName,UnOut,ErrStat,ErrMsg) + + ! run simulation + +DO n = 0,NumSteps-1 + count=1 + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + IF (n>0) THEN + CALL TMD_CopyInput( u(2), u(1), MESH_UPDATECOPY, ErrStat, ErrMsg ) + ! u(1) = u(2) ! save past input as first element in input vector + END IF + i=1 + j=1 + ! setup input mesh with data from nacelle positions: + do i = 1,3 + do j=1,3 + u(2)%Mesh%Orientation(i,j,1) = APvec(count,n+1) + count = count+1 + end do + u(2)%Mesh%RotationVel(i,1) = AVvec(i,n+1) + u(2)%Mesh%RotationAcc(i,1) = AAvec(i,n+1) + u(2)%Mesh%TranslationAcc(i,1) = LAvec(i,n+1) + end do + if (n==0) then + InputTime(1) = 0 + InputTime(2) = TimeInterval + else + InputTime(1) = Time + Time = n*TimeInterval + InputTime(2) = Time + end if + + + ! Calculate outputs at n + CALL TMD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + CALL TMD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + ! write outputs to file + CALL TMD_WriteOutputFile(x, y, UnOut,ErrStat,ErrMsg) +END DO +! close the output file +CALL TMD_CloseOutputFile(UnOut) + !............................................................................................................................... + ! Routines called in tight coupling -- time marching only + !............................................................................................................................... + !DO n = 0,10 + ! Time = n * TimeInterval ! Note that the discrete states must be updated only at the TimeInterval defined in initialization + ! ! set inputs (u) here: + ! ! u = + ! ! Update constraint states at Time + ! ! DO + ! !CALL TMD_CalcConstrStateResidual( Time, u(1), p, x, xd, z, OtherState, Z_residual, ErrStat, ErrMsg ) + ! ! + ! !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! ! CALL WrScr( ErrMsg ) + ! !END IF + ! ! z = + ! ! END DO + ! ! Calculate the outputs at Time + ! CALL TMD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, ErrStat, ErrMsg ) + ! + ! IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! CALL WrScr( ErrMsg ) + ! END IF + ! ! Calculate the continuous state derivatives at Time + ! CALL TMD_CalcContStateDeriv( Time, u(1), p, x, xd, z, OtherState, dxdt, ErrStat, ErrMsg ) + ! + ! IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! CALL WrScr( ErrMsg ) + ! END IF + ! ! Update the discrete state from step n to step n+1 + ! ! Note that the discrete states must be updated only at the TimeInterval defined in initialization + ! !CALL TMD_UpdateDiscState( Time, n, u(1), p, x, xd, z, OtherState, ErrStat, ErrMsg ) + ! ! + ! !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! ! CALL WrScr( ErrMsg ) + ! !END IF + ! ! Driver should integrate (update) continuous states here: + ! !x = function of dxdt, x + ! ! Jacobians required: + ! !CALL TMD_JacobianPInput( Time, u(1), p, x, xd, z, OtherState, dYdu=dYdu, dZdu=dZdu, ErrStat=ErrStat, ErrMsg=ErrMsg ) + ! ! + ! !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! ! CALL WrScr( ErrMsg ) + ! !END IF + ! ! + ! !CALL TMD_JacobianPConstrState( Time, u(1), p, x, xd, z, OtherState, dYdz=dYdz, dZdz=dZdz, & + ! !ErrStat=ErrStat, ErrMsg=ErrMsg ) + ! ! + ! !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! ! CALL WrScr( ErrMsg ) + ! !END IF + !END DO + ! Destroy Z_residual and dxdt because they are not necessary anymore + CALL TMD_DestroyConstrState( Z_residual, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + CALL TMD_DestroyContState( dxdt, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + !............................................................................................................................... + ! Jacobian routines called in tight coupling + !............................................................................................................................... + !CALL TMD_JacobianPInput( Time, u(1), p, x, xd, z, OtherState, dYdu, dXdu, dXddu, dZdu, ErrStat, ErrMsg ) + ! + !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + !END IF + ! + !CALL TMD_JacobianPContState( Time, u(1), p, x, xd, z, OtherState, dYdx, dXdx, dXddx, dZdx, ErrStat, ErrMsg ) + ! + !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! CALL WrScr( ErrMsg ) + !END IF + ! + !CALL TMD_JacobianPDiscState( Time, u(1), p, x, xd, z, OtherState, dYdxd, dXdxd, dXddxd, dZdxd, ErrStat, ErrMsg ) + ! + !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! CALL WrScr( ErrMsg ) + !END IF + ! + !CALL TMD_JacobianPConstrState( Time, u(1), p, x, xd, z, OtherState, dYdz, dXdz, dXddz, dZdz, ErrStat, ErrMsg ) + ! + !IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + ! CALL WrScr( ErrMsg ) + !END IF + !............................................................................................................................... + ! Routines to pack data (to restart later) + !............................................................................................................................... + !CALL TMD_Pack(Re_SaveAry, Db_SaveAry, Int_SaveAry, u(1), p, x, xd, z, OtherState, y, ErrStat, ErrMsg) + + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL TMD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + !............................................................................................................................... + ! Routines to retreive packed data (unpack for restart) + !............................................................................................................................... + !CALL TMD_Unpack( Re_SaveAry, Db_SaveAry, Int_SaveAry, u(1), p, x, xd, z, OtherState, y, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + !............................................................................................................................... + ! Routines to copy data (not already tested) + !............................................................................................................................... + !............................................................................................................................... + ! Routines to destroy data (not already tested) + !............................................................................................................................... + IF ( ALLOCATED( Re_SaveAry ) ) DEALLOCATE( Re_SaveAry ) + IF ( ALLOCATED( Db_SaveAry ) ) DEALLOCATE( Db_SaveAry ) + IF ( ALLOCATED( Int_SaveAry ) ) DEALLOCATE( Int_SaveAry ) + ! CALL TMD_DestroyPartialOutputPInput ( ) ! Jacobian Routine not yet implemented + !............................................................................................................................... + ! Routine to terminate program execution (again) + !............................................................................................................................... + CALL TMD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + +END PROGRAM TestTemplate \ No newline at end of file diff --git a/OpenFAST/modules/servodyn/src/TMD_Registry.txt b/OpenFAST/modules/servodyn/src/TMD_Registry.txt new file mode 100644 index 000000000..c2d74036c --- /dev/null +++ b/OpenFAST/modules/servodyn/src/TMD_Registry.txt @@ -0,0 +1,122 @@ +################################################################################################################################### +# Registry for TMD in the FAST Modularization Framework +# This Registry file is used to create MODULE TMD_Types, which contains all of the user-defined types needed in TMD. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# Entries are of the form +# keyword <TMD/TMD> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value from the previous line. +################################################################################################################################### + +# ..... Input File data ....................................................................................................... +typedef TMD/TMD TMD_InputFile CHARACTER(1024) TMDFileName - - - "Name of the input file; remove if there is no file" - +typedef ^ ^ INTEGER TMD_CMODE - - - "control mode {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode;} " - +typedef ^ ^ INTEGER TMD_SA_MODE - - - "Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} " - +typedef ^ ^ INTEGER TMD_DOF_MODE - - - "DOF mode {0: NO TMD_DOF; 1: TMD_X_DOF and TMD_Y_DOF; 2: TMD_XY_DOF} " - +typedef ^ ^ LOGICAL TMD_X_DOF - - - "DOF on or off" - +typedef ^ ^ LOGICAL TMD_Y_DOF - - - "DOF on or off" - +typedef ^ ^ ReKi TMD_X_DSP - - - "TMD_X initial displacement" m +typedef ^ ^ ReKi TMD_Y_DSP - - - "TMD_Y initial displacement" m +typedef ^ ^ ReKi TMD_X_M - - - "TMD mass" kg +typedef ^ ^ ReKi TMD_Y_M - - - "TMD mass" kg +typedef ^ ^ ReKi TMD_XY_M - - - "TMDXY mass" kg +typedef ^ ^ ReKi TMD_X_K - - - "TMD stiffness" "N/m" +typedef ^ ^ ReKi TMD_Y_K - - - "TMD stiffness" "N/m" +typedef ^ ^ ReKi TMD_X_C - - - "TMD damping" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C - - - "TMD damping" "N/(m/s)" +typedef ^ ^ ReKi TMD_X_DWSP - - - "DW stop position (maximum X mass displacement)" m +typedef ^ ^ ReKi TMD_X_UWSP - - - "UW stop position (minimum X mass displacement)" m +typedef ^ ^ ReKi TMD_X_KS - - - "stop spring stiffness" "N/m" +typedef ^ ^ ReKi TMD_X_CS - - - "stop spring damping" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_PLSP - - - "positive lateral stop position (maximum Y mass displacement)" m +typedef ^ ^ ReKi TMD_Y_NLSP - - - "negative lateral stop position (minimum Y mass displacement)" m +typedef ^ ^ ReKi TMD_Y_KS - - - "stop spring stiffness" "N/m" +typedef ^ ^ ReKi TMD_Y_CS - - - "stop spring damping" "N/(m/s)" +typedef ^ ^ ReKi TMD_P_X - - - "rest position of TMDs w.r.t. nacelle" m +typedef ^ ^ ReKi TMD_P_Y - - - "rest position of TMDs w.r.t. nacelle" m +typedef ^ ^ ReKi TMD_P_Z - - - "rest position of TMDs w.r.t. nacelle" m +typedef ^ ^ ReKi TMD_X_C_HIGH - - - "TMD X high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_X_C_LOW - - - "TMD X low damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_HIGH - - - "TMD Y high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_LOW - - - "TMD Y high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_X_C_BRAKE - - - "TMD X high damping for braking the TMD" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_BRAKE - - - "TMD X high damping for braking the TMD" "N/(m/s)" +typedef ^ ^ LOGICAL USE_F_TBL - - - "use spring force from user-defined table (flag)" - +typedef ^ ^ CHARACTER(1024) TMD_F_TBL_FILE - - - "user-defined spring table filename" - +typedef ^ ^ ReKi F_TBL {:}{:} - - "user-defined spring force" "N" +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef TMD/TMD InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ InitInputType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ ReKi Gravity - - - "Gravitational acceleration" m/s^2 +typedef ^ ^ ReKi r_N_O_G {3} - - "nacelle origin for setting up mesh" - +# Define outputs from the initialization routine here: +typedef ^ InitOutputType SiKi DummyInitOut - - - "dummy init output" - +#typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +#typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:}- - "Units of the output-to-file channels" - + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - +typedef ^ ContinuousStateType ReKi tmd_x {4} - - "Continuous States" - +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# Define any other states (e.g. logical states): +typedef ^ OtherStateType Reki DummyOtherState - - - "Remove this variable if you have other/logical states" - + +# Define any misc data used only for efficiency purposes (indices for searching in an array, copies of previous calculations of output +# at a given time, etc.) or other data that do not depend on time +typedef ^ MiscVarType Reki F_stop {2} - - "Stop forces" - +typedef ^ MiscVarType ReKi F_ext {2} - - "External forces (user defined)" - +typedef ^ MiscVarType ReKi F_fr {2} - - "Friction forces" - +typedef ^ MiscVarType ReKi C_ctrl {2} - - "Controlled Damping (On/Off)" - +typedef ^ MiscVarType ReKi C_Brake {2} - - "Braking Damping" - +typedef ^ MiscVarType ReKi F_table {2} - - "Tabled Stiffness" - +typedef ^ MiscVarType ReKi F_k_x - - - "Factor for x-component stiffness force" - +typedef ^ MiscVarType ReKi F_k_y - - - "Factor for y-component stiffness force" - + + +# ..... 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 DbKi DT - - - "Time step for cont. state integration & disc. state update" seconds +typedef ^ ^ CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ^ INTEGER TMD_DOF_MODE - - - "DOF mode {0: NO TMD_DOF; 1: TMD_X_DOF and TMD_Y_DOF; 2: TMD_XY_DOF} " - +typedef ^ ^ LOGICAL TMD_X_DOF - - - "DOF on or off" - +typedef ^ ^ LOGICAL TMD_Y_DOF - - - "DOF on or off" - +typedef ^ ^ ReKi X_DSP - - - "TMD_X initial displacement" m +typedef ^ ^ ReKi Y_DSP - - - "TMD_Y initial displacement" m +typedef ^ ^ ReKi M_X - - - "TMD mass" kg +typedef ^ ^ ReKi M_Y - - - "TMD mass" kg +typedef ^ ^ ReKi M_XY - - - "TMDXY mass" kg +typedef ^ ^ ReKi K_X - - - "TMD stiffness" "N/m" +typedef ^ ^ ReKi K_Y - - - "TMD stiffness" "N/m" +typedef ^ ^ ReKi C_X - - - "TMD damping" "N/(m/s)" +typedef ^ ^ ReKi C_Y - - - "TMD damping" "N/(m/s)" +typedef ^ ^ ReKi K_S {2} - - "TMD stop stiffness" "N/m" +typedef ^ ^ ReKi C_S {2} - - "TMD stop damping" "N/(m/s)" +typedef ^ ^ ReKi P_SP {2} - - "Positive stop position (maximum mass displacement)" m +typedef ^ ^ ReKi N_SP {2} - - "Negative stop position (minimum X mass displacement)" m +typedef ^ ^ ReKi F_ext {3} - - "External forces (for user modification)" - +typedef ^ ^ ReKi Gravity - - - "Gravitational acceleration" "m/s^2" +typedef ^ ^ INTEGER TMD_CMODE - - - "control mode {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode;} " - +typedef ^ ^ INTEGER TMD_SA_MODE - - - "Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} " - +typedef ^ ^ ReKi TMD_X_C_HIGH - - - "TMD X high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_X_C_LOW - - - "TMD X low damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_HIGH - - - "TMD Y high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_LOW - - - "TMD Y high damping for ground hook control" "N/(m/s)" +typedef ^ ^ ReKi TMD_X_C_BRAKE - - - "TMD X high damping for braking the TMD" "N/(m/s)" +typedef ^ ^ ReKi TMD_Y_C_BRAKE - - - "TMD X high damping for braking the TMD" "N/(m/s)" +typedef ^ ^ LOGICAL Use_F_TBL - - - "use spring force from user-defined table (flag)" - +typedef ^ ^ ReKi F_TBL {:}{:} - - "user-defined spring force" "N" +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +typedef ^ InputType MeshType Mesh - - - "Displacements at the TMD reference point P in the inertial frame" - +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType Mesh - - - "Loads at the TMD reference point in the inertial frame" - +# Define outputs that are not on this mesh here: +#typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file: see WriteOutputHdr for names of each variable" "see WriteOutputUnt" diff --git a/OpenFAST/modules/servodyn/src/TMD_Types.f90 b/OpenFAST/modules/servodyn/src/TMD_Types.f90 new file mode 100644 index 000000000..c0ba34ab4 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/TMD_Types.f90 @@ -0,0 +1,2692 @@ +!STARTOFREGISTRYGENERATEDFILE 'TMD_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 +!********************************************************************************************************************************* +! TMD_Types +!................................................................................................................................. +! This file is part of TMD. +! +! 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 TMD. 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 TMD_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= TMD_InputFile ======= + TYPE, PUBLIC :: TMD_InputFile + CHARACTER(1024) :: TMDFileName !< Name of the input file; remove if there is no file [-] + INTEGER(IntKi) :: TMD_CMODE !< control mode {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode;} [-] + INTEGER(IntKi) :: TMD_SA_MODE !< Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} [-] + INTEGER(IntKi) :: TMD_DOF_MODE !< DOF mode {0: NO TMD_DOF; 1: TMD_X_DOF and TMD_Y_DOF; 2: TMD_XY_DOF} [-] + LOGICAL :: TMD_X_DOF !< DOF on or off [-] + LOGICAL :: TMD_Y_DOF !< DOF on or off [-] + REAL(ReKi) :: TMD_X_DSP !< TMD_X initial displacement [m] + REAL(ReKi) :: TMD_Y_DSP !< TMD_Y initial displacement [m] + REAL(ReKi) :: TMD_X_M !< TMD mass [kg] + REAL(ReKi) :: TMD_Y_M !< TMD mass [kg] + REAL(ReKi) :: TMD_XY_M !< TMDXY mass [kg] + REAL(ReKi) :: TMD_X_K !< TMD stiffness [N/m] + REAL(ReKi) :: TMD_Y_K !< TMD stiffness [N/m] + REAL(ReKi) :: TMD_X_C !< TMD damping [N/(m/s)] + REAL(ReKi) :: TMD_Y_C !< TMD damping [N/(m/s)] + REAL(ReKi) :: TMD_X_DWSP !< DW stop position (maximum X mass displacement) [m] + REAL(ReKi) :: TMD_X_UWSP !< UW stop position (minimum X mass displacement) [m] + REAL(ReKi) :: TMD_X_KS !< stop spring stiffness [N/m] + REAL(ReKi) :: TMD_X_CS !< stop spring damping [N/(m/s)] + REAL(ReKi) :: TMD_Y_PLSP !< positive lateral stop position (maximum Y mass displacement) [m] + REAL(ReKi) :: TMD_Y_NLSP !< negative lateral stop position (minimum Y mass displacement) [m] + REAL(ReKi) :: TMD_Y_KS !< stop spring stiffness [N/m] + REAL(ReKi) :: TMD_Y_CS !< stop spring damping [N/(m/s)] + REAL(ReKi) :: TMD_P_X !< rest position of TMDs w.r.t. nacelle [m] + REAL(ReKi) :: TMD_P_Y !< rest position of TMDs w.r.t. nacelle [m] + REAL(ReKi) :: TMD_P_Z !< rest position of TMDs w.r.t. nacelle [m] + REAL(ReKi) :: TMD_X_C_HIGH !< TMD X high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_X_C_LOW !< TMD X low damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_HIGH !< TMD Y high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_LOW !< TMD Y high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_X_C_BRAKE !< TMD X high damping for braking the TMD [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_BRAKE !< TMD X high damping for braking the TMD [N/(m/s)] + LOGICAL :: USE_F_TBL !< use spring force from user-defined table (flag) [-] + CHARACTER(1024) :: TMD_F_TBL_FILE !< user-defined spring table filename [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_TBL !< user-defined spring force [N] + END TYPE TMD_InputFile +! ======================= +! ========= TMD_InitInputType ======= + TYPE, PUBLIC :: TMD_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + REAL(ReKi) , DIMENSION(1:3) :: r_N_O_G !< nacelle origin for setting up mesh [-] + END TYPE TMD_InitInputType +! ======================= +! ========= TMD_InitOutputType ======= + TYPE, PUBLIC :: TMD_InitOutputType + REAL(SiKi) :: DummyInitOut !< dummy init output [-] + END TYPE TMD_InitOutputType +! ======================= +! ========= TMD_ContinuousStateType ======= + TYPE, PUBLIC :: TMD_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + REAL(ReKi) , DIMENSION(1:4) :: tmd_x !< Continuous States [-] + END TYPE TMD_ContinuousStateType +! ======================= +! ========= TMD_DiscreteStateType ======= + TYPE, PUBLIC :: TMD_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE TMD_DiscreteStateType +! ======================= +! ========= TMD_ConstraintStateType ======= + TYPE, PUBLIC :: TMD_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE TMD_ConstraintStateType +! ======================= +! ========= TMD_OtherStateType ======= + TYPE, PUBLIC :: TMD_OtherStateType + REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other/logical states [-] + END TYPE TMD_OtherStateType +! ======================= +! ========= TMD_MiscVarType ======= + TYPE, PUBLIC :: TMD_MiscVarType + REAL(ReKi) , DIMENSION(1:2) :: F_stop !< Stop forces [-] + REAL(ReKi) , DIMENSION(1:2) :: F_ext !< External forces (user defined) [-] + REAL(ReKi) , DIMENSION(1:2) :: F_fr !< Friction forces [-] + REAL(ReKi) , DIMENSION(1:2) :: C_ctrl !< Controlled Damping (On/Off) [-] + REAL(ReKi) , DIMENSION(1:2) :: C_Brake !< Braking Damping [-] + REAL(ReKi) , DIMENSION(1:2) :: F_table !< Tabled Stiffness [-] + REAL(ReKi) :: F_k_x !< Factor for x-component stiffness force [-] + REAL(ReKi) :: F_k_y !< Factor for y-component stiffness force [-] + END TYPE TMD_MiscVarType +! ======================= +! ========= TMD_ParameterType ======= + TYPE, PUBLIC :: TMD_ParameterType + REAL(DbKi) :: DT !< Time step for cont. state integration & disc. state update [seconds] + CHARACTER(1024) :: RootName !< RootName for writing output files [-] + INTEGER(IntKi) :: TMD_DOF_MODE !< DOF mode {0: NO TMD_DOF; 1: TMD_X_DOF and TMD_Y_DOF; 2: TMD_XY_DOF} [-] + LOGICAL :: TMD_X_DOF !< DOF on or off [-] + LOGICAL :: TMD_Y_DOF !< DOF on or off [-] + REAL(ReKi) :: X_DSP !< TMD_X initial displacement [m] + REAL(ReKi) :: Y_DSP !< TMD_Y initial displacement [m] + REAL(ReKi) :: M_X !< TMD mass [kg] + REAL(ReKi) :: M_Y !< TMD mass [kg] + REAL(ReKi) :: M_XY !< TMDXY mass [kg] + REAL(ReKi) :: K_X !< TMD stiffness [N/m] + REAL(ReKi) :: K_Y !< TMD stiffness [N/m] + REAL(ReKi) :: C_X !< TMD damping [N/(m/s)] + REAL(ReKi) :: C_Y !< TMD damping [N/(m/s)] + REAL(ReKi) , DIMENSION(1:2) :: K_S !< TMD stop stiffness [N/m] + REAL(ReKi) , DIMENSION(1:2) :: C_S !< TMD stop damping [N/(m/s)] + REAL(ReKi) , DIMENSION(1:2) :: P_SP !< Positive stop position (maximum mass displacement) [m] + REAL(ReKi) , DIMENSION(1:2) :: N_SP !< Negative stop position (minimum X mass displacement) [m] + REAL(ReKi) , DIMENSION(1:3) :: F_ext !< External forces (for user modification) [-] + REAL(ReKi) :: Gravity !< Gravitational acceleration [m/s^2] + INTEGER(IntKi) :: TMD_CMODE !< control mode {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode;} [-] + INTEGER(IntKi) :: TMD_SA_MODE !< Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} [-] + REAL(ReKi) :: TMD_X_C_HIGH !< TMD X high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_X_C_LOW !< TMD X low damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_HIGH !< TMD Y high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_LOW !< TMD Y high damping for ground hook control [N/(m/s)] + REAL(ReKi) :: TMD_X_C_BRAKE !< TMD X high damping for braking the TMD [N/(m/s)] + REAL(ReKi) :: TMD_Y_C_BRAKE !< TMD X high damping for braking the TMD [N/(m/s)] + LOGICAL :: Use_F_TBL !< use spring force from user-defined table (flag) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_TBL !< user-defined spring force [N] + END TYPE TMD_ParameterType +! ======================= +! ========= TMD_InputType ======= + TYPE, PUBLIC :: TMD_InputType + TYPE(MeshType) :: Mesh !< Displacements at the TMD reference point P in the inertial frame [-] + END TYPE TMD_InputType +! ======================= +! ========= TMD_OutputType ======= + TYPE, PUBLIC :: TMD_OutputType + TYPE(MeshType) :: Mesh !< Loads at the TMD reference point in the inertial frame [-] + END TYPE TMD_OutputType +! ======================= +CONTAINS + SUBROUTINE TMD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_InputFile), INTENT(IN) :: SrcInputFileData + TYPE(TMD_InputFile), INTENT(INOUT) :: DstInputFileData + 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 = 'TMD_CopyInputFile' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputFileData%TMDFileName = SrcInputFileData%TMDFileName + DstInputFileData%TMD_CMODE = SrcInputFileData%TMD_CMODE + DstInputFileData%TMD_SA_MODE = SrcInputFileData%TMD_SA_MODE + DstInputFileData%TMD_DOF_MODE = SrcInputFileData%TMD_DOF_MODE + DstInputFileData%TMD_X_DOF = SrcInputFileData%TMD_X_DOF + DstInputFileData%TMD_Y_DOF = SrcInputFileData%TMD_Y_DOF + DstInputFileData%TMD_X_DSP = SrcInputFileData%TMD_X_DSP + DstInputFileData%TMD_Y_DSP = SrcInputFileData%TMD_Y_DSP + DstInputFileData%TMD_X_M = SrcInputFileData%TMD_X_M + DstInputFileData%TMD_Y_M = SrcInputFileData%TMD_Y_M + DstInputFileData%TMD_XY_M = SrcInputFileData%TMD_XY_M + DstInputFileData%TMD_X_K = SrcInputFileData%TMD_X_K + DstInputFileData%TMD_Y_K = SrcInputFileData%TMD_Y_K + DstInputFileData%TMD_X_C = SrcInputFileData%TMD_X_C + DstInputFileData%TMD_Y_C = SrcInputFileData%TMD_Y_C + DstInputFileData%TMD_X_DWSP = SrcInputFileData%TMD_X_DWSP + DstInputFileData%TMD_X_UWSP = SrcInputFileData%TMD_X_UWSP + DstInputFileData%TMD_X_KS = SrcInputFileData%TMD_X_KS + DstInputFileData%TMD_X_CS = SrcInputFileData%TMD_X_CS + DstInputFileData%TMD_Y_PLSP = SrcInputFileData%TMD_Y_PLSP + DstInputFileData%TMD_Y_NLSP = SrcInputFileData%TMD_Y_NLSP + DstInputFileData%TMD_Y_KS = SrcInputFileData%TMD_Y_KS + DstInputFileData%TMD_Y_CS = SrcInputFileData%TMD_Y_CS + DstInputFileData%TMD_P_X = SrcInputFileData%TMD_P_X + DstInputFileData%TMD_P_Y = SrcInputFileData%TMD_P_Y + DstInputFileData%TMD_P_Z = SrcInputFileData%TMD_P_Z + DstInputFileData%TMD_X_C_HIGH = SrcInputFileData%TMD_X_C_HIGH + DstInputFileData%TMD_X_C_LOW = SrcInputFileData%TMD_X_C_LOW + DstInputFileData%TMD_Y_C_HIGH = SrcInputFileData%TMD_Y_C_HIGH + DstInputFileData%TMD_Y_C_LOW = SrcInputFileData%TMD_Y_C_LOW + DstInputFileData%TMD_X_C_BRAKE = SrcInputFileData%TMD_X_C_BRAKE + DstInputFileData%TMD_Y_C_BRAKE = SrcInputFileData%TMD_Y_C_BRAKE + DstInputFileData%USE_F_TBL = SrcInputFileData%USE_F_TBL + DstInputFileData%TMD_F_TBL_FILE = SrcInputFileData%TMD_F_TBL_FILE +IF (ALLOCATED(SrcInputFileData%F_TBL)) THEN + i1_l = LBOUND(SrcInputFileData%F_TBL,1) + i1_u = UBOUND(SrcInputFileData%F_TBL,1) + i2_l = LBOUND(SrcInputFileData%F_TBL,2) + i2_u = UBOUND(SrcInputFileData%F_TBL,2) + IF (.NOT. ALLOCATED(DstInputFileData%F_TBL)) THEN + ALLOCATE(DstInputFileData%F_TBL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%F_TBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%F_TBL = SrcInputFileData%F_TBL +ENDIF + END SUBROUTINE TMD_CopyInputFile + + SUBROUTINE TMD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) + TYPE(TMD_InputFile), INTENT(INOUT) :: InputFileData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyInputFile' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InputFileData%F_TBL)) THEN + DEALLOCATE(InputFileData%F_TBL) +ENDIF + END SUBROUTINE TMD_DestroyInputFile + + SUBROUTINE TMD_PackInputFile( 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(TMD_InputFile), 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 = 'TMD_PackInputFile' + ! 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%TMDFileName) ! TMDFileName + Int_BufSz = Int_BufSz + 1 ! TMD_CMODE + Int_BufSz = Int_BufSz + 1 ! TMD_SA_MODE + Int_BufSz = Int_BufSz + 1 ! TMD_DOF_MODE + Int_BufSz = Int_BufSz + 1 ! TMD_X_DOF + Int_BufSz = Int_BufSz + 1 ! TMD_Y_DOF + Re_BufSz = Re_BufSz + 1 ! TMD_X_DSP + Re_BufSz = Re_BufSz + 1 ! TMD_Y_DSP + Re_BufSz = Re_BufSz + 1 ! TMD_X_M + Re_BufSz = Re_BufSz + 1 ! TMD_Y_M + Re_BufSz = Re_BufSz + 1 ! TMD_XY_M + Re_BufSz = Re_BufSz + 1 ! TMD_X_K + Re_BufSz = Re_BufSz + 1 ! TMD_Y_K + Re_BufSz = Re_BufSz + 1 ! TMD_X_C + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C + Re_BufSz = Re_BufSz + 1 ! TMD_X_DWSP + Re_BufSz = Re_BufSz + 1 ! TMD_X_UWSP + Re_BufSz = Re_BufSz + 1 ! TMD_X_KS + Re_BufSz = Re_BufSz + 1 ! TMD_X_CS + Re_BufSz = Re_BufSz + 1 ! TMD_Y_PLSP + Re_BufSz = Re_BufSz + 1 ! TMD_Y_NLSP + Re_BufSz = Re_BufSz + 1 ! TMD_Y_KS + Re_BufSz = Re_BufSz + 1 ! TMD_Y_CS + Re_BufSz = Re_BufSz + 1 ! TMD_P_X + Re_BufSz = Re_BufSz + 1 ! TMD_P_Y + Re_BufSz = Re_BufSz + 1 ! TMD_P_Z + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_HIGH + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_LOW + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_HIGH + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_LOW + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_BRAKE + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_BRAKE + Int_BufSz = Int_BufSz + 1 ! USE_F_TBL + Int_BufSz = Int_BufSz + 1*LEN(InData%TMD_F_TBL_FILE) ! TMD_F_TBL_FILE + Int_BufSz = Int_BufSz + 1 ! F_TBL allocated yes/no + IF ( ALLOCATED(InData%F_TBL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_TBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_TBL) ! F_TBL + 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%TMDFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%TMDFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%TMD_CMODE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TMD_SA_MODE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TMD_DOF_MODE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TMD_X_DOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TMD_Y_DOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_DSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_DSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_M + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_M + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_XY_M + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_K + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_K + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_DWSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_UWSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_KS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_CS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_PLSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_NLSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_KS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_CS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_P_X + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_P_Y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_P_Z + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_HIGH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_LOW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_HIGH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_LOW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_BRAKE + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_BRAKE + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%USE_F_TBL, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%TMD_F_TBL_FILE) + IntKiBuf(Int_Xferred) = ICHAR(InData%TMD_F_TBL_FILE(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%F_TBL) ) 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%F_TBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_TBL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_TBL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_TBL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_TBL,2), UBOUND(InData%F_TBL,2) + DO i1 = LBOUND(InData%F_TBL,1), UBOUND(InData%F_TBL,1) + ReKiBuf(Re_Xferred) = InData%F_TBL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE TMD_PackInputFile + + SUBROUTINE TMD_UnPackInputFile( 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(TMD_InputFile), 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 = 'TMD_UnPackInputFile' + ! 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%TMDFileName) + OutData%TMDFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%TMD_CMODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_SA_MODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_DOF_MODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_X_DOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TMD_X_DOF) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_Y_DOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TMD_Y_DOF) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_X_DSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_DSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_M = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_M = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_XY_M = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_K = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_K = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_DWSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_UWSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_KS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_CS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_PLSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_NLSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_KS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_CS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_P_X = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_P_Y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_P_Z = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C_HIGH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C_LOW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_HIGH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_LOW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C_BRAKE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_BRAKE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%USE_F_TBL = TRANSFER(IntKiBuf(Int_Xferred), OutData%USE_F_TBL) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%TMD_F_TBL_FILE) + OutData%TMD_F_TBL_FILE(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_TBL 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%F_TBL)) DEALLOCATE(OutData%F_TBL) + ALLOCATE(OutData%F_TBL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_TBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_TBL,2), UBOUND(OutData%F_TBL,2) + DO i1 = LBOUND(OutData%F_TBL,1), UBOUND(OutData%F_TBL,1) + OutData%F_TBL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE TMD_UnPackInputFile + + SUBROUTINE TMD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(TMD_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 = 'TMD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%r_N_O_G = SrcInitInputData%r_N_O_G + END SUBROUTINE TMD_CopyInitInput + + SUBROUTINE TMD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(TMD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyInitInput + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + SIZE(InData%r_N_O_G) ! r_N_O_G + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%r_N_O_G,1), UBOUND(InData%r_N_O_G,1) + ReKiBuf(Re_Xferred) = InData%r_N_O_G(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE TMD_PackInitInput + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%r_N_O_G,1) + i1_u = UBOUND(OutData%r_N_O_G,1) + DO i1 = LBOUND(OutData%r_N_O_G,1), UBOUND(OutData%r_N_O_G,1) + OutData%r_N_O_G(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE TMD_UnPackInitInput + + SUBROUTINE TMD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(TMD_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 = 'TMD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitOutputData%DummyInitOut = SrcInitOutputData%DummyInitOut + END SUBROUTINE TMD_CopyInitOutput + + SUBROUTINE TMD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(TMD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyInitOutput + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + Re_BufSz = Re_BufSz + 1 ! DummyInitOut + 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%DummyInitOut + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE TMD_PackInitOutput + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + OutData%DummyInitOut = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE TMD_UnPackInitOutput + + SUBROUTINE TMD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + DstContStateData%tmd_x = SrcContStateData%tmd_x + END SUBROUTINE TMD_CopyContState + + SUBROUTINE TMD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(TMD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyContState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + Re_BufSz = Re_BufSz + SIZE(InData%tmd_x) ! tmd_x + 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 + DO i1 = LBOUND(InData%tmd_x,1), UBOUND(InData%tmd_x,1) + ReKiBuf(Re_Xferred) = InData%tmd_x(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE TMD_PackContState + + SUBROUTINE TMD_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(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_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 + i1_l = LBOUND(OutData%tmd_x,1) + i1_u = UBOUND(OutData%tmd_x,1) + DO i1 = LBOUND(OutData%tmd_x,1), UBOUND(OutData%tmd_x,1) + OutData%tmd_x(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE TMD_UnPackContState + + SUBROUTINE TMD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(TMD_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 = 'TMD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE TMD_CopyDiscState + + SUBROUTINE TMD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(TMD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyDiscState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_PackDiscState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_UnPackDiscState + + SUBROUTINE TMD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(TMD_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 = 'TMD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE TMD_CopyConstrState + + SUBROUTINE TMD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(TMD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyConstrState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_PackConstrState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_UnPackConstrState + + SUBROUTINE TMD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(TMD_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 = 'TMD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE TMD_CopyOtherState + + SUBROUTINE TMD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(TMD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyOtherState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_PackOtherState + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 TMD_UnPackOtherState + + SUBROUTINE TMD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%F_stop = SrcMiscData%F_stop + DstMiscData%F_ext = SrcMiscData%F_ext + DstMiscData%F_fr = SrcMiscData%F_fr + DstMiscData%C_ctrl = SrcMiscData%C_ctrl + DstMiscData%C_Brake = SrcMiscData%C_Brake + DstMiscData%F_table = SrcMiscData%F_table + DstMiscData%F_k_x = SrcMiscData%F_k_x + DstMiscData%F_k_y = SrcMiscData%F_k_y + END SUBROUTINE TMD_CopyMisc + + SUBROUTINE TMD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(TMD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE TMD_DestroyMisc + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + SIZE(InData%F_stop) ! F_stop + Re_BufSz = Re_BufSz + SIZE(InData%F_ext) ! F_ext + Re_BufSz = Re_BufSz + SIZE(InData%F_fr) ! F_fr + Re_BufSz = Re_BufSz + SIZE(InData%C_ctrl) ! C_ctrl + Re_BufSz = Re_BufSz + SIZE(InData%C_Brake) ! C_Brake + Re_BufSz = Re_BufSz + SIZE(InData%F_table) ! F_table + Re_BufSz = Re_BufSz + 1 ! F_k_x + Re_BufSz = Re_BufSz + 1 ! F_k_y + 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%F_stop,1), UBOUND(InData%F_stop,1) + ReKiBuf(Re_Xferred) = InData%F_stop(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_ext,1), UBOUND(InData%F_ext,1) + ReKiBuf(Re_Xferred) = InData%F_ext(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_fr,1), UBOUND(InData%F_fr,1) + ReKiBuf(Re_Xferred) = InData%F_fr(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%C_ctrl,1), UBOUND(InData%C_ctrl,1) + ReKiBuf(Re_Xferred) = InData%C_ctrl(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%C_Brake,1), UBOUND(InData%C_Brake,1) + ReKiBuf(Re_Xferred) = InData%C_Brake(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_table,1), UBOUND(InData%F_table,1) + ReKiBuf(Re_Xferred) = InData%F_table(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%F_k_x + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%F_k_y + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE TMD_PackMisc + + SUBROUTINE TMD_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(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_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 + i1_l = LBOUND(OutData%F_stop,1) + i1_u = UBOUND(OutData%F_stop,1) + DO i1 = LBOUND(OutData%F_stop,1), UBOUND(OutData%F_stop,1) + OutData%F_stop(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_ext,1) + i1_u = UBOUND(OutData%F_ext,1) + DO i1 = LBOUND(OutData%F_ext,1), UBOUND(OutData%F_ext,1) + OutData%F_ext(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_fr,1) + i1_u = UBOUND(OutData%F_fr,1) + DO i1 = LBOUND(OutData%F_fr,1), UBOUND(OutData%F_fr,1) + OutData%F_fr(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%C_ctrl,1) + i1_u = UBOUND(OutData%C_ctrl,1) + DO i1 = LBOUND(OutData%C_ctrl,1), UBOUND(OutData%C_ctrl,1) + OutData%C_ctrl(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%C_Brake,1) + i1_u = UBOUND(OutData%C_Brake,1) + DO i1 = LBOUND(OutData%C_Brake,1), UBOUND(OutData%C_Brake,1) + OutData%C_Brake(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_table,1) + i1_u = UBOUND(OutData%F_table,1) + DO i1 = LBOUND(OutData%F_table,1), UBOUND(OutData%F_table,1) + OutData%F_table(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%F_k_x = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%F_k_y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE TMD_UnPackMisc + + SUBROUTINE TMD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + DstParamData%RootName = SrcParamData%RootName + DstParamData%TMD_DOF_MODE = SrcParamData%TMD_DOF_MODE + DstParamData%TMD_X_DOF = SrcParamData%TMD_X_DOF + DstParamData%TMD_Y_DOF = SrcParamData%TMD_Y_DOF + DstParamData%X_DSP = SrcParamData%X_DSP + DstParamData%Y_DSP = SrcParamData%Y_DSP + DstParamData%M_X = SrcParamData%M_X + DstParamData%M_Y = SrcParamData%M_Y + DstParamData%M_XY = SrcParamData%M_XY + DstParamData%K_X = SrcParamData%K_X + DstParamData%K_Y = SrcParamData%K_Y + DstParamData%C_X = SrcParamData%C_X + DstParamData%C_Y = SrcParamData%C_Y + DstParamData%K_S = SrcParamData%K_S + DstParamData%C_S = SrcParamData%C_S + DstParamData%P_SP = SrcParamData%P_SP + DstParamData%N_SP = SrcParamData%N_SP + DstParamData%F_ext = SrcParamData%F_ext + DstParamData%Gravity = SrcParamData%Gravity + DstParamData%TMD_CMODE = SrcParamData%TMD_CMODE + DstParamData%TMD_SA_MODE = SrcParamData%TMD_SA_MODE + DstParamData%TMD_X_C_HIGH = SrcParamData%TMD_X_C_HIGH + DstParamData%TMD_X_C_LOW = SrcParamData%TMD_X_C_LOW + DstParamData%TMD_Y_C_HIGH = SrcParamData%TMD_Y_C_HIGH + DstParamData%TMD_Y_C_LOW = SrcParamData%TMD_Y_C_LOW + DstParamData%TMD_X_C_BRAKE = SrcParamData%TMD_X_C_BRAKE + DstParamData%TMD_Y_C_BRAKE = SrcParamData%TMD_Y_C_BRAKE + DstParamData%Use_F_TBL = SrcParamData%Use_F_TBL +IF (ALLOCATED(SrcParamData%F_TBL)) THEN + i1_l = LBOUND(SrcParamData%F_TBL,1) + i1_u = UBOUND(SrcParamData%F_TBL,1) + i2_l = LBOUND(SrcParamData%F_TBL,2) + i2_u = UBOUND(SrcParamData%F_TBL,2) + IF (.NOT. ALLOCATED(DstParamData%F_TBL)) THEN + ALLOCATE(DstParamData%F_TBL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_TBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%F_TBL = SrcParamData%F_TBL +ENDIF + END SUBROUTINE TMD_CopyParam + + SUBROUTINE TMD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(TMD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%F_TBL)) THEN + DEALLOCATE(ParamData%F_TBL) +ENDIF + END SUBROUTINE TMD_DestroyParam + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Int_BufSz = Int_BufSz + 1 ! TMD_DOF_MODE + Int_BufSz = Int_BufSz + 1 ! TMD_X_DOF + Int_BufSz = Int_BufSz + 1 ! TMD_Y_DOF + Re_BufSz = Re_BufSz + 1 ! X_DSP + Re_BufSz = Re_BufSz + 1 ! Y_DSP + Re_BufSz = Re_BufSz + 1 ! M_X + Re_BufSz = Re_BufSz + 1 ! M_Y + Re_BufSz = Re_BufSz + 1 ! M_XY + Re_BufSz = Re_BufSz + 1 ! K_X + Re_BufSz = Re_BufSz + 1 ! K_Y + Re_BufSz = Re_BufSz + 1 ! C_X + Re_BufSz = Re_BufSz + 1 ! C_Y + Re_BufSz = Re_BufSz + SIZE(InData%K_S) ! K_S + Re_BufSz = Re_BufSz + SIZE(InData%C_S) ! C_S + Re_BufSz = Re_BufSz + SIZE(InData%P_SP) ! P_SP + Re_BufSz = Re_BufSz + SIZE(InData%N_SP) ! N_SP + Re_BufSz = Re_BufSz + SIZE(InData%F_ext) ! F_ext + Re_BufSz = Re_BufSz + 1 ! Gravity + Int_BufSz = Int_BufSz + 1 ! TMD_CMODE + Int_BufSz = Int_BufSz + 1 ! TMD_SA_MODE + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_HIGH + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_LOW + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_HIGH + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_LOW + Re_BufSz = Re_BufSz + 1 ! TMD_X_C_BRAKE + Re_BufSz = Re_BufSz + 1 ! TMD_Y_C_BRAKE + Int_BufSz = Int_BufSz + 1 ! Use_F_TBL + Int_BufSz = Int_BufSz + 1 ! F_TBL allocated yes/no + IF ( ALLOCATED(InData%F_TBL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_TBL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_TBL) ! F_TBL + 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 + + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%TMD_DOF_MODE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TMD_X_DOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TMD_Y_DOF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%X_DSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Y_DSP + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%M_X + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%M_Y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%M_XY + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%K_X + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%K_Y + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_X + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%C_Y + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%K_S,1), UBOUND(InData%K_S,1) + ReKiBuf(Re_Xferred) = InData%K_S(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%C_S,1), UBOUND(InData%C_S,1) + ReKiBuf(Re_Xferred) = InData%C_S(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%P_SP,1), UBOUND(InData%P_SP,1) + ReKiBuf(Re_Xferred) = InData%P_SP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%N_SP,1), UBOUND(InData%N_SP,1) + ReKiBuf(Re_Xferred) = InData%N_SP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%F_ext,1), UBOUND(InData%F_ext,1) + ReKiBuf(Re_Xferred) = InData%F_ext(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TMD_CMODE + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TMD_SA_MODE + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_HIGH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_LOW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_HIGH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_LOW + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_X_C_BRAKE + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TMD_Y_C_BRAKE + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Use_F_TBL, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%F_TBL) ) 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%F_TBL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_TBL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_TBL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_TBL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_TBL,2), UBOUND(InData%F_TBL,2) + DO i1 = LBOUND(InData%F_TBL,1), UBOUND(InData%F_TBL,1) + ReKiBuf(Re_Xferred) = InData%F_TBL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE TMD_PackParam + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%TMD_DOF_MODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_X_DOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TMD_X_DOF) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_Y_DOF = TRANSFER(IntKiBuf(Int_Xferred), OutData%TMD_Y_DOF) + Int_Xferred = Int_Xferred + 1 + OutData%X_DSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Y_DSP = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%M_X = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%M_Y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%M_XY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%K_X = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%K_Y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_X = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%C_Y = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%K_S,1) + i1_u = UBOUND(OutData%K_S,1) + DO i1 = LBOUND(OutData%K_S,1), UBOUND(OutData%K_S,1) + OutData%K_S(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%C_S,1) + i1_u = UBOUND(OutData%C_S,1) + DO i1 = LBOUND(OutData%C_S,1), UBOUND(OutData%C_S,1) + OutData%C_S(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%P_SP,1) + i1_u = UBOUND(OutData%P_SP,1) + DO i1 = LBOUND(OutData%P_SP,1), UBOUND(OutData%P_SP,1) + OutData%P_SP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%N_SP,1) + i1_u = UBOUND(OutData%N_SP,1) + DO i1 = LBOUND(OutData%N_SP,1), UBOUND(OutData%N_SP,1) + OutData%N_SP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%F_ext,1) + i1_u = UBOUND(OutData%F_ext,1) + DO i1 = LBOUND(OutData%F_ext,1), UBOUND(OutData%F_ext,1) + OutData%F_ext(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_CMODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_SA_MODE = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TMD_X_C_HIGH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C_LOW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_HIGH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_LOW = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_X_C_BRAKE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TMD_Y_C_BRAKE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Use_F_TBL = TRANSFER(IntKiBuf(Int_Xferred), OutData%Use_F_TBL) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_TBL 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%F_TBL)) DEALLOCATE(OutData%F_TBL) + ALLOCATE(OutData%F_TBL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_TBL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_TBL,2), UBOUND(OutData%F_TBL,2) + DO i1 = LBOUND(OutData%F_TBL,1), UBOUND(OutData%F_TBL,1) + OutData%F_TBL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE TMD_UnPackParam + + SUBROUTINE TMD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%Mesh, DstInputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE TMD_CopyInput + + SUBROUTINE TMD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(TMD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%Mesh, ErrStat, ErrMsg ) + END SUBROUTINE TMD_DestroyInput + + SUBROUTINE TMD_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(TMD_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 = 'TMD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 TMD_PackInput + + SUBROUTINE TMD_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(TMD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_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 + 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 TMD_UnPackInput + + SUBROUTINE TMD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TMD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(TMD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'TMD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE TMD_CopyOutput + + SUBROUTINE TMD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(TMD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) + END SUBROUTINE TMD_DestroyOutput + + SUBROUTINE TMD_PackOutput( 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(TMD_OutputType), 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 = 'TMD_PackOutput' + ! 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 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Mesh + 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 MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh + 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 TMD_PackOutput + + SUBROUTINE TMD_UnPackOutput( 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(TMD_OutputType), 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 = 'TMD_UnPackOutput' + ! 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 MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh + 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 TMD_UnPackOutput + + + SUBROUTINE TMD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(TMD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(TMD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL TMD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL TMD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL TMD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE TMD_Input_ExtrapInterp + + + SUBROUTINE TMD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(TMD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(TMD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(TMD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE TMD_Input_ExtrapInterp1 + + + SUBROUTINE TMD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(TMD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(TMD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(TMD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(TMD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE TMD_Input_ExtrapInterp2 + + + SUBROUTINE TMD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(TMD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(TMD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL TMD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL TMD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL TMD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE TMD_Output_ExtrapInterp + + + SUBROUTINE TMD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(TMD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(TMD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(TMD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE TMD_Output_ExtrapInterp1 + + + SUBROUTINE TMD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(TMD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(TMD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(TMD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(TMD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'TMD_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE TMD_Output_ExtrapInterp2 + +END MODULE TMD_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/servodyn/src/UserSubs.f90 b/OpenFAST/modules/servodyn/src/UserSubs.f90 new file mode 100644 index 000000000..bd276dcdb --- /dev/null +++ b/OpenFAST/modules/servodyn/src/UserSubs.f90 @@ -0,0 +1,459 @@ + ! NOTE: This source file contains dummy placeholders for the + ! user-specified routines available in ServoDyn. These routines + ! are as follows: + ! Routine Description + ! ------------ --------------------------------------------------- + ! PitchCntrl() User-specified blade pitch control (either + ! independent or rotor-collective) model. + ! UserGen() User-specified generator torque and power model. + ! UserHSSBr() User-specified high-speed shaft brake model. + ! UserVSCont() User-specified variable-speed torque and power + ! control model. + ! UserYawCont() User-specified nacelle-yaw control model. + ! In order to interface FAST with your own user-specified routines, + ! you can develop your own logic within these dummy placeholders and + ! recompile FAST; OR comment out the appropriate dummy placeholders, + ! create your own routines in their own source files, and recompile + ! FAST while linking in these additional source files. For example, + ! the executable version of FAST that is distributed with the FAST + ! archive is linked with the example PitchCntrl() routine contained in + ! source file PitchCntrl_ACH.f90 and the example UserGen() and + ! UserVSCont() routines contained in source file UserVSCont_KP.f90; + ! thus, the dummy placeholders for routines PitchCntrl(), UserGen(), + ! and UserVSCont() are commented out within this source file. The + ! example pitch controller was written by Craig Hansen (ACH) and the + ! example generator and variable speed controllers were written by + ! Kirk Pierce (KP). Please see the aforementioned source files for + ! additional information on these example user-specified routines. + + ! note: we recommend NOT using these routines because they do not conform to the FAST + ! modularization framework. They remain for legacy purposes only. + +module UserSubs +contains + +!======================================================================= +!SUBROUTINE PitchCntrl ( BlPitch, ElecPwr, LSS_Spd, TwrAccel, NumBl, ZTime, DT, DirRoot, BlPitchCom ) +! +! +! ! This is a dummy routine for holding the place of a user-specified +! ! blade pitch control model (either independent or rotor-collective). +! ! Modify this code to create your own model. +! +! +!USE Precision +! +! +!IMPLICIT NONE +! +! +! ! Passed variables: +! +!INTEGER(4), INTENT(IN ) :: NumBl ! Number of blades, (-). +! +!REAL(ReKi), INTENT(IN ) :: BlPitch (NumBl) ! Current values of the blade pitch angles, rad. +!REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +!REAL(ReKi), INTENT(IN ) :: ElecPwr ! Electrical power, watts. +!REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed (rad/s) +!REAL(ReKi), INTENT(OUT) :: BlPitchCom(NumBl) ! Commanded blade pitch angles (demand pitch angles), rad. +!REAL(ReKi), INTENT(IN ) :: TwrAccel ! Tower Acceleration, m/s^2. +!REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. +! +!CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. +! +! +! +!BlPitchCom = 0.0 +! +! +! +!RETURN +!END SUBROUTINE PitchCntrl +!======================================================================= +!SUBROUTINE UserGen ( HSS_Spd, LSS_Spd, NumBl, ZTime, DT, GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) +! +! +! ! This is a dummy routine for holding the place of a user-specified +! ! generator torque and power model. Modify this code to create your +! ! own model. +! +! ! NOTE: If you (the user) wants to switch on-or-off the generator DOF at +! ! runtime from this user-defined routine, then do the following: +! ! (1) USE MODULE DOFs(). +! ! (2) Type in "DOF_Flag(DOF_GeAz) = VALUE" where VALUE = .TRUE. or +! ! .FALSE. depending on whether you want to turn-on or turn-off +! ! the DOF, respectively. Turning off the DOF forces the +! ! current RATE to remain fixed. If the rate is currently zero, +! ! the current POSITION will remain fixed as well. +! ! Note that this technique WILL NOT work for user-defined routines +! ! written for ADAMS datasets extracted using the FAST-to-ADAMS +! ! preprocessor. +! +! +!USE Precision +! +! +!IMPLICIT NONE +! +! +! ! Passed Variables: +! +!INTEGER(4), INTENT(IN ) :: NumBl ! Number of blades, (-). +! +!REAL(ReKi), INTENT(IN ) :: DelGenTrq ! Pertubation in generator torque used during FAST linearization (zero otherwise), N-m. +!REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +!REAL(ReKi), INTENT(OUT) :: ElecPwr ! Electrical power (account for losses), watts. +!REAL(ReKi), INTENT(IN ) :: GenEff ! Generator efficiency, (-). +!REAL(ReKi), INTENT(OUT) :: GenTrq ! Electrical generator torque, N-m. +!REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed, rad/s. +!REAL(ReKi), INTENT(IN ) :: HSS_Spd ! HSS speed, rad/s. +!REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. +! +!CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. +! +! +! +!GenTrq = 0.0 + DelGenTrq ! Make sure to add the pertubation on generator torque, DelGenTrq. This is used only for FAST linearization (it is zero otherwise). +! +! +! ! The generator efficiency is either additive for motoring, +! ! or subtractive for generating power. +! +!IF ( GenTrq > 0.0 ) THEN +! ElecPwr = GenTrq*HSS_Spd*GenEff +!ELSE +! ElecPwr = GenTrq*HSS_Spd/GenEff +!ENDIF +! +! +! +!RETURN +!END SUBROUTINE UserGen +!======================================================================= +SUBROUTINE UserHSSBr ( GenTrq, ElecPwr, HSS_Spd, NumBl, ZTime, DT, DirRoot, HSSBrFrac ) + + + ! This is a dummy routine for holding the place of a user-specified + ! HSS brake model. This routine must specify the fraction + ! (HSSBrFrac) of full torque to be applied to the HSS by the HSS + ! brake. The magnitude of the full torque (HSSBrFrac = 1.0) equals + ! HSSBrTqF from the primary input file. Modify this code to create + ! your own model. + + ! NOTE: If you (the user) wants to switch on-or-off the generator DOF at + ! runtime from this user-defined routine, then do the following: + ! (1) USE MODULE DOFs(). + ! (2) Type in "DOF_Flag(DOF_GeAz) = VALUE" where VALUE = .TRUE. or + ! .FALSE. depending on whether you want to turn-on or turn-off + ! the DOF, respectively. Turning off the DOF forces the + ! current RATE to remain fixed. If the rate is currently zero, + ! the current POSITION will remain fixed as well. + ! Note that this technique WILL NOT work for user-defined routines + ! written for ADAMS datasets extracted using the FAST-to-ADAMS + ! preprocessor. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +INTEGER(4), INTENT(IN ) :: NumBl ! Number of blades, (-). + +REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +REAL(ReKi), INTENT(IN ) :: ElecPwr ! Electrical power (account for losses), watts. +REAL(ReKi), INTENT(IN ) :: GenTrq ! Electrical generator torque, N-m. +REAL(ReKi), INTENT(IN ) :: HSS_Spd ! HSS speed, rad/s. +REAL(ReKi), INTENT(OUT) :: HSSBrFrac ! Fraction of full braking torque: 0 (off) <= HSSBrFrac <= 1 (full), (-). +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +HSSBrFrac = 0.0 ! NOTE: This must be specified as a real number between 0.0 (off - no brake torque) and 1.0 (full - max brake torque = HSSBrTqF); FAST/ADAMS will Abort otherwise. + + + +RETURN +END SUBROUTINE UserHSSBr +!======================================================================= +SUBROUTINE UserTFin ( TFrlDef , TFrlRate, ZTime , DirRoot, & + TFinCPxi, TFinCPyi, TFinCPzi, & + TFinCPVx, TFinCPVy, TFinCPVz, & + TFinAOA , TFinQ , & + TFinCL , TFinCD , & + TFinKFx , TFinKFy ) + + + ! This is a dummy routine for holding the place of user-specified + ! computations for tail fin aerodynamic loads. Modify this code to + ! create your own logic. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +REAL(ReKi), INTENT(OUT) :: TFinAOA ! Angle-of-attack between the relative wind velocity and tail fin chordline, rad. +REAL(ReKi), INTENT(OUT) :: TFinCD ! Tail fin drag coefficient resulting from current TFinAOA, (-). +REAL(ReKi), INTENT(OUT) :: TFinCL ! Tail fin lift coefficient resulting from current TFinAOA, (-). +REAL(ReKi), INTENT(IN ) :: TFinCPVx ! Absolute Velocity of the tail center-of-pressure along tail fin chordline pointing toward tail fin trailing edge, m/s. +REAL(ReKi), INTENT(IN ) :: TFinCPVy ! Absolute Velocity of the tail center-of-pressure normal to plane of tail fin pointing towards suction surface , m/s. +REAL(ReKi), INTENT(IN ) :: TFinCPVz ! Absolute Velocity of the tail center-of-pressure in plane of tail fin normal to chordline and nominally upward , m/s. +!jmj Start of proposed change. v6.02a-jmj 25-Aug-2006. +!jmj Improve the description of input arguments TFinCPxi, TFinCPyi, and +!jmj TFinCPzi: +!remove6.02aREAL(ReKi), INTENT(IN ) :: TFinCPxi ! Downwind distance from the inertial frame origin to the tail fin center-of-pressure, m. +!remove6.02aREAL(ReKi), INTENT(IN ) :: TFinCPyi ! Lateral distance from the inertial frame origin to the tail fin center-of-pressure, m. +!remove6.02aREAL(ReKi), INTENT(IN ) :: TFinCPzi ! Vertical distance from the inertial frame origin to the tail fin center-of-pressure, m. +REAL(ReKi), INTENT(IN ) :: TFinCPxi ! Downwind distance from the inertial frame origin at ground level [onshore] or MSL [offshore] to the tail fin center-of-pressure, m. +REAL(ReKi), INTENT(IN ) :: TFinCPyi ! Lateral distance from the inertial frame origin at ground level [onshore] or MSL [offshore] to the tail fin center-of-pressure, m. +REAL(ReKi), INTENT(IN ) :: TFinCPzi ! Vertical distance from the inertial frame origin at ground level [onshore] or MSL [offshore] to the tail fin center-of-pressure, m. +!jmj End of proposed change. v6.02a-jmj 25-Aug-2006. +REAL(ReKi), INTENT(OUT) :: TFinKFx ! Aerodynamic force at the tail fin center-of-pressure (point K) along tail fin chordline pointing toward tail fin trailing edge, N. +REAL(ReKi), INTENT(OUT) :: TFinKFy ! Aerodynamic force at the tail fin center-of-pressure (point K) normal to plane of tail fin pointing towards suction surface , N. +REAL(ReKi), INTENT(OUT) :: TFinQ ! Dynamic pressure of the relative wind velocity, Pa. +REAL(ReKi), INTENT(IN ) :: TFrlDef ! Tail-furl angular deflection, rad. +REAL(ReKi), INTENT(IN ) :: TFrlRate ! Tail-furl angular rate, rad/s +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +TFinAOA = 0.0 +TFinCL = 0.0 +TFinCD = 0.0 +TFinQ = 0.0 +TFinKFx = 0.0 +TFinKFy = 0.0 + + + +RETURN +END SUBROUTINE UserTFin +!======================================================================= +!SUBROUTINE UserVSCont ( HSS_Spd, LSS_Spd, NumBl, ZTime, DT, GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) +! +! +! ! This is a dummy routine for holding the place of a user-specified +! ! variable-speed torque and power control model. Modify this code to +! ! create your own model. +! +! ! NOTE: If you (the user) wants to switch on-or-off the generator DOF at +! ! runtime from this user-defined routine, then do the following: +! ! (1) USE MODULE DOFs(). +! ! (2) Type in "DOF_Flag(DOF_GeAz) = VALUE" where VALUE = .TRUE. or +! ! .FALSE. depending on whether you want to turn-on or turn-off +! ! the DOF, respectively. Turning off the DOF forces the +! ! current RATE to remain fixed. If the rate is currently zero, +! ! the current POSITION will remain fixed as well. +! ! Note that this technique WILL NOT work for user-defined routines +! ! written for ADAMS datasets extracted using the FAST-to-ADAMS +! ! preprocessor. +! +! +!USE Precision +! +! +!IMPLICIT NONE +! +! +! ! Passed Variables: +! +!INTEGER(4), INTENT(IN ) :: NumBl ! Number of blades, (-). +! +!REAL(ReKi), INTENT(IN ) :: DelGenTrq ! Pertubation in generator torque used during FAST linearization (zero otherwise), N-m. +!REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +!REAL(ReKi), INTENT(OUT) :: ElecPwr ! Electrical power (account for losses), watts. +!REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed, rad/s. +!REAL(ReKi), INTENT(IN ) :: GenEff ! Generator efficiency, (-). +!REAL(ReKi), INTENT(OUT) :: GenTrq ! Electrical generator torque, N-m. +!REAL(ReKi), INTENT(IN ) :: HSS_Spd ! HSS speed, rad/s. +!REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. +! +!CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. +! +! +! +!GenTrq = 0.0 + DelGenTrq ! Make sure to add the pertubation on generator torque, DelGenTrq. This is used only for FAST linearization (it is zero otherwise). +! +! +! ! The generator efficiency is either additive for motoring, +! ! or subtractive for generating power. +! +!IF ( GenTrq > 0.0 ) THEN +! ElecPwr = GenTrq*HSS_Spd*GenEff +!ELSE +! ElecPwr = GenTrq*HSS_Spd/GenEff +!ENDIF +! +! +! +!RETURN +!END SUBROUTINE UserVSCont +!======================================================================= +SUBROUTINE UserYawCont ( YawPos, YawRate, WindDir, YawError, NumBl, ZTime, DT, DirRoot, YawPosCom, YawRateCom ) + + + ! This is a dummy routine for holding the place of a user-specified + ! nacelle-yaw controller. Modify this code to create your own device. + + + ! As indicated, the yaw controller must always specify a command (demand) + ! yaw angle, YawPosCom, AND command (demand) yaw rate, YawRateCom. + ! Normally, you should correlate these commands so that the commanded yaw + ! angle is the integral of the commanded yaw rate, or likewise, the + ! commanded yaw rate is the derivative of the commanded yaw angle. FAST + ! WILL NOT compute these correlations for you and DOES NOT check to + ! ensure that they are correlated. In some situations, it is desirable to + ! set one of the commands (either yaw angle OR yaw rate) to ZERO depending + ! on the desired transfer function of FAST's built-in actuator model (see + ! below for a discussion of FAST's built-in actuator model). In general, + ! the commanded yaw angle and rate SHOULD NEVER be defined independent of + ! each other with BOTH commands NONZERO. + + + ! The yaw controller's effect on the FAST model depends on whether or not + ! the yaw DOF is enabled as follows: + ! + ! YawDOF = False - If the yaw DOF is disabled, then the commanded yaw angle + ! and rate will be the ACTUAL yaw angle and yaw rate used + ! internally by FAST (in general, you should ensure these + ! are correlated). In this case, any desired actuator + ! effects should be built within this controller. Also in + ! this case, FAST WILL NOT compute the correlated yaw + ! acceleration, but assume that it is ZERO. If the + ! commanded yaw rate is zero while the commanded yaw angle + ! is changing in time, then the yaw controller's effect + ! on yaw angle is the identical to routine PitchCntrl()'s + ! effect on pitch angle (i.e., routine PitchCntrl() + ! commands changes in pitch angle with no associated + ! changes in pitch rate or pitch acceleration). For yaw + ! control, this situation should be avoided however, since + ! yaw-induced gyroscopic pitching loads on the turbine + ! brought about by the yaw rate may be significant. + ! + ! YawDOF = True - If the yaw DOF is enabled, then the commanded yaw angle + ! and rate, YawPosCom and YawRateCom, become the neutral + ! yaw angle, YawNeut, and neutral yaw rate, YawRateNeut, in + ! FAST's built-in second-order actuator model defined by + ! inputs YawSpr and YawDamp. + + + ! Description of FAST's built-in actuator model: + ! + ! In the time-domain, FAST's built-in actuator model is defined as follows: + ! + ! YawIner*YawAccel + YawDamp*YawRate + YawSpr*YawPos + ! = YawDamp*YawRateNeut + YawSpr*YawNeut + YawTq + ! + ! so that the transmitted torque is: + ! + ! YawMom = YawSpr*( YawPos - YawNeut ) + YawDamp*( YawRate - YawRateNeut ) + ! + ! where, + ! YawSpr = nacelle-yaw spring constant (defined in FAST's primary + ! input file) + ! YawDamp = nacelle-yaw damping constant (defined in FAST's primary + ! input file) + ! YawIner = instantaneous inertia of the nacelle and rotor about the + ! yaw axis + ! YawNeut = the commanded (neutral) yaw angle = YawPosCom + ! YawRateNeut = the commanded (neutral) yaw rate = YawRateCom + ! YawPos = yaw angle (position) + ! YawRate = yaw rate + ! YawAccel = yaw acceleration + ! YawTq = torque about the yaw axis applied by external forces above + ! the yaw bearing, such as wind loading + ! YawMom = torque transmitted through the yaw bearing + ! + ! If the commanded yaw angle and rate are correlated (so that the commanded + ! yaw angle is the integral of the commanded yaw rate, or likewise, the + ! commanded yaw rate is the derivative of the commanded yaw angle), then + ! FAST's built-in second-order actuator model will have the following + ! characteristic transfer function: + ! + ! YawDamp*s + YawSpr 2*Zeta*OmegaN*s + OmegaN^2 + ! T(s) = -------------------------------- = -------------------------------- + ! YawIner*s^2 + YawDamp*s + YawSpr s^2 + 2*Zeta*OmegaN*s + OmegaN^2 + ! + ! where, + ! T(s) = the transfer function of FAST's built-in 2nd order actuator + ! model + ! OmegaN = SQRT(YawSpr/YawIner) = yaw actuator natural frequency + ! Zeta = YawDamp/(2*SQRT(YawSpr*YawIner)) = yaw actuator damping ratio + ! in fraction of critical + ! + ! If only the yaw angle is commanded, and YawRateCom is zeroed, then the + ! charecteristic transfer function of FAST's built-in second-order + ! actuator model simplifies to: + ! + ! YawSpr OmegaN^2 + ! T(s) = -------------------------------- = -------------------------------- + ! YawIner*s^2 + YawDamp*s + YawSpr s^2 + 2*Zeta*OmegaN*s + OmegaN^2 + ! + ! If only the yaw rate is commanded, and YawPosCom is zeroed, then the + ! charecteristic transfer function of FAST's built-in second-order + ! actuator model simplifies to: + ! + ! YawDamp 2*Zeta*OmegaN + ! T(s) = -------------------------------- = -------------------------------- + ! YawIner*s^2 + YawDamp*s + YawSpr s^2 + 2*Zeta*OmegaN*s + OmegaN^2 + + + ! NOTE: If you (the user) wants to switch on-or-off the yaw DOF at + ! runtime from this user-defined routine, then do the following: + ! (1) USE MODULE DOFs(). + ! (2) Type in "DOF_Flag(DOF_Yaw) = VALUE" where VALUE = .TRUE. or + ! .FALSE. depending on whether you want to turn-on or turn-off + ! the DOF, respectively. Turning off the DOF acts is like + ! setting YawDOF to False. + ! This technique is useful, for example, if the yaw bearing has + ! an electromagnetic latch that will unlock and relock the hinge under + ! certain specified conditions. + ! Note that this technique WILL NOT work for user-defined routines + ! written for ADAMS datasets extracted using the FAST-to-ADAMS + ! preprocessor. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +INTEGER(4), INTENT(IN ) :: NumBl ! Number of blades, (-). + +REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +REAL(ReKi), INTENT(IN ) :: WindDir ! Current horizontal hub-height wind direction (positive about the zi-axis), rad. +REAL(ReKi), INTENT(IN ) :: YawError ! Current nacelle-yaw error estimate (positve about the zi-axis), rad. +REAL(ReKi), INTENT(IN ) :: YawPos ! Current nacelle-yaw angular position, rad. +REAL(ReKi), INTENT(OUT) :: YawPosCom ! Commanded nacelle-yaw angular position (demand yaw angle), rad. +REAL(ReKi), INTENT(IN ) :: YawRate ! Current nacelle-yaw angular rate, rad/s. +REAL(ReKi), INTENT(OUT) :: YawRateCom ! Commanded nacelle-yaw angular rate (demand yaw rate), rad/s. +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +YawPosCom = 0.0 +YawRateCom = 0.0 + + + +RETURN +END SUBROUTINE UserYawCont +!======================================================================= +end module UserSubs diff --git a/OpenFAST/modules/servodyn/src/UserVSCont_KP.f90 b/OpenFAST/modules/servodyn/src/UserVSCont_KP.f90 new file mode 100644 index 000000000..d36239968 --- /dev/null +++ b/OpenFAST/modules/servodyn/src/UserVSCont_KP.f90 @@ -0,0 +1,243 @@ + !> NOTE: This source file contains an example UserVSCont() user-specified + !! routine for computing variable-speed controlled generator torque + !! based on a table look-up of LSS speed and LSS torque provided in a + !! spd_trq.dat input file. It also contains an example UserGen, which + !! calls UserVSCont. These routines were written by Kirk Pierce (KP), + !! formerly of NREL/NWTC, and now with GE Wind Energy. Questions + !! related to the use of these routines should be addressed to Kirk + !! Pierce. +module UserVSCont_KP +contains + +!======================================================================= +SUBROUTINE UserGen ( HSS_Spd, LSS_Spd, NumBl, ZTime, DT, GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) + + + ! This example UserGen() is used do the same thing as SUBROUTINE + ! UserVSCont(), so that setting VSContrl to 0 and GenModel to 3 does + ! the same thing as setting VSContrl to 3. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: + +INTEGER(IntKi), INTENT(IN ) :: NumBl ! Number of blades, (-). + +REAL(ReKi), INTENT(IN ) :: DelGenTrq ! Pertubation in generator torque used during FAST linearization (zero otherwise), N-m. +REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +REAL(ReKi), INTENT(OUT) :: ElecPwr ! Electrical power (account for losses), watts. +REAL(ReKi), INTENT(IN ) :: GenEff ! Generator efficiency, (-). +REAL(ReKi), INTENT(OUT) :: GenTrq ! Electrical generator torque, N-m. +REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed, rad/s. +REAL(ReKi), INTENT(IN ) :: HSS_Spd ! HSS speed, rad/s. +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024),INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + +CALL UserVSCont ( HSS_Spd, LSS_Spd, NumBl, ZTime, DT, GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) ! Let's have UserGen() do the same thing as SUBROUTINE UserVSCont(). + + + +RETURN +END SUBROUTINE UserGen +!======================================================================= +SUBROUTINE UserVSCont ( HSS_Spd, LSS_Spd, NumBl, ZTime, DT, GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) + + + ! Written 2/28/00 by Kirk Pierce for use with FAST. + ! This subroutine uses a torque vs speed lookup table. + ! A first order lag of time constant TCONST is applied to the + ! calculated torque. + + ! Converted to modern Fortran by M. Buhl. + ! Modified to calculate electrical generator power by J. Jonkman. + + ! 1 + ! GenTrq = ----------- TRQ + ! TCONST*S+1 + + +USE NWTC_Library + +IMPLICIT NONE + + + ! Passed Variables: +!type(strd_outputtype), intent(in), optional :: y_StrD +INTEGER(IntKi), INTENT(IN ) :: NumBl ! Number of blades, (-). + +REAL(ReKi), INTENT(IN ) :: DelGenTrq ! Pertubation in generator torque used during FAST linearization (zero otherwise), N-m. +REAL(DbKi), INTENT(IN ) :: DT ! Integration time step, sec. +REAL(ReKi), INTENT(OUT) :: ElecPwr ! Electrical power (account for losses), watts. +REAL(ReKi), INTENT(IN ) :: LSS_Spd ! LSS speed, rad/s. +REAL(ReKi), INTENT(IN ) :: GenEff ! Generator efficiency, (-). +REAL(ReKi), INTENT(OUT) :: GenTrq ! Electrical generator torque, N-m. +REAL(ReKi), INTENT(IN ) :: HSS_Spd ! HSS speed, rad/s. +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. + +CHARACTER(1024),INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + + + ! Local Variables: + +REAL(ReKi), SAVE :: C1 +REAL(ReKi), SAVE :: C2 +REAL(DbKi) :: DELT +REAL(ReKi), SAVE :: FRPM (5) = 0.0 ! Filtered RPM. +REAL(ReKi), SAVE :: FTRQ = 0.0 ! Filtered torque, N-m. +REAL(ReKi), SAVE :: OLTRQ = 0.0 +REAL(ReKi) :: OMEGA ! Rotor speed, rad/s. +REAL(ReKi) :: RPM +REAL(ReKi), SAVE :: RPMSCH (100) +REAL(DbKi), SAVE :: SMPDT +REAL(DbKi), PARAMETER :: TCONST = 0.05 ! Time constant of first order lag applied to torque +REAL(ReKi), SAVE :: TLST = 0.0 +REAL(ReKi), SAVE :: TRQ = 0.0 +REAL(ReKi), SAVE :: TRQSCH (100) +REAL(DbKi), SAVE :: TTRQ = 0.0 + +INTEGER(IntKi) :: I +INTEGER(IntKi) :: IOS ! I/O status. Negative values indicate end of file. +INTEGER(IntKi) :: N1 +INTEGER, SAVE :: NSCH = 0 ! Number of lines found in the file +INTEGER, PARAMETER :: NST = 5 ! Number of integration time steps between controller torque calculations. +INTEGER, PARAMETER :: UnCont = 99 ! Unit number for the input file + +LOGICAL, SAVE :: SFLAG = .TRUE. + +CHARACTER(1024) :: TITLE +CHARACTER(1024) :: inFileName ! name of the input file + +INTEGER(IntKi) :: ErrStat +CHARACTER(ErrMsgLen) :: ErrMsg + +!bjj: there are numerical issues with time in this routine + + ! Abort if GBRatio is not unity; since this example routine returns the + ! generator torque cast to the LSS side of the gearbox, whereas routine + ! UserVSCont() should be returning the torque on the HSS side: +IF ( .NOT. EqualRealNos( HSS_Spd, LSS_Spd ) ) THEN + CALL ProgAbort ( " GBRatio must be set to 1.0 when using Kirk Pierce's UserVSCont() routine." ) +END IF + + +OMEGA = HSS_Spd + + +IF ( SFLAG ) THEN + + I = INDEX( DirRoot, PathSep, BACK=.TRUE. ) + IF ( I < LEN_TRIM(DirRoot) .OR. I > 0 ) THEN + inFileName = DirRoot(1:I)//'spd_trq.dat' + ELSE + inFileName = 'spd_trq.dat' + END IF + + + CALL OpenFInpFile ( UnCont, TRIM(inFileName), ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) CALL ProgAbort(TRIM(ErrMsg)) + + READ (UnCont,'(A)') TITLE + + CALL WrScr1( ' Using variable speed generator option.' ) + CALL WrScr ( ' '//TRIM( TITLE ) ) + CALL WrScr ( ' ' ) + + DO I=1,100 + READ(UnCont,*,IOSTAT=IOS) RPMSCH(I), TRQSCH(I) + IF ( IOS < 0 ) EXIT + + IF ( I > 1 ) THEN + IF ( RPMSCH(I) <= RPMSCH(I-1) ) THEN + CALL ProgWarn('RPM schedule must be increasing in file spd_trq.dat. Schedule will be stopped at ' & + //TRIM(Num2LStr(RPMSCH(I-1)))//' RPM.') + EXIT + END IF + END IF + NSCH = NSCH + 1 + ENDDO ! I + + SMPDT = REAL( NST, DbKi )*DT + + C1 = EXP( -DT/TCONST ) + C2 = 1.0 - C1 + + SFLAG = .FALSE. + CLOSE(UnCont) + + IF ( NSCH < 2 ) THEN + IF ( NSCH == 0 ) THEN + RPMSCH(1) = 0.0 + TRQSCH(1) = 0.0 + END IF + NSCH = 2 + RPMSCH(2) = RPMSCH(1) + TRQSCH(2) = TRQSCH(1) + END IF +ENDIF + +DELT = ZTime - TLST + + + ! Calculate torque setting at every NST time steps. +IF ( EqualRealNos( DELT, ( SMPDT - 0.5_DbKi*DT ) ) .OR. (DELT > ( SMPDT - 0.5*DT ))) then +!IF ( DELT >= ( SMPDT - 0.5*DT ) ) THEN !this should be comparing with EqualRealNos() + + TLST = ZTime !BJJ: TLST is a saved variable, which may have issues on re-initialization. + + + ! Update old values. + + DO I=5,2,-1 + FRPM(I) = FRPM(I-1) + ENDDO ! I + + RPM = OMEGA * 30.0/PI + + ! Calculate recursive lowpass filtered value. + + FRPM(1) = 0.7*FRPM(2) + 0.3*RPM + + + FRPM(1) = MIN( MAX( FRPM(1), RPMSCH(1) ), RPMSCH(NSCH) ) + TRQ = InterpBin( FRPM(1), RPMSCH(1:NSCH), TRQSCH(1:NSCH), N1, NSCH ) + + +ENDIF + + + ! Torque is updated at every integrator time step +IF ( (.NOT. EqualRealNos(ZTime, TTRQ )) .AND. ZTime > TTRQ ) THEN +!IF ( ZTime > TTRQ ) THEN + + FTRQ = C1*FTRQ + C2*OLTRQ + OLTRQ = TRQ + TTRQ = ZTime + 0.5_DbKi*DT + +ENDIF + + +GenTrq = FTRQ + DelGenTrq ! Make sure to add the pertubation on generator torque, DelGenTrq. This is used only for FAST linearization (it is zero otherwise). + + ! The generator efficiency is either additive for motoring, + ! or subtractive for generating power. + +IF ( GenTrq > 0.0 ) THEN + ElecPwr = GenTrq*HSS_Spd*GenEff +ELSE + ElecPwr = GenTrq*HSS_Spd/GenEff +ENDIF + + + +RETURN +END SUBROUTINE UserVSCont +!======================================================================= +end module UserVSCont_KP diff --git a/OpenFAST/modules/subdyn/CMakeLists.txt b/OpenFAST/modules/subdyn/CMakeLists.txt new file mode 100644 index 000000000..fa0fdbc85 --- /dev/null +++ b/OpenFAST/modules/subdyn/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/SubDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/SubDyn_Types.f90) +endif() + +set(SUBDYN_SOURCES + src/SubDyn.f90 + src/SD_FEM.f90 + src/SubDyn_Output.f90 + src/qsort_c_module.f90 + src/SubDyn_Types.f90 +) + +add_library(subdynlib ${SUBDYN_SOURCES}) +target_link_libraries(subdynlib nwtclibs) + +set(SUBDYN_DRIVER_SOURCES + src/SubDyn_Driver.f90) + +add_executable(subdyn_driver ${SUBDYN_DRIVER_SOURCES}) +target_link_libraries(subdyn_driver subdynlib nwtclibs versioninfolib) + +install(TARGETS subdynlib subdyn_driver + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/subdyn/README.md b/OpenFAST/modules/subdyn/README.md new file mode 100644 index 000000000..1e5f84bec --- /dev/null +++ b/OpenFAST/modules/subdyn/README.md @@ -0,0 +1,25 @@ +# SubDyn Module +The legacy version of this module and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/SubDyn/). + +## Overview +SubDyn is a time-domain structural-dynamics module for multi-member +fixed-bottom substructures that has been coupled into the OpenFAST +aero-hydro-servo-elastic computer-aided engineering (CAE) tool. Substructure +types supported by SubDyn include monopiles, tripods, jackets, and other +lattice-type substructures common for offshore wind installations in shallow +and transitional water depths. SubDyn can also be used to model lattice +support structures for land-based wind turbines. + +SubDyn follows the requirements of the FAST modularization framework and +couples to OpenFAST. It can also be driven as a standalone code to compute +the mode shapes, natural frequencies, and time-domain responses of +substructures, uncoupled from OpenFAST and in the absence of external loading +other than gravity and interface motion. + +SubDyn relies on two main engineering schematizations +1. a linear frame finite-element beam model (LFEB) +2. a dynamics system reduction via Craig-Bampton’s (C-B) method + +together with a Static-Improvement method, greatly reducing the number of modes +needed to obtain an accurate solution. diff --git a/OpenFAST/modules/subdyn/src/SD_FEM.f90 b/OpenFAST/modules/subdyn/src/SD_FEM.f90 new file mode 100644 index 000000000..dd59ec147 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SD_FEM.f90 @@ -0,0 +1,1018 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! 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 SD_FEM + USE NWTC_Library + USE SubDyn_Types + IMPLICIT NONE + + INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors + + INTEGER(IntKi), PARAMETER :: MaxMemjnt = 10 ! Maximum number of members at one joint + INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in + INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) + + ! values of these parameters are ordered by their place in SubDyn input file: + INTEGER(IntKi), PARAMETER :: JointsCol = 4 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) + INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction dof array (JointID,RctTDxss,RctTDYss,RctTDZss,RctRDXss,RctRDYss,RctRDZss) + INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) + INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) + INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) + INTEGER(IntKi), PARAMETER :: PropSetsCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs + INTEGER(IntKi), PARAMETER :: XPropSetsCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) + INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) + INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) + ! Indices in Members table + INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored + + INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsCol,XPropSetsCol,COSMsCol,CMassCol) + + + INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic + MODULE PROCEDURE FINDLOCI_ReKi + MODULE PROCEDURE FINDLOCI_IntKi + END INTERFACE + +CONTAINS + +!> Maps nodes to elements +!! allocate NodesConnE and NodesConnN +SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) + USE qsort_c_module ,only: QsortC + TYPE(SD_InitType), INTENT( INOUT ) :: Init + TYPE(SD_ParameterType), INTENT( IN ) :: p + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements + INTEGER(IntKi) :: I,J,K !counter + + ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) + CALL AllocAry(Init%NodesConnE, Init%NNode, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnN, Init%NNode, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; + Init%NodesConnE = 0 + Init%NodesConnN = 0 + + ! find the node connectivity, nodes/elements that connect to a common node + DO I = 1, Init%NNode + Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array + k = 0 + DO J = 1, Init%NElem !This should be vectorized + IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element + k = k + 1 + if (k > MaxMemJnt+1) then + CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); + endif + Init%NodesConnE(I, k + 1) = p%Elems(J, 1) + Init%NodesConnN(I, k + 1) = p%Elems(J, 3) + IF ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element + ENDIF + ENDDO + + IF( k>1 )THEN ! sort the nodes ascendingly + SortA(1:k, 1) = Init%NodesConnN(I, 3:(k+2)) + CALL QsortC( SortA(1:k, 1:1) ) + Init%NodesConnN(I, 3:(k+2)) = SortA(1:k, 1) + ENDIF + + Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column + Init%NodesConnN(I, 2) = k + ENDDO + +END SUBROUTINE NodeCon +!---------------------------------------------------------------------------- +!> +! - Removes the notion of "ID" and use Index instead +! - Creates Nodes (use indices instead of ID), similar to Joints array +! - Creates Elems (use indices instead of ID) similar to Members array +! - Updates Reacts (use indices instead of ID) +! - Updates Interf (use indices instead of ID) +SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) ::Init + TYPE(SD_ParameterType), INTENT(INOUT) ::p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variable + INTEGER :: I, n, iMem, iNode, JointID + CHARACTER(1024) :: sType !< String for element type + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initialize Nodes + Init%Nodes = 0 + do I = 1,Init%NJoints + Init%Nodes(I, 1) = I ! JointID replaced by index I + Init%Nodes(I, 2) = Init%Joints(I, 2) + Init%Nodes(I, 3) = Init%Joints(I, 3) + Init%Nodes(I, 4) = Init%Joints(I, 4) + enddo + + ! --- Re-Initialize Reactions, pointing to index instead of JointID + do I = 1, p%NReact + JointID=p%Reacts(I,1) + p%Reacts(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index + if (p%Reacts(I,1)<=0) then + CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! --- Re-Initialize interface joints, pointing to index instead of JointID + Init%IntFc = 0 + do I = 1, Init%NInterf + JointID=Init%Interf(I,1) + Init%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (Init%Interf(I,1)<=0) then + CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! Change numbering in concentrated mass matrix + do I = 1, Init%NCMass + JointID = Init%CMass(I,1) + Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (Init%Interf(I,1)<=0) then + CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + + ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) + p%Elems = 0 + ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables + DO iMem = 1, p%NMembers + ! Column 1 : member index (instead of MemberID) + p%Elems(iMem, 1) = iMem + ! Column 2-3: Joint index (instead of JointIDs) + p%Elems(iMem, 1) = iMem ! NOTE: element/member number (not MemberID) + do iNode=2,3 + p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) + if (p%Elems(iMem,iNode)<=0) then + CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list!') + return + endif + enddo + ! Column 4-5: PropIndex 1-2 (instead of PropSetID1&2) + ! NOTE: this index has different meaning depending on the member type ! + DO n=iMProp,iMProp+1 + + sType='Member x-section property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSets(:,1), Init%Members(iMem, n) ) + + if (p%Elems(iMem,n)<=0) then + CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//'the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') + endif + END DO !n, loop through property ids + END DO !iMem, loop through members + + ! TODO in theory, we shouldn't need these anymore + ! deallocate(Init%Members) + ! deallocate(Init%Joints) +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems'); + END SUBROUTINE Fatal +END SUBROUTINE SD_ReIndex_CreateNodesAndElems + +!---------------------------------------------------------------------------- +SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) ::Init + TYPE(SD_ParameterType), INTENT(INOUT) ::p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variable + INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 + INTEGER :: NNE ! number of nodes per element + INTEGER :: MaxNProp + REAL(ReKi), ALLOCATABLE :: TempProps(:, :) + INTEGER, ALLOCATABLE :: TempMembers(:, :) + INTEGER :: knode, kelem, kprop, nprop + REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 + LOGICAL :: found, CreateNewProp + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + ErrStat = ErrID_None + ErrMsg = "" + + ! number of nodes per element + IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN + NNE = 2 + ELSE + CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') + RETURN + ENDIF + + ! Total number of element + Init%NElem = p%NMembers*Init%NDiv + ! Total number of nodes - Depends on division and number of nodes per element + Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers + Init%NNode = Init%NNode + (NNE - 2)*Init%NElem + + ! check the number of interior modes + IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) + RETURN + ENDIF + + CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different + CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays + ! NOTE: need NNode and NElem + CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initialize boundary constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first + CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitConstr(Init, p) + + ! --- Initialize interface constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first + DO I = 1, Init%NInterf + DO J = 1, 6 + Init%IntFc( (I-1)*6+J, 1) = (Init%Interf(I,1)-1)*6+J; ! TODO assumes order of DOF, and needs Interf1 reindexed + Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); + ENDDO + ENDDO + + Init%MemberNodes = 0 + ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) + if (Init%NDiv==1) then + ! NDiv = 1 + Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) + Init%NProp = Init%NPropSets + + else if (Init%NDiv > 1) then + + ! Discretize structure according to NDiv + ! - Elems is fully reinitialized, connectivity needs to be done again using SetNewElem + ! - Nodes are not reinitialized, but appended to NNodes + ! + + ! Initialize Temp arrays that will contain user inputs + input from the subdivided members + ! We don't know how many properties will be needed, so allocated to size MaxNProp + MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempProps, MaxNProp, PropSetsCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return + TempProps = -9999. + TempMembers = p%Elems(1:p%NMembers,:) + TempProps(1:Init%NPropSets, :) = Init%PropSets + + kelem = 0 + knode = Init%NJoints + kprop = Init%NPropSets + DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information + ! Member data + Node1 = TempMembers(I, 2) + Node2 = TempMembers(I, 3) + Prop1 = TempMembers(I, iMProp ) + Prop2 = TempMembers(I, iMProp+1) + + IF ( Node1==Node2 ) THEN + CALL Fatal(' Same starting and ending node in the member.') + RETURN + ENDIF + + + Init%MemberNodes(I, 1) = Node1 + Init%MemberNodes(I, Init%NDiv+1) = Node2 + + IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN + + CALL Fatal(' Material E,G and rho in a member must be the same') + RETURN + ENDIF + + x1 = Init%Nodes(Node1, 2) + y1 = Init%Nodes(Node1, 3) + z1 = Init%Nodes(Node1, 4) + + x2 = Init%Nodes(Node2, 2) + y2 = Init%Nodes(Node2, 3) + z2 = Init%Nodes(Node2, 4) + + dx = ( x2 - x1 )/Init%NDiv + dy = ( y2 - y1 )/Init%NDiv + dz = ( z2 - z1 )/Init%NDiv + + d1 = TempProps(Prop1, 5) + t1 = TempProps(Prop1, 6) + + d2 = TempProps(Prop2, 5) + t2 = TempProps(Prop2, 6) + + dd = ( d2 - d1 )/Init%NDiv + dt = ( t2 - t1 )/Init%NDiv + + ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node + CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) + + ! node connect to Node1 + knode = knode + 1 + Init%MemberNodes(I, 2) = knode + CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, Prop1, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, Prop1, Prop1, p) + nprop = Prop1 + ENDIF + + ! interior nodes + DO J = 2, (Init%NDiv-1) + knode = knode + 1 + Init%MemberNodes(I, J+1) = knode + + CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3),& + Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, & + TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, nprop, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, nprop, nprop, p) + + ENDIF + ENDDO + + ! the element connect to Node2 + kelem = kelem + 1 + CALL SetNewElem(kelem, knode, Node2, nprop, Prop2, p) + + ENDDO ! loop over all members + ! + Init%NProp = kprop + + ENDIF ! if NDiv is greater than 1 + + ! set the props in Init + CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return + + if (Init%NDiv==1) then + Init%Props(1:Init%NProp, 1:PropSetsCol) = Init%PropSets(1:Init%NProp, 1:PropSetsCol) + else if (Init%NDiv>1) then + Init%Props(1:Init%NProp, 1:PropSetsCol) = TempProps(1:Init%NProp, 1:PropSetsCol) + endif + !Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps + !Init%Props = TempProps(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + + CALL CleanUp_Discrt() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') + Failed = ErrStat >= AbortErrLev + if (Failed) CALL CleanUp_Discrt() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); + CALL CleanUp_Discrt() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp_Discrt() + ! deallocate temp matrices + IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) + IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) + END SUBROUTINE CleanUp_Discrt + +END SUBROUTINE SD_Discrt + + +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_ReKi(Array, Val) result(i) + real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == NINT(Array(i)) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_IntKi(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION + + +!------------------------------------------------------------------------------------------------------ +!> Set properties of node k +SUBROUTINE SetNewNode(k, x, y, z, Init) + TYPE(SD_InitType), INTENT(INOUT) :: Init + INTEGER, INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: x, y, z + + Init%Nodes(k, 1) = k + Init%Nodes(k, 2) = x + Init%Nodes(k, 3) = y + Init%Nodes(k, 4) = z + +END SUBROUTINE SetNewNode + +!------------------------------------------------------------------------------------------------------ +!> Set properties of element k +SUBROUTINE SetNewElem(k, n1, n2, p1, p2, p) + INTEGER, INTENT(IN ) :: k + INTEGER, INTENT(IN ) :: n1 + INTEGER, INTENT(IN ) :: n2 + INTEGER, INTENT(IN ) :: p1 + INTEGER, INTENT(IN ) :: p2 + TYPE(SD_ParameterType), INTENT(INOUT) :: p + + p%Elems(k, 1) = k + p%Elems(k, 2) = n1 + p%Elems(k, 3) = n2 + p%Elems(k, iMProp ) = p1 + p%Elems(k, iMProp+1) = p2 + +END SUBROUTINE SetNewElem + +!------------------------------------------------------------------------------------------------------ +!> Set material properties of element k +SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) + INTEGER , INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: E, G, rho, d, t + REAL(ReKi), INTENT(INOUT):: TempProps(:, :) + + TempProps(k, 1) = k + TempProps(k, 2) = E + TempProps(k, 3) = G + TempProps(k, 4) = rho + TempProps(k, 5) = d + TempProps(k, 6) = t + +END SUBROUTINE SetNewProp + +!------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector +SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K, Jn, Kn + INTEGER, PARAMETER :: NNE=2 ! number of nodes in one element, fixed to 2 + INTEGER :: N1, N2 ! starting node and ending node in the element + INTEGER :: P1, P2 ! property set numbers for starting and ending nodes + REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section + REAL(ReKi) :: x1, y1, z1, x2, y2, z2 ! coordinates of the nodes + REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices + REAL(ReKi) :: L ! length of the element + REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer + LOGICAL :: shear + REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector + INTEGER, DIMENSION(NNE) :: nn ! node number in element + INTEGER :: r + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + + ! for current application + if (Init%FEMMod == 2) THEN ! tapered Euler-Bernoulli + CALL Fatal ('FEMMod = 2 is not implemented.') + return + elseif (Init%FEMMod == 4) THEN ! tapered Timoshenko + CALL Fatal ('FEMMod = 2 is not implemented.') + return + elseif ((Init%FEMMod == 1) .or. (Init%FEMMod == 3)) THEN ! + ! 1: uniform Euler-Bernouli, 3: uniform Timoshenko + else + CALL Fatal('FEMMod is not valid. Please choose from 1, 2, 3, and 4. ') + return + endif + + ! total degrees of freedom of the system + Init%TDOF = 6*Init%NNode + + ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL Fatal('Error allocating p%ElemProps') + return + ENDIF + + CALL AllocAry( Ke, NNE*6, NNE*6 , 'Ke', ErrStat2, ErrMsg2); if(Failed()) return; ! element stiffness matrix + CALL AllocAry( Me, NNE*6, NNE*6 , 'Me', ErrStat2, ErrMsg2); if(Failed()) return; ! element mass matrix + CALL AllocAry( FGe, NNE*6, 'FGe', ErrStat2, ErrMsg2); if(Failed()) return; ! element gravity force vector + CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + Init%K = 0.0_ReKi + Init%M = 0.0_ReKi + Init%FG = 0.0_ReKi + + + ! loop over all elements + DO I = 1, Init%NElem + + DO J = 1, NNE + NN(J) = p%Elems(I, J + 1) + ENDDO + + N1 = p%Elems(I, 2) + N2 = p%Elems(I, NNE + 1) + + P1 = p%Elems(I, NNE + 2) + P2 = p%Elems(I, NNE + 3) + + E = Init%Props(P1, 2) + G = Init%Props(P1, 3) + rho = Init%Props(P1, 4) + D1 = Init%Props(P1, 5) + t1 = Init%Props(P1, 6) + D2 = Init%Props(P2, 5) + t2 = Init%Props(P2, 6) + + x1 = Init%Nodes(N1, 2) + y1 = Init%Nodes(N1, 3) + z1 = Init%Nodes(N1, 4) + + x2 = Init%Nodes(N2, 2) + y2 = Init%Nodes(N2, 3) + z2 = Init%Nodes(N2, 4) + + CALL GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return + + r1 = 0.25*(D1 + D2) + t = 0.5*(t1+t2) + + IF ( EqualRealNos(t, 0.0_ReKi) ) THEN + r2 = 0 + ELSE + r2 = r1 - t + ENDIF + + A = Pi_D*(r1*r1-r2*r2) + Ixx = 0.25*Pi_D*(r1**4-r2**4) + Iyy = Ixx + Jzz = 2.0*Ixx + + IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli + Shear = .false. + kappa = 0 + ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko + Shear = .true. + ! kappa = 0.53 + ! equation 13 (Steinboeck et al) in SubDyn Theory Manual + nu = E / (2.0_ReKi*G) - 1.0_ReKi + D_outer = 2.0_ReKi * r1 ! average (outer) diameter + D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter + ratioSq = ( D_inner / D_outer)**2 + kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & + / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) + ENDIF + + p%ElemProps(i)%Area = A + p%ElemProps(i)%Length = L + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%kappa = kappa + p%ElemProps(i)%YoungE = E + p%ElemProps(i)%ShearG = G + p%ElemProps(i)%Rho = rho + p%ElemProps(i)%DirCos = DirCos + + CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) + CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) + CALL ElemG(A, L, rho, DirCos, FGe, Init%g) + + ! assemble element matrices to global matrices + DO J = 1, NNE + jn = nn(j) + Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) ) + DO K = 1, NNE + kn = nn(k) + Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) + Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Me( (J*6-5):(J*6), (K*6-5):(K*6) ) + ENDDO !K + ENDDO !J + ENDDO ! I end loop over elements + + ! add concentrated mass + DO I = 1, Init%NCMass + DO J = 1, 3 + r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + Init%M(r, r) = Init%M(r, r) + Init%CMass(I, 2) + ENDDO + DO J = 4, 6 + r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + Init%M(r, r) = Init%M(r, r) + Init%CMass(I, J-1) + ENDDO + ENDDO ! Loop on concentrated mass + + ! add concentrated mass induced gravity force + DO I = 1, Init%NCMass + r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 + Init%FG(r) = Init%FG(r) - Init%CMass(I, 2)*Init%g + ENDDO ! I concentrated mass induced gravity + + CALL CleanUp_AssembleKM() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM') + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup_AssembleKM() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); + CALL CleanUp_AssembleKM() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp_AssembleKM() + IF(ALLOCATED(Ke )) DEALLOCATE(Ke ) + IF(ALLOCATED(Me )) DEALLOCATE(Me ) + IF(ALLOCATED(FGe)) DEALLOCATE(FGe) + END SUBROUTINE CleanUp_AssembleKM + +END SUBROUTINE AssembleKM + +!------------------------------------------------------------------------------------------------------ +!> Computes directional cosine matrix DirCos +!! rrd: This should be from local to global +!! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix +!! in the FAST framework. It seems to be used consistantly in the code (i.e., the transpose +!! of this matrix is used later). +SUBROUTINE GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat, ErrMsg) + REAL(ReKi) , INTENT(IN ) :: x1, y1, z1, x2, y2, z2 ! (x,y,z) positions of two nodes making up an element + REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix + REAL(ReKi) , INTENT( OUT) :: L ! length of element + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi) :: Dx,Dy,Dz, Dxy ! distances between nodes + ErrMsg = "" + ErrStat = ErrID_None + + Dy=y2-y1 + Dx=x2-x1 + Dz=z2-z1 + Dxy = sqrt( Dx**2 + Dy**2 ) + L = sqrt( Dx**2 + Dy**2 + Dz**2) + + IF ( EqualRealNos(L, 0.0_ReKi) ) THEN + ErrMsg = ' Same starting and ending location in the element.' + ErrStat = ErrID_Fatal + RETURN + ENDIF + + IF ( EqualRealNos(Dxy, 0.0_ReKi) ) THEN + DirCos=0.0_ReKi ! whole matrix set to 0 + IF ( Dz < 0) THEN !x is kept along global x + DirCos(1, 1) = 1.0_ReKi + DirCos(2, 2) = -1.0_ReKi + DirCos(3, 3) = -1.0_ReKi + ELSE + DirCos(1, 1) = 1.0_ReKi + DirCos(2, 2) = 1.0_ReKi + DirCos(3, 3) = 1.0_ReKi + ENDIF + ELSE + DirCos(1, 1) = Dy/Dxy + DirCos(1, 2) = +Dx*Dz/(L*Dxy) + DirCos(1, 3) = Dx/L + + DirCos(2, 1) = -Dx/Dxy + DirCos(2, 2) = +Dz*Dy/(L*Dxy) + DirCos(2, 3) = Dy/L + + DirCos(3, 1) = 0.0_ReKi + DirCos(3, 2) = -Dxy/L + DirCos(3, 3) = +Dz/L + ENDIF + +END SUBROUTINE GetDirCos + +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for classical beam elements +!! shear is true -- non-tapered Timoshenko beam +!! shear is false -- non-tapered Euler-Bernoulli beam +SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + LOGICAL , INTENT( IN) :: Shear + REAL(ReKi), INTENT(OUT) :: K(12, 12) + ! Local variables + REAL(ReKi) :: Ax, Ay, Kx, Ky + REAL(ReKi) :: DC(12, 12) + + Ax = kappa*A + Ay = kappa*A + + K(1:12,1:12) = 0 + + IF (Shear) THEN + Kx = 12.0*E*Iyy / (G*Ax*L*L) + Ky = 12.0*E*Ixx / (G*Ay*L*L) + ELSE + Kx = 0.0 + Ky = 0.0 + ENDIF + + K( 9, 9) = E*A/L + K( 7, 7) = 12.0*E*Iyy/( L*L*L*(1.0 + Kx) ) + K( 8, 8) = 12.0*E*Ixx/( L*L*L*(1.0 + Ky) ) + K(12, 12) = G*Jzz/L + K(10, 10) = (4.0 + Ky)*E*Ixx / ( L*(1.0+Ky) ) + K(11, 11) = (4.0 + Kx)*E*Iyy / ( L*(1.0+Kx) ) + K( 2, 4) = -6.*E*Ixx / ( L*L*(1.0+Ky) ) + K( 1, 5) = 6.*E*Iyy / ( L*L*(1.0+Kx) ) + K( 4, 10) = (2.0-Ky)*E*Ixx / ( L*(1.0+Ky) ) + K( 5, 11) = (2.0-Kx)*E*Iyy / ( L*(1.0+Kx) ) + + K( 3, 3) = K(9,9) + K( 1, 1) = K(7,7) + K( 2, 2) = K(8,8) + K( 6, 6) = K(12,12) + K( 4, 4) = K(10,10) + K(5,5) = K(11,11) + K(4,2) = K(2,4) + K(5,1) = K(1,5) + K(10,4) = K(4,10) + K(11,5) = K(5,11) + K(12,6)= -K(6,6) + K(10,2)= K(4,2) + K(11,1)= K(5,1) + K(9,3) = -K(3,3) + K(7,1) = -K(1,1) + K(8,2) = -K(2,2) + K(6, 12) = -K(6,6) + K(2, 10) = K(4,2) + K(1, 11) = K(5,1) + K(3, 9) = -K(3,3) + K(1, 7) = -K(1,1) + K(2, 8) = -K(2,2) + K(11,7) = -K(5,1) + K(10,8) = -K(4,2) + K(7,11) = -K(5,1) + K(8,10) = -K(4,2) + K(7,5) = -K(5,1) + K(5,7) = -K(5,1) + K(8,4) = -K(4,2) + K(4,8) = -K(4,2) + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed + +END SUBROUTINE ElemK + +!------------------------------------------------------------------------------------------------------ +!> Element mass matrix for classical beam elements +SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT(OUT) :: M(12, 12) + + REAL(ReKi) :: t, rx, ry, po + REAL(ReKi) :: DC(12, 12) + + t = rho*A*L; + rx = rho*Ixx; + ry = rho*Iyy; + po = rho*Jzz*L; + + M(1:12,1:12) = 0 + + M( 9, 9) = t/3.0 + M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) + M( 8, 8) = 13.0*t/35.0 + 6.0*rx/(5.0*L) + M(12, 12) = po/3.0 + M(10, 10) = t*L*L/105.0 + 2.0*L*rx/15.0 + M(11, 11) = t*L*L/105.0 + 2.0*L*ry/15.0 + M( 2, 4) = -11.0*t*L/210.0 - rx/10.0 + M( 1, 5) = 11.0*t*L/210.0 + ry/10.0 + M( 3, 9) = t/6.0 + M( 5, 7) = 13.*t*L/420. - ry/10. + M( 4, 8) = -13.*t*L/420. + rx/10. + M( 6, 12) = po/6. + M( 2, 10) = 13.*t*L/420. - rx/10. + M( 1, 11) = -13.*t*L/420. + ry/10. + M( 8, 10) = 11.*t*L/210. + rx/10. + M( 7, 11) = -11.*t*L/210. - ry/10. + M( 1, 7) = 9.*t/70. - 6.*ry/(5.*L) + M( 2, 8) = 9.*t/70. - 6.*rx/(5.*L) + M( 4, 10) = -L*L*t/140. - rx*L/30. + M( 5, 11) = -L*L*t/140. - ry*L/30. + + M( 3, 3) = M( 9, 9) + M( 1, 1) = M( 7, 7) + M( 2, 2) = M( 8, 8) + M( 6, 6) = M(12, 12) + M( 4, 4) = M(10, 10) + M( 5, 5) = M(11, 11) + M( 4, 2) = M( 2, 4) + M( 5, 1) = M( 1, 5) + M( 9, 3) = M( 3, 9) + M( 7, 5) = M( 5, 7) + M( 8, 4) = M( 4, 8) + M(12, 6) = M( 6, 12) + M(10, 2) = M( 2, 10) + M(11, 1) = M( 1, 11) + M(10, 8) = M( 8, 10) + M(11, 7) = M( 7, 11) + M( 7, 1) = M( 1, 7) + M( 8, 2) = M( 2, 8) + M(10, 4) = M( 4, 10) + M(11, 5) = M( 5, 11) + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed + +END SUBROUTINE ElemM + +!------------------------------------------------------------------------------------------------------ +!> Sets a list of DOF indices and the value these DOF should have +!! NOTE: need p%Reacts to have an updated first column that uses indices and not JointID +SUBROUTINE InitConstr(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + ! + INTEGER(IntKi) :: I,J + + Init%BCs = 0 + DO I = 1, p%NReact + DO J = 1, 6 + Init%BCs( (I-1)*6+J, 1) = (p%Reacts(I,1)-1)*6+J; ! DOF Index, looping through Joints in index order + Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); + ENDDO + ENDDO +END SUBROUTINE InitConstr + +!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices +SUBROUTINE ApplyConstr(Init,p) + TYPE(SD_InitType ),INTENT(INOUT):: Init + TYPE(SD_ParameterType),INTENT(IN ):: p + + INTEGER :: I !, J, k + INTEGER :: row_n !bgn_j, end_j, + + DO I = 1, p%NReact*6 + row_n = Init%BCs(I, 1) + IF (Init%BCs(I, 2) == 1) THEN + Init%K(row_n,: )= 0 + Init%K(: ,row_n)= 0 + Init%K(row_n,row_n)= 1 + + Init%M(row_n,: )= 0 + Init%M(: ,row_n)= 0 + Init%M(row_n,row_n)= 0 + ENDIF + ENDDO ! I, loop on reaction nodes +END SUBROUTINE ApplyConstr + +!------------------------------------------------------------------------------------------------------ +!> calculates the lumped forces and moments due to gravity on a given element: +!! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: +!! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, +!! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 +SUBROUTINE ElemG(A, L, rho, DirCos, F, g) + REAL(ReKi), INTENT( IN ) :: A !< area + REAL(ReKi), INTENT( IN ) :: L !< element length + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix (for determining distance between nodes 1 and 2) + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1; 7-12 are loads for node 2. + REAL(ReKi) :: TempCoeff + REAL(ReKi) :: w ! weight per unit length + + F = 0 ! initialize whole array to zero, then set the non-zero portions + w = rho*A*g ! weight per unit length + + ! lumped forces on both nodes (z component only): + F(3) = -0.5*L*w + F(9) = F(3) + + ! lumped moments on node 1 (x and y components only): + ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary + ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. + TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice + F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12. !bjj: DirCos(2,3) = Dy/L + F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12. !bjj: DirCos(1,3) = Dx/L + + ! lumped moments on node 2: (note the opposite sign of node 1 moment) + F(10) = -F(4) + F(11) = -F(5) + !F(12) is 0 for g along z alone + +END SUBROUTINE ElemG +!------------------------------------------------------------------------------------------------------ +!> Calculates the lumped gravity forces at the nodes given the element geometry +!! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 +!! bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. +SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) + REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !< X-sectional areas at node 1 and node 2, t2/t1 thickness ratio + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( IN ) :: L !< Length of element + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< Direction cosine matrix + REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces + !LOCALS + REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force + print*,'Error: the function lumpforces is not ready to use' + STOP + + !Calculate quadratic polynomial coefficients + a0 = -99999 ! TODO: this is wrong + a2 = ( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. ! *x**2 + a1 = (Area2-Area1)/L -a2*L ! *x + + !Now calculate the Lumped Forces + F = 0 + F(3) = -(a0*L/2. +a1*L**2/6. +a2*L**3/12. )*rho*g !Forces along z (must be negative on earth) + F(9) = -(a0*L/2. +a1*L**2/3. +a2*L**3/4. )*rho*g !Forces along z (must be negative on earth) + + !Now calculate the Lumped Moments + !HERE TO BE COMPLETED FOR THE BELOW + TempCoeff = 1.0/12.0*g*L*L*rho*Area2 !RRD : I am changing this to >0 sign 6/10/13 + + !F(4) = TempCoeff*( DirCos(1, 3)*DirCos(2, 1) - DirCos(1, 1)*DirCos(2, 3) ) !These do not work if convnetion on z2>z1, x2>x1, y2>y1 are not followed as I have discovered 7/23 + !F(5) = TempCoeff*( DirCos(1, 3)*DirCos(2, 2) - DirCos(1, 2)*DirCos(2, 3) ) + + !RRD attempt at new dircos which keeps x in the X-Y plane + F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent + F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent + !RRD ends + F(10) = -F(4) + F(11) = -F(5) + !F(12) is 0 for g along z alone +END SUBROUTINE LumpForces + +END MODULE SD_FEM diff --git a/OpenFAST/modules/subdyn/src/SubDyn.f90 b/OpenFAST/modules/subdyn/src/SubDyn.f90 new file mode 100644 index 000000000..e93577dff --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SubDyn.f90 @@ -0,0 +1,2892 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! 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. +! +!********************************************************************************************************************************** +!> SubDyn is a time-domain structural-dynamics module for multi-member fixed-bottom substructures. +!! SubDyn relies on two main engineering schematizations: (1) a linear frame finite-element beam model (LFEB), and +!! (2) a dynamics system reduction via Craig-Bampton�s (C-B) method, together with a Static-Improvement method, greatly reducing +!! the number of modes needed to obtain an accurate solution. +Module SubDyn + + USE NWTC_Library + USE NWTC_LAPACK + USE SubDyn_Types + USE SubDyn_Output + USE SD_FEM + + IMPLICIT NONE + + PRIVATE + + !............................ + ! NOTE: for debugging, add preprocessor definition SD_SUMMARY_DEBUG + ! this will add additional matrices to the SubDyn summary file. + !............................ + TYPE(ProgDesc), PARAMETER :: SD_ProgDesc = ProgDesc( 'SubDyn', '', '' ) + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: SD_Init ! Initialization routine + PUBLIC :: SD_End ! Ending routine (includes clean up) + PUBLIC :: SD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + PUBLIC :: SD_CalcOutput ! Routine for computing outputs + PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + +CONTAINS + +SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) + REAL(ReKi), INTENT( IN ) :: TP_RefPoint(3) + TYPE(MeshType), INTENT( INOUT ) :: inputMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! NOTE: The initialization of the fields for these meshes is to be handled by FAST/Driver + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + ! Create the node on the mesh + CALL MeshPositionNode ( inputMesh & + , 1 & + , TP_RefPoint & + , ErrStat & + , ErrMsg ) !note: assumes identiy matrix as reference orientation + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Create the mesh element + CALL MeshConstructElement ( inputMesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , 1 ) + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh + CALL MeshCopy ( SrcMesh = inputMesh & + ,DestMesh = outputMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) +END SUBROUTINE CreateTPMeshes + +SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, IDC, inputMesh, outputMesh, ErrStat, ErrMsg ) + INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows + REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) + INTEGER(IntKi), INTENT( IN ) :: NNodes_I ! number interface nodes i.e. Y2 stuff at the beginning + INTEGER(IntKi), INTENT( IN ) :: IDI(NNodes_I*6) + INTEGER(IntKi), INTENT( IN ) :: NNodes_L ! number interior nodes (no constraints) i.e. Y2 stuff after interface stuff + INTEGER(IntKi), INTENT( IN ) :: IDL(NNodes_L*6) + INTEGER(IntKi), INTENT( IN ) :: NNodes_C ! number base reaction nodes i.e. Y2 stuff after interior stuff + INTEGER(IntKi), INTENT( IN ) :: IDC(NNodes_C*6) + TYPE(MeshType), INTENT( INOUT ) :: inputMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I ! generic counter variable + INTEGER :: nodeIndx + + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = NNodes_I + NNodes_L + NNodes_C & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + !--------------------------------------------------------------------- + ! Interface nodes + !--------------------------------------------------------------------- + DO I = 1,NNodes_I + ! Create the node on the mesh + nodeIndx = IDI(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID + CALL MeshPositionNode ( inputMesh & + , I & + , Nodes(nodeIndx,2:4) & ! position + , ErrStat & + , ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! Create the mesh element + CALL MeshConstructElement ( inputMesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , I ) + END DO + + !--------------------------------------------------------------------- + ! Interior nodes + !--------------------------------------------------------------------- + DO I = 1,NNodes_L + ! Create the node on the mesh + nodeIndx = IDL(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes + CALL MeshPositionNode ( inputMesh & + , I + NNodes_I & + , Nodes(nodeIndx,2:4) & + , ErrStat & + , ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! Create the mesh element + CALL MeshConstructElement ( inputMesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , I + NNodes_I ) + END DO + + !--------------------------------------------------------------------- + ! Base Reaction nodes + !--------------------------------------------------------------------- + DO I = 1,NNodes_C + ! Create the node on the mesh + nodeIndx = IDC(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID + CALL MeshPositionNode ( inputMesh & + , I + NNodes_I + NNodes_L & + , Nodes(nodeIndx,2:4) & + , ErrStat & + , ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! Create the mesh element + CALL MeshConstructElement ( inputMesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , I + NNodes_I + NNodes_L ) + END DO + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + ! Create the Interior Points output mesh as a sibling copy of the input mesh + CALL MeshCopy ( SrcMesh = inputMesh & + ,DestMesh = outputMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + ! Set the Orientation (rotational) field for the nodes based on assumed 0 (rotational) deflections + !Identity should mean no rotation, which is our first guess at the output -RRD + CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) + +END SUBROUTINE CreateY2Meshes +!------------------------------------------------------------------------------------------------------ +!> Set the index array that maps SD internal nodes to the Y2Mesh nodes. +!! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, +!! so this routine could easily have segmentation faults if any errors exist. +SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh ) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh + ! locals + INTEGER(IntKi) :: i + INTEGER(IntKi) :: SDnode + INTEGER(IntKi) :: y2Node + + y2Node = 0 + ! Interface nodes (IDI) + DO I = 1,SIZE(p%IDI,1)/6 + y2Node = y2Node + 1 + SDnode = p%IDI(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + + ! Interior nodes (IDL) + DO I = 1,SIZE(p%IDL,1)/6 + y2Node = y2Node + 1 + SDnode = p%IDL(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + + ! Base Reaction nodes (IDC) + DO I = 1,SIZE(p%IDC,1)/6 + y2Node = y2Node + 1 + SDnode = p%IDC(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + +END SUBROUTINE SD_Y2Mesh_Mapping + + +!--------------------------------------------------------------------------- +!> 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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(IN ) :: InitInput !< Input data for initialization routine + TYPE(SD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(SD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(SD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(SD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(SD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Mod1_UpdateStates() is called in loose coupling & + !! (2) Mod1_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(SD_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + TYPE(SD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_InitType) :: Init + TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file + TYPE(FEM_MatArrays) :: FEMparams ! FEM parameters to be stored and written to summary file + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + ! Display the module information + CALL DispNVD( SD_ProgDesc ) + InitOut%Ver = SD_ProgDesc + + ! transfer glue-code information to data structure for SubDyn initialization: + Init%g = InitInput%g + Init%TP_RefPoint = InitInput%TP_RefPoint + Init%SubRotateZ = InitInput%SubRotateZ + p%NAvgEls = 2 + + !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. + IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) + + ! Establish the GLUECODE requested/suggested time step. This may be overridden by SubDyn based on the SDdeltaT parameter of the SubDyn input file. + Init%DT = Interval + IF ( LEN_TRIM(Init%RootName) == 0 ) THEN + CALL GetRoot( InitInput%SDInputFile, Init%RootName ) + ELSE + Init%RootName = TRIM(InitInput%RootName)//'.SD' + END IF + + ! Parse the SubDyn inputs + CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Discretize the structure according to the division size + ! sets Init%NNode, Init%NElm + CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Assemble Stiffness and mass matrix + CALL AssembleKM(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Calculate values for FEMparams (for summary file output only + ! Solve dynamics problem + FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change + + CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. + CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + + + ! --- Craig-Bampton reduction (sets many parameters) + CALL Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initial system states + IF ( p%qmL > 0 ) THEN + CALL AllocAry(x%qm, p%qmL, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(x%qmdot, p%qmL, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(m%qmdotdot, p%qmL, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return + x%qm = 0.0_ReKi + x%qmdot = 0.0_ReKi + m%qmdotdot= 0.0_ReKi + END IF + + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + + ! Allocate OtherState%xdot if using multi-step method; initialize n + IF ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) THEN + !bjj: note that the way SD_UpdateStates is implemented, "n" doesn't need to be initialized here + Allocate( OtherState%xdot(4), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating OtherState%xdot', ErrStat, ErrMsg, 'SD_Init' ) + CALL CleanUp() + RETURN + END IF + ENDIF + + ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time + CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Write the summary file + IF ( Init%SSSum ) THEN + ! note p%KBB/MBB are KBBt/MBBt + ! Write a summary of the SubDyn Initialization + CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return + IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) + IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) + ENDIF + + ! --- Initialize Inputs and Outputs + ! Create the input and output meshes associated with Transition Piece reference point + CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction + CALL CreateY2Meshes( Init%NNode, Init%Nodes, Init%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Initialize the outputs & Store mapping between nodes and elements + CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Determine if we need to perform output file handling + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ); if(Failed()) return + END IF + + + ! Tell GLUECODE the SubDyn timestep interval + Interval = p%SDdeltaT + CALL CleanUp() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE CleanUp() + CALL SD_DestroyInitType(Init, ErrStat2, ErrMsg2) + CALL SD_DestroyCB_MatArrays( CBparams, ErrStat2, ErrMsg2 ) ! local variables + CALL SD_DestroyFEM_MatArrays( FEMparams, ErrStat2, ErrMsg2 ) ! local variables + END SUBROUTINE CleanUp + +END SUBROUTINE SD_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. +!! Continuous, discrete, constraint, and other states are updated for t + Interval. +SUBROUTINE SD_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(SD_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at Times + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(SD_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 + ! Initialize variables + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + IF ( p%qml == 0) RETURN ! no retained modes = no states + + IF (p%IntMethod .eq. 1) THEN + CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSEIF (p%IntMethod .eq. 2) THEN + CALL SD_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSEIF (p%IntMethod .eq. 3) THEN + CALL SD_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSE + CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + END IF + +END SUBROUTINE SD_UpdateStates + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SD_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 + !locals + INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays + INTEGER(IntKi) :: I,J ! Counters + REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) + REAL(ReKi) :: rotations(3) + REAL(ReKi) :: ULS(p%DOFL), UL0m(p%DOFL), FLt(p%DOFL) ! Temporary values in static improvement method + REAL(ReKi) :: Y1(6) + INTEGER(IntKi) :: startDOF + REAL(ReKi) :: DCM(3,3),junk(6,p%NNodes_L) + REAL(ReKi) :: HydroForces(6*p%NNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) + TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Compute the small rotation angles given the input direction cosine matrix + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return + + ! Inputs at the transition piece: + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) + m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + ! Inputs on interior nodes: + CALL ConstructUFL( u, p, m%UFL ) + + !________________________________________ + ! Set motion outputs on y%Y2mesh + !________________________________________ + ! Y2 = C2*x + D2*u + F2 (Eq. 17) + m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] + m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] + m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] + + IF ( p%qml > 0) THEN + m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? + + p%F2_61 ! + F2(6) ] + ELSE ! There are no states when p%qml=0 (i.e., no retained modes: p%Nmodes=0), so we omit those portions of the equations + m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] + END IF + + !STATIC IMPROVEMENT METHOD ( modify UL ) + IF (p%SttcSolve) THEN + FLt = MATMUL(p%PhiL_T, m%UFL + p%FGL) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? no (solution: don't call this routine thousands of time to calculate the jacobian) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? + m%UL = m%UL + ULS + + IF ( p%qml > 0) THEN + UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%qmL), FLt(1:p%qmL) ) + m%UL = m%UL - UL0M + END IF + ENDIF + + ! --------------------------------------------------------------------------------- + ! Place the outputs onto interface node portion of Y2 output mesh + ! --------------------------------------------------------------------------------- + DO I = 1, p%NNodes_I + startDOF = (I-1)*6 + 1 + ! Construct the direction cosine matrix given the output angles + CALL SmllRotTrans( 'UR_bar input angles', m%UR_bar(startDOF + 3), m%UR_bar(startDOF + 4), m%UR_bar(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + + y%Y2mesh%TranslationDisp (:,I) = m%UR_bar ( startDOF : startDOF + 2 ) + y%Y2mesh%Orientation (:,:,I) = DCM + y%Y2mesh%TranslationVel (:,I) = m%UR_bar_dot ( startDOF : startDOF + 2 ) + y%Y2mesh%RotationVel (:,I) = m%UR_bar_dot ( startDOF + 3 : startDOF + 5 ) + y%Y2mesh%TranslationAcc (:,I) = m%UR_bar_dotdot ( startDOF : startDOF + 2 ) + y%Y2mesh%RotationAcc (:,I) = m%UR_bar_dotdot ( startDOF + 3 : startDOF + 5 ) + + ENDDO + + ! --------------------------------------------------------------------------------- + ! Place the outputs onto interior node portion of Y2 output mesh + ! --------------------------------------------------------------------------------- + DO I = 1, p%NNodes_L !Only interior nodes here + ! starting index in the master arrays for the current node + startDOF = (I-1)*6 + 1 + + ! index into the Y2Mesh + J = p%NNodes_I + I + + ! Construct the direction cosine matrix given the output angles + CALL SmllRotTrans( 'UL input angles', m%UL(startDOF + 3), m%UL(startDOF + 4), m%UL(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + + ! Y2 = Interior node displacements and velocities for use as inputs to HydroDyn + y%Y2mesh%TranslationDisp (:,J) = m%UL ( startDOF : startDOF + 2 ) + y%Y2mesh%Orientation (:,:,J) = DCM + y%Y2mesh%TranslationVel (:,J) = m%UL_dot ( startDOF : startDOF + 2 ) + y%Y2mesh%RotationVel (:,J) = m%UL_dot ( startDOF + 3 : startDOF + 5 ) + + END DO + + !Repeat for the acceleration, there should be a way to combine into 1 loop + L1 = p%NNodes_I+1 + L2 = p%NNodes_I+p%NNodes_L + junk= RESHAPE(m%UL_dotdot,(/6 ,p%NNodes_L/)) + y%Y2mesh%TranslationAcc ( :,L1:L2) = junk(1:3,:) + y%Y2mesh%RotationAcc ( :,L1:L2) = junk(4:6,:) + + ! --------------------------------------------------------------------------------- + ! Base reaction nodes + ! --------------------------------------------------------------------------------- + L1 = p%NNodes_I+p%NNodes_L+1 + L2 = p%NNodes_I+p%NNodes_L+p%NReact + + y%Y2mesh%TranslationDisp( :,L1:L2) = 0.0 + CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return + + y%Y2mesh%TranslationVel ( :,L1:L2) = 0.0 + y%Y2mesh%RotationVel ( :,L1:L2) = 0.0 + y%Y2mesh%TranslationAcc ( :,L1:L2) = 0.0 + y%Y2mesh%RotationAcc ( :,L1:L2) = 0.0 + + !________________________________________ + ! Set loads outputs on y%Y1Mesh + !________________________________________ + ! --------------------------------------------------------------------------------- + !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above + ! --------------------------------------------------------------------------------- + ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] + !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES + !Aggregate the forces and moments at the interface nodes to the reference point + !TODO: where are these HydroTP, HydroForces documented? + DO I = 1, p%NNodes_I + startDOF = (I-1)*6 + 1 + !Take care of Hydrodynamic Forces that will go into INterface Forces later + HydroForces(startDOF:startDOF+5 ) = (/u%LMesh%Force(:,I),u%LMesh%Moment(:,I)/) !(6,NNODES_I) + ENDDO + + !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below + ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D + IF ( p%qml > 0) THEN + Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + ELSE ! No retained modes, so there are no states + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + END IF + + ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces + y%Y1Mesh%Force (:,1) = Y1(1:3) + y%Y1Mesh%Moment(:,1) = Y1(4:6) + + !________________________________________ + ! CALCULATE OUTPUT TO BE WRITTEN TO FILE + !________________________________________ + ! OutSwtch determines whether or not to actually output results via the WriteOutput array + ! 0 = No one needs the SubDyn outputs provided via the WriteOutput array. + ! 1 = SubDyn will generate an output file of its own. + ! 2 = the caller will handle the outputs, but SubDyn needs to provide them. + ! 3 = Both 1 and 2 + IF ( p%OutSwtch > 0 ) THEN + ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file + !find xdot at t + IF ( p%NModes > 0 ) THEN + ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() + CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return + !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear + m%qmdotdot=dxdt%qmdot + ! Destroy dxdt because it is not necessary for the rest of the subroutine + CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2); if(Failed()) return + END IF + + ! Write the previous output data into the output file + IF ( ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) .AND. ( t > m%LastOutTime ) ) THEN + IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN + m%Decimat=1 !reset counter + CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat2, ErrMsg2 ); if(Failed()) return + ELSE + m%Decimat=m%Decimat+1 + ENDIF + END IF + + ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations + CALL SDOut_MapOutputs(t, u,p,x,y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return + + ! Put the output data in the WriteOutput array + DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + m%SDWrOutput(I) = y%WriteOutput(I) + END IF + END DO + m%LastOutTime = t + ENDIF + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE CleanUp + CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + END SUBROUTINE CleanUp + +END SUBROUTINE SD_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +!! note that this also sets m%UFL and m%udotdot_TP +SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN) :: x !< Continuous states at t -WHY IS THIS INOUT and not JUST IN? RRD, changed to IN on2/19/14 check with Greg + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(SD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here + CALL AllocAry(dxdt%qm, p%qmL, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + CALL AllocAry(dxdt%qmdot, p%qmL, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( p%qmL == 0 ) RETURN + + ! form u(3) in Eq. 10: + m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) + + ! form u(4) in Eq. 10: + CALL ConstructUFL( u, p, m%UFL ) + + !Equation 12: X=A*x + B*u + Fx (Eq 12) + dxdt%qm= x%qmdot + + ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D + != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) + !dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX + dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX + +END SUBROUTINE SD_CalcContStateDeriv + +!----------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) + CHARACTER(*), INTENT(IN) :: SDInputFile + TYPE(SD_InitType) , INTENT(INOUT) :: Init + TYPE(SD_ParameterType) , INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! local variable for input and output +CHARACTER(1024) :: PriPath ! The path to the primary input file +CHARACTER(1024) :: Line ! String to temporarially hold value of read line + +LOGICAL :: Echo +INTEGER(IntKi) :: UnIn +INTEGER(IntKi) :: IOS +INTEGER(IntKi) :: UnEc !Echo file ID + +REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings + +INTEGER(IntKi) :: I, J, flg, K +REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) +INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) +INTEGER(IntKi) :: ErrStat2 +CHARACTER(ErrMsgLen) :: ErrMsg2 +! Initialize ErrStat +ErrStat = ErrID_None +ErrMsg = "" + +UnEc = -1 +Echo = .FALSE. + +CALL GetNewUnit( UnIn ) + +CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) + +IF ( ErrStat2 /= ErrID_None ) THEN + Call Fatal('Could not open SubDyn input file') + return +END IF + +CALL GetPath( SDInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + +!-------------------------- HEADER --------------------------------------------- +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ); if(Failed()) return + +!-------------------------- SIMULATION CONTROL PARAMETERS ---------------------- +CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadVar(UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2); if(Failed()) return + +IF ( Echo ) THEN + CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat2, ErrMsg2) + IF ( ErrStat2 /= 0 ) THEN + CALL Fatal("Could not open SubDyn echo file") + return + END IF + REWIND(UnIn) + !bjj: note we don't need to do error checking here; it was already checked (this is just a repeat of above) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SIMULATION CONTROL PARAMETERS' , ErrStat2, ErrMsg2, UnEc ) + CALL ReadVar( UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2, UnEc ) +ENDIF + +! Read time step ("default" means use the glue-code default) +CALL ReadVar( UnIn, SDInputFile, Line, 'SDdeltaT', 'Subdyn Time Step',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +CALL Conv2UC( Line ) ! Convert Line to upper case. +IF ( TRIM(Line) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. + p%SDdeltaT=Init%DT +ELSE ! The input must have been specified numerically. + READ (Line,*,IOSTAT=IOS) p%SDdeltaT + CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat2,ErrMsg2 ); if(Failed()) return + + IF ( ( p%SDdeltaT <= 0 ) ) THEN + call Fatal('SDdeltaT must be greater than or equal to 0.') + return + END IF +END IF + +CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, p%SttcSolve, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +!-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- +CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko +CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv , 'NDiv' , 'Number of divisions per member',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod , 'CBMod' , 'C-B mod flag' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +IF (Check( (p%IntMethod < 1) .OR.(p%IntMethod > 4) , 'IntMethod must be 1 through 4.')) return +IF (Check( (Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) , 'FEMMod must be 0, 1, 2, or 3.')) return +IF (Check( Init%NDiv < 1 , 'NDiv must be a positive integer')) return + +IF (Init%CBMod) THEN + ! Nmodes - Number of interal modes to retain. + CALL ReadIVar ( UnIn, SDInputFile, p%Nmodes, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + + IF (Check( p%Nmodes < 0 , 'Nmodes must be a non-negative integer.')) return + + if ( p%Nmodes > 0 ) THEN + ! Damping ratios for retained modes + CALL AllocAry(Init%JDampings, p%Nmodes, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + Init%JDampings=WrongNo !Initialize + + CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%Nmodes, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); + ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the + ! last entry to fill in remaining values. + !Check 1st value, we need at least one good value from user or throw error + IF ((Init%JDampings(1) < 0 ) .OR. (Init%JDampings(1) >= 100.0)) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100') + return + ELSE + DO I = 2, p%Nmodes + IF ( Init%JDampings(I) .EQ. WrongNo ) THEN + Init%Jdampings(I:p%Nmodes)=Init%JDampings(I-1) + IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) + ErrStat = ErrID_Info + ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%Nmodes))//'.' + END IF + EXIT + ELSEIF ( ( Init%JDampings(I) < 0 ) .OR.( Init%JDampings(I) >= 100.0 ) ) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100') + return + ENDIF + ENDDO + ENDIF + IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings + WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%Nmodes,NWTC_MaxAryLen)) + END IF + ELSE + CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + END IF + +ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet + !note at this stage I do not know DOFL yet; Nmodes will be updated later for the FULL FEM CASE. + p%Nmodes = -1 + !Ignore next line + CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + !Read 1 damping value for all modes + CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + IF ( ( Init%JDampings(1) < 0 ) .OR.( Init%JDampings(1) >= 100.0 ) ) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100.') + RETURN + ENDIF +ENDIF + +IF ((p%Nmodes > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%Nmodes is undefined, but if Nmodes=0 then JDampings does not exist + Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings +END IF + +!--------------------- STRUCTURE JOINTS: joints connect structure members ------------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Joints, Init%NJoints, JointsCol, 'Joints', ErrStat2, ErrMsg2 ); if(Failed()) return +DO I = 1, Init%NJoints + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, JointsCol, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + Init%Joints(I,:) = Dummy_ReAry(1:JointsCol) +ENDDO +IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return + +!---------- GO AHEAD and ROTATE STRUCTURE IF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- +CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) + +!------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- +! The joints should be all clamped for now +CALL ReadCom ( UnIn, SDInputFile, 'BASE REACTION JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NReact, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(p%Reacts, p%NReact, ReactCol, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +DO I = 1, p%NReact + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return + p%Reacts(I,:) = Dummy_IntAry(1:ReactCol) +ENDDO +IF (Check ( ( p%NReact < 1 ) .OR. (p%NReact > Init%NJoints) , 'NReact must be greater than 0 and less than number of joints')) return + +!------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- +! Joints with reaction forces, joint number and locked/free dof +CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Interf, Init%NInterf, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NInterf + CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Interf(I,:) = Dummy_IntAry(1:InterfCol) +ENDDO +IF (Check( ( Init%NInterf < 0 ) .OR. (Init%NInterf > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN + +!----------------------------------- MEMBERS -------------------------------------- +! One day we will need to take care of COSMIDs for non-circular members +CALL ReadCom ( UnIn, SDInputFile, 'Members ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) +DO I = 1, p%NMembers + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, MembersCol, 'Members', 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Members(I,:) = Dummy_IntAry(1:MembersCol) +ENDDO +IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return + +!------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ +CALL ReadCom ( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSets, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSets, Init%NPropSets, PropSetsCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSets + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSets(I,:) = Dummy_ReAry(1:PropSetsCol) +ENDDO +IF (Check( Init%NPropSets < 1 , 'NPropSets must be >0')) return + +!------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member X-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NXPropSets, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%XPropSets, Init%NXPropSets, XPropSetsCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NXPropSets + CALL ReadAry( UnIn, SDInputFile, Init%XPropSets(I,:), XPropSetsCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NXPropSets < 0, 'NXPropSets must be >=0')) return + +!---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member direction cosine matrices ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%COSMs, Init%NCOSMs, COSMsCol, 'COSMs', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NCOSMs + CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NCOSMs < 0 ,'NCOSMs must be >=0')) return + +!------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'Additional concentrated masses at joints ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NCMass, 'NCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%CMass, Init%NCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return +Init%CMass = 0.0 +DO I = 1, Init%NCMass + CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NCMass < 0 , 'NCMass must be >=0')) return + +!---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ +CALL ReadCom (UnIn, SDInputFile, 'OUTPUT' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. +CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +!Store an integer version of it +p%OutAllInt= 1 +IF ( .NOT. p%OutAll ) p%OutAllInt= 0 +CALL ReadIVar(UnIn, SDInputFile, p%OutSwtch, 'OutSwtch', 'Output to which file variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +IF (Check( ( p%OutSwtch < 1 ) .OR. ( p%OutSwtch > 3) ,'OutSwtch must be >0 and <4')) return + +Swtch: SELECT CASE (p%OutSwtch) + CASE (1, 3) Swtch + !p%OutJckF = TRIM(Init%RootName)//'.out' + CASE (2) Swtch + !pass to glue code + CASE DEFAULT Swtch + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') + return + END SELECT Swtch + +! TabDelim - Output format for tabular data. +CALL ReadLVar ( UnIn, SDInputFile, Init%TabDelim, 'TabDelim', 'Use Tab Delimitation for numerical outputs',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +IF ( Init%TabDelim ) THEN + p%Delim = TAB +ELSE + p%Delim = ' ' +END IF + +CALL ReadIVar( UnIn, SDInputFile, p%OutDec , 'OutDec' , 'Output Decimation' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutFmt , 'OutFmt' , 'Format for numerical outputs' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutSFmt , 'OutSFmt' , 'Format for output column headers' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, ' Member Output List SECTION ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar( UnIn, SDInputFile, p%NMOutputs, 'NMOutputs', 'Number of Members whose output must go into OutJckF and/or FAST .out',ErrStat2, ErrMsg2, UnEc ) +if (Failed()) return +IF (Check ( (p%NMOutputs < 0) .OR. (p%NMOutputs > p%NMembers) .OR. (p%NMOutputs > 9), 'NMOutputs must be >=0 and <= minimim(NMembers,9)')) return + +CALL ReadCom( UnIn, SDInputFile, ' Output Member Headers',ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, ' Output Member Units' ,ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return + +IF ( p%NMOutputs > 0 ) THEN + ! Allocate memory for filled group arrays + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat2 ) !this list contains different arrays for each of its elements + IF ( ErrStat2 /= ErrID_None ) THEN + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') + RETURN + END IF + + DO I = 1,p%NMOutputs + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt + IF ( ErrStat2 /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') + RETURN + END IF + CALL AllocAry( p%MOutLst(I)%NodeCnt, p%MOutLst(I)%NOutCnt, 'NodeCnt', ErrStat2, ErrMsg2); if(Failed()) return + + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt, p%MOutLst(I)%NodeCnt + IF ( Check( ErrStat2 /= 0 , 'Failed to read member output list properties.')) return + + ! Check if MemberID is in the member list and the NodeCnt is a valid number + flg = 0 + DO J = 1, p%NMembers + IF(p%MOutLst(I)%MemberID .EQ. Init%Members(j, 1)) THEN + flg = flg + 1 ! flg could be greater than 1, when there are more than 9 internal nodes of a member. + IF( (p%MOutLst(I)%NOutCnt < 10) .and. ((p%MOutLst(I)%NOutCnt > 0)) ) THEN + DO K = 1,p%MOutLst(I)%NOutCnt + ! node number should be less than NDiv + 1 + IF( (p%MOutLst(I)%NodeCnt(k) > (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) < 1) ) THEN + CALL Fatal(' NodeCnt should be less than NDIV+1 and greater than 0. ') + RETURN + ENDIF + ENDDO + ELSE + CALL Fatal(' NOutCnt should be less than 10 and greater than 0. ') + RETURN + ENDIF + ENDIF + ENDDO + IF (Check (flg .EQ. 0 , ' MemberID is not in the Members list. ')) return + + IF ( Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + END IF + END DO +END IF + +! OutList - list of requested parameters to output to a file +CALL ReadCom( UnIn, SDInputFile, 'SSOutList',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat2) +If (Check( ErrStat2 /= ErrID_None ,'Error allocating SSOutList arrays')) return + +CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, & + 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ) +if(Failed()) return +CALL CleanUp() + +CONTAINS + + LOGICAL FUNCTION Check(Condition, ErrMsg_in) + logical, intent(in) :: Condition + character(len=*), intent(in) :: ErrMsg_in + Check=Condition + if (Check) call Fatal(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) + END FUNCTION Check + + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Input') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Input'); + CALL CleanUp() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp() + CLOSE( UnIn ) + IF (Echo) CLOSE( UnEc ) + END SUBROUTINE + +END SUBROUTINE SD_Input + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Rotate the joint coordinates with respect to global z +SUBROUTINE SubRotate(Joints,NJoints,SubRotZ) + REAL(ReKi), INTENT(IN) :: SubRotZ ! Rotational angle in degrees + INTEGER(IntKi), INTENT(IN) :: NJOINTS ! Row size of Joints + REAL(ReKi), DIMENSION(NJOINTS,3), INTENT(INOUT) :: JOINTS ! Rotational angle in degrees (Njoints,4) + !locals + REAL(ReKi) :: rot !angle in rad + REAL(ReKi), DIMENSION(2,2) :: ROTM !rotational matrix (cos matrix with -theta) + + rot=pi*SubRotz/180. + ROTM=transpose(reshape([ COS(rot), -SIN(rot) , & + SIN(rot) , COS(rot)], [2,2] )) + Joints(:,2:3)= transpose(matmul(ROTM,transpose(Joints(:,2:3)))) + +END SUBROUTINE SubRotate + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE SD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(SD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(SD_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 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Determine if we need to close the output file + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN + ! Write out the last stored set of outputs before closing + CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat, ErrMsg ) + ENDIF + CALL SDOut_CloseOutput( p, ErrStat, ErrMsg ) + END IF + + ! Destroy data + CALL SD_DestroyInput( u, ErrStat, ErrMsg ) + CALL SD_DestroyParam( p, ErrStat, ErrMsg ) + CALL SD_DestroyContState( x, ErrStat, ErrMsg ) + CALL SD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL SD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL SD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + CALL SD_DestroyMisc( m, ErrStat, ErrMsg ) + CALL SD_DestroyOutput( y, ErrStat, ErrMsg ) + +END SUBROUTINE SD_End + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_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 + ! local variables + TYPE(SD_ContinuousStateType) :: xdot ! Continuous state derivs at t + TYPE(SD_InputType) :: u_interp + + ErrStat = ErrID_None + ErrMsg = "" + + ! need xdot at t + CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat, ErrMsg) + CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) ! initializes xdot + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! we don't need this local copy anymore + + if (n <= 2) then + OtherState%n = n + !OtherState%xdot ( 3 - n ) = xdot + CALL SD_CopyContState( xdot, OtherState%xdot ( 3 - n ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + else + if (OtherState%n < n) then + OtherState%n = n + CALL SD_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( OtherState%xdot ( 1 ), OtherState%xdot ( 2 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + !OtherState%xdot(4) = OtherState%xdot(3) + !OtherState%xdot(3) = OtherState%xdot(2) + !OtherState%xdot(2) = OtherState%xdot(1) + elseif (OtherState%n > n) then + ErrStat = ErrID_Fatal + ErrMsg = ' Backing up in time is not supported with a multistep method ' + RETURN + endif + CALL SD_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date + x%qm = x%qm + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qm - 59.*OtherState%xdot(2)%qm + 37.*OtherState%xdot(3)%qm & + - 9. * OtherState%xdot(4)%qm ) + x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qmdot - 59.*OtherState%xdot(2)%qmdot & + + 37.*OtherState%xdot(3)%qmdot - 9.*OtherState%xdot(4)%qmdot ) + endif + CALL SD_DestroyContState(xdot, ErrStat, ErrMsg) + CALL SD_DestroyInput(u_interp, ErrStat, ErrMsg) +END SUBROUTINE SD_AB4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_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 + ! local variables + TYPE(SD_InputType) :: u_interp ! Continuous states at t + TYPE(SD_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(SD_ContinuousStateType) :: xdot_pred ! Continuous states at t + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SD_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) !initialize x_pred + CALL SD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) + + if (n > 2) then + CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) + + CALL SD_CalcContStateDeriv(t + p%SDDeltaT, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat, ErrMsg ) ! initializes xdot_pred + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! local copy no longer needed + + x%qm = x%qm + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qm + 19. * OtherState%xdot(1)%qm - 5. * OtherState%xdot(2)%qm & + + 1. * OtherState%xdot(3)%qm ) + + x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qmdot + 19. * OtherState%xdot(1)%qmdot - 5. * OtherState%xdot(2)%qmdot & + + 1. * OtherState%xdot(3)%qmdot ) + CALL SD_DestroyContState( xdot_pred, ErrStat, ErrMsg) ! local copy no longer needed + else + x%qm = x_pred%qm + x%qmdot = x_pred%qmdot + endif + + CALL SD_DestroyContState( x_pred, ErrStat, ErrMsg) ! local copy no longer needed + +END SUBROUTINE SD_ABM4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_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 + ! local variables + TYPE(SD_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(SD_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(SD_InputType) :: u_interp ! interpolated value of inputs + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + !bjj: the state type contains allocatable arrays, so we must first allocate space: + CALL SD_CopyContState( x, k1, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k2, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k3, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k4, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat, ErrMsg ) + + ! interpolate u to find u_interp = u(t) + CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat, ErrMsg ) + + ! find xdot at t + CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) !initializes xdot + k1%qm = p%SDDeltaT * xdot%qm + k1%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k1%qm + x_tmp%qmdot = x%qmdot + 0.5 * k1%qmdot + ! interpolate u to find u_interp = u(t + dt/2) + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%SDDeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt/2 + CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k2%qm = p%SDDeltaT * xdot%qm + k2%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k2%qm + x_tmp%qmdot = x%qmdot + 0.5 * k2%qmdot + + ! find xdot at t + dt/2 + CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k3%qm = p%SDDeltaT * xdot%qm + k3%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + k3%qm + x_tmp%qmdot = x%qmdot + k3%qmdot + ! interpolate u to find u_interp = u(t + dt) + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt + CALL SD_CalcContStateDeriv( t + p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k4%qm = p%SDDeltaT * xdot%qm + k4%qmdot = p%SDDeltaT * xdot%qmdot + x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. + x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. + + CALL CleanUp() + +CONTAINS + + SUBROUTINE CleanUp() + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + + + CALL SD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + CALL SD_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + END SUBROUTINE CleanUp + +END SUBROUTINE SD_RK4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the 2nd-order Adams-Moulton Implicit Method (AM2,Trapezoidal rule) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = f(t , x_t ) +!! k2 = f(t + dt , x_t+dt ) +!! Then the continuous states at t = t + dt are +!! x_(t+dt) =x_n+1 = x_t + deltat/2*(k1 + k2) + O(dt^3) +!! Now this can be re-written as: 0=Z(x_n+1) = x_n - x_n+1 +dt/2 *(f_n + f_n+1) = 0 +!! f_n= A*x_n + B*u_n + Fx from Eq. 1.12 of the manual +!! So to solve this linear system, I can just use x(k)=x(k-1) -J^-1 * Z(x(k-1)) (this is a simple root solver of the linear equation) +!! with J=dZ/dx_n+1 = -I +dt/2*A +!! +!! Thus x_n+1 = x_n - J^-1 *dt/2 * (2*A*x_n + B *(u_n + u_n+1) +2*Fx) +!! or J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) +SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_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 + ! local variables + TYPE(SD_InputType) :: u_interp ! interpolated value of inputs + REAL(ReKi) :: junk2(2*p%qml) !temporary states (qm and qmdot only) + REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP + REAL(ReKi) :: UFL2(p%DOFL) ! temporary copy of UFL + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2,ErrMsg2);CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + + !Start by getting u_n and u_n+1 + ! interpolate u to find u_interp = u(t) = u_n + CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL ConstructUFL( u_interp, p, m%UFL ) + + ! extrapolate u to find u_interp = u(t + dt)=u_n+1 + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL ConstructUFL( u_interp, p, UFL2 ) + + ! calculate (u_n + u_n+1)/2 + udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) + UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) + + ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + junk2( 1: p%qml)=p%SDDeltaT * x%qmdot !upper portion of array + junk2(1+p%qml:2*p%qml)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D + + !.................................................... + ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) + ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + !.................................................... + CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + !IF ( ErrStat >= AbortErrLev ) RETURN + + ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: + x%qm = x%qm - junk2( 1: p%qml) + x%qmdot = x%qmdot - junk2(p%qml+1:2*p%qml) + + ! clean up temporary variable(s) + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) + +END SUBROUTINE SD_AM2 + +!------------------------------------------------------------------------------------------------------ +!> Perform Craig Bampton reduction +SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType),INTENT(INOUT) :: p ! Parameters + TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use + 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 :: MRR(:, :) + REAL(ReKi), ALLOCATABLE :: MLL(:, :) + REAL(ReKi), ALLOCATABLE :: MRL(:, :) + REAL(ReKi), ALLOCATABLE :: KRR(:, :) + REAL(ReKi), ALLOCATABLE :: KLL(:, :) + REAL(ReKi), ALLOCATABLE :: KRL(:, :) + REAL(ReKi), ALLOCATABLE :: FGR(:) + REAL(ReKi), ALLOCATABLE :: FGL(:) + REAL(ReKi), ALLOCATABLE :: MBBb(:, :) + REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: KBBb(:, :) + REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) + REAL(ReKi), ALLOCATABLE :: FGRb(:) + REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! number of nodes: + p%NNodes_I = Init%NInterf ! Number of interface nodes + p%NNodes_L = Init%NNode - p%NReact - p%NNodes_I ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I + + !DOFS of interface + !BJJ: TODO: are these 6's actually TPdofL? + p%DOFI = p%NNodes_I*6 + p%DOFC = p%NReact*6 + p%DOFR = (p%NReact+p%NNodes_I)*6 ! = p%DOFC + p%DOFI + p%DOFL = p%NNodes_L*6 ! = Init%TDOF - p%DOFR + + + IF(Init%CBMod) THEN ! C-B reduction + ! check number of internal modes + IF(p%Nmodes > p%DOFL) THEN + CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than maximum. ',ErrStat,ErrMsg,'Craig_Bampton') + CALL CleanupCB() + RETURN + ENDIF + + ELSE ! full FEM + p%Nmodes = p%DOFL + !Jdampings need to be reallocated here because DOFL not known during Init + !So assign value to one temporary variable + JDamping1=Init%Jdampings(1) + DEALLOCATE(Init%JDampings) + CALL AllocAry( Init%JDampings, p%DOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return + Init%JDampings = JDamping1 ! set default values for all modes + + ENDIF + + CBparams%DOFM = p%Nmodes ! retained modes (all if no C-B reduction) + + ! matrix dimension paramters + p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) + p%URbarL = p%DOFI !=p%NNodes_I*6 ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED + + + CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + + CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + + CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. + CALL SetIndexArrays(Init, p, ErrStat2, ErrMsg2) ; if(Failed()) return + + ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on + ! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: + CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + + ! Set p%TI and CBparams%TI2 + CALL TrnsfTI(Init, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + + !................................ + ! Sets the following values, as documented in the SubDyn Theory Guide: + ! CBparams%OmegaL (omega) and CBparams%PhiL from Eq. 2 + ! p%PhiL_T and p%PhiLInvOmgL2 for static improvement + ! CBparams%PhiR from Eq. 3 + ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. + !................................ + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%DOFM, Init, & ! < inputs + CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) + if(Failed()) return + + ! to use a little less space, let's deallocate these arrays that we don't need anymore, then allocate the next set of temporary arrays: + IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) + IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) + IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) + IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) + IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) + IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) + + ! "b" stands for "bar"; "t" stands for "tilde" + CALL AllocAry( MBBb, p%DOFI, p%DOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBmb, p%DOFI, CBparams%DOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KBBb, p%DOFI, p%DOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( PhiRb, p%DOFL, p%DOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGRb, p%DOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return + + !................................ + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to + ! MBBb, MBMb, KBBb, PHiRb, FGRb + ! (throw out rows/columns of first matrices to create second matrices) + !................................ + CALL CBApplyConstr(p%DOFI, p%DOFR, CBparams%DOFM, p%DOFL, & + CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & + MBBb, MBMb, KBBb, PHiRb, FGRb) + !................................ + ! set values needed to calculate outputs and update states: + !................................ + CALL SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, CBparams%OmegaL, FGL, CBparams%PhiL, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') + + CALL CleanUpCB() + +contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpCB() + end function Failed + + subroutine CleanUpCB() + IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) + IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) + IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) + IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) + IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) + IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) + IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) + IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) + IF(ALLOCATED(MBBb) ) DEALLOCATE(MBBb) + IF(ALLOCATED(MBmb) ) DEALLOCATE(MBmb) + IF(ALLOCATED(KBBb) ) DEALLOCATE(KBBb) + IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) + IF(ALLOCATED(FGRb) ) DEALLOCATE(FGRb) + end subroutine CleanUpCB + +END SUBROUTINE Craig_Bampton + +!------------------------------------------------------------------------------------------------------ +!> +SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(IN ) :: p + REAL(ReKi), INTENT( OUT) :: MRR(p%DOFR, p%DOFR) + REAL(ReKi), INTENT( OUT) :: MLL(p%DOFL, p%DOFL) + REAL(ReKi), INTENT( OUT) :: MRL(p%DOFR, p%DOFL) + REAL(ReKi), INTENT( OUT) :: KRR(p%DOFR, p%DOFR) + REAL(ReKi), INTENT( OUT) :: KLL(p%DOFL, p%DOFL) + REAL(ReKi), INTENT( OUT) :: KRL(p%DOFR, p%DOFL) + REAL(ReKi), INTENT( OUT) :: FGR(p%DOFR) + REAL(ReKi), INTENT( OUT) :: FGL(p%DOFL) + ! local variables + INTEGER(IntKi) :: I, J, II, JJ + + DO I = 1, p%DOFR !Boundary DOFs + II = p%IDR(I) + FGR(I) = Init%FG(II) + DO J = 1, p%DOFR + JJ = p%IDR(J) + MRR(I, J) = Init%M(II, JJ) + KRR(I, J) = Init%K(II, JJ) + ENDDO + ENDDO + + DO I = 1, p%DOFL + II = p%IDL(I) + FGL(I) = Init%FG(II) + DO J = 1, p%DOFL + JJ = p%IDL(J) + MLL(I, J) = Init%M(II, JJ) + KLL(I, J) = Init%K(II, JJ) + ENDDO + ENDDO + + DO I = 1, p%DOFR + II = p%IDR(I) + DO J = 1, p%DOFL + JJ = p%IDL(J) + MRL(I, J) = Init%M(II, JJ) + KRL(I, J) = Init%K(II, JJ) !Note KRL and MRL are getting data from a constraint-applied formatted M and K (i.e. Mbar and Kbar) this may not be legit!! RRD + ENDDO !I think this is fixed now since the constraint application occurs later + ENDDO + +END SUBROUTINE BreakSysMtrx + +!------------------------------------------------------------------------------------------------------ +!> Sets the CB values, as documented in the SubDyn Theory Guide: +! OmegaL (omega) and PhiL from Eq. 2 +! p%PhiL_T and p%PhiLInvOmgL2 for static improvement (will be added to theory guide later?) +! PhiR from Eq. 3 +! MBB, MBM, and KBB from Eq. 4. +!................................ +SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) + TYPE(SD_InitType), INTENT(IN) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( in) :: DOFM + REAL(ReKi), INTENT( IN) :: MRR( p%DOFR, p%DOFR) + REAL(ReKi), INTENT( IN) :: MLL( p%DOFL, p%DOFL) + REAL(ReKi), INTENT( IN) :: MRL( p%DOFR, p%DOFL) + REAL(ReKi), INTENT( IN) :: KRR( p%DOFR, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: KLL( p%DOFL, p%DOFL) ! on exit, it has been factored (otherwise not changed) + REAL(ReKi), INTENT( IN) :: KRL( p%DOFR, p%DOFL) + REAL(ReKi), INTENT(INOUT) :: MBB( p%DOFR, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: MBM( p%DOFR, DOFM) + REAL(ReKi), INTENT(INOUT) :: KBB( p%DOFR, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: PhiR(p%DOFL, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: PhiL(p%DOFL, p%DOFL) !used to be PhiM(DOFL,DOFM), now it is more generic + REAL(ReKi), INTENT(INOUT) :: OmegaL(p%DOFL) !used to be omegaM only ! Eigenvalues + 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 :: Mu(:, :) ! matrix for normalization Mu(p%DOFL, p%DOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%DOFR,p%DOFL) = transpose of PhiR * MLL (temporary storage) + INTEGER :: I !, lwork !counter, and varibales for inversion routines + INTEGER :: DOFvar !placeholder used to get both PhiL or PhiM into 1 process + INTEGER :: ipiv(p%DOFL) !the integer vector ipvt of length min(m,n), containing the pivot indices. + !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, + !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' + + ErrStat = ErrID_None + ErrMsg = '' + + CALL WrScr(' Calculating Internal Modal Eigenvectors') + + IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT + DOFvar=p%DOFL + ELSE + DOFvar=DOFM !Initialize for normal cases, dynamic only + ENDIF + + !.................................................... + ! Set OmegaL and PhiL from Eq. 2 + !.................................................... + IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... + CALL EigenSolve(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Normalize PhiL + ! bjj: break up this equation to avoid as many tenporary variables on the stack + ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) + CALL AllocAry( Temp , p%DOFL , p%DOFL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , p%DOFL , p%DOFL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + MU = TRANSPOSE(PhiL) + Temp = MATMUL( MU, MLL ) + MU = MATMUL( Temp, PhiL ) + DEALLOCATE(Temp) + ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) + DO I = 1, DOFvar + PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) + ENDDO + DO I=DOFvar+1, p%DOFL !loop done only if .not. p%SttcSolve .and. DOFM < p%DOFL (and actually, in that case, these values aren't used anywhere anyway) + PhiL(:,I) = 0.0_ReKi + OmegaL(I) = 0.0_ReKi + END DO + DEALLOCATE(MU) + + !.................................................... + ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement + !.................................................... + IF (p%SttcSolve) THEN + p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement + DO I = 1, p%DOFL + p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) + ENDDO + END IF + + ! ELSE .not. p%SttcSolve .and. DOFM < p%DOFL (in this case, PhiL, OmegaL aren't used) + END IF + + + !.................................................... + ! Set PhiR from Eq. 3: + !.................................................... + ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) + ! ** note this must be done after EigenSolve() because it modifies KLL ** + CALL LAPACK_getrf( p%DOFL, p%DOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return + + PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) + CALL LAPACK_getrs( TRANS='N',N=p%DOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return + + !.................................................... + ! Set MBB, MBM, and KBB from Eq. 4: + !.................................................... + CALL AllocAry( PhiR_T_MLL, p%DOFR, p%DOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + + PhiR_T_MLL = TRANSPOSE(PhiR) + PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) + MBB = MATMUL(MRL, PhiR) + MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) + + + IF ( DOFM .EQ. 0) THEN + MBM = 0.0_ReKi + ELSE + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:DOFM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:DOFM) ) + MBM !This had PhiM + ENDIF + DEALLOCATE( PhiR_T_MLL ) + + KBB = MATMUL(KRL, PhiR) + KBB = KBB + KRR + +CONTAINS + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CBMatrix') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + if (allocated(Mu )) DEALLOCATE(Mu ) + if (allocated(Temp )) DEALLOCATE(Temp ) + if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) + end subroutine +END SUBROUTINE CBMatrix + +!------------------------------------------------------------------------------------------------------ +!> +SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + INTEGER(IntKi), INTENT(IN ) :: DOFI ! # of DOFS of interface nodes + INTEGER(IntKi), INTENT(IN ) :: DOFR ! # of DOFS of restrained nodes (restraints and interface) + INTEGER(IntKi), INTENT(IN ) :: IDI(DOFI) + INTEGER(IntKi), INTENT(IN ) :: IDR(DOFR) + REAL(ReKi), INTENT(INOUT) :: TI( DOFI,6) ! matrix TI that relates the reduced matrix to the TP, + REAL(ReKi), INTENT(INOUT) :: TI2(DOFR,6) ! matrix TI2 that relates to (0,0,0) the overall substructure mass + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER :: I, di + INTEGER :: rmndr, n + REAL(ReKi) :: dx, dy, dz + + ErrStat = ErrID_None + ErrMsg = "" + + TI(:,:) = 0. !Initialize + DO I = 1, DOFI + di = IDI(I) + rmndr = MOD(di, 6) + n = CEILING(di/6.0) + + dx = Init%Nodes(n, 2) - Init%TP_RefPoint(1) + dy = Init%Nodes(n, 3) - Init%TP_RefPoint(2) + dz = Init%Nodes(n, 4) - Init%TP_RefPoint(3) + + SELECT CASE (rmndr) + CASE (1); TI(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); TI(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (0); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + CASE DEFAULT + ErrStat = ErrID_Fatal + ErrMsg = 'Error calculating transformation matrix TI ' + RETURN + END SELECT + + ENDDO + + !Augment with TI2 + TI2(:,:) = 0. !Initialize + DO I = 1, DOFR + di = IDR(I) + rmndr = MOD(di, 6) + n = CEILING(di/6.0) + + dx = Init%Nodes(n, 2) + dy = Init%Nodes(n, 3) + dz = Init%Nodes(n, 4) + SELECT CASE (rmndr) + CASE (1); TI2(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); TI2(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (0); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + CASE DEFAULT + ErrStat = ErrID_Fatal + ErrMsg = 'Error calculating transformation matrix TI2 ' + RETURN + END SELECT + ENDDO + +END SUBROUTINE TrnsfTI + +!------------------------------------------------------------------------------------------------------ +!> Return eigenvalues, Omega, and eigenvectors, Phi, +SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, ErrMsg ) + USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT + INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system + REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix + REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix + INTEGER, INTENT(IN ) :: NOmega ! RRD: no. of requested eigenvalues + LOGICAL, INTENT(IN ) :: Reduced ! Whether or not to reduce matrices, this will be removed altogether later, when reduction will be done apriori + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p + REAL(ReKi), INTENT( OUT) :: Phi(nDOF, NOmega) ! RRD: Returned Eigenvectors + REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! RRD: Returned Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! LOCALS + REAL(LAKi), ALLOCATABLE :: Omega2(:) !RRD: Eigen-values new system +! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. +! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 + REAL(LAKi), ALLOCATABLE :: Kred(:,:), Mred(:,:) + REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), VR(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables + INTEGER :: i + INTEGER :: N, LWORK !variables for the eigensolver + INTEGER, ALLOCATABLE :: KEY(:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = '' + + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + IF (Reduced) THEN !bjj: i.e., We need to reduce; it's not reduced yet + ! First I need to remove constrained nodes DOFs + ! This is actually done when we are printing out the 'full' set of eigenvalues + CALL ReduceKMdofs(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL ReduceKMdofs(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + N=SIZE(Kred,1) + ELSE + ! This is actually done whe we are generating the CB-reduced set of eigenvalues, so the the variable 'Reduced' can be a bit confusing. GJH 8/1/13 + N=SIZE(K,1) + CALL AllocAry( Kred, n, n, 'Kred', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( Mred, n, n, 'Mred', ErrStat2, ErrMsg2 ); if(Failed()) return + Kred=REAL( K, LAKi ) + Mred=REAL( M, LAKi ) + ENDIF + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! + IF ( NOmega > N ) THEN + CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolve') + CALL CleanupEigen() + RETURN + END IF + + ! allocate working arrays and return arrays for the eigensolver + LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine + !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out + CALL AllocAry( Work, lwork, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( Omega2, n, 'Omega2', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAR, n, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAI, n, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( BETA, n, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( VR, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( VL, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( KEY, n, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL LAPACK_ggev('N','V',N ,Kred, Mred, ALPHAR, ALPHAI, BETA, VL, VR, work, lwork, ErrStat2, ErrMsg2) + if(Failed()) return + !if (.not. reduced) call wrmatrix(REAL(VR,ReKi),77,'ES15.8e2') + ! bjj: This comes from the LAPACK documentation: + ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). + ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted + DO I=1,N !Initialize the key and calculate Omega2 + KEY(I)=I + IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN + Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + ELSE + Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) + END IF + ENDDO + CALL ScaLAPACK_LASRT('I',N,Omega2,key,ErrStat2,ErrMsg2); if(Failed()) return + + !we need to rearrange eigenvectors based on sorting of Omega2 + !Now rearrange VR based on the new key, also I might have to scale the eigenvectors following generalized mass =idnetity criterion, also if i reduced the matrix I will need to re-expand the eigenvector + ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) + ! result1 = matmul(Mred2,VR) + ! result2 = matmul(transpose(VR),result1) + ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors + !normcoeff=sqrt(matmul(transpose(VR),matmul(Mred2,VR))) !This should be a diagonal matrix which contains the normalization factors + VL=VR !temporary storage for sorting VR + DO I=1,N + !VR(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized + VR(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one + ENDDO + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + + ! --- Finish EigenSolve + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! + Omega=SQRT( Omega2(1:NOmega) ) !Assign my new Omega and below my new Phi (eigenvectors) [eigenvalues are actually the square of omega] + IF ( Reduced ) THEN ! this is called for the full system Eigenvalues: + !Need to expand eigenvectors for removed DOFs, setting Phi + CALL UnReduceVRdofs(VR(:,1:NOmega),Phi,N,NOmega, Init,p, ErrStat2, ErrMsg2 ) ; if(Failed()) return + ELSE ! IF (.NOT.(Reduced)) THEN !For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR + ! This is done as part of the CB-reduced eigensolve + Phi=REAL( VR(:,1:NOmega), ReKi ) ! eigenvectors + ENDIF + + CALL CleanupEigen() + RETURN + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + + SUBROUTINE CleanupEigen() + IF (ALLOCATED(Work) ) DEALLOCATE(Work) + IF (ALLOCATED(Omega2)) DEALLOCATE(Omega2) !bjj: break in Debug_Doub + IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) + IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) + IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) + IF (ALLOCATED(VR) ) DEALLOCATE(VR) + IF (ALLOCATED(VL) ) DEALLOCATE(VL) + IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) + IF (ALLOCATED(Kred) ) DEALLOCATE(Kred) + IF (ALLOCATED(Mred) ) DEALLOCATE(Mred) + END SUBROUTINE CleanupEigen + +END SUBROUTINE EigenSolve + +!------------------------------------------------------------------------------------------------------ +!> Calculate Kred from K after removing consstrained node DOFs from the full M and K matrices +!!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed +SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT( in) :: Init + TYPE(SD_ParameterType), INTENT( in) :: p + INTEGER, INTENT(IN ) :: TDOF ! Size of matrix K (total DOFs) + REAL(ReKi), INTENT(IN ) :: K(TDOF, TDOF) ! full matrix + REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Kred(:,:) ! reduced matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER :: I, J ! counters into full or reduced matrix + INTEGER :: L ! number of DOFs to eliminate + INTEGER, ALLOCATABLE :: idx(:) ! vector to map reduced matrix to full matrix + INTEGER :: NReactDOFs + INTEGER :: DOF_reduced + INTEGER :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = '' + + NReactDOFs = p%NReact*6 !p%DOFC + IF (NReactDOFs > TDOF) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'ReduceKMdofs:invalid matrix sizes.' + RETURN + END IF + + CALL AllocAry(idx, TDOF, 'idx', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') + IF (ErrStat >= AbortErrLev) THEN + RETURN + END IF + + ! Calculate how many rows/columns need to be eliminated: + DO I = 1, TDOF + idx(I) = I + END DO + + L = 0 + DO I = 1, NReactDOFs !Cycle on reaction DOFs + IF (Init%BCs(I, 2) == 1) THEN + L=L+1 !number of DOFs to eliminate + idx( Init%BCs(I, 1) ) = 0 ! Eliminate this one + END IF + END DO + + ! Allocate the output matrix and the index mapping array + DOF_reduced = TDOF-L + CALL AllocAry(Kred, DOF_reduced, DOF_reduced, 'Kred', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! set the indices we want to keep (i.e., a mapping from reduced to full matrix) + J = 1 + DO I=1,TDOF + idx(J) = idx(I) + IF ( idx(J) /= 0 ) J = J + 1 + END DO + + ! Remove rows and columns from every row/column in full matrix where Init%BC(:,2) == 1, + ! using the mapping created above. (This is a symmetric matrix.) + DO J = 1, DOF_reduced !Cycle on reaction DOFs + DO I = 1, DOF_reduced !Cycle on reaction DOFs + Kred(I,J) = REAL( K( idx(I), idx(J) ), LAKi ) + END DO + END DO + ! clean up local variables: + CALL CleanUp() +CONTAINS + subroutine CleanUp() + IF (ALLOCATED(idx)) DEALLOCATE(idx) + end subroutine +END SUBROUTINE ReduceKMdofs + +!------------------------------------------------------------------------------------------------------ +!> Augments VRred to VR for the constrained DOFs, somehow reversing what ReducedKM did for matrices +!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed +SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT(in ) :: Init + TYPE(SD_ParameterType), INTENT(in ) :: p + INTEGER, INTENT(IN ) :: rDOF ,RModes !retained DOFs after removing restrained DOFs and retained modes + REAL(LAKi), INTENT(IN ) :: VRred(rDOF, rModes) !eigenvector matrix with restrained DOFs removed + REAL(ReKi), INTENT(INOUT) :: VR(:,:) !eigenvalues including the previously removed DOFs + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER, ALLOCATABLE :: idx(:) + INTEGER :: I, I2, L !counters; I,I2 should be long, L short + + ErrStat = ErrID_None + ErrMsg = '' + + ALLOCATE(idx(p%NReact*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints + idx=0 !initialize + L=0 !initialize + DO I = 1, p%NReact*6 !Cycle on reaction DOFs + IF (Init%BCs(I, 2) == 1) THEN + idx(I)=Init%BCs(I, 1) !row/col index that was originally eliminated when applying restraints + L=L+1 !number of DOFs to eliminate + ENDIF + ENDDO +! PRINT *, ' rDOF+L=',rDOF+L, 'SIZE(Phi2)=',SIZE(VR,1) +! ALLOCATE(VR(rDOF+L,rModes), STAT = ErrStat ) !Restored eigenvectors with restrained node DOFs included + VR=0.!Initialize + + I2=1 !Initialize + DO I=1,rDOF+L !This loop inserts Vred in VR in all but the removed DOFs + IF (ALL((idx-I).NE.0)) THEN + VR(I,:)=REAL( VRred(I2,:), ReKi ) ! potentially change of precision + I2=I2+1 !Note this counter gets updated only if we insert Vred rows into VR + ENDIF + ENDDO +END SUBROUTINE UnReduceVRdofs + +!------------------------------------------------------------------------------------------------------ +SUBROUTINE CBApplyConstr(DOFI, DOFR, DOFM, DOFL, & + MBB , MBM , KBB , PHiR , FGR , & + MBBb, MBMb, KBBb, PHiRb, FGRb) + INTEGER(IntKi), INTENT(IN ) :: DOFR, DOFI, DOFM, DOFL + REAL(ReKi), INTENT(IN ) :: FGR(DOFR) + REAL(ReKi), INTENT(IN ) :: MBB(DOFR, DOFR) + REAL(ReKi), INTENT(IN ) :: MBM(DOFR, DOFM) + REAL(ReKi), INTENT(IN ) :: KBB(DOFR, DOFR) + REAL(ReKi), INTENT(IN ) :: PhiR(DOFL, DOFR) + REAL(ReKi), INTENT( OUT) :: MBBb(DOFI, DOFI) + REAL(ReKi), INTENT( OUT) :: KBBb(DOFI, DOFI) + REAL(ReKi), INTENT( OUT) :: MBMb(DOFI, DOFM) + REAL(ReKi), INTENT( OUT) :: FGRb(DOFI) + REAL(ReKi), INTENT( OUT) :: PhiRb(DOFL, DOFI) + + MBBb = MBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) + KBBb = KBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) +IF (DOFM > 0) THEN + MBMb = MBM(DOFR-DOFI+1:DOFR, : ) +END IF + FGRb = FGR(DOFR-DOFI+1:DOFR ) + PhiRb = PhiR( :, DOFR-DOFI+1:DOFR) + +END SUBROUTINE CBApplyConstr + +!------------------------------------------------------------------------------------------------------ +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters + REAL(ReKi), INTENT(IN ) :: MBBb( p%DOFI, p%DOFI) + REAL(ReKi), INTENT(IN ) :: MBMb( p%DOFI, p%Nmodes) + REAL(ReKi), INTENT(IN ) :: KBBb( p%DOFI, p%DOFI) + REAL(ReKi), INTENT(IN ) :: PhiL ( p%DOFL, p%DOFL) + REAL(ReKi), INTENT(IN ) :: PhiRb( p%DOFL, p%DOFI) + REAL(ReKi), INTENT(IN ) :: OmegaL(p%DOFL) + REAL(ReKi), INTENT(IN ) :: FGRb(p%DOFI) + REAL(ReKi), INTENT(IN ) :: FGL(p%DOFL) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: TI_transpose(TPdofL,p%DOFI) !bjj: added this so we don't have to take the transpose 5+ times + INTEGER(IntKi) :: I + integer(IntKi) :: n ! size of jacobian in AM2 calculation + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' + + ErrStat = ErrID_None + ErrMsg = '' + + TI_transpose = TRANSPOSE(p%TI) + + ! Store FGL for later processes + IF (p%SttcSolve) THEN + p%FGL = FGL + ENDIF + + ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) + p%PhiRb_TI = MATMUL(PhiRb, p%TI) + + !............................... + ! equation 46-47 (used to be 9): + !............................... + p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt + p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt + + !p%D1_15=-TI_transpose !this is 6x6NIN + IF ( p%NModes > 0 ) THEN ! These values don't exist for DOFM=0; i.e., p%NModes == 0 + ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt + CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') + + p%MMB = TRANSPOSE( p%MBM ) != MMBt + p%PhiM = PhiL(:,1:p%Nmodes) + + ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) + p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%Nmodes) * OmegaL(1:p%Nmodes) ! OmegaM is a one-dimensional array + p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%Nmodes) * Init%JDampings(1:p%Nmodes) ! Init%JDampings is also a one-dimensional array + + ! B_23, B_24 + !p%PhiM_T = TRANSPOSE( p%PhiM ) + + ! FX + ! p%FX = MATMUL( p%PhiM_T, FGL ) != MATMUL( TRANSPOSE(PhiM), FGL ) + p%FX = MATMUL( FGL, p%PhiM ) != MATMUL( TRANSPOSE(PhiM), FGL ) because FGL is 1-D + + ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) + DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped + p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) + p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) + ENDDO + + ! D1_13, D1_14 (with retained modes) + !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ) ! p%D1_13 = MATMUL( p%MBM, p%MMB ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + p%D1_13 = p%MBB - p%D1_13 + + !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! FY (with retained modes) + p%FY = MATMUL( p%MBM, p%FX ) & + - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) + + ! C2_21, C2_42 + ! C2_61, C2_62 + DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped + p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) + p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) + ENDDO + + ! D2_53, D2_63, D2_64 + p%D2_63 = MATMUL( p%PhiM, p%MMB ) + p%D2_63 = p%PhiRb_TI - p%D2_63 + + !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) !bjj: why does this use stack space? + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ) !bjj: replaced MATMUL with this routine to avoid issues with stack size + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! F2_61 + p%F2_61 = MATMUL( p%D2_64, FGL ) + + !Now calculate a Jacobian used when AM2 is called and store in parameters + IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%qmL > 0) + n=2*p%qmL + CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! First we calculate the Jacobian: + ! (note the Jacobian is first stored as p%AM2InvJac) + p%AM2Jac=0. + DO i=1,p%qmL + p%AM2Jac(i+p%qmL,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 + p%AM2Jac(i+p%qmL,i+p%qmL)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize + END DO + + DO I=1,p%qmL + p%AM2Jac(I,I)=-1. !J11 + p%AM2Jac(I,p%qmL+I)=p%SDdeltaT/2. !J12 + p%AM2Jac(p%qmL+I,p%qmL+I)=p%AM2Jac(p%qmL+I,p%qmL+I)-1 !J22 complete + ENDDO + ! Now need to factor it: + !I think it could be improved and made more efficient if we can say the matrix is positive definite + CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2); if(Failed()) return + END IF + + ELSE ! no retained modes, so + ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case + ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables + ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable + ! p%D1_13 = p%MBB in this case so we simplify the equations in the code, omitting storage of this variable + + ! D1_14 (with 0 retained modes) + p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + + ! FY (with 0 retained modes) + p%FY = - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) + + END IF + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetParameters') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + +END SUBROUTINE SetParameters + +!------------------------------------------------------------------------------------------------------ + +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. +SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) + TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters + INTEGER(IntKi), INTENT( in) :: DOFM + 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 + ! initialize error handling: + ErrStat = ErrID_None + ErrMsg = "" + + ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. + + CALL AllocAry( p%KBB, TPdofL, TPdofL, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MBB, TPdofL, TPdofL, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%TI, p%DOFI, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_14, TPdofL, p%DOFL, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FY, TPdofL, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiRb_TI, p%DOFL, TPdofL, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + +if (p%Nmodes > 0 ) THEN + CALL AllocAry( p%MBM, TPdofL, DOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MMB, DOFM, TPdofL, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%NOmegaM2, DOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%N2OmegaMJDamp, DOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FX, DOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_11, TPdofL, DOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_12, TPdofL, DOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiM, p%DOFL, DOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_61, p%DOFL, DOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_62, p%DOFL, DOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_13, TPdofL, TPdofL, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%NModes == 0 + CALL AllocAry( p%D2_63, p%DOFL, TPdofL, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%NModes == 0 + CALL AllocAry( p%D2_64, p%DOFL, p%DOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 + CALL AllocAry( p%F2_61, p%DOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 +end if + + CALL AllocAry( p%IDI, p%DOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%IDR, p%DOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%IDL, p%DOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%IDC, p%DOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%IDY, p%DOFC+p%DOFI+p%DOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + +if ( p%SttcSolve ) THEN + CALL AllocAry( p%PhiL_T, p%DOFL, p%DOFL, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiLInvOmgL2, p%DOFL, p%DOFL, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FGL, p%DOFL, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') +end if + +END SUBROUTINE AllocParameters + +!------------------------------------------------------------------------------------------------------ +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. +SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) + TYPE(SD_MiscVarType), INTENT(INOUT) :: Misc ! Miscellaneous values, used to avoid local copies and/or multiple allocation/deallocation of same variables each call + TYPE(SD_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 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! initialize error handling: + ErrStat = ErrID_None + ErrMsg = "" + + ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. + CALL AllocAry( Misc%UFL, p%DOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar, p%URbarL, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar_dot, p%URbarL, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar_dotdot,p%URbarL, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL, p%DOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dot, p%DOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dotdot, p%DOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + +END SUBROUTINE AllocMiscVars + +!------------------------------------------------------------------------------------------------------ +!> Set the index arrays IDI, IDR, IDL, IDC, and IDY. +SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) + USE qsort_c_module, only: QsortC + + TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine + TYPE(SD_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(IntKi) :: TempIDY(p%DOFC+p%DOFI+p%DOFL, 2) + INTEGER(IntKi) :: IDT(Init%TDOF) + INTEGER(IntKi) :: I, K ! counters + ErrStat = ErrID_None + ErrMsg = "" + + ! Index IDI for interface DOFs + p%IDI = Init%IntFc(1:p%DOFI, 1) !RRD interface DOFs + + ! Index IDC for constraint DOFs + p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs + + ! Index IDR for IDR DOFs + p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again + p%IDR(p%DOFC+1:p%DOFR) = p%IDI ! IDR contains DOFs ofboundaries, constraints first then interface + + ! --- Index IDL for IDL DOFs + ! first set the total DOFs: + DO I = 1, Init%TDOF !Total DOFs + IDT(I) = I + ENDDO + ! remove DOFs on the boundaries: + DO I = 1, p%DOFR !Boundary DOFs (Interface + Constraints) + IDT(p%IDR(I)) = 0 !Set 0 wherever DOFs belong to boundaries + ENDDO + ! That leaves the internal DOFs: + K = 0 + DO I = 1, Init%TDOF + IF ( IDT(I) .NE. 0 ) THEN + K = K+1 + p%IDL(K) = IDT(I) !Internal DOFs + ENDIF + ENDDO + IF ( K /= p%DOFL ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "SetIndexArrays: IDL or p%DOFL are the incorrect size." + RETURN + END IF + + ! --- Index IDY for all DOFs: + ! set the second column of the temp array + DO I = 1, SIZE(TempIDY,1) + TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) + ENDDO + ! set the first column of the temp array + TempIDY(1:p%DOFI, 1) = p%IDI + TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL + TempIDY(p%DOFI+p%DOFL+1: p%DOFI+p%DOFL+p%DOFC, 1) = p%IDC + ! sort based on the first column + CALL QsortC( TempIDY ) + ! the second column is the key: + p%IDY = TempIDY(:, 2) + +END SUBROUTINE SetIndexArrays + +!------------------------------------------------------------------------------------------------------ +!> +SUBROUTINE Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg,Init,p) + TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters + INTEGER(IntKi) :: DOFTP, DOFM + REAL(ReKi) :: MBBt(DOFTP, DOFTP) + REAL(ReKi) :: MBmt(DOFTP, DOFM) + REAL(ReKi) :: KBBt(DOFTP, DOFTP) + REAL(ReKi) :: OmegaM(DOFM) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: DOFT, NM, i + REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) + REAL(ReKi), Allocatable :: K(:, :) + REAL(ReKi), Allocatable :: M(:, :) + Character(1024) :: rootname + ErrStat = ErrID_None + ErrMsg = '' + + DOFT = DOFTP + DOFM + NM = DOFT - 3 + Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) + K = 0.0 + M = 0.0 + OmegaCB = 0.0 + PhiCB = 0.0 + + M(1:DOFTP, 1:DOFTP) = MBBt + M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt + M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) + + DO i = 1, DOFM + K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) + M(DOFTP+i, DOFTP+i) = 1.0 + ENDDO + + K(1:DOFTP, 1:DOFTP) = KBBt + + ! temporary rootname + rootname = './test_assemble_C-B_out' + + CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) + IF ( ErrStat /= 0 ) RETURN + +END SUBROUTINE Test_CB_Results + +!------------------------------------------------------------------------------------------------------ +!> Take the input u LMesh and constructs the appropriate corresponding UFL vector +SUBROUTINE ConstructUFL( u, p, UFL ) + TYPE(SD_InputType), INTENT(IN ) :: u ! Inputs + TYPE(SD_ParameterType), INTENT(IN ) :: p ! Parameters + REAL(ReKi) :: UFL(p%DOFL) + INTEGER :: I, J, StartDOF ! integers for indexing into mesh and UFL + + ! note that p%DOFL = p%NNodes_L*6 + DO I = 1, p%NNodes_L !Only interior nodes here + ! starting index in the master arrays for the current node + startDOF = (I-1)*6 + 1 + ! index into the Y2Mesh + J = p%NNodes_I + I + ! Construct UFL array from the Force and Moment fields of the input mesh + UFL ( startDOF : startDOF + 2 ) = u%LMesh%Force (:,J) + UFL ( startDOF+3 : startDOF + 5 ) = u%LMesh%Moment(:,J) + END DO + +END SUBROUTINE + +!------------------------------------------------------------------------------------------------------ +!> Output the summary file +SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) + TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file + TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file + TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use + TYPE(FEM_MatArrays), INTENT(IN) :: FEMparams ! FEM parameters that will be passed in for summary file use + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !LOCALS + INTEGER(IntKi) :: UnSum ! unit number for this summary file + INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors + CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file + INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders + INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) + REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix + REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3), mlength !temporary arrays, member i-th direction cosine matrix (global to local) and member length + CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' + CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' + CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SD_Y2Mesh_Mapping(p, SDtoMeshIndx ) + + !------------------------------------------------------------------------------------------------------------- + ! open txt file + !------------------------------------------------------------------------------------------------------------- + SummaryName = TRIM(Init%RootName)//'.sum' + UnSum = -1 ! we haven't opened the summary file, yet. + + CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ) + CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) + IF ( ErrStat >= AbortErrLev ) THEN + CLOSE(UnSum) + RETURN + END IF + + !------------------------------------------------------------------------------------------------------------- + ! write discretized data to a txt file + !------------------------------------------------------------------------------------------------------------- +!bjj: for debugging, i recommend using the p% versions of all these variables whenever possible in this summary file: +! (it helps in debugging) + WRITE(UnSum, '(A)') 'Unless specified, units are consistent with Input units, [SI] system is advised.' + WRITE(UnSum, '(A)') SectionDivide + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'Number of nodes (NNodes):',Init%NNode + WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' + WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') '--------', '-----------', '---------------', '---------------', '---------------' +! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, Init%NNode) !do not group the format or it won't work 3(E15.6) does not work !bjj??? + WRITE(UnSum, '('//Num2LStr(Init%NNode)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & + (NINT(Init%Nodes(i, 1)), SDtoMeshIndx(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, Init%NNode) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem + WRITE(UnSum, '(A8,4(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Prop_I', 'Prop_J' + WRITE(UnSum, '(I8,I10,I10,I10,I10)') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NProp + WRITE(UnSum, '(A8,5(A15))') 'Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' + WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%Props(i, 1)), (Init%Props(i, j), j = 2, 6), i = 1, Init%NProp) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%NReact*6 + WRITE(UnSum, '(A, A6)') 'Reaction DOF_ID', 'LOCK' + WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%NReact*6) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%DOFI + WRITE(UnSum, '(A,A6)') 'Interface DOF ID', 'LOCK' + WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%DOFI) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'Number of concentrated masses (NCMass):',Init%NCMass + WRITE(UnSum, '(A10,A15,A15,A15,A15)') 'JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ' + WRITE(UnSum, '(F10.0, E15.6,E15.6,E15.6,E15.6)') ((Init%Cmass(i, j), j = 1, 5), i = 1, Init%NCMass) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers + WRITE(UnSum, '(A,I6)') 'Number of nodes per member:', Init%Ndiv+1 + WRITE(UnSum, '(A9,A10,A10,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID', 'Mass', 'Node IDs...' + !WRITE(UnSum, '('//Num2LStr(Init%NDiv + 1 )//'(I6))') ((Init%MemberNodes(i, j), j = 1, Init%NDiv+1), i = 1, p%NMembers) + DO i=1,p%NMembers + !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else + !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS + propids=Init%Members(i,4:5) + mlength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) + IF (ErrStat .EQ. ErrID_None) THEN + WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & + MemberMass(Init%PropSets(propids(1),4),Init%PropSets(propids(1),5),Init%PropSets(propids(1),6), & + Init%PropSets(propids(2),4),Init%PropSets(propids(2),5),Init%PropSets(propids(2),6), mlength, .TRUE.), & + ' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + ELSE + RETURN + ENDIF + ENDDO + !------------------------------------------------------------------------------------------------------------- + ! write Cosine matrix for all members to a txt file + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') 'Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers + WRITE(UnSum, '(A9,9(A15))') 'Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' + DO i=1,p%NMembers + !Find the right index in the Nodes array for the selected JointID. This is horrible, but I do not know how to implement this search in a more efficient way + !The alternative would be to get an element that belongs to the member and use it with dircos + +!BJJ:TODO: DIDN'T we already calculate DirCos for each element? can't we use that here? + DO j=1,Init%NNode + IF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,2) )THEN + XYZ1=Init%Nodes(Init%Members(i,2),2:4) + ELSEIF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,3) ) THEN + XYZ2=Init%Nodes(Init%Members(i,3),2:4) + ENDIF + ENDDO + CALL GetDirCos(XYZ1(1), XYZ1(2), XYZ1(3), XYZ2(1), XYZ2(2), XYZ2(3), DirCos, mlength, ErrStat, ErrMsg) + DirCos=TRANSPOSE(DirCos) !This is now global to local + WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + ENDDO + + !------------------------------------------------------------------------------------------------------------- + ! write Eigenvalues of full SYstem and CB reduced System + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Eigenvalues' + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A, I6)') "FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", FEMparams%NOmega + WRITE(UnSum, '(I6, e15.6)') ( i, FEMparams%Omega(i)/2.0/pi, i = 1, FEMparams%NOmega ) + + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", CBparams%DOFM + WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, CBparams%DOFM ) + + !------------------------------------------------------------------------------------------------------------- + ! write Eigenvectors of full SYstem + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(Init%TDOF))//' x '//TRIM(Num2LStr(FEMparams%NOmega))//& + ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), FEMparams%NOmega + WRITE(UnSum, '(6x,'//Num2LStr(FEMparams%NOmega)//'(I15))') (i, i = 1, FEMparams%NOmega )!HEADERS + WRITE(UnSum, '(I6,'//Num2LStr(FEMparams%NOmega)//'e15.6)') ( i, (FEMparams%Modes(i,j), j = 1, FEMparams%NOmega ),i = 1, Init%TDOF) + + !------------------------------------------------------------------------------------------------------------- + ! write CB system matrices + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (no constraint applied)' + + WRITE(UnSum, '(A)') SubSectionDivide + IF (CBparams%DOFM > 0) THEN + CALL WrMatrix( CBparams%PhiL(:,1:CBparams%DOFM ), UnSum, 'e15.6', 'PhiM' ) + ELSE + WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%DOFL)), '0' + END IF + + WRITE(UnSum, '(A)') SubSectionDivide + CALL WrMatrix( CBparams%PhiR, UnSum, 'e15.6', 'PhiR' ) + + !------------------------------------------------------------------------------------------------------------- + ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') "SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') 'KBBt' !Note p%KBB stores KBBt + WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) + !tried implicit loop unsuccessfully + DO i=1,6 + WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%KBB(i,j), j = 1, 6) + ENDDO + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') ('MBBt')!Note p%MBB stores MBBt + WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) + DO i=1,6 + WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%MBB(i,j), j = 1, 6) + ENDDO + + MRB=matmul(TRANSPOSE(CBparams%TI2),matmul(CBparams%MBB,CBparams%TI2)) !Equivalent mass matrix of the rigid body + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') 'MRB' + WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) + DO i=1,6 + WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) + ENDDO + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + +#ifdef SD_SUMMARY_DEBUG + + WRITE(UnSum, '()') + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '**** Additional Debugging Information ****' + + !------------------------------------------------------------------------------------------------------------- + ! write assembed K M to a txt file + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') 'FULL FEM K and M matrices. TOTAL FEM TDOFs:', Init%TDOF + WRITE(UnSum, '(A)') ('Stiffness matrix K' ) + WRITE(UnSum, '(15x,'//TRIM(Num2LStr(Init%TDOF))//'(I15))') (i, i = 1, Init%TDOF ) + DO i=1,Init%TDOF + WRITE(UnSum, '(I15, '//TRIM(Num2LStr(Init%TDOF))//'(e15.6))') i, (Init%K(i, j), j = 1, Init%TDOF) + ENDDO + + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') ('Mass matrix M' ) + WRITE(UnSum, '(15x,'//TRIM(Num2LStr(Init%TDOF))//'(I15))') (i, i = 1, Init%TDOF ) + DO i=1,Init%TDOF + WRITE(UnSum, '(I15, '//TRIM(Num2LStr(Init%TDOF))//'(e15.6))') i, (Init%M(i, j), j = 1, Init%TDOF) + ENDDO + + !------------------------------------------------------------------------------------------------------------- + ! write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Gravity force vector FG applied at each node of the full system' + WRITE(UnSum, '(I6, e15.6)') (i, Init%FG(i), i = 1, Init%TDOF) + + !------------------------------------------------------------------------------------------------------------- + ! write CB system matrices + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Additional CB Matrices (MBB,MBM,KBB) (no constraint applied)' + + WRITE(UnSum, '(A)') SubSectionDivide + CALL WrMatrix( CBparams%MBB, UnSum, 'e15.6', 'MBB' ) + + WRITE(UnSum, '(A)') SubSectionDivide + IF ( CBparams%DOFM > 0 ) THEN + CALL WrMatrix( CBparams%MBM, UnSum, 'e15.6', 'MBM' ) + ELSE + WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "MBM", '6', '0' + END IF + + WRITE(UnSum, '(A)') SubSectionDivide + CALL WrMatrix( CBparams%KBB, UnSum, 'e15.6', 'KBB' ) + + WRITE(UnSum, '(A)') SubSectionDivide + CALL WrMatrix( CBparams%OmegaL**2, UnSum, 'e15.6','KMM (diagonal)' ) + + !------------------------------------------------------------------------------------------------------------- + ! write TP TI matrix + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'TP refpoint Transformation Matrix TI ' + CALL WrMatrix( p%TI, UnSum, 'e15.6', 'TI' ) + +#endif + + CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + +END SUBROUTINE OutSummary + +!------------------------------------------------------------------------------------------------------ +!> This function calculates the length of a member +FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) + TYPE(SD_InitType), INTENT(IN) :: Init !< Input data for initialization routine, this structure contains many variables needed for summary file + INTEGER(IntKi), INTENT(IN) :: MemberID !< Member ID # + REAL(ReKi) :: MemberLength !< Member Length + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + !Locals + REAL(Reki) :: xyz1(3),xyz2(3) ! Coordinates of joints in GLOBAL REF SYS + INTEGER(IntKi) :: i ! Counter + INTEGER(IntKi) :: Joint1,Joint2 ! JointID + CHARACTER(*), PARAMETER :: RoutineName = 'MemberLength' + ErrStat = ErrID_None + ErrMsg = '' + MemberLength=0.0 + + !Find the MemberID in the list + DO i=1,SIZE(Init%Members, DIM=1) + IF (Init%Members(i,1) .EQ. MemberID) THEN + ! Find joints ID for this member + Joint1 = FindNode(i,1); if (Joint1<0) return + Joint2 = FindNode(i,2); if (Joint2<0) return + xyz1= Init%Joints(Joint1,2:4) + xyz2= Init%Joints(Joint2,2:4) + MemberLength=SQRT( SUM((xyz2-xyz1)**2.) ) + if ( EqualRealNos(MemberLength, 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' has zero length!', ErrStat,ErrMsg,RoutineName); + return + endif + return + ENDIF + ENDDO + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' not found in member list!', ErrStat,ErrMsg,RoutineName); + +contains + !> Find JointID for node `iNode` (1 or 2) or member `iMember` + integer(IntKi) function FindNode(iMember,iNode) result(j) + integer(IntKi), intent(in) :: iMember !< Member index in Init%Members list + integer(IntKi), intent(in) :: iNode !< Node index, 1 or 2 for the member iMember + logical :: found + found = .false. + j=1 + do while ( .not. found .and. j <= Init%NJoints ) + if (Init%Members(iMember, iNode+1) == nint(Init%Joints(j,1))) then ! Columns 2/3 for iNode 1/2 + found = .true. + exit + endif + j = j + 1 + enddo + if (.not.found) then + j=-1 + call SetErrStat(ErrID_Fatal,' Member '//trim(Num2LStr(iMember))//' has JointID'//trim(Num2LStr(iNode))//' = '//& + trim(Num2LStr(Init%Members(iMember,iNode+1)))//' which is not in the node list !', ErrStat,ErrMsg,RoutineName) + endif + end function + +END FUNCTION MemberLength + +!------------------------------------------------------------------------------------------------------ +!> Calculate member mass, given properties at the ends, keep units consistent +!! For now it works only for circular pipes or for a linearly varying area +FUNCTION MemberMass(rho1,D1,t1,rho2,D2,t2,L,ctube) + REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member + ! IF ctube=.FALSE. then D1/2=Area at end1/2, t1 and t2 are ignored + REAL(ReKi) :: MemberMass !mass + LOGICAL, INTENT(IN) :: ctube ! =TRUE for circular pipes, false elseshape + !LOCALS + REAL(ReKi) ::a0,a1,a2,b0,b1,dd,dt !temporary coefficients + + !Density allowed to vary linearly only + b0=rho1 + b1=(rho2-rho1)/L + !Here we will need to figure out what element it is for now circular pipes + IF (ctube) THEN !circular tube + a0=pi * (D1*t1-t1**2.) + dt=t2-t1 !thickness variation + dd=D2-D1 !OD variation + a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L + a2=pi * ( dd*dt-dt**2.)/L**2. + + ELSE !linearly varying area + a0=D1 !This is an area + a1=(D2-D1)/L !Delta area + a2=0. + + ENDIF + MemberMass= b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz + +END FUNCTION MemberMass + +!------------------------------------------------------------------------------------------------------ +!> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR +SUBROUTINE SymMatDebug(M,MAT) + INTEGER(IntKi), INTENT(IN) :: M ! Number of rows and columns + REAL(ReKi),INTENT(IN) :: MAT(M ,M) !matrix to be checked + !LOCALS + REAL(ReKi) :: Error,MaxErr !element by element relative difference in (Transpose(MAT)-MAT)/MAT + INTEGER(IntKi) :: i, j, imax,jmax !counter and temporary holders + + MaxErr=0. + imax=0 + jmax=0 + DO j=1,M + DO i=1,M + Error=MAT(i,j)-MAT(j,i) + IF (MAT(i,j).NE.0) THEN + Error=ABS(Error)/MAT(i,j) + ENDIF + IF (Error > MaxErr) THEN + imax=i + jmax=j + MaxErr=Error + ENDIF + ENDDO + ENDDO + + !-------------------------------------- + ! write discretized data to a txt file + WRITE(*, '(A,e15.6)') 'Matrix Symmetry Check: Largest (abs) relative error is:', MaxErr + WRITE(*, '(A,I4,I4)') 'Matrix Symmetry Check: (I,J)=', imax,jmax + +END SUBROUTINE SymMatDebug + +End Module SubDyn diff --git a/OpenFAST/modules/subdyn/src/SubDyn_Driver.f90 b/OpenFAST/modules/subdyn/src/SubDyn_Driver.f90 new file mode 100644 index 000000000..eaa18c094 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SubDyn_Driver.f90 @@ -0,0 +1,793 @@ +!********************************************************************************************************************************** +! SubDyn_DriverCode: This code tests the SubDyn modules +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! 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. +! +!********************************************************************************************************************************** +PROGRAM TestSubDyn + + USE NWTC_Library + USE SubDyn + USE SubDyn_Types + USE SubDyn_Output + USE VersionInfo + + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 1 ! Number of inputs sent to SD_UpdateStates + + + TYPE SD_Drvr_InitInput + LOGICAL :: Echo + REAL(ReKi) :: Gravity + CHARACTER(1024) :: SDInputFile + REAL(ReKi) :: WtrDpth + CHARACTER(1024) :: OutRootName + INTEGER :: NSteps + REAL(DbKi) :: TimeInterval + REAL(ReKi) :: TP_RefPoint(3) + REAL(ReKi) :: SubRotateZ + INTEGER :: InputsMod + CHARACTER(1024) :: InputsFile + REAL(ReKi) :: uTPInSteady(6) + REAL(ReKi) :: uDotTPInSteady(6) + REAL(ReKi) :: uDotDotTPInSteady(6) + END TYPE SD_Drvr_InitInput + + + ! Program variables + + REAL(DbKi) :: Time ! Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) ! Variable for storing time associated with inputs, in seconds + + TYPE(SD_InitInputType) :: InitInData ! Input data for initialization + TYPE(SD_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(SD_ContinuousStateType) :: x ! Continuous states + TYPE(SD_DiscreteStateType) :: xd ! Discrete states + TYPE(SD_ConstraintStateType) :: z ! Constraint states + TYPE(SD_OtherStateType) :: OtherState ! Other states + TYPE(SD_MiscVarType) :: m ! Misc/optimization variables + + TYPE(SD_ParameterType) :: p ! Parameters + TYPE(SD_InputType) :: u(NumInp) ! System inputs + TYPE(SD_OutputType) :: y ! System outputs + + + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: ErrStat, ErrStat1, ErrStat2, ErrStat3 ! Status of error message + CHARACTER(1024) :: ErrMsg, ErrMsg1, ErrMsg2, ErrMsg3 ! Error message if ErrStat /= ErrID_None + + + CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. + TYPE(SD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program + INTEGER(IntKi) :: UnInp ! Inputs file identifier + INTEGER(IntKi) :: UnSD_Out ! Output file identifier + REAL(ReKi), ALLOCATABLE :: SDin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for SubDyn inputs + INTEGER(IntKi) :: J ! Generic loop counter + REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). + REAL(DbKi) :: maxAngle ! For debugging, see what the largest rotational angle input is for the simulation + CHARACTER(10) :: AngleMsg ! For debugging, a string version of the largest rotation input + + ! Other/Misc variables + REAL(DbKi) :: TiLstPrn ! The time of the last print + REAL(DbKi) :: TMax + REAL(DbKi) :: OutTime ! Used to determine if output should be generated at this simulation time + REAL(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds + REAL :: UsrTime1 ! User CPU time for simulation initialization + INTEGER :: StrtTime (8) ! Start time of simulation + CHARACTER(200) :: git_commit ! String containing the current git commit hash + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'SubDyn Driver', '', '' ) ! The version number of this program. + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + + + ! Get the current time + + CALL DATE_AND_TIME ( Values=StrtTime ) ! Let's time the whole simulation + CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + PrevClockTime = TimeValues2Seconds( StrtTime ) ! We'll use this time for the SimStats routine + TiLstPrn = 0.0_DbKi ! The first value of ZTime, used to write simulation stats to screen (s) + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + + + ! Set the abort error level to a fatal error + AbortErrLev = ErrID_Fatal + + IF ( command_argument_count() > 1 ) CALL print_help() + + ! Parse the driver input file and run the simulation based on that file + + IF ( command_argument_count() == 1 ) THEN + + CALL get_command_argument(1, drvrFilename) + CALL ReadDriverInputFile( drvrFilename, drvrInitInp, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) THEN + CALL WrScr( ErrMsg ) + STOP + END IF + InitInData%g = drvrInitInp%Gravity + !InitInData%UseInputFile = .TRUE. + InitInData%SDInputFile = drvrInitInp%SDInputFile + InitInData%RootName = drvrInitInp%OutRootName + InitInData%TP_RefPoint = drvrInitInp%TP_RefPoint + InitInData%SubRotateZ = drvrInitInp%SubRotateZ + TimeInterval = drvrInitInp%TimeInterval + InitInData%WtrDpth = drvrInitInp%WtrDpth + ELSE + ! Called without a driver input file! + CALL WrScr( 'Running SubDyn without a driver file! This is for SubDyn developers only.' ) + ! InitInData%SDInputFile = '..\BeamFEM\IOFiles\TestBeam2.txt' + InitInData%SDInputFile = '..\MergedSubDyn\IOFiles\TestBeam3.txt' + ! InitInData%SDInputFile = '..\BeamFEM\IOFiles\TestFrame.txt' + InitInData%g = 9.80665 + !InitInData%TP_RefPoint = (/0.0, 0.0, 100.0/) !testbeam2 + InitInData%TP_RefPoint = (/50.0, 0.0, 50.0/) !testbeam3 + InitInData%SubRotateZ = 0.0 + InitInData%WtrDpth = 20.0 + !InitInData%TP_RefPoint = (/0.0, 0.0, 40.0/) !testframe + ! Set the driver's request for time interval here: + TimeInterval = 0.001 ! Glue code's request for delta time (likely based on information from other modules) + END IF + + + TMax = TimeInterval * drvrInitInp%NSteps + + ! Initialize the module + + CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat1, ErrMsg1 ) + IF ( ErrStat1 /= 0 ) THEN + CALL WrScr( ErrMsg1 ) + STOP + END IF + + + ! Read Input time series data from a file + + IF ( drvrInitInp%InputsMod == 2 ) THEN + + ! Open the inputs data file + CALL GetNewUnit( UnInp ) + CALL OpenFInpFile ( UnInp, drvrInitInp%InputsFile, ErrStat, ErrMsg ) ! Open inputs file. + IF (ErrStat >= AbortErrLev) THEN + CALL WrScr( 'SubDyn input timeseries file not found.') + CALL WrScr( trim(ErrMsg) ) + STOP + END IF + + ALLOCATE ( SDin(drvrInitInp%NSteps, 13), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for SDin array.' + CALL WrScr( ErrMsg ) + CLOSE( UnInp ) + STOP + END IF + + DO n = 1,drvrInitInp%NSteps + READ (UnInp,*,IOSTAT=ErrStat) (SDin (n,J), J=1,13) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = 'File not found' + CALL WrScr( ErrMsg ) + CLOSE ( UnInp ) + STOP + END IF + END DO + + ! Close the inputs file + CLOSE ( UnInp ) + END IF + + ! Destroy initialization data + + CALL SD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ) + CALL SD_DestroyInitOutput( InitOutData, ErrStat3, ErrMsg3 ) + + + ! Handle the initialization error after destroying the data structures + + IF ( ErrStat1 /= ErrID_None .OR. ErrStat2 /=0 .OR. ErrStat3 /= 0) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg1 ) + STOP + END IF + + IF ( ErrStat2 /=0 .OR. ErrStat3 /= 0) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( 'Error destroying SubDyn intialization data' ) + STOP + END IF + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + + ! Force the displacement of the interface node in the global Z direction to be the sag of the column under it's own weight + + !u(1)%UFL(3) = -0.001821207 !-0.001821235 !This is for testbeam.txt + ! u(1)%UFL(3)=-12.958 !this is for testbeam3 + + call wrscr('') + DO n = 0,drvrInitInp%NSteps-1 + + Time = n*TimeInterval + InputTime(1) = Time + + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + + IF ( u(1)%TPMesh%Initialized ) THEN + + ! For now, set all hydrodynamic load inputs to 0.0 + u(1)%LMesh%Force (:,:) = 0.0 + !u(1)%LMesh%Force (3,5:8) = 1.e7 !DEBUGGING + !u(1)%LMesh%Force(3,5) = 1.e7 + !u(1)%LMesh%Force(3,6) = 1.e7 + !u(1)%LMesh%Force(3,7) = 1.e7 + !u(1)%LMesh%Force(3,8) = 1.e7 + u(1)%LMesh%Moment (:,:) = 0.0 + + IF ( drvrInitInp%InputsMod == 2 ) THEN + + + + u(1)%TPMesh%TranslationDisp(:,1) = SDin(n+1,2:4) + + + ! Compute direction cosine matrix from the rotation angles + + IF ( abs(SDin(n+1,5)) > maxAngle ) maxAngle = abs(SDin(n+1,5)) + IF ( abs(SDin(n+1,6)) > maxAngle ) maxAngle = abs(SDin(n+1,6)) + IF ( abs(SDin(n+1,7)) > maxAngle ) maxAngle = abs(SDin(n+1,7)) + + CALL SmllRotTrans( 'InputRotation', REAL(SDin(n+1,5),reki), REAL(SDin(n+1,6),reki), REAL(SDin(n+1,7),reki), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%TPMesh%Orientation(:,:,1) = dcm + + + u(1)%TPMesh%TranslationVel(:,1) = SDin(n+1,8:10) + u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) + + ELSE + + u(1)%TPMesh%TranslationDisp(:,1) = drvrInitInp%uTPInSteady(1:3) + + + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uTPInSteady(4),reki), REAL(drvrInitInp%uTPInSteady(5),reki), REAL(drvrInitInp%uTPInSteady(6),reki), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%TPMesh%Orientation(:,:,1) = dcm + + u(1)%TPMesh%TranslationVel(:,1) = drvrInitInp%uDotTPInSteady(1:3) + u(1)%TPMesh%RotationVel(:,1) = drvrInitInp%uDotTPInSteady(4:6) + + u(1)%TPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(1:3) + u(1)%TPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(4:6) + + END IF + + END IF + ! Calculate outputs at n + + CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + IF ( ErrStat >= AbortErrLev) STOP + END IF + + + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + + CALL SD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + IF ( ErrStat >= AbortErrLev) STOP + END IF + + !..................................................... + ! Display simulation status every SttsTime-seconds: + !..................................................... + + IF ( Time - TiLstPrn >= 1 ) THEN + + CALL SimStatus( TiLstPrn, PrevClockTime, Time, TMax ) + + ENDIF + END DO + + + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + + CALL SD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + + !............................................................................................................................ + ! Write simulation times and stop + !............................................................................................................................ + + CALL RunTimes( StrtTime, UsrTime1, StrtTime, UsrTime1, Time ) + +CONTAINS + + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) + ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to + ! any existing echo information + !............................................................................................................................... + LOGICAL, INTENT( IN ) :: EchoFlag ! local version of echo flag + INTEGER, INTENT( IN ) :: UnEcho ! echo unit number + + + ! Close this module's echo file + + IF ( EchoFlag ) THEN + CLOSE(UnEcho) + END IF + + + + END SUBROUTINE CleanupEchoFile + + + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE CheckError(ErrID,Msg) + ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev + !............................................................................................................................... + + ! Passed arguments + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) + + !............................................................................................................................ + ! Set error status/message; + !............................................................................................................................ + + IF ( ErrID /= ErrID_None ) THEN + + IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine + ErrMsg = TRIM(ErrMsg)//' '//TRIM(Msg) + ErrStat = MAX(ErrStat, ErrID) + + !......................................................................................................................... + ! Clean up if we're going to return on error: close files, deallocate local arrays + !......................................................................................................................... + IF ( ErrStat >= AbortErrLev ) THEN + ! CALL CleanupInit(InputFileData, ErrStat3, ErrMsg3 ) + + END IF + + END IF + + + END SUBROUTINE CheckError + + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) + ! + !............................................................................................................................... + CHARACTER(*), INTENT( IN ) :: inputFile + TYPE(SD_Drvr_InitInput), INTENT( OUT ) :: InitInp + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + + INTEGER :: I ! generic integer for counting + INTEGER :: J ! generic integer for counting + CHARACTER( 2) :: strI ! string version of the loop counter + + INTEGER :: UnIn ! Unit number for the input file + INTEGER :: UnEchoLocal ! The local unit number for this module's echo file + CHARACTER(1024) :: EchoFile ! Name of SubDyn echo file + CHARACTER(1024) :: Line ! String to temporarially hold value of read line + CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name + CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement + CHARACTER(1024) :: FileName ! Name of SubDyn input file + CHARACTER(1024) :: FilePath ! Path Name of SubDyn input file + + UnEChoLocal=-1 + + FileName = TRIM(inputFile) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile( UnIn, FileName, ErrStat, ErrMsg ) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL WrScr( 'Failed to open SubDyn Driver input file.') + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + CALL WrScr( 'Opening SubDyn Driver input file: '//FileName ) + + + !------------------------------------------------------------------------------------------------- + ! File header + !------------------------------------------------------------------------------------------------- + + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat, ErrMsg ) + + IF ( ErrStat >= AbortErrLev ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat, ErrMsg ) + + IF ( ErrStat >= AbortErrLev ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! Echo Input Files. + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat, ErrMsg ) + + IF ( ErrStat >= AbortErrLev ) THEN + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + + ! If we are Echoing the input then we should re-read the first three lines so that we can echo them + ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable + ! which we must store, set, and then replace on error or completion. + + IF ( InitInp%Echo ) THEN + + EchoFile = TRIM(FileName)//'.echo' + CALL GetNewUnit( UnEchoLocal ) + CALL OpenEcho ( UnEchoLocal, EchoFile, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + !ErrMsg = ' Failed to open Echo file.' + ErrStat = ErrID_Fatal + CLOSE( UnIn ) + RETURN + END IF + + REWIND(UnIn) + + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read SubDyn Driver input file header line 1.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read SubDyn Driver input file header line 2.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. + + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat, ErrMsg, UnEchoLocal ) + !WRITE (UnEchoLocal,Frmt ) InitInp%Echo, 'Echo', 'Echo input file' + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Echo parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + END IF + !------------------------------------------------------------------------------------------------- + ! Environmental conditions section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! Gravity - Gravity. + + CALL ReadVar ( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Gravity parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! WtrDpth - Gravity. + + CALL ReadVar ( UnIn, FileName, InitInp%WtrDpth, 'WtrDpth', 'WtrDpth', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read WtrDpth parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + !------------------------------------------------------------------------------------------------- + ! SubDyn section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'SubDyn header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! HDInputFile + + CALL ReadVar ( UnIn, FileName, InitInp%SDInputFile, 'HDInputFile', & + 'SubDyn input filename', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read SDInputFile parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + IF ( PathIsRelative( InitInp%SDInputFile ) ) then + CALL GetPath( FileName, FilePath ) + InitInp%SDInputFile = TRIM(FilePath)//TRIM(InitInp%SDInputFile) + END IF + + ! OutRootName + + CALL ReadVar ( UnIn, FileName, InitInp%OutRootName, 'OutRootName', & + 'SubDyn output root filename', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read OutRootName parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! NSteps + + CALL ReadVar ( UnIn, FileName, InitInp%NSteps, 'NSteps', & + 'Number of time steps in the SubDyn simulation', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read NSteps parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! TimeInterval + + CALL ReadVar ( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', & + 'Time interval for any SubDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read TimeInterval parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + ! TP_RefPoint + + CALL ReadAry ( UnIn, FileName, InitInp%TP_RefPoint, 3, 'TP reference point', & + 'TP reference point', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read TP_RefPoint parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + ! SubRotateZ + + CALL ReadVar ( UnIn, FileName, InitInp%SubRotateZ, 'SubRotateZ', & + 'Rotation angle in degrees about Z axis.', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read SubRotateZ parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + !------------------------------------------------------------------------------------------------- + ! INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + + ! InputsMod + + CALL ReadVar ( UnIn, FileName, InitInp%InputsMod, 'InputsMod', & + 'Model for the inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read InputsMod parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! InputsFile + + CALL ReadVar ( UnIn, FileName, InitInp%InputsFile, 'InputsFile', & + 'Filename for the SubDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read InputsFile parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! STEADY STATE INPUTS section + !------------------------------------------------------------------------------------------------- + + ! Header + + CALL ReadCom( UnIn, FileName, 'STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read Comment line.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + IF ( InitInp%InputsMod == 1 ) THEN + + ! uTPInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uTPInSteady, 6, 'uInSteady', & + 'Steady-state TP displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uTPInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotTPInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotTPInSteady, 6, 'uDotTPInSteady', & + ' Steady-state TP translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotTPInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + + + ! uDotDotTPInSteady + + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotTPInSteady, 6, 'uDotDotTPInSteady', & + ' Steady-state TP translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) + + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Failed to read uDotDotTPInSteady parameter.' + ErrStat = ErrID_Fatal + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + END IF + ELSE + InitInp%uTPInSteady = 0.0 + InitInp%uDotTPInSteady = 0.0 + InitInp%uDotDotTPInSteady = 0.0 + END IF + + + CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + CLOSE( UnIn ) + + END SUBROUTINE ReadDriverInputFile + + subroutine print_help() + print '(a)', 'usage: ' + print '(a)', '' + print '(a)', 'SubDynDriver.exe driverfilename' + print '(a)', '' + print '(a)', 'Where driverfilename is the name of the SubDyn driver input file.' + print '(a)', '' + end subroutine print_help + +!---------------------------------------------------------------------------------------------------------------------------------- + +END PROGRAM TestSubDyn diff --git a/OpenFAST/modules/subdyn/src/SubDyn_Output.f90 b/OpenFAST/modules/subdyn/src/SubDyn_Output.f90 new file mode 100644 index 000000000..cbd2913c4 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SubDyn_Output.f90 @@ -0,0 +1,4932 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! 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 SubDyn_Output + + ! This MODULE stores variables used for output. + + USE NWTC_Library + USE SubDyn_Types + USE SD_FEM + IMPLICIT NONE + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 + INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + + PRIVATE + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + + ! Time: + + INTEGER, PARAMETER :: Time = 0 + + + ! Member Forces: + + INTEGER(IntKi), PARAMETER :: M1N1FKxe = 1 + INTEGER(IntKi), PARAMETER :: M1N2FKxe = 2 + INTEGER(IntKi), PARAMETER :: M1N3FKxe = 3 + INTEGER(IntKi), PARAMETER :: M1N4FKxe = 4 + INTEGER(IntKi), PARAMETER :: M1N5FKxe = 5 + INTEGER(IntKi), PARAMETER :: M1N6FKxe = 6 + INTEGER(IntKi), PARAMETER :: M1N7FKxe = 7 + INTEGER(IntKi), PARAMETER :: M1N8FKxe = 8 + INTEGER(IntKi), PARAMETER :: M1N9FKxe = 9 + INTEGER(IntKi), PARAMETER :: M2N1FKxe = 10 + INTEGER(IntKi), PARAMETER :: M2N2FKxe = 11 + INTEGER(IntKi), PARAMETER :: M2N3FKxe = 12 + INTEGER(IntKi), PARAMETER :: M2N4FKxe = 13 + INTEGER(IntKi), PARAMETER :: M2N5FKxe = 14 + INTEGER(IntKi), PARAMETER :: M2N6FKxe = 15 + INTEGER(IntKi), PARAMETER :: M2N7FKxe = 16 + INTEGER(IntKi), PARAMETER :: M2N8FKxe = 17 + INTEGER(IntKi), PARAMETER :: M2N9FKxe = 18 + INTEGER(IntKi), PARAMETER :: M3N1FKxe = 19 + INTEGER(IntKi), PARAMETER :: M3N2FKxe = 20 + INTEGER(IntKi), PARAMETER :: M3N3FKxe = 21 + INTEGER(IntKi), PARAMETER :: M3N4FKxe = 22 + INTEGER(IntKi), PARAMETER :: M3N5FKxe = 23 + INTEGER(IntKi), PARAMETER :: M3N6FKxe = 24 + INTEGER(IntKi), PARAMETER :: M3N7FKxe = 25 + INTEGER(IntKi), PARAMETER :: M3N8FKxe = 26 + INTEGER(IntKi), PARAMETER :: M3N9FKxe = 27 + INTEGER(IntKi), PARAMETER :: M4N1FKxe = 28 + INTEGER(IntKi), PARAMETER :: M4N2FKxe = 29 + INTEGER(IntKi), PARAMETER :: M4N3FKxe = 30 + INTEGER(IntKi), PARAMETER :: M4N4FKxe = 31 + INTEGER(IntKi), PARAMETER :: M4N5FKxe = 32 + INTEGER(IntKi), PARAMETER :: M4N6FKxe = 33 + INTEGER(IntKi), PARAMETER :: M4N7FKxe = 34 + INTEGER(IntKi), PARAMETER :: M4N8FKxe = 35 + INTEGER(IntKi), PARAMETER :: M4N9FKxe = 36 + INTEGER(IntKi), PARAMETER :: M5N1FKxe = 37 + INTEGER(IntKi), PARAMETER :: M5N2FKxe = 38 + INTEGER(IntKi), PARAMETER :: M5N3FKxe = 39 + INTEGER(IntKi), PARAMETER :: M5N4FKxe = 40 + INTEGER(IntKi), PARAMETER :: M5N5FKxe = 41 + INTEGER(IntKi), PARAMETER :: M5N6FKxe = 42 + INTEGER(IntKi), PARAMETER :: M5N7FKxe = 43 + INTEGER(IntKi), PARAMETER :: M5N8FKxe = 44 + INTEGER(IntKi), PARAMETER :: M5N9FKxe = 45 + INTEGER(IntKi), PARAMETER :: M6N1FKxe = 46 + INTEGER(IntKi), PARAMETER :: M6N2FKxe = 47 + INTEGER(IntKi), PARAMETER :: M6N3FKxe = 48 + INTEGER(IntKi), PARAMETER :: M6N4FKxe = 49 + INTEGER(IntKi), PARAMETER :: M6N5FKxe = 50 + INTEGER(IntKi), PARAMETER :: M6N6FKxe = 51 + INTEGER(IntKi), PARAMETER :: M6N7FKxe = 52 + INTEGER(IntKi), PARAMETER :: M6N8FKxe = 53 + INTEGER(IntKi), PARAMETER :: M6N9FKxe = 54 + INTEGER(IntKi), PARAMETER :: M7N1FKxe = 55 + INTEGER(IntKi), PARAMETER :: M7N2FKxe = 56 + INTEGER(IntKi), PARAMETER :: M7N3FKxe = 57 + INTEGER(IntKi), PARAMETER :: M7N4FKxe = 58 + INTEGER(IntKi), PARAMETER :: M7N5FKxe = 59 + INTEGER(IntKi), PARAMETER :: M7N6FKxe = 60 + INTEGER(IntKi), PARAMETER :: M7N7FKxe = 61 + INTEGER(IntKi), PARAMETER :: M7N8FKxe = 62 + INTEGER(IntKi), PARAMETER :: M7N9FKxe = 63 + INTEGER(IntKi), PARAMETER :: M8N1FKxe = 64 + INTEGER(IntKi), PARAMETER :: M8N2FKxe = 65 + INTEGER(IntKi), PARAMETER :: M8N3FKxe = 66 + INTEGER(IntKi), PARAMETER :: M8N4FKxe = 67 + INTEGER(IntKi), PARAMETER :: M8N5FKxe = 68 + INTEGER(IntKi), PARAMETER :: M8N6FKxe = 69 + INTEGER(IntKi), PARAMETER :: M8N7FKxe = 70 + INTEGER(IntKi), PARAMETER :: M8N8FKxe = 71 + INTEGER(IntKi), PARAMETER :: M8N9FKxe = 72 + INTEGER(IntKi), PARAMETER :: M9N1FKxe = 73 + INTEGER(IntKi), PARAMETER :: M9N2FKxe = 74 + INTEGER(IntKi), PARAMETER :: M9N3FKxe = 75 + INTEGER(IntKi), PARAMETER :: M9N4FKxe = 76 + INTEGER(IntKi), PARAMETER :: M9N5FKxe = 77 + INTEGER(IntKi), PARAMETER :: M9N6FKxe = 78 + INTEGER(IntKi), PARAMETER :: M9N7FKxe = 79 + INTEGER(IntKi), PARAMETER :: M9N8FKxe = 80 + INTEGER(IntKi), PARAMETER :: M9N9FKxe = 81 + INTEGER(IntKi), PARAMETER :: M1N1FKye = 82 + INTEGER(IntKi), PARAMETER :: M1N2FKye = 83 + INTEGER(IntKi), PARAMETER :: M1N3FKye = 84 + INTEGER(IntKi), PARAMETER :: M1N4FKye = 85 + INTEGER(IntKi), PARAMETER :: M1N5FKye = 86 + INTEGER(IntKi), PARAMETER :: M1N6FKye = 87 + INTEGER(IntKi), PARAMETER :: M1N7FKye = 88 + INTEGER(IntKi), PARAMETER :: M1N8FKye = 89 + INTEGER(IntKi), PARAMETER :: M1N9FKye = 90 + INTEGER(IntKi), PARAMETER :: M2N1FKye = 91 + INTEGER(IntKi), PARAMETER :: M2N2FKye = 92 + INTEGER(IntKi), PARAMETER :: M2N3FKye = 93 + INTEGER(IntKi), PARAMETER :: M2N4FKye = 94 + INTEGER(IntKi), PARAMETER :: M2N5FKye = 95 + INTEGER(IntKi), PARAMETER :: M2N6FKye = 96 + INTEGER(IntKi), PARAMETER :: M2N7FKye = 97 + INTEGER(IntKi), PARAMETER :: M2N8FKye = 98 + INTEGER(IntKi), PARAMETER :: M2N9FKye = 99 + INTEGER(IntKi), PARAMETER :: M3N1FKye = 100 + INTEGER(IntKi), PARAMETER :: M3N2FKye = 101 + INTEGER(IntKi), PARAMETER :: M3N3FKye = 102 + INTEGER(IntKi), PARAMETER :: M3N4FKye = 103 + INTEGER(IntKi), PARAMETER :: M3N5FKye = 104 + INTEGER(IntKi), PARAMETER :: M3N6FKye = 105 + INTEGER(IntKi), PARAMETER :: M3N7FKye = 106 + INTEGER(IntKi), PARAMETER :: M3N8FKye = 107 + INTEGER(IntKi), PARAMETER :: M3N9FKye = 108 + INTEGER(IntKi), PARAMETER :: M4N1FKye = 109 + INTEGER(IntKi), PARAMETER :: M4N2FKye = 110 + INTEGER(IntKi), PARAMETER :: M4N3FKye = 111 + INTEGER(IntKi), PARAMETER :: M4N4FKye = 112 + INTEGER(IntKi), PARAMETER :: M4N5FKye = 113 + INTEGER(IntKi), PARAMETER :: M4N6FKye = 114 + INTEGER(IntKi), PARAMETER :: M4N7FKye = 115 + INTEGER(IntKi), PARAMETER :: M4N8FKye = 116 + INTEGER(IntKi), PARAMETER :: M4N9FKye = 117 + INTEGER(IntKi), PARAMETER :: M5N1FKye = 118 + INTEGER(IntKi), PARAMETER :: M5N2FKye = 119 + INTEGER(IntKi), PARAMETER :: M5N3FKye = 120 + INTEGER(IntKi), PARAMETER :: M5N4FKye = 121 + INTEGER(IntKi), PARAMETER :: M5N5FKye = 122 + INTEGER(IntKi), PARAMETER :: M5N6FKye = 123 + INTEGER(IntKi), PARAMETER :: M5N7FKye = 124 + INTEGER(IntKi), PARAMETER :: M5N8FKye = 125 + INTEGER(IntKi), PARAMETER :: M5N9FKye = 126 + INTEGER(IntKi), PARAMETER :: M6N1FKye = 127 + INTEGER(IntKi), PARAMETER :: M6N2FKye = 128 + INTEGER(IntKi), PARAMETER :: M6N3FKye = 129 + INTEGER(IntKi), PARAMETER :: M6N4FKye = 130 + INTEGER(IntKi), PARAMETER :: M6N5FKye = 131 + INTEGER(IntKi), PARAMETER :: M6N6FKye = 132 + INTEGER(IntKi), PARAMETER :: M6N7FKye = 133 + INTEGER(IntKi), PARAMETER :: M6N8FKye = 134 + INTEGER(IntKi), PARAMETER :: M6N9FKye = 135 + INTEGER(IntKi), PARAMETER :: M7N1FKye = 136 + INTEGER(IntKi), PARAMETER :: M7N2FKye = 137 + INTEGER(IntKi), PARAMETER :: M7N3FKye = 138 + INTEGER(IntKi), PARAMETER :: M7N4FKye = 139 + INTEGER(IntKi), PARAMETER :: M7N5FKye = 140 + INTEGER(IntKi), PARAMETER :: M7N6FKye = 141 + INTEGER(IntKi), PARAMETER :: M7N7FKye = 142 + INTEGER(IntKi), PARAMETER :: M7N8FKye = 143 + INTEGER(IntKi), PARAMETER :: M7N9FKye = 144 + INTEGER(IntKi), PARAMETER :: M8N1FKye = 145 + INTEGER(IntKi), PARAMETER :: M8N2FKye = 146 + INTEGER(IntKi), PARAMETER :: M8N3FKye = 147 + INTEGER(IntKi), PARAMETER :: M8N4FKye = 148 + INTEGER(IntKi), PARAMETER :: M8N5FKye = 149 + INTEGER(IntKi), PARAMETER :: M8N6FKye = 150 + INTEGER(IntKi), PARAMETER :: M8N7FKye = 151 + INTEGER(IntKi), PARAMETER :: M8N8FKye = 152 + INTEGER(IntKi), PARAMETER :: M8N9FKye = 153 + INTEGER(IntKi), PARAMETER :: M9N1FKye = 154 + INTEGER(IntKi), PARAMETER :: M9N2FKye = 155 + INTEGER(IntKi), PARAMETER :: M9N3FKye = 156 + INTEGER(IntKi), PARAMETER :: M9N4FKye = 157 + INTEGER(IntKi), PARAMETER :: M9N5FKye = 158 + INTEGER(IntKi), PARAMETER :: M9N6FKye = 159 + INTEGER(IntKi), PARAMETER :: M9N7FKye = 160 + INTEGER(IntKi), PARAMETER :: M9N8FKye = 161 + INTEGER(IntKi), PARAMETER :: M9N9FKye = 162 + INTEGER(IntKi), PARAMETER :: M1N1FKze = 163 + INTEGER(IntKi), PARAMETER :: M1N2FKze = 164 + INTEGER(IntKi), PARAMETER :: M1N3FKze = 165 + INTEGER(IntKi), PARAMETER :: M1N4FKze = 166 + INTEGER(IntKi), PARAMETER :: M1N5FKze = 167 + INTEGER(IntKi), PARAMETER :: M1N6FKze = 168 + INTEGER(IntKi), PARAMETER :: M1N7FKze = 169 + INTEGER(IntKi), PARAMETER :: M1N8FKze = 170 + INTEGER(IntKi), PARAMETER :: M1N9FKze = 171 + INTEGER(IntKi), PARAMETER :: M2N1FKze = 172 + INTEGER(IntKi), PARAMETER :: M2N2FKze = 173 + INTEGER(IntKi), PARAMETER :: M2N3FKze = 174 + INTEGER(IntKi), PARAMETER :: M2N4FKze = 175 + INTEGER(IntKi), PARAMETER :: M2N5FKze = 176 + INTEGER(IntKi), PARAMETER :: M2N6FKze = 177 + INTEGER(IntKi), PARAMETER :: M2N7FKze = 178 + INTEGER(IntKi), PARAMETER :: M2N8FKze = 179 + INTEGER(IntKi), PARAMETER :: M2N9FKze = 180 + INTEGER(IntKi), PARAMETER :: M3N1FKze = 181 + INTEGER(IntKi), PARAMETER :: M3N2FKze = 182 + INTEGER(IntKi), PARAMETER :: M3N3FKze = 183 + INTEGER(IntKi), PARAMETER :: M3N4FKze = 184 + INTEGER(IntKi), PARAMETER :: M3N5FKze = 185 + INTEGER(IntKi), PARAMETER :: M3N6FKze = 186 + INTEGER(IntKi), PARAMETER :: M3N7FKze = 187 + INTEGER(IntKi), PARAMETER :: M3N8FKze = 188 + INTEGER(IntKi), PARAMETER :: M3N9FKze = 189 + INTEGER(IntKi), PARAMETER :: M4N1FKze = 190 + INTEGER(IntKi), PARAMETER :: M4N2FKze = 191 + INTEGER(IntKi), PARAMETER :: M4N3FKze = 192 + INTEGER(IntKi), PARAMETER :: M4N4FKze = 193 + INTEGER(IntKi), PARAMETER :: M4N5FKze = 194 + INTEGER(IntKi), PARAMETER :: M4N6FKze = 195 + INTEGER(IntKi), PARAMETER :: M4N7FKze = 196 + INTEGER(IntKi), PARAMETER :: M4N8FKze = 197 + INTEGER(IntKi), PARAMETER :: M4N9FKze = 198 + INTEGER(IntKi), PARAMETER :: M5N1FKze = 199 + INTEGER(IntKi), PARAMETER :: M5N2FKze = 200 + INTEGER(IntKi), PARAMETER :: M5N3FKze = 201 + INTEGER(IntKi), PARAMETER :: M5N4FKze = 202 + INTEGER(IntKi), PARAMETER :: M5N5FKze = 203 + INTEGER(IntKi), PARAMETER :: M5N6FKze = 204 + INTEGER(IntKi), PARAMETER :: M5N7FKze = 205 + INTEGER(IntKi), PARAMETER :: M5N8FKze = 206 + INTEGER(IntKi), PARAMETER :: M5N9FKze = 207 + INTEGER(IntKi), PARAMETER :: M6N1FKze = 208 + INTEGER(IntKi), PARAMETER :: M6N2FKze = 209 + INTEGER(IntKi), PARAMETER :: M6N3FKze = 210 + INTEGER(IntKi), PARAMETER :: M6N4FKze = 211 + INTEGER(IntKi), PARAMETER :: M6N5FKze = 212 + INTEGER(IntKi), PARAMETER :: M6N6FKze = 213 + INTEGER(IntKi), PARAMETER :: M6N7FKze = 214 + INTEGER(IntKi), PARAMETER :: M6N8FKze = 215 + INTEGER(IntKi), PARAMETER :: M6N9FKze = 216 + INTEGER(IntKi), PARAMETER :: M7N1FKze = 217 + INTEGER(IntKi), PARAMETER :: M7N2FKze = 218 + INTEGER(IntKi), PARAMETER :: M7N3FKze = 219 + INTEGER(IntKi), PARAMETER :: M7N4FKze = 220 + INTEGER(IntKi), PARAMETER :: M7N5FKze = 221 + INTEGER(IntKi), PARAMETER :: M7N6FKze = 222 + INTEGER(IntKi), PARAMETER :: M7N7FKze = 223 + INTEGER(IntKi), PARAMETER :: M7N8FKze = 224 + INTEGER(IntKi), PARAMETER :: M7N9FKze = 225 + INTEGER(IntKi), PARAMETER :: M8N1FKze = 226 + INTEGER(IntKi), PARAMETER :: M8N2FKze = 227 + INTEGER(IntKi), PARAMETER :: M8N3FKze = 228 + INTEGER(IntKi), PARAMETER :: M8N4FKze = 229 + INTEGER(IntKi), PARAMETER :: M8N5FKze = 230 + INTEGER(IntKi), PARAMETER :: M8N6FKze = 231 + INTEGER(IntKi), PARAMETER :: M8N7FKze = 232 + INTEGER(IntKi), PARAMETER :: M8N8FKze = 233 + INTEGER(IntKi), PARAMETER :: M8N9FKze = 234 + INTEGER(IntKi), PARAMETER :: M9N1FKze = 235 + INTEGER(IntKi), PARAMETER :: M9N2FKze = 236 + INTEGER(IntKi), PARAMETER :: M9N3FKze = 237 + INTEGER(IntKi), PARAMETER :: M9N4FKze = 238 + INTEGER(IntKi), PARAMETER :: M9N5FKze = 239 + INTEGER(IntKi), PARAMETER :: M9N6FKze = 240 + INTEGER(IntKi), PARAMETER :: M9N7FKze = 241 + INTEGER(IntKi), PARAMETER :: M9N8FKze = 242 + INTEGER(IntKi), PARAMETER :: M9N9FKze = 243 + INTEGER(IntKi), PARAMETER :: M1N1FMxe = 244 + INTEGER(IntKi), PARAMETER :: M1N2FMxe = 245 + INTEGER(IntKi), PARAMETER :: M1N3FMxe = 246 + INTEGER(IntKi), PARAMETER :: M1N4FMxe = 247 + INTEGER(IntKi), PARAMETER :: M1N5FMxe = 248 + INTEGER(IntKi), PARAMETER :: M1N6FMxe = 249 + INTEGER(IntKi), PARAMETER :: M1N7FMxe = 250 + INTEGER(IntKi), PARAMETER :: M1N8FMxe = 251 + INTEGER(IntKi), PARAMETER :: M1N9FMxe = 252 + INTEGER(IntKi), PARAMETER :: M2N1FMxe = 253 + INTEGER(IntKi), PARAMETER :: M2N2FMxe = 254 + INTEGER(IntKi), PARAMETER :: M2N3FMxe = 255 + INTEGER(IntKi), PARAMETER :: M2N4FMxe = 256 + INTEGER(IntKi), PARAMETER :: M2N5FMxe = 257 + INTEGER(IntKi), PARAMETER :: M2N6FMxe = 258 + INTEGER(IntKi), PARAMETER :: M2N7FMxe = 259 + INTEGER(IntKi), PARAMETER :: M2N8FMxe = 260 + INTEGER(IntKi), PARAMETER :: M2N9FMxe = 261 + INTEGER(IntKi), PARAMETER :: M3N1FMxe = 262 + INTEGER(IntKi), PARAMETER :: M3N2FMxe = 263 + INTEGER(IntKi), PARAMETER :: M3N3FMxe = 264 + INTEGER(IntKi), PARAMETER :: M3N4FMxe = 265 + INTEGER(IntKi), PARAMETER :: M3N5FMxe = 266 + INTEGER(IntKi), PARAMETER :: M3N6FMxe = 267 + INTEGER(IntKi), PARAMETER :: M3N7FMxe = 268 + INTEGER(IntKi), PARAMETER :: M3N8FMxe = 269 + INTEGER(IntKi), PARAMETER :: M3N9FMxe = 270 + INTEGER(IntKi), PARAMETER :: M4N1FMxe = 271 + INTEGER(IntKi), PARAMETER :: M4N2FMxe = 272 + INTEGER(IntKi), PARAMETER :: M4N3FMxe = 273 + INTEGER(IntKi), PARAMETER :: M4N4FMxe = 274 + INTEGER(IntKi), PARAMETER :: M4N5FMxe = 275 + INTEGER(IntKi), PARAMETER :: M4N6FMxe = 276 + INTEGER(IntKi), PARAMETER :: M4N7FMxe = 277 + INTEGER(IntKi), PARAMETER :: M4N8FMxe = 278 + INTEGER(IntKi), PARAMETER :: M4N9FMxe = 279 + INTEGER(IntKi), PARAMETER :: M5N1FMxe = 280 + INTEGER(IntKi), PARAMETER :: M5N2FMxe = 281 + INTEGER(IntKi), PARAMETER :: M5N3FMxe = 282 + INTEGER(IntKi), PARAMETER :: M5N4FMxe = 283 + INTEGER(IntKi), PARAMETER :: M5N5FMxe = 284 + INTEGER(IntKi), PARAMETER :: M5N6FMxe = 285 + INTEGER(IntKi), PARAMETER :: M5N7FMxe = 286 + INTEGER(IntKi), PARAMETER :: M5N8FMxe = 287 + INTEGER(IntKi), PARAMETER :: M5N9FMxe = 288 + INTEGER(IntKi), PARAMETER :: M6N1FMxe = 289 + INTEGER(IntKi), PARAMETER :: M6N2FMxe = 290 + INTEGER(IntKi), PARAMETER :: M6N3FMxe = 291 + INTEGER(IntKi), PARAMETER :: M6N4FMxe = 292 + INTEGER(IntKi), PARAMETER :: M6N5FMxe = 293 + INTEGER(IntKi), PARAMETER :: M6N6FMxe = 294 + INTEGER(IntKi), PARAMETER :: M6N7FMxe = 295 + INTEGER(IntKi), PARAMETER :: M6N8FMxe = 296 + INTEGER(IntKi), PARAMETER :: M6N9FMxe = 297 + INTEGER(IntKi), PARAMETER :: M7N1FMxe = 298 + INTEGER(IntKi), PARAMETER :: M7N2FMxe = 299 + INTEGER(IntKi), PARAMETER :: M7N3FMxe = 300 + INTEGER(IntKi), PARAMETER :: M7N4FMxe = 301 + INTEGER(IntKi), PARAMETER :: M7N5FMxe = 302 + INTEGER(IntKi), PARAMETER :: M7N6FMxe = 303 + INTEGER(IntKi), PARAMETER :: M7N7FMxe = 304 + INTEGER(IntKi), PARAMETER :: M7N8FMxe = 305 + INTEGER(IntKi), PARAMETER :: M7N9FMxe = 306 + INTEGER(IntKi), PARAMETER :: M8N1FMxe = 307 + INTEGER(IntKi), PARAMETER :: M8N2FMxe = 308 + INTEGER(IntKi), PARAMETER :: M8N3FMxe = 309 + INTEGER(IntKi), PARAMETER :: M8N4FMxe = 310 + INTEGER(IntKi), PARAMETER :: M8N5FMxe = 311 + INTEGER(IntKi), PARAMETER :: M8N6FMxe = 312 + INTEGER(IntKi), PARAMETER :: M8N7FMxe = 313 + INTEGER(IntKi), PARAMETER :: M8N8FMxe = 314 + INTEGER(IntKi), PARAMETER :: M8N9FMxe = 315 + INTEGER(IntKi), PARAMETER :: M9N1FMxe = 316 + INTEGER(IntKi), PARAMETER :: M9N2FMxe = 317 + INTEGER(IntKi), PARAMETER :: M9N3FMxe = 318 + INTEGER(IntKi), PARAMETER :: M9N4FMxe = 319 + INTEGER(IntKi), PARAMETER :: M9N5FMxe = 320 + INTEGER(IntKi), PARAMETER :: M9N6FMxe = 321 + INTEGER(IntKi), PARAMETER :: M9N7FMxe = 322 + INTEGER(IntKi), PARAMETER :: M9N8FMxe = 323 + INTEGER(IntKi), PARAMETER :: M9N9FMxe = 324 + INTEGER(IntKi), PARAMETER :: M1N1FMye = 325 + INTEGER(IntKi), PARAMETER :: M1N2FMye = 326 + INTEGER(IntKi), PARAMETER :: M1N3FMye = 327 + INTEGER(IntKi), PARAMETER :: M1N4FMye = 328 + INTEGER(IntKi), PARAMETER :: M1N5FMye = 329 + INTEGER(IntKi), PARAMETER :: M1N6FMye = 330 + INTEGER(IntKi), PARAMETER :: M1N7FMye = 331 + INTEGER(IntKi), PARAMETER :: M1N8FMye = 332 + INTEGER(IntKi), PARAMETER :: M1N9FMye = 333 + INTEGER(IntKi), PARAMETER :: M2N1FMye = 334 + INTEGER(IntKi), PARAMETER :: M2N2FMye = 335 + INTEGER(IntKi), PARAMETER :: M2N3FMye = 336 + INTEGER(IntKi), PARAMETER :: M2N4FMye = 337 + INTEGER(IntKi), PARAMETER :: M2N5FMye = 338 + INTEGER(IntKi), PARAMETER :: M2N6FMye = 339 + INTEGER(IntKi), PARAMETER :: M2N7FMye = 340 + INTEGER(IntKi), PARAMETER :: M2N8FMye = 341 + INTEGER(IntKi), PARAMETER :: M2N9FMye = 342 + INTEGER(IntKi), PARAMETER :: M3N1FMye = 343 + INTEGER(IntKi), PARAMETER :: M3N2FMye = 344 + INTEGER(IntKi), PARAMETER :: M3N3FMye = 345 + INTEGER(IntKi), PARAMETER :: M3N4FMye = 346 + INTEGER(IntKi), PARAMETER :: M3N5FMye = 347 + INTEGER(IntKi), PARAMETER :: M3N6FMye = 348 + INTEGER(IntKi), PARAMETER :: M3N7FMye = 349 + INTEGER(IntKi), PARAMETER :: M3N8FMye = 350 + INTEGER(IntKi), PARAMETER :: M3N9FMye = 351 + INTEGER(IntKi), PARAMETER :: M4N1FMye = 352 + INTEGER(IntKi), PARAMETER :: M4N2FMye = 353 + INTEGER(IntKi), PARAMETER :: M4N3FMye = 354 + INTEGER(IntKi), PARAMETER :: M4N4FMye = 355 + INTEGER(IntKi), PARAMETER :: M4N5FMye = 356 + INTEGER(IntKi), PARAMETER :: M4N6FMye = 357 + INTEGER(IntKi), PARAMETER :: M4N7FMye = 358 + INTEGER(IntKi), PARAMETER :: M4N8FMye = 359 + INTEGER(IntKi), PARAMETER :: M4N9FMye = 360 + INTEGER(IntKi), PARAMETER :: M5N1FMye = 361 + INTEGER(IntKi), PARAMETER :: M5N2FMye = 362 + INTEGER(IntKi), PARAMETER :: M5N3FMye = 363 + INTEGER(IntKi), PARAMETER :: M5N4FMye = 364 + INTEGER(IntKi), PARAMETER :: M5N5FMye = 365 + INTEGER(IntKi), PARAMETER :: M5N6FMye = 366 + INTEGER(IntKi), PARAMETER :: M5N7FMye = 367 + INTEGER(IntKi), PARAMETER :: M5N8FMye = 368 + INTEGER(IntKi), PARAMETER :: M5N9FMye = 369 + INTEGER(IntKi), PARAMETER :: M6N1FMye = 370 + INTEGER(IntKi), PARAMETER :: M6N2FMye = 371 + INTEGER(IntKi), PARAMETER :: M6N3FMye = 372 + INTEGER(IntKi), PARAMETER :: M6N4FMye = 373 + INTEGER(IntKi), PARAMETER :: M6N5FMye = 374 + INTEGER(IntKi), PARAMETER :: M6N6FMye = 375 + INTEGER(IntKi), PARAMETER :: M6N7FMye = 376 + INTEGER(IntKi), PARAMETER :: M6N8FMye = 377 + INTEGER(IntKi), PARAMETER :: M6N9FMye = 378 + INTEGER(IntKi), PARAMETER :: M7N1FMye = 379 + INTEGER(IntKi), PARAMETER :: M7N2FMye = 380 + INTEGER(IntKi), PARAMETER :: M7N3FMye = 381 + INTEGER(IntKi), PARAMETER :: M7N4FMye = 382 + INTEGER(IntKi), PARAMETER :: M7N5FMye = 383 + INTEGER(IntKi), PARAMETER :: M7N6FMye = 384 + INTEGER(IntKi), PARAMETER :: M7N7FMye = 385 + INTEGER(IntKi), PARAMETER :: M7N8FMye = 386 + INTEGER(IntKi), PARAMETER :: M7N9FMye = 387 + INTEGER(IntKi), PARAMETER :: M8N1FMye = 388 + INTEGER(IntKi), PARAMETER :: M8N2FMye = 389 + INTEGER(IntKi), PARAMETER :: M8N3FMye = 390 + INTEGER(IntKi), PARAMETER :: M8N4FMye = 391 + INTEGER(IntKi), PARAMETER :: M8N5FMye = 392 + INTEGER(IntKi), PARAMETER :: M8N6FMye = 393 + INTEGER(IntKi), PARAMETER :: M8N7FMye = 394 + INTEGER(IntKi), PARAMETER :: M8N8FMye = 395 + INTEGER(IntKi), PARAMETER :: M8N9FMye = 396 + INTEGER(IntKi), PARAMETER :: M9N1FMye = 397 + INTEGER(IntKi), PARAMETER :: M9N2FMye = 398 + INTEGER(IntKi), PARAMETER :: M9N3FMye = 399 + INTEGER(IntKi), PARAMETER :: M9N4FMye = 400 + INTEGER(IntKi), PARAMETER :: M9N5FMye = 401 + INTEGER(IntKi), PARAMETER :: M9N6FMye = 402 + INTEGER(IntKi), PARAMETER :: M9N7FMye = 403 + INTEGER(IntKi), PARAMETER :: M9N8FMye = 404 + INTEGER(IntKi), PARAMETER :: M9N9FMye = 405 + INTEGER(IntKi), PARAMETER :: M1N1FMze = 406 + INTEGER(IntKi), PARAMETER :: M1N2FMze = 407 + INTEGER(IntKi), PARAMETER :: M1N3FMze = 408 + INTEGER(IntKi), PARAMETER :: M1N4FMze = 409 + INTEGER(IntKi), PARAMETER :: M1N5FMze = 410 + INTEGER(IntKi), PARAMETER :: M1N6FMze = 411 + INTEGER(IntKi), PARAMETER :: M1N7FMze = 412 + INTEGER(IntKi), PARAMETER :: M1N8FMze = 413 + INTEGER(IntKi), PARAMETER :: M1N9FMze = 414 + INTEGER(IntKi), PARAMETER :: M2N1FMze = 415 + INTEGER(IntKi), PARAMETER :: M2N2FMze = 416 + INTEGER(IntKi), PARAMETER :: M2N3FMze = 417 + INTEGER(IntKi), PARAMETER :: M2N4FMze = 418 + INTEGER(IntKi), PARAMETER :: M2N5FMze = 419 + INTEGER(IntKi), PARAMETER :: M2N6FMze = 420 + INTEGER(IntKi), PARAMETER :: M2N7FMze = 421 + INTEGER(IntKi), PARAMETER :: M2N8FMze = 422 + INTEGER(IntKi), PARAMETER :: M2N9FMze = 423 + INTEGER(IntKi), PARAMETER :: M3N1FMze = 424 + INTEGER(IntKi), PARAMETER :: M3N2FMze = 425 + INTEGER(IntKi), PARAMETER :: M3N3FMze = 426 + INTEGER(IntKi), PARAMETER :: M3N4FMze = 427 + INTEGER(IntKi), PARAMETER :: M3N5FMze = 428 + INTEGER(IntKi), PARAMETER :: M3N6FMze = 429 + INTEGER(IntKi), PARAMETER :: M3N7FMze = 430 + INTEGER(IntKi), PARAMETER :: M3N8FMze = 431 + INTEGER(IntKi), PARAMETER :: M3N9FMze = 432 + INTEGER(IntKi), PARAMETER :: M4N1FMze = 433 + INTEGER(IntKi), PARAMETER :: M4N2FMze = 434 + INTEGER(IntKi), PARAMETER :: M4N3FMze = 435 + INTEGER(IntKi), PARAMETER :: M4N4FMze = 436 + INTEGER(IntKi), PARAMETER :: M4N5FMze = 437 + INTEGER(IntKi), PARAMETER :: M4N6FMze = 438 + INTEGER(IntKi), PARAMETER :: M4N7FMze = 439 + INTEGER(IntKi), PARAMETER :: M4N8FMze = 440 + INTEGER(IntKi), PARAMETER :: M4N9FMze = 441 + INTEGER(IntKi), PARAMETER :: M5N1FMze = 442 + INTEGER(IntKi), PARAMETER :: M5N2FMze = 443 + INTEGER(IntKi), PARAMETER :: M5N3FMze = 444 + INTEGER(IntKi), PARAMETER :: M5N4FMze = 445 + INTEGER(IntKi), PARAMETER :: M5N5FMze = 446 + INTEGER(IntKi), PARAMETER :: M5N6FMze = 447 + INTEGER(IntKi), PARAMETER :: M5N7FMze = 448 + INTEGER(IntKi), PARAMETER :: M5N8FMze = 449 + INTEGER(IntKi), PARAMETER :: M5N9FMze = 450 + INTEGER(IntKi), PARAMETER :: M6N1FMze = 451 + INTEGER(IntKi), PARAMETER :: M6N2FMze = 452 + INTEGER(IntKi), PARAMETER :: M6N3FMze = 453 + INTEGER(IntKi), PARAMETER :: M6N4FMze = 454 + INTEGER(IntKi), PARAMETER :: M6N5FMze = 455 + INTEGER(IntKi), PARAMETER :: M6N6FMze = 456 + INTEGER(IntKi), PARAMETER :: M6N7FMze = 457 + INTEGER(IntKi), PARAMETER :: M6N8FMze = 458 + INTEGER(IntKi), PARAMETER :: M6N9FMze = 459 + INTEGER(IntKi), PARAMETER :: M7N1FMze = 460 + INTEGER(IntKi), PARAMETER :: M7N2FMze = 461 + INTEGER(IntKi), PARAMETER :: M7N3FMze = 462 + INTEGER(IntKi), PARAMETER :: M7N4FMze = 463 + INTEGER(IntKi), PARAMETER :: M7N5FMze = 464 + INTEGER(IntKi), PARAMETER :: M7N6FMze = 465 + INTEGER(IntKi), PARAMETER :: M7N7FMze = 466 + INTEGER(IntKi), PARAMETER :: M7N8FMze = 467 + INTEGER(IntKi), PARAMETER :: M7N9FMze = 468 + INTEGER(IntKi), PARAMETER :: M8N1FMze = 469 + INTEGER(IntKi), PARAMETER :: M8N2FMze = 470 + INTEGER(IntKi), PARAMETER :: M8N3FMze = 471 + INTEGER(IntKi), PARAMETER :: M8N4FMze = 472 + INTEGER(IntKi), PARAMETER :: M8N5FMze = 473 + INTEGER(IntKi), PARAMETER :: M8N6FMze = 474 + INTEGER(IntKi), PARAMETER :: M8N7FMze = 475 + INTEGER(IntKi), PARAMETER :: M8N8FMze = 476 + INTEGER(IntKi), PARAMETER :: M8N9FMze = 477 + INTEGER(IntKi), PARAMETER :: M9N1FMze = 478 + INTEGER(IntKi), PARAMETER :: M9N2FMze = 479 + INTEGER(IntKi), PARAMETER :: M9N3FMze = 480 + INTEGER(IntKi), PARAMETER :: M9N4FMze = 481 + INTEGER(IntKi), PARAMETER :: M9N5FMze = 482 + INTEGER(IntKi), PARAMETER :: M9N6FMze = 483 + INTEGER(IntKi), PARAMETER :: M9N7FMze = 484 + INTEGER(IntKi), PARAMETER :: M9N8FMze = 485 + INTEGER(IntKi), PARAMETER :: M9N9FMze = 486 + INTEGER(IntKi), PARAMETER :: M1N1MKxe = 487 + INTEGER(IntKi), PARAMETER :: M1N2MKxe = 488 + INTEGER(IntKi), PARAMETER :: M1N3MKxe = 489 + INTEGER(IntKi), PARAMETER :: M1N4MKxe = 490 + INTEGER(IntKi), PARAMETER :: M1N5MKxe = 491 + INTEGER(IntKi), PARAMETER :: M1N6MKxe = 492 + INTEGER(IntKi), PARAMETER :: M1N7MKxe = 493 + INTEGER(IntKi), PARAMETER :: M1N8MKxe = 494 + INTEGER(IntKi), PARAMETER :: M1N9MKxe = 495 + INTEGER(IntKi), PARAMETER :: M2N1MKxe = 496 + INTEGER(IntKi), PARAMETER :: M2N2MKxe = 497 + INTEGER(IntKi), PARAMETER :: M2N3MKxe = 498 + INTEGER(IntKi), PARAMETER :: M2N4MKxe = 499 + INTEGER(IntKi), PARAMETER :: M2N5MKxe = 500 + INTEGER(IntKi), PARAMETER :: M2N6MKxe = 501 + INTEGER(IntKi), PARAMETER :: M2N7MKxe = 502 + INTEGER(IntKi), PARAMETER :: M2N8MKxe = 503 + INTEGER(IntKi), PARAMETER :: M2N9MKxe = 504 + INTEGER(IntKi), PARAMETER :: M3N1MKxe = 505 + INTEGER(IntKi), PARAMETER :: M3N2MKxe = 506 + INTEGER(IntKi), PARAMETER :: M3N3MKxe = 507 + INTEGER(IntKi), PARAMETER :: M3N4MKxe = 508 + INTEGER(IntKi), PARAMETER :: M3N5MKxe = 509 + INTEGER(IntKi), PARAMETER :: M3N6MKxe = 510 + INTEGER(IntKi), PARAMETER :: M3N7MKxe = 511 + INTEGER(IntKi), PARAMETER :: M3N8MKxe = 512 + INTEGER(IntKi), PARAMETER :: M3N9MKxe = 513 + INTEGER(IntKi), PARAMETER :: M4N1MKxe = 514 + INTEGER(IntKi), PARAMETER :: M4N2MKxe = 515 + INTEGER(IntKi), PARAMETER :: M4N3MKxe = 516 + INTEGER(IntKi), PARAMETER :: M4N4MKxe = 517 + INTEGER(IntKi), PARAMETER :: M4N5MKxe = 518 + INTEGER(IntKi), PARAMETER :: M4N6MKxe = 519 + INTEGER(IntKi), PARAMETER :: M4N7MKxe = 520 + INTEGER(IntKi), PARAMETER :: M4N8MKxe = 521 + INTEGER(IntKi), PARAMETER :: M4N9MKxe = 522 + INTEGER(IntKi), PARAMETER :: M5N1MKxe = 523 + INTEGER(IntKi), PARAMETER :: M5N2MKxe = 524 + INTEGER(IntKi), PARAMETER :: M5N3MKxe = 525 + INTEGER(IntKi), PARAMETER :: M5N4MKxe = 526 + INTEGER(IntKi), PARAMETER :: M5N5MKxe = 527 + INTEGER(IntKi), PARAMETER :: M5N6MKxe = 528 + INTEGER(IntKi), PARAMETER :: M5N7MKxe = 529 + INTEGER(IntKi), PARAMETER :: M5N8MKxe = 530 + INTEGER(IntKi), PARAMETER :: M5N9MKxe = 531 + INTEGER(IntKi), PARAMETER :: M6N1MKxe = 532 + INTEGER(IntKi), PARAMETER :: M6N2MKxe = 533 + INTEGER(IntKi), PARAMETER :: M6N3MKxe = 534 + INTEGER(IntKi), PARAMETER :: M6N4MKxe = 535 + INTEGER(IntKi), PARAMETER :: M6N5MKxe = 536 + INTEGER(IntKi), PARAMETER :: M6N6MKxe = 537 + INTEGER(IntKi), PARAMETER :: M6N7MKxe = 538 + INTEGER(IntKi), PARAMETER :: M6N8MKxe = 539 + INTEGER(IntKi), PARAMETER :: M6N9MKxe = 540 + INTEGER(IntKi), PARAMETER :: M7N1MKxe = 541 + INTEGER(IntKi), PARAMETER :: M7N2MKxe = 542 + INTEGER(IntKi), PARAMETER :: M7N3MKxe = 543 + INTEGER(IntKi), PARAMETER :: M7N4MKxe = 544 + INTEGER(IntKi), PARAMETER :: M7N5MKxe = 545 + INTEGER(IntKi), PARAMETER :: M7N6MKxe = 546 + INTEGER(IntKi), PARAMETER :: M7N7MKxe = 547 + INTEGER(IntKi), PARAMETER :: M7N8MKxe = 548 + INTEGER(IntKi), PARAMETER :: M7N9MKxe = 549 + INTEGER(IntKi), PARAMETER :: M8N1MKxe = 550 + INTEGER(IntKi), PARAMETER :: M8N2MKxe = 551 + INTEGER(IntKi), PARAMETER :: M8N3MKxe = 552 + INTEGER(IntKi), PARAMETER :: M8N4MKxe = 553 + INTEGER(IntKi), PARAMETER :: M8N5MKxe = 554 + INTEGER(IntKi), PARAMETER :: M8N6MKxe = 555 + INTEGER(IntKi), PARAMETER :: M8N7MKxe = 556 + INTEGER(IntKi), PARAMETER :: M8N8MKxe = 557 + INTEGER(IntKi), PARAMETER :: M8N9MKxe = 558 + INTEGER(IntKi), PARAMETER :: M9N1MKxe = 559 + INTEGER(IntKi), PARAMETER :: M9N2MKxe = 560 + INTEGER(IntKi), PARAMETER :: M9N3MKxe = 561 + INTEGER(IntKi), PARAMETER :: M9N4MKxe = 562 + INTEGER(IntKi), PARAMETER :: M9N5MKxe = 563 + INTEGER(IntKi), PARAMETER :: M9N6MKxe = 564 + INTEGER(IntKi), PARAMETER :: M9N7MKxe = 565 + INTEGER(IntKi), PARAMETER :: M9N8MKxe = 566 + INTEGER(IntKi), PARAMETER :: M9N9MKxe = 567 + INTEGER(IntKi), PARAMETER :: M1N1MKye = 568 + INTEGER(IntKi), PARAMETER :: M1N2MKye = 569 + INTEGER(IntKi), PARAMETER :: M1N3MKye = 570 + INTEGER(IntKi), PARAMETER :: M1N4MKye = 571 + INTEGER(IntKi), PARAMETER :: M1N5MKye = 572 + INTEGER(IntKi), PARAMETER :: M1N6MKye = 573 + INTEGER(IntKi), PARAMETER :: M1N7MKye = 574 + INTEGER(IntKi), PARAMETER :: M1N8MKye = 575 + INTEGER(IntKi), PARAMETER :: M1N9MKye = 576 + INTEGER(IntKi), PARAMETER :: M2N1MKye = 577 + INTEGER(IntKi), PARAMETER :: M2N2MKye = 578 + INTEGER(IntKi), PARAMETER :: M2N3MKye = 579 + INTEGER(IntKi), PARAMETER :: M2N4MKye = 580 + INTEGER(IntKi), PARAMETER :: M2N5MKye = 581 + INTEGER(IntKi), PARAMETER :: M2N6MKye = 582 + INTEGER(IntKi), PARAMETER :: M2N7MKye = 583 + INTEGER(IntKi), PARAMETER :: M2N8MKye = 584 + INTEGER(IntKi), PARAMETER :: M2N9MKye = 585 + INTEGER(IntKi), PARAMETER :: M3N1MKye = 586 + INTEGER(IntKi), PARAMETER :: M3N2MKye = 587 + INTEGER(IntKi), PARAMETER :: M3N3MKye = 588 + INTEGER(IntKi), PARAMETER :: M3N4MKye = 589 + INTEGER(IntKi), PARAMETER :: M3N5MKye = 590 + INTEGER(IntKi), PARAMETER :: M3N6MKye = 591 + INTEGER(IntKi), PARAMETER :: M3N7MKye = 592 + INTEGER(IntKi), PARAMETER :: M3N8MKye = 593 + INTEGER(IntKi), PARAMETER :: M3N9MKye = 594 + INTEGER(IntKi), PARAMETER :: M4N1MKye = 595 + INTEGER(IntKi), PARAMETER :: M4N2MKye = 596 + INTEGER(IntKi), PARAMETER :: M4N3MKye = 597 + INTEGER(IntKi), PARAMETER :: M4N4MKye = 598 + INTEGER(IntKi), PARAMETER :: M4N5MKye = 599 + INTEGER(IntKi), PARAMETER :: M4N6MKye = 600 + INTEGER(IntKi), PARAMETER :: M4N7MKye = 601 + INTEGER(IntKi), PARAMETER :: M4N8MKye = 602 + INTEGER(IntKi), PARAMETER :: M4N9MKye = 603 + INTEGER(IntKi), PARAMETER :: M5N1MKye = 604 + INTEGER(IntKi), PARAMETER :: M5N2MKye = 605 + INTEGER(IntKi), PARAMETER :: M5N3MKye = 606 + INTEGER(IntKi), PARAMETER :: M5N4MKye = 607 + INTEGER(IntKi), PARAMETER :: M5N5MKye = 608 + INTEGER(IntKi), PARAMETER :: M5N6MKye = 609 + INTEGER(IntKi), PARAMETER :: M5N7MKye = 610 + INTEGER(IntKi), PARAMETER :: M5N8MKye = 611 + INTEGER(IntKi), PARAMETER :: M5N9MKye = 612 + INTEGER(IntKi), PARAMETER :: M6N1MKye = 613 + INTEGER(IntKi), PARAMETER :: M6N2MKye = 614 + INTEGER(IntKi), PARAMETER :: M6N3MKye = 615 + INTEGER(IntKi), PARAMETER :: M6N4MKye = 616 + INTEGER(IntKi), PARAMETER :: M6N5MKye = 617 + INTEGER(IntKi), PARAMETER :: M6N6MKye = 618 + INTEGER(IntKi), PARAMETER :: M6N7MKye = 619 + INTEGER(IntKi), PARAMETER :: M6N8MKye = 620 + INTEGER(IntKi), PARAMETER :: M6N9MKye = 621 + INTEGER(IntKi), PARAMETER :: M7N1MKye = 622 + INTEGER(IntKi), PARAMETER :: M7N2MKye = 623 + INTEGER(IntKi), PARAMETER :: M7N3MKye = 624 + INTEGER(IntKi), PARAMETER :: M7N4MKye = 625 + INTEGER(IntKi), PARAMETER :: M7N5MKye = 626 + INTEGER(IntKi), PARAMETER :: M7N6MKye = 627 + INTEGER(IntKi), PARAMETER :: M7N7MKye = 628 + INTEGER(IntKi), PARAMETER :: M7N8MKye = 629 + INTEGER(IntKi), PARAMETER :: M7N9MKye = 630 + INTEGER(IntKi), PARAMETER :: M8N1MKye = 631 + INTEGER(IntKi), PARAMETER :: M8N2MKye = 632 + INTEGER(IntKi), PARAMETER :: M8N3MKye = 633 + INTEGER(IntKi), PARAMETER :: M8N4MKye = 634 + INTEGER(IntKi), PARAMETER :: M8N5MKye = 635 + INTEGER(IntKi), PARAMETER :: M8N6MKye = 636 + INTEGER(IntKi), PARAMETER :: M8N7MKye = 637 + INTEGER(IntKi), PARAMETER :: M8N8MKye = 638 + INTEGER(IntKi), PARAMETER :: M8N9MKye = 639 + INTEGER(IntKi), PARAMETER :: M9N1MKye = 640 + INTEGER(IntKi), PARAMETER :: M9N2MKye = 641 + INTEGER(IntKi), PARAMETER :: M9N3MKye = 642 + INTEGER(IntKi), PARAMETER :: M9N4MKye = 643 + INTEGER(IntKi), PARAMETER :: M9N5MKye = 644 + INTEGER(IntKi), PARAMETER :: M9N6MKye = 645 + INTEGER(IntKi), PARAMETER :: M9N7MKye = 646 + INTEGER(IntKi), PARAMETER :: M9N8MKye = 647 + INTEGER(IntKi), PARAMETER :: M9N9MKye = 648 + INTEGER(IntKi), PARAMETER :: M1N1MKze = 649 + INTEGER(IntKi), PARAMETER :: M1N2MKze = 650 + INTEGER(IntKi), PARAMETER :: M1N3MKze = 651 + INTEGER(IntKi), PARAMETER :: M1N4MKze = 652 + INTEGER(IntKi), PARAMETER :: M1N5MKze = 653 + INTEGER(IntKi), PARAMETER :: M1N6MKze = 654 + INTEGER(IntKi), PARAMETER :: M1N7MKze = 655 + INTEGER(IntKi), PARAMETER :: M1N8MKze = 656 + INTEGER(IntKi), PARAMETER :: M1N9MKze = 657 + INTEGER(IntKi), PARAMETER :: M2N1MKze = 658 + INTEGER(IntKi), PARAMETER :: M2N2MKze = 659 + INTEGER(IntKi), PARAMETER :: M2N3MKze = 660 + INTEGER(IntKi), PARAMETER :: M2N4MKze = 661 + INTEGER(IntKi), PARAMETER :: M2N5MKze = 662 + INTEGER(IntKi), PARAMETER :: M2N6MKze = 663 + INTEGER(IntKi), PARAMETER :: M2N7MKze = 664 + INTEGER(IntKi), PARAMETER :: M2N8MKze = 665 + INTEGER(IntKi), PARAMETER :: M2N9MKze = 666 + INTEGER(IntKi), PARAMETER :: M3N1MKze = 667 + INTEGER(IntKi), PARAMETER :: M3N2MKze = 668 + INTEGER(IntKi), PARAMETER :: M3N3MKze = 669 + INTEGER(IntKi), PARAMETER :: M3N4MKze = 670 + INTEGER(IntKi), PARAMETER :: M3N5MKze = 671 + INTEGER(IntKi), PARAMETER :: M3N6MKze = 672 + INTEGER(IntKi), PARAMETER :: M3N7MKze = 673 + INTEGER(IntKi), PARAMETER :: M3N8MKze = 674 + INTEGER(IntKi), PARAMETER :: M3N9MKze = 675 + INTEGER(IntKi), PARAMETER :: M4N1MKze = 676 + INTEGER(IntKi), PARAMETER :: M4N2MKze = 677 + INTEGER(IntKi), PARAMETER :: M4N3MKze = 678 + INTEGER(IntKi), PARAMETER :: M4N4MKze = 679 + INTEGER(IntKi), PARAMETER :: M4N5MKze = 680 + INTEGER(IntKi), PARAMETER :: M4N6MKze = 681 + INTEGER(IntKi), PARAMETER :: M4N7MKze = 682 + INTEGER(IntKi), PARAMETER :: M4N8MKze = 683 + INTEGER(IntKi), PARAMETER :: M4N9MKze = 684 + INTEGER(IntKi), PARAMETER :: M5N1MKze = 685 + INTEGER(IntKi), PARAMETER :: M5N2MKze = 686 + INTEGER(IntKi), PARAMETER :: M5N3MKze = 687 + INTEGER(IntKi), PARAMETER :: M5N4MKze = 688 + INTEGER(IntKi), PARAMETER :: M5N5MKze = 689 + INTEGER(IntKi), PARAMETER :: M5N6MKze = 690 + INTEGER(IntKi), PARAMETER :: M5N7MKze = 691 + INTEGER(IntKi), PARAMETER :: M5N8MKze = 692 + INTEGER(IntKi), PARAMETER :: M5N9MKze = 693 + INTEGER(IntKi), PARAMETER :: M6N1MKze = 694 + INTEGER(IntKi), PARAMETER :: M6N2MKze = 695 + INTEGER(IntKi), PARAMETER :: M6N3MKze = 696 + INTEGER(IntKi), PARAMETER :: M6N4MKze = 697 + INTEGER(IntKi), PARAMETER :: M6N5MKze = 698 + INTEGER(IntKi), PARAMETER :: M6N6MKze = 699 + INTEGER(IntKi), PARAMETER :: M6N7MKze = 700 + INTEGER(IntKi), PARAMETER :: M6N8MKze = 701 + INTEGER(IntKi), PARAMETER :: M6N9MKze = 702 + INTEGER(IntKi), PARAMETER :: M7N1MKze = 703 + INTEGER(IntKi), PARAMETER :: M7N2MKze = 704 + INTEGER(IntKi), PARAMETER :: M7N3MKze = 705 + INTEGER(IntKi), PARAMETER :: M7N4MKze = 706 + INTEGER(IntKi), PARAMETER :: M7N5MKze = 707 + INTEGER(IntKi), PARAMETER :: M7N6MKze = 708 + INTEGER(IntKi), PARAMETER :: M7N7MKze = 709 + INTEGER(IntKi), PARAMETER :: M7N8MKze = 710 + INTEGER(IntKi), PARAMETER :: M7N9MKze = 711 + INTEGER(IntKi), PARAMETER :: M8N1MKze = 712 + INTEGER(IntKi), PARAMETER :: M8N2MKze = 713 + INTEGER(IntKi), PARAMETER :: M8N3MKze = 714 + INTEGER(IntKi), PARAMETER :: M8N4MKze = 715 + INTEGER(IntKi), PARAMETER :: M8N5MKze = 716 + INTEGER(IntKi), PARAMETER :: M8N6MKze = 717 + INTEGER(IntKi), PARAMETER :: M8N7MKze = 718 + INTEGER(IntKi), PARAMETER :: M8N8MKze = 719 + INTEGER(IntKi), PARAMETER :: M8N9MKze = 720 + INTEGER(IntKi), PARAMETER :: M9N1MKze = 721 + INTEGER(IntKi), PARAMETER :: M9N2MKze = 722 + INTEGER(IntKi), PARAMETER :: M9N3MKze = 723 + INTEGER(IntKi), PARAMETER :: M9N4MKze = 724 + INTEGER(IntKi), PARAMETER :: M9N5MKze = 725 + INTEGER(IntKi), PARAMETER :: M9N6MKze = 726 + INTEGER(IntKi), PARAMETER :: M9N7MKze = 727 + INTEGER(IntKi), PARAMETER :: M9N8MKze = 728 + INTEGER(IntKi), PARAMETER :: M9N9MKze = 729 + INTEGER(IntKi), PARAMETER :: M1N1MMxe = 730 + INTEGER(IntKi), PARAMETER :: M1N2MMxe = 731 + INTEGER(IntKi), PARAMETER :: M1N3MMxe = 732 + INTEGER(IntKi), PARAMETER :: M1N4MMxe = 733 + INTEGER(IntKi), PARAMETER :: M1N5MMxe = 734 + INTEGER(IntKi), PARAMETER :: M1N6MMxe = 735 + INTEGER(IntKi), PARAMETER :: M1N7MMxe = 736 + INTEGER(IntKi), PARAMETER :: M1N8MMxe = 737 + INTEGER(IntKi), PARAMETER :: M1N9MMxe = 738 + INTEGER(IntKi), PARAMETER :: M2N1MMxe = 739 + INTEGER(IntKi), PARAMETER :: M2N2MMxe = 740 + INTEGER(IntKi), PARAMETER :: M2N3MMxe = 741 + INTEGER(IntKi), PARAMETER :: M2N4MMxe = 742 + INTEGER(IntKi), PARAMETER :: M2N5MMxe = 743 + INTEGER(IntKi), PARAMETER :: M2N6MMxe = 744 + INTEGER(IntKi), PARAMETER :: M2N7MMxe = 745 + INTEGER(IntKi), PARAMETER :: M2N8MMxe = 746 + INTEGER(IntKi), PARAMETER :: M2N9MMxe = 747 + INTEGER(IntKi), PARAMETER :: M3N1MMxe = 748 + INTEGER(IntKi), PARAMETER :: M3N2MMxe = 749 + INTEGER(IntKi), PARAMETER :: M3N3MMxe = 750 + INTEGER(IntKi), PARAMETER :: M3N4MMxe = 751 + INTEGER(IntKi), PARAMETER :: M3N5MMxe = 752 + INTEGER(IntKi), PARAMETER :: M3N6MMxe = 753 + INTEGER(IntKi), PARAMETER :: M3N7MMxe = 754 + INTEGER(IntKi), PARAMETER :: M3N8MMxe = 755 + INTEGER(IntKi), PARAMETER :: M3N9MMxe = 756 + INTEGER(IntKi), PARAMETER :: M4N1MMxe = 757 + INTEGER(IntKi), PARAMETER :: M4N2MMxe = 758 + INTEGER(IntKi), PARAMETER :: M4N3MMxe = 759 + INTEGER(IntKi), PARAMETER :: M4N4MMxe = 760 + INTEGER(IntKi), PARAMETER :: M4N5MMxe = 761 + INTEGER(IntKi), PARAMETER :: M4N6MMxe = 762 + INTEGER(IntKi), PARAMETER :: M4N7MMxe = 763 + INTEGER(IntKi), PARAMETER :: M4N8MMxe = 764 + INTEGER(IntKi), PARAMETER :: M4N9MMxe = 765 + INTEGER(IntKi), PARAMETER :: M5N1MMxe = 766 + INTEGER(IntKi), PARAMETER :: M5N2MMxe = 767 + INTEGER(IntKi), PARAMETER :: M5N3MMxe = 768 + INTEGER(IntKi), PARAMETER :: M5N4MMxe = 769 + INTEGER(IntKi), PARAMETER :: M5N5MMxe = 770 + INTEGER(IntKi), PARAMETER :: M5N6MMxe = 771 + INTEGER(IntKi), PARAMETER :: M5N7MMxe = 772 + INTEGER(IntKi), PARAMETER :: M5N8MMxe = 773 + INTEGER(IntKi), PARAMETER :: M5N9MMxe = 774 + INTEGER(IntKi), PARAMETER :: M6N1MMxe = 775 + INTEGER(IntKi), PARAMETER :: M6N2MMxe = 776 + INTEGER(IntKi), PARAMETER :: M6N3MMxe = 777 + INTEGER(IntKi), PARAMETER :: M6N4MMxe = 778 + INTEGER(IntKi), PARAMETER :: M6N5MMxe = 779 + INTEGER(IntKi), PARAMETER :: M6N6MMxe = 780 + INTEGER(IntKi), PARAMETER :: M6N7MMxe = 781 + INTEGER(IntKi), PARAMETER :: M6N8MMxe = 782 + INTEGER(IntKi), PARAMETER :: M6N9MMxe = 783 + INTEGER(IntKi), PARAMETER :: M7N1MMxe = 784 + INTEGER(IntKi), PARAMETER :: M7N2MMxe = 785 + INTEGER(IntKi), PARAMETER :: M7N3MMxe = 786 + INTEGER(IntKi), PARAMETER :: M7N4MMxe = 787 + INTEGER(IntKi), PARAMETER :: M7N5MMxe = 788 + INTEGER(IntKi), PARAMETER :: M7N6MMxe = 789 + INTEGER(IntKi), PARAMETER :: M7N7MMxe = 790 + INTEGER(IntKi), PARAMETER :: M7N8MMxe = 791 + INTEGER(IntKi), PARAMETER :: M7N9MMxe = 792 + INTEGER(IntKi), PARAMETER :: M8N1MMxe = 793 + INTEGER(IntKi), PARAMETER :: M8N2MMxe = 794 + INTEGER(IntKi), PARAMETER :: M8N3MMxe = 795 + INTEGER(IntKi), PARAMETER :: M8N4MMxe = 796 + INTEGER(IntKi), PARAMETER :: M8N5MMxe = 797 + INTEGER(IntKi), PARAMETER :: M8N6MMxe = 798 + INTEGER(IntKi), PARAMETER :: M8N7MMxe = 799 + INTEGER(IntKi), PARAMETER :: M8N8MMxe = 800 + INTEGER(IntKi), PARAMETER :: M8N9MMxe = 801 + INTEGER(IntKi), PARAMETER :: M9N1MMxe = 802 + INTEGER(IntKi), PARAMETER :: M9N2MMxe = 803 + INTEGER(IntKi), PARAMETER :: M9N3MMxe = 804 + INTEGER(IntKi), PARAMETER :: M9N4MMxe = 805 + INTEGER(IntKi), PARAMETER :: M9N5MMxe = 806 + INTEGER(IntKi), PARAMETER :: M9N6MMxe = 807 + INTEGER(IntKi), PARAMETER :: M9N7MMxe = 808 + INTEGER(IntKi), PARAMETER :: M9N8MMxe = 809 + INTEGER(IntKi), PARAMETER :: M9N9MMxe = 810 + INTEGER(IntKi), PARAMETER :: M1N1MMye = 811 + INTEGER(IntKi), PARAMETER :: M1N2MMye = 812 + INTEGER(IntKi), PARAMETER :: M1N3MMye = 813 + INTEGER(IntKi), PARAMETER :: M1N4MMye = 814 + INTEGER(IntKi), PARAMETER :: M1N5MMye = 815 + INTEGER(IntKi), PARAMETER :: M1N6MMye = 816 + INTEGER(IntKi), PARAMETER :: M1N7MMye = 817 + INTEGER(IntKi), PARAMETER :: M1N8MMye = 818 + INTEGER(IntKi), PARAMETER :: M1N9MMye = 819 + INTEGER(IntKi), PARAMETER :: M2N1MMye = 820 + INTEGER(IntKi), PARAMETER :: M2N2MMye = 821 + INTEGER(IntKi), PARAMETER :: M2N3MMye = 822 + INTEGER(IntKi), PARAMETER :: M2N4MMye = 823 + INTEGER(IntKi), PARAMETER :: M2N5MMye = 824 + INTEGER(IntKi), PARAMETER :: M2N6MMye = 825 + INTEGER(IntKi), PARAMETER :: M2N7MMye = 826 + INTEGER(IntKi), PARAMETER :: M2N8MMye = 827 + INTEGER(IntKi), PARAMETER :: M2N9MMye = 828 + INTEGER(IntKi), PARAMETER :: M3N1MMye = 829 + INTEGER(IntKi), PARAMETER :: M3N2MMye = 830 + INTEGER(IntKi), PARAMETER :: M3N3MMye = 831 + INTEGER(IntKi), PARAMETER :: M3N4MMye = 832 + INTEGER(IntKi), PARAMETER :: M3N5MMye = 833 + INTEGER(IntKi), PARAMETER :: M3N6MMye = 834 + INTEGER(IntKi), PARAMETER :: M3N7MMye = 835 + INTEGER(IntKi), PARAMETER :: M3N8MMye = 836 + INTEGER(IntKi), PARAMETER :: M3N9MMye = 837 + INTEGER(IntKi), PARAMETER :: M4N1MMye = 838 + INTEGER(IntKi), PARAMETER :: M4N2MMye = 839 + INTEGER(IntKi), PARAMETER :: M4N3MMye = 840 + INTEGER(IntKi), PARAMETER :: M4N4MMye = 841 + INTEGER(IntKi), PARAMETER :: M4N5MMye = 842 + INTEGER(IntKi), PARAMETER :: M4N6MMye = 843 + INTEGER(IntKi), PARAMETER :: M4N7MMye = 844 + INTEGER(IntKi), PARAMETER :: M4N8MMye = 845 + INTEGER(IntKi), PARAMETER :: M4N9MMye = 846 + INTEGER(IntKi), PARAMETER :: M5N1MMye = 847 + INTEGER(IntKi), PARAMETER :: M5N2MMye = 848 + INTEGER(IntKi), PARAMETER :: M5N3MMye = 849 + INTEGER(IntKi), PARAMETER :: M5N4MMye = 850 + INTEGER(IntKi), PARAMETER :: M5N5MMye = 851 + INTEGER(IntKi), PARAMETER :: M5N6MMye = 852 + INTEGER(IntKi), PARAMETER :: M5N7MMye = 853 + INTEGER(IntKi), PARAMETER :: M5N8MMye = 854 + INTEGER(IntKi), PARAMETER :: M5N9MMye = 855 + INTEGER(IntKi), PARAMETER :: M6N1MMye = 856 + INTEGER(IntKi), PARAMETER :: M6N2MMye = 857 + INTEGER(IntKi), PARAMETER :: M6N3MMye = 858 + INTEGER(IntKi), PARAMETER :: M6N4MMye = 859 + INTEGER(IntKi), PARAMETER :: M6N5MMye = 860 + INTEGER(IntKi), PARAMETER :: M6N6MMye = 861 + INTEGER(IntKi), PARAMETER :: M6N7MMye = 862 + INTEGER(IntKi), PARAMETER :: M6N8MMye = 863 + INTEGER(IntKi), PARAMETER :: M6N9MMye = 864 + INTEGER(IntKi), PARAMETER :: M7N1MMye = 865 + INTEGER(IntKi), PARAMETER :: M7N2MMye = 866 + INTEGER(IntKi), PARAMETER :: M7N3MMye = 867 + INTEGER(IntKi), PARAMETER :: M7N4MMye = 868 + INTEGER(IntKi), PARAMETER :: M7N5MMye = 869 + INTEGER(IntKi), PARAMETER :: M7N6MMye = 870 + INTEGER(IntKi), PARAMETER :: M7N7MMye = 871 + INTEGER(IntKi), PARAMETER :: M7N8MMye = 872 + INTEGER(IntKi), PARAMETER :: M7N9MMye = 873 + INTEGER(IntKi), PARAMETER :: M8N1MMye = 874 + INTEGER(IntKi), PARAMETER :: M8N2MMye = 875 + INTEGER(IntKi), PARAMETER :: M8N3MMye = 876 + INTEGER(IntKi), PARAMETER :: M8N4MMye = 877 + INTEGER(IntKi), PARAMETER :: M8N5MMye = 878 + INTEGER(IntKi), PARAMETER :: M8N6MMye = 879 + INTEGER(IntKi), PARAMETER :: M8N7MMye = 880 + INTEGER(IntKi), PARAMETER :: M8N8MMye = 881 + INTEGER(IntKi), PARAMETER :: M8N9MMye = 882 + INTEGER(IntKi), PARAMETER :: M9N1MMye = 883 + INTEGER(IntKi), PARAMETER :: M9N2MMye = 884 + INTEGER(IntKi), PARAMETER :: M9N3MMye = 885 + INTEGER(IntKi), PARAMETER :: M9N4MMye = 886 + INTEGER(IntKi), PARAMETER :: M9N5MMye = 887 + INTEGER(IntKi), PARAMETER :: M9N6MMye = 888 + INTEGER(IntKi), PARAMETER :: M9N7MMye = 889 + INTEGER(IntKi), PARAMETER :: M9N8MMye = 890 + INTEGER(IntKi), PARAMETER :: M9N9MMye = 891 + INTEGER(IntKi), PARAMETER :: M1N1MMze = 892 + INTEGER(IntKi), PARAMETER :: M1N2MMze = 893 + INTEGER(IntKi), PARAMETER :: M1N3MMze = 894 + INTEGER(IntKi), PARAMETER :: M1N4MMze = 895 + INTEGER(IntKi), PARAMETER :: M1N5MMze = 896 + INTEGER(IntKi), PARAMETER :: M1N6MMze = 897 + INTEGER(IntKi), PARAMETER :: M1N7MMze = 898 + INTEGER(IntKi), PARAMETER :: M1N8MMze = 899 + INTEGER(IntKi), PARAMETER :: M1N9MMze = 900 + INTEGER(IntKi), PARAMETER :: M2N1MMze = 901 + INTEGER(IntKi), PARAMETER :: M2N2MMze = 902 + INTEGER(IntKi), PARAMETER :: M2N3MMze = 903 + INTEGER(IntKi), PARAMETER :: M2N4MMze = 904 + INTEGER(IntKi), PARAMETER :: M2N5MMze = 905 + INTEGER(IntKi), PARAMETER :: M2N6MMze = 906 + INTEGER(IntKi), PARAMETER :: M2N7MMze = 907 + INTEGER(IntKi), PARAMETER :: M2N8MMze = 908 + INTEGER(IntKi), PARAMETER :: M2N9MMze = 909 + INTEGER(IntKi), PARAMETER :: M3N1MMze = 910 + INTEGER(IntKi), PARAMETER :: M3N2MMze = 911 + INTEGER(IntKi), PARAMETER :: M3N3MMze = 912 + INTEGER(IntKi), PARAMETER :: M3N4MMze = 913 + INTEGER(IntKi), PARAMETER :: M3N5MMze = 914 + INTEGER(IntKi), PARAMETER :: M3N6MMze = 915 + INTEGER(IntKi), PARAMETER :: M3N7MMze = 916 + INTEGER(IntKi), PARAMETER :: M3N8MMze = 917 + INTEGER(IntKi), PARAMETER :: M3N9MMze = 918 + INTEGER(IntKi), PARAMETER :: M4N1MMze = 919 + INTEGER(IntKi), PARAMETER :: M4N2MMze = 920 + INTEGER(IntKi), PARAMETER :: M4N3MMze = 921 + INTEGER(IntKi), PARAMETER :: M4N4MMze = 922 + INTEGER(IntKi), PARAMETER :: M4N5MMze = 923 + INTEGER(IntKi), PARAMETER :: M4N6MMze = 924 + INTEGER(IntKi), PARAMETER :: M4N7MMze = 925 + INTEGER(IntKi), PARAMETER :: M4N8MMze = 926 + INTEGER(IntKi), PARAMETER :: M4N9MMze = 927 + INTEGER(IntKi), PARAMETER :: M5N1MMze = 928 + INTEGER(IntKi), PARAMETER :: M5N2MMze = 929 + INTEGER(IntKi), PARAMETER :: M5N3MMze = 930 + INTEGER(IntKi), PARAMETER :: M5N4MMze = 931 + INTEGER(IntKi), PARAMETER :: M5N5MMze = 932 + INTEGER(IntKi), PARAMETER :: M5N6MMze = 933 + INTEGER(IntKi), PARAMETER :: M5N7MMze = 934 + INTEGER(IntKi), PARAMETER :: M5N8MMze = 935 + INTEGER(IntKi), PARAMETER :: M5N9MMze = 936 + INTEGER(IntKi), PARAMETER :: M6N1MMze = 937 + INTEGER(IntKi), PARAMETER :: M6N2MMze = 938 + INTEGER(IntKi), PARAMETER :: M6N3MMze = 939 + INTEGER(IntKi), PARAMETER :: M6N4MMze = 940 + INTEGER(IntKi), PARAMETER :: M6N5MMze = 941 + INTEGER(IntKi), PARAMETER :: M6N6MMze = 942 + INTEGER(IntKi), PARAMETER :: M6N7MMze = 943 + INTEGER(IntKi), PARAMETER :: M6N8MMze = 944 + INTEGER(IntKi), PARAMETER :: M6N9MMze = 945 + INTEGER(IntKi), PARAMETER :: M7N1MMze = 946 + INTEGER(IntKi), PARAMETER :: M7N2MMze = 947 + INTEGER(IntKi), PARAMETER :: M7N3MMze = 948 + INTEGER(IntKi), PARAMETER :: M7N4MMze = 949 + INTEGER(IntKi), PARAMETER :: M7N5MMze = 950 + INTEGER(IntKi), PARAMETER :: M7N6MMze = 951 + INTEGER(IntKi), PARAMETER :: M7N7MMze = 952 + INTEGER(IntKi), PARAMETER :: M7N8MMze = 953 + INTEGER(IntKi), PARAMETER :: M7N9MMze = 954 + INTEGER(IntKi), PARAMETER :: M8N1MMze = 955 + INTEGER(IntKi), PARAMETER :: M8N2MMze = 956 + INTEGER(IntKi), PARAMETER :: M8N3MMze = 957 + INTEGER(IntKi), PARAMETER :: M8N4MMze = 958 + INTEGER(IntKi), PARAMETER :: M8N5MMze = 959 + INTEGER(IntKi), PARAMETER :: M8N6MMze = 960 + INTEGER(IntKi), PARAMETER :: M8N7MMze = 961 + INTEGER(IntKi), PARAMETER :: M8N8MMze = 962 + INTEGER(IntKi), PARAMETER :: M8N9MMze = 963 + INTEGER(IntKi), PARAMETER :: M9N1MMze = 964 + INTEGER(IntKi), PARAMETER :: M9N2MMze = 965 + INTEGER(IntKi), PARAMETER :: M9N3MMze = 966 + INTEGER(IntKi), PARAMETER :: M9N4MMze = 967 + INTEGER(IntKi), PARAMETER :: M9N5MMze = 968 + INTEGER(IntKi), PARAMETER :: M9N6MMze = 969 + INTEGER(IntKi), PARAMETER :: M9N7MMze = 970 + INTEGER(IntKi), PARAMETER :: M9N8MMze = 971 + INTEGER(IntKi), PARAMETER :: M9N9MMze = 972 + + + ! Displacements: + + INTEGER(IntKi), PARAMETER :: M1N1TDxss = 973 + INTEGER(IntKi), PARAMETER :: M1N2TDxss = 974 + INTEGER(IntKi), PARAMETER :: M1N3TDxss = 975 + INTEGER(IntKi), PARAMETER :: M1N4TDxss = 976 + INTEGER(IntKi), PARAMETER :: M1N5TDxss = 977 + INTEGER(IntKi), PARAMETER :: M1N6TDxss = 978 + INTEGER(IntKi), PARAMETER :: M1N7TDxss = 979 + INTEGER(IntKi), PARAMETER :: M1N8TDxss = 980 + INTEGER(IntKi), PARAMETER :: M1N9TDxss = 981 + INTEGER(IntKi), PARAMETER :: M2N1TDxss = 982 + INTEGER(IntKi), PARAMETER :: M2N2TDxss = 983 + INTEGER(IntKi), PARAMETER :: M2N3TDxss = 984 + INTEGER(IntKi), PARAMETER :: M2N4TDxss = 985 + INTEGER(IntKi), PARAMETER :: M2N5TDxss = 986 + INTEGER(IntKi), PARAMETER :: M2N6TDxss = 987 + INTEGER(IntKi), PARAMETER :: M2N7TDxss = 988 + INTEGER(IntKi), PARAMETER :: M2N8TDxss = 989 + INTEGER(IntKi), PARAMETER :: M2N9TDxss = 990 + INTEGER(IntKi), PARAMETER :: M3N1TDxss = 991 + INTEGER(IntKi), PARAMETER :: M3N2TDxss = 992 + INTEGER(IntKi), PARAMETER :: M3N3TDxss = 993 + INTEGER(IntKi), PARAMETER :: M3N4TDxss = 994 + INTEGER(IntKi), PARAMETER :: M3N5TDxss = 995 + INTEGER(IntKi), PARAMETER :: M3N6TDxss = 996 + INTEGER(IntKi), PARAMETER :: M3N7TDxss = 997 + INTEGER(IntKi), PARAMETER :: M3N8TDxss = 998 + INTEGER(IntKi), PARAMETER :: M3N9TDxss = 999 + INTEGER(IntKi), PARAMETER :: M4N1TDxss = 1000 + INTEGER(IntKi), PARAMETER :: M4N2TDxss = 1001 + INTEGER(IntKi), PARAMETER :: M4N3TDxss = 1002 + INTEGER(IntKi), PARAMETER :: M4N4TDxss = 1003 + INTEGER(IntKi), PARAMETER :: M4N5TDxss = 1004 + INTEGER(IntKi), PARAMETER :: M4N6TDxss = 1005 + INTEGER(IntKi), PARAMETER :: M4N7TDxss = 1006 + INTEGER(IntKi), PARAMETER :: M4N8TDxss = 1007 + INTEGER(IntKi), PARAMETER :: M4N9TDxss = 1008 + INTEGER(IntKi), PARAMETER :: M5N1TDxss = 1009 + INTEGER(IntKi), PARAMETER :: M5N2TDxss = 1010 + INTEGER(IntKi), PARAMETER :: M5N3TDxss = 1011 + INTEGER(IntKi), PARAMETER :: M5N4TDxss = 1012 + INTEGER(IntKi), PARAMETER :: M5N5TDxss = 1013 + INTEGER(IntKi), PARAMETER :: M5N6TDxss = 1014 + INTEGER(IntKi), PARAMETER :: M5N7TDxss = 1015 + INTEGER(IntKi), PARAMETER :: M5N8TDxss = 1016 + INTEGER(IntKi), PARAMETER :: M5N9TDxss = 1017 + INTEGER(IntKi), PARAMETER :: M6N1TDxss = 1018 + INTEGER(IntKi), PARAMETER :: M6N2TDxss = 1019 + INTEGER(IntKi), PARAMETER :: M6N3TDxss = 1020 + INTEGER(IntKi), PARAMETER :: M6N4TDxss = 1021 + INTEGER(IntKi), PARAMETER :: M6N5TDxss = 1022 + INTEGER(IntKi), PARAMETER :: M6N6TDxss = 1023 + INTEGER(IntKi), PARAMETER :: M6N7TDxss = 1024 + INTEGER(IntKi), PARAMETER :: M6N8TDxss = 1025 + INTEGER(IntKi), PARAMETER :: M6N9TDxss = 1026 + INTEGER(IntKi), PARAMETER :: M7N1TDxss = 1027 + INTEGER(IntKi), PARAMETER :: M7N2TDxss = 1028 + INTEGER(IntKi), PARAMETER :: M7N3TDxss = 1029 + INTEGER(IntKi), PARAMETER :: M7N4TDxss = 1030 + INTEGER(IntKi), PARAMETER :: M7N5TDxss = 1031 + INTEGER(IntKi), PARAMETER :: M7N6TDxss = 1032 + INTEGER(IntKi), PARAMETER :: M7N7TDxss = 1033 + INTEGER(IntKi), PARAMETER :: M7N8TDxss = 1034 + INTEGER(IntKi), PARAMETER :: M7N9TDxss = 1035 + INTEGER(IntKi), PARAMETER :: M8N1TDxss = 1036 + INTEGER(IntKi), PARAMETER :: M8N2TDxss = 1037 + INTEGER(IntKi), PARAMETER :: M8N3TDxss = 1038 + INTEGER(IntKi), PARAMETER :: M8N4TDxss = 1039 + INTEGER(IntKi), PARAMETER :: M8N5TDxss = 1040 + INTEGER(IntKi), PARAMETER :: M8N6TDxss = 1041 + INTEGER(IntKi), PARAMETER :: M8N7TDxss = 1042 + INTEGER(IntKi), PARAMETER :: M8N8TDxss = 1043 + INTEGER(IntKi), PARAMETER :: M8N9TDxss = 1044 + INTEGER(IntKi), PARAMETER :: M9N1TDxss = 1045 + INTEGER(IntKi), PARAMETER :: M9N2TDxss = 1046 + INTEGER(IntKi), PARAMETER :: M9N3TDxss = 1047 + INTEGER(IntKi), PARAMETER :: M9N4TDxss = 1048 + INTEGER(IntKi), PARAMETER :: M9N5TDxss = 1049 + INTEGER(IntKi), PARAMETER :: M9N6TDxss = 1050 + INTEGER(IntKi), PARAMETER :: M9N7TDxss = 1051 + INTEGER(IntKi), PARAMETER :: M9N8TDxss = 1052 + INTEGER(IntKi), PARAMETER :: M9N9TDxss = 1053 + INTEGER(IntKi), PARAMETER :: M1N1TDyss = 1054 + INTEGER(IntKi), PARAMETER :: M1N2TDyss = 1055 + INTEGER(IntKi), PARAMETER :: M1N3TDyss = 1056 + INTEGER(IntKi), PARAMETER :: M1N4TDyss = 1057 + INTEGER(IntKi), PARAMETER :: M1N5TDyss = 1058 + INTEGER(IntKi), PARAMETER :: M1N6TDyss = 1059 + INTEGER(IntKi), PARAMETER :: M1N7TDyss = 1060 + INTEGER(IntKi), PARAMETER :: M1N8TDyss = 1061 + INTEGER(IntKi), PARAMETER :: M1N9TDyss = 1062 + INTEGER(IntKi), PARAMETER :: M2N1TDyss = 1063 + INTEGER(IntKi), PARAMETER :: M2N2TDyss = 1064 + INTEGER(IntKi), PARAMETER :: M2N3TDyss = 1065 + INTEGER(IntKi), PARAMETER :: M2N4TDyss = 1066 + INTEGER(IntKi), PARAMETER :: M2N5TDyss = 1067 + INTEGER(IntKi), PARAMETER :: M2N6TDyss = 1068 + INTEGER(IntKi), PARAMETER :: M2N7TDyss = 1069 + INTEGER(IntKi), PARAMETER :: M2N8TDyss = 1070 + INTEGER(IntKi), PARAMETER :: M2N9TDyss = 1071 + INTEGER(IntKi), PARAMETER :: M3N1TDyss = 1072 + INTEGER(IntKi), PARAMETER :: M3N2TDyss = 1073 + INTEGER(IntKi), PARAMETER :: M3N3TDyss = 1074 + INTEGER(IntKi), PARAMETER :: M3N4TDyss = 1075 + INTEGER(IntKi), PARAMETER :: M3N5TDyss = 1076 + INTEGER(IntKi), PARAMETER :: M3N6TDyss = 1077 + INTEGER(IntKi), PARAMETER :: M3N7TDyss = 1078 + INTEGER(IntKi), PARAMETER :: M3N8TDyss = 1079 + INTEGER(IntKi), PARAMETER :: M3N9TDyss = 1080 + INTEGER(IntKi), PARAMETER :: M4N1TDyss = 1081 + INTEGER(IntKi), PARAMETER :: M4N2TDyss = 1082 + INTEGER(IntKi), PARAMETER :: M4N3TDyss = 1083 + INTEGER(IntKi), PARAMETER :: M4N4TDyss = 1084 + INTEGER(IntKi), PARAMETER :: M4N5TDyss = 1085 + INTEGER(IntKi), PARAMETER :: M4N6TDyss = 1086 + INTEGER(IntKi), PARAMETER :: M4N7TDyss = 1087 + INTEGER(IntKi), PARAMETER :: M4N8TDyss = 1088 + INTEGER(IntKi), PARAMETER :: M4N9TDyss = 1089 + INTEGER(IntKi), PARAMETER :: M5N1TDyss = 1090 + INTEGER(IntKi), PARAMETER :: M5N2TDyss = 1091 + INTEGER(IntKi), PARAMETER :: M5N3TDyss = 1092 + INTEGER(IntKi), PARAMETER :: M5N4TDyss = 1093 + INTEGER(IntKi), PARAMETER :: M5N5TDyss = 1094 + INTEGER(IntKi), PARAMETER :: M5N6TDyss = 1095 + INTEGER(IntKi), PARAMETER :: M5N7TDyss = 1096 + INTEGER(IntKi), PARAMETER :: M5N8TDyss = 1097 + INTEGER(IntKi), PARAMETER :: M5N9TDyss = 1098 + INTEGER(IntKi), PARAMETER :: M6N1TDyss = 1099 + INTEGER(IntKi), PARAMETER :: M6N2TDyss = 1100 + INTEGER(IntKi), PARAMETER :: M6N3TDyss = 1101 + INTEGER(IntKi), PARAMETER :: M6N4TDyss = 1102 + INTEGER(IntKi), PARAMETER :: M6N5TDyss = 1103 + INTEGER(IntKi), PARAMETER :: M6N6TDyss = 1104 + INTEGER(IntKi), PARAMETER :: M6N7TDyss = 1105 + INTEGER(IntKi), PARAMETER :: M6N8TDyss = 1106 + INTEGER(IntKi), PARAMETER :: M6N9TDyss = 1107 + INTEGER(IntKi), PARAMETER :: M7N1TDyss = 1108 + INTEGER(IntKi), PARAMETER :: M7N2TDyss = 1109 + INTEGER(IntKi), PARAMETER :: M7N3TDyss = 1110 + INTEGER(IntKi), PARAMETER :: M7N4TDyss = 1111 + INTEGER(IntKi), PARAMETER :: M7N5TDyss = 1112 + INTEGER(IntKi), PARAMETER :: M7N6TDyss = 1113 + INTEGER(IntKi), PARAMETER :: M7N7TDyss = 1114 + INTEGER(IntKi), PARAMETER :: M7N8TDyss = 1115 + INTEGER(IntKi), PARAMETER :: M7N9TDyss = 1116 + INTEGER(IntKi), PARAMETER :: M8N1TDyss = 1117 + INTEGER(IntKi), PARAMETER :: M8N2TDyss = 1118 + INTEGER(IntKi), PARAMETER :: M8N3TDyss = 1119 + INTEGER(IntKi), PARAMETER :: M8N4TDyss = 1120 + INTEGER(IntKi), PARAMETER :: M8N5TDyss = 1121 + INTEGER(IntKi), PARAMETER :: M8N6TDyss = 1122 + INTEGER(IntKi), PARAMETER :: M8N7TDyss = 1123 + INTEGER(IntKi), PARAMETER :: M8N8TDyss = 1124 + INTEGER(IntKi), PARAMETER :: M8N9TDyss = 1125 + INTEGER(IntKi), PARAMETER :: M9N1TDyss = 1126 + INTEGER(IntKi), PARAMETER :: M9N2TDyss = 1127 + INTEGER(IntKi), PARAMETER :: M9N3TDyss = 1128 + INTEGER(IntKi), PARAMETER :: M9N4TDyss = 1129 + INTEGER(IntKi), PARAMETER :: M9N5TDyss = 1130 + INTEGER(IntKi), PARAMETER :: M9N6TDyss = 1131 + INTEGER(IntKi), PARAMETER :: M9N7TDyss = 1132 + INTEGER(IntKi), PARAMETER :: M9N8TDyss = 1133 + INTEGER(IntKi), PARAMETER :: M9N9TDyss = 1134 + INTEGER(IntKi), PARAMETER :: M1N1TDzss = 1135 + INTEGER(IntKi), PARAMETER :: M1N2TDzss = 1136 + INTEGER(IntKi), PARAMETER :: M1N3TDzss = 1137 + INTEGER(IntKi), PARAMETER :: M1N4TDzss = 1138 + INTEGER(IntKi), PARAMETER :: M1N5TDzss = 1139 + INTEGER(IntKi), PARAMETER :: M1N6TDzss = 1140 + INTEGER(IntKi), PARAMETER :: M1N7TDzss = 1141 + INTEGER(IntKi), PARAMETER :: M1N8TDzss = 1142 + INTEGER(IntKi), PARAMETER :: M1N9TDzss = 1143 + INTEGER(IntKi), PARAMETER :: M2N1TDzss = 1144 + INTEGER(IntKi), PARAMETER :: M2N2TDzss = 1145 + INTEGER(IntKi), PARAMETER :: M2N3TDzss = 1146 + INTEGER(IntKi), PARAMETER :: M2N4TDzss = 1147 + INTEGER(IntKi), PARAMETER :: M2N5TDzss = 1148 + INTEGER(IntKi), PARAMETER :: M2N6TDzss = 1149 + INTEGER(IntKi), PARAMETER :: M2N7TDzss = 1150 + INTEGER(IntKi), PARAMETER :: M2N8TDzss = 1151 + INTEGER(IntKi), PARAMETER :: M2N9TDzss = 1152 + INTEGER(IntKi), PARAMETER :: M3N1TDzss = 1153 + INTEGER(IntKi), PARAMETER :: M3N2TDzss = 1154 + INTEGER(IntKi), PARAMETER :: M3N3TDzss = 1155 + INTEGER(IntKi), PARAMETER :: M3N4TDzss = 1156 + INTEGER(IntKi), PARAMETER :: M3N5TDzss = 1157 + INTEGER(IntKi), PARAMETER :: M3N6TDzss = 1158 + INTEGER(IntKi), PARAMETER :: M3N7TDzss = 1159 + INTEGER(IntKi), PARAMETER :: M3N8TDzss = 1160 + INTEGER(IntKi), PARAMETER :: M3N9TDzss = 1161 + INTEGER(IntKi), PARAMETER :: M4N1TDzss = 1162 + INTEGER(IntKi), PARAMETER :: M4N2TDzss = 1163 + INTEGER(IntKi), PARAMETER :: M4N3TDzss = 1164 + INTEGER(IntKi), PARAMETER :: M4N4TDzss = 1165 + INTEGER(IntKi), PARAMETER :: M4N5TDzss = 1166 + INTEGER(IntKi), PARAMETER :: M4N6TDzss = 1167 + INTEGER(IntKi), PARAMETER :: M4N7TDzss = 1168 + INTEGER(IntKi), PARAMETER :: M4N8TDzss = 1169 + INTEGER(IntKi), PARAMETER :: M4N9TDzss = 1170 + INTEGER(IntKi), PARAMETER :: M5N1TDzss = 1171 + INTEGER(IntKi), PARAMETER :: M5N2TDzss = 1172 + INTEGER(IntKi), PARAMETER :: M5N3TDzss = 1173 + INTEGER(IntKi), PARAMETER :: M5N4TDzss = 1174 + INTEGER(IntKi), PARAMETER :: M5N5TDzss = 1175 + INTEGER(IntKi), PARAMETER :: M5N6TDzss = 1176 + INTEGER(IntKi), PARAMETER :: M5N7TDzss = 1177 + INTEGER(IntKi), PARAMETER :: M5N8TDzss = 1178 + INTEGER(IntKi), PARAMETER :: M5N9TDzss = 1179 + INTEGER(IntKi), PARAMETER :: M6N1TDzss = 1180 + INTEGER(IntKi), PARAMETER :: M6N2TDzss = 1181 + INTEGER(IntKi), PARAMETER :: M6N3TDzss = 1182 + INTEGER(IntKi), PARAMETER :: M6N4TDzss = 1183 + INTEGER(IntKi), PARAMETER :: M6N5TDzss = 1184 + INTEGER(IntKi), PARAMETER :: M6N6TDzss = 1185 + INTEGER(IntKi), PARAMETER :: M6N7TDzss = 1186 + INTEGER(IntKi), PARAMETER :: M6N8TDzss = 1187 + INTEGER(IntKi), PARAMETER :: M6N9TDzss = 1188 + INTEGER(IntKi), PARAMETER :: M7N1TDzss = 1189 + INTEGER(IntKi), PARAMETER :: M7N2TDzss = 1190 + INTEGER(IntKi), PARAMETER :: M7N3TDzss = 1191 + INTEGER(IntKi), PARAMETER :: M7N4TDzss = 1192 + INTEGER(IntKi), PARAMETER :: M7N5TDzss = 1193 + INTEGER(IntKi), PARAMETER :: M7N6TDzss = 1194 + INTEGER(IntKi), PARAMETER :: M7N7TDzss = 1195 + INTEGER(IntKi), PARAMETER :: M7N8TDzss = 1196 + INTEGER(IntKi), PARAMETER :: M7N9TDzss = 1197 + INTEGER(IntKi), PARAMETER :: M8N1TDzss = 1198 + INTEGER(IntKi), PARAMETER :: M8N2TDzss = 1199 + INTEGER(IntKi), PARAMETER :: M8N3TDzss = 1200 + INTEGER(IntKi), PARAMETER :: M8N4TDzss = 1201 + INTEGER(IntKi), PARAMETER :: M8N5TDzss = 1202 + INTEGER(IntKi), PARAMETER :: M8N6TDzss = 1203 + INTEGER(IntKi), PARAMETER :: M8N7TDzss = 1204 + INTEGER(IntKi), PARAMETER :: M8N8TDzss = 1205 + INTEGER(IntKi), PARAMETER :: M8N9TDzss = 1206 + INTEGER(IntKi), PARAMETER :: M9N1TDzss = 1207 + INTEGER(IntKi), PARAMETER :: M9N2TDzss = 1208 + INTEGER(IntKi), PARAMETER :: M9N3TDzss = 1209 + INTEGER(IntKi), PARAMETER :: M9N4TDzss = 1210 + INTEGER(IntKi), PARAMETER :: M9N5TDzss = 1211 + INTEGER(IntKi), PARAMETER :: M9N6TDzss = 1212 + INTEGER(IntKi), PARAMETER :: M9N7TDzss = 1213 + INTEGER(IntKi), PARAMETER :: M9N8TDzss = 1214 + INTEGER(IntKi), PARAMETER :: M9N9TDzss = 1215 + INTEGER(IntKi), PARAMETER :: M1N1RDxe = 1216 + INTEGER(IntKi), PARAMETER :: M1N2RDxe = 1217 + INTEGER(IntKi), PARAMETER :: M1N3RDxe = 1218 + INTEGER(IntKi), PARAMETER :: M1N4RDxe = 1219 + INTEGER(IntKi), PARAMETER :: M1N5RDxe = 1220 + INTEGER(IntKi), PARAMETER :: M1N6RDxe = 1221 + INTEGER(IntKi), PARAMETER :: M1N7RDxe = 1222 + INTEGER(IntKi), PARAMETER :: M1N8RDxe = 1223 + INTEGER(IntKi), PARAMETER :: M1N9RDxe = 1224 + INTEGER(IntKi), PARAMETER :: M2N1RDxe = 1225 + INTEGER(IntKi), PARAMETER :: M2N2RDxe = 1226 + INTEGER(IntKi), PARAMETER :: M2N3RDxe = 1227 + INTEGER(IntKi), PARAMETER :: M2N4RDxe = 1228 + INTEGER(IntKi), PARAMETER :: M2N5RDxe = 1229 + INTEGER(IntKi), PARAMETER :: M2N6RDxe = 1230 + INTEGER(IntKi), PARAMETER :: M2N7RDxe = 1231 + INTEGER(IntKi), PARAMETER :: M2N8RDxe = 1232 + INTEGER(IntKi), PARAMETER :: M2N9RDxe = 1233 + INTEGER(IntKi), PARAMETER :: M3N1RDxe = 1234 + INTEGER(IntKi), PARAMETER :: M3N2RDxe = 1235 + INTEGER(IntKi), PARAMETER :: M3N3RDxe = 1236 + INTEGER(IntKi), PARAMETER :: M3N4RDxe = 1237 + INTEGER(IntKi), PARAMETER :: M3N5RDxe = 1238 + INTEGER(IntKi), PARAMETER :: M3N6RDxe = 1239 + INTEGER(IntKi), PARAMETER :: M3N7RDxe = 1240 + INTEGER(IntKi), PARAMETER :: M3N8RDxe = 1241 + INTEGER(IntKi), PARAMETER :: M3N9RDxe = 1242 + INTEGER(IntKi), PARAMETER :: M4N1RDxe = 1243 + INTEGER(IntKi), PARAMETER :: M4N2RDxe = 1244 + INTEGER(IntKi), PARAMETER :: M4N3RDxe = 1245 + INTEGER(IntKi), PARAMETER :: M4N4RDxe = 1246 + INTEGER(IntKi), PARAMETER :: M4N5RDxe = 1247 + INTEGER(IntKi), PARAMETER :: M4N6RDxe = 1248 + INTEGER(IntKi), PARAMETER :: M4N7RDxe = 1249 + INTEGER(IntKi), PARAMETER :: M4N8RDxe = 1250 + INTEGER(IntKi), PARAMETER :: M4N9RDxe = 1251 + INTEGER(IntKi), PARAMETER :: M5N1RDxe = 1252 + INTEGER(IntKi), PARAMETER :: M5N2RDxe = 1253 + INTEGER(IntKi), PARAMETER :: M5N3RDxe = 1254 + INTEGER(IntKi), PARAMETER :: M5N4RDxe = 1255 + INTEGER(IntKi), PARAMETER :: M5N5RDxe = 1256 + INTEGER(IntKi), PARAMETER :: M5N6RDxe = 1257 + INTEGER(IntKi), PARAMETER :: M5N7RDxe = 1258 + INTEGER(IntKi), PARAMETER :: M5N8RDxe = 1259 + INTEGER(IntKi), PARAMETER :: M5N9RDxe = 1260 + INTEGER(IntKi), PARAMETER :: M6N1RDxe = 1261 + INTEGER(IntKi), PARAMETER :: M6N2RDxe = 1262 + INTEGER(IntKi), PARAMETER :: M6N3RDxe = 1263 + INTEGER(IntKi), PARAMETER :: M6N4RDxe = 1264 + INTEGER(IntKi), PARAMETER :: M6N5RDxe = 1265 + INTEGER(IntKi), PARAMETER :: M6N6RDxe = 1266 + INTEGER(IntKi), PARAMETER :: M6N7RDxe = 1267 + INTEGER(IntKi), PARAMETER :: M6N8RDxe = 1268 + INTEGER(IntKi), PARAMETER :: M6N9RDxe = 1269 + INTEGER(IntKi), PARAMETER :: M7N1RDxe = 1270 + INTEGER(IntKi), PARAMETER :: M7N2RDxe = 1271 + INTEGER(IntKi), PARAMETER :: M7N3RDxe = 1272 + INTEGER(IntKi), PARAMETER :: M7N4RDxe = 1273 + INTEGER(IntKi), PARAMETER :: M7N5RDxe = 1274 + INTEGER(IntKi), PARAMETER :: M7N6RDxe = 1275 + INTEGER(IntKi), PARAMETER :: M7N7RDxe = 1276 + INTEGER(IntKi), PARAMETER :: M7N8RDxe = 1277 + INTEGER(IntKi), PARAMETER :: M7N9RDxe = 1278 + INTEGER(IntKi), PARAMETER :: M8N1RDxe = 1279 + INTEGER(IntKi), PARAMETER :: M8N2RDxe = 1280 + INTEGER(IntKi), PARAMETER :: M8N3RDxe = 1281 + INTEGER(IntKi), PARAMETER :: M8N4RDxe = 1282 + INTEGER(IntKi), PARAMETER :: M8N5RDxe = 1283 + INTEGER(IntKi), PARAMETER :: M8N6RDxe = 1284 + INTEGER(IntKi), PARAMETER :: M8N7RDxe = 1285 + INTEGER(IntKi), PARAMETER :: M8N8RDxe = 1286 + INTEGER(IntKi), PARAMETER :: M8N9RDxe = 1287 + INTEGER(IntKi), PARAMETER :: M9N1RDxe = 1288 + INTEGER(IntKi), PARAMETER :: M9N2RDxe = 1289 + INTEGER(IntKi), PARAMETER :: M9N3RDxe = 1290 + INTEGER(IntKi), PARAMETER :: M9N4RDxe = 1291 + INTEGER(IntKi), PARAMETER :: M9N5RDxe = 1292 + INTEGER(IntKi), PARAMETER :: M9N6RDxe = 1293 + INTEGER(IntKi), PARAMETER :: M9N7RDxe = 1294 + INTEGER(IntKi), PARAMETER :: M9N8RDxe = 1295 + INTEGER(IntKi), PARAMETER :: M9N9RDxe = 1296 + INTEGER(IntKi), PARAMETER :: M1N1RDye = 1297 + INTEGER(IntKi), PARAMETER :: M1N2RDye = 1298 + INTEGER(IntKi), PARAMETER :: M1N3RDye = 1299 + INTEGER(IntKi), PARAMETER :: M1N4RDye = 1300 + INTEGER(IntKi), PARAMETER :: M1N5RDye = 1301 + INTEGER(IntKi), PARAMETER :: M1N6RDye = 1302 + INTEGER(IntKi), PARAMETER :: M1N7RDye = 1303 + INTEGER(IntKi), PARAMETER :: M1N8RDye = 1304 + INTEGER(IntKi), PARAMETER :: M1N9RDye = 1305 + INTEGER(IntKi), PARAMETER :: M2N1RDye = 1306 + INTEGER(IntKi), PARAMETER :: M2N2RDye = 1307 + INTEGER(IntKi), PARAMETER :: M2N3RDye = 1308 + INTEGER(IntKi), PARAMETER :: M2N4RDye = 1309 + INTEGER(IntKi), PARAMETER :: M2N5RDye = 1310 + INTEGER(IntKi), PARAMETER :: M2N6RDye = 1311 + INTEGER(IntKi), PARAMETER :: M2N7RDye = 1312 + INTEGER(IntKi), PARAMETER :: M2N8RDye = 1313 + INTEGER(IntKi), PARAMETER :: M2N9RDye = 1314 + INTEGER(IntKi), PARAMETER :: M3N1RDye = 1315 + INTEGER(IntKi), PARAMETER :: M3N2RDye = 1316 + INTEGER(IntKi), PARAMETER :: M3N3RDye = 1317 + INTEGER(IntKi), PARAMETER :: M3N4RDye = 1318 + INTEGER(IntKi), PARAMETER :: M3N5RDye = 1319 + INTEGER(IntKi), PARAMETER :: M3N6RDye = 1320 + INTEGER(IntKi), PARAMETER :: M3N7RDye = 1321 + INTEGER(IntKi), PARAMETER :: M3N8RDye = 1322 + INTEGER(IntKi), PARAMETER :: M3N9RDye = 1323 + INTEGER(IntKi), PARAMETER :: M4N1RDye = 1324 + INTEGER(IntKi), PARAMETER :: M4N2RDye = 1325 + INTEGER(IntKi), PARAMETER :: M4N3RDye = 1326 + INTEGER(IntKi), PARAMETER :: M4N4RDye = 1327 + INTEGER(IntKi), PARAMETER :: M4N5RDye = 1328 + INTEGER(IntKi), PARAMETER :: M4N6RDye = 1329 + INTEGER(IntKi), PARAMETER :: M4N7RDye = 1330 + INTEGER(IntKi), PARAMETER :: M4N8RDye = 1331 + INTEGER(IntKi), PARAMETER :: M4N9RDye = 1332 + INTEGER(IntKi), PARAMETER :: M5N1RDye = 1333 + INTEGER(IntKi), PARAMETER :: M5N2RDye = 1334 + INTEGER(IntKi), PARAMETER :: M5N3RDye = 1335 + INTEGER(IntKi), PARAMETER :: M5N4RDye = 1336 + INTEGER(IntKi), PARAMETER :: M5N5RDye = 1337 + INTEGER(IntKi), PARAMETER :: M5N6RDye = 1338 + INTEGER(IntKi), PARAMETER :: M5N7RDye = 1339 + INTEGER(IntKi), PARAMETER :: M5N8RDye = 1340 + INTEGER(IntKi), PARAMETER :: M5N9RDye = 1341 + INTEGER(IntKi), PARAMETER :: M6N1RDye = 1342 + INTEGER(IntKi), PARAMETER :: M6N2RDye = 1343 + INTEGER(IntKi), PARAMETER :: M6N3RDye = 1344 + INTEGER(IntKi), PARAMETER :: M6N4RDye = 1345 + INTEGER(IntKi), PARAMETER :: M6N5RDye = 1346 + INTEGER(IntKi), PARAMETER :: M6N6RDye = 1347 + INTEGER(IntKi), PARAMETER :: M6N7RDye = 1348 + INTEGER(IntKi), PARAMETER :: M6N8RDye = 1349 + INTEGER(IntKi), PARAMETER :: M6N9RDye = 1350 + INTEGER(IntKi), PARAMETER :: M7N1RDye = 1351 + INTEGER(IntKi), PARAMETER :: M7N2RDye = 1352 + INTEGER(IntKi), PARAMETER :: M7N3RDye = 1353 + INTEGER(IntKi), PARAMETER :: M7N4RDye = 1354 + INTEGER(IntKi), PARAMETER :: M7N5RDye = 1355 + INTEGER(IntKi), PARAMETER :: M7N6RDye = 1356 + INTEGER(IntKi), PARAMETER :: M7N7RDye = 1357 + INTEGER(IntKi), PARAMETER :: M7N8RDye = 1358 + INTEGER(IntKi), PARAMETER :: M7N9RDye = 1359 + INTEGER(IntKi), PARAMETER :: M8N1RDye = 1360 + INTEGER(IntKi), PARAMETER :: M8N2RDye = 1361 + INTEGER(IntKi), PARAMETER :: M8N3RDye = 1362 + INTEGER(IntKi), PARAMETER :: M8N4RDye = 1363 + INTEGER(IntKi), PARAMETER :: M8N5RDye = 1364 + INTEGER(IntKi), PARAMETER :: M8N6RDye = 1365 + INTEGER(IntKi), PARAMETER :: M8N7RDye = 1366 + INTEGER(IntKi), PARAMETER :: M8N8RDye = 1367 + INTEGER(IntKi), PARAMETER :: M8N9RDye = 1368 + INTEGER(IntKi), PARAMETER :: M9N1RDye = 1369 + INTEGER(IntKi), PARAMETER :: M9N2RDye = 1370 + INTEGER(IntKi), PARAMETER :: M9N3RDye = 1371 + INTEGER(IntKi), PARAMETER :: M9N4RDye = 1372 + INTEGER(IntKi), PARAMETER :: M9N5RDye = 1373 + INTEGER(IntKi), PARAMETER :: M9N6RDye = 1374 + INTEGER(IntKi), PARAMETER :: M9N7RDye = 1375 + INTEGER(IntKi), PARAMETER :: M9N8RDye = 1376 + INTEGER(IntKi), PARAMETER :: M9N9RDye = 1377 + INTEGER(IntKi), PARAMETER :: M1N1RDze = 1378 + INTEGER(IntKi), PARAMETER :: M1N2RDze = 1379 + INTEGER(IntKi), PARAMETER :: M1N3RDze = 1380 + INTEGER(IntKi), PARAMETER :: M1N4RDze = 1381 + INTEGER(IntKi), PARAMETER :: M1N5RDze = 1382 + INTEGER(IntKi), PARAMETER :: M1N6RDze = 1383 + INTEGER(IntKi), PARAMETER :: M1N7RDze = 1384 + INTEGER(IntKi), PARAMETER :: M1N8RDze = 1385 + INTEGER(IntKi), PARAMETER :: M1N9RDze = 1386 + INTEGER(IntKi), PARAMETER :: M2N1RDze = 1387 + INTEGER(IntKi), PARAMETER :: M2N2RDze = 1388 + INTEGER(IntKi), PARAMETER :: M2N3RDze = 1389 + INTEGER(IntKi), PARAMETER :: M2N4RDze = 1390 + INTEGER(IntKi), PARAMETER :: M2N5RDze = 1391 + INTEGER(IntKi), PARAMETER :: M2N6RDze = 1392 + INTEGER(IntKi), PARAMETER :: M2N7RDze = 1393 + INTEGER(IntKi), PARAMETER :: M2N8RDze = 1394 + INTEGER(IntKi), PARAMETER :: M2N9RDze = 1395 + INTEGER(IntKi), PARAMETER :: M3N1RDze = 1396 + INTEGER(IntKi), PARAMETER :: M3N2RDze = 1397 + INTEGER(IntKi), PARAMETER :: M3N3RDze = 1398 + INTEGER(IntKi), PARAMETER :: M3N4RDze = 1399 + INTEGER(IntKi), PARAMETER :: M3N5RDze = 1400 + INTEGER(IntKi), PARAMETER :: M3N6RDze = 1401 + INTEGER(IntKi), PARAMETER :: M3N7RDze = 1402 + INTEGER(IntKi), PARAMETER :: M3N8RDze = 1403 + INTEGER(IntKi), PARAMETER :: M3N9RDze = 1404 + INTEGER(IntKi), PARAMETER :: M4N1RDze = 1405 + INTEGER(IntKi), PARAMETER :: M4N2RDze = 1406 + INTEGER(IntKi), PARAMETER :: M4N3RDze = 1407 + INTEGER(IntKi), PARAMETER :: M4N4RDze = 1408 + INTEGER(IntKi), PARAMETER :: M4N5RDze = 1409 + INTEGER(IntKi), PARAMETER :: M4N6RDze = 1410 + INTEGER(IntKi), PARAMETER :: M4N7RDze = 1411 + INTEGER(IntKi), PARAMETER :: M4N8RDze = 1412 + INTEGER(IntKi), PARAMETER :: M4N9RDze = 1413 + INTEGER(IntKi), PARAMETER :: M5N1RDze = 1414 + INTEGER(IntKi), PARAMETER :: M5N2RDze = 1415 + INTEGER(IntKi), PARAMETER :: M5N3RDze = 1416 + INTEGER(IntKi), PARAMETER :: M5N4RDze = 1417 + INTEGER(IntKi), PARAMETER :: M5N5RDze = 1418 + INTEGER(IntKi), PARAMETER :: M5N6RDze = 1419 + INTEGER(IntKi), PARAMETER :: M5N7RDze = 1420 + INTEGER(IntKi), PARAMETER :: M5N8RDze = 1421 + INTEGER(IntKi), PARAMETER :: M5N9RDze = 1422 + INTEGER(IntKi), PARAMETER :: M6N1RDze = 1423 + INTEGER(IntKi), PARAMETER :: M6N2RDze = 1424 + INTEGER(IntKi), PARAMETER :: M6N3RDze = 1425 + INTEGER(IntKi), PARAMETER :: M6N4RDze = 1426 + INTEGER(IntKi), PARAMETER :: M6N5RDze = 1427 + INTEGER(IntKi), PARAMETER :: M6N6RDze = 1428 + INTEGER(IntKi), PARAMETER :: M6N7RDze = 1429 + INTEGER(IntKi), PARAMETER :: M6N8RDze = 1430 + INTEGER(IntKi), PARAMETER :: M6N9RDze = 1431 + INTEGER(IntKi), PARAMETER :: M7N1RDze = 1432 + INTEGER(IntKi), PARAMETER :: M7N2RDze = 1433 + INTEGER(IntKi), PARAMETER :: M7N3RDze = 1434 + INTEGER(IntKi), PARAMETER :: M7N4RDze = 1435 + INTEGER(IntKi), PARAMETER :: M7N5RDze = 1436 + INTEGER(IntKi), PARAMETER :: M7N6RDze = 1437 + INTEGER(IntKi), PARAMETER :: M7N7RDze = 1438 + INTEGER(IntKi), PARAMETER :: M7N8RDze = 1439 + INTEGER(IntKi), PARAMETER :: M7N9RDze = 1440 + INTEGER(IntKi), PARAMETER :: M8N1RDze = 1441 + INTEGER(IntKi), PARAMETER :: M8N2RDze = 1442 + INTEGER(IntKi), PARAMETER :: M8N3RDze = 1443 + INTEGER(IntKi), PARAMETER :: M8N4RDze = 1444 + INTEGER(IntKi), PARAMETER :: M8N5RDze = 1445 + INTEGER(IntKi), PARAMETER :: M8N6RDze = 1446 + INTEGER(IntKi), PARAMETER :: M8N7RDze = 1447 + INTEGER(IntKi), PARAMETER :: M8N8RDze = 1448 + INTEGER(IntKi), PARAMETER :: M8N9RDze = 1449 + INTEGER(IntKi), PARAMETER :: M9N1RDze = 1450 + INTEGER(IntKi), PARAMETER :: M9N2RDze = 1451 + INTEGER(IntKi), PARAMETER :: M9N3RDze = 1452 + INTEGER(IntKi), PARAMETER :: M9N4RDze = 1453 + INTEGER(IntKi), PARAMETER :: M9N5RDze = 1454 + INTEGER(IntKi), PARAMETER :: M9N6RDze = 1455 + INTEGER(IntKi), PARAMETER :: M9N7RDze = 1456 + INTEGER(IntKi), PARAMETER :: M9N8RDze = 1457 + INTEGER(IntKi), PARAMETER :: M9N9RDze = 1458 + + + ! Accelerations: + + INTEGER(IntKi), PARAMETER :: M1N1TAxe = 1459 + INTEGER(IntKi), PARAMETER :: M1N2TAxe = 1460 + INTEGER(IntKi), PARAMETER :: M1N3TAxe = 1461 + INTEGER(IntKi), PARAMETER :: M1N4TAxe = 1462 + INTEGER(IntKi), PARAMETER :: M1N5TAxe = 1463 + INTEGER(IntKi), PARAMETER :: M1N6TAxe = 1464 + INTEGER(IntKi), PARAMETER :: M1N7TAxe = 1465 + INTEGER(IntKi), PARAMETER :: M1N8TAxe = 1466 + INTEGER(IntKi), PARAMETER :: M1N9TAxe = 1467 + INTEGER(IntKi), PARAMETER :: M2N1TAxe = 1468 + INTEGER(IntKi), PARAMETER :: M2N2TAxe = 1469 + INTEGER(IntKi), PARAMETER :: M2N3TAxe = 1470 + INTEGER(IntKi), PARAMETER :: M2N4TAxe = 1471 + INTEGER(IntKi), PARAMETER :: M2N5TAxe = 1472 + INTEGER(IntKi), PARAMETER :: M2N6TAxe = 1473 + INTEGER(IntKi), PARAMETER :: M2N7TAxe = 1474 + INTEGER(IntKi), PARAMETER :: M2N8TAxe = 1475 + INTEGER(IntKi), PARAMETER :: M2N9TAxe = 1476 + INTEGER(IntKi), PARAMETER :: M3N1TAxe = 1477 + INTEGER(IntKi), PARAMETER :: M3N2TAxe = 1478 + INTEGER(IntKi), PARAMETER :: M3N3TAxe = 1479 + INTEGER(IntKi), PARAMETER :: M3N4TAxe = 1480 + INTEGER(IntKi), PARAMETER :: M3N5TAxe = 1481 + INTEGER(IntKi), PARAMETER :: M3N6TAxe = 1482 + INTEGER(IntKi), PARAMETER :: M3N7TAxe = 1483 + INTEGER(IntKi), PARAMETER :: M3N8TAxe = 1484 + INTEGER(IntKi), PARAMETER :: M3N9TAxe = 1485 + INTEGER(IntKi), PARAMETER :: M4N1TAxe = 1486 + INTEGER(IntKi), PARAMETER :: M4N2TAxe = 1487 + INTEGER(IntKi), PARAMETER :: M4N3TAxe = 1488 + INTEGER(IntKi), PARAMETER :: M4N4TAxe = 1489 + INTEGER(IntKi), PARAMETER :: M4N5TAxe = 1490 + INTEGER(IntKi), PARAMETER :: M4N6TAxe = 1491 + INTEGER(IntKi), PARAMETER :: M4N7TAxe = 1492 + INTEGER(IntKi), PARAMETER :: M4N8TAxe = 1493 + INTEGER(IntKi), PARAMETER :: M4N9TAxe = 1494 + INTEGER(IntKi), PARAMETER :: M5N1TAxe = 1495 + INTEGER(IntKi), PARAMETER :: M5N2TAxe = 1496 + INTEGER(IntKi), PARAMETER :: M5N3TAxe = 1497 + INTEGER(IntKi), PARAMETER :: M5N4TAxe = 1498 + INTEGER(IntKi), PARAMETER :: M5N5TAxe = 1499 + INTEGER(IntKi), PARAMETER :: M5N6TAxe = 1500 + INTEGER(IntKi), PARAMETER :: M5N7TAxe = 1501 + INTEGER(IntKi), PARAMETER :: M5N8TAxe = 1502 + INTEGER(IntKi), PARAMETER :: M5N9TAxe = 1503 + INTEGER(IntKi), PARAMETER :: M6N1TAxe = 1504 + INTEGER(IntKi), PARAMETER :: M6N2TAxe = 1505 + INTEGER(IntKi), PARAMETER :: M6N3TAxe = 1506 + INTEGER(IntKi), PARAMETER :: M6N4TAxe = 1507 + INTEGER(IntKi), PARAMETER :: M6N5TAxe = 1508 + INTEGER(IntKi), PARAMETER :: M6N6TAxe = 1509 + INTEGER(IntKi), PARAMETER :: M6N7TAxe = 1510 + INTEGER(IntKi), PARAMETER :: M6N8TAxe = 1511 + INTEGER(IntKi), PARAMETER :: M6N9TAxe = 1512 + INTEGER(IntKi), PARAMETER :: M7N1TAxe = 1513 + INTEGER(IntKi), PARAMETER :: M7N2TAxe = 1514 + INTEGER(IntKi), PARAMETER :: M7N3TAxe = 1515 + INTEGER(IntKi), PARAMETER :: M7N4TAxe = 1516 + INTEGER(IntKi), PARAMETER :: M7N5TAxe = 1517 + INTEGER(IntKi), PARAMETER :: M7N6TAxe = 1518 + INTEGER(IntKi), PARAMETER :: M7N7TAxe = 1519 + INTEGER(IntKi), PARAMETER :: M7N8TAxe = 1520 + INTEGER(IntKi), PARAMETER :: M7N9TAxe = 1521 + INTEGER(IntKi), PARAMETER :: M8N1TAxe = 1522 + INTEGER(IntKi), PARAMETER :: M8N2TAxe = 1523 + INTEGER(IntKi), PARAMETER :: M8N3TAxe = 1524 + INTEGER(IntKi), PARAMETER :: M8N4TAxe = 1525 + INTEGER(IntKi), PARAMETER :: M8N5TAxe = 1526 + INTEGER(IntKi), PARAMETER :: M8N6TAxe = 1527 + INTEGER(IntKi), PARAMETER :: M8N7TAxe = 1528 + INTEGER(IntKi), PARAMETER :: M8N8TAxe = 1529 + INTEGER(IntKi), PARAMETER :: M8N9TAxe = 1530 + INTEGER(IntKi), PARAMETER :: M9N1TAxe = 1531 + INTEGER(IntKi), PARAMETER :: M9N2TAxe = 1532 + INTEGER(IntKi), PARAMETER :: M9N3TAxe = 1533 + INTEGER(IntKi), PARAMETER :: M9N4TAxe = 1534 + INTEGER(IntKi), PARAMETER :: M9N5TAxe = 1535 + INTEGER(IntKi), PARAMETER :: M9N6TAxe = 1536 + INTEGER(IntKi), PARAMETER :: M9N7TAxe = 1537 + INTEGER(IntKi), PARAMETER :: M9N8TAxe = 1538 + INTEGER(IntKi), PARAMETER :: M9N9TAxe = 1539 + INTEGER(IntKi), PARAMETER :: M1N1TAye = 1540 + INTEGER(IntKi), PARAMETER :: M1N2TAye = 1541 + INTEGER(IntKi), PARAMETER :: M1N3TAye = 1542 + INTEGER(IntKi), PARAMETER :: M1N4TAye = 1543 + INTEGER(IntKi), PARAMETER :: M1N5TAye = 1544 + INTEGER(IntKi), PARAMETER :: M1N6TAye = 1545 + INTEGER(IntKi), PARAMETER :: M1N7TAye = 1546 + INTEGER(IntKi), PARAMETER :: M1N8TAye = 1547 + INTEGER(IntKi), PARAMETER :: M1N9TAye = 1548 + INTEGER(IntKi), PARAMETER :: M2N1TAye = 1549 + INTEGER(IntKi), PARAMETER :: M2N2TAye = 1550 + INTEGER(IntKi), PARAMETER :: M2N3TAye = 1551 + INTEGER(IntKi), PARAMETER :: M2N4TAye = 1552 + INTEGER(IntKi), PARAMETER :: M2N5TAye = 1553 + INTEGER(IntKi), PARAMETER :: M2N6TAye = 1554 + INTEGER(IntKi), PARAMETER :: M2N7TAye = 1555 + INTEGER(IntKi), PARAMETER :: M2N8TAye = 1556 + INTEGER(IntKi), PARAMETER :: M2N9TAye = 1557 + INTEGER(IntKi), PARAMETER :: M3N1TAye = 1558 + INTEGER(IntKi), PARAMETER :: M3N2TAye = 1559 + INTEGER(IntKi), PARAMETER :: M3N3TAye = 1560 + INTEGER(IntKi), PARAMETER :: M3N4TAye = 1561 + INTEGER(IntKi), PARAMETER :: M3N5TAye = 1562 + INTEGER(IntKi), PARAMETER :: M3N6TAye = 1563 + INTEGER(IntKi), PARAMETER :: M3N7TAye = 1564 + INTEGER(IntKi), PARAMETER :: M3N8TAye = 1565 + INTEGER(IntKi), PARAMETER :: M3N9TAye = 1566 + INTEGER(IntKi), PARAMETER :: M4N1TAye = 1567 + INTEGER(IntKi), PARAMETER :: M4N2TAye = 1568 + INTEGER(IntKi), PARAMETER :: M4N3TAye = 1569 + INTEGER(IntKi), PARAMETER :: M4N4TAye = 1570 + INTEGER(IntKi), PARAMETER :: M4N5TAye = 1571 + INTEGER(IntKi), PARAMETER :: M4N6TAye = 1572 + INTEGER(IntKi), PARAMETER :: M4N7TAye = 1573 + INTEGER(IntKi), PARAMETER :: M4N8TAye = 1574 + INTEGER(IntKi), PARAMETER :: M4N9TAye = 1575 + INTEGER(IntKi), PARAMETER :: M5N1TAye = 1576 + INTEGER(IntKi), PARAMETER :: M5N2TAye = 1577 + INTEGER(IntKi), PARAMETER :: M5N3TAye = 1578 + INTEGER(IntKi), PARAMETER :: M5N4TAye = 1579 + INTEGER(IntKi), PARAMETER :: M5N5TAye = 1580 + INTEGER(IntKi), PARAMETER :: M5N6TAye = 1581 + INTEGER(IntKi), PARAMETER :: M5N7TAye = 1582 + INTEGER(IntKi), PARAMETER :: M5N8TAye = 1583 + INTEGER(IntKi), PARAMETER :: M5N9TAye = 1584 + INTEGER(IntKi), PARAMETER :: M6N1TAye = 1585 + INTEGER(IntKi), PARAMETER :: M6N2TAye = 1586 + INTEGER(IntKi), PARAMETER :: M6N3TAye = 1587 + INTEGER(IntKi), PARAMETER :: M6N4TAye = 1588 + INTEGER(IntKi), PARAMETER :: M6N5TAye = 1589 + INTEGER(IntKi), PARAMETER :: M6N6TAye = 1590 + INTEGER(IntKi), PARAMETER :: M6N7TAye = 1591 + INTEGER(IntKi), PARAMETER :: M6N8TAye = 1592 + INTEGER(IntKi), PARAMETER :: M6N9TAye = 1593 + INTEGER(IntKi), PARAMETER :: M7N1TAye = 1594 + INTEGER(IntKi), PARAMETER :: M7N2TAye = 1595 + INTEGER(IntKi), PARAMETER :: M7N3TAye = 1596 + INTEGER(IntKi), PARAMETER :: M7N4TAye = 1597 + INTEGER(IntKi), PARAMETER :: M7N5TAye = 1598 + INTEGER(IntKi), PARAMETER :: M7N6TAye = 1599 + INTEGER(IntKi), PARAMETER :: M7N7TAye = 1600 + INTEGER(IntKi), PARAMETER :: M7N8TAye = 1601 + INTEGER(IntKi), PARAMETER :: M7N9TAye = 1602 + INTEGER(IntKi), PARAMETER :: M8N1TAye = 1603 + INTEGER(IntKi), PARAMETER :: M8N2TAye = 1604 + INTEGER(IntKi), PARAMETER :: M8N3TAye = 1605 + INTEGER(IntKi), PARAMETER :: M8N4TAye = 1606 + INTEGER(IntKi), PARAMETER :: M8N5TAye = 1607 + INTEGER(IntKi), PARAMETER :: M8N6TAye = 1608 + INTEGER(IntKi), PARAMETER :: M8N7TAye = 1609 + INTEGER(IntKi), PARAMETER :: M8N8TAye = 1610 + INTEGER(IntKi), PARAMETER :: M8N9TAye = 1611 + INTEGER(IntKi), PARAMETER :: M9N1TAye = 1612 + INTEGER(IntKi), PARAMETER :: M9N2TAye = 1613 + INTEGER(IntKi), PARAMETER :: M9N3TAye = 1614 + INTEGER(IntKi), PARAMETER :: M9N4TAye = 1615 + INTEGER(IntKi), PARAMETER :: M9N5TAye = 1616 + INTEGER(IntKi), PARAMETER :: M9N6TAye = 1617 + INTEGER(IntKi), PARAMETER :: M9N7TAye = 1618 + INTEGER(IntKi), PARAMETER :: M9N8TAye = 1619 + INTEGER(IntKi), PARAMETER :: M9N9TAye = 1620 + INTEGER(IntKi), PARAMETER :: M1N1TAze = 1621 + INTEGER(IntKi), PARAMETER :: M1N2TAze = 1622 + INTEGER(IntKi), PARAMETER :: M1N3TAze = 1623 + INTEGER(IntKi), PARAMETER :: M1N4TAze = 1624 + INTEGER(IntKi), PARAMETER :: M1N5TAze = 1625 + INTEGER(IntKi), PARAMETER :: M1N6TAze = 1626 + INTEGER(IntKi), PARAMETER :: M1N7TAze = 1627 + INTEGER(IntKi), PARAMETER :: M1N8TAze = 1628 + INTEGER(IntKi), PARAMETER :: M1N9TAze = 1629 + INTEGER(IntKi), PARAMETER :: M2N1TAze = 1630 + INTEGER(IntKi), PARAMETER :: M2N2TAze = 1631 + INTEGER(IntKi), PARAMETER :: M2N3TAze = 1632 + INTEGER(IntKi), PARAMETER :: M2N4TAze = 1633 + INTEGER(IntKi), PARAMETER :: M2N5TAze = 1634 + INTEGER(IntKi), PARAMETER :: M2N6TAze = 1635 + INTEGER(IntKi), PARAMETER :: M2N7TAze = 1636 + INTEGER(IntKi), PARAMETER :: M2N8TAze = 1637 + INTEGER(IntKi), PARAMETER :: M2N9TAze = 1638 + INTEGER(IntKi), PARAMETER :: M3N1TAze = 1639 + INTEGER(IntKi), PARAMETER :: M3N2TAze = 1640 + INTEGER(IntKi), PARAMETER :: M3N3TAze = 1641 + INTEGER(IntKi), PARAMETER :: M3N4TAze = 1642 + INTEGER(IntKi), PARAMETER :: M3N5TAze = 1643 + INTEGER(IntKi), PARAMETER :: M3N6TAze = 1644 + INTEGER(IntKi), PARAMETER :: M3N7TAze = 1645 + INTEGER(IntKi), PARAMETER :: M3N8TAze = 1646 + INTEGER(IntKi), PARAMETER :: M3N9TAze = 1647 + INTEGER(IntKi), PARAMETER :: M4N1TAze = 1648 + INTEGER(IntKi), PARAMETER :: M4N2TAze = 1649 + INTEGER(IntKi), PARAMETER :: M4N3TAze = 1650 + INTEGER(IntKi), PARAMETER :: M4N4TAze = 1651 + INTEGER(IntKi), PARAMETER :: M4N5TAze = 1652 + INTEGER(IntKi), PARAMETER :: M4N6TAze = 1653 + INTEGER(IntKi), PARAMETER :: M4N7TAze = 1654 + INTEGER(IntKi), PARAMETER :: M4N8TAze = 1655 + INTEGER(IntKi), PARAMETER :: M4N9TAze = 1656 + INTEGER(IntKi), PARAMETER :: M5N1TAze = 1657 + INTEGER(IntKi), PARAMETER :: M5N2TAze = 1658 + INTEGER(IntKi), PARAMETER :: M5N3TAze = 1659 + INTEGER(IntKi), PARAMETER :: M5N4TAze = 1660 + INTEGER(IntKi), PARAMETER :: M5N5TAze = 1661 + INTEGER(IntKi), PARAMETER :: M5N6TAze = 1662 + INTEGER(IntKi), PARAMETER :: M5N7TAze = 1663 + INTEGER(IntKi), PARAMETER :: M5N8TAze = 1664 + INTEGER(IntKi), PARAMETER :: M5N9TAze = 1665 + INTEGER(IntKi), PARAMETER :: M6N1TAze = 1666 + INTEGER(IntKi), PARAMETER :: M6N2TAze = 1667 + INTEGER(IntKi), PARAMETER :: M6N3TAze = 1668 + INTEGER(IntKi), PARAMETER :: M6N4TAze = 1669 + INTEGER(IntKi), PARAMETER :: M6N5TAze = 1670 + INTEGER(IntKi), PARAMETER :: M6N6TAze = 1671 + INTEGER(IntKi), PARAMETER :: M6N7TAze = 1672 + INTEGER(IntKi), PARAMETER :: M6N8TAze = 1673 + INTEGER(IntKi), PARAMETER :: M6N9TAze = 1674 + INTEGER(IntKi), PARAMETER :: M7N1TAze = 1675 + INTEGER(IntKi), PARAMETER :: M7N2TAze = 1676 + INTEGER(IntKi), PARAMETER :: M7N3TAze = 1677 + INTEGER(IntKi), PARAMETER :: M7N4TAze = 1678 + INTEGER(IntKi), PARAMETER :: M7N5TAze = 1679 + INTEGER(IntKi), PARAMETER :: M7N6TAze = 1680 + INTEGER(IntKi), PARAMETER :: M7N7TAze = 1681 + INTEGER(IntKi), PARAMETER :: M7N8TAze = 1682 + INTEGER(IntKi), PARAMETER :: M7N9TAze = 1683 + INTEGER(IntKi), PARAMETER :: M8N1TAze = 1684 + INTEGER(IntKi), PARAMETER :: M8N2TAze = 1685 + INTEGER(IntKi), PARAMETER :: M8N3TAze = 1686 + INTEGER(IntKi), PARAMETER :: M8N4TAze = 1687 + INTEGER(IntKi), PARAMETER :: M8N5TAze = 1688 + INTEGER(IntKi), PARAMETER :: M8N6TAze = 1689 + INTEGER(IntKi), PARAMETER :: M8N7TAze = 1690 + INTEGER(IntKi), PARAMETER :: M8N8TAze = 1691 + INTEGER(IntKi), PARAMETER :: M8N9TAze = 1692 + INTEGER(IntKi), PARAMETER :: M9N1TAze = 1693 + INTEGER(IntKi), PARAMETER :: M9N2TAze = 1694 + INTEGER(IntKi), PARAMETER :: M9N3TAze = 1695 + INTEGER(IntKi), PARAMETER :: M9N4TAze = 1696 + INTEGER(IntKi), PARAMETER :: M9N5TAze = 1697 + INTEGER(IntKi), PARAMETER :: M9N6TAze = 1698 + INTEGER(IntKi), PARAMETER :: M9N7TAze = 1699 + INTEGER(IntKi), PARAMETER :: M9N8TAze = 1700 + INTEGER(IntKi), PARAMETER :: M9N9TAze = 1701 + INTEGER(IntKi), PARAMETER :: M1N1RAxe = 1702 + INTEGER(IntKi), PARAMETER :: M1N2RAxe = 1703 + INTEGER(IntKi), PARAMETER :: M1N3RAxe = 1704 + INTEGER(IntKi), PARAMETER :: M1N4RAxe = 1705 + INTEGER(IntKi), PARAMETER :: M1N5RAxe = 1706 + INTEGER(IntKi), PARAMETER :: M1N6RAxe = 1707 + INTEGER(IntKi), PARAMETER :: M1N7RAxe = 1708 + INTEGER(IntKi), PARAMETER :: M1N8RAxe = 1709 + INTEGER(IntKi), PARAMETER :: M1N9RAxe = 1710 + INTEGER(IntKi), PARAMETER :: M2N1RAxe = 1711 + INTEGER(IntKi), PARAMETER :: M2N2RAxe = 1712 + INTEGER(IntKi), PARAMETER :: M2N3RAxe = 1713 + INTEGER(IntKi), PARAMETER :: M2N4RAxe = 1714 + INTEGER(IntKi), PARAMETER :: M2N5RAxe = 1715 + INTEGER(IntKi), PARAMETER :: M2N6RAxe = 1716 + INTEGER(IntKi), PARAMETER :: M2N7RAxe = 1717 + INTEGER(IntKi), PARAMETER :: M2N8RAxe = 1718 + INTEGER(IntKi), PARAMETER :: M2N9RAxe = 1719 + INTEGER(IntKi), PARAMETER :: M3N1RAxe = 1720 + INTEGER(IntKi), PARAMETER :: M3N2RAxe = 1721 + INTEGER(IntKi), PARAMETER :: M3N3RAxe = 1722 + INTEGER(IntKi), PARAMETER :: M3N4RAxe = 1723 + INTEGER(IntKi), PARAMETER :: M3N5RAxe = 1724 + INTEGER(IntKi), PARAMETER :: M3N6RAxe = 1725 + INTEGER(IntKi), PARAMETER :: M3N7RAxe = 1726 + INTEGER(IntKi), PARAMETER :: M3N8RAxe = 1727 + INTEGER(IntKi), PARAMETER :: M3N9RAxe = 1728 + INTEGER(IntKi), PARAMETER :: M4N1RAxe = 1729 + INTEGER(IntKi), PARAMETER :: M4N2RAxe = 1730 + INTEGER(IntKi), PARAMETER :: M4N3RAxe = 1731 + INTEGER(IntKi), PARAMETER :: M4N4RAxe = 1732 + INTEGER(IntKi), PARAMETER :: M4N5RAxe = 1733 + INTEGER(IntKi), PARAMETER :: M4N6RAxe = 1734 + INTEGER(IntKi), PARAMETER :: M4N7RAxe = 1735 + INTEGER(IntKi), PARAMETER :: M4N8RAxe = 1736 + INTEGER(IntKi), PARAMETER :: M4N9RAxe = 1737 + INTEGER(IntKi), PARAMETER :: M5N1RAxe = 1738 + INTEGER(IntKi), PARAMETER :: M5N2RAxe = 1739 + INTEGER(IntKi), PARAMETER :: M5N3RAxe = 1740 + INTEGER(IntKi), PARAMETER :: M5N4RAxe = 1741 + INTEGER(IntKi), PARAMETER :: M5N5RAxe = 1742 + INTEGER(IntKi), PARAMETER :: M5N6RAxe = 1743 + INTEGER(IntKi), PARAMETER :: M5N7RAxe = 1744 + INTEGER(IntKi), PARAMETER :: M5N8RAxe = 1745 + INTEGER(IntKi), PARAMETER :: M5N9RAxe = 1746 + INTEGER(IntKi), PARAMETER :: M6N1RAxe = 1747 + INTEGER(IntKi), PARAMETER :: M6N2RAxe = 1748 + INTEGER(IntKi), PARAMETER :: M6N3RAxe = 1749 + INTEGER(IntKi), PARAMETER :: M6N4RAxe = 1750 + INTEGER(IntKi), PARAMETER :: M6N5RAxe = 1751 + INTEGER(IntKi), PARAMETER :: M6N6RAxe = 1752 + INTEGER(IntKi), PARAMETER :: M6N7RAxe = 1753 + INTEGER(IntKi), PARAMETER :: M6N8RAxe = 1754 + INTEGER(IntKi), PARAMETER :: M6N9RAxe = 1755 + INTEGER(IntKi), PARAMETER :: M7N1RAxe = 1756 + INTEGER(IntKi), PARAMETER :: M7N2RAxe = 1757 + INTEGER(IntKi), PARAMETER :: M7N3RAxe = 1758 + INTEGER(IntKi), PARAMETER :: M7N4RAxe = 1759 + INTEGER(IntKi), PARAMETER :: M7N5RAxe = 1760 + INTEGER(IntKi), PARAMETER :: M7N6RAxe = 1761 + INTEGER(IntKi), PARAMETER :: M7N7RAxe = 1762 + INTEGER(IntKi), PARAMETER :: M7N8RAxe = 1763 + INTEGER(IntKi), PARAMETER :: M7N9RAxe = 1764 + INTEGER(IntKi), PARAMETER :: M8N1RAxe = 1765 + INTEGER(IntKi), PARAMETER :: M8N2RAxe = 1766 + INTEGER(IntKi), PARAMETER :: M8N3RAxe = 1767 + INTEGER(IntKi), PARAMETER :: M8N4RAxe = 1768 + INTEGER(IntKi), PARAMETER :: M8N5RAxe = 1769 + INTEGER(IntKi), PARAMETER :: M8N6RAxe = 1770 + INTEGER(IntKi), PARAMETER :: M8N7RAxe = 1771 + INTEGER(IntKi), PARAMETER :: M8N8RAxe = 1772 + INTEGER(IntKi), PARAMETER :: M8N9RAxe = 1773 + INTEGER(IntKi), PARAMETER :: M9N1RAxe = 1774 + INTEGER(IntKi), PARAMETER :: M9N2RAxe = 1775 + INTEGER(IntKi), PARAMETER :: M9N3RAxe = 1776 + INTEGER(IntKi), PARAMETER :: M9N4RAxe = 1777 + INTEGER(IntKi), PARAMETER :: M9N5RAxe = 1778 + INTEGER(IntKi), PARAMETER :: M9N6RAxe = 1779 + INTEGER(IntKi), PARAMETER :: M9N7RAxe = 1780 + INTEGER(IntKi), PARAMETER :: M9N8RAxe = 1781 + INTEGER(IntKi), PARAMETER :: M9N9RAxe = 1782 + INTEGER(IntKi), PARAMETER :: M1N1RAye = 1783 + INTEGER(IntKi), PARAMETER :: M1N2RAye = 1784 + INTEGER(IntKi), PARAMETER :: M1N3RAye = 1785 + INTEGER(IntKi), PARAMETER :: M1N4RAye = 1786 + INTEGER(IntKi), PARAMETER :: M1N5RAye = 1787 + INTEGER(IntKi), PARAMETER :: M1N6RAye = 1788 + INTEGER(IntKi), PARAMETER :: M1N7RAye = 1789 + INTEGER(IntKi), PARAMETER :: M1N8RAye = 1790 + INTEGER(IntKi), PARAMETER :: M1N9RAye = 1791 + INTEGER(IntKi), PARAMETER :: M2N1RAye = 1792 + INTEGER(IntKi), PARAMETER :: M2N2RAye = 1793 + INTEGER(IntKi), PARAMETER :: M2N3RAye = 1794 + INTEGER(IntKi), PARAMETER :: M2N4RAye = 1795 + INTEGER(IntKi), PARAMETER :: M2N5RAye = 1796 + INTEGER(IntKi), PARAMETER :: M2N6RAye = 1797 + INTEGER(IntKi), PARAMETER :: M2N7RAye = 1798 + INTEGER(IntKi), PARAMETER :: M2N8RAye = 1799 + INTEGER(IntKi), PARAMETER :: M2N9RAye = 1800 + INTEGER(IntKi), PARAMETER :: M3N1RAye = 1801 + INTEGER(IntKi), PARAMETER :: M3N2RAye = 1802 + INTEGER(IntKi), PARAMETER :: M3N3RAye = 1803 + INTEGER(IntKi), PARAMETER :: M3N4RAye = 1804 + INTEGER(IntKi), PARAMETER :: M3N5RAye = 1805 + INTEGER(IntKi), PARAMETER :: M3N6RAye = 1806 + INTEGER(IntKi), PARAMETER :: M3N7RAye = 1807 + INTEGER(IntKi), PARAMETER :: M3N8RAye = 1808 + INTEGER(IntKi), PARAMETER :: M3N9RAye = 1809 + INTEGER(IntKi), PARAMETER :: M4N1RAye = 1810 + INTEGER(IntKi), PARAMETER :: M4N2RAye = 1811 + INTEGER(IntKi), PARAMETER :: M4N3RAye = 1812 + INTEGER(IntKi), PARAMETER :: M4N4RAye = 1813 + INTEGER(IntKi), PARAMETER :: M4N5RAye = 1814 + INTEGER(IntKi), PARAMETER :: M4N6RAye = 1815 + INTEGER(IntKi), PARAMETER :: M4N7RAye = 1816 + INTEGER(IntKi), PARAMETER :: M4N8RAye = 1817 + INTEGER(IntKi), PARAMETER :: M4N9RAye = 1818 + INTEGER(IntKi), PARAMETER :: M5N1RAye = 1819 + INTEGER(IntKi), PARAMETER :: M5N2RAye = 1820 + INTEGER(IntKi), PARAMETER :: M5N3RAye = 1821 + INTEGER(IntKi), PARAMETER :: M5N4RAye = 1822 + INTEGER(IntKi), PARAMETER :: M5N5RAye = 1823 + INTEGER(IntKi), PARAMETER :: M5N6RAye = 1824 + INTEGER(IntKi), PARAMETER :: M5N7RAye = 1825 + INTEGER(IntKi), PARAMETER :: M5N8RAye = 1826 + INTEGER(IntKi), PARAMETER :: M5N9RAye = 1827 + INTEGER(IntKi), PARAMETER :: M6N1RAye = 1828 + INTEGER(IntKi), PARAMETER :: M6N2RAye = 1829 + INTEGER(IntKi), PARAMETER :: M6N3RAye = 1830 + INTEGER(IntKi), PARAMETER :: M6N4RAye = 1831 + INTEGER(IntKi), PARAMETER :: M6N5RAye = 1832 + INTEGER(IntKi), PARAMETER :: M6N6RAye = 1833 + INTEGER(IntKi), PARAMETER :: M6N7RAye = 1834 + INTEGER(IntKi), PARAMETER :: M6N8RAye = 1835 + INTEGER(IntKi), PARAMETER :: M6N9RAye = 1836 + INTEGER(IntKi), PARAMETER :: M7N1RAye = 1837 + INTEGER(IntKi), PARAMETER :: M7N2RAye = 1838 + INTEGER(IntKi), PARAMETER :: M7N3RAye = 1839 + INTEGER(IntKi), PARAMETER :: M7N4RAye = 1840 + INTEGER(IntKi), PARAMETER :: M7N5RAye = 1841 + INTEGER(IntKi), PARAMETER :: M7N6RAye = 1842 + INTEGER(IntKi), PARAMETER :: M7N7RAye = 1843 + INTEGER(IntKi), PARAMETER :: M7N8RAye = 1844 + INTEGER(IntKi), PARAMETER :: M7N9RAye = 1845 + INTEGER(IntKi), PARAMETER :: M8N1RAye = 1846 + INTEGER(IntKi), PARAMETER :: M8N2RAye = 1847 + INTEGER(IntKi), PARAMETER :: M8N3RAye = 1848 + INTEGER(IntKi), PARAMETER :: M8N4RAye = 1849 + INTEGER(IntKi), PARAMETER :: M8N5RAye = 1850 + INTEGER(IntKi), PARAMETER :: M8N6RAye = 1851 + INTEGER(IntKi), PARAMETER :: M8N7RAye = 1852 + INTEGER(IntKi), PARAMETER :: M8N8RAye = 1853 + INTEGER(IntKi), PARAMETER :: M8N9RAye = 1854 + INTEGER(IntKi), PARAMETER :: M9N1RAye = 1855 + INTEGER(IntKi), PARAMETER :: M9N2RAye = 1856 + INTEGER(IntKi), PARAMETER :: M9N3RAye = 1857 + INTEGER(IntKi), PARAMETER :: M9N4RAye = 1858 + INTEGER(IntKi), PARAMETER :: M9N5RAye = 1859 + INTEGER(IntKi), PARAMETER :: M9N6RAye = 1860 + INTEGER(IntKi), PARAMETER :: M9N7RAye = 1861 + INTEGER(IntKi), PARAMETER :: M9N8RAye = 1862 + INTEGER(IntKi), PARAMETER :: M9N9RAye = 1863 + INTEGER(IntKi), PARAMETER :: M1N1RAze = 1864 + INTEGER(IntKi), PARAMETER :: M1N2RAze = 1865 + INTEGER(IntKi), PARAMETER :: M1N3RAze = 1866 + INTEGER(IntKi), PARAMETER :: M1N4RAze = 1867 + INTEGER(IntKi), PARAMETER :: M1N5RAze = 1868 + INTEGER(IntKi), PARAMETER :: M1N6RAze = 1869 + INTEGER(IntKi), PARAMETER :: M1N7RAze = 1870 + INTEGER(IntKi), PARAMETER :: M1N8RAze = 1871 + INTEGER(IntKi), PARAMETER :: M1N9RAze = 1872 + INTEGER(IntKi), PARAMETER :: M2N1RAze = 1873 + INTEGER(IntKi), PARAMETER :: M2N2RAze = 1874 + INTEGER(IntKi), PARAMETER :: M2N3RAze = 1875 + INTEGER(IntKi), PARAMETER :: M2N4RAze = 1876 + INTEGER(IntKi), PARAMETER :: M2N5RAze = 1877 + INTEGER(IntKi), PARAMETER :: M2N6RAze = 1878 + INTEGER(IntKi), PARAMETER :: M2N7RAze = 1879 + INTEGER(IntKi), PARAMETER :: M2N8RAze = 1880 + INTEGER(IntKi), PARAMETER :: M2N9RAze = 1881 + INTEGER(IntKi), PARAMETER :: M3N1RAze = 1882 + INTEGER(IntKi), PARAMETER :: M3N2RAze = 1883 + INTEGER(IntKi), PARAMETER :: M3N3RAze = 1884 + INTEGER(IntKi), PARAMETER :: M3N4RAze = 1885 + INTEGER(IntKi), PARAMETER :: M3N5RAze = 1886 + INTEGER(IntKi), PARAMETER :: M3N6RAze = 1887 + INTEGER(IntKi), PARAMETER :: M3N7RAze = 1888 + INTEGER(IntKi), PARAMETER :: M3N8RAze = 1889 + INTEGER(IntKi), PARAMETER :: M3N9RAze = 1890 + INTEGER(IntKi), PARAMETER :: M4N1RAze = 1891 + INTEGER(IntKi), PARAMETER :: M4N2RAze = 1892 + INTEGER(IntKi), PARAMETER :: M4N3RAze = 1893 + INTEGER(IntKi), PARAMETER :: M4N4RAze = 1894 + INTEGER(IntKi), PARAMETER :: M4N5RAze = 1895 + INTEGER(IntKi), PARAMETER :: M4N6RAze = 1896 + INTEGER(IntKi), PARAMETER :: M4N7RAze = 1897 + INTEGER(IntKi), PARAMETER :: M4N8RAze = 1898 + INTEGER(IntKi), PARAMETER :: M4N9RAze = 1899 + INTEGER(IntKi), PARAMETER :: M5N1RAze = 1900 + INTEGER(IntKi), PARAMETER :: M5N2RAze = 1901 + INTEGER(IntKi), PARAMETER :: M5N3RAze = 1902 + INTEGER(IntKi), PARAMETER :: M5N4RAze = 1903 + INTEGER(IntKi), PARAMETER :: M5N5RAze = 1904 + INTEGER(IntKi), PARAMETER :: M5N6RAze = 1905 + INTEGER(IntKi), PARAMETER :: M5N7RAze = 1906 + INTEGER(IntKi), PARAMETER :: M5N8RAze = 1907 + INTEGER(IntKi), PARAMETER :: M5N9RAze = 1908 + INTEGER(IntKi), PARAMETER :: M6N1RAze = 1909 + INTEGER(IntKi), PARAMETER :: M6N2RAze = 1910 + INTEGER(IntKi), PARAMETER :: M6N3RAze = 1911 + INTEGER(IntKi), PARAMETER :: M6N4RAze = 1912 + INTEGER(IntKi), PARAMETER :: M6N5RAze = 1913 + INTEGER(IntKi), PARAMETER :: M6N6RAze = 1914 + INTEGER(IntKi), PARAMETER :: M6N7RAze = 1915 + INTEGER(IntKi), PARAMETER :: M6N8RAze = 1916 + INTEGER(IntKi), PARAMETER :: M6N9RAze = 1917 + INTEGER(IntKi), PARAMETER :: M7N1RAze = 1918 + INTEGER(IntKi), PARAMETER :: M7N2RAze = 1919 + INTEGER(IntKi), PARAMETER :: M7N3RAze = 1920 + INTEGER(IntKi), PARAMETER :: M7N4RAze = 1921 + INTEGER(IntKi), PARAMETER :: M7N5RAze = 1922 + INTEGER(IntKi), PARAMETER :: M7N6RAze = 1923 + INTEGER(IntKi), PARAMETER :: M7N7RAze = 1924 + INTEGER(IntKi), PARAMETER :: M7N8RAze = 1925 + INTEGER(IntKi), PARAMETER :: M7N9RAze = 1926 + INTEGER(IntKi), PARAMETER :: M8N1RAze = 1927 + INTEGER(IntKi), PARAMETER :: M8N2RAze = 1928 + INTEGER(IntKi), PARAMETER :: M8N3RAze = 1929 + INTEGER(IntKi), PARAMETER :: M8N4RAze = 1930 + INTEGER(IntKi), PARAMETER :: M8N5RAze = 1931 + INTEGER(IntKi), PARAMETER :: M8N6RAze = 1932 + INTEGER(IntKi), PARAMETER :: M8N7RAze = 1933 + INTEGER(IntKi), PARAMETER :: M8N8RAze = 1934 + INTEGER(IntKi), PARAMETER :: M8N9RAze = 1935 + INTEGER(IntKi), PARAMETER :: M9N1RAze = 1936 + INTEGER(IntKi), PARAMETER :: M9N2RAze = 1937 + INTEGER(IntKi), PARAMETER :: M9N3RAze = 1938 + INTEGER(IntKi), PARAMETER :: M9N4RAze = 1939 + INTEGER(IntKi), PARAMETER :: M9N5RAze = 1940 + INTEGER(IntKi), PARAMETER :: M9N6RAze = 1941 + INTEGER(IntKi), PARAMETER :: M9N7RAze = 1942 + INTEGER(IntKi), PARAMETER :: M9N8RAze = 1943 + INTEGER(IntKi), PARAMETER :: M9N9RAze = 1944 + + + ! Reactions: + + INTEGER(IntKi), PARAMETER :: ReactFXss = 1945 + INTEGER(IntKi), PARAMETER :: ReactFYss = 1946 + INTEGER(IntKi), PARAMETER :: ReactFZss = 1947 + INTEGER(IntKi), PARAMETER :: ReactMXss = 1948 + INTEGER(IntKi), PARAMETER :: ReactMYss = 1949 + INTEGER(IntKi), PARAMETER :: ReactMZss = 1950 + INTEGER(IntKi), PARAMETER :: IntfFXss = 1951 + INTEGER(IntKi), PARAMETER :: IntfFYss = 1952 + INTEGER(IntKi), PARAMETER :: IntfFZss = 1953 + INTEGER(IntKi), PARAMETER :: IntfMXss = 1954 + INTEGER(IntKi), PARAMETER :: IntfMYss = 1955 + INTEGER(IntKi), PARAMETER :: IntfMZss = 1956 + + + ! Interface Deflections: + + INTEGER(IntKi), PARAMETER :: IntfTDXss = 1957 + INTEGER(IntKi), PARAMETER :: IntfTDYss = 1958 + INTEGER(IntKi), PARAMETER :: IntfTDZss = 1959 + INTEGER(IntKi), PARAMETER :: IntfRDXss = 1960 + INTEGER(IntKi), PARAMETER :: IntfRDYss = 1961 + INTEGER(IntKi), PARAMETER :: IntfRDZss = 1962 + + + ! Interface Accelerations: + + INTEGER(IntKi), PARAMETER :: IntfTAXss = 1963 + INTEGER(IntKi), PARAMETER :: IntfTAYss = 1964 + INTEGER(IntKi), PARAMETER :: IntfTAZss = 1965 + INTEGER(IntKi), PARAMETER :: IntfRAXss = 1966 + INTEGER(IntKi), PARAMETER :: IntfRAYss = 1967 + INTEGER(IntKi), PARAMETER :: IntfRAZss = 1968 + + + ! Modal Parameters: + + INTEGER(IntKi), PARAMETER :: SSqm01 = 1969 + INTEGER(IntKi), PARAMETER :: SSqm02 = 1970 + INTEGER(IntKi), PARAMETER :: SSqm03 = 1971 + INTEGER(IntKi), PARAMETER :: SSqm04 = 1972 + INTEGER(IntKi), PARAMETER :: SSqm05 = 1973 + INTEGER(IntKi), PARAMETER :: SSqm06 = 1974 + INTEGER(IntKi), PARAMETER :: SSqm07 = 1975 + INTEGER(IntKi), PARAMETER :: SSqm08 = 1976 + INTEGER(IntKi), PARAMETER :: SSqm09 = 1977 + INTEGER(IntKi), PARAMETER :: SSqm10 = 1978 + INTEGER(IntKi), PARAMETER :: SSqm11 = 1979 + INTEGER(IntKi), PARAMETER :: SSqm12 = 1980 + INTEGER(IntKi), PARAMETER :: SSqm13 = 1981 + INTEGER(IntKi), PARAMETER :: SSqm14 = 1982 + INTEGER(IntKi), PARAMETER :: SSqm15 = 1983 + INTEGER(IntKi), PARAMETER :: SSqm16 = 1984 + INTEGER(IntKi), PARAMETER :: SSqm17 = 1985 + INTEGER(IntKi), PARAMETER :: SSqm18 = 1986 + INTEGER(IntKi), PARAMETER :: SSqm19 = 1987 + INTEGER(IntKi), PARAMETER :: SSqm20 = 1988 + INTEGER(IntKi), PARAMETER :: SSqm21 = 1989 + INTEGER(IntKi), PARAMETER :: SSqm22 = 1990 + INTEGER(IntKi), PARAMETER :: SSqm23 = 1991 + INTEGER(IntKi), PARAMETER :: SSqm24 = 1992 + INTEGER(IntKi), PARAMETER :: SSqm25 = 1993 + INTEGER(IntKi), PARAMETER :: SSqm26 = 1994 + INTEGER(IntKi), PARAMETER :: SSqm27 = 1995 + INTEGER(IntKi), PARAMETER :: SSqm28 = 1996 + INTEGER(IntKi), PARAMETER :: SSqm29 = 1997 + INTEGER(IntKi), PARAMETER :: SSqm30 = 1998 + INTEGER(IntKi), PARAMETER :: SSqm31 = 1999 + INTEGER(IntKi), PARAMETER :: SSqm32 = 2000 + INTEGER(IntKi), PARAMETER :: SSqm33 = 2001 + INTEGER(IntKi), PARAMETER :: SSqm34 = 2002 + INTEGER(IntKi), PARAMETER :: SSqm35 = 2003 + INTEGER(IntKi), PARAMETER :: SSqm36 = 2004 + INTEGER(IntKi), PARAMETER :: SSqm37 = 2005 + INTEGER(IntKi), PARAMETER :: SSqm38 = 2006 + INTEGER(IntKi), PARAMETER :: SSqm39 = 2007 + INTEGER(IntKi), PARAMETER :: SSqm40 = 2008 + INTEGER(IntKi), PARAMETER :: SSqm41 = 2009 + INTEGER(IntKi), PARAMETER :: SSqm42 = 2010 + INTEGER(IntKi), PARAMETER :: SSqm43 = 2011 + INTEGER(IntKi), PARAMETER :: SSqm44 = 2012 + INTEGER(IntKi), PARAMETER :: SSqm45 = 2013 + INTEGER(IntKi), PARAMETER :: SSqm46 = 2014 + INTEGER(IntKi), PARAMETER :: SSqm47 = 2015 + INTEGER(IntKi), PARAMETER :: SSqm48 = 2016 + INTEGER(IntKi), PARAMETER :: SSqm49 = 2017 + INTEGER(IntKi), PARAMETER :: SSqm50 = 2018 + INTEGER(IntKi), PARAMETER :: SSqm51 = 2019 + INTEGER(IntKi), PARAMETER :: SSqm52 = 2020 + INTEGER(IntKi), PARAMETER :: SSqm53 = 2021 + INTEGER(IntKi), PARAMETER :: SSqm54 = 2022 + INTEGER(IntKi), PARAMETER :: SSqm55 = 2023 + INTEGER(IntKi), PARAMETER :: SSqm56 = 2024 + INTEGER(IntKi), PARAMETER :: SSqm57 = 2025 + INTEGER(IntKi), PARAMETER :: SSqm58 = 2026 + INTEGER(IntKi), PARAMETER :: SSqm59 = 2027 + INTEGER(IntKi), PARAMETER :: SSqm60 = 2028 + INTEGER(IntKi), PARAMETER :: SSqm61 = 2029 + INTEGER(IntKi), PARAMETER :: SSqm62 = 2030 + INTEGER(IntKi), PARAMETER :: SSqm63 = 2031 + INTEGER(IntKi), PARAMETER :: SSqm64 = 2032 + INTEGER(IntKi), PARAMETER :: SSqm65 = 2033 + INTEGER(IntKi), PARAMETER :: SSqm66 = 2034 + INTEGER(IntKi), PARAMETER :: SSqm67 = 2035 + INTEGER(IntKi), PARAMETER :: SSqm68 = 2036 + INTEGER(IntKi), PARAMETER :: SSqm69 = 2037 + INTEGER(IntKi), PARAMETER :: SSqm70 = 2038 + INTEGER(IntKi), PARAMETER :: SSqm71 = 2039 + INTEGER(IntKi), PARAMETER :: SSqm72 = 2040 + INTEGER(IntKi), PARAMETER :: SSqm73 = 2041 + INTEGER(IntKi), PARAMETER :: SSqm74 = 2042 + INTEGER(IntKi), PARAMETER :: SSqm75 = 2043 + INTEGER(IntKi), PARAMETER :: SSqm76 = 2044 + INTEGER(IntKi), PARAMETER :: SSqm77 = 2045 + INTEGER(IntKi), PARAMETER :: SSqm78 = 2046 + INTEGER(IntKi), PARAMETER :: SSqm79 = 2047 + INTEGER(IntKi), PARAMETER :: SSqm80 = 2048 + INTEGER(IntKi), PARAMETER :: SSqm81 = 2049 + INTEGER(IntKi), PARAMETER :: SSqm82 = 2050 + INTEGER(IntKi), PARAMETER :: SSqm83 = 2051 + INTEGER(IntKi), PARAMETER :: SSqm84 = 2052 + INTEGER(IntKi), PARAMETER :: SSqm85 = 2053 + INTEGER(IntKi), PARAMETER :: SSqm86 = 2054 + INTEGER(IntKi), PARAMETER :: SSqm87 = 2055 + INTEGER(IntKi), PARAMETER :: SSqm88 = 2056 + INTEGER(IntKi), PARAMETER :: SSqm89 = 2057 + INTEGER(IntKi), PARAMETER :: SSqm90 = 2058 + INTEGER(IntKi), PARAMETER :: SSqm91 = 2059 + INTEGER(IntKi), PARAMETER :: SSqm92 = 2060 + INTEGER(IntKi), PARAMETER :: SSqm93 = 2061 + INTEGER(IntKi), PARAMETER :: SSqm94 = 2062 + INTEGER(IntKi), PARAMETER :: SSqm95 = 2063 + INTEGER(IntKi), PARAMETER :: SSqm96 = 2064 + INTEGER(IntKi), PARAMETER :: SSqm97 = 2065 + INTEGER(IntKi), PARAMETER :: SSqm98 = 2066 + INTEGER(IntKi), PARAMETER :: SSqm99 = 2067 + INTEGER(IntKi), PARAMETER :: SSqmd01 = 2068 + INTEGER(IntKi), PARAMETER :: SSqmd02 = 2069 + INTEGER(IntKi), PARAMETER :: SSqmd03 = 2070 + INTEGER(IntKi), PARAMETER :: SSqmd04 = 2071 + INTEGER(IntKi), PARAMETER :: SSqmd05 = 2072 + INTEGER(IntKi), PARAMETER :: SSqmd06 = 2073 + INTEGER(IntKi), PARAMETER :: SSqmd07 = 2074 + INTEGER(IntKi), PARAMETER :: SSqmd08 = 2075 + INTEGER(IntKi), PARAMETER :: SSqmd09 = 2076 + INTEGER(IntKi), PARAMETER :: SSqmd10 = 2077 + INTEGER(IntKi), PARAMETER :: SSqmd11 = 2078 + INTEGER(IntKi), PARAMETER :: SSqmd12 = 2079 + INTEGER(IntKi), PARAMETER :: SSqmd13 = 2080 + INTEGER(IntKi), PARAMETER :: SSqmd14 = 2081 + INTEGER(IntKi), PARAMETER :: SSqmd15 = 2082 + INTEGER(IntKi), PARAMETER :: SSqmd16 = 2083 + INTEGER(IntKi), PARAMETER :: SSqmd17 = 2084 + INTEGER(IntKi), PARAMETER :: SSqmd18 = 2085 + INTEGER(IntKi), PARAMETER :: SSqmd19 = 2086 + INTEGER(IntKi), PARAMETER :: SSqmd20 = 2087 + INTEGER(IntKi), PARAMETER :: SSqmd21 = 2088 + INTEGER(IntKi), PARAMETER :: SSqmd22 = 2089 + INTEGER(IntKi), PARAMETER :: SSqmd23 = 2090 + INTEGER(IntKi), PARAMETER :: SSqmd24 = 2091 + INTEGER(IntKi), PARAMETER :: SSqmd25 = 2092 + INTEGER(IntKi), PARAMETER :: SSqmd26 = 2093 + INTEGER(IntKi), PARAMETER :: SSqmd27 = 2094 + INTEGER(IntKi), PARAMETER :: SSqmd28 = 2095 + INTEGER(IntKi), PARAMETER :: SSqmd29 = 2096 + INTEGER(IntKi), PARAMETER :: SSqmd30 = 2097 + INTEGER(IntKi), PARAMETER :: SSqmd31 = 2098 + INTEGER(IntKi), PARAMETER :: SSqmd32 = 2099 + INTEGER(IntKi), PARAMETER :: SSqmd33 = 2100 + INTEGER(IntKi), PARAMETER :: SSqmd34 = 2101 + INTEGER(IntKi), PARAMETER :: SSqmd35 = 2102 + INTEGER(IntKi), PARAMETER :: SSqmd36 = 2103 + INTEGER(IntKi), PARAMETER :: SSqmd37 = 2104 + INTEGER(IntKi), PARAMETER :: SSqmd38 = 2105 + INTEGER(IntKi), PARAMETER :: SSqmd39 = 2106 + INTEGER(IntKi), PARAMETER :: SSqmd40 = 2107 + INTEGER(IntKi), PARAMETER :: SSqmd41 = 2108 + INTEGER(IntKi), PARAMETER :: SSqmd42 = 2109 + INTEGER(IntKi), PARAMETER :: SSqmd43 = 2110 + INTEGER(IntKi), PARAMETER :: SSqmd44 = 2111 + INTEGER(IntKi), PARAMETER :: SSqmd45 = 2112 + INTEGER(IntKi), PARAMETER :: SSqmd46 = 2113 + INTEGER(IntKi), PARAMETER :: SSqmd47 = 2114 + INTEGER(IntKi), PARAMETER :: SSqmd48 = 2115 + INTEGER(IntKi), PARAMETER :: SSqmd49 = 2116 + INTEGER(IntKi), PARAMETER :: SSqmd50 = 2117 + INTEGER(IntKi), PARAMETER :: SSqmd51 = 2118 + INTEGER(IntKi), PARAMETER :: SSqmd52 = 2119 + INTEGER(IntKi), PARAMETER :: SSqmd53 = 2120 + INTEGER(IntKi), PARAMETER :: SSqmd54 = 2121 + INTEGER(IntKi), PARAMETER :: SSqmd55 = 2122 + INTEGER(IntKi), PARAMETER :: SSqmd56 = 2123 + INTEGER(IntKi), PARAMETER :: SSqmd57 = 2124 + INTEGER(IntKi), PARAMETER :: SSqmd58 = 2125 + INTEGER(IntKi), PARAMETER :: SSqmd59 = 2126 + INTEGER(IntKi), PARAMETER :: SSqmd60 = 2127 + INTEGER(IntKi), PARAMETER :: SSqmd61 = 2128 + INTEGER(IntKi), PARAMETER :: SSqmd62 = 2129 + INTEGER(IntKi), PARAMETER :: SSqmd63 = 2130 + INTEGER(IntKi), PARAMETER :: SSqmd64 = 2131 + INTEGER(IntKi), PARAMETER :: SSqmd65 = 2132 + INTEGER(IntKi), PARAMETER :: SSqmd66 = 2133 + INTEGER(IntKi), PARAMETER :: SSqmd67 = 2134 + INTEGER(IntKi), PARAMETER :: SSqmd68 = 2135 + INTEGER(IntKi), PARAMETER :: SSqmd69 = 2136 + INTEGER(IntKi), PARAMETER :: SSqmd70 = 2137 + INTEGER(IntKi), PARAMETER :: SSqmd71 = 2138 + INTEGER(IntKi), PARAMETER :: SSqmd72 = 2139 + INTEGER(IntKi), PARAMETER :: SSqmd73 = 2140 + INTEGER(IntKi), PARAMETER :: SSqmd74 = 2141 + INTEGER(IntKi), PARAMETER :: SSqmd75 = 2142 + INTEGER(IntKi), PARAMETER :: SSqmd76 = 2143 + INTEGER(IntKi), PARAMETER :: SSqmd77 = 2144 + INTEGER(IntKi), PARAMETER :: SSqmd78 = 2145 + INTEGER(IntKi), PARAMETER :: SSqmd79 = 2146 + INTEGER(IntKi), PARAMETER :: SSqmd80 = 2147 + INTEGER(IntKi), PARAMETER :: SSqmd81 = 2148 + INTEGER(IntKi), PARAMETER :: SSqmd82 = 2149 + INTEGER(IntKi), PARAMETER :: SSqmd83 = 2150 + INTEGER(IntKi), PARAMETER :: SSqmd84 = 2151 + INTEGER(IntKi), PARAMETER :: SSqmd85 = 2152 + INTEGER(IntKi), PARAMETER :: SSqmd86 = 2153 + INTEGER(IntKi), PARAMETER :: SSqmd87 = 2154 + INTEGER(IntKi), PARAMETER :: SSqmd88 = 2155 + INTEGER(IntKi), PARAMETER :: SSqmd89 = 2156 + INTEGER(IntKi), PARAMETER :: SSqmd90 = 2157 + INTEGER(IntKi), PARAMETER :: SSqmd91 = 2158 + INTEGER(IntKi), PARAMETER :: SSqmd92 = 2159 + INTEGER(IntKi), PARAMETER :: SSqmd93 = 2160 + INTEGER(IntKi), PARAMETER :: SSqmd94 = 2161 + INTEGER(IntKi), PARAMETER :: SSqmd95 = 2162 + INTEGER(IntKi), PARAMETER :: SSqmd96 = 2163 + INTEGER(IntKi), PARAMETER :: SSqmd97 = 2164 + INTEGER(IntKi), PARAMETER :: SSqmd98 = 2165 + INTEGER(IntKi), PARAMETER :: SSqmd99 = 2166 + INTEGER(IntKi), PARAMETER :: SSqmdd01 = 2167 + INTEGER(IntKi), PARAMETER :: SSqmdd02 = 2168 + INTEGER(IntKi), PARAMETER :: SSqmdd03 = 2169 + INTEGER(IntKi), PARAMETER :: SSqmdd04 = 2170 + INTEGER(IntKi), PARAMETER :: SSqmdd05 = 2171 + INTEGER(IntKi), PARAMETER :: SSqmdd06 = 2172 + INTEGER(IntKi), PARAMETER :: SSqmdd07 = 2173 + INTEGER(IntKi), PARAMETER :: SSqmdd08 = 2174 + INTEGER(IntKi), PARAMETER :: SSqmdd09 = 2175 + INTEGER(IntKi), PARAMETER :: SSqmdd10 = 2176 + INTEGER(IntKi), PARAMETER :: SSqmdd11 = 2177 + INTEGER(IntKi), PARAMETER :: SSqmdd12 = 2178 + INTEGER(IntKi), PARAMETER :: SSqmdd13 = 2179 + INTEGER(IntKi), PARAMETER :: SSqmdd14 = 2180 + INTEGER(IntKi), PARAMETER :: SSqmdd15 = 2181 + INTEGER(IntKi), PARAMETER :: SSqmdd16 = 2182 + INTEGER(IntKi), PARAMETER :: SSqmdd17 = 2183 + INTEGER(IntKi), PARAMETER :: SSqmdd18 = 2184 + INTEGER(IntKi), PARAMETER :: SSqmdd19 = 2185 + INTEGER(IntKi), PARAMETER :: SSqmdd20 = 2186 + INTEGER(IntKi), PARAMETER :: SSqmdd21 = 2187 + INTEGER(IntKi), PARAMETER :: SSqmdd22 = 2188 + INTEGER(IntKi), PARAMETER :: SSqmdd23 = 2189 + INTEGER(IntKi), PARAMETER :: SSqmdd24 = 2190 + INTEGER(IntKi), PARAMETER :: SSqmdd25 = 2191 + INTEGER(IntKi), PARAMETER :: SSqmdd26 = 2192 + INTEGER(IntKi), PARAMETER :: SSqmdd27 = 2193 + INTEGER(IntKi), PARAMETER :: SSqmdd28 = 2194 + INTEGER(IntKi), PARAMETER :: SSqmdd29 = 2195 + INTEGER(IntKi), PARAMETER :: SSqmdd30 = 2196 + INTEGER(IntKi), PARAMETER :: SSqmdd31 = 2197 + INTEGER(IntKi), PARAMETER :: SSqmdd32 = 2198 + INTEGER(IntKi), PARAMETER :: SSqmdd33 = 2199 + INTEGER(IntKi), PARAMETER :: SSqmdd34 = 2200 + INTEGER(IntKi), PARAMETER :: SSqmdd35 = 2201 + INTEGER(IntKi), PARAMETER :: SSqmdd36 = 2202 + INTEGER(IntKi), PARAMETER :: SSqmdd37 = 2203 + INTEGER(IntKi), PARAMETER :: SSqmdd38 = 2204 + INTEGER(IntKi), PARAMETER :: SSqmdd39 = 2205 + INTEGER(IntKi), PARAMETER :: SSqmdd40 = 2206 + INTEGER(IntKi), PARAMETER :: SSqmdd41 = 2207 + INTEGER(IntKi), PARAMETER :: SSqmdd42 = 2208 + INTEGER(IntKi), PARAMETER :: SSqmdd43 = 2209 + INTEGER(IntKi), PARAMETER :: SSqmdd44 = 2210 + INTEGER(IntKi), PARAMETER :: SSqmdd45 = 2211 + INTEGER(IntKi), PARAMETER :: SSqmdd46 = 2212 + INTEGER(IntKi), PARAMETER :: SSqmdd47 = 2213 + INTEGER(IntKi), PARAMETER :: SSqmdd48 = 2214 + INTEGER(IntKi), PARAMETER :: SSqmdd49 = 2215 + INTEGER(IntKi), PARAMETER :: SSqmdd50 = 2216 + INTEGER(IntKi), PARAMETER :: SSqmdd51 = 2217 + INTEGER(IntKi), PARAMETER :: SSqmdd52 = 2218 + INTEGER(IntKi), PARAMETER :: SSqmdd53 = 2219 + INTEGER(IntKi), PARAMETER :: SSqmdd54 = 2220 + INTEGER(IntKi), PARAMETER :: SSqmdd55 = 2221 + INTEGER(IntKi), PARAMETER :: SSqmdd56 = 2222 + INTEGER(IntKi), PARAMETER :: SSqmdd57 = 2223 + INTEGER(IntKi), PARAMETER :: SSqmdd58 = 2224 + INTEGER(IntKi), PARAMETER :: SSqmdd59 = 2225 + INTEGER(IntKi), PARAMETER :: SSqmdd60 = 2226 + INTEGER(IntKi), PARAMETER :: SSqmdd61 = 2227 + INTEGER(IntKi), PARAMETER :: SSqmdd62 = 2228 + INTEGER(IntKi), PARAMETER :: SSqmdd63 = 2229 + INTEGER(IntKi), PARAMETER :: SSqmdd64 = 2230 + INTEGER(IntKi), PARAMETER :: SSqmdd65 = 2231 + INTEGER(IntKi), PARAMETER :: SSqmdd66 = 2232 + INTEGER(IntKi), PARAMETER :: SSqmdd67 = 2233 + INTEGER(IntKi), PARAMETER :: SSqmdd68 = 2234 + INTEGER(IntKi), PARAMETER :: SSqmdd69 = 2235 + INTEGER(IntKi), PARAMETER :: SSqmdd70 = 2236 + INTEGER(IntKi), PARAMETER :: SSqmdd71 = 2237 + INTEGER(IntKi), PARAMETER :: SSqmdd72 = 2238 + INTEGER(IntKi), PARAMETER :: SSqmdd73 = 2239 + INTEGER(IntKi), PARAMETER :: SSqmdd74 = 2240 + INTEGER(IntKi), PARAMETER :: SSqmdd75 = 2241 + INTEGER(IntKi), PARAMETER :: SSqmdd76 = 2242 + INTEGER(IntKi), PARAMETER :: SSqmdd77 = 2243 + INTEGER(IntKi), PARAMETER :: SSqmdd78 = 2244 + INTEGER(IntKi), PARAMETER :: SSqmdd79 = 2245 + INTEGER(IntKi), PARAMETER :: SSqmdd80 = 2246 + INTEGER(IntKi), PARAMETER :: SSqmdd81 = 2247 + INTEGER(IntKi), PARAMETER :: SSqmdd82 = 2248 + INTEGER(IntKi), PARAMETER :: SSqmdd83 = 2249 + INTEGER(IntKi), PARAMETER :: SSqmdd84 = 2250 + INTEGER(IntKi), PARAMETER :: SSqmdd85 = 2251 + INTEGER(IntKi), PARAMETER :: SSqmdd86 = 2252 + INTEGER(IntKi), PARAMETER :: SSqmdd87 = 2253 + INTEGER(IntKi), PARAMETER :: SSqmdd88 = 2254 + INTEGER(IntKi), PARAMETER :: SSqmdd89 = 2255 + INTEGER(IntKi), PARAMETER :: SSqmdd90 = 2256 + INTEGER(IntKi), PARAMETER :: SSqmdd91 = 2257 + INTEGER(IntKi), PARAMETER :: SSqmdd92 = 2258 + INTEGER(IntKi), PARAMETER :: SSqmdd93 = 2259 + INTEGER(IntKi), PARAMETER :: SSqmdd94 = 2260 + INTEGER(IntKi), PARAMETER :: SSqmdd95 = 2261 + INTEGER(IntKi), PARAMETER :: SSqmdd96 = 2262 + INTEGER(IntKi), PARAMETER :: SSqmdd97 = 2263 + INTEGER(IntKi), PARAMETER :: SSqmdd98 = 2264 + INTEGER(IntKi), PARAMETER :: SSqmdd99 = 2265 + + + ! The maximum number of output channels which can be output by the code. + !INTEGER(IntKi), PARAMETER :: MaxOutPts = 2265 + +!End of code generated by Matlab script + + INTEGER, PARAMETER :: MNfmKe(6,9,9) = reshape((/ M1N1FKxe,M1N1FKye,M1N1FKze,M1N1MKxe,M1N1MKye,M1N1MKze, & + M1N2FKxe,M1N2FKye,M1N2FKze,M1N2MKxe,M1N2MKye,M1N2MKze, & + M1N3FKxe,M1N3FKye,M1N3FKze,M1N3MKxe,M1N3MKye,M1N3MKze, & + M1N4FKxe,M1N4FKye,M1N4FKze,M1N4MKxe,M1N4MKye,M1N4MKze, & + M1N5FKxe,M1N5FKye,M1N5FKze,M1N5MKxe,M1N5MKye,M1N5MKze, & + M1N6FKxe,M1N6FKye,M1N6FKze,M1N6MKxe,M1N6MKye,M1N6MKze, & + M1N7FKxe,M1N7FKye,M1N7FKze,M1N7MKxe,M1N7MKye,M1N7MKze, & + M1N8FKxe,M1N8FKye,M1N8FKze,M1N8MKxe,M1N8MKye,M1N8MKze, & + M1N9FKxe,M1N9FKye,M1N9FKze,M1N9MKxe,M1N9MKye,M1N9MKze, & + M2N1FKxe,M2N1FKye,M2N1FKze,M2N1MKxe,M2N1MKye,M2N1MKze, & + M2N2FKxe,M2N2FKye,M2N2FKze,M2N2MKxe,M2N2MKye,M2N2MKze, & + M2N3FKxe,M2N3FKye,M2N3FKze,M2N3MKxe,M2N3MKye,M2N3MKze, & + M2N4FKxe,M2N4FKye,M2N4FKze,M2N4MKxe,M2N4MKye,M2N4MKze, & + M2N5FKxe,M2N5FKye,M2N5FKze,M2N5MKxe,M2N5MKye,M2N5MKze, & + M2N6FKxe,M2N6FKye,M2N6FKze,M2N6MKxe,M2N6MKye,M2N6MKze, & + M2N7FKxe,M2N7FKye,M2N7FKze,M2N7MKxe,M2N7MKye,M2N7MKze, & + M2N8FKxe,M2N8FKye,M2N8FKze,M2N8MKxe,M2N8MKye,M2N8MKze, & + M2N9FKxe,M2N9FKye,M2N9FKze,M2N9MKxe,M2N9MKye,M2N9MKze, & + M3N1FKxe,M3N1FKye,M3N1FKze,M3N1MKxe,M3N1MKye,M3N1MKze, & + M3N2FKxe,M3N2FKye,M3N2FKze,M3N2MKxe,M3N2MKye,M3N2MKze, & + M3N3FKxe,M3N3FKye,M3N3FKze,M3N3MKxe,M3N3MKye,M3N3MKze, & + M3N4FKxe,M3N4FKye,M3N4FKze,M3N4MKxe,M3N4MKye,M3N4MKze, & + M3N5FKxe,M3N5FKye,M3N5FKze,M3N5MKxe,M3N5MKye,M3N5MKze, & + M3N6FKxe,M3N6FKye,M3N6FKze,M3N6MKxe,M3N6MKye,M3N6MKze, & + M3N7FKxe,M3N7FKye,M3N7FKze,M3N7MKxe,M3N7MKye,M3N7MKze, & + M3N8FKxe,M3N8FKye,M3N8FKze,M3N8MKxe,M3N8MKye,M3N8MKze, & + M3N9FKxe,M3N9FKye,M3N9FKze,M3N9MKxe,M3N9MKye,M3N9MKze, & + M4N1FKxe,M4N1FKye,M4N1FKze,M4N1MKxe,M4N1MKye,M4N1MKze, & + M4N2FKxe,M4N2FKye,M4N2FKze,M4N2MKxe,M4N2MKye,M4N2MKze, & + M4N3FKxe,M4N3FKye,M4N3FKze,M4N3MKxe,M4N3MKye,M4N3MKze, & + M4N4FKxe,M4N4FKye,M4N4FKze,M4N4MKxe,M4N4MKye,M4N4MKze, & + M4N5FKxe,M4N5FKye,M4N5FKze,M4N5MKxe,M4N5MKye,M4N5MKze, & + M4N6FKxe,M4N6FKye,M4N6FKze,M4N6MKxe,M4N6MKye,M4N6MKze, & + M4N7FKxe,M4N7FKye,M4N7FKze,M4N7MKxe,M4N7MKye,M4N7MKze, & + M4N8FKxe,M4N8FKye,M4N8FKze,M4N8MKxe,M4N8MKye,M4N8MKze, & + M4N9FKxe,M4N9FKye,M4N9FKze,M4N9MKxe,M4N9MKye,M4N9MKze, & + M5N1FKxe,M5N1FKye,M5N1FKze,M5N1MKxe,M5N1MKye,M5N1MKze, & + M5N2FKxe,M5N2FKye,M5N2FKze,M5N2MKxe,M5N2MKye,M5N2MKze, & + M5N3FKxe,M5N3FKye,M5N3FKze,M5N3MKxe,M5N3MKye,M5N3MKze, & + M5N4FKxe,M5N4FKye,M5N4FKze,M5N4MKxe,M5N4MKye,M5N4MKze, & + M5N5FKxe,M5N5FKye,M5N5FKze,M5N5MKxe,M5N5MKye,M5N5MKze, & + M5N6FKxe,M5N6FKye,M5N6FKze,M5N6MKxe,M5N6MKye,M5N6MKze, & + M5N7FKxe,M5N7FKye,M5N7FKze,M5N7MKxe,M5N7MKye,M5N7MKze, & + M5N8FKxe,M5N8FKye,M5N8FKze,M5N8MKxe,M5N8MKye,M5N8MKze, & + M5N9FKxe,M5N9FKye,M5N9FKze,M5N9MKxe,M5N9MKye,M5N9MKze, & + M6N1FKxe,M6N1FKye,M6N1FKze,M6N1MKxe,M6N1MKye,M6N1MKze, & + M6N2FKxe,M6N2FKye,M6N2FKze,M6N2MKxe,M6N2MKye,M6N2MKze, & + M6N3FKxe,M6N3FKye,M6N3FKze,M6N3MKxe,M6N3MKye,M6N3MKze, & + M6N4FKxe,M6N4FKye,M6N4FKze,M6N4MKxe,M6N4MKye,M6N4MKze, & + M6N5FKxe,M6N5FKye,M6N5FKze,M6N5MKxe,M6N5MKye,M6N5MKze, & + M6N6FKxe,M6N6FKye,M6N6FKze,M6N6MKxe,M6N6MKye,M6N6MKze, & + M6N7FKxe,M6N7FKye,M6N7FKze,M6N7MKxe,M6N7MKye,M6N7MKze, & + M6N8FKxe,M6N8FKye,M6N8FKze,M6N8MKxe,M6N8MKye,M6N8MKze, & + M6N9FKxe,M6N9FKye,M6N9FKze,M6N9MKxe,M6N9MKye,M6N9MKze, & + M7N1FKxe,M7N1FKye,M7N1FKze,M7N1MKxe,M7N1MKye,M7N1MKze, & + M7N2FKxe,M7N2FKye,M7N2FKze,M7N2MKxe,M7N2MKye,M7N2MKze, & + M7N3FKxe,M7N3FKye,M7N3FKze,M7N3MKxe,M7N3MKye,M7N3MKze, & + M7N4FKxe,M7N4FKye,M7N4FKze,M7N4MKxe,M7N4MKye,M7N4MKze, & + M7N5FKxe,M7N5FKye,M7N5FKze,M7N5MKxe,M7N5MKye,M7N5MKze, & + M7N6FKxe,M7N6FKye,M7N6FKze,M7N6MKxe,M7N6MKye,M7N6MKze, & + M7N7FKxe,M7N7FKye,M7N7FKze,M7N7MKxe,M7N7MKye,M7N7MKze, & + M7N8FKxe,M7N8FKye,M7N8FKze,M7N8MKxe,M7N8MKye,M7N8MKze, & + M7N9FKxe,M7N9FKye,M7N9FKze,M7N9MKxe,M7N9MKye,M7N9MKze, & + M8N1FKxe,M8N1FKye,M8N1FKze,M8N1MKxe,M8N1MKye,M8N1MKze, & + M8N2FKxe,M8N2FKye,M8N2FKze,M8N2MKxe,M8N2MKye,M8N2MKze, & + M8N3FKxe,M8N3FKye,M8N3FKze,M8N3MKxe,M8N3MKye,M8N3MKze, & + M8N4FKxe,M8N4FKye,M8N4FKze,M8N4MKxe,M8N4MKye,M8N4MKze, & + M8N5FKxe,M8N5FKye,M8N5FKze,M8N5MKxe,M8N5MKye,M8N5MKze, & + M8N6FKxe,M8N6FKye,M8N6FKze,M8N6MKxe,M8N6MKye,M8N6MKze, & + M8N7FKxe,M8N7FKye,M8N7FKze,M8N7MKxe,M8N7MKye,M8N7MKze, & + M8N8FKxe,M8N8FKye,M8N8FKze,M8N8MKxe,M8N8MKye,M8N8MKze, & + M8N9FKxe,M8N9FKye,M8N9FKze,M8N9MKxe,M8N9MKye,M8N9MKze, & + M9N1FKxe,M9N1FKye,M9N1FKze,M9N1MKxe,M9N1MKye,M9N1MKze, & + M9N2FKxe,M9N2FKye,M9N2FKze,M9N2MKxe,M9N2MKye,M9N2MKze, & + M9N3FKxe,M9N3FKye,M9N3FKze,M9N3MKxe,M9N3MKye,M9N3MKze, & + M9N4FKxe,M9N4FKye,M9N4FKze,M9N4MKxe,M9N4MKye,M9N4MKze, & + M9N5FKxe,M9N5FKye,M9N5FKze,M9N5MKxe,M9N5MKye,M9N5MKze, & + M9N6FKxe,M9N6FKye,M9N6FKze,M9N6MKxe,M9N6MKye,M9N6MKze, & + M9N7FKxe,M9N7FKye,M9N7FKze,M9N7MKxe,M9N7MKye,M9N7MKze, & + M9N8FKxe,M9N8FKye,M9N8FKze,M9N8MKxe,M9N8MKye,M9N8MKze, & + M9N9FKxe,M9N9FKye,M9N9FKze,M9N9MKxe,M9N9MKye,M9N9MKze /),(/6,9,9/)) + + + + INTEGER, PARAMETER :: MNfmMe(6,9,9) = reshape((/ M1N1FMxe,M1N1FMye,M1N1FMze,M1N1MMxe,M1N1MMye,M1N1MMze, & + M1N2FMxe,M1N2FMye,M1N2FMze,M1N2MMxe,M1N2MMye,M1N2MMze, & + M1N3FMxe,M1N3FMye,M1N3FMze,M1N3MMxe,M1N3MMye,M1N3MMze, & + M1N4FMxe,M1N4FMye,M1N4FMze,M1N4MMxe,M1N4MMye,M1N4MMze, & + M1N5FMxe,M1N5FMye,M1N5FMze,M1N5MMxe,M1N5MMye,M1N5MMze, & + M1N6FMxe,M1N6FMye,M1N6FMze,M1N6MMxe,M1N6MMye,M1N6MMze, & + M1N7FMxe,M1N7FMye,M1N7FMze,M1N7MMxe,M1N7MMye,M1N7MMze, & + M1N8FMxe,M1N8FMye,M1N8FMze,M1N8MMxe,M1N8MMye,M1N8MMze, & + M1N9FMxe,M1N9FMye,M1N9FMze,M1N9MMxe,M1N9MMye,M1N9MMze, & + M2N1FMxe,M2N1FMye,M2N1FMze,M2N1MMxe,M2N1MMye,M2N1MMze, & + M2N2FMxe,M2N2FMye,M2N2FMze,M2N2MMxe,M2N2MMye,M2N2MMze, & + M2N3FMxe,M2N3FMye,M2N3FMze,M2N3MMxe,M2N3MMye,M2N3MMze, & + M2N4FMxe,M2N4FMye,M2N4FMze,M2N4MMxe,M2N4MMye,M2N4MMze, & + M2N5FMxe,M2N5FMye,M2N5FMze,M2N5MMxe,M2N5MMye,M2N5MMze, & + M2N6FMxe,M2N6FMye,M2N6FMze,M2N6MMxe,M2N6MMye,M2N6MMze, & + M2N7FMxe,M2N7FMye,M2N7FMze,M2N7MMxe,M2N7MMye,M2N7MMze, & + M2N8FMxe,M2N8FMye,M2N8FMze,M2N8MMxe,M2N8MMye,M2N8MMze, & + M2N9FMxe,M2N9FMye,M2N9FMze,M2N9MMxe,M2N9MMye,M2N9MMze, & + M3N1FMxe,M3N1FMye,M3N1FMze,M3N1MMxe,M3N1MMye,M3N1MMze, & + M3N2FMxe,M3N2FMye,M3N2FMze,M3N2MMxe,M3N2MMye,M3N2MMze, & + M3N3FMxe,M3N3FMye,M3N3FMze,M3N3MMxe,M3N3MMye,M3N3MMze, & + M3N4FMxe,M3N4FMye,M3N4FMze,M3N4MMxe,M3N4MMye,M3N4MMze, & + M3N5FMxe,M3N5FMye,M3N5FMze,M3N5MMxe,M3N5MMye,M3N5MMze, & + M3N6FMxe,M3N6FMye,M3N6FMze,M3N6MMxe,M3N6MMye,M3N6MMze, & + M3N7FMxe,M3N7FMye,M3N7FMze,M3N7MMxe,M3N7MMye,M3N7MMze, & + M3N8FMxe,M3N8FMye,M3N8FMze,M3N8MMxe,M3N8MMye,M3N8MMze, & + M3N9FMxe,M3N9FMye,M3N9FMze,M3N9MMxe,M3N9MMye,M3N9MMze, & + M4N1FMxe,M4N1FMye,M4N1FMze,M4N1MMxe,M4N1MMye,M4N1MMze, & + M4N2FMxe,M4N2FMye,M4N2FMze,M4N2MMxe,M4N2MMye,M4N2MMze, & + M4N3FMxe,M4N3FMye,M4N3FMze,M4N3MMxe,M4N3MMye,M4N3MMze, & + M4N4FMxe,M4N4FMye,M4N4FMze,M4N4MMxe,M4N4MMye,M4N4MMze, & + M4N5FMxe,M4N5FMye,M4N5FMze,M4N5MMxe,M4N5MMye,M4N5MMze, & + M4N6FMxe,M4N6FMye,M4N6FMze,M4N6MMxe,M4N6MMye,M4N6MMze, & + M4N7FMxe,M4N7FMye,M4N7FMze,M4N7MMxe,M4N7MMye,M4N7MMze, & + M4N8FMxe,M4N8FMye,M4N8FMze,M4N8MMxe,M4N8MMye,M4N8MMze, & + M4N9FMxe,M4N9FMye,M4N9FMze,M4N9MMxe,M4N9MMye,M4N9MMze, & + M5N1FMxe,M5N1FMye,M5N1FMze,M5N1MMxe,M5N1MMye,M5N1MMze, & + M5N2FMxe,M5N2FMye,M5N2FMze,M5N2MMxe,M5N2MMye,M5N2MMze, & + M5N3FMxe,M5N3FMye,M5N3FMze,M5N3MMxe,M5N3MMye,M5N3MMze, & + M5N4FMxe,M5N4FMye,M5N4FMze,M5N4MMxe,M5N4MMye,M5N4MMze, & + M5N5FMxe,M5N5FMye,M5N5FMze,M5N5MMxe,M5N5MMye,M5N5MMze, & + M5N6FMxe,M5N6FMye,M5N6FMze,M5N6MMxe,M5N6MMye,M5N6MMze, & + M5N7FMxe,M5N7FMye,M5N7FMze,M5N7MMxe,M5N7MMye,M5N7MMze, & + M5N8FMxe,M5N8FMye,M5N8FMze,M5N8MMxe,M5N8MMye,M5N8MMze, & + M5N9FMxe,M5N9FMye,M5N9FMze,M5N9MMxe,M5N9MMye,M5N9MMze, & + M6N1FMxe,M6N1FMye,M6N1FMze,M6N1MMxe,M6N1MMye,M6N1MMze, & + M6N2FMxe,M6N2FMye,M6N2FMze,M6N2MMxe,M6N2MMye,M6N2MMze, & + M6N3FMxe,M6N3FMye,M6N3FMze,M6N3MMxe,M6N3MMye,M6N3MMze, & + M6N4FMxe,M6N4FMye,M6N4FMze,M6N4MMxe,M6N4MMye,M6N4MMze, & + M6N5FMxe,M6N5FMye,M6N5FMze,M6N5MMxe,M6N5MMye,M6N5MMze, & + M6N6FMxe,M6N6FMye,M6N6FMze,M6N6MMxe,M6N6MMye,M6N6MMze, & + M6N7FMxe,M6N7FMye,M6N7FMze,M6N7MMxe,M6N7MMye,M6N7MMze, & + M6N8FMxe,M6N8FMye,M6N8FMze,M6N8MMxe,M6N8MMye,M6N8MMze, & + M6N9FMxe,M6N9FMye,M6N9FMze,M6N9MMxe,M6N9MMye,M6N9MMze, & + M7N1FMxe,M7N1FMye,M7N1FMze,M7N1MMxe,M7N1MMye,M7N1MMze, & + M7N2FMxe,M7N2FMye,M7N2FMze,M7N2MMxe,M7N2MMye,M7N2MMze, & + M7N3FMxe,M7N3FMye,M7N3FMze,M7N3MMxe,M7N3MMye,M7N3MMze, & + M7N4FMxe,M7N4FMye,M7N4FMze,M7N4MMxe,M7N4MMye,M7N4MMze, & + M7N5FMxe,M7N5FMye,M7N5FMze,M7N5MMxe,M7N5MMye,M7N5MMze, & + M7N6FMxe,M7N6FMye,M7N6FMze,M7N6MMxe,M7N6MMye,M7N6MMze, & + M7N7FMxe,M7N7FMye,M7N7FMze,M7N7MMxe,M7N7MMye,M7N7MMze, & + M7N8FMxe,M7N8FMye,M7N8FMze,M7N8MMxe,M7N8MMye,M7N8MMze, & + M7N9FMxe,M7N9FMye,M7N9FMze,M7N9MMxe,M7N9MMye,M7N9MMze, & + M8N1FMxe,M8N1FMye,M8N1FMze,M8N1MMxe,M8N1MMye,M8N1MMze, & + M8N2FMxe,M8N2FMye,M8N2FMze,M8N2MMxe,M8N2MMye,M8N2MMze, & + M8N3FMxe,M8N3FMye,M8N3FMze,M8N3MMxe,M8N3MMye,M8N3MMze, & + M8N4FMxe,M8N4FMye,M8N4FMze,M8N4MMxe,M8N4MMye,M8N4MMze, & + M8N5FMxe,M8N5FMye,M8N5FMze,M8N5MMxe,M8N5MMye,M8N5MMze, & + M8N6FMxe,M8N6FMye,M8N6FMze,M8N6MMxe,M8N6MMye,M8N6MMze, & + M8N7FMxe,M8N7FMye,M8N7FMze,M8N7MMxe,M8N7MMye,M8N7MMze, & + M8N8FMxe,M8N8FMye,M8N8FMze,M8N8MMxe,M8N8MMye,M8N8MMze, & + M8N9FMxe,M8N9FMye,M8N9FMze,M8N9MMxe,M8N9MMye,M8N9MMze, & + M9N1FMxe,M9N1FMye,M9N1FMze,M9N1MMxe,M9N1MMye,M9N1MMze, & + M9N2FMxe,M9N2FMye,M9N2FMze,M9N2MMxe,M9N2MMye,M9N2MMze, & + M9N3FMxe,M9N3FMye,M9N3FMze,M9N3MMxe,M9N3MMye,M9N3MMze, & + M9N4FMxe,M9N4FMye,M9N4FMze,M9N4MMxe,M9N4MMye,M9N4MMze, & + M9N5FMxe,M9N5FMye,M9N5FMze,M9N5MMxe,M9N5MMye,M9N5MMze, & + M9N6FMxe,M9N6FMye,M9N6FMze,M9N6MMxe,M9N6MMye,M9N6MMze, & + M9N7FMxe,M9N7FMye,M9N7FMze,M9N7MMxe,M9N7MMye,M9N7MMze, & + M9N8FMxe,M9N8FMye,M9N8FMze,M9N8MMxe,M9N8MMye,M9N8MMze, & + M9N9FMxe,M9N9FMye,M9N9FMze,M9N9MMxe,M9N9MMye,M9N9MMze /),(/6,9,9/)) + + INTEGER, PARAMETER :: MNTDss(3,9,9) = reshape((/M1N1TDxss,M1N1TDyss,M1N1TDzss, & + M1N2TDxss,M1N2TDyss,M1N2TDzss, & + M1N3TDxss,M1N3TDyss,M1N3TDzss, & + M1N4TDxss,M1N4TDyss,M1N4TDzss, & + M1N5TDxss,M1N5TDyss,M1N5TDzss, & + M1N6TDxss,M1N6TDyss,M1N6TDzss, & + M1N7TDxss,M1N7TDyss,M1N7TDzss, & + M1N8TDxss,M1N8TDyss,M1N8TDzss, & + M1N9TDxss,M1N9TDyss,M1N9TDzss, & + M2N1TDxss,M2N1TDyss,M2N1TDzss, & + M2N2TDxss,M2N2TDyss,M2N2TDzss, & + M2N3TDxss,M2N3TDyss,M2N3TDzss, & + M2N4TDxss,M2N4TDyss,M2N4TDzss, & + M2N5TDxss,M2N5TDyss,M2N5TDzss, & + M2N6TDxss,M2N6TDyss,M2N6TDzss, & + M2N7TDxss,M2N7TDyss,M2N7TDzss, & + M2N8TDxss,M2N8TDyss,M2N8TDzss, & + M2N9TDxss,M2N9TDyss,M2N9TDzss, & + M3N1TDxss,M3N1TDyss,M3N1TDzss, & + M3N2TDxss,M3N2TDyss,M3N2TDzss, & + M3N3TDxss,M3N3TDyss,M3N3TDzss, & + M3N4TDxss,M3N4TDyss,M3N4TDzss, & + M3N5TDxss,M3N5TDyss,M3N5TDzss, & + M3N6TDxss,M3N6TDyss,M3N6TDzss, & + M3N7TDxss,M3N7TDyss,M3N7TDzss, & + M3N8TDxss,M3N8TDyss,M3N8TDzss, & + M3N9TDxss,M3N9TDyss,M3N9TDzss, & + M4N1TDxss,M4N1TDyss,M4N1TDzss, & + M4N2TDxss,M4N2TDyss,M4N2TDzss, & + M4N3TDxss,M4N3TDyss,M4N3TDzss, & + M4N4TDxss,M4N4TDyss,M4N4TDzss, & + M4N5TDxss,M4N5TDyss,M4N5TDzss, & + M4N6TDxss,M4N6TDyss,M4N6TDzss, & + M4N7TDxss,M4N7TDyss,M4N7TDzss, & + M4N8TDxss,M4N8TDyss,M4N8TDzss, & + M4N9TDxss,M4N9TDyss,M4N9TDzss, & + M5N1TDxss,M5N1TDyss,M5N1TDzss, & + M5N2TDxss,M5N2TDyss,M5N2TDzss, & + M5N3TDxss,M5N3TDyss,M5N3TDzss, & + M5N4TDxss,M5N4TDyss,M5N4TDzss, & + M5N5TDxss,M5N5TDyss,M5N5TDzss, & + M5N6TDxss,M5N6TDyss,M5N6TDzss, & + M5N7TDxss,M5N7TDyss,M5N7TDzss, & + M5N8TDxss,M5N8TDyss,M5N8TDzss, & + M5N9TDxss,M5N9TDyss,M5N9TDzss, & + M6N1TDxss,M6N1TDyss,M6N1TDzss, & + M6N2TDxss,M6N2TDyss,M6N2TDzss, & + M6N3TDxss,M6N3TDyss,M6N3TDzss, & + M6N4TDxss,M6N4TDyss,M6N4TDzss, & + M6N5TDxss,M6N5TDyss,M6N5TDzss, & + M6N6TDxss,M6N6TDyss,M6N6TDzss, & + M6N7TDxss,M6N7TDyss,M6N7TDzss, & + M6N8TDxss,M6N8TDyss,M6N8TDzss, & + M6N9TDxss,M6N9TDyss,M6N9TDzss, & + M7N1TDxss,M7N1TDyss,M7N1TDzss, & + M7N2TDxss,M7N2TDyss,M7N2TDzss, & + M7N3TDxss,M7N3TDyss,M7N3TDzss, & + M7N4TDxss,M7N4TDyss,M7N4TDzss, & + M7N5TDxss,M7N5TDyss,M7N5TDzss, & + M7N6TDxss,M7N6TDyss,M7N6TDzss, & + M7N7TDxss,M7N7TDyss,M7N7TDzss, & + M7N8TDxss,M7N8TDyss,M7N8TDzss, & + M7N9TDxss,M7N9TDyss,M7N9TDzss, & + M8N1TDxss,M8N1TDyss,M8N1TDzss, & + M8N2TDxss,M8N2TDyss,M8N2TDzss, & + M8N3TDxss,M8N3TDyss,M8N3TDzss, & + M8N4TDxss,M8N4TDyss,M8N4TDzss, & + M8N5TDxss,M8N5TDyss,M8N5TDzss, & + M8N6TDxss,M8N6TDyss,M8N6TDzss, & + M8N7TDxss,M8N7TDyss,M8N7TDzss, & + M8N8TDxss,M8N8TDyss,M8N8TDzss, & + M8N9TDxss,M8N9TDyss,M8N9TDzss, & + M9N1TDxss,M9N1TDyss,M9N1TDzss, & + M9N2TDxss,M9N2TDyss,M9N2TDzss, & + M9N3TDxss,M9N3TDyss,M9N3TDzss, & + M9N4TDxss,M9N4TDyss,M9N4TDzss, & + M9N5TDxss,M9N5TDyss,M9N5TDzss, & + M9N6TDxss,M9N6TDyss,M9N6TDzss, & + M9N7TDxss,M9N7TDyss,M9N7TDzss, & + M9N8TDxss,M9N8TDyss,M9N8TDzss, & + M9N9TDxss,M9N9TDyss,M9N9TDzss/), (/3,9,9/)) + +INTEGER, PARAMETER :: MNRDe (3,9,9) = reshape((/M1N1RDxe,M1N1RDye,M1N1RDze, & + M1N2RDxe,M1N2RDye,M1N2RDze, & + M1N3RDxe,M1N3RDye,M1N3RDze, & + M1N4RDxe,M1N4RDye,M1N4RDze, & + M1N5RDxe,M1N5RDye,M1N5RDze, & + M1N6RDxe,M1N6RDye,M1N6RDze, & + M1N7RDxe,M1N7RDye,M1N7RDze, & + M1N8RDxe,M1N8RDye,M1N8RDze, & + M1N9RDxe,M1N9RDye,M1N9RDze, & + M2N1RDxe,M2N1RDye,M2N1RDze, & + M2N2RDxe,M2N2RDye,M2N2RDze, & + M2N3RDxe,M2N3RDye,M2N3RDze, & + M2N4RDxe,M2N4RDye,M2N4RDze, & + M2N5RDxe,M2N5RDye,M2N5RDze, & + M2N6RDxe,M2N6RDye,M2N6RDze, & + M2N7RDxe,M2N7RDye,M2N7RDze, & + M2N8RDxe,M2N8RDye,M2N8RDze, & + M2N9RDxe,M2N9RDye,M2N9RDze, & + M3N1RDxe,M3N1RDye,M3N1RDze, & + M3N2RDxe,M3N2RDye,M3N2RDze, & + M3N3RDxe,M3N3RDye,M3N3RDze, & + M3N4RDxe,M3N4RDye,M3N4RDze, & + M3N5RDxe,M3N5RDye,M3N5RDze, & + M3N6RDxe,M3N6RDye,M3N6RDze, & + M3N7RDxe,M3N7RDye,M3N7RDze, & + M3N8RDxe,M3N8RDye,M3N8RDze, & + M3N9RDxe,M3N9RDye,M3N9RDze, & + M4N1RDxe,M4N1RDye,M4N1RDze, & + M4N2RDxe,M4N2RDye,M4N2RDze, & + M4N3RDxe,M4N3RDye,M4N3RDze, & + M4N4RDxe,M4N4RDye,M4N4RDze, & + M4N5RDxe,M4N5RDye,M4N5RDze, & + M4N6RDxe,M4N6RDye,M4N6RDze, & + M4N7RDxe,M4N7RDye,M4N7RDze, & + M4N8RDxe,M4N8RDye,M4N8RDze, & + M4N9RDxe,M4N9RDye,M4N9RDze, & + M5N1RDxe,M5N1RDye,M5N1RDze, & + M5N2RDxe,M5N2RDye,M5N2RDze, & + M5N3RDxe,M5N3RDye,M5N3RDze, & + M5N4RDxe,M5N4RDye,M5N4RDze, & + M5N5RDxe,M5N5RDye,M5N5RDze, & + M5N6RDxe,M5N6RDye,M5N6RDze, & + M5N7RDxe,M5N7RDye,M5N7RDze, & + M5N8RDxe,M5N8RDye,M5N8RDze, & + M5N9RDxe,M5N9RDye,M5N9RDze, & + M6N1RDxe,M6N1RDye,M6N1RDze, & + M6N2RDxe,M6N2RDye,M6N2RDze, & + M6N3RDxe,M6N3RDye,M6N3RDze, & + M6N4RDxe,M6N4RDye,M6N4RDze, & + M6N5RDxe,M6N5RDye,M6N5RDze, & + M6N6RDxe,M6N6RDye,M6N6RDze, & + M6N7RDxe,M6N7RDye,M6N7RDze, & + M6N8RDxe,M6N8RDye,M6N8RDze, & + M6N9RDxe,M6N9RDye,M6N9RDze, & + M7N1RDxe,M7N1RDye,M7N1RDze, & + M7N2RDxe,M7N2RDye,M7N2RDze, & + M7N3RDxe,M7N3RDye,M7N3RDze, & + M7N4RDxe,M7N4RDye,M7N4RDze, & + M7N5RDxe,M7N5RDye,M7N5RDze, & + M7N6RDxe,M7N6RDye,M7N6RDze, & + M7N7RDxe,M7N7RDye,M7N7RDze, & + M7N8RDxe,M7N8RDye,M7N8RDze, & + M7N9RDxe,M7N9RDye,M7N9RDze, & + M8N1RDxe,M8N1RDye,M8N1RDze, & + M8N2RDxe,M8N2RDye,M8N2RDze, & + M8N3RDxe,M8N3RDye,M8N3RDze, & + M8N4RDxe,M8N4RDye,M8N4RDze, & + M8N5RDxe,M8N5RDye,M8N5RDze, & + M8N6RDxe,M8N6RDye,M8N6RDze, & + M8N7RDxe,M8N7RDye,M8N7RDze, & + M8N8RDxe,M8N8RDye,M8N8RDze, & + M8N9RDxe,M8N9RDye,M8N9RDze, & + M9N1RDxe,M9N1RDye,M9N1RDze, & + M9N2RDxe,M9N2RDye,M9N2RDze, & + M9N3RDxe,M9N3RDye,M9N3RDze, & + M9N4RDxe,M9N4RDye,M9N4RDze, & + M9N5RDxe,M9N5RDye,M9N5RDze, & + M9N6RDxe,M9N6RDye,M9N6RDze, & + M9N7RDxe,M9N7RDye,M9N7RDze, & + M9N8RDxe,M9N8RDye,M9N8RDze, & + M9N9RDxe,M9N9RDye,M9N9RDze/), (/3,9,9/)) + + + INTEGER, PARAMETER :: MNTRAe(6,9,9) = reshape( (/M1N1TAxe,M1N1TAye,M1N1TAze,M1N1RAxe,M1N1RAye,M1N1RAze, & + M1N2TAxe,M1N2TAye,M1N2TAze,M1N2RAxe,M1N2RAye,M1N2RAze, & + M1N3TAxe,M1N3TAye,M1N3TAze,M1N3RAxe,M1N3RAye,M1N3RAze, & + M1N4TAxe,M1N4TAye,M1N4TAze,M1N4RAxe,M1N4RAye,M1N4RAze, & + M1N5TAxe,M1N5TAye,M1N5TAze,M1N5RAxe,M1N5RAye,M1N5RAze, & + M1N6TAxe,M1N6TAye,M1N6TAze,M1N6RAxe,M1N6RAye,M1N6RAze, & + M1N7TAxe,M1N7TAye,M1N7TAze,M1N7RAxe,M1N7RAye,M1N7RAze, & + M1N8TAxe,M1N8TAye,M1N8TAze,M1N8RAxe,M1N8RAye,M1N8RAze, & + M1N9TAxe,M1N9TAye,M1N9TAze,M1N9RAxe,M1N9RAye,M1N9RAze, & + M2N1TAxe,M2N1TAye,M2N1TAze,M2N1RAxe,M2N1RAye,M2N1RAze, & + M2N2TAxe,M2N2TAye,M2N2TAze,M2N2RAxe,M2N2RAye,M2N2RAze, & + M2N3TAxe,M2N3TAye,M2N3TAze,M2N3RAxe,M2N3RAye,M2N3RAze, & + M2N4TAxe,M2N4TAye,M2N4TAze,M2N4RAxe,M2N4RAye,M2N4RAze, & + M2N5TAxe,M2N5TAye,M2N5TAze,M2N5RAxe,M2N5RAye,M2N5RAze, & + M2N6TAxe,M2N6TAye,M2N6TAze,M2N6RAxe,M2N6RAye,M2N6RAze, & + M2N7TAxe,M2N7TAye,M2N7TAze,M2N7RAxe,M2N7RAye,M2N7RAze, & + M2N8TAxe,M2N8TAye,M2N8TAze,M2N8RAxe,M2N8RAye,M2N8RAze, & + M2N9TAxe,M2N9TAye,M2N9TAze,M2N9RAxe,M2N9RAye,M2N9RAze, & + M3N1TAxe,M3N1TAye,M3N1TAze,M3N1RAxe,M3N1RAye,M3N1RAze, & + M3N2TAxe,M3N2TAye,M3N2TAze,M3N2RAxe,M3N2RAye,M3N2RAze, & + M3N3TAxe,M3N3TAye,M3N3TAze,M3N3RAxe,M3N3RAye,M3N3RAze, & + M3N4TAxe,M3N4TAye,M3N4TAze,M3N4RAxe,M3N4RAye,M3N4RAze, & + M3N5TAxe,M3N5TAye,M3N5TAze,M3N5RAxe,M3N5RAye,M3N5RAze, & + M3N6TAxe,M3N6TAye,M3N6TAze,M3N6RAxe,M3N6RAye,M3N6RAze, & + M3N7TAxe,M3N7TAye,M3N7TAze,M3N7RAxe,M3N7RAye,M3N7RAze, & + M3N8TAxe,M3N8TAye,M3N8TAze,M3N8RAxe,M3N8RAye,M3N8RAze, & + M3N9TAxe,M3N9TAye,M3N9TAze,M3N9RAxe,M3N9RAye,M3N9RAze, & + M4N1TAxe,M4N1TAye,M4N1TAze,M4N1RAxe,M4N1RAye,M4N1RAze, & + M4N2TAxe,M4N2TAye,M4N2TAze,M4N2RAxe,M4N2RAye,M4N2RAze, & + M4N3TAxe,M4N3TAye,M4N3TAze,M4N3RAxe,M4N3RAye,M4N3RAze, & + M4N4TAxe,M4N4TAye,M4N4TAze,M4N4RAxe,M4N4RAye,M4N4RAze, & + M4N5TAxe,M4N5TAye,M4N5TAze,M4N5RAxe,M4N5RAye,M4N5RAze, & + M4N6TAxe,M4N6TAye,M4N6TAze,M4N6RAxe,M4N6RAye,M4N6RAze, & + M4N7TAxe,M4N7TAye,M4N7TAze,M4N7RAxe,M4N7RAye,M4N7RAze, & + M4N8TAxe,M4N8TAye,M4N8TAze,M4N8RAxe,M4N8RAye,M4N8RAze, & + M4N9TAxe,M4N9TAye,M4N9TAze,M4N9RAxe,M4N9RAye,M4N9RAze, & + M5N1TAxe,M5N1TAye,M5N1TAze,M5N1RAxe,M5N1RAye,M5N1RAze, & + M5N2TAxe,M5N2TAye,M5N2TAze,M5N2RAxe,M5N2RAye,M5N2RAze, & + M5N3TAxe,M5N3TAye,M5N3TAze,M5N3RAxe,M5N3RAye,M5N3RAze, & + M5N4TAxe,M5N4TAye,M5N4TAze,M5N4RAxe,M5N4RAye,M5N4RAze, & + M5N5TAxe,M5N5TAye,M5N5TAze,M5N5RAxe,M5N5RAye,M5N5RAze, & + M5N6TAxe,M5N6TAye,M5N6TAze,M5N6RAxe,M5N6RAye,M5N6RAze, & + M5N7TAxe,M5N7TAye,M5N7TAze,M5N7RAxe,M5N7RAye,M5N7RAze, & + M5N8TAxe,M5N8TAye,M5N8TAze,M5N8RAxe,M5N8RAye,M5N8RAze, & + M5N9TAxe,M5N9TAye,M5N9TAze,M5N9RAxe,M5N9RAye,M5N9RAze, & + M6N1TAxe,M6N1TAye,M6N1TAze,M6N1RAxe,M6N1RAye,M6N1RAze, & + M6N2TAxe,M6N2TAye,M6N2TAze,M6N2RAxe,M6N2RAye,M6N2RAze, & + M6N3TAxe,M6N3TAye,M6N3TAze,M6N3RAxe,M6N3RAye,M6N3RAze, & + M6N4TAxe,M6N4TAye,M6N4TAze,M6N4RAxe,M6N4RAye,M6N4RAze, & + M6N5TAxe,M6N5TAye,M6N5TAze,M6N5RAxe,M6N5RAye,M6N5RAze, & + M6N6TAxe,M6N6TAye,M6N6TAze,M6N6RAxe,M6N6RAye,M6N6RAze, & + M6N7TAxe,M6N7TAye,M6N7TAze,M6N7RAxe,M6N7RAye,M6N7RAze, & + M6N8TAxe,M6N8TAye,M6N8TAze,M6N8RAxe,M6N8RAye,M6N8RAze, & + M6N9TAxe,M6N9TAye,M6N9TAze,M6N9RAxe,M6N9RAye,M6N9RAze, & + M7N1TAxe,M7N1TAye,M7N1TAze,M7N1RAxe,M7N1RAye,M7N1RAze, & + M7N2TAxe,M7N2TAye,M7N2TAze,M7N2RAxe,M7N2RAye,M7N2RAze, & + M7N3TAxe,M7N3TAye,M7N3TAze,M7N3RAxe,M7N3RAye,M7N3RAze, & + M7N4TAxe,M7N4TAye,M7N4TAze,M7N4RAxe,M7N4RAye,M7N4RAze, & + M7N5TAxe,M7N5TAye,M7N5TAze,M7N5RAxe,M7N5RAye,M7N5RAze, & + M7N6TAxe,M7N6TAye,M7N6TAze,M7N6RAxe,M7N6RAye,M7N6RAze, & + M7N7TAxe,M7N7TAye,M7N7TAze,M7N7RAxe,M7N7RAye,M7N7RAze, & + M7N8TAxe,M7N8TAye,M7N8TAze,M7N8RAxe,M7N8RAye,M7N8RAze, & + M7N9TAxe,M7N9TAye,M7N9TAze,M7N9RAxe,M7N9RAye,M7N9RAze, & + M8N1TAxe,M8N1TAye,M8N1TAze,M8N1RAxe,M8N1RAye,M8N1RAze, & + M8N2TAxe,M8N2TAye,M8N2TAze,M8N2RAxe,M8N2RAye,M8N2RAze, & + M8N3TAxe,M8N3TAye,M8N3TAze,M8N3RAxe,M8N3RAye,M8N3RAze, & + M8N4TAxe,M8N4TAye,M8N4TAze,M8N4RAxe,M8N4RAye,M8N4RAze, & + M8N5TAxe,M8N5TAye,M8N5TAze,M8N5RAxe,M8N5RAye,M8N5RAze, & + M8N6TAxe,M8N6TAye,M8N6TAze,M8N6RAxe,M8N6RAye,M8N6RAze, & + M8N7TAxe,M8N7TAye,M8N7TAze,M8N7RAxe,M8N7RAye,M8N7RAze, & + M8N8TAxe,M8N8TAye,M8N8TAze,M8N8RAxe,M8N8RAye,M8N8RAze, & + M8N9TAxe,M8N9TAye,M8N9TAze,M8N9RAxe,M8N9RAye,M8N9RAze, & + M9N1TAxe,M9N1TAye,M9N1TAze,M9N1RAxe,M9N1RAye,M9N1RAze, & + M9N2TAxe,M9N2TAye,M9N2TAze,M9N2RAxe,M9N2RAye,M9N2RAze, & + M9N3TAxe,M9N3TAye,M9N3TAze,M9N3RAxe,M9N3RAye,M9N3RAze, & + M9N4TAxe,M9N4TAye,M9N4TAze,M9N4RAxe,M9N4RAye,M9N4RAze, & + M9N5TAxe,M9N5TAye,M9N5TAze,M9N5RAxe,M9N5RAye,M9N5RAze, & + M9N6TAxe,M9N6TAye,M9N6TAze,M9N6RAxe,M9N6RAye,M9N6RAze, & + M9N7TAxe,M9N7TAye,M9N7TAze,M9N7RAxe,M9N7RAye,M9N7RAze, & + M9N8TAxe,M9N8TAye,M9N8TAze,M9N8RAxe,M9N8RAye,M9N8RAze, & + M9N9TAxe,M9N9TAye,M9N9TAze,M9N9RAxe,M9N9RAye,M9N9RAze/), (/6,9,9/)) + + INTEGER, PARAMETER :: ReactSS(6) = (/ReactFXss, ReactFYss, ReactFZss , & + ReactMXss, ReactMYss, ReactMZss/) + + INTEGER, PARAMETER :: IntfSS(6) = (/IntfFXss, IntfFYss, IntfFZss , & + IntfMXss, IntfMYss, IntfMZss/) + + + INTEGER, PARAMETER :: IntfTRss(6) = (/IntfTDXss, IntfTDYss, IntfTDZss , & + IntfRDXss, IntfRDYss, IntfRDZss/) + + INTEGER, PARAMETER :: IntfTRAss(6) = (/IntfTAXss, IntfTAYss, IntfTAZss , & + IntfRAXss, IntfRAYss, IntfRAZss/) + + + + + + + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(2265) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "INTFFXSS ","INTFFYSS ","INTFFZSS ","INTFMXSS ","INTFMYSS ","INTFMZSS ","INTFRAXSS", & + "INTFRAYSS","INTFRAZSS","INTFRDXSS","INTFRDYSS","INTFRDZSS","INTFTAXSS","INTFTAYSS", & + "INTFTAZSS","INTFTDXSS","INTFTDYSS","INTFTDZSS","M1N1FKXE ","M1N1FKYE ","M1N1FKZE ", & + "M1N1FMXE ","M1N1FMYE ","M1N1FMZE ","M1N1MKXE ","M1N1MKYE ","M1N1MKZE ","M1N1MMXE ", & + "M1N1MMYE ","M1N1MMZE ","M1N1RAXE ","M1N1RAYE ","M1N1RAZE ","M1N1RDXE ","M1N1RDYE ", & + "M1N1RDZE ","M1N1TAXE ","M1N1TAYE ","M1N1TAZE ","M1N1TDXSS","M1N1TDYSS","M1N1TDZSS", & + "M1N2FKXE ","M1N2FKYE ","M1N2FKZE ","M1N2FMXE ","M1N2FMYE ","M1N2FMZE ","M1N2MKXE ", & + "M1N2MKYE ","M1N2MKZE ","M1N2MMXE ","M1N2MMYE ","M1N2MMZE ","M1N2RAXE ","M1N2RAYE ", & + "M1N2RAZE ","M1N2RDXE ","M1N2RDYE ","M1N2RDZE ","M1N2TAXE ","M1N2TAYE ","M1N2TAZE ", & + "M1N2TDXSS","M1N2TDYSS","M1N2TDZSS","M1N3FKXE ","M1N3FKYE ","M1N3FKZE ","M1N3FMXE ", & + "M1N3FMYE ","M1N3FMZE ","M1N3MKXE ","M1N3MKYE ","M1N3MKZE ","M1N3MMXE ","M1N3MMYE ", & + "M1N3MMZE ","M1N3RAXE ","M1N3RAYE ","M1N3RAZE ","M1N3RDXE ","M1N3RDYE ","M1N3RDZE ", & + "M1N3TAXE ","M1N3TAYE ","M1N3TAZE ","M1N3TDXSS","M1N3TDYSS","M1N3TDZSS","M1N4FKXE ", & + "M1N4FKYE ","M1N4FKZE ","M1N4FMXE ","M1N4FMYE ","M1N4FMZE ","M1N4MKXE ","M1N4MKYE ", & + "M1N4MKZE ","M1N4MMXE ","M1N4MMYE ","M1N4MMZE ","M1N4RAXE ","M1N4RAYE ","M1N4RAZE ", & + "M1N4RDXE ","M1N4RDYE ","M1N4RDZE ","M1N4TAXE ","M1N4TAYE ","M1N4TAZE ","M1N4TDXSS", & + "M1N4TDYSS","M1N4TDZSS","M1N5FKXE ","M1N5FKYE ","M1N5FKZE ","M1N5FMXE ","M1N5FMYE ", & + "M1N5FMZE ","M1N5MKXE ","M1N5MKYE ","M1N5MKZE ","M1N5MMXE ","M1N5MMYE ","M1N5MMZE ", & + "M1N5RAXE ","M1N5RAYE ","M1N5RAZE ","M1N5RDXE ","M1N5RDYE ","M1N5RDZE ","M1N5TAXE ", & + "M1N5TAYE ","M1N5TAZE ","M1N5TDXSS","M1N5TDYSS","M1N5TDZSS","M1N6FKXE ","M1N6FKYE ", & + "M1N6FKZE ","M1N6FMXE ","M1N6FMYE ","M1N6FMZE ","M1N6MKXE ","M1N6MKYE ","M1N6MKZE ", & + "M1N6MMXE ","M1N6MMYE ","M1N6MMZE ","M1N6RAXE ","M1N6RAYE ","M1N6RAZE ","M1N6RDXE ", & + "M1N6RDYE ","M1N6RDZE ","M1N6TAXE ","M1N6TAYE ","M1N6TAZE ","M1N6TDXSS","M1N6TDYSS", & + "M1N6TDZSS","M1N7FKXE ","M1N7FKYE ","M1N7FKZE ","M1N7FMXE ","M1N7FMYE ","M1N7FMZE ", & + "M1N7MKXE ","M1N7MKYE ","M1N7MKZE ","M1N7MMXE ","M1N7MMYE ","M1N7MMZE ","M1N7RAXE ", & + "M1N7RAYE ","M1N7RAZE ","M1N7RDXE ","M1N7RDYE ","M1N7RDZE ","M1N7TAXE ","M1N7TAYE ", & + "M1N7TAZE ","M1N7TDXSS","M1N7TDYSS","M1N7TDZSS","M1N8FKXE ","M1N8FKYE ","M1N8FKZE ", & + "M1N8FMXE ","M1N8FMYE ","M1N8FMZE ","M1N8MKXE ","M1N8MKYE ","M1N8MKZE ","M1N8MMXE ", & + "M1N8MMYE ","M1N8MMZE ","M1N8RAXE ","M1N8RAYE ","M1N8RAZE ","M1N8RDXE ","M1N8RDYE ", & + "M1N8RDZE ","M1N8TAXE ","M1N8TAYE ","M1N8TAZE ","M1N8TDXSS","M1N8TDYSS","M1N8TDZSS", & + "M1N9FKXE ","M1N9FKYE ","M1N9FKZE ","M1N9FMXE ","M1N9FMYE ","M1N9FMZE ","M1N9MKXE ", & + "M1N9MKYE ","M1N9MKZE ","M1N9MMXE ","M1N9MMYE ","M1N9MMZE ","M1N9RAXE ","M1N9RAYE ", & + "M1N9RAZE ","M1N9RDXE ","M1N9RDYE ","M1N9RDZE ","M1N9TAXE ","M1N9TAYE ","M1N9TAZE ", & + "M1N9TDXSS","M1N9TDYSS","M1N9TDZSS","M2N1FKXE ","M2N1FKYE ","M2N1FKZE ","M2N1FMXE ", & + "M2N1FMYE ","M2N1FMZE ","M2N1MKXE ","M2N1MKYE ","M2N1MKZE ","M2N1MMXE ","M2N1MMYE ", & + "M2N1MMZE ","M2N1RAXE ","M2N1RAYE ","M2N1RAZE ","M2N1RDXE ","M2N1RDYE ","M2N1RDZE ", & + "M2N1TAXE ","M2N1TAYE ","M2N1TAZE ","M2N1TDXSS","M2N1TDYSS","M2N1TDZSS","M2N2FKXE ", & + "M2N2FKYE ","M2N2FKZE ","M2N2FMXE ","M2N2FMYE ","M2N2FMZE ","M2N2MKXE ","M2N2MKYE ", & + "M2N2MKZE ","M2N2MMXE ","M2N2MMYE ","M2N2MMZE ","M2N2RAXE ","M2N2RAYE ","M2N2RAZE ", & + "M2N2RDXE ","M2N2RDYE ","M2N2RDZE ","M2N2TAXE ","M2N2TAYE ","M2N2TAZE ","M2N2TDXSS", & + "M2N2TDYSS","M2N2TDZSS","M2N3FKXE ","M2N3FKYE ","M2N3FKZE ","M2N3FMXE ","M2N3FMYE ", & + "M2N3FMZE ","M2N3MKXE ","M2N3MKYE ","M2N3MKZE ","M2N3MMXE ","M2N3MMYE ","M2N3MMZE ", & + "M2N3RAXE ","M2N3RAYE ","M2N3RAZE ","M2N3RDXE ","M2N3RDYE ","M2N3RDZE ","M2N3TAXE ", & + "M2N3TAYE ","M2N3TAZE ","M2N3TDXSS","M2N3TDYSS","M2N3TDZSS","M2N4FKXE ","M2N4FKYE ", & + "M2N4FKZE ","M2N4FMXE ","M2N4FMYE ","M2N4FMZE ","M2N4MKXE ","M2N4MKYE ","M2N4MKZE ", & + "M2N4MMXE ","M2N4MMYE ","M2N4MMZE ","M2N4RAXE ","M2N4RAYE ","M2N4RAZE ","M2N4RDXE ", & + "M2N4RDYE ","M2N4RDZE ","M2N4TAXE ","M2N4TAYE ","M2N4TAZE ","M2N4TDXSS","M2N4TDYSS", & + "M2N4TDZSS","M2N5FKXE ","M2N5FKYE ","M2N5FKZE ","M2N5FMXE ","M2N5FMYE ","M2N5FMZE ", & + "M2N5MKXE ","M2N5MKYE ","M2N5MKZE ","M2N5MMXE ","M2N5MMYE ","M2N5MMZE ","M2N5RAXE ", & + "M2N5RAYE ","M2N5RAZE ","M2N5RDXE ","M2N5RDYE ","M2N5RDZE ","M2N5TAXE ","M2N5TAYE ", & + "M2N5TAZE ","M2N5TDXSS","M2N5TDYSS","M2N5TDZSS","M2N6FKXE ","M2N6FKYE ","M2N6FKZE ", & + "M2N6FMXE ","M2N6FMYE ","M2N6FMZE ","M2N6MKXE ","M2N6MKYE ","M2N6MKZE ","M2N6MMXE ", & + "M2N6MMYE ","M2N6MMZE ","M2N6RAXE ","M2N6RAYE ","M2N6RAZE ","M2N6RDXE ","M2N6RDYE ", & + "M2N6RDZE ","M2N6TAXE ","M2N6TAYE ","M2N6TAZE ","M2N6TDXSS","M2N6TDYSS","M2N6TDZSS", & + "M2N7FKXE ","M2N7FKYE ","M2N7FKZE ","M2N7FMXE ","M2N7FMYE ","M2N7FMZE ","M2N7MKXE ", & + "M2N7MKYE ","M2N7MKZE ","M2N7MMXE ","M2N7MMYE ","M2N7MMZE ","M2N7RAXE ","M2N7RAYE ", & + "M2N7RAZE ","M2N7RDXE ","M2N7RDYE ","M2N7RDZE ","M2N7TAXE ","M2N7TAYE ","M2N7TAZE ", & + "M2N7TDXSS","M2N7TDYSS","M2N7TDZSS","M2N8FKXE ","M2N8FKYE ","M2N8FKZE ","M2N8FMXE ", & + "M2N8FMYE ","M2N8FMZE ","M2N8MKXE ","M2N8MKYE ","M2N8MKZE ","M2N8MMXE ","M2N8MMYE ", & + "M2N8MMZE ","M2N8RAXE ","M2N8RAYE ","M2N8RAZE ","M2N8RDXE ","M2N8RDYE ","M2N8RDZE ", & + "M2N8TAXE ","M2N8TAYE ","M2N8TAZE ","M2N8TDXSS","M2N8TDYSS","M2N8TDZSS","M2N9FKXE ", & + "M2N9FKYE ","M2N9FKZE ","M2N9FMXE ","M2N9FMYE ","M2N9FMZE ","M2N9MKXE ","M2N9MKYE ", & + "M2N9MKZE ","M2N9MMXE ","M2N9MMYE ","M2N9MMZE ","M2N9RAXE ","M2N9RAYE ","M2N9RAZE ", & + "M2N9RDXE ","M2N9RDYE ","M2N9RDZE ","M2N9TAXE ","M2N9TAYE ","M2N9TAZE ","M2N9TDXSS", & + "M2N9TDYSS","M2N9TDZSS","M3N1FKXE ","M3N1FKYE ","M3N1FKZE ","M3N1FMXE ","M3N1FMYE ", & + "M3N1FMZE ","M3N1MKXE ","M3N1MKYE ","M3N1MKZE ","M3N1MMXE ","M3N1MMYE ","M3N1MMZE ", & + "M3N1RAXE ","M3N1RAYE ","M3N1RAZE ","M3N1RDXE ","M3N1RDYE ","M3N1RDZE ","M3N1TAXE ", & + "M3N1TAYE ","M3N1TAZE ","M3N1TDXSS","M3N1TDYSS","M3N1TDZSS","M3N2FKXE ","M3N2FKYE ", & + "M3N2FKZE ","M3N2FMXE ","M3N2FMYE ","M3N2FMZE ","M3N2MKXE ","M3N2MKYE ","M3N2MKZE ", & + "M3N2MMXE ","M3N2MMYE ","M3N2MMZE ","M3N2RAXE ","M3N2RAYE ","M3N2RAZE ","M3N2RDXE ", & + "M3N2RDYE ","M3N2RDZE ","M3N2TAXE ","M3N2TAYE ","M3N2TAZE ","M3N2TDXSS","M3N2TDYSS", & + "M3N2TDZSS","M3N3FKXE ","M3N3FKYE ","M3N3FKZE ","M3N3FMXE ","M3N3FMYE ","M3N3FMZE ", & + "M3N3MKXE ","M3N3MKYE ","M3N3MKZE ","M3N3MMXE ","M3N3MMYE ","M3N3MMZE ","M3N3RAXE ", & + "M3N3RAYE ","M3N3RAZE ","M3N3RDXE ","M3N3RDYE ","M3N3RDZE ","M3N3TAXE ","M3N3TAYE ", & + "M3N3TAZE ","M3N3TDXSS","M3N3TDYSS","M3N3TDZSS","M3N4FKXE ","M3N4FKYE ","M3N4FKZE ", & + "M3N4FMXE ","M3N4FMYE ","M3N4FMZE ","M3N4MKXE ","M3N4MKYE ","M3N4MKZE ","M3N4MMXE ", & + "M3N4MMYE ","M3N4MMZE ","M3N4RAXE ","M3N4RAYE ","M3N4RAZE ","M3N4RDXE ","M3N4RDYE ", & + "M3N4RDZE ","M3N4TAXE ","M3N4TAYE ","M3N4TAZE ","M3N4TDXSS","M3N4TDYSS","M3N4TDZSS", & + "M3N5FKXE ","M3N5FKYE ","M3N5FKZE ","M3N5FMXE ","M3N5FMYE ","M3N5FMZE ","M3N5MKXE ", & + "M3N5MKYE ","M3N5MKZE ","M3N5MMXE ","M3N5MMYE ","M3N5MMZE ","M3N5RAXE ","M3N5RAYE ", & + "M3N5RAZE ","M3N5RDXE ","M3N5RDYE ","M3N5RDZE ","M3N5TAXE ","M3N5TAYE ","M3N5TAZE ", & + "M3N5TDXSS","M3N5TDYSS","M3N5TDZSS","M3N6FKXE ","M3N6FKYE ","M3N6FKZE ","M3N6FMXE ", & + "M3N6FMYE ","M3N6FMZE ","M3N6MKXE ","M3N6MKYE ","M3N6MKZE ","M3N6MMXE ","M3N6MMYE ", & + "M3N6MMZE ","M3N6RAXE ","M3N6RAYE ","M3N6RAZE ","M3N6RDXE ","M3N6RDYE ","M3N6RDZE ", & + "M3N6TAXE ","M3N6TAYE ","M3N6TAZE ","M3N6TDXSS","M3N6TDYSS","M3N6TDZSS","M3N7FKXE ", & + "M3N7FKYE ","M3N7FKZE ","M3N7FMXE ","M3N7FMYE ","M3N7FMZE ","M3N7MKXE ","M3N7MKYE ", & + "M3N7MKZE ","M3N7MMXE ","M3N7MMYE ","M3N7MMZE ","M3N7RAXE ","M3N7RAYE ","M3N7RAZE ", & + "M3N7RDXE ","M3N7RDYE ","M3N7RDZE ","M3N7TAXE ","M3N7TAYE ","M3N7TAZE ","M3N7TDXSS", & + "M3N7TDYSS","M3N7TDZSS","M3N8FKXE ","M3N8FKYE ","M3N8FKZE ","M3N8FMXE ","M3N8FMYE ", & + "M3N8FMZE ","M3N8MKXE ","M3N8MKYE ","M3N8MKZE ","M3N8MMXE ","M3N8MMYE ","M3N8MMZE ", & + "M3N8RAXE ","M3N8RAYE ","M3N8RAZE ","M3N8RDXE ","M3N8RDYE ","M3N8RDZE ","M3N8TAXE ", & + "M3N8TAYE ","M3N8TAZE ","M3N8TDXSS","M3N8TDYSS","M3N8TDZSS","M3N9FKXE ","M3N9FKYE ", & + "M3N9FKZE ","M3N9FMXE ","M3N9FMYE ","M3N9FMZE ","M3N9MKXE ","M3N9MKYE ","M3N9MKZE ", & + "M3N9MMXE ","M3N9MMYE ","M3N9MMZE ","M3N9RAXE ","M3N9RAYE ","M3N9RAZE ","M3N9RDXE ", & + "M3N9RDYE ","M3N9RDZE ","M3N9TAXE ","M3N9TAYE ","M3N9TAZE ","M3N9TDXSS","M3N9TDYSS", & + "M3N9TDZSS","M4N1FKXE ","M4N1FKYE ","M4N1FKZE ","M4N1FMXE ","M4N1FMYE ","M4N1FMZE ", & + "M4N1MKXE ","M4N1MKYE ","M4N1MKZE ","M4N1MMXE ","M4N1MMYE ","M4N1MMZE ","M4N1RAXE ", & + "M4N1RAYE ","M4N1RAZE ","M4N1RDXE ","M4N1RDYE ","M4N1RDZE ","M4N1TAXE ","M4N1TAYE ", & + "M4N1TAZE ","M4N1TDXSS","M4N1TDYSS","M4N1TDZSS","M4N2FKXE ","M4N2FKYE ","M4N2FKZE ", & + "M4N2FMXE ","M4N2FMYE ","M4N2FMZE ","M4N2MKXE ","M4N2MKYE ","M4N2MKZE ","M4N2MMXE ", & + "M4N2MMYE ","M4N2MMZE ","M4N2RAXE ","M4N2RAYE ","M4N2RAZE ","M4N2RDXE ","M4N2RDYE ", & + "M4N2RDZE ","M4N2TAXE ","M4N2TAYE ","M4N2TAZE ","M4N2TDXSS","M4N2TDYSS","M4N2TDZSS", & + "M4N3FKXE ","M4N3FKYE ","M4N3FKZE ","M4N3FMXE ","M4N3FMYE ","M4N3FMZE ","M4N3MKXE ", & + "M4N3MKYE ","M4N3MKZE ","M4N3MMXE ","M4N3MMYE ","M4N3MMZE ","M4N3RAXE ","M4N3RAYE ", & + "M4N3RAZE ","M4N3RDXE ","M4N3RDYE ","M4N3RDZE ","M4N3TAXE ","M4N3TAYE ","M4N3TAZE ", & + "M4N3TDXSS","M4N3TDYSS","M4N3TDZSS","M4N4FKXE ","M4N4FKYE ","M4N4FKZE ","M4N4FMXE ", & + "M4N4FMYE ","M4N4FMZE ","M4N4MKXE ","M4N4MKYE ","M4N4MKZE ","M4N4MMXE ","M4N4MMYE ", & + "M4N4MMZE ","M4N4RAXE ","M4N4RAYE ","M4N4RAZE ","M4N4RDXE ","M4N4RDYE ","M4N4RDZE ", & + "M4N4TAXE ","M4N4TAYE ","M4N4TAZE ","M4N4TDXSS","M4N4TDYSS","M4N4TDZSS","M4N5FKXE ", & + "M4N5FKYE ","M4N5FKZE ","M4N5FMXE ","M4N5FMYE ","M4N5FMZE ","M4N5MKXE ","M4N5MKYE ", & + "M4N5MKZE ","M4N5MMXE ","M4N5MMYE ","M4N5MMZE ","M4N5RAXE ","M4N5RAYE ","M4N5RAZE ", & + "M4N5RDXE ","M4N5RDYE ","M4N5RDZE ","M4N5TAXE ","M4N5TAYE ","M4N5TAZE ","M4N5TDXSS", & + "M4N5TDYSS","M4N5TDZSS","M4N6FKXE ","M4N6FKYE ","M4N6FKZE ","M4N6FMXE ","M4N6FMYE ", & + "M4N6FMZE ","M4N6MKXE ","M4N6MKYE ","M4N6MKZE ","M4N6MMXE ","M4N6MMYE ","M4N6MMZE ", & + "M4N6RAXE ","M4N6RAYE ","M4N6RAZE ","M4N6RDXE ","M4N6RDYE ","M4N6RDZE ","M4N6TAXE ", & + "M4N6TAYE ","M4N6TAZE ","M4N6TDXSS","M4N6TDYSS","M4N6TDZSS","M4N7FKXE ","M4N7FKYE ", & + "M4N7FKZE ","M4N7FMXE ","M4N7FMYE ","M4N7FMZE ","M4N7MKXE ","M4N7MKYE ","M4N7MKZE ", & + "M4N7MMXE ","M4N7MMYE ","M4N7MMZE ","M4N7RAXE ","M4N7RAYE ","M4N7RAZE ","M4N7RDXE ", & + "M4N7RDYE ","M4N7RDZE ","M4N7TAXE ","M4N7TAYE ","M4N7TAZE ","M4N7TDXSS","M4N7TDYSS", & + "M4N7TDZSS","M4N8FKXE ","M4N8FKYE ","M4N8FKZE ","M4N8FMXE ","M4N8FMYE ","M4N8FMZE ", & + "M4N8MKXE ","M4N8MKYE ","M4N8MKZE ","M4N8MMXE ","M4N8MMYE ","M4N8MMZE ","M4N8RAXE ", & + "M4N8RAYE ","M4N8RAZE ","M4N8RDXE ","M4N8RDYE ","M4N8RDZE ","M4N8TAXE ","M4N8TAYE ", & + "M4N8TAZE ","M4N8TDXSS","M4N8TDYSS","M4N8TDZSS","M4N9FKXE ","M4N9FKYE ","M4N9FKZE ", & + "M4N9FMXE ","M4N9FMYE ","M4N9FMZE ","M4N9MKXE ","M4N9MKYE ","M4N9MKZE ","M4N9MMXE ", & + "M4N9MMYE ","M4N9MMZE ","M4N9RAXE ","M4N9RAYE ","M4N9RAZE ","M4N9RDXE ","M4N9RDYE ", & + "M4N9RDZE ","M4N9TAXE ","M4N9TAYE ","M4N9TAZE ","M4N9TDXSS","M4N9TDYSS","M4N9TDZSS", & + "M5N1FKXE ","M5N1FKYE ","M5N1FKZE ","M5N1FMXE ","M5N1FMYE ","M5N1FMZE ","M5N1MKXE ", & + "M5N1MKYE ","M5N1MKZE ","M5N1MMXE ","M5N1MMYE ","M5N1MMZE ","M5N1RAXE ","M5N1RAYE ", & + "M5N1RAZE ","M5N1RDXE ","M5N1RDYE ","M5N1RDZE ","M5N1TAXE ","M5N1TAYE ","M5N1TAZE ", & + "M5N1TDXSS","M5N1TDYSS","M5N1TDZSS","M5N2FKXE ","M5N2FKYE ","M5N2FKZE ","M5N2FMXE ", & + "M5N2FMYE ","M5N2FMZE ","M5N2MKXE ","M5N2MKYE ","M5N2MKZE ","M5N2MMXE ","M5N2MMYE ", & + "M5N2MMZE ","M5N2RAXE ","M5N2RAYE ","M5N2RAZE ","M5N2RDXE ","M5N2RDYE ","M5N2RDZE ", & + "M5N2TAXE ","M5N2TAYE ","M5N2TAZE ","M5N2TDXSS","M5N2TDYSS","M5N2TDZSS","M5N3FKXE ", & + "M5N3FKYE ","M5N3FKZE ","M5N3FMXE ","M5N3FMYE ","M5N3FMZE ","M5N3MKXE ","M5N3MKYE ", & + "M5N3MKZE ","M5N3MMXE ","M5N3MMYE ","M5N3MMZE ","M5N3RAXE ","M5N3RAYE ","M5N3RAZE ", & + "M5N3RDXE ","M5N3RDYE ","M5N3RDZE ","M5N3TAXE ","M5N3TAYE ","M5N3TAZE ","M5N3TDXSS", & + "M5N3TDYSS","M5N3TDZSS","M5N4FKXE ","M5N4FKYE ","M5N4FKZE ","M5N4FMXE ","M5N4FMYE ", & + "M5N4FMZE ","M5N4MKXE ","M5N4MKYE ","M5N4MKZE ","M5N4MMXE ","M5N4MMYE ","M5N4MMZE ", & + "M5N4RAXE ","M5N4RAYE ","M5N4RAZE ","M5N4RDXE ","M5N4RDYE ","M5N4RDZE ","M5N4TAXE ", & + "M5N4TAYE ","M5N4TAZE ","M5N4TDXSS","M5N4TDYSS","M5N4TDZSS","M5N5FKXE ","M5N5FKYE ", & + "M5N5FKZE ","M5N5FMXE ","M5N5FMYE ","M5N5FMZE ","M5N5MKXE ","M5N5MKYE ","M5N5MKZE ", & + "M5N5MMXE ","M5N5MMYE ","M5N5MMZE ","M5N5RAXE ","M5N5RAYE ","M5N5RAZE ","M5N5RDXE ", & + "M5N5RDYE ","M5N5RDZE ","M5N5TAXE ","M5N5TAYE ","M5N5TAZE ","M5N5TDXSS","M5N5TDYSS", & + "M5N5TDZSS","M5N6FKXE ","M5N6FKYE ","M5N6FKZE ","M5N6FMXE ","M5N6FMYE ","M5N6FMZE ", & + "M5N6MKXE ","M5N6MKYE ","M5N6MKZE ","M5N6MMXE ","M5N6MMYE ","M5N6MMZE ","M5N6RAXE ", & + "M5N6RAYE ","M5N6RAZE ","M5N6RDXE ","M5N6RDYE ","M5N6RDZE ","M5N6TAXE ","M5N6TAYE ", & + "M5N6TAZE ","M5N6TDXSS","M5N6TDYSS","M5N6TDZSS","M5N7FKXE ","M5N7FKYE ","M5N7FKZE ", & + "M5N7FMXE ","M5N7FMYE ","M5N7FMZE ","M5N7MKXE ","M5N7MKYE ","M5N7MKZE ","M5N7MMXE ", & + "M5N7MMYE ","M5N7MMZE ","M5N7RAXE ","M5N7RAYE ","M5N7RAZE ","M5N7RDXE ","M5N7RDYE ", & + "M5N7RDZE ","M5N7TAXE ","M5N7TAYE ","M5N7TAZE ","M5N7TDXSS","M5N7TDYSS","M5N7TDZSS", & + "M5N8FKXE ","M5N8FKYE ","M5N8FKZE ","M5N8FMXE ","M5N8FMYE ","M5N8FMZE ","M5N8MKXE ", & + "M5N8MKYE ","M5N8MKZE ","M5N8MMXE ","M5N8MMYE ","M5N8MMZE ","M5N8RAXE ","M5N8RAYE ", & + "M5N8RAZE ","M5N8RDXE ","M5N8RDYE ","M5N8RDZE ","M5N8TAXE ","M5N8TAYE ","M5N8TAZE ", & + "M5N8TDXSS","M5N8TDYSS","M5N8TDZSS","M5N9FKXE ","M5N9FKYE ","M5N9FKZE ","M5N9FMXE ", & + "M5N9FMYE ","M5N9FMZE ","M5N9MKXE ","M5N9MKYE ","M5N9MKZE ","M5N9MMXE ","M5N9MMYE ", & + "M5N9MMZE ","M5N9RAXE ","M5N9RAYE ","M5N9RAZE ","M5N9RDXE ","M5N9RDYE ","M5N9RDZE ", & + "M5N9TAXE ","M5N9TAYE ","M5N9TAZE ","M5N9TDXSS","M5N9TDYSS","M5N9TDZSS","M6N1FKXE ", & + "M6N1FKYE ","M6N1FKZE ","M6N1FMXE ","M6N1FMYE ","M6N1FMZE ","M6N1MKXE ","M6N1MKYE ", & + "M6N1MKZE ","M6N1MMXE ","M6N1MMYE ","M6N1MMZE ","M6N1RAXE ","M6N1RAYE ","M6N1RAZE ", & + "M6N1RDXE ","M6N1RDYE ","M6N1RDZE ","M6N1TAXE ","M6N1TAYE ","M6N1TAZE ","M6N1TDXSS", & + "M6N1TDYSS","M6N1TDZSS","M6N2FKXE ","M6N2FKYE ","M6N2FKZE ","M6N2FMXE ","M6N2FMYE ", & + "M6N2FMZE ","M6N2MKXE ","M6N2MKYE ","M6N2MKZE ","M6N2MMXE ","M6N2MMYE ","M6N2MMZE ", & + "M6N2RAXE ","M6N2RAYE ","M6N2RAZE ","M6N2RDXE ","M6N2RDYE ","M6N2RDZE ","M6N2TAXE ", & + "M6N2TAYE ","M6N2TAZE ","M6N2TDXSS","M6N2TDYSS","M6N2TDZSS","M6N3FKXE ","M6N3FKYE ", & + "M6N3FKZE ","M6N3FMXE ","M6N3FMYE ","M6N3FMZE ","M6N3MKXE ","M6N3MKYE ","M6N3MKZE ", & + "M6N3MMXE ","M6N3MMYE ","M6N3MMZE ","M6N3RAXE ","M6N3RAYE ","M6N3RAZE ","M6N3RDXE ", & + "M6N3RDYE ","M6N3RDZE ","M6N3TAXE ","M6N3TAYE ","M6N3TAZE ","M6N3TDXSS","M6N3TDYSS", & + "M6N3TDZSS","M6N4FKXE ","M6N4FKYE ","M6N4FKZE ","M6N4FMXE ","M6N4FMYE ","M6N4FMZE ", & + "M6N4MKXE ","M6N4MKYE ","M6N4MKZE ","M6N4MMXE ","M6N4MMYE ","M6N4MMZE ","M6N4RAXE ", & + "M6N4RAYE ","M6N4RAZE ","M6N4RDXE ","M6N4RDYE ","M6N4RDZE ","M6N4TAXE ","M6N4TAYE ", & + "M6N4TAZE ","M6N4TDXSS","M6N4TDYSS","M6N4TDZSS","M6N5FKXE ","M6N5FKYE ","M6N5FKZE ", & + "M6N5FMXE ","M6N5FMYE ","M6N5FMZE ","M6N5MKXE ","M6N5MKYE ","M6N5MKZE ","M6N5MMXE ", & + "M6N5MMYE ","M6N5MMZE ","M6N5RAXE ","M6N5RAYE ","M6N5RAZE ","M6N5RDXE ","M6N5RDYE ", & + "M6N5RDZE ","M6N5TAXE ","M6N5TAYE ","M6N5TAZE ","M6N5TDXSS","M6N5TDYSS","M6N5TDZSS", & + "M6N6FKXE ","M6N6FKYE ","M6N6FKZE ","M6N6FMXE ","M6N6FMYE ","M6N6FMZE ","M6N6MKXE ", & + "M6N6MKYE ","M6N6MKZE ","M6N6MMXE ","M6N6MMYE ","M6N6MMZE ","M6N6RAXE ","M6N6RAYE ", & + "M6N6RAZE ","M6N6RDXE ","M6N6RDYE ","M6N6RDZE ","M6N6TAXE ","M6N6TAYE ","M6N6TAZE ", & + "M6N6TDXSS","M6N6TDYSS","M6N6TDZSS","M6N7FKXE ","M6N7FKYE ","M6N7FKZE ","M6N7FMXE ", & + "M6N7FMYE ","M6N7FMZE ","M6N7MKXE ","M6N7MKYE ","M6N7MKZE ","M6N7MMXE ","M6N7MMYE ", & + "M6N7MMZE ","M6N7RAXE ","M6N7RAYE ","M6N7RAZE ","M6N7RDXE ","M6N7RDYE ","M6N7RDZE ", & + "M6N7TAXE ","M6N7TAYE ","M6N7TAZE ","M6N7TDXSS","M6N7TDYSS","M6N7TDZSS","M6N8FKXE ", & + "M6N8FKYE ","M6N8FKZE ","M6N8FMXE ","M6N8FMYE ","M6N8FMZE ","M6N8MKXE ","M6N8MKYE ", & + "M6N8MKZE ","M6N8MMXE ","M6N8MMYE ","M6N8MMZE ","M6N8RAXE ","M6N8RAYE ","M6N8RAZE ", & + "M6N8RDXE ","M6N8RDYE ","M6N8RDZE ","M6N8TAXE ","M6N8TAYE ","M6N8TAZE ","M6N8TDXSS", & + "M6N8TDYSS","M6N8TDZSS","M6N9FKXE ","M6N9FKYE ","M6N9FKZE ","M6N9FMXE ","M6N9FMYE ", & + "M6N9FMZE ","M6N9MKXE ","M6N9MKYE ","M6N9MKZE ","M6N9MMXE ","M6N9MMYE ","M6N9MMZE ", & + "M6N9RAXE ","M6N9RAYE ","M6N9RAZE ","M6N9RDXE ","M6N9RDYE ","M6N9RDZE ","M6N9TAXE ", & + "M6N9TAYE ","M6N9TAZE ","M6N9TDXSS","M6N9TDYSS","M6N9TDZSS","M7N1FKXE ","M7N1FKYE ", & + "M7N1FKZE ","M7N1FMXE ","M7N1FMYE ","M7N1FMZE ","M7N1MKXE ","M7N1MKYE ","M7N1MKZE ", & + "M7N1MMXE ","M7N1MMYE ","M7N1MMZE ","M7N1RAXE ","M7N1RAYE ","M7N1RAZE ","M7N1RDXE ", & + "M7N1RDYE ","M7N1RDZE ","M7N1TAXE ","M7N1TAYE ","M7N1TAZE ","M7N1TDXSS","M7N1TDYSS", & + "M7N1TDZSS","M7N2FKXE ","M7N2FKYE ","M7N2FKZE ","M7N2FMXE ","M7N2FMYE ","M7N2FMZE ", & + "M7N2MKXE ","M7N2MKYE ","M7N2MKZE ","M7N2MMXE ","M7N2MMYE ","M7N2MMZE ","M7N2RAXE ", & + "M7N2RAYE ","M7N2RAZE ","M7N2RDXE ","M7N2RDYE ","M7N2RDZE ","M7N2TAXE ","M7N2TAYE ", & + "M7N2TAZE ","M7N2TDXSS","M7N2TDYSS","M7N2TDZSS","M7N3FKXE ","M7N3FKYE ","M7N3FKZE ", & + "M7N3FMXE ","M7N3FMYE ","M7N3FMZE ","M7N3MKXE ","M7N3MKYE ","M7N3MKZE ","M7N3MMXE ", & + "M7N3MMYE ","M7N3MMZE ","M7N3RAXE ","M7N3RAYE ","M7N3RAZE ","M7N3RDXE ","M7N3RDYE ", & + "M7N3RDZE ","M7N3TAXE ","M7N3TAYE ","M7N3TAZE ","M7N3TDXSS","M7N3TDYSS","M7N3TDZSS", & + "M7N4FKXE ","M7N4FKYE ","M7N4FKZE ","M7N4FMXE ","M7N4FMYE ","M7N4FMZE ","M7N4MKXE ", & + "M7N4MKYE ","M7N4MKZE ","M7N4MMXE ","M7N4MMYE ","M7N4MMZE ","M7N4RAXE ","M7N4RAYE ", & + "M7N4RAZE ","M7N4RDXE ","M7N4RDYE ","M7N4RDZE ","M7N4TAXE ","M7N4TAYE ","M7N4TAZE ", & + "M7N4TDXSS","M7N4TDYSS","M7N4TDZSS","M7N5FKXE ","M7N5FKYE ","M7N5FKZE ","M7N5FMXE ", & + "M7N5FMYE ","M7N5FMZE ","M7N5MKXE ","M7N5MKYE ","M7N5MKZE ","M7N5MMXE ","M7N5MMYE ", & + "M7N5MMZE ","M7N5RAXE ","M7N5RAYE ","M7N5RAZE ","M7N5RDXE ","M7N5RDYE ","M7N5RDZE ", & + "M7N5TAXE ","M7N5TAYE ","M7N5TAZE ","M7N5TDXSS","M7N5TDYSS","M7N5TDZSS","M7N6FKXE ", & + "M7N6FKYE ","M7N6FKZE ","M7N6FMXE ","M7N6FMYE ","M7N6FMZE ","M7N6MKXE ","M7N6MKYE ", & + "M7N6MKZE ","M7N6MMXE ","M7N6MMYE ","M7N6MMZE ","M7N6RAXE ","M7N6RAYE ","M7N6RAZE ", & + "M7N6RDXE ","M7N6RDYE ","M7N6RDZE ","M7N6TAXE ","M7N6TAYE ","M7N6TAZE ","M7N6TDXSS", & + "M7N6TDYSS","M7N6TDZSS","M7N7FKXE ","M7N7FKYE ","M7N7FKZE ","M7N7FMXE ","M7N7FMYE ", & + "M7N7FMZE ","M7N7MKXE ","M7N7MKYE ","M7N7MKZE ","M7N7MMXE ","M7N7MMYE ","M7N7MMZE ", & + "M7N7RAXE ","M7N7RAYE ","M7N7RAZE ","M7N7RDXE ","M7N7RDYE ","M7N7RDZE ","M7N7TAXE ", & + "M7N7TAYE ","M7N7TAZE ","M7N7TDXSS","M7N7TDYSS","M7N7TDZSS","M7N8FKXE ","M7N8FKYE ", & + "M7N8FKZE ","M7N8FMXE ","M7N8FMYE ","M7N8FMZE ","M7N8MKXE ","M7N8MKYE ","M7N8MKZE ", & + "M7N8MMXE ","M7N8MMYE ","M7N8MMZE ","M7N8RAXE ","M7N8RAYE ","M7N8RAZE ","M7N8RDXE ", & + "M7N8RDYE ","M7N8RDZE ","M7N8TAXE ","M7N8TAYE ","M7N8TAZE ","M7N8TDXSS","M7N8TDYSS", & + "M7N8TDZSS","M7N9FKXE ","M7N9FKYE ","M7N9FKZE ","M7N9FMXE ","M7N9FMYE ","M7N9FMZE ", & + "M7N9MKXE ","M7N9MKYE ","M7N9MKZE ","M7N9MMXE ","M7N9MMYE ","M7N9MMZE ","M7N9RAXE ", & + "M7N9RAYE ","M7N9RAZE ","M7N9RDXE ","M7N9RDYE ","M7N9RDZE ","M7N9TAXE ","M7N9TAYE ", & + "M7N9TAZE ","M7N9TDXSS","M7N9TDYSS","M7N9TDZSS","M8N1FKXE ","M8N1FKYE ","M8N1FKZE ", & + "M8N1FMXE ","M8N1FMYE ","M8N1FMZE ","M8N1MKXE ","M8N1MKYE ","M8N1MKZE ","M8N1MMXE ", & + "M8N1MMYE ","M8N1MMZE ","M8N1RAXE ","M8N1RAYE ","M8N1RAZE ","M8N1RDXE ","M8N1RDYE ", & + "M8N1RDZE ","M8N1TAXE ","M8N1TAYE ","M8N1TAZE ","M8N1TDXSS","M8N1TDYSS","M8N1TDZSS", & + "M8N2FKXE ","M8N2FKYE ","M8N2FKZE ","M8N2FMXE ","M8N2FMYE ","M8N2FMZE ","M8N2MKXE ", & + "M8N2MKYE ","M8N2MKZE ","M8N2MMXE ","M8N2MMYE ","M8N2MMZE ","M8N2RAXE ","M8N2RAYE ", & + "M8N2RAZE ","M8N2RDXE ","M8N2RDYE ","M8N2RDZE ","M8N2TAXE ","M8N2TAYE ","M8N2TAZE ", & + "M8N2TDXSS","M8N2TDYSS","M8N2TDZSS","M8N3FKXE ","M8N3FKYE ","M8N3FKZE ","M8N3FMXE ", & + "M8N3FMYE ","M8N3FMZE ","M8N3MKXE ","M8N3MKYE ","M8N3MKZE ","M8N3MMXE ","M8N3MMYE ", & + "M8N3MMZE ","M8N3RAXE ","M8N3RAYE ","M8N3RAZE ","M8N3RDXE ","M8N3RDYE ","M8N3RDZE ", & + "M8N3TAXE ","M8N3TAYE ","M8N3TAZE ","M8N3TDXSS","M8N3TDYSS","M8N3TDZSS","M8N4FKXE ", & + "M8N4FKYE ","M8N4FKZE ","M8N4FMXE ","M8N4FMYE ","M8N4FMZE ","M8N4MKXE ","M8N4MKYE ", & + "M8N4MKZE ","M8N4MMXE ","M8N4MMYE ","M8N4MMZE ","M8N4RAXE ","M8N4RAYE ","M8N4RAZE ", & + "M8N4RDXE ","M8N4RDYE ","M8N4RDZE ","M8N4TAXE ","M8N4TAYE ","M8N4TAZE ","M8N4TDXSS", & + "M8N4TDYSS","M8N4TDZSS","M8N5FKXE ","M8N5FKYE ","M8N5FKZE ","M8N5FMXE ","M8N5FMYE ", & + "M8N5FMZE ","M8N5MKXE ","M8N5MKYE ","M8N5MKZE ","M8N5MMXE ","M8N5MMYE ","M8N5MMZE ", & + "M8N5RAXE ","M8N5RAYE ","M8N5RAZE ","M8N5RDXE ","M8N5RDYE ","M8N5RDZE ","M8N5TAXE ", & + "M8N5TAYE ","M8N5TAZE ","M8N5TDXSS","M8N5TDYSS","M8N5TDZSS","M8N6FKXE ","M8N6FKYE ", & + "M8N6FKZE ","M8N6FMXE ","M8N6FMYE ","M8N6FMZE ","M8N6MKXE ","M8N6MKYE ","M8N6MKZE ", & + "M8N6MMXE ","M8N6MMYE ","M8N6MMZE ","M8N6RAXE ","M8N6RAYE ","M8N6RAZE ","M8N6RDXE ", & + "M8N6RDYE ","M8N6RDZE ","M8N6TAXE ","M8N6TAYE ","M8N6TAZE ","M8N6TDXSS","M8N6TDYSS", & + "M8N6TDZSS","M8N7FKXE ","M8N7FKYE ","M8N7FKZE ","M8N7FMXE ","M8N7FMYE ","M8N7FMZE ", & + "M8N7MKXE ","M8N7MKYE ","M8N7MKZE ","M8N7MMXE ","M8N7MMYE ","M8N7MMZE ","M8N7RAXE ", & + "M8N7RAYE ","M8N7RAZE ","M8N7RDXE ","M8N7RDYE ","M8N7RDZE ","M8N7TAXE ","M8N7TAYE ", & + "M8N7TAZE ","M8N7TDXSS","M8N7TDYSS","M8N7TDZSS","M8N8FKXE ","M8N8FKYE ","M8N8FKZE ", & + "M8N8FMXE ","M8N8FMYE ","M8N8FMZE ","M8N8MKXE ","M8N8MKYE ","M8N8MKZE ","M8N8MMXE ", & + "M8N8MMYE ","M8N8MMZE ","M8N8RAXE ","M8N8RAYE ","M8N8RAZE ","M8N8RDXE ","M8N8RDYE ", & + "M8N8RDZE ","M8N8TAXE ","M8N8TAYE ","M8N8TAZE ","M8N8TDXSS","M8N8TDYSS","M8N8TDZSS", & + "M8N9FKXE ","M8N9FKYE ","M8N9FKZE ","M8N9FMXE ","M8N9FMYE ","M8N9FMZE ","M8N9MKXE ", & + "M8N9MKYE ","M8N9MKZE ","M8N9MMXE ","M8N9MMYE ","M8N9MMZE ","M8N9RAXE ","M8N9RAYE ", & + "M8N9RAZE ","M8N9RDXE ","M8N9RDYE ","M8N9RDZE ","M8N9TAXE ","M8N9TAYE ","M8N9TAZE ", & + "M8N9TDXSS","M8N9TDYSS","M8N9TDZSS","M9N1FKXE ","M9N1FKYE ","M9N1FKZE ","M9N1FMXE ", & + "M9N1FMYE ","M9N1FMZE ","M9N1MKXE ","M9N1MKYE ","M9N1MKZE ","M9N1MMXE ","M9N1MMYE ", & + "M9N1MMZE ","M9N1RAXE ","M9N1RAYE ","M9N1RAZE ","M9N1RDXE ","M9N1RDYE ","M9N1RDZE ", & + "M9N1TAXE ","M9N1TAYE ","M9N1TAZE ","M9N1TDXSS","M9N1TDYSS","M9N1TDZSS","M9N2FKXE ", & + "M9N2FKYE ","M9N2FKZE ","M9N2FMXE ","M9N2FMYE ","M9N2FMZE ","M9N2MKXE ","M9N2MKYE ", & + "M9N2MKZE ","M9N2MMXE ","M9N2MMYE ","M9N2MMZE ","M9N2RAXE ","M9N2RAYE ","M9N2RAZE ", & + "M9N2RDXE ","M9N2RDYE ","M9N2RDZE ","M9N2TAXE ","M9N2TAYE ","M9N2TAZE ","M9N2TDXSS", & + "M9N2TDYSS","M9N2TDZSS","M9N3FKXE ","M9N3FKYE ","M9N3FKZE ","M9N3FMXE ","M9N3FMYE ", & + "M9N3FMZE ","M9N3MKXE ","M9N3MKYE ","M9N3MKZE ","M9N3MMXE ","M9N3MMYE ","M9N3MMZE ", & + "M9N3RAXE ","M9N3RAYE ","M9N3RAZE ","M9N3RDXE ","M9N3RDYE ","M9N3RDZE ","M9N3TAXE ", & + "M9N3TAYE ","M9N3TAZE ","M9N3TDXSS","M9N3TDYSS","M9N3TDZSS","M9N4FKXE ","M9N4FKYE ", & + "M9N4FKZE ","M9N4FMXE ","M9N4FMYE ","M9N4FMZE ","M9N4MKXE ","M9N4MKYE ","M9N4MKZE ", & + "M9N4MMXE ","M9N4MMYE ","M9N4MMZE ","M9N4RAXE ","M9N4RAYE ","M9N4RAZE ","M9N4RDXE ", & + "M9N4RDYE ","M9N4RDZE ","M9N4TAXE ","M9N4TAYE ","M9N4TAZE ","M9N4TDXSS","M9N4TDYSS", & + "M9N4TDZSS","M9N5FKXE ","M9N5FKYE ","M9N5FKZE ","M9N5FMXE ","M9N5FMYE ","M9N5FMZE ", & + "M9N5MKXE ","M9N5MKYE ","M9N5MKZE ","M9N5MMXE ","M9N5MMYE ","M9N5MMZE ","M9N5RAXE ", & + "M9N5RAYE ","M9N5RAZE ","M9N5RDXE ","M9N5RDYE ","M9N5RDZE ","M9N5TAXE ","M9N5TAYE ", & + "M9N5TAZE ","M9N5TDXSS","M9N5TDYSS","M9N5TDZSS","M9N6FKXE ","M9N6FKYE ","M9N6FKZE ", & + "M9N6FMXE ","M9N6FMYE ","M9N6FMZE ","M9N6MKXE ","M9N6MKYE ","M9N6MKZE ","M9N6MMXE ", & + "M9N6MMYE ","M9N6MMZE ","M9N6RAXE ","M9N6RAYE ","M9N6RAZE ","M9N6RDXE ","M9N6RDYE ", & + "M9N6RDZE ","M9N6TAXE ","M9N6TAYE ","M9N6TAZE ","M9N6TDXSS","M9N6TDYSS","M9N6TDZSS", & + "M9N7FKXE ","M9N7FKYE ","M9N7FKZE ","M9N7FMXE ","M9N7FMYE ","M9N7FMZE ","M9N7MKXE ", & + "M9N7MKYE ","M9N7MKZE ","M9N7MMXE ","M9N7MMYE ","M9N7MMZE ","M9N7RAXE ","M9N7RAYE ", & + "M9N7RAZE ","M9N7RDXE ","M9N7RDYE ","M9N7RDZE ","M9N7TAXE ","M9N7TAYE ","M9N7TAZE ", & + "M9N7TDXSS","M9N7TDYSS","M9N7TDZSS","M9N8FKXE ","M9N8FKYE ","M9N8FKZE ","M9N8FMXE ", & + "M9N8FMYE ","M9N8FMZE ","M9N8MKXE ","M9N8MKYE ","M9N8MKZE ","M9N8MMXE ","M9N8MMYE ", & + "M9N8MMZE ","M9N8RAXE ","M9N8RAYE ","M9N8RAZE ","M9N8RDXE ","M9N8RDYE ","M9N8RDZE ", & + "M9N8TAXE ","M9N8TAYE ","M9N8TAZE ","M9N8TDXSS","M9N8TDYSS","M9N8TDZSS","M9N9FKXE ", & + "M9N9FKYE ","M9N9FKZE ","M9N9FMXE ","M9N9FMYE ","M9N9FMZE ","M9N9MKXE ","M9N9MKYE ", & + "M9N9MKZE ","M9N9MMXE ","M9N9MMYE ","M9N9MMZE ","M9N9RAXE ","M9N9RAYE ","M9N9RAZE ", & + "M9N9RDXE ","M9N9RDYE ","M9N9RDZE ","M9N9TAXE ","M9N9TAYE ","M9N9TAZE ","M9N9TDXSS", & + "M9N9TDYSS","M9N9TDZSS","REACTFXSS","REACTFYSS","REACTFZSS","REACTMXSS","REACTMYSS", & + "REACTMZSS","SSQM01 ","SSQM02 ","SSQM03 ","SSQM04 ","SSQM05 ","SSQM06 ", & + "SSQM07 ","SSQM08 ","SSQM09 ","SSQM10 ","SSQM11 ","SSQM12 ","SSQM13 ", & + "SSQM14 ","SSQM15 ","SSQM16 ","SSQM17 ","SSQM18 ","SSQM19 ","SSQM20 ", & + "SSQM21 ","SSQM22 ","SSQM23 ","SSQM24 ","SSQM25 ","SSQM26 ","SSQM27 ", & + "SSQM28 ","SSQM29 ","SSQM30 ","SSQM31 ","SSQM32 ","SSQM33 ","SSQM34 ", & + "SSQM35 ","SSQM36 ","SSQM37 ","SSQM38 ","SSQM39 ","SSQM40 ","SSQM41 ", & + "SSQM42 ","SSQM43 ","SSQM44 ","SSQM45 ","SSQM46 ","SSQM47 ","SSQM48 ", & + "SSQM49 ","SSQM50 ","SSQM51 ","SSQM52 ","SSQM53 ","SSQM54 ","SSQM55 ", & + "SSQM56 ","SSQM57 ","SSQM58 ","SSQM59 ","SSQM60 ","SSQM61 ","SSQM62 ", & + "SSQM63 ","SSQM64 ","SSQM65 ","SSQM66 ","SSQM67 ","SSQM68 ","SSQM69 ", & + "SSQM70 ","SSQM71 ","SSQM72 ","SSQM73 ","SSQM74 ","SSQM75 ","SSQM76 ", & + "SSQM77 ","SSQM78 ","SSQM79 ","SSQM80 ","SSQM81 ","SSQM82 ","SSQM83 ", & + "SSQM84 ","SSQM85 ","SSQM86 ","SSQM87 ","SSQM88 ","SSQM89 ","SSQM90 ", & + "SSQM91 ","SSQM92 ","SSQM93 ","SSQM94 ","SSQM95 ","SSQM96 ","SSQM97 ", & + "SSQM98 ","SSQM99 ","SSQMD01 ","SSQMD02 ","SSQMD03 ","SSQMD04 ","SSQMD05 ", & + "SSQMD06 ","SSQMD07 ","SSQMD08 ","SSQMD09 ","SSQMD10 ","SSQMD11 ","SSQMD12 ", & + "SSQMD13 ","SSQMD14 ","SSQMD15 ","SSQMD16 ","SSQMD17 ","SSQMD18 ","SSQMD19 ", & + "SSQMD20 ","SSQMD21 ","SSQMD22 ","SSQMD23 ","SSQMD24 ","SSQMD25 ","SSQMD26 ", & + "SSQMD27 ","SSQMD28 ","SSQMD29 ","SSQMD30 ","SSQMD31 ","SSQMD32 ","SSQMD33 ", & + "SSQMD34 ","SSQMD35 ","SSQMD36 ","SSQMD37 ","SSQMD38 ","SSQMD39 ","SSQMD40 ", & + "SSQMD41 ","SSQMD42 ","SSQMD43 ","SSQMD44 ","SSQMD45 ","SSQMD46 ","SSQMD47 ", & + "SSQMD48 ","SSQMD49 ","SSQMD50 ","SSQMD51 ","SSQMD52 ","SSQMD53 ","SSQMD54 ", & + "SSQMD55 ","SSQMD56 ","SSQMD57 ","SSQMD58 ","SSQMD59 ","SSQMD60 ","SSQMD61 ", & + "SSQMD62 ","SSQMD63 ","SSQMD64 ","SSQMD65 ","SSQMD66 ","SSQMD67 ","SSQMD68 ", & + "SSQMD69 ","SSQMD70 ","SSQMD71 ","SSQMD72 ","SSQMD73 ","SSQMD74 ","SSQMD75 ", & + "SSQMD76 ","SSQMD77 ","SSQMD78 ","SSQMD79 ","SSQMD80 ","SSQMD81 ","SSQMD82 ", & + "SSQMD83 ","SSQMD84 ","SSQMD85 ","SSQMD86 ","SSQMD87 ","SSQMD88 ","SSQMD89 ", & + "SSQMD90 ","SSQMD91 ","SSQMD92 ","SSQMD93 ","SSQMD94 ","SSQMD95 ","SSQMD96 ", & + "SSQMD97 ","SSQMD98 ","SSQMD99 ","SSQMDD01 ","SSQMDD02 ","SSQMDD03 ","SSQMDD04 ", & + "SSQMDD05 ","SSQMDD06 ","SSQMDD07 ","SSQMDD08 ","SSQMDD09 ","SSQMDD10 ","SSQMDD11 ", & + "SSQMDD12 ","SSQMDD13 ","SSQMDD14 ","SSQMDD15 ","SSQMDD16 ","SSQMDD17 ","SSQMDD18 ", & + "SSQMDD19 ","SSQMDD20 ","SSQMDD21 ","SSQMDD22 ","SSQMDD23 ","SSQMDD24 ","SSQMDD25 ", & + "SSQMDD26 ","SSQMDD27 ","SSQMDD28 ","SSQMDD29 ","SSQMDD30 ","SSQMDD31 ","SSQMDD32 ", & + "SSQMDD33 ","SSQMDD34 ","SSQMDD35 ","SSQMDD36 ","SSQMDD37 ","SSQMDD38 ","SSQMDD39 ", & + "SSQMDD40 ","SSQMDD41 ","SSQMDD42 ","SSQMDD43 ","SSQMDD44 ","SSQMDD45 ","SSQMDD46 ", & + "SSQMDD47 ","SSQMDD48 ","SSQMDD49 ","SSQMDD50 ","SSQMDD51 ","SSQMDD52 ","SSQMDD53 ", & + "SSQMDD54 ","SSQMDD55 ","SSQMDD56 ","SSQMDD57 ","SSQMDD58 ","SSQMDD59 ","SSQMDD60 ", & + "SSQMDD61 ","SSQMDD62 ","SSQMDD63 ","SSQMDD64 ","SSQMDD65 ","SSQMDD66 ","SSQMDD67 ", & + "SSQMDD68 ","SSQMDD69 ","SSQMDD70 ","SSQMDD71 ","SSQMDD72 ","SSQMDD73 ","SSQMDD74 ", & + "SSQMDD75 ","SSQMDD76 ","SSQMDD77 ","SSQMDD78 ","SSQMDD79 ","SSQMDD80 ","SSQMDD81 ", & + "SSQMDD82 ","SSQMDD83 ","SSQMDD84 ","SSQMDD85 ","SSQMDD86 ","SSQMDD87 ","SSQMDD88 ", & + "SSQMDD89 ","SSQMDD90 ","SSQMDD91 ","SSQMDD92 ","SSQMDD93 ","SSQMDD94 ","SSQMDD95 ", & + "SSQMDD96 ","SSQMDD97 ","SSQMDD98 ","SSQMDD99 "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(2265) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + IntfFXss , IntfFYss , IntfFZss , IntfMXss , IntfMYss , IntfMZss , IntfRAXss , & + IntfRAYss , IntfRAZss , IntfRDXss , IntfRDYss , IntfRDZss , IntfTAXss , IntfTAYss , & + IntfTAZss , IntfTDXss , IntfTDYss , IntfTDZss , M1N1FKxe , M1N1FKye , M1N1FKze , & + M1N1FMxe , M1N1FMye , M1N1FMze , M1N1MKxe , M1N1MKye , M1N1MKze , M1N1MMxe , & + M1N1MMye , M1N1MMze , M1N1RAxe , M1N1RAye , M1N1RAze , M1N1RDxe , M1N1RDye , & + M1N1RDze , M1N1TAxe , M1N1TAye , M1N1TAze , M1N1TDxss , M1N1TDyss , M1N1TDzss , & + M1N2FKxe , M1N2FKye , M1N2FKze , M1N2FMxe , M1N2FMye , M1N2FMze , M1N2MKxe , & + M1N2MKye , M1N2MKze , M1N2MMxe , M1N2MMye , M1N2MMze , M1N2RAxe , M1N2RAye , & + M1N2RAze , M1N2RDxe , M1N2RDye , M1N2RDze , M1N2TAxe , M1N2TAye , M1N2TAze , & + M1N2TDxss , M1N2TDyss , M1N2TDzss , M1N3FKxe , M1N3FKye , M1N3FKze , M1N3FMxe , & + M1N3FMye , M1N3FMze , M1N3MKxe , M1N3MKye , M1N3MKze , M1N3MMxe , M1N3MMye , & + M1N3MMze , M1N3RAxe , M1N3RAye , M1N3RAze , M1N3RDxe , M1N3RDye , M1N3RDze , & + M1N3TAxe , M1N3TAye , M1N3TAze , M1N3TDxss , M1N3TDyss , M1N3TDzss , M1N4FKxe , & + M1N4FKye , M1N4FKze , M1N4FMxe , M1N4FMye , M1N4FMze , M1N4MKxe , M1N4MKye , & + M1N4MKze , M1N4MMxe , M1N4MMye , M1N4MMze , M1N4RAxe , M1N4RAye , M1N4RAze , & + M1N4RDxe , M1N4RDye , M1N4RDze , M1N4TAxe , M1N4TAye , M1N4TAze , M1N4TDxss , & + M1N4TDyss , M1N4TDzss , M1N5FKxe , M1N5FKye , M1N5FKze , M1N5FMxe , M1N5FMye , & + M1N5FMze , M1N5MKxe , M1N5MKye , M1N5MKze , M1N5MMxe , M1N5MMye , M1N5MMze , & + M1N5RAxe , M1N5RAye , M1N5RAze , M1N5RDxe , M1N5RDye , M1N5RDze , M1N5TAxe , & + M1N5TAye , M1N5TAze , M1N5TDxss , M1N5TDyss , M1N5TDzss , M1N6FKxe , M1N6FKye , & + M1N6FKze , M1N6FMxe , M1N6FMye , M1N6FMze , M1N6MKxe , M1N6MKye , M1N6MKze , & + M1N6MMxe , M1N6MMye , M1N6MMze , M1N6RAxe , M1N6RAye , M1N6RAze , M1N6RDxe , & + M1N6RDye , M1N6RDze , M1N6TAxe , M1N6TAye , M1N6TAze , M1N6TDxss , M1N6TDyss , & + M1N6TDzss , M1N7FKxe , M1N7FKye , M1N7FKze , M1N7FMxe , M1N7FMye , M1N7FMze , & + M1N7MKxe , M1N7MKye , M1N7MKze , M1N7MMxe , M1N7MMye , M1N7MMze , M1N7RAxe , & + M1N7RAye , M1N7RAze , M1N7RDxe , M1N7RDye , M1N7RDze , M1N7TAxe , M1N7TAye , & + M1N7TAze , M1N7TDxss , M1N7TDyss , M1N7TDzss , M1N8FKxe , M1N8FKye , M1N8FKze , & + M1N8FMxe , M1N8FMye , M1N8FMze , M1N8MKxe , M1N8MKye , M1N8MKze , M1N8MMxe , & + M1N8MMye , M1N8MMze , M1N8RAxe , M1N8RAye , M1N8RAze , M1N8RDxe , M1N8RDye , & + M1N8RDze , M1N8TAxe , M1N8TAye , M1N8TAze , M1N8TDxss , M1N8TDyss , M1N8TDzss , & + M1N9FKxe , M1N9FKye , M1N9FKze , M1N9FMxe , M1N9FMye , M1N9FMze , M1N9MKxe , & + M1N9MKye , M1N9MKze , M1N9MMxe , M1N9MMye , M1N9MMze , M1N9RAxe , M1N9RAye , & + M1N9RAze , M1N9RDxe , M1N9RDye , M1N9RDze , M1N9TAxe , M1N9TAye , M1N9TAze , & + M1N9TDxss , M1N9TDyss , M1N9TDzss , M2N1FKxe , M2N1FKye , M2N1FKze , M2N1FMxe , & + M2N1FMye , M2N1FMze , M2N1MKxe , M2N1MKye , M2N1MKze , M2N1MMxe , M2N1MMye , & + M2N1MMze , M2N1RAxe , M2N1RAye , M2N1RAze , M2N1RDxe , M2N1RDye , M2N1RDze , & + M2N1TAxe , M2N1TAye , M2N1TAze , M2N1TDxss , M2N1TDyss , M2N1TDzss , M2N2FKxe , & + M2N2FKye , M2N2FKze , M2N2FMxe , M2N2FMye , M2N2FMze , M2N2MKxe , M2N2MKye , & + M2N2MKze , M2N2MMxe , M2N2MMye , M2N2MMze , M2N2RAxe , M2N2RAye , M2N2RAze , & + M2N2RDxe , M2N2RDye , M2N2RDze , M2N2TAxe , M2N2TAye , M2N2TAze , M2N2TDxss , & + M2N2TDyss , M2N2TDzss , M2N3FKxe , M2N3FKye , M2N3FKze , M2N3FMxe , M2N3FMye , & + M2N3FMze , M2N3MKxe , M2N3MKye , M2N3MKze , M2N3MMxe , M2N3MMye , M2N3MMze , & + M2N3RAxe , M2N3RAye , M2N3RAze , M2N3RDxe , M2N3RDye , M2N3RDze , M2N3TAxe , & + M2N3TAye , M2N3TAze , M2N3TDxss , M2N3TDyss , M2N3TDzss , M2N4FKxe , M2N4FKye , & + M2N4FKze , M2N4FMxe , M2N4FMye , M2N4FMze , M2N4MKxe , M2N4MKye , M2N4MKze , & + M2N4MMxe , M2N4MMye , M2N4MMze , M2N4RAxe , M2N4RAye , M2N4RAze , M2N4RDxe , & + M2N4RDye , M2N4RDze , M2N4TAxe , M2N4TAye , M2N4TAze , M2N4TDxss , M2N4TDyss , & + M2N4TDzss , M2N5FKxe , M2N5FKye , M2N5FKze , M2N5FMxe , M2N5FMye , M2N5FMze , & + M2N5MKxe , M2N5MKye , M2N5MKze , M2N5MMxe , M2N5MMye , M2N5MMze , M2N5RAxe , & + M2N5RAye , M2N5RAze , M2N5RDxe , M2N5RDye , M2N5RDze , M2N5TAxe , M2N5TAye , & + M2N5TAze , M2N5TDxss , M2N5TDyss , M2N5TDzss , M2N6FKxe , M2N6FKye , M2N6FKze , & + M2N6FMxe , M2N6FMye , M2N6FMze , M2N6MKxe , M2N6MKye , M2N6MKze , M2N6MMxe , & + M2N6MMye , M2N6MMze , M2N6RAxe , M2N6RAye , M2N6RAze , M2N6RDxe , M2N6RDye , & + M2N6RDze , M2N6TAxe , M2N6TAye , M2N6TAze , M2N6TDxss , M2N6TDyss , M2N6TDzss , & + M2N7FKxe , M2N7FKye , M2N7FKze , M2N7FMxe , M2N7FMye , M2N7FMze , M2N7MKxe , & + M2N7MKye , M2N7MKze , M2N7MMxe , M2N7MMye , M2N7MMze , M2N7RAxe , M2N7RAye , & + M2N7RAze , M2N7RDxe , M2N7RDye , M2N7RDze , M2N7TAxe , M2N7TAye , M2N7TAze , & + M2N7TDxss , M2N7TDyss , M2N7TDzss , M2N8FKxe , M2N8FKye , M2N8FKze , M2N8FMxe , & + M2N8FMye , M2N8FMze , M2N8MKxe , M2N8MKye , M2N8MKze , M2N8MMxe , M2N8MMye , & + M2N8MMze , M2N8RAxe , M2N8RAye , M2N8RAze , M2N8RDxe , M2N8RDye , M2N8RDze , & + M2N8TAxe , M2N8TAye , M2N8TAze , M2N8TDxss , M2N8TDyss , M2N8TDzss , M2N9FKxe , & + M2N9FKye , M2N9FKze , M2N9FMxe , M2N9FMye , M2N9FMze , M2N9MKxe , M2N9MKye , & + M2N9MKze , M2N9MMxe , M2N9MMye , M2N9MMze , M2N9RAxe , M2N9RAye , M2N9RAze , & + M2N9RDxe , M2N9RDye , M2N9RDze , M2N9TAxe , M2N9TAye , M2N9TAze , M2N9TDxss , & + M2N9TDyss , M2N9TDzss , M3N1FKxe , M3N1FKye , M3N1FKze , M3N1FMxe , M3N1FMye , & + M3N1FMze , M3N1MKxe , M3N1MKye , M3N1MKze , M3N1MMxe , M3N1MMye , M3N1MMze , & + M3N1RAxe , M3N1RAye , M3N1RAze , M3N1RDxe , M3N1RDye , M3N1RDze , M3N1TAxe , & + M3N1TAye , M3N1TAze , M3N1TDxss , M3N1TDyss , M3N1TDzss , M3N2FKxe , M3N2FKye , & + M3N2FKze , M3N2FMxe , M3N2FMye , M3N2FMze , M3N2MKxe , M3N2MKye , M3N2MKze , & + M3N2MMxe , M3N2MMye , M3N2MMze , M3N2RAxe , M3N2RAye , M3N2RAze , M3N2RDxe , & + M3N2RDye , M3N2RDze , M3N2TAxe , M3N2TAye , M3N2TAze , M3N2TDxss , M3N2TDyss , & + M3N2TDzss , M3N3FKxe , M3N3FKye , M3N3FKze , M3N3FMxe , M3N3FMye , M3N3FMze , & + M3N3MKxe , M3N3MKye , M3N3MKze , M3N3MMxe , M3N3MMye , M3N3MMze , M3N3RAxe , & + M3N3RAye , M3N3RAze , M3N3RDxe , M3N3RDye , M3N3RDze , M3N3TAxe , M3N3TAye , & + M3N3TAze , M3N3TDxss , M3N3TDyss , M3N3TDzss , M3N4FKxe , M3N4FKye , M3N4FKze , & + M3N4FMxe , M3N4FMye , M3N4FMze , M3N4MKxe , M3N4MKye , M3N4MKze , M3N4MMxe , & + M3N4MMye , M3N4MMze , M3N4RAxe , M3N4RAye , M3N4RAze , M3N4RDxe , M3N4RDye , & + M3N4RDze , M3N4TAxe , M3N4TAye , M3N4TAze , M3N4TDxss , M3N4TDyss , M3N4TDzss , & + M3N5FKxe , M3N5FKye , M3N5FKze , M3N5FMxe , M3N5FMye , M3N5FMze , M3N5MKxe , & + M3N5MKye , M3N5MKze , M3N5MMxe , M3N5MMye , M3N5MMze , M3N5RAxe , M3N5RAye , & + M3N5RAze , M3N5RDxe , M3N5RDye , M3N5RDze , M3N5TAxe , M3N5TAye , M3N5TAze , & + M3N5TDxss , M3N5TDyss , M3N5TDzss , M3N6FKxe , M3N6FKye , M3N6FKze , M3N6FMxe , & + M3N6FMye , M3N6FMze , M3N6MKxe , M3N6MKye , M3N6MKze , M3N6MMxe , M3N6MMye , & + M3N6MMze , M3N6RAxe , M3N6RAye , M3N6RAze , M3N6RDxe , M3N6RDye , M3N6RDze , & + M3N6TAxe , M3N6TAye , M3N6TAze , M3N6TDxss , M3N6TDyss , M3N6TDzss , M3N7FKxe , & + M3N7FKye , M3N7FKze , M3N7FMxe , M3N7FMye , M3N7FMze , M3N7MKxe , M3N7MKye , & + M3N7MKze , M3N7MMxe , M3N7MMye , M3N7MMze , M3N7RAxe , M3N7RAye , M3N7RAze , & + M3N7RDxe , M3N7RDye , M3N7RDze , M3N7TAxe , M3N7TAye , M3N7TAze , M3N7TDxss , & + M3N7TDyss , M3N7TDzss , M3N8FKxe , M3N8FKye , M3N8FKze , M3N8FMxe , M3N8FMye , & + M3N8FMze , M3N8MKxe , M3N8MKye , M3N8MKze , M3N8MMxe , M3N8MMye , M3N8MMze , & + M3N8RAxe , M3N8RAye , M3N8RAze , M3N8RDxe , M3N8RDye , M3N8RDze , M3N8TAxe , & + M3N8TAye , M3N8TAze , M3N8TDxss , M3N8TDyss , M3N8TDzss , M3N9FKxe , M3N9FKye , & + M3N9FKze , M3N9FMxe , M3N9FMye , M3N9FMze , M3N9MKxe , M3N9MKye , M3N9MKze , & + M3N9MMxe , M3N9MMye , M3N9MMze , M3N9RAxe , M3N9RAye , M3N9RAze , M3N9RDxe , & + M3N9RDye , M3N9RDze , M3N9TAxe , M3N9TAye , M3N9TAze , M3N9TDxss , M3N9TDyss , & + M3N9TDzss , M4N1FKxe , M4N1FKye , M4N1FKze , M4N1FMxe , M4N1FMye , M4N1FMze , & + M4N1MKxe , M4N1MKye , M4N1MKze , M4N1MMxe , M4N1MMye , M4N1MMze , M4N1RAxe , & + M4N1RAye , M4N1RAze , M4N1RDxe , M4N1RDye , M4N1RDze , M4N1TAxe , M4N1TAye , & + M4N1TAze , M4N1TDxss , M4N1TDyss , M4N1TDzss , M4N2FKxe , M4N2FKye , M4N2FKze , & + M4N2FMxe , M4N2FMye , M4N2FMze , M4N2MKxe , M4N2MKye , M4N2MKze , M4N2MMxe , & + M4N2MMye , M4N2MMze , M4N2RAxe , M4N2RAye , M4N2RAze , M4N2RDxe , M4N2RDye , & + M4N2RDze , M4N2TAxe , M4N2TAye , M4N2TAze , M4N2TDxss , M4N2TDyss , M4N2TDzss , & + M4N3FKxe , M4N3FKye , M4N3FKze , M4N3FMxe , M4N3FMye , M4N3FMze , M4N3MKxe , & + M4N3MKye , M4N3MKze , M4N3MMxe , M4N3MMye , M4N3MMze , M4N3RAxe , M4N3RAye , & + M4N3RAze , M4N3RDxe , M4N3RDye , M4N3RDze , M4N3TAxe , M4N3TAye , M4N3TAze , & + M4N3TDxss , M4N3TDyss , M4N3TDzss , M4N4FKxe , M4N4FKye , M4N4FKze , M4N4FMxe , & + M4N4FMye , M4N4FMze , M4N4MKxe , M4N4MKye , M4N4MKze , M4N4MMxe , M4N4MMye , & + M4N4MMze , M4N4RAxe , M4N4RAye , M4N4RAze , M4N4RDxe , M4N4RDye , M4N4RDze , & + M4N4TAxe , M4N4TAye , M4N4TAze , M4N4TDxss , M4N4TDyss , M4N4TDzss , M4N5FKxe , & + M4N5FKye , M4N5FKze , M4N5FMxe , M4N5FMye , M4N5FMze , M4N5MKxe , M4N5MKye , & + M4N5MKze , M4N5MMxe , M4N5MMye , M4N5MMze , M4N5RAxe , M4N5RAye , M4N5RAze , & + M4N5RDxe , M4N5RDye , M4N5RDze , M4N5TAxe , M4N5TAye , M4N5TAze , M4N5TDxss , & + M4N5TDyss , M4N5TDzss , M4N6FKxe , M4N6FKye , M4N6FKze , M4N6FMxe , M4N6FMye , & + M4N6FMze , M4N6MKxe , M4N6MKye , M4N6MKze , M4N6MMxe , M4N6MMye , M4N6MMze , & + M4N6RAxe , M4N6RAye , M4N6RAze , M4N6RDxe , M4N6RDye , M4N6RDze , M4N6TAxe , & + M4N6TAye , M4N6TAze , M4N6TDxss , M4N6TDyss , M4N6TDzss , M4N7FKxe , M4N7FKye , & + M4N7FKze , M4N7FMxe , M4N7FMye , M4N7FMze , M4N7MKxe , M4N7MKye , M4N7MKze , & + M4N7MMxe , M4N7MMye , M4N7MMze , M4N7RAxe , M4N7RAye , M4N7RAze , M4N7RDxe , & + M4N7RDye , M4N7RDze , M4N7TAxe , M4N7TAye , M4N7TAze , M4N7TDxss , M4N7TDyss , & + M4N7TDzss , M4N8FKxe , M4N8FKye , M4N8FKze , M4N8FMxe , M4N8FMye , M4N8FMze , & + M4N8MKxe , M4N8MKye , M4N8MKze , M4N8MMxe , M4N8MMye , M4N8MMze , M4N8RAxe , & + M4N8RAye , M4N8RAze , M4N8RDxe , M4N8RDye , M4N8RDze , M4N8TAxe , M4N8TAye , & + M4N8TAze , M4N8TDxss , M4N8TDyss , M4N8TDzss , M4N9FKxe , M4N9FKye , M4N9FKze , & + M4N9FMxe , M4N9FMye , M4N9FMze , M4N9MKxe , M4N9MKye , M4N9MKze , M4N9MMxe , & + M4N9MMye , M4N9MMze , M4N9RAxe , M4N9RAye , M4N9RAze , M4N9RDxe , M4N9RDye , & + M4N9RDze , M4N9TAxe , M4N9TAye , M4N9TAze , M4N9TDxss , M4N9TDyss , M4N9TDzss , & + M5N1FKxe , M5N1FKye , M5N1FKze , M5N1FMxe , M5N1FMye , M5N1FMze , M5N1MKxe , & + M5N1MKye , M5N1MKze , M5N1MMxe , M5N1MMye , M5N1MMze , M5N1RAxe , M5N1RAye , & + M5N1RAze , M5N1RDxe , M5N1RDye , M5N1RDze , M5N1TAxe , M5N1TAye , M5N1TAze , & + M5N1TDxss , M5N1TDyss , M5N1TDzss , M5N2FKxe , M5N2FKye , M5N2FKze , M5N2FMxe , & + M5N2FMye , M5N2FMze , M5N2MKxe , M5N2MKye , M5N2MKze , M5N2MMxe , M5N2MMye , & + M5N2MMze , M5N2RAxe , M5N2RAye , M5N2RAze , M5N2RDxe , M5N2RDye , M5N2RDze , & + M5N2TAxe , M5N2TAye , M5N2TAze , M5N2TDxss , M5N2TDyss , M5N2TDzss , M5N3FKxe , & + M5N3FKye , M5N3FKze , M5N3FMxe , M5N3FMye , M5N3FMze , M5N3MKxe , M5N3MKye , & + M5N3MKze , M5N3MMxe , M5N3MMye , M5N3MMze , M5N3RAxe , M5N3RAye , M5N3RAze , & + M5N3RDxe , M5N3RDye , M5N3RDze , M5N3TAxe , M5N3TAye , M5N3TAze , M5N3TDxss , & + M5N3TDyss , M5N3TDzss , M5N4FKxe , M5N4FKye , M5N4FKze , M5N4FMxe , M5N4FMye , & + M5N4FMze , M5N4MKxe , M5N4MKye , M5N4MKze , M5N4MMxe , M5N4MMye , M5N4MMze , & + M5N4RAxe , M5N4RAye , M5N4RAze , M5N4RDxe , M5N4RDye , M5N4RDze , M5N4TAxe , & + M5N4TAye , M5N4TAze , M5N4TDxss , M5N4TDyss , M5N4TDzss , M5N5FKxe , M5N5FKye , & + M5N5FKze , M5N5FMxe , M5N5FMye , M5N5FMze , M5N5MKxe , M5N5MKye , M5N5MKze , & + M5N5MMxe , M5N5MMye , M5N5MMze , M5N5RAxe , M5N5RAye , M5N5RAze , M5N5RDxe , & + M5N5RDye , M5N5RDze , M5N5TAxe , M5N5TAye , M5N5TAze , M5N5TDxss , M5N5TDyss , & + M5N5TDzss , M5N6FKxe , M5N6FKye , M5N6FKze , M5N6FMxe , M5N6FMye , M5N6FMze , & + M5N6MKxe , M5N6MKye , M5N6MKze , M5N6MMxe , M5N6MMye , M5N6MMze , M5N6RAxe , & + M5N6RAye , M5N6RAze , M5N6RDxe , M5N6RDye , M5N6RDze , M5N6TAxe , M5N6TAye , & + M5N6TAze , M5N6TDxss , M5N6TDyss , M5N6TDzss , M5N7FKxe , M5N7FKye , M5N7FKze , & + M5N7FMxe , M5N7FMye , M5N7FMze , M5N7MKxe , M5N7MKye , M5N7MKze , M5N7MMxe , & + M5N7MMye , M5N7MMze , M5N7RAxe , M5N7RAye , M5N7RAze , M5N7RDxe , M5N7RDye , & + M5N7RDze , M5N7TAxe , M5N7TAye , M5N7TAze , M5N7TDxss , M5N7TDyss , M5N7TDzss , & + M5N8FKxe , M5N8FKye , M5N8FKze , M5N8FMxe , M5N8FMye , M5N8FMze , M5N8MKxe , & + M5N8MKye , M5N8MKze , M5N8MMxe , M5N8MMye , M5N8MMze , M5N8RAxe , M5N8RAye , & + M5N8RAze , M5N8RDxe , M5N8RDye , M5N8RDze , M5N8TAxe , M5N8TAye , M5N8TAze , & + M5N8TDxss , M5N8TDyss , M5N8TDzss , M5N9FKxe , M5N9FKye , M5N9FKze , M5N9FMxe , & + M5N9FMye , M5N9FMze , M5N9MKxe , M5N9MKye , M5N9MKze , M5N9MMxe , M5N9MMye , & + M5N9MMze , M5N9RAxe , M5N9RAye , M5N9RAze , M5N9RDxe , M5N9RDye , M5N9RDze , & + M5N9TAxe , M5N9TAye , M5N9TAze , M5N9TDxss , M5N9TDyss , M5N9TDzss , M6N1FKxe , & + M6N1FKye , M6N1FKze , M6N1FMxe , M6N1FMye , M6N1FMze , M6N1MKxe , M6N1MKye , & + M6N1MKze , M6N1MMxe , M6N1MMye , M6N1MMze , M6N1RAxe , M6N1RAye , M6N1RAze , & + M6N1RDxe , M6N1RDye , M6N1RDze , M6N1TAxe , M6N1TAye , M6N1TAze , M6N1TDxss , & + M6N1TDyss , M6N1TDzss , M6N2FKxe , M6N2FKye , M6N2FKze , M6N2FMxe , M6N2FMye , & + M6N2FMze , M6N2MKxe , M6N2MKye , M6N2MKze , M6N2MMxe , M6N2MMye , M6N2MMze , & + M6N2RAxe , M6N2RAye , M6N2RAze , M6N2RDxe , M6N2RDye , M6N2RDze , M6N2TAxe , & + M6N2TAye , M6N2TAze , M6N2TDxss , M6N2TDyss , M6N2TDzss , M6N3FKxe , M6N3FKye , & + M6N3FKze , M6N3FMxe , M6N3FMye , M6N3FMze , M6N3MKxe , M6N3MKye , M6N3MKze , & + M6N3MMxe , M6N3MMye , M6N3MMze , M6N3RAxe , M6N3RAye , M6N3RAze , M6N3RDxe , & + M6N3RDye , M6N3RDze , M6N3TAxe , M6N3TAye , M6N3TAze , M6N3TDxss , M6N3TDyss , & + M6N3TDzss , M6N4FKxe , M6N4FKye , M6N4FKze , M6N4FMxe , M6N4FMye , M6N4FMze , & + M6N4MKxe , M6N4MKye , M6N4MKze , M6N4MMxe , M6N4MMye , M6N4MMze , M6N4RAxe , & + M6N4RAye , M6N4RAze , M6N4RDxe , M6N4RDye , M6N4RDze , M6N4TAxe , M6N4TAye , & + M6N4TAze , M6N4TDxss , M6N4TDyss , M6N4TDzss , M6N5FKxe , M6N5FKye , M6N5FKze , & + M6N5FMxe , M6N5FMye , M6N5FMze , M6N5MKxe , M6N5MKye , M6N5MKze , M6N5MMxe , & + M6N5MMye , M6N5MMze , M6N5RAxe , M6N5RAye , M6N5RAze , M6N5RDxe , M6N5RDye , & + M6N5RDze , M6N5TAxe , M6N5TAye , M6N5TAze , M6N5TDxss , M6N5TDyss , M6N5TDzss , & + M6N6FKxe , M6N6FKye , M6N6FKze , M6N6FMxe , M6N6FMye , M6N6FMze , M6N6MKxe , & + M6N6MKye , M6N6MKze , M6N6MMxe , M6N6MMye , M6N6MMze , M6N6RAxe , M6N6RAye , & + M6N6RAze , M6N6RDxe , M6N6RDye , M6N6RDze , M6N6TAxe , M6N6TAye , M6N6TAze , & + M6N6TDxss , M6N6TDyss , M6N6TDzss , M6N7FKxe , M6N7FKye , M6N7FKze , M6N7FMxe , & + M6N7FMye , M6N7FMze , M6N7MKxe , M6N7MKye , M6N7MKze , M6N7MMxe , M6N7MMye , & + M6N7MMze , M6N7RAxe , M6N7RAye , M6N7RAze , M6N7RDxe , M6N7RDye , M6N7RDze , & + M6N7TAxe , M6N7TAye , M6N7TAze , M6N7TDxss , M6N7TDyss , M6N7TDzss , M6N8FKxe , & + M6N8FKye , M6N8FKze , M6N8FMxe , M6N8FMye , M6N8FMze , M6N8MKxe , M6N8MKye , & + M6N8MKze , M6N8MMxe , M6N8MMye , M6N8MMze , M6N8RAxe , M6N8RAye , M6N8RAze , & + M6N8RDxe , M6N8RDye , M6N8RDze , M6N8TAxe , M6N8TAye , M6N8TAze , M6N8TDxss , & + M6N8TDyss , M6N8TDzss , M6N9FKxe , M6N9FKye , M6N9FKze , M6N9FMxe , M6N9FMye , & + M6N9FMze , M6N9MKxe , M6N9MKye , M6N9MKze , M6N9MMxe , M6N9MMye , M6N9MMze , & + M6N9RAxe , M6N9RAye , M6N9RAze , M6N9RDxe , M6N9RDye , M6N9RDze , M6N9TAxe , & + M6N9TAye , M6N9TAze , M6N9TDxss , M6N9TDyss , M6N9TDzss , M7N1FKxe , M7N1FKye , & + M7N1FKze , M7N1FMxe , M7N1FMye , M7N1FMze , M7N1MKxe , M7N1MKye , M7N1MKze , & + M7N1MMxe , M7N1MMye , M7N1MMze , M7N1RAxe , M7N1RAye , M7N1RAze , M7N1RDxe , & + M7N1RDye , M7N1RDze , M7N1TAxe , M7N1TAye , M7N1TAze , M7N1TDxss , M7N1TDyss , & + M7N1TDzss , M7N2FKxe , M7N2FKye , M7N2FKze , M7N2FMxe , M7N2FMye , M7N2FMze , & + M7N2MKxe , M7N2MKye , M7N2MKze , M7N2MMxe , M7N2MMye , M7N2MMze , M7N2RAxe , & + M7N2RAye , M7N2RAze , M7N2RDxe , M7N2RDye , M7N2RDze , M7N2TAxe , M7N2TAye , & + M7N2TAze , M7N2TDxss , M7N2TDyss , M7N2TDzss , M7N3FKxe , M7N3FKye , M7N3FKze , & + M7N3FMxe , M7N3FMye , M7N3FMze , M7N3MKxe , M7N3MKye , M7N3MKze , M7N3MMxe , & + M7N3MMye , M7N3MMze , M7N3RAxe , M7N3RAye , M7N3RAze , M7N3RDxe , M7N3RDye , & + M7N3RDze , M7N3TAxe , M7N3TAye , M7N3TAze , M7N3TDxss , M7N3TDyss , M7N3TDzss , & + M7N4FKxe , M7N4FKye , M7N4FKze , M7N4FMxe , M7N4FMye , M7N4FMze , M7N4MKxe , & + M7N4MKye , M7N4MKze , M7N4MMxe , M7N4MMye , M7N4MMze , M7N4RAxe , M7N4RAye , & + M7N4RAze , M7N4RDxe , M7N4RDye , M7N4RDze , M7N4TAxe , M7N4TAye , M7N4TAze , & + M7N4TDxss , M7N4TDyss , M7N4TDzss , M7N5FKxe , M7N5FKye , M7N5FKze , M7N5FMxe , & + M7N5FMye , M7N5FMze , M7N5MKxe , M7N5MKye , M7N5MKze , M7N5MMxe , M7N5MMye , & + M7N5MMze , M7N5RAxe , M7N5RAye , M7N5RAze , M7N5RDxe , M7N5RDye , M7N5RDze , & + M7N5TAxe , M7N5TAye , M7N5TAze , M7N5TDxss , M7N5TDyss , M7N5TDzss , M7N6FKxe , & + M7N6FKye , M7N6FKze , M7N6FMxe , M7N6FMye , M7N6FMze , M7N6MKxe , M7N6MKye , & + M7N6MKze , M7N6MMxe , M7N6MMye , M7N6MMze , M7N6RAxe , M7N6RAye , M7N6RAze , & + M7N6RDxe , M7N6RDye , M7N6RDze , M7N6TAxe , M7N6TAye , M7N6TAze , M7N6TDxss , & + M7N6TDyss , M7N6TDzss , M7N7FKxe , M7N7FKye , M7N7FKze , M7N7FMxe , M7N7FMye , & + M7N7FMze , M7N7MKxe , M7N7MKye , M7N7MKze , M7N7MMxe , M7N7MMye , M7N7MMze , & + M7N7RAxe , M7N7RAye , M7N7RAze , M7N7RDxe , M7N7RDye , M7N7RDze , M7N7TAxe , & + M7N7TAye , M7N7TAze , M7N7TDxss , M7N7TDyss , M7N7TDzss , M7N8FKxe , M7N8FKye , & + M7N8FKze , M7N8FMxe , M7N8FMye , M7N8FMze , M7N8MKxe , M7N8MKye , M7N8MKze , & + M7N8MMxe , M7N8MMye , M7N8MMze , M7N8RAxe , M7N8RAye , M7N8RAze , M7N8RDxe , & + M7N8RDye , M7N8RDze , M7N8TAxe , M7N8TAye , M7N8TAze , M7N8TDxss , M7N8TDyss , & + M7N8TDzss , M7N9FKxe , M7N9FKye , M7N9FKze , M7N9FMxe , M7N9FMye , M7N9FMze , & + M7N9MKxe , M7N9MKye , M7N9MKze , M7N9MMxe , M7N9MMye , M7N9MMze , M7N9RAxe , & + M7N9RAye , M7N9RAze , M7N9RDxe , M7N9RDye , M7N9RDze , M7N9TAxe , M7N9TAye , & + M7N9TAze , M7N9TDxss , M7N9TDyss , M7N9TDzss , M8N1FKxe , M8N1FKye , M8N1FKze , & + M8N1FMxe , M8N1FMye , M8N1FMze , M8N1MKxe , M8N1MKye , M8N1MKze , M8N1MMxe , & + M8N1MMye , M8N1MMze , M8N1RAxe , M8N1RAye , M8N1RAze , M8N1RDxe , M8N1RDye , & + M8N1RDze , M8N1TAxe , M8N1TAye , M8N1TAze , M8N1TDxss , M8N1TDyss , M8N1TDzss , & + M8N2FKxe , M8N2FKye , M8N2FKze , M8N2FMxe , M8N2FMye , M8N2FMze , M8N2MKxe , & + M8N2MKye , M8N2MKze , M8N2MMxe , M8N2MMye , M8N2MMze , M8N2RAxe , M8N2RAye , & + M8N2RAze , M8N2RDxe , M8N2RDye , M8N2RDze , M8N2TAxe , M8N2TAye , M8N2TAze , & + M8N2TDxss , M8N2TDyss , M8N2TDzss , M8N3FKxe , M8N3FKye , M8N3FKze , M8N3FMxe , & + M8N3FMye , M8N3FMze , M8N3MKxe , M8N3MKye , M8N3MKze , M8N3MMxe , M8N3MMye , & + M8N3MMze , M8N3RAxe , M8N3RAye , M8N3RAze , M8N3RDxe , M8N3RDye , M8N3RDze , & + M8N3TAxe , M8N3TAye , M8N3TAze , M8N3TDxss , M8N3TDyss , M8N3TDzss , M8N4FKxe , & + M8N4FKye , M8N4FKze , M8N4FMxe , M8N4FMye , M8N4FMze , M8N4MKxe , M8N4MKye , & + M8N4MKze , M8N4MMxe , M8N4MMye , M8N4MMze , M8N4RAxe , M8N4RAye , M8N4RAze , & + M8N4RDxe , M8N4RDye , M8N4RDze , M8N4TAxe , M8N4TAye , M8N4TAze , M8N4TDxss , & + M8N4TDyss , M8N4TDzss , M8N5FKxe , M8N5FKye , M8N5FKze , M8N5FMxe , M8N5FMye , & + M8N5FMze , M8N5MKxe , M8N5MKye , M8N5MKze , M8N5MMxe , M8N5MMye , M8N5MMze , & + M8N5RAxe , M8N5RAye , M8N5RAze , M8N5RDxe , M8N5RDye , M8N5RDze , M8N5TAxe , & + M8N5TAye , M8N5TAze , M8N5TDxss , M8N5TDyss , M8N5TDzss , M8N6FKxe , M8N6FKye , & + M8N6FKze , M8N6FMxe , M8N6FMye , M8N6FMze , M8N6MKxe , M8N6MKye , M8N6MKze , & + M8N6MMxe , M8N6MMye , M8N6MMze , M8N6RAxe , M8N6RAye , M8N6RAze , M8N6RDxe , & + M8N6RDye , M8N6RDze , M8N6TAxe , M8N6TAye , M8N6TAze , M8N6TDxss , M8N6TDyss , & + M8N6TDzss , M8N7FKxe , M8N7FKye , M8N7FKze , M8N7FMxe , M8N7FMye , M8N7FMze , & + M8N7MKxe , M8N7MKye , M8N7MKze , M8N7MMxe , M8N7MMye , M8N7MMze , M8N7RAxe , & + M8N7RAye , M8N7RAze , M8N7RDxe , M8N7RDye , M8N7RDze , M8N7TAxe , M8N7TAye , & + M8N7TAze , M8N7TDxss , M8N7TDyss , M8N7TDzss , M8N8FKxe , M8N8FKye , M8N8FKze , & + M8N8FMxe , M8N8FMye , M8N8FMze , M8N8MKxe , M8N8MKye , M8N8MKze , M8N8MMxe , & + M8N8MMye , M8N8MMze , M8N8RAxe , M8N8RAye , M8N8RAze , M8N8RDxe , M8N8RDye , & + M8N8RDze , M8N8TAxe , M8N8TAye , M8N8TAze , M8N8TDxss , M8N8TDyss , M8N8TDzss , & + M8N9FKxe , M8N9FKye , M8N9FKze , M8N9FMxe , M8N9FMye , M8N9FMze , M8N9MKxe , & + M8N9MKye , M8N9MKze , M8N9MMxe , M8N9MMye , M8N9MMze , M8N9RAxe , M8N9RAye , & + M8N9RAze , M8N9RDxe , M8N9RDye , M8N9RDze , M8N9TAxe , M8N9TAye , M8N9TAze , & + M8N9TDxss , M8N9TDyss , M8N9TDzss , M9N1FKxe , M9N1FKye , M9N1FKze , M9N1FMxe , & + M9N1FMye , M9N1FMze , M9N1MKxe , M9N1MKye , M9N1MKze , M9N1MMxe , M9N1MMye , & + M9N1MMze , M9N1RAxe , M9N1RAye , M9N1RAze , M9N1RDxe , M9N1RDye , M9N1RDze , & + M9N1TAxe , M9N1TAye , M9N1TAze , M9N1TDxss , M9N1TDyss , M9N1TDzss , M9N2FKxe , & + M9N2FKye , M9N2FKze , M9N2FMxe , M9N2FMye , M9N2FMze , M9N2MKxe , M9N2MKye , & + M9N2MKze , M9N2MMxe , M9N2MMye , M9N2MMze , M9N2RAxe , M9N2RAye , M9N2RAze , & + M9N2RDxe , M9N2RDye , M9N2RDze , M9N2TAxe , M9N2TAye , M9N2TAze , M9N2TDxss , & + M9N2TDyss , M9N2TDzss , M9N3FKxe , M9N3FKye , M9N3FKze , M9N3FMxe , M9N3FMye , & + M9N3FMze , M9N3MKxe , M9N3MKye , M9N3MKze , M9N3MMxe , M9N3MMye , M9N3MMze , & + M9N3RAxe , M9N3RAye , M9N3RAze , M9N3RDxe , M9N3RDye , M9N3RDze , M9N3TAxe , & + M9N3TAye , M9N3TAze , M9N3TDxss , M9N3TDyss , M9N3TDzss , M9N4FKxe , M9N4FKye , & + M9N4FKze , M9N4FMxe , M9N4FMye , M9N4FMze , M9N4MKxe , M9N4MKye , M9N4MKze , & + M9N4MMxe , M9N4MMye , M9N4MMze , M9N4RAxe , M9N4RAye , M9N4RAze , M9N4RDxe , & + M9N4RDye , M9N4RDze , M9N4TAxe , M9N4TAye , M9N4TAze , M9N4TDxss , M9N4TDyss , & + M9N4TDzss , M9N5FKxe , M9N5FKye , M9N5FKze , M9N5FMxe , M9N5FMye , M9N5FMze , & + M9N5MKxe , M9N5MKye , M9N5MKze , M9N5MMxe , M9N5MMye , M9N5MMze , M9N5RAxe , & + M9N5RAye , M9N5RAze , M9N5RDxe , M9N5RDye , M9N5RDze , M9N5TAxe , M9N5TAye , & + M9N5TAze , M9N5TDxss , M9N5TDyss , M9N5TDzss , M9N6FKxe , M9N6FKye , M9N6FKze , & + M9N6FMxe , M9N6FMye , M9N6FMze , M9N6MKxe , M9N6MKye , M9N6MKze , M9N6MMxe , & + M9N6MMye , M9N6MMze , M9N6RAxe , M9N6RAye , M9N6RAze , M9N6RDxe , M9N6RDye , & + M9N6RDze , M9N6TAxe , M9N6TAye , M9N6TAze , M9N6TDxss , M9N6TDyss , M9N6TDzss , & + M9N7FKxe , M9N7FKye , M9N7FKze , M9N7FMxe , M9N7FMye , M9N7FMze , M9N7MKxe , & + M9N7MKye , M9N7MKze , M9N7MMxe , M9N7MMye , M9N7MMze , M9N7RAxe , M9N7RAye , & + M9N7RAze , M9N7RDxe , M9N7RDye , M9N7RDze , M9N7TAxe , M9N7TAye , M9N7TAze , & + M9N7TDxss , M9N7TDyss , M9N7TDzss , M9N8FKxe , M9N8FKye , M9N8FKze , M9N8FMxe , & + M9N8FMye , M9N8FMze , M9N8MKxe , M9N8MKye , M9N8MKze , M9N8MMxe , M9N8MMye , & + M9N8MMze , M9N8RAxe , M9N8RAye , M9N8RAze , M9N8RDxe , M9N8RDye , M9N8RDze , & + M9N8TAxe , M9N8TAye , M9N8TAze , M9N8TDxss , M9N8TDyss , M9N8TDzss , M9N9FKxe , & + M9N9FKye , M9N9FKze , M9N9FMxe , M9N9FMye , M9N9FMze , M9N9MKxe , M9N9MKye , & + M9N9MKze , M9N9MMxe , M9N9MMye , M9N9MMze , M9N9RAxe , M9N9RAye , M9N9RAze , & + M9N9RDxe , M9N9RDye , M9N9RDze , M9N9TAxe , M9N9TAye , M9N9TAze , M9N9TDxss , & + M9N9TDyss , M9N9TDzss , ReactFXss , ReactFYss , ReactFZss , ReactMXss , ReactMYss , & + ReactMZss , SSqm01 , SSqm02 , SSqm03 , SSqm04 , SSqm05 , SSqm06 , & + SSqm07 , SSqm08 , SSqm09 , SSqm10 , SSqm11 , SSqm12 , SSqm13 , & + SSqm14 , SSqm15 , SSqm16 , SSqm17 , SSqm18 , SSqm19 , SSqm20 , & + SSqm21 , SSqm22 , SSqm23 , SSqm24 , SSqm25 , SSqm26 , SSqm27 , & + SSqm28 , SSqm29 , SSqm30 , SSqm31 , SSqm32 , SSqm33 , SSqm34 , & + SSqm35 , SSqm36 , SSqm37 , SSqm38 , SSqm39 , SSqm40 , SSqm41 , & + SSqm42 , SSqm43 , SSqm44 , SSqm45 , SSqm46 , SSqm47 , SSqm48 , & + SSqm49 , SSqm50 , SSqm51 , SSqm52 , SSqm53 , SSqm54 , SSqm55 , & + SSqm56 , SSqm57 , SSqm58 , SSqm59 , SSqm60 , SSqm61 , SSqm62 , & + SSqm63 , SSqm64 , SSqm65 , SSqm66 , SSqm67 , SSqm68 , SSqm69 , & + SSqm70 , SSqm71 , SSqm72 , SSqm73 , SSqm74 , SSqm75 , SSqm76 , & + SSqm77 , SSqm78 , SSqm79 , SSqm80 , SSqm81 , SSqm82 , SSqm83 , & + SSqm84 , SSqm85 , SSqm86 , SSqm87 , SSqm88 , SSqm89 , SSqm90 , & + SSqm91 , SSqm92 , SSqm93 , SSqm94 , SSqm95 , SSqm96 , SSqm97 , & + SSqm98 , SSqm99 , SSqmd01 , SSqmd02 , SSqmd03 , SSqmd04 , SSqmd05 , & + SSqmd06 , SSqmd07 , SSqmd08 , SSqmd09 , SSqmd10 , SSqmd11 , SSqmd12 , & + SSqmd13 , SSqmd14 , SSqmd15 , SSqmd16 , SSqmd17 , SSqmd18 , SSqmd19 , & + SSqmd20 , SSqmd21 , SSqmd22 , SSqmd23 , SSqmd24 , SSqmd25 , SSqmd26 , & + SSqmd27 , SSqmd28 , SSqmd29 , SSqmd30 , SSqmd31 , SSqmd32 , SSqmd33 , & + SSqmd34 , SSqmd35 , SSqmd36 , SSqmd37 , SSqmd38 , SSqmd39 , SSqmd40 , & + SSqmd41 , SSqmd42 , SSqmd43 , SSqmd44 , SSqmd45 , SSqmd46 , SSqmd47 , & + SSqmd48 , SSqmd49 , SSqmd50 , SSqmd51 , SSqmd52 , SSqmd53 , SSqmd54 , & + SSqmd55 , SSqmd56 , SSqmd57 , SSqmd58 , SSqmd59 , SSqmd60 , SSqmd61 , & + SSqmd62 , SSqmd63 , SSqmd64 , SSqmd65 , SSqmd66 , SSqmd67 , SSqmd68 , & + SSqmd69 , SSqmd70 , SSqmd71 , SSqmd72 , SSqmd73 , SSqmd74 , SSqmd75 , & + SSqmd76 , SSqmd77 , SSqmd78 , SSqmd79 , SSqmd80 , SSqmd81 , SSqmd82 , & + SSqmd83 , SSqmd84 , SSqmd85 , SSqmd86 , SSqmd87 , SSqmd88 , SSqmd89 , & + SSqmd90 , SSqmd91 , SSqmd92 , SSqmd93 , SSqmd94 , SSqmd95 , SSqmd96 , & + SSqmd97 , SSqmd98 , SSqmd99 , SSqmdd01 , SSqmdd02 , SSqmdd03 , SSqmdd04 , & + SSqmdd05 , SSqmdd06 , SSqmdd07 , SSqmdd08 , SSqmdd09 , SSqmdd10 , SSqmdd11 , & + SSqmdd12 , SSqmdd13 , SSqmdd14 , SSqmdd15 , SSqmdd16 , SSqmdd17 , SSqmdd18 , & + SSqmdd19 , SSqmdd20 , SSqmdd21 , SSqmdd22 , SSqmdd23 , SSqmdd24 , SSqmdd25 , & + SSqmdd26 , SSqmdd27 , SSqmdd28 , SSqmdd29 , SSqmdd30 , SSqmdd31 , SSqmdd32 , & + SSqmdd33 , SSqmdd34 , SSqmdd35 , SSqmdd36 , SSqmdd37 , SSqmdd38 , SSqmdd39 , & + SSqmdd40 , SSqmdd41 , SSqmdd42 , SSqmdd43 , SSqmdd44 , SSqmdd45 , SSqmdd46 , & + SSqmdd47 , SSqmdd48 , SSqmdd49 , SSqmdd50 , SSqmdd51 , SSqmdd52 , SSqmdd53 , & + SSqmdd54 , SSqmdd55 , SSqmdd56 , SSqmdd57 , SSqmdd58 , SSqmdd59 , SSqmdd60 , & + SSqmdd61 , SSqmdd62 , SSqmdd63 , SSqmdd64 , SSqmdd65 , SSqmdd66 , SSqmdd67 , & + SSqmdd68 , SSqmdd69 , SSqmdd70 , SSqmdd71 , SSqmdd72 , SSqmdd73 , SSqmdd74 , & + SSqmdd75 , SSqmdd76 , SSqmdd77 , SSqmdd78 , SSqmdd79 , SSqmdd80 , SSqmdd81 , & + SSqmdd82 , SSqmdd83 , SSqmdd84 , SSqmdd85 , SSqmdd86 , SSqmdd87 , SSqmdd88 , & + SSqmdd89 , SSqmdd90 , SSqmdd91 , SSqmdd92 , SSqmdd93 , SSqmdd94 , SSqmdd95 , & + SSqmdd96 , SSqmdd97 , SSqmdd98 , SSqmdd99 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(2265) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(Nm) ","(Nm) ", & + "(Nm) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) "/) + + +!End of code generated by Matlab script + + + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: SDOut_CloseSum + PUBLIC :: SDOut_OpenSum + PUBLIC :: SDOut_MapOutputs + PUBLIC :: SDOut_OpenOutput + PUBLIC :: SDOut_CloseOutput + PUBLIC :: SDOut_WriteOutputNames + PUBLIC :: SDOut_WriteOutputUnits + PUBLIC :: SDOut_WriteOutputs + PUBLIC :: SDOut_Init + +CONTAINS + + +SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) +! This subroutine initializes the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + +! Passed variables + + TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module + TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module paramters + TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables + TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data + REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! Local variables + + INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters + INTEGER(IntKi) :: Junk !Temporary Holders + INTEGER(IntKi) :: iMember ! Member index (not member ID) + INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time +!------------------------------------------------------------------------------------------------- +! Initialize local variables +!------------------------------------------------------------------------------------------------- +ErrStat = 0 +ErrMsg="" + +p%OutAllDims=12*p%Nmembers*2 !size of AllOut Member Joint forces + +!------------------------------------------------------------------------------------------------- +! Check that the variables in OutList are valid +!------------------------------------------------------------------------------------------------- + +! SDOut_Data%NumOuts = HDO_InitData%NumOuts + CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat, ErrMsg ) + IF ( ErrStat /= 0 ) RETURN + +!------------------------------------------------------------------------------------------------- +! INITIALIZE FAST-TYPE OUTPUT (y) +!------------------------------------------------------------------------------------------------- + !ALLOCATE( y%Y1(TPdofL), STAT = ErrStat ) + !IF ( ErrStat/= 0 ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Error allocating output Y1 array in SDOut_Init' + ! RETURN + !END IF + +!------------------------------------------------------------------------------------------------- +! Open the output file, if necessary, and write the header +!------------------------------------------------------------------------------------------------- + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested + + + ! Allocate SDWrOuput which is used to store a time step's worth of output channels, prior to writing to a file. + ALLOCATE( misc%SDWrOutput( p%NumOuts +p%OutAllInt*p%OutAllDims), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for SDWrOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + misc%SDWrOutput = 0.0_ReKi + misc%LastOutTime = 0.0_DbKi + misc%Decimat = 0 + + !Allocate WriteOuput + ALLOCATE( y%WriteOutput( p%NumOuts +p%OutAllInt*p%OutAllDims), STAT = ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating space for WriteOutput array.' + ErrStat = ErrID_Fatal + RETURN + END IF + y%WriteOutput = 0 + + !Do some final mapping and carry out housekeeping to calculate some of the output variable + + + !Store mapping between nodes and elements + CALL NodeCon(Init,p,ErrStat, ErrMsg) + IF ( ErrStat /=0) RETURN + + DO I=1,p%NMOutputs + ALLOCATE( p%MOutLst(I)%NodeIDs(p%MoutLst(I)%NoutCnt), STAT = ErrStat ) + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%NodeIDs arrays in SDOut_Init' + RETURN + END IF + iMember = FINDLOCI(Init%Members(:,1), p%MoutLst(I)%MemberID) ! Reindexing from MemberID to 1:nMembers + p%MOutLst(I)%NodeIDs=Init%MemberNodes(iMember ,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting + + ALLOCATE( p%MOutLst(I)%ElmIDs(p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !ElmIDs has for each selected node within the member, several element numbers to refer to for averaging (max 2 elements) + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%ElmIDs arrays in SDOut_Init' + RETURN + END IF + p%MOutLst(I)%ElmIDs=0 !Initialize to 0 + + ALLOCATE( p%MOutLst(I)%ElmNds(p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !ElmNds has for each selected node within the member, for each element number to refer to for averaging, the flag 1 or 2 depending on whether it is the 1st or last node of that element + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%ElmNds arrays in SDOut_Init' + RETURN + END IF + + ALLOCATE( p%MOutLst(I)%Me(12,12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Me has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x12 matrix + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%Me arrays in SDOut_Init' + RETURN + END IF + ALLOCATE( p%MOutLst(I)%Ke(12,12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Ke has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x12 matrix + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%Ke arrays in SDOut_Init' + RETURN + END IF + ALLOCATE( p%MOutLst(I)%Fg(12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Fg has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x1 vector + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst(I)%Fg arrays in SDOut_Init' + RETURN + END IF + + + + DO J=1,p%MoutLst(I)%NoutCnt !Iterate on requested nodes for that member + !I need to get at most 2 elements that belong to the same MoutLst(I)%MemberID + !make use of MemberNodes and NodesConnE + NconEls=Init%NodesConnE(p%MoutLst(I)%NodeIDs(J),1)!Number of elements connecting to the j-th node + + K2=0 !Initialize counter + DO K=1, NconEls + L=Init%NodesConnE(p%MoutLst(I)%NodeIDs(J),k+1) !k-th Element Number + M=p%Elems(L,2:3) !1st and 2nd node of the k-th element + + !Select only the other node, not the one where elements connect to + Junk=M(1) + IF (M(1) .EQ. p%MoutLst(I)%NodeIDs(J)) Junk=M(2) + + IF (ANY(Init%MemberNodes(iMember,:) .EQ. Junk)) THEN !This means we are in the selected member + IF (K2 .EQ. 2) EXIT + K2=K2+1 + p%MoutLst(I)%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 + + p%MoutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MoutLst(I)%NodeIDs(J) ) p%MoutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element + + !Calculate Ke, Me to be used for output + CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & + p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) + CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) + + CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst(I)%Fg(:,J,K2), Init%g ) + END IF + ENDDO + ENDDO + + ENDDO + + + + END IF ! there are any requested outputs + + + IF (p%OutAll) THEN !I need to store all member end forces and moments + + ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat ) !this list contains different arrays for each of its elements + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst2 array in SDOut_Init' + RETURN + END IF + + + DO I=1,p%NMembers + p%MOutLst2(I)%MemberID=Init%Members(I,1) + + ALLOCATE( p%MOutLst2(I)%NodeIDs(Init%Ndiv+1), STAT = ErrStat ) !1st and last node of member + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst2(I)%NodeIDs arrays in SDOut_Init' + RETURN + END IF + p%MOutLst2(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member + + !Now I need to find out which elements are attached to those nodes and still belong to the member I + !ElmID2s could contain the same element twice if Ndiv=1 + p%MOutLst2(I)%ElmID2s=0 !Initialize to 0 + + + DO J=1,Init%Ndiv+1,Init%Ndiv !Iterate on requested nodes for that member (first and last) + !I need to get at most 2 elements that belong to the same I Member + !make use of MemberNodes and NodesConnE + + NconEls=Init%NodesConnE(p%MoutLst2(I)%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member + + K2= J/(Init%Ndiv+1)+1 !store this quantity used later, basically 1 or 2 depending on J + + DO K=1, NconEls + L=Init%NodesConnE(p%MoutLst2(I)%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node + M=p%Elems(L,2:3) !1st and 2nd node of the k-th element + !Select only the other node, not the one where elements connect to + Junk=M(1) + IF (M(1) .EQ. p%MoutLst2(I)%NodeIDs(J)) Junk=M(2) + + IF (ANY(Init%MemberNodes(I,:) .EQ. Junk)) THEN !This means we are in the selected member + + p%MoutLst2(I)%ElmID2s(K2)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for + + p%MoutLst2(I)%ElmNd2s(K2)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MoutLst2(I)%NodeIDs(J) ) p%MoutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element + + !Calculate Ke, Me to be used for output + CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & + p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst2(I)%Ke2(:,:,K2) ) + CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Me2(:,:,K2) ) + CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Fg2(:,K2), Init%g ) + + EXIT !We found the element for that node, exit loop on elements + ENDIF + + + ENDDO + + ENDDO + + ENDDO + + + ENDIF + + !_____________________________________REACTIONS_____________________________________________ +p%OutReact = .FALSE. +DO I=1,p%NumOuts + if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" + p%OutReact =.TRUE. + EXIT + ENDIF +ENDDO + + IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being + + ALLOCATE ( p%MOutLst3(p%NReact), STAT = ErrStat ) !this list contains different arrays for each of its elements + IF ( ErrStat /= ErrID_None ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3 array in SDOut_Init' + RETURN + END IF + + + DO I=1,p%NReact !For all constrained node + + p%MOutLst3(I)%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array + + !Next stuff to be eliminated + !ALLOCATE( p%MOutLst3(I)%NodeIDs(Init%Ndiv+1), STAT = ErrStat ) ! + ! IF ( ErrStat/= 0 ) THEN + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Error allocating p%MOutLst3(I)%NodeIDs arrays in SDOut_Init' + ! RETURN + ! END IF + ! + !p%MOutLst3(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member + !Now I need to find out which elements are attached to those nodes and still belong to the member I + !ElmID2s could contain the same element twice if Ndiv=1 + !p%MOutLst3(I)%ElmID2s=0 !Initialize to 0 + + !I need to get ALL the elements that belong to the same joint + !make use of MemberNodes and NodesConnE + + NconEls=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint + + ALLOCATE( p%MOutLst3(I)%ElmIDs(1,NconEls), STAT = ErrStat ) !element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other Moutlst + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3(I)%ElmIDs arrays in SDOut_Init' + RETURN + END IF + + ALLOCATE( p%MOutLst3(I)%ElmNds(1,NconEls), STAT = ErrStat ) !This array contains for each element connected to the joint, a flag that tells me whether the joint is node 1 or 2 for the elements + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3(I)%ElmIDs arrays in SDOut_Init' + RETURN + END IF + + ALLOCATE( p%MOutLst3(I)%Me(12,12,1,NconEls), STAT = ErrStat ) !Me has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3(I)%Me arrays in SDOut_Init' + RETURN + END IF + ALLOCATE( p%MOutLst3(I)%Ke(12,12,1,NconEls), STAT = ErrStat ) !Ke has for each selected joint, and for each element attached to that node a 12x12 matrix + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3(I)%Ke arrays in SDOut_Init' + RETURN + END IF + ALLOCATE( p%MOutLst3(I)%Fg(12,1,NconEls), STAT = ErrStat ) !Fg has for each selected joint, and for each element attached to that node a 12x1 vector + IF ( ErrStat/= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Error allocating p%MOutLst3(I)%Ke arrays in SDOut_Init' + RETURN + END IF + + DO K=1, NconEls + L=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node + + p%MoutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for + + M=p%Elems(L,2:3) !1st and 2nd node of the k-th element + + !Select whether the joint is the 1st or second node of the element + p%MoutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MoutLst3(I)%Noutcnt ) p%MoutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element + + !Calculate Ke, Me to be used for output + CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & + p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst3(I)%Ke(:,:,1,K) ) + CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Me(:,:,1,K) ) + CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Fg(:,1,K), Init%g ) + + + ENDDO + + ENDDO + + !Store the matrix that will let me calculate single point reaction at the base of structure + CALL ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) + ENDIF + + + + ! These variables are to help follow the framework template, but the data in them is simply a copy of data + ! already available in the OutParam data structure + + ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WriteOutputHdr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + END DO + + +RETURN + +END SUBROUTINE SDOut_Init + +!------------------------------------------------------------------------------------------------------ +SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) +!This subroutine allocates and calculated TIreact, Matrix to go from local reactions at constrained nodes to single point reactions + TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT( INOUT) :: p ! Parameter data + REAL(ReKi), INTENT(IN) :: WtrDpth + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! local variables + INTEGER :: I !counter + INTEGER :: rmndr !type-column index + INTEGER :: n !node ID + INTEGER(IntKi) :: DOFC ! DOFC = Init%NReact*6 + REAL(ReKi) :: x, y, z !coordinates + + !Initialize + ErrStat=ErrID_None + ErrMsg="" + + DOFC = p%NReact*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure + + ALLOCATE ( p%TIreact(6,DOFC), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for TIreact array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + p%TIreact=0 !Initialize + + DO I=1,3 !Take care of first three rows + p%TIreact(I,I:DOFC:6)=1 + ENDDO + + !Other rows done per column actually + DO I = 1, DOFC + + n = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) + + x = Init%Nodes(n, 2) + y = Init%Nodes(n, 3) + z = Init%Nodes(n, 4) + WtrDpth + + rmndr = MOD(I, 6) !It gives me the column index among the 6 different kinds + SELECT CASE (rmndr) + CASE (1) + p%TIreact(4:6, I) = (/0.0_ReKi, z, -y/) + + CASE (2) + p%TIreact(4:6, I) = (/-z, 0.0_ReKi, x/) + + CASE (3) + p%TIreact(4:6, I) = (/y, -x, 0.0_ReKi/) + + CASE (4) + p%TIreact(4:6, I) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + + CASE (5) + p%TIreact(4:6, I) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + + CASE (0) + p%TIreact(4:6, I) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + + CASE DEFAULT + ErrStat = ErrID_Fatal + ErrMsg = 'Error calculating transformation matrix TIreact ' + RETURN + END SELECT + + ENDDO + + +END SUBROUTINE ReactMatx + +!==================================================================================================== +SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) +! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +! This is called by SD_CalcOutput() at each time step. +! This routine does fill Allouts +! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling +! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) +!---------------------------------------------------------------------------------------------------- + REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(SD_InputType), INTENT( IN ) :: u ! SubDyn module's input data + TYPE(SD_ContinuousStateType), INTENT( IN ) :: x ! SubDyn module's states data + TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + TYPE(SD_MiscVarType), INTENT( INOUT ) :: m ! Misc/optimization variables + REAL(ReKi), INTENT( OUT ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + !locals + INTEGER(IntKi) ::I,J,K,K2,L,L2 ! Counters + INTEGER(IntKi), DIMENSION(2) ::K3 ! It stores Node IDs for element under consideration (may not be consecutive numbers) + INTEGER(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%Nmodes + REAL(ReKi), DIMENSION (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments + REAL(ReKi), DIMENSION (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments + Real(ReKi), DIMENSION (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions + REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL + + Real(reKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs + Real(ReKi), DIMENSION(p%URbarL+p%DOFL+6*p%Nreact) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs + Integer(IntKi) ::sgn !+1/-1 for node force calculations + ErrStat = ErrID_None + ErrMsg = "" + + AllOuts = 0.0_ReKi ! initialize for those outputs that aren't valid (and thus aren't set in this routine) + + !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array + yout =0 !Initialize and populate with Y2 data + yout(1: p%UrbarL ) = m%UR_bar + yout(p%URbarL+1:p%URbarL+p%DOFL) = m%UL + + !Same for a variable that deals with Udotdot + uddout =0 !Initialize and populate with Udotdot data + uddout(1 : p%URbarL ) = m%UR_bar_dotdot + uddout(p%URbarL+1 : p%URbarL+p%DOFL ) = m%UL_dotdot + + ! Only generate member-based outputs for the number of user-requested member outputs + !Now store and identify needed output as requested by user + !p%MOutLst has the mapping for the member, node, elements per node, to be used + !MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) + !Inertial Load for the elements that are needed + if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 + DO I=1,p%NMOutputs + !I know el # and whether it is 1st node or second node + DO J=1,p%MoutLst(I)%NOutCnt !Iterate on requested nodes for that member + !I need to average across potentially up to 2 elements + !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second + K=p%MOutLst(I)%ElmIDs(J,1) !element number + K2=p%MOutLst(I)%ElmNds(J,1) !first or second node of the element to be considered + !Assign the sign depending on whether it is the 1st or second node + sgn=-1 + IF (K2 .EQ. 2) sgn= +1 + + K3=p%Elems(K,2:3) !first and second node ID associated with element K + + L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + + DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local dir-cosine matrix + + !I need to find the Udotdot() for the two nodes of the element of interest + !I need to move the displacements to the local ref system + + ! bjj: added these temporary storage variables so that the CALC_LOCAL call doesn't created + ! new temporary *every time* it's called + Tmp_Udotdot(1: 6) = uddout( L : L+5 ) + Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) + + Tmp_y2(1: 6) = yout( L : L+5 ) + Tmp_y2(7:12) = yout( L2 : L2+5 ) + + CALL CALC_LOCAL( DIRCOS,p%MOutLst(I)%Me(:,:,J,1),p%MOutLst(I)%Ke(:,:,J,1),Tmp_Udotdot, & + Tmp_y2,p%MoutLst(I)%Fg(:,J,1), K2,FM_elm,FK_elm) + + FM_elm2=sgn*FM_elm + FK_elm2=sgn*FK_elm + + IF (p%MOutLst(I)%ElmIDs(J,p%NavgEls) .NE. 0) THEN !element number + K=p%MOutLst(I)%ElmIDs(J,p%NavgEls) !element number + K2=p%MOutLst(I)%ElmNds(J,p%NavgEls) !first or second node of the element to be considered + !Assign the sign depending on whether it is the 1st or second node + sgn=-1 + IF (K2 .EQ. 2) sgn= +1 + + K3=p%Elems(K,2:3) !first and second node ID associated with element K + + L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + CALL CALC_LOCAL(DIRCOS,p%MOutLst(I)%Me(:,:,J,p%NavgEls),p%MOutLst(I)%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst(I)%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) + + FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average + FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average + ENDIF + + !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts + !Forces and moments + AllOuts(MNfmKe (:,J,I)) = FK_elm2 !static forces and moments (6) Local Ref + AllOuts(MNfmMe (:,J,I)) = FM_elm2 !dynamic forces and moments (6) Local Ref + !Displacement- Translational -no need for averaging since it is a node translation - In global reference SS + L=p%IDY( (p%MOutLst(I)%NodeIDs(J)-1)*6 +1 )! starting index for nodeID(J) within yout + AllOuts(MNTDss (:,J,I)) = yout(L:L+2) + !Displacement- Rotational - I need to get the direction cosine matrix to tranform rotations - In Local reference Element Ref Sys + + AllOuts(MNRDe (:,J,I)) = matmul(DIRCOS,yout(L+3:L+5) ) !local ref + !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations + AllOuts(MNTRAe (1:3,J,I)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref + AllOuts(MNTRAe (4:6,J,I)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref + + + + ENDDO + + ENDDO + END IF + + + IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES + + DO I=1,p%NMembers !Cycle on all members + DO J=1,2 !Iterate on requested nodes for that member (first and last) + K=p%MOutLst2(I)%ElmID2s(J) !element number + K2=p%MOutLst2(I)%ElmNd2s(J) !first or second node of the element to be considered + + !Assign the sign depending on whether it is the 1st or second node + sgn=-1 + IF (K2 .EQ. 2) sgn= +1 + + K3=p%Elems(K,2:3) !first and second node ID associated with element K + + L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + + DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local + + CALL CALC_LOCAL( DIRCOS,p%MOutLst2(I)%Me2(:,:,J),p%MOutLst2(I)%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst2(I)%Fg2(:,J), K2,FM_elm,FK_elm) + + ! FM_elm2=sgn*FM_elm + ! FK_elm2=sgn*FK_elm + + !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts + L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index + L2=L+11 + AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) + + ENDDO + ENDDO + + ENDIF + + + !Assign interface forces and moments + AllOuts(IntfSS(1:TPdofL))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign + + !Assign interface translations and rotations at the TP ref point + AllOuts(IntfTRss(1:TPdofL))=m%u_TP + + !Assign interface translations and rotations accelerations + AllOuts(IntfTRAss(1:TPdofL))= m%udotdot_TP + + ! Assign all SSqm, SSqmdot, SSqmdotdot + ! We only have space for the first 99 values + maxOutModes = min(p%Nmodes,99) + IF ( maxOutModes > 0 ) THEN + !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) + Allouts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) + Allouts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) + Allouts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) + END IF + + !Need to Calculate Reaction Forces Now, but only if requested + IF (p%OutReact) THEN + + ALLOCATE ( ReactNs(6*p%NReact), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for ReactNs array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ReactNs = 0.0 !Initialize + + DO I=1,p%NReact !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh + + FK_elm2=0. !Initialize + FM_elm2=0. !Initialize + + !Find the joint forces + DO J=1,SIZE(p%MOutLst3(I)%ElmIDs(1,:)) !for all the elements connected (normally 1) + + K=p%MOutLst3(I)%ElmIDs(1,J) !element number + K2=p%MOutLst3(I)%ElmNds(1,J) !first or second node of the element to be considered + + !Assign the sign depending on whether it is the 1st or second node + K3=p%Elems(K,2:3) !first and second node ID associated with element K + + L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + + DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local + + CALL CALC_LOCAL( DIRCOS,p%MOutLst3(I)%Me(:,:,1,J),p%MOutLst3(I)%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst3(I)%Fg(:,1,J), K2,FM_elm,FK_elm) + + !transform back to global, need to do 3 at a time since cosine matrix is 3x3 + DO L=1,2 + FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF + FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; + ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 + ENDDO + + ENDDO + !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise + + !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES + ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt + !The index in Y2mesh is? + !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: + junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) + + ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES + ENDDO + + !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts + + AllOuts( ReactSS(1:TPdofL) ) = matmul(p%TIreact,ReactNs) + ENDIF + + if (allocated(ReactNs)) deallocate(ReactNs) + +END SUBROUTINE SDOut_MapOutputs + +!==================================================================================================== + SUBROUTINE CALC_LOCAL(DIRCOS,Me,Ke,Udotdot,Y2,Fg, K2,FM_elm,FK_elm) + !This function calculates for the given element the static and dynamic forces, given K and M of the element, and + !output quantities Udotdot and Y2 containing the + !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked +!---------------------------------------------------------------------------------------------------- + Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) + Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces + Integer(IntKi), INTENT(IN) :: K2 !1 or 2 depending on node of interest + REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_elm, FK_elm !output static and dynamic forces and moments + + !Locals + INTEGER(IntKi) ::L !counter + REAL(DbKi), DIMENSION(12) ::Junk,Junk1,Junk3,Junk4 ! temporary storage for output stuff + + Junk=matmul(Me,Udotdot) !GLOBAL REFERENCE + Junk1=matmul(Ke,Y2) !GLOBAL REFERENCE + Junk1=Junk1- Fg !GLOBAL REFERENCE + DO L=1,4 + Junk3((L-1)*3+1:L*3)= matmul(DIRCOS, Junk( (L-1)*3+1:L*3 ) ) + Junk4((L-1)*3+1:L*3) = matmul(DIRCOS, Junk1( (L-1)*3+1:L*3 ) ) + ENDDO + + + FM_elm=Junk3(6*(k2-1)+1:k2*6) + FK_elm=Junk4(6*(k2-1)+1:k2*6) + + + END SUBROUTINE CALC_LOCAL + + !==================================================================================================== +SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER, INTENT( IN ) :: UnSum ! the unit number for the SubDyn summary file + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + + ! Local variables + INTEGER :: Stat ! status from I/) operation + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + ! Write any closing information in the summary file + + IF ( UnSum > 0 ) THEN + + WRITE (UnSum,'(/,A/)', IOSTAT=Stat) 'This summary file was closed on '//CurDate()//' at '//CurTime()//'.' + IF (Stat /= 0) THEN + ErrStat = ErrID_FATAL + ErrMsg = ' Problem writing to summary file.' + END IF + + ! Close the file + + CLOSE( UnSum, IOSTAT=Stat ) + IF (Stat /= 0) THEN + ErrStat = ErrID_FATAL + ErrMsg = TRIM(ErrMsg)//' Problem closing summary file.' + END IF + + IF ( ErrStat /= ErrID_None ) ErrMsg = 'SDOut_CloseSum'//TRIM(ErrMsg) + + END IF + +END SUBROUTINE SDOut_CloseSum + +!==================================================================================================== +SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) + + + ! Passed variables + + INTEGER, INTENT( OUT ) :: UnSum ! the unit number for the SubDyn summary file + CHARACTER(*), INTENT( IN ) :: SummaryName ! the name of the SubDyn summary file + TYPE(ProgDesc), INTENT( IN ) :: SD_Prog ! the name/version/date of the program + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + integer :: ErrStat2 + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + CALL GetNewUnit( UnSum ) + CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + ErrMsg = 'Failed to open SubDyn summary file: '//TRIM(ErrMsg) + RETURN + END IF + + + ! Write the summary file header + + WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) 'This summary file was generated by '//TRIM( SD_Prog%Name )//& + ' '//TRIM( SD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' + +END SUBROUTINE SDOut_OpenSum + +!==================================================================================================== +SUBROUTINE SDOut_OpenOutput( ProgVer, OutRootName, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(ProgDesc), INTENT( IN ) :: ProgVer + CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file + TYPE(SD_ParameterType), INTENT( INOUT ) :: p + TYPE(SD_InitOutPutType ), INTENT( IN ) :: InitOut ! + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER :: I ! Generic loop counter + CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: ErrStat2 + + !------------------------------------------------------------------------------------------------- + ! Initialize local variables + !------------------------------------------------------------------------------------------------- + ErrStat = ErrID_None + ErrMsg = "" + + !------------------------------------------------------------------------------------------------- + ! Open the output file, if necessary, and write the header + !------------------------------------------------------------------------------------------------- + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + + ! Open the file for output + OutFileName = TRIM(OutRootName)//'.out' + CALL GetNewUnit( p%UnJckF ) + + CALL OpenFOutFile ( p%UnJckF, OutFileName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + ErrMsg = ' Error opening SubDyn-level output file: '//TRIM(ErrMsg) + RETURN + END IF + + + ! Write the output file header + + WRITE (p%UnJckF,'(/,A/)', IOSTAT=ErrStat2) 'These predictions were generated by '//TRIM(GETNVD(ProgVer))//& + ' on '//CurDate()//' at '//CurTime()//'.' + + WRITE(p%UnJckF, '(//)') ! add 3 lines to make file format consistant with FAST v8 (headers on line 7; units on line 8) [this allows easier post-processing] + + ! Write the names of the output parameters: + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 'Time' ), ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + + + ! Write the units of the output parameters: + WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 's'), ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + + + + END IF ! there are any requested outputs + + RETURN + +END SUBROUTINE SDOut_OpenOutput + +!==================================================================================================== + + +!==================================================================================================== +SUBROUTINE SDOut_CloseOutput ( p, ErrStat, ErrMsg ) +! This function cleans up after running the SubDyn output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + +! ! Internal variables + LOGICAL :: Err + + + !------------------------------------------------------------------------------------------------- + ! Initialize error information + !------------------------------------------------------------------------------------------------- + ErrStat = 0 + ErrMsg = "" + + Err = .FALSE. + + !------------------------------------------------------------------------------------------------- + ! Close our output file + !------------------------------------------------------------------------------------------------- + CLOSE( p%UnJckF, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + + + !------------------------------------------------------------------------------------------------- + ! Make sure ErrStat is non-zero if an error occurred + !------------------------------------------------------------------------------------------------- + IF ( Err ) ErrStat = ErrID_Fatal + + RETURN + +END SUBROUTINE SDOut_CloseOutput +!==================================================================================================== + + +SUBROUTINE SDOut_WriteOutputNames( UnJckF, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Name ), ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + +END SUBROUTINE SDOut_WriteOutputNames + +!==================================================================================================== + + +SUBROUTINE SDOut_WriteOutputUnits( UnJckF, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Units ), ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + +END SUBROUTINE SDOut_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in SDOut_Init() +!---------------------------------------------------------------------------------------------------- + + ! Passed variables + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + REAL(ReKi), INTENT( IN ) :: SDWrOutput(:) ! SubDyn module's output data + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables + ! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + + + + ! Initialize ErrStat and determine if it makes any sense to write output + + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnJckF < 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' To write outputs for SubDyn there must be a valid file ID and OutParam must be allocated.' + RETURN + ELSE + ErrStat = ErrID_None + END IF + + + ! Write the output parameters to the file + + Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutFmt )//'))' + + + WRITE(UnJckF,Frmt) Time, ( p%Delim, SDWrOutput(I), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + + + RETURN + + +END SUBROUTINE SDOut_WriteOutputs + +!==================================================================================================== + + +!==================================================================================================== +SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! NOTE OutParam is populated here +!---------------------------------------------------------------------------------------------------- + + + + ! Passed variables + + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module parameter data + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Local variables. + + INTEGER :: I,J,K ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + !CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + CHARACTER(ChanLen), DIMENSION(24) :: ToTUnits,ToTNames,ToTNames0 + + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + + LOGICAL :: CheckOutListAgain + + InvalidOutput = .FALSE. + +!End of code generated by Matlab script + + ! mark invalid output channels: + + DO k=p%Nmodes+1,99 + InvalidOutput(SSqm01 +k-1) = .true. + InvalidOutput(SSqmd01 +k-1) = .true. + InvalidOutput(SSqmdd01+k-1) = .true. + END DO + + DO I=1,9 + !I know el # and whether it is 1st node or second node + if (I <= p%NMOutputs) then + INDX=p%MoutLst(I)%NOutCnt+1 + else + INDX = 1 + end if + + DO J=INDX,9 !Iterate on requested nodes for that member + !Forces and moments + InvalidOutput(MNfmKe (:,J,I)) = .true. !static forces and moments (6) Local Ref + InvalidOutput(MNfmMe (:,J,I)) = .true. !dynamic forces and moments (6) Local Ref + !Displacement + InvalidOutput(MNTDss (:,J,I)) = .true. !Translational + InvalidOutput(MNRDe (:,J,I)) = .true. !Rotational + !Accelerations + InvalidOutput(MNTRAe (:,J,I)) = .true. !translational accel local ref + END DO + END DO + + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + ALLOCATE ( p%OutParam(1:p%NumOuts+p%OutAllInt*p%OutAllDims) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutParam array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag and return. + !------------------------------------------------------------------------------------------------- + !!!p%OutParam(0)%Name = 'Time' ! OutData(0) is the time channel by default. + !!!p%OutParam(0)%Units = '(sec)' ! + !!!p%OutParam(0)%Indx = Time + !!!p%OutParam(0)%SignM = 1 + + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' + ErrStat = ErrID_Fatal +! RETURN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 0 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + END DO + + IF (p%OutAll) THEN !Finish populating the OutParam with all the joint forces and moments + ToTNames0=RESHAPE(SPREAD( (/"FKxe", "FKye", "FKze", "MKxe", "MKye", "MKze", "FMxe", "FMye", "FMze", "MMxe", "MMye", "MMze"/), 2, 2), (/24/) ) + ToTUnits=RESHAPE(SPREAD( (/"(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)", "(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)"/), 2, 2), (/24/) ) + DO I=1,p%Nmembers + DO K=1,2 + DO J=1,12 !looks like I cnanot vectorize TRIM etc in Fortran + TotNames(J+(K-1)*12)=TRIM("M"//Int2Lstr(I))//TRIM("J"//Int2Lstr(K))//TRIM(TotNames0(J)) + ENDDO + ENDDO + p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Name = ToTNames + p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Units = ToTUnits + ENDDO + p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%SignM = 1 + p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%Indx= MaxOutPts+(/(J, J=1, p%OutAllDims)/) + ENDIF + + RETURN +END SUBROUTINE SDOut_ChkOutLst + + +!==================================================================================================== + + +END MODULE SubDyn_Output diff --git a/OpenFAST/modules/subdyn/src/SubDyn_Registry.txt b/OpenFAST/modules/subdyn/src/SubDyn_Registry.txt new file mode 100644 index 000000000..248ce4ba2 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SubDyn_Registry.txt @@ -0,0 +1,222 @@ +##################### Registry for SubDyn ################## +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# Keyword ModuleName/ModName Derived data type Field type Variable name Dimemsion of the variable Initial value not used Description Units + +# ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ +typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" +typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ InitInputType ReKi g - - - "Gravity acceleration" +typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" +typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" + +# ============================== Define Initialization outputs here: ============================================================================================================================================ +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +# ============================== Define Internal data types here: ============================================================================================================================================ +typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" +typedef ^ MeshAuxDataType INTEGER NOutCnt - - - "Number of Nodes for the output member" +typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" +typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" +typedef ^ MeshAuxDataType INTEGER ElmID2s {2} - - "Element IDs connected to each joint node" +typedef ^ MeshAuxDataType INTEGER ElmNd2s {2} - - Flag to indicate 1st or 2nd node of element which is attached to "member joint (for outAll)" +typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" +typedef ^ MeshAuxDataType ReKi Me2 {12}{12}{2} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Ke2 {12}{12}{2} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Fg2 {12}{2} - - "Gravity load vector connected to each joint element for outAll output" +# CB_MatArrays: Matrices and arrays for CB summary +typedef SubDyn/SD CB_MatArrays INTEGER DOFM - - - "retained degrees of freedom (modes)" +typedef ^ CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" +typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" +typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(DOFL,DOFL), or PhiL(DOFL,DOFM)" +typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" +typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (DOFL or DOFM)" +# FEM_MatArrays: Matrices and arrays for FEM summary +typedef SubDyn/SD FEM_MatArrays ReKi Omega {:} - - "Eigenvalues of full FEM model, we calculate them all" +typedef ^ FEM_MatArrays INTEGER NOmega - - - "Number of full FEM Eigenvalues (for now TDOF-6*Nreact)" +typedef ^ FEM_MatArrays ReKi Modes {:}{:} - - "Eigenmodes of full FEM model, we calculate them all" + +# +typedef ^ ElemPropType ReKi Area - - - "Area of an element" +typedef ^ ^ ReKi Length - - - "Length of an element" +typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" +typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" +typedef ^ ^ ReKi Kappa - - - "Shear coefficient" +typedef ^ ^ ReKi YoungE - - - "Young's modulus" +typedef ^ ^ ReKi ShearG - - - "Shear modulus" +typedef ^ ^ ReKi Rho - - - "Density" +typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" +# ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ +#--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- +typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ ^ ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ ^ ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ ^ ReKi g - - - "Gravity acceleration" +typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds +typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" +typedef ^ ^ INTEGER NPropSets - - - "Number of property sets" +typedef ^ ^ INTEGER NXPropSets - - - "Number of extended property sets" +typedef ^ ^ INTEGER NInterf - - - "Number of joints attached to transition piece" +typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" +typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" +typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" +typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" +typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" +typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" +typedef ^ ^ ReKi PropSets {:}{:} - - "Property sets number and values" +typedef ^ ^ ReKi XPropSets {:}{:} - - "Extended property sets" +typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" +typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" +typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" +typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" +typedef ^ ^ INTEGER Interf {:}{:} - - "Interface degree of freedoms" +typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" +typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" +typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" +#-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +typedef ^ ^ INTEGER NNode - - - "Total number of nodes" +typedef ^ ^ INTEGER NElem - - - "Total number of elements" +typedef ^ ^ INTEGER NProp - - - "Total number of property sets" +typedef ^ ^ INTEGER TDOF - - - "Total degree of freedom" +typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" +typedef ^ ^ ReKi Props {:}{:} - - "Property sets and values" +typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" +typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" +typedef ^ ^ ReKi F {:} - - "System force vector" N +typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N +typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" +typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" +typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" +typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and nodes in the member" +typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" +typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" +typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" + +# ============================== States ============================================================================================================================================ +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi qm {:} - - "Virtual states, Nmod elements" +typedef ^ ContinuousStateType ReKi qmdot {:} - - "Derivative of states, Nmod elements" +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" + +# Define any other states, including integer or logical states here: +typedef SubDyn/SD OtherStateType SD_ContinuousStateType xdot {:} - - "previous state derivs for m-step time integrator" +typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated last" + + +# ..... 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 qmdotdot {:} - - "2nd Derivative of states, used only for output-file purposes" +typedef ^ ^ ReKi u_TP 6 - - +typedef ^ ^ ReKi udot_TP 6 - - +typedef ^ ^ ReKi udotdot_TP 6 - - +typedef ^ ^ ReKi UFL {:} - - +typedef ^ ^ ReKi UR_bar {:} - - +typedef ^ ^ ReKi UR_bar_dot {:} - - +typedef ^ ^ ReKi UR_bar_dotdot {:} - - +typedef ^ ^ ReKi UL {:} - - +typedef ^ ^ ReKi UL_dot {:} - - +typedef ^ ^ ReKi UL_dotdot {:} - - +### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### +typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" +typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" +typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" + + + +# ============================== Parameters ============================================================================================================================================ +typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds +typedef ^ ParameterType Logical SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" +typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" +typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" +typedef ^ ParameterType ReKi FX {:} - - "Load components in X" +typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of u in Y1" +typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of u in Y1" +typedef ^ ParameterType ReKi FY {:} - - "Load Components in Y1" +typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" +typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R bar * TI)" +typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" +typedef ^ ParameterType ReKi MBB {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" +typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" +typedef ^ ParameterType ReKi FGL {:} - - "Internal node DOFL, gravity loads" +typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" +typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" +typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" +typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" +typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B method" +typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" +typedef ^ ParameterType IntKi qmL - - - "Length of state array" +typedef ^ ParameterType IntKi DofL - - - "Internal nodes # of DOFs" +typedef ^ ParameterType IntKi NNodes_I - - - "Number of Interface nodes" +typedef ^ ParameterType IntKi NNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi NNodes_RbarL - - - "Number of Interface + Internal nodes" +typedef ^ ParameterType IntKi DofI - - - "Interface nodes # of DOFs" +typedef ^ ParameterType IntKi DofR - - - "Interface and restrained nodes # of DOFs" +typedef ^ ParameterType IntKi DofC - - - "Contrained nodes # of DOFs" +typedef ^ ParameterType IntKi NReact - - - "Number of joints with reactions" +typedef ^ ParameterType IntKi Reacts {:}{:} - - "React degree of freedoms" +typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" +typedef ^ ParameterType IntKi URbarL - - - "Length of URbar, subarray of y2 array (DOFRb)" +typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" +typedef ^ ParameterType IntKi NAvgEls - 2 - "Max number of elements that should be averaged when calculating outputs at nodes" +typedef ^ ParameterType IntKi IDI {:} - - "Index array of the interface(nodes connect to TP) dofs" +typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and restraint dofs" +typedef ^ ParameterType IntKi IDL {:} - - "Index array of the internal dofs" +typedef ^ ParameterType IntKi IDC {:} - - "Index array of the contraint dofs" +typedef ^ ParameterType IntKi IDY {:} - - "Index array of the all dofs in Y2" +typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" +typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" +typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" +typedef ^ ParameterType IntKi UnJckF - - - "Unit of SD ouput file" +typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" +typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format for Output" +typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" +typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" +typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" +typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" +typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" +typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" + +# ============================== Inputs ============================================================================================================================================ +typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" +typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" + +# ============================== Outputs ============================================================================================================================================ +typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" +typedef ^ OutputType MeshType Y2Mesh - - - "Interior+Interface nodes outputs on a point mesh" +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file" diff --git a/OpenFAST/modules/subdyn/src/SubDyn_Types.f90 b/OpenFAST/modules/subdyn/src/SubDyn_Types.f90 new file mode 100644 index 000000000..31efd0db7 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/SubDyn_Types.f90 @@ -0,0 +1,9490 @@ +!STARTOFREGISTRYGENERATEDFILE 'SubDyn_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 +!********************************************************************************************************************************* +! SubDyn_Types +!................................................................................................................................. +! This file is part of SubDyn. +! +! 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 SubDyn. 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 SubDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= SD_InitInputType ======= + TYPE, PUBLIC :: SD_InitInputType + CHARACTER(1024) :: SDInputFile !< Name of the input file [-] + CHARACTER(1024) :: RootName !< SubDyn rootname [-] + REAL(ReKi) :: g !< Gravity acceleration [-] + REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] + REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] + REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + END TYPE SD_InitInputType +! ======================= +! ========= SD_InitOutputType ======= + TYPE, PUBLIC :: SD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE SD_InitOutputType +! ======================= +! ========= MeshAuxDataType ======= + TYPE, PUBLIC :: MeshAuxDataType + INTEGER(IntKi) :: MemberID !< Member ID for Output [-] + INTEGER(IntKi) :: NOutCnt !< Number of Nodes for the output member [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeCnt !< Node ordinal numbers for the output member [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIDs !< Node IDs associated with ordinal numbers for the output member [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmIDs !< Element IDs connected to each NodeIDs; max 10 elements [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmNds !< Flag to indicate 1st or 2nd node of element for each ElmIDs [-] + INTEGER(IntKi) , DIMENSION(1:2) :: ElmID2s !< Element IDs connected to each joint node [-] + INTEGER(IntKi) , DIMENSION(1:2) :: ElmNd2s !< Flag [to] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] + REAL(ReKi) , DIMENSION(1:12,1:12,1:2) :: Me2 !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(1:12,1:12,1:2) :: Ke2 !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(1:12,1:2) :: Fg2 !< Gravity load vector connected to each joint element for outAll output [-] + END TYPE MeshAuxDataType +! ======================= +! ========= CB_MatArrays ======= + TYPE, PUBLIC :: CB_MatArrays + INTEGER(IntKi) :: DOFM !< retained degrees of freedom (modes) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI2 !< TI2 matrix to refer to total mass to (0,0,0) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(DOFL,DOFL), or PhiL(DOFL,DOFM) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (DOFL or DOFM) [-] + END TYPE CB_MatArrays +! ======================= +! ========= FEM_MatArrays ======= + TYPE, PUBLIC :: FEM_MatArrays + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Omega !< Eigenvalues of full FEM model, we calculate them all [-] + INTEGER(IntKi) :: NOmega !< Number of full FEM Eigenvalues (for now TDOF-6*Nreact) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Modes !< Eigenmodes of full FEM model, we calculate them all [-] + END TYPE FEM_MatArrays +! ======================= +! ========= ElemPropType ======= + TYPE, PUBLIC :: ElemPropType + REAL(ReKi) :: Area !< Area of an element [-] + REAL(ReKi) :: Length !< Length of an element [-] + REAL(ReKi) :: Ixx !< Moment of inertia of an element [-] + REAL(ReKi) :: Iyy !< Moment of inertia of an element [-] + REAL(ReKi) :: Jzz !< Moment of inertia of an element [-] + LOGICAL :: Shear !< Use timoshenko (true) E-B (false) [-] + REAL(ReKi) :: Kappa !< Shear coefficient [-] + REAL(ReKi) :: YoungE !< Young's modulus [-] + REAL(ReKi) :: ShearG !< Shear modulus [-] + REAL(ReKi) :: Rho !< Density [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] + END TYPE ElemPropType +! ======================= +! ========= SD_InitType ======= + TYPE, PUBLIC :: SD_InitType + CHARACTER(1024) :: RootName !< SubDyn rootname [-] + REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] + REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + REAL(ReKi) :: g !< Gravity acceleration [-] + REAL(DbKi) :: DT !< Time step from Glue Code [seconds] + INTEGER(IntKi) :: NJoints !< Number of joints of the sub structure [-] + INTEGER(IntKi) :: NPropSets !< Number of property sets [-] + INTEGER(IntKi) :: NXPropSets !< Number of extended property sets [-] + INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] + INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] + INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] + INTEGER(IntKi) :: FEMMod !< FEM switch: element model in the FEM [-] + INTEGER(IntKi) :: NDiv !< Number of divisions for each member [-] + LOGICAL :: CBMod !< Perform C-B flag [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSets !< Property sets number and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: XPropSets !< Extended property sets [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Interf !< Interface degree of freedoms [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] + LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] + LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] + INTEGER(IntKi) :: NNode !< Total number of nodes [-] + INTEGER(IntKi) :: NElem !< Total number of elements [-] + INTEGER(IntKi) :: NProp !< Total number of property sets [-] + INTEGER(IntKi) :: TDOF !< Total degree of freedom [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Props !< Property sets and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and nodes in the member [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] + LOGICAL :: SSSum !< SubDyn Summary File Flag [-] + END TYPE SD_InitType +! ======================= +! ========= SD_ContinuousStateType ======= + TYPE, PUBLIC :: SD_ContinuousStateType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qm !< Virtual states, Nmod elements [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdot !< Derivative of states, Nmod elements [-] + END TYPE SD_ContinuousStateType +! ======================= +! ========= SD_DiscreteStateType ======= + TYPE, PUBLIC :: SD_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE SD_DiscreteStateType +! ======================= +! ========= SD_ConstraintStateType ======= + TYPE, PUBLIC :: SD_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE SD_ConstraintStateType +! ======================= +! ========= SD_OtherStateType ======= + TYPE, PUBLIC :: SD_OtherStateType + TYPE(SD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< previous state derivs for m-step time integrator [-] + INTEGER(IntKi) :: n !< tracks time step for which OtherState was updated last [-] + END TYPE SD_OtherStateType +! ======================= +! ========= SD_MiscVarType ======= + TYPE, PUBLIC :: SD_MiscVarType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdotdot !< 2nd Derivative of states, used only for output-file purposes [-] + REAL(ReKi) , DIMENSION(1:6) :: u_TP + REAL(ReKi) , DIMENSION(1:6) :: udot_TP + REAL(ReKi) , DIMENSION(1:6) :: udotdot_TP + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UFL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] + REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] + INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] + END TYPE SD_MiscVarType +! ======================= +! ========= SD_ParameterType ======= + TYPE, PUBLIC :: SD_ParameterType + REAL(DbKi) :: SDDeltaT !< Time step (for integration of continuous states) [seconds] + LOGICAL :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of u in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of u in Y1 [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Load Components in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiRb_TI !< Coefficient of u in Y2 (Phi_R bar * TI) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_63 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_64 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F2_61 !< Load Component in Y2 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node DOFL, gravity loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AM2Jac !< Jacobian (factored) for Adams-Boulton 2nd order Integration [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AM2JacPiv !< Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI !< Matrix to calculate TP reference point reaction at top of structure [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIreact !< Matrix to calculate single point reaction at base of structure [-] + INTEGER(IntKi) :: NModes !< Number of modes to retain in C-B method [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] + INTEGER(IntKi) :: qmL !< Length of state array [-] + INTEGER(IntKi) :: DofL !< Internal nodes of DOFs [-] + INTEGER(IntKi) :: NNodes_I !< Number of Interface nodes [-] + INTEGER(IntKi) :: NNodes_L !< Number of Internal nodes [-] + INTEGER(IntKi) :: NNodes_RbarL !< Number of Interface + Internal nodes [-] + INTEGER(IntKi) :: DofI !< Interface nodes of DOFs [-] + INTEGER(IntKi) :: DofR !< Interface and restrained nodes of DOFs [-] + INTEGER(IntKi) :: DofC !< Contrained nodes of DOFs [-] + INTEGER(IntKi) :: NReact !< Number of joints with reactions [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Reacts !< React degree of freedoms [-] + INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] + INTEGER(IntKi) :: URbarL !< Length of URbar, subarray of y2 array (DOFRb) [-] + INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] + INTEGER(IntKi) :: NAvgEls = 2 !< Max number of elements that should be averaged when calculating outputs at nodes [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI !< Index array of the interface(nodes connect to TP) dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL !< Index array of the internal dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC !< Index array of the contraint dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDY !< Index array of the all dofs in Y2 [-] + INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] + INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] + INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] + INTEGER(IntKi) :: UnJckF !< Unit of SD ouput file [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + CHARACTER(20) :: OutFmt !< Format for Output [-] + CHARACTER(20) :: OutSFmt !< Format for Output Headers [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst !< List of user requested members and nodes [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst2 !< List of all member joint nodes and elements for output [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst3 !< List of all member joint nodes and elements for output [-] + TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< An array holding names, units, and indices of all of the selected output channels. logical [-] + LOGICAL :: OutAll !< Flag to output or not all joint forces [-] + LOGICAL :: OutReact !< Flag to check whether reactions are requested [-] + INTEGER(IntKi) :: OutAllInt !< Integer version of OutAll [-] + INTEGER(IntKi) :: OutAllDims !< Integer version of OutAll [-] + INTEGER(IntKi) :: OutDec !< Output Decimation for Requested Channels [-] + END TYPE SD_ParameterType +! ======================= +! ========= SD_InputType ======= + TYPE, PUBLIC :: SD_InputType + TYPE(MeshType) :: TPMesh !< Transition piece inputs on a point mesh [-] + TYPE(MeshType) :: LMesh !< Point mesh for interior node inputs [-] + END TYPE SD_InputType +! ======================= +! ========= SD_OutputType ======= + TYPE, PUBLIC :: SD_OutputType + TYPE(MeshType) :: Y1Mesh !< Transition piece outputs on a point mesh [-] + TYPE(MeshType) :: Y2Mesh !< Interior+Interface nodes outputs on a point mesh [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file [-] + END TYPE SD_OutputType +! ======================= +CONTAINS + SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SD_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 = 'SD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%SDInputFile = SrcInitInputData%SDInputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%g = SrcInitInputData%g + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint + DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ + END SUBROUTINE SD_CopyInitInput + + SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyInitInput + + SUBROUTINE SD_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(SD_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 = 'SD_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%SDInputFile) ! SDInputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! g + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint + Re_BufSz = Re_BufSz + 1 ! SubRotateZ + 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%SDInputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) + ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_PackInitInput + + SUBROUTINE SD_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(SD_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 = 'SD_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%SDInputFile) + OutData%SDInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%TP_RefPoint,1) + i1_u = UBOUND(OutData%TP_RefPoint,1) + DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) + OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%SubRotateZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_UnPackInitInput + + SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SD_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 = 'SD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SD_CopyInitOutput + + SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInitOutput + + SUBROUTINE SD_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(SD_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 = 'SD_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! 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 + + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + 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 SD_PackInitOutput + + SUBROUTINE SD_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(SD_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 = 'SD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + 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 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 SD_UnPackInitOutput + + SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(IN) :: SrcMeshAuxDataTypeData + TYPE(MeshAuxDataType), INTENT(INOUT) :: DstMeshAuxDataTypeData + 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 = 'SD_CopyMeshAuxDataType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMeshAuxDataTypeData%MemberID = SrcMeshAuxDataTypeData%MemberID + DstMeshAuxDataTypeData%NOutCnt = SrcMeshAuxDataTypeData%NOutCnt +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeCnt)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeCnt)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeCnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%NodeCnt = SrcMeshAuxDataTypeData%NodeCnt +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%NodeIDs = SrcMeshAuxDataTypeData%NodeIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmIDs = SrcMeshAuxDataTypeData%ElmIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmNds)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmNds)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds +ENDIF + DstMeshAuxDataTypeData%ElmID2s = SrcMeshAuxDataTypeData%ElmID2s + DstMeshAuxDataTypeData%ElmNd2s = SrcMeshAuxDataTypeData%ElmNd2s +IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Me,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Me,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Me,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Me,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Me,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Me,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Me)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Me(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 DstMeshAuxDataTypeData%Me.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Me = SrcMeshAuxDataTypeData%Me +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Ke)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Ke,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Ke,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Ke,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Ke,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Ke,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Ke,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Ke,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Ke,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Ke)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Ke(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 DstMeshAuxDataTypeData%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Ke = SrcMeshAuxDataTypeData%Ke +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Fg)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Fg,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Fg,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Fg,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Fg,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Fg,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Fg,3) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Fg)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg +ENDIF + DstMeshAuxDataTypeData%Me2 = SrcMeshAuxDataTypeData%Me2 + DstMeshAuxDataTypeData%Ke2 = SrcMeshAuxDataTypeData%Ke2 + DstMeshAuxDataTypeData%Fg2 = SrcMeshAuxDataTypeData%Fg2 + END SUBROUTINE SD_CopyMeshAuxDataType + + SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(INOUT) :: MeshAuxDataTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMeshAuxDataType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MeshAuxDataTypeData%NodeCnt)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeCnt) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%NodeIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmNds)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmNds) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Me)) THEN + DEALLOCATE(MeshAuxDataTypeData%Me) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Ke)) THEN + DEALLOCATE(MeshAuxDataTypeData%Ke) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Fg)) THEN + DEALLOCATE(MeshAuxDataTypeData%Fg) +ENDIF + END SUBROUTINE SD_DestroyMeshAuxDataType + + SUBROUTINE SD_PackMeshAuxDataType( 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(MeshAuxDataType), 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 = 'SD_PackMeshAuxDataType' + ! 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 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NOutCnt + Int_BufSz = Int_BufSz + 1 ! NodeCnt allocated yes/no + IF ( ALLOCATED(InData%NodeCnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeCnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeCnt) ! NodeCnt + END IF + Int_BufSz = Int_BufSz + 1 ! NodeIDs allocated yes/no + IF ( ALLOCATED(InData%NodeIDs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeIDs) ! NodeIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmIDs allocated yes/no + IF ( ALLOCATED(InData%ElmIDs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmIDs) ! ElmIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmNds allocated yes/no + IF ( ALLOCATED(InData%ElmNds) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds + END IF + Int_BufSz = Int_BufSz + SIZE(InData%ElmID2s) ! ElmID2s + Int_BufSz = Int_BufSz + SIZE(InData%ElmNd2s) ! ElmNd2s + Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no + IF ( ALLOCATED(InData%Me) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Me) ! Me + END IF + Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no + IF ( ALLOCATED(InData%Ke) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Ke) ! Ke + END IF + Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no + IF ( ALLOCATED(InData%Fg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fg) ! Fg + END IF + Re_BufSz = Re_BufSz + SIZE(InData%Me2) ! Me2 + Re_BufSz = Re_BufSz + SIZE(InData%Ke2) ! Ke2 + Re_BufSz = Re_BufSz + SIZE(InData%Fg2) ! Fg2 + 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%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NOutCnt + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeCnt) ) 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%NodeCnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeCnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodeCnt,1), UBOUND(InData%NodeCnt,1) + IntKiBuf(Int_Xferred) = InData%NodeCnt(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodeIDs) ) 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%NodeIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIDs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodeIDs,1), UBOUND(InData%NodeIDs,1) + IntKiBuf(Int_Xferred) = InData%NodeIDs(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElmIDs) ) 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%ElmIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ElmIDs,2), UBOUND(InData%ElmIDs,2) + DO i1 = LBOUND(InData%ElmIDs,1), UBOUND(InData%ElmIDs,1) + IntKiBuf(Int_Xferred) = InData%ElmIDs(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElmNds) ) 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%ElmNds,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ElmNds,2), UBOUND(InData%ElmNds,2) + DO i1 = LBOUND(InData%ElmNds,1), UBOUND(InData%ElmNds,1) + IntKiBuf(Int_Xferred) = InData%ElmNds(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + DO i1 = LBOUND(InData%ElmID2s,1), UBOUND(InData%ElmID2s,1) + IntKiBuf(Int_Xferred) = InData%ElmID2s(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%ElmNd2s,1), UBOUND(InData%ElmNd2s,1) + IntKiBuf(Int_Xferred) = InData%ElmNd2s(i1) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%Me) ) 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%Me,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Me,4), UBOUND(InData%Me,4) + DO i3 = LBOUND(InData%Me,3), UBOUND(InData%Me,3) + DO i2 = LBOUND(InData%Me,2), UBOUND(InData%Me,2) + DO i1 = LBOUND(InData%Me,1), UBOUND(InData%Me,1) + ReKiBuf(Re_Xferred) = InData%Me(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Ke) ) 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%Ke,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Ke,4), UBOUND(InData%Ke,4) + DO i3 = LBOUND(InData%Ke,3), UBOUND(InData%Ke,3) + DO i2 = LBOUND(InData%Ke,2), UBOUND(InData%Ke,2) + DO i1 = LBOUND(InData%Ke,1), UBOUND(InData%Ke,1) + ReKiBuf(Re_Xferred) = InData%Ke(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fg) ) 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%Fg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Fg,3), UBOUND(InData%Fg,3) + DO i2 = LBOUND(InData%Fg,2), UBOUND(InData%Fg,2) + DO i1 = LBOUND(InData%Fg,1), UBOUND(InData%Fg,1) + ReKiBuf(Re_Xferred) = InData%Fg(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + DO i3 = LBOUND(InData%Me2,3), UBOUND(InData%Me2,3) + DO i2 = LBOUND(InData%Me2,2), UBOUND(InData%Me2,2) + DO i1 = LBOUND(InData%Me2,1), UBOUND(InData%Me2,1) + ReKiBuf(Re_Xferred) = InData%Me2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + DO i3 = LBOUND(InData%Ke2,3), UBOUND(InData%Ke2,3) + DO i2 = LBOUND(InData%Ke2,2), UBOUND(InData%Ke2,2) + DO i1 = LBOUND(InData%Ke2,1), UBOUND(InData%Ke2,1) + ReKiBuf(Re_Xferred) = InData%Ke2(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + DO i2 = LBOUND(InData%Fg2,2), UBOUND(InData%Fg2,2) + DO i1 = LBOUND(InData%Fg2,1), UBOUND(InData%Fg2,1) + ReKiBuf(Re_Xferred) = InData%Fg2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SD_PackMeshAuxDataType + + SUBROUTINE SD_UnPackMeshAuxDataType( 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(MeshAuxDataType), 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 = 'SD_UnPackMeshAuxDataType' + ! 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%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NOutCnt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeCnt 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%NodeCnt)) DEALLOCATE(OutData%NodeCnt) + ALLOCATE(OutData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeCnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeCnt,1), UBOUND(OutData%NodeCnt,1) + OutData%NodeCnt(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIDs 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%NodeIDs)) DEALLOCATE(OutData%NodeIDs) + ALLOCATE(OutData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeIDs,1), UBOUND(OutData%NodeIDs,1) + OutData%NodeIDs(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmIDs 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%ElmIDs)) DEALLOCATE(OutData%ElmIDs) + ALLOCATE(OutData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ElmIDs,2), UBOUND(OutData%ElmIDs,2) + DO i1 = LBOUND(OutData%ElmIDs,1), UBOUND(OutData%ElmIDs,1) + OutData%ElmIDs(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmNds 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%ElmNds)) DEALLOCATE(OutData%ElmNds) + ALLOCATE(OutData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ElmNds,2), UBOUND(OutData%ElmNds,2) + DO i1 = LBOUND(OutData%ElmNds,1), UBOUND(OutData%ElmNds,1) + OutData%ElmNds(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + i1_l = LBOUND(OutData%ElmID2s,1) + i1_u = UBOUND(OutData%ElmID2s,1) + DO i1 = LBOUND(OutData%ElmID2s,1), UBOUND(OutData%ElmID2s,1) + OutData%ElmID2s(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%ElmNd2s,1) + i1_u = UBOUND(OutData%ElmNd2s,1) + DO i1 = LBOUND(OutData%ElmNd2s,1), UBOUND(OutData%ElmNd2s,1) + OutData%ElmNd2s(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me 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%Me)) DEALLOCATE(OutData%Me) + ALLOCATE(OutData%Me(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%Me.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Me,4), UBOUND(OutData%Me,4) + DO i3 = LBOUND(OutData%Me,3), UBOUND(OutData%Me,3) + DO i2 = LBOUND(OutData%Me,2), UBOUND(OutData%Me,2) + DO i1 = LBOUND(OutData%Me,1), UBOUND(OutData%Me,1) + OutData%Me(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke 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%Ke)) DEALLOCATE(OutData%Ke) + ALLOCATE(OutData%Ke(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%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Ke,4), UBOUND(OutData%Ke,4) + DO i3 = LBOUND(OutData%Ke,3), UBOUND(OutData%Ke,3) + DO i2 = LBOUND(OutData%Ke,2), UBOUND(OutData%Ke,2) + DO i1 = LBOUND(OutData%Ke,1), UBOUND(OutData%Ke,1) + OutData%Ke(i1,i2,i3,i4) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg 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%Fg)) DEALLOCATE(OutData%Fg) + ALLOCATE(OutData%Fg(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%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fg,3), UBOUND(OutData%Fg,3) + DO i2 = LBOUND(OutData%Fg,2), UBOUND(OutData%Fg,2) + DO i1 = LBOUND(OutData%Fg,1), UBOUND(OutData%Fg,1) + OutData%Fg(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + i1_l = LBOUND(OutData%Me2,1) + i1_u = UBOUND(OutData%Me2,1) + i2_l = LBOUND(OutData%Me2,2) + i2_u = UBOUND(OutData%Me2,2) + i3_l = LBOUND(OutData%Me2,3) + i3_u = UBOUND(OutData%Me2,3) + DO i3 = LBOUND(OutData%Me2,3), UBOUND(OutData%Me2,3) + DO i2 = LBOUND(OutData%Me2,2), UBOUND(OutData%Me2,2) + DO i1 = LBOUND(OutData%Me2,1), UBOUND(OutData%Me2,1) + OutData%Me2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + i1_l = LBOUND(OutData%Ke2,1) + i1_u = UBOUND(OutData%Ke2,1) + i2_l = LBOUND(OutData%Ke2,2) + i2_u = UBOUND(OutData%Ke2,2) + i3_l = LBOUND(OutData%Ke2,3) + i3_u = UBOUND(OutData%Ke2,3) + DO i3 = LBOUND(OutData%Ke2,3), UBOUND(OutData%Ke2,3) + DO i2 = LBOUND(OutData%Ke2,2), UBOUND(OutData%Ke2,2) + DO i1 = LBOUND(OutData%Ke2,1), UBOUND(OutData%Ke2,1) + OutData%Ke2(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + i1_l = LBOUND(OutData%Fg2,1) + i1_u = UBOUND(OutData%Fg2,1) + i2_l = LBOUND(OutData%Fg2,2) + i2_u = UBOUND(OutData%Fg2,2) + DO i2 = LBOUND(OutData%Fg2,2), UBOUND(OutData%Fg2,2) + DO i1 = LBOUND(OutData%Fg2,1), UBOUND(OutData%Fg2,1) + OutData%Fg2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SD_UnPackMeshAuxDataType + + SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(IN) :: SrcCB_MatArraysData + TYPE(CB_MatArrays), INTENT(INOUT) :: DstCB_MatArraysData + 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 = 'SD_CopyCB_MatArrays' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCB_MatArraysData%DOFM = SrcCB_MatArraysData%DOFM +IF (ALLOCATED(SrcCB_MatArraysData%TI2)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%TI2,1) + i1_u = UBOUND(SrcCB_MatArraysData%TI2,1) + i2_l = LBOUND(SrcCB_MatArraysData%TI2,2) + i2_u = UBOUND(SrcCB_MatArraysData%TI2,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%TI2)) THEN + ALLOCATE(DstCB_MatArraysData%TI2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%TI2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%TI2 = SrcCB_MatArraysData%TI2 +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBB)) THEN + ALLOCATE(DstCB_MatArraysData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%MBB = SrcCB_MatArraysData%MBB +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%MBM)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBM,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBM,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBM,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBM,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBM)) THEN + ALLOCATE(DstCB_MatArraysData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%MBM = SrcCB_MatArraysData%MBM +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%KBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%KBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%KBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%KBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%KBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%KBB)) THEN + ALLOCATE(DstCB_MatArraysData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiL,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiL,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiL)) THEN + ALLOCATE(DstCB_MatArraysData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%PhiL = SrcCB_MatArraysData%PhiL +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%PhiR)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiR,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiR,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiR,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiR,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiR)) THEN + ALLOCATE(DstCB_MatArraysData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%PhiR = SrcCB_MatArraysData%PhiR +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%OmegaL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%OmegaL,1) + i1_u = UBOUND(SrcCB_MatArraysData%OmegaL,1) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%OmegaL)) THEN + ALLOCATE(DstCB_MatArraysData%OmegaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%OmegaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%OmegaL = SrcCB_MatArraysData%OmegaL +ENDIF + END SUBROUTINE SD_CopyCB_MatArrays + + SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(INOUT) :: CB_MatArraysData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyCB_MatArrays' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(CB_MatArraysData%TI2)) THEN + DEALLOCATE(CB_MatArraysData%TI2) +ENDIF +IF (ALLOCATED(CB_MatArraysData%MBB)) THEN + DEALLOCATE(CB_MatArraysData%MBB) +ENDIF +IF (ALLOCATED(CB_MatArraysData%MBM)) THEN + DEALLOCATE(CB_MatArraysData%MBM) +ENDIF +IF (ALLOCATED(CB_MatArraysData%KBB)) THEN + DEALLOCATE(CB_MatArraysData%KBB) +ENDIF +IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN + DEALLOCATE(CB_MatArraysData%PhiL) +ENDIF +IF (ALLOCATED(CB_MatArraysData%PhiR)) THEN + DEALLOCATE(CB_MatArraysData%PhiR) +ENDIF +IF (ALLOCATED(CB_MatArraysData%OmegaL)) THEN + DEALLOCATE(CB_MatArraysData%OmegaL) +ENDIF + END SUBROUTINE SD_DestroyCB_MatArrays + + SUBROUTINE SD_PackCB_MatArrays( 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(CB_MatArrays), 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 = 'SD_PackCB_MatArrays' + ! 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 ! DOFM + Int_BufSz = Int_BufSz + 1 ! TI2 allocated yes/no + IF ( ALLOCATED(InData%TI2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI2) ! TI2 + END IF + Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no + IF ( ALLOCATED(InData%MBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB + END IF + Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no + IF ( ALLOCATED(InData%MBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM + END IF + Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no + IF ( ALLOCATED(InData%KBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB + END IF + Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no + IF ( ALLOCATED(InData%PhiL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiL) ! PhiL + END IF + Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no + IF ( ALLOCATED(InData%PhiR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiR) ! PhiR + END IF + Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no + IF ( ALLOCATED(InData%OmegaL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OmegaL) ! OmegaL + 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%DOFM + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%TI2) ) 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%TI2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TI2,2), UBOUND(InData%TI2,2) + DO i1 = LBOUND(InData%TI2,1), UBOUND(InData%TI2,1) + ReKiBuf(Re_Xferred) = InData%TI2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MBB) ) 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%MBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MBB,2), UBOUND(InData%MBB,2) + DO i1 = LBOUND(InData%MBB,1), UBOUND(InData%MBB,1) + ReKiBuf(Re_Xferred) = InData%MBB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MBM) ) 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%MBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MBM,2), UBOUND(InData%MBM,2) + DO i1 = LBOUND(InData%MBM,1), UBOUND(InData%MBM,1) + ReKiBuf(Re_Xferred) = InData%MBM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%KBB) ) 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%KBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%KBB,2), UBOUND(InData%KBB,2) + DO i1 = LBOUND(InData%KBB,1), UBOUND(InData%KBB,1) + ReKiBuf(Re_Xferred) = InData%KBB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiL) ) 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%PhiL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiL,2), UBOUND(InData%PhiL,2) + DO i1 = LBOUND(InData%PhiL,1), UBOUND(InData%PhiL,1) + ReKiBuf(Re_Xferred) = InData%PhiL(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiR) ) 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%PhiR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiR,2), UBOUND(InData%PhiR,2) + DO i1 = LBOUND(InData%PhiR,1), UBOUND(InData%PhiR,1) + ReKiBuf(Re_Xferred) = InData%PhiR(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OmegaL) ) 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%OmegaL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OmegaL,1), UBOUND(InData%OmegaL,1) + ReKiBuf(Re_Xferred) = InData%OmegaL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_PackCB_MatArrays + + SUBROUTINE SD_UnPackCB_MatArrays( 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(CB_MatArrays), 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 = 'SD_UnPackCB_MatArrays' + ! 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%DOFM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI2 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%TI2)) DEALLOCATE(OutData%TI2) + ALLOCATE(OutData%TI2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TI2,2), UBOUND(OutData%TI2,2) + DO i1 = LBOUND(OutData%TI2,1), UBOUND(OutData%TI2,1) + OutData%TI2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB 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%MBB)) DEALLOCATE(OutData%MBB) + ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MBB,2), UBOUND(OutData%MBB,2) + DO i1 = LBOUND(OutData%MBB,1), UBOUND(OutData%MBB,1) + OutData%MBB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM 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%MBM)) DEALLOCATE(OutData%MBM) + ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MBM,2), UBOUND(OutData%MBM,2) + DO i1 = LBOUND(OutData%MBM,1), UBOUND(OutData%MBM,1) + OutData%MBM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB 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%KBB)) DEALLOCATE(OutData%KBB) + ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%KBB,2), UBOUND(OutData%KBB,2) + DO i1 = LBOUND(OutData%KBB,1), UBOUND(OutData%KBB,1) + OutData%KBB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL 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%PhiL)) DEALLOCATE(OutData%PhiL) + ALLOCATE(OutData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiL,2), UBOUND(OutData%PhiL,2) + DO i1 = LBOUND(OutData%PhiL,1), UBOUND(OutData%PhiL,1) + OutData%PhiL(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR 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%PhiR)) DEALLOCATE(OutData%PhiR) + ALLOCATE(OutData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiR,2), UBOUND(OutData%PhiR,2) + DO i1 = LBOUND(OutData%PhiR,1), UBOUND(OutData%PhiR,1) + OutData%PhiR(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL 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%OmegaL)) DEALLOCATE(OutData%OmegaL) + ALLOCATE(OutData%OmegaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OmegaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OmegaL,1), UBOUND(OutData%OmegaL,1) + OutData%OmegaL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_UnPackCB_MatArrays + + SUBROUTINE SD_CopyFEM_MatArrays( SrcFEM_MatArraysData, DstFEM_MatArraysData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FEM_MatArrays), INTENT(IN) :: SrcFEM_MatArraysData + TYPE(FEM_MatArrays), INTENT(INOUT) :: DstFEM_MatArraysData + 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 = 'SD_CopyFEM_MatArrays' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcFEM_MatArraysData%Omega)) THEN + i1_l = LBOUND(SrcFEM_MatArraysData%Omega,1) + i1_u = UBOUND(SrcFEM_MatArraysData%Omega,1) + IF (.NOT. ALLOCATED(DstFEM_MatArraysData%Omega)) THEN + ALLOCATE(DstFEM_MatArraysData%Omega(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEM_MatArraysData%Omega.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFEM_MatArraysData%Omega = SrcFEM_MatArraysData%Omega +ENDIF + DstFEM_MatArraysData%NOmega = SrcFEM_MatArraysData%NOmega +IF (ALLOCATED(SrcFEM_MatArraysData%Modes)) THEN + i1_l = LBOUND(SrcFEM_MatArraysData%Modes,1) + i1_u = UBOUND(SrcFEM_MatArraysData%Modes,1) + i2_l = LBOUND(SrcFEM_MatArraysData%Modes,2) + i2_u = UBOUND(SrcFEM_MatArraysData%Modes,2) + IF (.NOT. ALLOCATED(DstFEM_MatArraysData%Modes)) THEN + ALLOCATE(DstFEM_MatArraysData%Modes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEM_MatArraysData%Modes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstFEM_MatArraysData%Modes = SrcFEM_MatArraysData%Modes +ENDIF + END SUBROUTINE SD_CopyFEM_MatArrays + + SUBROUTINE SD_DestroyFEM_MatArrays( FEM_MatArraysData, ErrStat, ErrMsg ) + TYPE(FEM_MatArrays), INTENT(INOUT) :: FEM_MatArraysData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyFEM_MatArrays' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(FEM_MatArraysData%Omega)) THEN + DEALLOCATE(FEM_MatArraysData%Omega) +ENDIF +IF (ALLOCATED(FEM_MatArraysData%Modes)) THEN + DEALLOCATE(FEM_MatArraysData%Modes) +ENDIF + END SUBROUTINE SD_DestroyFEM_MatArrays + + SUBROUTINE SD_PackFEM_MatArrays( 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(FEM_MatArrays), 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 = 'SD_PackFEM_MatArrays' + ! 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 ! Omega allocated yes/no + IF ( ALLOCATED(InData%Omega) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Omega upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Omega) ! Omega + END IF + Int_BufSz = Int_BufSz + 1 ! NOmega + Int_BufSz = Int_BufSz + 1 ! Modes allocated yes/no + IF ( ALLOCATED(InData%Modes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Modes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Modes) ! Modes + 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%Omega) ) 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%Omega,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Omega,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Omega,1), UBOUND(InData%Omega,1) + ReKiBuf(Re_Xferred) = InData%Omega(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NOmega + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Modes) ) 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%Modes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Modes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Modes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Modes,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Modes,2), UBOUND(InData%Modes,2) + DO i1 = LBOUND(InData%Modes,1), UBOUND(InData%Modes,1) + ReKiBuf(Re_Xferred) = InData%Modes(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE SD_PackFEM_MatArrays + + SUBROUTINE SD_UnPackFEM_MatArrays( 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(FEM_MatArrays), 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 = 'SD_UnPackFEM_MatArrays' + ! 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 ! Omega 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%Omega)) DEALLOCATE(OutData%Omega) + ALLOCATE(OutData%Omega(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Omega.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Omega,1), UBOUND(OutData%Omega,1) + OutData%Omega(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NOmega = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Modes 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%Modes)) DEALLOCATE(OutData%Modes) + ALLOCATE(OutData%Modes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Modes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Modes,2), UBOUND(OutData%Modes,2) + DO i1 = LBOUND(OutData%Modes,1), UBOUND(OutData%Modes,1) + OutData%Modes(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE SD_UnPackFEM_MatArrays + + SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData + TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData + 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 = 'SD_CopyElemPropType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElemPropTypeData%Area = SrcElemPropTypeData%Area + DstElemPropTypeData%Length = SrcElemPropTypeData%Length + DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx + DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy + DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz + DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear + DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa + DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE + DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG + DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho + DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos + END SUBROUTINE SD_CopyElemPropType + + SUBROUTINE SD_DestroyElemPropType( ElemPropTypeData, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(INOUT) :: ElemPropTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyElemPropType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyElemPropType + + SUBROUTINE SD_PackElemPropType( 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(ElemPropType), 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 = 'SD_PackElemPropType' + ! 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 ! Area + Re_BufSz = Re_BufSz + 1 ! Length + Re_BufSz = Re_BufSz + 1 ! Ixx + Re_BufSz = Re_BufSz + 1 ! Iyy + Re_BufSz = Re_BufSz + 1 ! Jzz + Int_BufSz = Int_BufSz + 1 ! Shear + Re_BufSz = Re_BufSz + 1 ! Kappa + Re_BufSz = Re_BufSz + 1 ! YoungE + Re_BufSz = Re_BufSz + 1 ! ShearG + Re_BufSz = Re_BufSz + 1 ! Rho + Re_BufSz = Re_BufSz + SIZE(InData%DirCos) ! DirCos + 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%Area + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Length + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ixx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Iyy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Jzz + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Shear, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kappa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YoungE + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShearG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rho + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%DirCos,2), UBOUND(InData%DirCos,2) + DO i1 = LBOUND(InData%DirCos,1), UBOUND(InData%DirCos,1) + ReKiBuf(Re_Xferred) = InData%DirCos(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SD_PackElemPropType + + SUBROUTINE SD_UnPackElemPropType( 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(ElemPropType), 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 = 'SD_UnPackElemPropType' + ! 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%Area = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Length = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ixx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Iyy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Jzz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Shear = TRANSFER(IntKiBuf(Int_Xferred), OutData%Shear) + Int_Xferred = Int_Xferred + 1 + OutData%Kappa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YoungE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShearG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rho = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%DirCos,1) + i1_u = UBOUND(OutData%DirCos,1) + i2_l = LBOUND(OutData%DirCos,2) + i2_u = UBOUND(OutData%DirCos,2) + DO i2 = LBOUND(OutData%DirCos,2), UBOUND(OutData%DirCos,2) + DO i1 = LBOUND(OutData%DirCos,1), UBOUND(OutData%DirCos,1) + OutData%DirCos(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END SUBROUTINE SD_UnPackElemPropType + + SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT(IN) :: SrcInitTypeData + TYPE(SD_InitType), INTENT(INOUT) :: DstInitTypeData + 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 = 'SD_CopyInitType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitTypeData%RootName = SrcInitTypeData%RootName + DstInitTypeData%TP_RefPoint = SrcInitTypeData%TP_RefPoint + DstInitTypeData%SubRotateZ = SrcInitTypeData%SubRotateZ + DstInitTypeData%g = SrcInitTypeData%g + DstInitTypeData%DT = SrcInitTypeData%DT + DstInitTypeData%NJoints = SrcInitTypeData%NJoints + DstInitTypeData%NPropSets = SrcInitTypeData%NPropSets + DstInitTypeData%NXPropSets = SrcInitTypeData%NXPropSets + DstInitTypeData%NInterf = SrcInitTypeData%NInterf + DstInitTypeData%NCMass = SrcInitTypeData%NCMass + DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs + DstInitTypeData%FEMMod = SrcInitTypeData%FEMMod + DstInitTypeData%NDiv = SrcInitTypeData%NDiv + DstInitTypeData%CBMod = SrcInitTypeData%CBMod +IF (ALLOCATED(SrcInitTypeData%Joints)) THEN + i1_l = LBOUND(SrcInitTypeData%Joints,1) + i1_u = UBOUND(SrcInitTypeData%Joints,1) + i2_l = LBOUND(SrcInitTypeData%Joints,2) + i2_u = UBOUND(SrcInitTypeData%Joints,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Joints)) THEN + ALLOCATE(DstInitTypeData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Joints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Joints = SrcInitTypeData%Joints +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropSets)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSets,1) + i1_u = UBOUND(SrcInitTypeData%PropSets,1) + i2_l = LBOUND(SrcInitTypeData%PropSets,2) + i2_u = UBOUND(SrcInitTypeData%PropSets,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSets)) THEN + ALLOCATE(DstInitTypeData%PropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropSets = SrcInitTypeData%PropSets +ENDIF +IF (ALLOCATED(SrcInitTypeData%XPropSets)) THEN + i1_l = LBOUND(SrcInitTypeData%XPropSets,1) + i1_u = UBOUND(SrcInitTypeData%XPropSets,1) + i2_l = LBOUND(SrcInitTypeData%XPropSets,2) + i2_u = UBOUND(SrcInitTypeData%XPropSets,2) + IF (.NOT. ALLOCATED(DstInitTypeData%XPropSets)) THEN + ALLOCATE(DstInitTypeData%XPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%XPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%XPropSets = SrcInitTypeData%XPropSets +ENDIF +IF (ALLOCATED(SrcInitTypeData%COSMs)) THEN + i1_l = LBOUND(SrcInitTypeData%COSMs,1) + i1_u = UBOUND(SrcInitTypeData%COSMs,1) + i2_l = LBOUND(SrcInitTypeData%COSMs,2) + i2_u = UBOUND(SrcInitTypeData%COSMs,2) + IF (.NOT. ALLOCATED(DstInitTypeData%COSMs)) THEN + ALLOCATE(DstInitTypeData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%COSMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%COSMs = SrcInitTypeData%COSMs +ENDIF +IF (ALLOCATED(SrcInitTypeData%CMass)) THEN + i1_l = LBOUND(SrcInitTypeData%CMass,1) + i1_u = UBOUND(SrcInitTypeData%CMass,1) + i2_l = LBOUND(SrcInitTypeData%CMass,2) + i2_u = UBOUND(SrcInitTypeData%CMass,2) + IF (.NOT. ALLOCATED(DstInitTypeData%CMass)) THEN + ALLOCATE(DstInitTypeData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%CMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%CMass = SrcInitTypeData%CMass +ENDIF +IF (ALLOCATED(SrcInitTypeData%JDampings)) THEN + i1_l = LBOUND(SrcInitTypeData%JDampings,1) + i1_u = UBOUND(SrcInitTypeData%JDampings,1) + IF (.NOT. ALLOCATED(DstInitTypeData%JDampings)) THEN + ALLOCATE(DstInitTypeData%JDampings(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%JDampings.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%JDampings = SrcInitTypeData%JDampings +ENDIF +IF (ALLOCATED(SrcInitTypeData%Members)) THEN + i1_l = LBOUND(SrcInitTypeData%Members,1) + i1_u = UBOUND(SrcInitTypeData%Members,1) + i2_l = LBOUND(SrcInitTypeData%Members,2) + i2_u = UBOUND(SrcInitTypeData%Members,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Members)) THEN + ALLOCATE(DstInitTypeData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Members.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Members = SrcInitTypeData%Members +ENDIF +IF (ALLOCATED(SrcInitTypeData%Interf)) THEN + i1_l = LBOUND(SrcInitTypeData%Interf,1) + i1_u = UBOUND(SrcInitTypeData%Interf,1) + i2_l = LBOUND(SrcInitTypeData%Interf,2) + i2_u = UBOUND(SrcInitTypeData%Interf,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Interf)) THEN + ALLOCATE(DstInitTypeData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Interf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Interf = SrcInitTypeData%Interf +ENDIF +IF (ALLOCATED(SrcInitTypeData%SSOutList)) THEN + i1_l = LBOUND(SrcInitTypeData%SSOutList,1) + i1_u = UBOUND(SrcInitTypeData%SSOutList,1) + IF (.NOT. ALLOCATED(DstInitTypeData%SSOutList)) THEN + ALLOCATE(DstInitTypeData%SSOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSOutList = SrcInitTypeData%SSOutList +ENDIF + DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM + DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim + DstInitTypeData%NNode = SrcInitTypeData%NNode + DstInitTypeData%NElem = SrcInitTypeData%NElem + DstInitTypeData%NProp = SrcInitTypeData%NProp + DstInitTypeData%TDOF = SrcInitTypeData%TDOF +IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN + i1_l = LBOUND(SrcInitTypeData%Nodes,1) + i1_u = UBOUND(SrcInitTypeData%Nodes,1) + i2_l = LBOUND(SrcInitTypeData%Nodes,2) + i2_u = UBOUND(SrcInitTypeData%Nodes,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Nodes)) THEN + ALLOCATE(DstInitTypeData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Nodes = SrcInitTypeData%Nodes +ENDIF +IF (ALLOCATED(SrcInitTypeData%Props)) THEN + i1_l = LBOUND(SrcInitTypeData%Props,1) + i1_u = UBOUND(SrcInitTypeData%Props,1) + i2_l = LBOUND(SrcInitTypeData%Props,2) + i2_u = UBOUND(SrcInitTypeData%Props,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Props)) THEN + ALLOCATE(DstInitTypeData%Props(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Props.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Props = SrcInitTypeData%Props +ENDIF +IF (ALLOCATED(SrcInitTypeData%K)) THEN + i1_l = LBOUND(SrcInitTypeData%K,1) + i1_u = UBOUND(SrcInitTypeData%K,1) + i2_l = LBOUND(SrcInitTypeData%K,2) + i2_u = UBOUND(SrcInitTypeData%K,2) + IF (.NOT. ALLOCATED(DstInitTypeData%K)) THEN + ALLOCATE(DstInitTypeData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%K = SrcInitTypeData%K +ENDIF +IF (ALLOCATED(SrcInitTypeData%M)) THEN + i1_l = LBOUND(SrcInitTypeData%M,1) + i1_u = UBOUND(SrcInitTypeData%M,1) + i2_l = LBOUND(SrcInitTypeData%M,2) + i2_u = UBOUND(SrcInitTypeData%M,2) + IF (.NOT. ALLOCATED(DstInitTypeData%M)) THEN + ALLOCATE(DstInitTypeData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%M = SrcInitTypeData%M +ENDIF +IF (ALLOCATED(SrcInitTypeData%F)) THEN + i1_l = LBOUND(SrcInitTypeData%F,1) + i1_u = UBOUND(SrcInitTypeData%F,1) + IF (.NOT. ALLOCATED(DstInitTypeData%F)) THEN + ALLOCATE(DstInitTypeData%F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%F = SrcInitTypeData%F +ENDIF +IF (ALLOCATED(SrcInitTypeData%FG)) THEN + i1_l = LBOUND(SrcInitTypeData%FG,1) + i1_u = UBOUND(SrcInitTypeData%FG,1) + IF (.NOT. ALLOCATED(DstInitTypeData%FG)) THEN + ALLOCATE(DstInitTypeData%FG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%FG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%FG = SrcInitTypeData%FG +ENDIF +IF (ALLOCATED(SrcInitTypeData%ElemProps)) THEN + i1_l = LBOUND(SrcInitTypeData%ElemProps,1) + i1_u = UBOUND(SrcInitTypeData%ElemProps,1) + i2_l = LBOUND(SrcInitTypeData%ElemProps,2) + i2_u = UBOUND(SrcInitTypeData%ElemProps,2) + IF (.NOT. ALLOCATED(DstInitTypeData%ElemProps)) THEN + ALLOCATE(DstInitTypeData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%ElemProps = SrcInitTypeData%ElemProps +ENDIF +IF (ALLOCATED(SrcInitTypeData%BCs)) THEN + i1_l = LBOUND(SrcInitTypeData%BCs,1) + i1_u = UBOUND(SrcInitTypeData%BCs,1) + i2_l = LBOUND(SrcInitTypeData%BCs,2) + i2_u = UBOUND(SrcInitTypeData%BCs,2) + IF (.NOT. ALLOCATED(DstInitTypeData%BCs)) THEN + ALLOCATE(DstInitTypeData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%BCs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%BCs = SrcInitTypeData%BCs +ENDIF +IF (ALLOCATED(SrcInitTypeData%IntFc)) THEN + i1_l = LBOUND(SrcInitTypeData%IntFc,1) + i1_u = UBOUND(SrcInitTypeData%IntFc,1) + i2_l = LBOUND(SrcInitTypeData%IntFc,2) + i2_u = UBOUND(SrcInitTypeData%IntFc,2) + IF (.NOT. ALLOCATED(DstInitTypeData%IntFc)) THEN + ALLOCATE(DstInitTypeData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%IntFc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%IntFc = SrcInitTypeData%IntFc +ENDIF +IF (ALLOCATED(SrcInitTypeData%MemberNodes)) THEN + i1_l = LBOUND(SrcInitTypeData%MemberNodes,1) + i1_u = UBOUND(SrcInitTypeData%MemberNodes,1) + i2_l = LBOUND(SrcInitTypeData%MemberNodes,2) + i2_u = UBOUND(SrcInitTypeData%MemberNodes,2) + IF (.NOT. ALLOCATED(DstInitTypeData%MemberNodes)) THEN + ALLOCATE(DstInitTypeData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%MemberNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%MemberNodes = SrcInitTypeData%MemberNodes +ENDIF +IF (ALLOCATED(SrcInitTypeData%NodesConnN)) THEN + i1_l = LBOUND(SrcInitTypeData%NodesConnN,1) + i1_u = UBOUND(SrcInitTypeData%NodesConnN,1) + i2_l = LBOUND(SrcInitTypeData%NodesConnN,2) + i2_u = UBOUND(SrcInitTypeData%NodesConnN,2) + IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnN)) THEN + ALLOCATE(DstInitTypeData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%NodesConnN = SrcInitTypeData%NodesConnN +ENDIF +IF (ALLOCATED(SrcInitTypeData%NodesConnE)) THEN + i1_l = LBOUND(SrcInitTypeData%NodesConnE,1) + i1_u = UBOUND(SrcInitTypeData%NodesConnE,1) + i2_l = LBOUND(SrcInitTypeData%NodesConnE,2) + i2_u = UBOUND(SrcInitTypeData%NodesConnE,2) + IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnE)) THEN + ALLOCATE(DstInitTypeData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%NodesConnE = SrcInitTypeData%NodesConnE +ENDIF + DstInitTypeData%SSSum = SrcInitTypeData%SSSum + END SUBROUTINE SD_CopyInitType + + SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT(INOUT) :: InitTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitTypeData%Joints)) THEN + DEALLOCATE(InitTypeData%Joints) +ENDIF +IF (ALLOCATED(InitTypeData%PropSets)) THEN + DEALLOCATE(InitTypeData%PropSets) +ENDIF +IF (ALLOCATED(InitTypeData%XPropSets)) THEN + DEALLOCATE(InitTypeData%XPropSets) +ENDIF +IF (ALLOCATED(InitTypeData%COSMs)) THEN + DEALLOCATE(InitTypeData%COSMs) +ENDIF +IF (ALLOCATED(InitTypeData%CMass)) THEN + DEALLOCATE(InitTypeData%CMass) +ENDIF +IF (ALLOCATED(InitTypeData%JDampings)) THEN + DEALLOCATE(InitTypeData%JDampings) +ENDIF +IF (ALLOCATED(InitTypeData%Members)) THEN + DEALLOCATE(InitTypeData%Members) +ENDIF +IF (ALLOCATED(InitTypeData%Interf)) THEN + DEALLOCATE(InitTypeData%Interf) +ENDIF +IF (ALLOCATED(InitTypeData%SSOutList)) THEN + DEALLOCATE(InitTypeData%SSOutList) +ENDIF +IF (ALLOCATED(InitTypeData%Nodes)) THEN + DEALLOCATE(InitTypeData%Nodes) +ENDIF +IF (ALLOCATED(InitTypeData%Props)) THEN + DEALLOCATE(InitTypeData%Props) +ENDIF +IF (ALLOCATED(InitTypeData%K)) THEN + DEALLOCATE(InitTypeData%K) +ENDIF +IF (ALLOCATED(InitTypeData%M)) THEN + DEALLOCATE(InitTypeData%M) +ENDIF +IF (ALLOCATED(InitTypeData%F)) THEN + DEALLOCATE(InitTypeData%F) +ENDIF +IF (ALLOCATED(InitTypeData%FG)) THEN + DEALLOCATE(InitTypeData%FG) +ENDIF +IF (ALLOCATED(InitTypeData%ElemProps)) THEN + DEALLOCATE(InitTypeData%ElemProps) +ENDIF +IF (ALLOCATED(InitTypeData%BCs)) THEN + DEALLOCATE(InitTypeData%BCs) +ENDIF +IF (ALLOCATED(InitTypeData%IntFc)) THEN + DEALLOCATE(InitTypeData%IntFc) +ENDIF +IF (ALLOCATED(InitTypeData%MemberNodes)) THEN + DEALLOCATE(InitTypeData%MemberNodes) +ENDIF +IF (ALLOCATED(InitTypeData%NodesConnN)) THEN + DEALLOCATE(InitTypeData%NodesConnN) +ENDIF +IF (ALLOCATED(InitTypeData%NodesConnE)) THEN + DEALLOCATE(InitTypeData%NodesConnE) +ENDIF + END SUBROUTINE SD_DestroyInitType + + SUBROUTINE SD_PackInitType( 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(SD_InitType), 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 = 'SD_PackInitType' + ! 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%RootName) ! RootName + Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint + Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Re_BufSz = Re_BufSz + 1 ! g + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NJoints + Int_BufSz = Int_BufSz + 1 ! NPropSets + Int_BufSz = Int_BufSz + 1 ! NXPropSets + Int_BufSz = Int_BufSz + 1 ! NInterf + Int_BufSz = Int_BufSz + 1 ! NCMass + Int_BufSz = Int_BufSz + 1 ! NCOSMs + Int_BufSz = Int_BufSz + 1 ! FEMMod + Int_BufSz = Int_BufSz + 1 ! NDiv + Int_BufSz = Int_BufSz + 1 ! CBMod + Int_BufSz = Int_BufSz + 1 ! Joints allocated yes/no + IF ( ALLOCATED(InData%Joints) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Joints upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Joints) ! Joints + END IF + Int_BufSz = Int_BufSz + 1 ! PropSets allocated yes/no + IF ( ALLOCATED(InData%PropSets) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSets upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSets) ! PropSets + END IF + Int_BufSz = Int_BufSz + 1 ! XPropSets allocated yes/no + IF ( ALLOCATED(InData%XPropSets) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! XPropSets upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%XPropSets) ! XPropSets + END IF + Int_BufSz = Int_BufSz + 1 ! COSMs allocated yes/no + IF ( ALLOCATED(InData%COSMs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! COSMs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%COSMs) ! COSMs + END IF + Int_BufSz = Int_BufSz + 1 ! CMass allocated yes/no + IF ( ALLOCATED(InData%CMass) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMass) ! CMass + END IF + Int_BufSz = Int_BufSz + 1 ! JDampings allocated yes/no + IF ( ALLOCATED(InData%JDampings) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! JDampings upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%JDampings) ! JDampings + END IF + Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no + IF ( ALLOCATED(InData%Members) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Members upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Members) ! Members + END IF + Int_BufSz = Int_BufSz + 1 ! Interf allocated yes/no + IF ( ALLOCATED(InData%Interf) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Interf upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Interf) ! Interf + END IF + Int_BufSz = Int_BufSz + 1 ! SSOutList allocated yes/no + IF ( ALLOCATED(InData%SSOutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SSOutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SSOutList)*LEN(InData%SSOutList) ! SSOutList + END IF + Int_BufSz = Int_BufSz + 1 ! OutCOSM + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1 ! NNode + Int_BufSz = Int_BufSz + 1 ! NElem + Int_BufSz = Int_BufSz + 1 ! NProp + Int_BufSz = Int_BufSz + 1 ! TDOF + Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no + IF ( ALLOCATED(InData%Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Nodes) ! Nodes + END IF + Int_BufSz = Int_BufSz + 1 ! Props allocated yes/no + IF ( ALLOCATED(InData%Props) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Props upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Props) ! Props + END IF + Int_BufSz = Int_BufSz + 1 ! K allocated yes/no + IF ( ALLOCATED(InData%K) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K) ! K + END IF + Int_BufSz = Int_BufSz + 1 ! M allocated yes/no + IF ( ALLOCATED(InData%M) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + END IF + Int_BufSz = Int_BufSz + 1 ! F allocated yes/no + IF ( ALLOCATED(InData%F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + END IF + Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no + IF ( ALLOCATED(InData%FG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FG) ! FG + END IF + Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no + IF ( ALLOCATED(InData%ElemProps) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElemProps upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ElemProps) ! ElemProps + END IF + Int_BufSz = Int_BufSz + 1 ! BCs allocated yes/no + IF ( ALLOCATED(InData%BCs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BCs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BCs) ! BCs + END IF + Int_BufSz = Int_BufSz + 1 ! IntFc allocated yes/no + IF ( ALLOCATED(InData%IntFc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! IntFc upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IntFc) ! IntFc + END IF + Int_BufSz = Int_BufSz + 1 ! MemberNodes allocated yes/no + IF ( ALLOCATED(InData%MemberNodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MemberNodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MemberNodes) ! MemberNodes + END IF + Int_BufSz = Int_BufSz + 1 ! NodesConnN allocated yes/no + IF ( ALLOCATED(InData%NodesConnN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! NodesConnN upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodesConnN) ! NodesConnN + END IF + Int_BufSz = Int_BufSz + 1 ! NodesConnE allocated yes/no + IF ( ALLOCATED(InData%NodesConnE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! NodesConnE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodesConnE) ! NodesConnE + END IF + Int_BufSz = Int_BufSz + 1 ! SSSum + 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%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) + ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropSets + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NXPropSets + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NInterf + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NCMass + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NCOSMs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%FEMMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NDiv + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CBMod, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Joints) ) 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%Joints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Joints,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Joints,2), UBOUND(InData%Joints,2) + DO i1 = LBOUND(InData%Joints,1), UBOUND(InData%Joints,1) + ReKiBuf(Re_Xferred) = InData%Joints(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PropSets) ) 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%PropSets,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSets,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSets,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSets,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PropSets,2), UBOUND(InData%PropSets,2) + DO i1 = LBOUND(InData%PropSets,1), UBOUND(InData%PropSets,1) + ReKiBuf(Re_Xferred) = InData%PropSets(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%XPropSets) ) 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%XPropSets,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XPropSets,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%XPropSets,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XPropSets,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%XPropSets,2), UBOUND(InData%XPropSets,2) + DO i1 = LBOUND(InData%XPropSets,1), UBOUND(InData%XPropSets,1) + ReKiBuf(Re_Xferred) = InData%XPropSets(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%COSMs) ) 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%COSMs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%COSMs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%COSMs,2), UBOUND(InData%COSMs,2) + DO i1 = LBOUND(InData%COSMs,1), UBOUND(InData%COSMs,1) + ReKiBuf(Re_Xferred) = InData%COSMs(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CMass) ) 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%CMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CMass,2), UBOUND(InData%CMass,2) + DO i1 = LBOUND(InData%CMass,1), UBOUND(InData%CMass,1) + ReKiBuf(Re_Xferred) = InData%CMass(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%JDampings) ) 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%JDampings,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JDampings,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%JDampings,1), UBOUND(InData%JDampings,1) + ReKiBuf(Re_Xferred) = InData%JDampings(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Members) ) 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%Members,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Members,2), UBOUND(InData%Members,2) + DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) + IntKiBuf(Int_Xferred) = InData%Members(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Interf) ) 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%Interf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Interf,2), UBOUND(InData%Interf,2) + DO i1 = LBOUND(InData%Interf,1), UBOUND(InData%Interf,1) + IntKiBuf(Int_Xferred) = InData%Interf(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SSOutList) ) 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%SSOutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSOutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SSOutList,1), UBOUND(InData%SSOutList,1) + DO I = 1, LEN(InData%SSOutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%SSOutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutCOSM, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNode + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NElem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NProp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TDOF + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nodes) ) 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%Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Nodes,2), UBOUND(InData%Nodes,2) + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + ReKiBuf(Re_Xferred) = InData%Nodes(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Props) ) 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%Props,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Props,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Props,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Props,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Props,2), UBOUND(InData%Props,2) + DO i1 = LBOUND(InData%Props,1), UBOUND(InData%Props,1) + ReKiBuf(Re_Xferred) = InData%Props(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%K) ) 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%K,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%K,2), UBOUND(InData%K,2) + DO i1 = LBOUND(InData%K,1), UBOUND(InData%K,1) + ReKiBuf(Re_Xferred) = InData%K(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%M) ) 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%M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%M,2), UBOUND(InData%M,2) + DO i1 = LBOUND(InData%M,1), UBOUND(InData%M,1) + ReKiBuf(Re_Xferred) = InData%M(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F) ) 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%F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F,1), UBOUND(InData%F,1) + ReKiBuf(Re_Xferred) = InData%F(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FG) ) 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%FG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FG,1), UBOUND(InData%FG,1) + ReKiBuf(Re_Xferred) = InData%FG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElemProps) ) 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%ElemProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ElemProps,2), UBOUND(InData%ElemProps,2) + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + ReKiBuf(Re_Xferred) = InData%ElemProps(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%BCs) ) 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%BCs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%BCs,2), UBOUND(InData%BCs,2) + DO i1 = LBOUND(InData%BCs,1), UBOUND(InData%BCs,1) + IntKiBuf(Int_Xferred) = InData%BCs(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IntFc) ) 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%IntFc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%IntFc,2), UBOUND(InData%IntFc,2) + DO i1 = LBOUND(InData%IntFc,1), UBOUND(InData%IntFc,1) + IntKiBuf(Int_Xferred) = InData%IntFc(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MemberNodes) ) 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%MemberNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberNodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MemberNodes,2), UBOUND(InData%MemberNodes,2) + DO i1 = LBOUND(InData%MemberNodes,1), UBOUND(InData%MemberNodes,1) + IntKiBuf(Int_Xferred) = InData%MemberNodes(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodesConnN) ) 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%NodesConnN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%NodesConnN,2), UBOUND(InData%NodesConnN,2) + DO i1 = LBOUND(InData%NodesConnN,1), UBOUND(InData%NodesConnN,1) + IntKiBuf(Int_Xferred) = InData%NodesConnN(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodesConnE) ) 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%NodesConnE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%NodesConnE,2), UBOUND(InData%NodesConnE,2) + DO i1 = LBOUND(InData%NodesConnE,1), UBOUND(InData%NodesConnE,1) + IntKiBuf(Int_Xferred) = InData%NodesConnE(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%SSSum, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackInitType + + SUBROUTINE SD_UnPackInitType( 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(SD_InitType), 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 = 'SD_UnPackInitType' + ! 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%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%TP_RefPoint,1) + i1_u = UBOUND(OutData%TP_RefPoint,1) + DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) + OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%SubRotateZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NJoints = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSets = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NXPropSets = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NInterf = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NCMass = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NCOSMs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FEMMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NDiv = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CBMod = TRANSFER(IntKiBuf(Int_Xferred), OutData%CBMod) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Joints 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%Joints)) DEALLOCATE(OutData%Joints) + ALLOCATE(OutData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Joints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Joints,2), UBOUND(OutData%Joints,2) + DO i1 = LBOUND(OutData%Joints,1), UBOUND(OutData%Joints,1) + OutData%Joints(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSets 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%PropSets)) DEALLOCATE(OutData%PropSets) + ALLOCATE(OutData%PropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PropSets,2), UBOUND(OutData%PropSets,2) + DO i1 = LBOUND(OutData%PropSets,1), UBOUND(OutData%PropSets,1) + OutData%PropSets(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! XPropSets 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%XPropSets)) DEALLOCATE(OutData%XPropSets) + ALLOCATE(OutData%XPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%XPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%XPropSets,2), UBOUND(OutData%XPropSets,2) + DO i1 = LBOUND(OutData%XPropSets,1), UBOUND(OutData%XPropSets,1) + OutData%XPropSets(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs 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%COSMs)) DEALLOCATE(OutData%COSMs) + ALLOCATE(OutData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%COSMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%COSMs,2), UBOUND(OutData%COSMs,2) + DO i1 = LBOUND(OutData%COSMs,1), UBOUND(OutData%COSMs,1) + OutData%COSMs(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMass 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%CMass)) DEALLOCATE(OutData%CMass) + ALLOCATE(OutData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CMass,2), UBOUND(OutData%CMass,2) + DO i1 = LBOUND(OutData%CMass,1), UBOUND(OutData%CMass,1) + OutData%CMass(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JDampings 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%JDampings)) DEALLOCATE(OutData%JDampings) + ALLOCATE(OutData%JDampings(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JDampings.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%JDampings,1), UBOUND(OutData%JDampings,1) + OutData%JDampings(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members 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%Members)) DEALLOCATE(OutData%Members) + ALLOCATE(OutData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Members,2), UBOUND(OutData%Members,2) + DO i1 = LBOUND(OutData%Members,1), UBOUND(OutData%Members,1) + OutData%Members(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Interf 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%Interf)) DEALLOCATE(OutData%Interf) + ALLOCATE(OutData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Interf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Interf,2), UBOUND(OutData%Interf,2) + DO i1 = LBOUND(OutData%Interf,1), UBOUND(OutData%Interf,1) + OutData%Interf(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSOutList 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%SSOutList)) DEALLOCATE(OutData%SSOutList) + ALLOCATE(OutData%SSOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SSOutList,1), UBOUND(OutData%SSOutList,1) + DO I = 1, LEN(OutData%SSOutList) + OutData%SSOutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%OutCOSM = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutCOSM) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 + OutData%NNode = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NElem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NProp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%TDOF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes 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%Nodes)) DEALLOCATE(OutData%Nodes) + ALLOCATE(OutData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Nodes,2), UBOUND(OutData%Nodes,2) + DO i1 = LBOUND(OutData%Nodes,1), UBOUND(OutData%Nodes,1) + OutData%Nodes(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Props 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%Props)) DEALLOCATE(OutData%Props) + ALLOCATE(OutData%Props(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Props.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Props,2), UBOUND(OutData%Props,2) + DO i1 = LBOUND(OutData%Props,1), UBOUND(OutData%Props,1) + OutData%Props(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K 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%K)) DEALLOCATE(OutData%K) + ALLOCATE(OutData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%K,2), UBOUND(OutData%K,2) + DO i1 = LBOUND(OutData%K,1), UBOUND(OutData%K,1) + OutData%K(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M 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%M)) DEALLOCATE(OutData%M) + ALLOCATE(OutData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%M,2), UBOUND(OutData%M,2) + DO i1 = LBOUND(OutData%M,1), UBOUND(OutData%M,1) + OutData%M(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F 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%F)) DEALLOCATE(OutData%F) + ALLOCATE(OutData%F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F,1), UBOUND(OutData%F,1) + OutData%F(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG 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%FG)) DEALLOCATE(OutData%FG) + ALLOCATE(OutData%FG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FG,1), UBOUND(OutData%FG,1) + OutData%FG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps 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%ElemProps)) DEALLOCATE(OutData%ElemProps) + ALLOCATE(OutData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ElemProps,2), UBOUND(OutData%ElemProps,2) + DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,1) + OutData%ElemProps(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BCs 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%BCs)) DEALLOCATE(OutData%BCs) + ALLOCATE(OutData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BCs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%BCs,2), UBOUND(OutData%BCs,2) + DO i1 = LBOUND(OutData%BCs,1), UBOUND(OutData%BCs,1) + OutData%BCs(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IntFc 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%IntFc)) DEALLOCATE(OutData%IntFc) + ALLOCATE(OutData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IntFc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%IntFc,2), UBOUND(OutData%IntFc,2) + DO i1 = LBOUND(OutData%IntFc,1), UBOUND(OutData%IntFc,1) + OutData%IntFc(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberNodes 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%MemberNodes)) DEALLOCATE(OutData%MemberNodes) + ALLOCATE(OutData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MemberNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MemberNodes,2), UBOUND(OutData%MemberNodes,2) + DO i1 = LBOUND(OutData%MemberNodes,1), UBOUND(OutData%MemberNodes,1) + OutData%MemberNodes(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnN 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%NodesConnN)) DEALLOCATE(OutData%NodesConnN) + ALLOCATE(OutData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%NodesConnN,2), UBOUND(OutData%NodesConnN,2) + DO i1 = LBOUND(OutData%NodesConnN,1), UBOUND(OutData%NodesConnN,1) + OutData%NodesConnN(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnE 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%NodesConnE)) DEALLOCATE(OutData%NodesConnE) + ALLOCATE(OutData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%NodesConnE,2), UBOUND(OutData%NodesConnE,2) + DO i1 = LBOUND(OutData%NodesConnE,1), UBOUND(OutData%NodesConnE,1) + OutData%NodesConnE(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%SSSum = TRANSFER(IntKiBuf(Int_Xferred), OutData%SSSum) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackInitType + + SUBROUTINE SD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%qm)) THEN + i1_l = LBOUND(SrcContStateData%qm,1) + i1_u = UBOUND(SrcContStateData%qm,1) + IF (.NOT. ALLOCATED(DstContStateData%qm)) THEN + ALLOCATE(DstContStateData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qm = SrcContStateData%qm +ENDIF +IF (ALLOCATED(SrcContStateData%qmdot)) THEN + i1_l = LBOUND(SrcContStateData%qmdot,1) + i1_u = UBOUND(SrcContStateData%qmdot,1) + IF (.NOT. ALLOCATED(DstContStateData%qmdot)) THEN + ALLOCATE(DstContStateData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qmdot = SrcContStateData%qmdot +ENDIF + END SUBROUTINE SD_CopyContState + + SUBROUTINE SD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%qm)) THEN + DEALLOCATE(ContStateData%qm) +ENDIF +IF (ALLOCATED(ContStateData%qmdot)) THEN + DEALLOCATE(ContStateData%qmdot) +ENDIF + END SUBROUTINE SD_DestroyContState + + SUBROUTINE SD_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(SD_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 = 'SD_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 + Int_BufSz = Int_BufSz + 1 ! qm allocated yes/no + IF ( ALLOCATED(InData%qm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qm) ! qm + END IF + Int_BufSz = Int_BufSz + 1 ! qmdot allocated yes/no + IF ( ALLOCATED(InData%qmdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qmdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qmdot) ! qmdot + 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%qm) ) 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%qm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qm,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%qm,1), UBOUND(InData%qm,1) + ReKiBuf(Re_Xferred) = InData%qm(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%qmdot) ) 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%qmdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%qmdot,1), UBOUND(InData%qmdot,1) + ReKiBuf(Re_Xferred) = InData%qmdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_PackContState + + SUBROUTINE SD_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(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qm 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%qm)) DEALLOCATE(OutData%qm) + ALLOCATE(OutData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%qm,1), UBOUND(OutData%qm,1) + OutData%qm(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdot 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%qmdot)) DEALLOCATE(OutData%qmdot) + ALLOCATE(OutData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%qmdot,1), UBOUND(OutData%qmdot,1) + OutData%qmdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_UnPackContState + + SUBROUTINE SD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(SD_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 = 'SD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE SD_CopyDiscState + + SUBROUTINE SD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyDiscState + + SUBROUTINE SD_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(SD_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 = 'SD_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 SD_PackDiscState + + SUBROUTINE SD_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(SD_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 = 'SD_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 SD_UnPackDiscState + + SUBROUTINE SD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(SD_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 = 'SD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE SD_CopyConstrState + + SUBROUTINE SD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyConstrState + + SUBROUTINE SD_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(SD_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 = 'SD_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 SD_PackConstrState + + SUBROUTINE SD_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(SD_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 = 'SD_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 SD_UnPackConstrState + + SUBROUTINE SD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(SD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%xdot)) THEN + i1_l = LBOUND(SrcOtherStateData%xdot,1) + i1_u = UBOUND(SrcOtherStateData%xdot,1) + IF (.NOT. ALLOCATED(DstOtherStateData%xdot)) THEN + ALLOCATE(DstOtherStateData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL SD_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstOtherStateData%n = SrcOtherStateData%n + END SUBROUTINE SD_CopyOtherState + + SUBROUTINE SD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%xdot)) THEN +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL SD_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OtherStateData%xdot) +ENDIF + END SUBROUTINE SD_DestroyOtherState + + SUBROUTINE SD_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(SD_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 = 'SD_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 + Int_BufSz = Int_BufSz + 1 ! xdot allocated yes/no + IF ( ALLOCATED(InData%xdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xdot upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! n + 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%xdot) ) 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%xdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + 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 + IntKiBuf(Int_Xferred) = InData%n + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackOtherState + + SUBROUTINE SD_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(SD_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) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdot 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%xdot)) DEALLOCATE(OutData%xdot) + ALLOCATE(OutData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,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 SD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + 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 DO + END IF + OutData%n = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackOtherState + + SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%qmdotdot)) THEN + i1_l = LBOUND(SrcMiscData%qmdotdot,1) + i1_u = UBOUND(SrcMiscData%qmdotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%qmdotdot)) THEN + ALLOCATE(DstMiscData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%qmdotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%qmdotdot = SrcMiscData%qmdotdot +ENDIF + DstMiscData%u_TP = SrcMiscData%u_TP + DstMiscData%udot_TP = SrcMiscData%udot_TP + DstMiscData%udotdot_TP = SrcMiscData%udotdot_TP +IF (ALLOCATED(SrcMiscData%UFL)) THEN + i1_l = LBOUND(SrcMiscData%UFL,1) + i1_u = UBOUND(SrcMiscData%UFL,1) + IF (.NOT. ALLOCATED(DstMiscData%UFL)) THEN + ALLOCATE(DstMiscData%UFL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UFL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UFL = SrcMiscData%UFL +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar,1) + i1_u = UBOUND(SrcMiscData%UR_bar,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar)) THEN + ALLOCATE(DstMiscData%UR_bar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar = SrcMiscData%UR_bar +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar_dot)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar_dot,1) + i1_u = UBOUND(SrcMiscData%UR_bar_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dot)) THEN + ALLOCATE(DstMiscData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar_dot = SrcMiscData%UR_bar_dot +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar_dotdot,1) + i1_u = UBOUND(SrcMiscData%UR_bar_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dotdot)) THEN + ALLOCATE(DstMiscData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar_dotdot = SrcMiscData%UR_bar_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%UL)) THEN + i1_l = LBOUND(SrcMiscData%UL,1) + i1_u = UBOUND(SrcMiscData%UL,1) + IF (.NOT. ALLOCATED(DstMiscData%UL)) THEN + ALLOCATE(DstMiscData%UL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL = SrcMiscData%UL +ENDIF +IF (ALLOCATED(SrcMiscData%UL_dot)) THEN + i1_l = LBOUND(SrcMiscData%UL_dot,1) + i1_u = UBOUND(SrcMiscData%UL_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%UL_dot)) THEN + ALLOCATE(DstMiscData%UL_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL_dot = SrcMiscData%UL_dot +ENDIF +IF (ALLOCATED(SrcMiscData%UL_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%UL_dotdot,1) + i1_u = UBOUND(SrcMiscData%UL_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%UL_dotdot)) THEN + ALLOCATE(DstMiscData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL_dotdot = SrcMiscData%UL_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN + i1_l = LBOUND(SrcMiscData%SDWrOutput,1) + i1_u = UBOUND(SrcMiscData%SDWrOutput,1) + IF (.NOT. ALLOCATED(DstMiscData%SDWrOutput)) THEN + ALLOCATE(DstMiscData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SDWrOutput = SrcMiscData%SDWrOutput +ENDIF + DstMiscData%LastOutTime = SrcMiscData%LastOutTime + DstMiscData%Decimat = SrcMiscData%Decimat + END SUBROUTINE SD_CopyMisc + + SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(SD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%qmdotdot)) THEN + DEALLOCATE(MiscData%qmdotdot) +ENDIF +IF (ALLOCATED(MiscData%UFL)) THEN + DEALLOCATE(MiscData%UFL) +ENDIF +IF (ALLOCATED(MiscData%UR_bar)) THEN + DEALLOCATE(MiscData%UR_bar) +ENDIF +IF (ALLOCATED(MiscData%UR_bar_dot)) THEN + DEALLOCATE(MiscData%UR_bar_dot) +ENDIF +IF (ALLOCATED(MiscData%UR_bar_dotdot)) THEN + DEALLOCATE(MiscData%UR_bar_dotdot) +ENDIF +IF (ALLOCATED(MiscData%UL)) THEN + DEALLOCATE(MiscData%UL) +ENDIF +IF (ALLOCATED(MiscData%UL_dot)) THEN + DEALLOCATE(MiscData%UL_dot) +ENDIF +IF (ALLOCATED(MiscData%UL_dotdot)) THEN + DEALLOCATE(MiscData%UL_dotdot) +ENDIF +IF (ALLOCATED(MiscData%SDWrOutput)) THEN + DEALLOCATE(MiscData%SDWrOutput) +ENDIF + END SUBROUTINE SD_DestroyMisc + + SUBROUTINE SD_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(SD_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 = 'SD_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 ! qmdotdot allocated yes/no + IF ( ALLOCATED(InData%qmdotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qmdotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qmdotdot) ! qmdotdot + END IF + Re_BufSz = Re_BufSz + SIZE(InData%u_TP) ! u_TP + Re_BufSz = Re_BufSz + SIZE(InData%udot_TP) ! udot_TP + Re_BufSz = Re_BufSz + SIZE(InData%udotdot_TP) ! udotdot_TP + Int_BufSz = Int_BufSz + 1 ! UFL allocated yes/no + IF ( ALLOCATED(InData%UFL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UFL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UFL) ! UFL + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar allocated yes/no + IF ( ALLOCATED(InData%UR_bar) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar) ! UR_bar + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar_dot allocated yes/no + IF ( ALLOCATED(InData%UR_bar_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dot) ! UR_bar_dot + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar_dotdot allocated yes/no + IF ( ALLOCATED(InData%UR_bar_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dotdot) ! UR_bar_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! UL allocated yes/no + IF ( ALLOCATED(InData%UL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL) ! UL + END IF + Int_BufSz = Int_BufSz + 1 ! UL_dot allocated yes/no + IF ( ALLOCATED(InData%UL_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_dot) ! UL_dot + END IF + Int_BufSz = Int_BufSz + 1 ! UL_dotdot allocated yes/no + IF ( ALLOCATED(InData%UL_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_dotdot) ! UL_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no + IF ( ALLOCATED(InData%SDWrOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SDWrOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SDWrOutput) ! SDWrOutput + END IF + Db_BufSz = Db_BufSz + 1 ! LastOutTime + Int_BufSz = Int_BufSz + 1 ! Decimat + 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%qmdotdot) ) 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%qmdotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdotdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%qmdotdot,1), UBOUND(InData%qmdotdot,1) + ReKiBuf(Re_Xferred) = InData%qmdotdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DO i1 = LBOUND(InData%u_TP,1), UBOUND(InData%u_TP,1) + ReKiBuf(Re_Xferred) = InData%u_TP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%udot_TP,1), UBOUND(InData%udot_TP,1) + ReKiBuf(Re_Xferred) = InData%udot_TP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%udotdot_TP,1), UBOUND(InData%udotdot_TP,1) + ReKiBuf(Re_Xferred) = InData%udotdot_TP(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( .NOT. ALLOCATED(InData%UFL) ) 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%UFL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UFL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UFL,1), UBOUND(InData%UFL,1) + ReKiBuf(Re_Xferred) = InData%UFL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar) ) 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%UR_bar,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UR_bar,1), UBOUND(InData%UR_bar,1) + ReKiBuf(Re_Xferred) = InData%UR_bar(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar_dot) ) 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%UR_bar_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UR_bar_dot,1), UBOUND(InData%UR_bar_dot,1) + ReKiBuf(Re_Xferred) = InData%UR_bar_dot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar_dotdot) ) 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%UR_bar_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UR_bar_dotdot,1), UBOUND(InData%UR_bar_dotdot,1) + ReKiBuf(Re_Xferred) = InData%UR_bar_dotdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UL) ) 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%UL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UL,1), UBOUND(InData%UL,1) + ReKiBuf(Re_Xferred) = InData%UL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UL_dot) ) 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%UL_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UL_dot,1), UBOUND(InData%UL_dot,1) + ReKiBuf(Re_Xferred) = InData%UL_dot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%UL_dotdot) ) 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%UL_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%UL_dotdot,1), UBOUND(InData%UL_dotdot,1) + ReKiBuf(Re_Xferred) = InData%UL_dotdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) 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%SDWrOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SDWrOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SDWrOutput,1), UBOUND(InData%SDWrOutput,1) + ReKiBuf(Re_Xferred) = InData%SDWrOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + DbKiBuf(Db_Xferred) = InData%LastOutTime + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Decimat + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackMisc + + SUBROUTINE SD_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(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_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 ! qmdotdot 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%qmdotdot)) DEALLOCATE(OutData%qmdotdot) + ALLOCATE(OutData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%qmdotdot,1), UBOUND(OutData%qmdotdot,1) + OutData%qmdotdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + i1_l = LBOUND(OutData%u_TP,1) + i1_u = UBOUND(OutData%u_TP,1) + DO i1 = LBOUND(OutData%u_TP,1), UBOUND(OutData%u_TP,1) + OutData%u_TP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%udot_TP,1) + i1_u = UBOUND(OutData%udot_TP,1) + DO i1 = LBOUND(OutData%udot_TP,1), UBOUND(OutData%udot_TP,1) + OutData%udot_TP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%udotdot_TP,1) + i1_u = UBOUND(OutData%udotdot_TP,1) + DO i1 = LBOUND(OutData%udotdot_TP,1), UBOUND(OutData%udotdot_TP,1) + OutData%udotdot_TP(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UFL 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%UFL)) DEALLOCATE(OutData%UFL) + ALLOCATE(OutData%UFL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UFL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UFL,1), UBOUND(OutData%UFL,1) + OutData%UFL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar 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%UR_bar)) DEALLOCATE(OutData%UR_bar) + ALLOCATE(OutData%UR_bar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UR_bar,1), UBOUND(OutData%UR_bar,1) + OutData%UR_bar(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dot 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%UR_bar_dot)) DEALLOCATE(OutData%UR_bar_dot) + ALLOCATE(OutData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UR_bar_dot,1), UBOUND(OutData%UR_bar_dot,1) + OutData%UR_bar_dot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dotdot 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%UR_bar_dotdot)) DEALLOCATE(OutData%UR_bar_dotdot) + ALLOCATE(OutData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UR_bar_dotdot,1), UBOUND(OutData%UR_bar_dotdot,1) + OutData%UR_bar_dotdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL 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%UL)) DEALLOCATE(OutData%UL) + ALLOCATE(OutData%UL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UL,1), UBOUND(OutData%UL,1) + OutData%UL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dot 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%UL_dot)) DEALLOCATE(OutData%UL_dot) + ALLOCATE(OutData%UL_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UL_dot,1), UBOUND(OutData%UL_dot,1) + OutData%UL_dot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dotdot 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%UL_dotdot)) DEALLOCATE(OutData%UL_dotdot) + ALLOCATE(OutData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%UL_dotdot,1), UBOUND(OutData%UL_dotdot,1) + OutData%UL_dotdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput 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%SDWrOutput)) DEALLOCATE(OutData%SDWrOutput) + ALLOCATE(OutData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%SDWrOutput,1), UBOUND(OutData%SDWrOutput,1) + OutData%SDWrOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%LastOutTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Decimat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackMisc + + SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%SDDeltaT = SrcParamData%SDDeltaT + DstParamData%SttcSolve = SrcParamData%SttcSolve +IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN + i1_l = LBOUND(SrcParamData%NOmegaM2,1) + i1_u = UBOUND(SrcParamData%NOmegaM2,1) + IF (.NOT. ALLOCATED(DstParamData%NOmegaM2)) THEN + ALLOCATE(DstParamData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NOmegaM2 = SrcParamData%NOmegaM2 +ENDIF +IF (ALLOCATED(SrcParamData%N2OmegaMJDamp)) THEN + i1_l = LBOUND(SrcParamData%N2OmegaMJDamp,1) + i1_u = UBOUND(SrcParamData%N2OmegaMJDamp,1) + IF (.NOT. ALLOCATED(DstParamData%N2OmegaMJDamp)) THEN + ALLOCATE(DstParamData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%N2OmegaMJDamp = SrcParamData%N2OmegaMJDamp +ENDIF +IF (ALLOCATED(SrcParamData%MMB)) THEN + i1_l = LBOUND(SrcParamData%MMB,1) + i1_u = UBOUND(SrcParamData%MMB,1) + i2_l = LBOUND(SrcParamData%MMB,2) + i2_u = UBOUND(SrcParamData%MMB,2) + IF (.NOT. ALLOCATED(DstParamData%MMB)) THEN + ALLOCATE(DstParamData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MMB = SrcParamData%MMB +ENDIF +IF (ALLOCATED(SrcParamData%FX)) THEN + i1_l = LBOUND(SrcParamData%FX,1) + i1_u = UBOUND(SrcParamData%FX,1) + IF (.NOT. ALLOCATED(DstParamData%FX)) THEN + ALLOCATE(DstParamData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FX = SrcParamData%FX +ENDIF +IF (ALLOCATED(SrcParamData%C1_11)) THEN + i1_l = LBOUND(SrcParamData%C1_11,1) + i1_u = UBOUND(SrcParamData%C1_11,1) + i2_l = LBOUND(SrcParamData%C1_11,2) + i2_u = UBOUND(SrcParamData%C1_11,2) + IF (.NOT. ALLOCATED(DstParamData%C1_11)) THEN + ALLOCATE(DstParamData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C1_11 = SrcParamData%C1_11 +ENDIF +IF (ALLOCATED(SrcParamData%C1_12)) THEN + i1_l = LBOUND(SrcParamData%C1_12,1) + i1_u = UBOUND(SrcParamData%C1_12,1) + i2_l = LBOUND(SrcParamData%C1_12,2) + i2_u = UBOUND(SrcParamData%C1_12,2) + IF (.NOT. ALLOCATED(DstParamData%C1_12)) THEN + ALLOCATE(DstParamData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C1_12 = SrcParamData%C1_12 +ENDIF +IF (ALLOCATED(SrcParamData%D1_13)) THEN + i1_l = LBOUND(SrcParamData%D1_13,1) + i1_u = UBOUND(SrcParamData%D1_13,1) + i2_l = LBOUND(SrcParamData%D1_13,2) + i2_u = UBOUND(SrcParamData%D1_13,2) + IF (.NOT. ALLOCATED(DstParamData%D1_13)) THEN + ALLOCATE(DstParamData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_13.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_13 = SrcParamData%D1_13 +ENDIF +IF (ALLOCATED(SrcParamData%D1_14)) THEN + i1_l = LBOUND(SrcParamData%D1_14,1) + i1_u = UBOUND(SrcParamData%D1_14,1) + i2_l = LBOUND(SrcParamData%D1_14,2) + i2_u = UBOUND(SrcParamData%D1_14,2) + IF (.NOT. ALLOCATED(DstParamData%D1_14)) THEN + ALLOCATE(DstParamData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_14.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_14 = SrcParamData%D1_14 +ENDIF +IF (ALLOCATED(SrcParamData%FY)) THEN + i1_l = LBOUND(SrcParamData%FY,1) + i1_u = UBOUND(SrcParamData%FY,1) + IF (.NOT. ALLOCATED(DstParamData%FY)) THEN + ALLOCATE(DstParamData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FY = SrcParamData%FY +ENDIF +IF (ALLOCATED(SrcParamData%PhiM)) THEN + i1_l = LBOUND(SrcParamData%PhiM,1) + i1_u = UBOUND(SrcParamData%PhiM,1) + i2_l = LBOUND(SrcParamData%PhiM,2) + i2_u = UBOUND(SrcParamData%PhiM,2) + IF (.NOT. ALLOCATED(DstParamData%PhiM)) THEN + ALLOCATE(DstParamData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiM = SrcParamData%PhiM +ENDIF +IF (ALLOCATED(SrcParamData%C2_61)) THEN + i1_l = LBOUND(SrcParamData%C2_61,1) + i1_u = UBOUND(SrcParamData%C2_61,1) + i2_l = LBOUND(SrcParamData%C2_61,2) + i2_u = UBOUND(SrcParamData%C2_61,2) + IF (.NOT. ALLOCATED(DstParamData%C2_61)) THEN + ALLOCATE(DstParamData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C2_61 = SrcParamData%C2_61 +ENDIF +IF (ALLOCATED(SrcParamData%C2_62)) THEN + i1_l = LBOUND(SrcParamData%C2_62,1) + i1_u = UBOUND(SrcParamData%C2_62,1) + i2_l = LBOUND(SrcParamData%C2_62,2) + i2_u = UBOUND(SrcParamData%C2_62,2) + IF (.NOT. ALLOCATED(DstParamData%C2_62)) THEN + ALLOCATE(DstParamData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_62.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C2_62 = SrcParamData%C2_62 +ENDIF +IF (ALLOCATED(SrcParamData%PhiRb_TI)) THEN + i1_l = LBOUND(SrcParamData%PhiRb_TI,1) + i1_u = UBOUND(SrcParamData%PhiRb_TI,1) + i2_l = LBOUND(SrcParamData%PhiRb_TI,2) + i2_u = UBOUND(SrcParamData%PhiRb_TI,2) + IF (.NOT. ALLOCATED(DstParamData%PhiRb_TI)) THEN + ALLOCATE(DstParamData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiRb_TI = SrcParamData%PhiRb_TI +ENDIF +IF (ALLOCATED(SrcParamData%D2_63)) THEN + i1_l = LBOUND(SrcParamData%D2_63,1) + i1_u = UBOUND(SrcParamData%D2_63,1) + i2_l = LBOUND(SrcParamData%D2_63,2) + i2_u = UBOUND(SrcParamData%D2_63,2) + IF (.NOT. ALLOCATED(DstParamData%D2_63)) THEN + ALLOCATE(DstParamData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_63.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D2_63 = SrcParamData%D2_63 +ENDIF +IF (ALLOCATED(SrcParamData%D2_64)) THEN + i1_l = LBOUND(SrcParamData%D2_64,1) + i1_u = UBOUND(SrcParamData%D2_64,1) + i2_l = LBOUND(SrcParamData%D2_64,2) + i2_u = UBOUND(SrcParamData%D2_64,2) + IF (.NOT. ALLOCATED(DstParamData%D2_64)) THEN + ALLOCATE(DstParamData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_64.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D2_64 = SrcParamData%D2_64 +ENDIF +IF (ALLOCATED(SrcParamData%F2_61)) THEN + i1_l = LBOUND(SrcParamData%F2_61,1) + i1_u = UBOUND(SrcParamData%F2_61,1) + IF (.NOT. ALLOCATED(DstParamData%F2_61)) THEN + ALLOCATE(DstParamData%F2_61(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%F2_61 = SrcParamData%F2_61 +ENDIF +IF (ALLOCATED(SrcParamData%MBB)) THEN + i1_l = LBOUND(SrcParamData%MBB,1) + i1_u = UBOUND(SrcParamData%MBB,1) + i2_l = LBOUND(SrcParamData%MBB,2) + i2_u = UBOUND(SrcParamData%MBB,2) + IF (.NOT. ALLOCATED(DstParamData%MBB)) THEN + ALLOCATE(DstParamData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MBB = SrcParamData%MBB +ENDIF +IF (ALLOCATED(SrcParamData%KBB)) THEN + i1_l = LBOUND(SrcParamData%KBB,1) + i1_u = UBOUND(SrcParamData%KBB,1) + i2_l = LBOUND(SrcParamData%KBB,2) + i2_u = UBOUND(SrcParamData%KBB,2) + IF (.NOT. ALLOCATED(DstParamData%KBB)) THEN + ALLOCATE(DstParamData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KBB = SrcParamData%KBB +ENDIF +IF (ALLOCATED(SrcParamData%MBM)) THEN + i1_l = LBOUND(SrcParamData%MBM,1) + i1_u = UBOUND(SrcParamData%MBM,1) + i2_l = LBOUND(SrcParamData%MBM,2) + i2_u = UBOUND(SrcParamData%MBM,2) + IF (.NOT. ALLOCATED(DstParamData%MBM)) THEN + ALLOCATE(DstParamData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MBM = SrcParamData%MBM +ENDIF +IF (ALLOCATED(SrcParamData%PhiL_T)) THEN + i1_l = LBOUND(SrcParamData%PhiL_T,1) + i1_u = UBOUND(SrcParamData%PhiL_T,1) + i2_l = LBOUND(SrcParamData%PhiL_T,2) + i2_u = UBOUND(SrcParamData%PhiL_T,2) + IF (.NOT. ALLOCATED(DstParamData%PhiL_T)) THEN + ALLOCATE(DstParamData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiL_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiL_T = SrcParamData%PhiL_T +ENDIF +IF (ALLOCATED(SrcParamData%PhiLInvOmgL2)) THEN + i1_l = LBOUND(SrcParamData%PhiLInvOmgL2,1) + i1_u = UBOUND(SrcParamData%PhiLInvOmgL2,1) + i2_l = LBOUND(SrcParamData%PhiLInvOmgL2,2) + i2_u = UBOUND(SrcParamData%PhiLInvOmgL2,2) + IF (.NOT. ALLOCATED(DstParamData%PhiLInvOmgL2)) THEN + ALLOCATE(DstParamData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiLInvOmgL2 = SrcParamData%PhiLInvOmgL2 +ENDIF +IF (ALLOCATED(SrcParamData%FGL)) THEN + i1_l = LBOUND(SrcParamData%FGL,1) + i1_u = UBOUND(SrcParamData%FGL,1) + IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN + ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FGL = SrcParamData%FGL +ENDIF +IF (ALLOCATED(SrcParamData%AM2Jac)) THEN + i1_l = LBOUND(SrcParamData%AM2Jac,1) + i1_u = UBOUND(SrcParamData%AM2Jac,1) + i2_l = LBOUND(SrcParamData%AM2Jac,2) + i2_u = UBOUND(SrcParamData%AM2Jac,2) + IF (.NOT. ALLOCATED(DstParamData%AM2Jac)) THEN + ALLOCATE(DstParamData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AM2Jac = SrcParamData%AM2Jac +ENDIF +IF (ALLOCATED(SrcParamData%AM2JacPiv)) THEN + i1_l = LBOUND(SrcParamData%AM2JacPiv,1) + i1_u = UBOUND(SrcParamData%AM2JacPiv,1) + IF (.NOT. ALLOCATED(DstParamData%AM2JacPiv)) THEN + ALLOCATE(DstParamData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AM2JacPiv = SrcParamData%AM2JacPiv +ENDIF +IF (ALLOCATED(SrcParamData%TI)) THEN + i1_l = LBOUND(SrcParamData%TI,1) + i1_u = UBOUND(SrcParamData%TI,1) + i2_l = LBOUND(SrcParamData%TI,2) + i2_u = UBOUND(SrcParamData%TI,2) + IF (.NOT. ALLOCATED(DstParamData%TI)) THEN + ALLOCATE(DstParamData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TI = SrcParamData%TI +ENDIF +IF (ALLOCATED(SrcParamData%TIreact)) THEN + i1_l = LBOUND(SrcParamData%TIreact,1) + i1_u = UBOUND(SrcParamData%TIreact,1) + i2_l = LBOUND(SrcParamData%TIreact,2) + i2_u = UBOUND(SrcParamData%TIreact,2) + IF (.NOT. ALLOCATED(DstParamData%TIreact)) THEN + ALLOCATE(DstParamData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TIreact.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TIreact = SrcParamData%TIreact +ENDIF + DstParamData%NModes = SrcParamData%NModes +IF (ALLOCATED(SrcParamData%Elems)) THEN + i1_l = LBOUND(SrcParamData%Elems,1) + i1_u = UBOUND(SrcParamData%Elems,1) + i2_l = LBOUND(SrcParamData%Elems,2) + i2_u = UBOUND(SrcParamData%Elems,2) + IF (.NOT. ALLOCATED(DstParamData%Elems)) THEN + ALLOCATE(DstParamData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Elems = SrcParamData%Elems +ENDIF + DstParamData%qmL = SrcParamData%qmL + DstParamData%DofL = SrcParamData%DofL + DstParamData%NNodes_I = SrcParamData%NNodes_I + DstParamData%NNodes_L = SrcParamData%NNodes_L + DstParamData%NNodes_RbarL = SrcParamData%NNodes_RbarL + DstParamData%DofI = SrcParamData%DofI + DstParamData%DofR = SrcParamData%DofR + DstParamData%DofC = SrcParamData%DofC + DstParamData%NReact = SrcParamData%NReact +IF (ALLOCATED(SrcParamData%Reacts)) THEN + i1_l = LBOUND(SrcParamData%Reacts,1) + i1_u = UBOUND(SrcParamData%Reacts,1) + i2_l = LBOUND(SrcParamData%Reacts,2) + i2_u = UBOUND(SrcParamData%Reacts,2) + IF (.NOT. ALLOCATED(DstParamData%Reacts)) THEN + ALLOCATE(DstParamData%Reacts(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Reacts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Reacts = SrcParamData%Reacts +ENDIF + DstParamData%Nmembers = SrcParamData%Nmembers + DstParamData%URbarL = SrcParamData%URbarL + DstParamData%IntMethod = SrcParamData%IntMethod + DstParamData%NAvgEls = SrcParamData%NAvgEls +IF (ALLOCATED(SrcParamData%IDI)) THEN + i1_l = LBOUND(SrcParamData%IDI,1) + i1_u = UBOUND(SrcParamData%IDI,1) + IF (.NOT. ALLOCATED(DstParamData%IDI)) THEN + ALLOCATE(DstParamData%IDI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDI = SrcParamData%IDI +ENDIF +IF (ALLOCATED(SrcParamData%IDR)) THEN + i1_l = LBOUND(SrcParamData%IDR,1) + i1_u = UBOUND(SrcParamData%IDR,1) + IF (.NOT. ALLOCATED(DstParamData%IDR)) THEN + ALLOCATE(DstParamData%IDR(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDR = SrcParamData%IDR +ENDIF +IF (ALLOCATED(SrcParamData%IDL)) THEN + i1_l = LBOUND(SrcParamData%IDL,1) + i1_u = UBOUND(SrcParamData%IDL,1) + IF (.NOT. ALLOCATED(DstParamData%IDL)) THEN + ALLOCATE(DstParamData%IDL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDL = SrcParamData%IDL +ENDIF +IF (ALLOCATED(SrcParamData%IDC)) THEN + i1_l = LBOUND(SrcParamData%IDC,1) + i1_u = UBOUND(SrcParamData%IDC,1) + IF (.NOT. ALLOCATED(DstParamData%IDC)) THEN + ALLOCATE(DstParamData%IDC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC = SrcParamData%IDC +ENDIF +IF (ALLOCATED(SrcParamData%IDY)) THEN + i1_l = LBOUND(SrcParamData%IDY,1) + i1_u = UBOUND(SrcParamData%IDY,1) + IF (.NOT. ALLOCATED(DstParamData%IDY)) THEN + ALLOCATE(DstParamData%IDY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDY = SrcParamData%IDY +ENDIF + DstParamData%NMOutputs = SrcParamData%NMOutputs + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%OutSwtch = SrcParamData%OutSwtch + DstParamData%UnJckF = SrcParamData%UnJckF + DstParamData%Delim = SrcParamData%Delim + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt +IF (ALLOCATED(SrcParamData%MoutLst)) THEN + i1_l = LBOUND(SrcParamData%MoutLst,1) + i1_u = UBOUND(SrcParamData%MoutLst,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst)) THEN + ALLOCATE(DstParamData%MoutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst,1), UBOUND(SrcParamData%MoutLst,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst(i1), DstParamData%MoutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%MoutLst2)) THEN + i1_l = LBOUND(SrcParamData%MoutLst2,1) + i1_u = UBOUND(SrcParamData%MoutLst2,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst2)) THEN + ALLOCATE(DstParamData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst2,1), UBOUND(SrcParamData%MoutLst2,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst2(i1), DstParamData%MoutLst2(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%MoutLst3)) THEN + i1_l = LBOUND(SrcParamData%MoutLst3,1) + i1_u = UBOUND(SrcParamData%MoutLst3,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst3)) THEN + ALLOCATE(DstParamData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst3,1), UBOUND(SrcParamData%MoutLst3,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst3(i1), DstParamData%MoutLst3(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%ElemProps)) THEN + i1_l = LBOUND(SrcParamData%ElemProps,1) + i1_u = UBOUND(SrcParamData%ElemProps,1) + IF (.NOT. ALLOCATED(DstParamData%ElemProps)) THEN + ALLOCATE(DstParamData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) + CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%OutAll = SrcParamData%OutAll + DstParamData%OutReact = SrcParamData%OutReact + DstParamData%OutAllInt = SrcParamData%OutAllInt + DstParamData%OutAllDims = SrcParamData%OutAllDims + DstParamData%OutDec = SrcParamData%OutDec + END SUBROUTINE SD_CopyParam + + SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%NOmegaM2)) THEN + DEALLOCATE(ParamData%NOmegaM2) +ENDIF +IF (ALLOCATED(ParamData%N2OmegaMJDamp)) THEN + DEALLOCATE(ParamData%N2OmegaMJDamp) +ENDIF +IF (ALLOCATED(ParamData%MMB)) THEN + DEALLOCATE(ParamData%MMB) +ENDIF +IF (ALLOCATED(ParamData%FX)) THEN + DEALLOCATE(ParamData%FX) +ENDIF +IF (ALLOCATED(ParamData%C1_11)) THEN + DEALLOCATE(ParamData%C1_11) +ENDIF +IF (ALLOCATED(ParamData%C1_12)) THEN + DEALLOCATE(ParamData%C1_12) +ENDIF +IF (ALLOCATED(ParamData%D1_13)) THEN + DEALLOCATE(ParamData%D1_13) +ENDIF +IF (ALLOCATED(ParamData%D1_14)) THEN + DEALLOCATE(ParamData%D1_14) +ENDIF +IF (ALLOCATED(ParamData%FY)) THEN + DEALLOCATE(ParamData%FY) +ENDIF +IF (ALLOCATED(ParamData%PhiM)) THEN + DEALLOCATE(ParamData%PhiM) +ENDIF +IF (ALLOCATED(ParamData%C2_61)) THEN + DEALLOCATE(ParamData%C2_61) +ENDIF +IF (ALLOCATED(ParamData%C2_62)) THEN + DEALLOCATE(ParamData%C2_62) +ENDIF +IF (ALLOCATED(ParamData%PhiRb_TI)) THEN + DEALLOCATE(ParamData%PhiRb_TI) +ENDIF +IF (ALLOCATED(ParamData%D2_63)) THEN + DEALLOCATE(ParamData%D2_63) +ENDIF +IF (ALLOCATED(ParamData%D2_64)) THEN + DEALLOCATE(ParamData%D2_64) +ENDIF +IF (ALLOCATED(ParamData%F2_61)) THEN + DEALLOCATE(ParamData%F2_61) +ENDIF +IF (ALLOCATED(ParamData%MBB)) THEN + DEALLOCATE(ParamData%MBB) +ENDIF +IF (ALLOCATED(ParamData%KBB)) THEN + DEALLOCATE(ParamData%KBB) +ENDIF +IF (ALLOCATED(ParamData%MBM)) THEN + DEALLOCATE(ParamData%MBM) +ENDIF +IF (ALLOCATED(ParamData%PhiL_T)) THEN + DEALLOCATE(ParamData%PhiL_T) +ENDIF +IF (ALLOCATED(ParamData%PhiLInvOmgL2)) THEN + DEALLOCATE(ParamData%PhiLInvOmgL2) +ENDIF +IF (ALLOCATED(ParamData%FGL)) THEN + DEALLOCATE(ParamData%FGL) +ENDIF +IF (ALLOCATED(ParamData%AM2Jac)) THEN + DEALLOCATE(ParamData%AM2Jac) +ENDIF +IF (ALLOCATED(ParamData%AM2JacPiv)) THEN + DEALLOCATE(ParamData%AM2JacPiv) +ENDIF +IF (ALLOCATED(ParamData%TI)) THEN + DEALLOCATE(ParamData%TI) +ENDIF +IF (ALLOCATED(ParamData%TIreact)) THEN + DEALLOCATE(ParamData%TIreact) +ENDIF +IF (ALLOCATED(ParamData%Elems)) THEN + DEALLOCATE(ParamData%Elems) +ENDIF +IF (ALLOCATED(ParamData%Reacts)) THEN + DEALLOCATE(ParamData%Reacts) +ENDIF +IF (ALLOCATED(ParamData%IDI)) THEN + DEALLOCATE(ParamData%IDI) +ENDIF +IF (ALLOCATED(ParamData%IDR)) THEN + DEALLOCATE(ParamData%IDR) +ENDIF +IF (ALLOCATED(ParamData%IDL)) THEN + DEALLOCATE(ParamData%IDL) +ENDIF +IF (ALLOCATED(ParamData%IDC)) THEN + DEALLOCATE(ParamData%IDC) +ENDIF +IF (ALLOCATED(ParamData%IDY)) THEN + DEALLOCATE(ParamData%IDY) +ENDIF +IF (ALLOCATED(ParamData%MoutLst)) THEN +DO i1 = LBOUND(ParamData%MoutLst,1), UBOUND(ParamData%MoutLst,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst) +ENDIF +IF (ALLOCATED(ParamData%MoutLst2)) THEN +DO i1 = LBOUND(ParamData%MoutLst2,1), UBOUND(ParamData%MoutLst2,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst2) +ENDIF +IF (ALLOCATED(ParamData%MoutLst3)) THEN +DO i1 = LBOUND(ParamData%MoutLst3,1), UBOUND(ParamData%MoutLst3,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst3(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst3) +ENDIF +IF (ALLOCATED(ParamData%ElemProps)) THEN +DO i1 = LBOUND(ParamData%ElemProps,1), UBOUND(ParamData%ElemProps,1) + CALL SD_Destroyelemproptype( ParamData%ElemProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%ElemProps) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE SD_DestroyParam + + SUBROUTINE SD_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(SD_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 = 'SD_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 + Db_BufSz = Db_BufSz + 1 ! SDDeltaT + Int_BufSz = Int_BufSz + 1 ! SttcSolve + Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no + IF ( ALLOCATED(InData%NOmegaM2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%NOmegaM2) ! NOmegaM2 + END IF + Int_BufSz = Int_BufSz + 1 ! N2OmegaMJDamp allocated yes/no + IF ( ALLOCATED(InData%N2OmegaMJDamp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! N2OmegaMJDamp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%N2OmegaMJDamp) ! N2OmegaMJDamp + END IF + Int_BufSz = Int_BufSz + 1 ! MMB allocated yes/no + IF ( ALLOCATED(InData%MMB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MMB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MMB) ! MMB + END IF + Int_BufSz = Int_BufSz + 1 ! FX allocated yes/no + IF ( ALLOCATED(InData%FX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FX) ! FX + END IF + Int_BufSz = Int_BufSz + 1 ! C1_11 allocated yes/no + IF ( ALLOCATED(InData%C1_11) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C1_11 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C1_11) ! C1_11 + END IF + Int_BufSz = Int_BufSz + 1 ! C1_12 allocated yes/no + IF ( ALLOCATED(InData%C1_12) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C1_12 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C1_12) ! C1_12 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_13 allocated yes/no + IF ( ALLOCATED(InData%D1_13) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_14 allocated yes/no + IF ( ALLOCATED(InData%D1_14) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 + END IF + Int_BufSz = Int_BufSz + 1 ! FY allocated yes/no + IF ( ALLOCATED(InData%FY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FY) ! FY + END IF + Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no + IF ( ALLOCATED(InData%PhiM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiM) ! PhiM + END IF + Int_BufSz = Int_BufSz + 1 ! C2_61 allocated yes/no + IF ( ALLOCATED(InData%C2_61) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C2_61 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C2_61) ! C2_61 + END IF + Int_BufSz = Int_BufSz + 1 ! C2_62 allocated yes/no + IF ( ALLOCATED(InData%C2_62) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C2_62 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C2_62) ! C2_62 + END IF + Int_BufSz = Int_BufSz + 1 ! PhiRb_TI allocated yes/no + IF ( ALLOCATED(InData%PhiRb_TI) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiRb_TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiRb_TI) ! PhiRb_TI + END IF + Int_BufSz = Int_BufSz + 1 ! D2_63 allocated yes/no + IF ( ALLOCATED(InData%D2_63) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D2_63 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D2_63) ! D2_63 + END IF + Int_BufSz = Int_BufSz + 1 ! D2_64 allocated yes/no + IF ( ALLOCATED(InData%D2_64) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D2_64 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D2_64) ! D2_64 + END IF + Int_BufSz = Int_BufSz + 1 ! F2_61 allocated yes/no + IF ( ALLOCATED(InData%F2_61) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F2_61 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F2_61) ! F2_61 + END IF + Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no + IF ( ALLOCATED(InData%MBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB + END IF + Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no + IF ( ALLOCATED(InData%KBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB + END IF + Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no + IF ( ALLOCATED(InData%MBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM + END IF + Int_BufSz = Int_BufSz + 1 ! PhiL_T allocated yes/no + IF ( ALLOCATED(InData%PhiL_T) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiL_T upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiL_T) ! PhiL_T + END IF + Int_BufSz = Int_BufSz + 1 ! PhiLInvOmgL2 allocated yes/no + IF ( ALLOCATED(InData%PhiLInvOmgL2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiLInvOmgL2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiLInvOmgL2) ! PhiLInvOmgL2 + END IF + Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no + IF ( ALLOCATED(InData%FGL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL + END IF + Int_BufSz = Int_BufSz + 1 ! AM2Jac allocated yes/no + IF ( ALLOCATED(InData%AM2Jac) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AM2Jac upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AM2Jac) ! AM2Jac + END IF + Int_BufSz = Int_BufSz + 1 ! AM2JacPiv allocated yes/no + IF ( ALLOCATED(InData%AM2JacPiv) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AM2JacPiv upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AM2JacPiv) ! AM2JacPiv + END IF + Int_BufSz = Int_BufSz + 1 ! TI allocated yes/no + IF ( ALLOCATED(InData%TI) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI + END IF + Int_BufSz = Int_BufSz + 1 ! TIreact allocated yes/no + IF ( ALLOCATED(InData%TIreact) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TIreact upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TIreact) ! TIreact + END IF + Int_BufSz = Int_BufSz + 1 ! NModes + Int_BufSz = Int_BufSz + 1 ! Elems allocated yes/no + IF ( ALLOCATED(InData%Elems) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Elems upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Elems) ! Elems + END IF + Int_BufSz = Int_BufSz + 1 ! qmL + Int_BufSz = Int_BufSz + 1 ! DofL + Int_BufSz = Int_BufSz + 1 ! NNodes_I + Int_BufSz = Int_BufSz + 1 ! NNodes_L + Int_BufSz = Int_BufSz + 1 ! NNodes_RbarL + Int_BufSz = Int_BufSz + 1 ! DofI + Int_BufSz = Int_BufSz + 1 ! DofR + Int_BufSz = Int_BufSz + 1 ! DofC + Int_BufSz = Int_BufSz + 1 ! NReact + Int_BufSz = Int_BufSz + 1 ! Reacts allocated yes/no + IF ( ALLOCATED(InData%Reacts) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Reacts upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Reacts) ! Reacts + END IF + Int_BufSz = Int_BufSz + 1 ! Nmembers + Int_BufSz = Int_BufSz + 1 ! URbarL + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! NAvgEls + Int_BufSz = Int_BufSz + 1 ! IDI allocated yes/no + IF ( ALLOCATED(InData%IDI) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI) ! IDI + END IF + Int_BufSz = Int_BufSz + 1 ! IDR allocated yes/no + IF ( ALLOCATED(InData%IDR) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDR upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDR) ! IDR + END IF + Int_BufSz = Int_BufSz + 1 ! IDL allocated yes/no + IF ( ALLOCATED(InData%IDL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDL upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDL) ! IDL + END IF + Int_BufSz = Int_BufSz + 1 ! IDC allocated yes/no + IF ( ALLOCATED(InData%IDC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC) ! IDC + END IF + Int_BufSz = Int_BufSz + 1 ! IDY allocated yes/no + IF ( ALLOCATED(InData%IDY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDY upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDY) ! IDY + END IF + Int_BufSz = Int_BufSz + 1 ! NMOutputs + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1 ! UnJckF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1 ! MoutLst allocated yes/no + IF ( ALLOCATED(InData%MoutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MoutLst2 allocated yes/no + IF ( ALLOCATED(InData%MoutLst2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst2: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MoutLst3 allocated yes/no + IF ( ALLOCATED(InData%MoutLst3) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst3 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst3: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst3 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst3 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst3 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst3 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no + IF ( ALLOCATED(InData%ElemProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElemProps upper/lower bounds for each dimension + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + Int_BufSz = Int_BufSz + 3 ! ElemProps: size of buffers for each call to pack subtype + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ElemProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ElemProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ElemProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + 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 + 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 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! OutReact + Int_BufSz = Int_BufSz + 1 ! OutAllInt + Int_BufSz = Int_BufSz + 1 ! OutAllDims + Int_BufSz = Int_BufSz + 1 ! OutDec + 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 + + DbKiBuf(Db_Xferred) = InData%SDDeltaT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%SttcSolve, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) 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%NOmegaM2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NOmegaM2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NOmegaM2,1), UBOUND(InData%NOmegaM2,1) + ReKiBuf(Re_Xferred) = InData%NOmegaM2(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%N2OmegaMJDamp) ) 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%N2OmegaMJDamp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%N2OmegaMJDamp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%N2OmegaMJDamp,1), UBOUND(InData%N2OmegaMJDamp,1) + ReKiBuf(Re_Xferred) = InData%N2OmegaMJDamp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MMB) ) 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%MMB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MMB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MMB,2), UBOUND(InData%MMB,2) + DO i1 = LBOUND(InData%MMB,1), UBOUND(InData%MMB,1) + ReKiBuf(Re_Xferred) = InData%MMB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FX) ) 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%FX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FX,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FX,1), UBOUND(InData%FX,1) + ReKiBuf(Re_Xferred) = InData%FX(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C1_11) ) 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%C1_11,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_11,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C1_11,2), UBOUND(InData%C1_11,2) + DO i1 = LBOUND(InData%C1_11,1), UBOUND(InData%C1_11,1) + ReKiBuf(Re_Xferred) = InData%C1_11(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C1_12) ) 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%C1_12,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_12,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C1_12,2), UBOUND(InData%C1_12,2) + DO i1 = LBOUND(InData%C1_12,1), UBOUND(InData%C1_12,1) + ReKiBuf(Re_Xferred) = InData%C1_12(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D1_13) ) 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%D1_13,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D1_13,2), UBOUND(InData%D1_13,2) + DO i1 = LBOUND(InData%D1_13,1), UBOUND(InData%D1_13,1) + ReKiBuf(Re_Xferred) = InData%D1_13(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D1_14) ) 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%D1_14,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D1_14,2), UBOUND(InData%D1_14,2) + DO i1 = LBOUND(InData%D1_14,1), UBOUND(InData%D1_14,1) + ReKiBuf(Re_Xferred) = InData%D1_14(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FY) ) 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%FY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FY,1), UBOUND(InData%FY,1) + ReKiBuf(Re_Xferred) = InData%FY(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiM) ) 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%PhiM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiM,2), UBOUND(InData%PhiM,2) + DO i1 = LBOUND(InData%PhiM,1), UBOUND(InData%PhiM,1) + ReKiBuf(Re_Xferred) = InData%PhiM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C2_61) ) 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%C2_61,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_61,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C2_61,2), UBOUND(InData%C2_61,2) + DO i1 = LBOUND(InData%C2_61,1), UBOUND(InData%C2_61,1) + ReKiBuf(Re_Xferred) = InData%C2_61(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%C2_62) ) 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%C2_62,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_62,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%C2_62,2), UBOUND(InData%C2_62,2) + DO i1 = LBOUND(InData%C2_62,1), UBOUND(InData%C2_62,1) + ReKiBuf(Re_Xferred) = InData%C2_62(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiRb_TI) ) 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%PhiRb_TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiRb_TI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiRb_TI,2), UBOUND(InData%PhiRb_TI,2) + DO i1 = LBOUND(InData%PhiRb_TI,1), UBOUND(InData%PhiRb_TI,1) + ReKiBuf(Re_Xferred) = InData%PhiRb_TI(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D2_63) ) 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%D2_63,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_63,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D2_63,2), UBOUND(InData%D2_63,2) + DO i1 = LBOUND(InData%D2_63,1), UBOUND(InData%D2_63,1) + ReKiBuf(Re_Xferred) = InData%D2_63(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D2_64) ) 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%D2_64,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_64,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D2_64,2), UBOUND(InData%D2_64,2) + DO i1 = LBOUND(InData%D2_64,1), UBOUND(InData%D2_64,1) + ReKiBuf(Re_Xferred) = InData%D2_64(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F2_61) ) 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%F2_61,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F2_61,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F2_61,1), UBOUND(InData%F2_61,1) + ReKiBuf(Re_Xferred) = InData%F2_61(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MBB) ) 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%MBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MBB,2), UBOUND(InData%MBB,2) + DO i1 = LBOUND(InData%MBB,1), UBOUND(InData%MBB,1) + ReKiBuf(Re_Xferred) = InData%MBB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%KBB) ) 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%KBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%KBB,2), UBOUND(InData%KBB,2) + DO i1 = LBOUND(InData%KBB,1), UBOUND(InData%KBB,1) + ReKiBuf(Re_Xferred) = InData%KBB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MBM) ) 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%MBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MBM,2), UBOUND(InData%MBM,2) + DO i1 = LBOUND(InData%MBM,1), UBOUND(InData%MBM,1) + ReKiBuf(Re_Xferred) = InData%MBM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiL_T) ) 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%PhiL_T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL_T,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiL_T,2), UBOUND(InData%PhiL_T,2) + DO i1 = LBOUND(InData%PhiL_T,1), UBOUND(InData%PhiL_T,1) + ReKiBuf(Re_Xferred) = InData%PhiL_T(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PhiLInvOmgL2) ) 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%PhiLInvOmgL2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiLInvOmgL2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%PhiLInvOmgL2,2), UBOUND(InData%PhiLInvOmgL2,2) + DO i1 = LBOUND(InData%PhiLInvOmgL2,1), UBOUND(InData%PhiLInvOmgL2,1) + ReKiBuf(Re_Xferred) = InData%PhiLInvOmgL2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FGL) ) 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%FGL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FGL,1), UBOUND(InData%FGL,1) + ReKiBuf(Re_Xferred) = InData%FGL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AM2Jac) ) 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%AM2Jac,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2Jac,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AM2Jac,2), UBOUND(InData%AM2Jac,2) + DO i1 = LBOUND(InData%AM2Jac,1), UBOUND(InData%AM2Jac,1) + ReKiBuf(Re_Xferred) = InData%AM2Jac(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AM2JacPiv) ) 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%AM2JacPiv,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2JacPiv,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AM2JacPiv,1), UBOUND(InData%AM2JacPiv,1) + IntKiBuf(Int_Xferred) = InData%AM2JacPiv(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TI) ) 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%TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TI,2), UBOUND(InData%TI,2) + DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) + ReKiBuf(Re_Xferred) = InData%TI(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%TIreact) ) 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%TIreact,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TIreact,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%TIreact,2), UBOUND(InData%TIreact,2) + DO i1 = LBOUND(InData%TIreact,1), UBOUND(InData%TIreact,1) + ReKiBuf(Re_Xferred) = InData%TIreact(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NModes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Elems) ) 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%Elems,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Elems,2), UBOUND(InData%Elems,2) + DO i1 = LBOUND(InData%Elems,1), UBOUND(InData%Elems,1) + IntKiBuf(Int_Xferred) = InData%Elems(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%qmL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DofL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes_I + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes_RbarL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DofI + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DofR + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DofC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NReact + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Reacts) ) 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%Reacts,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Reacts,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Reacts,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Reacts,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Reacts,2), UBOUND(InData%Reacts,2) + DO i1 = LBOUND(InData%Reacts,1), UBOUND(InData%Reacts,1) + IntKiBuf(Int_Xferred) = InData%Reacts(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%Nmembers + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%URbarL + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NAvgEls + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%IDI) ) 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%IDI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IDI,1), UBOUND(InData%IDI,1) + IntKiBuf(Int_Xferred) = InData%IDI(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IDR) ) 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%IDR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IDR,1), UBOUND(InData%IDR,1) + IntKiBuf(Int_Xferred) = InData%IDR(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IDL) ) 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%IDL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IDL,1), UBOUND(InData%IDL,1) + IntKiBuf(Int_Xferred) = InData%IDL(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IDC) ) 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%IDC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IDC,1), UBOUND(InData%IDC,1) + IntKiBuf(Int_Xferred) = InData%IDC(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IDY) ) 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%IDY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDY,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%IDY,1), UBOUND(InData%IDY,1) + IntKiBuf(Int_Xferred) = InData%IDY(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NMOutputs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnJckF + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%MoutLst) ) 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%MoutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst + 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%MoutLst2) ) 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%MoutLst2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst2 + 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%MoutLst3) ) 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%MoutLst3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst3,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst3 + 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%ElemProps) ) 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%ElemProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps + 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%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 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutReact, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutAllInt + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutAllDims + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutDec + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackParam + + SUBROUTINE SD_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(SD_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 = 'SD_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%SDDeltaT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%SttcSolve = TRANSFER(IntKiBuf(Int_Xferred), OutData%SttcSolve) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 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%NOmegaM2)) DEALLOCATE(OutData%NOmegaM2) + ALLOCATE(OutData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NOmegaM2,1), UBOUND(OutData%NOmegaM2,1) + OutData%NOmegaM2(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! N2OmegaMJDamp 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%N2OmegaMJDamp)) DEALLOCATE(OutData%N2OmegaMJDamp) + ALLOCATE(OutData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%N2OmegaMJDamp,1), UBOUND(OutData%N2OmegaMJDamp,1) + OutData%N2OmegaMJDamp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMB 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%MMB)) DEALLOCATE(OutData%MMB) + ALLOCATE(OutData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MMB,2), UBOUND(OutData%MMB,2) + DO i1 = LBOUND(OutData%MMB,1), UBOUND(OutData%MMB,1) + OutData%MMB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FX 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%FX)) DEALLOCATE(OutData%FX) + ALLOCATE(OutData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FX,1), UBOUND(OutData%FX,1) + OutData%FX(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 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%C1_11)) DEALLOCATE(OutData%C1_11) + ALLOCATE(OutData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C1_11,2), UBOUND(OutData%C1_11,2) + DO i1 = LBOUND(OutData%C1_11,1), UBOUND(OutData%C1_11,1) + OutData%C1_11(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_12 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%C1_12)) DEALLOCATE(OutData%C1_12) + ALLOCATE(OutData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C1_12,2), UBOUND(OutData%C1_12,2) + DO i1 = LBOUND(OutData%C1_12,1), UBOUND(OutData%C1_12,1) + OutData%C1_12(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 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%D1_13)) DEALLOCATE(OutData%D1_13) + ALLOCATE(OutData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_13.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D1_13,2), UBOUND(OutData%D1_13,2) + DO i1 = LBOUND(OutData%D1_13,1), UBOUND(OutData%D1_13,1) + OutData%D1_13(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_14 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%D1_14)) DEALLOCATE(OutData%D1_14) + ALLOCATE(OutData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_14.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D1_14,2), UBOUND(OutData%D1_14,2) + DO i1 = LBOUND(OutData%D1_14,1), UBOUND(OutData%D1_14,1) + OutData%D1_14(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FY 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%FY)) DEALLOCATE(OutData%FY) + ALLOCATE(OutData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FY,1), UBOUND(OutData%FY,1) + OutData%FY(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM 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%PhiM)) DEALLOCATE(OutData%PhiM) + ALLOCATE(OutData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiM,2), UBOUND(OutData%PhiM,2) + DO i1 = LBOUND(OutData%PhiM,1), UBOUND(OutData%PhiM,1) + OutData%PhiM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_61 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%C2_61)) DEALLOCATE(OutData%C2_61) + ALLOCATE(OutData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C2_61,2), UBOUND(OutData%C2_61,2) + DO i1 = LBOUND(OutData%C2_61,1), UBOUND(OutData%C2_61,1) + OutData%C2_61(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_62 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%C2_62)) DEALLOCATE(OutData%C2_62) + ALLOCATE(OutData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_62.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%C2_62,2), UBOUND(OutData%C2_62,2) + DO i1 = LBOUND(OutData%C2_62,1), UBOUND(OutData%C2_62,1) + OutData%C2_62(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiRb_TI 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%PhiRb_TI)) DEALLOCATE(OutData%PhiRb_TI) + ALLOCATE(OutData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiRb_TI,2), UBOUND(OutData%PhiRb_TI,2) + DO i1 = LBOUND(OutData%PhiRb_TI,1), UBOUND(OutData%PhiRb_TI,1) + OutData%PhiRb_TI(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_63 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%D2_63)) DEALLOCATE(OutData%D2_63) + ALLOCATE(OutData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_63.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D2_63,2), UBOUND(OutData%D2_63,2) + DO i1 = LBOUND(OutData%D2_63,1), UBOUND(OutData%D2_63,1) + OutData%D2_63(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_64 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%D2_64)) DEALLOCATE(OutData%D2_64) + ALLOCATE(OutData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_64.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D2_64,2), UBOUND(OutData%D2_64,2) + DO i1 = LBOUND(OutData%D2_64,1), UBOUND(OutData%D2_64,1) + OutData%D2_64(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F2_61 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%F2_61)) DEALLOCATE(OutData%F2_61) + ALLOCATE(OutData%F2_61(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F2_61,1), UBOUND(OutData%F2_61,1) + OutData%F2_61(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB 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%MBB)) DEALLOCATE(OutData%MBB) + ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MBB,2), UBOUND(OutData%MBB,2) + DO i1 = LBOUND(OutData%MBB,1), UBOUND(OutData%MBB,1) + OutData%MBB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB 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%KBB)) DEALLOCATE(OutData%KBB) + ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%KBB,2), UBOUND(OutData%KBB,2) + DO i1 = LBOUND(OutData%KBB,1), UBOUND(OutData%KBB,1) + OutData%KBB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM 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%MBM)) DEALLOCATE(OutData%MBM) + ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%MBM,2), UBOUND(OutData%MBM,2) + DO i1 = LBOUND(OutData%MBM,1), UBOUND(OutData%MBM,1) + OutData%MBM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T 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%PhiL_T)) DEALLOCATE(OutData%PhiL_T) + ALLOCATE(OutData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiL_T,2), UBOUND(OutData%PhiL_T,2) + DO i1 = LBOUND(OutData%PhiL_T,1), UBOUND(OutData%PhiL_T,1) + OutData%PhiL_T(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiLInvOmgL2 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%PhiLInvOmgL2)) DEALLOCATE(OutData%PhiLInvOmgL2) + ALLOCATE(OutData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PhiLInvOmgL2,2), UBOUND(OutData%PhiLInvOmgL2,2) + DO i1 = LBOUND(OutData%PhiLInvOmgL2,1), UBOUND(OutData%PhiLInvOmgL2,1) + OutData%PhiLInvOmgL2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL 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%FGL)) DEALLOCATE(OutData%FGL) + ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FGL,1), UBOUND(OutData%FGL,1) + OutData%FGL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac 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%AM2Jac)) DEALLOCATE(OutData%AM2Jac) + ALLOCATE(OutData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AM2Jac,2), UBOUND(OutData%AM2Jac,2) + DO i1 = LBOUND(OutData%AM2Jac,1), UBOUND(OutData%AM2Jac,1) + OutData%AM2Jac(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2JacPiv 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%AM2JacPiv)) DEALLOCATE(OutData%AM2JacPiv) + ALLOCATE(OutData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AM2JacPiv,1), UBOUND(OutData%AM2JacPiv,1) + OutData%AM2JacPiv(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI 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%TI)) DEALLOCATE(OutData%TI) + ALLOCATE(OutData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TI,2), UBOUND(OutData%TI,2) + DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) + OutData%TI(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TIreact 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%TIreact)) DEALLOCATE(OutData%TIreact) + ALLOCATE(OutData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TIreact.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%TIreact,2), UBOUND(OutData%TIreact,2) + DO i1 = LBOUND(OutData%TIreact,1), UBOUND(OutData%TIreact,1) + OutData%TIreact(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%NModes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems 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%Elems)) DEALLOCATE(OutData%Elems) + ALLOCATE(OutData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Elems,2), UBOUND(OutData%Elems,2) + DO i1 = LBOUND(OutData%Elems,1), UBOUND(OutData%Elems,1) + OutData%Elems(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%qmL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DofL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NNodes_I = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NNodes_L = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NNodes_RbarL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DofI = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DofR = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DofC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NReact = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Reacts 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%Reacts)) DEALLOCATE(OutData%Reacts) + ALLOCATE(OutData%Reacts(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Reacts.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Reacts,2), UBOUND(OutData%Reacts,2) + DO i1 = LBOUND(OutData%Reacts,1), UBOUND(OutData%Reacts,1) + OutData%Reacts(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%Nmembers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%URbarL = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NAvgEls = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI 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%IDI)) DEALLOCATE(OutData%IDI) + ALLOCATE(OutData%IDI(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IDI,1), UBOUND(OutData%IDI,1) + OutData%IDI(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR 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%IDR)) DEALLOCATE(OutData%IDR) + ALLOCATE(OutData%IDR(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IDR,1), UBOUND(OutData%IDR,1) + OutData%IDR(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL 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%IDL)) DEALLOCATE(OutData%IDL) + ALLOCATE(OutData%IDL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IDL,1), UBOUND(OutData%IDL,1) + OutData%IDL(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC 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%IDC)) DEALLOCATE(OutData%IDC) + ALLOCATE(OutData%IDC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IDC,1), UBOUND(OutData%IDC,1) + OutData%IDC(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDY 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%IDY)) DEALLOCATE(OutData%IDY) + ALLOCATE(OutData%IDY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%IDY,1), UBOUND(OutData%IDY,1) + OutData%IDY(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NMOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnJckF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst 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%MoutLst)) DEALLOCATE(OutData%MoutLst) + ALLOCATE(OutData%MoutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst,1), UBOUND(OutData%MoutLst,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 SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst(i1), ErrStat2, ErrMsg2 ) ! MoutLst + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst2 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%MoutLst2)) DEALLOCATE(OutData%MoutLst2) + ALLOCATE(OutData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst2,1), UBOUND(OutData%MoutLst2,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 SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst2(i1), ErrStat2, ErrMsg2 ) ! MoutLst2 + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst3 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%MoutLst3)) DEALLOCATE(OutData%MoutLst3) + ALLOCATE(OutData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst3,1), UBOUND(OutData%MoutLst3,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 SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst3(i1), ErrStat2, ErrMsg2 ) ! MoutLst3 + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps 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%ElemProps)) DEALLOCATE(OutData%ElemProps) + ALLOCATE(OutData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,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 SD_Unpackelemproptype( Re_Buf, Db_Buf, Int_Buf, OutData%ElemProps(i1), ErrStat2, ErrMsg2 ) ! ElemProps + 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 DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam 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%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,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_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + 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 DO + END IF + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%OutReact = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutReact) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllInt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllDims = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutDec = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackParam + + SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%TPMesh, DstInputData%TPMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%LMesh, DstInputData%LMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SD_CopyInput + + SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%TPMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%LMesh, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInput + + SUBROUTINE SD_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(SD_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 = 'SD_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 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! TPMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TPMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TPMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TPMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LMesh + 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 MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TPMesh + 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 MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LMesh + 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 SD_PackInput + + SUBROUTINE SD_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(SD_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_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 + 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 MeshUnpack( OutData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TPMesh + 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 MeshUnpack( OutData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LMesh + 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 SD_UnPackInput + + SUBROUTINE SD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(SD_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'SD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%Y1Mesh, DstOutputData%Y1Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%Y2Mesh, DstOutputData%Y2Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE SD_CopyOutput + + SUBROUTINE SD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%Y1Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%Y2Mesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE SD_DestroyOutput + + SUBROUTINE SD_PackOutput( 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(SD_OutputType), 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 = 'SD_PackOutput' + ! 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 ! Y1Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y1Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Y1Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Y1Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Y1Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Y2Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Y2Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Y2Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Y2Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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 MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y1Mesh + 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 MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y2Mesh + 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%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_PackOutput + + SUBROUTINE SD_UnPackOutput( 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(SD_OutputType), 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 = 'SD_UnPackOutput' + ! 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 MeshUnpack( OutData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y1Mesh + 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 MeshUnpack( OutData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y2Mesh + 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 ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SD_UnPackOutput + + + SUBROUTINE SD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SD_Input_ExtrapInterp + + + SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(u1%TPMesh, u2%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%LMesh, u2%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE SD_Input_ExtrapInterp1 + + + SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(SD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(u1%TPMesh, u2%TPMesh, u3%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%LMesh, u2%LMesh, u3%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE SD_Input_ExtrapInterp2 + + + SUBROUTINE SD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SD_Output_ExtrapInterp + + + SUBROUTINE SD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) + CALL MeshExtrapInterp1(y1%Y1Mesh, y2%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%Y2Mesh, y2%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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)) + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE SD_Output_ExtrapInterp1 + + + SUBROUTINE SD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(SD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) + CALL MeshExtrapInterp2(y1%Y1Mesh, y2%Y1Mesh, y3%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%Y2Mesh, y2%Y2Mesh, y3%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +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 + c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor + y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE SD_Output_ExtrapInterp2 + +END MODULE SubDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/subdyn/src/qsort_c_module.f90 b/OpenFAST/modules/subdyn/src/qsort_c_module.f90 new file mode 100644 index 000000000..553b25544 --- /dev/null +++ b/OpenFAST/modules/subdyn/src/qsort_c_module.f90 @@ -0,0 +1,61 @@ +!********************************************************************************************************************************** +module qsort_c_module +!This routine ASSUMES A is (m,2) dimensioned array +implicit none +public :: QsortC +private :: Partition + +contains + +recursive subroutine QsortC(A) + integer, intent(in out), dimension(:,:) :: A + integer :: iq + + if(size(A,1) > 1) then + call Partition(A, iq) + call QsortC(A(:iq-1, :)) + call QsortC(A(iq:, :)) + endif +end subroutine QsortC + +subroutine Partition(A, marker) + integer, intent(in out), dimension(:,:) :: A + integer, intent(out) :: marker + integer :: i, j, k + integer :: temp + integer :: x ! pivot point + x = A(1, 1) + i= 0 + j= size(A,1) + 1 + + + do + j = j-1 + do + if (A(j,1) <= x) exit + j = j-1 + end do + i = i+1 + do + if (A(i,1) >= x) exit + i = i+1 + end do + if (i < j) then + ! exchange A(i) and A(j) + do k=1,size(A,2) + temp = A(i,k) + A(i,k) = A(j,k) + A(j,k) = temp + end do !k + elseif (i == j) then + marker = i+1 + return + else + marker = i + return + endif + end do + +end subroutine Partition + +end module qsort_c_module \ No newline at end of file diff --git a/OpenFAST/modules/supercontroller/CMakeLists.txt b/OpenFAST/modules/supercontroller/CMakeLists.txt new file mode 100644 index 000000000..8020da201 --- /dev/null +++ b/OpenFAST/modules/supercontroller/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# Copyright 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. +# + +if (GENERATE_TYPES) + generate_f90_types(src/SuperController_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/SuperController_Types.f90 -ccode) +endif() + +# copy the header files to their build location +configure_file(src/SuperController_Types.h ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) + +add_library(sctypeslib src/SuperController_Types.f90) +target_link_libraries(sctypeslib nwtclibs) + +add_library(scfastlib + src/SuperController.f90) +target_link_libraries(scfastlib sctypeslib openfast_prelib nwtclibs) + +install(TARGETS sctypeslib scfastlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/SuperController_Types.h + DESTINATION include) diff --git a/OpenFAST/modules/supercontroller/README.md b/OpenFAST/modules/supercontroller/README.md new file mode 100644 index 000000000..3d2552ea8 --- /dev/null +++ b/OpenFAST/modules/supercontroller/README.md @@ -0,0 +1,5 @@ +# SuperController Module + +## Overview +This is a pseudo module used to couple OpenFAST with SuperController; +it is considered part of the OpenFAST glue code diff --git a/OpenFAST/modules/supercontroller/src/SuperController.f90 b/OpenFAST/modules/supercontroller/src/SuperController.f90 new file mode 100644 index 000000000..decde0e90 --- /dev/null +++ b/OpenFAST/modules/supercontroller/src/SuperController.f90 @@ -0,0 +1,166 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015 National Renewable Energy Laboratory +! +! Lidar module, a submodule 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 SuperController + +! This is a pseudo module used to couple FAST v8 with SuperController; it is considered part of the FAST glue code + USE FAST_Types + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: SC_Ver = ProgDesc( 'SuperController Integration', '', '' ) + + +! ===================================================================================================" + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: Init_SC ! Initialization routine + PUBLIC :: SC_SetInputs ! Glue-code routine to update inputs for SuperController + PUBLIC :: SC_SetOutputs ! Glue-code routine to update inputs to turbine controller from SuperController + + +CONTAINS +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE Init_SC( InitInp, SC, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(SC_InitInputType), INTENT(IN ) :: InitInp ! Input data for initialization routine + TYPE(SuperController_Data), INTENT(INOUT) :: SC ! data for the SuperController integration module + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Init_SC' + + ! Initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + IF (InitInp%NumCtrl2SC > 0) THEN + CALL AllocPAry( SC%u%toSC, InitInp%NumCtrl2SC, 'u%toSC', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (ErrStat >= AbortErrLev) RETURN + + ! make sure the C versions are synced with these arrays + if (InitInp%NumCtrl2SC > 0) then + SC%u%c_obj%toSC_Len = InitInp%NumCtrl2SC + SC%u%c_obj%toSC = C_LOC( SC%u%toSC(1) ) + SC%u%toSC = 0.0_ReKi + end if + + ! initialize the arrays: + ! + + !............................................................................................ + ! Define system output initializations (set up mesh) here: + !............................................................................................ + if (InitInp%NumSC2Ctrl > 0) then + CALL AllocPAry( SC%y%fromSC, InitInp%NumSC2Ctrl, 'y%fromSC', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if + + IF (ErrStat >= AbortErrLev) RETURN + + ! make sure the C versions are synced with these arrays + if (InitInp%NumSC2Ctrl > 0) then + SC%y%c_obj%fromSC_Len = InitInp%NumSC2Ctrl + SC%y%c_obj%fromSC = C_LOC( SC%y%fromSC(1) ) + end if + + + if( (InitInp%NumSC2Ctrl > 0) .and. (InitInp%NumSC2Ctrl > 0)) then + SC%p%scOn = .true. + else + SC%p%scOn = .false. + end if + + RETURN + +END SUBROUTINE Init_SC +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SC_SetInputs(p_FAST, y_SrvD, SC, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(SrvD_OutputType), INTENT(IN) :: y_SrvD ! The outputs of the ServoDyn module (control) + TYPE(SuperController_Data), INTENT(INOUT) :: SC ! data for the SuperController integration module + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'SC_SetInputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! set SuperController inputs + if (p_FAST%CompServo == Module_SrvD) then + if (allocated(y_SrvD%SuperController).and. associated(SC%u%toSC)) SC%u%toSC = y_SrvD%SuperController + end if + + +END SUBROUTINE SC_SetInputs +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SC_SetOutputs(p_FAST, u_SrvD, SC, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST ! Parameters for the glue code + TYPE(SrvD_InputType), INTENT(INOUT) :: u_SrvD ! The inputs of the ServoDyn module (control) + TYPE(SuperController_Data), INTENT(IN) :: SC ! data for the SuperController integration module + 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 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'SC_SetOutputs' + + + ErrStat = ErrID_None + ErrMsg = "" + + ! set SuperController inputs + if (p_FAST%CompServo == Module_SrvD) then + if (allocated(u_SrvD%SuperController).and. associated(SC%y%fromSC)) u_SrvD%SuperController = SC%y%fromSC + end if + + +END SUBROUTINE SC_SetOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +END MODULE SuperController +!********************************************************************************************************************************** + + + + diff --git a/OpenFAST/modules/supercontroller/src/SuperController_Registry.txt b/OpenFAST/modules/supercontroller/src/SuperController_Registry.txt new file mode 100644 index 000000000..1c7f86f70 --- /dev/null +++ b/OpenFAST/modules/supercontroller/src/SuperController_Registry.txt @@ -0,0 +1,30 @@ +################################################################################################################################### +# Registry for SuperController interface types in the FAST Modularization Framework +# Entries are of the form +# <keyword> <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + + +# ..... SuperController_InitInputType data ....................................................................................................... +typedef SuperController/SC InitInputType IntKi NumSC2Ctrl - - - "number of controller inputs [from supercontroller]" - +typedef ^ ^ IntKi NumCtrl2SC - - - "number of controller outputs [to supercontroller]" - + +# ..... SuperController_InitOutputType data ....................................................................................................... +# Define outputs from the initialization routine here: +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +# ..... MiscVars ................................................................................................................ + +# ..... Parameters ................................................................................................................ +typedef SuperController/SC ParameterType Logical scOn - .FALSE. - "Flag that tells this module if supercontroller is on." - + +# ..... SuperController_InputType data ....................................................................................................... +typedef SuperController/SC InputType ReKi toSC {:} - - "inputs to the super controller (from the turbine controller)" - + +# ..... SuperController_OutputType data ....................................................................................................... +typedef SuperController/SC OutputType ReKi fromSC {:} - - "outputs of the super controller (to the turbine controller)" - diff --git a/OpenFAST/modules/supercontroller/src/SuperController_Types.f90 b/OpenFAST/modules/supercontroller/src/SuperController_Types.f90 new file mode 100644 index 000000000..0f3078661 --- /dev/null +++ b/OpenFAST/modules/supercontroller/src/SuperController_Types.f90 @@ -0,0 +1,1493 @@ +!STARTOFREGISTRYGENERATEDFILE 'SuperController_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 +!********************************************************************************************************************************* +! SuperController_Types +!................................................................................................................................. +! This file is part of SuperController. +! +! 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 SuperController. 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 SuperController_Types +!--------------------------------------------------------------------------------------------------------------------------------- +!USE, INTRINSIC :: ISO_C_Binding +USE NWTC_Library +IMPLICIT NONE +! ========= SC_InitInputType_C ======= + TYPE, BIND(C) :: SC_InitInputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + INTEGER(KIND=C_INT) :: NumSC2Ctrl + INTEGER(KIND=C_INT) :: NumCtrl2SC + END TYPE SC_InitInputType_C + TYPE, PUBLIC :: SC_InitInputType + TYPE( SC_InitInputType_C ) :: C_obj + INTEGER(IntKi) :: NumSC2Ctrl !< number of controller inputs [from supercontroller] [-] + INTEGER(IntKi) :: NumCtrl2SC !< number of controller outputs [to supercontroller] [-] + END TYPE SC_InitInputType +! ======================= +! ========= SC_InitOutputType_C ======= + TYPE, BIND(C) :: SC_InitOutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + END TYPE SC_InitOutputType_C + TYPE, PUBLIC :: SC_InitOutputType + TYPE( SC_InitOutputType_C ) :: C_obj + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE SC_InitOutputType +! ======================= +! ========= SC_ParameterType_C ======= + TYPE, BIND(C) :: SC_ParameterType_C + TYPE(C_PTR) :: object = C_NULL_PTR + LOGICAL(KIND=C_BOOL) :: scOn + END TYPE SC_ParameterType_C + TYPE, PUBLIC :: SC_ParameterType + TYPE( SC_ParameterType_C ) :: C_obj + LOGICAL :: scOn = .FALSE. !< Flag that tells this module if supercontroller is on. [-] + END TYPE SC_ParameterType +! ======================= +! ========= SC_InputType_C ======= + TYPE, BIND(C) :: SC_InputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: toSC = C_NULL_PTR + INTEGER(C_int) :: toSC_Len = 0 + END TYPE SC_InputType_C + TYPE, PUBLIC :: SC_InputType + TYPE( SC_InputType_C ) :: C_obj + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: toSC => NULL() !< inputs to the super controller (from the turbine controller) [-] + END TYPE SC_InputType +! ======================= +! ========= SC_OutputType_C ======= + TYPE, BIND(C) :: SC_OutputType_C + TYPE(C_PTR) :: object = C_NULL_PTR + TYPE(C_ptr) :: fromSC = C_NULL_PTR + INTEGER(C_int) :: fromSC_Len = 0 + END TYPE SC_OutputType_C + TYPE, PUBLIC :: SC_OutputType + TYPE( SC_OutputType_C ) :: C_obj + REAL(KIND=C_FLOAT) , DIMENSION(:), POINTER :: fromSC => NULL() !< outputs of the super controller (to the turbine controller) [-] + END TYPE SC_OutputType +! ======================= +CONTAINS + SUBROUTINE SC_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SC_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SC_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 = 'SC_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%NumSC2Ctrl = SrcInitInputData%NumSC2Ctrl + DstInitInputData%C_obj%NumSC2Ctrl = SrcInitInputData%C_obj%NumSC2Ctrl + DstInitInputData%NumCtrl2SC = SrcInitInputData%NumCtrl2SC + DstInitInputData%C_obj%NumCtrl2SC = SrcInitInputData%C_obj%NumCtrl2SC + END SUBROUTINE SC_CopyInitInput + + SUBROUTINE SC_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SC_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SC_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SC_DestroyInitInput + + SUBROUTINE SC_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(SC_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 = 'SC_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 ! NumSC2Ctrl + Int_BufSz = Int_BufSz + 1 ! NumCtrl2SC + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%NumSC2Ctrl + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumCtrl2SC + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SC_PackInitInput + + SUBROUTINE SC_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(SC_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 = 'SC_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%NumSC2Ctrl = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumSC2Ctrl = OutData%NumSC2Ctrl + OutData%NumCtrl2SC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%NumCtrl2SC = OutData%NumCtrl2SC + END SUBROUTINE SC_UnPackInitInput + + SUBROUTINE SC_C2Fary_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%NumSC2Ctrl = InitInputData%C_obj%NumSC2Ctrl + InitInputData%NumCtrl2SC = InitInputData%C_obj%NumCtrl2SC + END SUBROUTINE SC_C2Fary_CopyInitInput + + SUBROUTINE SC_F2C_CopyInitInput( InitInputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + InitInputData%C_obj%NumSC2Ctrl = InitInputData%NumSC2Ctrl + InitInputData%C_obj%NumCtrl2SC = InitInputData%NumCtrl2SC + END SUBROUTINE SC_F2C_CopyInitInput + + SUBROUTINE SC_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SC_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SC_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 = 'SC_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 SC_CopyInitOutput + + SUBROUTINE SC_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SC_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SC_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE SC_DestroyInitOutput + + SUBROUTINE SC_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(SC_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 = 'SC_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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + 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 SC_PackInitOutput + + SUBROUTINE SC_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(SC_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 = 'SC_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 SC_UnPackInitOutput + + SUBROUTINE SC_C2Fary_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE SC_C2Fary_CopyInitOutput + + SUBROUTINE SC_F2C_CopyInitOutput( InitOutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + END SUBROUTINE SC_F2C_CopyInitOutput + + SUBROUTINE SC_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SC_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SC_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 = 'SC_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%scOn = SrcParamData%scOn + DstParamData%C_obj%scOn = SrcParamData%C_obj%scOn + END SUBROUTINE SC_CopyParam + + SUBROUTINE SC_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SC_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SC_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SC_DestroyParam + + SUBROUTINE SC_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(SC_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 = 'SC_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 ! scOn + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = TRANSFER(InData%scOn, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SC_PackParam + + SUBROUTINE SC_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(SC_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 = 'SC_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%scOn = TRANSFER(IntKiBuf(Int_Xferred), OutData%scOn) + Int_Xferred = Int_Xferred + 1 + OutData%C_obj%scOn = OutData%scOn + END SUBROUTINE SC_UnPackParam + + SUBROUTINE SC_C2Fary_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%scOn = ParamData%C_obj%scOn + END SUBROUTINE SC_C2Fary_CopyParam + + SUBROUTINE SC_F2C_CopyParam( ParamData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + ParamData%C_obj%scOn = ParamData%scOn + END SUBROUTINE SC_F2C_CopyParam + + SUBROUTINE SC_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SC_InputType), INTENT(IN) :: SrcInputData + TYPE(SC_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SC_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcInputData%toSC)) THEN + i1_l = LBOUND(SrcInputData%toSC,1) + i1_u = UBOUND(SrcInputData%toSC,1) + IF (.NOT. ASSOCIATED(DstInputData%toSC)) THEN + ALLOCATE(DstInputData%toSC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%toSC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstInputData%c_obj%toSC_Len = SIZE(DstInputData%toSC) + IF (DstInputData%c_obj%toSC_Len > 0) & + DstInputData%c_obj%toSC = C_LOC( DstInputData%toSC(i1_l) ) + END IF + DstInputData%toSC = SrcInputData%toSC +ENDIF + END SUBROUTINE SC_CopyInput + + SUBROUTINE SC_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SC_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SC_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(InputData%toSC)) THEN + DEALLOCATE(InputData%toSC) + InputData%toSC => NULL() + InputData%C_obj%toSC = C_NULL_PTR + InputData%C_obj%toSC_Len = 0 +ENDIF + END SUBROUTINE SC_DestroyInput + + SUBROUTINE SC_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(SC_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 = 'SC_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 ! toSC allocated yes/no + IF ( ASSOCIATED(InData%toSC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! toSC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%toSC) ! toSC + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%toSC) ) 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%toSC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%toSC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%toSC,1), UBOUND(InData%toSC,1) + ReKiBuf(Re_Xferred) = InData%toSC(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SC_PackInput + + SUBROUTINE SC_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(SC_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SC_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 ! toSC 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 (ASSOCIATED(OutData%toSC)) DEALLOCATE(OutData%toSC) + ALLOCATE(OutData%toSC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%toSC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%toSC_Len = SIZE(OutData%toSC) + IF (OutData%c_obj%toSC_Len > 0) & + OutData%c_obj%toSC = C_LOC( OutData%toSC(i1_l) ) + DO i1 = LBOUND(OutData%toSC,1), UBOUND(OutData%toSC,1) + OutData%toSC(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SC_UnPackInput + + SUBROUTINE SC_C2Fary_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- toSC Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( InputData%C_obj%toSC ) ) THEN + NULLIFY( InputData%toSC ) + ELSE + CALL C_F_POINTER(InputData%C_obj%toSC, InputData%toSC, (/InputData%C_obj%toSC_Len/)) + END IF + END IF + END SUBROUTINE SC_C2Fary_CopyInput + + SUBROUTINE SC_F2C_CopyInput( InputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- toSC Input Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(InputData%toSC)) THEN + InputData%c_obj%toSC_Len = 0 + InputData%c_obj%toSC = C_NULL_PTR + ELSE + InputData%c_obj%toSC_Len = SIZE(InputData%toSC) + IF (InputData%c_obj%toSC_Len > 0) & + InputData%c_obj%toSC = C_LOC( InputData%toSC( LBOUND(InputData%toSC,1) ) ) + END IF + END IF + END SUBROUTINE SC_F2C_CopyInput + + SUBROUTINE SC_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SC_OutputType), INTENT(IN) :: SrcOutputData + TYPE(SC_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'SC_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(SrcOutputData%fromSC)) THEN + i1_l = LBOUND(SrcOutputData%fromSC,1) + i1_u = UBOUND(SrcOutputData%fromSC,1) + IF (.NOT. ASSOCIATED(DstOutputData%fromSC)) THEN + ALLOCATE(DstOutputData%fromSC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%fromSC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DstOutputData%c_obj%fromSC_Len = SIZE(DstOutputData%fromSC) + IF (DstOutputData%c_obj%fromSC_Len > 0) & + DstOutputData%c_obj%fromSC = C_LOC( DstOutputData%fromSC(i1_l) ) + END IF + DstOutputData%fromSC = SrcOutputData%fromSC +ENDIF + END SUBROUTINE SC_CopyOutput + + SUBROUTINE SC_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SC_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SC_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ASSOCIATED(OutputData%fromSC)) THEN + DEALLOCATE(OutputData%fromSC) + OutputData%fromSC => NULL() + OutputData%C_obj%fromSC = C_NULL_PTR + OutputData%C_obj%fromSC_Len = 0 +ENDIF + END SUBROUTINE SC_DestroyOutput + + SUBROUTINE SC_PackOutput( 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(SC_OutputType), 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 = 'SC_PackOutput' + ! 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 ! fromSC allocated yes/no + IF ( ASSOCIATED(InData%fromSC) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! fromSC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%fromSC) ! fromSC + 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) + + IF (C_ASSOCIATED(InData%C_obj%object)) CALL SetErrStat(ErrID_Severe,'C_obj%object cannot be packed.',ErrStat,ErrMsg,RoutineName) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ASSOCIATED(InData%fromSC) ) 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%fromSC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%fromSC,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%fromSC,1), UBOUND(InData%fromSC,1) + ReKiBuf(Re_Xferred) = InData%fromSC(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SC_PackOutput + + SUBROUTINE SC_UnPackOutput( 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(SC_OutputType), 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 = 'SC_UnPackOutput' + ! 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 ! fromSC 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 (ASSOCIATED(OutData%fromSC)) DEALLOCATE(OutData%fromSC) + ALLOCATE(OutData%fromSC(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%fromSC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + OutData%c_obj%fromSC_Len = SIZE(OutData%fromSC) + IF (OutData%c_obj%fromSC_Len > 0) & + OutData%c_obj%fromSC = C_LOC( OutData%fromSC(i1_l) ) + DO i1 = LBOUND(OutData%fromSC,1), UBOUND(OutData%fromSC,1) + OutData%fromSC(i1) = REAL(ReKiBuf(Re_Xferred), C_FLOAT) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE SC_UnPackOutput + + SUBROUTINE SC_C2Fary_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- fromSC Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. C_ASSOCIATED( OutputData%C_obj%fromSC ) ) THEN + NULLIFY( OutputData%fromSC ) + ELSE + CALL C_F_POINTER(OutputData%C_obj%fromSC, OutputData%fromSC, (/OutputData%C_obj%fromSC_Len/)) + END IF + END IF + END SUBROUTINE SC_C2Fary_CopyOutput + + SUBROUTINE SC_F2C_CopyOutput( OutputData, ErrStat, ErrMsg, SkipPointers ) + TYPE(SC_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: SkipPointers + ! + LOGICAL :: SkipPointers_local + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(SkipPointers)) THEN + SkipPointers_local = SkipPointers + ELSE + SkipPointers_local = .false. + END IF + + ! -- fromSC Output Data fields + IF ( .NOT. SkipPointers_local ) THEN + IF ( .NOT. ASSOCIATED(OutputData%fromSC)) THEN + OutputData%c_obj%fromSC_Len = 0 + OutputData%c_obj%fromSC = C_NULL_PTR + ELSE + OutputData%c_obj%fromSC_Len = SIZE(OutputData%fromSC) + IF (OutputData%c_obj%fromSC_Len > 0) & + OutputData%c_obj%fromSC = C_LOC( OutputData%fromSC( LBOUND(OutputData%fromSC,1) ) ) + END IF + END IF + END SUBROUTINE SC_F2C_CopyOutput + + + SUBROUTINE SC_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SC_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SC_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SC_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SC_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SC_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SC_Input_ExtrapInterp + + + SUBROUTINE SC_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SC_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(SC_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SC_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Input_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(u_out%toSC) .AND. ASSOCIATED(u1%toSC)) THEN + DO i1 = LBOUND(u_out%toSC,1),UBOUND(u_out%toSC,1) + b = -(u1%toSC(i1) - u2%toSC(i1)) + u_out%toSC(i1) = u1%toSC(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE SC_Input_ExtrapInterp1 + + + SUBROUTINE SC_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SC_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(SC_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(SC_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SC_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(u_out%toSC) .AND. ASSOCIATED(u1%toSC)) THEN + DO i1 = LBOUND(u_out%toSC,1),UBOUND(u_out%toSC,1) + b = (t(3)**2*(u1%toSC(i1) - u2%toSC(i1)) + t(2)**2*(-u1%toSC(i1) + u3%toSC(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%toSC(i1) + t(3)*u2%toSC(i1) - t(2)*u3%toSC(i1) ) * scaleFactor + u_out%toSC(i1) = u1%toSC(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE SC_Input_ExtrapInterp2 + + + SUBROUTINE SC_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SC_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SC_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SC_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SC_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SC_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SC_Output_ExtrapInterp + + + SUBROUTINE SC_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SC_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(SC_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SC_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Output_ExtrapInterp1' + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / t(2) +IF (ASSOCIATED(y_out%fromSC) .AND. ASSOCIATED(y1%fromSC)) THEN + DO i1 = LBOUND(y_out%fromSC,1),UBOUND(y_out%fromSC,1) + b = -(y1%fromSC(i1) - y2%fromSC(i1)) + y_out%fromSC(i1) = y1%fromSC(i1) + b * ScaleFactor + END DO +END IF ! check if allocated + END SUBROUTINE SC_Output_ExtrapInterp1 + + + SUBROUTINE SC_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SC_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(SC_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(SC_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SC_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b ! temporary for extrapolation/interpolation + REAL(DbKi) :: c ! temporary for extrapolation/interpolation + REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SC_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ASSOCIATED(y_out%fromSC) .AND. ASSOCIATED(y1%fromSC)) THEN + DO i1 = LBOUND(y_out%fromSC,1),UBOUND(y_out%fromSC,1) + b = (t(3)**2*(y1%fromSC(i1) - y2%fromSC(i1)) + t(2)**2*(-y1%fromSC(i1) + y3%fromSC(i1)))* scaleFactor + c = ( (t(2)-t(3))*y1%fromSC(i1) + t(3)*y2%fromSC(i1) - t(2)*y3%fromSC(i1) ) * scaleFactor + y_out%fromSC(i1) = y1%fromSC(i1) + b + c * t_out + END DO +END IF ! check if allocated + END SUBROUTINE SC_Output_ExtrapInterp2 + +END MODULE SuperController_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/supercontroller/src/SuperController_Types.h b/OpenFAST/modules/supercontroller/src/SuperController_Types.h new file mode 100644 index 000000000..c38bcf67a --- /dev/null +++ b/OpenFAST/modules/supercontroller/src/SuperController_Types.h @@ -0,0 +1,55 @@ +//!STARTOFREGISTRYGENERATEDFILE 'SuperController_Types.h' +//! +//! WARNING This file is generated automatically by the FAST registry. +//! Do not edit. Your changes to this file will be lost. +//! + +#ifndef _SuperController_TYPES_H +#define _SuperController_TYPES_H + + +#ifdef _WIN32 //define something for Windows (32-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#elif _WIN64 //define something for Windows (64-bit) +# include "stdbool.h" +# define CALL __declspec( dllexport ) +#else +# include <stdbool.h> +# define CALL +#endif + + + typedef struct SC_InitInputType { + void * object ; + int NumSC2Ctrl ; + int NumCtrl2SC ; + } SC_InitInputType_t ; + typedef struct SC_InitOutputType { + void * object ; + + } SC_InitOutputType_t ; + typedef struct SC_ParameterType { + void * object ; + bool scOn ; + } SC_ParameterType_t ; + typedef struct SC_InputType { + void * object ; + float * toSC ; int toSC_Len ; + } SC_InputType_t ; + typedef struct SC_OutputType { + void * object ; + float * fromSC ; int fromSC_Len ; + } SC_OutputType_t ; + typedef struct SC_UserData { + SC_InitInputType_t SC_InitInput ; + SC_InitOutputType_t SC_InitOutput ; + SC_ParameterType_t SC_Param ; + SC_InputType_t SC_Input ; + SC_OutputType_t SC_Output ; + } SC_t ; + +#endif // _SuperController_TYPES_H + + +//!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/modules/turbsim/CMakeLists.txt b/OpenFAST/modules/turbsim/CMakeLists.txt new file mode 100644 index 000000000..38a1cdb0b --- /dev/null +++ b/OpenFAST/modules/turbsim/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# Copyright 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. +# + +set(MODULE_SOURCES + src/BlankModVKM.f90 + src/CohStructures.f90 + src/Profiles.f90 + src/RandNum.f90 + src/Root_Searching.f90 + src/TS_FileIO.f90 + src/TSsubs.f90 + src/TurbSim.f90 + src/TurbSim_Types.f90 + src/VelocitySpectra.f90 + ) + +add_executable(turbsim ${MODULE_SOURCES}) +target_link_libraries(turbsim nwtclibs versioninfolib) + +install(TARGETS turbsim RUNTIME DESTINATION bin) diff --git a/OpenFAST/modules/turbsim/README.md b/OpenFAST/modules/turbsim/README.md new file mode 100644 index 000000000..0c79c2c5c --- /dev/null +++ b/OpenFAST/modules/turbsim/README.md @@ -0,0 +1,16 @@ +# TurbSim Module +The legacy version of this module and additional documentation are available +at the [NWTC Software Portal](https://nwtc.nrel.gov/TurbSim/). + +## Overview +TurbSim is a stochastic, full-field, turbulent-wind simulator primarialy for +use with [InflowWind](https://nwtc.nrel.gov/InflowWind "InflowWind")-based +simulation tools. It uses a statistical model (as opposed to a physics-based +model) to numerically simulate time series of three-component wind-speed +vectors at points in a two-dimensional vertical rectangular grid that is fixed +in space. + +Spectra of velocity components and spatial coherence are defined in the +frequency domain, and an inverse Fourier transform produces time series. The +underlying theory behind this method of simulating time series assumes a +stationary process. diff --git a/OpenFAST/modules/turbsim/src/BlankModVKM.f90 b/OpenFAST/modules/turbsim/src/BlankModVKM.f90 new file mode 100644 index 000000000..67639b856 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/BlankModVKM.f90 @@ -0,0 +1,76 @@ +MODULE ModifiedvKrm_mod + + USE NWTC_Library + + IMPLICIT NONE + +CONTAINS +!======================================================================= +SUBROUTINE Mod_vKrm ( Ht, Ucmp, Spec ) + + ! This subroutine defines the "Improved" von Karman PSD model. + ! The use of this subroutine requires that all variables have the units of meters and seconds. + IMPLICIT NONE + + !Passed variables + + REAL(ReKi), INTENT(IN) :: Ht ! height + REAL(ReKi), INTENT(IN) :: UCmp ! wind speed + REAL(ReKi), INTENT( OUT) :: Spec (:,:) + + Spec = 0.0_ReKi + +RETURN +END SUBROUTINE Mod_vKrm +!======================================================================= +SUBROUTINE ScaleMODVKM(Ht,UCmp, LambdaU, LambdaV, LambdaW) + +! THIS SUBROUTINE DEFINES HUB SCALE PARMS FOR Modified von KARMAN PSD MODEL + IMPLICIT NONE + + REAL(ReKi), INTENT(IN) :: Ht ! height + REAL(ReKi), INTENT(IN) :: UCmp ! wind speed + + REAL(ReKi) :: LambdaU + REAL(ReKi) :: LambdaV + REAL(ReKi) :: LambdaW + +RETURN +END SUBROUTINE ScaleMODVKM +!======================================================================= +FUNCTION FindZ0(z, sigma, U, f) + + ! This function is used in the Modified von Karman model to + ! determine the necessary surface roughness length for a given sigma. + IMPLICIT NONE + + REAL(ReKi) :: FindZ0 ! Estimated surface roughness length + REAL(ReKi),INTENT(IN) :: z ! Hub height + REAL(ReKi),INTENT(IN) :: sigma ! Target std deviation + REAL(ReKi),INTENT(IN) :: U ! Hub height wind speed + REAL(ReKi),INTENT(IN) :: f ! Coriolis parameter + + FindZ0 = 1.0 ! a default value + +RETURN +END FUNCTION FindZ0 +!======================================================================= +FUNCTION CalcDiff(z0Guess, z, sigma, U, f) + + ! This function calculates the difference between the specified + ! sigma and the calculated one. + IMPLICIT NONE + + REAL(ReKi) :: CalcDiff ! Output - will be nearly zero if surface roughness is correct + REAL(ReKi), INTENT(IN) :: z0Guess ! estimated surface roughness + REAL(ReKi), INTENT(IN) :: z ! Hub height (m) + REAL(ReKi), INTENT(IN) :: sigma ! Target standard deviation (m/s) + REAL(ReKi), INTENT(IN) :: U ! Mean hub-height wind speed (m/s) + REAL(ReKi), INTENT(IN) :: f ! Coriolis parameter + + CalcDiff = 0.0 + +RETURN +END FUNCTION CalcDiff +!======================================================================= +END MODULE ModifiedvKrm_mod diff --git a/OpenFAST/modules/turbsim/src/CohStructures.f90 b/OpenFAST/modules/turbsim/src/CohStructures.f90 new file mode 100644 index 000000000..9c1ad5214 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/CohStructures.f90 @@ -0,0 +1,901 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TS_CohStructures + + USE TurbSim_Types + + use TS_Profiles + use TS_RandNum + + IMPLICIT NONE + + + REAL(ReKi), PARAMETER :: KHT_LES_dT = 0.036335 ! The average time step in the LES test file, used here for the KH test + REAL(ReKi), PARAMETER :: KHT_LES_Zm = 6.35475 ! The non-dimensional z dimension defined in LES test file, used here for the KH test + + TYPE :: Event ! Coherent turbulent event to add to the background wind + INTEGER :: EventNum ! The event number (index into EventID() array) + REAL(ReKi) :: TStart ! The time at which to add this event + REAL(ReKi) :: delt ! The delta time before the event begins (for interpolation in AeroDyn) + LOGICAL :: Connect2Prev = .FALSE. ! Whether this event is connected to the next, otherwise there is space between them + TYPE(Event), POINTER :: Next => NULL() ! The next event to add + END TYPE + + TYPE :: CohStr_OutputType + REAL(ReKi) :: CTKE ! Maximum predicted Coherent Turbulent Kenetic Energy at the center of the billow + REAL(ReKi) :: lambda ! The expected value of interarrival times for the Poisson process + INTEGER(IntKi) :: NumCTEvents ! Number of events to be inserted into the .cts file + INTEGER(IntKi) :: NumCTEvents_separate ! Number of separate events inserted into the .cts file (# events with .Connect2Prev = .false.) + REAL(ReKi) :: ExpectedTime ! Amount of time the coherent structures should take + REAL(ReKi) :: EventTimeSum ! Amount of time the coherent structure takes + REAL(ReKi) :: EventTimeStep ! The average length of timesteps in output events + + REAL(ReKi) :: Zbottom ! The height of the lowest point on the grid (before tower points are added), equal to Z(1) + REAL(ReKi) :: ScaleWid ! Scaling width for LE coherent turbulence (RotDiam in AeroDyn FD_Wind) + REAL(ReKi) :: ScaleVel ! Scaling velocity for LE coherent turbulence, U0. 2*U0 is the difference in wind speed between the top and bottom of the wave. + + REAL(ReKi) :: Uwave ! Wind speed at center of the k-h billow (wave) + REAL(ReKi) :: Wsig ! Standard deviation of the w-component wind speed + + + INTEGER(IntKi) :: NumCTt ! Number of data points to be printed in the output coherent event timestep file + + TYPE (Event), POINTER :: PtrHead => NULL() ! Pointer to the first event + TYPE (Event), POINTER :: PtrTail => NULL() ! Pointer to the last event + + END TYPE CohStr_OutputType + + + ! local type, used only in two subroutines here + TYPE :: CohStr_EventType + + REAL(ReKi) :: Ym_max ! The nondimensional lateral width of the coherent turbulence dataset + REAL(ReKi) :: Zm_max ! The nondimensional vertical height of the coherent turbulence dataset + + REAL(ReKi), ALLOCATABLE :: pkCTKE (:) ! Array containing the peak CTKE of each coherent event + REAL(ReKi), ALLOCATABLE :: EventLen (:) ! The length of each event stored in EventStart() (non-dimensional time) + INTEGER(IntKi), ALLOCATABLE :: EventID (:) ! The timestep where the event starts, which determines the name of the event file + INTEGER(IntKi), ALLOCATABLE :: EventTS (:) ! The length of each event stored in EventStart() (number of timesteps) + INTEGER(IntKi) :: NumEvents ! Number of events in the event data file (length of the Event* arrays) + + END TYPE CohStr_EventType + + + +CONTAINS + +!======================================================================= +SUBROUTINE CohStr_ReadEventFile( p_CohStr, y_CohStr, e_CohStr, TSclFact, ErrStat, ErrMsg ) + + ! This subroutine reads the events definitions from the event data file + + + IMPLICIT NONE + + + ! Passed Variables + +TYPE(CohStr_ParameterType), INTENT(IN ) :: p_CohStr +TYPE(CohStr_OutputType), INTENT(INOUT) :: y_CohStr +TYPE(CohStr_EventType), INTENT( OUT) :: e_CohStr + +!REAL(ReKi), INTENT(IN) :: CTKE ! Predicted maximum CTKE +!REAL(ReKi), INTENT(INOUT) :: ScaleVel ! The shear we're scaling for +!REAL(ReKi), INTENT(IN) :: ScaleWid ! The height of the wave we're scaling with +REAL(ReKi), INTENT( OUT) :: TsclFact ! Scale factor for time (h/U0) in coherent turbulence events +INTEGER(IntKi), intent( out) :: ErrStat ! Error level +CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + ! Local variables +REAL(ReKi) :: MaxEvtCTKE ! The maximum CTKE in the dataset of events + +INTEGER :: I ! DO loop counter +INTEGER :: IOS ! I/O Status +INTEGER :: Un ! I/O Unit + +INTEGER(IntKi) :: ErrStat2 ! Error level (local) +CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + + + ErrStat = ErrID_None + ErrMsg = "" + + MaxEvtCTKE = 0.0 ! initialize the MAX variable + + CALL GetNewUnit( Un, ErrStat2, ErrMsg2 ) + + CALL OpenFInpFile ( Un, p_CohStr%CTEventFile, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + IF (ErrStat >= AbortErrLev) RETURN + + + ! Read the nondimensional lateral width of the dataset, Ym_max + + CALL ReadVar( Un, p_CohStr%CTEventFile, e_CohStr%Ym_max, "Ym_max", "Nondimensional lateral dataset width", ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + + ! Read the nondimensional vertical height of the dataset, Zm_max + + CALL ReadVar( Un, p_CohStr%CTEventFile, e_CohStr%Zm_max, "Zm_max", "Nondimensional vertical dataset height", ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + + + ! Read the rest of the header + + CALL ReadVar( Un, p_CohStr%CTEventFile, e_CohStr%NumEvents, "NumEvents", "the number of coherent structures.", ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + + + IF (ErrStat >= AbortErrLev) THEN + CLOSE(Un) + RETURN + END IF + + + IF ( e_CohStr%NumEvents > 0 ) THEN + + + CALL AllocAry( e_CohStr%EventID, e_CohStr%NumEvents , 'EventID', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CohStr_ReadEventFile') + CALL AllocAry( e_CohStr%EventTS, e_CohStr%NumEvents , 'EventTS', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CohStr_ReadEventFile') + CALL AllocAry( e_CohStr%EventLen, e_CohStr%NumEvents , 'EventLen', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CohStr_ReadEventFile') + CALL AllocAry( e_CohStr%pkCTKE, e_CohStr%NumEvents , 'pkCTKE', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CohStr_ReadEventFile') + + IF (ErrStat >= AbortErrLev) THEN + CLOSE(Un) + RETURN + END IF + + ! Read the last header lines + + CALL ReadCom( Un, p_CohStr%CTEventFile, 'the fourth header line', ErrStat2, ErrMsg2) ! A blank line + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + CALL ReadCom( Un, p_CohStr%CTEventFile, 'the fifth header line', ErrStat2, ErrMsg2) ! The column heading lines + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_ReadEventFile') + + + ! Read the event definitions and scale times by TScale + + DO I=1,e_CohStr%NumEvents + + READ ( Un, *, IOSTAT=IOS ) e_CohStr%EventID(I), e_CohStr%EventTS(I), e_CohStr%EventLen(I), e_CohStr%pkCTKE(I) + + IF ( IOS /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal, 'Error reading event '//TRIM( Int2LStr( I ) )//' from the coherent event data file.', ErrStat, ErrMsg, 'CohStr_ReadEventFile') + CLOSE(UN) + RETURN + ENDIF + MaxEvtCTKE = MAX( MaxEvtCTKE, e_CohStr%pkCTKE(I) ) + + ENDDO + + IF ( MaxEvtCTKE > 0.0 ) THEN + y_CohStr%ScaleVel = MAX( y_CohStr%ScaleVel, SQRT( y_CohStr%CTKE / MaxEvtCTKE ) ) + ! Calculate the Velocity Scale Factor, based on the requested maximum CTKE + ENDIF + + ! Calculate the TimeScaleFactor, based on the Zm_max in the Events file. + + TSclFact = y_CohStr%ScaleWid / (y_CohStr%ScaleVel * e_CohStr%Zm_max) + + ! Scale the time based on TSclFact + + DO I=1,e_CohStr%NumEvents + e_CohStr%EventLen(I) = e_CohStr%EventLen(I)*TSclFact + ENDDO + + ELSE + + TSclFact = y_CohStr%ScaleWid / (y_CohStr%ScaleVel * e_CohStr%Zm_max) + + ENDIF ! FileNum > 0 + + CLOSE ( Un ) + +END SUBROUTINE CohStr_ReadEventFile +!======================================================================= +SUBROUTINE CohStr_CalcEvents( p, e_CohStr, Height, OtherSt_RandNum, y_cohStr, ErrStat, ErrMsg ) + + ! This subroutine calculates what events to use and when to use them. + ! It computes the number of timesteps in the file, NumCTt. + + IMPLICIT NONE + + ! passed variables + TYPE(TurbSim_ParameterType), INTENT(IN) :: P + TYPE(CohStr_EventType) , INTENT(IN) :: e_CohStr ! event parameters for coherent structures + REAL(ReKi), INTENT(IN) :: Height ! Height for expected length PDF equation + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum ! other states for random numbers (next seed, etc) + TYPE(CohStr_OutputType), INTENT(INOUT) :: y_CohStr + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Message describing error + + ! local variables +REAL(ReKi) :: iA ! Variable used to calculate IAT +REAL(ReKi) :: iB ! Variable used to calculate IAT +REAL(ReKi) :: iC ! Variable used to calculate IAT +REAL(ReKi) :: rn ! random number +REAL(ReKi) :: TEnd ! End time for the current event +REAL(ReKi) :: TStartNext = 0.0 ! temporary start time for next event +REAL(ReKi) :: MaxCTKE ! Maximum CTKE of events we've picked + +INTEGER :: ErrStat2 ! temp error status +INTEGER :: NewEvent ! event number of the new event +INTEGER :: NumCompared ! Number of events we've compared + +LOGICAL(1) :: Inserted ! Whether an event was inserted here + +TYPE(Event), POINTER :: PtrCurr => NULL() ! Pointer to the current event in the list +TYPE(Event), POINTER :: PtrNew => NULL() ! A new event to be inserted into the list + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Compute the mean interarrival time and the expected length of events + + SELECT CASE ( p%met%TurbModel_ID ) + + CASE ( SpecModel_NWTCUP, SpecModel_NONE, SpecModel_USRVKM ) + y_CohStr%lambda = -0.000904*p%met%Rich_No + 0.000562*y_CohStr%Uwave + 0.001389 + y_CohStr%lambda = 1.0 / y_CohStr%lambda + + IF ( p%met%TurbModel_ID == SpecModel_NONE ) THEN + y_CohStr%ExpectedTime = 600.0 + ELSE + CALL RndModLogNorm( p%RNG, OtherSt_RandNum, y_CohStr%ExpectedTime, Height ) + ENDIF + + CASE ( SpecModel_GP_LLJ, SpecModel_SMOOTH, SpecModel_TIDAL, SpecModel_RIVER) ! HYDRO: added 'TIDAL' and 'RIVER' to the spectral models that get handled this way. + iA = 0.001797800 + (7.17399E-10)*Height**3.021144723 + iB = EXP(-10.590340100 - (4.92440E-05)*Height**2.5) + iC = SQRT( 3.655013599 + (8.91203E-06)*Height**3 ) + y_CohStr%lambda = iA + iB*MIN( (y_CohStr%Uwave**iC), HUGE(iC) ) ! lambda = iA + iB*(WindSpeed**iC) + y_CohStr%lambda = 1.0 / y_CohStr%lambda + + CALL RndTcohLLJ( p%RNG, OtherSt_RandNum, y_CohStr%ExpectedTime, Height ) + + CASE ( SpecModel_WF_UPW ) + y_CohStr%lambda = 0.000529*y_CohStr%Uwave + 0.000365*p%met%Rich_No - 0.000596 + y_CohStr%lambda = 1.0 / y_CohStr%lambda + + CALL RndTcoh_WF( p%RNG, OtherSt_RandNum, y_CohStr%ExpectedTime, SpecModel_WF_UPW ) + + CASE ( SpecModel_WF_07D ) + y_CohStr%lambda = 0.000813*y_CohStr%Uwave - 0.002642*p%met%Rich_No + 0.002676 + y_CohStr%lambda = 1.0 / y_CohStr%lambda + + CALL RndTcoh_WF( p%RNG, OtherSt_RandNum, y_CohStr%ExpectedTime, SpecModel_WF_07D ) + + CASE ( SpecModel_WF_14D ) + y_CohStr%lambda = 0.001003*y_CohStr%Uwave - 0.00254*p%met%Rich_No - 0.000984 + y_CohStr%lambda = 1.0 / y_CohStr%lambda + + CALL RndTcoh_WF( p%RNG, OtherSt_RandNum, y_CohStr%ExpectedTime, SpecModel_WF_14D ) + + CASE DEFAULT + !This should not happen + + END SELECT + + y_CohStr%ExpectedTime = y_CohStr%ExpectedTime * ( p%grid%UsableTime - p%CohStr%CTStartTime ) / 600.0_ReKi ! Scale for use with the amount of time we've been given + + +!BONNIE: PERHAPS WE SHOULD JUST PUT IN A CHECK THAT TURNS OFF THE COHERENT TIME STEP FILE IF THE +! CTSTARTTIME IS LESS THAN THE USABLETIME... MAYBE WHEN WE'RE READING THE INPUT FILE... +y_CohStr%ExpectedTime = MAX( y_CohStr%ExpectedTime, 0.0_ReKi ) ! This occurs if CTStartTime = 0 + + ! We start by adding events at random times + + y_CohStr%NumCTEvents = 0 ! Number of events = length of our linked list + y_CohStr%NumCTt = 0 ! Total number of time steps in the events we've picked + MaxCTKE = 0.0 ! Find the maximum CTKE for the events that we've selected + + y_CohStr%EventTimeSum = 0.0 + + CALL RndExp(p%RNG, OtherSt_RandNum, rn, y_CohStr%lambda) ! Assume the last event ended at time zero + + TStartNext = rn / 2.0 + + IF ( p%met%KHtest ) THEN + y_CohStr%ExpectedTime = p%grid%UsableTime / 2 ! When testing, add coherent events for half of the record + TStartNext = y_CohStr%ExpectedTime / 2 ! When testing, start about a quarter of the way into the record + ENDIF + + IF ( TStartNext < p%CohStr%CTStartTime ) THEN + TStartNext = TStartNext + p%CohStr%CTStartTime ! Make sure the events start after time specified by CTStartTime + ENDIF + + IF ( TStartNext > 0 ) y_CohStr%NumCTt = y_CohStr%NumCTt + 1 ! Add a point before the first event + + DO WHILE ( TStartNext < p%grid%UsableTime .AND. y_CohStr%EventTimeSum < y_CohStr%ExpectedTime ) + + CALL RndUnif( p%RNG, OtherSt_RandNum, rn ) + + NewEvent = INT( rn*( e_CohStr%NumEvents - 1 ) ) + 1 + NewEvent = MAX( 1, MIN( NewEvent, e_CohStr%NumEvents ) ) ! take care of possible rounding issues.... + + + IF ( .NOT. ASSOCIATED ( y_CohStr%PtrHead ) ) THEN + + ALLOCATE ( y_CohStr%PtrHead, STAT=ErrStat2 ) ! The pointer %Next is nullified in allocation + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for new event.' , ErrStat, ErrMsg, 'CohStr_CalcEvents') + RETURN + ENDIF + + y_CohStr%PtrTail => y_CohStr%PtrHead + + ELSE + + ALLOCATE ( y_CohStr%PtrTail%Next, STAT=ErrStat2 ) ! The pointer PtrTail%Next%Next is nullified in allocation + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for new event.' , ErrStat, ErrMsg, 'CohStr_CalcEvents') + RETURN + ENDIF + + y_CohStr%PtrTail => y_CohStr%PtrTail%Next ! Move the pointer to point to the last record in the list + + ENDIF + + y_CohStr%PtrTail%EventNum = NewEvent + y_CohStr%PtrTail%TStart = TStartNext + y_CohStr%PtrTail%delt = e_CohStr%EventLen( NewEvent ) / e_CohStr%EventTS( NewEvent ) ! the average delta time in the event + y_CohStr%PtrTail%Connect2Prev = .FALSE. + + MaxCTKE = MAX( MaxCTKE, e_CohStr%pkCTKE( NewEvent ) ) + y_CohStr%NumCTEvents = y_CohStr%NumCTEvents + 1 + + TEnd = TStartNext + e_CohStr%EventLen( NewEvent ) + + + IF ( p%met%KHtest ) THEN + TStartNext = p%grid%UsableTime + TStartNext !TEnd + PtrTail%delt ! Add the events right after each other + ELSE + + DO WHILE ( TStartNext <= TEnd ) + + CALL RndExp(p%RNG, OtherSt_RandNum, rn, y_CohStr%lambda) ! compute the interarrival time + TStartNext = TStartNext + rn !+ EventLen( NewEvent ) + + ENDDO + + ENDIF + + + IF ( (TStartNext - TEnd) > y_CohStr%PtrTail%delt ) THEN + y_CohStr%NumCTt = y_CohStr%NumCTt + e_CohStr%EventTS( NewEvent ) + 2 ! add a zero-line (essentially a break between events) + ELSE + y_CohStr%NumCTt = y_CohStr%NumCTt + e_CohStr%EventTS( NewEvent ) + 1 + ENDIF + + y_CohStr%EventTimeSum = y_CohStr%EventTimeSum + e_CohStr%EventLen( NewEvent ) + + ENDDO + + y_CohStr%NumCTEvents_separate = y_CohStr%NumCTEvents + + ! Next, we start concatenating events until there is no space or we exceed the expected time + + IF ( p%met%TurbModel_ID /= SpecModel_NONE ) THEN + + NumCompared = 0 + + DO WHILE ( y_CohStr%EventTimeSum < y_CohStr%ExpectedTime .AND. NumCompared < y_CohStr%NumCTEvents ) + + CALL RndUnif( p%RNG, OtherSt_RandNum, rn ) + + NewEvent = INT( rn*( e_CohStr%NumEvents - 1.0 ) ) + 1 + NewEvent = MAX( 1, MIN( NewEvent, e_CohStr%NumEvents ) ) ! take care of possible rounding issues.... + + NumCompared = 0 + Inserted = .FALSE. + + DO WHILE ( NumCompared < y_CohStr%NumCTEvents .AND. .NOT. Inserted ) + + IF ( .NOT. ASSOCIATED ( PtrCurr ) ) THEN ! Wrap around to the beginning of the list + PtrCurr => y_CohStr%PtrHead + ENDIF + + + ! See if the NewEvent fits between the end of event pointed to by PtrCurr and the + ! beginning of the event pointed to by PtrCurr%Next + + IF ( ASSOCIATED( PtrCurr%Next ) ) THEN + TStartNext = PtrCurr%Next%TStart + ELSE !We're starting after the last event in the record + TStartNext = p%grid%UsableTime + 0.5 * e_CohStr%EventLen( NewEvent ) ! We can go a little beyond the end... + ENDIF + + IF ( TStartNext - (PtrCurr%TStart + e_CohStr%EventLen( PtrCurr%EventNum ) + PtrCurr%delt) > e_CohStr%EventLen( NewEvent ) ) THEN + + Inserted = .TRUE. + + ALLOCATE ( PtrNew, STAT=ErrStat2 ) ! The pointer %Next is nullified in allocation + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for new event.' , ErrStat, ErrMsg, 'CohStr_CalcEvents') + ENDIF + + PtrNew%EventNum = NewEvent + PtrNew%TStart = PtrCurr%TStart + e_CohStr%EventLen( PtrCurr%EventNum ) + PtrNew%delt = e_CohStr%EventLen( NewEvent ) / e_CohStr%EventTS( NewEvent ) ! the average delta time in the event + PtrNew%Connect2Prev = .TRUE. + + PtrNew%Next => PtrCurr%Next + PtrCurr%Next => PtrNew + PtrCurr => PtrCurr%Next ! Let's try to add the next event after the other events + + MaxCTKE = MAX( MaxCTKE, e_CohStr%pkCTKE( NewEvent ) ) + y_CohStr%NumCTEvents = y_CohStr%NumCTEvents + 1 + y_CohStr%NumCTt = y_CohStr%NumCTt + e_CohStr%EventTS( NewEvent ) ! there is no break between events + !(we may have one too many NumCTt here, so we'll deal with it when we write the file later) + y_CohStr%EventTimeSum = y_CohStr%EventTimeSum + e_CohStr%EventLen( NewEvent ) + + + ELSE + + NumCompared = NumCompared + 1 + + ENDIF + + PtrCurr => PtrCurr%Next + + ENDDO ! WHILE (NumCompared < NumCTEvents .AND. .NOT. Inserted) + + ENDDO ! WHILE (EventTimeSum < ExpectedTime .AND. NumCompared < NumCTEvents) + + ENDIF ! SpecModel /= SpecModel_NONE + + IF ( y_CohStr%NumCTt > 0 ) THEN + y_CohStr%EventTimeStep = y_CohStr%EventTimeSum / y_CohStr%NumCTt ! Average timestep of coherent event data + ELSE + y_CohStr%EventTimeStep = 0.0 + ENDIF + + +END SUBROUTINE CohStr_CalcEvents +!======================================================================= +!> This subroutine writes the coherent events CTS file +SUBROUTINE CohStr_WriteCTS(p, WSig, OtherSt_RandNum, ErrStat, ErrMsg) + + TYPE(TurbSim_ParameterType), INTENT(IN ) :: p ! parameters for TurbSim (out only b/c it doesn't generate file for certain cases...) + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum ! other states for random numbers (next seed, etc) + REAL(ReKi), intent(in ) :: WSig ! Standard deviation of the vertical component + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + ! local variables + TYPE(CohStr_OutputType) :: y_CohStr + type(CohStr_EventType) :: e_CohStr ! coherent structure events + REAL(ReKi) :: TmpVel ! A temporary variable holding a velocity + REAL(ReKi) :: TmpRndNum ! A temporary variable holding a random variate + REAL(ReKi) :: TsclFact ! Scale factor for time (h/U0) in coherent turbulence events + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(MaxMsgLen) :: ErrMsg2 + + + + ErrStat = ErrID_None + ErrMsg = "" + + y_CohStr%WSig=WSig + + + CALL WrScr ( ' Generating coherent turbulent time step file "'//TRIM( p%RootName )//'.cts"' ) + + + y_CohStr%ScaleWid = p%grid%RotorDiameter * p%CohStr%DistScl ! This is the scaled height of the coherent event data set + y_CohStr%Zbottom = p%grid%HubHt - p%CohStr%CTLz*y_CohStr%ScaleWid ! This is the height of the bottom of the wave in the scaled/shifted coherent event data set + + CALL getVelocity(p, p%UHub,p%grid%HubHt,y_CohStr%Zbottom + 0.5_ReKi*y_CohStr%ScaleWid, y_CohStr%Uwave, ErrStat2, ErrMsg2) ! y_CohStr%Uwave =WindSpeed at center of wave + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + + !------------------------- + ! compute ScaleVel: + !------------------------- + + IF ( p%met%KHtest ) THEN + ! for LES test case.... + y_CohStr%ScaleVel = y_CohStr%ScaleWid * KHT_LES_dT / KHT_LES_Zm + y_CohStr%ScaleVel = 50 * y_CohStr%ScaleVel ! We want 25 hz bandwidth so multiply by 50 + ELSE + + CALL getVelocity(p, p%UHub,p%grid%HubHt,y_CohStr%Zbottom, TmpVel, ErrStat2, ErrMsg2) ! Velocity at bottom of billow + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + CALL getVelocity(p, p%UHub,p%grid%HubHt,y_CohStr%Zbottom+y_CohStr%ScaleWid, y_CohStr%ScaleVel, ErrStat2, ErrMsg2) ! Velocity at the top of the billow + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + + y_CohStr%ScaleVel = y_CohStr%ScaleVel - TmpVel ! Shear across the wave + y_CohStr%ScaleVel = 0.5 * y_CohStr%ScaleVel ! U0 is half the difference between the top and bottom of the billow + + + ! If the coherent structures do not cover the whole disk, increase the shear + + IF ( p%CohStr%DistScl < 1.0 ) THEN ! Increase the shear by up to two when the wave is half the size of the disk... + CALL RndUnif( p%RNG, OtherSt_RandNum, TmpRndNum ) !returns TmpRndNum, a random variate + y_CohStr%ScaleVel = y_CohStr%ScaleVel * ( 1.0 + TmpRndNum * (1 - p%CohStr%DistScl) / p%CohStr%DistScl ) + ENDIF + + !Apply a scaling factor to account for short inter-arrival times getting wiped out due to long events + + y_CohStr%ScaleVel = y_CohStr%ScaleVel*( 1.0 + 323.1429 * EXP( -MAX(y_CohStr%Uwave,10.0_ReKi) / 2.16617 ) ) + + ENDIF + + IF (y_CohStr%ScaleVel < 0. ) THEN + CALL SetErrStat( ErrID_Warn, 'A coherent turbulence time step file cannot be generated with negative shear.', ErrStat, ErrMsg, 'CohStr_WriteCTS') + !p%WrFile(FileExt_CTS) = .FALSE. + RETURN + ENDIF + + + !------------------------- + ! compute maximum predicted CTKE: + !------------------------- + + SELECT CASE ( p%met%TurbModel_ID ) + + CASE ( SpecModel_NWTCUP, SpecModel_NONE, SpecModel_USRVKM ) + + IF (p%met%KHtest) THEN + y_CohStr%CTKE = 30.0 !Scale for large coherence + CALL RndNWTCpkCTKE( p%RNG, OtherSt_RandNum, y_CohStr%CTKE ) + ELSE + + ! Increase the Scaling Velocity for computing U,V,W in AeroDyn + ! These numbers are based on LIST/ART data (58m-level sonic anemometer) + + y_CohStr%CTKE = 0.616055*p%met%Rich_No - 0.242143*y_CohStr%Uwave + 23.921801*y_CohStr%WSig - 11.082978 + + ! Add up to +/- 10% or +/- 6 m^2/s^2 (uniform distribution) + CALL RndUnif( p%RNG, OtherSt_RandNum, TmpRndNum ) + y_CohStr%CTKE = MAX( y_CohStr%CTKE + (2.0_ReKi * TmpRndNum - 1.0_ReKi) * 6.0_ReKi, 0.0_ReKi ) + + IF ( y_CohStr%CTKE > 0.0 ) THEN + IF ( y_CohStr%CTKE > 20.0) THEN ! Correct with residual + y_CohStr%CTKE = y_CohStr%CTKE + ( 0.11749127 * (y_CohStr%CTKE**1.369025) - 7.5976449 ) + ENDIF + + IF ( y_CohStr%CTKE >= 30.0 .AND. p%met%Rich_No >= 0.0 .AND. p%met%Rich_No <= 0.05 ) THEN + CALL RndNWTCpkCTKE( p%RNG, OtherSt_RandNum, y_CohStr%CTKE ) + ENDIF + ENDIF + + ENDIF !p%met%KHtest + + CASE ( SpecModel_GP_LLJ, SpecModel_SMOOTH, SpecModel_TIDAL, SpecModel_RIVER ) + + y_CohStr%CTKE = pkCTKE_LLJ( p, OtherSt_RandNum, y_CohStr%Zbottom+0.5_ReKi*y_CohStr%ScaleWid, p%met%ZL, p%met%UStar ) + + CASE ( SpecModel_WF_UPW ) + y_CohStr%CTKE = -2.964523*p%met%Rich_No - 0.207382*y_CohStr%Uwave + 25.640037*y_CohStr%WSig - 10.832925 + + CASE ( SpecModel_WF_07D ) + y_CohStr%CTKE = 9.276618*p%met%Rich_No + 6.557176*p%met%Ustar + 3.779539*y_CohStr%WSig - 0.106633 + + IF ( (p%met%Rich_No > -0.025) .AND. (p%met%Rich_No < 0.05) .AND. (p%met%Ustar > 1.0) .AND. (p%met%Ustar < 1.56) ) THEN + CALL RndpkCTKE_WFTA( p%RNG, OtherSt_RandNum, TmpRndNum ) ! Add a random residual + y_CohStr%CTKE = y_CohStr%CTKE + TmpRndNum + ENDIF + + + CASE ( SpecModel_WF_14D ) + y_CohStr%CTKE = 1.667367*p%met%Rich_No - 0.003063*y_CohStr%Uwave + 19.653682*y_CohStr%WSig - 11.808237 + + CASE DEFAULT ! This case should not happen + CALL SetErrStat( ErrID_Fatal, 'Invalid turbulence model in coherent structure analysis.', ErrStat, ErrMsg, 'CohStr_WriteCTS') + CALL Cleanup() + RETURN + END SELECT + + y_CohStr%CTKE = MAX( y_CohStr%CTKE, 1.0_ReKi ) ! make sure CTKE is not negative and, so that we don't divide by zero in ReadEventFile, set it to some arbitrary low number + + !------------------------- + ! Read and allocate coherent event start times and lengths, calculate TSclFact: + !------------------------- + CALL CohStr_ReadEventFile( p%CohStr, y_CohStr, e_CohStr, TSclFact, ErrStat2, ErrMsg2 ) !y_CohStr%%ScaleWid, y_CohStr%ScaleVel + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL CohStr_CalcEvents( p, e_CohStr, y_CohStr%Zbottom+0.5_ReKi*y_CohStr%ScaleWid, OtherSt_RandNum, y_cohStr, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !------------------------- + ! Write the file: + !------------------------- + + CALL CohStr_WriteEvents ( p%RootName, p%CohStr, e_CohStr, y_CohStr, TSclFact, p%UHub, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteCTS') + + + !------------------------- + ! Write some summary information: + !------------------------- + IF (p%met%KHtest) THEN + WRITE ( p%US,'(/)' ) + ELSE + WRITE ( p%US,'(//A,F8.3," seconds")' ) 'Average expected time between events = ',y_CohStr%lambda + ENDIF + + WRITE ( p%US, '(A,I8)' ) 'Number of coherent events = ', y_CohStr%NumCTEvents_separate + WRITE ( p%US, '(A,F8.3," seconds")') 'Predicted length of coherent events = ', y_CohStr%ExpectedTime + WRITE ( p%US, '(A,F8.3," seconds")') 'Length of coherent events = ', y_CohStr%EventTimeSum + WRITE ( p%US, '(A,F8.3," (m/s)^2")') 'Maximum predicted event CTKE = ', y_CohStr%CTKE +IF ( y_CohStr%EventTimeStep > 0.0_ReKi ) THEN + WRITE ( p%US, '(A,F8.3," Hz")' ) 'Nyquist frequency of coherent events = ', 0.5_ReKi / y_CohStr%EventTimeStep +ENDIF + + + !------------------------- + ! Deallocate the coherent event arrays. + !------------------------- + CALL Cleanup() + RETURN + +CONTAINS + SUBROUTINE Cleanup() + IF ( ALLOCATED( e_CohStr%EventID ) ) DEALLOCATE( e_CohStr%EventID ) + IF ( ALLOCATED( e_CohStr%EventTS ) ) DEALLOCATE( e_CohStr%EventTS ) + IF ( ALLOCATED( e_CohStr%EventLen ) ) DEALLOCATE( e_CohStr%EventLen ) + IF ( ALLOCATED( e_CohStr%pkCTKE ) ) DEALLOCATE( e_CohStr%pkCTKE ) + END SUBROUTINE Cleanup + +END SUBROUTINE CohStr_WriteCTS +!======================================================================= +FUNCTION pkCTKE_LLJ(p, OtherSt_RandNum, Ht, ZL, UStar) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(IN ):: p ! parameters + TYPE(RandNum_OtherStateType), INTENT(INOUT):: OtherSt_RandNum ! other states for random numbers (next seed, etc) + REAL(ReKi), INTENT(IN) :: Ht ! The height at the billow center + REAL(ReKi), INTENT(IN) :: ZL ! The height at the billow center + REAL(ReKi), INTENT(IN) :: Ustar ! The height at the billow center + + ! local variables + + REAL(ReKi) :: A ! A constant/offset term in the pkCTKE calculation + REAL(ReKi) :: A_uSt ! The scaling term for Ustar + REAL(ReKi) :: A_zL ! The scaling term for z/L + REAL(ReKi) :: pkCTKE_LLJ ! The max CTKE expected for LLJ coh structures + REAL(ReKi) :: rndCTKE ! The random residual + + REAL(ReKi), PARAMETER :: RndParms(5) = (/0.252510525, -0.67391279, 2.374794977, 1.920555797, -0.93417558/) ! parameters for the Pearson IV random residual + REAL(ReKi), PARAMETER :: z_Ary(4) = (/54., 67., 85., 116./) ! Aneomoeter heights + + INTEGER :: Zindx_mn (1) + + + + Zindx_mn = MINLOC( ABS(z_Ary-Ht) ) + + SELECT CASE ( Zindx_mn(1) ) + CASE ( 1 ) ! 54 m + A = -0.051 + A_zL = -0.0384 + A_uSt = 9.9710 + + CASE ( 2 ) ! 67 m + A = -0.054 + A_zL = -0.1330 + A_uSt = 10.2460 + + CASE ( 3 ) ! 85 m + A = -0.062 + A_zL = -0.1320 + A_uSt = 10.1660 + + CASE ( 4 ) !116 m + A = -0.092 + A_zL = -0.3330 + A_uSt = 10.7640 + + !CASE DEFAULT !This should not occur + ! ErrStat = ErrID_Fatal + ! ErrMsg = 'Error in pkCTKE_LLJ():: Height index is invalid.' + END SELECT + + CALL RndPearsonIV( p%RNG, OtherSt_RandNum, rndCTKE, RndParms, (/ -10.0_ReKi, 17.5_ReKi /) ) + + pkCTKE_LLJ = MAX(0.0_ReKi, A + A_uSt*UStar + A_zL*ZL + rndCTKE) + +END FUNCTION pkCTKE_LLJ +!======================================================================= +SUBROUTINE CohStr_WriteEvents( RootName, p_CohStr, e_CohStr, y_CohStr, TScale, UHub, ErrStat, ErrMsg ) + + ! This subroutine writes the events as calculated in CalcEvents. + + IMPLICIT NONE + + ! Passed Variables + TYPE(CohStr_ParameterType) , INTENT(IN ) :: p_CohStr ! parameters for coherent structures + TYPE(CohStr_EventType) , INTENT(IN ) :: e_CohStr ! parameters for coherent structure events + TYPE(CohStr_OutputType), INTENT(INOUT) :: y_CohStr + + REAL(ReKi), INTENT(IN) :: TScale ! Time scaling factor + REAL(ReKi), INTENT(IN) :: UHub ! Mean wind speed at hub height (advection speed) + CHARACTER(*), INTENT(IN) :: RootName + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + ! Local Variables + + REAL(ReKi) :: CurrentTime = 0.0 ! the current time (in seconds) + REAL(ReKi) :: CTTime ! Time from beginning of event file + REAL(ReKi) :: deltaTime = 0.0 ! difference between two time steps in the event files + + INTEGER :: FileNum ! File Number in the event file + INTEGER :: IE ! Loop counter for event number + INTEGER :: IT ! Loop counter for time step + + INTEGER(IntKi) :: UnIn ! I/O Unit for input file + INTEGER(IntKi) :: UnOut ! I/O Unit for output file + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + + + CHARACTER(200) :: InpFile ! Name of the input file + TYPE (Event), POINTER :: PtrCurr => NULL() ! Pointer to the current event + TYPE (Event), POINTER :: PtrPrev => NULL() ! Pointer to the previous event (for deallocation purposes) + + + ErrStat = ErrID_None + ErrMsg = "" + + UnOut = -1 + CALL GetNewUnit( UnOut, ErrStat2, ErrMsg2 ) + CALL OpenFOutFile ( UnOut, TRIM( RootName )//'.cts', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteEvents' ) + + UnIn = -1 + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + + + ! Write event data to the time step output file (opened at the beginnig) + + WRITE (UnOut, "( A14, ' = FileType')") p_CohStr%CTExt + WRITE (UnOut, "( G14.7, ' = ScaleVel')") y_CohStr%ScaleVel + WRITE (UnOut, "( G14.7, ' = MHHWindSpeed')") UHub + WRITE (UnOut, "( G14.7, ' = Ymax')") y_CohStr%ScaleWid*e_CohStr%Ym_max/e_CohStr%Zm_max + WRITE (UnOut, "( G14.7, ' = Zmax')") y_CohStr%ScaleWid + WRITE (UnOut, "( G14.7, ' = DistScl')") p_CohStr%DistScl + WRITE (UnOut, "( G14.7, ' = CTLy')") p_CohStr%CTLy + WRITE (UnOut, "( G14.7, ' = CTLz')") p_CohStr%CTLz + WRITE (UnOut, "( G14.7, ' = NumCTt')") y_CohStr%NumCTt + + + PtrCurr => y_CohStr%PtrHead + + + DO IE = 1,y_CohStr%NumCTEvents + + IF ( .NOT. ASSOCIATED ( PtrCurr ) ) EXIT ! This shouldn't be necessary, given the way we created the list + + + IF ( .NOT. PtrCurr%Connect2Prev ) THEN + + IF ( CurrentTime < PtrCurr%TStart ) THEN + + WRITE ( UnOut, '(G14.7,1x,I5.5)') CurrentTime, 0 ! Print end of previous event + + y_CohStr%NumCTt = y_CohStr%NumCTt - 1 ! Let's make sure the right number of points have been written to the file. + + IF ( CurrentTime < PtrCurr%TStart - PtrCurr%delt ) THEN !This assumes a ramp of 1 delta t for each structure.... + + WRITE ( UnOut, '(G14.7,1x,I5.5)') MAX(PtrCurr%TStart - PtrCurr%delt, REAL(0.0, ReKi) ), 0 + y_CohStr%NumCTt = y_CohStr%NumCTt - 1 + + ENDIF + + ENDIF + + ENDIF ! NOT Connect2Prev + + + WRITE ( InpFile, '(I5.5)' ) e_CohStr%EventID( PtrCurr%EventNum ) + InpFile = TRIM( p_CohStr%CTEventPath )//PathSep//'Event'//TRIM( InpFile)//'.dat' + + CALL OpenFInpFile( UnIn, InpFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CohStr_WriteEvents' ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + + DO IT = 1,e_CohStr%EventTS( PtrCurr%EventNum ) + + READ ( UnIn, *, IOSTAT=ErrStat2 ) FileNum, CTTime, deltaTime + + IF (ErrStat2 /= 0) THEN + CALL SetErrStat( ErrID_Fatal, 'Error reading event file'//TRIM( InpFile ), ErrStat, ErrMsg, 'CohStr_WriteEvents') + CALL Cleanup() + RETURN + ENDIF + + CurrentTime = PtrCurr%TStart + CTTime*TScale + + WRITE ( UnOut, '(G14.7,1x,I5.5)') CurrentTime, FileNum + y_CohStr%NumCTt = y_CohStr%NumCTt - 1 + + ENDDO ! IT: Event timestep + + + CLOSE ( UnIn ) + + + ! Add one (delta time) space between events + + CurrentTime = CurrentTime + deltaTime*TScale + + PtrPrev => PtrCurr + PtrCurr => PtrCurr%Next + + DEALLOCATE ( PtrPrev, STAT=ErrStat2 ) + + ENDDO !IE: number of events + + WRITE ( UnOut, '(G14.7,1x,I5.5)') CurrentTime, 0 !Add the last line + y_CohStr%NumCTt = y_CohStr%NumCTt - 1 + + ! Let's append zero lines at the end of the file if we haven't output NumCTt lines, yet. + ! We've subtracted from NumCTt every time we wrote a line so now the number in NumCTt is + ! how many lines short we are. + + IF ( deltaTime > 0 ) THEN + deltaTime = deltaTime*TScale + ELSE + deltaTime = 0.5 + ENDIF + + DO IE = 1, y_CohStr%NumCTt ! Write zeros at the end if we happened to insert an event that overwrote one of our zero lines + CurrentTime = CurrentTime + deltaTime + WRITE ( UnOut, '(G14.7,1x,I5.5)') CurrentTime, 0 + ENDDO + + CLOSE ( UnOut ) + +CONTAINS +!............................ +SUBROUTINE Cleanup() + + IF (UnIn > 0) CLOSE( UnIn ) + IF (UnOut > 0) CLOSE( UnOut ) + +END SUBROUTINE Cleanup +!............................ +END SUBROUTINE CohStr_WriteEvents +!======================================================================= +END MODULE TS_CohStructures diff --git a/OpenFAST/modules/turbsim/src/Profiles.f90 b/OpenFAST/modules/turbsim/src/Profiles.f90 new file mode 100644 index 000000000..7135b9285 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/Profiles.f90 @@ -0,0 +1,1411 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TS_Profiles + + USE NWTC_Library + USE TurbSim_Types + + IMPLICIT NONE + + +CONTAINS + +!======================================================================= +SUBROUTINE ChebyshevVals(coeffs,x,y,MinX,MaxX, ErrStat, ErrMsg) + + IMPLICIT NONE + + ! Passed variables + + REAL(ReKi), DIMENSION(:), INTENT(IN ) :: coeffs ! Coefficients defined on [-1,1] + REAL(ReKi), DIMENSION(:), INTENT(IN ) :: x ! The x values where f(x)=y is desired + REAL(ReKi), DIMENSION(:), INTENT( OUT) :: y ! The desired function values + REAL(SiKi), INTENT(IN ) :: MinX ! Min X of the interval the coeffs were originally calculated for + REAL(SiKi), INTENT(IN ) :: MaxX ! Max X of the interval the coeffs were originally calculated for + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Message describing error + + + + INTEGER :: i,j + INTEGER :: SC + INTEGER :: SX + INTEGER :: SY + + REAL(DbKi), DIMENSION(size(x)) :: x_hat + REAL(DbKi), DIMENSION(size(coeffs)) :: BasisFn ! The Chebyshev basis functions evaluated at x_hat + + SC = size(coeffs) + SX = size(x) + SY = size(y) + + IF (SX /= SY) THEN + ErrStat = ErrID_Warn + ErrMsg = 'ChebyshevVals:The x and y vectors must be the same size.' + SX = MIN(SX,SY) + SY = SX + ELSE + ErrStat = ErrID_None + ErrMsg = "" + ENDIF + + x_hat = (2.0*REAL(x(:),DbKi) - MaxX - MinX)/(MaxX - MinX) ! Transform from [MinX,MaxX] to [-1,1] + + + DO i=1,SX + CALL ChebyshevFuncs( x_hat(i), BasisFn ) + + y(i) = 0. + DO j=1,SC + y(i) = y(i) + coeffs(j)*REAL(BasisFn(j),ReKi) + ENDDO + + ENDDO + + RETURN + CONTAINS + !----------------------------------------------------------------------- + SUBROUTINE ChebyshevFuncs( x, Px ) + + REAL(DbKi), INTENT(IN) :: x + REAL(DbKi), INTENT(OUT), DIMENSION(:) :: Px ! The basis functions evaluated at x + + INTEGER :: I + INTEGER :: S_Px ! Size of Px, determines how many basis functions to use (i.e. order of the polynomial - 1) + + + S_Px = SIZE(Px) + + !---------------------------- + ! Define the basis functions: + !---------------------------- + Px(1) = 1 + + IF (S_Px > 1) THEN + + Px(2) = x + + ! Define Chebyshev polynomials recursively + + DO I=3,S_Px + Px(I) = 2.*x*Px(I-1) - Px(I-2) + ENDDO + + ENDIF !S_Px > 1 + + END SUBROUTINE ChebyshevFuncs +END SUBROUTINE ChebyshevVals +!======================================================================= +!> This subroutine determines what Chebyshev Coefficients will be used +!! for the jet wind speed and wind direction profiles +SUBROUTINE GetChebCoefs(p, UJetMax_IsKnown, ErrStat, ErrMsg) + + ! sets p%met%ChebyCoef_WS, p%met%ChebyCoef_WD, and + ! if .NOT. UJetMax_IsKnown, also sets p%met%UJetMax + + ! valid only for jet WindProfileType + +IMPLICIT NONE + + TYPE(TurbSim_ParameterType),INTENT(INOUT) :: p ! TurbSim parameters + LOGICAL, INTENT(IN) :: UJetMax_IsKnown + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + + REAL(ReKi) :: UH_coef(4,11) ! The coefficients that Neil developed for calculating the Chebyshev coefficients + REAL(ReKi) :: WD_coef(4,11) ! The coefficients that Neil developed for calculating the Chebyshev coefficients + REAL(ReKi) :: ChebyCoef_tmp(11) + REAL(ReKi) :: UTmp1 ! + REAL(ReKi) :: UTmp2 ! + + INTEGER :: I ! A loop counter + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Let's calculate the wind speed at the jet height + + CALL get_coefs(p%met%ZJetMax, UH_coef, WD_coef) + + + IF ( UJetMax_IsKnown ) THEN + + DO I=1,11 + p%met%ChebyCoef_WS(I) = p%met%UJetMax*UH_coef(1,I) + p%met%Rich_No*UH_coef(2,I) & + + p%met%Ustar *UH_coef(3,I) + UH_coef(4,I) + ENDDO + + ELSE + + ! Calculate the coefficients without UJetMax + + DO I=1,11 + p%met%ChebyCoef_WS(I) = p%met%Rich_No*UH_coef(2,I) + p%met%Ustar*UH_coef(3,I) + UH_coef(4,I) ! +UJetMax*UH_coef(1,I) + ENDDO + + CALL getVelocity(p, p%met%URef, p%met%RefHt, p%met%RefHt, Utmp1, ErrStat, ErrMsg) ! reference p%met%URef, p%met%RefHt are unused; return velocity at RefHt with the WS coeffs missing the UJetMax term + IF (ErrStat >= AbortErrLev) RETURN + + ! Now calculate the coefficients with just UJetMax term + + ChebyCoef_tmp(:) = p%met%ChebyCoef_WS(:) + p%met%ChebyCoef_WS(:) = UH_coef(1,:) + + CALL getVelocity(p, p%met%URef, p%met%RefHt, p%met%RefHt, Utmp2, ErrStat, ErrMsg) ! reference p%met%URef, p%met%RefHt are unused + IF (ErrStat >= AbortErrLev) RETURN + + ! this gives us UJetMax: + p%met%UJetMax = (p%met%URef - Utmp1)/Utmp2 + + ! Get the final coefficients, using the computed UJetMax + p%met%ChebyCoef_WS(:) = p%met%UJetMax*p%met%ChebyCoef_WS(:) + ChebyCoef_tmp(:) + + ENDIF + + DO I=1,11 + p%met%ChebyCoef_WD(I) = p%met%UJetMax*WD_coef(1,I) + p%met%Rich_No*WD_coef(2,I) & + + p%met%Ustar*WD_coef(3,I) + WD_coef(4,I) + ENDDO + + +RETURN +END SUBROUTINE GetChebCoefs +!======================================================================= +!> This subroutine sets the array VelocityProfile, which contains the velocies +!! at each height specified by the input array Ht. +SUBROUTINE getVelocityProfile(p, U_Ref, z_Ref, Ht, VelocityProfile, ErrStat, ErrMsg ) + + + ! Determine the wind speed at a given height, with reference wind speed. + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType),INTENT(IN) :: p !< TurbSim parameters + REAL(ReKi), INTENT(IN) :: U_Ref !< Velocity at reference height + REAL(ReKi), INTENT(IN) :: z_Ref !< Reference height + REAL(ReKi), INTENT(IN) :: Ht(:) !< Heights (array) in meters where wind/water velocity should be calculated + REAL(ReKi), INTENT( OUT) :: VelocityProfile(:) !< Calculated velocity (wind/water speed) at Ht + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + + REAL(SiKi), PARAMETER :: MinZ = 3. ! lower bound (height) for Cheby polynomial + REAL(SiKi), PARAMETER :: MaxZ = 500. ! upper bound (height) for Cheby polynomial + + + INTEGER :: I + INTEGER :: Indx + INTEGER :: J + +! REAL :: C_factor +! REAL(ReKi) :: ZRef + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( p%IEC%IEC_WindType == IEC_EWM50 ) THEN + VelocityProfile(:) = p%IEC%VRef*( Ht(:)/p%grid%HubHt )**p%met%PLExp ! [IEC 61400-1 6.3.2.1 (14)] + RETURN + ELSEIF ( p%IEC%IEC_WindType == IEC_EWM1 ) THEN + VelocityProfile(:) = 0.8*p%IEC%VRef*( Ht(:)/p%grid%HubHt )**p%met%PLExp ! [IEC 61400-1 6.3.2.1 (14), (15)] + RETURN + ELSEIF ( p%IEC%IEC_WindType == IEC_EWM100 ) THEN + VelocityProfile(:) = p%IEC%VRef*( Ht(:)/p%grid%HubHt )**p%met%PLExp ! [API-IEC RECCOMENDATAION] ADDED BY YGUO !bjj: this is the same as IEC_EWM50, but we should check that IEC_EWM100 is used in ALL the same places IEC_EWM50 is + RETURN + ENDIF + + + SELECT CASE ( TRIM(p%met%WindProfileType) ) + + CASE ( 'JET' ) + + CALL ChebyshevVals( p%met%ChebyCoef_WS, Ht, VelocityProfile, MinZ, MaxZ, ErrStat, ErrMsg ) ! We originally calculated the coeffs for 3-500 m in height + + CASE ( 'LOG' ) + + DO J = 1,SIZE(Ht) + VelocityProfile(J) = getLogWindSpeed( Ht(J), z_Ref, U_Ref, p%met%ZL, p%met%Z0) + END DO + + + + CASE ( 'H2L' ) + + ! Calculate the windspeed. + ! z_Ref and U_Ref both get modified consistently, therefore z_Ref is used instead of RefHt. + VelocityProfile(:) = LOG( Ht(:)/z_Ref) * p%met%Ustar / 0.41_ReKi + U_Ref + + CASE ( 'PL' ) + +! IF ( z_Ref > 0.0 .AND. Ht > 0.0 ) THEN + VelocityProfile(:) = U_Ref*( Ht(:)/z_Ref )**p%met%PLExp + +! ENDIF + + CASE ( 'TS' ) + + DO J = 1,SIZE(Ht) + VelocityProfile(J) = getTimeSeriesWindSpeed(p, Ht(J) ) + END DO + + + CASE ( 'API' ) + + ! sample to write to screen.CALL WrScr ( ' A default value will be used for '//TRIM(VarName)//'.' ) +! CALL WrScr ('calling to API wind profile and write array') + ! TO ADD THE FSOLVE PROGRAM TO CALCULATE C_factor +! VelocityProfile(:) = ZRef*(1+LOG( Ht(:) / 10) )*( 1-0.41*(0.06*(1+0.043*ZRef)*(Ht/10)**(-0.22)))*LOG(600.0/3600.0) +! VelocityProfile(:) = z_Ref*(1+LOG( Ht(:) / 10) )*( 1-0.41*(0.06*(1+0.043*z_Ref)*(Ht/10)**(-0.22)))*LOG(600.0/3600.0) +! VelocityProfile(:) = U_Ref*(1+LOG( Ht(:) / z_Ref) )*( 1-0.41*(0.06*(1+0.043*U_Ref)*(Ht/z_Ref)**(-0.22)))*LOG(600.0/3600.0) +! VelocityProfile(:) = U_Ref*(1+LOG( Ht(:) / z_Ref) ) +! VelocityProfile(:) = U_Ref*( 1.0 + 0.0573*SQRT( 1.0 + 0.15*p%met%URef )*LOG( Ht(:)/z_Ref) ) + VelocityProfile(:) = p%met%URef*( 1.0 + 0.0573*SQRT( 1.0 + 0.15*p%met%URef )*LOG( Ht(:)/p%met%RefHt) ) + CASE ( 'USR' ) + + DO J = 1,SIZE(Ht) + IF ( Ht(J) <= p%met%USR_Z(1) ) THEN + VelocityProfile(J) = p%met%USR_U(1) + ELSEIF ( Ht(J) >= p%met%USR_Z(p%met%NumUSRz) ) THEN + VelocityProfile(J) = p%met%USR_U(p%met%NumUSRz) + ELSE + ! Find the two points between which the height lies + + DO I=2,p%met%NumUSRz + IF ( Ht(J) <= p%met%USR_Z(I) ) THEN + Indx = I-1 + + ! Let's just do a linear interpolation for now + VelocityProfile(J) = (Ht(J) - p%met%USR_Z(Indx)) * ( p%met%USR_U(Indx) - p%met%USR_U(I) ) / ( p%met%USR_Z(Indx) - p%met%USR_Z(I) ) & + + p%met%USR_U(Indx) + EXIT + ENDIF + ENDDO + + ENDIF + + ENDDO + + CASE DEFAULT ! This is how it worked before + + DO I=1,SIZE(VelocityProfile) + IF ( Ht(I) == z_Ref ) THEN + VelocityProfile(I) = U_Ref + ELSEIF ( ABS( Ht(I)-z_Ref ) <= 0.5*p%grid%RotorDiameter ) THEN + VelocityProfile(I) = U_Ref*( Ht(I)/z_Ref )**p%met%PLExp + ELSEIF ( Ht(I) > 0.0 .AND. z_Ref > 0.0 .AND. .NOT. EqualRealNos(z_Ref, p%met%Z0) ) THEN !Check that we don't have an invalid domain + VelocityProfile(I) = U_Ref*LOG( Ht(I)/p%met%Z0 )/LOG( z_Ref/p%met%Z0 ) + ELSE + VelocityProfile(I) = 0.0 + ENDIF + ENDDO + + END SELECT + +RETURN +END SUBROUTINE getVelocityProfile +!======================================================================= +!> This subroutine sets the direction in degrees at each height in meters +!! specified by the input array Ht. +SUBROUTINE getDirectionProfile( p, Ht, DirectionProfile, VAngleProfile, ErrStat, ErrMsg ) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType),INTENT(IN) :: P !< TurbSim parameters + REAL(ReKi), INTENT(IN) :: Ht(:) !< Array of heights (meters) where wind speed should be calculated + REAL(ReKi) , intent( out) :: DirectionProfile(:) !< Wind direction at Ht + REAL(ReKi) , intent( out) :: VAngleProfile(:) !< Vertical Wind angle at Ht + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + REAL(SiKi), PARAMETER :: MinZ = 3. ! lower bound (height) for Cheby polynomial + REAL(SiKi), PARAMETER :: MaxZ = 500. ! upper bound (height) for Cheby polynomial + + + REAL(ReKi) :: tmpHt(2) + REAL(ReKi) :: tmpWD(2) + REAL(ReKi) :: diff + + INTEGER :: IZ, IZm1 + INTEGER :: J + + + ErrStat = ErrID_None + ErrMsg = "" + + SELECT CASE ( TRIM(p%met%WindProfileType) ) + + CASE ( 'JET' ) + + ! Calculate the wind direction at this height + CALL ChebyshevVals( p%met%ChebyCoef_WD, Ht(:), DirectionProfile(:), MinZ, MaxZ, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Compute the wind direction at hub height & the jet height + tmpHt(1) = p%grid%HubHt + tmpHt(2) = p%met%ZJetMax + CALL ChebyshevVals( p%met%ChebyCoef_WD, tmpHt, tmpWD(1:2), MinZ, MaxZ, ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + ! Make sure none of the directions are more than 45 degrees from the direction at the jet height + IF ( ABS(tmpWD(1) - tmpWD(2) ) > 45. ) THEN ! The direction at the hub height + tmpWD(1) = tmpWD(2) + SIGN(REAL(45.,ReKi), tmpWD(1) - tmpWD(2)) + ENDIF + + DO J = 1,SIZE(DirectionProfile) ! The directions at all the heights + IF ( ABS(DirectionProfile(J) - tmpWD(2) ) > 45. ) THEN + DirectionProfile(J) = tmpWD(2) + SIGN(REAL(45.,ReKi), DirectionProfile(J) - tmpWD(2)) + ENDIF + + ! Remove the hub height direction so that we have a relative direction, then + ! add the mean flow angle. (Note that the Chebyshev profile is cw looking upwind, + ! but the horizontal angle is ccw looking upwind) + + DirectionProfile(J) = p%met%HFlowAng - (DirectionProfile(J) - tmpWD(1)) ! This is the counter-clockwise angle of the wind + ENDDO + VAngleProfile = p%met%VFlowAng + + CASE ( 'USR' ) + + DO J = 1,SIZE(Ht) + + ! Calculate the wind direction at this height + + IF ( Ht(J) <= p%met%USR_Z(1) ) THEN + DirectionProfile(J) = p%met%USR_WindDir(1) + ELSEIF ( Ht(J) >= p%met%USR_Z(p%met%NumUSRz) ) THEN + DirectionProfile(J) = p%met%USR_WindDir(p%met%NumUSRz) + ELSE + + + ! Find the two points between which the height lies + + DO IZ=2,p%met%NumUSRz + IF ( Ht(J) <= p%met%USR_Z(IZ) ) THEN + IZm1 = IZ-1 + + ! Let's just do a linear interpolation for now + !we need to check if the angle goes through 360, before we do the interpolation + diff = p%met%USR_WindDir(IZm1) - p%met%USR_WindDir(IZ) + IF ( diff > 180. ) THEN + tmpWD(1) = p%met%USR_WindDir(IZm1) + tmpWD(2) = p%met%USR_WindDir(IZ ) + 360. + ELSEIF ( diff < -180. ) THEN + tmpWD(1) = p%met%USR_WindDir(IZm1) + 360. + tmpWD(2) = p%met%USR_WindDir(IZ ) + ELSE + tmpWD(1) = p%met%USR_WindDir(IZm1) + tmpWD(2) = p%met%USR_WindDir(IZ ) + ENDIF + + DirectionProfile(J) = (Ht(J) - p%met%USR_Z(IZm1)) * ( tmpWD(1) - tmpWD(2) ) / ( p%met%USR_Z(IZm1) - p%met%USR_Z(IZ) ) + tmpWD(1) + + EXIT + ENDIF + ENDDO + + + ENDIF + + ENDDO + +!bjj: TODO: See if we can get this to have direction of HFlowAng at hub height. + DirectionProfile = p%met%HFlowAng + DirectionProfile ! This is the counter-clockwise angle of the wind + VAngleProfile = p%met%VFlowAng + + CASE ('TS') + + DO J = 1,SIZE(Ht) + + ! Calculate the wind direction at this height + + IF ( Ht(J) <= p%usr%pointzi(1) ) THEN + DirectionProfile(J) = p%usr%meanDir(1) + VAngleProfile(J) = p%usr%meanVAng(1) + ELSEIF ( Ht(J) >= p%usr%pointzi(p%usr%NPoints) ) THEN + DirectionProfile(J) = p%usr%meanDir(p%usr%NPoints) + VAngleProfile(J) = p%usr%meanVAng(p%usr%NPoints) + ELSE + ! Find the two points between which the height lies + + DO IZ=2,p%usr%NPoints + IF ( Ht(J) <= p%usr%pointzi(IZ) ) THEN + IZm1 = IZ-1 + + ! Let's just do a linear interpolation for now + !we need to check if the angle goes through 360, before we do the interpolation + diff = p%usr%meanDir(IZm1) - p%usr%meanDir(IZ) + IF ( diff > 180. ) THEN + tmpWD(1) = p%usr%meanDir(IZm1) + tmpWD(2) = p%usr%meanDir(IZ ) + 360. + ELSEIF ( diff < -180. ) THEN + tmpWD(1) = p%usr%meanDir(IZm1) + 360. + tmpWD(2) = p%usr%meanDir(IZ ) + ELSE + tmpWD(1) = p%usr%meanDir(IZm1) + tmpWD(2) = p%usr%meanDir(IZ ) + ENDIF + + DirectionProfile(J) = (Ht(J) - p%usr%pointzi(IZm1)) * ( tmpWD(1) - tmpWD(2) ) / ( p%usr%pointzi(IZm1) - p%usr%pointzi(IZ) ) + tmpWD(1) + + + ! Let's just do a linear interpolation for now + !we need to check if the angle goes through 360, before we do the interpolation + diff = p%usr%meanVAng(IZm1) - p%usr%meanVAng(IZ) + IF ( diff > 180. ) THEN + tmpWD(1) = p%usr%meanVAng(IZm1) + tmpWD(2) = p%usr%meanVAng(IZ ) + 360. + ELSEIF ( diff < -180. ) THEN + tmpWD(1) = p%usr%meanVAng(IZm1) + 360. + tmpWD(2) = p%usr%meanVAng(IZ ) + ELSE + tmpWD(1) = p%usr%meanVAng(IZm1) + tmpWD(2) = p%usr%meanVAng(IZ ) + ENDIF + + VAngleProfile(J) = (Ht(J) - p%usr%pointzi(IZm1)) * ( tmpWD(1) - tmpWD(2) ) / ( p%usr%pointzi(IZm1) - p%usr%pointzi(IZ) ) + tmpWD(1) + + EXIT + ENDIF + ENDDO + + ENDIF + + END DO + + DirectionProfile = p%met%HFlowAng + DirectionProfile ! This is the counter-clockwise angle of the wind + VAngleProfile = p%met%VFlowAng + VAngleProfile + + CASE DEFAULT + + DirectionProfile = p%met%HFlowAng + VAngleProfile = p%met%VFlowAng + + END SELECT + +RETURN +END SUBROUTINE getDirectionProfile +!======================================================================= +!> This subroutine sets the scalar Velocity, which contains the velocity in m/s +!! at the height in mebers specified by the input value Ht. +SUBROUTINE getVelocity(p, U_Ref, z_Ref, Ht, Velocity, ErrStat, ErrMsg ) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(IN) :: P + REAL(ReKi), INTENT(IN) :: U_Ref ! Wind speed at reference height + REAL(ReKi), INTENT(IN) :: z_Ref ! Reference height + REAL(ReKi), INTENT(IN) :: Ht ! Height where wind speed should be calculated + REAL(ReKi) , intent( out) :: Velocity ! This function, approximate wind/water speed at Ht + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + REAL(SiKi), PARAMETER :: MinZ = 3. ! lower bound (height) for Cheby polynomial + REAL(SiKi), PARAMETER :: MaxZ = 500. ! upper bound (height) for Cheby polynomial + + +! REAL(ReKi) :: psiM ! The diabatic term for the log wind profile + REAL(ReKi) :: tmpHt(2) + REAL(ReKi) :: tmpWS(2) + + INTEGER :: I + INTEGER :: Indx + + !REAL(ReKi) :: U0_1HR ! Wind speed at reference height in 1hr time duration, added by Y.G. ON April 16 2013 +! REAL :: C_factor ! Factor to convert wind speed from 10-min to 1 hr, added by Y.G. ON April 16 2013 + REAL :: X0 ! Added by Y. Guo for calculating C_factor + !REAL :: X, TEMP_1, TEMP_2 ! Added by Y. Guo for calculating C_factor + !======================================= + + ErrStat = ErrID_None + ErrMsg = "" + + X0=U_Ref + !======================== + ! IF p%met%Z0 <= 0.0 CALL ProgAbort('The surface roughness must be a positive number') + + IF ( p%IEC%IEC_WindType == IEC_EWM50 ) THEN + Velocity = p%IEC%VRef*( Ht/p%grid%HubHt )**p%met%PLExp ! [IEC 61400-1 6.3.2.1 (14)] + RETURN + ELSEIF ( p%IEC%IEC_WindType == IEC_EWM1 ) THEN + Velocity = 0.8*p%IEC%VRef*( Ht/p%grid%HubHt )**p%met%PLExp ! [IEC 61400-1 6.3.2.1 (14), (15)] + RETURN + ELSEIF ( p%IEC%IEC_WindType == IEC_EWM100 ) THEN + Velocity = p%IEC%VRef*( Ht/p%grid%HubHt )**p%met%PLExp ! [API-IEC RECCOMENDATAION] ADDED BY YGUO !bjj: this is the same as IEC_EWM50, but we should check that IEC_EWM100 is used in ALL the same places IEC_EWM50 is + RETURN + ENDIF + + + SELECT CASE ( TRIM(p%met%WindProfileType) ) + + CASE ( 'JET' ) + + tmpHt(1) = Ht + CALL ChebyshevVals( p%met%ChebyCoef_WS, tmpHt(1:1), tmpWS(1:1), MinZ, MaxZ, ErrStat, ErrMsg ) ! We originally calculated the coeffs for 3-500 m in height + Velocity = tmpWS(1) + + CASE ( 'LOG' ) !Panofsky, H.A.; Dutton, J.A. (1984). Atmospheric Turbulence: Models and Methods for Engineering Applications. New York: Wiley-Interscience; 397 pp. + + Velocity = getLogWindSpeed(Ht, z_Ref, U_Ref, p%met%ZL, p%met%Z0) + + CASE ( 'H2L' ) + ! Calculate the windspeed. + ! z_Ref and U_Ref both get modified consistently, therefore z_Ref is used instead of RefHt. + Velocity = LOG( Ht/z_Ref ) * p%met%Ustar / 0.41_ReKi + U_Ref + + + CASE ( 'PL' ) ! POWER LAW, commented by Y. Guo on April 16 2013 + + IF ( z_Ref > 0.0 .AND. Ht > 0.0 ) THEN + Velocity = U_Ref*( Ht/z_Ref )**p%met%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + ELSE + Velocity = 0.0 + ENDIF + + CASE ( 'USR' ) + + IF ( Ht <= p%met%USR_Z(1) ) THEN + Velocity = p%met%USR_U(1) + ELSEIF ( Ht >= p%met%USR_Z(p%met%NumUSRz) ) THEN + Velocity = p%met%USR_U(p%met%NumUSRz) + ELSE + ! Find the two points between which the height lies + + DO I=2,p%met%NumUSRz + IF ( Ht <= p%met%USR_Z(I) ) THEN + Indx = I-1 + + ! Let's just do a linear interpolation for now + Velocity = (Ht - p%met%USR_Z(Indx)) * ( p%met%USR_U(Indx) - p%met%USR_U(I) ) / ( p%met%USR_Z(Indx) - p%met%USR_Z(I) ) + p%met%USR_U(Indx) + EXIT + ENDIF + ENDDO + + ENDIF + + CASE ( 'TS' ) + + Velocity = getTimeSeriesWindSpeed(p, Ht) + + + CASE ( 'API' ) + +!MLB: We can exclude this logic by forcing the user to enter the 1-hour mean wind speed. +! If we add the API stuff to the main version of TurbSim, we may want to eliminate that requirement, but we will have to +! add a new input parameter saying how long a period was used to calculate the reference wind speed. + +! CALL ROOT_SEARCHING(X0,X,U_Ref,z_Ref,p%grid%HubHt) !URef + !CALL Root_Searching(X0,X,42.5,10.0,10.0) !U_Ref, USED TO DEBUG THE CODE +! U0_1HR=X ! This is the wind speed at 10 m height within 1-hr window + +! CALL WrScr ('Calling to API wind profile') +! TEMP_1=0.0573*(1.0+0.15*U0_1HR)**0.5 +! TEMP_2=0.06*(1+0.043*U0_1HR)*(Ht/10.0)**(-0.22) +! Velocity = U0_1HR*(1.0+TEMP_1*LOG( Ht / 10.0) )*( 1.0-0.41*TEMP_2*LOG(600.0/3600.0)) +! Velocity = U0_1HR*( 1.0 + 0.0573*SQRT( 1.0 + 0.15*U0_1HR )*LOG( Ht/z_Ref) ) +!MLB: This assumes that the reference wind speed entered by the user is the 1-hour average wind speed at the input reference height. + Velocity = p%met%URef*( 1.0 + 0.0573*SQRT( 1.0 + 0.15*p%met%URef )*LOG( Ht/p%met%RefHt) ) + +! CALL WrScr ('API wind profile generated') + + CASE DEFAULT ! This is how it worked before + + IF ( Ht == z_Ref ) THEN + Velocity = U_Ref + ELSEIF ( ABS( Ht-z_Ref ) <= 0.5*p%grid%RotorDiameter ) THEN + Velocity = U_Ref*( Ht/z_Ref )**p%met%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + ELSEIF ( Ht > 0.0 .AND. z_Ref > 0.0 .AND. .NOT. EqualRealNos(z_Ref, p%met%Z0) ) THEN !Check that we don't have an invalid domain + Velocity = U_Ref*LOG( Ht/p%met%Z0 )/LOG( z_Ref/p%met%Z0 ) + ELSE + Velocity = 0.0 + ENDIF + + END SELECT + + +RETURN +END SUBROUTINE getVelocity + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the wind speed at Ht by linearly interpolating the mean wind speed at the points from the user-input +!! time series. +function getTimeSeriesWindSpeed(p, Ht) + + TYPE(TurbSim_ParameterType),INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(IN) :: Ht !< height at which wind speed is requested [m] + REAL(ReKi) :: getTimeSeriesWindSpeed !< the calculated wind speed at Ht + + INTEGER(IntKi) :: IZ, IZm1 + + + + IF ( Ht <= p%usr%pointzi(1) ) THEN + getTimeSeriesWindSpeed = p%usr%meanU(1,1) + ELSEIF ( Ht >= p%usr%pointzi(p%usr%NPoints) ) THEN + getTimeSeriesWindSpeed = p%usr%meanU(p%usr%NPoints,1) + ELSE + ! Find the two points between which the height lies + + DO IZ=2,p%usr%NPoints + IF ( Ht <= p%usr%pointzi(IZ) ) THEN + IZm1 = IZ-1 + + ! Let's just do a linear interpolation for now + getTimeSeriesWindSpeed = (Ht - p%usr%pointzi(IZm1)) * ( p%usr%meanU(IZm1,1) - p%usr%meanU(IZ,1) ) / ( p%usr%pointzi(IZm1) - p%usr%pointzi(IZ) ) + p%usr%meanU(IZm1,1) + EXIT + ENDIF + ENDDO + + ENDIF + +end function getTimeSeriesWindSpeed + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine calculates the wind speed at Ht assuming a logarithmic wind profile and inputs z_Ref, U_Ref, Z/L and Z0 +!! +!! U_{ref}*( LOG( Ht / Z0 ) - psiM )/( LOG( z_Ref / Z0 ) - psiM ) +!! where +!! psiM is a function of Z/L +!! In neutral conditions, psiM is 0 and we get the IEC log wind profile. +function getLogWindSpeed(Ht, z_Ref, U_Ref, ZL, Z0) + + REAL(ReKi), INTENT(IN) :: Ht !< height at which wind speed is requested [m] + REAL(ReKi), INTENT(IN) :: z_Ref !< height of the reference wind speed [m] + REAL(ReKi), INTENT(IN) :: U_Ref !< reference wind speed [m/s] + REAL(ReKi), INTENT(IN) :: ZL !< a measure of stability [-] + REAL(ReKi), INTENT(IN) :: Z0 !< surface roughness length [m] + + REAL(ReKi) :: getLogWindSpeed !< the calculated wind speed at Ht + + + ! local variables + REAL(ReKi) :: psiM ! The diabatic term for the log wind profile + REAL(ReKi) :: tmp ! A temporary variable for calculating psiM + + + + IF ( Ht > 0.0 .AND. z_Ref > 0.0 .AND. .NOT. EqualRealNos( z_Ref, Z0 ) ) THEN + + IF ( ZL >= 0 ) THEN !& ZL < 1 + psiM = -5.0*ZL + ELSE + tmp = (1.0 - 15.0*ZL)**0.25 + + !psiM = -2.0*LOG( (1.0 + tmp)/2.0 ) - LOG( (1.0 + tmp*tmp)/2.0 ) + 2.0*ATAN( tmp ) - 0.5 * PI + psiM = -LOG( 0.125 * ( (1.0 + tmp)**2 * (1.0 + tmp*tmp) ) ) + 2.0*ATAN( tmp ) - 0.5 * PI + + !bjj 11-may-2016: because of the negative sign in the equation below, I believe psiM needs to switch signs. + ! if true, this has been implemented incorrectly for at least 15 years. + psiM = -psiM + + ENDIF + +! IF ( p%met%Ustar > 0. ) THEN +! getLogWindSpeed = ( p%met%UstarDiab / 0.4 ) * ( LOG( Ht / Z0 ) - psiM ) +! ELSE + !In neutral conditions, psiM is 0 and we get the IEC log wind profile: + getLogWindSpeed = U_Ref*( LOG( Ht / Z0 ) - psiM )/( LOG( z_Ref / Z0 ) - psiM ) +! ENDIF + + ELSE + getLogWindSpeed = 0.0_ReKi + ENDIF + + +end function getLogWindSpeed +!======================================================================= +SUBROUTINE get_coefs(JetHt,UH_coef,WD_coef) + + ! This subroutine just returns the coefficients that Neil calculated + ! for getting the Chebyshev coefficients for jet wind profiles. + + ! The coefficients are + ! Row 1 = Jet maximum wind speed coefficient + ! Row 2 = Turbine layer Richardson number coefficient + ! Row 3 = uStar over the rotor diameter coefficient + ! Row 4 = constant coefficient + ! Columns 1:11 = coefficients for 0-10th Chebyshev Basis Functions + + + REAL(ReKi),INTENT(IN) :: JetHt ! The height of the jet + REAL(ReKi),INTENT(OUT) :: UH_coef(4,11) ! The coefficients for horizontal wind speed + REAL(ReKi),INTENT(OUT) :: WD_coef(4,11) ! The coefficients for (horizontal) wind direction + + INTEGER :: HtIndx + + HtIndx = INT(JetHt - 50) / INT(20) + HtIndx = MIN( MAX( HtIndx, 1 ), 21 ) + + ! The Horizontal Wind Speed coefficients + SELECT CASE ( HtIndx ) + CASE ( 1 ) ! 70-90 m + UH_coef(:, 1) = (/ 0.856851, 7.51E-02, 1.39276, 0.894127 /) + UH_coef(:, 2) = (/ -4.88E-02, 0.576344, 1.23582, 1.72687 /) + UH_coef(:, 3) = (/ 1.39E-02, 9.67E-02, 1.36737, -0.723851 /) + UH_coef(:, 4) = (/ 0.100585, 0.234968, -1.06287, -0.372353 /) + UH_coef(:, 5) = (/ -7.69E-02, -0.154071, -0.301483, 0.150179 /) + UH_coef(:, 6) = (/ 8.53E-03, 0.104602, -0.382453, 0.520224 /) + UH_coef(:, 7) = (/ -4.44E-03, -4.80E-02, 0.219135, -0.266775 /) + UH_coef(:, 8) = (/ 2.63E-02, -3.08E-02, -6.94E-02, -0.210521 /) + UH_coef(:, 9) = (/ -2.01E-02, -5.61E-02, 0.220825, 0.179622 /) + UH_coef(:,10) = (/ 8.11E-03, 3.96E-02, 0.109793, -3.81E-02 /) + UH_coef(:,11) = (/ 4.99E-03, 5.00E-02, -0.124887, -0.11035 /) + CASE ( 2 ) ! 90-110 m + UH_coef(:, 1) = (/ 0.741241, -0.122521, 0.875062, 1.43294 /) + UH_coef(:, 2) = (/ -0.264131, 0.28827, 0.717571, 3.30541 /) + UH_coef(:, 3) = (/ -5.92E-02, 3.86E-02, 1.09453, -0.377399 /) + UH_coef(:, 4) = (/ 0.13792, 0.175628, -0.57163, -0.539205 /) + UH_coef(:, 5) = (/ -2.59E-02, -0.211126, -4.25E-02, -0.338308 /) + UH_coef(:, 6) = (/ -1.02E-02, 0.153597, -0.197867, 0.570708 /) + UH_coef(:, 7) = (/ -3.22E-02, -8.17E-02, -9.63E-02, 0.19095 /) + UH_coef(:, 8) = (/ 2.72E-02, 3.09E-02, -0.249399, -0.273684 /) + UH_coef(:, 9) = (/ -1.60E-02, 8.88E-03, 0.132523, 9.58E-02 /) + UH_coef(:,10) = (/ -5.29E-03, 2.98E-02, 0.205812, 9.27E-02 /) + UH_coef(:,11) = (/ 7.00E-03, -1.47E-02, -2.11E-02, -0.123083 /) + CASE ( 3 ) ! 110-130 m + UH_coef(:, 1) = (/ 0.809492, -1.41752, -0.817619, 1.64159 /) + UH_coef(:, 2) = (/ -0.121866, -1.09012, -2.60044, 3.63875 /) + UH_coef(:, 3) = (/ -0.105142, -0.263657, -5.60E-02, 0.374811 /) + UH_coef(:, 4) = (/ 8.33E-02, 0.625103, 0.422112, -0.199598 /) + UH_coef(:, 5) = (/ -1.69E-02, -7.09E-02, 1.76933, -0.847721 /) + UH_coef(:, 6) = (/ 1.88E-02, 7.70E-02, -0.121062, 0.10533 /) + UH_coef(:, 7) = (/ -3.15E-02, 2.50E-02, -7.39E-02, 0.299197 /) + UH_coef(:, 8) = (/ 3.48E-03, 4.25E-02, -6.52E-02, -4.29E-03 /) + UH_coef(:, 9) = (/ -1.18E-02, -0.100754, 0.170602, 3.42E-02 /) + UH_coef(:,10) = (/ 2.09E-02, 3.36E-02, -0.104123, -8.49E-02 /) + UH_coef(:,11) = (/ -2.91E-03, -3.52E-02, -0.258115, 4.81E-02 /) + CASE ( 4 ) ! 130-150 m + UH_coef(:, 1) = (/ 0.694325, -0.463252, 2.11406, 1.28643 /) + UH_coef(:, 2) = (/ -0.269118, -1.31381, 2.13374, 3.46187 /) + UH_coef(:, 3) = (/ -8.40E-02, -5.97E-02, 2.09803, -0.592335 /) + UH_coef(:, 4) = (/ 0.135657, -0.117732, -0.11134, -0.28161 /) + UH_coef(:, 5) = (/ -1.29E-02, -0.239685, 0.151264, -0.412806 /) + UH_coef(:, 6) = (/ 3.54E-02, 0.513824, 0.673662, -0.519536 /) + UH_coef(:, 7) = (/ -1.55E-02, 7.49E-03, 0.393002, 2.07E-02 /) + UH_coef(:, 8) = (/ 2.37E-02, 0.225841, 3.84E-02, -0.202507 /) + UH_coef(:, 9) = (/ -3.26E-02, -0.239615, -0.133893, 0.29135 /) + UH_coef(:,10) = (/ 1.52E-02, 7.15E-02, 0.25228, -0.113016 /) + UH_coef(:,11) = (/ 7.19E-03, 9.79E-02, 0.252125, -0.173201 /) + CASE ( 5 ) ! 150-170 m + UH_coef(:, 1) = (/ 0.909534, 0.581254, -2.90539, -0.581377 /) + UH_coef(:, 2) = (/ 0.155834, -0.836954, -6.77075, 0.627044 /) + UH_coef(:, 3) = (/ -8.99E-02, -5.28E-02, -2.0719, 2.44E-02 /) + UH_coef(:, 4) = (/ 7.01E-02, -0.152904, -0.348237, 0.460754 /) + UH_coef(:, 5) = (/ -1.78E-02, -0.263166, 0.375798, -0.215738 /) + UH_coef(:, 6) = (/ 9.70E-03, 0.254932, 0.449286, -0.234 /) + UH_coef(:, 7) = (/ 7.46E-03, -0.304057, -0.122661, -7.14E-03 /) + UH_coef(:, 8) = (/ -6.26E-03, -0.142341, -1.95E-02, 0.299841 /) + UH_coef(:, 9) = (/ -2.59E-02, 0.174282, 0.193868, -5.81E-03 /) + UH_coef(:,10) = (/ 2.54E-03, -8.22E-02, 1.84E-02, 6.77E-02 /) + UH_coef(:,11) = (/ 5.77E-04, -5.43E-02, -7.69E-02, 2.96E-02 /) + CASE ( 6 ) ! 170-190 m + UH_coef(:, 1) = (/ 0.885753, -1.15015, 0.155218, -0.707043 /) + UH_coef(:, 2) = (/ -2.53E-02, -2.65126, 0.850151, 1.85279 /) + UH_coef(:, 3) = (/ -7.23E-02, -0.399161, 0.142486, -0.917176 /) + UH_coef(:, 4) = (/ 3.78E-02, 0.178924, 0.227745, 0.528861 /) + UH_coef(:, 5) = (/ -6.43E-03, 5.42E-02, 0.359052, -0.26111 /) + UH_coef(:, 6) = (/ 5.33E-02, 0.1546, -0.335116, -0.602604 /) + UH_coef(:, 7) = (/ -6.50E-03, -0.205907, -8.59E-02, 8.16E-02 /) + UH_coef(:, 8) = (/ 3.16E-02, 0.151199, -0.126411, -0.148609 /) + UH_coef(:, 9) = (/ -3.95E-02, 0.127418, 0.158511, 0.20932 /) + UH_coef(:,10) = (/ -2.53E-02, -5.32E-02, 0.36536, 0.214466 /) + UH_coef(:,11) = (/ 4.03E-03, 1.02E-02, -7.01E-03, -4.32E-02 /) + CASE ( 7 ) ! 190-210 m + UH_coef(:, 1) = (/ 0.735269, -1.48574, 0.983734, 0.887351 /) + UH_coef(:, 2) = (/ 0.233065, -0.850536, -1.17754, -0.880493 /) + UH_coef(:, 3) = (/ -0.172346, -0.862128, 1.20075, 3.48E-02 /) + UH_coef(:, 4) = (/ 8.04E-02, 5.24E-02, -0.916548, 0.247144 /) + UH_coef(:, 5) = (/ 2.88E-02, 0.112064, 1.51E-04, -0.466186 /) + UH_coef(:, 6) = (/ -2.75E-02, -9.01E-02, -0.321617, 0.379162 /) + UH_coef(:, 7) = (/ -1.08E-02, -0.161368, -2.51E-04, -1.33E-02 /) + UH_coef(:, 8) = (/ 5.09E-02, 0.228507, 0.195942, -0.45807 /) + UH_coef(:, 9) = (/ -1.98E-02, -7.23E-02, 6.66E-02, 0.133182 /) + UH_coef(:,10) = (/ -5.57E-03, -5.31E-02, 2.44E-02, 5.60E-02 /) + UH_coef(:,11) = (/ 3.71E-03, -1.63E-02, -5.44E-02, -1.40E-02 /) + CASE ( 8 ) ! 210-230 m + UH_coef(:, 1) = (/ 0.723721, -0.691359, -0.147971, 1.16041 /) + UH_coef(:, 2) = (/ 0.18799, 0.370199, 0.354538, -0.494962 /) + UH_coef(:, 3) = (/ -0.204727, -0.166723, 0.682431, 0.367566 /) + UH_coef(:, 4) = (/ 1.40E-02, 0.334677, 0.169944, 0.494211 /) + UH_coef(:, 5) = (/ 3.84E-02, 0.258361, 0.389453, -0.625709 /) + UH_coef(:, 6) = (/ -6.62E-03, -2.19E-02, -0.606278, 0.205521 /) + UH_coef(:, 7) = (/ -2.54E-02, -0.17744, 7.49E-02, 7.61E-02 /) + UH_coef(:, 8) = (/ 5.03E-02, 7.97E-02, -9.98E-02, -0.312218 /) + UH_coef(:, 9) = (/ -2.25E-02, 2.20E-02, 0.263227, 0.123311 /) + UH_coef(:,10) = (/ -1.43E-02, -2.01E-02, -5.14E-02, 0.159391 /) + UH_coef(:,11) = (/ 2.64E-03, 3.46E-02, -0.12318, -2.22E-02 /) + CASE ( 9 ) ! 230-250 m + UH_coef(:, 1) = (/ 0.717665, -0.294178, -0.521541, 0.876418 /) + UH_coef(:, 2) = (/ 0.183182, -0.52658, -1.34668, 0.414396 /) + UH_coef(:, 3) = (/ -0.196162, 9.84E-02, -3.83E-02, 0.156018 /) + UH_coef(:, 4) = (/ 2.92E-02, -0.362193, -0.658593, 0.521854 /) + UH_coef(:, 5) = (/ 3.37E-02, 0.108203, 0.318667, -0.375309 /) + UH_coef(:, 6) = (/ -8.24E-03, 0.128457, -0.149225, 0.1621 /) + UH_coef(:, 7) = (/ -3.06E-02, -0.210106, 4.55E-02, 8.42E-02 /) + UH_coef(:, 8) = (/ 3.02E-02, 0.184626, 9.46E-02, -0.215191 /) + UH_coef(:, 9) = (/ 7.03E-03, 2.49E-02, 3.13E-02, -9.70E-02 /) + UH_coef(:,10) = (/ -3.06E-03, -4.82E-02, -9.70E-02, 5.82E-02 /) + UH_coef(:,11) = (/ -9.57E-03, -3.93E-02, -0.125623, 0.112639 /) + CASE ( 10 ) ! 250-270 m + UH_coef(:, 1) = (/ 0.786229, -0.164848, 0.244948, -0.126263 /) + UH_coef(:, 2) = (/ 0.15218, -0.153233, -0.558524, 0.84425 /) + UH_coef(:, 3) = (/ -0.130716, -0.217411, 0.13439, -0.536893 /) + UH_coef(:, 4) = (/ 1.70E-03, 5.49E-02, 0.551012, 0.335778 /) + UH_coef(:, 5) = (/ 2.47E-02, 2.82E-02, 0.290918, -0.223416 /) + UH_coef(:, 6) = (/ 1.48E-02, 5.94E-02, -0.277959, 3.91E-02 /) + UH_coef(:, 7) = (/ -4.43E-02, 6.99E-03, 0.302386, 0.123719 /) + UH_coef(:, 8) = (/ 2.07E-02, 4.05E-02, -0.256155, -5.84E-02 /) + UH_coef(:, 9) = (/ 4.51E-03, -4.37E-02, -0.111911, -9.20E-03 /) + UH_coef(:,10) = (/ 4.05E-03, -6.90E-03, 0.14697, -7.03E-02 /) + UH_coef(:,11) = (/ -6.68E-03, 1.53E-02, -2.55E-02, 4.97E-02 /) + CASE ( 11 ) ! 270-290 m + UH_coef(:, 1) = (/ 0.715734, -0.772062, -0.556396, 1.02929 /) + UH_coef(:, 2) = (/ 0.322509, -0.465616, -0.671711, -1.2413 /) + UH_coef(:, 3) = (/ -0.166728, -0.281268, 0.924893, -0.282907 /) + UH_coef(:, 4) = (/ 1.27E-02, -0.342767, -1.10823, 0.516431 /) + UH_coef(:, 5) = (/ 3.80E-02, 5.35E-03, 0.833719, -0.510102 /) + UH_coef(:, 6) = (/ 1.97E-02, 0.279705, -0.179026, -4.36E-02 /) + UH_coef(:, 7) = (/ -4.74E-02, -0.227673, 9.00E-02, 0.341958 /) + UH_coef(:, 8) = (/ 8.99E-03, -1.92E-02, -0.433969, 5.90E-02 /) + UH_coef(:, 9) = (/ 4.34E-03, 8.12E-02, 0.25764, -0.148492 /) + UH_coef(:,10) = (/ 1.03E-02, 3.24E-02, 0.141971, -0.105207 /) + UH_coef(:,11) = (/ -4.84E-03, -1.99E-02, 7.33E-02, 2.84E-02 /) + CASE ( 12 ) ! 290-310 m + UH_coef(:, 1) = (/ 0.723348, -0.289581, -1.10618, 0.970713 /) + UH_coef(:, 2) = (/ 0.283383, 1.12986, -0.152861, -0.653269 /) + UH_coef(:, 3) = (/ -0.16513, 0.295047, 0.245326, -7.06E-02 /) + UH_coef(:, 4) = (/ 8.55E-03, 9.38E-02, -0.826824, 0.283436 /) + UH_coef(:, 5) = (/ 3.45E-02, 0.364581, 0.566317, -0.521081 /) + UH_coef(:, 6) = (/ 2.83E-02, 0.107252, -0.124867, -4.80E-02 /) + UH_coef(:, 7) = (/ -3.57E-02, -0.230151, -6.88E-02, 0.231208 /) + UH_coef(:, 8) = (/ 5.62E-04, 1.40E-02, -0.334942, 0.121313 /) + UH_coef(:, 9) = (/ -6.35E-03, -6.19E-02, 0.139396, 2.77E-02 /) + UH_coef(:,10) = (/ 1.14E-02, -2.67E-02, 0.24201, -0.127337 /) + UH_coef(:,11) = (/ 1.71E-04, -6.37E-04, 4.39E-02, -5.61E-03 /) + CASE ( 13 ) ! 310-330 m + UH_coef(:, 1) = (/ 0.736987, -0.103727, 9.95E-02, 0.343208 /) + UH_coef(:, 2) = (/ 0.28285, 0.370583, 1.17749, -0.490259 /) + UH_coef(:, 3) = (/ -0.130451, -0.557928, -0.272771, -0.230816 /) + UH_coef(:, 4) = (/ -1.83E-02, 1.00E-01, -0.367321, 0.486971 /) + UH_coef(:, 5) = (/ 2.66E-02, -0.149206, 0.365342, -0.318809 /) + UH_coef(:, 6) = (/ 4.16E-02, 3.60E-02, -0.801161, 6.00E-06 /) + UH_coef(:, 7) = (/ -2.36E-02, 1.96E-04, 0.340449, 2.72E-02 /) + UH_coef(:, 8) = (/ 1.30E-03, 0.214384, 0.125371, -8.47E-02 /) + UH_coef(:, 9) = (/ -1.23E-02, 4.75E-02, 0.182118, 1.78E-02 /) + UH_coef(:,10) = (/ 4.63E-03, -0.1309, -0.130584, 2.35E-02 /) + UH_coef(:,11) = (/ 9.03E-04, -6.18E-02, -7.85E-03, 1.17E-02 /) + CASE ( 14 ) ! 330-350 m + UH_coef(:, 1) = (/ 0.706488, -1.21766, 1.08617, 0.674247 /) + UH_coef(:, 2) = (/ 0.341777, 2.27476, 3.81434, -2.32363 /) + UH_coef(:, 3) = (/ -0.112822, 7.53E-02, 0.221349, -0.700428 /) + UH_coef(:, 4) = (/ -1.99E-02, -1.95E-02, 0.947788, 4.68E-02 /) + UH_coef(:, 5) = (/ 3.08E-02, 0.334947, 0.10847, -0.534662 /) + UH_coef(:, 6) = (/ 5.21E-02, 0.349056, -1.14517, -0.147474 /) + UH_coef(:, 7) = (/ -1.67E-02, -0.143994, -0.409398, 0.228081 /) + UH_coef(:, 8) = (/ -1.75E-03, -0.115198, 3.23E-03, 0.100094 /) + UH_coef(:, 9) = (/ -2.30E-02, -5.63E-02, 0.168561, 0.159537 /) + UH_coef(:,10) = (/ -6.41E-03, -8.48E-02, 0.135087, 8.81E-02 /) + UH_coef(:,11) = (/ 1.13E-03, 2.07E-02, 9.18E-02, -3.77E-02 /) + CASE ( 15 ) ! 350-370 m + UH_coef(:, 1) = (/ 0.721629, -0.941544, 0.923908, 0.543678 /) + UH_coef(:, 2) = (/ 0.346956, -0.281582, -2.32358, -0.244435 /) + UH_coef(:, 3) = (/ -0.109484, 0.275053, 0.86928, -0.771081 /) + UH_coef(:, 4) = (/ -3.96E-02, -0.790621, -8.84E-02, 0.723378 /) + UH_coef(:, 5) = (/ 1.59E-02, -0.394222, -0.479505, -8.67E-02 /) + UH_coef(:, 6) = (/ 2.68E-02, 0.466895, 0.522378, -0.263669 /) + UH_coef(:, 7) = (/ -9.57E-03, -8.52E-02, 1.11E-02, 3.20E-02 /) + UH_coef(:, 8) = (/ 3.46E-04, -5.34E-02, 0.15998, 0.108225 /) + UH_coef(:, 9) = (/ -1.10E-02, -0.116864, -6.06E-02, 6.09E-02 /) + UH_coef(:,10) = (/ -2.93E-03, 2.72E-02, 5.08E-02, 7.50E-03 /) + UH_coef(:,11) = (/ -2.04E-03, -2.07E-02, -3.07E-02, 3.58E-02 /) + CASE ( 16 ) ! 370-390 m + UH_coef(:, 1) = (/ 0.732127, -2.66819, -7.94E-02, 0.676096 /) + UH_coef(:, 2) = (/ 0.285167, 3.89442, -0.917426, 0.104248 /) + UH_coef(:, 3) = (/ -8.38E-02, 0.235268, -2.19E-03, -0.914663 /) + UH_coef(:, 4) = (/ -3.98E-02, -0.858603, -0.538194, 0.843739 /) + UH_coef(:, 5) = (/ -1.64E-02, 0.287007, -5.39E-02, 0.108834 /) + UH_coef(:, 6) = (/ 3.31E-02, 0.218726, 0.175636, -0.329844 /) + UH_coef(:, 7) = (/ 3.10E-05, -6.89E-02, 3.76E-02, -4.73E-02 /) + UH_coef(:, 8) = (/ 1.06E-02, -5.03E-02, 1.99E-02, 3.74E-02 /) + UH_coef(:, 9) = (/ -1.05E-02, 9.92E-02, 0.11293, 2.26E-02 /) + UH_coef(:,10) = (/ -2.99E-03, -0.106831, 0.122628, 1.83E-02 /) + UH_coef(:,11) = (/ -7.32E-03, 3.52E-02, -3.36E-02, 8.59E-02 /) + CASE ( 17 ) ! 390-410 m + UH_coef(:, 1) = (/ 0.707698, 0.119876, 0.427545, 0.2468 /) + UH_coef(:, 2) = (/ 0.307273, 0.428003, -3.09224, 1.01117 /) + UH_coef(:, 3) = (/ -7.33E-02, 0.51572, -0.229086, -0.792402 /) + UH_coef(:, 4) = (/ -4.73E-02, 8.49E-02, -0.52415, 0.571084 /) + UH_coef(:, 5) = (/ -2.83E-02, 0.165455, -0.691726, 0.349932 /) + UH_coef(:, 6) = (/ 2.17E-02, 0.258434, 0.170597, -0.236707 /) + UH_coef(:, 7) = (/ -4.59E-03, -0.130722, 0.182955, -3.40E-02 /) + UH_coef(:, 8) = (/ 1.82E-02, 9.79E-02, 0.189511, -0.158597 /) + UH_coef(:, 9) = (/ -7.84E-04, -2.50E-02, 0.137171, -5.77E-02 /) + UH_coef(:,10) = (/ -2.91E-03, -4.84E-02, 0.168698, 8.22E-03 /) + UH_coef(:,11) = (/ -4.67E-03, 1.75E-03, 1.80E-02, 4.41E-02 /) + CASE ( 18 ) ! 410-430 m + UH_coef(:, 1) = (/ 0.688761, -0.7286, -1.55711, 1.27145 /) + UH_coef(:, 2) = (/ 0.300421, 0.633115, 0.881706, -8.38E-03 /) + UH_coef(:, 3) = (/ -6.81E-02, 0.210301, 0.610772, -0.714435 /) + UH_coef(:, 4) = (/ -5.93E-02, -0.373997, -0.593894, 1.01556 /) + UH_coef(:, 5) = (/ -4.26E-02, -2.45E-02, -0.400705, 0.399717 /) + UH_coef(:, 6) = (/ 1.39E-02, 6.09E-02, -0.161239, -3.06E-02 /) + UH_coef(:, 7) = (/ -4.41E-03, -1.98E-02, 0.293288, -0.110401 /) + UH_coef(:, 8) = (/ 1.42E-02, 8.22E-02, -1.50E-02, -1.54E-02 /) + UH_coef(:, 9) = (/ 6.30E-03, -1.50E-02, -7.57E-02, -7.10E-02 /) + UH_coef(:,10) = (/ 2.19E-03, -2.59E-02, 8.53E-02, -2.29E-02 /) + UH_coef(:,11) = (/ -2.76E-03, 1.68E-02, -8.77E-02, 3.27E-02 /) + CASE ( 19 ) ! 430-450 m + UH_coef(:, 1) = (/ 0.659495, -0.22327, -1.75403, 1.65777 /) + UH_coef(:, 2) = (/ 0.384097, 1.06351, 2.53779, -1.63428 /) + UH_coef(:, 3) = (/ -2.42E-02, 0.113735, -1.42805, -0.690773 /) + UH_coef(:, 4) = (/ -3.30E-02, 8.60E-02, -1.00836, 0.764307 /) + UH_coef(:, 5) = (/ -2.76E-02, 0.297567, 0.697445, -0.187071 /) + UH_coef(:, 6) = (/ 1.21E-02, 0.212621, -0.570822, 1.23E-02 /) + UH_coef(:, 7) = (/ -2.22E-02, 0.166286, 0.50751, 1.87E-02 /) + UH_coef(:, 8) = (/ 1.52E-02, 5.81E-02, -0.256912, -5.10E-02 /) + UH_coef(:, 9) = (/ 2.11E-03, -1.45E-02, -8.94E-02, -2.00E-02 /) + UH_coef(:,10) = (/ 3.06E-03, 1.60E-02, 7.45E-02, -3.77E-02 /) + UH_coef(:,11) = (/ -1.84E-04, -1.56E-02, -6.25E-02, 1.57E-02 /) + CASE ( 20 ) ! 450-470 m + UH_coef(:, 1) = (/ 0.64099, -2.02496, 0.427597, 1.52166 /) + UH_coef(:, 2) = (/ 0.391609, 2.03441, -0.122486, -1.03579 /) + UH_coef(:, 3) = (/ 8.28E-03, 0.5942, -0.42469, -1.35655 /) + UH_coef(:, 4) = (/ -2.54E-02, -0.826812, -0.812187, 0.911776 /) + UH_coef(:, 5) = (/ -2.77E-02, -9.73E-03, 0.315974, 2.34E-02 /) + UH_coef(:, 6) = (/ 1.37E-02, 0.365984, 0.141952, -0.299349 /) + UH_coef(:, 7) = (/ -1.95E-02, -0.406182, 2.32E-02, 0.184752 /) + UH_coef(:, 8) = (/ 7.34E-03, 8.54E-02, -0.255458, 7.08E-02 /) + UH_coef(:, 9) = (/ 1.54E-03, 5.82E-02, -5.72E-02, -6.37E-02 /) + UH_coef(:,10) = (/ 5.11E-03, -6.11E-02, -7.04E-03, -3.64E-02 /) + UH_coef(:,11) = (/ 1.97E-03, -1.09E-02, -8.18E-02, -6.03E-03 /) + CASE ( 21 ) ! 470-490 m + UH_coef(:, 1) = (/ 0.547127, -0.327778, 2.00666, 2.67869 /) + UH_coef(:, 2) = (/ 0.427112, 8.56E-02, -1.61197, -1.17989 /) + UH_coef(:, 3) = (/ 6.23E-02, 0.760714, -0.659927, -2.30882 /) + UH_coef(:, 4) = (/ -4.04E-02, -0.873328, -0.118326, 1.19626 /) + UH_coef(:, 5) = (/ -4.85E-03, 0.130813, -0.169613, -0.181674 /) + UH_coef(:, 6) = (/ 4.82E-03, 0.289038, 7.34E-02, 6.45E-03 /) + UH_coef(:, 7) = (/ -2.49E-02, -0.375342, 0.15139, 0.208253 /) + UH_coef(:, 8) = (/ 9.48E-04, 5.23E-02, -0.213227, 0.137941 /) + UH_coef(:, 9) = (/ -9.18E-03, 3.91E-02, 7.26E-02, 4.73E-02 /) + UH_coef(:,10) = (/ -6.00E-05, 1.03E-02, 7.46E-03, 1.86E-02 /) + UH_coef(:,11) = (/ -2.21E-03, -9.70E-05, -7.13E-02, 4.29E-02 /) + CASE DEFAULT + CALL ProgAbort ('Error getting UH coefficients' ) + END SELECT + + SELECT CASE ( HtIndx ) + CASE ( 1 ) ! 70-90 m + WD_coef(:, 1) = (/ 5.07735, 96.4785, 18.8465, 110.986 /) + WD_coef(:, 2) = (/ 0.75209, -16.5103, -25.9592, 9.05636 /) + WD_coef(:, 3) = (/ -1.50806, 1.69319, -7.7859, 13.3041 /) + WD_coef(:, 4) = (/ 1.11287, 3.711, 13.1084, -11.9491 /) + WD_coef(:, 5) = (/ -0.987363, -2.93059, -4.75454, 9.04282 /) + WD_coef(:, 6) = (/ 0.65727, 0.560223, -0.541911, -5.33397 /) + WD_coef(:, 7) = (/ -0.493572, -0.455574, 2.03972, 3.53745 /) + WD_coef(:, 8) = (/ 0.244207, 0.390402, 1.5338, -1.9793 /) + WD_coef(:, 9) = (/ -1.26E-02, 0.19732, -2.70454, 0.179412 /) + WD_coef(:,10) = (/ 9.13E-04, 9.65E-02, 0.304467, 4.79E-02 /) + WD_coef(:,11) = (/ -7.71E-02, -0.11096, 0.51028, 0.585717 /) + CASE ( 2 ) ! 90-110 m + WD_coef(:, 1) = (/ 2.98622, 87.1045, 41.7453, 124.301 /) + WD_coef(:, 2) = (/ 0.241282, -10.9238, -31.5696, 11.0764 /) + WD_coef(:, 3) = (/ -0.380786, -1.71395, -8.35561, 3.68007 /) + WD_coef(:, 4) = (/ 0.287014, 6.76407, 17.1736, -7.4345 /) + WD_coef(:, 5) = (/ -0.682991, -5.48805, -12.7947, 10.9313 /) + WD_coef(:, 6) = (/ 0.415999, 2.36938, 4.47285, -5.47595 /) + WD_coef(:, 7) = (/ -0.184533, -7.04E-02, 0.81309, 1.06891 /) + WD_coef(:, 8) = (/ 0.152381, -0.344921, 3.40496, -1.81465 /) + WD_coef(:, 9) = (/ -0.113556, -1.02575, -5.54619, 2.51668 /) + WD_coef(:,10) = (/ 3.87E-02, 1.0794, 0.98668, -0.942351 /) + WD_coef(:,11) = (/ 7.37E-02, -0.284347, 1.12315, -1.04163 /) + CASE ( 3 ) ! 110-130 m + WD_coef(:, 1) = (/ -10.8064, 63.1523, 18.7751, 255.252 /) + WD_coef(:, 2) = (/ 1.89875, -15.7662, -27.2545, -5.90699 /) + WD_coef(:, 3) = (/ -1.81141, -7.58E-03, 4.49E-02, 19.4007 /) + WD_coef(:, 4) = (/ -0.420216, 4.54261, 16.6642, -1.5632 /) + WD_coef(:, 5) = (/ 3.09E-02, 0.162346, -5.68196, 1.70168 /) + WD_coef(:, 6) = (/ 0.372585, -0.888944, -0.400871, -3.98736 /) + WD_coef(:, 7) = (/ 0.137532, -1.86E-02, -1.97659, -1.07897 /) + WD_coef(:, 8) = (/ 7.11E-02, 0.275322, 2.06716, -0.99703 /) + WD_coef(:, 9) = (/ -0.142081, 0.690143, 1.74256, 0.963168 /) + WD_coef(:,10) = (/ -0.225792, -0.215169, 0.660299, 1.89319 /) + WD_coef(:,11) = (/ 1.91E-02, -0.23, -1.69222, 0.190668 /) + CASE ( 4 ) ! 130-150 m + WD_coef(:, 1) = (/ 0.270461, 107.786, 140.705, 143.549 /) + WD_coef(:, 2) = (/ 2.46519, 25.9261, 54.6629, -43.2182 /) + WD_coef(:, 3) = (/ -1.11746, -4.09287, -5.71316, 16.4144 /) + WD_coef(:, 4) = (/ -0.104557, 2.88836, 14.657, -5.58632 /) + WD_coef(:, 5) = (/ 1.4104, -0.862421, 1.88282, -13.3856 /) + WD_coef(:, 6) = (/ -0.994103, 6.07897, 6.16378, 6.53327 /) + WD_coef(:, 7) = (/ 0.440338, -7.14173, -12.2957, 0.653282 /) + WD_coef(:, 8) = (/ -0.705677, 2.13336, 2.39331, 5.62277 /) + WD_coef(:, 9) = (/ 0.398742, -3.5049, -3.97854, -1.68531 /) + WD_coef(:,10) = (/ -7.72E-02, 2.14124, 3.42657, -0.982025 /) + WD_coef(:,11) = (/ 0.120525, -1.80518, -3.44124, 0.391772 /) + CASE ( 5 ) ! 150-170 m + WD_coef(:, 1) = (/ 10.3894, 203.711, 87.9736, 0.818669 /) + WD_coef(:, 2) = (/ 4.15105, 37.734, 56.1061, -72.0928 /) + WD_coef(:, 3) = (/ -1.60031, -6.42686, 2.99983, 21.7355 /) + WD_coef(:, 4) = (/ 0.162421, -22.7335, 4.23498, 0.433394 /) + WD_coef(:, 5) = (/ -1.00817, -1.82237, -17.2291, 18.8346 /) + WD_coef(:, 6) = (/ 0.591051, 5.30019, 22.1782, -15.2786 /) + WD_coef(:, 7) = (/ -0.350898, -1.35238, -14.9057, 9.09022 /) + WD_coef(:, 8) = (/ 0.512704, 5.33682, 12.0501, -11.3284 /) + WD_coef(:, 9) = (/ -0.294613, -6.61282, -13.756, 9.48747 /) + WD_coef(:,10) = (/ 0.180824, 6.67558, 8.1748, -6.39538 /) + WD_coef(:,11) = (/ -0.168678, -3.5973, -2.92266, 3.62255 /) + CASE ( 6 ) ! 170-190 m + WD_coef(:, 1) = (/ -3.05838, 92.242, -6.17694, 218.678 /) + WD_coef(:, 2) = (/ -1.19176, 10.9436, 5.33317, 23.6574 /) + WD_coef(:, 3) = (/ 0.396791, 5.36609, 14.86, -12.1807 /) + WD_coef(:, 4) = (/ -0.260044, -3.3155, -1.83325, 3.07872 /) + WD_coef(:, 5) = (/ 0.147588, 3.54423, 2.61624, -2.87076 /) + WD_coef(:, 6) = (/ -3.09E-02, -0.298005, -3.99378, 2.512 /) + WD_coef(:, 7) = (/ 3.52E-02, 0.476622, 0.917889, -1.19482 /) + WD_coef(:, 8) = (/ -0.10397, -3.13393, -1.34654, 2.38467 /) + WD_coef(:, 9) = (/ 0.111959, 0.768005, 1.09164, -1.84864 /) + WD_coef(:,10) = (/ -5.32E-02, -0.753046, 0.517477, 0.77376 /) + WD_coef(:,11) = (/ 2.36E-02, -0.255733, -0.765475, -0.183366 /) + CASE ( 7 ) ! 190-210 m + WD_coef(:, 1) = (/ 2.63747, 48.8574, -148.839, 198.635 /) + WD_coef(:, 2) = (/ 0.276349, 8.15568, 11.5466, 4.89475 /) + WD_coef(:, 3) = (/ -0.161153, -3.92434, 15.2465, -2.75263 /) + WD_coef(:, 4) = (/ -0.215546, -6.05707, -0.221136, 2.96778 /) + WD_coef(:, 5) = (/ -0.174687, 0.722833, 2.58751, 1.43519 /) + WD_coef(:, 6) = (/ -3.24E-03, 0.841219, 2.36677, -0.541046 /) + WD_coef(:, 7) = (/ -0.14379, -0.422125, 6.03272, -3.55E-02 /) + WD_coef(:, 8) = (/ 4.94E-02, -0.165447, -1.64947, -0.118004 /) + WD_coef(:, 9) = (/ 6.88E-03, 0.618011, 0.600728, -0.312735 /) + WD_coef(:,10) = (/ -2.96E-02, -0.102388, -0.423526, 0.526055 /) + WD_coef(:,11) = (/ 3.77E-03, -0.79762, -1.48591, 0.487559 /) + CASE ( 8 ) ! 210-230 m + WD_coef(:, 1) = (/ 1.25931, 81.7121, -72.2497, 192.288 /) + WD_coef(:, 2) = (/ -0.421425, 0.812039, 26.4136, 12.7087 /) + WD_coef(:, 3) = (/ -0.477334, -0.804493, 10.2938, 2.63738 /) + WD_coef(:, 4) = (/ 0.27025, -1.48414, 6.44E-02, -3.62925 /) + WD_coef(:, 5) = (/ -0.206555, 2.60212, 4.78E-03, 1.41829 /) + WD_coef(:, 6) = (/ 0.199714, -0.145286, -1.43609, -1.0421 /) + WD_coef(:, 7) = (/ -8.81E-02, -1.11826, 0.562309, 0.568182 /) + WD_coef(:, 8) = (/ 4.38E-02, -0.94946, -1.20199, 0.184361 /) + WD_coef(:, 9) = (/ -5.13E-02, -0.157795, -0.596316, 0.747777 /) + WD_coef(:,10) = (/ 5.03E-02, 6.23E-02, -0.821348, -0.411198 /) + WD_coef(:,11) = (/ -2.45E-02, 3.66E-03, 0.61934, 0.147334 /) + CASE ( 9 ) ! 230-250 m + WD_coef(:, 1) = (/ 4.99773, 45.439, -22.9981, 142.166 /) + WD_coef(:, 2) = (/ 1.34923, -0.690733, 1.11037, -7.00256 /) + WD_coef(:, 3) = (/ -4.58E-02, -1.48399, 3.15438, -1.20619 /) + WD_coef(:, 4) = (/ -5.86E-02, -0.324401, -0.520264, 0.827308 /) + WD_coef(:, 5) = (/ 6.67E-02, 1.95293, -1.46579, -1.66186 /) + WD_coef(:, 6) = (/ 2.23E-02, 1.10257, 1.61038, -0.14154 /) + WD_coef(:, 7) = (/ 4.83E-02, -0.46633, 0.318096, -1.22718 /) + WD_coef(:, 8) = (/ -3.56E-02, -0.905797, -0.659337, 1.10221 /) + WD_coef(:, 9) = (/ -6.54E-04, 0.514329, 0.38488, -0.221416 /) + WD_coef(:,10) = (/ 2.40E-03, -0.307029, -0.455799, 0.167602 /) + WD_coef(:,11) = (/ 5.79E-03, -0.3575, -6.82E-02, -1.79E-02 /) + CASE ( 10 ) ! 250-270 m + WD_coef(:, 1) = (/ 2.87491, 81.7603, -14.221, 143.973 /) + WD_coef(:, 2) = (/ 0.176626, 0.711168, 14.3778, 3.41781 /) + WD_coef(:, 3) = (/ -0.112353, -4.44334, 5.01439, -0.539061 /) + WD_coef(:, 4) = (/ 0.135496, 0.868787, -2.54952, -1.4882 /) + WD_coef(:, 5) = (/ -5.87E-02, 7.34E-02, 0.618705, 0.341871 /) + WD_coef(:, 6) = (/ 4.36E-02, 1.16076, -2.2411, 0.371484 /) + WD_coef(:, 7) = (/ -4.21E-03, -0.219162, 3.07613, -1.48294 /) + WD_coef(:, 8) = (/ 2.91E-02, -7.90E-02, -2.06058, 0.637811 /) + WD_coef(:, 9) = (/ 6.84E-04, 0.398542, -0.227958, -0.195655 /) + WD_coef(:,10) = (/ -1.33E-02, -0.148014, 0.112677, 0.28039 /) + WD_coef(:,11) = (/ 4.56E-02, -0.4372, -1.05259, -0.39506 /) + CASE ( 11 ) ! 270-290 m + WD_coef(:, 1) = (/ -3.74E-02, 5.72313, -25.8459, 204.708 /) + WD_coef(:, 2) = (/ 0.387587, 5.70337, 37.0722, -5.10619 /) + WD_coef(:, 3) = (/ 0.130067, 8.86213, 7.6219, -6.77984 /) + WD_coef(:, 4) = (/ -1.83E-02, -4.80402, 1.26728, 1.1988 /) + WD_coef(:, 5) = (/ -0.125984, 5.69111, -2.4798, 0.370193 /) + WD_coef(:, 6) = (/ 7.02E-02, -4.02809, 0.545202, 0.396538 /) + WD_coef(:, 7) = (/ -4.89E-02, 1.99119, -7.47E-02, -0.617665 /) + WD_coef(:, 8) = (/ 7.28E-02, -1.94844, -0.9012, 0.174322 /) + WD_coef(:, 9) = (/ -2.75E-02, 0.875895, 8.29E-02, 1.47E-02 /) + WD_coef(:,10) = (/ -4.90E-03, -0.26505, 0.684299, -0.101304 /) + WD_coef(:,11) = (/ -2.46E-03, -9.03E-02, -0.25124, 0.130552 /) + CASE ( 12 ) ! 290-310 m + WD_coef(:, 1) = (/ 4.48806, 101.681, -24.2152, 108.849 /) + WD_coef(:, 2) = (/ 1.12228, -11.8153, -5.83094, -3.59506 /) + WD_coef(:, 3) = (/ 0.152934, 0.610899, 10.1148, -6.59595 /) + WD_coef(:, 4) = (/ 6.76E-02, 1.44362, -8.36227, 1.70741 /) + WD_coef(:, 5) = (/ -8.86E-02, 1.22016, 4.89384, -1.422 /) + WD_coef(:, 6) = (/ 1.14E-02, -0.801065, -4.6529, 2.29577 /) + WD_coef(:, 7) = (/ -5.68E-03, -0.156515, 3.48364, -1.85745 /) + WD_coef(:, 8) = (/ 3.21E-02, 0.643855, -1.80571, 0.499593 /) + WD_coef(:, 9) = (/ -5.96E-03, -0.645, 1.0105, -0.256849 /) + WD_coef(:,10) = (/ -1.79E-02, 0.137457, -7.45E-03, 0.232805 /) + WD_coef(:,11) = (/ -5.07E-04, -1.20E-03, -0.280138, 9.13E-02 /) + CASE ( 13 ) ! 310-330 m + WD_coef(:, 1) = (/ 0.253568, 43.3822, 42.3741, 166.917 /) + WD_coef(:, 2) = (/ -0.210713, 14.3161, 12.187, 9.66539 /) + WD_coef(:, 3) = (/ 0.176871, -3.28688, -2.78059, -1.64384 /) + WD_coef(:, 4) = (/ 0.30952, 2.34743, -5.8261, -3.72051 /) + WD_coef(:, 5) = (/ -0.211586, -1.38792, -0.891686, 3.26282 /) + WD_coef(:, 6) = (/ 0.114874, -1.0177, -2.95833, -0.285227 /) + WD_coef(:, 7) = (/ -0.168163, 1.33608, 5.32715, 0.270668 /) + WD_coef(:, 8) = (/ 0.106821, 0.746965, -1.28128, -1.11127 /) + WD_coef(:, 9) = (/ -2.17E-02, 0.198171, 0.911532, 2.31E-02 /) + WD_coef(:,10) = (/ -5.64E-03, 0.278658, 0.250055, -9.16E-02 /) + WD_coef(:,11) = (/ 7.21E-03, 2.24E-02, 6.76E-02, -0.1011 /) + CASE ( 14 ) ! 330-350 m + WD_coef(:, 1) = (/ 1.4365, 104.113, 86.7884, 138.082 /) + WD_coef(:, 2) = (/ 1.01951, -22.4231, 8.14651, -3.0374 /) + WD_coef(:, 3) = (/ -0.14238, 5.5217, -8.37098, 1.9052 /) + WD_coef(:, 4) = (/ -8.04E-02, 2.56411, 8.01756, 0.450076 /) + WD_coef(:, 5) = (/ 7.34E-03, -3.31792, -10.0037, 1.66433 /) + WD_coef(:, 6) = (/ -3.82E-02, 3.00083, 6.14358, -0.656165 /) + WD_coef(:, 7) = (/ 0.113861, -4.41267, -2.98194, -1.24882 /) + WD_coef(:, 8) = (/ -0.154066, 4.29174, 3.74587, 1.4816 /) + WD_coef(:, 9) = (/ 0.127996, -2.88696, -2.49795, -1.24336 /) + WD_coef(:,10) = (/ -6.71E-02, 1.70388, 0.935254, 0.748082 /) + WD_coef(:,11) = (/ 8.19E-03, -4.50E-02, -0.263839, -5.18E-02 /) + CASE ( 15 ) ! 350-370 m + WD_coef(:, 1) = (/ -0.675054, 121.016, 0.173435, 199.751 /) + WD_coef(:, 2) = (/ -0.52795, 26.7663, 36.6465, 8.14164 /) + WD_coef(:, 3) = (/ 0.686068, -2.58652, 1.37125, -12.8021 /) + WD_coef(:, 4) = (/ -0.115391, -0.715049, 0.225913, 2.68255 /) + WD_coef(:, 5) = (/ 0.127924, 1.18619, -3.81934, -2.40047 /) + WD_coef(:, 6) = (/ -0.201212, -1.51136, 4.51548, 3.23679 /) + WD_coef(:, 7) = (/ 0.175571, -0.664591, -5.74074, -2.24143 /) + WD_coef(:, 8) = (/ -0.107098, 0.889236, 3.25149, 1.18349 /) + WD_coef(:, 9) = (/ 3.15E-02, -6.48E-02, -0.882842, -0.404645 /) + WD_coef(:,10) = (/ -9.69E-03, -0.486174, -0.284323, 0.336898 /) + WD_coef(:,11) = (/ 1.04E-03, -0.144399, -6.10E-02, 6.62E-02 /) + CASE ( 16 ) ! 370-390 m + WD_coef(:, 1) = (/ 0.610558, -90.3161, -86.1311, 221.346 /) + WD_coef(:, 2) = (/ -0.878196, 0.234356, -1.96802, 30.3835 /) + WD_coef(:, 3) = (/ 0.536954, 2.31986, 0.611791, -11.624 /) + WD_coef(:, 4) = (/ -0.203843, -2.10521, -1.77538, 5.20693 /) + WD_coef(:, 5) = (/ -6.04E-02, -1.53784, 0.391834, 1.09004 /) + WD_coef(:, 6) = (/ -3.32E-02, 1.08307, 0.756223, 0.579045 /) + WD_coef(:, 7) = (/ 2.20E-03, 1.00851, 0.872176, -1.24302 /) + WD_coef(:, 8) = (/ -4.70E-02, 0.313443, -5.20E-02, 1.24129 /) + WD_coef(:, 9) = (/ 0.105906, 2.60251, -0.805126, -2.35033 /) + WD_coef(:,10) = (/ -3.95E-02, -0.866726, 0.244709, 0.996069 /) + WD_coef(:,11) = (/ 5.34E-02, 0.423689, -0.910358, -0.888237 /) + CASE ( 17 ) ! 390-410 m + WD_coef(:, 1) = (/ -0.256694, -53.0924, -28.899, 212.286 /) + WD_coef(:, 2) = (/ 0.368178, 0.200188,-15.1321, 9.40209 /) + WD_coef(:, 3) = (/ -0.102825, -4.83546, 9.24228, -0.64019 /) + WD_coef(:, 4) = (/ 0.191961, 2.99238, -4.8869, -2.80575 /) + WD_coef(:, 5) = (/ -9.33E-02, 0.237869, 3.72573, -8.03E-02 /) + WD_coef(:, 6) = (/ 1.70E-02, 2.22246, -0.874, 0.324301 /) + WD_coef(:, 7) = (/ -4.39E-02, -1.22545, 1.03253, -7.41E-02 /) + WD_coef(:, 8) = (/ 9.07E-03, -0.438369, -1.85468, 0.746178 /) + WD_coef(:, 9) = (/ -2.97E-02, -0.626331, 1.32958, 0.161941 /) + WD_coef(:,10) = (/ -4.73E-03, -0.639604, -0.50062, 0.398523 /) + WD_coef(:,11) = (/ 7.78E-04, 0.203885, 0.111938, -9.66E-02 /) + CASE ( 18 ) ! 410-430 m + WD_coef(:, 1) = (/ -1.05454, 19.3432, 14.3866, 209.914 /) + WD_coef(:, 2) = (/ -5.37E-02, -6.69143, -5.48868, 13.8188 /) + WD_coef(:, 3) = (/ 0.130461, 1.84379, 10.2975, -6.85151 /) + WD_coef(:, 4) = (/ 0.120135, 3.25255, -4.64527, -0.957415 /) + WD_coef(:, 5) = (/ -0.157071, -1.87681, 4.37492, 1.52585 /) + WD_coef(:, 6) = (/ 0.220174, 1.14707, -5.27774, -2.10403 /) + WD_coef(:, 7) = (/ -0.185849, -8.73E-02, 4.5702, 1.45097 /) + WD_coef(:, 8) = (/ 5.77E-02, -0.265271, -2.17262, 1.19E-02 /) + WD_coef(:, 9) = (/ -3.19E-02, 0.159054, 1.11463, 9.91E-02 /) + WD_coef(:,10) = (/ -9.31E-03, -0.514427, -0.486658, 0.472324 /) + WD_coef(:,11) = (/ 5.84E-03, -6.98E-02, -6.53E-02, -7.68E-02 /) + CASE ( 19 ) ! 430-450 m + WD_coef(:, 1) = (/ 0.624689, 63.9533, -115.139, 203.718 /) + WD_coef(:, 2) = (/ -0.249911, 8.56489, 12.0426, 11.2274 /) + WD_coef(:, 3) = (/ 0.208499, -2.38494, 8.76157, -7.17681 /) + WD_coef(:, 4) = (/ -0.205812, 3.60713, 5.60652, 2.51439 /) + WD_coef(:, 5) = (/ 0.320606, -7.16713, -10.6408, -3.32927 /) + WD_coef(:, 6) = (/ -0.178674, 5.15743, 3.70481, 2.92097 /) + WD_coef(:, 7) = (/ 0.101549, -5.22916, -1.89887, -1.64557 /) + WD_coef(:, 8) = (/ -9.30E-02, 2.8729, 1.14221, 1.4604 /) + WD_coef(:, 9) = (/ 1.45E-02, -1.29998, -0.491218, -6.91E-02 /) + WD_coef(:,10) = (/ -6.95E-04, 0.830442, 1.25591, -0.451134 /) + WD_coef(:,11) = (/ -6.90E-04, 1.30E-02, -0.16423, 7.65E-02 /) + CASE ( 20 ) ! 450-470 m + WD_coef(:, 1) = (/ 4.30205, 83.823, -77.8869, 120.115 /) + WD_coef(:, 2) = (/ 0.11147, -2.13123, -13.0305, 11.4506 /) + WD_coef(:, 3) = (/ 5.36E-02, -9.82942, 3.21203, -2.14437 /) + WD_coef(:, 4) = (/ 3.12E-02, -0.694, -2.56494, 0.846492 /) + WD_coef(:, 5) = (/ -3.97E-02, 0.628515, 0.898384, -0.403596 /) + WD_coef(:, 6) = (/ 0.187725, -1.32489, -3.10108, -1.64756 /) + WD_coef(:, 7) = (/ -8.75E-02, -0.750003, 1.2358, 0.95118 /) + WD_coef(:, 8) = (/ 4.29E-02, 0.206995, -0.591777, -0.495133 /) + WD_coef(:, 9) = (/ -3.25E-02, 0.187007, 0.351131, 0.374602 /) + WD_coef(:,10) = (/ -1.79E-02, -0.651232, -0.437205, 0.653204 /) + WD_coef(:,11) = (/ 5.74E-03, 0.210108, -0.185616, -8.91E-02 /) + CASE ( 21 ) ! 470-490 m + WD_coef(:, 1) = (/ 0.685959, 76.5757, -26.8137, 187.31 /) + WD_coef(:, 2) = (/ -0.229648, 3.36903, -12.3466, 19.5787 /) + WD_coef(:, 3) = (/ 5.56E-02, -6.33886, 2.64958, -2.35925 /) + WD_coef(:, 4) = (/ -3.42E-02, -1.78314, 1.51304, 0.43034 /) + WD_coef(:, 5) = (/ 5.81E-02, 4.2818, -1.08668, -2.13185 /) + WD_coef(:, 6) = (/ -1.94E-02, -2.76039, -0.573698, 1.97694 /) + WD_coef(:, 7) = (/ 1.26E-02, 0.932315, 0.974862, -1.5273 /) + WD_coef(:, 8) = (/ 1.04E-02, -0.143063, -0.728002, 0.464589 /) + WD_coef(:, 9) = (/ 1.21E-03, 0.262702, -0.133363, -0.236706 /) + WD_coef(:,10) = (/ -2.29E-04, -0.162697, -0.138587, 0.17236 /) + WD_coef(:,11) = (/ 6.61E-03, -5.47E-02, -0.104054, -9.64E-02 /) + CASE DEFAULT + CALL ProgAbort ('Error getting WD coefficients' ) + END SELECT + + RETURN +END SUBROUTINE get_coefs +!======================================================================= +FUNCTION getUStarProfile(p, WS, Ht, UStarOffset, UstarSlope) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(IN) :: Ht(:) ! Height at which ustar is defined + REAL(ReKi), INTENT(IN) :: WS(:) ! Wind speed(s) at heights, Ht + REAL(ReKi), INTENT(IN) :: UStarOffset ! A scaling/offset value used with the Ustar_profile to ensure that the mean hub u'w' and ustar inputs agree with the profile values + REAL(ReKi), INTENT(IN) :: UstarSlope ! A scaling/slope value used with the Ustar_profile to ensure that the mean hub u'w' and ustar inputs agree with the profile values + + REAL(ReKi) :: tmpZ ! a temporary value + REAL(ReKi) :: getUStarProfile(SIZE(Ht)) ! the array of ustar values + + INTEGER(IntKi) :: IZ + INTEGER(IntKi) :: Zindx + INTEGER(IntKi) :: Zindx_mn (1) + INTEGER(IntKi) :: Zindx_mx (1) + + LOGICAL :: mask(SIZE(Ht)) + + mask = Ht.GE.profileZmin + IF ( ANY(mask) ) THEN + Zindx_mn = MINLOC( Ht, MASK=mask ) + + mask = Ht.LE.profileZmax + IF ( ANY(mask) ) THEN + Zindx_mx = MAXLOC( Ht, MASK=mask ) + + DO IZ = 1,SIZE(Ht) + IF ( Ht(IZ) < profileZmin ) THEN + Zindx = Zindx_mn(1) + ELSEIF ( Ht(IZ) > profileZmax ) THEN + Zindx = Zindx_mx(1) + ELSE + Zindx = IZ + ENDIF + + tmpZ = Ht(Zindx) !ustar is constant below 50 meters, and we don't want to extrapolate too high (last measurement is at 116 m) + + getUStarProfile( IZ) = ( 0.045355367 + 4.47275E-8*tmpZ**3) & + + ( 0.511491978 - 0.09691157*LOG(tmpZ) - 199.226951/tmpZ**2 ) * WS(Zindx) & + + (-0.00396447 - 55.7818832/tmpZ**2 ) * p%met%RICH_NO & + + (-5.35764429 + 0.102002162*tmpZ/LOG(tmpZ) + 25.30585136/SQRT(tmpZ) ) * p%met%UstarDiab + ENDDO + + ELSE ! All are above the max height so we'll use the old relationship at all heights + getUStarProfile(:) = 0.17454 + 0.72045*p%met%UstarDiab**1.36242 + ENDIF + + ELSE ! All are below the min height so we'll use the diabatic Ustar value + getUStarProfile(:) = p%met%UstarDiab + ENDIF + + getUStarProfile = UstarSlope * getUStarProfile(:) + UstarOffset ! These terms are used to make the ustar profile match the rotor-disk averaged value and input hub u'w' + +END FUNCTION +!======================================================================= +FUNCTION getZLProfile(WS, Ht, RichNo, ZL, L, ZLOffset, WindProfileType) + + IMPLICIT NONE + + + REAL(ReKi), INTENT(IN) :: Ht(:) ! Height at which local z/L is defined + REAL(ReKi), INTENT(IN) :: WS(:) ! Wind speed(s) at heights, Ht + REAL(ReKi), INTENT(IN) :: RichNo ! Richardson Number + REAL(ReKi), INTENT(IN) :: ZL ! z/L, an alternate measure of stability (M-O) for RichNo + REAL(ReKi), INTENT(IN) :: L ! L, M-O length + REAL(ReKi), INTENT(IN) :: ZLOffset ! Offset to align profile with rotor-disk averaged z/L + + CHARACTER(*), INTENT(IN) :: WindProfileType + + REAL(ReKi) :: tmpZ ! a temporary value + REAL(ReKi) :: getZLProfile(SIZE(Ht)) ! the array of z/L values + + INTEGER :: IZ + INTEGER :: Zindx + INTEGER :: Zindx_mn (1) + INTEGER :: Zindx_mx (1) + + LOGICAL :: mask(SIZE(Ht)) + + mask = Ht.GE.profileZmin + IF ( ANY(mask) ) THEN + Zindx_mn = MINLOC( Ht, MASK=mask ) + + mask = Ht.LE.profileZmax + IF ( ANY(mask) ) THEN + Zindx_mx = MAXLOC( Ht, MASK=mask ) + + DO IZ = 1,SIZE(Ht) + IF ( Ht(IZ) < profileZmin ) THEN + Zindx = Zindx_mn(1) + tmpZ = Ht(IZ) / Ht(Zindx) ! This keeps L constant below 50 m + ELSEIF ( Ht(IZ) > profileZmax ) THEN + Zindx = Zindx_mx(1) + tmpZ = 1.0 ! L changes above measurement height, but since we don't know how much, we're going to keep z/L constant + ELSE + Zindx = IZ + tmpZ = 1.0 + ENDIF !L is constant below 50 meters, and we don't want to extrapolate too high (last measurement is at 116 m) + + IF ( INDEX( 'JU', WindProfileType(1:1) ) > 0 ) THEN + IF ( RichNo >= 0 ) THEN + getZLProfile( IZ) = - 0.352464*RichNo + 0.005272*WS(Zindx) + 0.465838 + ELSE + getZLProfile( IZ) = 0.004034*Ht(Zindx) + 0.809494*RichNo - 0.008298*WS(Zindx) - 0.386632 + ENDIF !RichNo + ELSE + IF ( RichNo >= 0 ) THEN + getZLProfile( IZ) = 0.003068*Ht(Zindx) + 1.140264*RichNo + 0.036726*WS(Zindx) - 0.407269 + ELSE + getZLProfile( IZ) = 0.003010*Ht(Zindx) + 0.942617*RichNo - 0.221886 + ENDIF + ENDIF + getZLProfile( IZ) = MIN( getZLProfile( IZ), 1.0_ReKi ) + getZLProfile( IZ) = getZLProfile(IZ) * tmpZ + + ENDDO + + ELSE ! All are above the max height so instead of extrapolating, we'll use ZL at all heights + getZLProfile(:) = ZL + ENDIF + + ELSE ! All are below the min height so we'll keep L constant (as is the case in the surface layer) + getZLProfile(:) = Ht(:) / L + ENDIF + + getZLProfile = getZLProfile(:) + ZLOffset ! This offset term is used to make the zl profile match the rotor-disk averaged value + + +END FUNCTION getZLProfile +!======================================================================= +END MODULE TS_Profiles diff --git a/OpenFAST/modules/turbsim/src/RandNum.f90 b/OpenFAST/modules/turbsim/src/RandNum.f90 new file mode 100644 index 000000000..34910d3c4 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/RandNum.f90 @@ -0,0 +1,1046 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TS_RandNum + + USE TurbSim_Types + USE Ran_Lux_Mod + + IMPLICIT NONE + + + INTEGER(IntKi), PARAMETER :: pRNG_RANLUX = 1 + INTEGER(IntKi), PARAMETER :: pRNG_INTRINSIC = 2 + INTEGER(IntKi), PARAMETER :: pRNG_SNLW3 = 3 + + + INTEGER, PARAMETER :: LuxLevel = 3 ! Luxury Level for RanLux RNG + + +CONTAINS + +!======================================================================= +SUBROUTINE RandNum_Init(p, OtherSt, ErrStat, ErrMsg ) + + ! Initialize the Random Number Generators + + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation +INTEGER(IntKi) , INTENT(OUT) :: ErrStat ! allocation status +CHARACTER(*) , INTENT(OUT) :: ErrMsg ! error message + + + +REAL(ReKi) :: RN(1) +INTEGER :: I ! loop counter +INTEGER :: NumSeeds ! number of seeds in the intrinsic random number generator + +ErrStat = ErrID_None +ErrMsg = "" + +IF (p%pRNG == pRNG_INTRINSIC) THEN ! RNG_type == 'NORMAL' + + + ! determine the number of seeds necessary (gfortran needs 8 or 12 seeds, not just 2) + + CALL RANDOM_SEED ( SIZE = NumSeeds ) + + IF ( NumSeeds /= 2 ) THEN + CALL ProgWarn( ' The random number generator in use differs from the original code provided by NREL. This pRNG uses ' & + //TRIM(Int2LStr(NumSeeds))//' seeds instead of the 2 in the TurbSim input file.') + END IF + + IF ( .NOT. ALLOCATED( OtherSt%nextSeed ) ) THEN + CALL AllocAry( OtherSt%nextSeed, NumSeeds, 'nextSeed', ErrSTat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + ! We'll just populate this with odd seeds = Seed(1) and even seeds = Seed(2) + DO I = 1,NumSeeds,2 + OtherSt%nextSeed(I) = p%RandSeed(1) + END DO + DO I = 2,NumSeeds,2 + OtherSt%nextSeed(I) = p%RandSeed(2) + END DO + + + CALL RANDOM_SEED ( PUT=OtherSt%nextSeed ) + + +ELSEIF (p%pRNG == pRNG_RANLUX) THEN ! RNG_type == 'RANLUX' + + CALL RLuxGo ( LuxLevel, ABS( p%RandSeed(1) ), 0, 0 ) + + IF (.NOT. ALLOCATED( OtherSt%nextSeed ) ) THEN + CALL AllocAry( OtherSt%nextSeed, 2, 'nextSeed', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + +ELSE ! pRNG == pRNG_SNLW3 + + + IF (.NOT. ALLOCATED( OtherSt%nextSeed ) ) THEN + CALL AllocAry( OtherSt%nextSeed, 3, 'nextSeed', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + END IF + + + ! A quick and dirty way to get three random seeds for u, v, and w + ! This implementation allows comparisons with Neil's SNLWIND-3D + + OtherSt%nextSeed = p%RandSeed + + CALL ARand( OtherSt%nextSeed(1), RN,1,1) + + OtherSt%nextSeed(2) = OtherSt%nextSeed(1)+1 + CALL ARand( OtherSt%nextSeed(2), RN,1,1) + + OtherSt%nextSeed(3) = OtherSt%nextSeed(2)+1 + CALL ARand( OtherSt%nextSeed(3), RN,1,1) + + +ENDIF + +END SUBROUTINE RandNum_Init +!======================================================================= +SUBROUTINE ARand(ix, RandNum_Ary,I, RNG_start) + +IMPLICIT NONE + + ! Passed variables + + +REAL(ReKi), INTENT(OUT) :: RandNum_Ary(:) ! Output: random numbers +INTEGER(IntKi), INTENT(IN) :: I ! Input: Size of RandNum_Ary to be filled +INTEGER(IntKi), INTENT(INOUT) :: ix ! Input/Output: Seed !BONNIE: should this be set to Integer(4), not default integer size? +INTEGER(IntKi), INTENT(IN) :: RNG_start + + ! Local variables + +INTEGER, PARAMETER :: B15 = 32768 ! = 2^15 +INTEGER, PARAMETER :: B16 = 65536 ! = 2^16 +INTEGER :: fHI +INTEGER :: K ! Loop counter +INTEGER :: leftLO +INTEGER, PARAMETER :: ranA = 16807 ! = 7^5 +INTEGER :: rank +INTEGER, PARAMETER :: ranP = 2147483647 ! = 2^31 - 1 = huge(ranP) +INTEGER :: xHI +INTEGER :: xaLO + +REAL(ReKi), PARAMETER :: ranPR = 1.0 / REAL(ranP, ReKi) + +!BONNIE: We should check that RandNum_Ary is dimensioned correctly.... + +DO K = RNG_start, RNG_start+I-1 + + xHI = ix / B16 + xaLO = (ix - B16*xHI) * ranA ! MOD( ix, B16 ) * ranA + + leftLO = xaLO / B16 + fHI = xHI*ranA + leftLO + rank = fHI / B15 + + ix = (((xaLO - leftLO*B16) - ranP) + (fHI - rank*B15)*B16) + rank + ! ranP is subtracted in order to avoid overflow + ! MOD( xaLO, B16 ) - ranP + B16*MOD( fHI, B15 ) + (fHI / B15) + + IF (ix < 0) ix = ix + ranP + + RandNum_Ary(K) = REAL(ix) * ranPR + +ENDDO + +END SUBROUTINE ARand +!======================================================================= +SUBROUTINE Rnd4ParmLogNorm( p, OtherSt, RandNum, Parms, FnRange ) + ! This subroutine generates a random variate with a PDF of the form + ! f(x) = A + B*exp(-0.5*(ln(x/C)/D)^2) + ! a truely log-normal distribution has A = 0 + +IMPLICIT NONE +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(IN) :: Parms(4) ! 1=a, 2=b, 3=c, 4=d +REAL(ReKi), INTENT(IN) :: FnRange(2) + +REAL(ReKi) :: fMAX ! Max(f(x)) ! occurs at f(b) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi) :: MaxVALUE ! Maximum value of returned variate +REAL(ReKi) :: MinVALUE ! Minimum value of returned variate +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +fMAX = Parms(1) + Parms(2) !See if this is correct. +MaxVALUE = MAX(FnRange(1),FnRange(2)) +MinVALUE = MIN(FnRange(1),FnRange(2)) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + Gx = Parms(1) + Parms(2)*EXP(-0.5*(LOG(RandNum/Parms(3))/Parms(4))**2); + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + +END SUBROUTINE Rnd4ParmLogNorm +!======================================================================= +SUBROUTINE Rnd3ParmNorm( p, OtherSt, RandNum, A, B, C, xMin, xMax, ErrStat, ErrMsg ) + +! Calculates a deviate from a distribution with pdf: +! f(x) = A * EXP( -0.5 * ((x-B)/C)**2 ) +! A 3-parameter normal distribution +! We assume the returned values are between -1 and 1, since this is for the Cross-Correlations, unless +! the optional values, xMin and xMax are used + + IMPLICIT NONE + + TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + + REAL(ReKi), INTENT(IN) :: A + REAL(ReKi), INTENT(IN) :: B + REAL(ReKi), INTENT(IN) :: C + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + +REAL(ReKi) :: fMAX ! Max(f(x)) = f(B) = A +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi) :: MaxVALUE ! Maximum value of returned variate +REAL(ReKi) :: MinVALUE ! Minimum value of returned variate +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method +REAL(ReKi), OPTIONAL, INTENT(IN) :: xMax ! The maximum returned iterate +REAL(ReKi), OPTIONAL, INTENT(IN) :: xMin ! The minimum returned iterate + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + + + ErrStat = ErrID_None + ErrMsg = "" + +! If A < 0 then we have a minimum value in the center of the distribution, not a maximum -- this method won't work. +! If A < 1/(MaxVALUE-MinVALUE), then this acceptance-rejection method won't work. + +IF ( PRESENT(xMax) ) THEN + MaxVALUE = xMax +ELSE + MaxVALUE = 1.0 +ENDIF + +IF ( PRESENT(xMin) ) THEN + MinVALUE = xMin +ELSE + MinVALUE = -MaxVALUE +ENDIF + +RN = 1. / (MaxVALUE-MinVALUE) +IF (A < RN .OR. C==0. .OR. MaxVALUE <= MinVALUE) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'Rnd3ParmNorm: Parameter A must at least 1/(xMax-xMin) and parameter C cannot be zero in this 3-parameter normal distribution.' + RETURN +ENDIF + + +fMAX = A +Count = 1 + + ! Generate a 3-parameter normal distribution on (-1,1) from a uniform distribution + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + Gx = A * EXP( -0.5 * ((RandNum-B)/C)**2 ) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -100 + ENDIF + +ENDDO + +END SUBROUTINE Rnd3ParmNorm +!======================================================================= +SUBROUTINE RndExp( p, OtherSt, RandExpNum, mu ) + + ! This subroutine computes an exponential distribution on (0,inf). If the + ! number of random variates to return is large, a different algorithm will + ! probably be faster (i.e. one that computes LOG(x) fewer times). + ! mu must be positive, it defaults to 1.0 if the parameter is not included. + ! RandNum has p.d.f.(x) = 1/mu * exp(-x/mu), x>=0 + ! The expected value of RandNum is mu. + + + IMPLICIT NONE + + ! Passed Variables + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandExpNum ! The exponentially distributed numbers in (0,1) +REAL(ReKi), OPTIONAL, INTENT(IN) :: mu ! The exponential distribution parameter equal to the expected value of the distribution + + ! Local Variable + +REAL(ReKi) :: mu_use + + +IF ( PRESENT(mu) ) THEN + IF (mu < 0.0) THEN + CALL WrScr( 'RndExp: Parameter mu is negative. Using -mu for exponential distribution.') + ENDIF + mu_use = ABS( mu ) +ELSE + mu_use = 1.0 +ENDIF + + + ! Get a uniform distribution of random numbers + +CALL RndUnif( p, OtherSt, RandExpNum ) + +IF ( RandExpNum == 0.0 ) THEN ! We shouldn't get two zeros in a row... + CALL RndUnif( p, OtherSt, RandExpNum ) +ENDIF + + ! Transform the uniform distribution to an exponential distribution + +RandExpNum = - mu_use * LOG( RandExpNum ) + +END SUBROUTINE RndExp + +!======================================================================= +SUBROUTINE RndJetHeight( p, OtherSt, RandNum ) +! This function uses the Pearson IV equation + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), PARAMETER :: a = 0.021548497 +REAL(ReKi), PARAMETER :: b = -13.173289 +REAL(ReKi), PARAMETER :: c = 13.43201034 +REAL(ReKi), PARAMETER :: d = 0.896588964 +REAL(ReKi), PARAMETER :: e = -0.71128456 + +REAL(ReKi), PARAMETER :: MaxVALUE = 120 ! Maximum value of returned variate +REAL(ReKi), PARAMETER :: MinVALUE = -160 ! Minimum value of returned variate +REAL(ReKi), PARAMETER :: Parms(5) = (/ a, b, c, d, e /) +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi), PARAMETER :: RangeFn(2) = (/ MinVALUE, MaxVALUE /) + + + CALL RndPearsonIV( p, OtherSt, RandNum, Parms, RangeFn ) + + +END SUBROUTINE RndJetHeight +!======================================================================= +SUBROUTINE RndModLogNorm( p, OtherSt, RandNum, Height ) + ! This subroutine generates a random variate with a PDF of the form + ! f(x) = A + B*exp(-0.5*(ln(x/C)/D)^2) + +!BJJ use Rnd4ParmLogNorm() +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandNum ! Near-Log-Normally distributed numbers +REAL(ReKi), OPTIONAL, INTENT(IN) :: Height ! height (in meters), determining what parameters to use + + ! Internal variables + +REAL(ReKi), PARAMETER :: A(3) = (/-0.0041046, -0.00566512, -0.00216964 /) +REAL(ReKi), PARAMETER :: B(3) = (/ 0.162945643, 0.278246235, 0.113718973 /) +REAL(ReKi), PARAMETER :: C(3) = (/ 0.67493672, 0.203262077, 3.211606394 /) +REAL(ReKi), PARAMETER :: D(3) = (/ 2.391316782, 2.715789776, 1.700298642 /) +REAL(ReKi) :: G ! The function g(x) = f(x)/B +REAL(ReKi) :: RN (2) ! Two random numbers for the acceptance-rejection method + + +INTEGER :: Count +INTEGER :: Indx +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) +INTEGER, PARAMETER :: MaxTime = 600 ! Maximum value of returned value (the data used to compute A,B,C,D is valid up to 600 s.) + + !Get the index closest to the station we want to use... +Indx = 2 ! Index 2 == NC-CC-SC stations (37 m) +IF ( PRESENT(Height) ) THEN + IF (Height > 47) THEN + Indx = 1 ! Index 1 == UC station (58 m) + ELSEIF (Height < 26) THEN + Indx = 3 ! Index 3 = LC station (15 m) + ENDIF +ENDIF + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN(1) ) + CALL RndUnif( p, OtherSt, RN(2) ) + + RandNum = RN(2)*MaxTime; + + g = A(Indx)/B(Indx) + EXP(-0.5*(LOG(RandNum/C(Indx))/D(Indx))**2); + + IF ( RN(1) <= g ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + + +END SUBROUTINE RndModLogNorm +!======================================================================= +SUBROUTINE RndNorm( p, OtherSt, RandNormNum, mu, sigma ) + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandNormNum ! Normally distributed numbers +REAL(ReKi), OPTIONAL, INTENT(IN) :: mu ! mean of the distributed numbers - DEFAULT IS 0.0 +REAL(ReKi), OPTIONAL, INTENT(IN) :: sigma ! standard deviation of the distributed numbers - DEFAULT IS 1.0 + + ! Internal variable + +REAL(ReKi) :: RN (2) ! Two random numbers + + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + + CALL RndUnif( p, OtherSt, RN(1) ) + CALL RndUnif( p, OtherSt, RN(2) ) + + RandNormNum = SQRT( PI / 8.0 ) * LOG( ( 1.0 + RN(1) ) / ( 1.0 - RN(1) ) ) + + IF ( RN(2) < 0.5 ) THEN + RandNormNum = -RandNormNum + ENDIF + + + ! Give the correct mean and standard deviation, if specified + + IF ( PRESENT( sigma ) ) THEN + RandNormNum = RandNormNum * sigma + ENDIF + + IF ( PRESENT( mu ) ) THEN + RandNormNum = RandNormNum + mu + ENDIF + +END SUBROUTINE RndNorm +!======================================================================= +SUBROUTINE RndNWTCpkCTKE( p, OtherSt, RandNum ) + ! This subroutine generates a random variate with a PDF of the form + ! f(x) = A + B * EXP( (-X + C + D - D*E*EXP(-( X + D*LOG(E) - C)/D)) / (D*E) + ! Maximum, f(C) = A + B + ! Uses the Acceptance-Rejection: f(x) = Cf*h(x)*g(x) + ! where h(x) = 1 / (150-30) (for our domain) + ! g(x) = f(x)/(A+B), and + ! Cf = (150-30)*(A+B) + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above + + ! Internal variables + +REAL(ReKi), PARAMETER :: A = 0.000500609 +REAL(ReKi), PARAMETER :: B = 0.286202317 +REAL(ReKi), PARAMETER :: C = -38.4131676 +REAL(ReKi), PARAMETER :: D = 244.6908697 +REAL(ReKi), PARAMETER :: E = 0.02115063 + +REAL(ReKi), PARAMETER :: fMAX = A + B ! Max(f(x)) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/B +REAL(ReKi), PARAMETER :: MaxVALUE = 150.0 ! Maximum value of returned variate +REAL(ReKi), PARAMETER :: MinVALUE = 30.0 ! Minimum value of returned variate +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + Gx = A + B * EXP( (-RandNum + C + D - D*E*EXP(-( RandNum + D*LOG(E) - C)/D)) / (D*E) ) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + +END SUBROUTINE RndNWTCpkCTKE +!======================================================================= +SUBROUTINE RndNWTCuStar( p, OtherSt, RandNum ) +!bjj 17-jul-2014: this isn't used anywhere.... + ! This subroutine generates a random variate with a PDF of the form + ! f(x) = (A + Cx + Ex^2 + Gx^3) / (1 + Bx + Dx^2 + Fx^3 + Hx^4) + ! using the acceptance/rejection method. + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above + + ! Internal variables + +REAL(ReKi), PARAMETER :: A = 4.50581 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: B = -0.60722 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: C = -14.23826 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: D = -0.96523 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: E = 15.92342 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: F = 14.41326 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: G = -6.16188 ! Scaling parameters for the pdf +REAL(ReKi), PARAMETER :: H = -4.82923 ! Scaling parameters for the pdf + +REAL(DbKi) :: Gx ! The function g(x) = f(x)/A +REAL(ReKi), PARAMETER :: MaxUstar = 1.0 ! Maximum value of returned value (the data used to compute A,B,C,D is valid up to 600 s.) +REAL(DbKi) :: RandNum2 ! RandNum**2 +REAL(DbKi) :: RandNum3 ! RandNum**3 +REAL(DbKi) :: RandNum4 ! RandNum**4 +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) + CALL RndUnif( p, OtherSt, RandNum ) + + RandNum = RandNum*MaxUstar; + + RandNum2 = RandNum*RandNum + RandNum3 = RandNum*RandNum2 + RandNum4 = RandNum*RandNum3 + + Gx = (A + C*RandNum + E*RandNum2 + G*RandNum3) / & + (1 + B*RandNum + D*RandNum2 + F*RandNum3 + H*RandNum4) + Gx = Gx / A ! This makes 0<Gx<=1 + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + +END SUBROUTINE RndNWTCuStar +!======================================================================= +SUBROUTINE RndPearsonIV( p, OtherSt, RandNum, Parms, FnRange ) +! This function uses the Pearson IV equation to generate a deviate from that distribution +! Equation 8186 in TableCurve + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(IN) :: Parms(5) ! 1=a, 2=b, 3=c, 4=d, 5=e +REAL(ReKi), INTENT(IN) :: FnRange(2) + +REAL(ReKi) :: fMAX ! Max(f(x)) ! occurs at f(b) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi) :: MaxVALUE ! Maximum value of returned variate +REAL(ReKi) :: MinVALUE ! Minimum value of returned variate +REAL(ReKi) :: n ! A temporary variable for calculating the function values +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +fMAX = Parms(1) +MaxVALUE = MAX(FnRange(1),FnRange(2)) +MinVALUE = MIN(FnRange(1),FnRange(2)) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + n = (RandNum - Parms(2))/Parms(3) - Parms(5)/(2.0*Parms(4)) + Gx = Parms(1) * (1+n**2)**(-Parms(4)) * EXP( -Parms(5)*(ATAN(n)+ATAN(Parms(5)/(2*Parms(4)))) ) / & + ( 1+Parms(5)**2/(4.*Parms(4)**2))**(-Parms(4) ) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + + +END SUBROUTINE RndPearsonIV +!======================================================================= +SUBROUTINE RndpkCTKE_WFTA( p, OtherSt, RandNum ) +! Calculates a deviate from a distribution with pdf: +! f(x) = (a + c*x^2 + e*x^4)/(1. + b*x^2 + d*x^4 + f*x^6), where + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +!67m and 85m +REAL(ReKi), PARAMETER :: A = 0.30985506 +REAL(ReKi), PARAMETER :: B = 0.006902104 +REAL(ReKi), PARAMETER :: C =-0.00206008 +REAL(ReKi), PARAMETER :: D = 1.28884E-05 +REAL(ReKi), PARAMETER :: E = 5.71475E-06 +REAL(ReKi), PARAMETER :: F = 8.70606E-07 + +REAL(ReKi) :: fMAX ! Max(f(x)) = f(MinVALUE) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi), PARAMETER :: MaxVALUE = 22. ! Maximum value of returned variate +REAL(ReKi), PARAMETER :: MinVALUE = 4. ! Minimum value of returned variate +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method +REAL(ReKi) :: x2 ! A temp variable for x^2 + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + + +x2 = MinVALUE**2 +fMAX = (A + C*x2 + E*x2**2)/(1.0 + B*x2 + D*x2**2 + F*x2**3) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + x2 = RandNum**2 + Gx = (A + C*x2 + E*x2**2)/(1.0 + B*x2 + D*x2**2 + F*x2**3) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + +END SUBROUTINE RndpkCTKE_WFTA +!======================================================================= +SUBROUTINE RndPolyFit( p, OtherSt, RandNum, Coeffs, FnRange, fMAX) +!bjj: 15-jul-2014: no longer used +! Calculates a deviate from a distribution with pdf: +! f(x) = (Coeffs(1) + Coeffs(3)*x + Coeffs(5)*x^2 + Coeffs(7)*x^3 + Coeffs(9)*x^4 + Coeffs(11)*x^5) / & +! ( 1. + Coeffs(2)*x + Coeffs(4)*x^2 + Coeffs(6)*x^3 + Coeffs(8)*x^4 + Coeffs(10)*x^5) +! This equation covers the following (plus others) from Table Curve\SysStat: +! Eqn 7906, Eqn 7907, Eqn 7908, & Eqn 7909 + + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + + +REAL(ReKi), INTENT(IN) :: Coeffs(11) +REAL(ReKi), INTENT(IN) :: FnRange(2) + +REAL(ReKi), INTENT(IN) :: fMAX ! Max(f(x)) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi) :: MaxVALUE ! Maximum value of returned variate +REAL(ReKi) :: MinVALUE ! Minimum value of returned variate +REAL(ReKi), INTENT(OUT) :: RandNum ! numbers distributed with the pdf above +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +MaxVALUE = MAX(FnRange(1),FnRange(2)) +MinVALUE = MIN(FnRange(1),FnRange(2)) + + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + Gx = (Coeffs(1) + Coeffs(3)*RandNum + Coeffs(5)*RandNum**2 + Coeffs( 7)*RandNum**3 + & + Coeffs(9)*RandNum**4 + Coeffs(11)*RandNum**5 ) / & + ( 1. + Coeffs(2)*RandNum + Coeffs(4)*RandNum**2 + Coeffs( 6)*RandNum**3 + & + Coeffs(8)*RandNum**4 + Coeffs(10)*RandNum**5 ) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + + +END SUBROUTINE RndPolyFit +!======================================================================= +SUBROUTINE RndTcohLLJ( p, OtherSt, RandNum, Height ) +! Calculates a deviate from a distribution with pdf: +! f(x) = EXP(A + B*SQRT(x) + C*LOG(x) ) !Eqn 1376 + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT( OUT) :: RandNum ! numbers distributed with the pdf above + + +!67m and 85m +REAL(ReKi), PARAMETER :: A(2) = (/ -1.34064396 , -1.17577736 /) +REAL(ReKi), PARAMETER :: B(2) = (/ -0.26996911 , -0.23056567 /) +REAL(ReKi), PARAMETER :: C(2) = (/ -0.57793906 , -0.69871145 /) + +REAL(ReKi) :: fMAX ! Max(f(x)) = f(MinValue) +REAL(ReKi) :: Gx ! The function g(x) = f(x)/fMAX +REAL(ReKi) :: Height ! The height of the center of the billow, in meters +REAL(ReKi), PARAMETER :: MaxVALUE = 600. ! Maximum value of returned variate +REAL(ReKi), PARAMETER :: MinVALUE = 2.5 ! Minimum value of returned variate +REAL(ReKi) :: RN ! A random number for the acceptance-rejection method + +INTEGER :: Count +INTEGER :: Indx +INTEGER, PARAMETER :: MaxIter = 10000 ! Max number of iterations to converge (so we don't get an infinite loop) + +IF (Height < 76) THEN + Indx = 1 +ELSE + Indx = 2 +ENDIF + +fMAX = EXP(A(Indx) + B(Indx)*SQRT(MinVALUE) + C(Indx)*LOG(MinVALUE) ) + +Count = 1 + + ! Generate a normal distribution on (0,1) from a uniform distribution ( ACTUALLY [0,1) ) + +DO WHILE (Count < MaxIter) + + CALL RndUnif( p, OtherSt, RN ) ! Generate RN from U(0,1) + CALL RndUnif( p, OtherSt, RandNum ) ! Generate RandNum from h(y) = 1 / (MaxVALUE - MinVALUE) + RandNum = RandNum*(MaxVALUE-MinVALUE)+MinVALUE; + + Gx = EXP(A(Indx) + B(Indx)*SQRT(RandNum) + C(Indx)*LOG(RandNum) ) + Gx = Gx / fMAX + + IF ( RN <= Gx ) THEN + Count = MaxIter ! Let's keep this deviate + ELSE + Count = Count + 1 ! try again + RandNum = -1 + ENDIF + +ENDDO + + +END SUBROUTINE RndTcohLLJ +!======================================================================= +SUBROUTINE RndTcoh_WF( p, OtherSt, RandNum, SpecModel ) + + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation +REAL(ReKi), INTENT( OUT) :: RandNum ! numbers distributed with the pdf above +INTEGER(IntKi), INTENT(IN ) :: SpecModel ! unique number identifying the spectral model being used + +REAL(ReKi) :: FnRange( 2) ! the min and max values of the returned deviate +REAL(ReKi) :: ParmsLN( 4) ! parameters for the 4-parameter Log-Norm function +REAL(ReKi) :: ParmsPIV(5) ! parameters for the Pearson IV function + + +SELECT CASE ( SpecModel ) + CASE ( SpecModel_WF_UPW ) + ParmsLN = (/ 0.0, 0.132537201, 0.348791907, 1.781668096 /) !parm(1) = 0 b/c there's no offset... it's a 3-parameter function + FnRange = (/ 0.4, 200.0 /) + + CALL Rnd4ParmLogNorm( p, OtherSt, RandNum, ParmsLN, FnRange ) + + CASE ( SpecModel_WF_07D ) + ParmsPIV = (/ 0.108721975, 5.705449915, 2.769408844, 0.475906651, 1.067616671 /) + FnRange = (/ 0.6, 30.0 /) + + CALL RndPearsonIV( p, OtherSt, RandNum, ParmsPIV, FnRange ) + + CASE ( SpecModel_WF_14D ) + ParmsPIV = (/ 0.080526074, 13.51637204, 6.391924365, 1.197332751, 0.390220799 /) + FnRange = (/ 5.0, 40.0 /) + + CALL RndPearsonIV( p, OtherSt, RandNum, ParmsPIV, FnRange ) + +END SELECT + +END SUBROUTINE RndTcoh_WF +!======================================================================= +SUBROUTINE RndUnif( p, OtherSt, RandUnifNum ) + +!This subroutine produces uniformly distributed random numbers, based on +!the pRNG that is requested in TurbSim's input file. This routine assumes +!that the random number generator has been initialized earlier in the main +!program. + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN) :: p ! parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt ! other states for random number generation + +REAL(ReKi), INTENT(OUT) :: RandUnifNum ! Uniformly distributed numbers +REAL(ReKi) :: RN(1) + +IF ( p%pRNG == pRNG_INTRINSIC ) THEN !RNG_type == 'NORMAL' + + CALL RANDOM_NUMBER( RN ) + +ELSEIF (p%pRNG == pRNG_RANLUX) THEN !RNG_type == 'RANLUX' + + CALL RanLux ( RN ) + +ELSE + + CALL ARand( OtherSt%NextSeed(1), RN, 1, 1) + +ENDIF + + +RandUnifNum = RN(1) + + +END SUBROUTINE RndUnif + +!====================================================================== +SUBROUTINE RndPhases(p, OtherSt, PhaseAngles, NPoints, NumFreq, US, ErrStat, ErrMsg) + + +IMPLICIT NONE + +TYPE(RandNum_ParameterType), INTENT(IN ) :: p !< parameters for random number generation +TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt !< other states for random number generation +INTEGER(IntKi) , INTENT(IN) :: US !< unit number of file in which to print a summary of the scaling used. If < 1, will not print summary. +INTEGER(IntKi) , INTENT(OUT) :: ErrStat !< error level/status +CHARACTER(*) , INTENT(OUT) :: ErrMsg !< error message + +INTEGER(IntKi) , INTENT(IN ) :: NPoints !< number of points being simulated +INTEGER(IntKi) , INTENT(IN ) :: NumFreq !< number of frequencies being simulated + +REAL(ReKi) , INTENT( OUT) :: PhaseAngles(NPoints,NumFreq,3) !< random phases + +! local variables + +REAL(ReKi), ALLOCATABLE :: RandNum(:) ! contains the uniformly-distributed random numbers for all the points and frequencies + +INTEGER(IntKi) :: Indx ! holds the next index in the RandNum array for the SNLWnd3d generator +INTEGER(IntKi) :: IVec ! loop counter (=number of wind components = 3) +INTEGER(IntKi) :: IFreq ! loop counter (=number of frequencies) +INTEGER(IntKi) :: J ! loop counter (=number of points on grid) +INTEGER(IntKi) :: NumPointsFreq ! number of points * number of frequency, or 1/3 the size of RandNum + +INTEGER :: LuxLevelOut, InitSeed +CHARACTER(20) :: NextSeedText + + +! get the uniformly distributed random numbers: + + + CALL AllocAry( RandNum, SIZE(PhaseAngles), 'RandNum', ErrStat, ErrMsg ) + + + ! Reinitialize the random number generator ( it was initialized when the + ! seeds were read in ) so that the same seed always generates the same + ! random phases, regardless of previous randomizations in this code. + + CALL RandNum_Init(p, OtherSt, ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + ! Let's go ahead and get all the random numbers we will need for the entire + ! run. This (hopefully) will be faster than getting them one at a time, + ! but it will use more memory. + ! These pRNGs have been initialized in the GetInput() subroutine + + IF ( p%pRNG == pRNG_INTRINSIC ) THEN ! RNG_type == 'NORMAL' + + !The first two real numbers in the RandSeed array are used as seeds + !The number of seeds needed are compiler specific, thus we can't assume only 2 seeds anymore + + CALL RANDOM_NUMBER ( RandNum ) + + ! Let's harvest the random seeds so that they can be used for the next run if desired. + ! Write them to the summary file. + + CALL RANDOM_SEED ( GET = OtherSt%nextSeed(:) ) ! bjj: 16-jul-2014: without the (:), I get an "internal compiler error" here using Intel(R) Visual Fortran Compiler XE 12.1.3.300 [Intel(R) 64] + + NextSeedText = ' Harvested seed #' + + ELSEIF ( p%pRNG == pRNG_RANLUX ) THEN ! RNG_type == 'RANLUX' + + CALL RanLux ( RandNum ) + + CALL RLuxAT ( LuxLevelOut, InitSeed, OtherSt%nextSeed(1), OtherSt%nextSeed(2) ) !luxury level, seed, nextSeed + + !InitSeed = p%RandSeed(1)???? + NextSeedText = ' K' + + ELSE + + NumPointsFreq = NPoints*NumFreq + + Indx = 1 + DO IVec = 1,3 ! 3 wind components + CALL ARand( OtherSt%nextSeed(IVec), RandNum, NumPointsFreq, Indx) + Indx = Indx + NumPointsFreq + ENDDO + + NextSeedText = ' Next seed #' + + ENDIF + +! set them to the range 0-2pi and +! sort them so we get the same random numbers as previous versions of TurbSim + + DO IVec = 1,3 + DO IFreq = 1,NumFreq + DO J=1,NPoints + Indx = IFreq + (J-1)*NumFreq + (IVec-1)*NPoints*NumFreq ! This sorts the random numbers as they were done previously + + PhaseAngles(J,IFreq,IVec) = TwoPi*RandNum(Indx) + ENDDO ! J + ENDDO !IFreq + ENDDO !IVec + + call cleanup() + + IF ( US > 0 ) THEN + + WRITE(US,"(//,'Harvested Random Seeds after Generation of the Random Numbers:',/)") + + DO J = 1,SIZE( OtherSt%nextSeed ) + WRITE(US,"(I13,A,I2)") OtherSt%nextSeed(J), TRIM(NextSeedText), J + END DO + + END IF + +contains + subroutine cleanup() + IF (ALLOCATED(RandNum)) DEALLOCATE(RandNum) + end subroutine cleanup + +END SUBROUTINE RndPhases +!======================================================================= + + +END MODULE TS_RandNum diff --git a/OpenFAST/modules/turbsim/src/Root_Searching.f90 b/OpenFAST/modules/turbsim/src/Root_Searching.f90 new file mode 100644 index 000000000..bd01c5ca7 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/Root_Searching.f90 @@ -0,0 +1,98 @@ +MODULE NEWTON_MOD +IMPLICIT NONE +PUBLIC :: F, FP +CONTAINS +!============================================================================== +FUNCTION F(X,URef,RefHt,HubHt) RESULT (Y) +USE NWTC_Library +REAL(ReKi), INTENT(IN) :: X +!REAL(ReKi), INTENT(IN) :: V_10 +REAL(ReKi), INTENT(IN) :: URef +REAL(ReKi), INTENT(IN) :: RefHt +REAL(ReKi), INTENT(IN) :: HubHt +REAL(ReKi) :: Y +REAL(ReKi) :: C_1 +REAL(ReKi) :: C_2 +REAL(ReKi) :: D_1 +REAL(ReKi) :: D_2 +REAL(ReKi) :: D_3 +REAL(ReKi) :: D_4 + +IF ( EqualRealNos( RefHt, 10.0_ReKi ) ) THEN + C_1=1.0-0.41*0.06*LOG(600.0/3600.0) + C_2=0.41*0.06*0.043*LOG(600.0/3600.0) + Y=C_1*X-C_2*X*X-URef +ELSEIF ( EqualRealNos( RefHt, HubHt) ) THEN + D_1=1.0-0.41*0.06*LOG(600.0/3600.0)*(RefHt/10.0)**(-0.22) + D_2=0.41*0.06*0.043*LOG(600.0/3600.0)*(RefHt/10.0)**(-0.22) + D_3=D_1*0.0573*LOG(RefHt/10.0) + D_4=D_2*0.0573*LOG(RefHt/10.0) + Y=D_1*X-D_2*X*X+D_3*X*(1.0+0.15*X)**0.5-D_4*X*X*(1.0+0.15*X)**0.5-URef +ELSE + Y = -9999999 +ENDIF + +END FUNCTION F +!============================================================================== +FUNCTION FP(X,URef,RefHt,HubHt) RESULT (Y) +USE NWTC_Library +REAL(ReKi), INTENT(IN) :: X +REAL(ReKi), INTENT(IN) :: URef +REAL(ReKi), INTENT(IN) :: RefHt +REAL(ReKi), INTENT(IN) :: HubHt +REAL(ReKi) :: Y +REAL(ReKi) :: C_1 +REAL(ReKi) :: C_2 +REAL(ReKi) :: D_1 +REAL(ReKi) :: D_2 +REAL(ReKi) :: D_3 +REAL(ReKi) :: D_4 + +IF ( EqualRealNos( RefHt, 10.0_ReKi ) ) THEN + C_1 = 1.0-0.41*0.06*LOG(600.0/3600.0) + C_2 = 0.41*0.06*0.043*LOG(600.0/3600.0) + Y = C_1-2.0*C_2*X +ELSEIF ( EqualRealNos( RefHt, HubHt) ) THEN + C_1 = 1.0 - 0.41 * 0.06 * LOG(600.0/3600.0) + C_2 = 0.41 * 0.06*0.043 * LOG(600.0/3600.0) + D_1 = 1.0-0.41*0.06*LOG(600.0/3600.0)*(RefHt/10.0)**(-0.22) + D_2 = 0.41*0.06*0.043*LOG(600.0/3600.0)*(RefHt/10.0)**(-0.22) + D_3 = D_1*0.0573*LOG(RefHt/10.0) + D_4 = D_2*0.0573*LOG(RefHt/10.0) + Y = D_1-2.0*D_2*X+D_3*((1.0+0.15*X)**0.5+0.15*X/2.0/(1.0+0.15*X)**0.5) & + -D_4*(2.0*X*(1.0+0.15*X)**0.5+0.15*X*X/2.0/(1.0+0.15*X)**0.5) +ELSE + Y = -9999999 +ENDIF + +END FUNCTION FP +!============================================================================== +END MODULE NEWTON_MOD + + +SUBROUTINE ROOT_SEARCHING(X0,X,URef,RefHt,HubHt) +USE NEWTON_MOD +USE NWTC_Library +IMPLICIT NONE + +REAL(ReKi), PARAMETER :: TOL=1.0E-5 + +REAL(ReKi), INTENT(IN ) :: URef +REAL(ReKi), INTENT(IN ) :: RefHt +REAL(ReKi), INTENT(IN ) :: HubHt +REAL(ReKi), INTENT(IN ) :: X0 +REAL(ReKi), INTENT( OUT) :: X + +X=X0 +DO ! bjj: I'd like this better if there were absolutely no way to have an infinite loop here... + X = X - F(X,URef,RefHt,HubHt) / FP(X,URef,RefHt,HubHt) + IF (ABS(F(X,URef,RefHt,HubHt)) < TOL) THEN + EXIT + END IF + +END DO +END SUBROUTINE ROOT_SEARCHING + + + + \ No newline at end of file diff --git a/OpenFAST/modules/turbsim/src/TS_FileIO.f90 b/OpenFAST/modules/turbsim/src/TS_FileIO.f90 new file mode 100644 index 000000000..1689f5e2f --- /dev/null +++ b/OpenFAST/modules/turbsim/src/TS_FileIO.f90 @@ -0,0 +1,5475 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TS_FileIO + + USE NWTC_Library + + use TS_Profiles + use TSSubs + use TS_RandNum + + IMPLICIT NONE + +CONTAINS + +!======================================================================= +!> This subroutine reads parameters from the primary TurbSim input file. +!> It validates most of the meteorology data (because it is used to +!> calculate default values later in the routine) +SUBROUTINE ReadInputFile(InFile, p, OtherSt_RandNum, ErrStat, ErrMsg) + + + ! This subroutine is used to read parameters from the input file. + + IMPLICIT NONE + + CHARACTER(*), INTENT(IN) :: InFile !< name of the primary TurbSim input file + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim's parameters + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum !< other states for random numbers (next seed, etc) + + + INTEGER(IntKi) , INTENT(OUT) :: ErrStat !< allocation status + CHARACTER(*) , INTENT(OUT) :: ErrMsg !< error message + + + + ! Local variables + + REAL(ReKi) :: InCVar (2) ! Contains the coherence parameters (used for input) + REAL(ReKi) :: tmp ! variable for estimating Ustar and calculating wind speeds + REAL(ReKi) :: TmpUary (3) !Temporary vector to store windSpeed(z) values + REAL(ReKi) :: TmpUstar(3) !Temporary vector to store ustar(z) values + REAL(ReKi) :: TmpUstarD !Temporary ustarD value + REAL(ReKi) :: RotorDiskHeights (3) !Temporary vector to store height(z) values + REAL(ReKi) :: TmpZLary(3) !Temporary vector to store zL(z) values + + INTEGER :: TmpIndex ! Contains the index number when searching for substrings + INTEGER :: UI ! I/O unit for input file + INTEGER :: UnEc ! I/O unit for echo file + + LOGICAL :: getDefaultPLExp ! Whether a default PLExp needs to be calculated + LOGICAL :: getDefaultURef ! Whether a default URef needs to be calculated + LOGICAL :: getDefaultZJetMax ! Whether a default ZJetMax needs to be calculated + + LOGICAL :: Randomize ! Whether to randomize the coherent turbulence scaling + LOGICAL :: UseDefault ! Whether or not to use a default value + LOGICAL :: IsUnusedParameter ! Whether or not this variable will be ignored + + CHARACTER(200) :: Line ! An input line + CHARACTER(1) :: Line1 ! The first character of an input line + + INTEGER(IntKi) :: ErrStat2 ! Temporary Error status + INTEGER(IntKi) :: I ! Loop counter (number of times file has been read) + + LOGICAL :: Echo ! Determines if an echo file should be written + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Temporary Error message + CHARACTER(1024) :: PriPath ! Path name of the primary file + + CHARACTER(1024) :: UserFile ! Name of file containing user-defined spectra or time-series files + CHARACTER(1024) :: ProfileFile ! Name of the file containing profile data for user-defined velocity profiles and/or USRVKM model + CHARACTER(*), PARAMETER :: RoutineName = 'ReadInputFile' + + ! Initialize some variables: + ErrStat = ErrID_None + ErrMsg = "" + + p%met%NumUSRz = 0 ! initialize the number of points in a user-defined wind profile + + + UnEc = -1 + Echo = .FALSE. + CALL GetPath( InFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + + !=============================================================================================================================== + ! Open input file + !=============================================================================================================================== + + CALL GetNewUnit( UI, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL OpenFInpFile( UI, InFile, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL WrScr1(' Reading the input file "'//TRIM(InFile)//'".' ) + + ! Read the lines up/including to the "Echo" simulation control variable + ! If echo is FALSE, don't write these lines to the echo file. + ! If Echo is TRUE, rewind and write on the second try. + + I = 1 !set the number of times we've read the file + DO + !-------------------------- HEADER --------------------------------------------- + + + !=============================================================================================================================== + ! Read the runtime options. + !=============================================================================================================================== + + CALL ReadCom( UI, InFile, "File Heading Line 1", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "File Heading Line 2", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Runtime Options Heading",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadVar( UI, InFile, Echo, 'Echo', 'Echo switch', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop + + ! Otherwise, open the echo file, then rewind the input file and echo everything we've read + + I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) + + + CALL OpenEcho ( UnEc, TRIM(p%RootName)//'.ech', ErrStat2, ErrMsg2, TurbSim_Ver ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(TurbSim_Ver%Name)//' primary input file "'//TRIM( InFile )//'":' + + REWIND( UI, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InFile)//'".', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + END DO + + + + ! RandSeed(1) + CALL ReadVar( UI, InFile, p%RNG%RandSeed(1), "RandSeed(1)", "Random seed #1",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! RandSeed(2) + CALL ReadVar( UI, InFile, Line, "RandSeed(2)", "Random seed #2",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Check if alternate random number generator is to be used >>>>>>>>>>>>>>>> + + READ (Line,*,IOSTAT=ErrStat2) Line1 ! check the first character to make sure we don't have T/F, which can be interpreted as 1/-1 or 0 in Fortran + + CALL Conv2UC( Line1 ) + IF ( (Line1 == 'T') .OR. (Line1 == 'F') ) THEN + CALL SetErrStat( ErrID_Fatal, ' RandSeed(2): Invalid RNG type.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + ENDIF + + READ (Line,*,IOSTAT=ErrStat2) p%RNG%RandSeed(2) + + IF (ErrStat2 == 0) THEN ! the user entered a number + p%RNG%RNG_type = "NORMAL" + p%RNG%pRNG = pRNG_INTRINSIC + ELSE + + p%RNG%RNG_type = ADJUSTL( Line ) + CALL Conv2UC( p%RNG%RNG_type ) + + IF ( p%RNG%RNG_type == "RANLUX") THEN + p%RNG%pRNG = pRNG_RANLUX + ELSE IF ( p%RNG%RNG_type == "RNSNLW") THEN + p%RNG%pRNG = pRNG_SNLW3 + ELSE + CALL SetErrStat( ErrID_Fatal, ' RandSeed(2): Invalid alternative random number generator.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + ENDIF + + ENDIF + + !<<<<<<<<<<<<<<<<<<<<<< end rng + + + ! --------- Read the flag for writing the binary HH (GenPro) turbulence parameters. ------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_BIN), "WrBHHTP", "Output binary HH turbulence parameters? [RootName.bin]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! --------- Read the flag for writing the formatted turbulence parameters. ---------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_DAT), "WrFHHTP", "Output formatted turbulence parameters? [RootName.dat]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing the AeroDyn HH files. ------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_HH), "WrADHH", "Output AeroDyn HH files? [RootName.hh]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing the AeroDyn FF files. --------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_BTS), "WrADFF", "Output AeroDyn FF files? [RootName.bts]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing the BLADED FF files. ----------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_WND) , "WrBLFF", "Output BLADED FF files? [RootName.wnd]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing the AeroDyn tower files. -------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_TWR), "WrADTWR", "Output tower data? [RootName.twr]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing the formatted FF files. --------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_UVW), "WrFMTFF", "Output formatted FF files? [RootName.u, .v, .w]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for writing coherent time series files. -------------------------------------- + CALL ReadVar( UI, InFile, p%WrFile(FileExt_CTS), "WrACT", "Output coherent time series files? [RootName.cts]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for turbine rotation. ----------------------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%Clockwise, "Clockwise", "Clockwise rotation when looking downwind?",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ---------- Read the flag for determining IEC scaling ----------------------------------------------------- + CALL ReadVar( UI, InFile, p%IEC%ScaleIEC, "ScaleIEC", "Scale IEC turbulence models to specified standard deviation?",& + ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! we'll check the errors before going to the next section of the input file + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !=============================================================================================================================== + ! Read the turbine/model specifications. + !=============================================================================================================================== + + CALL ReadCom( UI, InFile, "Turbine/Model Specifications Heading Line 1",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Turbine/Model Specifications Heading Line 2",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the vertical matrix dimension. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%NumGrid_Z, "NumGrid_Z", "Vertical grid-point matrix dimension [-]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the lateral matrix dimension. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%NumGrid_Y, "NumGrid_Y", "Horizontal grid-point matrix dimension [-]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the time step. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%TimeStep, "TimeStep", "Time step [seconds]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the analysis time. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%AnalysisTime, "AnalysisTime", "Analysis time [seconds]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the usable time. --------------------------------------------- + CALL ReadVar( UI, InFile, Line, "UsableTime", "Usable output time [seconds]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Check if usable time is "ALL" (for periodic files) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + READ( Line, *, IOSTAT=ErrStat2) p%grid%UsableTime + + IF ( ErrStat2 /= 0 ) THEN ! Line didn't contain a number + CALL Conv2UC( Line ) + IF ( TRIM(Line) == 'ALL' ) THEN + p%grid%Periodic = .TRUE. + p%grid%UsableTime = p%grid%AnalysisTime + ELSE + CALL SetErrStat( ErrID_Fatal, 'The usable output time must be a number greater than zero (or the string "ALL").', & + ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + ELSE + p%grid%Periodic = .FALSE. + END IF + ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end check for UsableTime = "ALL" (periodic) + + ! ------------ Read in the hub height. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%HubHt, "HubHt", "Hub height [m]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the grid height. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%GridHeight, "GridHeight", "Grid height [m]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the grid width. --------------------------------------------- + CALL ReadVar( UI, InFile, p%grid%GridWidth, "GridWidth", "Grid width [m]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the vertical flow angle. --------------------------------------------- + CALL ReadVar( UI, InFile, p%met%VFlowAng, "VFlowAng", "Vertical flow angle [degrees]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the horizontal flow angle. --------------------------------------------- + CALL ReadVar( UI, InFile, p%met%HFlowAng, "HFlowAng", "Horizontal flow angle [degrees]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + +!.................................................................................................................................. +! Do some error checking on the runtime options and turbine/model specifications before we read the meteorology data +!.................................................................................................................................. + + IF ( p%IEC%ScaleIEC > 2 .OR. p%IEC%ScaleIEC < 0 ) CALL SetErrStat( ErrID_Fatal, 'The value for parameter ScaleIEC must be 0, 1, or 2.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%NumGrid_Z < 2 ) CALL SetErrStat( ErrID_Fatal, 'The matrix must be >= 2x2.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%NumGrid_Y < 2 ) CALL SetErrStat( ErrID_Fatal, 'The matrix must be >= 2x2.', ErrStat, ErrMsg, RoutineName) + IF ( 0.5*p%grid%GridHeight > p%grid%HubHt ) CALL SetErrStat( ErrID_Fatal, 'The hub must be higher than half of the grid height.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%GridWidth <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'The grid width must be greater than zero.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%HubHt <= 0.0 ) CALL SetErrStat( ErrID_Fatal, 'The hub height must be greater than zero.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%AnalysisTime <= 0.0 ) CALL SetErrStat( ErrID_Fatal, 'The analysis time must be greater than zero.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%TimeStep <= 0.0 ) CALL SetErrStat( ErrID_Fatal, 'The time step must be greater than zero.', ErrStat, ErrMsg, RoutineName) + IF ( ABS( p%met%VFlowAng ) > 45.0 ) CALL SetErrStat( ErrID_Fatal, 'The vertical flow angle must not exceed +/- 45 degrees.', ErrStat, ErrMsg, RoutineName) + IF ( p%grid%UsableTime <= 0.0 ) CALL SetErrStat( ErrID_Fatal, 'The usable output time must be a number greater than zero'& + //' or the string "ALL".', ErrStat, ErrMsg, RoutineName) + +!.................................................................................................................................. +! initialize secondary parameters that will be used to calculate default values in the meteorological boundary conditions section +!.................................................................................................................................. + ! Initialize the RNG (for computing "default" values that contain random variates) + CALL RandNum_Init(p%RNG, OtherSt_RandNum, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ***** Calculate the diameter of the rotor disk ***** + p%grid%RotorDiameter = MIN( p%grid%GridWidth, p%grid%GridHeight ) + + ! we'll check the errors before going to the next section of the input file + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !=============================================================================================================================== + ! Read the meteorological boundary conditions. + !=============================================================================================================================== + + CALL ReadCom( UI, InFile, "Meteorological Boundary Conditions Heading Line 1",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Meteorological Boundary Conditions Heading Line 2",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the turbulence model. --------------------------------------------- + CALL ReadVar( UI, InFile, p%met%TurbModel, "TurbModel", "spectral model",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the UserFile------------------- --------------------------------------------- + CALL ReadVar( UI, InFile, UserFile, "UserFile", "Name of the input file for user-defined spectra or time-series inputs",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( PathIsRelative( UserFile ) ) UserFile = TRIM(PriPath)//TRIM(UserFile) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Verify turbulence model is valid (used for default values later) and read supplemental files + ! for user-defined spectra or time-series >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + p%met%TurbModel = ADJUSTL( p%met%TurbModel ) + CALL Conv2UC( p%met%TurbModel ) + + p%met%IsIECModel = .FALSE. + p%usr%nPoints = 0 + SELECT CASE ( TRIM(p%met%TurbModel) ) + CASE ( 'IECKAI' ) + p%met%TMName = 'IEC Kaimal' + p%met%TurbModel_ID = SpecModel_IECKAI + p%met%IsIECModel = .TRUE. + CASE ( 'IECVKM' ) + p%met%TMName = 'IEC von Karman' + p%met%TurbModel_ID = SpecModel_IECVKM + p%met%IsIECModel = .TRUE. + CASE ( 'TIDAL' ) + p%met%TMName = 'Tidal Channel Turbulence' + p%met%TurbModel_ID = SpecModel_TIDAL + CASE ( 'RIVER' ) + p%met%TMName = 'River Turbulence' + p%met%TurbModel_ID = SpecModel_RIVER + CASE ( 'SMOOTH' ) + p%met%TMName = 'RISO Smooth Terrain' + p%met%TurbModel_ID = SpecModel_SMOOTH + CASE ( 'WF_UPW' ) + p%met%TMName = 'NREL Wind Farm Upwind' + p%met%TurbModel_ID = SpecModel_WF_UPW + CASE ( 'WF_07D' ) + p%met%TMName = 'NREL 7D Spacing Wind Farm' + p%met%TurbModel_ID = SpecModel_WF_07D + CASE ( 'WF_14D' ) + p%met%TMName = 'NREL 14D Spacing Wind Farm' + p%met%TurbModel_ID = SpecModel_WF_14D + CASE ( 'NONE' ) + p%met%TMName = 'Steady wind components' + p%met%TurbModel_ID = SpecModel_NONE + CASE ( 'MODVKM' ) + p%met%TMName = 'Modified von Karman' + p%met%TurbModel_ID = SpecModel_MODVKM + p%met%IsIECModel = .TRUE. + CASE ( 'API' ) + p%met%TMName = 'API' + p%met%TurbModel_ID = SpecModel_API + p%met%IsIECModel = .TRUE. + CASE ( 'NWTCUP' ) + p%met%TMName = 'NREL National Wind Technology Center' + p%met%TurbModel_ID = SpecModel_NWTCUP + CASE ( 'GP_LLJ' ) + p%met%TMName = 'Great Plains Low-Level Jet' + p%met%TurbModel_ID = SpecModel_GP_LLJ + CASE ( 'USRVKM' ) + p%met%TMName = 'von Karman model with user-defined specifications' + p%met%TurbModel_ID = SpecModel_USRVKM + CASE ( 'USRINP' ) + p%met%TMName = 'Uniform user-input' + p%met%TurbModel_ID = SpecModel_USER + + CALL GetUSRspec(UserFile, p, UnEc, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CASE ( 'TIMESR' ) + p%met%TMName = 'User-input time series' + p%met%TurbModel_ID = SpecModel_TimeSer + + CALL GetUSRTimeSeries(UserFile, p, UnEc, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat,ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL TimeSeriesToSpectra( p, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat,ErrMsg, RoutineName) + + CASE DEFAULT + !BONNIE: todo: add the UsrVKM model to this list when the model is complete + CALL SetErrStat( ErrID_Fatal, 'The turbulence model must be one of the following: "IECKAI", "IECVKM", "SMOOTH",' & + //' "WF_UPW", "WF_07D", "WF_14D", "NWTCUP", "GP_LLJ", "TIDAL", "RIVER", "API", "USRINP", "TIMESR" "NONE".', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + + END SELECT ! TurbModel + + ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end TurbModel verification + +!bjj: todo: verify that the API model sets the parameters for IECKAI as well (because it's using IECKAI for the v and w components) + + ! ------------ Read in the IEC standard and edition numbers. --------------------------------------------- + CALL ReadVar( UI, InFile, Line, "IECstandard", "Number of the IEC standard",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + ! Process this line for IEC standard & edition & IECeditionStr >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + CALL ProcessLine_IECstandard( Line, p%met%IsIECModel, p%met%TurbModel_ID, p%IEC%IECstandard, p%IEC%IECedition, p%IEC%IECeditionStr, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end processing of IECstandard input variable + + ! ------------ Read in the IEC turbulence characteristic. --------------------------------------------- + CALL ReadVar( UI, InFile, Line, "IECturbc", "IEC turbulence characteristic",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Process this line for NumTurbInp, IECPerTurbInt, IECTurbC, and KHtest >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + CALL ProcessLine_IECTurbc(Line, p%met%IsIECModel, p%IEC%IECstandard, p%IEC%IECedition, p%IEC%IECeditionStr, & + p%IEC%NumTurbInp, p%IEC%IECTurbC, p%IEC%PerTurbInt, p%met%KHtest, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end processing of IECturbc input variable + + ! ------------ Read in the IEC wind turbulence type --------------------------------------------- + CALL ReadVar( UI, InFile, Line, "IEC_WindType", "IEC turbulence type",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! Process this line for IECTurbE, Vref, IEC_WindType, and IEC_WindDes >>>>>>>>>>>>>>>>>>>>>>>>>>>>> + CALL ProcessLine_IEC_WindType(Line, p, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end processing of IEC_WindType input variable + + +!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ! set default ETMc, WindProfileType, Z0, CohExp, and Latitude + ! for use in ReadRVarDefault, ReadRAryDefault, and ReadCVarDefault routines +CALL DefaultMetBndryCndtns(p) ! Requires turbModel (some require RICH_NO, which we'll have to redo later) +!<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + + ! ------------ Read in the ETM c parameter (IEC 61400-1, Ed 3: Section 6.3.2.3, Eq. 19) ---------------------- + CALL ReadRVarDefault( UI, InFile, p%IEC%ETMc, "ETMc", 'IEC Extreme Turbulence Model (ETM) "c" parameter [m/s]', UnEc, & + UseDefault, ErrStat2, ErrMsg2, IGNORE=(p%IEC%IEC_WindType /= IEC_ETM )) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the wind profile type ----------------------------------------------------------------- + CALL ReadCVarDefault( UI, InFile, p%met%WindProfileType, "WindProfileType", "Wind profile type", UnEc, UseDefault, ErrStat2, ErrMsg2) !converts WindProfileType to upper case + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the ProfileFile------------------- --------------------------------------------- + CALL ReadVar( UI, InFile, ProfileFile, "ProfileFile", 'Name of the input file for profiles used with WindProfileType="USR" or TurbModel="USRVKM"',ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( PathIsRelative( ProfileFile ) ) ProfileFile = TRIM(PriPath)//TRIM(ProfileFile) + + ! ------------ Read in the height for the reference wind speed. --------------------------------------------- + CALL ReadVar( UI, InFile, p%met%RefHt, "RefHt", "Reference height [m]",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the reference wind speed. ----------------------------------------------------- + IsUnusedParameter = p%IEC%IEC_WindType > IEC_ETM .OR. INDEX('TU',p%met%WindProfileType(1:1)) > 0 ! p%IEC%IEC_WindType > IEC_ETM == EWM models + CALL ReadRVarDefault( UI, InFile, p%met%URef, "URef", "Reference wind speed [m/s]", UnEc, getDefaultURef, ErrStat2, ErrMsg2, & + IGNORE=IsUnusedParameter ) ! p%IEC%IEC_WindType > IEC_ETM == EWM models + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + getDefaultURef = getDefaultURef .AND. .NOT. IsUnusedParameter + + + ! ------------ Read in the jet height ------------------------------------------------------------- + IsUnUsedParameter = TRIM(p%met%WindProfileType) /= 'JET' + CALL ReadRVarDefault( UI, InFile, p%met%ZJetMax, "ZJetMax", "Jet height [m]", UnEc, getDefaultZJetMax, ErrStat2, ErrMsg2, IGNORE=IsUnusedParameter) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + getDefaultZJetMax = getDefaultZJetMax .AND. .NOT. IsUnusedParameter ! Jet height for + + ! ------------ Read in the power law exponent, PLExp --------------------------------------------- + IsUnusedParameter = (TRIM(p%met%WindProfileType) /= "PL" .AND. TRIM(p%met%WindProfileType) /= "IEC") + CALL ReadRVarDefault( UI, InFile, p%met%PLExp, "PLExp", "Power law exponent [-]", UnEc, getDefaultPLExp, ErrStat2, ErrMsg2, IGNORE=IsUnusedParameter) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + getDefaultPLExp = getDefaultPLExp .AND. .NOT. IsUnusedParameter ! we need RICH_NO before we can calculate a default for this value RICH_NO + + ! ------------ Read in the surface roughness length, Z0 (that's z-zero) --------------------------------------------- + IsUnusedParameter = p%met%TurbModel_ID==SpecModel_TIDAL + CALL ReadRVarDefault( UI, InFile, p%met%Z0, "Z0", "Surface roughness length [m]", UnEc, UseDefault, ErrStat2, ErrMsg2, & + IGNORE=IsUnusedParameter) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +!.................................................................................................................................. +! Do some error checking on the meteorology before we read the non-IEC meteorology data +!.................................................................................................................................. + IF ( p%IEC%IEC_WindType == IEC_ETM .AND. p%IEC%ETMc <= 0. ) CALL SetErrStat( ErrID_Fatal, 'The ETM "c" parameter must be a positive number', ErrStat, ErrMsg, RoutineName) + + ! Make sure WindProfileType is valid for this turbulence model + SELECT CASE ( TRIM(p%met%WindProfileType) ) + CASE ( 'JET' ) + IF ( p%met%TurbModel_ID /= SpecModel_GP_LLJ ) CALL SetErrStat( ErrID_Fatal, 'The jet wind profile is available with the GP_LLJ spectral model only.', ErrStat, ErrMsg, RoutineName) + CASE ( 'LOG') + IF (p%IEC%IEC_WindType /= IEC_NTM ) CALL SetErrStat( ErrID_Fatal, 'The IEC turbulence type must be NTM for the logarithmic wind profile.', ErrStat, ErrMsg, RoutineName) + CASE ( 'PL' ) !this is a valid WindProfileType + CASE ( 'H2L' ) + IF ( p%met%TurbModel_ID /= SpecModel_TIDAL ) CALL SetErrStat( ErrID_Fatal, 'The "H2L" mean profile type can be used with only the "TIDAL" spectral model.', ErrStat, ErrMsg, RoutineName) + CASE ( 'IEC' ) + CASE ( 'USR' ) + !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ! Get parameters for USR wind profile (so that we can use these parameters to get the wind speed later): + CALL GetUSRProfiles( ProfileFile, p%met, UnEc, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + CASE ( 'TS' ) + IF ( p%met%TurbModel_ID /= SpecModel_TimeSer ) CALL SetErrStat( ErrID_Fatal, 'The "TS" mean profile type is valid only with the "TIMESR" spectral model.', ErrStat, ErrMsg, RoutineName) + CASE ( 'API' ) ! ADDED BY Y.GUO +!bjj: I think we need to add some checks here??? MLB has comments about difference between RefHt and HubHt and 10 m + CASE DEFAULT + CALL SetErrStat( ErrID_Fatal, 'The wind profile type must be "JET", "LOG", "PL", "IEC", "USR", "H2L", "TS", or default.' , ErrStat, ErrMsg, RoutineName) + END SELECT + + IF ( p%met%TurbModel_ID == SpecModel_TIDAL .AND. TRIM(p%met%WindProfileType) /= "H2L" ) THEN + p%met%WindProfileType = 'H2L' + CALL SetErrStat( ErrID_Warn, 'Overwriting wind profile type to "H2L" for the "TIDAL" spectral model.', ErrStat, ErrMsg, RoutineName) + ENDIF + + + IF (p%met%KHtest) THEN + IF ( p%met%TurbModel_ID /= SpecModel_NWTCUP ) CALL SetErrStat( ErrID_Fatal, 'The KH test can be used with the "NWTCUP" spectral model only.', ErrStat, ErrMsg, RoutineName) + + IF ( TRIM(p%met%WindProfileType) /= 'IEC' .AND. TRIM(p%met%WindProfileType) /= 'PL' ) THEN + CALL SetErrStat( ErrID_Warn, 'Overwriting wind profile type for the KH test.', ErrStat, ErrMsg, RoutineName) + p%met%WindProfileType = 'IEC' + ENDIF + + IF ( .NOT. p%WrFile(FileExt_CTS) ) THEN + CALL SetErrStat( ErrID_Warn, 'Coherent turbulence time step files must be generated when using the "KHTEST" option.', ErrStat, ErrMsg, RoutineName) + p%WrFile(FileExt_CTS) = .TRUE. + ENDIF + + IF ( .NOT. EqualRealNos(p%met%PLExp, 0.3_ReKi) ) THEN + CALL SetErrStat( ErrID_Warn, 'Overwriting the power law exponent for KH test.', ErrStat, ErrMsg, RoutineName) + p%met%PLExp = 0.3 + ENDIF + END IF + + + IF ( getDefaultURef ) THEN + IF ( p%usr%NPoints > 0 ) THEN + p%met%RefHt = p%usr%pointzi(p%usr%RefPtID) + p%met%URef = p%usr%meanU(p%usr%RefPtID,1) + getDefaultURef = .FALSE. + ELSEIF( TRIM(p%met%WindProfileType) /= 'JET' ) THEN + ! Also note that if we specify a "default for Ustar , we cannot enter "default" for URef. Otherwise, we get circular logic. Will check for that later. + CALL SetErrStat( ErrID_Fatal, 'URef can be "default" for only the "JET" WindProfileType.', ErrStat, ErrMsg, RoutineName) + END IF + END IF + + IF ( p%met%Z0 <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'The surface roughness length must be a positive number or "default".', ErrStat, ErrMsg, RoutineName) + + IF ( TRIM(p%met%WindProfileType) == 'JET' .AND. .NOT. getDefaultZJetMax ) THEN + IF ( p%met%ZJetMax < ZJetMax_LB .OR. p%met%ZJetMax > ZJetMax_UB ) THEN + CALL SetErrStat( ErrID_Fatal, 'The height of the maximum jet wind speed must be between '//TRIM(num2lstr(ZJetMax_LB))//& + ' and '//TRIM(num2lstr(ZJetMax_UB))//' m.', ErrStat, ErrMsg, RoutineName) + ENDIF + ENDIF + + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !................................................. + ! overwrite RefHt and URef for cases where they are unused [USR wind profiles (or TS)] + !................................................. + + ! NOTE: return on abortErrLev before calling getVelocity + IF ( TRIM(p%met%WindProfileType) == 'USR' .OR. TRIM(p%met%WindProfileType) == 'TS') THEN ! for user-defined wind profiles, we overwrite RefHt and URef because they don't mean anything otherwise + ! Calculate URef, which is UHub: + ! note that the 2 "ref" values in the subroutine arguments aren't used for the USR wind profile type. + ! (also, we do not necessarially know PLExp, yet, so we can't call this routine when we have "PL" or "IEC" wind profile types.) + CALL getVelocity(p, p%met%URef, p%met%RefHt, p%met%RefHt, tmp, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !p%met%RefHt = p%grid%HubHt bjj changed this on 23-sep-2014 + p%met%URef = tmp + ELSEIF( p%IEC%IEC_WindType > IEC_ETM ) THEN !i.e., any of the EWM models: IEC_EWM1, IEC_EWM50, IEC_EWM100 + p%met%RefHt = p%grid%HubHt + p%met%URef = p%IEC%VRef + ENDIF + + ! check that RefHt and URef are appropriate values: + IF ( p%met%RefHt <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'The reference height must be greater than zero.', ErrStat, ErrMsg, RoutineName) + IF ( .NOT. getDefaultURef ) THEN + IF ( p%met%URef <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'The reference wind speed must be greater than zero.', ErrStat, ErrMsg, RoutineName) + ENDIF ! Otherwise, we're using a Jet profile with default wind speed (for now it's -999.9) + + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !=============================================================================================================================== + ! Read the meteorological boundary conditions for non-IEC models. + !=============================================================================================================================== + + CALL ReadCom( UI, InFile, "Non-IEC Meteorological Boundary Conditions Heading Line 1", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Non-IEC Meteorological Boundary Conditions Heading Line 2", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the site latitude, LATITUDE --------------------------------------------- + IsUnusedParameter = p%met%IsIECModel .AND. p%met%TurbModel_ID /= SpecModel_MODVKM ! Used to caluculte z0 in ModVKM model; also used for default ZI + CALL ReadRVarDefault( UI, InFile, p%met%Latitude, "Latitude", "Site latitude [degrees]", UnEc, UseDefault, ErrStat2, ErrMsg2, & + IGNORE=IsUnusedParameter) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the gradient Richardson number, RICH_NO --------------------------------------------- + CALL ReadVar( UI, InFile, p%met%Rich_No, "RICH_NO", "Gradient Richardson number",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + +!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + ! Convert RICH_NO input to value that will be used in the code: + + IF ( p%met%KHtest ) THEN + IF ( .NOT. EqualRealNos(p%met%Rich_No, 0.02_ReKi) ) THEN + p%met%Rich_No = 0.02 + CALL SetErrStat( ErrID_Warn, 'Overwriting the Richardson Number for KH test.', ErrStat, ErrMsg, RoutineName) + ENDIF + ELSEIF ( p%met%TurbModel_ID == SpecModel_USRVKM ) THEN + IF ( .NOT. EqualRealNos(p%met%Rich_No, 0.0_ReKi) ) THEN + CALL SetErrStat( ErrID_Warn, 'Overwriting the Richardson Number for the '//TRIM(p%met%TurbModel)//' model.', ErrStat, ErrMsg, RoutineName) + p%met%Rich_No = 0.0 + ENDIF + ELSEIF ( p%met%TurbModel_ID == SpecModel_NWTCUP .OR. p%met%TurbModel_ID == SpecModel_GP_LLJ ) THEN + p%met%Rich_No = MIN( MAX( p%met%Rich_No, -1.0_ReKi ), 1.0_ReKi ) ! Ensure that: -1 <= RICH_NO <= 1 + ELSEIF (p%met%IsIECModel) THEN + p%met%Rich_No = 0.0 ! Richardson Number in neutral conditions + ENDIF + + ! now that we have Rich_No, we can calculate ZL and L + ! necessary for DefaultUStar(p) + CALL Calc_MO_zL(p%met%TurbModel_ID, p%met%Rich_No, p%grid%HubHt, p%met%ZL, p%met%L ) +!<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + ! ------------ Read in the shear/friction velocity, Ustar ------------------------ + CALL ReadRVarDefault( UI, InFile, p%met%Ustar, "UStar", "Friction or shear velocity [m/s]", UnEc, UseDefault, ErrStat2, ErrMsg2, IGNORE=p%met%IsIECModel ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + !IF ( p%met%IsIECModel ) THEN + ! p%met%Ustar = 0.0 ! Shear or friction velocity + !ELSE + IF ( UseDefault ) THEN + IF ( getDefaultURef ) THEN ! This occurs if "default" was entered for both GP_LLJ wind speed and UStar + CALL SetErrStat( ErrID_Fatal, 'The reference wind speed and friction velocity cannot both be "default."', ErrStat, ErrMsg, RoutineName) + ELSE + CALL DefaultUStar(p) + END IF + END IF + !END IF + + +!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ! Calculate Coriolis parameter from latitude ( Used for default ZI ) + p%met%Fc = 2.0 * Omega * SIN( ABS(p%met%Latitude*D2R) ) + + + ! We need the hub-height wind speed to calculate default Reynold's Stresses. + ! We have a few steps to take before we can get that wind speed: + + ! ***** Calculate power law exponent, if needed ***** + IF ( getDefaultPLExp ) p%met%PLExp = DefaultPowerLawExp( p ) + + ! ***** Calculate parameters for Jet profile, if needed ***** + IF ( TRIM(p%met%WindProfileType) == 'JET' ) THEN + IF ( getDefaultZJetMax ) CALL DefaultZJetMax(p, OtherSt_RandNum) ! requires Rich_No, ZL, Ustar + CALL getJetCoeffs( p, getDefaultURef, OtherSt_RandNum, ErrStat2, ErrMsg2) ! getDefault + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + + ! now that we know URef (in case getDefaultURef was true), set UstarDiab (used in ustar profile and default ZI): + p%met%UstarDiab = getUstarDiab(p%met%URef, p%met%RefHt, p%met%z0, p%met%ZL) + + IF (ErrStat >= AbortErrLev) THEN ! just in case we had a fatal error, let's check before calling getVelocity + CALL Cleanup() + RETURN + END IF + + CALL getVelocity(p, p%met%URef, p%met%RefHt, p%grid%HubHt, tmp, ErrStat2, ErrMsg2) + p%UHub = tmp + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! We need the (local) Ustar at the hub-height; while we're at it, we'll + ! calculate the UstarOffset and UstarSlope it uses: + + + ! Set up the heights for the zl- and ustar-profile averages across the rotor disk + RotorDiskHeights = (/ p%grid%HubHt-0.5*p%grid%RotorDiameter, p%grid%HubHt, p%grid%HubHt+0.5*p%grid%RotorDiameter /) + DO TmpIndex = 1,SIZE(RotorDiskHeights) ! set height limits so we don't extrapolate too far + RotorDiskHeights(TmpIndex) = MAX( MIN(RotorDiskHeights(TmpIndex), profileZmax), profileZmin) + ENDDO + + IF (p%met%TurbModel_ID == SpecModel_GP_LLJ ) THEN + p%met%UstarSlope = 1.0_ReKi + + CALL getVelocityProfile(p, p%met%URef, p%met%RefHt, RotorDiskHeights, TmpUary, ErrStat2, ErrMsg2) ! Set TmpUary + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + TmpUstar = getUStarProfile( P, TmpUary, RotorDiskHeights, 0.0_ReKi, p%met%UstarSlope ) ! set offset to 0 here <- + + p%met%UstarOffset = p%met%Ustar - SUM(TmpUstar) / SIZE(TmpUstar) ! Ustar minus the average of those 3 points + TmpUstar(:) = TmpUstar(:) + p%met%UstarOffset + ELSE + p%met%UstarSlope = 1.0_ReKi + + TmpUary = (/ 0.0_ReKi, 0.0_ReKi, 0.0_ReKi /) + TmpUstar = (/ 0.0_ReKi, 0.0_ReKi, 0.0_ReKi /) + + p%met%UstarOffset= 0.0_ReKi + ENDIF + + + ! Get the default mean spatial coherence models + CALL GetDefaultSCMod( p%met%TurbModel_ID, p%met%SCMod ) + + ! Get the default mean Reynolds stresses + ! (requires uHub, Ustar, Rich_No, ZL, TmpUStar) + CALL GetDefaultRS( p, OtherSt_RandNum, TmpUStar(2), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! Default coherence parameters and IEC scaling parameters + CALL CalcIECScalingParams(p%IEC, p%grid%HubHt, p%UHub, p%met%InCDec, p%met%InCohB, p%met%TurbModel_ID, p%met%IsIECModel, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( .NOT. p%met%IsIECModel ) THEN + CALL GetDefaultCoh( p%met%TurbModel_ID, p%met%RICH_NO, p%UHub, p%grid%HubHt, p%met%IncDec, p%met%InCohB ) + END IF + +!<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + ! ------------- Read in the mixing layer depth, ZI --------------------------------------------- + IsUnusedParameter = p%met%ZL >= 0.0_ReKi .AND. p%met%TurbModel_ID /= SpecModel_GP_LLJ ! used for unstable flows; GP_LLJ model may have both stable and unstable flows in its ZL_Profile + CALL ReadRVarDefault( UI, InFile, p%met%ZI, "ZI", "Mixing layer depth [m]", UnEc, UseDefault, ErrStat2, ErrMsg2, IGNORE=IsUnusedParameter ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( IsUnusedParameter ) THEN + p%met%ZI = 999.9_ReKi ! set to a value > 0 that we don't care about + ELSE + IF ( UseDefault ) CALL DefaultMixingLayerDepth(p) + ENDIF + + + ! ----------- Read in the mean hub u'w' Reynolds stress, PC_UW --------------------------------------------- + CALL ReadRVarDefault( UI, InFile, p%met%PC_UW, "PC_UW", "Mean hub u'w' Reynolds stress", UnEc, UseDefault, & + ErrStat2, ErrMsg2, IGNORE=p%met%IsIECModel, IGNORESTR = p%met%UWskip ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the mean hub u'v' Reynolds stress, PC_UV --------------------------------------------- + CALL ReadRVarDefault( UI, InFile, p%met%PC_UV, "PC_UV", "Mean hub u'v' Reynolds stress", UnEc, UseDefault, & + ErrStat2, ErrMsg2, IGNORE=p%met%IsIECModel, IGNORESTR = p%met%UVskip ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the mean hub v'w' Reynolds stress, PC_VW --------------------------------------------- + CALL ReadRVarDefault( UI, InFile, p%met%PC_VW, "PC_VW", "Mean hub v'w' Reynolds stress", UnEc, UseDefault, & + ErrStat2, ErrMsg2, IGNORE=p%met%IsIECModel, IGNORESTR = p%met%VWskip ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + !=============================================================================================================================== + ! Read the spatial coherence model section. + !=============================================================================================================================== + + CALL ReadCom( UI, InFile, "Spatial Coherence Models Heading Line 1", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Spatial Coherence Models Heading Line 2", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read in the spatial coherence models, SCMod(1), SCMod(2), SCMod(3). --------------------------------------------- + + DO I=1,3 + CALL ReadCVarDefault ( UI, InFile, Line, "SCMod"//TRIM(Num2LStr(I)), Comp(I)//"-component coherence model", UnEc, UseDefault, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( .NOT. UseDefault ) THEN + SELECT CASE ( TRIM(Line) ) + CASE("GENERAL") + p%met%SCMod(I) = CohMod_GENERAL + CASE ("IEC") + p%met%SCMod(I) = CohMod_IEC + CASE ("NONE") + p%met%SCMod(I) = CohMod_NONE + CASE ("API") + p%met%SCMOD(I) = CohMod_API + IF (I /= 1) CALL SetErrStat( ErrID_Fatal, "API coherence model is valid only for the u-component", ErrStat, ErrMsg, RoutineName) + CASE DEFAULT + p%met%SCMod(I) = CohMod_NONE + IF (I==1) THEN + CALL SetErrStat( ErrID_Fatal, 'Unknown value for SCMod'//TRIM(Num2LStr(I))//'. Valid entries are "GENERAL","IEC","API", or "NONE".', ErrStat, ErrMsg, RoutineName) + ELSE + CALL SetErrStat( ErrID_Fatal, 'Unknown value for SCMod'//TRIM(Num2LStr(I))//'. Valid entries are "GENERAL","IEC", or "NONE".', ErrStat, ErrMsg, RoutineName) + END IF + END SELECT + END IF + END DO + + ! ------------ Read in the u component coherence parameters, InCDec(1) and InCohB(1) ------------ + CALL ReadRAryDefault( UI, InFile, InCVar, "InCDec1", "u-component coherence parameters", UnEc, UseDefault, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( .NOT. UseDefault ) THEN + p%met%InCDec(1) = InCVar(1) + p%met%InCohB(1) = InCVar(2) + END IF + + ! ------------ Read in the v component coherence parameters, InCDec(2) and InCohB(2) ---------- + CALL ReadRAryDefault( UI, InFile, InCVar, "InCDec2", "v-component coherence parameters", UnEc, UseDefault, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( .NOT. UseDefault ) THEN ! these are the values we just read in + p%met%InCDec(2) = InCVar(1) + p%met%InCohB(2) = InCVar(2) + END IF + + ! ------------ Read in the w component coherence parameters, InCDec(3) and InCohB(3) ------- + CALL ReadRAryDefault( UI, InFile, InCVar, "InCDec3", "w-component coherence parameters", UnEc, UseDefault, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( .NOT. UseDefault ) THEN + p%met%InCDec(3) = InCVar(1) + p%met%InCohB(3) = InCVar(2) + END IF + + ! ------------ Read in the coherence exponent, COHEXP ----------------------------------- + CALL ReadRVarDefault( UI, InFile, p%met%CohExp, "CohExp", "Coherence exponent", UnEc, UseDefault, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + +!.................................................................................................................................. +! Do some error checking on the non-IEC meteorology data and coherence +!.................................................................................................................................. + + IF ( .NOT. p%met%IsIECModel ) THEN + IF ( ABS(p%met%Latitude) < 5.0 .OR. ABS(p%met%Latitude) > 90.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The latitude must be between -90 and 90 degrees but not between -5 and 5 degrees.', ErrStat, ErrMsg, RoutineName) + ENDIF + + IF (p%met%Ustar <= 0.0_ReKi) CALL SetErrStat( ErrID_Fatal, 'The friction velocity must be a positive number.', ErrStat, ErrMsg, RoutineName) + IF ( p%met%ZI <= 0.0_ReKi) CALL SetErrStat( ErrID_Fatal, 'The mixing layer depth must be a positive number for unstable flows.', ErrStat, ErrMsg, RoutineName) + END IF + + IF ( p%met%COHEXP < 0.0_ReKi) CALL SetErrStat( ErrID_Fatal, 'The coherence exponent must be non-negative.', ErrStat, ErrMsg, RoutineName) + + DO I = 1,3 + IF ( p%met%InCDec(I) <= 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'The '//Comp(I)//'-component coherence decrement must be a positive number.', ErrStat, ErrMsg, RoutineName) + END DO + +!.................................................................................................................................. +! Calculate zlOffset +! Adjust UstarSlope and UstarOffset based on entered PC_UW +!.................................................................................................................................. + TmpZLary = getZLProfile(TmpUary, RotorDiskHeights, p%met%Rich_No, p%met%ZL, p%met%L, 0.0_ReKi, p%met%WindProfileType) + p%met%zlOffset = p%met%ZL - SUM(TmpZLary) / SIZE(TmpZLary) + + ! Modify previously calculated UstarSlope and UstarOffset based on our input (target) Reynolds' stress values + IF (.NOT. p%met%UWskip) THEN + TmpUstarD = ( TmpUstar(1)- 2.0*TmpUstar(2) + TmpUstar(3) ) + + IF ( .NOT. EqualRealNos( TmpUstarD, 0.0_ReKi ) ) THEN + p%met%UstarSlope = 3.0*(p%met%Ustar - SQRT( ABS(p%met%PC_UW) ) ) / TmpUstarD + p%met%UstarOffset = SQRT( ABS(p%met%PC_UW) ) - p%met%UstarSlope*(TmpUstar(2) - p%met%UstarOffset) + ELSE + p%met%UstarSlope = 0.0 + p%met%UstarOffset = SQRT( ABS(p%met%PC_UW) ) + ENDIF + ENDIF + + + + !=============================================================================================================================== + ! Read the Coherent Turbulence Scaling Parameters, if necessary. + !=============================================================================================================================== +IF ( .NOT. p%met%IsIECModel ) THEN + + IF ( p%WrFile(FileExt_CTS) ) THEN + + CALL ReadCom( UI, InFile, "Coherent Turbulence Scaling Parameters Heading Line 1", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadCom( UI, InFile, "Coherent Turbulence Scaling Parameters Heading Line 2", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + ! ------------ Read the name of the path containg event file definitions, CTEventPath -------------------------- + + CALL ReadVar( UI, InFile, p%CohStr%CTEventPath, "CTEventPath", "Coherence events path",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL ReadVar( UI, InFile, Line, "CTEventFile", "Event file type",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + IF ( p%met%KHtest ) THEN + + p%CohStr%CText = 'les' + p%CohStr%CTEventFile = TRIM(p%CohStr%CTEventPath)//PathSep//'Events.xtm' + + CALL WrScr( ' LES events will be used for the KH test.' ) + + ELSE + + p%CohStr%CText = Line !This will preserve the case formatting, in case it matters. + + CALL Conv2UC( Line ) + + IF (Line(1:6) == "RANDOM") THEN + CALL RndUnif( p%RNG, OtherSt_RandNum, tmp ) + + IF ( tmp <= 0.5 ) THEN + p%CohStr%CText = 'les' + ELSE + p%CohStr%CText = 'dns' + ENDIF + ENDIF + + p%CohStr%CTEventFile = TRIM(p%CohStr%CTEventPath)//PathSep//'Events.'//TRIM(p%CohStr%CText) + + ENDIF + + + ! ------------ Read the Randomization Flag, Randomize ----------------------------------- + CALL ReadVar( UI, InFile, Randomize, "Randomize", "Randomize CT Scaling",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read the Disturbance Scale, DistScl --------------------------------------------- + CALL ReadVar( UI, InFile, p%CohStr%DistScl, "DistScl", "Disturbance scale",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read the Lateral Fractional Location of tower centerline in wave, CTLy ---------- + CALL ReadVar( UI, InFile, p%CohStr%CTLy, "CTLy", "Location of tower centerline",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! ------------ Read the Vertical Fraction Location of hub in wave, CTLz ------------------------ + CALL ReadVar( UI, InFile, p%CohStr%CTLz, "CTLz", "Location of hub height",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + IF ( p%met%KHtest ) THEN + p%CohStr%DistScl = 1.0 + p%CohStr%CTLy = 0.5 + p%CohStr%CTLz = 0.5 + Randomize = .FALSE. + CALL SetErrStat( ErrID_Info, 'Billow will cover rotor disk for KH test.', ErrStat, ErrMsg, RoutineName) + + ELSEIF ( Randomize ) THEN + + CALL RndUnif( p%RNG, OtherSt_RandNum, tmp ) + + ! Assume a 75% chance of coherent turbulence being the size of the rotor + ! If the rotor is too small, assume a 100% chance. + ! If the turbulence is not the size of the rotor, assume it's half the size + ! of the disk, with equal probablilty of being in the lower or upper half. + + IF ( tmp > 0.25 .OR. p%grid%RotorDiameter <= 30.0 ) THEN + + p%CohStr%DistScl = 1.0 + p%CohStr%CTLy = 0.5 + p%CohStr%CTLz = 0.5 + + ELSE + + p%CohStr%DistScl = 0.5 + p%CohStr%CTLy = 0.5 + + IF ( tmp < 0.125 ) THEN + p%CohStr%CTLz = 0.0 ! The hub is on the bottom of the dataset (i.e. the billow is on the top of the disk) + ELSE + p%CohStr%CTLz = 1.0 ! The hub is on the top of the dataset + ENDIF + + ENDIF + + ELSE !Don't randomize: + + IF ( p%CohStr%DistScl < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The disturbance scale must be a positive.', ErrStat, ErrMsg, RoutineName) + ELSEIF ( p%grid%RotorDiameter <= 30.0 .AND. p%CohStr%DistScl < 1.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The disturbance scale must be at least 1.0 for rotor diameters less than 30.', ErrStat, ErrMsg, RoutineName) + ELSEIF ( p%grid%RotorDiameter*p%CohStr%DistScl <= 15.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The coherent turbulence must be greater than 15 meters in height. '//& + 'Increase the rotor diameter or the disturbance scale. ', ErrStat, ErrMsg, RoutineName) + ENDIF + + ENDIF + + + ! ---------- Read the Minimum event start time, CTStartTime -------------------------------------------- + CALL ReadVar( UI, InFile, p%CohStr%CTStartTime, "CTStartTime", "CTS Start Time",ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + p%CohStr%CTStartTime = MAX( p%CohStr%CTStartTime, 0.0_ReKi ) ! A Negative start time doesn't really make sense... + + ENDIF ! WrFile(FileExt_CTS) + + +ELSE ! IECVKM, IECKAI, MODVKM, OR API models + + IF ( p%IEC%NumTurbInp .AND. EqualRealNos( p%IEC%PerTurbInt, 0.0_ReKi ) ) THEN ! This will produce constant winds, instead of an error when the transfer matrix is singular + p%met%TurbModel = 'NONE' + p%met%TurbModel_ID = SpecModel_NONE + ENDIF + +ENDIF + + + + + ! Done reading the input file. + +CALL Cleanup() + +RETURN +CONTAINS +!......................................... +SUBROUTINE Cleanup() + + IF ( UI > 0 ) CLOSE( UI) + IF ( UnEc > 0 ) CLOSE( UnEc ) + + END SUBROUTINE Cleanup +!......................................... +END SUBROUTINE ReadInputFile +!======================================================================= +SUBROUTINE OpenSummaryFile(RootName, US, DescStr, ErrStat, ErrMsg) + + ! This subroutine is used to open the summary output file. + +IMPLICIT NONE + + INTEGER(IntKi), INTENT(INOUT) :: US ! Unit specifier for summary file + CHARACTER(*), INTENT(IN ) :: RootName ! rootname of the primary TurbSim input file + CHARACTER(*), INTENT( OUT) :: DescStr ! string describing time TurbSim files were generated + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Message describing error + + + + + ! Open summary file. +CALL GetNewUnit( US, ErrStat, ErrMsg ) +CALL OpenFOutFile( US, TRIM( RootName )//'.sum', ErrStat, ErrMsg ) ! Formatted output file +if (ErrStat >= AbortErrLev) then + US = -1 + RETURN +end if + + + + + ! Let's make a string so that the binary file and the full-field file have the same date and time: +DescStr = 'generated by '//TRIM( GetNVD(TurbSim_Ver) )//' on '//CurDate()//' at '//CurTime()//'.' + + ! Write the program name and version, date and time into the summary file. +WRITE (US,"( / 'This summary file was ', A / )") TRIM(DescStr) + + ! Capitalize the first letter of the string and save it for the full-field files. +DescStr = 'This full-field file was '//TRIM(DescStr) + + +RETURN +END SUBROUTINE OpenSummaryFile +!======================================================================= +SUBROUTINE GetUSRProfiles(FileName, p_met, UnEc, ErrStat, ErrMsg) + + IMPLICIT NONE + + TYPE(Meteorology_ParameterType), INTENT(INOUT) :: p_met + INTEGER(IntKi), INTENT(IN ) :: UnEc ! echo file unit number + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Message describing error + CHARACTER(*), INTENT(IN ) :: FileName ! Name of the input file + + + ! local variables + + INTEGER :: U_in ! Input unit. + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + +! CHARACTER(200) :: LINE + + REAL(ReKi) :: L_Usr_Tmp + REAL(ReKi) :: Sigma_USR_Tmp + REAL(ReKi) :: U_USR_Tmp + REAL(ReKi) :: WindDir_USR_Tmp + REAL(ReKi) :: Z_USR_Tmp + + INTEGER :: I + INTEGER :: Indx + INTEGER :: J + + LOGICAL :: ReadSigL ! Whether or not to read the last 2 columns + + + ErrStat = ErrID_None + ErrMsg = "" + + U_in = -1 + CALL GetNewUnit( U_in, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + CALL OpenFInpFile( U_in, FileName, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + IF (ErrStat >= AbortErrLev) THEN + CLOSE(U_in) + RETURN + END IF + + DO I=1,3 + CALL ReadCom( U_in, FileName, "Header line "//trim(num2lstr(I))//" for user-defined profiles", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + END DO + + + ! ---------- Read the size of the arrays -------------------------------------------- + CALL ReadVar( U_in, FileName, p_met%NumUSRz, "NumUSRz", "Number of heights in the user-defined profiles", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + IF ( p_met%NumUSRz < 1 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The number of heights specified in the user-defined profiles must be at least 1.', ErrStat, ErrMsg, 'GetUSRProfiles') + ENDIF + + DO I=1,3 + ! ---------- Read the scaling for the standard deviations -------------------------------------------- + CALL ReadVar( U_in, FileName, p_met%USR_StdScale(I), "USR_StdScale", "Scaling value for user-defined standard deviation profile", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + + IF ( p_met%USR_StdScale(I) <= 0. ) THEN + CALL SetErrStat( ErrID_Fatal, 'The scaling value for the user-defined standard deviation profile must be positive.', ErrStat, ErrMsg, 'GetUSRProfiles') + ENDIF + ENDDO + + ! Allocate the data arrays + CALL AllocAry(p_met%USR_Z, p_met%NumUSRz, 'USR_Z (user-defined height)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrSTat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + CALL AllocAry(p_met%USR_U, p_met%NumUSRz, 'USR_U (user-defined wind speed)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrSTat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + CALL AllocAry(p_met%USR_WindDir, p_met%NumUSRz, 'USR_WindDir (user-defined wind direction)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrSTat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + + IF ( p_met%TurbModel_ID == SpecModel_USRVKM ) THEN + ReadSigL = .TRUE. + + CALL AllocAry(p_met%USR_Sigma, p_met%NumUSRz, 'USR_Sigma (user-defined sigma)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrSTat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + CALL AllocAry(p_met%USR_L, p_met%NumUSRz, 'USR_L (user-defined length scale)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrSTat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + ELSE + ReadSigL = .FALSE. + ENDIF + + IF (ErrStat >= AbortErrLev) THEN + CLOSE(U_in) + RETURN + END IF + + ! ---------- Skip 4 lines -------------------------------------------- + DO I=1,4 + CALL ReadCom( U_in, FileName, "Headers for user-defined variables", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRProfiles') + + ENDDO + + DO I=1,p_met%NumUSRz + + IF ( ReadSigL ) THEN + READ( U_in, *, IOSTAT=ErrStat2 ) p_met%USR_Z(I), p_met%USR_U(I), p_met%USR_WindDir(I), p_met%USR_Sigma(I), p_met%USR_L(I) + ELSE + READ( U_in, *, IOSTAT=ErrStat2 ) p_met%USR_Z(I), p_met%USR_U(I), p_met%USR_WindDir(I) + ENDIF + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Could not read entire user-defined variable list on line '//Int2LStr(I)//'.', ErrStat, ErrMsg, 'GetUSRProfiles') + CLOSE(U_in) + RETURN + ENDIF + + IF ( ReadSigL ) THEN + IF ( p_met%USR_Sigma(I) <= REAL( 0., ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'The standard deviation must be a positive number.', ErrStat, ErrMsg, 'GetUSRProfiles') + ELSEIF ( p_met%USR_L(I) <= REAL( 0., ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'The length scale must be a positive number.', ErrStat, ErrMsg, 'GetUSRProfiles') + ENDIF + ENDIF + + IF ( p_met%USR_WindDir(I) > 360. ) THEN + J = INT ( p_met%USR_WindDir(I) / 360. ) + p_met%USR_WindDir(I) = p_met%USR_WindDir(I) - J * 360. + ELSEIF ( p_met%USR_WindDir(I) < 0. ) THEN + J = INT ( -p_met%USR_WindDir(I) / 360. ) +1 + p_met%USR_WindDir(I) = p_met%USR_WindDir(I) + J * 360. + ENDIF + ENDDO + + ! Sort the arrays + DO I=2,p_met%NumUSRz + IF ( p_met%USR_Z(I) < p_met%USR_Z(I-1) ) THEN + + Indx = 1 + DO J=I-2,1,-1 + IF ( p_met%USR_Z(I) > p_met%USR_Z(J) ) THEN + Indx = J+1 + EXIT + ELSEIF ( p_met%USR_Z(I) == p_met%USR_Z(J) ) THEN + CALL SetErrStat( ErrID_Fatal, 'User-defined values must contain unique heights.', ErrStat, ErrMsg, 'GetUSRProfiles') + CLOSE(U_in) + RETURN + ENDIF + ENDDO + + Z_USR_Tmp = p_met%USR_Z(I) + U_USR_Tmp = p_met%USR_U(I) + WindDir_USR_Tmp = p_met%USR_WindDir(I) + + DO J=I,Indx+1,-1 + p_met%USR_Z(J) = p_met%USR_Z(J-1) + p_met%USR_U(J) = p_met%USR_U(J-1) + p_met%USR_WindDir(J) = p_met%USR_WindDir(J-1) + ENDDO + + p_met%USR_Z(Indx) = Z_USR_Tmp + p_met%USR_U(Indx) = U_USR_Tmp + p_met%USR_WindDir(Indx) = WindDir_USR_Tmp + + IF ( ReadSigL ) THEN + Sigma_USR_Tmp = p_met%USR_Sigma(I) + L_USR_Tmp = p_met%USR_L(I) + + DO J=I,Indx+1,-1 + p_met%USR_Sigma(J) = p_met%USR_Sigma(J-1) + p_met%USR_L(J) = p_met%USR_L(J-1) + ENDDO + + p_met%USR_Sigma(Indx) = Sigma_USR_Tmp + p_met%USR_L(Indx) = L_USR_Tmp + ENDIF ! ReadSigL + + ENDIF + ENDDO + + CLOSE(U_in) + +END SUBROUTINE GetUSRProfiles +!======================================================================= +!> Read the input file for user-defined spectra. +SUBROUTINE GetUSRSpec(FileName, p, UnEc, ErrStat, ErrMsg) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< Simulation parameters + INTEGER(IntKi), INTENT(IN ) :: UnEc !< Echo file unit number + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message describing error + CHARACTER(*), INTENT(IN) :: FileName !< Name of the input file + + ! local variables + REAL(ReKi) :: Freq_USR_Tmp + REAL(ReKi) :: U_USR_Tmp + REAL(ReKi) :: V_USR_Tmp + REAL(ReKi) :: W_USR_Tmp + REAL(ReKi) :: SpecScale (3) + + INTEGER :: I + INTEGER, PARAMETER :: iPoint = 1 ! spectra are input for only one point + INTEGER :: Indx + INTEGER :: J + INTEGER :: USpec ! I/O unit for user-defined spectra + + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + + ErrStat = ErrID_None + ErrMSg = "" + + ! --------- Open the file --------------- + + CALL GetNewUnit( USpec, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, 'GetUSRSpec') + + CALL OpenFInpFile( USpec, FileName, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, 'GetUSRSpec') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + + CALL WrScr1(' Reading the user-defined spectra input file "'//TRIM(FileName)//'".' ) + + + ! --------- Read the comment lines at the beginning of the file --------------- + DO I=1,3 + CALL ReadCom( USpec, FileName, "user-spectra header line #"//TRIM(Num2LStr(I)), ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRSpec') + ENDDO + + + ! ---------- Read the size of the arrays -------------------------------------------- + CALL ReadVar( USpec, FileName, p%usr%nFreq, "nFreq", "Number of frequencies in the user-defined spectra", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRSpec') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + + DO I=1,3 + ! ---------- Read the scaling for the arrays -------------------------------------------- + CALL ReadVar( USpec, FileName, SpecScale(I), "SpecScale", "Scaling value for user-defined standard deviation profile", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRSpec') + + ENDDO + + IF ( p%usr%nFreq < 3 ) CALL SetErrStat(ErrID_Fatal, 'The number of frequencies specified in the user-defined spectra must be at least 3.' , ErrStat, ErrMsg, 'GetUSRSpec') + IF ( ANY(SpecScale <= 0.) ) CALL SetErrStat(ErrID_Fatal, 'The scaling value for the user-defined spectra must be positive.' , ErrStat, ErrMsg, 'GetUSRSpec') + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + ! Allocate the data arrays + CALL AllocAry( p%usr%f, p%usr%nFreq, 'f (user-defined frequencies)' ,ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'GetUSRSpec') + CALL AllocAry( p%usr%S, p%usr%nFreq,1,3,'S (user-defined spectra)' ,ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'GetUSRSpec') + CALL AllocAry( p%usr%pointzi, iPoint , 'pointzi (user-defined spectra',ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'GetUSRSpec') + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + p%usr%pointzi = 0.0_ReKi ! we don't care what this is; it's only potentially used so we can use the same interpolation routine as the user time-series input + + ! ---------- Skip 4 lines -------------------------------------------- + DO I=1,4 + CALL ReadCom( USpec, FileName, "Headers for user-defined variables", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetUSRSpec') + ENDDO + + ! ---------- Read the data lines -------------------------------------- + DO I=1,p%usr%nFreq + + READ( USpec, *, IOSTAT=ErrStat2 ) p%usr%f(I), p%usr%S(I,iPoint,1), p%usr%S(I,iPoint,2), p%usr%S(I,iPoint,3) + + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat(ErrID_Fatal, 'Could not read entire user-defined spectra on line '//Int2LStr(I)//'.' , ErrStat, ErrMsg, 'GetUSRSpec') + CALL Cleanup() + RETURN + ENDIF + + IF ( ANY( p%usr%S(I,iPoint,:) <= 0._ReKi ) ) THEN + + CALL SetErrStat(ErrID_Fatal, 'The spectra must contain positive numbers.' , ErrStat, ErrMsg, 'GetUSRSpec') + CALL Cleanup() + RETURN + +! ELSEIF ( p%usr%f(I) <= 0.0_ReKi ) THEN +! CALL SetErrStat(ErrID_Fatal, 'The frequencies must be positive numbers.' , ErrStat, ErrMsg, 'GetUSRSpec') +! CALL Cleanup() +! RETURN + ENDIF + + ! Scale by the factors earlier in the input file + + p%usr%S(I,iPoint,1) = p%usr%S(I,iPoint,1)*SpecScale(1) + p%usr%S(I,iPoint,2) = p%usr%S(I,iPoint,2)*SpecScale(2) + p%usr%S(I,iPoint,3) = p%usr%S(I,iPoint,3)*SpecScale(3) + + ENDDO + + ! ------- Sort the arrays by frequency ----------------------------------- + DO I=2,p%usr%nFreq + IF ( p%usr%f(I) < p%usr%f(I-1) ) THEN + + Indx = 1 + DO J=I-2,1,-1 + IF ( p%usr%f(I) > p%usr%f(J) ) THEN + Indx = J+1 + EXIT + ELSEIF ( EqualRealNos( p%usr%f(I), p%usr%f(J) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'Error: user-defined spectra must contain unique frequencies.' , ErrStat, ErrMsg, 'GetUSRSpec') + CALL Cleanup() + RETURN + ENDIF + ENDDO + + Freq_USR_Tmp = p%usr%f(I) + U_USR_Tmp = p%usr%S(I,iPoint,1) + V_USR_Tmp = p%usr%S(I,iPoint,2) + W_USR_Tmp = p%usr%S(I,iPoint,3) + + DO J=I,Indx+1,-1 + p%usr%f(J) = p%usr%f(J-1) + p%usr%S(J,iPoint,1) = p%usr%S(J-1,iPoint,1) + p%usr%S(J,iPoint,2) = p%usr%S(J-1,iPoint,2) + p%usr%S(J,iPoint,3) = p%usr%S(J-1,iPoint,3) + ENDDO + + p%usr%f(Indx) = Freq_USR_Tmp + p%usr%S(I,iPoint,1) = U_USR_Tmp + p%usr%S(I,iPoint,2) = V_USR_Tmp + p%usr%S(I,iPoint,3) = W_USR_Tmp + + ENDIF + ENDDO + + ! --------- Close the file --------------------------------------- + + CALL Cleanup() + RETURN + +CONTAINS + SUBROUTINE Cleanup() + + CLOSE( USpec ) + + + END SUBROUTINE Cleanup + +END SUBROUTINE GetUSRSpec + +!======================================================================= +!> Read the input file for user-defined time series +SUBROUTINE GetUSRTimeSeries(FileName, p, UnEc, ErrStat, ErrMsg) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< Simulation parameters + INTEGER(IntKi), INTENT(IN ) :: UnEc !< Echo file unit number + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error level + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message describing error + CHARACTER(*), INTENT(IN) :: FileName !< Name of the input file + + ! local variables + real(reKi) :: tmpAry(2) + real(ReKi) :: dt ! difference between consecutive times entered in the file (must be constant) + INTEGER(IntKi), PARAMETER :: NumLinesBeforeTS = 11 ! Number of lines in the input file before the time series start (need to add nPoint lines). IMPORTANT: any changes to the number of lines in the header must be reflected here + + INTEGER(IntKi) :: UnIn ! unit number for reading input file + INTEGER(IntKi) :: I, J ! loop counters + INTEGER(IntKi) :: IPoint ! loop counter on number of points + INTEGER(IntKi) :: IVec ! loop counter on velocity components being read + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + CHARACTER(*), parameter :: RoutineName = 'GetUSRTimeSeries' + + CHARACTER(200) :: FormStr + CHARACTER(1) :: tmpChar + + ErrStat = ErrID_None + ErrMsg = "" + + ! --------- Open the file --------------- + + CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + + CALL WrScr1(' Reading the user-defined time-series input file "'//TRIM(FileName)//'".' ) + + IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(TurbSim_Ver%Name)//' user time-series input file "'//TRIM( FileName )//'":' + + + do i=1,3 + CALL ReadCom( UnIn, FileName, "Header #"//TRIM(Num2Lstr(i))//"for user time-series input", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + end do + + CALL ReadVar( UnIn, FileName, p%usr%nComp, 'nComp', 'How many velocity components will be input? (1=u component only; 2=u&v components; 3=u,v,and w)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + CALL ReadVar( UnIn, FileName, p%usr%nPoints, 'nPoints', 'Number of time series points contained in this file', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + CALL ReadVar( UnIn, FileName, p%usr%RefPtID, 'RefPtID', 'Index of the reference point (1-nPoints)', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + IF ( p%usr%RefPtID < 1 .OR. p%usr%RefPtID > p%usr%nPoints ) THEN + CALL SetErrStat(ErrID_Fatal, 'RefPtID must be between 1 and nPoints (inclusive).', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + + + CALL AllocAry(p%usr%Pointyi, p%usr%nPoints, 'Pointyi', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + CALL AllocAry(p%usr%Pointzi, p%usr%nPoints, 'Pointzi', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + do i=1,2 + CALL ReadCom( UnIn, FileName, "Point location header #"//TRIM(Num2Lstr(i)), ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + end do + + do iPoint=1,p%usr%nPoints + CALL ReadAry( UnIn, FileName, TmpAry, 2, "point"//trim(Num2Lstr(iPoint)), "locations of points", ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + + p%usr%Pointyi(iPoint) = TmpAry(1) + p%usr%Pointzi(iPoint) = TmpAry(2) + end do + + + do i=1,3 + CALL ReadCom( UnIn, FileName, "Time Series header #"//TRIM(Num2Lstr(i)), ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + end do + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !....... + ! find out how many rows there are to the end of the file + p%usr%NTimes = -1 + ErrStat2 = 0 + + + DO WHILE ( ErrStat2 == 0 ) + + p%usr%NTimes = p%usr%NTimes + 1 + READ(UnIn, *, IOSTAT=ErrStat2) tmpAry(1) + + END DO + + CALL WrScr( ' Found '//TRIM(Num2LStr(p%usr%NTimes))//' lines of time-series data.' ) + + IF (p%usr%NTimes < 2) THEN + CALL SetErrStat(ErrID_Fatal, 'The user time-series input file must contain at least 2 rows of time data.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + + ! now rewind and skip the first few lines. + REWIND( UnIn, IOSTAT=ErrStat2 ) + IF (ErrStat2 /= 0_IntKi ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(FileName)//'".', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + END IF + + !IMPORTANT: any changes to the number of lines in the header must be reflected in NumLinesBeforeTS + DO I=1,NumLinesBeforeTS + p%usr%nPoints + READ( UnIn, '(A)', IOSTAT=ErrStat2 ) TmpChar ! I'm going to ignore this error because we should have caught any issues the first time we read the file. + END DO + + !....... + + if (p%usr%nComp < 1 .OR. p%usr%nComp > 3) then + CALL SetErrStat( ErrID_Fatal, 'Number of velocity components in file must be 1, 2 or 3.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + END IF + + + + CALL AllocAry(p%usr%t, p%usr%nTimes, 't', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + CALL AllocAry(p%usr%v, p%usr%nTimes, p%usr%nPoints, p%usr%nComp, 'v', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2 , ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + DO i=1,p%usr%nTimes + READ( UnIn, *, IOSTAT=ErrStat2 ) p%usr%t(i), ( (p%usr%v(i,iPoint,iVec), iVec=1,p%usr%nComp), iPoint=1,p%usr%nPoints ) + IF (ErrStat2 /=0) THEN + CALL SetErrStat( ErrID_Fatal, 'Error reading from time series line '//trim(num2lstr(i))//'.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + END DO + + IF (UnEc > 0 ) THEN + FormStr = '('//trim(num2lstr(1+p%usr%nComp*p%usr%nPoints))//'(F13.4," "))' + DO i=1,p%usr%nTimes + WRITE( UnEc, FormStr) p%usr%t(i), ( (p%usr%v(i,iPoint,iVec), iVec=1,p%usr%nComp), iPoint=1,p%usr%nPoints ) + END DO + END IF + + + !......................................................... + ! a little bit of error checking: + !......................................................... + + !bjj: verify that the locations are okay; for now, we're going to make sure they are unique and that the z values are in increasing order. + do i=2,p%usr%nPoints + do j=1,i-1 + IF ( EqualRealNos( p%usr%Pointyi(i), p%usr%Pointyi(j) ) .AND. EqualRealNos( p%usr%Pointzi(i), p%usr%Pointzi(j) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'Locations of points specified in the user time-series input file must be unique.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + end do + + !bjj: fix this in the future. Currently the interpolation routine won't work if z is not ordered properly. Also, interpolation doesn't take y into account, so we may want to fix that. + IF ( p%usr%Pointzi(i) < p%usr%Pointzi(i-1) ) THEN + CALL SetErrStat(ErrID_Fatal, 'The current implementation of user time-series input requires that the points be entered in the order of increasing height.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END IF + end do + + + + !DO i = 2,p%usr%nTimes + ! IF (.NOT. EqualRealNos( p%usr%t(i-1) + p%grid%TimeStep, p%usr%t(i) ) ) THEN + ! call SetErrStat(ErrID_Fatal, 'the delta time in the file must be constant and must be equal to input file variable TimeStep.', ErrStat, ErrMsg, RoutineName) + ! EXIT + ! END IF + !END DO + + ! check for constant delta t: + + dt = p%usr%t(2) - p%usr%t(1) + + DO i = 3,p%usr%nTimes + IF (.NOT. EqualRealNos( p%usr%t(i-1) + dt, p%usr%t(i) ) ) THEN + call SetErrStat(ErrID_Fatal, 'The time between each row in the file must be constant.', ErrStat, ErrMsg, RoutineName) + EXIT + END IF + END DO + + + if ( .NOT. EqualRealNos( dt, p%grid%TimeStep ) ) THEN + call SetErrStat(ErrID_Fatal, 'In this version of TurbSim, TimeStep must be the same as the delta time in the user-input time series file.', ErrStat, ErrMsg, RoutineName) + end if + + + + CALL Cleanup() + RETURN + +CONTAINS +!............................................... + SUBROUTINE Cleanup() + + CLOSE( UnIn ) + + + END SUBROUTINE Cleanup +!............................................... +END SUBROUTINE GetUSRTimeSeries +!======================================================================= +SUBROUTINE ReadCVarDefault ( UnIn, Fil, CharVar, VarName, VarDescr, UnEc, Def, ErrStat, ErrMsg, IGNORE ) + + + ! This routine reads a single character variable from the next line of the input file. + ! The input is allowed to be "default" + + ! Argument declarations: + + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN) :: UnEc ! I/O unit for echo/summary file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + LOGICAL, INTENT(INOUT) :: Def ! - on input whether or not to use the default - on output, whether a default was used + LOGICAL, INTENT(IN), OPTIONAL:: IGNORE ! whether to ignore this input + + CHARACTER(250) :: CharLine ! Character string being read. + CHARACTER(*), INTENT(INOUT) :: CharVar ! Character variable being read. + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + ! Local declarations: + + + CALL ReadVar( UnIn, Fil, CharLine, VarName, VarDescr, ErrStat, ErrMsg, UnEc) + + IF ( PRESENT(IGNORE) ) THEN + IF ( IGNORE ) THEN + Def = .TRUE. + RETURN + ENDIF + + ENDIF + + CALL Conv2UC( CharLine ) + + IF ( TRIM(CharLine) == 'DEFAULT' ) THEN + +! CALL WrScr ( ' A default value will be used for '//TRIM(VarName)//'.' ) + Def = .TRUE. + + ELSE + + CharVar = CharLine + Def = .FALSE. + + ENDIF + + RETURN +END SUBROUTINE ReadCVarDefault ! ( UnIn, Fil, RealVar, VarName, VarDescr ) +!======================================================================= +SUBROUTINE ReadRAryDefault ( UnIn, Fil, RealAry, VarName, VarDescr, UnEc, Def, ErrStat, ErrMsg, IGNORE ) + + ! This routine reads a real array from the next line of the input file. + ! The input is allowed to be "default" + + ! Argument declarations: + + REAL(ReKi), INTENT(INOUT) :: RealAry (:) ! Real variable being read. + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN) :: UnEc ! I/O unit for echo/summary file. + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + LOGICAL, INTENT(INOUT) :: Def ! - on input whether or not to use the default - on output, whether a default was used + LOGICAL, INTENT(IN), OPTIONAL:: IGNORE ! whether or not to ignore this input + + CHARACTER(250) :: CharLine ! Character string being read. + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + CALL ReadVar( UnIn, Fil, CharLine, VarName, VarDescr, ErrStat, ErrMsg, UnEc) !Maybe I should read this in explicitly... + + IF ( PRESENT(IGNORE) ) THEN + IF ( IGNORE ) THEN + Def = .TRUE. + RETURN + ENDIF + + ENDIF + + CALL Conv2UC( CharLine ) + + IF ( TRIM(CharLine) == 'DEFAULT' ) THEN + +! CALL WrScr ( ' A default value will be used for '//TRIM(VarName)//'.' ) + Def = .TRUE. + + ELSE + + IF ( INDEX( CharLine(1:1), 'TF') > 0 ) THEN ! We don't want 'T' or 'F' read as -1 or 0. + CALL WrScr1 ( ' Invalid numerical input for "'//TRIM( VarName )//'".' ) + ENDIF + + READ (CharLine,*,IOSTAT=IOS) RealAry + + IF (IOS /=0) THEN + RealAry = 0.0_ReKi ! set these all to 0 + READ (CharLine,*,IOSTAT=IOS) RealAry(1) ! Try reading only the first element + ENDIF + + CALL CheckIOS ( IOS, Fil, VarName, NumType ) + Def = .FALSE. + + ENDIF + + + RETURN + +END SUBROUTINE ReadRAryDefault +!======================================================================= +SUBROUTINE ReadRVarDefault ( UnIn, Fil, RealVar, VarName, VarDescr, UnEc, Def, ErrStat, ErrMsg, IGNORE, IGNORESTR ) + + ! This routine reads a single real variable from the next line of the input file. + ! The input is allowed to be "default" + + ! Argument declarations: + + REAL(ReKi), INTENT(INOUT) :: RealVar ! Real variable being read. + + INTEGER, INTENT(IN) :: UnIn ! I/O unit for input file. + INTEGER, INTENT(IN) :: UnEc ! I/O unit for echo/summary file. + + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message + + LOGICAL, INTENT( OUT) :: Def ! - on input whether or not to use the default - on output, whether a default was used + LOGICAL, INTENT(IN), OPTIONAL:: IGNORE ! whether or not to ignore this input + LOGICAL, INTENT(INOUT),OPTIONAL:: IGNORESTR ! whether or not user requested to ignore this input + + CHARACTER(250) :: CharLine ! Character string being read. + CHARACTER( *), INTENT(IN) :: Fil ! Name of the input file. + CHARACTER( *), INTENT(IN) :: VarDescr ! Text string describing the variable. + CHARACTER( *), INTENT(IN) :: VarName ! Text string containing the variable name. + + ! Local declarations: + + INTEGER :: IOS ! I/O status returned from the read statement. + + + CALL ReadVar( UnIn, Fil, CharLine, VarName, VarDescr, ErrStat, ErrMsg, UnEc ) + + IF ( PRESENT(IGNORE) ) THEN + + IF ( IGNORE ) THEN + Def = .TRUE. + RETURN + ENDIF + + ENDIF + + + CALL Conv2UC( CharLine ) + + IF ( PRESENT(IGNORESTR) ) THEN + IF ( TRIM( CharLine ) == 'NONE' ) THEN + IGNORESTR = .TRUE. + Def = .TRUE. + RETURN + ENDIF + ENDIF + + IF ( TRIM(CharLine) == 'DEFAULT' ) THEN + +! CALL WrScr ( ' A default value will be used for '//TRIM(VarName)//'.' ) + Def = .TRUE. + RETURN + + ELSE + + IF ( INDEX( CharLine(1:1), 'TF') > 0 ) THEN ! We don't want 'T' or 'F' read as -1 or 0. + CALL WrScr1 ( ' Invalid numerical input for "'//TRIM( VarName )//'".' ) + ENDIF + + READ (CharLine,*,IOSTAT=IOS) RealVar + + CALL CheckIOS ( IOS, Fil, VarName, NumType ) + + Def = .FALSE. + + IF ( PRESENT(IGNORESTR) ) IGNORESTR = .FALSE. + + ENDIF + + + RETURN +END SUBROUTINE ReadRVarDefault +!======================================================================= +!> This routine writes the velocity grid to a binary file. +!! The file has a .wnd extension; scaling information is written in a summary +!! file. A tower file with extension .twr is generated if requested, too. +SUBROUTINE WrBinBLADED(p, V, USig, VSig, WSig, ErrStat, ErrMsg) + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + REAL(ReKi), INTENT(IN) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + REAL(ReKi), INTENT(IN) :: USig !< Standard deviation of U + REAL(ReKi), INTENT(IN) :: VSig !< Standard deviation of V + REAL(ReKi), INTENT(IN) :: WSig !< Standard deviation of W + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + REAL(ReKi) :: NewUSig ! Value of USig that will be used to scale values in the file + + REAL(ReKi) :: U_C1 ! Scale for converting BLADED U data + REAL(ReKi) :: U_C2 ! Offset for converting BLADED U data + REAL(ReKi) :: V_C ! Scale for converting BLADED V data + REAL(ReKi) :: W_C ! Scale for converting BLADED W data + REAL(ReKi) :: TI(3) ! Turbulence intensity for scaling data + REAL(ReKi) :: TmpU ! Max value of |V(:,:,1)-UHub| + + INTEGER(B4Ki) :: CFirst + INTEGER(B4Ki) :: CLast + INTEGER(B4Ki) :: CStep + INTEGER(B4Ki) :: II + INTEGER(B4Ki) :: IT + INTEGER(B4Ki) :: IY + INTEGER(B4Ki) :: IZ + + INTEGER(B4Ki) :: IP + INTEGER(B2Ki) :: TmpVarray(3*p%grid%NumGrid_Y*p%grid%NumGrid_Z) ! This array holds the normalized velocities before being written to the binary file + INTEGER(B2Ki), ALLOCATABLE :: TmpTWRarray(:) ! This array holds the normalized tower velocities + + INTEGER :: AllocStat + INTEGER :: UBFFW ! I/O unit for BLADED FF data (*.wnd file). + INTEGER :: UATWR ! I/O unit for AeroDyn tower data (*.twr file). + + CHARACTER(200) :: FormStr ! String used to store format specifiers. + + + ErrStat = ErrID_None + ErrMsg = "" + + + + ! We need to take into account the shear across the grid in the sigma calculations for scaling the data, + ! and ensure that 32.767*Usig >= |V-UHub| so that we don't get values out of the range of our scaling values + ! in this BLADED-style binary output. TmpU is |V-UHub| + TmpU = MAX( ABS(MAXVAL(V(:,:,1))-p%UHub), ABS(MINVAL(V(:,:,1))-p%UHub) ) !Get the range of wind speed values for scaling in BLADED-format .wnd files + NewUSig = MAX(USig,0.05*TmpU) + + + ! Put normalizing factors into the summary file. The user can use them to + ! tell a simulation program how to rescale the data. + + TI(1) = MAX(100.0*Tolerance, NewUSig) / p%UHub + TI(2) = MAX(100.0*Tolerance, VSig) / p%UHub + TI(3) = MAX(100.0*Tolerance, WSig) / p%UHub + + WRITE (p%US,"(//,'Normalizing Parameters for Binary Data (approximate statistics):',/)") + + FormStr = "(3X,A,' =',F9.4,A)" + WRITE (p%US,FormStr) 'UBar ', p%UHub, ' m/s' + WRITE (p%US,FormStr) 'TI(u)', 100.0*TI(1), ' %' + WRITE (p%US,FormStr) 'TI(v)', 100.0*TI(2), ' %' + WRITE (p%US,FormStr) 'TI(w)', 100.0*TI(3), ' %' + + WRITE (p%US,'()') + WRITE (p%US,FormStr) 'Height Offset', ( p%grid%HubHt - p%grid%GridHeight / 2.0 - p%grid%Zbottom ), ' m' + WRITE (p%US,FormStr) 'Grid Base ', p%grid%Zbottom, ' m' + + WRITE (p%US,'()' ) + IF ( p%grid%Periodic ) THEN + WRITE (p%US,'( A)' ) 'Creating a PERIODIC output file.' + END IF + + ! Calculate some numbers for normalizing the data. + + U_C1 = 1000.0/( p%UHub*TI(1) ) + U_C2 = 1000.0/TI(1) + V_C = 1000.0/( p%UHub*TI(2) ) + W_C = 1000.0/( p%UHub*TI(3) ) + + + IF ( p%WrFile(FileExt_WND) ) THEN + + CALL GetNewUnit( UBFFW ) + CALL OpenBOutFile ( UBFFW, TRIM(p%RootName)//'.wnd', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL WrScr ( ' Generating BLADED binary time-series file "'//TRIM( p%RootName )//'.wnd"' ) + + ! Put header information into the binary data file. + + WRITE (UBFFW) INT( -99 , B2Ki ) ! -99 = New Bladed format + WRITE (UBFFW) INT( 4 , B2Ki ) ! 4 = improved von karman (but needed for next 7 inputs) + WRITE (UBFFW) INT( 3 , B4Ki ) ! 3 = number of wind components + WRITE (UBFFW) REAL( p%met%Latitude , SiKi ) ! Latitude (degrees) + WRITE (UBFFW) REAL( p%met%Z0 , SiKi ) ! Roughness length (m) + WRITE (UBFFW) REAL( p%grid%Zbottom + p%grid%GridHeight/2.0 , SiKi ) ! Reference Height (m) ( Z(1) + GridHeight / 2.0 ) !This is the vertical center of the grid + WRITE (UBFFW) REAL( 100.0*TI(1) , SiKi ) ! Longitudinal turbulence intensity (%) + WRITE (UBFFW) REAL( 100.0*TI(2) , SiKi ) ! Lateral turbulence intensity (%) + WRITE (UBFFW) REAL( 100.0*TI(3) , SiKi ) ! Vertical turbulence intensity (%) + + WRITE (UBFFW) REAL( p%grid%GridRes_Z , SiKi ) ! grid spacing in vertical direction, in m + WRITE (UBFFW) REAL( p%grid%GridRes_Y , SiKi ) ! grid spacing in lateral direction, in m + WRITE (UBFFW) REAL( p%grid%TimeStep*p%UHub , SiKi ) ! grid spacing in longitudinal direciton, in m + WRITE (UBFFW) INT( p%grid%NumOutSteps/2 , B4Ki ) ! half the number of points in alongwind direction + WRITE (UBFFW) REAL( p%UHub , SiKi ) ! the mean wind speed in m/s + WRITE (UBFFW) REAL( 0 , SiKi ) ! the vertical length scale of the longitudinal component in m + WRITE (UBFFW) REAL( 0 , SiKi ) ! the lateral length scale of the longitudinal component in m + WRITE (UBFFW) REAL( 0 , SiKi ) ! the longitudinal length scale of the longitudinal component in m + WRITE (UBFFW) INT( 0 , B4Ki ) ! an unused integer + WRITE (UBFFW) INT( p%RNG%RandSeed(1) , B4Ki ) ! the random number seed + WRITE (UBFFW) INT( p%grid%NumGrid_Z , B4Ki ) ! the number of grid points vertically + WRITE (UBFFW) INT( p%grid%NumGrid_Y , B4Ki ) ! the number of grid points laterally + WRITE (UBFFW) INT( 0 , B4Ki ) ! the vertical length scale of the lateral component, not used + WRITE (UBFFW) INT( 0 , B4Ki ) ! the lateral length scale of the lateral component, not used + WRITE (UBFFW) INT( 0 , B4Ki ) ! the longitudinal length scale of the lateral component, not used + WRITE (UBFFW) INT( 0 , B4Ki ) ! the vertical length scale of the vertical component, not used + WRITE (UBFFW) INT( 0 , B4Ki ) ! the lateral length scale of the vertical component, not used + WRITE (UBFFW) INT( 0 , B4Ki ) ! the longitudinal length scale of the vertical component, not used + + + ! Compute parameters for ordering output for FF AeroDyn files. (This is for BLADED compatibility.) + + IF ( p%grid%Clockwise ) THEN + CFirst = p%grid%NumGrid_Y + CLast = 1 + CStep = -1 + ELSE + CFirst = 1 + CLast = p%grid%NumGrid_Y + CStep = 1 + ENDIF + + + ! Loop through time. + + DO IT=1,p%grid%NumOutSteps !Use only the number of timesteps requested originally + + ! Write out grid data in binary form. + IP = 1 + DO IZ=1,p%grid%NumGrid_Z + DO IY=CFirst,CLast,CStep + + II = ( IZ - 1 )*p%grid%NumGrid_Y + IY + + TmpVarray(IP) = NINT( U_C1*V(IT,p%grid%GridPtIndx(II),1) - U_C2, B2Ki ) ! Put the data into a temp array so that the WRITE() command works faster + TmpVarray(IP+1) = NINT( V_C *V(IT,p%grid%GridPtIndx(II),2) , B2Ki ) + TmpVarray(IP+2) = NINT( W_C *V(IT,p%grid%GridPtIndx(II),3) , B2Ki ) + + IP = IP + 3; + ENDDO ! IY + ENDDO ! IZ + + WRITE ( UBFFW ) TmpVarray ! bjj: We cannot write the array including time because of stack overflow errors.. otherwise use compile option to put this on the heap instead of the stack? + + ENDDO ! IT + + CLOSE ( UBFFW ) + + !....................................................... + ! Now write tower data file if necessary: + !....................................................... + + IF ( p%WrFile(FileExt_TWR) ) THEN + + CALL GetNewUnit( UATWR, ErrStat, ErrMsg ) + CALL OpenBOutFile ( UATWR, TRIM( p%RootName )//'.twr', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + + !IF ( ALLOCATED(p%grid%TwrPtIndx) ) THEN + ALLOCATE( TmpTwrarray( 3*SIZE(p%grid%TwrPtIndx) ), STAT=AllocStat ) + IF ( AllocStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = "WrBinBLADED: Error allocating space for temporary tower output array." + RETURN + END IF + !END IF + + + CALL WrScr ( ' Generating tower binary time-series file "'//TRIM( p%RootName )//'.twr"' ) + + + WRITE (UATWR) REAL( p%grid%GridRes_Z , SiKi ) ! grid spacing in vertical direction, in m + WRITE (UATWR) REAL( p%grid%TimeStep*p%UHub , SiKi ) ! grid spacing in longitudinal direciton, in m + WRITE (UATWR) REAL( p%grid%ZBottom , SiKi ) ! The vertical location of the highest tower grid point in m + WRITE (UATWR) INT( p%grid%NumOutSteps , B4Ki ) ! The number of points in alongwind direction + WRITE (UATWR) INT( SIZE(p%grid%TwrPtIndx) , B4Ki ) ! the number of grid points vertically + WRITE (UATWR) REAL( p%UHub , SiKi ) ! the mean wind speed in m/s + WRITE (UATWR) REAL( 100.0*TI(1), SiKi ) ! Longitudinal turbulence intensity + WRITE (UATWR) REAL( 100.0*TI(2), SiKi ) ! Lateral turbulence intensity + WRITE (UATWR) REAL( 100.0*TI(3), SiKi ) ! Vertical turbulence intensity + + + DO IT=1,p%grid%NumOutSteps + + IP = 1 + DO II = 1,SIZE(p%grid%TwrPtIndx) + TmpTWRarray(IP ) = NINT( U_C1*V(IT,p%grid%TwrPtIndx(II),1) - U_C2 , B2Ki ) + TmpTWRarray(IP+1) = NINT( V_C *V(IT,p%grid%TwrPtIndx(II),2) , B2Ki ) + TmpTWRarray(IP+2) = NINT( W_C *V(IT,p%grid%TwrPtIndx(II),3) , B2Ki ) + + IP = IP + 3 + ENDDO ! II + + WRITE (UATWR) TmpTWRarray(:) + + ENDDO ! IT + + CLOSE ( UATWR ) + + + ENDIF !WrADWTR + + ENDIF ! p%WrFile(FileExt_WND) + + +END SUBROUTINE WrBinBLADED +!======================================================================= +!> This routine writes the velocity grid to a binary file. +!! The file has a .bts extension. +!======================================================================= +SUBROUTINE WrBinTURBSIM(p, V, ErrStat, ErrMsg) + + IMPLICIT NONE + + ! passed variables + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + REAL(ReKi), INTENT(IN) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + REAL(SiKi), PARAMETER :: IntMax = 32767.0 + REAL(SiKi), PARAMETER :: IntMin = -32768.0 + REAL(SiKi), PARAMETER :: IntRng = IntMax - IntMin ! Max Range of 2-byte integer + + REAL(SiKi) :: UOff ! Offset for the U component + REAL(SiKi) :: UScl ! Slope for the U component + REAL(ReKi) :: VMax(3) ! Maximum value of the 3 wind components + REAL(ReKi) :: VMin(3) ! Minimum value of the 3 wind components + REAL(SiKi) :: VOff ! Offset for the V component + REAL(SiKi) :: VScl ! Slope for the V component + REAL(SiKi) :: WOff ! Offset for the W component + REAL(SiKi) :: WScl ! Slope for the W component + + INTEGER, PARAMETER :: DecRound = 3 ! Number of decimal places to round to + INTEGER(B2Ki) :: FileID ! File ID, determines specific output format (if periodic or not) + INTEGER :: IC ! counter for the velocity component of V + INTEGER :: II ! counter for the point on the grid/tower + INTEGER :: IT ! counter for the timestep + INTEGER(B4Ki) :: LenDesc ! Length of the description string + INTEGER(B4Ki) :: NumGrid ! Number of points on the grid + INTEGER(B4Ki) :: NumTower ! Number of points on the tower + + INTEGER(B4Ki) :: IP + INTEGER(B2Ki),ALLOCATABLE :: TmpVarray(:) ! This array holds the normalized velocities before being written to the binary file + + INTEGER :: AllocStat + INTEGER :: UAFFW ! I/O unit for AeroDyn FF data (*.bts file). + + + + ! Set the file format ID + + IF ( p%grid%Periodic ) THEN + FileID = 8 + ELSE + FileID = 7 + END IF + + + ! Find the range of our velocity + + DO IC=1,3 + + ! Initialize the Min/Max values + + VMin(IC) = V(1,1,IC) + VMax(IC) = V(1,1,IC) + + DO II=1,p%grid%NPoints ! Let's check all of the points + DO IT=1,p%grid%NumOutSteps ! Use only the number of timesteps requested originally + + IF ( V(IT,II,IC) > VMax(IC) ) THEN + + VMax(IC) = V(IT,II,IC) + + ELSEIF ( V(IT,II,IC) < VMin(IC) ) THEN + + VMin(IC) = V(IT,II,IC) + + ENDIF + + ENDDO !IT + ENDDO !II + + ENDDO !IC + + + ! Calculate the scaling parameters for each component + + + IF ( VMax(1) == VMin(1) ) THEN + UScl = 1 + ELSE + UScl = IntRng/REAL( VMax(1) - VMin(1) , SiKi ) + ENDIF + + IF ( VMax(2) == VMin(2) ) THEN + VScl = 1 + ELSE + VScl = IntRng/REAL( VMax(2) - VMin(2) , SiKi ) + ENDIF + + IF ( VMax(3) == VMin(3) ) THEN + WScl = 1 + ELSE + WScl = IntRng/REAL( VMax(3) - VMin(3) , SiKi ) + ENDIF + + + UOff = IntMin - UScl*REAL( VMin(1) , SiKi ) + VOff = IntMin - VScl*REAL( VMin(2) , SiKi ) + WOff = IntMin - WScl*REAL( VMin(3) , SiKi ) + + + ! Find the first tower point + + NumGrid = SIZE(p%grid%GridPtIndx) !p%grid%NumGrid_Y*p%grid%NumGrid_Z + + IF ( p%WrFile(FileExt_TWR) ) THEN + + NumTower = SIZE(p%grid%TwrPtIndx) + + ELSE + + NumTower = 0 + + ENDIF + + + LenDesc = LEN_TRIM( p%DescStr ) ! Length of the string that contains program name, version, date, and time + + CALL WrScr ( ' Generating AeroDyn binary time-series file "'//TRIM( p%RootName )//'.bts"' ) + + CALL GetNewUnit(UAFFW, ErrStat, ErrMsg) + CALL OpenBOutFile ( UAFFW, TRIM(p%RootName)//'.bts', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + + + ! Write the header + + WRITE (UAFFW) INT( FileID , B2Ki ) ! TurbSim format (7=not PERIODIC, 8=PERIODIC) + + WRITE (UAFFW) INT( p%grid%NumGrid_Z , B4Ki ) ! the number of grid points vertically + WRITE (UAFFW) INT( p%grid%NumGrid_Y , B4Ki ) ! the number of grid points laterally + WRITE (UAFFW) INT( NumTower , B4Ki ) ! the number of tower points + WRITE (UAFFW) INT( p%grid%NumOutSteps , B4Ki ) ! the number of time steps + + WRITE (UAFFW) REAL( p%grid%GridRes_Z , SiKi ) ! grid spacing in vertical direction, in m + WRITE (UAFFW) REAL( p%grid%GridRes_Y , SiKi ) ! grid spacing in lateral direction, in m + WRITE (UAFFW) REAL( p%grid%TimeStep , SiKi ) ! grid spacing in delta time, in m/s + WRITE (UAFFW) REAL( p%UHub , SiKi ) ! the mean wind speed in m/s at hub height + WRITE (UAFFW) REAL( p%grid%HubHt , SiKi ) ! the hub height, in m + WRITE (UAFFW) REAL( p%grid%Zbottom , SiKi ) ! the height of the grid bottom, in m + + WRITE (UAFFW) REAL( UScl , SiKi ) ! the U-component slope for scaling + WRITE (UAFFW) REAL( UOff , SiKi ) ! the U-component offset for scaling + WRITE (UAFFW) REAL( VScl , SiKi ) ! the V-component slope for scaling + WRITE (UAFFW) REAL( VOff , SiKi ) ! the V-component offset for scaling + WRITE (UAFFW) REAL( WScl , SiKi ) ! the W-component slope for scaling + WRITE (UAFFW) REAL( WOff , SiKi ) ! the W-component offset for scaling + + WRITE (UAFFW) INT( LenDesc , B4Ki ) ! the number of characters in the string, max 200 + + DO II=1,LenDesc + + WRITE (UAFFW) INT( IACHAR( p%DescStr(II:II) ), B1Ki ) ! converted ASCII characters + + ENDDO + + ALLOCATE ( TmpVarray( 3*(NumGrid + NumTower) ) , STAT=AllocStat ) + + IF ( AllocStat /= 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'WrBinTURBSIM:Error allocating memory for temporary wind speed array.' + RETURN + ENDIF + + ! Loop through time. + + DO IT=1,p%grid%NumOutSteps !Use only the number of timesteps requested originally + + ! Write out grid data in binary form. II = (IZ - 1)*NumGrid_Y + IY, IY varies most rapidly + + IP = 1 + + DO II=1,NumGrid + + TmpVarray(IP) = NINT( Max( Min( REAL(UScl*V(IT,p%grid%GridPtIndx(II),1) + UOff, SiKi), IntMax ),IntMin) , B2Ki ) + TmpVarray(IP+1) = NINT( Max( Min( REAL(VScl*V(IT,p%grid%GridPtIndx(II),2) + VOff, SiKi), IntMax ),IntMin) , B2Ki ) + TmpVarray(IP+2) = NINT( Max( Min( REAL(WScl*V(IT,p%grid%GridPtIndx(II),3) + Woff, SiKi), IntMax ),IntMin) , B2Ki ) + + IP = IP + 3 + ENDDO ! II + + + IF ( p%WrFile(FileExt_TWR) ) THEN + + ! Write out the tower data in binary form + + DO II=1,SIZE(p%grid%TwrPtIndx) + ! Values of tower data + TmpVarray(IP) = NINT( Max( Min( REAL(UScl*V(IT,p%grid%TwrPtIndx(II),1) + UOff, SiKi), IntMax ),IntMin) , B2Ki ) + TmpVarray(IP+1) = NINT( Max( Min( REAL(VScl*V(IT,p%grid%TwrPtIndx(II),2) + VOff, SiKi), IntMax ),IntMin) , B2Ki ) + TmpVarray(IP+2) = NINT( Max( Min( REAL(WScl*V(IT,p%grid%TwrPtIndx(II),3) + Woff, SiKi), IntMax ),IntMin) , B2Ki ) + + IP = IP + 3 + ENDDO ! II + + ENDIF + + WRITE ( UAFFW ) TmpVarray(:) + ENDDO ! IT + + CLOSE ( UAFFW ) + + IF ( ALLOCATED( TmpVarray ) ) DEALLOCATE( TmpVarray ) + + +END SUBROUTINE WrBinTURBSIM +!======================================================================= +SUBROUTINE WrFormattedFF(RootName, p_grid, UHub, V ) + + IMPLICIT NONE + + CHARACTER(*), intent(in ) :: RootName ! Rootname of output file + TYPE(Grid_ParameterType), INTENT(IN) :: p_grid + REAL(ReKi), INTENT(IN) :: UHub ! The steady hub-height velocity + REAL(ReKi), INTENT(IN) :: V (:,:,:) ! The Velocities to write to a file + + + +REAL(ReKi), ALLOCATABLE :: ZRow (:) ! The horizontal locations of the grid points (NumGrid_Y) at each height. + +INTEGER :: II +INTEGER :: IT +INTEGER :: IVec +INTEGER :: IY +INTEGER :: IZ + +CHARACTER(200) :: FormStr5 ! String used to store format specifiers. + +INTEGER :: UFFF ! I/O unit for formatted FF data. +INTEGER(IntKi) :: ErrStat +CHARACTER(ErrMsgLen) :: ErrMsg + + FormStr5 = "(1X,"//trim(num2lstr(max(p_grid%NumGrid_Z,p_grid%NumGrid_Y)))//"(F8.3),:)" + + ! Allocate the array of wind speeds. + + + CALL GetNewUnit(UFFF) + + DO IVec=1,3 + + CALL WrScr ( ' Generating full-field formatted file "'//TRIM(RootName)//'.'//Comp(IVec)//'".' ) + CALL OpenFOutFile ( UFFF, TRIM( RootName )//'.'//Comp(IVec), ErrStat, ErrMsg ) + IF (ErrStat /= ErrID_None) then + call WrScr(Trim(ErrMsg)) + if (ErrStat >= AbortErrLev) cycle + end if + + + ! Create file header. + + WRITE (UFFF,"( / 'This full-field turbulence file was generated by ' , A , ' on ' , A , ' at ' , A , '.' / )" ) TRIM(GetNVD(TurbSim_Ver)), CurDate(), CurTime() + + WRITE (UFFF,"( ' | ', A,'-comp | Y x Z | Grid Resolution (Y x Z) | Time-step | Hub Elev | Mean U |')") Comp(IVec) + + WRITE (UFFF,"(I14,I6,F11.3,F11.3,F15.3,F11.2,F10.2)") p_grid%NumGrid_Y, p_grid%NumGrid_Z, p_grid%GridRes_Y, p_grid%GridRes_Z, p_grid%TimeStep, p_grid%HubHt, UHub + WRITE (UFFF,"(/,' Z Coordinates (m):')") + WRITE (UFFF,FormStr5) ( p_grid%Z(p_grid%GridPtIndx(IZ))-p_grid%HubHt, IZ=1,p_grid%NPoints,p_grid%NumGrid_Y ) + WRITE (UFFF,"(/,' Y Coordinates (m):')") + WRITE (UFFF,FormStr5) ( p_grid%Y(p_grid%GridPtIndx(IY)), IY=1,p_grid%NumGrid_Y ) + + ! Write out elapsed time & hub-level value before component grid. + + DO IT=1,p_grid%NumOutSteps + + WRITE(UFFF,"(/,1X,2(F8.3))") p_grid%TimeStep*( IT - 1 ), V(IT,p_grid%HubIndx,IVec) + + DO IZ=1,p_grid%NumGrid_Z ! From the top to the bottom + + II = ( p_grid%NumGrid_Z - IZ )*p_grid%NumGrid_Y + + WRITE (UFFF,FormStr5) ( V(IT, p_grid%GridPtIndx(II+IY) ,IVec), IY=1,p_grid%NumGrid_Y ) ! From the left to the right + + ENDDO ! IZ + + ENDDO ! IT + + CLOSE ( UFFF ) + + ENDDO ! IVec + + ! Deallocate the array of wind speeds. + + IF ( ALLOCATED( ZRow ) ) DEALLOCATE( ZRow ) + +END SUBROUTINE WrFormattedFF +!======================================================================= + +SUBROUTINE WrSum_UserInput( p_met, p_usr, US ) + + + TYPE(Meteorology_ParameterType), INTENT(IN) :: p_met ! meteorology parameters for TurbSim + TYPE(UserTSSpec_ParameterType), INTENT(IN) :: p_usr ! user-defined parameters for TurbSim + + INTEGER, INTENT(IN) :: US + integer :: i + + + IF ( p_met%NumUSRz > 0 ) THEN + WRITE (US,"( // 'User-Defined Profiles:' / )") + + IF ( ALLOCATED( p_met%USR_L ) ) THEN + WRITE (US,"(A)") ' Height Wind Speed Horizontal Angle u Std. Dev. v Std. Dev. w Std. Dev. Length Scale' + WRITE (US,"(A)") ' (m) (m/s) (deg) (m/s) (m/s) (m/s) (m) ' + WRITE (US,"(A)") ' ------ ---------- ---------------- ----------- ----------- ----------- ------------' + + DO I=p_met%NumUSRz,1,-1 + WRITE (US,"( 1X,F7.2, 2X,F9.2,2X, 3X,F10.2,6X, 3(4X,F7.2,3X), 3X,F10.2 )") & + p_met%USR_Z(I), p_met%USR_U(I), p_met%USR_WindDir(I), & + p_met%USR_Sigma(I)*p_met%USR_StdScale(1), p_met%USR_Sigma(I)*p_met%USR_StdScale(2), & + p_met%USR_Sigma(I)*p_met%USR_StdScale(3), p_met%USR_L(I) + ENDDO + ELSE + WRITE (US,"(A)") ' Height Wind Speed Horizontal Angle' + WRITE (US,"(A)") ' (m) (m/s) (deg) ' + WRITE (US,"(A)") ' ------ ---------- ----------------' + + DO I=p_met%NumUSRz,1,-1 + WRITE (US,"( 1X,F7.2, 2X,F9.2,2X, 3X,F10.2)") p_met%USR_Z(I), p_met%USR_U(I), p_met%USR_WindDir(I) + ENDDO + ENDIF + + ENDIF + + IF ( p_usr%nPoints > 0 ) THEN + WRITE (US,"( // 'Profiles from User-Defined Time-Series Input:' / )") + + WRITE (US,"(A)") ' Height Wind Speed Horizontal Angle Vertical Angle' + WRITE (US,"(A)") ' (m) (m/s) (deg) (deg) ' + WRITE (US,"(A)") ' ------ ---------- ---------------- --------------' + + DO I=p_usr%nPoints,1,-1 + WRITE (US,"( 1X,F7.2, 2X,F9.2,2X, 3X,F10.2,10x,F10.2)") p_usr%pointzi(I), p_usr%meanU(I,1), p_usr%meanDir(I), p_usr%meanVAng(I) + END DO + + END IF + + +END SUBROUTINE WrSum_UserInput +!======================================================================= +SUBROUTINE WrSum_SpecModel(p, U, HWindDir, VWindDir, ErrStat, ErrMsg ) + + TYPE(TurbSim_ParameterType), INTENT(INout) :: p ! parameters for TurbSim !BJJ: FIX THIS!!! TODO: create equivalent plExp elsewhere + REAL(ReKi), INTENT(IN) :: HWindDir(:) ! profile of horizontal wind direction + REAL(ReKi), INTENT(IN) :: VWindDir(:) ! profile of vertical wind direction + REAL(ReKi), INTENT(IN) :: U (:) ! profile of steady wind speed + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + ! local variables: + + REAL(ReKi) :: HalfRotDiam ! Half of the rotor diameter + + + + REAL(ReKi) :: UTmp ! The best fit of observed peak Uh at het height vs jet height + REAL(ReKi) :: U_zb ! The velocity at the bottom of the rotor disk (for estimating log fit) + REAL(ReKi) :: U_zt ! The velocity at the top of the rotor disk (for estimating log fit) + + INTEGER :: iz, jz ! loop counter/indices of points + LOGICAL :: HubPr ! Flag to indicate if the hub height is to be printed separately in the summary file + + CHARACTER(200) :: FormStr ! String used to store format specifiers. + CHARACTER(*),PARAMETER :: FormStr1 = "(' ',A,' =' ,I9 ,A)" ! String used to store format specifiers. + CHARACTER(*),PARAMETER :: FormStr2 = "(' ',A,' = ',A)" ! String used to store format specifiers. + + + ! write to the summary file: + ErrStat = ErrID_None + ErrMsg = "" + + + WRITE (p%US,"( // 'Turbulence Simulation Scaling Parameter Summary:' / )") + WRITE (p%US, "(' Turbulence model used = ' , A )") TRIM(p%met%TMName) + + FormStr = "(' ',A,' =' ,F9.3,A)" + + + + ! Write out a parameter summary to the summary file. + +IF ( ( p%met%TurbModel_ID == SpecModel_IECKAI ) .OR. & + ( p%met%TurbModel_ID == SpecModel_IECVKM ) .OR. & + ( p%met%TurbModel_ID == SpecModel_MODVKM ) .OR. & + ( p%met%TurbModel_ID == SpecModel_API ) ) THEN ! ADDED BY YGUO on April 19, 2013 snow day!!! + + + IF ( p%IEC%NumTurbInp ) THEN + WRITE (p%US,FormStr2) "Turbulence characteristic ", "User-specified" + ELSE + WRITE (p%US,FormStr2) "Turbulence characteristic ", TRIM(p%IEC%IECTurbE)//p%IEC%IECTurbC + WRITE (p%US,FormStr2) "IEC turbulence type ", TRIM(p%IEC%IEC_WindDesc) + + IF ( p%IEC%IEC_WindType /= IEC_NTM ) THEN + WRITE (p%US,FormStr) "Reference wind speed average over 10 minutes ", p%IEC%Vref, " m/s" + WRITE (p%US,FormStr) "Annual wind speed average at hub height ", p%IEC%Vave, " m/s" + ENDIF + ENDIF + + WRITE (p%US,FormStr2) "IEC standard ", TRIM(p%IEC%IECeditionSTR) + + IF ( p%met%TurbModel_ID /= SpecModel_MODVKM ) THEN + ! Write out a parameter summary to the summary file. + + WRITE (p%US,FormStr) "Mean wind speed at hub height ", p%UHub, " m/s" + + IF (.NOT. p%IEC%NumTurbInp) THEN ! "A", "B", or "C" turbulence: + IF ( p%IEC%IECedition == 2 ) THEN + WRITE (p%US,FormStr) "Char value of turbulence intensity at 15 m/s ", 100.0*p%IEC%TurbInt15, "%" + WRITE (p%US,FormStr) "Standard deviation slope ", p%IEC%SigmaSlope, "" + ELSE + ! This is supposed to be the expected value of what is measured at a site. + ! We actually calculate the 90th percentile value to use in the code as the + ! "Characteristic Value". + WRITE (p%US,FormStr) "Expected value of turbulence intensity at 15 m/s", 100.0*p%IEC%TurbInt15, "%" + ENDIF + + ENDIF + + WRITE (p%US,FormStr) "Characteristic value of standard deviation ", p%IEC%SigmaIEC(1), " m/s" + WRITE (p%US,FormStr) "Turbulence scale ", p%IEC%Lambda(1), " m" + + IF ( p%met%TurbModel_ID == SpecModel_IECKAI ) THEN + WRITE (p%US,FormStr) "u-component integral scale ", p%IEC%IntegralScale(1), " m" + WRITE (p%US,FormStr) "Coherency scale ", p%IEC%LC, " m" + ELSEIF ( p%met%TurbModel_ID == SpecModel_IECVKM ) THEN + WRITE (p%US,FormStr) "Isotropic integral scale ", p%IEC%IntegralScale(1), " m" + ENDIF + + WRITE (p%US,FormStr) "Characteristic value of hub turbulence intensity", 100.0*p%IEC%TurbInt, "%" + + ELSE ! ModVKM +!bjj this is never set in TurbSim: WRITE (p%US,FormStr1) "Boundary layer depth ", NINT(h), " m" + WRITE (p%US,FormStr) "Site Latitude ", p%met%Latitude, " degs" + WRITE (p%US,FormStr) "Hub mean streamwise velocity ", p%UHub, " m/s" + WRITE (p%US,FormStr) "Hub local u* ", p%met%Ustar, " m/s" !BONNIE: is this LOCAL? of Disk-avg + WRITE (p%US,FormStr) "Target IEC Turbulence Intensity ", 100.0*p%IEC%TurbInt, "%" + WRITE (p%US,FormStr) "Target IEC u-component standard deviation ", p%IEC%SigmaIEC(1), " m/s" + WRITE (p%US,FormStr) "u-component integral scale ", p%IEC%Lambda(1), " m" + WRITE (p%US,FormStr) "v-component integral scale ", p%IEC%Lambda(2), " m" + WRITE (p%US,FormStr) "w-component integral scale ", p%IEC%Lambda(3), " m" + WRITE (p%US,FormStr) "Isotropic integral scale ", p%IEC%LC, " m" + ENDIF + WRITE (p%US,FormStr) "Gradient Richardson number ", 0.0, "" + +! p%met%Ustar = SigmaIEC/2.15 ! Value based on equating original Kaimal spectrum with IEC formulation + +ELSEIF ( p%met%TurbModel_ID == SpecModel_TIDAL ) THEN + WRITE (p%US,FormStr2) "Gradient Richardson number ", "N/A" + WRITE (p%US,FormStr) "Mean velocity at hub height ", p%UHub, " m/s" + +ELSE + + WRITE (p%US,FormStr) "Gradient Richardson number ", p%met%Rich_No, "" + WRITE (p%US,FormStr) "Monin-Obukhov (M-O) z/L parameter ", p%met%ZL, "" + + IF ( .not. EqualRealNos( p%met%ZL, 0.0_ReKi ) ) THEN + WRITE (p%US,FormStr) "Monin-Obukhov (M-O) length scale ", p%met%L, " m" + ELSE + WRITE (p%US,FormStr2) "Monin-Obukhov (M-O) length scale ", "Infinite" + ENDIF + WRITE (p%US,FormStr) "Mean wind speed at hub height ", p%UHub, " m/s" + +ENDIF ! TurbModel == 'IECKAI', 'IECVKM', or 'MODVKM' + + +HalfRotDiam = 0.5*p%grid%RotorDiameter +CALL getVelocity(p, p%UHub,p%grid%HubHt, p%grid%HubHt+HalfRotDiam, U_zt, ErrStat, ErrMsg) !Velocity at the top of rotor +CALL getVelocity(p, p%UHub,p%grid%HubHt, p%grid%HubHt-HalfRotDiam, U_zb, ErrStat, ErrMsg) !Velocity at the bottom of the rotor + +IF ( TRIM(p%met%WindProfileType) /= 'PL' .AND. TRIM(p%met%WindProfileType) /= 'IEC' ) THEN +!SELECT CASE ( TRIM(p%met%WindProfileType) ) +! CASE ('JET','LOG','H2L','USR','API', 'TS') !i.e., not PL or IEC + p%met%PLexp = LOG( U_zt/U_zb ) / LOG( (p%grid%HubHt+HalfRotDiam)/(p%grid%HubHt-HalfRotDiam) ) +!END SELECT +END IF + + +WRITE(p%US,'()') ! A BLANK LINE + +SELECT CASE ( TRIM(p%met%WindProfileType) ) + CASE ('JET') + UTmp = 0.0422*p%met%ZJetMax+10.1979 ! Best fit of observed peak Uh at jet height vs jet height + + WRITE (p%US,FormStr2) "Wind profile type ", "Low-level jet" + WRITE (p%US,FormStr) "Jet height ", p%met%ZJetMax, " m" + WRITE (p%US,FormStr) "Jet wind speed ", p%met%UJetMax, " m/s" + WRITE (p%US,FormStr) "Upper limit of observed jet wind speed ", UTmp, " m/s" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + IF ( UTmp < p%met%UJetMax ) THEN + CALL SetErrStat( ErrID_Warn, 'The computed jet wind speed is larger than the ' & + //'maximum observed jet wind speed at this height.', ErrStat, ErrMsg, 'WrSum_SpecModel') + ENDIF + + CASE ('LOG') + WRITE (p%US,FormStr2) "Wind profile type ", "Logarithmic" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + CASE ('H2L') + WRITE (p%US,FormStr2) "Velocity profile type ", "Logarithmic (H2L)" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + CASE ('PL') + WRITE (p%US,FormStr2) "Wind profile type ", "Power law" + WRITE (p%US,FormStr) "Power law exponent ", p%met%PLExp, "" + + CASE ('USR') + WRITE (p%US,FormStr2) "Wind profile type ", "Linear interpolation of user-defined profile" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + CASE ('TS') + WRITE (p%US,FormStr2) "Wind profile type ", "Linear interpolation of user-defined profile generated by time-series data" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + CASE ('API') +!bjj : fix me:!!! + WRITE (p%US,FormStr2) "Wind profile type ", "API" + WRITE (p%US,FormStr) "Equivalent power law exponent across rotor disk ", p%met%PLexp, "" + + CASE DEFAULT + WRITE (p%US,FormStr2) "Wind profile type ", "Power law on rotor disk, logarithmic elsewhere" + WRITE (p%US,FormStr) "Power law exponent ", p%met%PLExp, "" + +END SELECT + +WRITE(p%US,FormStr) "Mean shear across rotor disk ", (U_zt-U_zb)/p%grid%RotorDiameter, " (m/s)/m" +WRITE(p%US,FormStr) "Assumed rotor diameter ", p%grid%RotorDiameter, " m" +WRITE(p%US,FormStr) "Surface roughness length ", p%met%Z0, " m" +WRITE(p%US,'()') ! A BLANK LINE +WRITE(p%US,FormStr ) "Nyquist frequency of turbulent wind field ", 0.5_ReKi / p%grid%TimeStep," Hz" +WRITE(p%US,'()') ! A BLANK LINE +WRITE(p%US,FormStr1) "Number of time steps in the FFT ", p%grid%NumSteps, "" +WRITE(p%US,FormStr1) "Number of time steps output ", p%grid%NumOutSteps, "" +WRITE(p%US,FormStr1) "Number of points simulated ", p%grid%NPoints, "" + + +IF (p%met%KHtest) THEN + WRITE(p%US,"(/'KH Billow Test Parameters:' / )") ! HEADER + WRITE(p%US,FormStr) "Gradient Richardson number ", p%met%Rich_No, "" + WRITE(p%US,FormStr) "Power law exponent ", p%met%PLexp, "" + WRITE(p%US,FormStr) "Length of coherent structures ", p%grid%UsableTime / 2.0, " s" + WRITE(p%US,FormStr) "Minimum coherent TKE ", 30.0, " (m/s)^2" +ENDIF + + + ! Write mean flow angles and wind speed profile to the summary file. + +WRITE(p%US,"(//,'Mean Flow Angles:',/)") + +FormStr = "(3X,A,F6.1,' degrees')" +WRITE(p%US,FormStr) 'Vertical =', p%met%VFlowAng +WRITE(p%US,FormStr) 'Horizontal =', p%met%HFlowAng + + +WRITE(p%US,"(/'Mean Wind Speed Profile:')") + +IF ( ALLOCATED( p%met%ZL_profile ) .AND. ALLOCATED( p%met%Ustar_profile ) ) THEN + WRITE(p%US,"(/,' Height Wind Speed Horizontal Angle Vertical Angle U-comp (X) V-comp (Y) W-comp (Z) z/L(z) u*(z)')") + WRITE(p%US,"( ' (m) (m/s) (degrees) (degrees) (m/s) (m/s) (m/s) (-) (m/s)')") + WRITE(p%US,"( ' ------ ---------- ---------------- -------------- ---------- ---------- ---------- ------ ------')") + + FormStr = '(1X,F8.1,1X,F11.2,2(5x,F11.2),4x,3(2X,F8.2,3X),2(1X,F8.3))' +ELSE + WRITE(p%US,"(/,' Height Wind Speed Horizontal Angle Vertical Angle U-comp (X) V-comp (Y) W-comp (Z)')") + WRITE(p%US,"( ' (m) (m/s) (degrees) (degrees) (m/s) (m/s) (m/s) ')") + WRITE(p%US,"( ' ------ ---------- ---------------- -------------- ---------- ---------- ----------')") + + FormStr = '(1X,F8.1,1X,F11.2,2(5x,F11.2),4x,3(2X,F8.2,3X))' +ENDIF + + + + ! Get the angles to rotate the wind components from streamwise orientation to the X-Y-Z grid at the Hub + +HubPr = .NOT. p%grid%HubOnGrid !If the hub height is not on the z-grid, print it, too. + + + ! Write out the grid points & the hub + +DO JZ = p%grid%NumGrid_Z,1, -1 + + IZ = p%grid%GridPtIndx( (JZ-1)*p%grid%NumGrid_Y+1 ) + + IF ( HubPr .AND. ( p%grid%Z(IZ) < p%grid%HubHt ) ) THEN + + CALL writeLine( p%grid%HubIndx ) + + HubPr = .FALSE. ! we've printed the hub values, so we don't need to check this anymore + ENDIF + + CALL writeLine( IZ ) + +ENDDO ! JZ + + ! Write out the tower points +DO JZ = 2, SIZE(p%grid%TwrPtIndx) + CALL writeLine( p%grid%TwrPtIndx(JZ) ) +ENDDO ! JZ + +!.................................................. +CONTAINS + SUBROUTINE writeLine(Indx) + + INTEGER(IntKi), INTENT(IN) :: Indx + + REAL(ReKi) :: CVFA ! Cosine of the vertical flow angle + REAL(ReKi) :: SVFA ! Sine of the vertical flow angle + REAL(ReKi) :: CHFA ! Cosine of the horizontal flow angle + REAL(ReKi) :: SHFA ! Sine of the horizontal flow angle + + CHFA = COS( HWindDir(Indx)*D2R ) + SHFA = SIN( HWindDir(Indx)*D2R ) + + CVFA = COS( VWindDir(Indx)*D2R ) + SVFA = SIN( VWindDir(Indx)*D2R ) + + + IF ( ALLOCATED( p%met%ZL_profile ) ) THEN + WRITE(p%US,FormStr) p%grid%Z(Indx), U(Indx), HWindDir(Indx), VWindDir(Indx), U(Indx)*CHFA*CVFA, U(Indx)*SHFA*CVFA, U(Indx)*SVFA, & + p%met%ZL_profile(Indx), p%met%Ustar_profile(Indx) + ELSE + WRITE(p%US,FormStr) p%grid%Z(Indx), U(Indx), HWindDir(Indx), VWindDir(Indx), U(Indx)*CHFA*CVFA, U(Indx)*SHFA*CVFA, U(Indx)*SVFA + ENDIF + END SUBROUTINE writeLine + +END SUBROUTINE WrSum_SpecModel +!======================================================================= +SUBROUTINE WrHH_ADtxtfile(p, V, TurbInt, ErrStat, ErrMsg) + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(IN) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + REAL(ReKi), INTENT(IN) :: TurbInt !< IEC target Turbulence Intensity + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + REAL(ReKi) :: V_Inertial(3) ! U,V,W components (inertial) + REAL(ReKi) :: UH ! horizontal wind speed (U+V components) + + REAL(ReKi) :: Time ! The instantaneous Time (s) + INTEGER(IntKi) :: IT ! loop counter (time step) + INTEGER :: UAHH ! I/O unit for AeroDyn HH data (*.hh file). + + + + + CALL GetNewUnit( UAHH, ErrStat, ErrMsg) + CALL OpenFOutFile ( UAHH, TRIM( p%RootName)//'.hh', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL WrScr ( ' Hub-height AeroDyn data were written to "'//TRIM( p%RootName )//'.hh"' ) + + WRITE (UAHH,"( '! This hub-height wind-speed file was generated by ' , A , ' on ' , A , ' at ' , A , '.' )") TRIM(GetNVD(TurbSim_Ver)), CurDate(), CurTime() + WRITE (UAHH,"( '!' )") + WRITE (UAHH,"( '! The requested statistics for this data were:' )") + WRITE (UAHH,"( '! Mean Total Wind Speed = ' , F8.3 , ' m/s' )") p%UHub +IF ( p%met%TurbModel_ID == SpecModel_IECKAI .OR. p%met%TurbModel_ID == SpecModel_IECVKM .OR. p%met%TurbModel_ID == SpecModel_MODVKM ) THEN + WRITE (UAHH,"( '! Turbulence Intensity = ' , F8.3 , '%' )") 100.0*TurbInt +ELSE + WRITE (UAHH,"( '!' )") +ENDIF + WRITE (UAHH,"( '!' )") + WRITE (UAHH,"( '! Time HorSpd WndDir VerSpd HorShr VerShr LnVShr GstSpd' )") + WRITE (UAHH,"( '! (sec) (m/s) (deg) (m/s) (-) (-) (-) (m/s)' )") + + DO IT = 1, p%grid%NumOutSteps + + Time = p%grid%TimeStep*( IT - 1 ) + + CALL CalculateWindComponents(V(IT,p%grid%HubIndx,:), p%UHub, p%met%HH_HFlowAng, p%met%HH_VFlowAng, V_Inertial, UH) + + WRITE (UAHH,'(F8.3,3F8.2,3F8.3,F8.2)') Time, UH, -1.0*R2D*ATAN2( V_Inertial(2) , V_Inertial(1) ), & + V_Inertial(3), 0.0, p%met%PLExp, 0.0, 0.0 +!bjj: Should we output instantaneous horizontal shear, instead of 0? +! Should the power law exponent be an instantaneous value, too? +! + END DO + + CLOSE(UAHH) + + +END SUBROUTINE WrHH_ADtxtfile +!======================================================================= +SUBROUTINE WrHH_binary(p, V, ErrStat, ErrMsg) + + ! Output HH binary turbulence parameters for GenPro analysis. + ! Output order: Time,U,Uh,Ut,V,W,u',v',w',u'w',u'v',v'w',TKE,CTKE. + + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(IN) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + ! local variables + + REAL(ReKi) :: V_Inertial(3) ! U,V,W components (inertial) + REAL(ReKi) :: UH ! horizontal wind speed (U+V components) + REAL(ReKi) :: UT ! total wind speed (U+V+W components) + REAL(ReKi) :: uv ! The instantaneous u'v' Reynolds stress at the hub + REAL(ReKi) :: uw ! The instantaneous u'w' Reynolds stress at the hub + REAL(ReKi) :: vw ! The instantaneous v'w' Reynolds stress at the hub + REAL(ReKi) :: TKE ! The instantaneous TKE at the hub + REAL(ReKi) :: CTKE ! The instantaneous CTKE the hub + + REAL(ReKi) :: Time ! The instantaneous Time (s) + INTEGER(IntKi) :: IT ! loop counter (time step) + INTEGER :: UGTP ! I/O unit for GenPro HH turbulence properties. + + + + CALL GetNewUnit(UGTP, ErrStat, ErrMsg) + + CALL OpenUOutfile ( UGTP , TRIM( p%RootName)//'.bin', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL WrScr ( ' Hub-height binary turbulence parameters were written to "'//TRIM( p%RootName )//'.bin"' ) + + DO IT = 1, p%grid%NumOutSteps + + Time = p%grid%TimeStep*( IT - 1 ) + + CALL CalculateWindComponents(V(IT,p%grid%HubIndx,:), p%UHub, p%met%HH_HFlowAng, p%met%HH_VFlowAng, V_Inertial, UH, UT) + CALL CalculateStresses( V(IT,p%grid%HubIndx,:), uv, uw, vw, TKE, CTKE ) + + WRITE (UGTP) REAL(Time,SiKi), REAL(V_Inertial(1),SiKi), REAL(UH,SiKi), REAL(UT,SiKi), & + REAL(V_Inertial(2),SiKi), REAL(V_Inertial(3),SiKi), & + REAL(V(IT,p%grid%HubIndx,1),SiKi), & + REAL(V(IT,p%grid%HubIndx,2),SiKi), & + REAL(V(IT,p%grid%HubIndx,3),SiKi), & + REAL(uw,SiKi), REAL(uv,SiKi), REAL(vw,SiKi), REAL(TKE,SiKi), REAL(CTKE,SiKi) + + END DO + + CLOSE(UGTP) +!p%WrFile(FileExt_BIN) + +END SUBROUTINE WrHH_binary +!======================================================================= +SUBROUTINE WrHH_text(p, V, ErrStat, ErrMsg) + + ! Output HH text turbulence parameters + ! Output order: Time,U,Uh,Ut,V,W,u',v',w',u'w',u'v',v'w',TKE,CTKE. + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(IN) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + ! local variables + + REAL(ReKi) :: V_Inertial(3) ! U,V,W components (inertial) + REAL(ReKi) :: UH ! horizontal wind speed (U+V components) + REAL(ReKi) :: UT ! total wind speed (U+V+W components) + REAL(ReKi) :: uv ! The instantaneous u'v' Reynolds stress at the hub + REAL(ReKi) :: uw ! The instantaneous u'w' Reynolds stress at the hub + REAL(ReKi) :: vw ! The instantaneous v'w' Reynolds stress at the hub + REAL(ReKi) :: TKE ! The instantaneous TKE at the hub + REAL(ReKi) :: CTKE ! The instantaneous CTKE the hub + + REAL(ReKi) :: Time ! The instantaneous Time (s) + INTEGER(IntKi) :: IT ! loop counter (time step) + INTEGER(IntKi) :: UFTP ! I/O unit for formatted HH turbulence properties + + + ! p%WrFile(FileExt_DAT) + + CALL GetNewUnit( UFTP, ErrStat, ErrMsg ) + CALL OpenFOutFile ( UFTP, TRIM( p%RootName)//'.dat', ErrStat, ErrMsg ) + IF (ErrStat >= AbortErrLev) RETURN + + CALL WrScr ( ' Hub-height formatted turbulence parameters were written to "'//TRIM( p%RootName )//'.dat"' ) + + WRITE (UFTP,"( / 'This hub-height turbulence-parameter file was generated by ' , A , ' on ' , A , ' at ' , A , '.' / )") & + TRIM(GetNVD(TurbSim_Ver)), CurDate(), CurTime() + + WRITE (UFTP,"(' Time',6X,'U',7X,'Uh',7X,'Ut',8X,'V',8X,'W',8X,'u''',7X,'v''',7X,'w'''," & + //"6X,'u''w''',5X,'u''v''',5X,'v''w''',5X,'TKE',6X,'CTKE')") + + + DO IT = 1, p%grid%NumOutSteps + + Time = p%grid%TimeStep*( IT - 1 ) + + CALL CalculateWindComponents(V(IT,p%grid%HubIndx,:), p%UHub, p%met%HH_HFlowAng, p%met%HH_VFlowAng, V_Inertial, UH, UT) + CALL CalculateStresses( V(IT,p%grid%HubIndx,:), uv, uw, vw, TKE, CTKE ) + + + WRITE(UFTP,'(F7.2,13F9.3)') Time,V_Inertial(1),UH,UT,V_Inertial(2),V_Inertial(3), & + V(IT,p%grid%HubIndx,1), V(IT,p%grid%HubIndx,2), V(IT,p%grid%HubIndx,3), & + uw, uv, vw, TKE, CTKE + + + END DO + + CLOSE(UFTP) + +END SUBROUTINE WrHH_text +!======================================================================= +SUBROUTINE WrSum_Stats(p, V, USig, VSig, WSig, ErrStat, ErrMsg) + + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p ! parameters +REAL(ReKi), INTENT(IN ) :: V (:,:,:) ! An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), INTENT( OUT) :: USig ! Standard deviation of the u-component wind speed at the hub +REAL(ReKi), INTENT( OUT) :: VSig ! Standard deviation of the v-component wind speed at the hub +REAL(ReKi), INTENT( OUT) :: WSig ! Standard deviation of the w-component wind speed at the hub + +INTEGER(IntKi), intent( out) :: ErrStat ! Error level +CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + +REAL(DbKi) :: denom ! denominator of equation +REAL(DbKi) :: SumS ! Sum of the velocity-squared, used for calculating standard deviations in the summary file +REAL(DbKi) :: UBar ! The mean u-component wind speed at the hub +REAL(DbKi) :: UHBar ! The mean horizontal wind speed at the hub +REAL(DbKi) :: UHSum2 ! The sum of the squared horizontal wind speed at the hub +REAL(DbKi) :: UHTmp ! The instantaneous horizontal wind speed at the hub +REAL(DbKi) :: UHTmp2 ! The instantaneous squared horizontal wind speed at the hub +REAL(DbKi) :: USum2 ! The sum of the squared u-component wind speed at the hub +REAL(DbKi) :: UTBar ! The mean total wind speed at the hub +REAL(DbKi) :: UTmp ! The instantaneous u-component wind speed at the hub +REAL(DbKi) :: UTmp2 ! The instantaneous squared u-component wind speed at the hub +REAL(DbKi) :: UTSum2 ! The sum of the squared total wind speed at the hub +REAL(DbKi) :: UTTmp ! The instantaneous total wind speed at the hub +REAL(DbKi) :: UTTmp2 ! The instantaneous squared total wind speed at the hub +REAL(DbKi) :: UXBar ! The mean U-component (u rotated; x-direction) wind speed at the hub +REAL(DbKi) :: UXSum ! The sum of the U-component (u rotated) wind speed at the hub +REAL(DbKi) :: UXSum2 ! The sum of the squared U-component (u rotated) wind speed at the hub +REAL(DbKi) :: UXTmp ! The instantaneous U-component (u rotated) wind speed at the hub +REAL(DbKi) :: UXTmp2 ! The instantaneous squared U-component (u rotated) wind speed at the hub +REAL(DbKi) :: UYBar ! The mean V-component (v rotated; y-direction) wind speed at the hub +REAL(DbKi) :: UYSum ! The sum of the V-component (v rotated) wind speed at the hub +REAL(DbKi) :: UYSum2 ! The sum of the squared V-component (v rotated) wind speed at the hub +REAL(DbKi) :: UYTmp ! The instantaneous V-component (v rotated) wind speed at the hub +REAL(DbKi) :: UYTmp2 ! The instantaneous squared V-component (v rotated) wind speed at the hub +REAL(DbKi) :: UZBar ! The mean W-component (w rotated; z-direction) wind speed at the hub +REAL(DbKi) :: UZSum ! The sum of the W-component (w rotated) wind speed at the hub +REAL(DbKi) :: UZSum2 ! The sum of the squared W-component (w rotated) wind speed at the hub +REAL(DbKi) :: UZTmp ! The instantaneous W-component (w rotated) wind speed at the hub +REAL(DbKi) :: UZTmp2 ! The instantaneous squared W-component (w rotated) wind speed at the hub +REAL(DbKi) :: VBar ! The mean v-component wind speed at the hub +REAL(DbKi) :: VSum2 ! The sum of the squared v-component wind speed at the hub +REAL(DbKi) :: VTmp ! The instantaneous v-component wind speed at the hub +REAL(DbKi) :: VTmp2 ! The instantaneous squared v-component wind speed at the hub +REAL(DbKi) :: WBar ! The mean w-component wind speed at the hub +REAL(DbKi) :: WSum2 ! The sum of the squared w-component wind speed at the hub +REAL(DbKi) :: WTmp ! The instantaneous w-component wind speed at the hub +REAL(DbKi) :: WTmp2 ! The instantaneous squared w-component wind speed at the hub + +REAL(ReKi) :: CHFA ! Cosine of the Horizontal Flow Angle +REAL(ReKi) :: CVFA ! Cosine of the Vertical Flow Angle +REAL(ReKi) :: SVFA ! Sine of the Vertical Flow Angle +REAL(ReKi) :: SHFA ! Sine of the Horizontal Flow Angle +REAL(ReKi) :: CTKEmax ! Maximum instantaneous Coherent Turbulent Kenetic Energy at the hub +REAL(ReKi) :: TKEmax ! Maximum instantaneous Turbulent Kenetic Energy at the hub + + +REAL(ReKi) :: UHmax ! Maximum horizontal wind speed at the hub +REAL(ReKi) :: UHmin ! Minimum horizontal wind speed at the hub +REAL(ReKi) :: Umax ! Maximum u-component wind speed at the hub +REAL(ReKi) :: Umin ! Minimum u-component wind speed at the hub +REAL(ReKi) :: UTSig ! Standard deviation of the total wind speed at the hub +REAL(ReKi) :: UT_TI ! Turbulent Intensity of the total wind speed at the hub +REAL(ReKi) :: UTmax ! Maximum total wind speed at the hub +REAL(ReKi) :: UTmin ! Minimum total wind speed at the hub +REAL(ReKi) :: UVMax ! Maximum u'v' Reynolds Stress at the hub +REAL(ReKi) :: UVMin ! Minimum u'v' Reynolds Stress at the hub +REAL(ReKi) :: UVTmp ! The instantaneous u'v' Reynolds stress at the hub +REAL(ReKi) :: UV_RS ! The average u'v' Reynolds stress at the hub +REAL(ReKi) :: UVcor ! The u-v cross component correlation coefficient at the hub +REAL(ReKi) :: UVsum ! The sum of the u'v' Reynolds stress component at the hub +REAL(ReKi) :: UWMax ! Maximum u'w' Reynolds Stress at the hub +REAL(ReKi) :: UWMin ! Minimum u'w' Reynolds Stress at the hub +REAL(ReKi) :: UWTmp ! The instantaneous u'w' Reynolds stress at the hub +REAL(ReKi) :: UW_RS ! The average u'w' Reynolds stress at the hub +REAL(ReKi) :: UWcor ! The u-w cross component correlation coefficient at the hub +REAL(ReKi) :: UWsum ! The sum of the u'w' Reynolds stress component at the hub +REAL(ReKi) :: UXmax ! Maximum U-component (X-direction) wind speed at the hub +REAL(ReKi) :: UXmin ! Minimum U-component wind speed at the hub +REAL(ReKi) :: UXSig ! Standard deviation of the U-component wind speed at the hub +REAL(ReKi) :: UYmax ! Maximum V-component (Y-direction) wind speed at the hub +REAL(ReKi) :: UYmin ! Minimum V-component wind speed at the hub +REAL(ReKi) :: UYSig ! Standard deviation of the V-component wind speed at the hub +REAL(ReKi) :: UZmax ! Maximum W-component (Z-direction) wind speed at the hub +REAL(ReKi) :: UZmin ! Minimum W-component wind speed at the hub +REAL(ReKi) :: UZSig ! Standard deviation of the W-component wind speed at the hub +REAL(ReKi) :: U_TI ! The u-component turbulence intensity at the hub +REAL(ReKi) :: Vmax ! Maximum v-component wind speed at the hub +REAL(ReKi) :: Vmin ! Minimum v-component wind speed at the hub +REAL(ReKi) :: VWMax ! Maximum v'w' Reynolds Stress at the hub +REAL(ReKi) :: VWMin ! Minimum v'w' Reynolds Stress at the hub +REAL(ReKi) :: VWTmp ! The instantaneous v'w' Reynolds stress at the hub +REAL(ReKi) :: VW_RS ! The average v'w' Reynolds stress at the hub +REAL(ReKi) :: VWcor ! The v-w cross component correlation coefficient at the hub +REAL(ReKi) :: VWsum ! The sum of the v'w' Reynolds stress component at the hub +REAL(ReKi) :: V_TI ! The v-component turbulence intensity at the hub +REAL(ReKi) :: Wmax ! Maximum w-component wind speed at the hub +REAL(ReKi) :: Wmin ! Minimum w-component wind speed at the hub +REAL(ReKi) :: W_TI ! The w-component turbulence intensity at the hub + +REAL(ReKi) :: CTKE ! Coherent Turbulent Kenetic Energy at the hub +REAL(ReKi) :: TKE ! Turbulent Kenetic Energy at the hub +REAL(ReKi) :: INumSteps ! Multiplicative Inverse of the Number of time Steps +REAL(ReKi) :: UHSig ! Approximate sigma of the horizontal wind speed at the hub point +REAL(ReKi) :: SUstar ! Simulated U-star at the hub +REAL(ReKi), ALLOCATABLE :: SDary (:) ! The array of standard deviations (NumGrid_Z,NumGrid_Y). + +REAL(ReKi) :: UH_TI ! TI of the horizontal wind speed at the hub point + + +INTEGER(IntKi) :: IT, IVec, IY, IZ, II + + CHARACTER(200) :: FormStr ! String used to store format specifiers. + CHARACTER(*),PARAMETER :: FormStr2 = "(6X,A,' component: ',F8.3,' m/s')" ! String used to store format specifiers. + + + ! Initialize statistical quantities for hub-height turbulence parameters. + + CALL WrScr ( ' Computing hub-height statistics' ) + + INumSteps = 1.0/p%grid%NumSteps + + CTKEmax = -HUGE( CTKEmax ) + TKEmax = -HUGE( TKEmax ) + UBar = 0.0 + UHBar = 0.0 + UHmax = -HUGE( UHmax ) + UHmin = HUGE( UHmin ) + UHSum2 = 0.0 + Umax = -HUGE( Umax ) + Umin = HUGE( Umin ) + USum2 = 0.0 + UTBar = 0.0 + UTmax = -HUGE( UTmax ) + UTmin = HUGE( UTmin ) + UTSum2 = 0.0 + UV_RS = 0.0 + UVMax = V(1,p%grid%HubIndx,1)*V(1,p%grid%HubIndx,2) + UVMin = HUGE( UVMin ) + UVsum = 0.0 + UW_RS = 0.0 + UWMax = V(1,p%grid%HubIndx,1)*V(1,p%grid%HubIndx,3) + UWMin = HUGE( UWMin ) + UWsum = 0.0 + VBar = 0.0 + Vmax = -HUGE( Vmax ) + Vmin = HUGE( Vmin ) + VSum2 = 0.0 + VW_RS = 0.0 + VWMax = V(1,p%grid%HubIndx,2)*V(1,p%grid%HubIndx,3) + VWMin = HUGE( VWMin ) + VWsum = 0.0 + WBar = 0.0 + Wmax = -HUGE( Wmax ) + Wmin = HUGE( Wmin ) + WSum2 = 0.0 + UXBar = 0.0 + UXmax = -HUGE( UXmax ) + UXmin = HUGE( UXmin ) + UXSum = 0.0 + UXSum2 = 0.0 + UXTmp = 0.0 + UXTmp2 = 0.0 + UYBar = 0.0 + UYmax = -HUGE( UYmax ) + UYmin = HUGE( UYmin ) + UYSum = 0.0 + UYSum2 = 0.0 + UYTmp = 0.0 + UYTmp2 = 0.0 + UZBar = 0.0 + UZmax = -HUGE( UZmax ) + UZmin = HUGE( UZmin ) + UZSum = 0.0 + UZSum2 = 0.0 + UZTmp = 0.0 + UZTmp2 = 0.0 + + CHFA = COS( p%met%HH_HFlowAng*D2R ) + SHFA = SIN( p%met%HH_HFlowAng*D2R ) + + CVFA = COS( p%met%HH_VFlowAng*D2R ) + SVFA = SIN( p%met%HH_VFlowAng*D2R ) + + DO IT=1,p%grid%NumSteps + + ! Calculate longitudinal (UTmp), lateral (VTmp), and upward (WTmp) + ! values for hub station, as well as rotated (UXTmp, UYTmp, UZTmp) + ! components applying specified flow angles. + + ! Add mean wind speed to the streamwise component + UTmp = V(IT,p%grid%HubIndx,1) + p%UHub + VTmp = V(IT,p%grid%HubIndx,2) + WTmp = V(IT,p%grid%HubIndx,3) + + ! Rotate the wind components from streamwise orientation to the X-Y-Z grid at the Hub + UXTmp = UTmp*CHFA*CVFA - VTmp*SHFA - WTmp*CHFA*SVFA + UYTmp = UTmp*SHFA*CVFA + VTmp*CHFA - WTmp*SHFA*SVFA + UZTmp = UTmp*SVFA + WTmp*CVFA + + ! Calculate hub horizontal wind speed (UHTmp) and Total wind speed (UTTmp) + UTmp2 = UTmp*UTmp !flow coordinates + VTmp2 = VTmp*VTmp + WTmp2 = WTmp*WTmp + + UXTmp2 = UXTmp*UXTmp !inertial frame coordinates + UYTmp2 = UYTmp*UYTmp + UZTmp2 = UZTmp*UZTmp + + UHTmp2 = UXTmp2 + UYTmp2 !inertial frame coordinates + UTTmp2 = UHTmp2 + UZTmp2 + + UHTmp = SQRT( UHTmp2 ) !inertial frame coordinates + UTTmp = SQRT( UTTmp2 ) + + ! Form running sums for hub standard deviations + + UBar = UBar + UTmp !flow coordinates + VBar = VBar + VTmp !flow coordinates + WBar = WBar + WTmp !flow coordinates + + USum2 = USum2 + UTmp2 !flow coordinates + VSum2 = VSum2 + VTmp2 !flow coordinates + WSum2 = WSum2 + WTmp2 !flow coordinates + + UXBar = UXBar + UXTmp + UYBar = UYBar + UYTmp + UZBar = UZBar + UZTmp + + UXSum2 = UXSum2 + UXTmp2 + UYSum2 = UYSum2 + UYTmp2 + UZSum2 = UZSum2 + UZTmp2 + + UHBar = UHBar + UHTmp + UTBar = UTBar + UTTmp + + UHSum2 = UHSum2 + UHTmp2 + UTSum2 = UTSum2 + UTTmp2 + + + ! Determine hub extremes. + + IF ( UTmp > Umax ) Umax = UTmp !flow coordinates, + IF ( UTmp < Umin ) Umin = UTmp !flow coordinates, + + IF ( VTmp > Vmax ) Vmax = VTmp !flow coordinates, + IF ( VTmp < Vmin ) Vmin = VTmp !flow coordinates, + + IF ( WTmp > Wmax ) Wmax = WTmp !flow coordinates, + IF ( WTmp < Wmin ) Wmin = WTmp !flow coordinates, + + IF ( UXTmp > UXmax ) UXmax = UXTmp + IF ( UXTmp < UXmin ) UXmin = UXTmp + + IF ( UYTmp > UYmax ) UYmax = UYTmp + IF ( UYTmp < UYmin ) UYmin = UYTmp + + IF ( UZTmp > UZmax ) UZmax = UZTmp + IF ( UZTmp < UZmin ) UZmin = UZTmp + + IF ( UHTmp > UHmax ) UHmax = UHTmp + IF ( UHTmp < UHmin ) UHmin = UHTmp + + IF ( UTTmp > UTmax ) UTmax = UTTmp + IF ( UTTmp < UTmin ) UTmin = UTTmp + + ! Find maxes and mins of instantaneous hub Reynolds stresses u'w', u'v', and v'w' + + UVTmp = V(IT,p%grid%HubIndx,1)*V(IT,p%grid%HubIndx,2) + UWTmp = V(IT,p%grid%HubIndx,1)*V(IT,p%grid%HubIndx,3) + VWTmp = V(IT,p%grid%HubIndx,2)*V(IT,p%grid%HubIndx,3) + + IF ( UVTmp < UVMin ) THEN + UVMin = UVTmp + ELSEIF ( UVTmp > UVMax ) THEN + UVMax = UVTmp + ENDIF + + IF ( UWTmp < UWMin ) THEN + UWMin = UWTmp + ELSEIF ( UWTmp > UWMax ) THEN + UWMax = UWTmp + ENDIF + + IF ( VWTmp < VWMin ) THEN + VWMin = VWTmp + ELSEIF ( VWTmp > VWMax ) THEN + VWMax = VWTmp + ENDIF + + ! Find maximum of instantaneous TKE and CTKE. + + TKE = 0.5*(V(IT,p%grid%HubIndx,1)*V(IT,p%grid%HubIndx,1) + V(IT,p%grid%HubIndx,2)*V(IT,p%grid%HubIndx,2) + V(IT,p%grid%HubIndx,3)*V(IT,p%grid%HubIndx,3)) + CTKE = 0.5*SQRT(UVTmp*UVTmp + UWTmp*UWTmp + VWTmp*VWTmp) + + IF (CTKE > CTKEmax) CTKEmax = CTKE + IF ( TKE > TKEmax) TKEmax = TKE + + ! Find sums for mean and square Reynolds stresses for hub-level simulation. + UVsum = UVsum + UVTmp + UWsum = UWsum + UWTmp + VWsum = VWsum + VWTmp + + ENDDO ! IT + + + + ! Calculate mean hub-height Reynolds stresses. + UW_RS = UWsum*INumSteps + UV_RS = UVsum*INumSteps + VW_RS = VWsum*INumSteps + + ! Simulated Hub UStar. + SUstar = SQRT( ABS( UW_RS ) ) + + ! Calculate mean values for hub station. + + UBar = UBar*INumSteps + VBar = VBar*INumSteps + WBar = WBar*INumSteps + + UXBar = UXBar*INumSteps + UYBar = UYBar*INumSteps + UZBar = UZBar*INumSteps + + UHBar = UHBar*INumSteps + UTBar = UTBar*INumSteps + + + ! Calculate the standard deviations for hub station. + ! (SNWind/SNLwind-3D) NOTE: This algorithm is the approximate algorithm. + ! bjj: do the algebra and you'll find that it's std() using the 1/n definition + + USig = SQRT( MAX( USum2 *INumSteps-UBar *UBar , 0.0_DbKi ) ) + VSig = SQRT( MAX( VSum2 *INumSteps-VBar *VBar , 0.0_DbKi ) ) + WSig = SQRT( MAX( WSum2 *INumSteps-WBar *WBar , 0.0_DbKi ) ) + + UXSig = SQRT( MAX( UXSum2*INumSteps-UXBar*UXBar, 0.0_DbKi ) ) + UYSig = SQRT( MAX( UYSum2*INumSteps-UYBar*UYBar, 0.0_DbKi ) ) + UZSig = SQRT( MAX( UZSum2*INumSteps-UZBar*UZBar, 0.0_DbKi ) ) + + UHSig = SQRT( MAX( UHSum2*INumSteps-UHBar*UHBar, 0.0_DbKi ) ) + UTSig = SQRT( MAX( UTSum2*INumSteps-UTBar*UTBar, 0.0_DbKi ) ) + + + ! Calculate Cross-component correlation coefficients + denom = USig * WSig + if ( EqualRealNos( denom, 0.0_DbKi ) ) then + UWcor = 0.0 + else + UWcor = UW_RS / denom ! this definition assumes u' and w' have zero mean + end if + + denom = USig * VSig + if ( EqualRealNos( denom, 0.0_DbKi ) ) then + UVcor = 0.0 + else + UVcor = UV_RS / denom + end if + + denom = VSig * WSig + if ( EqualRealNos( denom, 0.0_DbKi ) ) then + VWcor = 0.0 + else + VWcor = VW_RS / denom + end if + + + ! Calculate turbulence intensities. + U_TI = USig/UBar + V_TI = VSig/UBar + W_TI = WSig/UBar + + UH_TI = UHSig/UHBar + UT_TI = UTSig/UTBar + + + ! Write out the hub-level stats to the summary file. + + CALL WrScr ( ' Writing statistics to summary file' ) + + WRITE(p%US,"(//,'Hub-Height Simulated Turbulence Statistical Summary:')") + WRITE(p%US,"(/,3X,'Type of Wind Min (m/s) Mean (m/s) Max (m/s) Sigma (m/s) TI (%)')") + WRITE(p%US,"( 3X,'---------------- --------- ---------- --------- ----------- ------')") + + FormStr = "(3X,A,F13.2,2F13.2,2F13.3)" + !bjj for analysis, extra precision: FormStr = "(3X,A,F13.2,2F13.2,2F13.6)" + + WRITE (p%US,FormStr) 'Longitudinal (u)', Umin, UBar, Umax, USig, 100.0* U_TI + WRITE (p%US,FormStr) 'Lateral (v) ', Vmin, VBar, Vmax, VSig, 100.0* V_TI + WRITE (p%US,FormStr) 'Vertical (w) ', Wmin, WBar, Wmax, WSig, 100.0* W_TI + WRITE (p%US,FormStr) 'U component ', UXmin, UXBar, UXmax, UXSig, 100.0*UXSig/UXBar + WRITE (p%US,FormStr) 'V component ', UYmin, UYBar, UYmax, UYSig, 100.0*UYSig/UXBar + WRITE (p%US,FormStr) 'W component ', UZmin, UZBar, UZmax, UZSig, 100.0*UZSig/UXBar + WRITE (p%US,FormStr) 'Horizontal (U&V)', UHmin, UHBar, UHmax, UHSig, 100.0*UH_TI + WRITE (p%US,FormStr) 'Total ', UTmin, UTBar, UTmax, UTSig, 100.0*UT_TI + + WRITE(p%US,"(/,3X,' Min Reynolds Mean Reynolds Max Reynolds Correlation')") + WRITE(p%US,"( 3X,'Product Stress (m/s)^2 Stress (m/s)^2 Stress (m/s)^2 Coefficient')") + WRITE(p%US,"( 3X,'---------------- -------------- -------------- -------------- -----------')") + + FormStr = "(3X,A,3(3X,F12.3,3X),F11.3)" + WRITE (p%US,FormStr) "u'w' ", UWMin, UW_RS, UWMax, UWcor + WRITE (p%US,FormStr) "u'v' ", UVMin, UV_RS, UVMax, UVcor + WRITE (p%US,FormStr) "v'w' ", VWMin, VW_RS, VWMax, VWcor + + FormStr = "(3X,A,' = ',F10.3,A)" + WRITE(p%US,"(/)") ! blank line + WRITE(p%US,FormStr) "Friction Velocity (Ustar) ", SUstar, " m/s" + WRITE(p%US,FormStr) "Maximum Instantaneous TKE ", TKEmax, " (m/s)^2" + WRITE(p%US,FormStr) "Maximum Instantaneous CTKE", CTKEmax, " (m/s)^2" + + ! Allocate the array of standard deviations. + + CALL AllocAry( SDary, p%grid%NumGrid_Y, 'SDary (standard deviations)', ErrStat, ErrMsg) + IF (ErrStat >= AbortErrLev) RETURN + + + ! Calculate standard deviations for each grid point. Write them to summary file. + + WRITE(p%US,"(//,'Grid Point Variance Summary:',/)") + WRITE(p%US,"(3X,'Y-coord',"//TRIM(Num2LStr(p%grid%NumGrid_Y))//"F8.2)") p%grid%Y( p%grid%GridPtIndx(1:p%grid%NumGrid_Y) ) + + + UTmp = 0 + VTmp = 0 + WTmp = 0 + + DO IVec=1,3 + + WRITE(p%US,"(/,3X'Height Standard deviation at grid points for the ',A,' component:')") Comp(IVec) + + DO IZ=p%grid%NumGrid_Z,1,-1 + + DO IY=1,p%grid%NumGrid_Y + + II = (IZ-1)*p%grid%NumGrid_Y+IY + II = p%grid%GridPtIndx(II) + + SumS = 0.0 + + DO IT=1,p%grid%NumSteps + SumS = SumS + V(IT,II,IVec)**2 + ENDDO ! IT + + SDary(IY) = SQRT(SumS*INumSteps) ! Was: SDary(IZ,IY) = SQRT(SumS*INumSteps)/U(IZ,NumGrid/2) + + ENDDO ! IY + + WRITE(p%US,"(F9.2,1X,"//TRIM(Num2LStr(p%grid%NumGrid_Y))//"F8.3)") p%grid%Z( p%grid%GridPtIndx( (IZ-1)*p%grid%NumGrid_Y+1 ) ), SDary(1:p%grid%NumGrid_Y) + + IF ( IVec == 1 ) THEN + UTmp = UTmp + SUM( SDary ) + ELSEIF ( IVec == 2 ) THEN + VTmp = VTmp + SUM( SDary ) + ELSE + WTmp = WTmp + SUM( SDary ) + ENDIF + ENDDO ! IZ + + ENDDO ! Ivec + + + WRITE(p%US,"(/' Mean standard deviation across all grid points:')") + WRITE(p%US,FormStr2) Comp(1), UTmp / ( p%grid%NumGrid_Y*p%grid%NumGrid_Z ) + WRITE(p%US,FormStr2) Comp(2), VTmp / ( p%grid%NumGrid_Y*p%grid%NumGrid_Z ) + WRITE(p%US,FormStr2) Comp(3), WTmp / ( p%grid%NumGrid_Y*p%grid%NumGrid_Z ) + + + ! Deallocate the array of standard deviations. + + IF ( ALLOCATED( SDary ) ) DEALLOCATE( SDary ) + + + +END SUBROUTINE WrSum_Stats +!======================================================================= +!> Calculate the mean velocity and turbulence intensity of the U-component +!! of the interpolated hub point for comparison with InflowWind output. +SUBROUTINE WrSum_InterpolatedHubStats(p, V) + + ! passed variables: + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + REAL(ReKi), INTENT(INOUT) :: V(:,:,:) !< velocity, aligned along the streamwise direction without mean values added + + ! local variables: + REAL(DbKi) :: CGridSum ! The sums of the velocity components at the points surrounding the hub (or at the hub if it's on the grid) + REAL(DbKi) :: CGridSum2 ! The sums of the squared velocity components at the points surrouding the hub + + REAL(ReKi) :: TmpV ! Temporarily holds the value of the v component + REAL(ReKi) :: TmpY ! Temp variable for interpolated hub point + REAL(ReKi) :: TmpZ ! Temp variable for interpolated hub point + REAL(ReKi) :: Tmp_YL_Z ! Temp variable for interpolated hub point + REAL(ReKi) :: Tmp_YH_Z ! Temp variable for interpolated hub point + + REAL(ReKi) :: UGridMean ! Average wind speed at the points surrounding the hub + REAL(ReKi) :: UGridSig ! Standard deviation of the wind speed at the points surrounding the hub + REAL(ReKi) :: UGridTI ! Turbulent Intensity of the points surrounding the hub + + INTEGER :: ZHi_YHi ! Index for interpolation of hub point, if necessary + INTEGER :: ZHi_YLo ! Index for interpolation of hub point, if necessary + INTEGER :: ZLo_YHi ! Index for interpolation of hub point, if necessary + INTEGER :: ZLo_YLo ! Index for interpolation of hub point, if necessary + INTEGER :: IT ! Index for time step + + INTEGER :: IZ_Lo, IY_Lo ! Index for lower bound of box surrounding hub point + + + + ! Calculate mean value & turb intensity of U-component of the interpolated hub point (for comparison w/ AeroDyn output) + + ! Note that this uses the InflowWind interpolation scheme, which may be updated some day so that it doesn't + ! depend on which dimension we interpolate first. + + IY_Lo = INT( 0.5_ReKi * p%grid%GridWidth / p%grid%GridRes_Y ) + 1 + IZ_Lo = INT( ( p%grid%HubHt - p%grid%Zbottom ) / p%grid%GridRes_Z ) + 1 + + + ! Get points for bi-linear interpolation ( indx @ (iy,iz) is (iz-1)*numgrid_y + iy, assuming a full grid (needs to be modified for user-defined spectra) + ZLo_YLo = p%grid%GridPtIndx( ( IZ_Lo - 1 )*p%grid%NumGrid_Y + IY_Lo ) + ZHi_YLo = p%grid%GridPtIndx( ( IZ_Lo )*p%grid%NumGrid_Y + IY_Lo ) + ZLo_YHi = p%grid%GridPtIndx( ( IZ_Lo - 1 )*p%grid%NumGrid_Y + IY_Lo + 1 ) + ZHi_YHi = p%grid%GridPtIndx( ( IZ_Lo )*p%grid%NumGrid_Y + IY_Lo + 1 ) + + TmpZ = (p%grid%HubHt - p%grid%Z(p%grid%GridPtIndx((IZ_Lo-1)*p%grid%NumGrid_Y + 1)))/p%grid%GridRes_Z + TmpY = ( 0.0_ReKi - p%grid%Y(p%grid%GridPtIndx( IY_Lo )))/p%grid%GridRes_Y + CGridSum = 0.0 + CGridSum2 = 0.0 + + DO IT=1,p%grid%NumSteps + + ! Interpolate within the grid for this time step. + + Tmp_YL_Z = ( V( IT, ZHi_YLo, 1 ) - V( IT, ZLo_YLo, 1 ) )*TmpZ + V( IT, ZLo_YLo, 1 ) + Tmp_YH_Z = ( V( IT, ZHi_YHi, 1 ) - V( IT, ZLo_YHi, 1 ) )*TmpZ + V( IT, ZLo_YHi, 1 ) + TmpV = ( Tmp_YH_Z - Tmp_YL_Z )*TmpY + Tmp_YL_Z + + CGridSum = CGridSum + TmpV + CGridSum2 = CGridSum2 + TmpV*TmpV + ENDDO ! IT + + UGridMean = CGridSum/p%grid%NumSteps + UGridSig = SQRT( ABS( (CGridSum2/p%grid%NumSteps) - UGridMean*UGridMean ) ) + UGridTI = 100.0*UGridSig/UGridMean + + + ! Put the average statistics of the four center points in the summary file. + + WRITE(p%US,"(//,'U-component (X) statistics from the interpolated hub point:',/)") + WRITE(p%US,"(3X,A,' =',F9.4,A)") 'Mean' , UGridMean, ' m/s' + WRITE(p%US,"(3X,A,' =',F9.4,A)") 'TI ' , UGridTI , ' %' + + +END SUBROUTINE WrSum_InterpolatedHubStats +!======================================================================= +SUBROUTINE WrSum_EchoInputs(p ) + + ! passed variables: + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + + INTEGER :: I ! loop counter + CHARACTER(10) :: TmpStr ! temporary string used to write output to summary file + + + +!.................................................................................................................................. + WRITE (p%US,"( / 'Runtime Options:' / )") + WRITE (p%US,"( I10 , 2X , 'Random seed #1' )" ) p%RNG%RandSeed(1) + + IF (p%RNG%pRNG == pRNG_INTRINSIC) THEN + WRITE (p%US,"( I10 , 2X , 'Random seed #2' )" ) p%RNG%RandSeed(2) + ELSE + WRITE (p%US,"( 4X, A6, 2X, 'Type of random number generator' )" ) p%RNG%RNG_type + ENDIF + + WRITE (p%US,"( L10 , 2X , 'Output binary HH turbulence parameters?' )" ) p%WrFile(FileExt_BIN) + WRITE (p%US,"( L10 , 2X , 'Output formatted turbulence parameters?' )" ) p%WrFile(FileExt_DAT) + WRITE (p%US,"( L10 , 2X , 'Output AeroDyn HH files?' )" ) p%WrFile(FileExt_HH) + WRITE (p%US,"( L10 , 2X , 'Output AeroDyn FF files?' )" ) p%WrFile(FileExt_BTS) + WRITE (p%US,"( L10 , 2X , 'Output BLADED FF files?' )" ) p%WrFile(FileExt_WND) + WRITE (p%US,"( L10 , 2X , 'Output tower data?' )" ) p%WrFile(FileExt_TWR) + WRITE (p%US,"( L10 , 2X , 'Output formatted FF files?' )" ) p%WrFile(FileExt_UVW) + WRITE (p%US,"( L10 , 2X , 'Output coherent turbulence time step file?' )") p%WrFile(FileExt_CTS) + WRITE (p%US,"( L10 , 2X , 'Clockwise rotation when looking downwind?' )" ) p%grid%Clockwise + + SELECT CASE ( p%IEC%ScaleIEC ) + CASE (0) + TmpStr= "NONE" + CASE (1, -1) ! included the -1 for reading t/f on other systems + TmpStr = "HUB" + CASE (2) + TmpStr = "ALL" + ENDSELECT + + WRITE (p%US,"( I2, ' - ', A5, 2X , 'IEC turbulence models scaled to exact specified standard deviation' )") p%IEC%ScaleIEC, TRIM(TmpStr) + + +!.................................................................................................................................. + WRITE (p%US,"( // 'Turbine/Model Specifications:' / )") + WRITE (p%US,"( I10 , 2X , 'Vertical grid-point matrix dimension' )" ) p%grid%NumGrid_Z + WRITE (p%US,"( I10 , 2X , 'Horizontal grid-point matrix dimension' )") p%grid%NumGrid_Y + WRITE (p%US,"( F10.3 , 2X , 'Time step [seconds]' )" ) p%grid%TimeStep + WRITE (p%US,"( F10.3 , 2X , 'Analysis time [seconds]' )" ) p%grid%AnalysisTime + WRITE (p%US,"( F10.3 , 2X , 'Usable output time [seconds]' )" ) p%grid%UsableTime + WRITE (p%US,"( F10.3 , 2X , 'Hub height [m]' )" ) p%grid%HubHt + WRITE (p%US,"( F10.3 , 2X , 'Grid height [m]' )" ) p%grid%GridHeight + WRITE (p%US,"( F10.3 , 2X , 'Grid width [m]' )" ) p%grid%GridWidth + WRITE (p%US,"( F10.3 , 2X , 'Vertical flow angle [degrees]' )" ) p%met%VFlowAng + WRITE (p%US,"( F10.3 , 2X , 'Horizontal flow angle [degrees]' )" ) p%met%HFlowAng + + +!.................................................................................................................................. + WRITE (p%US,"( // 'Meteorological Boundary Conditions:' / )") + WRITE (p%US, "( 4X , A6 , 2X , '"//TRIM( p%met%TMName )//" spectral model' )") p%met%TurbModel + IF (p%IEC%IECstandard > 0) then + WRITE (p%US,"( 7X, I3, 2X, 'IEC standard: ', A )") p%IEC%IECstandard, TRIM(p%IEC%IECeditionSTR) + IF (p%IEC%NumTurbInp) THEN + WRITE (p%US,"( F10.3 , 2X , 'Percent turbulence intensity, ', A )") p%IEC%PerTurbInt, TRIM(p%IEC%IECeditionSTR) + ELSE + WRITE (p%US,"( 9X , A1 , 2X , 'IEC turbulence characteristic' )" ) p%IEC%IECTurbC + END IF + + SELECT CASE ( p%IEC%IEC_WindType ) + CASE (IEC_NTM) + TmpStr= "NTM" + CASE (IEC_ETM) + TmpStr = "ETM" + CASE (IEC_EWM1) + TmpStr = "EWM1" + CASE (IEC_EWM50) + TmpStr = "EWM50" + CASE (IEC_EWM100) + TmpStr = "EWM100" + ENDSELECT + + WRITE (p%US,"( 4X, A6 , 2X , 'IEC ', A )") TRIM(p%IEC%IECTurbE)//TRIM(TmpStr), TRIM(p%IEC%IEC_WindDesc) + + ELSE + WRITE (p%US,"( 7X, A3, 2X, 'IEC standard' )" ) 'N/A' + IF (p%met%KHtest) THEN + WRITE (p%US,"( 4X, A6, 2X, 'Kelvin-Helmholtz billow test case' )") 'KHTEST' + ELSE + WRITE (p%US,"( A10, 2X, 'IEC turbulence characteristic' )" ) 'N/A' + END IF + WRITE (p%US,"( A10 , 2X , 'IEC turbulence type' )" ) 'N/A' + + END IF + + IF ( p%IEC%IEC_WindType == IEC_ETM ) THEN + WRITE (p%US,"( F10.3, 2X, 'IEC Extreme Turbulence Model (ETM) ""c"" parameter [m/s]' )") p%IEC%ETMc + ELSE + WRITE (p%US,"( A10, 2X, 'IEC Extreme Turbulence Model (ETM) ""c"" parameter [m/s]' )") 'N/A' + END IF + + WRITE (p%US,"( A10 , 2X , 'Wind profile type' )" ) p%met%WindProfileType + WRITE (p%US,"( F10.3 , 2X , 'Reference height [m]' )" ) p%met%RefHt !BJJ: TODO: check if refht makes sense (or is used) for USR profile. + IF ( p%met%WindProfileType == 'USR' .OR. p%met%WindProfileType == 'TS' ) THEN + WRITE (p%US,"( A10, 2X, 'Reference wind speed [m/s]' )" ) 'N/A' + ELSE + WRITE (p%US,"( F10.3 , 2X , 'Reference wind speed [m/s]' )" ) p%met%URef + END IF + + + IF ( p%met%WindProfileType == 'JET' ) THEN + WRITE (p%US,"( F10.3, 2X, 'Jet height [m]' )" ) p%met%ZJetMax + ELSE + WRITE (p%US,"( A10, 2X, 'Jet height [m]' )" ) 'N/A' + END IF + + IF ( INDEX( 'JLUHAT', p%met%WindProfileType(1:1) ) > 0 ) THEN + WRITE (p%US,"( A10, 2X, 'Power law exponent' )" ) 'N/A' + ELSE + WRITE (p%US,"( F10.3 , 2X , 'Power law exponent' )" ) p%met%PLExp + END IF + + IF ( p%met%TurbModel_ID==SpecModel_TIDAL ) THEN + WRITE (p%US,"( A10, 2X, 'Surface roughness length [m]' )" ) 'N/A' + ELSE + WRITE (p%US,"( F10.3 , 2X , 'Surface roughness length [m]' )" ) p%met%Z0 + END IF + +!.................................................................................................................................. + +WRITE (p%US,"( // 'Non-IEC Meteorological Boundary Conditions:' / )") + + IF ( p%met%TurbModel_ID /= SpecModel_IECKAI .AND. p%met%TurbModel_ID /= SpecModel_IECVKM .AND. p%met%TurbModel_ID /= SpecModel_API ) THEN + WRITE (p%US,"( F10.3 , 2X , 'Site latitude [degrees]' )" ) p%met%Latitude + ELSE + WRITE (p%US,"( A10 , 2X , 'Site latitude [degrees]' )" ) 'N/A' + END IF + + + IF ( .NOT. p%met%IsIECModel .AND. p%met%TurbModel_ID /= SpecModel_TIDAL ) THEN + WRITE (p%US,"( F10.3 , 2X , 'Gradient Richardson number' )") p%met%Rich_No + ELSE + WRITE (p%US,"( a10 , 2X , 'Gradient Richardson number' )") 'N/A' + END IF + + IF ( .NOT. p%met%IsIECModel ) THEN + WRITE (p%US,"( F10.3 , 2X , 'Friction or shear velocity [m/s]' )") p%met%Ustar + + IF (p%met%ZL>=0. .AND. p%met%TurbModel_ID /= SpecModel_GP_LLJ) THEN + WRITE (p%US,'( A10 , 2X , "Mixing layer depth [m]" )' ) 'N/A' + ELSE + WRITE (p%US,"( F10.3 , 2X , 'Mixing layer depth [m]' )" ) p%met%ZI + END IF + + ELSE + WRITE (p%US,'( A10 , 2X , "Friction or shear velocity [m/s]" )') 'N/A' + WRITE (p%US,'( A10 , 2X , "Mixing layer depth [m]" )' ) 'N/A' + END IF + + IF (.NOT. p%met%UWskip) THEN + WRITE (p%US,'( F10.3 , 2X , "Mean hub u''w'' Reynolds stress" )' ) p%met%PC_UW + ELSE + WRITE (p%US,'( A10 , 2X , "Mean hub u''w'' Reynolds stress" )' ) 'N/A' + END IF + + IF (.NOT. p%met%UVskip) THEN + WRITE (p%US,'( F10.3 , 2X , "Mean hub u''v'' Reynolds stress" )' ) p%met%PC_UV + ELSE + WRITE (p%US,'( A10 , 2X , "Mean hub u''v'' Reynolds stress" )' ) 'N/A' + END IF + + IF (.NOT. p%met%VWskip) THEN + WRITE (p%US,'( F10.3 , 2X , "Mean hub v''w'' Reynolds stress" )' ) p%met%PC_VW + ELSE + WRITE (p%US,'( A10 , 2X , "Mean hub v''w'' Reynolds stress" )' ) 'N/A' + END IF + +!.................................................................................................................................. + +WRITE (p%US,"( // 'Spatial Coherence Models:' / )") + + do i=1,3 + SELECT CASE (p%met%SCMod(i)) + CASE (CohMod_GENERAL) + TmpStr = "GENERAL" + CASE (CohMod_IEC) + TmpStr = "IEC" + CASE (CohMod_NONE) + TmpStr = "NONE" + CASE (CohMod_API) + TmpStr = "API" + END SELECT + WRITE (p%US,'( A10 , 2X , A, "-component coherence model" )' ) TRIM(TmpStr), Comp(i) + end do + + do i=1,3 + IF ( p%met%SCMod(i) == CohMod_General .OR. p%met%SCMod(i) == CohMod_IEC ) THEN + WRITE (p%US,"( '(',F9.3,',',G10.3,')',2X , A,'-component coherence parameters' )") p%met%InCDec(i), p%met%InCohB(i), Comp(i) + ELSE + WRITE (p%US,"( A22,2X , A,'-component coherence parameters' )") 'N/A', Comp(i) + END IF + end do + + IF ( ANY(p%met%SCMod == CohMod_General) ) THEN + WRITE (p%US,'( F10.3 , 2X , "Coherence exponent" )' ) p%met%CohExp + ELSE + WRITE (p%US,'( A10 , 2X , "Coherence exponent" )' ) 'N/A' + END IF + + +!.................................................................................................................................. +!*** +IF ( .NOT. p%WrFile(FileExt_CTS) .OR. p%met%IsIECModel ) RETURN +!*** + WRITE (p%US,"( // 'Coherent Turbulence Scaling Parameters:' / )") + + + IF ( LEN( TRIM(p%CohStr%CTEventPath) ) <= 10 ) THEN + WRITE (p%US,"( A10 , 2X , 'Name of the path containing the coherent turbulence data files' )") TRIM(p%CohStr%CTEventPath) + ELSE + WRITE (p%US,"( A, /, 12X , 'Name of the path containing the coherent turbulence data files' )") TRIM(p%CohStr%CTEventPath) + ENDIF + WRITE (p%US,"( 7X, A3, 2X, 'Type of coherent turbulence data files' )") TRIM(p%CohStr%CText) +! WRITE (p%US,"( L10 , 2X , 'Randomize the disturbance scale and location?' )") Randomize + WRITE (p%US,"( F10.3 , 2X , 'Disturbance scale (ratio of wave height to rotor diameter)' )") p%CohStr%DistScl + WRITE (p%US,"( F10.3 , 2X , 'Fractional location of tower centerline from right' )") p%CohStr%CTLy + WRITE (p%US,"( F10.3 , 2X , 'Fractional location of hub height from the bottom of the dataset' )") p%CohStr%CTLz + WRITE (p%US,"( F10.3 , 2X , 'Minimum start time for coherent structures [seconds]' )") p%CohStr%CTStartTime + +!.................................................................................................................................. + +END SUBROUTINE WrSum_EchoInputs +!======================================================================= +!> This subroutine processes the user input from the IECstandard line +!! and splits it into the standard and edition being used +SUBROUTINE ProcessLine_IECstandard(Line, IsIECModel, TurbModel_ID, IECstandard, IECedition, IECeditionStr, ErrStat, ErrMsg ) + + CHARACTER(*), INTENT(INOUT) :: Line !< on entry, the line from the input file. may be modified in this routine + LOGICAL, INTENT(IN ) :: IsIECModel !< Flag to indicate if this is an IEC model + INTEGER(IntKi), INTENT(IN ) :: TurbModel_ID !< Turbulence model identifier + INTEGER(IntKi), INTENT( OUT) :: IECedition !< IEC edition + INTEGER(IntKi), INTENT( OUT) :: IECstandard !< IEC standard + CHARACTER(*), INTENT( OUT) :: IECeditionStr !< string describing the IEC standard/edition being used + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + INTEGER(IntKi) :: IOS ! local error code + INTEGER(IntKi) :: TmpIndex ! index into string + CHARACTER(*), PARAMETER :: IECstandardErrMsg = 'The IECstandard input parameter must be either "1", "2", or "3"' & + // ' with an optional IEC 61400-1 edition number ("1-ED2"). If specified, the edition number must be "2" or "3".' + + CHARACTER( 23), PARAMETER :: IECeditionStr_p (3) = & ! strings for the + (/'IEC 61400-1 Ed. 1: 1993', & + 'IEC 61400-1 Ed. 2: 1999', & + 'IEC 61400-1 Ed. 3: 2005'/) ! The string description of the IEC 61400-1 standard being used + + + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( .NOT. IsIECModel ) THEN !bjj: SpecModel==SpecModel_MODVKM is not in the IEC standard + IECstandard = 0 + IECedition = 0 + IECeditionStr = "" + RETURN + ENDIF ! IEC + + + ! Did the line contain "T" or "F", which could be interpreted by Fortran as a number? + CALL Conv2UC( LINE ) + IF ( (Line(1:1) == 'T') .OR. (Line(1:1) == 'F') ) THEN + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg, ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + + + ! Did the user enter an edition number? + TmpIndex = INDEX(Line, "-ED") + IF ( TmpIndex > 0 ) THEN + READ ( Line(TmpIndex+3:),*,IOSTAT=IOS ) IECedition + + IF (IOS /= 0) THEN + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg, ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + END IF + + IF ( IECedition < 1 .OR. IECedition > 3 ) THEN + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg, ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + + Line = Line(1:TmpIndex-1) + ELSE + IECedition = 0 + ENDIF + + ! What standard did the user enter? + READ ( Line,*,IOSTAT=IOS ) IECstandard + + SELECT CASE ( IECstandard ) + + CASE ( 1 ) ! use the IEC 64100-1 standard, either edition 2 or 3 + IF (IECedition < 1 ) THEN ! Set up the default + IF ( TurbModel_ID == SpecModel_IECVKM .OR. TurbModel_ID == SpecModel_USRVKM ) THEN + IECedition = 2 ! The von Karman model is not specified in edition 3 of the -1 standard + ELSE + IECedition = 3 + ENDIF + ELSE + IF ( IECedition < 2 ) THEN + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg, ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + ENDIF + IECeditionSTR = IECeditionStr_p(IECedition) + + CASE ( 2 ) ! use the IEC 64100-2 (small turbine) standard, which the same as 64100-1, Ed. 2 with "A" or user-specified turbulence + IF (IECedition < 1 ) THEN ! Set up the default + IECedition = 2 ! This is the edition of the -1 standard + ELSE + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg//' The edition number cannot be specified for the 61400-2 standard.', ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + IECeditionSTR = 'IEC 61400-2 Ed. 2: 2005' + + CASE ( 3 ) ! Use the IEC 61400-3 (Offshore) standard, which is the same as 61400-1 except it has a different power law exponent + IF (IECedition < 1 ) THEN ! Set up the default + + IF ( TurbModel_ID /= SpecModel_IECKAI ) THEN + CALL SetErrStat(ErrID_Fatal, ' The Kaimal model (IECKAI) is the only turbulence model valid for the 61400-3 standard.', ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + IECedition = 3 ! This is the edition of the -1 standard + + ELSE + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg//' The edition number cannot be specified for the 61400-3 standard.', ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + ENDIF + IECeditionSTR = 'IEC 61400-3 Ed. 1: 2006' + + CASE DEFAULT + CALL SetErrStat(ErrID_Fatal, IECstandardErrMsg, ErrStat, ErrMsg, 'ProcessLine_IECstandard') + RETURN + + END SELECT +END SUBROUTINE ProcessLine_IECstandard +!======================================================================= +!> This subroutine processes the user input from the IECturbc line +!! and splits it into the NumTurbInp, IECTurbC, and KHtest variables. +SUBROUTINE ProcessLine_IECturbc(Line, IsIECModel, IECstandard, IECedition, IECeditionStr, NumTurbInp, IECTurbC, PerTurbInt, KHtest, ErrStat, ErrMsg) + REAL(ReKi) , INTENT( OUT) :: PerTurbInt !< Percent Turbulence Intensity + + INTEGER(IntKi), INTENT(IN ) :: IECedition !< IEC edition + INTEGER(IntKi), INTENT(IN ) :: IECstandard !< IEC standard + + LOGICAL, INTENT(IN ) :: IsIECModel !< Flag to indicate if this is an IEC model + LOGICAL, INTENT( OUT) :: NumTurbInp !< Flag to indicate if turbulence is user-specified (as opposed to IEC standard A, B, or C) + LOGICAL, INTENT( OUT) :: KHtest !< Flag to indicate that turbulence should be extreme, to demonstrate effect of KH billows + + CHARACTER(*), INTENT(IN ) :: IECeditionStr !< string describing the IEC standard/edition being used + CHARACTER(1), INTENT( OUT) :: IECTurbC !< IEC turbulence characteristic + CHARACTER(*), INTENT(INOUT) :: Line !< on entry, the line from the input file. may be modified in this routine + + !INTEGER(IntKi), INTENT(IN ) :: TurbModel_ID !< Turbulence model identifier + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + INTEGER(IntKi) :: IOS ! local error code + CHARACTER(*), PARAMETER :: IECstandardErrMsg = 'The IECstandard input parameter must be either "1", "2", or "3"' & + // ' with an optional IEC 61400-1 edition number ("1-ED2"). If specified, the edition number must be "2" or "3".' + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( IsIECModel ) THEN + KHtest = .FALSE. + + READ (Line,*,IOSTAT=IOS) IECTurbC + + CALL Conv2UC( IECTurbC ) + + IF ( (IECTurbC == 'T') .OR. (IECTurbC == 'F') ) THEN + CALL SetErrStat( ErrID_Fatal, 'The IEC turbulence characteristic must be either "A", "B", "C", or a real number.', ErrStat, ErrMsg, 'ProcessLine_IECturbc') + RETURN + ENDIF + + ! Check to see if the entry was a number. + + READ (Line,*,IOSTAT=IOS) PerTurbInt + + IF ( IOS == 0 ) THEN + + ! Let's use turbulence value. + + NumTurbInp = .TRUE. + IECTurbC = "" + + ELSE + + ! Let's use one of the standard turbulence values (A or B or C). + + NumTurbInp = .FALSE. + PerTurbInt = 0.0 ! will be set later if necessary + + IECTurbC = ADJUSTL( Line ) + CALL Conv2UC( IECTurbC ) + SELECT CASE ( IECTurbC ) + CASE ( 'A' ) + CASE ( 'B' ) + IF ( IECstandard == 2 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The IEC 61400-2 turbulence characteristic must be either "A" or a real number.', ErrStat, ErrMsg, 'ProcessLine_IECturbc') + ENDIF + CASE ( 'C' ) + IF ( IECstandard == 2 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The IEC 61400-2 turbulence characteristic must be either "A" or a real number.', ErrStat, ErrMsg, 'ProcessLine_IECturbc') + ELSEIF ( IECedition < 3 ) THEN + CALL SetErrStat( ErrID_Fatal, 'The turbulence characteristic for '//TRIM(IECeditionSTR )// & + ' must be either "A", "B", or a real number.', ErrStat, ErrMsg, 'ProcessLine_IECturbc') + ENDIF + CASE DEFAULT + CALL SetErrStat( ErrID_Fatal, 'The IEC turbulence characteristic must be either "A", "B", "C", or a real number.', ErrStat, ErrMsg, 'ProcessLine_IECturbc') + END SELECT ! IECTurbC + + ENDIF + + + + ELSE + + Line = ADJUSTL( Line ) + CALL Conv2UC( Line ) + + KHtest = ( Line(1:6) == 'KHTEST' ) + + ! These variables are not used for non-IEC turbulence + + NumTurbInp = .FALSE. + PerTurbInt = 0.0 + IECTurbC = "" + + ENDIF + + +END SUBROUTINE ProcessLine_IECturbc +!======================================================================= +!> This subroutine processes the user input from the IEC_WindType line +!! and initializes the variables p%IEC%IECTurbE, p%IEC%Vref, +!! p%IEC%IEC_WindType, and p%IEC%IEC_WindDesc. +SUBROUTINE ProcessLine_IEC_WindType(Line, p, ErrStat, ErrMsg) + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters + CHARACTER(*), INTENT(INOUT) :: Line !< on entry, the line from the input file. may be modified in this routine + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( p%met%IsIECModel .AND. p%met%TurbModel_ID /= SpecModel_MODVKM ) THEN + + CALL Conv2UC( Line ) + + p%IEC%IECTurbE = Line(1:1) + + ! Let's see if the first character is a number (for the ETM case) + SELECT CASE ( p%IEC%IECTurbE ) + CASE ('1') + p%IEC%Vref = 50.0_ReKi + Line = Line(2:) + CASE ('2') + p%IEC%Vref = 42.5_ReKi + Line = Line(2:) + CASE ('3') + p%IEC%Vref = 37.5_ReKi + Line = Line(2:) + CASE DEFAULT + ! There's no number at the start of the string so let's move on (it's NTM). + p%IEC%Vref = -999.9_ReKi + p%IEC%IECTurbE = ' ' + END SELECT + + SELECT CASE ( TRIM( Line ) ) + CASE ( 'NTM' ) + p%IEC%IEC_WindType = IEC_NTM + p%IEC%IEC_WindDesc = 'Normal Turbulence Model' + CASE ( 'ETM' ) + p%IEC%IEC_WindType = IEC_ETM + p%IEC%IEC_WindDesc = 'Extreme Turbulence Model' + CASE ( 'EWM1' ) + p%IEC%IEC_WindType = IEC_EWM1 + p%IEC%IEC_WindDesc = 'Extreme 1-Year Wind Speed Model' + CASE ( 'EWM50' ) + p%IEC%IEC_WindType = IEC_EWM50 + p%IEC%IEC_WindDesc = 'Extreme 50-Year Wind Speed Model' + !CASE ( 'EWM100' ) + ! p%IEC%IEC_WindType = IEC_EWM100 + ! p%IEC%IEC_WindDesc = 'Extreme 100-Year Wind Speed Model' + CASE DEFAULT + CALL SetErrStat( ErrID_Fatal, 'Valid entries for the IEC wind turbulence are "NTM", "xETM", "xEWM1", or "xEWM50", '// & + 'where x is the wind turbine class (1, 2, or 3).', ErrStat, ErrMsg, 'ProcessLine_IEC_WindType') + END SELECT + + IF ( p%IEC%IEC_WindType /= IEC_NTM ) THEN + + IF (p%IEC%IECedition /= 3 .OR. p%IEC%IECstandard == 2) THEN + CALL SetErrStat( ErrID_Fatal, 'The extreme turbulence and extreme wind speed models are available with '// & + 'the IEC 61400-1 Ed. 3 or 61400-3 scaling only.', ErrStat, ErrMsg, 'ProcessLine_IEC_WindType') + ENDIF + + IF (p%IEC%Vref < 0. ) THEN + CALL SetErrStat( ErrID_Fatal, 'A wind turbine class (1, 2, or 3) must be specified with the '// & + 'extreme turbulence and extreme wind types. (i.e. "1ETM")', ErrStat, ErrMsg, 'ProcessLine_IEC_WindType') + ENDIF + + IF ( p%IEC%NumTurbInp ) THEN + CALL SetErrStat( ErrID_Fatal, 'When the turbulence intensity is entered as a percent, '//& + 'the IEC wind type must be "NTM".', ErrStat, ErrMsg, 'ProcessLine_IEC_WindType') + ENDIF + + ELSE + + p%IEC%IECTurbE = ' ' + + ENDIF + + ELSE + p%IEC%IEC_WindType = IEC_NTM + p%IEC%IEC_WindDesc = 'Normal turbulence' + p%IEC%IECTurbE = ' ' ! unused for non-IEC models + p%IEC%Vref = -999.9_ReKi ! unused for non-IEC models + ENDIF + + + +END SUBROUTINE ProcessLine_IEC_WindType +!======================================================================= +SUBROUTINE GetDefaultSCMod( TurbModel_ID, SCMod ) + + INTEGER(IntKi), INTENT(IN ) :: TurbModel_ID ! turbulence model Identifier + INTEGER(IntKi), INTENT( OUT) :: SCMod(3) ! default spatial coherence model + + + + SELECT CASE (TurbModel_ID) + CASE ( SpecModel_IECKAI, SpecModel_IECVKM, SpecModel_MODVKM, SpecModel_USRVKM) + SCMod(1) = CohMod_IEC + SCMod(2:3) = CohMod_NONE + + CASE ( SpecModel_API ) + SCMod(1) = CohMod_API + SCMod(2:3) = CohMod_NONE + + CASE ( SpecModel_USER ) + SCMod(1) = CohMod_GENERAL + SCMod(2:3) = CohMod_NONE + + CASE ( SpecModel_None ) + SCMod = CohMod_NONE + + CASE DEFAULT + SCMod = CohMod_GENERAL + + END SELECT + + +END SUBROUTINE GetDefaultSCMod +!======================================================================= +SUBROUTINE GetDefaultCoh(TurbModel_ID, RICH_NO, WS, Ht, InCDec, InCohB ) +! This routine should NOT be called after CalcIECScalingParams() because it will +! incorrectly overwrite the InCDec and InCohB parameters for the IEC models. + + ! These numbers come from Neil's analysis + + INTEGER(IntKi), INTENT(IN) :: TurbModel_ID ! turbulence model Identifier + REAL(ReKi), INTENT(IN) :: RICH_NO ! Richardson Number (stability) + REAL(ReKi), INTENT(IN) :: Ht !Height, usually hub height + REAL(ReKi), INTENT(IN) :: WS !Wind speed, usually = UHub + REAL(ReKi), INTENT( OUT) :: InCDec(3) ! default coherence decrement + REAL(ReKi), INTENT( OUT) :: InCohB(3) ! default coherence parameter B + + +! REAL(ReKi), PARAMETER :: a = 0.007697495 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: b = 0.451759656 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: c = 6.559106387 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: d = -0.10471942 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: e = -1.19488521 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: f = 0.005529328 !coeffs for WF_xxD best-fit equations +! REAL(ReKi), PARAMETER :: g = 0.059157163 !coeffs for WF_xxD best-fit equations + + + REAL(ReKi) :: Coeffs(10,3) ! coeffs for WS category coherence decrements + REAL(ReKi) :: Ht1 !Height, set to bounds of the individual models + REAL(ReKi) :: Ht2 !Height squared + REAL(ReKi) :: Ht3 !Height cubed + REAL(ReKi) :: WS1 !Wind speed, set to bounds of individual models + REAL(ReKi) :: RI1 !RICH_NO, set to bounds of individual models + REAL(ReKi) :: RI2 !RICH_NO squared + REAL(ReKi) :: RI3 !RICH_NO cubed + + INTEGER :: I + INTEGER :: Ri_Cat + + + IF (RICH_NO <= 0.00_ReKi ) THEN + IF ( RICH_NO <= - 1.0_ReKi ) THEN + Ri_Cat = 1 + ELSE + Ri_Cat = 2 + ENDIF + ELSEIF ( RICH_NO <= 0.25_ReKi ) THEN + IF ( RICH_NO <= 0.10_ReKi ) THEN + Ri_Cat = 3 + ELSE + Ri_Cat = 4 + ENDIF + ELSE + Ri_Cat = 5 + ENDIF + + SELECT CASE ( TurbModel_ID ) + + CASE ( SpecModel_GP_LLJ ) + HT1 = MAX( 60.0_ReKi, MIN( Ht, 100.0_ReKi ) ) + IF ( WS <= 14.0 ) THEN + IF ( WS <= 8.0 ) THEN + IF ( WS <= 6.0 ) THEN + coeffs(:,3) = (/ 3.1322E+00, 2.2819E-03, 2.9214E+00, -5.2203E-04, 1.1877E+00, & + -5.7605E-02, 3.7233E-06, -3.5021E-01, -1.7555E-03, 3.9712E-04 /) !W 5 + IF ( WS <= 4.0 ) THEN ! WS <= 4 + RI1 = MAX( 0.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 4.8350E+00, -4.0113E-02, 7.8134E+00, -2.0069E-05, -1.9518E-01, & + -1.4009E-01, 2.3195E-06, 8.2029E-02, -7.4979E-04, 6.1186E-04 /) !U 3 + coeffs(:,2) = (/ 3.2587E+00, -5.9086E-02, 9.7426E+00, 5.7360E-04, 2.1274E-01, & + -1.6398E-01, -8.3786E-07, 6.6896E-02, -3.5254E-03, 6.4833E-04 /) !V 3 + ELSE ! 4 < WS <= 6 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 9.2474E+00, -4.9849E-02, 6.0887E+00, -5.9124E-04, 4.4312E-02, & + -1.1966E-01, 5.2652E-06, -1.0373E-01, 4.0480E-03, 5.5761E-04 /) !U 5 + coeffs(:,2) = (/ 3.6355E+00, 1.7701E-02, 4.2165E+00, -5.8828E-04, 9.5592E-02, & + -6.5313E-02, 3.3875E-06, -1.7981E-02, -1.6375E-03, 3.0423E-04 /) !V 5 + ENDIF + ELSE ! 6 < WS <= 8 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 1.1795E+01, -7.5393E-02, 9.5279E+00, -3.4922E-04, -5.8973E-01, & + -1.6753E-01, 4.4267E-06, 2.1797E-01, 7.7887E-04, 7.4912E-04 /) !U 7 + coeffs(:,2) = (/ 1.7730E+00, 9.6577E-02, 8.1310E+00, -1.2028E-03, 3.0145E-02, & + -1.2282E-01, 4.6866E-06, 3.5748E-02, -2.9013E-03, 4.8368E-04 /) !V 7 + coeffs(:,3) = (/ 9.1695E-01, 9.1488E-02, 6.7163E+00, -1.2938E-03, 1.0315E+00, & + -1.1976E-01, 5.6039E-06, -2.0416E-01, -3.4698E-03, 6.0175E-04 /) !W 7 + ENDIF + ELSE ! 8.0 < WS <= 14.0 + IF (WS <= 10.0) THEN ! 8 < WS <= 10 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 8.4674E+00, 1.2922E-01, 8.6170E+00, -3.3048E-03, -3.1928E-02, & + -1.2515E-01, 1.8209E-05, 2.9087E-01, -9.3031E-03, 5.0706E-04 /) !U 9 + coeffs(:,2) = (/ 2.8145E+00, 1.0257E-01, 4.2987E+00, -1.4901E-03, 4.9698E-02, & + -3.9964E-02, 6.7640E-06, 2.2980E-01, -1.0046E-02, 1.3037E-04 /) !V 9 + coeffs(:,3) = (/ 2.4952E+00, 5.8000E-02, 1.9851E+00, -9.4027E-04, -4.0135E-02, & + -1.8377E-02, 4.3320E-06, -1.0441E-01, 3.6831E-03, 8.6637E-05 /) !W 9 + ELSEIF (WS <= 12.0) THEN ! 10 < WS <= 12 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 1.2473E+01, 3.2270E-02, 1.4508E+01, -2.2856E-03, -1.4652E+00, & + -2.4114E-01, 1.4919E-05, 5.5578E-01, -8.5528E-04, 1.0273E-03 /) !U 11 + coeffs(:,2) = (/ 1.0882E+00, 1.9425E-01, 8.1533E+00, -2.5574E-03, 4.3113E-01, & + -8.0465E-02, 1.0478E-05, 1.1640E-01, -1.1717E-02, 1.6476E-04 /) !V 11 + coeffs(:,3) = (/ 5.0280E-01, 1.1637E-01, 4.0130E+00, -1.2034E-03, -2.7592E-01, & + -3.8744E-02, 3.4213E-06, -1.5144E-02, 2.4042E-03, 4.7818E-05 /) !W 11 + ELSE ! 12 < WS <= 14.0 + RI1 = MAX( -1.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 8.6311E+00, 2.5614E-01, 1.1165E+01, -5.1685E-03, 3.0895E+00, & + -1.9190E-01, 2.7162E-05, -2.6513E-01, -3.6479E-02, 8.8431E-04 /) !U 13 + coeffs(:,2) = (/ 1.2842E+00, 2.4007E-01, 5.3653E+00, -3.2589E-03, 3.4715E+00, & + -6.8865E-02, 1.3756E-05, -4.8465E-01, -4.0608E-02, 3.8578E-04 /) !V 13 + coeffs(:,3) = (/ 4.3681E+00, 1.2251E-02, 1.3826E+00, -1.1592E-04, 3.3654E+00, & + -5.2367E-02, -4.4086E-08, -3.5254E-01, -1.6780E-02, 3.9048E-04 /) !W 13 + ENDIF + ENDIF + ELSE ! WS > 14 + IF (WS <= 20.0 ) THEN + IF (WS <= 16.0) THEN ! 14 < WS <= 16 + RI1 = MAX( -1.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 1.3972E-01, 6.3486E-01, 1.7576E+01, -1.0017E-02, 2.8458E+00, & + -2.5233E-01, 4.6539E-05, -1.8899E-01, -2.6717E-02, 9.5173E-04 /) !U 15 + coeffs(:,2) = (/ -7.1243E+00, 5.6768E-01, 1.2886E+01, -7.3277E-03, 3.7880E+00, & + -1.4733E-01, 3.0898E-05, -1.5056E-01, -2.9500E-02, 3.6703E-04 /) !V 15 + coeffs(:,3) = (/ -1.1004E+01, 5.3470E-01, 5.3118E+00, -5.8999E-03, 1.9009E+00, & + -2.4063E-02, 2.1755E-05, -4.5798E-01, 1.6885E-02, -3.9974E-04 /) !W 15 + ELSEIF (WS <= 18.0) THEN ! 16 < WS <= 18 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ -6.9650E+00, 8.8636E-01, 2.3467E+01, -1.1973E-02, -4.3750E+00, & + -3.5519E-01, 5.0414E-05, 9.1789E-01, 9.8340E-03, 1.5885E-03 /) !U 17 + coeffs(:,2) = (/ 5.5495E-03, 3.2906E-01, 1.4609E+01, -4.1635E-03, -2.1246E+00, & + -1.8887E-01, 1.6964E-05, 3.7805E-01, 1.1880E-03, 8.8265E-04 /) !V 17 + coeffs(:,3) = (/ -1.3195E+00, 2.0022E-01, 2.3490E+00, -2.1308E-03, 3.5582E+00, & + 1.4379E-02, 7.6830E-06, -7.6155E-01, -2.4660E-02, -2.0199E-04 /) !W 17 + ELSE ! 18 < WS <= 20 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ -1.3985E+01, 1.3161E+00, 3.4773E+01, -1.9237E-02, -1.9845E+00, & + -5.5817E-01, 8.8310E-05, 1.7142E+00, -4.2907E-02, 2.3932E-03 /) !U 19 + coeffs(:,2) = (/ -1.2400E+01, 8.6854E-01, 1.9923E+01, -1.1557E-02, -1.0441E+00, & + -2.4593E-01, 4.9813E-05, 2.7861E-01, -8.6189E-03, 9.4314E-04 /) !V 19 + coeffs(:,3) = (/ -9.3436E+00, 6.4950E-01, 1.5316E+01, -8.7208E-03, 1.7329E+00, & + -2.2411E-01, 3.6288E-05, -8.0006E-01, -2.6439E-03, 7.9293E-04 /) !W 19 + ENDIF + ELSE ! WS > 20 + IF (WS <= 22.0) THEN ! 20 < WS <= 22 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ -2.4317E+01, 1.8176E+00, 5.3359E+01, -2.5973E-02, 6.0349E+00, & + -7.9927E-01, 1.1558E-04, 1.5926E+00, -1.5005E-01, 3.1688E-03 /) !U 21 + coeffs(:,2) = (/ 8.0459E+00, 1.8058E-01, 1.9426E+01, -3.6730E-03, -9.9717E-01, & + -1.8249E-01, 1.9237E-05, 4.9173E-01, -1.8255E-02, 6.9371E-04 /) !V 21 + coeffs(:,3) = (/ -2.3544E+01, 1.1403E+00, 8.3526E+00, -1.4511E-02, 7.2014E+00, & + 5.0216E-02, 5.9947E-05, -1.0659E+00, -7.4769E-02, -9.8390E-04 /) !W 21 + ELSEIF (WS <= 24.0) THEN ! 22 < WS <= 24 + RI1 = MAX( 0.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ -3.5790E+01, 1.5374E+00, 1.1322E+02, -1.6884E-02, -1.7767E+01, & + -1.8122E+00, 6.8247E-05, 7.2101E+00, 3.5536E-02, 7.9269E-03 /) !U 23 + coeffs(:,2) = (/ -7.2883E+01, 2.8210E+00, 8.6392E+01, -3.1084E-02, -2.4938E+01, & + -1.5898E+00, 1.0997E-04, 7.1972E+00, 1.2624E-01, 9.3084E-03 /) !V 23 + coeffs(:,3) = (/ -3.2844E+01, 1.2683E+00, 3.2032E+01, -1.3197E-02, -1.1129E+01, & + -3.6741E-01, 4.2852E-05, 4.1336E+00, 2.4775E-02, 1.8431E-03 /) !W 23 + ELSE ! 24 < WS + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 2.2906E+01, 9.3209E-02, 1.5448E+01, -5.7421E-03, -8.9114E+00, & + -3.1547E-02, 4.0144E-05, 5.4544E-01, 5.3557E-02, -3.1299E-04 /) !U 25 + coeffs(:,2) = (/ -1.1903E+01, 1.1104E+00, 1.7962E+01, -1.6045E-02, -9.2458E+00, & + -4.4526E-02, 6.9880E-05, 2.8017E+00, -2.7211E-02, -8.4099E-04 /) !V 25 + coeffs(:,3) = (/ 6.1054E-01, 7.1841E-03, 4.2996E+00, 2.9071E-04, -2.0002E+00, & + -7.0403E-02, -2.8931E-06, 2.3943E-02, 1.8395E-02, 5.0406E-04 /) !W 25 + ENDIF + ENDIF + ENDIF + + + HT2 = HT1*HT1 + HT3 = HT1*HT2 + RI2 = RI1*RI1 + RI3 = RI1*RI2 + + DO I = 1,3 + InCDec(I) = coeffs( 1,I) + coeffs(2,I)*Ht1 + coeffs(3,I)*RI1 & + + coeffs(4,I)*Ht2 + coeffs(5,I)*RI2 + coeffs( 6,I)*Ht1*RI1 & + + coeffs(7,I)*Ht3 + coeffs(8,I)*RI3 + coeffs( 9,I)*Ht1*RI2 & + + coeffs(10,I)*Ht2*RI1 + ENDDO + + WS1 = MAX( 2.0_ReKi, WS ) + SELECT CASE ( Ri_Cat ) + CASE ( 1, 2) +! InCDec = (/ 1.744591004*WS1**0.593219225, & +! -0.58750092+1.937230512*WS1**0.400548383, & +! -0.57833219+1.450654739*WS1**0.443191083 /) + InCohB = (/-0.00014115+0.006826264/WS1, & + 0.014025749/WS1, & + 0.000480386+0.020982336/WS1 /) + + CASE ( 3 ) +! InCDec = (/ 1.962126171*WS1**0.575523536, & +! -2.79495117+3.698342796*WS1**0.305415750, & +! 0.887573173*WS1**0.498317195 /) + InCohB = (/-0.00016838+0.009764148/WS1, & + 0.018582932/WS1, & + 0.001865953+0.061952454/WS1 /) + + CASE ( 4 ) +! InCDec = (/ 0.817085986*WS1**1.045777184, & +! 0.599696362*WS1**1.038373995, & +! 1.327586050*WS1**0.590370871 /) + InCohB = (/0.000175033+0.004195814/WS1, & + 0.008479460/WS1, & + 0.002318082+0.027820652/WS1 /) + + CASE ( 5 ) +! InCDec = (/ 0.959999473*WS1**0.972466847, & +! 0.082701643+0.867230846*WS1**0.925895412, & +! 1.524380209*WS1**0.548060899 /) + InCohB = (/0.000241808+0.004267702/WS1, & + 0.005408592/WS1, & + 0.001150319+0.010744459/WS1 /) + END SELECT + + + CASE ( SpecModel_NWTCUP, SpecModel_USRVKM ) + HT1 = MAX( 25.0_ReKi, MIN( Ht, 50.0_ReKi ) ) + + IF ( WS <= 14.0 ) THEN + RI1 = MAX( -1.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + IF ( WS <= 8.0 ) THEN + IF (WS <= 4.0 ) THEN ! WS <= 4 + coeffs(:,1) = (/ 8.1767E+00, -3.1018E-01, 3.3055E-01, 4.4232E-03, 4.6550E-01, & + -2.4582E-02, -5.8568E-06, -8.7873E-02, 1.3070E-02, 3.1871E-04 /) !U 3 + coeffs(:,2) = (/ 5.8003E+00, -2.0838E-01, 2.8727E-01, 2.8669E-03, 6.9669E-01, & + -8.2249E-03, -2.4732E-06, -1.0826E-01, 9.9973E-03, 1.8546E-05 /) !V 3 + coeffs(:,3) = (/ 5.9625E+00, -2.9247E-01, -9.3269E-01, 4.4089E-03, 1.3779E-01, & + 2.6993E-02, -6.1784E-06, -7.2920E-02, 1.7028E-02, -3.3753E-04 /) !W 3 + ELSEIF (WS <= 6.0 ) THEN ! 4 < WS <= 6 + coeffs(:,1) = (/ 1.2891E+01, -4.8265E-01, 3.5549E+00, 6.6099E-03, 8.2275E-01, & + -1.5913E-01, -7.9740E-06, -1.2357E-02, 3.2084E-03, 1.7145E-03 /) !U 5 + coeffs(:,2) = (/ 8.0267E+00, -2.5275E-01, 1.3801E+00, 3.2447E-03, 1.6004E+00, & + -3.2592E-02, -5.1265E-06, -9.8552E-02, -1.3513E-02, 2.8075E-04 /) !V 5 + coeffs(:,3) = (/ 7.9593E+00, -3.6336E-01, 1.4974E+00, 5.4012E-03, 9.5041E-01, & + -1.0152E-01, -1.0865E-05, 4.3121E-02, -3.2447E-03, 1.3797E-03 /) !W 5 + ELSE ! 6 < WS <= 8 + coeffs(:,1) = (/ 1.3702E+01, -4.4674E-01, 3.7943E+00, 5.9350E-03, 9.6026E-01, & + -1.7425E-01, -7.2917E-06, -8.8426E-02, 5.1530E-03, 2.0554E-03 /) !U 7 + coeffs(:,2) = (/ 9.2471E+00, -2.6247E-01, 1.4504E+00, 3.2436E-03, 1.8823E+00, & + -3.2180E-02, -5.9491E-06, -2.0100E-01, -1.7619E-02, 3.8519E-04 /) !V 7 + coeffs(:,3) = (/ 8.9439E+00, -3.8885E-01, 2.2175E+00, 5.6207E-03, 7.6040E-01, & + -1.3502E-01, -9.2514E-06, 1.9269E-02, 3.8862E-03, 1.7674E-03 /) !W 7 + ENDIF + ELSE ! 8.0 < WS <= 14.0 + IF (WS <= 10.0) THEN ! 8 < WS <= 10 + coeffs(:,1) = (/ 1.9061E+01, -4.5354E-01, 7.5961E+00, 5.2422E-03, 1.5158E+00, & + -2.4908E-01, -2.5277E-06, -1.6660E-01, 1.1369E-02, 3.0156E-03 /) !U 9 + coeffs(:,2) = (/ 1.3362E+01, -3.3806E-01, 7.0401E+00, 4.5349E-03, 2.6798E+00, & + -2.3637E-01, -9.9075E-06, -2.2373E-01, -1.6644E-03, 2.3879E-03 /) !V 9 + coeffs(:,3) = (/ 8.8401E+00, -2.9945E-01, 3.7883E+00, 4.4581E-03, 2.0417E+00, & + -2.7852E-01, -7.0750E-06, -6.2618E-02, 1.4646E-02, 3.8512E-03 /) !W 9 + ELSEIF (WS <= 12.0) THEN ! 10 < WS <= 12 + coeffs(:,1) = (/ 3.4011E+01, -1.2590E+00, 1.6320E+01, 1.9225E-02, 6.8346E+00, & + -8.8950E-01, -6.2453E-05, -2.4945E-01, -4.3892E-02, 1.2078E-02 /) !U 11 + coeffs(:,2) = (/ 1.7135E+01, -4.0754E-01, 1.0282E+01, 5.7832E-03, 6.3056E+00, & + -2.8536E-01, -3.0216E-05, -5.3170E-01, -5.7090E-02, 2.8463E-03 /) !V 11 + coeffs(:,3) = (/ 1.3002E+01, -4.8326E-01, 3.2819E+00, 7.8800E-03, 2.7094E+00, & + -2.5714E-01, -3.0117E-05, -2.1404E-01, -4.2711E-03, 4.1067E-03 /) !W 11 + ELSE ! 12 < WS <= 14 + coeffs(:,1) = (/ 2.6682E+01, -9.7229E-01, 1.3191E+01, 1.7604E-02, -1.3537E+00, & + -6.4082E-01, -7.8242E-05, 1.7548E-01, 9.7417E-02, 1.0259E-02 /) !U 13 + coeffs(:,2) = (/ 1.7083E+01, -4.7346E-01, 1.3515E+01, 7.7832E-03, 5.8633E-01, & + -6.1815E-01, -3.3752E-05, -1.7300E-01, 4.3584E-02, 8.9289E-03 /) !V 13 + coeffs(:,3) = (/ 1.6015E+01, -6.3912E-01, 1.3137E+01, 9.4757E-03, 2.5549E+00, & + -8.1438E-01, -1.5565E-05, 2.9244E-02, 2.2779E-02, 1.1982E-02 /) !W 13 + ENDIF + ENDIF + ELSE ! WS > 14 + IF (WS <= 20.0 ) THEN + IF (WS <= 16.0) THEN ! 14 < WS <= 16 + RI1 = MAX( -1.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 2.9459E+01, -7.3181E-01, 9.4613E+00, 9.2172E-03, 6.1086E+00, & + -4.9990E-01, -2.9994E-05, -6.9606E-01, -8.5076E-03, 8.1330E-03 /) !U 15 + coeffs(:,2) = (/ 1.7540E+01, -2.6071E-01, 9.3639E+00, 1.3341E-03, 9.4294E+00, & + -4.2565E-01, -2.7836E-06, -6.7708E-01, -6.9127E-02, 6.2290E-03 /) !V 15 + coeffs(:,3) = (/ 1.2792E+01, -4.6469E-01, 4.6350E+00, 1.0633E-02, 1.8523E+00, & + -3.2417E-01, -8.5038E-05, -2.2253E-01, -7.3351E-04, 5.4781E-03 /) !W 15 + ELSEIF (WS <= 18.0) THEN ! 16 < WS <= 18 + RI1 = MAX( -1.0_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 1.7775E+01, 4.5287E-01, 1.6417E+01, -2.3724E-02, 5.8998E+00, & + -5.3502E-01, 2.6202E-04, -9.9466E-02, 4.1386E-02, 4.5663E-03 /) !U 17 + coeffs(:,2) = (/ 1.2022E+01, 2.4246E-01, 1.3875E+01, -1.1725E-02, 5.1917E+00, & + -5.4329E-01, 1.1893E-04, -2.0308E-01, 6.5256E-02, 5.6597E-03 /) !V 17 + coeffs(:,3) = (/ 1.2680E+01, -1.4768E-01, 7.1498E+00, -3.0341E-03, 1.9747E+00, & + -3.8374E-01, 7.0412E-05, 2.2297E-01, 5.9943E-02, 5.3514E-03 /) !W 17 + ELSE ! 18 < WS <= 20 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + coeffs(:,1) = (/ 3.1187E+01, -6.8540E-01, 7.1288E+00, 1.1923E-02, 8.8547E+00, & + 6.3133E-02, -9.4673E-05, -2.5710E+00, -5.4077E-02, -1.2797E-04 /) !U 19 + coeffs(:,2) = (/ 1.2664E+01, 9.1858E-02, 1.9050E+01, -2.8868E-03, 7.2969E+00, & + -4.4573E-01, -6.1033E-06, -2.0960E+00, -1.9913E-02, 4.9023E-03 /) !V 19 + coeffs(:,3) = (/ 2.2146E+01, -7.6940E-01, 1.1948E+01, 1.0400E-02, 5.0034E+00, & + -4.3958E-01, -2.5936E-05, -3.0848E-01, -6.3381E-02, 5.1204E-03 /) !W 19 + ENDIF + ELSE ! WS > 20 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 1.0_ReKi ) ) + IF (WS <= 22.0) THEN ! 20 < WS <= 22 + coeffs(:,1) = (/ 2.5165E+01, -7.7660E-02, 1.9692E+01, -1.1794E-02, 9.8635E+00, & + -2.5520E-01, 2.0573E-04, -4.9850E+00, 1.1272E-01, 1.3267E-03 /) !U 21 + coeffs(:,2) = (/ 2.1691E+01, -3.1787E-01, 3.2327E+01, -4.5546E-03, 1.1194E+01, & + -8.0823E-01, 1.4306E-04, -4.3418E+00, 7.3163E-02, 6.3637E-03 /) !V 21 + coeffs(:,3) = (/ 1.4634E+01, -3.9394E-01, 1.1617E+01, 5.6387E-03, 5.4799E+00, & + -3.9011E-01, -1.0420E-05, -2.4279E+00, 6.6452E-02, 4.9504E-03 /) !W 21 + ELSEIF (WS <= 24.0) THEN ! 22 < WS <= 24 + coeffs(:,1) = (/ 7.3816E+00, 1.0538E+00, 2.1578E+01, -3.3487E-02, -6.4986E+00, & + -8.6782E-01, 3.2397E-04, 1.1412E+00, 2.2982E-01, 1.4660E-02 /) !U 23 + coeffs(:,2) = (/ 6.5302E+00, 1.0524E+00, 2.4596E+01, -4.1648E-02, 4.0584E+00, & + -6.1130E-01, 4.5468E-04, -3.6547E+00, 2.3176E-01, 8.4385E-03 /) !V 23 + coeffs(:,3) = (/ 1.3424E+01, 2.6104E-02, 7.6014E+00, -1.2744E-02, 1.0735E+01, & + 2.2086E-01, 1.9309E-04, -5.9548E+00, 8.6483E-02, -3.9550E-03 /) !W 23 + ELSE ! 24 < WS + coeffs(:,1) = (/ -1.6629E+01, 1.3094E+00, -4.4183E+00, -8.4860E-03, -1.3800E+01, & + -5.5221E-01, -5.6659E-05, 8.1834E+00, -8.2497E-03, 1.8383E-02 /) !U 25 + coeffs(:,2) = (/ 3.4796E+00, 7.1144E-01, 1.2153E+01, -2.7309E-02, 1.0003E+00, & + -6.3570E-01, 3.4424E-04, -8.5038E-01, 1.2822E-01, 1.3181E-02 /) !V 25 + coeffs(:,3) = (/ 2.7014E+00, 1.1794E-01, 2.1378E+00, 4.5539E-03, 1.6899E+00, & + 1.2254E-01, -9.6940E-05, -2.3430E-01, -2.3826E-02, 5.5964E-05 /) !W 25 + ENDIF + ENDIF + ENDIF + + HT2 = HT1*HT1 + HT3 = HT1*HT2 + RI2 = RI1*RI1 + RI3 = RI1*RI2 + + DO I = 1,3 + InCDec(I) = coeffs( 1,I) + coeffs(2,I)*Ht1 + coeffs(3,I)*RI1 & + + coeffs(4,I)*Ht2 + coeffs(5,I)*RI2 + coeffs( 6,I)*Ht1*RI1 & + + coeffs(7,I)*Ht3 + coeffs(8,I)*RI3 + coeffs( 9,I)*Ht1*RI2 & + + coeffs(10,I)*Ht2*RI1 + ENDDO + + WS1 = MAX( 2.0_ReKi, WS ) + SELECT CASE ( Ri_Cat ) + CASE ( 1 ) +! InCDec = (/ 1.623224368*WS1**1.015099356, & +! 0.884720872*WS1**1.192553093, & +! 1.338245093*WS1**0.841757461 /) + InCohB = (/ -2.524e-05+0.002122544/WS1, & + 0.004367773*WS1**(-1.14945936), & + 0.031284497*WS1**(-0.72509517) /) + + CASE ( 2 ) +! InCDec = (/ 1.478475074*WS1**0.752442176, & +! 1.310684825*WS1**0.624122449, & +! 0.849106068*WS1**0.627688235 /) + InCohB = (/ 0.003320615*WS1**(-1.18592214), & + 0.005402681*WS1**(-0.98637053), & + 0.091649927*WS1**(-1.48835650) /) + + CASE ( 3 ) +! InCDec = (/ 1.596175944*WS1**0.674743966, & +! 1.114069218*WS1**0.638049141, & +! 0.473225245*WS1**0.784331891 /) + InCohB = (/ 0.002387997*WS1**(-0.85956868), & + 0.009481901*WS1**(-1.02518835), & + 0.052147706*WS1**(-0.88949864) /) + + CASE ( 4 ) +! InCDec = (/ 1.293345620*WS1**0.955639280, & +! 1.296399839*WS1**0.838281755, & +! 0.333750239*WS1**1.103784094 /) + InCohB = (/ 0.002870978*WS1**(-1.07398490), & + 0.002435238*WS1**(-0.68685045), & + 0.125356016*WS1**(-1.34791890) /) + + CASE ( 5 ) +! InCDec = (/ 1.325256941*WS1**1.039629269, & +! 1.014004299*WS1**1.082810576, & +! 0.206383058*WS1**1.435200799 /) + InCohB = (/ 0.003545043*WS1**(-1.03669585), & + 0.003996215*WS1**(-0.95313438), & + 0.125103070*WS1**(-1.02886635) /) + END SELECT + + CASE ( SpecModel_WF_UPW ) + HT1 = MAX( 5.0_ReKi, MIN( Ht, 35.0_ReKi ) ) + IF ( WS <= 14.0 ) THEN + IF ( WS <= 10 ) THEN + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.15_ReKi ) ) + IF ( WS <= 8.0 ) THEN ! WS <= 8 + coeffs(:,1) = (/ 1.6715E+01, -3.8639E-01, 7.1817E+00, 1.5550E-03, -1.4293E+00, & + -2.0350E-01, 8.5532E-06, -3.4710E+00, -1.9743E-02, -3.9949E-04 /) !Upw_U 7 + coeffs(:,2) = (/ 8.4145E+00, -4.7610E-02, 3.9097E+00, -7.1412E-04, 1.8295E+01, & + 2.2583E-01, -1.6965E-05, 2.0769E+01, -9.1670E-02, -8.0300E-03 /) !Upw_V 7 + ELSE ! 8 < WS <= 10 + coeffs(:,1) = (/ 1.5432E+01, -2.1254E-01, 5.3075E+00, -2.9928E-03, 2.1647E+00, & + 1.1787E-02, 6.7458E-05, -9.0445E-01, -7.5941E-02, -4.7053E-03 /) !Upw_U 9 + coeffs(:,2) = (/ 7.5921E+00, 3.3520E-02, 1.2231E+01, -7.0018E-03, 6.0889E+01, & + 2.1810E-01, 1.1718E-04, 7.7287E+01, -1.3828E-01, -9.6568E-03 /) !Upw_V 9 + ENDIF + ELSE + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.05_ReKi ) ) + IF ( WS <= 12.0 ) THEN ! 10 < WS <= 12 + coeffs(:,1) = (/ 1.3539E+01, -8.4892E-02, -1.9237E+00, -1.1485E-03, -4.0840E-01, & + 3.0956E-01, 2.4048E-05, -1.1523E+00, 9.6877E-03, -4.0606E-03 /) !Upw_U 11 + coeffs(:,2) = (/ 7.7451E+00, -1.3818E-01, -9.5197E-01, 3.9610E-03, 8.3255E-01, & + 7.2166E-02, -4.5012E-05, -2.0948E-01, -2.1400E-02, -2.9788E-04 /) !Upw_V 11 + ELSE ! 12 < WS <= 14 + coeffs(:,1) = (/ 1.2857E+01, -7.9408E-03, -1.5310E+00, -4.1077E-03, 1.0496E+00, & + 1.9473E-01, 7.2808E-05, 1.8380E-01, -1.6559E-02, -2.0872E-03 /) !Upw_U 13 + coeffs(:,2) = (/ 7.2452E+00, -6.2662E-02, -2.4865E+00, 3.2123E-03, -1.0281E-01, & + 1.9698E-01, -7.5745E-05, -1.1637E+00, -4.6458E-02, -2.7037E-03 /) !Upw_V 13 + ENDIF + ENDIF + ELSE + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.05_ReKi ) ) + IF ( WS <= 18.0 ) THEN + IF ( WS <= 16.0 ) THEN ! 14 < WS <= 16 + coeffs(:,1) = (/ 1.4646E+01, -1.5023E-01, -9.7543E-01, -3.5607E-03, 4.8663E+00, & + -9.4360E-03, 1.4932E-04, 5.9503E+00, 7.4028E-02, 5.2698E-03 /) !Upw_U 15 + coeffs(:,2) = (/ 1.0133E+01, -3.1417E-01, 2.5400E+00, 6.6777E-03, 3.0790E+00, & + -2.5801E-01, -4.9501E-05, 2.8879E+00, -1.6722E-02, 4.8297E-03 /) !Upw_V 15 + ELSE ! 16 < WS <= 18 + coeffs(:,1) = (/ 1.5282E+01, -2.7642E-01, 2.5903E+00, 9.8716E-03, 5.9314E-01, & + -4.2790E-01, -1.6474E-04, -7.0065E-01, -3.2694E-02, 2.4583E-03 /) !Upw_U 17 + coeffs(:,2) = (/ 1.2464E+01, -3.4306E-01, 3.6261E+00, 5.8254E-03, 2.2592E+00, & + -1.1498E-01, -6.6196E-05, 1.3610E+00, -1.3345E-02, 1.0932E-03 /) !Upw_V 17 + ENDIF + ELSE + IF ( WS <= 20.0 ) THEN ! 18 < WS <= 20 + coeffs(:,1) = (/ 1.5059E+01, -8.0478E-02, 8.7088E+00, -1.7854E-03, 3.9922E+00, & + -6.0268E-01, 4.3906E-05, 3.3463E+00, -6.6490E-02, 1.2290E-02 /) !Upw_U 19 + coeffs(:,2) = (/ 1.0672E+01, -2.8104E-01, 7.8021E+00, 6.6360E-03, 2.4345E+00, & + -4.9103E-01, -8.3745E-05, 4.4084E-01, -9.2432E-02, 8.3096E-03 /) !Upw_V 19 + ELSE ! 20 < WS + coeffs(:,1) = (/ 1.8592E+01, 1.3888E-01, 1.6732E+01, -1.1880E-02, 2.3622E+01, & + 6.8199E-01, 7.3664E-05, 4.1289E+00, -3.8604E-01, -3.0381E-02 /) !Upw_U 21 + coeffs(:,2) = (/ 7.7137E+00, 1.2732E-01, 1.3477E+01, 1.9164E-03, 3.7133E+01, & + 3.8975E-01, -2.2818E-04, 1.8816E+01, -7.5304E-01, -2.1856E-02 /) !Upw_V 21 + ENDIF + ENDIF + ENDIF + + HT2 = HT1*HT1 + HT3 = HT1*HT2 + RI2 = RI1*RI1 + RI3 = RI1*RI2 + + DO I = 1,2 + InCDec(I) = coeffs( 1,I) + coeffs(2,I)*Ht1 + coeffs(3,I)*RI1 & + + coeffs(4,I)*Ht2 + coeffs(5,I)*RI2 + coeffs( 6,I)*Ht1*RI1 & + + coeffs(7,I)*Ht3 + coeffs(8,I)*RI3 + coeffs( 9,I)*Ht1*RI2 & + + coeffs(10,I)*Ht2*RI1 + ENDDO + + WS1 = MAX( 3.0_ReKi, WS ) +! InCDec(1:2) = (/ 5.640176786*WS1**0.269850341, & +! 6.059554513+18.44124731/WS1**1.5 /) + InCohB(1:2) = (/ 0.000448295+0.002502915/WS1, & + 0.001539069+0.005954785/WS1 /) + + + InCDec(3) = 0.4*InCDec(1) !cohA(w) = cohA(u)/2.5, number derived from histograms of u/w for NWTC and LLLJP data + InCohB(3) = 10.0*InCohB(1) !cohB(w) = cohB(u)*10, number derived from histograms of w/u for NWTC and LLLJP data + + CASE ( SpecModel_WF_07D, SpecModel_WF_14D ) + HT1 = MAX( 5.0_ReKi, MIN( Ht, 35.0_ReKi ) ) + IF ( WS <= 12.0 ) THEN + IF ( WS <= 8.0 ) THEN ! WS <= 8 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.15_ReKi ) ) + coeffs(:,1) = (/ 1.0310E+01, -6.4824E-03, -1.3258E+00, -2.7238E-03, -6.8515E+00, & + 3.1602E-02, 5.5982E-05, -8.4777E+00, 2.1506E-02, 4.9745E-04 /) !Dwn_U 7 + coeffs(:,2) = (/ 6.9491E+00, -1.3378E-01, 1.7961E-01, -4.9439E-04, -1.8140E+00, & + -4.2321E-02, 4.4962E-05, -3.6939E+00, -8.9465E-03, 4.7867E-04 /) !Dwn_V 7 + ELSEIF ( WS <= 10.0 ) THEN ! 8 < WS <= 10 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.05_ReKi ) ) + coeffs(:,1) = (/ 9.7420E+00, 6.1610E-02, 5.6636E-02, -5.5949E-03, -1.3014E+00, & + 2.0655E-01, 8.9989E-05, -1.9837E+00, 5.4957E-03, -3.5496E-03 /) !Dwn_U 9 + coeffs(:,2) = (/ 7.1063E+00, -1.7021E-01, 1.2560E+00, -4.2616E-04, 9.0937E-01, & + -1.3022E-01, 4.7976E-05, 2.1302E-01, -4.3159E-04, 1.5443E-03 /) !Dwn_V 9 + ELSE ! 10 < WS <= 12 + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.05_ReKi ) ) + coeffs(:,1) = (/ 1.0869E+01, -9.1393E-03, -1.1695E+00, -3.3725E-03, 3.2199E-01, & + 7.2692E-02, 7.0565E-05, 6.9573E-01, 2.5360E-02, 1.0187E-03 /) !Dwn_U 11 + coeffs(:,2) = (/ 6.9882E+00, -1.3517E-01, -3.0492E-01, -4.6775E-04, 4.6897E-01, & + -2.0102E-03, 3.3908E-05, 1.4604E-02, 1.1729E-02, -6.2775E-05 /) !Dwn_V 11 + ENDIF + ELSE + RI1 = MAX( -0.5_ReKi, MIN( RICH_NO, 0.05_ReKi ) ) + IF ( WS <= 14.0 ) THEN ! 12 < WS <= 14 + coeffs(:,1) = (/ 1.1105E+01, 5.3789E-02, -9.4253E-02, -5.4203E-03, -1.0114E+00, & + 1.1421E-01, 7.6110E-05, -1.2654E+00, 1.5121E-02, -2.9055E-03 /) !Dwn_U 13 + coeffs(:,2) = (/ 7.5741E+00, -8.3945E-02, 3.7020E+00, -6.0317E-03, 3.1339E-01, & + -2.1921E-01, 1.5598E-04, 6.2478E-01, 5.9490E-02, 3.4785E-03 /) !Dwn_V 13 + ELSE ! 14 < WS + coeffs(:,1) = (/ 1.2256E+01, 2.0131E-02, 1.9465E+00, -7.6608E-03, 1.5031E+00, & + -1.0916E-01, 1.3634E-04, 1.3451E+00, -1.6458E-02, 3.8312E-03 /) !Dwn_U 15 + coeffs(:,2) = (/ 7.7749E+00, -2.2712E-01, 1.3675E+00, 6.7944E-03, 4.2033E-02, & + -6.8887E-02, -9.6117E-05, -1.5526E+00, -2.2357E-02, -1.5311E-03 /) !Dwn_V 15 + ENDIF + ENDIF + + HT2 = HT1*HT1 + HT3 = HT1*HT2 + RI2 = RI1*RI1 + RI3 = RI1*RI2 + + DO I = 1,2 + InCDec(I) = coeffs( 1,I) + coeffs(2,I)*Ht1 + coeffs(3,I)*RI1 & + + coeffs(4,I)*Ht2 + coeffs(5,I)*RI2 + coeffs( 6,I)*Ht1*RI1 & + + coeffs(7,I)*Ht3 + coeffs(8,I)*RI3 + coeffs( 9,I)*Ht1*RI2 & + + coeffs(10,I)*Ht2*RI1 + ENDDO + + WS1 = MAX( 3.0_ReKi, WS ) +! WS2 = WS1*WS1 +! WS3 = WS2*WS1 +! InCDec(1:2) = (/ (a+c*WS1+e*WS2+g*WS3)/(1+b*WS1+d*WS2+f*WS3), & +! 3.357892649*WS1**0.1198781 /) + InCohB(1:2) = (/ 4.49289e-05+0.004933460/WS1, & + 0.00158053+0.014268899/WS1 /) + InCDec(3) = 0.4_ReKi*InCDec(1) !cohA(w) = cohA(u)/2.5, number derived from histograms of u/w for NWTC and LLLJP data + InCohB(3) = 10.0_ReKi*InCohB(1) !cohB(w) = cohB(u)*10, number derived from histograms of w/u for NWTC and LLLJP data + + CASE ( SpecModel_USER ) + InCDec = (/ WS, HUGE(InCohB(1)), HUGE(InCohB(1)) /) + InCohB = 0.0_ReKi ! entire array is zero + + CASE DEFAULT ! includes CASE ( 'SMOOTH' ) + + InCDec = (/1.0_ReKi, 0.75_ReKi, 0.75_ReKi /)*WS ! The davenport exponential parameter indicates that coh(v) ~ coh(w) in NWTC and LLLJP data + InCohB = 0.0_ReKi ! entire array is zero + + END SELECT + + !note that the IEC models specify their coherence parameters elsewhere... in CalcIECScalingParams() + +! IF ( p%met%IsIECModel ) THEN we'll get the defaults from CalcIECScalingParams + + +END SUBROUTINE GetDefaultCoh +!======================================================================= +!> This subroutine is used to get the default values of the Reynolds stresses. +!! sets p%met%PC_UW, p%met%PC_UV, p%met%PC_VW and +!! p%met%UWskip, p%met%UVskip, p%met%VWskip +SUBROUTINE GetDefaultRS( p, OtherSt_RandNum, TmpUstarHub, ErrStat, ErrMsg ) + + ! Needs p%grid information; calls getVelocityProfile(), also + ! depends on uHub, ZL, Rich_No, UStar + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p ! TurbSim parameters + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum ! other states for random numbers (next seed, etc) + + REAL(ReKi), INTENT(IN) :: TmpUstarHub + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + + REAL(ReKi) :: rndSgn + REAL(ReKi) :: SignProb + REAL(ReKi) :: Shr + REAL(ReKi) :: Ustar2 + REAL(ReKi) :: V(2) + REAL(ReKi) :: Z(2) + REAL(ReKi) :: ZLtmp + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(MaxMsgLen) :: ErrMsg2 + + + ErrStat = ErrID_None + ErrMsg = "" + + + Z(2) = p%grid%HubHt + 0.5*p%grid%RotorDiameter ! top of the grid + Z(1) = Z(2) - p%grid%GridHeight ! bottom of the grid + CALL getVelocityProfile(p, p%UHub, p%grid%HubHt, Z, V, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'GetDefaultRS') + + Shr = ( V(2)-V(1) ) / p%grid%GridHeight ! dv/dz + +!BJJ: check the ranges of our best-fit parameters, using domains of measured values + + SELECT CASE ( p%met%TurbModel_ID ) + CASE ( SpecModel_GP_LLJ ) + ZLtmp = MIN( MAX( p%met%ZL, -1.00_ReKi ), 1.0_ReKi ) !Limit the observed values of z/L + UStar2 = MIN( MAX( p%met%Ustar, 0.15_ReKi ), 1.0_ReKi ) !Limit the observed values of u* + Ustar2 = Ustar2*Ustar2 + CASE ( SpecModel_NWTCUP ) + ZLtmp = MIN( MAX( p%met%ZL, -0.5_ReKi ), 3.5_ReKi ) !Limit the observed values of z/L + UStar2 = MIN( MAX( p%met%Ustar, 0.2_ReKi ), 1.4_ReKi ) !Limit the observed values of u* + Ustar2 = Ustar2*Ustar2 +! CASE ( 'WF_UPW' ) +! CASE ( 'WF_07D' ) +! CASE ( 'WF_14D' ) + + CASE DEFAULT + ZLtmp = p%met%ZL + Ustar2 = p%met%Ustar*p%met%Ustar + END SELECT + + !------------------------------------------------------------------------------------------------- + ! default UW Reynolds stress + !------------------------------------------------------------------------------------------------- + p%met%UWskip = .FALSE. + + CALL RndUnif( p%RNG, OtherSt_RandNum, rndSgn ) + SELECT CASE ( p%met%TurbModel_ID ) + + CASE ( SpecModel_GP_LLJ ) + + p%met%PC_UW = TmpUstarHub**2 + + IF (p%met%PC_UW <= 0) THEN !We don't have a local u* value to tie it to; otherwise, assume p%met%PC_UW contains magnitude of value we want + IF ( p%grid%HubHt >= 100.5 ) THEN ! 116m + p%met%PC_UW = 0.0399 - 0.00371*p%UHub - 0.00182*p%met%RICH_NO + 0.00251*ZLtmp - 0.402*Shr + 1.033*Ustar2 + ELSEIF ( p%grid%HubHt >= 76.0 ) THEN ! 85 m + p%met%PC_UW = 0.00668 - 0.00184*p%UHub + 0.000709*p%met%RICH_NO + 0.264*Shr + 1.065*Ustar2 !magnitude + ELSEIF ( p%grid%HubHt >= 60.5 ) THEN ! 67 m + p%met%PC_UW = -0.0216 + 0.00319*p%UHub - 0.00205*ZLtmp + 0.206*Shr + 0.963*Ustar2 !magnitude + ELSE ! 54 m + p%met%PC_UW = -0.0373 + 0.00675*p%UHub - 0.00277*ZLtmp + 0.851*Ustar2 !magnitude + ENDIF + p%met%PC_UW = MAX(p%met%PC_UW,0.0_ReKi) + + ENDIF + + IF (p%met%PC_UW > 0) THEN + SignProb = 0.765 + 0.57/PI * ATAN( 0.78511*LOG(p%met%PC_UW)+3.42584) + IF (rndSgn <= SignProb) p%met%PC_UW = -p%met%PC_UW + ENDIF + + CASE ( SpecModel_NWTCUP ) + + IF ( p%grid%HubHt > 47.0 ) THEN ! 58m data + p%met%PC_UW = 0.165 - 0.0232*p%UHub - 0.0129*p%met%RICH_NO + 1.337*Ustar2 - 0.758*SHR + ELSEIF ( p%grid%HubHt >= 26.0 ) THEN ! 37m data + p%met%PC_UW = 0.00279 - 0.00139*p%UHub + 1.074*Ustar2 + 0.179*SHR + ELSE ! 15m data + p%met%PC_UW = -0.1310 + 0.0239*p%UHub + 0.556*Ustar2 + ENDIF + p%met%PC_UW = MAX(p%met%PC_UW,0.0_ReKi) + + IF (p%met%PC_UW > 0) THEN !i.e. not equal to zero + SignProb = 0.765 + 0.57/PI * ATAN( 0.88356*LOG(p%met%PC_UW)+2.47668) + IF (rndSgn <= SignProb) p%met%PC_UW = -p%met%PC_UW + ENDIF + + CASE ( SpecModel_WF_14D ) + + p%met%PC_UW = -Ustar2 + IF ( rndSgn > 0.9937 ) p%met%PC_UW = -p%met%PC_UW + + CASE ( SpecModel_USER, SpecModel_TimeSer ) + p%met%PC_UW = 0.0 + p%met%UWskip = .TRUE. + + CASE ( SpecModel_TIDAL, SpecModel_RIVER ) ! HYDROTURBSIM specific. + p%met%PC_UW = -Ustar2*(1-p%grid%HubHt/p%met%RefHt) + + CASE DEFAULT + + p%met%PC_UW = -Ustar2 + + END SELECT + + IF ( p%met%IsIECModel ) THEN + p%met%PC_UW = 0.0 + p%met%UWskip = .TRUE. + END IF + + !------------------------------------------------------------------------------------------------- + ! default UV Reynolds stress + !------------------------------------------------------------------------------------------------- + p%met%UVskip = .FALSE. + + CALL RndUnif( p%RNG, OtherSt_RandNum, rndSgn ) + SELECT CASE ( p%met%TurbModel_ID ) + + CASE ( SpecModel_GP_LLJ ) + + IF ( p%grid%HubHt >= 100.5 ) THEN ! 116m + p%met%PC_UV = 0.199 - 0.0167*p%UHub + 0.0115*ZLtmp + 1.143*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.6527 ) p%met%PC_UV = -p%met%PC_UV + ELSEIF ( p%grid%HubHt >= 76.0 ) THEN ! 85 m + p%met%PC_UV = 0.190 - 0.0156*p%UHub + 0.00931*ZLtmp + 1.101*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.6394 ) p%met%PC_UV = -p%met%PC_UV + ELSEIF ( p%grid%HubHt >= 60.5 ) THEN ! 67 m + p%met%PC_UV = 0.178 - 0.0141*p%UHub + 0.00709*ZLtmp + 1.072*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.6326 ) p%met%PC_UV = -p%met%PC_UV + ELSE ! 54 m + p%met%PC_UV = 0.162 - 0.0123*p%UHub + 0.00784*p%met%RICH_NO + 1.024*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.6191 ) p%met%PC_UV = -p%met%PC_UV + ENDIF + + CASE ( SpecModel_NWTCUP ) + + ! Get the magnitude and add the sign + IF ( p%grid%HubHt > 47.0 ) THEN ! 58m data + p%met%PC_UV = 0.669 - 0.0300*p%UHub - 0.0911*p%met%RICH_NO + 1.421*Ustar2 - 1.393*SHR + ELSEIF ( p%grid%HubHt >= 26.0 ) THEN ! 37m data + p%met%PC_UV = 1.521 - 0.00635*p%UHub - 0.2200*p%met%RICH_NO + 3.214*Ustar2 - 3.858*SHR + ELSE ! 15m data + p%met%PC_UV = 0.462 - 0.01400*p%UHub + 1.277*Ustar2 + ENDIF + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF (p%met%PC_UV > 0) THEN !i.e. not equal to zero + SignProb = 0.33 + 0.64/PI * ATAN( -0.374775*LOG(p%met%PC_UV)-0.205681) + IF (rndSgn <= SignProb) p%met%PC_UV = -p%met%PC_UV + ENDIF + + CASE ( SpecModel_WF_UPW ) + + p%met%PC_UV = 0.0202 + 0.890*Ustar2 - 2.461*Shr + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.7315 ) p%met%PC_UV = -p%met%PC_UV + + CASE ( SpecModel_WF_07D ) + + p%met%PC_UV = 0.5040 + 0.177*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.7355 ) p%met%PC_UV = -p%met%PC_UV + + CASE ( SpecModel_WF_14D ) + + p%met%PC_UV = 0.0430 + 0.258*Ustar2 + p%met%PC_UV = MAX(p%met%PC_UV,0.0_ReKi) + IF ( rndSgn < 0.4423 ) p%met%PC_UV = -p%met%PC_UV + + CASE DEFAULT + + p%met%PC_UV = 0.0 + p%met%UVskip = .TRUE. !use whatever comes our way from the random phases + + END SELECT + + + !------------------------------------------------------------------------------------------------- + ! default VW Reynolds stress + !------------------------------------------------------------------------------------------------- + p%met%VWskip = .FALSE. + + CALL RndUnif( p%RNG, OtherSt_RandNum, rndSgn ) + SELECT CASE ( p%met%TurbModel_ID ) + + CASE ( SpecModel_GP_LLJ ) + + IF ( p%grid%HubHt >= 100.5 ) THEN ! 116m + p%met%PC_VW = 0.0528 - 0.00210*p%UHub - 0.00531*p%met%RICH_NO - 0.519*Shr + 0.283*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.2999 ) p%met%PC_VW = -p%met%PC_VW + ELSEIF ( p%grid%HubHt >= 76.0 ) THEN ! 85 m + p%met%PC_VW = 0.0482 - 0.00264*p%UHub - 0.00391*p%met%RICH_NO - 0.240*Shr + 0.265*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.3061 ) p%met%PC_VW = -p%met%PC_VW + ELSEIF ( p%grid%HubHt >= 60.5 ) THEN ! 67 m + p%met%PC_VW = 0.0444 - 0.00249*p%UHub - 0.00403*p%met%RICH_NO - 0.141*Shr + 0.250*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.3041 ) p%met%PC_VW = -p%met%PC_VW + ELSE ! 54 m + p%met%PC_VW = 0.0443 - 0.00261*p%UHub - 0.00371*p%met%RICH_NO - 0.107*Shr + 0.226*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.3111 ) p%met%PC_VW = -p%met%PC_VW + ENDIF + + CASE ( SpecModel_NWTCUP ) + + IF ( p%grid%HubHt > 47.0 ) THEN ! 58m data + p%met%PC_VW = 0.174 + 0.00154*p%UHub - 0.0270*p%met%RICH_NO + 0.380*Ustar2 - 1.131*Shr - 0.00741*ZLtmp + ELSEIF ( p%grid%HubHt >= 26.0 ) THEN ! 37m data + p%met%PC_VW = 0.120 + 0.00283*p%UHub - 0.0227*p%met%RICH_NO + 0.306*Ustar2 - 0.825*Shr + ELSE ! 15m data + p%met%PC_VW = 0.0165 + 0.00833*p%UHub + 0.224*Ustar2 + ENDIF + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF (p%met%PC_VW > 0) THEN !i.e. not equal to zero + SignProb = 0.725 + 0.65/PI * ATAN( 0.654886_ReKi*LOG(p%met%PC_VW)+1.777198_ReKi) + IF (rndSgn <= SignProb) p%met%PC_VW = -p%met%PC_VW + ENDIF + + CASE ( SpecModel_WF_UPW ) + + p%met%PC_VW = 0.0263 + 0.273*Ustar2 - 0.684*Shr + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.3139_ReKi ) p%met%PC_VW = -p%met%PC_VW + + CASE ( SpecModel_WF_07D ) + + p%met%PC_VW = 0.241 + 0.118*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.0982_ReKi ) p%met%PC_VW = -p%met%PC_VW + + CASE ( SpecModel_WF_14D ) + + p%met%PC_VW =-0.0224 + 0.159*Ustar2 + p%met%PC_VW = MAX(p%met%PC_VW,0.0_ReKi) + IF ( rndSgn < 0.8436_ReKi ) p%met%PC_VW = -p%met%PC_VW + + CASE DEFAULT + + p%met%PC_VW = 0.0 + p%met%VWskip = .TRUE. !use whatever comes our way from the random phases + + END SELECT + + +RETURN +END SUBROUTINE GetDefaultRS +!======================================================================= +!< This function calculates the default power law exponent. +FUNCTION DefaultPowerLawExp( p ) + +! necessary requirements: +! Rich_No, KHtest, TurbModel_ID, IEC_WindType, IECstandard + + + IMPLICIT NONE + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi) :: DefaultPowerLawExp !< Default Power Law exponent for particular model + + IF ( p%met%KHtest ) THEN + DefaultPowerLawExp = 0.3 + RETURN + ENDIF + + SELECT CASE ( p%met%TurbModel_ID ) + + CASE (SpecModel_WF_UPW, SpecModel_NWTCUP) + IF ( p%met%RICH_NO > 0.0 ) THEN + DefaultPowerLawExp = 0.14733 + ELSE + DefaultPowerLawExp = 0.087687698 + 0.059641545*EXP(p%met%RICH_NO/0.04717783) + ENDIF + + CASE ( SpecModel_WF_07D, SpecModel_WF_14D ) + IF ( p%met%RICH_NO > 0.04 ) THEN + DefaultPowerLawExp = 0.17903 + ELSE + DefaultPowerLawExp = 0.127704032 + 0.031228952*EXP(p%met%RICH_NO/0.0805173) + ENDIF + + CASE (SpecModel_SMOOTH, SpecModel_GP_LLJ, SpecModel_TIDAL, SpecModel_RIVER, SpecModel_TimeSer ) + ! A 1/7 power law seems to work ok for HYDRO spectral models also... + DefaultPowerLawExp = 0.143 + + CASE DEFAULT + IF ( p%IEC%IEC_WindType == IEC_EWM1 .OR. p%IEC%IEC_WindType == IEC_EWM50 .OR. p%IEC%IEC_WindType == IEC_EWM100 ) THEN + DefaultPowerLawExp = 0.11 ! [IEC 61400-1 6.3.2.1 (14)] + ELSEIF ( p%IEC%IECstandard == 3 ) THEN + DefaultPowerLawExp = 0.14 ! [IEC 61400-3 Page 22 (3)] + ELSE + DefaultPowerLawExp = 0.2 ! [IEC 61400-1 6.3.1.2 (10)] + ENDIF + + END SELECT + + RETURN +END FUNCTION DefaultPowerLawExp +!======================================================================= +FUNCTION getUstarDiab(u_ref, z_ref, z0, ZL) + + + IMPLICIT NONE + + REAL(ReKi), INTENT(IN) :: u_ref ! Wind speed at reference height + REAL(ReKi), INTENT(IN) :: z_ref ! Reference height + REAL(ReKi), INTENT(IN) :: z0 ! Surface roughness length -- It must be > 0 (which we've already checked for) + REAL(ReKi), INTENT(IN) :: ZL ! M-O stability parameter + + REAL(ReKi) :: tmp ! a temporary value + REAL(ReKi) :: psiM + REAL(ReKi) :: getUstarDiab ! the diabatic u* value (u*0) + + IF ( ZL >= 0 ) THEN !& ZL < 1 + psiM = -5.0*MIN(ZL, REAL(1.0,ReKi) ) + ELSE + tmp = (1.0 - 15.0*ZL)**0.25 + + !psiM = -2.0*LOG( (1.0 + tmp)/2.0 ) - LOG( (1.0 + tmp*tmp)/2.0 ) + 2.0*ATAN( tmp ) - 0.5 * PI + psiM = -LOG( 0.125 * ( (1.0 + tmp)**2 * (1.0 + tmp*tmp) ) ) + 2.0*ATAN( tmp ) - 0.5 * PI + + !bjj 11-may-2016: because of the negative sign in the equation below, I believe psiM needs to switch signs. + ! if true, this has been implemented incorrectly for at least 15 years. + psiM = -psiM + + ENDIF + + getUstarDiab = ( 0.4 * u_ref ) / ( LOG( z_ref / z0 ) - psiM ) + +END FUNCTION getUstarDiab +!======================================================================= +!> this routine calculates the M-O z/L and L parameters using +!! Rich_No, SpecModel, and HubHt +SUBROUTINE Calc_MO_zL(SpecModel, Rich_No, HubHt, ZL, L ) + + + IMPLICIT NONE + + REAL(ReKi) , intent(in) :: HubHt ! Hub height + REAL(ReKi) , intent(in) :: RICH_NO ! Gradient Richardson number + REAL(ReKi) , intent( out) :: L ! M-O length + REAL(ReKi) , intent( out) :: ZL ! A measure of stability + + INTEGER(IntKi), intent(in) :: SpecModel ! Integer value of spectral model (see SpecModel enum) + + + ! ***** Calculate M-O z/L parameter : z/L is a number in (-inf, 1] ***** + + IF ( SpecModel == SpecModel_NWTCUP ) THEN + ! Calculate disk averaged Z/L from turbine layer Ri for NWTC/LIST experiment + + IF ( RICH_NO <= -0.1 ) THEN + ZL = -0.254 + 1.047*RICH_NO + ELSEIF ( RICH_NO < 0 ) THEN + ZL = 10.369*RICH_NO/(1.0 - 19.393*RICH_NO) + ELSE !( RICH_NO < 0.155 ) THEN + ZL = 2.535*MIN( RICH_NO, 0.155_ReKi ) / (1.0 - 6.252*MIN( RICH_NO, 0.155_ReKi )) + ENDIF + + + ELSEIF (SpecModel == SpecModel_GP_LLJ) THEN + + IF ( RICH_NO <= -0.1 ) THEN + ZL = -0.047 + 1.054*RICH_NO + ELSEIF ( RICH_NO < 0 ) THEN + ZL = 2.213*RICH_NO/(1.0 - 4.698*RICH_NO) + ELSE !( RICH_NO < 0.1367 ) THEN + ZL = 3.132*MIN( RICH_NO, 0.1367_ReKi ) / (1.0 - 6.762*MIN( RICH_NO, 0.1367_ReKi )) + ENDIF + + ELSE ! see Businger, J.A.; Wyngaard, J.C.; Izumi, Y.; Bradley, E.F. (1971). "Flux-Profile Relationships in the Atmospheric Surface Layer." Journal of the Atmospheric Sciences (28); pp.181-189. + + IF ( RICH_NO <= 0.0_ReKi ) THEN + ZL = RICH_NO + !PhiM = (1.0 - 16.0*ZL)**-0.25 + ELSEIF ( RICH_NO < 0.16667_ReKi ) THEN + ZL = MIN(RICH_NO / ( 1.0_ReKi - 5.0_ReKi*RICH_NO ), 1.0_ReKi ) ! The MIN() will take care of rounding issues. + !PhiM = (1.0 + 5.0*ZL) + ELSE + ZL = 1.0_ReKi + ENDIF + + ENDIF !SpecModels + + ZL = MIN( ZL, 1.0_ReKi ) + + + ! ***** Calculate M-O length scale, L [meters] ***** + ! L should be constant in the surface layer + + IF ( .NOT. EqualRealNos(ZL , 0.0_ReKi) ) THEN + L = HubHt / ZL ! Since ZL is the average ZL over the rotor disk, we should use HubHt to estimate L instead + ELSE + L = HUGE( L ) + ENDIF + + +END SUBROUTINE Calc_MO_zL +!======================================================================= +SUBROUTINE CalcIECScalingParams( p_IEC, HubHt, UHub, InCDec, InCohB, TurbModel_ID, IsIECModel, ErrStat, ErrMsg ) +! REQUires these be set prior to calling:NumTurbInp, IECedition, IECTurbC, IEC_WindType, IsIECModel +! calculates SigmaIEC, Lambda, IntegralScale, Lc + + TYPE(IEC_ParameterType), INTENT(INOUT) :: p_IEC ! parameters for IEC models + REAL(ReKi) , INTENT(IN) :: HubHt ! Hub-height + REAL(ReKi) , INTENT(IN) :: UHub ! Hub-height (total) wind speed (m/s) + + REAL(ReKi) , INTENT(OUT) :: InCDec (3) ! Contains the coherence decrements + REAL(ReKi) , INTENT(OUT) :: InCohB (3) ! Contains the coherence b/L (offset) parameters + INTEGER(IntKi) , INTENT(IN) :: TurbModel_ID ! Integer value of spectral model (see SpecModel enum) + LOGICAL , INTENT(IN) :: IsIECModel ! Determines if this is actually an IEC model, or if we just set the values to 0 and return + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( .NOT. IsIECModel ) THEN + + p_IEC%SigmaIEC = 0 + p_IEC%Lambda = 0 + p_IEC%IntegralScale = 0 + p_IEC%LC = 0.0 ! The length scale is not defined for the non-IEC models + + RETURN + + ENDIF ! TurbModel == 'IECKAI', 'IECVKM', 'API', or 'MODVKM' + + + + ! If IECKAI or IECVKM spectral models are specified, determine turb intensity + ! and slope of Sigma wrt wind speed from IEC turbulence characteristic, + ! IECTurbC = A, B, or C or from user specified quantity. + + + IF ( p_IEC%NumTurbInp ) THEN + + ! user specified a particular percent TI: + + p_IEC%TurbInt = 0.01*p_IEC%PerTurbInt + p_IEC%SigmaIEC(1) = p_IEC%TurbInt*UHub + + ! bjj: note Vave isn't set in this case, but we only print it to the summary file (and use it) if .not. NumTurbInp + + ELSE + + + SELECT CASE (p_IEC%IECedition) + + CASE ( 2 ) + + IF ( p_IEC%IECTurbC == 'A' ) THEN + p_IEC%TurbInt15 = 0.18 + p_IEC%SigmaSlope = 2.0 + ELSEIF ( p_IEC%IECTurbC == 'B' ) THEN + p_IEC%TurbInt15 = 0.16 + p_IEC%SigmaSlope = 3.0 + ELSE ! We should never get here, but just to be complete... + ErrStat = ErrID_Fatal + ErrMsg = 'CalcIECScalingParams: Invalid IEC turbulence characteristic.' + RETURN + ENDIF + + p_IEC%SigmaIEC(1) = p_IEC%TurbInt15*( ( 15.0 + p_IEC%SigmaSlope*UHub ) / ( p_IEC%SigmaSlope + 1.0 ) ) + p_IEC%TurbInt = p_IEC%SigmaIEC(1)/UHub + + CASE ( 3 ) + + IF ( p_IEC%IECTurbC == 'A' ) THEN + p_IEC%TurbInt15 = 0.16 + ELSEIF ( p_IEC%IECTurbC == 'B' ) THEN + p_IEC%TurbInt15 = 0.14 + ELSEIF ( p_IEC%IECTurbC == 'C' ) THEN + p_IEC%TurbInt15 = 0.12 + ELSE ! We should never get here, but just to be complete... + ErrStat = ErrID_Fatal + ErrMsg = 'CalcIECScalingParams: Invalid IEC turbulence characteristic.' + RETURN + ENDIF + + + SELECT CASE ( p_IEC%IEC_WindType ) + CASE ( IEC_NTM ) + p_IEC%SigmaIEC(1) = p_IEC%TurbInt15*( 0.75*UHub + 5.6 ) ! [IEC-1 Ed3 6.3.1.3 (11)] + CASE ( IEC_ETM ) + p_IEC%Vave = 0.2*p_IEC%Vref ! [IEC-1 Ed3 6.3.1.1 ( 9)] + p_IEC%SigmaIEC(1) = p_IEC%ETMc * p_IEC%TurbInt15 * ( 0.072 * & + ( p_IEC%Vave / p_IEC%ETMc + 3.0) * (Uhub / p_IEC%ETMc - 4.0)+10.0 ) ! [IEC-1 Ed3 6.3.2.3 (19)] + CASE ( IEC_EWM1, IEC_EWM50, IEC_EWM100 ) + p_IEC%Vave = 0.2*p_IEC%Vref ! [IEC-1 Ed3 6.3.1.1 ( 9)] + p_IEC%SigmaIEC(1) = 0.11*Uhub ! [IEC-1 Ed3 6.3.2.1 (16)] + CASE DEFAULT + ErrStat = ErrID_Fatal + ErrMsg = 'CalcIECScalingParams: Invalid IEC wind type.' + RETURN + END SELECT + p_IEC%TurbInt = p_IEC%SigmaIEC(1)/UHub + + CASE DEFAULT ! Likewise, this should never happen... + + ErrStat = ErrID_Fatal + ErrMsg = 'CalcIECScalingParams: Invalid IEC 61400-1 edition number.' + RETURN + + END SELECT + + + ENDIF + + ! note PLExp for IEC is set elsewhere + + ! IEC turbulence scale parameter, Lambda(1), and IEC coherency scale parameter, LC + + IF ( p_IEC%IECedition == 2 ) THEN + + ! section 6.3.1.3 Eq. 9 + IF ( HubHt < 30.0_ReKi ) THEN + p_IEC%Lambda(1) = 0.7*HubHt + ELSE + p_IEC%Lambda(1) = 21.0 + ENDIF + + p_IEC%LC = 3.5*p_IEC%Lambda(1) + InCDec = (/ 8.80_ReKi, HUGE(p_IEC%LC), HUGE(p_IEC%LC) /) ! u-, v-, and w-component coherence decrement + + ELSE !IF (p_IEC%IECedition == 3 ) THEN + + ! section 6.3.1.3 Eq. 9 + + IF ( HubHt < 60.0_ReKi ) THEN + p_IEC%Lambda(1) = 0.7*HubHt + ELSE + p_IEC%Lambda(1) = 42.0 + ENDIF + + p_IEC%LC = 8.1*p_IEC%Lambda(1) + InCDec = (/ 12.00_ReKi, HUGE(p_IEC%LC), HUGE(p_IEC%LC) /) ! u-, v-, and w-component coherence decrement for IEC Ed. 3 + + ENDIF + + InCohB = (/ 0.12_ReKi/p_IEC%LC, 0.0_ReKi, 0.0_ReKi /) + + + ! Set Lambda for Modified von Karman model: +#ifdef MVK +!bjj: this will probably need to be rethought with TurbSim v2.0 + IF ( MVK .AND. TurbModel_ID == SpecModel_MODVKM ) THEN + p%met%z0 = FindZ0(HubHt, p_IEC%SigmaIEC(1), UHub, p%met%Fc) + CALL ScaleMODVKM(HubHt, UHub, p_IEC%Lambda(1), p_IEC%Lambda(2), p_IEC%Lambda(3)) + ENDIF +#endif + + ! Sigma for v and w components and + ! Integral scales (which depend on lambda) + + IF ( TurbModel_ID == SpecModel_IECVKM ) THEN + + p_IEC%SigmaIEC(2) = 1.0*p_IEC%SigmaIEC(1) + p_IEC%SigmaIEC(3) = 1.0*p_IEC%SigmaIEC(1) + + p_IEC%IntegralScale(:) = 3.5 *p_IEC%Lambda(1) !L_k + + ELSE + + p_IEC%SigmaIEC(2) = 0.8*p_IEC%SigmaIEC(1) + p_IEC%SigmaIEC(3) = 0.5*p_IEC%SigmaIEC(1) + + p_IEC%IntegralScale(1) = 8.1 *p_IEC%Lambda(1) !L_k + p_IEC%IntegralScale(2) = 2.7 *p_IEC%Lambda(1) !L_k + p_IEC%IntegralScale(3) = 0.66*p_IEC%Lambda(1) !L_k + + END IF + + + +END SUBROUTINE CalcIECScalingParams +!======================================================================= +!> Routine sets the default ETMc, WindProfileType, Z0, Latitude, CohExp. +!! These depend on p%met%TurbModel_ID and p%usr%NPoints. +!! +!! URef, ZJetMax, and PLExp are initialized, but cannot calculate their +!! default values until the richardson number or ustar are set. +SUBROUTINE DefaultMetBndryCndtns(p) + + +TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters + + ! default ETMc + p%IEC%ETMc = 2.0_ReKi + + + ! default WindProfileType + SELECT CASE ( p%met%TurbModel_ID ) + CASE ( SpecModel_TimeSer ) + IF ( p%usr%NPoints > 1 ) THEN + p%met%WindProfileType = 'TS' + ELSE + p%met%WindProfileType = 'PL' + call WrScr( 'Warning: WindProfileType will default to power-law profile because only one time-series point was entered.') + END IF + CASE ( SpecModel_GP_LLJ ) + p%met%WindProfileType = 'JET' + + CASE ( SpecModel_TIDAL ) + p%met%WindProfileType = 'H2L' + + CASE ( SpecModel_USRVKM ) + p%met%WindProfileType = 'USR' + + CASE ( SpecModel_API ) + p%met%WindProfileType = 'API' ! ADDED BY YG + + CASE DEFAULT + p%met%WindProfileType = 'IEC' + END SELECT + + + ! Initialize ZJetMax (will need to set default later) + p%met%ZJetMax = 0.0_ReKi + + ! Initialize URef (will need to set default later) + p%met%URef = 0.0_ReKi + + ! Initialize PLExp (will need to set default later) + p%met%PLExp = 0.0_ReKi ! DefaultPowerLawExp( p ) For some models, this routine requires RICH_NO, which we do not know, yet. We'll call DefaultPowerLawExp later for all cases + + ! Default Z0 + SELECT CASE ( p%met%TurbModel_ID ) + CASE (SpecModel_SMOOTH) + p%met%Z0 = 0.010 + CASE (SpecModel_GP_LLJ ) + p%met%Z0 = 0.005 + CASE (SpecModel_WF_UPW ) + p%met%Z0 = 0.018 + CASE (SpecModel_NWTCUP ) + p%met%Z0 = 0.021 + CASE (SpecModel_WF_07D ) + p%met%Z0 = 0.233 + CASE (SpecModel_WF_14D ) + p%met%Z0 = 0.064 + CASE DEFAULT !IEC values + p%met%Z0 = 0.030 ! Represents smooth, homogenous terrain + END SELECT + + ! Default Latitude + p%met%Latitude = 45.0 + + ! Default CohExp + p%met%CohExp = 0.0 ! was 0.25 + + +END SUBROUTINE DefaultMetBndryCndtns +!======================================================================= +!> Calculate the default mixing layer depth, ZI, +!! based on Ustar, UstarDiab, Uref, RefHt, Z0, Fc +SUBROUTINE DefaultMixingLayerDepth(p) +! + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters + + IF ( p%met%Ustar < p%met%UstarDiab ) THEN + p%met%ZI = ( 0.04 * p%met%Uref ) / ( 1.0E-4 * LOG10( p%met%RefHt / p%met%Z0 ) ) !for "very" windy days + ELSE + !Should Wind Farm models use the other definition since that was what was used in creating those models? + p%met%ZI = p%met%Ustar / (6.0 * p%met%Fc) + ENDIF + +END SUBROUTINE DefaultMixingLayerDepth +!======================================================================= +!> Calculate the default UStar value, based on +!! UstarDiab (URef, RefHt, Z0, ZL), TurbModel_ID, ZL, URef +SUBROUTINE DefaultUstar(p) + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters + + + p%met%UstarDiab = getUstarDiab(p%met%URef, p%met%RefHt, p%met%z0, p%met%ZL) + SELECT CASE ( p%met%TurbModel_ID ) + + CASE (SpecModel_WF_UPW) + + IF ( p%met%ZL < 0.0 ) THEN + p%met%Ustar = 1.162 * p%met%UstarDiab**( 2.0 / 3.0 ) + ELSE ! Include the neutral case to avoid strange discontinuities + p%met%Ustar = 0.911 * p%met%UstarDiab**( 2.0 / 3.0 ) + ENDIF + + CASE ( SpecModel_WF_07D, SpecModel_WF_14D ) + + IF ( p%met%ZL < 0.0 ) THEN + p%met%Ustar = 1.484 * p%met%UstarDiab**( 2.0 / 3.0 ) + ELSE ! Include the neutral case with the stable one to avoid strange discontinuities + p%met%Ustar = 1.370 * p%met%UstarDiab**( 2.0 / 3.0 ) + ENDIF + + CASE (SpecModel_GP_LLJ ) + p%met%Ustar = 0.17454 + 0.72045*p%met%UstarDiab**1.36242 + + CASE ( SpecModel_NWTCUP ) + p%met%Ustar = 0.2716 + 0.7573*p%met%UstarDiab**1.2599 + + CASE ( SpecModel_TIDAL , SpecModel_RIVER ) + ! Use a constant drag coefficient for the HYDRO spectral models. + p%met%Ustar = p%met%Uref*0.05 ! This corresponds to a drag coefficient of 0.0025. + !p%met%Ustar = p%met%Uref*0.04 ! This corresponds to a drag coefficient of 0.0016. + + CASE DEFAULT + p%met%Ustar = p%met%UstarDiab + + END SELECT +END SUBROUTINE DefaultUstar +!======================================================================= +!> Calculate the default ZJetMax value, based on +!! Rich_No, ZL, Ustar, plus A random amount +SUBROUTINE DefaultZJetMax(p, OtherSt_RandNum) + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters + TYPE(RandNum_OtherStateType),INTENT(INOUT) :: OtherSt_RandNum !< other states for random numbers (next seed, etc) + + REAL(ReKi) :: RandomValue + + + ! values based on Neil Kelley's analysis + p%met%ZJetMax = -14.820561*p%met%Rich_No + 56.488123*p%met%ZL + 166.499069*p%met%Ustar + 188.253377 + p%met%ZJetMax = 1.9326 *p%met%ZJetMax - 252.7267 ! Correct with the residual + + CALL RndJetHeight( p%RNG, OtherSt_RandNum, RandomValue ) ! Add a random amount + + p%met%ZJetMax = MIN( MAX(p%met%ZJetMax + RandomValue, ZJetMax_LB ), ZJetMax_UB ) + +END SUBROUTINE DefaultZJetMax +!======================================================================= +!!> Calculate the default UStar value, based on +!!! UstarDiab, TurbModel_ID, ZL, URef +!SUBROUTINE Default(p) +! +! TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< TurbSim parameters +! +!END SUBROUTINE Default + +!======================================================================= +!< Routine to set parameters for the JET profile: UJetMax, ChebyCoef_WS, ChebyCoef_WD +!! will also calculate default URef if requested. +!! needs ZJetMax, RefHt, URef (unless asked to calculated here) set prior to calling +SUBROUTINE getJetCoeffs( p, getDefaultURef, OtherSt_RandNum, ErrStat, ErrMsg ) + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< parameters for TurbSim + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum !< other states for random number generation + LOGICAL , INTENT(IN ) :: getDefaultURef !< determines if we also calculate a default URef + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< error message + + ! local variables + REAL(ReKi) :: RandomValue + REAL(ReKi) :: URef + INTEGER(IntKi) :: ErrStat2 + CHARACTER(MaxMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + + IF ( getDefaultURef ) THEN ! Calculate a default value + + p%met%UJetMax = MAX( -21.5515_ReKi + 6.6827_ReKi*LOG(p%met%ZJetMax), 5.0_ReKi ) !Jet max must be at least 5 m/s (occurs ~50 m); shouldn't happen, but just in case.... + + CALL Rnd3ParmNorm( p%RNG, OtherSt_RandNum, RandomValue, 0.1076_ReKi, -0.1404_ReKi, 3.6111_ReKi, -15.0_ReKi, 20.0_ReKi, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'getJetCoeffs') + + IF (p%met%UJetMax + RandomValue > 0 ) p%met%UJetMax = p%met%UJetMax + RandomValue + + CALL GetChebCoefs( p, .TRUE. , ErrStat2, ErrMsg2 ) ! These coefficients are a function of UJetMax, ZJetMax, RICH_NO, and p%met%Ustar + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'getJetCoeffs') + + CALL getVelocity(p, p%met%UJetMax, p%met%ZJetMax, p%met%RefHt, URef, ErrStat2, ErrMsg2) + p%met%URef = URef + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'getJetCoeffs') + + + ELSE !IF ( trim(p%met%WindProfileType) == 'JET' ) then + IF ( EqualRealNos( p%met%RefHt, p%met%ZJetMax ) ) THEN + p%met%UJetMax = p%met%URef + CALL GetChebCoefs( p, .TRUE. , ErrStat2, ErrMsg2 ) ! These coefficients are a function of UJetMax, ZJetMax, RICH_NO, and p%met%Ustar + ELSE + CALL GetChebCoefs(p, .FALSE., ErrStat2, ErrMsg2) ! also calculate p%met%UJetMax + END IF + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'getJetCoeffs') + + ENDIF !Jet wind profile + +END SUBROUTINE getJetCoeffs +!======================================================================= + +END MODULE TS_FileIO diff --git a/OpenFAST/modules/turbsim/src/TSsubs.f90 b/OpenFAST/modules/turbsim/src/TSsubs.f90 new file mode 100644 index 000000000..f8b50992f --- /dev/null +++ b/OpenFAST/modules/turbsim/src/TSsubs.f90 @@ -0,0 +1,2536 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TSSubs + + USE ModifiedvKrm_mod + + use TS_Profiles + use TS_RandNum + use TS_VelocitySpectra + USE NWTC_FFTPACK + USE NWTC_LAPACK + + + IMPLICIT NONE + + + +CONTAINS + +!======================================================================= +!> This subroutine returns the complex Fourier coefficients (packed in a +!! real array) of the simulated velocity (wind/water speed). It returns +!! values FOR ONLY the velocity components that use the IEC method for +!! computing spatial coherence; i.e., for i where SCMod(i) == CohMod_IEC +SUBROUTINE CalcFourierCoeffs_IEC( p, U, PhaseAngles, S, V, TRH, ErrStat, ErrMsg ) + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< TurbSim parameters +REAL(ReKi), INTENT(IN) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), INTENT(IN) :: PhaseAngles (:,:,:) !< The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(IN) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: TRH (:) !< The transfer function matrix. just used as a work array +INTEGER(IntKi), INTENT(OUT) :: ErrStat +CHARACTER(*), INTENT(OUT) :: ErrMsg + + + ! Internal variables + +REAL(ReKi), ALLOCATABLE :: Dist(:) ! The distance between points +REAL(ReKi), ALLOCATABLE :: DistU(:) + +INTEGER :: J +INTEGER :: I +INTEGER :: IFreq +INTEGER :: Indx +INTEGER :: IVec ! wind component, 1=u, 2=v, 3=w + +INTEGER(IntKi) :: ErrStat2 +CHARACTER(MaxMsgLen) :: ErrMsg2 + + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. ANY(p%met%SCMod == CohMod_IEC) ) RETURN + + !-------------------------------------------------------------------------------- + ! allocate arrays + !-------------------------------------------------------------------------------- + CALL AllocAry( Dist, p%grid%NPacked, 'Dist coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_IEC') + CALL AllocAry( DistU, p%grid%NPacked, 'DistU coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_IEC') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !-------------------------------------------------------------------------------- + ! Calculate the distances and other parameters that don't change with frequency + !--------------------------------------------------------------------------------- + + ! Calculate Dist array (distance between points I and J) + ! and the DistU term, i.e., (r/u): u is uHub for IEC + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + Indx = Indx + 1 + Dist(Indx) = SQRT( ( p%grid%Y(I) - p%grid%Y(J) )**2 + ( p%grid%Z(I) - p%grid%Z(J) )**2 ) + DistU(Indx) = Dist(Indx)/p%UHub + END DO ! I + END DO ! J + + + !-------------------------------------------------------------------------------- + ! Calculate the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IVec = 1,3 + + IF (p%met%SCMod(IVec) /= CohMod_IEC) CYCLE ! Check the next component (this one doesn't use the IEC method) + + V(:,:,IVec) = 0.0_ReKi + + CALL WrScr ( ' '//Comp(IVec)//'-component matrices (IEC coherence method)' ) + + !-------------------------------------------------------------------------------- + ! Calculate the coherence, Veers' H matrix (CSDs), and the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IFREQ = 1,p%grid%NumFreq + ! ----------------------------------------------- + ! Create the coherence matrix for this frequency + ! ----------------------------------------------- + Indx = 1 + DO J = 1,p%usr%NPoints-1 ! start with the user-defined points (which don't get added coherence) + + TRH(Indx) = 1.0_ReKi + Indx = Indx + 1 + + DO I=J+1,p%grid%NPoints + TRH(Indx) = 0.0_ReKi + Indx = Indx + 1 + END DO !I + + END DO !J + + + DO J=max(1, p%usr%NPoints),p%grid%NPoints + DO I=J,p%grid%NPoints + + TRH(Indx) = EXP( -1.0_ReKi * p%met%InCDec(IVec) * & + SQRT( (p%grid%Freq(IFreq)*DistU(Indx) )**2 + (p%met%InCohB(IVec)*Dist(Indx))**2 ) ) + + Indx = Indx + 1 + + ENDDO ! I + ENDDO ! J + + ! ----------------------------------------------- + ! Now transform coherence to H matrix and then + ! use H matrix to calculate coefficients + ! ----------------------------------------------- + + CALL Coh2H( p, IVec, IFreq, TRH, S, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_IEC') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + CALL H2Coeffs( IVec, IFreq, TRH, PhaseAngles, V, p%grid%NPoints ) + END DO !IFreq + + END DO !IVec + + CALL Cleanup() + RETURN + +!............................................ +CONTAINS + SUBROUTINE Cleanup() + + IF ( ALLOCATED( Dist ) ) DEALLOCATE( Dist ) + IF ( ALLOCATED( DistU ) ) DEALLOCATE( DistU ) + END SUBROUTINE Cleanup +!............................................ +END SUBROUTINE CalcFourierCoeffs_IEC +!======================================================================= +!> This subroutine returns the complex Fourier coefficients (packed in a +!! real array) of the simulated velocity (wind/water speed). It returns +!! values FOR ONLY the velocity components that use the general method for +!! computing spatial coherence; i.e., for i where SCMod(i) == CohMod_GENERAL +SUBROUTINE CalcFourierCoeffs_General( p, U, PhaseAngles, S, V, TRH, ErrStat, ErrMsg ) + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< TurbSim parameters +REAL(ReKi), INTENT(IN) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), INTENT(IN) :: PhaseAngles (:,:,:) !< The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(IN) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: TRH (:) !< The transfer function matrix. just used as a work array +INTEGER(IntKi), INTENT(OUT) :: ErrStat +CHARACTER(*), INTENT(OUT) :: ErrMsg + + + ! Internal variables + +INTEGER :: UC ! I/O unit for Coherence debugging file. +LOGICAL, PARAMETER :: COH_OUT = .FALSE. ! This parameter has been added to replace the NON-STANDARD compiler directive previously used + +REAL(ReKi), ALLOCATABLE :: Dist(:) ! The distance between points +REAL(ReKi), ALLOCATABLE :: DistU(:) +REAL(ReKi), ALLOCATABLE :: DistZMExp(:) + +REAL(ReKi) :: dY ! the lateral distance between two points +REAL(ReKi) :: UM ! The mean wind speed of the two points +REAL(ReKi) :: ZM ! The mean height of the two points + +INTEGER :: J +INTEGER :: I +INTEGER :: IFreq +INTEGER :: Indx +INTEGER :: IVec ! wind component, 1=u, 2=v, 3=w + +INTEGER(IntKi) :: ErrStat2 +CHARACTER(MaxMsgLen) :: ErrMsg2 + + + + ErrStat = ErrID_None + ErrMsg = "" + + IF (.NOT. ANY(p%met%SCMod == CohMod_GENERAL) ) RETURN + + + !-------------------------------------------------------------------------------- + ! allocate arrays + !-------------------------------------------------------------------------------- + CALL AllocAry( Dist, p%grid%NPacked, 'Dist coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + CALL AllocAry( DistU, p%grid%NPacked, 'DistU coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + CALL AllocAry( DistZMExp, p%grid%NPacked, 'DistZMExp coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !-------------------------------------------------------------------------------- + ! Calculate the distances and other parameters that don't change with frequency + !--------------------------------------------------------------------------------- + + ! Calculate Dist array (distance between points I and J) + IF ( .NOT. PeriodicY ) THEN + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + Indx = Indx + 1 + Dist(Indx)= SQRT( ( p%grid%Y(I) - p%grid%Y(J) )**2 + ( p%grid%Z(I) - p%grid%Z(J) )**2 ) + END DO ! I + END DO ! J + ELSE + ! bjj need to test ths more!!! + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + + Indx = Indx + 1 + dY = p%grid%Y(I) - p%grid%Y(J) + IF (dY > 0.5*p%grid%GridWidth ) THEN + dY = dY - p%grid%GridWidth - p%grid%GridRes_Y + ELSE IF (dY < -0.5*p%grid%GridWidth ) THEN + dY = dY + p%grid%GridWidth + p%grid%GridRes_Y + END IF + + Dist(Indx)= SQRT( ( dY )**2 + ( p%grid%Z(I) - p%grid%Z(J) )**2 ) + + END DO + END DO + END IF + + + ! Compute the DistZMExp term, i.e., -(r/z_m)^CohExp + IF ( EqualRealNos( p%met%COHEXP, 0.0_ReKi ) ) THEN + DistZMExp = -1.0_ReKi ! value for entire array + ELSE + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + + Indx = Indx + 1 + ZM = 0.5*( p%grid%Z(I) + p%grid%Z(J) ) + DistZMExp(Indx) = -1.0_ReKi*( Dist(Indx)/ZM )**p%met%COHEXP ! Note: 0**0 = 1 + END DO ! I + END DO ! J + END IF + + ! Compute the DistU term, i.e., (r/u): u is average u at points I and J + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + Indx = Indx + 1 + UM = p%UHub ! was: 0.5*( U(I) + U(J) ) + DistU(Indx) = Dist(Indx)/UM + END DO ! I + END DO ! J + + !................. + ! DEBUGGING + !................. +IF ( COH_OUT ) THEN !debugging info... + + ! Write the coherence for three frequencies, for debugging purposes + CALL GetNewUnit( UC, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + + CALL OpenFOutFile( UC, TRIM(p%RootName)//'.coh', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + WRITE( UC, '(A4,X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'Comp','Freq',(I,I=1,p%grid%NPacked) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'Distance', Dist(:) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) '(r/u)', DistU(:) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) '(u)', p%met%URef + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) '-(r/z_m)^CohExp', DistZMExp(:) +ENDIF + + + !-------------------------------------------------------------------------------- + ! Calculate the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IVec = 1,3 + + IF (p%met%SCMod(IVec) /= CohMod_GENERAL) CYCLE ! Check the next component (this one doesn't use the GENERAL method) + + V(:,:,IVec) = 0.0_ReKi + + CALL WrScr ( ' '//Comp(IVec)//'-component matrices (general coherence model)' ) + + !-------------------------------------------------------------------------------- + ! Calculate the coherence, Veers' H matrix (CSDs), and the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IFREQ = 1,p%grid%NumFreq + ! ----------------------------------------------- + ! Create the coherence matrix for this frequency + ! ----------------------------------------------- + + Indx = 1 + DO J = 1,p%usr%NPoints-1 ! start with user-defined points (which don't get added coherence) + + TRH(Indx) = 1.0_ReKi + Indx = Indx + 1 + + DO I=J+1,p%grid%NPoints + TRH(Indx) = 0.0_ReKi + Indx = Indx + 1 + END DO !I + + END DO !J + + DO J=max(1, p%usr%NPoints),p%grid%NPoints + DO I=J,p%grid%NPoints + + TRH(Indx) = EXP( p%met%InCDec(IVec) * DistZMExp(Indx)* & + SQRT( (p%grid%Freq(IFreq)*DistU(Indx) )**2 + (p%met%InCohB(IVec)*Dist(Indx))**2 ) ) + + Indx = Indx + 1 + + ENDDO ! I + ENDDO ! J + !................. + ! DEBUGGING + !................. + IF (COH_OUT) THEN + ! IF (IFreq == 1 .OR. IFreq == p%grid%NumFreq) THEN + WRITE( UC, '(I3,2X,F15.5,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) IVec, p%grid%Freq(IFreq), TRH(1:p%grid%NPacked) + ! ENDIF + ENDIF + + ! ----------------------------------------------- + ! Now transform coherence to H matrix and then + ! use H matrix to calculate coefficients + ! ----------------------------------------------- + + CALL Coh2H( p, IVec, IFreq, TRH, S, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_General') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + CALL H2Coeffs( IVec, IFreq, TRH, PhaseAngles, V, p%grid%NPoints ) + END DO !IFreq + + END DO !IVec + + CALL Cleanup() + RETURN +!............................................ +CONTAINS + SUBROUTINE Cleanup() + + IF (COH_OUT .AND. UC > 0) CLOSE( UC ) + + IF ( ALLOCATED( Dist ) ) DEALLOCATE( Dist ) + IF ( ALLOCATED( DistU ) ) DEALLOCATE( DistU ) + IF ( ALLOCATED( DistZMExp ) ) DEALLOCATE( DistZMExp ) + END SUBROUTINE Cleanup +!............................................ +END SUBROUTINE CalcFourierCoeffs_General +!======================================================================= +!> This subroutine returns the complex Fourier coefficients (packed in a +!! real array) of the simulated velocity (wind/water speed). +!! It returns the values FOR ONLY the velocity components that use identity +!! spatial coherence; i.e., for i where SCMod(i) == CohMod_NONE +SUBROUTINE CalcFourierCoeffs_NONE( p, U, PhaseAngles, S, V, TRH, ErrStat, ErrMsg ) + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< TurbSim parameters +REAL(ReKi), INTENT(IN) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), INTENT(IN) :: PhaseAngles (:,:,:) !< The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(IN) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: TRH (:) !< The transfer function matrix. just used as a work array +INTEGER(IntKi), INTENT(OUT) :: ErrStat +CHARACTER(*), INTENT(OUT) :: ErrMsg + + + ! Internal variables +INTEGER :: IFreq +INTEGER :: IVec ! wind component, 1=u, 2=v, 3=w + + + ErrStat = ErrID_None + ErrMsg = "" + + !-------------------------------------------------------------------------------- + ! Calculate the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IVec = 1,3 + + IF (p%met%SCMod(IVec) /= CohMod_NONE) CYCLE ! Check the next component (this one doesn't use the identity coherence method) + + V(:,:,IVec) = 0.0_ReKi + + CALL WrScr ( ' '//Comp(IVec)//'-component matrices (identity coherence)' ) + + + ! now calculate coherence for compents that use this method + + ! ----------------------------------------------------------------------------------- + ! The coherence is the Identity (as is Cholesky Factorization); + ! the Veers' H matrix calculated in EyeCoh2H: + ! ----------------------------------------------------------------------------------- + + DO IFREQ = 1,p%grid%NumFreq + CALL EyeCoh2H( IVec, IFreq, TRH, S, p%grid%NPoints ) + CALL H2Coeffs( IVec, IFreq, TRH, PhaseAngles, V, p%grid%NPoints ) + ENDDO !IFreq + + END DO ! IVec + + RETURN +!............................................ +END SUBROUTINE CalcFourierCoeffs_NONE +!======================================================================= +!> This subroutine computes the coherence between two points on the grid, +!! forms the cross spectrum matrix, and returns the complex +!! Fourier coefficients of the simulated velocity (wind speed). +SUBROUTINE CalcFourierCoeffs( p, U, PhaseAngles, S, V, ErrStat, ErrMsg ) + +IMPLICIT NONE + + ! Passed variables + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< TurbSim parameters +REAL(ReKi), INTENT(in) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), INTENT(IN) :: PhaseAngles (:,:,:) !< The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(IN) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), INTENT( OUT) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). +INTEGER(IntKi), INTENT(OUT) :: ErrStat +CHARACTER(*), INTENT(OUT) :: ErrMsg + + ! Internal variables + +REAL(ReKi), ALLOCATABLE :: TRH (:) ! The transfer function matrix. +INTEGER(IntKi) :: ErrStat2 +CHARACTER(MaxMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! with no turbulence, we return all zeros + IF (p%met%TurbModel_ID == SpecModel_NONE) THEN + V = 0.0_ReKi + RETURN + END IF + + ! otherwise, we use the coherence method specified by the user + + CALL AllocAry( TRH, p%grid%NPacked, 'TRH coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL CalcFourierCoeffs_IEC( p, U, PhaseAngles, S, V, TRH, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs') + CALL CalcFourierCoeffs_API( p, U, PhaseAngles, S, V, TRH, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs') + CALL CalcFourierCoeffs_General( p, U, PhaseAngles, S, V, TRH, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs') + CALL CalcFourierCoeffs_NONE( p, U, PhaseAngles, S, V, TRH, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs') + + CALL Cleanup() + RETURN +!............................................ +CONTAINS + SUBROUTINE Cleanup() + IF ( ALLOCATED( TRH ) ) DEALLOCATE( TRH ) + END SUBROUTINE Cleanup +!............................................ +END SUBROUTINE CalcFourierCoeffs + +!======================================================================= +!> This subroutine returns the complex Fourier coefficients (packed in a +!! real array) of the simulated velocity (wind/water speed). It returns +!! values FOR ONLY the velocity components that use the API method for +!! computing spatial coherence; i.e., for i where SCMod(i) == CohMod_API +SUBROUTINE CalcFourierCoeffs_API( p, U, PhaseAngles, S, V, TRH, ErrStat, ErrMsg ) + +IMPLICIT NONE + + ! Passed variables +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< TurbSim parameters +REAL(ReKi), INTENT(IN ) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), INTENT(IN ) :: PhaseAngles (:,:,:) !< The array that holds the phase angles [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(IN ) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: V (:,:,:) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), INTENT(INOUT) :: TRH (:) !< The transfer function matrix. just used as a work array +INTEGER(IntKi), INTENT( OUT) :: ErrStat +CHARACTER(*), INTENT( OUT) :: ErrMsg + + ! Internal variables + +REAL(ReKi), ALLOCATABLE :: Dist_Y(:) ! The Y distance between points +REAL(ReKi), ALLOCATABLE :: Dist_Z(:) ! The Z distance between points +REAL(ReKi), ALLOCATABLE :: z_g(:) ! sqrt( Z(IZ)*Z(JZ) ) / H + +INTEGER :: J +INTEGER :: I +INTEGER :: K +INTEGER :: IFreq +INTEGER :: Indx +INTEGER :: IVec ! wind component, 1=u, 2=v, 3=w + +INTEGER :: UC ! I/O unit for Coherence debugging file. +LOGICAL, PARAMETER :: COH_OUT = .FALSE. ! This parameter has been added to replace the NON-STANDARD compiler directive previously used + +INTEGER(IntKi) :: ErrStat2 +CHARACTER(MaxMsgLen) :: ErrMsg2 + +REAL, PARAMETER :: Qc(3) = (/ 1.00, 1.00, 1.25 /) +REAL, PARAMETER :: Pc(3) = (/ 0.40, 0.40, 0.50 /) +REAL, PARAMETER :: Rc(3) = (/ 0.92, 0.92, 0.85 /) +REAL, PARAMETER :: Alpha(3) = (/ 2.9 ,45.0 ,13.0 /) + +REAL, PARAMETER :: H = 10. ! Reference height +REAL, PARAMETER :: Coef_1 = 1.0 !3.28 + +REAL :: A_Y, A_Z + + + ! initialize variables + ErrStat = ErrID_None + ErrMsg = "" + UC = -1 + + IF (.NOT. ANY(p%met%SCMod == CohMod_API) ) RETURN + + !-------------------------------------------------------------------------------- + ! allocate arrays + !-------------------------------------------------------------------------------- + + CALL AllocAry( Dist_Y, p%grid%NPacked, 'Dist_Y coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + CALL AllocAry( Dist_Z, p%grid%NPacked, 'Dist_Z coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + !CALL AllocAry( Dist_Z12, p%grid%NPacked, 'Dist_Z12 coherence array', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + CALL AllocAry( z_g, p%grid%NPacked, 'z_g coherence array', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + !-------------------------------------------------------------------------------- + ! Calculate the distances and other parameters that don't change with frequency + !--------------------------------------------------------------------------------- + + Indx=0 + DO J=1,p%grid%NPoints + DO I=J,p%grid%NPoints ! The coherence matrix is symmetric so we're going to skip the other side + Indx = Indx + 1 ! Indx = p%grid%NPoints*(J - 1) - J*(J - 1)/2 + I !Index of packed V matrix, coherence between points I & J + + Dist_Y(Indx)= ABS( p%grid%Y(I) - p%grid%Y(J) ) + Dist_Z(Indx)= ABS( p%grid%Z(I) - p%grid%Z(J) ) + z_g(Indx) = sqrt( p%grid%Z(I) * p%grid%Z(J) ) / H + + END DO + END DO + + + !................. + ! DEBUGGING + !................. +IF ( COH_OUT ) THEN !debugging info... + + ! Write the coherence for three frequencies, for debugging purposes + CALL GetNewUnit( UC, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + + CALL OpenFOutFile( UC, TRIM(p%RootName)//'.coh', ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + WRITE( UC, '(A4,X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'Comp','Freq',(I,I=1,p%grid%NPacked) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'Distance_Y', Dist_Y(:) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'Distance_Z', Dist_Z(:) + WRITE( UC, '(5X,A16,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) 'sqrt(Z(IZ)*Z(JZ))/H', z_g(:) +ENDIF + + !-------------------------------------------------------------------------------- + ! Calculate the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IVec = 1,1 !BJJ: note that only the u component is defined, and I don't want to look at how to change the coherence in the other components.... + + IF (p%met%SCMod(IVec) /= CohMod_API) CYCLE ! Check the next component (this one doesn't use the API method) + + CALL WrScr ( ' '//Comp(IVec)//'-component matrices (2-dimensional API coherence method)' ) + + !-------------------------------------------------------------------------------- + ! Calculate the coherence, Veers' H matrix (CSDs), and the fourier coefficients + !--------------------------------------------------------------------------------- + + DO IFREQ = 1,p%grid%NumFreq + ! ----------------------------------------------- + ! Create the coherence matrix for this frequency + ! ----------------------------------------------- + + Indx = 1 + DO J = 1,p%usr%NPoints-1 ! start with user-defined points (which don't get added coherence) + + TRH(Indx) = 1.0_ReKi + Indx = Indx + 1 + + DO I=J+1,p%grid%NPoints + TRH(Indx) = 0.0_ReKi + Indx = Indx + 1 + END DO !I + + END DO !J + + DO J=max(1, p%usr%NPoints),p%grid%NPoints + DO I=J,p%grid%NPoints + +!mlb: THis is where to look for the error. + +!mlb TEMP_Y=Coef_AlphaY*p%grid%Freq(IFreq)**Coef_RY*(Dist_Y(Indx)/Coef_1)**Coef_QY*(Dist_Z12(Indx)/Coef_2)**(-0.5*Coef_PY) +!mlb TEMP_Z=Coef_AlphaZ*p%grid%Freq(IFreq)**Coef_RZ*(Dist_Z(Indx)/Coef_1)**Coef_QZ*(Dist_Z12(Indx)/Coef_2)**(-0.5*Coef_PZ) + +!dist_x is zero, so we ignore it here (i.e., A_X = 0) + A_Y = Alpha(2) * (p%grid%Freq(IFreq)**rc(2)) * ((Dist_Y(Indx)/Coef_1)**qc(2)) * (z_g(Indx)**(-pc(2))) + A_Z = Alpha(3) * (p%grid%Freq(IFreq)**rc(3)) * ((Dist_Z(Indx)/Coef_1)**qc(3)) * (z_g(Indx)**(-pc(3))) + +!mlb TRH(Indx)=EXP(-Coef_1*SQRT(TEMP_Y**2+TEMP_Z**2)/U0_1HR) + TRH(Indx)=EXP(- Coef_1 * SQRT(A_Y**2 + A_Z**2) / p%met%URef) + + Indx = Indx + 1 + + ENDDO ! I + ENDDO ! J + + + !................. + ! DEBUGGING + !................. + IF (COH_OUT) THEN + ! IF (IFreq == 1 .OR. IFreq == p%grid%NumFreq) THEN + WRITE( UC, '(I3,2X,F15.5,1X,'//Num2LSTR(p%grid%NPacked)//'(G10.4,1X))' ) IVec, p%grid%Freq(IFreq), TRH(1:p%grid%NPacked) + ! ENDIF + ENDIF + + ! ----------------------------------------------- + ! Now transform coherence to H matrix and then + ! use H matrix to calculate coefficients + ! ----------------------------------------------- + + CALL Coh2H( p, IVec, IFreq, TRH, S, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CalcFourierCoeffs_API') + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + CALL H2Coeffs( IVec, IFreq, TRH, PhaseAngles, V, p%grid%NPoints ) + + ENDDO !IFreq + ENDDO !IVec + + CALL Cleanup() + +RETURN +!............................................ +CONTAINS + SUBROUTINE Cleanup() + + IF (COH_OUT .AND. UC > 0) CLOSE( UC ) + + IF ( ALLOCATED( Dist_Y ) ) DEALLOCATE( Dist_Y ) + IF ( ALLOCATED( Dist_Z ) ) DEALLOCATE( Dist_Z ) + IF ( ALLOCATED( z_g ) ) DEALLOCATE( z_g ) + END SUBROUTINE Cleanup +!............................................ +END SUBROUTINE CalcFourierCoeffs_API +!======================================================================= +SUBROUTINE EyeCoh2H( IVec, IFreq, TRH, S, NPoints ) + +REAL(ReKi), INTENT(INOUT) :: TRH (:) ! The transfer function matrix (length is >= p%grid%NPacked). +REAL(ReKi), INTENT(IN) :: S (:,:,:) ! The turbulence PSD array (NumFreq,NPoints,3). +INTEGER(IntKi), INTENT(IN) :: IVec ! loop counter (=number of wind components) +INTEGER(IntKi), INTENT(IN) :: IFreq ! loop counter (=number of frequencies) +INTEGER(IntKi), INTENT(IN) :: NPoints ! Size of dimension 2 of S + +integer :: Indx, J, I + +!NPoints = SIZE(S,2) + + ! ----------------------------------------------------------------------------------- + ! The coherence is the Identity (as is Cholesky); the Veers' H matrix is as follows: + ! ----------------------------------------------------------------------------------- + + Indx = 1 + DO J = 1,NPoints ! The column number + + ! The diagonal entries of the matrix: + + TRH(Indx) = SQRT( ABS( S(IFreq,J,IVec) ) ) + + ! The off-diagonal values: + Indx = Indx + 1 + DO I = J+1,NPoints ! The row number + TRH(Indx) = 0.0 + Indx = Indx + 1 + ENDDO ! I + ENDDO ! J + +END SUBROUTINE EyeCoh2H +!======================================================================= +SUBROUTINE Coh2H( p, IVec, IFreq, TRH, S, ErrStat, ErrMsg ) + +!use NWTC_LAPACK + +TYPE(TurbSim_ParameterType), INTENT(IN ) :: p ! TurbSim parameters +REAL(ReKi), INTENT(INOUT) :: TRH (:) ! The transfer function matrix (size >= NumSteps). +REAL(ReKi), INTENT(IN) :: S (:,:,:) ! The turbulence PSD array (NumFreq,NPoints,3). +INTEGER(IntKi), INTENT(IN) :: IVec ! loop counter (=number of wind components) +INTEGER(IntKi), INTENT(IN) :: IFreq ! loop counter (=number of frequencies) + +INTEGER(IntKi), INTENT(OUT) :: ErrStat +CHARACTER(*), INTENT(OUT) :: ErrMsg + + +integer :: Indx, J, I, NPts + + + ! ------------------------------------------------------------- + ! Calculate the Cholesky factorization for the coherence matrix + ! ------------------------------------------------------------- + IF ( p%usr%NPoints > 0 ) THEN + J = p%usr%NPoints + Indx = p%grid%NPoints*(J-1) - J*(J-1)/2 + J !Index of H(J,J) + NPts = p%grid%NPoints - p%usr%NPoints + 1 + ELSE + Indx = 1 + NPts = p%grid%NPoints + END IF + + CALL LAPACK_pptrf( 'L', NPts, TRH(Indx:), ErrStat, ErrMsg ) ! 'L'ower triangular 'TRH' matrix (packed form), of order 'NPoints'; returns Stat + + IF ( ErrStat /= ErrID_None ) THEN + IF (ErrStat < AbortErrLev) then + CALL WrScr(ErrMsg) + ELSE + ErrMsg = 'Error in Cholesky factorization: '//TRIM(ErrMsg)//newline//& + 'The error occurred in the '//Comp(IVec)//'-component coherence matrix at frequency '//& + TRIM(Int2LStr(IFreq))//' ('//TRIM(Num2LStr(p%grid%Freq(IFreq)))//' Hz)'//& + ' Check the input file for invalid physical properties or modify the coherence.' + RETURN + + END IF + ENDIF + + ! ------------------------------------------------------------- + ! Create the lower triangular matrix, H, from Veer's method + ! ------------------------------------------------------------- + + Indx = 1 + DO J = 1,p%usr%NPoints-1 ! Column + ! use identity coherence for the user-input time series: + + !Indx = p%grid%NPoints*(J-1) - J*(J-1)/2 + J !Index of H(J,J) + + TRH(Indx) = SQRT( ABS( S(IFreq,J,IVec) ) ) + Indx = Indx + 1 + + DO I=J+1,p%grid%NPoints + TRH(Indx) = 0.0_ReKi + Indx = Indx + 1 + END DO + + END DO !J + + DO J = max(1,p%usr%NPoints),p%grid%NPoints ! Column + + TRH(Indx) = TRH(Indx) * SQRT( ABS( S(IFreq,J,IVec) ) ) + Indx = Indx + 1 + + DO I = J+1,p%grid%NPoints ! Row + + ! S(IFreq,I,IVec) should never be less than zero, but the ABS makes sure... + !Indx = NPoints*(J-1) - J*(J-1)/2 + I !Index of H(I,J) + +! TRH(Indx) = TRH(Indx) * SQRT( ABS( S(IFreq,I,IVec) ) ) + TRH(Indx) = TRH(Indx) * SQRT( SQRT( ABS( S(IFreq,I,IVec) * S(IFreq,J,IVec) ) ) ) + + Indx = Indx + 1 + + ENDDO !I + ENDDO !J + + +END SUBROUTINE Coh2H +!======================================================================= +SUBROUTINE H2Coeffs( IVec, IFreq, TRH, PhaseAngles, V, NPoints ) + + +REAL(ReKi), INTENT(IN) :: TRH (:) ! The transfer function matrix (length is >= p%grid%NPacked). +REAL(ReKi), INTENT(IN) :: PhaseAngles (:,:,:) ! The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), INTENT(INOUT) :: V (:,:,:) ! An array containing the summations of the rows of H (NumSteps,NPoints,3). +INTEGER(IntKi), INTENT(IN) :: IVec ! loop counter (=number of wind components) +INTEGER(IntKi), INTENT(IN) :: IFreq ! loop counter (=number of frequencies) +INTEGER(IntKi), INTENT(IN) :: NPoints ! Size of dimension 2 of V + + +REAL(ReKi) :: CPh ! Cosine of the random phase +REAL(ReKi) :: SPh ! Sine of the random phase +INTEGER :: IF1 ! Index to real part of vector +INTEGER :: IF2 ! Index to complex part of vector + +integer :: Indx, J, I + + + ! ------------------------------------------------------------- + ! Calculate the correlated fourier coefficients. + ! ------------------------------------------------------------- + + IF2 = IFreq*2 + IF1 = IF2 - 1 + + DO J=1,NPoints + + ! Apply a random phase to each of the columns of H to + ! produce random phases in the wind component. + ! Then sum each of the rows into the vector V. + + CPh = COS( PhaseAngles(J,IFreq,IVec) ) + SPh = SIN( PhaseAngles(J,IFreq,IVec) ) + + Indx = NPoints*(J-1) - J*(J-1)/2 + J !Index of H(J,J) + DO I=J,NPoints + + V(IF1,I,IVec) = V(IF1,I,IVec) + TRH(Indx)*CPh !Real part + V(IF2,I,IVec) = V(IF2,I,IVec) + TRH(Indx)*SPh !Imaginary part + + Indx = Indx + 1 !H(I,J) + + ENDDO ! I + ENDDO ! J + +END SUBROUTINE H2Coeffs +!======================================================================= +!> This routine takes the Fourier coefficients and converts them to velocity +!! note that the resulting time series has zero mean. +SUBROUTINE Coeffs2TimeSeries( V, NumSteps, NPoints, NUsrPoints, ErrStat, ErrMsg ) + + + !USE NWTC_FFTPACK + + IMPLICIT NONE + + + ! passed variables + INTEGER(IntKi), INTENT(IN) :: NumSteps !< Size of dimension 1 of V (number of time steps) + INTEGER(IntKi), INTENT(IN) :: NPoints !< Size of dimension 2 of V (number of grid points) + INTEGER(IntKi), INTENT(IN) :: NUsrPoints !< number of user-defined time series + + REAL(ReKi), INTENT(INOUT) :: V (NumSteps,NPoints,3) !< An array containing the summations of the rows of H (NumSteps,NPoints,3). + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ! local variables + TYPE(FFT_DataType) :: FFT_Data ! data for applying FFT + REAL(SiKi), ALLOCATABLE :: Work ( : ) ! working array to hold coefficients of fft !bjj: made it allocatable so it doesn't take stack space + + + INTEGER(IntKi) :: ITime ! loop counter for time step/frequency + INTEGER(IntKi) :: IVec ! loop counter for velocity components + INTEGER(IntKi) :: IPoint ! loop counter for grid points + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + !CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + + + ! initialize variables + + !ErrStat = ErrID_None + !ErrMsg = "" + + CALL AllocAry(Work, NumSteps, 'Work',ErrStat,ErrMsg) + if (ErrStat >= AbortErrLev) return + + ! Allocate the FFT working storage and initialize its variables + +CALL InitFFT( NumSteps, FFT_Data, ErrStat=ErrStat2 ) + CALL SetErrStat(ErrStat2, 'Error in InitFFT', ErrStat, ErrMsg, 'Coeffs2TimeSeries' ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + ! Get the stationary-point time series. + +CALL WrScr ( ' Generating time series for all points:' ) + +DO IVec=1,3 + + CALL WrScr ( ' '//Comp(IVec)//'-component' ) + + DO IPoint=1,NPoints !NTotB + + ! Overwrite the first point with zero. This sets the real (and + ! imaginary) part of the steady-state value to zero so that we + ! can add in the mean value later. + + Work(1) = 0.0_ReKi + +! DO ITime = 2,NumSteps-1 + DO ITime = 2,NumSteps + Work(ITime) = V(ITime-1, IPoint, IVec) + ENDDO ! ITime + + IF (iPoint > NUsrPoints) THEN + ! BJJ: we can't override this for the user-input spectra or we don't get the correct time series out. + ! Per JMJ, I will keep this here for the other points, but I personally think it could be skipped, too. + + ! Now, let's add a complex zero to the end to set the power in the Nyquist + ! frequency to zero. + + Work(NumSteps) = 0.0 + END IF + + + + ! perform FFT + + CALL ApplyFFT( Work, FFT_Data, ErrStat2 ) + IF (ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat(ErrStat2, 'Error in ApplyFFT for point '//TRIM(Num2LStr(IPoint))//'.', ErrStat, ErrMsg, 'Coeffs2TimeSeries' ) + IF (ErrStat >= AbortErrLev) EXIT + END IF + + V(:,IPoint,IVec) = Work + + ENDDO ! IPoint + +ENDDO ! IVec + +CALL Cleanup() + +RETURN +CONTAINS +!........................................... +SUBROUTINE Cleanup() + + CALL ExitFFT( FFT_Data, ErrStat2 ) + CALL SetErrStat(ErrStat2, 'Error in ExitFFT', ErrStat, ErrMsg, 'Coeffs2TimeSeries' ) + + if (allocated(work)) deallocate(work) + + END SUBROUTINE Cleanup +END SUBROUTINE Coeffs2TimeSeries +!======================================================================= +!> This routine calculates the two-sided Fourier amplitudes of the frequencies +!! note that the resulting time series has zero mean. +SUBROUTINE CalcTargetPSD(p, S, U, ErrStat, ErrMsg) + + TYPE(TurbSim_ParameterType), INTENT(in) :: p !< TurbSim parameters + REAL(ReKi), INTENT(in) :: U (:) !< The steady u-component wind speeds for the grid (NPoints). + REAL(ReKi), INTENT( OUT) :: S (:,:,:) !< The turbulence PSD array (NumFreq,NPoints,3). + + INTEGER(IntKi), INTENT( out) :: ErrStat !< Error level + CHARACTER(*), INTENT( out) :: ErrMsg !< Message describing error + + + ! local variables + + INTEGER(IntKi) :: IFreq ! Index for frequency + INTEGER(IntKi) :: LastIndex(2) ! Index for the last (Freq, Ht) used in models that interpolate/extrapolate user-input spectra or time series + + INTEGER(IntKi) :: IVec ! loop counter for velocity components + INTEGER(IntKi) :: IPoint, iPointUsr ! loop counter for grid points + + REAL(ReKi), ALLOCATABLE :: SSVS (:,:) ! A temporary work array (NumFreq,3) that holds a single-sided velocity spectrum. + REAL(ReKi) :: DUDZ ! The steady u-component wind shear for the grid [used in Hydro models only]. + REAL(ReKi) :: ZTmp, UTmp ! temporary height and velocity used for finite difference calculations + + REAL(ReKi) :: HalfDelF ! half of the delta frequency, used to discretize the continuous PSD at each point + + !INTEGER(IntKi) :: UP ! I/O unit for PSD debugging file. + !CHARACTER(200) :: FormStr ! String used to store format specifiers for PSD debugging. + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + CHARACTER(*), PARAMETER :: RoutineName = 'CalcTargetPSD' + + ! initialize variables + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Allocate the array to hold the single-sided velocity spectrum. + + CALL AllocAry( SSVS, p%grid%NumFreq,3, 'SSVS', ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + + ! Calculate the single point Power Spectral Densities. + + HalfDelF = 0.5*p%grid%Freq(1) + + + SELECT CASE ( p%met%TurbModel_ID ) + CASE ( SpecModel_IECKAI ) ! IECKAI has uniform spectra (does not vary with height or velocity) + CALL Spec_IECKAI ( p%UHub, p%IEC%SigmaIEC, p%IEC%IntegralScale, p%grid%Freq, p%grid%NumFreq, SSVS ) + + DO IVec=1,3 + DO IFreq=1,p%grid%NumFreq + S(IFreq,:,IVec) = SSVS(IFreq,IVec)*HalfDelF + END DO ! IFreq + END DO ! IVec + + + CASE ( SpecModel_IECVKM ) ! IECVKM has uniform spectra (does not vary with height or velocity) + CALL Spec_IECVKM ( p%UHub, p%IEC%SigmaIEC(1), p%IEC%IntegralScale, p%grid%Freq, p%grid%NumFreq, SSVS ) + + DO IVec=1,3 + DO IFreq=1,p%grid%NumFreq + S(IFreq,:,IVec) = SSVS(IFreq,IVec)*HalfDelF + END DO ! IFreq + END DO ! IVec + + + CASE ( SpecModel_API ) + DO IPoint=1,p%grid%NPoints + CALL Spec_API ( p, p%grid%Z(IPoint), SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_GP_LLJ ) + IF ( ALLOCATED( p%met%ZL_profile ) ) THEN !.AND. ALLOCATED( p%met%Ustar_profile ) ) THEN + DO IPoint=1,p%grid%NPoints + CALL Spec_GPLLJ ( p, p%grid%Z(IPoint), U(IPoint), p%met%ZL_profile(IPoint), p%met%Ustar_profile(IPoint), SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + ELSE + DO IPoint=1,p%grid%NPoints + CALL Spec_GPLLJ ( p, p%grid%Z(IPoint), U(IPoint), p%met%ZL, p%met%Ustar, SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + ENDIF + + + CASE (SpecModel_NWTCUP) + DO IPoint=1,p%grid%NPoints + CALL Spec_NWTCUP ( p, p%grid%Z(IPoint), U(IPoint), SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_SMOOTH ) + DO IPoint=1,p%grid%NPoints + CALL Spec_SMOOTH ( P, p%grid%Z(IPoint), U(IPoint), SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_TIDAL, SpecModel_RIVER ) + DO IPoint=1,p%grid%NPoints + ZTmp = p%grid%Z(IPoint) + p%grid%GridRes_Z + + CALL getVelocity(p, p%UHub,p%grid%HubHt, ZTmp, UTmp, ErrStat2, ErrMsg2) !get velocity Utmp at height ZTmp + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + DUDZ = ( UTmp - U(IPoint) ) / p%grid%GridRes_Z + CALL Spec_TIDAL ( p, p%grid%Z(IPoint), DUDZ, SSVS, p%met%TurbModel_ID ) + + ! Discretize the continuous PSD and store it in matrix "S" + + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_USER ) ! currently is uniform spectra + CALL Spec_UserSpec ( p, SSVS ) + + DO IVec=1,3 + DO IFreq=1,p%grid%NumFreq + S(IFreq,:,IVec) = SSVS(IFreq,IVec)*HalfDelF + END DO ! IFreq + END DO ! IVec + + + CASE ( SpecModel_TimeSer ) + + DO iPointUsr = 1,p%usr%NPoints + + iPoint = iPointUsr + IF (iPointUsr == p%usr%RefPtID ) THEN + iPoint = p%usr%NPoints !this is the point on the grid + ELSEIF (iPointUsr == p%usr%NPoints) THEN + iPoint = p%usr%RefPtID + END IF + !bjj: make sure size(ssvs,1) = p%grid%NumFreq <= p%usr%nFreq = size(p%usr%S,1) + ! initialize SSVS with extrapolated values if there are non-specified components or frequencies + ! i.e., fill the gaps where wind component or frequencies exceed what was specified in the time-series data with some numerical model + ! (use zeros for known spectral values that will get overwritten later) + CALL Spec_TimeSer_Extrap ( p, p%grid%Z(iPoint), U(iPoint), SSVS ) + + ! overwrite the frequencies and wind components that were computed from measurements in the time-series file + SSVS(1:p%usr%nFreq,1:p%usr%nComp) = p%usr%S(1:p%usr%nFreq,iPointUsr,1:p%usr%nComp) + + S(:,iPoint,:) = SSVS*HalfDelF + END DO + + + DO iPoint=1+p%usr%NPoints,p%grid%NPoints + CALL Spec_TimeSer( p, p%grid%Z(iPoint), U(iPoint), LastIndex, SSVS ) + S(:,iPoint,:) = SSVS*HalfDelF + ENDDO + + CASE ( SpecModel_USRVKM ) + DO iPoint=1,p%grid%NPoints + CALL Spec_vonKrmn ( P, p%grid%Z(iPoint), U(iPoint), SSVS ) + S(:,iPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE (SpecModel_WF_UPW) + DO IPoint=1,p%grid%NPoints + CALL Spec_WF_UPW ( p, p%grid%Z(IPoint), U(IPoint), SSVS ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_WF_07D, SpecModel_WF_14D ) + DO IPoint=1,p%grid%NPoints + CALL Spec_WF_DW ( p, p%grid%Z(IPoint), U(IPoint), SSVS, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + S(:,IPoint,:) = SSVS*HalfDelF + ENDDO + + + CASE ( SpecModel_NONE ) + S = 0.0_ReKi ! whole matrix is zero + !bjj TEST: CALL Spec_Test ( p%grid%Z(IPoint), U(IPoint), SSVS ) + + CASE ( SpecModel_MODVKM ) + IF (MVK) THEN + ! DO IPoint=1,p%grid%NPoints + ! CALL Mod_vKrm( p%grid%Z(IPoint), U(IPoint), SSVS ) + ! S(:,IPoint,:) = SSVS*HalfDelF + ! ENDDO + ELSE + CALL SetErrStat( ErrID_Fatal, 'Specified turbulence PSD, "'//TRIM( p%met%TurbModel )//'", not availible.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + ENDIF + + CASE DEFAULT + CALL SetErrStat( ErrID_Fatal, 'Specified turbulence PSD, "'//TRIM( p%met%TurbModel )//'", not availible.', ErrStat, ErrMsg, RoutineName) + CALL Cleanup() + RETURN + END SELECT + + + !IF (PSD_OUT) THEN + ! UP = -1 + ! CALL GetNewUnit( UP, ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! CALL OpenFOutFile ( UP, TRIM( p%RootName )//'.psd', ErrStat2, ErrMsg2) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! IF (ErrStat >= AbortErrLev) THEN + ! CALL Cleanup() + ! RETURN + ! END IF + ! + ! WRITE (UP,"(A)") 'PSDs ' + ! WRITE (UP, "( A4,'"//TAB//"',A4,"//TRIM( Int2LStr( p%grid%NumFreq ) )//"('"//TAB//"',G10.4) )") 'Comp','Ht', p%grid%Freq(:) + ! FormStr = "( I4,"//TRIM( Int2LStr( p%grid%NumFreq+1 ) )//"('"//TAB//"',G10.4) )" + ! + ! DO IPoint=1,p%grid%NPoints + ! + ! !IF ( ABS(Ht - p%grid%HubHt) < Tolerance ) THEN + ! WRITE( UP, FormStr ) 1, p%grid%Z(IPoint), S(:,IPoint,1)/HalfDelF + ! WRITE( UP, FormStr ) 2, p%grid%Z(IPoint), S(:,IPoint,2)/HalfDelF + ! WRITE( UP, FormStr ) 3, p%grid%Z(IPoint), S(:,IPoint,3)/HalfDelF + ! !ENDIF + ! + ! ENDDO ! IPoint + ! + ! CLOSE( UP ) + !ENDIF + + + CALL Cleanup() + RETURN + +CONTAINS +!.................................... + SUBROUTINE Cleanup() + + !IF ( PSD_OUT .AND. UP > 0) CLOSE( UP ) + + IF ( ALLOCATED( SSVS ) ) DEALLOCATE( SSVS ) + + END SUBROUTINE Cleanup +END SUBROUTINE CalcTargetPSD +!======================================================================= +!> This routine creates the grid (cartesian + other points) that are +!! to be simulated. +SUBROUTINE CreateGrid( p_grid, p_usr, UHub, AddTower, ErrStat, ErrMsg ) + +! Assumes that these variables are set: +! GridHeight +! GridWidth +! NumGrid_Y +! NumGrid_Z + + TYPE(Grid_ParameterType), INTENT(INOUT) :: p_grid + TYPE(UserTSSpec_ParameterType), INTENT(INOUT) :: p_usr + + REAL(ReKi) , INTENT(IN ) :: UHub ! Mean wind speed at hub, used only when usable time is not "ALL" (i.e., periodic flag is false) + LOGICAL , INTENT(INOUT) :: AddTower ! Value of p%WrFile(FileExt_TWR) [determines if tower points should be generarated] + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + ! local variables: + REAL(DbKi) :: DelF ! Delta frequency + INTEGER(IntKi) :: IY, IZ, IFreq ! loop counters + INTEGER(IntKi) :: NTwrPts ! number of extra tower points + INTEGER(IntKi) :: NTwrIndx ! number of tower points to be placed in output file + + INTEGER(IntKi) :: TmpIndex ! temporary index + + INTEGER(IntKi) :: HubIndx_Y ! Index into Y dimension of grid for hub location + INTEGER(IntKi) :: HubIndx_Z ! Index into Z dimension of grid for hub location + + INTEGER(IntKi) :: NumSteps2 ! one-half the number of steps + INTEGER(IntKi) :: iPoint, iPointUsr ! loop counter for points + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + CHARACTER(*), PARAMETER :: RoutineName = 'CreateGrid' + LOGICAL :: GenerateExtraHubPoint + + ErrStat = ErrID_None + ErrMsg = "" + + + !..................................................... + ! First, let's deal with time and frequencies: + !..................................................... + + ! Calculate Total time and NumSteps. + ! Find the product of small factors that is larger than NumSteps (prime #9 = 23). +!bjj: I have no idea why it is necessary to be a factor of 4, so I'm removing it for now: ! Make sure it is a multiple of 2 too. + + IF ( p_grid%Periodic ) THEN + p_grid%NumSteps = CEILING( p_grid%AnalysisTime / p_grid%TimeStep ) + + ! make sure NumSteps is an even number and a product of small primes + NumSteps2 = ( p_grid%NumSteps - 1 )/2 + 1 + p_grid%NumSteps = 2*PSF( NumSteps2 , 9 ) ! >= 2*NumSteps2 = NumSteps + 1 - MOD(NumSteps-1,2) >= NumSteps + !p_grid%NumSteps = PSF( p_grid%NumSteps , 9 ) + + p_grid%NumOutSteps = p_grid%NumSteps + ELSE + p_grid%NumOutSteps = CEILING( ( p_grid%UsableTime + p_grid%GridWidth / UHub )/p_grid%TimeStep ) + p_grid%NumSteps = MAX( CEILING( p_grid%AnalysisTime / p_grid%TimeStep ), p_grid%NumOutSteps ) + + ! make sure NumSteps is an even number and a product of small primes +! p_grid%NumSteps = PSF( p_grid%NumSteps , 9 ) ! make sure it's a product of small primes + NumSteps2 = ( p_grid%NumSteps - 1 )/2 + 1 + p_grid%NumSteps = 2*PSF( NumSteps2 , 9 ) ! >= 2*NumSteps2 = NumOutSteps + 1 - MOD(NumOutSteps-1,2) >= NumOutSteps + + END IF + + !IF (p_grid%NumSteps < 2 ) THEN + ! CALL SetErrStat( ErrID_Fatal, 'There must be at least 2 time steps. '//& + ! 'Increase the usable length of the time series or decrease the time step.', ErrStat, ErrMsg, RoutineName ) + ! RETURN + !END IF + + p_grid%NumFreq = p_grid%NumSteps / 2 + DelF = 1.0_DbKi/( p_grid%NumSteps*p_grid%TimeStep ) + + ! quick check that the frequency contents are the same as the user-input time series. (necessary because we want to keep the exact time series) + IF (p_usr%NPoints > 0) THEN + ! IF ( .NOT. EqualRealNos( DelF, p_usr%f(1) ) .or. .not. EqualRealNos(p_grid%AnalysisTime,p_usr%f(1)*p_usr%NFreq ) .or. p_grid%NumFreq > size(p_usr%f) ) THEN + IF ( .NOT. EqualRealNos( DelF, p_usr%DelF ) ) THEN + CALL SetErrStat(ErrID_Fatal, 'Delta frequency in the user-input time series must be the same as the delta frequency in the simulated series. '//& + 'Change AnalysisTime or number of rows entered in user-defined time series file.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + if ( p_grid%NumFreq > p_usr%nFreq ) then + CALL SetErrStat(ErrID_Fatal, 'Cannot output more frequency values than were entered in user-defined time series file.', ErrStat, ErrMsg,RoutineName) + RETURN + end if + + END IF + + + CALL AllocAry( p_grid%Freq, p_grid%NumFreq, 'Freq (frequency array)', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + DO IFreq=1,p_grid%NumFreq + p_grid%Freq(IFreq) = IFreq*DelF + ENDDO + + + !..................................................... + ! Now, figure out the points in space: + ! 1) user-specified time-series points + ! 2) regularly spaced y-z grid + ! 3) hub point + ! 4) lollipop-stick tower points + !..................................................... + + ! start by determining how many points will be in the output files + ! (1) the full-field grid: + p_grid%GridRes_Y = p_grid%GridWidth / REAL( p_grid%NumGrid_Y - 1, ReKi ) + p_grid%GridRes_Z = p_grid%GridHeight / REAL( p_grid%NumGrid_Z - 1, ReKi ) + + p_grid%Zbottom = p_grid%HubHt + 0.5*p_grid%RotorDiameter ! height of the highest grid points + p_grid%Zbottom = p_grid%Zbottom - p_grid%GridRes_Z * REAL(p_grid%NumGrid_Z - 1, ReKi) ! height of the lowest grid points + + IF ( p_grid%Zbottom <= 0.0_ReKi ) THEN + CALL SetErrStat(ErrID_Fatal,'The lowest grid point ('//TRIM(Num2LStr(p_grid%Zbottom))// ' m) must be above the ground. '//& + 'Adjust the appropriate values in the input file.',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + + + ! (2) the tower points: + IF ( AddTower ) THEN + + IF ( MOD(p_grid%NumGrid_Y, 2) == 0 ) THEN + p_grid%ExtraTwrPT = .TRUE. + ELSE + p_grid%ExtraTwrPT = .FALSE. + END IF + + ! Compute the number of points between the bottom of the grid and the ground + ! ( but we don't want to be on the ground, just more than "Tolerance" from it ) + + NTwrPts = INT( ( p_grid%Zbottom - Tolerance ) / p_grid%GridRes_Z ) + NTwrIndx = NTwrPts + 1 + + IF ( NTwrPts < 1 ) THEN + CALL SetErrStat(ErrID_Warn, ' There are no extra tower data points below the grid. Tower output will be turned off.',ErrStat,ErrMsg,RoutineName) + AddTower = .FALSE. ! bjj: change this so it doesn't actually modify this variable inside this routine??? + NTwrPts = 0 + NTwrIndx = 0 + ENDIF + + IF ( p_grid%ExtraTwrPT ) THEN + NTwrPts = NTwrPts + 1 ! Let's add the point on the bottom of the grid so tower interpolation is easier in AeroDyn + ENDIF + + ELSE + NTwrPts = 0 + NTwrIndx = 0 + ENDIF + + ! we will set these index arrays to point to the grid/tower points or user-specified points + CALL AllocAry(p_grid%GridPtIndx,p_grid%NumGrid_Y*p_grid%NumGrid_Z, 'GridPtIndx', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p_grid%TwrPtIndx, NTwrIndx, 'TwrPtIndx', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + + !............... + ! Now, let's see how many points we're going to simulate + !.............. + + ! here's our first estimate of how many points there will be. Later we will add a point for the hub if + ! necessary and subtract points from the grid or tower that are duplicates of the user-specified ones. + p_grid%NPoints = p_usr%NPoints & ! (1) the user-specified time-series points + + p_grid%NumGrid_Y*p_grid%NumGrid_Z & ! (2) the rectangular grid + + NTwrPts ! (4) the tower points (the stick of the lollipop) + + ! Check if any of the user-specified time-series points are duplicated elsewhere: + p_grid%GridPtIndx = 0 + p_grid%TwrPtIndx = 0 + + ! (2) the rectangular grid: + DO iPointUsr = 1,p_usr%NPoints + + iPoint = iPointUsr + IF (iPointUsr == p_usr%RefPtID ) THEN + iPoint = p_usr%NPoints + ELSEIF (iPointUsr == p_usr%NPoints) THEN + iPoint = p_usr%RefPtID + END IF + + ! Is this point on the regularly-spaced grid? + TmpIndex = IndexOnGrid( p_grid, p_usr%pointyi(iPointUsr), p_usr%pointzi(iPointUsr) ) + + IF ( TmpIndex > 0 ) THEN + p_grid%GridPtIndx( TmpIndex ) = iPoint + ! it's a duplicate of a point on the rectangular grid, so subtract one from NPoints: + p_grid%NPoints = p_grid%NPoints - 1 + ELSE + ! Is this point on the tower? + IF ( NTwrPts > 0 ) THEN + TmpIndex = IndexOnTower( p_grid, p_usr%pointyi(iPointUsr), p_usr%pointzi(iPointUsr) ) + + IF ( TmpIndex > 0 ) THEN + p_grid%TwrPtIndx( TmpIndex ) = iPoint + + ! it's a duplicate of a tower point, so subtract one from NPoints: + p_grid%NPoints = p_grid%NPoints - 1 + END IF + END IF ! NTwrPts > 0 + + END IF + + END DO + + + ! (3) the hub point: + + IF ( MOD(p_grid%NumGrid_Y, 2) == 0 ) THEN + + p_grid%HubOnGrid = .FALSE. + + ELSE + ! This is the hub Z index if it falls on the grid + HubIndx_Z = INT( Tolerance + ( p_grid%HubHt - p_grid%Zbottom ) / p_grid%GridRes_Z ) + 1 + + IF ( ABS((HubIndx_Z-1)*p_grid%GridRes_Z + p_grid%Zbottom - p_grid%HubHt) > Tolerance ) THEN + p_grid%HubOnGrid = .FALSE. + ELSE + p_grid%HubOnGrid = .TRUE. + END IF + + END IF + + p_grid%HubIndx = 0 + IF ( .NOT. p_grid%HubOnGrid ) THEN + GenerateExtraHubPoint = .TRUE. + ! Is it a user-defined point? + DO iPointUsr = 1,p_usr%NPoints + + IF ( EqualRealNos( p_usr%pointyi(iPointUsr), 0.0_ReKi ) .AND. EqualRealNos( p_usr%pointzi(iPointUsr), p_grid%HubHt ) ) THEN + + IF (iPointUsr == p_usr%RefPtID ) THEN + iPoint = p_usr%NPoints + ELSEIF (iPointUsr == p_usr%NPoints) THEN + iPoint = p_usr%RefPtID + ELSE + iPoint = iPointUsr + END IF + + p_grid%HubIndx = iPoint + GenerateExtraHubPoint = .FALSE. + EXIT ! we found it + END IF + END DO + ELSE + GenerateExtraHubPoint = .FALSE. + END IF + + IF (GenerateExtraHubPoint) p_grid%NPoints = p_grid%NPoints + 1 + + p_grid%NPacked = p_grid%NPoints*( p_grid%NPoints + 1 )/2 ! number of entries stored in the packed version of the symmetric matrix of size NPoints by NPoints + + + ! we now know how many points there are going to be, so let's create the arrays that contains their locations and finish updating our index arrays + + CALL AllocAry(p_grid%Y, p_grid%NPoints, 'Y (lateral locations of the grid points)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p_grid%Z, p_grid%NPoints, 'Z (vertical locations of the grid points)', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + ! (1) User-defined points + DO iPointUsr = 1,p_usr%NPoints + + iPoint = iPointUsr + IF (iPointUsr == p_usr%RefPtID ) THEN + iPoint = p_usr%NPoints + ELSEIF (iPointUsr == p_usr%NPoints) THEN + iPoint = p_usr%RefPtID + END IF + + p_grid%y(iPoint) = p_usr%pointyi(iPointUsr) + p_grid%z(iPoint) = p_usr%pointzi(iPointUsr) + END DO + + + ! (2) rectangular y-z grid: + iPoint = p_usr%NPoints + DO IZ = 1,p_grid%NumGrid_Z + DO IY = 1,p_grid%NumGrid_Y + + TmpIndex = (IZ-1)*p_grid%NumGrid_Y + IY + + IF ( p_grid%GridPtIndx(TmpIndex) < 1 ) THEN ! we didn't find this grid point in the set of user-defined points, so create a new point + iPoint = iPoint + 1 + + p_grid%Y(iPoint) = -0.5*p_grid%GridWidth + p_grid%GridRes_Y*( IY - 1 ) + p_grid%Z(iPoint) = p_grid%Zbottom + p_grid%GridRes_Z*( IZ - 1 ) + p_grid%GridPtIndx(TmpIndex) = iPoint + END IF + + END DO + END DO + + ! note: GridPtIndx should be completely set now. + + ! (3) hub point: + + IF ( p_grid%HubOnGrid ) THEN + + HubIndx_Y = INT( ( p_grid%NumGrid_Y + 1 ) / 2 ) ! the center point + p_grid%HubIndx = p_grid%GridPtIndx( p_grid%NumGrid_Y*( HubIndx_Z - 1 ) + HubIndx_Y ) + + ELSEIF ( GenerateExtraHubPoint ) THEN + iPoint = iPoint + 1 + + p_grid%Y(iPoint) = 0.0_ReKi + p_grid%Z(iPoint) = p_grid%HubHt + p_grid%HubIndx = iPoint + + ! ELSE -> HubIndx is set already + ENDIF + + + ! (4) Finally, let's deal with the tower "lollipop" points: + + IF ( AddTower ) THEN !p%WrFile(FileExt_TWR) + + IF ( .NOT. p_grid%ExtraTwrPT ) THEN + p_grid%TwrPtIndx(1) = p_grid%GridPtIndx( INT(p_grid%NumGrid_Y / 2) + 1 ) ! center y location on bottom height + END IF + + + DO IZ = 1,NTwrIndx + IF ( p_grid%TwrPtIndx(IZ) < 1 ) THEN + iPoint = iPoint + 1 + + p_grid%Y(iPoint) = 0.0_ReKi + p_grid%Z(iPoint) = p_grid%ZBottom - (IZ-1)*p_grid%GridRes_Z + p_grid%TwrPtIndx(IZ) = iPoint + + END IF + END DO + + ENDIF + +END SUBROUTINE CreateGrid +!======================================================================= +!> This routine determines if a point at location (y,z) is +!! on the regularly-spaced y-z grid. If it does, it returns the +!! index of the point on the grid. If it does not, it returns -1. +FUNCTION IndexOnGrid( p_grid, y, z ) + + TYPE(Grid_ParameterType), INTENT(IN) :: p_grid !< grid parameters + REAL(ReKi), INTENT(IN) :: y !< y position of point we're querying + REAL(ReKi), INTENT(IN) :: z !< z position of point we're querying + + INTEGER(IntKi) :: IndexOnGrid !< Index on regularly spaced grid + + ! local variables + INTEGER(IntKi) :: YIndx ! Index on regularly spaced grid + INTEGER(IntKi) :: ZIndx ! Index on regularly spaced grid + REAL(ReKi) :: y1 ! left-most location on grid + + + y1 = -0.5_ReKi * p_grid%GridWidth + + ZIndx = INT( Tolerance + ( z - p_grid%Zbottom ) / p_grid%GridRes_Z ) + 1 + + IF ( .NOT. EqualRealNos( p_grid%Zbottom + (ZIndx-1)*p_grid%GridRes_Z , z) ) THEN + IndexOnGrid = -1 + RETURN + END IF + + + + YIndx = INT( Tolerance + ( y - y1 ) / p_grid%GridRes_Y ) + 1 + + IF ( .NOT. EqualRealNos( y1 + (YIndx-1)*p_grid%GridRes_Y , y) ) THEN + IndexOnGrid = -1 + RETURN + END IF + + IF ( YIndx < 1 .OR. YIndx > p_grid%NumGrid_Y .OR. & + ZIndx < 1 .OR. ZIndx > p_grid%NumGrid_Z ) THEN + IndexOnGrid = -1 + RETURN + END IF + + + IndexOnGrid = (ZIndx-1)*p_grid%NumGrid_Y + YIndx + +END FUNCTION IndexOnGrid +!======================================================================= +!> This routine determines if a point at location (y,z) is +!! on the regularly-spaced y-z grid. If it does, it returns the +!! index of the point on the grid. If it does not, it returns -1. +FUNCTION IndexOnTower( p_grid, y, z ) + + TYPE(Grid_ParameterType), INTENT(IN) :: p_grid !< grid parameters + REAL(ReKi), INTENT(IN) :: y !< y position of point we're querying + REAL(ReKi), INTENT(IN) :: z !< z position of point we're querying + + INTEGER(IntKi) :: IndexOnTower !< Index on regularly spaced tower points + + ! local variables + INTEGER(IntKi) :: ZIndx ! Index on regularly spaced grid + + + IF ( .NOT. EqualRealNos( 0.0_ReKi , y) ) THEN + IndexOnTower = -1 + RETURN + END IF + + ZIndx = INT( Tolerance + ( p_grid%Zbottom - z ) / p_grid%GridRes_Z ) + 1 + + IF ( zIndx < 0 .OR. .NOT. EqualRealNos( p_grid%Zbottom - (ZIndx-1)*p_grid%GridRes_Z , z) ) THEN + IndexOnTower = -1 + RETURN + END IF + + IndexOnTower = ZIndx + + +END FUNCTION IndexOnTower +!======================================================================= +!> This routine calculates the wind components in the Inertial reference +!! frame. +SUBROUTINE SetPhaseAngles( p, OtherSt_RandNum, PhaseAngles, ErrStat, ErrMsg ) + + + TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< parameters for TurbSim + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum !< other states for random number generation + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< error message + + REAL(ReKi) , INTENT( OUT) :: PhaseAngles(p%grid%NPoints,p%grid%NumFreq,3) !< phases + + ! local variables + INTEGER(IntKi) :: iPoint, iPointUsr ! points that have phases defined already + + + ! generate random phases for all the points + + ! bjj: todo: don't generate the angles for user-specified time-series points, which have phases already + CALL RndPhases(p%RNG, OtherSt_RandNum, PhaseAngles, p%grid%NPoints, p%grid%NumFreq, p%US, ErrStat, ErrMsg) + + + IF (p%met%TurbModel_ID == SpecModel_TimeSer) THEN + + ! note: setting the phase angles this way assumes that p%usr%f(1:p%usr%nFreq) = p%grid%f(1:p%usr%nFreq) [i.e., TMax, AnalysisTime are equal]; + ! however, the simulated time series may have more frequencies and/or smaller time step than the user time-series input file. + DO iPointUsr = 1,p%usr%NPoints + + iPoint = iPointUsr + IF (iPointUsr == p%usr%RefPtID ) THEN + iPoint = p%usr%NPoints + ELSEIF (iPointUsr == p%usr%NPoints) THEN + iPoint = p%usr%RefPtID + END IF + PhaseAngles(iPoint,1:p%usr%nFreq,1:p%usr%nComp) = p%usr%phaseAngles(:,iPointUsr,:) + END DO + + END IF + + ! nyquist frequency must be real, thus phase angle must be 0: + PhaseAngles(:,p%grid%NumFreq,:) = 0.0_ReKi + +END SUBROUTINE SetPhaseAngles +!======================================================================= +!> This routine calculates the wind components in the Inertial reference +!! frame. +SUBROUTINE CalculateWindComponents(v, ubar, HFlowAng, VFlowAng, V_Inertial, UH, UT) + + REAL(ReKi), INTENT(IN) :: v(3) !< u,v,w components (streamwise) + REAL(ReKi), INTENT(IN) :: ubar !< mean streamwise component + REAL(ReKi), INTENT(IN) :: HFlowAng !< horizontal flow angle + REAL(ReKi), INTENT(IN) :: VFlowAng !< vertical flow angle + + REAL(ReKi), INTENT(OUT) :: V_Inertial(3) !< U,V,W components (inertial) + REAL(ReKi), INTENT(OUT),OPTIONAL :: UH !< horizontal wind speed (U+V components) + REAL(ReKi), INTENT(OUT),OPTIONAL :: UT !< total wind speed (U+V+W components) + + + + ! Local variables + REAL(ReKi) :: UTmp ! The instantaneous u-component wind speed at the hub + REAL(ReKi) :: UHTmp2 ! The square of the instantaneous horizontal wind speed at the hub + REAL(ReKi) :: V_Inertial2(3) ! the U,V,W components (inertial) squared + + REAL(ReKi) :: CVFA ! Cosine of the vertical flow angle + REAL(ReKi) :: SVFA ! Sine of the vertical flow angle + REAL(ReKi) :: CHFA ! Cosine of the horizontal flow angle + REAL(ReKi) :: SHFA ! Sine of the horizontal flow angle + + + CHFA = COS( HFlowAng*D2R ) + SHFA = SIN( HFlowAng*D2R ) + + CVFA = COS( VFlowAng*D2R ) + SVFA = SIN( VFlowAng*D2R ) + + + + ! Calculate longitudinal (UTmp) value for point, + ! as well as rotated (V_Inertial) + ! components applying specified flow angles. + + ! Add mean wind speed to the streamwise component + UTmp = v(1) + ubar + + ! Rotate the wind components from streamwise orientation to the X-Y-Z grid + V_Inertial(1) = UTmp*CHFA*CVFA - v(2)*SHFA - v(3)*CHFA*SVFA + V_Inertial(2) = UTmp*SHFA*CVFA + v(2)*CHFA - v(3)*SHFA*SVFA + V_Inertial(3) = UTmp*SVFA + v(3)*CVFA + + IF ( PRESENT( UH ) .OR. PRESENT( UT ) ) THEN + ! Calculate hub horizontal wind speed (UHTmp) and Total wind speed (UTTmp) + + V_Inertial2 = V_Inertial*V_Inertial !inertial frame coordinates + UHTmp2 = V_Inertial2(1) + V_Inertial2(2) !inertial frame coordinates + + IF ( PRESENT( UH ) ) UH = SQRT( UHTmp2 ) !inertial frame coordinates + IF ( PRESENT( UT ) ) UT = SQRT( UHTmp2 + V_Inertial2(3) ) + END IF + +END SUBROUTINE CalculateWindComponents +!======================================================================= +! This routine calculates the instantaneous Reynolds stresses, including TKE and CTKE +SUBROUTINE CalculateStresses(v, uv, uw, vw, TKE, CTKE ) + REAL(ReKi), INTENT(IN) :: v(3) !< u,v,w components (streamwise, zero-mean) + + REAL(ReKi), INTENT(OUT) :: uv !< The instantaneous u'v' Reynolds stress at the hub + REAL(ReKi), INTENT(OUT) :: uw !< The instantaneous u'w' Reynolds stress at the hub + REAL(ReKi), INTENT(OUT) :: vw !< The instantaneous v'w' Reynolds stress at the hub + REAL(ReKi), INTENT(OUT) :: TKE !< The instantaneous TKE at the hub + REAL(ReKi), INTENT(OUT) :: CTKE !< The instantaneous CTKE the hub + + + uv = v(1)*v(2) + uw = v(1)*v(3) + vw = v(2)*v(3) + + TKE = 0.5*(v(1)*v(1) + v(2)*v(2) + v(3)*v(3)) + CTKE = 0.5*SQRT(uv*uv + uw*uw + vw*vw) + +END SUBROUTINE CalculateStresses +!======================================================================= +!> Scale the velocity aligned along the sreamwise direction. +SUBROUTINE ScaleTimeSeries(p, V, ErrStat, ErrMsg) + + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + REAL(ReKi), INTENT(INOUT) :: V(:,:,:) !< velocity, aligned along the streamwise direction without mean values added + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ErrStat = ErrID_None + ErrMsg = "" + + ! Crossfeed cross-axis components to u', v', w' components and scale IEC models if necessary + + SELECT CASE ( p%met%TurbModel_ID ) + !MLB: There does not seem to be a CASE for TurbModel=="API". + + CASE (SpecModel_GP_LLJ, & + SpecModel_NWTCUP, & + SpecModel_SMOOTH, & + SpecModel_WF_UPW, & + SpecModel_WF_07D, & + SpecModel_WF_14D, & + SpecModel_USRVKM, & + SpecModel_TIDAL, & + SpecModel_RIVER, & + SpecModel_USER ) ! Do reynolds stress for HYDRO also. + + + CALL TimeSeriesScaling_ReynoldsStress(p, V, ErrStat, ErrMsg) + + + CASE ( SpecModel_IECKAI , SpecModel_IECVKM ) ! API is considered an IEC model in this code, so it should fall here, if we wanted it + + CALL TimeSeriesScaling_IEC(p, V) + + END SELECT + +END SUBROUTINE ScaleTimeSeries +!======================================================================= +!> This routine scales the time series so that the output has the exact +!! statistics desired. This scaling has the effect of changing the amplitude +!! of the target spectra to account for discretizing the spectra over a +!! finite length of time. +SUBROUTINE TimeSeriesScaling_IEC(p, V) + + + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< TurbSim's parameters + REAL(ReKi), INTENT(INOUT) :: V(:,:,:) !< velocity, aligned along the streamwise direction without mean values added + + + REAL(DbKi) :: CGridSum ! The sums of the velocity components at the points surrounding the hub (or at the hub if it's on the grid) + REAL(DbKi) :: CGridSum2 ! The sums of the squared velocity components at the points surrouding the hub + REAL(ReKi) :: UGridMean ! Average wind speed at a point + REAL(ReKi) :: UGridSig ! Standard deviation of the wind speed at a point + INTEGER(IntKi) :: IT ! loop counter (time) + INTEGER(IntKi) :: Indx ! loop counter (grid point) + INTEGER(IntKi) :: IVec ! loop counter (wind component) + + + REAL(ReKi) :: ActualSigma(3) ! actual standard deviations + REAL(ReKi) :: HubFactor(3) ! factor used to scale standard deviations at the hub point + + IF (p%IEC%ScaleIEC < 1) RETURN + + DO IVec = 1,3 + CGridSum = 0.0 + CGridSum2 = 0.0 + + DO IT=1,p%grid%NumSteps !BJJ: NumOutSteps -- scale to the output value? + CGridSum = CGridSum + V( IT, p%grid%HubIndx, IVec ) + CGridSum2 = CGridSum2 + V( IT, p%grid%HubIndx, IVec )* V( IT, p%grid%HubIndx, IVec ) + ENDDO ! IT + + UGridMean = CGridSum/p%grid%NumSteps !BJJ: NumOutSteps -- scale to the output value? + ActualSigma(IVec) = SQRT( ABS( (CGridSum2/p%grid%NumSteps) - UGridMean*UGridMean ) ) + + + HubFactor(IVec) = p%IEC%SigmaIEC(IVec)/ActualSigma(IVec) ! factor = Target / actual + + IF (p%IEC%ScaleIEC == 1 .OR. p%met%SCMod(IVec) == CohMod_None) THEN ! with no coherence, all points have same std, so we'll save some calculations + + V(:,:,IVec) = HubFactor(IVec) * V(:,:,IVec) + + ELSE ! Scale each point individually + + DO Indx = 1,p%grid%NPoints + CGridSum = 0.0 + CGridSum2 = 0.0 + + DO IT=1,p%grid%NumSteps !BJJ: NumOutSteps -- scale to the output value? + CGridSum = CGridSum + V( IT, Indx, IVec ) + CGridSum2 = CGridSum2 + V( IT, Indx, IVec )* V( IT, Indx, IVec ) + ENDDO ! IT + + UGridMean = CGridSum/p%grid%NumSteps !BJJ: NumOutSteps -- scale to the output value? + UGridSig = SQRT( ABS( (CGridSum2/p%grid%NumSteps) - UGridMean*UGridMean ) ) + + V(:,Indx,IVec) = (p%IEC%SigmaIEC(IVec) / UGridSig) * V(:,Indx,IVec) + ENDDO ! Indx + + ENDIF + + ENDDO !IVec + + IF (p%US > 0 ) THEN + WRITE( p%US, "(//,'Scaling statistics from the hub grid point:',/)" ) + WRITE( p%US, "(2X,'Component Target Sigma (m/s) Simulated Sigma (m/s) Scaling Factor')" ) + WRITE( p%US, "(2X,'--------- ------------------ --------------------- --------------')" ) + + DO IVec = 1,3 + WRITE( p%US, "(5X,A,7x,f11.3,9x,f12.3,11x,f10.3)") Comp(IVec)//"'", p%IEC%SigmaIEC(IVec), & + ActualSigma(IVec), HubFactor(IVec) + END DO + END IF + + +END SUBROUTINE TimeSeriesScaling_IEC +!======================================================================= +!> This routine performs a linear combination of the uncorrelated zero-mean +!! velocity aligned along the streamwise direction to obtain the desired +!! Reynolds Stress values at the hub. +SUBROUTINE TimeSeriesScaling_ReynoldsStress(p, V, ErrStat, ErrMsg) + + ! passed variables + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(INOUT) :: V(:,:,:) !< velocity, aligned along the streamwise direction without mean values added + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ! local variables + REAL(DbKi) :: UVsum ! The sum of the u'v' Reynolds stress component at the hub + REAL(DbKi) :: UWsum ! The sum of the u'w' Reynolds stress component at the hub + REAL(DbKi) :: VWsum ! The sum of the v'w' Reynolds stress component at the hub + REAL(DbKi) :: UUsum ! The sum of the u'u' Reynolds stress component at the hub + REAL(DbKi) :: VVsum ! The sum of the v'v' Reynolds stress component at the hub + REAL(DbKi) :: WWsum ! The sum of the w'w' Reynolds stress component at the hub + + REAL(ReKi) :: UVmean ! The mean u'v' Reynolds stress component at the hub + REAL(ReKi) :: UWmean ! The mean u'w' Reynolds stress component at the hub + REAL(ReKi) :: VWmean ! The mean v'w' Reynolds stress component at the hub + REAL(ReKi) :: UUmean ! The mean u'u' Reynolds stress component at the hub + !REAL(ReKi) :: VVmean ! The mean v'v' Reynolds stress component at the hub + REAL(ReKi) :: WWmean ! The mean w'w' Reynolds stress component at the hub + + REAL(ReKi) :: alpha_uw ! The coefficient of the u component added to the w component for correlation + REAL(ReKi) :: alpha_uv ! The coefficient of the u component added to the v component for correlation + REAL(ReKi) :: alpha_wv ! The coefficient of the w component added to the v component for correlation + + REAL(ReKi) :: u_indept ! temporary copy of the uncorrelated u component of the velocity + REAL(ReKi) :: v_indept ! temporary copy of the uncorrelated v component of the velocity + REAL(ReKi) :: w_indept ! temporary copy of the uncorrelated w component of the velocity + + + REAL(ReKi) :: INumSteps ! Multiplicative Inverse of the Number of time Steps + + INTEGER(IntKi) :: ITime ! loop counter for time step/frequency + INTEGER(IntKi) :: IPoint ! loop counter for grid points + + + ErrStat = ErrID_None + ErrMsg = "" + + !................... + ! Calculate coefficients for obtaining "correct" Reynold's stresses at the hub + !................... + + ! compute mean values: + UWsum = 0.0_DbKi + UVsum = 0.0_DbKi + VWsum = 0.0_DbKi + UUSum = 0.0_DbKi + VVSum = 0.0_DbKi + WWSum = 0.0_DbKi + + DO ITime = 1,p%grid%NumSteps + UWsum = UWsum + V(ITime,p%grid%HubIndx,1) * V(ITime,p%grid%HubIndx,3) + UVsum = UVsum + V(ITime,p%grid%HubIndx,1) * V(ITime,p%grid%HubIndx,2) + VWsum = VWsum + V(ITime,p%grid%HubIndx,2) * V(ITime,p%grid%HubIndx,3) + UUSum = UUSum + V(ITime,p%grid%HubIndx,1) * V(ITime,p%grid%HubIndx,1) + !VVSum = VVSum + V(ITime,p%grid%HubIndx,2) * V(ITime,p%grid%HubIndx,2) + WWSum = WWSum + V(ITime,p%grid%HubIndx,3) * V(ITime,p%grid%HubIndx,3) + ENDDO + + INumSteps = 1.0/p%grid%NumSteps + + UWmean = UWsum * INumSteps + UVmean = UVsum * INumSteps + VWmean = VWsum * INumSteps + UUmean = UUSum * INumSteps + !VVmean = VVSum * INumSteps + WWmean = WWSum * INumSteps + + !BJJ: this is for v=alpha1, w=alpha2, u=alpha3 using derivation equations + alpha_uw = ( p%met%PC_UW - UWmean ) / UUmean !alpha23 + alpha_wv = ( UUmean*(p%met%PC_VW - VWmean - alpha_uw*UVmean) - p%met%PC_UW*(p%met%PC_UV - UVmean) ) / & !alpha12 + ( UUmean*(WWmean + alpha_uw*UWmean) - UWmean*p%met%PC_UW ) + alpha_uv = ( p%met%PC_UV - UVmean - alpha_wv*UWmean) / UUmean !alpha13 + + + ! if we enter "none" for any of the Reynolds-stress terms, don't scale that component: + IF (p%met%UWskip) alpha_uw = 0.0_ReKi + IF (p%met%UVskip) alpha_uv = 0.0_ReKi + IF (p%met%VWskip) alpha_wv = 0.0_ReKi + + !bjj: I'm implementing limits on the range of values here so that the spectra don't get too + ! out of whack. We'll display a warning in this case. + + IF ( ABS(alpha_uw) > 1.0 .OR. ABS(alpha_uv) > 1.0 .OR. ABS(alpha_wv) > 1.0 ) THEN + ErrStat = ErrID_Info + ErrMsg = "Scaling terms exceed 1.0. Reynolds stresses may be affected." + + alpha_uw = MAX( MIN( alpha_uw, 1.0_ReKi ), -1.0_ReKi ) + alpha_uv = MAX( MIN( alpha_uv, 1.0_ReKi ), -1.0_ReKi ) + alpha_wv = MAX( MIN( alpha_wv, 1.0_ReKi ), -1.0_ReKi ) + + ENDIF + + ! calculate the correlated time series: + + DO IPoint = 1,p%grid%NPoints + DO ITime = 1, p%grid%NumSteps + u_indept = V(ITime,IPoint,1) + v_indept = V(ITime,IPoint,2) + w_indept = V(ITime,IPoint,3) + + ! equation 16 [PC_UW] in TurbSim user's guide v1.50 + V(ITime,IPoint,2) = alpha_uv*u_indept + v_indept + alpha_wv*w_indept + V(ITime,IPoint,3) = alpha_uw*u_indept + w_indept + + ENDDO + ENDDO + + IF ( p%US > 0 ) THEN + + WRITE( p%US, "(//,'Scaling statistics from the hub grid point:',/)" ) + WRITE( p%US, "(3X, 'Cross-Component Scaling Factor')" ) + WRITE( p%US, "(3X, '--------------- --------------')" ) + WRITE( p%US, "(3X,A,2X,E14.5)" ) "u'w' ", alpha_uw + WRITE( p%US, "(3X,A,2X,E14.5)" ) "u'v' ", alpha_uv + WRITE( p%US, "(3X,A,2X,E14.5)" ) "v'w' ", alpha_wv + + END IF + +END SUBROUTINE TimeSeriesScaling_ReynoldsStress +!======================================================================= +SUBROUTINE AddMeanAndRotate(p, V, U, HWindDir, VWindDir) + + ! passed variables + TYPE(TurbSim_ParameterType), INTENT(IN) :: p !< parameters + REAL(ReKi), INTENT(INOUT) :: V(:,:,:) !< velocity, on input: aligned along with the mean velocity without mean values added + !! on output, aligned in the inertial reference frame with mean velocities added + REAL(ReKi), INTENT(IN) :: U (:) !< profile of steady wind speed + REAL(ReKi), INTENT(IN) :: HWindDir(:) !< profile of horizontal wind direction + REAL(ReKi), INTENT(IN) :: VWindDir(:) !< profile of vertical wind direction + + ! local variables + REAL(ReKi) :: v3(3) ! temporary 3-component array containing velocity + INTEGER(IntKi) :: ITime ! loop counter for time step + INTEGER(IntKi) :: IPoint ! loop counter for grid points + + + + + !.............................................................................. + ! Add mean wind to u' components and rotate to inertial reference + ! frame coordinate system + !.............................................................................. + DO IPoint=1,p%grid%Npoints + DO ITime=1,p%grid%NumSteps + + ! Add mean wind speed to the streamwise component and + ! Rotate the wind to the X-Y-Z (inertial) reference frame coordinates: + + v3 = V(ITime,IPoint,:) + CALL CalculateWindComponents( v3, U(IPoint), HWindDir(IPoint), VWindDir(IPoint), V(ITime,IPoint,:) ) + + ENDDO ! ITime + + ENDDO ! IPoint + + +END SUBROUTINE AddMeanAndRotate +!======================================================================= +SUBROUTINE TS_ValidateInput(P, ErrStat, ErrMsg) + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< parameters + + INTEGER(IntKi), intent( out) :: ErrStat ! Error level + CHARACTER(*), intent( out) :: ErrMsg ! Message describing error + + ! local variables + INTEGER(IntKi) :: UnOut ! unit for output files + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) + CHARACTER(*), PARAMETER :: RoutineName = 'TS_ValidateInput' + + +ErrStat = ErrID_None +ErrMsg = "" + + +!BONNIE: UPPER LIMIT ON RICH_NO? +IF ( p%WrFile(FileExt_CTS) ) THEN + + ! models where coherent structures apply: + IF ( p%met%TurbModel_ID == SpecModel_GP_LLJ .OR. & + p%met%TurbModel_ID == SpecModel_NWTCUP .OR. & + p%met%TurbModel_ID == SpecModel_SMOOTH .OR. & + p%met%TurbModel_ID == SpecModel_WF_UPW .OR. & + p%met%TurbModel_ID == SpecModel_WF_07D .OR. & + p%met%TurbModel_ID == SpecModel_WF_14D ) THEN + + IF ( p%met%RICH_NO <= -0.05 ) THEN + CALL SetErrStat( ErrID_Info, 'A coherent turbulence time step file cannot be generated for RICH_NO <= -0.05.', ErrStat, ErrMsg, RoutineName) + p%WrFile(FileExt_CTS) = .FALSE. + ELSEIF ( .NOT. ( p%WrFile(FileExt_BTS) .OR. p%WrFile(FileExt_WND) ) ) THEN + CALL SetErrStat( ErrID_Info, 'AeroDyn Full-Field files(.bts) will be generated along with the coherent turbulence file.', ErrStat, ErrMsg, RoutineName) + p%WrFile(FileExt_BTS) = .TRUE. + ENDIF + + ELSE + CALL SetErrStat( ErrID_Info, 'A coherent turbulence time step file cannot be generated with the '//TRIM(p%met%TurbModel)//' model.', ErrStat, ErrMsg, RoutineName) + p%WrFile(FileExt_CTS) = .FALSE. + END IF + +ENDIF !WrAct + + ! Make sure inputs make sense for API model +IF ( p%met%TurbModel_ID == SpecModel_API ) THEN + IF ( .not. EqualRealNos( p%grid%AnalysisTime, 3600.0_ReKi) ) then ! warn if AnalysisTime isn't 1 hour (which is what we're assuming the URef is defined for) + CALL SetErrStat( ErrID_Warn, 'API model assumes URef is the 1-hour mean wind speed, even though AnalysisTime does not equal 3600 seconds.', ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( p%IEC%ScaleIEC /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'API model does not provide time-series scaling to target standard deviation. Set ScaleIEC = 0.', ErrStat, ErrMsg, RoutineName ) + END IF + + IF ( .NOT. EqualRealNos( p%met%RefHt, 10.0_ReKi ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'API model requires a 10-m reference height. Set RefHt = 10.', ErrStat, ErrMsg, RoutineName ) + END IF + +END IF + + + + ! Warn if EWM is used with incompatible times + +IF ( ( p%IEC%IEC_WindType == IEC_EWM1 .OR. p%IEC%IEC_WindType == IEC_EWM50 .OR. p%IEC%IEC_WindType == IEC_EWM100) .AND. & + ABS( 600.0_ReKi - MAX(p%grid%AnalysisTime,p%grid%UsableTime) ) > 90.0_ReKi ) THEN + CALL SetErrStat( ErrID_Warn, 'The EWM parameters are valid for 10-min simulations only.', ErrStat, ErrMsg, RoutineName) +ENDIF + + + ! Warn if Periodic is used with incompatible settings +IF ( p%grid%Periodic .AND. .NOT. EqualRealNos(p%grid%AnalysisTime, p%grid%UsableTime) ) THEN + CALL SetErrStat( ErrID_Warn, 'Periodic output files will not be generated when AnalysisTime /= UsableTime. Setting Periodic = .FALSE.', ErrStat, ErrMsg, RoutineName) + p%grid%Periodic = .FALSE. +END IF + + + ! Warn if tower points are output but grid is not: +IF ( p%WrFile(FileExt_TWR) .AND. .NOT. ( p%WrFile(FileExt_WND) .OR. p%WrFile(FileExt_BTS)) ) THEN + CALL SetErrStat( ErrID_Info, 'TurbSim .bts file will be generated to contain the tower points.', ErrStat, ErrMsg, RoutineName) + p%WrFile(FileExt_BTS) = .TRUE. +END IF + + + + ! Open appropriate output files. We will open formatted FF files later, if requested. + ! Mention the files in the summary file. + +IF ( ANY (p%WrFile) ) THEN + CALL GetNewUnit( UnOut ) + + WRITE (p%US,"( // 'You have requested that the following file(s) be generated:' / )") +! CALL WrScr1 ( ' You have requested that the following file(s) be generated:' ) + + IF ( p%WrFile(FileExt_BIN) ) THEN + +! CALL OpenBOutFile ( UnOut, TRIM( p%RootName)//'.bin', ErrStat, ErrMsg ) + CALL OpenUOutfile ( UnOut , TRIM( p%RootName)//'.bin', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE(UnOut) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".bin (binary hub-height turbulence-parameter file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.bin (binary hub-height turbulence-parameter file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_DAT) ) THEN + + CALL OpenFOutFile ( UnOut, TRIM( p%RootName)//'.dat', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE( UnOut ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US, "( 3X ,'"//TRIM( p%RootName)//".dat (formatted turbulence-parameter file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.dat (formatted turbulence-parameter file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_HH) ) THEN + + CALL OpenFOutFile ( UnOut, TRIM( p%RootName)//'.hh', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE( UnOut ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".hh (AeroDyn hub-height file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.hh (AeroDyn hub-height file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_BTS) ) THEN + + CALL OpenBOutFile ( UnOut, TRIM(p%RootName)//'.bts', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE( UnOut ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".bts (AeroDyn/TurbSim full-field wind file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.bts (AeroDyn/TurbSim full-field wind file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_WND) ) THEN + + CALL OpenBOutFile ( UnOut, TRIM(p%RootName)//'.wnd', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE(UnOut) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".wnd (AeroDyn/BLADED full-field wnd file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.wnd (AeroDyn/BLADED full-field wnd file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_TWR) .AND. p%WrFile(FileExt_WND) ) THEN + + CALL OpenBOutFile ( UnOut, TRIM( p%RootName )//'.twr', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE(UnOut) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".twr (binary tower file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.twr (binary tower file)' ) + + ENDIF + + IF ( p%WrFile(FileExt_CTS) ) THEN + CALL OpenBOutFile ( UnOut, TRIM( p%RootName )//'.cts', ErrStat2, ErrMsg2 ) ! just making sure it can be opened (not locked elsewhere) + CLOSE(UnOut) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".cts (coherent turbulence time step file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.cts (coherent turbulence time step file)' ) + ENDIF + + IF ( p%WrFile(FileExt_UVW) ) THEN + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".u (formatted full-field U-component file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.u (formatted full-field U-component file)' ) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".v (formatted full-field V-component file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.v (formatted full-field V-component file)' ) + + WRITE (p%US,"( 3X ,'"//TRIM( p%RootName)//".w (formatted full-field W-component file)' )") +! CALL WrScr ( ' '//TRIM( p%RootName)//'.w (formatted full-field W-component file)' ) + ENDIF + +ELSE + CALL SetErrStat( ErrID_Fatal, 'You have requested no output.', ErrStat, ErrMsg, RoutineName) +ENDIF + + ! WARN if using a large grid and not creating ff output files +IF ( p%grid%NumGrid_Y*p%grid%NumGrid_Z > 250 ) THEN + IF (.NOT. p%WrFile(FileExt_WND) .AND. .NOT. p%WrFile(FileExt_BTS) .AND. .NOT. p%WrFile(FileExt_UVW) ) THEN + + CALL SetErrStat( ErrID_Warn, 'You are using a large number of grid points but are not generating full-field output files.'//& + ' The simulation will run faster if you reduce the number of points on the grid.', ErrStat, ErrMsg, RoutineName) + END IF +END IF + +END SUBROUTINE TS_ValidateInput +!======================================================================= +SUBROUTINE TimeSeriesToSpectra( p, ErrStat, ErrMsg ) + + ! USE NWTC_FFTPACK + + ! passed variables + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p + + INTEGER(IntKi), intent( out) :: ErrStat !< Error level + CHARACTER(*), intent( out) :: ErrMsg !< Message describing error + + + ! local variables + TYPE(FFT_DataType) :: FFT_Data ! data for applying FFT + real(siki), allocatable :: work (:) ! working array for converting fourier coefficients to spectra + real(reki) :: Re, Im ! real and imaginary parts of complex variable returned from fft + + REAL(ReKi) :: meanU ! mean value of the U component + REAL(ReKi) :: meanV ! mean value of the V component + REAL(ReKi) :: meanW ! mean value of the W component + + REAL(DbKi) :: DelF ! delta frequency + + REAL(ReKi) :: cosH, sinH ! cosine and sin of horizontal angles + REAL(ReKi) :: cosV, sinV ! cosine and sin of vertical angles + REAL(ReKi) :: rotateMatrix(3,3) ! rotation matrix to align with direction of mean velocity + REAL(ReKi) :: uvw(3) ! temporary array to hold 3 velocity components in case < 3 were entered + + INTEGER(IntKi) :: Indx ! generic index + INTEGER(IntKi) :: iFreq ! loop counter for frequency + INTEGER(IntKi) :: iTime ! loop counter for time + INTEGER(IntKi) :: iVec ! loop counter for velocity components + INTEGER(IntKi) :: iPoint ! loop counter for grid points + INTEGER(IntKi) :: NumSteps ! number of time steps + + INTEGER(IntKi) :: ErrStat2 ! Error level (local) + CHARACTER(MaxMsgLen) :: ErrMsg2 ! error message (local) + CHARACTER(*), parameter :: RoutineName = 'TimeSeriesToSpectra' + + ErrStat = ErrID_None + ErrMsg = "" + + + ! BJJ: consider putting the call to PSF in the reading part + p%usr%nFreq = PSF ( p%usr%NTimes/2, 9, .TRUE.) + NumSteps = p%usr%nFreq*2 + + CALL AllocAry(p%usr%meanU, p%usr%NPoints,p%usr%nComp,'meanU', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p%usr%meanDir, p%usr%NPoints, 'meanDir', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p%usr%meanVAng, p%usr%NPoints, 'meanVAng', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p%usr%S, p%usr%nFreq ,p%usr%NPoints,p%usr%nComp,'S', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p%usr%f, p%usr%nFreq , 'f', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(p%usr%phaseAngles,p%usr%nFreq ,p%usr%NPoints,p%usr%nComp,'phaseAngles',ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(work, NumSteps, 'work', ErrStat2,ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + !....................................................................... + ! calculate wind direction in radians (before rotating or removing mean): + !....................................................................... + + meanV = 0.0_ReKi + meanW = 0.0_ReKi + + DO iPoint = 1, p%usr%NPoints + meanU = sum(p%usr%v(:,iPoint,1))/p%usr%NTimes + + if (p%usr%nComp > 1 ) then + meanV = sum(p%usr%v(:,iPoint,2))/p%usr%NTimes + + if ( p%usr%nComp > 2 ) then + meanW = sum(p%usr%v(:,iPoint,3))/p%usr%NTimes + end if + + end if + + p%usr%meanDir( iPoint) = atan2( meanV, meanU ) + p%usr%meanVAng(iPoint) = atan2( meanW, sqrt( meanU**2 + meanV**2 ) ) + END DO + + !....................................................................... + ! rotate inputs based on angles at reference point: + !....................................................................... + uvw = 0.0_ReKi + DO iPoint = 1, p%usr%NPoints + + cosH = cos(p%usr%meanDir( iPoint ) ) + sinH = sin(p%usr%meanDir( iPoint ) ) + cosV = cos(p%usr%meanVAng( iPoint ) ) + sinV = sin(p%usr%meanVAng( iPoint ) ) + + rotateMatrix(1,1) = cosH*cosV + rotateMatrix(2,1) = -sinH + rotateMatrix(3,1) = -cosH*sinV + + rotateMatrix(1,2) = sinH*cosV + rotateMatrix(2,2) = cosH + rotateMatrix(3,2) = -sinH*sinV + + rotateMatrix(1,3) = sinV + rotateMatrix(2,3) = 0.0_ReKi + rotateMatrix(3,3) = cosV + + DO iTime = 1, p%usr%nTimes + uvw(1:p%usr%nComp) = p%usr%v(iTime,iPoint,:) + uvw = MATMUL( rotateMatrix, uvw ) + p%usr%v(iTime,iPoint,:) = uvw(1:p%usr%nComp) + END DO + + END DO + + ! now convert angles to degrees: + p%usr%meanDir = p%usr%meanDir * R2D + p%usr%meanVAng = p%usr%meanVAng * R2D + + + !....................................................................... + ! calculate and remove the mean wind components: + !....................................................................... + DO iVec = 1,p%usr%nComp + DO iPoint = 1, p%usr%NPoints + p%usr%meanU(iPoint,iVec) = SUM( p%usr%v(:,iPoint,iVec), 1 ) / p%usr%NTimes + p%usr%v(:, iPoint,iVec) = p%usr%v(:,iPoint,iVec) - p%usr%meanU(iPoint,iVec) + END DO + END DO + + + !....................................................................... + ! compute forward fft to get real and imaginary parts + ! S = Re^2 + Im^2 + ! PhaseAngle = acos( Re / S ) + !....................................................................... + + + CALL InitFFT( NumSteps, FFT_Data, NormalizeIn=.TRUE., ErrStat=ErrStat2 ) + CALL SetErrStat(ErrStat2, 'Error in InitFFT', ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + + ! Get the stationary-point time series. + DO iVec=1,p%usr%nComp + DO iPoint=1,p%usr%NPoints + + work = p%usr%v(:,iPoint,iVec) + + ! perform forward FFT + + CALL ApplyFFT_f( work, FFT_Data, ErrStat2 ) + IF (ErrStat2 /= ErrID_None ) THEN + CALL SetErrStat(ErrStat2, 'Error in ApplyFFT_f for point '//TRIM(Num2LStr(iPoint))//'.', ErrStat, ErrMsg, RoutineName ) + IF (ErrStat >= AbortErrLev) EXIT + END IF + + + DO iFreq = 1,p%usr%nFreq-1 + Indx = iFreq*2 + Re = work(Indx) + Im = work(Indx+1) + + p%usr%S( iFreq,iPoint,iVec) = Re**2 + Im**2 + + IF ( p%usr%S( iFreq,iPoint,iVec) /= 0.0_ReKi ) THEN + p%usr%PhaseAngles(iFreq,iPoint,iVec) = atan2( Im, Re ) ! this gives us the angles in range -pi to pi + if ( p%usr%PhaseAngles(iFreq,iPoint,iVec) < 0.0_ReKi ) then ! we want it in the range 0 to 2pi + p%usr%PhaseAngles(iFreq,iPoint,iVec) = TwoPi + p%usr%PhaseAngles(iFreq,iPoint,iVec) + end if + ELSE + p%usr%PhaseAngles(iFreq,iPoint,iVec) = 0.0_ReKi + END IF + END DO + + p%usr%S( p%usr%nFreq,iPoint,iVec) = work(NumSteps)**2 !0.0_ReKi !work(NumSteps)**2 ! this frequency doesn't seem to get used in the code, so I'm going to set it to zero. <<< bjj: will be used for extrapolation + p%usr%PhaseAngles(p%usr%nFreq,iPoint,iVec) = 0.0_ReKi + + ENDDO ! IPoint + ENDDO ! IVec + + ! calculate associated frequencies: + p%usr%DelF = 1.0_DbKi / ( NumSteps * ( p%usr%t(2) - p%usr%t(1) ) ) !store frequency in double precision for cases of very long time series + do iFreq=1,p%usr%nFreq + p%usr%f(iFreq) = p%usr%DelF * iFreq + end do + + p%usr%S = p%usr%S*real(2.0_DbKi/p%usr%DelF,ReKi) ! p%usr%S*2.0_ReKi/p%usr%f(1) ! make this the single-sided velocity spectra we're using in the rest of the code + + + CALL Cleanup() + + RETURN +CONTAINS +!........................................... + SUBROUTINE Cleanup() + + CALL ExitFFT( FFT_Data, ErrStat2 ) + CALL SetErrStat(ErrStat2, 'Error in ExitFFT', ErrStat, ErrMsg, RoutineName ) + + IF ( ALLOCATED(work) ) DEALLOCATE(work) + + ! we don't need these anymore: + IF ( ALLOCATED( p%usr%t ) ) DEALLOCATE( p%usr%t ) + IF ( ALLOCATED( p%usr%v ) ) DEALLOCATE( p%usr%v ) + + END SUBROUTINE Cleanup + +END SUBROUTINE TimeSeriesToSpectra +!======================================================================= +SUBROUTINE TS_End(p, OtherSt_RandNum) + + + TYPE(TurbSim_ParameterType), INTENT(INOUT) :: p !< parameters + TYPE(RandNum_OtherStateType), INTENT(INOUT) :: OtherSt_RandNum !< other states for random numbers (next seed, etc) + + + IF (p%US > 0) THEN + CLOSE( p%US ) + p%US = -1 + END IF + + +!bjj: todo: add more; make sure everything is deallocated here; make sure files are closed, too. + + IF ( ALLOCATED( p%grid%Y ) ) DEALLOCATE( p%grid%Y ) + IF ( ALLOCATED( p%grid%Z ) ) DEALLOCATE( p%grid%Z ) + IF ( ALLOCATED( p%grid%GridPtIndx ) ) DEALLOCATE( p%grid%GridPtIndx ) + IF ( ALLOCATED( p%grid%TwrPtIndx ) ) DEALLOCATE( p%grid%TwrPtIndx ) + IF ( ALLOCATED( p%grid%Freq ) ) DEALLOCATE( p%grid%Freq ) + + IF ( ALLOCATED( p%met%ZL_profile ) ) DEALLOCATE( p%met%ZL_profile ) + IF ( ALLOCATED( p%met%Ustar_profile ) ) DEALLOCATE( p%met%Ustar_profile ) + + IF ( ALLOCATED( p%met%USR_Z ) ) DEALLOCATE( p%met%USR_Z ) + IF ( ALLOCATED( p%met%USR_U ) ) DEALLOCATE( p%met%USR_U ) + IF ( ALLOCATED( p%met%USR_WindDir ) ) DEALLOCATE( p%met%USR_WindDir ) + IF ( ALLOCATED( p%met%USR_Sigma ) ) DEALLOCATE( p%met%USR_Sigma ) + IF ( ALLOCATED( p%met%USR_L ) ) DEALLOCATE( p%met%USR_L ) + + IF ( ALLOCATED( p%usr%pointyi ) ) DEALLOCATE( p%usr%pointyi ) + IF ( ALLOCATED( p%usr%pointzi ) ) DEALLOCATE( p%usr%pointzi ) + IF ( ALLOCATED( p%usr%t ) ) DEALLOCATE( p%usr%t ) + IF ( ALLOCATED( p%usr%v ) ) DEALLOCATE( p%usr%v ) + + IF ( ALLOCATED( p%usr%meanU ) ) DEALLOCATE( p%usr%meanU ) + IF ( ALLOCATED( p%usr%meanDir ) ) DEALLOCATE( p%usr%meanDir ) + IF ( ALLOCATED( p%usr%meanVAng ) ) DEALLOCATE( p%usr%meanVAng ) + + IF ( ALLOCATED( p%usr%f ) ) DEALLOCATE( p%usr%f ) + IF ( ALLOCATED( p%usr%S ) ) DEALLOCATE( p%usr%S ) + IF ( ALLOCATED( p%usr%phaseAngles ) ) DEALLOCATE( p%usr%phaseAngles ) + + IF ( ALLOCATED( p%RNG%RandSeedAry ) ) DEALLOCATE( p%RNG%RandSeedAry ) + + + IF (ALLOCATED(OtherSt_RandNum%nextSeed) ) DEALLOCATE(OtherSt_RandNum%nextSeed) + + +END SUBROUTINE TS_END +!======================================================================= +END MODULE TSSubs diff --git a/OpenFAST/modules/turbsim/src/TurbSim.f90 b/OpenFAST/modules/turbsim/src/TurbSim.f90 new file mode 100644 index 000000000..e07223fa2 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/TurbSim.f90 @@ -0,0 +1,386 @@ +!======================================================================= +PROGRAM TurbSim + + ! A turbulence simulator developed at the + ! National Renewable Energy Laboratory, Golden, Colorado + ! + ! v1.0a-bjj 15-Mar-2004 B. Jonkman + ! v1.0 4-Nov-2005 B. Jonkman + ! v1.01 24-Jan-2006 B. Jonkman (NWTC subs v1.00a-mlb) + ! v1.10 10-Apr-2006 B. Jonkman (NWTC subs v1.12) + ! v1.20 20-Oct-2006 B. Jonkman (NWTC subs v1.12) + ! v1.21 1-Feb-2007 B. Jonkman (NWTC subs v1.12) + ! v1.30 4-Apr-2008 B. Jonkman (NWTC subs v1.01.09) + ! v1.40 12-Sep-2008 B. Jonkman (NWTC subs v1.01.09) + ! v1.41h 11-Jun-2009 B. Jonkman (NWTC subs v1.01.09) + ! v1.50 25-Sep-2009 B. Jonkman (NWTC subs v1.01.09) + ! V1.06.00 21-Sep-2012 L. Kilcher & B. Jonkman (NWTC Library v1.04.01) + ! v1.07.00a-bjj 9-Jul-2014 B. Jonkman (NWTC Library v1.04.02a-bjj) + ! v2.00.00a-bjj Oct-2014 B. Jonkman (NWTC Library 2.0) + ! + ! This program simulates a full field of turbulent winds at points in space + ! in a rectangular Cartesian plane perpendicular to the mean wind direction. + ! + ! Example usage: at a command prompt, type + ! turbsim turbsim.inp + ! This will read the text input file named "turbsim.inp" + + ! ------------------------------------------------------------------------------------------------------- + ! This is for dimension 2 of V(:,:,:).... + ! + ! The grid of points on the Cartesian plane is numbered in the following way (notice that the first + ! height starts at the bottom of the grid): + ! + ! Yb(1) Yb(2) Yb(3) ... Yb(NumGrid_Y) + ! -------------------------------------------------------------------------------------------------------------------------------------------- + ! Zb(NumGrid_Z):|V(GridPtIndx(NumGrid_Y*(NumGrid_Z-1)+1)) ... V(GridPtIndx(NumGrid_Z*NumGrid_Y)) | + ! ... |... | + ! Zb(2) :|V(GridPtIndx(NumGrid_Y + 1)) V(GridPtIndx(NumGrid_Y + 2)) V(GridPtIndx(NumGrid_Y + 3)) ... V(GridPtIndx( 2*NumGrid_Y)) | + ! Zb(1) :|V(GridPtIndx( 1)) V(GridPtIndx( 2)) V(GridPtIndx( 3)) ... V(GridPtIndx( NumGrid_Y)) | + ! -------------------------------------------------------------------------------------------------------------------------------------------- + ! + ! Zb(i) < Zb(i+1) for all integers i, 1 <= i < NumGrid_Z + ! Yb(j) < Yb(j+1) for all integers j, 1 <= j < NumGrid_Y + ! note that the Y and Z arrays used in the code are NOT necessarially in the order of Yb and Zb described here. + ! + ! If an extra hub point is necessary because the point does not fall on the grid, + ! then it is added immediately following the regular grid points. + ! + ! If the tower wind file output is selected, those extra points (in a single vertical + ! line) are added at the end, at the end (after the grid and hub point). + ! + ! Any user-defined time-series points are stored at the BEGINNING, before the grid points. + ! -------------------------------------------------------------------------------------------------------- + + +USE TSsubs +USE TS_FileIO +USE TS_Profiles +use TS_CohStructures +use VersionInfo + +IMPLICIT NONE + + + ! Declare local variables + +TYPE( TurbSim_ParameterType ) :: p ! TurbSim parameters +TYPE(RandNum_OtherStateType) :: OtherSt_RandNum ! other states for random numbers (next seed, etc) + +REAL(ReKi), ALLOCATABLE :: PhaseAngles (:,:,:) ! The array that holds the random phases [number of points, number of frequencies, number of wind components=3]. +REAL(ReKi), ALLOCATABLE :: S (:,:,:) ! The turbulence PSD array (NumFreq,NPoints,3). +REAL(ReKi), ALLOCATABLE :: V (:,:,:) ! An array containing the summations of the rows of H (NumSteps,NPoints,3). +REAL(ReKi), ALLOCATABLE :: U (:) ! The steady u-component wind speeds for the grid (NPoints). +REAL(ReKi), ALLOCATABLE :: HWindDir (:) ! A profile of horizontal wind angle (NPoints) (measure of wind direction with height) +REAL(ReKi), ALLOCATABLE :: VWindDir (:) ! A profile of vretical wind angle (NPoints) (measure of wind vertical angle with height) + +REAL(ReKi) :: CPUtime ! Contains the number of seconds since the start of the program + +REAL(ReKi) :: USig ! Standard deviation of the u-component wind speed at the hub (used for scaling WND files) +REAL(ReKi) :: VSig ! Standard deviation of the v-component wind speed at the hub (used for scaling WND files) +REAL(ReKi) :: WSig ! Standard deviation of the w-component wind speed at the hub (used for scaling WND files and CTS files) + +INTEGER(IntKi) :: ErrStat ! allocation status +CHARACTER(MaxMsgLen) :: ErrMsg ! error message +CHARACTER(200) :: InFile ! Name of the TurbSim input file. +CHARACTER(200) :: git_commit ! String containing the current git commit hash +CHARACTER(20) :: FlagArg ! flag argument from command line + + +!BONNIE:***************************** +! Time = TIMEF() ! Initialize the Wall Clock Time counter +!BONNIE:***************************** + +p%US = -1 + + ! ... Initialize NWTC Library (open console, set pi constants) ... +CALL NWTC_Init( ProgNameIN=TurbSim_Ver%Name, EchoLibVer=.FALSE. ) + + ! Check for command line arguments. +InFile = 'TurbSim.inp' ! default name for input file +CALL CheckArgs( InFile, Flag=FlagArg ) +IF ( LEN( TRIM(FlagArg) ) > 0 ) CALL NormStop() + + ! Print out program name, version, and date. + + ! Display the copyright notice + CALL DispCopyrightLicense( TurbSim_Ver%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( TurbSim_Ver%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + +CALL GetRoot( InFile, p%RootName ) + + ! Open input file and summary file. + +CALL OpenSummaryFile( p%RootName, p%US, p%DescStr, ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + + ! Get input parameters. + +CALL ReadInputFile(InFile, p, OtherSt_RandNum, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + +CALL WrSum_EchoInputs(p) +call WrSum_UserInput(p%met,p%usr, p%US) + +CALL TS_ValidateInput(p, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + + +!.................................................................................................................................. +! Define the spatial grid +!.................................................................................................................................. + + ! Define the other parameters for the time series. +CALL CreateGrid( p%grid, p%usr, p%UHub, p%WrFile(FileExt_TWR), ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + +!.................................................................................................................................. +! Calculate mean velocity and direction profiles: +!.................................................................................................................................. + + ! Wind speed: +CALL AllocAry(U, SIZE(p%grid%Z), 'u (steady, u-component winds)', ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + +CALL getVelocityProfile( p, p%UHub, p%grid%HubHt, p%grid%Z, U, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + + ! Wind Direction: +CALL AllocAry(HWindDir, SIZE(p%grid%Z), 'HWindDir (wind direction profile)', ErrStat, ErrMsg ) ! Allocate the array for the wind direction profile +CALL CheckError(ErrStat, ErrMsg) + +CALL AllocAry(VWindDir, SIZE(p%grid%Z), 'VWindDir (vertical wind angle profile)', ErrStat, ErrMsg ) ! Allocate the array for the vertical wind profile +CALL CheckError(ErrStat, ErrMsg) + +CALL getDirectionProfile(p, p%grid%Z, HWindDir, VWindDir, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + +p%met%HH_HFlowAng = HWindDir( p%grid%HubIndx ) +p%met%HH_VFlowAng = VWindDir( p%grid%HubIndx ) + +!.................................................................................................................................. +! Calculate remaining parameters required for simulation: +!.................................................................................................................................. + + +IF ( p%met%TurbModel_ID == SpecModel_GP_LLJ) THEN + + ! Allocate the arrays for the z/l and ustar profile + + CALL AllocAry(p%met%ZL_profile, SIZE(p%grid%Z), 'ZL_profile (z/l profile)', ErrStat, ErrMsg ) + CALL CheckError(ErrStat, ErrMsg) + CALL AllocAry(p%met%Ustar_profile, SIZE(p%grid%Z), 'Ustar_profile (friction velocity profile)', ErrStat, ErrMsg ) + CALL CheckError(ErrStat, ErrMsg) + + p%met%ZL_profile(:) = getZLProfile( U, p%grid%Z, p%met%Rich_No, p%met%ZL, p%met%L, p%met%ZLOffset, p%met%WindProfileType ) + p%met%Ustar_profile(:) = getUStarProfile( p, U, p%grid%Z, p%met%UStarOffset, p%met%UStarSlope ) + +END IF + + +CALL WrSum_SpecModel( p, U, HWindDir, VWindDir, ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + + +!.................................................................................................................................. +! Get the single-point power spectral densities +!.................................................................................................................................. + +CALL AllocAry( S, p%grid%NumFreq,p%grid%NPoints,3, 'S (turbulence PSD)',ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + +CALL CalcTargetPSD(p, S, U, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + + ! we don't need these arrays any more, so deallocate to save some space +IF ( ALLOCATED( p%met%USR_Z ) ) DEALLOCATE( p%met%USR_Z ) +IF ( ALLOCATED( p%met%USR_U ) ) DEALLOCATE( p%met%USR_U ) +IF ( ALLOCATED( p%met%USR_WindDir ) ) DEALLOCATE( p%met%USR_WindDir ) +IF ( ALLOCATED( p%met%USR_Sigma ) ) DEALLOCATE( p%met%USR_Sigma ) +IF ( ALLOCATED( p%met%USR_L ) ) DEALLOCATE( p%met%USR_L ) + +IF ( ALLOCATED( p%met%ZL_profile ) ) DEALLOCATE( p%met%ZL_profile ) +IF ( ALLOCATED( p%met%Ustar_profile ) ) DEALLOCATE( p%met%Ustar_profile ) + +!IF ( ALLOCATED( p%usr%f ) ) DEALLOCATE( p%usr%f ) bjj: do we need to keep these for phase angles? +IF ( ALLOCATED( p%usr%S ) ) DEALLOCATE( p%usr%S ) +IF ( ALLOCATED( p%usr%meanU ) ) DEALLOCATE( p%usr%meanU ) +IF ( ALLOCATED( p%usr%meanDir ) ) DEALLOCATE( p%usr%meanDir ) +IF ( ALLOCATED( p%usr%meanVAng ) ) DEALLOCATE( p%usr%meanVAng ) + +!.................................................................................................................................. +! Get the phase angles +!.................................................................................................................................. + +CALL AllocAry( PhaseAngles, p%grid%NPoints, p%grid%NumFreq, 3, 'Random Phases', ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + +CALL SetPhaseAngles( p, OtherSt_RandNum, PhaseAngles, ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + + ! we don't need these arrays any more, so deallocate to save some space +IF ( ALLOCATED(OtherSt_RandNum%nextSeed ) ) DEALLOCATE( OtherSt_RandNum%nextSeed ) +IF ( ALLOCATED(p%usr%PhaseAngles ) ) DEALLOCATE( p%usr%PhaseAngles ) +IF ( ALLOCATED(p%usr%f ) ) DEALLOCATE( p%usr%f ) ! bjj: do we need to keep these for phase angles or should we destroy earlier? + +!.................................................................................................................................. +! Get the Fourier Coefficients +!.................................................................................................................................. +CALL AllocAry( V, p%grid%NumSteps, p%grid%NPoints, 3, 'V (velocity)', ErrStat, ErrMsg) ! Allocate the array that contains the velocities. +CALL CheckError(ErrStat, ErrMsg) + + + ! Calculate the transfer function matrices from the spectral matrix (the fourier coefficients). + +CALL WrScr ( ' Calculating the spectral and transfer function matrices:' ) + +CALL CalcFourierCoeffs( p, U, PhaseAngles, S, V, ErrStat, ErrMsg ) +CALL CheckError(ErrStat, ErrMsg) + + + ! we don't need these arrays any more, so deallocate to save some space +IF ( ALLOCATED( p%grid%Freq ) ) DEALLOCATE( p%grid%Freq ) +IF ( ALLOCATED( S ) ) DEALLOCATE( S ) +IF ( ALLOCATED( PhaseAngles ) ) DEALLOCATE( PhaseAngles ) + +!.................................................................................................................................. +! Create the time series +!.................................................................................................................................. +CALL Coeffs2TimeSeries( V, p%grid%NumSteps, p%grid%NPoints, p%usr%NPoints, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + +!.................................................................................................................................. +! Scale time series (if desired) for cross-component correlation or IEC statistics: +!.................................................................................................................................. +CALL ScaleTimeSeries(p, V, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + + +!.................................................................................................................................. +! Write statistics of the run to the summary file: +!.................................................................................................................................. +CALL WrSum_Stats(p, V, USig, VSig, WSig, ErrStat, ErrMsg) +CALL CheckError(ErrStat, ErrMsg) + +!.................................................................................................................................. +! Write hub-height output files (before adding mean and rotating final results) +!.................................................................................................................................. + +IF ( p%WrFile(FileExt_HH) ) THEN + CALL WrHH_ADtxtfile(p, V, p%IEC%TurbInt, ErrStat, ErrMsg) + CALL CheckError(ErrStat, ErrMsg) +END IF + +IF ( p%WrFile(FileExt_BIN) ) THEN + CALL WrHH_binary(p, V, ErrStat, ErrMsg) + CALL CheckError(ErrStat, ErrMsg) +END IF + +IF ( p%WrFile(FileExt_DAT) ) THEN + CALL WrHH_text(p, V, ErrStat, ErrMsg ) + CALL CheckError(ErrStat, ErrMsg) +END IF + + +!.................................................................................................................................. +! Add mean wind to u' components and rotate to inertial reference frame coordinate system +!.................................................................................................................................. +CALL AddMeanAndRotate(p, V, U, HWindDir, VWindDir) + + ! Deallocate memory for the matrix of the steady, u-component winds. + +IF ( ALLOCATED( U ) ) DEALLOCATE( U ) +IF ( ALLOCATED( HWindDir ) ) DEALLOCATE( HWindDir ) +IF ( ALLOCATED( VWindDir ) ) DEALLOCATE( VWindDir ) + +!.................................................................................................................................. +! Generate coherent turbulence if desired: +!.................................................................................................................................. +IF ( p%WrFile(FileExt_CTS) ) THEN + + CALL CohStr_WriteCTS(p, WSig, OtherSt_RandNum, ErrStat, ErrMsg) + CALL CheckError(ErrStat, ErrMsg) + +ENDIF !WrACT + +!.................................................................................................................................. +! Generate full-field output files: +!.................................................................................................................................. + + ! Are we generating binary FF files? +IF ( p%WrFile(FileExt_BTS) .OR. p%WrFile(FileExt_WND) ) THEN + CALL WrSum_InterpolatedHubStats(p, V) + + IF ( p%WrFile(FileExt_BTS) ) THEN + CALL WrBinTURBSIM(p, V, ErrStat, ErrMsg) + CALL CheckError(ErrStat, ErrMsg) + END IF + + IF ( p%WrFile(FileExt_WND) ) THEN + CALL WrBinBLADED(p, V, USig, VSig, WSig, ErrStat, ErrMsg) + CALL CheckError(ErrStat, ErrMsg) + END IF +END IF + + + ! Are we generating formatted (text) FF files? +IF ( p%WrFile(FileExt_UVW) ) THEN + CALL WrFormattedFF(p%RootName, p%grid, p%UHub, V) +ENDIF ! ( WrFile(FileExt_UVW) ) + +!.................................................................................................................................. +! End: +!.................................................................................................................................. + +IF ( ALLOCATED( V ) ) DEALLOCATE( V ) + + + ! Request CPU-time used. + +CALL CPU_TIME ( CPUtime ) +WRITE (p%US,"(//,'Processing complete. ',A,' CPU seconds used.')") TRIM( Num2LStr( CPUtime ) ) +CALL WrScr1 ( ' Processing complete. '//TRIM( Num2LStr( CPUtime ) )//' CPU seconds used.' ) + +CALL TS_End( p, OtherSt_RandNum ) +CALL NormStop + + +CONTAINS +!.................................................................................................................................. +SUBROUTINE CheckError(ErrID,Msg) + INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) + CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) + + + IF (ErrID /= ErrID_None) THEN + + IF (ErrID >= AbortErrLev) THEN + + IF (ALLOCATED(PhaseAngles)) DEALLOCATE(PhaseAngles) + IF (ALLOCATED(S )) DEALLOCATE(S ) + IF (ALLOCATED(V )) DEALLOCATE(V ) + IF (ALLOCATED(U )) DEALLOCATE(U ) + IF (ALLOCATED(HWindDir )) DEALLOCATE(HWindDir ) + IF (ALLOCATED(VWindDir )) DEALLOCATE(VWindDir ) + + + if (p%US > 0) then + WRITE (p%US, "(/'ERROR: ', A / )") TRIM(Msg) + WRITE (p%US, "('ABORTING PROGRAM.')" ) + end if + + CALL TS_end(p, OtherSt_RandNum) + + CALL ProgAbort ( TRIM(Msg), .FALSE., 5.0_ReKi ) + + ELSE + CALL WrScr(TRIM(Msg)) + END IF + + END IF +END SUBROUTINE CheckError + +END PROGRAM diff --git a/OpenFAST/modules/turbsim/src/TurbSim_Types.f90 b/OpenFAST/modules/turbsim/src/TurbSim_Types.f90 new file mode 100644 index 000000000..3e99754b0 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/TurbSim_Types.f90 @@ -0,0 +1,299 @@ +!================================================================================================================================== +MODULE TurbSim_Types + +use NWTC_Library + + TYPE(ProgDesc), PARAMETER :: TurbSim_Ver = ProgDesc( 'TurbSim', '', '' ) + + LOGICAL, PARAMETER :: MVK = .FALSE. ! This parameter has been added to replace the NON-STANDARD compiler directive previously used + LOGICAL, PARAMETER :: PeriodicY = .FALSE. !.TRUE. + + + INTEGER(IntKi), PARAMETER :: MaxMsgLen = 1024 ! Maximum length of error messages + + ! Valid spectral models (i.e., turbulence models; values of TurbModel_ID) + INTEGER(IntKi), PARAMETER :: SpecModel_NONE = 0 ! No turbulence + INTEGER(IntKi), PARAMETER :: SpecModel_IECKAI = 1 ! IEC Kaimal + INTEGER(IntKi), PARAMETER :: SpecModel_IECVKM = 2 ! IEC von Karman + INTEGER(IntKi), PARAMETER :: SpecModel_GP_LLJ = 3 ! Great Plains Low-Level Jet + INTEGER(IntKi), PARAMETER :: SpecModel_NWTCUP = 4 ! NWTC (upwind) + INTEGER(IntKi), PARAMETER :: SpecModel_SMOOTH = 5 ! Risoe Smooth-Terrain + INTEGER(IntKi), PARAMETER :: SpecModel_WF_UPW = 6 ! Wind Farm Upwind + INTEGER(IntKi), PARAMETER :: SpecModel_WF_07D = 7 ! Wind Farm 7 rotor diameters downwind + INTEGER(IntKi), PARAMETER :: SpecModel_WF_14D = 8 ! Wind Farm 14 rotor diameters downwind + INTEGER(IntKi), PARAMETER :: SpecModel_TIDAL = 9 ! Tidal (Hydro) + INTEGER(IntKi), PARAMETER :: SpecModel_RIVER = 10 ! River (Hydro) + INTEGER(IntKi), PARAMETER :: SpecModel_API = 11 ! API + INTEGER(IntKi), PARAMETER :: SpecModel_MODVKM = 12 ! user-specified scaling in von Karman model + INTEGER(IntKi), PARAMETER :: SpecModel_USRVKM = 13 ! user-specified scaling in von Karman model + INTEGER(IntKi), PARAMETER :: SpecModel_USER = 14 ! User-defined spectra from file + INTEGER(IntKi), PARAMETER :: SpecModel_TimeSer = 15 ! time series input from file + + ! Spatial Coherence Models (SCMod) + INTEGER(IntKi), PARAMETER :: CohMod_NONE = 0 ! no additional spatial coherence + INTEGER(IntKi), PARAMETER :: CohMod_GENERAL = 1 ! General spatial coherence model using parameters input from file + INTEGER(IntKi), PARAMETER :: CohMod_IEC = 2 ! Spatial coherence specified by IEC standard + INTEGER(IntKi), PARAMETER :: CohMod_API = 3 ! Spatial coherence specified by API standard + + + ! IEC turbulence types (IEC_WindType) + ! bjj: note that EWM models *MUST* directly follow ETM, and EWM models must be at the end + INTEGER(IntKi), PARAMETER :: IEC_NTM = 1 ! Number to indicate the IEC Normal Turbulence Model + INTEGER(IntKi), PARAMETER :: IEC_ETM = 2 ! Number to indicate the IEC Extreme Turbulence Model + INTEGER(IntKi), PARAMETER :: IEC_EWM1 = 3 ! Number to indicate the IEC Extreme Wind speed Model ( 1-year) + INTEGER(IntKi), PARAMETER :: IEC_EWM50 = 4 ! Number to indicate the IEC Extreme Wind speed Model ( 50-year) + INTEGER(IntKi), PARAMETER :: IEC_EWM100 = 5 ! Number to indicate the IEC Extreme Wind speed Model (100-year) + + + ! distinct output file formats (WrFile()) (listed by extension) + INTEGER(IntKi), PARAMETER :: FileExt_BTS = 1 ! .bts file : AeroDyn FF data (binary) [WrADFF] + INTEGER(IntKi), PARAMETER :: FileExt_WND = 2 ! .wnd file : BLADED FF data (binary) [WrBLFF] + INTEGER(IntKi), PARAMETER :: FileExt_HH = 3 ! .hh file : AeroDyn HH data (formatted) [WrADHH] + INTEGER(IntKi), PARAMETER :: FileExt_BIN = 4 ! .bin file : binary HH turbulence parameters [WrBHHTP] + INTEGER(IntKi), PARAMETER :: FileExt_DAT = 5 ! .dat file : formatted HH turbulence parameters [WrFHHTP] + INTEGER(IntKi), PARAMETER :: FileExt_UVW = 6 ! .u, .v, .w files : formatted FF data (Traditional SNLWIND-3D format) [WrFMTFF] + INTEGER(IntKi), PARAMETER :: FileExt_CTS = 7 ! .cts file : coherent turbulence + INTEGER(IntKi), PARAMETER :: FileExt_TWR = 8 ! .twr file : AeroDyn tower data (binary) + INTEGER(IntKi), PARAMETER :: NumFileFmt = 8 ! TOTAL number of output file formats (used to dimension array) + + ! other parameters: + REAL(ReKi), PARAMETER :: ZJetMax_UB = 490.0_ReKi ! upper bound on height where jet maximum occurs + REAL(ReKi), PARAMETER :: ZJetMax_LB = 70.0_ReKi ! lower bound on height where jet maximum occurs + REAL(ReKi), PARAMETER :: profileZmax = 140. ! Upper height limit for extrapolating GP_LLJ profiles of ustar and zl + REAL(ReKi), PARAMETER :: profileZmin = 50. ! Lower height limit for extrapolating GP_LLJ profiles of ustar and zl + REAL(ReKi), PARAMETER :: Omega = 7.292116E-05 ! Angular speed of rotation of the earth (rad/s) + REAL(ReKi), PARAMETER :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal + + CHARACTER(1), PARAMETER :: Comp (3) = (/ 'u', 'v', 'w' /) ! The names of the wind components + + + type :: RandNum_ParameterType + + integer(IntKi) :: pRNG + INTEGER(IntKi) :: RandSeed (3) ! The array that holds the initial random seeds for the 3 components. + INTEGER(IntKi), ALLOCATABLE :: RandSeedAry(:) ! The array that holds the random seeds. + CHARACTER( 6) :: RNG_type ! Type of Random Number Generator to use + + end type RandNum_ParameterType + + type :: RandNum_OtherStateType + INTEGER(IntKi), ALLOCATABLE :: NextSeed (:) ! The array that holds the next random seed for the 3 components. + end type RandNum_OtherStateType + + + TYPE :: CohStr_ParameterType + + 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 the bottom of the dataset. + REAL(ReKi) :: CTStartTime ! Minimum time to add coherent structures + REAL(ReKi) :: DistScl ! Disturbance scale for AeroDyn coherent turbulence events + + + CHARACTER(200) :: CTEventPath ! String used to store the name of the coherent event definition file + CHARACTER(200) :: CTEventFile ! String used to store the name of the coherent event definition file + CHARACTER( 3) :: CTExt ! String used to determine the type of coherent structures ("dns" or "les") + + END TYPE CohStr_ParameterType + + + + type :: Grid_ParameterType + + REAL(ReKi) :: GridHeight ! Grid height + REAL(ReKi) :: GridRes_Z ! Distance between two consecutive vertical points on the grid (Vertical resolution) + INTEGER(IntKi) :: NumGrid_Z ! Grid dimension. (in vertical direction) + + REAL(ReKi) :: GridWidth ! Grid width. + REAL(ReKi) :: GridRes_Y ! Distance between two consecutive horizontal points on the grid (Horizontal resolution) + INTEGER(IntKi) :: NumGrid_Y ! Grid dimension. (in horizontal direction) + + INTEGER(IntKi) :: NPoints ! Number of points being simulated. + INTEGER(IntKi) :: NPacked ! Number of entries stored in the packed version of the symmetric matrix of size NPoints by NPoints + + REAL(ReKi) :: Zbottom ! The height of the lowest point on the grid (before tower points are added), equal to Z(1) + REAL(ReKi) :: RotorDiameter ! The assumed diameter of the rotor + + INTEGER(IntKi) :: HubIndx ! Index that tells where the hub point is in the V matrix + + REAL(ReKi) :: HubHt ! Hub height. + LOGICAL :: HubOnGrid ! Flag to indicate if the hub is on the regular grid (true) or if an extra point must be added (false) + LOGICAL :: ExtraTwrPT ! Flag to indicate if the tower is on the regular grid or if an extra point must be added + + + REAL(ReKi), ALLOCATABLE :: Y (:) ! The lateral locations of the points (NPoints). + REAL(ReKi), ALLOCATABLE :: Z (:) ! The vertical locations of the points (NPoints). + + INTEGER(IntKi),ALLOCATABLE :: GridPtIndx (:) ! size is (NumGrid_Y * NumGrid_Z): The indices into the velocity array, indicating the points in the cartesian grid for output. Previously was assumed to be the first NumGrid_Y * NumGrid_Z points; now necessary because user-defined time series data may specifiy points on the grid. + INTEGER(IntKi),ALLOCATABLE :: TwrPtIndx (:) ! size is number of tower points: The indices into the velocity array, indicating the points to be put in the tower file for output. Previously was assumed to be the last NumTower points; now necessary because user-defined time series data may specifiy points on the tower. + + + REAL(ReKi) :: AnalysisTime ! Analysis Time. (amount of time for analysis, allows user to perform analysis using one time length, but output UsableTime + REAL(ReKi) :: UsableTime ! Usable time. Program adds GridWidth/MeanHHWS if not specified as "ALL" AnalysisTime in input file. + REAL(ReKi) :: TimeStep ! Time step. + REAL(ReKi), ALLOCATABLE :: Freq (:) ! The array of frequencies (NumFreq). + INTEGER(IntKi) :: NumFreq ! Number of frequencies (=NumSteps/2). + INTEGER(IntKi) :: NumSteps ! Number of time steps for the FFT. + INTEGER(IntKi) :: NumOutSteps ! Number of output time steps. + + LOGICAL :: Periodic ! Flag to indicate that output files must contain exactly one full (time) period + LOGICAL :: Clockwise ! Flag to indicate clockwise rotation when looking downwind. + + end type Grid_ParameterType + + + type IEC_ParameterType + INTEGER(IntKi) :: IECedition ! The edition number of the IEC 61400-1 standard that is being used (determines the scaling) + INTEGER(IntKi) :: IECstandard ! The standard number (x) of the IEC 61400-x that is being used + INTEGER(IntKi) :: IEC_WindType ! Number to indicate the IEC wind type + INTEGER(IntKi) :: ScaleIEC ! Switch to indicate if turbulence should be scaled to target value; 0 = NO scaling; 1 = scale based on hub; 2 = scale each point individually + + REAL(ReKi) :: Lambda (3) ! IEC turbulence scale parameter: defined as wavelength where the non-dimensional power spectral density fS(f)/sigma^2 == 0.05 [m] + REAL(ReKi) :: SigmaIEC (3) ! IEC target standard deviation. + REAL(ReKi) :: IntegralScale (3) ! IEC integral scales (s) + REAL(ReKi) :: LC ! IEC coherency scale parameter + REAL(ReKi) :: SigmaSlope ! Slope used with IEC models to determine target sigma and turbulent intensity + REAL(ReKi) :: TurbInt ! IEC target Turbulence Intensity + REAL(ReKi) :: TurbInt15 ! Turbulence Intensity at hub height with a mean wind speed of 15 m/s + REAL(ReKi) :: ETMc ! The c parameter in IEC ETM, 61400-1, Ed 3. Section 6.3.2.3, Eq. 19. Variable per last sentence in section 7.4.1 + REAL(ReKi) :: Vave ! The IEC Vave for ETM + REAL(ReKi) :: Vref ! The IEC Vref for ETM + REAL(ReKi) :: PerTurbInt ! Percent Turbulence Intensity + + LOGICAL :: NumTurbInp ! Flag to indicate if turbulence is user-specified (as opposed to IEC standard A, B, or C) + + CHARACTER( 1) :: IECTurbC ! IEC turbulence characteristic + CHARACTER( 1) :: IECTurbE ! IEC Extreme turbulence class + CHARACTER( 35) :: IEC_WindDesc ! The description of the IEC wind type + CHARACTER( 25) :: IECeditionStr ! description of the IEC standard being used + end type IEC_ParameterType + + + type Meteorology_ParameterType + + INTEGER(IntKi) :: TurbModel_ID ! Integer value of spectral model (see SpecModel enum) + LOGICAL :: KHtest ! Flag to indicate that turbulence should be extreme, to demonstrate effect of KH billows + CHARACTER( 3) :: WindProfileType ! The wind profile type + CHARACTER( 6) :: TurbModel ! Turbulence model + CHARACTER( 50) :: TMName ! Turbulence model name. + + REAL(ReKi) :: Fc ! Coriolis parameter in units (1/sec) + !REAL(ReKi) :: h ! Boundary layer depth + REAL(ReKi) :: RICH_NO ! Gradient Richardson number + REAL(ReKi) :: Z0 ! Surface roughness length, meters + REAL(ReKi) :: ZI ! Mixing layer depth + REAL(ReKi) :: Latitude ! The site latitude in radians + REAL(ReKi) :: L ! M-O length + REAL(ReKi) :: ZL ! A measure of stability + REAL(ReKi) :: PLExp ! Rotor disk power law exponent + REAL(ReKi) :: Ustar ! Shear or friction velocity (m/s) -- rotor-disk average + REAL(ReKi) :: UstarDiab ! The diabatic ustar value + REAL(ReKi) :: UstarOffset ! A scaling/offset value used with the Ustar_profile to ensure that the mean hub u'w' and ustar inputs agree with the profile values + REAL(ReKi) :: UstarSlope ! A scaling/slope value used with the Ustar_profile to ensure that the mean hub u'w' and ustar inputs agree with the profile values + REAL(ReKi) :: ZLoffset ! An offset to align the zl profile with the mean zl input parameter + + REAL(ReKi) :: RefHt ! Height for reference wind speed. + REAL(ReKi) :: URef ! The input wind speed at the reference height. (Added by M. Buhl for API profiles) + + REAL(ReKi), ALLOCATABLE :: ZL_profile(:) ! A profile of z/l (measure of stability with height) + REAL(ReKi), ALLOCATABLE :: Ustar_profile(:) ! A profile of ustar (measure of friction velocity with height) + !REAL(ReKi) :: TurbIntH20 ! Turbulence intensity used for HYDRO module. + + + REAL(ReKi) :: HH_HFlowAng ! Horizontal flow angle at the hub (may be different than HFlowAng if using direction profile). + REAL(ReKi) :: HH_VFlowAng ! Vertical flow angle at the hub (may be different than VFlowAng if using vertical angle profile (i.e., user-defined time-series)). + REAL(ReKi) :: HFlowAng ! Horizontal flow angle + REAL(ReKi) :: VFlowAng ! Vertical flow angle + + + ! coefficients for velocity and direction profiles (currently used with jet profiles only) + REAL(ReKi) :: ChebyCoef_WS(11) ! The Chebyshev coefficients for wind speed + REAL(ReKi) :: ChebyCoef_WD(11) ! The Chebyshev coefficients for wind direction + + + REAL(ReKi) :: ZJetMax ! The height of the jet maximum (m) + REAL(ReKi) :: UJetMax ! The (horizontal) wind speed at the height of the jet maximum (m/s) + + + ! Coherence + REAL(ReKi) :: COHEXP ! Coherence exponent for general spatial coherence model + REAL(ReKi) :: InCDec (3) ! Contains the coherence decrements for general spatial coherence model + REAL(ReKi) :: InCohB (3) ! Contains the coherence b/L (offset) parameters for general spatial coherence model + + INTEGER(IntKi) :: SCMod (3) ! SCMod_u, SCMod_v, and SCMod_w: switches determining which coherence model to use + + LOGICAL :: IsIECModel ! Flag to determine if we're using IEC scaling (coherence, etc) + + + ! Scaling + REAL(ReKi) :: PC_UW ! u'w' cross-correlation coefficient + REAL(ReKi) :: PC_UV ! u'v' cross-correlation coefficient + REAL(ReKi) :: PC_VW ! v'w' cross-correlation coefficient + + LOGICAL :: UVskip ! Flag to determine if UV cross-feed term should be skipped or used + LOGICAL :: UWskip ! Flag to determine if UW cross-feed term should be skipped or used + LOGICAL :: VWskip ! Flag to determine if VW cross-feed term should be skipped or used + + + ! user-defined profiles (also used with UsrVKM model): + INTEGER(IntKi) :: NumUSRz ! Number of heights defined in the user-defined profiles. + REAL(ReKi), ALLOCATABLE :: USR_Z (:) ! Heights of user-specified variables + REAL(ReKi), ALLOCATABLE :: USR_U (:) ! User-specified total wind speed, varying with height + REAL(ReKi), ALLOCATABLE :: USR_WindDir (:) ! User-specified wind direction profile, varying with height + REAL(ReKi), ALLOCATABLE :: USR_Sigma (:) ! User-specified standard deviation of the wind speed components (isotropic), varying with height + REAL(ReKi), ALLOCATABLE :: USR_L (:) ! User-specified von Karman length scale, varying with height + REAL(ReKi) :: USR_StdScale (3) ! Scaling for the user-specified standard deviation + + end type Meteorology_ParameterType + + + TYPE UserTSSpec_ParameterType + + integer(intKi) :: nComp ! number of velocity components in the file (1=u; 2=u&v; 3=u,v,w) + integer(intKi) :: nFreq ! number of frequencies in the calculated spectra + real(dbKi) :: DelF ! delta frequenc of the calculated spectra (same as f(1) in double precision) + integer(intKi) :: nPoints ! number of points in the time series input + integer(intKi) :: RefPtID ! Index of the reference point (1-nPoints) + integer(intKi) :: nTimes ! number of rows in the time series input + real(reki), allocatable :: pointyi (:) ! y position where each time series was input; size: nPoints + real(reki), allocatable :: pointzi (:) ! z position (height) where each time series was input; size: nPoints + real(reki), allocatable :: t(:) + real(reki), allocatable :: v(:,:,:) ! velocity time series; size: nTimes, nPoints, { 2 if .not. containsW | 3 otherwise } + + real(reKi), allocatable :: meanU(:,:) ! mean velocity; size: nPoints, nComp [m/s] + real(reKi), allocatable :: meanDir(:) ! mean horizontal direction; size: nPoints [degrees] + real(reKi), allocatable :: meanVAng(:) ! mean vertical angle; size: nPoints [degrees] + real(reKi), allocatable :: S(:,:,:) ! spectra; size: nFreq, nPoints, nComp + real(reKi), allocatable :: f(:) ! frequency; size: nFreq [Hz] + real(reKi), allocatable :: phaseAngles(:,:,:) + + INTEGER(IntKi) :: TurbModel_ID = SpecModel_NONE ! Integer value of spectral model (see SpecModel enum) for filling in high-frequency content; not all SpecModel values are valid here + + END TYPE UserTSSpec_ParameterType + + + type TurbSim_ParameterType + LOGICAL :: WrFile(NumFileFmt) ! Flag to determine which output files should be generated + INTEGER :: US = -1 ! I/O unit for summary file. + + + CHARACTER(200) :: DescStr ! String used to describe the run (and the first line of the summary file) + CHARACTER(197) :: RootName ! Root name of the I/O files. + TYPE(RandNum_ParameterType) :: RNG ! parameters for random numbers p_RandNum + TYPE(Grid_ParameterType) :: grid ! parameters for TurbSim (specify grid/frequency size) + TYPE(Meteorology_ParameterType) :: met ! parameters for TurbSim + TYPE(IEC_ParameterType) :: IEC ! parameters for IEC models + TYPE(UserTSSpec_ParameterType) :: usr ! parameters for user spectra or time-series input + TYPE(CohStr_ParameterType) :: CohStr ! parameters for coherent structures + + !bjj: there probably won't be a need for this later... + REAL(ReKi) :: UHub ! Hub-height (total) wind speed (m/s) + + + end type + + + + + +END MODULE TurbSim_Types +!================================================================================================================================== diff --git a/OpenFAST/modules/turbsim/src/VelocitySpectra.f90 b/OpenFAST/modules/turbsim/src/VelocitySpectra.f90 new file mode 100644 index 000000000..c122a5c68 --- /dev/null +++ b/OpenFAST/modules/turbsim/src/VelocitySpectra.f90 @@ -0,0 +1,2158 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2014, 2016 National Renewable Energy Laboratory +! +! This file is part of TurbSim. +! +! 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 TS_VelocitySpectra + + USE TurbSim_Types + + IMPLICIT NONE + +CONTAINS + + +!======================================================================= +!> This subroutine defines the Kaimal PSD model as specified by IEC 61400-1, 2nd Ed. & 3rd Ed. +!! the use of this subroutine requires that all variables have the units of meters and seconds. +SUBROUTINE Spec_IECKAI ( UHub, SigmaIEC, L_K, Freq, NumFreq, Spec ) + + + IMPLICIT NONE + + ! Passed variables + INTEGER(IntKi), INTENT(IN ) :: NumFreq !< Input: Number of frequencies + REAL(ReKi), INTENT(IN ) :: SigmaIEC (3) !< Input: sigma for 3 wind components specified by the IEC + REAL(ReKi), INTENT(IN ) :: L_k (3) !< Input: L_k (integral scale parameter) for 3 wind components specified by the IEC + REAL(ReKi), INTENT(IN ) :: UHub !< Input: mean wind speed at hub height + REAL(ReKi), INTENT(IN ) :: Freq (NumFreq) !< Input: frequency array + REAL(ReKi), INTENT(INOUT) :: Spec (NumFreq,3) !< Output: target spectrum + + ! Internal variables + + REAL(ReKi),PARAMETER :: Exp1 = 5.0/3.0 + + REAL(ReKi) :: L_over_U (3) + REAL(ReKi) :: SigmaLU (3) + + INTEGER :: I + INTEGER :: IVec + + + + ! Create the spectrum. +L_over_U = L_k / UHub +SigmaLU = 4.0 * SigmaIEC**2 * L_over_U ! array operations + +DO IVec = 1,3 + + L_over_U(IVec) = 6.0*L_over_U(IVec) + + DO I = 1,NumFreq + Spec(I,IVec) = SigmaLU(IVec) / ( 1.0 + L_over_U(IVec)*Freq(I) )**Exp1 + ENDDO !I + +ENDDO !IVec + + +RETURN +END SUBROUTINE Spec_IECKAI +!======================================================================= +!> This subroutine defines the von Karman PSD model as specified by IEC 61400-1 (2nd Ed). +!! The use of this subroutine requires that all variables have the units of meters and seconds. +SUBROUTINE Spec_IECVKM ( UHub, SigmaIEC_u, IntegralScale, Freq, NumFreq, Spec ) + + IMPLICIT NONE + + ! Passed variables + + INTEGER(IntKi), INTENT(IN ) :: NumFreq !< Input: Number of frequencies + REAL(ReKi), INTENT(IN ) :: SigmaIEC_u !< Input: target standard deviation for u component + REAL(ReKi), INTENT(IN ) :: IntegralScale (3) !< Input: integral scale parameter, L (isotropic, so we only care about the 1st one) + REAL(ReKi), INTENT(IN ) :: UHub !< Input: mean wind speed at hub height + REAL(ReKi), INTENT(IN ) :: Freq (NumFreq) !< Input: frequency array + REAL(ReKi), INTENT( OUT) :: Spec (NumFreq,3) !< Output: target spectrum + + + ! Internal variables + + REAL(ReKi),PARAMETER :: Exp1 = 5.0/6.0 + REAL(ReKi),PARAMETER :: Exp2 = 11.0/6.0 + REAL(ReKi) :: FLU2 + REAL(ReKi) :: L1_U + REAL(ReKi) :: SigmaL1_U + REAL(ReKi) :: Tmp + + INTEGER :: I + + + ! Set up scaling values. + + + ! Define u-component integral scale. + +L1_U = IntegralScale(1)/UHub +SigmaL1_U = 2.0*SigmaIEC_u*SigmaIEC_u*L1_U + +DO I=1,NumFreq + + FLU2 = ( Freq(I)*L1_U )**2 + Tmp = 1.0 + 71.0*FLU2 + + Spec(I,1) = 2.0*SigmaL1_U/Tmp**Exp1 + Spec(I,2) = SigmaL1_U*( 1.0 + 189.0*FLU2 )/Tmp**Exp2 + Spec(I,3) = Spec(I,2) + +ENDDO ! I + +RETURN +END SUBROUTINE Spec_IECVKM +!======================================================================= +!> This subroutine defines the API-BULLET-IN recommended extreme wind spectrum +!! The use of this subroutine requires that all variables have the units of meters and seconds. +!! See A.7.4 (Page 41) of API 2MET/ISO 19901-1:2005(E). +!! See https://rules.dnvgl.com/docs/pdf/DNV/codes/docs/2010-10/RP-C205.pdf (page 20 of 124), describing the +!! Froya model spectral density proposed by Andersen and Lovseth (1992, 2006) for wind over water. +SUBROUTINE Spec_API ( p, Ht, Spec ) + + ! NOTE: This routine uses the Kaimal model to create the spectrum for all three components + ! and then overwrites the u-component spectrum with the API model. + + +IMPLICIT NONE + + ! Passed variables + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN) :: Ht !< Input: Height (Should be HubHt), value ignored !bjj: is this true???? + REAL(ReKi), INTENT(INOUT) :: Spec (:,:) !< Output: target spectrum + +!REAL(ReKi),INTENT(IN) :: URef ! Added by YG +!REAL(ReKi),INTENT(IN) :: RefHt ! Reference height + + ! Internal variables + +REAL(ReKi),PARAMETER :: N = 0.468 +REAL(ReKi),PARAMETER :: Exp5 = 5.0/( 3.0*N ) +!mlb REAL(ReKi),PARAMETER :: Exp5 = 11.0/6.0 +REAL(ReKi),PARAMETER :: Ref_Ht = 10.0 +REAL(ReKi),PARAMETER :: Ref_WS = 10.0 +REAL(ReKi) :: Scale1 +REAL(ReKi) :: Scale2 +REAL(ReKi) :: Temp +!mlb REAL(ReKi) :: FLU2 +!mlb REAL(ReKi) :: L1_U +!mlb REAL :: X0=10.0 ! Added by Y. Guo for calculating UHr_10 +!mlb REAL :: X +INTEGER :: I +!mlb REAL :: UHr_10 + + ! Set up scaling values. + + ! calculate the spectra for the v and w components using IECKAI model + ! because API doesn't specify a spectra for those components +CALL Spec_IECKAI ( p%UHub, p%IEC%SigmaIEC, p%IEC%IntegralScale, p%grid%Freq, p%grid%NumFreq, Spec ) + + ! Define u-component integral scale. +!CALL WrScr ('Calling Froya/API wind spectrum.............') +!mlb L1_U = 3.5*Lambda/p%UHub +!mlb SigmaL1_U = 2.0*SigmaIEC(1)*p%UHub*L1_U + +!mlb CALL ROOT_SEARCHING(X0,X,p%UHub,Ht,Ht) +!mlb UHr_10=X; + + ! Compute some parameters that are independent of frequency. + +Scale1 = 172.0*( Ht/Ref_Ht )**(2.0/3.0) * ( p%met%URef/Ref_WS )**(-0.75) +Scale2 = 320.0*( p%met%URef/Ref_WS )**2 * ( Ht/Ref_Ht )**0.45 + +DO I=1,p%grid%NumFreq + + +!mlb Tmp1 = 172.0*p%grid%Freq(I)*(Ht/10.0)**Exp2*(UHr_10/10.0)**Exp3 +!mlb Tmp2 = (1.0+Tmp1**Exp1)**(5.0/3.0/Exp1) +!mlb +!mlb Spec(I,1) = 320.0*(UHr_10/10.0)**2*(Ht/10.0)**Exp4/Tmp2 + + Temp = Scale1*p%grid%Freq(I) + Spec(I,1) = Scale2/( 1.0 + Temp**N )**Exp5 + +ENDDO ! I + +!CALL WrScr ('Froya/API wind spectrum generated') + +RETURN +END SUBROUTINE Spec_API +!======================================================================= +!> This subroutine defines the 3-D turbulence spectrum that can be expected over terrain +!! and heights similiar to the LLLJP project as developed by Neil Kelley & Bonnie Jonkman at NREL. +!! The use of this subroutine requires that variables have the units of meters and seconds. +SUBROUTINE Spec_GPLLJ ( p, Ht, Ucmp, ZL_tmp, UStar_tmp, Spec ) + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN) :: Ht !< Height (local) + REAL(ReKi), INTENT(IN) :: Ucmp !< Longitudinal Velocity (local) + REAL(ReKi), INTENT(IN) :: Ustar_tmp !< Local ustar + REAL(ReKi), INTENT(IN) :: ZL_tmp !< Local z/l + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Output: target spectrum + + + ! Internal variables + +REAL(ReKi), PARAMETER :: Exp53 = 5.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp23 = 2.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp32 = 3.0 / 2.0 +REAL(ReKi) :: fi ! Temporary variable for calculation of Spec +REAL(ReKi) :: fr ! Temporary variable for calculation of Spec +REAL(ReKi) :: Freq2 ! Temporary variable for the reduced frequency squared +REAL(ReKi) :: fr_ih(3) ! Scaling for high-frequency peak location +REAL(ReKi) :: fr_il(3) ! Scaling for low-frequency peak location +REAL(ReKi) :: HtZI ! Temporary variable for calculation of Spec +REAL(ReKi) :: HtZI2 ! Temporary variable for calculation of Spec +REAL(ReKi) :: phiE +REAL(ReKi) :: phiM ! Non-Dimensional Wind Shear +REAL(ReKi) :: Pr_ih(3) ! Scaling for magnitude of high-frequency peak +REAL(ReKi) :: Pr_il(3) ! Scaling for magnitude of low-frequency peak +REAL(ReKi) :: ps_h +REAL(ReKi) :: ps_l +REAL(ReKi), PARAMETER :: Scales(2,3) = RESHAPE( (/ 79.0, 13.0, 3.5, & + 263.0, 32.0, 8.6 /), & + SHAPE=(/2,3/), ORDER=(/2,1/) ) +REAL(ReKi) :: tmpF ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpFw ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpX ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpPhi ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZIL ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZIU ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZU ! Temporary variable for calculation of Spec +REAL(ReKi) :: UDen +REAL(ReKi) :: Ustar_loc ! Local ustar +REAL(ReKi) :: uStar2 ! Temporary variable holding Ustar-squared +REAL(ReKi) :: Ustar2F +REAL(ReKi) :: VDen +REAL(ReKi) :: X_h +REAL(ReKi) :: X_l +REAL(ReKi) :: ZL_loc ! Local z/l + +INTEGER :: I ! DO LOOP counter +INTEGER :: IC ! DO LOOP counter + +uStar2 = Ustar_tmp * Ustar_tmp ! We don't use ustar_loc here b/c this ustar_loc was used to calculate non-dimensional spectral; this is to scale to dimensional values + +ustar_loc = MAX( MIN(ustar_tmp, REAL(1.0,ReKi) ), REAL( 0.15,ReKi) ) ! make sure ustar does not go beyond the observed range that the values were calcualted over +zl_loc = MAX( MIN(zl_tmp, REAL(1.0,ReKi) ), REAL(-1.00,ReKi) ) ! make sure z/l does not go beyond the calculated range + + +IF (zL_loc >= 0) THEN + + phiM = 1.0 + 4.7*(zL_loc) ! = q + phiE = (1.0 + 2.5*(zL_loc)**0.6)**Exp32 + + zl_loc = MAX( zl_loc, REAL(0.025,ReKi) ) !This will prevent 0**-x from becoming infinite. ustar_loc has this built in already. This value is the observed min here anyway. + + ! Calculate NEUTRAL/STABLE spectral estimates + + fr_il(1) = 0.014746*( zl_loc**(-0.37495232))*(ustar_loc**(-0.6167086) )*exp(-0.994591040*zl_loc+1.676298830*ustar_loc) + fr_ih(1) = 0.043108*( zl_loc**(-0.39311528))*(ustar_loc**(-2.1719048) )*exp( 0.152732100*zl_loc+2.939119120*ustar_loc) + Pr_il(1) = 0.003043*( zl_loc**(-0.60526081))*(ustar_loc**(-2.4348077) )*exp( 1.386013230*zl_loc+2.185372290*ustar_loc) + Pr_ih(1) = 15.468066*( zl_loc**( 0.27375765))*(ustar_loc**( 1.8091998) )*exp(-0.266223760*zl_loc-3.091731900*ustar_loc) + + fr_il(2) = 0.0008437*( zl_loc**(-0.79592929))*(ustar_loc**(-1.78297586))*exp( 1.316511335*zl_loc+0.175154746*ustar_loc) + fr_ih(2) = 1.5278523*( zl_loc**(-0.14197939))*(ustar_loc**( 0.02684469))*exp(-0.261902952*zl_loc-0.672772974*ustar_loc) + Pr_il(2) = 0.0222952*( zl_loc**( 0.18448738))*(ustar_loc**(-2.23473414))*exp(-1.216594402*zl_loc+1.491864128*ustar_loc) + Pr_ih(2) = 1.6568440*( zl_loc**(-0.03919916))*(ustar_loc**( 0.57537263))*exp(+0.282805584*zl_loc-1.199845489*ustar_loc) + + fr_il(3) = 1. + fr_ih(3) = 0.97627403*(zl_loc**(-0.05470045))*(ustar_loc**(0.09666427) )*exp(-0.301255210*zl_loc-0.063122900*ustar_loc) + Pr_il(3) = 0. + Pr_ih(3) = 0.69547455*(zl_loc**(-0.00800265))*(ustar_loc**(-0.1352012) )*exp( 0.041784840*zl_loc-0.003785870*ustar_loc) + + fr_il(1) = MAX( MIN( fr_il(1), REAL(0.30,ReKi) ), REAL(0.015,ReKi) ) + fr_ih(1) = MAX( MIN( fr_ih(1), REAL(2.5 ,ReKi) ), REAL(1.25 ,ReKi) ) + Pr_il(1) = MAX( MIN( Pr_il(1), REAL(0.75,ReKi) ), REAL(0.1 ,ReKi) ) + Pr_ih(1) = MAX( MIN( Pr_ih(1), REAL(0.75,ReKi) ), REAL(0.25 ,ReKi) ) + + fr_il(2) = MAX( MIN( fr_il(2), REAL(0.3 ,ReKi) ), REAL(0.005,ReKi) ) + fr_ih(2) = MAX( MIN( fr_ih(2), REAL(2.5 ,ReKi) ), REAL(0.75 ,ReKi) ) + Pr_il(2) = MAX( MIN( Pr_il(2), REAL(1.4 ,ReKi) ), REAL(0.05 ,ReKi) ) + Pr_ih(2) = MAX( MIN( Pr_ih(2), REAL(1.0 ,ReKi) ), REAL(0.5 ,ReKi) ) + + fr_ih(3) = MAX( MIN( fr_ih(3), REAL(1.4 ,ReKi) ), REAL(0.5 ,ReKi) ) + Pr_ih(3) = MAX( MIN( Pr_ih(3), REAL(1.1 ,ReKi) ), REAL(0.6 ,ReKi) ) + + tmpPhi = ( (phiE / phiM)**Exp23 ) + tmpF = Ht / (Ucmp * phiM) + + + DO IC = 1,3 ! Wind components + DO I = 1,p%grid%NumFreq + tmpX = p%grid%Freq(I)*tmpF ! reduced frequency divided by q (q = phiM here) + X_l = tmpX/fr_il(ic) + X_h = tmpX/fr_ih(ic) + + ps_l = (Pr_il(ic)*scales(1,ic)*X_l*tmpPhi) / (1.0 + scales(2,ic)*X_l**Exp53); + ps_h = (Pr_ih(ic)*scales(1,ic)*X_h*tmpPhi) / (1.0 + scales(2,ic)*X_h**Exp53); + + Spec(I,IC) = (ps_l + ps_h)*uStar2/p%grid%Freq(I) + ENDDO + ENDDO + + +ELSE + ! Calculate UNSTABLE spectral estimates + fr_il(:) = 1. + fr_ih(:) = 1. + Pr_il(:) = 1. + Pr_ih(:) = 1. + +! THESE VALUES ARE BASED ON A SMALL AMOUNT OF DATA AND DON'T SEEM TO BEHAVE VERY WELL FOR THE GENERAL CASE. +! Using 1 for each of these values creates the spectral estimates for the SMOOTH model. +! +! nzl = -zl_loc +! +! fr_il(1) = MIN(10.0, 0.0443117*( (nzl)**(-0.42429))*(ustar_loc**(- 2.03969))*exp( 7.18271*(nzl)+ 1.11017*ustar_loc)) +! fr_ih(1) = MIN( 5.0, 1.10957*( (nzl)**( 0.18200))*(ustar_loc**(- 0.13968))*exp( 2.48651*(nzl)+ 0.88788*ustar_loc)) +! Pr_il(1) = MIN(20.0, 1.08387e-004*((nzl)**( 0.32784))*(ustar_loc**(- 6.69897))*exp(-8.25590*(nzl)+14.46554*ustar_loc)) +! Pr_ih(1) = MIN( 5.0, 0.0870653*( (nzl)**(-0.55618))*(ustar_loc**(- 0.85499))*exp( 3.66686*(nzl)- 0.34810*ustar_loc)) +! +! fr_il(2) = MIN( 5.0, 2.8412e-013*( (nzl)**(-0.43587))*(ustar_loc**(-14.62097))*exp( 2.41002*(nzl)+31.59745*ustar_loc)) +! fr_ih(2) = MIN( 5.0, 0.12219003 *( (nzl)**(-0.20010))*(ustar_loc**(- 1.11780))*exp( 1.66314*(nzl)+ 1.74815*ustar_loc)) +! Pr_il(2) = MIN(10.0, 6.6853e-018*( (nzl)**(-1.48280))*(ustar_loc**(-18.80570))*exp( 9.92010*(nzl)+41.12724*ustar_loc)) +! Pr_ih(2) = MIN( 5.0, 2.47627547 *( (nzl)**( 0.04305))*(ustar_loc**(- 0.01287))*exp(-2.74234*(nzl)- 0.95780*ustar_loc)) +! +! fr_il(3) = MIN(30.0, 2.66408e-004*((nzl)**(-0.65260))*(ustar_loc**(- 4.82119))*exp( 7.08116*(nzl)+ 5.85913*ustar_loc)) +! fr_ih(3) = MIN( 5.0, 0.0118916* ( (nzl)**( 0.09544))*(ustar_loc**(- 2.82943))*exp(-3.21429*(nzl)+ 5.95403*ustar_loc)) +! Pr_il(3) = MIN(10.0, 3.6709e-011*( (nzl)**(-0.96751))*(ustar_loc**(-11.48936))*exp( 5.06644*(nzl)+26.26320*ustar_loc)) +! Pr_ih(3) = MIN( 5.0, 13.53430* ( (nzl)**(-0.14450))*(ustar_loc**( 1.32560))*exp( 1.66323*(nzl)- 4.28085*ustar_loc)) + + tmpZIL = ( ABS(p%met%ZI / p%met%L) )**Exp23 + HtZI = Ht / p%met%ZI + + tmpZIU = p%met%ZI / Ucmp + tmpZU = Ht / Ucmp + HtZI2 = (1.0 - HtZI)**2 + UDen = 1.0 + 15.0*HtZI + VDen = 1.0 + 2.8*HtZI + + DO I=1,p%grid%NumFreq + fi = p%grid%Freq(I)*tmpZIU + tmpF = p%grid%Freq(I)*tmpZU ! reduced frequency + Ustar2F = uStar2/p%grid%Freq(I) ! Normalizing term + + ! u component + + fr = tmpF/UDen + X_l = fi/fr_il(1) + X_h = fr/fr_ih(1) + + ps_l = (Pr_il(1)* tmpZIL * 0.50*X_l)/( 1.0 + 2.2*X_l**Exp53 ) + ps_h = (Pr_ih(1)*(HtZI2/(UDen**Exp23))*105.00*X_h)/((1.0 + 33.0*X_h)**Exp53) + + Spec(I,1) = (ps_l + ps_h) * Ustar2F + + + ! v component + + fr = tmpF/VDen + X_l = fi/fr_il(2) + X_h = fr/fr_ih(2) + + ps_l = (Pr_il(2)* tmpZIL * 0.95*X_l)/((1.0 + 2.0*X_l)**Exp53) + ps_h = (Pr_ih(2)*(HtZI2/(VDen**Exp23))* 17.00*X_h)/((1.0 + 9.5*X_h)**Exp53) + + Spec(I,2) = (ps_l + ps_h) * Ustar2F + + + ! w component + + Freq2 = tmpF**2 + tmpFw = SQRT( (Freq2 + (0.3*HtZI)**2 ) / (Freq2 + 0.15**2) ) + X_l = fi /fr_il(3) + X_h = tmpF/fr_ih(3) + + ps_l = tmpFw*(Pr_il(3)*tmpZIL*0.95*X_l)/((1.0 + 2.0*X_l)**Exp53) + ps_h = (Pr_ih(3)*HtZI2 *2.00*X_h)/( 1.0 + 5.3*X_h**Exp53 ) + + Spec(I,3) = (ps_l + ps_h) * Ustar2F + + ENDDO +ENDIF + + +RETURN +END SUBROUTINE Spec_GPLLJ +!======================================================================= +!> This subroutine defines the 3-D turbulence spectrum that can be expected +!! over terrain and heights similiar to the NWTC LIST project as developed +!! by Neil Kelley & Bonnie Jonkman at NREL. The use of this subroutine +!! requires that variables have the units of meters and seconds. +SUBROUTINE Spec_NWTCUP ( p, Ht, Ucmp, Spec ) + + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Height (local) + REAL(ReKi), INTENT(IN ) :: Ucmp !< Longitudinal Velocity (local) + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Output: target spectrum + + + + ! Internal variables + +REAL(ReKi), PARAMETER :: Exp53 = 5.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp23 = 2.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp32 = 3.0 / 2.0 +REAL(ReKi) :: fi ! Temporary variable for calculation of Spec +REAL(ReKi) :: fr ! Temporary variable for calculation of Spec +REAL(ReKi) :: Freq2 ! Temporary variable for the reduced frequency squared +REAL(ReKi) :: fr_ih(3) ! Scaling for high-frequency peak location +REAL(ReKi) :: fr_il(3) ! Scaling for low-frequency peak location +REAL(ReKi) :: HtZI ! Temporary variable for calculation of Spec +REAL(ReKi) :: HtZI2 ! Temporary variable for calculation of Spec +REAL(ReKi) :: phiE +REAL(ReKi) :: phiM ! Non-Dimensional Wind Shear +REAL(ReKi) :: Pr_ih(3) ! Scaling for magnitude of high-frequency peak +REAL(ReKi) :: Pr_il(3) ! Scaling for magnitude of low-frequency peak +REAL(ReKi) :: ps_h +REAL(ReKi) :: ps_l +REAL(ReKi), PARAMETER :: Scales(2,3) = RESHAPE( (/ 79.0, 13.0, 3.5, & + 263.0, 32.0, 8.6 /), & + SHAPE=(/2,3/), ORDER=(/2,1/) ) +REAL(ReKi) :: tmpF ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpFw ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpX ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpPhi ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZIL ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZIU ! Temporary variable for calculation of Spec +REAL(ReKi) :: tmpZU ! Temporary variable for calculation of Spec +REAL(ReKi) :: UDen +REAL(ReKi) :: Ustar_tmp ! Disk-averaged ustar, limited by the observed range of values for fitting these emperical functions +REAL(ReKi) :: uStar2 ! Temporary variable holding Ustar-squared +REAL(ReKi) :: Ustar2F +REAL(ReKi) :: VDen +REAL(ReKi) :: X_h +REAL(ReKi) :: X_l +REAL(ReKi) :: ZL_tmp ! Disk-averaged z/l, limited by the observed range of z/l for fitting these emperical functions + +INTEGER :: I ! DO LOOP counter +INTEGER :: IC ! DO LOOP counter + +uStar2 = p%met%Ustar * p%met%Ustar + +IF (p%met%zL >= 0) THEN + + zl_tmp = max( min(p%met%zl, 3.5_ReKi ), 0.005_ReKi ) + + ! Calculate NEUTRAL/STABLE spectral estimates + + fr_il(1) = 0.096376774*(zl_tmp**(-0.315715361)) * exp(-0.385026736*zl_tmp) + fr_ih(1) = 1.690996304*(zl_tmp**(-0.340366943)) * exp(-0.132661086*zl_tmp) + Pr_il(1) = 1.209487882*(zl_tmp**( 0.052273494)) * exp( 0.189014328*zl_tmp) + Pr_ih(1) = 0.224103219*(zl_tmp**( 0.169561956)) * exp( 0.222723480*zl_tmp) + + fr_il(2) = 0.032285308*(zl_tmp**(-0.387804427)) * exp(-0.388660410*zl_tmp) + fr_ih(2) = 0.473438689*(zl_tmp**(-0.441450751)) * exp( 0.290697895*zl_tmp) + Pr_il(2) = 1.285421087*(zl_tmp**( 0.006644801)) * exp( 0.354496483*zl_tmp) + Pr_ih(2) = 0.991251080*(zl_tmp**( 0.343831230)) * exp(-0.605373943*zl_tmp) + + fr_il(3) = 0.097156827*(zl_tmp**(-0.096412942)) * exp(-0.616256651*zl_tmp) + fr_ih(3) = 0.469904415*(zl_tmp**(-0.218253779)) * exp(-0.157526974*zl_tmp) + Pr_il(3) = 0.368138932*(zl_tmp**( 0.093776256)) * exp( 0.109020969*zl_tmp) + Pr_ih(3) = 0.638868926*(zl_tmp**( 0.035396647)) * exp(-0.031884105*zl_tmp) + + fr_il(1) = MAX( MIN( fr_il(1),REAL( 0.40,ReKi) ), REAL(0.015,ReKi) ) + fr_ih(1) = MAX( MIN( fr_ih(1),REAL(10.0 ,ReKi) ), REAL(0.35 ,ReKi) ) + Pr_il(1) = MAX( MIN( Pr_il(1),REAL( 2.25,ReKi) ), REAL(0.8 ,ReKi) ) + Pr_ih(1) = MAX( MIN( Pr_ih(1),REAL( 0.8 ,ReKi) ), REAL(0.05 ,ReKi) ) + + fr_il(2) = MAX( MIN( fr_il(2),REAL( 0.23,ReKi) ), REAL(0.003,ReKi) ) + fr_ih(2) = MAX( MIN( fr_ih(2),REAL( 3.0 ,ReKi) ), REAL(0.25 ,ReKi) ) + Pr_il(2) = MAX( MIN( Pr_il(2),REAL( 2.25,ReKi) ), REAL(0.95 ,ReKi) ) + Pr_ih(2) = MAX( MIN( Pr_ih(2),REAL( 1.0 ,ReKi) ), REAL(0.2 ,ReKi) ) + + fr_il(3) = MAX( MIN( fr_il(3),REAL( 0.175,ReKi)), REAL(0.006,ReKi) ) + fr_ih(3) = MAX( MIN( fr_ih(3),REAL( 1.25 ,ReKi)), REAL(0.2 ,ReKi) ) + Pr_il(3) = MAX( MIN( Pr_il(3),REAL( 0.75 ,ReKi)), REAL(0.2 ,ReKi) ) + Pr_ih(3) = MAX( MIN( Pr_ih(3),REAL( 1.0 ,ReKi)), REAL(0.25 ,ReKi) ) + + phiM = 1.0 + 4.7*(zl_tmp) ! = q + phiE = (1.0 + 2.5*(zl_tmp)**0.6)**Exp32 + + tmpPhi = ( (phiE / phiM)**Exp23 ) + tmpF = Ht / (Ucmp * phiM) + + + DO IC = 1,3 ! Wind components + DO I = 1,p%grid%NumFreq + tmpX = p%grid%Freq(I)*tmpF ! reduced frequency divided by q (q = phiM here) + X_l = tmpX/fr_il(ic) + X_h = tmpX/fr_ih(ic) + + ps_l = (Pr_il(ic)*scales(1,ic)*X_l*tmpPhi) / (1.0 + scales(2,ic)*X_l**Exp53); + ps_h = (Pr_ih(ic)*scales(1,ic)*X_h*tmpPhi) / (1.0 + scales(2,ic)*X_h**Exp53); + + Spec(I,IC) = (ps_l + ps_h)*uStar2/p%grid%Freq(I) + ENDDO + ENDDO + + +ELSE + ! Calculate UNSTABLE spectral estimates + + zl_tmp = abs( min( max( p%met%zl ,REAL(-0.5,ReKi) ),REAL( -0.025,ReKi) ) ) + ustar_tmp = max( min(p%met%ustar,REAL( 1.4,ReKi) ),REAL( 0.2 ,ReKi) ) + + fr_il(1) = 0.08825035*(zl_tmp**(-0.08806865))*(ustar_tmp**(-0.26295052))*exp( 1.74135233*zl_tmp + 1.86785832*ustar_tmp) + fr_ih(1) = 1.34307411*(zl_tmp**(-0.55126969))*(ustar_tmp**(-0.07034031))*exp( 0.40185202*zl_tmp - 0.55083463*ustar_tmp) + Pr_il(1) = 57.51578485*(zl_tmp**(-1.89080610))*(ustar_tmp**( 4.03260796))*exp( 6.09158000*zl_tmp - 7.47414385*ustar_tmp) + Pr_ih(1) = 4.52702491*(zl_tmp**( 0.72447070))*(ustar_tmp**(-0.10602646))*exp(-3.73265876*zl_tmp - 0.49429015*ustar_tmp) + + fr_il(2) = 0.58374913*(zl_tmp**(-0.53220033))*(ustar_tmp**( 1.49509302))*exp( 3.61867635*zl_tmp - 0.98540722*ustar_tmp) + fr_ih(2) = 4.30596626*(zl_tmp**( 0.31302745))*(ustar_tmp**(-0.26457011))*exp(-1.41513284*zl_tmp + 0.91503248*ustar_tmp) + Pr_il(2) = 32.06436225*(zl_tmp**(-1.43676866))*(ustar_tmp**( 3.57797045))*exp( 5.31617813*zl_tmp - 5.76800891*ustar_tmp) + Pr_ih(2) = 3.93109762*(zl_tmp**( 0.57974534))*(ustar_tmp**(-0.20510478))*exp(-4.85367443*zl_tmp - 0.61610914*ustar_tmp) + + fr_il(3) = 0.81092087*(zl_tmp**(-0.03483105))*(ustar_tmp**( 0.58332966))*exp(-0.10731274*zl_tmp - 0.16463702*ustar_tmp) + fr_ih(3) = 1.05515450*(zl_tmp**(-0.25002535))*(ustar_tmp**( 0.14528047))*exp( 1.00641958*zl_tmp - 0.67569359*ustar_tmp) + Pr_il(3) = 6.60003543*(zl_tmp**(-0.45005503))*(ustar_tmp**( 1.35937877))*exp( 2.45632937*zl_tmp - 1.98267575*ustar_tmp) + Pr_ih(3) = 16.56290180*(zl_tmp**( 0.40464339))*(ustar_tmp**( 0.82276250))*exp(-3.92300971*zl_tmp - 1.82957067*ustar_tmp) + + + fr_il(1) = MAX( MIN( fr_il(1), REAL(1.50,ReKi) ), REAL(0.2 ,ReKi) ) + fr_ih(1) = MAX( MIN( fr_ih(1), REAL(8.0 ,ReKi) ), REAL(0.1 ,ReKi) ) + Pr_il(1) = MAX( MIN( Pr_il(1), REAL(8.0 ,ReKi) ), REAL(1.0 ,ReKi) ) + Pr_ih(1) = MAX( MIN( Pr_ih(1), REAL(1.2 ,ReKi) ), REAL(0.1 ,ReKi) ) + + fr_il(2) = MAX( MIN( fr_il(2), REAL(2.3 ,ReKi) ), REAL(0.12,ReKi) ) + fr_ih(2) = MAX( MIN( fr_ih(2), REAL(7.5 ,ReKi) ), REAL(1.8 ,ReKi) ) + Pr_il(2) = MAX( MIN( Pr_il(2), REAL(8.0 ,ReKi) ), REAL(0.2 ,ReKi) ) + Pr_ih(2) = MAX( MIN( Pr_ih(2), REAL(0.9 ,ReKi) ), REAL(0.2 ,ReKi) ) + + fr_il(3) = MAX( MIN( fr_il(3), REAL(1.4 ,ReKi) ), REAL(0.2 ,ReKi) ) + fr_ih(3) = MAX( MIN( fr_ih(3), REAL(1.75,ReKi) ), REAL(0.95,ReKi) ) + Pr_il(3) = MAX( MIN( Pr_il(3), REAL(7.0 ,ReKi) ), REAL(1.0 ,ReKi) ) + Pr_ih(3) = MAX( MIN( Pr_ih(3), REAL(1.0 ,ReKi) ), REAL(0.3 ,ReKi) ) + + tmpZIL = (-p%met%ZI / p%met%L)**Exp23 + HtZI = Ht / p%met%ZI + + tmpZIU = p%met%ZI / Ucmp + tmpZU = Ht / Ucmp + HtZI2 = (1.0 - HtZI)**2 + UDen = 1.0 + 15.0*HtZI + VDen = 1.0 + 2.8*HtZI + + DO I=1,p%grid%NumFreq + fi = p%grid%Freq(I)*tmpZIU + + tmpF = p%grid%Freq(I)*tmpZU ! reduced frequency + Ustar2F = uStar2/p%grid%Freq(I) ! Normalizing term + + ! u component + + fr = tmpF/UDen + X_l = fi/fr_il(1) + X_h = fr/fr_ih(1) + + ps_l = (Pr_il(1)* tmpZIL * 0.50*X_l)/( 1.0 + 2.2*X_l**Exp53 ) + ps_h = (Pr_ih(1)*(HtZI2/(UDen**Exp23))*105.00*X_h)/((1.0 + 33.0*X_h)**Exp53) + + Spec(I,1) = (ps_l + ps_h) * Ustar2F + + + ! v component + + fr = tmpF/VDen + X_l = fi/fr_il(2) + X_h = fr/fr_ih(2) + + ps_l = (Pr_il(2)* tmpZIL * 0.95*X_l)/((1.0 + 2.0*X_l)**Exp53) + ps_h = (Pr_ih(2)*(HtZI2/(VDen**Exp23))* 17.00*X_h)/((1.0 + 9.5*X_h)**Exp53) + + Spec(I,2) = (ps_l + ps_h) * Ustar2F + + + ! w component + + Freq2 = tmpF**2 + tmpFw = SQRT( (Freq2 + (0.3*HtZI)**2 ) / (Freq2 + 0.15**2) ) + X_l = fi /fr_il(3) + X_h = tmpF/fr_ih(3) + + ps_l = tmpFw*(Pr_il(3)*tmpZIL*0.95*X_l)/((1.0 + 2.0*X_l)**Exp53) + ps_h = (Pr_ih(3)*HtZI2 *2.00*X_h)/( 1.0 + 5.3*X_h**Exp53 ) + + Spec(I,3) = (ps_l + ps_h) * Ustar2F + + ENDDO +ENDIF + + +RETURN + +END SUBROUTINE Spec_NWTCUP +!======================================================================= +!> This routine gets velocity spectra for each of 3 wind components (u,v,w) +!! by 2-D interpolation. +SUBROUTINE Spec_TimeSer ( p, Ht, Ucmp, LastIndex, Spec ) + + + ! Passed variables + TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Input: height for which spectra are requested + REAL(ReKi), INTENT(IN ) :: Ucmp !< Input: wind speed for which spectra are requested (used for missing components) + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(2) !< Index for the last (Freq, Ht) used + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Output: target spectrum (Frequency, component) + ! Local variables + REAL(ReKi) :: InCoord(2) ! Arranged as (Freq, Ht) + INTEGER(IntKi) :: i ! loop counters + + + +!bjj: fix me!!! (make use of nComp and height ) + + ! initialize Spec with extrapolated values on non-specified components or frequencies + ! i.e., fill the gaps where wind component or frequencies exceed what was specified in the time-series data with some numerical model + ! (or use zeros for known spectral values that will get overwritten later) + CALL Spec_TimeSer_Extrap ( p, Ht, Ucmp, Spec ) + + + InCoord(2) = Ht + + ! overwrite Spec at the frequencies and wind components by interpolating from known points + DO I=1,p%usr%nFreq !p%grid%NumFreq ! note that this assumes TMax = AnalysisTime (i.e., we have the same delta frequencies) + + InCoord(1) = p%grid%Freq(i) + CALL UserSpec_Interp2D( InCoord, p%usr, LastIndex, Spec(I,:) ) ! sets only Spec(1:p%usr%nFreq, 1:p%usr%nComp) values + + ENDDO ! I + + RETURN + + +END SUBROUTINE Spec_TimeSer +!======================================================================= +!< This routine adds high-frequency content to user-supplied data, +!! using the model specified in p%usr%TurbModel_ID +SUBROUTINE Spec_TimeSer_Extrap ( p, Ht, Ucmp, Spec ) + + + ! Passed variables + TYPE(TurbSim_ParameterType), INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Input: height for which spectra are requested + REAL(ReKi), INTENT(IN ) :: Ucmp !< Input: wind speed for which spectra are requested (used for missing components) + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Output: target spectrum (Frequency, component) + + + IF ( p%usr%nComp < 3 .OR. p%usr%nFreq < p%grid%NumFreq ) THEN + + SELECT CASE ( p%usr%TurbModel_ID ) + CASE ( SpecModel_IECKAI ) ! IECKAI has uniform spectra (does not vary with height or velocity) + CALL Spec_IECKAI ( p%UHub, p%IEC%SigmaIEC, p%IEC%IntegralScale, p%grid%Freq, p%grid%NumFreq, Spec ) + + CASE ( SpecModel_IECVKM ) ! IECVKM has uniform spectra (does not vary with height or velocity) + CALL Spec_IECVKM ( p%UHub, p%IEC%SigmaIEC(1), p%IEC%IntegralScale, p%grid%Freq, p%grid%NumFreq, Spec ) + + CASE ( SpecModel_API ) + CALL Spec_API ( p, Ht, Spec ) + + CASE ( SpecModel_SMOOTH ) + CALL Spec_SMOOTH ( p, Ht, Ucmp, Spec ) + + CASE DEFAULT + Spec = 0.0_ReKi ! whole matrix is zero + + END SELECT + + ELSE + Spec = 0.0_ReKi ! whole matrix is zero + END IF + +END SUBROUTINE Spec_TimeSer_Extrap +!======================================================================= +!< This routine linearly interpolates the p%usr spectral data. It is +!! set for a 2-d interpolation on frequency and height of the input point. +!! p%usr%f and p%usr%pointzi must be in increasing order. Each dimension +!! may contain only 1 value. +SUBROUTINE UserSpec_Interp2D( InCoord, p_usr, LastIndex, OutSpec ) + + ! I/O variables + + REAL(ReKi), INTENT(IN ) :: InCoord(2) !< Arranged as (Freq, Ht) + TYPE(UserTSSpec_ParameterType), INTENT(IN ) :: p_usr !< + INTEGER(IntKi), INTENT(INOUT) :: LastIndex(2) !< Index for the last (Freq, Ht) used + REAL(ReKi), INTENT(INOUT) :: OutSpec(3) !< The interpolated resulting PSD from each component of p%usr%S(:,:,1-3) + + + ! Local variables + + INTEGER(IntKi) :: I ! loop counter + INTEGER(IntKi) :: Indx_Lo(2) ! index associated with lower bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + INTEGER(IntKi) :: Indx_Hi(2) ! index associated with upper bound of dimension 1,2 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + REAL(ReKi) :: Pos_Lo(2) ! coordinate value with lower bound of dimension 1,2 + REAL(ReKi) :: Pos_Hi(2) ! coordinate value with upper bound of dimension 1,2 + + REAL(ReKi) :: isopc(2) ! isoparametric coordinates + + REAL(ReKi) :: N(4) ! size 2^n + REAL(ReKi) :: u(4) ! size 2^n + + + + ! find the indices into the arrays representing coordinates of each dimension: + ! (by using LocateStp, we do not require equally spaced frequencies or points) + + CALL LocateStp( InCoord(1), p_usr%f, LastIndex(1), p_usr%nFreq ) + CALL LocateStp( InCoord(2), p_usr%pointzi, LastIndex(2), p_usr%nPoints ) + + Indx_Lo = LastIndex ! at this point, 0 <= Indx_Lo(i) <= n(i) for all i + + + ! Frequency (indx 1) + IF (Indx_Lo(1) == 0) THEN + Indx_Lo(1) = 1 + ELSEIF (Indx_Lo(1) == p_usr%nFreq ) THEN + Indx_Lo(1) = max( p_usr%nFreq - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(1) = min( Indx_Lo(1) + 1 , p_usr%nFreq ) ! make sure it's a valid index + + ! Height (indx 2) + IF (Indx_Lo(2) == 0) THEN + Indx_Lo(2) = 1 + ELSEIF (Indx_Lo(2) == p_usr%nPoints ) THEN + Indx_Lo(2) = max( p_usr%nPoints - 1, 1 ) ! make sure it's a valid index + END IF + Indx_Hi(2) = min( Indx_Lo(2) + 1 , p_usr%nPoints ) ! make sure it's a valid index + + + ! calculate the bounding box; the positions of all dimensions: + + pos_Lo(1) = p_usr%f( Indx_Lo(1) ) + pos_Hi(1) = p_usr%f( Indx_Hi(1) ) + + pos_Lo(2) = p_usr%pointzi( Indx_Lo(2) ) ! note that this assumes z are in increasing order + pos_Hi(2) = p_usr%pointzi (Indx_Hi(2) ) + + + ! 2-D linear interpolation: + + CALL IsoparametricCoords( InCoord, pos_Lo, pos_Hi, isopc ) ! Calculate iospc + + N(1) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi - isopc(2) ) + N(2) = ( 1.0_ReKi + isopc(1) )*( 1.0_ReKi + isopc(2) ) + N(3) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi + isopc(2) ) + N(4) = ( 1.0_ReKi - isopc(1) )*( 1.0_ReKi - isopc(2) ) + N = N / REAL( SIZE(N), ReKi ) ! normalize + + + do i = 1,p_usr%nComp + u(1) = p_usr%S( Indx_Hi(1), Indx_Lo(2), i ) + u(2) = p_usr%S( Indx_Hi(1), Indx_Hi(2), i ) + u(3) = p_usr%S( Indx_Lo(1), Indx_Hi(2), i ) + u(4) = p_usr%S( Indx_Lo(1), Indx_Lo(2), i ) + + OutSpec(i) = SUM ( N * u ) + end do + + +END SUBROUTINE UserSpec_Interp2D +!======================================================================= +!> This routine linearly interpolates data from an input file that +!! specifies the velocity spectra for each of 3 wind components (u,v,w) +SUBROUTINE Spec_UserSpec ( p, Spec ) + + IMPLICIT NONE + + ! Passed variables + type(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Output: target spectrum + + ! Internal variables + + REAL(ReKi) :: Tmp + + + INTEGER :: I + INTEGER :: Indx + INTEGER :: J + INTEGER,PARAMETER :: iPoint = 1 + + ! --------- Interpolate to the desired frequencies --------------- + + Indx = 1; + + DO I=1,p%grid%NumFreq + + IF ( p%grid%Freq(I) <= p%usr%f(1) ) THEN + Spec(I,:) = p%usr%S(1,iPoint,:) + ELSEIF ( p%grid%Freq(I) >= p%usr%f(p%usr%nFreq) ) THEN + Spec(I,:) = p%usr%S(p%usr%nFreq,iPoint,:) + ELSE + + ! Find the two points between which the frequency lies + + DO J=(Indx+1),p%usr%nFreq + IF ( p%grid%Freq(I) <= p%usr%f(J) ) THEN + Indx = J-1 + + ! Let's just do a linear interpolation for now + + Tmp = (p%grid%Freq(I) - p%usr%f(Indx)) / ( p%usr%f(Indx) - p%usr%f(J) ) + + Spec(I,:) = Tmp * ( p%usr%S(Indx,iPoint,:) - p%usr%S(J,iPoint,:) ) + p%usr%S(Indx,iPoint,:) + + EXIT + ENDIF + ENDDO ! J + + ENDIF + + ENDDO ! I + + RETURN + + +END SUBROUTINE Spec_UserSpec +!======================================================================= +!> This subroutine defines the 3-D turbulence spectrum that can be expected over flat, +!! homogeneous terrain as developed by RISO authors Hojstrup, Olesen, and Larsen. +!! The use of this subroutine requires that variables have the units of meters and seconds. +SUBROUTINE Spec_SMOOTH ( p, Ht, Ucmp, Spec ) + + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Height + REAL(ReKi), INTENT(IN ) :: Ucmp !< Longitudinal Velocity + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< output: target spectra + + ! Internal variables + + REAL(ReKi), PARAMETER :: Exp1 = 5.0 / 3.0 + REAL(ReKi), PARAMETER :: Exp2 = 2.0 / 3.0 + REAL(ReKi), PARAMETER :: Exp3 = 3.0 / 2.0 + REAL(ReKi) :: fi ! Temporary variable for calculation of Spec + REAL(ReKi) :: fr ! Temporary variable for calculation of Spec + REAL(ReKi) :: HtZI ! Temporary variable for calculation of Spec + REAL(ReKi) :: HtZI2 ! Temporary variable for calculation of Spec + REAL(ReKi) :: phiE + REAL(ReKi) :: phiM ! Non-Dimensional Wind Shear + REAL(ReKi) :: ps_h + REAL(ReKi) :: ps_l + REAL(ReKi) :: tmpF ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpN ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpX ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpXX ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpPhi ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpZIL ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpZIU ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpZU ! Temporary variable for calculation of Spec + REAL(ReKi) :: UDen + REAL(ReKi) :: uStar2 ! Temporary variable holding Ustar-squared + REAL(ReKi) :: Ustar2F + REAL(ReKi) :: VDen + + INTEGER :: I ! DO LOOP counter + +uStar2 = p%met%Ustar * p%met%Ustar + +IF (p%met%zL >= 0) THEN + + ! Calculate NEUTRAL/STABLE spectral estimates + + phiM = 1.0 + 4.7*(p%met%zL) ! = q + phiE = (1.0 + 2.5*(p%met%zL)**0.6)**Exp3 + + tmpPhi = uStar2 * ( (phiE / phiM)**Exp2 ) + tmpF = Ht / (Ucmp * phiM) + + DO I = 1,p%grid%NumFreq + tmpX = p%grid%Freq(I)*tmpF ! reduced frequency divided by q (q = phiM here) + tmpXX = tmpX**Exp1 + tmpN = tmpPhi / p%grid%Freq(I) * tmpX ! normalization factor used to obtain power spectrum components + + Spec(I,1) = tmpN * (79.0) / (1.0 + 263.0*tmpXX) + Spec(I,2) = tmpN * (13.0) / (1.0 + 32.0*tmpXX) + Spec(I,3) = tmpN * ( 3.5) / (1.0 + 8.6*tmpXX) + ENDDO + +ELSE + ! Calculate UNSTABLE spectral estimates + tmpZIL = (- p%met%ZI / p%met%L)**Exp2 + HtZI = Ht / p%met%ZI + + HtZI2 = (1.0 - HtZI)**2 + tmpZU = Ht / Ucmp + tmpZIU = p%met%ZI / Ucmp + UDen = 1.0 + 15.0*HtZI + VDen = 1.0 + 2.8*HtZI + + DO I = 1,p%grid%NumFreq + + Fi = p%grid%Freq(I)*tmpZIU + tmpF = p%grid%Freq(I)*tmpZU ! reduced frequency + + Ustar2F = uStar2/p%grid%Freq(I) + + ! u component + Fr = tmpF / UDen + ps_l = ( ( 0.5*Fi) / (1.0 + 2.2* Fi**Exp1)) * tmpZIL + ps_h = ( (105.0*Fr) / (1.0 + 33.0*Fr )**Exp1 ) * HtZI2 / UDen**Exp2 + + Spec(I,1) = (ps_l + ps_h) * Ustar2F + + ! v component + Fr = tmpF / VDen + ps_l = ( ( 0.95*Fi) / (1.0 + 2.0*Fi)**Exp1 ) * tmpZIL + ps_h = ( (17.00*Fr) / (1.0 + 9.5*Fr)**Exp1 ) * HtZI2 / VDen**Exp2 + + Spec(I,2) = (ps_l + ps_h) * Ustar2F + + ! w component + tmpN = SQRT( (tmpF**2 + (0.3*HtZI)**2) / (tmpF**2 + 0.0225) ) + + ps_l = tmpN * ( (0.95*Fi ) / (1.0 + 2.0*Fi )**Exp1 ) * tmpZIL + ps_h = ( (2.00*tmpF) / (1.0 + 5.3*tmpF**Exp1)) * HtZI2 + + Spec(I,3) = (ps_l + ps_h) * Ustar2F + + ENDDO + +ENDIF + + +RETURN +END SUBROUTINE Spec_SMOOTH +!======================================================================= +!> This subroutine defines the 3-D turbulence expected in a tidal channel (HYDROTURBSIM specific). +!! It is similar to the 'smooth' spectral model (RISO; Hojstrup, Olesen and Larsen) for wind, +!! but is scaled by the TKE (SigmaU**2), and du/dz rather than Ustar and u/z. +!! The fit is based on data from Puget Sound, estimated by L. Kilcher. +!! The use of this subroutine requires that variables have the units of meters and seconds. +!! Note that this model does not require height. +SUBROUTINE Spec_TIDAL ( p, Ht, Shr_DuDz, Spec, SpecModel ) + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Height (dz) + REAL(ReKi), INTENT(IN ) :: Shr_DuDz !< Shear (du/dz) + INTEGER(IntKi), INTENT(IN ) :: SpecModel !< SpecModel (SpecModel_TIDAL .OR. SpecModel_RIVER) + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< output: target spectra + + ! Internal variables + + REAL(ReKi), PARAMETER :: Exp1 = 5.0 / 3.0 + REAL(ReKi) :: Sigma_U2 ! Standard Deviation of U velocity, squared. + REAL(ReKi) :: Sigma_V2 ! Standard Deviation of V velocity, squared. + REAL(ReKi) :: Sigma_W2 ! Standard Deviation of W velocity, squared. + + REAL(ReKi) :: tmpX ! Temporary variable for calculation of Spec + REAL(ReKi) :: tmpvec(3) ! Temporary vector for calculation of Spec + REAL(ReKi) :: tmpa (3) ! Spectra coefficients + REAL(ReKi) :: tmpb (3) ! Spectra coefficients + INTEGER :: I ! DO LOOP counter + + + +!print *, Ustar +!Sigma_U2=(TurbIntH20*U(IZ))**2 ! A fixed value of the turbulence intensity. Do we want to implement this? +Sigma_U2=4.5*p%met%Ustar*p%met%Ustar*EXP(-2*Ht/p%met%RefHt) +Sigma_V2=0.5*Sigma_U2 +Sigma_W2=0.2*Sigma_U2 + + +SELECT CASE ( SpecModel ) + CASE ( SpecModel_TIDAL ) + tmpa = (/ 0.193, 0.053 , 0.0362 /)*TwoPi ! These coefficients were calculated using Shr_DuDz in units of 'radians', so we multiply these coefficients by 2*pi. + tmpb = (/ 0.201, 0.0234, 0.0124 /)*(TwoPi**Exp1) + CASE ( SpecModel_RIVER ) + ! THESE ARE NOT VERIFIED YET!!!, therefore they are undocumented. + tmpa = (/ 0.081, 0.056 , 0.026 /)*TwoPi + tmpb = (/ 0.16, 0.025, 0.020 /)*(TwoPi**Exp1) +END SELECT + +tmpvec = tmpa*(/Sigma_U2, Sigma_V2, Sigma_W2/)/Shr_DuDz + +DO I = 1,p%grid%NumFreq + tmpX = (p%grid%Freq(I)/Shr_DuDz)**Exp1 + Spec(I,1) = tmpvec(1) / (1.0 + tmpb(1)*tmpX) + Spec(I,2) = tmpvec(2) / (1.0 + tmpb(2)*tmpX) + Spec(I,3) = tmpvec(3) / (1.0 + tmpb(3)*tmpX) +ENDDO + +RETURN +END SUBROUTINE Spec_TIDAL +!======================================================================= +!> This routine is just a test function to see if we get the requested +!! spectra from the TurbSim code. +SUBROUTINE Spec_Test ( Spec, Freq ) + +IMPLICIT NONE + + ! Passed variables + REAL(ReKi), intent( out) :: Spec (:,:) !< Output: target spectrum + REAL(ReKi), INTENT(IN ) :: Freq(:) + + +INTEGER :: I +INTEGER :: IVec + + + ! Create the spectrum. + +DO IVec = 1,3 + + DO I = 1,SIZE(Spec,1) + Spec(I,IVec) = 0.0 + ENDDO !I + !I = INT( NumFreq/2 ) + I = INT( 100 ) + Spec( I, IVec ) = 1/Freq(1) + + call WrScr( 'Test Spectra: sine wave with frequency '//trim(num2lstr(Freq(I)))//' Hz.' ) + +ENDDO !IVec + + +RETURN +END SUBROUTINE Spec_Test +!======================================================================= +!> This subroutine defines the von Karman PSD model. +!! The use of this subroutine requires that all variables have the units of meters and seconds. +SUBROUTINE Spec_vonKrmn ( p, Ht, Ucmp, Spec ) + + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< local height + REAL(ReKi), INTENT(IN ) :: Ucmp !< local wind speed + REAL(ReKi), INTENT( OUT) :: Spec (:,:) !< Target spectra + + ! Internal variables + +REAL(ReKi),PARAMETER :: Exp1 = 5.0/6.0 +REAL(ReKi),PARAMETER :: Exp2 = 11.0/6.0 +REAL(ReKi) :: FLU2 +REAL(ReKi) :: L1_U +REAL(ReKi) :: Lambda +REAL(ReKi) :: Lvk ! von Karman length scale +REAL(ReKi) :: Sigma ! Standard deviation +REAL(ReKi) :: SigmaL1_U +REAL(ReKi) :: Tmp + +INTEGER :: I + + ! Define isotropic integral scale. +IF ( ALLOCATED( p%met%USR_L ) ) THEN + IF ( Ht <= p%met%USR_Z(1) ) THEN + Lvk = p%met%USR_L(1) ! Extrapolation: nearest neighbor for heights below minimum height specified + ELSEIF ( Ht >= p%met%USR_Z(p%met%NumUSRz) ) THEN + Lvk = p%met%USR_L(p%met%NumUSRz) ! Extrapolation: nearest neighbor for heights above maximum height specified + ELSE !Interpolation: linear between user-defined height/integral scale curves + DO I=2,p%met%NumUSRz + IF ( Ht <= p%met%USR_Z(I) ) THEN + Lvk = (Ht - p%met%USR_Z(I-1)) * ( p%met%USR_L(I-1) - p%met%USR_L(I) ) / ( p%met%USR_Z(I-1) - p%met%USR_Z(I) ) + p%met%USR_L(I-1) + EXIT + ENDIF + ENDDO + ENDIF +ELSE + IF ( Ht < 150.0 ) THEN + Lambda = 0.7*Ht + ELSE + Lambda = 105.0 + ENDIF + Lvk = 3.5*Lambda +ENDIF + + ! Define isotropic integral scale. +IF ( ALLOCATED( p%met%USR_Sigma ) ) THEN + IF ( Ht <= p%met%USR_Z(1) ) THEN + Sigma = p%met%USR_Sigma(1) + ELSEIF ( Ht >= p%met%USR_Z(p%met%NumUSRz) ) THEN + Sigma = p%met%USR_Sigma(p%met%NumUSRz) + ELSE + DO I=2,p%met%NumUSRz + IF ( Ht <= p%met%USR_Z(I) ) THEN + Sigma = (Ht - p%met%USR_Z(I-1)) * ( p%met%USR_Sigma(I-1) - p%met%USR_Sigma(I) ) / ( p%met%USR_Z(I-1) - p%met%USR_Z(I) ) + p%met%USR_Sigma(I-1) + EXIT + ENDIF + ENDDO + ENDIF +ELSE + Sigma = p%met%Ustar*2.15 !bjj: BONNIE, make sure this is defined, or else define ustar for this model... +ENDIF + + +L1_U = Lvk/Ucmp +SigmaL1_U = 2.0*Sigma*Sigma*L1_U + +DO I=1,p%grid%NumFreq + + FLU2 = ( p%grid%Freq(I)*L1_U )**2 + Tmp = 1.0 + 71.0*FLU2 + + Spec(I,1) = (p%met%USR_StdScale(1)**2)*2.0*SigmaL1_U/Tmp**Exp1 + Spec(I,2) = SigmaL1_U*( 1.0 + 189.0*FLU2 )/Tmp**Exp2 + Spec(I,3) = Spec(I,2) + + Spec(I,2) = (p%met%USR_StdScale(2)**2)*Spec(I,2) + Spec(I,3) = (p%met%USR_StdScale(3)**2)*Spec(I,3) + +ENDDO ! I + +RETURN +END SUBROUTINE Spec_vonKrmn +!======================================================================= +!> This subroutine defines the 3-D turbulence spectrum that can be expected to exist upstream of a large, multi-row +!! wind park. It is based on the smooth or homogeneous terrain models of Hojstrup, Olesen, and Larsen of RISO +!! National Laboratory in Denmark. The RISO model has been adjusted to reflect the different spectral scaling present +!! in the flow upwind of a large wind park. The scaling is based on measurements made by the National Renewable Energy +!! Laboratory (NREL) in San Gorgonio Pass, California. +SUBROUTINE Spec_WF_UPW ( p, Ht, Ucmp, Spec ) + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Height ( input ) + REAL(ReKi), INTENT(IN ) :: Ucmp !< Velocity ( input ) + REAL(ReKi), INTENT( out) :: Spec (:,:) !< Target velocity spectra ( output ) + + ! Internal variables + +REAL(ReKi) :: den ! Denominator (replaces Pum_ih, Pum_il, fum_ih, fum_il) +REAL(ReKi), PARAMETER :: Exp1 = 5.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp2 = 2.0 / 3.0 +REAL(ReKi), PARAMETER :: Exp3 = 3.0 / 2.0 +REAL(ReKi) :: F ! Reduced frequency +REAL(ReKi) :: Fi +REAL(ReKi) :: Fq ! reduced frequency / q +REAL(ReKi) :: fur_ih +REAL(ReKi) :: fur_il +REAL(ReKi) :: fvr_ih +REAL(ReKi) :: fvr_il +REAL(ReKi) :: fwr_ih +REAL(ReKi) :: fwr_il +REAL(ReKi) :: Fw +REAL(ReKi) :: HtU ! Height / Ucmp +REAL(ReKi) :: HtZI ! Height / ZI -- used to avoid recalculation +REAL(ReKi) :: HtZI2 ! (1.0 - Height / ZI)^2 +REAL(ReKi) :: num ! Numerator (replaces Puo_ih, Puo_il, fuo_ih, fuo_il) +REAL(ReKi) :: phiE +REAL(ReKi) :: phiEQ ! temp variable +REAL(ReKi) :: phiM +REAL(ReKi) :: Ps_h +REAL(ReKi) :: Ps_l +REAL(ReKi) :: Pur_ih +REAL(ReKi) :: Pur_il +REAL(ReKi) :: Pvr_ih +REAL(ReKi) :: Pvr_il +REAL(ReKi) :: Pwr_ih +REAL(ReKi) :: Pwr_il +REAL(ReKi) :: q +REAL(ReKi) :: UDen ! +REAL(ReKi) :: UDen2 ! +REAL(ReKi) :: Ustar2 ! Ustar**2 +REAL(ReKi) :: Ustar2F ! Ustar**2 / Frequency +REAL(ReKi) :: VDen ! +REAL(ReKi) :: VDen2 ! +REAL(ReKi) :: X ! Temporary variable +REAL(ReKi) :: ZInL ! ZI / -L -- used to avoid recalculation +REAL(ReKi) :: ZIU ! ZI / Ucmp +REAL(ReKi), PARAMETER :: ZI_UVlimit = 1350.0 +REAL(ReKi), PARAMETER :: ZI_Wlimit = 1600.0 +REAL(ReKi), PARAMETER :: ZL_MaxObs = 0.15 +REAL(ReKi), PARAMETER :: ZL_MinObs = -1.00 + + +INTEGER :: I ! Loop counter + + +Ustar2 = p%met%Ustar*p%met%Ustar + +IF ( p%met%ZL < 0 ) THEN + ! BEGIN UNSTABLE FLOW LOOP + + ! Unstable high-frequency range scaling... + + X = - MAX( p%met%ZL, ZL_MinObs) + + Num = 0.691114 + 0.0791666*X ! was "Original" Puo_ih = + Den = 0.77991 + 0.1761624 / ( 1.0 + EXP( -(X - 0.0405364) / (-0.0184402) ) ) ! was "Measured" Pum_ih = + Pur_ih = 0.10 * ( Num / Den ) + IF (p%met%ZI > ZI_UVlimit) Pur_ih = (p%met%ZI / ZI_UVlimit) * Pur_ih + + Num = 0.421958 * EXP( 0.20739895*X ) + Den = 0.5247865 + 0.0419204 / ( 1.0 + EXP( -(X - 0.0434172) / (-0.0179269) ) ) + Pvr_ih = Num / Den + + Num = 0.222875 + 0.1347188*X + Den = 0.3542331 + 0.0168806 / ( 1.0 + EXP( -(X - 0.0388899) / (-0.0220998) ) ) + Pwr_ih = 0.80 * ( Num / Den ) + + Num = 0.047465 + 0.0132692*X + Den = 0.0599494 - 0.0139033*EXP(-X / 0.02603846) + fur_ih = 1.75 * ( Num / Den ) + IF (p%met%ZI > ZI_UVlimit) fur_ih = (p%met%ZI / ZI_UVlimit)*fur_ih + + Num = 0.18377384 * EXP( 0.2995136*X ) + Den = 0.1581509 + 0.09501906*X + fvr_ih = 1.50 * ( Num / Den ) + IF (p%met%ZI > ZI_UVlimit) fvr_ih = (p%met%ZI / ZI_UVlimit)*fvr_ih + + Num = 0.3419874 + 0.24985029 * EXP(-X / 0.02619489) + Den = 0.451295 + 0.2355227*X + fwr_ih = 2.0 * ( Num / Den ) + IF (p%met%ZI > ZI_Wlimit) fwr_ih = 0.35*(p%met%ZI / ZI_Wlimit)*fwr_ih + + + ! Unstable low-frequency range scaling... + + Num = -0.436922 + 2.784789 / ( 1.0 + EXP( -(X - 0.104094) / 0.136708 ) ) + Den = 0.1392684 + 1.7396251*X + Pur_il = 2.00 * ( Num / Den ) + + Num = 0.467006 + (5.3032075*X)**1.1713260 + Den = 0.1425146 + 2.2011562*X + Pvr_il = 0.25 * ( Num / Den ) + + Num = 0.086908 + (2.3719755 *X)**1.3106297 + Den = 0.00251981 + (0.50642167*X)**0.6607754 + Pwr_il = Num / Den + + Num = 0.467962 + 0.9270681*EXP( -X / 0.02039003 ) + Den = 0.759259 - 0.1448362*X ! X < 5.24 + fur_il = Num / Den + + Num = 0.369625 + 1.0772852*EXP( -X / 0.0210098 ) + !Den = 0.759259 - 0.1448362*X calculated previously + fvr_il = 2.25 * ( Num / Den ) + IF (p%met%ZI > ZI_UVlimit) fvr_il = (p%met%ZI / ZI_UVlimit)*fvr_il + + Num = 3.39482 * EXP( 0.279914*X ) + Den = 4.59769 + 12.58881*EXP( -X / 0.03351852 ) + fwr_il = 2.25 * ( Num / Den ) + IF (p%met%ZI > ZI_Wlimit) fwr_il=4.0*(p%met%ZI / ZI_Wlimit)*fwr_il + + HtZI = Ht / p%met%ZI + HtZI2 = (1.0 - HtZI)**2 + ZInL = ( p%met%ZI / ( -p%met%L ) )**Exp2 + HtU = Ht / Ucmp + ZIU = p%met%ZI / Ucmp + UDen = 1.0 + 15.0*HtZI + VDen = 1.0 + 2.8*HtZI + UDen2 = HtZI2 / UDen**Exp2 + VDen2 = HtZI2 / VDen**Exp2 + + + DO I = 1,p%grid%NumFreq + + F = p%grid%Freq(I) * HtU + Fi = p%grid%Freq(I) * ZIU + + ! Bonnie: These () around 0.3 HtZI are incorrect as compared to the original SMOOTH model. (For now, leave as is since parameters were-supposedly-calculated with this formulation) + Fw = SQRT( (F**2 + (0.3*HtZI**2) ) / (F**2 + 0.0225) ) + + Ustar2F = Ustar2 / p%grid%Freq(I) + + ! CALCULATE UNSTABLE LONGITUDINAL SPECTRAL COMPONENT, nSu(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fi / fur_il + Ps_l = Pur_il * ( (0.5*X) / (1.0 + 2.2 * X**Exp1) ) * ZInL + + X = F / (UDen * fur_ih) ! Fru = F / UDen + Ps_h = ( (105.0 * X) / (1.0 + 33.0 * X )**Exp1 ) * UDen2 + Ps_h = Ps_h*Pur_ih + + Spec(I,1) = ( Ps_l + Ps_h ) * Ustar2F + + ! CALCULATE UNSTABLE CROSSWIND SPECTRAL COMPONENT, nSv(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fi / fvr_il + Ps_l = ( (0.95*X) / (1.0 + 2.0 * X)**Exp1 ) * ZInL + Ps_l = Ps_l*Pvr_il + + X = F / (VDen * fvr_ih) ! Frv = F / VDen + Ps_h = ( (17.0 * X) / (1.0 + 9.5*X)**Exp1 ) * VDen2 + Ps_h = Ps_h*Pvr_ih + + Spec(I,2) = ( Ps_l + Ps_h ) * Ustar2F + + ! CALCULATE UNSTABLE VERTICAL SPECTRAL COMPONENT, nSw(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fi / fwr_il + Ps_l = Fw * ( (0.95*X) / (1.0 + 2.0*X)**Exp1 ) * ZInL + Ps_l = Ps_l*Pwr_il + + X = F / fwr_ih + Ps_h = ( (2.0*X) / (1.0 + 5.3 * X**Exp1) ) * HtZI2 + Ps_h = Ps_h * Pwr_ih + + Spec(I,3) = ( Ps_l + Ps_h ) * Ustar2F + + ENDDO + +ELSE ! ZL >= 0 ! BEGIN STABLE FLOW LOOP + + X = MIN(p%met%ZL, ZL_MaxObs) + + ! Get stable spectral peaks + + ! Calculate smooth terrain scaling functions + + phiE = (1.0 + 2.5 * X**0.6) **Exp3 + phiM = 1.0 + 4.7*X + + q = phiM + + ! Stable high-frequency (shear) range scaling ... + + Num = 0.8029768 + ( 1.708247*X )**3.669245 + Den = 1.5431 * EXP( 1.6379*X ) + Pur_ih = 0.01*( Num / Den ) + + Num = 0.419234 + ( 2.759119*X )**1.4483715 + Den = 0.89717 * EXP( 1.67034*X ) + Pvr_ih = 1.30 * ( Num / Den ) + + Num = 0.239692 + ( 2.3531204*X )**1.062937 + Den = 0.5324 * EXP( 1.6314*X ) + Pwr_ih = Num / Den + Pwr_ih = Pwr_ih - 2.0*X + IF ( Pwr_ih <= 0.0) Pwr_ih = 1.0 + Pwr_ih = 1.5*Pwr_ih + + Num = 0.042393 + ( 1.28175*X )**1.409066 + Den = 0.045 + 0.21137*X + fur_ih = 3.5 * ( Num / Den ) + + Num = 0.220831 + (0.630632*X)**0.8120686 + Den = 0.160 + 0.74876*X + fvr_ih = 1.25 * ( Num / Den ) + + Num = 0.382558 + (1.3640485*X)**1.524565 + Den = 0.350 + 1.638806*X + fwr_ih = 1.5 * ( Num / Den ) + + ! Low-frequency range scaling... + + Num = 0.88418 + (11.665367*X)**0.794753 + Den = 1.55288 * EXP( 1.56925*X ) + Pur_il = 1.50 * ( Num / Den ) + + Num = 0.4671733 + 4.3093084 * X**(0.859202) + Den = 0.90382 * EXP( 1.59076*X ) + Pvr_il = 0.75 * ( Num / Den ) + + Num = 0.076136 + 2.644456 * X**(1.207014) + Den = 0.533202 * EXP( 1.51415*X ) + Pwr_il = Num / Den + Pwr_il = Pwr_il - 1.75*X + + Num = 0.009709 + ( 0.4266236*X )**1.644925 + Den = 0.045 + 0.212038*X + fur_il = 2.00 * ( Num / Den ) + fur_il = ABS(fur_il - 3.0*X) + + Num = 0.0220509 + ( 0.93256713*X )**1.719292 + Den = 0.160 + 0.74985*X + fvr_il = 1.15 * ( Num / Den ) + + Num = 0.0351474 + ( 1.4410838*X )**1.833043 + Den = 0.350 + 1.645667*X + fwr_il = Num / Den + + + phiEQ = (phiE / q)**Exp2 + + DO I = 1,p%grid%NumFreq + + ! CALCULATE Reduced Frequency, f + + f = p%grid%Freq(I) * Ht / Ucmp + fq = f / q ! was XU = f/qu, XV = f/qv, XW = f/qw + + Ustar2F = Ustar2 / p%grid%Freq(I) + + ! CALCULATE NEUTRAL/STABLE LONGITUDINAL SPECTRAL COMPONENT, nSu(n)/(u*)^2, then multiply by (u*)^2/n + + X = fq / fur_ih + Ps_h = ( (79.0 * X) / (1.0 + 263.0 * X**Exp1) ) * phiEQ + Ps_h = Ps_h*Pur_ih + + X = fq / fur_il + Ps_l = ( (79.0 * X) / (1.0 + 263.0 * X**Exp1) ) * phiEQ + Ps_l = Ps_l*Pur_il + + Spec(I,1) = ( Ps_l + Ps_h ) * Ustar2F + + ! CALCULATE NEUTRAL/STABLE CROSSWIND SPECTRAL COMPONENT, nSv(n)/(u*)^2, then multiply by (u*)^2/n + + X = fq / fvr_ih + Ps_h = ( (13.0 * X) / (1.0 + 32.0 * X**Exp1) ) * phiEQ + Ps_h = Ps_h*Pvr_ih + + X = fq / fvr_il + Ps_l = ( (13.0 * X) / (1.0 + 32.0 * X**Exp1) ) * phiEQ + Ps_l = Ps_l*Pvr_il + + Spec(I,2) = ( Ps_h + Ps_l ) * Ustar2F + + ! CALCULATE NEUTRAL/STABLE VERTICAL SPECTRAL COMPONENT, nSw(n)/(u*)^2, then multiply by (u*)^2/n + + X = fq / fwr_ih + Ps_h = ( ( 3.5 * X) / (1.0 + 8.6 * X**Exp1) ) * phiEQ + Ps_h = Ps_h*Pwr_ih + + X = fq / fwr_il + Ps_l = ( ( 3.5 * X) / (1.0 + 8.6 * X**Exp1) ) * phiEQ + Ps_l = Ps_l*Pwr_il + + Spec(I,3) = ( Ps_l + Ps_h ) * Ustar2F + + ENDDO ! I + +ENDIF ! ZL < 0 + + +RETURN +END SUBROUTINE Spec_WF_UPW +!======================================================================= +!> This subroutine defines the 3-D turbulence spectrum that can be expected to exist (7 to 14 rotor diameters) +!! downstream of a large, multi-row wind park. The scaling is based on measurements made by the National +!! Renewable Energy Laboratory (NREL) in San Gorgonio Pass, California. +SUBROUTINE Spec_WF_DW ( p, Ht, Ucmp, Spec, ErrStat, ErrMsg ) + + +IMPLICIT NONE + + ! Passed variables + + TYPE(TurbSim_ParameterType) , INTENT(IN ) :: p !< Input: turbsim parameters + REAL(ReKi), INTENT(IN ) :: Ht !< Height ( input ) + REAL(ReKi), INTENT(IN ) :: Ucmp !< Velocity ( input ) + REAL(ReKi), INTENT( out) :: Spec (:,:) !< Target velocity spectra ( output ) + + INTEGER(IntKi), INTENT(OUT) :: ErrStat + CHARACTER(*), INTENT(OUT) :: ErrMsg + + + ! Internal variables + + REAL(ReKi) :: A0 + REAL(ReKi) :: A1 + REAL(ReKi) :: A2 + REAL(ReKi) :: A3 + REAL(ReKi), PARAMETER :: Exp1 = 5.0 / 3.0 + REAL(ReKi), PARAMETER :: Exp2 = 2.0 / 3.0 + REAL(ReKi), PARAMETER :: Exp3 = 3.0 / 2.0 + REAL(ReKi) :: den ! Denominator (replaces Pum_oh, Pum_ol, fum_oh, fum_ol, Pvm_oh) + REAL(ReKi) :: F ! Reduced frequency + REAL(ReKi) :: Fi + REAL(ReKi) :: fur_oh + REAL(ReKi) :: fur_ol + REAL(ReKi) :: fvr_oh + REAL(ReKi) :: fvr_ol + REAL(ReKi) :: fvr_wk + REAL(ReKi) :: Fw + REAL(ReKi) :: fwr_oh + REAL(ReKi) :: fwr_ol + REAL(ReKi) :: Fq ! reduced frequency / q + REAL(ReKi) :: HtZI ! Height / ZI -- used to avoid recalculation + REAL(ReKi) :: HtZI2 ! (1.0 - Height / ZI)^2 + REAL(ReKi) :: num ! Numerator (replaces Puo_oh, Puo_ol, fuo_oh, fuo_ol, Pvo_wk) + REAL(ReKi) :: phiE + REAL(ReKi) :: phiM + REAL(ReKi) :: Ps_h + REAL(ReKi) :: Ps_l + REAL(ReKi) :: Ps_wk + REAL(ReKi) :: Pur_oh ! High Frequency Range + REAL(ReKi) :: Pur_ol ! Low Frequency Range + REAL(ReKi) :: Pvr_oh + REAL(ReKi) :: Pvr_ol + REAL(ReKi) :: Pvr_wk + REAL(ReKi) :: Pwr_oh + REAL(ReKi) :: Pwr_ol + REAL(ReKi) :: q + REAL(ReKi) :: tmp ! holds calculation common to several formulae + REAL(ReKi) :: UDen ! + REAL(ReKi) :: UDen2 ! + REAL(ReKi) :: Ustar2 ! Ustar**2 + REAL(ReKi) :: Ustar2F ! Ustar**2 / Frequency + REAL(ReKi) :: VDen ! + REAL(ReKi) :: VDen2 ! + REAL(ReKi) :: X ! Temporary variable + REAL(ReKi) :: ZInL ! ZI / -L -- used to avoid recalculation + REAL(ReKi), PARAMETER :: ZL_MaxObs = 0.4 ! The largest z/L value where the spectral peak scaling should work. + REAL(ReKi), PARAMETER :: ZL_MinObs = -1.0 ! The smallest z/L value where the spectral peak scaling should work. + + INTEGER :: I ! Loop counter + + + ErrStat = ErrID_None + ErrMsg = "" + +Ustar2 = p%met%Ustar*p%met%Ustar + +IF (p%met%ZL < 0) THEN + + + ! Get Unstable spectral peaks + + ! Unstable high-frequency range scaling... + + X = - MAX( p%met%ZL, ZL_MinObs ) + + Num = 0.598894 + 0.282106 * EXP(-X / 0.0594047) + Den = 0.600977 + 9.137681 / (1.0 + EXP( -(X + 0.830756) / (-0.252026) )) + Pur_oh = 0.1 * (Num / Den) + + Num = 0.4830249 + 0.3703596 * EXP(-X / 0.0553952) + Den = 0.464604 + 1.900294 / (1.0 + EXP( -(X + 0.928719) / (-0.317242) )) + Pvr_oh = 5.0 * (Num / Den) + + Num = 0.320112 + 0.229540 * EXP(-X / 0.0126555) + Den = 0.331887 + 1.933535 / (1.0 + EXP( -(X + 1.19018 ) / (-0.3011064) )) + Pwr_oh = 1.25 * (Num / Den) + + Num = 0.049279 + EXP(0.245214 * X * 2.478923) ! was Num = 0.049279 + EXP(0.245214 * X)**2.478923 + Den = -2.333556 + 2.4111804 / (1.0 + EXP( -(X + 0.623439) / 0.1438076)) + fur_oh = 0.3 * (Num / Den) + + Num = -2.94362 + 3.155970 / (1.0 + EXP( -(X + 0.872698) / 0.245246)) + Den = 0.0171463 + 0.188081 / (1.0 + EXP( -(X + 0.711851) / 0.688910)) + fvr_oh = 2.0 * (Num / Den) + + Num = 0.7697576 * EXP( -X / 3.8408779 ) - 0.561527 * EXP( -X / 0.1684403 ) ! was Num = Beta4(X,A0,A1,A2,A3) + Den = 0.512356 - 0.044946 / (1.0 + EXP( -(X - 0.066061) / (-0.0121168) )) + fwr_oh = 1.75 * (Num / Den) + IF (p%met%ZI < 1350.0 ) fwr_oh = (p%met%ZI / 1350.0) * fwr_oh + + ! Unstable low-frequency range scaling ... + + Num = 0.796264 + 0.316895 / (1.0 + EXP( -(X - 0.082483) / 0.027480 )) + Den = 0.07616 + EXP(0.303919 * X * 0.390906) ! was Den = 0.07616 + EXP(0.303919*X)**0.390906 + Pur_ol = 4.0 * (Num / Den) + IF (p%met%ZI < 1600.0) Pur_ol = (p%met%ZI / 1600.0) * Pur_ol + + Num = 0.812483 + 0.1332134 * X + Den = 0.104132 + EXP(0.714674 * X * 0.495370) ! was Den = 0.104132 + EXP(0.714674*X)**0.495370 + Pvr_ol = Num / Den + Pvr_ol = (p%met%ZI / 1600.0)*Pvr_ol + + Num = 0.371298 + 0.0425447 * X + Den = 0.0004375 + EXP(0.4145751 * X * 0.6091557) ! was Den = 0.0004375 + EXP(0.4145751*X)**0.6091557 + Pwr_ol = 0.75 * (Num / Den) + + Num = 0.859809 * EXP(0.157999 * X) + Den = 0.81459 + 0.021942 * X + fur_ol = 1.5 * (Num / Den) + IF (p%met%ZI > 1850.0) fur_ol = 2.6 * (p%met%ZI / 1850.0) * fur_ol + + !A0 = 0.8121775 + !A1 = 4.122E+15 + !A2 = -0.594909 + !A3 = 0.0559581 + Num = 0.8121775 * EXP( -X / 4.122E+15 ) - 0.594909 * EXP( -X / 0.0559581 ) ! was Num = BETA4(X,A0,A1,A2,A3) + Den = 0.72535 - 0.0256291 * X + fvr_ol = 3.0 * (Num / Den) + fvr_ol = (p%met%ZI / 1600.0) * fvr_ol + + Num = 6.05669 * EXP(-0.97418 * X) + Den = 3.418386 + 9.58012 / (1.0 + EXP( -(X - 0.0480283) / (-0.022657) )) + fwr_ol = 0.9 * (Num / Den) + + ! Unstable Wake Range Scaling for v-component only + + Num = 0.247754 + 0.16703142 * EXP(-X / 0.1172513) + Den = 0.464604 + 1.900294 / (1.0 + EXP( -(X + 0.928719) / (-0.317242) )) + Pvr_wk = 0.05 * (Num / Den) + + !A0 = 0.72435 + !A1 = 0.0436448 + !A2 = 0.08527 + Num = 0.72435 / (1.0 + EXP( -(X - 0.0436448) / 0.08527 )) ! was Num = BETA5(X,A0,A1,A2) + Den = 0.0171463 + 0.188081 / (1.0 + EXP( -(X + 0.711851) / 0.688910)) + fvr_wk = 3.0 * (Num / Den) + + HtZI = Ht / p%met%ZI + HtZI2 = (1.0 - HtZI)**2 + ZInL = ( p%met%ZI / (-p%met%L) )**Exp2 + UDen = 1.0 + 15.0 * HtZI + VDen = 1.0 + 2.8 * HtZI + UDen2 = HtZI2 / UDen**Exp2 + VDen2 = HtZI2 / VDen**Exp2 + + DO I = 1,p%grid%NumFreq + + ! Calculate f,fi,fru,frv + + F = p%grid%Freq(I)*Ht / Ucmp + Fi = p%grid%Freq(I)*p%met%ZI / Ucmp + Fw = SQRT( (F**2 + (0.3*HtZI**2)) / (F**2 + 0.0225) ) + + Ustar2F = Ustar2 / p%grid%Freq(I) + + ! CALCULATE UNSTABLE LONGITUDINAL SPECTRAL COMPONENT, nSu(n)/(u*)^2, then multiply by (u*)^2/n + + ! No identifiable wake contribution was found in u-component + + X = Fi / fur_ol + Ps_l = ( (0.5*X) / (1.0 + 2.2 * X**Exp1) ) * ZInL + Ps_l = ABS(Ps_l*Pur_ol) + + X = F / (UDen * fur_oh) + Ps_h = ( (105.0 * X) / (1.0 + 33.0 * X)**Exp1 ) * UDen2 + Ps_h = Ps_h * Pur_oh + Spec(I,1) = ( Ps_l + Ps_h ) * Ustar2F + + ! CALCULATE UNSTABLE CROSSWIND SPECTRAL COMPONENT, nSv(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fi / fvr_ol + Ps_l = ( (0.95*X) / (1.0 + 2.0*X)**Exp1 ) * ZInL +! Ps_l = ABS(Psv_l)*Pvr_ol + + X = F / (VDen * fvr_oh) + Ps_h = ( (17.0 * X) / (1.0 + 9.5*X)**Exp1 ) * VDen2 +! Ps_h = Ps_h*Pvr_oh + + ! Wake contribution for v-component only + X = F / (VDen * fvr_wk) + Ps_wk = ( (17.0 * X) / (1.0 + 9.5 * X)**Exp1 ) * VDen2 + Ps_wk = Ps_wk*Pvr_wk + Spec(I,2) = ( Ps_l + Ps_h + Ps_wk ) * Ustar2F + + ! CALCULATE UNSTABLE VERTICAL SPECTRAL COMPONENT, nSw(n)/(u*)^2, then multiply by (u*)^2/n + + ! No identifiable wake contribution was found in w-component + + X = Fi / fwr_ol + Ps_l = Fw*( (0.95 * X) / (1.0 + 2.0 * X)**Exp1 ) * ZInL + Ps_l = ABS(Ps_l)*Pwr_ol + + X = F / fwr_oh + Ps_h = ( (2.0 * X) / (1.0 + 5.3 * X**Exp1) ) * HtZI2 + Ps_h = Ps_h*Pwr_oh + + Spec(I,3) = ( Ps_l + Ps_h ) * Ustar2F + + ENDDO + +ELSE ! ZL >= 0 + + ! BEGIN STABLE FLOW LOOP... + + ! Get Stable spectral peaks + + ! Stable high-frequency (wake) range scaling... + + X = MIN( p%met%ZL, ZL_MaxObs ) + + Num = 0.149471 + 0.028528 * & + EXP( -EXP( -( (X - 0.003580) / 0.0018863 ) ) - ( (X - 0.0035802) / 0.0018863) + 1.0) + Den = 1.563166 * EXP(1.137965 * X) + Pur_oh = 0.35 * (Num / Den) + + A0 = 2.66666062 + A1 = 0.0034082 + A2 = 0.0229827 + Num = Beta3(X, A0, A1, A2) + A0 = 33.942268 + A1 = 0.0160732 + A2 = -0.008654 + A3 = 0.0053586 + Num = Num + Beta1(X, A0, A1, A2, A3) + Num = 1.0 / Num + Den = 0.9170783 * EXP(1.152393 * X) + Pvr_oh = 2.25 * (Num / Den) + + A0 = 0.1990569 + A1 = 0.0286048 + A2 = 0.006751 + Num = Beta3(X, A0, A1, A2) + A0 = 0.0435354 + A1 = 0.0599214 + A2 = 0.0520877 + Num = Num + Beta2(X, A0, A1, A2) + Den = 0.539112 * EXP(1.124104 * X) + Pwr_oh = 0.9 * (Num / Den) + + tmp = -(X - 0.037003738) / 0.01612278 + Num = 0.764910145 + 0.654370025 * EXP( -EXP(tmp) + tmp + 1.0 ) + Den = 0.045 + 0.209305 * X + fur_oh = Num / Den + + A0 = 0.5491507 + A1 = 0.0099211 + A2 = 0.0044011 + Num = Beta3(X, A0, A1, A2) + A0 = 0.0244484 + A1 = 0.0139515 + A2 = 0.0109543 + Num = Num + Beta2(X, A0, A1, A2) + Den = 0.160 + 0.7496606 * X + fvr_oh = 0.5 * (Num / Den) + + Num = 0.391962642 + 0.546722344*EXP( -0.5* ( (X - 0.023188588) / 0.018447575)**2 ) + Den = 0.350 + 1.6431833 * X + fwr_oh = 2.0 * (Num / Den) + + ! Stable low-frequency range scaling ... + + Num = 0.894383 + (1.55915 * X)**3.111778 + Den = 1.563317 * EXP(1.137965 * X) + Pur_ol = 0.9 * (Num / Den) + + Num = 0.747514 + (1.57011 * X)**1.681581 + Den = 0.910783 * EXP(1.1523931 * X) + Pvr_ol = 0.60 * (Num / Den - 1.75 * X) + + Num = 0.376008 * EXP(1.4807733* X) + Den = 0.539112 * EXP(1.124104 * X) + Pwr_ol = 0.6 * (Num / Den - 2.0 * X) + + Num = 0.023450 + (0.3088194 * X)**1.24710 + Den = 0.045 + 0.209305 * X + fur_ol = 1.5 * (Num / Den - X) + fur_ol = MAX( fur_ol, REAL( 0.1,ReKi ) ) ! We divide by this number so it should not get too small. + + Num = 0.051616 + (0.8950263 * X)**1.37514 + Den = 0.160 + 0.749661 * X + fvr_ol = 0.5 * (Num / Den) + + Num = 0.250375 - 0.690491 * X + 2.4329342 * X**2 + Den = 0.350 + 1.6431833 * X + fwr_ol = Num / Den + + ! Calculate smooth terrain scaling functions + + phiE = (1.0 + 2.5 * X**0.6)**Exp3 + phiM = 1.0 + 4.7 * X + q = phiM + + tmp = (phiE / q)**Exp2 + + DO I = 1,p%grid%NumFreq + + F = p%grid%Freq(I) * Ht / Ucmp ! Reduced frequency + + Fq = F / q + Ustar2F = Ustar2 / p%grid%Freq(I) + + ! CALCULATE NEUTRAL/STABLE LONGITUDINAL SPECTRAL COMPONENT, nSu(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fq / fur_ol + Ps_l = ( (79.0 * X) / (1.0 + 263.0 * X**Exp1) ) * tmp + Ps_l = ABS(Ps_l * Pur_ol) + + X = Fq / fur_oh + Ps_h = ( (79.0 * X) / (1.0 + 263.0 * X**Exp1) ) * tmp + Ps_h = Ps_h * Pur_oh + + Spec(I,1) = (Ps_l + Ps_h) * Ustar2F + + ! CALCULATE NEUTRAL/STABLE CROSSWIND SPECTRAL COMPONENT, nSv(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fq / fvr_ol + Ps_l = ( (13.0 * X) / (1.0 + 32.0 * X**Exp1) ) * tmp + Ps_l = ABS(Ps_l * Pvr_ol) + + X = Fq / fvr_oh + Ps_h = ( (13.0 * X) / (1.0 + 32.0 * X**Exp1) ) * tmp + Ps_h = Ps_h * Pvr_oh + + Spec(I,2) = (Ps_h + Ps_l) * Ustar2F + + ! CALCULATE NEUTRAL/STABLE VERTICAL SPECTRAL COMPONENT, nSw(n)/(u*)^2, then multiply by (u*)^2/n + + X = Fq / fwr_ol + Ps_l = ( (3.5 * X) / (1.0 + 8.6 * X**Exp1) ) * tmp + Ps_l = ABS(Ps_l * Pwr_ol) + + X = Fq / fwr_oh + Ps_h = ( (3.5 * X) / (1.0 + 8.6 * X**Exp1) ) * tmp + Ps_h = Ps_h * Pwr_oh + + Spec(I,3) = (Ps_l + Ps_h) * Ustar2F + + ENDDO + +ENDIF ! ZL < 0 + +RETURN + + +CONTAINS + !======================================================================= + FUNCTION Beta1( X, A0, A1, A2, A3 ) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi), INTENT(IN) :: X ! Function input + REAL(ReKi), INTENT(IN) :: A0 ! Function input + REAL(ReKi), INTENT(IN) :: A1 ! Function input + REAL(ReKi), INTENT(IN) :: A2 ! Function input + REAL(ReKi), INTENT(IN) :: A3 ! Function input + REAL(ReKi) :: Beta1 ! Function result + + REAL(ReKi) :: tmp1 ! temporary variable + REAL(ReKi) :: tmp2 ! temporary variable + + + tmp1 = X - A1 + tmp2 = A2 / 2.0 + + Beta1 = A0 / (1.0 + EXP( ( tmp1 + tmp2 ) / (-A3) )) * & + (1.0 - ( 1.0 / (1.0 + EXP( ( tmp1 - tmp2 ) / (-A3) )) )) + + + RETURN + END FUNCTION Beta1 + !======================================================================= + FUNCTION BETA2(X,A0,A1,A2) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi),INTENT(IN) :: X ! Function input + REAL(ReKi),INTENT(IN) :: A0 ! Function input + REAL(ReKi),INTENT(IN) :: A1 ! Function input + REAL(ReKi),INTENT(IN) :: A2 ! Function input + REAL(ReKi) :: Beta2 ! Function output + + + Beta2 = ( A0 / ( 2.50663 * A2 ) ) * EXP( -0.5 * ( (X-A1) / A2 )**2 ) + + RETURN + END FUNCTION Beta2 + !======================================================================= + FUNCTION BETA3(X,A0,A1,A2) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta3 ! Function output + REAL(ReKi),INTENT(IN) :: X ! Function input + REAL(ReKi),INTENT(IN) :: A0 ! Function input + REAL(ReKi),INTENT(IN) :: A1 ! Function input + REAL(ReKi),INTENT(IN) :: A2 ! Function input + + Beta3 = 0.5 * A0 * ( 1.0 + Beta10( (X-A1) / (1.414*A2) ) ) + + RETURN + END FUNCTION Beta3 + !======================================================================= + FUNCTION Beta4(X,A0,A1,A2,A3) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta4 ! Function output + REAL(ReKi),INTENT(IN) :: X ! Function input + REAL(ReKi),INTENT(IN) :: A0 ! Function input + REAL(ReKi),INTENT(IN) :: A1 ! Function input + REAL(ReKi),INTENT(IN) :: A2 ! Function input + REAL(ReKi),INTENT(IN) :: A3 ! Function input + + + Beta4 = A0 * EXP( -X/A1 ) + A2 * EXP( -X/A3 ) + + RETURN + END FUNCTION Beta4 + !======================================================================= + FUNCTION Beta5(X,A0,A1,A2) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta5 ! Function output + REAL(ReKi),INTENT(IN) :: X ! Function input + REAL(ReKi),INTENT(IN) :: A0 ! Function input + REAL(ReKi),INTENT(IN) :: A1 ! Function input + REAL(ReKi),INTENT(IN) :: A2 ! Function input + + Beta5 = A0 / ( 1.0 + EXP( -(X-A1) / A2 ) ) + + RETURN + END FUNCTION Beta5 + !======================================================================= + FUNCTION Beta6(A,X) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta6 ! Function output + REAL(ReKi),INTENT(IN) :: A ! Function input + REAL(ReKi),INTENT(IN) :: X ! Function input + + IF ( ( X < 0.0 ) .OR. ( A <= 0.0 ) ) THEN + CALL SetErrStat( ErrID_Fatal, 'Invalid X or A inputs.', ErrStat, ErrMsg, 'Beta6' ) + RETURN + ENDIF + + IF ( X < A + 1.0 ) THEN + CALL Beta8( Beta6, A, X ) + ! Beta6 = GAMSER + ELSE + CALL Beta7( Beta6, A, X) + Beta6 = 1.0 - Beta6 + ENDIF + + RETURN + END FUNCTION Beta6 + !======================================================================= + SUBROUTINE Beta7(GAMMCF, A, X ) + + ! This subroutine is used in the calculation of the Wind Farm models' PSD + + + IMPLICIT NONE + + REAL(ReKi),INTENT(OUT) :: GAMMCF ! Subroutine Output + REAL(ReKi),INTENT(IN) :: A ! Subroutine Input + REAL(ReKi),INTENT(IN) :: X ! Subroutine Input + + REAL(ReKi) :: GLN + REAL(ReKi) :: g + REAL(ReKi) :: gOld + REAL(ReKi) :: A0 + REAL(ReKi) :: A1 + REAL(ReKi) :: B0 + REAL(ReKi) :: B1 + REAL(ReKi) :: FAC + REAL(ReKi) :: AN + REAL(ReKi) :: ANA + REAL(ReKi) :: ANF + + REAL(ReKi), PARAMETER :: eps = 3.0E-7 + REAL(ReKi), PARAMETER :: ITmax = 100.0 + + LOGICAL :: continueIT + + + IF ( X <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Input variable X must be positive.', ErrStat, ErrMsg, 'Beta7' ) + RETURN + ENDIF + + gOld = 0.0 + + A0 = 1.0 + A1 = X + B0 = 0.0 + B1 = 1.0 + FAC = 1.0 + + AN = 0.0 + continueIT = .TRUE. + + DO WHILE ( ( AN < ITmax ) .AND. continueIT ) + + AN = AN + 1.0 + + ANA = AN - A + A0 = ( A1 + A0*ANA )*FAC + B0 = ( B1 + B0*ANA )*FAC + + ANF = AN*FAC + A1 = X*A0 + ANF*A1 + B1 = X*B0 + ANF*B1 + + IF ( A1 /= 0.0 ) THEN + FAC = 1.0 / A1 + g = B1*FAC + + IF( ABS( ( g - gOld ) / g ) < eps) continueIT = .FALSE. + + gOld = g + ENDIF + + ENDDO + + IF ( continueIT ) THEN + CALL SetErrStat( ErrID_Fatal, 'Value of A is too large or ITMAX is too small.', ErrStat, ErrMsg, 'Beta7' ) + RETURN + ENDIF + + GLN = Beta9( A ) + IF (ErrStat >= AbortErrLev) RETURN + + GAMMCF = EXP( -X + A*LOG( X ) - GLN ) * G + + RETURN + END SUBROUTINE Beta7 + !======================================================================= + SUBROUTINE Beta8(GAMSER,A,X) + + ! This subroutine is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi),INTENT(OUT) :: GAMSER ! Subroutine Output + REAL(ReKi),INTENT(IN) :: A ! Subroutine Input + REAL(ReKi),INTENT(IN) :: X ! Subroutine Input + + REAL(ReKi) :: GLN + REAL(ReKi) :: AP + REAL(ReKi) :: Sum + REAL(ReKi) :: del + + REAL(ReKi),PARAMETER :: eps = 3.0E-7 ! Tolerance + INTEGER,PARAMETER :: ITmax = 100 ! Maximum loop iterations + + + INTEGER :: N ! Loop counter + + LOGICAL :: continueIT + + + IF ( ( X > 0.0 ) .AND. ( A /= 0.0 ) ) THEN + continueIT = .TRUE. + + AP = A + Sum = 1.0 / A + del = Sum + + N = 1 + + DO WHILE ( ( N <= ITmax ) .AND. ( continueIT ) ) + AP = AP + 1.0 + del = del * X / AP + Sum = Sum + del + + IF( ABS(del) < ABS(Sum) * eps ) continueIT = .FALSE. + + N = N + 1 + ENDDO + + IF ( continueIT ) THEN + CALL SetErrStat( ErrID_Fatal, 'Value of A is too large or ITMAX is too small.', ErrStat, ErrMsg, 'BETA8' ) + RETURN + ENDIF + + GLN = Beta9( A ) + IF (ErrStat >= AbortErrLev) RETURN + + GAMSER = Sum * EXP( -X + A * LOG(X) - GLN) + + ELSEIF ( X == 0.0 ) THEN + + GAMSER = 0.0 + + ELSE ! ( X < 0.0 ) + CALL SetErrStat( ErrID_Fatal, 'Invalid input.', ErrStat, ErrMsg, 'BETA8' ) + RETURN + ENDIF + + RETURN + END SUBROUTINE Beta8 + !======================================================================= + FUNCTION Beta9(XX) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta9 ! Output value + REAL(ReKi),INTENT(IN) :: XX ! Input value + + REAL(ReKi) :: X + REAL(ReKi) :: Tmp + REAL(ReKi) :: SER + + REAL(ReKi), PARAMETER :: Cof(6) = (/ 76.18009173, -86.50532033, 24.01409822, -1.231739516, 0.120858003E-2, -0.536382E-5 /) + REAL(ReKi), PARAMETER :: STP = 2.50662827465 + + INTEGER :: J ! Loop counter + + IF ( XX <= -4.5 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Input variable XX must be larger than -4.5.', ErrStat, ErrMsg, 'Beta9' ) + RETURN + ENDIF + + + X = XX - 1.0 + Tmp = X + 5.5 + Tmp = ( X + 0.5 ) * LOG( Tmp ) - Tmp + + SER = 1.0 + + DO J = 1,6 + X = X + 1.0 + SER = SER + Cof(J) / X + ENDDO + + + IF ( SER <= 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Variable SER must be larger than 0.0.', ErrStat, ErrMsg, 'Beta9' ) + RETURN + ENDIF + + + Beta9 = Tmp + LOG( STP*SER ) + + RETURN + END FUNCTION Beta9 + !======================================================================= + FUNCTION Beta10(X) + + ! This function is used in the calculation of the Wind Farm models' PSD + + IMPLICIT NONE + + REAL(ReKi) :: Beta10 + REAL(ReKi), INTENT(IN) :: X + REAL(ReKi), PARAMETER :: Tmp = 0.5 + + + IF ( X < 0.0 ) THEN + Beta10 = -Beta6(Tmp, X**2) + ELSE + Beta10 = Beta6(Tmp, X**2) + ENDIF + + RETURN + END FUNCTION Beta10 + !======================================================================= +END SUBROUTINE Spec_WF_DW + +!======================================================================= +END MODULE TS_VelocitySpectra diff --git a/OpenFAST/modules/version/CMakeLists.txt b/OpenFAST/modules/version/CMakeLists.txt new file mode 100644 index 000000000..1a1b0af02 --- /dev/null +++ b/OpenFAST/modules/version/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# Copyright 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. +# + +# Allow the git-version information to be set externally for the +# package manager distributions (homebrew, conda, apt) that download +# the tarball source code rather than clone with git. +if( DEFINED GIT_DESCRIBE ) + message( WARNING + "Version information has been set as a CMake flag. This should only used when the git-version cannot be set automatically." + ) +else() + include(GetGitRevisionDescription) + git_describe(GIT_DESCRIBE) +endif() +add_definitions(-DGIT_VERSION_INFO="${GIT_DESCRIBE}") + +add_library(versioninfolib src/VersionInfo.f90) + +install(TARGETS versioninfolib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) diff --git a/OpenFAST/modules/version/README.md b/OpenFAST/modules/version/README.md new file mode 100644 index 000000000..f2efaabd7 --- /dev/null +++ b/OpenFAST/modules/version/README.md @@ -0,0 +1,20 @@ +# Version Module + +## Overview +The Version module provides all driver and glue codes with the version based +on the git status. OpenFAST follows [semantic versioning](https://semver.org). +In summary, this means that with a version number as MAJOR.MINOR.PATCH, the +components will be incremented as follows: + +- MAJOR version when introducing incompatible API changes, +- MINOR version when adding functionality in a backwards-compatible manner, and +- PATCH version when making backwards-compatible bug fixes. + +For example, ``OpenFAST-v1.0.0-123-gabcd1234-dirty`` describes OpenFAST as: + +- v1.0.0 is the MAJOR.MINOR.PATCH numbering system and corresponds to a tagged + commit made by NREL on GitHub +- 123-g is the number of additional commits after the most recent tag for a + build [the ``-g`` is for ``git``] +- abcd1234 is the first 8 characters of the current commit hash +- dirty denotes that local changes have been made but not committed diff --git a/OpenFAST/modules/version/src/VersionInfo.f90 b/OpenFAST/modules/version/src/VersionInfo.f90 new file mode 100644 index 000000000..27dbc73e7 --- /dev/null +++ b/OpenFAST/modules/version/src/VersionInfo.f90 @@ -0,0 +1,45 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! 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 VersionInfo + + implicit none + +contains + +FUNCTION QueryGitVersion() + + CHARACTER(200) :: QueryGitVersion + +! The Visual Studio project sets the path for where to find the header file with version info +#ifdef GIT_INCLUDE_FILE +#include GIT_INCLUDE_FILE +#endif + +#ifdef GIT_VERSION_INFO + QueryGitVersion = GIT_VERSION_INFO +#else + QueryGitVersion = 'unversioned' +#endif + + RETURN +END FUNCTION QueryGitVersion + +END MODULE diff --git a/OpenFAST/reg_tests/CMakeLists.txt b/OpenFAST/reg_tests/CMakeLists.txt new file mode 100644 index 000000000..71350e798 --- /dev/null +++ b/OpenFAST/reg_tests/CMakeLists.txt @@ -0,0 +1,104 @@ +# +# Copyright 2017 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. +# + +# ----------------------------------------------------------- +# -- OpenFAST Testing +# ----------------------------------------------------------- + +cmake_minimum_required(VERSION 2.8.12) +project(OpenFAST_RegressionTest Fortran) + +include(CTest) + +# Store the CTest build directory +set(CTEST_BINARY_DIR "${CMAKE_BINARY_DIR}/reg_tests") + +# Verify that the test data submodule exists +if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/r-test") + message(FATAL_ERROR "CMake cannot find the test data directory, r-test. Did you initialize the git submodule?" ) +endif() + +# Set the default plotting flag to OFF +option(CTEST_PLOT_ERRORS "Generate plots of regression test errors." OFF) + +# Set the OpenFAST executable configuration option and default +set(CTEST_OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast" CACHE FILEPATH "Specify the OpenFAST executable to use in testing.") + +# Set the AeroDyn executable configuration option and default +set(CTEST_AERODYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/aerodyn/aerodyn_driver" CACHE FILEPATH "Specify the AeroDyn driver executable to use in testing.") + +# Set the BeamDyn executable configuration option and default +set(CTEST_BEAMDYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/beamdyn/beamdyn_driver" CACHE FILEPATH "Specify the BeamDyn driver executable to use in testing.") + +# Set the HydroDyn executable configuration option and default +set(CTEST_HYDRODYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/hydrodyn/hydrodyn_driver" CACHE FILEPATH "Specify the HydroDyn driver executable to use in testing.") + +# Set the python executable configuration option and default +if(NOT EXISTS ${PYTHON_EXECUTABLE}) + find_program(PYTHON_EXECUTABLE NAMES python3 python py) + if(NOT EXISTS ${PYTHON_EXECUTABLE}) + message(FATAL_ERROR "CMake cannot find a Python interpreter in your path. Python is required to run OpenFAST tests." ) + endif() +endif() + +# Set the testing tolerance +set(CTEST_REGRESSION_TOL "0.00001" CACHE STRING "Set the tolerance for the regression test. Leave empty to automatically set.") +if(NOT ${CTEST_REGRESSION_TOL} STREQUAL "") + set(TOLERANCE ${CTEST_REGRESSION_TOL}) +else(NOT ${CTEST_REGRESSION_TOL} STREQUAL "") + set(TOLERANCE 0.00001) +endif() + +# include the r-test cmake projects (servodyn controllers) +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/r-test") + +# build and seed the test directories with the data they need to run the tests +file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}) +foreach(regTest glue-codes/openfast modules/aerodyn modules/beamdyn modules/hydrodyn) + file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}/${regTest}) +endforeach() + +## openfast seed +foreach(turbineDirectory 5MW_Baseline AOC AWT27 SWRT UAE_VI WP_Baseline) + file(COPY "${CMAKE_CURRENT_LIST_DIR}/r-test/glue-codes/openfast/${turbineDirectory}" + DESTINATION "${CTEST_BINARY_DIR}/glue-codes/openfast/") +endforeach() + +# add the tests +include(${CMAKE_CURRENT_LIST_DIR}/CTestList.cmake) + +set(src "${CMAKE_CURRENT_LIST_DIR}/r-test/glue-codes/openfast/5MW_Baseline/ServoData") +set(dest "${CTEST_BINARY_DIR}/glue-codes/openfast/5MW_Baseline/ServoData/") +add_custom_command( + OUTPUT "${dest}/DISCON.dll" + DEPENDS DISCON + COMMAND "${CMAKE_COMMAND}" -E copy "${src}/DISCON/build/DISCON.dll" "${dest}" +) +add_custom_command( + OUTPUT "${dest}/DISCON_ITIBarge.dll" + DEPENDS DISCON_ITIBarge + COMMAND "${CMAKE_COMMAND}" -E copy "${src}/DISCON_ITI/build/DISCON_ITIBarge.dll" "${dest}" + ) +add_custom_command( + OUTPUT "${dest}/DISCON_OC3Hywind.dll" + DEPENDS DISCON_OC3Hywind + COMMAND "${CMAKE_COMMAND}" -E copy "${src}/DISCON_OC3/build/DISCON_OC3Hywind.dll" "${dest}" +) + +add_custom_target( + regression_tests + DEPENDS openfast "${dest}/DISCON.dll" "${dest}/DISCON_ITIBarge.dll" "${dest}/DISCON_OC3Hywind.dll" +) diff --git a/OpenFAST/reg_tests/CTestList.cmake b/OpenFAST/reg_tests/CTestList.cmake new file mode 100644 index 000000000..6c0209050 --- /dev/null +++ b/OpenFAST/reg_tests/CTestList.cmake @@ -0,0 +1,175 @@ +# +# Copyright 2017 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. +# + +#=============================================================================== +# Generic test functions +#=============================================================================== + +function(regression TEST_SCRIPT EXECUTABLE SOURCE_DIRECTORY BUILD_DIRECTORY TESTNAME LABEL) + file(TO_NATIVE_PATH "${PYTHON_EXECUTABLE}" PYTHON_EXECUTABLE) + + file(TO_NATIVE_PATH "${EXECUTABLE}" EXECUTABLE) + file(TO_NATIVE_PATH "${TEST_SCRIPT}" TEST_SCRIPT) + file(TO_NATIVE_PATH "${SOURCE_DIRECTORY}" SOURCE_DIRECTORY) + file(TO_NATIVE_PATH "${BUILD_DIRECTORY}" BUILD_DIRECTORY) + + string(REPLACE "\\" "\\\\" EXECUTABLE ${EXECUTABLE}) + string(REPLACE "\\" "\\\\" TEST_SCRIPT ${TEST_SCRIPT}) + string(REPLACE "\\" "\\\\" SOURCE_DIRECTORY ${SOURCE_DIRECTORY}) + string(REPLACE "\\" "\\\\" BUILD_DIRECTORY ${BUILD_DIRECTORY}) + + set(PLOT_FLAG "") + if(CTEST_PLOT_ERRORS) + set(PLOT_FLAG "-p") + endif() + + add_test( + ${TESTNAME} ${PYTHON_EXECUTABLE} + ${TEST_SCRIPT} + ${TESTNAME} + ${EXECUTABLE} + ${SOURCE_DIRECTORY} # openfast source directory + ${BUILD_DIRECTORY} # build directory for test + ${TOLERANCE} + ${CMAKE_SYSTEM_NAME} # [Darwin,Linux,Windows] + ${CMAKE_Fortran_COMPILER_ID} # [Intel,GNU] + ${PLOT_FLAG} # empty or "-p" + ) + # limit each test to 90 minutes: 5400s + set_tests_properties(${TESTNAME} PROPERTIES TIMEOUT 5400 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" LABELS "${LABEL}") +endfunction(regression) + +#=============================================================================== +# Module specific regression test calls +#=============================================================================== + +# openfast +function(of_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeOpenfastRegressionCase.py") + set(OPENFAST_EXECUTABLE "${CTEST_OPENFAST_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/glue-codes/openfast") + regression(${TEST_SCRIPT} ${OPENFAST_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(of_regression) + +# openfast aeroacoustic +function(of_regression_aeroacoustic TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeOpenfastAeroAcousticRegressionCase.py") + set(OPENFAST_EXECUTABLE "${CTEST_OPENFAST_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/glue-codes/openfast") + regression(${TEST_SCRIPT} ${OPENFAST_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(of_regression_aeroacoustic) + +# beamdyn +# openfast linearized +function(of_regression_linear TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeOpenfastLinearRegressionCase.py") + set(OPENFAST_EXECUTABLE "${CTEST_OPENFAST_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/glue-codes/openfast") + regression(${TEST_SCRIPT} ${OPENFAST_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(of_regression_linear) + +# aerodyn +function(ad_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeAerodynRegressionCase.py") + set(AERODYN_EXECUTABLE "${CTEST_AERODYN_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/modules/aerodyn") + regression(${TEST_SCRIPT} ${AERODYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(ad_regression) + +# beamdyn +function(bd_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeBeamdynRegressionCase.py") + set(BEAMDYN_EXECUTABLE "${CTEST_BEAMDYN_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/modules/beamdyn") + regression(${TEST_SCRIPT} ${BEAMDYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(bd_regression) + +# hydrodyn +function(hd_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeHydrodynRegressionCase.py") + set(HYDRODYN_EXECUTABLE "${CTEST_HYDRODYN_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/modules/hydrodyn") + regression(${TEST_SCRIPT} ${HYDRODYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(hd_regression) + +#=============================================================================== +# Regression tests +#=============================================================================== + +# OpenFAST regression tests +of_regression("AWT_YFix_WSt" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("AWT_WSt_StartUp_HighSpShutDown" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("AWT_YFree_WSt" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("AWT_YFree_WTurb" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("AWT_WSt_StartUpShutDown" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("AOC_WSt" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("AOC_YFree_WTurb" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("AOC_YFix_WSt" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("UAE_Dnwind_YRamp_WSt" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("UAE_Upwind_Rigid_WRamp_PwrCurve" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("WP_VSP_WTurb_PitchFail" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("WP_VSP_ECD" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("WP_VSP_WTurb" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("SWRT_YFree_VS_EDG01" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("SWRT_YFree_VS_EDC01" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("SWRT_YFree_VS_WTurb" "openfast;elastodyn;aerodyn14;servodyn") +of_regression("5MW_Land_DLL_WTurb" "openfast;elastodyn;aerodyn15;servodyn") +of_regression("5MW_OC3Mnpl_DLL_WTurb_WavesIrr" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;subdyn;offshore") +of_regression("5MW_OC3Trpd_DLL_WSt_WavesReg" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;subdyn;offshore") +of_regression("5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;subdyn;offshore") +of_regression("5MW_ITIBarge_DLL_WTurb_WavesIrr" "openfast;elastodyn;aerodyn14;servodyn;hydrodyn;map;offshore") +of_regression("5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;map;offshore") +of_regression("5MW_OC3Spar_DLL_WTurb_WavesIrr" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;map;offshore") +of_regression("5MW_OC4Semi_WSt_WavesWN" "openfast;elastodyn;aerodyn15;servodyn;hydrodyn;moordyn;offshore") +of_regression("5MW_Land_BD_DLL_WTurb" "openfast;beamdyn;aerodyn15;servodyn") +of_regression("5MW_OC4Jckt_ExtPtfm" "openfast;elastodyn;extptfm") +of_regression("HelicalWake_OLAF" "openfast;aerodyn15;olaf") +of_regression("EllipticalWing_OLAF" "openfast;aerodyn15;olaf") + +# AeroAcoustic regression test +of_regression_aeroacoustic("IEA_LB_RWT-AeroAcoustics" "openfast;aerodyn15;aeroacoustics") + +# Linearized OpenFAST regression tests +of_regression_linear("WP_Stationary_Linear" "openfast;linear;elastodyn") +of_regression_linear("Ideal_Beam_Fixed_Free_Linear" "openfast;linear;beamdyn") +of_regression_linear("Ideal_Beam_Free_Free_Linear" "openfast;linear;beamdyn") +of_regression_linear("5MW_Land_BD_Linear" "openfast;linear;beamdyn;servodyn") +of_regression_linear("5MW_OC4Semi_Linear" "openfast;linear;hydrodyn;servodyn") + +# AeroDyn regression tests +ad_regression("ad_timeseries_shutdown" "aerodyn;bem") + +# BeamDyn regression tests +bd_regression("bd_5MW_dynamic" "beamdyn;dynamic") +bd_regression("bd_5MW_dynamic_gravity_Az00" "beamdyn;dynamic") +bd_regression("bd_5MW_dynamic_gravity_Az90" "beamdyn;dynamic") +bd_regression("bd_curved_beam" "beamdyn;static") +bd_regression("bd_isotropic_rollup" "beamdyn;static") +bd_regression("bd_static_cantilever_beam" "beamdyn;static") +bd_regression("bd_static_twisted_with_k1" "beamdyn;static") + +# HydroDyn regression tests +hd_regression("hd_OC3tripod_offshore_fixedbottom_wavesirr" "hydrodyn;offshore") +hd_regression("hd_5MW_ITIBarge_DLL_WTurb_WavesIrr" "hydrodyn;offshore") +hd_regression("hd_5MW_OC3Spar_DLL_WTurb_WavesIrr" "hydrodyn;offshore") +hd_regression("hd_5MW_OC4Semi_WSt_WavesWN" "hydrodyn;offshore") +hd_regression("hd_5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti" "hydrodyn;offshore") diff --git a/OpenFAST/reg_tests/README.md b/OpenFAST/reg_tests/README.md new file mode 100644 index 000000000..12f84f2f0 --- /dev/null +++ b/OpenFAST/reg_tests/README.md @@ -0,0 +1,88 @@ +# openfast/reg_tests + +This directory contains the regression test suite for OpenFAST and its modules. Its contents are listed here and further described below. +- [r-test](https://github.com/openfast/r-test), a standalone repository containing the regression test data +- CMake/CTest configuration files +- Module specific regression test execution scripts +- A `lib` subdirectory with lower level python scripts + +Dependencies required to run the regression test suite are +- Python 3.7+ +- Numpy +- CMake and CTest +- Bokeh 1.4 (optional) + +## Execution +The automated regression test runs CTest and can be executed by running either of the commands `make test` or `ctest` from the build directory. If the entire OpenFAST package is to be built, CMake will configure CTest to find the new binary at `openfast/build/glue-codes/openfast/openfast`. However, if the intention is to build only the test suite, the OpenFAST binary should be specified in the CMake configuration under the `CTEST_OPENFAST_EXECUTABLE` flag. There is also a corresponding `CTEST_[MODULE]_NAME` flag for each module that is included in the regression test. + +The regression test can be executed manually with the included driver `manualRegressionTest.py`. Run `manualRegressionTest.py -h` for usage. + +In both modes of execution a subdirectory is created in the build directory called `reg_tests` where all of the input files for the test cases are copied and all of the locally generated outputs are stored. + +## r-test +This repository serves as a container for regression test data for system level and module level testing of OpenFAST. The repository contains: +- input files for test case execution +- baseline solutions for various machine and compiler combinations +- turbine specific inputs + +The baseline solutions serve as "gold standards" for the regression test suite and are updated periodically as OpenFAST and its modules are improved. + +r-test is brought into OpenFAST as a git submodule and should be initialized after cloning with `git submodule update --init --recursive` or updated with `git submodule update`. + +## CTest/CMake +The configuration files consist of +- CMakeLists.txt +- CTestList.cmake + +#### CMakeLists.txt +This is a CMake file which configures the regression test in the CMake build directory. It should be left untouched unless advanced configuration of CMake or CTest is required. + +#### CTestList.txt +This is the CTest configuration file which lists the test cases that run in the automated test. The test list can be modified as needed by commenting lines with a `#`, but the full regression test consists of all the tests listed in this file. + +## Python Scripts +The included Python scripts are used to execute various parts of the automated regression test, so they should remain in their current location with their current name. Each script can be executed independently. The syntax and options for using the scripts can be found by running each with the `-h` flag. + +#### executeOpenfastRegressionCase.py +This program executes OpenFAST and a regression test for a single test case. +The test data is contained in a git submodule, r-test, which must be initialized +prior to running. See the r-test README or OpenFAST documentation for more info. + +Get usage with: `executeOpenfastRegressionCase.py -h` + +#### executeBeamdynRegressionCase.py +This program executes BeamDyn and a regression test for a single test case. +The test data is contained in a git submodule, r-test, which must be initialized +prior to running. See the r-test README or OpenFAST documentation for more info. + +Get usage with: `executeBeamdynRegressionCase.py -h` + +#### manualRegressionTest.py +This program executes OpenFAST on all of the CertTest cases. It mimics the +regression test execution through CMake/CTest. All generated data goes into +`openfast/build/reg_tests`. + +Get usage with: `manualRegressionTest.py -h` + +#### lib/errorPlotting.py +This library provides tools for plotting the output channels over time of a +given solution attribute for two OpenFAST solutions, with the second solution +assumed to be the baseline for comparison. There are functions for solution +file I/O, plot creation, and html creation for navigating the plots. + +#### lib/fast_io.py +This program reads OpenFAST structured output files in binary or ascii format +and returns the data in a Numpy array. + +#### lib/openfastDrivers.py +This library provides tools for executing cases with drivers contained in the +OpenFAST framework. Any new drivers should have a corresponding public driver +function called `def run[NewDriver]Case()` in this library. + +#### lib/pass_fail.py +This library provides tools for comparing a test solution to a baseline solution +for any structured output file generated within the OpenFAST framework. + +#### lib/rtestlib.py +This library contains utility functions for the custom python programs making +up the regression test system. diff --git a/OpenFAST/reg_tests/executeAerodynRegressionCase.py b/OpenFAST/reg_tests/executeAerodynRegressionCase.py new file mode 100644 index 000000000..8bcd869d5 --- /dev/null +++ b/OpenFAST/reg_tests/executeAerodynRegressionCase.py @@ -0,0 +1,138 @@ +# +# Copyright 2017 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. +# + +""" + This program executes AeroDyn and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeAerodynRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import glob +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="AeroDyn-Driver", type=str, nargs=1, help="The path to the AeroDyn driver executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", action='store_true', help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", action='store_true', help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", action='store_true', help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +plotError = args.plot if args.plot is False else True +noExec = args.noExec if args.noExec is False else True +verbose = args.verbose if args.verbose is False else True + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Build the filesystem navigation variables for running the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "modules", "aerodyn") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# 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,"ad_*inp")): + filename = file.split(os.path.sep)[-1] + shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) + +### Run aerodyn on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, "ad_driver.inp") + returnCode = openfastDrivers.runAerodynDriverCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +localOutFile = os.path.join(testBuildDirectory, "ad_driver.out") +baselineOutFile = os.path.join(targetOutputDirectory, "ad_driver.out") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + ixFailChannels = [i for i in range(len(testInfo["attribute_names"])) if normalizedNorm[i] > tolerance] + failChannels = [channel for i, channel in enumerate(testInfo["attribute_names"]) if i in ixFailChannels] + failResults = [res for i, res in enumerate(results) if i in ixFailChannels] + for channel in failChannels: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error.msg)) + finalizePlotDirectory(localOutFile, failChannels, caseName) + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/executeBeamdynRegressionCase.py b/OpenFAST/reg_tests/executeBeamdynRegressionCase.py new file mode 100644 index 000000000..4aad3fb70 --- /dev/null +++ b/OpenFAST/reg_tests/executeBeamdynRegressionCase.py @@ -0,0 +1,137 @@ +# +# Copyright 2017 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. +# + +""" + This program executes BeamDyn and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeBeamdynRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="BeamDyn-Driver", type=str, nargs=1, help="The path to the BeamDyn driver executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", action='store_true', help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", action='store_true', help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", action='store_true', help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +plotError = args.plot if args.plot is False else True +noExec = args.noExec if args.noExec is False else True +verbose = args.verbose if args.verbose is False else True + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Build the filesystem navigation variables for running the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "modules", "beamdyn") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# and initialize it with input files for all test cases +if not os.path.isdir(testBuildDirectory): + os.makedirs(testBuildDirectory) + shutil.copy(os.path.join(inputsDirectory,"bd_driver.inp"), os.path.join(testBuildDirectory,"bd_driver.inp")) + shutil.copy(os.path.join(inputsDirectory,"bd_primary.inp"), os.path.join(testBuildDirectory,"bd_primary.inp")) + shutil.copy(os.path.join(inputsDirectory,"beam_props.inp"), os.path.join(testBuildDirectory,"beam_props.inp")) + +### Run beamdyn on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, "bd_driver.inp") + returnCode = openfastDrivers.runBeamdynDriverCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +localOutFile = os.path.join(testBuildDirectory, "bd_driver.out") +baselineOutFile = os.path.join(targetOutputDirectory, "bd_driver.out") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + ixFailChannels = [i for i in range(len(testInfo["attribute_names"])) if normalizedNorm[i] > tolerance] + failChannels = [channel for i, channel in enumerate(testInfo["attribute_names"]) if i in ixFailChannels] + failResults = [res for i, res in enumerate(results) if i in ixFailChannels] + for channel in failChannels: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error.msg)) + finalizePlotDirectory(localOutFile, failChannels, caseName) + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/executeHydrodynRegressionCase.py b/OpenFAST/reg_tests/executeHydrodynRegressionCase.py new file mode 100644 index 000000000..1f559a6a5 --- /dev/null +++ b/OpenFAST/reg_tests/executeHydrodynRegressionCase.py @@ -0,0 +1,141 @@ +# +# Copyright 2017 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. +# + +""" + This program executes HydroDyn and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeHydrodynRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import glob +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes HydroDyn and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="HydroDyn-Driver", type=str, nargs=1, help="The path to the HydroDyn driver executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", default=False, metavar="Plotting-Flag", type=bool, nargs="?", help="bool to include matplotlib plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", default=False, metavar="No-Execution", type=bool, nargs="?", help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", default=False, metavar="Verbose-Flag", type=bool, nargs="?", help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +plotError = args.plot if args.plot is False else True +noExec = args.noExec if args.noExec is False else True +verbose = args.verbose if args.verbose is False else True + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Build the filesystem navigation variables for running the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "modules", "hydrodyn") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# 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,"hd_*inp")): + filename = file.split(os.path.sep)[-1] + shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) + for file in glob.glob(os.path.join(inputsDirectory,"*dat")): + filename = file.split(os.path.sep)[-1] + shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) + +### Run HydroDyn on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, "hd_driver.inp") + returnCode = openfastDrivers.runHydrodynDriverCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +localOutFile = os.path.join(testBuildDirectory, "driver.HD.out") +baselineOutFile = os.path.join(targetOutputDirectory, "driver.HD.out") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + ixFailChannels = [i for i in range(len(testInfo["attribute_names"])) if normalizedNorm[i] > tolerance] + failChannels = [channel for i, channel in enumerate(testInfo["attribute_names"]) if i in ixFailChannels] + failResults = [res for i, res in enumerate(results) if i in ixFailChannels] + for channel in failChannels: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error.msg)) + finalizePlotDirectory(localOutFile, failChannels, caseName) + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/executeOpenfastAeroAcousticRegressionCase.py b/OpenFAST/reg_tests/executeOpenfastAeroAcousticRegressionCase.py new file mode 100644 index 000000000..ccb9de8cd --- /dev/null +++ b/OpenFAST/reg_tests/executeOpenfastAeroAcousticRegressionCase.py @@ -0,0 +1,169 @@ +# +# Copyright 2017 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. +# + +""" + This program executes OpenFAST and a regression test for a single test case with + the aero-acoustics module in AeroDyn15. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeOpenfastAeroAcousticRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Helper functions +def ignoreBaselineItems(directory, contents): + itemFilter = ['linux-intel', 'linux-gnu', 'macos-gnu', 'windows-intel'] + caught = [] + for c in contents: + if c in itemFilter: + caught.append(c) + return tuple(caught) + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="OpenFAST", type=str, nargs=1, help="The path to the OpenFAST executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", action='store_true', help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", action='store_true', help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", action='store_true', help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +systemName = args.systemName[0] +compilerId = args.compilerId[0] +plotError = args.plot +noExec = args.noExec +verbose = args.verbose + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Map the system and compiler configurations to a solution set +# Internal names -> Human readable names +systemName_map = { + "darwin": "macos", + "linux": "linux", + "windows": "windows" +} +compilerId_map = { + "gnu": "gnu", + "intel": "intel" +} +# Build the target output directory name or choose the default +supportedBaselines = ["macos-gnu", "linux-intel", "linux-gnu", "windows-intel"] +targetSystem = systemName_map.get(systemName.lower(), "") +targetCompiler = compilerId_map.get(compilerId.lower(), "") +outputType = os.path.join(targetSystem+"-"+targetCompiler) +if outputType not in supportedBaselines: + outputType = supportedBaselines[0] +print("-- Using gold standard files with machine-compiler type {}".format(outputType)) + +### Build the filesystem navigation variables for running openfast on the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "glue-codes", "openfast") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory, outputType) +testBuildDirectory = os.path.join(buildDirectory, caseName) + + + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# and initialize it with input files for all test cases +if not os.path.isdir(testBuildDirectory): + shutil.copytree(inputsDirectory, testBuildDirectory, ignore=ignoreBaselineItems) + +### Run openfast on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, caseName + ".fst") + returnCode = openfastDrivers.runOpenfastCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +# testing on file 2. Gives each observer and sweep of frequency ranges +localOutFile = os.path.join(testBuildDirectory, caseName + "_2.out") +baselineOutFile = os.path.join(targetOutputDirectory, caseName + "_2.out") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + ixFailChannels = [i for i in range(len(testInfo["attribute_names"])) if normalizedNorm[i] > tolerance] + failChannels = [channel for i, channel in enumerate(testInfo["attribute_names"]) if i in ixFailChannels] + failResults = [res for i, res in enumerate(results) if i in ixFailChannels] + for channel in failChannels: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error.msg)) + finalizePlotDirectory(localOutFile, failChannels, caseName) + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/executeOpenfastLinearRegressionCase.py b/OpenFAST/reg_tests/executeOpenfastLinearRegressionCase.py new file mode 100644 index 000000000..d23937bbf --- /dev/null +++ b/OpenFAST/reg_tests/executeOpenfastLinearRegressionCase.py @@ -0,0 +1,272 @@ +# +# Copyright 2017 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. +# + +""" + This program executes OpenFAST and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeOpenfastLinearRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Helper functions +def ignoreBaselineItems(directory, contents): + itemFilter = ['linux-intel', 'linux-gnu', 'macos-gnu', 'windows-intel'] + caught = [] + for c in contents: + if c in itemFilter: + caught.append(c) + return tuple(caught) + +def file_line_count(filename): + file_handle = open(filename, 'r') + for i, _ in enumerate(file_handle): + pass + file_handle.close() + return i + 1 + +def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): + return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="OpenFAST", type=str, nargs=1, help="The path to the OpenFAST executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", default=False, metavar="Plotting-Flag", type=bool, nargs="?", help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", default=False, metavar="No-Execution", type=bool, nargs="?", help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", default=False, metavar="Verbose-Flag", type=bool, nargs="?", help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +systemName = args.systemName[0] +compilerId = args.compilerId[0] +plotError = args.plot if args.plot is False else True +noExec = args.noExec if args.noExec is False else True +verbose = args.verbose if args.verbose is False else True + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Map the system and compiler configurations to a solution set +# Internal names -> Human readable names +systemName_map = { + "darwin": "macos", + "linux": "linux", + "windows": "windows" +} +compilerId_map = { + "gnu": "gnu", + "intel": "intel" +} +# Build the target output directory name or choose the default +supportedBaselines = ["macos-gnu", "linux-intel", "linux-gnu", "windows-intel"] +targetSystem = systemName_map.get(systemName.lower(), "") +targetCompiler = compilerId_map.get(compilerId.lower(), "") +outputType = os.path.join(targetSystem+"-"+targetCompiler) +if outputType not in supportedBaselines: + outputType = supportedBaselines[0] +print("-- Using gold standard files with machine-compiler type {}".format(outputType)) + +### Build the filesystem navigation variables for running openfast on the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "glue-codes", "openfast") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory, outputType) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# and initialize it with input files for all test cases +for data in ["Ideal_Beam", "WP_Baseline"]: + dataDir = os.path.join(buildDirectory, data) + if not os.path.isdir(dataDir): + shutil.copytree(os.path.join(moduleDirectory, data), dataDir) + +# Special copy for the 5MW_Baseline folder because the Windows python-only workflow may have already created data in the subfolder ServoData +dst = os.path.join(buildDirectory, "5MW_Baseline") +src = os.path.join(moduleDirectory, "5MW_Baseline") +if not os.path.isdir(dst): + shutil.copytree(src, dst) +else: + names = os.listdir(src) + for name in names: + if name == "ServoData": + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + if os.path.isdir(srcname): + if not os.path.isdir(dstname): + shutil.copytree(srcname, dstname) + else: + shutil.copy2(srcname, dstname) + +if not os.path.isdir(testBuildDirectory): + shutil.copytree(inputsDirectory, testBuildDirectory, ignore=ignoreBaselineItems) + +### Run openfast on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, caseName + ".fst") + returnCode = openfastDrivers.runOpenfastCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Get a list of all the files in the baseline directory +baselineOutFiles = os.listdir(targetOutputDirectory) +# Drop the log file, if its listed +if caseName + '.log' in baselineOutFiles: + baselineOutFiles.remove(caseName + '.log') + +# these should all exist in the local outputs directory +localFiles = os.listdir(testBuildDirectory) +localOutFiles = [f for f in localFiles if f in baselineOutFiles] +if len(localOutFiles) != len(baselineOutFiles): + print("Error in case {}: an expected local solution file does not exist.".format(caseName)) + sys.exit(1) + +### test for regression +for i, f in enumerate(localOutFiles): + local_file = os.path.join(testBuildDirectory, f) + baseline_file = os.path.join(targetOutputDirectory, f) + + # verify both files have the same number of lines + local_file_line_count = file_line_count(local_file) + baseline_file_line_count = file_line_count(baseline_file) + if local_file_line_count != baseline_file_line_count: + print("Error in case {}: local and baseline solutions have different line counts in".format(caseName)) + print("\t{}".format(local_file)) + print("\t{}".format(baseline_file)) + sys.exit(1) + + # open both files + local_handle = open(local_file, 'r') + baseline_handle = open(baseline_file, 'r') + + # parse the files + + # skip the first 6 lines since they are headers and may change without conseequence + for i in range(6): + baseline_handle.readline() + local_handle.readline() + + # the next 10 lines are simulation info; save what we need + for i in range(11): + b_line = baseline_handle.readline() + l_line = local_handle.readline() + if i == 5: + b_num_continuous_states = int(b_line.split()[-1]) + l_num_continuous_states = int(l_line.split()[-1]) + elif i == 8: + b_num_inputs = int(b_line.split()[-1]) + l_num_inputs = int(l_line.split()[-1]) + elif i == 9: + b_num_outputs = int(b_line.split()[-1]) + l_num_outputs = int(l_line.split()[-1]) + + # find the "Jacobian matrices:" line + for i in range(local_file_line_count): + b_line = baseline_handle.readline() + l_line = local_handle.readline() + if "Jacobian matrices:" in l_line: + break + + # skip 1 empty/header lines + for i in range(1): + baseline_handle.readline() + local_handle.readline() + + # read and compare Jacobian matrices + for i in range(local_file_line_count): + b_line = baseline_handle.readline() + l_line = local_handle.readline() + if ":" in l_line: + continue + if len(l_line) < 5: + break + b_elements = b_line.split() + l_elements = l_line.split() + for j, l_element in enumerate(l_elements): + l_float = float(l_element) + b_float = float(b_elements[j]) + if not isclose(l_float, b_float, tolerance, tolerance): + print(f"Failed in Jacobian matrix comparison: {l_float} and {b_float}") + sys.exit(1) + + # skip 2 empty/header lines + for i in range(2): + baseline_handle.readline() + local_handle.readline() + + # read and compare Linearized state matrices + for i in range(local_file_line_count): + b_line = baseline_handle.readline() + l_line = local_handle.readline() + if ":" in l_line: + continue + if len(l_line) < 5: + break + b_elements = b_line.split() + l_elements = l_line.split() + for j, l_element in enumerate(l_elements): + l_float = float(l_element) + b_float = float(b_elements[j]) + if not isclose(l_float, b_float, tolerance, tolerance): + print(f"Failed in state matrix comparison: {l_float} and {b_float}") + sys.exit(1) + + local_handle.close() + baseline_handle.close() + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/executeOpenfastRegressionCase.py b/OpenFAST/reg_tests/executeOpenfastRegressionCase.py new file mode 100644 index 000000000..975ca0f87 --- /dev/null +++ b/OpenFAST/reg_tests/executeOpenfastRegressionCase.py @@ -0,0 +1,186 @@ +# +# Copyright 2017 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. +# + +""" + This program executes OpenFAST and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeOpenfastRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Helper functions +def ignoreBaselineItems(directory, contents): + itemFilter = ['linux-intel', 'linux-gnu', 'macos-gnu', 'windows-intel'] + caught = [] + for c in contents: + if c in itemFilter: + caught.append(c) + return tuple(caught) + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="OpenFAST", type=str, nargs=1, help="The path to the OpenFAST executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", action='store_true', help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", action='store_true', help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", action='store_true', help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +systemName = args.systemName[0] +compilerId = args.compilerId[0] +plotError = args.plot +noExec = args.noExec +verbose = args.verbose + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Map the system and compiler configurations to a solution set +# Internal names -> Human readable names +systemName_map = { + "darwin": "macos", + "linux": "linux", + "windows": "windows" +} +compilerId_map = { + "gnu": "gnu", + "intel": "intel" +} +# Build the target output directory name or choose the default +supportedBaselines = ["macos-gnu", "linux-intel", "linux-gnu", "windows-intel"] +targetSystem = systemName_map.get(systemName.lower(), "") +targetCompiler = compilerId_map.get(compilerId.lower(), "") +outputType = os.path.join(targetSystem+"-"+targetCompiler) +if outputType not in supportedBaselines: + outputType = supportedBaselines[0] +print("-- Using gold standard files with machine-compiler type {}".format(outputType)) + +### Build the filesystem navigation variables for running openfast on the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "glue-codes", "openfast") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory, outputType) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# and initialize it with input files for all test cases +for data in ["AOC", "AWT27", "SWRT", "UAE_VI", "WP_Baseline"]: + dataDir = os.path.join(buildDirectory, data) + if not os.path.isdir(dataDir): + shutil.copytree(os.path.join(moduleDirectory, data), dataDir) + +# Special copy for the 5MW_Baseline folder because the Windows python-only workflow may have already created data in the subfolder ServoData +dst = os.path.join(buildDirectory, "5MW_Baseline") +src = os.path.join(moduleDirectory, "5MW_Baseline") +if not os.path.isdir(dst): + shutil.copytree(src, dst) +else: + names = os.listdir(src) + for name in names: + if name == "ServoData": + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + if os.path.isdir(srcname): + if not os.path.isdir(dstname): + shutil.copytree(srcname, dstname) + else: + shutil.copy2(srcname, dstname) + +if not os.path.isdir(testBuildDirectory): + shutil.copytree(inputsDirectory, testBuildDirectory, ignore=ignoreBaselineItems) + +### Run openfast on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, caseName + ".fst") + returnCode = openfastDrivers.runOpenfastCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +localOutFile = os.path.join(testBuildDirectory, caseName + ".outb") +baselineOutFile = os.path.join(targetOutputDirectory, caseName + ".outb") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + for channel in testInfo["attribute_names"]: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error)) + finalizePlotDirectory(localOutFile, testInfo["attribute_names"], caseName) + + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/OpenFAST/reg_tests/lib/errorPlotting.py b/OpenFAST/reg_tests/lib/errorPlotting.py new file mode 100644 index 000000000..1778f3fe7 --- /dev/null +++ b/OpenFAST/reg_tests/lib/errorPlotting.py @@ -0,0 +1,289 @@ + +# +# Copyright 2017 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. +# + +""" + This library provides tools for plotting the output channels over time of a + given solution attribute for two OpenFAST solutions, with the second solution + assumed to be the baseline for comparison. There are functions for solution + file I/O, plot creation, and html creation for navigating the plots. +""" + +import os +import sys +import shutil + +import numpy as np + +import rtestlib as rtl +from fast_io import load_output + +def _validateAndExpandInputs(argv): + rtl.validateInputOrExit(argv, 3, "solution1 solution2 attribute") + testSolution = argv[0] + baselineSolution = argv[1] + attribute = argv[2] + rtl.validateFileOrExit(testSolution) + rtl.validateFileOrExit(baselineSolution) + return (testSolution, baselineSolution, attribute) + +def _parseSolution(solution): + try: + data, info, _ = load_output(solution) + return (data, info) + except Exception as e: + rtl.exitWithError("Error: {}".format(e)) + +def _plotError(xseries, y1series, y2series, xlabel, title1, title2): + from bokeh.embed import components + from bokeh.layouts import gridplot + from bokeh.plotting import figure + from bokeh.models.tools import HoverTool, BoxZoomTool + + p1 = figure(title=title1) + p1.title.align = 'center' + p1.grid.grid_line_alpha=0.3 + p1.xaxis.axis_label = 'Time (s)' + p1.line(xseries, y2series, color='green', line_width=3, legend_label='Baseline') + p1.line(xseries, y1series, color='red', line_width=1, legend_label='Local') + p1.add_tools(HoverTool(tooltips=[('Time','@x'), ('Value', '@y')],mode='vline')) + + p2 = figure(title=title2, x_range=p1.x_range) + p2.title.align = 'center' + p2.grid.grid_line_alpha = 0 + p2.xaxis.axis_label = 'Time (s)' + p2.line(xseries, abs(y2series - y1series), color='blue') + p2.add_tools(HoverTool(tooltips=[('Time','@x'), ('Error', '@y')], mode='vline')) + + grid = gridplot([[p1, p2]], plot_width=650, plot_height=375, sizing_mode="scale_both") + script, div = components(grid) + + return script, div + +def _replace_id_div(html_string, plot): + id_start = html_string.find('id=') + 4 + id_end = html_string[id_start:].find('"') + id_start + html_string = plot.join((html_string[:id_start], html_string[id_end:])) + return html_string + +def _replace_id_script(html_string, plot): + id_start = html_string.find('var render_items') + id_start += html_string[id_start:].find('roots') + id_start += html_string[id_start:].find('":"') + 3 + id_end = html_string[id_start:].find('"') + id_start + html_string = plot.join((html_string[:id_start], html_string[id_end:])) + return html_string + +def _save_plot(script, div, path, attribute): + div_class = ' class="col-sm-12 col-md-6 col-lg-6"' + + file_name = "_script".join((attribute, ".txt")) + with open(os.path.join(path, file_name), 'w') as f: + script = _replace_id_script(script.replace('\n', '\n '), attribute) + f.write(script) + + file_name = "_div".join((attribute, ".txt")) + with open(os.path.join(path, file_name), 'w') as f: + div = _replace_id_div(div, attribute) + ix_insert = div.find('></div>') + div = div_class.join((div[:ix_insert], div[ix_insert:])) + style = 'style="margin:10 auto"' + div = div.replace("<div", " ".join(("<div", style))) + f.write(div) + +def plotOpenfastError(testSolution, baselineSolution, attribute): + testSolution, baselineSolution, attribute = _validateAndExpandInputs([ + testSolution, baselineSolution, attribute + ]) + dict1, info1 = _parseSolution(testSolution) + dict2, info2 = _parseSolution(baselineSolution) + + try: + channel = info1['attribute_names'].index(attribute) + except Exception as e: + rtl.exitWithError("Error: Invalid channel name--{}".format(e)) + + title1 = attribute + " (" + info1["attribute_units"][channel] + ")" + title2 = "Max norm" + xlabel = 'Time (s)' + + timevec = dict1[:, 0] + y1series = np.array(dict1[:, channel], dtype = np.float) + y2series = np.array(dict2[:, channel], dtype = np.float) + script, div = _plotError(timevec, y1series, y2series, xlabel, title1, title2) + + basePath = os.path.sep.join(testSolution.split(os.path.sep)[:-1]) + plotPath = os.path.join(basePath, "plots") + rtl.validateDirOrMkdir(plotPath) + _save_plot(script, div, plotPath, attribute) + +def _htmlHead(title): + head = '<!DOCTYPE html>' + '\n' + head += '<html>' + '\n' + head += '<head>' + '\n' + head += ' <title>{}</title>'.format(title) + '\n' + + head += ' <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">' + '\n' + head += ' <link href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.css" rel="stylesheet" type="text/css">' + '\n' + head += ' <link href="https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.css" rel="stylesheet" type="text/css">' + '\n' + + head += ' <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>' + '\n' + head += ' <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>' + '\n' + head += ' <script src="https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.js"></script>' + '\n' + head += ' <script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.js"></script>' + '\n' + head += ' <script type="text/javascript"> Bokeh.set_log_level("info"); </script>' + '\n' + + head += ' <style media="screen" type="text/css">' + head += ' .cell-warning {' + head += ' background-color: #efc15c;' + head += ' }' + head += ' .cell-highlight {' + head += ' background-color: #f5ed86 ;' + head += ' }' + head += ' </style>' + head += '</head>' + '\n' + return head + +def _htmlTail(): + tail = '</html>' + '\n' + return tail + +def _tableHead(columns): + head = ' <table class="table table-bordered table-hover table-sm" style="margin: auto; width: 100%; font-size:80%">' + '\n' + head += ' <thead>' + '\n' + head += ' <tr>' + '\n' + head += ' <th>#</th>' + '\n' + for column in columns: + head += ' <th>{}</th>'.format(column) + '\n' + head += ' </tr>' + '\n' + head += ' </thead>' + '\n' + return head + +def finalizePlotDirectory(test_solution, plot_list, case): + base_path = os.path.sep.join(test_solution.split(os.path.sep)[:-1]) + plot_path = os.path.join(base_path, "plots") + + with open(os.path.join(base_path, '.'.join((case, 'html'))), 'r') as html: + html = html.read() + script_ix = html.rfind('</script>\n') + len('</script>\n') + + for i, plot in enumerate(plot_list): + _path = os.path.join(plot_path, plot + '_div.txt') + with open(_path, 'r') as f: + div = f.read().strip().join((' ', '\n')) + html = ''.join((html, div)) + + html = ''.join((html, ' </div>' + '\n')) + html = ''.join((html, ' </div>' + '\n')) + html = ''.join((html, '</body>' + '\n')) + html = ''.join((html, _htmlTail())) + + for i, plot in enumerate(plot_list): + _path = os.path.join(plot_path, f'{plot}_script.txt') + with open(_path, "r") as f: + _s = f.read() + if i == 0: + script = _s + else: + script = ''.join((script, _s)) + + shutil.rmtree(plot_path, ignore_errors=True) + + script = ''.join((script, '\n')) + html = script.join((html[:script_ix], html[script_ix:])) + with open(os.path.join(base_path, '.'.join((case, 'html'))), 'w') as f: + f.write(html) + +def exportResultsSummary(path, results): + with open(os.path.join(path, "regression_test_summary.html"), "w") as html: + + html.write( _htmlHead("Regression Test Summary") ) + + html.write('<body>' + '\n') + html.write(' <h2 class="text-center">{}</h2>'.format("Regression Test Summary") + '\n') + html.write(' <div class="container">' + '\n') + + # Test Case - Pass/Fail - Max Relative Norm + data = [('<a href="{0}/{0}.html">{0}</a>'.format(r[0]), r[1]) for i,r in enumerate(results)] + table = _tableHead(['Test Case', 'Pass/Fail']) + body = ' <tbody>' + '\n' + for i, d in enumerate(data): + body += ' <tr>' + '\n' + body += ' <th scope="row">{}</th>'.format(i+1) + '\n' + body += ' <td>{0:s}</td>'.format(d[0]) + '\n' + + fmt = '{0:s}' + if d[1] == "FAIL": + body += (' <td class="cell-warning">' + fmt + '</td>').format(d[1]) + '\n' + else: + body += (' <td>' + fmt + '</td>').format(d[1]) + '\n' + + body += ' </tr>' + '\n' + body += ' </tbody>' + '\n' + table += body + table += ' </table>' + '\n' + html.write(table) + + html.write(' <br>' + '\n') + html.write(' </div>' + '\n') + html.write('</body>' + '\n') + html.write( _htmlTail() ) + html.close() + +def exportCaseSummary(path, case, results, results_max, tolerance): + with open(os.path.join(path, case+".html"), "w") as html: + html.write( _htmlHead(case + " Summary") ) + + html.write('<body>\n') + html.write(' <h2 class="text-center">{}</h2>\n'.format(case + " Summary")) + html.write(' <h4 class="text-center">Maximum values for each norm are <span class="cell-warning">highlighted</span> and failing norms (norm >= {0}) are <span class="cell-highlight">highlighted</span></h2>\n'.format(tolerance)) + html.write(' <div class="container">\n') + + data = [ + ('<a href="#{0}">{0}</a>'.format(attribute), *norms) + for attribute, *norms in results + ] + cols = [ + 'Channel', 'Relative Max Norm', + 'Relative L2 Norm', 'Infinity Norm' + ] + table = _tableHead(cols) + + body = ' <tbody>' + '\n' + for i, d in enumerate(data): + body += ' <tr>' + '\n' + body += ' <th scope="row">{}</th>'.format(i+1) + '\n' + body += ' <td>{0:s}</td>'.format(d[0]) + '\n' + + fmt = '{0:0.4e}' + for j, val in enumerate(d[1]): + if val == results_max[j]: + body += (' <td class="cell-warning">' + fmt + '</td>\n').format(val) + elif val > tolerance: + body += (' <td class="cell-highlight">' + fmt + '</td>\n').format(val) + else: + body += (' <td>' + fmt + '</td>\n').format(val) + + body += ' </tr>' + '\n' + body += ' </tbody>' + '\n' + table += body + table += ' </table>' + '\n' + html.write(table) + + html.write(' <br>' + '\n') + html.write(' </div>' + '\n') + html.write('</body>' + '\n') + html.write( _htmlTail() ) diff --git a/OpenFAST/reg_tests/lib/fast_io.py b/OpenFAST/reg_tests/lib/fast_io.py new file mode 100644 index 000000000..c730f9937 --- /dev/null +++ b/OpenFAST/reg_tests/lib/fast_io.py @@ -0,0 +1,180 @@ +# +# Copyright 2017 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. +# + +''' +Created on 03/09/2015 +@author: MMPE +Copied from https://github.com/WISDEM/AeroelasticSE/tree/openmdao1/src/AeroelasticSE/old_files on 15 Aug 2016 by Ganesh Vijayakumar +''' +import os +import numpy as np +import struct + +def load_output(filename): + """ + Load a FAST binary or ascii output file + + Parameters + ---------- + filename : str + filename + + Returns + ------- + data: ndarray + data values + info: dict + info containing: + - name: filename + - description: description of dataset + - attribute_names: list of attribute names + - attribute_units: list of attribute units + """ + + assert os.path.isfile(filename), "File, %s, does not exists" % filename + with open(filename, 'r') as f: + if "outb" in filename: + return load_binary_output(filename) + elif "out" in filename: + try: + print(f.readline()) + except UnicodeDecodeError: + return load_binary_output(filename) + return load_ascii_output(filename) + (np.ones(1),) + +def load_ascii_output(filename): + with open(filename) as f: + info = {} + info['name'] = os.path.splitext(os.path.basename(filename))[0] + try: + header = [f.readline() for _ in range(8)] + info['description'] = header[4].strip() + info['attribute_names'] = header[6].split() + info['attribute_units'] = [unit[1:-1] for unit in header[7].split()] #removing "()" + data = np.array([line.split() for line in f.readlines()]).astype(np.float) + return data, info + + except (ValueError, AssertionError): + raise + +def load_binary_output(filename): + """ + Ported from ReadFASTbinary.m by Mads M Pedersen, DTU Wind + Info about ReadFASTbinary.m: + Author: Bonnie Jonkman, National Renewable Energy Laboratory + (c) 2012, National Renewable Energy Laboratory + Edited for FAST v7.02.00b-bjj 22-Oct-2012 + """ + + def fread(fid, n, type): + fmt, nbytes = {'uint8': ('B', 1), 'int16':('h', 2), 'int32':('i', 4), 'float32':('f', 4), 'float64':('d', 8)}[type] + return struct.unpack(fmt * n, fid.read(nbytes * n)) + + FileFmtID_WithTime = 1 # File identifiers used in FAST + FileFmtID_WithoutTime = 2 + FileFmtID_NoCompressWithoutTime = 3 + FileFmtID_ChanLen_In = 4 + + with open(filename, 'rb') as fid: + FileID = fread(fid, 1, 'int16')[0] # FAST output file format, INT(2) + + if FileID == FileFmtID_ChanLen_In: + LenName = fread(fid, 1, 'int16')[0] # Number of characters in channel names and units + else: + LenName = 10 # default number of characters per channel name + + + NumOutChans = fread(fid, 1, 'int32')[0] # The number of output channels, INT(4) + NT = fread(fid, 1, 'int32')[0] # The number of time steps, INT(4) + + if FileID == FileFmtID_WithTime: + TimeScl = fread(fid, 1, 'float64') # The time slopes for scaling, REAL(8) + TimeOff = fread(fid, 1, 'float64') # The time offsets for scaling, REAL(8) + else: + TimeOut1 = fread(fid, 1, 'float64') # The first time in the time series, REAL(8) + TimeIncr = fread(fid, 1, 'float64') # The time increment, REAL(8) + + if FileID != FileFmtID_NoCompressWithoutTime: + ColScl = fread(fid, NumOutChans, 'float32') # The channel slopes for scaling, REAL(4) + ColOff = fread(fid, NumOutChans, 'float32') # The channel offsets for scaling, REAL(4) + + LenDesc = fread(fid, 1, 'int32')[0] # The number of characters in the description string, INT(4) + DescStrASCII = fread(fid, LenDesc, 'uint8') # DescStr converted to ASCII + DescStr = "".join(map(chr, DescStrASCII)).strip() + + ChanName = [] # initialize the ChanName cell array + for iChan in range(NumOutChans + 1): + ChanNameASCII = fread(fid, LenName, 'uint8') # ChanName converted to numeric ASCII + ChanName.append("".join(map(chr, ChanNameASCII)).strip()) + + ChanUnit = [] # initialize the ChanUnit cell array + for iChan in range(NumOutChans + 1): + ChanUnitASCII = fread(fid, LenName, 'uint8') # ChanUnit converted to numeric ASCII + ChanUnit.append("".join(map(chr, ChanUnitASCII)).strip()[1:-1]) + + # get the channel time series + nPts = NT * NumOutChans # number of data points in the file + if FileID == FileFmtID_WithTime: + PackedTime = fread(fid, NT, 'int32') # read the time data + cnt = len(PackedTime) + if cnt < NT: + raise Exception('Could not read entire %s file: read %d of %d time values' % (filename, cnt, NT)) + + if FileID == FileFmtID_NoCompressWithoutTime: + PackedData = fread(fid, nPts, 'float64') # read the channel data + else: + PackedData = fread(fid, nPts, 'int16') # read the channel data + + cnt = len(PackedData) + if cnt < nPts: + raise Exception('Could not read entire %s file: read %d of %d values' % (filename, cnt, nPts)) + + if FileID == FileFmtID_NoCompressWithoutTime: + pack = np.array(PackedData).reshape(NT, NumOutChans) + data = pack + else: + # Scale the packed binary to real data + pack = np.array(PackedData).reshape(NT, NumOutChans) + data = (pack - ColOff) / ColScl + + if FileID == FileFmtID_WithTime: + time = (np.array(PackedTime) - TimeOff) / TimeScl; + else: + time = TimeOut1 + TimeIncr * np.arange(NT) + + data = np.concatenate([time.reshape(NT, 1), data], 1) + pack = np.concatenate([time.reshape(NT, 1), pack], 1) + + info = {'name': os.path.splitext(os.path.basename(filename))[0], + 'description': DescStr, + 'attribute_names': ChanName, + 'attribute_units': ChanUnit} + return data, info, pack + +if __name__=="__main__": + d,i = load_binary_output('Test18.T1.outb') + types = [] + for j in range(39): + types.append('f8') + print(type(i['attribute_names'])) + + print(np.dtype({'names':tuple(i['attribute_names']), 'formats': tuple(types) })) + print(type(d)) + print(np.array(d,dtype=np.dtype({'names':tuple(i['attribute_names']), 'formats': tuple(types) }))) + + print(i) + print(len(i['attribute_names'])) + print(np.shape(d)) diff --git a/OpenFAST/reg_tests/lib/openfastDrivers.py b/OpenFAST/reg_tests/lib/openfastDrivers.py new file mode 100644 index 000000000..b06fd7621 --- /dev/null +++ b/OpenFAST/reg_tests/lib/openfastDrivers.py @@ -0,0 +1,66 @@ +# +# Copyright 2017 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. +# + +""" + This library provides tools for executing cases with drivers contained in the + OpenFAST framework. Any new drivers should have a corresponding public driver + function called `def run[NewDriver]Case` in this library. +""" + +import argparse +import os +import sys +import shutil +import subprocess +import rtestlib as rtl + +def _runCase(executable, inputFile, logFile, stdout): + command = "{} {} > {}".format(executable, inputFile, logFile) + print(command) + return subprocess.call(command, stdout=stdout, shell=True) + +def _runGenericCase(inputFile, executable, verbose=False): + stdout = sys.stdout if verbose else open(os.devnull, 'w') + + rtl.validateFileOrExit(inputFile) + rtl.validateExeOrExit(executable) + + casebase = os.path.sep.join(inputFile.split(os.path.sep)[-1].split('.')[:-1]) + caseparent = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) + logFile = caseparent + os.path.sep + casebase + '.log' + + returnCode = _runCase(executable, inputFile, logFile, stdout) + print("COMPLETE with code {}".format(returnCode), flush=True) + + return returnCode + +def runOpenfastCase(inputFile, executable, verbose=False): + return _runGenericCase(inputFile, executable, verbose) + +def runAerodynDriverCase(inputFile, executable, verbose=False): + caseDirectory = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) + os.chdir(caseDirectory) + return _runGenericCase(inputFile, executable, verbose) + +def runBeamdynDriverCase(inputFile, executable, verbose=False): + caseDirectory = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) + os.chdir(caseDirectory) + return _runGenericCase(inputFile, executable, verbose) + +def runHydrodynDriverCase(inputFile, executable, verbose=False): + caseDirectory = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) + os.chdir(caseDirectory) + return _runGenericCase(inputFile, executable, verbose) diff --git a/OpenFAST/reg_tests/lib/pass_fail.py b/OpenFAST/reg_tests/lib/pass_fail.py new file mode 100644 index 000000000..51daa17f4 --- /dev/null +++ b/OpenFAST/reg_tests/lib/pass_fail.py @@ -0,0 +1,101 @@ +# +# Copyright 2017 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. +# + +""" + This library provides tools for comparing a test solution to a baseline solution + for any structured output file generated within the OpenFAST framework. +""" +import sys, os +import numpy as np +from numpy import linalg as LA +from fast_io import load_output +import rtestlib as rtl + +def readFASTOut(fastoutput): + try: + return load_output(fastoutput) + except Exception as e: + rtl.exitWithError("Error: {}".format(e)) + +def passRegressionTest(norm, tolerance): + return True if max(norm) < tolerance else False + +def maxnorm(data, axis=0): + return LA.norm(data, np.inf, axis=axis) + +def l2norm(data, axis=0): + return LA.norm(data, 2, axis=axis) + +def calculate_relative_norm(testData, baselineData): + norm_diff = l2norm(testData - baselineData) + norm_baseline = l2norm(baselineData) + + # replace any 0s with small number before for division + norm_baseline[norm_baseline == 0] = 1e-16 + + norm = norm_diff.copy() + ix_non_diff = (norm_baseline >= 1) + norm[ix_non_diff] = norm_diff[ix_non_diff] / norm_baseline[ix_non_diff] + return norm + +def calculate_max_norm_over_range(test_data, baseline_data): + channel_ranges = np.abs(baseline_data.max(axis=0) - baseline_data.min(axis=0)) + diff = abs(test_data - baseline_data) + + ix_non_diff = (channel_ranges >= 1) + norm = maxnorm(diff, axis=0) + norm[ix_non_diff] = maxnorm(diff[:, ix_non_diff] / channel_ranges[ix_non_diff]) + + return norm + +def calculate_max_norm(testData, baselineData): + return maxnorm(abs(testData - baselineData)) + +def calculateNorms(test_data, baseline_data): + relative_norm = calculate_max_norm_over_range(test_data, baseline_data) + max_norm = calculate_max_norm(test_data, baseline_data) + relative_l2_norm = calculate_relative_norm(test_data, baseline_data) + results = np.hstack(( + relative_norm.reshape(-1, 1), relative_l2_norm.reshape(-1, 1), + max_norm.reshape(-1, 1) + )) + return results + +if __name__=="__main__": + + rtl.validateInputOrExit(sys.argv, 4, "{} test_solution baseline_solution tolerance".format(sys.argv[0])) + + testSolution = sys.argv[1] + baselineSolution = sys.argv[2] + tolerance = sys.argv[3] + + try: + tolerance = float(tolerance) + except ValueError: + rtl.exitWithError("Error: invalid tolerance given, {}".format(tolerance)) + + rtl.validateFileOrExit(testSolution) + rtl.validateFileOrExit(baselineSolution) + + testData, testInfo, testPack = readFASTOut(testSolution) + baselineData, baselineInfo, basePack = readFASTOut(baselineSolution) + + normalizedNorm, maxNorm = pass_fail.calculateNorms(testData, baselineData, tolerance) + if passRegressionTest(normalizedNorm, tolerance): + sys.exit(0) + else: + dict1, info1, pack1 = readFASTOut(testSolution) + sys.exit(1) diff --git a/OpenFAST/reg_tests/lib/rtestlib.py b/OpenFAST/reg_tests/lib/rtestlib.py new file mode 100644 index 000000000..f797318f8 --- /dev/null +++ b/OpenFAST/reg_tests/lib/rtestlib.py @@ -0,0 +1,57 @@ +# +# Copyright 2017 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. +# + +""" + This library contains utility functions for the custom python programs making + up the regression test system. +""" + +import sys +import os +from stat import ST_MODE + +def exitWithError(error, code=1): + print(error) + sys.exit(code) + +def validInput(argv, nArgsExpected): + valid = True if len(argv) == nArgsExpected else False + return valid + +def validateInputOrExit(argv, nArgsExpected, usage): + if len(argv) != nArgsExpected: + exitWithError( + "Error: {} arguments given, expected {}\n".format(len(argv), nArgsExpected) + + "Usage: {}".format(usage) + ) + +def validateFileOrExit(path): + if not os.path.isfile(path): + exitWithError("Error: file does not exist at {}".format(path)) + +def validateDirOrExit(path): + if not os.path.isdir(path): + exitWithError("Error: directory does not exist at {}".format(path)) + +def validateDirOrMkdir(path): + if not os.path.exists(path): + os.makedirs(path) + +def validateExeOrExit(path): + validateFileOrExit(path) + permissionsMask = oct(os.stat(path)[ST_MODE])[-1:] + if not int(permissionsMask)%2 == 1: + exitWithError("Error: executable at {} does not have proper permissions.".format(path)) diff --git a/OpenFAST/reg_tests/manualRegressionTest.py b/OpenFAST/reg_tests/manualRegressionTest.py new file mode 100644 index 000000000..f51b1e5a5 --- /dev/null +++ b/OpenFAST/reg_tests/manualRegressionTest.py @@ -0,0 +1,96 @@ +# +# Copyright 2017 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. +# + +""" + This program executes OpenFAST on the CertTest cases. It mimics the + regression test execution through CMake/CTest. All generated data goes into + `openfast/build/reg_tests`. + + Get usage with: `manualRegressionTest.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import subprocess + +def strFormat(string): + return "{:<" + str(len(string)) + "}" + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes OpenFAST and a regression test for a single test case.") +parser.add_argument("executable", metavar="OpenFAST", type=str, nargs=1, help="path to the OpenFAST executable") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="current system's name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="compiler's id: [Intel,GNU]") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="tolerance defining pass or failure in the regression test") +parser.add_argument("-p", "-plot", dest="plot", default=False, metavar="Plotting-Flag", type=bool, nargs="?", help="bool to include plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", default=False, metavar="No-Execution", type=bool, nargs="?", help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", default=False, metavar="Verbose-Flag", type=bool, nargs="?", help="bool to include verbose system output") +parser.add_argument("-case", dest="case", default="", metavar="Case-Name", type=str, nargs="?", help="single case name to execute") + +args = parser.parse_args() +openfast_executable = args.executable[0] +sourceDirectory = ".." +buildDirectory = os.path.join("..", "build", "reg_tests", "glue-codes", "openfast") +machine = args.systemName[0] +compiler = args.compilerId[0] +tolerance = args.tolerance[0] +plotError = args.plot if args.plot is False else True +plotFlag = "-p" if plotError else "" +noExec = args.noExec if args.noExec is False else True +noExecFlag = "-n" if noExec else "" +verbose = args.verbose if args.verbose is False else True +case = args.case + +outstd = sys.stdout if verbose else open(os.devnull, 'w') +pythonCommand = sys.executable + +if case != "": + caselist = [case] +else: + with open(os.path.join("r-test", "glue-codes", "openfast", "CaseList.md")) as listfile: + caselist = listfile.readlines() +# allow comments with '#' +casenames = [c.rstrip("\n\r").strip() for c in caselist if "#" not in c] +# allow empty lines +casenames = [c for c in casenames if len(c.strip()) > 0] + +results = [] +prefix, passString, failString = "executing", "PASS", "FAIL" +longestName = max(casenames, key=len) +for case in casenames: + print(strFormat(prefix).format(prefix), strFormat(longestName+" ").format(case), end="", flush=True) + if "linear" in case.lower(): + command = "\"{}\" executeOpenfastLinearRegressionCase.py {} {} {} {} {} {} {} {} {}".format(pythonCommand, case, openfast_executable, sourceDirectory, buildDirectory, tolerance, machine, compiler, plotFlag, noExecFlag) + else: + command = "\"{}\" executeOpenfastRegressionCase.py {} {} {} {} {} {} {} {} {}".format(pythonCommand, case, openfast_executable, sourceDirectory, buildDirectory, tolerance, machine, compiler, plotFlag, noExecFlag) + returnCode = subprocess.call(command, stdout=outstd, shell=True) + resultString = passString if returnCode == 0 else failString + results.append((case, resultString)) + print(resultString) + +from errorPlotting import exportResultsSummary +exportResultsSummary(buildDirectory, results) + +print("\nRegression test execution completed with these results:") +for r in results: + print(" ".join([strFormat(longestName).format(r[0]), r[1]])) + +nPasses = len( [r[1] for r in results if r[1] == passString] ) +print("Total PASSING tests - {}".format(nPasses)) +print("Total FAILING tests - {}".format(len(results) - nPasses)) diff --git a/OpenFAST/share/discon/CMakeLists.txt b/OpenFAST/share/discon/CMakeLists.txt new file mode 100644 index 000000000..7ca94e253 --- /dev/null +++ b/OpenFAST/share/discon/CMakeLists.txt @@ -0,0 +1,100 @@ +# +# Copyright 2017 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 impClied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Helper macros for setting appropriate compiler flags + +# Customizations for GNU Fortran compiler +macro(set_gfortran) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -m64 -ffree-line-length-none -fdefault-real-8 -C") + + # debug flags + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fcheck=all -pedantic -fbacktrace" ) + endif() +endmacro(set_gfortran) + +# Customizations for Intel Fortran Compiler +macro(set_ifort) + if(WIN32) + set_ifort_windows() + else() + set_ifort_posix() + endif() +endmacro(set_ifort) + +# Customizations for Intel Fortran Compiler on posix systems +macro(set_ifort_posix) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -m64 -fpp -real-size 64") + + # debug flags + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -g -check all -traceback" ) + endif() +endmacro(set_ifort_posix) + +# Customizations for Intel Fortran Compiler on Windows systems +macro(set_ifort_windows) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /Qm64 /fpp /real-size:64 /libs:static") + + # debug flags + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} /Z7 /check:all /traceback" ) + endif() +endmacro(set_ifort_windows) + + +# CMake config +cmake_minimum_required(VERSION 2.8.12) +project(DISCON) +enable_language(Fortran) + +set(SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/DISCON.F90") +file(TO_CMAKE_PATH ${SOURCE_PATH} SOURCE_PATH) + +# set the build type option +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type: Debug Release" FORCE) +endif (NOT CMAKE_BUILD_TYPE) + +# set the build flags +if (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU") + set_gfortran() +elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel") + set_ifort() +endif() +set(CMAKE_SHARE_LINKER_FLAGS "-shared") + +if(APPLE OR UNIX) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DIMPLICIT_DLLEXPORT") +endif() + +# supress the mac runtime path warnings +if(APPLE) + set(CMAKE_MACOSX_RPATH 1) +endif() + +add_library(DISCON SHARED ${SOURCE_PATH}) +set_target_properties(DISCON PROPERTIES PREFIX "" SUFFIX ".dll") + +# if this project is built standlone +if (${CMAKE_CURRENT_LIST_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) + set(INSTALL_DEST "${CMAKE_SOURCE_DIR}/..") +# otherwise +else() + set(INSTALL_DEST "${CMAKE_BINARY_DIR}/reg_tests/glue-codes/openfast/5MW_Baseline/ServoData") +endif() + +install(TARGETS DISCON DESTINATION ${INSTALL_DEST}) diff --git a/OpenFAST/share/discon/DISCON.F90 b/OpenFAST/share/discon/DISCON.F90 new file mode 100644 index 000000000..c37070c7e --- /dev/null +++ b/OpenFAST/share/discon/DISCON.F90 @@ -0,0 +1,589 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2015-2016 National Renewable Energy Laboratory +! Copyright (C) 2016-2017 Envision Energy USA, LTD +! +! 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. +!********************************************************************************************************************************** +SUBROUTINE DISCON ( avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG ) BIND (C, NAME='DISCON') + + ! This Bladed-style DLL controller is used to implement a variable-speed + ! generator-torque controller and PI collective blade pitch controller for + ! the NREL Offshore 5MW baseline wind turbine. This routine was written by + ! J. Jonkman of NREL/NWTC for use in the IEA Annex XXIII OC3 studies. + + ! Modified by B. Jonkman to conform to ISO C Bindings (standard Fortran 2003) and + ! compile with either gfortran or Intel Visual Fortran (IVF) + ! DO NOT REMOVE or MODIFY LINES starting with "!DEC$" or "!GCC$" + ! !DEC$ specifies attributes for IVF and !GCC$ specifies attributes for gfortran + ! + ! Note that gfortran v5.x on Mac produces compiler errors with the DLLEXPORT attribute, + ! so I've added the compiler directive IMPLICIT_DLLEXPORT. + +USE, INTRINSIC :: ISO_C_Binding + +IMPLICIT NONE +#ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: DISCON +!GCC$ ATTRIBUTES DLLEXPORT :: DISCON +#endif + + ! Passed Variables: +!REAL(C_FLOAT), INTENT(IN ) :: from_SC (*) ! DATA from the supercontroller +!REAL(C_FLOAT), INTENT(INOUT) :: to_SC (*) ! DATA to the supercontroller + + +REAL(C_FLOAT), INTENT(INOUT) :: avrSWAP (*) ! The swap array, used to pass data to, and receive data from, the DLL controller. +INTEGER(C_INT), INTENT(INOUT) :: aviFAIL ! A flag used to indicate the success of this DLL call set as follows: 0 if the DLL call was successful, >0 if the DLL call was successful but cMessage should be issued as a warning messsage, <0 if the DLL call was unsuccessful or for any other reason the simulation is to be stopped at this point with cMessage as the error message. +CHARACTER(KIND=C_CHAR), INTENT(IN) :: accINFILE (NINT(avrSWAP(50))) ! The name of the parameter input file, 'DISCON.IN'. +CHARACTER(KIND=C_CHAR), INTENT(IN) :: avcOUTNAME(NINT(avrSWAP(51))) ! OUTNAME (Simulation RootName) +CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: avcMSG (NINT(avrSWAP(49))) ! MESSAGE (Message from DLL to simulation code [ErrMsg]) The message which will be displayed by the calling program if aviFAIL <> 0. + + + ! Local Variables: + +REAL(4) :: Alpha ! Current coefficient in the recursive, single-pole, low-pass filter, (-). +REAL(4) :: BlPitch (3) ! Current values of the blade pitch angles, rad. +REAL(4) :: ElapTime ! Elapsed time since the last call to the controller, sec. +REAL(4), PARAMETER :: CornerFreq = 1.570796 ! Corner frequency (-3dB point) in the recursive, single-pole, low-pass filter, rad/s. -- chosen to be 1/4 the blade edgewise natural frequency ( 1/4 of approx. 1Hz = 0.25Hz = 1.570796rad/s) +REAL(4) :: GenSpeed ! Current HSS (generator) speed, rad/s. +REAL(4), SAVE :: GenSpeedF ! Filtered HSS (generator) speed, rad/s. +REAL(4) :: GenTrq ! Electrical generator torque, N-m. +REAL(4) :: GK ! Current value of the gain correction factor, used in the gain scheduling law of the pitch controller, (-). +REAL(4) :: HorWindV ! Horizontal hub-heigh wind speed, m/s. +REAL(4), SAVE :: IntSpdErr ! Current integral of speed error w.r.t. time, rad. +REAL(4), SAVE :: LastGenTrq ! Commanded electrical generator torque the last time the controller was called, N-m. +REAL(4), SAVE :: LastTime ! Last time this DLL was called, sec. +REAL(4), SAVE :: LastTimePC ! Last time the pitch controller was called, sec. +REAL(4), SAVE :: LastTimeVS ! Last time the torque controller was called, sec. +REAL(4), PARAMETER :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in single precision. +REAL(4), PARAMETER :: PC_DT = 0.000125 !JASON:THIS CHANGED FOR ITI BARGE: 0.0001 ! Communication interval for pitch controller, sec. +REAL(4), PARAMETER :: PC_KI = 0.008068634 ! Integral gain for pitch controller at rated pitch (zero), (-). +REAL(4), PARAMETER :: PC_KK = 0.1099965 ! Pitch angle where the the derivative of the aerodynamic power w.r.t. pitch has increased by a factor of two relative to the derivative at rated pitch (zero), rad. +REAL(4), PARAMETER :: PC_KP = 0.01882681 ! Proportional gain for pitch controller at rated pitch (zero), sec. +REAL(4), PARAMETER :: PC_MaxPit = 1.570796 ! Maximum pitch setting in pitch controller, rad. +REAL(4), PARAMETER :: PC_MaxRat = 0.1396263 ! Maximum pitch rate (in absolute value) in pitch controller, rad/s. +REAL(4), PARAMETER :: PC_MinPit = 0.0 ! Minimum pitch setting in pitch controller, rad. +REAL(4), PARAMETER :: PC_RefSpd = 122.9096 ! Desired (reference) HSS speed for pitch controller, rad/s. +REAL(4), SAVE :: PitCom (3) ! Commanded pitch of each blade the last time the controller was called, rad. +REAL(4) :: PitComI ! Integral term of command pitch, rad. +REAL(4) :: PitComP ! Proportional term of command pitch, rad. +REAL(4) :: PitComT ! Total command pitch based on the sum of the proportional and integral terms, rad. +REAL(4) :: PitRate (3) ! Pitch rates of each blade based on the current pitch angles and current pitch command, rad/s. +REAL(4), PARAMETER :: R2D = 57.295780 ! Factor to convert radians to degrees. +REAL(4), PARAMETER :: RPS2RPM = 9.5492966 ! Factor to convert radians per second to revolutions per minute. +REAL(4) :: SpdErr ! Current speed error, rad/s. +REAL(4) :: Time ! Current simulation time, sec. +REAL(4) :: TrqRate ! Torque rate based on the current and last torque commands, N-m/s. +REAL(4), PARAMETER :: VS_CtInSp = 70.16224 ! Transitional generator speed (HSS side) between regions 1 and 1 1/2, rad/s. +REAL(4), PARAMETER :: VS_DT = 0.000125 !JASON:THIS CHANGED FOR ITI BARGE: 0.0001 ! Communication interval for torque controller, sec. +REAL(4), PARAMETER :: VS_MaxRat = 15000.0 ! Maximum torque rate (in absolute value) in torque controller, N-m/s. +REAL(4), PARAMETER :: VS_MaxTq = 47402.91 ! Maximum generator torque in Region 3 (HSS side), N-m. -- chosen to be 10% above VS_RtTq = 43.09355kNm +REAL(4), PARAMETER :: VS_Rgn2K = 2.332287 ! Generator torque constant in Region 2 (HSS side), N-m/(rad/s)^2. +REAL(4), PARAMETER :: VS_Rgn2Sp = 91.21091 ! Transitional generator speed (HSS side) between regions 1 1/2 and 2, rad/s. +REAL(4), PARAMETER :: VS_Rgn3MP = 0.01745329 ! Minimum pitch angle at which the torque is computed as if we are in region 3 regardless of the generator speed, rad. -- chosen to be 1.0 degree above PC_MinPit +REAL(4), PARAMETER :: VS_RtGnSp = 121.6805 ! Rated generator speed (HSS side), rad/s. -- chosen to be 99% of PC_RefSpd +REAL(4), PARAMETER :: VS_RtPwr = 5296610.0 ! Rated generator generator power in Region 3, Watts. -- chosen to be 5MW divided by the electrical generator efficiency of 94.4% +REAL(4), SAVE :: VS_Slope15 ! Torque/speed slope of region 1 1/2 cut-in torque ramp , N-m/(rad/s). +REAL(4), SAVE :: VS_Slope25 ! Torque/speed slope of region 2 1/2 induction generator, N-m/(rad/s). +REAL(4), PARAMETER :: VS_SlPc = 10.0 ! Rated generator slip percentage in Region 2 1/2, %. +REAL(4), SAVE :: VS_SySp ! Synchronous speed of region 2 1/2 induction generator, rad/s. +REAL(4), SAVE :: VS_TrGnSp ! Transitional generator speed (HSS side) between regions 2 and 2 1/2, rad/s. + +INTEGER(4) :: I ! Generic index. +INTEGER(4) :: iStatus ! A status flag set by the simulation as follows: 0 if this is the first call, 1 for all subsequent time steps, -1 if this is the final call at the end of the simulation. +INTEGER(4) :: K ! Loops through blades. +INTEGER(4) :: NumBl ! Number of blades, (-). +INTEGER(4), PARAMETER :: UnDb = 85 ! I/O unit for the debugging information +INTEGER(4), PARAMETER :: UnDb2 = 86 ! I/O unit for the debugging information +INTEGER(4), PARAMETER :: Un = 87 ! I/O unit for pack/unpack (checkpoint & restart) +INTEGER(4) :: ErrStat + +LOGICAL(1), PARAMETER :: PC_DbgOut = .FALSE. ! Flag to indicate whether to output debugging information + +CHARACTER( 1), PARAMETER :: Tab = CHAR( 9 ) ! The tab character. +CHARACTER( 25), PARAMETER :: FmtDat = "(F8.3,99('"//Tab//"',ES10.3E2,:))" ! The format of the debugging data + +CHARACTER(SIZE(accINFILE)-1) :: InFile ! a Fortran version of the input C string (not considered an array here) [subtract 1 for the C null-character] +CHARACTER(SIZE(avcOUTNAME)-1):: RootName ! a Fortran version of the input C string (not considered an array here) [subtract 1 for the C null-character] +CHARACTER(SIZE(avcMSG)-1) :: ErrMsg ! a Fortran version of the C string argument (not considered an array here) [subtract 1 for the C null-character] + + + ! Load variables from calling program (See Appendix A of Bladed User's Guide): + +iStatus = NINT( avrSWAP( 1) ) +NumBl = NINT( avrSWAP(61) ) + +!print *, 'from_sc: ', from_sc(1:4) +!to_sc(1) = 5.0; +!to_sc(2) = 2.0; + + +!BlPitch (1) = MIN( MAX( avrSWAP( 4), PC_MinPit ), PC_MaxPit ) ! assume that blade pitch can't exceed limits +!BlPitch (2) = MIN( MAX( avrSWAP(33), PC_MinPit ), PC_MaxPit ) ! assume that blade pitch can't exceed limits +!BlPitch (3) = MIN( MAX( avrSWAP(34), PC_MinPit ), PC_MaxPit ) ! assume that blade pitch can't exceed limits +BlPitch (1) = avrSWAP( 4) +BlPitch (2) = avrSWAP(33) +BlPitch (3) = avrSWAP(34) +GenSpeed = avrSWAP(20) +HorWindV = avrSWAP(27) +Time = avrSWAP( 2) + + ! Convert C character arrays to Fortran strings: + +RootName = TRANSFER( avcOUTNAME(1:LEN(RootName)), RootName ) +I = INDEX(RootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... +IF ( I > 0 ) RootName = RootName(1:I) ! remove it + +InFile = TRANSFER( accINFILE(1:LEN(InFile)), InFile ) +I = INDEX(InFile,C_NULL_CHAR) - 1 ! if this has a c null character at the end... +IF ( I > 0 ) InFile = InFile(1:I) ! remove it + + + + ! Initialize aviFAIL to 0: + +aviFAIL = 0 + + + ! Read any External Controller Parameters specified in the User Interface + ! and initialize variables: + +IF ( iStatus == 0 ) THEN ! .TRUE. if we're on the first call to the DLL + + ! Inform users that we are using this user-defined routine: + + aviFAIL = 1 + ErrMsg = 'Running with torque and pitch control of the NREL offshore '// & + '5MW baseline wind turbine from DISCON.dll as written by J. '// & + 'Jonkman of NREL/NWTC for use in the IEA Annex XXIII OC3 ' // & + 'studies.' + + ! Determine some torque control parameters not specified directly: + + VS_SySp = VS_RtGnSp/( 1.0 + 0.01*VS_SlPc ) + VS_Slope15 = ( VS_Rgn2K*VS_Rgn2Sp*VS_Rgn2Sp )/( VS_Rgn2Sp - VS_CtInSp ) + VS_Slope25 = ( VS_RtPwr/VS_RtGnSp )/( VS_RtGnSp - VS_SySp ) + IF ( VS_Rgn2K == 0.0 ) THEN ! .TRUE. if the Region 2 torque is flat, and thus, the denominator in the ELSE condition is zero + VS_TrGnSp = VS_SySp + ELSE ! .TRUE. if the Region 2 torque is quadratic with speed + VS_TrGnSp = ( VS_Slope25 - SQRT( VS_Slope25*( VS_Slope25 - 4.0*VS_Rgn2K*VS_SySp ) ) )/( 2.0*VS_Rgn2K ) + ENDIF + + + ! Check validity of input parameters: + + IF ( CornerFreq <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'CornerFreq must be greater than zero.' + ENDIF + + IF ( VS_DT <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_DT must be greater than zero.' + ENDIF + + IF ( VS_CtInSp < 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_CtInSp must not be negative.' + ENDIF + + IF ( VS_Rgn2Sp <= VS_CtInSp ) THEN + aviFAIL = -1 + ErrMsg = 'VS_Rgn2Sp must be greater than VS_CtInSp.' + ENDIF + + IF ( VS_TrGnSp < VS_Rgn2Sp ) THEN + aviFAIL = -1 + ErrMsg = 'VS_TrGnSp must not be less than VS_Rgn2Sp.' + ENDIF + + IF ( VS_SlPc <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_SlPc must be greater than zero.' + ENDIF + + IF ( VS_MaxRat <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_MaxRat must be greater than zero.' + ENDIF + + IF ( VS_RtPwr < 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_RtPwr must not be negative.' + ENDIF + + IF ( VS_Rgn2K < 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'VS_Rgn2K must not be negative.' + ENDIF + + IF ( VS_Rgn2K*VS_RtGnSp*VS_RtGnSp > VS_RtPwr/VS_RtGnSp ) THEN + aviFAIL = -1 + ErrMsg = 'VS_Rgn2K*VS_RtGnSp^2 must not be greater than VS_RtPwr/VS_RtGnSp.' + ENDIF + + IF ( VS_MaxTq < VS_RtPwr/VS_RtGnSp ) THEN + aviFAIL = -1 + ErrMsg = 'VS_RtPwr/VS_RtGnSp must not be greater than VS_MaxTq.' + ENDIF + + IF ( PC_DT <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'PC_DT must be greater than zero.' + ENDIF + + IF ( PC_KI <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'PC_KI must be greater than zero.' + ENDIF + + IF ( PC_KK <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'PC_KK must be greater than zero.' + ENDIF + + IF ( PC_RefSpd <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'PC_RefSpd must be greater than zero.' + ENDIF + + IF ( PC_MaxRat <= 0.0 ) THEN + aviFAIL = -1 + ErrMsg = 'PC_MaxRat must be greater than zero.' + ENDIF + + IF ( PC_MinPit >= PC_MaxPit ) THEN + aviFAIL = -1 + ErrMsg = 'PC_MinPit must be less than PC_MaxPit.' + ENDIF + + + ! If we're debugging the pitch controller, open the debug file and write the + ! header: + + IF ( PC_DbgOut ) THEN + + OPEN ( UnDb, FILE=TRIM( RootName )//'.dbg', STATUS='REPLACE' ) + + WRITE (UnDb,'(/////)') + WRITE (UnDb,'(A)') 'Time '//Tab//'ElapTime'//Tab//'HorWindV'//Tab//'GenSpeed'//Tab//'GenSpeedF'//Tab//'RelSpdErr'//Tab// & + 'SpdErr '//Tab//'IntSpdErr'//Tab//'GK '//Tab//'PitComP'//Tab//'PitComI'//Tab//'PitComT'//Tab// & + 'PitRate1'//Tab//'PitRate2'//Tab//'PitRate3'//Tab//'PitCom1'//Tab//'PitCom2'//Tab//'PitCom3'//Tab// & + 'BlPitch1'//Tab//'BlPitch2'//Tab//'BlPitch3' + WRITE (UnDb,'(A)') '(sec)'//Tab//'(sec) '//Tab//'(m/sec) '//Tab//'(rpm) '//Tab//'(rpm) '//Tab//'(%) '//Tab// & + '(rad/s)'//Tab//'(rad) '//Tab//'(-)'//Tab//'(deg) '//Tab//'(deg) '//Tab//'(deg) '//Tab// & + '(deg/s) '//Tab//'(deg/s) '//Tab//'(deg/s) '//Tab//'(deg) '//Tab//'(deg) '//Tab//'(deg) '//Tab// & + '(deg) '//Tab//'(deg) '//Tab//'(deg) ' + + + OPEN ( UnDb2, FILE=TRIM( RootName )//'.dbg2', STATUS='REPLACE' ) + WRITE (UnDb2,'(/////)') + + WRITE (UnDb2,'(A,85("'//Tab//'AvrSWAP(",I2,")"))') 'Time ', (i,i=1,85) + WRITE (UnDb2,'(A,85("'//Tab//'(-)"))') '(s)' + + ENDIF + + + ! Initialize the SAVEd variables: + ! NOTE: LastGenTrq, though SAVEd, is initialized in the torque controller + ! below for simplicity, not here. + + GenSpeedF = GenSpeed ! This will ensure that generator speed filter will use the initial value of the generator speed on the first pass + PitCom = BlPitch ! This will ensure that the variable speed controller picks the correct control region and the pitch controller picks the correct gain on the first call + GK = 1.0/( 1.0 + PitCom(1)/PC_KK ) ! This will ensure that the pitch angle is unchanged if the initial SpdErr is zero + IntSpdErr = PitCom(1)/( GK*PC_KI ) ! This will ensure that the pitch angle is unchanged if the initial SpdErr is zero + + LastTime = Time ! This will ensure that generator speed filter will use the initial value of the generator speed on the first pass + LastTimePC = Time - PC_DT ! This will ensure that the pitch controller is called on the first pass + LastTimeVS = Time - VS_DT ! This will ensure that the torque controller is called on the first pass + + +ENDIF + + + + ! Main control calculations: + +IF ( ( iStatus >= 0 ) .AND. ( aviFAIL >= 0 ) ) THEN ! Only compute control calculations if no error has occured and we are not on the last time step + + + + ! Abort if the user has not requested a pitch angle actuator (See Appendix A + ! of Bladed User's Guide): + + IF ( NINT(avrSWAP(10)) /= 0 ) THEN ! .TRUE. if a pitch angle actuator hasn't been requested + aviFAIL = -1 + ErrMsg = 'Pitch angle actuator not requested.' + ENDIF + + + ! Set unused outputs to zero (See Appendix A of Bladed User's Guide): + + avrSWAP(36) = 0.0 ! Shaft brake status: 0=off + avrSWAP(41) = 0.0 ! Demanded yaw actuator torque + avrSWAP(46) = 0.0 ! Demanded pitch rate (Collective pitch) + avrSWAP(48) = 0.0 ! Demanded nacelle yaw rate + avrSWAP(65) = 0.0 ! Number of variables returned for logging + avrSWAP(72) = 0.0 ! Generator start-up resistance + avrSWAP(79) = 0.0 ! Request for loads: 0=none + avrSWAP(80) = 0.0 ! Variable slip current status + avrSWAP(81) = 0.0 ! Variable slip current demand + + +!======================================================================= + + + ! Filter the HSS (generator) speed measurement: + ! NOTE: This is a very simple recursive, single-pole, low-pass filter with + ! exponential smoothing. + + ! Update the coefficient in the recursive formula based on the elapsed time + ! since the last call to the controller: + + Alpha = EXP( ( LastTime - Time )*CornerFreq ) + + + ! Apply the filter: + + GenSpeedF = ( 1.0 - Alpha )*GenSpeed + Alpha*GenSpeedF + + +!======================================================================= + + + ! Variable-speed torque control: + + ! Compute the elapsed time since the last call to the controller: + + ElapTime = Time - LastTimeVS + + + ! Only perform the control calculations if the elapsed time is greater than + ! or equal to the communication interval of the torque controller: + ! NOTE: Time is scaled by OnePlusEps to ensure that the contoller is called + ! at every time step when VS_DT = DT, even in the presence of + ! numerical precision errors. + + IF ( ( Time*OnePlusEps - LastTimeVS ) >= VS_DT ) THEN + + + ! Compute the generator torque, which depends on which region we are in: + + IF ( ( GenSpeedF >= VS_RtGnSp ) .OR. ( PitCom(1) >= VS_Rgn3MP ) ) THEN ! We are in region 3 - power is constant + GenTrq = VS_RtPwr/GenSpeedF + ELSEIF ( GenSpeedF <= VS_CtInSp ) THEN ! We are in region 1 - torque is zero + GenTrq = 0.0 + ELSEIF ( GenSpeedF < VS_Rgn2Sp ) THEN ! We are in region 1 1/2 - linear ramp in torque from zero to optimal + GenTrq = VS_Slope15*( GenSpeedF - VS_CtInSp ) + ELSEIF ( GenSpeedF < VS_TrGnSp ) THEN ! We are in region 2 - optimal torque is proportional to the square of the generator speed + GenTrq = VS_Rgn2K*GenSpeedF*GenSpeedF + ELSE ! We are in region 2 1/2 - simple induction generator transition region + GenTrq = VS_Slope25*( GenSpeedF - VS_SySp ) + ENDIF + + + ! Saturate the commanded torque using the maximum torque limit: + + GenTrq = MIN( GenTrq , VS_MaxTq ) ! Saturate the command using the maximum torque limit + + + ! Saturate the commanded torque using the torque rate limit: + + IF ( iStatus == 0 ) LastGenTrq = GenTrq ! Initialize the value of LastGenTrq on the first pass only + TrqRate = ( GenTrq - LastGenTrq )/ElapTime ! Torque rate (unsaturated) + TrqRate = MIN( MAX( TrqRate, -VS_MaxRat ), VS_MaxRat ) ! Saturate the torque rate using its maximum absolute value + GenTrq = LastGenTrq + TrqRate*ElapTime ! Saturate the command using the torque rate limit + + + ! Reset the values of LastTimeVS and LastGenTrq to the current values: + + LastTimeVS = Time + LastGenTrq = GenTrq + + + ENDIF + + + ! Set the generator contactor status, avrSWAP(35), to main (high speed) + ! variable-speed generator, the torque override to yes, and command the + ! generator torque (See Appendix A of Bladed User's Guide): + + avrSWAP(35) = 1.0 ! Generator contactor status: 1=main (high speed) variable-speed generator + avrSWAP(56) = 0.0 ! Torque override: 0=yes + avrSWAP(47) = LastGenTrq ! Demanded generator torque + + +!======================================================================= + + + ! Pitch control: + + ! Compute the elapsed time since the last call to the controller: + + ElapTime = Time - LastTimePC + + + ! Only perform the control calculations if the elapsed time is greater than + ! or equal to the communication interval of the pitch controller: + ! NOTE: Time is scaled by OnePlusEps to ensure that the contoller is called + ! at every time step when PC_DT = DT, even in the presence of + ! numerical precision errors. + + IF ( ( Time*OnePlusEps - LastTimePC ) >= PC_DT ) THEN + + + ! Compute the gain scheduling correction factor based on the previously + ! commanded pitch angle for blade 1: + + GK = 1.0/( 1.0 + PitCom(1)/PC_KK ) + + + ! Compute the current speed error and its integral w.r.t. time; saturate the + ! integral term using the pitch angle limits: + + SpdErr = GenSpeedF - PC_RefSpd ! Current speed error + IntSpdErr = IntSpdErr + SpdErr*ElapTime ! Current integral of speed error w.r.t. time + IntSpdErr = MIN( MAX( IntSpdErr, PC_MinPit/( GK*PC_KI ) ), & + PC_MaxPit/( GK*PC_KI ) ) ! Saturate the integral term using the pitch angle limits, converted to integral speed error limits + + + ! Compute the pitch commands associated with the proportional and integral + ! gains: + + PitComP = GK*PC_KP* SpdErr ! Proportional term + PitComI = GK*PC_KI*IntSpdErr ! Integral term (saturated) + + + ! Superimpose the individual commands to get the total pitch command; + ! saturate the overall command using the pitch angle limits: + + PitComT = PitComP + PitComI ! Overall command (unsaturated) + PitComT = MIN( MAX( PitComT, PC_MinPit ), PC_MaxPit ) ! Saturate the overall command using the pitch angle limits + + + ! Saturate the overall commanded pitch using the pitch rate limit: + ! NOTE: Since the current pitch angle may be different for each blade + ! (depending on the type of actuator implemented in the structural + ! dynamics model), this pitch rate limit calculation and the + ! resulting overall pitch angle command may be different for each + ! blade. + + DO K = 1,NumBl ! Loop through all blades + + PitRate(K) = ( PitComT - BlPitch(K) )/ElapTime ! Pitch rate of blade K (unsaturated) + PitRate(K) = MIN( MAX( PitRate(K), -PC_MaxRat ), PC_MaxRat ) ! Saturate the pitch rate of blade K using its maximum absolute value + PitCom (K) = BlPitch(K) + PitRate(K)*ElapTime ! Saturate the overall command of blade K using the pitch rate limit + + PitCom(K) = MIN( MAX( PitCom(K), PC_MinPit ), PC_MaxPit ) ! Saturate the overall command using the pitch angle limits + + ENDDO ! K - all blades + + + ! Reset the value of LastTimePC to the current value: + + LastTimePC = Time + + + ! Output debugging information if requested: + + IF ( PC_DbgOut ) THEN + WRITE (UnDb,FmtDat) Time, ElapTime, HorWindV, GenSpeed*RPS2RPM, GenSpeedF*RPS2RPM, & + 100.0*SpdErr/PC_RefSpd, SpdErr, IntSpdErr, GK, PitComP*R2D, PitComI*R2D, & + PitComT*R2D, PitRate*R2D, PitCom*R2D, BlPitch*R2D + + END IF + + ENDIF + + + ! Set the pitch override to yes and command the pitch demanded from the last + ! call to the controller (See Appendix A of Bladed User's Guide): + + avrSWAP(55) = 0.0 ! Pitch override: 0=yes + + avrSWAP(42) = PitCom(1) ! Use the command angles of all blades if using individual pitch + avrSWAP(43) = PitCom(2) ! " + avrSWAP(44) = PitCom(3) ! " + + avrSWAP(45) = PitCom(1) ! Use the command angle of blade 1 if using collective pitch + + IF ( PC_DbgOut ) WRITE (UnDb2,FmtDat) Time, avrSWAP(1:85) + +!======================================================================= + + + ! Reset the value of LastTime to the current value: + + LastTime = Time + +ELSEIF ( iStatus == -8 ) THEN + ! pack + OPEN( Un, FILE=TRIM( InFile ), STATUS='UNKNOWN', FORM='UNFORMATTED' , ACCESS='STREAM', IOSTAT=ErrStat, ACTION='WRITE' ) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = 'Cannot open file "'//TRIM( InFile )//'". Another program may have locked it for writing.' + aviFAIL = -1 + ELSE + + ! write all static variables to the checkpoint file (inverse of unpack): + WRITE( Un, IOSTAT=ErrStat ) GenSpeedF ! Filtered HSS (generator) speed, rad/s. + WRITE( Un, IOSTAT=ErrStat ) IntSpdErr ! Current integral of speed error w.r.t. time, rad. + WRITE( Un, IOSTAT=ErrStat ) LastGenTrq ! Commanded electrical generator torque the last time the controller was called, N-m. + WRITE( Un, IOSTAT=ErrStat ) LastTime ! Last time this DLL was called, sec. + WRITE( Un, IOSTAT=ErrStat ) LastTimePC ! Last time the pitch controller was called, sec. + WRITE( Un, IOSTAT=ErrStat ) LastTimeVS ! Last time the torque controller was called, sec. + WRITE( Un, IOSTAT=ErrStat ) PitCom ! Commanded pitch of each blade the last time the controller was called, rad. + WRITE( Un, IOSTAT=ErrStat ) VS_Slope15 ! Torque/speed slope of region 1 1/2 cut-in torque ramp , N-m/(rad/s). + WRITE( Un, IOSTAT=ErrStat ) VS_Slope25 ! Torque/speed slope of region 2 1/2 induction generator, N-m/(rad/s). + WRITE( Un, IOSTAT=ErrStat ) VS_SySp ! Synchronous speed of region 2 1/2 induction generator, rad/s. + WRITE( Un, IOSTAT=ErrStat ) VS_TrGnSp ! Transitional generator speed (HSS side) between regions 2 and 2 1/2, rad/s. + + CLOSE ( Un ) + + END IF + +ELSEIF( iStatus == -9 ) THEN + !unpack + OPEN( Un, FILE=TRIM( InFile ), STATUS='OLD', FORM='UNFORMATTED', ACCESS='STREAM', IOSTAT=ErrStat, ACTION='READ' ) + + IF ( ErrStat /= 0 ) THEN + aviFAIL = -1 + ErrMsg = ' Cannot open file "'//TRIM( InFile )//'" for reading. Another program may have locked.' + ELSE + + ! READ all static variables from the restart file (inverse of pack): + READ( Un, IOSTAT=ErrStat ) GenSpeedF ! Filtered HSS (generator) speed, rad/s. + READ( Un, IOSTAT=ErrStat ) IntSpdErr ! Current integral of speed error w.r.t. time, rad. + READ( Un, IOSTAT=ErrStat ) LastGenTrq ! Commanded electrical generator torque the last time the controller was called, N-m. + READ( Un, IOSTAT=ErrStat ) LastTime ! Last time this DLL was called, sec. + READ( Un, IOSTAT=ErrStat ) LastTimePC ! Last time the pitch controller was called, sec. + READ( Un, IOSTAT=ErrStat ) LastTimeVS ! Last time the torque controller was called, sec. + READ( Un, IOSTAT=ErrStat ) PitCom ! Commanded pitch of each blade the last time the controller was called, rad. + READ( Un, IOSTAT=ErrStat ) VS_Slope15 ! Torque/speed slope of region 1 1/2 cut-in torque ramp , N-m/(rad/s). + READ( Un, IOSTAT=ErrStat ) VS_Slope25 ! Torque/speed slope of region 2 1/2 induction generator, N-m/(rad/s). + READ( Un, IOSTAT=ErrStat ) VS_SySp ! Synchronous speed of region 2 1/2 induction generator, rad/s. + READ( Un, IOSTAT=ErrStat ) VS_TrGnSp ! Transitional generator speed (HSS side) between regions 2 and 2 1/2, rad/s. + + CLOSE ( Un ) + END IF + + +ENDIF + +avcMSG = TRANSFER( TRIM(ErrMsg)//C_NULL_CHAR, avcMSG, SIZE(avcMSG) ) + +RETURN +END SUBROUTINE DISCON +!======================================================================= diff --git a/OpenFAST/share/docker/openfast_dev/Dockerfile b/OpenFAST/share/docker/openfast_dev/Dockerfile new file mode 100644 index 000000000..5042c7bbb --- /dev/null +++ b/OpenFAST/share/docker/openfast_dev/Dockerfile @@ -0,0 +1,29 @@ +# +# Copyright 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. +# + +FROM rafmudaf/openfast-ubuntu:v2.3.0 + +# Move into the openfast directory and update +WORKDIR /openfast +RUN git fetch && \ + git checkout -b dev origin/dev && \ + git submodule update + +# Move into the "build" directory, remove the old reg tests, and compile +WORKDIR /openfast/build +RUN rm -rf reg_tests && \ + cmake .. && \ + make -j4 install diff --git a/OpenFAST/share/docker/openfast_ubuntu/Dockerfile b/OpenFAST/share/docker/openfast_ubuntu/Dockerfile new file mode 100644 index 000000000..8470e5623 --- /dev/null +++ b/OpenFAST/share/docker/openfast_ubuntu/Dockerfile @@ -0,0 +1,54 @@ +# +# Copyright 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. +# + +FROM ubuntu:bionic + +# Install dependencies + +# For gfortran-8 +# RUN add-apt-repository ppa:ubuntu-toolchain-r/test -y +# apt-get install gfortran-8 + +ENV DEBIAN_FRONTEND=noninteractive TZ=America/Denver + +RUN apt update -qq && \ + apt install -y software-properties-common build-essential && \ + add-apt-repository ppa:git-core/ppa -y && \ + apt install -y python3-pip && \ + apt install -y cmake cmake-curses-gui && \ + apt install -y gcc gfortran make && \ + apt install -y libblas-dev liblapack-dev && \ + apt install -y git && \ + apt install -y nano + +RUN pip3 install numpy + +# Configure the environment +ENV FC=/usr/bin/gfortran + +# Clone the project +RUN git clone --recursive https://github.com/openfast/openfast.git openfast +WORKDIR /openfast + +# Build the project +RUN mkdir build +WORKDIR /openfast/build + +# NOTE: building with optimizations on (RELEASE or RELWITHDEBINFO), the virtual machine +# will require about 6GB of memoery. Otherwise, the gfortran compiler will exit with an +# "internal error" +RUN cmake .. -DBUILD_TESTING=ON -DDOUBLE_PRECISION=ON -DCMAKE_BUILD_TYPE=RELWITHDEBINFO +RUN make -j4 install diff --git a/OpenFAST/share/fast-build-cpp-spack.sh b/OpenFAST/share/fast-build-cpp-spack.sh new file mode 100755 index 000000000..fd5ca9c8e --- /dev/null +++ b/OpenFAST/share/fast-build-cpp-spack.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -ex + +COMPILER=gcc +SPACK_ROOT= +SPACK_EXE=${SPACK_ROOT}/bin/spack +module purge +module load gcc/5.2.0 +module load python/2.7.8 +module use ${SPACK_ROOT}/share/spack/modules/$(${SPACK_EXE} arch) +module load $(${SPACK_EXE} module find cmake %${COMPILER}) +module load $(${SPACK_EXE} module find openmpi %${COMPILER}) +module load $(${SPACK_EXE} module find hdf5 %${COMPILER}) +module load $(${SPACK_EXE} module find zlib %${COMPILER}) +module load $(${SPACK_EXE} module find libxml2 %${COMPILER}) +module load $(${SPACK_EXE} module find xz %${COMPILER}) +module load $(${SPACK_EXE} module find binutils %${COMPILER}) +module list +which cmake + + +OPENFAST_DIR= +yaml_install_dir=`${SPACK_EXE} location -i yaml-cpp %${COMPILER}` +hdf5_install_dir=`${SPACK_EXE} location -i hdf5 %${COMPILER}` +zlib_install_dir=`${SPACK_EXE} location -i zlib %${COMPILER}` +libxml2_install_dir=`${SPACK_EXE} location -i libxml2 %${COMPILER}` +CC=gcc CXX=g++ FC=gfortran cmake \ + -DCMAKE_INSTALL_PREFIX=${OPENFAST_DIR}/install/ \ + -DCMAKE_BUILD_TYPE=DEBUG \ + -DBUILD_OPENFAST_CPP_API=ON \ + -DFPE_TRAP_ENABLED:BOOL=ON \ + -DYAML_ROOT:PATH=$yaml_install_dir \ + -DHDF5_USE_STATIC_LIBRARIES=ON \ + -DHDF5_ROOT:PATH=$hdf5_install_dir \ + -DLIBXML2_ROOT:PATH=$libxml2_install_dir \ + -DLIBXML2_USE_STATIC_LIBRARIES=ON \ + -DHDF5_ROOT:PATH=$hdf5_install_dir \ + $EXTRA_ARGS \ +../ &> log.cmake +make VERBOSE=1 &> log.make diff --git a/OpenFAST/share/fast-build-cpp.sh b/OpenFAST/share/fast-build-cpp.sh new file mode 100755 index 000000000..5477dac7e --- /dev/null +++ b/OpenFAST/share/fast-build-cpp.sh @@ -0,0 +1,17 @@ +openfast_dir= +yaml_install_dir=$openfast_dir/install/ +hdf5_install_dir=$openfast_dir/install/ + +EXTRA_ARGS=$@ + +CC=mpicc CXX=mpic++ FC=gfortran cmake \ + -DCMAKE_INSTALL_PREFIX=$openfast_dir/install/ \ + -DCMAKE_BUILD_TYPE=RELEASE \ + -DBUILD_OPENFAST_CPP_API=ON \ + -DYAML_ROOT:PATH=$yaml_install_dir \ + -DHDF5_USE_STATIC_LIBRARIES=ON \ + -DHDF5_ROOT:PATH=$hdf5_install_dir \ + -DFPE_TRAP_ENABLED=OFF \ + $EXTRA_ARGS \ +../ &> log.cmake + diff --git a/OpenFAST/share/fast-build.sh b/OpenFAST/share/fast-build.sh new file mode 100755 index 000000000..64831a633 --- /dev/null +++ b/OpenFAST/share/fast-build.sh @@ -0,0 +1,16 @@ +openfast_dir= +yaml_install_dir=$openfast_dir/install/ +hdf5_install_dir=$openfast_dir/install/ + +EXTRA_ARGS=$@ + +CC=mpicc CXX=mpic++ FC=gfortran cmake \ + -DCMAKE_INSTALL_PREFIX=$openfast_dir/install/ \ + -DCMAKE_BUILD_TYPE=RELEASE \ + -DYAML_ROOT:PATH=$yaml_install_dir \ + -DHDF5_USE_STATIC_LIBRARIES=ON \ + -DHDF5_ROOT:PATH=$hdf5_install_dir \ + -DFPE_TRAP_ENABLED=OFF \ + $EXTRA_ARGS \ +../ &> log.cmake + diff --git a/OpenFAST/share/fast-install.sh b/OpenFAST/share/fast-install.sh new file mode 100755 index 000000000..14b20efce --- /dev/null +++ b/OpenFAST/share/fast-install.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +passFail() { + if [ $1 -eq 0 ] + then + echo "... PASSED" + else + echo "... FAILED" + fi +} + +prepInstall() { +#Prepare for installation + echo -n "Prepping install" + echo -n $PWD > /tmp/fastDir + openfast_dir=$(sed 's:/:\\/:g' /tmp/fastDir) + echo "export openfast_dir=${openfast_dir}" > .prepInstall + source .prepInstall + passFail $? +} + +compileLapack() { +#Registry + echo -n "Compiling Lapack" + [ -d modules/lapack ] || mkdir modules/lapack + cd modules/lapack + curl -k -o lapack-3.6.0.tgz http://www.netlib.org/lapack/lapack-3.6.0.tgz &> log.wget + tar -zxf lapack-3.6.0.tgz &> log.untar + [ -d build ] || mkdir build + cd build + make clean &> /dev/null + # if [ -f CMakeCache.txt] ; then + # rm CMakeCache.txt + # fi + cmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc -DCMAKE_FORTRAN_COMPILER=gfortran -DCMAKE_INSTALL_PREFIX=../../../../install/ -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_SHARED_LIBS=ON -DBUILD_DEPRECATED=ON -DLAPACKE=ON ../lapack-3.6.0 &> log.config + make -j 8 &> log.make + make install &> log.makeInstall + passFail $? + cd ${openfast_dir} +} + +compileYAMLcpp() { +#yaml-cpp + echo "Compiling yaml-cpp" + echo -n " Setting up build directory" + [ -d modules/yaml-cpp ] || mkdir modules/yaml-cpp + cd modules/yaml-cpp + git clone https://github.com/jbeder/yaml-cpp.git &> /dev/null + [ -d build ] || mkdir build + cd build + if [ -f CMakeCache.txt ] ; then + rm -rf CMakeCache.txt CMakeFiles/ + fi + passFail $? + echo -n " Configuring" + cmake ../yaml-cpp/ -DCMAKE_INSTALL_PREFIX=${openfast_dir}/install &> log.cmake + passFail $? + echo -n " Compiling" + make -j 8 &> log.make + passFail $? + echo -n " Installing" + make install &> log.makeInstall + passFail $? + cd ${openfast_dir} +} + +compileHDF5() { + echo "Compiling hdf5" + echo -n " Getting source" + [ -d modules/hdf5 ] || mkdir modules/hdf5 + cd modules/hdf5 + wget --no-check-certificate https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.1/src/hdf5-1.10.1.tar.bz2 &> log.wget + passFail $? + echo -n " Setting up build directory" + tar -jxf hdf5-1.10.1.tar.bz2 &> log.untar + cd hdf5-1.10.1 + passFail $? + echo -n " Configuring" + ./configure CC=mpicc FC=mpif90 CXX=mpicxx --enable-parallel --prefix=${openfast_dir}/install &> log.config + passFail $? + echo -n " Compiling" + make -j 8 &> log.make + passFail $? + echo -n " Installing" + make install &> log.makeInstall + passFail $? + cd ${openfast_dir} +} + +compileOpenFAST() { + echo "Compiling OpenFAST" + echo -n " Setting up config" + [ -d build ] || mkdir build + cd build/ + make clean &> /dev/null + # if [ -f CMakeCache.txt] ; then + # rm CMakeCache.txt + # fi + cp ${openfast_dir}/share/fast-build-cpp.sh . + passFail $? + echo -n " Configuring" + ./fast-build-cpp.sh + passFail $? + echo -n " Compiling" + make &> log.make + passFail $? + echo -n " Installing" + make install &> log.makeInstall + passFail $? + cd ${openfast_dir} +} + +prepInstall +compileYAMLcpp +compileHDF5 +compileOpenFAST + + diff --git a/OpenFAST/share/spack/package.py b/OpenFAST/share/spack/package.py new file mode 100644 index 000000000..fa95189d5 --- /dev/null +++ b/OpenFAST/share/spack/package.py @@ -0,0 +1,99 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +from spack import * + + +class Openfast(CMakePackage): + """NREL OpenFAST - Wind Turbine Simulation Package""" + + homepage = "http://openfast.readthedocs.io/en/latest/" + url = "https://github.com/OpenFAST/openfast.git" + + version('develop', + git='https://github.com/OpenFAST/openfast.git', + branch='dev') + version('master', + git='https://github.com/OpenFAST/openfast.git', + branch='master') + + variant('shared', default=False, + description="Build shared libraries") + variant('double-precision', default=True, + description="Treat REAL as double precision") + variant('dll-interface', default=True, + description="Enable dynamic library loading interface") + variant('cxx', default=False, + description="Enable C++ bindings") + variant('debug', default=False, + description="Enable debugging symbols with RelWithDebInfo") + + # Dependencies for OpenFAST Fortran + depends_on('blas') + depends_on('lapack') + + # Additional dependencies when compiling C++ library + depends_on('mpi', when='+cxx') + depends_on('yaml-cpp', when='+cxx') + depends_on('hdf5+mpi+cxx', when='+cxx') + depends_on('zlib', when='+cxx') + depends_on('libxml2', when='+cxx') + + # Disable parallel builds because of OpenFOAM Types modules dependencies + parallel = False + + def build_type(self): + if '+debug' in self.spec: + return 'RelWithDebInfo' + else: + return 'Release' + + def cmake_args(self): + spec = self.spec + + options = [] + + options.extend([ + '-DBUILD_SHARED_LIBS:BOOL=%s' % ( + 'ON' if '+shared' in spec else 'OFF'), + '-DDOUBLE_PRECISION:BOOL=%s' % ( + 'ON' if '+double-precision' in spec else 'OFF'), + '-DUSE_DLL_INTERFACE:BOOL=%s' % ( + 'ON' if '+dll-interface' in spec else 'OFF'), + '-DBUILD_OPENFAST_CPP_API:BOOL=%s' % ( + 'ON' if '+cxx' in spec else 'OFF'), + ]) + + if '+cxx' in spec: + options.extend([ + '-DHDF5_ROOT:PATH=%s' % spec['hdf5'].prefix, + '-DYAML_ROOT:PATH=%s' % spec['yaml-cpp'].prefix, + ]) + + if not '+shared' in spec: + options.extend([ + '-DHDF5_USE_STATIC_LIBRARIES=ON', + ]) + + return options diff --git a/OpenFAST/share/template-module/ChangeLog.txt b/OpenFAST/share/template-module/ChangeLog.txt new file mode 100644 index 000000000..996c6b23c --- /dev/null +++ b/OpenFAST/share/template-module/ChangeLog.txt @@ -0,0 +1,38 @@ +ModuleName: The Template for modules in the FAST modularization framework + + +v1.00.02 22-Oct-2012 + Shortened some local variable names in the module and driver code (Param = p, ContState = x, etc.) + +v1.00.03 13-Nov-2012 + Modified template to address changes in Registry-generated code + +v1.00.04, 25-Jan-2013 + Cleaned up some text, removed the references to PACK and and UNPACK, as they are generated by the Registry. + +v1.00.05, 28-Jan-2013 + Made InitOut%WriteOutputHdr, InitOut%WriteOutputUnt, and y%WriteOutput ALLOCATABLE arrays. + +v1.01.00, 1-Mar-2013 + I renamed variable "Time" to "t" in the template.f90 file. + I added input "n" to _UpdateStates() and _UpdateDiscState() routines. n will start at zero. + I added an additional output argument to _UpdateStates(): zGuess(t+Increment) + I renamed "z_residual" to "Z_residual" + I modified the "u" input argument to _UpdateStates() to be an array of "Inputs", and I added a "InputTimes" array to + indicate what times are associated with each input. + +v1.02.00, 26-Mar-2013 + I removed z_next from the _UpdateStates routine and changed the description of the z argument (it + is no longer a "guess" at time t). The input z is the value at time t and the output z is the value + at time t+Interval. + I replaced "equations" with "functions" in the comments. + +v1.02.01, 21-May-2013 + I modified the INTENT attribute on the Inputs(:) argument of the template. This modification is due to the use + of the ExtrapInterp routine, which may need to update record-keeping attributes in Meshes. + +v2.00.00, 13-Nov-2015 + I added a MiscVar type as a standard type to split OtherStates into actual logical (other) states and miscellaneous variables + for optimization. OtherStates will now be associated with time, and miscellaneous variables will be used for optimzation, + not associated with time. + I modified the template with Doxygen-style comments and error handling. diff --git a/OpenFAST/share/template-module/README.md b/OpenFAST/share/template-module/README.md new file mode 100644 index 000000000..426d0c425 --- /dev/null +++ b/OpenFAST/share/template-module/README.md @@ -0,0 +1,3 @@ +# OpenFAST Module Template + +This directory contains a template for modules within the OpenFAST Framework. diff --git a/OpenFAST/share/template-module/src/ModuleName.f90 b/OpenFAST/share/template-module/src/ModuleName.f90 new file mode 100644 index 000000000..7a8af084f --- /dev/null +++ b/OpenFAST/share/template-module/src/ModuleName.f90 @@ -0,0 +1,851 @@ +!********************************************************************************************************************************** +!> ## ModuleName +!! The ModuleName and ModuleName_Types modules make up a template for creating user-defined calculations in the FAST Modularization +!! Framework. ModuleName_Types will be auto-generated by the FAST registry program, based on the variables specified in the +!! ModuleName_Registry.txt file. +!! +!! This template file contains comments in the style required for Doxygen, and it contains methods for handling errors. +!! +!! "ModuleName" should be replaced with the name of your module. Example: ElastoDyn \n +!! "ModName" (in ModName_*) should be replaced with the module name or an abbreviation of it. Example: ED +! .................................................................................................................................. +!! ## LICENSING +!! Copyright (C) 2012-2013, 2015-2016 National Renewable Energy Laboratory +!! +!! This file is part of ModuleName. +!! +!! 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 ModuleName + + USE ModuleName_Types + USE NWTC_Library + + IMPLICIT NONE + + PRIVATE + + TYPE(ProgDesc), PARAMETER :: ModName_Ver = ProgDesc( 'ModuleName', 'v2.01.00', '7-Jul-2016' ) !< module date/version information + + + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: ModName_Init ! Initialization routine + PUBLIC :: ModName_End ! Ending routine (includes clean up) + + PUBLIC :: ModName_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + ! continuous states, and updating discrete states + PUBLIC :: ModName_CalcOutput ! Routine for computing outputs + + PUBLIC :: ModName_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual + PUBLIC :: ModName_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: ModName_UpdateDiscState ! Tight coupling routine for updating discrete states + + PUBLIC :: ModName_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 :: ModName_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 :: ModName_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 :: ModName_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 :: ModName_GetOP ! Routine to get the operating-point values for linearization (from data structures to arrays) + +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. +!! The initial states and initial guess for the input are defined. +SUBROUTINE ModName_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ModName_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + TYPE(ModName_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(ModName_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(ModName_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(ModName_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(ModName_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (logical, etc) + TYPE(ModName_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(ModName_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) ModName_UpdateStates() is called in loose coupling & + !! (2) ModName_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(ModName_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! local variables + + INTEGER(IntKi) :: NumOuts ! number of outputs; would probably be in the parameter type + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Init' + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = "" + NumOuts = 2 + + + ! Initialize the NWTC Subroutine Library + call NWTC_Init( ) + + ! Display the module information + call DispNVD( ModName_Ver ) + + + ! Define parameters here: + p%DT = Interval + + + ! Define initial system states here: + x%DummyContState = 0.0_ReKi + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + OtherState%DummyOtherState = 0.0_ReKi + + + ! Define optimization variables here: + m%DummyMiscVar = 0.0_ReKi + + + ! Define initial guess for the system inputs here: + u%DummyInput = 0.0_ReKi + + + ! Define system output initializations (set up mesh) here: + call AllocAry( y%WriteOutput, NumOuts, 'WriteOutput', ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! set return error status based on local (concatenate errors) + if (ErrStat >= AbortErrLev) return ! if there are local variables that need to be deallocated, do so before early return + + y%DummyOutput = 0 + y%WriteOutput = 0 + + + ! Define initialization-routine output here: + call AllocAry(InitOut%WriteOutputHdr,NumOuts,'WriteOutputHdr',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call AllocAry(InitOut%WriteOutputUnt,NumOuts,'WriteOutputUnt',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return ! if there are local variables that need to be deallocated, do so before early return + + InitOut%WriteOutputHdr = (/ 'Time ', 'Column2' /) + InitOut%WriteOutputUnt = (/ '(s)', '(-)' /) + + + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: + + !Interval = p%DT + + + if (InitInp%Linearize) then + + ! If the module does not implement the four Jacobian routines at the end of this template, or the module cannot + ! linearize with the features that are enabled, stop the simulation if InitInp%Linearize is true. + + CALL SetErrStat( ErrID_Fatal, 'ModuleName cannot perform linearization analysis.', ErrStat, ErrMsg, RoutineName) + + ! Otherwise, if the module does allow linearization, return the appropriate Jacobian row/column names and rotating-frame flags here: + ! Allocate and set these variables: InitOut%LinNames_y, InitOut%LinNames_x, InitOut%LinNames_xd, InitOut%LinNames_z, InitOut%LinNames_u + ! Allocate and set these variables: InitOut%RotFrame_y, InitOut%RotFrame_x, InitOut%RotFrame_xd, InitOut%RotFrame_z, InitOut%RotFrame_u + + end if + + +END SUBROUTINE ModName_Init +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE ModName_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + TYPE(ModName_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(ModName_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(ModName_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(ModName_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(ModName_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(ModName_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) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_End' + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + !! Place any last minute operations or calculations here: + + + !! Close files here (but because of checkpoint-restart capability, it is not recommended to have files open during the simulation): + + + !! Destroy the input data: + + call ModName_DestroyInput( u, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + !! Destroy the parameter data: + + call ModName_DestroyParam( p, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + !! Destroy the state data: + + call ModName_DestroyContState( x, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ModName_DestroyDiscState( xd, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ModName_DestroyConstrState( z, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call ModName_DestroyOtherState( OtherState, ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + !! Destroy the output data: + + call ModName_DestroyOutput( y, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + !! Destroy the misc data: + + call ModName_DestroyMisc( m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + +END SUBROUTINE ModName_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ModName_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(ModName_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes (output from this routine only + !! because of record keeping in routines that copy meshes) + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(ModName_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(ModName_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; + !! Output: Other states at t + Interval + TYPE(ModName_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 + + TYPE(ModName_ContinuousStateType) :: dxdt ! Continuous state derivatives at t + TYPE(ModName_DiscreteStateType) :: xd_t ! Discrete states at t (copy) + TYPE(ModName_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z) + TYPE(ModName_InputType) :: u ! Instantaneous inputs + + INTEGER(IntKi) :: ErrStat2 ! local error status + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local error message + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_UpdateStates' + + + ! Initialize variables + + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + + ! This subroutine contains an example of how the states could be updated. Developers will + ! want to adjust the logic as necessary for their own situations. + + + + ! Get the inputs at time t, based on the array of values sent by the glue code: + + ! before calling ExtrapInterp routine, memory in u must be allocated; we can do that with a copy: + call ModName_CopyInput( Inputs(1), u, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() ! to avoid memory leaks, we have to destroy the local variables that may have allocatable arrays or meshes + return + end if + + call ModName_Input_ExtrapInterp( Inputs, InputTimes, u, t, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + return + end if + + + + ! Get first time derivatives of continuous states (dxdt): + + call ModName_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + return + end if + + + ! Update discrete states: + ! Note that xd [discrete state] is changed in ModName_UpdateDiscState() so xd will now contain values at t+Interval + ! We'll first make a copy that contains xd at time t, which will be used in computing the constraint states + call ModName_CopyDiscState( xd, xd_t, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + return + end if + + call ModName_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + return + end if + + + ! Solve for the constraint states (z) here: + + ! Iterate until the value is within a given tolerance. + + ! DO + + call ModName_CalcConstrStateResidual( t, u, p, x, xd_t, z, OtherState, m, Z_Residual, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + return + end if + + ! z = + + ! END DO + + + + ! Integrate (update) continuous states (x) here: + + !x = function of dxdt and x + + + ! Destroy local variables before returning + call cleanup() + + +CONTAINS + SUBROUTINE cleanup() + ! note that this routine inherits all of the data in ModName_UpdateStates + + + CALL ModName_DestroyInput( u, ErrStat2, ErrMsg2) + CALL ModName_DestroyConstrState( Z_Residual, ErrStat2, ErrMsg2) + CALL ModName_DestroyContState( dxdt, ErrStat2, ErrMsg2) + CALL ModName_DestroyDiscState( xd_t, ErrStat2, ErrMsg2) + + END SUBROUTINE cleanup +END SUBROUTINE ModName_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE ModName_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ModName_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ModName_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute outputs here: + y%DummyOutput = 2.0_ReKi + + y%WriteOutput(1) = REAL(t,ReKi) + y%WriteOutput(2) = 1.0_ReKi + + +END SUBROUTINE ModName_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> This is a tight coupling routine for computing derivatives of continuous states. +SUBROUTINE ModName_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ModName_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ModName_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Compute the first time derivatives of the continuous states here: + + dxdt%DummyContState = 0.0_ReKi + +END SUBROUTINE ModName_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for updating discrete states. +SUBROUTINE ModName_UpdateDiscState( t, n, u, 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(ModName_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ModName_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 + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Update discrete states here: + + xd%DummyDiscState = 0.0_Reki + +END SUBROUTINE ModName_UpdateDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a tight coupling routine for solving for the residual of the constraint state functions. +SUBROUTINE ModName_CalcConstrStateResidual( t, u, p, x, xd, z, OtherState, m, Z_residual, ErrStat, ErrMsg ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(ModName_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(ModName_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(ModName_ConstraintStateType), INTENT( OUT) :: Z_residual !< Residual of the constraint state functions 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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ! Solve for the residual of the constraint state functions here: + + Z_residual%DummyConstrState = 0.0_ReKi + +END SUBROUTINE ModName_CalcConstrStateResidual +!---------------------------------------------------------------------------------------------------------------------------------- + + +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in ModName_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> 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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ModName_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(ModName_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) :: dYdu(:,:) !< Partial derivatives of output functions (Y) with respect + !! to the inputs (u) [intent in to avoid deallocation] + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) with + !! respect to the inputs (u) [intent in to avoid deallocation] + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) with + !! respect to the inputs (u) [intent in to avoid deallocation] + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + IF ( PRESENT( dYdu ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + + ! allocate and set dYdu + + END IF + + IF ( PRESENT( dXdu ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + + ! allocate and set dXdu + + END IF + + IF ( PRESENT( dXddu ) ) THEN + + ! Calculate the partial derivative of the discrete state functions (Xd) with respect to the inputs (u) here: + + ! allocate and set dXddu + + END IF + + IF ( PRESENT( dZdu ) ) THEN + + ! Calculate the partial derivative of the constraint state functions (Z) with respect to the inputs (u) here: + + ! allocate and set dZdu + + END IF + + +END SUBROUTINE ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ModName_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(ModName_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) :: dYdx(:,:) !< Partial derivatives of output functions + !! (Y) with respect to the continuous + !! states (x) [intent in to avoid deallocation] + REAL(ReKi), 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(ReKi), 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(ReKi), 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 ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ModName_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(ModName_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) :: dYdxd(:,:) !< Partial derivatives of output functions + !! (Y) with respect to the discrete + !! states (xd) [intent in to avoid deallocation] + REAL(ReKi), 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(ReKi), 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(ReKi), 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 ModName_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 ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ModName_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(ModName_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) :: dYdz(:,:) !< Partial derivatives of output + !! functions (Y) with respect to the + !! constraint states (z) [intent in to avoid deallocation] + REAL(ReKi), 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(ReKi), 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(ReKi), 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 ModName_JacobianPConstrState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE ModName_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(ModName_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(ModName_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(ModName_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(ModName_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(ModName_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(ModName_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(ModName_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(ModName_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 + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( u_op ) ) THEN + + END IF + + IF ( PRESENT( y_op ) ) THEN + END IF + + IF ( PRESENT( x_op ) ) THEN + + END IF + + IF ( PRESENT( dx_op ) ) THEN + + END IF + + IF ( PRESENT( xd_op ) ) THEN + + END IF + + IF ( PRESENT( z_op ) ) THEN + + END IF + +END SUBROUTINE ModName_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +END MODULE ModuleName +!********************************************************************************************************************************** diff --git a/OpenFAST/share/template-module/src/ModuleName_Registry.txt b/OpenFAST/share/template-module/src/ModuleName_Registry.txt new file mode 100644 index 000000000..424928843 --- /dev/null +++ b/OpenFAST/share/template-module/src/ModuleName_Registry.txt @@ -0,0 +1,78 @@ +################################################################################################################################### +# Registry for ModuleName in the FAST Modularization Framework +# This Registry file is used to create MODULE ModuleName_Types, which contains all of the user-defined types needed in ModuleName. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# +# Entries are of the form +# keyword <ModuleName/ModName> <TypeName> <FieldType> <FieldName> <Dims> <IO> <DNAME> <DESCRIP> <UNITS> +# +# Use ^ as a shortcut for the value from the previous line. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + + +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name, etc. +typedef ModuleName/ModName InitInputType CHARACTER(1024) InputFile - - - "Name of the input file; remove if there is no file" - +typedef ^ ^ LOGICAL Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - + +# Define outputs from the initialization routine here: +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +# if this module has implemented linearization, return the names of the rows/columns of the Jacobian matrices: +#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_xd {:} - - "Names of the discrete states used in linearization" - +#typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_z {:} - - "Names of the constraint states 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" - +#typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +#typedef ^ InitOutputType LOGICAL RotFrame_xd {:} - - "Flag that tells FAST if the discrete states used in linearization are in the rotating frame" - +#typedef ^ InitOutputType LOGICAL RotFrame_z {:} - - "Flag that tells FAST if the constraint states used in linearization are in the rotating frame" - +#typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - + + +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - + +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - + +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - + +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType IntKi 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/optimization 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 DbKi DT - - - "Time step for cont. state integration & disc. state update" seconds + + +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +#typedef ^ InputType MeshType MeshedInput - - - "Meshed data" - +# Define inputs that are not on this mesh here: +typedef ^ InputType ReKi DummyInput - - - "Remove this variable if you have input data" - + + +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +#typedef ModuleName ModName_OutputType MeshType MeshedOutput - - - "Meshed data" - +# Define outputs that are not on this mesh here: +typedef ^ OutputType ReKi DummyOutput - - - "Remove this variable if you have output data" - +typedef ^ ^ ReKi WriteOutput {:} - - "Example of data to be written to an output file" "s,-" + diff --git a/OpenFAST/share/template-module/src/ModuleName_Types.f90 b/OpenFAST/share/template-module/src/ModuleName_Types.f90 new file mode 100644 index 000000000..da54b58b1 --- /dev/null +++ b/OpenFAST/share/template-module/src/ModuleName_Types.f90 @@ -0,0 +1,1916 @@ +!STARTOFREGISTRYGENERATEDFILE 'ModuleName_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 (v3.01.01, 19-Apr-2016) +!********************************************************************************************************************************* +! ModuleName_Types +!................................................................................................................................. +! This file is part of ModuleName. +! +! 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 ModuleName. 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 ModuleName_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= ModName_InitInputType ======= + TYPE, PUBLIC :: ModName_InitInputType + CHARACTER(1024) :: InputFile !< Name of the input file; remove if there is no file [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + END TYPE ModName_InitInputType +! ======================= +! ========= ModName_InitOutputType ======= + TYPE, PUBLIC :: ModName_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + END TYPE ModName_InitOutputType +! ======================= +! ========= ModName_ContinuousStateType ======= + TYPE, PUBLIC :: ModName_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE ModName_ContinuousStateType +! ======================= +! ========= ModName_DiscreteStateType ======= + TYPE, PUBLIC :: ModName_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE ModName_DiscreteStateType +! ======================= +! ========= ModName_ConstraintStateType ======= + TYPE, PUBLIC :: ModName_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE ModName_ConstraintStateType +! ======================= +! ========= ModName_OtherStateType ======= + TYPE, PUBLIC :: ModName_OtherStateType + INTEGER(IntKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE ModName_OtherStateType +! ======================= +! ========= ModName_MiscVarType ======= + TYPE, PUBLIC :: ModName_MiscVarType + REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc/optimization variables [-] + END TYPE ModName_MiscVarType +! ======================= +! ========= ModName_ParameterType ======= + TYPE, PUBLIC :: ModName_ParameterType + REAL(DbKi) :: DT !< Time step for cont. state integration & disc. state update [seconds] + END TYPE ModName_ParameterType +! ======================= +! ========= ModName_InputType ======= + TYPE, PUBLIC :: ModName_InputType + REAL(ReKi) :: DummyInput !< Remove this variable if you have input data [-] + END TYPE ModName_InputType +! ======================= +! ========= ModName_OutputType ======= + TYPE, PUBLIC :: ModName_OutputType + REAL(ReKi) :: DummyOutput !< Remove this variable if you have output data [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Example of data to be written to an output file [s,-] + END TYPE ModName_OutputType +! ======================= +CONTAINS + SUBROUTINE ModName_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(ModName_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 = 'ModName_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%Linearize = SrcInitInputData%Linearize + END SUBROUTINE ModName_CopyInitInput + + SUBROUTINE ModName_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(ModName_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyInitInput + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! Linearize + 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%InputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Linearize , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ModName_PackInitInput + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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%InputFile) + OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%Linearize = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ModName_UnPackInitInput + + SUBROUTINE ModName_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(ModName_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 = 'ModName_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + END SUBROUTINE ModName_CopyInitOutput + + SUBROUTINE ModName_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(ModName_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + END SUBROUTINE ModName_DestroyInitOutput + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + 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%WriteOutputHdr) ) 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%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) 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%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + END SUBROUTINE ModName_PackInitOutput + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr 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%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt 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%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + END SUBROUTINE ModName_UnPackInitOutput + + SUBROUTINE ModName_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(ModName_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 = 'ModName_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE ModName_CopyContState + + SUBROUTINE ModName_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(ModName_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyContState + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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:Re_Xferred+(1)-1 ) = InData%DummyContState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_PackContState + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 ModName_UnPackContState + + SUBROUTINE ModName_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(ModName_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 = 'ModName_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE ModName_CopyDiscState + + SUBROUTINE ModName_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(ModName_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyDiscState + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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:Re_Xferred+(1)-1 ) = InData%DummyDiscState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_PackDiscState + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 ModName_UnPackDiscState + + SUBROUTINE ModName_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(ModName_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 = 'ModName_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE ModName_CopyConstrState + + SUBROUTINE ModName_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(ModName_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyConstrState + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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:Re_Xferred+(1)-1 ) = InData%DummyConstrState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_PackConstrState + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 ModName_UnPackConstrState + + SUBROUTINE ModName_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(ModName_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 = 'ModName_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE ModName_CopyOtherState + + SUBROUTINE ModName_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(ModName_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyOtherState + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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 + Int_BufSz = Int_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 + + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DummyOtherState + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ModName_PackOtherState + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE ModName_UnPackOtherState + + SUBROUTINE ModName_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(ModName_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 = 'ModName_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE ModName_CopyMisc + + SUBROUTINE ModName_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(ModName_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyMisc + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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:Re_Xferred+(1)-1 ) = InData%DummyMiscVar + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_PackMisc + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 ModName_UnPackMisc + + SUBROUTINE ModName_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_ParameterType), INTENT(IN) :: SrcParamData + TYPE(ModName_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 = 'ModName_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%DT = SrcParamData%DT + END SUBROUTINE ModName_CopyParam + + SUBROUTINE ModName_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(ModName_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyParam + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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 + Db_BufSz = Db_BufSz + 1 ! DT + 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 + + DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE ModName_PackParam + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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%DT = DbKiBuf( Db_Xferred ) + Db_Xferred = Db_Xferred + 1 + END SUBROUTINE ModName_UnPackParam + + SUBROUTINE ModName_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_InputType), INTENT(IN) :: SrcInputData + TYPE(ModName_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) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInputData%DummyInput = SrcInputData%DummyInput + END SUBROUTINE ModName_CopyInput + + SUBROUTINE ModName_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(ModName_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE ModName_DestroyInput + + SUBROUTINE ModName_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(ModName_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 = 'ModName_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 + Re_BufSz = Re_BufSz + 1 ! DummyInput + 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:Re_Xferred+(1)-1 ) = InData%DummyInput + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_PackInput + + SUBROUTINE ModName_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(ModName_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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_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 + OutData%DummyInput = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE ModName_UnPackInput + + SUBROUTINE ModName_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ModName_OutputType), INTENT(IN) :: SrcOutputData + TYPE(ModName_OutputType), INTENT(INOUT) :: DstOutputData + 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 = 'ModName_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOutputData%DummyOutput = SrcOutputData%DummyOutput +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE ModName_CopyOutput + + SUBROUTINE ModName_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(ModName_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE ModName_DestroyOutput + + SUBROUTINE ModName_PackOutput( 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(ModName_OutputType), 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 = 'ModName_PackOutput' + ! 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 ! DummyOutput + 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 + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + 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:Re_Xferred+(1)-1 ) = InData%DummyOutput + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) 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%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) + END IF + END SUBROUTINE ModName_PackOutput + + SUBROUTINE ModName_UnPackOutput( 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(ModName_OutputType), 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 + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_UnPackOutput' + ! 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%DummyOutput = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput 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%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) + DEALLOCATE(mask1) + END IF + END SUBROUTINE ModName_UnPackOutput + + + SUBROUTINE ModName_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ModName_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(ModName_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL ModName_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ModName_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ModName_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ModName_Input_ExtrapInterp + + + SUBROUTINE ModName_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(ModName_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(ModName_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(ModName_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Input_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = -(u1%DummyInput - u2%DummyInput)/t(2) + u_out%DummyInput = u1%DummyInput + b0 * t_out + END SUBROUTINE ModName_Input_ExtrapInterp1 + + + SUBROUTINE ModName_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(ModName_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(ModName_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(ModName_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(ModName_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = (t(3)**2*(u1%DummyInput - u2%DummyInput) + t(2)**2*(-u1%DummyInput + u3%DummyInput))/(t(2)*t(3)*(t(2) - t(3))) + c0 = ( (t(2)-t(3))*u1%DummyInput + t(3)*u2%DummyInput - t(2)*u3%DummyInput ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%DummyInput = u1%DummyInput + b0 * t_out + c0 * t_out**2 + END SUBROUTINE ModName_Input_ExtrapInterp2 + + + SUBROUTINE ModName_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(ModName_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(ModName_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL ModName_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL ModName_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL ModName_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE ModName_Output_ExtrapInterp + + + SUBROUTINE ModName_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(ModName_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(ModName_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(ModName_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Output_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = -(y1%DummyOutput - y2%DummyOutput)/t(2) + y_out%DummyOutput = y1%DummyOutput + b0 * t_out +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) + ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) + b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) + y_out%WriteOutput = y1%WriteOutput + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated + END SUBROUTINE ModName_Output_ExtrapInterp1 + + + SUBROUTINE ModName_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(ModName_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(ModName_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(ModName_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(ModName_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'ModName_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + b0 = (t(3)**2*(y1%DummyOutput - y2%DummyOutput) + t(2)**2*(-y1%DummyOutput + y3%DummyOutput))/(t(2)*t(3)*(t(2) - t(3))) + c0 = ( (t(2)-t(3))*y1%DummyOutput + t(3)*y2%DummyOutput - t(2)*y3%DummyOutput ) / (t(2)*t(3)*(t(2) - t(3))) + y_out%DummyOutput = y1%DummyOutput + b0 * t_out + c0 * t_out**2 +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) + ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) + b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*y1%WriteOutput + t(3)*y2%WriteOutput - t(2)*y3%WriteOutput ) / (t(2)*t(3)*(t(2) - t(3))) + y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated + END SUBROUTINE ModName_Output_ExtrapInterp2 + +END MODULE ModuleName_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/OpenFAST/share/template-module/src/drivers/ModName_Driver.f90 b/OpenFAST/share/template-module/src/drivers/ModName_Driver.f90 new file mode 100644 index 000000000..6e6bae299 --- /dev/null +++ b/OpenFAST/share/template-module/src/drivers/ModName_Driver.f90 @@ -0,0 +1,128 @@ +!********************************************************************************************************************************** +!> ## ModuleName_DriverCode: This code tests the template modules +!!.................................................................................................................................. +!! LICENSING +!! Copyright (C) 2012, 2015 National Renewable Energy Laboratory +!! +!! This file is part of ModuleName. +!! +!! 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. +!********************************************************************************************************************************** +PROGRAM ModName_Driver + + USE NWTC_Library + USE ModuleName + USE ModuleName_Types + + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 1 !< Number of inputs sent to ModName_UpdateStates + + ! Program variables + + REAL(DbKi) :: Time !< Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval !< Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) !< Variable for storing time associated with inputs, in seconds + + TYPE(ModName_InitInputType) :: InitInData !< Input data for initialization + TYPE(ModName_InitOutputType) :: InitOutData !< Output data from initialization + + TYPE(ModName_ContinuousStateType) :: x !< Continuous states + TYPE(ModName_DiscreteStateType) :: xd !< Discrete states + TYPE(ModName_ConstraintStateType) :: z !< Constraint states + TYPE(ModName_ConstraintStateType) :: Z_residual !< Residual of the constraint state functions (Z) + TYPE(ModName_OtherStateType) :: OtherState !< Other states + TYPE(ModName_MiscVarType) :: misc !< Optimization variables + + TYPE(ModName_ParameterType) :: p !< Parameters + TYPE(ModName_InputType) :: u(NumInp) !< System inputs + TYPE(ModName_OutputType) :: y !< System outputs + + + + INTEGER(IntKi) :: n !< Loop counter (for time step) + INTEGER(IntKi) :: ErrStat !< Status of error message + CHARACTER(ErrMsgLen) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + + ! Populate the InitInData data structure here: + + InitInData%InputFile = 'MyInputFileName.inp' + + ! Set the driver's request for time interval here: + + TimeInterval = 0.25 ! Glue code's request for delta time (likely based on information from other modules) + + + ! Initialize the module + + CALL ModName_Init( InitInData, u(1), p, x, xd, z, OtherState, y, misc, TimeInterval, InitOutData, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + ! Destroy initialization data + + CALL ModName_DestroyInitInput( InitInData, ErrStat, ErrMsg ) + CALL ModName_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + + + DO n = 0,2 + + Time = n*TimeInterval + InputTime(1) = Time + + ! Modify u (likely from the outputs of another module or a set of test conditions) here: + + + ! Calculate outputs at n + + CALL ModName_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + + CALL ModName_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, misc, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary + CALL WrScr( ErrMsg ) + END IF + + + END DO + + + !............................................................................................................................... + ! Routine to terminate program execution + !............................................................................................................................... + CALL ModName_End( u(1), p, x, xd, z, OtherState, y, misc, ErrStat, ErrMsg ) + + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + +END PROGRAM ModName_Driver diff --git a/OpenFAST/share/vscode/launch.json b/OpenFAST/share/vscode/launch.json new file mode 100644 index 000000000..77824f2e2 --- /dev/null +++ b/OpenFAST/share/vscode/launch.json @@ -0,0 +1,43 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "5MW_OC3Trpd_DLL_WSt_WavesReg", + "type": "gdb", + "request": "launch", + "printCalls": false, + "showDevDebugOutput": true, + "valuesFormatting": "prettyPrinters", + "gdbpath": "gdb", + "target": "${workspaceRoot}/build/glue-codes/openfast/openfast", + "cwd": "${workspaceRoot}/build/reg_tests/glue-codes/openfast/5MW_OC3Trpd_DLL_WSt_WavesReg/", + "arguments": "5MW_OC3Trpd_DLL_WSt_WavesReg.fst" + }, + { + "name": "bd_curved_beam", + "type": "gdb", + "request": "launch", + "printCalls": false, + "showDevDebugOutput": false, + "valuesFormatting": "prettyPrinters", + "gdbpath": "gdb-ia", + "target": "${workspaceRoot}/build/modules-local/beamdyn/beamdyn_driver", + "cwd": "${workspaceRoot}/build/reg_tests/modules-local/beamdyn/bd_curved_beam/", + "arguments": "${workspaceRoot}/build/reg_tests/modules-local/beamdyn/bd_curved_beam/bd_driver.inp" + }, + { + "name": "beamdyn_utest", + "type": "gdb", + "request": "launch", + "printCalls": false, + "showDevDebugOutput": false, + "valuesFormatting": "prettyPrinters", + "gdbpath": "gdb-ia", + "target": "${workspaceRoot}/build/unit_tests/beamdyn_utest", + "cwd": "${workspaceRoot}/build/unit_tests" + } + ] +} \ No newline at end of file diff --git a/OpenFAST/unit_tests/CMakeLists.txt b/OpenFAST/unit_tests/CMakeLists.txt new file mode 100644 index 000000000..4339b0c43 --- /dev/null +++ b/OpenFAST/unit_tests/CMakeLists.txt @@ -0,0 +1,80 @@ +# +# Copyright 2017 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. +# + +# ----------------------------------------------------------- +# -- OpenFAST Unit Testing +# ----------------------------------------------------------- + +cmake_minimum_required(VERSION 2.8.12) +project(OpenFAST_UnitTest Fortran) + +include(CTest) + +# Set the python executable configuration option and default +if(NOT EXISTS ${PYTHON_EXECUTABLE}) + find_program(PYTHON_EXECUTABLE NAMES python3 python py) + if(NOT EXISTS ${PYTHON_EXECUTABLE}) + message(FATAL_ERROR "CMake cannot find a Python interpreter in your path. Python is required to run OpenFAST tests." ) + endif() +endif() + +### pfunit +include(ExternalProject) +set(ExternalProjectCMakeArgs + -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/pfunit + -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} + -DROBUST=OFF +) +set(PFUNIT_INSTALL ${PROJECT_BINARY_DIR}/pfunit) + +ExternalProject_Add(pfunit + SOURCE_DIR ${PROJECT_SOURCE_DIR}/pfunit + BINARY_DIR ${PROJECT_BINARY_DIR}/pfunit-build + STAMP_DIR ${PROJECT_BINARY_DIR}/pfunit-stamp + TMP_DIR ${PROJECT_BINARY_DIR}/pfunit-tmp + INSTALL_DIR ${PFUNIT_INSTALL} + CMAKE_ARGS ${ExternalProjectCMakeArgs} +) + +include_directories(${PROJECT_BINARY_DIR}/pfunit/mod) + +set(pfunit_directory ${PFUNIT_INSTALL}) +set(source_modulesdirectory ${PROJECT_SOURCE_DIR}/../modules) +set(build_testdirectory ${PROJECT_BINARY_DIR}/tests) + +include_directories( + ${PROJECT_SOURCE_DIR} + ${build_testdirectory} + ${pfunit_directory}/mod +) + +set_source_files_properties(${pfunit_directory}/include/driver.F90 PROPERTIES GENERATED 1) +if(APPLE OR UNIX OR CYGWIN OR MINGW) + set(pfunit_lib "/lib/libpfunit.a") +else() # Windows + set(pfunit_lib "/lib/pfunit.lib") +endif() + +### Add the unit tests here +add_subdirectory("beamdyn") +add_subdirectory("nwtc-library") +add_subdirectory("aerodyn") +add_subdirectory("inflowwind") + +add_custom_target( + unit_tests + DEPENDS beamdyn_utest nwtc_library_utest fvw_utest inflowwind_utest +) diff --git a/OpenFAST/unit_tests/README.md b/OpenFAST/unit_tests/README.md new file mode 100644 index 000000000..48cc58948 --- /dev/null +++ b/OpenFAST/unit_tests/README.md @@ -0,0 +1,14 @@ +# openfast/unit_tests + +This directory contains the unit test suite for the OpenFAST framework. Contained in this directory are +- [pFUnit](http://pfunit.sourceforge.net), an external framework for Fortran unit testing +- CMake configuration file +- A unit test template file + +The dependencies for unit testing are: +- Python 3.7+ +- pFUnit +- CMake + +### Usage +See [readthedocs](http://openfast.readthedocs.io/en/latest/source/user/testing/unit_test.html) for complete documentation on OpenFAST unit test usage and expansion. \ No newline at end of file diff --git a/OpenFAST/unit_tests/aerodyn/CMakeLists.txt b/OpenFAST/unit_tests/aerodyn/CMakeLists.txt new file mode 100644 index 000000000..4e0bf8685 --- /dev/null +++ b/OpenFAST/unit_tests/aerodyn/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# Copyright 2017 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. +# + +set_source_files_properties(${pfunit_directory}/include/driver.F90 PROPERTIES GENERATED 1) + +set(module_name "fvw") +set(module_directory "aerodyn") +set(module_library "fvwlib") + +file(MAKE_DIRECTORY ${build_testdirectory}/${module_directory}) +file(WRITE ${build_testdirectory}/${module_directory}/testSuites.inc "") + +include_directories( + ${PROJECT_SOURCE_DIR} + ${pfunit_directory}/mod + ${build_testdirectory}/${module_directory} +) + +set(testlist + test_FVW_testsuite +) +foreach(test ${testlist}) + set(test_dependency pfunit ${source_modulesdirectory}/${module_directory}/tests/${test}.F90) + add_custom_command( + OUTPUT ${build_testdirectory}/${module_directory}/${test}.F90 + COMMAND ${PYTHON_EXECUTABLE} ${pfunit_directory}/bin/pFUnitParser.py ${source_modulesdirectory}/${module_directory}/tests/${test}.F90 ${build_testdirectory}/${module_directory}/${test}.F90 + DEPENDS ${test_dependency} + ) + set(test_sources ${test_sources} ${build_testdirectory}/${module_directory}/${test}.F90) + file(APPEND ${build_testdirectory}/${module_directory}/testSuites.inc "ADD_TEST_SUITE(${test}_suite)\n") +endforeach() + +add_executable( + ${module_name}_utest + ${pfunit_directory}/include/driver.F90 + ${test_sources} +) + +target_link_libraries( + ${module_name}_utest + ${pfunit_directory}${pfunit_lib} + ${module_library} +) + +add_test( + ${module_name}_utest + ${PROJECT_BINARY_DIR}/${module_directory}/${module_name}_utest +) diff --git a/OpenFAST/unit_tests/beamdyn/CMakeLists.txt b/OpenFAST/unit_tests/beamdyn/CMakeLists.txt new file mode 100644 index 000000000..c93ac2849 --- /dev/null +++ b/OpenFAST/unit_tests/beamdyn/CMakeLists.txt @@ -0,0 +1,79 @@ +# +# Copyright 2017 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. +# + +set_source_files_properties(${pfunit_directory}/include/driver.F90 PROPERTIES GENERATED 1) + +set(module_name "beamdyn") +set(module_directory "beamdyn") +set(module_library "beamdynlib") + +file(MAKE_DIRECTORY ${build_testdirectory}/${module_directory}) +file(WRITE ${build_testdirectory}/${module_directory}/testSuites.inc "") + +include_directories( + ${PROJECT_SOURCE_DIR} + ${pfunit_directory}/mod + ${build_testdirectory}/${module_directory} +) + +set(testlist + test_tools + test_BD_ComputeIniNodalCrv + test_BD_CrvCompose + test_BD_CheckRotMat + test_BD_CrvExtractCrv + test_BD_CrvMatrixR + test_BD_CrvMatrixH + test_ExtractRelativeRotation + test_BD_InputGlobalLocal + test_BD_DistrLoadCopy + test_BD_GravityForce + test_BD_QPData_mEta_rho + test_BD_GenerateGLL + test_BD_GaussPointWeight + test_BD_diffmtc + test_BD_InitShpDerJaco + test_BD_MemberEta + test_BD_TrapezoidalPointWeight + test_InitializeNodalLocations +) +foreach(test ${testlist}) + set(test_dependency pfunit ${source_modulesdirectory}/${module_directory}/tests/${test}.F90) + add_custom_command( + OUTPUT ${build_testdirectory}/${module_directory}/${test}.F90 + COMMAND ${PYTHON_EXECUTABLE} ${pfunit_directory}/bin/pFUnitParser.py ${source_modulesdirectory}/${module_directory}/tests/${test}.F90 ${build_testdirectory}/${module_directory}/${test}.F90 + DEPENDS ${test_dependency} + ) + set(test_sources ${test_sources} ${build_testdirectory}/${module_directory}/${test}.F90) + file(APPEND ${build_testdirectory}/${module_directory}/testSuites.inc "ADD_TEST_SUITE(${test}_suite)\n") +endforeach() + +add_executable( + ${module_name}_utest + ${pfunit_directory}/include/driver.F90 + ${test_sources} +) + +target_link_libraries( + ${module_name}_utest + ${pfunit_directory}${pfunit_lib} + ${module_library} +) + +add_test( + ${module_name}_utest + ${PROJECT_BINARY_DIR}/${module_directory}/${module_name}_utest +) diff --git a/OpenFAST/unit_tests/inflowwind/CMakeLists.txt b/OpenFAST/unit_tests/inflowwind/CMakeLists.txt new file mode 100644 index 000000000..b1a41ef67 --- /dev/null +++ b/OpenFAST/unit_tests/inflowwind/CMakeLists.txt @@ -0,0 +1,67 @@ +# +# Copyright 2017 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. +# + +set_source_files_properties(${pfunit_directory}/include/driver.F90 PROPERTIES GENERATED 1) + +set(module_name "inflowwind") +set(module_directory "inflowwind") +set(module_library "ifwlib") + +file(MAKE_DIRECTORY ${build_testdirectory}/${module_directory}) +file(WRITE ${build_testdirectory}/${module_directory}/testSuites.inc "") + +include_directories( + ${PROJECT_SOURCE_DIR} + ${pfunit_directory}/mod + ${build_testdirectory}/${module_directory} +) + +set(testlist + ifw_test_tools + test_steady_wind + test_turbsim_wind + test_bladed_wind + test_hawc_wind + test_outputs + test_uniform_wind +) +foreach(test ${testlist}) + set(test_dependency pfunit ${source_modulesdirectory}/${module_directory}/tests/${test}.F90) + add_custom_command( + OUTPUT ${build_testdirectory}/${module_directory}/${test}.F90 + COMMAND ${PYTHON_EXECUTABLE} ${pfunit_directory}/bin/pFUnitParser.py ${source_modulesdirectory}/${module_directory}/tests/${test}.F90 ${build_testdirectory}/${module_directory}/${test}.F90 + DEPENDS ${test_dependency} + ) + set(test_sources ${test_sources} ${build_testdirectory}/${module_directory}/${test}.F90) + file(APPEND ${build_testdirectory}/${module_directory}/testSuites.inc "ADD_TEST_SUITE(${test}_suite)\n") +endforeach() + +add_executable( + ${module_name}_utest + ${pfunit_directory}/include/driver.F90 + ${test_sources} +) + +target_link_libraries( + ${module_name}_utest + ${pfunit_directory}${pfunit_lib} + ${module_library} +) + +add_test( + ${module_name}_utest + ${PROJECT_BINARY_DIR}/${module_directory}/${module_name}_utest +) diff --git a/OpenFAST/unit_tests/nwtc-library/CMakeLists.txt b/OpenFAST/unit_tests/nwtc-library/CMakeLists.txt new file mode 100644 index 000000000..7b425944a --- /dev/null +++ b/OpenFAST/unit_tests/nwtc-library/CMakeLists.txt @@ -0,0 +1,65 @@ +# +# Copyright 2017 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. +# + +# Tell CMake not to look for this file to exist since its generated by pFUnit during compile +set_source_files_properties(${pfunit_directory}/include/driver.F90 PROPERTIES GENERATED 1) + +set(module_name "nwtc_library") +set(module_directory "nwtc-library") +set(module_library "nwtclibs") + +file(MAKE_DIRECTORY ${build_testdirectory}/${module_directory}) +file(WRITE ${build_testdirectory}/${module_directory}/testSuites.inc "") + +include_directories( + ${PROJECT_SOURCE_DIR} + ${pfunit_directory}/mod + ${build_testdirectory}/${module_directory} +) + +set(testlist + test_NWTC_IO_CheckArgs + test_NWTC_IO_FileInfo + test_NWTC_RandomNumber +) +foreach(test ${testlist}) + set(test_dependency pfunit ${source_modulesdirectory}/${module_directory}/tests/${test}.F90) + add_custom_command( + OUTPUT ${build_testdirectory}/${module_directory}/${test}.F90 + COMMAND ${PYTHON_EXECUTABLE} ${pfunit_directory}/bin/pFUnitParser.py ${source_modulesdirectory}/${module_directory}/tests/${test}.F90 ${build_testdirectory}/${module_directory}/${test}.F90 + DEPENDS ${test_dependency} + ) + set(test_sources ${test_sources} ${build_testdirectory}/${module_directory}/${test}.F90) + file(APPEND ${build_testdirectory}/${module_directory}/testSuites.inc "ADD_TEST_SUITE(${test}_suite)\n") +endforeach() + +add_executable( + ${module_name}_utest + ${pfunit_directory}/include/driver.F90 + ${test_sources} +) + +target_link_libraries( + ${module_name}_utest + ${pfunit_directory}${pfunit_lib} + ${module_library} +) + +add_test( + ${module_name}_utest + ${PROJECT_BINARY_DIR}/${module_directory}/${module_name}_utest +) + diff --git a/OpenFAST/unit_tests/pfunit b/OpenFAST/unit_tests/pfunit new file mode 160000 index 000000000..a192e8224 --- /dev/null +++ b/OpenFAST/unit_tests/pfunit @@ -0,0 +1 @@ +Subproject commit a192e82246b44e701446811a9792a530e4f250c7 diff --git a/OpenFAST/unit_tests/test_SUBROUTINE.F90 b/OpenFAST/unit_tests/test_SUBROUTINE.F90 new file mode 100644 index 000000000..01807ab05 --- /dev/null +++ b/OpenFAST/unit_tests/test_SUBROUTINE.F90 @@ -0,0 +1,89 @@ +module test_SUBROUTINE + + use pFUnit_mod + use NWTC_IO + ! use MODULE ! Import the module that will be tested here. + + implicit none + + real(ReKi) :: tolerance = 1e-14 + character(1024) :: testname + +contains + + ! Test branches + ! - branch 1 + ! - branch 2 + ! - branch 3 + + ! Note that this module is *not* conforming Fortran code. + ! This is passed through a Python preprocessor included with pFUnit which parses + ! pFUnit directives like `@test` and `@assertEqual` to generate proper Fortran code. + + @test + subroutine test_branch1() + + ! Describe this test. + ! What is the expected result from the tested subroutine? + ! Why is the expected result the result that is expected? + + real(ReKi) :: zero = 0.0 + real(ReKi) :: test_result + integer(IntKi) :: error_status + + testname = "Branch 1" + expected = 0.0 + + ! Assume SUBROUTINE( intent(in), intent(out), intent(out) ) + call SUBROUTINE(zero, test_result, error_status) + + @assertEqual(expected, test_result, tolerance, testname) + @assertEqual(0, error_status, tolerance, testname) + + end subroutine + + @test + subroutine test_branch2() + + ! Describe this test. + ! What is the expected result from the tested subroutine? + ! Why is the expected result the result that is expected? + + real(ReKi) :: pi = 3.14159 + real(ReKi) :: test_result + integer(IntKi) :: error_status + + testname = "Branch 2" + expected = 0.0 + + ! Assume SUBROUTINE( intent(in), intent(out), intent(out) ) + call SUBROUTINE(pi, test_result, error_status) + + @assertEqual(expected, test_result, tolerance, testname) + @assertEqual(0, error_status, tolerance, testname) + + end subroutine + + @test + subroutine test_branch3() + + ! Describe this test. + ! What is the expected result from the tested subroutine? + ! Why is the expected result the result that is expected? + + real(ReKi) :: pi_by_2 = 1.57079 + real(ReKi) :: test_result + integer(IntKi) :: error_status + + testname = "Branch 3" + expected = 99.9 + + ! Assume SUBROUTINE( intent(in), intent(out), intent(out) ) + call SUBROUTINE(pi_by_2, test_result, error_status) + + @assertEqual(expected, test_result, tolerance, testname) + @assertEqual(0, error_status, tolerance, testname) + + end subroutine + +end module diff --git a/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.sln b/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.sln new file mode 100644 index 000000000..032b12d2f --- /dev/null +++ b/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "AeroDyn_Driver", "AeroDyn_Driver.vfproj", "{97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug|Win32.ActiveCfg = Debug|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug|Win32.Build.0 = Debug|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug|x64.ActiveCfg = Debug|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Debug|x64.Build.0 = Debug|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release_Double|x64.Build.0 = Release_Double|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|Win32.ActiveCfg = Release|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|Win32.Build.0 = Release|Win32 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|x64.ActiveCfg = Release|x64 + {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|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|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {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|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 + {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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.vfproj b/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.vfproj new file mode 100644 index 000000000..72d14743c --- /dev/null +++ b/OpenFAST/vs-build/AeroDyn/AeroDyn_Driver.vfproj @@ -0,0 +1,681 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="AeroAcoustics"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\AeroAcoustics_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\AeroAcoustics_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\AeroAcoustics.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\AeroAcoustics_IO.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\AeroAcoustics_TNO.f90"/></Filter> + <Filter Name="AeroDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn_AllBldNdOuts_IO.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_IO.f90"/></Filter> + <Filter Name="AeroDyn_Driver"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Driver_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn_Driver" Description="Running Registry for AeroDyn Driver" Outputs="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Driver_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Driver.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\AeroDyn_Driver_Subs.f90"/></Filter> + <Filter Name="AirFoil_Info"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\AirfoilInfo_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\AirfoilInfo_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\AirfoilInfo.f90"/></Filter> + <Filter Name="BEMT"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\BEMT_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\AeroDyn\src\BEMT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\BEMT_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\BEMT.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\BEMTUncoupled.f90"/> + <File RelativePath="..\..\modules\AeroDyn\src\mod_root1dim.f90"/></Filter> + <Filter Name="DBEMT"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\DBEMT_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\AeroDyn\src\DBEMT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\DBEMT_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\DBEMT.f90"/></Filter> + <Filter Name="FVW"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\FVW_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\AeroDyn\src\FVW_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\FVW_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\aerodyn\src\FVW.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_BiotSavart.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" OpenMP="OpenMPParallelCode"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\FVW_IO.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Subs.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Tests.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_VortexTools.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_VTK.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Wings.f90"/></Filter> + <Filter Name="NWTC_Library"> + <Filter Name="NetLib"> + <Filter Name="FFTPACK"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\fftpack4.1.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <Filter Name="ScaLAPACK"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\dlasrt2.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\slasrt2.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <Filter Name="SLATEC"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\d1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\dqk61.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\fdump.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\i1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\j4save.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\qk61.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\r1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xercnt.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xerhlt.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xermsg.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xerprn.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xersve.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xgetua.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\NWTC_FFTPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\NWTC_ScaLAPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\NWTC_SLATEC.f90"/></Filter> + <Filter Name="RanLux"> + <File RelativePath="..\..\modules\nwtc-library\src\ranlux\RANLUX.f90"/></Filter> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\nwtc-library\src\Registry_NWTC_Library.txt"/></Filter> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"/></Filter> + <Filter Name="UnsteadyAero"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\AeroDyn\src\UnsteadyAero_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\AeroDyn\src\UnsteadyAero_Types.f90"/></Filter> + <File RelativePath="..\..\modules\AeroDyn\src\UnsteadyAero.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/BeamDyn/BeamDyn-w-registry.sln b/OpenFAST/vs-build/BeamDyn/BeamDyn-w-registry.sln new file mode 100644 index 000000000..0261cbdc7 --- /dev/null +++ b/OpenFAST/vs-build/BeamDyn/BeamDyn-w-registry.sln @@ -0,0 +1,64 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "BeamDyn", "BeamDyn.vfproj", "{815C302F-A93D-4C22-9329-7112345113C0}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-7112345113C0}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug|Win32.Build.0 = Debug|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug|x64.ActiveCfg = Debug|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Debug|x64.Build.0 = Debug|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Release_Double|x64.Build.0 = Release_Double|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Release|Win32.ActiveCfg = Release|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Release|Win32.Build.0 = Release|Win32 + {815C302F-A93D-4C22-9329-7112345113C0}.Release|x64.ActiveCfg = Release|x64 + {815C302F-A93D-4C22-9329-7112345113C0}.Release|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 + {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|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 + {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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {37F40376-E0A4-4BB3-A987-A3CF5A440217} + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/BeamDyn/BeamDyn.vfproj b/OpenFAST/vs-build/BeamDyn/BeamDyn.vfproj new file mode 100644 index 000000000..852d40158 --- /dev/null +++ b/OpenFAST/vs-build/BeamDyn/BeamDyn.vfproj @@ -0,0 +1,295 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{815C302F-A93D-4C22-9329-7112345113C0}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" InitLocalVarToNAN="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="BeamDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" DisableSpecificDiagnostics="5268" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" DisableSpecificDiagnostics="5268" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\beamdyn\src\Registry_BeamDyn.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_BldNdOuts_IO.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_IO.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_Subs.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\Driver_Beam.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\Driver_Beam_Subs.f90"/></Filter> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/></Filter> + <Filter Name="NWTC_Library"> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/CreateGitVersion.bat b/OpenFAST/vs-build/CreateGitVersion.bat new file mode 100644 index 000000000..91647f8e9 --- /dev/null +++ b/OpenFAST/vs-build/CreateGitVersion.bat @@ -0,0 +1,9 @@ +@ECHO off +SET IncludeFile=..\gitVersionInfo.h + +<NUL SET /p IncludeTxt=#define GIT_VERSION_INFO '> %IncludeFile% +FOR /f %%a IN ('git describe --abbrev^=8 --always --tags --dirty') DO <NUL SET /p IncludeTxt=%%a>> %IncludeFile% +git describe --abbrev^=8 --always --tags --dirty > NUL +IF %ERRORLEVEL%==0 ( ECHO '>> %IncludeFile% ) else ( ECHO Unversioned from $Format:%H$ '>> %IncludeFile% ) + +EXIT /B 0 \ No newline at end of file diff --git a/OpenFAST/vs-build/Discon/Discon.sln b/OpenFAST/vs-build/Discon/Discon.sln new file mode 100644 index 000000000..7c5b5beb5 --- /dev/null +++ b/OpenFAST/vs-build/Discon/Discon.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2043 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "Discon", "Discon.vfproj", "{183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}" +EndProject +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "Discon_ITIBarge", "Discon_ITIBarge.vfproj", "{11A28263-1385-47DF-9122-30BF9C0DF013}" +EndProject +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "Discon_OC3Hywind", "Discon_OC3Hywind.vfproj", "{3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Debug|Win32.Build.0 = Debug|Win32 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Debug|x64.ActiveCfg = Debug|x64 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Debug|x64.Build.0 = Debug|x64 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Release|Win32.ActiveCfg = Release|Win32 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Release|Win32.Build.0 = Release|Win32 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Release|x64.ActiveCfg = Release|x64 + {183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}.Release|x64.Build.0 = Release|x64 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Debug|Win32.ActiveCfg = Debug|Win32 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Debug|Win32.Build.0 = Debug|Win32 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Debug|x64.ActiveCfg = Debug|x64 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Debug|x64.Build.0 = Debug|x64 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Release|Win32.ActiveCfg = Release|Win32 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Release|Win32.Build.0 = Release|Win32 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Release|x64.ActiveCfg = Release|x64 + {11A28263-1385-47DF-9122-30BF9C0DF013}.Release|x64.Build.0 = Release|x64 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Debug|Win32.Build.0 = Debug|Win32 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Debug|x64.ActiveCfg = Debug|x64 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Debug|x64.Build.0 = Debug|x64 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Release|Win32.ActiveCfg = Release|Win32 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Release|Win32.Build.0 = Release|Win32 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Release|x64.ActiveCfg = Release|x64 + {3BA7CEDE-8D58-4D18-8A59-A4114FB70B9C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A4EE85D3-EA0C-4285-B446-0E8D70945A10} + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/Discon/Discon.vfproj b/OpenFAST/vs-build/Discon/Discon.vfproj new file mode 100644 index 000000000..30d07a9dc --- /dev/null +++ b/OpenFAST/vs-build/Discon/Discon.vfproj @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectType="typeDynamicLibrary" ProjectCreator="Intel Fortran" Keyword="Dll" Version="11.0" ProjectIdGuid="{183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd;h;inc"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <File RelativePath="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData\DISCON\DISCON.F90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/Discon/Discon_ITIBarge.vfproj b/OpenFAST/vs-build/Discon/Discon_ITIBarge.vfproj new file mode 100644 index 000000000..d263c96c1 --- /dev/null +++ b/OpenFAST/vs-build/Discon/Discon_ITIBarge.vfproj @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectType="typeDynamicLibrary" ProjectCreator="Intel Fortran" Keyword="Dll" Version="11.0" ProjectIdGuid="{183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd;h;inc"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <File RelativePath="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData\DISCON_ITI\DISCON_ITIBarge.F90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/Discon/Discon_OC3Hywind.vfproj b/OpenFAST/vs-build/Discon/Discon_OC3Hywind.vfproj new file mode 100644 index 000000000..f821f3dcf --- /dev/null +++ b/OpenFAST/vs-build/Discon/Discon_OC3Hywind.vfproj @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectType="typeDynamicLibrary" ProjectCreator="Intel Fortran" Keyword="Dll" Version="11.0" ProjectIdGuid="{183CC593-AD4C-4A15-81C1-7D6D20A9A5ED}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData" IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" ProgramDatabaseFile="" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd;h;inc"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <File RelativePath="..\..\reg_tests\r-test\glue-codes\openfast\5MW_Baseline\ServoData\DISCON_OC3\DISCON_OC3Hywind.F90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/FAST/FAST.sln b/OpenFAST/vs-build/FAST/FAST.sln new file mode 100644 index 000000000..ec3d69105 --- /dev/null +++ b/OpenFAST/vs-build/FAST/FAST.sln @@ -0,0 +1,160 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2043 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "FAST", "FAST.vfproj", "{18AE8067-CCC6-4479-A0DB-C4089EF9FE71}" + ProjectSection(ProjectDependencies) = postProject + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9} = {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9} + EndProjectSection +EndProject +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "FASTlib", "..\FASTlib\FASTlib.vfproj", "{1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}" + ProjectSection(ProjectDependencies) = postProject + {BF86702A-CB17-4050-8AE9-078CDC5910D3} = {BF86702A-CB17-4050-8AE9-078CDC5910D3} + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MAP_dll", "..\MAPlib\MAP_dll.vcxproj", "{BF86702A-CB17-4050-8AE9-078CDC5910D3}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "OpenFAST-Simulink", "..\OpenFAST-Simulink\OpenFAST-Simulink.vfproj", "{C3C93CC0-EDD7-438F-988C-1F917FAEFA67}" + ProjectSection(ProjectDependencies) = postProject + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9} = {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 + Debug_Matlab|Win32 = Debug_Matlab|Win32 + Debug_Matlab|x64 = Debug_Matlab|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 + Release_Matlab|Win32 = Release_Matlab|Win32 + Release_Matlab|x64 = Release_Matlab|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Matlab|Win32.ActiveCfg = Debug|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug_Matlab|x64.ActiveCfg = Debug|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug|Win32.ActiveCfg = Debug|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug|Win32.Build.0 = Debug|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug|x64.ActiveCfg = Debug|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Debug|x64.Build.0 = Debug|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Double|x64.Build.0 = Release_Double|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Matlab|Win32.ActiveCfg = Release|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release_Matlab|x64.ActiveCfg = Release|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release|Win32.ActiveCfg = Release|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release|Win32.Build.0 = Release|Win32 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release|x64.ActiveCfg = Release|x64 + {18AE8067-CCC6-4479-A0DB-C4089EF9FE71}.Release|x64.Build.0 = Release|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Matlab|Win32.ActiveCfg = Debug_Matlab|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Matlab|Win32.Build.0 = Debug_Matlab|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Matlab|x64.ActiveCfg = Debug_Matlab|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug_Matlab|x64.Build.0 = Debug_Matlab|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug|Win32.ActiveCfg = Debug|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug|Win32.Build.0 = Debug|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug|x64.ActiveCfg = Debug|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Debug|x64.Build.0 = Debug|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Double|x64.Build.0 = Release_Double|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Matlab|Win32.ActiveCfg = Release_Matlab|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Matlab|Win32.Build.0 = Release_Matlab|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Matlab|x64.ActiveCfg = Release_Matlab|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release_Matlab|x64.Build.0 = Release_Matlab|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release|Win32.ActiveCfg = Release|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release|Win32.Build.0 = Release|Win32 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release|x64.ActiveCfg = Release|x64 + {1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}.Release|x64.Build.0 = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Double|Win32.ActiveCfg = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Double|Win32.Build.0 = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Double|x64.ActiveCfg = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Double|x64.Build.0 = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Matlab|Win32.ActiveCfg = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Matlab|Win32.Build.0 = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Matlab|x64.ActiveCfg = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug_Matlab|x64.Build.0 = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug|Win32.Build.0 = Debug|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug|x64.ActiveCfg = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Debug|x64.Build.0 = Debug|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Double|Win32.ActiveCfg = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Double|Win32.Build.0 = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Double|x64.ActiveCfg = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Double|x64.Build.0 = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Matlab|Win32.ActiveCfg = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Matlab|Win32.Build.0 = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Matlab|x64.ActiveCfg = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release_Matlab|x64.Build.0 = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|Win32.ActiveCfg = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|Win32.Build.0 = Release|Win32 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.ActiveCfg = Release|x64 + {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.Build.0 = Release|Win32 + {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|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.Build.0 = Release|Win32 + {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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Double|Win32.ActiveCfg = Debug_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Double|x64.ActiveCfg = Debug_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Matlab|Win32.ActiveCfg = Debug_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Matlab|Win32.Build.0 = Debug_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Matlab|x64.ActiveCfg = Debug_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Matlab|x64.Build.0 = Debug_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug|Win32.ActiveCfg = Debug_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug|x64.ActiveCfg = Debug_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Double|Win32.ActiveCfg = Release_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Double|x64.ActiveCfg = Release_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Matlab|Win32.ActiveCfg = Release_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Matlab|Win32.Build.0 = Release_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Matlab|x64.ActiveCfg = Release_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release_Matlab|x64.Build.0 = Release_Matlab|x64 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release|Win32.ActiveCfg = Release_Matlab|Win32 + {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Release|x64.ActiveCfg = Release_Matlab|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {60B1042F-6137-4E78-9A9D-75E796E6E22B} + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/FAST/FAST.vfproj b/OpenFAST/vs-build/FAST/FAST.vfproj new file mode 100644 index 000000000..b9c9ca2a9 --- /dev/null +++ b/OpenFAST/vs-build/FAST/FAST.vfproj @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{18AE8067-CCC6-4479-A0DB-C4089EF9FE71}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Debug"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)" WholeProgramOptimization="true"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Debug"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)" WholeProgramOptimization="true"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Double" WholeProgramOptimization="true"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Double" WholeProgramOptimization="true"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Debug_Double"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" WarnInterfaces="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin\" TargetName="openfast_$(PlatformName)_Debug_Double"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" WarnInterfaces="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd;h;inc"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <File RelativePath="..\..\glue-codes\openfast\src\FAST_Prog.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/FASTlib/FASTlib.vfproj b/OpenFAST/vs-build/FASTlib/FASTlib.vfproj new file mode 100644 index 000000000..18a52174a --- /dev/null +++ b/OpenFAST/vs-build/FASTlib/FASTlib.vfproj @@ -0,0 +1,2235 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectType="typeStaticLibrary" ProjectCreator="Intel Fortran" Keyword="Static Library" Version="11.0" ProjectIdGuid="{1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool" AdditionalDependencies="terdf"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release_Matlab|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Matlab" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release_Matlab|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Matlab" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Debug_Matlab|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug_Matlab" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="CONSOLE_FILE;COMPILE_SIMULINK;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Debug_Matlab|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug_Matlab" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="CONSOLE_FILE;COMPILE_SIMULINK;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Double" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Double" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug_Double" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)_Debug_Double" ConfigurationType="typeStaticLibrary"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLibrarianTool" AdditionalDependencies="$(OutDir)\MAP_$(PlatformName).lib"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="call ..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"> + <File RelativePath="..\gitVersionInfo.h"/></Filter> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + <File RelativePath="..\CreateGitVersion.bat"/> + <File RelativePath="..\RunRegistry.bat"/></Filter> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="Aero"> + <Filter Name="AeroDyn"> + <Filter Name="AeroAcoustics"> + <File RelativePath="..\..\modules\aerodyn\src\AeroAcoustics.f90" /> + <File RelativePath="..\..\modules\aerodyn\src\AeroAcoustics_IO.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\AeroAcoustics_TNO.f90"/></Filter> + <Filter Name="FVW"> + <File RelativePath="..\..\modules\aerodyn\src\FVW.f90" /> + <File RelativePath="..\..\modules\aerodyn\src\FVW_BiotSavart.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_IO.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Subs.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Tests.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_VortexTools.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_VTK.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Wings.f90"/></Filter> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\aerodyn\src\AeroAcoustics_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AA" Description="Running Registry for AeroAcoustics" Outputs="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AeroAcoustics_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" BuildDependencies="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" BuildDependencies="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn" Description="Running Registry for AeroDyn" Outputs="..\..\modules\aerodyn\src\AeroDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\BEMT_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BEMT" Description="Running Registry for BEMT" Outputs="..\..\modules\aerodyn\src\BEMT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\BEMT_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\DBEMT_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DBEMT" Description="Running Registry for DBEMT" Outputs="..\..\modules\aerodyn\src\DBEMT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\DBEMT_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FVW" Description="Running Registry for FVW" Outputs="..\..\modules\aerodyn\src\FVW_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\FVW_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn_AllBldNdOuts_IO.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\AeroDyn_IO.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\BEMT.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\BEMTUncoupled.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\DBEMT.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\mod_root1dim.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero.f90"/></Filter> + <Filter Name="AeroDyn14"> + <Filter Name="DWM"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\aerodyn14\src\DWM_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn14\src\Registry-DWM.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat DWM" Description="Running Registry for DWM" Outputs="..\..\modules\aerodyn14\src\DWM_Types.f90"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\aerodyn14\src\DWM.f90"/> + <File RelativePath="..\..\modules\aerodyn14\src\DWM_Wake_Sub_ver2.f90"/></Filter> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn14\src\Registry-AD14.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AeroDyn14" Description="Running Registry for AeroDyn14" Outputs="..\..\modules\aerodyn14\src\AeroDyn14_Types.f90"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\aerodyn14\src\AeroDyn14.f90"/> + <File RelativePath="..\..\modules\aerodyn14\src\AeroSubs.f90"/> + <File RelativePath="..\..\modules\aerodyn14\src\GenSubs.f90"/></Filter></Filter> + <Filter Name="BeamDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\beamdyn\src\Registry_BeamDyn.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat BeamDyn" Description="Running Registry for BeamDyn" Outputs="..\..\modules\beamdyn\src\BeamDyn_Types.f90"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_BldNdOuts_IO.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_IO.f90"/> + <File RelativePath="..\..\modules\beamdyn\src\BeamDyn_Subs.f90"/></Filter> + <Filter Name="ElastoDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\elastodyn\src\ElastoDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ElastoDyn" Description="Running Registry for ElastoDyn" Outputs="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\elastodyn\src\ElastoDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\elastodyn\src\ED_UserSubs.f90"/> + <File RelativePath="..\..\modules\elastodyn\src\ElastoDyn.f90"/> + <File RelativePath="..\..\modules\elastodyn\src\ElastoDyn_AllBldNdOuts_IO.f90"/> + <File RelativePath="..\..\modules\elastodyn\src\ElastoDyn_IO.f90"/></Filter> + <Filter Name="External Platform"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\extptfm\src\ExtPtfm_MCKF_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ExtPtfm_MCKF" Description="Running Registry for ExtPtfm_MCKF" Outputs="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\extptfm\src\ExtPtfm_MCKF_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\extptfm\src\ExtPtfm_MCKF.f90"/> + <File RelativePath="..\..\modules\extptfm\src\ExtPtfm_MCKF_IO.f90"/></Filter> + <Filter Name="FAST"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FAST" Description="Running Registry for FAST" Outputs="..\..\modules\openfast-library\src\FAST_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Lin.f90"/> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Mods.f90"/> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Solver.f90"/> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Subs.f90"/></Filter> + <Filter Name="HydroDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\hydrodyn\src\Conv_Radiation.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Conv_Radiation_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Current.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\hydrodyn\src\Current_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Current_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\HydroDyn.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\HydroDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Morison.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\hydrodyn\src\Morison_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Morison_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Excitation.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Excitation_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Radiation.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Radiation_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\hydrodyn\src\WAMIT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT2.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT2_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Waves.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\hydrodyn\src\Waves_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Waves2.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\hydrodyn\src\Waves2_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Waves2_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\Waves_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\hydrodyn\src\Conv_Radiation.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Current.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\HydroDyn.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\HydroDyn_Input.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\HydroDyn_Output.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Morison.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Morison_Output.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Excitation.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Radiation.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\UserWaves.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT2.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT2_Output.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT_Interp.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\WAMIT_Output.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Waves.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Waves2.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\Waves2_Output.f90"/></Filter> + <Filter Name="Ice"> + <Filter Name="IceDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\icedyn\src\IceDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\icedyn\src\Registry_IceDyn.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceDyn" Description="Running Registry for IceDyn" Outputs="..\..\modules\icedyn\src\IceDyn_Types.f90"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\icedyn\src\IceDyn.f90"/></Filter> + <Filter Name="IceFloe"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\icefloe\src\interfaces\FAST\IceFloe_FASTRegistry.inp"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IceFloe" Description="Running Registry for IceFloe" Outputs="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\icefloe\src\icefloe\IceFloe_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\icefloe\src\icefloe\coupledCrushing.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\crushingIEC.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\crushingISO.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\IceFlexBase.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\IceFlexIEC.f90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\IceFlexISO.f90"/> + <File RelativePath="..\..\modules\icefloe\src\interfaces\FAST\IceFloe.f90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\IceFloeBase.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\iceInput.f90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\iceLog.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\intermittentCrushing.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\lockInISO.F90"/> + <File RelativePath="..\..\modules\icefloe\src\icefloe\randomCrushing.F90"/></Filter></Filter> + <Filter Name="InflowWind"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\inflowwind\src\IfW_4Dext.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_4Dext_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_BladedFFWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_BladedFFWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_FFWind_Base.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_FFWind_Base_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_HAWCWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWind" Outputs="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_HAWCWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_TSFFWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_TSFFWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UniformWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UniformWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UserWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UserWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\InflowWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\inflowwind\src\InflowWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\InflowWind_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\Lidar.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\inflowwind\src\Lidar_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\inflowwind\src\Lidar_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\inflowwind\src\IfW_4Dext.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_BladedFFWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_FFWind_Base.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_HAWCWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_TSFFWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UniformWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\IfW_UserWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\InflowWind.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\InflowWind_Subs.f90"/> + <File RelativePath="..\..\modules\inflowwind\src\Lidar.f90"/></Filter> + <Filter Name="Mooring Lines"> + <Filter Name="FEAMooring"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\feamooring\src\FEAM_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat FEAMooring" Description="Running Registry for FEAMooring" Outputs="..\..\modules\feamooring\src\FEAMooring_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\feamooring\src\FEAMooring_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\feamooring\src\FEAM.f90"/></Filter> + <Filter Name="MAP"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\map\src\MAP_Fortran_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Fortran_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\map\src\MAP_Fortran_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\map\src\MAP_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="" Description="" Outputs=""/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Map" Description="Running Registry for Map" Outputs="..\..\modules\map\src\Map_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\map\src\Map_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\map\src\map.f90"/></Filter> + <Filter Name="MoorDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\moordyn\src\MoorDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat MoorDyn" Description="Running Registry for MoorDyn" Outputs="..\..\modules\moordyn\src\MoorDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\moordyn\src\MoorDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\moordyn\src\MoorDyn.f90"/> + <File RelativePath="..\..\modules\moordyn\src\MoorDyn_IO.f90"/></Filter> + <Filter Name="OrcaFlex"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\orcaflex-interface\src\OrcaFlexInterface.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OrcaFlexInterface" Description="Running Registry for OrcaFlex Interface" Outputs="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\orcaflex-interface\src\OrcaFlexInterface_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\orcaflex-interface\src\OrcaFlexInterface.F90"/></Filter></Filter> + <Filter Name="NWTC_Library"> + <Filter Name="NetLib"> + <Filter Name="FFTPACK"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\fftpack4.1.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <Filter Name="ScaLAPACK"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\dlasrt2.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\slasrt2.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <Filter Name="SLATEC"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\d1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\dqk61.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\fdump.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\i1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\j4save.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\qk61.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\r1mach.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xercnt.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xerhlt.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xermsg.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xerprn.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xersve.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\xgetua.f"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" DisableSpecificDiagnostics="6717"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\NWTC_FFTPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\slatec\NWTC_SLATEC.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\NWTC_ScaLAPACK.f90"/></Filter> + <Filter Name="RanLux"> + <File RelativePath="..\..\modules\nwtc-library\src\ranlux\RANLUX.f90"/></Filter> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\nwtc-library\src\Registry_NWTC_Library.txt"/></Filter> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_RandomNumber.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"> + <FileConfiguration Name="Debug_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug_Matlab|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|Win32" ExcludedFromBuild="true"/></File> + <File RelativePath="..\..\modules\nwtc-library\src\SysMatlabWindows.f90"> + <FileConfiguration Name="Debug_Double|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Double|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug_Double|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Double|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release|Win32" ExcludedFromBuild="true"/></File></Filter> + <Filter Name="OpenFOAM Integration"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\openfoam\src\OpenFOAM_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat OpenFOAM" Description="Running Registry for OpenFOAM" Outputs="..\..\modules\openfoam\src\OpenFOAM_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\openfoam\src\OpenFOAM_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\openfoam\src\OpenFOAM.f90"/></Filter> + <Filter Name="ServoDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\servodyn\src\ServoDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat ServoDyn" Description="Running Registry for ServoDyn" Outputs="..\..\modules\servodyn\src\ServoDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\servodyn\src\ServoDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\servodyn\src\TMD_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat TMD" Description="Running Registry for TMD" Outputs="..\..\modules\servodyn\src\TMD_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\servodyn\src\TMD_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\servodyn\src\BladedInterface.F90"/> + <File RelativePath="..\..\modules\servodyn\src\PitchCntrl_ACH.f90"/> + <File RelativePath="..\..\modules\servodyn\src\ServoDyn.f90"/> + <File RelativePath="..\..\modules\servodyn\src\TMD.f90"/> + <File RelativePath="..\..\modules\servodyn\src\UserSubs.f90"/> + <File RelativePath="..\..\modules\servodyn\src\UserVSCont_KP.f90"/></Filter> + <Filter Name="SubDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\subdyn\src\qsort_c_module.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SD_FEM.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SubDyn.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Output.f90"/></Filter> + <Filter Name="Super Controller"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\supercontroller\src\SuperController_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Matlab|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SuperController" Description="Running Registry for SuperController" Outputs="..\..\modules\supercontroller\src\SuperController_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\supercontroller\src\SuperController_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\supercontroller\src\SuperController.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/HydroDyn/HydroDynDriver.sln b/OpenFAST/vs-build/HydroDyn/HydroDynDriver.sln new file mode 100644 index 000000000..e149d6049 --- /dev/null +++ b/OpenFAST/vs-build/HydroDyn/HydroDynDriver.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "HydroDynDriver", "HydroDynDriver.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.Build.0 = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.ActiveCfg = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.Build.0 = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.ActiveCfg = Release|Win32 + {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 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/HydroDyn/HydroDynDriver.vfproj b/OpenFAST/vs-build/HydroDyn/HydroDynDriver.vfproj new file mode 100644 index 000000000..89e4500f4 --- /dev/null +++ b/OpenFAST/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{815C302F-A93D-4C22-9329-717B085113C0}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnalignedData="false" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="999999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="HydroDynDriver_dev_$(ConfigurationName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="999999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="100000000"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="999999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="HydroDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\HydroDyn\src\Conv_Radiation.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\HydroDyn\src\Conv_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Conv_Radiation" Description="Running Registry for Conv_Radiation" Outputs="..\..\modules\HydroDyn\src\Conv_Radiation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Conv_Radiation_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Current.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\HydroDyn\src\Current_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Current" Description="Running Registry for Current" Outputs="..\..\modules\HydroDyn\src\Current_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Current_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\HydroDyn\src\HydroDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat HydroDyn" Description="Running Registry for HydroDyn" Outputs="..\..\modules\HydroDyn\src\HydroDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Morison.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\HydroDyn\src\Morison_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Morison" Description="Running Registry for Morison" Outputs="..\..\modules\HydroDyn\src\Morison_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Morison_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Excitation.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\HydroDyn\src\SS_Excitation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Excitation" Description="Running Registry for SS_Excitation" Outputs="..\..\modules\HydroDyn\src\SS_Excitation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\SS_Excitation_Types.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\SS_Radiation.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\HydroDyn\src\SS_Radiation_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SS_Radiation" Description="Running Registry for SS_Radiation" Outputs="..\..\modules\HydroDyn\src\SS_Radiation_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\SS_Radiation_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\HydroDyn\src\WAMIT_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT" Description="Running Registry for WAMIT" Outputs="..\..\modules\HydroDyn\src\WAMIT_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT2.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\HydroDyn\src\WAMIT2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat WAMIT2" Description="Running Registry for WAMIT2" Outputs="..\..\modules\HydroDyn\src\WAMIT2_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT2_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Waves.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\HydroDyn\src\Waves_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves" Description="Running Registry for Waves" Outputs="..\..\modules\HydroDyn\src\Waves_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Waves2.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\HydroDyn\src\Waves2_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Waves2" Description="Running Registry for Waves2" Outputs="..\..\modules\HydroDyn\src\Waves2_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Waves2_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\HydroDyn\src\Waves_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\HydroDyn\src\Conv_Radiation.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Current.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn_DriverCode.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn_Input.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\HydroDyn_Output.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Morison.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Morison_Output.f90"/> + <File RelativePath="..\..\modules\hydrodyn\src\SS_Excitation.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\SS_Radiation.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\UserWaves.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT2.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT2_Output.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT_Interp.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\WAMIT_Output.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Waves.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Waves2.f90"/> + <File RelativePath="..\..\modules\HydroDyn\src\Waves2_Output.f90"/></Filter> + <Filter Name="RanLux"> + <File RelativePath="..\..\modules\nwtc-library\src\ranlux\RANLUX.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnDeclarations="false" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnDeclarations="false" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\fftpack4.1.f"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnDeclarations="false" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnDeclarations="false" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\NWTC_FFTPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/></Filter> + <Filter Name="NWTC_Library"> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_RandomNumber.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/InflowWind/InflowWind_driver.sln b/OpenFAST/vs-build/InflowWind/InflowWind_driver.sln new file mode 100644 index 000000000..bb6d88cdf --- /dev/null +++ b/OpenFAST/vs-build/InflowWind/InflowWind_driver.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "InflowWind_driver", "InflowWind_driver.vfproj", "{3BBE2741-5B28-47BC-9E7F-3E1D172838FB}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug|Win32.Build.0 = Debug|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug|x64.ActiveCfg = Debug|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Debug|x64.Build.0 = Debug|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release_Double|x64.Build.0 = Release_Double|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|Win32.ActiveCfg = Release|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|Win32.Build.0 = Release|Win32 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|x64.ActiveCfg = Release|x64 + {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 + {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|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 + {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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/InflowWind/InflowWind_driver.vfproj b/OpenFAST/vs-build/InflowWind/InflowWind_driver.vfproj new file mode 100644 index 000000000..c7179bd93 --- /dev/null +++ b/OpenFAST/vs-build/InflowWind/InflowWind_driver.vfproj @@ -0,0 +1,357 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{3BBE2741-5B28-47BC-9E7F-3E1D172838FB}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" AdditionalOptions="/fpe-all:0" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" OpenMP="OpenMPParallelCode" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="InflowWind"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\InflowWind\src\IfW_4Dext.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_4Dext" Description="Running Registry for IfW_4Dext" Outputs="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_BladedFFWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_BladedFFWind" Description="Running Registry for IfW_BladedFFWind" Outputs="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_BladedFFWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_FFWind_Base.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_FFWind_Base" Description="Running Registry for IfW_FFWind_Base" Outputs="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_FFWind_Base_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_HAWCWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_HAWCWind" Description="Running Registry for IfW_HAWCWindWind" Outputs="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_HAWCWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_TSFFWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_TSFFWind" Description="Running Registry for IfW_TSFFWind" Outputs="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_TSFFWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UniformWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UniformWind" Description="Running Registry for IfW_UniformWind" Outputs="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UniformWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UserWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat IfW_UserWind" Description="Running Registry for IfW_UserWind" Outputs="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UserWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat InflowWind" Description="Running Registry for InflowWind" Outputs="..\..\modules\InflowWind\src\InflowWind_Types.f90" AdditionalDependencies="..\..\modules\InflowWind\src\Reg-IfW_FFWind.txt;..\..\modules\InflowWind\src\Reg-IfW_HHWind.txt"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\Lidar.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat Lidar" Description="Running Registry for Lidar" Outputs="..\..\modules\InflowWind\src\Lidar_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\Lidar_Types.f90"/></Filter> + <File RelativePath="..\..\modules\InflowWind\src\IfW_4Dext.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_4Dext_Types.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\IfW_BladedFFWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_FFWind_Base.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_HAWCWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_TSFFWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UniformWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\IfW_UserWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind_Subs.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\InflowWind\src\Lidar.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true"/></FileConfiguration></File></Filter> + <Filter Name="InflowWind Driver"> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind_Driver.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind_Driver_Subs.f90"/> + <File RelativePath="..\..\modules\InflowWind\src\InflowWind_Driver_Types.f90"/></Filter> + <Filter Name="NWTC_Library"> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/></Filter> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\nwtc-library\src\Registry_NWTC_Library.txt"/></Filter> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/MAPlib/MAP_dll.vcxproj b/OpenFAST/vs-build/MAPlib/MAP_dll.vcxproj new file mode 100644 index 000000000..0339dfa08 --- /dev/null +++ b/OpenFAST/vs-build/MAPlib/MAP_dll.vcxproj @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{BF86702A-CB17-4050-8AE9-078CDC5910D3}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>MAP_DLL</RootNamespace> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + <TargetName>MAP_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>MAP_$(PlatformName)</TargetName> + <LinkIncremental>true</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + <TargetName>MAP_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>MAP_$(PlatformName)</TargetName> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MAP_DLL_EXPORTS;CMINPACK_NO_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <AdditionalIncludeDirectories>..\..\modules\map\src</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MAP_DLL_EXPORTS;CMINPACK_NO_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MAP_DLL_EXPORTS;CMINPACK_NO_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MAP_DLL_EXPORTS;CMINPACK_NO_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\modules\map\src\bstring\bstraux.c" /> + <ClCompile Include="..\..\modules\map\src\bstring\bstrlib.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\dpmpar.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\enorm.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\enorm_u.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\lmder.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\lmpar.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\qrfac.c" /> + <ClCompile Include="..\..\modules\map\src\cminpack\qrsolv.c" /> + <ClCompile Include="..\..\modules\map\src\freedata.c" /> + <ClCompile Include="..\..\modules\map\src\jacobian.c" /> + <ClCompile Include="..\..\modules\map\src\lineroutines.c" /> + <ClCompile Include="..\..\modules\map\src\lmroutines.cc" /> + <ClCompile Include="..\..\modules\map\src\mapapi.c" /> + <ClCompile Include="..\..\modules\map\src\maperror.c" /> + <ClCompile Include="..\..\modules\map\src\mapinit.c" /> + <ClCompile Include="..\..\modules\map\src\numeric.c" /> + <ClCompile Include="..\..\modules\map\src\outputstream.c" /> + <ClCompile Include="..\..\modules\map\src\residual.c" /> + <ClCompile Include="..\..\modules\map\src\simclist\simclist.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\modules\map\src\bstring\bstraux.h" /> + <ClInclude Include="..\..\modules\map\src\bstring\bstrlib.h" /> + <ClInclude Include="..\..\modules\map\src\cminpack\cminpack.h" /> + <ClInclude Include="..\..\modules\map\src\cminpack\cminpackP.h" /> + <ClInclude Include="..\..\modules\map\src\cminpack\minpack.h" /> + <ClInclude Include="..\..\modules\map\src\freedata.h" /> + <ClInclude Include="..\..\modules\map\src\jacobian.h" /> + <ClInclude Include="..\..\modules\map\src\lapack\lapacke.h" /> + <ClInclude Include="..\..\modules\map\src\lapack\lapacke_mangling.h" /> + <ClInclude Include="..\..\modules\map\src\lineroutines.h" /> + <ClInclude Include="..\..\modules\map\src\lmroutines.hpp" /> + <ClInclude Include="..\..\modules\map\src\map.h" /> + <ClInclude Include="..\..\modules\map\src\mapapi.h" /> + <ClInclude Include="..\..\modules\map\src\maperror.h" /> + <ClInclude Include="..\..\modules\map\src\mapinit.h" /> + <ClInclude Include="..\..\modules\map\src\mapsys.h" /> + <ClInclude Include="..\..\modules\map\src\MAP_Types.h" /> + <ClInclude Include="..\..\modules\map\src\numeric.h" /> + <ClInclude Include="..\..\modules\map\src\outputstream.h" /> + <ClInclude Include="..\..\modules\map\src\residual.h" /> + <ClInclude Include="..\..\modules\map\src\simclist\simclist.h" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="..\..\modules\map\src\MAP_Registry.txt"> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CALL ..\RunRegistry.bat MAP</Command> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\modules\map\src\MAP_Types.h</Outputs> + <TreatOutputAsContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</TreatOutputAsContent> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CALL ..\RunRegistry.bat MAP</Command> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\modules\map\src\MAP_Types.h</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CALL ..\RunRegistry.bat MAP</Command> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\modules\map\src\MAP_Types.h</Outputs> + <TreatOutputAsContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</TreatOutputAsContent> + <TreatOutputAsContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</TreatOutputAsContent> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CALL ..\RunRegistry.bat MAP</Command> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\modules\map\src\MAP_Types.h</Outputs> + <TreatOutputAsContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</TreatOutputAsContent> + </CustomBuild> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/OpenFAST/vs-build/OpenFAST-Simulink/OpenFAST-Simulink.vfproj b/OpenFAST/vs-build/OpenFAST-Simulink/OpenFAST-Simulink.vfproj new file mode 100644 index 000000000..de68e189f --- /dev/null +++ b/OpenFAST/vs-build/OpenFAST-Simulink/OpenFAST-Simulink.vfproj @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectType="typeDynamicLibrary" ProjectCreator="Intel Fortran" Keyword="Dll" Version="11.0" ProjectIdGuid="{C3C93CC0-EDD7-438F-988C-1F917FAEFA67}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug_Matlab|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(ConfigurationName)_$(PlatformName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK;CONSOLE_FILE" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Matlab|Win32" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemWindows" LinkDLL="true" AdditionalDependencies="&quot;C:\Program Files (x86)\MATLAB\R2018a\extern\lib\win32\microsoft\libmex.lib&quot;"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Matlab|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(ConfigurationName)_$(PlatformName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK;CONSOLE_FILE" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199" WarnInterfaces="true" Traceback="true" BoundsCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemWindows" LinkDLL="true"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Matlab|x64" OutputDirectory="..\..\build\bin\" TargetName="$(ProjectName)_$(PlatformName)" ConfigurationType="typeDynamicLibrary"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="COMPILE_SIMULINK" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268,5199"/> + <Tool Name="VFLinkerTool" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemWindows" LinkDLL="true" AdditionalDependencies="&quot;C:\Program Files\MATLAB\R2018a\extern\lib\win64\microsoft\libmex.lib&quot;"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd;h;inc"> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Library.h"> + <FileConfiguration Name="Debug_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug_Matlab|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|Win32" ExcludedFromBuild="true"/></File> + <File RelativePath="..\..\glue-codes\simulink\src\FAST_SFunc.c"> + <FileConfiguration Name="Debug_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|x64" ExcludedFromBuild="true"/> + <FileConfiguration Name="Debug_Matlab|Win32" ExcludedFromBuild="true"/> + <FileConfiguration Name="Release_Matlab|Win32" ExcludedFromBuild="true"/></File></Filter> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <File RelativePath="..\..\modules\openfast-library\src\FAST_Library.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/ReadMe.md b/OpenFAST/vs-build/ReadMe.md new file mode 100644 index 000000000..afb0097ab --- /dev/null +++ b/OpenFAST/vs-build/ReadMe.md @@ -0,0 +1,20 @@ +# Visual Studio builds for Windows +The following solution files are available for code development on Windows using the Intel Fortran compiler with Visual Studio. + +- [OpenFAST](FAST/FAST.sln) + This contains builds for both the command-line OpenFAST executable as well as the DLL for use with the OpenFAST-Simulink interface. +- Module-level drivers: + - AeroDynamics: + - [AeroDyn driver](AeroDyn/AeroDyn_Driver.sln) + - [UnsteadyAero driver](UnsteadyAero/UnsteadyAero.sln) + - Structural: + - [BeamDyn driver](BeamDyn/BeamDyn-w-registry.sln) + - [SubDyn driver](SubDyn/SubDyn.sln) + - Wind/Wave conditions + - [TurbSim](TurbSim/TurbSim.sln) Generates wind files + - [InflowWind driver](InflowWind/InflowWind_driver.sln) Reads and interpolates existing wind files + - [HydroDyn driver](HydroDyn/HydroDynDriver.sln) +- Other: + - [Discon](Discon/Discon.sln) This solution file contains all 3 controllers used in the OpenFAST r-test (with the NREL 5MW model). + - [OpenFAST Registry](Registry/Registry.sln) + The Registry project is included in almost every other solution file, so this solution file is only for debugging changes to the OpenFAST Registry. diff --git a/OpenFAST/vs-build/Registry/FAST_Registry.sln b/OpenFAST/vs-build/Registry/FAST_Registry.sln new file mode 100644 index 000000000..689421c6c --- /dev/null +++ b/OpenFAST/vs-build/Registry/FAST_Registry.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2043 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Debug|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Debug|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E46DCC9C-7BC9-40BA-8EF9-BDE0CD4C584B} + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/Registry/FAST_Registry.vcxproj b/OpenFAST/vs-build/Registry/FAST_Registry.vcxproj new file mode 100644 index 000000000..40649f85f --- /dev/null +++ b/OpenFAST/vs-build/Registry/FAST_Registry.vcxproj @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>FAST_Registry_c</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <TargetName>Registry</TargetName> + <OutDir>..\..\build\bin\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <TargetName>Registry</TargetName> + <OutDir>..\..\build\bin\</OutDir> + <IntDir>$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + <TargetName>Registry</TargetName> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>Registry</TargetName> + <GenerateManifest>false</GenerateManifest> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\build\bin\</OutDir> + <IntDir>$(Configuration)\</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <DisableSpecificWarnings>4996</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <DisableSpecificWarnings>4996</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <DisableSpecificWarnings>4996</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <DisableSpecificWarnings>4996</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\modules\openfast-registry\src\data.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\gen_c_types.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\gen_module_files.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\misc.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\my_strtok.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\registry.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\reg_parse.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\sym.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\symtab_gen.c" /> + <ClCompile Include="..\..\modules\openfast-registry\src\type.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\modules\openfast-registry\src\data.h" /> + <ClInclude Include="..\..\modules\openfast-registry\src\FAST_preamble.h" /> + <ClInclude Include="..\..\modules\openfast-registry\src\protos.h" /> + <ClInclude Include="..\..\modules\openfast-registry\src\registry.h" /> + <ClInclude Include="..\..\modules\openfast-registry\src\sym.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/OpenFAST/vs-build/RunRegistry.bat b/OpenFAST/vs-build/RunRegistry.bat new file mode 100644 index 000000000..734ebf9cc --- /dev/null +++ b/OpenFAST/vs-build/RunRegistry.bat @@ -0,0 +1,328 @@ +@ECHO OFF + +set lines======================================================================= +echo %lines% +IF "%1"=="" ( +ECHO. +ECHO The calling syntax for this script is +ECHO RunRegistry ModuleName [FAST_Root_Loc] +ECHO. +GOTO Done +) + + +REM ---------------------------------------------------------------------------- +REM ------------------------- LOCAL PATHS -------------------------------------- +REM ---------------------------------------------------------------------------- +REM -- USERS MAY EDIT THESE PATHS TO POINT TO FOLDERS ON THEIR LOCAL MACHINES. - +REM -- NOTE: do not use quotation marks around the path names!!!! -------------- +REM ---------------------------------------------------------------------------- +REM ---------------------------------------------------------------------------- +SET Root_Loc=..\.. +IF not "%2"=="" SET Root_Loc=%2 + +SET Modules_Loc=%Root_Loc%\modules +SET Registry=..\..\build\bin\Registry.exe +SET FAST_Loc=%Modules_Loc%\openfast-library\src +SET ED_Loc=%Modules_Loc%\elastodyn\src +SET AD14_Loc=%Modules_Loc%\aerodyn14\src +SET IfW_Loc=%Modules_Loc%\inflowwind\src +SET HD_Loc=%Modules_Loc%\hydrodyn\src +SET SD_Loc=%Modules_Loc%\subdyn\src +SET MAP_Loc=%Modules_Loc%\map\src +SET FEAM_Loc=%Modules_Loc%\feamooring\src +SET IceF_Loc=%Modules_Loc%\icefloe\src\interfaces\FAST +SET IceD_Loc=%Modules_Loc%\icedyn\src +SET MD_Loc=%Modules_Loc%\moordyn\src +SET OpFM_Loc=%Modules_Loc%\openfoam\src +SET Orca_Loc=%Modules_Loc%\orcaflex-interface\src +SET NWTC_Lib_Loc=%Modules_Loc%\nwtc-library\src +SET ExtPtfm_Loc=%Modules_Loc%\extptfm\src +SET AD_Loc=%Modules_Loc%\aerodyn\src +SET SrvD_Loc=%Modules_Loc%\servodyn\src +SET BD_Loc=%Modules_Loc%\beamdyn\src +SET SC_Loc=%Modules_Loc%\supercontroller\src + +SET ALL_FAST_Includes=-I "%FAST_Loc%" -I "%NWTC_Lib_Loc%" -I "%ED_Loc%" -I "%SrvD_Loc%" -I "%AD14_Loc%" -I^ + "%AD_Loc%" -I "%BD_Loc%" -I "%SC_Loc%" -I^ + "%IfW_Loc%" -I "%SD_Loc%" -I "%HD_Loc%" -I "%MAP_Loc%" -I "%FEAM_Loc%" -I^ + "%IceF_Loc%" -I "%IceD_Loc%" -I "%MD_Loc%" -I "%OpFM_Loc%" -I "%Orca_Loc%" -I "%ExtPtfm_Loc%" + + +SET ModuleName=%1 + +GOTO %ModuleName% + +REM ---------------------------------------------------------------------------- +REM ---------------- RUN THE REGISTRY TO AUTO-GENERATE FILES ------------------- +REM ---------------------------------------------------------------------------- +:MAP +SET CURR_LOC=%MAP_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -ccode -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +%REGISTRY% "%CURR_LOC%\MAP_Fortran_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" -noextrap +GOTO checkError + +:FAST +SET CURR_LOC=%FAST_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\FAST_Registry.txt" %ALL_FAST_Includes% -noextrap -O "%Output_Loc%" +GOTO checkError + +:BeamDyn +SET CURR_LOC=%BD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\Registry_BeamDyn.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:SuperController +SET CURR_LOC=%SC_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\SuperController_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" -ccode +GOTO checkError + +:ElastoDyn +SET CURR_LOC=%ED_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:TMD +:ServoDyn +SET CURR_LOC=%SrvD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Lidar +:InflowWind +SET CURR_LOC=%IfW_Loc% +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 +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%" +GOTO checkError + +:OpenFOAM +SET CURR_LOC=%OpFM_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -ccode -O "%Output_Loc%" +GOTO checkError + +:AeroDyn +:BEMT +:DBEMT +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:AeroDyn_Driver +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\AeroDyn_Driver_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" -noextrap +GOTO checkError + +:AFI +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\AirfoilInfo_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -noextrap -O "%Output_Loc%" +GOTO checkError + +:UA +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\UnsteadyAero_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:FVW +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\FVW_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:AA +SET CURR_LOC=%AD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\AeroAcoustics_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:AeroDyn14 +SET CURR_LOC=%AD14_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\Registry-AD14.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -I "%IfW_Loc%" -O "%Output_Loc%" +GOTO checkError + +:DWM +SET CURR_LOC=%AD14_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\Registry-DWM.txt" -I "%NWTC_Lib_Loc%" -I "%IfW_Loc%" -O "%Output_Loc%" +GOTO checkError + +:HydroDyn +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Current +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Waves +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Waves2 +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:SS_Excitation +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:SS_Radiation +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Conv_Radiation +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:WAMIT +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:WAMIT2 +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:Morison +SET CURR_LOC=%HD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + +:SubDyn +SET CURR_LOC=%SD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:FEAMooring +SET CURR_LOC=%FEAM_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\FEAM_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:MoorDyn +SET CURR_LOC=%MD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:IceFloe +SET CURR_LOC=%IceF_Loc% +SET Output_Loc=%Modules_Loc%\icefloe\src\icefloe +%REGISTRY% "%CURR_LOC%\%ModuleName%_FASTRegistry.inp" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:IceDyn +SET CURR_LOC=%IceD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\Registry_%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:OrcaFlexInterface +SET CURR_LOC=%Orca_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:ExtPtfm_MCKF +SET CURR_LOC=%ExtPtfm_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\%ModuleName%_Registry.txt" -I "%NWTC_Lib_Loc%" -O "%Output_Loc%" +GOTO checkError + +:Version +DEL "%Root_Loc%\VersionInfo.obj" "%Root_Loc%\versioninfo.mod" +GOTO end + +:checkError +ECHO. +IF %ERRORLEVEL% NEQ 0 ( +ECHO Error running FAST Registry for %ModuleName%. +) ELSE ( +ECHO Registry for %ModuleName% completed. +REM COPY /Y "%ModuleName%_Types.f90" "%CURR_LOC%" +rem IF /I "%ModuleName%"=="MAP" COPY /Y "%ModuleName%_Types.h" "%CURR_LOC%" +) + +:end +REM ---------------------------------------------------------------------------- +REM ------------------------- CLEAR MEMORY ------------------------------------- +REM ---------------------------------------------------------------------------- +ECHO.  + +SET ModuleName= +SET CURR_LOC= + +SET Root_Loc= + +SET Subs_Loc= +SET FAST_Loc= +SET Registry= + +SET ED_Loc= +SET BD_Loc= +SET AD14_Loc= +SET IfW_Loc= +SET HD_Loc= +SET SD_Loc= +SET MAP_Loc= +SET FEAM_Loc= +SET IceF_Loc= +SET IceD_Loc= +SET MD_Loc= +SET OpFM_Loc= +SET Orca_Loc= +SET NWTC_Lib_Loc= +SET ExtPtfm_Loc= +SET AD_Loc= +SET SrvD_Loc= + +SET MAP_Loc= +SET ALL_FAST_Includes= + +:Done +echo %lines% +set lines= + +:PathsOnly diff --git a/OpenFAST/vs-build/SubDyn/SubDyn.sln b/OpenFAST/vs-build/SubDyn/SubDyn.sln new file mode 100644 index 000000000..0aa100f6f --- /dev/null +++ b/OpenFAST/vs-build/SubDyn/SubDyn.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "SubDyn", "SubDyn.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.Build.0 = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.ActiveCfg = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.Build.0 = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.ActiveCfg = Release|Win32 + {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|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|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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/SubDyn/SubDyn.vfproj b/OpenFAST/vs-build/SubDyn/SubDyn.vfproj new file mode 100644 index 000000000..5f0256521 --- /dev/null +++ b/OpenFAST/vs-build/SubDyn/SubDyn.vfproj @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{815C302F-A93D-4C22-9329-717B085113C0}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUnalignedData="false" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" WarnDeclarations="true" WarnUnusedVariables="true" WarnUnalignedData="false" WarnUncalled="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\dlasrt2.f"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\NWTC_ScaLAPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\scalapack\slasrt2.f"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" StandardWarnings="standardWarningsNone"/></FileConfiguration></File></Filter> + <Filter Name="NWTC_Library"> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <Filter Name="SubDyn"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Registry.txt"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat SubDyn" Description="Running Registry for SubDyn" Outputs="..\..\modules\subdyn\src\SubDyn_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Types.f90"> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" DisableSpecificDiagnostics="5268" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\subdyn\src\qsort_c_module.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SD_FEM.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SubDyn.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Driver.f90"/> + <File RelativePath="..\..\modules\subdyn\src\SubDyn_Output.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/TurbSim/TurbSim.vfproj b/OpenFAST/vs-build/TurbSim/TurbSim.vfproj new file mode 100644 index 000000000..e11bffc34 --- /dev/null +++ b/OpenFAST/vs-build/TurbSim/TurbSim.vfproj @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{9B76F7F4-E04F-4CAE-A34C-27F6FE973710}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="NO_MESHMAPPING;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnInterfaces="true" Traceback="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="NO_MESHMAPPING;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="NO_MESHMAPPING;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnInterfaces="true" Traceback="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="NO_MESHMAPPING;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="dependencies"> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\fftpack4.1.f"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\fftpack\NWTC_FFTPACK.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/></Filter> + <Filter Name="NWTC_Library"> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"/> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"/></Filter> + <Filter Name="RanLux"> + <File RelativePath="..\..\modules\nwtc-library\src\ranlux\RANLUX.f90"/></Filter></Filter> + <Filter Name="TurbSim"> + <File RelativePath="..\..\modules\turbsim\src\BlankModVKM.f90"/> + <File RelativePath="..\..\modules\turbsim\src\CohStructures.f90"/> + <File RelativePath="..\..\modules\turbsim\src\Profiles.f90"/> + <File RelativePath="..\..\modules\turbsim\src\RandNum.f90"/> + <File RelativePath="..\..\modules\turbsim\src\Root_Searching.f90"/> + <File RelativePath="..\..\modules\turbsim\src\TS_FileIO.f90"/> + <File RelativePath="..\..\modules\turbsim\src\TSsubs.f90"/> + <File RelativePath="..\..\modules\turbsim\src\TurbSim.f90"/> + <File RelativePath="..\..\modules\turbsim\src\TurbSim_Types.f90"/> + <File RelativePath="..\..\modules\turbsim\src\VelocitySpectra.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject> diff --git a/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.sln b/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.sln new file mode 100644 index 000000000..4daa940c6 --- /dev/null +++ b/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.sln @@ -0,0 +1,64 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "UnsteadyAero", "UnsteadyAero.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" + ProjectSection(ProjectDependencies) = postProject + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "..\Registry\FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.Build.0 = Debug_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.Build.0 = Debug|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.ActiveCfg = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.Build.0 = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|x64.Build.0 = Release_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.ActiveCfg = Release|Win32 + {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 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 + {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|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 + {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 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {367EADB6-7C90-46F7-B3DD-31AFA0C0D727} + EndGlobalSection +EndGlobal diff --git a/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.vfproj b/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.vfproj new file mode 100644 index 000000000..93f686c97 --- /dev/null +++ b/OpenFAST/vs-build/UnsteadyAero/UnsteadyAero.vfproj @@ -0,0 +1,324 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{815C302F-A93D-4C22-9329-717B085113C0}"> + <Platforms> + <Platform Name="Win32"/> + <Platform Name="x64"/></Platforms> + <Configurations> + <Configuration Name="Debug|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" InitLocalVarToNAN="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" FloatingPointExceptionHandling="fpe0" FloatingPointStackCheck="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Debug_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_$(ConfigurationName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUnusedVariables="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" Traceback="true" NullPointerCheck="true" BoundsCheck="true" UninitializedVariablesCheck="true" StackFrameCheck="true" RuntimeLibrary="rtMultiThreadedDebug" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" GenerateDebugInformation="true" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|Win32" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" InitLocalVarToNAN="true" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole" StackReserveSize="9999999" LargeAddressAware="addrAwareLarge"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration> + <Configuration Name="Release_Double|x64" OutputDirectory="..\..\build\bin" TargetName="$(ProjectName)_Driver_$(PlatformName)_Double"> + <Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" Preprocess="preprocessYes" PreprocessorDefinitions="UA_OUTS;&quot;GIT_INCLUDE_FILE='$(ProjectDir)\..\gitVersionInfo.h'&quot;;DOUBLE_PRECISION" StandardWarnings="standardWarningsF03" DisableSpecificDiagnostics="5268" WarnDeclarations="true" WarnUncalled="true" RealKIND="realKIND8" DoublePrecisionKIND="doublePrecisionKIND16" UseMkl="mklSequential"/> + <Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateManifest="false" SubSystem="subSystemConsole"/> + <Tool Name="VFResourceCompilerTool"/> + <Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/> + <Tool Name="VFCustomBuildTool"/> + <Tool Name="VFPreLinkEventTool"/> + <Tool Name="VFPreBuildEventTool" CommandLine="..\CreateGitVersion.bat"/> + <Tool Name="VFPostBuildEventTool"/> + <Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations> + <Files> + <Filter Name="Header Files" Filter="fi;fd"/> + <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/> + <Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl"> + <Filter Name="AirfoilInfo"> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true" WarnUncalled="true"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="true" WarnUncalled="true"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat AFI" Description="Running Registry for AirfoilInfo" Outputs="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\AirfoilInfo_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <Filter Name="NetLib"> + <File RelativePath="..\..\modules\nwtc-library\src\NetLib\lapack\NWTC_LAPACK.f90"/></Filter> + <Filter Name="NWTC_Library"> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Mapping.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\ModMesh_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Base.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_IO.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Library_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\NWTC_Num.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SingPrec.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File> + <File RelativePath="..\..\modules\nwtc-library\src\SysIVF.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFFortranCompilerTool" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <Filter Name="UnsteadyAero"> + <Filter Name="RegistryFiles"> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero_Registry.txt"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Debug_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release|Win32"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration> + <FileConfiguration Name="Release_Double|x64"> + <Tool Name="VFCustomBuildTool" CommandLine="CALL ..\RunRegistry.bat UA" Description="Running Registry for UnsteadyAero" Outputs="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"/></FileConfiguration></File> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero_Types.f90"> + <FileConfiguration Name="Debug_Double|Win32"> + <Tool Name="VFFortranCompilerTool" DisableSpecificDiagnostics="5268" WarnUnusedVariables="false"/></FileConfiguration> + <FileConfiguration Name="Debug|Win32"> + <Tool Name="VFFortranCompilerTool" DisableSpecificDiagnostics="5268" WarnUnusedVariables="false"/></FileConfiguration></File></Filter> + <File RelativePath="..\..\modules\aerodyn\src\UA_Dvr_subs.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero.f90"/> + <File RelativePath="..\..\modules\aerodyn\src\UnsteadyAero_Driver.f90"/></Filter> + <File RelativePath="..\..\modules\version\src\VersionInfo.f90"/></Filter></Files> + <Globals/></VisualStudioProject>